diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index 7772928ee48f6edfa61d52921164ed106501515b..deb6b489e4e5da71d80f367961dc46cfafcd8f08 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -144,3 +144,16 @@ Description: Write a 1 to force the device to disconnect (equivalent to unplugging a wired USB device). + +What: /sys/bus/usb/drivers/.../remove_id +Date: November 2009 +Contact: CHENG Renquan +Description: + Writing a device ID to this file will remove an ID + that was dynamically added via the new_id sysfs entry. + The format for the device ID is: + idVendor idProduct. After successfully + removing an ID, the driver will no longer support the + device. This is useful to ensure auto probing won't + match the driver to the device. For example: + # echo "046d c315" > /sys/bus/usb/drivers/foo/remove_id diff --git a/Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc b/Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc index 4e8106f7cfd9a1677ed0e0023dfc1009930fe2b1..25b1e751b77714a5ecbf05f56b3d0f7784cee386 100644 --- a/Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc +++ b/Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc @@ -23,3 +23,16 @@ Description: Since this relates to security (specifically, the lifetime of PTKs and GTKs) it should not be changed from the default. + +What: /sys/class/uwb_rc/uwbN/wusbhc/wusb_phy_rate +Date: August 2009 +KernelVersion: 2.6.32 +Contact: David Vrabel +Description: + The maximum PHY rate to use for all connected devices. + This is only of limited use for testing and + development as the hardware's automatic rate + adaptation is better then this simple control. + + Refer to [ECMA-368] section 10.3.1.1 for the value to + use. diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu index a703b9e9aeb9d778b6591b066abb210811234705..2aae06fcbed7ae8d57489d89c5fea158beb37748 100644 --- a/Documentation/ABI/testing/sysfs-devices-system-cpu +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu @@ -62,6 +62,21 @@ Description: CPU topology files that describe kernel limits related to See Documentation/cputopology.txt for more information. +What: /sys/devices/system/cpu/probe + /sys/devices/system/cpu/release +Date: November 2009 +Contact: Linux kernel mailing list +Description: Dynamic addition and removal of CPU's. This is not hotplug + removal, this is meant complete removal/addition of the CPU + from the system. + + probe: writes to this file will dynamically add a CPU to the + system. Information written to the file to add CPU's is + architecture specific. + + release: writes to this file dynamically remove a CPU from + the system. Information writtento the file to remove CPU's + is architecture specific. What: /sys/devices/system/cpu/cpu#/node Date: October 2009 @@ -136,6 +151,24 @@ Description: Discover cpuidle policy and mechanism See files in Documentation/cpuidle/ for more information. +What: /sys/devices/system/cpu/cpu#/cpufreq/* +Date: pre-git history +Contact: cpufreq@vger.kernel.org +Description: Discover and change clock speed of CPUs + + Clock scaling allows you to change the clock speed of the + CPUs on the fly. This is a nice method to save battery + power, because the lower the clock speed, the less power + the CPU consumes. + + There are many knobs to tweak in this directory. + + See files in Documentation/cpu-freq/ for more information. + + In particular, read Documentation/cpu-freq/user-guide.txt + to learn how to control the knobs. + + What: /sys/devices/system/cpu/cpu*/cache/index*/cache_disable_X Date: August 2008 KernelVersion: 2.6.27 diff --git a/Documentation/ABI/testing/sysfs-kernel-slab b/Documentation/ABI/testing/sysfs-kernel-slab index 6dcf75e594fb54affe313518c951ab1671f30c22..8b093f8222d318e411113735f7e841c4b52e7ae0 100644 --- a/Documentation/ABI/testing/sysfs-kernel-slab +++ b/Documentation/ABI/testing/sysfs-kernel-slab @@ -45,8 +45,9 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The alloc_fastpath file is read-only and specifies how many - objects have been allocated using the fast path. + The alloc_fastpath file shows how many objects have been + allocated using the fast path. It can be written to clear the + current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/alloc_from_partial @@ -55,9 +56,10 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The alloc_from_partial file is read-only and specifies how - many times a cpu slab has been full and it has been refilled - by using a slab from the list of partially used slabs. + The alloc_from_partial file shows how many times a cpu slab has + been full and it has been refilled by using a slab from the list + of partially used slabs. It can be written to clear the current + count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/alloc_refill @@ -66,9 +68,9 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The alloc_refill file is read-only and specifies how many - times the per-cpu freelist was empty but there were objects - available as the result of remote cpu frees. + The alloc_refill file shows how many times the per-cpu freelist + was empty but there were objects available as the result of + remote cpu frees. It can be written to clear the current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/alloc_slab @@ -77,8 +79,9 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The alloc_slab file is read-only and specifies how many times - a new slab had to be allocated from the page allocator. + The alloc_slab file is shows how many times a new slab had to + be allocated from the page allocator. It can be written to + clear the current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/alloc_slowpath @@ -87,9 +90,10 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The alloc_slowpath file is read-only and specifies how many - objects have been allocated using the slow path because of a - refill or allocation from a partial or new slab. + The alloc_slowpath file shows how many objects have been + allocated using the slow path because of a refill or + allocation from a partial or new slab. It can be written to + clear the current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/cache_dma @@ -117,10 +121,11 @@ KernelVersion: 2.6.31 Contact: Pekka Enberg , Christoph Lameter Description: - The file cpuslab_flush is read-only and specifies how many - times a cache's cpu slabs have been flushed as the result of - destroying or shrinking a cache, a cpu going offline, or as - the result of forcing an allocation from a certain node. + The file cpuslab_flush shows how many times a cache's cpu slabs + have been flushed as the result of destroying or shrinking a + cache, a cpu going offline, or as the result of forcing an + allocation from a certain node. It can be written to clear the + current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/ctor @@ -139,8 +144,8 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The file deactivate_empty is read-only and specifies how many - times an empty cpu slab was deactivated. + The deactivate_empty file shows how many times an empty cpu slab + was deactivated. It can be written to clear the current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/deactivate_full @@ -149,8 +154,8 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The file deactivate_full is read-only and specifies how many - times a full cpu slab was deactivated. + The deactivate_full file shows how many times a full cpu slab + was deactivated. It can be written to clear the current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/deactivate_remote_frees @@ -159,9 +164,9 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The file deactivate_remote_frees is read-only and specifies how - many times a cpu slab has been deactivated and contained free - objects that were freed remotely. + The deactivate_remote_frees file shows how many times a cpu slab + has been deactivated and contained free objects that were freed + remotely. It can be written to clear the current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/deactivate_to_head @@ -170,9 +175,9 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The file deactivate_to_head is read-only and specifies how - many times a partial cpu slab was deactivated and added to the - head of its node's partial list. + The deactivate_to_head file shows how many times a partial cpu + slab was deactivated and added to the head of its node's partial + list. It can be written to clear the current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/deactivate_to_tail @@ -181,9 +186,9 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The file deactivate_to_tail is read-only and specifies how - many times a partial cpu slab was deactivated and added to the - tail of its node's partial list. + The deactivate_to_tail file shows how many times a partial cpu + slab was deactivated and added to the tail of its node's partial + list. It can be written to clear the current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/destroy_by_rcu @@ -201,9 +206,9 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The file free_add_partial is read-only and specifies how many - times an object has been freed in a full slab so that it had to - added to its node's partial list. + The free_add_partial file shows how many times an object has + been freed in a full slab so that it had to added to its node's + partial list. It can be written to clear the current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/free_calls @@ -222,9 +227,9 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The free_fastpath file is read-only and specifies how many - objects have been freed using the fast path because it was an - object from the cpu slab. + The free_fastpath file shows how many objects have been freed + using the fast path because it was an object from the cpu slab. + It can be written to clear the current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/free_frozen @@ -233,9 +238,9 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The free_frozen file is read-only and specifies how many - objects have been freed to a frozen slab (i.e. a remote cpu - slab). + The free_frozen file shows how many objects have been freed to + a frozen slab (i.e. a remote cpu slab). It can be written to + clear the current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/free_remove_partial @@ -244,9 +249,10 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The file free_remove_partial is read-only and specifies how - many times an object has been freed to a now-empty slab so - that it had to be removed from its node's partial list. + The free_remove_partial file shows how many times an object has + been freed to a now-empty slab so that it had to be removed from + its node's partial list. It can be written to clear the current + count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/free_slab @@ -255,8 +261,9 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The free_slab file is read-only and specifies how many times an - empty slab has been freed back to the page allocator. + The free_slab file shows how many times an empty slab has been + freed back to the page allocator. It can be written to clear + the current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/free_slowpath @@ -265,9 +272,9 @@ KernelVersion: 2.6.25 Contact: Pekka Enberg , Christoph Lameter Description: - The free_slowpath file is read-only and specifies how many - objects have been freed using the slow path (i.e. to a full or - partial slab). + The free_slowpath file shows how many objects have been freed + using the slow path (i.e. to a full or partial slab). It can + be written to clear the current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/hwcache_align @@ -346,10 +353,10 @@ KernelVersion: 2.6.26 Contact: Pekka Enberg , Christoph Lameter Description: - The file order_fallback is read-only and specifies how many - times an allocation of a new slab has not been possible at the - cache's order and instead fallen back to its minimum possible - order. + The order_fallback file shows how many times an allocation of a + new slab has not been possible at the cache's order and instead + fallen back to its minimum possible order. It can be written to + clear the current count. Available when CONFIG_SLUB_STATS is enabled. What: /sys/kernel/slab/cache/partial diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS new file mode 100644 index 0000000000000000000000000000000000000000..0af0e9eed5d6c1281433b4c0bc26f7c6577fe8a6 --- /dev/null +++ b/Documentation/arm/OMAP/DSS @@ -0,0 +1,317 @@ +OMAP2/3 Display Subsystem +------------------------- + +This is an almost total rewrite of the OMAP FB driver in drivers/video/omap +(let's call it DSS1). The main differences between DSS1 and DSS2 are DSI, +TV-out and multiple display support, but there are lots of small improvements +also. + +The DSS2 driver (omapdss module) is in arch/arm/plat-omap/dss/, and the FB, +panel and controller drivers are in drivers/video/omap2/. DSS1 and DSS2 live +currently side by side, you can choose which one to use. + +Features +-------- + +Working and tested features include: + +- MIPI DPI (parallel) output +- MIPI DSI output in command mode +- MIPI DBI (RFBI) output +- SDI output +- TV output +- All pieces can be compiled as a module or inside kernel +- Use DISPC to update any of the outputs +- Use CPU to update RFBI or DSI output +- OMAP DISPC planes +- RGB16, RGB24 packed, RGB24 unpacked +- YUV2, UYVY +- Scaling +- Adjusting DSS FCK to find a good pixel clock +- Use DSI DPLL to create DSS FCK + +Tested boards include: +- OMAP3 SDP board +- Beagle board +- N810 + +omapdss driver +-------------- + +The DSS driver does not itself have any support for Linux framebuffer, V4L or +such like the current ones, but it has an internal kernel API that upper level +drivers can use. + +The DSS driver models OMAP's overlays, overlay managers and displays in a +flexible way to enable non-common multi-display configuration. In addition to +modelling the hardware overlays, omapdss supports virtual overlays and overlay +managers. These can be used when updating a display with CPU or system DMA. + +Panel and controller drivers +---------------------------- + +The drivers implement panel or controller specific functionality and are not +usually visible to users except through omapfb driver. They register +themselves to the DSS driver. + +omapfb driver +------------- + +The omapfb driver implements arbitrary number of standard linux framebuffers. +These framebuffers can be routed flexibly to any overlays, thus allowing very +dynamic display architecture. + +The driver exports some omapfb specific ioctls, which are compatible with the +ioctls in the old driver. + +The rest of the non standard features are exported via sysfs. Whether the final +implementation will use sysfs, or ioctls, is still open. + +V4L2 drivers +------------ + +V4L2 is being implemented in TI. + +From omapdss point of view the V4L2 drivers should be similar to framebuffer +driver. + +Architecture +-------------------- + +Some clarification what the different components do: + + - Framebuffer is a memory area inside OMAP's SRAM/SDRAM that contains the + pixel data for the image. Framebuffer has width and height and color + depth. + - Overlay defines where the pixels are read from and where they go on the + screen. The overlay may be smaller than framebuffer, thus displaying only + part of the framebuffer. The position of the overlay may be changed if + the overlay is smaller than the display. + - Overlay manager combines the overlays in to one image and feeds them to + display. + - Display is the actual physical display device. + +A framebuffer can be connected to multiple overlays to show the same pixel data +on all of the overlays. Note that in this case the overlay input sizes must be +the same, but, in case of video overlays, the output size can be different. Any +framebuffer can be connected to any overlay. + +An overlay can be connected to one overlay manager. Also DISPC overlays can be +connected only to DISPC overlay managers, and virtual overlays can be only +connected to virtual overlays. + +An overlay manager can be connected to one display. There are certain +restrictions which kinds of displays an overlay manager can be connected: + + - DISPC TV overlay manager can be only connected to TV display. + - Virtual overlay managers can only be connected to DBI or DSI displays. + - DISPC LCD overlay manager can be connected to all displays, except TV + display. + +Sysfs +----- +The sysfs interface is mainly used for testing. I don't think sysfs +interface is the best for this in the final version, but I don't quite know +what would be the best interfaces for these things. + +The sysfs interface is divided to two parts: DSS and FB. + +/sys/class/graphics/fb? directory: +mirror 0=off, 1=on +rotate Rotation 0-3 for 0, 90, 180, 270 degrees +rotate_type 0 = DMA rotation, 1 = VRFB rotation +overlays List of overlay numbers to which framebuffer pixels go +phys_addr Physical address of the framebuffer +virt_addr Virtual address of the framebuffer +size Size of the framebuffer + +/sys/devices/platform/omapdss/overlay? directory: +enabled 0=off, 1=on +input_size width,height (ie. the framebuffer size) +manager Destination overlay manager name +name +output_size width,height +position x,y +screen_width width +global_alpha global alpha 0-255 0=transparent 255=opaque + +/sys/devices/platform/omapdss/manager? directory: +display Destination display +name +alpha_blending_enabled 0=off, 1=on +trans_key_enabled 0=off, 1=on +trans_key_type gfx-destination, video-source +trans_key_value transparency color key (RGB24) +default_color default background color (RGB24) + +/sys/devices/platform/omapdss/display? directory: +ctrl_name Controller name +mirror 0=off, 1=on +update_mode 0=off, 1=auto, 2=manual +enabled 0=off, 1=on +name +rotate Rotation 0-3 for 0, 90, 180, 270 degrees +timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw) + When writing, two special timings are accepted for tv-out: + "pal" and "ntsc" +panel_name +tear_elim Tearing elimination 0=off, 1=on + +There are also some debugfs files at /omapdss/ which show information +about clocks and registers. + +Examples +-------- + +The following definitions have been made for the examples below: + +ovl0=/sys/devices/platform/omapdss/overlay0 +ovl1=/sys/devices/platform/omapdss/overlay1 +ovl2=/sys/devices/platform/omapdss/overlay2 + +mgr0=/sys/devices/platform/omapdss/manager0 +mgr1=/sys/devices/platform/omapdss/manager1 + +lcd=/sys/devices/platform/omapdss/display0 +dvi=/sys/devices/platform/omapdss/display1 +tv=/sys/devices/platform/omapdss/display2 + +fb0=/sys/class/graphics/fb0 +fb1=/sys/class/graphics/fb1 +fb2=/sys/class/graphics/fb2 + +Default setup on OMAP3 SDP +-------------------------- + +Here's the default setup on OMAP3 SDP board. All planes go to LCD. DVI +and TV-out are not in use. The columns from left to right are: +framebuffers, overlays, overlay managers, displays. Framebuffers are +handled by omapfb, and the rest by the DSS. + +FB0 --- GFX -\ DVI +FB1 --- VID1 --+- LCD ---- LCD +FB2 --- VID2 -/ TV ----- TV + +Example: Switch from LCD to DVI +---------------------- + +w=`cat $dvi/timings | cut -d "," -f 2 | cut -d "/" -f 1` +h=`cat $dvi/timings | cut -d "," -f 3 | cut -d "/" -f 1` + +echo "0" > $lcd/enabled +echo "" > $mgr0/display +fbset -fb /dev/fb0 -xres $w -yres $h -vxres $w -vyres $h +# at this point you have to switch the dvi/lcd dip-switch from the omap board +echo "dvi" > $mgr0/display +echo "1" > $dvi/enabled + +After this the configuration looks like: + +FB0 --- GFX -\ -- DVI +FB1 --- VID1 --+- LCD -/ LCD +FB2 --- VID2 -/ TV ----- TV + +Example: Clone GFX overlay to LCD and TV +------------------------------- + +w=`cat $tv/timings | cut -d "," -f 2 | cut -d "/" -f 1` +h=`cat $tv/timings | cut -d "," -f 3 | cut -d "/" -f 1` + +echo "0" > $ovl0/enabled +echo "0" > $ovl1/enabled + +echo "" > $fb1/overlays +echo "0,1" > $fb0/overlays + +echo "$w,$h" > $ovl1/output_size +echo "tv" > $ovl1/manager + +echo "1" > $ovl0/enabled +echo "1" > $ovl1/enabled + +echo "1" > $tv/enabled + +After this the configuration looks like (only relevant parts shown): + +FB0 +-- GFX ---- LCD ---- LCD + \- VID1 ---- TV ---- TV + +Misc notes +---------- + +OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator. + +Using DSI DPLL to generate pixel clock it is possible produce the pixel clock +of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI. + +Rotation and mirroring currently only supports RGB565 and RGB8888 modes. VRFB +does not support mirroring. + +VRFB rotation requires much more memory than non-rotated framebuffer, so you +probably need to increase your vram setting before using VRFB rotation. Also, +many applications may not work with VRFB if they do not pay attention to all +framebuffer parameters. + +Kernel boot arguments +--------------------- + +vram= + - Amount of total VRAM to preallocate. For example, "10M". omapfb + allocates memory for framebuffers from VRAM. + +omapfb.mode=:[,...] + - Default video mode for specified displays. For example, + "dvi:800x400MR-24@60". See drivers/video/modedb.c. + There are also two special modes: "pal" and "ntsc" that + can be used to tv out. + +omapfb.vram=:[@][,...] + - VRAM allocated for a framebuffer. Normally omapfb allocates vram + depending on the display size. With this you can manually allocate + more or define the physical address of each framebuffer. For example, + "1:4M" to allocate 4M for fb1. + +omapfb.debug= + - Enable debug printing. You have to have OMAPFB debug support enabled + in kernel config. + +omapfb.test= + - Draw test pattern to framebuffer whenever framebuffer settings change. + You need to have OMAPFB debug support enabled in kernel config. + +omapfb.vrfb= + - Use VRFB rotation for all framebuffers. + +omapfb.rotate= + - Default rotation applied to all framebuffers. + 0 - 0 degree rotation + 1 - 90 degree rotation + 2 - 180 degree rotation + 3 - 270 degree rotation + +omapfb.mirror= + - Default mirror for all framebuffers. Only works with DMA rotation. + +omapdss.def_disp= + - Name of default display, to which all overlays will be connected. + Common examples are "lcd" or "tv". + +omapdss.debug= + - Enable debug printing. You have to have DSS debug support enabled in + kernel config. + +TODO +---- + +DSS locking + +Error checking +- Lots of checks are missing or implemented just as BUG() + +System DMA update for DSI +- Can be used for RGB16 and RGB24P modes. Probably not for RGB24U (how + to skip the empty byte?) + +OMAP1 support +- Not sure if needed + diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt index 75a58d14d3cf42de050b292ea1dafdb5f2f2cb53..6c30e930c1225d141cda19989cbb62462804b29d 100644 --- a/Documentation/cpu-freq/cpu-drivers.txt +++ b/Documentation/cpu-freq/cpu-drivers.txt @@ -92,9 +92,9 @@ policy->cpuinfo.max_freq - the minimum and maximum frequency (in kHz) which is supported by this CPU policy->cpuinfo.transition_latency the time it takes on this CPU to - switch between two frequencies (if - appropriate, else specify - CPUFREQ_ETERNAL) + switch between two frequencies in + nanoseconds (if appropriate, else + specify CPUFREQ_ETERNAL) policy->cur The current operating frequency of this CPU (if appropriate) diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt index 2a5b850847c024e676395320f534c1982c8ae33a..04f6b32993e69ca4185a81bbaadb677aac5056e9 100644 --- a/Documentation/cpu-freq/user-guide.txt +++ b/Documentation/cpu-freq/user-guide.txt @@ -203,6 +203,17 @@ scaling_cur_freq : Current frequency of the CPU as determined by the frequency the kernel thinks the CPU runs at. +bios_limit : If the BIOS tells the OS to limit a CPU to + lower frequencies, the user can read out the + maximum available frequency from this file. + This typically can happen through (often not + intended) BIOS settings, restrictions + triggered through a service processor or other + BIOS/HW based implementations. + This does not cover thermal ACPI limitations + which can be detected through the generic + thermal driver. + If you have selected the "userspace" governor which allows you to set the CPU operating frequency to a specific value, you can read out the current frequency in diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt index 9d620c153b04f2469bf664e6489e3af6817663e2..4d4a644b505eeb42cb5acae0b69f162c3f053a4d 100644 --- a/Documentation/cpu-hotplug.txt +++ b/Documentation/cpu-hotplug.txt @@ -49,6 +49,12 @@ maxcpus=n Restrict boot time cpus to n. Say if you have 4 cpus, using additional_cpus=n (*) Use this to limit hotpluggable cpus. This option sets cpu_possible_map = cpu_present_map + additional_cpus +cede_offline={"off","on"} Use this option to disable/enable putting offlined + processors to an extended H_CEDE state on + supported pseries platforms. + If nothing is specified, + cede_offline is set to "on". + (*) Option valid only for following architectures - ia64 diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 2a4d77946c7dc075df1a6678a54204ea8e618502..eb2c138c277c45ec66b25116cbd744d42c41878f 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -291,13 +291,6 @@ Who: Michael Buesch --------------------------- -What: usedac i386 kernel parameter -When: 2.6.27 -Why: replaced by allowdac and no dac combination -Who: Glauber Costa - ---------------------------- - What: print_fn_descriptor_symbol() When: October 2009 Why: The %pF vsprintf format provides the same functionality in a diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX index f15621ee55996e0a0928f08783ddcaa43ddfee21..7001782ab932dbc3a8b5a16b8188c8a2605d84d3 100644 --- a/Documentation/filesystems/00-INDEX +++ b/Documentation/filesystems/00-INDEX @@ -36,6 +36,8 @@ dnotify.txt - info about directory notification in Linux. ecryptfs.txt - docs on eCryptfs: stacked cryptographic filesystem for Linux. +exofs.txt + - info, usage, mount options, design about EXOFS. ext2.txt - info, mount options and specifications for the Ext2 filesystem. ext3.txt diff --git a/Documentation/filesystems/exofs.txt b/Documentation/filesystems/exofs.txt index 0ced74c2f73c57a489413a0aa226da45a778016d..abd2a9b5b787c324034f24d3a84523f99c657de1 100644 --- a/Documentation/filesystems/exofs.txt +++ b/Documentation/filesystems/exofs.txt @@ -60,13 +60,13 @@ USAGE mkfs.exofs --pid=65536 --format /dev/osd0 - The --format is optional if not specified no OSD_FORMAT will be - preformed and a clean file system will be created in the specified pid, + The --format is optional. If not specified, no OSD_FORMAT will be + performed and a clean file system will be created in the specified pid, in the available space of the target. (Use --format=size_in_meg to limit the total LUN space available) - If pid already exist it will be deleted and a new one will be created in it's - place. Be careful. + If pid already exists, it will be deleted and a new one will be created in + its place. Be careful. An exofs lives inside a single OSD partition. You can create multiple exofs filesystems on the same device using multiple pids. @@ -81,7 +81,7 @@ USAGE 7. For reference (See do-exofs example script): do-exofs start - an example of how to perform the above steps. - do-exofs stop - an example of how to unmount the file system. + do-exofs stop - an example of how to unmount the file system. do-exofs format - an example of how to format and mkfs a new exofs. 8. Extra compilation flags (uncomment in fs/exofs/Kbuild): @@ -104,8 +104,8 @@ Where: exofs specific options: Options are separated by commas (,) pid= - The partition number to mount/create as container of the filesystem. - This option is mandatory - to= - Timeout in ticks for a single command + This option is mandatory. + to= - Timeout in ticks for a single command. default is (60 * HZ) [for debugging only] =============================================================================== @@ -116,7 +116,7 @@ DESIGN with a special ID (defined in common.h). Information included in the file system control block is used to fill the in-memory superblock structure at mount time. This object is created before - the file system is used by mkexofs.c It contains information such as: + the file system is used by mkexofs.c. It contains information such as: - The file system's magic number - The next inode number to be allocated @@ -134,8 +134,8 @@ DESIGN attributes. This applies to both regular files and other types (directories, device files, symlinks, etc.). -* Credentials are generated per object (inode and superblock) when they is - created in memory (read off disk or created). The credential works for all +* Credentials are generated per object (inode and superblock) when they are + created in memory (read from disk or created). The credential works for all operations and is used as long as the object remains in memory. * Async OSD operations are used whenever possible, but the target may execute @@ -145,7 +145,8 @@ DESIGN from executing in reverse order: - The following are handled with the OBJ_CREATED and OBJ_2BCREATED flags. OBJ_CREATED is set when we know the object exists on the OSD - - in create's callback function, and when we successfully do a read_inode. + in create's callback function, and when we successfully do a + read_inode. OBJ_2BCREATED is set in the beginning of the create function, so we know that we should wait. - create/delete: delete should wait until the object is created diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt index 05d5cf1d743f1318ef97e2f47cf06a607ebc0f2c..867c5b50cb42967a40484a6ffb9dae07b74bfe8a 100644 --- a/Documentation/filesystems/ext3.txt +++ b/Documentation/filesystems/ext3.txt @@ -32,8 +32,8 @@ journal_dev=devnum When the external journal device's major/minor numbers identified through its new major/minor numbers encoded in devnum. -noload Don't load the journal on mounting. Note that this forces - mount of inconsistent filesystem, which can lead to +norecovery Don't load the journal on mounting. Note that this forces +noload mount of inconsistent filesystem, which can lead to various problems. data=journal All data are committed into the journal prior to being diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt index 6d94e0696f8c313ee5a439f5ed2f140b356500f6..af6885c3c821f621f5827a46cb0728c61a9e768c 100644 --- a/Documentation/filesystems/ext4.txt +++ b/Documentation/filesystems/ext4.txt @@ -153,8 +153,8 @@ journal_dev=devnum When the external journal device's major/minor numbers identified through its new major/minor numbers encoded in devnum. -noload Don't load the journal on mounting. Note that - if the filesystem was not unmounted cleanly, +norecovery Don't load the journal on mounting. Note that +noload if the filesystem was not unmounted cleanly, skipping the journal replay will lead to the filesystem containing inconsistencies that can lead to any number of problems. @@ -353,6 +353,12 @@ noauto_da_alloc replacing existing files via patterns such as system crashes before the delayed allocation blocks are forced to disk. +discard Controls whether ext4 should issue discard/TRIM +nodiscard(*) commands to the underlying block device when + blocks are freed. This is useful for SSD devices + and sparse/thinly-provisioned LUNs, but it is off + by default until sufficient testing has been done. + Data Mode ========= There are 3 different data modes: diff --git a/Documentation/filesystems/nilfs2.txt b/Documentation/filesystems/nilfs2.txt index 01539f4106763f8b9ad283d7e315a4b9c3639a73..4949fcaa6b6a94f6d8b42d483a86c9a5984e0420 100644 --- a/Documentation/filesystems/nilfs2.txt +++ b/Documentation/filesystems/nilfs2.txt @@ -49,8 +49,7 @@ Mount options NILFS2 supports the following mount options: (*) == default -barrier=on(*) This enables/disables barriers. barrier=off disables - it, barrier=on enables it. +nobarrier Disables barriers. errors=continue(*) Keep going on a filesystem error. errors=remount-ro Remount the filesystem read-only on an error. errors=panic Panic and halt the machine if an error occurs. @@ -71,6 +70,10 @@ order=strict Apply strict in-order semantics that preserves sequence blocks. That means, it is guaranteed that no overtaking of events occurs in the recovered file system after a crash. +norecovery Disable recovery of the filesystem on mount. + This disables every write access on the device for + read-only mounts or snapshots. This option will fail + for r/w mounts on an unclean volume. NILFS2 usage ============ diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 623f094c9d8d95a535d3274f60d6a30dc8d71b5f..3de2f32edd9008e3af8e1c89e02a3d5bfeae06ae 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -472,7 +472,7 @@ __sync_single_inode) to check if ->writepages has been successful in writing out the whole address_space. The Writeback tag is used by filemap*wait* and sync_page* functions, -via wait_on_page_writeback_range, to wait for all writeback to +via filemap_fdatawait_range, to wait for all writeback to complete. While waiting ->sync_page (if defined) will be called on each page that is found to require writeback. diff --git a/Documentation/isdn/README.gigaset b/Documentation/isdn/README.gigaset index 0fc9831d7ecbe3e3c8f605767df3a9a3fca365e4..794941fc94931f32d22265f4574eb0a39619cbd1 100644 --- a/Documentation/isdn/README.gigaset +++ b/Documentation/isdn/README.gigaset @@ -68,22 +68,38 @@ GigaSet 307x Device Driver for troubleshooting or to pass module parameters. The module ser_gigaset provides a serial line discipline N_GIGASET_M101 - which drives the device through the regular serial line driver. It must - be attached to the serial line to which the M101 is connected with the - ldattach(8) command (requires util-linux-ng release 2.14 or later), for - example: - ldattach GIGASET_M101 /dev/ttyS1 + which uses the regular serial port driver to access the device, and must + therefore be attached to the serial device to which the M101 is connected. + The ldattach(8) command (included in util-linux-ng release 2.14 or later) + can be used for that purpose, for example: + ldattach GIGASET_M101 /dev/ttyS1 This will open the device file, attach the line discipline to it, and then sleep in the background, keeping the device open so that the line discipline remains active. To deactivate it, kill the daemon, for example with - killall ldattach + killall ldattach before disconnecting the device. To have this happen automatically at system startup/shutdown on an LSB compatible system, create and activate an appropriate LSB startup script /etc/init.d/gigaset. (The init name 'gigaset' is officially assigned to this project by LANANA.) Alternatively, just add the 'ldattach' command line to /etc/rc.local. + The modules accept the following parameters: + + Module Parameter Meaning + + gigaset debug debug level (see section 3.2.) + + startmode initial operation mode (see section 2.5.): + bas_gigaset ) 1=ISDN4linux/CAPI (default), 0=Unimodem + ser_gigaset ) + usb_gigaset ) cidmode initial Call-ID mode setting (see section + 2.5.): 1=on (default), 0=off + + Depending on your distribution you may want to create a separate module + configuration file /etc/modprobe.d/gigaset for these, or add them to a + custom file like /etc/modprobe.conf.local. + 2.2. Device nodes for user space programs ------------------------------------ The device can be accessed from user space (eg. by the user space tools @@ -93,11 +109,48 @@ GigaSet 307x Device Driver - /dev/ttyGU0 for M105 (USB data boxes) - /dev/ttyGB0 for the base driver (direct USB connection) - You can also select a "default device" which is used by the frontends when + If you connect more than one device of a type, they will get consecutive + device nodes, eg. /dev/ttyGU1 for a second M105. + + You can also set a "default device" for the user space tools to use when no device node is given as parameter, by creating a symlink /dev/ttyG to one of them, eg.: - ln -s /dev/ttyGB0 /dev/ttyG + ln -s /dev/ttyGB0 /dev/ttyG + + The devices accept the following device specific ioctl calls + (defined in gigaset_dev.h): + + ioctl(int fd, GIGASET_REDIR, int *cmd); + If cmd==1, the device is set to be controlled exclusively through the + character device node; access from the ISDN subsystem is blocked. + If cmd==0, the device is set to be used from the ISDN subsystem and does + not communicate through the character device node. + + ioctl(int fd, GIGASET_CONFIG, int *cmd); + (ser_gigaset and usb_gigaset only) + If cmd==1, the device is set to adapter configuration mode where commands + are interpreted by the M10x DECT adapter itself instead of being + forwarded to the base station. In this mode, the device accepts the + commands described in Siemens document "AT-Kommando Alignment M10x Data" + for setting the operation mode, associating with a base station and + querying parameters like field strengh and signal quality. + Note that there is no ioctl command for leaving adapter configuration + mode and returning to regular operation. In order to leave adapter + configuration mode, write the command ATO to the device. + + ioctl(int fd, GIGASET_BRKCHARS, unsigned char brkchars[6]); + (usb_gigaset only) + Set the break characters on an M105's internal serial adapter to the six + bytes stored in brkchars[]. Unused bytes should be set to zero. + + ioctl(int fd, GIGASET_VERSION, unsigned version[4]); + Retrieve version information from the driver. version[0] must be set to + one of: + - GIGVER_DRIVER: retrieve driver version + - GIGVER_COMPAT: retrieve interface compatibility version + - GIGVER_FWBASE: retrieve the firmware version of the base + Upon return, version[] is filled with the requested version information. 2.3. ISDN4linux ---------- @@ -113,15 +166,24 @@ GigaSet 307x Device Driver Connection State: 0, Response: -1 gigaset_process_response: resp_code -1 in ConState 0 ! Timeout occurred - you might need to use unimodem mode. (see section 2.5.) + you probably need to use unimodem mode. (see section 2.5.) 2.4. CAPI ---- If the driver is compiled with CAPI support (kernel configuration option GIGASET_CAPI, experimental) it can also be used with CAPI 2.0 kernel and - user space applications. ISDN4Linux is supported in this configuration + user space applications. For user space access, the module capi.ko must + be loaded. The capiinit command (included in the capi4k-utils package) + does this for you. + + The CAPI variant of the driver supports legacy ISDN4Linux applications via the capidrv compatibility driver. The kernel module capidrv.ko must - be loaded explicitly ("modprobe capidrv") if needed. + be loaded explicitly with the command + modprobe capidrv + if needed, and cannot be unloaded again without unloading the driver + first. (These are limitations of capidrv.) + + The note about unimodem mode in the preceding section applies here, too. 2.5. Unimodem mode ------------- @@ -134,9 +196,14 @@ GigaSet 307x Device Driver You can switch back using gigacontr --mode isdn - You can also load the driver using e.g. - modprobe usb_gigaset startmode=0 - to prevent the driver from starting in "isdn4linux mode". + You can also put the driver directly into Unimodem mode when it's loaded, + by passing the module parameter startmode=0 to the hardware specific + module, e.g. + modprobe usb_gigaset startmode=0 + or by adding a line like + options usb_gigaset startmode=0 + to an appropriate module configuration file, like /etc/modprobe.d/gigaset + or /etc/modprobe.conf.local. In this mode the device works like a modem connected to a serial port (the /dev/ttyGU0, ... mentioned above) which understands the commands @@ -164,9 +231,8 @@ GigaSet 307x Device Driver options ppp_async flag_time=0 - to /etc/modprobe.conf. If your distribution has some local module - configuration file like /etc/modprobe.conf.local, - using that should be preferred. + to an appropriate module configuration file, like /etc/modprobe.d/gigaset + or /etc/modprobe.conf.local. 2.6. Call-ID (CID) mode ------------------ @@ -189,12 +255,13 @@ GigaSet 307x Device Driver settings (CID mode). - If you have several DECT data devices (M10x) which you want to use in turn, select Unimodem mode by passing the parameter "cidmode=0" to - the driver ("modprobe usb_gigaset cidmode=0" or modprobe.conf). + the appropriate driver module (ser_gigaset or usb_gigaset). If you want both of these at once, you are out of luck. - You can also use /sys/class/tty/ttyGxy/cidmode for changing the CID mode - setting (ttyGxy is ttyGU0 or ttyGB0). + You can also use the tty class parameter "cidmode" of the device to + change its CID mode while the driver is loaded, eg. + echo 0 > /sys/class/tty/ttyGU0/cidmode 2.7. Unregistered Wireless Devices (M101/M105) ----------------------------------------- @@ -208,7 +275,7 @@ GigaSet 307x Device Driver driver. In that situation, a restricted set of functions is available which includes, in particular, those necessary for registering the device to a base or for switching it between Fixed Part and Portable Part - modes. + modes. See the gigacontr(8) manpage for details. 3. Troubleshooting --------------- @@ -222,9 +289,7 @@ GigaSet 307x Device Driver options isdn dialtimeout=15 - to /etc/modprobe.conf. If your distribution has some local module - configuration file like /etc/modprobe.conf.local, - using that should be preferred. + to /etc/modprobe.d/gigaset, /etc/modprobe.conf.local or a similar file. Problem: Your isdn script aborts with a message about isdnlog. @@ -264,7 +329,8 @@ GigaSet 307x Device Driver The initial value can be set using the debug parameter when loading the module "gigaset", e.g. by adding a line options gigaset debug=0 - to /etc/modprobe.conf, ... + to your module configuration file, eg. /etc/modprobe.d/gigaset or + /etc/modprobe.conf.local. Generated debugging information can be found - as output of the command diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 777dc8a32df8d077fc9bdca101a071d3c7f97294..ab95d3ada5c7f7210d2a13adc619ec3d4b9548bd 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1787,6 +1787,11 @@ and is between 256 and 4096 characters. It is defined in the file waiting for the ACK, so if this is set too high interrupts *may* be lost! + omap_mux= [OMAP] Override bootloader pin multiplexing. + Format: ... + For example, to override I2C bus2: + omap_mux=i2c2_scl.i2c2_scl=0x100,i2c2_sda.i2c2_sda=0x100 + opl3= [HW,OSS] Format: @@ -2663,6 +2668,8 @@ and is between 256 and 4096 characters. It is defined in the file to a common usb-storage quirk flag as follows: a = SANE_SENSE (collect more than 18 bytes of sense data); + b = BAD_SENSE (don't collect more than 18 + bytes of sense data); c = FIX_CAPACITY (decrease the reported device capacity by one sector); h = CAPACITY_HEURISTICS (decrease the diff --git a/Documentation/lockstat.txt b/Documentation/lockstat.txt index 9cb9138f7a79bcd67bf4ac2f69741e812b5a14c2..65f4c795015dead0cfde0f60381b7efcec67da9b 100644 --- a/Documentation/lockstat.txt +++ b/Documentation/lockstat.txt @@ -62,8 +62,20 @@ applicable). It also tracks 4 contention points per class. A contention point is a call site that had to wait on lock acquisition. + - CONFIGURATION + +Lock statistics are enabled via CONFIG_LOCK_STATS. + - USAGE +Enable collection of statistics: + +# echo 1 >/proc/sys/kernel/lock_stat + +Disable collection of statistics: + +# echo 0 >/proc/sys/kernel/lock_stat + Look at the current lock statistics: ( line numbers not part of actual output, done for clarity in the explanation diff --git a/Documentation/md.txt b/Documentation/md.txt index 4edd39ec7db91abcbcbac352fc3c5e6d3e3c3eca..188f4768f1d58c013d962f993ae36483195fd288 100644 --- a/Documentation/md.txt +++ b/Documentation/md.txt @@ -233,9 +233,9 @@ All md devices contain: 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. + this will be a very large number (or 'none' since 2.6.30-rc1). 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 @@ -296,6 +296,51 @@ All md devices contain: active-idle like active, but no writes have been seen for a while (safe_mode_delay). + bitmap/location + This indicates where the write-intent bitmap for the array is + stored. + It can be one of "none", "file" or "[+-]N". + "file" may later be extended to "file:/file/name" + "[+-]N" means that many sectors from the start of the metadata. + This is replicated on all devices. For arrays with externally + managed metadata, the offset is from the beginning of the + device. + bitmap/chunksize + The size, in bytes, of the chunk which will be represented by a + single bit. For RAID456, it is a portion of an individual + device. For RAID10, it is a portion of the array. For RAID1, it + is both (they come to the same thing). + bitmap/time_base + The time, in seconds, between looking for bits in the bitmap to + be cleared. In the current implementation, a bit will be cleared + between 2 and 3 times "time_base" after all the covered blocks + are known to be in-sync. + bitmap/backlog + When write-mostly devices are active in a RAID1, write requests + to those devices proceed in the background - the filesystem (or + other user of the device) does not have to wait for them. + 'backlog' sets a limit on the number of concurrent background + writes. If there are more than this, new writes will by + synchronous. + bitmap/metadata + This can be either 'internal' or 'external'. + 'internal' is the default and means the metadata for the bitmap + is stored in the first 256 bytes of the allocated space and is + managed by the md module. + 'external' means that bitmap metadata is managed externally to + the kernel (i.e. by some userspace program) + bitmap/can_clear + This is either 'true' or 'false'. If 'true', then bits in the + bitmap will be cleared when the corresponding blocks are thought + to be in-sync. If 'false', bits will never be cleared. + This is automatically set to 'false' if a write happens on a + degraded array, or if the array becomes degraded during a write. + When metadata is managed externally, it should be set to true + once the array becomes non-degraded, and this fact has been + recorded in the metadata. + + + As component devices are added to an md array, they appear in the 'md' directory as new directories named @@ -334,8 +379,9 @@ Each directory contains: Writing "writemostly" sets the writemostly flag. Writing "-writemostly" clears the writemostly flag. Writing "blocked" sets the "blocked" flag. - Writing "-blocked" clear the "blocked" flag and allows writes + Writing "-blocked" clears the "blocked" flag and allows writes to complete. + Writing "in_sync" sets the in_sync flag. This file responds to select/poll. Any change to 'faulty' or 'blocked' causes an event. @@ -372,6 +418,24 @@ Each directory contains: array. If a value less than the current component_size is written, it will be rejected. + recovery_start + + When the device is not 'in_sync', this records the number of + sectors from the start of the device which are known to be + correct. This is normally zero, but during a recovery + operation is will steadily increase, and if the recovery is + interrupted, restoring this value can cause recovery to + avoid repeating the earlier blocks. With v1.x metadata, this + value is saved and restored automatically. + + This can be set whenever the device is not an active member of + the array, either before the array is activated, or before + the 'slot' is set. + + Setting this to 'none' is equivalent to setting 'in_sync'. + Setting to any other value also clears the 'in_sync' flag. + + An active md device will also contain and entry for each active device in the array. These are named diff --git a/Documentation/powerpc/dts-bindings/fsl/board.txt b/Documentation/powerpc/dts-bindings/fsl/board.txt index e8b5bc24d0acab21dd1efd094fc8940cf7c0b63a..39e941515a36ee18ab3ca59d0b71e4e4ae93c53c 100644 --- a/Documentation/powerpc/dts-bindings/fsl/board.txt +++ b/Documentation/powerpc/dts-bindings/fsl/board.txt @@ -20,12 +20,16 @@ Required properities: - compatible : should be "fsl,fpga-pixis". - reg : should contain the address and the length of the FPPGA register set. +- interrupt-parent: should specify phandle for the interrupt controller. +- interrupts : should specify event (wakeup) IRQ. Example (MPC8610HPCD): board-control@e8000000 { compatible = "fsl,fpga-pixis"; reg = <0xe8000000 32>; + interrupt-parent = <&mpic>; + interrupts = <8 8>; }; * Freescale BCSR GPIO banks diff --git a/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt b/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt index cabc780f7258fc0c04875b859a7e45659b0e04af..5c6602dbfdc22aae9cffc284b7303193616af2a7 100644 --- a/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt +++ b/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt @@ -103,7 +103,22 @@ fsl,mpc5200-gpt nodes --------------------- On the mpc5200 and 5200b, GPT0 has a watchdog timer function. If the board design supports the internal wdt, then the device node for GPT0 should -include the empty property 'fsl,has-wdt'. +include the empty property 'fsl,has-wdt'. Note that this does not activate +the watchdog. The timer will function as a GPT if the timer api is used, and +it will function as watchdog if the watchdog device is used. The watchdog +mode has priority over the gpt mode, i.e. if the watchdog is activated, any +gpt api call to this timer will fail with -EBUSY. + +If you add the property + fsl,wdt-on-boot = ; +GPT0 will be marked as in-use watchdog, i.e. blocking every gpt access to it. +If n>0, the watchdog is started with a timeout of n seconds. If n=0, the +configuration of the watchdog is not touched. This is useful in two cases: +- just mark GPT0 as watchdog, blocking gpt accesses, and configure it later; +- do not touch a configuration assigned by the boot loader which supervises + the boot process itself. + +The watchdog will respect the CONFIG_WATCHDOG_NOWAYOUT option. An mpc5200-gpt can be used as a single line GPIO controller. To do so, add the following properties to the gpt node: diff --git a/Documentation/powerpc/dts-bindings/xilinx.txt b/Documentation/powerpc/dts-bindings/xilinx.txt index 80339fe4300b7cf504ddc55ebe57af54b34df1ce..ea68046bb9cb1381db127087280822bc04e49a6d 100644 --- a/Documentation/powerpc/dts-bindings/xilinx.txt +++ b/Documentation/powerpc/dts-bindings/xilinx.txt @@ -292,4 +292,15 @@ - reg-offset : A value of 3 is required - reg-shift : A value of 2 is required + vii) Xilinx USB Host controller + + The Xilinx USB host controller is EHCI compatible but with a different + base address for the EHCI registers, and it is always a big-endian + USB Host controller. The hardware can be configured as high speed only, + or high speed/full speed hybrid. + + Required properties: + - xlnx,support-usb-fs: A value 0 means the core is built as high speed + only. A value 1 means the core also supports + full speed devices. diff --git a/Documentation/serial/hayes-esp.txt b/Documentation/serial/hayes-esp.txt deleted file mode 100644 index 09b5d58567588ff3e24d8b6bea5511eafba651d1..0000000000000000000000000000000000000000 --- a/Documentation/serial/hayes-esp.txt +++ /dev/null @@ -1,154 +0,0 @@ -HAYES ESP DRIVER VERSION 2.1 - -A big thanks to the people at Hayes, especially Alan Adamson. Their support -has enabled me to provide enhancements to the driver. - -Please report your experiences with this driver to me (arobinso@nyx.net). I -am looking for both positive and negative feedback. - -*** IMPORTANT CHANGES FOR 2.1 *** -Support for PIO mode. Five situations will cause PIO mode to be used: -1) A multiport card is detected. PIO mode will always be used. (8 port cards -do not support DMA). -2) The DMA channel is set to an invalid value (anything other than 1 or 3). -3) The DMA buffer/channel could not be allocated. The port will revert to PIO -mode until it is reopened. -4) Less than a specified number of bytes need to be transferred to/from the -FIFOs. PIO mode will be used for that transfer only. -5) A port needs to do a DMA transfer and another port is already using the -DMA channel. PIO mode will be used for that transfer only. - -Since the Hayes ESP seems to conflict with other cards (notably sound cards) -when using DMA, DMA is turned off by default. To use DMA, it must be turned -on explicitly, either with the "dma=" option described below or with -setserial. A multiport card can be forced into DMA mode by using setserial; -however, most multiport cards don't support DMA. - -The latest version of setserial allows the enhanced configuration of the ESP -card to be viewed and modified. -*** - -This package contains the files needed to compile a module to support the Hayes -ESP card. The drivers are basically a modified version of the serial drivers. - -Features: - -- Uses the enhanced mode of the ESP card, allowing a wider range of - interrupts and features than compatibility mode -- Uses DMA and 16 bit PIO mode to transfer data to and from the ESP's FIFOs, - reducing CPU load -- Supports primary and secondary ports - - -If the driver is compiled as a module, the IRQs to use can be specified by -using the irq= option. The format is: - -irq=[0x100],[0x140],[0x180],[0x200],[0x240],[0x280],[0x300],[0x380] - -The address in brackets is the base address of the card. The IRQ of -nonexistent cards can be set to 0. If an IRQ of a card that does exist is set -to 0, the driver will attempt to guess at the correct IRQ. For example, to set -the IRQ of the card at address 0x300 to 12, the insmod command would be: - -insmod esp irq=0,0,0,0,0,0,12,0 - -The custom divisor can be set by using the divisor= option. The format is the -same as for the irq= option. Each divisor value is a series of hex digits, -with each digit representing the divisor to use for a corresponding port. The -divisor value is constructed RIGHT TO LEFT. Specifying a nonzero divisor value -will automatically set the spd_cust flag. To calculate the divisor to use for -a certain baud rate, divide the port's base baud (generally 921600) by the -desired rate. For example, to set the divisor of the primary port at 0x300 to -4 and the divisor of the secondary port at 0x308 to 8, the insmod command would -be: - -insmod esp divisor=0,0,0,0,0,0,0x84,0 - -The dma= option can be used to set the DMA channel. The channel can be either -1 or 3. Specifying any other value will force the driver to use PIO mode. -For example, to set the DMA channel to 3, the insmod command would be: - -insmod esp dma=3 - -The rx_trigger= and tx_trigger= options can be used to set the FIFO trigger -levels. They specify when the ESP card should send an interrupt. Larger -values will decrease the number of interrupts; however, a value too high may -result in data loss. Valid values are 1 through 1023, with 768 being the -default. For example, to set the receive trigger level to 512 bytes and the -transmit trigger level to 700 bytes, the insmod command would be: - -insmod esp rx_trigger=512 tx_trigger=700 - -The flow_off= and flow_on= options can be used to set the hardware flow off/ -flow on levels. The flow on level must be lower than the flow off level, and -the flow off level should be higher than rx_trigger. Valid values are 1 -through 1023, with 1016 being the default flow off level and 944 being the -default flow on level. For example, to set the flow off level to 1000 bytes -and the flow on level to 935 bytes, the insmod command would be: - -insmod esp flow_off=1000 flow_on=935 - -The rx_timeout= option can be used to set the receive timeout value. This -value indicates how long after receiving the last character that the ESP card -should wait before signalling an interrupt. Valid values are 0 though 255, -with 128 being the default. A value too high will increase latency, and a -value too low will cause unnecessary interrupts. For example, to set the -receive timeout to 255, the insmod command would be: - -insmod esp rx_timeout=255 - -The pio_threshold= option sets the threshold (in number of characters) for -using PIO mode instead of DMA mode. For example, if this value is 32, -transfers of 32 bytes or less will always use PIO mode. - -insmod esp pio_threshold=32 - -Multiple options can be listed on the insmod command line by separating each -option with a space. For example: - -insmod esp dma=3 trigger=512 - -The esp module can be automatically loaded when needed. To cause this to -happen, add the following lines to /etc/modprobe.conf (replacing the last line -with options for your configuration): - -alias char-major-57 esp -alias char-major-58 esp -options esp irq=0,0,0,0,0,0,3,0 divisor=0,0,0,0,0,0,0x4,0 - -You may also need to run 'depmod -a'. - -Devices must be created manually. To create the devices, note the output from -the module after it is inserted. The output will appear in the location where -kernel messages usually appear (usually /var/adm/messages). Create two devices -for each 'tty' mentioned, one with major of 57 and the other with major of 58. -The minor number should be the same as the tty number reported. The commands -would be (replace ? with the tty number): - -mknod /dev/ttyP? c 57 ? -mknod /dev/cup? c 58 ? - -For example, if the following line appears: - -Oct 24 18:17:23 techno kernel: ttyP8 at 0x0140 (irq = 3) is an ESP primary port - -...two devices should be created: - -mknod /dev/ttyP8 c 57 8 -mknod /dev/cup8 c 58 8 - -You may need to set the permissions on the devices: - -chmod 666 /dev/ttyP* -chmod 666 /dev/cup* - -The ESP module and the serial module should not conflict (they can be used at -the same time). After the ESP module has been loaded the ports on the ESP card -will no longer be accessible by the serial driver. - -If I/O errors are experienced when accessing the port, check for IRQ and DMA -conflicts ('cat /proc/interrupts' and 'cat /proc/dma' for a list of IRQs and -DMAs currently in use). - -Enjoy! -Andrew J. Robinson diff --git a/Documentation/serial/tty.txt b/Documentation/serial/tty.txt index 8e65c4498c521259d93061e0a94a2d3652eaef98..5e5349a4fcd281b2450415d7d668456aedd34b4b 100644 --- a/Documentation/serial/tty.txt +++ b/Documentation/serial/tty.txt @@ -42,7 +42,8 @@ TTY side interfaces: open() - Called when the line discipline is attached to the terminal. No other call into the line discipline for this tty will occur until it - completes successfully. Can sleep. + completes successfully. Returning an error will + prevent the ldisc from being attached. Can sleep. close() - This is called on a terminal when the line discipline is being unplugged. At the point of @@ -52,7 +53,7 @@ close() - This is called on a terminal when the line hangup() - Called when the tty line is hung up. The line discipline should cease I/O to the tty. No further calls into the ldisc code will occur. - Can sleep. + The return value is ignored. Can sleep. write() - A process is writing data through the line discipline. Multiple write calls are serialized @@ -83,6 +84,10 @@ ioctl() - Called when an ioctl is handed to the tty layer that might be for the ldisc. Multiple ioctl calls may occur in parallel. May sleep. +compat_ioctl() - Called when a 32 bit ioctl is handed to the tty layer + that might be for the ldisc. Multiple ioctl calls + may occur in parallel. May sleep. + Driver Side Interfaces: receive_buf() - Hand buffers of bytes from the driver to the ldisc diff --git a/Documentation/spinlocks.txt b/Documentation/spinlocks.txt index 619699dde5938b64c6d63e1059cf0ed702c128af..178c831b907d08c8096b72c307508d0b272fccbe 100644 --- a/Documentation/spinlocks.txt +++ b/Documentation/spinlocks.txt @@ -1,73 +1,8 @@ -SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED defeat lockdep state tracking and -are hence deprecated. +Lesson 1: Spin locks -Please use DEFINE_SPINLOCK()/DEFINE_RWLOCK() or -__SPIN_LOCK_UNLOCKED()/__RW_LOCK_UNLOCKED() as appropriate for static -initialization. - -Most of the time, you can simply turn: - - static spinlock_t xxx_lock = SPIN_LOCK_UNLOCKED; - -into: - - static DEFINE_SPINLOCK(xxx_lock); - -Static structure member variables go from: - - struct foo bar { - .lock = SPIN_LOCK_UNLOCKED; - }; - -to: - - struct foo bar { - .lock = __SPIN_LOCK_UNLOCKED(bar.lock); - }; - -Declaration of static rw_locks undergo a similar transformation. - -Dynamic initialization, when necessary, may be performed as -demonstrated below. - - spinlock_t xxx_lock; - rwlock_t xxx_rw_lock; - - static int __init xxx_init(void) - { - spin_lock_init(&xxx_lock); - rwlock_init(&xxx_rw_lock); - ... - } - - module_init(xxx_init); - -The following discussion is still valid, however, with the dynamic -initialization of spinlocks or with DEFINE_SPINLOCK, etc., used -instead of SPIN_LOCK_UNLOCKED. - ------------------------ - -On Fri, 2 Jan 1998, Doug Ledford wrote: -> -> I'm working on making the aic7xxx driver more SMP friendly (as well as -> importing the latest FreeBSD sequencer code to have 7895 support) and wanted -> to get some info from you. The goal here is to make the various routines -> SMP safe as well as UP safe during interrupts and other manipulating -> routines. So far, I've added a spin_lock variable to things like my queue -> structs. Now, from what I recall, there are some spin lock functions I can -> use to lock these spin locks from other use as opposed to a (nasty) -> save_flags(); cli(); stuff; restore_flags(); construct. Where do I find -> these routines and go about making use of them? Do they only lock on a -> per-processor basis or can they also lock say an interrupt routine from -> mucking with a queue if the queue routine was manipulating it when the -> interrupt occurred, or should I still use a cli(); based construct on that -> one? - -See . The basic version is: - - spinlock_t xxx_lock = SPIN_LOCK_UNLOCKED; +The most basic primitive for locking is spinlock. +static DEFINE_SPINLOCK(xxx_lock); unsigned long flags; @@ -75,13 +10,11 @@ See . The basic version is: ... critical section here .. spin_unlock_irqrestore(&xxx_lock, flags); -and the above is always safe. It will disable interrupts _locally_, but the +The above is always safe. It will disable interrupts _locally_, but the spinlock itself will guarantee the global lock, so it will guarantee that there is only one thread-of-control within the region(s) protected by that -lock. - -Note that it works well even under UP - the above sequence under UP -essentially is just the same as doing a +lock. This works well even under UP. The above sequence under UP +essentially is just the same as doing unsigned long flags; @@ -91,15 +24,13 @@ essentially is just the same as doing a so the code does _not_ need to worry about UP vs SMP issues: the spinlocks work correctly under both (and spinlocks are actually more efficient on -architectures that allow doing the "save_flags + cli" in one go because I -don't export that interface normally). +architectures that allow doing the "save_flags + cli" in one operation). + + NOTE! Implications of spin_locks for memory are further described in: -NOTE NOTE NOTE! The reason the spinlock is so much faster than a global -interrupt lock under SMP is exactly because it disables interrupts only on -the local CPU. The spin-lock is safe only when you _also_ use the lock -itself to do locking across CPU's, which implies that EVERYTHING that -touches a shared variable has to agree about the spinlock they want to -use. + Documentation/memory-barriers.txt + (5) LOCK operations. + (6) UNLOCK operations. The above is usually pretty simple (you usually need and want only one spinlock for most things - using more than one spinlock can make things a @@ -120,20 +51,24 @@ and another sequence that does then they are NOT mutually exclusive, and the critical regions can happen at the same time on two different CPU's. That's fine per se, but the critical regions had better be critical for different things (ie they -can't stomp on each other). +can't stomp on each other). The above is a problem mainly if you end up mixing code - for example the routines in ll_rw_block() tend to use cli/sti to protect the atomicity of their actions, and if a driver uses spinlocks instead then you should -think about issues like the above.. +think about issues like the above. This is really the only really hard part about spinlocks: once you start using spinlocks they tend to expand to areas you might not have noticed before, because you have to make sure the spinlocks correctly protect the shared data structures _everywhere_ they are used. The spinlocks are most -easily added to places that are completely independent of other code (ie -internal driver data structures that nobody else ever touches, for -example). +easily added to places that are completely independent of other code (for +example, internal driver data structures that nobody else ever touches). + + NOTE! The spin-lock is safe only when you _also_ use the lock itself + to do locking across CPU's, which implies that EVERYTHING that + touches a shared variable has to agree about the spinlock they want + to use. ---- @@ -141,13 +76,17 @@ Lesson 2: reader-writer spinlocks. If your data accesses have a very natural pattern where you usually tend to mostly read from the shared variables, the reader-writer locks -(rw_lock) versions of the spinlocks are often nicer. They allow multiple +(rw_lock) versions of the spinlocks are sometimes useful. They allow multiple readers to be in the same critical region at once, but if somebody wants -to change the variables it has to get an exclusive write lock. The -routines look the same as above: +to change the variables it has to get an exclusive write lock. - rwlock_t xxx_lock = RW_LOCK_UNLOCKED; + NOTE! reader-writer locks require more atomic memory operations than + simple spinlocks. Unless the reader critical section is long, you + are better off just using spinlocks. +The routines look the same as above: + + rwlock_t xxx_lock = RW_LOCK_UNLOCKED; unsigned long flags; @@ -159,18 +98,21 @@ routines look the same as above: .. read and write exclusive access to the info ... write_unlock_irqrestore(&xxx_lock, flags); -The above kind of lock is useful for complex data structures like linked -lists etc, especially when you know that most of the work is to just -traverse the list searching for entries without changing the list itself, -for example. Then you can use the read lock for that kind of list -traversal, which allows many concurrent readers. Anything that _changes_ -the list will have to get the write lock. +The above kind of lock may be useful for complex data structures like +linked lists, especially searching for entries without changing the list +itself. The read lock allows many concurrent readers. Anything that +_changes_ the list will have to get the write lock. + + NOTE! RCU is better for list traversal, but requires careful + attention to design detail (see Documentation/RCU/listRCU.txt). -Note: you cannot "upgrade" a read-lock to a write-lock, so if you at _any_ +Also, you cannot "upgrade" a read-lock to a write-lock, so if you at _any_ time need to do any changes (even if you don't do it every time), you have -to get the write-lock at the very beginning. I could fairly easily add a -primitive to create a "upgradeable" read-lock, but it hasn't been an issue -yet. Tell me if you'd want one. +to get the write-lock at the very beginning. + + NOTE! We are working hard to remove reader-writer spinlocks in most + cases, so please don't add a new one without consensus. (Instead, see + Documentation/RCU/rcu.txt for complete information.) ---- @@ -233,4 +175,46 @@ indeed), while write-locks need to protect themselves against interrupts. Linus +---- + +Reference information: + +For dynamic initialization, use spin_lock_init() or rwlock_init() as +appropriate: + + spinlock_t xxx_lock; + rwlock_t xxx_rw_lock; + + static int __init xxx_init(void) + { + spin_lock_init(&xxx_lock); + rwlock_init(&xxx_rw_lock); + ... + } + + module_init(xxx_init); + +For static initialization, use DEFINE_SPINLOCK() / DEFINE_RWLOCK() or +__SPIN_LOCK_UNLOCKED() / __RW_LOCK_UNLOCKED() as appropriate. + +SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED are deprecated. These interfere +with lockdep state tracking. + +Most of the time, you can simply turn: + static spinlock_t xxx_lock = SPIN_LOCK_UNLOCKED; +into: + static DEFINE_SPINLOCK(xxx_lock); + +Static structure member variables go from: + + struct foo bar { + .lock = SPIN_LOCK_UNLOCKED; + }; + +to: + struct foo bar { + .lock = __SPIN_LOCK_UNLOCKED(bar.lock); + }; + +Declaration of static rw_locks undergo a similar transformation. diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 8f7a0e73ef44a2d48c6d0ae6755fde7d5479535e..3894eaa23486f951ace787893740ac2850f7d6d9 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -19,6 +19,8 @@ Currently, these files might (depending on your configuration) show up in /proc/sys/kernel: - acpi_video_flags - acct +- bootloader_type [ X86 only ] +- bootloader_version [ X86 only ] - callhome [ S390 only ] - auto_msgmni - core_pattern @@ -93,6 +95,35 @@ valid for 30 seconds. ============================================================== +bootloader_type: + +x86 bootloader identification + +This gives the bootloader type number as indicated by the bootloader, +shifted left by 4, and OR'd with the low four bits of the bootloader +version. The reason for this encoding is that this used to match the +type_of_loader field in the kernel header; the encoding is kept for +backwards compatibility. That is, if the full bootloader type number +is 0x15 and the full version number is 0x234, this file will contain +the value 340 = 0x154. + +See the type_of_loader and ext_loader_type fields in +Documentation/x86/boot.txt for additional information. + +============================================================== + +bootloader_version: + +x86 bootloader version + +The complete bootloader version number. In the example above, this +file will contain the value 564 = 0x234. + +See the type_of_loader and ext_loader_ver fields in +Documentation/x86/boot.txt for additional information. + +============================================================== + callhome: Controls the kernel's callhome behavior in case of a kernel panic. diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt index ad642615ad4cf370d5ded0e3c80f7bb6aa89a9a9..c7c1dc2f80179755f29cb2f86c8a5792029084f7 100644 --- a/Documentation/usb/power-management.txt +++ b/Documentation/usb/power-management.txt @@ -2,7 +2,7 @@ Alan Stern - October 5, 2007 + November 10, 2009 @@ -123,9 +123,9 @@ relevant attribute files are: wakeup, level, and autosuspend. power/level - This file contains one of three words: "on", "auto", - or "suspend". You can write those words to the file - to change the device's setting. + This file contains one of two words: "on" or "auto". + You can write those words to the file to change the + device's setting. "on" means that the device should be resumed and autosuspend is not allowed. (Of course, system @@ -134,10 +134,10 @@ relevant attribute files are: wakeup, level, and autosuspend. "auto" is the normal state in which the kernel is allowed to autosuspend and autoresume the device. - "suspend" means that the device should remain - suspended, and autoresume is not allowed. (But remote - wakeup may still be allowed, since it is controlled - separately by the power/wakeup attribute.) + (In kernels up to 2.6.32, you could also specify + "suspend", meaning that the device should remain + suspended and autoresume was not allowed. This + setting is no longer supported.) power/autosuspend @@ -313,13 +313,14 @@ three of the methods listed above. In addition, a driver indicates that it supports autosuspend by setting the .supports_autosuspend flag in its usb_driver structure. It is then responsible for informing the USB core whenever one of its interfaces becomes busy or idle. The -driver does so by calling these five functions: +driver does so by calling these six functions: int usb_autopm_get_interface(struct usb_interface *intf); void usb_autopm_put_interface(struct usb_interface *intf); - int usb_autopm_set_interface(struct usb_interface *intf); int usb_autopm_get_interface_async(struct usb_interface *intf); void usb_autopm_put_interface_async(struct usb_interface *intf); + void usb_autopm_get_interface_no_resume(struct usb_interface *intf); + void usb_autopm_put_interface_no_suspend(struct usb_interface *intf); The functions work by maintaining a counter in the usb_interface structure. When intf->pm_usage_count is > 0 then the interface is @@ -331,11 +332,13 @@ considered to be idle, and the kernel may autosuspend the device. associated with the device itself rather than any of its interfaces. This field is used only by the USB core.) -The driver owns intf->pm_usage_count; it can modify the value however -and whenever it likes. A nice aspect of the non-async usb_autopm_* -routines is that the changes they make are protected by the usb_device -structure's PM mutex (udev->pm_mutex); however drivers may change -pm_usage_count without holding the mutex. Drivers using the async +Drivers must not modify intf->pm_usage_count directly; its value +should be changed only be using the functions listed above. Drivers +are responsible for insuring that the overall change to pm_usage_count +during their lifetime balances out to 0 (it may be necessary for the +disconnect method to call usb_autopm_put_interface() one or more times +to fulfill this requirement). The first two routines use the PM mutex +in struct usb_device for mutual exclusion; drivers using the async routines are responsible for their own synchronization and mutual exclusion. @@ -347,11 +350,6 @@ exclusion. attempts an autosuspend if the new value is <= 0 and the device isn't suspended. - usb_autopm_set_interface() leaves pm_usage_count alone. - It attempts an autoresume if the value is > 0 and the device - is suspended, and it attempts an autosuspend if the value is - <= 0 and the device isn't suspended. - usb_autopm_get_interface_async() and usb_autopm_put_interface_async() do almost the same things as their non-async counterparts. The differences are: they do @@ -360,13 +358,11 @@ exclusion. such as an URB's completion handler, but when they return the device will not generally not yet be in the desired state. -There also are a couple of utility routines drivers can use: - - usb_autopm_enable() sets pm_usage_cnt to 0 and then calls - usb_autopm_set_interface(), which will attempt an autosuspend. - - usb_autopm_disable() sets pm_usage_cnt to 1 and then calls - usb_autopm_set_interface(), which will attempt an autoresume. + usb_autopm_get_interface_no_resume() and + usb_autopm_put_interface_no_suspend() merely increment or + decrement the pm_usage_count value; they do not attempt to + carry out an autoresume or an autosuspend. Hence they can be + called in an atomic context. The conventional usage pattern is that a driver calls usb_autopm_get_interface() in its open routine and @@ -400,11 +396,11 @@ though, setting this flag won't cause the kernel to autoresume it. Normally a driver would set this flag in its probe method, at which time the device is guaranteed not to be autosuspended.) -The usb_autopm_* routines have to run in a sleepable process context; -they must not be called from an interrupt handler or while holding a -spinlock. In fact, the entire autosuspend mechanism is not well geared -toward interrupt-driven operation. However there is one thing a -driver can do in an interrupt handler: +The synchronous usb_autopm_* routines have to run in a sleepable +process context; they must not be called from an interrupt handler or +while holding a spinlock. In fact, the entire autosuspend mechanism +is not well geared toward interrupt-driven operation. However there +is one thing a driver can do in an interrupt handler: usb_mark_last_busy(struct usb_device *udev); @@ -423,15 +419,16 @@ an URB had completed too recently. External suspend calls should never be allowed to fail in this way, only autosuspend calls. The driver can tell them apart by checking -udev->auto_pm; this flag will be set to 1 for internal PM events -(autosuspend or autoresume) and 0 for external PM events. +the PM_EVENT_AUTO bit in the message.event argument to the suspend +method; this bit will be set for internal PM events (autosuspend) and +clear for external PM events. Many of the ingredients in the autosuspend framework are oriented towards interfaces: The usb_interface structure contains the pm_usage_cnt field, and the usb_autopm_* routines take an interface pointer as their argument. But somewhat confusingly, a few of the -pieces (usb_mark_last_busy() and udev->auto_pm) use the usb_device -structure instead. Drivers need to keep this straight; they can call +pieces (i.e., usb_mark_last_busy()) use the usb_device structure +instead. Drivers need to keep this straight; they can call interface_to_usbdev() to find the device structure for a given interface. diff --git a/MAINTAINERS b/MAINTAINERS index 746b706206da70d40f62a6998f387cdfdf182a2f..1f21c34124db44d77fabe9ed7f9b8b1decfb299b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -801,6 +801,19 @@ L: openmoko-kernel@lists.openmoko.org (subscribers-only) W: http://wiki.openmoko.org/wiki/Neo_FreeRunner S: Supported +ARM/QUALCOMM MSM MACHINE SUPPORT +M: David Brown +M: Daniel Walker +M: Bryan Huntsman +F: arch/arm/mach-msm/ +F: drivers/video/msm/ +F: drivers/mmc/host/msm_sdcc.c +F: drivers/mmc/host/msm_sdcc.h +F: drivers/serial/msm_serial.h +F: drivers/serial/msm_serial.c +T: git git://codeaurora.org/quic/kernel/dwalker/linux-msm.git +S: Maintained + ARM/TOSA MACHINE SUPPORT M: Dmitry Eremin-Solenikov M: Dirk Opfer @@ -3247,6 +3260,7 @@ LINUX FOR IBM pSERIES (RS/6000) M: Paul Mackerras W: http://www.ibm.com/linux/ltc/projects/ppc S: Supported +F: arch/powerpc/boot/rs6000.h LINUX FOR POWERPC (32-BIT AND 64-BIT) M: Benjamin Herrenschmidt @@ -3255,18 +3269,24 @@ W: http://www.penguinppc.org/ L: linuxppc-dev@ozlabs.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git S: Supported +F: Documentation/powerpc/ +F: arch/powerpc/ LINUX FOR POWER MACINTOSH M: Benjamin Herrenschmidt W: http://www.penguinppc.org/ L: linuxppc-dev@ozlabs.org S: Maintained +F: arch/powerpc/platforms/powermac/ +F: drivers/macintosh/ LINUX FOR POWERPC EMBEDDED MPC5XXX M: Grant Likely L: linuxppc-dev@ozlabs.org T: git git://git.secretlab.ca/git/linux-2.6.git S: Maintained +F: arch/powerpc/platforms/512x/ +F: arch/powerpc/platforms/52xx/ LINUX FOR POWERPC EMBEDDED PPC4XX M: Josh Boyer @@ -3275,6 +3295,8 @@ W: http://www.penguinppc.org/ L: linuxppc-dev@ozlabs.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git S: Maintained +F: arch/powerpc/platforms/40x/ +F: arch/powerpc/platforms/44x/ LINUX FOR POWERPC EMBEDDED XILINX VIRTEX M: Grant Likely @@ -3282,6 +3304,8 @@ W: http://wiki.secretlab.ca/index.php/Linux_on_Xilinx_Virtex L: linuxppc-dev@ozlabs.org T: git git://git.secretlab.ca/git/linux-2.6.git S: Maintained +F: arch/powerpc/*/*virtex* +F: arch/powerpc/*/*/*virtex* LINUX FOR POWERPC EMBEDDED PPC8XX M: Vitaly Bordug @@ -3295,12 +3319,16 @@ M: Kumar Gala W: http://www.penguinppc.org/ L: linuxppc-dev@ozlabs.org S: Maintained +F: arch/powerpc/platforms/83xx/ LINUX FOR POWERPC PA SEMI PWRFICIENT M: Olof Johansson W: http://www.pasemi.com/ L: linuxppc-dev@ozlabs.org S: Supported +F: arch/powerpc/platforms/pasemi/ +F: drivers/*/*pasemi* +F: drivers/*/*/*pasemi* LINUX SECURITY MODULE (LSM) FRAMEWORK M: Chris Wright @@ -3903,6 +3931,23 @@ L: linux-omap@vger.kernel.org S: Maintained F: drivers/video/omap/ +OMAP DISPLAY SUBSYSTEM SUPPORT (DSS2) +M: Tomi Valkeinen +L: linux-omap@vger.kernel.org +L: linux-fbdev@vger.kernel.org (moderated for non-subscribers) +S: Maintained +F: drivers/video/omap2/dss/ +F: drivers/video/omap2/vrfb.c +F: drivers/video/omap2/vram.c +F: Documentation/arm/OMAP/DSS + +OMAP FRAMEBUFFER SUPPORT (FOR DSS2) +M: Tomi Valkeinen +L: linux-omap@vger.kernel.org +L: linux-fbdev@vger.kernel.org (moderated for non-subscribers) +S: Maintained +F: drivers/video/omap2/omapfb/ + OMAP MMC SUPPORT M: Jarkko Lavinen L: linux-omap@vger.kernel.org @@ -5035,6 +5080,7 @@ F: drivers/char/specialix* SPI SUBSYSTEM M: David Brownell +M: Grant Likely L: spi-devel-general@lists.sourceforge.net S: Maintained F: Documentation/spi/ @@ -5335,7 +5381,7 @@ S: Maintained F: drivers/scsi/u14-34f.c UBI FILE SYSTEM (UBIFS) -M: Artem Bityutskiy +M: Artem Bityutskiy M: Adrian Hunter L: linux-mtd@lists.infradead.org T: git git://git.infradead.org/ubifs-2.6.git @@ -5386,7 +5432,7 @@ F: drivers/cdrom/cdrom.c F: include/linux/cdrom.h UNSORTED BLOCK IMAGES (UBI) -M: Artem Bityutskiy +M: Artem Bityutskiy W: http://www.linux-mtd.infradead.org/ L: linux-mtd@lists.infradead.org T: git git://git.infradead.org/ubi-2.6.git @@ -5409,10 +5455,9 @@ S: Supported F: drivers/block/ub.c USB CDC ETHERNET DRIVER -M: Greg Kroah-Hartman +M: Oliver Neukum L: linux-usb@vger.kernel.org S: Maintained -W: http://www.kroah.com/linux-usb/ F: drivers/net/usb/cdc_*.c F: include/linux/usb/cdc.h @@ -5663,9 +5708,11 @@ S: Maintained F: drivers/net/wireless/rndis_wlan.c USB XHCI DRIVER -M: Sarah Sharp +M: Sarah Sharp L: linux-usb@vger.kernel.org S: Supported +F: drivers/usb/host/xhci* +F: drivers/usb/host/pci-quirks* USB ZC0301 DRIVER M: Luca Risolia diff --git a/arch/alpha/include/asm/fcntl.h b/arch/alpha/include/asm/fcntl.h index 25da0017ec87fb2dd675257d7d16a68cc5f89aff..21b1117a0c61344af1acc94c36dc2f6e475d67a0 100644 --- a/arch/alpha/include/asm/fcntl.h +++ b/arch/alpha/include/asm/fcntl.h @@ -1,8 +1,6 @@ #ifndef _ALPHA_FCNTL_H #define _ALPHA_FCNTL_H -/* open/fcntl - O_SYNC is only implemented on blocks devices and on files - located on an ext2 file system */ #define O_CREAT 01000 /* not fcntl */ #define O_TRUNC 02000 /* not fcntl */ #define O_EXCL 04000 /* not fcntl */ @@ -10,13 +8,28 @@ #define O_NONBLOCK 00004 #define O_APPEND 00010 -#define O_SYNC 040000 +#define O_DSYNC 040000 /* used to be O_SYNC, see below */ #define O_DIRECTORY 0100000 /* must be a directory */ #define O_NOFOLLOW 0200000 /* don't follow links */ #define O_LARGEFILE 0400000 /* will be set by the kernel on every open */ #define O_DIRECT 02000000 /* direct disk access - should check with OSF/1 */ #define O_NOATIME 04000000 #define O_CLOEXEC 010000000 /* set close_on_exec */ +/* + * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using + * the O_SYNC flag. We continue to use the existing numerical value + * for O_DSYNC semantics now, but using the correct symbolic name for it. + * This new value is used to request true Posix O_SYNC semantics. It is + * defined in this strange way to make sure applications compiled against + * new headers get at least O_DSYNC semantics on older kernels. + * + * This has the nice side-effect that we can simply test for O_DSYNC + * wherever we do not care if O_DSYNC or O_SYNC is used. + * + * Note: __O_SYNC must never be used directly. + */ +#define __O_SYNC 020000000 +#define O_SYNC (__O_SYNC|O_DSYNC) #define F_GETLK 7 #define F_SETLK 8 diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 9a3334ae282e38345d177e060acc2021fdeda084..62619f25132f93018d3a7850dda6c91aee5d0eb2 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -178,25 +178,18 @@ SYSCALL_DEFINE6(osf_mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, off) { - struct file *file = NULL; - unsigned long ret = -EBADF; + unsigned long ret = -EINVAL; #if 0 if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED)) printk("%s: unimplemented OSF mmap flags %04lx\n", current->comm, flags); #endif - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); - ret = do_mmap(file, addr, len, prot, flags, off); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); + if ((off + PAGE_ALIGN(len)) < off) + goto out; + if (off & ~PAGE_MASK) + goto out; + ret = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); out: return ret; } diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index cf8a99f19dc4dde348094e6817ade53391b7f4ab..233a222752c0c507a3879109b3c81d0793d3bf76 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -603,6 +603,7 @@ config ARCH_SA1100 select ARCH_SPARSEMEM_ENABLE select ARCH_MTD_XIP select ARCH_HAS_CPUFREQ + select CPU_FREQ select GENERIC_GPIO select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -1359,13 +1360,9 @@ source "drivers/cpufreq/Kconfig" config CPU_FREQ_SA1100 bool - depends on CPU_FREQ && (SA1100_H3100 || SA1100_H3600 || SA1100_LART || SA1100_PLEB || SA1100_BADGE4 || SA1100_HACKKIT) - default y config CPU_FREQ_SA1110 bool - depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3) - default y config CPU_FREQ_INTEGRATOR tristate "CPUfreq driver for ARM Integrator CPUs" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index ff54c23d085e51844332615a98bd12259d1b7015..5cb9326df7a7ad2e75fe10205c3786c40432cfa9 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -71,6 +71,14 @@ config DEBUG_LL in the kernel. This is helpful if you are debugging code that executes before the console is initialized. +config EARLY_PRINTK + bool "Early printk" + depends on DEBUG_LL + help + Say Y here if you want to have an early console using the + kernel low-level debugging functions. Add earlyprintk to your + kernel parameters to enable this console. + config DEBUG_ICEDCC bool "Kernel low-level debugging via EmbeddedICE DCC channel" depends on DEBUG_LL diff --git a/arch/arm/configs/htcherald_defconfig b/arch/arm/configs/htcherald_defconfig index 33826767407544566b9d01c279e4dc6acdd72820..1b39691b816f1962f744f2279f2d575766f9f541 100644 --- a/arch/arm/configs/htcherald_defconfig +++ b/arch/arm/configs/htcherald_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.32-rc6 -# Sat Nov 14 10:56:01 2009 +# Linux kernel version: 2.6.32-rc8 +# Sat Dec 5 12:16:24 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -198,7 +198,9 @@ CONFIG_ARCH_OMAP1=y # OMAP Feature Selections # # CONFIG_OMAP_RESET_CLOCKS is not set -# CONFIG_OMAP_MUX is not set +CONFIG_OMAP_MUX=y +# CONFIG_OMAP_MUX_DEBUG is not set +CONFIG_OMAP_MUX_WARNINGS=y CONFIG_OMAP_MCBSP=y # CONFIG_OMAP_MBOX_FWK is not set CONFIG_OMAP_MPU_TIMER=y @@ -207,6 +209,7 @@ CONFIG_OMAP_LL_DEBUG_UART1=y # CONFIG_OMAP_LL_DEBUG_UART2 is not set # CONFIG_OMAP_LL_DEBUG_UART3 is not set # CONFIG_OMAP_LL_DEBUG_NONE is not set +CONFIG_OMAP_SERIAL_WAKE=y # CONFIG_OMAP_PM_NONE is not set CONFIG_OMAP_PM_NOOP=y diff --git a/arch/arm/configs/omap3_touchbook_defconfig b/arch/arm/configs/omap3_touchbook_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..7c8515e65c0266c3049999c399d03932f453567a --- /dev/null +++ b/arch/arm/configs/omap3_touchbook_defconfig @@ -0,0 +1,2431 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.32-rc8 +# Fri Dec 4 16:02:17 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_OPROFILE_ARMV7=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL 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 is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y +CONFIG_OPROFILE=y +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_SLOW_WORK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +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" +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +# 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_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5PC1XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_DAVINCI is not set +CONFIG_ARCH_OMAP=y +# CONFIG_ARCH_BCMRING is not set + +# +# TI OMAP Implementations +# +CONFIG_ARCH_OMAP_OTG=y +# CONFIG_ARCH_OMAP1 is not set +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP3=y +# CONFIG_ARCH_OMAP4 is not set + +# +# OMAP Feature Selections +# +# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set +# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set +CONFIG_OMAP_RESET_CLOCKS=y +# CONFIG_OMAP_MUX is not set +CONFIG_OMAP_MCBSP=y +# CONFIG_OMAP_MBOX_FWK is not set +# CONFIG_OMAP_MPU_TIMER is not set +CONFIG_OMAP_32K_TIMER=y +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +# CONFIG_OMAP_LL_DEBUG_UART1 is not set +# CONFIG_OMAP_LL_DEBUG_UART2 is not set +CONFIG_OMAP_LL_DEBUG_UART3=y +# CONFIG_OMAP_LL_DEBUG_NONE is not set +# CONFIG_OMAP_PM_NONE is not set +CONFIG_OMAP_PM_NOOP=y +CONFIG_ARCH_OMAP34XX=y +CONFIG_ARCH_OMAP3430=y + +# +# OMAP Board Type +# +# CONFIG_MACH_OMAP3_BEAGLE is not set +# CONFIG_MACH_OMAP_LDP is not set +# CONFIG_MACH_OVERO is not set +# CONFIG_MACH_OMAP3EVM is not set +# CONFIG_MACH_OMAP3517EVM is not set +# CONFIG_MACH_OMAP3_PANDORA is not set +CONFIG_MACH_OMAP3_TOUCHBOOK=y +# CONFIG_MACH_OMAP_3430SDP is not set +# CONFIG_MACH_NOKIA_RX51 is not set +# CONFIG_MACH_OMAP_ZOOM2 is not set +# CONFIG_MACH_OMAP_ZOOM3 is not set +# CONFIG_MACH_CM_T35 is not set +# CONFIG_MACH_IGEP0020 is not set +# CONFIG_MACH_OMAP_3630SDP is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +CONFIG_ARM_THUMBEE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_HAS_TLS_REG=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +CONFIG_COMMON_CLKDEV=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_HZ=128 +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM 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_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_LEDS=y +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE=" debug " +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y + +# +# CPU Power Management +# +# CONFIG_CPU_FREQ is not set +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_HAVE_AOUT=y +CONFIG_BINFMT_AOUT=m +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_PM_VERBOSE is not set +CONFIG_CAN_PM_TRACE=y +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_SUSPEND_FREEZER=y +# CONFIG_APM_EMULATION is not set +# CONFIG_PM_RUNTIME is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE 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=m +CONFIG_NET_IPGRE=m +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +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_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +# CONFIG_DEFAULT_BIC is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_VEGAS is not set +# CONFIG_DEFAULT_WESTWOOD is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +# CONFIG_IPV6_PIMSM_V2 is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CT_ACCT=y +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +# CONFIG_NETFILTER_TPROXY is not set +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +CONFIG_NETFILTER_XT_TARGET_HL=m +# CONFIG_NETFILTER_XT_TARGET_LED is not set +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=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_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +CONFIG_IP_VS_DEBUG=y +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_AH_ESP=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 + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_NF_NAT_SIP=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +# CONFIG_BRIDGE_NF_EBTABLES is not set +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP_CCID2_DEBUG is not set +CONFIG_IP_DCCP_CCID3=y +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +CONFIG_IP_DCCP_CCID3_RTO=100 +CONFIG_IP_DCCP_TFRC_LIB=y + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set +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 +# CONFIG_RDS is not set +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# 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_STP=m +CONFIG_GARP=m +CONFIG_BRIDGE=m +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +# 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_ECONET is not set +CONFIG_WAN_ROUTER=m +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# 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_MULTIQ=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_DRR=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +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=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_CLS_IND=y +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_DROP_MONITOR is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=y +CONFIG_BT_L2CAP=y +CONFIG_BT_SCO=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIBTUSB=y +CONFIG_BT_HCIBTSDIO=y +CONFIG_BT_HCIUART=y +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIBCM203X=y +CONFIG_BT_HCIBPA10X=y +CONFIG_BT_HCIBFUSB=y +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_MRVL is not set +CONFIG_AF_RXRPC=m +# CONFIG_AF_RXRPC_DEBUG is not set +# CONFIG_RXKAD is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_CFG80211=m +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_DEFAULT_PS=y +CONFIG_CFG80211_DEFAULT_PS_VALUE=1 +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_WIRELESS_OLD_REGULATORY is not set +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_LIB80211=y +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_RC_PID=y +# CONFIG_MAC80211_RC_MINSTREL is not set +CONFIG_MAC80211_RC_DEFAULT_PID=y +# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set +CONFIG_MAC80211_RC_DEFAULT="pid" +# CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_LEDS is not set +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_WIMAX=m +CONFIG_WIMAX_DEBUG_LEVEL=8 +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS is not set +CONFIG_MTD_CONCAT=y +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 +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=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 +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS 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 +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SST25L 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 +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_OMAP2=y +CONFIG_MTD_NAND_OMAP_PREFETCH=y +# CONFIG_MTD_NAND_OMAP_PREFETCH_DMA is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_PLATFORM=y +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_GLUEBI is not set + +# +# UBI debugging options +# +# CONFIG_MTD_UBI_DEBUG is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +# 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=16384 +# CONFIG_BLK_DEV_XIP is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_ISL29003 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +CONFIG_EEPROM_93CX6=y +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +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=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=m +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +CONFIG_SCSI_ISCSI_ATTRS=m +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +CONFIG_ISCSI_TCP=m +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +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_RAID456=m +CONFIG_MD_RAID6_PQ=m +# CONFIG_ASYNC_RAID6_TEST is not set +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +# CONFIG_DM_DEBUG is not set +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +# CONFIG_DM_LOG_USERSPACE is not set +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +# CONFIG_DM_MULTIPATH_QL is not set +# CONFIG_DM_MULTIPATH_ST is not set +CONFIG_DM_DELAY=m +# CONFIG_DM_UEVENT is not set +CONFIG_NETDEVICES=y +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_MACVLAN=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_VETH=m +# CONFIG_NET_ETHERNET is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +CONFIG_WLAN=y +# CONFIG_WLAN_PRE80211 is not set +CONFIG_WLAN_80211=y +# CONFIG_LIBERTAS is not set +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_AT76C50X_USB is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8187 is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_P54_COMMON is not set +# CONFIG_ATH_COMMON is not set +# CONFIG_HOSTAP is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_ZD1211RW is not set +# CONFIG_RT2X00 is not set +# CONFIG_WL12XX is not set +# CONFIG_IWM is not set + +# +# WiMAX Wireless Broadband devices +# +# CONFIG_WIMAX_I2400M_USB is not set +# CONFIG_WIMAX_I2400M_SDIO 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_WAN is not set +# CONFIG_ATM_DRIVERS is not set +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 is not set +CONFIG_PPPOL2TP=m +# CONFIG_SLIP is not set +CONFIG_SLHC=m +CONFIG_NETCONSOLE=m +CONFIG_NETCONSOLE_DYNAMIC=y +CONFIG_NETPOLL=y +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_FF_MEMLESS=y +# CONFIG_INPUT_POLLDEV is not set + +# +# 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_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_TWL4030 is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=y +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879_I2C is not set +# CONFIG_TOUCHSCREEN_AD7879_SPI is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_W90X900 is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +CONFIG_INPUT_TWL4030_PWRBUTTON=y +CONFIG_INPUT_UINPUT=y +# CONFIG_INPUT_GPIO_ROTARY_ENCODER 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_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=32 +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=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_OMAP=y +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_TSL2550 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 +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +CONFIG_SPI_OMAP24XX=y + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +CONFIG_GPIO_TWL4030=y + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set + +# +# AC97 GPIO expanders: +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_BATTERY_DS2760 is not set +# CONFIG_BATTERY_DS2782 is not set +CONFIG_BATTERY_BQ27x00=y +# CONFIG_BATTERY_MAX17040 is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A 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_LM70 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_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_LIS3_SPI is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_OMAP_WATCHDOG=y +# CONFIG_TWL4030_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS65010 is not set +CONFIG_TWL4030_CORE=y +# CONFIG_TWL4030_POWER is not set +# CONFIG_TWL4030_CODEC is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13783 is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_EZX_PCAP is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_REGULATOR_MAX1586 is not set +CONFIG_REGULATOR_TWL4030=y +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_OMAP is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y + +# +# Display device support +# +CONFIG_DISPLAY_SUPPORT=y + +# +# Display hardware drivers +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_SOUND=y +CONFIG_SOUND_OSS_CORE=y +CONFIG_SOUND_OSS_CORE_PRECLAIM=y +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=y +CONFIG_SND_RAWMIDI=y +CONFIG_SND_JACK=y +CONFIG_SND_SEQUENCER=m +# CONFIG_SND_SEQ_DUMMY is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=m +CONFIG_SND_SEQ_HRTIMER_DEFAULT=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 +CONFIG_SND_RAWMIDI_SEQ=m +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +# CONFIG_SND_ARM is not set +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_SOC=y +CONFIG_SND_OMAP_SOC=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_ZEROPLUS is not set +CONFIG_USB_SUPPORT=y +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 +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_OXU210HP_HCD=y +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_SOC=y + +# +# OMAP 343x high speed USB support +# +# CONFIG_USB_MUSB_HOST is not set +# CONFIG_USB_MUSB_PERIPHERAL is not set +CONFIG_USB_MUSB_OTG=y +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_USB_MUSB_HDRC_HCD=y +# CONFIG_MUSB_PIO_ONLY is not set +CONFIG_USB_INVENTRA_DMA=y +# CONFIG_USB_TI_CPPI_DMA is not set +# CONFIG_USB_MUSB_DEBUG is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_WDM=m +CONFIG_USB_TMC=m + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +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_ISD200 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_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=m +CONFIG_USB_EZUSB=y +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +# CONFIG_USB_SERIAL_CP210X is not set +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=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=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +CONFIG_USB_SERIAL_KEYSPAN_USA28=y +CONFIG_USB_SERIAL_KEYSPAN_USA28X=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +CONFIG_USB_SERIAL_KEYSPAN_USA19=y +CONFIG_USB_SERIAL_KEYSPAN_USA18X=y +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MOTOROLA=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +# CONFIG_USB_SERIAL_QUALCOMM is not set +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +# CONFIG_USB_SERIAL_SAFE_PADDED is not set +CONFIG_USB_SERIAL_SIEMENS_MPI=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +# CONFIG_USB_SERIAL_SYMBOL is not set +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_DEBUG=m + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +CONFIG_USB_TEST=m +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +# CONFIG_USB_ATM is not set +CONFIG_USB_GADGET=m +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_R8A66597 is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C_HSOTG is not set +# CONFIG_USB_GADGET_IMX is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_CI13XXX is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LANGWELL is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_ZERO=m +CONFIG_USB_ZERO_HNPTEST=y +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_ETH_EEM is not set +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m +CONFIG_USB_MIDI_GADGET=m +CONFIG_USB_G_PRINTER=m +CONFIG_USB_CDC_COMPOSITE=m + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +CONFIG_USB_GPIO_VBUS=y +# CONFIG_ISP1301_OMAP is not set +CONFIG_TWL4030_USB=y +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_UNSAFE_RESUME=y + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_SDIO_UART=y +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_OMAP is not set +CONFIG_MMC_OMAP_HS=y +# CONFIG_MMC_AT91 is not set +# CONFIG_MMC_ATMELMCI is not set +CONFIG_MMC_SPI=m +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_GPIO_PLATFORM=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_BD2802 is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=m +# CONFIG_LEDS_TRIGGER_GPIO is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +CONFIG_RTC_DRV_TWL4030=y +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +CONFIG_UIO=m +CONFIG_UIO_PDRV=m +CONFIG_UIO_PDRV_GENIRQ=m +# CONFIG_UIO_SMX is not set +# CONFIG_UIO_SERCOS3 is not set + +# +# TI VLYNQ +# +CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set +# CONFIG_USB_IP_COMMON is not set +# CONFIG_W35UND is not set +# CONFIG_PRISM2_USB is not set +# CONFIG_ECHO is not set +# CONFIG_OTUS is not set +# CONFIG_COMEDI is not set +# CONFIG_ASUS_OLED is not set +# CONFIG_INPUT_MIMIO is not set +# CONFIG_TRANZPORT is not set + +# +# Android +# + +# +# Qualcomm MSM Camera And Video +# + +# +# Camera Sensor Selection +# +# CONFIG_INPUT_GPIO is not set +# CONFIG_DST is not set +# CONFIG_POHMELFS is not set +# CONFIG_PLAN9AUTH is not set +# CONFIG_LINE6_USB is not set +# CONFIG_USB_SERIAL_QUATECH2 is not set +# CONFIG_USB_SERIAL_QUATECH_USB2 is not set +# CONFIG_VT6656 is not set +# CONFIG_FB_UDL is not set + +# +# RAR Register Driver +# +# CONFIG_RAR_REGISTER is not set +# CONFIG_IIO 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_DEFAULTS_TO_ORDERED is not set +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_EXT4_FS=m +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=m +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=m +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +# CONFIG_REISERFS_FS_POSIX_ACL is not set +# CONFIG_REISERFS_FS_SECURITY is not set +CONFIG_JFS_FS=m +# CONFIG_JFS_POSIX_ACL is not set +# CONFIG_JFS_SECURITY is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_DEBUG is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_PRINT_QUOTA_WARNING=y +CONFIG_QUOTA_TREE=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# 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=y + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=m +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_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_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_FS_POSIX_ACL=y +CONFIG_JFFS2_FS_SECURITY=y +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_LZO=y +CONFIG_JFFS2_RTIME=y +CONFIG_JFFS2_RUBIN=y +# CONFIG_JFFS2_CMODE_NONE is not set +# CONFIG_JFFS2_CMODE_PRIORITY is not set +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_JFFS2_CMODE_FAVOURLZO=y +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_DEBUG is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +CONFIG_ROOT_NFS=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=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 is not set +CONFIG_CIFS=m +CONFIG_CIFS_STATS=y +CONFIG_CIFS_STATS2=y +# CONFIG_CIFS_WEAK_PW_HASH is not set +# CONFIG_CIFS_UPCALL is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_DFS_UPCALL is not set +CONFIG_CIFS_EXPERIMENTAL=y +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_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=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=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +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=y +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_PAGE_POISONING is not set +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_RING_BUFFER=y +CONFIG_EVENT_TRACING=y +CONFIG_CONTEXT_SWITCH_TRACER=y +CONFIG_RING_BUFFER_ALLOW_SWAP=y +CONFIG_TRACING=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +# CONFIG_BOOT_TRACER is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_XOR_BLOCKS=m +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_ASYNC_PQ=m +CONFIG_ASYNC_RAID6_RECOV=m +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_FIPS=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_GF128MUL=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_SEQIV=m + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=m +CONFIG_CRYPTO_CTS=m +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_XTS=m + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=m +CONFIG_CRYPTO_XCBC=m +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_GHASH=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=y +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SALSA20=m +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_HW=y +CONFIG_BINARY_PRINTF=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +CONFIG_CRC7=y +CONFIG_LIBCRC32C=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/arm/configs/omap_3430sdp_defconfig b/arch/arm/configs/omap_3430sdp_defconfig index 84829587d55aa29d6ed595b770179dcb76a14f1a..592457cfbbe577139968b9bfd85b1d9afc3a480a 100644 --- a/arch/arm/configs/omap_3430sdp_defconfig +++ b/arch/arm/configs/omap_3430sdp_defconfig @@ -963,10 +963,32 @@ CONFIG_FB_CFB_IMAGEBLIT=y # # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set -CONFIG_FB_OMAP=y -# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_OMAP_LCD_VGA is not set # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set -CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2 +CONFIG_OMAP2_VRAM=y +CONFIG_OMAP2_VRFB=y +CONFIG_OMAP2_DSS=y +CONFIG_OMAP2_VRAM_SIZE=4 +CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y +# CONFIG_OMAP2_DSS_RFBI is not set +CONFIG_OMAP2_DSS_VENC=y +# CONFIG_OMAP2_DSS_SDI is not set +# CONFIG_OMAP2_DSS_DSI is not set +# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 +CONFIG_FB_OMAP2=y +CONFIG_FB_OMAP2_DEBUG_SUPPORT=y +# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set +CONFIG_FB_OMAP2_NUM_FBS=3 + +# +# OMAP2/3 Display Device Drivers +# +CONFIG_PANEL_GENERIC=y +CONFIG_PANEL_SHARP_LS037V7DW01=y # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # diff --git a/arch/arm/configs/omap_4430sdp_defconfig b/arch/arm/configs/omap_4430sdp_defconfig index a464ca332a23b8e74ab88fd3de94dc0170e16558..2319113c86bfc2c7ac3fb2eb4a8306095f0c348d 100644 --- a/arch/arm/configs/omap_4430sdp_defconfig +++ b/arch/arm/configs/omap_4430sdp_defconfig @@ -1,26 +1,29 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.30-rc7 -# Tue Jun 9 12:36:23 2009 +# Linux kernel version: 2.6.32 +# Sun Dec 6 23:37:45 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_MMU=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y CONFIG_GENERIC_HARDIRQS=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y CONFIG_TRACE_IRQFLAGS_SUPPORT=y CONFIG_HARDIRQS_SW_RESEND=y CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_LOCKBREAK=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPUFREQ=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y # # General setup @@ -39,11 +42,12 @@ CONFIG_BSD_PROCESS_ACCT=y # # RCU Subsystem # -CONFIG_CLASSIC_RCU=y -# CONFIG_TREE_RCU is not set -# CONFIG_PREEMPT_RCU is not set +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set # CONFIG_TREE_RCU_TRACE is not set -# CONFIG_PREEMPT_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_GROUP_SCHED=y @@ -52,8 +56,7 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -# CONFIG_SYSFS_DEPRECATED=y is not set -# CONFIG_SYSFS_DEPRECATED_V2=y is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y @@ -70,7 +73,6 @@ CONFIG_UID16=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set -# CONFIG_STRIP_ASM_SYMS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y @@ -83,6 +85,10 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_AIO=y + +# +# Kernel Performance Events And Counters +# CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLUB_DEBUG=y CONFIG_COMPAT_BRK=y @@ -90,13 +96,16 @@ CONFIG_COMPAT_BRK=y CONFIG_SLUB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# # CONFIG_SLOW_WORK is not set CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y @@ -110,7 +119,7 @@ CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_STOP_MACHINE=y CONFIG_BLOCK=y -# CONFIG_LBD is not set +CONFIG_LBDAF=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -131,6 +140,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # # System Type # +CONFIG_MMU=y # CONFIG_ARCH_AAEC2000 is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_REALVIEW is not set @@ -142,8 +152,10 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set # CONFIG_ARCH_NETX is not set # CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_NOMADIK is not set # CONFIG_ARCH_IOP13XX is not set # CONFIG_ARCH_IOP32X is not set # CONFIG_ARCH_IOP33X is not set @@ -166,10 +178,13 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set # CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5PC1XX is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set # CONFIG_ARCH_DAVINCI is not set CONFIG_ARCH_OMAP=y +# CONFIG_ARCH_BCMRING is not set # # TI OMAP Implementations @@ -190,9 +205,12 @@ CONFIG_ARCH_OMAP4=y CONFIG_OMAP_32K_TIMER=y CONFIG_OMAP_32K_TIMER_HZ=128 CONFIG_OMAP_DM_TIMER=y -CONFIG_OMAP_LL_DEBUG_UART1=y +# CONFIG_OMAP_LL_DEBUG_UART1 is not set # CONFIG_OMAP_LL_DEBUG_UART2 is not set -# CONFIG_OMAP_LL_DEBUG_UART3 is not set +CONFIG_OMAP_LL_DEBUG_UART3=y +# CONFIG_OMAP_LL_DEBUG_NONE is not set +# CONFIG_OMAP_PM_NONE is not set +CONFIG_OMAP_PM_NOOP=y # # OMAP Board Type @@ -207,7 +225,7 @@ CONFIG_CPU_32v6K=y CONFIG_CPU_V7=y CONFIG_CPU_32v7=y CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_PABRT_IFAR=y +CONFIG_CPU_PABRT_V7=y CONFIG_CPU_CACHE_V7=y CONFIG_CPU_CACHE_VIPT=y CONFIG_CPU_COPY_V6=y @@ -222,9 +240,10 @@ CONFIG_CPU_CP15_MMU=y # CONFIG_ARM_THUMB is not set # CONFIG_ARM_THUMBEE is not set # CONFIG_CPU_ICACHE_DISABLE is not set -CONFIG_CPU_DCACHE_DISABLE=y +# CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_BPREDICT_DISABLE is not set CONFIG_HAS_TLS_REG=y +CONFIG_ARM_L1_CACHE_SHIFT=5 # CONFIG_ARM_ERRATA_430973 is not set # CONFIG_ARM_ERRATA_458693 is not set # CONFIG_ARM_ERRATA_460075 is not set @@ -245,18 +264,20 @@ CONFIG_ARM_GIC=y CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_SMP=y CONFIG_HAVE_ARM_SCU=y -CONFIG_HAVE_ARM_TWD=y CONFIG_VMSPLIT_3G=y # CONFIG_VMSPLIT_2G is not set # CONFIG_VMSPLIT_1G is not set CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_NR_CPUS=2 # CONFIG_HOTPLUG_CPU is not set -CONFIG_LOCAL_TIMERS=y -# CONFIG_PREEMPT is not set +# CONFIG_LOCAL_TIMERS is not set +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y CONFIG_HZ=128 +# CONFIG_THUMB2_KERNEL is not set CONFIG_AEABI=y -# CONFIG_OABI_COMPAT is not set +CONFIG_OABI_COMPAT=y # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set # CONFIG_HIGHMEM is not set @@ -271,10 +292,13 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y -# CONFIG_UNEVICTABLE_LRU is not set CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 # CONFIG_LEDS is not set CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set # # Boot options @@ -298,9 +322,11 @@ CONFIG_CMDLINE="root=/dev/ram0 rw mem=128M console=ttyS0,115200n8 initrd=0x81600 # # At least one emulation must be selected # +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set CONFIG_VFP=y CONFIG_VFPv3=y -# CONFIG_NEON is not set +CONFIG_NEON=y # # Userspace binary formats @@ -325,6 +351,7 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y # Generic Driver Options # CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set @@ -342,6 +369,7 @@ CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_BLK_DEV_XIP is not set # CONFIG_CDROM_PKTCDVD is not set +# CONFIG_MG_DISK is not set # CONFIG_MISC_DEVICES is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -355,6 +383,7 @@ CONFIG_HAVE_IDE=y # CONFIG_SCSI_NETLINK is not set # CONFIG_ATA is not set # CONFIG_MD is not set +# CONFIG_PHONE is not set # # Input device support @@ -427,6 +456,11 @@ CONFIG_HW_RANDOM=y # CONFIG_TCG_TPM is not set # CONFIG_I2C is not set # CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y # CONFIG_DEBUG_GPIO is not set @@ -447,11 +481,14 @@ CONFIG_GPIOLIB=y # # SPI GPIO expanders: # + +# +# AC97 GPIO expanders: +# # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set -# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set CONFIG_SSB_POSSIBLE=y @@ -472,21 +509,8 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_T7L66XB is not set # CONFIG_MFD_TC6387XB is not set # CONFIG_MFD_TC6393XB is not set - -# -# Multimedia devices -# - -# -# Multimedia core support -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_VIDEO_MEDIA is not set - -# -# Multimedia drivers -# -CONFIG_DAB=y +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set # # Graphics support @@ -511,14 +535,17 @@ CONFIG_DUMMY_CONSOLE=y # CONFIG_USB_SUPPORT is not set # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set -# CONFIG_ACCESSIBILITY is not set # CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set CONFIG_RTC_LIB=y # CONFIG_RTC_CLASS is not set # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set -# CONFIG_REGULATOR is not set # CONFIG_UIO is not set + +# +# TI VLYNQ +# # CONFIG_STAGING is not set # @@ -535,9 +562,12 @@ CONFIG_JBD=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set -CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set # CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y @@ -601,7 +631,6 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set -# CONFIG_NILFS2_FS is not set # # Partition Types @@ -673,23 +702,24 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_ENABLE_MUST_CHECK is not set CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set # CONFIG_UNUSED_SYMBOLS is not set # CONFIG_DEBUG_FS is not set # CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set -CONFIG_DETECT_SOFTLOCKUP=y -# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set -CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +# CONFIG_DETECT_SOFTLOCKUP is not set CONFIG_DETECT_HUNG_TASK=y # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 -CONFIG_SCHED_DEBUG=y +# CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_PREEMPT is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -708,31 +738,22 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set CONFIG_FRAME_POINTER=y # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_PAGE_POISONING is not set CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_TRACING_SUPPORT=y - -# -# Tracers -# -# CONFIG_FUNCTION_TRACER is not set -# CONFIG_IRQSOFF_TRACER is not set -# CONFIG_SCHED_TRACER is not set -# CONFIG_CONTEXT_SWITCH_TRACER is not set -# CONFIG_EVENT_TRACER is not set -# CONFIG_BOOT_TRACER is not set -# CONFIG_TRACE_BRANCH_PROFILING is not set -# CONFIG_STACK_TRACER is not set -# CONFIG_KMEMTRACE is not set -# CONFIG_WORKQUEUE_TRACER is not set -# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_FTRACE is not set +# CONFIG_BRANCH_PROFILE_NONE is not set +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set @@ -754,7 +775,6 @@ CONFIG_CRYPTO=y # # Crypto core or helper # -# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_ALGAPI2=y CONFIG_CRYPTO_AEAD2=y @@ -796,11 +816,13 @@ CONFIG_CRYPTO_PCBC=m # # CONFIG_CRYPTO_HMAC is not set # CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set # # Digest # CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_GHASH is not set # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_MICHAEL_MIC is not set diff --git a/arch/arm/configs/omap_zoom2_defconfig b/arch/arm/configs/omap_zoom2_defconfig index eef93627fb13f7d2105556eabf0347882539c7a3..4b00a4306812117c66c7983c5512f5d9b425d7fc 100644 --- a/arch/arm/configs/omap_zoom2_defconfig +++ b/arch/arm/configs/omap_zoom2_defconfig @@ -610,7 +610,8 @@ CONFIG_INPUT_EVDEV=y # # Input Device Drivers # -# CONFIG_INPUT_KEYBOARD is not set +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_TWL4030=y # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set diff --git a/arch/arm/configs/omap_zoom3_defconfig b/arch/arm/configs/omap_zoom3_defconfig index f0e7d0f85582f1f7c27f98444ea8c276aaba6e09..0d7e37a3651bf01b7004af893a6b92fea3409124 100644 --- a/arch/arm/configs/omap_zoom3_defconfig +++ b/arch/arm/configs/omap_zoom3_defconfig @@ -629,7 +629,8 @@ CONFIG_INPUT_EVDEV=y # # Input Device Drivers # -# CONFIG_INPUT_KEYBOARD is not set +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_TWL4030=y # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set diff --git a/arch/arm/configs/zeus_defconfig b/arch/arm/configs/zeus_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..823b11e7091af4c21fc6d8b6b978b4616a1f459e --- /dev/null +++ b/arch/arm/configs/zeus_defconfig @@ -0,0 +1,2032 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.32 +# Tue Dec 8 20:27:05 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_MTD_XIP=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +# CONFIG_TREE_RCU is not set +# CONFIG_TREE_PREEMPT_RCU is not set +CONFIG_TINY_RCU=y +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=13 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=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_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +# 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_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_PNX4008 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5PC1XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_U8500 is not set + +# +# Intel PXA2xx/PXA3xx Implementations +# + +# +# Intel/Marvell Dev Platforms (sorted by hardware release time) +# +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_MACH_MAINSTONE is not set +# CONFIG_MACH_ZYLONITE300 is not set +# CONFIG_MACH_ZYLONITE320 is not set +# CONFIG_MACH_LITTLETON is not set +# CONFIG_MACH_TAVOREVB is not set +# CONFIG_MACH_SAAR is not set + +# +# Third Party Dev Platforms (sorted by vendor name) +# +# CONFIG_ARCH_PXA_IDP is not set +# CONFIG_ARCH_VIPER is not set +CONFIG_MACH_ARCOM_ZEUS=y +# CONFIG_MACH_BALLOON3 is not set +# CONFIG_MACH_CSB726 is not set +# CONFIG_MACH_ARMCORE is not set +# CONFIG_MACH_EM_X270 is not set +# CONFIG_MACH_EXEDA is not set +# CONFIG_MACH_CM_X300 is not set +# CONFIG_ARCH_GUMSTIX is not set +# CONFIG_MACH_INTELMOTE2 is not set +# CONFIG_MACH_STARGATE2 is not set +# CONFIG_MACH_XCEP is not set +# CONFIG_TRIZEPS_PXA is not set +CONFIG_ARCOM_PCMCIA=y +# CONFIG_MACH_LOGICPD_PXA270 is not set +# CONFIG_MACH_PCM027 is not set +# CONFIG_MACH_COLIBRI is not set +# CONFIG_MACH_COLIBRI300 is not set +# CONFIG_MACH_COLIBRI320 is not set + +# +# End-user Products (sorted by vendor name) +# +# CONFIG_MACH_H4700 is not set +# CONFIG_MACH_H5000 is not set +# CONFIG_MACH_HIMALAYA is not set +# CONFIG_MACH_MAGICIAN is not set +# CONFIG_MACH_MIOA701 is not set +# CONFIG_PXA_EZX is not set +# CONFIG_MACH_MP900C is not set +# CONFIG_ARCH_PXA_PALM is not set +# CONFIG_PXA_SHARPSL is not set +# CONFIG_ARCH_PXA_ESERIES is not set +CONFIG_PXA27x=y +CONFIG_PXA_SSP=y +CONFIG_PXA_HAVE_BOARD_IRQS=y +CONFIG_PXA_HAVE_ISA_IRQS=y +CONFIG_PLAT_PXA=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSCALE=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_PABRT_LEGACY=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_DCACHE_DISABLE is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_IWMMXT=y +CONFIG_XSCALE_PMU=y +CONFIG_COMMON_CLKDEV=y + +# +# Bus support +# +CONFIG_ISA=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCCARD=m +CONFIG_PCMCIA=m +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y + +# +# PC-card bridges +# +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +CONFIG_PCMCIA_SOC_COMMON=m +CONFIG_PCMCIA_PXA2XX=m +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA_PROBE=y + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM 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_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=31:02 rootfstype=jffs2 ro console=ttyS0,115200" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +# CONFIG_CPU_FREQ_DEBUG is not set +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +# CONFIG_CPU_IDLE 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_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_APM_EMULATION=y +# CONFIG_PM_RUNTIME is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS 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=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=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_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA 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_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=m +CONFIG_BT_L2CAP=m +# CONFIG_BT_SCO is not set +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +# CONFIG_BT_BNEP_MC_FILTER is not set +# CONFIG_BT_BNEP_PROTO_FILTER is not set +# CONFIG_BT_HIDP is not set + +# +# Bluetooth device drivers +# +# CONFIG_BT_HCIBTUSB is not set +# CONFIG_BT_HCIBTSDIO is not set +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +# CONFIG_BT_HCIUART_LL is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIDTL1 is not set +# CONFIG_BT_HCIBT3C is not set +# CONFIG_BT_HCIBLUECARD is not set +# CONFIG_BT_HCIBTUART is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_MRVL is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=m +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_WIRELESS_OLD_REGULATORY is not set +CONFIG_CFG80211_WEXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_LIB80211=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_RC_MINSTREL=y +# CONFIG_MAC80211_RC_DEFAULT_PID is not set +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel" +# CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_LEDS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS 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=y +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLKDEVS=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 +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS 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=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 is not set +# 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 is not set +# 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=y +# 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_XIP is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PXA2XX=y +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_GPIO_ADDR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SST25L 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 +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +# CONFIG_PNP is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_ISL29003 is not set +# CONFIG_DS1682 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=m +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_IWMC3200TOP is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +# 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 is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_ATA=m +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +# CONFIG_SATA_PMP is not set +CONFIG_ATA_SFF=y +# CONFIG_SATA_MV is not set +# CONFIG_PATA_LEGACY is not set +CONFIG_PATA_PCMCIA=m +# CONFIG_PATA_QDI is not set +# CONFIG_PATA_WINBOND_VLB is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_ARCNET is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_SMC91X is not set +CONFIG_DM9000=y +CONFIG_DM9000_DEBUGLEVEL=4 +# CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set +# CONFIG_ENC28J60 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_DNET 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_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_NET_PCI is not set +# CONFIG_B44 is not set +# CONFIG_CS89x0 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_TR is not set +CONFIG_WLAN=y +# CONFIG_PCMCIA_RAYCS is not set +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_ATMEL is not set +# CONFIG_AT76C50X_USB is not set +# CONFIG_AIRO_CS is not set +# CONFIG_PCMCIA_WL3501 is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8187 is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_ATH_COMMON is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_HOSTAP is not set +# CONFIG_IWM is not set +# CONFIG_LIBERTAS is not set +CONFIG_HERMES=m +CONFIG_HERMES_CACHE_FW_ON_INIT=y +CONFIG_PCMCIA_HERMES=m +# CONFIG_PCMCIA_SPECTRUM is not set +# CONFIG_P54_COMMON is not set +CONFIG_RT2X00=m +# CONFIG_RT2500USB is not set +CONFIG_RT73USB=m +# CONFIG_RT2800USB is not set +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_DEBUG is not set +# CONFIG_WL12XX is not set +# CONFIG_ZD1211RW is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# 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_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set +# 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 is not set +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +# CONFIG_PPP_MPPE is not set +# CONFIG_PPPOE is not set +# CONFIG_PPPOL2TP is not set +# CONFIG_SLIP is not set +CONFIG_SLHC=m +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# 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_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_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879_I2C is not set +# CONFIG_TOUCHSCREEN_AD7879_SPI is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_EETI is not set +CONFIG_TOUCHSCREEN_FUJITSU=m +# CONFIG_TOUCHSCREEN_GUNZE is not set +CONFIG_TOUCHSCREEN_ELO=m +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_INEXIO=m +# CONFIG_TOUCHSCREEN_MK712 is not set +CONFIG_TOUCHSCREEN_HTCPEN=m +CONFIG_TOUCHSCREEN_PENMOUNT=m +CONFIG_TOUCHSCREEN_TOUCHRIGHT=m +CONFIG_TOUCHSCREEN_TOUCHWIN=m +# CONFIG_TOUCHSCREEN_WM97XX is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +CONFIG_TOUCHSCREEN_TOUCHIT213=m +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_W90X900 is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +CONFIG_INPUT_UINPUT=m +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_CS is not set +CONFIG_SERIAL_8250_NR_UARTS=7 +CONFIG_SERIAL_8250_RUNTIME_UARTS=7 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_PXA is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=m +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_IPWIRELESS is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_HELPER_AUTO is not set + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE is not set +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PXA=y +# CONFIG_I2C_PXA_SLAVE is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_ELEKTOR is not set +# CONFIG_I2C_PCA_ISA is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_TSL2550 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 +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +CONFIG_SPI_PXA2XX=y + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +CONFIG_GPIO_PCA953X=y +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set + +# +# AC97 GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A 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_LM70 is not set +CONFIG_SENSORS_LM75=m +# 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_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_SA1100_WATCHDOG is not set + +# +# ISA-based Watchdog Cards +# +# CONFIG_PCWATCHDOG is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_WDT is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_UCB1400_CORE is not set +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13783 is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=m +CONFIG_FB_CFB_COPYAREA=m +CONFIG_FB_CFB_IMAGEBLIT=m +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_PXA=m +# CONFIG_FB_PXA_OVERLAY is not set +# CONFIG_FB_PXA_SMARTPANEL is not set +CONFIG_FB_PXA_PARAMETERS=y +# CONFIG_FB_MBX is not set +# CONFIG_FB_W100 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=m +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_PLATFORM is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_GENERIC=m + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT 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=m +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_SOUND=m +CONFIG_SOUND_OSS_CORE=y +CONFIG_SOUND_OSS_CORE_PRECLAIM=y +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +# 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 +CONFIG_SND_VMASTER=y +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_DRIVERS=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 +# CONFIG_SND_AC97_POWER_SAVE is not set +CONFIG_SND_ARM=y +CONFIG_SND_PXA2XX_PCM=m +CONFIG_SND_PXA2XX_LIB=m +CONFIG_SND_PXA2XX_LIB_AC97=y +CONFIG_SND_PXA2XX_AC97=m +# CONFIG_SND_SPI is not set +CONFIG_SND_USB=y +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_PCMCIA is not set +CONFIG_SND_SOC=m +CONFIG_SND_PXA2XX_SOC=m +CONFIG_SND_SOC_I2C_AND_SPI=m +# CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_AC97_BUS=m +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=m +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +# CONFIG_USB_OTG is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +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_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_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=m +# CONFIG_USB_EZUSB is not set +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP210X 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 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_IUU 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=m +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MOTOROLA is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_HP4X is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIEMENS_MPI is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_SYMBOL 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 +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +CONFIG_USB_GADGET=m +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_R8A66597 is not set +CONFIG_USB_GADGET_PXA27X=y +CONFIG_USB_PXA27X=m +# CONFIG_USB_GADGET_S3C_HSOTG is not set +# CONFIG_USB_GADGET_IMX is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_CI13XXX is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LANGWELL is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_ETH_EEM is not set +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_MIDI_GADGET is not set +CONFIG_USB_G_PRINTER=m +# CONFIG_USB_CDC_COMPOSITE is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +# CONFIG_MMC_BLOCK_BOUNCE is not set +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_PXA=y +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_AT91 is not set +# CONFIG_MMC_ATMELMCI is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=m + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=m +CONFIG_LEDS_GPIO_PLATFORM=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_BD2802 is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_BACKLIGHT=m +CONFIG_LEDS_TRIGGER_GPIO=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +CONFIG_RTC_DRV_ISL1208=m +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_SA1100 is not set +CONFIG_RTC_DRV_PXA=m +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# TI VLYNQ +# +# CONFIG_STAGING 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_DEFAULTS_TO_ORDERED is not set +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=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_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE 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 is not set +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_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# 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_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +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 + +# +# 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 +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=m +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=m +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +# CONFIG_BOOT_TRACER is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_OC_ETM is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_AEAD2=m +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=m +CONFIG_CRYPTO_HASH=m +CONFIG_CRYPTO_HASH2=m +CONFIG_CRYPTO_RNG2=m +CONFIG_CRYPTO_PCOMP=m +CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_MANAGER2=m +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_WORKQUEUE=m +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC_T10DIF=m +CONFIG_CRC_ITU_T=m +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/arm/include/asm/mman.h b/arch/arm/include/asm/mman.h index 8eebf89f5ab17884a98543f3b37a3b710355083b..41f99c573b93c918843ccbcd50ea2640bcb5e3ac 100644 --- a/arch/arm/include/asm/mman.h +++ b/arch/arm/include/asm/mman.h @@ -1 +1,4 @@ #include + +#define arch_mmap_check(addr, len, flags) \ + (((flags) & MAP_FIXED && (addr) < FIRST_USER_ADDRESS) ? -EINVAL : 0) diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index e7ccf7e697ce4c30bdb744f855fb2488284f7c59..dd00f747e2ad00aeb844dd6b8c8373dd34b2a853 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -54,5 +54,6 @@ endif head-y := head$(MMUEXT).o obj-$(CONFIG_DEBUG_LL) += debug.o +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o extra-y := $(head-y) init_task.o vmlinux.lds diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index f58c1156e779f4a7caf94ea238a757c26d64e795..9314a2d681f15a299e614842c37eb97f694dbd23 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -172,7 +172,7 @@ /* 160 */ CALL(sys_sched_get_priority_min) CALL(sys_sched_rr_get_interval) CALL(sys_nanosleep) - CALL(sys_arm_mremap) + CALL(sys_mremap) CALL(sys_setresuid16) /* 165 */ CALL(sys_getresuid16) CALL(sys_ni_syscall) /* vm86 */ diff --git a/arch/arm/kernel/early_printk.c b/arch/arm/kernel/early_printk.c new file mode 100644 index 0000000000000000000000000000000000000000..85aa2b292692b5296f86ca57851bab1e5c9cab05 --- /dev/null +++ b/arch/arm/kernel/early_printk.c @@ -0,0 +1,57 @@ +/* + * linux/arch/arm/kernel/early_printk.c + * + * Copyright (C) 2009 Sascha Hauer + * + * 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 + +extern void printch(int); + +static void early_write(const char *s, unsigned n) +{ + while (n-- > 0) { + if (*s == '\n') + printch('\r'); + printch(*s); + s++; + } +} + +static void early_console_write(struct console *con, const char *s, unsigned n) +{ + early_write(s, n); +} + +static struct console early_console = { + .name = "earlycon", + .write = early_console_write, + .flags = CON_PRINTBUFFER | CON_BOOT, + .index = -1, +}; + +asmlinkage void early_printk(const char *fmt, ...) +{ + char buf[512]; + int n; + va_list ap; + + va_start(ap, fmt); + n = vscnprintf(buf, sizeof(buf), fmt, ap); + early_write(buf, n); + va_end(ap); +} + +static int __init setup_early_printk(char *buf) +{ + register_console(&early_console); + return 0; +} + +early_param("earlyprintk", setup_early_printk); diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index f0fe95b7085d8020682b297915ba1910af476828..2c1db77d78487cbdfa95d660f3abfa8acf6e215b 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -416,12 +416,12 @@ sys_mmap2: tst r5, #PGOFF_MASK moveq r5, r5, lsr #PAGE_SHIFT - 12 streq r5, [sp, #4] - beq do_mmap2 + beq sys_mmap_pgoff mov r0, #-EINVAL mov pc, lr #else str r5, [sp, #4] - b do_mmap2 + b sys_mmap_pgoff #endif ENDPROC(sys_mmap2) diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index a73a34dccf2a6de247f20bb5fc4e9622b03561a1..ea02a7b1c244af0afd610f6fc00c7f836f72ae4d 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -160,6 +160,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) /* Make sure our local interrupt controller has this enabled */ local_irq_save(flags); + irq_to_desc(clk->irq)->status |= IRQ_NOPROBE; get_irq_chip(clk->irq)->unmask(clk->irq); local_irq_restore(flags); diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 78ecaac652069217b965eca0cd336b40858698b2..ae4027bd01bd3f921d54d558a640d0ef9bbe8c23 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -28,41 +28,6 @@ #include #include -extern unsigned long do_mremap(unsigned long addr, unsigned long old_len, - unsigned long new_len, unsigned long flags, - unsigned long new_addr); - -/* common code for old and new mmaps */ -inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EINVAL; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - if (flags & MAP_FIXED && addr < FIRST_USER_ADDRESS) - goto out; - - error = -EBADF; - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - struct mmap_arg_struct { unsigned long addr; unsigned long len; @@ -84,29 +49,11 @@ asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) if (a.offset & ~PAGE_MASK) goto out; - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); out: return error; } -asmlinkage unsigned long -sys_arm_mremap(unsigned long addr, unsigned long old_len, - unsigned long new_len, unsigned long flags, - unsigned long new_addr) -{ - unsigned long ret = -EINVAL; - - if (flags & MREMAP_FIXED && new_addr < FIRST_USER_ADDRESS) - goto out; - - down_write(¤t->mm->mmap_sem); - ret = do_mremap(addr, old_len, new_len, flags, new_addr); - up_write(¤t->mm->mmap_sem); - -out: - return ret; -} - /* * Perform the select(nd, in, out, ex, tv) and mmap() system * calls. diff --git a/arch/arm/mach-clps711x/include/mach/memory.h b/arch/arm/mach-clps711x/include/mach/memory.h index e522b20bcbc25efcd17f4976c0544ea43252b57d..f70d52be48a2a61c88b7276a830b7b3abf17aee5 100644 --- a/arch/arm/mach-clps711x/include/mach/memory.h +++ b/arch/arm/mach-clps711x/include/mach/memory.h @@ -30,6 +30,8 @@ #define __virt_to_bus(x) ((x) - PAGE_OFFSET) #define __bus_to_virt(x) ((x) + PAGE_OFFSET) +#define __pfn_to_bus(x) (__pfn_to_phys(x) - PHYS_OFFSET) +#define __bus_to_pfn(x) __phys_to_pfn((x) + PHYS_OFFSET) #endif diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c index b97f529e58e8455016f675d965f2cc568fda1b2e..41febc796b1c7e1564684eccc910516568fb54ad 100644 --- a/arch/arm/mach-footbridge/common.c +++ b/arch/arm/mach-footbridge/common.c @@ -201,6 +201,11 @@ void __init footbridge_map_io(void) #ifdef CONFIG_FOOTBRIDGE_ADDIN +static inline unsigned long fb_bus_sdram_offset(void) +{ + return *CSR_PCISDRAMBASE & 0xfffffff0; +} + /* * These two functions convert virtual addresses to PCI addresses and PCI * addresses to virtual addresses. Note that it is only legal to use these @@ -210,14 +215,13 @@ unsigned long __virt_to_bus(unsigned long res) { WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory); - return (res - PAGE_OFFSET) + (*CSR_PCISDRAMBASE & 0xfffffff0); + return res + (fb_bus_sdram_offset() - PAGE_OFFSET); } EXPORT_SYMBOL(__virt_to_bus); unsigned long __bus_to_virt(unsigned long res) { - res -= (*CSR_PCISDRAMBASE & 0xfffffff0); - res += PAGE_OFFSET; + res = res - (fb_bus_sdram_offset() - PAGE_OFFSET); WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory); @@ -225,4 +229,16 @@ unsigned long __bus_to_virt(unsigned long res) } EXPORT_SYMBOL(__bus_to_virt); +unsigned long __pfn_to_bus(unsigned long pfn) +{ + return __pfn_to_phys(pfn) + (fb_bus_sdram_offset() - PHYS_OFFSET)); +} +EXPORT_SYMBOL(__pfn_to_bus); + +unsigned long __bus_to_pfn(unsigned long bus) +{ + return __phys_to_pfn(bus - (fb_bus_sdram_offset() - PHYS_OFFSET)); +} +EXPORT_SYMBOL(__bus_to_pfn); + #endif diff --git a/arch/arm/mach-footbridge/include/mach/memory.h b/arch/arm/mach-footbridge/include/mach/memory.h index cb16e59d87b63c81f807b67c65b013fa7c11e763..8d64f45740873e419c62f8547031322c1894836a 100644 --- a/arch/arm/mach-footbridge/include/mach/memory.h +++ b/arch/arm/mach-footbridge/include/mach/memory.h @@ -29,6 +29,8 @@ #ifndef __ASSEMBLY__ extern unsigned long __virt_to_bus(unsigned long); extern unsigned long __bus_to_virt(unsigned long); +extern unsigned long __pfn_to_bus(unsigned long); +extern unsigned long __bus_to_pfn(unsigned long); #endif #define __virt_to_bus __virt_to_bus #define __bus_to_virt __bus_to_virt @@ -36,14 +38,15 @@ extern unsigned long __bus_to_virt(unsigned long); #elif defined(CONFIG_FOOTBRIDGE_HOST) /* - * The footbridge is programmed to expose the system RAM at the corresponding - * address. So, if PAGE_OFFSET is 0xc0000000, RAM appears at 0xe0000000. - * If 0x80000000, then its exposed at 0xa0000000 on the bus. etc. - * The only requirement is that the RAM isn't placed at bus address 0 which + * The footbridge is programmed to expose the system RAM at 0xe0000000. + * The requirement is that the RAM isn't placed at bus address 0, which * would clash with VGA cards. */ -#define __virt_to_bus(x) ((x) - 0xe0000000) -#define __bus_to_virt(x) ((x) + 0xe0000000) +#define BUS_OFFSET 0xe0000000 +#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) +#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) +#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - PHYS_OFFSET)) +#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PHYS_OFFSET)) #else diff --git a/arch/arm/mach-integrator/include/mach/memory.h b/arch/arm/mach-integrator/include/mach/memory.h index 4891828454f5fdca8c72f5146633e2e5a362c204..991f24d2c1150d0ee72b0341be967715ed0361bb 100644 --- a/arch/arm/mach-integrator/include/mach/memory.h +++ b/arch/arm/mach-integrator/include/mach/memory.h @@ -28,6 +28,7 @@ #define BUS_OFFSET UL(0x80000000) #define __virt_to_bus(x) ((x) - PAGE_OFFSET + BUS_OFFSET) #define __bus_to_virt(x) ((x) - BUS_OFFSET + PAGE_OFFSET) -#define __pfn_to_bus(x) (((x) << PAGE_SHIFT) + BUS_OFFSET) +#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - PHYS_OFFSET)) +#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PHYS_OFFSET)) #endif diff --git a/arch/arm/mach-ixp2000/include/mach/memory.h b/arch/arm/mach-ixp2000/include/mach/memory.h index aee7eb8a71b24eb7d8580534551866c5c068efaf..98e3471be15bc28081987de78700720ac9f04ed6 100644 --- a/arch/arm/mach-ixp2000/include/mach/memory.h +++ b/arch/arm/mach-ixp2000/include/mach/memory.h @@ -17,11 +17,15 @@ #include -#define __virt_to_bus(v) \ - (((__virt_to_phys(v) - 0x0) + (*IXP2000_PCI_SDRAM_BAR & 0xfffffff0))) +#define IXP2000_PCI_SDRAM_OFFSET (*IXP2000_PCI_SDRAM_BAR & 0xfffffff0) -#define __bus_to_virt(b) \ - __phys_to_virt((((b - (*IXP2000_PCI_SDRAM_BAR & 0xfffffff0)) + 0x0))) +#define __phys_to_bus(x) ((x) + (IXP2000_PCI_SDRAM_OFFSET - PHYS_OFFSET)) +#define __bus_to_phys(x) ((x) - (IXP2000_PCI_SDRAM_OFFSET - PHYS_OFFSET)) + +#define __virt_to_bus(v) __phys_to_bus(__virt_to_phys(v)) +#define __bus_to_virt(b) __phys_to_virt(__bus_to_phys(b)) +#define __pfn_to_bus(p) __phys_to_bus(__pfn_to_phys(p)) +#define __bus_to_pfn(b) __phys_to_pfn(__bus_to_phys(b)) #endif diff --git a/arch/arm/mach-ixp23xx/include/mach/memory.h b/arch/arm/mach-ixp23xx/include/mach/memory.h index fdd138706c704f7b0e72264f2a60248e94f0f0f6..94a3a86cfeb8be7ae854aa26162e33c7796683d0 100644 --- a/arch/arm/mach-ixp23xx/include/mach/memory.h +++ b/arch/arm/mach-ixp23xx/include/mach/memory.h @@ -19,16 +19,15 @@ */ #define PHYS_OFFSET (0x00000000) -#define __virt_to_bus(v) \ - ({ unsigned int ret; \ - ret = ((__virt_to_phys(v) - 0x00000000) + \ - (*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0)); \ - ret; }) - -#define __bus_to_virt(b) \ - ({ unsigned int data; \ - data = *((volatile int *)IXP23XX_PCI_SDRAM_BAR); \ - __phys_to_virt((((b - (data & 0xfffffff0)) + 0x00000000))); }) +#define IXP23XX_PCI_SDRAM_OFFSET (*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0)) + +#define __phys_to_bus(x) ((x) + (IXP23XX_PCI_SDRAM_OFFSET - PHYS_OFFSET)) +#define __bus_to_phys(x) ((x) - (IXP23XX_PCI_SDRAM_OFFSET - PHYS_OFFSET)) + +#define __virt_to_bus(v) __phys_to_bus(__virt_to_phys(v)) +#define __bus_to_virt(b) __phys_to_virt(__bus_to_phys(b)) +#define __pfn_to_bus(p) __phys_to_bus(__pfn_to_phys(p)) +#define __bus_to_pfn(b) __phys_to_pfn(__bus_to_phys(b)) #define arch_is_coherent() 1 diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig index 264f4d59f898158bdd0175ed9ccf17b1fb3392ef..9e5070da17ae8f2d6033eeb0c43adc7127a3b992 100644 --- a/arch/arm/mach-ixp4xx/Kconfig +++ b/arch/arm/mach-ixp4xx/Kconfig @@ -179,21 +179,21 @@ config IXP4XX_INDIRECT_PCI help IXP4xx provides two methods of accessing PCI memory space: - 1) A direct mapped window from 0x48000000 to 0x4bffffff (64MB). + 1) A direct mapped window from 0x48000000 to 0x4BFFFFFF (64MB). To access PCI via this space, we simply ioremap() the BAR into the kernel and we can use the standard read[bwl]/write[bwl] macros. This is the preferred method due to speed but it - limits the system to just 64MB of PCI memory. This can be + limits the system to just 64MB of PCI memory. This can be problematic if using video cards and other memory-heavy devices. - - 2) If > 64MB of memory space is required, the IXP4xx can be - configured to use indirect registers to access PCI This allows - for up to 128MB (0x48000000 to 0x4fffffff) of memory on the bus. - The disadvantage of this is that every PCI access requires - three local register accesses plus a spinlock, but in some - cases the performance hit is acceptable. In addition, you cannot - mmap() PCI devices in this case due to the indirect nature - of the PCI window. + + 2) If > 64MB of memory space is required, the IXP4xx can be + configured to use indirect registers to access the whole PCI + memory space. This currently allows for up to 1 GB (0x10000000 + to 0x4FFFFFFF) of memory on the bus. The disadvantage of this + is that every PCI access requires three local register accesses + plus a spinlock, but in some cases the performance hit is + acceptable. In addition, you cannot mmap() PCI devices in this + case due to the indirect nature of the PCI window. By default, the direct method is used. Choose this option if you need to use the indirect method instead. If you don't know diff --git a/arch/arm/mach-ixp4xx/avila-pci.c b/arch/arm/mach-ixp4xx/avila-pci.c index 08d65dcdb5fe237b686963d180128ca7fd32d180..845e1b5005484d0bfb79c6e8a0993951d3dc0341 100644 --- a/arch/arm/mach-ixp4xx/avila-pci.c +++ b/arch/arm/mach-ixp4xx/avila-pci.c @@ -22,40 +22,45 @@ #include #include #include - #include #include #include #include +#define AVILA_MAX_DEV 4 +#define LOFT_MAX_DEV 6 +#define IRQ_LINES 4 + +/* PCI controller GPIO to IRQ pin mappings */ +#define INTA 11 +#define INTB 10 +#define INTC 9 +#define INTD 8 + void __init avila_pci_preinit(void) { - set_irq_type(IRQ_AVILA_PCI_INTA, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_AVILA_PCI_INTB, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_AVILA_PCI_INTC, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_AVILA_PCI_INTD, IRQ_TYPE_LEVEL_LOW); - + set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW); ixp4xx_pci_preinit(); } static int __init avila_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - static int pci_irq_table[AVILA_PCI_IRQ_LINES] = { - IRQ_AVILA_PCI_INTA, - IRQ_AVILA_PCI_INTB, - IRQ_AVILA_PCI_INTC, - IRQ_AVILA_PCI_INTD + static int pci_irq_table[IRQ_LINES] = { + IXP4XX_GPIO_IRQ(INTA), + IXP4XX_GPIO_IRQ(INTB), + IXP4XX_GPIO_IRQ(INTC), + IXP4XX_GPIO_IRQ(INTD) }; - int irq = -1; - if (slot >= 1 && - slot <= (machine_is_loft() ? LOFT_PCI_MAX_DEV : AVILA_PCI_MAX_DEV) && - pin >= 1 && pin <= AVILA_PCI_IRQ_LINES) { - irq = pci_irq_table[(slot + pin - 2) % 4]; - } + slot <= (machine_is_loft() ? LOFT_MAX_DEV : AVILA_MAX_DEV) && + pin >= 1 && pin <= IRQ_LINES) + return pci_irq_table[(slot + pin - 2) % 4]; - return irq; + return -1; } struct hw_pci avila_pci __initdata = { @@ -75,4 +80,3 @@ int __init avila_pci_init(void) } subsys_initcall(avila_pci_init); - diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c index 797995ce18b9203155febaa89696392d9b981f61..6e558a76457d154a5aa38d0c816b720b062cdc82 100644 --- a/arch/arm/mach-ixp4xx/avila-setup.c +++ b/arch/arm/mach-ixp4xx/avila-setup.c @@ -19,7 +19,6 @@ #include #include #include - #include #include #include @@ -29,6 +28,9 @@ #include #include +#define AVILA_SDA_PIN 7 +#define AVILA_SCL_PIN 6 + static struct flash_platform_data avila_flash_data = { .map_name = "cfi_probe", .width = 2, diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index 70afcfe5b8810943012ee5ee394ccea404f63ce0..c4a01594c761bf380c7b0ac8e8469ce2d1aad6f2 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c @@ -481,11 +481,7 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys) res[1].name = "PCI Memory Space"; res[1].start = PCIBIOS_MIN_MEM; -#ifndef CONFIG_IXP4XX_INDIRECT_PCI - res[1].end = 0x4bffffff; -#else - res[1].end = 0x4fffffff; -#endif + res[1].end = PCIBIOS_MAX_MEM; res[1].flags = IORESOURCE_MEM; request_resource(&ioport_resource, &res[0]); diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index cfd52fb341cb0545558006cf806df799cbdc379f..3bbf40f6d964b277a7a153fa6a93e694c73ff9da 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -117,7 +117,7 @@ int gpio_to_irq(int gpio) } EXPORT_SYMBOL(gpio_to_irq); -int irq_to_gpio(int irq) +int irq_to_gpio(unsigned int irq) { int gpio = (irq < 32) ? irq2gpio[irq] : -EINVAL; diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c index efddf01ed17bf22774cc35de9377680a5a031600..b978ea8bd6f09ed723aa18d2d7b7f23ceef93363 100644 --- a/arch/arm/mach-ixp4xx/coyote-pci.c +++ b/arch/arm/mach-ixp4xx/coyote-pci.c @@ -18,27 +18,31 @@ #include #include #include - #include #include #include - #include +#define SLOT0_DEVID 14 +#define SLOT1_DEVID 15 + +/* PCI controller GPIO to IRQ pin mappings */ +#define SLOT0_INTA 6 +#define SLOT1_INTA 11 + void __init coyote_pci_preinit(void) { - set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_COYOTE_PCI_SLOT1, IRQ_TYPE_LEVEL_LOW); - + set_irq_type(IXP4XX_GPIO_IRQ(SLOT0_INTA), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(SLOT1_INTA), IRQ_TYPE_LEVEL_LOW); ixp4xx_pci_preinit(); } static int __init coyote_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - if (slot == COYOTE_PCI_SLOT0_DEVID) - return IRQ_COYOTE_PCI_SLOT0; - else if (slot == COYOTE_PCI_SLOT1_DEVID) - return IRQ_COYOTE_PCI_SLOT1; + if (slot == SLOT0_DEVID) + return IXP4XX_GPIO_IRQ(SLOT0_INTA); + else if (slot == SLOT1_DEVID) + return IXP4XX_GPIO_IRQ(SLOT1_INTA); else return -1; } diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c index aab1954e274715d3969101b4609f0d21129c4ed8..25bf5ad770eaa14c6213e27579bd0b912691bd69 100644 --- a/arch/arm/mach-ixp4xx/coyote-setup.c +++ b/arch/arm/mach-ixp4xx/coyote-setup.c @@ -25,6 +25,15 @@ #include #include +#define COYOTE_IDE_BASE_PHYS IXP4XX_EXP_BUS_BASE(3) +#define COYOTE_IDE_BASE_VIRT 0xFFFE1000 +#define COYOTE_IDE_REGION_SIZE 0x1000 + +#define COYOTE_IDE_DATA_PORT 0xFFFE10E0 +#define COYOTE_IDE_CTRL_PORT 0xFFFE10FC +#define COYOTE_IDE_ERROR_PORT 0xFFFE10E2 +#define IRQ_COYOTE_IDE IRQ_IXP4XX_GPIO5 + static struct flash_platform_data coyote_flash_data = { .map_name = "cfi_probe", .width = 2, diff --git a/arch/arm/mach-ixp4xx/dsmg600-pci.c b/arch/arm/mach-ixp4xx/dsmg600-pci.c index 926d15f885fb7a77dedf3727c9dc96d747e81f29..fa70fed462babf1a20dc2a0eba30313b726666b4 100644 --- a/arch/arm/mach-ixp4xx/dsmg600-pci.c +++ b/arch/arm/mach-ixp4xx/dsmg600-pci.c @@ -19,39 +19,45 @@ #include #include #include - #include #include +#define MAX_DEV 4 +#define IRQ_LINES 3 + +/* PCI controller GPIO to IRQ pin mappings */ +#define INTA 11 +#define INTB 10 +#define INTC 9 +#define INTD 8 +#define INTE 7 +#define INTF 6 + void __init dsmg600_pci_preinit(void) { - set_irq_type(IRQ_DSMG600_PCI_INTA, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_DSMG600_PCI_INTB, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_DSMG600_PCI_INTC, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_DSMG600_PCI_INTD, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_DSMG600_PCI_INTE, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_DSMG600_PCI_INTF, IRQ_TYPE_LEVEL_LOW); - + set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTE), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTF), IRQ_TYPE_LEVEL_LOW); ixp4xx_pci_preinit(); } static int __init dsmg600_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - static int pci_irq_table[DSMG600_PCI_MAX_DEV][DSMG600_PCI_IRQ_LINES] = - { - { IRQ_DSMG600_PCI_INTE, -1, -1 }, - { IRQ_DSMG600_PCI_INTA, -1, -1 }, - { IRQ_DSMG600_PCI_INTB, IRQ_DSMG600_PCI_INTC, IRQ_DSMG600_PCI_INTD }, - { IRQ_DSMG600_PCI_INTF, -1, -1 }, + static int pci_irq_table[MAX_DEV][IRQ_LINES] = { + { IXP4XX_GPIO_IRQ(INTE), -1, -1 }, + { IXP4XX_GPIO_IRQ(INTA), -1, -1 }, + { IXP4XX_GPIO_IRQ(INTB), IXP4XX_GPIO_IRQ(INTC), + IXP4XX_GPIO_IRQ(INTD) }, + { IXP4XX_GPIO_IRQ(INTF), -1, -1 }, }; - int irq = -1; - - if (slot >= 1 && slot <= DSMG600_PCI_MAX_DEV && - pin >= 1 && pin <= DSMG600_PCI_IRQ_LINES) - irq = pci_irq_table[slot-1][pin-1]; + if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES) + return pci_irq_table[slot - 1][pin - 1]; - return irq; + return -1; } struct hw_pci __initdata dsmg600_pci = { diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c index a51bfa6978b6a619190987d5ffb3e45a74fc5001..7c1fa54a6145a987a4d41a4910421231a62a2ea5 100644 --- a/arch/arm/mach-ixp4xx/dsmg600-setup.c +++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c @@ -33,6 +33,23 @@ #include #include +#define DSMG600_SDA_PIN 5 +#define DSMG600_SCL_PIN 4 + +/* DSM-G600 Timer Setting */ +#define DSMG600_FREQ 66000000 + +/* Buttons */ +#define DSMG600_PB_GPIO 15 /* power button */ +#define DSMG600_RB_GPIO 3 /* reset button */ + +/* Power control */ +#define DSMG600_PO_GPIO 2 /* power off */ + +/* LEDs */ +#define DSMG600_LED_PWR_GPIO 0 +#define DSMG600_LED_WLAN_GPIO 14 + static struct flash_platform_data dsmg600_flash_data = { .map_name = "cfi_probe", .width = 2, diff --git a/arch/arm/mach-ixp4xx/fsg-pci.c b/arch/arm/mach-ixp4xx/fsg-pci.c index ca12a9ca083045f479409d0a5172a88ab5eb529e..5a810c930624cb0768259fc19043d32f8cfbda46 100644 --- a/arch/arm/mach-ixp4xx/fsg-pci.c +++ b/arch/arm/mach-ixp4xx/fsg-pci.c @@ -19,33 +19,38 @@ #include #include #include - #include #include +#define MAX_DEV 3 +#define IRQ_LINES 3 + +/* PCI controller GPIO to IRQ pin mappings */ +#define INTA 6 +#define INTB 7 +#define INTC 5 + void __init fsg_pci_preinit(void) { - set_irq_type(IRQ_FSG_PCI_INTA, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_FSG_PCI_INTB, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_FSG_PCI_INTC, IRQ_TYPE_LEVEL_LOW); - + set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW); ixp4xx_pci_preinit(); } static int __init fsg_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - static int pci_irq_table[FSG_PCI_IRQ_LINES] = { - IRQ_FSG_PCI_INTC, - IRQ_FSG_PCI_INTB, - IRQ_FSG_PCI_INTA, + static int pci_irq_table[IRQ_LINES] = { + IXP4XX_GPIO_IRQ(INTC), + IXP4XX_GPIO_IRQ(INTB), + IXP4XX_GPIO_IRQ(INTA), }; int irq = -1; - slot = slot - 11; + slot -= 11; - if (slot >= 1 && slot <= FSG_PCI_MAX_DEV && - pin >= 1 && pin <= FSG_PCI_IRQ_LINES) - irq = pci_irq_table[(slot - 1)]; + if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES) + irq = pci_irq_table[slot - 1]; printk(KERN_INFO "%s: Mapped slot %d pin %d to IRQ %d\n", __func__, slot, pin, irq); diff --git a/arch/arm/mach-ixp4xx/fsg-setup.c b/arch/arm/mach-ixp4xx/fsg-setup.c index 5add22fc98999ac57b0da0f688926b4f65c0dcfc..e7f4befba4224b364c5d601ffe7359ef474fbc60 100644 --- a/arch/arm/mach-ixp4xx/fsg-setup.c +++ b/arch/arm/mach-ixp4xx/fsg-setup.c @@ -24,12 +24,18 @@ #include #include #include - #include #include #include #include +#define FSG_SDA_PIN 12 +#define FSG_SCL_PIN 13 + +#define FSG_SB_GPIO 4 /* sync button */ +#define FSG_RB_GPIO 9 /* reset button */ +#define FSG_UB_GPIO 10 /* usb button */ + static struct flash_platform_data fsg_flash_data = { .map_name = "cfi_probe", .width = 2, diff --git a/arch/arm/mach-ixp4xx/goramo_mlr.c b/arch/arm/mach-ixp4xx/goramo_mlr.c index a733b8ff3cec5844f9f9ed8306bd20691c2a09ad..1c28048209c14c233407902fd86364f153fbaf9c 100644 --- a/arch/arm/mach-ixp4xx/goramo_mlr.c +++ b/arch/arm/mach-ixp4xx/goramo_mlr.c @@ -17,29 +17,28 @@ #include #include -#define xgpio_irq(n) (IRQ_IXP4XX_GPIO ## n) -#define gpio_irq(n) xgpio_irq(n) - #define SLOT_ETHA 0x0B /* IDSEL = AD21 */ #define SLOT_ETHB 0x0C /* IDSEL = AD20 */ #define SLOT_MPCI 0x0D /* IDSEL = AD19 */ #define SLOT_NEC 0x0E /* IDSEL = AD18 */ -#define IRQ_ETHA IRQ_IXP4XX_GPIO4 -#define IRQ_ETHB IRQ_IXP4XX_GPIO5 -#define IRQ_NEC IRQ_IXP4XX_GPIO3 -#define IRQ_MPCI IRQ_IXP4XX_GPIO12 - /* GPIO lines */ #define GPIO_SCL 0 #define GPIO_SDA 1 #define GPIO_STR 2 +#define GPIO_IRQ_NEC 3 +#define GPIO_IRQ_ETHA 4 +#define GPIO_IRQ_ETHB 5 #define GPIO_HSS0_DCD_N 6 #define GPIO_HSS1_DCD_N 7 +#define GPIO_UART0_DCD 8 +#define GPIO_UART1_DCD 9 #define GPIO_HSS0_CTS_N 10 #define GPIO_HSS1_CTS_N 11 +#define GPIO_IRQ_MPCI 12 #define GPIO_HSS1_RTS_N 13 #define GPIO_HSS0_RTS_N 14 +/* GPIO15 is not connected */ /* Control outputs from 74HC4094 */ #define CONTROL_HSS0_CLK_INT 0 @@ -152,7 +151,7 @@ static int hss_set_clock(int port, unsigned int clock_type) static irqreturn_t hss_dcd_irq(int irq, void *pdev) { - int i, port = (irq == gpio_irq(GPIO_HSS1_DCD_N)); + int i, port = (irq == IXP4XX_GPIO_IRQ(GPIO_HSS1_DCD_N)); gpio_line_get(port ? GPIO_HSS1_DCD_N : GPIO_HSS0_DCD_N, &i); set_carrier_cb_tab[port](pdev, !i); return IRQ_HANDLED; @@ -165,9 +164,9 @@ static int hss_open(int port, void *pdev, int i, irq; if (!port) - irq = gpio_irq(GPIO_HSS0_DCD_N); + irq = IXP4XX_GPIO_IRQ(GPIO_HSS0_DCD_N); else - irq = gpio_irq(GPIO_HSS1_DCD_N); + irq = IXP4XX_GPIO_IRQ(GPIO_HSS1_DCD_N); gpio_line_get(port ? GPIO_HSS1_DCD_N : GPIO_HSS0_DCD_N, &i); set_carrier_cb(pdev, !i); @@ -188,8 +187,8 @@ static int hss_open(int port, void *pdev, static void hss_close(int port, void *pdev) { - free_irq(port ? gpio_irq(GPIO_HSS1_DCD_N) : gpio_irq(GPIO_HSS0_DCD_N), - pdev); + free_irq(port ? IXP4XX_GPIO_IRQ(GPIO_HSS1_DCD_N) : + IXP4XX_GPIO_IRQ(GPIO_HSS0_DCD_N), pdev); set_carrier_cb_tab[!!port] = NULL; /* catch bugs */ set_control(port ? CONTROL_HSS1_DTR_N : CONTROL_HSS0_DTR_N, 1); @@ -421,8 +420,8 @@ static void __init gmlr_init(void) gpio_line_config(GPIO_HSS1_RTS_N, IXP4XX_GPIO_OUT); gpio_line_config(GPIO_HSS0_DCD_N, IXP4XX_GPIO_IN); gpio_line_config(GPIO_HSS1_DCD_N, IXP4XX_GPIO_IN); - set_irq_type(gpio_irq(GPIO_HSS0_DCD_N), IRQ_TYPE_EDGE_BOTH); - set_irq_type(gpio_irq(GPIO_HSS1_DCD_N), IRQ_TYPE_EDGE_BOTH); + set_irq_type(IXP4XX_GPIO_IRQ(GPIO_HSS0_DCD_N), IRQ_TYPE_EDGE_BOTH); + set_irq_type(IXP4XX_GPIO_IRQ(GPIO_HSS1_DCD_N), IRQ_TYPE_EDGE_BOTH); set_control(CONTROL_HSS0_DTR_N, 1); set_control(CONTROL_HSS1_DTR_N, 1); @@ -442,10 +441,10 @@ static void __init gmlr_init(void) #ifdef CONFIG_PCI static void __init gmlr_pci_preinit(void) { - set_irq_type(IRQ_ETHA, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_ETHB, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_NEC, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_MPCI, IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHA), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHB), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_NEC), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_MPCI), IRQ_TYPE_LEVEL_LOW); ixp4xx_pci_preinit(); } @@ -466,10 +465,10 @@ static void __init gmlr_pci_postinit(void) static int __init gmlr_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { switch(slot) { - case SLOT_ETHA: return IRQ_ETHA; - case SLOT_ETHB: return IRQ_ETHB; - case SLOT_NEC: return IRQ_NEC; - default: return IRQ_MPCI; + case SLOT_ETHA: return IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHA); + case SLOT_ETHB: return IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHB); + case SLOT_NEC: return IXP4XX_GPIO_IRQ(GPIO_IRQ_NEC); + default: return IXP4XX_GPIO_IRQ(GPIO_IRQ_MPCI); } } diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c index 7b8a2c323840ad209c456b94e16974e2b4244f65..25d2c333c2045f2e353b26ce3f74292a2cf69d4e 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-pci.c @@ -26,14 +26,16 @@ #include #include #include - #include #include -#include #include +#define SLOT0_DEVID 0 +#define SLOT1_DEVID 1 +#define INTA 10 /* slot 1 has INTA and INTB crossed */ +#define INTB 11 + /* - * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h * Slot 0 isn't actually populated with a card connector but * we initialize it anyway in case a future version has the * slot populated or someone with good soldering skills has @@ -41,32 +43,26 @@ */ void __init gtwx5715_pci_preinit(void) { - set_irq_type(GTWX5715_PCI_SLOT0_INTA_IRQ, IRQ_TYPE_LEVEL_LOW); - set_irq_type(GTWX5715_PCI_SLOT0_INTB_IRQ, IRQ_TYPE_LEVEL_LOW); - set_irq_type(GTWX5715_PCI_SLOT1_INTA_IRQ, IRQ_TYPE_LEVEL_LOW); - set_irq_type(GTWX5715_PCI_SLOT1_INTB_IRQ, IRQ_TYPE_LEVEL_LOW); - + set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW); ixp4xx_pci_preinit(); } static int __init gtwx5715_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - int rc; - static int gtwx5715_irqmap - [GTWX5715_PCI_SLOT_COUNT] - [GTWX5715_PCI_INT_PIN_COUNT] = { - {GTWX5715_PCI_SLOT0_INTA_IRQ, GTWX5715_PCI_SLOT0_INTB_IRQ}, - {GTWX5715_PCI_SLOT1_INTA_IRQ, GTWX5715_PCI_SLOT1_INTB_IRQ}, -}; + int rc = -1; - if (slot >= GTWX5715_PCI_SLOT_COUNT || - pin >= GTWX5715_PCI_INT_PIN_COUNT) rc = -1; - else - rc = gtwx5715_irqmap[slot][pin-1]; + if ((slot == SLOT0_DEVID && pin == 1) || + (slot == SLOT1_DEVID && pin == 2)) + rc = IXP4XX_GPIO_IRQ(INTA); + else if ((slot == SLOT0_DEVID && pin == 2) || + (slot == SLOT1_DEVID && pin == 1)) + rc = IXP4XX_GPIO_IRQ(INTB); - printk("%s: Mapped slot %d pin %d to IRQ %d\n", __func__, slot, pin, rc); - return(rc); + printk(KERN_INFO "%s: Mapped slot %d pin %d to IRQ %d\n", + __func__, slot, pin, rc); + return rc; } struct hw_pci gtwx5715_pci __initdata = { @@ -81,9 +77,7 @@ struct hw_pci gtwx5715_pci __initdata = { int __init gtwx5715_pci_init(void) { if (machine_is_gtwx5715()) - { pci_common_init(>wx5715_pci); - } return 0; } diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c index 25c21d6665ec5fafcc55bdacdb1d537902ee91b1..0bc7185cb6f7282e7447ffe091ea9783f108c206 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c @@ -28,7 +28,6 @@ #include #include #include - #include #include #include @@ -37,7 +36,34 @@ #include #include #include -#include + +/* GPIO 5,6,7 and 12 are hard wired to the Kendin KS8995M Switch + and operate as an SPI type interface. The details of the interface + are available on Kendin/Micrel's web site. */ + +#define GTWX5715_KSSPI_SELECT 5 +#define GTWX5715_KSSPI_TXD 6 +#define GTWX5715_KSSPI_CLOCK 7 +#define GTWX5715_KSSPI_RXD 12 + +/* The "reset" button is wired to GPIO 3. + The GPIO is brought "low" when the button is pushed. */ + +#define GTWX5715_BUTTON_GPIO 3 + +/* Board Label Front Label + LED1 Power + LED2 Wireless-G + LED3 not populated but could be + LED4 Internet + LED5 - LED8 Controlled by KS8995M Switch + LED9 DMZ */ + +#define GTWX5715_LED1_GPIO 2 +#define GTWX5715_LED2_GPIO 9 +#define GTWX5715_LED3_GPIO 8 +#define GTWX5715_LED4_GPIO 1 +#define GTWX5715_LED9_GPIO 4 /* * Xscale UART registers are 32 bits wide with only the least diff --git a/arch/arm/mach-ixp4xx/include/mach/avila.h b/arch/arm/mach-ixp4xx/include/mach/avila.h deleted file mode 100644 index 1640cb61972b729c01851e2fafb56bf4f7443d56..0000000000000000000000000000000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/avila.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/include/mach/avila.h - * - * Gateworks Avila platform specific definitions - * - * Author: Michael-Luke Jones - * - * Based on ixdp425.h - * Author: Deepak Saxena - * - * Copyright 2004 (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 __ASM_ARCH_HARDWARE_H__ -#error "Do not include this directly, instead #include " -#endif - -#define AVILA_SDA_PIN 7 -#define AVILA_SCL_PIN 6 - -/* - * AVILA PCI IRQs - */ -#define AVILA_PCI_MAX_DEV 4 -#define LOFT_PCI_MAX_DEV 6 -#define AVILA_PCI_IRQ_LINES 4 - - -/* PCI controller GPIO to IRQ pin mappings */ -#define AVILA_PCI_INTA_PIN 11 -#define AVILA_PCI_INTB_PIN 10 -#define AVILA_PCI_INTC_PIN 9 -#define AVILA_PCI_INTD_PIN 8 - - diff --git a/arch/arm/mach-ixp4xx/include/mach/coyote.h b/arch/arm/mach-ixp4xx/include/mach/coyote.h deleted file mode 100644 index 717ac6d16f55603474fe4c511f389aad648b3cde..0000000000000000000000000000000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/coyote.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/include/mach/coyote.h - * - * ADI Engineering platform specific definitions - * - * Author: Deepak Saxena - * - * Copyright 2004 (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 __ASM_ARCH_HARDWARE_H__ -#error "Do not include this directly, instead #include " -#endif - -/* PCI controller GPIO to IRQ pin mappings */ -#define COYOTE_PCI_SLOT0_PIN 6 -#define COYOTE_PCI_SLOT1_PIN 11 - -#define COYOTE_PCI_SLOT0_DEVID 14 -#define COYOTE_PCI_SLOT1_DEVID 15 - -#define COYOTE_IDE_BASE_PHYS IXP4XX_EXP_BUS_BASE(3) -#define COYOTE_IDE_BASE_VIRT 0xFFFE1000 -#define COYOTE_IDE_REGION_SIZE 0x1000 - -#define COYOTE_IDE_DATA_PORT 0xFFFE10E0 -#define COYOTE_IDE_CTRL_PORT 0xFFFE10FC -#define COYOTE_IDE_ERROR_PORT 0xFFFE10E2 - diff --git a/arch/arm/mach-ixp4xx/include/mach/dsmg600.h b/arch/arm/mach-ixp4xx/include/mach/dsmg600.h deleted file mode 100644 index dc087a34a268a7fc3bf71be3f8ff4ecff354540f..0000000000000000000000000000000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/dsmg600.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * DSM-G600 platform specific definitions - * - * Copyright (C) 2006 Tower Technologies - * Author: Alessandro Zummo - * - * based on ixdp425.h: - * Copyright 2004 (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 __ASM_ARCH_HARDWARE_H__ -#error "Do not include this directly, instead #include " -#endif - -#define DSMG600_SDA_PIN 5 -#define DSMG600_SCL_PIN 4 - -/* - * DSMG600 PCI IRQs - */ -#define DSMG600_PCI_MAX_DEV 4 -#define DSMG600_PCI_IRQ_LINES 3 - - -/* PCI controller GPIO to IRQ pin mappings */ -#define DSMG600_PCI_INTA_PIN 11 -#define DSMG600_PCI_INTB_PIN 10 -#define DSMG600_PCI_INTC_PIN 9 -#define DSMG600_PCI_INTD_PIN 8 -#define DSMG600_PCI_INTE_PIN 7 -#define DSMG600_PCI_INTF_PIN 6 - -/* DSM-G600 Timer Setting */ -#define DSMG600_FREQ 66000000 - -/* Buttons */ - -#define DSMG600_PB_GPIO 15 /* power button */ -#define DSMG600_RB_GPIO 3 /* reset button */ - -/* Power control */ - -#define DSMG600_PO_GPIO 2 /* power off */ - -/* LEDs */ - -#define DSMG600_LED_PWR_GPIO 0 -#define DSMG600_LED_WLAN_GPIO 14 diff --git a/arch/arm/mach-ixp4xx/include/mach/fsg.h b/arch/arm/mach-ixp4xx/include/mach/fsg.h deleted file mode 100644 index 1f02b7e22a139e4042886352bbe7fa446493f956..0000000000000000000000000000000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/fsg.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/include/mach/fsg.h - * - * Freecom FSG-3 platform specific definitions - * - * Author: Rod Whitby - * Author: Tomasz Chmielewski - * Maintainers: http://www.nslu2-linux.org - * - * Based on coyote.h by - * Copyright 2004 (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 __ASM_ARCH_HARDWARE_H__ -#error "Do not include this directly, instead #include " -#endif - -#define FSG_SDA_PIN 12 -#define FSG_SCL_PIN 13 - -/* - * FSG PCI IRQs - */ -#define FSG_PCI_MAX_DEV 3 -#define FSG_PCI_IRQ_LINES 3 - - -/* PCI controller GPIO to IRQ pin mappings */ -#define FSG_PCI_INTA_PIN 6 -#define FSG_PCI_INTB_PIN 7 -#define FSG_PCI_INTC_PIN 5 - -/* Buttons */ - -#define FSG_SB_GPIO 4 /* sync button */ -#define FSG_RB_GPIO 9 /* reset button */ -#define FSG_UB_GPIO 10 /* usb button */ - -/* LEDs */ - -#define FSG_LED_WLAN_BIT 0 -#define FSG_LED_WAN_BIT 1 -#define FSG_LED_SATA_BIT 2 -#define FSG_LED_USB_BIT 4 -#define FSG_LED_RING_BIT 5 -#define FSG_LED_SYNC_BIT 7 diff --git a/arch/arm/mach-ixp4xx/include/mach/gpio.h b/arch/arm/mach-ixp4xx/include/mach/gpio.h index cd5aec26c072d3d218cd171ad8cb02635529ba84..a5f87ded2f28bd8e039d8c09ac04db6e8fc43d50 100644 --- a/arch/arm/mach-ixp4xx/include/mach/gpio.h +++ b/arch/arm/mach-ixp4xx/include/mach/gpio.h @@ -70,7 +70,7 @@ static inline void gpio_set_value(unsigned gpio, int value) #include /* cansleep wrappers */ extern int gpio_to_irq(int gpio); -extern int irq_to_gpio(int gpio); +extern int irq_to_gpio(unsigned int irq); #endif diff --git a/arch/arm/mach-ixp4xx/include/mach/gtwx5715.h b/arch/arm/mach-ixp4xx/include/mach/gtwx5715.h deleted file mode 100644 index 5d5e201cac7e69562393c4f51cc4612afcfee69b..0000000000000000000000000000000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/gtwx5715.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/include/mach/gtwx5715.h - * - * Gemtek GTWX5715 Gateway (Linksys WRV54G) - * - * Copyright 2004 (c) George T. Joseph - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public 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 __ASM_ARCH_HARDWARE_H__ -#error "Do not include this directly, instead #include " -#endif -#include "irqs.h" - -#define GTWX5715_GPIO0 0 -#define GTWX5715_GPIO1 1 -#define GTWX5715_GPIO2 2 -#define GTWX5715_GPIO3 3 -#define GTWX5715_GPIO4 4 -#define GTWX5715_GPIO5 5 -#define GTWX5715_GPIO6 6 -#define GTWX5715_GPIO7 7 -#define GTWX5715_GPIO8 8 -#define GTWX5715_GPIO9 9 -#define GTWX5715_GPIO10 10 -#define GTWX5715_GPIO11 11 -#define GTWX5715_GPIO12 12 -#define GTWX5715_GPIO13 13 -#define GTWX5715_GPIO14 14 - -#define GTWX5715_GPIO0_IRQ IRQ_IXP4XX_GPIO0 -#define GTWX5715_GPIO1_IRQ IRQ_IXP4XX_GPIO1 -#define GTWX5715_GPIO2_IRQ IRQ_IXP4XX_GPIO2 -#define GTWX5715_GPIO3_IRQ IRQ_IXP4XX_GPIO3 -#define GTWX5715_GPIO4_IRQ IRQ_IXP4XX_GPIO4 -#define GTWX5715_GPIO5_IRQ IRQ_IXP4XX_GPIO5 -#define GTWX5715_GPIO6_IRQ IRQ_IXP4XX_GPIO6 -#define GTWX5715_GPIO7_IRQ IRQ_IXP4XX_GPIO7 -#define GTWX5715_GPIO8_IRQ IRQ_IXP4XX_GPIO8 -#define GTWX5715_GPIO9_IRQ IRQ_IXP4XX_GPIO9 -#define GTWX5715_GPIO10_IRQ IRQ_IXP4XX_GPIO10 -#define GTWX5715_GPIO11_IRQ IRQ_IXP4XX_GPIO11 -#define GTWX5715_GPIO12_IRQ IRQ_IXP4XX_GPIO12 -#define GTWX5715_GPIO13_IRQ IRQ_IXP4XX_SW_INT1 -#define GTWX5715_GPIO14_IRQ IRQ_IXP4XX_SW_INT2 - -/* PCI controller GPIO to IRQ pin mappings - - INTA INTB -SLOT 0 10 11 -SLOT 1 11 10 - -*/ - -#define GTWX5715_PCI_SLOT0_DEVID 0 -#define GTWX5715_PCI_SLOT0_INTA_GPIO GTWX5715_GPIO10 -#define GTWX5715_PCI_SLOT0_INTB_GPIO GTWX5715_GPIO11 -#define GTWX5715_PCI_SLOT0_INTA_IRQ GTWX5715_GPIO10_IRQ -#define GTWX5715_PCI_SLOT0_INTB_IRQ GTWX5715_GPIO11_IRQ - -#define GTWX5715_PCI_SLOT1_DEVID 1 -#define GTWX5715_PCI_SLOT1_INTA_GPIO GTWX5715_GPIO11 -#define GTWX5715_PCI_SLOT1_INTB_GPIO GTWX5715_GPIO10 -#define GTWX5715_PCI_SLOT1_INTA_IRQ GTWX5715_GPIO11_IRQ -#define GTWX5715_PCI_SLOT1_INTB_IRQ GTWX5715_GPIO10_IRQ - -#define GTWX5715_PCI_SLOT_COUNT 2 -#define GTWX5715_PCI_INT_PIN_COUNT 2 - -/* - * GPIO 5,6,7 and12 are hard wired to the Kendin KS8995M Switch - * and operate as an SPI type interface. The details of the interface - * are available on Kendin/Micrel's web site. - */ - -#define GTWX5715_KSSPI_SELECT GTWX5715_GPIO5 -#define GTWX5715_KSSPI_TXD GTWX5715_GPIO6 -#define GTWX5715_KSSPI_CLOCK GTWX5715_GPIO7 -#define GTWX5715_KSSPI_RXD GTWX5715_GPIO12 - -/* - * The "reset" button is wired to GPIO 3. - * The GPIO is brought "low" when the button is pushed. - */ - -#define GTWX5715_BUTTON_GPIO GTWX5715_GPIO3 -#define GTWX5715_BUTTON_IRQ GTWX5715_GPIO3_IRQ - -/* - * Board Label Front Label - * LED1 Power - * LED2 Wireless-G - * LED3 not populated but could be - * LED4 Internet - * LED5 - LED8 Controlled by KS8995M Switch - * LED9 DMZ - */ - -#define GTWX5715_LED1_GPIO GTWX5715_GPIO2 -#define GTWX5715_LED2_GPIO GTWX5715_GPIO9 -#define GTWX5715_LED3_GPIO GTWX5715_GPIO8 -#define GTWX5715_LED4_GPIO GTWX5715_GPIO1 -#define GTWX5715_LED9_GPIO GTWX5715_GPIO4 diff --git a/arch/arm/mach-ixp4xx/include/mach/hardware.h b/arch/arm/mach-ixp4xx/include/mach/hardware.h index f58a43a2396638bc315d3e8444472272f61c1353..f9d1c43e4a54516d8ebfd098435c9d1297223360 100644 --- a/arch/arm/mach-ixp4xx/include/mach/hardware.h +++ b/arch/arm/mach-ixp4xx/include/mach/hardware.h @@ -18,7 +18,13 @@ #define __ASM_ARCH_HARDWARE_H__ #define PCIBIOS_MIN_IO 0x00001000 -#define PCIBIOS_MIN_MEM (cpu_is_ixp43x() ? 0x40000000 : 0x48000000) +#ifdef CONFIG_IXP4XX_INDIRECT_PCI +#define PCIBIOS_MIN_MEM 0x10000000 /* 1 GB of indirect PCI MMIO space */ +#define PCIBIOS_MAX_MEM 0x4FFFFFFF +#else +#define PCIBIOS_MIN_MEM 0x48000000 /* 64 MB of PCI MMIO space */ +#define PCIBIOS_MAX_MEM 0x4BFFFFFF +#endif /* * We override the standard dma-mask routines for bouncing. @@ -37,14 +43,4 @@ /* Platform helper functions and definitions */ #include "platform.h" -/* Platform specific details */ -#include "ixdp425.h" -#include "avila.h" -#include "coyote.h" -#include "prpmc1100.h" -#include "nslu2.h" -#include "nas100d.h" -#include "dsmg600.h" -#include "fsg.h" - #endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-ixp4xx/include/mach/io.h b/arch/arm/mach-ixp4xx/include/mach/io.h index 8a947d42a6f1b83bf7ed4b4b74e96d3f13b9e8be..6ea7e2fb2701b755830d4285da7266bec3591c04 100644 --- a/arch/arm/mach-ixp4xx/include/mach/io.h +++ b/arch/arm/mach-ixp4xx/include/mach/io.h @@ -26,22 +26,20 @@ extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data); /* * IXP4xx provides two methods of accessing PCI memory space: * - * 1) A direct mapped window from 0x48000000 to 0x4bffffff (64MB). + * 1) A direct mapped window from 0x48000000 to 0x4BFFFFFF (64MB). * To access PCI via this space, we simply ioremap() the BAR * into the kernel and we can use the standard read[bwl]/write[bwl] * macros. This is the preffered method due to speed but it - * limits the system to just 64MB of PCI memory. This can be - * problamatic if using video cards and other memory-heavy - * targets. - * - * 2) If > 64MB of memory space is required, the IXP4xx can be configured - * to use indirect registers to access PCI (as we do below for I/O - * transactions). This allows for up to 128MB (0x48000000 to 0x4fffffff) - * of memory on the bus. The disadvantage of this is that every - * PCI access requires three local register accesses plus a spinlock, - * but in some cases the performance hit is acceptable. In addition, - * you cannot mmap() PCI devices in this case. + * limits the system to just 64MB of PCI memory. This can be + * problematic if using video cards and other memory-heavy targets. * + * 2) If > 64MB of memory space is required, the IXP4xx can use indirect + * registers to access the whole 4 GB of PCI memory space (as we do below + * for I/O transactions). This allows currently for up to 1 GB (0x10000000 + * to 0x4FFFFFFF) of memory on the bus. The disadvantage of this is that + * every PCI access requires three local register accesses plus a spinlock, + * but in some cases the performance hit is acceptable. In addition, you + * cannot mmap() PCI devices in this case. */ #ifndef CONFIG_IXP4XX_INDIRECT_PCI @@ -55,48 +53,52 @@ extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data); * access registers. If something outside of PCI is ioremap'd, we * fallback to the default. */ -static inline void __iomem * -__ixp4xx_ioremap(unsigned long addr, size_t size, unsigned int mtype) + +static inline int is_pci_memory(u32 addr) +{ + return (addr >= PCIBIOS_MIN_MEM) && (addr <= 0x4FFFFFFF); +} + +static inline void __iomem * __indirect_ioremap(unsigned long addr, size_t size, + unsigned int mtype) { - if((addr < PCIBIOS_MIN_MEM) || (addr > 0x4fffffff)) + if (!is_pci_memory(addr)) return __arm_ioremap(addr, size, mtype); return (void __iomem *)addr; } -static inline void -__ixp4xx_iounmap(void __iomem *addr) +static inline void __indirect_iounmap(void __iomem *addr) { - if ((__force u32)addr >= VMALLOC_START) + if (!is_pci_memory((__force u32)addr)) __iounmap(addr); } -#define __arch_ioremap(a, s, f) __ixp4xx_ioremap(a, s, f) -#define __arch_iounmap(a) __ixp4xx_iounmap(a) +#define __arch_ioremap(a, s, f) __indirect_ioremap(a, s, f) +#define __arch_iounmap(a) __indirect_iounmap(a) -#define writeb(v, p) __ixp4xx_writeb(v, p) -#define writew(v, p) __ixp4xx_writew(v, p) -#define writel(v, p) __ixp4xx_writel(v, p) +#define writeb(v, p) __indirect_writeb(v, p) +#define writew(v, p) __indirect_writew(v, p) +#define writel(v, p) __indirect_writel(v, p) -#define writesb(p, v, l) __ixp4xx_writesb(p, v, l) -#define writesw(p, v, l) __ixp4xx_writesw(p, v, l) -#define writesl(p, v, l) __ixp4xx_writesl(p, v, l) - -#define readb(p) __ixp4xx_readb(p) -#define readw(p) __ixp4xx_readw(p) -#define readl(p) __ixp4xx_readl(p) - -#define readsb(p, v, l) __ixp4xx_readsb(p, v, l) -#define readsw(p, v, l) __ixp4xx_readsw(p, v, l) -#define readsl(p, v, l) __ixp4xx_readsl(p, v, l) +#define writesb(p, v, l) __indirect_writesb(p, v, l) +#define writesw(p, v, l) __indirect_writesw(p, v, l) +#define writesl(p, v, l) __indirect_writesl(p, v, l) -static inline void -__ixp4xx_writeb(u8 value, volatile void __iomem *p) +#define readb(p) __indirect_readb(p) +#define readw(p) __indirect_readw(p) +#define readl(p) __indirect_readl(p) + +#define readsb(p, v, l) __indirect_readsb(p, v, l) +#define readsw(p, v, l) __indirect_readsw(p, v, l) +#define readsl(p, v, l) __indirect_readsl(p, v, l) + +static inline void __indirect_writeb(u8 value, volatile void __iomem *p) { u32 addr = (u32)p; u32 n, byte_enables, data; - if (addr >= VMALLOC_START) { + if (!is_pci_memory(addr)) { __raw_writeb(value, addr); return; } @@ -107,20 +109,19 @@ __ixp4xx_writeb(u8 value, volatile void __iomem *p) ixp4xx_pci_write(addr, byte_enables | NP_CMD_MEMWRITE, data); } -static inline void -__ixp4xx_writesb(volatile void __iomem *bus_addr, const u8 *vaddr, int count) +static inline void __indirect_writesb(volatile void __iomem *bus_addr, + const u8 *vaddr, int count) { while (count--) writeb(*vaddr++, bus_addr); } -static inline void -__ixp4xx_writew(u16 value, volatile void __iomem *p) +static inline void __indirect_writew(u16 value, volatile void __iomem *p) { u32 addr = (u32)p; u32 n, byte_enables, data; - if (addr >= VMALLOC_START) { + if (!is_pci_memory(addr)) { __raw_writew(value, addr); return; } @@ -131,18 +132,18 @@ __ixp4xx_writew(u16 value, volatile void __iomem *p) ixp4xx_pci_write(addr, byte_enables | NP_CMD_MEMWRITE, data); } -static inline void -__ixp4xx_writesw(volatile void __iomem *bus_addr, const u16 *vaddr, int count) +static inline void __indirect_writesw(volatile void __iomem *bus_addr, + const u16 *vaddr, int count) { while (count--) writew(*vaddr++, bus_addr); } -static inline void -__ixp4xx_writel(u32 value, volatile void __iomem *p) +static inline void __indirect_writel(u32 value, volatile void __iomem *p) { u32 addr = (__force u32)p; - if (addr >= VMALLOC_START) { + + if (!is_pci_memory(addr)) { __raw_writel(value, p); return; } @@ -150,20 +151,19 @@ __ixp4xx_writel(u32 value, volatile void __iomem *p) ixp4xx_pci_write(addr, NP_CMD_MEMWRITE, value); } -static inline void -__ixp4xx_writesl(volatile void __iomem *bus_addr, const u32 *vaddr, int count) +static inline void __indirect_writesl(volatile void __iomem *bus_addr, + const u32 *vaddr, int count) { while (count--) writel(*vaddr++, bus_addr); } -static inline unsigned char -__ixp4xx_readb(const volatile void __iomem *p) +static inline unsigned char __indirect_readb(const volatile void __iomem *p) { u32 addr = (u32)p; u32 n, byte_enables, data; - if (addr >= VMALLOC_START) + if (!is_pci_memory(addr)) return __raw_readb(addr); n = addr % 4; @@ -174,20 +174,19 @@ __ixp4xx_readb(const volatile void __iomem *p) return data >> (8*n); } -static inline void -__ixp4xx_readsb(const volatile void __iomem *bus_addr, u8 *vaddr, u32 count) +static inline void __indirect_readsb(const volatile void __iomem *bus_addr, + u8 *vaddr, u32 count) { while (count--) *vaddr++ = readb(bus_addr); } -static inline unsigned short -__ixp4xx_readw(const volatile void __iomem *p) +static inline unsigned short __indirect_readw(const volatile void __iomem *p) { u32 addr = (u32)p; u32 n, byte_enables, data; - if (addr >= VMALLOC_START) + if (!is_pci_memory(addr)) return __raw_readw(addr); n = addr % 4; @@ -198,20 +197,19 @@ __ixp4xx_readw(const volatile void __iomem *p) return data>>(8*n); } -static inline void -__ixp4xx_readsw(const volatile void __iomem *bus_addr, u16 *vaddr, u32 count) +static inline void __indirect_readsw(const volatile void __iomem *bus_addr, + u16 *vaddr, u32 count) { while (count--) *vaddr++ = readw(bus_addr); } -static inline unsigned long -__ixp4xx_readl(const volatile void __iomem *p) +static inline unsigned long __indirect_readl(const volatile void __iomem *p) { u32 addr = (__force u32)p; u32 data; - if (addr >= VMALLOC_START) + if (!is_pci_memory(addr)) return __raw_readl(p); if (ixp4xx_pci_read(addr, NP_CMD_MEMREAD, &data)) @@ -220,8 +218,8 @@ __ixp4xx_readl(const volatile void __iomem *p) return data; } -static inline void -__ixp4xx_readsl(const volatile void __iomem *bus_addr, u32 *vaddr, u32 count) +static inline void __indirect_readsl(const volatile void __iomem *bus_addr, + u32 *vaddr, u32 count) { while (count--) *vaddr++ = readl(bus_addr); @@ -235,7 +233,7 @@ __ixp4xx_readsl(const volatile void __iomem *bus_addr, u32 *vaddr, u32 count) #define memcpy_fromio(a,c,l) _memcpy_fromio((a),(c),(l)) #define memcpy_toio(c,a,l) _memcpy_toio((c),(a),(l)) -#endif +#endif /* CONFIG_IXP4XX_INDIRECT_PCI */ #ifndef CONFIG_PCI @@ -250,25 +248,8 @@ __ixp4xx_readsl(const volatile void __iomem *bus_addr, u32 *vaddr, u32 count) * transaction. This means that we need to override the default * I/O functions. */ -#define outb(p, v) __ixp4xx_outb(p, v) -#define outw(p, v) __ixp4xx_outw(p, v) -#define outl(p, v) __ixp4xx_outl(p, v) - -#define outsb(p, v, l) __ixp4xx_outsb(p, v, l) -#define outsw(p, v, l) __ixp4xx_outsw(p, v, l) -#define outsl(p, v, l) __ixp4xx_outsl(p, v, l) -#define inb(p) __ixp4xx_inb(p) -#define inw(p) __ixp4xx_inw(p) -#define inl(p) __ixp4xx_inl(p) - -#define insb(p, v, l) __ixp4xx_insb(p, v, l) -#define insw(p, v, l) __ixp4xx_insw(p, v, l) -#define insl(p, v, l) __ixp4xx_insl(p, v, l) - - -static inline void -__ixp4xx_outb(u8 value, u32 addr) +static inline void outb(u8 value, u32 addr) { u32 n, byte_enables, data; n = addr % 4; @@ -277,15 +258,13 @@ __ixp4xx_outb(u8 value, u32 addr) ixp4xx_pci_write(addr, byte_enables | NP_CMD_IOWRITE, data); } -static inline void -__ixp4xx_outsb(u32 io_addr, const u8 *vaddr, u32 count) +static inline void outsb(u32 io_addr, const u8 *vaddr, u32 count) { while (count--) outb(*vaddr++, io_addr); } -static inline void -__ixp4xx_outw(u16 value, u32 addr) +static inline void outw(u16 value, u32 addr) { u32 n, byte_enables, data; n = addr % 4; @@ -294,28 +273,24 @@ __ixp4xx_outw(u16 value, u32 addr) ixp4xx_pci_write(addr, byte_enables | NP_CMD_IOWRITE, data); } -static inline void -__ixp4xx_outsw(u32 io_addr, const u16 *vaddr, u32 count) +static inline void outsw(u32 io_addr, const u16 *vaddr, u32 count) { while (count--) outw(cpu_to_le16(*vaddr++), io_addr); } -static inline void -__ixp4xx_outl(u32 value, u32 addr) +static inline void outl(u32 value, u32 addr) { ixp4xx_pci_write(addr, NP_CMD_IOWRITE, value); } -static inline void -__ixp4xx_outsl(u32 io_addr, const u32 *vaddr, u32 count) +static inline void outsl(u32 io_addr, const u32 *vaddr, u32 count) { while (count--) - outl(*vaddr++, io_addr); + outl(cpu_to_le32(*vaddr++), io_addr); } -static inline u8 -__ixp4xx_inb(u32 addr) +static inline u8 inb(u32 addr) { u32 n, byte_enables, data; n = addr % 4; @@ -326,15 +301,13 @@ __ixp4xx_inb(u32 addr) return data >> (8*n); } -static inline void -__ixp4xx_insb(u32 io_addr, u8 *vaddr, u32 count) +static inline void insb(u32 io_addr, u8 *vaddr, u32 count) { while (count--) *vaddr++ = inb(io_addr); } -static inline u16 -__ixp4xx_inw(u32 addr) +static inline u16 inw(u32 addr) { u32 n, byte_enables, data; n = addr % 4; @@ -345,15 +318,13 @@ __ixp4xx_inw(u32 addr) return data>>(8*n); } -static inline void -__ixp4xx_insw(u32 io_addr, u16 *vaddr, u32 count) +static inline void insw(u32 io_addr, u16 *vaddr, u32 count) { while (count--) *vaddr++ = le16_to_cpu(inw(io_addr)); } -static inline u32 -__ixp4xx_inl(u32 addr) +static inline u32 inl(u32 addr) { u32 data; if (ixp4xx_pci_read(addr, NP_CMD_IOREAD, &data)) @@ -362,11 +333,10 @@ __ixp4xx_inl(u32 addr) return data; } -static inline void -__ixp4xx_insl(u32 io_addr, u32 *vaddr, u32 count) +static inline void insl(u32 io_addr, u32 *vaddr, u32 count) { while (count--) - *vaddr++ = inl(io_addr); + *vaddr++ = le32_to_cpu(inl(io_addr)); } #define PIO_OFFSET 0x10000UL @@ -374,194 +344,183 @@ __ixp4xx_insl(u32 io_addr, u32 *vaddr, u32 count) #define __is_io_address(p) (((unsigned long)p >= PIO_OFFSET) && \ ((unsigned long)p <= (PIO_MASK + PIO_OFFSET))) -static inline unsigned int -__ixp4xx_ioread8(const void __iomem *addr) + +#define ioread8(p) ioread8(p) +static inline unsigned int ioread8(const void __iomem *addr) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - return (unsigned int)__ixp4xx_inb(port & PIO_MASK); + return (unsigned int)inb(port & PIO_MASK); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI return (unsigned int)__raw_readb(port); #else - return (unsigned int)__ixp4xx_readb(addr); + return (unsigned int)__indirect_readb(addr); #endif } -static inline void -__ixp4xx_ioread8_rep(const void __iomem *addr, void *vaddr, u32 count) +#define ioread8_rep(p, v, c) ioread8_rep(p, v, c) +static inline void ioread8_rep(const void __iomem *addr, void *vaddr, u32 count) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_insb(port & PIO_MASK, vaddr, count); + insb(port & PIO_MASK, vaddr, count); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_readsb(addr, vaddr, count); #else - __ixp4xx_readsb(addr, vaddr, count); + __indirect_readsb(addr, vaddr, count); #endif } -static inline unsigned int -__ixp4xx_ioread16(const void __iomem *addr) +#define ioread16(p) ioread16(p) +static inline unsigned int ioread16(const void __iomem *addr) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - return (unsigned int)__ixp4xx_inw(port & PIO_MASK); + return (unsigned int)inw(port & PIO_MASK); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI return le16_to_cpu(__raw_readw((u32)port)); #else - return (unsigned int)__ixp4xx_readw(addr); + return (unsigned int)__indirect_readw(addr); #endif } -static inline void -__ixp4xx_ioread16_rep(const void __iomem *addr, void *vaddr, u32 count) +#define ioread16_rep(p, v, c) ioread16_rep(p, v, c) +static inline void ioread16_rep(const void __iomem *addr, void *vaddr, + u32 count) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_insw(port & PIO_MASK, vaddr, count); + insw(port & PIO_MASK, vaddr, count); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_readsw(addr, vaddr, count); #else - __ixp4xx_readsw(addr, vaddr, count); + __indirect_readsw(addr, vaddr, count); #endif } -static inline unsigned int -__ixp4xx_ioread32(const void __iomem *addr) +#define ioread32(p) ioread32(p) +static inline unsigned int ioread32(const void __iomem *addr) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - return (unsigned int)__ixp4xx_inl(port & PIO_MASK); + return (unsigned int)inl(port & PIO_MASK); else { #ifndef CONFIG_IXP4XX_INDIRECT_PCI return le32_to_cpu((__force __le32)__raw_readl(addr)); #else - return (unsigned int)__ixp4xx_readl(addr); + return (unsigned int)__indirect_readl(addr); #endif } } -static inline void -__ixp4xx_ioread32_rep(const void __iomem *addr, void *vaddr, u32 count) +#define ioread32_rep(p, v, c) ioread32_rep(p, v, c) +static inline void ioread32_rep(const void __iomem *addr, void *vaddr, + u32 count) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_insl(port & PIO_MASK, vaddr, count); + insl(port & PIO_MASK, vaddr, count); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_readsl(addr, vaddr, count); #else - __ixp4xx_readsl(addr, vaddr, count); + __indirect_readsl(addr, vaddr, count); #endif } -static inline void -__ixp4xx_iowrite8(u8 value, void __iomem *addr) +#define iowrite8(v, p) iowrite8(v, p) +static inline void iowrite8(u8 value, void __iomem *addr) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_outb(value, port & PIO_MASK); + outb(value, port & PIO_MASK); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_writeb(value, port); #else - __ixp4xx_writeb(value, addr); + __indirect_writeb(value, addr); #endif } -static inline void -__ixp4xx_iowrite8_rep(void __iomem *addr, const void *vaddr, u32 count) +#define iowrite8_rep(p, v, c) iowrite8_rep(p, v, c) +static inline void iowrite8_rep(void __iomem *addr, const void *vaddr, + u32 count) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_outsb(port & PIO_MASK, vaddr, count); + outsb(port & PIO_MASK, vaddr, count); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_writesb(addr, vaddr, count); #else - __ixp4xx_writesb(addr, vaddr, count); + __indirect_writesb(addr, vaddr, count); #endif } -static inline void -__ixp4xx_iowrite16(u16 value, void __iomem *addr) +#define iowrite16(v, p) iowrite16(v, p) +static inline void iowrite16(u16 value, void __iomem *addr) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_outw(value, port & PIO_MASK); + outw(value, port & PIO_MASK); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_writew(cpu_to_le16(value), addr); #else - __ixp4xx_writew(value, addr); + __indirect_writew(value, addr); #endif } -static inline void -__ixp4xx_iowrite16_rep(void __iomem *addr, const void *vaddr, u32 count) +#define iowrite16_rep(p, v, c) iowrite16_rep(p, v, c) +static inline void iowrite16_rep(void __iomem *addr, const void *vaddr, + u32 count) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_outsw(port & PIO_MASK, vaddr, count); + outsw(port & PIO_MASK, vaddr, count); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_writesw(addr, vaddr, count); #else - __ixp4xx_writesw(addr, vaddr, count); + __indirect_writesw(addr, vaddr, count); #endif } -static inline void -__ixp4xx_iowrite32(u32 value, void __iomem *addr) +#define iowrite32(v, p) iowrite32(v, p) +static inline void iowrite32(u32 value, void __iomem *addr) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_outl(value, port & PIO_MASK); + outl(value, port & PIO_MASK); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_writel((u32 __force)cpu_to_le32(value), addr); #else - __ixp4xx_writel(value, addr); + __indirect_writel(value, addr); #endif } -static inline void -__ixp4xx_iowrite32_rep(void __iomem *addr, const void *vaddr, u32 count) +#define iowrite32_rep(p, v, c) iowrite32_rep(p, v, c) +static inline void iowrite32_rep(void __iomem *addr, const void *vaddr, + u32 count) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_outsl(port & PIO_MASK, vaddr, count); + outsl(port & PIO_MASK, vaddr, count); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_writesl(addr, vaddr, count); #else - __ixp4xx_writesl(addr, vaddr, count); + __indirect_writesl(addr, vaddr, count); #endif } -#define ioread8(p) __ixp4xx_ioread8(p) -#define ioread16(p) __ixp4xx_ioread16(p) -#define ioread32(p) __ixp4xx_ioread32(p) - -#define ioread8_rep(p, v, c) __ixp4xx_ioread8_rep(p, v, c) -#define ioread16_rep(p, v, c) __ixp4xx_ioread16_rep(p, v, c) -#define ioread32_rep(p, v, c) __ixp4xx_ioread32_rep(p, v, c) - -#define iowrite8(v,p) __ixp4xx_iowrite8(v,p) -#define iowrite16(v,p) __ixp4xx_iowrite16(v,p) -#define iowrite32(v,p) __ixp4xx_iowrite32(v,p) - -#define iowrite8_rep(p, v, c) __ixp4xx_iowrite8_rep(p, v, c) -#define iowrite16_rep(p, v, c) __ixp4xx_iowrite16_rep(p, v, c) -#define iowrite32_rep(p, v, c) __ixp4xx_iowrite32_rep(p, v, c) - #define ioport_map(port, nr) ((void __iomem*)(port + PIO_OFFSET)) #define ioport_unmap(addr) -#endif // !CONFIG_PCI - -#endif // __ASM_ARM_ARCH_IO_H +#endif /* CONFIG_PCI */ +#endif /* __ASM_ARM_ARCH_IO_H */ diff --git a/arch/arm/mach-ixp4xx/include/mach/irqs.h b/arch/arm/mach-ixp4xx/include/mach/irqs.h index f4d74de1566a5abce40410832f321a4fc16dae59..7e6d4cce7c27f9bbeb3869e217d81a1c6ea27177 100644 --- a/arch/arm/mach-ixp4xx/include/mach/irqs.h +++ b/arch/arm/mach-ixp4xx/include/mach/irqs.h @@ -15,7 +15,6 @@ #ifndef _ARCH_IXP4XX_IRQS_H_ #define _ARCH_IXP4XX_IRQS_H_ - #define IRQ_IXP4XX_NPEA 0 #define IRQ_IXP4XX_NPEB 1 #define IRQ_IXP4XX_NPEC 2 @@ -59,6 +58,9 @@ #define IRQ_IXP4XX_MCU_ECC 61 #define IRQ_IXP4XX_EXP_PE 62 +#define _IXP4XX_GPIO_IRQ(n) (IRQ_IXP4XX_GPIO ## n) +#define IXP4XX_GPIO_IRQ(n) _IXP4XX_GPIO_IRQ(n) + /* * Only first 32 sources are valid if running on IXP42x systems */ @@ -70,69 +72,4 @@ #define XSCALE_PMU_IRQ (IRQ_IXP4XX_XSCALE_PMU) -/* - * IXDP425 board IRQs - */ -#define IRQ_IXDP425_PCI_INTA IRQ_IXP4XX_GPIO11 -#define IRQ_IXDP425_PCI_INTB IRQ_IXP4XX_GPIO10 -#define IRQ_IXDP425_PCI_INTC IRQ_IXP4XX_GPIO9 -#define IRQ_IXDP425_PCI_INTD IRQ_IXP4XX_GPIO8 - -/* - * Gateworks Avila board IRQs - */ -#define IRQ_AVILA_PCI_INTA IRQ_IXP4XX_GPIO11 -#define IRQ_AVILA_PCI_INTB IRQ_IXP4XX_GPIO10 -#define IRQ_AVILA_PCI_INTC IRQ_IXP4XX_GPIO9 -#define IRQ_AVILA_PCI_INTD IRQ_IXP4XX_GPIO8 - - -/* - * PrPMC1100 Board IRQs - */ -#define IRQ_PRPMC1100_PCI_INTA IRQ_IXP4XX_GPIO11 -#define IRQ_PRPMC1100_PCI_INTB IRQ_IXP4XX_GPIO10 -#define IRQ_PRPMC1100_PCI_INTC IRQ_IXP4XX_GPIO9 -#define IRQ_PRPMC1100_PCI_INTD IRQ_IXP4XX_GPIO8 - -/* - * ADI Coyote Board IRQs - */ -#define IRQ_COYOTE_PCI_SLOT0 IRQ_IXP4XX_GPIO6 -#define IRQ_COYOTE_PCI_SLOT1 IRQ_IXP4XX_GPIO11 -#define IRQ_COYOTE_IDE IRQ_IXP4XX_GPIO5 - -/* - * NSLU2 board IRQs - */ -#define IRQ_NSLU2_PCI_INTA IRQ_IXP4XX_GPIO11 -#define IRQ_NSLU2_PCI_INTB IRQ_IXP4XX_GPIO10 -#define IRQ_NSLU2_PCI_INTC IRQ_IXP4XX_GPIO9 - -/* - * NAS100D board IRQs - */ -#define IRQ_NAS100D_PCI_INTA IRQ_IXP4XX_GPIO11 -#define IRQ_NAS100D_PCI_INTB IRQ_IXP4XX_GPIO10 -#define IRQ_NAS100D_PCI_INTC IRQ_IXP4XX_GPIO9 -#define IRQ_NAS100D_PCI_INTD IRQ_IXP4XX_GPIO8 -#define IRQ_NAS100D_PCI_INTE IRQ_IXP4XX_GPIO7 - -/* - * D-Link DSM-G600 RevA board IRQs - */ -#define IRQ_DSMG600_PCI_INTA IRQ_IXP4XX_GPIO11 -#define IRQ_DSMG600_PCI_INTB IRQ_IXP4XX_GPIO10 -#define IRQ_DSMG600_PCI_INTC IRQ_IXP4XX_GPIO9 -#define IRQ_DSMG600_PCI_INTD IRQ_IXP4XX_GPIO8 -#define IRQ_DSMG600_PCI_INTE IRQ_IXP4XX_GPIO7 -#define IRQ_DSMG600_PCI_INTF IRQ_IXP4XX_GPIO6 - -/* - * Freecom FSG-3 Board IRQs - */ -#define IRQ_FSG_PCI_INTA IRQ_IXP4XX_GPIO6 -#define IRQ_FSG_PCI_INTB IRQ_IXP4XX_GPIO7 -#define IRQ_FSG_PCI_INTC IRQ_IXP4XX_GPIO5 - #endif diff --git a/arch/arm/mach-ixp4xx/include/mach/ixdp425.h b/arch/arm/mach-ixp4xx/include/mach/ixdp425.h deleted file mode 100644 index 2cafe65ebfee1979b366363289e753ff83e40215..0000000000000000000000000000000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/ixdp425.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/include/mach/ixdp425.h - * - * IXDP425 platform specific definitions - * - * Author: Deepak Saxena - * - * Copyright 2004 (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 __ASM_ARCH_HARDWARE_H__ -#error "Do not include this directly, instead #include " -#endif - -#define IXDP425_SDA_PIN 7 -#define IXDP425_SCL_PIN 6 - -/* - * IXDP425 PCI IRQs - */ -#define IXDP425_PCI_MAX_DEV 4 -#define IXDP425_PCI_IRQ_LINES 4 - - -/* PCI controller GPIO to IRQ pin mappings */ -#define IXDP425_PCI_INTA_PIN 11 -#define IXDP425_PCI_INTB_PIN 10 -#define IXDP425_PCI_INTC_PIN 9 -#define IXDP425_PCI_INTD_PIN 8 - -/* NAND Flash pins */ -#define IXDP425_NAND_NCE_PIN 12 - -#define IXDP425_NAND_CMD_BYTE 0x01 -#define IXDP425_NAND_ADDR_BYTE 0x02 diff --git a/arch/arm/mach-ixp4xx/include/mach/nas100d.h b/arch/arm/mach-ixp4xx/include/mach/nas100d.h deleted file mode 100644 index 3771d62a97486b1ee9f15a74f5d5704a6da5bd4d..0000000000000000000000000000000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/nas100d.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/include/mach/nas100d.h - * - * NAS100D platform specific definitions - * - * Copyright (c) 2005 Tower Technologies - * - * Author: Alessandro Zummo - * - * based on ixdp425.h: - * Copyright 2004 (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 __ASM_ARCH_HARDWARE_H__ -#error "Do not include this directly, instead #include " -#endif - -#define NAS100D_SDA_PIN 5 -#define NAS100D_SCL_PIN 6 - -/* - * NAS100D PCI IRQs - */ -#define NAS100D_PCI_MAX_DEV 3 -#define NAS100D_PCI_IRQ_LINES 3 - - -/* PCI controller GPIO to IRQ pin mappings */ -#define NAS100D_PCI_INTA_PIN 11 -#define NAS100D_PCI_INTB_PIN 10 -#define NAS100D_PCI_INTC_PIN 9 -#define NAS100D_PCI_INTD_PIN 8 -#define NAS100D_PCI_INTE_PIN 7 - -/* Buttons */ - -#define NAS100D_PB_GPIO 14 /* power button */ -#define NAS100D_RB_GPIO 4 /* reset button */ - -/* Power control */ - -#define NAS100D_PO_GPIO 12 /* power off */ - -/* LEDs */ - -#define NAS100D_LED_WLAN_GPIO 0 -#define NAS100D_LED_DISK_GPIO 3 -#define NAS100D_LED_PWR_GPIO 15 diff --git a/arch/arm/mach-ixp4xx/include/mach/npe.h b/arch/arm/mach-ixp4xx/include/mach/npe.h index 37d0511689dc343873c57414f0554138a66efcac..e320db2457ae931eab7d6257f67ab8ea89d14f85 100644 --- a/arch/arm/mach-ixp4xx/include/mach/npe.h +++ b/arch/arm/mach-ixp4xx/include/mach/npe.h @@ -33,7 +33,7 @@ int npe_send_message(struct npe *npe, const void *msg, const char *what); int npe_recv_message(struct npe *npe, void *msg, const char *what); int npe_send_recv_message(struct npe *npe, void *msg, const char *what); int npe_load_firmware(struct npe *npe, const char *name, struct device *dev); -struct npe *npe_request(int id); +struct npe *npe_request(unsigned id); void npe_release(struct npe *npe); #endif /* __IXP4XX_NPE_H */ diff --git a/arch/arm/mach-ixp4xx/include/mach/nslu2.h b/arch/arm/mach-ixp4xx/include/mach/nslu2.h deleted file mode 100644 index 85d00adbfb920024c1c8617cc75e6f54c0099e6a..0000000000000000000000000000000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/nslu2.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/include/mach/nslu2.h - * - * NSLU2 platform specific definitions - * - * Author: Mark Rakes - * Maintainers: http://www.nslu2-linux.org - * - * based on ixdp425.h: - * Copyright 2004 (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 __ASM_ARCH_HARDWARE_H__ -#error "Do not include this directly, instead #include " -#endif - -#define NSLU2_SDA_PIN 7 -#define NSLU2_SCL_PIN 6 - -/* - * NSLU2 PCI IRQs - */ -#define NSLU2_PCI_MAX_DEV 3 -#define NSLU2_PCI_IRQ_LINES 3 - - -/* PCI controller GPIO to IRQ pin mappings */ -#define NSLU2_PCI_INTA_PIN 11 -#define NSLU2_PCI_INTB_PIN 10 -#define NSLU2_PCI_INTC_PIN 9 -#define NSLU2_PCI_INTD_PIN 8 - -/* NSLU2 Timer */ -#define NSLU2_FREQ 66000000 - -/* Buttons */ - -#define NSLU2_PB_GPIO 5 /* power button */ -#define NSLU2_PO_GPIO 8 /* power off */ -#define NSLU2_RB_GPIO 12 /* reset button */ - -/* Buzzer */ - -#define NSLU2_GPIO_BUZZ 4 - -/* LEDs */ - -#define NSLU2_LED_RED_GPIO 0 -#define NSLU2_LED_GRN_GPIO 1 -#define NSLU2_LED_DISK1_GPIO 3 -#define NSLU2_LED_DISK2_GPIO 2 diff --git a/arch/arm/mach-ixp4xx/include/mach/prpmc1100.h b/arch/arm/mach-ixp4xx/include/mach/prpmc1100.h deleted file mode 100644 index 17274a2e3decf1c373414520f7d8e848b9c86dfb..0000000000000000000000000000000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/prpmc1100.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/include/mach/prpmc1100.h - * - * Motorolla PrPMC1100 platform specific definitions - * - * Author: Deepak Saxena - * - * Copyright 2004 (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 __ASM_ARCH_HARDWARE_H__ -#error "Do not include this directly, instead #include " -#endif - -#define PRPMC1100_FLASH_BASE IXP4XX_EXP_BUS_CS0_BASE_PHYS -#define PRPMC1100_FLASH_SIZE IXP4XX_EXP_BUS_CSX_REGION_SIZE - -#define PRPMC1100_PCI_MIN_DEVID 10 -#define PRPMC1100_PCI_MAX_DEVID 16 -#define PRPMC1100_PCI_IRQ_LINES 4 - - -/* PCI controller GPIO to IRQ pin mappings */ -#define PRPMC1100_PCI_INTA_PIN 11 -#define PRPMC1100_PCI_INTB_PIN 10 -#define PRPMC1100_PCI_INTC_PIN 9 -#define PRPMC1100_PCI_INTD_PIN 8 - - diff --git a/arch/arm/mach-ixp4xx/include/mach/timex.h b/arch/arm/mach-ixp4xx/include/mach/timex.h index 89ce3ee846986d735a0097246b4e39209a8aadb5..2c3f93c3eb79937cb6360904cbeb1f6599adf1ce 100644 --- a/arch/arm/mach-ixp4xx/include/mach/timex.h +++ b/arch/arm/mach-ixp4xx/include/mach/timex.h @@ -10,6 +10,6 @@ * 66.66... MHz. We do a convulted calculation of CLOCK_TICK_RATE b/c the * timer register ignores the bottom 2 bits of the LATCH value. */ -#define FREQ 66666666 +#define FREQ 66666000 #define CLOCK_TICK_RATE (((FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ) diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c index 64c29aacaac9f5e971976d3d1322bb2b496b4254..1ba165a6edaca3b0b77583a7e7380c3ffe021f01 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-pci.c +++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c @@ -1,5 +1,5 @@ /* - * arch/arm/mach-ixp4xx/ixdp425-pci.c + * arch/arm/mach-ixp4xx/ixdp425-pci.c * * IXDP425 board-level PCI initialization * @@ -19,39 +19,43 @@ #include #include #include - #include #include #include #include +#define MAX_DEV 4 +#define IRQ_LINES 4 + +/* PCI controller GPIO to IRQ pin mappings */ +#define INTA 11 +#define INTB 10 +#define INTC 9 +#define INTD 8 + + void __init ixdp425_pci_preinit(void) { - set_irq_type(IRQ_IXDP425_PCI_INTA, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_IXDP425_PCI_INTB, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_IXDP425_PCI_INTC, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_IXDP425_PCI_INTD, IRQ_TYPE_LEVEL_LOW); - + set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW); ixp4xx_pci_preinit(); } static int __init ixdp425_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - static int pci_irq_table[IXDP425_PCI_IRQ_LINES] = { - IRQ_IXDP425_PCI_INTA, - IRQ_IXDP425_PCI_INTB, - IRQ_IXDP425_PCI_INTC, - IRQ_IXDP425_PCI_INTD + static int pci_irq_table[IRQ_LINES] = { + IXP4XX_GPIO_IRQ(INTA), + IXP4XX_GPIO_IRQ(INTB), + IXP4XX_GPIO_IRQ(INTC), + IXP4XX_GPIO_IRQ(INTD) }; - int irq = -1; - - if (slot >= 1 && slot <= IXDP425_PCI_MAX_DEV && - pin >= 1 && pin <= IXDP425_PCI_IRQ_LINES) { - irq = pci_irq_table[(slot + pin - 2) % 4]; - } + if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES) + return pci_irq_table[(slot + pin - 2) % 4]; - return irq; + return -1; } struct hw_pci ixdp425_pci __initdata = { @@ -72,4 +76,3 @@ int __init ixdp425_pci_init(void) } subsys_initcall(ixdp425_pci_init); - diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index f4a0c1bc133111e7674f240546734803085a2d99..bbb768988845dae9dc5910acf3f245ba786a0ec4 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-ixp4xx/ixdp425-setup.c * - * IXDP425/IXCDP1100 board-setup + * IXDP425/IXCDP1100 board-setup * * Copyright (C) 2003-2005 MontaVista Software, Inc. * @@ -21,7 +21,6 @@ #include #include #include - #include #include #include @@ -31,6 +30,15 @@ #include #include +#define IXDP425_SDA_PIN 7 +#define IXDP425_SCL_PIN 6 + +/* NAND Flash pins */ +#define IXDP425_NAND_NCE_PIN 12 + +#define IXDP425_NAND_CMD_BYTE 0x01 +#define IXDP425_NAND_ADDR_BYTE 0x02 + static struct flash_platform_data ixdp425_flash_data = { .map_name = "cfi_probe", .width = 2, diff --git a/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/arch/arm/mach-ixp4xx/ixp4xx_npe.c index 47ac69c7ec7891a6bbbd07765fa264210746df35..e8bb257781661da9424208d8f79862cc088e377f 100644 --- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c +++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c @@ -665,7 +665,7 @@ err: } -struct npe *npe_request(int id) +struct npe *npe_request(unsigned id) { if (id < NPE_COUNT) if (npe_tab[id].valid) diff --git a/arch/arm/mach-ixp4xx/nas100d-pci.c b/arch/arm/mach-ixp4xx/nas100d-pci.c index 1088426fdcee3054a1907fc6506573cff4adf687..d0cea34cf61e4987d164895eee0b2208af004b0b 100644 --- a/arch/arm/mach-ixp4xx/nas100d-pci.c +++ b/arch/arm/mach-ixp4xx/nas100d-pci.c @@ -18,37 +18,42 @@ #include #include #include - #include #include +#define MAX_DEV 3 +#define IRQ_LINES 3 + +/* PCI controller GPIO to IRQ pin mappings */ +#define INTA 11 +#define INTB 10 +#define INTC 9 +#define INTD 8 +#define INTE 7 + void __init nas100d_pci_preinit(void) { - set_irq_type(IRQ_NAS100D_PCI_INTA, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_NAS100D_PCI_INTB, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_NAS100D_PCI_INTC, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_NAS100D_PCI_INTD, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_NAS100D_PCI_INTE, IRQ_TYPE_LEVEL_LOW); - + set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTE), IRQ_TYPE_LEVEL_LOW); ixp4xx_pci_preinit(); } static int __init nas100d_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - static int pci_irq_table[NAS100D_PCI_MAX_DEV][NAS100D_PCI_IRQ_LINES] = - { - { IRQ_NAS100D_PCI_INTA, -1, -1 }, - { IRQ_NAS100D_PCI_INTB, -1, -1 }, - { IRQ_NAS100D_PCI_INTC, IRQ_NAS100D_PCI_INTD, IRQ_NAS100D_PCI_INTE }, + static int pci_irq_table[MAX_DEV][IRQ_LINES] = { + { IXP4XX_GPIO_IRQ(INTA), -1, -1 }, + { IXP4XX_GPIO_IRQ(INTB), -1, -1 }, + { IXP4XX_GPIO_IRQ(INTC), IXP4XX_GPIO_IRQ(INTD), + IXP4XX_GPIO_IRQ(INTE) }, }; - int irq = -1; - - if (slot >= 1 && slot <= NAS100D_PCI_MAX_DEV && - pin >= 1 && pin <= NAS100D_PCI_IRQ_LINES) - irq = pci_irq_table[slot-1][pin-1]; + if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES) + return pci_irq_table[slot - 1][pin - 1]; - return irq; + return -1; } struct hw_pci __initdata nas100d_pci = { diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c index 921c947b5b6b33f170f279525cf8e87dfc0697a4..e3ee880aa1e687ae3df927bddaf95de4206710c4 100644 --- a/arch/arm/mach-ixp4xx/nas100d-setup.c +++ b/arch/arm/mach-ixp4xx/nas100d-setup.c @@ -29,12 +29,26 @@ #include #include #include - #include #include #include #include +#define NAS100D_SDA_PIN 5 +#define NAS100D_SCL_PIN 6 + +/* Buttons */ +#define NAS100D_PB_GPIO 14 /* power button */ +#define NAS100D_RB_GPIO 4 /* reset button */ + +/* Power control */ +#define NAS100D_PO_GPIO 12 /* power off */ + +/* LEDs */ +#define NAS100D_LED_WLAN_GPIO 0 +#define NAS100D_LED_DISK_GPIO 3 +#define NAS100D_LED_PWR_GPIO 15 + static struct flash_platform_data nas100d_flash_data = { .map_name = "cfi_probe", .width = 2, diff --git a/arch/arm/mach-ixp4xx/nslu2-pci.c b/arch/arm/mach-ixp4xx/nslu2-pci.c index 4429b8448b61caa0d9a106738caa920f5f70c755..1eb5a90470bc58e031d29942dcdfb66955352799 100644 --- a/arch/arm/mach-ixp4xx/nslu2-pci.c +++ b/arch/arm/mach-ixp4xx/nslu2-pci.c @@ -18,35 +18,38 @@ #include #include #include - #include #include +#define MAX_DEV 3 +#define IRQ_LINES 3 + +/* PCI controller GPIO to IRQ pin mappings */ +#define INTA 11 +#define INTB 10 +#define INTC 9 +#define INTD 8 + void __init nslu2_pci_preinit(void) { - set_irq_type(IRQ_NSLU2_PCI_INTA, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_NSLU2_PCI_INTB, IRQ_TYPE_LEVEL_LOW); - set_irq_type(IRQ_NSLU2_PCI_INTC, IRQ_TYPE_LEVEL_LOW); - + set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW); + set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW); ixp4xx_pci_preinit(); } static int __init nslu2_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - static int pci_irq_table[NSLU2_PCI_IRQ_LINES] = { - IRQ_NSLU2_PCI_INTA, - IRQ_NSLU2_PCI_INTB, - IRQ_NSLU2_PCI_INTC, + static int pci_irq_table[IRQ_LINES] = { + IXP4XX_GPIO_IRQ(INTA), + IXP4XX_GPIO_IRQ(INTB), + IXP4XX_GPIO_IRQ(INTC), }; - int irq = -1; - - if (slot >= 1 && slot <= NSLU2_PCI_MAX_DEV && - pin >= 1 && pin <= NSLU2_PCI_IRQ_LINES) { - irq = pci_irq_table[(slot + pin - 2) % NSLU2_PCI_IRQ_LINES]; - } + if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES) + return pci_irq_table[(slot + pin - 2) % IRQ_LINES]; - return irq; + return -1; } struct hw_pci __initdata nslu2_pci = { diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c index ff6a08d02cc42e8b050c3c91eced3b490ec92877..c14e0034be4b42b134175d4614a764db59f04ec8 100644 --- a/arch/arm/mach-ixp4xx/nslu2-setup.c +++ b/arch/arm/mach-ixp4xx/nslu2-setup.c @@ -26,13 +26,32 @@ #include #include #include - #include #include #include #include #include +#define NSLU2_SDA_PIN 7 +#define NSLU2_SCL_PIN 6 + +/* NSLU2 Timer */ +#define NSLU2_FREQ 66000000 + +/* Buttons */ +#define NSLU2_PB_GPIO 5 /* power button */ +#define NSLU2_PO_GPIO 8 /* power off */ +#define NSLU2_RB_GPIO 12 /* reset button */ + +/* Buzzer */ +#define NSLU2_GPIO_BUZZ 4 + +/* LEDs */ +#define NSLU2_LED_RED_GPIO 0 +#define NSLU2_LED_GRN_GPIO 1 +#define NSLU2_LED_DISK1_GPIO 3 +#define NSLU2_LED_DISK2_GPIO 2 + static struct flash_platform_data nslu2_flash_data = { .map_name = "cfi_probe", .width = 2, diff --git a/arch/arm/mach-lh7a40x/clocks.c b/arch/arm/mach-lh7a40x/clocks.c index 6182f5410b4de466a88b6da43f72050463363411..fcaf876f19b6617dc25495885a933cae0b2baee0 100644 --- a/arch/arm/mach-lh7a40x/clocks.c +++ b/arch/arm/mach-lh7a40x/clocks.c @@ -7,8 +7,6 @@ * version 2 as published by the Free Software Foundation. * */ - -#include #include #include #include @@ -31,12 +29,6 @@ struct clk { #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; diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index d140abca690afdee1a0c78a0a288ec545312f3f2..f780086befd78697d16da2654758270dd75bd1d6 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -3,6 +3,30 @@ if ARCH_MSM comment "MSM Board Type" depends on ARCH_MSM +config MSM_DEBUG_UART + int + default 1 if MSM_DEBUG_UART1 + default 2 if MSM_DEBUG_UART2 + default 3 if MSM_DEBUG_UART3 + +choice + prompt "Debug UART" + + default MSM_DEBUG_UART_NONE + + config MSM_DEBUG_UART_NONE + bool "None" + + config MSM_DEBUG_UART1 + bool "UART1" + + config MSM_DEBUG_UART2 + bool "UART2" + + config MSM_DEBUG_UART3 + bool "UART3" +endchoice + config MACH_HALIBUT depends on ARCH_MSM default y @@ -10,4 +34,10 @@ config MACH_HALIBUT help Support for the Qualcomm SURF7201A eval board. +config MACH_TROUT + default y + bool "HTC Dream (aka trout)" + help + Support for the HTC Dream, T-Mobile G1, Android ADP1 devices. + endif diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 1aa47001aa3b065b1b0d4f3a5387a0447bda5cb0..91e6f5c95dc161806e7a6199ef38727c5b0a4563 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -6,3 +6,4 @@ obj-y += clock.o clock-7x01a.o obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o +obj-$(CONFIG_MACH_TROUT) += board-dream.o diff --git a/arch/arm/mach-msm/board-dream.c b/arch/arm/mach-msm/board-dream.c new file mode 100644 index 0000000000000000000000000000000000000000..21afa85131687d2577860713737d69dc63a62273 --- /dev/null +++ b/arch/arm/mach-msm/board-dream.c @@ -0,0 +1,93 @@ +/* linux/arch/arm/mach-msm/board-dream.c + * + * Copyright (C) 2009 Google, Inc. + * Author: Brian Swetland + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "devices.h" +#include "board-dream.h" + +static struct platform_device *devices[] __initdata = { + &msm_device_uart3, + &msm_device_smd, + &msm_device_nand, + &msm_device_hsusb, + &msm_device_i2c, +}; + +extern struct sys_timer msm_timer; + +static void __init trout_init_irq(void) +{ + msm_init_irq(); +} + +static void __init trout_fixup(struct machine_desc *desc, struct tag *tags, + char **cmdline, struct meminfo *mi) +{ + mi->nr_banks = 1; + mi->bank[0].start = PHYS_OFFSET; + mi->bank[0].node = PHYS_TO_NID(PHYS_OFFSET); + mi->bank[0].size = (101*1024*1024); +} + +static void __init trout_init(void) +{ + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +static struct map_desc trout_io_desc[] __initdata = { + { + .virtual = TROUT_CPLD_BASE, + .pfn = __phys_to_pfn(TROUT_CPLD_START), + .length = TROUT_CPLD_SIZE, + .type = MT_DEVICE_NONSHARED + } +}; + +static void __init trout_map_io(void) +{ + msm_map_common_io(); + iotable_init(trout_io_desc, ARRAY_SIZE(trout_io_desc)); + +#ifdef CONFIG_MSM_DEBUG_UART3 + /* route UART3 to the "H2W" extended usb connector */ + writeb(0x80, TROUT_CPLD_BASE + 0x00); +#endif + + msm_clock_init(); +} + +MACHINE_START(TROUT, "HTC Dream") + .phys_io = MSM_DEBUG_UART_PHYS, + .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc, + .boot_params = 0x10000100, + .fixup = trout_fixup, + .map_io = trout_map_io, + .init_irq = trout_init_irq, + .init_machine = trout_init, + .timer = &msm_timer, +MACHINE_END diff --git a/arch/arm/mach-msm/board-dream.h b/arch/arm/mach-msm/board-dream.h new file mode 100644 index 0000000000000000000000000000000000000000..4f345a5a0a61c7a0cd223a996e07b8650cddd52a --- /dev/null +++ b/arch/arm/mach-msm/board-dream.h @@ -0,0 +1,5 @@ + +#define TROUT_CPLD_BASE 0xE8100000 +#define TROUT_CPLD_START 0x98000000 +#define TROUT_CPLD_SIZE SZ_4K + diff --git a/arch/arm/mach-msm/include/mach/debug-macro.S b/arch/arm/mach-msm/include/mach/debug-macro.S index 1db3c97dbc49e4738d386396a5db3e6169cb7785..d48747ebcd3dc64be6df5bbd0409a5e6705f43bf 100644 --- a/arch/arm/mach-msm/include/mach/debug-macro.S +++ b/arch/arm/mach-msm/include/mach/debug-macro.S @@ -14,15 +14,18 @@ * */ + + #include #include +#ifdef CONFIG_MSM_DEBUG_UART .macro addruart,rx @ see if the MMU is enabled and select appropriate base address mrc p15, 0, \rx, c1, c0 tst \rx, #1 - ldreq \rx, =MSM_UART1_PHYS - movne \rx, #0 + ldreq \rx, =MSM_DEBUG_UART_PHYS + ldrne \rx, =MSM_DEBUG_UART_BASE .endm .macro senduart,rd,rx @@ -32,13 +35,20 @@ .macro waituart,rd,rx @ wait for TX_READY - teq \rx, #0 - bne 2f -1: ldr \rd, [\rx, #0x08] +1001: ldr \rd, [\rx, #0x08] tst \rd, #0x04 - beq 1b -2: + beq 1001b + .endm +#else + .macro addruart,rx + .endm + + .macro senduart,rd,rx + .endm + + .macro waituart,rd,rx .endm +#endif .macro busyuart,rd,rx .endm diff --git a/arch/arm/mach-msm/include/mach/mmc.h b/arch/arm/mach-msm/include/mach/mmc.h new file mode 100644 index 0000000000000000000000000000000000000000..0ecf25426284b1c534e4bbf9992eabee8c90d6aa --- /dev/null +++ b/arch/arm/mach-msm/include/mach/mmc.h @@ -0,0 +1,26 @@ +/* + * arch/arm/include/asm/mach/mmc.h + */ +#ifndef ASMARM_MACH_MMC_H +#define ASMARM_MACH_MMC_H + +#include +#include +#include + +struct embedded_sdio_data { + struct sdio_cis cis; + struct sdio_cccr cccr; + struct sdio_embedded_func *funcs; + int num_funcs; +}; + +struct mmc_platform_data { + unsigned int ocr_mask; /* available voltages */ + u32 (*translate_vdd)(struct device *, unsigned int); + unsigned int (*status)(struct device *); + struct embedded_sdio_data *embedded_sdio; + int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id); +}; + +#endif diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h index 2f7b4c8620d95f257e6c845f541ce4a42a4abea7..9dae1a98c77afdf8acf105e96828dda14b13fca9 100644 --- a/arch/arm/mach-msm/include/mach/msm_iomap.h +++ b/arch/arm/mach-msm/include/mach/msm_iomap.h @@ -84,6 +84,18 @@ #define MSM_UART3_PHYS 0xA9C00000 #define MSM_UART3_SIZE SZ_4K +#ifdef CONFIG_MSM_DEBUG_UART +#define MSM_DEBUG_UART_BASE 0xE1000000 +#if CONFIG_MSM_DEBUG_UART == 1 +#define MSM_DEBUG_UART_PHYS MSM_UART1_PHYS +#elif CONFIG_MSM_DEBUG_UART == 2 +#define MSM_DEBUG_UART_PHYS MSM_UART2_PHYS +#elif CONFIG_MSM_DEBUG_UART == 3 +#define MSM_DEBUG_UART_PHYS MSM_UART3_PHYS +#endif +#define MSM_DEBUG_UART_SIZE SZ_4K +#endif + #define MSM_SDC1_PHYS 0xA0400000 #define MSM_SDC1_SIZE SZ_4K diff --git a/arch/arm/mach-msm/include/mach/uncompress.h b/arch/arm/mach-msm/include/mach/uncompress.h index 026e8955ace9d4c47cc53bf1118d54ba862a3bc6..d94292c29d8e27ed6a736a8bb24b7d8f640d3dd0 100644 --- a/arch/arm/mach-msm/include/mach/uncompress.h +++ b/arch/arm/mach-msm/include/mach/uncompress.h @@ -16,9 +16,16 @@ #ifndef __ASM_ARCH_MSM_UNCOMPRESS_H #include "hardware.h" +#include "linux/io.h" +#include "mach/msm_iomap.h" static void putc(int c) { +#if defined(MSM_DEBUG_UART_PHYS) + unsigned base = MSM_DEBUG_UART_PHYS; + while (!(readl(base + 0x08) & 0x04)) ; + writel(c, base + 0x0c); +#endif } static inline void flush(void) diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c index 6e7692ff6f2cb1a7416a8b12c44d0aed0748f3ae..1c5e7dac086f1892d9a6c831f8d5cf99dee90453 100644 --- a/arch/arm/mach-msm/io.c +++ b/arch/arm/mach-msm/io.c @@ -42,6 +42,9 @@ static struct map_desc msm_io_desc[] __initdata = { MSM_DEVICE(GPIO1), MSM_DEVICE(GPIO2), MSM_DEVICE(CLK_CTL), +#ifdef CONFIG_MSM_DEBUG_UART + MSM_DEVICE(DEBUG_UART), +#endif { .virtual = (unsigned long) MSM_SHARED_RAM_BASE, .pfn = __phys_to_pfn(MSM_SHARED_RAM_PHYS), diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index 87e539aa8ad90d3587bd93fc5e9375ff089f0640..9ce17f13d3f1da961bda9d18255b64e51e326f1b 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -3,7 +3,8 @@ # # Common support -obj-y := io.o id.o sram.o clock.o irq.o mux.o serial.o devices.o +obj-y := io.o id.o sram.o irq.o mux.o serial.o devices.o +obj-y += clock.o clock_data.o opp_data.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o @@ -17,6 +18,9 @@ obj-$(CONFIG_PM) += pm.o sleep.o obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o mailbox_mach-objs := mailbox.o +i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o +obj-y += $(i2c-omap-m) $(i2c-omap-y) + led-y := leds.o # Specific board support @@ -48,3 +52,7 @@ led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o led-$(CONFIG_MACH_OMAP_OSK) += leds-osk.o obj-$(CONFIG_LEDS) += $(led-y) + +ifneq ($(CONFIG_FB_OMAP),) +obj-y += lcd_dma.o +endif diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c index f4b72c1654f5ee7fc114423333cff0ca0b544c1d..7e70c3c08da63b584889ca6b7655859e3539602b 100644 --- a/arch/arm/mach-omap1/board-fsample.c +++ b/arch/arm/mach-omap1/board-fsample.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -100,6 +100,12 @@ static int fsample_keymap[] = { 0 }; +static struct smc91x_platdata smc91x_info = { + .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, + .leda = RPC_LED_100_10, + .ledb = RPC_LED_TX_RX, +}; + static struct resource smc91x_resources[] = { [0] = { .start = H2P2_DBG_FPGA_ETHR_START, /* Physical */ @@ -167,8 +173,40 @@ static struct platform_device nor_device = { .resource = &nor_resource, }; -static struct omap_nand_platform_data nand_data = { - .options = NAND_SAMSUNG_LP_OPTIONS, +static void nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *this = mtd->priv; + unsigned long mask; + + if (cmd == NAND_CMD_NONE) + return; + + mask = (ctrl & NAND_CLE) ? 0x02 : 0; + if (ctrl & NAND_ALE) + mask |= 0x04; + writeb(cmd, (unsigned long)this->IO_ADDR_W | mask); +} + +#define FSAMPLE_NAND_RB_GPIO_PIN 62 + +static int nand_dev_ready(struct mtd_info *mtd) +{ + return gpio_get_value(FSAMPLE_NAND_RB_GPIO_PIN); +} + +static const char *part_probes[] = { "cmdlinepart", NULL }; + +static struct platform_nand_data nand_data = { + .chip = { + .nr_chips = 1, + .chip_offset = 0, + .options = NAND_SAMSUNG_LP_OPTIONS, + .part_probe_types = part_probes, + }, + .ctrl = { + .cmd_ctrl = nand_cmd_ctl, + .dev_ready = nand_dev_ready, + }, }; static struct resource nand_resource = { @@ -178,7 +216,7 @@ static struct resource nand_resource = { }; static struct platform_device nand_device = { - .name = "omapnand", + .name = "gen_nand", .id = 0, .dev = { .platform_data = &nand_data, @@ -190,6 +228,9 @@ static struct platform_device nand_device = { static struct platform_device smc91x_device = { .name = "smc91x", .id = 0, + .dev = { + .platform_data = &smc91x_info, + }, .num_resources = ARRAY_SIZE(smc91x_resources), .resource = smc91x_resources, }; @@ -233,13 +274,6 @@ static struct platform_device *devices[] __initdata = { &lcd_device, }; -#define P2_NAND_RB_GPIO_PIN 62 - -static int nand_dev_ready(struct omap_nand_platform_data *data) -{ - return gpio_get_value(P2_NAND_RB_GPIO_PIN); -} - static struct omap_lcd_config fsample_lcd_config __initdata = { .ctrl_name = "internal", }; @@ -250,9 +284,9 @@ static struct omap_board_config_kernel fsample_config[] = { static void __init omap_fsample_init(void) { - if (gpio_request(P2_NAND_RB_GPIO_PIN, "NAND ready") < 0) + if (gpio_request(FSAMPLE_NAND_RB_GPIO_PIN, "NAND ready") < 0) BUG(); - nand_data.dev_ready = nand_dev_ready; + gpio_direction_input(FSAMPLE_NAND_RB_GPIO_PIN); omap_cfg_reg(L3_1610_FLASH_CS2B_OE); omap_cfg_reg(M8_1610_FLASH_CS2B_WE); diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index 89ba8ec4bbf4679102e56971fa1069775f2bf632..fa7cecea19f92800fa520248e074582ff24c6687 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -40,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -179,11 +179,43 @@ static struct mtd_partition h2_nand_partitions[] = { }, }; -/* dip switches control NAND chip access: 8 bit, 16 bit, or neither */ -static struct omap_nand_platform_data h2_nand_data = { - .options = NAND_SAMSUNG_LP_OPTIONS, - .parts = h2_nand_partitions, - .nr_parts = ARRAY_SIZE(h2_nand_partitions), +static void h2_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *this = mtd->priv; + unsigned long mask; + + if (cmd == NAND_CMD_NONE) + return; + + mask = (ctrl & NAND_CLE) ? 0x02 : 0; + if (ctrl & NAND_ALE) + mask |= 0x04; + writeb(cmd, (unsigned long)this->IO_ADDR_W | mask); +} + +#define H2_NAND_RB_GPIO_PIN 62 + +static int h2_nand_dev_ready(struct mtd_info *mtd) +{ + return gpio_get_value(H2_NAND_RB_GPIO_PIN); +} + +static const char *h2_part_probes[] = { "cmdlinepart", NULL }; + +struct platform_nand_data h2_nand_platdata = { + .chip = { + .nr_chips = 1, + .chip_offset = 0, + .nr_partitions = ARRAY_SIZE(h2_nand_partitions), + .partitions = h2_nand_partitions, + .options = NAND_SAMSUNG_LP_OPTIONS, + .part_probe_types = h2_part_probes, + }, + .ctrl = { + .cmd_ctrl = h2_nand_cmd_ctl, + .dev_ready = h2_nand_dev_ready, + + }, }; static struct resource h2_nand_resource = { @@ -191,15 +223,21 @@ static struct resource h2_nand_resource = { }; static struct platform_device h2_nand_device = { - .name = "omapnand", + .name = "gen_nand", .id = 0, .dev = { - .platform_data = &h2_nand_data, + .platform_data = &h2_nand_platdata, }, .num_resources = 1, .resource = &h2_nand_resource, }; +static struct smc91x_platdata h2_smc91x_info = { + .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, + .leda = RPC_LED_100_10, + .ledb = RPC_LED_TX_RX, +}; + static struct resource h2_smc91x_resources[] = { [0] = { .start = OMAP1610_ETHR_START, /* Physical */ @@ -216,6 +254,9 @@ static struct resource h2_smc91x_resources[] = { static struct platform_device h2_smc91x_device = { .name = "smc91x", .id = 0, + .dev = { + .platform_data = &h2_smc91x_info, + }, .num_resources = ARRAY_SIZE(h2_smc91x_resources), .resource = h2_smc91x_resources, }; @@ -368,8 +409,6 @@ static struct omap_board_config_kernel h2_config[] __initdata = { { OMAP_TAG_LCD, &h2_lcd_config }, }; -#define H2_NAND_RB_GPIO_PIN 62 - static void __init h2_init(void) { /* Here we assume the NOR boot config: NOR on CS3 (possibly swapped diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index f5cc0a7305245ebd5d31c412d2c63c9c0b630897..6a7f9c391cf1ea3c51fc68a3bf23ac4be0a58061 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -42,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -181,11 +181,43 @@ static struct mtd_partition nand_partitions[] = { }, }; -/* dip switches control NAND chip access: 8 bit, 16 bit, or neither */ -static struct omap_nand_platform_data nand_data = { - .options = NAND_SAMSUNG_LP_OPTIONS, - .parts = nand_partitions, - .nr_parts = ARRAY_SIZE(nand_partitions), +static void nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *this = mtd->priv; + unsigned long mask; + + if (cmd == NAND_CMD_NONE) + return; + + mask = (ctrl & NAND_CLE) ? 0x02 : 0; + if (ctrl & NAND_ALE) + mask |= 0x04; + writeb(cmd, (unsigned long)this->IO_ADDR_W | mask); +} + +#define H3_NAND_RB_GPIO_PIN 10 + +static int nand_dev_ready(struct mtd_info *mtd) +{ + return gpio_get_value(H3_NAND_RB_GPIO_PIN); +} + +static const char *part_probes[] = { "cmdlinepart", NULL }; + +struct platform_nand_data nand_platdata = { + .chip = { + .nr_chips = 1, + .chip_offset = 0, + .nr_partitions = ARRAY_SIZE(nand_partitions), + .partitions = nand_partitions, + .options = NAND_SAMSUNG_LP_OPTIONS, + .part_probe_types = part_probes, + }, + .ctrl = { + .cmd_ctrl = nand_cmd_ctl, + .dev_ready = nand_dev_ready, + + }, }; static struct resource nand_resource = { @@ -193,15 +225,21 @@ static struct resource nand_resource = { }; static struct platform_device nand_device = { - .name = "omapnand", + .name = "gen_nand", .id = 0, .dev = { - .platform_data = &nand_data, + .platform_data = &nand_platdata, }, .num_resources = 1, .resource = &nand_resource, }; +static struct smc91x_platdata smc91x_info = { + .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, + .leda = RPC_LED_100_10, + .ledb = RPC_LED_TX_RX, +}; + static struct resource smc91x_resources[] = { [0] = { .start = OMAP1710_ETHR_START, /* Physical */ @@ -218,6 +256,9 @@ static struct resource smc91x_resources[] = { static struct platform_device smc91x_device = { .name = "smc91x", .id = 0, + .dev = { + .platform_data = &smc91x_info, + }, .num_resources = ARRAY_SIZE(smc91x_resources), .resource = smc91x_resources, }; @@ -332,13 +373,6 @@ static struct i2c_board_info __initdata h3_i2c_board_info[] = { }, }; -#define H3_NAND_RB_GPIO_PIN 10 - -static int nand_dev_ready(struct omap_nand_platform_data *data) -{ - return gpio_get_value(H3_NAND_RB_GPIO_PIN); -} - static void __init h3_init(void) { /* Here we assume the NOR boot config: NOR on CS3 (possibly swapped @@ -356,7 +390,7 @@ static void __init h3_init(void) nand_resource.end += SZ_4K - 1; if (gpio_request(H3_NAND_RB_GPIO_PIN, "NAND ready") < 0) BUG(); - nand_data.dev_ready = nand_dev_ready; + gpio_direction_input(H3_NAND_RB_GPIO_PIN); /* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */ /* GPIO10 pullup/down register, Enable pullup on GPIO10 */ diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c index 5f28a5ceacacf65d57dfdfabc12dda1c9c06e557..e36639f661509795fae89cded8e8a1a0d9a6119e 100644 --- a/arch/arm/mach-omap1/board-htcherald.c +++ b/arch/arm/mach-omap1/board-htcherald.c @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -140,6 +141,15 @@ static struct platform_device kp_device = { .resource = kp_resources, }; +/* USB Device */ +static struct omap_usb_config htcherald_usb_config __initdata = { + .otg = 0, + .register_host = 0, + .register_dev = 1, + .hmc_mode = 4, + .pins[0] = 2, +}; + /* LCD Device resources */ static struct platform_device lcd_device = { .name = "lcd_htcherald", @@ -214,6 +224,57 @@ static void __init htcherald_disable_watchdog(void) } } +#define HTCHERALD_GPIO_USB_EN1 33 +#define HTCHERALD_GPIO_USB_EN2 73 +#define HTCHERALD_GPIO_USB_DM 35 +#define HTCHERALD_GPIO_USB_DP 36 + +static void __init htcherald_usb_enable(void) +{ + unsigned int tries = 20; + unsigned int value = 0; + + /* Request the GPIOs we need to control here */ + if (gpio_request(HTCHERALD_GPIO_USB_EN1, "herald_usb") < 0) + goto err1; + + if (gpio_request(HTCHERALD_GPIO_USB_EN2, "herald_usb") < 0) + goto err2; + + if (gpio_request(HTCHERALD_GPIO_USB_DM, "herald_usb") < 0) + goto err3; + + if (gpio_request(HTCHERALD_GPIO_USB_DP, "herald_usb") < 0) + goto err4; + + /* force USB_EN GPIO to 0 */ + do { + /* output low */ + gpio_direction_output(HTCHERALD_GPIO_USB_EN1, 0); + } while ((value = gpio_get_value(HTCHERALD_GPIO_USB_EN1)) == 1 && + --tries); + + if (value == 1) + printk(KERN_WARNING "Unable to reset USB, trying to continue\n"); + + gpio_direction_output(HTCHERALD_GPIO_USB_EN2, 0); /* output low */ + gpio_direction_input(HTCHERALD_GPIO_USB_DM); /* input */ + gpio_direction_input(HTCHERALD_GPIO_USB_DP); /* input */ + + goto done; + +err4: + gpio_free(HTCHERALD_GPIO_USB_DM); +err3: + gpio_free(HTCHERALD_GPIO_USB_EN2); +err2: + gpio_free(HTCHERALD_GPIO_USB_EN1); +err1: + printk(KERN_ERR "Unabled to request GPIO for USB\n"); +done: + printk(KERN_INFO "USB setup complete.\n"); +} + static void __init htcherald_init(void) { printk(KERN_INFO "HTC Herald init.\n"); @@ -225,6 +286,9 @@ static void __init htcherald_init(void) platform_add_devices(devices, ARRAY_SIZE(devices)); htcherald_disable_watchdog(); + + htcherald_usb_enable(); + omap_usb_init(&htcherald_usb_config); } static void __init htcherald_init_irq(void) diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index cf0fdb9c182f9a7b0903708b77eddc13a3793380..2133b006f6a3fe88fe1bd026439e53ea5a9d7179 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -142,6 +143,11 @@ static struct platform_device innovator_kp_device = { .resource = innovator_kp_resources, }; +static struct smc91x_platdata innovator_smc91x_info = { + .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, + .leda = RPC_LED_100_10, + .ledb = RPC_LED_TX_RX, +}; #ifdef CONFIG_ARCH_OMAP15XX @@ -175,6 +181,9 @@ static struct resource innovator1510_smc91x_resources[] = { static struct platform_device innovator1510_smc91x_device = { .name = "smc91x", .id = 0, + .dev = { + .platform_data = &innovator_smc91x_info, + }, .num_resources = ARRAY_SIZE(innovator1510_smc91x_resources), .resource = innovator1510_smc91x_resources, }; @@ -241,6 +250,9 @@ static struct resource innovator1610_smc91x_resources[] = { static struct platform_device innovator1610_smc91x_device = { .name = "smc91x", .id = 0, + .dev = { + .platform_data = &innovator_smc91x_info, + }, .num_resources = ARRAY_SIZE(innovator1610_smc91x_resources), .resource = innovator1610_smc91x_resources, }; diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index 5a275bab2dfe392a7e2a8bce944cb443c2846764..71e1a3fad0ead110b7947e555af8c652da261695 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -32,7 +33,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index 50c92c13e48aced34e8fea2e71ca66dc7ba6f7ae..ccea4f448e9a18e8d367c50153ef3871b083983e 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -115,6 +116,12 @@ static struct platform_device osk5912_flash_device = { .resource = &osk_flash_resource, }; +static struct smc91x_platdata osk5912_smc91x_info = { + .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, + .leda = RPC_LED_100_10, + .ledb = RPC_LED_TX_RX, +}; + static struct resource osk5912_smc91x_resources[] = { [0] = { .start = OMAP_OSK_ETHR_START, /* Physical */ @@ -131,6 +138,9 @@ static struct resource osk5912_smc91x_resources[] = { static struct platform_device osk5912_smc91x_device = { .name = "smc91x", .id = -1, + .dev = { + .platform_data = &osk5912_smc91x_info, + }, .num_resources = ARRAY_SIZE(osk5912_smc91x_resources), .resource = osk5912_smc91x_resources, }; diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c index ca7df1e93efc7a245437bbfaa98ce0d9c5b37c5b..1387a4f15da9ddea32db967e32699be93d086353 100644 --- a/arch/arm/mach-omap1/board-perseus2.c +++ b/arch/arm/mach-omap1/board-perseus2.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -67,6 +67,12 @@ static int p2_keymap[] = { 0 }; +static struct smc91x_platdata smc91x_info = { + .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, + .leda = RPC_LED_100_10, + .ledb = RPC_LED_TX_RX, +}; + static struct resource smc91x_resources[] = { [0] = { .start = H2P2_DBG_FPGA_ETHR_START, /* Physical */ @@ -134,8 +140,40 @@ static struct platform_device nor_device = { .resource = &nor_resource, }; -static struct omap_nand_platform_data nand_data = { - .options = NAND_SAMSUNG_LP_OPTIONS, +static void nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *this = mtd->priv; + unsigned long mask; + + if (cmd == NAND_CMD_NONE) + return; + + mask = (ctrl & NAND_CLE) ? 0x02 : 0; + if (ctrl & NAND_ALE) + mask |= 0x04; + writeb(cmd, (unsigned long)this->IO_ADDR_W | mask); +} + +#define P2_NAND_RB_GPIO_PIN 62 + +static int nand_dev_ready(struct mtd_info *mtd) +{ + return gpio_get_value(P2_NAND_RB_GPIO_PIN); +} + +static const char *part_probes[] = { "cmdlinepart", NULL }; + +static struct platform_nand_data nand_data = { + .chip = { + .nr_chips = 1, + .chip_offset = 0, + .options = NAND_SAMSUNG_LP_OPTIONS, + .part_probe_types = part_probes, + }, + .ctrl = { + .cmd_ctrl = nand_cmd_ctl, + .dev_ready = nand_dev_ready, + }, }; static struct resource nand_resource = { @@ -145,7 +183,7 @@ static struct resource nand_resource = { }; static struct platform_device nand_device = { - .name = "omapnand", + .name = "gen_nand", .id = 0, .dev = { .platform_data = &nand_data, @@ -157,6 +195,9 @@ static struct platform_device nand_device = { static struct platform_device smc91x_device = { .name = "smc91x", .id = 0, + .dev = { + .platform_data = &smc91x_info, + }, .num_resources = ARRAY_SIZE(smc91x_resources), .resource = smc91x_resources, }; @@ -201,13 +242,6 @@ static struct platform_device *devices[] __initdata = { &lcd_device, }; -#define P2_NAND_RB_GPIO_PIN 62 - -static int nand_dev_ready(struct omap_nand_platform_data *data) -{ - return gpio_get_value(P2_NAND_RB_GPIO_PIN); -} - static struct omap_lcd_config perseus2_lcd_config __initdata = { .ctrl_name = "internal", }; @@ -220,7 +254,7 @@ static void __init omap_perseus2_init(void) { if (gpio_request(P2_NAND_RB_GPIO_PIN, "NAND ready") < 0) BUG(); - nand_data.dev_ready = nand_dev_ready; + gpio_direction_input(P2_NAND_RB_GPIO_PIN); omap_cfg_reg(L3_1610_FLASH_CS2B_OE); omap_cfg_reg(M8_1610_FLASH_CS2B_WE); diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index 35c75c1bd0aaaacf03eb3006fb6e504e5496e909..169183537997a70153edf212c2f08216631eea4d 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -106,6 +107,12 @@ static struct platform_device voiceblue_flash_device = { .resource = &voiceblue_flash_resource, }; +static struct smc91x_platdata voiceblue_smc91x_info = { + .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, + .leda = RPC_LED_100_10, + .ledb = RPC_LED_TX_RX, +}; + static struct resource voiceblue_smc91x_resources[] = { [0] = { .start = OMAP_CS2_PHYS + 0x300, @@ -122,6 +129,9 @@ static struct resource voiceblue_smc91x_resources[] = { static struct platform_device voiceblue_smc91x_device = { .name = "smc91x", .id = 0, + .dev = { + .platform_data = &voiceblue_smc91x_info, + }, .num_resources = ARRAY_SIZE(voiceblue_smc91x_resources), .resource = voiceblue_smc91x_resources, }; diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 42cbe203da36d6030f04807aed36025e8c63e54b..2ba9ab95373114507acd51460b0406cb59be8b2b 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/mach-omap1/clock.c * - * Copyright (C) 2004 - 2005 Nokia corporation + * Copyright (C) 2004 - 2005, 2009 Nokia corporation * Written by Tuukka Tikkanen * * Modified to use omap shared clock framework by @@ -26,12 +26,17 @@ #include #include #include - -static const struct clkops clkops_generic; -static const struct clkops clkops_uart; -static const struct clkops clkops_dspck; +#include #include "clock.h" +#include "opp.h" + +__u32 arm_idlect1_mask; +struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p; + +/*------------------------------------------------------------------------- + * Omap1 specific clock functions + *-------------------------------------------------------------------------*/ static int clk_omap1_dummy_enable(struct clk *clk) { @@ -42,134 +47,24 @@ static void clk_omap1_dummy_disable(struct clk *clk) { } -static const struct clkops clkops_dummy = { - .enable = clk_omap1_dummy_enable, - .disable = clk_omap1_dummy_disable, -}; - -static struct clk dummy_ck = { - .name = "dummy", - .ops = &clkops_dummy, - .flags = RATE_FIXED, -}; - -struct omap_clk { - u32 cpu; - struct clk_lookup lk; +const struct clkops clkops_dummy = { + .enable = clk_omap1_dummy_enable, + .disable = clk_omap1_dummy_disable, }; -#define CLK(dev, con, ck, cp) \ - { \ - .cpu = cp, \ - .lk = { \ - .dev_id = dev, \ - .con_id = con, \ - .clk = ck, \ - }, \ - } - -#define CK_310 (1 << 0) -#define CK_7XX (1 << 1) -#define CK_1510 (1 << 2) -#define CK_16XX (1 << 3) - -static struct omap_clk omap_clks[] = { - /* non-ULPD clocks */ - CLK(NULL, "ck_ref", &ck_ref, CK_16XX | CK_1510 | CK_310 | CK_7XX), - CLK(NULL, "ck_dpll1", &ck_dpll1, CK_16XX | CK_1510 | CK_310), - /* CK_GEN1 clocks */ - CLK(NULL, "ck_dpll1out", &ck_dpll1out.clk, CK_16XX), - CLK(NULL, "ck_sossi", &sossi_ck, CK_16XX), - CLK(NULL, "arm_ck", &arm_ck, CK_16XX | CK_1510 | CK_310), - CLK(NULL, "armper_ck", &armper_ck.clk, CK_16XX | CK_1510 | CK_310), - CLK(NULL, "arm_gpio_ck", &arm_gpio_ck, CK_1510 | CK_310), - CLK(NULL, "armxor_ck", &armxor_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX), - CLK(NULL, "armtim_ck", &armtim_ck.clk, CK_16XX | CK_1510 | CK_310), - CLK("omap_wdt", "fck", &armwdt_ck.clk, CK_16XX | CK_1510 | CK_310), - CLK("omap_wdt", "ick", &armper_ck.clk, CK_16XX), - CLK("omap_wdt", "ick", &dummy_ck, CK_1510 | CK_310), - CLK(NULL, "arminth_ck", &arminth_ck1510, CK_1510 | CK_310), - CLK(NULL, "arminth_ck", &arminth_ck16xx, CK_16XX), - /* CK_GEN2 clocks */ - CLK(NULL, "dsp_ck", &dsp_ck, CK_16XX | CK_1510 | CK_310), - CLK(NULL, "dspmmu_ck", &dspmmu_ck, CK_16XX | CK_1510 | CK_310), - CLK(NULL, "dspper_ck", &dspper_ck, CK_16XX | CK_1510 | CK_310), - CLK(NULL, "dspxor_ck", &dspxor_ck, CK_16XX | CK_1510 | CK_310), - CLK(NULL, "dsptim_ck", &dsptim_ck, CK_16XX | CK_1510 | CK_310), - /* CK_GEN3 clocks */ - CLK(NULL, "tc_ck", &tc_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX), - CLK(NULL, "tipb_ck", &tipb_ck, CK_1510 | CK_310), - CLK(NULL, "l3_ocpi_ck", &l3_ocpi_ck, CK_16XX | CK_7XX), - CLK(NULL, "tc1_ck", &tc1_ck, CK_16XX), - CLK(NULL, "tc2_ck", &tc2_ck, CK_16XX), - CLK(NULL, "dma_ck", &dma_ck, CK_16XX | CK_1510 | CK_310), - CLK(NULL, "dma_lcdfree_ck", &dma_lcdfree_ck, CK_16XX), - CLK(NULL, "api_ck", &api_ck.clk, CK_16XX | CK_1510 | CK_310), - CLK(NULL, "lb_ck", &lb_ck.clk, CK_1510 | CK_310), - CLK(NULL, "rhea1_ck", &rhea1_ck, CK_16XX), - CLK(NULL, "rhea2_ck", &rhea2_ck, CK_16XX), - CLK(NULL, "lcd_ck", &lcd_ck_16xx, CK_16XX | CK_7XX), - CLK(NULL, "lcd_ck", &lcd_ck_1510.clk, CK_1510 | CK_310), - /* ULPD clocks */ - CLK(NULL, "uart1_ck", &uart1_1510, CK_1510 | CK_310), - CLK(NULL, "uart1_ck", &uart1_16xx.clk, CK_16XX), - CLK(NULL, "uart2_ck", &uart2_ck, CK_16XX | CK_1510 | CK_310), - CLK(NULL, "uart3_ck", &uart3_1510, CK_1510 | CK_310), - CLK(NULL, "uart3_ck", &uart3_16xx.clk, CK_16XX), - CLK(NULL, "usb_clko", &usb_clko, CK_16XX | CK_1510 | CK_310), - CLK(NULL, "usb_hhc_ck", &usb_hhc_ck1510, CK_1510 | CK_310), - CLK(NULL, "usb_hhc_ck", &usb_hhc_ck16xx, CK_16XX), - CLK(NULL, "usb_dc_ck", &usb_dc_ck, CK_16XX), - CLK(NULL, "usb_dc_ck", &usb_dc_ck7xx, CK_7XX), - CLK(NULL, "mclk", &mclk_1510, CK_1510 | CK_310), - CLK(NULL, "mclk", &mclk_16xx, CK_16XX), - CLK(NULL, "bclk", &bclk_1510, CK_1510 | CK_310), - CLK(NULL, "bclk", &bclk_16xx, CK_16XX), - CLK("mmci-omap.0", "fck", &mmc1_ck, CK_16XX | CK_1510 | CK_310), - CLK("mmci-omap.0", "fck", &mmc3_ck, CK_7XX), - CLK("mmci-omap.0", "ick", &armper_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX), - CLK("mmci-omap.1", "fck", &mmc2_ck, CK_16XX), - CLK("mmci-omap.1", "ick", &armper_ck.clk, CK_16XX), - /* Virtual clocks */ - CLK(NULL, "mpu", &virtual_ck_mpu, CK_16XX | CK_1510 | CK_310), - CLK("i2c_omap.1", "fck", &i2c_fck, CK_16XX | CK_1510 | CK_310), - CLK("i2c_omap.1", "ick", &i2c_ick, CK_16XX), - CLK("i2c_omap.1", "ick", &dummy_ck, CK_1510 | CK_310), - CLK("omap_uwire", "fck", &armxor_ck.clk, CK_16XX | CK_1510 | CK_310), - CLK("omap-mcbsp.1", "ick", &dspper_ck, CK_16XX), - CLK("omap-mcbsp.1", "ick", &dummy_ck, CK_1510 | CK_310), - CLK("omap-mcbsp.2", "ick", &armper_ck.clk, CK_16XX), - CLK("omap-mcbsp.2", "ick", &dummy_ck, CK_1510 | CK_310), - CLK("omap-mcbsp.3", "ick", &dspper_ck, CK_16XX), - CLK("omap-mcbsp.3", "ick", &dummy_ck, CK_1510 | CK_310), - CLK("omap-mcbsp.1", "fck", &dspxor_ck, CK_16XX | CK_1510 | CK_310), - CLK("omap-mcbsp.2", "fck", &armper_ck.clk, CK_16XX | CK_1510 | CK_310), - CLK("omap-mcbsp.3", "fck", &dspxor_ck, CK_16XX | CK_1510 | CK_310), -}; - -static int omap1_clk_enable_generic(struct clk * clk); -static int omap1_clk_enable(struct clk *clk); -static void omap1_clk_disable_generic(struct clk * clk); -static void omap1_clk_disable(struct clk *clk); - -__u32 arm_idlect1_mask; - -/*------------------------------------------------------------------------- - * Omap1 specific clock functions - *-------------------------------------------------------------------------*/ - -static unsigned long omap1_watchdog_recalc(struct clk *clk) +/* XXX can be replaced with a fixed_divisor_recalc */ +unsigned long omap1_watchdog_recalc(struct clk *clk) { return clk->parent->rate / 14; } -static unsigned long omap1_uart_recalc(struct clk *clk) +unsigned long omap1_uart_recalc(struct clk *clk) { unsigned int val = __raw_readl(clk->enable_reg); return val & clk->enable_bit ? 48000000 : 12000000; } -static unsigned long omap1_sossi_recalc(struct clk *clk) +unsigned long omap1_sossi_recalc(struct clk *clk) { u32 div = omap_readl(MOD_CONF_CTRL_1); @@ -179,64 +74,6 @@ static unsigned long omap1_sossi_recalc(struct clk *clk) return clk->parent->rate / div; } -static int omap1_clk_enable_dsp_domain(struct clk *clk) -{ - int retval; - - retval = omap1_clk_enable(&api_ck.clk); - if (!retval) { - retval = omap1_clk_enable_generic(clk); - omap1_clk_disable(&api_ck.clk); - } - - return retval; -} - -static void omap1_clk_disable_dsp_domain(struct clk *clk) -{ - if (omap1_clk_enable(&api_ck.clk) == 0) { - omap1_clk_disable_generic(clk); - omap1_clk_disable(&api_ck.clk); - } -} - -static const struct clkops clkops_dspck = { - .enable = &omap1_clk_enable_dsp_domain, - .disable = &omap1_clk_disable_dsp_domain, -}; - -static int omap1_clk_enable_uart_functional(struct clk *clk) -{ - int ret; - struct uart_clk *uclk; - - ret = omap1_clk_enable_generic(clk); - if (ret == 0) { - /* Set smart idle acknowledgement mode */ - uclk = (struct uart_clk *)clk; - omap_writeb((omap_readb(uclk->sysc_addr) & ~0x10) | 8, - uclk->sysc_addr); - } - - return ret; -} - -static void omap1_clk_disable_uart_functional(struct clk *clk) -{ - struct uart_clk *uclk; - - /* Set force idle acknowledgement mode */ - uclk = (struct uart_clk *)clk; - omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr); - - omap1_clk_disable_generic(clk); -} - -static const struct clkops clkops_uart = { - .enable = &omap1_clk_enable_uart_functional, - .disable = &omap1_clk_disable_uart_functional, -}; - static void omap1_clk_allow_idle(struct clk *clk) { struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk; @@ -344,7 +181,7 @@ static int calc_dsor_exp(struct clk *clk, unsigned long rate) return dsor_exp; } -static unsigned long omap1_ckctl_recalc(struct clk *clk) +unsigned long omap1_ckctl_recalc(struct clk *clk) { /* Calculate divisor encoded as 2-bit exponent */ int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset)); @@ -352,7 +189,7 @@ static unsigned long omap1_ckctl_recalc(struct clk *clk) return clk->parent->rate / dsor; } -static unsigned long omap1_ckctl_recalc_dsp_domain(struct clk *clk) +unsigned long omap1_ckctl_recalc_dsp_domain(struct clk *clk) { int dsor; @@ -363,28 +200,29 @@ static unsigned long omap1_ckctl_recalc_dsp_domain(struct clk *clk) * Note that DSP_CKCTL virt addr = phys addr, so * we must use __raw_readw() instead of omap_readw(). */ - omap1_clk_enable(&api_ck.clk); + omap1_clk_enable(api_ck_p); dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset)); - omap1_clk_disable(&api_ck.clk); + omap1_clk_disable(api_ck_p); return clk->parent->rate / dsor; } /* MPU virtual clock functions */ -static int omap1_select_table_rate(struct clk * clk, unsigned long rate) +int omap1_select_table_rate(struct clk *clk, unsigned long rate) { /* Find the highest supported frequency <= rate and switch to it */ struct mpu_rate * ptr; + unsigned long dpll1_rate, ref_rate; - if (clk != &virtual_ck_mpu) - return -EINVAL; + dpll1_rate = clk_get_rate(ck_dpll1_p); + ref_rate = clk_get_rate(ck_ref_p); - for (ptr = rate_table; ptr->rate; ptr++) { - if (ptr->xtal != ck_ref.rate) + for (ptr = omap1_rate_table; ptr->rate; ptr++) { + if (ptr->xtal != ref_rate) continue; /* DPLL1 cannot be reprogrammed without risking system crash */ - if (likely(ck_dpll1.rate!=0) && ptr->pll_rate != ck_dpll1.rate) + if (likely(dpll1_rate != 0) && ptr->pll_rate != dpll1_rate) continue; /* Can check only after xtal frequency check */ @@ -405,11 +243,13 @@ static int omap1_select_table_rate(struct clk * clk, unsigned long rate) else omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val); - ck_dpll1.rate = ptr->pll_rate; + /* XXX Do we need to recalculate the tree below DPLL1 at this point? */ + ck_dpll1_p->rate = ptr->pll_rate; + return 0; } -static int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate) +int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate) { int dsor_exp; u16 regval; @@ -429,7 +269,7 @@ static int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate) return 0; } -static long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate) +long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate) { int dsor_exp = calc_dsor_exp(clk, rate); if (dsor_exp < 0) @@ -439,7 +279,7 @@ static long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate) return clk->parent->rate / (1 << dsor_exp); } -static int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate) +int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate) { int dsor_exp; u16 regval; @@ -459,19 +299,19 @@ static int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate) return 0; } -static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate) +long omap1_round_to_table_rate(struct clk *clk, unsigned long rate) { /* Find the highest supported frequency <= rate */ struct mpu_rate * ptr; - long highest_rate; + long highest_rate; + unsigned long ref_rate; - if (clk != &virtual_ck_mpu) - return -EINVAL; + ref_rate = clk_get_rate(ck_ref_p); highest_rate = -EINVAL; - for (ptr = rate_table; ptr->rate; ptr++) { - if (ptr->xtal != ck_ref.rate) + for (ptr = omap1_rate_table; ptr->rate; ptr++) { + if (ptr->xtal != ref_rate) continue; highest_rate = ptr->rate; @@ -506,8 +346,8 @@ static unsigned calc_ext_dsor(unsigned long rate) return dsor; } -/* Only needed on 1510 */ -static int omap1_set_uart_rate(struct clk * clk, unsigned long rate) +/* XXX Only needed on 1510 */ +int omap1_set_uart_rate(struct clk *clk, unsigned long rate) { unsigned int val; @@ -525,7 +365,7 @@ static int omap1_set_uart_rate(struct clk * clk, unsigned long rate) } /* External clock (MCLK & BCLK) functions */ -static int omap1_set_ext_clk_rate(struct clk * clk, unsigned long rate) +int omap1_set_ext_clk_rate(struct clk *clk, unsigned long rate) { unsigned dsor; __u16 ratio_bits; @@ -543,7 +383,7 @@ static int omap1_set_ext_clk_rate(struct clk * clk, unsigned long rate) return 0; } -static int omap1_set_sossi_rate(struct clk *clk, unsigned long rate) +int omap1_set_sossi_rate(struct clk *clk, unsigned long rate) { u32 l; int div; @@ -566,12 +406,12 @@ static int omap1_set_sossi_rate(struct clk *clk, unsigned long rate) return 0; } -static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate) +long omap1_round_ext_clk_rate(struct clk *clk, unsigned long rate) { return 96000000 / calc_ext_dsor(rate); } -static void omap1_init_ext_clk(struct clk * clk) +void omap1_init_ext_clk(struct clk *clk) { unsigned dsor; __u16 ratio_bits; @@ -589,7 +429,7 @@ static void omap1_init_ext_clk(struct clk * clk) clk-> rate = 96000000 / dsor; } -static int omap1_clk_enable(struct clk *clk) +int omap1_clk_enable(struct clk *clk) { int ret = 0; @@ -617,7 +457,7 @@ err: return ret; } -static void omap1_clk_disable(struct clk *clk) +void omap1_clk_disable(struct clk *clk) { if (clk->usecount > 0 && !(--clk->usecount)) { clk->ops->disable(clk); @@ -672,12 +512,70 @@ static void omap1_clk_disable_generic(struct clk *clk) } } -static const struct clkops clkops_generic = { - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, +const struct clkops clkops_generic = { + .enable = omap1_clk_enable_generic, + .disable = omap1_clk_disable_generic, +}; + +static int omap1_clk_enable_dsp_domain(struct clk *clk) +{ + int retval; + + retval = omap1_clk_enable(api_ck_p); + if (!retval) { + retval = omap1_clk_enable_generic(clk); + omap1_clk_disable(api_ck_p); + } + + return retval; +} + +static void omap1_clk_disable_dsp_domain(struct clk *clk) +{ + if (omap1_clk_enable(api_ck_p) == 0) { + omap1_clk_disable_generic(clk); + omap1_clk_disable(api_ck_p); + } +} + +const struct clkops clkops_dspck = { + .enable = omap1_clk_enable_dsp_domain, + .disable = omap1_clk_disable_dsp_domain, +}; + +static int omap1_clk_enable_uart_functional(struct clk *clk) +{ + int ret; + struct uart_clk *uclk; + + ret = omap1_clk_enable_generic(clk); + if (ret == 0) { + /* Set smart idle acknowledgement mode */ + uclk = (struct uart_clk *)clk; + omap_writeb((omap_readb(uclk->sysc_addr) & ~0x10) | 8, + uclk->sysc_addr); + } + + return ret; +} + +static void omap1_clk_disable_uart_functional(struct clk *clk) +{ + struct uart_clk *uclk; + + /* Set force idle acknowledgement mode */ + uclk = (struct uart_clk *)clk; + omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr); + + omap1_clk_disable_generic(clk); +} + +const struct clkops clkops_uart = { + .enable = omap1_clk_enable_uart_functional, + .disable = omap1_clk_disable_uart_functional, }; -static long omap1_clk_round_rate(struct clk *clk, unsigned long rate) +long omap1_clk_round_rate(struct clk *clk, unsigned long rate) { if (clk->flags & RATE_FIXED) return clk->rate; @@ -688,7 +586,7 @@ static long omap1_clk_round_rate(struct clk *clk, unsigned long rate) return clk->rate; } -static int omap1_clk_set_rate(struct clk *clk, unsigned long rate) +int omap1_clk_set_rate(struct clk *clk, unsigned long rate) { int ret = -EINVAL; @@ -703,7 +601,7 @@ static int omap1_clk_set_rate(struct clk *clk, unsigned long rate) #ifdef CONFIG_OMAP_RESET_CLOCKS -static void __init omap1_clk_disable_unused(struct clk *clk) +void __init omap1_clk_disable_unused(struct clk *clk) { __u32 regval32; @@ -724,184 +622,9 @@ static void __init omap1_clk_disable_unused(struct clk *clk) if ((regval32 & (1 << clk->enable_bit)) == 0) return; - /* FIXME: This clock seems to be necessary but no-one - * has asked for its activation. */ - if (clk == &tc2_ck /* FIX: pm.c (SRAM), CCP, Camera */ - || clk == &ck_dpll1out.clk /* FIX: SoSSI, SSR */ - || clk == &arm_gpio_ck /* FIX: GPIO code for 1510 */ - ) { - printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n", - clk->name); - return; - } - printk(KERN_INFO "Disabling unused clock \"%s\"... ", clk->name); clk->ops->disable(clk); printk(" done\n"); } -#else -#define omap1_clk_disable_unused NULL #endif - -static struct clk_functions omap1_clk_functions = { - .clk_enable = omap1_clk_enable, - .clk_disable = omap1_clk_disable, - .clk_round_rate = omap1_clk_round_rate, - .clk_set_rate = omap1_clk_set_rate, - .clk_disable_unused = omap1_clk_disable_unused, -}; - -int __init omap1_clk_init(void) -{ - struct omap_clk *c; - const struct omap_clock_config *info; - int crystal_type = 0; /* Default 12 MHz */ - u32 reg, cpu_mask; - -#ifdef CONFIG_DEBUG_LL - /* Resets some clocks that may be left on from bootloader, - * but leaves serial clocks on. - */ - omap_writel(0x3 << 29, MOD_CONF_CTRL_0); -#endif - - /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */ - reg = omap_readw(SOFT_REQ_REG) & (1 << 4); - omap_writew(reg, SOFT_REQ_REG); - if (!cpu_is_omap15xx()) - omap_writew(0, SOFT_REQ_REG2); - - clk_init(&omap1_clk_functions); - - /* By default all idlect1 clocks are allowed to idle */ - arm_idlect1_mask = ~0; - - for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++) - clk_preinit(c->lk.clk); - - cpu_mask = 0; - if (cpu_is_omap16xx()) - cpu_mask |= CK_16XX; - if (cpu_is_omap1510()) - cpu_mask |= CK_1510; - if (cpu_is_omap7xx()) - cpu_mask |= CK_7XX; - if (cpu_is_omap310()) - cpu_mask |= CK_310; - - for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++) - if (c->cpu & cpu_mask) { - clkdev_add(&c->lk); - clk_register(c->lk.clk); - } - - info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config); - if (info != NULL) { - if (!cpu_is_omap15xx()) - crystal_type = info->system_clock_type; - } - -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) - ck_ref.rate = 13000000; -#elif defined(CONFIG_ARCH_OMAP16XX) - if (crystal_type == 2) - ck_ref.rate = 19200000; -#endif - - printk("Clocks: ARM_SYSST: 0x%04x DPLL_CTL: 0x%04x ARM_CKCTL: 0x%04x\n", - omap_readw(ARM_SYSST), omap_readw(DPLL_CTL), - omap_readw(ARM_CKCTL)); - - /* We want to be in syncronous scalable mode */ - omap_writew(0x1000, ARM_SYSST); - -#ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER - /* Use values set by bootloader. Determine PLL rate and recalculate - * dependent clocks as if kernel had changed PLL or divisors. - */ - { - unsigned pll_ctl_val = omap_readw(DPLL_CTL); - - ck_dpll1.rate = ck_ref.rate; /* Base xtal rate */ - if (pll_ctl_val & 0x10) { - /* PLL enabled, apply multiplier and divisor */ - if (pll_ctl_val & 0xf80) - ck_dpll1.rate *= (pll_ctl_val & 0xf80) >> 7; - ck_dpll1.rate /= ((pll_ctl_val & 0x60) >> 5) + 1; - } else { - /* PLL disabled, apply bypass divisor */ - switch (pll_ctl_val & 0xc) { - case 0: - break; - case 0x4: - ck_dpll1.rate /= 2; - break; - default: - ck_dpll1.rate /= 4; - break; - } - } - } -#else - /* Find the highest supported frequency and enable it */ - if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) { - printk(KERN_ERR "System frequencies not set. Check your config.\n"); - /* Guess sane values (60MHz) */ - omap_writew(0x2290, DPLL_CTL); - omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL); - ck_dpll1.rate = 60000000; - } -#endif - propagate_rate(&ck_dpll1); - /* Cache rates for clocks connected to ck_ref (not dpll1) */ - propagate_rate(&ck_ref); - printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): " - "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n", - ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10, - ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10, - arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10); - -#if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE) - /* Select slicer output as OMAP input clock */ - omap_writew(omap_readw(OMAP7XX_PCC_UPLD_CTRL) & ~0x1, OMAP7XX_PCC_UPLD_CTRL); -#endif - - /* Amstrad Delta wants BCLK high when inactive */ - if (machine_is_ams_delta()) - omap_writel(omap_readl(ULPD_CLOCK_CTRL) | - (1 << SDW_MCLK_INV_BIT), - ULPD_CLOCK_CTRL); - - /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */ - /* (on 730, bit 13 must not be cleared) */ - if (cpu_is_omap7xx()) - omap_writew(omap_readw(ARM_CKCTL) & 0x2fff, ARM_CKCTL); - else - omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL); - - /* Put DSP/MPUI into reset until needed */ - omap_writew(0, ARM_RSTCT1); - omap_writew(1, ARM_RSTCT2); - omap_writew(0x400, ARM_IDLECT1); - - /* - * According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8) - * of the ARM_IDLECT2 register must be set to zero. The power-on - * default value of this bit is one. - */ - omap_writew(0x0000, ARM_IDLECT2); /* Turn LCD clock off also */ - - /* - * Only enable those clocks we will need, let the drivers - * enable other clocks as necessary - */ - clk_enable(&armper_ck.clk); - clk_enable(&armxor_ck.clk); - clk_enable(&armtim_ck.clk); /* This should be done by timer code */ - - if (cpu_is_omap15xx()) - clk_enable(&arm_gpio_ck); - - return 0; -} diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index 29ffa97dc7f3fecb6d9b29ed8c4c12191f824973..a4190afb86140774ef4b7661544bd971c4282e6a 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h @@ -1,7 +1,7 @@ /* * linux/arch/arm/mach-omap1/clock.h * - * Copyright (C) 2004 - 2005 Nokia corporation + * Copyright (C) 2004 - 2005, 2009 Nokia corporation * Written by Tuukka Tikkanen * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc * @@ -13,30 +13,36 @@ #ifndef __ARCH_ARM_MACH_OMAP1_CLOCK_H #define __ARCH_ARM_MACH_OMAP1_CLOCK_H -static unsigned long omap1_ckctl_recalc(struct clk *clk); -static unsigned long omap1_watchdog_recalc(struct clk *clk); -static int omap1_set_sossi_rate(struct clk *clk, unsigned long rate); -static unsigned long omap1_sossi_recalc(struct clk *clk); -static unsigned long omap1_ckctl_recalc_dsp_domain(struct clk *clk); -static int omap1_clk_set_rate_dsp_domain(struct clk * clk, unsigned long rate); -static int omap1_set_uart_rate(struct clk * clk, unsigned long rate); -static unsigned long omap1_uart_recalc(struct clk *clk); -static int omap1_set_ext_clk_rate(struct clk * clk, unsigned long rate); -static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate); -static void omap1_init_ext_clk(struct clk * clk); -static int omap1_select_table_rate(struct clk * clk, unsigned long rate); -static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate); - -static int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate); -static long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate); - -struct mpu_rate { - unsigned long rate; - unsigned long xtal; - unsigned long pll_rate; - __u16 ckctl_val; - __u16 dpllctl_val; -}; +#include + +#include + +extern int __init omap1_clk_init(void); +extern int omap1_clk_enable(struct clk *clk); +extern void omap1_clk_disable(struct clk *clk); +extern long omap1_clk_round_rate(struct clk *clk, unsigned long rate); +extern int omap1_clk_set_rate(struct clk *clk, unsigned long rate); +extern unsigned long omap1_ckctl_recalc(struct clk *clk); +extern int omap1_set_sossi_rate(struct clk *clk, unsigned long rate); +extern unsigned long omap1_sossi_recalc(struct clk *clk); +extern unsigned long omap1_ckctl_recalc_dsp_domain(struct clk *clk); +extern int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate); +extern int omap1_set_uart_rate(struct clk *clk, unsigned long rate); +extern unsigned long omap1_uart_recalc(struct clk *clk); +extern int omap1_set_ext_clk_rate(struct clk *clk, unsigned long rate); +extern long omap1_round_ext_clk_rate(struct clk *clk, unsigned long rate); +extern void omap1_init_ext_clk(struct clk *clk); +extern int omap1_select_table_rate(struct clk *clk, unsigned long rate); +extern long omap1_round_to_table_rate(struct clk *clk, unsigned long rate); +extern int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate); +extern long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate); +extern unsigned long omap1_watchdog_recalc(struct clk *clk); + +#ifdef CONFIG_OMAP_RESET_CLOCKS +extern void __init omap1_clk_disable_unused(struct clk *clk); +#else +#define omap1_clk_disable_unused NULL +#endif struct uart_clk { struct clk clk; @@ -96,596 +102,12 @@ struct arm_idlect1_clk { #define SOFT_REQ_REG 0xfffe0834 #define SOFT_REQ_REG2 0xfffe0880 -/*------------------------------------------------------------------------- - * Omap1 MPU rate table - *-------------------------------------------------------------------------*/ -static struct mpu_rate rate_table[] = { - /* MPU MHz, xtal MHz, dpll1 MHz, CKCTL, DPLL_CTL - * NOTE: Comment order here is different from bits in CKCTL value: - * armdiv, dspdiv, dspmmu, tcdiv, perdiv, lcddiv - */ -#if defined(CONFIG_OMAP_ARM_216MHZ) - { 216000000, 12000000, 216000000, 0x050d, 0x2910 }, /* 1/1/2/2/2/8 */ -#endif -#if defined(CONFIG_OMAP_ARM_195MHZ) - { 195000000, 13000000, 195000000, 0x050e, 0x2790 }, /* 1/1/2/2/4/8 */ -#endif -#if defined(CONFIG_OMAP_ARM_192MHZ) - { 192000000, 19200000, 192000000, 0x050f, 0x2510 }, /* 1/1/2/2/8/8 */ - { 192000000, 12000000, 192000000, 0x050f, 0x2810 }, /* 1/1/2/2/8/8 */ - { 96000000, 12000000, 192000000, 0x055f, 0x2810 }, /* 2/2/2/2/8/8 */ - { 48000000, 12000000, 192000000, 0x0baf, 0x2810 }, /* 4/4/4/8/8/8 */ - { 24000000, 12000000, 192000000, 0x0fff, 0x2810 }, /* 8/8/8/8/8/8 */ -#endif -#if defined(CONFIG_OMAP_ARM_182MHZ) - { 182000000, 13000000, 182000000, 0x050e, 0x2710 }, /* 1/1/2/2/4/8 */ -#endif -#if defined(CONFIG_OMAP_ARM_168MHZ) - { 168000000, 12000000, 168000000, 0x010f, 0x2710 }, /* 1/1/1/2/8/8 */ -#endif -#if defined(CONFIG_OMAP_ARM_150MHZ) - { 150000000, 12000000, 150000000, 0x010a, 0x2cb0 }, /* 1/1/1/2/4/4 */ -#endif -#if defined(CONFIG_OMAP_ARM_120MHZ) - { 120000000, 12000000, 120000000, 0x010a, 0x2510 }, /* 1/1/1/2/4/4 */ -#endif -#if defined(CONFIG_OMAP_ARM_96MHZ) - { 96000000, 12000000, 96000000, 0x0005, 0x2410 }, /* 1/1/1/1/2/2 */ -#endif -#if defined(CONFIG_OMAP_ARM_60MHZ) - { 60000000, 12000000, 60000000, 0x0005, 0x2290 }, /* 1/1/1/1/2/2 */ -#endif -#if defined(CONFIG_OMAP_ARM_30MHZ) - { 30000000, 12000000, 60000000, 0x0555, 0x2290 }, /* 2/2/2/2/2/2 */ -#endif - { 0, 0, 0, 0, 0 }, -}; - -/*------------------------------------------------------------------------- - * Omap1 clocks - *-------------------------------------------------------------------------*/ - -static struct clk ck_ref = { - .name = "ck_ref", - .ops = &clkops_null, - .rate = 12000000, -}; - -static struct clk ck_dpll1 = { - .name = "ck_dpll1", - .ops = &clkops_null, - .parent = &ck_ref, -}; - -static struct arm_idlect1_clk ck_dpll1out = { - .clk = { - .name = "ck_dpll1out", - .ops = &clkops_generic, - .parent = &ck_dpll1, - .flags = CLOCK_IDLE_CONTROL | ENABLE_REG_32BIT, - .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), - .enable_bit = EN_CKOUT_ARM, - .recalc = &followparent_recalc, - }, - .idlect_shift = 12, -}; - -static struct clk sossi_ck = { - .name = "ck_sossi", - .ops = &clkops_generic, - .parent = &ck_dpll1out.clk, - .flags = CLOCK_NO_IDLE_PARENT | ENABLE_REG_32BIT, - .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1), - .enable_bit = 16, - .recalc = &omap1_sossi_recalc, - .set_rate = &omap1_set_sossi_rate, -}; - -static struct clk arm_ck = { - .name = "arm_ck", - .ops = &clkops_null, - .parent = &ck_dpll1, - .rate_offset = CKCTL_ARMDIV_OFFSET, - .recalc = &omap1_ckctl_recalc, - .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = omap1_clk_set_rate_ckctl_arm, -}; - -static struct arm_idlect1_clk armper_ck = { - .clk = { - .name = "armper_ck", - .ops = &clkops_generic, - .parent = &ck_dpll1, - .flags = CLOCK_IDLE_CONTROL, - .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), - .enable_bit = EN_PERCK, - .rate_offset = CKCTL_PERDIV_OFFSET, - .recalc = &omap1_ckctl_recalc, - .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = omap1_clk_set_rate_ckctl_arm, - }, - .idlect_shift = 2, -}; - -static struct clk arm_gpio_ck = { - .name = "arm_gpio_ck", - .ops = &clkops_generic, - .parent = &ck_dpll1, - .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), - .enable_bit = EN_GPIOCK, - .recalc = &followparent_recalc, -}; - -static struct arm_idlect1_clk armxor_ck = { - .clk = { - .name = "armxor_ck", - .ops = &clkops_generic, - .parent = &ck_ref, - .flags = CLOCK_IDLE_CONTROL, - .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), - .enable_bit = EN_XORPCK, - .recalc = &followparent_recalc, - }, - .idlect_shift = 1, -}; - -static struct arm_idlect1_clk armtim_ck = { - .clk = { - .name = "armtim_ck", - .ops = &clkops_generic, - .parent = &ck_ref, - .flags = CLOCK_IDLE_CONTROL, - .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), - .enable_bit = EN_TIMCK, - .recalc = &followparent_recalc, - }, - .idlect_shift = 9, -}; - -static struct arm_idlect1_clk armwdt_ck = { - .clk = { - .name = "armwdt_ck", - .ops = &clkops_generic, - .parent = &ck_ref, - .flags = CLOCK_IDLE_CONTROL, - .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), - .enable_bit = EN_WDTCK, - .recalc = &omap1_watchdog_recalc, - }, - .idlect_shift = 0, -}; - -static struct clk arminth_ck16xx = { - .name = "arminth_ck", - .ops = &clkops_null, - .parent = &arm_ck, - .recalc = &followparent_recalc, - /* Note: On 16xx the frequency can be divided by 2 by programming - * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1 - * - * 1510 version is in TC clocks. - */ -}; - -static struct clk dsp_ck = { - .name = "dsp_ck", - .ops = &clkops_generic, - .parent = &ck_dpll1, - .enable_reg = OMAP1_IO_ADDRESS(ARM_CKCTL), - .enable_bit = EN_DSPCK, - .rate_offset = CKCTL_DSPDIV_OFFSET, - .recalc = &omap1_ckctl_recalc, - .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = omap1_clk_set_rate_ckctl_arm, -}; - -static struct clk dspmmu_ck = { - .name = "dspmmu_ck", - .ops = &clkops_null, - .parent = &ck_dpll1, - .rate_offset = CKCTL_DSPMMUDIV_OFFSET, - .recalc = &omap1_ckctl_recalc, - .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = omap1_clk_set_rate_ckctl_arm, -}; - -static struct clk dspper_ck = { - .name = "dspper_ck", - .ops = &clkops_dspck, - .parent = &ck_dpll1, - .enable_reg = DSP_IDLECT2, - .enable_bit = EN_PERCK, - .rate_offset = CKCTL_PERDIV_OFFSET, - .recalc = &omap1_ckctl_recalc_dsp_domain, - .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = &omap1_clk_set_rate_dsp_domain, -}; - -static struct clk dspxor_ck = { - .name = "dspxor_ck", - .ops = &clkops_dspck, - .parent = &ck_ref, - .enable_reg = DSP_IDLECT2, - .enable_bit = EN_XORPCK, - .recalc = &followparent_recalc, -}; - -static struct clk dsptim_ck = { - .name = "dsptim_ck", - .ops = &clkops_dspck, - .parent = &ck_ref, - .enable_reg = DSP_IDLECT2, - .enable_bit = EN_DSPTIMCK, - .recalc = &followparent_recalc, -}; - -/* Tie ARM_IDLECT1:IDLIF_ARM to this logical clock structure */ -static struct arm_idlect1_clk tc_ck = { - .clk = { - .name = "tc_ck", - .ops = &clkops_null, - .parent = &ck_dpll1, - .flags = CLOCK_IDLE_CONTROL, - .rate_offset = CKCTL_TCDIV_OFFSET, - .recalc = &omap1_ckctl_recalc, - .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = omap1_clk_set_rate_ckctl_arm, - }, - .idlect_shift = 6, -}; - -static struct clk arminth_ck1510 = { - .name = "arminth_ck", - .ops = &clkops_null, - .parent = &tc_ck.clk, - .recalc = &followparent_recalc, - /* Note: On 1510 the frequency follows TC_CK - * - * 16xx version is in MPU clocks. - */ -}; - -static struct clk tipb_ck = { - /* No-idle controlled by "tc_ck" */ - .name = "tipb_ck", - .ops = &clkops_null, - .parent = &tc_ck.clk, - .recalc = &followparent_recalc, -}; - -static struct clk l3_ocpi_ck = { - /* No-idle controlled by "tc_ck" */ - .name = "l3_ocpi_ck", - .ops = &clkops_generic, - .parent = &tc_ck.clk, - .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3), - .enable_bit = EN_OCPI_CK, - .recalc = &followparent_recalc, -}; - -static struct clk tc1_ck = { - .name = "tc1_ck", - .ops = &clkops_generic, - .parent = &tc_ck.clk, - .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3), - .enable_bit = EN_TC1_CK, - .recalc = &followparent_recalc, -}; +extern __u32 arm_idlect1_mask; +extern struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p; -static struct clk tc2_ck = { - .name = "tc2_ck", - .ops = &clkops_generic, - .parent = &tc_ck.clk, - .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3), - .enable_bit = EN_TC2_CK, - .recalc = &followparent_recalc, -}; - -static struct clk dma_ck = { - /* No-idle controlled by "tc_ck" */ - .name = "dma_ck", - .ops = &clkops_null, - .parent = &tc_ck.clk, - .recalc = &followparent_recalc, -}; - -static struct clk dma_lcdfree_ck = { - .name = "dma_lcdfree_ck", - .ops = &clkops_null, - .parent = &tc_ck.clk, - .recalc = &followparent_recalc, -}; - -static struct arm_idlect1_clk api_ck = { - .clk = { - .name = "api_ck", - .ops = &clkops_generic, - .parent = &tc_ck.clk, - .flags = CLOCK_IDLE_CONTROL, - .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), - .enable_bit = EN_APICK, - .recalc = &followparent_recalc, - }, - .idlect_shift = 8, -}; - -static struct arm_idlect1_clk lb_ck = { - .clk = { - .name = "lb_ck", - .ops = &clkops_generic, - .parent = &tc_ck.clk, - .flags = CLOCK_IDLE_CONTROL, - .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), - .enable_bit = EN_LBCK, - .recalc = &followparent_recalc, - }, - .idlect_shift = 4, -}; - -static struct clk rhea1_ck = { - .name = "rhea1_ck", - .ops = &clkops_null, - .parent = &tc_ck.clk, - .recalc = &followparent_recalc, -}; - -static struct clk rhea2_ck = { - .name = "rhea2_ck", - .ops = &clkops_null, - .parent = &tc_ck.clk, - .recalc = &followparent_recalc, -}; - -static struct clk lcd_ck_16xx = { - .name = "lcd_ck", - .ops = &clkops_generic, - .parent = &ck_dpll1, - .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), - .enable_bit = EN_LCDCK, - .rate_offset = CKCTL_LCDDIV_OFFSET, - .recalc = &omap1_ckctl_recalc, - .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = omap1_clk_set_rate_ckctl_arm, -}; - -static struct arm_idlect1_clk lcd_ck_1510 = { - .clk = { - .name = "lcd_ck", - .ops = &clkops_generic, - .parent = &ck_dpll1, - .flags = CLOCK_IDLE_CONTROL, - .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), - .enable_bit = EN_LCDCK, - .rate_offset = CKCTL_LCDDIV_OFFSET, - .recalc = &omap1_ckctl_recalc, - .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = omap1_clk_set_rate_ckctl_arm, - }, - .idlect_shift = 3, -}; - -static struct clk uart1_1510 = { - .name = "uart1_ck", - .ops = &clkops_null, - /* Direct from ULPD, no real parent */ - .parent = &armper_ck.clk, - .rate = 12000000, - .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, - .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), - .enable_bit = 29, /* Chooses between 12MHz and 48MHz */ - .set_rate = &omap1_set_uart_rate, - .recalc = &omap1_uart_recalc, -}; - -static struct uart_clk uart1_16xx = { - .clk = { - .name = "uart1_ck", - .ops = &clkops_uart, - /* Direct from ULPD, no real parent */ - .parent = &armper_ck.clk, - .rate = 48000000, - .flags = RATE_FIXED | ENABLE_REG_32BIT | - CLOCK_NO_IDLE_PARENT, - .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), - .enable_bit = 29, - }, - .sysc_addr = 0xfffb0054, -}; - -static struct clk uart2_ck = { - .name = "uart2_ck", - .ops = &clkops_null, - /* Direct from ULPD, no real parent */ - .parent = &armper_ck.clk, - .rate = 12000000, - .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, - .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), - .enable_bit = 30, /* Chooses between 12MHz and 48MHz */ - .set_rate = &omap1_set_uart_rate, - .recalc = &omap1_uart_recalc, -}; - -static struct clk uart3_1510 = { - .name = "uart3_ck", - .ops = &clkops_null, - /* Direct from ULPD, no real parent */ - .parent = &armper_ck.clk, - .rate = 12000000, - .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, - .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), - .enable_bit = 31, /* Chooses between 12MHz and 48MHz */ - .set_rate = &omap1_set_uart_rate, - .recalc = &omap1_uart_recalc, -}; - -static struct uart_clk uart3_16xx = { - .clk = { - .name = "uart3_ck", - .ops = &clkops_uart, - /* Direct from ULPD, no real parent */ - .parent = &armper_ck.clk, - .rate = 48000000, - .flags = RATE_FIXED | ENABLE_REG_32BIT | - CLOCK_NO_IDLE_PARENT, - .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), - .enable_bit = 31, - }, - .sysc_addr = 0xfffb9854, -}; - -static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */ - .name = "usb_clko", - .ops = &clkops_generic, - /* Direct from ULPD, no parent */ - .rate = 6000000, - .flags = RATE_FIXED | ENABLE_REG_32BIT, - .enable_reg = OMAP1_IO_ADDRESS(ULPD_CLOCK_CTRL), - .enable_bit = USB_MCLK_EN_BIT, -}; - -static struct clk usb_hhc_ck1510 = { - .name = "usb_hhc_ck", - .ops = &clkops_generic, - /* Direct from ULPD, no parent */ - .rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */ - .flags = RATE_FIXED | ENABLE_REG_32BIT, - .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), - .enable_bit = USB_HOST_HHC_UHOST_EN, -}; - -static struct clk usb_hhc_ck16xx = { - .name = "usb_hhc_ck", - .ops = &clkops_generic, - /* Direct from ULPD, no parent */ - .rate = 48000000, - /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */ - .flags = RATE_FIXED | ENABLE_REG_32BIT, - .enable_reg = OMAP1_IO_ADDRESS(OTG_BASE + 0x08), /* OTG_SYSCON_2 */ - .enable_bit = 8 /* UHOST_EN */, -}; - -static struct clk usb_dc_ck = { - .name = "usb_dc_ck", - .ops = &clkops_generic, - /* Direct from ULPD, no parent */ - .rate = 48000000, - .flags = RATE_FIXED, - .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG), - .enable_bit = 4, -}; - -static struct clk usb_dc_ck7xx = { - .name = "usb_dc_ck", - .ops = &clkops_generic, - /* Direct from ULPD, no parent */ - .rate = 48000000, - .flags = RATE_FIXED, - .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG), - .enable_bit = 8, -}; - -static struct clk mclk_1510 = { - .name = "mclk", - .ops = &clkops_generic, - /* Direct from ULPD, no parent. May be enabled by ext hardware. */ - .rate = 12000000, - .flags = RATE_FIXED, - .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG), - .enable_bit = 6, -}; - -static struct clk mclk_16xx = { - .name = "mclk", - .ops = &clkops_generic, - /* Direct from ULPD, no parent. May be enabled by ext hardware. */ - .enable_reg = OMAP1_IO_ADDRESS(COM_CLK_DIV_CTRL_SEL), - .enable_bit = COM_ULPD_PLL_CLK_REQ, - .set_rate = &omap1_set_ext_clk_rate, - .round_rate = &omap1_round_ext_clk_rate, - .init = &omap1_init_ext_clk, -}; - -static struct clk bclk_1510 = { - .name = "bclk", - .ops = &clkops_generic, - /* Direct from ULPD, no parent. May be enabled by ext hardware. */ - .rate = 12000000, - .flags = RATE_FIXED, -}; - -static struct clk bclk_16xx = { - .name = "bclk", - .ops = &clkops_generic, - /* Direct from ULPD, no parent. May be enabled by ext hardware. */ - .enable_reg = OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL), - .enable_bit = SWD_ULPD_PLL_CLK_REQ, - .set_rate = &omap1_set_ext_clk_rate, - .round_rate = &omap1_round_ext_clk_rate, - .init = &omap1_init_ext_clk, -}; - -static struct clk mmc1_ck = { - .name = "mmc_ck", - .ops = &clkops_generic, - /* Functional clock is direct from ULPD, interface clock is ARMPER */ - .parent = &armper_ck.clk, - .rate = 48000000, - .flags = RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, - .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), - .enable_bit = 23, -}; - -static struct clk mmc2_ck = { - .name = "mmc_ck", - .id = 1, - .ops = &clkops_generic, - /* Functional clock is direct from ULPD, interface clock is ARMPER */ - .parent = &armper_ck.clk, - .rate = 48000000, - .flags = RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, - .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), - .enable_bit = 20, -}; - -static struct clk mmc3_ck = { - .name = "mmc_ck", - .id = 2, - .ops = &clkops_generic, - /* Functional clock is direct from ULPD, interface clock is ARMPER */ - .parent = &armper_ck.clk, - .rate = 48000000, - .flags = RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, - .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG), - .enable_bit = 12, -}; - -static struct clk virtual_ck_mpu = { - .name = "mpu", - .ops = &clkops_null, - .parent = &arm_ck, /* Is smarter alias for */ - .recalc = &followparent_recalc, - .set_rate = &omap1_select_table_rate, - .round_rate = &omap1_round_to_table_rate, -}; - -/* virtual functional clock domain for I2C. Just for making sure that ARMXOR_CK -remains active during MPU idle whenever this is enabled */ -static struct clk i2c_fck = { - .name = "i2c_fck", - .id = 1, - .ops = &clkops_null, - .flags = CLOCK_NO_IDLE_PARENT, - .parent = &armxor_ck.clk, - .recalc = &followparent_recalc, -}; - -static struct clk i2c_ick = { - .name = "i2c_ick", - .id = 1, - .ops = &clkops_null, - .flags = CLOCK_NO_IDLE_PARENT, - .parent = &armper_ck.clk, - .recalc = &followparent_recalc, -}; +extern const struct clkops clkops_dspck; +extern const struct clkops clkops_dummy; +extern const struct clkops clkops_uart; +extern const struct clkops clkops_generic; #endif diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c new file mode 100644 index 0000000000000000000000000000000000000000..ab995a9c606caf889d793eb1e6b53384994a919d --- /dev/null +++ b/arch/arm/mach-omap1/clock_data.c @@ -0,0 +1,843 @@ +/* + * linux/arch/arm/mach-omap1/clock_data.c + * + * Copyright (C) 2004 - 2005, 2009 Nokia corporation + * Written by Tuukka Tikkanen + * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include /* for machine_is_* */ + +#include +#include +#include +#include /* for OTG_BASE */ + +#include "clock.h" + +/*------------------------------------------------------------------------ + * Omap1 clocks + *-------------------------------------------------------------------------*/ + +/* XXX is this necessary? */ +static struct clk dummy_ck = { + .name = "dummy", + .ops = &clkops_dummy, + .flags = RATE_FIXED, +}; + +static struct clk ck_ref = { + .name = "ck_ref", + .ops = &clkops_null, + .rate = 12000000, +}; + +static struct clk ck_dpll1 = { + .name = "ck_dpll1", + .ops = &clkops_null, + .parent = &ck_ref, +}; + +/* + * FIXME: This clock seems to be necessary but no-one has asked for its + * activation. [ FIX: SoSSI, SSR ] + */ +static struct arm_idlect1_clk ck_dpll1out = { + .clk = { + .name = "ck_dpll1out", + .ops = &clkops_generic, + .parent = &ck_dpll1, + .flags = CLOCK_IDLE_CONTROL | ENABLE_REG_32BIT | + ENABLE_ON_INIT, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), + .enable_bit = EN_CKOUT_ARM, + .recalc = &followparent_recalc, + }, + .idlect_shift = 12, +}; + +static struct clk sossi_ck = { + .name = "ck_sossi", + .ops = &clkops_generic, + .parent = &ck_dpll1out.clk, + .flags = CLOCK_NO_IDLE_PARENT | ENABLE_REG_32BIT, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1), + .enable_bit = 16, + .recalc = &omap1_sossi_recalc, + .set_rate = &omap1_set_sossi_rate, +}; + +static struct clk arm_ck = { + .name = "arm_ck", + .ops = &clkops_null, + .parent = &ck_dpll1, + .rate_offset = CKCTL_ARMDIV_OFFSET, + .recalc = &omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, +}; + +static struct arm_idlect1_clk armper_ck = { + .clk = { + .name = "armper_ck", + .ops = &clkops_generic, + .parent = &ck_dpll1, + .flags = CLOCK_IDLE_CONTROL, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), + .enable_bit = EN_PERCK, + .rate_offset = CKCTL_PERDIV_OFFSET, + .recalc = &omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, + }, + .idlect_shift = 2, +}; + +/* + * FIXME: This clock seems to be necessary but no-one has asked for its + * activation. [ GPIO code for 1510 ] + */ +static struct clk arm_gpio_ck = { + .name = "arm_gpio_ck", + .ops = &clkops_generic, + .parent = &ck_dpll1, + .flags = ENABLE_ON_INIT, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), + .enable_bit = EN_GPIOCK, + .recalc = &followparent_recalc, +}; + +static struct arm_idlect1_clk armxor_ck = { + .clk = { + .name = "armxor_ck", + .ops = &clkops_generic, + .parent = &ck_ref, + .flags = CLOCK_IDLE_CONTROL, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), + .enable_bit = EN_XORPCK, + .recalc = &followparent_recalc, + }, + .idlect_shift = 1, +}; + +static struct arm_idlect1_clk armtim_ck = { + .clk = { + .name = "armtim_ck", + .ops = &clkops_generic, + .parent = &ck_ref, + .flags = CLOCK_IDLE_CONTROL, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), + .enable_bit = EN_TIMCK, + .recalc = &followparent_recalc, + }, + .idlect_shift = 9, +}; + +static struct arm_idlect1_clk armwdt_ck = { + .clk = { + .name = "armwdt_ck", + .ops = &clkops_generic, + .parent = &ck_ref, + .flags = CLOCK_IDLE_CONTROL, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), + .enable_bit = EN_WDTCK, + .recalc = &omap1_watchdog_recalc, + }, + .idlect_shift = 0, +}; + +static struct clk arminth_ck16xx = { + .name = "arminth_ck", + .ops = &clkops_null, + .parent = &arm_ck, + .recalc = &followparent_recalc, + /* Note: On 16xx the frequency can be divided by 2 by programming + * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1 + * + * 1510 version is in TC clocks. + */ +}; + +static struct clk dsp_ck = { + .name = "dsp_ck", + .ops = &clkops_generic, + .parent = &ck_dpll1, + .enable_reg = OMAP1_IO_ADDRESS(ARM_CKCTL), + .enable_bit = EN_DSPCK, + .rate_offset = CKCTL_DSPDIV_OFFSET, + .recalc = &omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, +}; + +static struct clk dspmmu_ck = { + .name = "dspmmu_ck", + .ops = &clkops_null, + .parent = &ck_dpll1, + .rate_offset = CKCTL_DSPMMUDIV_OFFSET, + .recalc = &omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, +}; + +static struct clk dspper_ck = { + .name = "dspper_ck", + .ops = &clkops_dspck, + .parent = &ck_dpll1, + .enable_reg = DSP_IDLECT2, + .enable_bit = EN_PERCK, + .rate_offset = CKCTL_PERDIV_OFFSET, + .recalc = &omap1_ckctl_recalc_dsp_domain, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = &omap1_clk_set_rate_dsp_domain, +}; + +static struct clk dspxor_ck = { + .name = "dspxor_ck", + .ops = &clkops_dspck, + .parent = &ck_ref, + .enable_reg = DSP_IDLECT2, + .enable_bit = EN_XORPCK, + .recalc = &followparent_recalc, +}; + +static struct clk dsptim_ck = { + .name = "dsptim_ck", + .ops = &clkops_dspck, + .parent = &ck_ref, + .enable_reg = DSP_IDLECT2, + .enable_bit = EN_DSPTIMCK, + .recalc = &followparent_recalc, +}; + +/* Tie ARM_IDLECT1:IDLIF_ARM to this logical clock structure */ +static struct arm_idlect1_clk tc_ck = { + .clk = { + .name = "tc_ck", + .ops = &clkops_null, + .parent = &ck_dpll1, + .flags = CLOCK_IDLE_CONTROL, + .rate_offset = CKCTL_TCDIV_OFFSET, + .recalc = &omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, + }, + .idlect_shift = 6, +}; + +static struct clk arminth_ck1510 = { + .name = "arminth_ck", + .ops = &clkops_null, + .parent = &tc_ck.clk, + .recalc = &followparent_recalc, + /* Note: On 1510 the frequency follows TC_CK + * + * 16xx version is in MPU clocks. + */ +}; + +static struct clk tipb_ck = { + /* No-idle controlled by "tc_ck" */ + .name = "tipb_ck", + .ops = &clkops_null, + .parent = &tc_ck.clk, + .recalc = &followparent_recalc, +}; + +static struct clk l3_ocpi_ck = { + /* No-idle controlled by "tc_ck" */ + .name = "l3_ocpi_ck", + .ops = &clkops_generic, + .parent = &tc_ck.clk, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3), + .enable_bit = EN_OCPI_CK, + .recalc = &followparent_recalc, +}; + +static struct clk tc1_ck = { + .name = "tc1_ck", + .ops = &clkops_generic, + .parent = &tc_ck.clk, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3), + .enable_bit = EN_TC1_CK, + .recalc = &followparent_recalc, +}; + +/* + * FIXME: This clock seems to be necessary but no-one has asked for its + * activation. [ pm.c (SRAM), CCP, Camera ] + */ +static struct clk tc2_ck = { + .name = "tc2_ck", + .ops = &clkops_generic, + .parent = &tc_ck.clk, + .flags = ENABLE_ON_INIT, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3), + .enable_bit = EN_TC2_CK, + .recalc = &followparent_recalc, +}; + +static struct clk dma_ck = { + /* No-idle controlled by "tc_ck" */ + .name = "dma_ck", + .ops = &clkops_null, + .parent = &tc_ck.clk, + .recalc = &followparent_recalc, +}; + +static struct clk dma_lcdfree_ck = { + .name = "dma_lcdfree_ck", + .ops = &clkops_null, + .parent = &tc_ck.clk, + .recalc = &followparent_recalc, +}; + +static struct arm_idlect1_clk api_ck = { + .clk = { + .name = "api_ck", + .ops = &clkops_generic, + .parent = &tc_ck.clk, + .flags = CLOCK_IDLE_CONTROL, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), + .enable_bit = EN_APICK, + .recalc = &followparent_recalc, + }, + .idlect_shift = 8, +}; + +static struct arm_idlect1_clk lb_ck = { + .clk = { + .name = "lb_ck", + .ops = &clkops_generic, + .parent = &tc_ck.clk, + .flags = CLOCK_IDLE_CONTROL, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), + .enable_bit = EN_LBCK, + .recalc = &followparent_recalc, + }, + .idlect_shift = 4, +}; + +static struct clk rhea1_ck = { + .name = "rhea1_ck", + .ops = &clkops_null, + .parent = &tc_ck.clk, + .recalc = &followparent_recalc, +}; + +static struct clk rhea2_ck = { + .name = "rhea2_ck", + .ops = &clkops_null, + .parent = &tc_ck.clk, + .recalc = &followparent_recalc, +}; + +static struct clk lcd_ck_16xx = { + .name = "lcd_ck", + .ops = &clkops_generic, + .parent = &ck_dpll1, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), + .enable_bit = EN_LCDCK, + .rate_offset = CKCTL_LCDDIV_OFFSET, + .recalc = &omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, +}; + +static struct arm_idlect1_clk lcd_ck_1510 = { + .clk = { + .name = "lcd_ck", + .ops = &clkops_generic, + .parent = &ck_dpll1, + .flags = CLOCK_IDLE_CONTROL, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), + .enable_bit = EN_LCDCK, + .rate_offset = CKCTL_LCDDIV_OFFSET, + .recalc = &omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, + }, + .idlect_shift = 3, +}; + +static struct clk uart1_1510 = { + .name = "uart1_ck", + .ops = &clkops_null, + /* Direct from ULPD, no real parent */ + .parent = &armper_ck.clk, + .rate = 12000000, + .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), + .enable_bit = 29, /* Chooses between 12MHz and 48MHz */ + .set_rate = &omap1_set_uart_rate, + .recalc = &omap1_uart_recalc, +}; + +static struct uart_clk uart1_16xx = { + .clk = { + .name = "uart1_ck", + .ops = &clkops_uart, + /* Direct from ULPD, no real parent */ + .parent = &armper_ck.clk, + .rate = 48000000, + .flags = RATE_FIXED | ENABLE_REG_32BIT | + CLOCK_NO_IDLE_PARENT, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), + .enable_bit = 29, + }, + .sysc_addr = 0xfffb0054, +}; + +static struct clk uart2_ck = { + .name = "uart2_ck", + .ops = &clkops_null, + /* Direct from ULPD, no real parent */ + .parent = &armper_ck.clk, + .rate = 12000000, + .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), + .enable_bit = 30, /* Chooses between 12MHz and 48MHz */ + .set_rate = &omap1_set_uart_rate, + .recalc = &omap1_uart_recalc, +}; + +static struct clk uart3_1510 = { + .name = "uart3_ck", + .ops = &clkops_null, + /* Direct from ULPD, no real parent */ + .parent = &armper_ck.clk, + .rate = 12000000, + .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), + .enable_bit = 31, /* Chooses between 12MHz and 48MHz */ + .set_rate = &omap1_set_uart_rate, + .recalc = &omap1_uart_recalc, +}; + +static struct uart_clk uart3_16xx = { + .clk = { + .name = "uart3_ck", + .ops = &clkops_uart, + /* Direct from ULPD, no real parent */ + .parent = &armper_ck.clk, + .rate = 48000000, + .flags = RATE_FIXED | ENABLE_REG_32BIT | + CLOCK_NO_IDLE_PARENT, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), + .enable_bit = 31, + }, + .sysc_addr = 0xfffb9854, +}; + +static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */ + .name = "usb_clko", + .ops = &clkops_generic, + /* Direct from ULPD, no parent */ + .rate = 6000000, + .flags = RATE_FIXED | ENABLE_REG_32BIT, + .enable_reg = OMAP1_IO_ADDRESS(ULPD_CLOCK_CTRL), + .enable_bit = USB_MCLK_EN_BIT, +}; + +static struct clk usb_hhc_ck1510 = { + .name = "usb_hhc_ck", + .ops = &clkops_generic, + /* Direct from ULPD, no parent */ + .rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */ + .flags = RATE_FIXED | ENABLE_REG_32BIT, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), + .enable_bit = USB_HOST_HHC_UHOST_EN, +}; + +static struct clk usb_hhc_ck16xx = { + .name = "usb_hhc_ck", + .ops = &clkops_generic, + /* Direct from ULPD, no parent */ + .rate = 48000000, + /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */ + .flags = RATE_FIXED | ENABLE_REG_32BIT, + .enable_reg = OMAP1_IO_ADDRESS(OTG_BASE + 0x08), /* OTG_SYSCON_2 */ + .enable_bit = 8 /* UHOST_EN */, +}; + +static struct clk usb_dc_ck = { + .name = "usb_dc_ck", + .ops = &clkops_generic, + /* Direct from ULPD, no parent */ + .rate = 48000000, + .flags = RATE_FIXED, + .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG), + .enable_bit = 4, +}; + +static struct clk usb_dc_ck7xx = { + .name = "usb_dc_ck", + .ops = &clkops_generic, + /* Direct from ULPD, no parent */ + .rate = 48000000, + .flags = RATE_FIXED, + .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG), + .enable_bit = 8, +}; + +static struct clk mclk_1510 = { + .name = "mclk", + .ops = &clkops_generic, + /* Direct from ULPD, no parent. May be enabled by ext hardware. */ + .rate = 12000000, + .flags = RATE_FIXED, + .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG), + .enable_bit = 6, +}; + +static struct clk mclk_16xx = { + .name = "mclk", + .ops = &clkops_generic, + /* Direct from ULPD, no parent. May be enabled by ext hardware. */ + .enable_reg = OMAP1_IO_ADDRESS(COM_CLK_DIV_CTRL_SEL), + .enable_bit = COM_ULPD_PLL_CLK_REQ, + .set_rate = &omap1_set_ext_clk_rate, + .round_rate = &omap1_round_ext_clk_rate, + .init = &omap1_init_ext_clk, +}; + +static struct clk bclk_1510 = { + .name = "bclk", + .ops = &clkops_generic, + /* Direct from ULPD, no parent. May be enabled by ext hardware. */ + .rate = 12000000, + .flags = RATE_FIXED, +}; + +static struct clk bclk_16xx = { + .name = "bclk", + .ops = &clkops_generic, + /* Direct from ULPD, no parent. May be enabled by ext hardware. */ + .enable_reg = OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL), + .enable_bit = SWD_ULPD_PLL_CLK_REQ, + .set_rate = &omap1_set_ext_clk_rate, + .round_rate = &omap1_round_ext_clk_rate, + .init = &omap1_init_ext_clk, +}; + +static struct clk mmc1_ck = { + .name = "mmc_ck", + .ops = &clkops_generic, + /* Functional clock is direct from ULPD, interface clock is ARMPER */ + .parent = &armper_ck.clk, + .rate = 48000000, + .flags = RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), + .enable_bit = 23, +}; + +static struct clk mmc2_ck = { + .name = "mmc_ck", + .id = 1, + .ops = &clkops_generic, + /* Functional clock is direct from ULPD, interface clock is ARMPER */ + .parent = &armper_ck.clk, + .rate = 48000000, + .flags = RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), + .enable_bit = 20, +}; + +static struct clk mmc3_ck = { + .name = "mmc_ck", + .id = 2, + .ops = &clkops_generic, + /* Functional clock is direct from ULPD, interface clock is ARMPER */ + .parent = &armper_ck.clk, + .rate = 48000000, + .flags = RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, + .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG), + .enable_bit = 12, +}; + +static struct clk virtual_ck_mpu = { + .name = "mpu", + .ops = &clkops_null, + .parent = &arm_ck, /* Is smarter alias for */ + .recalc = &followparent_recalc, + .set_rate = &omap1_select_table_rate, + .round_rate = &omap1_round_to_table_rate, +}; + +/* virtual functional clock domain for I2C. Just for making sure that ARMXOR_CK +remains active during MPU idle whenever this is enabled */ +static struct clk i2c_fck = { + .name = "i2c_fck", + .id = 1, + .ops = &clkops_null, + .flags = CLOCK_NO_IDLE_PARENT, + .parent = &armxor_ck.clk, + .recalc = &followparent_recalc, +}; + +static struct clk i2c_ick = { + .name = "i2c_ick", + .id = 1, + .ops = &clkops_null, + .flags = CLOCK_NO_IDLE_PARENT, + .parent = &armper_ck.clk, + .recalc = &followparent_recalc, +}; + +/* + * clkdev integration + */ + +static struct omap_clk omap_clks[] = { + /* non-ULPD clocks */ + CLK(NULL, "ck_ref", &ck_ref, CK_16XX | CK_1510 | CK_310 | CK_7XX), + CLK(NULL, "ck_dpll1", &ck_dpll1, CK_16XX | CK_1510 | CK_310), + /* CK_GEN1 clocks */ + CLK(NULL, "ck_dpll1out", &ck_dpll1out.clk, CK_16XX), + CLK(NULL, "ck_sossi", &sossi_ck, CK_16XX), + CLK(NULL, "arm_ck", &arm_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "armper_ck", &armper_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "arm_gpio_ck", &arm_gpio_ck, CK_1510 | CK_310), + CLK(NULL, "armxor_ck", &armxor_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX), + CLK(NULL, "armtim_ck", &armtim_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK("omap_wdt", "fck", &armwdt_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK("omap_wdt", "ick", &armper_ck.clk, CK_16XX), + CLK("omap_wdt", "ick", &dummy_ck, CK_1510 | CK_310), + CLK(NULL, "arminth_ck", &arminth_ck1510, CK_1510 | CK_310), + CLK(NULL, "arminth_ck", &arminth_ck16xx, CK_16XX), + /* CK_GEN2 clocks */ + CLK(NULL, "dsp_ck", &dsp_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "dspmmu_ck", &dspmmu_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "dspper_ck", &dspper_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "dspxor_ck", &dspxor_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "dsptim_ck", &dsptim_ck, CK_16XX | CK_1510 | CK_310), + /* CK_GEN3 clocks */ + CLK(NULL, "tc_ck", &tc_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX), + CLK(NULL, "tipb_ck", &tipb_ck, CK_1510 | CK_310), + CLK(NULL, "l3_ocpi_ck", &l3_ocpi_ck, CK_16XX | CK_7XX), + CLK(NULL, "tc1_ck", &tc1_ck, CK_16XX), + CLK(NULL, "tc2_ck", &tc2_ck, CK_16XX), + CLK(NULL, "dma_ck", &dma_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "dma_lcdfree_ck", &dma_lcdfree_ck, CK_16XX), + CLK(NULL, "api_ck", &api_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "lb_ck", &lb_ck.clk, CK_1510 | CK_310), + CLK(NULL, "rhea1_ck", &rhea1_ck, CK_16XX), + CLK(NULL, "rhea2_ck", &rhea2_ck, CK_16XX), + CLK(NULL, "lcd_ck", &lcd_ck_16xx, CK_16XX | CK_7XX), + CLK(NULL, "lcd_ck", &lcd_ck_1510.clk, CK_1510 | CK_310), + /* ULPD clocks */ + CLK(NULL, "uart1_ck", &uart1_1510, CK_1510 | CK_310), + CLK(NULL, "uart1_ck", &uart1_16xx.clk, CK_16XX), + CLK(NULL, "uart2_ck", &uart2_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "uart3_ck", &uart3_1510, CK_1510 | CK_310), + CLK(NULL, "uart3_ck", &uart3_16xx.clk, CK_16XX), + CLK(NULL, "usb_clko", &usb_clko, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "usb_hhc_ck", &usb_hhc_ck1510, CK_1510 | CK_310), + CLK(NULL, "usb_hhc_ck", &usb_hhc_ck16xx, CK_16XX), + CLK(NULL, "usb_dc_ck", &usb_dc_ck, CK_16XX), + CLK(NULL, "usb_dc_ck", &usb_dc_ck7xx, CK_7XX), + CLK(NULL, "mclk", &mclk_1510, CK_1510 | CK_310), + CLK(NULL, "mclk", &mclk_16xx, CK_16XX), + CLK(NULL, "bclk", &bclk_1510, CK_1510 | CK_310), + CLK(NULL, "bclk", &bclk_16xx, CK_16XX), + CLK("mmci-omap.0", "fck", &mmc1_ck, CK_16XX | CK_1510 | CK_310), + CLK("mmci-omap.0", "fck", &mmc3_ck, CK_7XX), + CLK("mmci-omap.0", "ick", &armper_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX), + CLK("mmci-omap.1", "fck", &mmc2_ck, CK_16XX), + CLK("mmci-omap.1", "ick", &armper_ck.clk, CK_16XX), + /* Virtual clocks */ + CLK(NULL, "mpu", &virtual_ck_mpu, CK_16XX | CK_1510 | CK_310), + CLK("i2c_omap.1", "fck", &i2c_fck, CK_16XX | CK_1510 | CK_310 | CK_7XX), + CLK("i2c_omap.1", "ick", &i2c_ick, CK_16XX), + CLK("i2c_omap.1", "ick", &dummy_ck, CK_1510 | CK_310 | CK_7XX), + CLK("omap_uwire", "fck", &armxor_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK("omap-mcbsp.1", "ick", &dspper_ck, CK_16XX), + CLK("omap-mcbsp.1", "ick", &dummy_ck, CK_1510 | CK_310), + CLK("omap-mcbsp.2", "ick", &armper_ck.clk, CK_16XX), + CLK("omap-mcbsp.2", "ick", &dummy_ck, CK_1510 | CK_310), + CLK("omap-mcbsp.3", "ick", &dspper_ck, CK_16XX), + CLK("omap-mcbsp.3", "ick", &dummy_ck, CK_1510 | CK_310), + CLK("omap-mcbsp.1", "fck", &dspxor_ck, CK_16XX | CK_1510 | CK_310), + CLK("omap-mcbsp.2", "fck", &armper_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK("omap-mcbsp.3", "fck", &dspxor_ck, CK_16XX | CK_1510 | CK_310), +}; + +/* + * init + */ + +static struct clk_functions omap1_clk_functions __initdata = { + .clk_enable = omap1_clk_enable, + .clk_disable = omap1_clk_disable, + .clk_round_rate = omap1_clk_round_rate, + .clk_set_rate = omap1_clk_set_rate, + .clk_disable_unused = omap1_clk_disable_unused, +}; + +int __init omap1_clk_init(void) +{ + struct omap_clk *c; + const struct omap_clock_config *info; + int crystal_type = 0; /* Default 12 MHz */ + u32 reg, cpu_mask; + +#ifdef CONFIG_DEBUG_LL + /* + * Resets some clocks that may be left on from bootloader, + * but leaves serial clocks on. + */ + omap_writel(0x3 << 29, MOD_CONF_CTRL_0); +#endif + + /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */ + reg = omap_readw(SOFT_REQ_REG) & (1 << 4); + omap_writew(reg, SOFT_REQ_REG); + if (!cpu_is_omap15xx()) + omap_writew(0, SOFT_REQ_REG2); + + clk_init(&omap1_clk_functions); + + /* By default all idlect1 clocks are allowed to idle */ + arm_idlect1_mask = ~0; + + for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++) + clk_preinit(c->lk.clk); + + cpu_mask = 0; + if (cpu_is_omap16xx()) + cpu_mask |= CK_16XX; + if (cpu_is_omap1510()) + cpu_mask |= CK_1510; + if (cpu_is_omap7xx()) + cpu_mask |= CK_7XX; + if (cpu_is_omap310()) + cpu_mask |= CK_310; + + for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++) + if (c->cpu & cpu_mask) { + clkdev_add(&c->lk); + clk_register(c->lk.clk); + } + + /* Pointers to these clocks are needed by code in clock.c */ + api_ck_p = clk_get(NULL, "api_ck"); + ck_dpll1_p = clk_get(NULL, "ck_dpll1"); + ck_ref_p = clk_get(NULL, "ck_ref"); + + info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config); + if (info != NULL) { + if (!cpu_is_omap15xx()) + crystal_type = info->system_clock_type; + } + +#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) + ck_ref.rate = 13000000; +#elif defined(CONFIG_ARCH_OMAP16XX) + if (crystal_type == 2) + ck_ref.rate = 19200000; +#endif + + pr_info("Clocks: ARM_SYSST: 0x%04x DPLL_CTL: 0x%04x ARM_CKCTL: " + "0x%04x\n", omap_readw(ARM_SYSST), omap_readw(DPLL_CTL), + omap_readw(ARM_CKCTL)); + + /* We want to be in syncronous scalable mode */ + omap_writew(0x1000, ARM_SYSST); + +#ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER + /* Use values set by bootloader. Determine PLL rate and recalculate + * dependent clocks as if kernel had changed PLL or divisors. + */ + { + unsigned pll_ctl_val = omap_readw(DPLL_CTL); + + ck_dpll1.rate = ck_ref.rate; /* Base xtal rate */ + if (pll_ctl_val & 0x10) { + /* PLL enabled, apply multiplier and divisor */ + if (pll_ctl_val & 0xf80) + ck_dpll1.rate *= (pll_ctl_val & 0xf80) >> 7; + ck_dpll1.rate /= ((pll_ctl_val & 0x60) >> 5) + 1; + } else { + /* PLL disabled, apply bypass divisor */ + switch (pll_ctl_val & 0xc) { + case 0: + break; + case 0x4: + ck_dpll1.rate /= 2; + break; + default: + ck_dpll1.rate /= 4; + break; + } + } + } +#else + /* Find the highest supported frequency and enable it */ + if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) { + printk(KERN_ERR "System frequencies not set. Check your config.\n"); + /* Guess sane values (60MHz) */ + omap_writew(0x2290, DPLL_CTL); + omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL); + ck_dpll1.rate = 60000000; + } +#endif + propagate_rate(&ck_dpll1); + /* Cache rates for clocks connected to ck_ref (not dpll1) */ + propagate_rate(&ck_ref); + printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): " + "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n", + ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10, + ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10, + arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10); + +#if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE) + /* Select slicer output as OMAP input clock */ + omap_writew(omap_readw(OMAP7XX_PCC_UPLD_CTRL) & ~0x1, OMAP7XX_PCC_UPLD_CTRL); +#endif + + /* Amstrad Delta wants BCLK high when inactive */ + if (machine_is_ams_delta()) + omap_writel(omap_readl(ULPD_CLOCK_CTRL) | + (1 << SDW_MCLK_INV_BIT), + ULPD_CLOCK_CTRL); + + /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */ + /* (on 730, bit 13 must not be cleared) */ + if (cpu_is_omap7xx()) + omap_writew(omap_readw(ARM_CKCTL) & 0x2fff, ARM_CKCTL); + else + omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL); + + /* Put DSP/MPUI into reset until needed */ + omap_writew(0, ARM_RSTCT1); + omap_writew(1, ARM_RSTCT2); + omap_writew(0x400, ARM_IDLECT1); + + /* + * According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8) + * of the ARM_IDLECT2 register must be set to zero. The power-on + * default value of this bit is one. + */ + omap_writew(0x0000, ARM_IDLECT2); /* Turn LCD clock off also */ + + /* + * Only enable those clocks we will need, let the drivers + * enable other clocks as necessary + */ + clk_enable(&armper_ck.clk); + clk_enable(&armxor_ck.clk); + clk_enable(&armtim_ck.clk); /* This should be done by timer code */ + + if (cpu_is_omap15xx()) + clk_enable(&arm_gpio_ck); + + return 0; +} diff --git a/arch/arm/mach-omap1/i2c.c b/arch/arm/mach-omap1/i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..1bf4735e27a636285ad512f26b5cff0b7b519748 --- /dev/null +++ b/arch/arm/mach-omap1/i2c.c @@ -0,0 +1,39 @@ +/* + * Helper module for board specific I2C bus registration + * + * Copyright (C) 2009 Nokia Corporation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include + +int __init omap_register_i2c_bus(int bus_id, u32 clkrate, + struct i2c_board_info const *info, + unsigned len) +{ + if (cpu_is_omap7xx()) { + omap_cfg_reg(I2C_7XX_SDA); + omap_cfg_reg(I2C_7XX_SCL); + } else { + omap_cfg_reg(I2C_SDA); + omap_cfg_reg(I2C_SCL); + } + + return omap_plat_register_i2c_bus(bus_id, clkrate, info, len); +} diff --git a/arch/arm/mach-omap1/include/mach/lcd_dma.h b/arch/arm/mach-omap1/include/mach/lcd_dma.h new file mode 100644 index 0000000000000000000000000000000000000000..d7a457bbcb7f0382d7688c63f34aa0bcc251e730 --- /dev/null +++ b/arch/arm/mach-omap1/include/mach/lcd_dma.h @@ -0,0 +1,78 @@ +/* + * arch/arm/mach-omap1/include/mach/lcd_dma.h + * + * Extracted from arch/arm/plat-omap/include/plat/dma.h + * Copyright (C) 2003 Nokia Corporation + * Author: Juha Yrjölä + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 __MACH_OMAP1_LCD_DMA_H__ +#define __MACH_OMAP1_LCD_DMA_H__ + +/* Hardware registers for LCD DMA */ +#define OMAP1510_DMA_LCD_BASE (0xfffedb00) +#define OMAP1510_DMA_LCD_CTRL (OMAP1510_DMA_LCD_BASE + 0x00) +#define OMAP1510_DMA_LCD_TOP_F1_L (OMAP1510_DMA_LCD_BASE + 0x02) +#define OMAP1510_DMA_LCD_TOP_F1_U (OMAP1510_DMA_LCD_BASE + 0x04) +#define OMAP1510_DMA_LCD_BOT_F1_L (OMAP1510_DMA_LCD_BASE + 0x06) +#define OMAP1510_DMA_LCD_BOT_F1_U (OMAP1510_DMA_LCD_BASE + 0x08) + +#define OMAP1610_DMA_LCD_BASE (0xfffee300) +#define OMAP1610_DMA_LCD_CSDP (OMAP1610_DMA_LCD_BASE + 0xc0) +#define OMAP1610_DMA_LCD_CCR (OMAP1610_DMA_LCD_BASE + 0xc2) +#define OMAP1610_DMA_LCD_CTRL (OMAP1610_DMA_LCD_BASE + 0xc4) +#define OMAP1610_DMA_LCD_TOP_B1_L (OMAP1610_DMA_LCD_BASE + 0xc8) +#define OMAP1610_DMA_LCD_TOP_B1_U (OMAP1610_DMA_LCD_BASE + 0xca) +#define OMAP1610_DMA_LCD_BOT_B1_L (OMAP1610_DMA_LCD_BASE + 0xcc) +#define OMAP1610_DMA_LCD_BOT_B1_U (OMAP1610_DMA_LCD_BASE + 0xce) +#define OMAP1610_DMA_LCD_TOP_B2_L (OMAP1610_DMA_LCD_BASE + 0xd0) +#define OMAP1610_DMA_LCD_TOP_B2_U (OMAP1610_DMA_LCD_BASE + 0xd2) +#define OMAP1610_DMA_LCD_BOT_B2_L (OMAP1610_DMA_LCD_BASE + 0xd4) +#define OMAP1610_DMA_LCD_BOT_B2_U (OMAP1610_DMA_LCD_BASE + 0xd6) +#define OMAP1610_DMA_LCD_SRC_EI_B1 (OMAP1610_DMA_LCD_BASE + 0xd8) +#define OMAP1610_DMA_LCD_SRC_FI_B1_L (OMAP1610_DMA_LCD_BASE + 0xda) +#define OMAP1610_DMA_LCD_SRC_EN_B1 (OMAP1610_DMA_LCD_BASE + 0xe0) +#define OMAP1610_DMA_LCD_SRC_FN_B1 (OMAP1610_DMA_LCD_BASE + 0xe4) +#define OMAP1610_DMA_LCD_LCH_CTRL (OMAP1610_DMA_LCD_BASE + 0xea) +#define OMAP1610_DMA_LCD_SRC_FI_B1_U (OMAP1610_DMA_LCD_BASE + 0xf4) + +/* LCD DMA block numbers */ +enum { + OMAP_LCD_DMA_B1_TOP, + OMAP_LCD_DMA_B1_BOTTOM, + OMAP_LCD_DMA_B2_TOP, + OMAP_LCD_DMA_B2_BOTTOM +}; + +/* LCD DMA functions */ +extern int omap_request_lcd_dma(void (*callback)(u16 status, void *data), + void *data); +extern void omap_free_lcd_dma(void); +extern void omap_setup_lcd_dma(void); +extern void omap_enable_lcd_dma(void); +extern void omap_stop_lcd_dma(void); +extern void omap_set_lcd_dma_ext_controller(int external); +extern void omap_set_lcd_dma_single_transfer(int single); +extern void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres, + int data_type); +extern void omap_set_lcd_dma_b1_rotation(int rotate); +extern void omap_set_lcd_dma_b1_vxres(unsigned long vxres); +extern void omap_set_lcd_dma_b1_mirror(int mirror); +extern void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale); + +extern int omap_lcd_dma_running(void); + +#endif /* __MACH_OMAP1_LCD_DMA_H__ */ diff --git a/arch/arm/mach-omap1/include/mach/lcdc.h b/arch/arm/mach-omap1/include/mach/lcdc.h new file mode 100644 index 0000000000000000000000000000000000000000..89bd703adaf60d15f6d18d00db17596a8f039b11 --- /dev/null +++ b/arch/arm/mach-omap1/include/mach/lcdc.h @@ -0,0 +1,57 @@ +/* + * arch/arm/mach-omap1/include/mach/lcdc.h + * + * Extracted from drivers/video/omap/lcdc.c + * Copyright (C) 2004 Nokia Corporation + * Author: Imre Deak + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 __MACH_LCDC_H__ +#define __MACH_LCDC_H__ + +#define OMAP_LCDC_BASE 0xfffec000 +#define OMAP_LCDC_SIZE 256 +#define OMAP_LCDC_IRQ INT_LCD_CTRL + +#define OMAP_LCDC_CONTROL (OMAP_LCDC_BASE + 0x00) +#define OMAP_LCDC_TIMING0 (OMAP_LCDC_BASE + 0x04) +#define OMAP_LCDC_TIMING1 (OMAP_LCDC_BASE + 0x08) +#define OMAP_LCDC_TIMING2 (OMAP_LCDC_BASE + 0x0c) +#define OMAP_LCDC_STATUS (OMAP_LCDC_BASE + 0x10) +#define OMAP_LCDC_SUBPANEL (OMAP_LCDC_BASE + 0x14) +#define OMAP_LCDC_LINE_INT (OMAP_LCDC_BASE + 0x18) +#define OMAP_LCDC_DISPLAY_STATUS (OMAP_LCDC_BASE + 0x1c) + +#define OMAP_LCDC_STAT_DONE (1 << 0) +#define OMAP_LCDC_STAT_VSYNC (1 << 1) +#define OMAP_LCDC_STAT_SYNC_LOST (1 << 2) +#define OMAP_LCDC_STAT_ABC (1 << 3) +#define OMAP_LCDC_STAT_LINE_INT (1 << 4) +#define OMAP_LCDC_STAT_FUF (1 << 5) +#define OMAP_LCDC_STAT_LOADED_PALETTE (1 << 6) + +#define OMAP_LCDC_CTRL_LCD_EN (1 << 0) +#define OMAP_LCDC_CTRL_LCD_TFT (1 << 7) +#define OMAP_LCDC_CTRL_LINE_IRQ_CLR_SEL (1 << 10) + +#define OMAP_LCDC_IRQ_VSYNC (1 << 2) +#define OMAP_LCDC_IRQ_DONE (1 << 3) +#define OMAP_LCDC_IRQ_LOADED_PALETTE (1 << 4) +#define OMAP_LCDC_IRQ_LINE_NIRQ (1 << 5) +#define OMAP_LCDC_IRQ_LINE (1 << 6) +#define OMAP_LCDC_IRQ_MASK (((1 << 5) - 1) << 2) + +#endif /* __MACH_LCDC_H__ */ diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c index 2a6d68aa3489b3cb74a5b0ef83e4ffa4d9f96ee2..d9b8d82530ae165bf18ab272c49ff61a069ae298 100644 --- a/arch/arm/mach-omap1/io.c +++ b/arch/arm/mach-omap1/io.c @@ -18,7 +18,8 @@ #include #include -extern int omap1_clk_init(void); +#include "clock.h" + extern void omap_check_revision(void); extern void omap_sram_init(void); extern void omapfb_reserve_sdram(void); diff --git a/arch/arm/mach-omap1/lcd_dma.c b/arch/arm/mach-omap1/lcd_dma.c new file mode 100644 index 0000000000000000000000000000000000000000..3be11af687bb26652be53303b17d7d5265568e03 --- /dev/null +++ b/arch/arm/mach-omap1/lcd_dma.c @@ -0,0 +1,448 @@ +/* + * linux/arch/arm/mach-omap1/lcd_dma.c + * + * Extracted from arch/arm/plat-omap/dma.c + * Copyright (C) 2003 - 2008 Nokia Corporation + * Author: Juha Yrjölä + * DMA channel linking for 1610 by Samuel Ortiz + * Graphics DMA and LCD DMA graphics tranformations + * by Imre Deak + * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc. + * Merged to support both OMAP1 and OMAP2 by Tony Lindgren + * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. + * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar + * + * Support functions for the OMAP internal DMA channels. + * + * 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 + +int omap_lcd_dma_running(void) +{ + /* + * On OMAP1510, internal LCD controller will start the transfer + * when it gets enabled, so assume DMA running if LCD enabled. + */ + if (cpu_is_omap1510()) + if (omap_readw(OMAP_LCDC_CONTROL) & OMAP_LCDC_CTRL_LCD_EN) + return 1; + + /* Check if LCD DMA is running */ + if (cpu_is_omap16xx()) + if (omap_readw(OMAP1610_DMA_LCD_CCR) & OMAP_DMA_CCR_EN) + return 1; + + return 0; +} + +static struct lcd_dma_info { + spinlock_t lock; + int reserved; + void (*callback)(u16 status, void *data); + void *cb_data; + + int active; + unsigned long addr, size; + int rotate, data_type, xres, yres; + int vxres; + int mirror; + int xscale, yscale; + int ext_ctrl; + int src_port; + int single_transfer; +} lcd_dma; + +void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres, + int data_type) +{ + lcd_dma.addr = addr; + lcd_dma.data_type = data_type; + lcd_dma.xres = fb_xres; + lcd_dma.yres = fb_yres; +} +EXPORT_SYMBOL(omap_set_lcd_dma_b1); + +void omap_set_lcd_dma_src_port(int port) +{ + lcd_dma.src_port = port; +} + +void omap_set_lcd_dma_ext_controller(int external) +{ + lcd_dma.ext_ctrl = external; +} +EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller); + +void omap_set_lcd_dma_single_transfer(int single) +{ + lcd_dma.single_transfer = single; +} +EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer); + +void omap_set_lcd_dma_b1_rotation(int rotate) +{ + if (cpu_is_omap1510()) { + printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n"); + BUG(); + return; + } + lcd_dma.rotate = rotate; +} +EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation); + +void omap_set_lcd_dma_b1_mirror(int mirror) +{ + if (cpu_is_omap1510()) { + printk(KERN_ERR "DMA mirror is not supported in 1510 mode\n"); + BUG(); + } + lcd_dma.mirror = mirror; +} +EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror); + +void omap_set_lcd_dma_b1_vxres(unsigned long vxres) +{ + if (cpu_is_omap1510()) { + printk(KERN_ERR "DMA virtual resulotion is not supported " + "in 1510 mode\n"); + BUG(); + } + lcd_dma.vxres = vxres; +} +EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres); + +void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale) +{ + if (cpu_is_omap1510()) { + printk(KERN_ERR "DMA scale is not supported in 1510 mode\n"); + BUG(); + } + lcd_dma.xscale = xscale; + lcd_dma.yscale = yscale; +} +EXPORT_SYMBOL(omap_set_lcd_dma_b1_scale); + +static void set_b1_regs(void) +{ + unsigned long top, bottom; + int es; + u16 w; + unsigned long en, fn; + long ei, fi; + unsigned long vxres; + unsigned int xscale, yscale; + + switch (lcd_dma.data_type) { + case OMAP_DMA_DATA_TYPE_S8: + es = 1; + break; + case OMAP_DMA_DATA_TYPE_S16: + es = 2; + break; + case OMAP_DMA_DATA_TYPE_S32: + es = 4; + break; + default: + BUG(); + return; + } + + vxres = lcd_dma.vxres ? lcd_dma.vxres : lcd_dma.xres; + xscale = lcd_dma.xscale ? lcd_dma.xscale : 1; + yscale = lcd_dma.yscale ? lcd_dma.yscale : 1; + BUG_ON(vxres < lcd_dma.xres); + +#define PIXADDR(x, y) (lcd_dma.addr + \ + ((y) * vxres * yscale + (x) * xscale) * es) +#define PIXSTEP(sx, sy, dx, dy) (PIXADDR(dx, dy) - PIXADDR(sx, sy) - es + 1) + + switch (lcd_dma.rotate) { + case 0: + if (!lcd_dma.mirror) { + top = PIXADDR(0, 0); + bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); + /* 1510 DMA requires the bottom address to be 2 more + * than the actual last memory access location. */ + if (cpu_is_omap1510() && + lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32) + bottom += 2; + ei = PIXSTEP(0, 0, 1, 0); + fi = PIXSTEP(lcd_dma.xres - 1, 0, 0, 1); + } else { + top = PIXADDR(lcd_dma.xres - 1, 0); + bottom = PIXADDR(0, lcd_dma.yres - 1); + ei = PIXSTEP(1, 0, 0, 0); + fi = PIXSTEP(0, 0, lcd_dma.xres - 1, 1); + } + en = lcd_dma.xres; + fn = lcd_dma.yres; + break; + case 90: + if (!lcd_dma.mirror) { + top = PIXADDR(0, lcd_dma.yres - 1); + bottom = PIXADDR(lcd_dma.xres - 1, 0); + ei = PIXSTEP(0, 1, 0, 0); + fi = PIXSTEP(0, 0, 1, lcd_dma.yres - 1); + } else { + top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); + bottom = PIXADDR(0, 0); + ei = PIXSTEP(0, 1, 0, 0); + fi = PIXSTEP(1, 0, 0, lcd_dma.yres - 1); + } + en = lcd_dma.yres; + fn = lcd_dma.xres; + break; + case 180: + if (!lcd_dma.mirror) { + top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); + bottom = PIXADDR(0, 0); + ei = PIXSTEP(1, 0, 0, 0); + fi = PIXSTEP(0, 1, lcd_dma.xres - 1, 0); + } else { + top = PIXADDR(0, lcd_dma.yres - 1); + bottom = PIXADDR(lcd_dma.xres - 1, 0); + ei = PIXSTEP(0, 0, 1, 0); + fi = PIXSTEP(lcd_dma.xres - 1, 1, 0, 0); + } + en = lcd_dma.xres; + fn = lcd_dma.yres; + break; + case 270: + if (!lcd_dma.mirror) { + top = PIXADDR(lcd_dma.xres - 1, 0); + bottom = PIXADDR(0, lcd_dma.yres - 1); + ei = PIXSTEP(0, 0, 0, 1); + fi = PIXSTEP(1, lcd_dma.yres - 1, 0, 0); + } else { + top = PIXADDR(0, 0); + bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); + ei = PIXSTEP(0, 0, 0, 1); + fi = PIXSTEP(0, lcd_dma.yres - 1, 1, 0); + } + en = lcd_dma.yres; + fn = lcd_dma.xres; + break; + default: + BUG(); + return; /* Suppress warning about uninitialized vars */ + } + + if (cpu_is_omap1510()) { + omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U); + omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L); + omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U); + omap_writew(bottom, OMAP1510_DMA_LCD_BOT_F1_L); + + return; + } + + /* 1610 regs */ + omap_writew(top >> 16, OMAP1610_DMA_LCD_TOP_B1_U); + omap_writew(top, OMAP1610_DMA_LCD_TOP_B1_L); + omap_writew(bottom >> 16, OMAP1610_DMA_LCD_BOT_B1_U); + omap_writew(bottom, OMAP1610_DMA_LCD_BOT_B1_L); + + omap_writew(en, OMAP1610_DMA_LCD_SRC_EN_B1); + omap_writew(fn, OMAP1610_DMA_LCD_SRC_FN_B1); + + w = omap_readw(OMAP1610_DMA_LCD_CSDP); + w &= ~0x03; + w |= lcd_dma.data_type; + omap_writew(w, OMAP1610_DMA_LCD_CSDP); + + w = omap_readw(OMAP1610_DMA_LCD_CTRL); + /* Always set the source port as SDRAM for now*/ + w &= ~(0x03 << 6); + if (lcd_dma.callback != NULL) + w |= 1 << 1; /* Block interrupt enable */ + else + w &= ~(1 << 1); + omap_writew(w, OMAP1610_DMA_LCD_CTRL); + + if (!(lcd_dma.rotate || lcd_dma.mirror || + lcd_dma.vxres || lcd_dma.xscale || lcd_dma.yscale)) + return; + + w = omap_readw(OMAP1610_DMA_LCD_CCR); + /* Set the double-indexed addressing mode */ + w |= (0x03 << 12); + omap_writew(w, OMAP1610_DMA_LCD_CCR); + + omap_writew(ei, OMAP1610_DMA_LCD_SRC_EI_B1); + omap_writew(fi >> 16, OMAP1610_DMA_LCD_SRC_FI_B1_U); + omap_writew(fi, OMAP1610_DMA_LCD_SRC_FI_B1_L); +} + +static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id) +{ + u16 w; + + w = omap_readw(OMAP1610_DMA_LCD_CTRL); + if (unlikely(!(w & (1 << 3)))) { + printk(KERN_WARNING "Spurious LCD DMA IRQ\n"); + return IRQ_NONE; + } + /* Ack the IRQ */ + w |= (1 << 3); + omap_writew(w, OMAP1610_DMA_LCD_CTRL); + lcd_dma.active = 0; + if (lcd_dma.callback != NULL) + lcd_dma.callback(w, lcd_dma.cb_data); + + return IRQ_HANDLED; +} + +int omap_request_lcd_dma(void (*callback)(u16 status, void *data), + void *data) +{ + spin_lock_irq(&lcd_dma.lock); + if (lcd_dma.reserved) { + spin_unlock_irq(&lcd_dma.lock); + printk(KERN_ERR "LCD DMA channel already reserved\n"); + BUG(); + return -EBUSY; + } + lcd_dma.reserved = 1; + spin_unlock_irq(&lcd_dma.lock); + lcd_dma.callback = callback; + lcd_dma.cb_data = data; + lcd_dma.active = 0; + lcd_dma.single_transfer = 0; + lcd_dma.rotate = 0; + lcd_dma.vxres = 0; + lcd_dma.mirror = 0; + lcd_dma.xscale = 0; + lcd_dma.yscale = 0; + lcd_dma.ext_ctrl = 0; + lcd_dma.src_port = 0; + + return 0; +} +EXPORT_SYMBOL(omap_request_lcd_dma); + +void omap_free_lcd_dma(void) +{ + spin_lock(&lcd_dma.lock); + if (!lcd_dma.reserved) { + spin_unlock(&lcd_dma.lock); + printk(KERN_ERR "LCD DMA is not reserved\n"); + BUG(); + return; + } + if (!cpu_is_omap1510()) + omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1, + OMAP1610_DMA_LCD_CCR); + lcd_dma.reserved = 0; + spin_unlock(&lcd_dma.lock); +} +EXPORT_SYMBOL(omap_free_lcd_dma); + +void omap_enable_lcd_dma(void) +{ + u16 w; + + /* + * Set the Enable bit only if an external controller is + * connected. Otherwise the OMAP internal controller will + * start the transfer when it gets enabled. + */ + if (cpu_is_omap1510() || !lcd_dma.ext_ctrl) + return; + + w = omap_readw(OMAP1610_DMA_LCD_CTRL); + w |= 1 << 8; + omap_writew(w, OMAP1610_DMA_LCD_CTRL); + + lcd_dma.active = 1; + + w = omap_readw(OMAP1610_DMA_LCD_CCR); + w |= 1 << 7; + omap_writew(w, OMAP1610_DMA_LCD_CCR); +} +EXPORT_SYMBOL(omap_enable_lcd_dma); + +void omap_setup_lcd_dma(void) +{ + BUG_ON(lcd_dma.active); + if (!cpu_is_omap1510()) { + /* Set some reasonable defaults */ + omap_writew(0x5440, OMAP1610_DMA_LCD_CCR); + omap_writew(0x9102, OMAP1610_DMA_LCD_CSDP); + omap_writew(0x0004, OMAP1610_DMA_LCD_LCH_CTRL); + } + set_b1_regs(); + if (!cpu_is_omap1510()) { + u16 w; + + w = omap_readw(OMAP1610_DMA_LCD_CCR); + /* + * If DMA was already active set the end_prog bit to have + * the programmed register set loaded into the active + * register set. + */ + w |= 1 << 11; /* End_prog */ + if (!lcd_dma.single_transfer) + w |= (3 << 8); /* Auto_init, repeat */ + omap_writew(w, OMAP1610_DMA_LCD_CCR); + } +} +EXPORT_SYMBOL(omap_setup_lcd_dma); + +void omap_stop_lcd_dma(void) +{ + u16 w; + + lcd_dma.active = 0; + if (cpu_is_omap1510() || !lcd_dma.ext_ctrl) + return; + + w = omap_readw(OMAP1610_DMA_LCD_CCR); + w &= ~(1 << 7); + omap_writew(w, OMAP1610_DMA_LCD_CCR); + + w = omap_readw(OMAP1610_DMA_LCD_CTRL); + w &= ~(1 << 8); + omap_writew(w, OMAP1610_DMA_LCD_CTRL); +} +EXPORT_SYMBOL(omap_stop_lcd_dma); + +static int __init omap_init_lcd_dma(void) +{ + int r; + + if (cpu_is_omap16xx()) { + u16 w; + + /* this would prevent OMAP sleep */ + w = omap_readw(OMAP1610_DMA_LCD_CTRL); + w &= ~(1 << 8); + omap_writew(w, OMAP1610_DMA_LCD_CTRL); + } + + spin_lock_init(&lcd_dma.lock); + + r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0, + "LCD DMA", NULL); + if (r != 0) + printk(KERN_ERR "unable to request IRQ for LCD DMA " + "(error %d)\n", r); + + return r; +} + +arch_initcall(omap_init_lcd_dma); + diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c index 785371e982fc3296e40b2340676e04bbb6118018..07212cc621ae27716c43b4bbf6a81f5ff9c990d5 100644 --- a/arch/arm/mach-omap1/mux.c +++ b/arch/arm/mach-omap1/mux.c @@ -50,12 +50,18 @@ MUX_CFG_7XX("E3_7XX_KBC4", 13, 25, 0, 24, 1, 0) MUX_CFG_7XX("AA17_7XX_USB_DM", 2, 21, 0, 20, 0, 0) MUX_CFG_7XX("W16_7XX_USB_PU_EN", 2, 25, 0, 24, 0, 0) -MUX_CFG_7XX("W17_7XX_USB_VBUSI", 2, 29, 0, 28, 0, 0) +MUX_CFG_7XX("W17_7XX_USB_VBUSI", 2, 29, 6, 28, 1, 0) +MUX_CFG_7XX("W18_7XX_USB_DMCK_OUT",3, 3, 1, 2, 0, 0) +MUX_CFG_7XX("W19_7XX_USB_DCRST", 3, 7, 1, 6, 0, 0) /* MMC Pins */ MUX_CFG_7XX("MMC_7XX_CMD", 2, 9, 0, 8, 1, 0) MUX_CFG_7XX("MMC_7XX_CLK", 2, 13, 0, 12, 1, 0) MUX_CFG_7XX("MMC_7XX_DAT0", 2, 17, 0, 16, 1, 0) + +/* I2C interface */ +MUX_CFG_7XX("I2C_7XX_SCL", 5, 1, 0, 0, 1, 0) +MUX_CFG_7XX("I2C_7XX_SDA", 5, 5, 0, 0, 1, 0) }; #define OMAP7XX_PINS_SZ ARRAY_SIZE(omap7xx_pins) #else diff --git a/arch/arm/mach-omap1/opp.h b/arch/arm/mach-omap1/opp.h new file mode 100644 index 0000000000000000000000000000000000000000..07074d79adcea5aae223d890d0f5e4239e696041 --- /dev/null +++ b/arch/arm/mach-omap1/opp.h @@ -0,0 +1,28 @@ +/* + * linux/arch/arm/mach-omap1/opp.h + * + * Copyright (C) 2004 - 2005 Nokia corporation + * Written by Tuukka Tikkanen + * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ARCH_ARM_MACH_OMAP1_OPP_H +#define __ARCH_ARM_MACH_OMAP1_OPP_H + +#include + +struct mpu_rate { + unsigned long rate; + unsigned long xtal; + unsigned long pll_rate; + __u16 ckctl_val; + __u16 dpllctl_val; +}; + +extern struct mpu_rate omap1_rate_table[]; + +#endif diff --git a/arch/arm/mach-omap1/opp_data.c b/arch/arm/mach-omap1/opp_data.c new file mode 100644 index 0000000000000000000000000000000000000000..75a5465149947aeeba33adbfdec804d595d2256c --- /dev/null +++ b/arch/arm/mach-omap1/opp_data.c @@ -0,0 +1,59 @@ +/* + * linux/arch/arm/mach-omap1/opp_data.c + * + * Copyright (C) 2004 - 2005 Nokia corporation + * Written by Tuukka Tikkanen + * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "opp.h" + +/*------------------------------------------------------------------------- + * Omap1 MPU rate table + *-------------------------------------------------------------------------*/ +struct mpu_rate omap1_rate_table[] = { + /* MPU MHz, xtal MHz, dpll1 MHz, CKCTL, DPLL_CTL + * NOTE: Comment order here is different from bits in CKCTL value: + * armdiv, dspdiv, dspmmu, tcdiv, perdiv, lcddiv + */ +#if defined(CONFIG_OMAP_ARM_216MHZ) + { 216000000, 12000000, 216000000, 0x050d, 0x2910 }, /* 1/1/2/2/2/8 */ +#endif +#if defined(CONFIG_OMAP_ARM_195MHZ) + { 195000000, 13000000, 195000000, 0x050e, 0x2790 }, /* 1/1/2/2/4/8 */ +#endif +#if defined(CONFIG_OMAP_ARM_192MHZ) + { 192000000, 19200000, 192000000, 0x050f, 0x2510 }, /* 1/1/2/2/8/8 */ + { 192000000, 12000000, 192000000, 0x050f, 0x2810 }, /* 1/1/2/2/8/8 */ + { 96000000, 12000000, 192000000, 0x055f, 0x2810 }, /* 2/2/2/2/8/8 */ + { 48000000, 12000000, 192000000, 0x0baf, 0x2810 }, /* 4/4/4/8/8/8 */ + { 24000000, 12000000, 192000000, 0x0fff, 0x2810 }, /* 8/8/8/8/8/8 */ +#endif +#if defined(CONFIG_OMAP_ARM_182MHZ) + { 182000000, 13000000, 182000000, 0x050e, 0x2710 }, /* 1/1/2/2/4/8 */ +#endif +#if defined(CONFIG_OMAP_ARM_168MHZ) + { 168000000, 12000000, 168000000, 0x010f, 0x2710 }, /* 1/1/1/2/8/8 */ +#endif +#if defined(CONFIG_OMAP_ARM_150MHZ) + { 150000000, 12000000, 150000000, 0x010a, 0x2cb0 }, /* 1/1/1/2/4/4 */ +#endif +#if defined(CONFIG_OMAP_ARM_120MHZ) + { 120000000, 12000000, 120000000, 0x010a, 0x2510 }, /* 1/1/1/2/4/4 */ +#endif +#if defined(CONFIG_OMAP_ARM_96MHZ) + { 96000000, 12000000, 96000000, 0x0005, 0x2410 }, /* 1/1/1/1/2/2 */ +#endif +#if defined(CONFIG_OMAP_ARM_60MHZ) + { 60000000, 12000000, 60000000, 0x0005, 0x2290 }, /* 1/1/1/1/2/2 */ +#endif +#if defined(CONFIG_OMAP_ARM_30MHZ) + { 30000000, 12000000, 60000000, 0x0555, 0x2290 }, /* 2/2/2/2/2/2 */ +#endif + { 0, 0, 0, 0, 0 }, +}; + diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 7309aab305a98a85d535a6f8ec8791ecac334799..76c11ee113e9f38cbbb96e3f177de65fe7396232 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -24,6 +24,18 @@ config ARCH_OMAP3430 depends on ARCH_OMAP3 && ARCH_OMAP34XX select ARCH_OMAP_OTG +config OMAP_PACKAGE_CBC + bool + +config OMAP_PACKAGE_CBB + bool + +config OMAP_PACKAGE_CUS + bool + +config OMAP_PACKAGE_CBP + bool + comment "OMAP Board Type" depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4 @@ -52,14 +64,17 @@ config MACH_OMAP_2430SDP config MACH_OMAP3_BEAGLE bool "OMAP3 BEAGLE board" depends on ARCH_OMAP3 && ARCH_OMAP34XX + select OMAP_PACKAGE_CBB config MACH_OMAP_LDP bool "OMAP3 LDP board" depends on ARCH_OMAP3 && ARCH_OMAP34XX + select OMAP_PACKAGE_CBB config MACH_OVERO bool "Gumstix Overo board" depends on ARCH_OMAP3 && ARCH_OMAP34XX + select OMAP_PACKAGE_CBB config MACH_OMAP3EVM bool "OMAP 3530 EVM board" @@ -68,14 +83,22 @@ config MACH_OMAP3EVM config MACH_OMAP3517EVM bool "OMAP3517/ AM3517 EVM board" depends on ARCH_OMAP3 && ARCH_OMAP34XX + select OMAP_PACKAGE_CBB config MACH_OMAP3_PANDORA bool "OMAP3 Pandora" depends on ARCH_OMAP3 && ARCH_OMAP34XX + select OMAP_PACKAGE_CBB + +config MACH_OMAP3_TOUCHBOOK + bool "OMAP3 Touch Book" + depends on ARCH_OMAP3 && ARCH_OMAP34XX + select BACKLIGHT_CLASS_DEVICE config MACH_OMAP_3430SDP bool "OMAP 3430 SDP board" depends on ARCH_OMAP3 && ARCH_OMAP34XX + select OMAP_PACKAGE_CBB config MACH_NOKIA_N800 bool @@ -96,26 +119,33 @@ config MACH_NOKIA_N8X0 config MACH_NOKIA_RX51 bool "Nokia RX-51 board" depends on ARCH_OMAP3 && ARCH_OMAP34XX + select OMAP_PACKAGE_CBB config MACH_OMAP_ZOOM2 bool "OMAP3 Zoom2 board" depends on ARCH_OMAP3 && ARCH_OMAP34XX + select OMAP_PACKAGE_CBB config MACH_OMAP_ZOOM3 bool "OMAP3630 Zoom3 board" depends on ARCH_OMAP3 && ARCH_OMAP34XX + select OMAP_PACKAGE_CBP config MACH_CM_T35 bool "CompuLab CM-T35 module" depends on ARCH_OMAP3 && ARCH_OMAP34XX + select OMAP_PACKAGE_CUS + select OMAP_MUX config MACH_IGEP0020 bool "IGEP0020" depends on ARCH_OMAP3 && ARCH_OMAP34XX + select OMAP_PACKAGE_CBB config MACH_OMAP_3630SDP bool "OMAP3630 SDP board" depends on ARCH_OMAP3 && ARCH_OMAP34XX + select OMAP_PACKAGE_CBP config MACH_OMAP_4430SDP bool "OMAP 4430 SDP board" @@ -128,3 +158,15 @@ config OMAP3_EMU help Say Y here to enable debugging hardware of omap3 +config OMAP3_SDRC_AC_TIMING + bool "Enable SDRC AC timing register changes" + depends on ARCH_OMAP3 && ARCH_OMAP34XX + default n + help + If you know that none of your system initiators will attempt to + access SDRAM during CORE DVFS, select Y here. This should boost + SDRAM performance at lower CORE OPPs. There are relatively few + users who will wish to say yes at this point - almost everyone will + wish to say no. Selecting yes without understanding what is + going on could result in system crashes; + diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 32548a4510c51b89e3fc3637fcf306dcc712a77d..b32678b848bc8d3a838cdae59059bae230ec3ea7 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -6,11 +6,14 @@ obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o omap-2-3-common = irq.o sdrc.o omap_hwmod.o +omap-3-4-common = dpll.o prcm-common = prcm.o powerdomain.o -clock-common = clock.o clockdomain.o +clock-common = clock.o clock_common_data.o clockdomain.o obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(prcm-common) $(clock-common) -obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(prcm-common) $(clock-common) +obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(prcm-common) $(clock-common) \ + $(omap-3-4-common) +obj-$(CONFIG_ARCH_OMAP4) += $(omap-3-4-common) prcm.o clock.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o @@ -23,6 +26,9 @@ obj-$(CONFIG_ARCH_OMAP2420) += sram242x.o obj-$(CONFIG_ARCH_OMAP2430) += sram243x.o obj-$(CONFIG_ARCH_OMAP3) += sram34xx.o +# Pin multiplexing +obj-$(CONFIG_ARCH_OMAP3) += mux34xx.o + # SMS/SDRC obj-$(CONFIG_ARCH_OMAP2) += sdrc2xxx.o # obj-$(CONFIG_ARCH_OMAP3) += sdrc3xxx.o @@ -41,8 +47,11 @@ obj-$(CONFIG_ARCH_OMAP3) += cm.o obj-$(CONFIG_ARCH_OMAP4) += cm4xxx.o # Clock framework -obj-$(CONFIG_ARCH_OMAP2) += clock24xx.o -obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o +obj-$(CONFIG_ARCH_OMAP2) += clock2xxx.o clock2xxx_data.o +obj-$(CONFIG_ARCH_OMAP2420) += opp2420_data.o +obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o clock34xx_data.o +obj-$(CONFIG_ARCH_OMAP2430) += opp2430_data.o +obj-$(CONFIG_ARCH_OMAP4) += clock44xx.o clock44xx_data.o # EMU peripherals obj-$(CONFIG_OMAP3_EMU) += emu.o @@ -55,6 +64,9 @@ iommu-$(CONFIG_ARCH_OMAP3) += omap3-iommu.o obj-$(CONFIG_OMAP_IOMMU) += $(iommu-y) +i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o +obj-y += $(i2c-omap-m) $(i2c-omap-y) + # Specific board support obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o @@ -93,7 +105,8 @@ obj-$(CONFIG_MACH_CM_T35) += board-cm-t35.o \ mmc-twl4030.o obj-$(CONFIG_MACH_IGEP0020) += board-igep0020.o \ mmc-twl4030.o - +obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK) += board-omap3touchbook.o \ + mmc-twl4030.o obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index db9374bc528b588f8b51545dd8e686d4c10bef00..e508904fb67e3addfe4066f44860e6ecd737afd8 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 491364e44c7d02629671896d5170e9ac556a5f3f..c90b0d0b1927e58911dad6d7bfe593b712323557 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -31,16 +31,17 @@ #include #include -#include #include #include #include #include #include +#include #include #include +#include "mux.h" #include "sdram-qimonda-hyb18m512160af-6.h" #include "mmc-twl4030.h" @@ -152,31 +153,152 @@ static struct spi_board_info sdp3430_spi_board_info[] __initdata = { }, }; -static struct platform_device sdp3430_lcd_device = { - .name = "sdp2430_lcd", - .id = -1, + +#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8 +#define SDP3430_LCD_PANEL_ENABLE_GPIO 5 + +static unsigned backlight_gpio; +static unsigned enable_gpio; +static int lcd_enabled; +static int dvi_enabled; + +static void __init sdp3430_display_init(void) +{ + int r; + + enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO; + backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO; + + r = gpio_request(enable_gpio, "LCD reset"); + if (r) { + printk(KERN_ERR "failed to get LCD reset GPIO\n"); + goto err0; + } + + r = gpio_request(backlight_gpio, "LCD Backlight"); + if (r) { + printk(KERN_ERR "failed to get LCD backlight GPIO\n"); + goto err1; + } + + gpio_direction_output(enable_gpio, 0); + gpio_direction_output(backlight_gpio, 0); + + return; +err1: + gpio_free(enable_gpio); +err0: + return; +} + +static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev) +{ + if (dvi_enabled) { + printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); + return -EINVAL; + } + + gpio_direction_output(enable_gpio, 1); + gpio_direction_output(backlight_gpio, 1); + + lcd_enabled = 1; + + return 0; +} + +static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev) +{ + lcd_enabled = 0; + + gpio_direction_output(enable_gpio, 0); + gpio_direction_output(backlight_gpio, 0); +} + +static int sdp3430_panel_enable_dvi(struct omap_dss_device *dssdev) +{ + if (lcd_enabled) { + printk(KERN_ERR "cannot enable DVI, LCD is enabled\n"); + return -EINVAL; + } + + dvi_enabled = 1; + + return 0; +} + +static void sdp3430_panel_disable_dvi(struct omap_dss_device *dssdev) +{ + dvi_enabled = 0; +} + +static int sdp3430_panel_enable_tv(struct omap_dss_device *dssdev) +{ + return 0; +} + +static void sdp3430_panel_disable_tv(struct omap_dss_device *dssdev) +{ +} + + +static struct omap_dss_device sdp3430_lcd_device = { + .name = "lcd", + .driver_name = "sharp_ls_panel", + .type = OMAP_DISPLAY_TYPE_DPI, + .phy.dpi.data_lines = 16, + .platform_enable = sdp3430_panel_enable_lcd, + .platform_disable = sdp3430_panel_disable_lcd, }; -static struct regulator_consumer_supply sdp3430_vdac_supply = { - .supply = "vdac", - .dev = &sdp3430_lcd_device.dev, +static struct omap_dss_device sdp3430_dvi_device = { + .name = "dvi", + .driver_name = "generic_panel", + .type = OMAP_DISPLAY_TYPE_DPI, + .phy.dpi.data_lines = 24, + .platform_enable = sdp3430_panel_enable_dvi, + .platform_disable = sdp3430_panel_disable_dvi, }; -static struct regulator_consumer_supply sdp3430_vdvi_supply = { - .supply = "vdvi", - .dev = &sdp3430_lcd_device.dev, +static struct omap_dss_device sdp3430_tv_device = { + .name = "tv", + .driver_name = "venc", + .type = OMAP_DISPLAY_TYPE_VENC, + .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, + .platform_enable = sdp3430_panel_enable_tv, + .platform_disable = sdp3430_panel_disable_tv, }; -static struct platform_device *sdp3430_devices[] __initdata = { + +static struct omap_dss_device *sdp3430_dss_devices[] = { &sdp3430_lcd_device, + &sdp3430_dvi_device, + &sdp3430_tv_device, +}; + +static struct omap_dss_board_info sdp3430_dss_data = { + .num_devices = ARRAY_SIZE(sdp3430_dss_devices), + .devices = sdp3430_dss_devices, + .default_device = &sdp3430_lcd_device, }; -static struct omap_lcd_config sdp3430_lcd_config __initdata = { - .ctrl_name = "internal", +static struct platform_device sdp3430_dss_device = { + .name = "omapdss", + .id = -1, + .dev = { + .platform_data = &sdp3430_dss_data, + }, +}; + +static struct regulator_consumer_supply sdp3430_vdda_dac_supply = { + .supply = "vdda_dac", + .dev = &sdp3430_dss_device.dev, +}; + +static struct platform_device *sdp3430_devices[] __initdata = { + &sdp3430_dss_device, }; static struct omap_board_config_kernel sdp3430_config[] __initdata = { - { OMAP_TAG_LCD, &sdp3430_lcd_config }, }; static void __init omap_3430sdp_init_irq(void) @@ -392,22 +514,34 @@ static struct regulator_init_data sdp3430_vdac = { | REGULATOR_CHANGE_STATUS, }, .num_consumer_supplies = 1, - .consumer_supplies = &sdp3430_vdac_supply, + .consumer_supplies = &sdp3430_vdda_dac_supply, }; /* VPLL2 for digital video outputs */ +static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = { + { + .supply = "vdvi", + .dev = &sdp3430_lcd_device.dev, + }, + { + .supply = "vdds_dsi", + .dev = &sdp3430_dss_device.dev, + } +}; + static struct regulator_init_data sdp3430_vpll2 = { .constraints = { .name = "VDVI", .min_uV = 1800000, .max_uV = 1800000, + .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &sdp3430_vdvi_supply, + .num_consumer_supplies = ARRAY_SIZE(sdp3430_vpll2_supplies), + .consumer_supplies = sdp3430_vpll2_supplies, }; static struct twl4030_codec_audio_data sdp3430_audio = { @@ -491,7 +625,9 @@ static inline void board_smc91x_init(void) static void enable_board_wakeup_source(void) { - omap_cfg_reg(AF26_34XX_SYS_NIRQ); /* T2 interrupt line (keypad) */ + /* T2 interrupt line (keypad) */ + omap_mux_init_signal("sys_nirq", + OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP); } static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { @@ -506,8 +642,17 @@ static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { .reset_gpio_port[2] = -EINVAL }; +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define board_mux NULL +#endif + static void __init omap_3430sdp_init(void) { + omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); omap3430_i2c_init(); platform_add_devices(sdp3430_devices, ARRAY_SIZE(sdp3430_devices)); if (omap_rev() > OMAP3430_REV_ES1_0) @@ -521,6 +666,7 @@ static void __init omap_3430sdp_init(void) omap_serial_init(); usb_musb_init(); board_smc91x_init(); + sdp3430_display_init(); enable_board_wakeup_source(); usb_ehci_init(&ehci_pdata); } diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c index 348b70b983366cab7712c829adc30f50879527d8..7390596328116b2972c1e3ceb6c232c283003d1f 100755 --- a/arch/arm/mach-omap2/board-3630sdp.c +++ b/arch/arm/mach-omap2/board-3630sdp.c @@ -23,6 +23,7 @@ #include +#include "mux.h" #include "sdram-hynix-h8mbx00u0mer-0em.h" #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) @@ -48,7 +49,9 @@ static inline void board_smc91x_init(void) static void enable_board_wakeup_source(void) { - omap_cfg_reg(AF26_34XX_SYS_NIRQ); /* T2 interrupt line (keypad) */ + /* T2 interrupt line (keypad) */ + omap_mux_init_signal("sys_nirq", + OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP); } static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { @@ -82,8 +85,17 @@ static void __init omap_sdp_init_irq(void) omap_gpio_init(); } +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define board_mux NULL +#endif + static void __init omap_sdp_init(void) { + omap3_mux_init(board_mux, OMAP_PACKAGE_CBP); zoom_peripherals_init(); board_smc91x_init(); enable_board_wakeup_source(); diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 415a13d767cc48a79288e322a6d666fe48da92e2..b4e6eca0e8a9b373d2744f1a3be78f4bcb3262d9 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -30,6 +30,8 @@ #include #include +#include "mux.h" + /* * Board initialization */ @@ -60,8 +62,17 @@ static struct ehci_hcd_omap_platform_data ehci_pdata __initdata = { .reset_gpio_port[2] = -EINVAL }; +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define board_mux NULL +#endif + static void __init am3517_evm_init(void) { + omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); platform_add_devices(am3517_evm_devices, ARRAY_SIZE(am3517_evm_devices)); diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 8a2ce77a02ecbe8f65398e6021a7f74f8229bc10..fbbd68d69cc8cc50d0f426bcc67db622f1bf5c16 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -120,6 +121,12 @@ static void __init apollon_flash_init(void) apollon_flash_resource[0].end = base + SZ_128K - 1; } +static struct smc91x_platdata appolon_smc91x_info = { + .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, + .leda = RPC_LED_100_10, + .ledb = RPC_LED_TX_RX, +}; + static struct resource apollon_smc91x_resources[] = { [0] = { .flags = IORESOURCE_MEM, @@ -134,6 +141,9 @@ static struct resource apollon_smc91x_resources[] = { static struct platform_device apollon_smc91x_device = { .name = "smc91x", .id = -1, + .dev = { + .platform_data = &appolon_smc91x_info, + }, .num_resources = ARRAY_SIZE(apollon_smc91x_resources), .resource = apollon_smc91x_resources, }; diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index 22c45290db634b3c607007867cf36a3893ccd2ce..1591aae645006be6f47edcc322ad49b175bd83ab 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -38,13 +38,13 @@ #include #include -#include #include #include #include #include +#include "mux.h" #include "sdram-micron-mt46h32m32lf-6.h" #include "mmc-twl4030.h" @@ -482,8 +482,102 @@ static void __init cm_t35_map_io(void) omap2_map_common_io(); } +static struct omap_board_mux board_mux[] __initdata = { + /* nCS and IRQ for CM-T35 ethernet */ + OMAP3_MUX(GPMC_NCS5, OMAP_MUX_MODE0), + OMAP3_MUX(UART3_CTS_RCTX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP), + + /* nCS and IRQ for SB-T35 ethernet */ + OMAP3_MUX(GPMC_NCS4, OMAP_MUX_MODE0), + OMAP3_MUX(GPMC_WAIT3, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP), + + /* PENDOWN GPIO */ + OMAP3_MUX(GPMC_NCS6, OMAP_MUX_MODE4 | OMAP_PIN_INPUT), + + /* mUSB */ + OMAP3_MUX(HSUSB0_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(HSUSB0_STP, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(HSUSB0_DIR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(HSUSB0_NXT, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(HSUSB0_DATA0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(HSUSB0_DATA1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(HSUSB0_DATA2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(HSUSB0_DATA3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(HSUSB0_DATA4, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(HSUSB0_DATA5, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(HSUSB0_DATA6, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(HSUSB0_DATA7, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + + /* MMC 2 */ + OMAP3_MUX(SDMMC2_DAT4, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT), + OMAP3_MUX(SDMMC2_DAT5, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT), + OMAP3_MUX(SDMMC2_DAT6, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT), + OMAP3_MUX(SDMMC2_DAT7, OMAP_MUX_MODE1 | OMAP_PIN_INPUT), + + /* McSPI 1 */ + OMAP3_MUX(MCSPI1_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(MCSPI1_SIMO, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(MCSPI1_SOMI, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(MCSPI1_CS0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN), + + /* McSPI 4 */ + OMAP3_MUX(MCBSP1_CLKR, OMAP_MUX_MODE1 | OMAP_PIN_INPUT), + OMAP3_MUX(MCBSP1_DX, OMAP_MUX_MODE1 | OMAP_PIN_INPUT), + OMAP3_MUX(MCBSP1_DR, OMAP_MUX_MODE1 | OMAP_PIN_INPUT), + OMAP3_MUX(MCBSP1_FSX, OMAP_MUX_MODE1 | OMAP_PIN_INPUT_PULLUP), + + /* McBSP 2 */ + OMAP3_MUX(MCBSP2_FSX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(MCBSP2_CLKX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(MCBSP2_DR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + OMAP3_MUX(MCBSP2_DX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + + /* serial ports */ + OMAP3_MUX(MCBSP3_CLKX, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT), + OMAP3_MUX(MCBSP3_FSX, OMAP_MUX_MODE1 | OMAP_PIN_INPUT), + OMAP3_MUX(UART1_TX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(UART1_RX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), + + /* DSS */ + OMAP3_MUX(DSS_PCLK, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_HSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_VSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_ACBIAS, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA0, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA1, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA2, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA3, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA4, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA5, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA6, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA7, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA8, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA9, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA10, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA11, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA12, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA13, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA14, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA15, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA16, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA17, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA18, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA19, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA20, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA21, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA23, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + + /* TPS IRQ */ + OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_WAKEUP_EN | \ + OMAP_PIN_INPUT_PULLUP), + + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; + static void __init cm_t35_init(void) { + omap3_mux_init(board_mux, OMAP_PACKAGE_CUS); omap_serial_init(); cm_t35_init_i2c(); cm_t35_init_nand(); @@ -492,8 +586,6 @@ static void __init cm_t35_init(void) cm_t35_init_led(); usb_musb_init(); - - omap_cfg_reg(AF26_34XX_SYS_NIRQ); } MACHINE_START(CM_T35, "Compulab CM-T35") diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index fa62e80c13b7c7d3aab3feacbb02d5a16188b7a9..44239e3ec02e802ec45d281043e56bec3207aec0 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -27,9 +27,9 @@ #include #include #include -#include #include +#include "mux.h" #include "mmc-twl4030.h" #define IGEP2_SMSC911X_CS 5 @@ -203,8 +203,17 @@ static int __init igep2_i2c_init(void) return 0; } +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define board_mux NULL +#endif + static void __init igep2_init(void) { + omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); igep2_i2c_init(); omap_serial_init(); usb_musb_init(); diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index c062238fe88144c1d81c949d0ac28c2a2f3b2cf3..995d4a2b2dfd5fa61c7337ee350d1e0e60b5f000 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -43,6 +43,7 @@ #include #include +#include "mux.h" #include "mmc-twl4030.h" #define LDP_SMSC911X_CS 1 @@ -374,8 +375,17 @@ static struct platform_device *ldp_devices[] __initdata = { &ldp_gpio_keys_device, }; +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define board_mux NULL +#endif + static void __init omap_ldp_init(void) { + omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); omap_i2c_init(); platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices)); ts_gpio = 54; diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 41480bd0e58a669b698b36a61d07c730a7d2366b..231cb4ec1847cfd51c038e2d533c7f40ae9d1295 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include @@ -41,10 +41,10 @@ #include #include #include -#include #include #include +#include "mux.h" #include "mmc-twl4030.h" #define GPMC_CS0_BASE 0x60 @@ -140,10 +140,10 @@ static int beagle_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { if (system_rev >= 0x20 && system_rev <= 0x34301000) { - omap_cfg_reg(AG9_34XX_GPIO23); + omap_mux_init_gpio(23, OMAP_PIN_INPUT); mmc[0].gpio_wp = 23; } else { - omap_cfg_reg(AH8_34XX_GPIO29); + omap_mux_init_gpio(29, OMAP_PIN_INPUT); } /* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0].gpio_cd = gpio + 0; @@ -422,14 +422,23 @@ static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { .reset_gpio_port[2] = -EINVAL }; +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define board_mux NULL +#endif + static void __init omap3_beagle_init(void) { + omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); omap3_beagle_i2c_init(); platform_add_devices(omap3_beagle_devices, ARRAY_SIZE(omap3_beagle_devices)); omap_serial_init(); - omap_cfg_reg(J25_34XX_GPIO170); + omap_mux_init_gpio(170, OMAP_PIN_INPUT); gpio_request(170, "DVI_nPD"); /* REVISIT leave DVI powered down until it's needed ... */ gpio_direction_output(170, true); @@ -439,8 +448,8 @@ static void __init omap3_beagle_init(void) omap3beagle_flash_init(); /* Ensure SDRC pins are mux'd for self-refresh */ - omap_cfg_reg(H16_34XX_SDRC_CKE0); - omap_cfg_reg(H17_34XX_SDRC_CKE1); + omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); + omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); } static void __init omap3_beagle_map_io(void) diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index 5efc2e9068db8f549ebce1e009043da2405961d0..18913e96e34d3fd3b66200156175938fc3c0e214 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -38,11 +38,11 @@ #include #include -#include #include #include #include +#include "mux.h" #include "sdram-micron-mt46h32m32lf-6.h" #include "mmc-twl4030.h" @@ -223,7 +223,7 @@ static int omap3evm_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { /* gpio + 0 is "mmc0_cd" (input/IRQ) */ - omap_cfg_reg(L8_34XX_GPIO63); + omap_mux_init_gpio(63, OMAP_PIN_INPUT); mmc[0].gpio_cd = gpio + 0; twl4030_mmc_init(mmc); @@ -422,9 +422,18 @@ static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { .reset_gpio_port[2] = -EINVAL }; +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define board_mux NULL +#endif + static void __init omap3_evm_init(void) { omap3_evm_get_revision(); + omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); omap3_evm_i2c_init(); @@ -440,24 +449,24 @@ static void __init omap3_evm_init(void) #endif if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) { /* enable EHCI VBUS using GPIO22 */ - omap_cfg_reg(AF9_34XX_GPIO22); + omap_mux_init_gpio(22, OMAP_PIN_INPUT_PULLUP); gpio_request(OMAP3_EVM_EHCI_VBUS, "enable EHCI VBUS"); gpio_direction_output(OMAP3_EVM_EHCI_VBUS, 0); gpio_set_value(OMAP3_EVM_EHCI_VBUS, 1); /* Select EHCI port on main board */ - omap_cfg_reg(U3_34XX_GPIO61); + omap_mux_init_gpio(61, OMAP_PIN_INPUT_PULLUP); gpio_request(OMAP3_EVM_EHCI_SELECT, "select EHCI port"); gpio_direction_output(OMAP3_EVM_EHCI_SELECT, 0); gpio_set_value(OMAP3_EVM_EHCI_SELECT, 0); /* setup EHCI phy reset config */ - omap_cfg_reg(AH14_34XX_GPIO21); + omap_mux_init_gpio(21, OMAP_PIN_INPUT_PULLUP); ehci_pdata.reset_gpio_port[1] = 21; } else { /* setup EHCI phy reset on MDC */ - omap_cfg_reg(AF4_34XX_GPIO135_OUT); + omap_mux_init_gpio(135, OMAP_PIN_OUTPUT); ehci_pdata.reset_gpio_port[1] = 135; } usb_musb_init(); diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 2db5ba5b3bf7d4bf7c33c8d48fa6d6a447a7b861..ef17cf1ab6d7cc37b132a30d3b443ea4e93f9bf0 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -40,8 +40,8 @@ #include #include #include -#include +#include "mux.h" #include "sdram-micron-mt46h32m32lf-6.h" #include "mmc-twl4030.h" @@ -98,10 +98,10 @@ static struct gpio_keys_button pandora_gpio_keys[] = { GPIO_BUTTON_LOW(103, KEY_DOWN, "down"), GPIO_BUTTON_LOW(96, KEY_LEFT, "left"), GPIO_BUTTON_LOW(98, KEY_RIGHT, "right"), - GPIO_BUTTON_LOW(111, BTN_A, "a"), - GPIO_BUTTON_LOW(106, BTN_B, "b"), - GPIO_BUTTON_LOW(109, BTN_X, "x"), - GPIO_BUTTON_LOW(101, BTN_Y, "y"), + GPIO_BUTTON_LOW(109, KEY_KP1, "game 1"), + GPIO_BUTTON_LOW(111, KEY_KP2, "game 2"), + GPIO_BUTTON_LOW(106, KEY_KP3, "game 3"), + GPIO_BUTTON_LOW(101, KEY_KP4, "game 4"), GPIO_BUTTON_LOW(102, BTN_TL, "l"), GPIO_BUTTON_LOW(97, BTN_TL2, "l2"), GPIO_BUTTON_LOW(105, BTN_TR, "r"), @@ -315,7 +315,7 @@ static int __init omap3pandora_i2c_init(void) omap_register_i2c_bus(1, 2600, omap3pandora_i2c_boardinfo, ARRAY_SIZE(omap3pandora_i2c_boardinfo)); /* i2c2 pins are not connected */ - omap_register_i2c_bus(3, 400, NULL, 0); + omap_register_i2c_bus(3, 100, NULL, 0); return 0; } @@ -368,23 +368,8 @@ static struct spi_board_info omap3pandora_spi_board_info[] __initdata = { } }; -static struct platform_device omap3pandora_lcd_device = { - .name = "pandora_lcd", - .id = -1, -}; - -static struct omap_lcd_config omap3pandora_lcd_config __initdata = { - .ctrl_name = "internal", -}; - -static struct omap_board_config_kernel omap3pandora_config[] __initdata = { - { OMAP_TAG_LCD, &omap3pandora_lcd_config }, -}; - static void __init omap3pandora_init_irq(void) { - omap_board_config = omap3pandora_config; - omap_board_config_size = ARRAY_SIZE(omap3pandora_config); omap2_init_common_hw(mt46h32m32lf6_sdrc_params, mt46h32m32lf6_sdrc_params); omap_init_irq(); @@ -392,7 +377,6 @@ static void __init omap3pandora_init_irq(void) } static struct platform_device *omap3pandora_devices[] __initdata = { - &omap3pandora_lcd_device, &pandora_leds_gpio, &pandora_keys_gpio, }; @@ -409,8 +393,17 @@ static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { .reset_gpio_port[2] = -EINVAL }; +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define board_mux NULL +#endif + static void __init omap3pandora_init(void) { + omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); omap3pandora_i2c_init(); platform_add_devices(omap3pandora_devices, ARRAY_SIZE(omap3pandora_devices)); @@ -423,8 +416,8 @@ static void __init omap3pandora_init(void) usb_musb_init(); /* Ensure SDRC pins are mux'd for self-refresh */ - omap_cfg_reg(H16_34XX_SDRC_CKE0); - omap_cfg_reg(H17_34XX_SDRC_CKE1); + omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); + omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); } static void __init omap3pandora_map_io(void) diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c new file mode 100644 index 0000000000000000000000000000000000000000..c9e5ebb4d91d5ba4b8090e5631b9fdfc0e0f3840 --- /dev/null +++ b/arch/arm/mach-omap2/board-omap3touchbook.c @@ -0,0 +1,572 @@ +/* + * linux/arch/arm/mach-omap2/board-omap3touchbook.c + * + * Copyright (C) 2009 Always Innovating + * + * Modified from mach-omap2/board-omap3beagleboard.c + * + * Initial code: Grégoire Gentil, Tim Yamin + * + * 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 +#include + +#include +#include +#include +#include +#include +#include + +#include "mux.h" +#include "mmc-twl4030.h" + +#include + +#define GPMC_CS0_BASE 0x60 +#define GPMC_CS_SIZE 0x30 + +#define NAND_BLOCK_SIZE SZ_128K + +#define OMAP3_AC_GPIO 136 +#define OMAP3_TS_GPIO 162 +#define TB_BL_PWM_TIMER 9 +#define TB_KILL_POWER_GPIO 168 + +unsigned long touchbook_revision; + +static struct mtd_partition omap3touchbook_nand_partitions[] = { + /* All the partition sizes are listed in terms of NAND block size */ + { + .name = "X-Loader", + .offset = 0, + .size = 4 * NAND_BLOCK_SIZE, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + { + .name = "U-Boot", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */ + .size = 15 * NAND_BLOCK_SIZE, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + { + .name = "U-Boot Env", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x260000 */ + .size = 1 * NAND_BLOCK_SIZE, + }, + { + .name = "Kernel", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */ + .size = 32 * NAND_BLOCK_SIZE, + }, + { + .name = "File System", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x680000 */ + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct omap_nand_platform_data omap3touchbook_nand_data = { + .options = NAND_BUSWIDTH_16, + .parts = omap3touchbook_nand_partitions, + .nr_parts = ARRAY_SIZE(omap3touchbook_nand_partitions), + .dma_channel = -1, /* disable DMA in OMAP NAND driver */ + .nand_setup = NULL, + .dev_ready = NULL, +}; + +static struct resource omap3touchbook_nand_resource = { + .flags = IORESOURCE_MEM, +}; + +static struct platform_device omap3touchbook_nand_device = { + .name = "omap2-nand", + .id = -1, + .dev = { + .platform_data = &omap3touchbook_nand_data, + }, + .num_resources = 1, + .resource = &omap3touchbook_nand_resource, +}; + +#include "sdram-micron-mt46h32m32lf-6.h" + +static struct twl4030_hsmmc_info mmc[] = { + { + .mmc = 1, + .wires = 8, + .gpio_wp = 29, + }, + {} /* Terminator */ +}; + +static struct platform_device omap3_touchbook_lcd_device = { + .name = "omap3touchbook_lcd", + .id = -1, +}; + +static struct omap_lcd_config omap3_touchbook_lcd_config __initdata = { + .ctrl_name = "internal", +}; + +static struct regulator_consumer_supply touchbook_vmmc1_supply = { + .supply = "vmmc", +}; + +static struct regulator_consumer_supply touchbook_vsim_supply = { + .supply = "vmmc_aux", +}; + +static struct gpio_led gpio_leds[]; + +static int touchbook_twl_gpio_setup(struct device *dev, + unsigned gpio, unsigned ngpio) +{ + if (system_rev >= 0x20 && system_rev <= 0x34301000) { + omap_mux_init_gpio(23, OMAP_PIN_INPUT); + mmc[0].gpio_wp = 23; + } else { + omap_mux_init_gpio(29, OMAP_PIN_INPUT); + } + /* gpio + 0 is "mmc0_cd" (input/IRQ) */ + mmc[0].gpio_cd = gpio + 0; + twl4030_mmc_init(mmc); + + /* link regulators to MMC adapters */ + touchbook_vmmc1_supply.dev = mmc[0].dev; + touchbook_vsim_supply.dev = mmc[0].dev; + + /* REVISIT: need ehci-omap hooks for external VBUS + * power switch and overcurrent detect + */ + + gpio_request(gpio + 1, "EHCI_nOC"); + gpio_direction_input(gpio + 1); + + /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */ + gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR"); + gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0); + + /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */ + gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; + + return 0; +} + +static struct twl4030_gpio_platform_data touchbook_gpio_data = { + .gpio_base = OMAP_MAX_GPIO_LINES, + .irq_base = TWL4030_GPIO_IRQ_BASE, + .irq_end = TWL4030_GPIO_IRQ_END, + .use_leds = true, + .pullups = BIT(1), + .pulldowns = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13) + | BIT(15) | BIT(16) | BIT(17), + .setup = touchbook_twl_gpio_setup, +}; + +static struct regulator_consumer_supply touchbook_vdac_supply = { + .supply = "vdac", + .dev = &omap3_touchbook_lcd_device.dev, +}; + +static struct regulator_consumer_supply touchbook_vdvi_supply = { + .supply = "vdvi", + .dev = &omap3_touchbook_lcd_device.dev, +}; + +/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ +static struct regulator_init_data touchbook_vmmc1 = { + .constraints = { + .min_uV = 1850000, + .max_uV = 3150000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &touchbook_vmmc1_supply, +}; + +/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */ +static struct regulator_init_data touchbook_vsim = { + .constraints = { + .min_uV = 1800000, + .max_uV = 3000000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &touchbook_vsim_supply, +}; + +/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */ +static struct regulator_init_data touchbook_vdac = { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &touchbook_vdac_supply, +}; + +/* VPLL2 for digital video outputs */ +static struct regulator_init_data touchbook_vpll2 = { + .constraints = { + .name = "VDVI", + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &touchbook_vdvi_supply, +}; + +static struct twl4030_usb_data touchbook_usb_data = { + .usb_mode = T2_USB_MODE_ULPI, +}; + +static struct twl4030_codec_audio_data touchbook_audio_data = { + .audio_mclk = 26000000, +}; + +static struct twl4030_codec_data touchbook_codec_data = { + .audio_mclk = 26000000, + .audio = &touchbook_audio_data, +}; + +static struct twl4030_platform_data touchbook_twldata = { + .irq_base = TWL4030_IRQ_BASE, + .irq_end = TWL4030_IRQ_END, + + /* platform_data for children goes here */ + .usb = &touchbook_usb_data, + .gpio = &touchbook_gpio_data, + .codec = &touchbook_codec_data, + .vmmc1 = &touchbook_vmmc1, + .vsim = &touchbook_vsim, + .vdac = &touchbook_vdac, + .vpll2 = &touchbook_vpll2, +}; + +static struct i2c_board_info __initdata touchbook_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &touchbook_twldata, + }, +}; + +static struct i2c_board_info __initdata touchBook_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("bq27200", 0x55), + }, +}; + +static int __init omap3_touchbook_i2c_init(void) +{ + /* Standard TouchBook bus */ + omap_register_i2c_bus(1, 2600, touchbook_i2c_boardinfo, + ARRAY_SIZE(touchbook_i2c_boardinfo)); + + /* Additional TouchBook bus */ + omap_register_i2c_bus(3, 100, touchBook_i2c_boardinfo, + ARRAY_SIZE(touchBook_i2c_boardinfo)); + + return 0; +} + +static void __init omap3_ads7846_init(void) +{ + if (gpio_request(OMAP3_TS_GPIO, "ads7846_pen_down")) { + printk(KERN_ERR "Failed to request GPIO %d for " + "ads7846 pen down IRQ\n", OMAP3_TS_GPIO); + return; + } + + gpio_direction_input(OMAP3_TS_GPIO); + omap_set_gpio_debounce(OMAP3_TS_GPIO, 1); + omap_set_gpio_debounce_time(OMAP3_TS_GPIO, 0xa); +} + +static struct ads7846_platform_data ads7846_config = { + .x_min = 100, + .y_min = 265, + .x_max = 3950, + .y_max = 3750, + .x_plate_ohms = 40, + .pressure_max = 255, + .debounce_max = 10, + .debounce_tol = 5, + .debounce_rep = 1, + .gpio_pendown = OMAP3_TS_GPIO, + .keep_vref_on = 1, +}; + +static struct omap2_mcspi_device_config ads7846_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +static struct spi_board_info omap3_ads7846_spi_board_info[] __initdata = { + { + .modalias = "ads7846", + .bus_num = 4, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &ads7846_mcspi_config, + .irq = OMAP_GPIO_IRQ(OMAP3_TS_GPIO), + .platform_data = &ads7846_config, + } +}; + +static struct gpio_led gpio_leds[] = { + { + .name = "touchbook::usr0", + .default_trigger = "heartbeat", + .gpio = 150, + }, + { + .name = "touchbook::usr1", + .default_trigger = "mmc0", + .gpio = 149, + }, + { + .name = "touchbook::pmu_stat", + .gpio = -EINVAL, /* gets replaced */ + .active_low = true, + }, +}; + +static struct gpio_led_platform_data gpio_led_info = { + .leds = gpio_leds, + .num_leds = ARRAY_SIZE(gpio_leds), +}; + +static struct platform_device leds_gpio = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &gpio_led_info, + }, +}; + +static struct gpio_keys_button gpio_buttons[] = { + { + .code = BTN_EXTRA, + .gpio = 7, + .desc = "user", + .wakeup = 1, + }, + { + .code = KEY_POWER, + .gpio = 183, + .desc = "power", + .wakeup = 1, + }, +}; + +static struct gpio_keys_platform_data gpio_key_info = { + .buttons = gpio_buttons, + .nbuttons = ARRAY_SIZE(gpio_buttons), +}; + +static struct platform_device keys_gpio = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &gpio_key_info, + }, +}; + +static struct omap_board_config_kernel omap3_touchbook_config[] __initdata = { + { OMAP_TAG_LCD, &omap3_touchbook_lcd_config }, +}; + +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define board_mux NULL +#endif + +static void __init omap3_touchbook_init_irq(void) +{ + omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); + omap_board_config = omap3_touchbook_config; + omap_board_config_size = ARRAY_SIZE(omap3_touchbook_config); + omap2_init_common_hw(mt46h32m32lf6_sdrc_params, + mt46h32m32lf6_sdrc_params); + omap_init_irq(); +#ifdef CONFIG_OMAP_32K_TIMER + omap2_gp_clockevent_set_gptimer(12); +#endif + omap_gpio_init(); +} + +static struct platform_device *omap3_touchbook_devices[] __initdata = { + &omap3_touchbook_lcd_device, + &leds_gpio, + &keys_gpio, +}; + +static void __init omap3touchbook_flash_init(void) +{ + u8 cs = 0; + u8 nandcs = GPMC_CS_NUM + 1; + + u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; + + /* find out the chip-select on which NAND exists */ + while (cs < GPMC_CS_NUM) { + u32 ret = 0; + ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + if ((ret & 0xC00) == 0x800) { + printk(KERN_INFO "Found NAND on CS%d\n", cs); + if (nandcs > GPMC_CS_NUM) + nandcs = cs; + } + cs++; + } + + if (nandcs > GPMC_CS_NUM) { + printk(KERN_INFO "NAND: Unable to find configuration " + "in GPMC\n "); + return; + } + + if (nandcs < GPMC_CS_NUM) { + omap3touchbook_nand_data.cs = nandcs; + omap3touchbook_nand_data.gpmc_cs_baseaddr = (void *) + (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); + omap3touchbook_nand_data.gpmc_baseaddr = + (void *) (gpmc_base_add); + + printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); + if (platform_device_register(&omap3touchbook_nand_device) < 0) + printk(KERN_ERR "Unable to register NAND device\n"); + } +} + +static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { + + .port_mode[0] = EHCI_HCD_OMAP_MODE_PHY, + .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY, + .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN, + + .phy_reset = true, + .reset_gpio_port[0] = -EINVAL, + .reset_gpio_port[1] = 147, + .reset_gpio_port[2] = -EINVAL +}; + +static void omap3_touchbook_poweroff(void) +{ + int r; + + r = gpio_request(TB_KILL_POWER_GPIO, "DVI reset"); + if (r < 0) { + printk(KERN_ERR "Unable to get kill power GPIO\n"); + return; + } + + gpio_direction_output(TB_KILL_POWER_GPIO, 0); +} + +static void __init early_touchbook_revision(char **p) +{ + if (!*p) + return; + + strict_strtoul(*p, 10, &touchbook_revision); +} +__early_param("tbr=", early_touchbook_revision); + +static void __init omap3_touchbook_init(void) +{ + pm_power_off = omap3_touchbook_poweroff; + + omap3_touchbook_i2c_init(); + platform_add_devices(omap3_touchbook_devices, + ARRAY_SIZE(omap3_touchbook_devices)); + omap_serial_init(); + + omap_mux_init_gpio(170, OMAP_PIN_INPUT); + gpio_request(176, "DVI_nPD"); + /* REVISIT leave DVI powered down until it's needed ... */ + gpio_direction_output(176, true); + + /* Touchscreen and accelerometer */ + spi_register_board_info(omap3_ads7846_spi_board_info, + ARRAY_SIZE(omap3_ads7846_spi_board_info)); + omap3_ads7846_init(); + usb_musb_init(); + usb_ehci_init(&ehci_pdata); + omap3touchbook_flash_init(); + + /* Ensure SDRC pins are mux'd for self-refresh */ + omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); + omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); +} + +static void __init omap3_touchbook_map_io(void) +{ + omap2_set_globals_343x(); + omap2_map_common_io(); +} + +MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board") + /* Maintainer: Gregoire Gentil - http://www.alwaysinnovating.com */ + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap3_touchbook_map_io, + .init_irq = omap3_touchbook_init_irq, + .init_machine = omap3_touchbook_init, + .timer = &omap_timer, +MACHINE_END diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 52dfd51a938ec8d8148afe024fb798ae5ef29a27..d192dd98a591779ac126fdf3c3ab0fbb2b489f51 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include @@ -44,9 +44,9 @@ #include #include #include -#include #include +#include "mux.h" #include "sdram-micron-mt46h32m32lf-6.h" #include "mmc-twl4030.h" @@ -405,9 +405,17 @@ static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { .reset_gpio_port[2] = -EINVAL }; +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define board_mux NULL +#endif static void __init overo_init(void) { + omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); overo_i2c_init(); platform_add_devices(overo_devices, ARRAY_SIZE(overo_devices)); omap_serial_init(); @@ -418,8 +426,8 @@ static void __init overo_init(void) overo_init_smsc911x(); /* Ensure SDRC pins are mux'd for self-refresh */ - omap_cfg_reg(H16_34XX_SDRC_CKE0); - omap_cfg_reg(H17_34XX_SDRC_CKE1); + omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); + omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); if ((gpio_request(OVERO_GPIO_W2W_NRESET, "OVERO_GPIO_W2W_NRESET") == 0) && diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 15ce6514c5fd53389c25904363ebdb0a50420850..17f3c91231dbfb066725d730984b2e99dc9f1b1d 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -33,6 +33,7 @@ #include #include +#include "mux.h" #include "mmc-twl4030.h" #define SYSTEM_REV_B_USES_VAUX3 0x1699 @@ -59,7 +60,7 @@ static struct spi_board_info rx51_peripherals_spi_board_info[] __initdata = { .bus_num = 4, .chip_select = 0, .max_speed_hz = 48000000, - .mode = SPI_MODE_2, + .mode = SPI_MODE_3, .controller_data = &wl1251_mcspi_config, .platform_data = &wl1251_pdata, }, @@ -401,15 +402,9 @@ static struct twl4030_usb_data rx51_usb_data = { static struct twl4030_ins sleep_on_seq[] __initdata = { /* - * Turn off VDD1 and VDD2. + * Turn off everything */ - {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_OFF), 4}, - {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_OFF), 2}, -/* - * And also turn off the OMAP3 PLLs and the sysclk output. - */ - {MSG_SINGULAR(DEV_GRP_P1, 0x7, RES_STATE_OFF), 3}, - {MSG_SINGULAR(DEV_GRP_P1, 0x17, RES_STATE_OFF), 3}, + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 1, 0, RES_STATE_SLEEP), 2}, }; static struct twl4030_script sleep_on_script __initdata = { @@ -420,14 +415,9 @@ static struct twl4030_script sleep_on_script __initdata = { static struct twl4030_ins wakeup_seq[] __initdata = { /* - * Reenable the OMAP3 PLLs. - * Wakeup VDD1 and VDD2. - * Reenable sysclk output. + * Reenable everything */ - {MSG_SINGULAR(DEV_GRP_P1, 0x7, RES_STATE_ACTIVE), 0x30}, - {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_ACTIVE), 0x30}, - {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_ACTIVE), 0x37}, - {MSG_SINGULAR(DEV_GRP_P1, 0x19, RES_STATE_ACTIVE), 3}, + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 1, 0, RES_STATE_ACTIVE), 2}, }; static struct twl4030_script wakeup_script __initdata = { @@ -438,10 +428,9 @@ static struct twl4030_script wakeup_script __initdata = { static struct twl4030_ins wakeup_p3_seq[] __initdata = { /* - * Wakeup VDD1 (dummy to be able to insert a delay) - * Enable CLKEN + * Reenable everything */ - {MSG_SINGULAR(DEV_GRP_P1, 0x17, RES_STATE_ACTIVE), 3}, + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 1, 0, RES_STATE_ACTIVE), 2}, }; static struct twl4030_script wakeup_p3_script __initdata = { @@ -462,12 +451,11 @@ static struct twl4030_ins wrst_seq[] __initdata = { {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_OFF), 2}, {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 0, 1, RES_STATE_ACTIVE), 0x13}, - {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_PP, 0, 2, RES_STATE_WRST), 0x13}, {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_PP, 0, 3, RES_STATE_OFF), 0x13}, {MSG_SINGULAR(DEV_GRP_NULL, RES_VDD1, RES_STATE_WRST), 0x13}, {MSG_SINGULAR(DEV_GRP_NULL, RES_VDD2, RES_STATE_WRST), 0x13}, {MSG_SINGULAR(DEV_GRP_NULL, RES_VPLL1, RES_STATE_WRST), 0x35}, - {MSG_SINGULAR(DEV_GRP_P1, RES_HFCLKOUT, RES_STATE_ACTIVE), 2}, + {MSG_SINGULAR(DEV_GRP_P3, RES_HFCLKOUT, RES_STATE_ACTIVE), 2}, {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_ACTIVE), 2}, }; @@ -489,22 +477,81 @@ static struct twl4030_script *twl4030_scripts[] __initdata = { }; static struct twl4030_resconfig twl4030_rconfig[] __initdata = { - { .resource = RES_VINTANA1, .devgroup = -1, .type = -1, .type2 = 1 }, - { .resource = RES_VINTANA2, .devgroup = -1, .type = -1, .type2 = 1 }, - { .resource = RES_VINTDIG, .devgroup = -1, .type = -1, .type2 = 1 }, - { .resource = RES_VMMC1, .devgroup = -1, .type = -1, .type2 = 3}, - { .resource = RES_VMMC2, .devgroup = DEV_GRP_NULL, .type = -1, - .type2 = 3}, - { .resource = RES_VAUX1, .devgroup = -1, .type = -1, .type2 = 3}, - { .resource = RES_VAUX2, .devgroup = -1, .type = -1, .type2 = 3}, - { .resource = RES_VAUX3, .devgroup = -1, .type = -1, .type2 = 3}, - { .resource = RES_VAUX4, .devgroup = -1, .type = -1, .type2 = 3}, - { .resource = RES_VPLL2, .devgroup = -1, .type = -1, .type2 = 3}, - { .resource = RES_VDAC, .devgroup = -1, .type = -1, .type2 = 3}, - { .resource = RES_VSIM, .devgroup = DEV_GRP_NULL, .type = -1, - .type2 = 3}, - { .resource = RES_CLKEN, .devgroup = DEV_GRP_P3, .type = -1, - .type2 = 1 }, + { .resource = RES_VDD1, .devgroup = -1, + .type = 1, .type2 = -1, .remap_off = RES_STATE_OFF, + .remap_sleep = RES_STATE_OFF + }, + { .resource = RES_VDD2, .devgroup = -1, + .type = 1, .type2 = -1, .remap_off = RES_STATE_OFF, + .remap_sleep = RES_STATE_OFF + }, + { .resource = RES_VPLL1, .devgroup = -1, + .type = 1, .type2 = -1, .remap_off = RES_STATE_OFF, + .remap_sleep = RES_STATE_OFF + }, + { .resource = RES_VPLL2, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VAUX1, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VAUX2, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VAUX3, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VAUX4, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VMMC1, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VMMC2, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VDAC, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VSIM, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VINTANA1, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, + .type = -1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VINTANA2, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VINTDIG, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, + .type = -1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VIO, .devgroup = DEV_GRP_P3, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_CLKEN, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, + .type = 1, .type2 = -1 , .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_REGEN, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_NRES_PWRON, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_SYSEN, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P3, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_32KCLKOUT, .devgroup = -1, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_RESET, .devgroup = -1, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_Main_Ref, .devgroup = -1, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, { 0, 0}, }; @@ -630,9 +677,9 @@ static struct omap_smc91x_platform_data board_smc91x_data = { static void __init board_smc91x_init(void) { - omap_cfg_reg(U8_34XX_GPIO54_DOWN); - omap_cfg_reg(G25_34XX_GPIO86_OUT); - omap_cfg_reg(H19_34XX_GPIO164_OUT); + omap_mux_init_gpio(54, OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_gpio(86, OMAP_PIN_OUTPUT); + omap_mux_init_gpio(164, OMAP_PIN_OUTPUT); gpmc_smc91x_init(&board_smc91x_data); } diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c index 1bb1de24591742bdf4717fb6bf8536e65caa6032..67bb3476b7078cb42f789005e98f03868241e7b8 100644 --- a/arch/arm/mach-omap2/board-rx51.c +++ b/arch/arm/mach-omap2/board-rx51.c @@ -23,13 +23,14 @@ #include #include -#include #include #include #include #include #include +#include "mux.h" + struct omap_sdrc_params *rx51_get_sdram_timings(void); static struct omap_lcd_config rx51_lcd_config = { @@ -69,15 +70,24 @@ static void __init rx51_init_irq(void) extern void __init rx51_peripherals_init(void); +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define board_mux NULL +#endif + static void __init rx51_init(void) { + omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); omap_serial_init(); usb_musb_init(); rx51_peripherals_init(); /* Ensure SDRC pins are mux'd for self-refresh */ - omap_cfg_reg(H16_34XX_SDRC_CKE0); - omap_cfg_reg(H17_34XX_SDRC_CKE1); + omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); + omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); } static void __init rx51_map_io(void) diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c index f14baa39276047c80e99781d2c5c1d4116bd917c..258794db488f53a49ca8c4aab56ec6da1f060631 100755 --- a/arch/arm/mach-omap2/board-zoom-peripherals.c +++ b/arch/arm/mach-omap2/board-zoom-peripherals.c @@ -152,14 +152,20 @@ static struct regulator_init_data zoom_vsim = { static struct twl4030_hsmmc_info mmc[] __initdata = { { + .name = "external", .mmc = 1, .wires = 4, .gpio_wp = -EINVAL, + .power_saving = true, }, { + .name = "internal", .mmc = 2, - .wires = 4, + .wires = 8, + .gpio_cd = -EINVAL, .gpio_wp = -EINVAL, + .nonremovable = true, + .power_saving = true, }, {} /* Terminator */ }; @@ -167,11 +173,8 @@ static struct twl4030_hsmmc_info mmc[] __initdata = { static int zoom_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { - /* gpio + 0 is "mmc0_cd" (input/IRQ), - * gpio + 1 is "mmc1_cd" (input/IRQ) - */ + /* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0].gpio_cd = gpio + 0; - mmc[1].gpio_cd = gpio + 1; twl4030_mmc_init(mmc); /* link regulators to MMC adapters ... we "know" the @@ -236,6 +239,7 @@ static struct twl4030_platform_data zoom_twldata = { .gpio = &zoom_gpio_data, .keypad = &zoom_kp_twl4030_data, .codec = &zoom_codec_data, + .vmmc1 = &zoom_vmmc1, .vmmc2 = &zoom_vmmc2, .vsim = &zoom_vsim, diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c index d94d047c7dce5b740debe34dcd5643fa0fed8c62..bb87cf7878ff6e0931e2b1042c82ae4299d93cbf 100644 --- a/arch/arm/mach-omap2/board-zoom2.c +++ b/arch/arm/mach-omap2/board-zoom2.c @@ -23,6 +23,7 @@ #include +#include "mux.h" #include "sdram-micron-mt46h32m32lf-6.h" static void __init omap_zoom2_init_irq(void) @@ -68,8 +69,17 @@ static struct twl4030_platform_data zoom2_twldata = { #endif +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define board_mux NULL +#endif + static void __init omap_zoom2_init(void) { + omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); zoom_peripherals_init(); zoom_debugboard_init(); } diff --git a/arch/arm/mach-omap2/board-zoom3.c b/arch/arm/mach-omap2/board-zoom3.c index 8d965a6516c87abfdc54a9d0c07d87ae58890af8..a9fe9181b01089ad06fa53682189c1620059c31e 100644 --- a/arch/arm/mach-omap2/board-zoom3.c +++ b/arch/arm/mach-omap2/board-zoom3.c @@ -21,6 +21,7 @@ #include #include +#include "mux.h" #include "sdram-hynix-h8mbx00u0mer-0em.h" static void __init omap_zoom_map_io(void) @@ -42,8 +43,17 @@ static void __init omap_zoom_init_irq(void) omap_gpio_init(); } +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define board_mux NULL +#endif + static void __init omap_zoom_init(void) { + omap3_mux_init(board_mux, OMAP_PACKAGE_CBP); zoom_peripherals_init(); zoom_debugboard_init(); } diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 4716206547ac06adfe839d057edf397363f3da88..759c72a48f7f188c5232919df2702edaabf562cd 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -70,9 +70,41 @@ u8 cpu_mask; /*------------------------------------------------------------------------- - * OMAP2/3 specific clock functions + * OMAP2/3/4 specific clock functions *-------------------------------------------------------------------------*/ +void omap2_init_dpll_parent(struct clk *clk) +{ + u32 v; + struct dpll_data *dd; + + dd = clk->dpll_data; + if (!dd) + return; + + /* Return bypass rate if DPLL is bypassed */ + v = __raw_readl(dd->control_reg); + v &= dd->enable_mask; + v >>= __ffs(dd->enable_mask); + + /* Reparent in case the dpll is in bypass */ + if (cpu_is_omap24xx()) { + if (v == OMAP2XXX_EN_DPLL_LPBYPASS || + v == OMAP2XXX_EN_DPLL_FRBYPASS) + clk_reparent(clk, dd->clk_bypass); + } else if (cpu_is_omap34xx()) { + if (v == OMAP3XXX_EN_DPLL_LPBYPASS || + v == OMAP3XXX_EN_DPLL_FRBYPASS) + clk_reparent(clk, dd->clk_bypass); + } else if (cpu_is_omap44xx()) { + if (v == OMAP4XXX_EN_DPLL_LPBYPASS || + v == OMAP4XXX_EN_DPLL_FRBYPASS || + v == OMAP4XXX_EN_DPLL_MNBYPASS) + clk_reparent(clk, dd->clk_bypass); + } + return; +} + /** * _omap2xxx_clk_commit - commit clock parent/rate changes in hardware * @clk: struct clk * @@ -149,6 +181,7 @@ static int _dpll_test_fint(struct clk *clk, u8 n) * clockdomain pointer, and save it into the struct clk. Intended to be * called during clk_register(). No return value. */ +#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdm f/w is in place */ void omap2_init_clk_clkdm(struct clk *clk) { struct clockdomain *clkdm; @@ -166,6 +199,7 @@ void omap2_init_clk_clkdm(struct clk *clk) "clkdm %s\n", clk->name, clk->clkdm_name); } } +#endif /** * omap2_init_clksel_parent - set a clksel clk's parent field from the hardware @@ -247,6 +281,11 @@ u32 omap2_get_dpll_rate(struct clk *clk) if (v == OMAP3XXX_EN_DPLL_LPBYPASS || v == OMAP3XXX_EN_DPLL_FRBYPASS) return dd->clk_bypass->rate; + } else if (cpu_is_omap44xx()) { + if (v == OMAP4XXX_EN_DPLL_LPBYPASS || + v == OMAP4XXX_EN_DPLL_FRBYPASS || + v == OMAP4XXX_EN_DPLL_MNBYPASS) + return dd->clk_bypass->rate; } v = __raw_readl(dd->mult_div1_reg); @@ -437,8 +476,10 @@ void omap2_clk_disable(struct clk *clk) _omap2_clk_disable(clk); if (clk->parent) omap2_clk_disable(clk->parent); +#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdm f/w is in place */ if (clk->clkdm) omap2_clkdm_clk_disable(clk->clkdm, clk); +#endif } } @@ -448,8 +489,10 @@ int omap2_clk_enable(struct clk *clk) int ret = 0; if (clk->usecount++ == 0) { +#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdm f/w is in place */ if (clk->clkdm) omap2_clkdm_clk_enable(clk->clkdm, clk); +#endif if (clk->parent) { ret = omap2_clk_enable(clk->parent); @@ -468,8 +511,10 @@ int omap2_clk_enable(struct clk *clk) return ret; err: +#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdm f/w is in place */ if (clk->clkdm) omap2_clkdm_clk_disable(clk->clkdm, clk); +#endif clk->usecount--; return ret; } diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 43b6bedaafd611e1a42dfaf9cf970e8edfec0157..93c48df3b5b1f864587e23474731ed9f4399c5fb 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -1,8 +1,8 @@ /* * linux/arch/arm/mach-omap2/clock.h * - * Copyright (C) 2005-2008 Texas Instruments, Inc. - * Copyright (C) 2004-2008 Nokia Corporation + * Copyright (C) 2005-2009 Texas Instruments, Inc. + * Copyright (C) 2004-2009 Nokia Corporation * * Contacts: * Richard Woodruff @@ -36,6 +36,17 @@ #define OMAP3XXX_EN_DPLL_FRBYPASS 0x6 #define OMAP3XXX_EN_DPLL_LOCKED 0x7 +/* OMAP4xxx CM_CLKMODE_DPLL*.EN_*_DPLL bits - for omap2_get_dpll_rate() */ +#define OMAP4XXX_EN_DPLL_MNBYPASS 0x4 +#define OMAP4XXX_EN_DPLL_LPBYPASS 0x5 +#define OMAP4XXX_EN_DPLL_FRBYPASS 0x6 +#define OMAP4XXX_EN_DPLL_LOCKED 0x7 + +/* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */ +#define DPLL_LOW_POWER_STOP 0x1 +#define DPLL_LOW_POWER_BYPASS 0x5 +#define DPLL_LOCKED 0x7 + int omap2_clk_init(void); int omap2_clk_enable(struct clk *clk); void omap2_clk_disable(struct clk *clk); @@ -44,6 +55,14 @@ int omap2_clk_set_rate(struct clk *clk, unsigned long rate); int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent); int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance); long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate); +unsigned long omap3_dpll_recalc(struct clk *clk); +unsigned long omap3_clkoutx2_recalc(struct clk *clk); +void omap3_dpll_allow_idle(struct clk *clk); +void omap3_dpll_deny_idle(struct clk *clk); +u32 omap3_dpll_autoidle_read(struct clk *clk); +int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate); +int omap3_noncore_dpll_enable(struct clk *clk); +void omap3_noncore_dpll_disable(struct clk *clk); #ifdef CONFIG_OMAP_RESET_CLOCKS void omap2_clk_disable_unused(struct clk *clk); @@ -63,6 +82,7 @@ unsigned long omap2_fixed_divisor_recalc(struct clk *clk); long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate); int omap2_clksel_set_rate(struct clk *clk, unsigned long rate); u32 omap2_get_dpll_rate(struct clk *clk); +void omap2_init_dpll_parent(struct clk *clk); int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name); void omap2_clk_prepare_for_reboot(void); int omap2_dflt_clk_enable(struct clk *clk); @@ -72,29 +92,17 @@ void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg, void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg, u8 *idlest_bit); +extern u8 cpu_mask; + extern const struct clkops clkops_omap2_dflt_wait; extern const struct clkops clkops_omap2_dflt; -extern u8 cpu_mask; +extern struct clk_functions omap2_clk_functions; +extern struct clk *vclk, *sclk; -/* clksel_rate data common to 24xx/343x */ -static const struct clksel_rate gpt_32k_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel_rate gpt_sys_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel_rate gfx_l3_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_343X }, - { .div = 2, .val = 2, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE }, - { .div = 3, .val = 3, .flags = RATE_IN_243X | RATE_IN_343X }, - { .div = 4, .val = 4, .flags = RATE_IN_243X | RATE_IN_343X }, - { .div = 0 } -}; +extern const struct clksel_rate gpt_32k_rates[]; +extern const struct clksel_rate gpt_sys_rates[]; +extern const struct clksel_rate gfx_l3_rates[]; #endif diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c deleted file mode 100644 index e70e7e000eaae00b5ad6942c58edc16e11024c34..0000000000000000000000000000000000000000 --- a/arch/arm/mach-omap2/clock24xx.c +++ /dev/null @@ -1,805 +0,0 @@ -/* - * linux/arch/arm/mach-omap2/clock.c - * - * Copyright (C) 2005-2008 Texas Instruments, Inc. - * Copyright (C) 2004-2008 Nokia Corporation - * - * Contacts: - * Richard Woodruff - * Paul Walmsley - * - * Based on earlier work by Tuukka Tikkanen, Tony Lindgren, - * Gordon McNutt and RidgeRun, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include "clock.h" -#include "prm.h" -#include "prm-regbits-24xx.h" -#include "cm.h" -#include "cm-regbits-24xx.h" - -static const struct clkops clkops_oscck; -static const struct clkops clkops_fixed; - -static void omap2430_clk_i2chs_find_idlest(struct clk *clk, - void __iomem **idlest_reg, - u8 *idlest_bit); - -/* 2430 I2CHS has non-standard IDLEST register */ -static const struct clkops clkops_omap2430_i2chs_wait = { - .enable = omap2_dflt_clk_enable, - .disable = omap2_dflt_clk_disable, - .find_idlest = omap2430_clk_i2chs_find_idlest, - .find_companion = omap2_clk_dflt_find_companion, -}; - -#include "clock24xx.h" - -struct omap_clk { - u32 cpu; - struct clk_lookup lk; -}; - -#define CLK(dev, con, ck, cp) \ - { \ - .cpu = cp, \ - .lk = { \ - .dev_id = dev, \ - .con_id = con, \ - .clk = ck, \ - }, \ - } - -#define CK_243X RATE_IN_243X -#define CK_242X RATE_IN_242X - -static struct omap_clk omap24xx_clks[] = { - /* external root sources */ - CLK(NULL, "func_32k_ck", &func_32k_ck, CK_243X | CK_242X), - CLK(NULL, "secure_32k_ck", &secure_32k_ck, CK_243X | CK_242X), - CLK(NULL, "osc_ck", &osc_ck, CK_243X | CK_242X), - CLK(NULL, "sys_ck", &sys_ck, CK_243X | CK_242X), - CLK(NULL, "alt_ck", &alt_ck, CK_243X | CK_242X), - /* internal analog sources */ - CLK(NULL, "dpll_ck", &dpll_ck, CK_243X | CK_242X), - CLK(NULL, "apll96_ck", &apll96_ck, CK_243X | CK_242X), - CLK(NULL, "apll54_ck", &apll54_ck, CK_243X | CK_242X), - /* internal prcm root sources */ - CLK(NULL, "func_54m_ck", &func_54m_ck, CK_243X | CK_242X), - CLK(NULL, "core_ck", &core_ck, CK_243X | CK_242X), - CLK(NULL, "func_96m_ck", &func_96m_ck, CK_243X | CK_242X), - CLK(NULL, "func_48m_ck", &func_48m_ck, CK_243X | CK_242X), - CLK(NULL, "func_12m_ck", &func_12m_ck, CK_243X | CK_242X), - CLK(NULL, "ck_wdt1_osc", &wdt1_osc_ck, CK_243X | CK_242X), - CLK(NULL, "sys_clkout_src", &sys_clkout_src, CK_243X | CK_242X), - CLK(NULL, "sys_clkout", &sys_clkout, CK_243X | CK_242X), - CLK(NULL, "sys_clkout2_src", &sys_clkout2_src, CK_242X), - CLK(NULL, "sys_clkout2", &sys_clkout2, CK_242X), - CLK(NULL, "emul_ck", &emul_ck, CK_242X), - /* mpu domain clocks */ - CLK(NULL, "mpu_ck", &mpu_ck, CK_243X | CK_242X), - /* dsp domain clocks */ - CLK(NULL, "dsp_fck", &dsp_fck, CK_243X | CK_242X), - CLK(NULL, "dsp_irate_ick", &dsp_irate_ick, CK_243X | CK_242X), - CLK(NULL, "dsp_ick", &dsp_ick, CK_242X), - CLK(NULL, "iva2_1_ick", &iva2_1_ick, CK_243X), - CLK(NULL, "iva1_ifck", &iva1_ifck, CK_242X), - CLK(NULL, "iva1_mpu_int_ifck", &iva1_mpu_int_ifck, CK_242X), - /* GFX domain clocks */ - CLK(NULL, "gfx_3d_fck", &gfx_3d_fck, CK_243X | CK_242X), - CLK(NULL, "gfx_2d_fck", &gfx_2d_fck, CK_243X | CK_242X), - CLK(NULL, "gfx_ick", &gfx_ick, CK_243X | CK_242X), - /* Modem domain clocks */ - CLK(NULL, "mdm_ick", &mdm_ick, CK_243X), - CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X), - /* DSS domain clocks */ - CLK("omapfb", "ick", &dss_ick, CK_243X | CK_242X), - CLK("omapfb", "dss1_fck", &dss1_fck, CK_243X | CK_242X), - CLK("omapfb", "dss2_fck", &dss2_fck, CK_243X | CK_242X), - CLK("omapfb", "tv_fck", &dss_54m_fck, CK_243X | CK_242X), - /* L3 domain clocks */ - CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X | CK_242X), - CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X | CK_242X), - CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_243X | CK_242X), - /* L4 domain clocks */ - CLK(NULL, "l4_ck", &l4_ck, CK_243X | CK_242X), - CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_243X | CK_242X), - /* virtual meta-group clock */ - CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_243X | CK_242X), - /* general l4 interface ck, multi-parent functional clk */ - CLK(NULL, "gpt1_ick", &gpt1_ick, CK_243X | CK_242X), - CLK(NULL, "gpt1_fck", &gpt1_fck, CK_243X | CK_242X), - CLK(NULL, "gpt2_ick", &gpt2_ick, CK_243X | CK_242X), - CLK(NULL, "gpt2_fck", &gpt2_fck, CK_243X | CK_242X), - CLK(NULL, "gpt3_ick", &gpt3_ick, CK_243X | CK_242X), - CLK(NULL, "gpt3_fck", &gpt3_fck, CK_243X | CK_242X), - CLK(NULL, "gpt4_ick", &gpt4_ick, CK_243X | CK_242X), - CLK(NULL, "gpt4_fck", &gpt4_fck, CK_243X | CK_242X), - CLK(NULL, "gpt5_ick", &gpt5_ick, CK_243X | CK_242X), - CLK(NULL, "gpt5_fck", &gpt5_fck, CK_243X | CK_242X), - CLK(NULL, "gpt6_ick", &gpt6_ick, CK_243X | CK_242X), - CLK(NULL, "gpt6_fck", &gpt6_fck, CK_243X | CK_242X), - CLK(NULL, "gpt7_ick", &gpt7_ick, CK_243X | CK_242X), - CLK(NULL, "gpt7_fck", &gpt7_fck, CK_243X | CK_242X), - CLK(NULL, "gpt8_ick", &gpt8_ick, CK_243X | CK_242X), - CLK(NULL, "gpt8_fck", &gpt8_fck, CK_243X | CK_242X), - CLK(NULL, "gpt9_ick", &gpt9_ick, CK_243X | CK_242X), - CLK(NULL, "gpt9_fck", &gpt9_fck, CK_243X | CK_242X), - CLK(NULL, "gpt10_ick", &gpt10_ick, CK_243X | CK_242X), - CLK(NULL, "gpt10_fck", &gpt10_fck, CK_243X | CK_242X), - CLK(NULL, "gpt11_ick", &gpt11_ick, CK_243X | CK_242X), - CLK(NULL, "gpt11_fck", &gpt11_fck, CK_243X | CK_242X), - CLK(NULL, "gpt12_ick", &gpt12_ick, CK_243X | CK_242X), - CLK(NULL, "gpt12_fck", &gpt12_fck, CK_243X | CK_242X), - CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_243X | CK_242X), - CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_243X | CK_242X), - CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_243X | CK_242X), - CLK("omap-mcbsp.2", "fck", &mcbsp2_fck, CK_243X | CK_242X), - CLK("omap-mcbsp.3", "ick", &mcbsp3_ick, CK_243X), - CLK("omap-mcbsp.3", "fck", &mcbsp3_fck, CK_243X), - CLK("omap-mcbsp.4", "ick", &mcbsp4_ick, CK_243X), - CLK("omap-mcbsp.4", "fck", &mcbsp4_fck, CK_243X), - CLK("omap-mcbsp.5", "ick", &mcbsp5_ick, CK_243X), - CLK("omap-mcbsp.5", "fck", &mcbsp5_fck, CK_243X), - CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_243X | CK_242X), - CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_243X | CK_242X), - CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_243X | CK_242X), - CLK("omap2_mcspi.2", "fck", &mcspi2_fck, CK_243X | CK_242X), - CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_243X), - CLK("omap2_mcspi.3", "fck", &mcspi3_fck, CK_243X), - CLK(NULL, "uart1_ick", &uart1_ick, CK_243X | CK_242X), - CLK(NULL, "uart1_fck", &uart1_fck, CK_243X | CK_242X), - CLK(NULL, "uart2_ick", &uart2_ick, CK_243X | CK_242X), - CLK(NULL, "uart2_fck", &uart2_fck, CK_243X | CK_242X), - CLK(NULL, "uart3_ick", &uart3_ick, CK_243X | CK_242X), - CLK(NULL, "uart3_fck", &uart3_fck, CK_243X | CK_242X), - CLK(NULL, "gpios_ick", &gpios_ick, CK_243X | CK_242X), - CLK(NULL, "gpios_fck", &gpios_fck, CK_243X | CK_242X), - CLK("omap_wdt", "ick", &mpu_wdt_ick, CK_243X | CK_242X), - CLK("omap_wdt", "fck", &mpu_wdt_fck, CK_243X | CK_242X), - CLK(NULL, "sync_32k_ick", &sync_32k_ick, CK_243X | CK_242X), - CLK(NULL, "wdt1_ick", &wdt1_ick, CK_243X | CK_242X), - CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_243X | CK_242X), - CLK(NULL, "icr_ick", &icr_ick, CK_243X), - CLK("omap24xxcam", "fck", &cam_fck, CK_243X | CK_242X), - CLK("omap24xxcam", "ick", &cam_ick, CK_243X | CK_242X), - CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_243X | CK_242X), - CLK(NULL, "wdt4_ick", &wdt4_ick, CK_243X | CK_242X), - CLK(NULL, "wdt4_fck", &wdt4_fck, CK_243X | CK_242X), - CLK(NULL, "wdt3_ick", &wdt3_ick, CK_242X), - CLK(NULL, "wdt3_fck", &wdt3_fck, CK_242X), - CLK(NULL, "mspro_ick", &mspro_ick, CK_243X | CK_242X), - CLK(NULL, "mspro_fck", &mspro_fck, CK_243X | CK_242X), - CLK("mmci-omap.0", "ick", &mmc_ick, CK_242X), - CLK("mmci-omap.0", "fck", &mmc_fck, CK_242X), - CLK(NULL, "fac_ick", &fac_ick, CK_243X | CK_242X), - CLK(NULL, "fac_fck", &fac_fck, CK_243X | CK_242X), - CLK(NULL, "eac_ick", &eac_ick, CK_242X), - CLK(NULL, "eac_fck", &eac_fck, CK_242X), - CLK("omap_hdq.0", "ick", &hdq_ick, CK_243X | CK_242X), - CLK("omap_hdq.1", "fck", &hdq_fck, CK_243X | CK_242X), - CLK("i2c_omap.1", "ick", &i2c1_ick, CK_243X | CK_242X), - CLK("i2c_omap.1", "fck", &i2c1_fck, CK_242X), - CLK("i2c_omap.1", "fck", &i2chs1_fck, CK_243X), - CLK("i2c_omap.2", "ick", &i2c2_ick, CK_243X | CK_242X), - CLK("i2c_omap.2", "fck", &i2c2_fck, CK_242X), - CLK("i2c_omap.2", "fck", &i2chs2_fck, CK_243X), - CLK(NULL, "gpmc_fck", &gpmc_fck, CK_243X | CK_242X), - CLK(NULL, "sdma_fck", &sdma_fck, CK_243X | CK_242X), - CLK(NULL, "sdma_ick", &sdma_ick, CK_243X | CK_242X), - CLK(NULL, "vlynq_ick", &vlynq_ick, CK_242X), - CLK(NULL, "vlynq_fck", &vlynq_fck, CK_242X), - CLK(NULL, "sdrc_ick", &sdrc_ick, CK_243X), - CLK(NULL, "des_ick", &des_ick, CK_243X | CK_242X), - CLK(NULL, "sha_ick", &sha_ick, CK_243X | CK_242X), - CLK("omap_rng", "ick", &rng_ick, CK_243X | CK_242X), - CLK(NULL, "aes_ick", &aes_ick, CK_243X | CK_242X), - CLK(NULL, "pka_ick", &pka_ick, CK_243X | CK_242X), - CLK(NULL, "usb_fck", &usb_fck, CK_243X | CK_242X), - CLK("musb_hdrc", "ick", &usbhs_ick, CK_243X), - CLK("mmci-omap-hs.0", "ick", &mmchs1_ick, CK_243X), - CLK("mmci-omap-hs.0", "fck", &mmchs1_fck, CK_243X), - CLK("mmci-omap-hs.1", "ick", &mmchs2_ick, CK_243X), - CLK("mmci-omap-hs.1", "fck", &mmchs2_fck, CK_243X), - CLK(NULL, "gpio5_ick", &gpio5_ick, CK_243X), - CLK(NULL, "gpio5_fck", &gpio5_fck, CK_243X), - CLK(NULL, "mdm_intc_ick", &mdm_intc_ick, CK_243X), - CLK("mmci-omap-hs.0", "mmchsdb_fck", &mmchsdb1_fck, CK_243X), - CLK("mmci-omap-hs.1", "mmchsdb_fck", &mmchsdb2_fck, CK_243X), -}; - -/* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */ -#define EN_APLL_STOPPED 0 -#define EN_APLL_LOCKED 3 - -/* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */ -#define APLLS_CLKIN_19_2MHZ 0 -#define APLLS_CLKIN_13MHZ 2 -#define APLLS_CLKIN_12MHZ 3 - -/* #define DOWN_VARIABLE_DPLL 1 */ /* Experimental */ - -static struct prcm_config *curr_prcm_set; -static struct clk *vclk; -static struct clk *sclk; - -static void __iomem *prcm_clksrc_ctrl; - -/*------------------------------------------------------------------------- - * Omap24xx specific clock functions - *-------------------------------------------------------------------------*/ - -/** - * omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS - * @clk: struct clk * being enabled - * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into - * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into - * - * OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the - * CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE. This custom function - * passes back the correct CM_IDLEST register address for I2CHS - * modules. No return value. - */ -static void omap2430_clk_i2chs_find_idlest(struct clk *clk, - void __iomem **idlest_reg, - u8 *idlest_bit) -{ - *idlest_reg = OMAP_CM_REGADDR(CORE_MOD, CM_IDLEST); - *idlest_bit = clk->enable_bit; -} - - -/** - * omap2xxx_clk_get_core_rate - return the CORE_CLK rate - * @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck") - * - * Returns the CORE_CLK rate. CORE_CLK can have one of three rate - * sources on OMAP2xxx: the DPLL CLKOUT rate, DPLL CLKOUTX2, or 32KHz - * (the latter is unusual). This currently should be called with - * struct clk *dpll_ck, which is a composite clock of dpll_ck and - * core_ck. - */ -static unsigned long omap2xxx_clk_get_core_rate(struct clk *clk) -{ - long long core_clk; - u32 v; - - core_clk = omap2_get_dpll_rate(clk); - - v = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2); - v &= OMAP24XX_CORE_CLK_SRC_MASK; - - if (v == CORE_CLK_SRC_32K) - core_clk = 32768; - else - core_clk *= v; - - return core_clk; -} - -static int omap2_enable_osc_ck(struct clk *clk) -{ - u32 pcc; - - pcc = __raw_readl(prcm_clksrc_ctrl); - - __raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl); - - return 0; -} - -static void omap2_disable_osc_ck(struct clk *clk) -{ - u32 pcc; - - pcc = __raw_readl(prcm_clksrc_ctrl); - - __raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl); -} - -static const struct clkops clkops_oscck = { - .enable = &omap2_enable_osc_ck, - .disable = &omap2_disable_osc_ck, -}; - -#ifdef OLD_CK -/* Recalculate SYST_CLK */ -static void omap2_sys_clk_recalc(struct clk * clk) -{ - u32 div = PRCM_CLKSRC_CTRL; - div &= (1 << 7) | (1 << 6); /* Test if ext clk divided by 1 or 2 */ - div >>= clk->rate_offset; - clk->rate = (clk->parent->rate / div); - propagate_rate(clk); -} -#endif /* OLD_CK */ - -/* Enable an APLL if off */ -static int omap2_clk_fixed_enable(struct clk *clk) -{ - u32 cval, apll_mask; - - apll_mask = EN_APLL_LOCKED << clk->enable_bit; - - cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN); - - if ((cval & apll_mask) == apll_mask) - return 0; /* apll already enabled */ - - cval &= ~apll_mask; - cval |= apll_mask; - cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN); - - if (clk == &apll96_ck) - cval = OMAP24XX_ST_96M_APLL; - else if (clk == &apll54_ck) - cval = OMAP24XX_ST_54M_APLL; - - omap2_cm_wait_idlest(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), cval, - clk->name); - - /* - * REVISIT: Should we return an error code if omap2_wait_clock_ready() - * fails? - */ - return 0; -} - -/* Stop APLL */ -static void omap2_clk_fixed_disable(struct clk *clk) -{ - u32 cval; - - cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN); - cval &= ~(EN_APLL_LOCKED << clk->enable_bit); - cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN); -} - -static const struct clkops clkops_fixed = { - .enable = &omap2_clk_fixed_enable, - .disable = &omap2_clk_fixed_disable, -}; - -/* - * Uses the current prcm set to tell if a rate is valid. - * You can go slower, but not faster within a given rate set. - */ -static long omap2_dpllcore_round_rate(unsigned long target_rate) -{ - u32 high, low, core_clk_src; - - core_clk_src = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2); - core_clk_src &= OMAP24XX_CORE_CLK_SRC_MASK; - - if (core_clk_src == CORE_CLK_SRC_DPLL) { /* DPLL clockout */ - high = curr_prcm_set->dpll_speed * 2; - low = curr_prcm_set->dpll_speed; - } else { /* DPLL clockout x 2 */ - high = curr_prcm_set->dpll_speed; - low = curr_prcm_set->dpll_speed / 2; - } - -#ifdef DOWN_VARIABLE_DPLL - if (target_rate > high) - return high; - else - return target_rate; -#else - if (target_rate > low) - return high; - else - return low; -#endif - -} - -static unsigned long omap2_dpllcore_recalc(struct clk *clk) -{ - return omap2xxx_clk_get_core_rate(clk); -} - -static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate) -{ - u32 cur_rate, low, mult, div, valid_rate, done_rate; - u32 bypass = 0; - struct prcm_config tmpset; - const struct dpll_data *dd; - - cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck); - mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2); - mult &= OMAP24XX_CORE_CLK_SRC_MASK; - - if ((rate == (cur_rate / 2)) && (mult == 2)) { - omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1); - } else if ((rate == (cur_rate * 2)) && (mult == 1)) { - omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); - } else if (rate != cur_rate) { - valid_rate = omap2_dpllcore_round_rate(rate); - if (valid_rate != rate) - return -EINVAL; - - if (mult == 1) - low = curr_prcm_set->dpll_speed; - else - low = curr_prcm_set->dpll_speed / 2; - - dd = clk->dpll_data; - if (!dd) - return -EINVAL; - - tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg); - tmpset.cm_clksel1_pll &= ~(dd->mult_mask | - dd->div1_mask); - div = ((curr_prcm_set->xtal_speed / 1000000) - 1); - tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2); - tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK; - if (rate > low) { - tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2; - mult = ((rate / 2) / 1000000); - done_rate = CORE_CLK_SRC_DPLL_X2; - } else { - tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL; - mult = (rate / 1000000); - done_rate = CORE_CLK_SRC_DPLL; - } - tmpset.cm_clksel1_pll |= (div << __ffs(dd->mult_mask)); - tmpset.cm_clksel1_pll |= (mult << __ffs(dd->div1_mask)); - - /* Worst case */ - tmpset.base_sdrc_rfr = SDRC_RFR_CTRL_BYPASS; - - if (rate == curr_prcm_set->xtal_speed) /* If asking for 1-1 */ - bypass = 1; - - /* For omap2xxx_sdrc_init_params() */ - omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); - - /* Force dll lock mode */ - omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr, - bypass); - - /* Errata: ret dll entry state */ - omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked()); - omap2xxx_sdrc_reprogram(done_rate, 0); - } - - return 0; -} - -/** - * omap2_table_mpu_recalc - just return the MPU speed - * @clk: virt_prcm_set struct clk - * - * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set. - */ -static unsigned long omap2_table_mpu_recalc(struct clk *clk) -{ - return curr_prcm_set->mpu_speed; -} - -/* - * Look for a rate equal or less than the target rate given a configuration set. - * - * What's not entirely clear is "which" field represents the key field. - * Some might argue L3-DDR, others ARM, others IVA. This code is simple and - * just uses the ARM rates. - */ -static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate) -{ - struct prcm_config *ptr; - long highest_rate; - - if (clk != &virt_prcm_set) - return -EINVAL; - - highest_rate = -EINVAL; - - for (ptr = rate_table; ptr->mpu_speed; ptr++) { - if (!(ptr->flags & cpu_mask)) - continue; - if (ptr->xtal_speed != sys_ck.rate) - continue; - - highest_rate = ptr->mpu_speed; - - /* Can check only after xtal frequency check */ - if (ptr->mpu_speed <= rate) - break; - } - return highest_rate; -} - -/* Sets basic clocks based on the specified rate */ -static int omap2_select_table_rate(struct clk *clk, unsigned long rate) -{ - u32 cur_rate, done_rate, bypass = 0, tmp; - struct prcm_config *prcm; - unsigned long found_speed = 0; - unsigned long flags; - - if (clk != &virt_prcm_set) - return -EINVAL; - - for (prcm = rate_table; prcm->mpu_speed; prcm++) { - if (!(prcm->flags & cpu_mask)) - continue; - - if (prcm->xtal_speed != sys_ck.rate) - continue; - - if (prcm->mpu_speed <= rate) { - found_speed = prcm->mpu_speed; - break; - } - } - - if (!found_speed) { - printk(KERN_INFO "Could not set MPU rate to %luMHz\n", - rate / 1000000); - return -EINVAL; - } - - curr_prcm_set = prcm; - cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck); - - if (prcm->dpll_speed == cur_rate / 2) { - omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1); - } else if (prcm->dpll_speed == cur_rate * 2) { - omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); - } else if (prcm->dpll_speed != cur_rate) { - local_irq_save(flags); - - if (prcm->dpll_speed == prcm->xtal_speed) - bypass = 1; - - if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) == - CORE_CLK_SRC_DPLL_X2) - done_rate = CORE_CLK_SRC_DPLL_X2; - else - done_rate = CORE_CLK_SRC_DPLL; - - /* MPU divider */ - cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL); - - /* dsp + iva1 div(2420), iva2.1(2430) */ - cm_write_mod_reg(prcm->cm_clksel_dsp, - OMAP24XX_DSP_MOD, CM_CLKSEL); - - cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL); - - /* Major subsystem dividers */ - tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK; - cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD, - CM_CLKSEL1); - - if (cpu_is_omap2430()) - cm_write_mod_reg(prcm->cm_clksel_mdm, - OMAP2430_MDM_MOD, CM_CLKSEL); - - /* x2 to enter omap2xxx_sdrc_init_params() */ - omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); - - omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr, - bypass); - - omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked()); - omap2xxx_sdrc_reprogram(done_rate, 0); - - local_irq_restore(flags); - } - - return 0; -} - -#ifdef CONFIG_CPU_FREQ -/* - * Walk PRCM rate table and fillout cpufreq freq_table - */ -static struct cpufreq_frequency_table freq_table[ARRAY_SIZE(rate_table)]; - -void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table) -{ - struct prcm_config *prcm; - int i = 0; - - for (prcm = rate_table; prcm->mpu_speed; prcm++) { - if (!(prcm->flags & cpu_mask)) - continue; - if (prcm->xtal_speed != sys_ck.rate) - continue; - - /* don't put bypass rates in table */ - if (prcm->dpll_speed == prcm->xtal_speed) - continue; - - freq_table[i].index = i; - freq_table[i].frequency = prcm->mpu_speed / 1000; - i++; - } - - if (i == 0) { - printk(KERN_WARNING "%s: failed to initialize frequency " - "table\n", __func__); - return; - } - - freq_table[i].index = i; - freq_table[i].frequency = CPUFREQ_TABLE_END; - - *table = &freq_table[0]; -} -#endif - -static struct clk_functions omap2_clk_functions = { - .clk_enable = omap2_clk_enable, - .clk_disable = omap2_clk_disable, - .clk_round_rate = omap2_clk_round_rate, - .clk_set_rate = omap2_clk_set_rate, - .clk_set_parent = omap2_clk_set_parent, - .clk_disable_unused = omap2_clk_disable_unused, -#ifdef CONFIG_CPU_FREQ - .clk_init_cpufreq_table = omap2_clk_init_cpufreq_table, -#endif -}; - -static u32 omap2_get_apll_clkin(void) -{ - u32 aplls, srate = 0; - - aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1); - aplls &= OMAP24XX_APLLS_CLKIN_MASK; - aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT; - - if (aplls == APLLS_CLKIN_19_2MHZ) - srate = 19200000; - else if (aplls == APLLS_CLKIN_13MHZ) - srate = 13000000; - else if (aplls == APLLS_CLKIN_12MHZ) - srate = 12000000; - - return srate; -} - -static u32 omap2_get_sysclkdiv(void) -{ - u32 div; - - div = __raw_readl(prcm_clksrc_ctrl); - div &= OMAP_SYSCLKDIV_MASK; - div >>= OMAP_SYSCLKDIV_SHIFT; - - return div; -} - -static unsigned long omap2_osc_clk_recalc(struct clk *clk) -{ - return omap2_get_apll_clkin() * omap2_get_sysclkdiv(); -} - -static unsigned long omap2_sys_clk_recalc(struct clk *clk) -{ - return clk->parent->rate / omap2_get_sysclkdiv(); -} - -/* - * Set clocks for bypass mode for reboot to work. - */ -void omap2_clk_prepare_for_reboot(void) -{ - u32 rate; - - if (vclk == NULL || sclk == NULL) - return; - - rate = clk_get_rate(sclk); - clk_set_rate(vclk, rate); -} - -/* - * Switch the MPU rate if specified on cmdline. - * We cannot do this early until cmdline is parsed. - */ -static int __init omap2_clk_arch_init(void) -{ - if (!mpurate) - return -EINVAL; - - if (clk_set_rate(&virt_prcm_set, mpurate)) - printk(KERN_ERR "Could not find matching MPU rate\n"); - - recalculate_root_clocks(); - - printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): " - "%ld.%01ld/%ld/%ld MHz\n", - (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10, - (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ; - - return 0; -} -arch_initcall(omap2_clk_arch_init); - -int __init omap2_clk_init(void) -{ - struct prcm_config *prcm; - struct omap_clk *c; - u32 clkrate; - - if (cpu_is_omap242x()) { - prcm_clksrc_ctrl = OMAP2420_PRCM_CLKSRC_CTRL; - cpu_mask = RATE_IN_242X; - } else if (cpu_is_omap2430()) { - prcm_clksrc_ctrl = OMAP2430_PRCM_CLKSRC_CTRL; - cpu_mask = RATE_IN_243X; - } - - clk_init(&omap2_clk_functions); - - for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++) - clk_preinit(c->lk.clk); - - osc_ck.rate = omap2_osc_clk_recalc(&osc_ck); - propagate_rate(&osc_ck); - sys_ck.rate = omap2_sys_clk_recalc(&sys_ck); - propagate_rate(&sys_ck); - - for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++) - if (c->cpu & cpu_mask) { - clkdev_add(&c->lk); - clk_register(c->lk.clk); - omap2_init_clk_clkdm(c->lk.clk); - } - - /* Check the MPU rate set by bootloader */ - clkrate = omap2xxx_clk_get_core_rate(&dpll_ck); - for (prcm = rate_table; prcm->mpu_speed; prcm++) { - if (!(prcm->flags & cpu_mask)) - continue; - if (prcm->xtal_speed != sys_ck.rate) - continue; - if (prcm->dpll_speed <= clkrate) - break; - } - curr_prcm_set = prcm; - - recalculate_root_clocks(); - - printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): " - "%ld.%01ld/%ld/%ld MHz\n", - (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10, - (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ; - - /* - * Only enable those clocks we will need, let the drivers - * enable other clocks as necessary - */ - clk_enable_init_clocks(); - - /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */ - vclk = clk_get(NULL, "virt_prcm_set"); - sclk = clk_get(NULL, "sys_ck"); - - return 0; -} diff --git a/arch/arm/mach-omap2/clock2xxx.c b/arch/arm/mach-omap2/clock2xxx.c new file mode 100644 index 0000000000000000000000000000000000000000..d0e3fb7f92983fcbc41bedf0e9378b194aebb616 --- /dev/null +++ b/arch/arm/mach-omap2/clock2xxx.c @@ -0,0 +1,587 @@ +/* + * linux/arch/arm/mach-omap2/clock.c + * + * Copyright (C) 2005-2008 Texas Instruments, Inc. + * Copyright (C) 2004-2008 Nokia Corporation + * + * Contacts: + * Richard Woodruff + * Paul Walmsley + * + * Based on earlier work by Tuukka Tikkanen, Tony Lindgren, + * Gordon McNutt and RidgeRun, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include "clock.h" +#include "clock2xxx.h" +#include "opp2xxx.h" +#include "prm.h" +#include "prm-regbits-24xx.h" +#include "cm.h" +#include "cm-regbits-24xx.h" + + +/* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */ +#define EN_APLL_STOPPED 0 +#define EN_APLL_LOCKED 3 + +/* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */ +#define APLLS_CLKIN_19_2MHZ 0 +#define APLLS_CLKIN_13MHZ 2 +#define APLLS_CLKIN_12MHZ 3 + +/* #define DOWN_VARIABLE_DPLL 1 */ /* Experimental */ + +const struct prcm_config *curr_prcm_set; +const struct prcm_config *rate_table; + +struct clk *vclk, *sclk, *dclk; + +void __iomem *prcm_clksrc_ctrl; + +/*------------------------------------------------------------------------- + * Omap24xx specific clock functions + *-------------------------------------------------------------------------*/ + +/** + * omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS + * @clk: struct clk * being enabled + * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into + * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into + * + * OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the + * CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE. This custom function + * passes back the correct CM_IDLEST register address for I2CHS + * modules. No return value. + */ +static void omap2430_clk_i2chs_find_idlest(struct clk *clk, + void __iomem **idlest_reg, + u8 *idlest_bit) +{ + *idlest_reg = OMAP_CM_REGADDR(CORE_MOD, CM_IDLEST); + *idlest_bit = clk->enable_bit; +} + +/* 2430 I2CHS has non-standard IDLEST register */ +const struct clkops clkops_omap2430_i2chs_wait = { + .enable = omap2_dflt_clk_enable, + .disable = omap2_dflt_clk_disable, + .find_idlest = omap2430_clk_i2chs_find_idlest, + .find_companion = omap2_clk_dflt_find_companion, +}; + +/** + * omap2xxx_clk_get_core_rate - return the CORE_CLK rate + * @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck") + * + * Returns the CORE_CLK rate. CORE_CLK can have one of three rate + * sources on OMAP2xxx: the DPLL CLKOUT rate, DPLL CLKOUTX2, or 32KHz + * (the latter is unusual). This currently should be called with + * struct clk *dpll_ck, which is a composite clock of dpll_ck and + * core_ck. + */ +unsigned long omap2xxx_clk_get_core_rate(struct clk *clk) +{ + long long core_clk; + u32 v; + + core_clk = omap2_get_dpll_rate(clk); + + v = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2); + v &= OMAP24XX_CORE_CLK_SRC_MASK; + + if (v == CORE_CLK_SRC_32K) + core_clk = 32768; + else + core_clk *= v; + + return core_clk; +} + +static int omap2_enable_osc_ck(struct clk *clk) +{ + u32 pcc; + + pcc = __raw_readl(prcm_clksrc_ctrl); + + __raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl); + + return 0; +} + +static void omap2_disable_osc_ck(struct clk *clk) +{ + u32 pcc; + + pcc = __raw_readl(prcm_clksrc_ctrl); + + __raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl); +} + +const struct clkops clkops_oscck = { + .enable = omap2_enable_osc_ck, + .disable = omap2_disable_osc_ck, +}; + +#ifdef OLD_CK +/* Recalculate SYST_CLK */ +static void omap2_sys_clk_recalc(struct clk *clk) +{ + u32 div = PRCM_CLKSRC_CTRL; + div &= (1 << 7) | (1 << 6); /* Test if ext clk divided by 1 or 2 */ + div >>= clk->rate_offset; + clk->rate = (clk->parent->rate / div); + propagate_rate(clk); +} +#endif /* OLD_CK */ + +/* Enable an APLL if off */ +static int omap2_clk_apll_enable(struct clk *clk, u32 status_mask) +{ + u32 cval, apll_mask; + + apll_mask = EN_APLL_LOCKED << clk->enable_bit; + + cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN); + + if ((cval & apll_mask) == apll_mask) + return 0; /* apll already enabled */ + + cval &= ~apll_mask; + cval |= apll_mask; + cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN); + + omap2_cm_wait_idlest(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), status_mask, + clk->name); + + /* + * REVISIT: Should we return an error code if omap2_wait_clock_ready() + * fails? + */ + return 0; +} + +static int omap2_clk_apll96_enable(struct clk *clk) +{ + return omap2_clk_apll_enable(clk, OMAP24XX_ST_96M_APLL); +} + +static int omap2_clk_apll54_enable(struct clk *clk) +{ + return omap2_clk_apll_enable(clk, OMAP24XX_ST_54M_APLL); +} + +/* Stop APLL */ +static void omap2_clk_apll_disable(struct clk *clk) +{ + u32 cval; + + cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN); + cval &= ~(EN_APLL_LOCKED << clk->enable_bit); + cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN); +} + +const struct clkops clkops_apll96 = { + .enable = omap2_clk_apll96_enable, + .disable = omap2_clk_apll_disable, +}; + +const struct clkops clkops_apll54 = { + .enable = omap2_clk_apll54_enable, + .disable = omap2_clk_apll_disable, +}; + +/* + * Uses the current prcm set to tell if a rate is valid. + * You can go slower, but not faster within a given rate set. + */ +long omap2_dpllcore_round_rate(unsigned long target_rate) +{ + u32 high, low, core_clk_src; + + core_clk_src = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2); + core_clk_src &= OMAP24XX_CORE_CLK_SRC_MASK; + + if (core_clk_src == CORE_CLK_SRC_DPLL) { /* DPLL clockout */ + high = curr_prcm_set->dpll_speed * 2; + low = curr_prcm_set->dpll_speed; + } else { /* DPLL clockout x 2 */ + high = curr_prcm_set->dpll_speed; + low = curr_prcm_set->dpll_speed / 2; + } + +#ifdef DOWN_VARIABLE_DPLL + if (target_rate > high) + return high; + else + return target_rate; +#else + if (target_rate > low) + return high; + else + return low; +#endif + +} + +unsigned long omap2_dpllcore_recalc(struct clk *clk) +{ + return omap2xxx_clk_get_core_rate(clk); +} + +int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate) +{ + u32 cur_rate, low, mult, div, valid_rate, done_rate; + u32 bypass = 0; + struct prcm_config tmpset; + const struct dpll_data *dd; + + cur_rate = omap2xxx_clk_get_core_rate(dclk); + mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2); + mult &= OMAP24XX_CORE_CLK_SRC_MASK; + + if ((rate == (cur_rate / 2)) && (mult == 2)) { + omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1); + } else if ((rate == (cur_rate * 2)) && (mult == 1)) { + omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); + } else if (rate != cur_rate) { + valid_rate = omap2_dpllcore_round_rate(rate); + if (valid_rate != rate) + return -EINVAL; + + if (mult == 1) + low = curr_prcm_set->dpll_speed; + else + low = curr_prcm_set->dpll_speed / 2; + + dd = clk->dpll_data; + if (!dd) + return -EINVAL; + + tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg); + tmpset.cm_clksel1_pll &= ~(dd->mult_mask | + dd->div1_mask); + div = ((curr_prcm_set->xtal_speed / 1000000) - 1); + tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2); + tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK; + if (rate > low) { + tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2; + mult = ((rate / 2) / 1000000); + done_rate = CORE_CLK_SRC_DPLL_X2; + } else { + tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL; + mult = (rate / 1000000); + done_rate = CORE_CLK_SRC_DPLL; + } + tmpset.cm_clksel1_pll |= (div << __ffs(dd->mult_mask)); + tmpset.cm_clksel1_pll |= (mult << __ffs(dd->div1_mask)); + + /* Worst case */ + tmpset.base_sdrc_rfr = SDRC_RFR_CTRL_BYPASS; + + if (rate == curr_prcm_set->xtal_speed) /* If asking for 1-1 */ + bypass = 1; + + /* For omap2xxx_sdrc_init_params() */ + omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); + + /* Force dll lock mode */ + omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr, + bypass); + + /* Errata: ret dll entry state */ + omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked()); + omap2xxx_sdrc_reprogram(done_rate, 0); + } + + return 0; +} + +/** + * omap2_table_mpu_recalc - just return the MPU speed + * @clk: virt_prcm_set struct clk + * + * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set. + */ +unsigned long omap2_table_mpu_recalc(struct clk *clk) +{ + return curr_prcm_set->mpu_speed; +} + +/* + * Look for a rate equal or less than the target rate given a configuration set. + * + * What's not entirely clear is "which" field represents the key field. + * Some might argue L3-DDR, others ARM, others IVA. This code is simple and + * just uses the ARM rates. + */ +long omap2_round_to_table_rate(struct clk *clk, unsigned long rate) +{ + const struct prcm_config *ptr; + long highest_rate; + long sys_ck_rate; + + sys_ck_rate = clk_get_rate(sclk); + + highest_rate = -EINVAL; + + for (ptr = rate_table; ptr->mpu_speed; ptr++) { + if (!(ptr->flags & cpu_mask)) + continue; + if (ptr->xtal_speed != sys_ck_rate) + continue; + + highest_rate = ptr->mpu_speed; + + /* Can check only after xtal frequency check */ + if (ptr->mpu_speed <= rate) + break; + } + return highest_rate; +} + +/* Sets basic clocks based on the specified rate */ +int omap2_select_table_rate(struct clk *clk, unsigned long rate) +{ + u32 cur_rate, done_rate, bypass = 0, tmp; + const struct prcm_config *prcm; + unsigned long found_speed = 0; + unsigned long flags; + long sys_ck_rate; + + sys_ck_rate = clk_get_rate(sclk); + + for (prcm = rate_table; prcm->mpu_speed; prcm++) { + if (!(prcm->flags & cpu_mask)) + continue; + + if (prcm->xtal_speed != sys_ck_rate) + continue; + + if (prcm->mpu_speed <= rate) { + found_speed = prcm->mpu_speed; + break; + } + } + + if (!found_speed) { + printk(KERN_INFO "Could not set MPU rate to %luMHz\n", + rate / 1000000); + return -EINVAL; + } + + curr_prcm_set = prcm; + cur_rate = omap2xxx_clk_get_core_rate(dclk); + + if (prcm->dpll_speed == cur_rate / 2) { + omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1); + } else if (prcm->dpll_speed == cur_rate * 2) { + omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); + } else if (prcm->dpll_speed != cur_rate) { + local_irq_save(flags); + + if (prcm->dpll_speed == prcm->xtal_speed) + bypass = 1; + + if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) == + CORE_CLK_SRC_DPLL_X2) + done_rate = CORE_CLK_SRC_DPLL_X2; + else + done_rate = CORE_CLK_SRC_DPLL; + + /* MPU divider */ + cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL); + + /* dsp + iva1 div(2420), iva2.1(2430) */ + cm_write_mod_reg(prcm->cm_clksel_dsp, + OMAP24XX_DSP_MOD, CM_CLKSEL); + + cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL); + + /* Major subsystem dividers */ + tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK; + cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD, + CM_CLKSEL1); + + if (cpu_is_omap2430()) + cm_write_mod_reg(prcm->cm_clksel_mdm, + OMAP2430_MDM_MOD, CM_CLKSEL); + + /* x2 to enter omap2xxx_sdrc_init_params() */ + omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); + + omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr, + bypass); + + omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked()); + omap2xxx_sdrc_reprogram(done_rate, 0); + + local_irq_restore(flags); + } + + return 0; +} + +#ifdef CONFIG_CPU_FREQ +/* + * Walk PRCM rate table and fillout cpufreq freq_table + */ +static struct cpufreq_frequency_table freq_table[ARRAY_SIZE(rate_table)]; + +void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table) +{ + struct prcm_config *prcm; + int i = 0; + + for (prcm = rate_table; prcm->mpu_speed; prcm++) { + if (!(prcm->flags & cpu_mask)) + continue; + if (prcm->xtal_speed != sys_ck.rate) + continue; + + /* don't put bypass rates in table */ + if (prcm->dpll_speed == prcm->xtal_speed) + continue; + + freq_table[i].index = i; + freq_table[i].frequency = prcm->mpu_speed / 1000; + i++; + } + + if (i == 0) { + printk(KERN_WARNING "%s: failed to initialize frequency " + "table\n", __func__); + return; + } + + freq_table[i].index = i; + freq_table[i].frequency = CPUFREQ_TABLE_END; + + *table = &freq_table[0]; +} +#endif + +struct clk_functions omap2_clk_functions = { + .clk_enable = omap2_clk_enable, + .clk_disable = omap2_clk_disable, + .clk_round_rate = omap2_clk_round_rate, + .clk_set_rate = omap2_clk_set_rate, + .clk_set_parent = omap2_clk_set_parent, + .clk_disable_unused = omap2_clk_disable_unused, +#ifdef CONFIG_CPU_FREQ + .clk_init_cpufreq_table = omap2_clk_init_cpufreq_table, +#endif +}; + +static u32 omap2_get_apll_clkin(void) +{ + u32 aplls, srate = 0; + + aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1); + aplls &= OMAP24XX_APLLS_CLKIN_MASK; + aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT; + + if (aplls == APLLS_CLKIN_19_2MHZ) + srate = 19200000; + else if (aplls == APLLS_CLKIN_13MHZ) + srate = 13000000; + else if (aplls == APLLS_CLKIN_12MHZ) + srate = 12000000; + + return srate; +} + +static u32 omap2_get_sysclkdiv(void) +{ + u32 div; + + div = __raw_readl(prcm_clksrc_ctrl); + div &= OMAP_SYSCLKDIV_MASK; + div >>= OMAP_SYSCLKDIV_SHIFT; + + return div; +} + +unsigned long omap2_osc_clk_recalc(struct clk *clk) +{ + return omap2_get_apll_clkin() * omap2_get_sysclkdiv(); +} + +unsigned long omap2_sys_clk_recalc(struct clk *clk) +{ + return clk->parent->rate / omap2_get_sysclkdiv(); +} + +/* + * Set clocks for bypass mode for reboot to work. + */ +void omap2_clk_prepare_for_reboot(void) +{ + u32 rate; + + if (vclk == NULL || sclk == NULL) + return; + + rate = clk_get_rate(sclk); + clk_set_rate(vclk, rate); +} + +/* + * Switch the MPU rate if specified on cmdline. + * We cannot do this early until cmdline is parsed. + */ +static int __init omap2_clk_arch_init(void) +{ + struct clk *virt_prcm_set, *sys_ck, *dpll_ck, *mpu_ck; + unsigned long sys_ck_rate; + + if (!mpurate) + return -EINVAL; + + virt_prcm_set = clk_get(NULL, "virt_prcm_set"); + sys_ck = clk_get(NULL, "sys_ck"); + dpll_ck = clk_get(NULL, "dpll_ck"); + mpu_ck = clk_get(NULL, "mpu_ck"); + + if (clk_set_rate(virt_prcm_set, mpurate)) + printk(KERN_ERR "Could not find matching MPU rate\n"); + + recalculate_root_clocks(); + + sys_ck_rate = clk_get_rate(sys_ck); + + pr_info("Switched to new clocking rate (Crystal/DPLL/MPU): " + "%ld.%01ld/%ld/%ld MHz\n", + (sys_ck_rate / 1000000), (sys_ck_rate / 100000) % 10, + (clk_get_rate(dpll_ck) / 1000000), + (clk_get_rate(mpu_ck) / 1000000)); + + return 0; +} +arch_initcall(omap2_clk_arch_init); + + diff --git a/arch/arm/mach-omap2/clock2xxx.h b/arch/arm/mach-omap2/clock2xxx.h new file mode 100644 index 0000000000000000000000000000000000000000..e35efde4bd8050eb317de5457d90e758560bc10b --- /dev/null +++ b/arch/arm/mach-omap2/clock2xxx.h @@ -0,0 +1,41 @@ +/* + * OMAP2 clock function prototypes and macros + * + * Copyright (C) 2005-2009 Texas Instruments, Inc. + * Copyright (C) 2004-2009 Nokia Corporation + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK_24XX_H +#define __ARCH_ARM_MACH_OMAP2_CLOCK_24XX_H + +unsigned long omap2_table_mpu_recalc(struct clk *clk); +int omap2_select_table_rate(struct clk *clk, unsigned long rate); +long omap2_round_to_table_rate(struct clk *clk, unsigned long rate); +unsigned long omap2_sys_clk_recalc(struct clk *clk); +unsigned long omap2_osc_clk_recalc(struct clk *clk); +unsigned long omap2_sys_clk_recalc(struct clk *clk); +unsigned long omap2_dpllcore_recalc(struct clk *clk); +int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate); +unsigned long omap2xxx_clk_get_core_rate(struct clk *clk); + +/* REVISIT: These should be set dynamically for CONFIG_MULTI_OMAP2 */ +#ifdef CONFIG_ARCH_OMAP2420 +#define OMAP_CM_REGADDR OMAP2420_CM_REGADDR +#define OMAP24XX_PRCM_CLKOUT_CTRL OMAP2420_PRCM_CLKOUT_CTRL +#define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP2420_PRCM_CLKEMUL_CTRL +#else +#define OMAP_CM_REGADDR OMAP2430_CM_REGADDR +#define OMAP24XX_PRCM_CLKOUT_CTRL OMAP2430_PRCM_CLKOUT_CTRL +#define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP2430_PRCM_CLKEMUL_CTRL +#endif + +extern void __iomem *prcm_clksrc_ctrl; + +extern struct clk *dclk; + +extern const struct clkops clkops_omap2430_i2chs_wait; +extern const struct clkops clkops_oscck; +extern const struct clkops clkops_apll96; +extern const struct clkops clkops_apll54; + +#endif diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock2xxx_data.c similarity index 73% rename from arch/arm/mach-omap2/clock24xx.h rename to arch/arm/mach-omap2/clock2xxx_data.c index d19cf7a7d8db36ef7045edb601b65361709c4ddd..97dc7cf7751d6248e7491134fe54841a44aba377 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock2xxx_data.c @@ -1,8 +1,8 @@ /* - * linux/arch/arm/mach-omap2/clock24xx.h + * linux/arch/arm/mach-omap2/clock2xxx_data.c * - * Copyright (C) 2005-2008 Texas Instruments, Inc. - * Copyright (C) 2004-2008 Nokia Corporation + * Copyright (C) 2005-2009 Texas Instruments, Inc. + * Copyright (C) 2004-2009 Nokia Corporation * * Contacts: * Richard Woodruff @@ -13,600 +13,21 @@ * published by the Free Software Foundation. */ -#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK24XX_H -#define __ARCH_ARM_MACH_OMAP2_CLOCK24XX_H +#include +#include +#include -#include "clock.h" +#include +#include "clock.h" +#include "clock2xxx.h" +#include "opp2xxx.h" #include "prm.h" #include "cm.h" #include "prm-regbits-24xx.h" #include "cm-regbits-24xx.h" #include "sdrc.h" -/* REVISIT: These should be set dynamically for CONFIG_MULTI_OMAP2 */ -#ifdef CONFIG_ARCH_OMAP2420 -#define OMAP_CM_REGADDR OMAP2420_CM_REGADDR -#define OMAP24XX_PRCM_CLKOUT_CTRL OMAP2420_PRCM_CLKOUT_CTRL -#define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP2420_PRCM_CLKEMUL_CTRL -#else -#define OMAP_CM_REGADDR OMAP2430_CM_REGADDR -#define OMAP24XX_PRCM_CLKOUT_CTRL OMAP2430_PRCM_CLKOUT_CTRL -#define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP2430_PRCM_CLKEMUL_CTRL -#endif - -static unsigned long omap2_table_mpu_recalc(struct clk *clk); -static int omap2_select_table_rate(struct clk *clk, unsigned long rate); -static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate); -static unsigned long omap2_sys_clk_recalc(struct clk *clk); -static unsigned long omap2_osc_clk_recalc(struct clk *clk); -static unsigned long omap2_sys_clk_recalc(struct clk *clk); -static unsigned long omap2_dpllcore_recalc(struct clk *clk); -static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate); - -/* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated. - * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP - * CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM - */ -struct prcm_config { - unsigned long xtal_speed; /* crystal rate */ - unsigned long dpll_speed; /* dpll: out*xtal*M/(N-1)table_recalc */ - unsigned long mpu_speed; /* speed of MPU */ - unsigned long cm_clksel_mpu; /* mpu divider */ - unsigned long cm_clksel_dsp; /* dsp+iva1 div(2420), iva2.1(2430) */ - unsigned long cm_clksel_gfx; /* gfx dividers */ - unsigned long cm_clksel1_core; /* major subsystem dividers */ - unsigned long cm_clksel1_pll; /* m,n */ - unsigned long cm_clksel2_pll; /* dpllx1 or x2 out */ - unsigned long cm_clksel_mdm; /* modem dividers 2430 only */ - unsigned long base_sdrc_rfr; /* base refresh timing for a set */ - unsigned char flags; -}; - -/* - * The OMAP2 processor can be run at several discrete 'PRCM configurations'. - * These configurations are characterized by voltage and speed for clocks. - * The device is only validated for certain combinations. One way to express - * these combinations is via the 'ratio's' which the clocks operate with - * respect to each other. These ratio sets are for a given voltage/DPLL - * setting. All configurations can be described by a DPLL setting and a ratio - * There are 3 ratio sets for the 2430 and X ratio sets for 2420. - * - * 2430 differs from 2420 in that there are no more phase synchronizers used. - * They both have a slightly different clock domain setup. 2420(iva1,dsp) vs - * 2430 (iva2.1, NOdsp, mdm) - */ - -/* Core fields for cm_clksel, not ratio governed */ -#define RX_CLKSEL_DSS1 (0x10 << 8) -#define RX_CLKSEL_DSS2 (0x0 << 13) -#define RX_CLKSEL_SSI (0x5 << 20) - -/*------------------------------------------------------------------------- - * Voltage/DPLL ratios - *-------------------------------------------------------------------------*/ - -/* 2430 Ratio's, 2430-Ratio Config 1 */ -#define R1_CLKSEL_L3 (4 << 0) -#define R1_CLKSEL_L4 (2 << 5) -#define R1_CLKSEL_USB (4 << 25) -#define R1_CM_CLKSEL1_CORE_VAL R1_CLKSEL_USB | RX_CLKSEL_SSI | \ - RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \ - R1_CLKSEL_L4 | R1_CLKSEL_L3 -#define R1_CLKSEL_MPU (2 << 0) -#define R1_CM_CLKSEL_MPU_VAL R1_CLKSEL_MPU -#define R1_CLKSEL_DSP (2 << 0) -#define R1_CLKSEL_DSP_IF (2 << 5) -#define R1_CM_CLKSEL_DSP_VAL R1_CLKSEL_DSP | R1_CLKSEL_DSP_IF -#define R1_CLKSEL_GFX (2 << 0) -#define R1_CM_CLKSEL_GFX_VAL R1_CLKSEL_GFX -#define R1_CLKSEL_MDM (4 << 0) -#define R1_CM_CLKSEL_MDM_VAL R1_CLKSEL_MDM - -/* 2430-Ratio Config 2 */ -#define R2_CLKSEL_L3 (6 << 0) -#define R2_CLKSEL_L4 (2 << 5) -#define R2_CLKSEL_USB (2 << 25) -#define R2_CM_CLKSEL1_CORE_VAL R2_CLKSEL_USB | RX_CLKSEL_SSI | \ - RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \ - R2_CLKSEL_L4 | R2_CLKSEL_L3 -#define R2_CLKSEL_MPU (2 << 0) -#define R2_CM_CLKSEL_MPU_VAL R2_CLKSEL_MPU -#define R2_CLKSEL_DSP (2 << 0) -#define R2_CLKSEL_DSP_IF (3 << 5) -#define R2_CM_CLKSEL_DSP_VAL R2_CLKSEL_DSP | R2_CLKSEL_DSP_IF -#define R2_CLKSEL_GFX (2 << 0) -#define R2_CM_CLKSEL_GFX_VAL R2_CLKSEL_GFX -#define R2_CLKSEL_MDM (6 << 0) -#define R2_CM_CLKSEL_MDM_VAL R2_CLKSEL_MDM - -/* 2430-Ratio Bootm (BYPASS) */ -#define RB_CLKSEL_L3 (1 << 0) -#define RB_CLKSEL_L4 (1 << 5) -#define RB_CLKSEL_USB (1 << 25) -#define RB_CM_CLKSEL1_CORE_VAL RB_CLKSEL_USB | RX_CLKSEL_SSI | \ - RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \ - RB_CLKSEL_L4 | RB_CLKSEL_L3 -#define RB_CLKSEL_MPU (1 << 0) -#define RB_CM_CLKSEL_MPU_VAL RB_CLKSEL_MPU -#define RB_CLKSEL_DSP (1 << 0) -#define RB_CLKSEL_DSP_IF (1 << 5) -#define RB_CM_CLKSEL_DSP_VAL RB_CLKSEL_DSP | RB_CLKSEL_DSP_IF -#define RB_CLKSEL_GFX (1 << 0) -#define RB_CM_CLKSEL_GFX_VAL RB_CLKSEL_GFX -#define RB_CLKSEL_MDM (1 << 0) -#define RB_CM_CLKSEL_MDM_VAL RB_CLKSEL_MDM - -/* 2420 Ratio Equivalents */ -#define RXX_CLKSEL_VLYNQ (0x12 << 15) -#define RXX_CLKSEL_SSI (0x8 << 20) - -/* 2420-PRCM III 532MHz core */ -#define RIII_CLKSEL_L3 (4 << 0) /* 133MHz */ -#define RIII_CLKSEL_L4 (2 << 5) /* 66.5MHz */ -#define RIII_CLKSEL_USB (4 << 25) /* 33.25MHz */ -#define RIII_CM_CLKSEL1_CORE_VAL RIII_CLKSEL_USB | RXX_CLKSEL_SSI | \ - RXX_CLKSEL_VLYNQ | RX_CLKSEL_DSS2 | \ - RX_CLKSEL_DSS1 | RIII_CLKSEL_L4 | \ - RIII_CLKSEL_L3 -#define RIII_CLKSEL_MPU (2 << 0) /* 266MHz */ -#define RIII_CM_CLKSEL_MPU_VAL RIII_CLKSEL_MPU -#define RIII_CLKSEL_DSP (3 << 0) /* c5x - 177.3MHz */ -#define RIII_CLKSEL_DSP_IF (2 << 5) /* c5x - 88.67MHz */ -#define RIII_SYNC_DSP (1 << 7) /* Enable sync */ -#define RIII_CLKSEL_IVA (6 << 8) /* iva1 - 88.67MHz */ -#define RIII_SYNC_IVA (1 << 13) /* Enable sync */ -#define RIII_CM_CLKSEL_DSP_VAL RIII_SYNC_IVA | RIII_CLKSEL_IVA | \ - RIII_SYNC_DSP | RIII_CLKSEL_DSP_IF | \ - RIII_CLKSEL_DSP -#define RIII_CLKSEL_GFX (2 << 0) /* 66.5MHz */ -#define RIII_CM_CLKSEL_GFX_VAL RIII_CLKSEL_GFX - -/* 2420-PRCM II 600MHz core */ -#define RII_CLKSEL_L3 (6 << 0) /* 100MHz */ -#define RII_CLKSEL_L4 (2 << 5) /* 50MHz */ -#define RII_CLKSEL_USB (2 << 25) /* 50MHz */ -#define RII_CM_CLKSEL1_CORE_VAL RII_CLKSEL_USB | \ - RXX_CLKSEL_SSI | RXX_CLKSEL_VLYNQ | \ - RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \ - RII_CLKSEL_L4 | RII_CLKSEL_L3 -#define RII_CLKSEL_MPU (2 << 0) /* 300MHz */ -#define RII_CM_CLKSEL_MPU_VAL RII_CLKSEL_MPU -#define RII_CLKSEL_DSP (3 << 0) /* c5x - 200MHz */ -#define RII_CLKSEL_DSP_IF (2 << 5) /* c5x - 100MHz */ -#define RII_SYNC_DSP (0 << 7) /* Bypass sync */ -#define RII_CLKSEL_IVA (3 << 8) /* iva1 - 200MHz */ -#define RII_SYNC_IVA (0 << 13) /* Bypass sync */ -#define RII_CM_CLKSEL_DSP_VAL RII_SYNC_IVA | RII_CLKSEL_IVA | \ - RII_SYNC_DSP | RII_CLKSEL_DSP_IF | \ - RII_CLKSEL_DSP -#define RII_CLKSEL_GFX (2 << 0) /* 50MHz */ -#define RII_CM_CLKSEL_GFX_VAL RII_CLKSEL_GFX - -/* 2420-PRCM I 660MHz core */ -#define RI_CLKSEL_L3 (4 << 0) /* 165MHz */ -#define RI_CLKSEL_L4 (2 << 5) /* 82.5MHz */ -#define RI_CLKSEL_USB (4 << 25) /* 41.25MHz */ -#define RI_CM_CLKSEL1_CORE_VAL RI_CLKSEL_USB | \ - RXX_CLKSEL_SSI | RXX_CLKSEL_VLYNQ | \ - RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \ - RI_CLKSEL_L4 | RI_CLKSEL_L3 -#define RI_CLKSEL_MPU (2 << 0) /* 330MHz */ -#define RI_CM_CLKSEL_MPU_VAL RI_CLKSEL_MPU -#define RI_CLKSEL_DSP (3 << 0) /* c5x - 220MHz */ -#define RI_CLKSEL_DSP_IF (2 << 5) /* c5x - 110MHz */ -#define RI_SYNC_DSP (1 << 7) /* Activate sync */ -#define RI_CLKSEL_IVA (4 << 8) /* iva1 - 165MHz */ -#define RI_SYNC_IVA (0 << 13) /* Bypass sync */ -#define RI_CM_CLKSEL_DSP_VAL RI_SYNC_IVA | RI_CLKSEL_IVA | \ - RI_SYNC_DSP | RI_CLKSEL_DSP_IF | \ - RI_CLKSEL_DSP -#define RI_CLKSEL_GFX (1 << 0) /* 165MHz */ -#define RI_CM_CLKSEL_GFX_VAL RI_CLKSEL_GFX - -/* 2420-PRCM VII (boot) */ -#define RVII_CLKSEL_L3 (1 << 0) -#define RVII_CLKSEL_L4 (1 << 5) -#define RVII_CLKSEL_DSS1 (1 << 8) -#define RVII_CLKSEL_DSS2 (0 << 13) -#define RVII_CLKSEL_VLYNQ (1 << 15) -#define RVII_CLKSEL_SSI (1 << 20) -#define RVII_CLKSEL_USB (1 << 25) - -#define RVII_CM_CLKSEL1_CORE_VAL RVII_CLKSEL_USB | RVII_CLKSEL_SSI | \ - RVII_CLKSEL_VLYNQ | RVII_CLKSEL_DSS2 | \ - RVII_CLKSEL_DSS1 | RVII_CLKSEL_L4 | RVII_CLKSEL_L3 - -#define RVII_CLKSEL_MPU (1 << 0) /* all divide by 1 */ -#define RVII_CM_CLKSEL_MPU_VAL RVII_CLKSEL_MPU - -#define RVII_CLKSEL_DSP (1 << 0) -#define RVII_CLKSEL_DSP_IF (1 << 5) -#define RVII_SYNC_DSP (0 << 7) -#define RVII_CLKSEL_IVA (1 << 8) -#define RVII_SYNC_IVA (0 << 13) -#define RVII_CM_CLKSEL_DSP_VAL RVII_SYNC_IVA | RVII_CLKSEL_IVA | RVII_SYNC_DSP | \ - RVII_CLKSEL_DSP_IF | RVII_CLKSEL_DSP - -#define RVII_CLKSEL_GFX (1 << 0) -#define RVII_CM_CLKSEL_GFX_VAL RVII_CLKSEL_GFX - -/*------------------------------------------------------------------------- - * 2430 Target modes: Along with each configuration the CPU has several - * modes which goes along with them. Modes mainly are the addition of - * describe DPLL combinations to go along with a ratio. - *-------------------------------------------------------------------------*/ - -/* Hardware governed */ -#define MX_48M_SRC (0 << 3) -#define MX_54M_SRC (0 << 5) -#define MX_APLLS_CLIKIN_12 (3 << 23) -#define MX_APLLS_CLIKIN_13 (2 << 23) -#define MX_APLLS_CLIKIN_19_2 (0 << 23) - -/* - * 2430 - standalone, 2*ref*M/(n+1), M/N is for exactness not relock speed - * #5a (ratio1) baseport-target, target DPLL = 266*2 = 532MHz - */ -#define M5A_DPLL_MULT_12 (133 << 12) -#define M5A_DPLL_DIV_12 (5 << 8) -#define M5A_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \ - M5A_DPLL_DIV_12 | M5A_DPLL_MULT_12 | \ - MX_APLLS_CLIKIN_12 -#define M5A_DPLL_MULT_13 (61 << 12) -#define M5A_DPLL_DIV_13 (2 << 8) -#define M5A_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \ - M5A_DPLL_DIV_13 | M5A_DPLL_MULT_13 | \ - MX_APLLS_CLIKIN_13 -#define M5A_DPLL_MULT_19 (55 << 12) -#define M5A_DPLL_DIV_19 (3 << 8) -#define M5A_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \ - M5A_DPLL_DIV_19 | M5A_DPLL_MULT_19 | \ - MX_APLLS_CLIKIN_19_2 -/* #5b (ratio1) target DPLL = 200*2 = 400MHz */ -#define M5B_DPLL_MULT_12 (50 << 12) -#define M5B_DPLL_DIV_12 (2 << 8) -#define M5B_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \ - M5B_DPLL_DIV_12 | M5B_DPLL_MULT_12 | \ - MX_APLLS_CLIKIN_12 -#define M5B_DPLL_MULT_13 (200 << 12) -#define M5B_DPLL_DIV_13 (12 << 8) - -#define M5B_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \ - M5B_DPLL_DIV_13 | M5B_DPLL_MULT_13 | \ - MX_APLLS_CLIKIN_13 -#define M5B_DPLL_MULT_19 (125 << 12) -#define M5B_DPLL_DIV_19 (31 << 8) -#define M5B_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \ - M5B_DPLL_DIV_19 | M5B_DPLL_MULT_19 | \ - MX_APLLS_CLIKIN_19_2 -/* - * #4 (ratio2), DPLL = 399*2 = 798MHz, L3=133MHz - */ -#define M4_DPLL_MULT_12 (133 << 12) -#define M4_DPLL_DIV_12 (3 << 8) -#define M4_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \ - M4_DPLL_DIV_12 | M4_DPLL_MULT_12 | \ - MX_APLLS_CLIKIN_12 - -#define M4_DPLL_MULT_13 (399 << 12) -#define M4_DPLL_DIV_13 (12 << 8) -#define M4_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \ - M4_DPLL_DIV_13 | M4_DPLL_MULT_13 | \ - MX_APLLS_CLIKIN_13 - -#define M4_DPLL_MULT_19 (145 << 12) -#define M4_DPLL_DIV_19 (6 << 8) -#define M4_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \ - M4_DPLL_DIV_19 | M4_DPLL_MULT_19 | \ - MX_APLLS_CLIKIN_19_2 - -/* - * #3 (ratio2) baseport-target, target DPLL = 330*2 = 660MHz - */ -#define M3_DPLL_MULT_12 (55 << 12) -#define M3_DPLL_DIV_12 (1 << 8) -#define M3_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \ - M3_DPLL_DIV_12 | M3_DPLL_MULT_12 | \ - MX_APLLS_CLIKIN_12 -#define M3_DPLL_MULT_13 (76 << 12) -#define M3_DPLL_DIV_13 (2 << 8) -#define M3_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \ - M3_DPLL_DIV_13 | M3_DPLL_MULT_13 | \ - MX_APLLS_CLIKIN_13 -#define M3_DPLL_MULT_19 (17 << 12) -#define M3_DPLL_DIV_19 (0 << 8) -#define M3_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \ - M3_DPLL_DIV_19 | M3_DPLL_MULT_19 | \ - MX_APLLS_CLIKIN_19_2 - -/* - * #2 (ratio1) DPLL = 330*2 = 660MHz, L3=165MHz - */ -#define M2_DPLL_MULT_12 (55 << 12) -#define M2_DPLL_DIV_12 (1 << 8) -#define M2_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \ - M2_DPLL_DIV_12 | M2_DPLL_MULT_12 | \ - MX_APLLS_CLIKIN_12 - -/* Speed changes - Used 658.7MHz instead of 660MHz for LP-Refresh M=76 N=2, - * relock time issue */ -/* Core frequency changed from 330/165 to 329/164 MHz*/ -#define M2_DPLL_MULT_13 (76 << 12) -#define M2_DPLL_DIV_13 (2 << 8) -#define M2_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \ - M2_DPLL_DIV_13 | M2_DPLL_MULT_13 | \ - MX_APLLS_CLIKIN_13 - -#define M2_DPLL_MULT_19 (17 << 12) -#define M2_DPLL_DIV_19 (0 << 8) -#define M2_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \ - M2_DPLL_DIV_19 | M2_DPLL_MULT_19 | \ - MX_APLLS_CLIKIN_19_2 - -/* boot (boot) */ -#define MB_DPLL_MULT (1 << 12) -#define MB_DPLL_DIV (0 << 8) -#define MB_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\ - MB_DPLL_MULT | MX_APLLS_CLIKIN_12 - -#define MB_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\ - MB_DPLL_MULT | MX_APLLS_CLIKIN_13 - -#define MB_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\ - MB_DPLL_MULT | MX_APLLS_CLIKIN_19 - -/* - * 2430 - chassis (sedna) - * 165 (ratio1) same as above #2 - * 150 (ratio1) - * 133 (ratio2) same as above #4 - * 110 (ratio2) same as above #3 - * 104 (ratio2) - * boot (boot) - */ - -/* PRCM I target DPLL = 2*330MHz = 660MHz */ -#define MI_DPLL_MULT_12 (55 << 12) -#define MI_DPLL_DIV_12 (1 << 8) -#define MI_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \ - MI_DPLL_DIV_12 | MI_DPLL_MULT_12 | \ - MX_APLLS_CLIKIN_12 - -/* - * 2420 Equivalent - mode registers - * PRCM II , target DPLL = 2*300MHz = 600MHz - */ -#define MII_DPLL_MULT_12 (50 << 12) -#define MII_DPLL_DIV_12 (1 << 8) -#define MII_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \ - MII_DPLL_DIV_12 | MII_DPLL_MULT_12 | \ - MX_APLLS_CLIKIN_12 -#define MII_DPLL_MULT_13 (300 << 12) -#define MII_DPLL_DIV_13 (12 << 8) -#define MII_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \ - MII_DPLL_DIV_13 | MII_DPLL_MULT_13 | \ - MX_APLLS_CLIKIN_13 - -/* PRCM III target DPLL = 2*266 = 532MHz*/ -#define MIII_DPLL_MULT_12 (133 << 12) -#define MIII_DPLL_DIV_12 (5 << 8) -#define MIII_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \ - MIII_DPLL_DIV_12 | MIII_DPLL_MULT_12 | \ - MX_APLLS_CLIKIN_12 -#define MIII_DPLL_MULT_13 (266 << 12) -#define MIII_DPLL_DIV_13 (12 << 8) -#define MIII_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \ - MIII_DPLL_DIV_13 | MIII_DPLL_MULT_13 | \ - MX_APLLS_CLIKIN_13 - -/* PRCM VII (boot bypass) */ -#define MVII_CM_CLKSEL1_PLL_12_VAL MB_CM_CLKSEL1_PLL_12_VAL -#define MVII_CM_CLKSEL1_PLL_13_VAL MB_CM_CLKSEL1_PLL_13_VAL - -/* High and low operation value */ -#define MX_CLKSEL2_PLL_2x_VAL (2 << 0) -#define MX_CLKSEL2_PLL_1x_VAL (1 << 0) - -/* MPU speed defines */ -#define S12M 12000000 -#define S13M 13000000 -#define S19M 19200000 -#define S26M 26000000 -#define S100M 100000000 -#define S133M 133000000 -#define S150M 150000000 -#define S164M 164000000 -#define S165M 165000000 -#define S199M 199000000 -#define S200M 200000000 -#define S266M 266000000 -#define S300M 300000000 -#define S329M 329000000 -#define S330M 330000000 -#define S399M 399000000 -#define S400M 400000000 -#define S532M 532000000 -#define S600M 600000000 -#define S658M 658000000 -#define S660M 660000000 -#define S798M 798000000 - -/*------------------------------------------------------------------------- - * Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated. - * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU, - * CM_CLKSEL_DSP, CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL, - * CM_CLKSEL2_PLL, CM_CLKSEL_MDM - * - * Filling in table based on H4 boards and 2430-SDPs variants available. - * There are quite a few more rates combinations which could be defined. - * - * When multiple values are defined the start up will try and choose the - * fastest one. If a 'fast' value is defined, then automatically, the /2 - * one should be included as it can be used. Generally having more that - * one fast set does not make sense, as static timings need to be changed - * to change the set. The exception is the bypass setting which is - * availble for low power bypass. - * - * Note: This table needs to be sorted, fastest to slowest. - *-------------------------------------------------------------------------*/ -static struct prcm_config rate_table[] = { - /* PRCM I - FAST */ - {S12M, S660M, S330M, RI_CM_CLKSEL_MPU_VAL, /* 330MHz ARM */ - RI_CM_CLKSEL_DSP_VAL, RI_CM_CLKSEL_GFX_VAL, - RI_CM_CLKSEL1_CORE_VAL, MI_CM_CLKSEL1_PLL_12_VAL, - MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_165MHz, - RATE_IN_242X}, - - /* PRCM II - FAST */ - {S12M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL, /* 300MHz ARM */ - RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL, - RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL, - MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz, - RATE_IN_242X}, - - {S13M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL, /* 300MHz ARM */ - RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL, - RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL, - MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz, - RATE_IN_242X}, - - /* PRCM III - FAST */ - {S12M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */ - RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL, - RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL, - MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz, - RATE_IN_242X}, - - {S13M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */ - RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL, - RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL, - MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz, - RATE_IN_242X}, - - /* PRCM II - SLOW */ - {S12M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL, /* 150MHz ARM */ - RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL, - RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL, - MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz, - RATE_IN_242X}, - - {S13M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL, /* 150MHz ARM */ - RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL, - RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL, - MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz, - RATE_IN_242X}, - - /* PRCM III - SLOW */ - {S12M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */ - RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL, - RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL, - MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz, - RATE_IN_242X}, - - {S13M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */ - RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL, - RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL, - MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz, - RATE_IN_242X}, - - /* PRCM-VII (boot-bypass) */ - {S12M, S12M, S12M, RVII_CM_CLKSEL_MPU_VAL, /* 12MHz ARM*/ - RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL, - RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_12_VAL, - MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_BYPASS, - RATE_IN_242X}, - - /* PRCM-VII (boot-bypass) */ - {S13M, S13M, S13M, RVII_CM_CLKSEL_MPU_VAL, /* 13MHz ARM */ - RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL, - RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_13_VAL, - MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_BYPASS, - RATE_IN_242X}, - - /* PRCM #4 - ratio2 (ES2.1) - FAST */ - {S13M, S798M, S399M, R2_CM_CLKSEL_MPU_VAL, /* 399MHz ARM */ - R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL, - R2_CM_CLKSEL1_CORE_VAL, M4_CM_CLKSEL1_PLL_13_VAL, - MX_CLKSEL2_PLL_2x_VAL, R2_CM_CLKSEL_MDM_VAL, - SDRC_RFR_CTRL_133MHz, - RATE_IN_243X}, - - /* PRCM #2 - ratio1 (ES2) - FAST */ - {S13M, S658M, S329M, R1_CM_CLKSEL_MPU_VAL, /* 330MHz ARM */ - R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, - R1_CM_CLKSEL1_CORE_VAL, M2_CM_CLKSEL1_PLL_13_VAL, - MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL, - SDRC_RFR_CTRL_165MHz, - RATE_IN_243X}, - - /* PRCM #5a - ratio1 - FAST */ - {S13M, S532M, S266M, R1_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */ - R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, - R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL, - MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL, - SDRC_RFR_CTRL_133MHz, - RATE_IN_243X}, - - /* PRCM #5b - ratio1 - FAST */ - {S13M, S400M, S200M, R1_CM_CLKSEL_MPU_VAL, /* 200MHz ARM */ - R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, - R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL, - MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL, - SDRC_RFR_CTRL_100MHz, - RATE_IN_243X}, - - /* PRCM #4 - ratio1 (ES2.1) - SLOW */ - {S13M, S399M, S199M, R2_CM_CLKSEL_MPU_VAL, /* 200MHz ARM */ - R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL, - R2_CM_CLKSEL1_CORE_VAL, M4_CM_CLKSEL1_PLL_13_VAL, - MX_CLKSEL2_PLL_1x_VAL, R2_CM_CLKSEL_MDM_VAL, - SDRC_RFR_CTRL_133MHz, - RATE_IN_243X}, - - /* PRCM #2 - ratio1 (ES2) - SLOW */ - {S13M, S329M, S164M, R1_CM_CLKSEL_MPU_VAL, /* 165MHz ARM */ - R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, - R1_CM_CLKSEL1_CORE_VAL, M2_CM_CLKSEL1_PLL_13_VAL, - MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL, - SDRC_RFR_CTRL_165MHz, - RATE_IN_243X}, - - /* PRCM #5a - ratio1 - SLOW */ - {S13M, S266M, S133M, R1_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */ - R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, - R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL, - MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL, - SDRC_RFR_CTRL_133MHz, - RATE_IN_243X}, - - /* PRCM #5b - ratio1 - SLOW*/ - {S13M, S200M, S100M, R1_CM_CLKSEL_MPU_VAL, /* 100MHz ARM */ - R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, - R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL, - MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL, - SDRC_RFR_CTRL_100MHz, - RATE_IN_243X}, - - /* PRCM-boot/bypass */ - {S13M, S13M, S13M, RB_CM_CLKSEL_MPU_VAL, /* 13Mhz */ - RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL, - RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_13_VAL, - MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL, - SDRC_RFR_CTRL_BYPASS, - RATE_IN_243X}, - - /* PRCM-boot/bypass */ - {S12M, S12M, S12M, RB_CM_CLKSEL_MPU_VAL, /* 12Mhz */ - RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL, - RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_12_VAL, - MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL, - SDRC_RFR_CTRL_BYPASS, - RATE_IN_243X}, - - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -}; - /*------------------------------------------------------------------------- * 24xx clock tree. * @@ -708,7 +129,7 @@ static struct clk dpll_ck = { static struct clk apll96_ck = { .name = "apll96_ck", - .ops = &clkops_fixed, + .ops = &clkops_apll96, .parent = &sys_ck, .rate = 96000000, .flags = RATE_FIXED | ENABLE_ON_INIT, @@ -719,7 +140,7 @@ static struct clk apll96_ck = { static struct clk apll54_ck = { .name = "apll54_ck", - .ops = &clkops_fixed, + .ops = &clkops_apll54, .parent = &sys_ck, .rate = 54000000, .flags = RATE_FIXED | ENABLE_ON_INIT, @@ -2653,5 +2074,236 @@ static struct clk virt_prcm_set = { .round_rate = &omap2_round_to_table_rate, }; -#endif + +/* + * clkdev integration + */ + +static struct omap_clk omap24xx_clks[] = { + /* external root sources */ + CLK(NULL, "func_32k_ck", &func_32k_ck, CK_243X | CK_242X), + CLK(NULL, "secure_32k_ck", &secure_32k_ck, CK_243X | CK_242X), + CLK(NULL, "osc_ck", &osc_ck, CK_243X | CK_242X), + CLK(NULL, "sys_ck", &sys_ck, CK_243X | CK_242X), + CLK(NULL, "alt_ck", &alt_ck, CK_243X | CK_242X), + /* internal analog sources */ + CLK(NULL, "dpll_ck", &dpll_ck, CK_243X | CK_242X), + CLK(NULL, "apll96_ck", &apll96_ck, CK_243X | CK_242X), + CLK(NULL, "apll54_ck", &apll54_ck, CK_243X | CK_242X), + /* internal prcm root sources */ + CLK(NULL, "func_54m_ck", &func_54m_ck, CK_243X | CK_242X), + CLK(NULL, "core_ck", &core_ck, CK_243X | CK_242X), + CLK(NULL, "func_96m_ck", &func_96m_ck, CK_243X | CK_242X), + CLK(NULL, "func_48m_ck", &func_48m_ck, CK_243X | CK_242X), + CLK(NULL, "func_12m_ck", &func_12m_ck, CK_243X | CK_242X), + CLK(NULL, "ck_wdt1_osc", &wdt1_osc_ck, CK_243X | CK_242X), + CLK(NULL, "sys_clkout_src", &sys_clkout_src, CK_243X | CK_242X), + CLK(NULL, "sys_clkout", &sys_clkout, CK_243X | CK_242X), + CLK(NULL, "sys_clkout2_src", &sys_clkout2_src, CK_242X), + CLK(NULL, "sys_clkout2", &sys_clkout2, CK_242X), + CLK(NULL, "emul_ck", &emul_ck, CK_242X), + /* mpu domain clocks */ + CLK(NULL, "mpu_ck", &mpu_ck, CK_243X | CK_242X), + /* dsp domain clocks */ + CLK(NULL, "dsp_fck", &dsp_fck, CK_243X | CK_242X), + CLK(NULL, "dsp_irate_ick", &dsp_irate_ick, CK_243X | CK_242X), + CLK(NULL, "dsp_ick", &dsp_ick, CK_242X), + CLK(NULL, "iva2_1_ick", &iva2_1_ick, CK_243X), + CLK(NULL, "iva1_ifck", &iva1_ifck, CK_242X), + CLK(NULL, "iva1_mpu_int_ifck", &iva1_mpu_int_ifck, CK_242X), + /* GFX domain clocks */ + CLK(NULL, "gfx_3d_fck", &gfx_3d_fck, CK_243X | CK_242X), + CLK(NULL, "gfx_2d_fck", &gfx_2d_fck, CK_243X | CK_242X), + CLK(NULL, "gfx_ick", &gfx_ick, CK_243X | CK_242X), + /* Modem domain clocks */ + CLK(NULL, "mdm_ick", &mdm_ick, CK_243X), + CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X), + /* DSS domain clocks */ + CLK("omapdss", "ick", &dss_ick, CK_243X | CK_242X), + CLK("omapdss", "dss1_fck", &dss1_fck, CK_243X | CK_242X), + CLK("omapdss", "dss2_fck", &dss2_fck, CK_243X | CK_242X), + CLK("omapdss", "tv_fck", &dss_54m_fck, CK_243X | CK_242X), + /* L3 domain clocks */ + CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X | CK_242X), + CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X | CK_242X), + CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_243X | CK_242X), + /* L4 domain clocks */ + CLK(NULL, "l4_ck", &l4_ck, CK_243X | CK_242X), + CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_243X | CK_242X), + /* virtual meta-group clock */ + CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_243X | CK_242X), + /* general l4 interface ck, multi-parent functional clk */ + CLK(NULL, "gpt1_ick", &gpt1_ick, CK_243X | CK_242X), + CLK(NULL, "gpt1_fck", &gpt1_fck, CK_243X | CK_242X), + CLK(NULL, "gpt2_ick", &gpt2_ick, CK_243X | CK_242X), + CLK(NULL, "gpt2_fck", &gpt2_fck, CK_243X | CK_242X), + CLK(NULL, "gpt3_ick", &gpt3_ick, CK_243X | CK_242X), + CLK(NULL, "gpt3_fck", &gpt3_fck, CK_243X | CK_242X), + CLK(NULL, "gpt4_ick", &gpt4_ick, CK_243X | CK_242X), + CLK(NULL, "gpt4_fck", &gpt4_fck, CK_243X | CK_242X), + CLK(NULL, "gpt5_ick", &gpt5_ick, CK_243X | CK_242X), + CLK(NULL, "gpt5_fck", &gpt5_fck, CK_243X | CK_242X), + CLK(NULL, "gpt6_ick", &gpt6_ick, CK_243X | CK_242X), + CLK(NULL, "gpt6_fck", &gpt6_fck, CK_243X | CK_242X), + CLK(NULL, "gpt7_ick", &gpt7_ick, CK_243X | CK_242X), + CLK(NULL, "gpt7_fck", &gpt7_fck, CK_243X | CK_242X), + CLK(NULL, "gpt8_ick", &gpt8_ick, CK_243X | CK_242X), + CLK(NULL, "gpt8_fck", &gpt8_fck, CK_243X | CK_242X), + CLK(NULL, "gpt9_ick", &gpt9_ick, CK_243X | CK_242X), + CLK(NULL, "gpt9_fck", &gpt9_fck, CK_243X | CK_242X), + CLK(NULL, "gpt10_ick", &gpt10_ick, CK_243X | CK_242X), + CLK(NULL, "gpt10_fck", &gpt10_fck, CK_243X | CK_242X), + CLK(NULL, "gpt11_ick", &gpt11_ick, CK_243X | CK_242X), + CLK(NULL, "gpt11_fck", &gpt11_fck, CK_243X | CK_242X), + CLK(NULL, "gpt12_ick", &gpt12_ick, CK_243X | CK_242X), + CLK(NULL, "gpt12_fck", &gpt12_fck, CK_243X | CK_242X), + CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_243X | CK_242X), + CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_243X | CK_242X), + CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_243X | CK_242X), + CLK("omap-mcbsp.2", "fck", &mcbsp2_fck, CK_243X | CK_242X), + CLK("omap-mcbsp.3", "ick", &mcbsp3_ick, CK_243X), + CLK("omap-mcbsp.3", "fck", &mcbsp3_fck, CK_243X), + CLK("omap-mcbsp.4", "ick", &mcbsp4_ick, CK_243X), + CLK("omap-mcbsp.4", "fck", &mcbsp4_fck, CK_243X), + CLK("omap-mcbsp.5", "ick", &mcbsp5_ick, CK_243X), + CLK("omap-mcbsp.5", "fck", &mcbsp5_fck, CK_243X), + CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_243X | CK_242X), + CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_243X | CK_242X), + CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_243X | CK_242X), + CLK("omap2_mcspi.2", "fck", &mcspi2_fck, CK_243X | CK_242X), + CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_243X), + CLK("omap2_mcspi.3", "fck", &mcspi3_fck, CK_243X), + CLK(NULL, "uart1_ick", &uart1_ick, CK_243X | CK_242X), + CLK(NULL, "uart1_fck", &uart1_fck, CK_243X | CK_242X), + CLK(NULL, "uart2_ick", &uart2_ick, CK_243X | CK_242X), + CLK(NULL, "uart2_fck", &uart2_fck, CK_243X | CK_242X), + CLK(NULL, "uart3_ick", &uart3_ick, CK_243X | CK_242X), + CLK(NULL, "uart3_fck", &uart3_fck, CK_243X | CK_242X), + CLK(NULL, "gpios_ick", &gpios_ick, CK_243X | CK_242X), + CLK(NULL, "gpios_fck", &gpios_fck, CK_243X | CK_242X), + CLK("omap_wdt", "ick", &mpu_wdt_ick, CK_243X | CK_242X), + CLK("omap_wdt", "fck", &mpu_wdt_fck, CK_243X | CK_242X), + CLK(NULL, "sync_32k_ick", &sync_32k_ick, CK_243X | CK_242X), + CLK(NULL, "wdt1_ick", &wdt1_ick, CK_243X | CK_242X), + CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_243X | CK_242X), + CLK(NULL, "icr_ick", &icr_ick, CK_243X), + CLK("omap24xxcam", "fck", &cam_fck, CK_243X | CK_242X), + CLK("omap24xxcam", "ick", &cam_ick, CK_243X | CK_242X), + CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_243X | CK_242X), + CLK(NULL, "wdt4_ick", &wdt4_ick, CK_243X | CK_242X), + CLK(NULL, "wdt4_fck", &wdt4_fck, CK_243X | CK_242X), + CLK(NULL, "wdt3_ick", &wdt3_ick, CK_242X), + CLK(NULL, "wdt3_fck", &wdt3_fck, CK_242X), + CLK(NULL, "mspro_ick", &mspro_ick, CK_243X | CK_242X), + CLK(NULL, "mspro_fck", &mspro_fck, CK_243X | CK_242X), + CLK("mmci-omap.0", "ick", &mmc_ick, CK_242X), + CLK("mmci-omap.0", "fck", &mmc_fck, CK_242X), + CLK(NULL, "fac_ick", &fac_ick, CK_243X | CK_242X), + CLK(NULL, "fac_fck", &fac_fck, CK_243X | CK_242X), + CLK(NULL, "eac_ick", &eac_ick, CK_242X), + CLK(NULL, "eac_fck", &eac_fck, CK_242X), + CLK("omap_hdq.0", "ick", &hdq_ick, CK_243X | CK_242X), + CLK("omap_hdq.1", "fck", &hdq_fck, CK_243X | CK_242X), + CLK("i2c_omap.1", "ick", &i2c1_ick, CK_243X | CK_242X), + CLK("i2c_omap.1", "fck", &i2c1_fck, CK_242X), + CLK("i2c_omap.1", "fck", &i2chs1_fck, CK_243X), + CLK("i2c_omap.2", "ick", &i2c2_ick, CK_243X | CK_242X), + CLK("i2c_omap.2", "fck", &i2c2_fck, CK_242X), + CLK("i2c_omap.2", "fck", &i2chs2_fck, CK_243X), + CLK(NULL, "gpmc_fck", &gpmc_fck, CK_243X | CK_242X), + CLK(NULL, "sdma_fck", &sdma_fck, CK_243X | CK_242X), + CLK(NULL, "sdma_ick", &sdma_ick, CK_243X | CK_242X), + CLK(NULL, "vlynq_ick", &vlynq_ick, CK_242X), + CLK(NULL, "vlynq_fck", &vlynq_fck, CK_242X), + CLK(NULL, "sdrc_ick", &sdrc_ick, CK_243X), + CLK(NULL, "des_ick", &des_ick, CK_243X | CK_242X), + CLK(NULL, "sha_ick", &sha_ick, CK_243X | CK_242X), + CLK("omap_rng", "ick", &rng_ick, CK_243X | CK_242X), + CLK(NULL, "aes_ick", &aes_ick, CK_243X | CK_242X), + CLK(NULL, "pka_ick", &pka_ick, CK_243X | CK_242X), + CLK(NULL, "usb_fck", &usb_fck, CK_243X | CK_242X), + CLK("musb_hdrc", "ick", &usbhs_ick, CK_243X), + CLK("mmci-omap-hs.0", "ick", &mmchs1_ick, CK_243X), + CLK("mmci-omap-hs.0", "fck", &mmchs1_fck, CK_243X), + CLK("mmci-omap-hs.1", "ick", &mmchs2_ick, CK_243X), + CLK("mmci-omap-hs.1", "fck", &mmchs2_fck, CK_243X), + CLK(NULL, "gpio5_ick", &gpio5_ick, CK_243X), + CLK(NULL, "gpio5_fck", &gpio5_fck, CK_243X), + CLK(NULL, "mdm_intc_ick", &mdm_intc_ick, CK_243X), + CLK("mmci-omap-hs.0", "mmchsdb_fck", &mmchsdb1_fck, CK_243X), + CLK("mmci-omap-hs.1", "mmchsdb_fck", &mmchsdb2_fck, CK_243X), +}; + +/* + * init code + */ + +int __init omap2_clk_init(void) +{ + const struct prcm_config *prcm; + struct omap_clk *c; + u32 clkrate; + u16 cpu_clkflg; + + if (cpu_is_omap242x()) { + prcm_clksrc_ctrl = OMAP2420_PRCM_CLKSRC_CTRL; + cpu_mask = RATE_IN_242X; + cpu_clkflg = CK_242X; + rate_table = omap2420_rate_table; + } else if (cpu_is_omap2430()) { + prcm_clksrc_ctrl = OMAP2430_PRCM_CLKSRC_CTRL; + cpu_mask = RATE_IN_243X; + cpu_clkflg = CK_243X; + rate_table = omap2430_rate_table; + } + + clk_init(&omap2_clk_functions); + + for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++) + clk_preinit(c->lk.clk); + + osc_ck.rate = omap2_osc_clk_recalc(&osc_ck); + propagate_rate(&osc_ck); + sys_ck.rate = omap2_sys_clk_recalc(&sys_ck); + propagate_rate(&sys_ck); + + for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++) + if (c->cpu & cpu_clkflg) { + clkdev_add(&c->lk); + clk_register(c->lk.clk); + omap2_init_clk_clkdm(c->lk.clk); + } + + /* Check the MPU rate set by bootloader */ + clkrate = omap2xxx_clk_get_core_rate(&dpll_ck); + for (prcm = rate_table; prcm->mpu_speed; prcm++) { + if (!(prcm->flags & cpu_mask)) + continue; + if (prcm->xtal_speed != sys_ck.rate) + continue; + if (prcm->dpll_speed <= clkrate) + break; + } + curr_prcm_set = prcm; + + recalculate_root_clocks(); + + printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): " + "%ld.%01ld/%ld/%ld MHz\n", + (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10, + (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ; + + /* + * Only enable those clocks we will need, let the drivers + * enable other clocks as necessary + */ + clk_enable_init_clocks(); + + /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */ + vclk = clk_get(NULL, "virt_prcm_set"); + sclk = clk_get(NULL, "sys_ck"); + dclk = clk_get(NULL, "dpll_ck"); + + return 0; +} diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 9f2feaf798658933951a723232a005466e6599bc..ded32364f32b0cfe270873252a4e4702409ed828 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -30,314 +30,21 @@ #include #include #include +#include #include #include #include #include "clock.h" +#include "clock34xx.h" +#include "sdrc.h" #include "prm.h" #include "prm-regbits-34xx.h" #include "cm.h" #include "cm-regbits-34xx.h" -static const struct clkops clkops_noncore_dpll_ops; - -static void omap3430es2_clk_ssi_find_idlest(struct clk *clk, - void __iomem **idlest_reg, - u8 *idlest_bit); -static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk, - void __iomem **idlest_reg, - u8 *idlest_bit); -static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk, - void __iomem **idlest_reg, - u8 *idlest_bit); - -static const struct clkops clkops_omap3430es2_ssi_wait = { - .enable = omap2_dflt_clk_enable, - .disable = omap2_dflt_clk_disable, - .find_idlest = omap3430es2_clk_ssi_find_idlest, - .find_companion = omap2_clk_dflt_find_companion, -}; - -static const struct clkops clkops_omap3430es2_hsotgusb_wait = { - .enable = omap2_dflt_clk_enable, - .disable = omap2_dflt_clk_disable, - .find_idlest = omap3430es2_clk_hsotgusb_find_idlest, - .find_companion = omap2_clk_dflt_find_companion, -}; - -static const struct clkops clkops_omap3430es2_dss_usbhost_wait = { - .enable = omap2_dflt_clk_enable, - .disable = omap2_dflt_clk_disable, - .find_idlest = omap3430es2_clk_dss_usbhost_find_idlest, - .find_companion = omap2_clk_dflt_find_companion, -}; - -#include "clock34xx.h" - -struct omap_clk { - u32 cpu; - struct clk_lookup lk; -}; - -#define CLK(dev, con, ck, cp) \ - { \ - .cpu = cp, \ - .lk = { \ - .dev_id = dev, \ - .con_id = con, \ - .clk = ck, \ - }, \ - } - -#define CK_343X (1 << 0) -#define CK_3430ES1 (1 << 1) -#define CK_3430ES2 (1 << 2) - -static struct omap_clk omap34xx_clks[] = { - CLK(NULL, "omap_32k_fck", &omap_32k_fck, CK_343X), - CLK(NULL, "virt_12m_ck", &virt_12m_ck, CK_343X), - CLK(NULL, "virt_13m_ck", &virt_13m_ck, CK_343X), - CLK(NULL, "virt_16_8m_ck", &virt_16_8m_ck, CK_3430ES2), - CLK(NULL, "virt_19_2m_ck", &virt_19_2m_ck, CK_343X), - CLK(NULL, "virt_26m_ck", &virt_26m_ck, CK_343X), - CLK(NULL, "virt_38_4m_ck", &virt_38_4m_ck, CK_343X), - CLK(NULL, "osc_sys_ck", &osc_sys_ck, CK_343X), - CLK(NULL, "sys_ck", &sys_ck, CK_343X), - CLK(NULL, "sys_altclk", &sys_altclk, CK_343X), - CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_343X), - CLK(NULL, "sys_clkout1", &sys_clkout1, CK_343X), - CLK(NULL, "dpll1_ck", &dpll1_ck, CK_343X), - CLK(NULL, "dpll1_x2_ck", &dpll1_x2_ck, CK_343X), - CLK(NULL, "dpll1_x2m2_ck", &dpll1_x2m2_ck, CK_343X), - CLK(NULL, "dpll2_ck", &dpll2_ck, CK_343X), - CLK(NULL, "dpll2_m2_ck", &dpll2_m2_ck, CK_343X), - CLK(NULL, "dpll3_ck", &dpll3_ck, CK_343X), - CLK(NULL, "core_ck", &core_ck, CK_343X), - CLK(NULL, "dpll3_x2_ck", &dpll3_x2_ck, CK_343X), - CLK(NULL, "dpll3_m2_ck", &dpll3_m2_ck, CK_343X), - CLK(NULL, "dpll3_m2x2_ck", &dpll3_m2x2_ck, CK_343X), - CLK(NULL, "dpll3_m3_ck", &dpll3_m3_ck, CK_343X), - CLK(NULL, "dpll3_m3x2_ck", &dpll3_m3x2_ck, CK_343X), - CLK("etb", "emu_core_alwon_ck", &emu_core_alwon_ck, CK_343X), - CLK(NULL, "dpll4_ck", &dpll4_ck, CK_343X), - CLK(NULL, "dpll4_x2_ck", &dpll4_x2_ck, CK_343X), - CLK(NULL, "omap_96m_alwon_fck", &omap_96m_alwon_fck, CK_343X), - CLK(NULL, "omap_96m_fck", &omap_96m_fck, CK_343X), - CLK(NULL, "cm_96m_fck", &cm_96m_fck, CK_343X), - CLK(NULL, "omap_54m_fck", &omap_54m_fck, CK_343X), - CLK(NULL, "omap_48m_fck", &omap_48m_fck, CK_343X), - CLK(NULL, "omap_12m_fck", &omap_12m_fck, CK_343X), - CLK(NULL, "dpll4_m2_ck", &dpll4_m2_ck, CK_343X), - CLK(NULL, "dpll4_m2x2_ck", &dpll4_m2x2_ck, CK_343X), - CLK(NULL, "dpll4_m3_ck", &dpll4_m3_ck, CK_343X), - CLK(NULL, "dpll4_m3x2_ck", &dpll4_m3x2_ck, CK_343X), - CLK(NULL, "dpll4_m4_ck", &dpll4_m4_ck, CK_343X), - CLK(NULL, "dpll4_m4x2_ck", &dpll4_m4x2_ck, CK_343X), - CLK(NULL, "dpll4_m5_ck", &dpll4_m5_ck, CK_343X), - CLK(NULL, "dpll4_m5x2_ck", &dpll4_m5x2_ck, CK_343X), - CLK(NULL, "dpll4_m6_ck", &dpll4_m6_ck, CK_343X), - CLK(NULL, "dpll4_m6x2_ck", &dpll4_m6x2_ck, CK_343X), - CLK("etb", "emu_per_alwon_ck", &emu_per_alwon_ck, CK_343X), - CLK(NULL, "dpll5_ck", &dpll5_ck, CK_3430ES2), - CLK(NULL, "dpll5_m2_ck", &dpll5_m2_ck, CK_3430ES2), - CLK(NULL, "clkout2_src_ck", &clkout2_src_ck, CK_343X), - CLK(NULL, "sys_clkout2", &sys_clkout2, CK_343X), - CLK(NULL, "corex2_fck", &corex2_fck, CK_343X), - CLK(NULL, "dpll1_fck", &dpll1_fck, CK_343X), - CLK(NULL, "mpu_ck", &mpu_ck, CK_343X), - CLK(NULL, "arm_fck", &arm_fck, CK_343X), - CLK("etb", "emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_343X), - CLK(NULL, "dpll2_fck", &dpll2_fck, CK_343X), - CLK(NULL, "iva2_ck", &iva2_ck, CK_343X), - CLK(NULL, "l3_ick", &l3_ick, CK_343X), - CLK(NULL, "l4_ick", &l4_ick, CK_343X), - CLK(NULL, "rm_ick", &rm_ick, CK_343X), - CLK(NULL, "gfx_l3_ck", &gfx_l3_ck, CK_3430ES1), - CLK(NULL, "gfx_l3_fck", &gfx_l3_fck, CK_3430ES1), - CLK(NULL, "gfx_l3_ick", &gfx_l3_ick, CK_3430ES1), - CLK(NULL, "gfx_cg1_ck", &gfx_cg1_ck, CK_3430ES1), - CLK(NULL, "gfx_cg2_ck", &gfx_cg2_ck, CK_3430ES1), - CLK(NULL, "sgx_fck", &sgx_fck, CK_3430ES2), - CLK(NULL, "sgx_ick", &sgx_ick, CK_3430ES2), - CLK(NULL, "d2d_26m_fck", &d2d_26m_fck, CK_3430ES1), - CLK(NULL, "modem_fck", &modem_fck, CK_343X), - CLK(NULL, "sad2d_ick", &sad2d_ick, CK_343X), - CLK(NULL, "mad2d_ick", &mad2d_ick, CK_343X), - CLK(NULL, "gpt10_fck", &gpt10_fck, CK_343X), - CLK(NULL, "gpt11_fck", &gpt11_fck, CK_343X), - CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2), - CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2), - CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2), - CLK(NULL, "core_96m_fck", &core_96m_fck, CK_343X), - CLK("mmci-omap-hs.2", "fck", &mmchs3_fck, CK_3430ES2), - CLK("mmci-omap-hs.1", "fck", &mmchs2_fck, CK_343X), - CLK(NULL, "mspro_fck", &mspro_fck, CK_343X), - CLK("mmci-omap-hs.0", "fck", &mmchs1_fck, CK_343X), - CLK("i2c_omap.3", "fck", &i2c3_fck, CK_343X), - CLK("i2c_omap.2", "fck", &i2c2_fck, CK_343X), - CLK("i2c_omap.1", "fck", &i2c1_fck, CK_343X), - CLK("omap-mcbsp.5", "fck", &mcbsp5_fck, CK_343X), - CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_343X), - CLK(NULL, "core_48m_fck", &core_48m_fck, CK_343X), - CLK("omap2_mcspi.4", "fck", &mcspi4_fck, CK_343X), - CLK("omap2_mcspi.3", "fck", &mcspi3_fck, CK_343X), - CLK("omap2_mcspi.2", "fck", &mcspi2_fck, CK_343X), - CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_343X), - CLK(NULL, "uart2_fck", &uart2_fck, CK_343X), - CLK(NULL, "uart1_fck", &uart1_fck, CK_343X), - CLK(NULL, "fshostusb_fck", &fshostusb_fck, CK_3430ES1), - CLK(NULL, "core_12m_fck", &core_12m_fck, CK_343X), - CLK("omap_hdq.0", "fck", &hdq_fck, CK_343X), - CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es1, CK_3430ES1), - CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es2, CK_3430ES2), - CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es1, CK_3430ES1), - CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es2, CK_3430ES2), - CLK(NULL, "core_l3_ick", &core_l3_ick, CK_343X), - CLK("musb_hdrc", "ick", &hsotgusb_ick_3430es1, CK_3430ES1), - CLK("musb_hdrc", "ick", &hsotgusb_ick_3430es2, CK_3430ES2), - CLK(NULL, "sdrc_ick", &sdrc_ick, CK_343X), - CLK(NULL, "gpmc_fck", &gpmc_fck, CK_343X), - CLK(NULL, "security_l3_ick", &security_l3_ick, CK_343X), - CLK(NULL, "pka_ick", &pka_ick, CK_343X), - CLK(NULL, "core_l4_ick", &core_l4_ick, CK_343X), - CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2), - CLK("mmci-omap-hs.2", "ick", &mmchs3_ick, CK_3430ES2), - CLK(NULL, "icr_ick", &icr_ick, CK_343X), - CLK(NULL, "aes2_ick", &aes2_ick, CK_343X), - CLK(NULL, "sha12_ick", &sha12_ick, CK_343X), - CLK(NULL, "des2_ick", &des2_ick, CK_343X), - CLK("mmci-omap-hs.1", "ick", &mmchs2_ick, CK_343X), - CLK("mmci-omap-hs.0", "ick", &mmchs1_ick, CK_343X), - CLK(NULL, "mspro_ick", &mspro_ick, CK_343X), - CLK("omap_hdq.0", "ick", &hdq_ick, CK_343X), - CLK("omap2_mcspi.4", "ick", &mcspi4_ick, CK_343X), - CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_343X), - CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_343X), - CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_343X), - CLK("i2c_omap.3", "ick", &i2c3_ick, CK_343X), - CLK("i2c_omap.2", "ick", &i2c2_ick, CK_343X), - CLK("i2c_omap.1", "ick", &i2c1_ick, CK_343X), - CLK(NULL, "uart2_ick", &uart2_ick, CK_343X), - CLK(NULL, "uart1_ick", &uart1_ick, CK_343X), - CLK(NULL, "gpt11_ick", &gpt11_ick, CK_343X), - CLK(NULL, "gpt10_ick", &gpt10_ick, CK_343X), - CLK("omap-mcbsp.5", "ick", &mcbsp5_ick, CK_343X), - CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_343X), - CLK(NULL, "fac_ick", &fac_ick, CK_3430ES1), - CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_343X), - CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_343X), - CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_343X), - CLK(NULL, "ssi_ick", &ssi_ick_3430es1, CK_3430ES1), - CLK(NULL, "ssi_ick", &ssi_ick_3430es2, CK_3430ES2), - CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_3430ES1), - CLK(NULL, "security_l4_ick2", &security_l4_ick2, CK_343X), - CLK(NULL, "aes1_ick", &aes1_ick, CK_343X), - CLK("omap_rng", "ick", &rng_ick, CK_343X), - CLK(NULL, "sha11_ick", &sha11_ick, CK_343X), - CLK(NULL, "des1_ick", &des1_ick, CK_343X), - CLK("omapfb", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1), - CLK("omapfb", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2), - CLK("omapfb", "tv_fck", &dss_tv_fck, CK_343X), - CLK("omapfb", "video_fck", &dss_96m_fck, CK_343X), - CLK("omapfb", "dss2_fck", &dss2_alwon_fck, CK_343X), - CLK("omapfb", "ick", &dss_ick_3430es1, CK_3430ES1), - CLK("omapfb", "ick", &dss_ick_3430es2, CK_3430ES2), - CLK(NULL, "cam_mclk", &cam_mclk, CK_343X), - CLK(NULL, "cam_ick", &cam_ick, CK_343X), - CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_343X), - CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2), - CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2), - CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2), - CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2), - CLK(NULL, "gpt1_fck", &gpt1_fck, CK_343X), - CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_343X), - CLK(NULL, "gpio1_dbck", &gpio1_dbck, CK_343X), - CLK("omap_wdt", "fck", &wdt2_fck, CK_343X), - CLK(NULL, "wkup_l4_ick", &wkup_l4_ick, CK_343X), - CLK(NULL, "usim_ick", &usim_ick, CK_3430ES2), - CLK("omap_wdt", "ick", &wdt2_ick, CK_343X), - CLK(NULL, "wdt1_ick", &wdt1_ick, CK_343X), - CLK(NULL, "gpio1_ick", &gpio1_ick, CK_343X), - CLK(NULL, "omap_32ksync_ick", &omap_32ksync_ick, CK_343X), - CLK(NULL, "gpt12_ick", &gpt12_ick, CK_343X), - CLK(NULL, "gpt1_ick", &gpt1_ick, CK_343X), - CLK(NULL, "per_96m_fck", &per_96m_fck, CK_343X), - CLK(NULL, "per_48m_fck", &per_48m_fck, CK_343X), - CLK(NULL, "uart3_fck", &uart3_fck, CK_343X), - CLK(NULL, "gpt2_fck", &gpt2_fck, CK_343X), - CLK(NULL, "gpt3_fck", &gpt3_fck, CK_343X), - CLK(NULL, "gpt4_fck", &gpt4_fck, CK_343X), - CLK(NULL, "gpt5_fck", &gpt5_fck, CK_343X), - CLK(NULL, "gpt6_fck", &gpt6_fck, CK_343X), - CLK(NULL, "gpt7_fck", &gpt7_fck, CK_343X), - CLK(NULL, "gpt8_fck", &gpt8_fck, CK_343X), - CLK(NULL, "gpt9_fck", &gpt9_fck, CK_343X), - CLK(NULL, "per_32k_alwon_fck", &per_32k_alwon_fck, CK_343X), - CLK(NULL, "gpio6_dbck", &gpio6_dbck, CK_343X), - CLK(NULL, "gpio5_dbck", &gpio5_dbck, CK_343X), - CLK(NULL, "gpio4_dbck", &gpio4_dbck, CK_343X), - CLK(NULL, "gpio3_dbck", &gpio3_dbck, CK_343X), - CLK(NULL, "gpio2_dbck", &gpio2_dbck, CK_343X), - CLK(NULL, "wdt3_fck", &wdt3_fck, CK_343X), - CLK(NULL, "per_l4_ick", &per_l4_ick, CK_343X), - CLK(NULL, "gpio6_ick", &gpio6_ick, CK_343X), - CLK(NULL, "gpio5_ick", &gpio5_ick, CK_343X), - CLK(NULL, "gpio4_ick", &gpio4_ick, CK_343X), - CLK(NULL, "gpio3_ick", &gpio3_ick, CK_343X), - CLK(NULL, "gpio2_ick", &gpio2_ick, CK_343X), - CLK(NULL, "wdt3_ick", &wdt3_ick, CK_343X), - CLK(NULL, "uart3_ick", &uart3_ick, CK_343X), - CLK(NULL, "gpt9_ick", &gpt9_ick, CK_343X), - CLK(NULL, "gpt8_ick", &gpt8_ick, CK_343X), - CLK(NULL, "gpt7_ick", &gpt7_ick, CK_343X), - CLK(NULL, "gpt6_ick", &gpt6_ick, CK_343X), - CLK(NULL, "gpt5_ick", &gpt5_ick, CK_343X), - CLK(NULL, "gpt4_ick", &gpt4_ick, CK_343X), - CLK(NULL, "gpt3_ick", &gpt3_ick, CK_343X), - CLK(NULL, "gpt2_ick", &gpt2_ick, CK_343X), - CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_343X), - CLK("omap-mcbsp.3", "ick", &mcbsp3_ick, CK_343X), - CLK("omap-mcbsp.4", "ick", &mcbsp4_ick, CK_343X), - CLK("omap-mcbsp.2", "fck", &mcbsp2_fck, CK_343X), - CLK("omap-mcbsp.3", "fck", &mcbsp3_fck, CK_343X), - CLK("omap-mcbsp.4", "fck", &mcbsp4_fck, CK_343X), - CLK("etb", "emu_src_ck", &emu_src_ck, CK_343X), - CLK(NULL, "pclk_fck", &pclk_fck, CK_343X), - CLK(NULL, "pclkx2_fck", &pclkx2_fck, CK_343X), - CLK(NULL, "atclk_fck", &atclk_fck, CK_343X), - CLK(NULL, "traceclk_src_fck", &traceclk_src_fck, CK_343X), - CLK(NULL, "traceclk_fck", &traceclk_fck, CK_343X), - CLK(NULL, "sr1_fck", &sr1_fck, CK_343X), - CLK(NULL, "sr2_fck", &sr2_fck, CK_343X), - CLK(NULL, "sr_l4_ick", &sr_l4_ick, CK_343X), - CLK(NULL, "secure_32k_fck", &secure_32k_fck, CK_343X), - CLK(NULL, "gpt12_fck", &gpt12_fck, CK_343X), - CLK(NULL, "wdt1_fck", &wdt1_fck, CK_343X), -}; - -/* CM_AUTOIDLE_PLL*.AUTO_* bit values */ -#define DPLL_AUTOIDLE_DISABLE 0x0 -#define DPLL_AUTOIDLE_LOW_POWER_STOP 0x1 - -#define MAX_DPLL_WAIT_TRIES 1000000 - -#define MIN_SDRC_DLL_LOCK_FREQ 83000000 - #define CYCLES_PER_MHZ 1000000 -/* Scale factor for fixed-point arith in omap3_core_dpll_m2_set_rate() */ -#define SDRC_MPURATE_SCALE 8 - -/* 2^SDRC_MPURATE_BASE_SHIFT: MPU MHz that SDRC_MPURATE_LOOPS is defined for */ -#define SDRC_MPURATE_BASE_SHIFT 9 - -/* - * SDRC_MPURATE_LOOPS: Number of MPU loops to execute at - * 2^MPURATE_BASE_SHIFT MHz for SDRC to stabilize - */ -#define SDRC_MPURATE_LOOPS 96 - /* * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks * that are sourced by DPLL5, and both of these require this clock @@ -345,6 +52,9 @@ static struct omap_clk omap34xx_clks[] = { */ #define DPLL5_FREQ_FOR_USBHOST 120000000 +/* needed by omap3_core_dpll_m2_set_rate() */ +struct clk *sdrc_ick_p, *arm_fck_p; + /** * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI * @clk: struct clk * being enabled @@ -366,6 +76,13 @@ static void omap3430es2_clk_ssi_find_idlest(struct clk *clk, *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT; } +const struct clkops clkops_omap3430es2_ssi_wait = { + .enable = omap2_dflt_clk_enable, + .disable = omap2_dflt_clk_disable, + .find_idlest = omap3430es2_clk_ssi_find_idlest, + .find_companion = omap2_clk_dflt_find_companion, +}; + /** * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST * @clk: struct clk * being enabled @@ -391,6 +108,13 @@ static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk, *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT; } +const struct clkops clkops_omap3430es2_dss_usbhost_wait = { + .enable = omap2_dflt_clk_enable, + .disable = omap2_dflt_clk_disable, + .find_idlest = omap3430es2_clk_dss_usbhost_find_idlest, + .find_companion = omap2_clk_dflt_find_companion, +}; + /** * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB * @clk: struct clk * being enabled @@ -412,395 +136,19 @@ static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk, *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT; } -/** - * omap3_dpll_recalc - recalculate DPLL rate - * @clk: DPLL struct clk - * - * Recalculate and propagate the DPLL rate. - */ -static unsigned long omap3_dpll_recalc(struct clk *clk) -{ - return omap2_get_dpll_rate(clk); -} - -/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */ -static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits) -{ - const struct dpll_data *dd; - u32 v; - - dd = clk->dpll_data; - - v = __raw_readl(dd->control_reg); - v &= ~dd->enable_mask; - v |= clken_bits << __ffs(dd->enable_mask); - __raw_writel(v, dd->control_reg); -} - -/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */ -static int _omap3_wait_dpll_status(struct clk *clk, u8 state) -{ - const struct dpll_data *dd; - int i = 0; - int ret = -EINVAL; - - dd = clk->dpll_data; - - state <<= __ffs(dd->idlest_mask); - - while (((__raw_readl(dd->idlest_reg) & dd->idlest_mask) != state) && - i < MAX_DPLL_WAIT_TRIES) { - i++; - udelay(1); - } - - if (i == MAX_DPLL_WAIT_TRIES) { - printk(KERN_ERR "clock: %s failed transition to '%s'\n", - clk->name, (state) ? "locked" : "bypassed"); - } else { - pr_debug("clock: %s transition to '%s' in %d loops\n", - clk->name, (state) ? "locked" : "bypassed", i); - - ret = 0; - } - - return ret; -} - -/* From 3430 TRM ES2 4.7.6.2 */ -static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n) -{ - unsigned long fint; - u16 f = 0; - - fint = clk->dpll_data->clk_ref->rate / n; - - pr_debug("clock: fint is %lu\n", fint); - - if (fint >= 750000 && fint <= 1000000) - f = 0x3; - else if (fint > 1000000 && fint <= 1250000) - f = 0x4; - else if (fint > 1250000 && fint <= 1500000) - f = 0x5; - else if (fint > 1500000 && fint <= 1750000) - f = 0x6; - else if (fint > 1750000 && fint <= 2100000) - f = 0x7; - else if (fint > 7500000 && fint <= 10000000) - f = 0xB; - else if (fint > 10000000 && fint <= 12500000) - f = 0xC; - else if (fint > 12500000 && fint <= 15000000) - f = 0xD; - else if (fint > 15000000 && fint <= 17500000) - f = 0xE; - else if (fint > 17500000 && fint <= 21000000) - f = 0xF; - else - pr_debug("clock: unknown freqsel setting for %d\n", n); - - return f; -} - -/* Non-CORE DPLL (e.g., DPLLs that do not control SDRC) clock functions */ - -/* - * _omap3_noncore_dpll_lock - instruct a DPLL to lock and wait for readiness - * @clk: pointer to a DPLL struct clk - * - * Instructs a non-CORE DPLL to lock. Waits for the DPLL to report - * readiness before returning. Will save and restore the DPLL's - * autoidle state across the enable, per the CDP code. If the DPLL - * locked successfully, return 0; if the DPLL did not lock in the time - * allotted, or DPLL3 was passed in, return -EINVAL. - */ -static int _omap3_noncore_dpll_lock(struct clk *clk) -{ - u8 ai; - int r; - - if (clk == &dpll3_ck) - return -EINVAL; - - pr_debug("clock: locking DPLL %s\n", clk->name); - - ai = omap3_dpll_autoidle_read(clk); - - omap3_dpll_deny_idle(clk); - - _omap3_dpll_write_clken(clk, DPLL_LOCKED); - - r = _omap3_wait_dpll_status(clk, 1); - - if (ai) - omap3_dpll_allow_idle(clk); - - return r; -} - -/* - * _omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness - * @clk: pointer to a DPLL struct clk - * - * Instructs a non-CORE DPLL to enter low-power bypass mode. In - * bypass mode, the DPLL's rate is set equal to its parent clock's - * rate. Waits for the DPLL to report readiness before returning. - * Will save and restore the DPLL's autoidle state across the enable, - * per the CDP code. If the DPLL entered bypass mode successfully, - * return 0; if the DPLL did not enter bypass in the time allotted, or - * DPLL3 was passed in, or the DPLL does not support low-power bypass, - * return -EINVAL. - */ -static int _omap3_noncore_dpll_bypass(struct clk *clk) -{ - int r; - u8 ai; - - if (clk == &dpll3_ck) - return -EINVAL; - - if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) - return -EINVAL; - - pr_debug("clock: configuring DPLL %s for low-power bypass\n", - clk->name); - - ai = omap3_dpll_autoidle_read(clk); - - _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_BYPASS); - - r = _omap3_wait_dpll_status(clk, 0); - - if (ai) - omap3_dpll_allow_idle(clk); - else - omap3_dpll_deny_idle(clk); - - return r; -} - -/* - * _omap3_noncore_dpll_stop - instruct a DPLL to stop - * @clk: pointer to a DPLL struct clk - * - * Instructs a non-CORE DPLL to enter low-power stop. Will save and - * restore the DPLL's autoidle state across the stop, per the CDP - * code. If DPLL3 was passed in, or the DPLL does not support - * low-power stop, return -EINVAL; otherwise, return 0. - */ -static int _omap3_noncore_dpll_stop(struct clk *clk) -{ - u8 ai; - - if (clk == &dpll3_ck) - return -EINVAL; - - if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP))) - return -EINVAL; - - pr_debug("clock: stopping DPLL %s\n", clk->name); - - ai = omap3_dpll_autoidle_read(clk); - - _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_STOP); - - if (ai) - omap3_dpll_allow_idle(clk); - else - omap3_dpll_deny_idle(clk); - - return 0; -} - -/** - * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode - * @clk: pointer to a DPLL struct clk - * - * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock. - * The choice of modes depends on the DPLL's programmed rate: if it is - * the same as the DPLL's parent clock, it will enter bypass; - * otherwise, it will enter lock. This code will wait for the DPLL to - * indicate readiness before returning, unless the DPLL takes too long - * to enter the target state. Intended to be used as the struct clk's - * enable function. If DPLL3 was passed in, or the DPLL does not - * support low-power stop, or if the DPLL took too long to enter - * bypass or lock, return -EINVAL; otherwise, return 0. - */ -static int omap3_noncore_dpll_enable(struct clk *clk) -{ - int r; - struct dpll_data *dd; - - if (clk == &dpll3_ck) - return -EINVAL; - - dd = clk->dpll_data; - if (!dd) - return -EINVAL; - - if (clk->rate == dd->clk_bypass->rate) { - WARN_ON(clk->parent != dd->clk_bypass); - r = _omap3_noncore_dpll_bypass(clk); - } else { - WARN_ON(clk->parent != dd->clk_ref); - r = _omap3_noncore_dpll_lock(clk); - } - /* FIXME: this is dubious - if clk->rate has changed, what about propagating? */ - if (!r) - clk->rate = omap2_get_dpll_rate(clk); - - return r; -} - -/** - * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode - * @clk: pointer to a DPLL struct clk - * - * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock. - * The choice of modes depends on the DPLL's programmed rate: if it is - * the same as the DPLL's parent clock, it will enter bypass; - * otherwise, it will enter lock. This code will wait for the DPLL to - * indicate readiness before returning, unless the DPLL takes too long - * to enter the target state. Intended to be used as the struct clk's - * enable function. If DPLL3 was passed in, or the DPLL does not - * support low-power stop, or if the DPLL took too long to enter - * bypass or lock, return -EINVAL; otherwise, return 0. - */ -static void omap3_noncore_dpll_disable(struct clk *clk) -{ - if (clk == &dpll3_ck) - return; - - _omap3_noncore_dpll_stop(clk); -} - - -/* Non-CORE DPLL rate set code */ - -/* - * omap3_noncore_dpll_program - set non-core DPLL M,N values directly - * @clk: struct clk * of DPLL to set - * @m: DPLL multiplier to set - * @n: DPLL divider to set - * @freqsel: FREQSEL value to set - * - * Program the DPLL with the supplied M, N values, and wait for the DPLL to - * lock.. Returns -EINVAL upon error, or 0 upon success. - */ -static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel) -{ - struct dpll_data *dd = clk->dpll_data; - u32 v; - - /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */ - _omap3_noncore_dpll_bypass(clk); - - /* Set jitter correction */ - v = __raw_readl(dd->control_reg); - v &= ~dd->freqsel_mask; - v |= freqsel << __ffs(dd->freqsel_mask); - __raw_writel(v, dd->control_reg); - - /* Set DPLL multiplier, divider */ - v = __raw_readl(dd->mult_div1_reg); - v &= ~(dd->mult_mask | dd->div1_mask); - v |= m << __ffs(dd->mult_mask); - v |= (n - 1) << __ffs(dd->div1_mask); - __raw_writel(v, dd->mult_div1_reg); - - /* We let the clock framework set the other output dividers later */ - - /* REVISIT: Set ramp-up delay? */ - - _omap3_noncore_dpll_lock(clk); - - return 0; -} - -/** - * omap3_noncore_dpll_set_rate - set non-core DPLL rate - * @clk: struct clk * of DPLL to set - * @rate: rounded target rate - * - * Set the DPLL CLKOUT to the target rate. If the DPLL can enter - * low-power bypass, and the target rate is the bypass source clock - * rate, then configure the DPLL for bypass. Otherwise, round the - * target rate if it hasn't been done already, then program and lock - * the DPLL. Returns -EINVAL upon error, or 0 upon success. - */ -static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate) -{ - struct clk *new_parent = NULL; - u16 freqsel; - struct dpll_data *dd; - int ret; - - if (!clk || !rate) - return -EINVAL; - - dd = clk->dpll_data; - if (!dd) - return -EINVAL; - - if (rate == omap2_get_dpll_rate(clk)) - return 0; - - /* - * Ensure both the bypass and ref clocks are enabled prior to - * doing anything; we need the bypass clock running to reprogram - * the DPLL. - */ - omap2_clk_enable(dd->clk_bypass); - omap2_clk_enable(dd->clk_ref); - - if (dd->clk_bypass->rate == rate && - (clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) { - pr_debug("clock: %s: set rate: entering bypass.\n", clk->name); - - ret = _omap3_noncore_dpll_bypass(clk); - if (!ret) - new_parent = dd->clk_bypass; - } else { - if (dd->last_rounded_rate != rate) - omap2_dpll_round_rate(clk, rate); - - if (dd->last_rounded_rate == 0) - return -EINVAL; - - freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n); - if (!freqsel) - WARN_ON(1); - - pr_debug("clock: %s: set rate: locking rate to %lu.\n", - clk->name, rate); - - ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m, - dd->last_rounded_n, freqsel); - if (!ret) - new_parent = dd->clk_ref; - } - if (!ret) { - /* - * Switch the parent clock in the heirarchy, and make sure - * that the new parent's usecount is correct. Note: we - * enable the new parent before disabling the old to avoid - * any unnecessary hardware disable->enable transitions. - */ - if (clk->usecount) { - omap2_clk_enable(new_parent); - omap2_clk_disable(clk->parent); - } - clk_reparent(clk, new_parent); - clk->rate = rate; - } - omap2_clk_disable(dd->clk_ref); - omap2_clk_disable(dd->clk_bypass); +const struct clkops clkops_omap3430es2_hsotgusb_wait = { + .enable = omap2_dflt_clk_enable, + .disable = omap2_dflt_clk_disable, + .find_idlest = omap3430es2_clk_hsotgusb_find_idlest, + .find_companion = omap2_clk_dflt_find_companion, +}; - return 0; -} +const struct clkops clkops_noncore_dpll_ops = { + .enable = omap3_noncore_dpll_enable, + .disable = omap3_noncore_dpll_disable, +}; -static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate) +int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate) { /* * According to the 12-5 CDP code from TI, "Limitation 2.5" @@ -831,12 +179,12 @@ static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate) * Program the DPLL M2 divider with the rounded target rate. Returns * -EINVAL upon error, or 0 upon success. */ -static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) +int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) { u32 new_div = 0; u32 unlock_dll = 0; u32 c; - unsigned long validrate, sdrcrate, mpurate; + unsigned long validrate, sdrcrate, _mpurate; struct omap_sdrc_params *sdrc_cs0; struct omap_sdrc_params *sdrc_cs1; int ret; @@ -844,14 +192,11 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) if (!clk || !rate) return -EINVAL; - if (clk != &dpll3_m2_ck) - return -EINVAL; - validrate = omap2_clksel_round_rate_div(clk, rate, &new_div); if (validrate != rate) return -EINVAL; - sdrcrate = sdrc_ick.rate; + sdrcrate = sdrc_ick_p->rate; if (rate > clk->rate) sdrcrate <<= ((rate / clk->rate) >> 1); else @@ -869,8 +214,8 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) /* * XXX This only needs to be done when the CPU frequency changes */ - mpurate = arm_fck.rate / CYCLES_PER_MHZ; - c = (mpurate << SDRC_MPURATE_SCALE) >> SDRC_MPURATE_BASE_SHIFT; + _mpurate = arm_fck_p->rate / CYCLES_PER_MHZ; + c = (_mpurate << SDRC_MPURATE_SCALE) >> SDRC_MPURATE_BASE_SHIFT; c += 1; /* for safety */ c *= SDRC_MPURATE_LOOPS; c >>= SDRC_MPURATE_SCALE; @@ -906,129 +251,6 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) return 0; } - -static const struct clkops clkops_noncore_dpll_ops = { - .enable = &omap3_noncore_dpll_enable, - .disable = &omap3_noncore_dpll_disable, -}; - -/* DPLL autoidle read/set code */ - - -/** - * omap3_dpll_autoidle_read - read a DPLL's autoidle bits - * @clk: struct clk * of the DPLL to read - * - * Return the DPLL's autoidle bits, shifted down to bit 0. Returns - * -EINVAL if passed a null pointer or if the struct clk does not - * appear to refer to a DPLL. - */ -static u32 omap3_dpll_autoidle_read(struct clk *clk) -{ - const struct dpll_data *dd; - u32 v; - - if (!clk || !clk->dpll_data) - return -EINVAL; - - dd = clk->dpll_data; - - v = __raw_readl(dd->autoidle_reg); - v &= dd->autoidle_mask; - v >>= __ffs(dd->autoidle_mask); - - return v; -} - -/** - * omap3_dpll_allow_idle - enable DPLL autoidle bits - * @clk: struct clk * of the DPLL to operate on - * - * Enable DPLL automatic idle control. This automatic idle mode - * switching takes effect only when the DPLL is locked, at least on - * OMAP3430. The DPLL will enter low-power stop when its downstream - * clocks are gated. No return value. - */ -static void omap3_dpll_allow_idle(struct clk *clk) -{ - const struct dpll_data *dd; - u32 v; - - if (!clk || !clk->dpll_data) - return; - - dd = clk->dpll_data; - - /* - * REVISIT: CORE DPLL can optionally enter low-power bypass - * by writing 0x5 instead of 0x1. Add some mechanism to - * optionally enter this mode. - */ - v = __raw_readl(dd->autoidle_reg); - v &= ~dd->autoidle_mask; - v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask); - __raw_writel(v, dd->autoidle_reg); -} - -/** - * omap3_dpll_deny_idle - prevent DPLL from automatically idling - * @clk: struct clk * of the DPLL to operate on - * - * Disable DPLL automatic idle control. No return value. - */ -static void omap3_dpll_deny_idle(struct clk *clk) -{ - const struct dpll_data *dd; - u32 v; - - if (!clk || !clk->dpll_data) - return; - - dd = clk->dpll_data; - - v = __raw_readl(dd->autoidle_reg); - v &= ~dd->autoidle_mask; - v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask); - __raw_writel(v, dd->autoidle_reg); -} - -/* Clock control for DPLL outputs */ - -/** - * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate - * @clk: DPLL output struct clk - * - * Using parent clock DPLL data, look up DPLL state. If locked, set our - * rate to the dpll_clk * 2; otherwise, just use dpll_clk. - */ -static unsigned long omap3_clkoutx2_recalc(struct clk *clk) -{ - const struct dpll_data *dd; - unsigned long rate; - u32 v; - struct clk *pclk; - - /* Walk up the parents of clk, looking for a DPLL */ - pclk = clk->parent; - while (pclk && !pclk->dpll_data) - pclk = pclk->parent; - - /* clk does not have a DPLL as a parent? */ - WARN_ON(!pclk); - - dd = pclk->dpll_data; - - WARN_ON(!dd->enable_mask); - - v = __raw_readl(dd->control_reg) & dd->enable_mask; - v >>= __ffs(dd->enable_mask); - if (v != OMAP3XXX_EN_DPLL_LOCKED) - rate = clk->parent->rate; - else - rate = clk->parent->rate * 2; - return rate; -} - /* Common clock code */ /* @@ -1037,7 +259,7 @@ static unsigned long omap3_clkoutx2_recalc(struct clk *clk) */ #if defined(CONFIG_ARCH_OMAP3) -static struct clk_functions omap2_clk_functions = { +struct clk_functions omap2_clk_functions = { .clk_enable = omap2_clk_enable, .clk_disable = omap2_clk_disable, .clk_round_rate = omap2_clk_round_rate, @@ -1063,7 +285,7 @@ void omap2_clk_prepare_for_reboot(void) #endif } -static void omap3_clk_lock_dpll5(void) +void omap3_clk_lock_dpll5(void) { struct clk *dpll5_clk; struct clk *dpll5_m2_clk; @@ -1093,19 +315,32 @@ static void omap3_clk_lock_dpll5(void) */ static int __init omap2_clk_arch_init(void) { + struct clk *osc_sys_ck, *dpll1_ck, *arm_fck, *core_ck; + unsigned long osc_sys_rate; + if (!mpurate) return -EINVAL; + /* XXX test these for success */ + dpll1_ck = clk_get(NULL, "dpll1_ck"); + arm_fck = clk_get(NULL, "arm_fck"); + core_ck = clk_get(NULL, "core_ck"); + osc_sys_ck = clk_get(NULL, "osc_sys_ck"); + /* REVISIT: not yet ready for 343x */ - if (clk_set_rate(&dpll1_ck, mpurate)) + if (clk_set_rate(dpll1_ck, mpurate)) printk(KERN_ERR "*** Unable to set MPU rate\n"); recalculate_root_clocks(); - printk(KERN_INFO "Switched to new clocking rate (Crystal/Core/MPU): " - "%ld.%01ld/%ld/%ld MHz\n", - (osc_sys_ck.rate / 1000000), ((osc_sys_ck.rate / 100000) % 10), - (core_ck.rate / 1000000), (arm_fck.rate / 1000000)) ; + osc_sys_rate = clk_get_rate(osc_sys_ck); + + pr_info("Switched to new clocking rate (Crystal/Core/MPU): " + "%ld.%01ld/%ld/%ld MHz\n", + (osc_sys_rate / 1000000), + ((osc_sys_rate / 100000) % 10), + (clk_get_rate(core_ck) / 1000000), + (clk_get_rate(arm_fck) / 1000000)); calibrate_delay(); @@ -1113,83 +348,7 @@ static int __init omap2_clk_arch_init(void) } arch_initcall(omap2_clk_arch_init); -int __init omap2_clk_init(void) -{ - /* struct prcm_config *prcm; */ - struct omap_clk *c; - /* u32 clkrate; */ - u32 cpu_clkflg; - - if (cpu_is_omap34xx()) { - cpu_mask = RATE_IN_343X; - cpu_clkflg = CK_343X; - - /* - * Update this if there are further clock changes between ES2 - * and production parts - */ - if (omap_rev() == OMAP3430_REV_ES1_0) { - /* No 3430ES1-only rates exist, so no RATE_IN_3430ES1 */ - cpu_clkflg |= CK_3430ES1; - } else { - cpu_mask |= RATE_IN_3430ES2; - cpu_clkflg |= CK_3430ES2; - } - } - - clk_init(&omap2_clk_functions); - - for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++) - clk_preinit(c->lk.clk); - for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++) - if (c->cpu & cpu_clkflg) { - clkdev_add(&c->lk); - clk_register(c->lk.clk); - omap2_init_clk_clkdm(c->lk.clk); - } - - /* REVISIT: Not yet ready for OMAP3 */ -#if 0 - /* Check the MPU rate set by bootloader */ - clkrate = omap2_get_dpll_rate_24xx(&dpll_ck); - for (prcm = rate_table; prcm->mpu_speed; prcm++) { - if (!(prcm->flags & cpu_mask)) - continue; - if (prcm->xtal_speed != sys_ck.rate) - continue; - if (prcm->dpll_speed <= clkrate) - break; - } - curr_prcm_set = prcm; #endif - recalculate_root_clocks(); - - printk(KERN_INFO "Clocking rate (Crystal/Core/MPU): " - "%ld.%01ld/%ld/%ld MHz\n", - (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10, - (core_ck.rate / 1000000), (arm_fck.rate / 1000000)); - - /* - * Only enable those clocks we will need, let the drivers - * enable other clocks as necessary - */ - clk_enable_init_clocks(); - - /* - * Lock DPLL5 and put it in autoidle. - */ - if (omap_rev() >= OMAP3430_REV_ES2_0) - omap3_clk_lock_dpll5(); - /* Avoid sleeping during omap2_clk_prepare_for_reboot() */ - /* REVISIT: not yet ready for 343x */ -#if 0 - vclk = clk_get(NULL, "virt_prcm_set"); - sclk = clk_get(NULL, "sys_ck"); -#endif - return 0; -} - -#endif diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 8fe1bcb23dd931a254fc591836813065d59c9a06..9a2c07eac9adfcfaf51522b018116c11537d148b 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -1,2993 +1,24 @@ /* - * OMAP3 clock framework + * OMAP3 clock function prototypes and macros * - * Copyright (C) 2007-2008 Texas Instruments, Inc. - * Copyright (C) 2007-2008 Nokia Corporation - * - * Written by Paul Walmsley - * With many device clock fixes by Kevin Hilman and Jouni Högander - * DPLL bypass clock support added by Roman Tereshonkov - * - */ - -/* - * Virtual clocks are introduced as convenient tools. - * They are sources for other clocks and not supposed - * to be requested from drivers directly. - */ - -#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H -#define __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H - -#include - -#include "clock.h" -#include "cm.h" -#include "cm-regbits-34xx.h" -#include "prm.h" -#include "prm-regbits-34xx.h" - -#define OMAP_CM_REGADDR OMAP34XX_CM_REGADDR - -static unsigned long omap3_dpll_recalc(struct clk *clk); -static unsigned long omap3_clkoutx2_recalc(struct clk *clk); -static void omap3_dpll_allow_idle(struct clk *clk); -static void omap3_dpll_deny_idle(struct clk *clk); -static u32 omap3_dpll_autoidle_read(struct clk *clk); -static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate); -static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate); -static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate); - -/* Maximum DPLL multiplier, divider values for OMAP3 */ -#define OMAP3_MAX_DPLL_MULT 2048 -#define OMAP3_MAX_DPLL_DIV 128 - -/* - * DPLL1 supplies clock to the MPU. - * DPLL2 supplies clock to the IVA2. - * DPLL3 supplies CORE domain clocks. - * DPLL4 supplies peripheral clocks. - * DPLL5 supplies other peripheral clocks (USBHOST, USIM). - */ - -/* Forward declarations for DPLL bypass clocks */ -static struct clk dpll1_fck; -static struct clk dpll2_fck; - -/* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */ -#define DPLL_LOW_POWER_STOP 0x1 -#define DPLL_LOW_POWER_BYPASS 0x5 -#define DPLL_LOCKED 0x7 - -/* PRM CLOCKS */ - -/* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */ -static struct clk omap_32k_fck = { - .name = "omap_32k_fck", - .ops = &clkops_null, - .rate = 32768, - .flags = RATE_FIXED, -}; - -static struct clk secure_32k_fck = { - .name = "secure_32k_fck", - .ops = &clkops_null, - .rate = 32768, - .flags = RATE_FIXED, -}; - -/* Virtual source clocks for osc_sys_ck */ -static struct clk virt_12m_ck = { - .name = "virt_12m_ck", - .ops = &clkops_null, - .rate = 12000000, - .flags = RATE_FIXED, -}; - -static struct clk virt_13m_ck = { - .name = "virt_13m_ck", - .ops = &clkops_null, - .rate = 13000000, - .flags = RATE_FIXED, -}; - -static struct clk virt_16_8m_ck = { - .name = "virt_16_8m_ck", - .ops = &clkops_null, - .rate = 16800000, - .flags = RATE_FIXED, -}; - -static struct clk virt_19_2m_ck = { - .name = "virt_19_2m_ck", - .ops = &clkops_null, - .rate = 19200000, - .flags = RATE_FIXED, -}; - -static struct clk virt_26m_ck = { - .name = "virt_26m_ck", - .ops = &clkops_null, - .rate = 26000000, - .flags = RATE_FIXED, -}; - -static struct clk virt_38_4m_ck = { - .name = "virt_38_4m_ck", - .ops = &clkops_null, - .rate = 38400000, - .flags = RATE_FIXED, -}; - -static const struct clksel_rate osc_sys_12m_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel_rate osc_sys_13m_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel_rate osc_sys_16_8m_rates[] = { - { .div = 1, .val = 5, .flags = RATE_IN_3430ES2 | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel_rate osc_sys_19_2m_rates[] = { - { .div = 1, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel_rate osc_sys_26m_rates[] = { - { .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel_rate osc_sys_38_4m_rates[] = { - { .div = 1, .val = 4, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel osc_sys_clksel[] = { - { .parent = &virt_12m_ck, .rates = osc_sys_12m_rates }, - { .parent = &virt_13m_ck, .rates = osc_sys_13m_rates }, - { .parent = &virt_16_8m_ck, .rates = osc_sys_16_8m_rates }, - { .parent = &virt_19_2m_ck, .rates = osc_sys_19_2m_rates }, - { .parent = &virt_26m_ck, .rates = osc_sys_26m_rates }, - { .parent = &virt_38_4m_ck, .rates = osc_sys_38_4m_rates }, - { .parent = NULL }, -}; - -/* Oscillator clock */ -/* 12, 13, 16.8, 19.2, 26, or 38.4 MHz */ -static struct clk osc_sys_ck = { - .name = "osc_sys_ck", - .ops = &clkops_null, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP3430_PRM_CLKSEL, - .clksel_mask = OMAP3430_SYS_CLKIN_SEL_MASK, - .clksel = osc_sys_clksel, - /* REVISIT: deal with autoextclkmode? */ - .flags = RATE_FIXED, - .recalc = &omap2_clksel_recalc, -}; - -static const struct clksel_rate div2_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 2, .val = 2, .flags = RATE_IN_343X }, - { .div = 0 } -}; - -static const struct clksel sys_clksel[] = { - { .parent = &osc_sys_ck, .rates = div2_rates }, - { .parent = NULL } -}; - -/* Latency: this clock is only enabled after PRM_CLKSETUP.SETUP_TIME */ -/* Feeds DPLLs - divided first by PRM_CLKSRC_CTRL.SYSCLKDIV? */ -static struct clk sys_ck = { - .name = "sys_ck", - .ops = &clkops_null, - .parent = &osc_sys_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP3430_PRM_CLKSRC_CTRL, - .clksel_mask = OMAP_SYSCLKDIV_MASK, - .clksel = sys_clksel, - .recalc = &omap2_clksel_recalc, -}; - -static struct clk sys_altclk = { - .name = "sys_altclk", - .ops = &clkops_null, -}; - -/* Optional external clock input for some McBSPs */ -static struct clk mcbsp_clks = { - .name = "mcbsp_clks", - .ops = &clkops_null, -}; - -/* PRM EXTERNAL CLOCK OUTPUT */ - -static struct clk sys_clkout1 = { - .name = "sys_clkout1", - .ops = &clkops_omap2_dflt, - .parent = &osc_sys_ck, - .enable_reg = OMAP3430_PRM_CLKOUT_CTRL, - .enable_bit = OMAP3430_CLKOUT_EN_SHIFT, - .recalc = &followparent_recalc, -}; - -/* DPLLS */ - -/* CM CLOCKS */ - -static const struct clksel_rate div16_dpll_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 2, .val = 2, .flags = RATE_IN_343X }, - { .div = 3, .val = 3, .flags = RATE_IN_343X }, - { .div = 4, .val = 4, .flags = RATE_IN_343X }, - { .div = 5, .val = 5, .flags = RATE_IN_343X }, - { .div = 6, .val = 6, .flags = RATE_IN_343X }, - { .div = 7, .val = 7, .flags = RATE_IN_343X }, - { .div = 8, .val = 8, .flags = RATE_IN_343X }, - { .div = 9, .val = 9, .flags = RATE_IN_343X }, - { .div = 10, .val = 10, .flags = RATE_IN_343X }, - { .div = 11, .val = 11, .flags = RATE_IN_343X }, - { .div = 12, .val = 12, .flags = RATE_IN_343X }, - { .div = 13, .val = 13, .flags = RATE_IN_343X }, - { .div = 14, .val = 14, .flags = RATE_IN_343X }, - { .div = 15, .val = 15, .flags = RATE_IN_343X }, - { .div = 16, .val = 16, .flags = RATE_IN_343X }, - { .div = 0 } -}; - -/* DPLL1 */ -/* MPU clock source */ -/* Type: DPLL */ -static struct dpll_data dpll1_dd = { - .mult_div1_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL), - .mult_mask = OMAP3430_MPU_DPLL_MULT_MASK, - .div1_mask = OMAP3430_MPU_DPLL_DIV_MASK, - .clk_bypass = &dpll1_fck, - .clk_ref = &sys_ck, - .freqsel_mask = OMAP3430_MPU_DPLL_FREQSEL_MASK, - .control_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL), - .enable_mask = OMAP3430_EN_MPU_DPLL_MASK, - .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), - .auto_recal_bit = OMAP3430_EN_MPU_DPLL_DRIFTGUARD_SHIFT, - .recal_en_bit = OMAP3430_MPU_DPLL_RECAL_EN_SHIFT, - .recal_st_bit = OMAP3430_MPU_DPLL_ST_SHIFT, - .autoidle_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL), - .autoidle_mask = OMAP3430_AUTO_MPU_DPLL_MASK, - .idlest_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), - .idlest_mask = OMAP3430_ST_MPU_CLK_MASK, - .max_multiplier = OMAP3_MAX_DPLL_MULT, - .min_divider = 1, - .max_divider = OMAP3_MAX_DPLL_DIV, - .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE -}; - -static struct clk dpll1_ck = { - .name = "dpll1_ck", - .ops = &clkops_null, - .parent = &sys_ck, - .dpll_data = &dpll1_dd, - .round_rate = &omap2_dpll_round_rate, - .set_rate = &omap3_noncore_dpll_set_rate, - .clkdm_name = "dpll1_clkdm", - .recalc = &omap3_dpll_recalc, -}; - -/* - * This virtual clock provides the CLKOUTX2 output from the DPLL if the - * DPLL isn't bypassed. - */ -static struct clk dpll1_x2_ck = { - .name = "dpll1_x2_ck", - .ops = &clkops_null, - .parent = &dpll1_ck, - .clkdm_name = "dpll1_clkdm", - .recalc = &omap3_clkoutx2_recalc, -}; - -/* On DPLL1, unlike other DPLLs, the divider is downstream from CLKOUTX2 */ -static const struct clksel div16_dpll1_x2m2_clksel[] = { - { .parent = &dpll1_x2_ck, .rates = div16_dpll_rates }, - { .parent = NULL } -}; - -/* - * Does not exist in the TRM - needed to separate the M2 divider from - * bypass selection in mpu_ck - */ -static struct clk dpll1_x2m2_ck = { - .name = "dpll1_x2m2_ck", - .ops = &clkops_null, - .parent = &dpll1_x2_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), - .clksel_mask = OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK, - .clksel = div16_dpll1_x2m2_clksel, - .clkdm_name = "dpll1_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -/* DPLL2 */ -/* IVA2 clock source */ -/* Type: DPLL */ - -static struct dpll_data dpll2_dd = { - .mult_div1_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL), - .mult_mask = OMAP3430_IVA2_DPLL_MULT_MASK, - .div1_mask = OMAP3430_IVA2_DPLL_DIV_MASK, - .clk_bypass = &dpll2_fck, - .clk_ref = &sys_ck, - .freqsel_mask = OMAP3430_IVA2_DPLL_FREQSEL_MASK, - .control_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL), - .enable_mask = OMAP3430_EN_IVA2_DPLL_MASK, - .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED) | - (1 << DPLL_LOW_POWER_BYPASS), - .auto_recal_bit = OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_SHIFT, - .recal_en_bit = OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN_SHIFT, - .recal_st_bit = OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST_SHIFT, - .autoidle_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL), - .autoidle_mask = OMAP3430_AUTO_IVA2_DPLL_MASK, - .idlest_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL), - .idlest_mask = OMAP3430_ST_IVA2_CLK_MASK, - .max_multiplier = OMAP3_MAX_DPLL_MULT, - .min_divider = 1, - .max_divider = OMAP3_MAX_DPLL_DIV, - .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE -}; - -static struct clk dpll2_ck = { - .name = "dpll2_ck", - .ops = &clkops_noncore_dpll_ops, - .parent = &sys_ck, - .dpll_data = &dpll2_dd, - .round_rate = &omap2_dpll_round_rate, - .set_rate = &omap3_noncore_dpll_set_rate, - .clkdm_name = "dpll2_clkdm", - .recalc = &omap3_dpll_recalc, -}; - -static const struct clksel div16_dpll2_m2x2_clksel[] = { - { .parent = &dpll2_ck, .rates = div16_dpll_rates }, - { .parent = NULL } -}; - -/* - * The TRM is conflicted on whether IVA2 clock comes from DPLL2 CLKOUT - * or CLKOUTX2. CLKOUT seems most plausible. - */ -static struct clk dpll2_m2_ck = { - .name = "dpll2_m2_ck", - .ops = &clkops_null, - .parent = &dpll2_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, - OMAP3430_CM_CLKSEL2_PLL), - .clksel_mask = OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK, - .clksel = div16_dpll2_m2x2_clksel, - .clkdm_name = "dpll2_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -/* - * DPLL3 - * Source clock for all interfaces and for some device fclks - * REVISIT: Also supports fast relock bypass - not included below - */ -static struct dpll_data dpll3_dd = { - .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), - .mult_mask = OMAP3430_CORE_DPLL_MULT_MASK, - .div1_mask = OMAP3430_CORE_DPLL_DIV_MASK, - .clk_bypass = &sys_ck, - .clk_ref = &sys_ck, - .freqsel_mask = OMAP3430_CORE_DPLL_FREQSEL_MASK, - .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), - .enable_mask = OMAP3430_EN_CORE_DPLL_MASK, - .auto_recal_bit = OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT, - .recal_en_bit = OMAP3430_CORE_DPLL_RECAL_EN_SHIFT, - .recal_st_bit = OMAP3430_CORE_DPLL_ST_SHIFT, - .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE), - .autoidle_mask = OMAP3430_AUTO_CORE_DPLL_MASK, - .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), - .idlest_mask = OMAP3430_ST_CORE_CLK_MASK, - .max_multiplier = OMAP3_MAX_DPLL_MULT, - .min_divider = 1, - .max_divider = OMAP3_MAX_DPLL_DIV, - .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE -}; - -static struct clk dpll3_ck = { - .name = "dpll3_ck", - .ops = &clkops_null, - .parent = &sys_ck, - .dpll_data = &dpll3_dd, - .round_rate = &omap2_dpll_round_rate, - .clkdm_name = "dpll3_clkdm", - .recalc = &omap3_dpll_recalc, -}; - -/* - * This virtual clock provides the CLKOUTX2 output from the DPLL if the - * DPLL isn't bypassed - */ -static struct clk dpll3_x2_ck = { - .name = "dpll3_x2_ck", - .ops = &clkops_null, - .parent = &dpll3_ck, - .clkdm_name = "dpll3_clkdm", - .recalc = &omap3_clkoutx2_recalc, -}; - -static const struct clksel_rate div31_dpll3_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 2, .val = 2, .flags = RATE_IN_343X }, - { .div = 3, .val = 3, .flags = RATE_IN_3430ES2 }, - { .div = 4, .val = 4, .flags = RATE_IN_3430ES2 }, - { .div = 5, .val = 5, .flags = RATE_IN_3430ES2 }, - { .div = 6, .val = 6, .flags = RATE_IN_3430ES2 }, - { .div = 7, .val = 7, .flags = RATE_IN_3430ES2 }, - { .div = 8, .val = 8, .flags = RATE_IN_3430ES2 }, - { .div = 9, .val = 9, .flags = RATE_IN_3430ES2 }, - { .div = 10, .val = 10, .flags = RATE_IN_3430ES2 }, - { .div = 11, .val = 11, .flags = RATE_IN_3430ES2 }, - { .div = 12, .val = 12, .flags = RATE_IN_3430ES2 }, - { .div = 13, .val = 13, .flags = RATE_IN_3430ES2 }, - { .div = 14, .val = 14, .flags = RATE_IN_3430ES2 }, - { .div = 15, .val = 15, .flags = RATE_IN_3430ES2 }, - { .div = 16, .val = 16, .flags = RATE_IN_3430ES2 }, - { .div = 17, .val = 17, .flags = RATE_IN_3430ES2 }, - { .div = 18, .val = 18, .flags = RATE_IN_3430ES2 }, - { .div = 19, .val = 19, .flags = RATE_IN_3430ES2 }, - { .div = 20, .val = 20, .flags = RATE_IN_3430ES2 }, - { .div = 21, .val = 21, .flags = RATE_IN_3430ES2 }, - { .div = 22, .val = 22, .flags = RATE_IN_3430ES2 }, - { .div = 23, .val = 23, .flags = RATE_IN_3430ES2 }, - { .div = 24, .val = 24, .flags = RATE_IN_3430ES2 }, - { .div = 25, .val = 25, .flags = RATE_IN_3430ES2 }, - { .div = 26, .val = 26, .flags = RATE_IN_3430ES2 }, - { .div = 27, .val = 27, .flags = RATE_IN_3430ES2 }, - { .div = 28, .val = 28, .flags = RATE_IN_3430ES2 }, - { .div = 29, .val = 29, .flags = RATE_IN_3430ES2 }, - { .div = 30, .val = 30, .flags = RATE_IN_3430ES2 }, - { .div = 31, .val = 31, .flags = RATE_IN_3430ES2 }, - { .div = 0 }, -}; - -static const struct clksel div31_dpll3m2_clksel[] = { - { .parent = &dpll3_ck, .rates = div31_dpll3_rates }, - { .parent = NULL } -}; - -/* DPLL3 output M2 - primary control point for CORE speed */ -static struct clk dpll3_m2_ck = { - .name = "dpll3_m2_ck", - .ops = &clkops_null, - .parent = &dpll3_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK, - .clksel = div31_dpll3m2_clksel, - .clkdm_name = "dpll3_clkdm", - .round_rate = &omap2_clksel_round_rate, - .set_rate = &omap3_core_dpll_m2_set_rate, - .recalc = &omap2_clksel_recalc, -}; - -static struct clk core_ck = { - .name = "core_ck", - .ops = &clkops_null, - .parent = &dpll3_m2_ck, - .recalc = &followparent_recalc, -}; - -static struct clk dpll3_m2x2_ck = { - .name = "dpll3_m2x2_ck", - .ops = &clkops_null, - .parent = &dpll3_m2_ck, - .clkdm_name = "dpll3_clkdm", - .recalc = &omap3_clkoutx2_recalc, -}; - -/* The PWRDN bit is apparently only available on 3430ES2 and above */ -static const struct clksel div16_dpll3_clksel[] = { - { .parent = &dpll3_ck, .rates = div16_dpll_rates }, - { .parent = NULL } -}; - -/* This virtual clock is the source for dpll3_m3x2_ck */ -static struct clk dpll3_m3_ck = { - .name = "dpll3_m3_ck", - .ops = &clkops_null, - .parent = &dpll3_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_DIV_DPLL3_MASK, - .clksel = div16_dpll3_clksel, - .clkdm_name = "dpll3_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -/* The PWRDN bit is apparently only available on 3430ES2 and above */ -static struct clk dpll3_m3x2_ck = { - .name = "dpll3_m3x2_ck", - .ops = &clkops_omap2_dflt_wait, - .parent = &dpll3_m3_ck, - .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), - .enable_bit = OMAP3430_PWRDN_EMU_CORE_SHIFT, - .flags = INVERT_ENABLE, - .clkdm_name = "dpll3_clkdm", - .recalc = &omap3_clkoutx2_recalc, -}; - -static struct clk emu_core_alwon_ck = { - .name = "emu_core_alwon_ck", - .ops = &clkops_null, - .parent = &dpll3_m3x2_ck, - .clkdm_name = "dpll3_clkdm", - .recalc = &followparent_recalc, -}; - -/* DPLL4 */ -/* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */ -/* Type: DPLL */ -static struct dpll_data dpll4_dd = { - .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2), - .mult_mask = OMAP3430_PERIPH_DPLL_MULT_MASK, - .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK, - .clk_bypass = &sys_ck, - .clk_ref = &sys_ck, - .freqsel_mask = OMAP3430_PERIPH_DPLL_FREQSEL_MASK, - .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), - .enable_mask = OMAP3430_EN_PERIPH_DPLL_MASK, - .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), - .auto_recal_bit = OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT, - .recal_en_bit = OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT, - .recal_st_bit = OMAP3430_PERIPH_DPLL_ST_SHIFT, - .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE), - .autoidle_mask = OMAP3430_AUTO_PERIPH_DPLL_MASK, - .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), - .idlest_mask = OMAP3430_ST_PERIPH_CLK_MASK, - .max_multiplier = OMAP3_MAX_DPLL_MULT, - .min_divider = 1, - .max_divider = OMAP3_MAX_DPLL_DIV, - .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE -}; - -static struct clk dpll4_ck = { - .name = "dpll4_ck", - .ops = &clkops_noncore_dpll_ops, - .parent = &sys_ck, - .dpll_data = &dpll4_dd, - .round_rate = &omap2_dpll_round_rate, - .set_rate = &omap3_dpll4_set_rate, - .clkdm_name = "dpll4_clkdm", - .recalc = &omap3_dpll_recalc, -}; - -/* - * This virtual clock provides the CLKOUTX2 output from the DPLL if the - * DPLL isn't bypassed -- - * XXX does this serve any downstream clocks? - */ -static struct clk dpll4_x2_ck = { - .name = "dpll4_x2_ck", - .ops = &clkops_null, - .parent = &dpll4_ck, - .clkdm_name = "dpll4_clkdm", - .recalc = &omap3_clkoutx2_recalc, -}; - -static const struct clksel div16_dpll4_clksel[] = { - { .parent = &dpll4_ck, .rates = div16_dpll_rates }, - { .parent = NULL } -}; - -/* This virtual clock is the source for dpll4_m2x2_ck */ -static struct clk dpll4_m2_ck = { - .name = "dpll4_m2_ck", - .ops = &clkops_null, - .parent = &dpll4_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3), - .clksel_mask = OMAP3430_DIV_96M_MASK, - .clksel = div16_dpll4_clksel, - .clkdm_name = "dpll4_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -/* The PWRDN bit is apparently only available on 3430ES2 and above */ -static struct clk dpll4_m2x2_ck = { - .name = "dpll4_m2x2_ck", - .ops = &clkops_omap2_dflt_wait, - .parent = &dpll4_m2_ck, - .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), - .enable_bit = OMAP3430_PWRDN_96M_SHIFT, - .flags = INVERT_ENABLE, - .clkdm_name = "dpll4_clkdm", - .recalc = &omap3_clkoutx2_recalc, -}; - -/* - * DPLL4 generates DPLL4_M2X2_CLK which is then routed into the PRM as - * PRM_96M_ALWON_(F)CLK. Two clocks then emerge from the PRM: - * 96M_ALWON_FCLK (called "omap_96m_alwon_fck" below) and - * CM_96K_(F)CLK. - */ -static struct clk omap_96m_alwon_fck = { - .name = "omap_96m_alwon_fck", - .ops = &clkops_null, - .parent = &dpll4_m2x2_ck, - .recalc = &followparent_recalc, -}; - -static struct clk cm_96m_fck = { - .name = "cm_96m_fck", - .ops = &clkops_null, - .parent = &omap_96m_alwon_fck, - .recalc = &followparent_recalc, -}; - -static const struct clksel_rate omap_96m_dpll_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel_rate omap_96m_sys_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel omap_96m_fck_clksel[] = { - { .parent = &cm_96m_fck, .rates = omap_96m_dpll_rates }, - { .parent = &sys_ck, .rates = omap_96m_sys_rates }, - { .parent = NULL } -}; - -static struct clk omap_96m_fck = { - .name = "omap_96m_fck", - .ops = &clkops_null, - .parent = &sys_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_SOURCE_96M_MASK, - .clksel = omap_96m_fck_clksel, - .recalc = &omap2_clksel_recalc, -}; - -/* This virtual clock is the source for dpll4_m3x2_ck */ -static struct clk dpll4_m3_ck = { - .name = "dpll4_m3_ck", - .ops = &clkops_null, - .parent = &dpll4_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_TV_MASK, - .clksel = div16_dpll4_clksel, - .clkdm_name = "dpll4_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -/* The PWRDN bit is apparently only available on 3430ES2 and above */ -static struct clk dpll4_m3x2_ck = { - .name = "dpll4_m3x2_ck", - .ops = &clkops_omap2_dflt_wait, - .parent = &dpll4_m3_ck, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), - .enable_bit = OMAP3430_PWRDN_TV_SHIFT, - .flags = INVERT_ENABLE, - .clkdm_name = "dpll4_clkdm", - .recalc = &omap3_clkoutx2_recalc, -}; - -static const struct clksel_rate omap_54m_d4m3x2_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel_rate omap_54m_alt_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel omap_54m_clksel[] = { - { .parent = &dpll4_m3x2_ck, .rates = omap_54m_d4m3x2_rates }, - { .parent = &sys_altclk, .rates = omap_54m_alt_rates }, - { .parent = NULL } -}; - -static struct clk omap_54m_fck = { - .name = "omap_54m_fck", - .ops = &clkops_null, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_SOURCE_54M_MASK, - .clksel = omap_54m_clksel, - .recalc = &omap2_clksel_recalc, -}; - -static const struct clksel_rate omap_48m_cm96m_rates[] = { - { .div = 2, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel_rate omap_48m_alt_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel omap_48m_clksel[] = { - { .parent = &cm_96m_fck, .rates = omap_48m_cm96m_rates }, - { .parent = &sys_altclk, .rates = omap_48m_alt_rates }, - { .parent = NULL } -}; - -static struct clk omap_48m_fck = { - .name = "omap_48m_fck", - .ops = &clkops_null, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_SOURCE_48M_MASK, - .clksel = omap_48m_clksel, - .recalc = &omap2_clksel_recalc, -}; - -static struct clk omap_12m_fck = { - .name = "omap_12m_fck", - .ops = &clkops_null, - .parent = &omap_48m_fck, - .fixed_div = 4, - .recalc = &omap2_fixed_divisor_recalc, -}; - -/* This virstual clock is the source for dpll4_m4x2_ck */ -static struct clk dpll4_m4_ck = { - .name = "dpll4_m4_ck", - .ops = &clkops_null, - .parent = &dpll4_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_DSS1_MASK, - .clksel = div16_dpll4_clksel, - .clkdm_name = "dpll4_clkdm", - .recalc = &omap2_clksel_recalc, - .set_rate = &omap2_clksel_set_rate, - .round_rate = &omap2_clksel_round_rate, -}; - -/* The PWRDN bit is apparently only available on 3430ES2 and above */ -static struct clk dpll4_m4x2_ck = { - .name = "dpll4_m4x2_ck", - .ops = &clkops_omap2_dflt_wait, - .parent = &dpll4_m4_ck, - .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), - .enable_bit = OMAP3430_PWRDN_CAM_SHIFT, - .flags = INVERT_ENABLE, - .clkdm_name = "dpll4_clkdm", - .recalc = &omap3_clkoutx2_recalc, -}; - -/* This virtual clock is the source for dpll4_m5x2_ck */ -static struct clk dpll4_m5_ck = { - .name = "dpll4_m5_ck", - .ops = &clkops_null, - .parent = &dpll4_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_CAM_MASK, - .clksel = div16_dpll4_clksel, - .clkdm_name = "dpll4_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -/* The PWRDN bit is apparently only available on 3430ES2 and above */ -static struct clk dpll4_m5x2_ck = { - .name = "dpll4_m5x2_ck", - .ops = &clkops_omap2_dflt_wait, - .parent = &dpll4_m5_ck, - .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), - .enable_bit = OMAP3430_PWRDN_CAM_SHIFT, - .flags = INVERT_ENABLE, - .clkdm_name = "dpll4_clkdm", - .recalc = &omap3_clkoutx2_recalc, -}; - -/* This virtual clock is the source for dpll4_m6x2_ck */ -static struct clk dpll4_m6_ck = { - .name = "dpll4_m6_ck", - .ops = &clkops_null, - .parent = &dpll4_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_DIV_DPLL4_MASK, - .clksel = div16_dpll4_clksel, - .clkdm_name = "dpll4_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -/* The PWRDN bit is apparently only available on 3430ES2 and above */ -static struct clk dpll4_m6x2_ck = { - .name = "dpll4_m6x2_ck", - .ops = &clkops_omap2_dflt_wait, - .parent = &dpll4_m6_ck, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), - .enable_bit = OMAP3430_PWRDN_EMU_PERIPH_SHIFT, - .flags = INVERT_ENABLE, - .clkdm_name = "dpll4_clkdm", - .recalc = &omap3_clkoutx2_recalc, -}; - -static struct clk emu_per_alwon_ck = { - .name = "emu_per_alwon_ck", - .ops = &clkops_null, - .parent = &dpll4_m6x2_ck, - .clkdm_name = "dpll4_clkdm", - .recalc = &followparent_recalc, -}; - -/* DPLL5 */ -/* Supplies 120MHz clock, USIM source clock */ -/* Type: DPLL */ -/* 3430ES2 only */ -static struct dpll_data dpll5_dd = { - .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4), - .mult_mask = OMAP3430ES2_PERIPH2_DPLL_MULT_MASK, - .div1_mask = OMAP3430ES2_PERIPH2_DPLL_DIV_MASK, - .clk_bypass = &sys_ck, - .clk_ref = &sys_ck, - .freqsel_mask = OMAP3430ES2_PERIPH2_DPLL_FREQSEL_MASK, - .control_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKEN2), - .enable_mask = OMAP3430ES2_EN_PERIPH2_DPLL_MASK, - .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), - .auto_recal_bit = OMAP3430ES2_EN_PERIPH2_DPLL_DRIFTGUARD_SHIFT, - .recal_en_bit = OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_SHIFT, - .recal_st_bit = OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT, - .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_AUTOIDLE2_PLL), - .autoidle_mask = OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK, - .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2), - .idlest_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK, - .max_multiplier = OMAP3_MAX_DPLL_MULT, - .min_divider = 1, - .max_divider = OMAP3_MAX_DPLL_DIV, - .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE -}; - -static struct clk dpll5_ck = { - .name = "dpll5_ck", - .ops = &clkops_noncore_dpll_ops, - .parent = &sys_ck, - .dpll_data = &dpll5_dd, - .round_rate = &omap2_dpll_round_rate, - .set_rate = &omap3_noncore_dpll_set_rate, - .clkdm_name = "dpll5_clkdm", - .recalc = &omap3_dpll_recalc, -}; - -static const struct clksel div16_dpll5_clksel[] = { - { .parent = &dpll5_ck, .rates = div16_dpll_rates }, - { .parent = NULL } -}; - -static struct clk dpll5_m2_ck = { - .name = "dpll5_m2_ck", - .ops = &clkops_null, - .parent = &dpll5_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5), - .clksel_mask = OMAP3430ES2_DIV_120M_MASK, - .clksel = div16_dpll5_clksel, - .clkdm_name = "dpll5_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -/* CM EXTERNAL CLOCK OUTPUTS */ - -static const struct clksel_rate clkout2_src_core_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel_rate clkout2_src_sys_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel_rate clkout2_src_96m_rates[] = { - { .div = 1, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel_rate clkout2_src_54m_rates[] = { - { .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel clkout2_src_clksel[] = { - { .parent = &core_ck, .rates = clkout2_src_core_rates }, - { .parent = &sys_ck, .rates = clkout2_src_sys_rates }, - { .parent = &cm_96m_fck, .rates = clkout2_src_96m_rates }, - { .parent = &omap_54m_fck, .rates = clkout2_src_54m_rates }, - { .parent = NULL } -}; - -static struct clk clkout2_src_ck = { - .name = "clkout2_src_ck", - .ops = &clkops_omap2_dflt, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP3430_CM_CLKOUT_CTRL, - .enable_bit = OMAP3430_CLKOUT2_EN_SHIFT, - .clksel_reg = OMAP3430_CM_CLKOUT_CTRL, - .clksel_mask = OMAP3430_CLKOUT2SOURCE_MASK, - .clksel = clkout2_src_clksel, - .clkdm_name = "core_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static const struct clksel_rate sys_clkout2_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 2, .val = 1, .flags = RATE_IN_343X }, - { .div = 4, .val = 2, .flags = RATE_IN_343X }, - { .div = 8, .val = 3, .flags = RATE_IN_343X }, - { .div = 16, .val = 4, .flags = RATE_IN_343X }, - { .div = 0 }, -}; - -static const struct clksel sys_clkout2_clksel[] = { - { .parent = &clkout2_src_ck, .rates = sys_clkout2_rates }, - { .parent = NULL }, -}; - -static struct clk sys_clkout2 = { - .name = "sys_clkout2", - .ops = &clkops_null, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP3430_CM_CLKOUT_CTRL, - .clksel_mask = OMAP3430_CLKOUT2_DIV_MASK, - .clksel = sys_clkout2_clksel, - .recalc = &omap2_clksel_recalc, -}; - -/* CM OUTPUT CLOCKS */ - -static struct clk corex2_fck = { - .name = "corex2_fck", - .ops = &clkops_null, - .parent = &dpll3_m2x2_ck, - .recalc = &followparent_recalc, -}; - -/* DPLL power domain clock controls */ - -static const struct clksel_rate div4_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 2, .val = 2, .flags = RATE_IN_343X }, - { .div = 4, .val = 4, .flags = RATE_IN_343X }, - { .div = 0 } -}; - -static const struct clksel div4_core_clksel[] = { - { .parent = &core_ck, .rates = div4_rates }, - { .parent = NULL } -}; - -/* - * REVISIT: Are these in DPLL power domain or CM power domain? docs - * may be inconsistent here? - */ -static struct clk dpll1_fck = { - .name = "dpll1_fck", - .ops = &clkops_null, - .parent = &core_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL), - .clksel_mask = OMAP3430_MPU_CLK_SRC_MASK, - .clksel = div4_core_clksel, - .recalc = &omap2_clksel_recalc, -}; - -static struct clk mpu_ck = { - .name = "mpu_ck", - .ops = &clkops_null, - .parent = &dpll1_x2m2_ck, - .clkdm_name = "mpu_clkdm", - .recalc = &followparent_recalc, -}; - -/* arm_fck is divided by two when DPLL1 locked; otherwise, passthrough mpu_ck */ -static const struct clksel_rate arm_fck_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 2, .val = 1, .flags = RATE_IN_343X }, - { .div = 0 }, -}; - -static const struct clksel arm_fck_clksel[] = { - { .parent = &mpu_ck, .rates = arm_fck_rates }, - { .parent = NULL } -}; - -static struct clk arm_fck = { - .name = "arm_fck", - .ops = &clkops_null, - .parent = &mpu_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), - .clksel_mask = OMAP3430_ST_MPU_CLK_MASK, - .clksel = arm_fck_clksel, - .clkdm_name = "mpu_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -/* XXX What about neon_clkdm ? */ - -/* - * REVISIT: This clock is never specifically defined in the 3430 TRM, - * although it is referenced - so this is a guess - */ -static struct clk emu_mpu_alwon_ck = { - .name = "emu_mpu_alwon_ck", - .ops = &clkops_null, - .parent = &mpu_ck, - .recalc = &followparent_recalc, -}; - -static struct clk dpll2_fck = { - .name = "dpll2_fck", - .ops = &clkops_null, - .parent = &core_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL), - .clksel_mask = OMAP3430_IVA2_CLK_SRC_MASK, - .clksel = div4_core_clksel, - .recalc = &omap2_clksel_recalc, -}; - -static struct clk iva2_ck = { - .name = "iva2_ck", - .ops = &clkops_omap2_dflt_wait, - .parent = &dpll2_m2_ck, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT, - .clkdm_name = "iva2_clkdm", - .recalc = &followparent_recalc, -}; - -/* Common interface clocks */ - -static const struct clksel div2_core_clksel[] = { - { .parent = &core_ck, .rates = div2_rates }, - { .parent = NULL } -}; - -static struct clk l3_ick = { - .name = "l3_ick", - .ops = &clkops_null, - .parent = &core_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_L3_MASK, - .clksel = div2_core_clksel, - .clkdm_name = "core_l3_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static const struct clksel div2_l3_clksel[] = { - { .parent = &l3_ick, .rates = div2_rates }, - { .parent = NULL } -}; - -static struct clk l4_ick = { - .name = "l4_ick", - .ops = &clkops_null, - .parent = &l3_ick, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_L4_MASK, - .clksel = div2_l3_clksel, - .clkdm_name = "core_l4_clkdm", - .recalc = &omap2_clksel_recalc, - -}; - -static const struct clksel div2_l4_clksel[] = { - { .parent = &l4_ick, .rates = div2_rates }, - { .parent = NULL } -}; - -static struct clk rm_ick = { - .name = "rm_ick", - .ops = &clkops_null, - .parent = &l4_ick, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_RM_MASK, - .clksel = div2_l4_clksel, - .recalc = &omap2_clksel_recalc, -}; - -/* GFX power domain */ - -/* GFX clocks are in 3430ES1 only. 3430ES2 and later uses the SGX instead */ - -static const struct clksel gfx_l3_clksel[] = { - { .parent = &l3_ick, .rates = gfx_l3_rates }, - { .parent = NULL } -}; - -/* Virtual parent clock for gfx_l3_ick and gfx_l3_fck */ -static struct clk gfx_l3_ck = { - .name = "gfx_l3_ck", - .ops = &clkops_omap2_dflt_wait, - .parent = &l3_ick, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN), - .enable_bit = OMAP_EN_GFX_SHIFT, - .recalc = &followparent_recalc, -}; - -static struct clk gfx_l3_fck = { - .name = "gfx_l3_fck", - .ops = &clkops_null, - .parent = &gfx_l3_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL), - .clksel_mask = OMAP_CLKSEL_GFX_MASK, - .clksel = gfx_l3_clksel, - .clkdm_name = "gfx_3430es1_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk gfx_l3_ick = { - .name = "gfx_l3_ick", - .ops = &clkops_null, - .parent = &gfx_l3_ck, - .clkdm_name = "gfx_3430es1_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gfx_cg1_ck = { - .name = "gfx_cg1_ck", - .ops = &clkops_omap2_dflt_wait, - .parent = &gfx_l3_fck, /* REVISIT: correct? */ - .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN), - .enable_bit = OMAP3430ES1_EN_2D_SHIFT, - .clkdm_name = "gfx_3430es1_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gfx_cg2_ck = { - .name = "gfx_cg2_ck", - .ops = &clkops_omap2_dflt_wait, - .parent = &gfx_l3_fck, /* REVISIT: correct? */ - .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN), - .enable_bit = OMAP3430ES1_EN_3D_SHIFT, - .clkdm_name = "gfx_3430es1_clkdm", - .recalc = &followparent_recalc, -}; - -/* SGX power domain - 3430ES2 only */ - -static const struct clksel_rate sgx_core_rates[] = { - { .div = 3, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 4, .val = 1, .flags = RATE_IN_343X }, - { .div = 6, .val = 2, .flags = RATE_IN_343X }, - { .div = 0 }, -}; - -static const struct clksel_rate sgx_96m_rates[] = { - { .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 }, -}; - -static const struct clksel sgx_clksel[] = { - { .parent = &core_ck, .rates = sgx_core_rates }, - { .parent = &cm_96m_fck, .rates = sgx_96m_rates }, - { .parent = NULL }, -}; - -static struct clk sgx_fck = { - .name = "sgx_fck", - .ops = &clkops_omap2_dflt_wait, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_FCLKEN), - .enable_bit = OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430ES2_CLKSEL_SGX_MASK, - .clksel = sgx_clksel, - .clkdm_name = "sgx_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk sgx_ick = { - .name = "sgx_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &l3_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN), - .enable_bit = OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_SHIFT, - .clkdm_name = "sgx_clkdm", - .recalc = &followparent_recalc, -}; - -/* CORE power domain */ - -static struct clk d2d_26m_fck = { - .name = "d2d_26m_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &sys_ck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430ES1_EN_D2D_SHIFT, - .clkdm_name = "d2d_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk modem_fck = { - .name = "modem_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &sys_ck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_MODEM_SHIFT, - .clkdm_name = "d2d_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk sad2d_ick = { - .name = "sad2d_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &l3_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_SAD2D_SHIFT, - .clkdm_name = "d2d_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mad2d_ick = { - .name = "mad2d_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &l3_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), - .enable_bit = OMAP3430_EN_MAD2D_SHIFT, - .clkdm_name = "d2d_clkdm", - .recalc = &followparent_recalc, -}; - -static const struct clksel omap343x_gpt_clksel[] = { - { .parent = &omap_32k_fck, .rates = gpt_32k_rates }, - { .parent = &sys_ck, .rates = gpt_sys_rates }, - { .parent = NULL} -}; - -static struct clk gpt10_fck = { - .name = "gpt10_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &sys_ck, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_GPT10_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_GPT10_MASK, - .clksel = omap343x_gpt_clksel, - .clkdm_name = "core_l4_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk gpt11_fck = { - .name = "gpt11_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &sys_ck, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_GPT11_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_GPT11_MASK, - .clksel = omap343x_gpt_clksel, - .clkdm_name = "core_l4_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk cpefuse_fck = { - .name = "cpefuse_fck", - .ops = &clkops_omap2_dflt, - .parent = &sys_ck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), - .enable_bit = OMAP3430ES2_EN_CPEFUSE_SHIFT, - .recalc = &followparent_recalc, -}; - -static struct clk ts_fck = { - .name = "ts_fck", - .ops = &clkops_omap2_dflt, - .parent = &omap_32k_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), - .enable_bit = OMAP3430ES2_EN_TS_SHIFT, - .recalc = &followparent_recalc, -}; - -static struct clk usbtll_fck = { - .name = "usbtll_fck", - .ops = &clkops_omap2_dflt, - .parent = &dpll5_m2_ck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), - .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT, - .recalc = &followparent_recalc, -}; - -/* CORE 96M FCLK-derived clocks */ - -static struct clk core_96m_fck = { - .name = "core_96m_fck", - .ops = &clkops_null, - .parent = &omap_96m_fck, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mmchs3_fck = { - .name = "mmchs_fck", - .ops = &clkops_omap2_dflt_wait, - .id = 2, - .parent = &core_96m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mmchs2_fck = { - .name = "mmchs_fck", - .ops = &clkops_omap2_dflt_wait, - .id = 1, - .parent = &core_96m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_MMC2_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mspro_fck = { - .name = "mspro_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_96m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_MSPRO_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mmchs1_fck = { - .name = "mmchs_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_96m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_MMC1_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk i2c3_fck = { - .name = "i2c_fck", - .ops = &clkops_omap2_dflt_wait, - .id = 3, - .parent = &core_96m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_I2C3_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk i2c2_fck = { - .name = "i2c_fck", - .ops = &clkops_omap2_dflt_wait, - .id = 2, - .parent = &core_96m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_I2C2_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk i2c1_fck = { - .name = "i2c_fck", - .ops = &clkops_omap2_dflt_wait, - .id = 1, - .parent = &core_96m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_I2C1_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -/* - * MCBSP 1 & 5 get their 96MHz clock from core_96m_fck; - * MCBSP 2, 3, 4 get their 96MHz clock from per_96m_fck. - */ -static const struct clksel_rate common_mcbsp_96m_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel_rate common_mcbsp_mcbsp_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 } -}; - -static const struct clksel mcbsp_15_clksel[] = { - { .parent = &core_96m_fck, .rates = common_mcbsp_96m_rates }, - { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates }, - { .parent = NULL } -}; - -static struct clk mcbsp5_fck = { - .name = "mcbsp_fck", - .ops = &clkops_omap2_dflt_wait, - .id = 5, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_MCBSP5_SHIFT, - .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1), - .clksel_mask = OMAP2_MCBSP5_CLKS_MASK, - .clksel = mcbsp_15_clksel, - .clkdm_name = "core_l4_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk mcbsp1_fck = { - .name = "mcbsp_fck", - .ops = &clkops_omap2_dflt_wait, - .id = 1, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_MCBSP1_SHIFT, - .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0), - .clksel_mask = OMAP2_MCBSP1_CLKS_MASK, - .clksel = mcbsp_15_clksel, - .clkdm_name = "core_l4_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -/* CORE_48M_FCK-derived clocks */ - -static struct clk core_48m_fck = { - .name = "core_48m_fck", - .ops = &clkops_null, - .parent = &omap_48m_fck, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mcspi4_fck = { - .name = "mcspi_fck", - .ops = &clkops_omap2_dflt_wait, - .id = 4, - .parent = &core_48m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_MCSPI4_SHIFT, - .recalc = &followparent_recalc, -}; - -static struct clk mcspi3_fck = { - .name = "mcspi_fck", - .ops = &clkops_omap2_dflt_wait, - .id = 3, - .parent = &core_48m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_MCSPI3_SHIFT, - .recalc = &followparent_recalc, -}; - -static struct clk mcspi2_fck = { - .name = "mcspi_fck", - .ops = &clkops_omap2_dflt_wait, - .id = 2, - .parent = &core_48m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_MCSPI2_SHIFT, - .recalc = &followparent_recalc, -}; - -static struct clk mcspi1_fck = { - .name = "mcspi_fck", - .ops = &clkops_omap2_dflt_wait, - .id = 1, - .parent = &core_48m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_MCSPI1_SHIFT, - .recalc = &followparent_recalc, -}; - -static struct clk uart2_fck = { - .name = "uart2_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_48m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_UART2_SHIFT, - .recalc = &followparent_recalc, -}; - -static struct clk uart1_fck = { - .name = "uart1_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_48m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_UART1_SHIFT, - .recalc = &followparent_recalc, -}; - -static struct clk fshostusb_fck = { - .name = "fshostusb_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_48m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430ES1_EN_FSHOSTUSB_SHIFT, - .recalc = &followparent_recalc, -}; - -/* CORE_12M_FCK based clocks */ - -static struct clk core_12m_fck = { - .name = "core_12m_fck", - .ops = &clkops_null, - .parent = &omap_12m_fck, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk hdq_fck = { - .name = "hdq_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_12m_fck, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_HDQ_SHIFT, - .recalc = &followparent_recalc, -}; - -/* DPLL3-derived clock */ - -static const struct clksel_rate ssi_ssr_corex2_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 2, .val = 2, .flags = RATE_IN_343X }, - { .div = 3, .val = 3, .flags = RATE_IN_343X }, - { .div = 4, .val = 4, .flags = RATE_IN_343X }, - { .div = 6, .val = 6, .flags = RATE_IN_343X }, - { .div = 8, .val = 8, .flags = RATE_IN_343X }, - { .div = 0 } -}; - -static const struct clksel ssi_ssr_clksel[] = { - { .parent = &corex2_fck, .rates = ssi_ssr_corex2_rates }, - { .parent = NULL } -}; - -static struct clk ssi_ssr_fck_3430es1 = { - .name = "ssi_ssr_fck", - .ops = &clkops_omap2_dflt, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_SSI_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_SSI_MASK, - .clksel = ssi_ssr_clksel, - .clkdm_name = "core_l4_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk ssi_ssr_fck_3430es2 = { - .name = "ssi_ssr_fck", - .ops = &clkops_omap3430es2_ssi_wait, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), - .enable_bit = OMAP3430_EN_SSI_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_SSI_MASK, - .clksel = ssi_ssr_clksel, - .clkdm_name = "core_l4_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk ssi_sst_fck_3430es1 = { - .name = "ssi_sst_fck", - .ops = &clkops_null, - .parent = &ssi_ssr_fck_3430es1, - .fixed_div = 2, - .recalc = &omap2_fixed_divisor_recalc, -}; - -static struct clk ssi_sst_fck_3430es2 = { - .name = "ssi_sst_fck", - .ops = &clkops_null, - .parent = &ssi_ssr_fck_3430es2, - .fixed_div = 2, - .recalc = &omap2_fixed_divisor_recalc, -}; - - - -/* CORE_L3_ICK based clocks */ - -/* - * XXX must add clk_enable/clk_disable for these if standard code won't - * handle it - */ -static struct clk core_l3_ick = { - .name = "core_l3_ick", - .ops = &clkops_null, - .parent = &l3_ick, - .clkdm_name = "core_l3_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk hsotgusb_ick_3430es1 = { - .name = "hsotgusb_ick", - .ops = &clkops_omap2_dflt, - .parent = &core_l3_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT, - .clkdm_name = "core_l3_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk hsotgusb_ick_3430es2 = { - .name = "hsotgusb_ick", - .ops = &clkops_omap3430es2_hsotgusb_wait, - .parent = &core_l3_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT, - .clkdm_name = "core_l3_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk sdrc_ick = { - .name = "sdrc_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l3_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_SDRC_SHIFT, - .flags = ENABLE_ON_INIT, - .clkdm_name = "core_l3_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpmc_fck = { - .name = "gpmc_fck", - .ops = &clkops_null, - .parent = &core_l3_ick, - .flags = ENABLE_ON_INIT, /* huh? */ - .clkdm_name = "core_l3_clkdm", - .recalc = &followparent_recalc, -}; - -/* SECURITY_L3_ICK based clocks */ - -static struct clk security_l3_ick = { - .name = "security_l3_ick", - .ops = &clkops_null, - .parent = &l3_ick, - .recalc = &followparent_recalc, -}; - -static struct clk pka_ick = { - .name = "pka_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &security_l3_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), - .enable_bit = OMAP3430_EN_PKA_SHIFT, - .recalc = &followparent_recalc, -}; - -/* CORE_L4_ICK based clocks */ - -static struct clk core_l4_ick = { - .name = "core_l4_ick", - .ops = &clkops_null, - .parent = &l4_ick, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk usbtll_ick = { - .name = "usbtll_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), - .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mmchs3_ick = { - .name = "mmchs_ick", - .ops = &clkops_omap2_dflt_wait, - .id = 2, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -/* Intersystem Communication Registers - chassis mode only */ -static struct clk icr_ick = { - .name = "icr_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_ICR_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk aes2_ick = { - .name = "aes2_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_AES2_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk sha12_ick = { - .name = "sha12_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_SHA12_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk des2_ick = { - .name = "des2_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_DES2_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mmchs2_ick = { - .name = "mmchs_ick", - .ops = &clkops_omap2_dflt_wait, - .id = 1, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_MMC2_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mmchs1_ick = { - .name = "mmchs_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_MMC1_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mspro_ick = { - .name = "mspro_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_MSPRO_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk hdq_ick = { - .name = "hdq_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_HDQ_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mcspi4_ick = { - .name = "mcspi_ick", - .ops = &clkops_omap2_dflt_wait, - .id = 4, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_MCSPI4_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mcspi3_ick = { - .name = "mcspi_ick", - .ops = &clkops_omap2_dflt_wait, - .id = 3, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_MCSPI3_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mcspi2_ick = { - .name = "mcspi_ick", - .ops = &clkops_omap2_dflt_wait, - .id = 2, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_MCSPI2_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mcspi1_ick = { - .name = "mcspi_ick", - .ops = &clkops_omap2_dflt_wait, - .id = 1, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_MCSPI1_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk i2c3_ick = { - .name = "i2c_ick", - .ops = &clkops_omap2_dflt_wait, - .id = 3, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_I2C3_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk i2c2_ick = { - .name = "i2c_ick", - .ops = &clkops_omap2_dflt_wait, - .id = 2, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_I2C2_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk i2c1_ick = { - .name = "i2c_ick", - .ops = &clkops_omap2_dflt_wait, - .id = 1, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_I2C1_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk uart2_ick = { - .name = "uart2_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_UART2_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk uart1_ick = { - .name = "uart1_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_UART1_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpt11_ick = { - .name = "gpt11_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_GPT11_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpt10_ick = { - .name = "gpt10_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_GPT10_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mcbsp5_ick = { - .name = "mcbsp_ick", - .ops = &clkops_omap2_dflt_wait, - .id = 5, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_MCBSP5_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mcbsp1_ick = { - .name = "mcbsp_ick", - .ops = &clkops_omap2_dflt_wait, - .id = 1, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_MCBSP1_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk fac_ick = { - .name = "fac_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430ES1_EN_FAC_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mailboxes_ick = { - .name = "mailboxes_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_MAILBOXES_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk omapctrl_ick = { - .name = "omapctrl_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &core_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_OMAPCTRL_SHIFT, - .flags = ENABLE_ON_INIT, - .recalc = &followparent_recalc, -}; - -/* SSI_L4_ICK based clocks */ - -static struct clk ssi_l4_ick = { - .name = "ssi_l4_ick", - .ops = &clkops_null, - .parent = &l4_ick, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk ssi_ick_3430es1 = { - .name = "ssi_ick", - .ops = &clkops_omap2_dflt, - .parent = &ssi_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_SSI_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk ssi_ick_3430es2 = { - .name = "ssi_ick", - .ops = &clkops_omap3430es2_ssi_wait, - .parent = &ssi_l4_ick, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430_EN_SSI_SHIFT, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; - -/* REVISIT: Technically the TRM claims that this is CORE_CLK based, - * but l4_ick makes more sense to me */ - -static const struct clksel usb_l4_clksel[] = { - { .parent = &l4_ick, .rates = div2_rates }, - { .parent = NULL }, -}; - -static struct clk usb_l4_ick = { - .name = "usb_l4_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &l4_ick, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), - .enable_bit = OMAP3430ES1_EN_FSHOSTUSB_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK, - .clksel = usb_l4_clksel, - .recalc = &omap2_clksel_recalc, -}; - -/* SECURITY_L4_ICK2 based clocks */ - -static struct clk security_l4_ick2 = { - .name = "security_l4_ick2", - .ops = &clkops_null, - .parent = &l4_ick, - .recalc = &followparent_recalc, -}; - -static struct clk aes1_ick = { - .name = "aes1_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &security_l4_ick2, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), - .enable_bit = OMAP3430_EN_AES1_SHIFT, - .recalc = &followparent_recalc, -}; - -static struct clk rng_ick = { - .name = "rng_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &security_l4_ick2, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), - .enable_bit = OMAP3430_EN_RNG_SHIFT, - .recalc = &followparent_recalc, -}; - -static struct clk sha11_ick = { - .name = "sha11_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &security_l4_ick2, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), - .enable_bit = OMAP3430_EN_SHA11_SHIFT, - .recalc = &followparent_recalc, -}; - -static struct clk des1_ick = { - .name = "des1_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &security_l4_ick2, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), - .enable_bit = OMAP3430_EN_DES1_SHIFT, - .recalc = &followparent_recalc, -}; - -/* DSS */ -static struct clk dss1_alwon_fck_3430es1 = { - .name = "dss1_alwon_fck", - .ops = &clkops_omap2_dflt, - .parent = &dpll4_m4x2_ck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_DSS1_SHIFT, - .clkdm_name = "dss_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk dss1_alwon_fck_3430es2 = { - .name = "dss1_alwon_fck", - .ops = &clkops_omap3430es2_dss_usbhost_wait, - .parent = &dpll4_m4x2_ck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_DSS1_SHIFT, - .clkdm_name = "dss_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk dss_tv_fck = { - .name = "dss_tv_fck", - .ops = &clkops_omap2_dflt, - .parent = &omap_54m_fck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_TV_SHIFT, - .clkdm_name = "dss_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk dss_96m_fck = { - .name = "dss_96m_fck", - .ops = &clkops_omap2_dflt, - .parent = &omap_96m_fck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_TV_SHIFT, - .clkdm_name = "dss_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk dss2_alwon_fck = { - .name = "dss2_alwon_fck", - .ops = &clkops_omap2_dflt, - .parent = &sys_ck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_DSS2_SHIFT, - .clkdm_name = "dss_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk dss_ick_3430es1 = { - /* Handles both L3 and L4 clocks */ - .name = "dss_ick", - .ops = &clkops_omap2_dflt, - .parent = &l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT, - .clkdm_name = "dss_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk dss_ick_3430es2 = { - /* Handles both L3 and L4 clocks */ - .name = "dss_ick", - .ops = &clkops_omap3430es2_dss_usbhost_wait, - .parent = &l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT, - .clkdm_name = "dss_clkdm", - .recalc = &followparent_recalc, -}; - -/* CAM */ - -static struct clk cam_mclk = { - .name = "cam_mclk", - .ops = &clkops_omap2_dflt, - .parent = &dpll4_m5x2_ck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_CAM_SHIFT, - .clkdm_name = "cam_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk cam_ick = { - /* Handles both L3 and L4 clocks */ - .name = "cam_ick", - .ops = &clkops_omap2_dflt, - .parent = &l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_CAM_SHIFT, - .clkdm_name = "cam_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk csi2_96m_fck = { - .name = "csi2_96m_fck", - .ops = &clkops_omap2_dflt, - .parent = &core_96m_fck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_CSI2_SHIFT, - .clkdm_name = "cam_clkdm", - .recalc = &followparent_recalc, -}; - -/* USBHOST - 3430ES2 only */ - -static struct clk usbhost_120m_fck = { - .name = "usbhost_120m_fck", - .ops = &clkops_omap2_dflt, - .parent = &dpll5_m2_ck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN), - .enable_bit = OMAP3430ES2_EN_USBHOST2_SHIFT, - .clkdm_name = "usbhost_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk usbhost_48m_fck = { - .name = "usbhost_48m_fck", - .ops = &clkops_omap3430es2_dss_usbhost_wait, - .parent = &omap_48m_fck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN), - .enable_bit = OMAP3430ES2_EN_USBHOST1_SHIFT, - .clkdm_name = "usbhost_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk usbhost_ick = { - /* Handles both L3 and L4 clocks */ - .name = "usbhost_ick", - .ops = &clkops_omap3430es2_dss_usbhost_wait, - .parent = &l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN), - .enable_bit = OMAP3430ES2_EN_USBHOST_SHIFT, - .clkdm_name = "usbhost_clkdm", - .recalc = &followparent_recalc, -}; - -/* WKUP */ - -static const struct clksel_rate usim_96m_rates[] = { - { .div = 2, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 4, .val = 4, .flags = RATE_IN_343X }, - { .div = 8, .val = 5, .flags = RATE_IN_343X }, - { .div = 10, .val = 6, .flags = RATE_IN_343X }, - { .div = 0 }, -}; - -static const struct clksel_rate usim_120m_rates[] = { - { .div = 4, .val = 7, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 8, .val = 8, .flags = RATE_IN_343X }, - { .div = 16, .val = 9, .flags = RATE_IN_343X }, - { .div = 20, .val = 10, .flags = RATE_IN_343X }, - { .div = 0 }, -}; - -static const struct clksel usim_clksel[] = { - { .parent = &omap_96m_fck, .rates = usim_96m_rates }, - { .parent = &dpll5_m2_ck, .rates = usim_120m_rates }, - { .parent = &sys_ck, .rates = div2_rates }, - { .parent = NULL }, -}; - -/* 3430ES2 only */ -static struct clk usim_fck = { - .name = "usim_fck", - .ops = &clkops_omap2_dflt_wait, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), - .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430ES2_CLKSEL_USIMOCP_MASK, - .clksel = usim_clksel, - .recalc = &omap2_clksel_recalc, -}; - -/* XXX should gpt1's clksel have wkup_32k_fck as the 32k opt? */ -static struct clk gpt1_fck = { - .name = "gpt1_fck", - .ops = &clkops_omap2_dflt_wait, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPT1_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_GPT1_MASK, - .clksel = omap343x_gpt_clksel, - .clkdm_name = "wkup_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk wkup_32k_fck = { - .name = "wkup_32k_fck", - .ops = &clkops_null, - .parent = &omap_32k_fck, - .clkdm_name = "wkup_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpio1_dbck = { - .name = "gpio1_dbck", - .ops = &clkops_omap2_dflt, - .parent = &wkup_32k_fck, - .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPIO1_SHIFT, - .clkdm_name = "wkup_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk wdt2_fck = { - .name = "wdt2_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &wkup_32k_fck, - .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_WDT2_SHIFT, - .clkdm_name = "wkup_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk wkup_l4_ick = { - .name = "wkup_l4_ick", - .ops = &clkops_null, - .parent = &sys_ck, - .clkdm_name = "wkup_clkdm", - .recalc = &followparent_recalc, -}; - -/* 3430ES2 only */ -/* Never specifically named in the TRM, so we have to infer a likely name */ -static struct clk usim_ick = { - .name = "usim_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &wkup_l4_ick, - .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), - .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT, - .clkdm_name = "wkup_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk wdt2_ick = { - .name = "wdt2_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &wkup_l4_ick, - .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_WDT2_SHIFT, - .clkdm_name = "wkup_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk wdt1_ick = { - .name = "wdt1_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &wkup_l4_ick, - .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_WDT1_SHIFT, - .clkdm_name = "wkup_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpio1_ick = { - .name = "gpio1_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &wkup_l4_ick, - .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPIO1_SHIFT, - .clkdm_name = "wkup_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk omap_32ksync_ick = { - .name = "omap_32ksync_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &wkup_l4_ick, - .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_32KSYNC_SHIFT, - .clkdm_name = "wkup_clkdm", - .recalc = &followparent_recalc, -}; - -/* XXX This clock no longer exists in 3430 TRM rev F */ -static struct clk gpt12_ick = { - .name = "gpt12_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &wkup_l4_ick, - .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPT12_SHIFT, - .clkdm_name = "wkup_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpt1_ick = { - .name = "gpt1_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &wkup_l4_ick, - .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPT1_SHIFT, - .clkdm_name = "wkup_clkdm", - .recalc = &followparent_recalc, -}; - - - -/* PER clock domain */ - -static struct clk per_96m_fck = { - .name = "per_96m_fck", - .ops = &clkops_null, - .parent = &omap_96m_alwon_fck, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk per_48m_fck = { - .name = "per_48m_fck", - .ops = &clkops_null, - .parent = &omap_48m_fck, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk uart3_fck = { - .name = "uart3_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_48m_fck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_UART3_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpt2_fck = { - .name = "gpt2_fck", - .ops = &clkops_omap2_dflt_wait, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPT2_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_GPT2_MASK, - .clksel = omap343x_gpt_clksel, - .clkdm_name = "per_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk gpt3_fck = { - .name = "gpt3_fck", - .ops = &clkops_omap2_dflt_wait, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPT3_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_GPT3_MASK, - .clksel = omap343x_gpt_clksel, - .clkdm_name = "per_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk gpt4_fck = { - .name = "gpt4_fck", - .ops = &clkops_omap2_dflt_wait, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPT4_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_GPT4_MASK, - .clksel = omap343x_gpt_clksel, - .clkdm_name = "per_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk gpt5_fck = { - .name = "gpt5_fck", - .ops = &clkops_omap2_dflt_wait, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPT5_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_GPT5_MASK, - .clksel = omap343x_gpt_clksel, - .clkdm_name = "per_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk gpt6_fck = { - .name = "gpt6_fck", - .ops = &clkops_omap2_dflt_wait, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPT6_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_GPT6_MASK, - .clksel = omap343x_gpt_clksel, - .clkdm_name = "per_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk gpt7_fck = { - .name = "gpt7_fck", - .ops = &clkops_omap2_dflt_wait, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPT7_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_GPT7_MASK, - .clksel = omap343x_gpt_clksel, - .clkdm_name = "per_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk gpt8_fck = { - .name = "gpt8_fck", - .ops = &clkops_omap2_dflt_wait, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPT8_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_GPT8_MASK, - .clksel = omap343x_gpt_clksel, - .clkdm_name = "per_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk gpt9_fck = { - .name = "gpt9_fck", - .ops = &clkops_omap2_dflt_wait, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPT9_SHIFT, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_GPT9_MASK, - .clksel = omap343x_gpt_clksel, - .clkdm_name = "per_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk per_32k_alwon_fck = { - .name = "per_32k_alwon_fck", - .ops = &clkops_null, - .parent = &omap_32k_fck, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpio6_dbck = { - .name = "gpio6_dbck", - .ops = &clkops_omap2_dflt, - .parent = &per_32k_alwon_fck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPIO6_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpio5_dbck = { - .name = "gpio5_dbck", - .ops = &clkops_omap2_dflt, - .parent = &per_32k_alwon_fck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPIO5_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpio4_dbck = { - .name = "gpio4_dbck", - .ops = &clkops_omap2_dflt, - .parent = &per_32k_alwon_fck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPIO4_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpio3_dbck = { - .name = "gpio3_dbck", - .ops = &clkops_omap2_dflt, - .parent = &per_32k_alwon_fck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPIO3_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpio2_dbck = { - .name = "gpio2_dbck", - .ops = &clkops_omap2_dflt, - .parent = &per_32k_alwon_fck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_GPIO2_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk wdt3_fck = { - .name = "wdt3_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_32k_alwon_fck, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_WDT3_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk per_l4_ick = { - .name = "per_l4_ick", - .ops = &clkops_null, - .parent = &l4_ick, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpio6_ick = { - .name = "gpio6_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPIO6_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpio5_ick = { - .name = "gpio5_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPIO5_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpio4_ick = { - .name = "gpio4_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPIO4_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpio3_ick = { - .name = "gpio3_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPIO3_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpio2_ick = { - .name = "gpio2_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPIO2_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk wdt3_ick = { - .name = "wdt3_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_WDT3_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk uart3_ick = { - .name = "uart3_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_UART3_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpt9_ick = { - .name = "gpt9_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPT9_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpt8_ick = { - .name = "gpt8_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPT8_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpt7_ick = { - .name = "gpt7_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPT7_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpt6_ick = { - .name = "gpt6_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPT6_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpt5_ick = { - .name = "gpt5_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPT5_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpt4_ick = { - .name = "gpt4_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPT4_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpt3_ick = { - .name = "gpt3_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPT3_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk gpt2_ick = { - .name = "gpt2_ick", - .ops = &clkops_omap2_dflt_wait, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_GPT2_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mcbsp2_ick = { - .name = "mcbsp_ick", - .ops = &clkops_omap2_dflt_wait, - .id = 2, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_MCBSP2_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mcbsp3_ick = { - .name = "mcbsp_ick", - .ops = &clkops_omap2_dflt_wait, - .id = 3, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_MCBSP3_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk mcbsp4_ick = { - .name = "mcbsp_ick", - .ops = &clkops_omap2_dflt_wait, - .id = 4, - .parent = &per_l4_ick, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_MCBSP4_SHIFT, - .clkdm_name = "per_clkdm", - .recalc = &followparent_recalc, -}; - -static const struct clksel mcbsp_234_clksel[] = { - { .parent = &core_96m_fck, .rates = common_mcbsp_96m_rates }, - { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates }, - { .parent = NULL } -}; - -static struct clk mcbsp2_fck = { - .name = "mcbsp_fck", - .ops = &clkops_omap2_dflt_wait, - .id = 2, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_MCBSP2_SHIFT, - .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0), - .clksel_mask = OMAP2_MCBSP2_CLKS_MASK, - .clksel = mcbsp_234_clksel, - .clkdm_name = "per_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk mcbsp3_fck = { - .name = "mcbsp_fck", - .ops = &clkops_omap2_dflt_wait, - .id = 3, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_MCBSP3_SHIFT, - .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1), - .clksel_mask = OMAP2_MCBSP3_CLKS_MASK, - .clksel = mcbsp_234_clksel, - .clkdm_name = "per_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk mcbsp4_fck = { - .name = "mcbsp_fck", - .ops = &clkops_omap2_dflt_wait, - .id = 4, - .init = &omap2_init_clksel_parent, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_MCBSP4_SHIFT, - .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1), - .clksel_mask = OMAP2_MCBSP4_CLKS_MASK, - .clksel = mcbsp_234_clksel, - .clkdm_name = "per_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -/* EMU clocks */ - -/* More information: ARM Cortex-A8 Technical Reference Manual, sect 10.1 */ - -static const struct clksel_rate emu_src_sys_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 }, -}; - -static const struct clksel_rate emu_src_core_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 }, -}; - -static const struct clksel_rate emu_src_per_rates[] = { - { .div = 1, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 }, -}; - -static const struct clksel_rate emu_src_mpu_rates[] = { - { .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 0 }, -}; - -static const struct clksel emu_src_clksel[] = { - { .parent = &sys_ck, .rates = emu_src_sys_rates }, - { .parent = &emu_core_alwon_ck, .rates = emu_src_core_rates }, - { .parent = &emu_per_alwon_ck, .rates = emu_src_per_rates }, - { .parent = &emu_mpu_alwon_ck, .rates = emu_src_mpu_rates }, - { .parent = NULL }, -}; - -/* - * Like the clkout_src clocks, emu_src_clk is a virtual clock, existing only - * to switch the source of some of the EMU clocks. - * XXX Are there CLKEN bits for these EMU clks? + * Copyright (C) 2007-2009 Texas Instruments, Inc. + * Copyright (C) 2007-2009 Nokia Corporation */ -static struct clk emu_src_ck = { - .name = "emu_src_ck", - .ops = &clkops_null, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_MUX_CTRL_MASK, - .clksel = emu_src_clksel, - .clkdm_name = "emu_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static const struct clksel_rate pclk_emu_rates[] = { - { .div = 2, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 3, .val = 3, .flags = RATE_IN_343X }, - { .div = 4, .val = 4, .flags = RATE_IN_343X }, - { .div = 6, .val = 6, .flags = RATE_IN_343X }, - { .div = 0 }, -}; - -static const struct clksel pclk_emu_clksel[] = { - { .parent = &emu_src_ck, .rates = pclk_emu_rates }, - { .parent = NULL }, -}; - -static struct clk pclk_fck = { - .name = "pclk_fck", - .ops = &clkops_null, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_CLKSEL_PCLK_MASK, - .clksel = pclk_emu_clksel, - .clkdm_name = "emu_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static const struct clksel_rate pclkx2_emu_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 2, .val = 2, .flags = RATE_IN_343X }, - { .div = 3, .val = 3, .flags = RATE_IN_343X }, - { .div = 0 }, -}; - -static const struct clksel pclkx2_emu_clksel[] = { - { .parent = &emu_src_ck, .rates = pclkx2_emu_rates }, - { .parent = NULL }, -}; - -static struct clk pclkx2_fck = { - .name = "pclkx2_fck", - .ops = &clkops_null, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_CLKSEL_PCLKX2_MASK, - .clksel = pclkx2_emu_clksel, - .clkdm_name = "emu_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static const struct clksel atclk_emu_clksel[] = { - { .parent = &emu_src_ck, .rates = div2_rates }, - { .parent = NULL }, -}; - -static struct clk atclk_fck = { - .name = "atclk_fck", - .ops = &clkops_null, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_CLKSEL_ATCLK_MASK, - .clksel = atclk_emu_clksel, - .clkdm_name = "emu_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static struct clk traceclk_src_fck = { - .name = "traceclk_src_fck", - .ops = &clkops_null, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_TRACE_MUX_CTRL_MASK, - .clksel = emu_src_clksel, - .clkdm_name = "emu_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -static const struct clksel_rate traceclk_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, - { .div = 2, .val = 2, .flags = RATE_IN_343X }, - { .div = 4, .val = 4, .flags = RATE_IN_343X }, - { .div = 0 }, -}; - -static const struct clksel traceclk_clksel[] = { - { .parent = &traceclk_src_fck, .rates = traceclk_rates }, - { .parent = NULL }, -}; - -static struct clk traceclk_fck = { - .name = "traceclk_fck", - .ops = &clkops_null, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_CLKSEL_TRACECLK_MASK, - .clksel = traceclk_clksel, - .clkdm_name = "emu_clkdm", - .recalc = &omap2_clksel_recalc, -}; - -/* SR clocks */ - -/* SmartReflex fclk (VDD1) */ -static struct clk sr1_fck = { - .name = "sr1_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &sys_ck, - .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_SR1_SHIFT, - .recalc = &followparent_recalc, -}; - -/* SmartReflex fclk (VDD2) */ -static struct clk sr2_fck = { - .name = "sr2_fck", - .ops = &clkops_omap2_dflt_wait, - .parent = &sys_ck, - .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), - .enable_bit = OMAP3430_EN_SR2_SHIFT, - .recalc = &followparent_recalc, -}; -static struct clk sr_l4_ick = { - .name = "sr_l4_ick", - .ops = &clkops_null, /* RMK: missing? */ - .parent = &l4_ick, - .clkdm_name = "core_l4_clkdm", - .recalc = &followparent_recalc, -}; +#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK_34XX_H +#define __ARCH_ARM_MACH_OMAP2_CLOCK_34XX_H -/* SECURE_32K_FCK clocks */ +int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate); +int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate); +void omap3_clk_lock_dpll5(void); -static struct clk gpt12_fck = { - .name = "gpt12_fck", - .ops = &clkops_null, - .parent = &secure_32k_fck, - .recalc = &followparent_recalc, -}; +extern struct clk *sdrc_ick_p; +extern struct clk *arm_fck_p; -static struct clk wdt1_fck = { - .name = "wdt1_fck", - .ops = &clkops_null, - .parent = &secure_32k_fck, - .recalc = &followparent_recalc, -}; +/* OMAP34xx-specific clkops */ +extern const struct clkops clkops_omap3430es2_ssi_wait; +extern const struct clkops clkops_omap3430es2_hsotgusb_wait; +extern const struct clkops clkops_omap3430es2_dss_usbhost_wait; +extern const struct clkops clkops_noncore_dpll_ops; #endif diff --git a/arch/arm/mach-omap2/clock34xx_data.c b/arch/arm/mach-omap2/clock34xx_data.c new file mode 100644 index 0000000000000000000000000000000000000000..8bdcc9cc7f9af0e1b6d092374278fec743c23487 --- /dev/null +++ b/arch/arm/mach-omap2/clock34xx_data.c @@ -0,0 +1,3289 @@ +/* + * OMAP3 clock data + * + * Copyright (C) 2007-2009 Texas Instruments, Inc. + * Copyright (C) 2007-2009 Nokia Corporation + * + * Written by Paul Walmsley + * With many device clock fixes by Kevin Hilman and Jouni Högander + * DPLL bypass clock support added by Roman Tereshonkov + * + */ + +/* + * Virtual clocks are introduced as convenient tools. + * They are sources for other clocks and not supposed + * to be requested from drivers directly. + */ + +#include +#include +#include + +#include +#include + +#include "clock.h" +#include "clock34xx.h" +#include "cm.h" +#include "cm-regbits-34xx.h" +#include "prm.h" +#include "prm-regbits-34xx.h" + +/* + * clocks + */ + +#define OMAP_CM_REGADDR OMAP34XX_CM_REGADDR + +/* Maximum DPLL multiplier, divider values for OMAP3 */ +#define OMAP3_MAX_DPLL_MULT 2048 +#define OMAP3_MAX_DPLL_DIV 128 + +/* + * DPLL1 supplies clock to the MPU. + * DPLL2 supplies clock to the IVA2. + * DPLL3 supplies CORE domain clocks. + * DPLL4 supplies peripheral clocks. + * DPLL5 supplies other peripheral clocks (USBHOST, USIM). + */ + +/* Forward declarations for DPLL bypass clocks */ +static struct clk dpll1_fck; +static struct clk dpll2_fck; + +/* PRM CLOCKS */ + +/* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */ +static struct clk omap_32k_fck = { + .name = "omap_32k_fck", + .ops = &clkops_null, + .rate = 32768, + .flags = RATE_FIXED, +}; + +static struct clk secure_32k_fck = { + .name = "secure_32k_fck", + .ops = &clkops_null, + .rate = 32768, + .flags = RATE_FIXED, +}; + +/* Virtual source clocks for osc_sys_ck */ +static struct clk virt_12m_ck = { + .name = "virt_12m_ck", + .ops = &clkops_null, + .rate = 12000000, + .flags = RATE_FIXED, +}; + +static struct clk virt_13m_ck = { + .name = "virt_13m_ck", + .ops = &clkops_null, + .rate = 13000000, + .flags = RATE_FIXED, +}; + +static struct clk virt_16_8m_ck = { + .name = "virt_16_8m_ck", + .ops = &clkops_null, + .rate = 16800000, + .flags = RATE_FIXED, +}; + +static struct clk virt_19_2m_ck = { + .name = "virt_19_2m_ck", + .ops = &clkops_null, + .rate = 19200000, + .flags = RATE_FIXED, +}; + +static struct clk virt_26m_ck = { + .name = "virt_26m_ck", + .ops = &clkops_null, + .rate = 26000000, + .flags = RATE_FIXED, +}; + +static struct clk virt_38_4m_ck = { + .name = "virt_38_4m_ck", + .ops = &clkops_null, + .rate = 38400000, + .flags = RATE_FIXED, +}; + +static const struct clksel_rate osc_sys_12m_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel_rate osc_sys_13m_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel_rate osc_sys_16_8m_rates[] = { + { .div = 1, .val = 5, .flags = RATE_IN_3430ES2 | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel_rate osc_sys_19_2m_rates[] = { + { .div = 1, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel_rate osc_sys_26m_rates[] = { + { .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel_rate osc_sys_38_4m_rates[] = { + { .div = 1, .val = 4, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel osc_sys_clksel[] = { + { .parent = &virt_12m_ck, .rates = osc_sys_12m_rates }, + { .parent = &virt_13m_ck, .rates = osc_sys_13m_rates }, + { .parent = &virt_16_8m_ck, .rates = osc_sys_16_8m_rates }, + { .parent = &virt_19_2m_ck, .rates = osc_sys_19_2m_rates }, + { .parent = &virt_26m_ck, .rates = osc_sys_26m_rates }, + { .parent = &virt_38_4m_ck, .rates = osc_sys_38_4m_rates }, + { .parent = NULL }, +}; + +/* Oscillator clock */ +/* 12, 13, 16.8, 19.2, 26, or 38.4 MHz */ +static struct clk osc_sys_ck = { + .name = "osc_sys_ck", + .ops = &clkops_null, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP3430_PRM_CLKSEL, + .clksel_mask = OMAP3430_SYS_CLKIN_SEL_MASK, + .clksel = osc_sys_clksel, + /* REVISIT: deal with autoextclkmode? */ + .flags = RATE_FIXED, + .recalc = &omap2_clksel_recalc, +}; + +static const struct clksel_rate div2_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 2, .val = 2, .flags = RATE_IN_343X }, + { .div = 0 } +}; + +static const struct clksel sys_clksel[] = { + { .parent = &osc_sys_ck, .rates = div2_rates }, + { .parent = NULL } +}; + +/* Latency: this clock is only enabled after PRM_CLKSETUP.SETUP_TIME */ +/* Feeds DPLLs - divided first by PRM_CLKSRC_CTRL.SYSCLKDIV? */ +static struct clk sys_ck = { + .name = "sys_ck", + .ops = &clkops_null, + .parent = &osc_sys_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP3430_PRM_CLKSRC_CTRL, + .clksel_mask = OMAP_SYSCLKDIV_MASK, + .clksel = sys_clksel, + .recalc = &omap2_clksel_recalc, +}; + +static struct clk sys_altclk = { + .name = "sys_altclk", + .ops = &clkops_null, +}; + +/* Optional external clock input for some McBSPs */ +static struct clk mcbsp_clks = { + .name = "mcbsp_clks", + .ops = &clkops_null, +}; + +/* PRM EXTERNAL CLOCK OUTPUT */ + +static struct clk sys_clkout1 = { + .name = "sys_clkout1", + .ops = &clkops_omap2_dflt, + .parent = &osc_sys_ck, + .enable_reg = OMAP3430_PRM_CLKOUT_CTRL, + .enable_bit = OMAP3430_CLKOUT_EN_SHIFT, + .recalc = &followparent_recalc, +}; + +/* DPLLS */ + +/* CM CLOCKS */ + +static const struct clksel_rate div16_dpll_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 2, .val = 2, .flags = RATE_IN_343X }, + { .div = 3, .val = 3, .flags = RATE_IN_343X }, + { .div = 4, .val = 4, .flags = RATE_IN_343X }, + { .div = 5, .val = 5, .flags = RATE_IN_343X }, + { .div = 6, .val = 6, .flags = RATE_IN_343X }, + { .div = 7, .val = 7, .flags = RATE_IN_343X }, + { .div = 8, .val = 8, .flags = RATE_IN_343X }, + { .div = 9, .val = 9, .flags = RATE_IN_343X }, + { .div = 10, .val = 10, .flags = RATE_IN_343X }, + { .div = 11, .val = 11, .flags = RATE_IN_343X }, + { .div = 12, .val = 12, .flags = RATE_IN_343X }, + { .div = 13, .val = 13, .flags = RATE_IN_343X }, + { .div = 14, .val = 14, .flags = RATE_IN_343X }, + { .div = 15, .val = 15, .flags = RATE_IN_343X }, + { .div = 16, .val = 16, .flags = RATE_IN_343X }, + { .div = 0 } +}; + +/* DPLL1 */ +/* MPU clock source */ +/* Type: DPLL */ +static struct dpll_data dpll1_dd = { + .mult_div1_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL), + .mult_mask = OMAP3430_MPU_DPLL_MULT_MASK, + .div1_mask = OMAP3430_MPU_DPLL_DIV_MASK, + .clk_bypass = &dpll1_fck, + .clk_ref = &sys_ck, + .freqsel_mask = OMAP3430_MPU_DPLL_FREQSEL_MASK, + .control_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL), + .enable_mask = OMAP3430_EN_MPU_DPLL_MASK, + .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), + .auto_recal_bit = OMAP3430_EN_MPU_DPLL_DRIFTGUARD_SHIFT, + .recal_en_bit = OMAP3430_MPU_DPLL_RECAL_EN_SHIFT, + .recal_st_bit = OMAP3430_MPU_DPLL_ST_SHIFT, + .autoidle_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL), + .autoidle_mask = OMAP3430_AUTO_MPU_DPLL_MASK, + .idlest_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), + .idlest_mask = OMAP3430_ST_MPU_CLK_MASK, + .max_multiplier = OMAP3_MAX_DPLL_MULT, + .min_divider = 1, + .max_divider = OMAP3_MAX_DPLL_DIV, + .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE +}; + +static struct clk dpll1_ck = { + .name = "dpll1_ck", + .ops = &clkops_null, + .parent = &sys_ck, + .dpll_data = &dpll1_dd, + .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, + .clkdm_name = "dpll1_clkdm", + .recalc = &omap3_dpll_recalc, +}; + +/* + * This virtual clock provides the CLKOUTX2 output from the DPLL if the + * DPLL isn't bypassed. + */ +static struct clk dpll1_x2_ck = { + .name = "dpll1_x2_ck", + .ops = &clkops_null, + .parent = &dpll1_ck, + .clkdm_name = "dpll1_clkdm", + .recalc = &omap3_clkoutx2_recalc, +}; + +/* On DPLL1, unlike other DPLLs, the divider is downstream from CLKOUTX2 */ +static const struct clksel div16_dpll1_x2m2_clksel[] = { + { .parent = &dpll1_x2_ck, .rates = div16_dpll_rates }, + { .parent = NULL } +}; + +/* + * Does not exist in the TRM - needed to separate the M2 divider from + * bypass selection in mpu_ck + */ +static struct clk dpll1_x2m2_ck = { + .name = "dpll1_x2m2_ck", + .ops = &clkops_null, + .parent = &dpll1_x2_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), + .clksel_mask = OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK, + .clksel = div16_dpll1_x2m2_clksel, + .clkdm_name = "dpll1_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +/* DPLL2 */ +/* IVA2 clock source */ +/* Type: DPLL */ + +static struct dpll_data dpll2_dd = { + .mult_div1_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL), + .mult_mask = OMAP3430_IVA2_DPLL_MULT_MASK, + .div1_mask = OMAP3430_IVA2_DPLL_DIV_MASK, + .clk_bypass = &dpll2_fck, + .clk_ref = &sys_ck, + .freqsel_mask = OMAP3430_IVA2_DPLL_FREQSEL_MASK, + .control_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL), + .enable_mask = OMAP3430_EN_IVA2_DPLL_MASK, + .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED) | + (1 << DPLL_LOW_POWER_BYPASS), + .auto_recal_bit = OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_SHIFT, + .recal_en_bit = OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN_SHIFT, + .recal_st_bit = OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST_SHIFT, + .autoidle_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL), + .autoidle_mask = OMAP3430_AUTO_IVA2_DPLL_MASK, + .idlest_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL), + .idlest_mask = OMAP3430_ST_IVA2_CLK_MASK, + .max_multiplier = OMAP3_MAX_DPLL_MULT, + .min_divider = 1, + .max_divider = OMAP3_MAX_DPLL_DIV, + .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE +}; + +static struct clk dpll2_ck = { + .name = "dpll2_ck", + .ops = &clkops_noncore_dpll_ops, + .parent = &sys_ck, + .dpll_data = &dpll2_dd, + .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, + .clkdm_name = "dpll2_clkdm", + .recalc = &omap3_dpll_recalc, +}; + +static const struct clksel div16_dpll2_m2x2_clksel[] = { + { .parent = &dpll2_ck, .rates = div16_dpll_rates }, + { .parent = NULL } +}; + +/* + * The TRM is conflicted on whether IVA2 clock comes from DPLL2 CLKOUT + * or CLKOUTX2. CLKOUT seems most plausible. + */ +static struct clk dpll2_m2_ck = { + .name = "dpll2_m2_ck", + .ops = &clkops_null, + .parent = &dpll2_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, + OMAP3430_CM_CLKSEL2_PLL), + .clksel_mask = OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK, + .clksel = div16_dpll2_m2x2_clksel, + .clkdm_name = "dpll2_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +/* + * DPLL3 + * Source clock for all interfaces and for some device fclks + * REVISIT: Also supports fast relock bypass - not included below + */ +static struct dpll_data dpll3_dd = { + .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), + .mult_mask = OMAP3430_CORE_DPLL_MULT_MASK, + .div1_mask = OMAP3430_CORE_DPLL_DIV_MASK, + .clk_bypass = &sys_ck, + .clk_ref = &sys_ck, + .freqsel_mask = OMAP3430_CORE_DPLL_FREQSEL_MASK, + .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), + .enable_mask = OMAP3430_EN_CORE_DPLL_MASK, + .auto_recal_bit = OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT, + .recal_en_bit = OMAP3430_CORE_DPLL_RECAL_EN_SHIFT, + .recal_st_bit = OMAP3430_CORE_DPLL_ST_SHIFT, + .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE), + .autoidle_mask = OMAP3430_AUTO_CORE_DPLL_MASK, + .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), + .idlest_mask = OMAP3430_ST_CORE_CLK_MASK, + .max_multiplier = OMAP3_MAX_DPLL_MULT, + .min_divider = 1, + .max_divider = OMAP3_MAX_DPLL_DIV, + .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE +}; + +static struct clk dpll3_ck = { + .name = "dpll3_ck", + .ops = &clkops_null, + .parent = &sys_ck, + .dpll_data = &dpll3_dd, + .round_rate = &omap2_dpll_round_rate, + .clkdm_name = "dpll3_clkdm", + .recalc = &omap3_dpll_recalc, +}; + +/* + * This virtual clock provides the CLKOUTX2 output from the DPLL if the + * DPLL isn't bypassed + */ +static struct clk dpll3_x2_ck = { + .name = "dpll3_x2_ck", + .ops = &clkops_null, + .parent = &dpll3_ck, + .clkdm_name = "dpll3_clkdm", + .recalc = &omap3_clkoutx2_recalc, +}; + +static const struct clksel_rate div31_dpll3_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 2, .val = 2, .flags = RATE_IN_343X }, + { .div = 3, .val = 3, .flags = RATE_IN_3430ES2 }, + { .div = 4, .val = 4, .flags = RATE_IN_3430ES2 }, + { .div = 5, .val = 5, .flags = RATE_IN_3430ES2 }, + { .div = 6, .val = 6, .flags = RATE_IN_3430ES2 }, + { .div = 7, .val = 7, .flags = RATE_IN_3430ES2 }, + { .div = 8, .val = 8, .flags = RATE_IN_3430ES2 }, + { .div = 9, .val = 9, .flags = RATE_IN_3430ES2 }, + { .div = 10, .val = 10, .flags = RATE_IN_3430ES2 }, + { .div = 11, .val = 11, .flags = RATE_IN_3430ES2 }, + { .div = 12, .val = 12, .flags = RATE_IN_3430ES2 }, + { .div = 13, .val = 13, .flags = RATE_IN_3430ES2 }, + { .div = 14, .val = 14, .flags = RATE_IN_3430ES2 }, + { .div = 15, .val = 15, .flags = RATE_IN_3430ES2 }, + { .div = 16, .val = 16, .flags = RATE_IN_3430ES2 }, + { .div = 17, .val = 17, .flags = RATE_IN_3430ES2 }, + { .div = 18, .val = 18, .flags = RATE_IN_3430ES2 }, + { .div = 19, .val = 19, .flags = RATE_IN_3430ES2 }, + { .div = 20, .val = 20, .flags = RATE_IN_3430ES2 }, + { .div = 21, .val = 21, .flags = RATE_IN_3430ES2 }, + { .div = 22, .val = 22, .flags = RATE_IN_3430ES2 }, + { .div = 23, .val = 23, .flags = RATE_IN_3430ES2 }, + { .div = 24, .val = 24, .flags = RATE_IN_3430ES2 }, + { .div = 25, .val = 25, .flags = RATE_IN_3430ES2 }, + { .div = 26, .val = 26, .flags = RATE_IN_3430ES2 }, + { .div = 27, .val = 27, .flags = RATE_IN_3430ES2 }, + { .div = 28, .val = 28, .flags = RATE_IN_3430ES2 }, + { .div = 29, .val = 29, .flags = RATE_IN_3430ES2 }, + { .div = 30, .val = 30, .flags = RATE_IN_3430ES2 }, + { .div = 31, .val = 31, .flags = RATE_IN_3430ES2 }, + { .div = 0 }, +}; + +static const struct clksel div31_dpll3m2_clksel[] = { + { .parent = &dpll3_ck, .rates = div31_dpll3_rates }, + { .parent = NULL } +}; + +/* DPLL3 output M2 - primary control point for CORE speed */ +static struct clk dpll3_m2_ck = { + .name = "dpll3_m2_ck", + .ops = &clkops_null, + .parent = &dpll3_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), + .clksel_mask = OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK, + .clksel = div31_dpll3m2_clksel, + .clkdm_name = "dpll3_clkdm", + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap3_core_dpll_m2_set_rate, + .recalc = &omap2_clksel_recalc, +}; + +static struct clk core_ck = { + .name = "core_ck", + .ops = &clkops_null, + .parent = &dpll3_m2_ck, + .recalc = &followparent_recalc, +}; + +static struct clk dpll3_m2x2_ck = { + .name = "dpll3_m2x2_ck", + .ops = &clkops_null, + .parent = &dpll3_m2_ck, + .clkdm_name = "dpll3_clkdm", + .recalc = &omap3_clkoutx2_recalc, +}; + +/* The PWRDN bit is apparently only available on 3430ES2 and above */ +static const struct clksel div16_dpll3_clksel[] = { + { .parent = &dpll3_ck, .rates = div16_dpll_rates }, + { .parent = NULL } +}; + +/* This virtual clock is the source for dpll3_m3x2_ck */ +static struct clk dpll3_m3_ck = { + .name = "dpll3_m3_ck", + .ops = &clkops_null, + .parent = &dpll3_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), + .clksel_mask = OMAP3430_DIV_DPLL3_MASK, + .clksel = div16_dpll3_clksel, + .clkdm_name = "dpll3_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +/* The PWRDN bit is apparently only available on 3430ES2 and above */ +static struct clk dpll3_m3x2_ck = { + .name = "dpll3_m3x2_ck", + .ops = &clkops_omap2_dflt_wait, + .parent = &dpll3_m3_ck, + .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), + .enable_bit = OMAP3430_PWRDN_EMU_CORE_SHIFT, + .flags = INVERT_ENABLE, + .clkdm_name = "dpll3_clkdm", + .recalc = &omap3_clkoutx2_recalc, +}; + +static struct clk emu_core_alwon_ck = { + .name = "emu_core_alwon_ck", + .ops = &clkops_null, + .parent = &dpll3_m3x2_ck, + .clkdm_name = "dpll3_clkdm", + .recalc = &followparent_recalc, +}; + +/* DPLL4 */ +/* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */ +/* Type: DPLL */ +static struct dpll_data dpll4_dd = { + .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2), + .mult_mask = OMAP3430_PERIPH_DPLL_MULT_MASK, + .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK, + .clk_bypass = &sys_ck, + .clk_ref = &sys_ck, + .freqsel_mask = OMAP3430_PERIPH_DPLL_FREQSEL_MASK, + .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), + .enable_mask = OMAP3430_EN_PERIPH_DPLL_MASK, + .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), + .auto_recal_bit = OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT, + .recal_en_bit = OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT, + .recal_st_bit = OMAP3430_PERIPH_DPLL_ST_SHIFT, + .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE), + .autoidle_mask = OMAP3430_AUTO_PERIPH_DPLL_MASK, + .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), + .idlest_mask = OMAP3430_ST_PERIPH_CLK_MASK, + .max_multiplier = OMAP3_MAX_DPLL_MULT, + .min_divider = 1, + .max_divider = OMAP3_MAX_DPLL_DIV, + .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE +}; + +static struct clk dpll4_ck = { + .name = "dpll4_ck", + .ops = &clkops_noncore_dpll_ops, + .parent = &sys_ck, + .dpll_data = &dpll4_dd, + .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_dpll4_set_rate, + .clkdm_name = "dpll4_clkdm", + .recalc = &omap3_dpll_recalc, +}; + +/* + * This virtual clock provides the CLKOUTX2 output from the DPLL if the + * DPLL isn't bypassed -- + * XXX does this serve any downstream clocks? + */ +static struct clk dpll4_x2_ck = { + .name = "dpll4_x2_ck", + .ops = &clkops_null, + .parent = &dpll4_ck, + .clkdm_name = "dpll4_clkdm", + .recalc = &omap3_clkoutx2_recalc, +}; + +static const struct clksel div16_dpll4_clksel[] = { + { .parent = &dpll4_ck, .rates = div16_dpll_rates }, + { .parent = NULL } +}; + +/* This virtual clock is the source for dpll4_m2x2_ck */ +static struct clk dpll4_m2_ck = { + .name = "dpll4_m2_ck", + .ops = &clkops_null, + .parent = &dpll4_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3), + .clksel_mask = OMAP3430_DIV_96M_MASK, + .clksel = div16_dpll4_clksel, + .clkdm_name = "dpll4_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +/* The PWRDN bit is apparently only available on 3430ES2 and above */ +static struct clk dpll4_m2x2_ck = { + .name = "dpll4_m2x2_ck", + .ops = &clkops_omap2_dflt_wait, + .parent = &dpll4_m2_ck, + .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), + .enable_bit = OMAP3430_PWRDN_96M_SHIFT, + .flags = INVERT_ENABLE, + .clkdm_name = "dpll4_clkdm", + .recalc = &omap3_clkoutx2_recalc, +}; + +/* + * DPLL4 generates DPLL4_M2X2_CLK which is then routed into the PRM as + * PRM_96M_ALWON_(F)CLK. Two clocks then emerge from the PRM: + * 96M_ALWON_FCLK (called "omap_96m_alwon_fck" below) and + * CM_96K_(F)CLK. + */ +static struct clk omap_96m_alwon_fck = { + .name = "omap_96m_alwon_fck", + .ops = &clkops_null, + .parent = &dpll4_m2x2_ck, + .recalc = &followparent_recalc, +}; + +static struct clk cm_96m_fck = { + .name = "cm_96m_fck", + .ops = &clkops_null, + .parent = &omap_96m_alwon_fck, + .recalc = &followparent_recalc, +}; + +static const struct clksel_rate omap_96m_dpll_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel_rate omap_96m_sys_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel omap_96m_fck_clksel[] = { + { .parent = &cm_96m_fck, .rates = omap_96m_dpll_rates }, + { .parent = &sys_ck, .rates = omap_96m_sys_rates }, + { .parent = NULL } +}; + +static struct clk omap_96m_fck = { + .name = "omap_96m_fck", + .ops = &clkops_null, + .parent = &sys_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), + .clksel_mask = OMAP3430_SOURCE_96M_MASK, + .clksel = omap_96m_fck_clksel, + .recalc = &omap2_clksel_recalc, +}; + +/* This virtual clock is the source for dpll4_m3x2_ck */ +static struct clk dpll4_m3_ck = { + .name = "dpll4_m3_ck", + .ops = &clkops_null, + .parent = &dpll4_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_TV_MASK, + .clksel = div16_dpll4_clksel, + .clkdm_name = "dpll4_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +/* The PWRDN bit is apparently only available on 3430ES2 and above */ +static struct clk dpll4_m3x2_ck = { + .name = "dpll4_m3x2_ck", + .ops = &clkops_omap2_dflt_wait, + .parent = &dpll4_m3_ck, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), + .enable_bit = OMAP3430_PWRDN_TV_SHIFT, + .flags = INVERT_ENABLE, + .clkdm_name = "dpll4_clkdm", + .recalc = &omap3_clkoutx2_recalc, +}; + +static const struct clksel_rate omap_54m_d4m3x2_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel_rate omap_54m_alt_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel omap_54m_clksel[] = { + { .parent = &dpll4_m3x2_ck, .rates = omap_54m_d4m3x2_rates }, + { .parent = &sys_altclk, .rates = omap_54m_alt_rates }, + { .parent = NULL } +}; + +static struct clk omap_54m_fck = { + .name = "omap_54m_fck", + .ops = &clkops_null, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), + .clksel_mask = OMAP3430_SOURCE_54M_MASK, + .clksel = omap_54m_clksel, + .recalc = &omap2_clksel_recalc, +}; + +static const struct clksel_rate omap_48m_cm96m_rates[] = { + { .div = 2, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel_rate omap_48m_alt_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel omap_48m_clksel[] = { + { .parent = &cm_96m_fck, .rates = omap_48m_cm96m_rates }, + { .parent = &sys_altclk, .rates = omap_48m_alt_rates }, + { .parent = NULL } +}; + +static struct clk omap_48m_fck = { + .name = "omap_48m_fck", + .ops = &clkops_null, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), + .clksel_mask = OMAP3430_SOURCE_48M_MASK, + .clksel = omap_48m_clksel, + .recalc = &omap2_clksel_recalc, +}; + +static struct clk omap_12m_fck = { + .name = "omap_12m_fck", + .ops = &clkops_null, + .parent = &omap_48m_fck, + .fixed_div = 4, + .recalc = &omap2_fixed_divisor_recalc, +}; + +/* This virstual clock is the source for dpll4_m4x2_ck */ +static struct clk dpll4_m4_ck = { + .name = "dpll4_m4_ck", + .ops = &clkops_null, + .parent = &dpll4_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_DSS1_MASK, + .clksel = div16_dpll4_clksel, + .clkdm_name = "dpll4_clkdm", + .recalc = &omap2_clksel_recalc, + .set_rate = &omap2_clksel_set_rate, + .round_rate = &omap2_clksel_round_rate, +}; + +/* The PWRDN bit is apparently only available on 3430ES2 and above */ +static struct clk dpll4_m4x2_ck = { + .name = "dpll4_m4x2_ck", + .ops = &clkops_omap2_dflt_wait, + .parent = &dpll4_m4_ck, + .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), + .enable_bit = OMAP3430_PWRDN_CAM_SHIFT, + .flags = INVERT_ENABLE, + .clkdm_name = "dpll4_clkdm", + .recalc = &omap3_clkoutx2_recalc, +}; + +/* This virtual clock is the source for dpll4_m5x2_ck */ +static struct clk dpll4_m5_ck = { + .name = "dpll4_m5_ck", + .ops = &clkops_null, + .parent = &dpll4_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_CAM_MASK, + .clksel = div16_dpll4_clksel, + .clkdm_name = "dpll4_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +/* The PWRDN bit is apparently only available on 3430ES2 and above */ +static struct clk dpll4_m5x2_ck = { + .name = "dpll4_m5x2_ck", + .ops = &clkops_omap2_dflt_wait, + .parent = &dpll4_m5_ck, + .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), + .enable_bit = OMAP3430_PWRDN_CAM_SHIFT, + .flags = INVERT_ENABLE, + .clkdm_name = "dpll4_clkdm", + .recalc = &omap3_clkoutx2_recalc, +}; + +/* This virtual clock is the source for dpll4_m6x2_ck */ +static struct clk dpll4_m6_ck = { + .name = "dpll4_m6_ck", + .ops = &clkops_null, + .parent = &dpll4_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), + .clksel_mask = OMAP3430_DIV_DPLL4_MASK, + .clksel = div16_dpll4_clksel, + .clkdm_name = "dpll4_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +/* The PWRDN bit is apparently only available on 3430ES2 and above */ +static struct clk dpll4_m6x2_ck = { + .name = "dpll4_m6x2_ck", + .ops = &clkops_omap2_dflt_wait, + .parent = &dpll4_m6_ck, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), + .enable_bit = OMAP3430_PWRDN_EMU_PERIPH_SHIFT, + .flags = INVERT_ENABLE, + .clkdm_name = "dpll4_clkdm", + .recalc = &omap3_clkoutx2_recalc, +}; + +static struct clk emu_per_alwon_ck = { + .name = "emu_per_alwon_ck", + .ops = &clkops_null, + .parent = &dpll4_m6x2_ck, + .clkdm_name = "dpll4_clkdm", + .recalc = &followparent_recalc, +}; + +/* DPLL5 */ +/* Supplies 120MHz clock, USIM source clock */ +/* Type: DPLL */ +/* 3430ES2 only */ +static struct dpll_data dpll5_dd = { + .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4), + .mult_mask = OMAP3430ES2_PERIPH2_DPLL_MULT_MASK, + .div1_mask = OMAP3430ES2_PERIPH2_DPLL_DIV_MASK, + .clk_bypass = &sys_ck, + .clk_ref = &sys_ck, + .freqsel_mask = OMAP3430ES2_PERIPH2_DPLL_FREQSEL_MASK, + .control_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKEN2), + .enable_mask = OMAP3430ES2_EN_PERIPH2_DPLL_MASK, + .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), + .auto_recal_bit = OMAP3430ES2_EN_PERIPH2_DPLL_DRIFTGUARD_SHIFT, + .recal_en_bit = OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_SHIFT, + .recal_st_bit = OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT, + .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_AUTOIDLE2_PLL), + .autoidle_mask = OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK, + .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2), + .idlest_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK, + .max_multiplier = OMAP3_MAX_DPLL_MULT, + .min_divider = 1, + .max_divider = OMAP3_MAX_DPLL_DIV, + .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE +}; + +static struct clk dpll5_ck = { + .name = "dpll5_ck", + .ops = &clkops_noncore_dpll_ops, + .parent = &sys_ck, + .dpll_data = &dpll5_dd, + .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, + .clkdm_name = "dpll5_clkdm", + .recalc = &omap3_dpll_recalc, +}; + +static const struct clksel div16_dpll5_clksel[] = { + { .parent = &dpll5_ck, .rates = div16_dpll_rates }, + { .parent = NULL } +}; + +static struct clk dpll5_m2_ck = { + .name = "dpll5_m2_ck", + .ops = &clkops_null, + .parent = &dpll5_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5), + .clksel_mask = OMAP3430ES2_DIV_120M_MASK, + .clksel = div16_dpll5_clksel, + .clkdm_name = "dpll5_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +/* CM EXTERNAL CLOCK OUTPUTS */ + +static const struct clksel_rate clkout2_src_core_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel_rate clkout2_src_sys_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel_rate clkout2_src_96m_rates[] = { + { .div = 1, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel_rate clkout2_src_54m_rates[] = { + { .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel clkout2_src_clksel[] = { + { .parent = &core_ck, .rates = clkout2_src_core_rates }, + { .parent = &sys_ck, .rates = clkout2_src_sys_rates }, + { .parent = &cm_96m_fck, .rates = clkout2_src_96m_rates }, + { .parent = &omap_54m_fck, .rates = clkout2_src_54m_rates }, + { .parent = NULL } +}; + +static struct clk clkout2_src_ck = { + .name = "clkout2_src_ck", + .ops = &clkops_omap2_dflt, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP3430_CM_CLKOUT_CTRL, + .enable_bit = OMAP3430_CLKOUT2_EN_SHIFT, + .clksel_reg = OMAP3430_CM_CLKOUT_CTRL, + .clksel_mask = OMAP3430_CLKOUT2SOURCE_MASK, + .clksel = clkout2_src_clksel, + .clkdm_name = "core_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static const struct clksel_rate sys_clkout2_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 2, .val = 1, .flags = RATE_IN_343X }, + { .div = 4, .val = 2, .flags = RATE_IN_343X }, + { .div = 8, .val = 3, .flags = RATE_IN_343X }, + { .div = 16, .val = 4, .flags = RATE_IN_343X }, + { .div = 0 }, +}; + +static const struct clksel sys_clkout2_clksel[] = { + { .parent = &clkout2_src_ck, .rates = sys_clkout2_rates }, + { .parent = NULL }, +}; + +static struct clk sys_clkout2 = { + .name = "sys_clkout2", + .ops = &clkops_null, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP3430_CM_CLKOUT_CTRL, + .clksel_mask = OMAP3430_CLKOUT2_DIV_MASK, + .clksel = sys_clkout2_clksel, + .recalc = &omap2_clksel_recalc, +}; + +/* CM OUTPUT CLOCKS */ + +static struct clk corex2_fck = { + .name = "corex2_fck", + .ops = &clkops_null, + .parent = &dpll3_m2x2_ck, + .recalc = &followparent_recalc, +}; + +/* DPLL power domain clock controls */ + +static const struct clksel_rate div4_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 2, .val = 2, .flags = RATE_IN_343X }, + { .div = 4, .val = 4, .flags = RATE_IN_343X }, + { .div = 0 } +}; + +static const struct clksel div4_core_clksel[] = { + { .parent = &core_ck, .rates = div4_rates }, + { .parent = NULL } +}; + +/* + * REVISIT: Are these in DPLL power domain or CM power domain? docs + * may be inconsistent here? + */ +static struct clk dpll1_fck = { + .name = "dpll1_fck", + .ops = &clkops_null, + .parent = &core_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL), + .clksel_mask = OMAP3430_MPU_CLK_SRC_MASK, + .clksel = div4_core_clksel, + .recalc = &omap2_clksel_recalc, +}; + +static struct clk mpu_ck = { + .name = "mpu_ck", + .ops = &clkops_null, + .parent = &dpll1_x2m2_ck, + .clkdm_name = "mpu_clkdm", + .recalc = &followparent_recalc, +}; + +/* arm_fck is divided by two when DPLL1 locked; otherwise, passthrough mpu_ck */ +static const struct clksel_rate arm_fck_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 2, .val = 1, .flags = RATE_IN_343X }, + { .div = 0 }, +}; + +static const struct clksel arm_fck_clksel[] = { + { .parent = &mpu_ck, .rates = arm_fck_rates }, + { .parent = NULL } +}; + +static struct clk arm_fck = { + .name = "arm_fck", + .ops = &clkops_null, + .parent = &mpu_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), + .clksel_mask = OMAP3430_ST_MPU_CLK_MASK, + .clksel = arm_fck_clksel, + .clkdm_name = "mpu_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +/* XXX What about neon_clkdm ? */ + +/* + * REVISIT: This clock is never specifically defined in the 3430 TRM, + * although it is referenced - so this is a guess + */ +static struct clk emu_mpu_alwon_ck = { + .name = "emu_mpu_alwon_ck", + .ops = &clkops_null, + .parent = &mpu_ck, + .recalc = &followparent_recalc, +}; + +static struct clk dpll2_fck = { + .name = "dpll2_fck", + .ops = &clkops_null, + .parent = &core_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL), + .clksel_mask = OMAP3430_IVA2_CLK_SRC_MASK, + .clksel = div4_core_clksel, + .recalc = &omap2_clksel_recalc, +}; + +static struct clk iva2_ck = { + .name = "iva2_ck", + .ops = &clkops_omap2_dflt_wait, + .parent = &dpll2_m2_ck, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT, + .clkdm_name = "iva2_clkdm", + .recalc = &followparent_recalc, +}; + +/* Common interface clocks */ + +static const struct clksel div2_core_clksel[] = { + { .parent = &core_ck, .rates = div2_rates }, + { .parent = NULL } +}; + +static struct clk l3_ick = { + .name = "l3_ick", + .ops = &clkops_null, + .parent = &core_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_L3_MASK, + .clksel = div2_core_clksel, + .clkdm_name = "core_l3_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static const struct clksel div2_l3_clksel[] = { + { .parent = &l3_ick, .rates = div2_rates }, + { .parent = NULL } +}; + +static struct clk l4_ick = { + .name = "l4_ick", + .ops = &clkops_null, + .parent = &l3_ick, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_L4_MASK, + .clksel = div2_l3_clksel, + .clkdm_name = "core_l4_clkdm", + .recalc = &omap2_clksel_recalc, + +}; + +static const struct clksel div2_l4_clksel[] = { + { .parent = &l4_ick, .rates = div2_rates }, + { .parent = NULL } +}; + +static struct clk rm_ick = { + .name = "rm_ick", + .ops = &clkops_null, + .parent = &l4_ick, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_RM_MASK, + .clksel = div2_l4_clksel, + .recalc = &omap2_clksel_recalc, +}; + +/* GFX power domain */ + +/* GFX clocks are in 3430ES1 only. 3430ES2 and later uses the SGX instead */ + +static const struct clksel gfx_l3_clksel[] = { + { .parent = &l3_ick, .rates = gfx_l3_rates }, + { .parent = NULL } +}; + +/* Virtual parent clock for gfx_l3_ick and gfx_l3_fck */ +static struct clk gfx_l3_ck = { + .name = "gfx_l3_ck", + .ops = &clkops_omap2_dflt_wait, + .parent = &l3_ick, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN), + .enable_bit = OMAP_EN_GFX_SHIFT, + .recalc = &followparent_recalc, +}; + +static struct clk gfx_l3_fck = { + .name = "gfx_l3_fck", + .ops = &clkops_null, + .parent = &gfx_l3_ck, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL), + .clksel_mask = OMAP_CLKSEL_GFX_MASK, + .clksel = gfx_l3_clksel, + .clkdm_name = "gfx_3430es1_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk gfx_l3_ick = { + .name = "gfx_l3_ick", + .ops = &clkops_null, + .parent = &gfx_l3_ck, + .clkdm_name = "gfx_3430es1_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gfx_cg1_ck = { + .name = "gfx_cg1_ck", + .ops = &clkops_omap2_dflt_wait, + .parent = &gfx_l3_fck, /* REVISIT: correct? */ + .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN), + .enable_bit = OMAP3430ES1_EN_2D_SHIFT, + .clkdm_name = "gfx_3430es1_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gfx_cg2_ck = { + .name = "gfx_cg2_ck", + .ops = &clkops_omap2_dflt_wait, + .parent = &gfx_l3_fck, /* REVISIT: correct? */ + .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN), + .enable_bit = OMAP3430ES1_EN_3D_SHIFT, + .clkdm_name = "gfx_3430es1_clkdm", + .recalc = &followparent_recalc, +}; + +/* SGX power domain - 3430ES2 only */ + +static const struct clksel_rate sgx_core_rates[] = { + { .div = 3, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 4, .val = 1, .flags = RATE_IN_343X }, + { .div = 6, .val = 2, .flags = RATE_IN_343X }, + { .div = 0 }, +}; + +static const struct clksel_rate sgx_96m_rates[] = { + { .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 }, +}; + +static const struct clksel sgx_clksel[] = { + { .parent = &core_ck, .rates = sgx_core_rates }, + { .parent = &cm_96m_fck, .rates = sgx_96m_rates }, + { .parent = NULL }, +}; + +static struct clk sgx_fck = { + .name = "sgx_fck", + .ops = &clkops_omap2_dflt_wait, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_FCLKEN), + .enable_bit = OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430ES2_CLKSEL_SGX_MASK, + .clksel = sgx_clksel, + .clkdm_name = "sgx_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk sgx_ick = { + .name = "sgx_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &l3_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN), + .enable_bit = OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_SHIFT, + .clkdm_name = "sgx_clkdm", + .recalc = &followparent_recalc, +}; + +/* CORE power domain */ + +static struct clk d2d_26m_fck = { + .name = "d2d_26m_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &sys_ck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430ES1_EN_D2D_SHIFT, + .clkdm_name = "d2d_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk modem_fck = { + .name = "modem_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &sys_ck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_MODEM_SHIFT, + .clkdm_name = "d2d_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk sad2d_ick = { + .name = "sad2d_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &l3_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_SAD2D_SHIFT, + .clkdm_name = "d2d_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mad2d_ick = { + .name = "mad2d_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &l3_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), + .enable_bit = OMAP3430_EN_MAD2D_SHIFT, + .clkdm_name = "d2d_clkdm", + .recalc = &followparent_recalc, +}; + +static const struct clksel omap343x_gpt_clksel[] = { + { .parent = &omap_32k_fck, .rates = gpt_32k_rates }, + { .parent = &sys_ck, .rates = gpt_sys_rates }, + { .parent = NULL} +}; + +static struct clk gpt10_fck = { + .name = "gpt10_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &sys_ck, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_GPT10_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_GPT10_MASK, + .clksel = omap343x_gpt_clksel, + .clkdm_name = "core_l4_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk gpt11_fck = { + .name = "gpt11_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &sys_ck, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_GPT11_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_GPT11_MASK, + .clksel = omap343x_gpt_clksel, + .clkdm_name = "core_l4_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk cpefuse_fck = { + .name = "cpefuse_fck", + .ops = &clkops_omap2_dflt, + .parent = &sys_ck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), + .enable_bit = OMAP3430ES2_EN_CPEFUSE_SHIFT, + .recalc = &followparent_recalc, +}; + +static struct clk ts_fck = { + .name = "ts_fck", + .ops = &clkops_omap2_dflt, + .parent = &omap_32k_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), + .enable_bit = OMAP3430ES2_EN_TS_SHIFT, + .recalc = &followparent_recalc, +}; + +static struct clk usbtll_fck = { + .name = "usbtll_fck", + .ops = &clkops_omap2_dflt, + .parent = &dpll5_m2_ck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), + .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT, + .recalc = &followparent_recalc, +}; + +/* CORE 96M FCLK-derived clocks */ + +static struct clk core_96m_fck = { + .name = "core_96m_fck", + .ops = &clkops_null, + .parent = &omap_96m_fck, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mmchs3_fck = { + .name = "mmchs_fck", + .ops = &clkops_omap2_dflt_wait, + .id = 2, + .parent = &core_96m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mmchs2_fck = { + .name = "mmchs_fck", + .ops = &clkops_omap2_dflt_wait, + .id = 1, + .parent = &core_96m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_MMC2_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mspro_fck = { + .name = "mspro_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_96m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_MSPRO_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mmchs1_fck = { + .name = "mmchs_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_96m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_MMC1_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk i2c3_fck = { + .name = "i2c_fck", + .ops = &clkops_omap2_dflt_wait, + .id = 3, + .parent = &core_96m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_I2C3_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk i2c2_fck = { + .name = "i2c_fck", + .ops = &clkops_omap2_dflt_wait, + .id = 2, + .parent = &core_96m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_I2C2_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk i2c1_fck = { + .name = "i2c_fck", + .ops = &clkops_omap2_dflt_wait, + .id = 1, + .parent = &core_96m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_I2C1_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +/* + * MCBSP 1 & 5 get their 96MHz clock from core_96m_fck; + * MCBSP 2, 3, 4 get their 96MHz clock from per_96m_fck. + */ +static const struct clksel_rate common_mcbsp_96m_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel_rate common_mcbsp_mcbsp_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel mcbsp_15_clksel[] = { + { .parent = &core_96m_fck, .rates = common_mcbsp_96m_rates }, + { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates }, + { .parent = NULL } +}; + +static struct clk mcbsp5_fck = { + .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, + .id = 5, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_MCBSP5_SHIFT, + .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1), + .clksel_mask = OMAP2_MCBSP5_CLKS_MASK, + .clksel = mcbsp_15_clksel, + .clkdm_name = "core_l4_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk mcbsp1_fck = { + .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, + .id = 1, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_MCBSP1_SHIFT, + .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0), + .clksel_mask = OMAP2_MCBSP1_CLKS_MASK, + .clksel = mcbsp_15_clksel, + .clkdm_name = "core_l4_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +/* CORE_48M_FCK-derived clocks */ + +static struct clk core_48m_fck = { + .name = "core_48m_fck", + .ops = &clkops_null, + .parent = &omap_48m_fck, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mcspi4_fck = { + .name = "mcspi_fck", + .ops = &clkops_omap2_dflt_wait, + .id = 4, + .parent = &core_48m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_MCSPI4_SHIFT, + .recalc = &followparent_recalc, +}; + +static struct clk mcspi3_fck = { + .name = "mcspi_fck", + .ops = &clkops_omap2_dflt_wait, + .id = 3, + .parent = &core_48m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_MCSPI3_SHIFT, + .recalc = &followparent_recalc, +}; + +static struct clk mcspi2_fck = { + .name = "mcspi_fck", + .ops = &clkops_omap2_dflt_wait, + .id = 2, + .parent = &core_48m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_MCSPI2_SHIFT, + .recalc = &followparent_recalc, +}; + +static struct clk mcspi1_fck = { + .name = "mcspi_fck", + .ops = &clkops_omap2_dflt_wait, + .id = 1, + .parent = &core_48m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_MCSPI1_SHIFT, + .recalc = &followparent_recalc, +}; + +static struct clk uart2_fck = { + .name = "uart2_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_48m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_UART2_SHIFT, + .recalc = &followparent_recalc, +}; + +static struct clk uart1_fck = { + .name = "uart1_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_48m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_UART1_SHIFT, + .recalc = &followparent_recalc, +}; + +static struct clk fshostusb_fck = { + .name = "fshostusb_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_48m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430ES1_EN_FSHOSTUSB_SHIFT, + .recalc = &followparent_recalc, +}; + +/* CORE_12M_FCK based clocks */ + +static struct clk core_12m_fck = { + .name = "core_12m_fck", + .ops = &clkops_null, + .parent = &omap_12m_fck, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk hdq_fck = { + .name = "hdq_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_12m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_HDQ_SHIFT, + .recalc = &followparent_recalc, +}; + +/* DPLL3-derived clock */ + +static const struct clksel_rate ssi_ssr_corex2_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 2, .val = 2, .flags = RATE_IN_343X }, + { .div = 3, .val = 3, .flags = RATE_IN_343X }, + { .div = 4, .val = 4, .flags = RATE_IN_343X }, + { .div = 6, .val = 6, .flags = RATE_IN_343X }, + { .div = 8, .val = 8, .flags = RATE_IN_343X }, + { .div = 0 } +}; + +static const struct clksel ssi_ssr_clksel[] = { + { .parent = &corex2_fck, .rates = ssi_ssr_corex2_rates }, + { .parent = NULL } +}; + +static struct clk ssi_ssr_fck_3430es1 = { + .name = "ssi_ssr_fck", + .ops = &clkops_omap2_dflt, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_SSI_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_SSI_MASK, + .clksel = ssi_ssr_clksel, + .clkdm_name = "core_l4_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk ssi_ssr_fck_3430es2 = { + .name = "ssi_ssr_fck", + .ops = &clkops_omap3430es2_ssi_wait, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_SSI_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_SSI_MASK, + .clksel = ssi_ssr_clksel, + .clkdm_name = "core_l4_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk ssi_sst_fck_3430es1 = { + .name = "ssi_sst_fck", + .ops = &clkops_null, + .parent = &ssi_ssr_fck_3430es1, + .fixed_div = 2, + .recalc = &omap2_fixed_divisor_recalc, +}; + +static struct clk ssi_sst_fck_3430es2 = { + .name = "ssi_sst_fck", + .ops = &clkops_null, + .parent = &ssi_ssr_fck_3430es2, + .fixed_div = 2, + .recalc = &omap2_fixed_divisor_recalc, +}; + + + +/* CORE_L3_ICK based clocks */ + +/* + * XXX must add clk_enable/clk_disable for these if standard code won't + * handle it + */ +static struct clk core_l3_ick = { + .name = "core_l3_ick", + .ops = &clkops_null, + .parent = &l3_ick, + .clkdm_name = "core_l3_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk hsotgusb_ick_3430es1 = { + .name = "hsotgusb_ick", + .ops = &clkops_omap2_dflt, + .parent = &core_l3_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT, + .clkdm_name = "core_l3_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk hsotgusb_ick_3430es2 = { + .name = "hsotgusb_ick", + .ops = &clkops_omap3430es2_hsotgusb_wait, + .parent = &core_l3_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT, + .clkdm_name = "core_l3_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk sdrc_ick = { + .name = "sdrc_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l3_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_SDRC_SHIFT, + .flags = ENABLE_ON_INIT, + .clkdm_name = "core_l3_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpmc_fck = { + .name = "gpmc_fck", + .ops = &clkops_null, + .parent = &core_l3_ick, + .flags = ENABLE_ON_INIT, /* huh? */ + .clkdm_name = "core_l3_clkdm", + .recalc = &followparent_recalc, +}; + +/* SECURITY_L3_ICK based clocks */ + +static struct clk security_l3_ick = { + .name = "security_l3_ick", + .ops = &clkops_null, + .parent = &l3_ick, + .recalc = &followparent_recalc, +}; + +static struct clk pka_ick = { + .name = "pka_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &security_l3_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), + .enable_bit = OMAP3430_EN_PKA_SHIFT, + .recalc = &followparent_recalc, +}; + +/* CORE_L4_ICK based clocks */ + +static struct clk core_l4_ick = { + .name = "core_l4_ick", + .ops = &clkops_null, + .parent = &l4_ick, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk usbtll_ick = { + .name = "usbtll_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), + .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mmchs3_ick = { + .name = "mmchs_ick", + .ops = &clkops_omap2_dflt_wait, + .id = 2, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +/* Intersystem Communication Registers - chassis mode only */ +static struct clk icr_ick = { + .name = "icr_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_ICR_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk aes2_ick = { + .name = "aes2_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_AES2_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk sha12_ick = { + .name = "sha12_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_SHA12_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk des2_ick = { + .name = "des2_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_DES2_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mmchs2_ick = { + .name = "mmchs_ick", + .ops = &clkops_omap2_dflt_wait, + .id = 1, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_MMC2_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mmchs1_ick = { + .name = "mmchs_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_MMC1_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mspro_ick = { + .name = "mspro_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_MSPRO_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk hdq_ick = { + .name = "hdq_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_HDQ_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mcspi4_ick = { + .name = "mcspi_ick", + .ops = &clkops_omap2_dflt_wait, + .id = 4, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_MCSPI4_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mcspi3_ick = { + .name = "mcspi_ick", + .ops = &clkops_omap2_dflt_wait, + .id = 3, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_MCSPI3_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mcspi2_ick = { + .name = "mcspi_ick", + .ops = &clkops_omap2_dflt_wait, + .id = 2, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_MCSPI2_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mcspi1_ick = { + .name = "mcspi_ick", + .ops = &clkops_omap2_dflt_wait, + .id = 1, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_MCSPI1_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk i2c3_ick = { + .name = "i2c_ick", + .ops = &clkops_omap2_dflt_wait, + .id = 3, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_I2C3_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk i2c2_ick = { + .name = "i2c_ick", + .ops = &clkops_omap2_dflt_wait, + .id = 2, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_I2C2_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk i2c1_ick = { + .name = "i2c_ick", + .ops = &clkops_omap2_dflt_wait, + .id = 1, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_I2C1_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk uart2_ick = { + .name = "uart2_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_UART2_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk uart1_ick = { + .name = "uart1_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_UART1_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpt11_ick = { + .name = "gpt11_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_GPT11_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpt10_ick = { + .name = "gpt10_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_GPT10_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mcbsp5_ick = { + .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, + .id = 5, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_MCBSP5_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mcbsp1_ick = { + .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, + .id = 1, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_MCBSP1_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk fac_ick = { + .name = "fac_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430ES1_EN_FAC_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mailboxes_ick = { + .name = "mailboxes_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_MAILBOXES_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk omapctrl_ick = { + .name = "omapctrl_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_OMAPCTRL_SHIFT, + .flags = ENABLE_ON_INIT, + .recalc = &followparent_recalc, +}; + +/* SSI_L4_ICK based clocks */ + +static struct clk ssi_l4_ick = { + .name = "ssi_l4_ick", + .ops = &clkops_null, + .parent = &l4_ick, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk ssi_ick_3430es1 = { + .name = "ssi_ick", + .ops = &clkops_omap2_dflt, + .parent = &ssi_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_SSI_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk ssi_ick_3430es2 = { + .name = "ssi_ick", + .ops = &clkops_omap3430es2_ssi_wait, + .parent = &ssi_l4_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_SSI_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +/* REVISIT: Technically the TRM claims that this is CORE_CLK based, + * but l4_ick makes more sense to me */ + +static const struct clksel usb_l4_clksel[] = { + { .parent = &l4_ick, .rates = div2_rates }, + { .parent = NULL }, +}; + +static struct clk usb_l4_ick = { + .name = "usb_l4_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &l4_ick, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430ES1_EN_FSHOSTUSB_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK, + .clksel = usb_l4_clksel, + .recalc = &omap2_clksel_recalc, +}; + +/* SECURITY_L4_ICK2 based clocks */ + +static struct clk security_l4_ick2 = { + .name = "security_l4_ick2", + .ops = &clkops_null, + .parent = &l4_ick, + .recalc = &followparent_recalc, +}; + +static struct clk aes1_ick = { + .name = "aes1_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &security_l4_ick2, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), + .enable_bit = OMAP3430_EN_AES1_SHIFT, + .recalc = &followparent_recalc, +}; + +static struct clk rng_ick = { + .name = "rng_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &security_l4_ick2, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), + .enable_bit = OMAP3430_EN_RNG_SHIFT, + .recalc = &followparent_recalc, +}; + +static struct clk sha11_ick = { + .name = "sha11_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &security_l4_ick2, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), + .enable_bit = OMAP3430_EN_SHA11_SHIFT, + .recalc = &followparent_recalc, +}; + +static struct clk des1_ick = { + .name = "des1_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &security_l4_ick2, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), + .enable_bit = OMAP3430_EN_DES1_SHIFT, + .recalc = &followparent_recalc, +}; + +/* DSS */ +static struct clk dss1_alwon_fck_3430es1 = { + .name = "dss1_alwon_fck", + .ops = &clkops_omap2_dflt, + .parent = &dpll4_m4x2_ck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_DSS1_SHIFT, + .clkdm_name = "dss_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk dss1_alwon_fck_3430es2 = { + .name = "dss1_alwon_fck", + .ops = &clkops_omap3430es2_dss_usbhost_wait, + .parent = &dpll4_m4x2_ck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_DSS1_SHIFT, + .clkdm_name = "dss_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk dss_tv_fck = { + .name = "dss_tv_fck", + .ops = &clkops_omap2_dflt, + .parent = &omap_54m_fck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_TV_SHIFT, + .clkdm_name = "dss_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk dss_96m_fck = { + .name = "dss_96m_fck", + .ops = &clkops_omap2_dflt, + .parent = &omap_96m_fck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_TV_SHIFT, + .clkdm_name = "dss_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk dss2_alwon_fck = { + .name = "dss2_alwon_fck", + .ops = &clkops_omap2_dflt, + .parent = &sys_ck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_DSS2_SHIFT, + .clkdm_name = "dss_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk dss_ick_3430es1 = { + /* Handles both L3 and L4 clocks */ + .name = "dss_ick", + .ops = &clkops_omap2_dflt, + .parent = &l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT, + .clkdm_name = "dss_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk dss_ick_3430es2 = { + /* Handles both L3 and L4 clocks */ + .name = "dss_ick", + .ops = &clkops_omap3430es2_dss_usbhost_wait, + .parent = &l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT, + .clkdm_name = "dss_clkdm", + .recalc = &followparent_recalc, +}; + +/* CAM */ + +static struct clk cam_mclk = { + .name = "cam_mclk", + .ops = &clkops_omap2_dflt, + .parent = &dpll4_m5x2_ck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_CAM_SHIFT, + .clkdm_name = "cam_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk cam_ick = { + /* Handles both L3 and L4 clocks */ + .name = "cam_ick", + .ops = &clkops_omap2_dflt, + .parent = &l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_CAM_SHIFT, + .clkdm_name = "cam_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk csi2_96m_fck = { + .name = "csi2_96m_fck", + .ops = &clkops_omap2_dflt, + .parent = &core_96m_fck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_CSI2_SHIFT, + .clkdm_name = "cam_clkdm", + .recalc = &followparent_recalc, +}; + +/* USBHOST - 3430ES2 only */ + +static struct clk usbhost_120m_fck = { + .name = "usbhost_120m_fck", + .ops = &clkops_omap2_dflt, + .parent = &dpll5_m2_ck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN), + .enable_bit = OMAP3430ES2_EN_USBHOST2_SHIFT, + .clkdm_name = "usbhost_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk usbhost_48m_fck = { + .name = "usbhost_48m_fck", + .ops = &clkops_omap3430es2_dss_usbhost_wait, + .parent = &omap_48m_fck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN), + .enable_bit = OMAP3430ES2_EN_USBHOST1_SHIFT, + .clkdm_name = "usbhost_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk usbhost_ick = { + /* Handles both L3 and L4 clocks */ + .name = "usbhost_ick", + .ops = &clkops_omap3430es2_dss_usbhost_wait, + .parent = &l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN), + .enable_bit = OMAP3430ES2_EN_USBHOST_SHIFT, + .clkdm_name = "usbhost_clkdm", + .recalc = &followparent_recalc, +}; + +/* WKUP */ + +static const struct clksel_rate usim_96m_rates[] = { + { .div = 2, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 4, .val = 4, .flags = RATE_IN_343X }, + { .div = 8, .val = 5, .flags = RATE_IN_343X }, + { .div = 10, .val = 6, .flags = RATE_IN_343X }, + { .div = 0 }, +}; + +static const struct clksel_rate usim_120m_rates[] = { + { .div = 4, .val = 7, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 8, .val = 8, .flags = RATE_IN_343X }, + { .div = 16, .val = 9, .flags = RATE_IN_343X }, + { .div = 20, .val = 10, .flags = RATE_IN_343X }, + { .div = 0 }, +}; + +static const struct clksel usim_clksel[] = { + { .parent = &omap_96m_fck, .rates = usim_96m_rates }, + { .parent = &dpll5_m2_ck, .rates = usim_120m_rates }, + { .parent = &sys_ck, .rates = div2_rates }, + { .parent = NULL }, +}; + +/* 3430ES2 only */ +static struct clk usim_fck = { + .name = "usim_fck", + .ops = &clkops_omap2_dflt_wait, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), + .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430ES2_CLKSEL_USIMOCP_MASK, + .clksel = usim_clksel, + .recalc = &omap2_clksel_recalc, +}; + +/* XXX should gpt1's clksel have wkup_32k_fck as the 32k opt? */ +static struct clk gpt1_fck = { + .name = "gpt1_fck", + .ops = &clkops_omap2_dflt_wait, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPT1_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_GPT1_MASK, + .clksel = omap343x_gpt_clksel, + .clkdm_name = "wkup_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk wkup_32k_fck = { + .name = "wkup_32k_fck", + .ops = &clkops_null, + .parent = &omap_32k_fck, + .clkdm_name = "wkup_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpio1_dbck = { + .name = "gpio1_dbck", + .ops = &clkops_omap2_dflt, + .parent = &wkup_32k_fck, + .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPIO1_SHIFT, + .clkdm_name = "wkup_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk wdt2_fck = { + .name = "wdt2_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &wkup_32k_fck, + .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_WDT2_SHIFT, + .clkdm_name = "wkup_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk wkup_l4_ick = { + .name = "wkup_l4_ick", + .ops = &clkops_null, + .parent = &sys_ck, + .clkdm_name = "wkup_clkdm", + .recalc = &followparent_recalc, +}; + +/* 3430ES2 only */ +/* Never specifically named in the TRM, so we have to infer a likely name */ +static struct clk usim_ick = { + .name = "usim_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &wkup_l4_ick, + .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), + .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT, + .clkdm_name = "wkup_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk wdt2_ick = { + .name = "wdt2_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &wkup_l4_ick, + .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_WDT2_SHIFT, + .clkdm_name = "wkup_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk wdt1_ick = { + .name = "wdt1_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &wkup_l4_ick, + .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_WDT1_SHIFT, + .clkdm_name = "wkup_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpio1_ick = { + .name = "gpio1_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &wkup_l4_ick, + .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPIO1_SHIFT, + .clkdm_name = "wkup_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk omap_32ksync_ick = { + .name = "omap_32ksync_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &wkup_l4_ick, + .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_32KSYNC_SHIFT, + .clkdm_name = "wkup_clkdm", + .recalc = &followparent_recalc, +}; + +/* XXX This clock no longer exists in 3430 TRM rev F */ +static struct clk gpt12_ick = { + .name = "gpt12_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &wkup_l4_ick, + .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPT12_SHIFT, + .clkdm_name = "wkup_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpt1_ick = { + .name = "gpt1_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &wkup_l4_ick, + .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPT1_SHIFT, + .clkdm_name = "wkup_clkdm", + .recalc = &followparent_recalc, +}; + + + +/* PER clock domain */ + +static struct clk per_96m_fck = { + .name = "per_96m_fck", + .ops = &clkops_null, + .parent = &omap_96m_alwon_fck, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk per_48m_fck = { + .name = "per_48m_fck", + .ops = &clkops_null, + .parent = &omap_48m_fck, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk uart3_fck = { + .name = "uart3_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_48m_fck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_UART3_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpt2_fck = { + .name = "gpt2_fck", + .ops = &clkops_omap2_dflt_wait, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPT2_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_GPT2_MASK, + .clksel = omap343x_gpt_clksel, + .clkdm_name = "per_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk gpt3_fck = { + .name = "gpt3_fck", + .ops = &clkops_omap2_dflt_wait, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPT3_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_GPT3_MASK, + .clksel = omap343x_gpt_clksel, + .clkdm_name = "per_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk gpt4_fck = { + .name = "gpt4_fck", + .ops = &clkops_omap2_dflt_wait, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPT4_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_GPT4_MASK, + .clksel = omap343x_gpt_clksel, + .clkdm_name = "per_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk gpt5_fck = { + .name = "gpt5_fck", + .ops = &clkops_omap2_dflt_wait, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPT5_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_GPT5_MASK, + .clksel = omap343x_gpt_clksel, + .clkdm_name = "per_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk gpt6_fck = { + .name = "gpt6_fck", + .ops = &clkops_omap2_dflt_wait, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPT6_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_GPT6_MASK, + .clksel = omap343x_gpt_clksel, + .clkdm_name = "per_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk gpt7_fck = { + .name = "gpt7_fck", + .ops = &clkops_omap2_dflt_wait, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPT7_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_GPT7_MASK, + .clksel = omap343x_gpt_clksel, + .clkdm_name = "per_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk gpt8_fck = { + .name = "gpt8_fck", + .ops = &clkops_omap2_dflt_wait, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPT8_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_GPT8_MASK, + .clksel = omap343x_gpt_clksel, + .clkdm_name = "per_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk gpt9_fck = { + .name = "gpt9_fck", + .ops = &clkops_omap2_dflt_wait, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPT9_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), + .clksel_mask = OMAP3430_CLKSEL_GPT9_MASK, + .clksel = omap343x_gpt_clksel, + .clkdm_name = "per_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk per_32k_alwon_fck = { + .name = "per_32k_alwon_fck", + .ops = &clkops_null, + .parent = &omap_32k_fck, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpio6_dbck = { + .name = "gpio6_dbck", + .ops = &clkops_omap2_dflt, + .parent = &per_32k_alwon_fck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPIO6_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpio5_dbck = { + .name = "gpio5_dbck", + .ops = &clkops_omap2_dflt, + .parent = &per_32k_alwon_fck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPIO5_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpio4_dbck = { + .name = "gpio4_dbck", + .ops = &clkops_omap2_dflt, + .parent = &per_32k_alwon_fck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPIO4_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpio3_dbck = { + .name = "gpio3_dbck", + .ops = &clkops_omap2_dflt, + .parent = &per_32k_alwon_fck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPIO3_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpio2_dbck = { + .name = "gpio2_dbck", + .ops = &clkops_omap2_dflt, + .parent = &per_32k_alwon_fck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_GPIO2_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk wdt3_fck = { + .name = "wdt3_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_32k_alwon_fck, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_WDT3_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk per_l4_ick = { + .name = "per_l4_ick", + .ops = &clkops_null, + .parent = &l4_ick, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpio6_ick = { + .name = "gpio6_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPIO6_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpio5_ick = { + .name = "gpio5_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPIO5_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpio4_ick = { + .name = "gpio4_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPIO4_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpio3_ick = { + .name = "gpio3_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPIO3_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpio2_ick = { + .name = "gpio2_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPIO2_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk wdt3_ick = { + .name = "wdt3_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_WDT3_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk uart3_ick = { + .name = "uart3_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_UART3_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpt9_ick = { + .name = "gpt9_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPT9_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpt8_ick = { + .name = "gpt8_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPT8_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpt7_ick = { + .name = "gpt7_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPT7_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpt6_ick = { + .name = "gpt6_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPT6_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpt5_ick = { + .name = "gpt5_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPT5_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpt4_ick = { + .name = "gpt4_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPT4_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpt3_ick = { + .name = "gpt3_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPT3_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk gpt2_ick = { + .name = "gpt2_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_GPT2_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mcbsp2_ick = { + .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, + .id = 2, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_MCBSP2_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mcbsp3_ick = { + .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, + .id = 3, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_MCBSP3_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mcbsp4_ick = { + .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, + .id = 4, + .parent = &per_l4_ick, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), + .enable_bit = OMAP3430_EN_MCBSP4_SHIFT, + .clkdm_name = "per_clkdm", + .recalc = &followparent_recalc, +}; + +static const struct clksel mcbsp_234_clksel[] = { + { .parent = &core_96m_fck, .rates = common_mcbsp_96m_rates }, + { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates }, + { .parent = NULL } +}; + +static struct clk mcbsp2_fck = { + .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, + .id = 2, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_MCBSP2_SHIFT, + .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0), + .clksel_mask = OMAP2_MCBSP2_CLKS_MASK, + .clksel = mcbsp_234_clksel, + .clkdm_name = "per_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk mcbsp3_fck = { + .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, + .id = 3, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_MCBSP3_SHIFT, + .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1), + .clksel_mask = OMAP2_MCBSP3_CLKS_MASK, + .clksel = mcbsp_234_clksel, + .clkdm_name = "per_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk mcbsp4_fck = { + .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, + .id = 4, + .init = &omap2_init_clksel_parent, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_MCBSP4_SHIFT, + .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1), + .clksel_mask = OMAP2_MCBSP4_CLKS_MASK, + .clksel = mcbsp_234_clksel, + .clkdm_name = "per_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +/* EMU clocks */ + +/* More information: ARM Cortex-A8 Technical Reference Manual, sect 10.1 */ + +static const struct clksel_rate emu_src_sys_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 }, +}; + +static const struct clksel_rate emu_src_core_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 }, +}; + +static const struct clksel_rate emu_src_per_rates[] = { + { .div = 1, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 }, +}; + +static const struct clksel_rate emu_src_mpu_rates[] = { + { .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 }, +}; + +static const struct clksel emu_src_clksel[] = { + { .parent = &sys_ck, .rates = emu_src_sys_rates }, + { .parent = &emu_core_alwon_ck, .rates = emu_src_core_rates }, + { .parent = &emu_per_alwon_ck, .rates = emu_src_per_rates }, + { .parent = &emu_mpu_alwon_ck, .rates = emu_src_mpu_rates }, + { .parent = NULL }, +}; + +/* + * Like the clkout_src clocks, emu_src_clk is a virtual clock, existing only + * to switch the source of some of the EMU clocks. + * XXX Are there CLKEN bits for these EMU clks? + */ +static struct clk emu_src_ck = { + .name = "emu_src_ck", + .ops = &clkops_null, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), + .clksel_mask = OMAP3430_MUX_CTRL_MASK, + .clksel = emu_src_clksel, + .clkdm_name = "emu_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static const struct clksel_rate pclk_emu_rates[] = { + { .div = 2, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 3, .val = 3, .flags = RATE_IN_343X }, + { .div = 4, .val = 4, .flags = RATE_IN_343X }, + { .div = 6, .val = 6, .flags = RATE_IN_343X }, + { .div = 0 }, +}; + +static const struct clksel pclk_emu_clksel[] = { + { .parent = &emu_src_ck, .rates = pclk_emu_rates }, + { .parent = NULL }, +}; + +static struct clk pclk_fck = { + .name = "pclk_fck", + .ops = &clkops_null, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), + .clksel_mask = OMAP3430_CLKSEL_PCLK_MASK, + .clksel = pclk_emu_clksel, + .clkdm_name = "emu_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static const struct clksel_rate pclkx2_emu_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 2, .val = 2, .flags = RATE_IN_343X }, + { .div = 3, .val = 3, .flags = RATE_IN_343X }, + { .div = 0 }, +}; + +static const struct clksel pclkx2_emu_clksel[] = { + { .parent = &emu_src_ck, .rates = pclkx2_emu_rates }, + { .parent = NULL }, +}; + +static struct clk pclkx2_fck = { + .name = "pclkx2_fck", + .ops = &clkops_null, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), + .clksel_mask = OMAP3430_CLKSEL_PCLKX2_MASK, + .clksel = pclkx2_emu_clksel, + .clkdm_name = "emu_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static const struct clksel atclk_emu_clksel[] = { + { .parent = &emu_src_ck, .rates = div2_rates }, + { .parent = NULL }, +}; + +static struct clk atclk_fck = { + .name = "atclk_fck", + .ops = &clkops_null, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), + .clksel_mask = OMAP3430_CLKSEL_ATCLK_MASK, + .clksel = atclk_emu_clksel, + .clkdm_name = "emu_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static struct clk traceclk_src_fck = { + .name = "traceclk_src_fck", + .ops = &clkops_null, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), + .clksel_mask = OMAP3430_TRACE_MUX_CTRL_MASK, + .clksel = emu_src_clksel, + .clkdm_name = "emu_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +static const struct clksel_rate traceclk_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 2, .val = 2, .flags = RATE_IN_343X }, + { .div = 4, .val = 4, .flags = RATE_IN_343X }, + { .div = 0 }, +}; + +static const struct clksel traceclk_clksel[] = { + { .parent = &traceclk_src_fck, .rates = traceclk_rates }, + { .parent = NULL }, +}; + +static struct clk traceclk_fck = { + .name = "traceclk_fck", + .ops = &clkops_null, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), + .clksel_mask = OMAP3430_CLKSEL_TRACECLK_MASK, + .clksel = traceclk_clksel, + .clkdm_name = "emu_clkdm", + .recalc = &omap2_clksel_recalc, +}; + +/* SR clocks */ + +/* SmartReflex fclk (VDD1) */ +static struct clk sr1_fck = { + .name = "sr1_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &sys_ck, + .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_SR1_SHIFT, + .recalc = &followparent_recalc, +}; + +/* SmartReflex fclk (VDD2) */ +static struct clk sr2_fck = { + .name = "sr2_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &sys_ck, + .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_SR2_SHIFT, + .recalc = &followparent_recalc, +}; + +static struct clk sr_l4_ick = { + .name = "sr_l4_ick", + .ops = &clkops_null, /* RMK: missing? */ + .parent = &l4_ick, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + +/* SECURE_32K_FCK clocks */ + +static struct clk gpt12_fck = { + .name = "gpt12_fck", + .ops = &clkops_null, + .parent = &secure_32k_fck, + .recalc = &followparent_recalc, +}; + +static struct clk wdt1_fck = { + .name = "wdt1_fck", + .ops = &clkops_null, + .parent = &secure_32k_fck, + .recalc = &followparent_recalc, +}; + + +/* + * clkdev + */ + +static struct omap_clk omap34xx_clks[] = { + CLK(NULL, "omap_32k_fck", &omap_32k_fck, CK_343X), + CLK(NULL, "virt_12m_ck", &virt_12m_ck, CK_343X), + CLK(NULL, "virt_13m_ck", &virt_13m_ck, CK_343X), + CLK(NULL, "virt_16_8m_ck", &virt_16_8m_ck, CK_3430ES2), + CLK(NULL, "virt_19_2m_ck", &virt_19_2m_ck, CK_343X), + CLK(NULL, "virt_26m_ck", &virt_26m_ck, CK_343X), + CLK(NULL, "virt_38_4m_ck", &virt_38_4m_ck, CK_343X), + CLK(NULL, "osc_sys_ck", &osc_sys_ck, CK_343X), + CLK(NULL, "sys_ck", &sys_ck, CK_343X), + CLK(NULL, "sys_altclk", &sys_altclk, CK_343X), + CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_343X), + CLK(NULL, "sys_clkout1", &sys_clkout1, CK_343X), + CLK(NULL, "dpll1_ck", &dpll1_ck, CK_343X), + CLK(NULL, "dpll1_x2_ck", &dpll1_x2_ck, CK_343X), + CLK(NULL, "dpll1_x2m2_ck", &dpll1_x2m2_ck, CK_343X), + CLK(NULL, "dpll2_ck", &dpll2_ck, CK_343X), + CLK(NULL, "dpll2_m2_ck", &dpll2_m2_ck, CK_343X), + CLK(NULL, "dpll3_ck", &dpll3_ck, CK_343X), + CLK(NULL, "core_ck", &core_ck, CK_343X), + CLK(NULL, "dpll3_x2_ck", &dpll3_x2_ck, CK_343X), + CLK(NULL, "dpll3_m2_ck", &dpll3_m2_ck, CK_343X), + CLK(NULL, "dpll3_m2x2_ck", &dpll3_m2x2_ck, CK_343X), + CLK(NULL, "dpll3_m3_ck", &dpll3_m3_ck, CK_343X), + CLK(NULL, "dpll3_m3x2_ck", &dpll3_m3x2_ck, CK_343X), + CLK("etb", "emu_core_alwon_ck", &emu_core_alwon_ck, CK_343X), + CLK(NULL, "dpll4_ck", &dpll4_ck, CK_343X), + CLK(NULL, "dpll4_x2_ck", &dpll4_x2_ck, CK_343X), + CLK(NULL, "omap_96m_alwon_fck", &omap_96m_alwon_fck, CK_343X), + CLK(NULL, "omap_96m_fck", &omap_96m_fck, CK_343X), + CLK(NULL, "cm_96m_fck", &cm_96m_fck, CK_343X), + CLK(NULL, "omap_54m_fck", &omap_54m_fck, CK_343X), + CLK(NULL, "omap_48m_fck", &omap_48m_fck, CK_343X), + CLK(NULL, "omap_12m_fck", &omap_12m_fck, CK_343X), + CLK(NULL, "dpll4_m2_ck", &dpll4_m2_ck, CK_343X), + CLK(NULL, "dpll4_m2x2_ck", &dpll4_m2x2_ck, CK_343X), + CLK(NULL, "dpll4_m3_ck", &dpll4_m3_ck, CK_343X), + CLK(NULL, "dpll4_m3x2_ck", &dpll4_m3x2_ck, CK_343X), + CLK(NULL, "dpll4_m4_ck", &dpll4_m4_ck, CK_343X), + CLK(NULL, "dpll4_m4x2_ck", &dpll4_m4x2_ck, CK_343X), + CLK(NULL, "dpll4_m5_ck", &dpll4_m5_ck, CK_343X), + CLK(NULL, "dpll4_m5x2_ck", &dpll4_m5x2_ck, CK_343X), + CLK(NULL, "dpll4_m6_ck", &dpll4_m6_ck, CK_343X), + CLK(NULL, "dpll4_m6x2_ck", &dpll4_m6x2_ck, CK_343X), + CLK("etb", "emu_per_alwon_ck", &emu_per_alwon_ck, CK_343X), + CLK(NULL, "dpll5_ck", &dpll5_ck, CK_3430ES2), + CLK(NULL, "dpll5_m2_ck", &dpll5_m2_ck, CK_3430ES2), + CLK(NULL, "clkout2_src_ck", &clkout2_src_ck, CK_343X), + CLK(NULL, "sys_clkout2", &sys_clkout2, CK_343X), + CLK(NULL, "corex2_fck", &corex2_fck, CK_343X), + CLK(NULL, "dpll1_fck", &dpll1_fck, CK_343X), + CLK(NULL, "mpu_ck", &mpu_ck, CK_343X), + CLK(NULL, "arm_fck", &arm_fck, CK_343X), + CLK("etb", "emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_343X), + CLK(NULL, "dpll2_fck", &dpll2_fck, CK_343X), + CLK(NULL, "iva2_ck", &iva2_ck, CK_343X), + CLK(NULL, "l3_ick", &l3_ick, CK_343X), + CLK(NULL, "l4_ick", &l4_ick, CK_343X), + CLK(NULL, "rm_ick", &rm_ick, CK_343X), + CLK(NULL, "gfx_l3_ck", &gfx_l3_ck, CK_3430ES1), + CLK(NULL, "gfx_l3_fck", &gfx_l3_fck, CK_3430ES1), + CLK(NULL, "gfx_l3_ick", &gfx_l3_ick, CK_3430ES1), + CLK(NULL, "gfx_cg1_ck", &gfx_cg1_ck, CK_3430ES1), + CLK(NULL, "gfx_cg2_ck", &gfx_cg2_ck, CK_3430ES1), + CLK(NULL, "sgx_fck", &sgx_fck, CK_3430ES2), + CLK(NULL, "sgx_ick", &sgx_ick, CK_3430ES2), + CLK(NULL, "d2d_26m_fck", &d2d_26m_fck, CK_3430ES1), + CLK(NULL, "modem_fck", &modem_fck, CK_343X), + CLK(NULL, "sad2d_ick", &sad2d_ick, CK_343X), + CLK(NULL, "mad2d_ick", &mad2d_ick, CK_343X), + CLK(NULL, "gpt10_fck", &gpt10_fck, CK_343X), + CLK(NULL, "gpt11_fck", &gpt11_fck, CK_343X), + CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2), + CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2), + CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2), + CLK(NULL, "core_96m_fck", &core_96m_fck, CK_343X), + CLK("mmci-omap-hs.2", "fck", &mmchs3_fck, CK_3430ES2), + CLK("mmci-omap-hs.1", "fck", &mmchs2_fck, CK_343X), + CLK(NULL, "mspro_fck", &mspro_fck, CK_343X), + CLK("mmci-omap-hs.0", "fck", &mmchs1_fck, CK_343X), + CLK("i2c_omap.3", "fck", &i2c3_fck, CK_343X), + CLK("i2c_omap.2", "fck", &i2c2_fck, CK_343X), + CLK("i2c_omap.1", "fck", &i2c1_fck, CK_343X), + CLK("omap-mcbsp.5", "fck", &mcbsp5_fck, CK_343X), + CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_343X), + CLK(NULL, "core_48m_fck", &core_48m_fck, CK_343X), + CLK("omap2_mcspi.4", "fck", &mcspi4_fck, CK_343X), + CLK("omap2_mcspi.3", "fck", &mcspi3_fck, CK_343X), + CLK("omap2_mcspi.2", "fck", &mcspi2_fck, CK_343X), + CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_343X), + CLK(NULL, "uart2_fck", &uart2_fck, CK_343X), + CLK(NULL, "uart1_fck", &uart1_fck, CK_343X), + CLK(NULL, "fshostusb_fck", &fshostusb_fck, CK_3430ES1), + CLK(NULL, "core_12m_fck", &core_12m_fck, CK_343X), + CLK("omap_hdq.0", "fck", &hdq_fck, CK_343X), + CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es1, CK_3430ES1), + CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es2, CK_3430ES2), + CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es1, CK_3430ES1), + CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es2, CK_3430ES2), + CLK(NULL, "core_l3_ick", &core_l3_ick, CK_343X), + CLK("musb_hdrc", "ick", &hsotgusb_ick_3430es1, CK_3430ES1), + CLK("musb_hdrc", "ick", &hsotgusb_ick_3430es2, CK_3430ES2), + CLK(NULL, "sdrc_ick", &sdrc_ick, CK_343X), + CLK(NULL, "gpmc_fck", &gpmc_fck, CK_343X), + CLK(NULL, "security_l3_ick", &security_l3_ick, CK_343X), + CLK(NULL, "pka_ick", &pka_ick, CK_343X), + CLK(NULL, "core_l4_ick", &core_l4_ick, CK_343X), + CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2), + CLK("mmci-omap-hs.2", "ick", &mmchs3_ick, CK_3430ES2), + CLK(NULL, "icr_ick", &icr_ick, CK_343X), + CLK(NULL, "aes2_ick", &aes2_ick, CK_343X), + CLK(NULL, "sha12_ick", &sha12_ick, CK_343X), + CLK(NULL, "des2_ick", &des2_ick, CK_343X), + CLK("mmci-omap-hs.1", "ick", &mmchs2_ick, CK_343X), + CLK("mmci-omap-hs.0", "ick", &mmchs1_ick, CK_343X), + CLK(NULL, "mspro_ick", &mspro_ick, CK_343X), + CLK("omap_hdq.0", "ick", &hdq_ick, CK_343X), + CLK("omap2_mcspi.4", "ick", &mcspi4_ick, CK_343X), + CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_343X), + CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_343X), + CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_343X), + CLK("i2c_omap.3", "ick", &i2c3_ick, CK_343X), + CLK("i2c_omap.2", "ick", &i2c2_ick, CK_343X), + CLK("i2c_omap.1", "ick", &i2c1_ick, CK_343X), + CLK(NULL, "uart2_ick", &uart2_ick, CK_343X), + CLK(NULL, "uart1_ick", &uart1_ick, CK_343X), + CLK(NULL, "gpt11_ick", &gpt11_ick, CK_343X), + CLK(NULL, "gpt10_ick", &gpt10_ick, CK_343X), + CLK("omap-mcbsp.5", "ick", &mcbsp5_ick, CK_343X), + CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_343X), + CLK(NULL, "fac_ick", &fac_ick, CK_3430ES1), + CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_343X), + CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_343X), + CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_343X), + CLK(NULL, "ssi_ick", &ssi_ick_3430es1, CK_3430ES1), + CLK(NULL, "ssi_ick", &ssi_ick_3430es2, CK_3430ES2), + CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_3430ES1), + CLK(NULL, "security_l4_ick2", &security_l4_ick2, CK_343X), + CLK(NULL, "aes1_ick", &aes1_ick, CK_343X), + CLK("omap_rng", "ick", &rng_ick, CK_343X), + CLK(NULL, "sha11_ick", &sha11_ick, CK_343X), + CLK(NULL, "des1_ick", &des1_ick, CK_343X), + CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1), + CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2), + CLK("omapdss", "tv_fck", &dss_tv_fck, CK_343X), + CLK("omapdss", "video_fck", &dss_96m_fck, CK_343X), + CLK("omapdss", "dss2_fck", &dss2_alwon_fck, CK_343X), + CLK("omapdss", "ick", &dss_ick_3430es1, CK_3430ES1), + CLK("omapdss", "ick", &dss_ick_3430es2, CK_3430ES2), + CLK(NULL, "cam_mclk", &cam_mclk, CK_343X), + CLK(NULL, "cam_ick", &cam_ick, CK_343X), + CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_343X), + CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2), + CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2), + CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2), + CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2), + CLK(NULL, "gpt1_fck", &gpt1_fck, CK_343X), + CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_343X), + CLK(NULL, "gpio1_dbck", &gpio1_dbck, CK_343X), + CLK("omap_wdt", "fck", &wdt2_fck, CK_343X), + CLK(NULL, "wkup_l4_ick", &wkup_l4_ick, CK_343X), + CLK(NULL, "usim_ick", &usim_ick, CK_3430ES2), + CLK("omap_wdt", "ick", &wdt2_ick, CK_343X), + CLK(NULL, "wdt1_ick", &wdt1_ick, CK_343X), + CLK(NULL, "gpio1_ick", &gpio1_ick, CK_343X), + CLK(NULL, "omap_32ksync_ick", &omap_32ksync_ick, CK_343X), + CLK(NULL, "gpt12_ick", &gpt12_ick, CK_343X), + CLK(NULL, "gpt1_ick", &gpt1_ick, CK_343X), + CLK(NULL, "per_96m_fck", &per_96m_fck, CK_343X), + CLK(NULL, "per_48m_fck", &per_48m_fck, CK_343X), + CLK(NULL, "uart3_fck", &uart3_fck, CK_343X), + CLK(NULL, "gpt2_fck", &gpt2_fck, CK_343X), + CLK(NULL, "gpt3_fck", &gpt3_fck, CK_343X), + CLK(NULL, "gpt4_fck", &gpt4_fck, CK_343X), + CLK(NULL, "gpt5_fck", &gpt5_fck, CK_343X), + CLK(NULL, "gpt6_fck", &gpt6_fck, CK_343X), + CLK(NULL, "gpt7_fck", &gpt7_fck, CK_343X), + CLK(NULL, "gpt8_fck", &gpt8_fck, CK_343X), + CLK(NULL, "gpt9_fck", &gpt9_fck, CK_343X), + CLK(NULL, "per_32k_alwon_fck", &per_32k_alwon_fck, CK_343X), + CLK(NULL, "gpio6_dbck", &gpio6_dbck, CK_343X), + CLK(NULL, "gpio5_dbck", &gpio5_dbck, CK_343X), + CLK(NULL, "gpio4_dbck", &gpio4_dbck, CK_343X), + CLK(NULL, "gpio3_dbck", &gpio3_dbck, CK_343X), + CLK(NULL, "gpio2_dbck", &gpio2_dbck, CK_343X), + CLK(NULL, "wdt3_fck", &wdt3_fck, CK_343X), + CLK(NULL, "per_l4_ick", &per_l4_ick, CK_343X), + CLK(NULL, "gpio6_ick", &gpio6_ick, CK_343X), + CLK(NULL, "gpio5_ick", &gpio5_ick, CK_343X), + CLK(NULL, "gpio4_ick", &gpio4_ick, CK_343X), + CLK(NULL, "gpio3_ick", &gpio3_ick, CK_343X), + CLK(NULL, "gpio2_ick", &gpio2_ick, CK_343X), + CLK(NULL, "wdt3_ick", &wdt3_ick, CK_343X), + CLK(NULL, "uart3_ick", &uart3_ick, CK_343X), + CLK(NULL, "gpt9_ick", &gpt9_ick, CK_343X), + CLK(NULL, "gpt8_ick", &gpt8_ick, CK_343X), + CLK(NULL, "gpt7_ick", &gpt7_ick, CK_343X), + CLK(NULL, "gpt6_ick", &gpt6_ick, CK_343X), + CLK(NULL, "gpt5_ick", &gpt5_ick, CK_343X), + CLK(NULL, "gpt4_ick", &gpt4_ick, CK_343X), + CLK(NULL, "gpt3_ick", &gpt3_ick, CK_343X), + CLK(NULL, "gpt2_ick", &gpt2_ick, CK_343X), + CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_343X), + CLK("omap-mcbsp.3", "ick", &mcbsp3_ick, CK_343X), + CLK("omap-mcbsp.4", "ick", &mcbsp4_ick, CK_343X), + CLK("omap-mcbsp.2", "fck", &mcbsp2_fck, CK_343X), + CLK("omap-mcbsp.3", "fck", &mcbsp3_fck, CK_343X), + CLK("omap-mcbsp.4", "fck", &mcbsp4_fck, CK_343X), + CLK("etb", "emu_src_ck", &emu_src_ck, CK_343X), + CLK(NULL, "pclk_fck", &pclk_fck, CK_343X), + CLK(NULL, "pclkx2_fck", &pclkx2_fck, CK_343X), + CLK(NULL, "atclk_fck", &atclk_fck, CK_343X), + CLK(NULL, "traceclk_src_fck", &traceclk_src_fck, CK_343X), + CLK(NULL, "traceclk_fck", &traceclk_fck, CK_343X), + CLK(NULL, "sr1_fck", &sr1_fck, CK_343X), + CLK(NULL, "sr2_fck", &sr2_fck, CK_343X), + CLK(NULL, "sr_l4_ick", &sr_l4_ick, CK_343X), + CLK(NULL, "secure_32k_fck", &secure_32k_fck, CK_343X), + CLK(NULL, "gpt12_fck", &gpt12_fck, CK_343X), + CLK(NULL, "wdt1_fck", &wdt1_fck, CK_343X), +}; + + +int __init omap2_clk_init(void) +{ + /* struct prcm_config *prcm; */ + struct omap_clk *c; + /* u32 clkrate; */ + u32 cpu_clkflg; + + if (cpu_is_omap34xx()) { + cpu_mask = RATE_IN_343X; + cpu_clkflg = CK_343X; + + /* + * Update this if there are further clock changes between ES2 + * and production parts + */ + if (omap_rev() == OMAP3430_REV_ES1_0) { + /* No 3430ES1-only rates exist, so no RATE_IN_3430ES1 */ + cpu_clkflg |= CK_3430ES1; + } else { + cpu_mask |= RATE_IN_3430ES2; + cpu_clkflg |= CK_3430ES2; + } + } + + clk_init(&omap2_clk_functions); + + for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++) + clk_preinit(c->lk.clk); + + for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++) + if (c->cpu & cpu_clkflg) { + clkdev_add(&c->lk); + clk_register(c->lk.clk); + omap2_init_clk_clkdm(c->lk.clk); + } + + /* REVISIT: Not yet ready for OMAP3 */ +#if 0 + /* Check the MPU rate set by bootloader */ + clkrate = omap2_get_dpll_rate_24xx(&dpll_ck); + for (prcm = rate_table; prcm->mpu_speed; prcm++) { + if (!(prcm->flags & cpu_mask)) + continue; + if (prcm->xtal_speed != sys_ck.rate) + continue; + if (prcm->dpll_speed <= clkrate) + break; + } + curr_prcm_set = prcm; +#endif + + recalculate_root_clocks(); + + printk(KERN_INFO "Clocking rate (Crystal/Core/MPU): " + "%ld.%01ld/%ld/%ld MHz\n", + (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10, + (core_ck.rate / 1000000), (arm_fck.rate / 1000000)); + + /* + * Only enable those clocks we will need, let the drivers + * enable other clocks as necessary + */ + clk_enable_init_clocks(); + + /* + * Lock DPLL5 and put it in autoidle. + */ + if (omap_rev() >= OMAP3430_REV_ES2_0) + omap3_clk_lock_dpll5(); + + /* Avoid sleeping during omap3_core_dpll_m2_set_rate() */ + sdrc_ick_p = clk_get(NULL, "sdrc_ick"); + arm_fck_p = clk_get(NULL, "arm_fck"); + + return 0; +} diff --git a/arch/arm/mach-omap2/clock44xx.c b/arch/arm/mach-omap2/clock44xx.c new file mode 100644 index 0000000000000000000000000000000000000000..e370868a79a862c4263238ab5272d8404d9d80ec --- /dev/null +++ b/arch/arm/mach-omap2/clock44xx.c @@ -0,0 +1,33 @@ +/* + * OMAP4-specific clock framework functions + * + * Copyright (C) 2009 Texas Instruments, Inc. + * + * Rajendra Nayak (rnayak@ti.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include "clock.h" + +struct clk_functions omap2_clk_functions = { + .clk_enable = omap2_clk_enable, + .clk_disable = omap2_clk_disable, + .clk_round_rate = omap2_clk_round_rate, + .clk_set_rate = omap2_clk_set_rate, + .clk_set_parent = omap2_clk_set_parent, + .clk_disable_unused = omap2_clk_disable_unused, +}; + +const struct clkops clkops_noncore_dpll_ops = { + .enable = &omap3_noncore_dpll_enable, + .disable = &omap3_noncore_dpll_disable, +}; + +void omap2_clk_prepare_for_reboot(void) +{ + return; +} diff --git a/arch/arm/mach-omap2/clock44xx.h b/arch/arm/mach-omap2/clock44xx.h new file mode 100644 index 0000000000000000000000000000000000000000..59b9ced4daa18ef710096b9a14e198247810e864 --- /dev/null +++ b/arch/arm/mach-omap2/clock44xx.h @@ -0,0 +1,15 @@ +/* + * OMAP4 clock function prototypes and macros + * + * Copyright (C) 2009 Texas Instruments, Inc. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK_44XX_H +#define __ARCH_ARM_MACH_OMAP2_CLOCK_44XX_H + +#define OMAP4430_MAX_DPLL_MULT 2048 +#define OMAP4430_MAX_DPLL_DIV 128 + +extern const struct clkops clkops_noncore_dpll_ops; + +#endif diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c new file mode 100644 index 0000000000000000000000000000000000000000..2210e227d78a2b93fdd9ccba0d84f94a26cbb0bd --- /dev/null +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -0,0 +1,2766 @@ +/* + * OMAP4 Clock data + * + * Copyright (C) 2009 Texas Instruments, Inc. + * Copyright (C) 2009 Nokia Corporation + * + * Paul Walmsley (paul@pwsan.com) + * Rajendra Nayak (rnayak@ti.com) + * Benoit Cousson (b-cousson@ti.com) + * + * This file is automatically generated from the OMAP hardware databases. + * We respectfully ask that any modifications to this file be coordinated + * with the public linux-omap@vger.kernel.org mailing list and the + * authors above to ensure that the autogeneration scripts are kept + * up-to-date with the file contents. + * + * 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 "clock.h" +#include "clock44xx.h" +#include "cm.h" +#include "cm-regbits-44xx.h" +#include "prm.h" +#include "prm-regbits-44xx.h" + +/* Root clocks */ + +static struct clk extalt_clkin_ck = { + .name = "extalt_clkin_ck", + .rate = 59000000, + .ops = &clkops_null, + .flags = CLOCK_IN_OMAP4430 | ALWAYS_ENABLED, +}; + +static struct clk pad_clks_ck = { + .name = "pad_clks_ck", + .rate = 12000000, + .ops = &clkops_null, + .flags = CLOCK_IN_OMAP4430 | ALWAYS_ENABLED, +}; + +static struct clk pad_slimbus_core_clks_ck = { + .name = "pad_slimbus_core_clks_ck", + .rate = 12000000, + .ops = &clkops_null, + .flags = CLOCK_IN_OMAP4430 | ALWAYS_ENABLED, +}; + +static struct clk secure_32k_clk_src_ck = { + .name = "secure_32k_clk_src_ck", + .rate = 32768, + .ops = &clkops_null, + .flags = CLOCK_IN_OMAP4430 | ALWAYS_ENABLED, +}; + +static struct clk slimbus_clk = { + .name = "slimbus_clk", + .rate = 12000000, + .ops = &clkops_null, + .flags = CLOCK_IN_OMAP4430 | ALWAYS_ENABLED, +}; + +static struct clk sys_32k_ck = { + .name = "sys_32k_ck", + .rate = 32768, + .ops = &clkops_null, + .flags = CLOCK_IN_OMAP4430 | ALWAYS_ENABLED, +}; + +static struct clk virt_12000000_ck = { + .name = "virt_12000000_ck", + .ops = &clkops_null, + .rate = 12000000, +}; + +static struct clk virt_13000000_ck = { + .name = "virt_13000000_ck", + .ops = &clkops_null, + .rate = 13000000, +}; + +static struct clk virt_16800000_ck = { + .name = "virt_16800000_ck", + .ops = &clkops_null, + .rate = 16800000, +}; + +static struct clk virt_19200000_ck = { + .name = "virt_19200000_ck", + .ops = &clkops_null, + .rate = 19200000, +}; + +static struct clk virt_26000000_ck = { + .name = "virt_26000000_ck", + .ops = &clkops_null, + .rate = 26000000, +}; + +static struct clk virt_27000000_ck = { + .name = "virt_27000000_ck", + .ops = &clkops_null, + .rate = 27000000, +}; + +static struct clk virt_38400000_ck = { + .name = "virt_38400000_ck", + .ops = &clkops_null, + .rate = 38400000, +}; + +static const struct clksel_rate div_1_0_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel_rate div_1_1_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel_rate div_1_2_rates[] = { + { .div = 1, .val = 2, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel_rate div_1_3_rates[] = { + { .div = 1, .val = 3, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel_rate div_1_4_rates[] = { + { .div = 1, .val = 4, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel_rate div_1_5_rates[] = { + { .div = 1, .val = 5, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel_rate div_1_6_rates[] = { + { .div = 1, .val = 6, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel_rate div_1_7_rates[] = { + { .div = 1, .val = 7, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel sys_clkin_sel[] = { + { .parent = &virt_12000000_ck, .rates = div_1_1_rates }, + { .parent = &virt_13000000_ck, .rates = div_1_2_rates }, + { .parent = &virt_16800000_ck, .rates = div_1_3_rates }, + { .parent = &virt_19200000_ck, .rates = div_1_4_rates }, + { .parent = &virt_26000000_ck, .rates = div_1_5_rates }, + { .parent = &virt_27000000_ck, .rates = div_1_6_rates }, + { .parent = &virt_38400000_ck, .rates = div_1_7_rates }, + { .parent = NULL }, +}; + +static struct clk sys_clkin_ck = { + .name = "sys_clkin_ck", + .rate = 38400000, + .clksel = sys_clkin_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_SYS_CLKSEL, + .clksel_mask = OMAP4430_SYS_CLKSEL_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430 | ALWAYS_ENABLED, +}; + +static struct clk utmi_phy_clkout_ck = { + .name = "utmi_phy_clkout_ck", + .rate = 12000000, + .ops = &clkops_null, + .flags = CLOCK_IN_OMAP4430 | ALWAYS_ENABLED, +}; + +static struct clk xclk60mhsp1_ck = { + .name = "xclk60mhsp1_ck", + .rate = 12000000, + .ops = &clkops_null, + .flags = CLOCK_IN_OMAP4430 | ALWAYS_ENABLED, +}; + +static struct clk xclk60mhsp2_ck = { + .name = "xclk60mhsp2_ck", + .rate = 12000000, + .ops = &clkops_null, + .flags = CLOCK_IN_OMAP4430 | ALWAYS_ENABLED, +}; + +static struct clk xclk60motg_ck = { + .name = "xclk60motg_ck", + .rate = 60000000, + .ops = &clkops_null, + .flags = CLOCK_IN_OMAP4430 | ALWAYS_ENABLED, +}; + +/* Module clocks and DPLL outputs */ + +static const struct clksel_rate div2_1to2_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_4430 }, + { .div = 2, .val = 1, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel dpll_sys_ref_clk_div[] = { + { .parent = &sys_clkin_ck, .rates = div2_1to2_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_sys_ref_clk = { + .name = "dpll_sys_ref_clk", + .parent = &sys_clkin_ck, + .clksel = dpll_sys_ref_clk_div, + .clksel_reg = OMAP4430_CM_DPLL_SYS_REF_CLKSEL, + .clksel_mask = OMAP4430_CLKSEL_0_0_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel abe_dpll_refclk_mux_sel[] = { + { .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates }, + { .parent = &sys_32k_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk abe_dpll_refclk_mux_ck = { + .name = "abe_dpll_refclk_mux_ck", + .parent = &dpll_sys_ref_clk, + .clksel = abe_dpll_refclk_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_ABE_PLL_REF_CLKSEL, + .clksel_mask = OMAP4430_CLKSEL_0_0_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +/* DPLL_ABE */ +static struct dpll_data dpll_abe_dd = { + .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_ABE, + .clk_bypass = &sys_clkin_ck, + .clk_ref = &abe_dpll_refclk_mux_ck, + .control_reg = OMAP4430_CM_CLKMODE_DPLL_ABE, + .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), + .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_ABE, + .idlest_reg = OMAP4430_CM_IDLEST_DPLL_ABE, + .mult_mask = OMAP4430_DPLL_MULT_MASK, + .div1_mask = OMAP4430_DPLL_DIV_MASK, + .enable_mask = OMAP4430_DPLL_EN_MASK, + .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK, + .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK, + .max_multiplier = OMAP4430_MAX_DPLL_MULT, + .max_divider = OMAP4430_MAX_DPLL_DIV, + .min_divider = 1, +}; + + +static struct clk dpll_abe_ck = { + .name = "dpll_abe_ck", + .parent = &abe_dpll_refclk_mux_ck, + .dpll_data = &dpll_abe_dd, + .init = &omap2_init_dpll_parent, + .ops = &clkops_noncore_dpll_ops, + .recalc = &omap3_dpll_recalc, + .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_abe_m2x2_ck = { + .name = "dpll_abe_m2x2_ck", + .parent = &dpll_abe_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk abe_24m_fclk = { + .name = "abe_24m_fclk", + .parent = &dpll_abe_m2x2_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel_rate div3_1to4_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_4430 }, + { .div = 2, .val = 1, .flags = RATE_IN_4430 }, + { .div = 4, .val = 2, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel abe_clk_div[] = { + { .parent = &dpll_abe_m2x2_ck, .rates = div3_1to4_rates }, + { .parent = NULL }, +}; + +static struct clk abe_clk = { + .name = "abe_clk", + .parent = &dpll_abe_m2x2_ck, + .clksel = abe_clk_div, + .clksel_reg = OMAP4430_CM_CLKSEL_ABE, + .clksel_mask = OMAP4430_CLKSEL_OPP_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel aess_fclk_div[] = { + { .parent = &abe_clk, .rates = div2_1to2_rates }, + { .parent = NULL }, +}; + +static struct clk aess_fclk = { + .name = "aess_fclk", + .parent = &abe_clk, + .clksel = aess_fclk_div, + .clksel_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_AESS_FCLK_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel_rate div31_1to31_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_4430 }, + { .div = 2, .val = 1, .flags = RATE_IN_4430 }, + { .div = 3, .val = 2, .flags = RATE_IN_4430 }, + { .div = 4, .val = 3, .flags = RATE_IN_4430 }, + { .div = 5, .val = 4, .flags = RATE_IN_4430 }, + { .div = 6, .val = 5, .flags = RATE_IN_4430 }, + { .div = 7, .val = 6, .flags = RATE_IN_4430 }, + { .div = 8, .val = 7, .flags = RATE_IN_4430 }, + { .div = 9, .val = 8, .flags = RATE_IN_4430 }, + { .div = 10, .val = 9, .flags = RATE_IN_4430 }, + { .div = 11, .val = 10, .flags = RATE_IN_4430 }, + { .div = 12, .val = 11, .flags = RATE_IN_4430 }, + { .div = 13, .val = 12, .flags = RATE_IN_4430 }, + { .div = 14, .val = 13, .flags = RATE_IN_4430 }, + { .div = 15, .val = 14, .flags = RATE_IN_4430 }, + { .div = 16, .val = 15, .flags = RATE_IN_4430 }, + { .div = 17, .val = 16, .flags = RATE_IN_4430 }, + { .div = 18, .val = 17, .flags = RATE_IN_4430 }, + { .div = 19, .val = 18, .flags = RATE_IN_4430 }, + { .div = 20, .val = 19, .flags = RATE_IN_4430 }, + { .div = 21, .val = 20, .flags = RATE_IN_4430 }, + { .div = 22, .val = 21, .flags = RATE_IN_4430 }, + { .div = 23, .val = 22, .flags = RATE_IN_4430 }, + { .div = 24, .val = 23, .flags = RATE_IN_4430 }, + { .div = 25, .val = 24, .flags = RATE_IN_4430 }, + { .div = 26, .val = 25, .flags = RATE_IN_4430 }, + { .div = 27, .val = 26, .flags = RATE_IN_4430 }, + { .div = 28, .val = 27, .flags = RATE_IN_4430 }, + { .div = 29, .val = 28, .flags = RATE_IN_4430 }, + { .div = 30, .val = 29, .flags = RATE_IN_4430 }, + { .div = 31, .val = 30, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel dpll_abe_m3_div[] = { + { .parent = &dpll_abe_ck, .rates = div31_1to31_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_abe_m3_ck = { + .name = "dpll_abe_m3_ck", + .parent = &dpll_abe_ck, + .clksel = dpll_abe_m3_div, + .clksel_reg = OMAP4430_CM_DIV_M3_DPLL_ABE, + .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel core_hsd_byp_clk_mux_sel[] = { + { .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates }, + { .parent = &dpll_abe_m3_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk core_hsd_byp_clk_mux_ck = { + .name = "core_hsd_byp_clk_mux_ck", + .parent = &dpll_sys_ref_clk, + .clksel = core_hsd_byp_clk_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_CLKSEL_DPLL_CORE, + .clksel_mask = OMAP4430_DPLL_BYP_CLKSEL_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +/* DPLL_CORE */ +static struct dpll_data dpll_core_dd = { + .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_CORE, + .clk_bypass = &core_hsd_byp_clk_mux_ck, + .clk_ref = &dpll_sys_ref_clk, + .control_reg = OMAP4430_CM_CLKMODE_DPLL_CORE, + .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), + .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_CORE, + .idlest_reg = OMAP4430_CM_IDLEST_DPLL_CORE, + .mult_mask = OMAP4430_DPLL_MULT_MASK, + .div1_mask = OMAP4430_DPLL_DIV_MASK, + .enable_mask = OMAP4430_DPLL_EN_MASK, + .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK, + .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK, + .max_multiplier = OMAP4430_MAX_DPLL_MULT, + .max_divider = OMAP4430_MAX_DPLL_DIV, + .min_divider = 1, +}; + + +static struct clk dpll_core_ck = { + .name = "dpll_core_ck", + .parent = &dpll_sys_ref_clk, + .dpll_data = &dpll_core_dd, + .init = &omap2_init_dpll_parent, + .ops = &clkops_null, + .recalc = &omap3_dpll_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel dpll_core_m6_div[] = { + { .parent = &dpll_core_ck, .rates = div31_1to31_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_core_m6_ck = { + .name = "dpll_core_m6_ck", + .parent = &dpll_core_ck, + .clksel = dpll_core_m6_div, + .clksel_reg = OMAP4430_CM_DIV_M6_DPLL_CORE, + .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel dbgclk_mux_sel[] = { + { .parent = &sys_clkin_ck, .rates = div_1_0_rates }, + { .parent = &dpll_core_m6_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk dbgclk_mux_ck = { + .name = "dbgclk_mux_ck", + .parent = &sys_clkin_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_core_m2_ck = { + .name = "dpll_core_m2_ck", + .parent = &dpll_core_ck, + .clksel = dpll_core_m6_div, + .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_CORE, + .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk ddrphy_ck = { + .name = "ddrphy_ck", + .parent = &dpll_core_m2_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_core_m5_ck = { + .name = "dpll_core_m5_ck", + .parent = &dpll_core_ck, + .clksel = dpll_core_m6_div, + .clksel_reg = OMAP4430_CM_DIV_M5_DPLL_CORE, + .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel div_core_div[] = { + { .parent = &dpll_core_m5_ck, .rates = div2_1to2_rates }, + { .parent = NULL }, +}; + +static struct clk div_core_ck = { + .name = "div_core_ck", + .parent = &dpll_core_m5_ck, + .clksel = div_core_div, + .clksel_reg = OMAP4430_CM_CLKSEL_CORE, + .clksel_mask = OMAP4430_CLKSEL_CORE_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel_rate div4_1to8_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_4430 }, + { .div = 2, .val = 1, .flags = RATE_IN_4430 }, + { .div = 4, .val = 2, .flags = RATE_IN_4430 }, + { .div = 8, .val = 3, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel div_iva_hs_clk_div[] = { + { .parent = &dpll_core_m5_ck, .rates = div4_1to8_rates }, + { .parent = NULL }, +}; + +static struct clk div_iva_hs_clk = { + .name = "div_iva_hs_clk", + .parent = &dpll_core_m5_ck, + .clksel = div_iva_hs_clk_div, + .clksel_reg = OMAP4430_CM_BYPCLK_DPLL_IVA, + .clksel_mask = OMAP4430_CLKSEL_0_1_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk div_mpu_hs_clk = { + .name = "div_mpu_hs_clk", + .parent = &dpll_core_m5_ck, + .clksel = div_iva_hs_clk_div, + .clksel_reg = OMAP4430_CM_BYPCLK_DPLL_MPU, + .clksel_mask = OMAP4430_CLKSEL_0_1_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_core_m4_ck = { + .name = "dpll_core_m4_ck", + .parent = &dpll_core_ck, + .clksel = dpll_core_m6_div, + .clksel_reg = OMAP4430_CM_DIV_M4_DPLL_CORE, + .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dll_clk_div_ck = { + .name = "dll_clk_div_ck", + .parent = &dpll_core_m4_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_abe_m2_ck = { + .name = "dpll_abe_m2_ck", + .parent = &dpll_abe_ck, + .clksel = dpll_abe_m3_div, + .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE, + .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_core_m3_ck = { + .name = "dpll_core_m3_ck", + .parent = &dpll_core_ck, + .clksel = dpll_core_m6_div, + .clksel_reg = OMAP4430_CM_DIV_M3_DPLL_CORE, + .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_core_m7_ck = { + .name = "dpll_core_m7_ck", + .parent = &dpll_core_ck, + .clksel = dpll_core_m6_div, + .clksel_reg = OMAP4430_CM_DIV_M7_DPLL_CORE, + .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel iva_hsd_byp_clk_mux_sel[] = { + { .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates }, + { .parent = &div_iva_hs_clk, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk iva_hsd_byp_clk_mux_ck = { + .name = "iva_hsd_byp_clk_mux_ck", + .parent = &dpll_sys_ref_clk, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +/* DPLL_IVA */ +static struct dpll_data dpll_iva_dd = { + .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_IVA, + .clk_bypass = &iva_hsd_byp_clk_mux_ck, + .clk_ref = &dpll_sys_ref_clk, + .control_reg = OMAP4430_CM_CLKMODE_DPLL_IVA, + .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), + .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_IVA, + .idlest_reg = OMAP4430_CM_IDLEST_DPLL_IVA, + .mult_mask = OMAP4430_DPLL_MULT_MASK, + .div1_mask = OMAP4430_DPLL_DIV_MASK, + .enable_mask = OMAP4430_DPLL_EN_MASK, + .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK, + .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK, + .max_multiplier = OMAP4430_MAX_DPLL_MULT, + .max_divider = OMAP4430_MAX_DPLL_DIV, + .min_divider = 1, +}; + + +static struct clk dpll_iva_ck = { + .name = "dpll_iva_ck", + .parent = &dpll_sys_ref_clk, + .dpll_data = &dpll_iva_dd, + .init = &omap2_init_dpll_parent, + .ops = &clkops_noncore_dpll_ops, + .recalc = &omap3_dpll_recalc, + .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel dpll_iva_m4_div[] = { + { .parent = &dpll_iva_ck, .rates = div31_1to31_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_iva_m4_ck = { + .name = "dpll_iva_m4_ck", + .parent = &dpll_iva_ck, + .clksel = dpll_iva_m4_div, + .clksel_reg = OMAP4430_CM_DIV_M4_DPLL_IVA, + .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_iva_m5_ck = { + .name = "dpll_iva_m5_ck", + .parent = &dpll_iva_ck, + .clksel = dpll_iva_m4_div, + .clksel_reg = OMAP4430_CM_DIV_M5_DPLL_IVA, + .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +/* DPLL_MPU */ +static struct dpll_data dpll_mpu_dd = { + .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_MPU, + .clk_bypass = &div_mpu_hs_clk, + .clk_ref = &dpll_sys_ref_clk, + .control_reg = OMAP4430_CM_CLKMODE_DPLL_MPU, + .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), + .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_MPU, + .idlest_reg = OMAP4430_CM_IDLEST_DPLL_MPU, + .mult_mask = OMAP4430_DPLL_MULT_MASK, + .div1_mask = OMAP4430_DPLL_DIV_MASK, + .enable_mask = OMAP4430_DPLL_EN_MASK, + .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK, + .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK, + .max_multiplier = OMAP4430_MAX_DPLL_MULT, + .max_divider = OMAP4430_MAX_DPLL_DIV, + .min_divider = 1, +}; + + +static struct clk dpll_mpu_ck = { + .name = "dpll_mpu_ck", + .parent = &dpll_sys_ref_clk, + .dpll_data = &dpll_mpu_dd, + .init = &omap2_init_dpll_parent, + .ops = &clkops_noncore_dpll_ops, + .recalc = &omap3_dpll_recalc, + .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel dpll_mpu_m2_div[] = { + { .parent = &dpll_mpu_ck, .rates = div31_1to31_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_mpu_m2_ck = { + .name = "dpll_mpu_m2_ck", + .parent = &dpll_mpu_ck, + .clksel = dpll_mpu_m2_div, + .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_MPU, + .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk per_hs_clk_div_ck = { + .name = "per_hs_clk_div_ck", + .parent = &dpll_abe_m3_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel per_hsd_byp_clk_mux_sel[] = { + { .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates }, + { .parent = &per_hs_clk_div_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk per_hsd_byp_clk_mux_ck = { + .name = "per_hsd_byp_clk_mux_ck", + .parent = &dpll_sys_ref_clk, + .clksel = per_hsd_byp_clk_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_CLKSEL_DPLL_PER, + .clksel_mask = OMAP4430_DPLL_BYP_CLKSEL_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +/* DPLL_PER */ +static struct dpll_data dpll_per_dd = { + .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_PER, + .clk_bypass = &per_hsd_byp_clk_mux_ck, + .clk_ref = &dpll_sys_ref_clk, + .control_reg = OMAP4430_CM_CLKMODE_DPLL_PER, + .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), + .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_PER, + .idlest_reg = OMAP4430_CM_IDLEST_DPLL_PER, + .mult_mask = OMAP4430_DPLL_MULT_MASK, + .div1_mask = OMAP4430_DPLL_DIV_MASK, + .enable_mask = OMAP4430_DPLL_EN_MASK, + .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK, + .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK, + .max_multiplier = OMAP4430_MAX_DPLL_MULT, + .max_divider = OMAP4430_MAX_DPLL_DIV, + .min_divider = 1, +}; + + +static struct clk dpll_per_ck = { + .name = "dpll_per_ck", + .parent = &dpll_sys_ref_clk, + .dpll_data = &dpll_per_dd, + .init = &omap2_init_dpll_parent, + .ops = &clkops_noncore_dpll_ops, + .recalc = &omap3_dpll_recalc, + .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel dpll_per_m2_div[] = { + { .parent = &dpll_per_ck, .rates = div31_1to31_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_per_m2_ck = { + .name = "dpll_per_m2_ck", + .parent = &dpll_per_ck, + .clksel = dpll_per_m2_div, + .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER, + .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_per_m2x2_ck = { + .name = "dpll_per_m2x2_ck", + .parent = &dpll_per_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_per_m3_ck = { + .name = "dpll_per_m3_ck", + .parent = &dpll_per_ck, + .clksel = dpll_per_m2_div, + .clksel_reg = OMAP4430_CM_DIV_M3_DPLL_PER, + .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_per_m4_ck = { + .name = "dpll_per_m4_ck", + .parent = &dpll_per_ck, + .clksel = dpll_per_m2_div, + .clksel_reg = OMAP4430_CM_DIV_M4_DPLL_PER, + .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_per_m5_ck = { + .name = "dpll_per_m5_ck", + .parent = &dpll_per_ck, + .clksel = dpll_per_m2_div, + .clksel_reg = OMAP4430_CM_DIV_M5_DPLL_PER, + .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_per_m6_ck = { + .name = "dpll_per_m6_ck", + .parent = &dpll_per_ck, + .clksel = dpll_per_m2_div, + .clksel_reg = OMAP4430_CM_DIV_M6_DPLL_PER, + .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_per_m7_ck = { + .name = "dpll_per_m7_ck", + .parent = &dpll_per_ck, + .clksel = dpll_per_m2_div, + .clksel_reg = OMAP4430_CM_DIV_M7_DPLL_PER, + .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +/* DPLL_UNIPRO */ +static struct dpll_data dpll_unipro_dd = { + .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_UNIPRO, + .clk_bypass = &dpll_sys_ref_clk, + .clk_ref = &dpll_sys_ref_clk, + .control_reg = OMAP4430_CM_CLKMODE_DPLL_UNIPRO, + .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), + .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_UNIPRO, + .idlest_reg = OMAP4430_CM_IDLEST_DPLL_UNIPRO, + .mult_mask = OMAP4430_DPLL_MULT_MASK, + .div1_mask = OMAP4430_DPLL_DIV_MASK, + .enable_mask = OMAP4430_DPLL_EN_MASK, + .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK, + .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK, + .max_multiplier = OMAP4430_MAX_DPLL_MULT, + .max_divider = OMAP4430_MAX_DPLL_DIV, + .min_divider = 1, +}; + + +static struct clk dpll_unipro_ck = { + .name = "dpll_unipro_ck", + .parent = &dpll_sys_ref_clk, + .dpll_data = &dpll_unipro_dd, + .init = &omap2_init_dpll_parent, + .ops = &clkops_noncore_dpll_ops, + .recalc = &omap3_dpll_recalc, + .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel dpll_unipro_m2x2_div[] = { + { .parent = &dpll_unipro_ck, .rates = div31_1to31_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_unipro_m2x2_ck = { + .name = "dpll_unipro_m2x2_ck", + .parent = &dpll_unipro_ck, + .clksel = dpll_unipro_m2x2_div, + .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_UNIPRO, + .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk usb_hs_clk_div_ck = { + .name = "usb_hs_clk_div_ck", + .parent = &dpll_abe_m3_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +/* DPLL_USB */ +static struct dpll_data dpll_usb_dd = { + .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_USB, + .clk_bypass = &usb_hs_clk_div_ck, + .clk_ref = &dpll_sys_ref_clk, + .control_reg = OMAP4430_CM_CLKMODE_DPLL_USB, + .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), + .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_USB, + .idlest_reg = OMAP4430_CM_IDLEST_DPLL_USB, + .mult_mask = OMAP4430_DPLL_MULT_MASK, + .div1_mask = OMAP4430_DPLL_DIV_MASK, + .enable_mask = OMAP4430_DPLL_EN_MASK, + .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK, + .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK, + .max_multiplier = OMAP4430_MAX_DPLL_MULT, + .max_divider = OMAP4430_MAX_DPLL_DIV, + .min_divider = 1, +}; + + +static struct clk dpll_usb_ck = { + .name = "dpll_usb_ck", + .parent = &dpll_sys_ref_clk, + .dpll_data = &dpll_usb_dd, + .init = &omap2_init_dpll_parent, + .ops = &clkops_noncore_dpll_ops, + .recalc = &omap3_dpll_recalc, + .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk dpll_usb_clkdcoldo_ck = { + .name = "dpll_usb_clkdcoldo_ck", + .parent = &dpll_usb_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel dpll_usb_m2_div[] = { + { .parent = &dpll_usb_ck, .rates = div31_1to31_rates }, + { .parent = NULL }, +}; + +static struct clk dpll_usb_m2_ck = { + .name = "dpll_usb_m2_ck", + .parent = &dpll_usb_ck, + .clksel = dpll_usb_m2_div, + .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_USB, + .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel ducati_clk_mux_sel[] = { + { .parent = &div_core_ck, .rates = div_1_0_rates }, + { .parent = &dpll_per_m6_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk ducati_clk_mux_ck = { + .name = "ducati_clk_mux_ck", + .parent = &div_core_ck, + .clksel = ducati_clk_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_CLKSEL_DUCATI_ISS_ROOT, + .clksel_mask = OMAP4430_CLKSEL_0_0_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk func_12m_fclk = { + .name = "func_12m_fclk", + .parent = &dpll_per_m2x2_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk func_24m_clk = { + .name = "func_24m_clk", + .parent = &dpll_per_m2_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk func_24mc_fclk = { + .name = "func_24mc_fclk", + .parent = &dpll_per_m2x2_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel_rate div2_4to8_rates[] = { + { .div = 4, .val = 0, .flags = RATE_IN_4430 }, + { .div = 8, .val = 1, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel func_48m_fclk_div[] = { + { .parent = &dpll_per_m2x2_ck, .rates = div2_4to8_rates }, + { .parent = NULL }, +}; + +static struct clk func_48m_fclk = { + .name = "func_48m_fclk", + .parent = &dpll_per_m2x2_ck, + .clksel = func_48m_fclk_div, + .clksel_reg = OMAP4430_CM_SCALE_FCLK, + .clksel_mask = OMAP4430_SCALE_FCLK_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk func_48mc_fclk = { + .name = "func_48mc_fclk", + .parent = &dpll_per_m2x2_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel_rate div2_2to4_rates[] = { + { .div = 2, .val = 0, .flags = RATE_IN_4430 }, + { .div = 4, .val = 1, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel func_64m_fclk_div[] = { + { .parent = &dpll_per_m4_ck, .rates = div2_2to4_rates }, + { .parent = NULL }, +}; + +static struct clk func_64m_fclk = { + .name = "func_64m_fclk", + .parent = &dpll_per_m4_ck, + .clksel = func_64m_fclk_div, + .clksel_reg = OMAP4430_CM_SCALE_FCLK, + .clksel_mask = OMAP4430_SCALE_FCLK_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel func_96m_fclk_div[] = { + { .parent = &dpll_per_m2x2_ck, .rates = div2_2to4_rates }, + { .parent = NULL }, +}; + +static struct clk func_96m_fclk = { + .name = "func_96m_fclk", + .parent = &dpll_per_m2x2_ck, + .clksel = func_96m_fclk_div, + .clksel_reg = OMAP4430_CM_SCALE_FCLK, + .clksel_mask = OMAP4430_SCALE_FCLK_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel hsmmc6_fclk_sel[] = { + { .parent = &func_64m_fclk, .rates = div_1_0_rates }, + { .parent = &func_96m_fclk, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk hsmmc6_fclk = { + .name = "hsmmc6_fclk", + .parent = &func_64m_fclk, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel_rate div2_1to8_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_4430 }, + { .div = 8, .val = 1, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel init_60m_fclk_div[] = { + { .parent = &dpll_usb_m2_ck, .rates = div2_1to8_rates }, + { .parent = NULL }, +}; + +static struct clk init_60m_fclk = { + .name = "init_60m_fclk", + .parent = &dpll_usb_m2_ck, + .clksel = init_60m_fclk_div, + .clksel_reg = OMAP4430_CM_CLKSEL_USB_60MHZ, + .clksel_mask = OMAP4430_CLKSEL_0_0_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel l3_div_div[] = { + { .parent = &div_core_ck, .rates = div2_1to2_rates }, + { .parent = NULL }, +}; + +static struct clk l3_div_ck = { + .name = "l3_div_ck", + .parent = &div_core_ck, + .clksel = l3_div_div, + .clksel_reg = OMAP4430_CM_CLKSEL_CORE, + .clksel_mask = OMAP4430_CLKSEL_L3_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel l4_div_div[] = { + { .parent = &l3_div_ck, .rates = div2_1to2_rates }, + { .parent = NULL }, +}; + +static struct clk l4_div_ck = { + .name = "l4_div_ck", + .parent = &l3_div_ck, + .clksel = l4_div_div, + .clksel_reg = OMAP4430_CM_CLKSEL_CORE, + .clksel_mask = OMAP4430_CLKSEL_L4_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk lp_clk_div_ck = { + .name = "lp_clk_div_ck", + .parent = &dpll_abe_m2x2_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel l4_wkup_clk_mux_sel[] = { + { .parent = &sys_clkin_ck, .rates = div_1_0_rates }, + { .parent = &lp_clk_div_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk l4_wkup_clk_mux_ck = { + .name = "l4_wkup_clk_mux_ck", + .parent = &sys_clkin_ck, + .clksel = l4_wkup_clk_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_L4_WKUP_CLKSEL, + .clksel_mask = OMAP4430_CLKSEL_0_0_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel per_abe_nc_fclk_div[] = { + { .parent = &dpll_abe_m2_ck, .rates = div2_1to2_rates }, + { .parent = NULL }, +}; + +static struct clk per_abe_nc_fclk = { + .name = "per_abe_nc_fclk", + .parent = &dpll_abe_m2_ck, + .clksel = per_abe_nc_fclk_div, + .clksel_reg = OMAP4430_CM_SCALE_FCLK, + .clksel_mask = OMAP4430_SCALE_FCLK_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel mcasp2_fclk_sel[] = { + { .parent = &func_96m_fclk, .rates = div_1_0_rates }, + { .parent = &per_abe_nc_fclk, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk mcasp2_fclk = { + .name = "mcasp2_fclk", + .parent = &func_96m_fclk, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk mcasp3_fclk = { + .name = "mcasp3_fclk", + .parent = &func_96m_fclk, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk ocp_abe_iclk = { + .name = "ocp_abe_iclk", + .parent = &aess_fclk, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk per_abe_24m_fclk = { + .name = "per_abe_24m_fclk", + .parent = &dpll_abe_m2_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel pmd_stm_clock_mux_sel[] = { + { .parent = &sys_clkin_ck, .rates = div_1_0_rates }, + { .parent = &dpll_core_m6_ck, .rates = div_1_1_rates }, + { .parent = &dpll_per_m7_ck, .rates = div_1_2_rates }, + { .parent = NULL }, +}; + +static struct clk pmd_stm_clock_mux_ck = { + .name = "pmd_stm_clock_mux_ck", + .parent = &sys_clkin_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk pmd_trace_clk_mux_ck = { + .name = "pmd_trace_clk_mux_ck", + .parent = &sys_clkin_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static struct clk syc_clk_div_ck = { + .name = "syc_clk_div_ck", + .parent = &sys_clkin_ck, + .clksel = dpll_sys_ref_clk_div, + .clksel_reg = OMAP4430_CM_ABE_DSS_SYS_CLKSEL, + .clksel_mask = OMAP4430_CLKSEL_0_0_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +/* Leaf clocks controlled by modules */ + +static struct clk aes1_ck = { + .name = "aes1_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4SEC_AES1_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_secure_clkdm", + .parent = &l3_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk aes2_ck = { + .name = "aes2_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4SEC_AES2_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_secure_clkdm", + .parent = &l3_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk aess_ck = { + .name = "aess_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "abe_clkdm", + .parent = &aess_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk cust_efuse_ck = { + .name = "cust_efuse_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_cefuse_clkdm", + .parent = &sys_clkin_ck, + .recalc = &followparent_recalc, +}; + +static struct clk des3des_ck = { + .name = "des3des_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4SEC_DES3DES_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_secure_clkdm", + .parent = &l4_div_ck, + .recalc = &followparent_recalc, +}; + +static const struct clksel dmic_sync_mux_sel[] = { + { .parent = &abe_24m_fclk, .rates = div_1_0_rates }, + { .parent = &syc_clk_div_ck, .rates = div_1_1_rates }, + { .parent = &func_24m_clk, .rates = div_1_2_rates }, + { .parent = NULL }, +}; + +static struct clk dmic_sync_mux_ck = { + .name = "dmic_sync_mux_ck", + .parent = &abe_24m_fclk, + .clksel = dmic_sync_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel func_dmic_abe_gfclk_sel[] = { + { .parent = &dmic_sync_mux_ck, .rates = div_1_0_rates }, + { .parent = &pad_clks_ck, .rates = div_1_1_rates }, + { .parent = &slimbus_clk, .rates = div_1_2_rates }, + { .parent = NULL }, +}; + +/* Merged func_dmic_abe_gfclk into dmic_ck */ +static struct clk dmic_ck = { + .name = "dmic_ck", + .parent = &dmic_sync_mux_ck, + .clksel = func_dmic_abe_gfclk_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "abe_clkdm", +}; + +static struct clk dss_ck = { + .name = "dss_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l3_dss_clkdm", + .parent = &l3_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk ducati_ck = { + .name = "ducati_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_DUCATI_DUCATI_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "ducati_clkdm", + .parent = &ducati_clk_mux_ck, + .recalc = &followparent_recalc, +}; + +static struct clk emif1_ck = { + .name = "emif1_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l3_emif_clkdm", + .parent = &ddrphy_ck, + .recalc = &followparent_recalc, +}; + +static struct clk emif2_ck = { + .name = "emif2_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l3_emif_clkdm", + .parent = &ddrphy_ck, + .recalc = &followparent_recalc, +}; + +static const struct clksel fdif_fclk_div[] = { + { .parent = &dpll_per_m4_ck, .rates = div3_1to4_rates }, + { .parent = NULL }, +}; + +/* Merged fdif_fclk into fdif_ck */ +static struct clk fdif_ck = { + .name = "fdif_ck", + .parent = &dpll_per_m4_ck, + .clksel = fdif_fclk_div, + .clksel_reg = OMAP4430_CM_CAM_FDIF_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_FCLK_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM_CAM_FDIF_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "iss_clkdm", +}; + +static const struct clksel per_sgx_fclk_div[] = { + { .parent = &dpll_per_m2x2_ck, .rates = div3_1to4_rates }, + { .parent = NULL }, +}; + +static struct clk per_sgx_fclk = { + .name = "per_sgx_fclk", + .parent = &dpll_per_m2x2_ck, + .clksel = per_sgx_fclk_div, + .clksel_reg = OMAP4430_CM_GFX_GFX_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_PER_192M_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel sgx_clk_mux_sel[] = { + { .parent = &dpll_core_m7_ck, .rates = div_1_0_rates }, + { .parent = &per_sgx_fclk, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +/* Merged sgx_clk_mux into gfx_ck */ +static struct clk gfx_ck = { + .name = "gfx_ck", + .parent = &dpll_core_m7_ck, + .clksel = sgx_clk_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_GFX_GFX_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_SGX_FCLK_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM_GFX_GFX_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l3_gfx_clkdm", +}; + +static struct clk gpio1_ck = { + .name = "gpio1_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_WKUP_GPIO1_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l4_wkup_clkdm", + .parent = &l4_wkup_clk_mux_ck, + .recalc = &followparent_recalc, +}; + +static struct clk gpio2_ck = { + .name = "gpio2_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_GPIO2_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &l4_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk gpio3_ck = { + .name = "gpio3_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_GPIO3_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &l4_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk gpio4_ck = { + .name = "gpio4_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_GPIO4_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &l4_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk gpio5_ck = { + .name = "gpio5_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_GPIO5_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &l4_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk gpio6_ck = { + .name = "gpio6_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_GPIO6_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &l4_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk gpmc_ck = { + .name = "gpmc_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L3_2_GPMC_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l3_2_clkdm", + .parent = &l3_div_ck, + .recalc = &followparent_recalc, +}; + +static const struct clksel dmt1_clk_mux_sel[] = { + { .parent = &sys_clkin_ck, .rates = div_1_0_rates }, + { .parent = &sys_32k_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +/* Merged dmt1_clk_mux into gptimer1_ck */ +static struct clk gptimer1_ck = { + .name = "gptimer1_ck", + .parent = &sys_clkin_ck, + .clksel = dmt1_clk_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_WKUP_TIMER1_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM_WKUP_TIMER1_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_wkup_clkdm", +}; + +/* Merged cm2_dm10_mux into gptimer10_ck */ +static struct clk gptimer10_ck = { + .name = "gptimer10_ck", + .parent = &sys_clkin_ck, + .clksel = dmt1_clk_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", +}; + +/* Merged cm2_dm11_mux into gptimer11_ck */ +static struct clk gptimer11_ck = { + .name = "gptimer11_ck", + .parent = &sys_clkin_ck, + .clksel = dmt1_clk_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", +}; + +/* Merged cm2_dm2_mux into gptimer2_ck */ +static struct clk gptimer2_ck = { + .name = "gptimer2_ck", + .parent = &sys_clkin_ck, + .clksel = dmt1_clk_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", +}; + +/* Merged cm2_dm3_mux into gptimer3_ck */ +static struct clk gptimer3_ck = { + .name = "gptimer3_ck", + .parent = &sys_clkin_ck, + .clksel = dmt1_clk_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", +}; + +/* Merged cm2_dm4_mux into gptimer4_ck */ +static struct clk gptimer4_ck = { + .name = "gptimer4_ck", + .parent = &sys_clkin_ck, + .clksel = dmt1_clk_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", +}; + +static const struct clksel timer5_sync_mux_sel[] = { + { .parent = &syc_clk_div_ck, .rates = div_1_0_rates }, + { .parent = &sys_32k_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +/* Merged timer5_sync_mux into gptimer5_ck */ +static struct clk gptimer5_ck = { + .name = "gptimer5_ck", + .parent = &syc_clk_div_ck, + .clksel = timer5_sync_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "abe_clkdm", +}; + +/* Merged timer6_sync_mux into gptimer6_ck */ +static struct clk gptimer6_ck = { + .name = "gptimer6_ck", + .parent = &syc_clk_div_ck, + .clksel = timer5_sync_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "abe_clkdm", +}; + +/* Merged timer7_sync_mux into gptimer7_ck */ +static struct clk gptimer7_ck = { + .name = "gptimer7_ck", + .parent = &syc_clk_div_ck, + .clksel = timer5_sync_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "abe_clkdm", +}; + +/* Merged timer8_sync_mux into gptimer8_ck */ +static struct clk gptimer8_ck = { + .name = "gptimer8_ck", + .parent = &syc_clk_div_ck, + .clksel = timer5_sync_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "abe_clkdm", +}; + +/* Merged cm2_dm9_mux into gptimer9_ck */ +static struct clk gptimer9_ck = { + .name = "gptimer9_ck", + .parent = &sys_clkin_ck, + .clksel = dmt1_clk_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", +}; + +static struct clk hdq1w_ck = { + .name = "hdq1w_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_HDQ1W_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_12m_fclk, + .recalc = &followparent_recalc, +}; + +/* Merged hsi_fclk into hsi_ck */ +static struct clk hsi_ck = { + .name = "hsi_ck", + .parent = &dpll_per_m2x2_ck, + .clksel = per_sgx_fclk_div, + .clksel_reg = OMAP4430_CM_L3INIT_HSI_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_24_25_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM_L3INIT_HSI_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l3_init_clkdm", +}; + +static struct clk i2c1_ck = { + .name = "i2c1_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_I2C1_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_96m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk i2c2_ck = { + .name = "i2c2_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_I2C2_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_96m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk i2c3_ck = { + .name = "i2c3_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_I2C3_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_96m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk i2c4_ck = { + .name = "i2c4_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_I2C4_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_96m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk iss_ck = { + .name = "iss_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_CAM_ISS_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "iss_clkdm", + .parent = &ducati_clk_mux_ck, + .recalc = &followparent_recalc, +}; + +static struct clk ivahd_ck = { + .name = "ivahd_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_IVAHD_IVAHD_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "ivahd_clkdm", + .parent = &dpll_iva_m5_ck, + .recalc = &followparent_recalc, +}; + +static struct clk keyboard_ck = { + .name = "keyboard_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_wkup_clkdm", + .parent = &sys_32k_ck, + .recalc = &followparent_recalc, +}; + +static struct clk l3_instr_interconnect_ck = { + .name = "l3_instr_interconnect_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l3_instr_clkdm", + .parent = &l3_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk l3_interconnect_3_ck = { + .name = "l3_interconnect_3_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L3INSTR_L3_3_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l3_instr_clkdm", + .parent = &l3_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk mcasp_sync_mux_ck = { + .name = "mcasp_sync_mux_ck", + .parent = &abe_24m_fclk, + .clksel = dmic_sync_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM1_ABE_MCASP_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel func_mcasp_abe_gfclk_sel[] = { + { .parent = &mcasp_sync_mux_ck, .rates = div_1_0_rates }, + { .parent = &pad_clks_ck, .rates = div_1_1_rates }, + { .parent = &slimbus_clk, .rates = div_1_2_rates }, + { .parent = NULL }, +}; + +/* Merged func_mcasp_abe_gfclk into mcasp_ck */ +static struct clk mcasp_ck = { + .name = "mcasp_ck", + .parent = &mcasp_sync_mux_ck, + .clksel = func_mcasp_abe_gfclk_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM1_ABE_MCASP_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM1_ABE_MCASP_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "abe_clkdm", +}; + +static struct clk mcbsp1_sync_mux_ck = { + .name = "mcbsp1_sync_mux_ck", + .parent = &abe_24m_fclk, + .clksel = dmic_sync_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel func_mcbsp1_gfclk_sel[] = { + { .parent = &mcbsp1_sync_mux_ck, .rates = div_1_0_rates }, + { .parent = &pad_clks_ck, .rates = div_1_1_rates }, + { .parent = &slimbus_clk, .rates = div_1_2_rates }, + { .parent = NULL }, +}; + +/* Merged func_mcbsp1_gfclk into mcbsp1_ck */ +static struct clk mcbsp1_ck = { + .name = "mcbsp1_ck", + .parent = &mcbsp1_sync_mux_ck, + .clksel = func_mcbsp1_gfclk_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "abe_clkdm", +}; + +static struct clk mcbsp2_sync_mux_ck = { + .name = "mcbsp2_sync_mux_ck", + .parent = &abe_24m_fclk, + .clksel = dmic_sync_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel func_mcbsp2_gfclk_sel[] = { + { .parent = &mcbsp2_sync_mux_ck, .rates = div_1_0_rates }, + { .parent = &pad_clks_ck, .rates = div_1_1_rates }, + { .parent = &slimbus_clk, .rates = div_1_2_rates }, + { .parent = NULL }, +}; + +/* Merged func_mcbsp2_gfclk into mcbsp2_ck */ +static struct clk mcbsp2_ck = { + .name = "mcbsp2_ck", + .parent = &mcbsp2_sync_mux_ck, + .clksel = func_mcbsp2_gfclk_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "abe_clkdm", +}; + +static struct clk mcbsp3_sync_mux_ck = { + .name = "mcbsp3_sync_mux_ck", + .parent = &abe_24m_fclk, + .clksel = dmic_sync_mux_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel func_mcbsp3_gfclk_sel[] = { + { .parent = &mcbsp3_sync_mux_ck, .rates = div_1_0_rates }, + { .parent = &pad_clks_ck, .rates = div_1_1_rates }, + { .parent = &slimbus_clk, .rates = div_1_2_rates }, + { .parent = NULL }, +}; + +/* Merged func_mcbsp3_gfclk into mcbsp3_ck */ +static struct clk mcbsp3_ck = { + .name = "mcbsp3_ck", + .parent = &mcbsp3_sync_mux_ck, + .clksel = func_mcbsp3_gfclk_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "abe_clkdm", +}; + +static struct clk mcbsp4_sync_mux_ck = { + .name = "mcbsp4_sync_mux_ck", + .parent = &func_96m_fclk, + .clksel = mcasp2_fclk_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel per_mcbsp4_gfclk_sel[] = { + { .parent = &mcbsp4_sync_mux_ck, .rates = div_1_0_rates }, + { .parent = &pad_clks_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +/* Merged per_mcbsp4_gfclk into mcbsp4_ck */ +static struct clk mcbsp4_ck = { + .name = "mcbsp4_ck", + .parent = &mcbsp4_sync_mux_ck, + .clksel = per_mcbsp4_gfclk_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_SOURCE_24_24_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", +}; + +static struct clk mcspi1_ck = { + .name = "mcspi1_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_MCSPI1_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_48m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk mcspi2_ck = { + .name = "mcspi2_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_MCSPI2_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_48m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk mcspi3_ck = { + .name = "mcspi3_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_MCSPI3_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_48m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk mcspi4_ck = { + .name = "mcspi4_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_MCSPI4_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_48m_fclk, + .recalc = &followparent_recalc, +}; + +/* Merged hsmmc1_fclk into mmc1_ck */ +static struct clk mmc1_ck = { + .name = "mmc1_ck", + .parent = &func_64m_fclk, + .clksel = hsmmc6_fclk_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_L3INIT_MMC1_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM_L3INIT_MMC1_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l3_init_clkdm", +}; + +/* Merged hsmmc2_fclk into mmc2_ck */ +static struct clk mmc2_ck = { + .name = "mmc2_ck", + .parent = &func_64m_fclk, + .clksel = hsmmc6_fclk_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_L3INIT_MMC2_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_MASK, + .ops = &clkops_omap2_dflt, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, + .enable_reg = OMAP4430_CM_L3INIT_MMC2_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l3_init_clkdm", +}; + +static struct clk mmc3_ck = { + .name = "mmc3_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_MMCSD3_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_48m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk mmc4_ck = { + .name = "mmc4_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_MMCSD4_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_48m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk mmc5_ck = { + .name = "mmc5_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_MMCSD5_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_48m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk ocp_wp1_ck = { + .name = "ocp_wp1_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l3_instr_clkdm", + .parent = &l3_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk pdm_ck = { + .name = "pdm_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM1_ABE_PDM_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "abe_clkdm", + .parent = &pad_clks_ck, + .recalc = &followparent_recalc, +}; + +static struct clk pkaeip29_ck = { + .name = "pkaeip29_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_secure_clkdm", + .parent = &l4_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk rng_ck = { + .name = "rng_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4SEC_RNG_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l4_secure_clkdm", + .parent = &l4_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk sha2md51_ck = { + .name = "sha2md51_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_secure_clkdm", + .parent = &l3_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk sl2_ck = { + .name = "sl2_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_IVAHD_SL2_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "ivahd_clkdm", + .parent = &dpll_iva_m5_ck, + .recalc = &followparent_recalc, +}; + +static struct clk slimbus1_ck = { + .name = "slimbus1_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "abe_clkdm", + .parent = &ocp_abe_iclk, + .recalc = &followparent_recalc, +}; + +static struct clk slimbus2_ck = { + .name = "slimbus2_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &l4_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk sr_core_ck = { + .name = "sr_core_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_ao_clkdm", + .parent = &l4_wkup_clk_mux_ck, + .recalc = &followparent_recalc, +}; + +static struct clk sr_iva_ck = { + .name = "sr_iva_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_ao_clkdm", + .parent = &l4_wkup_clk_mux_ck, + .recalc = &followparent_recalc, +}; + +static struct clk sr_mpu_ck = { + .name = "sr_mpu_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_ao_clkdm", + .parent = &l4_wkup_clk_mux_ck, + .recalc = &followparent_recalc, +}; + +static struct clk tesla_ck = { + .name = "tesla_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_TESLA_TESLA_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "tesla_clkdm", + .parent = &dpll_iva_m4_ck, + .recalc = &followparent_recalc, +}; + +static struct clk uart1_ck = { + .name = "uart1_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_UART1_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_48m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk uart2_ck = { + .name = "uart2_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_UART2_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_48m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk uart3_ck = { + .name = "uart3_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_UART3_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_48m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk uart4_ck = { + .name = "uart4_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L4PER_UART4_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_per_clkdm", + .parent = &func_48m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk unipro1_ck = { + .name = "unipro1_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L3INIT_UNIPRO1_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l3_init_clkdm", + .parent = &func_96m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk usb_host_ck = { + .name = "usb_host_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l3_init_clkdm", + .parent = &init_60m_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk usb_host_fs_ck = { + .name = "usb_host_fs_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_FS_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l3_init_clkdm", + .parent = &func_48mc_fclk, + .recalc = &followparent_recalc, +}; + +static struct clk usb_otg_ck = { + .name = "usb_otg_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l3_init_clkdm", + .parent = &l3_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk usb_tll_ck = { + .name = "usb_tll_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l3_init_clkdm", + .parent = &l4_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk usbphyocp2scp_ck = { + .name = "usbphyocp2scp_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .clkdm_name = "l3_init_clkdm", + .parent = &l4_div_ck, + .recalc = &followparent_recalc, +}; + +static struct clk usim_ck = { + .name = "usim_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_WKUP_USIM_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_wkup_clkdm", + .parent = &sys_32k_ck, + .recalc = &followparent_recalc, +}; + +static struct clk wdt2_ck = { + .name = "wdt2_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_WKUP_WDT2_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "l4_wkup_clkdm", + .parent = &sys_32k_ck, + .recalc = &followparent_recalc, +}; + +static struct clk wdt3_ck = { + .name = "wdt3_ck", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM1_ABE_WDT3_CLKCTRL, + .enable_bit = OMAP4430_MODULEMODE_SWCTRL, + .clkdm_name = "abe_clkdm", + .parent = &sys_32k_ck, + .recalc = &followparent_recalc, +}; + +/* Remaining optional clocks */ +static const struct clksel otg_60m_gfclk_sel[] = { + { .parent = &utmi_phy_clkout_ck, .rates = div_1_0_rates }, + { .parent = &xclk60motg_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk otg_60m_gfclk_ck = { + .name = "otg_60m_gfclk_ck", + .parent = &utmi_phy_clkout_ck, + .clksel = otg_60m_gfclk_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_60M_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel stm_clk_div_div[] = { + { .parent = &pmd_stm_clock_mux_ck, .rates = div3_1to4_rates }, + { .parent = NULL }, +}; + +static struct clk stm_clk_div_ck = { + .name = "stm_clk_div_ck", + .parent = &pmd_stm_clock_mux_ck, + .clksel = stm_clk_div_div, + .clksel_reg = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_PMD_STM_CLK_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel trace_clk_div_div[] = { + { .parent = &pmd_trace_clk_mux_ck, .rates = div3_1to4_rates }, + { .parent = NULL }, +}; + +static struct clk trace_clk_div_ck = { + .name = "trace_clk_div_ck", + .parent = &pmd_trace_clk_mux_ck, + .clksel = trace_clk_div_div, + .clksel_reg = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel_rate div2_14to18_rates[] = { + { .div = 14, .val = 0, .flags = RATE_IN_4430 }, + { .div = 18, .val = 1, .flags = RATE_IN_4430 }, + { .div = 0 }, +}; + +static const struct clksel usim_fclk_div[] = { + { .parent = &dpll_per_m4_ck, .rates = div2_14to18_rates }, + { .parent = NULL }, +}; + +static struct clk usim_fclk = { + .name = "usim_fclk", + .parent = &dpll_per_m4_ck, + .clksel = usim_fclk_div, + .clksel_reg = OMAP4430_CM_WKUP_USIM_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_DIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel utmi_p1_gfclk_sel[] = { + { .parent = &init_60m_fclk, .rates = div_1_0_rates }, + { .parent = &xclk60mhsp1_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk utmi_p1_gfclk_ck = { + .name = "utmi_p1_gfclk_ck", + .parent = &init_60m_fclk, + .clksel = utmi_p1_gfclk_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_UTMI_P1_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +static const struct clksel utmi_p2_gfclk_sel[] = { + { .parent = &init_60m_fclk, .rates = div_1_0_rates }, + { .parent = &xclk60mhsp2_ck, .rates = div_1_1_rates }, + { .parent = NULL }, +}; + +static struct clk utmi_p2_gfclk_ck = { + .name = "utmi_p2_gfclk_ck", + .parent = &init_60m_fclk, + .clksel = utmi_p2_gfclk_sel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_UTMI_P2_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .flags = CLOCK_IN_OMAP4430, +}; + +/* + * clkdev + */ + +static struct omap_clk omap44xx_clks[] = { + CLK(NULL, "extalt_clkin_ck", &extalt_clkin_ck, CK_443X), + CLK(NULL, "pad_clks_ck", &pad_clks_ck, CK_443X), + CLK(NULL, "pad_slimbus_core_clks_ck", &pad_slimbus_core_clks_ck, CK_443X), + CLK(NULL, "secure_32k_clk_src_ck", &secure_32k_clk_src_ck, CK_443X), + CLK(NULL, "slimbus_clk", &slimbus_clk, CK_443X), + CLK(NULL, "sys_32k_ck", &sys_32k_ck, CK_443X), + CLK(NULL, "virt_12000000_ck", &virt_12000000_ck, CK_443X), + CLK(NULL, "virt_13000000_ck", &virt_13000000_ck, CK_443X), + CLK(NULL, "virt_16800000_ck", &virt_16800000_ck, CK_443X), + CLK(NULL, "virt_19200000_ck", &virt_19200000_ck, CK_443X), + CLK(NULL, "virt_26000000_ck", &virt_26000000_ck, CK_443X), + CLK(NULL, "virt_27000000_ck", &virt_27000000_ck, CK_443X), + CLK(NULL, "virt_38400000_ck", &virt_38400000_ck, CK_443X), + CLK(NULL, "sys_clkin_ck", &sys_clkin_ck, CK_443X), + CLK(NULL, "utmi_phy_clkout_ck", &utmi_phy_clkout_ck, CK_443X), + CLK(NULL, "xclk60mhsp1_ck", &xclk60mhsp1_ck, CK_443X), + CLK(NULL, "xclk60mhsp2_ck", &xclk60mhsp2_ck, CK_443X), + CLK(NULL, "xclk60motg_ck", &xclk60motg_ck, CK_443X), + CLK(NULL, "dpll_sys_ref_clk", &dpll_sys_ref_clk, CK_443X), + CLK(NULL, "abe_dpll_refclk_mux_ck", &abe_dpll_refclk_mux_ck, CK_443X), + CLK(NULL, "dpll_abe_ck", &dpll_abe_ck, CK_443X), + CLK(NULL, "dpll_abe_m2x2_ck", &dpll_abe_m2x2_ck, CK_443X), + CLK(NULL, "abe_24m_fclk", &abe_24m_fclk, CK_443X), + CLK(NULL, "abe_clk", &abe_clk, CK_443X), + CLK(NULL, "aess_fclk", &aess_fclk, CK_443X), + CLK(NULL, "dpll_abe_m3_ck", &dpll_abe_m3_ck, CK_443X), + CLK(NULL, "core_hsd_byp_clk_mux_ck", &core_hsd_byp_clk_mux_ck, CK_443X), + CLK(NULL, "dpll_core_ck", &dpll_core_ck, CK_443X), + CLK(NULL, "dpll_core_m6_ck", &dpll_core_m6_ck, CK_443X), + CLK(NULL, "dbgclk_mux_ck", &dbgclk_mux_ck, CK_443X), + CLK(NULL, "dpll_core_m2_ck", &dpll_core_m2_ck, CK_443X), + CLK(NULL, "ddrphy_ck", &ddrphy_ck, CK_443X), + CLK(NULL, "dpll_core_m5_ck", &dpll_core_m5_ck, CK_443X), + CLK(NULL, "div_core_ck", &div_core_ck, CK_443X), + CLK(NULL, "div_iva_hs_clk", &div_iva_hs_clk, CK_443X), + CLK(NULL, "div_mpu_hs_clk", &div_mpu_hs_clk, CK_443X), + CLK(NULL, "dpll_core_m4_ck", &dpll_core_m4_ck, CK_443X), + CLK(NULL, "dll_clk_div_ck", &dll_clk_div_ck, CK_443X), + CLK(NULL, "dpll_abe_m2_ck", &dpll_abe_m2_ck, CK_443X), + CLK(NULL, "dpll_core_m3_ck", &dpll_core_m3_ck, CK_443X), + CLK(NULL, "dpll_core_m7_ck", &dpll_core_m7_ck, CK_443X), + CLK(NULL, "iva_hsd_byp_clk_mux_ck", &iva_hsd_byp_clk_mux_ck, CK_443X), + CLK(NULL, "dpll_iva_ck", &dpll_iva_ck, CK_443X), + CLK(NULL, "dpll_iva_m4_ck", &dpll_iva_m4_ck, CK_443X), + CLK(NULL, "dpll_iva_m5_ck", &dpll_iva_m5_ck, CK_443X), + CLK(NULL, "dpll_mpu_ck", &dpll_mpu_ck, CK_443X), + CLK(NULL, "dpll_mpu_m2_ck", &dpll_mpu_m2_ck, CK_443X), + CLK(NULL, "per_hs_clk_div_ck", &per_hs_clk_div_ck, CK_443X), + CLK(NULL, "per_hsd_byp_clk_mux_ck", &per_hsd_byp_clk_mux_ck, CK_443X), + CLK(NULL, "dpll_per_ck", &dpll_per_ck, CK_443X), + CLK(NULL, "dpll_per_m2_ck", &dpll_per_m2_ck, CK_443X), + CLK(NULL, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck, CK_443X), + CLK(NULL, "dpll_per_m3_ck", &dpll_per_m3_ck, CK_443X), + CLK(NULL, "dpll_per_m4_ck", &dpll_per_m4_ck, CK_443X), + CLK(NULL, "dpll_per_m5_ck", &dpll_per_m5_ck, CK_443X), + CLK(NULL, "dpll_per_m6_ck", &dpll_per_m6_ck, CK_443X), + CLK(NULL, "dpll_per_m7_ck", &dpll_per_m7_ck, CK_443X), + CLK(NULL, "dpll_unipro_ck", &dpll_unipro_ck, CK_443X), + CLK(NULL, "dpll_unipro_m2x2_ck", &dpll_unipro_m2x2_ck, CK_443X), + CLK(NULL, "usb_hs_clk_div_ck", &usb_hs_clk_div_ck, CK_443X), + CLK(NULL, "dpll_usb_ck", &dpll_usb_ck, CK_443X), + CLK(NULL, "dpll_usb_clkdcoldo_ck", &dpll_usb_clkdcoldo_ck, CK_443X), + CLK(NULL, "dpll_usb_m2_ck", &dpll_usb_m2_ck, CK_443X), + CLK(NULL, "ducati_clk_mux_ck", &ducati_clk_mux_ck, CK_443X), + CLK(NULL, "func_12m_fclk", &func_12m_fclk, CK_443X), + CLK(NULL, "func_24m_clk", &func_24m_clk, CK_443X), + CLK(NULL, "func_24mc_fclk", &func_24mc_fclk, CK_443X), + CLK(NULL, "func_48m_fclk", &func_48m_fclk, CK_443X), + CLK(NULL, "func_48mc_fclk", &func_48mc_fclk, CK_443X), + CLK(NULL, "func_64m_fclk", &func_64m_fclk, CK_443X), + CLK(NULL, "func_96m_fclk", &func_96m_fclk, CK_443X), + CLK(NULL, "hsmmc6_fclk", &hsmmc6_fclk, CK_443X), + CLK(NULL, "init_60m_fclk", &init_60m_fclk, CK_443X), + CLK(NULL, "l3_div_ck", &l3_div_ck, CK_443X), + CLK(NULL, "l4_div_ck", &l4_div_ck, CK_443X), + CLK(NULL, "lp_clk_div_ck", &lp_clk_div_ck, CK_443X), + CLK(NULL, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck, CK_443X), + CLK(NULL, "per_abe_nc_fclk", &per_abe_nc_fclk, CK_443X), + CLK(NULL, "mcasp2_fclk", &mcasp2_fclk, CK_443X), + CLK(NULL, "mcasp3_fclk", &mcasp3_fclk, CK_443X), + CLK(NULL, "ocp_abe_iclk", &ocp_abe_iclk, CK_443X), + CLK(NULL, "per_abe_24m_fclk", &per_abe_24m_fclk, CK_443X), + CLK(NULL, "pmd_stm_clock_mux_ck", &pmd_stm_clock_mux_ck, CK_443X), + CLK(NULL, "pmd_trace_clk_mux_ck", &pmd_trace_clk_mux_ck, CK_443X), + CLK(NULL, "syc_clk_div_ck", &syc_clk_div_ck, CK_443X), + CLK(NULL, "aes1_ck", &aes1_ck, CK_443X), + CLK(NULL, "aes2_ck", &aes2_ck, CK_443X), + CLK(NULL, "aess_ck", &aess_ck, CK_443X), + CLK(NULL, "cust_efuse_ck", &cust_efuse_ck, CK_443X), + CLK(NULL, "des3des_ck", &des3des_ck, CK_443X), + CLK(NULL, "dmic_sync_mux_ck", &dmic_sync_mux_ck, CK_443X), + CLK(NULL, "dmic_ck", &dmic_ck, CK_443X), + CLK(NULL, "dss_ck", &dss_ck, CK_443X), + CLK(NULL, "ducati_ck", &ducati_ck, CK_443X), + CLK(NULL, "emif1_ck", &emif1_ck, CK_443X), + CLK(NULL, "emif2_ck", &emif2_ck, CK_443X), + CLK(NULL, "fdif_ck", &fdif_ck, CK_443X), + CLK(NULL, "per_sgx_fclk", &per_sgx_fclk, CK_443X), + CLK(NULL, "gfx_ck", &gfx_ck, CK_443X), + CLK(NULL, "gpio1_ck", &gpio1_ck, CK_443X), + CLK(NULL, "gpio2_ck", &gpio2_ck, CK_443X), + CLK(NULL, "gpio3_ck", &gpio3_ck, CK_443X), + CLK(NULL, "gpio4_ck", &gpio4_ck, CK_443X), + CLK(NULL, "gpio5_ck", &gpio5_ck, CK_443X), + CLK(NULL, "gpio6_ck", &gpio6_ck, CK_443X), + CLK(NULL, "gpmc_ck", &gpmc_ck, CK_443X), + CLK(NULL, "gptimer1_ck", &gptimer1_ck, CK_443X), + CLK(NULL, "gptimer10_ck", &gptimer10_ck, CK_443X), + CLK(NULL, "gptimer11_ck", &gptimer11_ck, CK_443X), + CLK(NULL, "gptimer2_ck", &gptimer2_ck, CK_443X), + CLK(NULL, "gptimer3_ck", &gptimer3_ck, CK_443X), + CLK(NULL, "gptimer4_ck", &gptimer4_ck, CK_443X), + CLK(NULL, "gptimer5_ck", &gptimer5_ck, CK_443X), + CLK(NULL, "gptimer6_ck", &gptimer6_ck, CK_443X), + CLK(NULL, "gptimer7_ck", &gptimer7_ck, CK_443X), + CLK(NULL, "gptimer8_ck", &gptimer8_ck, CK_443X), + CLK(NULL, "gptimer9_ck", &gptimer9_ck, CK_443X), + CLK("omap2_hdq.0", "ick", &hdq1w_ck, CK_443X), + CLK(NULL, "hsi_ck", &hsi_ck, CK_443X), + CLK("i2c_omap.1", "ick", &i2c1_ck, CK_443X), + CLK("i2c_omap.2", "ick", &i2c2_ck, CK_443X), + CLK("i2c_omap.3", "ick", &i2c3_ck, CK_443X), + CLK("i2c_omap.4", "ick", &i2c4_ck, CK_443X), + CLK(NULL, "iss_ck", &iss_ck, CK_443X), + CLK(NULL, "ivahd_ck", &ivahd_ck, CK_443X), + CLK(NULL, "keyboard_ck", &keyboard_ck, CK_443X), + CLK(NULL, "l3_instr_interconnect_ck", &l3_instr_interconnect_ck, CK_443X), + CLK(NULL, "l3_interconnect_3_ck", &l3_interconnect_3_ck, CK_443X), + CLK(NULL, "mcasp_sync_mux_ck", &mcasp_sync_mux_ck, CK_443X), + CLK(NULL, "mcasp_ck", &mcasp_ck, CK_443X), + CLK(NULL, "mcbsp1_sync_mux_ck", &mcbsp1_sync_mux_ck, CK_443X), + CLK("omap-mcbsp.1", "fck", &mcbsp1_ck, CK_443X), + CLK(NULL, "mcbsp2_sync_mux_ck", &mcbsp2_sync_mux_ck, CK_443X), + CLK("omap-mcbsp.2", "fck", &mcbsp2_ck, CK_443X), + CLK(NULL, "mcbsp3_sync_mux_ck", &mcbsp3_sync_mux_ck, CK_443X), + CLK("omap-mcbsp.3", "fck", &mcbsp3_ck, CK_443X), + CLK(NULL, "mcbsp4_sync_mux_ck", &mcbsp4_sync_mux_ck, CK_443X), + CLK("omap-mcbsp.4", "fck", &mcbsp4_ck, CK_443X), + CLK("omap2_mcspi.1", "fck", &mcspi1_ck, CK_443X), + CLK("omap2_mcspi.2", "fck", &mcspi2_ck, CK_443X), + CLK("omap2_mcspi.3", "fck", &mcspi3_ck, CK_443X), + CLK("omap2_mcspi.4", "fck", &mcspi4_ck, CK_443X), + CLK("mmci-omap-hs.0", "fck", &mmc1_ck, CK_443X), + CLK("mmci-omap-hs.1", "fck", &mmc2_ck, CK_443X), + CLK("mmci-omap-hs.2", "fck", &mmc3_ck, CK_443X), + CLK("mmci-omap-hs.3", "fck", &mmc4_ck, CK_443X), + CLK("mmci-omap-hs.4", "fck", &mmc5_ck, CK_443X), + CLK(NULL, "ocp_wp1_ck", &ocp_wp1_ck, CK_443X), + CLK(NULL, "pdm_ck", &pdm_ck, CK_443X), + CLK(NULL, "pkaeip29_ck", &pkaeip29_ck, CK_443X), + CLK("omap_rng", "ick", &rng_ck, CK_443X), + CLK(NULL, "sha2md51_ck", &sha2md51_ck, CK_443X), + CLK(NULL, "sl2_ck", &sl2_ck, CK_443X), + CLK(NULL, "slimbus1_ck", &slimbus1_ck, CK_443X), + CLK(NULL, "slimbus2_ck", &slimbus2_ck, CK_443X), + CLK(NULL, "sr_core_ck", &sr_core_ck, CK_443X), + CLK(NULL, "sr_iva_ck", &sr_iva_ck, CK_443X), + CLK(NULL, "sr_mpu_ck", &sr_mpu_ck, CK_443X), + CLK(NULL, "tesla_ck", &tesla_ck, CK_443X), + CLK(NULL, "uart1_ck", &uart1_ck, CK_443X), + CLK(NULL, "uart2_ck", &uart2_ck, CK_443X), + CLK(NULL, "uart3_ck", &uart3_ck, CK_443X), + CLK(NULL, "uart4_ck", &uart4_ck, CK_443X), + CLK(NULL, "unipro1_ck", &unipro1_ck, CK_443X), + CLK(NULL, "usb_host_ck", &usb_host_ck, CK_443X), + CLK(NULL, "usb_host_fs_ck", &usb_host_fs_ck, CK_443X), + CLK("musb_hdrc", "ick", &usb_otg_ck, CK_443X), + CLK(NULL, "usb_tll_ck", &usb_tll_ck, CK_443X), + CLK(NULL, "usbphyocp2scp_ck", &usbphyocp2scp_ck, CK_443X), + CLK(NULL, "usim_ck", &usim_ck, CK_443X), + CLK("omap_wdt", "fck", &wdt2_ck, CK_443X), + CLK(NULL, "wdt3_ck", &wdt3_ck, CK_443X), + CLK(NULL, "otg_60m_gfclk_ck", &otg_60m_gfclk_ck, CK_443X), + CLK(NULL, "stm_clk_div_ck", &stm_clk_div_ck, CK_443X), + CLK(NULL, "trace_clk_div_ck", &trace_clk_div_ck, CK_443X), + CLK(NULL, "usim_fclk", &usim_fclk, CK_443X), + CLK(NULL, "utmi_p1_gfclk_ck", &utmi_p1_gfclk_ck, CK_443X), + CLK(NULL, "utmi_p2_gfclk_ck", &utmi_p2_gfclk_ck, CK_443X), +}; + +int __init omap2_clk_init(void) +{ + /* struct prcm_config *prcm; */ + struct omap_clk *c; + /* u32 clkrate; */ + u32 cpu_clkflg; + + if (cpu_is_omap44xx()) { + cpu_mask = RATE_IN_4430; + cpu_clkflg = CK_443X; + } + + clk_init(&omap2_clk_functions); + + for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks); + c++) + clk_preinit(c->lk.clk); + + for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks); + c++) + if (c->cpu & cpu_clkflg) { + clkdev_add(&c->lk); + clk_register(c->lk.clk); + /* TODO + omap2_init_clk_clkdm(c->lk.clk); + */ + } + + recalculate_root_clocks(); + + /* + * Only enable those clocks we will need, let the drivers + * enable other clocks as necessary + */ + clk_enable_init_clocks(); + + return 0; +} diff --git a/arch/arm/mach-omap2/clock_common_data.c b/arch/arm/mach-omap2/clock_common_data.c new file mode 100644 index 0000000000000000000000000000000000000000..f69096b88cdbc3503c8a88a64ca0ebf95fc7a927 --- /dev/null +++ b/arch/arm/mach-omap2/clock_common_data.c @@ -0,0 +1,39 @@ +/* + * linux/arch/arm/mach-omap2/clock_common_data.c + * + * Copyright (C) 2005-2009 Texas Instruments, Inc. + * Copyright (C) 2004-2009 Nokia Corporation + * + * Contacts: + * Richard Woodruff + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This file contains clock data that is common to both the OMAP2xxx and + * OMAP3xxx clock definition files. + */ + +#include "clock.h" + +/* clksel_rate data common to 24xx/343x */ +const struct clksel_rate gpt_32k_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +const struct clksel_rate gpt_sys_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +const struct clksel_rate gfx_l3_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_343X }, + { .div = 2, .val = 2, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE }, + { .div = 3, .val = 3, .flags = RATE_IN_243X | RATE_IN_343X }, + { .div = 4, .val = 4, .flags = RATE_IN_243X | RATE_IN_343X }, + { .div = 0 } +}; + diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index fcd82320a6a36d6a15bbd30e0b7c3d7ec13b8edb..1a45ed1e8ba1096e33e8b3dd5a3d1432a3547149 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -2,7 +2,7 @@ * OMAP2/3 clockdomain framework functions * * Copyright (C) 2008 Texas Instruments, Inc. - * Copyright (C) 2008 Nokia Corporation + * Copyright (C) 2008-2009 Nokia Corporation * * Written by Paul Walmsley and Jouni Högander * @@ -10,9 +10,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#ifdef CONFIG_OMAP_DEBUG_CLOCKDOMAIN -# define DEBUG -#endif +#undef DEBUG #include #include diff --git a/arch/arm/mach-omap2/cm-regbits-44xx.h b/arch/arm/mach-omap2/cm-regbits-44xx.h new file mode 100644 index 0000000000000000000000000000000000000000..0e67f75aa35c6ff7b8176d9abb71ed1fa1e5a592 --- /dev/null +++ b/arch/arm/mach-omap2/cm-regbits-44xx.h @@ -0,0 +1,1474 @@ +/* + * OMAP44xx Clock Management register bits + * + * Copyright (C) 2009 Texas Instruments, Inc. + * Copyright (C) 2009 Nokia Corporation + * + * Paul Walmsley (paul@pwsan.com) + * Rajendra Nayak (rnayak@ti.com) + * Benoit Cousson (b-cousson@ti.com) + * + * This file is automatically generated from the OMAP hardware databases. + * We respectfully ask that any modifications to this file be coordinated + * with the public linux-omap@vger.kernel.org mailing list and the + * authors above to ensure that the autogeneration scripts are kept + * up-to-date with the file contents. + * + * 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. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_CM_REGBITS_44XX_H +#define __ARCH_ARM_MACH_OMAP2_CM_REGBITS_44XX_H + +#include "cm.h" + + +/* Used by CM_L3_1_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP */ +#define OMAP4430_ABE_DYNDEP_SHIFT (1 << 3) +#define OMAP4430_ABE_DYNDEP_MASK BITFIELD(3, 3) + +/* + * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, + * CM_L3INIT_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP, + * CM_TESLA_STATICDEP + */ +#define OMAP4430_ABE_STATDEP_SHIFT (1 << 3) +#define OMAP4430_ABE_STATDEP_MASK BITFIELD(3, 3) + +/* Used by CM_L4CFG_DYNAMICDEP */ +#define OMAP4430_ALWONCORE_DYNDEP_SHIFT (1 << 16) +#define OMAP4430_ALWONCORE_DYNDEP_MASK BITFIELD(16, 16) + +/* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_TESLA_STATICDEP */ +#define OMAP4430_ALWONCORE_STATDEP_SHIFT (1 << 16) +#define OMAP4430_ALWONCORE_STATDEP_MASK BITFIELD(16, 16) + +/* + * Used by CM_AUTOIDLE_DPLL_PER, CM_AUTOIDLE_DPLL_UNIPRO, CM_AUTOIDLE_DPLL_USB, + * CM_AUTOIDLE_DPLL_CORE_RESTORE, CM_AUTOIDLE_DPLL_ABE, CM_AUTOIDLE_DPLL_CORE, + * CM_AUTOIDLE_DPLL_DDRPHY, CM_AUTOIDLE_DPLL_IVA, CM_AUTOIDLE_DPLL_MPU + */ +#define OMAP4430_AUTO_DPLL_MODE_SHIFT (1 << 0) +#define OMAP4430_AUTO_DPLL_MODE_MASK BITFIELD(0, 2) + +/* Used by CM_L4CFG_DYNAMICDEP */ +#define OMAP4430_CEFUSE_DYNDEP_SHIFT (1 << 17) +#define OMAP4430_CEFUSE_DYNDEP_MASK BITFIELD(17, 17) + +/* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_TESLA_STATICDEP */ +#define OMAP4430_CEFUSE_STATDEP_SHIFT (1 << 17) +#define OMAP4430_CEFUSE_STATDEP_MASK BITFIELD(17, 17) + +/* Used by CM1_ABE_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_SHIFT (1 << 13) +#define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_MASK BITFIELD(13, 13) + +/* Used by CM1_ABE_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_SHIFT (1 << 12) +#define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_MASK BITFIELD(12, 12) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_ABE_LP_CLK_SHIFT (1 << 9) +#define OMAP4430_CLKACTIVITY_ABE_LP_CLK_MASK BITFIELD(9, 9) + +/* Used by CM1_ABE_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_ABE_SYSCLK_SHIFT (1 << 11) +#define OMAP4430_CLKACTIVITY_ABE_SYSCLK_MASK BITFIELD(11, 11) + +/* Used by CM1_ABE_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_ABE_X2_CLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_ABE_X2_CLK_MASK BITFIELD(8, 8) + +/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_SHIFT (1 << 11) +#define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_MASK BITFIELD(11, 11) + +/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_SHIFT (1 << 12) +#define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_MASK BITFIELD(12, 12) + +/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_SHIFT (1 << 13) +#define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_MASK BITFIELD(13, 13) + +/* Used by CM_CAM_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_SHIFT (1 << 9) +#define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_MASK BITFIELD(9, 9) + +/* Used by CM_EMU_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_SHIFT (1 << 9) +#define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_MASK BITFIELD(9, 9) + +/* Used by CM_CEFUSE_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_SHIFT (1 << 9) +#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK BITFIELD(9, 9) + +/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_DLL_CLK_SHIFT (1 << 9) +#define OMAP4430_CLKACTIVITY_DLL_CLK_MASK BITFIELD(9, 9) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_DMT10_GFCLK_SHIFT (1 << 9) +#define OMAP4430_CLKACTIVITY_DMT10_GFCLK_MASK BITFIELD(9, 9) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_DMT11_GFCLK_SHIFT (1 << 10) +#define OMAP4430_CLKACTIVITY_DMT11_GFCLK_MASK BITFIELD(10, 10) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_DMT2_GFCLK_SHIFT (1 << 11) +#define OMAP4430_CLKACTIVITY_DMT2_GFCLK_MASK BITFIELD(11, 11) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_DMT3_GFCLK_SHIFT (1 << 12) +#define OMAP4430_CLKACTIVITY_DMT3_GFCLK_MASK BITFIELD(12, 12) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_DMT4_GFCLK_SHIFT (1 << 13) +#define OMAP4430_CLKACTIVITY_DMT4_GFCLK_MASK BITFIELD(13, 13) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_DMT9_GFCLK_SHIFT (1 << 14) +#define OMAP4430_CLKACTIVITY_DMT9_GFCLK_MASK BITFIELD(14, 14) + +/* Used by CM_DSS_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_SHIFT (1 << 10) +#define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_MASK BITFIELD(10, 10) + +/* Used by CM_DSS_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_DSS_FCLK_SHIFT (1 << 9) +#define OMAP4430_CLKACTIVITY_DSS_FCLK_MASK BITFIELD(9, 9) + +/* Used by CM_DUCATI_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_DUCATI_GCLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_DUCATI_GCLK_MASK BITFIELD(8, 8) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_EMAC_50MHZ_CLK_SHIFT (1 << 10) +#define OMAP4430_CLKACTIVITY_EMAC_50MHZ_CLK_MASK BITFIELD(10, 10) + +/* Used by CM_EMU_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_EMU_SYS_CLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_EMU_SYS_CLK_MASK BITFIELD(8, 8) + +/* Used by CM_CAM_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_FDIF_GFCLK_SHIFT (1 << 10) +#define OMAP4430_CLKACTIVITY_FDIF_GFCLK_MASK BITFIELD(10, 10) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_SHIFT (1 << 15) +#define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_MASK BITFIELD(15, 15) + +/* Used by CM1_ABE_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_SHIFT (1 << 10) +#define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_MASK BITFIELD(10, 10) + +/* Used by CM_DSS_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_SHIFT (1 << 11) +#define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_MASK BITFIELD(11, 11) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_SHIFT (1 << 20) +#define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_MASK BITFIELD(20, 20) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_SHIFT (1 << 26) +#define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_MASK BITFIELD(26, 26) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_SHIFT (1 << 21) +#define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_MASK BITFIELD(21, 21) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_SHIFT (1 << 27) +#define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_MASK BITFIELD(27, 27) + +/* Used by CM_L3INIT_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_INIT_32K_GFCLK_SHIFT (1 << 31) +#define OMAP4430_CLKACTIVITY_INIT_32K_GFCLK_MASK BITFIELD(31, 31) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_SHIFT (1 << 13) +#define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_MASK BITFIELD(13, 13) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_SHIFT (1 << 12) +#define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_MASK BITFIELD(12, 12) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_SHIFT (1 << 28) +#define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_MASK BITFIELD(28, 28) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_SHIFT (1 << 29) +#define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_MASK BITFIELD(29, 29) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_SHIFT (1 << 11) +#define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_MASK BITFIELD(11, 11) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_SHIFT (1 << 16) +#define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_MASK BITFIELD(16, 16) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_SHIFT (1 << 17) +#define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_MASK BITFIELD(17, 17) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_SHIFT (1 << 18) +#define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_MASK BITFIELD(18, 18) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_SHIFT (1 << 19) +#define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_MASK BITFIELD(19, 19) + +/* Used by CM_CAM_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_ISS_GCLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_ISS_GCLK_MASK BITFIELD(8, 8) + +/* Used by CM_IVAHD_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_MASK BITFIELD(8, 8) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_L3INIT_DPLL_ALWON_CLK_SHIFT (1 << 14) +#define OMAP4430_CLKACTIVITY_L3INIT_DPLL_ALWON_CLK_MASK BITFIELD(14, 14) + +/* Used by CM_L3_1_CLKSTCTRL, CM_L3_1_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_L3_1_GICLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_L3_1_GICLK_MASK BITFIELD(8, 8) + +/* Used by CM_L3_2_CLKSTCTRL, CM_L3_2_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_L3_2_GICLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_L3_2_GICLK_MASK BITFIELD(8, 8) + +/* Used by CM_D2D_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_MASK BITFIELD(8, 8) + +/* Used by CM_SDMA_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_MASK BITFIELD(8, 8) + +/* Used by CM_DSS_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_MASK BITFIELD(8, 8) + +/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_MASK BITFIELD(8, 8) + +/* Used by CM_GFX_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_MASK BITFIELD(8, 8) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_MASK BITFIELD(8, 8) + +/* Used by CM_L3INSTR_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_MASK BITFIELD(8, 8) + +/* Used by CM_L4SEC_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_MASK BITFIELD(8, 8) + +/* Used by CM_ALWON_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_L4_AO_ICLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_L4_AO_ICLK_MASK BITFIELD(8, 8) + +/* Used by CM_CEFUSE_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_MASK BITFIELD(8, 8) + +/* Used by CM_L4CFG_CLKSTCTRL, CM_L4CFG_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_MASK BITFIELD(8, 8) + +/* Used by CM_D2D_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_SHIFT (1 << 9) +#define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_MASK BITFIELD(9, 9) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_SHIFT (1 << 9) +#define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_MASK BITFIELD(9, 9) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_L4_PER_GICLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_L4_PER_GICLK_MASK BITFIELD(8, 8) + +/* Used by CM_L4SEC_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_SHIFT (1 << 9) +#define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_MASK BITFIELD(9, 9) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_SHIFT (1 << 12) +#define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_MASK BITFIELD(12, 12) + +/* Used by CM_MPU_CLKSTCTRL, CM_MPU_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_MASK BITFIELD(8, 8) + +/* Used by CM1_ABE_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_SHIFT (1 << 9) +#define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_MASK BITFIELD(9, 9) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_SHIFT (1 << 16) +#define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_MASK BITFIELD(16, 16) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_SHIFT (1 << 17) +#define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_MASK BITFIELD(17, 17) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_SHIFT (1 << 18) +#define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_MASK BITFIELD(18, 18) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_SHIFT (1 << 19) +#define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_MASK BITFIELD(19, 19) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_SHIFT (1 << 25) +#define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_MASK BITFIELD(25, 25) + +/* Used by CM_EMU_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_PER_DPLL_EMU_CLK_SHIFT (1 << 10) +#define OMAP4430_CLKACTIVITY_PER_DPLL_EMU_CLK_MASK BITFIELD(10, 10) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_SHIFT (1 << 20) +#define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_MASK BITFIELD(20, 20) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_SHIFT (1 << 21) +#define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_MASK BITFIELD(21, 21) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_SHIFT (1 << 22) +#define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_MASK BITFIELD(22, 22) + +/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_SHIFT (1 << 24) +#define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_MASK BITFIELD(24, 24) + +/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_SHIFT (1 << 10) +#define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_MASK BITFIELD(10, 10) + +/* Used by CM_GFX_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_SGX_GFCLK_SHIFT (1 << 9) +#define OMAP4430_CLKACTIVITY_SGX_GFCLK_MASK BITFIELD(9, 9) + +/* Used by CM_ALWON_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_SHIFT (1 << 11) +#define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_MASK BITFIELD(11, 11) + +/* Used by CM_ALWON_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_SHIFT (1 << 10) +#define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_MASK BITFIELD(10, 10) + +/* Used by CM_ALWON_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_SHIFT (1 << 9) +#define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_MASK BITFIELD(9, 9) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_SYS_CLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_SYS_CLK_MASK BITFIELD(8, 8) + +/* Used by CM_TESLA_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_SHIFT (1 << 8) +#define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_MASK BITFIELD(8, 8) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_SHIFT (1 << 22) +#define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_MASK BITFIELD(22, 22) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_SHIFT (1 << 23) +#define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_MASK BITFIELD(23, 23) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_SHIFT (1 << 24) +#define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_MASK BITFIELD(24, 24) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_SHIFT (1 << 15) +#define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_MASK BITFIELD(15, 15) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_USIM_GFCLK_SHIFT (1 << 10) +#define OMAP4430_CLKACTIVITY_USIM_GFCLK_MASK BITFIELD(10, 10) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_SHIFT (1 << 30) +#define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_MASK BITFIELD(30, 30) + +/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */ +#define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_SHIFT (1 << 25) +#define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_MASK BITFIELD(25, 25) + +/* Used by CM_WKUP_CLKSTCTRL */ +#define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_SHIFT (1 << 11) +#define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_MASK BITFIELD(11, 11) + +/* + * Used by CM_WKUP_TIMER1_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL, + * CM_L4PER_DMTIMER11_CLKCTRL, CM_L4PER_DMTIMER2_CLKCTRL, + * CM_L4PER_DMTIMER3_CLKCTRL, CM_L4PER_DMTIMER4_CLKCTRL, + * CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL, + * CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL, CM_L3INIT_MMC6_CLKCTRL, + * CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL, + * CM1_ABE_TIMER8_CLKCTRL + */ +#define OMAP4430_CLKSEL_SHIFT (1 << 24) +#define OMAP4430_CLKSEL_MASK BITFIELD(24, 24) + +/* + * Renamed from CLKSEL Used by CM_ABE_DSS_SYS_CLKSEL, CM_ABE_PLL_REF_CLKSEL, + * CM_DPLL_SYS_REF_CLKSEL, CM_L4_WKUP_CLKSEL, CM_CLKSEL_DUCATI_ISS_ROOT, + * CM_CLKSEL_USB_60MHZ + */ +#define OMAP4430_CLKSEL_0_0_SHIFT (1 << 0) +#define OMAP4430_CLKSEL_0_0_MASK BITFIELD(0, 0) + +/* Renamed from CLKSEL Used by CM_BYPCLK_DPLL_IVA, CM_BYPCLK_DPLL_MPU */ +#define OMAP4430_CLKSEL_0_1_SHIFT (1 << 0) +#define OMAP4430_CLKSEL_0_1_MASK BITFIELD(0, 1) + +/* Renamed from CLKSEL Used by CM_L3INIT_HSI_CLKCTRL */ +#define OMAP4430_CLKSEL_24_25_SHIFT (1 << 24) +#define OMAP4430_CLKSEL_24_25_MASK BITFIELD(24, 25) + +/* Used by CM_L3INIT_USB_OTG_CLKCTRL */ +#define OMAP4430_CLKSEL_60M_SHIFT (1 << 24) +#define OMAP4430_CLKSEL_60M_MASK BITFIELD(24, 24) + +/* Used by CM1_ABE_AESS_CLKCTRL */ +#define OMAP4430_CLKSEL_AESS_FCLK_SHIFT (1 << 24) +#define OMAP4430_CLKSEL_AESS_FCLK_MASK BITFIELD(24, 24) + +/* Used by CM_CLKSEL_CORE_RESTORE, CM_CLKSEL_CORE */ +#define OMAP4430_CLKSEL_CORE_SHIFT (1 << 0) +#define OMAP4430_CLKSEL_CORE_MASK BITFIELD(0, 0) + +/* Renamed from CLKSEL_CORE Used by CM_SHADOW_FREQ_CONFIG2 */ +#define OMAP4430_CLKSEL_CORE_1_1_SHIFT (1 << 1) +#define OMAP4430_CLKSEL_CORE_1_1_MASK BITFIELD(1, 1) + +/* Used by CM_WKUP_USIM_CLKCTRL */ +#define OMAP4430_CLKSEL_DIV_SHIFT (1 << 24) +#define OMAP4430_CLKSEL_DIV_MASK BITFIELD(24, 24) + +/* Used by CM_CAM_FDIF_CLKCTRL */ +#define OMAP4430_CLKSEL_FCLK_SHIFT (1 << 24) +#define OMAP4430_CLKSEL_FCLK_MASK BITFIELD(24, 25) + +/* Used by CM_L4PER_MCBSP4_CLKCTRL */ +#define OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT (1 << 25) +#define OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK BITFIELD(25, 25) + +/* + * Renamed from CLKSEL_INTERNAL_SOURCE Used by CM1_ABE_DMIC_CLKCTRL, + * CM1_ABE_MCASP_CLKCTRL, CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL, + * CM1_ABE_MCBSP3_CLKCTRL + */ +#define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_SHIFT (1 << 26) +#define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_MASK BITFIELD(26, 27) + +/* Used by CM_CLKSEL_CORE_RESTORE, CM_CLKSEL_CORE */ +#define OMAP4430_CLKSEL_L3_SHIFT (1 << 4) +#define OMAP4430_CLKSEL_L3_MASK BITFIELD(4, 4) + +/* Renamed from CLKSEL_L3 Used by CM_SHADOW_FREQ_CONFIG2 */ +#define OMAP4430_CLKSEL_L3_SHADOW_SHIFT (1 << 2) +#define OMAP4430_CLKSEL_L3_SHADOW_MASK BITFIELD(2, 2) + +/* Used by CM_CLKSEL_CORE_RESTORE, CM_CLKSEL_CORE */ +#define OMAP4430_CLKSEL_L4_SHIFT (1 << 8) +#define OMAP4430_CLKSEL_L4_MASK BITFIELD(8, 8) + +/* Used by CM_CLKSEL_ABE */ +#define OMAP4430_CLKSEL_OPP_SHIFT (1 << 0) +#define OMAP4430_CLKSEL_OPP_MASK BITFIELD(0, 1) + +/* Used by CM_GFX_GFX_CLKCTRL */ +#define OMAP4430_CLKSEL_PER_192M_SHIFT (1 << 25) +#define OMAP4430_CLKSEL_PER_192M_MASK BITFIELD(25, 26) + +/* Used by CM_EMU_DEBUGSS_CLKCTRL */ +#define OMAP4430_CLKSEL_PMD_STM_CLK_SHIFT (1 << 27) +#define OMAP4430_CLKSEL_PMD_STM_CLK_MASK BITFIELD(27, 29) + +/* Used by CM_EMU_DEBUGSS_CLKCTRL */ +#define OMAP4430_CLKSEL_PMD_TRACE_CLK_SHIFT (1 << 24) +#define OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK BITFIELD(24, 26) + +/* Used by CM_GFX_GFX_CLKCTRL */ +#define OMAP4430_CLKSEL_SGX_FCLK_SHIFT (1 << 24) +#define OMAP4430_CLKSEL_SGX_FCLK_MASK BITFIELD(24, 24) + +/* + * Used by CM1_ABE_DMIC_CLKCTRL, CM1_ABE_MCASP_CLKCTRL, CM1_ABE_MCBSP1_CLKCTRL, + * CM1_ABE_MCBSP2_CLKCTRL, CM1_ABE_MCBSP3_CLKCTRL + */ +#define OMAP4430_CLKSEL_SOURCE_SHIFT (1 << 24) +#define OMAP4430_CLKSEL_SOURCE_MASK BITFIELD(24, 25) + +/* Renamed from CLKSEL_SOURCE Used by CM_L4PER_MCBSP4_CLKCTRL */ +#define OMAP4430_CLKSEL_SOURCE_24_24_SHIFT (1 << 24) +#define OMAP4430_CLKSEL_SOURCE_24_24_MASK BITFIELD(24, 24) + +/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */ +#define OMAP4430_CLKSEL_UTMI_P1_SHIFT (1 << 24) +#define OMAP4430_CLKSEL_UTMI_P1_MASK BITFIELD(24, 24) + +/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */ +#define OMAP4430_CLKSEL_UTMI_P2_SHIFT (1 << 25) +#define OMAP4430_CLKSEL_UTMI_P2_MASK BITFIELD(25, 25) + +/* + * Used by CM_WKUP_CLKSTCTRL, CM_EMU_CLKSTCTRL, CM_D2D_CLKSTCTRL, + * CM_DUCATI_CLKSTCTRL, CM_L3INSTR_CLKSTCTRL, CM_L3_1_CLKSTCTRL, + * CM_L3_2_CLKSTCTRL, CM_L4CFG_CLKSTCTRL, CM_MEMIF_CLKSTCTRL, + * CM_SDMA_CLKSTCTRL, CM_GFX_CLKSTCTRL, CM_L4PER_CLKSTCTRL, CM_L4SEC_CLKSTCTRL, + * CM_L3INIT_CLKSTCTRL, CM_CAM_CLKSTCTRL, CM_CEFUSE_CLKSTCTRL, + * CM_L3INIT_CLKSTCTRL_RESTORE, CM_L3_1_CLKSTCTRL_RESTORE, + * CM_L3_2_CLKSTCTRL_RESTORE, CM_L4CFG_CLKSTCTRL_RESTORE, + * CM_L4PER_CLKSTCTRL_RESTORE, CM_MEMIF_CLKSTCTRL_RESTORE, CM_ALWON_CLKSTCTRL, + * CM_IVAHD_CLKSTCTRL, CM_DSS_CLKSTCTRL, CM_MPU_CLKSTCTRL, CM_TESLA_CLKSTCTRL, + * CM1_ABE_CLKSTCTRL, CM_MPU_CLKSTCTRL_RESTORE + */ +#define OMAP4430_CLKTRCTRL_SHIFT (1 << 0) +#define OMAP4430_CLKTRCTRL_MASK BITFIELD(0, 1) + +/* Used by CM_EMU_OVERRIDE_DPLL_CORE */ +#define OMAP4430_CORE_DPLL_EMU_DIV_SHIFT (1 << 0) +#define OMAP4430_CORE_DPLL_EMU_DIV_MASK BITFIELD(0, 6) + +/* Used by CM_EMU_OVERRIDE_DPLL_CORE */ +#define OMAP4430_CORE_DPLL_EMU_MULT_SHIFT (1 << 8) +#define OMAP4430_CORE_DPLL_EMU_MULT_MASK BITFIELD(8, 18) + +/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP */ +#define OMAP4430_D2D_DYNDEP_SHIFT (1 << 18) +#define OMAP4430_D2D_DYNDEP_MASK BITFIELD(18, 18) + +/* Used by CM_MPU_STATICDEP */ +#define OMAP4430_D2D_STATDEP_SHIFT (1 << 18) +#define OMAP4430_D2D_STATDEP_MASK BITFIELD(18, 18) + +/* + * Used by CM_SSC_DELTAMSTEP_DPLL_PER, CM_SSC_DELTAMSTEP_DPLL_UNIPRO, + * CM_SSC_DELTAMSTEP_DPLL_USB, CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE, + * CM_SSC_DELTAMSTEP_DPLL_ABE, CM_SSC_DELTAMSTEP_DPLL_CORE, + * CM_SSC_DELTAMSTEP_DPLL_DDRPHY, CM_SSC_DELTAMSTEP_DPLL_IVA, + * CM_SSC_DELTAMSTEP_DPLL_MPU + */ +#define OMAP4430_DELTAMSTEP_SHIFT (1 << 0) +#define OMAP4430_DELTAMSTEP_MASK BITFIELD(0, 19) + +/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */ +#define OMAP4430_DLL_OVERRIDE_SHIFT (1 << 2) +#define OMAP4430_DLL_OVERRIDE_MASK BITFIELD(2, 2) + +/* Renamed from DLL_OVERRIDE Used by CM_DLL_CTRL */ +#define OMAP4430_DLL_OVERRIDE_0_0_SHIFT (1 << 0) +#define OMAP4430_DLL_OVERRIDE_0_0_MASK BITFIELD(0, 0) + +/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */ +#define OMAP4430_DLL_RESET_SHIFT (1 << 3) +#define OMAP4430_DLL_RESET_MASK BITFIELD(3, 3) + +/* + * Used by CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO, CM_CLKSEL_DPLL_USB, + * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE, + * CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU + */ +#define OMAP4430_DPLL_BYP_CLKSEL_SHIFT (1 << 23) +#define OMAP4430_DPLL_BYP_CLKSEL_MASK BITFIELD(23, 23) + +/* Used by CM_CLKDCOLDO_DPLL_USB */ +#define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_SHIFT (1 << 8) +#define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_MASK BITFIELD(8, 8) + +/* Used by CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_CORE */ +#define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_SHIFT (1 << 20) +#define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_MASK BITFIELD(20, 20) + +/* + * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE, + * CM_DIV_M3_DPLL_CORE + */ +#define OMAP4430_DPLL_CLKOUTHIF_DIV_SHIFT (1 << 0) +#define OMAP4430_DPLL_CLKOUTHIF_DIV_MASK BITFIELD(0, 4) + +/* + * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE, + * CM_DIV_M3_DPLL_CORE + */ +#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_SHIFT (1 << 5) +#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_MASK BITFIELD(5, 5) + +/* + * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE, + * CM_DIV_M3_DPLL_CORE + */ +#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT (1 << 8) +#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_MASK BITFIELD(8, 8) + +/* Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO, CM_DIV_M2_DPLL_ABE */ +#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_SHIFT (1 << 10) +#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK BITFIELD(10, 10) + +/* + * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO, + * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, + * CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU + */ +#define OMAP4430_DPLL_CLKOUT_DIV_SHIFT (1 << 0) +#define OMAP4430_DPLL_CLKOUT_DIV_MASK BITFIELD(0, 4) + +/* Renamed from DPLL_CLKOUT_DIV Used by CM_DIV_M2_DPLL_USB */ +#define OMAP4430_DPLL_CLKOUT_DIV_0_6_SHIFT (1 << 0) +#define OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK BITFIELD(0, 6) + +/* + * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO, + * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, + * CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU + */ +#define OMAP4430_DPLL_CLKOUT_DIVCHACK_SHIFT (1 << 5) +#define OMAP4430_DPLL_CLKOUT_DIVCHACK_MASK BITFIELD(5, 5) + +/* Renamed from DPLL_CLKOUT_DIVCHACK Used by CM_DIV_M2_DPLL_USB */ +#define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_SHIFT (1 << 7) +#define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_MASK BITFIELD(7, 7) + +/* + * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB, CM_DIV_M2_DPLL_CORE_RESTORE, + * CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY, + * CM_DIV_M2_DPLL_MPU + */ +#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_SHIFT (1 << 8) +#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK BITFIELD(8, 8) + +/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */ +#define OMAP4430_DPLL_CORE_DPLL_EN_SHIFT (1 << 8) +#define OMAP4430_DPLL_CORE_DPLL_EN_MASK BITFIELD(8, 10) + +/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */ +#define OMAP4430_DPLL_CORE_M2_DIV_SHIFT (1 << 11) +#define OMAP4430_DPLL_CORE_M2_DIV_MASK BITFIELD(11, 15) + +/* Used by CM_SHADOW_FREQ_CONFIG2 */ +#define OMAP4430_DPLL_CORE_M5_DIV_SHIFT (1 << 3) +#define OMAP4430_DPLL_CORE_M5_DIV_MASK BITFIELD(3, 7) + +/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */ +#define OMAP4430_DPLL_CORE_SYS_REF_CLKSEL_SHIFT (1 << 1) +#define OMAP4430_DPLL_CORE_SYS_REF_CLKSEL_MASK BITFIELD(1, 1) + +/* + * Used by CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO, + * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE, + * CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU + */ +#define OMAP4430_DPLL_DIV_SHIFT (1 << 0) +#define OMAP4430_DPLL_DIV_MASK BITFIELD(0, 6) + +/* Renamed from DPLL_DIV Used by CM_CLKSEL_DPLL_USB */ +#define OMAP4430_DPLL_DIV_0_7_SHIFT (1 << 0) +#define OMAP4430_DPLL_DIV_0_7_MASK BITFIELD(0, 7) + +/* + * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_USB, + * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, + * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU + */ +#define OMAP4430_DPLL_DRIFTGUARD_EN_SHIFT (1 << 8) +#define OMAP4430_DPLL_DRIFTGUARD_EN_MASK BITFIELD(8, 8) + +/* Renamed from DPLL_DRIFTGUARD_EN Used by CM_CLKMODE_DPLL_UNIPRO */ +#define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_SHIFT (1 << 3) +#define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_MASK BITFIELD(3, 3) + +/* + * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB, + * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, + * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU + */ +#define OMAP4430_DPLL_EN_SHIFT (1 << 0) +#define OMAP4430_DPLL_EN_MASK BITFIELD(0, 2) + +/* + * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, + * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, + * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU + */ +#define OMAP4430_DPLL_LPMODE_EN_SHIFT (1 << 10) +#define OMAP4430_DPLL_LPMODE_EN_MASK BITFIELD(10, 10) + +/* + * Used by CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO, + * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE, + * CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU + */ +#define OMAP4430_DPLL_MULT_SHIFT (1 << 8) +#define OMAP4430_DPLL_MULT_MASK BITFIELD(8, 18) + +/* Renamed from DPLL_MULT Used by CM_CLKSEL_DPLL_USB */ +#define OMAP4430_DPLL_MULT_USB_SHIFT (1 << 8) +#define OMAP4430_DPLL_MULT_USB_MASK BITFIELD(8, 19) + +/* + * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, + * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, + * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU + */ +#define OMAP4430_DPLL_REGM4XEN_SHIFT (1 << 11) +#define OMAP4430_DPLL_REGM4XEN_MASK BITFIELD(11, 11) + +/* Used by CM_CLKSEL_DPLL_USB */ +#define OMAP4430_DPLL_SD_DIV_SHIFT (1 << 24) +#define OMAP4430_DPLL_SD_DIV_MASK BITFIELD(24, 31) + +/* + * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB, + * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, + * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU + */ +#define OMAP4430_DPLL_SSC_ACK_SHIFT (1 << 13) +#define OMAP4430_DPLL_SSC_ACK_MASK BITFIELD(13, 13) + +/* + * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB, + * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, + * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU + */ +#define OMAP4430_DPLL_SSC_DOWNSPREAD_SHIFT (1 << 14) +#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK BITFIELD(14, 14) + +/* + * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB, + * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, + * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU + */ +#define OMAP4430_DPLL_SSC_EN_SHIFT (1 << 12) +#define OMAP4430_DPLL_SSC_EN_MASK BITFIELD(12, 12) + +/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L4PER_DYNAMICDEP */ +#define OMAP4430_DSS_DYNDEP_SHIFT (1 << 8) +#define OMAP4430_DSS_DYNDEP_MASK BITFIELD(8, 8) + +/* + * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, + * CM_MPU_STATICDEP + */ +#define OMAP4430_DSS_STATDEP_SHIFT (1 << 8) +#define OMAP4430_DSS_STATDEP_MASK BITFIELD(8, 8) + +/* Used by CM_L3_2_DYNAMICDEP */ +#define OMAP4430_DUCATI_DYNDEP_SHIFT (1 << 0) +#define OMAP4430_DUCATI_DYNDEP_MASK BITFIELD(0, 0) + +/* Used by CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP */ +#define OMAP4430_DUCATI_STATDEP_SHIFT (1 << 0) +#define OMAP4430_DUCATI_STATDEP_MASK BITFIELD(0, 0) + +/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */ +#define OMAP4430_FREQ_UPDATE_SHIFT (1 << 0) +#define OMAP4430_FREQ_UPDATE_MASK BITFIELD(0, 0) + +/* Used by CM_L3_2_DYNAMICDEP */ +#define OMAP4430_GFX_DYNDEP_SHIFT (1 << 10) +#define OMAP4430_GFX_DYNDEP_MASK BITFIELD(10, 10) + +/* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */ +#define OMAP4430_GFX_STATDEP_SHIFT (1 << 10) +#define OMAP4430_GFX_STATDEP_MASK BITFIELD(10, 10) + +/* Used by CM_SHADOW_FREQ_CONFIG2 */ +#define OMAP4430_GPMC_FREQ_UPDATE_SHIFT (1 << 0) +#define OMAP4430_GPMC_FREQ_UPDATE_MASK BITFIELD(0, 0) + +/* + * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE, + * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA + */ +#define OMAP4430_HSDIVIDER_CLKOUT1_DIV_SHIFT (1 << 0) +#define OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK BITFIELD(0, 4) + +/* + * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE, + * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA + */ +#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_SHIFT (1 << 5) +#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_MASK BITFIELD(5, 5) + +/* + * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE, + * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA + */ +#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_SHIFT (1 << 8) +#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK BITFIELD(8, 8) + +/* + * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE, + * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA + */ +#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_SHIFT (1 << 12) +#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_MASK BITFIELD(12, 12) + +/* + * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE, + * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA + */ +#define OMAP4430_HSDIVIDER_CLKOUT2_DIV_SHIFT (1 << 0) +#define OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK BITFIELD(0, 4) + +/* + * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE, + * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA + */ +#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_SHIFT (1 << 5) +#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_MASK BITFIELD(5, 5) + +/* + * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE, + * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA + */ +#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_SHIFT (1 << 8) +#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK BITFIELD(8, 8) + +/* + * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE, + * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA + */ +#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_SHIFT (1 << 12) +#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_MASK BITFIELD(12, 12) + +/* + * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE, + * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY + */ +#define OMAP4430_HSDIVIDER_CLKOUT3_DIV_SHIFT (1 << 0) +#define OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK BITFIELD(0, 4) + +/* + * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE, + * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY + */ +#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_SHIFT (1 << 5) +#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_MASK BITFIELD(5, 5) + +/* + * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE, + * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY + */ +#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_SHIFT (1 << 8) +#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK BITFIELD(8, 8) + +/* + * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE, + * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY + */ +#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_SHIFT (1 << 12) +#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_MASK BITFIELD(12, 12) + +/* + * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE, + * CM_DIV_M7_DPLL_CORE + */ +#define OMAP4430_HSDIVIDER_CLKOUT4_DIV_SHIFT (1 << 0) +#define OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK BITFIELD(0, 4) + +/* + * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE, + * CM_DIV_M7_DPLL_CORE + */ +#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_SHIFT (1 << 5) +#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_MASK BITFIELD(5, 5) + +/* + * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE, + * CM_DIV_M7_DPLL_CORE + */ +#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_SHIFT (1 << 8) +#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_MASK BITFIELD(8, 8) + +/* + * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE, + * CM_DIV_M7_DPLL_CORE + */ +#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_SHIFT (1 << 12) +#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_MASK BITFIELD(12, 12) + +/* + * Used by PRM_PRM_PROFILING_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL, + * CM_WKUP_KEYBOARD_CLKCTRL, CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL, + * CM_WKUP_SARRAM_CLKCTRL, CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL, + * CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL, + * CM_WKUP_WDT2_CLKCTRL, CM_EMU_DEBUGSS_CLKCTRL, CM_D2D_MODEM_ICR_CLKCTRL, + * CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL, + * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL, + * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL, + * CM_L3_2_L3_2_CLKCTRL, CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL, + * CM_L4CFG_L4_CFG_CLKCTRL, CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL, + * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL, + * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL, + * CM_MEMIF_EMIF_H2_CLKCTRL, CM_SDMA_SDMA_CLKCTRL, CM_GFX_GFX_CLKCTRL, + * CM_L4PER_ADC_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL, + * CM_L4PER_DMTIMER11_CLKCTRL, CM_L4PER_DMTIMER2_CLKCTRL, + * CM_L4PER_DMTIMER3_CLKCTRL, CM_L4PER_DMTIMER4_CLKCTRL, + * CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL, + * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL, + * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL, + * CM_L4PER_HECC2_CLKCTRL, CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL, + * CM_L4PER_I2C3_CLKCTRL, CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL, + * CM_L4PER_L4PER_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL, + * CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL, + * CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL, + * CM_L4PER_MMCSD3_CLKCTRL, CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL, + * CM_L4PER_MSPROHG_CLKCTRL, CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL, + * CM_L4PER_UART2_CLKCTRL, CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL, + * CM_L4SEC_AES1_CLKCTRL, CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, + * CM_L4SEC_DES3DES_CLKCTRL, CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL, + * CM_L4SEC_SHA2MD51_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL, + * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL, + * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL, + * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL, + * CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL, + * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL, + * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_CAM_FDIF_CLKCTRL, + * CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL, + * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE, + * CM_L3INSTR_L3_3_CLKCTRL_RESTORE, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE, + * CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE, CM_L4PER_GPIO2_CLKCTRL_RESTORE, + * CM_L4PER_GPIO3_CLKCTRL_RESTORE, CM_L4PER_GPIO4_CLKCTRL_RESTORE, + * CM_L4PER_GPIO5_CLKCTRL_RESTORE, CM_L4PER_GPIO6_CLKCTRL_RESTORE, + * CM_ALWON_MDMINTC_CLKCTRL, CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL, + * CM_ALWON_SR_MPU_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL, CM_IVAHD_SL2_CLKCTRL, + * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_CM2_PROFILING_CLKCTRL, + * CM_MPU_MPU_CLKCTRL, CM_TESLA_TESLA_CLKCTRL, CM1_ABE_AESS_CLKCTRL, + * CM1_ABE_DMIC_CLKCTRL, CM1_ABE_L4ABE_CLKCTRL, CM1_ABE_MCASP_CLKCTRL, + * CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL, CM1_ABE_MCBSP3_CLKCTRL, + * CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL, CM1_ABE_TIMER5_CLKCTRL, + * CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL, + * CM1_ABE_WDT3_CLKCTRL, CM_CM1_PROFILING_CLKCTRL + */ +#define OMAP4430_IDLEST_SHIFT (1 << 16) +#define OMAP4430_IDLEST_MASK BITFIELD(16, 17) + +/* Used by CM_DUCATI_DYNAMICDEP, CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP */ +#define OMAP4430_ISS_DYNDEP_SHIFT (1 << 9) +#define OMAP4430_ISS_DYNDEP_MASK BITFIELD(9, 9) + +/* + * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, + * CM_MPU_STATICDEP, CM_TESLA_STATICDEP + */ +#define OMAP4430_ISS_STATDEP_SHIFT (1 << 9) +#define OMAP4430_ISS_STATDEP_MASK BITFIELD(9, 9) + +/* Used by CM_L3_2_DYNAMICDEP, CM_TESLA_DYNAMICDEP */ +#define OMAP4430_IVAHD_DYNDEP_SHIFT (1 << 2) +#define OMAP4430_IVAHD_DYNDEP_MASK BITFIELD(2, 2) + +/* + * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, + * CM_GFX_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP, + * CM_SDMA_STATICDEP_RESTORE, CM_DSS_STATICDEP, CM_MPU_STATICDEP, + * CM_TESLA_STATICDEP + */ +#define OMAP4430_IVAHD_STATDEP_SHIFT (1 << 2) +#define OMAP4430_IVAHD_STATDEP_MASK BITFIELD(2, 2) + +/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L4PER_DYNAMICDEP */ +#define OMAP4430_L3INIT_DYNDEP_SHIFT (1 << 7) +#define OMAP4430_L3INIT_DYNDEP_MASK BITFIELD(7, 7) + +/* + * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, + * CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP, CM_TESLA_STATICDEP + */ +#define OMAP4430_L3INIT_STATDEP_SHIFT (1 << 7) +#define OMAP4430_L3INIT_STATDEP_MASK BITFIELD(7, 7) + +/* + * Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L3INIT_DYNAMICDEP, + * CM_DSS_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP + */ +#define OMAP4430_L3_1_DYNDEP_SHIFT (1 << 5) +#define OMAP4430_L3_1_DYNDEP_MASK BITFIELD(5, 5) + +/* + * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, + * CM_GFX_STATICDEP, CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP, + * CM_SDMA_STATICDEP_RESTORE, CM_IVAHD_STATICDEP, CM_DSS_STATICDEP, + * CM_MPU_STATICDEP, CM_TESLA_STATICDEP + */ +#define OMAP4430_L3_1_STATDEP_SHIFT (1 << 5) +#define OMAP4430_L3_1_STATDEP_MASK BITFIELD(5, 5) + +/* + * Used by CM_EMU_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_DUCATI_DYNAMICDEP, + * CM_L3_1_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_SDMA_DYNAMICDEP, + * CM_GFX_DYNAMICDEP, CM_L4SEC_DYNAMICDEP, CM_L3INIT_DYNAMICDEP, + * CM_CAM_DYNAMICDEP, CM_IVAHD_DYNAMICDEP + */ +#define OMAP4430_L3_2_DYNDEP_SHIFT (1 << 6) +#define OMAP4430_L3_2_DYNDEP_MASK BITFIELD(6, 6) + +/* + * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, + * CM_GFX_STATICDEP, CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP, + * CM_SDMA_STATICDEP_RESTORE, CM_IVAHD_STATICDEP, CM_DSS_STATICDEP, + * CM_MPU_STATICDEP, CM_TESLA_STATICDEP + */ +#define OMAP4430_L3_2_STATDEP_SHIFT (1 << 6) +#define OMAP4430_L3_2_STATDEP_MASK BITFIELD(6, 6) + +/* Used by CM_L3_1_DYNAMICDEP */ +#define OMAP4430_L4CFG_DYNDEP_SHIFT (1 << 12) +#define OMAP4430_L4CFG_DYNDEP_MASK BITFIELD(12, 12) + +/* + * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, + * CM_L3INIT_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP, + * CM_TESLA_STATICDEP + */ +#define OMAP4430_L4CFG_STATDEP_SHIFT (1 << 12) +#define OMAP4430_L4CFG_STATDEP_MASK BITFIELD(12, 12) + +/* Used by CM_L3_2_DYNAMICDEP */ +#define OMAP4430_L4PER_DYNDEP_SHIFT (1 << 13) +#define OMAP4430_L4PER_DYNDEP_MASK BITFIELD(13, 13) + +/* + * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, + * CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_SDMA_STATICDEP_RESTORE, + * CM_MPU_STATICDEP, CM_TESLA_STATICDEP + */ +#define OMAP4430_L4PER_STATDEP_SHIFT (1 << 13) +#define OMAP4430_L4PER_STATDEP_MASK BITFIELD(13, 13) + +/* Used by CM_L3_2_DYNAMICDEP, CM_L4PER_DYNAMICDEP */ +#define OMAP4430_L4SEC_DYNDEP_SHIFT (1 << 14) +#define OMAP4430_L4SEC_DYNDEP_MASK BITFIELD(14, 14) + +/* + * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_L3INIT_STATICDEP, + * CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP + */ +#define OMAP4430_L4SEC_STATDEP_SHIFT (1 << 14) +#define OMAP4430_L4SEC_STATDEP_MASK BITFIELD(14, 14) + +/* Used by CM_L4CFG_DYNAMICDEP */ +#define OMAP4430_L4WKUP_DYNDEP_SHIFT (1 << 15) +#define OMAP4430_L4WKUP_DYNDEP_MASK BITFIELD(15, 15) + +/* + * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_L3INIT_STATICDEP, + * CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP, CM_TESLA_STATICDEP + */ +#define OMAP4430_L4WKUP_STATDEP_SHIFT (1 << 15) +#define OMAP4430_L4WKUP_STATDEP_MASK BITFIELD(15, 15) + +/* + * Used by CM_D2D_DYNAMICDEP, CM_L3_1_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, + * CM_MPU_DYNAMICDEP + */ +#define OMAP4430_MEMIF_DYNDEP_SHIFT (1 << 4) +#define OMAP4430_MEMIF_DYNDEP_MASK BITFIELD(4, 4) + +/* + * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, + * CM_GFX_STATICDEP, CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP, + * CM_SDMA_STATICDEP_RESTORE, CM_IVAHD_STATICDEP, CM_DSS_STATICDEP, + * CM_MPU_STATICDEP, CM_TESLA_STATICDEP + */ +#define OMAP4430_MEMIF_STATDEP_SHIFT (1 << 4) +#define OMAP4430_MEMIF_STATDEP_MASK BITFIELD(4, 4) + +/* + * Used by CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO, + * CM_SSC_MODFREQDIV_DPLL_USB, CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE, + * CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE, + * CM_SSC_MODFREQDIV_DPLL_DDRPHY, CM_SSC_MODFREQDIV_DPLL_IVA, + * CM_SSC_MODFREQDIV_DPLL_MPU + */ +#define OMAP4430_MODFREQDIV_EXPONENT_SHIFT (1 << 8) +#define OMAP4430_MODFREQDIV_EXPONENT_MASK BITFIELD(8, 10) + +/* + * Used by CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO, + * CM_SSC_MODFREQDIV_DPLL_USB, CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE, + * CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE, + * CM_SSC_MODFREQDIV_DPLL_DDRPHY, CM_SSC_MODFREQDIV_DPLL_IVA, + * CM_SSC_MODFREQDIV_DPLL_MPU + */ +#define OMAP4430_MODFREQDIV_MANTISSA_SHIFT (1 << 0) +#define OMAP4430_MODFREQDIV_MANTISSA_MASK BITFIELD(0, 6) + +/* + * Used by PRM_PRM_PROFILING_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL, + * CM_WKUP_KEYBOARD_CLKCTRL, CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL, + * CM_WKUP_SARRAM_CLKCTRL, CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL, + * CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL, + * CM_WKUP_WDT2_CLKCTRL, CM_EMU_DEBUGSS_CLKCTRL, CM_D2D_MODEM_ICR_CLKCTRL, + * CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL, + * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL, + * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL, + * CM_L3_2_L3_2_CLKCTRL, CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL, + * CM_L4CFG_L4_CFG_CLKCTRL, CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL, + * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL, + * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL, + * CM_MEMIF_EMIF_H2_CLKCTRL, CM_SDMA_SDMA_CLKCTRL, CM_GFX_GFX_CLKCTRL, + * CM_L4PER_ADC_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL, + * CM_L4PER_DMTIMER11_CLKCTRL, CM_L4PER_DMTIMER2_CLKCTRL, + * CM_L4PER_DMTIMER3_CLKCTRL, CM_L4PER_DMTIMER4_CLKCTRL, + * CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL, + * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL, + * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL, + * CM_L4PER_HECC2_CLKCTRL, CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL, + * CM_L4PER_I2C3_CLKCTRL, CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL, + * CM_L4PER_L4PER_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL, + * CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL, + * CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL, + * CM_L4PER_MMCSD3_CLKCTRL, CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL, + * CM_L4PER_MSPROHG_CLKCTRL, CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL, + * CM_L4PER_UART2_CLKCTRL, CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL, + * CM_L4SEC_AES1_CLKCTRL, CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, + * CM_L4SEC_DES3DES_CLKCTRL, CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL, + * CM_L4SEC_SHA2MD51_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL, + * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL, + * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL, + * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL, + * CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL, + * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL, + * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_CAM_FDIF_CLKCTRL, + * CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL, + * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE, + * CM_L3INSTR_L3_3_CLKCTRL_RESTORE, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE, + * CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE, CM_L4PER_GPIO2_CLKCTRL_RESTORE, + * CM_L4PER_GPIO3_CLKCTRL_RESTORE, CM_L4PER_GPIO4_CLKCTRL_RESTORE, + * CM_L4PER_GPIO5_CLKCTRL_RESTORE, CM_L4PER_GPIO6_CLKCTRL_RESTORE, + * CM_ALWON_MDMINTC_CLKCTRL, CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL, + * CM_ALWON_SR_MPU_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL, CM_IVAHD_SL2_CLKCTRL, + * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_CM2_PROFILING_CLKCTRL, + * CM_MPU_MPU_CLKCTRL, CM_TESLA_TESLA_CLKCTRL, CM1_ABE_AESS_CLKCTRL, + * CM1_ABE_DMIC_CLKCTRL, CM1_ABE_L4ABE_CLKCTRL, CM1_ABE_MCASP_CLKCTRL, + * CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL, CM1_ABE_MCBSP3_CLKCTRL, + * CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL, CM1_ABE_TIMER5_CLKCTRL, + * CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL, + * CM1_ABE_WDT3_CLKCTRL, CM_CM1_PROFILING_CLKCTRL + */ +#define OMAP4430_MODULEMODE_SHIFT (1 << 0) +#define OMAP4430_MODULEMODE_MASK BITFIELD(0, 1) + +/* Used by CM_DSS_DSS_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT (1 << 9) +#define OMAP4430_OPTFCLKEN_48MHZ_CLK_MASK BITFIELD(9, 9) + +/* Used by CM_WKUP_BANDGAP_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT (1 << 8) +#define OMAP4430_OPTFCLKEN_BGAP_32K_MASK BITFIELD(8, 8) + +/* Used by CM_L3INIT_USBPHYOCP2SCP_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_CLK32K_SHIFT (1 << 9) +#define OMAP4430_OPTFCLKEN_CLK32K_MASK BITFIELD(9, 9) + +/* Used by CM_CAM_ISS_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT (1 << 8) +#define OMAP4430_OPTFCLKEN_CTRLCLK_MASK BITFIELD(8, 8) + +/* + * Used by CM_WKUP_GPIO1_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL, + * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL, + * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE, + * CM_L4PER_GPIO3_CLKCTRL_RESTORE, CM_L4PER_GPIO4_CLKCTRL_RESTORE, + * CM_L4PER_GPIO5_CLKCTRL_RESTORE, CM_L4PER_GPIO6_CLKCTRL_RESTORE + */ +#define OMAP4430_OPTFCLKEN_DBCLK_SHIFT (1 << 8) +#define OMAP4430_OPTFCLKEN_DBCLK_MASK BITFIELD(8, 8) + +/* Used by CM_MEMIF_DLL_CLKCTRL, CM_MEMIF_DLL_H_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_DLL_CLK_SHIFT (1 << 8) +#define OMAP4430_OPTFCLKEN_DLL_CLK_MASK BITFIELD(8, 8) + +/* Used by CM_DSS_DSS_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_DSSCLK_SHIFT (1 << 8) +#define OMAP4430_OPTFCLKEN_DSSCLK_MASK BITFIELD(8, 8) + +/* Used by CM1_ABE_SLIMBUS_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_FCLK0_SHIFT (1 << 8) +#define OMAP4430_OPTFCLKEN_FCLK0_MASK BITFIELD(8, 8) + +/* Used by CM1_ABE_SLIMBUS_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_FCLK1_SHIFT (1 << 9) +#define OMAP4430_OPTFCLKEN_FCLK1_MASK BITFIELD(9, 9) + +/* Used by CM1_ABE_SLIMBUS_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_FCLK2_SHIFT (1 << 10) +#define OMAP4430_OPTFCLKEN_FCLK2_MASK BITFIELD(10, 10) + +/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */ +#define OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT (1 << 15) +#define OMAP4430_OPTFCLKEN_FUNC48MCLK_MASK BITFIELD(15, 15) + +/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */ +#define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT (1 << 13) +#define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_MASK BITFIELD(13, 13) + +/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */ +#define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT (1 << 14) +#define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_MASK BITFIELD(14, 14) + +/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */ +#define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT (1 << 11) +#define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_MASK BITFIELD(11, 11) + +/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */ +#define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT (1 << 12) +#define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_MASK BITFIELD(12, 12) + +/* Used by CM_L4PER_SLIMBUS2_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_SHIFT (1 << 8) +#define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_MASK BITFIELD(8, 8) + +/* Used by CM_L4PER_SLIMBUS2_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT (1 << 9) +#define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_MASK BITFIELD(9, 9) + +/* Used by CM_L3INIT_USBPHYOCP2SCP_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_PHY_48M_SHIFT (1 << 8) +#define OMAP4430_OPTFCLKEN_PHY_48M_MASK BITFIELD(8, 8) + +/* Used by CM_L4PER_SLIMBUS2_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT (1 << 10) +#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_MASK BITFIELD(10, 10) + +/* Renamed from OPTFCLKEN_SLIMBUS_CLK Used by CM1_ABE_SLIMBUS_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT (1 << 11) +#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_MASK BITFIELD(11, 11) + +/* Used by CM_DSS_DSS_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT (1 << 10) +#define OMAP4430_OPTFCLKEN_SYS_CLK_MASK BITFIELD(10, 10) + +/* Used by CM_DSS_DSS_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_TV_CLK_SHIFT (1 << 11) +#define OMAP4430_OPTFCLKEN_TV_CLK_MASK BITFIELD(11, 11) + +/* Used by CM_L3INIT_UNIPRO1_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_TXPHYCLK_SHIFT (1 << 8) +#define OMAP4430_OPTFCLKEN_TXPHYCLK_MASK BITFIELD(8, 8) + +/* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */ +#define OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT (1 << 8) +#define OMAP4430_OPTFCLKEN_USB_CH0_CLK_MASK BITFIELD(8, 8) + +/* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */ +#define OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT (1 << 9) +#define OMAP4430_OPTFCLKEN_USB_CH1_CLK_MASK BITFIELD(9, 9) + +/* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */ +#define OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT (1 << 10) +#define OMAP4430_OPTFCLKEN_USB_CH2_CLK_MASK BITFIELD(10, 10) + +/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */ +#define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT (1 << 8) +#define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_MASK BITFIELD(8, 8) + +/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */ +#define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT (1 << 9) +#define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_MASK BITFIELD(9, 9) + +/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */ +#define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT (1 << 10) +#define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_MASK BITFIELD(10, 10) + +/* Used by CM_L3INIT_USB_OTG_CLKCTRL */ +#define OMAP4430_OPTFCLKEN_XCLK_SHIFT (1 << 8) +#define OMAP4430_OPTFCLKEN_XCLK_MASK BITFIELD(8, 8) + +/* Used by CM_EMU_OVERRIDE_DPLL_PER, CM_EMU_OVERRIDE_DPLL_CORE */ +#define OMAP4430_OVERRIDE_ENABLE_SHIFT (1 << 19) +#define OMAP4430_OVERRIDE_ENABLE_MASK BITFIELD(19, 19) + +/* Used by CM_CLKSEL_ABE */ +#define OMAP4430_PAD_CLKS_GATE_SHIFT (1 << 8) +#define OMAP4430_PAD_CLKS_GATE_MASK BITFIELD(8, 8) + +/* Used by CM_CORE_DVFS_CURRENT, CM_IVA_DVFS_CURRENT */ +#define OMAP4430_PERF_CURRENT_SHIFT (1 << 0) +#define OMAP4430_PERF_CURRENT_MASK BITFIELD(0, 7) + +/* + * Used by CM_CORE_DVFS_PERF1, CM_CORE_DVFS_PERF2, CM_CORE_DVFS_PERF3, + * CM_CORE_DVFS_PERF4, CM_IVA_DVFS_PERF_ABE, CM_IVA_DVFS_PERF_IVAHD, + * CM_IVA_DVFS_PERF_TESLA + */ +#define OMAP4430_PERF_REQ_SHIFT (1 << 0) +#define OMAP4430_PERF_REQ_MASK BITFIELD(0, 7) + +/* Used by CM_EMU_OVERRIDE_DPLL_PER */ +#define OMAP4430_PER_DPLL_EMU_DIV_SHIFT (1 << 0) +#define OMAP4430_PER_DPLL_EMU_DIV_MASK BITFIELD(0, 6) + +/* Used by CM_EMU_OVERRIDE_DPLL_PER */ +#define OMAP4430_PER_DPLL_EMU_MULT_SHIFT (1 << 8) +#define OMAP4430_PER_DPLL_EMU_MULT_MASK BITFIELD(8, 18) + +/* Used by CM_RESTORE_ST */ +#define OMAP4430_PHASE1_COMPLETED_SHIFT (1 << 0) +#define OMAP4430_PHASE1_COMPLETED_MASK BITFIELD(0, 0) + +/* Used by CM_RESTORE_ST */ +#define OMAP4430_PHASE2A_COMPLETED_SHIFT (1 << 1) +#define OMAP4430_PHASE2A_COMPLETED_MASK BITFIELD(1, 1) + +/* Used by CM_RESTORE_ST */ +#define OMAP4430_PHASE2B_COMPLETED_SHIFT (1 << 2) +#define OMAP4430_PHASE2B_COMPLETED_MASK BITFIELD(2, 2) + +/* Used by CM_EMU_DEBUGSS_CLKCTRL */ +#define OMAP4430_PMD_STM_MUX_CTRL_SHIFT (1 << 20) +#define OMAP4430_PMD_STM_MUX_CTRL_MASK BITFIELD(20, 21) + +/* Used by CM_EMU_DEBUGSS_CLKCTRL */ +#define OMAP4430_PMD_TRACE_MUX_CTRL_SHIFT (1 << 22) +#define OMAP4430_PMD_TRACE_MUX_CTRL_MASK BITFIELD(22, 23) + +/* Used by CM_DYN_DEP_PRESCAL */ +#define OMAP4430_PRESCAL_SHIFT (1 << 0) +#define OMAP4430_PRESCAL_MASK BITFIELD(0, 5) + +/* Used by REVISION_CM2, REVISION_CM1 */ +#define OMAP4430_REV_SHIFT (1 << 0) +#define OMAP4430_REV_MASK BITFIELD(0, 7) + +/* + * Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL, + * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE + */ +#define OMAP4430_SAR_MODE_SHIFT (1 << 4) +#define OMAP4430_SAR_MODE_MASK BITFIELD(4, 4) + +/* Used by CM_SCALE_FCLK */ +#define OMAP4430_SCALE_FCLK_SHIFT (1 << 0) +#define OMAP4430_SCALE_FCLK_MASK BITFIELD(0, 0) + +/* Used by CM_L4CFG_DYNAMICDEP */ +#define OMAP4430_SDMA_DYNDEP_SHIFT (1 << 11) +#define OMAP4430_SDMA_DYNDEP_MASK BITFIELD(11, 11) + +/* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */ +#define OMAP4430_SDMA_STATDEP_SHIFT (1 << 11) +#define OMAP4430_SDMA_STATDEP_MASK BITFIELD(11, 11) + +/* Used by CM_CLKSEL_ABE */ +#define OMAP4430_SLIMBUS_CLK_GATE_SHIFT (1 << 10) +#define OMAP4430_SLIMBUS_CLK_GATE_MASK BITFIELD(10, 10) + +/* + * Used by CM_EMU_DEBUGSS_CLKCTRL, CM_D2D_SAD2D_CLKCTRL, + * CM_DUCATI_DUCATI_CLKCTRL, CM_SDMA_SDMA_CLKCTRL, CM_GFX_GFX_CLKCTRL, + * CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL, + * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL, + * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL, + * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL, + * CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_FS_CLKCTRL, + * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_CAM_FDIF_CLKCTRL, + * CM_CAM_ISS_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, + * CM_IVAHD_IVAHD_CLKCTRL, CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, + * CM_MPU_MPU_CLKCTRL, CM_TESLA_TESLA_CLKCTRL, CM1_ABE_AESS_CLKCTRL + */ +#define OMAP4430_STBYST_SHIFT (1 << 18) +#define OMAP4430_STBYST_MASK BITFIELD(18, 18) + +/* + * Used by CM_IDLEST_DPLL_PER, CM_IDLEST_DPLL_UNIPRO, CM_IDLEST_DPLL_USB, + * CM_IDLEST_DPLL_ABE, CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDRPHY, + * CM_IDLEST_DPLL_IVA, CM_IDLEST_DPLL_MPU + */ +#define OMAP4430_ST_DPLL_CLK_SHIFT (1 << 0) +#define OMAP4430_ST_DPLL_CLK_MASK BITFIELD(0, 0) + +/* Used by CM_CLKDCOLDO_DPLL_USB */ +#define OMAP4430_ST_DPLL_CLKDCOLDO_SHIFT (1 << 9) +#define OMAP4430_ST_DPLL_CLKDCOLDO_MASK BITFIELD(9, 9) + +/* + * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB, CM_DIV_M2_DPLL_CORE_RESTORE, + * CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY, + * CM_DIV_M2_DPLL_MPU + */ +#define OMAP4430_ST_DPLL_CLKOUT_SHIFT (1 << 9) +#define OMAP4430_ST_DPLL_CLKOUT_MASK BITFIELD(9, 9) + +/* + * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE, + * CM_DIV_M3_DPLL_CORE + */ +#define OMAP4430_ST_DPLL_CLKOUTHIF_SHIFT (1 << 9) +#define OMAP4430_ST_DPLL_CLKOUTHIF_MASK BITFIELD(9, 9) + +/* Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO, CM_DIV_M2_DPLL_ABE */ +#define OMAP4430_ST_DPLL_CLKOUTX2_SHIFT (1 << 11) +#define OMAP4430_ST_DPLL_CLKOUTX2_MASK BITFIELD(11, 11) + +/* + * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE, + * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA + */ +#define OMAP4430_ST_HSDIVIDER_CLKOUT1_SHIFT (1 << 9) +#define OMAP4430_ST_HSDIVIDER_CLKOUT1_MASK BITFIELD(9, 9) + +/* + * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE, + * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA + */ +#define OMAP4430_ST_HSDIVIDER_CLKOUT2_SHIFT (1 << 9) +#define OMAP4430_ST_HSDIVIDER_CLKOUT2_MASK BITFIELD(9, 9) + +/* + * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE, + * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY + */ +#define OMAP4430_ST_HSDIVIDER_CLKOUT3_SHIFT (1 << 9) +#define OMAP4430_ST_HSDIVIDER_CLKOUT3_MASK BITFIELD(9, 9) + +/* + * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE, + * CM_DIV_M7_DPLL_CORE + */ +#define OMAP4430_ST_HSDIVIDER_CLKOUT4_SHIFT (1 << 9) +#define OMAP4430_ST_HSDIVIDER_CLKOUT4_MASK BITFIELD(9, 9) + +/* Used by CM_SYS_CLKSEL */ +#define OMAP4430_SYS_CLKSEL_SHIFT (1 << 0) +#define OMAP4430_SYS_CLKSEL_MASK BITFIELD(0, 2) + +/* Used by CM_L4CFG_DYNAMICDEP */ +#define OMAP4430_TESLA_DYNDEP_SHIFT (1 << 1) +#define OMAP4430_TESLA_DYNDEP_MASK BITFIELD(1, 1) + +/* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */ +#define OMAP4430_TESLA_STATDEP_SHIFT (1 << 1) +#define OMAP4430_TESLA_STATDEP_MASK BITFIELD(1, 1) + +/* + * Used by CM_EMU_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_DUCATI_DYNAMICDEP, + * CM_L3_1_DYNAMICDEP, CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, + * CM_L4PER_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP + */ +#define OMAP4430_WINDOWSIZE_SHIFT (1 << 24) +#define OMAP4430_WINDOWSIZE_MASK BITFIELD(24, 27) +#endif diff --git a/arch/arm/mach-omap2/cm.c b/arch/arm/mach-omap2/cm.c index 8eb2dab8c7dbf0adde3dab5b83572c6aa3967f8c..58e4a1c557d8574745a3a41fe1d0fa95db66c42d 100644 --- a/arch/arm/mach-omap2/cm.c +++ b/arch/arm/mach-omap2/cm.c @@ -21,6 +21,8 @@ #include +#include + #include "cm.h" #include "cm-regbits-24xx.h" #include "cm-regbits-34xx.h" @@ -61,9 +63,8 @@ int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift) mask = 1 << idlest_shift; /* XXX should be OMAP2 CM */ - while (((cm_read_mod_reg(prcm_mod, cm_idlest_reg) & mask) != ena) && - (i++ < MAX_MODULE_READY_TIME)) - udelay(1); + omap_test_timeout(((cm_read_mod_reg(prcm_mod, cm_idlest_reg) & mask) == ena), + MAX_MODULE_READY_TIME, i); return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; } diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h index a2fcfcc253cc4a6519db7bf5d6729c2cbde2e7d1..90a4086fbdf4574228fd419f6898115e02f41c9a 100644 --- a/arch/arm/mach-omap2/cm.h +++ b/arch/arm/mach-omap2/cm.h @@ -4,8 +4,8 @@ /* * OMAP2/3 Clock Management (CM) register definitions * - * Copyright (C) 2007-2008 Texas Instruments, Inc. - * Copyright (C) 2007-2008 Nokia Corporation + * Copyright (C) 2007-2009 Texas Instruments, Inc. + * Copyright (C) 2007-2009 Nokia Corporation * * Written by Paul Walmsley * @@ -22,6 +22,12 @@ OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg)) #define OMAP34XX_CM_REGADDR(module, reg) \ OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg)) +#define OMAP44XX_CM1_REGADDR(module, reg) \ + OMAP2_L4_IO_ADDRESS(OMAP4430_CM1_BASE + (module) + (reg)) +#define OMAP44XX_CM2_REGADDR(module, reg) \ + OMAP2_L4_IO_ADDRESS(OMAP4430_CM2_BASE + (module) + (reg)) + +#include "cm44xx.h" /* * Architecture-specific global CM registers @@ -89,6 +95,11 @@ #define OMAP3430_CM_CLKSEL2_EMU 0x0050 #define OMAP3430_CM_CLKSEL3_EMU 0x0054 +/* CM2.CEFUSE_CM2 register offsets */ + +/* OMAP4 modulemode control */ +#define OMAP4430_MODULEMODE_HWCTRL 0 +#define OMAP4430_MODULEMODE_SWCTRL 1 /* Clock management domain register get/set */ diff --git a/arch/arm/mach-omap2/cm44xx.h b/arch/arm/mach-omap2/cm44xx.h new file mode 100644 index 0000000000000000000000000000000000000000..c575b9b0c041ea04a67ce3bc98b18724aac727b6 --- /dev/null +++ b/arch/arm/mach-omap2/cm44xx.h @@ -0,0 +1,358 @@ +/* + * OMAP44xx CM1 & CM2 instance offset macros + * + * Copyright (C) 2009 Texas Instruments, Inc. + * Copyright (C) 2009 Nokia Corporation + * + * Paul Walmsley (paul@pwsan.com) + * Rajendra Nayak (rnayak@ti.com) + * Benoit Cousson (b-cousson@ti.com) + * + * This file is automatically generated from the OMAP hardware databases. + * We respectfully ask that any modifications to this file be coordinated + * with the public linux-omap@vger.kernel.org mailing list and the + * authors above to ensure that the autogeneration scripts are kept + * up-to-date with the file contents. + * + * 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. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_CM44XX_H +#define __ARCH_ARM_MACH_OMAP2_CM44XX_H + + +/* CM1 */ + + +/* CM1.OCP_SOCKET_CM1 register offsets */ +#define OMAP4430_REVISION_CM1 OMAP44XX_CM1_REGADDR(OMAP4430_CM1_OCP_SOCKET_MOD, 0x0000) +#define OMAP4430_CM_CM1_PROFILING_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_OCP_SOCKET_MOD, 0x0040) + +/* CM1.CKGEN_CM1 register offsets */ +#define OMAP4430_CM_CLKSEL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0000) +#define OMAP4430_CM_CLKSEL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0008) +#define OMAP4430_CM_DLL_CTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0010) +#define OMAP4430_CM_CLKMODE_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0020) +#define OMAP4430_CM_IDLEST_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0024) +#define OMAP4430_CM_AUTOIDLE_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0028) +#define OMAP4430_CM_CLKSEL_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x002c) +#define OMAP4430_CM_DIV_M2_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0030) +#define OMAP4430_CM_DIV_M3_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0034) +#define OMAP4430_CM_DIV_M4_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0038) +#define OMAP4430_CM_DIV_M5_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x003c) +#define OMAP4430_CM_DIV_M6_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0040) +#define OMAP4430_CM_DIV_M7_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0044) +#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0048) +#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x004c) +#define OMAP4430_CM_EMU_OVERRIDE_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0050) +#define OMAP4430_CM_CLKMODE_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0060) +#define OMAP4430_CM_IDLEST_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0064) +#define OMAP4430_CM_AUTOIDLE_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0068) +#define OMAP4430_CM_CLKSEL_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x006c) +#define OMAP4430_CM_DIV_M2_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0070) +#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0088) +#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x008c) +#define OMAP4430_CM_BYPCLK_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x009c) +#define OMAP4430_CM_CLKMODE_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00a0) +#define OMAP4430_CM_IDLEST_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00a4) +#define OMAP4430_CM_AUTOIDLE_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00a8) +#define OMAP4430_CM_CLKSEL_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00ac) +#define OMAP4430_CM_DIV_M4_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00b8) +#define OMAP4430_CM_DIV_M5_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00bc) +#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00c8) +#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00cc) +#define OMAP4430_CM_BYPCLK_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00dc) +#define OMAP4430_CM_CLKMODE_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00e0) +#define OMAP4430_CM_IDLEST_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00e4) +#define OMAP4430_CM_AUTOIDLE_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00e8) +#define OMAP4430_CM_CLKSEL_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00ec) +#define OMAP4430_CM_DIV_M2_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00f0) +#define OMAP4430_CM_DIV_M3_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00f4) +#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0108) +#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x010c) +#define OMAP4430_CM_CLKMODE_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0120) +#define OMAP4430_CM_IDLEST_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0124) +#define OMAP4430_CM_AUTOIDLE_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0128) +#define OMAP4430_CM_CLKSEL_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x012c) +#define OMAP4430_CM_DIV_M2_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0130) +#define OMAP4430_CM_DIV_M4_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0138) +#define OMAP4430_CM_DIV_M5_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x013c) +#define OMAP4430_CM_DIV_M6_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0140) +#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0148) +#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x014c) +#define OMAP4430_CM_SHADOW_FREQ_CONFIG1 OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0160) +#define OMAP4430_CM_SHADOW_FREQ_CONFIG2 OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0164) +#define OMAP4430_CM_DYN_DEP_PRESCAL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0170) +#define OMAP4430_CM_RESTORE_ST OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0180) + +/* CM1.MPU_CM1 register offsets */ +#define OMAP4430_CM_MPU_CLKSTCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_MPU_MOD, 0x0000) +#define OMAP4430_CM_MPU_STATICDEP OMAP44XX_CM1_REGADDR(OMAP4430_CM1_MPU_MOD, 0x0004) +#define OMAP4430_CM_MPU_DYNAMICDEP OMAP44XX_CM1_REGADDR(OMAP4430_CM1_MPU_MOD, 0x0008) +#define OMAP4430_CM_MPU_MPU_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_MPU_MOD, 0x0020) + +/* CM1.TESLA_CM1 register offsets */ +#define OMAP4430_CM_TESLA_CLKSTCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_TESLA_MOD, 0x0000) +#define OMAP4430_CM_TESLA_STATICDEP OMAP44XX_CM1_REGADDR(OMAP4430_CM1_TESLA_MOD, 0x0004) +#define OMAP4430_CM_TESLA_DYNAMICDEP OMAP44XX_CM1_REGADDR(OMAP4430_CM1_TESLA_MOD, 0x0008) +#define OMAP4430_CM_TESLA_TESLA_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_TESLA_MOD, 0x0020) + +/* CM1.ABE_CM1 register offsets */ +#define OMAP4430_CM1_ABE_CLKSTCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0000) +#define OMAP4430_CM1_ABE_L4ABE_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0020) +#define OMAP4430_CM1_ABE_AESS_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0028) +#define OMAP4430_CM1_ABE_PDM_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0030) +#define OMAP4430_CM1_ABE_DMIC_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0038) +#define OMAP4430_CM1_ABE_MCASP_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0040) +#define OMAP4430_CM1_ABE_MCBSP1_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0048) +#define OMAP4430_CM1_ABE_MCBSP2_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0050) +#define OMAP4430_CM1_ABE_MCBSP3_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0058) +#define OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0060) +#define OMAP4430_CM1_ABE_TIMER5_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0068) +#define OMAP4430_CM1_ABE_TIMER6_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0070) +#define OMAP4430_CM1_ABE_TIMER7_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0078) +#define OMAP4430_CM1_ABE_TIMER8_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0080) +#define OMAP4430_CM1_ABE_WDT3_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0088) + +/* CM1.RESTORE_CM1 register offsets */ +#define OMAP4430_CM_CLKSEL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0000) +#define OMAP4430_CM_DIV_M2_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0004) +#define OMAP4430_CM_DIV_M3_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0008) +#define OMAP4430_CM_DIV_M4_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x000c) +#define OMAP4430_CM_DIV_M5_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0010) +#define OMAP4430_CM_DIV_M6_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0014) +#define OMAP4430_CM_DIV_M7_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0018) +#define OMAP4430_CM_CLKSEL_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x001c) +#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0020) +#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0024) +#define OMAP4430_CM_CLKMODE_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0028) +#define OMAP4430_CM_SHADOW_FREQ_CONFIG1_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x002c) +#define OMAP4430_CM_AUTOIDLE_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0030) +#define OMAP4430_CM_MPU_CLKSTCTRL_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0034) + +/* CM2 */ + + +/* CM2.OCP_SOCKET_CM2 register offsets */ +#define OMAP4430_REVISION_CM2 OMAP44XX_CM2_REGADDR(OMAP4430_CM2_OCP_SOCKET_MOD, 0x0000) +#define OMAP4430_CM_CM2_PROFILING_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_OCP_SOCKET_MOD, 0x0040) + +/* CM2.CKGEN_CM2 register offsets */ +#define OMAP4430_CM_CLKSEL_DUCATI_ISS_ROOT OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0000) +#define OMAP4430_CM_CLKSEL_USB_60MHZ OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0004) +#define OMAP4430_CM_SCALE_FCLK OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0008) +#define OMAP4430_CM_CORE_DVFS_PERF1 OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0010) +#define OMAP4430_CM_CORE_DVFS_PERF2 OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0014) +#define OMAP4430_CM_CORE_DVFS_PERF3 OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0018) +#define OMAP4430_CM_CORE_DVFS_PERF4 OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x001c) +#define OMAP4430_CM_CORE_DVFS_CURRENT OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0024) +#define OMAP4430_CM_IVA_DVFS_PERF_TESLA OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0028) +#define OMAP4430_CM_IVA_DVFS_PERF_IVAHD OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x002c) +#define OMAP4430_CM_IVA_DVFS_PERF_ABE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0030) +#define OMAP4430_CM_IVA_DVFS_CURRENT OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0038) +#define OMAP4430_CM_CLKMODE_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0040) +#define OMAP4430_CM_IDLEST_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0044) +#define OMAP4430_CM_AUTOIDLE_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0048) +#define OMAP4430_CM_CLKSEL_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x004c) +#define OMAP4430_CM_DIV_M2_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0050) +#define OMAP4430_CM_DIV_M3_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0054) +#define OMAP4430_CM_DIV_M4_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0058) +#define OMAP4430_CM_DIV_M5_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x005c) +#define OMAP4430_CM_DIV_M6_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0060) +#define OMAP4430_CM_DIV_M7_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0064) +#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0068) +#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x006c) +#define OMAP4430_CM_EMU_OVERRIDE_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0070) +#define OMAP4430_CM_CLKMODE_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0080) +#define OMAP4430_CM_IDLEST_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0084) +#define OMAP4430_CM_AUTOIDLE_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0088) +#define OMAP4430_CM_CLKSEL_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x008c) +#define OMAP4430_CM_DIV_M2_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0090) +#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00a8) +#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00ac) +#define OMAP4430_CM_CLKDCOLDO_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00b4) +#define OMAP4430_CM_CLKMODE_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00c0) +#define OMAP4430_CM_IDLEST_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00c4) +#define OMAP4430_CM_AUTOIDLE_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00c8) +#define OMAP4430_CM_CLKSEL_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00cc) +#define OMAP4430_CM_DIV_M2_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00d0) +#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00e8) +#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00ec) + +/* CM2.ALWAYS_ON_CM2 register offsets */ +#define OMAP4430_CM_ALWON_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0000) +#define OMAP4430_CM_ALWON_MDMINTC_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0020) +#define OMAP4430_CM_ALWON_SR_MPU_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0028) +#define OMAP4430_CM_ALWON_SR_IVA_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0030) +#define OMAP4430_CM_ALWON_SR_CORE_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0038) + +/* CM2.CORE_CM2 register offsets */ +#define OMAP4430_CM_L3_1_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0000) +#define OMAP4430_CM_L3_1_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0008) +#define OMAP4430_CM_L3_1_L3_1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0020) +#define OMAP4430_CM_L3_2_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0100) +#define OMAP4430_CM_L3_2_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0108) +#define OMAP4430_CM_L3_2_L3_2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0120) +#define OMAP4430_CM_L3_2_GPMC_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0128) +#define OMAP4430_CM_L3_2_OCMC_RAM_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0130) +#define OMAP4430_CM_DUCATI_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0200) +#define OMAP4430_CM_DUCATI_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0204) +#define OMAP4430_CM_DUCATI_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0208) +#define OMAP4430_CM_DUCATI_DUCATI_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0220) +#define OMAP4430_CM_SDMA_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0300) +#define OMAP4430_CM_SDMA_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0304) +#define OMAP4430_CM_SDMA_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0308) +#define OMAP4430_CM_SDMA_SDMA_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0320) +#define OMAP4430_CM_MEMIF_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0400) +#define OMAP4430_CM_MEMIF_DMM_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0420) +#define OMAP4430_CM_MEMIF_EMIF_FW_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0428) +#define OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0430) +#define OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0438) +#define OMAP4430_CM_MEMIF_DLL_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0440) +#define OMAP4430_CM_MEMIF_EMIF_H1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0450) +#define OMAP4430_CM_MEMIF_EMIF_H2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0458) +#define OMAP4430_CM_MEMIF_DLL_H_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0460) +#define OMAP4430_CM_D2D_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0500) +#define OMAP4430_CM_D2D_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0504) +#define OMAP4430_CM_D2D_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0508) +#define OMAP4430_CM_D2D_SAD2D_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0520) +#define OMAP4430_CM_D2D_MODEM_ICR_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0528) +#define OMAP4430_CM_D2D_SAD2D_FW_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0530) +#define OMAP4430_CM_L4CFG_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0600) +#define OMAP4430_CM_L4CFG_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0608) +#define OMAP4430_CM_L4CFG_L4_CFG_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0620) +#define OMAP4430_CM_L4CFG_HW_SEM_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0628) +#define OMAP4430_CM_L4CFG_MAILBOX_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0630) +#define OMAP4430_CM_L4CFG_SAR_ROM_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0638) +#define OMAP4430_CM_L3INSTR_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0700) +#define OMAP4430_CM_L3INSTR_L3_3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0720) +#define OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0728) +#define OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0740) + +/* CM2.IVAHD_CM2 register offsets */ +#define OMAP4430_CM_IVAHD_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_MOD, 0x0000) +#define OMAP4430_CM_IVAHD_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_MOD, 0x0004) +#define OMAP4430_CM_IVAHD_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_MOD, 0x0008) +#define OMAP4430_CM_IVAHD_IVAHD_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_MOD, 0x0020) +#define OMAP4430_CM_IVAHD_SL2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_MOD, 0x0028) + +/* CM2.CAM_CM2 register offsets */ +#define OMAP4430_CM_CAM_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_MOD, 0x0000) +#define OMAP4430_CM_CAM_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_MOD, 0x0004) +#define OMAP4430_CM_CAM_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_MOD, 0x0008) +#define OMAP4430_CM_CAM_ISS_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_MOD, 0x0020) +#define OMAP4430_CM_CAM_FDIF_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_MOD, 0x0028) + +/* CM2.DSS_CM2 register offsets */ +#define OMAP4430_CM_DSS_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_MOD, 0x0000) +#define OMAP4430_CM_DSS_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_MOD, 0x0004) +#define OMAP4430_CM_DSS_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_MOD, 0x0008) +#define OMAP4430_CM_DSS_DSS_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_MOD, 0x0020) +#define OMAP4430_CM_DSS_DEISS_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_MOD, 0x0028) + +/* CM2.GFX_CM2 register offsets */ +#define OMAP4430_CM_GFX_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_GFX_MOD, 0x0000) +#define OMAP4430_CM_GFX_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_GFX_MOD, 0x0004) +#define OMAP4430_CM_GFX_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_GFX_MOD, 0x0008) +#define OMAP4430_CM_GFX_GFX_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_GFX_MOD, 0x0020) + +/* CM2.L3INIT_CM2 register offsets */ +#define OMAP4430_CM_L3INIT_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0000) +#define OMAP4430_CM_L3INIT_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0004) +#define OMAP4430_CM_L3INIT_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0008) +#define OMAP4430_CM_L3INIT_MMC1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0028) +#define OMAP4430_CM_L3INIT_MMC2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0030) +#define OMAP4430_CM_L3INIT_HSI_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0038) +#define OMAP4430_CM_L3INIT_UNIPRO1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0040) +#define OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0058) +#define OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0060) +#define OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0068) +#define OMAP4430_CM_L3INIT_P1500_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0078) +#define OMAP4430_CM_L3INIT_EMAC_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0080) +#define OMAP4430_CM_L3INIT_SATA_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0088) +#define OMAP4430_CM_L3INIT_TPPSS_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0090) +#define OMAP4430_CM_L3INIT_PCIESS_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0098) +#define OMAP4430_CM_L3INIT_CCPTX_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x00a8) +#define OMAP4430_CM_L3INIT_XHPI_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x00c0) +#define OMAP4430_CM_L3INIT_MMC6_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x00c8) +#define OMAP4430_CM_L3INIT_USB_HOST_FS_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x00d0) +#define OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x00e0) + +/* CM2.L4PER_CM2 register offsets */ +#define OMAP4430_CM_L4PER_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0000) +#define OMAP4430_CM_L4PER_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0008) +#define OMAP4430_CM_L4PER_ADC_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0020) +#define OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0028) +#define OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0030) +#define OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0038) +#define OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0040) +#define OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0048) +#define OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0050) +#define OMAP4430_CM_L4PER_ELM_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0058) +#define OMAP4430_CM_L4PER_GPIO2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0060) +#define OMAP4430_CM_L4PER_GPIO3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0068) +#define OMAP4430_CM_L4PER_GPIO4_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0070) +#define OMAP4430_CM_L4PER_GPIO5_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0078) +#define OMAP4430_CM_L4PER_GPIO6_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0080) +#define OMAP4430_CM_L4PER_HDQ1W_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0088) +#define OMAP4430_CM_L4PER_HECC1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0090) +#define OMAP4430_CM_L4PER_HECC2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0098) +#define OMAP4430_CM_L4PER_I2C1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00a0) +#define OMAP4430_CM_L4PER_I2C2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00a8) +#define OMAP4430_CM_L4PER_I2C3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00b0) +#define OMAP4430_CM_L4PER_I2C4_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00b8) +#define OMAP4430_CM_L4PER_L4PER_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00c0) +#define OMAP4430_CM_L4PER_MCASP2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00d0) +#define OMAP4430_CM_L4PER_MCASP3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00d8) +#define OMAP4430_CM_L4PER_MCBSP4_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00e0) +#define OMAP4430_CM_L4PER_MGATE_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00e8) +#define OMAP4430_CM_L4PER_MCSPI1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00f0) +#define OMAP4430_CM_L4PER_MCSPI2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00f8) +#define OMAP4430_CM_L4PER_MCSPI3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0100) +#define OMAP4430_CM_L4PER_MCSPI4_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0108) +#define OMAP4430_CM_L4PER_MMCSD3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0120) +#define OMAP4430_CM_L4PER_MMCSD4_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0128) +#define OMAP4430_CM_L4PER_MSPROHG_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0130) +#define OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0138) +#define OMAP4430_CM_L4PER_UART1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0140) +#define OMAP4430_CM_L4PER_UART2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0148) +#define OMAP4430_CM_L4PER_UART3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0150) +#define OMAP4430_CM_L4PER_UART4_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0158) +#define OMAP4430_CM_L4PER_MMCSD5_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0160) +#define OMAP4430_CM_L4PER_I2C5_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0168) +#define OMAP4430_CM_L4SEC_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0180) +#define OMAP4430_CM_L4SEC_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0184) +#define OMAP4430_CM_L4SEC_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0188) +#define OMAP4430_CM_L4SEC_AES1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x01a0) +#define OMAP4430_CM_L4SEC_AES2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x01a8) +#define OMAP4430_CM_L4SEC_DES3DES_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x01b0) +#define OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x01b8) +#define OMAP4430_CM_L4SEC_RNG_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x01c0) +#define OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x01c8) +#define OMAP4430_CM_L4SEC_CRYPTODMA_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x01d8) + +/* CM2.CEFUSE_CM2 register offsets */ +#define OMAP4430_CM_CEFUSE_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_MOD, 0x0000) +#define OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_MOD, 0x0020) + +/* CM2.RESTORE_CM2 register offsets */ +#define OMAP4430_CM_L3_1_CLKSTCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0000) +#define OMAP4430_CM_L3_2_CLKSTCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0004) +#define OMAP4430_CM_L4CFG_CLKSTCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0008) +#define OMAP4430_CM_MEMIF_CLKSTCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x000c) +#define OMAP4430_CM_L4PER_CLKSTCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0010) +#define OMAP4430_CM_L3INIT_CLKSTCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0014) +#define OMAP4430_CM_L3INSTR_L3_3_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0018) +#define OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x001c) +#define OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0020) +#define OMAP4430_CM_L4PER_GPIO2_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0024) +#define OMAP4430_CM_L4PER_GPIO3_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0028) +#define OMAP4430_CM_L4PER_GPIO4_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x002c) +#define OMAP4430_CM_L4PER_GPIO5_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0030) +#define OMAP4430_CM_L4PER_GPIO6_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0034) +#define OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0038) +#define OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x003c) +#define OMAP4430_CM_SDMA_STATICDEP_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0040) +#endif diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 733d3dcff98bb9214de34fa9d6ec032d40a4c4e9..18ad93160abbc5fca7bf68ae3dba578c7f2f22b9 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -27,6 +27,8 @@ #include #include +#include "mux.h" + #if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE) static struct resource cam_resources[] = { @@ -595,27 +597,40 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller, if (cpu_is_omap34xx()) { if (controller_nr == 0) { - omap_cfg_reg(N28_3430_MMC1_CLK); - omap_cfg_reg(M27_3430_MMC1_CMD); - omap_cfg_reg(N27_3430_MMC1_DAT0); + omap_mux_init_signal("sdmmc1_clk", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("sdmmc1_cmd", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("sdmmc1_dat0", + OMAP_PIN_INPUT_PULLUP); if (mmc_controller->slots[0].wires == 4 || mmc_controller->slots[0].wires == 8) { - omap_cfg_reg(N26_3430_MMC1_DAT1); - omap_cfg_reg(N25_3430_MMC1_DAT2); - omap_cfg_reg(P28_3430_MMC1_DAT3); + omap_mux_init_signal("sdmmc1_dat1", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("sdmmc1_dat2", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("sdmmc1_dat3", + OMAP_PIN_INPUT_PULLUP); } if (mmc_controller->slots[0].wires == 8) { - omap_cfg_reg(P27_3430_MMC1_DAT4); - omap_cfg_reg(P26_3430_MMC1_DAT5); - omap_cfg_reg(R27_3430_MMC1_DAT6); - omap_cfg_reg(R25_3430_MMC1_DAT7); + omap_mux_init_signal("sdmmc1_dat4", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("sdmmc1_dat5", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("sdmmc1_dat6", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("sdmmc1_dat7", + OMAP_PIN_INPUT_PULLUP); } } if (controller_nr == 1) { /* MMC2 */ - omap_cfg_reg(AE2_3430_MMC2_CLK); - omap_cfg_reg(AG5_3430_MMC2_CMD); - omap_cfg_reg(AH5_3430_MMC2_DAT0); + omap_mux_init_signal("sdmmc2_clk", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("sdmmc2_cmd", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("sdmmc2_dat0", + OMAP_PIN_INPUT_PULLUP); /* * For 8 wire configurations, Lines DAT4, 5, 6 and 7 need to be muxed @@ -623,15 +638,22 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller, */ if (mmc_controller->slots[0].wires == 4 || mmc_controller->slots[0].wires == 8) { - omap_cfg_reg(AH4_3430_MMC2_DAT1); - omap_cfg_reg(AG4_3430_MMC2_DAT2); - omap_cfg_reg(AF4_3430_MMC2_DAT3); + omap_mux_init_signal("sdmmc2_dat1", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("sdmmc2_dat2", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("sdmmc2_dat3", + OMAP_PIN_INPUT_PULLUP); } if (mmc_controller->slots[0].wires == 8) { - omap_cfg_reg(AE4_3430_MMC2_DAT4); - omap_cfg_reg(AH3_3430_MMC2_DAT5); - omap_cfg_reg(AF3_3430_MMC2_DAT6); - omap_cfg_reg(AE3_3430_MMC2_DAT7); + omap_mux_init_signal("sdmmc2_dat4.sdmmc2_dat4", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("sdmmc2_dat5.sdmmc2_dat5", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("sdmmc2_dat6.sdmmc2_dat6", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("sdmmc2_dat7.sdmmc2_dat7", + OMAP_PIN_INPUT_PULLUP); } } diff --git a/arch/arm/mach-omap2/dpll.c b/arch/arm/mach-omap2/dpll.c new file mode 100644 index 0000000000000000000000000000000000000000..f6055b493294496a96db5fe9782fc6152b39f028 --- /dev/null +++ b/arch/arm/mach-omap2/dpll.c @@ -0,0 +1,538 @@ +/* + * OMAP3/4 - specific DPLL control functions + * + * Copyright (C) 2009 Texas Instruments, Inc. + * Copyright (C) 2009 Nokia Corporation + * + * Written by Paul Walmsley + * Testing and integration fixes by Jouni Högander + * + * Parts of this code are based on code written by + * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu + * + * 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 "clock.h" +#include "prm.h" +#include "prm-regbits-34xx.h" +#include "cm.h" +#include "cm-regbits-34xx.h" + +/* CM_AUTOIDLE_PLL*.AUTO_* bit values */ +#define DPLL_AUTOIDLE_DISABLE 0x0 +#define DPLL_AUTOIDLE_LOW_POWER_STOP 0x1 + +#define MAX_DPLL_WAIT_TRIES 1000000 + + +/** + * omap3_dpll_recalc - recalculate DPLL rate + * @clk: DPLL struct clk + * + * Recalculate and propagate the DPLL rate. + */ +unsigned long omap3_dpll_recalc(struct clk *clk) +{ + return omap2_get_dpll_rate(clk); +} + +/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */ +static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits) +{ + const struct dpll_data *dd; + u32 v; + + dd = clk->dpll_data; + + v = __raw_readl(dd->control_reg); + v &= ~dd->enable_mask; + v |= clken_bits << __ffs(dd->enable_mask); + __raw_writel(v, dd->control_reg); +} + +/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */ +static int _omap3_wait_dpll_status(struct clk *clk, u8 state) +{ + const struct dpll_data *dd; + int i = 0; + int ret = -EINVAL; + + dd = clk->dpll_data; + + state <<= __ffs(dd->idlest_mask); + + while (((__raw_readl(dd->idlest_reg) & dd->idlest_mask) != state) && + i < MAX_DPLL_WAIT_TRIES) { + i++; + udelay(1); + } + + if (i == MAX_DPLL_WAIT_TRIES) { + printk(KERN_ERR "clock: %s failed transition to '%s'\n", + clk->name, (state) ? "locked" : "bypassed"); + } else { + pr_debug("clock: %s transition to '%s' in %d loops\n", + clk->name, (state) ? "locked" : "bypassed", i); + + ret = 0; + } + + return ret; +} + +/* From 3430 TRM ES2 4.7.6.2 */ +static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n) +{ + unsigned long fint; + u16 f = 0; + + fint = clk->dpll_data->clk_ref->rate / n; + + pr_debug("clock: fint is %lu\n", fint); + + if (fint >= 750000 && fint <= 1000000) + f = 0x3; + else if (fint > 1000000 && fint <= 1250000) + f = 0x4; + else if (fint > 1250000 && fint <= 1500000) + f = 0x5; + else if (fint > 1500000 && fint <= 1750000) + f = 0x6; + else if (fint > 1750000 && fint <= 2100000) + f = 0x7; + else if (fint > 7500000 && fint <= 10000000) + f = 0xB; + else if (fint > 10000000 && fint <= 12500000) + f = 0xC; + else if (fint > 12500000 && fint <= 15000000) + f = 0xD; + else if (fint > 15000000 && fint <= 17500000) + f = 0xE; + else if (fint > 17500000 && fint <= 21000000) + f = 0xF; + else + pr_debug("clock: unknown freqsel setting for %d\n", n); + + return f; +} + +/* Non-CORE DPLL (e.g., DPLLs that do not control SDRC) clock functions */ + +/* + * _omap3_noncore_dpll_lock - instruct a DPLL to lock and wait for readiness + * @clk: pointer to a DPLL struct clk + * + * Instructs a non-CORE DPLL to lock. Waits for the DPLL to report + * readiness before returning. Will save and restore the DPLL's + * autoidle state across the enable, per the CDP code. If the DPLL + * locked successfully, return 0; if the DPLL did not lock in the time + * allotted, or DPLL3 was passed in, return -EINVAL. + */ +static int _omap3_noncore_dpll_lock(struct clk *clk) +{ + u8 ai; + int r; + + pr_debug("clock: locking DPLL %s\n", clk->name); + + ai = omap3_dpll_autoidle_read(clk); + + omap3_dpll_deny_idle(clk); + + _omap3_dpll_write_clken(clk, DPLL_LOCKED); + + r = _omap3_wait_dpll_status(clk, 1); + + if (ai) + omap3_dpll_allow_idle(clk); + + return r; +} + +/* + * _omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness + * @clk: pointer to a DPLL struct clk + * + * Instructs a non-CORE DPLL to enter low-power bypass mode. In + * bypass mode, the DPLL's rate is set equal to its parent clock's + * rate. Waits for the DPLL to report readiness before returning. + * Will save and restore the DPLL's autoidle state across the enable, + * per the CDP code. If the DPLL entered bypass mode successfully, + * return 0; if the DPLL did not enter bypass in the time allotted, or + * DPLL3 was passed in, or the DPLL does not support low-power bypass, + * return -EINVAL. + */ +static int _omap3_noncore_dpll_bypass(struct clk *clk) +{ + int r; + u8 ai; + + if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) + return -EINVAL; + + pr_debug("clock: configuring DPLL %s for low-power bypass\n", + clk->name); + + ai = omap3_dpll_autoidle_read(clk); + + _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_BYPASS); + + r = _omap3_wait_dpll_status(clk, 0); + + if (ai) + omap3_dpll_allow_idle(clk); + else + omap3_dpll_deny_idle(clk); + + return r; +} + +/* + * _omap3_noncore_dpll_stop - instruct a DPLL to stop + * @clk: pointer to a DPLL struct clk + * + * Instructs a non-CORE DPLL to enter low-power stop. Will save and + * restore the DPLL's autoidle state across the stop, per the CDP + * code. If DPLL3 was passed in, or the DPLL does not support + * low-power stop, return -EINVAL; otherwise, return 0. + */ +static int _omap3_noncore_dpll_stop(struct clk *clk) +{ + u8 ai; + + if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP))) + return -EINVAL; + + pr_debug("clock: stopping DPLL %s\n", clk->name); + + ai = omap3_dpll_autoidle_read(clk); + + _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_STOP); + + if (ai) + omap3_dpll_allow_idle(clk); + else + omap3_dpll_deny_idle(clk); + + return 0; +} + +/** + * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode + * @clk: pointer to a DPLL struct clk + * + * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock. + * The choice of modes depends on the DPLL's programmed rate: if it is + * the same as the DPLL's parent clock, it will enter bypass; + * otherwise, it will enter lock. This code will wait for the DPLL to + * indicate readiness before returning, unless the DPLL takes too long + * to enter the target state. Intended to be used as the struct clk's + * enable function. If DPLL3 was passed in, or the DPLL does not + * support low-power stop, or if the DPLL took too long to enter + * bypass or lock, return -EINVAL; otherwise, return 0. + */ +int omap3_noncore_dpll_enable(struct clk *clk) +{ + int r; + struct dpll_data *dd; + + dd = clk->dpll_data; + if (!dd) + return -EINVAL; + + if (clk->rate == dd->clk_bypass->rate) { + WARN_ON(clk->parent != dd->clk_bypass); + r = _omap3_noncore_dpll_bypass(clk); + } else { + WARN_ON(clk->parent != dd->clk_ref); + r = _omap3_noncore_dpll_lock(clk); + } + /* + *FIXME: this is dubious - if clk->rate has changed, what about + * propagating? + */ + if (!r) + clk->rate = omap2_get_dpll_rate(clk); + + return r; +} + +/** + * omap3_noncore_dpll_disable - instruct a DPLL to enter low-power stop + * @clk: pointer to a DPLL struct clk + * + * Instructs a non-CORE DPLL to enter low-power stop. This function is + * intended for use in struct clkops. No return value. + */ +void omap3_noncore_dpll_disable(struct clk *clk) +{ + _omap3_noncore_dpll_stop(clk); +} + + +/* Non-CORE DPLL rate set code */ + +/* + * omap3_noncore_dpll_program - set non-core DPLL M,N values directly + * @clk: struct clk * of DPLL to set + * @m: DPLL multiplier to set + * @n: DPLL divider to set + * @freqsel: FREQSEL value to set + * + * Program the DPLL with the supplied M, N values, and wait for the DPLL to + * lock.. Returns -EINVAL upon error, or 0 upon success. + */ +int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel) +{ + struct dpll_data *dd = clk->dpll_data; + u32 v; + + /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */ + _omap3_noncore_dpll_bypass(clk); + + /* Set jitter correction */ + if (!cpu_is_omap44xx()) { + v = __raw_readl(dd->control_reg); + v &= ~dd->freqsel_mask; + v |= freqsel << __ffs(dd->freqsel_mask); + __raw_writel(v, dd->control_reg); + } + + /* Set DPLL multiplier, divider */ + v = __raw_readl(dd->mult_div1_reg); + v &= ~(dd->mult_mask | dd->div1_mask); + v |= m << __ffs(dd->mult_mask); + v |= (n - 1) << __ffs(dd->div1_mask); + __raw_writel(v, dd->mult_div1_reg); + + /* We let the clock framework set the other output dividers later */ + + /* REVISIT: Set ramp-up delay? */ + + _omap3_noncore_dpll_lock(clk); + + return 0; +} + +/** + * omap3_noncore_dpll_set_rate - set non-core DPLL rate + * @clk: struct clk * of DPLL to set + * @rate: rounded target rate + * + * Set the DPLL CLKOUT to the target rate. If the DPLL can enter + * low-power bypass, and the target rate is the bypass source clock + * rate, then configure the DPLL for bypass. Otherwise, round the + * target rate if it hasn't been done already, then program and lock + * the DPLL. Returns -EINVAL upon error, or 0 upon success. + */ +int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk *new_parent = NULL; + u16 freqsel = 0; + struct dpll_data *dd; + int ret; + + if (!clk || !rate) + return -EINVAL; + + dd = clk->dpll_data; + if (!dd) + return -EINVAL; + + if (rate == omap2_get_dpll_rate(clk)) + return 0; + + /* + * Ensure both the bypass and ref clocks are enabled prior to + * doing anything; we need the bypass clock running to reprogram + * the DPLL. + */ + omap2_clk_enable(dd->clk_bypass); + omap2_clk_enable(dd->clk_ref); + + if (dd->clk_bypass->rate == rate && + (clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) { + pr_debug("clock: %s: set rate: entering bypass.\n", clk->name); + + ret = _omap3_noncore_dpll_bypass(clk); + if (!ret) + new_parent = dd->clk_bypass; + } else { + if (dd->last_rounded_rate != rate) + omap2_dpll_round_rate(clk, rate); + + if (dd->last_rounded_rate == 0) + return -EINVAL; + + /* No freqsel on OMAP4 */ + if (!cpu_is_omap44xx()) { + freqsel = _omap3_dpll_compute_freqsel(clk, + dd->last_rounded_n); + if (!freqsel) + WARN_ON(1); + } + + pr_debug("clock: %s: set rate: locking rate to %lu.\n", + clk->name, rate); + + ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m, + dd->last_rounded_n, freqsel); + if (!ret) + new_parent = dd->clk_ref; + } + if (!ret) { + /* + * Switch the parent clock in the heirarchy, and make sure + * that the new parent's usecount is correct. Note: we + * enable the new parent before disabling the old to avoid + * any unnecessary hardware disable->enable transitions. + */ + if (clk->usecount) { + omap2_clk_enable(new_parent); + omap2_clk_disable(clk->parent); + } + clk_reparent(clk, new_parent); + clk->rate = rate; + } + omap2_clk_disable(dd->clk_ref); + omap2_clk_disable(dd->clk_bypass); + + return 0; +} + +/* DPLL autoidle read/set code */ + +/** + * omap3_dpll_autoidle_read - read a DPLL's autoidle bits + * @clk: struct clk * of the DPLL to read + * + * Return the DPLL's autoidle bits, shifted down to bit 0. Returns + * -EINVAL if passed a null pointer or if the struct clk does not + * appear to refer to a DPLL. + */ +u32 omap3_dpll_autoidle_read(struct clk *clk) +{ + const struct dpll_data *dd; + u32 v; + + if (!clk || !clk->dpll_data) + return -EINVAL; + + dd = clk->dpll_data; + + v = __raw_readl(dd->autoidle_reg); + v &= dd->autoidle_mask; + v >>= __ffs(dd->autoidle_mask); + + return v; +} + +/** + * omap3_dpll_allow_idle - enable DPLL autoidle bits + * @clk: struct clk * of the DPLL to operate on + * + * Enable DPLL automatic idle control. This automatic idle mode + * switching takes effect only when the DPLL is locked, at least on + * OMAP3430. The DPLL will enter low-power stop when its downstream + * clocks are gated. No return value. + */ +void omap3_dpll_allow_idle(struct clk *clk) +{ + const struct dpll_data *dd; + u32 v; + + if (!clk || !clk->dpll_data) + return; + + dd = clk->dpll_data; + + /* + * REVISIT: CORE DPLL can optionally enter low-power bypass + * by writing 0x5 instead of 0x1. Add some mechanism to + * optionally enter this mode. + */ + v = __raw_readl(dd->autoidle_reg); + v &= ~dd->autoidle_mask; + v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask); + __raw_writel(v, dd->autoidle_reg); +} + +/** + * omap3_dpll_deny_idle - prevent DPLL from automatically idling + * @clk: struct clk * of the DPLL to operate on + * + * Disable DPLL automatic idle control. No return value. + */ +void omap3_dpll_deny_idle(struct clk *clk) +{ + const struct dpll_data *dd; + u32 v; + + if (!clk || !clk->dpll_data) + return; + + dd = clk->dpll_data; + + v = __raw_readl(dd->autoidle_reg); + v &= ~dd->autoidle_mask; + v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask); + __raw_writel(v, dd->autoidle_reg); + +} + +/* Clock control for DPLL outputs */ + +/** + * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate + * @clk: DPLL output struct clk + * + * Using parent clock DPLL data, look up DPLL state. If locked, set our + * rate to the dpll_clk * 2; otherwise, just use dpll_clk. + */ +unsigned long omap3_clkoutx2_recalc(struct clk *clk) +{ + const struct dpll_data *dd; + unsigned long rate; + u32 v; + struct clk *pclk; + + /* Walk up the parents of clk, looking for a DPLL */ + pclk = clk->parent; + while (pclk && !pclk->dpll_data) + pclk = pclk->parent; + + /* clk does not have a DPLL as a parent? */ + WARN_ON(!pclk); + + dd = pclk->dpll_data; + + WARN_ON(!dd->enable_mask); + + v = __raw_readl(dd->control_reg) & dd->enable_mask; + v >>= __ffs(dd->enable_mask); + if (v != OMAP3XXX_EN_DPLL_LOCKED) + rate = clk->parent->rate; + else + rate = clk->parent->rate * 2; + return rate; +} diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c index 6083e21b3be650347a6b4cc14c68509833c5d3e6..877c6f5807b7b1d5e68a623715bfa78711286dfd 100644 --- a/arch/arm/mach-omap2/gpmc-smc91x.c +++ b/arch/arm/mach-omap2/gpmc-smc91x.c @@ -33,17 +33,19 @@ static struct resource gpmc_smc91x_resources[] = { }; static struct smc91x_platdata gpmc_smc91x_info = { - .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_IO_SHIFT_0, + .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_IO_SHIFT_0, + .leda = RPC_LED_100_10, + .ledb = RPC_LED_TX_RX, }; static struct platform_device gpmc_smc91x_device = { .name = "smc91x", .id = -1, - .num_resources = ARRAY_SIZE(gpmc_smc91x_resources), - .resource = gpmc_smc91x_resources, .dev = { .platform_data = &gpmc_smc91x_info, }, + .num_resources = ARRAY_SIZE(gpmc_smc91x_resources), + .resource = gpmc_smc91x_resources, }; /* diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index e86f5ca180ea7981f38018889a6a222701353fdf..bd8cb5974726bb670da33dd078965eb49ef96471 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -517,7 +517,7 @@ void __init gpmc_init(void) ck = "gpmc_fck"; l = OMAP34XX_GPMC_BASE; } else if (cpu_is_omap44xx()) { - ck = "gpmc_fck"; + ck = "gpmc_ck"; l = OMAP44XX_GPMC_BASE; } diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..789ca8c02f0c9bf00b2baf54b439881641b7f511 --- /dev/null +++ b/arch/arm/mach-omap2/i2c.c @@ -0,0 +1,56 @@ +/* + * Helper module for board specific I2C bus registration + * + * Copyright (C) 2009 Nokia Corporation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include + +#include "mux.h" + +int __init omap_register_i2c_bus(int bus_id, u32 clkrate, + struct i2c_board_info const *info, + unsigned len) +{ + if (cpu_is_omap24xx()) { + const int omap24xx_pins[][2] = { + { M19_24XX_I2C1_SCL, L15_24XX_I2C1_SDA }, + { J15_24XX_I2C2_SCL, H19_24XX_I2C2_SDA }, + }; + int scl, sda; + + scl = omap24xx_pins[bus_id - 1][0]; + sda = omap24xx_pins[bus_id - 1][1]; + omap_cfg_reg(sda); + omap_cfg_reg(scl); + } + + /* First I2C bus is not muxable */ + if (cpu_is_omap34xx() && bus_id > 1) { + char mux_name[sizeof("i2c2_scl.i2c2_scl")]; + + sprintf(mux_name, "i2c%i_scl.i2c%i_scl", bus_id, bus_id); + omap_mux_init_signal(mux_name, OMAP_PIN_INPUT); + sprintf(mux_name, "i2c%i_sda.i2c%i_sda", bus_id, bus_id); + omap_mux_init_signal(mux_name, OMAP_PIN_INPUT); + } + + return omap_plat_register_i2c_bus(bus_id, clkrate, info, len); +} diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index f48a4b2654ddb1a98afa5caf22bba58b05cf8985..a091b53657b9744514dc1683e32194cccb261888 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -246,6 +246,31 @@ void __init omap3_check_revision(void) } } +void __init omap4_check_revision(void) +{ + u32 idcode; + u16 hawkeye; + u8 rev; + char *rev_name = "ES1.0"; + + /* + * The IC rev detection is done with hawkeye and rev. + * Note that rev does not map directly to defined processor + * revision numbers as ES1.0 uses value 0. + */ + idcode = read_tap_reg(OMAP_TAP_IDCODE); + hawkeye = (idcode >> 12) & 0xffff; + rev = (idcode >> 28) & 0xff; + + if ((hawkeye == 0xb852) && (rev == 0x0)) { + omap_revision = OMAP4430_REV_ES1_0; + pr_info("OMAP%04x %s\n", omap_rev() >> 16, rev_name); + return; + } + + pr_err("Unknown OMAP4 CPU id\n"); +} + #define OMAP3_SHOW_FEATURE(feat) \ if (omap3_has_ ##feat()) \ printk(#feat" "); @@ -277,10 +302,10 @@ void __init omap3_cpuinfo(void) } else if (omap3_has_iva() && omap3_has_sgx()) { /* OMAP3430, OMAP3525, OMAP3515, OMAP3503 devices */ strcpy(cpu_name, "OMAP3430/3530"); - } else if (omap3_has_sgx()) { + } else if (omap3_has_iva()) { omap_revision = OMAP3525_REV(rev); strcpy(cpu_name, "OMAP3525"); - } else if (omap3_has_iva()) { + } else if (omap3_has_sgx()) { omap_revision = OMAP3515_REV(rev); strcpy(cpu_name, "OMAP3515"); } else { @@ -336,7 +361,7 @@ void __init omap2_check_revision(void) omap3_check_features(); omap3_cpuinfo(); } else if (cpu_is_omap44xx()) { - printk(KERN_INFO "FIXME: CPU revision = OMAP4430\n"); + omap4_check_revision(); return; } else { pr_err("OMAP revision unknown, please fix!\n"); diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 59d28b2fd8c54ced6a1dc6dc7d8da364f5beedac..a8749e8017b95974102cf620ca596f6463163961 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -22,19 +22,20 @@ #include #include #include +#include #include #include #include -#include #include #include #include #include +#include +#include -#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdev is ready */ #include "clock.h" #include @@ -43,7 +44,6 @@ #include #include "clockdomains.h" -#endif #include #include "omap_hwmod_2420.h" #include "omap_hwmod_2430.h" @@ -264,6 +264,7 @@ void __init omap2_map_common_io(void) omap2_check_revision(); omap_sram_init(); omapfb_reserve_sdram(); + omap_vram_reserve_sdram(); } /* @@ -319,8 +320,8 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0, omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps); pwrdm_init(powerdomains_omap); clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps); - omap2_clk_init(); #endif + omap2_clk_init(); omap_serial_early_init(); #ifndef CONFIG_ARCH_OMAP4 omap_hwmod_late_init(); diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index c18a94eca641d61826fbad85322bc9f3d2cb4841..e071b3fd1878681d377037bb97880617721c0c76 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -27,19 +27,52 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include -#ifdef CONFIG_OMAP_MUX +#include "mux.h" + +#define OMAP_MUX_BASE_OFFSET 0x30 /* Offset from CTRL_BASE */ +#define OMAP_MUX_BASE_SZ 0x5ca + +struct omap_mux_entry { + struct omap_mux mux; + struct list_head node; +}; + +static unsigned long mux_phys; +static void __iomem *mux_base; + +static inline u16 omap_mux_read(u16 reg) +{ + if (cpu_is_omap24xx()) + return __raw_readb(mux_base + reg); + else + return __raw_readw(mux_base + reg); +} + +static inline void omap_mux_write(u16 val, u16 reg) +{ + if (cpu_is_omap24xx()) + __raw_writeb(val, mux_base + reg); + else + __raw_writew(val, mux_base + reg); +} + +#if defined(CONFIG_ARCH_OMAP24XX) && defined(CONFIG_OMAP_MUX) static struct omap_mux_cfg arch_mux_cfg; /* NOTE: See mux.h for the enumeration */ -#ifdef CONFIG_ARCH_OMAP24XX static struct pin_config __initdata_or_module omap24xx_pins[] = { /* * description mux mux pull pull debug @@ -249,342 +282,14 @@ MUX_CFG_24XX("AF19_2430_GPIO_85", 0x0113, 3, 0, 0, 1) #define OMAP24XX_PINS_SZ ARRAY_SIZE(omap24xx_pins) -#else -#define omap24xx_pins NULL -#define OMAP24XX_PINS_SZ 0 -#endif /* CONFIG_ARCH_OMAP24XX */ - -#ifdef CONFIG_ARCH_OMAP34XX -static struct pin_config __initdata_or_module omap34xx_pins[] = { -/* - * Name, reg-offset, - * mux-mode | [active-mode | off-mode] - */ - -/* 34xx I2C */ -MUX_CFG_34XX("K21_34XX_I2C1_SCL", 0x1ba, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("J21_34XX_I2C1_SDA", 0x1bc, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AF15_34XX_I2C2_SCL", 0x1be, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AE15_34XX_I2C2_SDA", 0x1c0, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AF14_34XX_I2C3_SCL", 0x1c2, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AG14_34XX_I2C3_SDA", 0x1c4, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AD26_34XX_I2C4_SCL", 0xa00, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AE26_34XX_I2C4_SDA", 0xa02, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) - -/* PHY - HSUSB: 12-pin ULPI PHY: Port 1*/ -MUX_CFG_34XX("Y8_3430_USB1HS_PHY_CLK", 0x5da, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_OUTPUT) -MUX_CFG_34XX("Y9_3430_USB1HS_PHY_STP", 0x5d8, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_OUTPUT) -MUX_CFG_34XX("AA14_3430_USB1HS_PHY_DIR", 0x5ec, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AA11_3430_USB1HS_PHY_NXT", 0x5ee, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W13_3430_USB1HS_PHY_D0", 0x5dc, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W12_3430_USB1HS_PHY_D1", 0x5de, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W11_3430_USB1HS_PHY_D2", 0x5e0, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("Y11_3430_USB1HS_PHY_D3", 0x5ea, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W9_3430_USB1HS_PHY_D4", 0x5e4, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("Y12_3430_USB1HS_PHY_D5", 0x5e6, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W8_3430_USB1HS_PHY_D6", 0x5e8, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("Y13_3430_USB1HS_PHY_D7", 0x5e2, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) - -/* PHY - HSUSB: 12-pin ULPI PHY: Port 2*/ -MUX_CFG_34XX("AA8_3430_USB2HS_PHY_CLK", 0x5f0, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_OUTPUT) -MUX_CFG_34XX("AA10_3430_USB2HS_PHY_STP", 0x5f2, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_OUTPUT) -MUX_CFG_34XX("AA9_3430_USB2HS_PHY_DIR", 0x5f4, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AB11_3430_USB2HS_PHY_NXT", 0x5f6, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AB10_3430_USB2HS_PHY_D0", 0x5f8, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AB9_3430_USB2HS_PHY_D1", 0x5fa, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W3_3430_USB2HS_PHY_D2", 0x1d4, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("T4_3430_USB2HS_PHY_D3", 0x1de, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("T3_3430_USB2HS_PHY_D4", 0x1d8, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("R3_3430_USB2HS_PHY_D5", 0x1da, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("R4_3430_USB2HS_PHY_D6", 0x1dc, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("T2_3430_USB2HS_PHY_D7", 0x1d6, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN) - -/* TLL - HSUSB: 12-pin TLL Port 1*/ -MUX_CFG_34XX("Y8_3430_USB1HS_TLL_CLK", 0x5da, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("Y9_3430_USB1HS_TLL_STP", 0x5d8, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AA14_3430_USB1HS_TLL_DIR", 0x5ec, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AA11_3430_USB1HS_TLL_NXT", 0x5ee, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W13_3430_USB1HS_TLL_D0", 0x5dc, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W12_3430_USB1HS_TLL_D1", 0x5de, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W11_3430_USB1HS_TLL_D2", 0x5e0, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("Y11_3430_USB1HS_TLL_D3", 0x5ea, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W9_3430_USB1HS_TLL_D4", 0x5e4, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("Y12_3430_USB1HS_TLL_D5", 0x5e6, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W8_3430_USB1HS_TLL_D6", 0x5e8, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("Y13_3430_USB1HS_TLL_D7", 0x5e2, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) - -/* TLL - HSUSB: 12-pin TLL Port 2*/ -MUX_CFG_34XX("AA8_3430_USB2HS_TLL_CLK", 0x5f0, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AA10_3430_USB2HS_TLL_STP", 0x5f2, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AA9_3430_USB2HS_TLL_DIR", 0x5f4, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AB11_3430_USB2HS_TLL_NXT", 0x5f6, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AB10_3430_USB2HS_TLL_D0", 0x5f8, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AB9_3430_USB2HS_TLL_D1", 0x5fa, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W3_3430_USB2HS_TLL_D2", 0x1d4, - OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("T4_3430_USB2HS_TLL_D3", 0x1de, - OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("T3_3430_USB2HS_TLL_D4", 0x1d8, - OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("R3_3430_USB2HS_TLL_D5", 0x1da, - OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("R4_3430_USB2HS_TLL_D6", 0x1dc, - OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("T2_3430_USB2HS_TLL_D7", 0x1d6, - OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLDOWN) - -/* TLL - HSUSB: 12-pin TLL Port 3*/ -MUX_CFG_34XX("AA6_3430_USB3HS_TLL_CLK", 0x180, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AB3_3430_USB3HS_TLL_STP", 0x166, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AA3_3430_USB3HS_TLL_DIR", 0x168, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("Y3_3430_USB3HS_TLL_NXT", 0x16a, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AA5_3430_USB3HS_TLL_D0", 0x186, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("Y4_3430_USB3HS_TLL_D1", 0x184, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("Y5_3430_USB3HS_TLL_D2", 0x188, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W5_3430_USB3HS_TLL_D3", 0x18a, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AB12_3430_USB3HS_TLL_D4", 0x16c, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AB13_3430_USB3HS_TLL_D5", 0x16e, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AA13_3430_USB3HS_TLL_D6", 0x170, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AA12_3430_USB3HS_TLL_D7", 0x172, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) - -/* PHY FSUSB: FS Serial for Port 1 (multiple PHY modes supported) */ -MUX_CFG_34XX("AF10_3430_USB1FS_PHY_MM1_RXDP", 0x5d8, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AG9_3430_USB1FS_PHY_MM1_RXDM", 0x5ee, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W13_3430_USB1FS_PHY_MM1_RXRCV", 0x5dc, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W12_3430_USB1FS_PHY_MM1_TXSE0", 0x5de, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W11_3430_USB1FS_PHY_MM1_TXDAT", 0x5e0, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("Y11_3430_USB1FS_PHY_MM1_TXEN_N", 0x5ea, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_OUTPUT) - -/* PHY FSUSB: FS Serial for Port 2 (multiple PHY modes supported) */ -MUX_CFG_34XX("AF7_3430_USB2FS_PHY_MM2_RXDP", 0x5f2, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AH7_3430_USB2FS_PHY_MM2_RXDM", 0x5f6, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AB10_3430_USB2FS_PHY_MM2_RXRCV", 0x5f8, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AB9_3430_USB2FS_PHY_MM2_TXSE0", 0x5fa, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("W3_3430_USB2FS_PHY_MM2_TXDAT", 0x1d4, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("T4_3430_USB2FS_PHY_MM2_TXEN_N", 0x1de, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_OUTPUT) - -/* PHY FSUSB: FS Serial for Port 3 (multiple PHY modes supported) */ -MUX_CFG_34XX("AH3_3430_USB3FS_PHY_MM3_RXDP", 0x166, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AE3_3430_USB3FS_PHY_MM3_RXDM", 0x16a, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AD1_3430_USB3FS_PHY_MM3_RXRCV", 0x186, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AE1_3430_USB3FS_PHY_MM3_TXSE0", 0x184, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AD2_3430_USB3FS_PHY_MM3_TXDAT", 0x188, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("AC1_3430_USB3FS_PHY_MM3_TXEN_N", 0x18a, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_OUTPUT) - - -/* 34XX GPIO - bidirectional, unless the name has an "_OUT" suffix. - * (Always specify PIN_INPUT, except for names suffixed by "_OUT".) - * No internal pullup/pulldown without "_UP" or "_DOWN" suffix. - */ -MUX_CFG_34XX("AF26_34XX_GPIO0", 0x1e0, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) -MUX_CFG_34XX("AF22_34XX_GPIO9", 0xa18, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) -MUX_CFG_34XX("AG9_34XX_GPIO23", 0x5ee, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) -MUX_CFG_34XX("AH8_34XX_GPIO29", 0x5fa, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) -MUX_CFG_34XX("U8_34XX_GPIO54_OUT", 0x0b4, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) -MUX_CFG_34XX("U8_34XX_GPIO54_DOWN", 0x0b4, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT_PULLDOWN) -MUX_CFG_34XX("L8_34XX_GPIO63", 0x0ce, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) -MUX_CFG_34XX("G25_34XX_GPIO86_OUT", 0x0fc, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) -MUX_CFG_34XX("AG4_34XX_GPIO134_OUT", 0x160, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) -MUX_CFG_34XX("AF4_34XX_GPIO135_OUT", 0x162, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) -MUX_CFG_34XX("AE4_34XX_GPIO136_OUT", 0x164, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) -MUX_CFG_34XX("AF6_34XX_GPIO140_UP", 0x16c, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AE6_34XX_GPIO141", 0x16e, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) -MUX_CFG_34XX("AF5_34XX_GPIO142", 0x170, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) -MUX_CFG_34XX("AE5_34XX_GPIO143", 0x172, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) -MUX_CFG_34XX("H19_34XX_GPIO164_OUT", 0x19c, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) -MUX_CFG_34XX("J25_34XX_GPIO170", 0x1c6, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) - -/* OMAP3 SDRC CKE signals to SDR/DDR ram chips */ -MUX_CFG_34XX("H16_34XX_SDRC_CKE0", 0x262, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT) -MUX_CFG_34XX("H17_34XX_SDRC_CKE1", 0x264, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT) - -/* MMC1 */ -MUX_CFG_34XX("N28_3430_MMC1_CLK", 0x144, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("M27_3430_MMC1_CMD", 0x146, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("N27_3430_MMC1_DAT0", 0x148, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("N26_3430_MMC1_DAT1", 0x14a, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("N25_3430_MMC1_DAT2", 0x14c, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("P28_3430_MMC1_DAT3", 0x14e, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("P27_3430_MMC1_DAT4", 0x150, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("P26_3430_MMC1_DAT5", 0x152, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("R27_3430_MMC1_DAT6", 0x154, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("R25_3430_MMC1_DAT7", 0x156, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) - -/* MMC2 */ -MUX_CFG_34XX("AE2_3430_MMC2_CLK", 0x158, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AG5_3430_MMC2_CMD", 0x15A, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AH5_3430_MMC2_DAT0", 0x15c, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AH4_3430_MMC2_DAT1", 0x15e, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AG4_3430_MMC2_DAT2", 0x160, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AF4_3430_MMC2_DAT3", 0x162, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AE4_3430_MMC2_DAT4", 0x164, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AH3_3430_MMC2_DAT5", 0x166, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AF3_3430_MMC2_DAT6", 0x168, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AE3_3430_MMC2_DAT7", 0x16A, - OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP) - -/* MMC3 */ -MUX_CFG_34XX("AF10_3430_MMC3_CLK", 0x5d8, - OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AC3_3430_MMC3_CMD", 0x1d0, - OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AE11_3430_MMC3_DAT0", 0x5e4, - OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AH9_3430_MMC3_DAT1", 0x5e6, - OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AF13_3430_MMC3_DAT2", 0x5e8, - OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AF13_3430_MMC3_DAT3", 0x5e2, - OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLUP) - -/* SYS_NIRQ T2 INT1 */ -MUX_CFG_34XX("AF26_34XX_SYS_NIRQ", 0x1E0, - OMAP3_WAKEUP_EN | OMAP34XX_PIN_INPUT_PULLUP | - OMAP34XX_MUX_MODE0) -/* EHCI GPIO's on OMAP3EVM (Rev >= E) */ -MUX_CFG_34XX("AH14_34XX_GPIO21", 0x5ea, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("AF9_34XX_GPIO22", 0x5ec, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT_PULLUP) -MUX_CFG_34XX("U3_34XX_GPIO61", 0x0c8, - OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT_PULLUP) -}; - -#define OMAP34XX_PINS_SZ ARRAY_SIZE(omap34xx_pins) - -#else -#define omap34xx_pins NULL -#define OMAP34XX_PINS_SZ 0 -#endif /* CONFIG_ARCH_OMAP34XX */ - #if defined(CONFIG_OMAP_MUX_DEBUG) || defined(CONFIG_OMAP_MUX_WARNINGS) + static void __init_or_module omap2_cfg_debug(const struct pin_config *cfg, u16 reg) { u16 orig; u8 warn = 0, debug = 0; - if (cpu_is_omap24xx()) - orig = omap_ctrl_readb(cfg->mux_reg); - else - orig = omap_ctrl_readw(cfg->mux_reg); + orig = omap_mux_read(cfg->mux_reg - OMAP_MUX_BASE_OFFSET); #ifdef CONFIG_OMAP_MUX_DEBUG debug = cfg->debug; @@ -600,7 +305,6 @@ static void __init_or_module omap2_cfg_debug(const struct pin_config *cfg, u16 r #define omap2_cfg_debug(x, y) do {} while (0) #endif -#ifdef CONFIG_ARCH_OMAP24XX static int __init_or_module omap24xx_cfg_reg(const struct pin_config *cfg) { static DEFINE_SPINLOCK(mux_spin_lock); @@ -614,47 +318,692 @@ static int __init_or_module omap24xx_cfg_reg(const struct pin_config *cfg) if (cfg->pu_pd_val) reg |= OMAP2_PULL_UP; omap2_cfg_debug(cfg, reg); - omap_ctrl_writeb(reg, cfg->mux_reg); + omap_mux_write(reg, cfg->mux_reg - OMAP_MUX_BASE_OFFSET); spin_unlock_irqrestore(&mux_spin_lock, flags); return 0; } + +int __init omap2_mux_init(void) +{ + u32 mux_pbase; + + if (cpu_is_omap2420()) + mux_pbase = OMAP2420_CTRL_BASE + OMAP_MUX_BASE_OFFSET; + else if (cpu_is_omap2430()) + mux_pbase = OMAP243X_CTRL_BASE + OMAP_MUX_BASE_OFFSET; + else + return -ENODEV; + + mux_base = ioremap(mux_pbase, OMAP_MUX_BASE_SZ); + if (!mux_base) { + printk(KERN_ERR "mux: Could not ioremap\n"); + return -ENODEV; + } + + if (cpu_is_omap24xx()) { + arch_mux_cfg.pins = omap24xx_pins; + arch_mux_cfg.size = OMAP24XX_PINS_SZ; + arch_mux_cfg.cfg_reg = omap24xx_cfg_reg; + + return omap_mux_register(&arch_mux_cfg); + } + + return 0; +} + #else -#define omap24xx_cfg_reg NULL -#endif +int __init omap2_mux_init(void) +{ + return 0; +} +#endif /* CONFIG_OMAP_MUX */ + +/*----------------------------------------------------------------------------*/ #ifdef CONFIG_ARCH_OMAP34XX -static int __init_or_module omap34xx_cfg_reg(const struct pin_config *cfg) +static LIST_HEAD(muxmodes); +static DEFINE_MUTEX(muxmode_mutex); + +#ifdef CONFIG_OMAP_MUX + +static char *omap_mux_options; + +int __init omap_mux_init_gpio(int gpio, int val) { - static DEFINE_SPINLOCK(mux_spin_lock); - unsigned long flags; - u16 reg = 0; + struct omap_mux_entry *e; + int found = 0; + + if (!gpio) + return -EINVAL; + + list_for_each_entry(e, &muxmodes, node) { + struct omap_mux *m = &e->mux; + if (gpio == m->gpio) { + u16 old_mode; + u16 mux_mode; + + old_mode = omap_mux_read(m->reg_offset); + mux_mode = val & ~(OMAP_MUX_NR_MODES - 1); + mux_mode |= OMAP_MUX_MODE4; + printk(KERN_DEBUG "mux: Setting signal " + "%s.gpio%i 0x%04x -> 0x%04x\n", + m->muxnames[0], gpio, old_mode, mux_mode); + omap_mux_write(mux_mode, m->reg_offset); + found++; + } + } - spin_lock_irqsave(&mux_spin_lock, flags); - reg |= cfg->mux_val; - omap2_cfg_debug(cfg, reg); - omap_ctrl_writew(reg, cfg->mux_reg); - spin_unlock_irqrestore(&mux_spin_lock, flags); + if (found == 1) + return 0; + + if (found > 1) { + printk(KERN_ERR "mux: Multiple gpio paths for gpio%i\n", gpio); + return -EINVAL; + } + + printk(KERN_ERR "mux: Could not set gpio%i\n", gpio); + + return -ENODEV; +} + +int __init omap_mux_init_signal(char *muxname, int val) +{ + struct omap_mux_entry *e; + char *m0_name = NULL, *mode_name = NULL; + int found = 0; + + mode_name = strchr(muxname, '.'); + if (mode_name) { + *mode_name = '\0'; + mode_name++; + m0_name = muxname; + } else { + mode_name = muxname; + } + + list_for_each_entry(e, &muxmodes, node) { + struct omap_mux *m = &e->mux; + char *m0_entry = m->muxnames[0]; + int i; + + if (m0_name && strcmp(m0_name, m0_entry)) + continue; + + for (i = 0; i < OMAP_MUX_NR_MODES; i++) { + char *mode_cur = m->muxnames[i]; + + if (!mode_cur) + continue; + + if (!strcmp(mode_name, mode_cur)) { + u16 old_mode; + u16 mux_mode; + + old_mode = omap_mux_read(m->reg_offset); + mux_mode = val | i; + printk(KERN_DEBUG "mux: Setting signal " + "%s.%s 0x%04x -> 0x%04x\n", + m0_entry, muxname, old_mode, mux_mode); + omap_mux_write(mux_mode, m->reg_offset); + found++; + } + } + } + + if (found == 1) + return 0; + + if (found > 1) { + printk(KERN_ERR "mux: Multiple signal paths (%i) for %s\n", + found, muxname); + return -EINVAL; + } + + printk(KERN_ERR "mux: Could not set signal %s\n", muxname); + + return -ENODEV; +} + +#ifdef CONFIG_DEBUG_FS + +#define OMAP_MUX_MAX_NR_FLAGS 10 +#define OMAP_MUX_TEST_FLAG(val, mask) \ + if (((val) & (mask)) == (mask)) { \ + i++; \ + flags[i] = #mask; \ + } + +/* REVISIT: Add checking for non-optimal mux settings */ +static inline void omap_mux_decode(struct seq_file *s, u16 val) +{ + char *flags[OMAP_MUX_MAX_NR_FLAGS]; + char mode[14]; + int i = -1; + + sprintf(mode, "OMAP_MUX_MODE%d", val & 0x7); + i++; + flags[i] = mode; + + OMAP_MUX_TEST_FLAG(val, OMAP_PIN_OFF_WAKEUPENABLE); + if (val & OMAP_OFF_EN) { + if (!(val & OMAP_OFFOUT_EN)) { + if (!(val & OMAP_OFF_PULL_UP)) { + OMAP_MUX_TEST_FLAG(val, + OMAP_PIN_OFF_INPUT_PULLDOWN); + } else { + OMAP_MUX_TEST_FLAG(val, + OMAP_PIN_OFF_INPUT_PULLUP); + } + } else { + if (!(val & OMAP_OFFOUT_VAL)) { + OMAP_MUX_TEST_FLAG(val, + OMAP_PIN_OFF_OUTPUT_LOW); + } else { + OMAP_MUX_TEST_FLAG(val, + OMAP_PIN_OFF_OUTPUT_HIGH); + } + } + } + + if (val & OMAP_INPUT_EN) { + if (val & OMAP_PULL_ENA) { + if (!(val & OMAP_PULL_UP)) { + OMAP_MUX_TEST_FLAG(val, + OMAP_PIN_INPUT_PULLDOWN); + } else { + OMAP_MUX_TEST_FLAG(val, OMAP_PIN_INPUT_PULLUP); + } + } else { + OMAP_MUX_TEST_FLAG(val, OMAP_PIN_INPUT); + } + } else { + i++; + flags[i] = "OMAP_PIN_OUTPUT"; + } + + do { + seq_printf(s, "%s", flags[i]); + if (i > 0) + seq_printf(s, " | "); + } while (i-- > 0); +} + +#define OMAP_MUX_DEFNAME_LEN 16 + +static int omap_mux_dbg_board_show(struct seq_file *s, void *unused) +{ + struct omap_mux_entry *e; + + list_for_each_entry(e, &muxmodes, node) { + struct omap_mux *m = &e->mux; + char m0_def[OMAP_MUX_DEFNAME_LEN]; + char *m0_name = m->muxnames[0]; + u16 val; + int i, mode; + + if (!m0_name) + continue; + + for (i = 0; i < OMAP_MUX_DEFNAME_LEN; i++) { + if (m0_name[i] == '\0') { + m0_def[i] = m0_name[i]; + break; + } + m0_def[i] = toupper(m0_name[i]); + } + val = omap_mux_read(m->reg_offset); + mode = val & OMAP_MUX_MODE7; + + seq_printf(s, "OMAP%i_MUX(%s, ", + cpu_is_omap34xx() ? 3 : 0, m0_def); + omap_mux_decode(s, val); + seq_printf(s, "),\n"); + } + + return 0; +} + +static int omap_mux_dbg_board_open(struct inode *inode, struct file *file) +{ + return single_open(file, omap_mux_dbg_board_show, &inode->i_private); +} + +static const struct file_operations omap_mux_dbg_board_fops = { + .open = omap_mux_dbg_board_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int omap_mux_dbg_signal_show(struct seq_file *s, void *unused) +{ + struct omap_mux *m = s->private; + const char *none = "NA"; + u16 val; + int mode; + + val = omap_mux_read(m->reg_offset); + mode = val & OMAP_MUX_MODE7; + + seq_printf(s, "name: %s.%s (0x%08lx/0x%03x = 0x%04x), b %s, t %s\n", + m->muxnames[0], m->muxnames[mode], + mux_phys + m->reg_offset, m->reg_offset, val, + m->balls[0] ? m->balls[0] : none, + m->balls[1] ? m->balls[1] : none); + seq_printf(s, "mode: "); + omap_mux_decode(s, val); + seq_printf(s, "\n"); + seq_printf(s, "signals: %s | %s | %s | %s | %s | %s | %s | %s\n", + m->muxnames[0] ? m->muxnames[0] : none, + m->muxnames[1] ? m->muxnames[1] : none, + m->muxnames[2] ? m->muxnames[2] : none, + m->muxnames[3] ? m->muxnames[3] : none, + m->muxnames[4] ? m->muxnames[4] : none, + m->muxnames[5] ? m->muxnames[5] : none, + m->muxnames[6] ? m->muxnames[6] : none, + m->muxnames[7] ? m->muxnames[7] : none); return 0; } + +#define OMAP_MUX_MAX_ARG_CHAR 7 + +static ssize_t omap_mux_dbg_signal_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + char buf[OMAP_MUX_MAX_ARG_CHAR]; + struct seq_file *seqf; + struct omap_mux *m; + unsigned long val; + int buf_size, ret; + + if (count > OMAP_MUX_MAX_ARG_CHAR) + return -EINVAL; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + + ret = strict_strtoul(buf, 0x10, &val); + if (ret < 0) + return ret; + + if (val > 0xffff) + return -EINVAL; + + seqf = file->private_data; + m = seqf->private; + + omap_mux_write((u16)val, m->reg_offset); + *ppos += count; + + return count; +} + +static int omap_mux_dbg_signal_open(struct inode *inode, struct file *file) +{ + return single_open(file, omap_mux_dbg_signal_show, inode->i_private); +} + +static const struct file_operations omap_mux_dbg_signal_fops = { + .open = omap_mux_dbg_signal_open, + .read = seq_read, + .write = omap_mux_dbg_signal_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct dentry *mux_dbg_dir; + +static void __init omap_mux_dbg_init(void) +{ + struct omap_mux_entry *e; + + mux_dbg_dir = debugfs_create_dir("omap_mux", NULL); + if (!mux_dbg_dir) + return; + + (void)debugfs_create_file("board", S_IRUGO, mux_dbg_dir, + NULL, &omap_mux_dbg_board_fops); + + list_for_each_entry(e, &muxmodes, node) { + struct omap_mux *m = &e->mux; + + (void)debugfs_create_file(m->muxnames[0], S_IWUGO, mux_dbg_dir, + m, &omap_mux_dbg_signal_fops); + } +} + #else -#define omap34xx_cfg_reg NULL +static inline void omap_mux_dbg_init(void) +{ +} +#endif /* CONFIG_DEBUG_FS */ + +static void __init omap_mux_free_names(struct omap_mux *m) +{ + int i; + + for (i = 0; i < OMAP_MUX_NR_MODES; i++) + kfree(m->muxnames[i]); + +#ifdef CONFIG_DEBUG_FS + for (i = 0; i < OMAP_MUX_NR_SIDES; i++) + kfree(m->balls[i]); #endif -int __init omap2_mux_init(void) +} + +/* Free all data except for GPIO pins unless CONFIG_DEBUG_FS is set */ +static int __init omap_mux_late_init(void) { - if (cpu_is_omap24xx()) { - arch_mux_cfg.pins = omap24xx_pins; - arch_mux_cfg.size = OMAP24XX_PINS_SZ; - arch_mux_cfg.cfg_reg = omap24xx_cfg_reg; - } else if (cpu_is_omap34xx()) { - arch_mux_cfg.pins = omap34xx_pins; - arch_mux_cfg.size = OMAP34XX_PINS_SZ; - arch_mux_cfg.cfg_reg = omap34xx_cfg_reg; + struct omap_mux_entry *e, *tmp; + + list_for_each_entry_safe(e, tmp, &muxmodes, node) { + struct omap_mux *m = &e->mux; + u16 mode = omap_mux_read(m->reg_offset); + + if (OMAP_MODE_GPIO(mode)) + continue; + +#ifndef CONFIG_DEBUG_FS + mutex_lock(&muxmode_mutex); + list_del(&e->node); + mutex_unlock(&muxmode_mutex); + omap_mux_free_names(m); + kfree(m); +#endif + + } + + omap_mux_dbg_init(); + + return 0; +} +late_initcall(omap_mux_late_init); + +static void __init omap_mux_package_fixup(struct omap_mux *p, + struct omap_mux *superset) +{ + while (p->reg_offset != OMAP_MUX_TERMINATOR) { + struct omap_mux *s = superset; + int found = 0; + + while (s->reg_offset != OMAP_MUX_TERMINATOR) { + if (s->reg_offset == p->reg_offset) { + *s = *p; + found++; + break; + } + s++; + } + if (!found) + printk(KERN_ERR "mux: Unknown entry offset 0x%x\n", + p->reg_offset); + p++; + } +} + +#ifdef CONFIG_DEBUG_FS + +static void __init omap_mux_package_init_balls(struct omap_ball *b, + struct omap_mux *superset) +{ + while (b->reg_offset != OMAP_MUX_TERMINATOR) { + struct omap_mux *s = superset; + int found = 0; + + while (s->reg_offset != OMAP_MUX_TERMINATOR) { + if (s->reg_offset == b->reg_offset) { + s->balls[0] = b->balls[0]; + s->balls[1] = b->balls[1]; + found++; + break; + } + s++; + } + if (!found) + printk(KERN_ERR "mux: Unknown ball offset 0x%x\n", + b->reg_offset); + b++; + } +} + +#else /* CONFIG_DEBUG_FS */ + +static inline void omap_mux_package_init_balls(struct omap_ball *b, + struct omap_mux *superset) +{ +} + +#endif /* CONFIG_DEBUG_FS */ + +static int __init omap_mux_setup(char *options) +{ + if (!options) + return 0; + + omap_mux_options = options; + + return 1; +} +__setup("omap_mux=", omap_mux_setup); + +/* + * Note that the omap_mux=some.signal1=0x1234,some.signal2=0x1234 + * cmdline options only override the bootloader values. + * During development, please enable CONFIG_DEBUG_FS, and use the + * signal specific entries under debugfs. + */ +static void __init omap_mux_set_cmdline_signals(void) +{ + char *options, *next_opt, *token; + + if (!omap_mux_options) + return; + + options = kmalloc(strlen(omap_mux_options) + 1, GFP_KERNEL); + if (!options) + return; + + strcpy(options, omap_mux_options); + next_opt = options; + + while ((token = strsep(&next_opt, ",")) != NULL) { + char *keyval, *name; + unsigned long val; + + keyval = token; + name = strsep(&keyval, "="); + if (name) { + int res; + + res = strict_strtoul(keyval, 0x10, &val); + if (res < 0) + continue; + + omap_mux_init_signal(name, (u16)val); + } + } + + kfree(options); +} + +static void __init omap_mux_set_board_signals(struct omap_board_mux *board_mux) +{ + while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) { + omap_mux_write(board_mux->value, board_mux->reg_offset); + board_mux++; + } +} + +static int __init omap_mux_copy_names(struct omap_mux *src, + struct omap_mux *dst) +{ + int i; + + for (i = 0; i < OMAP_MUX_NR_MODES; i++) { + if (src->muxnames[i]) { + dst->muxnames[i] = + kmalloc(strlen(src->muxnames[i]) + 1, + GFP_KERNEL); + if (!dst->muxnames[i]) + goto free; + strcpy(dst->muxnames[i], src->muxnames[i]); + } + } + +#ifdef CONFIG_DEBUG_FS + for (i = 0; i < OMAP_MUX_NR_SIDES; i++) { + if (src->balls[i]) { + dst->balls[i] = + kmalloc(strlen(src->balls[i]) + 1, + GFP_KERNEL); + if (!dst->balls[i]) + goto free; + strcpy(dst->balls[i], src->balls[i]); + } + } +#endif + + return 0; + +free: + omap_mux_free_names(dst); + return -ENOMEM; + +} + +#endif /* CONFIG_OMAP_MUX */ + +static u16 omap_mux_get_by_gpio(int gpio) +{ + struct omap_mux_entry *e; + u16 offset = OMAP_MUX_TERMINATOR; + + list_for_each_entry(e, &muxmodes, node) { + struct omap_mux *m = &e->mux; + if (m->gpio == gpio) { + offset = m->reg_offset; + break; + } + } + + return offset; +} + +/* Needed for dynamic muxing of GPIO pins for off-idle */ +u16 omap_mux_get_gpio(int gpio) +{ + u16 offset; + + offset = omap_mux_get_by_gpio(gpio); + if (offset == OMAP_MUX_TERMINATOR) { + printk(KERN_ERR "mux: Could not get gpio%i\n", gpio); + return offset; + } + + return omap_mux_read(offset); +} + +/* Needed for dynamic muxing of GPIO pins for off-idle */ +void omap_mux_set_gpio(u16 val, int gpio) +{ + u16 offset; + + offset = omap_mux_get_by_gpio(gpio); + if (offset == OMAP_MUX_TERMINATOR) { + printk(KERN_ERR "mux: Could not set gpio%i\n", gpio); + return; + } + + omap_mux_write(val, offset); +} + +static struct omap_mux * __init omap_mux_list_add(struct omap_mux *src) +{ + struct omap_mux_entry *entry; + struct omap_mux *m; + + entry = kzalloc(sizeof(struct omap_mux_entry), GFP_KERNEL); + if (!entry) + return NULL; + + m = &entry->mux; + memcpy(m, src, sizeof(struct omap_mux_entry)); + +#ifdef CONFIG_OMAP_MUX + if (omap_mux_copy_names(src, m)) { + kfree(entry); + return NULL; } +#endif + + mutex_lock(&muxmode_mutex); + list_add_tail(&entry->node, &muxmodes); + mutex_unlock(&muxmode_mutex); - return omap_mux_register(&arch_mux_cfg); + return m; } +/* + * Note if CONFIG_OMAP_MUX is not selected, we will only initialize + * the GPIO to mux offset mapping that is needed for dynamic muxing + * of GPIO pins for off-idle. + */ +static void __init omap_mux_init_list(struct omap_mux *superset) +{ + while (superset->reg_offset != OMAP_MUX_TERMINATOR) { + struct omap_mux *entry; + +#ifndef CONFIG_OMAP_MUX + /* Skip pins that are not muxed as GPIO by bootloader */ + if (!OMAP_MODE_GPIO(omap_mux_read(superset->reg_offset))) { + superset++; + continue; + } #endif + + entry = omap_mux_list_add(superset); + if (!entry) { + printk(KERN_ERR "mux: Could not add entry\n"); + return; + } + superset++; + } +} + +int __init omap_mux_init(u32 mux_pbase, u32 mux_size, + struct omap_mux *superset, + struct omap_mux *package_subset, + struct omap_board_mux *board_mux, + struct omap_ball *package_balls) +{ + if (mux_base) + return -EBUSY; + + mux_phys = mux_pbase; + mux_base = ioremap(mux_pbase, mux_size); + if (!mux_base) { + printk(KERN_ERR "mux: Could not ioremap\n"); + return -ENODEV; + } + +#ifdef CONFIG_OMAP_MUX + omap_mux_package_fixup(package_subset, superset); + omap_mux_package_init_balls(package_balls, superset); + omap_mux_set_cmdline_signals(); + omap_mux_set_board_signals(board_mux); +#endif + + omap_mux_init_list(superset); + + return 0; +} + +#endif /* CONFIG_ARCH_OMAP34XX */ + diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h new file mode 100644 index 0000000000000000000000000000000000000000..d8b4d5ad22783ffe342611ba801a07a709ce6b18 --- /dev/null +++ b/arch/arm/mach-omap2/mux.h @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2009 Nokia + * Copyright (C) 2009 Texas Instruments + * + * 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 "mux34xx.h" + +#define OMAP_MUX_TERMINATOR 0xffff + +/* 34xx mux mode options for each pin. See TRM for options */ +#define OMAP_MUX_MODE0 0 +#define OMAP_MUX_MODE1 1 +#define OMAP_MUX_MODE2 2 +#define OMAP_MUX_MODE3 3 +#define OMAP_MUX_MODE4 4 +#define OMAP_MUX_MODE5 5 +#define OMAP_MUX_MODE6 6 +#define OMAP_MUX_MODE7 7 + +/* 24xx/34xx mux bit defines */ +#define OMAP_PULL_ENA (1 << 3) +#define OMAP_PULL_UP (1 << 4) +#define OMAP_ALTELECTRICALSEL (1 << 5) + +/* 34xx specific mux bit defines */ +#define OMAP_INPUT_EN (1 << 8) +#define OMAP_OFF_EN (1 << 9) +#define OMAP_OFFOUT_EN (1 << 10) +#define OMAP_OFFOUT_VAL (1 << 11) +#define OMAP_OFF_PULL_EN (1 << 12) +#define OMAP_OFF_PULL_UP (1 << 13) +#define OMAP_WAKEUP_EN (1 << 14) + +/* Active pin states */ +#define OMAP_PIN_OUTPUT 0 +#define OMAP_PIN_INPUT OMAP_INPUT_EN +#define OMAP_PIN_INPUT_PULLUP (OMAP_PULL_ENA | OMAP_INPUT_EN \ + | OMAP_PULL_UP) +#define OMAP_PIN_INPUT_PULLDOWN (OMAP_PULL_ENA | OMAP_INPUT_EN) + +/* Off mode states */ +#define OMAP_PIN_OFF_NONE 0 +#define OMAP_PIN_OFF_OUTPUT_HIGH (OMAP_OFF_EN | OMAP_OFFOUT_EN \ + | OMAP_OFFOUT_VAL) +#define OMAP_PIN_OFF_OUTPUT_LOW (OMAP_OFF_EN | OMAP_OFFOUT_EN) +#define OMAP_PIN_OFF_INPUT_PULLUP (OMAP_OFF_EN | OMAP_OFF_PULL_EN \ + | OMAP_OFF_PULL_UP) +#define OMAP_PIN_OFF_INPUT_PULLDOWN (OMAP_OFF_EN | OMAP_OFF_PULL_EN) +#define OMAP_PIN_OFF_WAKEUPENABLE OMAP_WAKEUP_EN + +#define OMAP_MODE_GPIO(x) (((x) & OMAP_MUX_MODE7) == OMAP_MUX_MODE4) + +/* Flags for omap_mux_init */ +#define OMAP_PACKAGE_MASK 0xffff +#define OMAP_PACKAGE_CBP 4 /* 515-pin 0.40 0.50 */ +#define OMAP_PACKAGE_CUS 3 /* 423-pin 0.65 */ +#define OMAP_PACKAGE_CBB 2 /* 515-pin 0.40 0.50 */ +#define OMAP_PACKAGE_CBC 1 /* 515-pin 0.50 0.65 */ + + +#define OMAP_MUX_NR_MODES 8 /* Available modes */ +#define OMAP_MUX_NR_SIDES 2 /* Bottom & top */ + +/** + * struct omap_mux - data for omap mux register offset and it's value + * @reg_offset: mux register offset from the mux base + * @gpio: GPIO number + * @muxnames: available signal modes for a ball + */ +struct omap_mux { + u16 reg_offset; + u16 gpio; +#ifdef CONFIG_OMAP_MUX + char *muxnames[OMAP_MUX_NR_MODES]; +#ifdef CONFIG_DEBUG_FS + char *balls[OMAP_MUX_NR_SIDES]; +#endif +#endif +}; + +/** + * struct omap_ball - data for balls on omap package + * @reg_offset: mux register offset from the mux base + * @balls: available balls on the package + */ +struct omap_ball { + u16 reg_offset; + char *balls[OMAP_MUX_NR_SIDES]; +}; + +/** + * struct omap_board_mux - data for initializing mux registers + * @reg_offset: mux register offset from the mux base + * @mux_value: desired mux value to set + */ +struct omap_board_mux { + u16 reg_offset; + u16 value; +}; + +#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_ARCH_OMAP34XX) + +/** + * omap_mux_init_gpio - initialize a signal based on the GPIO number + * @gpio: GPIO number + * @val: Options for the mux register value + */ +int omap_mux_init_gpio(int gpio, int val); + +/** + * omap_mux_init_signal - initialize a signal based on the signal name + * @muxname: Mux name in mode0_name.signal_name format + * @val: Options for the mux register value + */ +int omap_mux_init_signal(char *muxname, int val); + +#else + +static inline int omap_mux_init_gpio(int gpio, int val) +{ + return 0; +} +static inline int omap_mux_init_signal(char *muxname, int val) +{ + return 0; +} + +#endif + +/** + * omap_mux_get_gpio() - get mux register value based on GPIO number + * @gpio: GPIO number + * + */ +u16 omap_mux_get_gpio(int gpio); + +/** + * omap_mux_set_gpio() - set mux register value based on GPIO number + * @val: New mux register value + * @gpio: GPIO number + * + */ +void omap_mux_set_gpio(u16 val, int gpio); + +/** + * omap3_mux_init() - initialize mux system with board specific set + * @board_mux: Board specific mux table + * @flags: OMAP package type used for the board + */ +int omap3_mux_init(struct omap_board_mux *board_mux, int flags); + +/** + * omap_mux_init - private mux init function, do not call + */ +int omap_mux_init(u32 mux_pbase, u32 mux_size, + struct omap_mux *superset, + struct omap_mux *package_subset, + struct omap_board_mux *board_mux, + struct omap_ball *package_balls); diff --git a/arch/arm/mach-omap2/mux34xx.c b/arch/arm/mach-omap2/mux34xx.c new file mode 100644 index 0000000000000000000000000000000000000000..68e0a595f9a18f42878baa5048dfca08e9585d28 --- /dev/null +++ b/arch/arm/mach-omap2/mux34xx.c @@ -0,0 +1,2099 @@ +/* + * Copyright (C) 2009 Nokia + * Copyright (C) 2009 Texas Instruments + * + * 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 "mux.h" + +#ifdef CONFIG_OMAP_MUX + +#define _OMAP3_MUXENTRY(M0, g, m0, m1, m2, m3, m4, m5, m6, m7) \ +{ \ + .reg_offset = (OMAP3_CONTROL_PADCONF_##M0##_OFFSET), \ + .gpio = (g), \ + .muxnames = { m0, m1, m2, m3, m4, m5, m6, m7 }, \ +} + +#else + +#define _OMAP3_MUXENTRY(M0, g, m0, m1, m2, m3, m4, m5, m6, m7) \ +{ \ + .reg_offset = (OMAP3_CONTROL_PADCONF_##M0##_OFFSET), \ + .gpio = (g), \ +} + +#endif + +#define _OMAP3_BALLENTRY(M0, bb, bt) \ +{ \ + .reg_offset = (OMAP3_CONTROL_PADCONF_##M0##_OFFSET), \ + .balls = { bb, bt }, \ +} + +/* + * Superset of all mux modes for omap3 + */ +static struct omap_mux __initdata omap3_muxmodes[] = { + _OMAP3_MUXENTRY(CAM_D0, 99, + "cam_d0", NULL, NULL, NULL, + "gpio_99", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D1, 100, + "cam_d1", NULL, NULL, NULL, + "gpio_100", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D10, 109, + "cam_d10", NULL, NULL, NULL, + "gpio_109", "hw_dbg8", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D11, 110, + "cam_d11", NULL, NULL, NULL, + "gpio_110", "hw_dbg9", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D2, 101, + "cam_d2", NULL, NULL, NULL, + "gpio_101", "hw_dbg4", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D3, 102, + "cam_d3", NULL, NULL, NULL, + "gpio_102", "hw_dbg5", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D4, 103, + "cam_d4", NULL, NULL, NULL, + "gpio_103", "hw_dbg6", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D5, 104, + "cam_d5", NULL, NULL, NULL, + "gpio_104", "hw_dbg7", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D6, 105, + "cam_d6", NULL, NULL, NULL, + "gpio_105", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D7, 106, + "cam_d7", NULL, NULL, NULL, + "gpio_106", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D8, 107, + "cam_d8", NULL, NULL, NULL, + "gpio_107", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D9, 108, + "cam_d9", NULL, NULL, NULL, + "gpio_108", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_FLD, 98, + "cam_fld", NULL, "cam_global_reset", NULL, + "gpio_98", "hw_dbg3", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_HS, 94, + "cam_hs", NULL, NULL, NULL, + "gpio_94", "hw_dbg0", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_PCLK, 97, + "cam_pclk", NULL, NULL, NULL, + "gpio_97", "hw_dbg2", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_STROBE, 126, + "cam_strobe", NULL, NULL, NULL, + "gpio_126", "hw_dbg11", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_VS, 95, + "cam_vs", NULL, NULL, NULL, + "gpio_95", "hw_dbg1", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_WEN, 167, + "cam_wen", NULL, "cam_shutter", NULL, + "gpio_167", "hw_dbg10", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_XCLKA, 96, + "cam_xclka", NULL, NULL, NULL, + "gpio_96", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_XCLKB, 111, + "cam_xclkb", NULL, NULL, NULL, + "gpio_111", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CSI2_DX0, 112, + "csi2_dx0", NULL, NULL, NULL, + "gpio_112", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CSI2_DX1, 114, + "csi2_dx1", NULL, NULL, NULL, + "gpio_114", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CSI2_DY0, 113, + "csi2_dy0", NULL, NULL, NULL, + "gpio_113", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CSI2_DY1, 115, + "csi2_dy1", NULL, NULL, NULL, + "gpio_115", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_ACBIAS, 69, + "dss_acbias", NULL, NULL, NULL, + "gpio_69", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA0, 70, + "dss_data0", NULL, "uart1_cts", NULL, + "gpio_70", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA1, 71, + "dss_data1", NULL, "uart1_rts", NULL, + "gpio_71", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA10, 80, + "dss_data10", NULL, NULL, NULL, + "gpio_80", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA11, 81, + "dss_data11", NULL, NULL, NULL, + "gpio_81", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA12, 82, + "dss_data12", NULL, NULL, NULL, + "gpio_82", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA13, 83, + "dss_data13", NULL, NULL, NULL, + "gpio_83", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA14, 84, + "dss_data14", NULL, NULL, NULL, + "gpio_84", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA15, 85, + "dss_data15", NULL, NULL, NULL, + "gpio_85", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA16, 86, + "dss_data16", NULL, NULL, NULL, + "gpio_86", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA17, 87, + "dss_data17", NULL, NULL, NULL, + "gpio_87", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA18, 88, + "dss_data18", NULL, "mcspi3_clk", "dss_data0", + "gpio_88", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA19, 89, + "dss_data19", NULL, "mcspi3_simo", "dss_data1", + "gpio_89", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA20, 90, + "dss_data20", NULL, "mcspi3_somi", "dss_data2", + "gpio_90", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA21, 91, + "dss_data21", NULL, "mcspi3_cs0", "dss_data3", + "gpio_91", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA22, 92, + "dss_data22", NULL, "mcspi3_cs1", "dss_data4", + "gpio_92", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA23, 93, + "dss_data23", NULL, NULL, "dss_data5", + "gpio_93", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA2, 72, + "dss_data2", NULL, NULL, NULL, + "gpio_72", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA3, 73, + "dss_data3", NULL, NULL, NULL, + "gpio_73", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA4, 74, + "dss_data4", NULL, "uart3_rx_irrx", NULL, + "gpio_74", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA5, 75, + "dss_data5", NULL, "uart3_tx_irtx", NULL, + "gpio_75", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA6, 76, + "dss_data6", NULL, "uart1_tx", NULL, + "gpio_76", "hw_dbg14", NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA7, 77, + "dss_data7", NULL, "uart1_rx", NULL, + "gpio_77", "hw_dbg15", NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA8, 78, + "dss_data8", NULL, NULL, NULL, + "gpio_78", "hw_dbg16", NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA9, 79, + "dss_data9", NULL, NULL, NULL, + "gpio_79", "hw_dbg17", NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_HSYNC, 67, + "dss_hsync", NULL, NULL, NULL, + "gpio_67", "hw_dbg13", NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_PCLK, 66, + "dss_pclk", NULL, NULL, NULL, + "gpio_66", "hw_dbg12", NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_VSYNC, 68, + "dss_vsync", NULL, NULL, NULL, + "gpio_68", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(ETK_CLK, 12, + "etk_clk", "mcbsp5_clkx", "sdmmc3_clk", "hsusb1_stp", + "gpio_12", "mm1_rxdp", "hsusb1_tll_stp", "hw_dbg0"), + _OMAP3_MUXENTRY(ETK_CTL, 13, + "etk_ctl", NULL, "sdmmc3_cmd", "hsusb1_clk", + "gpio_13", NULL, "hsusb1_tll_clk", "hw_dbg1"), + _OMAP3_MUXENTRY(ETK_D0, 14, + "etk_d0", "mcspi3_simo", "sdmmc3_dat4", "hsusb1_data0", + "gpio_14", "mm1_rxrcv", "hsusb1_tll_data0", "hw_dbg2"), + _OMAP3_MUXENTRY(ETK_D1, 15, + "etk_d1", "mcspi3_somi", NULL, "hsusb1_data1", + "gpio_15", "mm1_txse0", "hsusb1_tll_data1", "hw_dbg3"), + _OMAP3_MUXENTRY(ETK_D10, 24, + "etk_d10", NULL, "uart1_rx", "hsusb2_clk", + "gpio_24", NULL, "hsusb2_tll_clk", "hw_dbg12"), + _OMAP3_MUXENTRY(ETK_D11, 25, + "etk_d11", NULL, NULL, "hsusb2_stp", + "gpio_25", "mm2_rxdp", "hsusb2_tll_stp", "hw_dbg13"), + _OMAP3_MUXENTRY(ETK_D12, 26, + "etk_d12", NULL, NULL, "hsusb2_dir", + "gpio_26", NULL, "hsusb2_tll_dir", "hw_dbg14"), + _OMAP3_MUXENTRY(ETK_D13, 27, + "etk_d13", NULL, NULL, "hsusb2_nxt", + "gpio_27", "mm2_rxdm", "hsusb2_tll_nxt", "hw_dbg15"), + _OMAP3_MUXENTRY(ETK_D14, 28, + "etk_d14", NULL, NULL, "hsusb2_data0", + "gpio_28", "mm2_rxrcv", "hsusb2_tll_data0", "hw_dbg16"), + _OMAP3_MUXENTRY(ETK_D15, 29, + "etk_d15", NULL, NULL, "hsusb2_data1", + "gpio_29", "mm2_txse0", "hsusb2_tll_data1", "hw_dbg17"), + _OMAP3_MUXENTRY(ETK_D2, 16, + "etk_d2", "mcspi3_cs0", NULL, "hsusb1_data2", + "gpio_16", "mm1_txdat", "hsusb1_tll_data2", "hw_dbg4"), + _OMAP3_MUXENTRY(ETK_D3, 17, + "etk_d3", "mcspi3_clk", "sdmmc3_dat3", "hsusb1_data7", + "gpio_17", NULL, "hsusb1_tll_data7", "hw_dbg5"), + _OMAP3_MUXENTRY(ETK_D4, 18, + "etk_d4", "mcbsp5_dr", "sdmmc3_dat0", "hsusb1_data4", + "gpio_18", NULL, "hsusb1_tll_data4", "hw_dbg6"), + _OMAP3_MUXENTRY(ETK_D5, 19, + "etk_d5", "mcbsp5_fsx", "sdmmc3_dat1", "hsusb1_data5", + "gpio_19", NULL, "hsusb1_tll_data5", "hw_dbg7"), + _OMAP3_MUXENTRY(ETK_D6, 20, + "etk_d6", "mcbsp5_dx", "sdmmc3_dat2", "hsusb1_data6", + "gpio_20", NULL, "hsusb1_tll_data6", "hw_dbg8"), + _OMAP3_MUXENTRY(ETK_D7, 21, + "etk_d7", "mcspi3_cs1", "sdmmc3_dat7", "hsusb1_data3", + "gpio_21", "mm1_txen_n", "hsusb1_tll_data3", "hw_dbg9"), + _OMAP3_MUXENTRY(ETK_D8, 22, + "etk_d8", "sys_drm_msecure", "sdmmc3_dat6", "hsusb1_dir", + "gpio_22", NULL, "hsusb1_tll_dir", "hw_dbg10"), + _OMAP3_MUXENTRY(ETK_D9, 23, + "etk_d9", "sys_secure_indicator", "sdmmc3_dat5", "hsusb1_nxt", + "gpio_23", "mm1_rxdm", "hsusb1_tll_nxt", "hw_dbg11"), + _OMAP3_MUXENTRY(GPMC_A1, 34, + "gpmc_a1", NULL, NULL, NULL, + "gpio_34", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_A10, 43, + "gpmc_a10", "sys_ndmareq3", NULL, NULL, + "gpio_43", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_A2, 35, + "gpmc_a2", NULL, NULL, NULL, + "gpio_35", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_A3, 36, + "gpmc_a3", NULL, NULL, NULL, + "gpio_36", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_A4, 37, + "gpmc_a4", NULL, NULL, NULL, + "gpio_37", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_A5, 38, + "gpmc_a5", NULL, NULL, NULL, + "gpio_38", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_A6, 39, + "gpmc_a6", NULL, NULL, NULL, + "gpio_39", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_A7, 40, + "gpmc_a7", NULL, NULL, NULL, + "gpio_40", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_A8, 41, + "gpmc_a8", NULL, NULL, NULL, + "gpio_41", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_A9, 42, + "gpmc_a9", "sys_ndmareq2", NULL, NULL, + "gpio_42", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_CLK, 59, + "gpmc_clk", NULL, NULL, NULL, + "gpio_59", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_D10, 46, + "gpmc_d10", NULL, NULL, NULL, + "gpio_46", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_D11, 47, + "gpmc_d11", NULL, NULL, NULL, + "gpio_47", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_D12, 48, + "gpmc_d12", NULL, NULL, NULL, + "gpio_48", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_D13, 49, + "gpmc_d13", NULL, NULL, NULL, + "gpio_49", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_D14, 50, + "gpmc_d14", NULL, NULL, NULL, + "gpio_50", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_D15, 51, + "gpmc_d15", NULL, NULL, NULL, + "gpio_51", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_D8, 44, + "gpmc_d8", NULL, NULL, NULL, + "gpio_44", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_D9, 45, + "gpmc_d9", NULL, NULL, NULL, + "gpio_45", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_NBE0_CLE, 60, + "gpmc_nbe0_cle", NULL, NULL, NULL, + "gpio_60", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_NBE1, 61, + "gpmc_nbe1", NULL, NULL, NULL, + "gpio_61", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_NCS1, 52, + "gpmc_ncs1", NULL, NULL, NULL, + "gpio_52", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_NCS2, 53, + "gpmc_ncs2", NULL, NULL, NULL, + "gpio_53", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_NCS3, 54, + "gpmc_ncs3", "sys_ndmareq0", NULL, NULL, + "gpio_54", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_NCS4, 55, + "gpmc_ncs4", "sys_ndmareq1", "mcbsp4_clkx", "gpt9_pwm_evt", + "gpio_55", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_NCS5, 56, + "gpmc_ncs5", "sys_ndmareq2", "mcbsp4_dr", "gpt10_pwm_evt", + "gpio_56", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_NCS6, 57, + "gpmc_ncs6", "sys_ndmareq3", "mcbsp4_dx", "gpt11_pwm_evt", + "gpio_57", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_NCS7, 58, + "gpmc_ncs7", "gpmc_io_dir", "mcbsp4_fsx", "gpt8_pwm_evt", + "gpio_58", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_NWP, 62, + "gpmc_nwp", NULL, NULL, NULL, + "gpio_62", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_WAIT1, 63, + "gpmc_wait1", NULL, NULL, NULL, + "gpio_63", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_WAIT2, 64, + "gpmc_wait2", NULL, NULL, NULL, + "gpio_64", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_WAIT3, 65, + "gpmc_wait3", "sys_ndmareq1", NULL, NULL, + "gpio_65", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(HDQ_SIO, 170, + "hdq_sio", "sys_altclk", "i2c2_sccbe", "i2c3_sccbe", + "gpio_170", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_CLK, 120, + "hsusb0_clk", NULL, NULL, NULL, + "gpio_120", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_DATA0, 125, + "hsusb0_data0", NULL, "uart3_tx_irtx", NULL, + "gpio_125", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_DATA1, 130, + "hsusb0_data1", NULL, "uart3_rx_irrx", NULL, + "gpio_130", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_DATA2, 131, + "hsusb0_data2", NULL, "uart3_rts_sd", NULL, + "gpio_131", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_DATA3, 169, + "hsusb0_data3", NULL, "uart3_cts_rctx", NULL, + "gpio_169", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_DATA4, 188, + "hsusb0_data4", NULL, NULL, NULL, + "gpio_188", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_DATA5, 189, + "hsusb0_data5", NULL, NULL, NULL, + "gpio_189", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_DATA6, 190, + "hsusb0_data6", NULL, NULL, NULL, + "gpio_190", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_DATA7, 191, + "hsusb0_data7", NULL, NULL, NULL, + "gpio_191", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_DIR, 122, + "hsusb0_dir", NULL, NULL, NULL, + "gpio_122", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_NXT, 124, + "hsusb0_nxt", NULL, NULL, NULL, + "gpio_124", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_STP, 121, + "hsusb0_stp", NULL, NULL, NULL, + "gpio_121", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(I2C2_SCL, 168, + "i2c2_scl", NULL, NULL, NULL, + "gpio_168", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(I2C2_SDA, 183, + "i2c2_sda", NULL, NULL, NULL, + "gpio_183", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(I2C3_SCL, 184, + "i2c3_scl", NULL, NULL, NULL, + "gpio_184", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(I2C3_SDA, 185, + "i2c3_sda", NULL, NULL, NULL, + "gpio_185", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(I2C4_SCL, 0, + "i2c4_scl", "sys_nvmode1", NULL, NULL, + NULL, NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(I2C4_SDA, 0, + "i2c4_sda", "sys_nvmode2", NULL, NULL, + NULL, NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(JTAG_EMU0, 11, + "jtag_emu0", NULL, NULL, NULL, + "gpio_11", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(JTAG_EMU1, 31, + "jtag_emu1", NULL, NULL, NULL, + "gpio_31", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP1_CLKR, 156, + "mcbsp1_clkr", "mcspi4_clk", NULL, NULL, + "gpio_156", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP1_CLKX, 162, + "mcbsp1_clkx", NULL, "mcbsp3_clkx", NULL, + "gpio_162", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP1_DR, 159, + "mcbsp1_dr", "mcspi4_somi", "mcbsp3_dr", NULL, + "gpio_159", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP1_DX, 158, + "mcbsp1_dx", "mcspi4_simo", "mcbsp3_dx", NULL, + "gpio_158", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP1_FSR, 157, + "mcbsp1_fsr", NULL, "cam_global_reset", NULL, + "gpio_157", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP1_FSX, 161, + "mcbsp1_fsx", "mcspi4_cs0", "mcbsp3_fsx", NULL, + "gpio_161", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP2_CLKX, 117, + "mcbsp2_clkx", NULL, NULL, NULL, + "gpio_117", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP2_DR, 118, + "mcbsp2_dr", NULL, NULL, NULL, + "gpio_118", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP2_DX, 119, + "mcbsp2_dx", NULL, NULL, NULL, + "gpio_119", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP2_FSX, 116, + "mcbsp2_fsx", NULL, NULL, NULL, + "gpio_116", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP3_CLKX, 142, + "mcbsp3_clkx", "uart2_tx", NULL, NULL, + "gpio_142", "hsusb3_tll_data6", NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP3_DR, 141, + "mcbsp3_dr", "uart2_rts", NULL, NULL, + "gpio_141", "hsusb3_tll_data5", NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP3_DX, 140, + "mcbsp3_dx", "uart2_cts", NULL, NULL, + "gpio_140", "hsusb3_tll_data4", NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP3_FSX, 143, + "mcbsp3_fsx", "uart2_rx", NULL, NULL, + "gpio_143", "hsusb3_tll_data7", NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP4_CLKX, 152, + "mcbsp4_clkx", NULL, NULL, NULL, + "gpio_152", "hsusb3_tll_data1", "mm3_txse0", "safe_mode"), + _OMAP3_MUXENTRY(MCBSP4_DR, 153, + "mcbsp4_dr", NULL, NULL, NULL, + "gpio_153", "hsusb3_tll_data0", "mm3_rxrcv", "safe_mode"), + _OMAP3_MUXENTRY(MCBSP4_DX, 154, + "mcbsp4_dx", NULL, NULL, NULL, + "gpio_154", "hsusb3_tll_data2", "mm3_txdat", "safe_mode"), + _OMAP3_MUXENTRY(MCBSP4_FSX, 155, + "mcbsp4_fsx", NULL, NULL, NULL, + "gpio_155", "hsusb3_tll_data3", "mm3_txen_n", "safe_mode"), + _OMAP3_MUXENTRY(MCBSP_CLKS, 160, + "mcbsp_clks", NULL, "cam_shutter", NULL, + "gpio_160", "uart1_cts", NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCSPI1_CLK, 171, + "mcspi1_clk", "sdmmc2_dat4", NULL, NULL, + "gpio_171", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCSPI1_CS0, 174, + "mcspi1_cs0", "sdmmc2_dat7", NULL, NULL, + "gpio_174", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCSPI1_CS1, 175, + "mcspi1_cs1", NULL, NULL, "sdmmc3_cmd", + "gpio_175", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCSPI1_CS2, 176, + "mcspi1_cs2", NULL, NULL, "sdmmc3_clk", + "gpio_176", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCSPI1_CS3, 177, + "mcspi1_cs3", NULL, "hsusb2_tll_data2", "hsusb2_data2", + "gpio_177", "mm2_txdat", NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCSPI1_SIMO, 172, + "mcspi1_simo", "sdmmc2_dat5", NULL, NULL, + "gpio_172", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCSPI1_SOMI, 173, + "mcspi1_somi", "sdmmc2_dat6", NULL, NULL, + "gpio_173", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCSPI2_CLK, 178, + "mcspi2_clk", NULL, "hsusb2_tll_data7", "hsusb2_data7", + "gpio_178", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCSPI2_CS0, 181, + "mcspi2_cs0", "gpt11_pwm_evt", + "hsusb2_tll_data6", "hsusb2_data6", + "gpio_181", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCSPI2_CS1, 182, + "mcspi2_cs1", "gpt8_pwm_evt", + "hsusb2_tll_data3", "hsusb2_data3", + "gpio_182", "mm2_txen_n", NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCSPI2_SIMO, 179, + "mcspi2_simo", "gpt9_pwm_evt", + "hsusb2_tll_data4", "hsusb2_data4", + "gpio_179", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCSPI2_SOMI, 180, + "mcspi2_somi", "gpt10_pwm_evt", + "hsusb2_tll_data5", "hsusb2_data5", + "gpio_180", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_CLK, 120, + "sdmmc1_clk", NULL, NULL, NULL, + "gpio_120", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_CMD, 121, + "sdmmc1_cmd", NULL, NULL, NULL, + "gpio_121", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_DAT0, 122, + "sdmmc1_dat0", NULL, NULL, NULL, + "gpio_122", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_DAT1, 123, + "sdmmc1_dat1", NULL, NULL, NULL, + "gpio_123", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_DAT2, 124, + "sdmmc1_dat2", NULL, NULL, NULL, + "gpio_124", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_DAT3, 125, + "sdmmc1_dat3", NULL, NULL, NULL, + "gpio_125", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_DAT4, 126, + "sdmmc1_dat4", NULL, "sim_io", NULL, + "gpio_126", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_DAT5, 127, + "sdmmc1_dat5", NULL, "sim_clk", NULL, + "gpio_127", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_DAT6, 128, + "sdmmc1_dat6", NULL, "sim_pwrctrl", NULL, + "gpio_128", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_DAT7, 129, + "sdmmc1_dat7", NULL, "sim_rst", NULL, + "gpio_129", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC2_CLK, 130, + "sdmmc2_clk", "mcspi3_clk", NULL, NULL, + "gpio_130", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC2_CMD, 131, + "sdmmc2_cmd", "mcspi3_simo", NULL, NULL, + "gpio_131", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC2_DAT0, 132, + "sdmmc2_dat0", "mcspi3_somi", NULL, NULL, + "gpio_132", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC2_DAT1, 133, + "sdmmc2_dat1", NULL, NULL, NULL, + "gpio_133", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC2_DAT2, 134, + "sdmmc2_dat2", "mcspi3_cs1", NULL, NULL, + "gpio_134", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC2_DAT3, 135, + "sdmmc2_dat3", "mcspi3_cs0", NULL, NULL, + "gpio_135", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC2_DAT4, 136, + "sdmmc2_dat4", "sdmmc2_dir_dat0", NULL, "sdmmc3_dat0", + "gpio_136", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC2_DAT5, 137, + "sdmmc2_dat5", "sdmmc2_dir_dat1", + "cam_global_reset", "sdmmc3_dat1", + "gpio_137", "hsusb3_tll_stp", "mm3_rxdp", "safe_mode"), + _OMAP3_MUXENTRY(SDMMC2_DAT6, 138, + "sdmmc2_dat6", "sdmmc2_dir_cmd", "cam_shutter", "sdmmc3_dat2", + "gpio_138", "hsusb3_tll_dir", NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC2_DAT7, 139, + "sdmmc2_dat7", "sdmmc2_clkin", NULL, "sdmmc3_dat3", + "gpio_139", "hsusb3_tll_nxt", "mm3_rxdm", "safe_mode"), + _OMAP3_MUXENTRY(SDRC_CKE0, 0, + "sdrc_cke0", NULL, NULL, NULL, + NULL, NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDRC_CKE1, 0, + "sdrc_cke1", NULL, NULL, NULL, + NULL, NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_BOOT0, 2, + "sys_boot0", NULL, NULL, NULL, + "gpio_2", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_BOOT1, 3, + "sys_boot1", NULL, NULL, NULL, + "gpio_3", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_BOOT2, 4, + "sys_boot2", NULL, NULL, NULL, + "gpio_4", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_BOOT3, 5, + "sys_boot3", NULL, NULL, NULL, + "gpio_5", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_BOOT4, 6, + "sys_boot4", "sdmmc2_dir_dat2", NULL, NULL, + "gpio_6", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_BOOT5, 7, + "sys_boot5", "sdmmc2_dir_dat3", NULL, NULL, + "gpio_7", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_BOOT6, 8, + "sys_boot6", NULL, NULL, NULL, + "gpio_8", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_CLKOUT1, 10, + "sys_clkout1", NULL, NULL, NULL, + "gpio_10", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_CLKOUT2, 186, + "sys_clkout2", NULL, NULL, NULL, + "gpio_186", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_CLKREQ, 1, + "sys_clkreq", NULL, NULL, NULL, + "gpio_1", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_NIRQ, 0, + "sys_nirq", NULL, NULL, NULL, + "gpio_0", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_NRESWARM, 30, + "sys_nreswarm", NULL, NULL, NULL, + "gpio_30", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_OFF_MODE, 9, + "sys_off_mode", NULL, NULL, NULL, + "gpio_9", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART1_CTS, 150, + "uart1_cts", NULL, NULL, NULL, + "gpio_150", "hsusb3_tll_clk", NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART1_RTS, 149, + "uart1_rts", NULL, NULL, NULL, + "gpio_149", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART1_RX, 151, + "uart1_rx", NULL, "mcbsp1_clkr", "mcspi4_clk", + "gpio_151", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART1_TX, 148, + "uart1_tx", NULL, NULL, NULL, + "gpio_148", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART2_CTS, 144, + "uart2_cts", "mcbsp3_dx", "gpt9_pwm_evt", NULL, + "gpio_144", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART2_RTS, 145, + "uart2_rts", "mcbsp3_dr", "gpt10_pwm_evt", NULL, + "gpio_145", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART2_RX, 147, + "uart2_rx", "mcbsp3_fsx", "gpt8_pwm_evt", NULL, + "gpio_147", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART2_TX, 146, + "uart2_tx", "mcbsp3_clkx", "gpt11_pwm_evt", NULL, + "gpio_146", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART3_CTS_RCTX, 163, + "uart3_cts_rctx", NULL, NULL, NULL, + "gpio_163", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART3_RTS_SD, 164, + "uart3_rts_sd", NULL, NULL, NULL, + "gpio_164", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART3_RX_IRRX, 165, + "uart3_rx_irrx", NULL, NULL, NULL, + "gpio_165", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART3_TX_IRTX, 166, + "uart3_tx_irtx", NULL, NULL, NULL, + "gpio_166", NULL, NULL, "safe_mode"), + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; + +/* + * Signals different on CBC package compared to the superset + */ +#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBC) +struct omap_mux __initdata omap3_cbc_subset[] = { + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define omap3_cbc_subset NULL +#endif + +/* + * Balls for CBC package + * 515-pin s-PBGA Package, 0.65mm Ball Pitch (Top), 0.50mm Ball Pitch (Bottom) + * + * FIXME: What's up with the outdated TI documentation? See: + * + * http://wiki.davincidsp.com/index.php/Datasheet_Errata_for_OMAP35x_CBC_Package + * http://community.ti.com/forums/t/10982.aspx + */ +#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS) \ + && defined(CONFIG_OMAP_PACKAGE_CBC) +struct omap_ball __initdata omap3_cbc_ball[] = { + _OMAP3_BALLENTRY(CAM_D0, "ae16", NULL), + _OMAP3_BALLENTRY(CAM_D1, "ae15", NULL), + _OMAP3_BALLENTRY(CAM_D10, "d25", NULL), + _OMAP3_BALLENTRY(CAM_D11, "e26", NULL), + _OMAP3_BALLENTRY(CAM_D2, "a24", NULL), + _OMAP3_BALLENTRY(CAM_D3, "b24", NULL), + _OMAP3_BALLENTRY(CAM_D4, "d24", NULL), + _OMAP3_BALLENTRY(CAM_D5, "c24", NULL), + _OMAP3_BALLENTRY(CAM_D6, "p25", NULL), + _OMAP3_BALLENTRY(CAM_D7, "p26", NULL), + _OMAP3_BALLENTRY(CAM_D8, "n25", NULL), + _OMAP3_BALLENTRY(CAM_D9, "n26", NULL), + _OMAP3_BALLENTRY(CAM_FLD, "b23", NULL), + _OMAP3_BALLENTRY(CAM_HS, "c23", NULL), + _OMAP3_BALLENTRY(CAM_PCLK, "c26", NULL), + _OMAP3_BALLENTRY(CAM_STROBE, "d26", NULL), + _OMAP3_BALLENTRY(CAM_VS, "d23", NULL), + _OMAP3_BALLENTRY(CAM_WEN, "a23", NULL), + _OMAP3_BALLENTRY(CAM_XCLKA, "c25", NULL), + _OMAP3_BALLENTRY(CAM_XCLKB, "e25", NULL), + _OMAP3_BALLENTRY(CSI2_DX0, "ad17", NULL), + _OMAP3_BALLENTRY(CSI2_DX1, "ae18", NULL), + _OMAP3_BALLENTRY(CSI2_DY0, "ad16", NULL), + _OMAP3_BALLENTRY(CSI2_DY1, "ae17", NULL), + _OMAP3_BALLENTRY(DSS_ACBIAS, "f26", NULL), + _OMAP3_BALLENTRY(DSS_DATA0, "ae21", NULL), + _OMAP3_BALLENTRY(DSS_DATA1, "ae22", NULL), + _OMAP3_BALLENTRY(DSS_DATA10, "ac26", NULL), + _OMAP3_BALLENTRY(DSS_DATA11, "ad26", NULL), + _OMAP3_BALLENTRY(DSS_DATA12, "aa25", NULL), + _OMAP3_BALLENTRY(DSS_DATA13, "y25", NULL), + _OMAP3_BALLENTRY(DSS_DATA14, "aa26", NULL), + _OMAP3_BALLENTRY(DSS_DATA15, "ab26", NULL), + _OMAP3_BALLENTRY(DSS_DATA16, "l25", NULL), + _OMAP3_BALLENTRY(DSS_DATA17, "l26", NULL), + _OMAP3_BALLENTRY(DSS_DATA18, "m24", NULL), + _OMAP3_BALLENTRY(DSS_DATA19, "m26", NULL), + _OMAP3_BALLENTRY(DSS_DATA2, "ae23", NULL), + _OMAP3_BALLENTRY(DSS_DATA20, "f25", NULL), + _OMAP3_BALLENTRY(DSS_DATA21, "n24", NULL), + _OMAP3_BALLENTRY(DSS_DATA22, "ac25", NULL), + _OMAP3_BALLENTRY(DSS_DATA23, "ab25", NULL), + _OMAP3_BALLENTRY(DSS_DATA3, "ae24", NULL), + _OMAP3_BALLENTRY(DSS_DATA4, "ad23", NULL), + _OMAP3_BALLENTRY(DSS_DATA5, "ad24", NULL), + _OMAP3_BALLENTRY(DSS_DATA6, "g26", NULL), + _OMAP3_BALLENTRY(DSS_DATA7, "h25", NULL), + _OMAP3_BALLENTRY(DSS_DATA8, "h26", NULL), + _OMAP3_BALLENTRY(DSS_DATA9, "j26", NULL), + _OMAP3_BALLENTRY(DSS_HSYNC, "k24", NULL), + _OMAP3_BALLENTRY(DSS_PCLK, "g25", NULL), + _OMAP3_BALLENTRY(DSS_VSYNC, "m25", NULL), + _OMAP3_BALLENTRY(ETK_CLK, "ab2", NULL), + _OMAP3_BALLENTRY(ETK_CTL, "ab3", NULL), + _OMAP3_BALLENTRY(ETK_D0, "ac3", NULL), + _OMAP3_BALLENTRY(ETK_D1, "ad4", NULL), + _OMAP3_BALLENTRY(ETK_D10, "ae4", NULL), + _OMAP3_BALLENTRY(ETK_D11, "af6", NULL), + _OMAP3_BALLENTRY(ETK_D12, "ae6", NULL), + _OMAP3_BALLENTRY(ETK_D13, "af7", NULL), + _OMAP3_BALLENTRY(ETK_D14, "af9", NULL), + _OMAP3_BALLENTRY(ETK_D15, "ae9", NULL), + _OMAP3_BALLENTRY(ETK_D2, "ad3", NULL), + _OMAP3_BALLENTRY(ETK_D3, "aa3", NULL), + _OMAP3_BALLENTRY(ETK_D4, "y3", NULL), + _OMAP3_BALLENTRY(ETK_D5, "ab1", NULL), + _OMAP3_BALLENTRY(ETK_D6, "ae3", NULL), + _OMAP3_BALLENTRY(ETK_D7, "ad2", NULL), + _OMAP3_BALLENTRY(ETK_D8, "aa4", NULL), + _OMAP3_BALLENTRY(ETK_D9, "v2", NULL), + _OMAP3_BALLENTRY(GPMC_A1, "j2", NULL), + _OMAP3_BALLENTRY(GPMC_A10, "d2", NULL), + _OMAP3_BALLENTRY(GPMC_A2, "h1", NULL), + _OMAP3_BALLENTRY(GPMC_A3, "h2", NULL), + _OMAP3_BALLENTRY(GPMC_A4, "g2", NULL), + _OMAP3_BALLENTRY(GPMC_A5, "f1", NULL), + _OMAP3_BALLENTRY(GPMC_A6, "f2", NULL), + _OMAP3_BALLENTRY(GPMC_A7, "e1", NULL), + _OMAP3_BALLENTRY(GPMC_A8, "e2", NULL), + _OMAP3_BALLENTRY(GPMC_A9, "d1", NULL), + _OMAP3_BALLENTRY(GPMC_CLK, "n1", "l1"), + _OMAP3_BALLENTRY(GPMC_D10, "t1", "n1"), + _OMAP3_BALLENTRY(GPMC_D11, "u2", "p2"), + _OMAP3_BALLENTRY(GPMC_D12, "u1", "p1"), + _OMAP3_BALLENTRY(GPMC_D13, "p1", "m1"), + _OMAP3_BALLENTRY(GPMC_D14, "l2", "j2"), + _OMAP3_BALLENTRY(GPMC_D15, "m2", "k2"), + _OMAP3_BALLENTRY(GPMC_D8, "v1", "r1"), + _OMAP3_BALLENTRY(GPMC_D9, "y1", "t1"), + _OMAP3_BALLENTRY(GPMC_NBE0_CLE, "k2", NULL), + _OMAP3_BALLENTRY(GPMC_NBE1, "j1", NULL), + _OMAP3_BALLENTRY(GPMC_NCS1, "ad1", "w1"), + _OMAP3_BALLENTRY(GPMC_NCS2, "a3", NULL), + _OMAP3_BALLENTRY(GPMC_NCS3, "b6", NULL), + _OMAP3_BALLENTRY(GPMC_NCS4, "b4", NULL), + _OMAP3_BALLENTRY(GPMC_NCS5, "c4", NULL), + _OMAP3_BALLENTRY(GPMC_NCS6, "b5", NULL), + _OMAP3_BALLENTRY(GPMC_NCS7, "c5", NULL), + _OMAP3_BALLENTRY(GPMC_NWP, "ac6", "y5"), + _OMAP3_BALLENTRY(GPMC_WAIT1, "ac8", "y8"), + _OMAP3_BALLENTRY(GPMC_WAIT2, "b3", NULL), + _OMAP3_BALLENTRY(GPMC_WAIT3, "c6", NULL), + _OMAP3_BALLENTRY(HDQ_SIO, "j23", NULL), + _OMAP3_BALLENTRY(HSUSB0_CLK, "w19", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA0, "v20", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA1, "y20", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA2, "v18", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA3, "w20", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA4, "w17", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA5, "y18", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA6, "y19", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA7, "y17", NULL), + _OMAP3_BALLENTRY(HSUSB0_DIR, "v19", NULL), + _OMAP3_BALLENTRY(HSUSB0_NXT, "w18", NULL), + _OMAP3_BALLENTRY(HSUSB0_STP, "u20", NULL), + _OMAP3_BALLENTRY(I2C2_SCL, "c2", NULL), + _OMAP3_BALLENTRY(I2C2_SDA, "c1", NULL), + _OMAP3_BALLENTRY(I2C3_SCL, "ab4", NULL), + _OMAP3_BALLENTRY(I2C3_SDA, "ac4", NULL), + _OMAP3_BALLENTRY(I2C4_SCL, "ad15", NULL), + _OMAP3_BALLENTRY(I2C4_SDA, "w16", NULL), + _OMAP3_BALLENTRY(JTAG_EMU0, "y15", NULL), + _OMAP3_BALLENTRY(JTAG_EMU1, "y14", NULL), + _OMAP3_BALLENTRY(MCBSP1_CLKR, "u19", NULL), + _OMAP3_BALLENTRY(MCBSP1_CLKX, "t17", NULL), + _OMAP3_BALLENTRY(MCBSP1_DR, "t20", NULL), + _OMAP3_BALLENTRY(MCBSP1_DX, "u17", NULL), + _OMAP3_BALLENTRY(MCBSP1_FSR, "v17", NULL), + _OMAP3_BALLENTRY(MCBSP1_FSX, "p20", NULL), + _OMAP3_BALLENTRY(MCBSP2_CLKX, "r18", NULL), + _OMAP3_BALLENTRY(MCBSP2_DR, "t18", NULL), + _OMAP3_BALLENTRY(MCBSP2_DX, "r19", NULL), + _OMAP3_BALLENTRY(MCBSP2_FSX, "u18", NULL), + _OMAP3_BALLENTRY(MCBSP3_CLKX, "u3", NULL), + _OMAP3_BALLENTRY(MCBSP3_DR, "n3", NULL), + _OMAP3_BALLENTRY(MCBSP3_DX, "p3", NULL), + _OMAP3_BALLENTRY(MCBSP3_FSX, "w3", NULL), + _OMAP3_BALLENTRY(MCBSP4_CLKX, "v3", NULL), + _OMAP3_BALLENTRY(MCBSP4_DR, "u4", NULL), + _OMAP3_BALLENTRY(MCBSP4_DX, "r3", NULL), + _OMAP3_BALLENTRY(MCBSP4_FSX, "t3", NULL), + _OMAP3_BALLENTRY(MCBSP_CLKS, "t19", NULL), + _OMAP3_BALLENTRY(MCSPI1_CLK, "p9", NULL), + _OMAP3_BALLENTRY(MCSPI1_CS0, "r7", NULL), + _OMAP3_BALLENTRY(MCSPI1_CS1, "r8", NULL), + _OMAP3_BALLENTRY(MCSPI1_CS2, "r9", NULL), + _OMAP3_BALLENTRY(MCSPI1_CS3, "t8", NULL), + _OMAP3_BALLENTRY(MCSPI1_SIMO, "p8", NULL), + _OMAP3_BALLENTRY(MCSPI1_SOMI, "p7", NULL), + _OMAP3_BALLENTRY(MCSPI2_CLK, "w7", NULL), + _OMAP3_BALLENTRY(MCSPI2_CS0, "v8", NULL), + _OMAP3_BALLENTRY(MCSPI2_CS1, "v9", NULL), + _OMAP3_BALLENTRY(MCSPI2_SIMO, "w8", NULL), + _OMAP3_BALLENTRY(MCSPI2_SOMI, "u8", NULL), + _OMAP3_BALLENTRY(SDMMC1_CLK, "n19", NULL), + _OMAP3_BALLENTRY(SDMMC1_CMD, "l18", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT0, "m19", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT1, "m18", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT2, "k18", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT3, "n20", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT4, "m20", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT5, "p17", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT6, "p18", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT7, "p19", NULL), + _OMAP3_BALLENTRY(SDMMC2_CLK, "w10", NULL), + _OMAP3_BALLENTRY(SDMMC2_CMD, "r10", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT0, "t10", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT1, "t9", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT2, "u10", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT3, "u9", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT4, "v10", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT5, "m3", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT6, "l3", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT7, "k3", NULL), + _OMAP3_BALLENTRY(SYS_BOOT0, "f3", NULL), + _OMAP3_BALLENTRY(SYS_BOOT1, "d3", NULL), + _OMAP3_BALLENTRY(SYS_BOOT2, "c3", NULL), + _OMAP3_BALLENTRY(SYS_BOOT3, "e3", NULL), + _OMAP3_BALLENTRY(SYS_BOOT4, "e4", NULL), + _OMAP3_BALLENTRY(SYS_BOOT5, "g3", NULL), + _OMAP3_BALLENTRY(SYS_BOOT6, "d4", NULL), + _OMAP3_BALLENTRY(SYS_CLKOUT1, "ae14", NULL), + _OMAP3_BALLENTRY(SYS_CLKOUT2, "w11", NULL), + _OMAP3_BALLENTRY(SYS_CLKREQ, "w15", NULL), + _OMAP3_BALLENTRY(SYS_NIRQ, "v16", NULL), + _OMAP3_BALLENTRY(SYS_NRESWARM, "ad7", "aa5"), + _OMAP3_BALLENTRY(SYS_OFF_MODE, "v12", NULL), + _OMAP3_BALLENTRY(UART1_CTS, "w2", NULL), + _OMAP3_BALLENTRY(UART1_RTS, "r2", NULL), + _OMAP3_BALLENTRY(UART1_RX, "h3", NULL), + _OMAP3_BALLENTRY(UART1_TX, "l4", NULL), + _OMAP3_BALLENTRY(UART2_CTS, "y24", NULL), + _OMAP3_BALLENTRY(UART2_RTS, "aa24", NULL), + _OMAP3_BALLENTRY(UART2_RX, "ad21", NULL), + _OMAP3_BALLENTRY(UART2_TX, "ad22", NULL), + _OMAP3_BALLENTRY(UART3_CTS_RCTX, "f23", NULL), + _OMAP3_BALLENTRY(UART3_RTS_SD, "f24", NULL), + _OMAP3_BALLENTRY(UART3_RX_IRRX, "h24", NULL), + _OMAP3_BALLENTRY(UART3_TX_IRTX, "g24", NULL), + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define omap3_cbc_ball NULL +#endif + +/* + * Signals different on CUS package compared to superset + */ +#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CUS) +struct omap_mux __initdata omap3_cus_subset[] = { + _OMAP3_MUXENTRY(CAM_D10, 109, + "cam_d10", NULL, NULL, NULL, + "gpio_109", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D11, 110, + "cam_d11", NULL, NULL, NULL, + "gpio_110", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D2, 101, + "cam_d2", NULL, NULL, NULL, + "gpio_101", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D3, 102, + "cam_d3", NULL, NULL, NULL, + "gpio_102", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D4, 103, + "cam_d4", NULL, NULL, NULL, + "gpio_103", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D5, 104, + "cam_d5", NULL, NULL, NULL, + "gpio_104", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_FLD, 98, + "cam_fld", NULL, "cam_global_reset", NULL, + "gpio_98", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_HS, 94, + "cam_hs", NULL, NULL, NULL, + "gpio_94", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_PCLK, 97, + "cam_pclk", NULL, NULL, NULL, + "gpio_97", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_STROBE, 126, + "cam_strobe", NULL, NULL, NULL, + "gpio_126", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_VS, 95, + "cam_vs", NULL, NULL, NULL, + "gpio_95", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_WEN, 167, + "cam_wen", NULL, "cam_shutter", NULL, + "gpio_167", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA6, 76, + "dss_data6", NULL, "uart1_tx", NULL, + "gpio_76", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA7, 77, + "dss_data7", NULL, "uart1_rx", NULL, + "gpio_77", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA8, 78, + "dss_data8", NULL, NULL, NULL, + "gpio_78", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA9, 79, + "dss_data9", NULL, NULL, NULL, + "gpio_79", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_HSYNC, 67, + "dss_hsync", NULL, NULL, NULL, + "gpio_67", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_PCLK, 66, + "dss_pclk", NULL, NULL, NULL, + "gpio_66", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(ETK_CLK, 12, + "etk_clk", "mcbsp5_clkx", "sdmmc3_clk", "hsusb1_stp", + "gpio_12", "mm1_rxdp", "hsusb1_tll_stp", NULL), + _OMAP3_MUXENTRY(ETK_CTL, 13, + "etk_ctl", NULL, "sdmmc3_cmd", "hsusb1_clk", + "gpio_13", NULL, "hsusb1_tll_clk", NULL), + _OMAP3_MUXENTRY(ETK_D0, 14, + "etk_d0", "mcspi3_simo", "sdmmc3_dat4", "hsusb1_data0", + "gpio_14", "mm1_rxrcv", "hsusb1_tll_data0", NULL), + _OMAP3_MUXENTRY(ETK_D1, 15, + "etk_d1", "mcspi3_somi", NULL, "hsusb1_data1", + "gpio_15", "mm1_txse0", "hsusb1_tll_data1", NULL), + _OMAP3_MUXENTRY(ETK_D10, 24, + "etk_d10", NULL, "uart1_rx", "hsusb2_clk", + "gpio_24", NULL, "hsusb2_tll_clk", NULL), + _OMAP3_MUXENTRY(ETK_D11, 25, + "etk_d11", NULL, NULL, "hsusb2_stp", + "gpio_25", "mm2_rxdp", "hsusb2_tll_stp", NULL), + _OMAP3_MUXENTRY(ETK_D12, 26, + "etk_d12", NULL, NULL, "hsusb2_dir", + "gpio_26", NULL, "hsusb2_tll_dir", NULL), + _OMAP3_MUXENTRY(ETK_D13, 27, + "etk_d13", NULL, NULL, "hsusb2_nxt", + "gpio_27", "mm2_rxdm", "hsusb2_tll_nxt", NULL), + _OMAP3_MUXENTRY(ETK_D14, 28, + "etk_d14", NULL, NULL, "hsusb2_data0", + "gpio_28", "mm2_rxrcv", "hsusb2_tll_data0", NULL), + _OMAP3_MUXENTRY(ETK_D15, 29, + "etk_d15", NULL, NULL, "hsusb2_data1", + "gpio_29", "mm2_txse0", "hsusb2_tll_data1", NULL), + _OMAP3_MUXENTRY(ETK_D2, 16, + "etk_d2", "mcspi3_cs0", NULL, "hsusb1_data2", + "gpio_16", "mm1_txdat", "hsusb1_tll_data2", NULL), + _OMAP3_MUXENTRY(ETK_D3, 17, + "etk_d3", "mcspi3_clk", "sdmmc3_dat3", "hsusb1_data7", + "gpio_17", NULL, "hsusb1_tll_data7", NULL), + _OMAP3_MUXENTRY(ETK_D4, 18, + "etk_d4", "mcbsp5_dr", "sdmmc3_dat0", "hsusb1_data4", + "gpio_18", NULL, "hsusb1_tll_data4", NULL), + _OMAP3_MUXENTRY(ETK_D5, 19, + "etk_d5", "mcbsp5_fsx", "sdmmc3_dat1", "hsusb1_data5", + "gpio_19", NULL, "hsusb1_tll_data5", NULL), + _OMAP3_MUXENTRY(ETK_D6, 20, + "etk_d6", "mcbsp5_dx", "sdmmc3_dat2", "hsusb1_data6", + "gpio_20", NULL, "hsusb1_tll_data6", NULL), + _OMAP3_MUXENTRY(ETK_D7, 21, + "etk_d7", "mcspi3_cs1", "sdmmc3_dat7", "hsusb1_data3", + "gpio_21", "mm1_txen_n", "hsusb1_tll_data3", NULL), + _OMAP3_MUXENTRY(ETK_D8, 22, + "etk_d8", "sys_drm_msecure", "sdmmc3_dat6", "hsusb1_dir", + "gpio_22", NULL, "hsusb1_tll_dir", NULL), + _OMAP3_MUXENTRY(ETK_D9, 23, + "etk_d9", "sys_secure_indicator", "sdmmc3_dat5", "hsusb1_nxt", + "gpio_23", "mm1_rxdm", "hsusb1_tll_nxt", NULL), + _OMAP3_MUXENTRY(MCBSP3_CLKX, 142, + "mcbsp3_clkx", "uart2_tx", NULL, NULL, + "gpio_142", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP3_DR, 141, + "mcbsp3_dr", "uart2_rts", NULL, NULL, + "gpio_141", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP3_DX, 140, + "mcbsp3_dx", "uart2_cts", NULL, NULL, + "gpio_140", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP3_FSX, 143, + "mcbsp3_fsx", "uart2_rx", NULL, NULL, + "gpio_143", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC2_DAT5, 137, + "sdmmc2_dat5", "sdmmc2_dir_dat1", + "cam_global_reset", "sdmmc3_dat1", + "gpio_137", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC2_DAT6, 138, + "sdmmc2_dat6", "sdmmc2_dir_cmd", "cam_shutter", "sdmmc3_dat2", + "gpio_138", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC2_DAT7, 139, + "sdmmc2_dat7", "sdmmc2_clkin", NULL, "sdmmc3_dat3", + "gpio_139", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART1_CTS, 150, + "uart1_cts", NULL, NULL, NULL, + "gpio_150", NULL, NULL, "safe_mode"), + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define omap3_cus_subset NULL +#endif + +/* + * Balls for CUS package + * 423-pin s-PBGA Package, 0.65mm Ball Pitch (Bottom) + */ +#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS) \ + && defined(CONFIG_OMAP_PACKAGE_CUS) +struct omap_ball __initdata omap3_cus_ball[] = { + _OMAP3_BALLENTRY(CAM_D0, "ab18", NULL), + _OMAP3_BALLENTRY(CAM_D1, "ac18", NULL), + _OMAP3_BALLENTRY(CAM_D10, "f21", NULL), + _OMAP3_BALLENTRY(CAM_D11, "g21", NULL), + _OMAP3_BALLENTRY(CAM_D2, "g19", NULL), + _OMAP3_BALLENTRY(CAM_D3, "f19", NULL), + _OMAP3_BALLENTRY(CAM_D4, "g20", NULL), + _OMAP3_BALLENTRY(CAM_D5, "b21", NULL), + _OMAP3_BALLENTRY(CAM_D6, "l24", NULL), + _OMAP3_BALLENTRY(CAM_D7, "k24", NULL), + _OMAP3_BALLENTRY(CAM_D8, "j23", NULL), + _OMAP3_BALLENTRY(CAM_D9, "k23", NULL), + _OMAP3_BALLENTRY(CAM_FLD, "h24", NULL), + _OMAP3_BALLENTRY(CAM_HS, "a22", NULL), + _OMAP3_BALLENTRY(CAM_PCLK, "j19", NULL), + _OMAP3_BALLENTRY(CAM_STROBE, "j20", NULL), + _OMAP3_BALLENTRY(CAM_VS, "e18", NULL), + _OMAP3_BALLENTRY(CAM_WEN, "f18", NULL), + _OMAP3_BALLENTRY(CAM_XCLKA, "b22", NULL), + _OMAP3_BALLENTRY(CAM_XCLKB, "c22", NULL), + _OMAP3_BALLENTRY(DSS_ACBIAS, "j21", NULL), + _OMAP3_BALLENTRY(DSS_DATA0, "ac19", NULL), + _OMAP3_BALLENTRY(DSS_DATA1, "ab19", NULL), + _OMAP3_BALLENTRY(DSS_DATA10, "ac22", NULL), + _OMAP3_BALLENTRY(DSS_DATA11, "ac23", NULL), + _OMAP3_BALLENTRY(DSS_DATA12, "ab22", NULL), + _OMAP3_BALLENTRY(DSS_DATA13, "y22", NULL), + _OMAP3_BALLENTRY(DSS_DATA14, "w22", NULL), + _OMAP3_BALLENTRY(DSS_DATA15, "v22", NULL), + _OMAP3_BALLENTRY(DSS_DATA16, "j22", NULL), + _OMAP3_BALLENTRY(DSS_DATA17, "g23", NULL), + _OMAP3_BALLENTRY(DSS_DATA18, "g24", NULL), + _OMAP3_BALLENTRY(DSS_DATA19, "h23", NULL), + _OMAP3_BALLENTRY(DSS_DATA2, "ad20", NULL), + _OMAP3_BALLENTRY(DSS_DATA20, "d23", NULL), + _OMAP3_BALLENTRY(DSS_DATA21, "k22", NULL), + _OMAP3_BALLENTRY(DSS_DATA22, "v21", NULL), + _OMAP3_BALLENTRY(DSS_DATA23, "w21", NULL), + _OMAP3_BALLENTRY(DSS_DATA3, "ac20", NULL), + _OMAP3_BALLENTRY(DSS_DATA4, "ad21", NULL), + _OMAP3_BALLENTRY(DSS_DATA5, "ac21", NULL), + _OMAP3_BALLENTRY(DSS_DATA6, "d24", NULL), + _OMAP3_BALLENTRY(DSS_DATA7, "e23", NULL), + _OMAP3_BALLENTRY(DSS_DATA8, "e24", NULL), + _OMAP3_BALLENTRY(DSS_DATA9, "f23", NULL), + _OMAP3_BALLENTRY(DSS_HSYNC, "e22", NULL), + _OMAP3_BALLENTRY(DSS_PCLK, "g22", NULL), + _OMAP3_BALLENTRY(DSS_VSYNC, "f22", NULL), + _OMAP3_BALLENTRY(ETK_CLK, "ac1", NULL), + _OMAP3_BALLENTRY(ETK_CTL, "ad3", NULL), + _OMAP3_BALLENTRY(ETK_D0, "ad6", NULL), + _OMAP3_BALLENTRY(ETK_D1, "ac6", NULL), + _OMAP3_BALLENTRY(ETK_D10, "ac3", NULL), + _OMAP3_BALLENTRY(ETK_D11, "ac9", NULL), + _OMAP3_BALLENTRY(ETK_D12, "ac10", NULL), + _OMAP3_BALLENTRY(ETK_D13, "ad11", NULL), + _OMAP3_BALLENTRY(ETK_D14, "ac11", NULL), + _OMAP3_BALLENTRY(ETK_D15, "ad12", NULL), + _OMAP3_BALLENTRY(ETK_D2, "ac7", NULL), + _OMAP3_BALLENTRY(ETK_D3, "ad8", NULL), + _OMAP3_BALLENTRY(ETK_D4, "ac5", NULL), + _OMAP3_BALLENTRY(ETK_D5, "ad2", NULL), + _OMAP3_BALLENTRY(ETK_D6, "ac8", NULL), + _OMAP3_BALLENTRY(ETK_D7, "ad9", NULL), + _OMAP3_BALLENTRY(ETK_D8, "ac4", NULL), + _OMAP3_BALLENTRY(ETK_D9, "ad5", NULL), + _OMAP3_BALLENTRY(GPMC_A1, "k4", NULL), + _OMAP3_BALLENTRY(GPMC_A10, "g2", NULL), + _OMAP3_BALLENTRY(GPMC_A2, "k3", NULL), + _OMAP3_BALLENTRY(GPMC_A3, "k2", NULL), + _OMAP3_BALLENTRY(GPMC_A4, "j4", NULL), + _OMAP3_BALLENTRY(GPMC_A5, "j3", NULL), + _OMAP3_BALLENTRY(GPMC_A6, "j2", NULL), + _OMAP3_BALLENTRY(GPMC_A7, "j1", NULL), + _OMAP3_BALLENTRY(GPMC_A8, "h1", NULL), + _OMAP3_BALLENTRY(GPMC_A9, "h2", NULL), + _OMAP3_BALLENTRY(GPMC_CLK, "w2", NULL), + _OMAP3_BALLENTRY(GPMC_D10, "u1", NULL), + _OMAP3_BALLENTRY(GPMC_D11, "r3", NULL), + _OMAP3_BALLENTRY(GPMC_D12, "t3", NULL), + _OMAP3_BALLENTRY(GPMC_D13, "u2", NULL), + _OMAP3_BALLENTRY(GPMC_D14, "v1", NULL), + _OMAP3_BALLENTRY(GPMC_D15, "v2", NULL), + _OMAP3_BALLENTRY(GPMC_D8, "r2", NULL), + _OMAP3_BALLENTRY(GPMC_D9, "t2", NULL), + _OMAP3_BALLENTRY(GPMC_NBE0_CLE, "k5", NULL), + _OMAP3_BALLENTRY(GPMC_NBE1, "l1", NULL), + _OMAP3_BALLENTRY(GPMC_NCS3, "d2", NULL), + _OMAP3_BALLENTRY(GPMC_NCS4, "f4", NULL), + _OMAP3_BALLENTRY(GPMC_NCS5, "g5", NULL), + _OMAP3_BALLENTRY(GPMC_NCS6, "f3", NULL), + _OMAP3_BALLENTRY(GPMC_NCS7, "g4", NULL), + _OMAP3_BALLENTRY(GPMC_NWP, "e1", NULL), + _OMAP3_BALLENTRY(GPMC_WAIT3, "c2", NULL), + _OMAP3_BALLENTRY(HDQ_SIO, "a24", NULL), + _OMAP3_BALLENTRY(HSUSB0_CLK, "r21", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA0, "t24", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA1, "t23", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA2, "u24", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA3, "u23", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA4, "w24", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA5, "v23", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA6, "w23", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA7, "t22", NULL), + _OMAP3_BALLENTRY(HSUSB0_DIR, "p23", NULL), + _OMAP3_BALLENTRY(HSUSB0_NXT, "r22", NULL), + _OMAP3_BALLENTRY(HSUSB0_STP, "r23", NULL), + _OMAP3_BALLENTRY(I2C2_SCL, "ac15", NULL), + _OMAP3_BALLENTRY(I2C2_SDA, "ac14", NULL), + _OMAP3_BALLENTRY(I2C3_SCL, "ac13", NULL), + _OMAP3_BALLENTRY(I2C3_SDA, "ac12", NULL), + _OMAP3_BALLENTRY(I2C4_SCL, "y16", NULL), + _OMAP3_BALLENTRY(I2C4_SDA, "y15", NULL), + _OMAP3_BALLENTRY(JTAG_EMU0, "ac24", NULL), + _OMAP3_BALLENTRY(JTAG_EMU1, "ad24", NULL), + _OMAP3_BALLENTRY(MCBSP1_CLKR, "w19", NULL), + _OMAP3_BALLENTRY(MCBSP1_CLKX, "v18", NULL), + _OMAP3_BALLENTRY(MCBSP1_DR, "y18", NULL), + _OMAP3_BALLENTRY(MCBSP1_DX, "w18", NULL), + _OMAP3_BALLENTRY(MCBSP1_FSR, "ab20", NULL), + _OMAP3_BALLENTRY(MCBSP1_FSX, "aa19", NULL), + _OMAP3_BALLENTRY(MCBSP2_CLKX, "t21", NULL), + _OMAP3_BALLENTRY(MCBSP2_DR, "v19", NULL), + _OMAP3_BALLENTRY(MCBSP2_DX, "r20", NULL), + _OMAP3_BALLENTRY(MCBSP2_FSX, "v20", NULL), + _OMAP3_BALLENTRY(MCBSP3_CLKX, "w4", NULL), + _OMAP3_BALLENTRY(MCBSP3_DR, "v5", NULL), + _OMAP3_BALLENTRY(MCBSP3_DX, "v6", NULL), + _OMAP3_BALLENTRY(MCBSP3_FSX, "v4", NULL), + _OMAP3_BALLENTRY(MCBSP_CLKS, "aa18", NULL), + _OMAP3_BALLENTRY(MCSPI1_CLK, "t5", NULL), + _OMAP3_BALLENTRY(MCSPI1_CS0, "t6", NULL), + _OMAP3_BALLENTRY(MCSPI1_CS3, "r5", NULL), + _OMAP3_BALLENTRY(MCSPI1_SIMO, "r4", NULL), + _OMAP3_BALLENTRY(MCSPI1_SOMI, "t4", NULL), + _OMAP3_BALLENTRY(MCSPI2_CLK, "n5", NULL), + _OMAP3_BALLENTRY(MCSPI2_CS0, "m5", NULL), + _OMAP3_BALLENTRY(MCSPI2_CS1, "m4", NULL), + _OMAP3_BALLENTRY(MCSPI2_SIMO, "n4", NULL), + _OMAP3_BALLENTRY(MCSPI2_SOMI, "n3", NULL), + _OMAP3_BALLENTRY(SDMMC1_CLK, "m23", NULL), + _OMAP3_BALLENTRY(SDMMC1_CMD, "l23", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT0, "m22", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT1, "m21", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT2, "m20", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT3, "n23", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT4, "n22", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT5, "n21", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT6, "n20", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT7, "p24", NULL), + _OMAP3_BALLENTRY(SDMMC2_CLK, "y1", NULL), + _OMAP3_BALLENTRY(SDMMC2_CMD, "ab5", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT0, "ab3", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT1, "y3", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT2, "w3", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT3, "v3", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT4, "ab2", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT5, "aa2", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT6, "y2", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT7, "aa1", NULL), + _OMAP3_BALLENTRY(SYS_BOOT0, "ab12", NULL), + _OMAP3_BALLENTRY(SYS_BOOT1, "ac16", NULL), + _OMAP3_BALLENTRY(SYS_BOOT2, "ad17", NULL), + _OMAP3_BALLENTRY(SYS_BOOT3, "ad18", NULL), + _OMAP3_BALLENTRY(SYS_BOOT4, "ac17", NULL), + _OMAP3_BALLENTRY(SYS_BOOT5, "ab16", NULL), + _OMAP3_BALLENTRY(SYS_BOOT6, "aa15", NULL), + _OMAP3_BALLENTRY(SYS_CLKOUT1, "y7", NULL), + _OMAP3_BALLENTRY(SYS_CLKOUT2, "aa6", NULL), + _OMAP3_BALLENTRY(SYS_CLKREQ, "y13", NULL), + _OMAP3_BALLENTRY(SYS_NIRQ, "w16", NULL), + _OMAP3_BALLENTRY(SYS_NRESWARM, "y10", NULL), + _OMAP3_BALLENTRY(SYS_OFF_MODE, "ad23", NULL), + _OMAP3_BALLENTRY(UART1_CTS, "ac2", NULL), + _OMAP3_BALLENTRY(UART1_RTS, "w6", NULL), + _OMAP3_BALLENTRY(UART1_RX, "v7", NULL), + _OMAP3_BALLENTRY(UART1_TX, "w7", NULL), + _OMAP3_BALLENTRY(UART3_CTS_RCTX, "a23", NULL), + _OMAP3_BALLENTRY(UART3_RTS_SD, "b23", NULL), + _OMAP3_BALLENTRY(UART3_RX_IRRX, "b24", NULL), + _OMAP3_BALLENTRY(UART3_TX_IRTX, "c23", NULL), + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define omap3_cus_ball NULL +#endif + +/* + * Signals different on CBB package comapared to superset + */ +#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBB) +struct omap_mux __initdata omap3_cbb_subset[] = { + _OMAP3_MUXENTRY(CAM_D10, 109, + "cam_d10", NULL, NULL, NULL, + "gpio_109", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D11, 110, + "cam_d11", NULL, NULL, NULL, + "gpio_110", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D2, 101, + "cam_d2", NULL, NULL, NULL, + "gpio_101", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D3, 102, + "cam_d3", NULL, NULL, NULL, + "gpio_102", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D4, 103, + "cam_d4", NULL, NULL, NULL, + "gpio_103", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D5, 104, + "cam_d5", NULL, NULL, NULL, + "gpio_104", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_FLD, 98, + "cam_fld", NULL, "cam_global_reset", NULL, + "gpio_98", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_HS, 94, + "cam_hs", NULL, NULL, NULL, + "gpio_94", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_PCLK, 97, + "cam_pclk", NULL, NULL, NULL, + "gpio_97", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_STROBE, 126, + "cam_strobe", NULL, NULL, NULL, + "gpio_126", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_VS, 95, + "cam_vs", NULL, NULL, NULL, + "gpio_95", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_WEN, 167, + "cam_wen", NULL, "cam_shutter", NULL, + "gpio_167", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA6, 76, + "dss_data6", NULL, "uart1_tx", NULL, + "gpio_76", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA7, 77, + "dss_data7", NULL, "uart1_rx", NULL, + "gpio_77", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA8, 78, + "dss_data8", NULL, NULL, NULL, + "gpio_78", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA9, 79, + "dss_data9", NULL, NULL, NULL, + "gpio_79", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_HSYNC, 67, + "dss_hsync", NULL, NULL, NULL, + "gpio_67", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_PCLK, 66, + "dss_pclk", NULL, NULL, NULL, + "gpio_66", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(ETK_CLK, 12, + "etk_clk", "mcbsp5_clkx", "sdmmc3_clk", "hsusb1_stp", + "gpio_12", "mm1_rxdp", "hsusb1_tll_stp", NULL), + _OMAP3_MUXENTRY(ETK_CTL, 13, + "etk_ctl", NULL, "sdmmc3_cmd", "hsusb1_clk", + "gpio_13", NULL, "hsusb1_tll_clk", NULL), + _OMAP3_MUXENTRY(ETK_D0, 14, + "etk_d0", "mcspi3_simo", "sdmmc3_dat4", "hsusb1_data0", + "gpio_14", "mm1_rxrcv", "hsusb1_tll_data0", NULL), + _OMAP3_MUXENTRY(ETK_D1, 15, + "etk_d1", "mcspi3_somi", NULL, "hsusb1_data1", + "gpio_15", "mm1_txse0", "hsusb1_tll_data1", NULL), + _OMAP3_MUXENTRY(ETK_D10, 24, + "etk_d10", NULL, "uart1_rx", "hsusb2_clk", + "gpio_24", NULL, "hsusb2_tll_clk", NULL), + _OMAP3_MUXENTRY(ETK_D11, 25, + "etk_d11", NULL, NULL, "hsusb2_stp", + "gpio_25", "mm2_rxdp", "hsusb2_tll_stp", NULL), + _OMAP3_MUXENTRY(ETK_D12, 26, + "etk_d12", NULL, NULL, "hsusb2_dir", + "gpio_26", NULL, "hsusb2_tll_dir", NULL), + _OMAP3_MUXENTRY(ETK_D13, 27, + "etk_d13", NULL, NULL, "hsusb2_nxt", + "gpio_27", "mm2_rxdm", "hsusb2_tll_nxt", NULL), + _OMAP3_MUXENTRY(ETK_D14, 28, + "etk_d14", NULL, NULL, "hsusb2_data0", + "gpio_28", "mm2_rxrcv", "hsusb2_tll_data0", NULL), + _OMAP3_MUXENTRY(ETK_D15, 29, + "etk_d15", NULL, NULL, "hsusb2_data1", + "gpio_29", "mm2_txse0", "hsusb2_tll_data1", NULL), + _OMAP3_MUXENTRY(ETK_D2, 16, + "etk_d2", "mcspi3_cs0", NULL, "hsusb1_data2", + "gpio_16", "mm1_txdat", "hsusb1_tll_data2", NULL), + _OMAP3_MUXENTRY(ETK_D3, 17, + "etk_d3", "mcspi3_clk", "sdmmc3_dat3", "hsusb1_data7", + "gpio_17", NULL, "hsusb1_tll_data7", NULL), + _OMAP3_MUXENTRY(ETK_D4, 18, + "etk_d4", "mcbsp5_dr", "sdmmc3_dat0", "hsusb1_data4", + "gpio_18", NULL, "hsusb1_tll_data4", NULL), + _OMAP3_MUXENTRY(ETK_D5, 19, + "etk_d5", "mcbsp5_fsx", "sdmmc3_dat1", "hsusb1_data5", + "gpio_19", NULL, "hsusb1_tll_data5", NULL), + _OMAP3_MUXENTRY(ETK_D6, 20, + "etk_d6", "mcbsp5_dx", "sdmmc3_dat2", "hsusb1_data6", + "gpio_20", NULL, "hsusb1_tll_data6", NULL), + _OMAP3_MUXENTRY(ETK_D7, 21, + "etk_d7", "mcspi3_cs1", "sdmmc3_dat7", "hsusb1_data3", + "gpio_21", "mm1_txen_n", "hsusb1_tll_data3", NULL), + _OMAP3_MUXENTRY(ETK_D8, 22, + "etk_d8", "sys_drm_msecure", "sdmmc3_dat6", "hsusb1_dir", + "gpio_22", NULL, "hsusb1_tll_dir", NULL), + _OMAP3_MUXENTRY(ETK_D9, 23, + "etk_d9", "sys_secure_indicator", "sdmmc3_dat5", "hsusb1_nxt", + "gpio_23", "mm1_rxdm", "hsusb1_tll_nxt", NULL), + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define omap3_cbb_subset NULL +#endif + +/* + * Balls for CBB package + * 515-pin s-PBGA Package, 0.50mm Ball Pitch (Top), 0.40mm Ball Pitch (Bottom) + */ +#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS) \ + && defined(CONFIG_OMAP_PACKAGE_CBB) +struct omap_ball __initdata omap3_cbb_ball[] = { + _OMAP3_BALLENTRY(CAM_D0, "ag17", NULL), + _OMAP3_BALLENTRY(CAM_D1, "ah17", NULL), + _OMAP3_BALLENTRY(CAM_D10, "b25", NULL), + _OMAP3_BALLENTRY(CAM_D11, "c26", NULL), + _OMAP3_BALLENTRY(CAM_D2, "b24", NULL), + _OMAP3_BALLENTRY(CAM_D3, "c24", NULL), + _OMAP3_BALLENTRY(CAM_D4, "d24", NULL), + _OMAP3_BALLENTRY(CAM_D5, "a25", NULL), + _OMAP3_BALLENTRY(CAM_D6, "k28", NULL), + _OMAP3_BALLENTRY(CAM_D7, "l28", NULL), + _OMAP3_BALLENTRY(CAM_D8, "k27", NULL), + _OMAP3_BALLENTRY(CAM_D9, "l27", NULL), + _OMAP3_BALLENTRY(CAM_FLD, "c23", NULL), + _OMAP3_BALLENTRY(CAM_HS, "a24", NULL), + _OMAP3_BALLENTRY(CAM_PCLK, "c27", NULL), + _OMAP3_BALLENTRY(CAM_STROBE, "d25", NULL), + _OMAP3_BALLENTRY(CAM_VS, "a23", NULL), + _OMAP3_BALLENTRY(CAM_WEN, "b23", NULL), + _OMAP3_BALLENTRY(CAM_XCLKA, "c25", NULL), + _OMAP3_BALLENTRY(CAM_XCLKB, "b26", NULL), + _OMAP3_BALLENTRY(CSI2_DX0, "ag19", NULL), + _OMAP3_BALLENTRY(CSI2_DX1, "ag18", NULL), + _OMAP3_BALLENTRY(CSI2_DY0, "ah19", NULL), + _OMAP3_BALLENTRY(CSI2_DY1, "ah18", NULL), + _OMAP3_BALLENTRY(DSS_ACBIAS, "e27", NULL), + _OMAP3_BALLENTRY(DSS_DATA0, "ag22", NULL), + _OMAP3_BALLENTRY(DSS_DATA1, "ah22", NULL), + _OMAP3_BALLENTRY(DSS_DATA10, "ad28", NULL), + _OMAP3_BALLENTRY(DSS_DATA11, "ad27", NULL), + _OMAP3_BALLENTRY(DSS_DATA12, "ab28", NULL), + _OMAP3_BALLENTRY(DSS_DATA13, "ab27", NULL), + _OMAP3_BALLENTRY(DSS_DATA14, "aa28", NULL), + _OMAP3_BALLENTRY(DSS_DATA15, "aa27", NULL), + _OMAP3_BALLENTRY(DSS_DATA16, "g25", NULL), + _OMAP3_BALLENTRY(DSS_DATA17, "h27", NULL), + _OMAP3_BALLENTRY(DSS_DATA18, "h26", NULL), + _OMAP3_BALLENTRY(DSS_DATA19, "h25", NULL), + _OMAP3_BALLENTRY(DSS_DATA2, "ag23", NULL), + _OMAP3_BALLENTRY(DSS_DATA20, "e28", NULL), + _OMAP3_BALLENTRY(DSS_DATA21, "j26", NULL), + _OMAP3_BALLENTRY(DSS_DATA22, "ac27", NULL), + _OMAP3_BALLENTRY(DSS_DATA23, "ac28", NULL), + _OMAP3_BALLENTRY(DSS_DATA3, "ah23", NULL), + _OMAP3_BALLENTRY(DSS_DATA4, "ag24", NULL), + _OMAP3_BALLENTRY(DSS_DATA5, "ah24", NULL), + _OMAP3_BALLENTRY(DSS_DATA6, "e26", NULL), + _OMAP3_BALLENTRY(DSS_DATA7, "f28", NULL), + _OMAP3_BALLENTRY(DSS_DATA8, "f27", NULL), + _OMAP3_BALLENTRY(DSS_DATA9, "g26", NULL), + _OMAP3_BALLENTRY(DSS_HSYNC, "d26", NULL), + _OMAP3_BALLENTRY(DSS_PCLK, "d28", NULL), + _OMAP3_BALLENTRY(DSS_VSYNC, "d27", NULL), + _OMAP3_BALLENTRY(ETK_CLK, "af10", NULL), + _OMAP3_BALLENTRY(ETK_CTL, "ae10", NULL), + _OMAP3_BALLENTRY(ETK_D0, "af11", NULL), + _OMAP3_BALLENTRY(ETK_D1, "ag12", NULL), + _OMAP3_BALLENTRY(ETK_D10, "ae7", NULL), + _OMAP3_BALLENTRY(ETK_D11, "af7", NULL), + _OMAP3_BALLENTRY(ETK_D12, "ag7", NULL), + _OMAP3_BALLENTRY(ETK_D13, "ah7", NULL), + _OMAP3_BALLENTRY(ETK_D14, "ag8", NULL), + _OMAP3_BALLENTRY(ETK_D15, "ah8", NULL), + _OMAP3_BALLENTRY(ETK_D2, "ah12", NULL), + _OMAP3_BALLENTRY(ETK_D3, "ae13", NULL), + _OMAP3_BALLENTRY(ETK_D4, "ae11", NULL), + _OMAP3_BALLENTRY(ETK_D5, "ah9", NULL), + _OMAP3_BALLENTRY(ETK_D6, "af13", NULL), + _OMAP3_BALLENTRY(ETK_D7, "ah14", NULL), + _OMAP3_BALLENTRY(ETK_D8, "af9", NULL), + _OMAP3_BALLENTRY(ETK_D9, "ag9", NULL), + _OMAP3_BALLENTRY(GPMC_A1, "n4", "ac15"), + _OMAP3_BALLENTRY(GPMC_A10, "k3", "ab19"), + _OMAP3_BALLENTRY(GPMC_A2, "m4", "ab15"), + _OMAP3_BALLENTRY(GPMC_A3, "l4", "ac16"), + _OMAP3_BALLENTRY(GPMC_A4, "k4", "ab16"), + _OMAP3_BALLENTRY(GPMC_A5, "t3", "ac17"), + _OMAP3_BALLENTRY(GPMC_A6, "r3", "ab17"), + _OMAP3_BALLENTRY(GPMC_A7, "n3", "ac18"), + _OMAP3_BALLENTRY(GPMC_A8, "m3", "ab18"), + _OMAP3_BALLENTRY(GPMC_A9, "l3", "ac19"), + _OMAP3_BALLENTRY(GPMC_CLK, "t4", "w2"), + _OMAP3_BALLENTRY(GPMC_D10, "p1", "ab4"), + _OMAP3_BALLENTRY(GPMC_D11, "r1", "ac4"), + _OMAP3_BALLENTRY(GPMC_D12, "r2", "ab6"), + _OMAP3_BALLENTRY(GPMC_D13, "t2", "ac6"), + _OMAP3_BALLENTRY(GPMC_D14, "w1", "ab7"), + _OMAP3_BALLENTRY(GPMC_D15, "y1", "ac7"), + _OMAP3_BALLENTRY(GPMC_D8, "h2", "ab3"), + _OMAP3_BALLENTRY(GPMC_D9, "k2", "ac3"), + _OMAP3_BALLENTRY(GPMC_NBE0_CLE, "g3", "ac12"), + _OMAP3_BALLENTRY(GPMC_NBE1, "u3", NULL), + _OMAP3_BALLENTRY(GPMC_NCS1, "h3", "y1"), + _OMAP3_BALLENTRY(GPMC_NCS2, "v8", NULL), + _OMAP3_BALLENTRY(GPMC_NCS3, "u8", NULL), + _OMAP3_BALLENTRY(GPMC_NCS4, "t8", NULL), + _OMAP3_BALLENTRY(GPMC_NCS5, "r8", NULL), + _OMAP3_BALLENTRY(GPMC_NCS6, "p8", NULL), + _OMAP3_BALLENTRY(GPMC_NCS7, "n8", NULL), + _OMAP3_BALLENTRY(GPMC_NWP, "h1", "ab10"), + _OMAP3_BALLENTRY(GPMC_WAIT1, "l8", "ac10"), + _OMAP3_BALLENTRY(GPMC_WAIT2, "k8", NULL), + _OMAP3_BALLENTRY(GPMC_WAIT3, "j8", NULL), + _OMAP3_BALLENTRY(HDQ_SIO, "j25", NULL), + _OMAP3_BALLENTRY(HSUSB0_CLK, "t28", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA0, "t27", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA1, "u28", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA2, "u27", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA3, "u26", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA4, "u25", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA5, "v28", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA6, "v27", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA7, "v26", NULL), + _OMAP3_BALLENTRY(HSUSB0_DIR, "r28", NULL), + _OMAP3_BALLENTRY(HSUSB0_NXT, "t26", NULL), + _OMAP3_BALLENTRY(HSUSB0_STP, "t25", NULL), + _OMAP3_BALLENTRY(I2C2_SCL, "af15", NULL), + _OMAP3_BALLENTRY(I2C2_SDA, "ae15", NULL), + _OMAP3_BALLENTRY(I2C3_SCL, "af14", NULL), + _OMAP3_BALLENTRY(I2C3_SDA, "ag14", NULL), + _OMAP3_BALLENTRY(I2C4_SCL, "ad26", NULL), + _OMAP3_BALLENTRY(I2C4_SDA, "ae26", NULL), + _OMAP3_BALLENTRY(JTAG_EMU0, "aa11", NULL), + _OMAP3_BALLENTRY(JTAG_EMU1, "aa10", NULL), + _OMAP3_BALLENTRY(MCBSP1_CLKR, "y21", NULL), + _OMAP3_BALLENTRY(MCBSP1_CLKX, "w21", NULL), + _OMAP3_BALLENTRY(MCBSP1_DR, "u21", NULL), + _OMAP3_BALLENTRY(MCBSP1_DX, "v21", NULL), + _OMAP3_BALLENTRY(MCBSP1_FSR, "aa21", NULL), + _OMAP3_BALLENTRY(MCBSP1_FSX, "k26", NULL), + _OMAP3_BALLENTRY(MCBSP2_CLKX, "n21", NULL), + _OMAP3_BALLENTRY(MCBSP2_DR, "r21", NULL), + _OMAP3_BALLENTRY(MCBSP2_DX, "m21", NULL), + _OMAP3_BALLENTRY(MCBSP2_FSX, "p21", NULL), + _OMAP3_BALLENTRY(MCBSP3_CLKX, "af5", NULL), + _OMAP3_BALLENTRY(MCBSP3_DR, "ae6", NULL), + _OMAP3_BALLENTRY(MCBSP3_DX, "af6", NULL), + _OMAP3_BALLENTRY(MCBSP3_FSX, "ae5", NULL), + _OMAP3_BALLENTRY(MCBSP4_CLKX, "ae1", NULL), + _OMAP3_BALLENTRY(MCBSP4_DR, "ad1", NULL), + _OMAP3_BALLENTRY(MCBSP4_DX, "ad2", NULL), + _OMAP3_BALLENTRY(MCBSP4_FSX, "ac1", NULL), + _OMAP3_BALLENTRY(MCBSP_CLKS, "t21", NULL), + _OMAP3_BALLENTRY(MCSPI1_CLK, "ab3", NULL), + _OMAP3_BALLENTRY(MCSPI1_CS0, "ac2", NULL), + _OMAP3_BALLENTRY(MCSPI1_CS1, "ac3", NULL), + _OMAP3_BALLENTRY(MCSPI1_CS2, "ab1", NULL), + _OMAP3_BALLENTRY(MCSPI1_CS3, "ab2", NULL), + _OMAP3_BALLENTRY(MCSPI1_SIMO, "ab4", NULL), + _OMAP3_BALLENTRY(MCSPI1_SOMI, "aa4", NULL), + _OMAP3_BALLENTRY(MCSPI2_CLK, "aa3", NULL), + _OMAP3_BALLENTRY(MCSPI2_CS0, "y4", NULL), + _OMAP3_BALLENTRY(MCSPI2_CS1, "v3", NULL), + _OMAP3_BALLENTRY(MCSPI2_SIMO, "y2", NULL), + _OMAP3_BALLENTRY(MCSPI2_SOMI, "y3", NULL), + _OMAP3_BALLENTRY(SDMMC1_CLK, "n28", NULL), + _OMAP3_BALLENTRY(SDMMC1_CMD, "m27", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT0, "n27", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT1, "n26", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT2, "n25", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT3, "p28", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT4, "p27", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT5, "p26", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT6, "r27", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT7, "r25", NULL), + _OMAP3_BALLENTRY(SDMMC2_CLK, "ae2", NULL), + _OMAP3_BALLENTRY(SDMMC2_CMD, "ag5", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT0, "ah5", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT1, "ah4", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT2, "ag4", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT3, "af4", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT4, "ae4", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT5, "ah3", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT6, "af3", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT7, "ae3", NULL), + _OMAP3_BALLENTRY(SYS_BOOT0, "ah26", NULL), + _OMAP3_BALLENTRY(SYS_BOOT1, "ag26", NULL), + _OMAP3_BALLENTRY(SYS_BOOT2, "ae14", NULL), + _OMAP3_BALLENTRY(SYS_BOOT3, "af18", NULL), + _OMAP3_BALLENTRY(SYS_BOOT4, "af19", NULL), + _OMAP3_BALLENTRY(SYS_BOOT5, "ae21", NULL), + _OMAP3_BALLENTRY(SYS_BOOT6, "af21", NULL), + _OMAP3_BALLENTRY(SYS_CLKOUT1, "ag25", NULL), + _OMAP3_BALLENTRY(SYS_CLKOUT2, "ae22", NULL), + _OMAP3_BALLENTRY(SYS_CLKREQ, "af25", NULL), + _OMAP3_BALLENTRY(SYS_NIRQ, "af26", NULL), + _OMAP3_BALLENTRY(SYS_NRESWARM, "af24", NULL), + _OMAP3_BALLENTRY(SYS_OFF_MODE, "af22", NULL), + _OMAP3_BALLENTRY(UART1_CTS, "w8", NULL), + _OMAP3_BALLENTRY(UART1_RTS, "aa9", NULL), + _OMAP3_BALLENTRY(UART1_RX, "y8", NULL), + _OMAP3_BALLENTRY(UART1_TX, "aa8", NULL), + _OMAP3_BALLENTRY(UART2_CTS, "ab26", NULL), + _OMAP3_BALLENTRY(UART2_RTS, "ab25", NULL), + _OMAP3_BALLENTRY(UART2_RX, "ad25", NULL), + _OMAP3_BALLENTRY(UART2_TX, "aa25", NULL), + _OMAP3_BALLENTRY(UART3_CTS_RCTX, "h18", NULL), + _OMAP3_BALLENTRY(UART3_RTS_SD, "h19", NULL), + _OMAP3_BALLENTRY(UART3_RX_IRRX, "h20", NULL), + _OMAP3_BALLENTRY(UART3_TX_IRTX, "h21", NULL), + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define omap3_cbb_ball NULL +#endif + +/* + * Signals different on 36XX CBP package comapared to 34XX CBC package + */ +#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBP) +struct omap_mux __initdata omap36xx_cbp_subset[] = { + _OMAP3_MUXENTRY(CAM_D0, 99, + "cam_d0", NULL, "csi2_dx2", NULL, + "gpio_99", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D1, 100, + "cam_d1", NULL, "csi2_dy2", NULL, + "gpio_100", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D10, 109, + "cam_d10", "ssi2_wake", NULL, NULL, + "gpio_109", "hw_dbg8", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D2, 101, + "cam_d2", "ssi2_rdy_tx", NULL, NULL, + "gpio_101", "hw_dbg4", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D3, 102, + "cam_d3", "ssi2_dat_rx", NULL, NULL, + "gpio_102", "hw_dbg5", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D4, 103, + "cam_d4", "ssi2_flag_rx", NULL, NULL, + "gpio_103", "hw_dbg6", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_D5, 104, + "cam_d5", "ssi2_rdy_rx", NULL, NULL, + "gpio_104", "hw_dbg7", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_HS, 94, + "cam_hs", "ssi2_dat_tx", NULL, NULL, + "gpio_94", "hw_dbg0", NULL, "safe_mode"), + _OMAP3_MUXENTRY(CAM_VS, 95, + "cam_vs", "ssi2_flag_tx", NULL, NULL, + "gpio_95", "hw_dbg1", NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA0, 70, + "dss_data0", "dsi_dx0", "uart1_cts", NULL, + "gpio_70", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA1, 71, + "dss_data1", "dsi_dy0", "uart1_rts", NULL, + "gpio_71", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA2, 72, + "dss_data2", "dsi_dx1", NULL, NULL, + "gpio_72", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA3, 73, + "dss_data3", "dsi_dy1", NULL, NULL, + "gpio_73", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA4, 74, + "dss_data4", "dsi_dx2", "uart3_rx_irrx", NULL, + "gpio_74", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA5, 75, + "dss_data5", "dsi_dy2", "uart3_tx_irtx", NULL, + "gpio_75", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA6, 76, + "dss_data6", NULL, "uart1_tx", "dssvenc656_data6", + "gpio_76", "hw_dbg14", NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA7, 77, + "dss_data7", NULL, "uart1_rx", "dssvenc656_data7", + "gpio_77", "hw_dbg15", NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA8, 78, + "dss_data8", NULL, "uart3_rx_irrx", NULL, + "gpio_78", "hw_dbg16", NULL, "safe_mode"), + _OMAP3_MUXENTRY(DSS_DATA9, 79, + "dss_data9", NULL, "uart3_tx_irtx", NULL, + "gpio_79", "hw_dbg17", NULL, "safe_mode"), + _OMAP3_MUXENTRY(ETK_D12, 26, + "etk_d12", "sys_drm_msecure", NULL, "hsusb2_dir", + "gpio_26", NULL, "hsusb2_tll_dir", "hw_dbg14"), + _OMAP3_MUXENTRY(GPMC_A11, 0, + "gpmc_a11", NULL, NULL, NULL, + NULL, NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_WAIT2, 64, + "gpmc_wait2", NULL, "uart4_tx", NULL, + "gpio_64", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(GPMC_WAIT3, 65, + "gpmc_wait3", "sys_ndmareq1", "uart4_rx", NULL, + "gpio_65", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_DATA0, 125, + "hsusb0_data0", NULL, "uart3_tx_irtx", NULL, + "gpio_125", "uart2_tx", NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_DATA1, 130, + "hsusb0_data1", NULL, "uart3_rx_irrx", NULL, + "gpio_130", "uart2_rx", NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_DATA2, 131, + "hsusb0_data2", NULL, "uart3_rts_sd", NULL, + "gpio_131", "uart2_rts", NULL, "safe_mode"), + _OMAP3_MUXENTRY(HSUSB0_DATA3, 169, + "hsusb0_data3", NULL, "uart3_cts_rctx", NULL, + "gpio_169", "uart2_cts", NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP1_CLKR, 156, + "mcbsp1_clkr", "mcspi4_clk", "sim_cd", NULL, + "gpio_156", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP1_FSR, 157, + "mcbsp1_fsr", "adpllv2d_dithering_en1", + "cam_global_reset", NULL, + "gpio_157", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(MCBSP4_CLKX, 152, + "mcbsp4_clkx", "ssi1_dat_rx", NULL, NULL, + "gpio_152", "hsusb3_tll_data1", "mm3_txse0", "safe_mode"), + _OMAP3_MUXENTRY(MCBSP4_DR, 153, + "mcbsp4_dr", "ssi1_flag_rx", NULL, NULL, + "gpio_153", "hsusb3_tll_data0", "mm3_rxrcv", "safe_mode"), + _OMAP3_MUXENTRY(MCBSP4_DX, 154, + "mcbsp4_dx", "ssi1_rdy_rx", NULL, NULL, + "gpio_154", "hsusb3_tll_data2", "mm3_txdat", "safe_mode"), + _OMAP3_MUXENTRY(MCBSP4_FSX, 155, + "mcbsp4_fsx", "ssi1_wake", NULL, NULL, + "gpio_155", "hsusb3_tll_data3", "mm3_txen_n", "safe_mode"), + _OMAP3_MUXENTRY(MCSPI1_CS1, 175, + "mcspi1_cs1", "adpllv2d_dithering_en2", NULL, "sdmmc3_cmd", + "gpio_175", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SAD2D_MBUSFLAG, 0, + "sad2d_mbusflag", "mad2d_sbusflag", NULL, NULL, + NULL, NULL, NULL, NULL), + _OMAP3_MUXENTRY(SAD2D_MCAD28, 0, + "sad2d_mcad28", "mad2d_mcad28", NULL, NULL, + NULL, NULL, NULL, NULL), + _OMAP3_MUXENTRY(SAD2D_MCAD29, 0, + "sad2d_mcad29", "mad2d_mcad29", NULL, NULL, + NULL, NULL, NULL, NULL), + _OMAP3_MUXENTRY(SAD2D_MCAD32, 0, + "sad2d_mcad32", "mad2d_mcad32", NULL, NULL, + NULL, NULL, NULL, NULL), + _OMAP3_MUXENTRY(SAD2D_MCAD33, 0, + "sad2d_mcad33", "mad2d_mcad33", NULL, NULL, + NULL, NULL, NULL, NULL), + _OMAP3_MUXENTRY(SAD2D_MCAD34, 0, + "sad2d_mcad34", "mad2d_mcad34", NULL, NULL, + NULL, NULL, NULL, NULL), + _OMAP3_MUXENTRY(SAD2D_MCAD35, 0, + "sad2d_mcad35", "mad2d_mcad35", NULL, NULL, + NULL, NULL, NULL, NULL), + _OMAP3_MUXENTRY(SAD2D_MCAD36, 0, + "sad2d_mcad36", "mad2d_mcad36", NULL, NULL, + NULL, NULL, NULL, NULL), + _OMAP3_MUXENTRY(SAD2D_MREAD, 0, + "sad2d_mread", "mad2d_sread", NULL, NULL, + NULL, NULL, NULL, NULL), + _OMAP3_MUXENTRY(SAD2D_MWRITE, 0, + "sad2d_mwrite", "mad2d_swrite", NULL, NULL, + NULL, NULL, NULL, NULL), + _OMAP3_MUXENTRY(SAD2D_SBUSFLAG, 0, + "sad2d_sbusflag", "mad2d_mbusflag", NULL, NULL, + NULL, NULL, NULL, NULL), + _OMAP3_MUXENTRY(SAD2D_SREAD, 0, + "sad2d_sread", "mad2d_mread", NULL, NULL, + NULL, NULL, NULL, NULL), + _OMAP3_MUXENTRY(SAD2D_SWRITE, 0, + "sad2d_swrite", "mad2d_mwrite", NULL, NULL, + NULL, NULL, NULL, NULL), + _OMAP3_MUXENTRY(SDMMC1_CLK, 120, + "sdmmc1_clk", "ms_clk", NULL, NULL, + "gpio_120", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_CMD, 121, + "sdmmc1_cmd", "ms_bs", NULL, NULL, + "gpio_121", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_DAT0, 122, + "sdmmc1_dat0", "ms_dat0", NULL, NULL, + "gpio_122", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_DAT1, 123, + "sdmmc1_dat1", "ms_dat1", NULL, NULL, + "gpio_123", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_DAT2, 124, + "sdmmc1_dat2", "ms_dat2", NULL, NULL, + "gpio_124", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDMMC1_DAT3, 125, + "sdmmc1_dat3", "ms_dat3", NULL, NULL, + "gpio_125", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SDRC_CKE0, 0, + "sdrc_cke0", NULL, NULL, NULL, + NULL, NULL, NULL, "safe_mode_out1"), + _OMAP3_MUXENTRY(SDRC_CKE1, 0, + "sdrc_cke1", NULL, NULL, NULL, + NULL, NULL, NULL, "safe_mode_out1"), + _OMAP3_MUXENTRY(SIM_IO, 126, + "sim_io", "sim_io_low_impedance", NULL, NULL, + "gpio_126", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SIM_CLK, 127, + "sim_clk", NULL, NULL, NULL, + "gpio_127", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SIM_PWRCTRL, 128, + "sim_pwrctrl", NULL, NULL, NULL, + "gpio_128", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SIM_RST, 129, + "sim_rst", NULL, NULL, NULL, + "gpio_129", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_BOOT0, 2, + "sys_boot0", NULL, NULL, "dss_data18", + "gpio_2", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_BOOT1, 3, + "sys_boot1", NULL, NULL, "dss_data19", + "gpio_3", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_BOOT3, 5, + "sys_boot3", NULL, NULL, "dss_data20", + "gpio_5", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_BOOT4, 6, + "sys_boot4", "sdmmc2_dir_dat2", NULL, "dss_data21", + "gpio_6", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_BOOT5, 7, + "sys_boot5", "sdmmc2_dir_dat3", NULL, "dss_data22", + "gpio_7", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(SYS_BOOT6, 8, + "sys_boot6", NULL, NULL, "dss_data23", + "gpio_8", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART1_CTS, 150, + "uart1_cts", "ssi1_rdy_tx", NULL, NULL, + "gpio_150", "hsusb3_tll_clk", NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART1_RTS, 149, + "uart1_rts", "ssi1_flag_tx", NULL, NULL, + "gpio_149", NULL, NULL, "safe_mode"), + _OMAP3_MUXENTRY(UART1_TX, 148, + "uart1_tx", "ssi1_dat_tx", NULL, NULL, + "gpio_148", NULL, NULL, "safe_mode"), + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define omap36xx_cbp_subset NULL +#endif + +/* + * Balls for 36XX CBP package + * 515-pin s-PBGA Package, 0.50mm Ball Pitch (Top), 0.40mm Ball Pitch (Bottom) + */ +#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS) \ + && defined (CONFIG_OMAP_PACKAGE_CBP) +struct omap_ball __initdata omap36xx_cbp_ball[] = { + _OMAP3_BALLENTRY(CAM_D0, "ag17", NULL), + _OMAP3_BALLENTRY(CAM_D1, "ah17", NULL), + _OMAP3_BALLENTRY(CAM_D10, "b25", NULL), + _OMAP3_BALLENTRY(CAM_D11, "c26", NULL), + _OMAP3_BALLENTRY(CAM_D2, "b24", NULL), + _OMAP3_BALLENTRY(CAM_D3, "c24", NULL), + _OMAP3_BALLENTRY(CAM_D4, "d24", NULL), + _OMAP3_BALLENTRY(CAM_D5, "a25", NULL), + _OMAP3_BALLENTRY(CAM_D6, "k28", NULL), + _OMAP3_BALLENTRY(CAM_D7, "l28", NULL), + _OMAP3_BALLENTRY(CAM_D8, "k27", NULL), + _OMAP3_BALLENTRY(CAM_D9, "l27", NULL), + _OMAP3_BALLENTRY(CAM_FLD, "c23", NULL), + _OMAP3_BALLENTRY(CAM_HS, "a24", NULL), + _OMAP3_BALLENTRY(CAM_PCLK, "c27", NULL), + _OMAP3_BALLENTRY(CAM_STROBE, "d25", NULL), + _OMAP3_BALLENTRY(CAM_VS, "a23", NULL), + _OMAP3_BALLENTRY(CAM_WEN, "b23", NULL), + _OMAP3_BALLENTRY(CAM_XCLKA, "c25", NULL), + _OMAP3_BALLENTRY(CAM_XCLKB, "b26", NULL), + _OMAP3_BALLENTRY(CSI2_DX0, "ag19", NULL), + _OMAP3_BALLENTRY(CSI2_DX1, "ag18", NULL), + _OMAP3_BALLENTRY(CSI2_DY0, "ah19", NULL), + _OMAP3_BALLENTRY(CSI2_DY1, "ah18", NULL), + _OMAP3_BALLENTRY(DSS_ACBIAS, "e27", NULL), + _OMAP3_BALLENTRY(DSS_DATA0, "ag22", NULL), + _OMAP3_BALLENTRY(DSS_DATA1, "ah22", NULL), + _OMAP3_BALLENTRY(DSS_DATA10, "ad28", NULL), + _OMAP3_BALLENTRY(DSS_DATA11, "ad27", NULL), + _OMAP3_BALLENTRY(DSS_DATA12, "ab28", NULL), + _OMAP3_BALLENTRY(DSS_DATA13, "ab27", NULL), + _OMAP3_BALLENTRY(DSS_DATA14, "aa28", NULL), + _OMAP3_BALLENTRY(DSS_DATA15, "aa27", NULL), + _OMAP3_BALLENTRY(DSS_DATA16, "g25", NULL), + _OMAP3_BALLENTRY(DSS_DATA17, "h27", NULL), + _OMAP3_BALLENTRY(DSS_DATA18, "h26", NULL), + _OMAP3_BALLENTRY(DSS_DATA19, "h25", NULL), + _OMAP3_BALLENTRY(DSS_DATA2, "ag23", NULL), + _OMAP3_BALLENTRY(DSS_DATA20, "e28", NULL), + _OMAP3_BALLENTRY(DSS_DATA21, "j26", NULL), + _OMAP3_BALLENTRY(DSS_DATA22, "ac27", NULL), + _OMAP3_BALLENTRY(DSS_DATA23, "ac28", NULL), + _OMAP3_BALLENTRY(DSS_DATA3, "ah23", NULL), + _OMAP3_BALLENTRY(DSS_DATA4, "ag24", NULL), + _OMAP3_BALLENTRY(DSS_DATA5, "ah24", NULL), + _OMAP3_BALLENTRY(DSS_DATA6, "e26", NULL), + _OMAP3_BALLENTRY(DSS_DATA7, "f28", NULL), + _OMAP3_BALLENTRY(DSS_DATA8, "f27", NULL), + _OMAP3_BALLENTRY(DSS_DATA9, "g26", NULL), + _OMAP3_BALLENTRY(DSS_HSYNC, "d26", NULL), + _OMAP3_BALLENTRY(DSS_PCLK, "d28", NULL), + _OMAP3_BALLENTRY(DSS_VSYNC, "d27", NULL), + _OMAP3_BALLENTRY(ETK_CLK, "af10", NULL), + _OMAP3_BALLENTRY(ETK_CTL, "ae10", NULL), + _OMAP3_BALLENTRY(ETK_D0, "af11", NULL), + _OMAP3_BALLENTRY(ETK_D1, "ag12", NULL), + _OMAP3_BALLENTRY(ETK_D10, "ae7", NULL), + _OMAP3_BALLENTRY(ETK_D11, "af7", NULL), + _OMAP3_BALLENTRY(ETK_D12, "ag7", NULL), + _OMAP3_BALLENTRY(ETK_D13, "ah7", NULL), + _OMAP3_BALLENTRY(ETK_D14, "ag8", NULL), + _OMAP3_BALLENTRY(ETK_D15, "ah8", NULL), + _OMAP3_BALLENTRY(ETK_D2, "ah12", NULL), + _OMAP3_BALLENTRY(ETK_D3, "ae13", NULL), + _OMAP3_BALLENTRY(ETK_D4, "ae11", NULL), + _OMAP3_BALLENTRY(ETK_D5, "ah9", NULL), + _OMAP3_BALLENTRY(ETK_D6, "af13", NULL), + _OMAP3_BALLENTRY(ETK_D7, "ah14", NULL), + _OMAP3_BALLENTRY(ETK_D8, "af9", NULL), + _OMAP3_BALLENTRY(ETK_D9, "ag9", NULL), + _OMAP3_BALLENTRY(GPMC_A1, "n4", "ac15"), + _OMAP3_BALLENTRY(GPMC_A10, "k3", "ab19"), + _OMAP3_BALLENTRY(GPMC_A11, NULL, "ac20"), + _OMAP3_BALLENTRY(GPMC_A2, "m4", "ab15"), + _OMAP3_BALLENTRY(GPMC_A3, "l4", "ac16"), + _OMAP3_BALLENTRY(GPMC_A4, "k4", "ab16"), + _OMAP3_BALLENTRY(GPMC_A5, "t3", "ac17"), + _OMAP3_BALLENTRY(GPMC_A6, "r3", "ab17"), + _OMAP3_BALLENTRY(GPMC_A7, "n3", "ac18"), + _OMAP3_BALLENTRY(GPMC_A8, "m3", "ab18"), + _OMAP3_BALLENTRY(GPMC_A9, "l3", "ac19"), + _OMAP3_BALLENTRY(GPMC_CLK, "t4", "w2"), + _OMAP3_BALLENTRY(GPMC_D0, "k1", "m2"), + _OMAP3_BALLENTRY(GPMC_D1, "l1", "m1"), + _OMAP3_BALLENTRY(GPMC_D10, "p1", "ab4"), + _OMAP3_BALLENTRY(GPMC_D11, "r1", "ac4"), + _OMAP3_BALLENTRY(GPMC_D12, "r2", "ab6"), + _OMAP3_BALLENTRY(GPMC_D13, "t2", "ac6"), + _OMAP3_BALLENTRY(GPMC_D14, "w1", "ab7"), + _OMAP3_BALLENTRY(GPMC_D15, "y1", "ac7"), + _OMAP3_BALLENTRY(GPMC_D2, "l2", "n2"), + _OMAP3_BALLENTRY(GPMC_D3, "p2", "n1"), + _OMAP3_BALLENTRY(GPMC_D4, "t1", "r2"), + _OMAP3_BALLENTRY(GPMC_D5, "v1", "r1"), + _OMAP3_BALLENTRY(GPMC_D6, "v2", "t2"), + _OMAP3_BALLENTRY(GPMC_D7, "w2", "t1"), + _OMAP3_BALLENTRY(GPMC_D8, "h2", "ab3"), + _OMAP3_BALLENTRY(GPMC_D9, "k2", "ac3"), + _OMAP3_BALLENTRY(GPMC_NADV_ALE, "f3", "w1"), + _OMAP3_BALLENTRY(GPMC_NBE0_CLE, "g3", "ac12"), + _OMAP3_BALLENTRY(GPMC_NBE1, "u3", NULL), + _OMAP3_BALLENTRY(GPMC_NCS0, "g4", "y2"), + _OMAP3_BALLENTRY(GPMC_NCS1, "h3", "y1"), + _OMAP3_BALLENTRY(GPMC_NCS2, "v8", NULL), + _OMAP3_BALLENTRY(GPMC_NCS3, "u8", NULL), + _OMAP3_BALLENTRY(GPMC_NCS4, "t8", NULL), + _OMAP3_BALLENTRY(GPMC_NCS5, "r8", NULL), + _OMAP3_BALLENTRY(GPMC_NCS6, "p8", NULL), + _OMAP3_BALLENTRY(GPMC_NCS7, "n8", NULL), + _OMAP3_BALLENTRY(GPMC_NOE, "g2", "v2"), + _OMAP3_BALLENTRY(GPMC_NWE, "f4", "v1"), + _OMAP3_BALLENTRY(GPMC_NWP, "h1", "ab10"), + _OMAP3_BALLENTRY(GPMC_WAIT0, "m8", "ab12"), + _OMAP3_BALLENTRY(GPMC_WAIT1, "l8", "ac10"), + _OMAP3_BALLENTRY(GPMC_WAIT2, "k8", NULL), + _OMAP3_BALLENTRY(GPMC_WAIT3, "j8", NULL), + _OMAP3_BALLENTRY(HDQ_SIO, "j25", NULL), + _OMAP3_BALLENTRY(HSUSB0_CLK, "t28", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA0, "t27", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA1, "u28", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA2, "u27", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA3, "u26", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA4, "u25", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA5, "v28", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA6, "v27", NULL), + _OMAP3_BALLENTRY(HSUSB0_DATA7, "v26", NULL), + _OMAP3_BALLENTRY(HSUSB0_DIR, "r28", NULL), + _OMAP3_BALLENTRY(HSUSB0_NXT, "t26", NULL), + _OMAP3_BALLENTRY(HSUSB0_STP, "t25", NULL), + _OMAP3_BALLENTRY(I2C1_SCL, "k21", NULL), + _OMAP3_BALLENTRY(I2C1_SDA, "j21", NULL), + _OMAP3_BALLENTRY(I2C2_SCL, "af15", NULL), + _OMAP3_BALLENTRY(I2C2_SDA, "ae15", NULL), + _OMAP3_BALLENTRY(I2C3_SCL, "af14", NULL), + _OMAP3_BALLENTRY(I2C3_SDA, "ag14", NULL), + _OMAP3_BALLENTRY(I2C4_SCL, "ad26", NULL), + _OMAP3_BALLENTRY(I2C4_SDA, "ae26", NULL), + _OMAP3_BALLENTRY(JTAG_EMU0, "aa11", NULL), + _OMAP3_BALLENTRY(JTAG_EMU1, "aa10", NULL), + _OMAP3_BALLENTRY(JTAG_RTCK, "aa12", NULL), + _OMAP3_BALLENTRY(JTAG_TCK, "aa13", NULL), + _OMAP3_BALLENTRY(JTAG_TDI, "aa20", NULL), + _OMAP3_BALLENTRY(JTAG_TDO, "aa19", NULL), + _OMAP3_BALLENTRY(JTAG_TMS_TMSC, "aa18", NULL), + _OMAP3_BALLENTRY(MCBSP1_CLKR, "y21", NULL), + _OMAP3_BALLENTRY(MCBSP1_CLKX, "w21", NULL), + _OMAP3_BALLENTRY(MCBSP1_DR, "u21", NULL), + _OMAP3_BALLENTRY(MCBSP1_DX, "v21", NULL), + _OMAP3_BALLENTRY(MCBSP1_FSR, "aa21", NULL), + _OMAP3_BALLENTRY(MCBSP1_FSX, "k26", NULL), + _OMAP3_BALLENTRY(MCBSP2_CLKX, "n21", NULL), + _OMAP3_BALLENTRY(MCBSP2_DR, "r21", NULL), + _OMAP3_BALLENTRY(MCBSP2_DX, "m21", NULL), + _OMAP3_BALLENTRY(MCBSP2_FSX, "p21", NULL), + _OMAP3_BALLENTRY(MCBSP3_CLKX, "af5", NULL), + _OMAP3_BALLENTRY(MCBSP3_DR, "ae6", NULL), + _OMAP3_BALLENTRY(MCBSP3_DX, "af6", NULL), + _OMAP3_BALLENTRY(MCBSP3_FSX, "ae5", NULL), + _OMAP3_BALLENTRY(MCBSP4_CLKX, "ae1", NULL), + _OMAP3_BALLENTRY(MCBSP4_DR, "ad1", NULL), + _OMAP3_BALLENTRY(MCBSP4_DX, "ad2", NULL), + _OMAP3_BALLENTRY(MCBSP4_FSX, "ac1", NULL), + _OMAP3_BALLENTRY(MCBSP_CLKS, "t21", NULL), + _OMAP3_BALLENTRY(MCSPI1_CLK, "ab3", NULL), + _OMAP3_BALLENTRY(MCSPI1_CS0, "ac2", NULL), + _OMAP3_BALLENTRY(MCSPI1_CS1, "ac3", NULL), + _OMAP3_BALLENTRY(MCSPI1_CS2, "ab1", NULL), + _OMAP3_BALLENTRY(MCSPI1_CS3, "ab2", NULL), + _OMAP3_BALLENTRY(MCSPI1_SIMO, "ab4", NULL), + _OMAP3_BALLENTRY(MCSPI1_SOMI, "aa4", NULL), + _OMAP3_BALLENTRY(MCSPI2_CLK, "aa3", NULL), + _OMAP3_BALLENTRY(MCSPI2_CS0, "y4", NULL), + _OMAP3_BALLENTRY(MCSPI2_CS1, "v3", NULL), + _OMAP3_BALLENTRY(MCSPI2_SIMO, "y2", NULL), + _OMAP3_BALLENTRY(MCSPI2_SOMI, "y3", NULL), + _OMAP3_BALLENTRY(SDMMC1_CLK, "n28", NULL), + _OMAP3_BALLENTRY(SDMMC1_CMD, "m27", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT0, "n27", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT1, "n26", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT2, "n25", NULL), + _OMAP3_BALLENTRY(SDMMC1_DAT3, "p28", NULL), + _OMAP3_BALLENTRY(SDMMC2_CLK, "ae2", NULL), + _OMAP3_BALLENTRY(SDMMC2_CMD, "ag5", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT0, "ah5", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT1, "ah4", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT2, "ag4", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT3, "af4", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT4, "ae4", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT5, "ah3", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT6, "af3", NULL), + _OMAP3_BALLENTRY(SDMMC2_DAT7, "ae3", NULL), + _OMAP3_BALLENTRY(SDRC_A0, NULL, "n22"), + _OMAP3_BALLENTRY(SDRC_A1, NULL, "n23"), + _OMAP3_BALLENTRY(SDRC_A10, NULL, "v22"), + _OMAP3_BALLENTRY(SDRC_A11, NULL, "v23"), + _OMAP3_BALLENTRY(SDRC_A12, NULL, "w22"), + _OMAP3_BALLENTRY(SDRC_A13, NULL, "w23"), + _OMAP3_BALLENTRY(SDRC_A14, NULL, "y22"), + _OMAP3_BALLENTRY(SDRC_A2, NULL, "p22"), + _OMAP3_BALLENTRY(SDRC_A3, NULL, "p23"), + _OMAP3_BALLENTRY(SDRC_A4, NULL, "r22"), + _OMAP3_BALLENTRY(SDRC_A5, NULL, "r23"), + _OMAP3_BALLENTRY(SDRC_A6, NULL, "t22"), + _OMAP3_BALLENTRY(SDRC_A7, NULL, "t23"), + _OMAP3_BALLENTRY(SDRC_A8, NULL, "u22"), + _OMAP3_BALLENTRY(SDRC_A9, NULL, "u23"), + _OMAP3_BALLENTRY(SDRC_BA0, "h9", "ab21"), + _OMAP3_BALLENTRY(SDRC_BA1, "h10", "ac21"), + _OMAP3_BALLENTRY(SDRC_CKE0, "h16", "j22"), + _OMAP3_BALLENTRY(SDRC_CKE1, "h17", "j23"), + _OMAP3_BALLENTRY(SDRC_CLK, "a13", "a11"), + _OMAP3_BALLENTRY(SDRC_D0, NULL, "j2"), + _OMAP3_BALLENTRY(SDRC_D1, NULL, "j1"), + _OMAP3_BALLENTRY(SDRC_D10, "c15", "b14"), + _OMAP3_BALLENTRY(SDRC_D11, "b16", "a14"), + _OMAP3_BALLENTRY(SDRC_D12, "d17", "b16"), + _OMAP3_BALLENTRY(SDRC_D13, "c17", "a16"), + _OMAP3_BALLENTRY(SDRC_D14, "b17", "b19"), + _OMAP3_BALLENTRY(SDRC_D15, "d18", "a19"), + _OMAP3_BALLENTRY(SDRC_D16, NULL, "b3"), + _OMAP3_BALLENTRY(SDRC_D17, NULL, "a3"), + _OMAP3_BALLENTRY(SDRC_D18, NULL, "b5"), + _OMAP3_BALLENTRY(SDRC_D19, NULL, "a5"), + _OMAP3_BALLENTRY(SDRC_D2, NULL, "g2"), + _OMAP3_BALLENTRY(SDRC_D20, NULL, "b8"), + _OMAP3_BALLENTRY(SDRC_D21, NULL, "a8"), + _OMAP3_BALLENTRY(SDRC_D22, NULL, "b9"), + _OMAP3_BALLENTRY(SDRC_D23, NULL, "a9"), + _OMAP3_BALLENTRY(SDRC_D24, NULL, "b21"), + _OMAP3_BALLENTRY(SDRC_D25, NULL, "a21"), + _OMAP3_BALLENTRY(SDRC_D26, NULL, "d22"), + _OMAP3_BALLENTRY(SDRC_D27, NULL, "d23"), + _OMAP3_BALLENTRY(SDRC_D28, NULL, "e22"), + _OMAP3_BALLENTRY(SDRC_D29, NULL, "e23"), + _OMAP3_BALLENTRY(SDRC_D3, NULL, "g1"), + _OMAP3_BALLENTRY(SDRC_D30, NULL, "g22"), + _OMAP3_BALLENTRY(SDRC_D31, NULL, "g23"), + _OMAP3_BALLENTRY(SDRC_D4, NULL, "f2"), + _OMAP3_BALLENTRY(SDRC_D5, NULL, "f1"), + _OMAP3_BALLENTRY(SDRC_D6, NULL, "d2"), + _OMAP3_BALLENTRY(SDRC_D7, NULL, "d1"), + _OMAP3_BALLENTRY(SDRC_D8, "c14", "b13"), + _OMAP3_BALLENTRY(SDRC_D9, "b14", "a13"), + _OMAP3_BALLENTRY(SDRC_DM0, NULL, "c1"), + _OMAP3_BALLENTRY(SDRC_DM1, "a16", "a17"), + _OMAP3_BALLENTRY(SDRC_DM2, NULL, "a6"), + _OMAP3_BALLENTRY(SDRC_DM3, NULL, "a20"), + _OMAP3_BALLENTRY(SDRC_DQS0, NULL, "c2"), + _OMAP3_BALLENTRY(SDRC_DQS1, "a17", "b17"), + _OMAP3_BALLENTRY(SDRC_DQS2, NULL, "b6"), + _OMAP3_BALLENTRY(SDRC_DQS3, NULL, "b20"), + _OMAP3_BALLENTRY(SDRC_NCAS, "h13", "l22"), + _OMAP3_BALLENTRY(SDRC_NCLK, "a14", "b11"), + _OMAP3_BALLENTRY(SDRC_NCS0, "h11", "m22"), + _OMAP3_BALLENTRY(SDRC_NCS1, "h12", "m23"), + _OMAP3_BALLENTRY(SDRC_NRAS, "h14", "l23"), + _OMAP3_BALLENTRY(SDRC_NWE, "h15", "k23"), + _OMAP3_BALLENTRY(SIM_CLK, "p26", NULL), + _OMAP3_BALLENTRY(SIM_IO, "p27", NULL), + _OMAP3_BALLENTRY(SIM_PWRCTRL, "r27", NULL), + _OMAP3_BALLENTRY(SIM_RST, "r25", NULL), + _OMAP3_BALLENTRY(SYS_32K, "ae25", NULL), + _OMAP3_BALLENTRY(SYS_BOOT0, "ah26", NULL), + _OMAP3_BALLENTRY(SYS_BOOT1, "ag26", NULL), + _OMAP3_BALLENTRY(SYS_BOOT2, "ae14", NULL), + _OMAP3_BALLENTRY(SYS_BOOT3, "af18", NULL), + _OMAP3_BALLENTRY(SYS_BOOT4, "af19", NULL), + _OMAP3_BALLENTRY(SYS_BOOT5, "ae21", NULL), + _OMAP3_BALLENTRY(SYS_BOOT6, "af21", NULL), + _OMAP3_BALLENTRY(SYS_CLKOUT1, "ag25", NULL), + _OMAP3_BALLENTRY(SYS_CLKOUT2, "ae22", NULL), + _OMAP3_BALLENTRY(SYS_CLKREQ, "af25", NULL), + _OMAP3_BALLENTRY(SYS_NIRQ, "af26", NULL), + _OMAP3_BALLENTRY(SYS_NRESWARM, "af24", NULL), + _OMAP3_BALLENTRY(SYS_OFF_MODE, "af22", NULL), + _OMAP3_BALLENTRY(UART1_CTS, "w8", NULL), + _OMAP3_BALLENTRY(UART1_RTS, "aa9", NULL), + _OMAP3_BALLENTRY(UART1_RX, "y8", NULL), + _OMAP3_BALLENTRY(UART1_TX, "aa8", NULL), + _OMAP3_BALLENTRY(UART2_CTS, "ab26", NULL), + _OMAP3_BALLENTRY(UART2_RTS, "ab25", NULL), + _OMAP3_BALLENTRY(UART2_RX, "ad25", NULL), + _OMAP3_BALLENTRY(UART2_TX, "aa25", NULL), + _OMAP3_BALLENTRY(UART3_CTS_RCTX, "h18", NULL), + _OMAP3_BALLENTRY(UART3_RTS_SD, "h19", NULL), + _OMAP3_BALLENTRY(UART3_RX_IRRX, "h20", NULL), + _OMAP3_BALLENTRY(UART3_TX_IRTX, "h21", NULL), + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; +#else +#define omap36xx_cbp_ball NULL +#endif + +int __init omap3_mux_init(struct omap_board_mux *board_subset, int flags) +{ + struct omap_mux *package_subset; + struct omap_ball *package_balls; + + switch (flags & OMAP_PACKAGE_MASK) { + case (OMAP_PACKAGE_CBC): + package_subset = omap3_cbc_subset; + package_balls = omap3_cbc_ball; + break; + case (OMAP_PACKAGE_CBB): + package_subset = omap3_cbb_subset; + package_balls = omap3_cbb_ball; + break; + case (OMAP_PACKAGE_CUS): + package_subset = omap3_cus_subset; + package_balls = omap3_cus_ball; + break; + case (OMAP_PACKAGE_CBP): + package_subset = omap36xx_cbp_subset; + package_balls = omap36xx_cbp_ball; + break; + default: + printk(KERN_ERR "mux: Unknown omap package, mux disabled\n"); + return -EINVAL; + } + + return omap_mux_init(OMAP3_CONTROL_PADCONF_MUX_PBASE, + OMAP3_CONTROL_PADCONF_MUX_SIZE, + omap3_muxmodes, package_subset, board_subset, + package_balls); +} diff --git a/arch/arm/mach-omap2/mux34xx.h b/arch/arm/mach-omap2/mux34xx.h new file mode 100644 index 0000000000000000000000000000000000000000..6543ebf8ecfc1ab7698a6d73b81d414b343249ca --- /dev/null +++ b/arch/arm/mach-omap2/mux34xx.h @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2009 Nokia + * Copyright (C) 2009 Texas Instruments + * + * 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. + */ + +#define OMAP3_CONTROL_PADCONF_MUX_PBASE 0x48002030LU + +#define OMAP3_MUX(mode0, mux_value) \ +{ \ + .reg_offset = (OMAP3_CONTROL_PADCONF_##mode0##_OFFSET), \ + .value = (mux_value), \ +} + +/* + * OMAP3 CONTROL_PADCONF* register offsets for pin-muxing + * + * Extracted from the TRM. Add 0x48002030 to these values to get the + * absolute addresses. The name in the macro is the mode-0 name of + * the pin. NOTE: These registers are 16-bits wide. + * + * Note that 34XX TRM uses MMC instead of SDMMC and SAD2D instead + * of CHASSIS for some registers. For the defines, we follow the + * 36XX naming, and use SDMMC and CHASSIS. + */ +#define OMAP3_CONTROL_PADCONF_SDRC_D0_OFFSET 0x000 +#define OMAP3_CONTROL_PADCONF_SDRC_D1_OFFSET 0x002 +#define OMAP3_CONTROL_PADCONF_SDRC_D2_OFFSET 0x004 +#define OMAP3_CONTROL_PADCONF_SDRC_D3_OFFSET 0x006 +#define OMAP3_CONTROL_PADCONF_SDRC_D4_OFFSET 0x008 +#define OMAP3_CONTROL_PADCONF_SDRC_D5_OFFSET 0x00a +#define OMAP3_CONTROL_PADCONF_SDRC_D6_OFFSET 0x00c +#define OMAP3_CONTROL_PADCONF_SDRC_D7_OFFSET 0x00e +#define OMAP3_CONTROL_PADCONF_SDRC_D8_OFFSET 0x010 +#define OMAP3_CONTROL_PADCONF_SDRC_D9_OFFSET 0x012 +#define OMAP3_CONTROL_PADCONF_SDRC_D10_OFFSET 0x014 +#define OMAP3_CONTROL_PADCONF_SDRC_D11_OFFSET 0x016 +#define OMAP3_CONTROL_PADCONF_SDRC_D12_OFFSET 0x018 +#define OMAP3_CONTROL_PADCONF_SDRC_D13_OFFSET 0x01a +#define OMAP3_CONTROL_PADCONF_SDRC_D14_OFFSET 0x01c +#define OMAP3_CONTROL_PADCONF_SDRC_D15_OFFSET 0x01e +#define OMAP3_CONTROL_PADCONF_SDRC_D16_OFFSET 0x020 +#define OMAP3_CONTROL_PADCONF_SDRC_D17_OFFSET 0x022 +#define OMAP3_CONTROL_PADCONF_SDRC_D18_OFFSET 0x024 +#define OMAP3_CONTROL_PADCONF_SDRC_D19_OFFSET 0x026 +#define OMAP3_CONTROL_PADCONF_SDRC_D20_OFFSET 0x028 +#define OMAP3_CONTROL_PADCONF_SDRC_D21_OFFSET 0x02a +#define OMAP3_CONTROL_PADCONF_SDRC_D22_OFFSET 0x02c +#define OMAP3_CONTROL_PADCONF_SDRC_D23_OFFSET 0x02e +#define OMAP3_CONTROL_PADCONF_SDRC_D24_OFFSET 0x030 +#define OMAP3_CONTROL_PADCONF_SDRC_D25_OFFSET 0x032 +#define OMAP3_CONTROL_PADCONF_SDRC_D26_OFFSET 0x034 +#define OMAP3_CONTROL_PADCONF_SDRC_D27_OFFSET 0x036 +#define OMAP3_CONTROL_PADCONF_SDRC_D28_OFFSET 0x038 +#define OMAP3_CONTROL_PADCONF_SDRC_D29_OFFSET 0x03a +#define OMAP3_CONTROL_PADCONF_SDRC_D30_OFFSET 0x03c +#define OMAP3_CONTROL_PADCONF_SDRC_D31_OFFSET 0x03e +#define OMAP3_CONTROL_PADCONF_SDRC_CLK_OFFSET 0x040 +#define OMAP3_CONTROL_PADCONF_SDRC_DQS0_OFFSET 0x042 +#define OMAP3_CONTROL_PADCONF_SDRC_DQS1_OFFSET 0x044 +#define OMAP3_CONTROL_PADCONF_SDRC_DQS2_OFFSET 0x046 +#define OMAP3_CONTROL_PADCONF_SDRC_DQS3_OFFSET 0x048 +#define OMAP3_CONTROL_PADCONF_GPMC_A1_OFFSET 0x04a +#define OMAP3_CONTROL_PADCONF_GPMC_A2_OFFSET 0x04c +#define OMAP3_CONTROL_PADCONF_GPMC_A3_OFFSET 0x04e +#define OMAP3_CONTROL_PADCONF_GPMC_A4_OFFSET 0x050 +#define OMAP3_CONTROL_PADCONF_GPMC_A5_OFFSET 0x052 +#define OMAP3_CONTROL_PADCONF_GPMC_A6_OFFSET 0x054 +#define OMAP3_CONTROL_PADCONF_GPMC_A7_OFFSET 0x056 +#define OMAP3_CONTROL_PADCONF_GPMC_A8_OFFSET 0x058 +#define OMAP3_CONTROL_PADCONF_GPMC_A9_OFFSET 0x05a +#define OMAP3_CONTROL_PADCONF_GPMC_A10_OFFSET 0x05c +#define OMAP3_CONTROL_PADCONF_GPMC_D0_OFFSET 0x05e +#define OMAP3_CONTROL_PADCONF_GPMC_D1_OFFSET 0x060 +#define OMAP3_CONTROL_PADCONF_GPMC_D2_OFFSET 0x062 +#define OMAP3_CONTROL_PADCONF_GPMC_D3_OFFSET 0x064 +#define OMAP3_CONTROL_PADCONF_GPMC_D4_OFFSET 0x066 +#define OMAP3_CONTROL_PADCONF_GPMC_D5_OFFSET 0x068 +#define OMAP3_CONTROL_PADCONF_GPMC_D6_OFFSET 0x06a +#define OMAP3_CONTROL_PADCONF_GPMC_D7_OFFSET 0x06c +#define OMAP3_CONTROL_PADCONF_GPMC_D8_OFFSET 0x06e +#define OMAP3_CONTROL_PADCONF_GPMC_D9_OFFSET 0x070 +#define OMAP3_CONTROL_PADCONF_GPMC_D10_OFFSET 0x072 +#define OMAP3_CONTROL_PADCONF_GPMC_D11_OFFSET 0x074 +#define OMAP3_CONTROL_PADCONF_GPMC_D12_OFFSET 0x076 +#define OMAP3_CONTROL_PADCONF_GPMC_D13_OFFSET 0x078 +#define OMAP3_CONTROL_PADCONF_GPMC_D14_OFFSET 0x07a +#define OMAP3_CONTROL_PADCONF_GPMC_D15_OFFSET 0x07c +#define OMAP3_CONTROL_PADCONF_GPMC_NCS0_OFFSET 0x07e +#define OMAP3_CONTROL_PADCONF_GPMC_NCS1_OFFSET 0x080 +#define OMAP3_CONTROL_PADCONF_GPMC_NCS2_OFFSET 0x082 +#define OMAP3_CONTROL_PADCONF_GPMC_NCS3_OFFSET 0x084 +#define OMAP3_CONTROL_PADCONF_GPMC_NCS4_OFFSET 0x086 +#define OMAP3_CONTROL_PADCONF_GPMC_NCS5_OFFSET 0x088 +#define OMAP3_CONTROL_PADCONF_GPMC_NCS6_OFFSET 0x08a +#define OMAP3_CONTROL_PADCONF_GPMC_NCS7_OFFSET 0x08c +#define OMAP3_CONTROL_PADCONF_GPMC_CLK_OFFSET 0x08e +#define OMAP3_CONTROL_PADCONF_GPMC_NADV_ALE_OFFSET 0x090 +#define OMAP3_CONTROL_PADCONF_GPMC_NOE_OFFSET 0x092 +#define OMAP3_CONTROL_PADCONF_GPMC_NWE_OFFSET 0x094 +#define OMAP3_CONTROL_PADCONF_GPMC_NBE0_CLE_OFFSET 0x096 +#define OMAP3_CONTROL_PADCONF_GPMC_NBE1_OFFSET 0x098 +#define OMAP3_CONTROL_PADCONF_GPMC_NWP_OFFSET 0x09a +#define OMAP3_CONTROL_PADCONF_GPMC_WAIT0_OFFSET 0x09c +#define OMAP3_CONTROL_PADCONF_GPMC_WAIT1_OFFSET 0x09e +#define OMAP3_CONTROL_PADCONF_GPMC_WAIT2_OFFSET 0x0a0 +#define OMAP3_CONTROL_PADCONF_GPMC_WAIT3_OFFSET 0x0a2 +#define OMAP3_CONTROL_PADCONF_DSS_PCLK_OFFSET 0x0a4 +#define OMAP3_CONTROL_PADCONF_DSS_HSYNC_OFFSET 0x0a6 +#define OMAP3_CONTROL_PADCONF_DSS_VSYNC_OFFSET 0x0a8 +#define OMAP3_CONTROL_PADCONF_DSS_ACBIAS_OFFSET 0x0aa +#define OMAP3_CONTROL_PADCONF_DSS_DATA0_OFFSET 0x0ac +#define OMAP3_CONTROL_PADCONF_DSS_DATA1_OFFSET 0x0ae +#define OMAP3_CONTROL_PADCONF_DSS_DATA2_OFFSET 0x0b0 +#define OMAP3_CONTROL_PADCONF_DSS_DATA3_OFFSET 0x0b2 +#define OMAP3_CONTROL_PADCONF_DSS_DATA4_OFFSET 0x0b4 +#define OMAP3_CONTROL_PADCONF_DSS_DATA5_OFFSET 0x0b6 +#define OMAP3_CONTROL_PADCONF_DSS_DATA6_OFFSET 0x0b8 +#define OMAP3_CONTROL_PADCONF_DSS_DATA7_OFFSET 0x0ba +#define OMAP3_CONTROL_PADCONF_DSS_DATA8_OFFSET 0x0bc +#define OMAP3_CONTROL_PADCONF_DSS_DATA9_OFFSET 0x0be +#define OMAP3_CONTROL_PADCONF_DSS_DATA10_OFFSET 0x0c0 +#define OMAP3_CONTROL_PADCONF_DSS_DATA11_OFFSET 0x0c2 +#define OMAP3_CONTROL_PADCONF_DSS_DATA12_OFFSET 0x0c4 +#define OMAP3_CONTROL_PADCONF_DSS_DATA13_OFFSET 0x0c6 +#define OMAP3_CONTROL_PADCONF_DSS_DATA14_OFFSET 0x0c8 +#define OMAP3_CONTROL_PADCONF_DSS_DATA15_OFFSET 0x0ca +#define OMAP3_CONTROL_PADCONF_DSS_DATA16_OFFSET 0x0cc +#define OMAP3_CONTROL_PADCONF_DSS_DATA17_OFFSET 0x0ce +#define OMAP3_CONTROL_PADCONF_DSS_DATA18_OFFSET 0x0d0 +#define OMAP3_CONTROL_PADCONF_DSS_DATA19_OFFSET 0x0d2 +#define OMAP3_CONTROL_PADCONF_DSS_DATA20_OFFSET 0x0d4 +#define OMAP3_CONTROL_PADCONF_DSS_DATA21_OFFSET 0x0d6 +#define OMAP3_CONTROL_PADCONF_DSS_DATA22_OFFSET 0x0d8 +#define OMAP3_CONTROL_PADCONF_DSS_DATA23_OFFSET 0x0da +#define OMAP3_CONTROL_PADCONF_CAM_HS_OFFSET 0x0dc +#define OMAP3_CONTROL_PADCONF_CAM_VS_OFFSET 0x0de +#define OMAP3_CONTROL_PADCONF_CAM_XCLKA_OFFSET 0x0e0 +#define OMAP3_CONTROL_PADCONF_CAM_PCLK_OFFSET 0x0e2 +#define OMAP3_CONTROL_PADCONF_CAM_FLD_OFFSET 0x0e4 +#define OMAP3_CONTROL_PADCONF_CAM_D0_OFFSET 0x0e6 +#define OMAP3_CONTROL_PADCONF_CAM_D1_OFFSET 0x0e8 +#define OMAP3_CONTROL_PADCONF_CAM_D2_OFFSET 0x0ea +#define OMAP3_CONTROL_PADCONF_CAM_D3_OFFSET 0x0ec +#define OMAP3_CONTROL_PADCONF_CAM_D4_OFFSET 0x0ee +#define OMAP3_CONTROL_PADCONF_CAM_D5_OFFSET 0x0f0 +#define OMAP3_CONTROL_PADCONF_CAM_D6_OFFSET 0x0f2 +#define OMAP3_CONTROL_PADCONF_CAM_D7_OFFSET 0x0f4 +#define OMAP3_CONTROL_PADCONF_CAM_D8_OFFSET 0x0f6 +#define OMAP3_CONTROL_PADCONF_CAM_D9_OFFSET 0x0f8 +#define OMAP3_CONTROL_PADCONF_CAM_D10_OFFSET 0x0fa +#define OMAP3_CONTROL_PADCONF_CAM_D11_OFFSET 0x0fc +#define OMAP3_CONTROL_PADCONF_CAM_XCLKB_OFFSET 0x0fe +#define OMAP3_CONTROL_PADCONF_CAM_WEN_OFFSET 0x100 +#define OMAP3_CONTROL_PADCONF_CAM_STROBE_OFFSET 0x102 +#define OMAP3_CONTROL_PADCONF_CSI2_DX0_OFFSET 0x104 +#define OMAP3_CONTROL_PADCONF_CSI2_DY0_OFFSET 0x106 +#define OMAP3_CONTROL_PADCONF_CSI2_DX1_OFFSET 0x108 +#define OMAP3_CONTROL_PADCONF_CSI2_DY1_OFFSET 0x10a +#define OMAP3_CONTROL_PADCONF_MCBSP2_FSX_OFFSET 0x10c +#define OMAP3_CONTROL_PADCONF_MCBSP2_CLKX_OFFSET 0x10e +#define OMAP3_CONTROL_PADCONF_MCBSP2_DR_OFFSET 0x110 +#define OMAP3_CONTROL_PADCONF_MCBSP2_DX_OFFSET 0x112 +#define OMAP3_CONTROL_PADCONF_SDMMC1_CLK_OFFSET 0x114 +#define OMAP3_CONTROL_PADCONF_SDMMC1_CMD_OFFSET 0x116 +#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT0_OFFSET 0x118 +#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT1_OFFSET 0x11a +#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT2_OFFSET 0x11c +#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT3_OFFSET 0x11e + +/* SDMMC1_DAT4 - DAT7 are SIM_IO SIM_CLK SIM_PWRCTRL and SIM_RST on 36xx */ +#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT4_OFFSET 0x120 +#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT5_OFFSET 0x122 +#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT6_OFFSET 0x124 +#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT7_OFFSET 0x126 + +#define OMAP3_CONTROL_PADCONF_SDMMC2_CLK_OFFSET 0x128 +#define OMAP3_CONTROL_PADCONF_SDMMC2_CMD_OFFSET 0x12a +#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT0_OFFSET 0x12c +#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT1_OFFSET 0x12e +#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT2_OFFSET 0x130 +#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT3_OFFSET 0x132 +#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT4_OFFSET 0x134 +#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT5_OFFSET 0x136 +#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT6_OFFSET 0x138 +#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT7_OFFSET 0x13a +#define OMAP3_CONTROL_PADCONF_MCBSP3_DX_OFFSET 0x13c +#define OMAP3_CONTROL_PADCONF_MCBSP3_DR_OFFSET 0x13e +#define OMAP3_CONTROL_PADCONF_MCBSP3_CLKX_OFFSET 0x140 +#define OMAP3_CONTROL_PADCONF_MCBSP3_FSX_OFFSET 0x142 +#define OMAP3_CONTROL_PADCONF_UART2_CTS_OFFSET 0x144 +#define OMAP3_CONTROL_PADCONF_UART2_RTS_OFFSET 0x146 +#define OMAP3_CONTROL_PADCONF_UART2_TX_OFFSET 0x148 +#define OMAP3_CONTROL_PADCONF_UART2_RX_OFFSET 0x14a +#define OMAP3_CONTROL_PADCONF_UART1_TX_OFFSET 0x14c +#define OMAP3_CONTROL_PADCONF_UART1_RTS_OFFSET 0x14e +#define OMAP3_CONTROL_PADCONF_UART1_CTS_OFFSET 0x150 +#define OMAP3_CONTROL_PADCONF_UART1_RX_OFFSET 0x152 +#define OMAP3_CONTROL_PADCONF_MCBSP4_CLKX_OFFSET 0x154 +#define OMAP3_CONTROL_PADCONF_MCBSP4_DR_OFFSET 0x156 +#define OMAP3_CONTROL_PADCONF_MCBSP4_DX_OFFSET 0x158 +#define OMAP3_CONTROL_PADCONF_MCBSP4_FSX_OFFSET 0x15a +#define OMAP3_CONTROL_PADCONF_MCBSP1_CLKR_OFFSET 0x15c +#define OMAP3_CONTROL_PADCONF_MCBSP1_FSR_OFFSET 0x15e +#define OMAP3_CONTROL_PADCONF_MCBSP1_DX_OFFSET 0x160 +#define OMAP3_CONTROL_PADCONF_MCBSP1_DR_OFFSET 0x162 +#define OMAP3_CONTROL_PADCONF_MCBSP_CLKS_OFFSET 0x164 +#define OMAP3_CONTROL_PADCONF_MCBSP1_FSX_OFFSET 0x166 +#define OMAP3_CONTROL_PADCONF_MCBSP1_CLKX_OFFSET 0x168 +#define OMAP3_CONTROL_PADCONF_UART3_CTS_RCTX_OFFSET 0x16a +#define OMAP3_CONTROL_PADCONF_UART3_RTS_SD_OFFSET 0x16c +#define OMAP3_CONTROL_PADCONF_UART3_RX_IRRX_OFFSET 0x16e +#define OMAP3_CONTROL_PADCONF_UART3_TX_IRTX_OFFSET 0x170 +#define OMAP3_CONTROL_PADCONF_HSUSB0_CLK_OFFSET 0x172 +#define OMAP3_CONTROL_PADCONF_HSUSB0_STP_OFFSET 0x174 +#define OMAP3_CONTROL_PADCONF_HSUSB0_DIR_OFFSET 0x176 +#define OMAP3_CONTROL_PADCONF_HSUSB0_NXT_OFFSET 0x178 +#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA0_OFFSET 0x17a +#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA1_OFFSET 0x17c +#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA2_OFFSET 0x17e +#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA3_OFFSET 0x180 +#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA4_OFFSET 0x182 +#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA5_OFFSET 0x184 +#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA6_OFFSET 0x186 +#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA7_OFFSET 0x188 +#define OMAP3_CONTROL_PADCONF_I2C1_SCL_OFFSET 0x18a +#define OMAP3_CONTROL_PADCONF_I2C1_SDA_OFFSET 0x18c +#define OMAP3_CONTROL_PADCONF_I2C2_SCL_OFFSET 0x18e +#define OMAP3_CONTROL_PADCONF_I2C2_SDA_OFFSET 0x190 +#define OMAP3_CONTROL_PADCONF_I2C3_SCL_OFFSET 0x192 +#define OMAP3_CONTROL_PADCONF_I2C3_SDA_OFFSET 0x194 +#define OMAP3_CONTROL_PADCONF_HDQ_SIO_OFFSET 0x196 +#define OMAP3_CONTROL_PADCONF_MCSPI1_CLK_OFFSET 0x198 +#define OMAP3_CONTROL_PADCONF_MCSPI1_SIMO_OFFSET 0x19a +#define OMAP3_CONTROL_PADCONF_MCSPI1_SOMI_OFFSET 0x19c +#define OMAP3_CONTROL_PADCONF_MCSPI1_CS0_OFFSET 0x19e +#define OMAP3_CONTROL_PADCONF_MCSPI1_CS1_OFFSET 0x1a0 +#define OMAP3_CONTROL_PADCONF_MCSPI1_CS2_OFFSET 0x1a2 +#define OMAP3_CONTROL_PADCONF_MCSPI1_CS3_OFFSET 0x1a4 +#define OMAP3_CONTROL_PADCONF_MCSPI2_CLK_OFFSET 0x1a6 +#define OMAP3_CONTROL_PADCONF_MCSPI2_SIMO_OFFSET 0x1a8 +#define OMAP3_CONTROL_PADCONF_MCSPI2_SOMI_OFFSET 0x1aa +#define OMAP3_CONTROL_PADCONF_MCSPI2_CS0_OFFSET 0x1ac +#define OMAP3_CONTROL_PADCONF_MCSPI2_CS1_OFFSET 0x1ae +#define OMAP3_CONTROL_PADCONF_SYS_NIRQ_OFFSET 0x1b0 +#define OMAP3_CONTROL_PADCONF_SYS_CLKOUT2_OFFSET 0x1b2 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD0_OFFSET 0x1b4 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD1_OFFSET 0x1b6 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD2_OFFSET 0x1b8 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD3_OFFSET 0x1ba +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD4_OFFSET 0x1bc +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD5_OFFSET 0x1be +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD6_OFFSET 0x1c0 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD7_OFFSET 0x1c2 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD8_OFFSET 0x1c4 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD9_OFFSET 0x1c6 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD10_OFFSET 0x1c8 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD11_OFFSET 0x1ca +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD12_OFFSET 0x1cc +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD13_OFFSET 0x1ce +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD14_OFFSET 0x1d0 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD15_OFFSET 0x1d2 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD16_OFFSET 0x1d4 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD17_OFFSET 0x1d6 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD18_OFFSET 0x1d8 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD19_OFFSET 0x1da +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD20_OFFSET 0x1dc +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD21_OFFSET 0x1de +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD22_OFFSET 0x1e0 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD23_OFFSET 0x1e2 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD24_OFFSET 0x1e4 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD25_OFFSET 0x1e6 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD26_OFFSET 0x1e8 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD27_OFFSET 0x1ea +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD28_OFFSET 0x1ec +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD29_OFFSET 0x1ee +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD30_OFFSET 0x1f0 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD31_OFFSET 0x1f2 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD32_OFFSET 0x1f4 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD33_OFFSET 0x1f6 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD34_OFFSET 0x1f8 +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD35_OFFSET 0x1fa +#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD36_OFFSET 0x1fc + +/* Note that 34xx TRM has SAD2D instead of CHASSIS for these */ +#define OMAP3_CONTROL_PADCONF_CHASSIS_CLK26MI_OFFSET 0x1fe +#define OMAP3_CONTROL_PADCONF_CHASSIS_NRESPWRON_OFFSET 0x200 +#define OMAP3_CONTROL_PADCONF_CHASSIS_NRESWARW_OFFSET 0x202 +#define OMAP3_CONTROL_PADCONF_CHASSIS_NIRQ_OFFSET 0x204 +#define OMAP3_CONTROL_PADCONF_CHASSIS_FIQ_OFFSET 0x206 +#define OMAP3_CONTROL_PADCONF_CHASSIS_ARMIRQ_OFFSET 0x208 +#define OMAP3_CONTROL_PADCONF_CHASSIS_IVAIRQ_OFFSET 0x20a +#define OMAP3_CONTROL_PADCONF_CHASSIS_DMAREQ0_OFFSET 0x20c +#define OMAP3_CONTROL_PADCONF_CHASSIS_DMAREQ1_OFFSET 0x20e +#define OMAP3_CONTROL_PADCONF_CHASSIS_DMAREQ2_OFFSET 0x210 +#define OMAP3_CONTROL_PADCONF_CHASSIS_DMAREQ3_OFFSET 0x212 +#define OMAP3_CONTROL_PADCONF_CHASSIS_NTRST_OFFSET 0x214 +#define OMAP3_CONTROL_PADCONF_CHASSIS_TDI_OFFSET 0x216 +#define OMAP3_CONTROL_PADCONF_CHASSIS_TDO_OFFSET 0x218 +#define OMAP3_CONTROL_PADCONF_CHASSIS_TMS_OFFSET 0x21a +#define OMAP3_CONTROL_PADCONF_CHASSIS_TCK_OFFSET 0x21c +#define OMAP3_CONTROL_PADCONF_CHASSIS_RTCK_OFFSET 0x21e +#define OMAP3_CONTROL_PADCONF_CHASSIS_MSTDBY_OFFSET 0x220 +#define OMAP3_CONTROL_PADCONF_CHASSIS_IDLEREQ_OFFSET 0x222 +#define OMAP3_CONTROL_PADCONF_CHASSIS_IDLEACK_OFFSET 0x224 + +#define OMAP3_CONTROL_PADCONF_SAD2D_MWRITE_OFFSET 0x226 +#define OMAP3_CONTROL_PADCONF_SAD2D_SWRITE_OFFSET 0x228 +#define OMAP3_CONTROL_PADCONF_SAD2D_MREAD_OFFSET 0x22a +#define OMAP3_CONTROL_PADCONF_SAD2D_SREAD_OFFSET 0x22c +#define OMAP3_CONTROL_PADCONF_SAD2D_MBUSFLAG_OFFSET 0x22e +#define OMAP3_CONTROL_PADCONF_SAD2D_SBUSFLAG_OFFSET 0x230 +#define OMAP3_CONTROL_PADCONF_SDRC_CKE0_OFFSET 0x232 +#define OMAP3_CONTROL_PADCONF_SDRC_CKE1_OFFSET 0x234 + +/* 36xx only */ +#define OMAP3_CONTROL_PADCONF_GPMC_A11_OFFSET 0x236 +#define OMAP3_CONTROL_PADCONF_SDRC_BA0_OFFSET 0x570 +#define OMAP3_CONTROL_PADCONF_SDRC_BA1_OFFSET 0x572 +#define OMAP3_CONTROL_PADCONF_SDRC_A0_OFFSET 0x574 +#define OMAP3_CONTROL_PADCONF_SDRC_A1_OFFSET 0x576 +#define OMAP3_CONTROL_PADCONF_SDRC_A2_OFFSET 0x578 +#define OMAP3_CONTROL_PADCONF_SDRC_A3_OFFSET 0x57a +#define OMAP3_CONTROL_PADCONF_SDRC_A4_OFFSET 0x57c +#define OMAP3_CONTROL_PADCONF_SDRC_A5_OFFSET 0x57e +#define OMAP3_CONTROL_PADCONF_SDRC_A6_OFFSET 0x580 +#define OMAP3_CONTROL_PADCONF_SDRC_A7_OFFSET 0x582 +#define OMAP3_CONTROL_PADCONF_SDRC_A8_OFFSET 0x584 +#define OMAP3_CONTROL_PADCONF_SDRC_A9_OFFSET 0x586 +#define OMAP3_CONTROL_PADCONF_SDRC_A10_OFFSET 0x588 +#define OMAP3_CONTROL_PADCONF_SDRC_A11_OFFSET 0x58a +#define OMAP3_CONTROL_PADCONF_SDRC_A12_OFFSET 0x58c +#define OMAP3_CONTROL_PADCONF_SDRC_A13_OFFSET 0x58e +#define OMAP3_CONTROL_PADCONF_SDRC_A14_OFFSET 0x590 +#define OMAP3_CONTROL_PADCONF_SDRC_NCS0_OFFSET 0x592 +#define OMAP3_CONTROL_PADCONF_SDRC_NCS1_OFFSET 0x594 +#define OMAP3_CONTROL_PADCONF_SDRC_NCLK_OFFSET 0x596 +#define OMAP3_CONTROL_PADCONF_SDRC_NRAS_OFFSET 0x598 +#define OMAP3_CONTROL_PADCONF_SDRC_NCAS_OFFSET 0x59a +#define OMAP3_CONTROL_PADCONF_SDRC_NWE_OFFSET 0x59c +#define OMAP3_CONTROL_PADCONF_SDRC_DM0_OFFSET 0x59e +#define OMAP3_CONTROL_PADCONF_SDRC_DM1_OFFSET 0x5a0 +#define OMAP3_CONTROL_PADCONF_SDRC_DM2_OFFSET 0x5a2 +#define OMAP3_CONTROL_PADCONF_SDRC_DM3_OFFSET 0x5a4 + +/* 36xx only, these are SDMMC1_DAT4 - DAT7 on 34xx */ +#define OMAP3_CONTROL_PADCONF_SIM_IO_OFFSET 0x120 +#define OMAP3_CONTROL_PADCONF_SIM_CLK_OFFSET 0x122 +#define OMAP3_CONTROL_PADCONF_SIM_PWRCTRL_OFFSET 0x124 +#define OMAP3_CONTROL_PADCONF_SIM_RST_OFFSET 0x126 + +#define OMAP3_CONTROL_PADCONF_ETK_CLK_OFFSET 0x5a8 +#define OMAP3_CONTROL_PADCONF_ETK_CTL_OFFSET 0x5aa +#define OMAP3_CONTROL_PADCONF_ETK_D0_OFFSET 0x5ac +#define OMAP3_CONTROL_PADCONF_ETK_D1_OFFSET 0x5ae +#define OMAP3_CONTROL_PADCONF_ETK_D2_OFFSET 0x5b0 +#define OMAP3_CONTROL_PADCONF_ETK_D3_OFFSET 0x5b2 +#define OMAP3_CONTROL_PADCONF_ETK_D4_OFFSET 0x5b4 +#define OMAP3_CONTROL_PADCONF_ETK_D5_OFFSET 0x5b6 +#define OMAP3_CONTROL_PADCONF_ETK_D6_OFFSET 0x5b8 +#define OMAP3_CONTROL_PADCONF_ETK_D7_OFFSET 0x5ba +#define OMAP3_CONTROL_PADCONF_ETK_D8_OFFSET 0x5bc +#define OMAP3_CONTROL_PADCONF_ETK_D9_OFFSET 0x5be +#define OMAP3_CONTROL_PADCONF_ETK_D10_OFFSET 0x5c0 +#define OMAP3_CONTROL_PADCONF_ETK_D11_OFFSET 0x5c2 +#define OMAP3_CONTROL_PADCONF_ETK_D12_OFFSET 0x5c4 +#define OMAP3_CONTROL_PADCONF_ETK_D13_OFFSET 0x5c6 +#define OMAP3_CONTROL_PADCONF_ETK_D14_OFFSET 0x5c8 +#define OMAP3_CONTROL_PADCONF_ETK_D15_OFFSET 0x5ca +#define OMAP3_CONTROL_PADCONF_I2C4_SCL_OFFSET 0x9d0 +#define OMAP3_CONTROL_PADCONF_I2C4_SDA_OFFSET 0x9d2 +#define OMAP3_CONTROL_PADCONF_SYS_32K_OFFSET 0x9d4 +#define OMAP3_CONTROL_PADCONF_SYS_CLKREQ_OFFSET 0x9d6 +#define OMAP3_CONTROL_PADCONF_SYS_NRESWARM_OFFSET 0x9d8 +#define OMAP3_CONTROL_PADCONF_SYS_BOOT0_OFFSET 0x9da +#define OMAP3_CONTROL_PADCONF_SYS_BOOT1_OFFSET 0x9dc +#define OMAP3_CONTROL_PADCONF_SYS_BOOT2_OFFSET 0x9de +#define OMAP3_CONTROL_PADCONF_SYS_BOOT3_OFFSET 0x9e0 +#define OMAP3_CONTROL_PADCONF_SYS_BOOT4_OFFSET 0x9e2 +#define OMAP3_CONTROL_PADCONF_SYS_BOOT5_OFFSET 0x9e4 +#define OMAP3_CONTROL_PADCONF_SYS_BOOT6_OFFSET 0x9e6 +#define OMAP3_CONTROL_PADCONF_SYS_OFF_MODE_OFFSET 0x9e8 +#define OMAP3_CONTROL_PADCONF_SYS_CLKOUT1_OFFSET 0x9ea +#define OMAP3_CONTROL_PADCONF_JTAG_NTRST_OFFSET 0x9ec +#define OMAP3_CONTROL_PADCONF_JTAG_TCK_OFFSET 0x9ee +#define OMAP3_CONTROL_PADCONF_JTAG_TMS_TMSC_OFFSET 0x9f0 +#define OMAP3_CONTROL_PADCONF_JTAG_TDI_OFFSET 0x9f2 +#define OMAP3_CONTROL_PADCONF_JTAG_EMU0_OFFSET 0x9f4 +#define OMAP3_CONTROL_PADCONF_JTAG_EMU1_OFFSET 0x9f6 +#define OMAP3_CONTROL_PADCONF_SAD2D_SWAKEUP_OFFSET 0xa1c +#define OMAP3_CONTROL_PADCONF_JTAG_RTCK_OFFSET 0xa1e +#define OMAP3_CONTROL_PADCONF_JTAG_TDO_OFFSET 0xa20 + +#define OMAP3_CONTROL_PADCONF_MUX_SIZE \ + (OMAP3_CONTROL_PADCONF_JTAG_TDO_OFFSET + 0x2) diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S index 4afadba094770133ba9115f38cde100cd484a539..aa3f65c2ac973a70e562123d423fa70a3ddb933d 100644 --- a/arch/arm/mach-omap2/omap-headsmp.S +++ b/arch/arm/mach-omap2/omap-headsmp.S @@ -27,20 +27,39 @@ * OMAP4 specific entry point for secondary CPU to jump from ROM * code. This routine also provides a holding flag into which * secondary core is held until we're ready for it to initialise. - * The primary core will update the this flag using a hardware - * register AuxCoreBoot1. + * The primary core will update this flag using a hardware + * register AuxCoreBoot0. */ ENTRY(omap_secondary_startup) - mrc p15, 0, r0, c0, c0, 5 - and r0, r0, #0x0f -hold: ldr r1, =OMAP4_AUX_CORE_BOOT1_PA @ read from AuxCoreBoot1 - ldr r2, [r1] - cmp r2, r0 +hold: ldr r12,=0x103 + dsb + smc @ read from AuxCoreBoot0 + mov r0, r0, lsr #9 + mrc p15, 0, r4, c0, c0, 5 + and r4, r4, #0x0f + cmp r0, r4 bne hold /* - * we've been released from the cpu_release,secondary_stack + * we've been released from the wait loop,secondary_stack * should now contain the SVC stack for this core */ b secondary_startup +END(omap_secondary_startup) + +ENTRY(omap_modify_auxcoreboot0) + stmfd sp!, {r1-r12, lr} + ldr r12, =0x104 + dsb + smc + ldmfd sp!, {r1-r12, pc} +END(omap_modify_auxcoreboot0) + +ENTRY(omap_auxcoreboot_addr) + stmfd sp!, {r2-r12, lr} + ldr r12, =0x105 + dsb + smc + ldmfd sp!, {r2-r12, pc} +END(omap_auxcoreboot_addr) diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index 4890bcf4dadd2fc556e0bc6e797e5df3cf3c356e..38153e5fbca0106bbc7314f86467ddd857b69fe4 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -17,19 +17,15 @@ */ #include #include -#include #include #include +#include #include #include #include #include -/* Registers used for communicating startup information */ -static void __iomem *omap4_auxcoreboot_reg0; -static void __iomem *omap4_auxcoreboot_reg1; - /* SCU base address */ static void __iomem *scu_base; @@ -65,8 +61,6 @@ void __cpuinit platform_secondary_init(unsigned int cpu) int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) { - unsigned long timeout; - /* * Set synchronisation state between this boot processor * and the secondary one @@ -74,18 +68,15 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) spin_lock(&boot_lock); /* - * Update the AuxCoreBoot1 with boot state for secondary core. + * Update the AuxCoreBoot0 with boot state for secondary core. * omap_secondary_startup() routine will hold the secondary core till * the AuxCoreBoot1 register is updated with cpu state * A barrier is added to ensure that write buffer is drained */ - __raw_writel(cpu, omap4_auxcoreboot_reg1); + omap_modify_auxcoreboot0(0x200, 0x0); + flush_cache_all(); smp_wmb(); - timeout = jiffies + (1 * HZ); - while (time_before(jiffies, timeout)) - ; - /* * Now the secondary core is starting up let it run its * calibrations, then wait for it to finish @@ -99,17 +90,18 @@ static void __init wakeup_secondary(void) { /* * Write the address of secondary startup routine into the - * AuxCoreBoot0 where ROM code will jump and start executing + * AuxCoreBoot1 where ROM code will jump and start executing * on secondary core once out of WFE * A barrier is added to ensure that write buffer is drained */ - __raw_writel(virt_to_phys(omap_secondary_startup), \ - omap4_auxcoreboot_reg0); + omap_auxcoreboot_addr(virt_to_phys(omap_secondary_startup)); smp_wmb(); /* * Send a 'sev' to wake the secondary core from WFE. + * Drain the outstanding writes to memory */ + dsb(); set_event(); mb(); } @@ -136,7 +128,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) { unsigned int ncores = get_core_count(); unsigned int cpu = smp_processor_id(); - void __iomem *omap4_wkupgen_base; int i; /* sanity check */ @@ -168,12 +159,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) for (i = 0; i < max_cpus; i++) set_cpu_present(i, true); - /* Never released */ - omap4_wkupgen_base = ioremap(OMAP44XX_WKUPGEN_BASE, SZ_4K); - BUG_ON(!omap4_wkupgen_base); - omap4_auxcoreboot_reg0 = omap4_wkupgen_base + 0x800; - omap4_auxcoreboot_reg1 = omap4_wkupgen_base + 0x804; - if (max_cpus > 1) { /* * Enable the local timer or broadcast device for the diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 633b216a8b26a14ddb33d4f483f1fc624a446b6b..d8c8545875b18b84aa89449ffa87911d687d129e 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -45,6 +45,7 @@ #include #include +#include #include #include #include @@ -209,6 +210,32 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v) return 0; } +/** + * _set_module_autoidle: set the OCP_SYSCONFIG AUTOIDLE field in @v + * @oh: struct omap_hwmod * + * @autoidle: desired AUTOIDLE bitfield value (0 or 1) + * @v: pointer to register contents to modify + * + * Update the module autoidle bit in @v to be @autoidle for the @oh + * hwmod. The autoidle bit controls whether the module can gate + * internal clocks automatically when it isn't doing anything; the + * exact function of this bit varies on a per-module basis. This + * function does not write to the hardware. Returns -EINVAL upon + * error or 0 upon success. + */ +static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle, + u32 *v) +{ + if (!oh->sysconfig || + !(oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE)) + return -EINVAL; + + *v &= ~SYSC_AUTOIDLE_MASK; + *v |= autoidle << SYSC_AUTOIDLE_SHIFT; + + return 0; +} + /** * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware * @oh: struct omap_hwmod * @@ -326,6 +353,9 @@ static int _init_main_clk(struct omap_hwmod *oh) ret = -EINVAL; oh->_clk = c; + WARN(!c->clkdm, "omap_hwmod: %s: missing clockdomain for %s.\n", + oh->clkdev_con_id, c->name); + return ret; } @@ -557,8 +587,19 @@ static void _sysc_enable(struct omap_hwmod *oh) _set_master_standbymode(oh, idlemode, &v); } - /* XXX OCP AUTOIDLE bit? */ + if (oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE) { + idlemode = (oh->flags & HWMOD_NO_OCP_AUTOIDLE) ? + 0 : 1; + _set_module_autoidle(oh, idlemode, &v); + } + + /* XXX OCP ENAWAKEUP bit? */ + /* + * XXX The clock framework should handle this, by + * calling into this code. But this must wait until the + * clock structures are tagged with omap_hwmod entries + */ if (oh->flags & HWMOD_SET_DEFAULT_CLOCKACT && oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY) _set_clockactivity(oh, oh->sysconfig->clockact, &v); @@ -622,7 +663,8 @@ static void _sysc_shutdown(struct omap_hwmod *oh) if (oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE) _set_master_standbymode(oh, HWMOD_IDLEMODE_FORCE, &v); - /* XXX clear OCP AUTOIDLE bit? */ + if (oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE) + _set_module_autoidle(oh, 1, &v); _write_sysconfig(v, oh); } @@ -736,7 +778,7 @@ static int _wait_target_ready(struct omap_hwmod *oh) static int _reset(struct omap_hwmod *oh) { u32 r, v; - int c; + int c = 0; if (!oh->sysconfig || !(oh->sysconfig->sysc_flags & SYSC_HAS_SOFTRESET) || @@ -758,13 +800,9 @@ static int _reset(struct omap_hwmod *oh) return r; _write_sysconfig(v, oh); - c = 0; - while (c < MAX_MODULE_RESET_WAIT && - !(omap_hwmod_readl(oh, oh->sysconfig->syss_offs) & - SYSS_RESETDONE_MASK)) { - udelay(1); - c++; - } + omap_test_timeout((omap_hwmod_readl(oh, oh->sysconfig->syss_offs) & + SYSS_RESETDONE_MASK), + MAX_MODULE_RESET_WAIT, c); if (c == MAX_MODULE_RESET_WAIT) WARN(1, "omap_hwmod: %s: failed to reset in %d usec\n", @@ -883,33 +921,6 @@ static int _shutdown(struct omap_hwmod *oh) return 0; } -/** - * _write_clockact_lock - set the module's clockactivity bits - * @oh: struct omap_hwmod * - * @clockact: CLOCKACTIVITY field bits - * - * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh - * OCP_SYSCONFIG register. Returns -EINVAL if the hwmod is in the - * wrong state or returns 0. - */ -static int _write_clockact_lock(struct omap_hwmod *oh, u8 clockact) -{ - u32 v; - - if (!oh->sysconfig || - !(oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY)) - return -EINVAL; - - mutex_lock(&omap_hwmod_mutex); - v = oh->_sysc_cache; - _set_clockactivity(oh, clockact, &v); - _write_sysconfig(v, oh); - mutex_unlock(&omap_hwmod_mutex); - - return 0; -} - - /** * _setup - do initial configuration of omap_hwmod * @oh: struct omap_hwmod * @@ -948,11 +959,19 @@ static int _setup(struct omap_hwmod *oh) _enable(oh); - if (!(oh->flags & HWMOD_INIT_NO_RESET)) - _reset(oh); - - /* XXX OCP AUTOIDLE bit? */ - /* XXX OCP ENAWAKEUP bit? */ + if (!(oh->flags & HWMOD_INIT_NO_RESET)) { + /* + * XXX Do the OCP_SYSCONFIG bits need to be + * reprogrammed after a reset? If not, then this can + * be removed. If they do, then probably the + * _enable() function should be split to avoid the + * rewrite of the OCP_SYSCONFIG register. + */ + if (oh->sysconfig) { + _update_sysc_cache(oh); + _sysc_enable(oh); + } + } if (!(oh->flags & HWMOD_INIT_NO_IDLE)) _idle(oh); @@ -1348,8 +1367,9 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res) /* For each IRQ, DMA, memory area, fill in array.*/ for (i = 0; i < oh->mpu_irqs_cnt; i++) { - (res + r)->start = *(oh->mpu_irqs + i); - (res + r)->end = *(oh->mpu_irqs + i); + (res + r)->name = (oh->mpu_irqs + i)->name; + (res + r)->start = (oh->mpu_irqs + i)->irq; + (res + r)->end = (oh->mpu_irqs + i)->irq; (res + r)->flags = IORESOURCE_IRQ; r++; } @@ -1453,62 +1473,6 @@ int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh, return _del_initiator_dep(oh, init_oh); } -/** - * omap_hwmod_set_clockact_none - set clockactivity test to BOTH - * @oh: struct omap_hwmod * - * - * On some modules, this function can affect the wakeup latency vs. - * power consumption balance. Intended to be called by the - * omap_device layer. Passes along the return value from - * _write_clockact_lock(). - */ -int omap_hwmod_set_clockact_both(struct omap_hwmod *oh) -{ - return _write_clockact_lock(oh, CLOCKACT_TEST_BOTH); -} - -/** - * omap_hwmod_set_clockact_none - set clockactivity test to MAIN - * @oh: struct omap_hwmod * - * - * On some modules, this function can affect the wakeup latency vs. - * power consumption balance. Intended to be called by the - * omap_device layer. Passes along the return value from - * _write_clockact_lock(). - */ -int omap_hwmod_set_clockact_main(struct omap_hwmod *oh) -{ - return _write_clockact_lock(oh, CLOCKACT_TEST_MAIN); -} - -/** - * omap_hwmod_set_clockact_none - set clockactivity test to ICLK - * @oh: struct omap_hwmod * - * - * On some modules, this function can affect the wakeup latency vs. - * power consumption balance. Intended to be called by the - * omap_device layer. Passes along the return value from - * _write_clockact_lock(). - */ -int omap_hwmod_set_clockact_iclk(struct omap_hwmod *oh) -{ - return _write_clockact_lock(oh, CLOCKACT_TEST_ICLK); -} - -/** - * omap_hwmod_set_clockact_none - set clockactivity test to NONE - * @oh: struct omap_hwmod * - * - * On some modules, this function can affect the wakeup latency vs. - * power consumption balance. Intended to be called by the - * omap_device layer. Passes along the return value from - * _write_clockact_lock(). - */ -int omap_hwmod_set_clockact_none(struct omap_hwmod *oh) -{ - return _write_clockact_lock(oh, CLOCKACT_TEST_NONE); -} - /** * omap_hwmod_enable_wakeup - allow device to wake up the system * @oh: struct omap_hwmod * diff --git a/arch/arm/mach-omap2/opp2420_data.c b/arch/arm/mach-omap2/opp2420_data.c new file mode 100644 index 0000000000000000000000000000000000000000..126a9396b3a8e9c8b39609c71e136c15a2aa2756 --- /dev/null +++ b/arch/arm/mach-omap2/opp2420_data.c @@ -0,0 +1,126 @@ +/* + * opp2420_data.c - old-style "OPP" table for OMAP2420 + * + * Copyright (C) 2005-2009 Texas Instruments, Inc. + * Copyright (C) 2004-2009 Nokia Corporation + * + * Richard Woodruff + * + * The OMAP2 processor can be run at several discrete 'PRCM configurations'. + * These configurations are characterized by voltage and speed for clocks. + * The device is only validated for certain combinations. One way to express + * these combinations is via the 'ratio's' which the clocks operate with + * respect to each other. These ratio sets are for a given voltage/DPLL + * setting. All configurations can be described by a DPLL setting and a ratio + * There are 3 ratio sets for the 2430 and X ratio sets for 2420. + * + * 2430 differs from 2420 in that there are no more phase synchronizers used. + * They both have a slightly different clock domain setup. 2420(iva1,dsp) vs + * 2430 (iva2.1, NOdsp, mdm) + * + * XXX Missing voltage data. + * + * THe format described in this file is deprecated. Once a reasonable + * OPP API exists, the data in this file should be converted to use it. + * + * This is technically part of the OMAP2xxx clock code. + */ + +#include "opp2xxx.h" +#include "sdrc.h" +#include "clock.h" + +/*------------------------------------------------------------------------- + * Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated. + * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU, + * CM_CLKSEL_DSP, CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL, + * CM_CLKSEL2_PLL, CM_CLKSEL_MDM + * + * Filling in table based on H4 boards and 2430-SDPs variants available. + * There are quite a few more rates combinations which could be defined. + * + * When multiple values are defined the start up will try and choose the + * fastest one. If a 'fast' value is defined, then automatically, the /2 + * one should be included as it can be used. Generally having more that + * one fast set does not make sense, as static timings need to be changed + * to change the set. The exception is the bypass setting which is + * availble for low power bypass. + * + * Note: This table needs to be sorted, fastest to slowest. + *-------------------------------------------------------------------------*/ +const struct prcm_config omap2420_rate_table[] = { + /* PRCM I - FAST */ + {S12M, S660M, S330M, RI_CM_CLKSEL_MPU_VAL, /* 330MHz ARM */ + RI_CM_CLKSEL_DSP_VAL, RI_CM_CLKSEL_GFX_VAL, + RI_CM_CLKSEL1_CORE_VAL, MI_CM_CLKSEL1_PLL_12_VAL, + MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_165MHz, + RATE_IN_242X}, + + /* PRCM II - FAST */ + {S12M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL, /* 300MHz ARM */ + RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL, + RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL, + MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz, + RATE_IN_242X}, + + {S13M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL, /* 300MHz ARM */ + RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL, + RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL, + MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz, + RATE_IN_242X}, + + /* PRCM III - FAST */ + {S12M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */ + RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL, + RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL, + MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz, + RATE_IN_242X}, + + {S13M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */ + RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL, + RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL, + MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz, + RATE_IN_242X}, + + /* PRCM II - SLOW */ + {S12M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL, /* 150MHz ARM */ + RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL, + RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL, + MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz, + RATE_IN_242X}, + + {S13M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL, /* 150MHz ARM */ + RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL, + RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL, + MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz, + RATE_IN_242X}, + + /* PRCM III - SLOW */ + {S12M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */ + RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL, + RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL, + MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz, + RATE_IN_242X}, + + {S13M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */ + RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL, + RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL, + MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz, + RATE_IN_242X}, + + /* PRCM-VII (boot-bypass) */ + {S12M, S12M, S12M, RVII_CM_CLKSEL_MPU_VAL, /* 12MHz ARM*/ + RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL, + RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_12_VAL, + MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_BYPASS, + RATE_IN_242X}, + + /* PRCM-VII (boot-bypass) */ + {S13M, S13M, S13M, RVII_CM_CLKSEL_MPU_VAL, /* 13MHz ARM */ + RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL, + RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_13_VAL, + MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_BYPASS, + RATE_IN_242X}, + + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +}; diff --git a/arch/arm/mach-omap2/opp2430_data.c b/arch/arm/mach-omap2/opp2430_data.c new file mode 100644 index 0000000000000000000000000000000000000000..edb81672c8446f3a334986d1604985e48b37c50f --- /dev/null +++ b/arch/arm/mach-omap2/opp2430_data.c @@ -0,0 +1,133 @@ +/* + * opp2420_data.c - old-style "OPP" table for OMAP2420 + * + * Copyright (C) 2005-2009 Texas Instruments, Inc. + * Copyright (C) 2004-2009 Nokia Corporation + * + * Richard Woodruff + * + * The OMAP2 processor can be run at several discrete 'PRCM configurations'. + * These configurations are characterized by voltage and speed for clocks. + * The device is only validated for certain combinations. One way to express + * these combinations is via the 'ratio's' which the clocks operate with + * respect to each other. These ratio sets are for a given voltage/DPLL + * setting. All configurations can be described by a DPLL setting and a ratio + * There are 3 ratio sets for the 2430 and X ratio sets for 2420. + * + * 2430 differs from 2420 in that there are no more phase synchronizers used. + * They both have a slightly different clock domain setup. 2420(iva1,dsp) vs + * 2430 (iva2.1, NOdsp, mdm) + * + * XXX Missing voltage data. + * + * THe format described in this file is deprecated. Once a reasonable + * OPP API exists, the data in this file should be converted to use it. + * + * This is technically part of the OMAP2xxx clock code. + */ + +#include "opp2xxx.h" +#include "sdrc.h" +#include "clock.h" + +/*------------------------------------------------------------------------- + * Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated. + * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU, + * CM_CLKSEL_DSP, CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL, + * CM_CLKSEL2_PLL, CM_CLKSEL_MDM + * + * Filling in table based on H4 boards and 2430-SDPs variants available. + * There are quite a few more rates combinations which could be defined. + * + * When multiple values are defined the start up will try and choose the + * fastest one. If a 'fast' value is defined, then automatically, the /2 + * one should be included as it can be used. Generally having more that + * one fast set does not make sense, as static timings need to be changed + * to change the set. The exception is the bypass setting which is + * availble for low power bypass. + * + * Note: This table needs to be sorted, fastest to slowest. + *-------------------------------------------------------------------------*/ +const struct prcm_config omap2430_rate_table[] = { + /* PRCM #4 - ratio2 (ES2.1) - FAST */ + {S13M, S798M, S399M, R2_CM_CLKSEL_MPU_VAL, /* 399MHz ARM */ + R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL, + R2_CM_CLKSEL1_CORE_VAL, M4_CM_CLKSEL1_PLL_13_VAL, + MX_CLKSEL2_PLL_2x_VAL, R2_CM_CLKSEL_MDM_VAL, + SDRC_RFR_CTRL_133MHz, + RATE_IN_243X}, + + /* PRCM #2 - ratio1 (ES2) - FAST */ + {S13M, S658M, S329M, R1_CM_CLKSEL_MPU_VAL, /* 330MHz ARM */ + R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, + R1_CM_CLKSEL1_CORE_VAL, M2_CM_CLKSEL1_PLL_13_VAL, + MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL, + SDRC_RFR_CTRL_165MHz, + RATE_IN_243X}, + + /* PRCM #5a - ratio1 - FAST */ + {S13M, S532M, S266M, R1_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */ + R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, + R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL, + MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL, + SDRC_RFR_CTRL_133MHz, + RATE_IN_243X}, + + /* PRCM #5b - ratio1 - FAST */ + {S13M, S400M, S200M, R1_CM_CLKSEL_MPU_VAL, /* 200MHz ARM */ + R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, + R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL, + MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL, + SDRC_RFR_CTRL_100MHz, + RATE_IN_243X}, + + /* PRCM #4 - ratio1 (ES2.1) - SLOW */ + {S13M, S399M, S199M, R2_CM_CLKSEL_MPU_VAL, /* 200MHz ARM */ + R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL, + R2_CM_CLKSEL1_CORE_VAL, M4_CM_CLKSEL1_PLL_13_VAL, + MX_CLKSEL2_PLL_1x_VAL, R2_CM_CLKSEL_MDM_VAL, + SDRC_RFR_CTRL_133MHz, + RATE_IN_243X}, + + /* PRCM #2 - ratio1 (ES2) - SLOW */ + {S13M, S329M, S164M, R1_CM_CLKSEL_MPU_VAL, /* 165MHz ARM */ + R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, + R1_CM_CLKSEL1_CORE_VAL, M2_CM_CLKSEL1_PLL_13_VAL, + MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL, + SDRC_RFR_CTRL_165MHz, + RATE_IN_243X}, + + /* PRCM #5a - ratio1 - SLOW */ + {S13M, S266M, S133M, R1_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */ + R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, + R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL, + MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL, + SDRC_RFR_CTRL_133MHz, + RATE_IN_243X}, + + /* PRCM #5b - ratio1 - SLOW*/ + {S13M, S200M, S100M, R1_CM_CLKSEL_MPU_VAL, /* 100MHz ARM */ + R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL, + R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL, + MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL, + SDRC_RFR_CTRL_100MHz, + RATE_IN_243X}, + + /* PRCM-boot/bypass */ + {S13M, S13M, S13M, RB_CM_CLKSEL_MPU_VAL, /* 13Mhz */ + RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL, + RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_13_VAL, + MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL, + SDRC_RFR_CTRL_BYPASS, + RATE_IN_243X}, + + /* PRCM-boot/bypass */ + {S12M, S12M, S12M, RB_CM_CLKSEL_MPU_VAL, /* 12Mhz */ + RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL, + RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_12_VAL, + MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL, + SDRC_RFR_CTRL_BYPASS, + RATE_IN_243X}, + + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +}; diff --git a/arch/arm/mach-omap2/opp2xxx.h b/arch/arm/mach-omap2/opp2xxx.h new file mode 100644 index 0000000000000000000000000000000000000000..ed6df04e2f291acaad717b03eed4b842d0778fce --- /dev/null +++ b/arch/arm/mach-omap2/opp2xxx.h @@ -0,0 +1,424 @@ +/* + * opp2xxx.h - macros for old-style OMAP2xxx "OPP" definitions + * + * Copyright (C) 2005-2009 Texas Instruments, Inc. + * Copyright (C) 2004-2009 Nokia Corporation + * + * Richard Woodruff + * + * The OMAP2 processor can be run at several discrete 'PRCM configurations'. + * These configurations are characterized by voltage and speed for clocks. + * The device is only validated for certain combinations. One way to express + * these combinations is via the 'ratio's' which the clocks operate with + * respect to each other. These ratio sets are for a given voltage/DPLL + * setting. All configurations can be described by a DPLL setting and a ratio + * There are 3 ratio sets for the 2430 and X ratio sets for 2420. + * + * 2430 differs from 2420 in that there are no more phase synchronizers used. + * They both have a slightly different clock domain setup. 2420(iva1,dsp) vs + * 2430 (iva2.1, NOdsp, mdm) + * + * XXX Missing voltage data. + * + * THe format described in this file is deprecated. Once a reasonable + * OPP API exists, the data in this file should be converted to use it. + * + * This is technically part of the OMAP2xxx clock code. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_OPP2XXX_H +#define __ARCH_ARM_MACH_OMAP2_OPP2XXX_H + +/** + * struct prcm_config - define clock rates on a per-OPP basis (24xx) + * + * Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated. + * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP + * CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM + * + * This is deprecated. As soon as we have a decent OPP API, we should + * move all this stuff to it. + */ +struct prcm_config { + unsigned long xtal_speed; /* crystal rate */ + unsigned long dpll_speed; /* dpll: out*xtal*M/(N-1)table_recalc */ + unsigned long mpu_speed; /* speed of MPU */ + unsigned long cm_clksel_mpu; /* mpu divider */ + unsigned long cm_clksel_dsp; /* dsp+iva1 div(2420), iva2.1(2430) */ + unsigned long cm_clksel_gfx; /* gfx dividers */ + unsigned long cm_clksel1_core; /* major subsystem dividers */ + unsigned long cm_clksel1_pll; /* m,n */ + unsigned long cm_clksel2_pll; /* dpllx1 or x2 out */ + unsigned long cm_clksel_mdm; /* modem dividers 2430 only */ + unsigned long base_sdrc_rfr; /* base refresh timing for a set */ + unsigned char flags; +}; + + +/* Core fields for cm_clksel, not ratio governed */ +#define RX_CLKSEL_DSS1 (0x10 << 8) +#define RX_CLKSEL_DSS2 (0x0 << 13) +#define RX_CLKSEL_SSI (0x5 << 20) + +/*------------------------------------------------------------------------- + * Voltage/DPLL ratios + *-------------------------------------------------------------------------*/ + +/* 2430 Ratio's, 2430-Ratio Config 1 */ +#define R1_CLKSEL_L3 (4 << 0) +#define R1_CLKSEL_L4 (2 << 5) +#define R1_CLKSEL_USB (4 << 25) +#define R1_CM_CLKSEL1_CORE_VAL (R1_CLKSEL_USB | RX_CLKSEL_SSI | \ + RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \ + R1_CLKSEL_L4 | R1_CLKSEL_L3) +#define R1_CLKSEL_MPU (2 << 0) +#define R1_CM_CLKSEL_MPU_VAL R1_CLKSEL_MPU +#define R1_CLKSEL_DSP (2 << 0) +#define R1_CLKSEL_DSP_IF (2 << 5) +#define R1_CM_CLKSEL_DSP_VAL (R1_CLKSEL_DSP | R1_CLKSEL_DSP_IF) +#define R1_CLKSEL_GFX (2 << 0) +#define R1_CM_CLKSEL_GFX_VAL R1_CLKSEL_GFX +#define R1_CLKSEL_MDM (4 << 0) +#define R1_CM_CLKSEL_MDM_VAL R1_CLKSEL_MDM + +/* 2430-Ratio Config 2 */ +#define R2_CLKSEL_L3 (6 << 0) +#define R2_CLKSEL_L4 (2 << 5) +#define R2_CLKSEL_USB (2 << 25) +#define R2_CM_CLKSEL1_CORE_VAL (R2_CLKSEL_USB | RX_CLKSEL_SSI | \ + RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \ + R2_CLKSEL_L4 | R2_CLKSEL_L3) +#define R2_CLKSEL_MPU (2 << 0) +#define R2_CM_CLKSEL_MPU_VAL R2_CLKSEL_MPU +#define R2_CLKSEL_DSP (2 << 0) +#define R2_CLKSEL_DSP_IF (3 << 5) +#define R2_CM_CLKSEL_DSP_VAL (R2_CLKSEL_DSP | R2_CLKSEL_DSP_IF) +#define R2_CLKSEL_GFX (2 << 0) +#define R2_CM_CLKSEL_GFX_VAL R2_CLKSEL_GFX +#define R2_CLKSEL_MDM (6 << 0) +#define R2_CM_CLKSEL_MDM_VAL R2_CLKSEL_MDM + +/* 2430-Ratio Bootm (BYPASS) */ +#define RB_CLKSEL_L3 (1 << 0) +#define RB_CLKSEL_L4 (1 << 5) +#define RB_CLKSEL_USB (1 << 25) +#define RB_CM_CLKSEL1_CORE_VAL (RB_CLKSEL_USB | RX_CLKSEL_SSI | \ + RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \ + RB_CLKSEL_L4 | RB_CLKSEL_L3) +#define RB_CLKSEL_MPU (1 << 0) +#define RB_CM_CLKSEL_MPU_VAL RB_CLKSEL_MPU +#define RB_CLKSEL_DSP (1 << 0) +#define RB_CLKSEL_DSP_IF (1 << 5) +#define RB_CM_CLKSEL_DSP_VAL (RB_CLKSEL_DSP | RB_CLKSEL_DSP_IF) +#define RB_CLKSEL_GFX (1 << 0) +#define RB_CM_CLKSEL_GFX_VAL RB_CLKSEL_GFX +#define RB_CLKSEL_MDM (1 << 0) +#define RB_CM_CLKSEL_MDM_VAL RB_CLKSEL_MDM + +/* 2420 Ratio Equivalents */ +#define RXX_CLKSEL_VLYNQ (0x12 << 15) +#define RXX_CLKSEL_SSI (0x8 << 20) + +/* 2420-PRCM III 532MHz core */ +#define RIII_CLKSEL_L3 (4 << 0) /* 133MHz */ +#define RIII_CLKSEL_L4 (2 << 5) /* 66.5MHz */ +#define RIII_CLKSEL_USB (4 << 25) /* 33.25MHz */ +#define RIII_CM_CLKSEL1_CORE_VAL (RIII_CLKSEL_USB | RXX_CLKSEL_SSI | \ + RXX_CLKSEL_VLYNQ | RX_CLKSEL_DSS2 | \ + RX_CLKSEL_DSS1 | RIII_CLKSEL_L4 | \ + RIII_CLKSEL_L3) +#define RIII_CLKSEL_MPU (2 << 0) /* 266MHz */ +#define RIII_CM_CLKSEL_MPU_VAL RIII_CLKSEL_MPU +#define RIII_CLKSEL_DSP (3 << 0) /* c5x - 177.3MHz */ +#define RIII_CLKSEL_DSP_IF (2 << 5) /* c5x - 88.67MHz */ +#define RIII_SYNC_DSP (1 << 7) /* Enable sync */ +#define RIII_CLKSEL_IVA (6 << 8) /* iva1 - 88.67MHz */ +#define RIII_SYNC_IVA (1 << 13) /* Enable sync */ +#define RIII_CM_CLKSEL_DSP_VAL (RIII_SYNC_IVA | RIII_CLKSEL_IVA | \ + RIII_SYNC_DSP | RIII_CLKSEL_DSP_IF | \ + RIII_CLKSEL_DSP) +#define RIII_CLKSEL_GFX (2 << 0) /* 66.5MHz */ +#define RIII_CM_CLKSEL_GFX_VAL RIII_CLKSEL_GFX + +/* 2420-PRCM II 600MHz core */ +#define RII_CLKSEL_L3 (6 << 0) /* 100MHz */ +#define RII_CLKSEL_L4 (2 << 5) /* 50MHz */ +#define RII_CLKSEL_USB (2 << 25) /* 50MHz */ +#define RII_CM_CLKSEL1_CORE_VAL (RII_CLKSEL_USB | RXX_CLKSEL_SSI | \ + RXX_CLKSEL_VLYNQ | RX_CLKSEL_DSS2 | \ + RX_CLKSEL_DSS1 | RII_CLKSEL_L4 | \ + RII_CLKSEL_L3) +#define RII_CLKSEL_MPU (2 << 0) /* 300MHz */ +#define RII_CM_CLKSEL_MPU_VAL RII_CLKSEL_MPU +#define RII_CLKSEL_DSP (3 << 0) /* c5x - 200MHz */ +#define RII_CLKSEL_DSP_IF (2 << 5) /* c5x - 100MHz */ +#define RII_SYNC_DSP (0 << 7) /* Bypass sync */ +#define RII_CLKSEL_IVA (3 << 8) /* iva1 - 200MHz */ +#define RII_SYNC_IVA (0 << 13) /* Bypass sync */ +#define RII_CM_CLKSEL_DSP_VAL (RII_SYNC_IVA | RII_CLKSEL_IVA | \ + RII_SYNC_DSP | RII_CLKSEL_DSP_IF | \ + RII_CLKSEL_DSP) +#define RII_CLKSEL_GFX (2 << 0) /* 50MHz */ +#define RII_CM_CLKSEL_GFX_VAL RII_CLKSEL_GFX + +/* 2420-PRCM I 660MHz core */ +#define RI_CLKSEL_L3 (4 << 0) /* 165MHz */ +#define RI_CLKSEL_L4 (2 << 5) /* 82.5MHz */ +#define RI_CLKSEL_USB (4 << 25) /* 41.25MHz */ +#define RI_CM_CLKSEL1_CORE_VAL (RI_CLKSEL_USB | \ + RXX_CLKSEL_SSI | RXX_CLKSEL_VLYNQ | \ + RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \ + RI_CLKSEL_L4 | RI_CLKSEL_L3) +#define RI_CLKSEL_MPU (2 << 0) /* 330MHz */ +#define RI_CM_CLKSEL_MPU_VAL RI_CLKSEL_MPU +#define RI_CLKSEL_DSP (3 << 0) /* c5x - 220MHz */ +#define RI_CLKSEL_DSP_IF (2 << 5) /* c5x - 110MHz */ +#define RI_SYNC_DSP (1 << 7) /* Activate sync */ +#define RI_CLKSEL_IVA (4 << 8) /* iva1 - 165MHz */ +#define RI_SYNC_IVA (0 << 13) /* Bypass sync */ +#define RI_CM_CLKSEL_DSP_VAL (RI_SYNC_IVA | RI_CLKSEL_IVA | \ + RI_SYNC_DSP | RI_CLKSEL_DSP_IF | \ + RI_CLKSEL_DSP) +#define RI_CLKSEL_GFX (1 << 0) /* 165MHz */ +#define RI_CM_CLKSEL_GFX_VAL RI_CLKSEL_GFX + +/* 2420-PRCM VII (boot) */ +#define RVII_CLKSEL_L3 (1 << 0) +#define RVII_CLKSEL_L4 (1 << 5) +#define RVII_CLKSEL_DSS1 (1 << 8) +#define RVII_CLKSEL_DSS2 (0 << 13) +#define RVII_CLKSEL_VLYNQ (1 << 15) +#define RVII_CLKSEL_SSI (1 << 20) +#define RVII_CLKSEL_USB (1 << 25) + +#define RVII_CM_CLKSEL1_CORE_VAL (RVII_CLKSEL_USB | RVII_CLKSEL_SSI | \ + RVII_CLKSEL_VLYNQ | \ + RVII_CLKSEL_DSS2 | RVII_CLKSEL_DSS1 | \ + RVII_CLKSEL_L4 | RVII_CLKSEL_L3) + +#define RVII_CLKSEL_MPU (1 << 0) /* all divide by 1 */ +#define RVII_CM_CLKSEL_MPU_VAL RVII_CLKSEL_MPU + +#define RVII_CLKSEL_DSP (1 << 0) +#define RVII_CLKSEL_DSP_IF (1 << 5) +#define RVII_SYNC_DSP (0 << 7) +#define RVII_CLKSEL_IVA (1 << 8) +#define RVII_SYNC_IVA (0 << 13) +#define RVII_CM_CLKSEL_DSP_VAL (RVII_SYNC_IVA | RVII_CLKSEL_IVA | \ + RVII_SYNC_DSP | RVII_CLKSEL_DSP_IF | \ + RVII_CLKSEL_DSP) + +#define RVII_CLKSEL_GFX (1 << 0) +#define RVII_CM_CLKSEL_GFX_VAL RVII_CLKSEL_GFX + +/*------------------------------------------------------------------------- + * 2430 Target modes: Along with each configuration the CPU has several + * modes which goes along with them. Modes mainly are the addition of + * describe DPLL combinations to go along with a ratio. + *-------------------------------------------------------------------------*/ + +/* Hardware governed */ +#define MX_48M_SRC (0 << 3) +#define MX_54M_SRC (0 << 5) +#define MX_APLLS_CLIKIN_12 (3 << 23) +#define MX_APLLS_CLIKIN_13 (2 << 23) +#define MX_APLLS_CLIKIN_19_2 (0 << 23) + +/* + * 2430 - standalone, 2*ref*M/(n+1), M/N is for exactness not relock speed + * #5a (ratio1) baseport-target, target DPLL = 266*2 = 532MHz + */ +#define M5A_DPLL_MULT_12 (133 << 12) +#define M5A_DPLL_DIV_12 (5 << 8) +#define M5A_CM_CLKSEL1_PLL_12_VAL (MX_48M_SRC | MX_54M_SRC | \ + M5A_DPLL_DIV_12 | M5A_DPLL_MULT_12 | \ + MX_APLLS_CLIKIN_12) +#define M5A_DPLL_MULT_13 (61 << 12) +#define M5A_DPLL_DIV_13 (2 << 8) +#define M5A_CM_CLKSEL1_PLL_13_VAL (MX_48M_SRC | MX_54M_SRC | \ + M5A_DPLL_DIV_13 | M5A_DPLL_MULT_13 | \ + MX_APLLS_CLIKIN_13) +#define M5A_DPLL_MULT_19 (55 << 12) +#define M5A_DPLL_DIV_19 (3 << 8) +#define M5A_CM_CLKSEL1_PLL_19_VAL (MX_48M_SRC | MX_54M_SRC | \ + M5A_DPLL_DIV_19 | M5A_DPLL_MULT_19 | \ + MX_APLLS_CLIKIN_19_2) +/* #5b (ratio1) target DPLL = 200*2 = 400MHz */ +#define M5B_DPLL_MULT_12 (50 << 12) +#define M5B_DPLL_DIV_12 (2 << 8) +#define M5B_CM_CLKSEL1_PLL_12_VAL (MX_48M_SRC | MX_54M_SRC | \ + M5B_DPLL_DIV_12 | M5B_DPLL_MULT_12 | \ + MX_APLLS_CLIKIN_12) +#define M5B_DPLL_MULT_13 (200 << 12) +#define M5B_DPLL_DIV_13 (12 << 8) + +#define M5B_CM_CLKSEL1_PLL_13_VAL (MX_48M_SRC | MX_54M_SRC | \ + M5B_DPLL_DIV_13 | M5B_DPLL_MULT_13 | \ + MX_APLLS_CLIKIN_13) +#define M5B_DPLL_MULT_19 (125 << 12) +#define M5B_DPLL_DIV_19 (31 << 8) +#define M5B_CM_CLKSEL1_PLL_19_VAL (MX_48M_SRC | MX_54M_SRC | \ + M5B_DPLL_DIV_19 | M5B_DPLL_MULT_19 | \ + MX_APLLS_CLIKIN_19_2) +/* + * #4 (ratio2), DPLL = 399*2 = 798MHz, L3=133MHz + */ +#define M4_DPLL_MULT_12 (133 << 12) +#define M4_DPLL_DIV_12 (3 << 8) +#define M4_CM_CLKSEL1_PLL_12_VAL (MX_48M_SRC | MX_54M_SRC | \ + M4_DPLL_DIV_12 | M4_DPLL_MULT_12 | \ + MX_APLLS_CLIKIN_12) + +#define M4_DPLL_MULT_13 (399 << 12) +#define M4_DPLL_DIV_13 (12 << 8) +#define M4_CM_CLKSEL1_PLL_13_VAL (MX_48M_SRC | MX_54M_SRC | \ + M4_DPLL_DIV_13 | M4_DPLL_MULT_13 | \ + MX_APLLS_CLIKIN_13) + +#define M4_DPLL_MULT_19 (145 << 12) +#define M4_DPLL_DIV_19 (6 << 8) +#define M4_CM_CLKSEL1_PLL_19_VAL (MX_48M_SRC | MX_54M_SRC | \ + M4_DPLL_DIV_19 | M4_DPLL_MULT_19 | \ + MX_APLLS_CLIKIN_19_2) + +/* + * #3 (ratio2) baseport-target, target DPLL = 330*2 = 660MHz + */ +#define M3_DPLL_MULT_12 (55 << 12) +#define M3_DPLL_DIV_12 (1 << 8) +#define M3_CM_CLKSEL1_PLL_12_VAL (MX_48M_SRC | MX_54M_SRC | \ + M3_DPLL_DIV_12 | M3_DPLL_MULT_12 | \ + MX_APLLS_CLIKIN_12) +#define M3_DPLL_MULT_13 (76 << 12) +#define M3_DPLL_DIV_13 (2 << 8) +#define M3_CM_CLKSEL1_PLL_13_VAL (MX_48M_SRC | MX_54M_SRC | \ + M3_DPLL_DIV_13 | M3_DPLL_MULT_13 | \ + MX_APLLS_CLIKIN_13) +#define M3_DPLL_MULT_19 (17 << 12) +#define M3_DPLL_DIV_19 (0 << 8) +#define M3_CM_CLKSEL1_PLL_19_VAL (MX_48M_SRC | MX_54M_SRC | \ + M3_DPLL_DIV_19 | M3_DPLL_MULT_19 | \ + MX_APLLS_CLIKIN_19_2) + +/* + * #2 (ratio1) DPLL = 330*2 = 660MHz, L3=165MHz + */ +#define M2_DPLL_MULT_12 (55 << 12) +#define M2_DPLL_DIV_12 (1 << 8) +#define M2_CM_CLKSEL1_PLL_12_VAL (MX_48M_SRC | MX_54M_SRC | \ + M2_DPLL_DIV_12 | M2_DPLL_MULT_12 | \ + MX_APLLS_CLIKIN_12) + +/* Speed changes - Used 658.7MHz instead of 660MHz for LP-Refresh M=76 N=2, + * relock time issue */ +/* Core frequency changed from 330/165 to 329/164 MHz*/ +#define M2_DPLL_MULT_13 (76 << 12) +#define M2_DPLL_DIV_13 (2 << 8) +#define M2_CM_CLKSEL1_PLL_13_VAL (MX_48M_SRC | MX_54M_SRC | \ + M2_DPLL_DIV_13 | M2_DPLL_MULT_13 | \ + MX_APLLS_CLIKIN_13) + +#define M2_DPLL_MULT_19 (17 << 12) +#define M2_DPLL_DIV_19 (0 << 8) +#define M2_CM_CLKSEL1_PLL_19_VAL (MX_48M_SRC | MX_54M_SRC | \ + M2_DPLL_DIV_19 | M2_DPLL_MULT_19 | \ + MX_APLLS_CLIKIN_19_2) + +/* boot (boot) */ +#define MB_DPLL_MULT (1 << 12) +#define MB_DPLL_DIV (0 << 8) +#define MB_CM_CLKSEL1_PLL_12_VAL (MX_48M_SRC | MX_54M_SRC | \ + MB_DPLL_DIV | MB_DPLL_MULT | \ + MX_APLLS_CLIKIN_12) + +#define MB_CM_CLKSEL1_PLL_13_VAL (MX_48M_SRC | MX_54M_SRC | \ + MB_DPLL_DIV | MB_DPLL_MULT | \ + MX_APLLS_CLIKIN_13) + +#define MB_CM_CLKSEL1_PLL_19_VAL (MX_48M_SRC | MX_54M_SRC | \ + MB_DPLL_DIV | MB_DPLL_MULT | \ + MX_APLLS_CLIKIN_19) + +/* + * 2430 - chassis (sedna) + * 165 (ratio1) same as above #2 + * 150 (ratio1) + * 133 (ratio2) same as above #4 + * 110 (ratio2) same as above #3 + * 104 (ratio2) + * boot (boot) + */ + +/* PRCM I target DPLL = 2*330MHz = 660MHz */ +#define MI_DPLL_MULT_12 (55 << 12) +#define MI_DPLL_DIV_12 (1 << 8) +#define MI_CM_CLKSEL1_PLL_12_VAL (MX_48M_SRC | MX_54M_SRC | \ + MI_DPLL_DIV_12 | MI_DPLL_MULT_12 | \ + MX_APLLS_CLIKIN_12) + +/* + * 2420 Equivalent - mode registers + * PRCM II , target DPLL = 2*300MHz = 600MHz + */ +#define MII_DPLL_MULT_12 (50 << 12) +#define MII_DPLL_DIV_12 (1 << 8) +#define MII_CM_CLKSEL1_PLL_12_VAL (MX_48M_SRC | MX_54M_SRC | \ + MII_DPLL_DIV_12 | MII_DPLL_MULT_12 | \ + MX_APLLS_CLIKIN_12) +#define MII_DPLL_MULT_13 (300 << 12) +#define MII_DPLL_DIV_13 (12 << 8) +#define MII_CM_CLKSEL1_PLL_13_VAL (MX_48M_SRC | MX_54M_SRC | \ + MII_DPLL_DIV_13 | MII_DPLL_MULT_13 | \ + MX_APLLS_CLIKIN_13) + +/* PRCM III target DPLL = 2*266 = 532MHz*/ +#define MIII_DPLL_MULT_12 (133 << 12) +#define MIII_DPLL_DIV_12 (5 << 8) +#define MIII_CM_CLKSEL1_PLL_12_VAL (MX_48M_SRC | MX_54M_SRC | \ + MIII_DPLL_DIV_12 | \ + MIII_DPLL_MULT_12 | MX_APLLS_CLIKIN_12) +#define MIII_DPLL_MULT_13 (266 << 12) +#define MIII_DPLL_DIV_13 (12 << 8) +#define MIII_CM_CLKSEL1_PLL_13_VAL (MX_48M_SRC | MX_54M_SRC | \ + MIII_DPLL_DIV_13 | \ + MIII_DPLL_MULT_13 | MX_APLLS_CLIKIN_13) + +/* PRCM VII (boot bypass) */ +#define MVII_CM_CLKSEL1_PLL_12_VAL MB_CM_CLKSEL1_PLL_12_VAL +#define MVII_CM_CLKSEL1_PLL_13_VAL MB_CM_CLKSEL1_PLL_13_VAL + +/* High and low operation value */ +#define MX_CLKSEL2_PLL_2x_VAL (2 << 0) +#define MX_CLKSEL2_PLL_1x_VAL (1 << 0) + +/* MPU speed defines */ +#define S12M 12000000 +#define S13M 13000000 +#define S19M 19200000 +#define S26M 26000000 +#define S100M 100000000 +#define S133M 133000000 +#define S150M 150000000 +#define S164M 164000000 +#define S165M 165000000 +#define S199M 199000000 +#define S200M 200000000 +#define S266M 266000000 +#define S300M 300000000 +#define S329M 329000000 +#define S330M 330000000 +#define S399M 399000000 +#define S400M 400000000 +#define S532M 532000000 +#define S600M 600000000 +#define S658M 658000000 +#define S660M 660000000 +#define S798M 798000000 + + +extern const struct prcm_config omap2420_rate_table[]; +extern const struct prcm_config omap2430_rate_table[]; +extern const struct prcm_config *rate_table; +extern const struct prcm_config *curr_prcm_set; + +#endif diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 8baa30d2acfbf2dd79a464ecda5c935b457e96b6..860b755d222074ce1bb061510f3a16fbc2cafa5b 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -326,7 +326,7 @@ int pm_dbg_regset_save(int reg_set) return 0; } -static const char pwrdm_state_names[][4] = { +static const char pwrdm_state_names[][PWRDM_MAX_PWRSTS] = { "OFF", "RET", "INA", @@ -381,7 +381,7 @@ static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user) seq_printf(s, "%s (%s)", pwrdm->name, pwrdm_state_names[pwrdm->state]); - for (i = 0; i < 4; i++) + for (i = 0; i < PWRDM_MAX_PWRSTS; i++) seq_printf(s, ",%s:%d", pwrdm_state_names[i], pwrdm->state_counter[i]); diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index b6990e37778341e98b65418668d473982e1583b7..26b3f3ee82a33abc92bd38427a47512d68955c48 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -10,9 +10,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#ifdef CONFIG_OMAP_DEBUG_POWERDOMAIN -# define DEBUG -#endif +#undef DEBUG #include #include @@ -160,7 +158,7 @@ static __init void _pwrdm_setup(struct powerdomain *pwrdm) { int i; - for (i = 0; i < 4; i++) + for (i = 0; i < PWRDM_MAX_PWRSTS; i++) pwrdm->state_counter[i] = 0; pwrdm_wait_transition(pwrdm); @@ -480,7 +478,7 @@ int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) if (IS_ERR(p)) { pr_debug("powerdomain: hardware cannot set/clear wake up of " "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name); - return IS_ERR(p); + return PTR_ERR(p); } pr_debug("powerdomain: hardware will wake up %s when %s wakes up\n", @@ -513,7 +511,7 @@ int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) if (IS_ERR(p)) { pr_debug("powerdomain: hardware cannot set/clear wake up of " "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name); - return IS_ERR(p); + return PTR_ERR(p); } pr_debug("powerdomain: hardware will no longer wake up %s after %s " @@ -550,7 +548,7 @@ int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) if (IS_ERR(p)) { pr_debug("powerdomain: hardware cannot set/clear wake up of " "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name); - return IS_ERR(p); + return PTR_ERR(p); } return prm_read_mod_bits_shift(pwrdm1->prcm_offs, PM_WKDEP, @@ -573,10 +571,10 @@ int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) { struct powerdomain *p; - if (!pwrdm1) + if (!cpu_is_omap34xx()) return -EINVAL; - if (!cpu_is_omap34xx()) + if (!pwrdm1) return -EINVAL; p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs); @@ -584,7 +582,7 @@ int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) pr_debug("powerdomain: hardware cannot set/clear sleep " "dependency affecting %s from %s\n", pwrdm1->name, pwrdm2->name); - return IS_ERR(p); + return PTR_ERR(p); } pr_debug("powerdomain: will prevent %s from sleeping if %s is active\n", @@ -612,10 +610,10 @@ int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) { struct powerdomain *p; - if (!pwrdm1) + if (!cpu_is_omap34xx()) return -EINVAL; - if (!cpu_is_omap34xx()) + if (!pwrdm1) return -EINVAL; p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs); @@ -623,7 +621,7 @@ int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) pr_debug("powerdomain: hardware cannot set/clear sleep " "dependency affecting %s from %s\n", pwrdm1->name, pwrdm2->name); - return IS_ERR(p); + return PTR_ERR(p); } pr_debug("powerdomain: will no longer prevent %s from sleeping if " @@ -655,10 +653,10 @@ int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) { struct powerdomain *p; - if (!pwrdm1) + if (!cpu_is_omap34xx()) return -EINVAL; - if (!cpu_is_omap34xx()) + if (!pwrdm1) return -EINVAL; p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs); @@ -666,7 +664,7 @@ int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) pr_debug("powerdomain: hardware cannot set/clear sleep " "dependency affecting %s from %s\n", pwrdm1->name, pwrdm2->name); - return IS_ERR(p); + return PTR_ERR(p); } return prm_read_mod_bits_shift(pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP, @@ -985,6 +983,9 @@ int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) if (pwrdm->banks < (bank + 1)) return -EEXIST; + if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) + bank = 1; + /* * The register bit names below may not correspond to the * actual names of the bits in each powerdomain's register, @@ -1032,6 +1033,9 @@ int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) if (pwrdm->banks < (bank + 1)) return -EEXIST; + if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) + bank = 1; + /* * The register bit names below may not correspond to the * actual names of the bits in each powerdomain's register, diff --git a/arch/arm/mach-omap2/powerdomains34xx.h b/arch/arm/mach-omap2/powerdomains34xx.h index fd09b0827df077a380f0ec7f2ea4f50469777891..588f7e07d0eacc868727797190c998da8cb273d9 100644 --- a/arch/arm/mach-omap2/powerdomains34xx.h +++ b/arch/arm/mach-omap2/powerdomains34xx.h @@ -190,6 +190,7 @@ static struct powerdomain mpu_34xx_pwrdm = { .wkdep_srcs = mpu_34xx_wkdeps, .pwrsts = PWRSTS_OFF_RET_ON, .pwrsts_logic_ret = PWRSTS_OFF_RET, + .flags = PWRDM_HAS_MPU_QUIRK, .banks = 1, .pwrsts_mem_ret = { [0] = PWRSTS_OFF_RET, diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h index cb1ae84e0925a597a31bb6385c82d686a887bff3..61ac2a418bd0461a1aa61f1cc3c872414414f9ae 100644 --- a/arch/arm/mach-omap2/prcm-common.h +++ b/arch/arm/mach-omap2/prcm-common.h @@ -4,10 +4,12 @@ /* * OMAP2/3 PRCM base and module definitions * - * Copyright (C) 2007-2008 Texas Instruments, Inc. - * Copyright (C) 2007-2008 Nokia Corporation + * Copyright (C) 2007-2009 Texas Instruments, Inc. + * Copyright (C) 2007-2009 Nokia Corporation * * Written by Paul Walmsley + * OMAP4 defines in this file are automatically generated from the OMAP hardware + * databases. * * 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 @@ -49,6 +51,73 @@ #define OMAP3430_NEON_MOD 0xb00 #define OMAP3430ES2_USBHOST_MOD 0xc00 +#define BITS(n_bit) \ + (((1 << n_bit) - 1) | (1 << n_bit)) + +#define BITFIELD(l_bit, u_bit) \ + (BITS(u_bit) & ~((BITS(l_bit)) >> 1)) + +/* OMAP44XX specific module offsets */ + +/* CM1 instances */ + +#define OMAP4430_CM1_OCP_SOCKET_MOD 0x0000 +#define OMAP4430_CM1_CKGEN_MOD 0x0100 +#define OMAP4430_CM1_MPU_MOD 0x0300 +#define OMAP4430_CM1_TESLA_MOD 0x0400 +#define OMAP4430_CM1_ABE_MOD 0x0500 +#define OMAP4430_CM1_RESTORE_MOD 0x0e00 +#define OMAP4430_CM1_INSTR_MOD 0x0f00 + +/* CM2 instances */ + +#define OMAP4430_CM2_OCP_SOCKET_MOD 0x0000 +#define OMAP4430_CM2_CKGEN_MOD 0x0100 +#define OMAP4430_CM2_ALWAYS_ON_MOD 0x0600 +#define OMAP4430_CM2_CORE_MOD 0x0700 +#define OMAP4430_CM2_IVAHD_MOD 0x0f00 +#define OMAP4430_CM2_CAM_MOD 0x1000 +#define OMAP4430_CM2_DSS_MOD 0x1100 +#define OMAP4430_CM2_GFX_MOD 0x1200 +#define OMAP4430_CM2_L3INIT_MOD 0x1300 +#define OMAP4430_CM2_L4PER_MOD 0x1400 +#define OMAP4430_CM2_CEFUSE_MOD 0x1600 +#define OMAP4430_CM2_RESTORE_MOD 0x1e00 +#define OMAP4430_CM2_INSTR_MOD 0x1f00 + +/* PRM instances */ + +#define OMAP4430_PRM_OCP_SOCKET_MOD 0x0000 +#define OMAP4430_PRM_CKGEN_MOD 0x0100 +#define OMAP4430_PRM_MPU_MOD 0x0300 +#define OMAP4430_PRM_TESLA_MOD 0x0400 +#define OMAP4430_PRM_ABE_MOD 0x0500 +#define OMAP4430_PRM_ALWAYS_ON_MOD 0x0600 +#define OMAP4430_PRM_CORE_MOD 0x0700 +#define OMAP4430_PRM_IVAHD_MOD 0x0f00 +#define OMAP4430_PRM_CAM_MOD 0x1000 +#define OMAP4430_PRM_DSS_MOD 0x1100 +#define OMAP4430_PRM_GFX_MOD 0x1200 +#define OMAP4430_PRM_L3INIT_MOD 0x1300 +#define OMAP4430_PRM_L4PER_MOD 0x1400 +#define OMAP4430_PRM_CEFUSE_MOD 0x1600 +#define OMAP4430_PRM_WKUP_MOD 0x1700 +#define OMAP4430_PRM_WKUP_CM_MOD 0x1800 +#define OMAP4430_PRM_EMU_MOD 0x1900 +#define OMAP4430_PRM_EMU_CM_MOD 0x1a00 +#define OMAP4430_PRM_DEVICE_MOD 0x1b00 +#define OMAP4430_PRM_INSTR_MOD 0x1f00 + +/* SCRM instances */ + +#define OMAP4430_SCRM_SCRM_MOD 0x0000 + +/* CHIRONSS instances */ + +#define OMAP4430_CHIRONSS_CHIRONSS_OCP_SOCKET_PRCM_MOD 0x0000 +#define OMAP4430_CHIRONSS_CHIRONSS_DEVICE_PRM_MOD 0x0200 +#define OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD 0x0400 +#define OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD 0x0800 /* 24XX register bits shared between CM & PRM registers */ diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c index 029d376198d4c592bf4c145907ea231c5b7d62a9..3ea8177ffb2508be4a2b821ff09e05b0ac826bed 100644 --- a/arch/arm/mach-omap2/prcm.c +++ b/arch/arm/mach-omap2/prcm.c @@ -34,6 +34,7 @@ static void __iomem *prm_base; static void __iomem *cm_base; +static void __iomem *cm2_base; #define MAX_MODULE_ENABLE_WAIT 100000 @@ -170,14 +171,12 @@ u32 prm_read_mod_reg(s16 module, u16 idx) { return __omap_prcm_read(prm_base, module, idx); } -EXPORT_SYMBOL(prm_read_mod_reg); /* Write into a register in a PRM module */ void prm_write_mod_reg(u32 val, s16 module, u16 idx) { __omap_prcm_write(val, prm_base, module, idx); } -EXPORT_SYMBOL(prm_write_mod_reg); /* Read-modify-write a register in a PRM module. Caller must lock */ u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx) @@ -191,21 +190,18 @@ u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx) return v; } -EXPORT_SYMBOL(prm_rmw_mod_reg_bits); /* Read a register in a CM module */ u32 cm_read_mod_reg(s16 module, u16 idx) { return __omap_prcm_read(cm_base, module, idx); } -EXPORT_SYMBOL(cm_read_mod_reg); /* Write into a register in a CM module */ void cm_write_mod_reg(u32 val, s16 module, u16 idx) { __omap_prcm_write(val, cm_base, module, idx); } -EXPORT_SYMBOL(cm_write_mod_reg); /* Read-modify-write a register in a CM module. Caller must lock */ u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx) @@ -219,7 +215,6 @@ u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx) return v; } -EXPORT_SYMBOL(cm_rmw_mod_reg_bits); /** * omap2_cm_wait_idlest - wait for IDLEST bit to indicate module readiness @@ -247,9 +242,8 @@ int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, const char *name) BUG(); /* Wait for lock */ - while (((__raw_readl(reg) & mask) != ena) && - (i++ < MAX_MODULE_ENABLE_WAIT)) - udelay(1); + omap_test_timeout(((__raw_readl(reg) & mask) == ena), + MAX_MODULE_ENABLE_WAIT, i); if (i < MAX_MODULE_ENABLE_WAIT) pr_debug("cm: Module associated with clock %s ready after %d " @@ -265,6 +259,7 @@ void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals) { prm_base = omap2_globals->prm; cm_base = omap2_globals->cm; + cm2_base = omap2_globals->cm2; } #ifdef CONFIG_ARCH_OMAP3 diff --git a/arch/arm/mach-omap2/prm-regbits-44xx.h b/arch/arm/mach-omap2/prm-regbits-44xx.h new file mode 100644 index 0000000000000000000000000000000000000000..301c810fb269c0e33dd614f8fd1d27e178d11976 --- /dev/null +++ b/arch/arm/mach-omap2/prm-regbits-44xx.h @@ -0,0 +1,2205 @@ +/* + * OMAP44xx Power Management register bits + * + * Copyright (C) 2009 Texas Instruments, Inc. + * Copyright (C) 2009 Nokia Corporation + * + * Paul Walmsley (paul@pwsan.com) + * Rajendra Nayak (rnayak@ti.com) + * Benoit Cousson (b-cousson@ti.com) + * + * This file is automatically generated from the OMAP hardware databases. + * We respectfully ask that any modifications to this file be coordinated + * with the public linux-omap@vger.kernel.org mailing list and the + * authors above to ensure that the autogeneration scripts are kept + * up-to-date with the file contents. + * + * 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. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_44XX_H +#define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_44XX_H + +#include "prm.h" + + +/* + * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP, + * PRM_LDO_SRAM_MPU_SETUP + */ +#define OMAP4430_ABBOFF_ACT_EXPORT_SHIFT (1 << 1) +#define OMAP4430_ABBOFF_ACT_EXPORT_MASK BITFIELD(1, 1) + +/* + * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP, + * PRM_LDO_SRAM_MPU_SETUP + */ +#define OMAP4430_ABBOFF_SLEEP_EXPORT_SHIFT (1 << 2) +#define OMAP4430_ABBOFF_SLEEP_EXPORT_MASK BITFIELD(2, 2) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_ABB_IVA_DONE_EN_SHIFT (1 << 31) +#define OMAP4430_ABB_IVA_DONE_EN_MASK BITFIELD(31, 31) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_ABB_IVA_DONE_ST_SHIFT (1 << 31) +#define OMAP4430_ABB_IVA_DONE_ST_MASK BITFIELD(31, 31) + +/* Used by PRM_IRQENABLE_MPU_2 */ +#define OMAP4430_ABB_MPU_DONE_EN_SHIFT (1 << 7) +#define OMAP4430_ABB_MPU_DONE_EN_MASK BITFIELD(7, 7) + +/* Used by PRM_IRQSTATUS_MPU_2 */ +#define OMAP4430_ABB_MPU_DONE_ST_SHIFT (1 << 7) +#define OMAP4430_ABB_MPU_DONE_ST_MASK BITFIELD(7, 7) + +/* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */ +#define OMAP4430_ACTIVE_FBB_SEL_SHIFT (1 << 2) +#define OMAP4430_ACTIVE_FBB_SEL_MASK BITFIELD(2, 2) + +/* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */ +#define OMAP4430_ACTIVE_RBB_SEL_SHIFT (1 << 1) +#define OMAP4430_ACTIVE_RBB_SEL_MASK BITFIELD(1, 1) + +/* Used by PM_ABE_PWRSTCTRL */ +#define OMAP4430_AESSMEM_ONSTATE_SHIFT (1 << 16) +#define OMAP4430_AESSMEM_ONSTATE_MASK BITFIELD(16, 17) + +/* Used by PM_ABE_PWRSTCTRL */ +#define OMAP4430_AESSMEM_RETSTATE_SHIFT (1 << 8) +#define OMAP4430_AESSMEM_RETSTATE_MASK BITFIELD(8, 8) + +/* Used by PM_ABE_PWRSTST */ +#define OMAP4430_AESSMEM_STATEST_SHIFT (1 << 4) +#define OMAP4430_AESSMEM_STATEST_MASK BITFIELD(4, 5) + +/* + * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP, + * PRM_LDO_SRAM_MPU_SETUP + */ +#define OMAP4430_AIPOFF_SHIFT (1 << 8) +#define OMAP4430_AIPOFF_MASK BITFIELD(8, 8) + +/* Used by PRM_VOLTCTRL */ +#define OMAP4430_AUTO_CTRL_VDD_CORE_L_SHIFT (1 << 0) +#define OMAP4430_AUTO_CTRL_VDD_CORE_L_MASK BITFIELD(0, 1) + +/* Used by PRM_VOLTCTRL */ +#define OMAP4430_AUTO_CTRL_VDD_IVA_L_SHIFT (1 << 4) +#define OMAP4430_AUTO_CTRL_VDD_IVA_L_MASK BITFIELD(4, 5) + +/* Used by PRM_VOLTCTRL */ +#define OMAP4430_AUTO_CTRL_VDD_MPU_L_SHIFT (1 << 2) +#define OMAP4430_AUTO_CTRL_VDD_MPU_L_MASK BITFIELD(2, 3) + +/* Used by PM_CAM_PWRSTCTRL */ +#define OMAP4430_CAM_MEM_ONSTATE_SHIFT (1 << 16) +#define OMAP4430_CAM_MEM_ONSTATE_MASK BITFIELD(16, 17) + +/* Used by PM_CAM_PWRSTST */ +#define OMAP4430_CAM_MEM_STATEST_SHIFT (1 << 4) +#define OMAP4430_CAM_MEM_STATEST_MASK BITFIELD(4, 5) + +/* Used by PRM_CLKREQCTRL */ +#define OMAP4430_CLKREQ_COND_SHIFT (1 << 0) +#define OMAP4430_CLKREQ_COND_MASK BITFIELD(0, 2) + +/* Used by PRM_VC_VAL_SMPS_RA_CMD */ +#define OMAP4430_CMDRA_VDD_CORE_L_SHIFT (1 << 0) +#define OMAP4430_CMDRA_VDD_CORE_L_MASK BITFIELD(0, 7) + +/* Used by PRM_VC_VAL_SMPS_RA_CMD */ +#define OMAP4430_CMDRA_VDD_IVA_L_SHIFT (1 << 8) +#define OMAP4430_CMDRA_VDD_IVA_L_MASK BITFIELD(8, 15) + +/* Used by PRM_VC_VAL_SMPS_RA_CMD */ +#define OMAP4430_CMDRA_VDD_MPU_L_SHIFT (1 << 16) +#define OMAP4430_CMDRA_VDD_MPU_L_MASK BITFIELD(16, 23) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_CMD_VDD_CORE_L_SHIFT (1 << 4) +#define OMAP4430_CMD_VDD_CORE_L_MASK BITFIELD(4, 4) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_CMD_VDD_IVA_L_SHIFT (1 << 12) +#define OMAP4430_CMD_VDD_IVA_L_MASK BITFIELD(12, 12) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_CMD_VDD_MPU_L_SHIFT (1 << 17) +#define OMAP4430_CMD_VDD_MPU_L_MASK BITFIELD(17, 17) + +/* Used by PM_CORE_PWRSTCTRL */ +#define OMAP4430_CORE_OCMRAM_ONSTATE_SHIFT (1 << 18) +#define OMAP4430_CORE_OCMRAM_ONSTATE_MASK BITFIELD(18, 19) + +/* Used by PM_CORE_PWRSTCTRL */ +#define OMAP4430_CORE_OCMRAM_RETSTATE_SHIFT (1 << 9) +#define OMAP4430_CORE_OCMRAM_RETSTATE_MASK BITFIELD(9, 9) + +/* Used by PM_CORE_PWRSTST */ +#define OMAP4430_CORE_OCMRAM_STATEST_SHIFT (1 << 6) +#define OMAP4430_CORE_OCMRAM_STATEST_MASK BITFIELD(6, 7) + +/* Used by PM_CORE_PWRSTCTRL */ +#define OMAP4430_CORE_OTHER_BANK_ONSTATE_SHIFT (1 << 16) +#define OMAP4430_CORE_OTHER_BANK_ONSTATE_MASK BITFIELD(16, 17) + +/* Used by PM_CORE_PWRSTCTRL */ +#define OMAP4430_CORE_OTHER_BANK_RETSTATE_SHIFT (1 << 8) +#define OMAP4430_CORE_OTHER_BANK_RETSTATE_MASK BITFIELD(8, 8) + +/* Used by PM_CORE_PWRSTST */ +#define OMAP4430_CORE_OTHER_BANK_STATEST_SHIFT (1 << 4) +#define OMAP4430_CORE_OTHER_BANK_STATEST_MASK BITFIELD(4, 5) + +/* Used by PRM_VC_VAL_BYPASS */ +#define OMAP4430_DATA_SHIFT (1 << 16) +#define OMAP4430_DATA_MASK BITFIELD(16, 23) + +/* Used by PRM_DEVICE_OFF_CTRL */ +#define OMAP4430_DEVICE_OFF_ENABLE_SHIFT (1 << 0) +#define OMAP4430_DEVICE_OFF_ENABLE_MASK BITFIELD(0, 0) + +/* Used by PRM_VC_CFG_I2C_MODE */ +#define OMAP4430_DFILTEREN_SHIFT (1 << 6) +#define OMAP4430_DFILTEREN_MASK BITFIELD(6, 6) + +/* Used by PRM_IRQENABLE_MPU, PRM_IRQENABLE_TESLA */ +#define OMAP4430_DPLL_ABE_RECAL_EN_SHIFT (1 << 4) +#define OMAP4430_DPLL_ABE_RECAL_EN_MASK BITFIELD(4, 4) + +/* Used by PRM_IRQSTATUS_MPU, PRM_IRQSTATUS_TESLA */ +#define OMAP4430_DPLL_ABE_RECAL_ST_SHIFT (1 << 4) +#define OMAP4430_DPLL_ABE_RECAL_ST_MASK BITFIELD(4, 4) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_DPLL_CORE_RECAL_EN_SHIFT (1 << 0) +#define OMAP4430_DPLL_CORE_RECAL_EN_MASK BITFIELD(0, 0) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_DPLL_CORE_RECAL_ST_SHIFT (1 << 0) +#define OMAP4430_DPLL_CORE_RECAL_ST_MASK BITFIELD(0, 0) + +/* Used by PRM_IRQENABLE_MPU */ +#define OMAP4430_DPLL_DDRPHY_RECAL_EN_SHIFT (1 << 6) +#define OMAP4430_DPLL_DDRPHY_RECAL_EN_MASK BITFIELD(6, 6) + +/* Used by PRM_IRQSTATUS_MPU */ +#define OMAP4430_DPLL_DDRPHY_RECAL_ST_SHIFT (1 << 6) +#define OMAP4430_DPLL_DDRPHY_RECAL_ST_MASK BITFIELD(6, 6) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU, PRM_IRQENABLE_TESLA */ +#define OMAP4430_DPLL_IVA_RECAL_EN_SHIFT (1 << 2) +#define OMAP4430_DPLL_IVA_RECAL_EN_MASK BITFIELD(2, 2) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU, PRM_IRQSTATUS_TESLA */ +#define OMAP4430_DPLL_IVA_RECAL_ST_SHIFT (1 << 2) +#define OMAP4430_DPLL_IVA_RECAL_ST_MASK BITFIELD(2, 2) + +/* Used by PRM_IRQENABLE_MPU */ +#define OMAP4430_DPLL_MPU_RECAL_EN_SHIFT (1 << 1) +#define OMAP4430_DPLL_MPU_RECAL_EN_MASK BITFIELD(1, 1) + +/* Used by PRM_IRQSTATUS_MPU */ +#define OMAP4430_DPLL_MPU_RECAL_ST_SHIFT (1 << 1) +#define OMAP4430_DPLL_MPU_RECAL_ST_MASK BITFIELD(1, 1) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_DPLL_PER_RECAL_EN_SHIFT (1 << 3) +#define OMAP4430_DPLL_PER_RECAL_EN_MASK BITFIELD(3, 3) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_DPLL_PER_RECAL_ST_SHIFT (1 << 3) +#define OMAP4430_DPLL_PER_RECAL_ST_MASK BITFIELD(3, 3) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_DPLL_UNIPRO_RECAL_EN_SHIFT (1 << 7) +#define OMAP4430_DPLL_UNIPRO_RECAL_EN_MASK BITFIELD(7, 7) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_DPLL_UNIPRO_RECAL_ST_SHIFT (1 << 7) +#define OMAP4430_DPLL_UNIPRO_RECAL_ST_MASK BITFIELD(7, 7) + +/* Used by PRM_IRQENABLE_MPU */ +#define OMAP4430_DPLL_USB_RECAL_EN_SHIFT (1 << 5) +#define OMAP4430_DPLL_USB_RECAL_EN_MASK BITFIELD(5, 5) + +/* Used by PRM_IRQSTATUS_MPU */ +#define OMAP4430_DPLL_USB_RECAL_ST_SHIFT (1 << 5) +#define OMAP4430_DPLL_USB_RECAL_ST_MASK BITFIELD(5, 5) + +/* Used by PM_DSS_PWRSTCTRL */ +#define OMAP4430_DSS_MEM_ONSTATE_SHIFT (1 << 16) +#define OMAP4430_DSS_MEM_ONSTATE_MASK BITFIELD(16, 17) + +/* Used by PM_DSS_PWRSTCTRL */ +#define OMAP4430_DSS_MEM_RETSTATE_SHIFT (1 << 8) +#define OMAP4430_DSS_MEM_RETSTATE_MASK BITFIELD(8, 8) + +/* Used by PM_DSS_PWRSTST */ +#define OMAP4430_DSS_MEM_STATEST_SHIFT (1 << 4) +#define OMAP4430_DSS_MEM_STATEST_MASK BITFIELD(4, 5) + +/* Used by PM_CORE_PWRSTCTRL */ +#define OMAP4430_DUCATI_L2RAM_ONSTATE_SHIFT (1 << 20) +#define OMAP4430_DUCATI_L2RAM_ONSTATE_MASK BITFIELD(20, 21) + +/* Used by PM_CORE_PWRSTCTRL */ +#define OMAP4430_DUCATI_L2RAM_RETSTATE_SHIFT (1 << 10) +#define OMAP4430_DUCATI_L2RAM_RETSTATE_MASK BITFIELD(10, 10) + +/* Used by PM_CORE_PWRSTST */ +#define OMAP4430_DUCATI_L2RAM_STATEST_SHIFT (1 << 8) +#define OMAP4430_DUCATI_L2RAM_STATEST_MASK BITFIELD(8, 9) + +/* Used by PM_CORE_PWRSTCTRL */ +#define OMAP4430_DUCATI_UNICACHE_ONSTATE_SHIFT (1 << 22) +#define OMAP4430_DUCATI_UNICACHE_ONSTATE_MASK BITFIELD(22, 23) + +/* Used by PM_CORE_PWRSTCTRL */ +#define OMAP4430_DUCATI_UNICACHE_RETSTATE_SHIFT (1 << 11) +#define OMAP4430_DUCATI_UNICACHE_RETSTATE_MASK BITFIELD(11, 11) + +/* Used by PM_CORE_PWRSTST */ +#define OMAP4430_DUCATI_UNICACHE_STATEST_SHIFT (1 << 10) +#define OMAP4430_DUCATI_UNICACHE_STATEST_MASK BITFIELD(10, 11) + +/* Used by RM_MPU_RSTST */ +#define OMAP4430_EMULATION_RST_SHIFT (1 << 0) +#define OMAP4430_EMULATION_RST_MASK BITFIELD(0, 0) + +/* Used by RM_DUCATI_RSTST */ +#define OMAP4430_EMULATION_RST1ST_SHIFT (1 << 3) +#define OMAP4430_EMULATION_RST1ST_MASK BITFIELD(3, 3) + +/* Used by RM_DUCATI_RSTST */ +#define OMAP4430_EMULATION_RST2ST_SHIFT (1 << 4) +#define OMAP4430_EMULATION_RST2ST_MASK BITFIELD(4, 4) + +/* Used by RM_IVAHD_RSTST */ +#define OMAP4430_EMULATION_SEQ1_RST1ST_SHIFT (1 << 3) +#define OMAP4430_EMULATION_SEQ1_RST1ST_MASK BITFIELD(3, 3) + +/* Used by RM_IVAHD_RSTST */ +#define OMAP4430_EMULATION_SEQ2_RST2ST_SHIFT (1 << 4) +#define OMAP4430_EMULATION_SEQ2_RST2ST_MASK BITFIELD(4, 4) + +/* Used by PM_EMU_PWRSTCTRL */ +#define OMAP4430_EMU_BANK_ONSTATE_SHIFT (1 << 16) +#define OMAP4430_EMU_BANK_ONSTATE_MASK BITFIELD(16, 17) + +/* Used by PM_EMU_PWRSTST */ +#define OMAP4430_EMU_BANK_STATEST_SHIFT (1 << 4) +#define OMAP4430_EMU_BANK_STATEST_MASK BITFIELD(4, 5) + +/* + * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP, + * PRM_LDO_SRAM_MPU_SETUP, PRM_SRAM_WKUP_SETUP + */ +#define OMAP4430_ENABLE_RTA_EXPORT_SHIFT (1 << 0) +#define OMAP4430_ENABLE_RTA_EXPORT_MASK BITFIELD(0, 0) + +/* + * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP, + * PRM_LDO_SRAM_MPU_SETUP + */ +#define OMAP4430_ENFUNC1_SHIFT (1 << 3) +#define OMAP4430_ENFUNC1_MASK BITFIELD(3, 3) + +/* + * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP, + * PRM_LDO_SRAM_MPU_SETUP + */ +#define OMAP4430_ENFUNC3_SHIFT (1 << 5) +#define OMAP4430_ENFUNC3_MASK BITFIELD(5, 5) + +/* + * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP, + * PRM_LDO_SRAM_MPU_SETUP + */ +#define OMAP4430_ENFUNC4_SHIFT (1 << 6) +#define OMAP4430_ENFUNC4_MASK BITFIELD(6, 6) + +/* + * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP, + * PRM_LDO_SRAM_MPU_SETUP + */ +#define OMAP4430_ENFUNC5_SHIFT (1 << 7) +#define OMAP4430_ENFUNC5_MASK BITFIELD(7, 7) + +/* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */ +#define OMAP4430_ERRORGAIN_SHIFT (1 << 16) +#define OMAP4430_ERRORGAIN_MASK BITFIELD(16, 23) + +/* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */ +#define OMAP4430_ERROROFFSET_SHIFT (1 << 24) +#define OMAP4430_ERROROFFSET_MASK BITFIELD(24, 31) + +/* Used by PRM_RSTST */ +#define OMAP4430_EXTERNAL_WARM_RST_SHIFT (1 << 5) +#define OMAP4430_EXTERNAL_WARM_RST_MASK BITFIELD(5, 5) + +/* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */ +#define OMAP4430_FORCEUPDATE_SHIFT (1 << 1) +#define OMAP4430_FORCEUPDATE_MASK BITFIELD(1, 1) + +/* Used by PRM_VP_CORE_VOLTAGE, PRM_VP_IVA_VOLTAGE, PRM_VP_MPU_VOLTAGE */ +#define OMAP4430_FORCEUPDATEWAIT_SHIFT (1 << 8) +#define OMAP4430_FORCEUPDATEWAIT_MASK BITFIELD(8, 31) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_TESLA */ +#define OMAP4430_FORCEWKUP_EN_SHIFT (1 << 10) +#define OMAP4430_FORCEWKUP_EN_MASK BITFIELD(10, 10) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_TESLA */ +#define OMAP4430_FORCEWKUP_ST_SHIFT (1 << 10) +#define OMAP4430_FORCEWKUP_ST_MASK BITFIELD(10, 10) + +/* Used by PM_GFX_PWRSTCTRL */ +#define OMAP4430_GFX_MEM_ONSTATE_SHIFT (1 << 16) +#define OMAP4430_GFX_MEM_ONSTATE_MASK BITFIELD(16, 17) + +/* Used by PM_GFX_PWRSTST */ +#define OMAP4430_GFX_MEM_STATEST_SHIFT (1 << 4) +#define OMAP4430_GFX_MEM_STATEST_MASK BITFIELD(4, 5) + +/* Used by PRM_RSTST */ +#define OMAP4430_GLOBAL_COLD_RST_SHIFT (1 << 0) +#define OMAP4430_GLOBAL_COLD_RST_MASK BITFIELD(0, 0) + +/* Used by PRM_RSTST */ +#define OMAP4430_GLOBAL_WARM_SW_RST_SHIFT (1 << 1) +#define OMAP4430_GLOBAL_WARM_SW_RST_MASK BITFIELD(1, 1) + +/* Used by PRM_IO_PMCTRL */ +#define OMAP4430_GLOBAL_WUEN_SHIFT (1 << 16) +#define OMAP4430_GLOBAL_WUEN_MASK BITFIELD(16, 16) + +/* Used by PRM_VC_CFG_I2C_MODE */ +#define OMAP4430_HSMCODE_SHIFT (1 << 0) +#define OMAP4430_HSMCODE_MASK BITFIELD(0, 2) + +/* Used by PRM_VC_CFG_I2C_MODE */ +#define OMAP4430_HSMODEEN_SHIFT (1 << 3) +#define OMAP4430_HSMODEEN_MASK BITFIELD(3, 3) + +/* Used by PRM_VC_CFG_I2C_CLK */ +#define OMAP4430_HSSCLH_SHIFT (1 << 16) +#define OMAP4430_HSSCLH_MASK BITFIELD(16, 23) + +/* Used by PRM_VC_CFG_I2C_CLK */ +#define OMAP4430_HSSCLL_SHIFT (1 << 24) +#define OMAP4430_HSSCLL_MASK BITFIELD(24, 31) + +/* Used by PM_IVAHD_PWRSTCTRL */ +#define OMAP4430_HWA_MEM_ONSTATE_SHIFT (1 << 16) +#define OMAP4430_HWA_MEM_ONSTATE_MASK BITFIELD(16, 17) + +/* Used by PM_IVAHD_PWRSTCTRL */ +#define OMAP4430_HWA_MEM_RETSTATE_SHIFT (1 << 8) +#define OMAP4430_HWA_MEM_RETSTATE_MASK BITFIELD(8, 8) + +/* Used by PM_IVAHD_PWRSTST */ +#define OMAP4430_HWA_MEM_STATEST_SHIFT (1 << 4) +#define OMAP4430_HWA_MEM_STATEST_MASK BITFIELD(4, 5) + +/* Used by RM_MPU_RSTST */ +#define OMAP4430_ICECRUSHER_MPU_RST_SHIFT (1 << 1) +#define OMAP4430_ICECRUSHER_MPU_RST_MASK BITFIELD(1, 1) + +/* Used by RM_DUCATI_RSTST */ +#define OMAP4430_ICECRUSHER_RST1ST_SHIFT (1 << 5) +#define OMAP4430_ICECRUSHER_RST1ST_MASK BITFIELD(5, 5) + +/* Used by RM_DUCATI_RSTST */ +#define OMAP4430_ICECRUSHER_RST2ST_SHIFT (1 << 6) +#define OMAP4430_ICECRUSHER_RST2ST_MASK BITFIELD(6, 6) + +/* Used by RM_IVAHD_RSTST */ +#define OMAP4430_ICECRUSHER_SEQ1_RST1ST_SHIFT (1 << 5) +#define OMAP4430_ICECRUSHER_SEQ1_RST1ST_MASK BITFIELD(5, 5) + +/* Used by RM_IVAHD_RSTST */ +#define OMAP4430_ICECRUSHER_SEQ2_RST2ST_SHIFT (1 << 6) +#define OMAP4430_ICECRUSHER_SEQ2_RST2ST_MASK BITFIELD(6, 6) + +/* Used by PRM_RSTST */ +#define OMAP4430_ICEPICK_RST_SHIFT (1 << 9) +#define OMAP4430_ICEPICK_RST_MASK BITFIELD(9, 9) + +/* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */ +#define OMAP4430_INITVDD_SHIFT (1 << 2) +#define OMAP4430_INITVDD_MASK BITFIELD(2, 2) + +/* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */ +#define OMAP4430_INITVOLTAGE_SHIFT (1 << 8) +#define OMAP4430_INITVOLTAGE_MASK BITFIELD(8, 15) + +/* + * Used by PM_EMU_PWRSTST, PM_CORE_PWRSTST, PM_CAM_PWRSTST, PM_L3INIT_PWRSTST, + * PM_ABE_PWRSTST, PM_GFX_PWRSTST, PM_MPU_PWRSTST, PM_CEFUSE_PWRSTST, + * PM_DSS_PWRSTST, PM_L4PER_PWRSTST, PM_TESLA_PWRSTST, PM_IVAHD_PWRSTST + */ +#define OMAP4430_INTRANSITION_SHIFT (1 << 20) +#define OMAP4430_INTRANSITION_MASK BITFIELD(20, 20) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_IO_EN_SHIFT (1 << 9) +#define OMAP4430_IO_EN_MASK BITFIELD(9, 9) + +/* Used by PRM_IO_PMCTRL */ +#define OMAP4430_IO_ON_STATUS_SHIFT (1 << 5) +#define OMAP4430_IO_ON_STATUS_MASK BITFIELD(5, 5) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_IO_ST_SHIFT (1 << 9) +#define OMAP4430_IO_ST_MASK BITFIELD(9, 9) + +/* Used by PRM_IO_PMCTRL */ +#define OMAP4430_ISOCLK_OVERRIDE_SHIFT (1 << 0) +#define OMAP4430_ISOCLK_OVERRIDE_MASK BITFIELD(0, 0) + +/* Used by PRM_IO_PMCTRL */ +#define OMAP4430_ISOCLK_STATUS_SHIFT (1 << 1) +#define OMAP4430_ISOCLK_STATUS_MASK BITFIELD(1, 1) + +/* Used by PRM_IO_PMCTRL */ +#define OMAP4430_ISOOVR_EXTEND_SHIFT (1 << 4) +#define OMAP4430_ISOOVR_EXTEND_MASK BITFIELD(4, 4) + +/* Used by PRM_IO_COUNT */ +#define OMAP4430_ISO_2_ON_TIME_SHIFT (1 << 0) +#define OMAP4430_ISO_2_ON_TIME_MASK BITFIELD(0, 7) + +/* Used by PM_L3INIT_PWRSTCTRL */ +#define OMAP4430_L3INIT_BANK1_ONSTATE_SHIFT (1 << 16) +#define OMAP4430_L3INIT_BANK1_ONSTATE_MASK BITFIELD(16, 17) + +/* Used by PM_L3INIT_PWRSTCTRL */ +#define OMAP4430_L3INIT_BANK1_RETSTATE_SHIFT (1 << 8) +#define OMAP4430_L3INIT_BANK1_RETSTATE_MASK BITFIELD(8, 8) + +/* Used by PM_L3INIT_PWRSTST */ +#define OMAP4430_L3INIT_BANK1_STATEST_SHIFT (1 << 4) +#define OMAP4430_L3INIT_BANK1_STATEST_MASK BITFIELD(4, 5) + +/* + * Used by PM_CORE_PWRSTCTRL, PM_L3INIT_PWRSTCTRL, PM_ABE_PWRSTCTRL, + * PM_MPU_PWRSTCTRL, PM_DSS_PWRSTCTRL, PM_L4PER_PWRSTCTRL, PM_TESLA_PWRSTCTRL, + * PM_IVAHD_PWRSTCTRL + */ +#define OMAP4430_LOGICRETSTATE_SHIFT (1 << 2) +#define OMAP4430_LOGICRETSTATE_MASK BITFIELD(2, 2) + +/* + * Used by PM_EMU_PWRSTST, PM_CORE_PWRSTST, PM_CAM_PWRSTST, PM_L3INIT_PWRSTST, + * PM_ABE_PWRSTST, PM_GFX_PWRSTST, PM_MPU_PWRSTST, PM_CEFUSE_PWRSTST, + * PM_DSS_PWRSTST, PM_L4PER_PWRSTST, PM_TESLA_PWRSTST, PM_IVAHD_PWRSTST + */ +#define OMAP4430_LOGICSTATEST_SHIFT (1 << 2) +#define OMAP4430_LOGICSTATEST_MASK BITFIELD(2, 2) + +/* + * Used by RM_WKUP_GPIO1_CONTEXT, RM_WKUP_KEYBOARD_CONTEXT, + * RM_WKUP_L4WKUP_CONTEXT, RM_WKUP_RTC_CONTEXT, RM_WKUP_SARRAM_CONTEXT, + * RM_WKUP_SYNCTIMER_CONTEXT, RM_WKUP_TIMER12_CONTEXT, RM_WKUP_TIMER1_CONTEXT, + * RM_WKUP_USIM_CONTEXT, RM_WKUP_WDT1_CONTEXT, RM_WKUP_WDT2_CONTEXT, + * RM_EMU_DEBUGSS_CONTEXT, RM_D2D_SAD2D_CONTEXT, RM_D2D_SAD2D_FW_CONTEXT, + * RM_DUCATI_DUCATI_CONTEXT, RM_L3INSTR_L3_3_CONTEXT, + * RM_L3INSTR_L3_INSTR_CONTEXT, RM_L3INSTR_OCP_WP1_CONTEXT, + * RM_L3_1_L3_1_CONTEXT, RM_L3_2_L3_2_CONTEXT, RM_L3_2_OCMC_RAM_CONTEXT, + * RM_L4CFG_L4_CFG_CONTEXT, RM_L4CFG_SAR_ROM_CONTEXT, RM_MEMIF_DLL_CONTEXT, + * RM_MEMIF_DLL_H_CONTEXT, RM_MEMIF_DMM_CONTEXT, RM_MEMIF_EMIF_FW_CONTEXT, + * RM_CAM_FDIF_CONTEXT, RM_CAM_ISS_CONTEXT, RM_L3INIT_CCPTX_CONTEXT, + * RM_L3INIT_EMAC_CONTEXT, RM_L3INIT_P1500_CONTEXT, RM_L3INIT_PCIESS_CONTEXT, + * RM_L3INIT_SATA_CONTEXT, RM_L3INIT_TPPSS_CONTEXT, RM_L3INIT_UNIPRO1_CONTEXT, + * RM_L3INIT_USBPHYOCP2SCP_CONTEXT, RM_L3INIT_XHPI_CONTEXT, + * RM_ABE_AESS_CONTEXT, RM_ABE_DMIC_CONTEXT, RM_ABE_MCASP_CONTEXT, + * RM_ABE_MCBSP1_CONTEXT, RM_ABE_MCBSP2_CONTEXT, RM_ABE_MCBSP3_CONTEXT, + * RM_ABE_PDM_CONTEXT, RM_ABE_SLIMBUS_CONTEXT, RM_ABE_TIMER5_CONTEXT, + * RM_ABE_TIMER6_CONTEXT, RM_ABE_TIMER7_CONTEXT, RM_ABE_TIMER8_CONTEXT, + * RM_ABE_WDT3_CONTEXT, RM_GFX_GFX_CONTEXT, RM_MPU_MPU_CONTEXT, + * RM_CEFUSE_CEFUSE_CONTEXT, RM_ALWON_MDMINTC_CONTEXT, + * RM_ALWON_SR_CORE_CONTEXT, RM_ALWON_SR_IVA_CONTEXT, RM_ALWON_SR_MPU_CONTEXT, + * RM_DSS_DEISS_CONTEXT, RM_DSS_DSS_CONTEXT, RM_L4PER_ADC_CONTEXT, + * RM_L4PER_DMTIMER10_CONTEXT, RM_L4PER_DMTIMER11_CONTEXT, + * RM_L4PER_DMTIMER2_CONTEXT, RM_L4PER_DMTIMER3_CONTEXT, + * RM_L4PER_DMTIMER4_CONTEXT, RM_L4PER_DMTIMER9_CONTEXT, RM_L4PER_ELM_CONTEXT, + * RM_L4PER_HDQ1W_CONTEXT, RM_L4PER_HECC1_CONTEXT, RM_L4PER_HECC2_CONTEXT, + * RM_L4PER_I2C2_CONTEXT, RM_L4PER_I2C3_CONTEXT, RM_L4PER_I2C4_CONTEXT, + * RM_L4PER_I2C5_CONTEXT, RM_L4PER_L4_PER_CONTEXT, RM_L4PER_MCASP2_CONTEXT, + * RM_L4PER_MCASP3_CONTEXT, RM_L4PER_MCBSP4_CONTEXT, RM_L4PER_MCSPI1_CONTEXT, + * RM_L4PER_MCSPI2_CONTEXT, RM_L4PER_MCSPI3_CONTEXT, RM_L4PER_MCSPI4_CONTEXT, + * RM_L4PER_MGATE_CONTEXT, RM_L4PER_MMCSD3_CONTEXT, RM_L4PER_MMCSD4_CONTEXT, + * RM_L4PER_MMCSD5_CONTEXT, RM_L4PER_MSPROHG_CONTEXT, + * RM_L4PER_SLIMBUS2_CONTEXT, RM_L4SEC_PKAEIP29_CONTEXT, + * RM_TESLA_TESLA_CONTEXT, RM_IVAHD_IVAHD_CONTEXT, RM_IVAHD_SL2_CONTEXT + */ +#define OMAP4430_LOSTCONTEXT_DFF_SHIFT (1 << 0) +#define OMAP4430_LOSTCONTEXT_DFF_MASK BITFIELD(0, 0) + +/* + * Used by RM_D2D_MODEM_ICR_CONTEXT, RM_D2D_SAD2D_CONTEXT, + * RM_D2D_SAD2D_FW_CONTEXT, RM_DUCATI_DUCATI_CONTEXT, RM_L3INSTR_L3_3_CONTEXT, + * RM_L3INSTR_OCP_WP1_CONTEXT, RM_L3_1_L3_1_CONTEXT, RM_L3_2_GPMC_CONTEXT, + * RM_L3_2_L3_2_CONTEXT, RM_L4CFG_HW_SEM_CONTEXT, RM_L4CFG_L4_CFG_CONTEXT, + * RM_L4CFG_MAILBOX_CONTEXT, RM_MEMIF_DMM_CONTEXT, RM_MEMIF_EMIF_1_CONTEXT, + * RM_MEMIF_EMIF_2_CONTEXT, RM_MEMIF_EMIF_FW_CONTEXT, RM_MEMIF_EMIF_H1_CONTEXT, + * RM_MEMIF_EMIF_H2_CONTEXT, RM_SDMA_SDMA_CONTEXT, RM_L3INIT_HSI_CONTEXT, + * RM_L3INIT_MMC1_CONTEXT, RM_L3INIT_MMC2_CONTEXT, RM_L3INIT_MMC6_CONTEXT, + * RM_L3INIT_USB_HOST_CONTEXT, RM_L3INIT_USB_HOST_FS_CONTEXT, + * RM_L3INIT_USB_OTG_CONTEXT, RM_L3INIT_USB_TLL_CONTEXT, RM_DSS_DSS_CONTEXT, + * RM_L4PER_GPIO2_CONTEXT, RM_L4PER_GPIO3_CONTEXT, RM_L4PER_GPIO4_CONTEXT, + * RM_L4PER_GPIO5_CONTEXT, RM_L4PER_GPIO6_CONTEXT, RM_L4PER_I2C1_CONTEXT, + * RM_L4PER_L4_PER_CONTEXT, RM_L4PER_UART1_CONTEXT, RM_L4PER_UART2_CONTEXT, + * RM_L4PER_UART3_CONTEXT, RM_L4PER_UART4_CONTEXT, RM_L4SEC_AES1_CONTEXT, + * RM_L4SEC_AES2_CONTEXT, RM_L4SEC_CRYPTODMA_CONTEXT, RM_L4SEC_DES3DES_CONTEXT, + * RM_L4SEC_RNG_CONTEXT, RM_L4SEC_SHA2MD51_CONTEXT, RM_TESLA_TESLA_CONTEXT + */ +#define OMAP4430_LOSTCONTEXT_RFF_SHIFT (1 << 1) +#define OMAP4430_LOSTCONTEXT_RFF_MASK BITFIELD(1, 1) + +/* Used by RM_ABE_AESS_CONTEXT */ +#define OMAP4430_LOSTMEM_AESSMEM_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_AESSMEM_MASK BITFIELD(8, 8) + +/* Used by RM_CAM_FDIF_CONTEXT, RM_CAM_ISS_CONTEXT */ +#define OMAP4430_LOSTMEM_CAM_MEM_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_CAM_MEM_MASK BITFIELD(8, 8) + +/* Used by RM_L3INSTR_OCP_WP1_CONTEXT */ +#define OMAP4430_LOSTMEM_CORE_NRET_BANK_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_CORE_NRET_BANK_MASK BITFIELD(8, 8) + +/* Renamed from LOSTMEM_CORE_NRET_BANK Used by RM_MEMIF_DMM_CONTEXT */ +#define OMAP4430_LOSTMEM_CORE_NRET_BANK_9_9_SHIFT (1 << 9) +#define OMAP4430_LOSTMEM_CORE_NRET_BANK_9_9_MASK BITFIELD(9, 9) + +/* Used by RM_L3_2_OCMC_RAM_CONTEXT */ +#define OMAP4430_LOSTMEM_CORE_OCMRAM_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_CORE_OCMRAM_MASK BITFIELD(8, 8) + +/* + * Used by RM_D2D_MODEM_ICR_CONTEXT, RM_MEMIF_DMM_CONTEXT, + * RM_SDMA_SDMA_CONTEXT + */ +#define OMAP4430_LOSTMEM_CORE_OTHER_BANK_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_CORE_OTHER_BANK_MASK BITFIELD(8, 8) + +/* Used by RM_DSS_DEISS_CONTEXT, RM_DSS_DSS_CONTEXT */ +#define OMAP4430_LOSTMEM_DSS_MEM_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_DSS_MEM_MASK BITFIELD(8, 8) + +/* Used by RM_DUCATI_DUCATI_CONTEXT */ +#define OMAP4430_LOSTMEM_DUCATI_L2RAM_SHIFT (1 << 9) +#define OMAP4430_LOSTMEM_DUCATI_L2RAM_MASK BITFIELD(9, 9) + +/* Used by RM_DUCATI_DUCATI_CONTEXT */ +#define OMAP4430_LOSTMEM_DUCATI_UNICACHE_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_DUCATI_UNICACHE_MASK BITFIELD(8, 8) + +/* Used by RM_EMU_DEBUGSS_CONTEXT */ +#define OMAP4430_LOSTMEM_EMU_BANK_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_EMU_BANK_MASK BITFIELD(8, 8) + +/* Used by RM_GFX_GFX_CONTEXT */ +#define OMAP4430_LOSTMEM_GFX_MEM_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_GFX_MEM_MASK BITFIELD(8, 8) + +/* Used by RM_IVAHD_IVAHD_CONTEXT */ +#define OMAP4430_LOSTMEM_HWA_MEM_SHIFT (1 << 10) +#define OMAP4430_LOSTMEM_HWA_MEM_MASK BITFIELD(10, 10) + +/* + * Used by RM_L3INIT_CCPTX_CONTEXT, RM_L3INIT_EMAC_CONTEXT, + * RM_L3INIT_HSI_CONTEXT, RM_L3INIT_MMC1_CONTEXT, RM_L3INIT_MMC2_CONTEXT, + * RM_L3INIT_MMC6_CONTEXT, RM_L3INIT_PCIESS_CONTEXT, RM_L3INIT_SATA_CONTEXT, + * RM_L3INIT_TPPSS_CONTEXT, RM_L3INIT_UNIPRO1_CONTEXT, + * RM_L3INIT_USB_OTG_CONTEXT, RM_L3INIT_XHPI_CONTEXT + */ +#define OMAP4430_LOSTMEM_L3INIT_BANK1_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK BITFIELD(8, 8) + +/* Used by RM_MPU_MPU_CONTEXT */ +#define OMAP4430_LOSTMEM_MPU_L1_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_MPU_L1_MASK BITFIELD(8, 8) + +/* Used by RM_MPU_MPU_CONTEXT */ +#define OMAP4430_LOSTMEM_MPU_L2_SHIFT (1 << 9) +#define OMAP4430_LOSTMEM_MPU_L2_MASK BITFIELD(9, 9) + +/* Used by RM_MPU_MPU_CONTEXT */ +#define OMAP4430_LOSTMEM_MPU_RAM_SHIFT (1 << 10) +#define OMAP4430_LOSTMEM_MPU_RAM_MASK BITFIELD(10, 10) + +/* + * Used by RM_L4PER_HECC1_CONTEXT, RM_L4PER_HECC2_CONTEXT, + * RM_L4PER_MCBSP4_CONTEXT, RM_L4PER_MMCSD3_CONTEXT, RM_L4PER_MMCSD4_CONTEXT, + * RM_L4PER_MMCSD5_CONTEXT, RM_L4PER_SLIMBUS2_CONTEXT, RM_L4SEC_PKAEIP29_CONTEXT + */ +#define OMAP4430_LOSTMEM_NONRETAINED_BANK_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_NONRETAINED_BANK_MASK BITFIELD(8, 8) + +/* + * Used by RM_ABE_DMIC_CONTEXT, RM_ABE_MCBSP1_CONTEXT, RM_ABE_MCBSP2_CONTEXT, + * RM_ABE_MCBSP3_CONTEXT, RM_ABE_PDM_CONTEXT, RM_ABE_SLIMBUS_CONTEXT + */ +#define OMAP4430_LOSTMEM_PERIHPMEM_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_PERIHPMEM_MASK BITFIELD(8, 8) + +/* + * Used by RM_L4PER_MSPROHG_CONTEXT, RM_L4PER_UART1_CONTEXT, + * RM_L4PER_UART2_CONTEXT, RM_L4PER_UART3_CONTEXT, RM_L4PER_UART4_CONTEXT, + * RM_L4SEC_CRYPTODMA_CONTEXT + */ +#define OMAP4430_LOSTMEM_RETAINED_BANK_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_RETAINED_BANK_MASK BITFIELD(8, 8) + +/* Used by RM_IVAHD_SL2_CONTEXT */ +#define OMAP4430_LOSTMEM_SL2_MEM_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_SL2_MEM_MASK BITFIELD(8, 8) + +/* Used by RM_IVAHD_IVAHD_CONTEXT */ +#define OMAP4430_LOSTMEM_TCM1_MEM_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_TCM1_MEM_MASK BITFIELD(8, 8) + +/* Used by RM_IVAHD_IVAHD_CONTEXT */ +#define OMAP4430_LOSTMEM_TCM2_MEM_SHIFT (1 << 9) +#define OMAP4430_LOSTMEM_TCM2_MEM_MASK BITFIELD(9, 9) + +/* Used by RM_TESLA_TESLA_CONTEXT */ +#define OMAP4430_LOSTMEM_TESLA_EDMA_SHIFT (1 << 10) +#define OMAP4430_LOSTMEM_TESLA_EDMA_MASK BITFIELD(10, 10) + +/* Used by RM_TESLA_TESLA_CONTEXT */ +#define OMAP4430_LOSTMEM_TESLA_L1_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_TESLA_L1_MASK BITFIELD(8, 8) + +/* Used by RM_TESLA_TESLA_CONTEXT */ +#define OMAP4430_LOSTMEM_TESLA_L2_SHIFT (1 << 9) +#define OMAP4430_LOSTMEM_TESLA_L2_MASK BITFIELD(9, 9) + +/* Used by RM_WKUP_SARRAM_CONTEXT */ +#define OMAP4430_LOSTMEM_WKUP_BANK_SHIFT (1 << 8) +#define OMAP4430_LOSTMEM_WKUP_BANK_MASK BITFIELD(8, 8) + +/* + * Used by PM_CORE_PWRSTCTRL, PM_CAM_PWRSTCTRL, PM_L3INIT_PWRSTCTRL, + * PM_ABE_PWRSTCTRL, PM_GFX_PWRSTCTRL, PM_MPU_PWRSTCTRL, PM_CEFUSE_PWRSTCTRL, + * PM_DSS_PWRSTCTRL, PM_L4PER_PWRSTCTRL, PM_TESLA_PWRSTCTRL, PM_IVAHD_PWRSTCTRL + */ +#define OMAP4430_LOWPOWERSTATECHANGE_SHIFT (1 << 4) +#define OMAP4430_LOWPOWERSTATECHANGE_MASK BITFIELD(4, 4) + +/* Used by PM_CORE_PWRSTCTRL */ +#define OMAP4430_MEMORYCHANGE_SHIFT (1 << 3) +#define OMAP4430_MEMORYCHANGE_MASK BITFIELD(3, 3) + +/* Used by PRM_MODEM_IF_CTRL */ +#define OMAP4430_MODEM_READY_SHIFT (1 << 1) +#define OMAP4430_MODEM_READY_MASK BITFIELD(1, 1) + +/* Used by PRM_MODEM_IF_CTRL */ +#define OMAP4430_MODEM_SHUTDOWN_IRQ_SHIFT (1 << 9) +#define OMAP4430_MODEM_SHUTDOWN_IRQ_MASK BITFIELD(9, 9) + +/* Used by PRM_MODEM_IF_CTRL */ +#define OMAP4430_MODEM_SLEEP_ST_SHIFT (1 << 16) +#define OMAP4430_MODEM_SLEEP_ST_MASK BITFIELD(16, 16) + +/* Used by PRM_MODEM_IF_CTRL */ +#define OMAP4430_MODEM_WAKE_IRQ_SHIFT (1 << 8) +#define OMAP4430_MODEM_WAKE_IRQ_MASK BITFIELD(8, 8) + +/* Used by PM_MPU_PWRSTCTRL */ +#define OMAP4430_MPU_L1_ONSTATE_SHIFT (1 << 16) +#define OMAP4430_MPU_L1_ONSTATE_MASK BITFIELD(16, 17) + +/* Used by PM_MPU_PWRSTCTRL */ +#define OMAP4430_MPU_L1_RETSTATE_SHIFT (1 << 8) +#define OMAP4430_MPU_L1_RETSTATE_MASK BITFIELD(8, 8) + +/* Used by PM_MPU_PWRSTST */ +#define OMAP4430_MPU_L1_STATEST_SHIFT (1 << 4) +#define OMAP4430_MPU_L1_STATEST_MASK BITFIELD(4, 5) + +/* Used by PM_MPU_PWRSTCTRL */ +#define OMAP4430_MPU_L2_ONSTATE_SHIFT (1 << 18) +#define OMAP4430_MPU_L2_ONSTATE_MASK BITFIELD(18, 19) + +/* Used by PM_MPU_PWRSTCTRL */ +#define OMAP4430_MPU_L2_RETSTATE_SHIFT (1 << 9) +#define OMAP4430_MPU_L2_RETSTATE_MASK BITFIELD(9, 9) + +/* Used by PM_MPU_PWRSTST */ +#define OMAP4430_MPU_L2_STATEST_SHIFT (1 << 6) +#define OMAP4430_MPU_L2_STATEST_MASK BITFIELD(6, 7) + +/* Used by PM_MPU_PWRSTCTRL */ +#define OMAP4430_MPU_RAM_ONSTATE_SHIFT (1 << 20) +#define OMAP4430_MPU_RAM_ONSTATE_MASK BITFIELD(20, 21) + +/* Used by PM_MPU_PWRSTCTRL */ +#define OMAP4430_MPU_RAM_RETSTATE_SHIFT (1 << 10) +#define OMAP4430_MPU_RAM_RETSTATE_MASK BITFIELD(10, 10) + +/* Used by PM_MPU_PWRSTST */ +#define OMAP4430_MPU_RAM_STATEST_SHIFT (1 << 8) +#define OMAP4430_MPU_RAM_STATEST_MASK BITFIELD(8, 9) + +/* Used by PRM_RSTST */ +#define OMAP4430_MPU_SECURITY_VIOL_RST_SHIFT (1 << 2) +#define OMAP4430_MPU_SECURITY_VIOL_RST_MASK BITFIELD(2, 2) + +/* Used by PRM_RSTST */ +#define OMAP4430_MPU_WDT_RST_SHIFT (1 << 3) +#define OMAP4430_MPU_WDT_RST_MASK BITFIELD(3, 3) + +/* Used by PM_L4PER_PWRSTCTRL */ +#define OMAP4430_NONRETAINED_BANK_ONSTATE_SHIFT (1 << 18) +#define OMAP4430_NONRETAINED_BANK_ONSTATE_MASK BITFIELD(18, 19) + +/* Used by PM_L4PER_PWRSTCTRL */ +#define OMAP4430_NONRETAINED_BANK_RETSTATE_SHIFT (1 << 9) +#define OMAP4430_NONRETAINED_BANK_RETSTATE_MASK BITFIELD(9, 9) + +/* Used by PM_L4PER_PWRSTST */ +#define OMAP4430_NONRETAINED_BANK_STATEST_SHIFT (1 << 6) +#define OMAP4430_NONRETAINED_BANK_STATEST_MASK BITFIELD(6, 7) + +/* Used by PM_CORE_PWRSTCTRL */ +#define OMAP4430_OCP_NRET_BANK_ONSTATE_SHIFT (1 << 24) +#define OMAP4430_OCP_NRET_BANK_ONSTATE_MASK BITFIELD(24, 25) + +/* Used by PM_CORE_PWRSTCTRL */ +#define OMAP4430_OCP_NRET_BANK_RETSTATE_SHIFT (1 << 12) +#define OMAP4430_OCP_NRET_BANK_RETSTATE_MASK BITFIELD(12, 12) + +/* Used by PM_CORE_PWRSTST */ +#define OMAP4430_OCP_NRET_BANK_STATEST_SHIFT (1 << 12) +#define OMAP4430_OCP_NRET_BANK_STATEST_MASK BITFIELD(12, 13) + +/* + * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L, + * PRM_VC_VAL_CMD_VDD_MPU_L + */ +#define OMAP4430_OFF_SHIFT (1 << 0) +#define OMAP4430_OFF_MASK BITFIELD(0, 7) + +/* Used by PRM_LDO_BANDGAP_CTRL */ +#define OMAP4430_OFF_ENABLE_SHIFT (1 << 0) +#define OMAP4430_OFF_ENABLE_MASK BITFIELD(0, 0) + +/* + * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L, + * PRM_VC_VAL_CMD_VDD_MPU_L + */ +#define OMAP4430_ON_SHIFT (1 << 24) +#define OMAP4430_ON_MASK BITFIELD(24, 31) + +/* + * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L, + * PRM_VC_VAL_CMD_VDD_MPU_L + */ +#define OMAP4430_ONLP_SHIFT (1 << 16) +#define OMAP4430_ONLP_MASK BITFIELD(16, 23) + +/* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */ +#define OMAP4430_OPP_CHANGE_SHIFT (1 << 2) +#define OMAP4430_OPP_CHANGE_MASK BITFIELD(2, 2) + +/* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */ +#define OMAP4430_OPP_SEL_SHIFT (1 << 0) +#define OMAP4430_OPP_SEL_MASK BITFIELD(0, 1) + +/* Used by PRM_SRAM_COUNT */ +#define OMAP4430_PCHARGECNT_VALUE_SHIFT (1 << 0) +#define OMAP4430_PCHARGECNT_VALUE_MASK BITFIELD(0, 5) + +/* Used by PRM_PSCON_COUNT */ +#define OMAP4430_PCHARGE_TIME_SHIFT (1 << 0) +#define OMAP4430_PCHARGE_TIME_MASK BITFIELD(0, 7) + +/* Used by PM_ABE_PWRSTCTRL */ +#define OMAP4430_PERIPHMEM_ONSTATE_SHIFT (1 << 20) +#define OMAP4430_PERIPHMEM_ONSTATE_MASK BITFIELD(20, 21) + +/* Used by PM_ABE_PWRSTCTRL */ +#define OMAP4430_PERIPHMEM_RETSTATE_SHIFT (1 << 10) +#define OMAP4430_PERIPHMEM_RETSTATE_MASK BITFIELD(10, 10) + +/* Used by PM_ABE_PWRSTST */ +#define OMAP4430_PERIPHMEM_STATEST_SHIFT (1 << 8) +#define OMAP4430_PERIPHMEM_STATEST_MASK BITFIELD(8, 9) + +/* Used by PRM_PHASE1_CNDP */ +#define OMAP4430_PHASE1_CNDP_SHIFT (1 << 0) +#define OMAP4430_PHASE1_CNDP_MASK BITFIELD(0, 31) + +/* Used by PRM_PHASE2A_CNDP */ +#define OMAP4430_PHASE2A_CNDP_SHIFT (1 << 0) +#define OMAP4430_PHASE2A_CNDP_MASK BITFIELD(0, 31) + +/* Used by PRM_PHASE2B_CNDP */ +#define OMAP4430_PHASE2B_CNDP_SHIFT (1 << 0) +#define OMAP4430_PHASE2B_CNDP_MASK BITFIELD(0, 31) + +/* Used by PRM_PSCON_COUNT */ +#define OMAP4430_PONOUT_2_PGOODIN_TIME_SHIFT (1 << 8) +#define OMAP4430_PONOUT_2_PGOODIN_TIME_MASK BITFIELD(8, 15) + +/* + * Used by PM_EMU_PWRSTCTRL, PM_CORE_PWRSTCTRL, PM_CAM_PWRSTCTRL, + * PM_L3INIT_PWRSTCTRL, PM_ABE_PWRSTCTRL, PM_GFX_PWRSTCTRL, PM_MPU_PWRSTCTRL, + * PM_CEFUSE_PWRSTCTRL, PM_DSS_PWRSTCTRL, PM_L4PER_PWRSTCTRL, + * PM_TESLA_PWRSTCTRL, PM_IVAHD_PWRSTCTRL + */ +#define OMAP4430_POWERSTATE_SHIFT (1 << 0) +#define OMAP4430_POWERSTATE_MASK BITFIELD(0, 1) + +/* + * Used by PM_EMU_PWRSTST, PM_CORE_PWRSTST, PM_CAM_PWRSTST, PM_L3INIT_PWRSTST, + * PM_ABE_PWRSTST, PM_GFX_PWRSTST, PM_MPU_PWRSTST, PM_CEFUSE_PWRSTST, + * PM_DSS_PWRSTST, PM_L4PER_PWRSTST, PM_TESLA_PWRSTST, PM_IVAHD_PWRSTST + */ +#define OMAP4430_POWERSTATEST_SHIFT (1 << 0) +#define OMAP4430_POWERSTATEST_MASK BITFIELD(0, 1) + +/* Used by PRM_PWRREQCTRL */ +#define OMAP4430_PWRREQ_COND_SHIFT (1 << 0) +#define OMAP4430_PWRREQ_COND_MASK BITFIELD(0, 1) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_RACEN_VDD_CORE_L_SHIFT (1 << 3) +#define OMAP4430_RACEN_VDD_CORE_L_MASK BITFIELD(3, 3) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_RACEN_VDD_IVA_L_SHIFT (1 << 11) +#define OMAP4430_RACEN_VDD_IVA_L_MASK BITFIELD(11, 11) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_RACEN_VDD_MPU_L_SHIFT (1 << 20) +#define OMAP4430_RACEN_VDD_MPU_L_MASK BITFIELD(20, 20) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_RAC_VDD_CORE_L_SHIFT (1 << 2) +#define OMAP4430_RAC_VDD_CORE_L_MASK BITFIELD(2, 2) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_RAC_VDD_IVA_L_SHIFT (1 << 10) +#define OMAP4430_RAC_VDD_IVA_L_MASK BITFIELD(10, 10) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_RAC_VDD_MPU_L_SHIFT (1 << 19) +#define OMAP4430_RAC_VDD_MPU_L_MASK BITFIELD(19, 19) + +/* + * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP, + * PRM_VOLTSETUP_IVA_OFF, PRM_VOLTSETUP_IVA_RET_SLEEP, PRM_VOLTSETUP_MPU_OFF, + * PRM_VOLTSETUP_MPU_RET_SLEEP + */ +#define OMAP4430_RAMP_DOWN_COUNT_SHIFT (1 << 16) +#define OMAP4430_RAMP_DOWN_COUNT_MASK BITFIELD(16, 21) + +/* + * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP, + * PRM_VOLTSETUP_IVA_OFF, PRM_VOLTSETUP_IVA_RET_SLEEP, PRM_VOLTSETUP_MPU_OFF, + * PRM_VOLTSETUP_MPU_RET_SLEEP + */ +#define OMAP4430_RAMP_DOWN_PRESCAL_SHIFT (1 << 24) +#define OMAP4430_RAMP_DOWN_PRESCAL_MASK BITFIELD(24, 25) + +/* + * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP, + * PRM_VOLTSETUP_IVA_OFF, PRM_VOLTSETUP_IVA_RET_SLEEP, PRM_VOLTSETUP_MPU_OFF, + * PRM_VOLTSETUP_MPU_RET_SLEEP + */ +#define OMAP4430_RAMP_UP_COUNT_SHIFT (1 << 0) +#define OMAP4430_RAMP_UP_COUNT_MASK BITFIELD(0, 5) + +/* + * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP, + * PRM_VOLTSETUP_IVA_OFF, PRM_VOLTSETUP_IVA_RET_SLEEP, PRM_VOLTSETUP_MPU_OFF, + * PRM_VOLTSETUP_MPU_RET_SLEEP + */ +#define OMAP4430_RAMP_UP_PRESCAL_SHIFT (1 << 8) +#define OMAP4430_RAMP_UP_PRESCAL_MASK BITFIELD(8, 9) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_RAV_VDD_CORE_L_SHIFT (1 << 1) +#define OMAP4430_RAV_VDD_CORE_L_MASK BITFIELD(1, 1) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_RAV_VDD_IVA_L_SHIFT (1 << 9) +#define OMAP4430_RAV_VDD_IVA_L_MASK BITFIELD(9, 9) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_RAV_VDD_MPU_L_SHIFT (1 << 18) +#define OMAP4430_RAV_VDD_MPU_L_MASK BITFIELD(18, 18) + +/* Used by PRM_VC_VAL_BYPASS */ +#define OMAP4430_REGADDR_SHIFT (1 << 8) +#define OMAP4430_REGADDR_MASK BITFIELD(8, 15) + +/* + * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L, + * PRM_VC_VAL_CMD_VDD_MPU_L + */ +#define OMAP4430_RET_SHIFT (1 << 8) +#define OMAP4430_RET_MASK BITFIELD(8, 15) + +/* Used by PM_L4PER_PWRSTCTRL */ +#define OMAP4430_RETAINED_BANK_ONSTATE_SHIFT (1 << 16) +#define OMAP4430_RETAINED_BANK_ONSTATE_MASK BITFIELD(16, 17) + +/* Used by PM_L4PER_PWRSTCTRL */ +#define OMAP4430_RETAINED_BANK_RETSTATE_SHIFT (1 << 8) +#define OMAP4430_RETAINED_BANK_RETSTATE_MASK BITFIELD(8, 8) + +/* Used by PM_L4PER_PWRSTST */ +#define OMAP4430_RETAINED_BANK_STATEST_SHIFT (1 << 4) +#define OMAP4430_RETAINED_BANK_STATEST_MASK BITFIELD(4, 5) + +/* + * Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_IVA_CTRL, + * PRM_LDO_SRAM_MPU_CTRL + */ +#define OMAP4430_RETMODE_ENABLE_SHIFT (1 << 0) +#define OMAP4430_RETMODE_ENABLE_MASK BITFIELD(0, 0) + +/* Used by REVISION_PRM */ +#define OMAP4430_REV_SHIFT (1 << 0) +#define OMAP4430_REV_MASK BITFIELD(0, 7) + +/* Used by RM_DUCATI_RSTCTRL, RM_TESLA_RSTCTRL, RM_IVAHD_RSTCTRL */ +#define OMAP4430_RST1_SHIFT (1 << 0) +#define OMAP4430_RST1_MASK BITFIELD(0, 0) + +/* Used by RM_DUCATI_RSTST, RM_TESLA_RSTST, RM_IVAHD_RSTST */ +#define OMAP4430_RST1ST_SHIFT (1 << 0) +#define OMAP4430_RST1ST_MASK BITFIELD(0, 0) + +/* Used by RM_DUCATI_RSTCTRL, RM_TESLA_RSTCTRL, RM_IVAHD_RSTCTRL */ +#define OMAP4430_RST2_SHIFT (1 << 1) +#define OMAP4430_RST2_MASK BITFIELD(1, 1) + +/* Used by RM_DUCATI_RSTST, RM_TESLA_RSTST, RM_IVAHD_RSTST */ +#define OMAP4430_RST2ST_SHIFT (1 << 1) +#define OMAP4430_RST2ST_MASK BITFIELD(1, 1) + +/* Used by RM_DUCATI_RSTCTRL, RM_IVAHD_RSTCTRL */ +#define OMAP4430_RST3_SHIFT (1 << 2) +#define OMAP4430_RST3_MASK BITFIELD(2, 2) + +/* Used by RM_DUCATI_RSTST, RM_IVAHD_RSTST */ +#define OMAP4430_RST3ST_SHIFT (1 << 2) +#define OMAP4430_RST3ST_MASK BITFIELD(2, 2) + +/* Used by PRM_RSTTIME */ +#define OMAP4430_RSTTIME1_SHIFT (1 << 0) +#define OMAP4430_RSTTIME1_MASK BITFIELD(0, 9) + +/* Used by PRM_RSTTIME */ +#define OMAP4430_RSTTIME2_SHIFT (1 << 10) +#define OMAP4430_RSTTIME2_MASK BITFIELD(10, 14) + +/* Used by PRM_RSTCTRL */ +#define OMAP4430_RST_GLOBAL_COLD_SW_SHIFT (1 << 1) +#define OMAP4430_RST_GLOBAL_COLD_SW_MASK BITFIELD(1, 1) + +/* Used by PRM_RSTCTRL */ +#define OMAP4430_RST_GLOBAL_WARM_SW_SHIFT (1 << 0) +#define OMAP4430_RST_GLOBAL_WARM_SW_MASK BITFIELD(0, 0) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_SA_VDD_CORE_L_SHIFT (1 << 0) +#define OMAP4430_SA_VDD_CORE_L_MASK BITFIELD(0, 0) + +/* Renamed from SA_VDD_CORE_L Used by PRM_VC_SMPS_SA */ +#define OMAP4430_SA_VDD_CORE_L_0_6_SHIFT (1 << 0) +#define OMAP4430_SA_VDD_CORE_L_0_6_MASK BITFIELD(0, 6) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_SA_VDD_IVA_L_SHIFT (1 << 8) +#define OMAP4430_SA_VDD_IVA_L_MASK BITFIELD(8, 8) + +/* Renamed from SA_VDD_IVA_L Used by PRM_VC_SMPS_SA */ +#define OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT (1 << 8) +#define OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK BITFIELD(8, 14) + +/* Used by PRM_VC_CFG_CHANNEL */ +#define OMAP4430_SA_VDD_MPU_L_SHIFT (1 << 16) +#define OMAP4430_SA_VDD_MPU_L_MASK BITFIELD(16, 16) + +/* Renamed from SA_VDD_MPU_L Used by PRM_VC_SMPS_SA */ +#define OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT (1 << 16) +#define OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK BITFIELD(16, 22) + +/* Used by PRM_VC_CFG_I2C_CLK */ +#define OMAP4430_SCLH_SHIFT (1 << 0) +#define OMAP4430_SCLH_MASK BITFIELD(0, 7) + +/* Used by PRM_VC_CFG_I2C_CLK */ +#define OMAP4430_SCLL_SHIFT (1 << 8) +#define OMAP4430_SCLL_MASK BITFIELD(8, 15) + +/* Used by PRM_RSTST */ +#define OMAP4430_SECURE_WDT_RST_SHIFT (1 << 4) +#define OMAP4430_SECURE_WDT_RST_MASK BITFIELD(4, 4) + +/* Used by PM_IVAHD_PWRSTCTRL */ +#define OMAP4430_SL2_MEM_ONSTATE_SHIFT (1 << 18) +#define OMAP4430_SL2_MEM_ONSTATE_MASK BITFIELD(18, 19) + +/* Used by PM_IVAHD_PWRSTCTRL */ +#define OMAP4430_SL2_MEM_RETSTATE_SHIFT (1 << 9) +#define OMAP4430_SL2_MEM_RETSTATE_MASK BITFIELD(9, 9) + +/* Used by PM_IVAHD_PWRSTST */ +#define OMAP4430_SL2_MEM_STATEST_SHIFT (1 << 6) +#define OMAP4430_SL2_MEM_STATEST_MASK BITFIELD(6, 7) + +/* Used by PRM_VC_VAL_BYPASS */ +#define OMAP4430_SLAVEADDR_SHIFT (1 << 0) +#define OMAP4430_SLAVEADDR_MASK BITFIELD(0, 6) + +/* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */ +#define OMAP4430_SLEEP_RBB_SEL_SHIFT (1 << 3) +#define OMAP4430_SLEEP_RBB_SEL_MASK BITFIELD(3, 3) + +/* Used by PRM_SRAM_COUNT */ +#define OMAP4430_SLPCNT_VALUE_SHIFT (1 << 16) +#define OMAP4430_SLPCNT_VALUE_MASK BITFIELD(16, 23) + +/* Used by PRM_VP_CORE_VSTEPMAX, PRM_VP_IVA_VSTEPMAX, PRM_VP_MPU_VSTEPMAX */ +#define OMAP4430_SMPSWAITTIMEMAX_SHIFT (1 << 8) +#define OMAP4430_SMPSWAITTIMEMAX_MASK BITFIELD(8, 23) + +/* Used by PRM_VP_CORE_VSTEPMIN, PRM_VP_IVA_VSTEPMIN, PRM_VP_MPU_VSTEPMIN */ +#define OMAP4430_SMPSWAITTIMEMIN_SHIFT (1 << 8) +#define OMAP4430_SMPSWAITTIMEMIN_MASK BITFIELD(8, 23) + +/* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */ +#define OMAP4430_SR2EN_SHIFT (1 << 0) +#define OMAP4430_SR2EN_MASK BITFIELD(0, 0) + +/* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */ +#define OMAP4430_SR2_IN_TRANSITION_SHIFT (1 << 6) +#define OMAP4430_SR2_IN_TRANSITION_MASK BITFIELD(6, 6) + +/* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */ +#define OMAP4430_SR2_STATUS_SHIFT (1 << 3) +#define OMAP4430_SR2_STATUS_MASK BITFIELD(3, 4) + +/* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */ +#define OMAP4430_SR2_WTCNT_VALUE_SHIFT (1 << 8) +#define OMAP4430_SR2_WTCNT_VALUE_MASK BITFIELD(8, 15) + +/* + * Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_IVA_CTRL, + * PRM_LDO_SRAM_MPU_CTRL + */ +#define OMAP4430_SRAMLDO_STATUS_SHIFT (1 << 8) +#define OMAP4430_SRAMLDO_STATUS_MASK BITFIELD(8, 8) + +/* + * Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_IVA_CTRL, + * PRM_LDO_SRAM_MPU_CTRL + */ +#define OMAP4430_SRAM_IN_TRANSITION_SHIFT (1 << 9) +#define OMAP4430_SRAM_IN_TRANSITION_MASK BITFIELD(9, 9) + +/* Used by PRM_VC_CFG_I2C_MODE */ +#define OMAP4430_SRMODEEN_SHIFT (1 << 4) +#define OMAP4430_SRMODEEN_MASK BITFIELD(4, 4) + +/* Used by PRM_VOLTSETUP_WARMRESET */ +#define OMAP4430_STABLE_COUNT_SHIFT (1 << 0) +#define OMAP4430_STABLE_COUNT_MASK BITFIELD(0, 5) + +/* Used by PRM_VOLTSETUP_WARMRESET */ +#define OMAP4430_STABLE_PRESCAL_SHIFT (1 << 8) +#define OMAP4430_STABLE_PRESCAL_MASK BITFIELD(8, 9) + +/* Used by PM_IVAHD_PWRSTCTRL */ +#define OMAP4430_TCM1_MEM_ONSTATE_SHIFT (1 << 20) +#define OMAP4430_TCM1_MEM_ONSTATE_MASK BITFIELD(20, 21) + +/* Used by PM_IVAHD_PWRSTCTRL */ +#define OMAP4430_TCM1_MEM_RETSTATE_SHIFT (1 << 10) +#define OMAP4430_TCM1_MEM_RETSTATE_MASK BITFIELD(10, 10) + +/* Used by PM_IVAHD_PWRSTST */ +#define OMAP4430_TCM1_MEM_STATEST_SHIFT (1 << 8) +#define OMAP4430_TCM1_MEM_STATEST_MASK BITFIELD(8, 9) + +/* Used by PM_IVAHD_PWRSTCTRL */ +#define OMAP4430_TCM2_MEM_ONSTATE_SHIFT (1 << 22) +#define OMAP4430_TCM2_MEM_ONSTATE_MASK BITFIELD(22, 23) + +/* Used by PM_IVAHD_PWRSTCTRL */ +#define OMAP4430_TCM2_MEM_RETSTATE_SHIFT (1 << 11) +#define OMAP4430_TCM2_MEM_RETSTATE_MASK BITFIELD(11, 11) + +/* Used by PM_IVAHD_PWRSTST */ +#define OMAP4430_TCM2_MEM_STATEST_SHIFT (1 << 10) +#define OMAP4430_TCM2_MEM_STATEST_MASK BITFIELD(10, 11) + +/* Used by RM_TESLA_RSTST */ +#define OMAP4430_TESLASS_EMU_RSTST_SHIFT (1 << 2) +#define OMAP4430_TESLASS_EMU_RSTST_MASK BITFIELD(2, 2) + +/* Used by RM_TESLA_RSTST */ +#define OMAP4430_TESLA_DSP_EMU_REQ_RSTST_SHIFT (1 << 3) +#define OMAP4430_TESLA_DSP_EMU_REQ_RSTST_MASK BITFIELD(3, 3) + +/* Used by PM_TESLA_PWRSTCTRL */ +#define OMAP4430_TESLA_EDMA_ONSTATE_SHIFT (1 << 20) +#define OMAP4430_TESLA_EDMA_ONSTATE_MASK BITFIELD(20, 21) + +/* Used by PM_TESLA_PWRSTCTRL */ +#define OMAP4430_TESLA_EDMA_RETSTATE_SHIFT (1 << 10) +#define OMAP4430_TESLA_EDMA_RETSTATE_MASK BITFIELD(10, 10) + +/* Used by PM_TESLA_PWRSTST */ +#define OMAP4430_TESLA_EDMA_STATEST_SHIFT (1 << 8) +#define OMAP4430_TESLA_EDMA_STATEST_MASK BITFIELD(8, 9) + +/* Used by PM_TESLA_PWRSTCTRL */ +#define OMAP4430_TESLA_L1_ONSTATE_SHIFT (1 << 16) +#define OMAP4430_TESLA_L1_ONSTATE_MASK BITFIELD(16, 17) + +/* Used by PM_TESLA_PWRSTCTRL */ +#define OMAP4430_TESLA_L1_RETSTATE_SHIFT (1 << 8) +#define OMAP4430_TESLA_L1_RETSTATE_MASK BITFIELD(8, 8) + +/* Used by PM_TESLA_PWRSTST */ +#define OMAP4430_TESLA_L1_STATEST_SHIFT (1 << 4) +#define OMAP4430_TESLA_L1_STATEST_MASK BITFIELD(4, 5) + +/* Used by PM_TESLA_PWRSTCTRL */ +#define OMAP4430_TESLA_L2_ONSTATE_SHIFT (1 << 18) +#define OMAP4430_TESLA_L2_ONSTATE_MASK BITFIELD(18, 19) + +/* Used by PM_TESLA_PWRSTCTRL */ +#define OMAP4430_TESLA_L2_RETSTATE_SHIFT (1 << 9) +#define OMAP4430_TESLA_L2_RETSTATE_MASK BITFIELD(9, 9) + +/* Used by PM_TESLA_PWRSTST */ +#define OMAP4430_TESLA_L2_STATEST_SHIFT (1 << 6) +#define OMAP4430_TESLA_L2_STATEST_MASK BITFIELD(6, 7) + +/* Used by PRM_VP_CORE_VLIMITTO, PRM_VP_IVA_VLIMITTO, PRM_VP_MPU_VLIMITTO */ +#define OMAP4430_TIMEOUT_SHIFT (1 << 0) +#define OMAP4430_TIMEOUT_MASK BITFIELD(0, 15) + +/* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */ +#define OMAP4430_TIMEOUTEN_SHIFT (1 << 3) +#define OMAP4430_TIMEOUTEN_MASK BITFIELD(3, 3) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_TRANSITION_EN_SHIFT (1 << 8) +#define OMAP4430_TRANSITION_EN_MASK BITFIELD(8, 8) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_TRANSITION_ST_SHIFT (1 << 8) +#define OMAP4430_TRANSITION_ST_MASK BITFIELD(8, 8) + +/* Used by PRM_VC_VAL_BYPASS */ +#define OMAP4430_VALID_SHIFT (1 << 24) +#define OMAP4430_VALID_MASK BITFIELD(24, 24) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VC_BYPASSACK_EN_SHIFT (1 << 14) +#define OMAP4430_VC_BYPASSACK_EN_MASK BITFIELD(14, 14) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VC_BYPASSACK_ST_SHIFT (1 << 14) +#define OMAP4430_VC_BYPASSACK_ST_MASK BITFIELD(14, 14) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VC_IVA_VPACK_EN_SHIFT (1 << 30) +#define OMAP4430_VC_IVA_VPACK_EN_MASK BITFIELD(30, 30) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VC_IVA_VPACK_ST_SHIFT (1 << 30) +#define OMAP4430_VC_IVA_VPACK_ST_MASK BITFIELD(30, 30) + +/* Used by PRM_IRQENABLE_MPU_2 */ +#define OMAP4430_VC_MPU_VPACK_EN_SHIFT (1 << 6) +#define OMAP4430_VC_MPU_VPACK_EN_MASK BITFIELD(6, 6) + +/* Used by PRM_IRQSTATUS_MPU_2 */ +#define OMAP4430_VC_MPU_VPACK_ST_SHIFT (1 << 6) +#define OMAP4430_VC_MPU_VPACK_ST_MASK BITFIELD(6, 6) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VC_RAERR_EN_SHIFT (1 << 12) +#define OMAP4430_VC_RAERR_EN_MASK BITFIELD(12, 12) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VC_RAERR_ST_SHIFT (1 << 12) +#define OMAP4430_VC_RAERR_ST_MASK BITFIELD(12, 12) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VC_SAERR_EN_SHIFT (1 << 11) +#define OMAP4430_VC_SAERR_EN_MASK BITFIELD(11, 11) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VC_SAERR_ST_SHIFT (1 << 11) +#define OMAP4430_VC_SAERR_ST_MASK BITFIELD(11, 11) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VC_TOERR_EN_SHIFT (1 << 13) +#define OMAP4430_VC_TOERR_EN_MASK BITFIELD(13, 13) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VC_TOERR_ST_SHIFT (1 << 13) +#define OMAP4430_VC_TOERR_ST_MASK BITFIELD(13, 13) + +/* Used by PRM_VP_CORE_VLIMITTO, PRM_VP_IVA_VLIMITTO, PRM_VP_MPU_VLIMITTO */ +#define OMAP4430_VDDMAX_SHIFT (1 << 24) +#define OMAP4430_VDDMAX_MASK BITFIELD(24, 31) + +/* Used by PRM_VP_CORE_VLIMITTO, PRM_VP_IVA_VLIMITTO, PRM_VP_MPU_VLIMITTO */ +#define OMAP4430_VDDMIN_SHIFT (1 << 16) +#define OMAP4430_VDDMIN_MASK BITFIELD(16, 23) + +/* Used by PRM_VOLTCTRL */ +#define OMAP4430_VDD_CORE_I2C_DISABLE_SHIFT (1 << 12) +#define OMAP4430_VDD_CORE_I2C_DISABLE_MASK BITFIELD(12, 12) + +/* Used by PRM_RSTST */ +#define OMAP4430_VDD_CORE_VOLT_MGR_RST_SHIFT (1 << 8) +#define OMAP4430_VDD_CORE_VOLT_MGR_RST_MASK BITFIELD(8, 8) + +/* Used by PRM_VOLTCTRL */ +#define OMAP4430_VDD_IVA_I2C_DISABLE_SHIFT (1 << 14) +#define OMAP4430_VDD_IVA_I2C_DISABLE_MASK BITFIELD(14, 14) + +/* Used by PRM_VOLTCTRL */ +#define OMAP4430_VDD_IVA_PRESENCE_SHIFT (1 << 9) +#define OMAP4430_VDD_IVA_PRESENCE_MASK BITFIELD(9, 9) + +/* Used by PRM_RSTST */ +#define OMAP4430_VDD_IVA_VOLT_MGR_RST_SHIFT (1 << 7) +#define OMAP4430_VDD_IVA_VOLT_MGR_RST_MASK BITFIELD(7, 7) + +/* Used by PRM_VOLTCTRL */ +#define OMAP4430_VDD_MPU_I2C_DISABLE_SHIFT (1 << 13) +#define OMAP4430_VDD_MPU_I2C_DISABLE_MASK BITFIELD(13, 13) + +/* Used by PRM_VOLTCTRL */ +#define OMAP4430_VDD_MPU_PRESENCE_SHIFT (1 << 8) +#define OMAP4430_VDD_MPU_PRESENCE_MASK BITFIELD(8, 8) + +/* Used by PRM_RSTST */ +#define OMAP4430_VDD_MPU_VOLT_MGR_RST_SHIFT (1 << 6) +#define OMAP4430_VDD_MPU_VOLT_MGR_RST_MASK BITFIELD(6, 6) + +/* Used by PRM_VC_VAL_SMPS_RA_VOL */ +#define OMAP4430_VOLRA_VDD_CORE_L_SHIFT (1 << 0) +#define OMAP4430_VOLRA_VDD_CORE_L_MASK BITFIELD(0, 7) + +/* Used by PRM_VC_VAL_SMPS_RA_VOL */ +#define OMAP4430_VOLRA_VDD_IVA_L_SHIFT (1 << 8) +#define OMAP4430_VOLRA_VDD_IVA_L_MASK BITFIELD(8, 15) + +/* Used by PRM_VC_VAL_SMPS_RA_VOL */ +#define OMAP4430_VOLRA_VDD_MPU_L_SHIFT (1 << 16) +#define OMAP4430_VOLRA_VDD_MPU_L_MASK BITFIELD(16, 23) + +/* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */ +#define OMAP4430_VPENABLE_SHIFT (1 << 0) +#define OMAP4430_VPENABLE_MASK BITFIELD(0, 0) + +/* Used by PRM_VP_CORE_STATUS, PRM_VP_IVA_STATUS, PRM_VP_MPU_STATUS */ +#define OMAP4430_VPINIDLE_SHIFT (1 << 0) +#define OMAP4430_VPINIDLE_MASK BITFIELD(0, 0) + +/* Used by PRM_VP_CORE_VOLTAGE, PRM_VP_IVA_VOLTAGE, PRM_VP_MPU_VOLTAGE */ +#define OMAP4430_VPVOLTAGE_SHIFT (1 << 0) +#define OMAP4430_VPVOLTAGE_MASK BITFIELD(0, 7) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VP_CORE_EQVALUE_EN_SHIFT (1 << 20) +#define OMAP4430_VP_CORE_EQVALUE_EN_MASK BITFIELD(20, 20) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VP_CORE_EQVALUE_ST_SHIFT (1 << 20) +#define OMAP4430_VP_CORE_EQVALUE_ST_MASK BITFIELD(20, 20) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VP_CORE_MAXVDD_EN_SHIFT (1 << 18) +#define OMAP4430_VP_CORE_MAXVDD_EN_MASK BITFIELD(18, 18) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VP_CORE_MAXVDD_ST_SHIFT (1 << 18) +#define OMAP4430_VP_CORE_MAXVDD_ST_MASK BITFIELD(18, 18) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VP_CORE_MINVDD_EN_SHIFT (1 << 17) +#define OMAP4430_VP_CORE_MINVDD_EN_MASK BITFIELD(17, 17) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VP_CORE_MINVDD_ST_SHIFT (1 << 17) +#define OMAP4430_VP_CORE_MINVDD_ST_MASK BITFIELD(17, 17) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VP_CORE_NOSMPSACK_EN_SHIFT (1 << 19) +#define OMAP4430_VP_CORE_NOSMPSACK_EN_MASK BITFIELD(19, 19) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VP_CORE_NOSMPSACK_ST_SHIFT (1 << 19) +#define OMAP4430_VP_CORE_NOSMPSACK_ST_MASK BITFIELD(19, 19) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VP_CORE_OPPCHANGEDONE_EN_SHIFT (1 << 16) +#define OMAP4430_VP_CORE_OPPCHANGEDONE_EN_MASK BITFIELD(16, 16) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VP_CORE_OPPCHANGEDONE_ST_SHIFT (1 << 16) +#define OMAP4430_VP_CORE_OPPCHANGEDONE_ST_MASK BITFIELD(16, 16) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VP_CORE_TRANXDONE_EN_SHIFT (1 << 21) +#define OMAP4430_VP_CORE_TRANXDONE_EN_MASK BITFIELD(21, 21) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VP_CORE_TRANXDONE_ST_SHIFT (1 << 21) +#define OMAP4430_VP_CORE_TRANXDONE_ST_MASK BITFIELD(21, 21) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VP_IVA_EQVALUE_EN_SHIFT (1 << 28) +#define OMAP4430_VP_IVA_EQVALUE_EN_MASK BITFIELD(28, 28) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VP_IVA_EQVALUE_ST_SHIFT (1 << 28) +#define OMAP4430_VP_IVA_EQVALUE_ST_MASK BITFIELD(28, 28) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VP_IVA_MAXVDD_EN_SHIFT (1 << 26) +#define OMAP4430_VP_IVA_MAXVDD_EN_MASK BITFIELD(26, 26) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VP_IVA_MAXVDD_ST_SHIFT (1 << 26) +#define OMAP4430_VP_IVA_MAXVDD_ST_MASK BITFIELD(26, 26) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VP_IVA_MINVDD_EN_SHIFT (1 << 25) +#define OMAP4430_VP_IVA_MINVDD_EN_MASK BITFIELD(25, 25) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VP_IVA_MINVDD_ST_SHIFT (1 << 25) +#define OMAP4430_VP_IVA_MINVDD_ST_MASK BITFIELD(25, 25) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VP_IVA_NOSMPSACK_EN_SHIFT (1 << 27) +#define OMAP4430_VP_IVA_NOSMPSACK_EN_MASK BITFIELD(27, 27) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VP_IVA_NOSMPSACK_ST_SHIFT (1 << 27) +#define OMAP4430_VP_IVA_NOSMPSACK_ST_MASK BITFIELD(27, 27) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VP_IVA_OPPCHANGEDONE_EN_SHIFT (1 << 24) +#define OMAP4430_VP_IVA_OPPCHANGEDONE_EN_MASK BITFIELD(24, 24) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VP_IVA_OPPCHANGEDONE_ST_SHIFT (1 << 24) +#define OMAP4430_VP_IVA_OPPCHANGEDONE_ST_MASK BITFIELD(24, 24) + +/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */ +#define OMAP4430_VP_IVA_TRANXDONE_EN_SHIFT (1 << 29) +#define OMAP4430_VP_IVA_TRANXDONE_EN_MASK BITFIELD(29, 29) + +/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */ +#define OMAP4430_VP_IVA_TRANXDONE_ST_SHIFT (1 << 29) +#define OMAP4430_VP_IVA_TRANXDONE_ST_MASK BITFIELD(29, 29) + +/* Used by PRM_IRQENABLE_MPU_2 */ +#define OMAP4430_VP_MPU_EQVALUE_EN_SHIFT (1 << 4) +#define OMAP4430_VP_MPU_EQVALUE_EN_MASK BITFIELD(4, 4) + +/* Used by PRM_IRQSTATUS_MPU_2 */ +#define OMAP4430_VP_MPU_EQVALUE_ST_SHIFT (1 << 4) +#define OMAP4430_VP_MPU_EQVALUE_ST_MASK BITFIELD(4, 4) + +/* Used by PRM_IRQENABLE_MPU_2 */ +#define OMAP4430_VP_MPU_MAXVDD_EN_SHIFT (1 << 2) +#define OMAP4430_VP_MPU_MAXVDD_EN_MASK BITFIELD(2, 2) + +/* Used by PRM_IRQSTATUS_MPU_2 */ +#define OMAP4430_VP_MPU_MAXVDD_ST_SHIFT (1 << 2) +#define OMAP4430_VP_MPU_MAXVDD_ST_MASK BITFIELD(2, 2) + +/* Used by PRM_IRQENABLE_MPU_2 */ +#define OMAP4430_VP_MPU_MINVDD_EN_SHIFT (1 << 1) +#define OMAP4430_VP_MPU_MINVDD_EN_MASK BITFIELD(1, 1) + +/* Used by PRM_IRQSTATUS_MPU_2 */ +#define OMAP4430_VP_MPU_MINVDD_ST_SHIFT (1 << 1) +#define OMAP4430_VP_MPU_MINVDD_ST_MASK BITFIELD(1, 1) + +/* Used by PRM_IRQENABLE_MPU_2 */ +#define OMAP4430_VP_MPU_NOSMPSACK_EN_SHIFT (1 << 3) +#define OMAP4430_VP_MPU_NOSMPSACK_EN_MASK BITFIELD(3, 3) + +/* Used by PRM_IRQSTATUS_MPU_2 */ +#define OMAP4430_VP_MPU_NOSMPSACK_ST_SHIFT (1 << 3) +#define OMAP4430_VP_MPU_NOSMPSACK_ST_MASK BITFIELD(3, 3) + +/* Used by PRM_IRQENABLE_MPU_2 */ +#define OMAP4430_VP_MPU_OPPCHANGEDONE_EN_SHIFT (1 << 0) +#define OMAP4430_VP_MPU_OPPCHANGEDONE_EN_MASK BITFIELD(0, 0) + +/* Used by PRM_IRQSTATUS_MPU_2 */ +#define OMAP4430_VP_MPU_OPPCHANGEDONE_ST_SHIFT (1 << 0) +#define OMAP4430_VP_MPU_OPPCHANGEDONE_ST_MASK BITFIELD(0, 0) + +/* Used by PRM_IRQENABLE_MPU_2 */ +#define OMAP4430_VP_MPU_TRANXDONE_EN_SHIFT (1 << 5) +#define OMAP4430_VP_MPU_TRANXDONE_EN_MASK BITFIELD(5, 5) + +/* Used by PRM_IRQSTATUS_MPU_2 */ +#define OMAP4430_VP_MPU_TRANXDONE_ST_SHIFT (1 << 5) +#define OMAP4430_VP_MPU_TRANXDONE_ST_MASK BITFIELD(5, 5) + +/* Used by PRM_SRAM_COUNT */ +#define OMAP4430_VSETUPCNT_VALUE_SHIFT (1 << 8) +#define OMAP4430_VSETUPCNT_VALUE_MASK BITFIELD(8, 15) + +/* Used by PRM_VP_CORE_VSTEPMAX, PRM_VP_IVA_VSTEPMAX, PRM_VP_MPU_VSTEPMAX */ +#define OMAP4430_VSTEPMAX_SHIFT (1 << 0) +#define OMAP4430_VSTEPMAX_MASK BITFIELD(0, 7) + +/* Used by PRM_VP_CORE_VSTEPMIN, PRM_VP_IVA_VSTEPMIN, PRM_VP_MPU_VSTEPMIN */ +#define OMAP4430_VSTEPMIN_SHIFT (1 << 0) +#define OMAP4430_VSTEPMIN_MASK BITFIELD(0, 7) + +/* Used by PRM_MODEM_IF_CTRL */ +#define OMAP4430_WAKE_MODEM_SHIFT (1 << 0) +#define OMAP4430_WAKE_MODEM_MASK BITFIELD(0, 0) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_DISPC_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_DISPC_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_DISPC_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_DISPC_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_DISPC_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_DISPC_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_DISPC_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_DISPC_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_ABE_DMIC_WKDEP */ +#define OMAP4430_WKUPDEP_DMIC_DMA_SDMA_SHIFT (1 << 7) +#define OMAP4430_WKUPDEP_DMIC_DMA_SDMA_MASK BITFIELD(7, 7) + +/* Used by PM_ABE_DMIC_WKDEP */ +#define OMAP4430_WKUPDEP_DMIC_DMA_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_DMIC_DMA_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_ABE_DMIC_WKDEP */ +#define OMAP4430_WKUPDEP_DMIC_IRQ_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_DMIC_IRQ_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ABE_DMIC_WKDEP */ +#define OMAP4430_WKUPDEP_DMIC_IRQ_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_DMIC_IRQ_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_L4PER_DMTIMER10_WKDEP */ +#define OMAP4430_WKUPDEP_DMTIMER10_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_DMTIMER10_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_DMTIMER11_WKDEP */ +#define OMAP4430_WKUPDEP_DMTIMER11_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_DMTIMER11_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_DMTIMER11_WKDEP */ +#define OMAP4430_WKUPDEP_DMTIMER11_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_DMTIMER11_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_DMTIMER2_WKDEP */ +#define OMAP4430_WKUPDEP_DMTIMER2_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_DMTIMER2_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_DMTIMER3_WKDEP */ +#define OMAP4430_WKUPDEP_DMTIMER3_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_DMTIMER3_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_DMTIMER3_WKDEP */ +#define OMAP4430_WKUPDEP_DMTIMER3_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_DMTIMER3_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_DMTIMER4_WKDEP */ +#define OMAP4430_WKUPDEP_DMTIMER4_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_DMTIMER4_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_DMTIMER4_WKDEP */ +#define OMAP4430_WKUPDEP_DMTIMER4_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_DMTIMER4_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_DMTIMER9_WKDEP */ +#define OMAP4430_WKUPDEP_DMTIMER9_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_DMTIMER9_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_DMTIMER9_WKDEP */ +#define OMAP4430_WKUPDEP_DMTIMER9_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_DMTIMER9_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_DSI1_DUCATI_SHIFT (1 << 5) +#define OMAP4430_WKUPDEP_DSI1_DUCATI_MASK BITFIELD(5, 5) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_DSI1_MPU_SHIFT (1 << 4) +#define OMAP4430_WKUPDEP_DSI1_MPU_MASK BITFIELD(4, 4) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_DSI1_SDMA_SHIFT (1 << 7) +#define OMAP4430_WKUPDEP_DSI1_SDMA_MASK BITFIELD(7, 7) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_DSI1_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_DSI1_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_DSI2_DUCATI_SHIFT (1 << 9) +#define OMAP4430_WKUPDEP_DSI2_DUCATI_MASK BITFIELD(9, 9) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_DSI2_MPU_SHIFT (1 << 8) +#define OMAP4430_WKUPDEP_DSI2_MPU_MASK BITFIELD(8, 8) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_DSI2_SDMA_SHIFT (1 << 11) +#define OMAP4430_WKUPDEP_DSI2_SDMA_MASK BITFIELD(11, 11) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_DSI2_TESLA_SHIFT (1 << 10) +#define OMAP4430_WKUPDEP_DSI2_TESLA_MASK BITFIELD(10, 10) + +/* Used by PM_WKUP_GPIO1_WKDEP */ +#define OMAP4430_WKUPDEP_GPIO1_IRQ1_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_GPIO1_IRQ1_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_WKUP_GPIO1_WKDEP */ +#define OMAP4430_WKUPDEP_GPIO1_IRQ1_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_GPIO1_IRQ1_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_WKUP_GPIO1_WKDEP */ +#define OMAP4430_WKUPDEP_GPIO1_IRQ2_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_GPIO1_IRQ2_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_L4PER_GPIO2_WKDEP */ +#define OMAP4430_WKUPDEP_GPIO2_IRQ1_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_GPIO2_IRQ1_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_GPIO2_WKDEP */ +#define OMAP4430_WKUPDEP_GPIO2_IRQ1_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_GPIO2_IRQ1_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_GPIO2_WKDEP */ +#define OMAP4430_WKUPDEP_GPIO2_IRQ2_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_GPIO2_IRQ2_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_L4PER_GPIO3_WKDEP */ +#define OMAP4430_WKUPDEP_GPIO3_IRQ1_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_GPIO3_IRQ1_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_GPIO3_WKDEP */ +#define OMAP4430_WKUPDEP_GPIO3_IRQ2_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_GPIO3_IRQ2_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_L4PER_GPIO4_WKDEP */ +#define OMAP4430_WKUPDEP_GPIO4_IRQ1_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_GPIO4_IRQ1_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_GPIO4_WKDEP */ +#define OMAP4430_WKUPDEP_GPIO4_IRQ2_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_GPIO4_IRQ2_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_L4PER_GPIO5_WKDEP */ +#define OMAP4430_WKUPDEP_GPIO5_IRQ1_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_GPIO5_IRQ1_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_GPIO5_WKDEP */ +#define OMAP4430_WKUPDEP_GPIO5_IRQ2_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_GPIO5_IRQ2_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_L4PER_GPIO6_WKDEP */ +#define OMAP4430_WKUPDEP_GPIO6_IRQ1_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_GPIO6_IRQ1_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_GPIO6_WKDEP */ +#define OMAP4430_WKUPDEP_GPIO6_IRQ2_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_GPIO6_IRQ2_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_HDMIDMA_SDMA_SHIFT (1 << 19) +#define OMAP4430_WKUPDEP_HDMIDMA_SDMA_MASK BITFIELD(19, 19) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_HDMIIRQ_DUCATI_SHIFT (1 << 13) +#define OMAP4430_WKUPDEP_HDMIIRQ_DUCATI_MASK BITFIELD(13, 13) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_HDMIIRQ_MPU_SHIFT (1 << 12) +#define OMAP4430_WKUPDEP_HDMIIRQ_MPU_MASK BITFIELD(12, 12) + +/* Used by PM_DSS_DSS_WKDEP */ +#define OMAP4430_WKUPDEP_HDMIIRQ_TESLA_SHIFT (1 << 14) +#define OMAP4430_WKUPDEP_HDMIIRQ_TESLA_MASK BITFIELD(14, 14) + +/* Used by PM_L4PER_HECC1_WKDEP */ +#define OMAP4430_WKUPDEP_HECC1_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_HECC1_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_HECC2_WKDEP */ +#define OMAP4430_WKUPDEP_HECC2_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_HECC2_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L3INIT_HSI_WKDEP */ +#define OMAP4430_WKUPDEP_HSI_DSP_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_HSI_DSP_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_L3INIT_HSI_WKDEP */ +#define OMAP4430_WKUPDEP_HSI_MCU_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_HSI_MCU_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L3INIT_HSI_WKDEP */ +#define OMAP4430_WKUPDEP_HSI_MCU_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_HSI_MCU_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_I2C1_WKDEP */ +#define OMAP4430_WKUPDEP_I2C1_DMA_SDMA_SHIFT (1 << 7) +#define OMAP4430_WKUPDEP_I2C1_DMA_SDMA_MASK BITFIELD(7, 7) + +/* Used by PM_L4PER_I2C1_WKDEP */ +#define OMAP4430_WKUPDEP_I2C1_IRQ_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_I2C1_IRQ_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_I2C1_WKDEP */ +#define OMAP4430_WKUPDEP_I2C1_IRQ_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_I2C1_IRQ_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_I2C2_WKDEP */ +#define OMAP4430_WKUPDEP_I2C2_DMA_SDMA_SHIFT (1 << 7) +#define OMAP4430_WKUPDEP_I2C2_DMA_SDMA_MASK BITFIELD(7, 7) + +/* Used by PM_L4PER_I2C2_WKDEP */ +#define OMAP4430_WKUPDEP_I2C2_IRQ_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_I2C2_IRQ_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_I2C2_WKDEP */ +#define OMAP4430_WKUPDEP_I2C2_IRQ_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_I2C2_IRQ_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_I2C3_WKDEP */ +#define OMAP4430_WKUPDEP_I2C3_DMA_SDMA_SHIFT (1 << 7) +#define OMAP4430_WKUPDEP_I2C3_DMA_SDMA_MASK BITFIELD(7, 7) + +/* Used by PM_L4PER_I2C3_WKDEP */ +#define OMAP4430_WKUPDEP_I2C3_IRQ_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_I2C3_IRQ_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_I2C3_WKDEP */ +#define OMAP4430_WKUPDEP_I2C3_IRQ_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_I2C3_IRQ_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_I2C4_WKDEP */ +#define OMAP4430_WKUPDEP_I2C4_DMA_SDMA_SHIFT (1 << 7) +#define OMAP4430_WKUPDEP_I2C4_DMA_SDMA_MASK BITFIELD(7, 7) + +/* Used by PM_L4PER_I2C4_WKDEP */ +#define OMAP4430_WKUPDEP_I2C4_IRQ_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_I2C4_IRQ_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_I2C4_WKDEP */ +#define OMAP4430_WKUPDEP_I2C4_IRQ_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_I2C4_IRQ_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_I2C5_WKDEP */ +#define OMAP4430_WKUPDEP_I2C5_DMA_SDMA_SHIFT (1 << 7) +#define OMAP4430_WKUPDEP_I2C5_DMA_SDMA_MASK BITFIELD(7, 7) + +/* Used by PM_L4PER_I2C5_WKDEP */ +#define OMAP4430_WKUPDEP_I2C5_IRQ_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_I2C5_IRQ_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_WKUP_KEYBOARD_WKDEP */ +#define OMAP4430_WKUPDEP_KEYBOARD_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_KEYBOARD_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ABE_MCASP_WKDEP */ +#define OMAP4430_WKUPDEP_MCASP1_DMA_SDMA_SHIFT (1 << 7) +#define OMAP4430_WKUPDEP_MCASP1_DMA_SDMA_MASK BITFIELD(7, 7) + +/* Used by PM_ABE_MCASP_WKDEP */ +#define OMAP4430_WKUPDEP_MCASP1_DMA_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_MCASP1_DMA_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_ABE_MCASP_WKDEP */ +#define OMAP4430_WKUPDEP_MCASP1_IRQ_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MCASP1_IRQ_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ABE_MCASP_WKDEP */ +#define OMAP4430_WKUPDEP_MCASP1_IRQ_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_MCASP1_IRQ_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_L4PER_MCASP2_WKDEP */ +#define OMAP4430_WKUPDEP_MCASP2_DMA_SDMA_SHIFT (1 << 7) +#define OMAP4430_WKUPDEP_MCASP2_DMA_SDMA_MASK BITFIELD(7, 7) + +/* Used by PM_L4PER_MCASP2_WKDEP */ +#define OMAP4430_WKUPDEP_MCASP2_DMA_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_MCASP2_DMA_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_L4PER_MCASP2_WKDEP */ +#define OMAP4430_WKUPDEP_MCASP2_IRQ_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MCASP2_IRQ_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_MCASP2_WKDEP */ +#define OMAP4430_WKUPDEP_MCASP2_IRQ_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_MCASP2_IRQ_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_L4PER_MCASP3_WKDEP */ +#define OMAP4430_WKUPDEP_MCASP3_DMA_SDMA_SHIFT (1 << 7) +#define OMAP4430_WKUPDEP_MCASP3_DMA_SDMA_MASK BITFIELD(7, 7) + +/* Used by PM_L4PER_MCASP3_WKDEP */ +#define OMAP4430_WKUPDEP_MCASP3_DMA_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_MCASP3_DMA_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_L4PER_MCASP3_WKDEP */ +#define OMAP4430_WKUPDEP_MCASP3_IRQ_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MCASP3_IRQ_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_MCASP3_WKDEP */ +#define OMAP4430_WKUPDEP_MCASP3_IRQ_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_MCASP3_IRQ_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_ABE_MCBSP1_WKDEP */ +#define OMAP4430_WKUPDEP_MCBSP1_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MCBSP1_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ABE_MCBSP1_WKDEP */ +#define OMAP4430_WKUPDEP_MCBSP1_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_MCBSP1_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_ABE_MCBSP1_WKDEP */ +#define OMAP4430_WKUPDEP_MCBSP1_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_MCBSP1_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_ABE_MCBSP2_WKDEP */ +#define OMAP4430_WKUPDEP_MCBSP2_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MCBSP2_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ABE_MCBSP2_WKDEP */ +#define OMAP4430_WKUPDEP_MCBSP2_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_MCBSP2_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_ABE_MCBSP2_WKDEP */ +#define OMAP4430_WKUPDEP_MCBSP2_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_MCBSP2_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_ABE_MCBSP3_WKDEP */ +#define OMAP4430_WKUPDEP_MCBSP3_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MCBSP3_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ABE_MCBSP3_WKDEP */ +#define OMAP4430_WKUPDEP_MCBSP3_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_MCBSP3_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_ABE_MCBSP3_WKDEP */ +#define OMAP4430_WKUPDEP_MCBSP3_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_MCBSP3_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_L4PER_MCBSP4_WKDEP */ +#define OMAP4430_WKUPDEP_MCBSP4_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MCBSP4_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_MCBSP4_WKDEP */ +#define OMAP4430_WKUPDEP_MCBSP4_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_MCBSP4_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_L4PER_MCBSP4_WKDEP */ +#define OMAP4430_WKUPDEP_MCBSP4_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_MCBSP4_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_L4PER_MCSPI1_WKDEP */ +#define OMAP4430_WKUPDEP_MCSPI1_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_MCSPI1_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_MCSPI1_WKDEP */ +#define OMAP4430_WKUPDEP_MCSPI1_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MCSPI1_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_MCSPI1_WKDEP */ +#define OMAP4430_WKUPDEP_MCSPI1_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_MCSPI1_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_L4PER_MCSPI1_WKDEP */ +#define OMAP4430_WKUPDEP_MCSPI1_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_MCSPI1_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_L4PER_MCSPI2_WKDEP */ +#define OMAP4430_WKUPDEP_MCSPI2_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_MCSPI2_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_MCSPI2_WKDEP */ +#define OMAP4430_WKUPDEP_MCSPI2_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MCSPI2_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_MCSPI2_WKDEP */ +#define OMAP4430_WKUPDEP_MCSPI2_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_MCSPI2_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_L4PER_MCSPI3_WKDEP */ +#define OMAP4430_WKUPDEP_MCSPI3_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MCSPI3_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_MCSPI3_WKDEP */ +#define OMAP4430_WKUPDEP_MCSPI3_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_MCSPI3_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_L4PER_MCSPI4_WKDEP */ +#define OMAP4430_WKUPDEP_MCSPI4_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MCSPI4_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_MCSPI4_WKDEP */ +#define OMAP4430_WKUPDEP_MCSPI4_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_MCSPI4_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_L3INIT_MMC1_WKDEP */ +#define OMAP4430_WKUPDEP_MMC1_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_MMC1_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L3INIT_MMC1_WKDEP */ +#define OMAP4430_WKUPDEP_MMC1_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MMC1_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L3INIT_MMC1_WKDEP */ +#define OMAP4430_WKUPDEP_MMC1_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_MMC1_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_L3INIT_MMC1_WKDEP */ +#define OMAP4430_WKUPDEP_MMC1_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_MMC1_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_L3INIT_MMC2_WKDEP */ +#define OMAP4430_WKUPDEP_MMC2_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_MMC2_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L3INIT_MMC2_WKDEP */ +#define OMAP4430_WKUPDEP_MMC2_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MMC2_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L3INIT_MMC2_WKDEP */ +#define OMAP4430_WKUPDEP_MMC2_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_MMC2_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_L3INIT_MMC2_WKDEP */ +#define OMAP4430_WKUPDEP_MMC2_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_MMC2_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_L3INIT_MMC6_WKDEP */ +#define OMAP4430_WKUPDEP_MMC6_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_MMC6_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L3INIT_MMC6_WKDEP */ +#define OMAP4430_WKUPDEP_MMC6_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MMC6_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L3INIT_MMC6_WKDEP */ +#define OMAP4430_WKUPDEP_MMC6_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_MMC6_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_L4PER_MMCSD3_WKDEP */ +#define OMAP4430_WKUPDEP_MMCSD3_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_MMCSD3_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_MMCSD3_WKDEP */ +#define OMAP4430_WKUPDEP_MMCSD3_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MMCSD3_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_MMCSD3_WKDEP */ +#define OMAP4430_WKUPDEP_MMCSD3_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_MMCSD3_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_L4PER_MMCSD4_WKDEP */ +#define OMAP4430_WKUPDEP_MMCSD4_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_MMCSD4_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_MMCSD4_WKDEP */ +#define OMAP4430_WKUPDEP_MMCSD4_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MMCSD4_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_MMCSD4_WKDEP */ +#define OMAP4430_WKUPDEP_MMCSD4_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_MMCSD4_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_L4PER_MMCSD5_WKDEP */ +#define OMAP4430_WKUPDEP_MMCSD5_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_MMCSD5_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_MMCSD5_WKDEP */ +#define OMAP4430_WKUPDEP_MMCSD5_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_MMCSD5_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_MMCSD5_WKDEP */ +#define OMAP4430_WKUPDEP_MMCSD5_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_MMCSD5_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_L3INIT_PCIESS_WKDEP */ +#define OMAP4430_WKUPDEP_PCIESS_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_PCIESS_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L3INIT_PCIESS_WKDEP */ +#define OMAP4430_WKUPDEP_PCIESS_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_PCIESS_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_ABE_PDM_WKDEP */ +#define OMAP4430_WKUPDEP_PDM_DMA_SDMA_SHIFT (1 << 7) +#define OMAP4430_WKUPDEP_PDM_DMA_SDMA_MASK BITFIELD(7, 7) + +/* Used by PM_ABE_PDM_WKDEP */ +#define OMAP4430_WKUPDEP_PDM_DMA_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_PDM_DMA_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_ABE_PDM_WKDEP */ +#define OMAP4430_WKUPDEP_PDM_IRQ_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_PDM_IRQ_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ABE_PDM_WKDEP */ +#define OMAP4430_WKUPDEP_PDM_IRQ_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_PDM_IRQ_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_WKUP_RTC_WKDEP */ +#define OMAP4430_WKUPDEP_RTC_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_RTC_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L3INIT_SATA_WKDEP */ +#define OMAP4430_WKUPDEP_SATA_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_SATA_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L3INIT_SATA_WKDEP */ +#define OMAP4430_WKUPDEP_SATA_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_SATA_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_ABE_SLIMBUS_WKDEP */ +#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_SDMA_SHIFT (1 << 7) +#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_SDMA_MASK BITFIELD(7, 7) + +/* Used by PM_ABE_SLIMBUS_WKDEP */ +#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_ABE_SLIMBUS_WKDEP */ +#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ABE_SLIMBUS_WKDEP */ +#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_L4PER_SLIMBUS2_WKDEP */ +#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_SDMA_SHIFT (1 << 7) +#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_SDMA_MASK BITFIELD(7, 7) + +/* Used by PM_L4PER_SLIMBUS2_WKDEP */ +#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_TESLA_SHIFT (1 << 6) +#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_TESLA_MASK BITFIELD(6, 6) + +/* Used by PM_L4PER_SLIMBUS2_WKDEP */ +#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_SLIMBUS2_WKDEP */ +#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_ALWON_SR_CORE_WKDEP */ +#define OMAP4430_WKUPDEP_SR_CORE_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_SR_CORE_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_ALWON_SR_CORE_WKDEP */ +#define OMAP4430_WKUPDEP_SR_CORE_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_SR_CORE_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ALWON_SR_IVA_WKDEP */ +#define OMAP4430_WKUPDEP_SR_IVA_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_SR_IVA_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_ALWON_SR_IVA_WKDEP */ +#define OMAP4430_WKUPDEP_SR_IVA_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_SR_IVA_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ALWON_SR_MPU_WKDEP */ +#define OMAP4430_WKUPDEP_SR_MPU_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_SR_MPU_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_WKUP_TIMER12_WKDEP */ +#define OMAP4430_WKUPDEP_TIMER12_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_TIMER12_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_WKUP_TIMER1_WKDEP */ +#define OMAP4430_WKUPDEP_TIMER1_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_TIMER1_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ABE_TIMER5_WKDEP */ +#define OMAP4430_WKUPDEP_TIMER5_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_TIMER5_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ABE_TIMER5_WKDEP */ +#define OMAP4430_WKUPDEP_TIMER5_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_TIMER5_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_ABE_TIMER6_WKDEP */ +#define OMAP4430_WKUPDEP_TIMER6_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_TIMER6_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ABE_TIMER6_WKDEP */ +#define OMAP4430_WKUPDEP_TIMER6_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_TIMER6_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_ABE_TIMER7_WKDEP */ +#define OMAP4430_WKUPDEP_TIMER7_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_TIMER7_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ABE_TIMER7_WKDEP */ +#define OMAP4430_WKUPDEP_TIMER7_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_TIMER7_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_ABE_TIMER8_WKDEP */ +#define OMAP4430_WKUPDEP_TIMER8_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_TIMER8_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ABE_TIMER8_WKDEP */ +#define OMAP4430_WKUPDEP_TIMER8_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_TIMER8_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_L4PER_UART1_WKDEP */ +#define OMAP4430_WKUPDEP_UART1_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_UART1_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_UART1_WKDEP */ +#define OMAP4430_WKUPDEP_UART1_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_UART1_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_L4PER_UART2_WKDEP */ +#define OMAP4430_WKUPDEP_UART2_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_UART2_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_UART2_WKDEP */ +#define OMAP4430_WKUPDEP_UART2_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_UART2_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_L4PER_UART3_WKDEP */ +#define OMAP4430_WKUPDEP_UART3_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_UART3_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L4PER_UART3_WKDEP */ +#define OMAP4430_WKUPDEP_UART3_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_UART3_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_UART3_WKDEP */ +#define OMAP4430_WKUPDEP_UART3_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_UART3_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_L4PER_UART3_WKDEP */ +#define OMAP4430_WKUPDEP_UART3_TESLA_SHIFT (1 << 2) +#define OMAP4430_WKUPDEP_UART3_TESLA_MASK BITFIELD(2, 2) + +/* Used by PM_L4PER_UART4_WKDEP */ +#define OMAP4430_WKUPDEP_UART4_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_UART4_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L4PER_UART4_WKDEP */ +#define OMAP4430_WKUPDEP_UART4_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_UART4_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_L3INIT_UNIPRO1_WKDEP */ +#define OMAP4430_WKUPDEP_UNIPRO1_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_UNIPRO1_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L3INIT_UNIPRO1_WKDEP */ +#define OMAP4430_WKUPDEP_UNIPRO1_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_UNIPRO1_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L3INIT_USB_HOST_WKDEP */ +#define OMAP4430_WKUPDEP_USB_HOST_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_USB_HOST_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L3INIT_USB_HOST_FS_WKDEP */ +#define OMAP4430_WKUPDEP_USB_HOST_FS_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_USB_HOST_FS_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L3INIT_USB_HOST_FS_WKDEP */ +#define OMAP4430_WKUPDEP_USB_HOST_FS_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_USB_HOST_FS_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L3INIT_USB_HOST_WKDEP */ +#define OMAP4430_WKUPDEP_USB_HOST_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_USB_HOST_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L3INIT_USB_OTG_WKDEP */ +#define OMAP4430_WKUPDEP_USB_OTG_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_USB_OTG_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L3INIT_USB_OTG_WKDEP */ +#define OMAP4430_WKUPDEP_USB_OTG_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_USB_OTG_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L3INIT_USB_TLL_WKDEP */ +#define OMAP4430_WKUPDEP_USB_TLL_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_USB_TLL_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_L3INIT_USB_TLL_WKDEP */ +#define OMAP4430_WKUPDEP_USB_TLL_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_USB_TLL_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_WKUP_USIM_WKDEP */ +#define OMAP4430_WKUPDEP_USIM_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_USIM_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_WKUP_USIM_WKDEP */ +#define OMAP4430_WKUPDEP_USIM_SDMA_SHIFT (1 << 3) +#define OMAP4430_WKUPDEP_USIM_SDMA_MASK BITFIELD(3, 3) + +/* Used by PM_WKUP_WDT2_WKDEP */ +#define OMAP4430_WKUPDEP_WDT2_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_WDT2_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PM_WKUP_WDT2_WKDEP */ +#define OMAP4430_WKUPDEP_WDT2_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_WDT2_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_ABE_WDT3_WKDEP */ +#define OMAP4430_WKUPDEP_WDT3_MPU_SHIFT (1 << 0) +#define OMAP4430_WKUPDEP_WDT3_MPU_MASK BITFIELD(0, 0) + +/* Used by PM_L3INIT_HSI_WKDEP */ +#define OMAP4430_WKUPDEP_WGM_HSI_WAKE_MPU_SHIFT (1 << 8) +#define OMAP4430_WKUPDEP_WGM_HSI_WAKE_MPU_MASK BITFIELD(8, 8) + +/* Used by PM_L3INIT_XHPI_WKDEP */ +#define OMAP4430_WKUPDEP_XHPI_DUCATI_SHIFT (1 << 1) +#define OMAP4430_WKUPDEP_XHPI_DUCATI_MASK BITFIELD(1, 1) + +/* Used by PRM_IO_PMCTRL */ +#define OMAP4430_WUCLK_CTRL_SHIFT (1 << 8) +#define OMAP4430_WUCLK_CTRL_MASK BITFIELD(8, 8) + +/* Used by PRM_IO_PMCTRL */ +#define OMAP4430_WUCLK_STATUS_SHIFT (1 << 9) +#define OMAP4430_WUCLK_STATUS_MASK BITFIELD(9, 9) +#endif diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h index a117f853ea39212ac21d144a6016bdf13f2bf000..ea050ce188a7f9ea484649c489a480755e89b9da 100644 --- a/arch/arm/mach-omap2/prm.h +++ b/arch/arm/mach-omap2/prm.h @@ -4,8 +4,8 @@ /* * OMAP2/3 Power/Reset Management (PRM) register definitions * - * Copyright (C) 2007 Texas Instruments, Inc. - * Copyright (C) 2007 Nokia Corporation + * Copyright (C) 2007-2009 Texas Instruments, Inc. + * Copyright (C) 2009 Nokia Corporation * * Written by Paul Walmsley * @@ -22,6 +22,10 @@ OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg)) #define OMAP34XX_PRM_REGADDR(module, reg) \ OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg)) +#define OMAP44XX_PRM_REGADDR(module, reg) \ + OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE + (module) + (reg)) + +#include "prm44xx.h" /* * Architecture-specific global PRM registers diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h new file mode 100644 index 0000000000000000000000000000000000000000..89be97f0589dd026b14629581c5dde7f911eea04 --- /dev/null +++ b/arch/arm/mach-omap2/prm44xx.h @@ -0,0 +1,411 @@ +/* + * OMAP44xx PRM instance offset macros + * + * Copyright (C) 2009 Texas Instruments, Inc. + * Copyright (C) 2009 Nokia Corporation + * + * Paul Walmsley (paul@pwsan.com) + * Rajendra Nayak (rnayak@ti.com) + * Benoit Cousson (b-cousson@ti.com) + * + * This file is automatically generated from the OMAP hardware databases. + * We respectfully ask that any modifications to this file be coordinated + * with the public linux-omap@vger.kernel.org mailing list and the + * authors above to ensure that the autogeneration scripts are kept + * up-to-date with the file contents. + * + * 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. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_PRM44XX_H +#define __ARCH_ARM_MACH_OMAP2_PRM44XX_H + + +/* PRM */ + + +/* PRM.OCP_SOCKET_PRM register offsets */ +#define OMAP4430_REVISION_PRM OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0000) +#define OMAP4430_PRM_IRQSTATUS_MPU OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0010) +#define OMAP4430_PRM_IRQSTATUS_MPU_2 OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0014) +#define OMAP4430_PRM_IRQENABLE_MPU OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0018) +#define OMAP4430_PRM_IRQENABLE_MPU_2 OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x001c) +#define OMAP4430_PRM_IRQSTATUS_DUCATI OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0020) +#define OMAP4430_PRM_IRQENABLE_DUCATI OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0028) +#define OMAP4430_PRM_IRQSTATUS_TESLA OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0030) +#define OMAP4430_PRM_IRQENABLE_TESLA OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0038) +#define OMAP4430_PRM_PRM_PROFILING_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0040) + +/* PRM.CKGEN_PRM register offsets */ +#define OMAP4430_CM_ABE_DSS_SYS_CLKSEL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0000) +#define OMAP4430_CM_DPLL_SYS_REF_CLKSEL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0004) +#define OMAP4430_CM_L4_WKUP_CLKSEL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0008) +#define OMAP4430_CM_ABE_PLL_REF_CLKSEL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x000c) +#define OMAP4430_CM_SYS_CLKSEL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0010) + +/* PRM.MPU_PRM register offsets */ +#define OMAP4430_PM_MPU_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_MPU_MOD, 0x0000) +#define OMAP4430_PM_MPU_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_MPU_MOD, 0x0004) +#define OMAP4430_RM_MPU_RSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_MPU_MOD, 0x0014) +#define OMAP4430_RM_MPU_MPU_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_MPU_MOD, 0x0024) + +/* PRM.TESLA_PRM register offsets */ +#define OMAP4430_PM_TESLA_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_MOD, 0x0000) +#define OMAP4430_PM_TESLA_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_MOD, 0x0004) +#define OMAP4430_RM_TESLA_RSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_MOD, 0x0010) +#define OMAP4430_RM_TESLA_RSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_MOD, 0x0014) +#define OMAP4430_RM_TESLA_TESLA_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_MOD, 0x0024) + +/* PRM.ABE_PRM register offsets */ +#define OMAP4430_PM_ABE_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0000) +#define OMAP4430_PM_ABE_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0004) +#define OMAP4430_RM_ABE_AESS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x002c) +#define OMAP4430_PM_ABE_PDM_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0030) +#define OMAP4430_RM_ABE_PDM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0034) +#define OMAP4430_PM_ABE_DMIC_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0038) +#define OMAP4430_RM_ABE_DMIC_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x003c) +#define OMAP4430_PM_ABE_MCASP_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0040) +#define OMAP4430_RM_ABE_MCASP_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0044) +#define OMAP4430_PM_ABE_MCBSP1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0048) +#define OMAP4430_RM_ABE_MCBSP1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x004c) +#define OMAP4430_PM_ABE_MCBSP2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0050) +#define OMAP4430_RM_ABE_MCBSP2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0054) +#define OMAP4430_PM_ABE_MCBSP3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0058) +#define OMAP4430_RM_ABE_MCBSP3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x005c) +#define OMAP4430_PM_ABE_SLIMBUS_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0060) +#define OMAP4430_RM_ABE_SLIMBUS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0064) +#define OMAP4430_PM_ABE_TIMER5_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0068) +#define OMAP4430_RM_ABE_TIMER5_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x006c) +#define OMAP4430_PM_ABE_TIMER6_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0070) +#define OMAP4430_RM_ABE_TIMER6_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0074) +#define OMAP4430_PM_ABE_TIMER7_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0078) +#define OMAP4430_RM_ABE_TIMER7_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x007c) +#define OMAP4430_PM_ABE_TIMER8_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0080) +#define OMAP4430_RM_ABE_TIMER8_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0084) +#define OMAP4430_PM_ABE_WDT3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0088) +#define OMAP4430_RM_ABE_WDT3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x008c) + +/* PRM.ALWAYS_ON_PRM register offsets */ +#define OMAP4430_RM_ALWON_MDMINTC_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_MOD, 0x0024) +#define OMAP4430_PM_ALWON_SR_MPU_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_MOD, 0x0028) +#define OMAP4430_RM_ALWON_SR_MPU_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_MOD, 0x002c) +#define OMAP4430_PM_ALWON_SR_IVA_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_MOD, 0x0030) +#define OMAP4430_RM_ALWON_SR_IVA_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_MOD, 0x0034) +#define OMAP4430_PM_ALWON_SR_CORE_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_MOD, 0x0038) +#define OMAP4430_RM_ALWON_SR_CORE_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_MOD, 0x003c) + +/* PRM.CORE_PRM register offsets */ +#define OMAP4430_PM_CORE_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0000) +#define OMAP4430_PM_CORE_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0004) +#define OMAP4430_RM_L3_1_L3_1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0024) +#define OMAP4430_RM_L3_2_L3_2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0124) +#define OMAP4430_RM_L3_2_GPMC_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x012c) +#define OMAP4430_RM_L3_2_OCMC_RAM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0134) +#define OMAP4430_RM_DUCATI_RSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0210) +#define OMAP4430_RM_DUCATI_RSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0214) +#define OMAP4430_RM_DUCATI_DUCATI_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0224) +#define OMAP4430_RM_SDMA_SDMA_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0324) +#define OMAP4430_RM_MEMIF_DMM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0424) +#define OMAP4430_RM_MEMIF_EMIF_FW_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x042c) +#define OMAP4430_RM_MEMIF_EMIF_1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0434) +#define OMAP4430_RM_MEMIF_EMIF_2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x043c) +#define OMAP4430_RM_MEMIF_DLL_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0444) +#define OMAP4430_RM_MEMIF_EMIF_H1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0454) +#define OMAP4430_RM_MEMIF_EMIF_H2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x045c) +#define OMAP4430_RM_MEMIF_DLL_H_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0464) +#define OMAP4430_RM_D2D_SAD2D_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0524) +#define OMAP4430_RM_D2D_MODEM_ICR_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x052c) +#define OMAP4430_RM_D2D_SAD2D_FW_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0534) +#define OMAP4430_RM_L4CFG_L4_CFG_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0624) +#define OMAP4430_RM_L4CFG_HW_SEM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x062c) +#define OMAP4430_RM_L4CFG_MAILBOX_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0634) +#define OMAP4430_RM_L4CFG_SAR_ROM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x063c) +#define OMAP4430_RM_L3INSTR_L3_3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0724) +#define OMAP4430_RM_L3INSTR_L3_INSTR_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x072c) +#define OMAP4430_RM_L3INSTR_OCP_WP1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0744) + +/* PRM.IVAHD_PRM register offsets */ +#define OMAP4430_PM_IVAHD_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_MOD, 0x0000) +#define OMAP4430_PM_IVAHD_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_MOD, 0x0004) +#define OMAP4430_RM_IVAHD_RSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_MOD, 0x0010) +#define OMAP4430_RM_IVAHD_RSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_MOD, 0x0014) +#define OMAP4430_RM_IVAHD_IVAHD_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_MOD, 0x0024) +#define OMAP4430_RM_IVAHD_SL2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_MOD, 0x002c) + +/* PRM.CAM_PRM register offsets */ +#define OMAP4430_PM_CAM_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CAM_MOD, 0x0000) +#define OMAP4430_PM_CAM_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CAM_MOD, 0x0004) +#define OMAP4430_RM_CAM_ISS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CAM_MOD, 0x0024) +#define OMAP4430_RM_CAM_FDIF_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CAM_MOD, 0x002c) + +/* PRM.DSS_PRM register offsets */ +#define OMAP4430_PM_DSS_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_MOD, 0x0000) +#define OMAP4430_PM_DSS_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_MOD, 0x0004) +#define OMAP4430_PM_DSS_DSS_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_MOD, 0x0020) +#define OMAP4430_RM_DSS_DSS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_MOD, 0x0024) +#define OMAP4430_RM_DSS_DEISS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_MOD, 0x002c) + +/* PRM.GFX_PRM register offsets */ +#define OMAP4430_PM_GFX_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_GFX_MOD, 0x0000) +#define OMAP4430_PM_GFX_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_GFX_MOD, 0x0004) +#define OMAP4430_RM_GFX_GFX_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_GFX_MOD, 0x0024) + +/* PRM.L3INIT_PRM register offsets */ +#define OMAP4430_PM_L3INIT_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0000) +#define OMAP4430_PM_L3INIT_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0004) +#define OMAP4430_PM_L3INIT_MMC1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0028) +#define OMAP4430_RM_L3INIT_MMC1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x002c) +#define OMAP4430_PM_L3INIT_MMC2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0030) +#define OMAP4430_RM_L3INIT_MMC2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0034) +#define OMAP4430_PM_L3INIT_HSI_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0038) +#define OMAP4430_RM_L3INIT_HSI_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x003c) +#define OMAP4430_PM_L3INIT_UNIPRO1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0040) +#define OMAP4430_RM_L3INIT_UNIPRO1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0044) +#define OMAP4430_PM_L3INIT_USB_HOST_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0058) +#define OMAP4430_RM_L3INIT_USB_HOST_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x005c) +#define OMAP4430_PM_L3INIT_USB_OTG_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0060) +#define OMAP4430_RM_L3INIT_USB_OTG_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0064) +#define OMAP4430_PM_L3INIT_USB_TLL_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0068) +#define OMAP4430_RM_L3INIT_USB_TLL_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x006c) +#define OMAP4430_RM_L3INIT_P1500_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x007c) +#define OMAP4430_RM_L3INIT_EMAC_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0084) +#define OMAP4430_PM_L3INIT_SATA_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0088) +#define OMAP4430_RM_L3INIT_SATA_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x008c) +#define OMAP4430_RM_L3INIT_TPPSS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0094) +#define OMAP4430_PM_L3INIT_PCIESS_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0098) +#define OMAP4430_RM_L3INIT_PCIESS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x009c) +#define OMAP4430_RM_L3INIT_CCPTX_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00ac) +#define OMAP4430_PM_L3INIT_XHPI_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00c0) +#define OMAP4430_RM_L3INIT_XHPI_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00c4) +#define OMAP4430_PM_L3INIT_MMC6_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00c8) +#define OMAP4430_RM_L3INIT_MMC6_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00cc) +#define OMAP4430_PM_L3INIT_USB_HOST_FS_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00d0) +#define OMAP4430_RM_L3INIT_USB_HOST_FS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00d4) +#define OMAP4430_RM_L3INIT_USBPHYOCP2SCP_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00e4) + +/* PRM.L4PER_PRM register offsets */ +#define OMAP4430_PM_L4PER_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0000) +#define OMAP4430_PM_L4PER_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0004) +#define OMAP4430_RM_L4PER_ADC_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0024) +#define OMAP4430_PM_L4PER_DMTIMER10_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0028) +#define OMAP4430_RM_L4PER_DMTIMER10_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x002c) +#define OMAP4430_PM_L4PER_DMTIMER11_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0030) +#define OMAP4430_RM_L4PER_DMTIMER11_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0034) +#define OMAP4430_PM_L4PER_DMTIMER2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0038) +#define OMAP4430_RM_L4PER_DMTIMER2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x003c) +#define OMAP4430_PM_L4PER_DMTIMER3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0040) +#define OMAP4430_RM_L4PER_DMTIMER3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0044) +#define OMAP4430_PM_L4PER_DMTIMER4_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0048) +#define OMAP4430_RM_L4PER_DMTIMER4_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x004c) +#define OMAP4430_PM_L4PER_DMTIMER9_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0050) +#define OMAP4430_RM_L4PER_DMTIMER9_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0054) +#define OMAP4430_RM_L4PER_ELM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x005c) +#define OMAP4430_PM_L4PER_GPIO2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0060) +#define OMAP4430_RM_L4PER_GPIO2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0064) +#define OMAP4430_PM_L4PER_GPIO3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0068) +#define OMAP4430_RM_L4PER_GPIO3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x006c) +#define OMAP4430_PM_L4PER_GPIO4_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0070) +#define OMAP4430_RM_L4PER_GPIO4_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0074) +#define OMAP4430_PM_L4PER_GPIO5_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0078) +#define OMAP4430_RM_L4PER_GPIO5_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x007c) +#define OMAP4430_PM_L4PER_GPIO6_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0080) +#define OMAP4430_RM_L4PER_GPIO6_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0084) +#define OMAP4430_RM_L4PER_HDQ1W_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x008c) +#define OMAP4430_PM_L4PER_HECC1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0090) +#define OMAP4430_RM_L4PER_HECC1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0094) +#define OMAP4430_PM_L4PER_HECC2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0098) +#define OMAP4430_RM_L4PER_HECC2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x009c) +#define OMAP4430_PM_L4PER_I2C1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00a0) +#define OMAP4430_RM_L4PER_I2C1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00a4) +#define OMAP4430_PM_L4PER_I2C2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00a8) +#define OMAP4430_RM_L4PER_I2C2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00ac) +#define OMAP4430_PM_L4PER_I2C3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00b0) +#define OMAP4430_RM_L4PER_I2C3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00b4) +#define OMAP4430_PM_L4PER_I2C4_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00b8) +#define OMAP4430_RM_L4PER_I2C4_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00bc) +#define OMAP4430_RM_L4PER_L4_PER_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00c0) +#define OMAP4430_PM_L4PER_MCASP2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00d0) +#define OMAP4430_RM_L4PER_MCASP2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00d4) +#define OMAP4430_PM_L4PER_MCASP3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00d8) +#define OMAP4430_RM_L4PER_MCASP3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00dc) +#define OMAP4430_PM_L4PER_MCBSP4_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00e0) +#define OMAP4430_RM_L4PER_MCBSP4_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00e4) +#define OMAP4430_RM_L4PER_MGATE_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00ec) +#define OMAP4430_PM_L4PER_MCSPI1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00f0) +#define OMAP4430_RM_L4PER_MCSPI1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00f4) +#define OMAP4430_PM_L4PER_MCSPI2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00f8) +#define OMAP4430_RM_L4PER_MCSPI2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00fc) +#define OMAP4430_PM_L4PER_MCSPI3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0100) +#define OMAP4430_RM_L4PER_MCSPI3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0104) +#define OMAP4430_PM_L4PER_MCSPI4_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0108) +#define OMAP4430_RM_L4PER_MCSPI4_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x010c) +#define OMAP4430_PM_L4PER_MMCSD3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0120) +#define OMAP4430_RM_L4PER_MMCSD3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0124) +#define OMAP4430_PM_L4PER_MMCSD4_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0128) +#define OMAP4430_RM_L4PER_MMCSD4_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x012c) +#define OMAP4430_RM_L4PER_MSPROHG_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0134) +#define OMAP4430_PM_L4PER_SLIMBUS2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0138) +#define OMAP4430_RM_L4PER_SLIMBUS2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x013c) +#define OMAP4430_PM_L4PER_UART1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0140) +#define OMAP4430_RM_L4PER_UART1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0144) +#define OMAP4430_PM_L4PER_UART2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0148) +#define OMAP4430_RM_L4PER_UART2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x014c) +#define OMAP4430_PM_L4PER_UART3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0150) +#define OMAP4430_RM_L4PER_UART3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0154) +#define OMAP4430_PM_L4PER_UART4_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0158) +#define OMAP4430_RM_L4PER_UART4_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x015c) +#define OMAP4430_PM_L4PER_MMCSD5_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0160) +#define OMAP4430_RM_L4PER_MMCSD5_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0164) +#define OMAP4430_PM_L4PER_I2C5_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0168) +#define OMAP4430_RM_L4PER_I2C5_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x016c) +#define OMAP4430_RM_L4SEC_AES1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x01a4) +#define OMAP4430_RM_L4SEC_AES2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x01ac) +#define OMAP4430_RM_L4SEC_DES3DES_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x01b4) +#define OMAP4430_RM_L4SEC_PKAEIP29_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x01bc) +#define OMAP4430_RM_L4SEC_RNG_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x01c4) +#define OMAP4430_RM_L4SEC_SHA2MD51_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x01cc) +#define OMAP4430_RM_L4SEC_CRYPTODMA_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x01dc) + +/* PRM.CEFUSE_PRM register offsets */ +#define OMAP4430_PM_CEFUSE_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CEFUSE_MOD, 0x0000) +#define OMAP4430_PM_CEFUSE_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CEFUSE_MOD, 0x0004) +#define OMAP4430_RM_CEFUSE_CEFUSE_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CEFUSE_MOD, 0x0024) + +/* PRM.WKUP_PRM register offsets */ +#define OMAP4430_RM_WKUP_L4WKUP_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0024) +#define OMAP4430_RM_WKUP_WDT1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x002c) +#define OMAP4430_PM_WKUP_WDT2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0030) +#define OMAP4430_RM_WKUP_WDT2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0034) +#define OMAP4430_PM_WKUP_GPIO1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0038) +#define OMAP4430_RM_WKUP_GPIO1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x003c) +#define OMAP4430_PM_WKUP_TIMER1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0040) +#define OMAP4430_RM_WKUP_TIMER1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0044) +#define OMAP4430_PM_WKUP_TIMER12_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0048) +#define OMAP4430_RM_WKUP_TIMER12_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x004c) +#define OMAP4430_RM_WKUP_SYNCTIMER_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0054) +#define OMAP4430_PM_WKUP_USIM_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0058) +#define OMAP4430_RM_WKUP_USIM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x005c) +#define OMAP4430_RM_WKUP_SARRAM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0064) +#define OMAP4430_PM_WKUP_KEYBOARD_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0078) +#define OMAP4430_RM_WKUP_KEYBOARD_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x007c) +#define OMAP4430_PM_WKUP_RTC_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0080) +#define OMAP4430_RM_WKUP_RTC_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0084) + +/* PRM.WKUP_CM register offsets */ +#define OMAP4430_CM_WKUP_CLKSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0000) +#define OMAP4430_CM_WKUP_L4WKUP_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0020) +#define OMAP4430_CM_WKUP_WDT1_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0028) +#define OMAP4430_CM_WKUP_WDT2_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0030) +#define OMAP4430_CM_WKUP_GPIO1_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0038) +#define OMAP4430_CM_WKUP_TIMER1_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0040) +#define OMAP4430_CM_WKUP_TIMER12_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0048) +#define OMAP4430_CM_WKUP_SYNCTIMER_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0050) +#define OMAP4430_CM_WKUP_USIM_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0058) +#define OMAP4430_CM_WKUP_SARRAM_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0060) +#define OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0078) +#define OMAP4430_CM_WKUP_RTC_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0080) +#define OMAP4430_CM_WKUP_BANDGAP_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0088) + +/* PRM.EMU_PRM register offsets */ +#define OMAP4430_PM_EMU_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_MOD, 0x0000) +#define OMAP4430_PM_EMU_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_MOD, 0x0004) +#define OMAP4430_RM_EMU_DEBUGSS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_MOD, 0x0024) + +/* PRM.EMU_CM register offsets */ +#define OMAP4430_CM_EMU_CLKSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_CM_MOD, 0x0000) +#define OMAP4430_CM_EMU_DYNAMICDEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_CM_MOD, 0x0008) +#define OMAP4430_CM_EMU_DEBUGSS_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_CM_MOD, 0x0020) + +/* PRM.DEVICE_PRM register offsets */ +#define OMAP4430_PRM_RSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0000) +#define OMAP4430_PRM_RSTST OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0004) +#define OMAP4430_PRM_RSTTIME OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0008) +#define OMAP4430_PRM_CLKREQCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x000c) +#define OMAP4430_PRM_VOLTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0010) +#define OMAP4430_PRM_PWRREQCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0014) +#define OMAP4430_PRM_PSCON_COUNT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0018) +#define OMAP4430_PRM_IO_COUNT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x001c) +#define OMAP4430_PRM_IO_PMCTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0020) +#define OMAP4430_PRM_VOLTSETUP_WARMRESET OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0024) +#define OMAP4430_PRM_VOLTSETUP_CORE_OFF OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0028) +#define OMAP4430_PRM_VOLTSETUP_MPU_OFF OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x002c) +#define OMAP4430_PRM_VOLTSETUP_IVA_OFF OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0030) +#define OMAP4430_PRM_VOLTSETUP_CORE_RET_SLEEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0034) +#define OMAP4430_PRM_VOLTSETUP_MPU_RET_SLEEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0038) +#define OMAP4430_PRM_VOLTSETUP_IVA_RET_SLEEP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x003c) +#define OMAP4430_PRM_VP_CORE_CONFIG OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0040) +#define OMAP4430_PRM_VP_CORE_STATUS OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0044) +#define OMAP4430_PRM_VP_CORE_VLIMITTO OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0048) +#define OMAP4430_PRM_VP_CORE_VOLTAGE OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x004c) +#define OMAP4430_PRM_VP_CORE_VSTEPMAX OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0050) +#define OMAP4430_PRM_VP_CORE_VSTEPMIN OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0054) +#define OMAP4430_PRM_VP_MPU_CONFIG OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0058) +#define OMAP4430_PRM_VP_MPU_STATUS OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x005c) +#define OMAP4430_PRM_VP_MPU_VLIMITTO OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0060) +#define OMAP4430_PRM_VP_MPU_VOLTAGE OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0064) +#define OMAP4430_PRM_VP_MPU_VSTEPMAX OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0068) +#define OMAP4430_PRM_VP_MPU_VSTEPMIN OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x006c) +#define OMAP4430_PRM_VP_IVA_CONFIG OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0070) +#define OMAP4430_PRM_VP_IVA_STATUS OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0074) +#define OMAP4430_PRM_VP_IVA_VLIMITTO OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0078) +#define OMAP4430_PRM_VP_IVA_VOLTAGE OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x007c) +#define OMAP4430_PRM_VP_IVA_VSTEPMAX OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0080) +#define OMAP4430_PRM_VP_IVA_VSTEPMIN OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0084) +#define OMAP4430_PRM_VC_SMPS_SA OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0088) +#define OMAP4430_PRM_VC_VAL_SMPS_RA_VOL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x008c) +#define OMAP4430_PRM_VC_VAL_SMPS_RA_CMD OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0090) +#define OMAP4430_PRM_VC_VAL_CMD_VDD_CORE_L OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0094) +#define OMAP4430_PRM_VC_VAL_CMD_VDD_MPU_L OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0098) +#define OMAP4430_PRM_VC_VAL_CMD_VDD_IVA_L OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x009c) +#define OMAP4430_PRM_VC_VAL_BYPASS OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00a0) +#define OMAP4430_PRM_VC_CFG_CHANNEL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00a4) +#define OMAP4430_PRM_VC_CFG_I2C_MODE OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00a8) +#define OMAP4430_PRM_VC_CFG_I2C_CLK OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00ac) +#define OMAP4430_PRM_SRAM_COUNT OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00b0) +#define OMAP4430_PRM_SRAM_WKUP_SETUP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00b4) +#define OMAP4430_PRM_LDO_SRAM_CORE_SETUP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00b8) +#define OMAP4430_PRM_LDO_SRAM_CORE_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00bc) +#define OMAP4430_PRM_LDO_SRAM_MPU_SETUP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00c0) +#define OMAP4430_PRM_LDO_SRAM_MPU_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00c4) +#define OMAP4430_PRM_LDO_SRAM_IVA_SETUP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00c8) +#define OMAP4430_PRM_LDO_SRAM_IVA_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00cc) +#define OMAP4430_PRM_LDO_ABB_MPU_SETUP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00d0) +#define OMAP4430_PRM_LDO_ABB_MPU_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00d4) +#define OMAP4430_PRM_LDO_ABB_IVA_SETUP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00d8) +#define OMAP4430_PRM_LDO_ABB_IVA_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00dc) +#define OMAP4430_PRM_LDO_BANDGAP_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e0) +#define OMAP4430_PRM_DEVICE_OFF_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e4) +#define OMAP4430_PRM_PHASE1_CNDP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e8) +#define OMAP4430_PRM_PHASE2A_CNDP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00ec) +#define OMAP4430_PRM_PHASE2B_CNDP OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00f0) +#define OMAP4430_PRM_MODEM_IF_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00f4) + +/* CHIRON_PRCM */ + + +/* CHIRON_PRCM.CHIRONSS_OCP_SOCKET_PRCM register offsets */ +#define OMAP4430_REVISION_PRCM OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_OCP_SOCKET_PRCM_MOD, 0x0000) + +/* CHIRON_PRCM.CHIRONSS_DEVICE_PRM register offsets */ +#define OMAP4430_CHIRON_PRCM_PRM_RSTST OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_DEVICE_PRM_MOD, 0x0000) + +/* CHIRON_PRCM.CHIRONSS_CPU0 register offsets */ +#define OMAP4430_PM_PDA_CPU0_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0000) +#define OMAP4430_PM_PDA_CPU0_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0004) +#define OMAP4430_RM_PDA_CPU0_CPU0_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0008) +#define OMAP4430_RM_PDA_CPU0_CPU0_RSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x000c) +#define OMAP4430_RM_PDA_CPU0_CPU0_RSTST OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0010) +#define OMAP4430_CM_PDA_CPU0_CPU0_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0014) +#define OMAP4430_CM_PDA_CPU0_CLKSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0018) + +/* CHIRON_PRCM.CHIRONSS_CPU1 register offsets */ +#define OMAP4430_PM_PDA_CPU1_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0000) +#define OMAP4430_PM_PDA_CPU1_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0004) +#define OMAP4430_RM_PDA_CPU1_CPU1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0008) +#define OMAP4430_RM_PDA_CPU1_CPU1_RSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x000c) +#define OMAP4430_RM_PDA_CPU1_CPU1_RSTST OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0010) +#define OMAP4430_CM_PDA_CPU1_CPU1_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0014) +#define OMAP4430_CM_PDA_CPU1_CLKSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0018) +#endif diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c index 9a592199321c5330237faf303500149356604270..cbfbd142e946662fe1b4d6588873a79273aa4bfa 100644 --- a/arch/arm/mach-omap2/sdrc.c +++ b/arch/arm/mach-omap2/sdrc.c @@ -160,3 +160,19 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0, sdrc_write_reg(l, SDRC_POWER); omap2_sms_save_context(); } + +void omap2_sms_write_rot_control(u32 val, unsigned ctx) +{ + sms_write_reg(val, SMS_ROT_CONTROL(ctx)); +} + +void omap2_sms_write_rot_size(u32 val, unsigned ctx) +{ + sms_write_reg(val, SMS_ROT_SIZE(ctx)); +} + +void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx) +{ + sms_write_reg(val, SMS_ROT_PHYSICAL_BA(ctx)); +} + diff --git a/arch/arm/mach-omap2/sdrc.h b/arch/arm/mach-omap2/sdrc.h index 48207b0189899342236fac5d74315d758c8adac0..68f57bb67fc567ca3a4193f548203eb4eb54f5b0 100644 --- a/arch/arm/mach-omap2/sdrc.h +++ b/arch/arm/mach-omap2/sdrc.h @@ -18,6 +18,9 @@ #include #ifndef __ASSEMBLER__ + +#include + extern void __iomem *omap2_sdrc_base; extern void __iomem *omap2_sms_base; @@ -56,4 +59,20 @@ static inline u32 sms_read_reg(u16 reg) OMAP2_L3_IO_ADDRESS(OMAP343X_SDRC_BASE + (reg)) #endif /* __ASSEMBLER__ */ +/* Minimum frequency that the SDRC DLL can lock at */ +#define MIN_SDRC_DLL_LOCK_FREQ 83000000 + +/* Scale factor for fixed-point arith in omap3_core_dpll_m2_set_rate() */ +#define SDRC_MPURATE_SCALE 8 + +/* 2^SDRC_MPURATE_BASE_SHIFT: MPU MHz that SDRC_MPURATE_LOOPS is defined for */ +#define SDRC_MPURATE_BASE_SHIFT 9 + +/* + * SDRC_MPURATE_LOOPS: Number of MPU loops to execute at + * 2^MPURATE_BASE_SHIFT MHz for SDRC to stabilize + */ +#define SDRC_MPURATE_LOOPS 96 + + #endif diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 2e17b57f5b23bb6703a2d621103585af1d8d729b..39b797bc14d62045c8f1d7f198f9522b4c5c78a2 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -33,6 +33,7 @@ #include "pm.h" #include "prm-regbits-34xx.h" +#define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52 #define UART_OMAP_WER 0x17 /* Wake-up enable register */ #define DEFAULT_TIMEOUT (5 * HZ) @@ -572,6 +573,23 @@ static struct omap_uart_state omap_uart[] = { #endif }; +/* + * Override the default 8250 read handler: mem_serial_in() + * Empty RX fifo read causes an abort on omap3630 and omap4 + * This function makes sure that an empty rx fifo is not read on these silicons + * (OMAP1/2/3430 are not affected) + */ +static unsigned int serial_in_override(struct uart_port *up, int offset) +{ + if (UART_RX == offset) { + unsigned int lsr; + lsr = serial_read_reg(omap_uart[up->line].p, UART_LSR); + if (!(lsr & UART_LSR_DR)) + return -EPERM; + } + return serial_read_reg(omap_uart[up->line].p, offset); +} + void __init omap_serial_early_init(void) { int i; @@ -631,24 +649,64 @@ void __init omap_serial_early_init(void) } } -void __init omap_serial_init(void) +/** + * omap_serial_init_port() - initialize single serial port + * @port: serial port number (0-3) + * + * This function initialies serial driver for given @port only. + * Platforms can call this function instead of omap_serial_init() + * if they don't plan to use all available UARTs as serial ports. + * + * Don't mix calls to omap_serial_init_port() and omap_serial_init(), + * use only one of the two. + */ +void __init omap_serial_init_port(int port) { - int i; + struct omap_uart_state *uart; + struct platform_device *pdev; + struct device *dev; - for (i = 0; i < ARRAY_SIZE(omap_uart); i++) { - struct omap_uart_state *uart = &omap_uart[i]; - struct platform_device *pdev = &uart->pdev; - struct device *dev = &pdev->dev; + BUG_ON(port < 0); + BUG_ON(port >= ARRAY_SIZE(omap_uart)); - omap_uart_reset(uart); - omap_uart_idle_init(uart); + uart = &omap_uart[port]; + pdev = &uart->pdev; + dev = &pdev->dev; - if (WARN_ON(platform_device_register(pdev))) - continue; - if ((cpu_is_omap34xx() && uart->padconf) || - (uart->wk_en && uart->wk_mask)) { - device_init_wakeup(dev, true); - DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout); - } + omap_uart_reset(uart); + omap_uart_idle_init(uart); + + if (WARN_ON(platform_device_register(pdev))) + return; + + if ((cpu_is_omap34xx() && uart->padconf) || + (uart->wk_en && uart->wk_mask)) { + device_init_wakeup(dev, true); + DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout); } + + /* omap44xx: Never read empty UART fifo + * omap3xxx: Never read empty UART fifo on UARTs + * with IP rev >=0x52 + */ + if (cpu_is_omap44xx()) + uart->p->serial_in = serial_in_override; + else if ((serial_read_reg(uart->p, UART_OMAP_MVER) & 0xFF) + >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV) + uart->p->serial_in = serial_in_override; +} + +/** + * omap_serial_init() - intialize all supported serial ports + * + * Initializes all available UARTs as serial ports. Platforms + * can call this function when they want to have default behaviour + * for serial ports (e.g initialize them all as serial ports). + */ +void __init omap_serial_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(omap_uart); i++) + omap_serial_init_port(i); } diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S index 82aa4a3d160ce917b8b85ce0959b3a5d093968ed..de99ba2a57ab21c1c82ce739e94e2f306668337c 100644 --- a/arch/arm/mach-omap2/sram34xx.S +++ b/arch/arm/mach-omap2/sram34xx.S @@ -91,8 +91,19 @@ * new SDRC_ACTIM_CTRL_B_1 register contents * new SDRC_MR_1 register value * - * If the param SDRC_RFR_CTRL_1 is 0, the parameters - * are not programmed into the SDRC CS1 registers + * If the param SDRC_RFR_CTRL_1 is 0, the parameters are not programmed into + * the SDRC CS1 registers + * + * NOTE: This code no longer attempts to program the SDRC AC timing and MR + * registers. This is because the code currently cannot ensure that all + * L3 initiators (e.g., sDMA, IVA, DSS DISPC, etc.) are not accessing the + * SDRAM when the registers are written. If the registers are changed while + * an initiator is accessing SDRAM, memory can be corrupted and/or the SDRC + * may enter an unpredictable state. In the future, the intent is to + * re-enable this code in cases where we can ensure that no initiators are + * touching the SDRAM. Until that time, users who know that their use case + * can satisfy the above requirement can enable the CONFIG_OMAP3_SDRC_AC_TIMING + * option. */ ENTRY(omap3_sram_configure_core_dpll) stmfd sp!, {r1-r12, lr} @ store regs to stack @@ -219,6 +230,7 @@ configure_sdrc: ldr r12, omap_sdrc_rfr_ctrl_0_val @ fetch value from SRAM ldr r11, omap3_sdrc_rfr_ctrl_0 @ fetch addr from SRAM str r12, [r11] @ store +#ifdef CONFIG_OMAP3_SDRC_AC_TIMING ldr r12, omap_sdrc_actim_ctrl_a_0_val ldr r11, omap3_sdrc_actim_ctrl_a_0 str r12, [r11] @@ -228,11 +240,13 @@ configure_sdrc: ldr r12, omap_sdrc_mr_0_val ldr r11, omap3_sdrc_mr_0 str r12, [r11] +#endif ldr r12, omap_sdrc_rfr_ctrl_1_val cmp r12, #0 @ if SDRC_RFR_CTRL_1 is 0, beq skip_cs1_prog @ do not program cs1 params ldr r11, omap3_sdrc_rfr_ctrl_1 str r12, [r11] +#ifdef CONFIG_OMAP3_SDRC_AC_TIMING ldr r12, omap_sdrc_actim_ctrl_a_1_val ldr r11, omap3_sdrc_actim_ctrl_a_1 str r12, [r11] @@ -242,6 +256,7 @@ configure_sdrc: ldr r12, omap_sdrc_mr_1_val ldr r11, omap3_sdrc_mr_1 str r12, [r11] +#endif skip_cs1_prog: ldr r12, [r11] @ posted-write barrier for SDRC bx lr diff --git a/arch/arm/mach-omap2/usb-ehci.c b/arch/arm/mach-omap2/usb-ehci.c index e448abd5ec5d8e629e71a1fe70357eec6ae57275..f1df873d59dbf881b9d6a60e01ea9dab1fc1a845 100644 --- a/arch/arm/mach-omap2/usb-ehci.c +++ b/arch/arm/mach-omap2/usb-ehci.c @@ -27,6 +27,8 @@ #include #include +#include "mux.h" + #if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE) static struct resource ehci_resources[] = { @@ -72,32 +74,44 @@ static void setup_ehci_io_mux(enum ehci_hcd_omap_mode *port_mode) { switch (port_mode[0]) { case EHCI_HCD_OMAP_MODE_PHY: - omap_cfg_reg(Y9_3430_USB1HS_PHY_STP); - omap_cfg_reg(Y8_3430_USB1HS_PHY_CLK); - omap_cfg_reg(AA14_3430_USB1HS_PHY_DIR); - omap_cfg_reg(AA11_3430_USB1HS_PHY_NXT); - omap_cfg_reg(W13_3430_USB1HS_PHY_DATA0); - omap_cfg_reg(W12_3430_USB1HS_PHY_DATA1); - omap_cfg_reg(W11_3430_USB1HS_PHY_DATA2); - omap_cfg_reg(Y11_3430_USB1HS_PHY_DATA3); - omap_cfg_reg(W9_3430_USB1HS_PHY_DATA4); - omap_cfg_reg(Y12_3430_USB1HS_PHY_DATA5); - omap_cfg_reg(W8_3430_USB1HS_PHY_DATA6); - omap_cfg_reg(Y13_3430_USB1HS_PHY_DATA7); + omap_mux_init_signal("hsusb1_stp", OMAP_PIN_OUTPUT); + omap_mux_init_signal("hsusb1_clk", OMAP_PIN_OUTPUT); + omap_mux_init_signal("hsusb1_dir", OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_nxt", OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_data0", OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_data1", OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_data2", OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_data3", OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_data4", OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_data5", OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_data6", OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_data7", OMAP_PIN_INPUT_PULLDOWN); break; case EHCI_HCD_OMAP_MODE_TLL: - omap_cfg_reg(Y9_3430_USB1HS_TLL_STP); - omap_cfg_reg(Y8_3430_USB1HS_TLL_CLK); - omap_cfg_reg(AA14_3430_USB1HS_TLL_DIR); - omap_cfg_reg(AA11_3430_USB1HS_TLL_NXT); - omap_cfg_reg(W13_3430_USB1HS_TLL_DATA0); - omap_cfg_reg(W12_3430_USB1HS_TLL_DATA1); - omap_cfg_reg(W11_3430_USB1HS_TLL_DATA2); - omap_cfg_reg(Y11_3430_USB1HS_TLL_DATA3); - omap_cfg_reg(W9_3430_USB1HS_TLL_DATA4); - omap_cfg_reg(Y12_3430_USB1HS_TLL_DATA5); - omap_cfg_reg(W8_3430_USB1HS_TLL_DATA6); - omap_cfg_reg(Y13_3430_USB1HS_TLL_DATA7); + omap_mux_init_signal("hsusb1_tll_stp", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("hsusb1_tll_clk", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_tll_dir", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_tll_nxt", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_tll_data0", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_tll_data1", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_tll_data2", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_tll_data3", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_tll_data4", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_tll_data5", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_tll_data6", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb1_tll_data7", + OMAP_PIN_INPUT_PULLDOWN); break; case EHCI_HCD_OMAP_MODE_UNKNOWN: /* FALLTHROUGH */ @@ -107,32 +121,52 @@ static void setup_ehci_io_mux(enum ehci_hcd_omap_mode *port_mode) switch (port_mode[1]) { case EHCI_HCD_OMAP_MODE_PHY: - omap_cfg_reg(AA10_3430_USB2HS_PHY_STP); - omap_cfg_reg(AA8_3430_USB2HS_PHY_CLK); - omap_cfg_reg(AA9_3430_USB2HS_PHY_DIR); - omap_cfg_reg(AB11_3430_USB2HS_PHY_NXT); - omap_cfg_reg(AB10_3430_USB2HS_PHY_DATA0); - omap_cfg_reg(AB9_3430_USB2HS_PHY_DATA1); - omap_cfg_reg(W3_3430_USB2HS_PHY_DATA2); - omap_cfg_reg(T4_3430_USB2HS_PHY_DATA3); - omap_cfg_reg(T3_3430_USB2HS_PHY_DATA4); - omap_cfg_reg(R3_3430_USB2HS_PHY_DATA5); - omap_cfg_reg(R4_3430_USB2HS_PHY_DATA6); - omap_cfg_reg(T2_3430_USB2HS_PHY_DATA7); + omap_mux_init_signal("hsusb2_stp", OMAP_PIN_OUTPUT); + omap_mux_init_signal("hsusb2_clk", OMAP_PIN_OUTPUT); + omap_mux_init_signal("hsusb2_dir", OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_nxt", OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_data0", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_data1", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_data2", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_data3", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_data4", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_data5", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_data6", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_data7", + OMAP_PIN_INPUT_PULLDOWN); break; case EHCI_HCD_OMAP_MODE_TLL: - omap_cfg_reg(AA10_3430_USB2HS_TLL_STP); - omap_cfg_reg(AA8_3430_USB2HS_TLL_CLK); - omap_cfg_reg(AA9_3430_USB2HS_TLL_DIR); - omap_cfg_reg(AB11_3430_USB2HS_TLL_NXT); - omap_cfg_reg(AB10_3430_USB2HS_TLL_DATA0); - omap_cfg_reg(AB9_3430_USB2HS_TLL_DATA1); - omap_cfg_reg(W3_3430_USB2HS_TLL_DATA2); - omap_cfg_reg(T4_3430_USB2HS_TLL_DATA3); - omap_cfg_reg(T3_3430_USB2HS_TLL_DATA4); - omap_cfg_reg(R3_3430_USB2HS_TLL_DATA5); - omap_cfg_reg(R4_3430_USB2HS_TLL_DATA6); - omap_cfg_reg(T2_3430_USB2HS_TLL_DATA7); + omap_mux_init_signal("hsusb2_tll_stp", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("hsusb2_tll_clk", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_tll_dir", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_tll_nxt", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_tll_data0", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_tll_data1", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_tll_data2", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_tll_data3", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_tll_data4", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_tll_data5", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_tll_data6", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb2_tll_data7", + OMAP_PIN_INPUT_PULLDOWN); break; case EHCI_HCD_OMAP_MODE_UNKNOWN: /* FALLTHROUGH */ @@ -145,18 +179,30 @@ static void setup_ehci_io_mux(enum ehci_hcd_omap_mode *port_mode) printk(KERN_WARNING "Port3 can't be used in PHY mode\n"); break; case EHCI_HCD_OMAP_MODE_TLL: - omap_cfg_reg(AB3_3430_USB3HS_TLL_STP); - omap_cfg_reg(AA6_3430_USB3HS_TLL_CLK); - omap_cfg_reg(AA3_3430_USB3HS_TLL_DIR); - omap_cfg_reg(Y3_3430_USB3HS_TLL_NXT); - omap_cfg_reg(AA5_3430_USB3HS_TLL_DATA0); - omap_cfg_reg(Y4_3430_USB3HS_TLL_DATA1); - omap_cfg_reg(Y5_3430_USB3HS_TLL_DATA2); - omap_cfg_reg(W5_3430_USB3HS_TLL_DATA3); - omap_cfg_reg(AB12_3430_USB3HS_TLL_DATA4); - omap_cfg_reg(AB13_3430_USB3HS_TLL_DATA5); - omap_cfg_reg(AA13_3430_USB3HS_TLL_DATA6); - omap_cfg_reg(AA12_3430_USB3HS_TLL_DATA7); + omap_mux_init_signal("hsusb3_tll_stp", + OMAP_PIN_INPUT_PULLUP); + omap_mux_init_signal("hsusb3_tll_clk", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb3_tll_dir", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb3_tll_nxt", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb3_tll_data0", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb3_tll_data1", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb3_tll_data2", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb3_tll_data3", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb3_tll_data4", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb3_tll_data5", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb3_tll_data6", + OMAP_PIN_INPUT_PULLDOWN); + omap_mux_init_signal("hsusb3_tll_data7", + OMAP_PIN_INPUT_PULLDOWN); break; case EHCI_HCD_OMAP_MODE_UNKNOWN: /* FALLTHROUGH */ diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index d89c6adbe8bc44a3434a43bd0253716be0340c54..e6d8e10ae5d1fe74c8e8b17414a325c69a763f6c 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -63,6 +63,15 @@ config ARCH_VIPER select HAVE_PWM select PXA_HAVE_BOARD_IRQS select PXA_HAVE_ISA_IRQS + select ARCOM_PCMCIA + +config MACH_ARCOM_ZEUS + bool "Arcom/Eurotech ZEUS SBC" + select PXA27x + select ISA + select PXA_HAVE_BOARD_IRQS + select PXA_HAVE_ISA_IRQS + select ARCOM_PCMCIA config MACH_BALLOON3 bool "Balloon 3 board" @@ -179,6 +188,11 @@ config MACH_TRIZEPS_ANY endchoice +config ARCOM_PCMCIA + bool + help + Generic option for Arcom Viper/Zeus PCMCIA + config TRIZEPS_PCMCIA bool help diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index b5d29e60a3412b6f0abbbdfa8a584d2d4a53c69e..f64afda7e6f6323c65ddbffa13ddc7c3370959e8 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_MACH_SAAR) += saar.o # 3rd Party Dev Platforms obj-$(CONFIG_ARCH_PXA_IDP) += idp.o obj-$(CONFIG_ARCH_VIPER) += viper.o +obj-$(CONFIG_MACH_ARCOM_ZEUS) += zeus.o obj-$(CONFIG_MACH_BALLOON3) += balloon3.o obj-$(CONFIG_MACH_CSB726) += csb726.o obj-$(CONFIG_CSB726_CSB701) += csb701.o diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index 1c0de808b54d456e9c780146efc26b2168e0a85f..c8a01bc85fdefe2452e9acb74ad590a05953831d 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -497,16 +497,15 @@ static int em_x270_usb_hub_init(void) goto err_free_vbus_gpio; /* USB Hub power-on and reset */ - gpio_direction_output(usb_hub_reset, 0); + gpio_direction_output(usb_hub_reset, 1); + gpio_direction_output(GPIO9_USB_VBUS_EN, 0); regulator_enable(em_x270_usb_ldo); - gpio_set_value(usb_hub_reset, 1); gpio_set_value(usb_hub_reset, 0); + gpio_set_value(usb_hub_reset, 1); regulator_disable(em_x270_usb_ldo); regulator_enable(em_x270_usb_ldo); - gpio_set_value(usb_hub_reset, 1); - - /* enable VBUS */ - gpio_direction_output(GPIO9_USB_VBUS_EN, 1); + gpio_set_value(usb_hub_reset, 0); + gpio_set_value(GPIO9_USB_VBUS_EN, 1); return 0; diff --git a/arch/arm/mach-pxa/include/mach/arcom-pcmcia.h b/arch/arm/mach-pxa/include/mach/arcom-pcmcia.h new file mode 100644 index 0000000000000000000000000000000000000000..d428be4db44c5e415ad2d26ec56c629d83ac2207 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/arcom-pcmcia.h @@ -0,0 +1,11 @@ +#ifndef __ARCOM_PCMCIA_H +#define __ARCOM_PCMCIA_H + +struct arcom_pcmcia_pdata { + int cd_gpio; + int rdy_gpio; + int pwr_gpio; + void (*reset)(int state); +}; + +#endif diff --git a/arch/arm/mach-pxa/include/mach/viper.h b/arch/arm/mach-pxa/include/mach/viper.h index 10988c270ca3270aab82dd8af321332c63125e71..5f5fbf1f648944b0768fee4278611b21505f06b8 100644 --- a/arch/arm/mach-pxa/include/mach/viper.h +++ b/arch/arm/mach-pxa/include/mach/viper.h @@ -85,8 +85,6 @@ /* Interrupt and Configuration Register (VIPER_ICR) */ /* This is a write only register. Only CF_RST is used under Linux */ -extern void viper_cf_rst(int state); - #define VIPER_ICR_RETRIG (1 << 0) #define VIPER_ICR_AUTO_CLR (1 << 1) #define VIPER_ICR_R_DIS (1 << 2) diff --git a/arch/arm/mach-pxa/include/mach/zeus.h b/arch/arm/mach-pxa/include/mach/zeus.h new file mode 100644 index 0000000000000000000000000000000000000000..c387046d2f28c435680f113c0ab835f54e2d0b6a --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/zeus.h @@ -0,0 +1,82 @@ +/* + * arch/arm/mach-pxa/include/mach/zeus.h + * + * Author: David Vrabel + * Created: Sept 28, 2005 + * Copyright: Arcom Control Systems Ltd. + * + * Maintained by: Marc Zyngier + * + * 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. + */ + +#ifndef _MACH_ZEUS_H +#define _MACH_ZEUS_H + +/* Physical addresses */ +#define ZEUS_FLASH_PHYS PXA_CS0_PHYS +#define ZEUS_ETH0_PHYS PXA_CS1_PHYS +#define ZEUS_ETH1_PHYS PXA_CS2_PHYS +#define ZEUS_CPLD_PHYS (PXA_CS4_PHYS+0x2000000) +#define ZEUS_SRAM_PHYS PXA_CS5_PHYS +#define ZEUS_PC104IO_PHYS (0x30000000) + +#define ZEUS_CPLD_VERSION_PHYS (ZEUS_CPLD_PHYS + 0x00000000) +#define ZEUS_CPLD_ISA_IRQ_PHYS (ZEUS_CPLD_PHYS + 0x00800000) +#define ZEUS_CPLD_CONTROL_PHYS (ZEUS_CPLD_PHYS + 0x01000000) +#define ZEUS_CPLD_EXTWDOG_PHYS (ZEUS_CPLD_PHYS + 0x01800000) + +/* GPIOs */ +#define ZEUS_AC97_GPIO 0 +#define ZEUS_WAKEUP_GPIO 1 +#define ZEUS_UARTA_GPIO 9 +#define ZEUS_UARTB_GPIO 10 +#define ZEUS_UARTC_GPIO 12 +#define ZEUS_UARTD_GPIO 11 +#define ZEUS_ETH0_GPIO 14 +#define ZEUS_ISA_GPIO 17 +#define ZEUS_BKLEN_GPIO 19 +#define ZEUS_USB2_PWREN_GPIO 22 +#define ZEUS_PTT_GPIO 27 +#define ZEUS_CF_CD_GPIO 35 +#define ZEUS_MMC_WP_GPIO 52 +#define ZEUS_MMC_CD_GPIO 53 +#define ZEUS_EXTGPIO_GPIO 91 +#define ZEUS_CF_PWEN_GPIO 97 +#define ZEUS_CF_RDY_GPIO 99 +#define ZEUS_LCD_EN_GPIO 101 +#define ZEUS_ETH1_GPIO 113 +#define ZEUS_CAN_GPIO 116 + +#define ZEUS_EXT0_GPIO_BASE 128 +#define ZEUS_EXT1_GPIO_BASE 160 +#define ZEUS_USER_GPIO_BASE 192 + +#define ZEUS_EXT0_GPIO(x) (ZEUS_EXT0_GPIO_BASE + (x)) +#define ZEUS_EXT1_GPIO(x) (ZEUS_EXT1_GPIO_BASE + (x)) +#define ZEUS_USER_GPIO(x) (ZEUS_USER_GPIO_BASE + (x)) + +/* + * CPLD registers: + * Only 4 registers, but spreaded over a 32MB address space. + * Be gentle, and remap that over 32kB... + */ + +#define ZEUS_CPLD (0xf0000000) +#define ZEUS_CPLD_VERSION (ZEUS_CPLD + 0x0000) +#define ZEUS_CPLD_ISA_IRQ (ZEUS_CPLD + 0x1000) +#define ZEUS_CPLD_CONTROL (ZEUS_CPLD + 0x2000) +#define ZEUS_CPLD_EXTWDOG (ZEUS_CPLD + 0x3000) + +/* CPLD register bits */ +#define ZEUS_CPLD_CONTROL_CF_RST 0x01 + +#define ZEUS_PC104IO (0xf1000000) + +#define ZEUS_SRAM_SIZE (256 * 1024) + +#endif + + diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c index cf0d71b7797e09427f9339137e57a58575df31e6..5352b4e5a7dda117cad09368339733f3fef9e106 100644 --- a/arch/arm/mach-pxa/viper.c +++ b/arch/arm/mach-pxa/viper.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -76,14 +77,28 @@ static void viper_icr_clear_bit(unsigned int bit) } /* This function is used from the pcmcia module to reset the CF */ -void viper_cf_rst(int state) +static void viper_cf_reset(int state) { if (state) viper_icr_set_bit(VIPER_ICR_CF_RST); else viper_icr_clear_bit(VIPER_ICR_CF_RST); } -EXPORT_SYMBOL(viper_cf_rst); + +static struct arcom_pcmcia_pdata viper_pcmcia_info = { + .cd_gpio = VIPER_CF_CD_GPIO, + .rdy_gpio = VIPER_CF_RDY_GPIO, + .pwr_gpio = VIPER_CF_POWER_GPIO, + .reset = viper_cf_reset, +}; + +static struct platform_device viper_pcmcia_device = { + .name = "viper-pcmcia", + .id = -1, + .dev = { + .platform_data = &viper_pcmcia_info, + }, +}; /* * The CPLD version register was not present on VIPER boards prior to @@ -685,6 +700,7 @@ static struct platform_device *viper_devs[] __initdata = { &viper_mtd_devices[0], &viper_mtd_devices[1], &viper_backlight_device, + &viper_pcmcia_device, }; static mfp_cfg_t viper_pin_config[] __initdata = { diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c new file mode 100644 index 0000000000000000000000000000000000000000..5b986a8bd9e62a41a057b533da7e978549a7dc82 --- /dev/null +++ b/arch/arm/mach-pxa/zeus.c @@ -0,0 +1,820 @@ +/* + * Support for the Arcom ZEUS. + * + * Copyright (C) 2006 Arcom Control Systems Ltd. + * + * Loosely based on Arcom's 2.6.16.28. + * Maintained by Marc Zyngier + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "generic.h" + +/* + * Interrupt handling + */ + +static unsigned long zeus_irq_enabled_mask; +static const int zeus_isa_irqs[] = { 3, 4, 5, 6, 7, 10, 11, 12, }; +static const int zeus_isa_irq_map[] = { + 0, /* ISA irq #0, invalid */ + 0, /* ISA irq #1, invalid */ + 0, /* ISA irq #2, invalid */ + 1 << 0, /* ISA irq #3 */ + 1 << 1, /* ISA irq #4 */ + 1 << 2, /* ISA irq #5 */ + 1 << 3, /* ISA irq #6 */ + 1 << 4, /* ISA irq #7 */ + 0, /* ISA irq #8, invalid */ + 0, /* ISA irq #9, invalid */ + 1 << 5, /* ISA irq #10 */ + 1 << 6, /* ISA irq #11 */ + 1 << 7, /* ISA irq #12 */ +}; + +static inline int zeus_irq_to_bitmask(unsigned int irq) +{ + return zeus_isa_irq_map[irq - PXA_ISA_IRQ(0)]; +} + +static inline int zeus_bit_to_irq(int bit) +{ + return zeus_isa_irqs[bit] + PXA_ISA_IRQ(0); +} + +static void zeus_ack_irq(unsigned int irq) +{ + __raw_writew(zeus_irq_to_bitmask(irq), ZEUS_CPLD_ISA_IRQ); +} + +static void zeus_mask_irq(unsigned int irq) +{ + zeus_irq_enabled_mask &= ~(zeus_irq_to_bitmask(irq)); +} + +static void zeus_unmask_irq(unsigned int irq) +{ + zeus_irq_enabled_mask |= zeus_irq_to_bitmask(irq); +} + +static inline unsigned long zeus_irq_pending(void) +{ + return __raw_readw(ZEUS_CPLD_ISA_IRQ) & zeus_irq_enabled_mask; +} + +static void zeus_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + unsigned long pending; + + pending = zeus_irq_pending(); + do { + /* we're in a chained irq handler, + * so ack the interrupt by hand */ + desc->chip->ack(gpio_to_irq(ZEUS_ISA_GPIO)); + + if (likely(pending)) { + irq = zeus_bit_to_irq(__ffs(pending)); + generic_handle_irq(irq); + } + pending = zeus_irq_pending(); + } while (pending); +} + +static struct irq_chip zeus_irq_chip = { + .name = "ISA", + .ack = zeus_ack_irq, + .mask = zeus_mask_irq, + .unmask = zeus_unmask_irq, +}; + +static void __init zeus_init_irq(void) +{ + int level; + int isa_irq; + + pxa27x_init_irq(); + + /* Peripheral IRQs. It would be nice to move those inside driver + configuration, but it is not supported at the moment. */ + set_irq_type(gpio_to_irq(ZEUS_AC97_GPIO), IRQ_TYPE_EDGE_RISING); + set_irq_type(gpio_to_irq(ZEUS_WAKEUP_GPIO), IRQ_TYPE_EDGE_RISING); + set_irq_type(gpio_to_irq(ZEUS_PTT_GPIO), IRQ_TYPE_EDGE_RISING); + set_irq_type(gpio_to_irq(ZEUS_EXTGPIO_GPIO), IRQ_TYPE_EDGE_FALLING); + set_irq_type(gpio_to_irq(ZEUS_CAN_GPIO), IRQ_TYPE_EDGE_FALLING); + + /* Setup ISA IRQs */ + for (level = 0; level < ARRAY_SIZE(zeus_isa_irqs); level++) { + isa_irq = zeus_bit_to_irq(level); + set_irq_chip(isa_irq, &zeus_irq_chip); + set_irq_handler(isa_irq, handle_edge_irq); + set_irq_flags(isa_irq, IRQF_VALID | IRQF_PROBE); + } + + set_irq_type(gpio_to_irq(ZEUS_ISA_GPIO), IRQ_TYPE_EDGE_RISING); + set_irq_chained_handler(gpio_to_irq(ZEUS_ISA_GPIO), zeus_irq_handler); +} + + +/* + * Platform devices + */ + +/* Flash */ +static struct resource zeus_mtd_resources[] = { + [0] = { /* NOR Flash (up to 64MB) */ + .start = ZEUS_FLASH_PHYS, + .end = ZEUS_FLASH_PHYS + SZ_64M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { /* SRAM */ + .start = ZEUS_SRAM_PHYS, + .end = ZEUS_SRAM_PHYS + SZ_512K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct physmap_flash_data zeus_flash_data[] = { + [0] = { + .width = 2, + .parts = NULL, + .nr_parts = 0, + }, +}; + +static struct platform_device zeus_mtd_devices[] = { + [0] = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &zeus_flash_data[0], + }, + .resource = &zeus_mtd_resources[0], + .num_resources = 1, + }, +}; + +/* Serial */ +static struct resource zeus_serial_resources[] = { + { + .start = 0x10000000, + .end = 0x1000000f, + .flags = IORESOURCE_MEM, + }, + { + .start = 0x10800000, + .end = 0x1080000f, + .flags = IORESOURCE_MEM, + }, + { + .start = 0x11000000, + .end = 0x1100000f, + .flags = IORESOURCE_MEM, + }, + { + .start = 0x40100000, + .end = 0x4010001f, + .flags = IORESOURCE_MEM, + }, + { + .start = 0x40200000, + .end = 0x4020001f, + .flags = IORESOURCE_MEM, + }, + { + .start = 0x40700000, + .end = 0x4070001f, + .flags = IORESOURCE_MEM, + }, +}; + +static struct plat_serial8250_port serial_platform_data[] = { + /* External UARTs */ + /* FIXME: Shared IRQs on COM1-COM4 will not work properly on v1i1 hardware. */ + { /* COM1 */ + .mapbase = 0x10000000, + .irq = gpio_to_irq(ZEUS_UARTA_GPIO), + .irqflags = IRQF_TRIGGER_RISING, + .uartclk = 14745600, + .regshift = 1, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .iotype = UPIO_MEM, + }, + { /* COM2 */ + .mapbase = 0x10800000, + .irq = gpio_to_irq(ZEUS_UARTB_GPIO), + .irqflags = IRQF_TRIGGER_RISING, + .uartclk = 14745600, + .regshift = 1, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .iotype = UPIO_MEM, + }, + { /* COM3 */ + .mapbase = 0x11000000, + .irq = gpio_to_irq(ZEUS_UARTC_GPIO), + .irqflags = IRQF_TRIGGER_RISING, + .uartclk = 14745600, + .regshift = 1, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .iotype = UPIO_MEM, + }, + { /* COM4 */ + .mapbase = 0x11800000, + .irq = gpio_to_irq(ZEUS_UARTD_GPIO), + .irqflags = IRQF_TRIGGER_RISING, + .uartclk = 14745600, + .regshift = 1, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .iotype = UPIO_MEM, + }, + /* Internal UARTs */ + { /* FFUART */ + .membase = (void *)&FFUART, + .mapbase = __PREG(FFUART), + .irq = IRQ_FFUART, + .uartclk = 921600 * 16, + .regshift = 2, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .iotype = UPIO_MEM, + }, + { /* BTUART */ + .membase = (void *)&BTUART, + .mapbase = __PREG(BTUART), + .irq = IRQ_BTUART, + .uartclk = 921600 * 16, + .regshift = 2, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .iotype = UPIO_MEM, + }, + { /* STUART */ + .membase = (void *)&STUART, + .mapbase = __PREG(STUART), + .irq = IRQ_STUART, + .uartclk = 921600 * 16, + .regshift = 2, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .iotype = UPIO_MEM, + }, + { }, +}; + +static struct platform_device zeus_serial_device = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = serial_platform_data, + }, + .num_resources = ARRAY_SIZE(zeus_serial_resources), + .resource = zeus_serial_resources, +}; + +/* Ethernet */ +static struct resource zeus_dm9k0_resource[] = { + [0] = { + .start = ZEUS_ETH0_PHYS, + .end = ZEUS_ETH0_PHYS + 1, + .flags = IORESOURCE_MEM + }, + [1] = { + .start = ZEUS_ETH0_PHYS + 2, + .end = ZEUS_ETH0_PHYS + 3, + .flags = IORESOURCE_MEM + }, + [2] = { + .start = gpio_to_irq(ZEUS_ETH0_GPIO), + .end = gpio_to_irq(ZEUS_ETH0_GPIO), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE, + }, +}; + +static struct resource zeus_dm9k1_resource[] = { + [0] = { + .start = ZEUS_ETH1_PHYS, + .end = ZEUS_ETH1_PHYS + 1, + .flags = IORESOURCE_MEM + }, + [1] = { + .start = ZEUS_ETH1_PHYS + 2, + .end = ZEUS_ETH1_PHYS + 3, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = gpio_to_irq(ZEUS_ETH1_GPIO), + .end = gpio_to_irq(ZEUS_ETH1_GPIO), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE, + }, +}; + +static struct dm9000_plat_data zeus_dm9k_platdata = { + .flags = DM9000_PLATF_16BITONLY, +}; + +static struct platform_device zeus_dm9k0_device = { + .name = "dm9000", + .id = 0, + .num_resources = ARRAY_SIZE(zeus_dm9k0_resource), + .resource = zeus_dm9k0_resource, + .dev = { + .platform_data = &zeus_dm9k_platdata, + } +}; + +static struct platform_device zeus_dm9k1_device = { + .name = "dm9000", + .id = 1, + .num_resources = ARRAY_SIZE(zeus_dm9k1_resource), + .resource = zeus_dm9k1_resource, + .dev = { + .platform_data = &zeus_dm9k_platdata, + } +}; + +/* External SRAM */ +static struct resource zeus_sram_resource = { + .start = ZEUS_SRAM_PHYS, + .end = ZEUS_SRAM_PHYS + ZEUS_SRAM_SIZE * 2 - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device zeus_sram_device = { + .name = "pxa2xx-8bit-sram", + .id = 0, + .num_resources = 1, + .resource = &zeus_sram_resource, +}; + +/* SPI interface on SSP3 */ +static struct pxa2xx_spi_master pxa2xx_spi_ssp3_master_info = { + .num_chipselect = 1, + .enable_dma = 1, +}; + +static struct platform_device pxa2xx_spi_ssp3_device = { + .name = "pxa2xx-spi", + .id = 3, + .dev = { + .platform_data = &pxa2xx_spi_ssp3_master_info, + }, +}; + +/* Leds */ +static struct gpio_led zeus_leds[] = { + [0] = { + .name = "zeus:yellow:1", + .default_trigger = "heartbeat", + .gpio = ZEUS_EXT0_GPIO(3), + .active_low = 1, + }, + [1] = { + .name = "zeus:yellow:2", + .default_trigger = "default-on", + .gpio = ZEUS_EXT0_GPIO(4), + .active_low = 1, + }, + [2] = { + .name = "zeus:yellow:3", + .default_trigger = "default-on", + .gpio = ZEUS_EXT0_GPIO(5), + .active_low = 1, + }, +}; + +static struct gpio_led_platform_data zeus_leds_info = { + .leds = zeus_leds, + .num_leds = ARRAY_SIZE(zeus_leds), +}; + +static struct platform_device zeus_leds_device = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &zeus_leds_info, + }, +}; + +static void zeus_cf_reset(int state) +{ + u16 cpld_state = __raw_readw(ZEUS_CPLD_CONTROL); + + if (state) + cpld_state |= ZEUS_CPLD_CONTROL_CF_RST; + else + cpld_state &= ~ZEUS_CPLD_CONTROL_CF_RST; + + __raw_writew(cpld_state, ZEUS_CPLD_CONTROL); +} + +static struct arcom_pcmcia_pdata zeus_pcmcia_info = { + .cd_gpio = ZEUS_CF_CD_GPIO, + .rdy_gpio = ZEUS_CF_RDY_GPIO, + .pwr_gpio = ZEUS_CF_PWEN_GPIO, + .reset = zeus_cf_reset, +}; + +static struct platform_device zeus_pcmcia_device = { + .name = "zeus-pcmcia", + .id = -1, + .dev = { + .platform_data = &zeus_pcmcia_info, + }, +}; + +static struct platform_device *zeus_devices[] __initdata = { + &zeus_serial_device, + &zeus_mtd_devices[0], + &zeus_dm9k0_device, + &zeus_dm9k1_device, + &zeus_sram_device, + &pxa2xx_spi_ssp3_device, + &zeus_leds_device, + &zeus_pcmcia_device, +}; + +/* AC'97 */ +static pxa2xx_audio_ops_t zeus_ac97_info = { + .reset_gpio = 95, +}; + + +/* + * USB host + */ + +static int zeus_ohci_init(struct device *dev) +{ + int err; + + /* Switch on port 2. */ + if ((err = gpio_request(ZEUS_USB2_PWREN_GPIO, "USB2_PWREN"))) { + dev_err(dev, "Can't request USB2_PWREN\n"); + return err; + } + + if ((err = gpio_direction_output(ZEUS_USB2_PWREN_GPIO, 1))) { + gpio_free(ZEUS_USB2_PWREN_GPIO); + dev_err(dev, "Can't enable USB2_PWREN\n"); + return err; + } + + /* Port 2 is shared between host and client interface. */ + UP2OCR = UP2OCR_HXOE | UP2OCR_HXS | UP2OCR_DMPDE | UP2OCR_DPPDE; + + return 0; +} + +static void zeus_ohci_exit(struct device *dev) +{ + /* Power-off port 2 */ + gpio_direction_output(ZEUS_USB2_PWREN_GPIO, 0); + gpio_free(ZEUS_USB2_PWREN_GPIO); +} + +static struct pxaohci_platform_data zeus_ohci_platform_data = { + .port_mode = PMM_NPS_MODE, + .flags = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW, + .init = zeus_ohci_init, + .exit = zeus_ohci_exit, +}; + +/* + * Flat Panel + */ + +static void zeus_lcd_power(int on, struct fb_var_screeninfo *si) +{ + gpio_set_value(ZEUS_LCD_EN_GPIO, on); +} + +static void zeus_backlight_power(int on) +{ + gpio_set_value(ZEUS_BKLEN_GPIO, on); +} + +static int zeus_setup_fb_gpios(void) +{ + int err; + + if ((err = gpio_request(ZEUS_LCD_EN_GPIO, "LCD_EN"))) + goto out_err; + + if ((err = gpio_direction_output(ZEUS_LCD_EN_GPIO, 0))) + goto out_err_lcd; + + if ((err = gpio_request(ZEUS_BKLEN_GPIO, "BKLEN"))) + goto out_err_lcd; + + if ((err = gpio_direction_output(ZEUS_BKLEN_GPIO, 0))) + goto out_err_bkl; + + return 0; + +out_err_bkl: + gpio_free(ZEUS_BKLEN_GPIO); +out_err_lcd: + gpio_free(ZEUS_LCD_EN_GPIO); +out_err: + return err; +} + +static struct pxafb_mode_info zeus_fb_mode_info[] = { + { + .pixclock = 39722, + + .xres = 640, + .yres = 480, + + .bpp = 16, + + .hsync_len = 63, + .left_margin = 16, + .right_margin = 81, + + .vsync_len = 2, + .upper_margin = 12, + .lower_margin = 31, + + .sync = 0, + }, +}; + +static struct pxafb_mach_info zeus_fb_info = { + .modes = zeus_fb_mode_info, + .num_modes = 1, + .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL, + .pxafb_lcd_power = zeus_lcd_power, + .pxafb_backlight_power = zeus_backlight_power, +}; + +/* + * MMC/SD Device + * + * The card detect interrupt isn't debounced so we delay it by 250ms + * to give the card a chance to fully insert/eject. + */ + +static struct pxamci_platform_data zeus_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .detect_delay = HZ/4, + .gpio_card_detect = ZEUS_MMC_CD_GPIO, + .gpio_card_ro = ZEUS_MMC_WP_GPIO, + .gpio_card_ro_invert = 1, + .gpio_power = -1 +}; + +/* + * USB Device Controller + */ +static void zeus_udc_command(int cmd) +{ + switch (cmd) { + case PXA2XX_UDC_CMD_DISCONNECT: + pr_info("zeus: disconnecting USB client\n"); + UP2OCR = UP2OCR_HXOE | UP2OCR_HXS | UP2OCR_DMPDE | UP2OCR_DPPDE; + break; + + case PXA2XX_UDC_CMD_CONNECT: + pr_info("zeus: connecting USB client\n"); + UP2OCR = UP2OCR_HXOE | UP2OCR_DPPUE; + break; + } +} + +static struct pxa2xx_udc_mach_info zeus_udc_info = { + .udc_command = zeus_udc_command, +}; + +static void zeus_power_off(void) +{ + local_irq_disable(); + pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP); +} + +int zeus_get_pcb_info(struct i2c_client *client, unsigned gpio, + unsigned ngpio, void *context) +{ + int i; + u8 pcb_info = 0; + + for (i = 0; i < 8; i++) { + int pcb_bit = gpio + i + 8; + + if (gpio_request(pcb_bit, "pcb info")) { + dev_err(&client->dev, "Can't request pcb info %d\n", i); + continue; + } + + if (gpio_direction_input(pcb_bit)) { + dev_err(&client->dev, "Can't read pcb info %d\n", i); + gpio_free(pcb_bit); + continue; + } + + pcb_info |= !!gpio_get_value(pcb_bit) << i; + + gpio_free(pcb_bit); + } + + dev_info(&client->dev, "Zeus PCB version %d issue %d\n", + pcb_info >> 4, pcb_info & 0xf); + + return 0; +} + +static struct pca953x_platform_data zeus_pca953x_pdata[] = { + [0] = { .gpio_base = ZEUS_EXT0_GPIO_BASE, }, + [1] = { + .gpio_base = ZEUS_EXT1_GPIO_BASE, + .setup = zeus_get_pcb_info, + }, + [2] = { .gpio_base = ZEUS_USER_GPIO_BASE, }, +}; + +static struct i2c_board_info __initdata zeus_i2c_devices[] = { + { + I2C_BOARD_INFO("pca9535", 0x21), + .platform_data = &zeus_pca953x_pdata[0], + }, + { + I2C_BOARD_INFO("pca9535", 0x22), + .platform_data = &zeus_pca953x_pdata[1], + }, + { + I2C_BOARD_INFO("pca9535", 0x20), + .platform_data = &zeus_pca953x_pdata[2], + .irq = gpio_to_irq(ZEUS_EXTGPIO_GPIO), + }, + { I2C_BOARD_INFO("lm75a", 0x48) }, + { I2C_BOARD_INFO("24c01", 0x50) }, + { I2C_BOARD_INFO("isl1208", 0x6f) }, +}; + +static mfp_cfg_t zeus_pin_config[] __initdata = { + GPIO15_nCS_1, + GPIO78_nCS_2, + GPIO80_nCS_4, + GPIO33_nCS_5, + + GPIO22_GPIO, + GPIO32_MMC_CLK, + GPIO92_MMC_DAT_0, + GPIO109_MMC_DAT_1, + GPIO110_MMC_DAT_2, + GPIO111_MMC_DAT_3, + GPIO112_MMC_CMD, + + GPIO88_USBH1_PWR, + GPIO89_USBH1_PEN, + GPIO119_USBH2_PWR, + GPIO120_USBH2_PEN, + + GPIO86_LCD_LDD_16, + GPIO87_LCD_LDD_17, + + GPIO102_GPIO, + GPIO104_CIF_DD_2, + GPIO105_CIF_DD_1, + + GPIO48_nPOE, + GPIO49_nPWE, + GPIO50_nPIOR, + GPIO51_nPIOW, + GPIO85_nPCE_1, + GPIO54_nPCE_2, + GPIO79_PSKTSEL, + GPIO55_nPREG, + GPIO56_nPWAIT, + GPIO57_nIOIS16, + GPIO36_GPIO, /* CF CD */ + GPIO97_GPIO, /* CF PWREN */ + GPIO99_GPIO, /* CF RDY */ +}; + +static void __init zeus_init(void) +{ + u16 dm9000_msc = 0xe279; + + system_rev = __raw_readw(ZEUS_CPLD_VERSION); + pr_info("Zeus CPLD V%dI%d\n", (system_rev & 0xf0) >> 4, (system_rev & 0x0f)); + + /* Fix timings for dm9000s (CS1/CS2)*/ + MSC0 = (MSC0 & 0xffff) | (dm9000_msc << 16); + MSC1 = (MSC1 & 0xffff0000) | dm9000_msc; + + pm_power_off = zeus_power_off; + + pxa2xx_mfp_config(ARRAY_AND_SIZE(zeus_pin_config)); + + platform_add_devices(zeus_devices, ARRAY_SIZE(zeus_devices)); + + pxa_set_ohci_info(&zeus_ohci_platform_data); + + if (zeus_setup_fb_gpios()) + pr_err("Failed to setup fb gpios\n"); + else + set_pxa_fb_info(&zeus_fb_info); + + pxa_set_mci_info(&zeus_mci_platform_data); + pxa_set_udc_info(&zeus_udc_info); + pxa_set_ac97_info(&zeus_ac97_info); + pxa_set_i2c_info(NULL); + i2c_register_board_info(0, ARRAY_AND_SIZE(zeus_i2c_devices)); +} + +static struct map_desc zeus_io_desc[] __initdata = { + { + .virtual = ZEUS_CPLD_VERSION, + .pfn = __phys_to_pfn(ZEUS_CPLD_VERSION_PHYS), + .length = 0x1000, + .type = MT_DEVICE, + }, + { + .virtual = ZEUS_CPLD_ISA_IRQ, + .pfn = __phys_to_pfn(ZEUS_CPLD_ISA_IRQ_PHYS), + .length = 0x1000, + .type = MT_DEVICE, + }, + { + .virtual = ZEUS_CPLD_CONTROL, + .pfn = __phys_to_pfn(ZEUS_CPLD_CONTROL_PHYS), + .length = 0x1000, + .type = MT_DEVICE, + }, + { + .virtual = ZEUS_CPLD_EXTWDOG, + .pfn = __phys_to_pfn(ZEUS_CPLD_EXTWDOG_PHYS), + .length = 0x1000, + .type = MT_DEVICE, + }, + { + .virtual = ZEUS_PC104IO, + .pfn = __phys_to_pfn(ZEUS_PC104IO_PHYS), + .length = 0x00800000, + .type = MT_DEVICE, + }, +}; + +static void __init zeus_map_io(void) +{ + pxa_map_io(); + + iotable_init(zeus_io_desc, ARRAY_SIZE(zeus_io_desc)); + + /* Clear PSPR to ensure a full restart on wake-up. */ + PMCR = PSPR = 0; + + /* enable internal 32.768Khz oscillator (ignore OSCC_OOK) */ + OSCC |= OSCC_OON; + + /* Some clock cycles later (from OSCC_ON), programme PCFR (OPDE...). + * float chip selects and PCMCIA */ + PCFR = PCFR_OPDE | PCFR_DC_EN | PCFR_FS | PCFR_FP; +} + +MACHINE_START(ARCOM_ZEUS, "Arcom ZEUS") + /* Maintainer: Marc Zyngier */ + .phys_io = 0x40000000, + .io_pg_offst = ((io_p2v(0x40000000) >> 18) & 0xfffc), + .boot_params = 0xa0000100, + .map_io = zeus_map_io, + .init_irq = zeus_init_irq, + .timer = &pxa_timer, + .init_machine = zeus_init, +MACHINE_END + diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index c48e1f2c3349492472d02316fb77f0cb7f29c8ed..ee5e392430e87e4f45721320e33172f68e933e56 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -70,7 +70,7 @@ config MACH_REALVIEW_PBX bool "Support RealView/PBX platform" select ARM_GIC select HAVE_PATA_PLATFORM - select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !HIGH_PHYS_OFFSET + select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET select ZONE_DMA if SPARSEMEM help Include support for the ARM(R) RealView PBX platform. diff --git a/arch/arm/mach-s3c24a0/include/mach/memory.h b/arch/arm/mach-s3c24a0/include/mach/memory.h index 585211ca0187487e0cbfc60bc98cc38899a926ec..7d74fd5c8d665aa2aa899c91ed5915aa9a98defe 100644 --- a/arch/arm/mach-s3c24a0/include/mach/memory.h +++ b/arch/arm/mach-s3c24a0/include/mach/memory.h @@ -15,5 +15,7 @@ #define __virt_to_bus(x) __virt_to_phys(x) #define __bus_to_virt(x) __phys_to_virt(x) +#define __pfn_to_bus(x) __pfn_to_phys(x) +#define __bus_to_pfn(x) __phys_to_pfn(x) #endif diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig index 03a7f3857c5e69e210b4370ab5e15218a3b014bd..b17d52f7cc48739b2d02d24e690021c4e28d69fc 100644 --- a/arch/arm/mach-sa1100/Kconfig +++ b/arch/arm/mach-sa1100/Kconfig @@ -4,6 +4,7 @@ menu "SA11x0 Implementations" config SA1100_ASSABET bool "Assabet" + select CPU_FREQ_SA1110 help Say Y here if you are using the Intel(R) StrongARM(R) SA-1110 Microprocessor Development Board (also known as the Assabet). @@ -19,6 +20,7 @@ config ASSABET_NEPONSET config SA1100_CERF bool "CerfBoard" + select CPU_FREQ_SA1110 help The Intrinsyc CerfBoard is based on the StrongARM 1110 (Discontinued). More information is available at: @@ -45,6 +47,7 @@ endchoice config SA1100_COLLIE bool "Sharp Zaurus SL5500" + # FIXME: select CPU_FREQ_SA11x0 select SHARP_LOCOMO select SHARP_SCOOP select SHARP_PARAM @@ -54,6 +57,7 @@ config SA1100_COLLIE config SA1100_H3100 bool "Compaq iPAQ H3100" select HTC_EGPIO + select CPU_FREQ_SA1100 help Say Y here if you intend to run this kernel on the Compaq iPAQ H3100 handheld computer. Information about this machine and the @@ -64,6 +68,7 @@ config SA1100_H3100 config SA1100_H3600 bool "Compaq iPAQ H3600/H3700" select HTC_EGPIO + select CPU_FREQ_SA1100 help Say Y here if you intend to run this kernel on the Compaq iPAQ H3600 handheld computer. Information about this machine and the @@ -74,6 +79,7 @@ config SA1100_H3600 config SA1100_BADGE4 bool "HP Labs BadgePAD 4" select SA1111 + select CPU_FREQ_SA1100 help Say Y here if you want to build a kernel for the HP Laboratories BadgePAD 4. @@ -81,6 +87,7 @@ config SA1100_BADGE4 config SA1100_JORNADA720 bool "HP Jornada 720" select SA1111 + # FIXME: select CPU_FREQ_SA11x0 help Say Y here if you want to build a kernel for the HP Jornada 720 handheld computer. See @@ -98,12 +105,14 @@ config SA1100_JORNADA720_SSP config SA1100_HACKKIT bool "HackKit Core CPU Board" + select CPU_FREQ_SA1100 help Say Y here to support the HackKit Core CPU Board ; config SA1100_LART bool "LART" + select CPU_FREQ_SA1100 help Say Y here if you are using the Linux Advanced Radio Terminal (also known as the LART). See for @@ -111,6 +120,7 @@ config SA1100_LART config SA1100_PLEB bool "PLEB" + select CPU_FREQ_SA1100 help Say Y here if you are using version 1 of the Portable Linux Embedded Board (also known as PLEB). @@ -119,6 +129,7 @@ config SA1100_PLEB config SA1100_SHANNON bool "Shannon" + select CPU_FREQ_SA1100 help The Shannon (also known as a Tuxscreen, and also as a IS2630) was a limited edition webphone produced by Philips. The Shannon is a SA1100 @@ -127,6 +138,7 @@ config SA1100_SHANNON config SA1100_SIMPAD bool "Simpad" + select CPU_FREQ_SA1110 help The SIEMENS webpad SIMpad is based on the StrongARM 1110. There are two different versions CL4 and SL4. CL4 has 32MB RAM and 16MB @@ -145,3 +157,4 @@ config SA1100_SSP endmenu endif + diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 9faea1511c1f06554277b99a35192641e23cade0..3c1fcd6967145cc91a04752db09c856d031f4e49 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -58,7 +58,6 @@ static const unsigned short cclk_frequency_100khz[NR_FREQS] = { 2802 /* 280.2 MHz */ }; -#if defined(CONFIG_CPU_FREQ_SA1100) || defined(CONFIG_CPU_FREQ_SA1110) /* rounds up(!) */ unsigned int sa11x0_freq_to_ppcr(unsigned int khz) { @@ -110,17 +109,6 @@ unsigned int sa11x0_getspeed(unsigned int cpu) return cclk_frequency_100khz[PPCR & 0xf] * 100; } -#else -/* - * We still need to provide this so building without cpufreq works. - */ -unsigned int cpufreq_get(unsigned int cpu) -{ - return cclk_frequency_100khz[PPCR & 0xf] * 100; -} -EXPORT_SYMBOL(cpufreq_get); -#endif - /* * This is the SA11x0 sched_clock implementation. This has * a resolution of 271ns, and a maximum value of 32025597s (370 days). diff --git a/arch/arm/mach-w90x900/include/mach/nuc900_spi.h b/arch/arm/mach-w90x900/include/mach/nuc900_spi.h new file mode 100644 index 0000000000000000000000000000000000000000..bd94819e314fed7f67173c016a00bbcfbacc38c6 --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/nuc900_spi.h @@ -0,0 +1,35 @@ +/* + * arch/arm/mach-w90x900/include/mach/nuc900_spi.h + * + * Copyright (c) 2009 Nuvoton technology corporation. + * + * Wan ZongShun + * + * This program is free software; 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. + * + */ + +#ifndef __ASM_ARCH_SPI_H +#define __ASM_ARCH_SPI_H + +extern void mfp_set_groupg(struct device *dev); + +struct nuc900_spi_info { + unsigned int num_cs; + unsigned int lsb; + unsigned int txneg; + unsigned int rxneg; + unsigned int divider; + unsigned int sleep; + unsigned int txnum; + unsigned int txbitlen; + int bus_num; +}; + +struct nuc900_spi_chip { + unsigned char bits_per_word; +}; + +#endif /* __ASM_ARCH_SPI_H */ diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index 2b7996401b0f9f602dfa2d809f86e40b57f79117..f5abc51c5a07ff24e047ef333c7dd47b942fc3a4 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -54,7 +54,8 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, * We enforce the MAP_FIXED case. */ if (flags & MAP_FIXED) { - if (aliasing && flags & MAP_SHARED && addr & (SHMLBA - 1)) + if (aliasing && flags & MAP_SHARED && + (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)) return -EINVAL; return addr; } diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile index 4cbca9da150599bb8ee4c12df2fa96161a00f8db..996cbac6932c77995650735715e9784c8bb5fbb5 100644 --- a/arch/arm/plat-mxc/Makefile +++ b/arch/arm/plat-mxc/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_ARCH_MX1) += iomux-mx1-mx2.o dma-mx1-mx2.o obj-$(CONFIG_ARCH_MX2) += iomux-mx1-mx2.o dma-mx1-mx2.o obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o obj-$(CONFIG_MXC_PWM) += pwm.o +obj-$(CONFIG_USB_EHCI_MXC) += ehci.o obj-$(CONFIG_MXC_ULPI) += ulpi.o obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o diff --git a/arch/arm/plat-mxc/ehci.c b/arch/arm/plat-mxc/ehci.c new file mode 100644 index 0000000000000000000000000000000000000000..41599be882e8dbb17d01172adff26bed43055e12 --- /dev/null +++ b/arch/arm/plat-mxc/ehci.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2009 Daniel Mack + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You 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 + +#define USBCTRL_OTGBASE_OFFSET 0x600 + +#define MX31_OTG_SIC_SHIFT 29 +#define MX31_OTG_SIC_MASK (0xf << MX31_OTG_SIC_SHIFT) +#define MX31_OTG_PM_BIT (1 << 24) + +#define MX31_H2_SIC_SHIFT 21 +#define MX31_H2_SIC_MASK (0xf << MX31_H2_SIC_SHIFT) +#define MX31_H2_PM_BIT (1 << 16) +#define MX31_H2_DT_BIT (1 << 5) + +#define MX31_H1_SIC_SHIFT 13 +#define MX31_H1_SIC_MASK (0xf << MX31_H1_SIC_SHIFT) +#define MX31_H1_PM_BIT (1 << 8) +#define MX31_H1_DT_BIT (1 << 4) + +int mxc_set_usbcontrol(int port, unsigned int flags) +{ + unsigned int v; + + if (cpu_is_mx31()) { + v = readl(IO_ADDRESS(MX31_OTG_BASE_ADDR + + USBCTRL_OTGBASE_OFFSET)); + + switch (port) { + case 0: /* OTG port */ + v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT); + v |= (flags & MXC_EHCI_INTERFACE_MASK) + << MX31_OTG_SIC_SHIFT; + if (flags & MXC_EHCI_POWER_PINS_ENABLED) + v |= MX31_OTG_PM_BIT; + + break; + case 1: /* H1 port */ + v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT); + v |= (flags & MXC_EHCI_INTERFACE_MASK) + << MX31_H1_SIC_SHIFT; + if (flags & MXC_EHCI_POWER_PINS_ENABLED) + v |= MX31_H1_PM_BIT; + + if (!(flags & MXC_EHCI_TTL_ENABLED)) + v |= MX31_H1_DT_BIT; + + break; + case 2: /* H2 port */ + v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT); + v |= (flags & MXC_EHCI_INTERFACE_MASK) + << MX31_H2_SIC_SHIFT; + if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) + v |= MX31_H2_PM_BIT; + + if (!(flags & MXC_EHCI_TTL_ENABLED)) + v |= MX31_H2_DT_BIT; + + break; + } + + writel(v, IO_ADDRESS(MX31_OTG_BASE_ADDR + + USBCTRL_OTGBASE_OFFSET)); + return 0; + } + + printk(KERN_WARNING + "%s() unable to setup USBCONTROL for this CPU\n", __func__); + return -EINVAL; +} +EXPORT_SYMBOL(mxc_set_usbcontrol); + diff --git a/arch/arm/plat-mxc/include/mach/mxc_ehci.h b/arch/arm/plat-mxc/include/mach/mxc_ehci.h new file mode 100644 index 0000000000000000000000000000000000000000..8f796239393e757a7f1ceff343ddfc7556882d5d --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/mxc_ehci.h @@ -0,0 +1,37 @@ +#ifndef __INCLUDE_ASM_ARCH_MXC_EHCI_H +#define __INCLUDE_ASM_ARCH_MXC_EHCI_H + +/* values for portsc field */ +#define MXC_EHCI_PHY_LOW_POWER_SUSPEND (1 << 23) +#define MXC_EHCI_FORCE_FS (1 << 24) +#define MXC_EHCI_UTMI_8BIT (0 << 28) +#define MXC_EHCI_UTMI_16BIT (1 << 28) +#define MXC_EHCI_SERIAL (1 << 29) +#define MXC_EHCI_MODE_UTMI (0 << 30) +#define MXC_EHCI_MODE_PHILIPS (1 << 30) +#define MXC_EHCI_MODE_ULPI (2 << 30) +#define MXC_EHCI_MODE_SERIAL (3 << 30) + +/* values for flags field */ +#define MXC_EHCI_INTERFACE_DIFF_UNI (0 << 0) +#define MXC_EHCI_INTERFACE_DIFF_BI (1 << 0) +#define MXC_EHCI_INTERFACE_SINGLE_UNI (2 << 0) +#define MXC_EHCI_INTERFACE_SINGLE_BI (3 << 0) +#define MXC_EHCI_INTERFACE_MASK (0xf) + +#define MXC_EHCI_POWER_PINS_ENABLED (1 << 5) +#define MXC_EHCI_TTL_ENABLED (1 << 6) + +struct mxc_usbh_platform_data { + int (*init)(struct platform_device *pdev); + int (*exit)(struct platform_device *pdev); + + unsigned int portsc; + unsigned int flags; + struct otg_transceiver *otg; +}; + +int mxc_set_usbcontrol(int port, unsigned int flags); + +#endif /* __INCLUDE_ASM_ARCH_MXC_EHCI_H */ + diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index f348ddfb04922605edf5401ad2df58314317db78..e2ea04a4c8a1b06b2c8d477b631fe38251fe9018 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -27,6 +27,7 @@ config ARCH_OMAP4 bool "TI OMAP4" select CPU_V7 select ARM_GIC + select COMMON_CLKDEV endchoice @@ -42,28 +43,6 @@ config OMAP_DEBUG_LEDS depends on OMAP_DEBUG_DEVICES default y if LEDS || LEDS_OMAP_DEBUG -config OMAP_DEBUG_POWERDOMAIN - bool "Emit debug messages from powerdomain layer" - depends on ARCH_OMAP2 || ARCH_OMAP3 - help - Say Y here if you want to compile in powerdomain layer - debugging messages for OMAP2/3. These messages can - provide more detail as to why some powerdomain calls - may be failing, and will also emit a descriptive message - for every powerdomain register write. However, the - extra detail costs some memory. - -config OMAP_DEBUG_CLOCKDOMAIN - bool "Emit debug messages from clockdomain layer" - depends on ARCH_OMAP2 || ARCH_OMAP3 - help - Say Y here if you want to compile in clockdomain layer - debugging messages for OMAP2/3. These messages can - provide more detail as to why some clockdomain calls - may be failing, and will also emit a descriptive message - for every clockdomain register write. However, the - extra detail costs some memory. - config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" depends on ARCH_OMAP @@ -78,28 +57,28 @@ config OMAP_RESET_CLOCKS config OMAP_MUX bool "OMAP multiplexing support" - depends on ARCH_OMAP + depends on ARCH_OMAP default y - help - Pin multiplexing support for OMAP boards. If your bootloader - sets the multiplexing correctly, say N. Otherwise, or if unsure, - say Y. + help + Pin multiplexing support for OMAP boards. If your bootloader + sets the multiplexing correctly, say N. Otherwise, or if unsure, + say Y. config OMAP_MUX_DEBUG bool "Multiplexing debug output" - depends on OMAP_MUX - help - Makes the multiplexing functions print out a lot of debug info. - This is useful if you want to find out the correct values of the - multiplexing registers. + depends on OMAP_MUX + help + Makes the multiplexing functions print out a lot of debug info. + This is useful if you want to find out the correct values of the + multiplexing registers. config OMAP_MUX_WARNINGS bool "Warn about pins the bootloader didn't set up" - depends on OMAP_MUX - default y - help + depends on OMAP_MUX + default y + help Choose Y here to warn whenever driver initialization logic needs - to change the pin multiplexing setup. When there are no warnings + to change the pin multiplexing setup. When there are no warnings printed, it's safe to deselect OMAP_MUX for your product. config OMAP_MCBSP @@ -125,7 +104,7 @@ config OMAP_IOMMU_DEBUG tristate choice - prompt "System timer" + prompt "System timer" default OMAP_MPU_TIMER config OMAP_MPU_TIMER @@ -148,11 +127,11 @@ config OMAP_32K_TIMER endchoice config OMAP_32K_TIMER_HZ - int "Kernel internal timer frequency for 32KHz timer" - range 32 1024 - depends on OMAP_32K_TIMER - default "128" - help + int "Kernel internal timer frequency for 32KHz timer" + range 32 1024 + depends on OMAP_32K_TIMER + default "128" + help Kernel internal timer frequency should be a divisor of 32768, such as 64 or 128. diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 681bfc37ebb28b8e926d0cd67e23afd01f95df7e..89cafc9372496d2d33989be36f2ea38b657d0949 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -40,36 +40,10 @@ static struct clk_functions *arch_clock; * clock framework is not up , it is defined here to avoid rework in * every driver. Also dummy prcm reset function is added */ -/* Dummy hooks only for OMAP4.For rest OMAPs, common clkdev is used */ -#if defined(CONFIG_ARCH_OMAP4) -struct clk *clk_get(struct device *dev, const char *id) -{ - return NULL; -} -EXPORT_SYMBOL(clk_get); - -void clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_put); - -void omap2_clk_prepare_for_reboot(void) -{ -} -EXPORT_SYMBOL(omap2_clk_prepare_for_reboot); - -void omap_prcm_arch_reset(char mode) -{ -} -EXPORT_SYMBOL(omap_prcm_arch_reset); -#endif int clk_enable(struct clk *clk) { unsigned long flags; int ret = 0; - if (cpu_is_omap44xx()) - /* OMAP4 clk framework not supported yet */ - return 0; if (clk == NULL || IS_ERR(clk)) return -EINVAL; diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index cc050b3313bd0126c4b352a249bb159beb13acbb..bf1eaf3a27d452e915a83fb381ccc54490a4a88b 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -280,16 +280,18 @@ void __init omap2_set_globals_343x(void) #if defined(CONFIG_ARCH_OMAP4) static struct omap_globals omap4_globals = { .class = OMAP443X_CLASS, - .tap = OMAP2_L4_IO_ADDRESS(0x4830a000), + .tap = OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE), .ctrl = OMAP2_L4_IO_ADDRESS(OMAP443X_CTRL_BASE), .prm = OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE), .cm = OMAP2_L4_IO_ADDRESS(OMAP4430_CM_BASE), + .cm2 = OMAP2_L4_IO_ADDRESS(OMAP4430_CM2_BASE), }; void __init omap2_set_globals_443x(void) { omap2_set_globals_tap(&omap4_globals); omap2_set_globals_control(&omap4_globals); + omap2_set_globals_prcm(&omap4_globals); } #endif diff --git a/arch/arm/plat-omap/debug-devices.c b/arch/arm/plat-omap/debug-devices.c index 09c1107637f613d641ae42724c613f37d80ac5fa..923c9621096b85f63e6e8c6ba2fa9909b3c06311 100644 --- a/arch/arm/plat-omap/debug-devices.c +++ b/arch/arm/plat-omap/debug-devices.c @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -24,6 +25,12 @@ * platforms include H2, H3, H4, and Perseus2. */ +static struct smc91x_platdata smc91x_info = { + .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, + .leda = RPC_LED_100_10, + .ledb = RPC_LED_TX_RX, +}; + static struct resource smc91x_resources[] = { [0] = { .flags = IORESOURCE_MEM, @@ -36,6 +43,9 @@ static struct resource smc91x_resources[] = { static struct platform_device smc91x_device = { .name = "smc91x", .id = -1, + .dev = { + .platform_data = &smc91x_info, + }, .num_resources = ARRAY_SIZE(smc91x_resources), .resource = smc91x_resources, }; diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index f86617869b3899c3292bc63fe227e18f0c2a5e9c..30b5db73017a0e345178deb19cd3fe156a546101 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -242,6 +242,39 @@ fail: /*-------------------------------------------------------------------------*/ +#if defined(CONFIG_HW_RANDOM_OMAP) || defined(CONFIG_HW_RANDOM_OMAP_MODULE) + +#ifdef CONFIG_ARCH_OMAP24XX +#define OMAP_RNG_BASE 0x480A0000 +#else +#define OMAP_RNG_BASE 0xfffe5000 +#endif + +static struct resource rng_resources[] = { + { + .start = OMAP_RNG_BASE, + .end = OMAP_RNG_BASE + 0x4f, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device omap_rng_device = { + .name = "omap_rng", + .id = -1, + .num_resources = ARRAY_SIZE(rng_resources), + .resource = rng_resources, +}; + +static void omap_init_rng(void) +{ + (void) platform_device_register(&omap_rng_device); +} +#else +static inline void omap_init_rng(void) {} +#endif + +/*-------------------------------------------------------------------------*/ + /* Numbering for the SPI-capable controllers when used for SPI: * spi = 1 * uwire = 2 @@ -324,39 +357,6 @@ static void omap_init_wdt(void) static inline void omap_init_wdt(void) {} #endif -/*-------------------------------------------------------------------------*/ - -#if defined(CONFIG_HW_RANDOM_OMAP) || defined(CONFIG_HW_RANDOM_OMAP_MODULE) - -#ifdef CONFIG_ARCH_OMAP24XX -#define OMAP_RNG_BASE 0x480A0000 -#else -#define OMAP_RNG_BASE 0xfffe5000 -#endif - -static struct resource rng_resources[] = { - { - .start = OMAP_RNG_BASE, - .end = OMAP_RNG_BASE + 0x4f, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device omap_rng_device = { - .name = "omap_rng", - .id = -1, - .num_resources = ARRAY_SIZE(rng_resources), - .resource = rng_resources, -}; - -static void omap_init_rng(void) -{ - (void) platform_device_register(&omap_rng_device); -} -#else -static inline void omap_init_rng(void) {} -#endif - /* * This gets called after board-specific INIT_MACHINE, and initializes most * on-chip peripherals accessible on this board (except for few like USB): @@ -384,9 +384,9 @@ static int __init omap_init_devices(void) */ omap_init_dsp(); omap_init_kp(); + omap_init_rng(); omap_init_uwire(); omap_init_wdt(); - omap_init_rng(); return 0; } arch_initcall(omap_init_devices); diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index d17375e06a1e8f956a674b57c2659e991cb5ebaf..09d82b3c66ce3f2331e9581dadea3f804bf075fd 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -47,7 +47,6 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED }; #endif #define OMAP_DMA_ACTIVE 0x01 -#define OMAP_DMA_CCR_EN (1 << 7) #define OMAP2_DMA_CSR_CLEAR_MASK 0xffe #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec) @@ -1120,17 +1119,8 @@ int omap_dma_running(void) { int lch; - /* - * On OMAP1510, internal LCD controller will start the transfer - * when it gets enabled, so assume DMA running if LCD enabled. - */ - if (cpu_is_omap1510()) - if (omap_readw(0xfffec000 + 0x00) & (1 << 0)) - return 1; - - /* Check if LCD DMA is running */ - if (cpu_is_omap16xx()) - if (omap_readw(OMAP1610_DMA_LCD_CCR) & OMAP_DMA_CCR_EN) + if (cpu_class_is_omap1()) + if (omap_lcd_dma_running()) return 1; for (lch = 0; lch < dma_chan_count; lch++) @@ -1990,377 +1980,6 @@ static struct irqaction omap24xx_dma_irq; /*----------------------------------------------------------------------------*/ -static struct lcd_dma_info { - spinlock_t lock; - int reserved; - void (*callback)(u16 status, void *data); - void *cb_data; - - int active; - unsigned long addr, size; - int rotate, data_type, xres, yres; - int vxres; - int mirror; - int xscale, yscale; - int ext_ctrl; - int src_port; - int single_transfer; -} lcd_dma; - -void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres, - int data_type) -{ - lcd_dma.addr = addr; - lcd_dma.data_type = data_type; - lcd_dma.xres = fb_xres; - lcd_dma.yres = fb_yres; -} -EXPORT_SYMBOL(omap_set_lcd_dma_b1); - -void omap_set_lcd_dma_src_port(int port) -{ - lcd_dma.src_port = port; -} - -void omap_set_lcd_dma_ext_controller(int external) -{ - lcd_dma.ext_ctrl = external; -} -EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller); - -void omap_set_lcd_dma_single_transfer(int single) -{ - lcd_dma.single_transfer = single; -} -EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer); - -void omap_set_lcd_dma_b1_rotation(int rotate) -{ - if (omap_dma_in_1510_mode()) { - printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n"); - BUG(); - return; - } - lcd_dma.rotate = rotate; -} -EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation); - -void omap_set_lcd_dma_b1_mirror(int mirror) -{ - if (omap_dma_in_1510_mode()) { - printk(KERN_ERR "DMA mirror is not supported in 1510 mode\n"); - BUG(); - } - lcd_dma.mirror = mirror; -} -EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror); - -void omap_set_lcd_dma_b1_vxres(unsigned long vxres) -{ - if (omap_dma_in_1510_mode()) { - printk(KERN_ERR "DMA virtual resulotion is not supported " - "in 1510 mode\n"); - BUG(); - } - lcd_dma.vxres = vxres; -} -EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres); - -void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale) -{ - if (omap_dma_in_1510_mode()) { - printk(KERN_ERR "DMA scale is not supported in 1510 mode\n"); - BUG(); - } - lcd_dma.xscale = xscale; - lcd_dma.yscale = yscale; -} -EXPORT_SYMBOL(omap_set_lcd_dma_b1_scale); - -static void set_b1_regs(void) -{ - unsigned long top, bottom; - int es; - u16 w; - unsigned long en, fn; - long ei, fi; - unsigned long vxres; - unsigned int xscale, yscale; - - switch (lcd_dma.data_type) { - case OMAP_DMA_DATA_TYPE_S8: - es = 1; - break; - case OMAP_DMA_DATA_TYPE_S16: - es = 2; - break; - case OMAP_DMA_DATA_TYPE_S32: - es = 4; - break; - default: - BUG(); - return; - } - - vxres = lcd_dma.vxres ? lcd_dma.vxres : lcd_dma.xres; - xscale = lcd_dma.xscale ? lcd_dma.xscale : 1; - yscale = lcd_dma.yscale ? lcd_dma.yscale : 1; - BUG_ON(vxres < lcd_dma.xres); - -#define PIXADDR(x, y) (lcd_dma.addr + \ - ((y) * vxres * yscale + (x) * xscale) * es) -#define PIXSTEP(sx, sy, dx, dy) (PIXADDR(dx, dy) - PIXADDR(sx, sy) - es + 1) - - switch (lcd_dma.rotate) { - case 0: - if (!lcd_dma.mirror) { - top = PIXADDR(0, 0); - bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); - /* 1510 DMA requires the bottom address to be 2 more - * than the actual last memory access location. */ - if (omap_dma_in_1510_mode() && - lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32) - bottom += 2; - ei = PIXSTEP(0, 0, 1, 0); - fi = PIXSTEP(lcd_dma.xres - 1, 0, 0, 1); - } else { - top = PIXADDR(lcd_dma.xres - 1, 0); - bottom = PIXADDR(0, lcd_dma.yres - 1); - ei = PIXSTEP(1, 0, 0, 0); - fi = PIXSTEP(0, 0, lcd_dma.xres - 1, 1); - } - en = lcd_dma.xres; - fn = lcd_dma.yres; - break; - case 90: - if (!lcd_dma.mirror) { - top = PIXADDR(0, lcd_dma.yres - 1); - bottom = PIXADDR(lcd_dma.xres - 1, 0); - ei = PIXSTEP(0, 1, 0, 0); - fi = PIXSTEP(0, 0, 1, lcd_dma.yres - 1); - } else { - top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); - bottom = PIXADDR(0, 0); - ei = PIXSTEP(0, 1, 0, 0); - fi = PIXSTEP(1, 0, 0, lcd_dma.yres - 1); - } - en = lcd_dma.yres; - fn = lcd_dma.xres; - break; - case 180: - if (!lcd_dma.mirror) { - top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); - bottom = PIXADDR(0, 0); - ei = PIXSTEP(1, 0, 0, 0); - fi = PIXSTEP(0, 1, lcd_dma.xres - 1, 0); - } else { - top = PIXADDR(0, lcd_dma.yres - 1); - bottom = PIXADDR(lcd_dma.xres - 1, 0); - ei = PIXSTEP(0, 0, 1, 0); - fi = PIXSTEP(lcd_dma.xres - 1, 1, 0, 0); - } - en = lcd_dma.xres; - fn = lcd_dma.yres; - break; - case 270: - if (!lcd_dma.mirror) { - top = PIXADDR(lcd_dma.xres - 1, 0); - bottom = PIXADDR(0, lcd_dma.yres - 1); - ei = PIXSTEP(0, 0, 0, 1); - fi = PIXSTEP(1, lcd_dma.yres - 1, 0, 0); - } else { - top = PIXADDR(0, 0); - bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); - ei = PIXSTEP(0, 0, 0, 1); - fi = PIXSTEP(0, lcd_dma.yres - 1, 1, 0); - } - en = lcd_dma.yres; - fn = lcd_dma.xres; - break; - default: - BUG(); - return; /* Suppress warning about uninitialized vars */ - } - - if (omap_dma_in_1510_mode()) { - omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U); - omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L); - omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U); - omap_writew(bottom, OMAP1510_DMA_LCD_BOT_F1_L); - - return; - } - - /* 1610 regs */ - omap_writew(top >> 16, OMAP1610_DMA_LCD_TOP_B1_U); - omap_writew(top, OMAP1610_DMA_LCD_TOP_B1_L); - omap_writew(bottom >> 16, OMAP1610_DMA_LCD_BOT_B1_U); - omap_writew(bottom, OMAP1610_DMA_LCD_BOT_B1_L); - - omap_writew(en, OMAP1610_DMA_LCD_SRC_EN_B1); - omap_writew(fn, OMAP1610_DMA_LCD_SRC_FN_B1); - - w = omap_readw(OMAP1610_DMA_LCD_CSDP); - w &= ~0x03; - w |= lcd_dma.data_type; - omap_writew(w, OMAP1610_DMA_LCD_CSDP); - - w = omap_readw(OMAP1610_DMA_LCD_CTRL); - /* Always set the source port as SDRAM for now*/ - w &= ~(0x03 << 6); - if (lcd_dma.callback != NULL) - w |= 1 << 1; /* Block interrupt enable */ - else - w &= ~(1 << 1); - omap_writew(w, OMAP1610_DMA_LCD_CTRL); - - if (!(lcd_dma.rotate || lcd_dma.mirror || - lcd_dma.vxres || lcd_dma.xscale || lcd_dma.yscale)) - return; - - w = omap_readw(OMAP1610_DMA_LCD_CCR); - /* Set the double-indexed addressing mode */ - w |= (0x03 << 12); - omap_writew(w, OMAP1610_DMA_LCD_CCR); - - omap_writew(ei, OMAP1610_DMA_LCD_SRC_EI_B1); - omap_writew(fi >> 16, OMAP1610_DMA_LCD_SRC_FI_B1_U); - omap_writew(fi, OMAP1610_DMA_LCD_SRC_FI_B1_L); -} - -static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id) -{ - u16 w; - - w = omap_readw(OMAP1610_DMA_LCD_CTRL); - if (unlikely(!(w & (1 << 3)))) { - printk(KERN_WARNING "Spurious LCD DMA IRQ\n"); - return IRQ_NONE; - } - /* Ack the IRQ */ - w |= (1 << 3); - omap_writew(w, OMAP1610_DMA_LCD_CTRL); - lcd_dma.active = 0; - if (lcd_dma.callback != NULL) - lcd_dma.callback(w, lcd_dma.cb_data); - - return IRQ_HANDLED; -} - -int omap_request_lcd_dma(void (*callback)(u16 status, void *data), - void *data) -{ - spin_lock_irq(&lcd_dma.lock); - if (lcd_dma.reserved) { - spin_unlock_irq(&lcd_dma.lock); - printk(KERN_ERR "LCD DMA channel already reserved\n"); - BUG(); - return -EBUSY; - } - lcd_dma.reserved = 1; - spin_unlock_irq(&lcd_dma.lock); - lcd_dma.callback = callback; - lcd_dma.cb_data = data; - lcd_dma.active = 0; - lcd_dma.single_transfer = 0; - lcd_dma.rotate = 0; - lcd_dma.vxres = 0; - lcd_dma.mirror = 0; - lcd_dma.xscale = 0; - lcd_dma.yscale = 0; - lcd_dma.ext_ctrl = 0; - lcd_dma.src_port = 0; - - return 0; -} -EXPORT_SYMBOL(omap_request_lcd_dma); - -void omap_free_lcd_dma(void) -{ - spin_lock(&lcd_dma.lock); - if (!lcd_dma.reserved) { - spin_unlock(&lcd_dma.lock); - printk(KERN_ERR "LCD DMA is not reserved\n"); - BUG(); - return; - } - if (!enable_1510_mode) - omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1, - OMAP1610_DMA_LCD_CCR); - lcd_dma.reserved = 0; - spin_unlock(&lcd_dma.lock); -} -EXPORT_SYMBOL(omap_free_lcd_dma); - -void omap_enable_lcd_dma(void) -{ - u16 w; - - /* - * Set the Enable bit only if an external controller is - * connected. Otherwise the OMAP internal controller will - * start the transfer when it gets enabled. - */ - if (enable_1510_mode || !lcd_dma.ext_ctrl) - return; - - w = omap_readw(OMAP1610_DMA_LCD_CTRL); - w |= 1 << 8; - omap_writew(w, OMAP1610_DMA_LCD_CTRL); - - lcd_dma.active = 1; - - w = omap_readw(OMAP1610_DMA_LCD_CCR); - w |= 1 << 7; - omap_writew(w, OMAP1610_DMA_LCD_CCR); -} -EXPORT_SYMBOL(omap_enable_lcd_dma); - -void omap_setup_lcd_dma(void) -{ - BUG_ON(lcd_dma.active); - if (!enable_1510_mode) { - /* Set some reasonable defaults */ - omap_writew(0x5440, OMAP1610_DMA_LCD_CCR); - omap_writew(0x9102, OMAP1610_DMA_LCD_CSDP); - omap_writew(0x0004, OMAP1610_DMA_LCD_LCH_CTRL); - } - set_b1_regs(); - if (!enable_1510_mode) { - u16 w; - - w = omap_readw(OMAP1610_DMA_LCD_CCR); - /* - * If DMA was already active set the end_prog bit to have - * the programmed register set loaded into the active - * register set. - */ - w |= 1 << 11; /* End_prog */ - if (!lcd_dma.single_transfer) - w |= (3 << 8); /* Auto_init, repeat */ - omap_writew(w, OMAP1610_DMA_LCD_CCR); - } -} -EXPORT_SYMBOL(omap_setup_lcd_dma); - -void omap_stop_lcd_dma(void) -{ - u16 w; - - lcd_dma.active = 0; - if (enable_1510_mode || !lcd_dma.ext_ctrl) - return; - - w = omap_readw(OMAP1610_DMA_LCD_CCR); - w &= ~(1 << 7); - omap_writew(w, OMAP1610_DMA_LCD_CCR); - - w = omap_readw(OMAP1610_DMA_LCD_CTRL); - w &= ~(1 << 8); - omap_writew(w, OMAP1610_DMA_LCD_CTRL); -} -EXPORT_SYMBOL(omap_stop_lcd_dma); - void omap_dma_global_context_save(void) { omap_dma_global_context.dma_irqenable_l0 = @@ -2465,14 +2084,6 @@ static int __init omap_init_dma(void) dma_chan_count = 16; } else dma_chan_count = 9; - if (cpu_is_omap16xx()) { - u16 w; - - /* this would prevent OMAP sleep */ - w = omap_readw(OMAP1610_DMA_LCD_CTRL); - w &= ~(1 << 8); - omap_writew(w, OMAP1610_DMA_LCD_CTRL); - } } else if (cpu_class_is_omap2()) { u8 revision = dma_read(REVISION) & 0xff; printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", @@ -2483,7 +2094,6 @@ static int __init omap_init_dma(void) return 0; } - spin_lock_init(&lcd_dma.lock); spin_lock_init(&dma_chan_lock); for (ch = 0; ch < dma_chan_count; ch++) { @@ -2548,22 +2158,6 @@ static int __init omap_init_dma(void) } } - - /* FIXME: Update LCD DMA to work on 24xx */ - if (cpu_class_is_omap1()) { - r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0, - "LCD DMA", NULL); - if (r != 0) { - int i; - - printk(KERN_ERR "unable to request IRQ for LCD DMA " - "(error %d)\n", r); - for (i = 0; i < dma_chan_count; i++) - free_irq(omap1_dma_irq[i], (void *) (i + 1)); - goto out_free; - } - } - return 0; out_free: diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c index 78a4ce538dbd9f1e1732daa49910ed2b99ad7280..d3eea4f47533050618ce2a0e489a79f5f2725088 100644 --- a/arch/arm/plat-omap/fb.c +++ b/arch/arm/plat-omap/fb.c @@ -28,13 +28,13 @@ #include #include #include +#include #include #include #include #include -#include #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) @@ -55,6 +55,10 @@ static struct platform_device omap_fb_device = { .num_resources = 0, }; +void omapfb_set_platform_data(struct omapfb_platform_data *data) +{ +} + static inline int ranges_overlap(unsigned long start1, unsigned long size1, unsigned long start2, unsigned long size2) { @@ -327,7 +331,33 @@ static inline int omap_init_fb(void) arch_initcall(omap_init_fb); -#else +#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) + +static u64 omap_fb_dma_mask = ~(u32)0; +static struct omapfb_platform_data omapfb_config; + +static struct platform_device omap_fb_device = { + .name = "omapfb", + .id = -1, + .dev = { + .dma_mask = &omap_fb_dma_mask, + .coherent_dma_mask = ~(u32)0, + .platform_data = &omapfb_config, + }, + .num_resources = 0, +}; + +void omapfb_set_platform_data(struct omapfb_platform_data *data) +{ + omapfb_config = *data; +} + +static inline int omap_init_fb(void) +{ + return platform_device_register(&omap_fb_device); +} + +arch_initcall(omap_init_fb); void omapfb_reserve_sdram(void) {} unsigned long omapfb_reserve_sram(unsigned long sram_pstart, @@ -339,5 +369,20 @@ unsigned long omapfb_reserve_sram(unsigned long sram_pstart, return 0; } +#else + +void omapfb_set_platform_data(struct omapfb_platform_data *data) +{ +} + +void omapfb_reserve_sdram(void) {} +unsigned long omapfb_reserve_sram(unsigned long sram_pstart, + unsigned long sram_vstart, + unsigned long sram_size, + unsigned long start_avail, + unsigned long size_avail) +{ + return 0; +} #endif diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index c08362dbb8ed34367ea6d8ca3ebc10c5c5f60928..33fff4ef382dde539011389935631d80406e3022 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -80,47 +80,8 @@ static struct platform_device omap_i2c_devices[] = { #endif }; -#if defined(CONFIG_ARCH_OMAP24XX) -static const int omap24xx_pins[][2] = { - { M19_24XX_I2C1_SCL, L15_24XX_I2C1_SDA }, - { J15_24XX_I2C2_SCL, H19_24XX_I2C2_SDA }, -}; -#else -static const int omap24xx_pins[][2] = {}; -#endif -#if defined(CONFIG_ARCH_OMAP34XX) -static const int omap34xx_pins[][2] = { - { K21_34XX_I2C1_SCL, J21_34XX_I2C1_SDA}, - { AF15_34XX_I2C2_SCL, AE15_34XX_I2C2_SDA}, - { AF14_34XX_I2C3_SCL, AG14_34XX_I2C3_SDA}, -}; -#else -static const int omap34xx_pins[][2] = {}; -#endif - #define OMAP_I2C_CMDLINE_SETUP (BIT(31)) -static void __init omap_i2c_mux_pins(int bus) -{ - int scl, sda; - - if (cpu_class_is_omap1()) { - scl = I2C_SCL; - sda = I2C_SDA; - } else if (cpu_is_omap24xx()) { - scl = omap24xx_pins[bus][0]; - sda = omap24xx_pins[bus][1]; - } else if (cpu_is_omap34xx()) { - scl = omap34xx_pins[bus][0]; - sda = omap34xx_pins[bus][1]; - } else { - return; - } - - omap_cfg_reg(sda); - omap_cfg_reg(scl); -} - static int __init omap_i2c_nr_ports(void) { int ports = 0; @@ -156,7 +117,6 @@ static int __init omap_i2c_add_bus(int bus_id) res[1].start = irq; } - omap_i2c_mux_pins(bus_id - 1); return platform_device_register(pdev); } @@ -209,7 +169,7 @@ out: subsys_initcall(omap_register_i2c_bus_cmdline); /** - * omap_register_i2c_bus - register I2C bus with device descriptors + * omap_plat_register_i2c_bus - register I2C bus with device descriptors * @bus_id: bus id counting from number 1 * @clkrate: clock rate of the bus in kHz * @info: pointer into I2C device descriptor table or NULL @@ -217,7 +177,7 @@ subsys_initcall(omap_register_i2c_bus_cmdline); * * Returns 0 on success or an error code. */ -int __init omap_register_i2c_bus(int bus_id, u32 clkrate, +int __init omap_plat_register_i2c_bus(int bus_id, u32 clkrate, struct i2c_board_info const *info, unsigned len) { diff --git a/arch/arm/plat-omap/include/plat/board.h b/arch/arm/plat-omap/include/plat/board.h index abb17b604f821238e4d6de00a3a8d5389eeb4b59..376ce18216ff8ee4ac613b9e2dff5bf285995bc6 100644 --- a/arch/arm/plat-omap/include/plat/board.h +++ b/arch/arm/plat-omap/include/plat/board.h @@ -114,15 +114,6 @@ struct omap_pwm_led_platform_data { void (*set_power)(struct omap_pwm_led_platform_data *self, int on_off); }; -/* See arch/arm/plat-omap/include/mach/gpio-switch.h for definitions */ -struct omap_gpio_switch_config { - char name[12]; - u16 gpio; - int flags:4; - int type:4; - int key_code:24; /* Linux key code */ -}; - struct omap_uart_config { /* Bit field of UARTs present; bit 0 --> UART1 */ unsigned int enabled_uarts; diff --git a/arch/arm/plat-omap/include/plat/clkdev_omap.h b/arch/arm/plat-omap/include/plat/clkdev_omap.h new file mode 100644 index 0000000000000000000000000000000000000000..35b36caf5f9151faa054219215ecc83e828f6084 --- /dev/null +++ b/arch/arm/plat-omap/include/plat/clkdev_omap.h @@ -0,0 +1,41 @@ +/* + * clkdev <-> OMAP integration + * + * Russell King + * + */ + +#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H + +#include + +struct omap_clk { + u16 cpu; + struct clk_lookup lk; +}; + +#define CLK(dev, con, ck, cp) \ + { \ + .cpu = cp, \ + .lk = { \ + .dev_id = dev, \ + .con_id = con, \ + .clk = ck, \ + }, \ + } + + +#define CK_310 (1 << 0) +#define CK_7XX (1 << 1) +#define CK_1510 (1 << 2) +#define CK_16XX (1 << 3) +#define CK_243X (1 << 4) +#define CK_242X (1 << 5) +#define CK_343X (1 << 6) +#define CK_3430ES1 (1 << 7) +#define CK_3430ES2 (1 << 8) +#define CK_443X (1 << 9) + +#endif + diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h index 4b8b0d65cbf20c10dfcc0b0795ed16b3bf054de9..309b6d1dccdba8670ae0b63a8de4b13d7ea92053 100644 --- a/arch/arm/plat-omap/include/plat/clock.h +++ b/arch/arm/plat-omap/include/plat/clock.h @@ -13,6 +13,8 @@ #ifndef __ARCH_ARM_OMAP_CLOCK_H #define __ARCH_ARM_OMAP_CLOCK_H +#include + struct module; struct clk; struct clockdomain; @@ -148,6 +150,8 @@ extern const struct clkops clkops_null; #define CONFIG_PARTICIPANT (1 << 10) /* Fundamental clock */ #define ENABLE_ON_INIT (1 << 11) /* Enable upon framework init */ #define INVERT_ENABLE (1 << 12) /* 0 enables, 1 disables */ +#define CLOCK_IN_OMAP4430 (1 << 13) +#define ALWAYS_ENABLED (1 << 14) /* bits 13-31 are currently free */ /* Clksel_rate flags */ @@ -156,6 +160,7 @@ extern const struct clkops clkops_null; #define RATE_IN_243X (1 << 2) #define RATE_IN_343X (1 << 3) /* rates common to all 343X */ #define RATE_IN_3430ES2 (1 << 4) /* 3430ES2 rates only */ +#define RATE_IN_4430 (1 << 5) #define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X) diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h index 064f1730f43bb7c3a03088e2d557c48f10c1ae77..32c22272425d7582a285872d5a5f2cd0b36e7841 100644 --- a/arch/arm/plat-omap/include/plat/common.h +++ b/arch/arm/plat-omap/include/plat/common.h @@ -27,7 +27,7 @@ #ifndef __ARCH_ARM_MACH_OMAP_COMMON_H #define __ARCH_ARM_MACH_OMAP_COMMON_H -#include +#include struct sys_timer; @@ -36,18 +36,6 @@ extern void __iomem *gic_cpu_base_addr; extern void omap_map_common_io(void); extern struct sys_timer omap_timer; -#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) -extern int omap_register_i2c_bus(int bus_id, u32 clkrate, - struct i2c_board_info const *info, - unsigned len); -#else -static inline int omap_register_i2c_bus(int bus_id, u32 clkrate, - struct i2c_board_info const *info, - unsigned len) -{ - return 0; -} -#endif /* IO bases for various OMAP processors */ struct omap_globals { @@ -58,6 +46,7 @@ struct omap_globals { void __iomem *ctrl; /* System Control Module */ void __iomem *prm; /* Power and Reset Management */ void __iomem *cm; /* Clock Management */ + void __iomem *cm2; }; void omap2_set_globals_242x(void); @@ -71,4 +60,24 @@ void omap2_set_globals_sdrc(struct omap_globals *); void omap2_set_globals_control(struct omap_globals *); void omap2_set_globals_prcm(struct omap_globals *); +/** + * omap_test_timeout - busy-loop, testing a condition + * @cond: condition to test until it evaluates to true + * @timeout: maximum number of microseconds in the timeout + * @index: loop index (integer) + * + * Loop waiting for @cond to become true or until at least @timeout + * microseconds have passed. To use, define some integer @index in the + * calling code. After running, if @index == @timeout, then the loop has + * timed out. + */ +#define omap_test_timeout(cond, timeout, index) \ +({ \ + for (index = 0; index < timeout; index++) { \ + if (cond) \ + break; \ + udelay(1); \ + } \ +}) + #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */ diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h index 2e1789001dfe9a2807aebfd6b0b2e9377e153438..9a028bdebb06797166f2a3fff44e0aacd685740b 100644 --- a/arch/arm/plat-omap/include/plat/cpu.h +++ b/arch/arm/plat-omap/include/plat/cpu.h @@ -176,11 +176,13 @@ IS_OMAP_CLASS(15xx, 0x15) IS_OMAP_CLASS(16xx, 0x16) IS_OMAP_CLASS(24xx, 0x24) IS_OMAP_CLASS(34xx, 0x34) +IS_OMAP_CLASS(44xx, 0x44) IS_OMAP_SUBCLASS(242x, 0x242) IS_OMAP_SUBCLASS(243x, 0x243) IS_OMAP_SUBCLASS(343x, 0x343) IS_OMAP_SUBCLASS(363x, 0x363) +IS_OMAP_SUBCLASS(443x, 0x443) #define cpu_is_omap7xx() 0 #define cpu_is_omap15xx() 0 @@ -393,11 +395,11 @@ IS_OMAP_TYPE(3517, 0x3517) (!omap3_has_iva()) && \ (!omap3_has_sgx())) # define cpu_is_omap3515() (cpu_is_omap3430() && \ - (omap3_has_iva()) && \ - (!omap3_has_sgx())) + (!omap3_has_iva()) && \ + (omap3_has_sgx())) # define cpu_is_omap3525() (cpu_is_omap3430() && \ - (omap3_has_sgx()) && \ - (!omap3_has_iva())) + (!omap3_has_sgx()) && \ + (omap3_has_iva())) # define cpu_is_omap3530() (cpu_is_omap3430()) # define cpu_is_omap3505() is_omap3505() # define cpu_is_omap3517() is_omap3517() @@ -408,8 +410,8 @@ IS_OMAP_TYPE(3517, 0x3517) # if defined(CONFIG_ARCH_OMAP4) # undef cpu_is_omap44xx # undef cpu_is_omap443x -# define cpu_is_omap44xx() 1 -# define cpu_is_omap443x() 1 +# define cpu_is_omap44xx() is_omap44xx() +# define cpu_is_omap443x() is_omap443x() # endif /* Macros to detect if we have OMAP1 or OMAP2 */ @@ -436,14 +438,15 @@ IS_OMAP_TYPE(3517, 0x3517) #define OMAP3630_REV_ES1_0 0x36300034 #define OMAP35XX_CLASS 0x35000034 -#define OMAP3503_REV(v) (OMAP35XX_CLASS | (0x3503 << 16) | (v << 12)) -#define OMAP3515_REV(v) (OMAP35XX_CLASS | (0x3515 << 16) | (v << 12)) -#define OMAP3525_REV(v) (OMAP35XX_CLASS | (0x3525 << 16) | (v << 12)) -#define OMAP3530_REV(v) (OMAP35XX_CLASS | (0x3530 << 16) | (v << 12)) -#define OMAP3505_REV(v) (OMAP35XX_CLASS | (0x3505 << 16) | (v << 12)) -#define OMAP3517_REV(v) (OMAP35XX_CLASS | (0x3517 << 16) | (v << 12)) - -#define OMAP443X_CLASS 0x44300034 +#define OMAP3503_REV(v) (OMAP35XX_CLASS | (0x3503 << 16) | (v << 8)) +#define OMAP3515_REV(v) (OMAP35XX_CLASS | (0x3515 << 16) | (v << 8)) +#define OMAP3525_REV(v) (OMAP35XX_CLASS | (0x3525 << 16) | (v << 8)) +#define OMAP3530_REV(v) (OMAP35XX_CLASS | (0x3530 << 16) | (v << 8)) +#define OMAP3505_REV(v) (OMAP35XX_CLASS | (0x3505 << 16) | (v << 8)) +#define OMAP3517_REV(v) (OMAP35XX_CLASS | (0x3517 << 16) | (v << 8)) + +#define OMAP443X_CLASS 0x44300044 +#define OMAP4430_REV_ES1_0 0x44300044 /* * omap_chip bits diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h new file mode 100644 index 0000000000000000000000000000000000000000..c66e464732df1e33c24d068c3b7c4eca40760306 --- /dev/null +++ b/arch/arm/plat-omap/include/plat/display.h @@ -0,0 +1,575 @@ +/* + * linux/include/asm-arm/arch-omap/display.h + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen + * + * 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, see . + */ + +#ifndef __ASM_ARCH_OMAP_DISPLAY_H +#define __ASM_ARCH_OMAP_DISPLAY_H + +#include +#include +#include +#include + +#define DISPC_IRQ_FRAMEDONE (1 << 0) +#define DISPC_IRQ_VSYNC (1 << 1) +#define DISPC_IRQ_EVSYNC_EVEN (1 << 2) +#define DISPC_IRQ_EVSYNC_ODD (1 << 3) +#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4) +#define DISPC_IRQ_PROG_LINE_NUM (1 << 5) +#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6) +#define DISPC_IRQ_GFX_END_WIN (1 << 7) +#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8) +#define DISPC_IRQ_OCP_ERR (1 << 9) +#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10) +#define DISPC_IRQ_VID1_END_WIN (1 << 11) +#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12) +#define DISPC_IRQ_VID2_END_WIN (1 << 13) +#define DISPC_IRQ_SYNC_LOST (1 << 14) +#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15) +#define DISPC_IRQ_WAKEUP (1 << 16) + +struct omap_dss_device; +struct omap_overlay_manager; + +enum omap_display_type { + OMAP_DISPLAY_TYPE_NONE = 0, + OMAP_DISPLAY_TYPE_DPI = 1 << 0, + OMAP_DISPLAY_TYPE_DBI = 1 << 1, + OMAP_DISPLAY_TYPE_SDI = 1 << 2, + OMAP_DISPLAY_TYPE_DSI = 1 << 3, + OMAP_DISPLAY_TYPE_VENC = 1 << 4, +}; + +enum omap_plane { + OMAP_DSS_GFX = 0, + OMAP_DSS_VIDEO1 = 1, + OMAP_DSS_VIDEO2 = 2 +}; + +enum omap_channel { + OMAP_DSS_CHANNEL_LCD = 0, + OMAP_DSS_CHANNEL_DIGIT = 1, +}; + +enum omap_color_mode { + OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */ + OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */ + OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */ + OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */ + OMAP_DSS_COLOR_RGB12U = 1 << 4, /* RGB12, 16-bit container */ + OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16 */ + OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16 */ + OMAP_DSS_COLOR_RGB24U = 1 << 7, /* RGB24, 32-bit container */ + OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24, 24-bit container */ + OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */ + OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */ + OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */ + OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */ + OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */ + + OMAP_DSS_COLOR_GFX_OMAP2 = + OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | + OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 | + OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 | + OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P, + + OMAP_DSS_COLOR_VID_OMAP2 = + OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | + OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 | + OMAP_DSS_COLOR_UYVY, + + OMAP_DSS_COLOR_GFX_OMAP3 = + OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | + OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 | + OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 | + OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | + OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 | + OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, + + OMAP_DSS_COLOR_VID1_OMAP3 = + OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 | + OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P | + OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY, + + OMAP_DSS_COLOR_VID2_OMAP3 = + OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 | + OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | + OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 | + OMAP_DSS_COLOR_UYVY | OMAP_DSS_COLOR_ARGB32 | + OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, +}; + +enum omap_lcd_display_type { + OMAP_DSS_LCD_DISPLAY_STN, + OMAP_DSS_LCD_DISPLAY_TFT, +}; + +enum omap_dss_load_mode { + OMAP_DSS_LOAD_CLUT_AND_FRAME = 0, + OMAP_DSS_LOAD_CLUT_ONLY = 1, + OMAP_DSS_LOAD_FRAME_ONLY = 2, + OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3, +}; + +enum omap_dss_trans_key_type { + OMAP_DSS_COLOR_KEY_GFX_DST = 0, + OMAP_DSS_COLOR_KEY_VID_SRC = 1, +}; + +enum omap_rfbi_te_mode { + OMAP_DSS_RFBI_TE_MODE_1 = 1, + OMAP_DSS_RFBI_TE_MODE_2 = 2, +}; + +enum omap_panel_config { + OMAP_DSS_LCD_IVS = 1<<0, + OMAP_DSS_LCD_IHS = 1<<1, + OMAP_DSS_LCD_IPC = 1<<2, + OMAP_DSS_LCD_IEO = 1<<3, + OMAP_DSS_LCD_RF = 1<<4, + OMAP_DSS_LCD_ONOFF = 1<<5, + + OMAP_DSS_LCD_TFT = 1<<20, +}; + +enum omap_dss_venc_type { + OMAP_DSS_VENC_TYPE_COMPOSITE, + OMAP_DSS_VENC_TYPE_SVIDEO, +}; + +enum omap_display_caps { + OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0, + OMAP_DSS_DISPLAY_CAP_TEAR_ELIM = 1 << 1, +}; + +enum omap_dss_update_mode { + OMAP_DSS_UPDATE_DISABLED = 0, + OMAP_DSS_UPDATE_AUTO, + OMAP_DSS_UPDATE_MANUAL, +}; + +enum omap_dss_display_state { + OMAP_DSS_DISPLAY_DISABLED = 0, + OMAP_DSS_DISPLAY_ACTIVE, + OMAP_DSS_DISPLAY_SUSPENDED, +}; + +/* XXX perhaps this should be removed */ +enum omap_dss_overlay_managers { + OMAP_DSS_OVL_MGR_LCD, + OMAP_DSS_OVL_MGR_TV, +}; + +enum omap_dss_rotation_type { + OMAP_DSS_ROT_DMA = 0, + OMAP_DSS_ROT_VRFB = 1, +}; + +/* clockwise rotation angle */ +enum omap_dss_rotation_angle { + OMAP_DSS_ROT_0 = 0, + OMAP_DSS_ROT_90 = 1, + OMAP_DSS_ROT_180 = 2, + OMAP_DSS_ROT_270 = 3, +}; + +enum omap_overlay_caps { + OMAP_DSS_OVL_CAP_SCALE = 1 << 0, + OMAP_DSS_OVL_CAP_DISPC = 1 << 1, +}; + +enum omap_overlay_manager_caps { + OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0, +}; + +/* RFBI */ + +struct rfbi_timings { + int cs_on_time; + int cs_off_time; + int we_on_time; + int we_off_time; + int re_on_time; + int re_off_time; + int we_cycle_time; + int re_cycle_time; + int cs_pulse_width; + int access_time; + + int clk_div; + + u32 tim[5]; /* set by rfbi_convert_timings() */ + + int converted; +}; + +void omap_rfbi_write_command(const void *buf, u32 len); +void omap_rfbi_read_data(void *buf, u32 len); +void omap_rfbi_write_data(const void *buf, u32 len); +void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, + u16 x, u16 y, + u16 w, u16 h); +int omap_rfbi_enable_te(bool enable, unsigned line); +int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode, + unsigned hs_pulse_time, unsigned vs_pulse_time, + int hs_pol_inv, int vs_pol_inv, int extif_div); + +/* DSI */ +void dsi_bus_lock(void); +void dsi_bus_unlock(void); +int dsi_vc_dcs_write(int channel, u8 *data, int len); +int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len); +int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen); +int dsi_vc_set_max_rx_packet_size(int channel, u16 len); +int dsi_vc_send_null(int channel); +int dsi_vc_send_bta_sync(int channel); + +/* Board specific data */ +struct omap_dss_board_info { + int (*get_last_off_on_transaction_id)(struct device *dev); + int num_devices; + struct omap_dss_device **devices; + struct omap_dss_device *default_device; +}; + +struct omap_video_timings { + /* Unit: pixels */ + u16 x_res; + /* Unit: pixels */ + u16 y_res; + /* Unit: KHz */ + u32 pixel_clock; + /* Unit: pixel clocks */ + u16 hsw; /* Horizontal synchronization pulse width */ + /* Unit: pixel clocks */ + u16 hfp; /* Horizontal front porch */ + /* Unit: pixel clocks */ + u16 hbp; /* Horizontal back porch */ + /* Unit: line clocks */ + u16 vsw; /* Vertical synchronization pulse width */ + /* Unit: line clocks */ + u16 vfp; /* Vertical front porch */ + /* Unit: line clocks */ + u16 vbp; /* Vertical back porch */ +}; + +#ifdef CONFIG_OMAP2_DSS_VENC +/* Hardcoded timings for tv modes. Venc only uses these to + * identify the mode, and does not actually use the configs + * itself. However, the configs should be something that + * a normal monitor can also show */ +const extern struct omap_video_timings omap_dss_pal_timings; +const extern struct omap_video_timings omap_dss_ntsc_timings; +#endif + +struct omap_overlay_info { + bool enabled; + + u32 paddr; + void __iomem *vaddr; + u16 screen_width; + u16 width; + u16 height; + enum omap_color_mode color_mode; + u8 rotation; + enum omap_dss_rotation_type rotation_type; + bool mirror; + + u16 pos_x; + u16 pos_y; + u16 out_width; /* if 0, out_width == width */ + u16 out_height; /* if 0, out_height == height */ + u8 global_alpha; +}; + +struct omap_overlay { + struct kobject kobj; + struct list_head list; + + /* static fields */ + const char *name; + int id; + enum omap_color_mode supported_modes; + enum omap_overlay_caps caps; + + /* dynamic fields */ + struct omap_overlay_manager *manager; + struct omap_overlay_info info; + + /* if true, info has been changed, but not applied() yet */ + bool info_dirty; + + int (*set_manager)(struct omap_overlay *ovl, + struct omap_overlay_manager *mgr); + int (*unset_manager)(struct omap_overlay *ovl); + + int (*set_overlay_info)(struct omap_overlay *ovl, + struct omap_overlay_info *info); + void (*get_overlay_info)(struct omap_overlay *ovl, + struct omap_overlay_info *info); + + int (*wait_for_go)(struct omap_overlay *ovl); +}; + +struct omap_overlay_manager_info { + u32 default_color; + + enum omap_dss_trans_key_type trans_key_type; + u32 trans_key; + bool trans_enabled; + + bool alpha_enabled; +}; + +struct omap_overlay_manager { + struct kobject kobj; + struct list_head list; + + /* static fields */ + const char *name; + int id; + enum omap_overlay_manager_caps caps; + int num_overlays; + struct omap_overlay **overlays; + enum omap_display_type supported_displays; + + /* dynamic fields */ + struct omap_dss_device *device; + struct omap_overlay_manager_info info; + + bool device_changed; + /* if true, info has been changed but not applied() yet */ + bool info_dirty; + + int (*set_device)(struct omap_overlay_manager *mgr, + struct omap_dss_device *dssdev); + int (*unset_device)(struct omap_overlay_manager *mgr); + + int (*set_manager_info)(struct omap_overlay_manager *mgr, + struct omap_overlay_manager_info *info); + void (*get_manager_info)(struct omap_overlay_manager *mgr, + struct omap_overlay_manager_info *info); + + int (*apply)(struct omap_overlay_manager *mgr); + int (*wait_for_go)(struct omap_overlay_manager *mgr); +}; + +struct omap_dss_device { + struct device dev; + + enum omap_display_type type; + + union { + struct { + u8 data_lines; + } dpi; + + struct { + u8 channel; + u8 data_lines; + } rfbi; + + struct { + u8 datapairs; + } sdi; + + struct { + u8 clk_lane; + u8 clk_pol; + u8 data1_lane; + u8 data1_pol; + u8 data2_lane; + u8 data2_pol; + + struct { + u16 regn; + u16 regm; + u16 regm3; + u16 regm4; + + u16 lp_clk_div; + + u16 lck_div; + u16 pck_div; + } div; + + bool ext_te; + u8 ext_te_gpio; + } dsi; + + struct { + enum omap_dss_venc_type type; + bool invert_polarity; + } venc; + } phy; + + struct { + struct omap_video_timings timings; + + int acbi; /* ac-bias pin transitions per interrupt */ + /* Unit: line clocks */ + int acb; /* ac-bias pin frequency */ + + enum omap_panel_config config; + + u8 recommended_bpp; + + struct omap_dss_device *ctrl; + } panel; + + struct { + u8 pixel_size; + struct rfbi_timings rfbi_timings; + struct omap_dss_device *panel; + } ctrl; + + int reset_gpio; + + int max_backlight_level; + + const char *name; + + /* used to match device to driver */ + const char *driver_name; + + void *data; + + struct omap_dss_driver *driver; + + /* helper variable for driver suspend/resume */ + bool activate_after_resume; + + enum omap_display_caps caps; + + struct omap_overlay_manager *manager; + + enum omap_dss_display_state state; + + int (*enable)(struct omap_dss_device *dssdev); + void (*disable)(struct omap_dss_device *dssdev); + + int (*suspend)(struct omap_dss_device *dssdev); + int (*resume)(struct omap_dss_device *dssdev); + + void (*get_resolution)(struct omap_dss_device *dssdev, + u16 *xres, u16 *yres); + int (*get_recommended_bpp)(struct omap_dss_device *dssdev); + + int (*check_timings)(struct omap_dss_device *dssdev, + struct omap_video_timings *timings); + void (*set_timings)(struct omap_dss_device *dssdev, + struct omap_video_timings *timings); + void (*get_timings)(struct omap_dss_device *dssdev, + struct omap_video_timings *timings); + int (*update)(struct omap_dss_device *dssdev, + u16 x, u16 y, u16 w, u16 h); + int (*sync)(struct omap_dss_device *dssdev); + int (*wait_vsync)(struct omap_dss_device *dssdev); + + int (*set_update_mode)(struct omap_dss_device *dssdev, + enum omap_dss_update_mode); + enum omap_dss_update_mode (*get_update_mode) + (struct omap_dss_device *dssdev); + + int (*enable_te)(struct omap_dss_device *dssdev, bool enable); + int (*get_te)(struct omap_dss_device *dssdev); + + u8 (*get_rotate)(struct omap_dss_device *dssdev); + int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate); + + bool (*get_mirror)(struct omap_dss_device *dssdev); + int (*set_mirror)(struct omap_dss_device *dssdev, bool enable); + + int (*run_test)(struct omap_dss_device *dssdev, int test); + int (*memory_read)(struct omap_dss_device *dssdev, + void *buf, size_t size, + u16 x, u16 y, u16 w, u16 h); + + int (*set_wss)(struct omap_dss_device *dssdev, u32 wss); + u32 (*get_wss)(struct omap_dss_device *dssdev); + + /* platform specific */ + int (*platform_enable)(struct omap_dss_device *dssdev); + void (*platform_disable)(struct omap_dss_device *dssdev); + int (*set_backlight)(struct omap_dss_device *dssdev, int level); + int (*get_backlight)(struct omap_dss_device *dssdev); +}; + +struct omap_dss_driver { + struct device_driver driver; + + int (*probe)(struct omap_dss_device *); + void (*remove)(struct omap_dss_device *); + + int (*enable)(struct omap_dss_device *display); + void (*disable)(struct omap_dss_device *display); + int (*suspend)(struct omap_dss_device *display); + int (*resume)(struct omap_dss_device *display); + int (*run_test)(struct omap_dss_device *display, int test); + + void (*setup_update)(struct omap_dss_device *dssdev, + u16 x, u16 y, u16 w, u16 h); + + int (*enable_te)(struct omap_dss_device *dssdev, bool enable); + int (*wait_for_te)(struct omap_dss_device *dssdev); + + u8 (*get_rotate)(struct omap_dss_device *dssdev); + int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate); + + bool (*get_mirror)(struct omap_dss_device *dssdev); + int (*set_mirror)(struct omap_dss_device *dssdev, bool enable); + + int (*memory_read)(struct omap_dss_device *dssdev, + void *buf, size_t size, + u16 x, u16 y, u16 w, u16 h); +}; + +int omap_dss_register_driver(struct omap_dss_driver *); +void omap_dss_unregister_driver(struct omap_dss_driver *); + +int omap_dss_register_device(struct omap_dss_device *); +void omap_dss_unregister_device(struct omap_dss_device *); + +void omap_dss_get_device(struct omap_dss_device *dssdev); +void omap_dss_put_device(struct omap_dss_device *dssdev); +#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL) +struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from); +struct omap_dss_device *omap_dss_find_device(void *data, + int (*match)(struct omap_dss_device *dssdev, void *data)); + +int omap_dss_start_device(struct omap_dss_device *dssdev); +void omap_dss_stop_device(struct omap_dss_device *dssdev); + +int omap_dss_get_num_overlay_managers(void); +struct omap_overlay_manager *omap_dss_get_overlay_manager(int num); + +int omap_dss_get_num_overlays(void); +struct omap_overlay *omap_dss_get_overlay(int num); + +typedef void (*omap_dispc_isr_t) (void *arg, u32 mask); +int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask); +int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask); + +int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout); +int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, + unsigned long timeout); + +#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver) +#define to_dss_device(x) container_of((x), struct omap_dss_device, dev) + +#endif diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index 1c017b29b7e99ea0091ae6d89ea9f0b0a7164f52..4ede9e17a0be2e4e578d4463a79cc7f09231e1c3 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -401,33 +401,6 @@ /*----------------------------------------------------------------------------*/ -/* Hardware registers for LCD DMA */ -#define OMAP1510_DMA_LCD_BASE (0xfffedb00) -#define OMAP1510_DMA_LCD_CTRL (OMAP1510_DMA_LCD_BASE + 0x00) -#define OMAP1510_DMA_LCD_TOP_F1_L (OMAP1510_DMA_LCD_BASE + 0x02) -#define OMAP1510_DMA_LCD_TOP_F1_U (OMAP1510_DMA_LCD_BASE + 0x04) -#define OMAP1510_DMA_LCD_BOT_F1_L (OMAP1510_DMA_LCD_BASE + 0x06) -#define OMAP1510_DMA_LCD_BOT_F1_U (OMAP1510_DMA_LCD_BASE + 0x08) - -#define OMAP1610_DMA_LCD_BASE (0xfffee300) -#define OMAP1610_DMA_LCD_CSDP (OMAP1610_DMA_LCD_BASE + 0xc0) -#define OMAP1610_DMA_LCD_CCR (OMAP1610_DMA_LCD_BASE + 0xc2) -#define OMAP1610_DMA_LCD_CTRL (OMAP1610_DMA_LCD_BASE + 0xc4) -#define OMAP1610_DMA_LCD_TOP_B1_L (OMAP1610_DMA_LCD_BASE + 0xc8) -#define OMAP1610_DMA_LCD_TOP_B1_U (OMAP1610_DMA_LCD_BASE + 0xca) -#define OMAP1610_DMA_LCD_BOT_B1_L (OMAP1610_DMA_LCD_BASE + 0xcc) -#define OMAP1610_DMA_LCD_BOT_B1_U (OMAP1610_DMA_LCD_BASE + 0xce) -#define OMAP1610_DMA_LCD_TOP_B2_L (OMAP1610_DMA_LCD_BASE + 0xd0) -#define OMAP1610_DMA_LCD_TOP_B2_U (OMAP1610_DMA_LCD_BASE + 0xd2) -#define OMAP1610_DMA_LCD_BOT_B2_L (OMAP1610_DMA_LCD_BASE + 0xd4) -#define OMAP1610_DMA_LCD_BOT_B2_U (OMAP1610_DMA_LCD_BASE + 0xd6) -#define OMAP1610_DMA_LCD_SRC_EI_B1 (OMAP1610_DMA_LCD_BASE + 0xd8) -#define OMAP1610_DMA_LCD_SRC_FI_B1_L (OMAP1610_DMA_LCD_BASE + 0xda) -#define OMAP1610_DMA_LCD_SRC_EN_B1 (OMAP1610_DMA_LCD_BASE + 0xe0) -#define OMAP1610_DMA_LCD_SRC_FN_B1 (OMAP1610_DMA_LCD_BASE + 0xe4) -#define OMAP1610_DMA_LCD_LCH_CTRL (OMAP1610_DMA_LCD_BASE + 0xea) -#define OMAP1610_DMA_LCD_SRC_FI_B1_U (OMAP1610_DMA_LCD_BASE + 0xf4) - #define OMAP1_DMA_TOUT_IRQ (1 << 0) #define OMAP_DMA_DROP_IRQ (1 << 1) #define OMAP_DMA_HALF_IRQ (1 << 2) @@ -441,6 +414,8 @@ #define OMAP2_DMA_SUPERVISOR_ERR_IRQ (1 << 10) #define OMAP2_DMA_MISALIGNED_ERR_IRQ (1 << 11) +#define OMAP_DMA_CCR_EN (1 << 7) + #define OMAP_DMA_DATA_TYPE_S8 0x00 #define OMAP_DMA_DATA_TYPE_S16 0x01 #define OMAP_DMA_DATA_TYPE_S32 0x02 @@ -503,14 +478,6 @@ #define DMA_CH_PRIO_HIGH 0x1 #define DMA_CH_PRIO_LOW 0x0 /* Def */ -/* LCD DMA block numbers */ -enum { - OMAP_LCD_DMA_B1_TOP, - OMAP_LCD_DMA_B1_BOTTOM, - OMAP_LCD_DMA_B2_TOP, - OMAP_LCD_DMA_B2_BOTTOM -}; - enum omap_dma_burst_mode { OMAP_DMA_DATA_BURST_DIS = 0, OMAP_DMA_DATA_BURST_4, @@ -661,20 +628,13 @@ extern int omap_modify_dma_chain_params(int chain_id, extern int omap_dma_chain_status(int chain_id); #endif -/* LCD DMA functions */ -extern int omap_request_lcd_dma(void (*callback)(u16 status, void *data), - void *data); -extern void omap_free_lcd_dma(void); -extern void omap_setup_lcd_dma(void); -extern void omap_enable_lcd_dma(void); -extern void omap_stop_lcd_dma(void); -extern void omap_set_lcd_dma_ext_controller(int external); -extern void omap_set_lcd_dma_single_transfer(int single); -extern void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres, - int data_type); -extern void omap_set_lcd_dma_b1_rotation(int rotate); -extern void omap_set_lcd_dma_b1_vxres(unsigned long vxres); -extern void omap_set_lcd_dma_b1_mirror(int mirror); -extern void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale); +#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_FB_OMAP) +#include +#else +static inline int omap_lcd_dma_running(void) +{ + return 0; +} +#endif #endif /* __ASM_ARCH_DMA_H */ diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 696e0ca051b77f89be6f4eb0d77da808632e1f15..e081338e0b23fa5a9a02ef38cf59be73eb86afa6 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -45,7 +45,7 @@ #define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) #define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10) #define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) -#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(1) +#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(2) #define GPMC_CONFIG1_MUXADDDATA (1 << 9) #define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4) #define GPMC_CONFIG1_FCLK_DIV(val) (val & 3) diff --git a/arch/arm/plat-omap/include/plat/i2c.h b/arch/arm/plat-omap/include/plat/i2c.h new file mode 100644 index 0000000000000000000000000000000000000000..585d9ca68b974c38a4c9ea0abb318f40c65bf9a9 --- /dev/null +++ b/arch/arm/plat-omap/include/plat/i2c.h @@ -0,0 +1,39 @@ +/* + * Helper module for board specific I2C bus registration + * + * Copyright (C) 2009 Nokia Corporation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include + +#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) +extern int omap_register_i2c_bus(int bus_id, u32 clkrate, + struct i2c_board_info const *info, + unsigned len); +#else +static inline int omap_register_i2c_bus(int bus_id, u32 clkrate, + struct i2c_board_info const *info, + unsigned len) +{ + return 0; +} +#endif + +int omap_plat_register_i2c_bus(int bus_id, u32 clkrate, + struct i2c_board_info const *info, + unsigned len); diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h index ce5dd2d1dc21507caf2212fa2b86064205f1d099..97d6c50c3dcb00b24d1d43551e6a4a3b8402621f 100644 --- a/arch/arm/plat-omap/include/plat/irqs.h +++ b/arch/arm/plat-omap/include/plat/irqs.h @@ -472,8 +472,22 @@ #endif #define TWL4030_GPIO_IRQ_END (TWL4030_GPIO_IRQ_BASE + TWL4030_GPIO_NR_IRQS) +#define TWL6030_IRQ_BASE (OMAP_FPGA_IRQ_END) +#ifdef CONFIG_TWL4030_CORE +#define TWL6030_BASE_NR_IRQS 20 +#else +#define TWL6030_BASE_NR_IRQS 0 +#endif +#define TWL6030_IRQ_END (TWL6030_IRQ_BASE + TWL6030_BASE_NR_IRQS) + /* Total number of interrupts depends on the enabled blocks above */ -#define NR_IRQS TWL4030_GPIO_IRQ_END +#if (TWL4030_GPIO_IRQ_END > TWL6030_IRQ_END) +#define TWL_IRQ_END TWL4030_GPIO_IRQ_END +#else +#define TWL_IRQ_END TWL6030_IRQ_END +#endif + +#define NR_IRQS TWL_IRQ_END #define OMAP_IRQ_BIT(irq) (1 << ((irq) % 32)) diff --git a/arch/arm/plat-omap/include/plat/mux.h b/arch/arm/plat-omap/include/plat/mux.h index ba77de6015010890a8300aead4de605472b7d769..8f069cc803504dc5a45263635c4ad4f5e1dc93c1 100644 --- a/arch/arm/plat-omap/include/plat/mux.h +++ b/arch/arm/plat-omap/include/plat/mux.h @@ -130,58 +130,11 @@ #define OMAP2_PULL_UP (1 << 4) #define OMAP2_ALTELECTRICALSEL (1 << 5) -/* 34xx specific mux bit defines */ -#define OMAP3_INPUT_EN (1 << 8) -#define OMAP3_OFF_EN (1 << 9) -#define OMAP3_OFFOUT_EN (1 << 10) -#define OMAP3_OFFOUT_VAL (1 << 11) -#define OMAP3_OFF_PULL_EN (1 << 12) -#define OMAP3_OFF_PULL_UP (1 << 13) -#define OMAP3_WAKEUP_EN (1 << 14) - -/* 34xx mux mode options for each pin. See TRM for options */ -#define OMAP34XX_MUX_MODE0 0 -#define OMAP34XX_MUX_MODE1 1 -#define OMAP34XX_MUX_MODE2 2 -#define OMAP34XX_MUX_MODE3 3 -#define OMAP34XX_MUX_MODE4 4 -#define OMAP34XX_MUX_MODE5 5 -#define OMAP34XX_MUX_MODE6 6 -#define OMAP34XX_MUX_MODE7 7 - -/* 34xx active pin states */ -#define OMAP34XX_PIN_OUTPUT 0 -#define OMAP34XX_PIN_INPUT OMAP3_INPUT_EN -#define OMAP34XX_PIN_INPUT_PULLUP (OMAP2_PULL_ENA | OMAP3_INPUT_EN \ - | OMAP2_PULL_UP) -#define OMAP34XX_PIN_INPUT_PULLDOWN (OMAP2_PULL_ENA | OMAP3_INPUT_EN) - -/* 34xx off mode states */ -#define OMAP34XX_PIN_OFF_NONE 0 -#define OMAP34XX_PIN_OFF_OUTPUT_HIGH (OMAP3_OFF_EN | OMAP3_OFFOUT_EN \ - | OMAP3_OFFOUT_VAL) -#define OMAP34XX_PIN_OFF_OUTPUT_LOW (OMAP3_OFF_EN | OMAP3_OFFOUT_EN) -#define OMAP34XX_PIN_OFF_INPUT_PULLUP (OMAP3_OFF_EN | OMAP3_OFF_PULL_EN \ - | OMAP3_OFF_PULL_UP) -#define OMAP34XX_PIN_OFF_INPUT_PULLDOWN (OMAP3_OFF_EN | OMAP3_OFF_PULL_EN) -#define OMAP34XX_PIN_OFF_WAKEUPENABLE OMAP3_WAKEUP_EN - -#define MUX_CFG_34XX(desc, reg_offset, mux_value) { \ - .name = desc, \ - .debug = 0, \ - .mux_reg = reg_offset, \ - .mux_val = mux_value \ -}, - struct pin_config { char *name; const unsigned int mux_reg; unsigned char debug; -#if defined(CONFIG_ARCH_OMAP34XX) - u16 mux_val; /* Wake-up, off mode, pull, mux mode */ -#endif - #if defined(CONFIG_ARCH_OMAP1) || defined(CONFIG_ARCH_OMAP24XX) const unsigned char mask_offset; const unsigned char mask; @@ -219,11 +172,17 @@ enum omap7xx_index { AA17_7XX_USB_DM, W16_7XX_USB_PU_EN, W17_7XX_USB_VBUSI, + W18_7XX_USB_DMCK_OUT, + W19_7XX_USB_DCRST, /* MMC */ MMC_7XX_CMD, MMC_7XX_CLK, MMC_7XX_DAT0, + + /* I2C */ + I2C_7XX_SCL, + I2C_7XX_SDA, }; enum omap1xxx_index { @@ -681,181 +640,6 @@ enum omap24xx_index { }; -enum omap34xx_index { - /* 34xx I2C */ - K21_34XX_I2C1_SCL, - J21_34XX_I2C1_SDA, - AF15_34XX_I2C2_SCL, - AE15_34XX_I2C2_SDA, - AF14_34XX_I2C3_SCL, - AG14_34XX_I2C3_SDA, - AD26_34XX_I2C4_SCL, - AE26_34XX_I2C4_SDA, - - /* PHY - HSUSB: 12-pin ULPI PHY: Port 1*/ - Y8_3430_USB1HS_PHY_CLK, - Y9_3430_USB1HS_PHY_STP, - AA14_3430_USB1HS_PHY_DIR, - AA11_3430_USB1HS_PHY_NXT, - W13_3430_USB1HS_PHY_DATA0, - W12_3430_USB1HS_PHY_DATA1, - W11_3430_USB1HS_PHY_DATA2, - Y11_3430_USB1HS_PHY_DATA3, - W9_3430_USB1HS_PHY_DATA4, - Y12_3430_USB1HS_PHY_DATA5, - W8_3430_USB1HS_PHY_DATA6, - Y13_3430_USB1HS_PHY_DATA7, - - /* PHY - HSUSB: 12-pin ULPI PHY: Port 2*/ - AA8_3430_USB2HS_PHY_CLK, - AA10_3430_USB2HS_PHY_STP, - AA9_3430_USB2HS_PHY_DIR, - AB11_3430_USB2HS_PHY_NXT, - AB10_3430_USB2HS_PHY_DATA0, - AB9_3430_USB2HS_PHY_DATA1, - W3_3430_USB2HS_PHY_DATA2, - T4_3430_USB2HS_PHY_DATA3, - T3_3430_USB2HS_PHY_DATA4, - R3_3430_USB2HS_PHY_DATA5, - R4_3430_USB2HS_PHY_DATA6, - T2_3430_USB2HS_PHY_DATA7, - - - /* TLL - HSUSB: 12-pin TLL Port 1*/ - Y8_3430_USB1HS_TLL_CLK, - Y9_3430_USB1HS_TLL_STP, - AA14_3430_USB1HS_TLL_DIR, - AA11_3430_USB1HS_TLL_NXT, - W13_3430_USB1HS_TLL_DATA0, - W12_3430_USB1HS_TLL_DATA1, - W11_3430_USB1HS_TLL_DATA2, - Y11_3430_USB1HS_TLL_DATA3, - W9_3430_USB1HS_TLL_DATA4, - Y12_3430_USB1HS_TLL_DATA5, - W8_3430_USB1HS_TLL_DATA6, - Y13_3430_USB1HS_TLL_DATA7, - - /* TLL - HSUSB: 12-pin TLL Port 2*/ - AA8_3430_USB2HS_TLL_CLK, - AA10_3430_USB2HS_TLL_STP, - AA9_3430_USB2HS_TLL_DIR, - AB11_3430_USB2HS_TLL_NXT, - AB10_3430_USB2HS_TLL_DATA0, - AB9_3430_USB2HS_TLL_DATA1, - W3_3430_USB2HS_TLL_DATA2, - T4_3430_USB2HS_TLL_DATA3, - T3_3430_USB2HS_TLL_DATA4, - R3_3430_USB2HS_TLL_DATA5, - R4_3430_USB2HS_TLL_DATA6, - T2_3430_USB2HS_TLL_DATA7, - - /* TLL - HSUSB: 12-pin TLL Port 3*/ - AA6_3430_USB3HS_TLL_CLK, - AB3_3430_USB3HS_TLL_STP, - AA3_3430_USB3HS_TLL_DIR, - Y3_3430_USB3HS_TLL_NXT, - AA5_3430_USB3HS_TLL_DATA0, - Y4_3430_USB3HS_TLL_DATA1, - Y5_3430_USB3HS_TLL_DATA2, - W5_3430_USB3HS_TLL_DATA3, - AB12_3430_USB3HS_TLL_DATA4, - AB13_3430_USB3HS_TLL_DATA5, - AA13_3430_USB3HS_TLL_DATA6, - AA12_3430_USB3HS_TLL_DATA7, - - /* PHY FSUSB: FS Serial for Port 1 (multiple PHY modes supported) */ - AF10_3430_USB1FS_PHY_MM1_RXDP, - AG9_3430_USB1FS_PHY_MM1_RXDM, - W13_3430_USB1FS_PHY_MM1_RXRCV, - W12_3430_USB1FS_PHY_MM1_TXSE0, - W11_3430_USB1FS_PHY_MM1_TXDAT, - Y11_3430_USB1FS_PHY_MM1_TXEN_N, - - /* PHY FSUSB: FS Serial for Port 2 (multiple PHY modes supported) */ - AF7_3430_USB2FS_PHY_MM2_RXDP, - AH7_3430_USB2FS_PHY_MM2_RXDM, - AB10_3430_USB2FS_PHY_MM2_RXRCV, - AB9_3430_USB2FS_PHY_MM2_TXSE0, - W3_3430_USB2FS_PHY_MM2_TXDAT, - T4_3430_USB2FS_PHY_MM2_TXEN_N, - - /* PHY FSUSB: FS Serial for Port 3 (multiple PHY modes supported) */ - AH3_3430_USB3FS_PHY_MM3_RXDP, - AE3_3430_USB3FS_PHY_MM3_RXDM, - AD1_3430_USB3FS_PHY_MM3_RXRCV, - AE1_3430_USB3FS_PHY_MM3_TXSE0, - AD2_3430_USB3FS_PHY_MM3_TXDAT, - AC1_3430_USB3FS_PHY_MM3_TXEN_N, - - /* 34xx GPIO - * - normally these are bidirectional, no internal pullup/pulldown - * - "_UP" suffix (GPIO3_UP) if internal pullup is configured - * - "_DOWN" suffix (GPIO3_DOWN) with internal pulldown - * - "_OUT" suffix (GPIO3_OUT) for output-only pins (unlike 24xx) - */ - AF26_34XX_GPIO0, - AF22_34XX_GPIO9, - AG9_34XX_GPIO23, - AH8_34XX_GPIO29, - U8_34XX_GPIO54_OUT, - U8_34XX_GPIO54_DOWN, - L8_34XX_GPIO63, - G25_34XX_GPIO86_OUT, - AG4_34XX_GPIO134_OUT, - AF4_34XX_GPIO135_OUT, - AE4_34XX_GPIO136_OUT, - AF6_34XX_GPIO140_UP, - AE6_34XX_GPIO141, - AF5_34XX_GPIO142, - AE5_34XX_GPIO143, - H19_34XX_GPIO164_OUT, - J25_34XX_GPIO170, - - /* OMAP3 SDRC CKE signals to SDR/DDR ram chips */ - H16_34XX_SDRC_CKE0, - H17_34XX_SDRC_CKE1, - - /* MMC1 */ - N28_3430_MMC1_CLK, - M27_3430_MMC1_CMD, - N27_3430_MMC1_DAT0, - N26_3430_MMC1_DAT1, - N25_3430_MMC1_DAT2, - P28_3430_MMC1_DAT3, - P27_3430_MMC1_DAT4, - P26_3430_MMC1_DAT5, - R27_3430_MMC1_DAT6, - R25_3430_MMC1_DAT7, - - /* MMC2 */ - AE2_3430_MMC2_CLK, - AG5_3430_MMC2_CMD, - AH5_3430_MMC2_DAT0, - AH4_3430_MMC2_DAT1, - AG4_3430_MMC2_DAT2, - AF4_3430_MMC2_DAT3, - AE4_3430_MMC2_DAT4, - AH3_3430_MMC2_DAT5, - AF3_3430_MMC2_DAT6, - AE3_3430_MMC2_DAT7, - - /* MMC3 */ - AF10_3430_MMC3_CLK, - AC3_3430_MMC3_CMD, - AE11_3430_MMC3_DAT0, - AH9_3430_MMC3_DAT1, - AF13_3430_MMC3_DAT2, - AF13_3430_MMC3_DAT3, - - /* SYS_NIRQ T2 INT1 */ - AF26_34XX_SYS_NIRQ, - - /* EHCI GPIO's for OMAP3EVM (Rev >= E) */ - AH14_34XX_GPIO21, - AF9_34XX_GPIO22, - U3_34XX_GPIO61, -}; - struct omap_mux_cfg { struct pin_config *pins; unsigned long size; @@ -865,14 +649,14 @@ struct omap_mux_cfg { #ifdef CONFIG_OMAP_MUX /* setup pin muxing in Linux */ extern int omap1_mux_init(void); -extern int omap2_mux_init(void); extern int omap_mux_register(struct omap_mux_cfg *); extern int omap_cfg_reg(unsigned long reg_cfg); #else /* boot loader does it all (no warnings from CONFIG_OMAP_MUX_WARNINGS) */ static inline int omap1_mux_init(void) { return 0; } -static inline int omap2_mux_init(void) { return 0; } static inline int omap_cfg_reg(unsigned long reg_cfg) { return 0; } #endif +extern int omap2_mux_init(void); + #endif diff --git a/arch/arm/plat-omap/include/plat/omap44xx.h b/arch/arm/plat-omap/include/plat/omap44xx.h index e52902a15c1a2cdddf658820a2b7fe4e41a5ddd5..ef870de43c29b9c12d7491e0262bf1815b7e7865 100644 --- a/arch/arm/plat-omap/include/plat/omap44xx.h +++ b/arch/arm/plat-omap/include/plat/omap44xx.h @@ -26,8 +26,10 @@ #define OMAP44XX_EMIF2_BASE 0x4d000000 #define OMAP44XX_DMM_BASE 0x4e000000 #define OMAP4430_32KSYNCT_BASE 0x4a304000 -#define OMAP4430_CM_BASE 0x4a004000 -#define OMAP4430_PRM_BASE 0x48306000 +#define OMAP4430_CM1_BASE 0x4a004000 +#define OMAP4430_CM_BASE OMAP4430_CM1_BASE +#define OMAP4430_CM2_BASE 0x4a008000 +#define OMAP4430_PRM_BASE 0x4a306000 #define OMAP44XX_GPMC_BASE 0x50000000 #define OMAP443X_SCM_BASE 0x4a002000 #define OMAP443X_CTRL_BASE OMAP443X_SCM_BASE diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h index 11a9773a4e7ff75c44feeb02dd8945d7d4e1ef0e..dc1fac1d805c0ab7677e02e485af0e270d06d808 100644 --- a/arch/arm/plat-omap/include/plat/omap_device.h +++ b/arch/arm/plat-omap/include/plat/omap_device.h @@ -50,8 +50,8 @@ * @pm_lats: ptr to an omap_device_pm_latency table * @pm_lats_cnt: ARRAY_SIZE() of what is passed to @pm_lats * @pm_lat_level: array index of the last odpl entry executed - -1 if never - * @dev_wakeup_lat: dev wakeup latency in microseconds - * @_dev_wakeup_lat_limit: dev wakeup latency limit in usec - set by OMAP PM + * @dev_wakeup_lat: dev wakeup latency in nanoseconds + * @_dev_wakeup_lat_limit: dev wakeup latency limit in nsec - set by OMAP PM * @_state: one of OMAP_DEVICE_STATE_* (see above) * @flags: device flags * @@ -137,5 +137,7 @@ struct omap_device_pm_latency { }; -#endif +/* Get omap_device pointer from platform_device pointer */ +#define to_omap_device(x) container_of((x), struct omap_device, pdev) +#endif diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index dbdd123eca162a3c54f61347411326a0996d2c58..007935a921eaeaa4efd69ab1a0b53d757ad90587 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -50,6 +50,8 @@ struct omap_device; #define SYSC_ENAWAKEUP_MASK (1 << SYSC_ENAWAKEUP_SHIFT) #define SYSC_SOFTRESET_SHIFT 1 #define SYSC_SOFTRESET_MASK (1 << SYSC_SOFTRESET_SHIFT) +#define SYSC_AUTOIDLE_SHIFT 0 +#define SYSC_AUTOIDLE_MASK (1 << SYSC_AUTOIDLE_SHIFT) /* OCP SYSSTATUS bit shifts/masks */ #define SYSS_RESETDONE_SHIFT 0 @@ -62,7 +64,21 @@ struct omap_device; /** - * struct omap_hwmod_dma_info - MPU address space handled by the hwmod + * struct omap_hwmod_irq_info - MPU IRQs used by the hwmod + * @name: name of the IRQ channel (module local name) + * @irq_ch: IRQ channel ID + * + * @name should be something short, e.g., "tx" or "rx". It is for use + * by platform_get_resource_byname(). It is defined locally to the + * hwmod. + */ +struct omap_hwmod_irq_info { + const char *name; + u16 irq; +}; + +/** + * struct omap_hwmod_dma_info - DMA channels used by the hwmod * @name: name of the DMA channel (module local name) * @dma_ch: DMA channel ID * @@ -294,13 +310,17 @@ struct omap_hwmod_omap4_prcm { * SDRAM controller, etc. * HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM * controller, etc. + * HWMOD_NO_AUTOIDLE: disable module autoidle (OCP_SYSCONFIG.AUTOIDLE) + * when module is enabled, rather than the default, which is to + * enable autoidle * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup */ #define HWMOD_SWSUP_SIDLE (1 << 0) #define HWMOD_SWSUP_MSTANDBY (1 << 1) #define HWMOD_INIT_NO_RESET (1 << 2) #define HWMOD_INIT_NO_IDLE (1 << 3) -#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 4) +#define HWMOD_NO_OCP_AUTOIDLE (1 << 4) +#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 5) /* * omap_hwmod._int_flags definitions @@ -373,7 +393,7 @@ struct omap_hwmod_omap4_prcm { struct omap_hwmod { const char *name; struct omap_device *od; - u8 *mpu_irqs; + struct omap_hwmod_irq_info *mpu_irqs; struct omap_hwmod_dma_info *sdma_chs; union { struct omap_hwmod_omap2_prcm omap2; diff --git a/arch/arm/plat-omap/include/plat/powerdomain.h b/arch/arm/plat-omap/include/plat/powerdomain.h index 3d45ee1d3cf49fad790459ca16aff0021f1b02d9..0b960051eaed9b14070062c82a9e92ff6d8b55fc 100644 --- a/arch/arm/plat-omap/include/plat/powerdomain.h +++ b/arch/arm/plat-omap/include/plat/powerdomain.h @@ -28,6 +28,8 @@ #define PWRDM_POWER_INACTIVE 0x2 #define PWRDM_POWER_ON 0x3 +#define PWRDM_MAX_PWRSTS 4 + /* Powerdomain allowable state bitfields */ #define PWRSTS_OFF_ON ((1 << PWRDM_POWER_OFF) | \ (1 << PWRDM_POWER_ON)) @@ -40,7 +42,10 @@ /* Powerdomain flags */ #define PWRDM_HAS_HDWR_SAR (1 << 0) /* hardware save-and-restore support */ - +#define PWRDM_HAS_MPU_QUIRK (1 << 1) /* MPU pwr domain has MEM bank 0 bits + * in MEM bank 1 position. This is + * true for OMAP3430 + */ /* * Number of memory banks that are power-controllable. On OMAP3430, the @@ -85,15 +90,15 @@ struct powerdomain { /* Used to represent the OMAP chip types containing this pwrdm */ const struct omap_chip_id omap_chip; - /* Bit shift of this powerdomain's PM_WKDEP/CM_SLEEPDEP bit */ - const u8 dep_bit; - /* Powerdomains that can be told to wake this powerdomain up */ struct pwrdm_dep *wkdep_srcs; /* Powerdomains that can be told to keep this pwrdm from inactivity */ struct pwrdm_dep *sleepdep_srcs; + /* Bit shift of this powerdomain's PM_WKDEP/CM_SLEEPDEP bit */ + const u8 dep_bit; + /* Possible powerdomain power states */ const u8 pwrsts; @@ -118,11 +123,11 @@ struct powerdomain { struct list_head node; int state; - unsigned state_counter[4]; + unsigned state_counter[PWRDM_MAX_PWRSTS]; #ifdef CONFIG_PM_DEBUG s64 timer; - s64 state_timer[4]; + s64 state_timer[PWRDM_MAX_PWRSTS]; #endif }; diff --git a/arch/arm/plat-omap/include/plat/sdrc.h b/arch/arm/plat-omap/include/plat/sdrc.h index f704030d2a701f434eeb0defac83637330cb878c..7b76f50564ba543c1626df470383c3b58c55afa9 100644 --- a/arch/arm/plat-omap/include/plat/sdrc.h +++ b/arch/arm/plat-omap/include/plat/sdrc.h @@ -94,7 +94,10 @@ /* SMS register offsets - read/write with sms_{read,write}_reg() */ -#define SMS_SYSCONFIG 0x010 +#define SMS_SYSCONFIG 0x010 +#define SMS_ROT_CONTROL(context) (0x180 + 0x10 * context) +#define SMS_ROT_SIZE(context) (0x184 + 0x10 * context) +#define SMS_ROT_PHYSICAL_BA(context) (0x188 + 0x10 * context) /* REVISIT: fill in other SMS registers here */ @@ -129,6 +132,10 @@ int omap2_sdrc_get_params(unsigned long r, void omap2_sms_save_context(void); void omap2_sms_restore_context(void); +void omap2_sms_write_rot_control(u32 val, unsigned ctx); +void omap2_sms_write_rot_size(u32 val, unsigned ctx); +void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx); + #ifdef CONFIG_ARCH_OMAP2 struct memory_timings { diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h index 9951345a25d6ae1b17d901d461af6156393f33d1..f5a4a92393ef2f0c34261ee4eb606b362bcb4c53 100644 --- a/arch/arm/plat-omap/include/plat/serial.h +++ b/arch/arm/plat-omap/include/plat/serial.h @@ -53,6 +53,7 @@ #ifndef __ASSEMBLER__ extern void __init omap_serial_early_init(void); extern void omap_serial_init(void); +extern void omap_serial_init_port(int port); extern int omap_uart_can_sleep(void); extern void omap_uart_check_wakeup(void); extern void omap_uart_prepare_suspend(void); diff --git a/arch/arm/plat-omap/include/plat/smp.h b/arch/arm/plat-omap/include/plat/smp.h index dcaa8fde70634cf56e0b63750dea5495758b2529..8983d54c4fd2e95a8a30c2a5920376cb07893eb6 100644 --- a/arch/arm/plat-omap/include/plat/smp.h +++ b/arch/arm/plat-omap/include/plat/smp.h @@ -28,6 +28,8 @@ /* Needed for secondary core boot */ extern void omap_secondary_startup(void); +extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask); +extern void omap_auxcoreboot_addr(u32 cpu_addr); /* * We use Soft IRQ1 as the IPI diff --git a/arch/arm/plat-omap/include/plat/vram.h b/arch/arm/plat-omap/include/plat/vram.h new file mode 100644 index 0000000000000000000000000000000000000000..edd4987758a64db91d606a26806593ae2a48d698 --- /dev/null +++ b/arch/arm/plat-omap/include/plat/vram.h @@ -0,0 +1,62 @@ +/* + * VRAM manager for OMAP + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * 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. + */ + +#ifndef __OMAP_VRAM_H__ +#define __OMAP_VRAM_H__ + +#include + +#define OMAP_VRAM_MEMTYPE_SDRAM 0 +#define OMAP_VRAM_MEMTYPE_SRAM 1 +#define OMAP_VRAM_MEMTYPE_MAX 1 + +extern int omap_vram_add_region(unsigned long paddr, size_t size); +extern int omap_vram_free(unsigned long paddr, size_t size); +extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr); +extern int omap_vram_reserve(unsigned long paddr, size_t size); +extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram, + unsigned long *largest_free_block); + +#ifdef CONFIG_OMAP2_VRAM +extern void omap_vram_set_sdram_vram(u32 size, u32 start); +extern void omap_vram_set_sram_vram(u32 size, u32 start); + +extern void omap_vram_reserve_sdram(void); +extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart, + unsigned long sram_vstart, + unsigned long sram_size, + unsigned long pstart_avail, + unsigned long size_avail); +#else +static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { } +static inline void omap_vram_set_sram_vram(u32 size, u32 start) { } + +static inline void omap_vram_reserve_sdram(void) { } +static inline unsigned long omap_vram_reserve_sram(unsigned long sram_pstart, + unsigned long sram_vstart, + unsigned long sram_size, + unsigned long pstart_avail, + unsigned long size_avail) +{ + return 0; +} +#endif + +#endif diff --git a/arch/arm/plat-omap/include/plat/vrfb.h b/arch/arm/plat-omap/include/plat/vrfb.h new file mode 100644 index 0000000000000000000000000000000000000000..d8a03ced3b108cbd78c494a364e9c98e1215ca50 --- /dev/null +++ b/arch/arm/plat-omap/include/plat/vrfb.h @@ -0,0 +1,50 @@ +/* + * VRFB Rotation Engine + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * 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. + */ + +#ifndef __OMAP_VRFB_H__ +#define __OMAP_VRFB_H__ + +#define OMAP_VRFB_LINE_LEN 2048 + +struct vrfb { + u8 context; + void __iomem *vaddr[4]; + unsigned long paddr[4]; + u16 xres; + u16 yres; + u16 xoffset; + u16 yoffset; + u8 bytespp; + bool yuv_mode; +}; + +extern int omap_vrfb_request_ctx(struct vrfb *vrfb); +extern void omap_vrfb_release_ctx(struct vrfb *vrfb); +extern void omap_vrfb_adjust_size(u16 *width, u16 *height, + u8 bytespp); +extern u32 omap_vrfb_min_phys_size(u16 width, u16 height, u8 bytespp); +extern u16 omap_vrfb_max_height(u32 phys_size, u16 width, u8 bytespp); +extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr, + u16 width, u16 height, + unsigned bytespp, bool yuv_mode); +extern int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot); +extern void omap_vrfb_restore_context(void); + +#endif /* __VRFB_H */ diff --git a/arch/arm/plat-omap/mux.c b/arch/arm/plat-omap/mux.c index 05aebcad215b4b0a9308187bf3e82f824a33436e..06703635ace15672b7d82f3fad9e4a032dc2afaa 100644 --- a/arch/arm/plat-omap/mux.c +++ b/arch/arm/plat-omap/mux.c @@ -54,8 +54,12 @@ int __init_or_module omap_cfg_reg(const unsigned long index) { struct pin_config *reg; - if (cpu_is_omap44xx()) - return 0; + if (cpu_is_omap34xx() || cpu_is_omap44xx()) { + printk(KERN_ERR "mux: Broken omap_cfg_reg(%lu) entry\n", + index); + WARN_ON(1); + return -EINVAL; + } if (mux_cfg == NULL) { printk(KERN_ERR "Pin mux table not initialized\n"); diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index bb16e624a557aabbeea7ee8d952b490acbea2678..1e5648d3e3d8a04a08092e42777b593cca04f073 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -134,18 +134,18 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat) (od->dev_wakeup_lat <= od->_dev_wakeup_lat_limit)) break; - getnstimeofday(&a); + read_persistent_clock(&a); /* XXX check return code */ odpl->activate_func(od); - getnstimeofday(&b); + read_persistent_clock(&b); c = timespec_sub(b, a); - act_lat = timespec_to_ns(&c) * NSEC_PER_USEC; + act_lat = timespec_to_ns(&c); pr_debug("omap_device: %s: pm_lat %d: activate: elapsed time " - "%llu usec\n", od->pdev.name, od->pm_lat_level, + "%llu nsec\n", od->pdev.name, od->pm_lat_level, act_lat); WARN(act_lat > odpl->activate_lat, "omap_device: %s.%d: " @@ -190,18 +190,18 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat) od->_dev_wakeup_lat_limit)) break; - getnstimeofday(&a); + read_persistent_clock(&a); /* XXX check return code */ odpl->deactivate_func(od); - getnstimeofday(&b); + read_persistent_clock(&b); c = timespec_sub(b, a); - deact_lat = timespec_to_ns(&c) * NSEC_PER_USEC; + deact_lat = timespec_to_ns(&c); pr_debug("omap_device: %s: pm_lat %d: deactivate: elapsed time " - "%llu usec\n", od->pdev.name, od->pm_lat_level, + "%llu nsec\n", od->pdev.name, od->pm_lat_level, deact_lat); WARN(deact_lat > odpl->deactivate_lat, "omap_device: %s.%d: " @@ -459,7 +459,7 @@ int omap_device_enable(struct platform_device *pdev) ret = _omap_device_activate(od, IGNORE_WAKEUP_LAT); od->dev_wakeup_lat = 0; - od->_dev_wakeup_lat_limit = INT_MAX; + od->_dev_wakeup_lat_limit = UINT_MAX; od->_state = OMAP_DEVICE_STATE_ENABLED; return ret; diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 3e923668778d8aa88018837e39ae5ca9586226fb..d8d5094b37ed81c7a126dbf117ec7ce392778aeb 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -47,8 +48,10 @@ #define OMAP3_SRAM_VA 0xfe400000 #define OMAP3_SRAM_PUB_PA 0x40208000 #define OMAP3_SRAM_PUB_VA (OMAP3_SRAM_VA + 0x8000) -#define OMAP4_SRAM_PA 0x40200000 /*0x402f0000*/ -#define OMAP4_SRAM_VA 0xfe400000 /*0xfe4f0000*/ +#define OMAP4_SRAM_PA 0x40300000 +#define OMAP4_SRAM_VA 0xfe400000 +#define OMAP4_SRAM_PUB_PA (OMAP4_SRAM_PA + 0x4000) +#define OMAP4_SRAM_PUB_VA (OMAP4_SRAM_VA + 0x4000) #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) #define SRAM_BOOTLOADER_SZ 0x00 @@ -139,6 +142,10 @@ void __init omap_detect_sram(void) } else { omap_sram_size = 0x8000; /* 32K */ } + } else if (cpu_is_omap44xx()) { + omap_sram_base = OMAP4_SRAM_PUB_VA; + omap_sram_start = OMAP4_SRAM_PUB_PA; + omap_sram_size = 0xa000; /* 40K */ } else { omap_sram_base = OMAP2_SRAM_PUB_VA; omap_sram_start = OMAP2_SRAM_PUB_PA; @@ -152,7 +159,7 @@ void __init omap_detect_sram(void) } else if (cpu_is_omap44xx()) { omap_sram_base = OMAP4_SRAM_VA; omap_sram_start = OMAP4_SRAM_PA; - omap_sram_size = 0x8000; /* 32K */ + omap_sram_size = 0xe000; /* 56K */ } else { omap_sram_base = OMAP2_SRAM_VA; omap_sram_start = OMAP2_SRAM_PA; @@ -185,6 +192,13 @@ void __init omap_detect_sram(void) omap_sram_start + SRAM_BOOTLOADER_SZ, omap_sram_size - SRAM_BOOTLOADER_SZ); omap_sram_size -= reserved; + + reserved = omap_vram_reserve_sram(omap_sram_start, omap_sram_base, + omap_sram_size, + omap_sram_start + SRAM_BOOTLOADER_SZ, + omap_sram_size - SRAM_BOOTLOADER_SZ); + omap_sram_size -= reserved; + omap_sram_ceil = omap_sram_base + omap_sram_size; } diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c index 51033a4503c3eb7821876d740a0e829ae1719447..d3bf17cd36f37f997c1c3dbe879905f70bdf5289 100644 --- a/arch/arm/plat-omap/usb.c +++ b/arch/arm/plat-omap/usb.c @@ -137,7 +137,13 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) if (is_device) { if (cpu_is_omap24xx()) omap_cfg_reg(J20_24XX_USB0_PUEN); - else + else if (cpu_is_omap7xx()) { + omap_cfg_reg(AA17_7XX_USB_DM); + omap_cfg_reg(W16_7XX_USB_PU_EN); + omap_cfg_reg(W17_7XX_USB_VBUSI); + omap_cfg_reg(W18_7XX_USB_DMCK_OUT); + omap_cfg_reg(W19_7XX_USB_DCRST); + } else omap_cfg_reg(W4_USB_PUEN); } diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 2d7423af1197a3418f1b7bb84222f04f77954884..aed05bc3c2eaecf29ddd63c1aabf1842d8f9440f 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -38,16 +38,72 @@ union vfp_state *last_VFP_context[NR_CPUS]; */ unsigned int VFP_arch; +/* + * Per-thread VFP initialization. + */ +static void vfp_thread_flush(struct thread_info *thread) +{ + union vfp_state *vfp = &thread->vfpstate; + unsigned int cpu; + + memset(vfp, 0, sizeof(union vfp_state)); + + vfp->hard.fpexc = FPEXC_EN; + vfp->hard.fpscr = FPSCR_ROUND_NEAREST; + + /* + * Disable VFP to ensure we initialize it first. We must ensure + * that the modification of last_VFP_context[] and hardware disable + * are done for the same CPU and without preemption. + */ + cpu = get_cpu(); + if (last_VFP_context[cpu] == vfp) + last_VFP_context[cpu] = NULL; + fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); + put_cpu(); +} + +static void vfp_thread_release(struct thread_info *thread) +{ + /* release case: Per-thread VFP cleanup. */ + union vfp_state *vfp = &thread->vfpstate; + unsigned int cpu = thread->cpu; + + if (last_VFP_context[cpu] == vfp) + last_VFP_context[cpu] = NULL; +} + +/* + * When this function is called with the following 'cmd's, the following + * is true while this function is being run: + * THREAD_NOFTIFY_SWTICH: + * - the previously running thread will not be scheduled onto another CPU. + * - the next thread to be run (v) will not be running on another CPU. + * - thread->cpu is the local CPU number + * - not preemptible as we're called in the middle of a thread switch + * THREAD_NOTIFY_FLUSH: + * - the thread (v) will be running on the local CPU, so + * v === current_thread_info() + * - thread->cpu is the local CPU number at the time it is accessed, + * but may change at any time. + * - we could be preempted if tree preempt rcu is enabled, so + * it is unsafe to use thread->cpu. + * THREAD_NOTIFY_RELEASE: + * - the thread (v) will not be running on any CPU; it is a dead thread. + * - thread->cpu will be the last CPU the thread ran on, which may not + * be the current CPU. + * - we could be preempted if tree preempt rcu is enabled. + */ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v) { struct thread_info *thread = v; - union vfp_state *vfp; - __u32 cpu = thread->cpu; if (likely(cmd == THREAD_NOTIFY_SWITCH)) { u32 fpexc = fmrx(FPEXC); #ifdef CONFIG_SMP + unsigned int cpu = thread->cpu; + /* * On SMP, if VFP is enabled, save the old state in * case the thread migrates to a different CPU. The @@ -74,25 +130,10 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v) return NOTIFY_DONE; } - vfp = &thread->vfpstate; - if (cmd == THREAD_NOTIFY_FLUSH) { - /* - * Per-thread VFP initialisation. - */ - memset(vfp, 0, sizeof(union vfp_state)); - - vfp->hard.fpexc = FPEXC_EN; - vfp->hard.fpscr = FPSCR_ROUND_NEAREST; - - /* - * Disable VFP to ensure we initialise it first. - */ - fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); - } - - /* flush and release case: Per-thread VFP cleanup. */ - if (last_VFP_context[cpu] == vfp) - last_VFP_context[cpu] = NULL; + if (cmd == THREAD_NOTIFY_FLUSH) + vfp_thread_flush(thread); + else + vfp_thread_release(thread); return NOTIFY_DONE; } diff --git a/arch/avr32/include/asm/syscalls.h b/arch/avr32/include/asm/syscalls.h index 483d666c27c092bd2289b970a51f2edc6396b182..66a197266637e07f898102903e609ae710f521f8 100644 --- a/arch/avr32/include/asm/syscalls.h +++ b/arch/avr32/include/asm/syscalls.h @@ -29,10 +29,6 @@ asmlinkage int sys_sigaltstack(const stack_t __user *, stack_t __user *, struct pt_regs *); asmlinkage int sys_rt_sigreturn(struct pt_regs *); -/* kernel/sys_avr32.c */ -asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long, - unsigned long, unsigned long, off_t); - /* mm/cache.c */ asmlinkage int sys_cacheflush(int, void __user *, size_t); diff --git a/arch/avr32/kernel/sys_avr32.c b/arch/avr32/kernel/sys_avr32.c index 5d2daeaf356f73331489d5e21a8be7e440cb6a45..459349b5ed5aa9d74982f2079edeb205ecdbef90 100644 --- a/arch/avr32/kernel/sys_avr32.c +++ b/arch/avr32/kernel/sys_avr32.c @@ -5,39 +5,8 @@ * 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 - -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, off_t offset) -{ - int error = -EBADF; - struct file *file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - return error; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, offset); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); - return error; -} - int kernel_execve(const char *file, char **argv, char **envp) { register long scno asm("r8") = __NR_execve; diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S index f7244cd02fbbf0b96fd31f56f40c47e14d61430b..0447a3e2ba64b773c108fb7f5db9935329fcbc21 100644 --- a/arch/avr32/kernel/syscall-stubs.S +++ b/arch/avr32/kernel/syscall-stubs.S @@ -61,7 +61,7 @@ __sys_execve: __sys_mmap2: pushm lr st.w --sp, ARG6 - call sys_mmap2 + call sys_mmap_pgoff sub sp, -4 popm pc diff --git a/arch/blackfin/include/asm/fcntl.h b/arch/blackfin/include/asm/fcntl.h index 8727b2b382f11207ae224b519a7a6da83aa109f7..251c911d59c1181efbbafbeaa94b37b2c7f08c08 100644 --- a/arch/blackfin/include/asm/fcntl.h +++ b/arch/blackfin/include/asm/fcntl.h @@ -7,8 +7,6 @@ #ifndef _BFIN_FCNTL_H #define _BFIN_FCNTL_H -/* open/fcntl - O_SYNC is only implemented on blocks devices and on files - located on an ext2 file system */ #define O_DIRECTORY 040000 /* must be a directory */ #define O_NOFOLLOW 0100000 /* don't follow links */ #define O_DIRECT 0200000 /* direct disk access hint - currently ignored */ diff --git a/arch/blackfin/kernel/sys_bfin.c b/arch/blackfin/kernel/sys_bfin.c index afcef129d4e843fb3c81b27253356f55c76bbc50..2e7f8e10bf87109083f43f73411327ae5223f724 100644 --- a/arch/blackfin/kernel/sys_bfin.c +++ b/arch/blackfin/kernel/sys_bfin.c @@ -22,39 +22,6 @@ #include #include -/* common code for old and new mmaps */ -static inline long -do_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file *file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); - out: - return error; -} - -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - return do_mmap2(addr, len, prot, flags, fd, pgoff); -} - asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags) { return sram_alloc_with_lsl(size, flags); diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index a50637a8b9bddb9c468c5615b2a0586f2224e03b..f3f8bb46b517d8f291633c8fda13195462731fe9 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -1422,7 +1422,7 @@ ENTRY(_sys_call_table) .long _sys_ni_syscall /* streams2 */ .long _sys_vfork /* 190 */ .long _sys_getrlimit - .long _sys_mmap2 + .long _sys_mmap_pgoff .long _sys_truncate64 .long _sys_ftruncate64 .long _sys_stat64 /* 195 */ diff --git a/arch/cris/kernel/sys_cris.c b/arch/cris/kernel/sys_cris.c index 2ad962c7e88ebaddcbc11ed7a3a88f3e2e900385..c2bbb1ac98a964b9ffaa2ae8454d8becda607712 100644 --- a/arch/cris/kernel/sys_cris.c +++ b/arch/cris/kernel/sys_cris.c @@ -26,31 +26,6 @@ #include #include -/* common code for old and new mmaps */ -static inline long -do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, - unsigned long flags, unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - asmlinkage unsigned long old_mmap(unsigned long __user *args) { unsigned long buffer[6]; @@ -63,7 +38,7 @@ asmlinkage unsigned long old_mmap(unsigned long __user *args) if (buffer[5] & ~PAGE_MASK) /* verify that offset is on page boundary */ goto out; - err = do_mmap2(buffer[0], buffer[1], buffer[2], buffer[3], + err = sys_mmap_pgoff(buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5] >> PAGE_SHIFT); out: return err; @@ -73,7 +48,8 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { - return do_mmap2(addr, len, prot, flags, fd, pgoff); + /* bug(?): 8Kb pages here */ + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); } /* diff --git a/arch/frv/kernel/sys_frv.c b/arch/frv/kernel/sys_frv.c index 2b6b5289cdccefbd2d5029d5da4e62ebdc989803..1d3d4c9e25218e13341ed77d3cc43e3e4f8586a6 100644 --- a/arch/frv/kernel/sys_frv.c +++ b/arch/frv/kernel/sys_frv.c @@ -31,9 +31,6 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { - int error = -EBADF; - struct file * file = NULL; - /* As with sparc32, make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE we have.... */ @@ -41,69 +38,10 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, trying to map something we can't */ if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1)) return -EINVAL; - pgoff >>= PAGE_SHIFT - 12; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - -#if 0 /* DAVIDM - do we want this */ -struct mmap_arg_struct64 { - __u32 addr; - __u32 len; - __u32 prot; - __u32 flags; - __u64 offset; /* 64 bits */ - __u32 fd; -}; - -asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg) -{ - int error = -EFAULT; - struct file * file = NULL; - struct mmap_arg_struct64 a; - unsigned long pgoff; - - if (copy_from_user(&a, arg, sizeof(a))) - return -EFAULT; - - if ((long)a.offset & ~PAGE_MASK) - return -EINVAL; - - pgoff = a.offset >> PAGE_SHIFT; - if ((a.offset >> PAGE_SHIFT) != pgoff) - return -EINVAL; - - if (!(a.flags & MAP_ANONYMOUS)) { - error = -EBADF; - file = fget(a.fd); - if (!file) - goto out; - } - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); -out: - return error; + return sys_mmap_pgoff(addr, len, prot, flags, fd, + pgoff >> (PAGE_SHIFT - 12)); } -#endif /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c index 8cb5d73a0e357cbc530b6d2a408c7a5b8065009b..b5969db0ca10fbe401dd5977b86482b59ba21b0e 100644 --- a/arch/h8300/kernel/sys_h8300.c +++ b/arch/h8300/kernel/sys_h8300.c @@ -26,39 +26,6 @@ #include #include -/* common code for old and new mmaps */ -static inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - return do_mmap2(addr, len, prot, flags, fd, pgoff); -} - /* * Perform the select(nd, in, out, ex, tv) and mmap() system * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to @@ -87,57 +54,11 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg) if (a.offset & ~PAGE_MASK) goto out; - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); -out: - return error; -} - -#if 0 /* DAVIDM - do we want this */ -struct mmap_arg_struct64 { - __u32 addr; - __u32 len; - __u32 prot; - __u32 flags; - __u64 offset; /* 64 bits */ - __u32 fd; -}; - -asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg) -{ - int error = -EFAULT; - struct file * file = NULL; - struct mmap_arg_struct64 a; - unsigned long pgoff; - - if (copy_from_user(&a, arg, sizeof(a))) - return -EFAULT; - - if ((long)a.offset & ~PAGE_MASK) - return -EINVAL; - - pgoff = a.offset >> PAGE_SHIFT; - if ((a.offset >> PAGE_SHIFT) != pgoff) - return -EINVAL; - - if (!(a.flags & MAP_ANONYMOUS)) { - error = -EBADF; - file = fget(a.fd); - if (!file) - goto out; - } - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, + a.offset >> PAGE_SHIFT); out: return error; } -#endif struct sel_arg_struct { unsigned long n; diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S index 4eb67faac6337878717224f9d39d292bc5712846..2d69881eda6ade4e9666500aeb110f7776d209a1 100644 --- a/arch/h8300/kernel/syscalls.S +++ b/arch/h8300/kernel/syscalls.S @@ -206,7 +206,7 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ .long SYMBOL_NAME(sys_vfork) /* 190 */ .long SYMBOL_NAME(sys_getrlimit) - .long SYMBOL_NAME(sys_mmap2) + .long SYMBOL_NAME(sys_mmap_pgoff) .long SYMBOL_NAME(sys_truncate64) .long SYMBOL_NAME(sys_ftruncate64) .long SYMBOL_NAME(sys_stat64) /* 195 */ diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 1ee596cd942ff8c3a3915b2428acacb206c1f6b8..2d7f56a98e0f484ce80d544223b4b9923526cb2a 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -87,9 +87,6 @@ config GENERIC_TIME_VSYSCALL bool default y -config HAVE_LEGACY_PER_CPU_AREA - def_bool y - config HAVE_SETUP_PER_CPU_AREA def_bool y diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 429ec968c9ee62178ffcc8c3afe1005510695eb1..045b746b98081e493b3ea85244cf10113c83126a 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -858,6 +858,9 @@ ia32_do_mmap (struct file *file, unsigned long addr, unsigned long len, int prot prot = get_prot32(prot); + if (flags & MAP_HUGETLB) + return -ENOMEM; + #if PAGE_SHIFT > IA32_PAGE_SHIFT mutex_lock(&ia32_mmap_mutex); { diff --git a/arch/ia64/include/asm/meminit.h b/arch/ia64/include/asm/meminit.h index 688a812c017d64c1f5c9763012ecac75d7b00f0e..61c7b1750b169f33ccb544b5cb83c83e1dd432ee 100644 --- a/arch/ia64/include/asm/meminit.h +++ b/arch/ia64/include/asm/meminit.h @@ -61,7 +61,7 @@ extern int register_active_ranges(u64 start, u64 len, int nid); #ifdef CONFIG_VIRTUAL_MEM_MAP # define LARGE_GAP 0x40000000 /* Use virtual mem map if hole is > than this */ - extern unsigned long vmalloc_end; + extern unsigned long VMALLOC_END; extern struct page *vmem_map; extern int find_largest_hole(u64 start, u64 end, void *arg); extern int create_mem_map_page_table(u64 start, u64 end, void *arg); diff --git a/arch/ia64/include/asm/pgtable.h b/arch/ia64/include/asm/pgtable.h index 8840a690d1e7aa346b82fc68672186631c2e0828..69bf13857a9fc8ac9ff07e73a24436c17af19adb 100644 --- a/arch/ia64/include/asm/pgtable.h +++ b/arch/ia64/include/asm/pgtable.h @@ -228,8 +228,7 @@ ia64_phys_addr_valid (unsigned long addr) #define VMALLOC_START (RGN_BASE(RGN_GATE) + 0x200000000UL) #ifdef CONFIG_VIRTUAL_MEM_MAP # define VMALLOC_END_INIT (RGN_BASE(RGN_GATE) + (1UL << (4*PAGE_SHIFT - 9))) -# define VMALLOC_END vmalloc_end - extern unsigned long vmalloc_end; +extern unsigned long VMALLOC_END; #else #if defined(CONFIG_SPARSEMEM) && defined(CONFIG_SPARSEMEM_VMEMMAP) /* SPARSEMEM_VMEMMAP uses half of vmalloc... */ diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h index 3eaeedf1aef2cf20d5a8c707d64ddd34746c18b2..7fa90f73f6be37757e3a36ed46c85ac3ede3df77 100644 --- a/arch/ia64/include/asm/processor.h +++ b/arch/ia64/include/asm/processor.h @@ -229,7 +229,7 @@ struct cpuinfo_ia64 { #endif }; -DECLARE_PER_CPU(struct cpuinfo_ia64, cpu_info); +DECLARE_PER_CPU(struct cpuinfo_ia64, ia64_cpu_info); /* * The "local" data variable. It refers to the per-CPU data of the currently executing @@ -237,8 +237,8 @@ DECLARE_PER_CPU(struct cpuinfo_ia64, cpu_info); * Do not use the address of local_cpu_data, since it will be different from * cpu_data(smp_processor_id())! */ -#define local_cpu_data (&__ia64_per_cpu_var(cpu_info)) -#define cpu_data(cpu) (&per_cpu(cpu_info, cpu)) +#define local_cpu_data (&__ia64_per_cpu_var(ia64_cpu_info)) +#define cpu_data(cpu) (&per_cpu(ia64_cpu_info, cpu)) extern void print_cpu_info (struct cpuinfo_ia64 *); diff --git a/arch/ia64/include/asm/xen/hypervisor.h b/arch/ia64/include/asm/xen/hypervisor.h index 88afb54501e48feba6c24d6f25c7f5967b308c89..67455c2ed2b12d85acbaf1087da08d4e57739f76 100644 --- a/arch/ia64/include/asm/xen/hypervisor.h +++ b/arch/ia64/include/asm/xen/hypervisor.h @@ -37,35 +37,9 @@ #include #include /* to compile feature.c */ #include /* to comiple xen-netfront.c */ +#include #include -/* xen_domain_type is set before executing any C code by early_xen_setup */ -enum xen_domain_type { - XEN_NATIVE, /* running on bare hardware */ - XEN_PV_DOMAIN, /* running in a PV domain */ - XEN_HVM_DOMAIN, /* running in a Xen hvm domain*/ -}; - -#ifdef CONFIG_XEN -extern enum xen_domain_type xen_domain_type; -#else -#define xen_domain_type XEN_NATIVE -#endif - -#define xen_domain() (xen_domain_type != XEN_NATIVE) -#define xen_pv_domain() (xen_domain() && \ - xen_domain_type == XEN_PV_DOMAIN) -#define xen_hvm_domain() (xen_domain() && \ - xen_domain_type == XEN_HVM_DOMAIN) - -#ifdef CONFIG_XEN_DOM0 -#define xen_initial_domain() (xen_pv_domain() && \ - (xen_start_info->flags & SIF_INITDOMAIN)) -#else -#define xen_initial_domain() (0) -#endif - - #ifdef CONFIG_XEN extern struct shared_info *HYPERVISOR_shared_info; extern struct start_info *xen_start_info; diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index baec6f00f7f3feee71c5110b01f12b5c8b3f4fda..40574ae114018e4db5efce7fc499435c4c863eec 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -702,11 +702,23 @@ int __init early_acpi_boot_init(void) printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries\n"); +#ifdef CONFIG_SMP + if (available_cpus == 0) { + printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n"); + printk(KERN_INFO "CPU 0 (0x%04x)", hard_smp_processor_id()); + smp_boot_data.cpu_phys_id[available_cpus] = + hard_smp_processor_id(); + available_cpus = 1; /* We've got at least one of these, no? */ + } + smp_boot_data.cpu_count = available_cpus; +#endif + /* Make boot-up look pretty */ + printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, + total_cpus); + return 0; } - - int __init acpi_boot_init(void) { @@ -769,18 +781,8 @@ int __init acpi_boot_init(void) if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt)) printk(KERN_ERR PREFIX "Can't find FADT\n"); +#ifdef CONFIG_ACPI_NUMA #ifdef CONFIG_SMP - if (available_cpus == 0) { - printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n"); - printk(KERN_INFO "CPU 0 (0x%04x)", hard_smp_processor_id()); - smp_boot_data.cpu_phys_id[available_cpus] = - hard_smp_processor_id(); - available_cpus = 1; /* We've got at least one of these, no? */ - } - smp_boot_data.cpu_count = available_cpus; - - smp_build_cpu_map(); -# ifdef CONFIG_ACPI_NUMA if (srat_num_cpus == 0) { int cpu, i = 1; for (cpu = 0; cpu < smp_boot_data.cpu_count; cpu++) @@ -789,14 +791,9 @@ int __init acpi_boot_init(void) node_cpuid[i++].phys_id = smp_boot_data.cpu_phys_id[cpu]; } -# endif #endif -#ifdef CONFIG_ACPI_NUMA build_cpu_to_node_map(); #endif - /* Make boot-up look pretty */ - printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, - total_cpus); return 0; } diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index 696eff28a0c44c477465314a4c3ee5daa71b4198..17a9fba38930ab0504aa7b17262765af117c2740 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -1051,7 +1051,7 @@ END(ia64_delay_loop) * intermediate precision so that we can produce a full 64-bit result. */ GLOBAL_ENTRY(ia64_native_sched_clock) - addl r8=THIS_CPU(cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0 + addl r8=THIS_CPU(ia64_cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0 mov.m r9=ar.itc // fetch cycle-counter (35 cyc) ;; ldf8 f8=[r8] @@ -1077,7 +1077,7 @@ sched_clock = ia64_native_sched_clock #ifdef CONFIG_VIRT_CPU_ACCOUNTING GLOBAL_ENTRY(cycle_to_cputime) alloc r16=ar.pfs,1,0,0,0 - addl r8=THIS_CPU(cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0 + addl r8=THIS_CPU(ia64_cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0 ;; ldf8 f8=[r8] ;; diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c index 14d39e3006274fb054382505d8f0ba32959c6cb8..461b99902bf6ff2f703029c6fed6463271584048 100644 --- a/arch/ia64/kernel/ia64_ksyms.c +++ b/arch/ia64/kernel/ia64_ksyms.c @@ -30,7 +30,7 @@ EXPORT_SYMBOL(max_low_pfn); /* defined by bootmem.c, but not exported by generic #endif #include -EXPORT_SYMBOL(per_cpu__cpu_info); +EXPORT_SYMBOL(per_cpu__ia64_cpu_info); #ifdef CONFIG_SMP EXPORT_SYMBOL(per_cpu__local_per_cpu_offset); #endif diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index 7461d2573d41106191fe7b7a42d7cfe2d370a9bf..d5bdf9de36b6362f81a039b4494f0fa657497e87 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S @@ -59,7 +59,7 @@ ia64_do_tlb_purge: #define O(member) IA64_CPUINFO_##member##_OFFSET - GET_THIS_PADDR(r2, cpu_info) // load phys addr of cpu_info into r2 + GET_THIS_PADDR(r2, ia64_cpu_info) // load phys addr of cpu_info into r2 ;; addl r17=O(PTCE_STRIDE),r2 addl r2=O(PTCE_BASE),r2 diff --git a/arch/ia64/kernel/relocate_kernel.S b/arch/ia64/kernel/relocate_kernel.S index 32f6fc131fbe2946831ee4eb2ef15d2f35bf132e..c370e02f0061fbf8414457b16dd342fbd5201872 100644 --- a/arch/ia64/kernel/relocate_kernel.S +++ b/arch/ia64/kernel/relocate_kernel.S @@ -61,7 +61,7 @@ GLOBAL_ENTRY(relocate_new_kernel) // purge all TC entries #define O(member) IA64_CPUINFO_##member##_OFFSET - GET_THIS_PADDR(r2, cpu_info) // load phys addr of cpu_info into r2 + GET_THIS_PADDR(r2, ia64_cpu_info) // load phys addr of cpu_info into r2 ;; addl r17=O(PTCE_STRIDE),r2 addl r2=O(PTCE_BASE),r2 diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 1de86c96801d60fe81ae2d6fc4930bdfdc190c45..a1ea879197770a2347ccff6ac0049146937d1ca9 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -74,7 +74,7 @@ unsigned long __per_cpu_offset[NR_CPUS]; EXPORT_SYMBOL(__per_cpu_offset); #endif -DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info); +DEFINE_PER_CPU(struct cpuinfo_ia64, ia64_cpu_info); DEFINE_PER_CPU(unsigned long, local_per_cpu_offset); unsigned long ia64_cycles_per_usec; struct ia64_boot_param *ia64_boot_param; @@ -566,19 +566,18 @@ setup_arch (char **cmdline_p) early_acpi_boot_init(); # ifdef CONFIG_ACPI_NUMA acpi_numa_init(); -#ifdef CONFIG_ACPI_HOTPLUG_CPU +# ifdef CONFIG_ACPI_HOTPLUG_CPU prefill_possible_map(); -#endif +# endif per_cpu_scan_finalize((cpus_weight(early_cpu_possible_map) == 0 ? 32 : cpus_weight(early_cpu_possible_map)), additional_cpus > 0 ? additional_cpus : 0); # endif -#else -# ifdef CONFIG_SMP - smp_build_cpu_map(); /* happens, e.g., with the Ski simulator */ -# endif #endif /* CONFIG_APCI_BOOT */ +#ifdef CONFIG_SMP + smp_build_cpu_map(); +#endif find_memory(); /* process SAL system table: */ @@ -855,18 +854,6 @@ identify_cpu (struct cpuinfo_ia64 *c) c->unimpl_pa_mask = ~((1L<<63) | ((1L << phys_addr_size) - 1)); } -/* - * In UP configuration, setup_per_cpu_areas() is defined in - * include/linux/percpu.h - */ -#ifdef CONFIG_SMP -void __init -setup_per_cpu_areas (void) -{ - /* start_kernel() requires this... */ -} -#endif - /* * Do the following calculations: * @@ -980,7 +967,7 @@ cpu_init (void) * depends on the data returned by identify_cpu(). We break the dependency by * accessing cpu_data() through the canonical per-CPU address. */ - cpu_info = cpu_data + ((char *) &__ia64_per_cpu_var(cpu_info) - __per_cpu_start); + cpu_info = cpu_data + ((char *) &__ia64_per_cpu_var(ia64_cpu_info) - __per_cpu_start); identify_cpu(cpu_info); #ifdef CONFIG_MCKINLEY diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c index 92ed83f34036f0b52cccc36a529bb48bdbd5127d..609d50056a6c7bd9fba2d46b757960b3e8893388 100644 --- a/arch/ia64/kernel/sys_ia64.c +++ b/arch/ia64/kernel/sys_ia64.c @@ -100,51 +100,7 @@ sys_getpagesize (void) asmlinkage unsigned long ia64_brk (unsigned long brk) { - unsigned long rlim, retval, newbrk, oldbrk; - struct mm_struct *mm = current->mm; - - /* - * Most of this replicates the code in sys_brk() except for an additional safety - * check and the clearing of r8. However, we can't call sys_brk() because we need - * to acquire the mmap_sem before we can do the test... - */ - down_write(&mm->mmap_sem); - - if (brk < mm->end_code) - goto out; - newbrk = PAGE_ALIGN(brk); - oldbrk = PAGE_ALIGN(mm->brk); - if (oldbrk == newbrk) - goto set_brk; - - /* Always allow shrinking brk. */ - if (brk <= mm->brk) { - if (!do_munmap(mm, newbrk, oldbrk-newbrk)) - goto set_brk; - goto out; - } - - /* Check against unimplemented/unmapped addresses: */ - if ((newbrk - oldbrk) > RGN_MAP_LIMIT || REGION_OFFSET(newbrk) > RGN_MAP_LIMIT) - goto out; - - /* Check against rlimit.. */ - rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; - if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim) - goto out; - - /* Check against existing mmap mappings. */ - if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE)) - goto out; - - /* Ok, looks good - let it rip. */ - if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk) - goto out; -set_brk: - mm->brk = brk; -out: - retval = mm->brk; - up_write(&mm->mmap_sem); + unsigned long retval = sys_brk(brk); force_successful_syscall_return(); return retval; } @@ -185,39 +141,6 @@ int ia64_mmap_check(unsigned long addr, unsigned long len, return 0; } -static inline unsigned long -do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff) -{ - struct file *file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - return -EBADF; - - if (!file->f_op || !file->f_op->mmap) { - addr = -ENODEV; - goto out; - } - } - - /* Careful about overflows.. */ - len = PAGE_ALIGN(len); - if (!len || len > TASK_SIZE) { - addr = -EINVAL; - goto out; - } - - down_write(¤t->mm->mmap_sem); - addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - -out: if (file) - fput(file); - return addr; -} - /* * mmap2() is like mmap() except that the offset is expressed in units * of PAGE_SIZE (instead of bytes). This allows to mmap2() (pieces @@ -226,7 +149,7 @@ out: if (file) asmlinkage unsigned long sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff) { - addr = do_mmap2(addr, len, prot, flags, fd, pgoff); + addr = sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); if (!IS_ERR((void *) addr)) force_successful_syscall_return(); return addr; @@ -238,7 +161,7 @@ sys_mmap (unsigned long addr, unsigned long len, int prot, int flags, int fd, lo if (offset_in_page(off) != 0) return -EINVAL; - addr = do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT); + addr = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); if (!IS_ERR((void *) addr)) force_successful_syscall_return(); return addr; diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 0a0c77b2c9881cd01c9766b203ac0af7adefc95d..1295ba327f6ff2728f422079aedd6090bc51013b 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S @@ -166,6 +166,12 @@ SECTIONS } #endif +#ifdef CONFIG_SMP + . = ALIGN(PERCPU_PAGE_SIZE); + __cpu0_per_cpu = .; + . = . + PERCPU_PAGE_SIZE; /* cpu0 per-cpu space */ +#endif + . = ALIGN(PAGE_SIZE); __init_end = .; @@ -198,11 +204,6 @@ SECTIONS data : { } :data .data : AT(ADDR(.data) - LOAD_OFFSET) { -#ifdef CONFIG_SMP - . = ALIGN(PERCPU_PAGE_SIZE); - __cpu0_per_cpu = .; - . = . + PERCPU_PAGE_SIZE; /* cpu0 per-cpu space */ -#endif INIT_TASK_DATA(PAGE_SIZE) CACHELINE_ALIGNED_DATA(SMP_CACHE_BYTES) READ_MOSTLY_DATA(SMP_CACHE_BYTES) diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index 2f724d2bf2995d42251ed223bcca86ce2db21131..54bf540598118339a04919e1f08c505a5ad57cd8 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -154,38 +154,99 @@ static void *cpu_data; void * __cpuinit per_cpu_init (void) { - int cpu; - static int first_time=1; + static bool first_time = true; + void *cpu0_data = __cpu0_per_cpu; + unsigned int cpu; + + if (!first_time) + goto skip; + first_time = false; /* - * get_free_pages() cannot be used before cpu_init() done. BSP - * allocates "NR_CPUS" pages for all CPUs to avoid that AP calls - * get_zeroed_page(). + * get_free_pages() cannot be used before cpu_init() done. + * BSP allocates PERCPU_PAGE_SIZE bytes for all possible CPUs + * to avoid that AP calls get_zeroed_page(). */ - if (first_time) { - void *cpu0_data = __cpu0_per_cpu; + for_each_possible_cpu(cpu) { + void *src = cpu == 0 ? cpu0_data : __phys_per_cpu_start; - first_time=0; + memcpy(cpu_data, src, __per_cpu_end - __per_cpu_start); + __per_cpu_offset[cpu] = (char *)cpu_data - __per_cpu_start; + per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; - __per_cpu_offset[0] = (char *) cpu0_data - __per_cpu_start; - per_cpu(local_per_cpu_offset, 0) = __per_cpu_offset[0]; + /* + * percpu area for cpu0 is moved from the __init area + * which is setup by head.S and used till this point. + * Update ar.k3. This move is ensures that percpu + * area for cpu0 is on the correct node and its + * virtual address isn't insanely far from other + * percpu areas which is important for congruent + * percpu allocator. + */ + if (cpu == 0) + ia64_set_kr(IA64_KR_PER_CPU_DATA, __pa(cpu_data) - + (unsigned long)__per_cpu_start); - for (cpu = 1; cpu < NR_CPUS; cpu++) { - memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); - __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start; - cpu_data += PERCPU_PAGE_SIZE; - per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; - } + cpu_data += PERCPU_PAGE_SIZE; } +skip: return __per_cpu_start + __per_cpu_offset[smp_processor_id()]; } static inline void alloc_per_cpu_data(void) { - cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS-1, + cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * num_possible_cpus(), PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); } + +/** + * setup_per_cpu_areas - setup percpu areas + * + * Arch code has already allocated and initialized percpu areas. All + * this function has to do is to teach the determined layout to the + * dynamic percpu allocator, which happens to be more complex than + * creating whole new ones using helpers. + */ +void __init +setup_per_cpu_areas(void) +{ + struct pcpu_alloc_info *ai; + struct pcpu_group_info *gi; + unsigned int cpu; + ssize_t static_size, reserved_size, dyn_size; + int rc; + + ai = pcpu_alloc_alloc_info(1, num_possible_cpus()); + if (!ai) + panic("failed to allocate pcpu_alloc_info"); + gi = &ai->groups[0]; + + /* units are assigned consecutively to possible cpus */ + for_each_possible_cpu(cpu) + gi->cpu_map[gi->nr_units++] = cpu; + + /* set parameters */ + static_size = __per_cpu_end - __per_cpu_start; + reserved_size = PERCPU_MODULE_RESERVE; + dyn_size = PERCPU_PAGE_SIZE - static_size - reserved_size; + if (dyn_size < 0) + panic("percpu area overflow static=%zd reserved=%zd\n", + static_size, reserved_size); + + ai->static_size = static_size; + ai->reserved_size = reserved_size; + ai->dyn_size = dyn_size; + ai->unit_size = PERCPU_PAGE_SIZE; + ai->atom_size = PAGE_SIZE; + ai->alloc_size = PERCPU_PAGE_SIZE; + + rc = pcpu_setup_first_chunk(ai, __per_cpu_start + __per_cpu_offset[0]); + if (rc) + panic("failed to setup percpu area (err=%d)", rc); + + pcpu_free_alloc_info(ai); +} #else #define alloc_per_cpu_data() do { } while (0) #endif /* CONFIG_SMP */ @@ -270,8 +331,8 @@ paging_init (void) map_size = PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) * sizeof(struct page)); - vmalloc_end -= map_size; - vmem_map = (struct page *) vmalloc_end; + VMALLOC_END -= map_size; + vmem_map = (struct page *) VMALLOC_END; efi_memmap_walk(create_mem_map_page_table, NULL); /* diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index d85ba98d90087dea812636768a2f223e6a940fdf..19c4b2195dceef1af966bccf388c432050b1f3e3 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -143,22 +143,120 @@ static void *per_cpu_node_setup(void *cpu_data, int node) int cpu; for_each_possible_early_cpu(cpu) { - if (cpu == 0) { - void *cpu0_data = __cpu0_per_cpu; - __per_cpu_offset[cpu] = (char*)cpu0_data - - __per_cpu_start; - } else if (node == node_cpuid[cpu].nid) { - memcpy(__va(cpu_data), __phys_per_cpu_start, - __per_cpu_end - __per_cpu_start); - __per_cpu_offset[cpu] = (char*)__va(cpu_data) - - __per_cpu_start; - cpu_data += PERCPU_PAGE_SIZE; - } + void *src = cpu == 0 ? __cpu0_per_cpu : __phys_per_cpu_start; + + if (node != node_cpuid[cpu].nid) + continue; + + memcpy(__va(cpu_data), src, __per_cpu_end - __per_cpu_start); + __per_cpu_offset[cpu] = (char *)__va(cpu_data) - + __per_cpu_start; + + /* + * percpu area for cpu0 is moved from the __init area + * which is setup by head.S and used till this point. + * Update ar.k3. This move is ensures that percpu + * area for cpu0 is on the correct node and its + * virtual address isn't insanely far from other + * percpu areas which is important for congruent + * percpu allocator. + */ + if (cpu == 0) + ia64_set_kr(IA64_KR_PER_CPU_DATA, + (unsigned long)cpu_data - + (unsigned long)__per_cpu_start); + + cpu_data += PERCPU_PAGE_SIZE; } #endif return cpu_data; } +#ifdef CONFIG_SMP +/** + * setup_per_cpu_areas - setup percpu areas + * + * Arch code has already allocated and initialized percpu areas. All + * this function has to do is to teach the determined layout to the + * dynamic percpu allocator, which happens to be more complex than + * creating whole new ones using helpers. + */ +void __init setup_per_cpu_areas(void) +{ + struct pcpu_alloc_info *ai; + struct pcpu_group_info *uninitialized_var(gi); + unsigned int *cpu_map; + void *base; + unsigned long base_offset; + unsigned int cpu; + ssize_t static_size, reserved_size, dyn_size; + int node, prev_node, unit, nr_units, rc; + + ai = pcpu_alloc_alloc_info(MAX_NUMNODES, nr_cpu_ids); + if (!ai) + panic("failed to allocate pcpu_alloc_info"); + cpu_map = ai->groups[0].cpu_map; + + /* determine base */ + base = (void *)ULONG_MAX; + for_each_possible_cpu(cpu) + base = min(base, + (void *)(__per_cpu_offset[cpu] + __per_cpu_start)); + base_offset = (void *)__per_cpu_start - base; + + /* build cpu_map, units are grouped by node */ + unit = 0; + for_each_node(node) + for_each_possible_cpu(cpu) + if (node == node_cpuid[cpu].nid) + cpu_map[unit++] = cpu; + nr_units = unit; + + /* set basic parameters */ + static_size = __per_cpu_end - __per_cpu_start; + reserved_size = PERCPU_MODULE_RESERVE; + dyn_size = PERCPU_PAGE_SIZE - static_size - reserved_size; + if (dyn_size < 0) + panic("percpu area overflow static=%zd reserved=%zd\n", + static_size, reserved_size); + + ai->static_size = static_size; + ai->reserved_size = reserved_size; + ai->dyn_size = dyn_size; + ai->unit_size = PERCPU_PAGE_SIZE; + ai->atom_size = PAGE_SIZE; + ai->alloc_size = PERCPU_PAGE_SIZE; + + /* + * CPUs are put into groups according to node. Walk cpu_map + * and create new groups at node boundaries. + */ + prev_node = -1; + ai->nr_groups = 0; + for (unit = 0; unit < nr_units; unit++) { + cpu = cpu_map[unit]; + node = node_cpuid[cpu].nid; + + if (node == prev_node) { + gi->nr_units++; + continue; + } + prev_node = node; + + gi = &ai->groups[ai->nr_groups++]; + gi->nr_units = 1; + gi->base_offset = __per_cpu_offset[cpu] + base_offset; + gi->cpu_map = &cpu_map[unit]; + } + + rc = pcpu_setup_first_chunk(ai, base); + if (rc) + panic("failed to setup percpu area (err=%d)", rc); + + pcpu_free_alloc_info(ai); +} +#endif + /** * fill_pernode - initialize pernode data. * @node: the node id. @@ -352,7 +450,8 @@ static void __init initialize_pernode_data(void) /* Set the node_data pointer for each per-cpu struct */ for_each_possible_early_cpu(cpu) { node = node_cpuid[cpu].nid; - per_cpu(cpu_info, cpu).node_data = mem_data[node].node_data; + per_cpu(ia64_cpu_info, cpu).node_data = + mem_data[node].node_data; } #else { @@ -360,7 +459,7 @@ static void __init initialize_pernode_data(void) cpu = 0; node = node_cpuid[cpu].nid; cpu0_cpu_info = (struct cpuinfo_ia64 *)(__phys_per_cpu_start + - ((char *)&per_cpu__cpu_info - __per_cpu_start)); + ((char *)&per_cpu__ia64_cpu_info - __per_cpu_start)); cpu0_cpu_info->node_data = mem_data[node].node_data; } #endif /* CONFIG_SMP */ @@ -666,9 +765,9 @@ void __init paging_init(void) sparse_init(); #ifdef CONFIG_VIRTUAL_MEM_MAP - vmalloc_end -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) * + VMALLOC_END -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) * sizeof(struct page)); - vmem_map = (struct page *) vmalloc_end; + vmem_map = (struct page *) VMALLOC_END; efi_memmap_walk(create_mem_map_page_table, NULL); printk("Virtual mem_map starts at 0x%p\n", vmem_map); #endif diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 1857766a63c1850d968320559471c22a851b6335..b9609c69343a373f5e742be333bcac7d24cf4381 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -44,8 +44,8 @@ extern void ia64_tlb_init (void); unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL; #ifdef CONFIG_VIRTUAL_MEM_MAP -unsigned long vmalloc_end = VMALLOC_END_INIT; -EXPORT_SYMBOL(vmalloc_end); +unsigned long VMALLOC_END = VMALLOC_END_INIT; +EXPORT_SYMBOL(VMALLOC_END); struct page *vmem_map; EXPORT_SYMBOL(vmem_map); #endif diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index c0fca2c1c858372493675695f9a5341200c139ae..df639db779f95192a71d93d5895113080b1bf41a 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -131,6 +131,7 @@ alloc_pci_controller (int seg) } struct pci_root_info { + struct acpi_device *bridge; struct pci_controller *controller; char *name; }; @@ -297,9 +298,20 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) window->offset = offset; if (insert_resource(root, &window->resource)) { - printk(KERN_ERR "alloc 0x%llx-0x%llx from %s for %s failed\n", - window->resource.start, window->resource.end, - root->name, info->name); + dev_err(&info->bridge->dev, + "can't allocate host bridge window %pR\n", + &window->resource); + } else { + if (offset) + dev_info(&info->bridge->dev, "host bridge window %pR " + "(PCI address [%#llx-%#llx])\n", + &window->resource, + window->resource.start - offset, + window->resource.end - offset); + else + dev_info(&info->bridge->dev, + "host bridge window %pR\n", + &window->resource); } return AE_OK; @@ -319,8 +331,9 @@ pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl) (res->end - res->start < 16)) continue; if (j >= PCI_BUS_NUM_RESOURCES) { - printk("Ignoring range [%#llx-%#llx] (%lx)\n", - res->start, res->end, res->flags); + dev_warn(&bus->dev, + "ignoring host bridge window %pR (no space)\n", + res); continue; } bus->resource[j++] = res; @@ -364,6 +377,7 @@ pci_acpi_scan_root(struct acpi_device *device, int domain, int bus) goto out3; sprintf(name, "PCI Bus %04x:%02x", domain, bus); + info.bridge = device; info.controller = controller; info.name = name; acpi_walk_resources(device->handle, METHOD_NAME__CRS, @@ -720,9 +734,6 @@ int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size) return ret; } -/* It's defined in drivers/pci/pci.c */ -extern u8 pci_cache_line_size; - /** * set_pci_cacheline_size - determine cacheline size for PCI devices * @@ -731,7 +742,7 @@ extern u8 pci_cache_line_size; * * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info(). */ -static void __init set_pci_cacheline_size(void) +static void __init set_pci_dfl_cacheline_size(void) { unsigned long levels, unique_caches; long status; @@ -751,7 +762,7 @@ static void __init set_pci_cacheline_size(void) "(status=%ld)\n", __func__, status); return; } - pci_cache_line_size = (1 << cci.pcci_line_size) / 4; + pci_dfl_cache_line_size = (1 << cci.pcci_line_size) / 4; } u64 ia64_dma_get_required_mask(struct device *dev) @@ -782,7 +793,7 @@ EXPORT_SYMBOL_GPL(dma_get_required_mask); static int __init pcibios_init(void) { - set_pci_cacheline_size(); + set_pci_dfl_cacheline_size(); return 0; } diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 1176506b2baeb780e5cad3ba08cb533c54a801d8..e884ba4e031de4d1550cc2811a52a5a2c182db42 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -496,13 +496,13 @@ static int sn2_ptc_seq_show(struct seq_file *file, void *data) seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed, stat->deadlocks, - 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, - 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, - 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec, + 1000 * stat->lock_itc_clocks / per_cpu(ia64_cpu_info, cpu).cyc_per_usec, + 1000 * stat->shub_itc_clocks / per_cpu(ia64_cpu_info, cpu).cyc_per_usec, + 1000 * stat->shub_itc_clocks_max / per_cpu(ia64_cpu_info, cpu).cyc_per_usec, stat->shub_ptc_flushes_not_my_mm, stat->deadlocks2, stat->shub_ipi_flushes, - 1000 * stat->shub_ipi_flushes_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec); + 1000 * stat->shub_ipi_flushes_itc_clocks / per_cpu(ia64_cpu_info, cpu).cyc_per_usec); } return 0; } diff --git a/arch/ia64/xen/irq_xen.c b/arch/ia64/xen/irq_xen.c index f042e192d2feadd4f32c0188154920771d225fae..a3fb7cf9ae1db1664217a7f7bd915b597ebeb483 100644 --- a/arch/ia64/xen/irq_xen.c +++ b/arch/ia64/xen/irq_xen.c @@ -63,19 +63,19 @@ xen_free_irq_vector(int vector) } -static DEFINE_PER_CPU(int, timer_irq) = -1; -static DEFINE_PER_CPU(int, ipi_irq) = -1; -static DEFINE_PER_CPU(int, resched_irq) = -1; -static DEFINE_PER_CPU(int, cmc_irq) = -1; -static DEFINE_PER_CPU(int, cmcp_irq) = -1; -static DEFINE_PER_CPU(int, cpep_irq) = -1; +static DEFINE_PER_CPU(int, xen_timer_irq) = -1; +static DEFINE_PER_CPU(int, xen_ipi_irq) = -1; +static DEFINE_PER_CPU(int, xen_resched_irq) = -1; +static DEFINE_PER_CPU(int, xen_cmc_irq) = -1; +static DEFINE_PER_CPU(int, xen_cmcp_irq) = -1; +static DEFINE_PER_CPU(int, xen_cpep_irq) = -1; #define NAME_SIZE 15 -static DEFINE_PER_CPU(char[NAME_SIZE], timer_name); -static DEFINE_PER_CPU(char[NAME_SIZE], ipi_name); -static DEFINE_PER_CPU(char[NAME_SIZE], resched_name); -static DEFINE_PER_CPU(char[NAME_SIZE], cmc_name); -static DEFINE_PER_CPU(char[NAME_SIZE], cmcp_name); -static DEFINE_PER_CPU(char[NAME_SIZE], cpep_name); +static DEFINE_PER_CPU(char[NAME_SIZE], xen_timer_name); +static DEFINE_PER_CPU(char[NAME_SIZE], xen_ipi_name); +static DEFINE_PER_CPU(char[NAME_SIZE], xen_resched_name); +static DEFINE_PER_CPU(char[NAME_SIZE], xen_cmc_name); +static DEFINE_PER_CPU(char[NAME_SIZE], xen_cmcp_name); +static DEFINE_PER_CPU(char[NAME_SIZE], xen_cpep_name); #undef NAME_SIZE struct saved_irq { @@ -144,64 +144,64 @@ __xen_register_percpu_irq(unsigned int cpu, unsigned int vec, if (xen_slab_ready) { switch (vec) { case IA64_TIMER_VECTOR: - snprintf(per_cpu(timer_name, cpu), - sizeof(per_cpu(timer_name, cpu)), + snprintf(per_cpu(xen_timer_name, cpu), + sizeof(per_cpu(xen_timer_name, cpu)), "%s%d", action->name, cpu); irq = bind_virq_to_irqhandler(VIRQ_ITC, cpu, action->handler, action->flags, - per_cpu(timer_name, cpu), action->dev_id); - per_cpu(timer_irq, cpu) = irq; + per_cpu(xen_timer_name, cpu), action->dev_id); + per_cpu(xen_timer_irq, cpu) = irq; break; case IA64_IPI_RESCHEDULE: - snprintf(per_cpu(resched_name, cpu), - sizeof(per_cpu(resched_name, cpu)), + snprintf(per_cpu(xen_resched_name, cpu), + sizeof(per_cpu(xen_resched_name, cpu)), "%s%d", action->name, cpu); irq = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, cpu, action->handler, action->flags, - per_cpu(resched_name, cpu), action->dev_id); - per_cpu(resched_irq, cpu) = irq; + per_cpu(xen_resched_name, cpu), action->dev_id); + per_cpu(xen_resched_irq, cpu) = irq; break; case IA64_IPI_VECTOR: - snprintf(per_cpu(ipi_name, cpu), - sizeof(per_cpu(ipi_name, cpu)), + snprintf(per_cpu(xen_ipi_name, cpu), + sizeof(per_cpu(xen_ipi_name, cpu)), "%s%d", action->name, cpu); irq = bind_ipi_to_irqhandler(XEN_IPI_VECTOR, cpu, action->handler, action->flags, - per_cpu(ipi_name, cpu), action->dev_id); - per_cpu(ipi_irq, cpu) = irq; + per_cpu(xen_ipi_name, cpu), action->dev_id); + per_cpu(xen_ipi_irq, cpu) = irq; break; case IA64_CMC_VECTOR: - snprintf(per_cpu(cmc_name, cpu), - sizeof(per_cpu(cmc_name, cpu)), + snprintf(per_cpu(xen_cmc_name, cpu), + sizeof(per_cpu(xen_cmc_name, cpu)), "%s%d", action->name, cpu); irq = bind_virq_to_irqhandler(VIRQ_MCA_CMC, cpu, - action->handler, - action->flags, - per_cpu(cmc_name, cpu), - action->dev_id); - per_cpu(cmc_irq, cpu) = irq; + action->handler, + action->flags, + per_cpu(xen_cmc_name, cpu), + action->dev_id); + per_cpu(xen_cmc_irq, cpu) = irq; break; case IA64_CMCP_VECTOR: - snprintf(per_cpu(cmcp_name, cpu), - sizeof(per_cpu(cmcp_name, cpu)), + snprintf(per_cpu(xen_cmcp_name, cpu), + sizeof(per_cpu(xen_cmcp_name, cpu)), "%s%d", action->name, cpu); irq = bind_ipi_to_irqhandler(XEN_CMCP_VECTOR, cpu, - action->handler, - action->flags, - per_cpu(cmcp_name, cpu), - action->dev_id); - per_cpu(cmcp_irq, cpu) = irq; + action->handler, + action->flags, + per_cpu(xen_cmcp_name, cpu), + action->dev_id); + per_cpu(xen_cmcp_irq, cpu) = irq; break; case IA64_CPEP_VECTOR: - snprintf(per_cpu(cpep_name, cpu), - sizeof(per_cpu(cpep_name, cpu)), + snprintf(per_cpu(xen_cpep_name, cpu), + sizeof(per_cpu(xen_cpep_name, cpu)), "%s%d", action->name, cpu); irq = bind_ipi_to_irqhandler(XEN_CPEP_VECTOR, cpu, - action->handler, - action->flags, - per_cpu(cpep_name, cpu), - action->dev_id); - per_cpu(cpep_irq, cpu) = irq; + action->handler, + action->flags, + per_cpu(xen_cpep_name, cpu), + action->dev_id); + per_cpu(xen_cpep_irq, cpu) = irq; break; case IA64_CPE_VECTOR: case IA64_MCA_RENDEZ_VECTOR: @@ -275,30 +275,33 @@ unbind_evtchn_callback(struct notifier_block *nfb, if (action == CPU_DEAD) { /* Unregister evtchn. */ - if (per_cpu(cpep_irq, cpu) >= 0) { - unbind_from_irqhandler(per_cpu(cpep_irq, cpu), NULL); - per_cpu(cpep_irq, cpu) = -1; + if (per_cpu(xen_cpep_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(xen_cpep_irq, cpu), + NULL); + per_cpu(xen_cpep_irq, cpu) = -1; } - if (per_cpu(cmcp_irq, cpu) >= 0) { - unbind_from_irqhandler(per_cpu(cmcp_irq, cpu), NULL); - per_cpu(cmcp_irq, cpu) = -1; + if (per_cpu(xen_cmcp_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(xen_cmcp_irq, cpu), + NULL); + per_cpu(xen_cmcp_irq, cpu) = -1; } - if (per_cpu(cmc_irq, cpu) >= 0) { - unbind_from_irqhandler(per_cpu(cmc_irq, cpu), NULL); - per_cpu(cmc_irq, cpu) = -1; + if (per_cpu(xen_cmc_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(xen_cmc_irq, cpu), NULL); + per_cpu(xen_cmc_irq, cpu) = -1; } - if (per_cpu(ipi_irq, cpu) >= 0) { - unbind_from_irqhandler(per_cpu(ipi_irq, cpu), NULL); - per_cpu(ipi_irq, cpu) = -1; + if (per_cpu(xen_ipi_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(xen_ipi_irq, cpu), NULL); + per_cpu(xen_ipi_irq, cpu) = -1; } - if (per_cpu(resched_irq, cpu) >= 0) { - unbind_from_irqhandler(per_cpu(resched_irq, cpu), - NULL); - per_cpu(resched_irq, cpu) = -1; + if (per_cpu(xen_resched_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu), + NULL); + per_cpu(xen_resched_irq, cpu) = -1; } - if (per_cpu(timer_irq, cpu) >= 0) { - unbind_from_irqhandler(per_cpu(timer_irq, cpu), NULL); - per_cpu(timer_irq, cpu) = -1; + if (per_cpu(xen_timer_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(xen_timer_irq, cpu), + NULL); + per_cpu(xen_timer_irq, cpu) = -1; } } return NOTIFY_OK; diff --git a/arch/ia64/xen/time.c b/arch/ia64/xen/time.c index dbeadb9c8e20550fd0e4a6ad4d2c84e7420430b9..c1c544513e8d0926a8a4bd879f0056240f067bb0 100644 --- a/arch/ia64/xen/time.c +++ b/arch/ia64/xen/time.c @@ -34,15 +34,15 @@ #include "../kernel/fsyscall_gtod_data.h" -DEFINE_PER_CPU(struct vcpu_runstate_info, runstate); -DEFINE_PER_CPU(unsigned long, processed_stolen_time); -DEFINE_PER_CPU(unsigned long, processed_blocked_time); +static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate); +static DEFINE_PER_CPU(unsigned long, xen_stolen_time); +static DEFINE_PER_CPU(unsigned long, xen_blocked_time); /* taken from i386/kernel/time-xen.c */ static void xen_init_missing_ticks_accounting(int cpu) { struct vcpu_register_runstate_memory_area area; - struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu); + struct vcpu_runstate_info *runstate = &per_cpu(xen_runstate, cpu); int rc; memset(runstate, 0, sizeof(*runstate)); @@ -52,8 +52,8 @@ static void xen_init_missing_ticks_accounting(int cpu) &area); WARN_ON(rc && rc != -ENOSYS); - per_cpu(processed_blocked_time, cpu) = runstate->time[RUNSTATE_blocked]; - per_cpu(processed_stolen_time, cpu) = runstate->time[RUNSTATE_runnable] + per_cpu(xen_blocked_time, cpu) = runstate->time[RUNSTATE_blocked]; + per_cpu(xen_stolen_time, cpu) = runstate->time[RUNSTATE_runnable] + runstate->time[RUNSTATE_offline]; } @@ -68,7 +68,7 @@ static void get_runstate_snapshot(struct vcpu_runstate_info *res) BUG_ON(preemptible()); - state = &__get_cpu_var(runstate); + state = &__get_cpu_var(xen_runstate); /* * The runstate info is always updated by the hypervisor on @@ -103,12 +103,12 @@ consider_steal_time(unsigned long new_itm) * This function just checks and reject this effect. */ if (!time_after_eq(runstate.time[RUNSTATE_blocked], - per_cpu(processed_blocked_time, cpu))) + per_cpu(xen_blocked_time, cpu))) blocked = 0; if (!time_after_eq(runstate.time[RUNSTATE_runnable] + runstate.time[RUNSTATE_offline], - per_cpu(processed_stolen_time, cpu))) + per_cpu(xen_stolen_time, cpu))) stolen = 0; if (!time_after(delta_itm + new_itm, ia64_get_itc())) @@ -147,8 +147,8 @@ consider_steal_time(unsigned long new_itm) } else { local_cpu_data->itm_next = delta_itm + new_itm; } - per_cpu(processed_stolen_time, cpu) += NS_PER_TICK * stolen; - per_cpu(processed_blocked_time, cpu) += NS_PER_TICK * blocked; + per_cpu(xen_stolen_time, cpu) += NS_PER_TICK * stolen; + per_cpu(xen_blocked_time, cpu) += NS_PER_TICK * blocked; } return delta_itm; } diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c index 305ac852bbed417dda77de7a9b100c6a401bc75d..d3c865c5a6bab95d1a79a9ca078e5bafceb3a2c5 100644 --- a/arch/m32r/kernel/sys_m32r.c +++ b/arch/m32r/kernel/sys_m32r.c @@ -76,30 +76,6 @@ asmlinkage int sys_tas(int __user *addr) return oldval; } -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file *file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. * diff --git a/arch/m32r/kernel/syscall_table.S b/arch/m32r/kernel/syscall_table.S index aa3bf4cfab37cd8b0f999ba5211baeef6ebae3c3..60536e271233c20a1401dc7ee09a70e9251f0d48 100644 --- a/arch/m32r/kernel/syscall_table.S +++ b/arch/m32r/kernel/syscall_table.S @@ -191,7 +191,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* streams2 */ .long sys_vfork /* 190 */ .long sys_getrlimit - .long sys_mmap2 + .long sys_mmap_pgoff .long sys_truncate64 .long sys_ftruncate64 .long sys_stat64 /* 195 */ diff --git a/arch/m68k/include/asm/pgtable_mm.h b/arch/m68k/include/asm/pgtable_mm.h index fe60e1abaee8900523cb827ea8d9ca1a410dcde8..aca0e28581c7733febbd2029a5c0a687f41b7485 100644 --- a/arch/m68k/include/asm/pgtable_mm.h +++ b/arch/m68k/include/asm/pgtable_mm.h @@ -83,9 +83,9 @@ #define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_END KMAP_START #else -extern unsigned long vmalloc_end; +extern unsigned long m68k_vmalloc_end; #define VMALLOC_START 0x0f800000 -#define VMALLOC_END vmalloc_end +#define VMALLOC_END m68k_vmalloc_end #endif /* CONFIG_SUN3 */ /* zero page used for uninitialized stuff */ diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index 7deb402bfc751c9ba7a77f13afdd2c904b02a7ae..218f441de667c6f5fb35de5d5caaefdeeb6f84fb 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c @@ -29,37 +29,16 @@ #include #include -/* common code for old and new mmaps */ -static inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { - return do_mmap2(addr, len, prot, flags, fd, pgoff); + /* + * This is wrong for sun3 - there PAGE_SIZE is 8Kb, + * so we need to shift the argument down by 1; m68k mmap64(3) + * (in libc) expects the last argument of mmap2 in 4Kb units. + */ + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); } /* @@ -90,57 +69,11 @@ asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) if (a.offset & ~PAGE_MASK) goto out; - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); -out: - return error; -} - -#if 0 -struct mmap_arg_struct64 { - __u32 addr; - __u32 len; - __u32 prot; - __u32 flags; - __u64 offset; /* 64 bits */ - __u32 fd; -}; - -asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg) -{ - int error = -EFAULT; - struct file * file = NULL; - struct mmap_arg_struct64 a; - unsigned long pgoff; - - if (copy_from_user(&a, arg, sizeof(a))) - return -EFAULT; - - if ((long)a.offset & ~PAGE_MASK) - return -EINVAL; - - pgoff = a.offset >> PAGE_SHIFT; - if ((a.offset >> PAGE_SHIFT) != pgoff) - return -EINVAL; - - if (!(a.flags & MAP_ANONYMOUS)) { - error = -EBADF; - file = fget(a.fd); - if (!file) - goto out; - } - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, + a.offset >> PAGE_SHIFT); out: return error; } -#endif struct sel_arg_struct { unsigned long n; diff --git a/arch/m68k/sun3/mmu_emu.c b/arch/m68k/sun3/mmu_emu.c index 3cd19390aae51fcfa73ebe35b8c8075249cf780e..94f81ecfe3f83f91217dc1d721402d658e204dc5 100644 --- a/arch/m68k/sun3/mmu_emu.c +++ b/arch/m68k/sun3/mmu_emu.c @@ -45,8 +45,8 @@ ** Globals */ -unsigned long vmalloc_end; -EXPORT_SYMBOL(vmalloc_end); +unsigned long m68k_vmalloc_end; +EXPORT_SYMBOL(m68k_vmalloc_end); unsigned long pmeg_vaddr[PMEGS_NUM]; unsigned char pmeg_alloc[PMEGS_NUM]; @@ -172,8 +172,8 @@ void mmu_emu_init(unsigned long bootmem_end) #endif // the lowest mapping here is the end of our // vmalloc region - if(!vmalloc_end) - vmalloc_end = seg; + if (!m68k_vmalloc_end) + m68k_vmalloc_end = seg; // mark the segmap alloc'd, and reserve any // of the first 0xbff pages the hardware is diff --git a/arch/m68knommu/kernel/sys_m68k.c b/arch/m68knommu/kernel/sys_m68k.c index efdd090778a371d57ff749561a799e263755fc67..b67cbc735a9b13d7e0ca3d52fdef01b3ff944d09 100644 --- a/arch/m68knommu/kernel/sys_m68k.c +++ b/arch/m68knommu/kernel/sys_m68k.c @@ -27,39 +27,6 @@ #include #include -/* common code for old and new mmaps */ -static inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - return do_mmap2(addr, len, prot, flags, fd, pgoff); -} - /* * Perform the select(nd, in, out, ex, tv) and mmap() system * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to @@ -88,9 +55,8 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg) if (a.offset & ~PAGE_MASK) goto out; - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, + a.offset >> PAGE_SHIFT); out: return error; } diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S index 23535cc415aea014accf7f726b225cd18a67a9e5..486837efa3d788d5196f77130675880d23a43a0d 100644 --- a/arch/m68knommu/kernel/syscalltable.S +++ b/arch/m68knommu/kernel/syscalltable.S @@ -210,7 +210,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* streams2 */ .long sys_vfork /* 190 */ .long sys_getrlimit - .long sys_mmap2 + .long sys_mmap_pgoff .long sys_truncate64 .long sys_ftruncate64 .long sys_stat64 /* 195 */ diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index bbd8327f18901d80d5eefe3e27015f65993a099f..fd53e500be67b21e5d48c96f9e745d8dfa0e158a 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -6,8 +6,15 @@ mainmenu "Linux/Microblaze Kernel Configuration" config MICROBLAZE def_bool y select HAVE_LMB + select HAVE_FUNCTION_TRACER + select HAVE_FUNCTION_TRACE_MCOUNT_TEST + select HAVE_FUNCTION_GRAPH_TRACER + select HAVE_DYNAMIC_FTRACE + select HAVE_FTRACE_MCOUNT_RECORD select USB_ARCH_HAS_EHCI select ARCH_WANT_OPTIONAL_GPIOLIB + select HAVE_OPROFILE + select TRACING_SUPPORT config SWAP def_bool n @@ -57,12 +64,24 @@ config GENERIC_GPIO config GENERIC_CSUM def_bool y +config STACKTRACE_SUPPORT + def_bool y + +config LOCKDEP_SUPPORT + def_bool y + +config HAVE_LATENCYTOP_SUPPORT + def_bool y + config PCI def_bool n config NO_DMA def_bool y +config DTC + def_bool y + source "init/Kconfig" source "kernel/Kconfig.freezer" diff --git a/arch/microblaze/Kconfig.debug b/arch/microblaze/Kconfig.debug index 242cd35bdb4bfe22970a0110be801e98a410d616..9dc708a7f7005a5bf35f55c6b80654743a9b4e54 100644 --- a/arch/microblaze/Kconfig.debug +++ b/arch/microblaze/Kconfig.debug @@ -3,6 +3,9 @@ menu "Kernel hacking" +config TRACE_IRQFLAGS_SUPPORT + def_bool y + source "lib/Kconfig.debug" config EARLY_PRINTK diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile index 34187354304a6217d16ff3dab5315e605409ab05..d2d6cfcb1a3028bde39bad803094746713518d5d 100644 --- a/arch/microblaze/Makefile +++ b/arch/microblaze/Makefile @@ -51,6 +51,8 @@ core-y += arch/microblaze/kernel/ core-y += arch/microblaze/mm/ core-y += arch/microblaze/platform/ +drivers-$(CONFIG_OPROFILE) += arch/microblaze/oprofile/ + boot := arch/microblaze/boot # Are we making a simpleImage. target? If so, crack out the boardname diff --git a/arch/microblaze/boot/Makefile b/arch/microblaze/boot/Makefile index 21f13322a4cad74da687055e50eb840804dda78b..902cf9846c3cb9b89f0940a8a635554cb265fd0b 100644 --- a/arch/microblaze/boot/Makefile +++ b/arch/microblaze/boot/Makefile @@ -2,11 +2,13 @@ # arch/microblaze/boot/Makefile # +MKIMAGE := $(srctree)/scripts/mkuboot.sh + obj-y += linked_dtb.o targets := linux.bin linux.bin.gz simpleImage.% -OBJCOPYFLAGS_linux.bin := -O binary +OBJCOPYFLAGS := -O binary # Where the DTS files live dtstree := $(srctree)/$(src)/dts @@ -24,6 +26,7 @@ $(obj)/linux.bin: vmlinux FORCE [ -n $(CONFIG_INITRAMFS_SOURCE) ] && [ ! -e $(CONFIG_INITRAMFS_SOURCE) ] && \ touch $(CONFIG_INITRAMFS_SOURCE) || echo "No CPIO image" $(call if_changed,objcopy) + $(call if_changed,uimage) @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' $(obj)/linux.bin.gz: $(obj)/linux.bin FORCE @@ -36,8 +39,16 @@ quiet_cmd_cp = CP $< $@$2 quiet_cmd_strip = STRIP $@ cmd_strip = $(STRIP) -K _start -K _end -K __log_buf -K _fdt_start vmlinux -o $@ +quiet_cmd_uimage = UIMAGE $@.ub + cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A microblaze -O linux -T kernel \ + -C none -n 'Linux-$(KERNELRELEASE)' \ + -a $(CONFIG_KERNEL_BASE_ADDR) -e $(CONFIG_KERNEL_BASE_ADDR) \ + -d $@ $@.ub + $(obj)/simpleImage.%: vmlinux FORCE $(call if_changed,cp,.unstrip) + $(call if_changed,objcopy) + $(call if_changed,uimage) $(call if_changed,strip) @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' @@ -53,4 +64,4 @@ $(obj)/%.dtb: $(dtstree)/%.dts FORCE clean-kernel += linux.bin linux.bin.gz simpleImage.* -clean-files += *.dtb +clean-files += *.dtb simpleImage.*.unstrip diff --git a/arch/microblaze/include/asm/cache.h b/arch/microblaze/include/asm/cache.h index c209c47509d52435303c8b09008405fb14837afc..e52210891d78ed167a71e24ca35c1cd9abee6bf4 100644 --- a/arch/microblaze/include/asm/cache.h +++ b/arch/microblaze/include/asm/cache.h @@ -21,20 +21,4 @@ #define SMP_CACHE_BYTES L1_CACHE_BYTES -void _enable_icache(void); -void _disable_icache(void); -void _invalidate_icache(unsigned int addr); - -#define __enable_icache() _enable_icache() -#define __disable_icache() _disable_icache() -#define __invalidate_icache(addr) _invalidate_icache(addr) - -void _enable_dcache(void); -void _disable_dcache(void); -void _invalidate_dcache(unsigned int addr); - -#define __enable_dcache() _enable_dcache() -#define __disable_dcache() _disable_dcache() -#define __invalidate_dcache(addr) _invalidate_dcache(addr) - #endif /* _ASM_MICROBLAZE_CACHE_H */ diff --git a/arch/microblaze/include/asm/cacheflush.h b/arch/microblaze/include/asm/cacheflush.h index 088076e657b32189ac16e6b9a9e3d0959740633a..a6edd356cd08c583807fb278913f943172f7ae20 100644 --- a/arch/microblaze/include/asm/cacheflush.h +++ b/arch/microblaze/include/asm/cacheflush.h @@ -18,6 +18,8 @@ /* Somebody depends on this; sigh... */ #include +/* Look at Documentation/cachetlb.txt */ + /* * Cache handling functions. * Microblaze has a write-through data cache, meaning that the data cache @@ -27,78 +29,81 @@ * instruction cache to make sure we don't fetch old, bad code. */ +/* struct cache, d=dcache, i=icache, fl = flush, iv = invalidate, + * suffix r = range */ +struct scache { + /* icache */ + void (*ie)(void); /* enable */ + void (*id)(void); /* disable */ + void (*ifl)(void); /* flush */ + void (*iflr)(unsigned long a, unsigned long b); + void (*iin)(void); /* invalidate */ + void (*iinr)(unsigned long a, unsigned long b); + /* dcache */ + void (*de)(void); /* enable */ + void (*dd)(void); /* disable */ + void (*dfl)(void); /* flush */ + void (*dflr)(unsigned long a, unsigned long b); + void (*din)(void); /* invalidate */ + void (*dinr)(unsigned long a, unsigned long b); +}; + +/* microblaze cache */ +extern struct scache *mbc; + +void microblaze_cache_init(void); + +#define enable_icache() mbc->ie(); +#define disable_icache() mbc->id(); +#define flush_icache() mbc->ifl(); +#define flush_icache_range(start, end) mbc->iflr(start, end); +#define invalidate_icache() mbc->iin(); +#define invalidate_icache_range(start, end) mbc->iinr(start, end); + + +#define flush_icache_user_range(vma, pg, adr, len) flush_icache(); +#define flush_icache_page(vma, pg) do { } while (0) + +#define enable_dcache() mbc->de(); +#define disable_dcache() mbc->dd(); /* FIXME for LL-temac driver */ -#define invalidate_dcache_range(start, end) \ - __invalidate_dcache_range(start, end) - -#define flush_cache_all() __invalidate_cache_all() -#define flush_cache_mm(mm) do { } while (0) -#define flush_cache_range(vma, start, end) __invalidate_cache_all() -#define flush_cache_page(vma, vmaddr, pfn) do { } while (0) +#define invalidate_dcache() mbc->din(); +#define invalidate_dcache_range(start, end) mbc->dinr(start, end); +#define flush_dcache() mbc->dfl(); +#define flush_dcache_range(start, end) mbc->dflr(start, end); -#define flush_dcache_range(start, end) __invalidate_dcache_range(start, end) #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 +/* D-cache aliasing problem can't happen - cache is between MMU and ram */ #define flush_dcache_page(page) do { } while (0) #define flush_dcache_mmap_lock(mapping) do { } while (0) #define flush_dcache_mmap_unlock(mapping) do { } while (0) -#define flush_icache_range(start, len) __invalidate_icache_range(start, len) -#define flush_icache_page(vma, pg) do { } while (0) - -#ifndef CONFIG_MMU -# define flush_icache_user_range(start, len) do { } while (0) -#else -# define flush_icache_user_range(vma, pg, adr, len) __invalidate_icache_all() - -# define flush_page_to_ram(page) do { } while (0) -# define flush_icache() __invalidate_icache_all() -# define flush_cache_sigtramp(vaddr) \ - __invalidate_icache_range(vaddr, vaddr + 8) - -# define flush_dcache_mmap_lock(mapping) do { } while (0) -# define flush_dcache_mmap_unlock(mapping) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) +#define flush_cache_vmap(start, end) do { } while (0) +#define flush_cache_vunmap(start, end) do { } while (0) +#define flush_cache_mm(mm) do { } while (0) +#define flush_cache_page(vma, vmaddr, pfn) do { } while (0) -# define flush_cache_dup_mm(mm) do { } while (0) +/* MS: kgdb code use this macro, wrong len with FLASH */ +#if 0 +#define flush_cache_range(vma, start, len) { \ + flush_icache_range((unsigned) (start), (unsigned) (start) + (len)); \ + flush_dcache_range((unsigned) (start), (unsigned) (start) + (len)); \ +} #endif -#define flush_cache_vmap(start, end) do { } while (0) -#define flush_cache_vunmap(start, end) do { } while (0) - -struct page; -struct mm_struct; -struct vm_area_struct; - -/* see arch/microblaze/kernel/cache.c */ -extern void __invalidate_icache_all(void); -extern void __invalidate_icache_range(unsigned long start, unsigned long end); -extern void __invalidate_icache_page(struct vm_area_struct *vma, - struct page *page); -extern void __invalidate_icache_user_range(struct vm_area_struct *vma, - struct page *page, - unsigned long adr, int len); -extern void __invalidate_cache_sigtramp(unsigned long addr); - -extern void __invalidate_dcache_all(void); -extern void __invalidate_dcache_range(unsigned long start, unsigned long end); -extern void __invalidate_dcache_page(struct vm_area_struct *vma, - struct page *page); -extern void __invalidate_dcache_user_range(struct vm_area_struct *vma, - struct page *page, - unsigned long adr, int len); - -extern inline void __invalidate_cache_all(void) -{ - __invalidate_icache_all(); - __invalidate_dcache_all(); -} +#define flush_cache_range(vma, start, len) do { } while (0) -#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ -do { memcpy((dst), (src), (len)); \ - flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \ +#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ +do { \ + memcpy((dst), (src), (len)); \ + flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \ } while (0) -#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ - memcpy((dst), (src), (len)) +#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ +do { \ + memcpy((dst), (src), (len)); \ +} while (0) #endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */ diff --git a/arch/microblaze/include/asm/cpuinfo.h b/arch/microblaze/include/asm/cpuinfo.h index 52f28f6dc4eb1b0985965d03f8fe9401a986c3f6..b4f5ca33aebf09a831226022ae0b9513c8344322 100644 --- a/arch/microblaze/include/asm/cpuinfo.h +++ b/arch/microblaze/include/asm/cpuinfo.h @@ -43,7 +43,7 @@ struct cpuinfo { u32 use_icache; u32 icache_tagbits; u32 icache_write; - u32 icache_line; + u32 icache_line_length; u32 icache_size; unsigned long icache_base; unsigned long icache_high; @@ -51,8 +51,9 @@ struct cpuinfo { u32 use_dcache; u32 dcache_tagbits; u32 dcache_write; - u32 dcache_line; + u32 dcache_line_length; u32 dcache_size; + u32 dcache_wb; unsigned long dcache_base; unsigned long dcache_high; diff --git a/arch/microblaze/include/asm/device.h b/arch/microblaze/include/asm/device.h index 30286db27c1c2a08e94c513991deb2a4904d23c1..78a038452c0faa0106f3a0f7bb48e50e811c91da 100644 --- a/arch/microblaze/include/asm/device.h +++ b/arch/microblaze/include/asm/device.h @@ -19,6 +19,18 @@ struct dev_archdata { struct pdev_archdata { }; +static inline void dev_archdata_set_node(struct dev_archdata *ad, + struct device_node *np) +{ + ad->of_node = np; +} + +static inline struct device_node * +dev_archdata_get_node(const struct dev_archdata *ad) +{ + return ad->of_node; +} + #endif /* _ASM_MICROBLAZE_DEVICE_H */ diff --git a/arch/microblaze/include/asm/ftrace.h b/arch/microblaze/include/asm/ftrace.h index 8b137891791fe96927ad78e64b0aad7bded08bdc..fd2fa2eca62f18fe2541300a8ffc5453632760d7 100644 --- a/arch/microblaze/include/asm/ftrace.h +++ b/arch/microblaze/include/asm/ftrace.h @@ -1 +1,26 @@ +#ifndef _ASM_MICROBLAZE_FTRACE +#define _ASM_MICROBLAZE_FTRACE +#ifdef CONFIG_FUNCTION_TRACER + +#define MCOUNT_ADDR ((long)(_mcount)) +#define MCOUNT_INSN_SIZE 8 /* sizeof mcount call */ + +#ifndef __ASSEMBLY__ +extern void _mcount(void); +extern void ftrace_call_graph(void); +#endif + +#ifdef CONFIG_DYNAMIC_FTRACE +/* reloction of mcount call site is the same as the address */ +static inline unsigned long ftrace_call_adjust(unsigned long addr) +{ + return addr; +} + +struct dyn_arch_ftrace { +}; +#endif /* CONFIG_DYNAMIC_FTRACE */ + +#endif /* CONFIG_FUNCTION_TRACER */ +#endif /* _ASM_MICROBLAZE_FTRACE */ diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h index 0b745828f42bc9be46ded49786b887c9ad35df2d..8dbb6e7a03a2183c135656ca4fee82e302223885 100644 --- a/arch/microblaze/include/asm/futex.h +++ b/arch/microblaze/include/asm/futex.h @@ -1 +1,126 @@ -#include +#ifndef _ASM_MICROBLAZE_FUTEX_H +#define _ASM_MICROBLAZE_FUTEX_H + +#ifdef __KERNEL__ + +#include +#include +#include + +#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ +({ \ + __asm__ __volatile__ ( \ + "1: lwx %0, %2, r0; " \ + insn \ + "2: swx %1, %2, r0; \ + addic %1, r0, 0; \ + bnei %1, 1b; \ + 3: \ + .section .fixup,\"ax\"; \ + 4: brid 3b; \ + addik %1, r0, %3; \ + .previous; \ + .section __ex_table,\"a\"; \ + .word 1b,4b,2b,4b; \ + .previous;" \ + : "=&r" (oldval), "=&r" (ret) \ + : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \ + ); \ +}) + +static inline int +futex_atomic_op_inuser(int encoded_op, int __user *uaddr) +{ + int op = (encoded_op >> 28) & 7; + int cmp = (encoded_op >> 24) & 15; + int oparg = (encoded_op << 8) >> 20; + int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; + if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) + oparg = 1 << oparg; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + pagefault_disable(); + + switch (op) { + case FUTEX_OP_SET: + __futex_atomic_op("or %1,%4,%4;", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_ADD: + __futex_atomic_op("add %1,%0,%4;", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_OR: + __futex_atomic_op("or %1,%0,%4;", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_ANDN: + __futex_atomic_op("and %1,%0,%4;", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_XOR: + __futex_atomic_op("xor %1,%0,%4;", ret, oldval, uaddr, oparg); + break; + default: + ret = -ENOSYS; + } + + pagefault_enable(); + + if (!ret) { + switch (cmp) { + case FUTEX_OP_CMP_EQ: + ret = (oldval == cmparg); + break; + case FUTEX_OP_CMP_NE: + ret = (oldval != cmparg); + break; + case FUTEX_OP_CMP_LT: + ret = (oldval < cmparg); + break; + case FUTEX_OP_CMP_GE: + ret = (oldval >= cmparg); + break; + case FUTEX_OP_CMP_LE: + ret = (oldval <= cmparg); + break; + case FUTEX_OP_CMP_GT: + ret = (oldval > cmparg); + break; + default: + ret = -ENOSYS; + } + } + return ret; +} + +static inline int +futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) +{ + int prev, cmp; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + __asm__ __volatile__ ("1: lwx %0, %2, r0; \ + cmp %1, %0, %3; \ + beqi %1, 3f; \ + 2: swx %4, %2, r0; \ + addic %1, r0, 0; \ + bnei %1, 1b; \ + 3: \ + .section .fixup,\"ax\"; \ + 4: brid 3b; \ + addik %0, r0, %5; \ + .previous; \ + .section __ex_table,\"a\"; \ + .word 1b,4b,2b,4b; \ + .previous;" \ + : "=&r" (prev), "=&r"(cmp) \ + : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)); + + return prev; +} + +#endif /* __KERNEL__ */ + +#endif diff --git a/arch/microblaze/include/asm/irqflags.h b/arch/microblaze/include/asm/irqflags.h index dea65645a4f8d5d8cc591c534c6eec8adeb16b67..2c38c6d801769be469348fa80f4ef3283aab44e2 100644 --- a/arch/microblaze/include/asm/irqflags.h +++ b/arch/microblaze/include/asm/irqflags.h @@ -10,78 +10,73 @@ #define _ASM_MICROBLAZE_IRQFLAGS_H #include +#include # if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR -# define local_irq_save(flags) \ +# define raw_local_irq_save(flags) \ do { \ - asm volatile ("# local_irq_save \n\t" \ - "msrclr %0, %1 \n\t" \ - "nop \n\t" \ + asm volatile (" msrclr %0, %1; \ + nop;" \ : "=r"(flags) \ : "i"(MSR_IE) \ : "memory"); \ } while (0) -# define local_irq_disable() \ - do { \ - asm volatile ("# local_irq_disable \n\t" \ - "msrclr r0, %0 \n\t" \ - "nop \n\t" \ - : \ - : "i"(MSR_IE) \ - : "memory"); \ +# define raw_local_irq_disable() \ + do { \ + asm volatile (" msrclr r0, %0; \ + nop;" \ + : \ + : "i"(MSR_IE) \ + : "memory"); \ } while (0) -# define local_irq_enable() \ - do { \ - asm volatile ("# local_irq_enable \n\t" \ - "msrset r0, %0 \n\t" \ - "nop \n\t" \ - : \ - : "i"(MSR_IE) \ - : "memory"); \ +# define raw_local_irq_enable() \ + do { \ + asm volatile (" msrset r0, %0; \ + nop;" \ + : \ + : "i"(MSR_IE) \ + : "memory"); \ } while (0) # else /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR == 0 */ -# define local_irq_save(flags) \ +# define raw_local_irq_save(flags) \ do { \ register unsigned tmp; \ - asm volatile ("# local_irq_save \n\t" \ - "mfs %0, rmsr \n\t" \ - "nop \n\t" \ - "andi %1, %0, %2 \n\t" \ - "mts rmsr, %1 \n\t" \ - "nop \n\t" \ + asm volatile (" mfs %0, rmsr; \ + nop; \ + andi %1, %0, %2; \ + mts rmsr, %1; \ + nop;" \ : "=r"(flags), "=r" (tmp) \ : "i"(~MSR_IE) \ : "memory"); \ } while (0) -# define local_irq_disable() \ +# define raw_local_irq_disable() \ do { \ register unsigned tmp; \ - asm volatile ("# local_irq_disable \n\t" \ - "mfs %0, rmsr \n\t" \ - "nop \n\t" \ - "andi %0, %0, %1 \n\t" \ - "mts rmsr, %0 \n\t" \ - "nop \n\t" \ + asm volatile (" mfs %0, rmsr; \ + nop; \ + andi %0, %0, %1; \ + mts rmsr, %0; \ + nop;" \ : "=r"(tmp) \ : "i"(~MSR_IE) \ : "memory"); \ } while (0) -# define local_irq_enable() \ +# define raw_local_irq_enable() \ do { \ register unsigned tmp; \ - asm volatile ("# local_irq_enable \n\t" \ - "mfs %0, rmsr \n\t" \ - "nop \n\t" \ - "ori %0, %0, %1 \n\t" \ - "mts rmsr, %0 \n\t" \ - "nop \n\t" \ + asm volatile (" mfs %0, rmsr; \ + nop; \ + ori %0, %0, %1; \ + mts rmsr, %0; \ + nop;" \ : "=r"(tmp) \ : "i"(MSR_IE) \ : "memory"); \ @@ -89,35 +84,28 @@ # endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */ -#define local_save_flags(flags) \ +#define raw_local_irq_restore(flags) \ do { \ - asm volatile ("# local_save_flags \n\t" \ - "mfs %0, rmsr \n\t" \ - "nop \n\t" \ - : "=r"(flags) \ + asm volatile (" mts rmsr, %0; \ + nop;" \ : \ + : "r"(flags) \ : "memory"); \ } while (0) -#define local_irq_restore(flags) \ - do { \ - asm volatile ("# local_irq_restore \n\t"\ - "mts rmsr, %0 \n\t" \ - "nop \n\t" \ - : \ - : "r"(flags) \ - : "memory"); \ - } while (0) - -static inline int irqs_disabled(void) +static inline unsigned long get_msr(void) { unsigned long flags; - - local_save_flags(flags); - return ((flags & MSR_IE) == 0); + asm volatile (" mfs %0, rmsr; \ + nop;" \ + : "=r"(flags) \ + : \ + : "memory"); \ + return flags; } -#define raw_irqs_disabled irqs_disabled -#define raw_irqs_disabled_flags(flags) ((flags) == 0) +#define raw_local_save_flags(flags) ((flags) = get_msr()) +#define raw_irqs_disabled() ((get_msr() & MSR_IE) == 0) +#define raw_irqs_disabled_flags(flags) ((flags & MSR_IE) == 0) #endif /* _ASM_MICROBLAZE_IRQFLAGS_H */ diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h index 880c988c2237e2a333bbb7cc51c939a385ea9d07..9b66c0fa9a32caf5ba14e7f0c9478119808a0759 100644 --- a/arch/microblaze/include/asm/page.h +++ b/arch/microblaze/include/asm/page.h @@ -164,7 +164,8 @@ extern int page_is_ram(unsigned long pfn); # endif /* CONFIG_MMU */ # ifndef CONFIG_MMU -# define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) <= max_mapnr) +# define pfn_valid(pfn) (((pfn) >= min_low_pfn) && \ + ((pfn) <= (min_low_pfn + max_mapnr))) # define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) # else /* CONFIG_MMU */ # define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT) diff --git a/arch/microblaze/include/asm/pgalloc.h b/arch/microblaze/include/asm/pgalloc.h index b0131da1387bb131cd9e7666519eedb9591302e3..7547f50645608c9c34170e9680d3072b9e636a8d 100644 --- a/arch/microblaze/include/asm/pgalloc.h +++ b/arch/microblaze/include/asm/pgalloc.h @@ -106,9 +106,6 @@ extern inline void free_pgd_slow(pgd_t *pgd) */ #define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); }) #define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); }) -/* FIXME two definition - look below */ -#define pmd_free(mm, x) do { } while (0) -#define pgd_populate(mm, pmd, pte) BUG() static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) @@ -192,14 +189,14 @@ extern inline void pte_free(struct mm_struct *mm, struct page *ptepage) * the pgd will always be present.. */ #define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); }) -/*#define pmd_free(mm, x) do { } while (0)*/ -#define __pmd_free_tlb(tlb, x, addr) do { } while (0) +#define pmd_free(mm, x) do { } while (0) +#define __pmd_free_tlb(tlb, x, addr) pmd_free((tlb)->mm, x) #define pgd_populate(mm, pmd, pte) BUG() extern int do_check_pgt_cache(int, int); #endif /* CONFIG_MMU */ -#define check_pgt_cache() do {} while (0) +#define check_pgt_cache() do { } while (0) #endif /* _ASM_MICROBLAZE_PGALLOC_H */ diff --git a/arch/microblaze/include/asm/pvr.h b/arch/microblaze/include/asm/pvr.h index 66f1b30dd097db0fabde6ca1ddb475b71107b96a..e38abc7714b60bff43f11b2c52e5401cfd3e8db5 100644 --- a/arch/microblaze/include/asm/pvr.h +++ b/arch/microblaze/include/asm/pvr.h @@ -76,20 +76,23 @@ struct pvr_s { #define PVR3_FSL_LINKS_MASK 0x00000380 /* ICache config PVR masks */ -#define PVR4_USE_ICACHE_MASK 0x80000000 -#define PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000 -#define PVR4_ICACHE_USE_FSL_MASK 0x02000000 -#define PVR4_ICACHE_ALLOW_WR_MASK 0x01000000 -#define PVR4_ICACHE_LINE_LEN_MASK 0x00E00000 -#define PVR4_ICACHE_BYTE_SIZE_MASK 0x001F0000 +#define PVR4_USE_ICACHE_MASK 0x80000000 /* ICU */ +#define PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000 /* ICTS */ +#define PVR4_ICACHE_ALLOW_WR_MASK 0x01000000 /* ICW */ +#define PVR4_ICACHE_LINE_LEN_MASK 0x00E00000 /* ICLL */ +#define PVR4_ICACHE_BYTE_SIZE_MASK 0x001F0000 /* ICBS */ +#define PVR4_ICACHE_ALWAYS_USED 0x00008000 /* IAU */ +#define PVR4_ICACHE_INTERFACE 0x00002000 /* ICI */ /* DCache config PVR masks */ -#define PVR5_USE_DCACHE_MASK 0x80000000 -#define PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000 -#define PVR5_DCACHE_USE_FSL_MASK 0x02000000 -#define PVR5_DCACHE_ALLOW_WR_MASK 0x01000000 -#define PVR5_DCACHE_LINE_LEN_MASK 0x00E00000 -#define PVR5_DCACHE_BYTE_SIZE_MASK 0x001F0000 +#define PVR5_USE_DCACHE_MASK 0x80000000 /* DCU */ +#define PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000 /* DCTS */ +#define PVR5_DCACHE_ALLOW_WR_MASK 0x01000000 /* DCW */ +#define PVR5_DCACHE_LINE_LEN_MASK 0x00E00000 /* DCLL */ +#define PVR5_DCACHE_BYTE_SIZE_MASK 0x001F0000 /* DCBS */ +#define PVR5_DCACHE_ALWAYS_USED 0x00008000 /* DAU */ +#define PVR5_DCACHE_USE_WRITEBACK 0x00004000 /* DWB */ +#define PVR5_DCACHE_INTERFACE 0x00002000 /* DCI */ /* ICache base address PVR mask */ #define PVR6_ICACHE_BASEADDR_MASK 0xFFFFFFFF @@ -178,11 +181,14 @@ struct pvr_s { ((pvr.pvr[5] & PVR5_DCACHE_ADDR_TAG_BITS_MASK) >> 26) #define PVR_DCACHE_USE_FSL(pvr) (pvr.pvr[5] & PVR5_DCACHE_USE_FSL_MASK) #define PVR_DCACHE_ALLOW_WR(pvr) (pvr.pvr[5] & PVR5_DCACHE_ALLOW_WR_MASK) +/* FIXME two shifts on one line needs any comment */ #define PVR_DCACHE_LINE_LEN(pvr) \ (1 << ((pvr.pvr[5] & PVR5_DCACHE_LINE_LEN_MASK) >> 21)) #define PVR_DCACHE_BYTE_SIZE(pvr) \ (1 << ((pvr.pvr[5] & PVR5_DCACHE_BYTE_SIZE_MASK) >> 16)) +#define PVR_DCACHE_USE_WRITEBACK(pvr) \ + ((pvr.pvr[5] & PVR5_DCACHE_USE_WRITEBACK) >> 14) #define PVR_ICACHE_BASEADDR(pvr) (pvr.pvr[6] & PVR6_ICACHE_BASEADDR_MASK) #define PVR_ICACHE_HIGHADDR(pvr) (pvr.pvr[7] & PVR7_ICACHE_HIGHADDR_MASK) diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h index ed67c9ed15b8346f8752ff506b59ffe6e43afe17..7f31394985e05f5884d6848ab902de53f8c45ac4 100644 --- a/arch/microblaze/include/asm/setup.h +++ b/arch/microblaze/include/asm/setup.h @@ -35,6 +35,8 @@ extern void mmu_reset(void); extern void early_console_reg_tlb_alloc(unsigned int addr); # endif /* CONFIG_MMU */ +extern void of_platform_reset_gpio_probe(void); + void time_init(void); void init_IRQ(void); void machine_early_init(const char *cmdline, unsigned int ram, diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h index b1ed6159066006bd3d635f57126316a12f25962a..157970688b2aba72037e94b4e08a96fc831184ac 100644 --- a/arch/microblaze/include/asm/system.h +++ b/arch/microblaze/include/asm/system.h @@ -16,6 +16,8 @@ #include #include +#define __ARCH_WANT_INTERRUPTS_ON_CTXSW + struct task_struct; struct thread_info; diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index 5431b4631a7ad479bc23baf72de4563c68b8efb8..371bd6e56d9a20e60624147a050366f9fd06d2ea 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h @@ -272,8 +272,9 @@ static inline int clear_user(char *to, int size) return size; } -extern unsigned long __copy_tofrom_user(void __user *to, - const void __user *from, unsigned long size); +#define __copy_from_user(to, from, n) copy_from_user((to), (from), (n)) +#define __copy_from_user_inatomic(to, from, n) \ + copy_from_user((to), (from), (n)) #define copy_to_user(to, from, n) \ (access_ok(VERIFY_WRITE, (to), (n)) ? \ @@ -290,10 +291,6 @@ extern unsigned long __copy_tofrom_user(void __user *to, (void __user *)(from), (n)) \ : -EFAULT) -#define __copy_from_user(to, from, n) copy_from_user((to), (from), (n)) -#define __copy_from_user_inatomic(to, from, n) \ - copy_from_user((to), (from), (n)) - extern int __strncpy_user(char *to, const char __user *from, int len); extern int __strnlen_user(const char __user *sstr, int len); @@ -305,6 +302,9 @@ extern int __strnlen_user(const char __user *sstr, int len); #endif /* CONFIG_MMU */ +extern unsigned long __copy_tofrom_user(void __user *to, + const void __user *from, unsigned long size); + /* * The exception table consists of pairs of addresses: the first is the * address of an instruction that is allowed to fault, and the second is diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile index d487729683de8a0b66c6d082a8cefb096621687d..b07594eccf9b0d71c47e996bc33d22f61ffd39e4 100644 --- a/arch/microblaze/kernel/Makefile +++ b/arch/microblaze/kernel/Makefile @@ -2,12 +2,22 @@ # Makefile # +ifdef CONFIG_FUNCTION_TRACER +# Do not trace early boot code and low level code +CFLAGS_REMOVE_timer.o = -pg +CFLAGS_REMOVE_intc.o = -pg +CFLAGS_REMOVE_early_printk.o = -pg +CFLAGS_REMOVE_selfmod.o = -pg +CFLAGS_REMOVE_heartbeat.o = -pg +CFLAGS_REMOVE_ftrace.o = -pg +endif + extra-y := head.o vmlinux.lds obj-y += exceptions.o \ hw_exception_handler.o init_task.o intc.o irq.o of_device.o \ of_platform.o process.o prom.o prom_parse.o ptrace.o \ - setup.o signal.o sys_microblaze.o timer.o traps.o + setup.o signal.o sys_microblaze.o timer.o traps.o reset.o obj-y += cpu/ @@ -16,5 +26,7 @@ obj-$(CONFIG_SELFMOD) += selfmod.o obj-$(CONFIG_HEART_BEAT) += heartbeat.o obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o obj-$(CONFIG_MMU) += misc.o +obj-$(CONFIG_STACKTRACE) += stacktrace.o +obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount.o obj-y += entry$(MMU).o diff --git a/arch/microblaze/kernel/cpu/Makefile b/arch/microblaze/kernel/cpu/Makefile index 20646e5492710bd51893e07e8452a0c481c32b07..59cc7bceaf8c493d35ef426e9bafaad914dbf3ab 100644 --- a/arch/microblaze/kernel/cpu/Makefile +++ b/arch/microblaze/kernel/cpu/Makefile @@ -2,6 +2,10 @@ # Build the appropriate CPU version support # +ifdef CONFIG_FUNCTION_TRACER +CFLAGS_REMOVE_cache.o = -pg +endif + EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \ -DCPU_REV=$(CPU_REV) diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index af866a4501256a4028b0daa99c92ff40a8b40e69..d9d63831cc2f9d6318257fa358ac41d41553c789 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c @@ -3,7 +3,7 @@ * * Copyright (C) 2007-2009 Michal Simek * Copyright (C) 2007-2009 PetaLogix - * Copyright (C) 2007 John Williams + * Copyright (C) 2007-2009 John Williams * * 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 @@ -13,243 +13,534 @@ #include #include #include +#include -/* Exported functions */ +static inline void __invalidate_flush_icache(unsigned int addr) +{ + __asm__ __volatile__ ("wic %0, r0;" \ + : : "r" (addr)); +} + +static inline void __flush_dcache(unsigned int addr) +{ + __asm__ __volatile__ ("wdc.flush %0, r0;" \ + : : "r" (addr)); +} + +static inline void __invalidate_dcache(unsigned int baseaddr, + unsigned int offset) +{ + __asm__ __volatile__ ("wdc.clear %0, %1;" \ + : : "r" (baseaddr), "r" (offset)); +} -void _enable_icache(void) +static inline void __enable_icache_msr(void) { - if (cpuinfo.use_icache) { -#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR - __asm__ __volatile__ (" \ - msrset r0, %0; \ - nop; " \ - : \ - : "i" (MSR_ICE) \ + __asm__ __volatile__ (" msrset r0, %0; \ + nop; " \ + : : "i" (MSR_ICE) : "memory"); +} + +static inline void __disable_icache_msr(void) +{ + __asm__ __volatile__ (" msrclr r0, %0; \ + nop; " \ + : : "i" (MSR_ICE) : "memory"); +} + +static inline void __enable_dcache_msr(void) +{ + __asm__ __volatile__ (" msrset r0, %0; \ + nop; " \ + : \ + : "i" (MSR_DCE) \ : "memory"); -#else - __asm__ __volatile__ (" \ - mfs r12, rmsr; \ - nop; \ - ori r12, r12, %0; \ - mts rmsr, r12; \ - nop; " \ - : \ - : "i" (MSR_ICE) \ - : "memory", "r12"); -#endif - } } -void _disable_icache(void) +static inline void __disable_dcache_msr(void) { - if (cpuinfo.use_icache) { -#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR - __asm__ __volatile__ (" \ - msrclr r0, %0; \ - nop; " \ - : \ - : "i" (MSR_ICE) \ + __asm__ __volatile__ (" msrclr r0, %0; \ + nop; " \ + : \ + : "i" (MSR_DCE) \ : "memory"); -#else - __asm__ __volatile__ (" \ - mfs r12, rmsr; \ - nop; \ - andi r12, r12, ~%0; \ - mts rmsr, r12; \ - nop; " \ - : \ - : "i" (MSR_ICE) \ +} + +static inline void __enable_icache_nomsr(void) +{ + __asm__ __volatile__ (" mfs r12, rmsr; \ + nop; \ + ori r12, r12, %0; \ + mts rmsr, r12; \ + nop; " \ + : \ + : "i" (MSR_ICE) \ : "memory", "r12"); -#endif - } } -void _invalidate_icache(unsigned int addr) +static inline void __disable_icache_nomsr(void) { - if (cpuinfo.use_icache) { - __asm__ __volatile__ (" \ - wic %0, r0" \ - : \ - : "r" (addr)); - } + __asm__ __volatile__ (" mfs r12, rmsr; \ + nop; \ + andi r12, r12, ~%0; \ + mts rmsr, r12; \ + nop; " \ + : \ + : "i" (MSR_ICE) \ + : "memory", "r12"); } -void _enable_dcache(void) +static inline void __enable_dcache_nomsr(void) { - if (cpuinfo.use_dcache) { -#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR - __asm__ __volatile__ (" \ - msrset r0, %0; \ - nop; " \ - : \ - : "i" (MSR_DCE) \ - : "memory"); -#else - __asm__ __volatile__ (" \ - mfs r12, rmsr; \ - nop; \ - ori r12, r12, %0; \ - mts rmsr, r12; \ - nop; " \ - : \ - : "i" (MSR_DCE) \ + __asm__ __volatile__ (" mfs r12, rmsr; \ + nop; \ + ori r12, r12, %0; \ + mts rmsr, r12; \ + nop; " \ + : \ + : "i" (MSR_DCE) \ : "memory", "r12"); -#endif - } } -void _disable_dcache(void) +static inline void __disable_dcache_nomsr(void) { -#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR - __asm__ __volatile__ (" \ - msrclr r0, %0; \ - nop; " \ - : \ - : "i" (MSR_DCE) \ - : "memory"); -#else - __asm__ __volatile__ (" \ - mfs r12, rmsr; \ - nop; \ - andi r12, r12, ~%0; \ - mts rmsr, r12; \ - nop; " \ - : \ - : "i" (MSR_DCE) \ + __asm__ __volatile__ (" mfs r12, rmsr; \ + nop; \ + andi r12, r12, ~%0; \ + mts rmsr, r12; \ + nop; " \ + : \ + : "i" (MSR_DCE) \ : "memory", "r12"); -#endif } -void _invalidate_dcache(unsigned int addr) + +/* Helper macro for computing the limits of cache range loops */ +#define CACHE_LOOP_LIMITS(start, end, cache_line_length, cache_size) \ +do { \ + int align = ~(cache_line_length - 1); \ + end = min(start + cache_size, end); \ + start &= align; \ + end = ((end & align) + cache_line_length); \ +} while (0); + +/* + * Helper macro to loop over the specified cache_size/line_length and + * execute 'op' on that cacheline + */ +#define CACHE_ALL_LOOP(cache_size, line_length, op) \ +do { \ + unsigned int len = cache_size; \ + int step = -line_length; \ + BUG_ON(step >= 0); \ + \ + __asm__ __volatile__ (" 1: " #op " %0, r0; \ + bgtid %0, 1b; \ + addk %0, %0, %1; \ + " : : "r" (len), "r" (step) \ + : "memory"); \ +} while (0); + + +#define CACHE_ALL_LOOP2(cache_size, line_length, op) \ +do { \ + unsigned int len = cache_size; \ + int step = -line_length; \ + BUG_ON(step >= 0); \ + \ + __asm__ __volatile__ (" 1: " #op " r0, %0; \ + bgtid %0, 1b; \ + addk %0, %0, %1; \ + " : : "r" (len), "r" (step) \ + : "memory"); \ +} while (0); + +/* for wdc.flush/clear */ +#define CACHE_RANGE_LOOP_2(start, end, line_length, op) \ +do { \ + int step = -line_length; \ + int count = end - start; \ + BUG_ON(count <= 0); \ + \ + __asm__ __volatile__ (" 1: " #op " %0, %1; \ + bgtid %1, 1b; \ + addk %1, %1, %2; \ + " : : "r" (start), "r" (count), \ + "r" (step) : "memory"); \ +} while (0); + +/* It is used only first parameter for OP - for wic, wdc */ +#define CACHE_RANGE_LOOP_1(start, end, line_length, op) \ +do { \ + int step = -line_length; \ + int count = end - start; \ + BUG_ON(count <= 0); \ + \ + __asm__ __volatile__ (" 1: addk %0, %0, %1; \ + " #op " %0, r0; \ + bgtid %1, 1b; \ + addk %1, %1, %2; \ + " : : "r" (start), "r" (count), \ + "r" (step) : "memory"); \ +} while (0); + +static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end) { - __asm__ __volatile__ (" \ - wdc %0, r0" \ - : \ - : "r" (addr)); + unsigned long flags; + + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); + + CACHE_LOOP_LIMITS(start, end, + cpuinfo.icache_line_length, cpuinfo.icache_size); + + local_irq_save(flags); + __disable_icache_msr(); + + CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); + + __enable_icache_msr(); + local_irq_restore(flags); } -void __invalidate_icache_all(void) +static void __flush_icache_range_nomsr_irq(unsigned long start, + unsigned long end) { - unsigned int i; - unsigned flags; + unsigned long flags; - if (cpuinfo.use_icache) { - local_irq_save(flags); - __disable_icache(); + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); - /* Just loop through cache size and invalidate, no need to add - CACHE_BASE address */ - for (i = 0; i < cpuinfo.icache_size; - i += cpuinfo.icache_line) - __invalidate_icache(i); + CACHE_LOOP_LIMITS(start, end, + cpuinfo.icache_line_length, cpuinfo.icache_size); - __enable_icache(); - local_irq_restore(flags); - } + local_irq_save(flags); + __disable_icache_nomsr(); + + CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); + + __enable_icache_nomsr(); + local_irq_restore(flags); } -void __invalidate_icache_range(unsigned long start, unsigned long end) +static void __flush_icache_range_noirq(unsigned long start, + unsigned long end) { - unsigned int i; - unsigned flags; - unsigned int align; - - if (cpuinfo.use_icache) { - /* - * No need to cover entire cache range, - * just cover cache footprint - */ - end = min(start + cpuinfo.icache_size, end); - align = ~(cpuinfo.icache_line - 1); - start &= align; /* Make sure we are aligned */ - /* Push end up to the next cache line */ - end = ((end & align) + cpuinfo.icache_line); - - local_irq_save(flags); - __disable_icache(); - - for (i = start; i < end; i += cpuinfo.icache_line) - __invalidate_icache(i); - - __enable_icache(); - local_irq_restore(flags); - } + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); + + CACHE_LOOP_LIMITS(start, end, + cpuinfo.icache_line_length, cpuinfo.icache_size); + CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); +} + +static void __flush_icache_all_msr_irq(void) +{ + unsigned long flags; + + pr_debug("%s\n", __func__); + + local_irq_save(flags); + __disable_icache_msr(); + + CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); + + __enable_icache_msr(); + local_irq_restore(flags); +} + +static void __flush_icache_all_nomsr_irq(void) +{ + unsigned long flags; + + pr_debug("%s\n", __func__); + + local_irq_save(flags); + __disable_icache_nomsr(); + + CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); + + __enable_icache_nomsr(); + local_irq_restore(flags); } -void __invalidate_icache_page(struct vm_area_struct *vma, struct page *page) +static void __flush_icache_all_noirq(void) { - __invalidate_icache_all(); + pr_debug("%s\n", __func__); + CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); } -void __invalidate_icache_user_range(struct vm_area_struct *vma, - struct page *page, unsigned long adr, - int len) +static void __invalidate_dcache_all_msr_irq(void) { - __invalidate_icache_all(); + unsigned long flags; + + pr_debug("%s\n", __func__); + + local_irq_save(flags); + __disable_dcache_msr(); + + CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc); + + __enable_dcache_msr(); + local_irq_restore(flags); } -void __invalidate_cache_sigtramp(unsigned long addr) +static void __invalidate_dcache_all_nomsr_irq(void) { - __invalidate_icache_range(addr, addr + 8); + unsigned long flags; + + pr_debug("%s\n", __func__); + + local_irq_save(flags); + __disable_dcache_nomsr(); + + CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc); + + __enable_dcache_nomsr(); + local_irq_restore(flags); } -void __invalidate_dcache_all(void) +static void __invalidate_dcache_all_noirq_wt(void) { - unsigned int i; - unsigned flags; - - if (cpuinfo.use_dcache) { - local_irq_save(flags); - __disable_dcache(); - - /* - * Just loop through cache size and invalidate, - * no need to add CACHE_BASE address - */ - for (i = 0; i < cpuinfo.dcache_size; - i += cpuinfo.dcache_line) - __invalidate_dcache(i); - - __enable_dcache(); - local_irq_restore(flags); - } + pr_debug("%s\n", __func__); + CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc) } -void __invalidate_dcache_range(unsigned long start, unsigned long end) +/* FIXME this is weird - should be only wdc but not work + * MS: I am getting bus errors and other weird things */ +static void __invalidate_dcache_all_wb(void) { + pr_debug("%s\n", __func__); + CACHE_ALL_LOOP2(cpuinfo.dcache_size, cpuinfo.dcache_line_length, + wdc.clear) + +#if 0 unsigned int i; - unsigned flags; - unsigned int align; - - if (cpuinfo.use_dcache) { - /* - * No need to cover entire cache range, - * just cover cache footprint - */ - end = min(start + cpuinfo.dcache_size, end); - align = ~(cpuinfo.dcache_line - 1); - start &= align; /* Make sure we are aligned */ - /* Push end up to the next cache line */ - end = ((end & align) + cpuinfo.dcache_line); - local_irq_save(flags); - __disable_dcache(); - - for (i = start; i < end; i += cpuinfo.dcache_line) - __invalidate_dcache(i); - - __enable_dcache(); - local_irq_restore(flags); - } + + pr_debug("%s\n", __func__); + + /* Just loop through cache size and invalidate it */ + for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) + __invalidate_dcache(0, i); +#endif +} + +static void __invalidate_dcache_range_wb(unsigned long start, + unsigned long end) +{ + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); + + CACHE_LOOP_LIMITS(start, end, + cpuinfo.dcache_line_length, cpuinfo.dcache_size); + CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear); +} + +static void __invalidate_dcache_range_nomsr_wt(unsigned long start, + unsigned long end) +{ + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); + CACHE_LOOP_LIMITS(start, end, + cpuinfo.dcache_line_length, cpuinfo.dcache_size); + + CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); } -void __invalidate_dcache_page(struct vm_area_struct *vma, struct page *page) +static void __invalidate_dcache_range_msr_irq_wt(unsigned long start, + unsigned long end) { - __invalidate_dcache_all(); + unsigned long flags; + + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); + CACHE_LOOP_LIMITS(start, end, + cpuinfo.dcache_line_length, cpuinfo.dcache_size); + + local_irq_save(flags); + __disable_dcache_msr(); + + CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); + + __enable_dcache_msr(); + local_irq_restore(flags); +} + +static void __invalidate_dcache_range_nomsr_irq(unsigned long start, + unsigned long end) +{ + unsigned long flags; + + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); + + CACHE_LOOP_LIMITS(start, end, + cpuinfo.dcache_line_length, cpuinfo.dcache_size); + + local_irq_save(flags); + __disable_dcache_nomsr(); + + CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); + + __enable_dcache_nomsr(); + local_irq_restore(flags); +} + +static void __flush_dcache_all_wb(void) +{ + pr_debug("%s\n", __func__); + CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, + wdc.flush); } -void __invalidate_dcache_user_range(struct vm_area_struct *vma, - struct page *page, unsigned long adr, - int len) +static void __flush_dcache_range_wb(unsigned long start, unsigned long end) { - __invalidate_dcache_all(); + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); + + CACHE_LOOP_LIMITS(start, end, + cpuinfo.dcache_line_length, cpuinfo.dcache_size); + CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush); +} + +/* struct for wb caches and for wt caches */ +struct scache *mbc; + +/* new wb cache model */ +const struct scache wb_msr = { + .ie = __enable_icache_msr, + .id = __disable_icache_msr, + .ifl = __flush_icache_all_noirq, + .iflr = __flush_icache_range_noirq, + .iin = __flush_icache_all_noirq, + .iinr = __flush_icache_range_noirq, + .de = __enable_dcache_msr, + .dd = __disable_dcache_msr, + .dfl = __flush_dcache_all_wb, + .dflr = __flush_dcache_range_wb, + .din = __invalidate_dcache_all_wb, + .dinr = __invalidate_dcache_range_wb, +}; + +/* There is only difference in ie, id, de, dd functions */ +const struct scache wb_nomsr = { + .ie = __enable_icache_nomsr, + .id = __disable_icache_nomsr, + .ifl = __flush_icache_all_noirq, + .iflr = __flush_icache_range_noirq, + .iin = __flush_icache_all_noirq, + .iinr = __flush_icache_range_noirq, + .de = __enable_dcache_nomsr, + .dd = __disable_dcache_nomsr, + .dfl = __flush_dcache_all_wb, + .dflr = __flush_dcache_range_wb, + .din = __invalidate_dcache_all_wb, + .dinr = __invalidate_dcache_range_wb, +}; + +/* Old wt cache model with disabling irq and turn off cache */ +const struct scache wt_msr = { + .ie = __enable_icache_msr, + .id = __disable_icache_msr, + .ifl = __flush_icache_all_msr_irq, + .iflr = __flush_icache_range_msr_irq, + .iin = __flush_icache_all_msr_irq, + .iinr = __flush_icache_range_msr_irq, + .de = __enable_dcache_msr, + .dd = __disable_dcache_msr, + .dfl = __invalidate_dcache_all_msr_irq, + .dflr = __invalidate_dcache_range_msr_irq_wt, + .din = __invalidate_dcache_all_msr_irq, + .dinr = __invalidate_dcache_range_msr_irq_wt, +}; + +const struct scache wt_nomsr = { + .ie = __enable_icache_nomsr, + .id = __disable_icache_nomsr, + .ifl = __flush_icache_all_nomsr_irq, + .iflr = __flush_icache_range_nomsr_irq, + .iin = __flush_icache_all_nomsr_irq, + .iinr = __flush_icache_range_nomsr_irq, + .de = __enable_dcache_nomsr, + .dd = __disable_dcache_nomsr, + .dfl = __invalidate_dcache_all_nomsr_irq, + .dflr = __invalidate_dcache_range_nomsr_irq, + .din = __invalidate_dcache_all_nomsr_irq, + .dinr = __invalidate_dcache_range_nomsr_irq, +}; + +/* New wt cache model for newer Microblaze versions */ +const struct scache wt_msr_noirq = { + .ie = __enable_icache_msr, + .id = __disable_icache_msr, + .ifl = __flush_icache_all_noirq, + .iflr = __flush_icache_range_noirq, + .iin = __flush_icache_all_noirq, + .iinr = __flush_icache_range_noirq, + .de = __enable_dcache_msr, + .dd = __disable_dcache_msr, + .dfl = __invalidate_dcache_all_noirq_wt, + .dflr = __invalidate_dcache_range_nomsr_wt, + .din = __invalidate_dcache_all_noirq_wt, + .dinr = __invalidate_dcache_range_nomsr_wt, +}; + +const struct scache wt_nomsr_noirq = { + .ie = __enable_icache_nomsr, + .id = __disable_icache_nomsr, + .ifl = __flush_icache_all_noirq, + .iflr = __flush_icache_range_noirq, + .iin = __flush_icache_all_noirq, + .iinr = __flush_icache_range_noirq, + .de = __enable_dcache_nomsr, + .dd = __disable_dcache_nomsr, + .dfl = __invalidate_dcache_all_noirq_wt, + .dflr = __invalidate_dcache_range_nomsr_wt, + .din = __invalidate_dcache_all_noirq_wt, + .dinr = __invalidate_dcache_range_nomsr_wt, +}; + +/* CPU version code for 7.20.c - see arch/microblaze/kernel/cpu/cpuinfo.c */ +#define CPUVER_7_20_A 0x0c +#define CPUVER_7_20_D 0x0f + +#define INFO(s) printk(KERN_INFO "cache: " s " \n"); + +void microblaze_cache_init(void) +{ + if (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) { + if (cpuinfo.dcache_wb) { + INFO("wb_msr"); + mbc = (struct scache *)&wb_msr; + if (cpuinfo.ver_code < CPUVER_7_20_D) { + /* MS: problem with signal handling - hw bug */ + INFO("WB won't work properly"); + } + } else { + if (cpuinfo.ver_code >= CPUVER_7_20_A) { + INFO("wt_msr_noirq"); + mbc = (struct scache *)&wt_msr_noirq; + } else { + INFO("wt_msr"); + mbc = (struct scache *)&wt_msr; + } + } + } else { + if (cpuinfo.dcache_wb) { + INFO("wb_nomsr"); + mbc = (struct scache *)&wb_nomsr; + if (cpuinfo.ver_code < CPUVER_7_20_D) { + /* MS: problem with signal handling - hw bug */ + INFO("WB won't work properly"); + } + } else { + if (cpuinfo.ver_code >= CPUVER_7_20_A) { + INFO("wt_nomsr_noirq"); + mbc = (struct scache *)&wt_nomsr_noirq; + } else { + INFO("wt_nomsr"); + mbc = (struct scache *)&wt_nomsr; + } + } + } } diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c index c259786e7faa1c51853d3a0e31621ea1ddd154c7..f72dbd66c84411041c59705f72d253ee896af574 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c @@ -21,8 +21,14 @@ */ #define CI(c, p) { ci->c = PVR_##p(pvr); } + +#if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_SERIAL_UARTLITE_CONSOLE) #define err_printk(x) \ early_printk("ERROR: Microblaze " x "-different for PVR and DTS\n"); +#else +#define err_printk(x) \ + printk(KERN_INFO "ERROR: Microblaze " x "-different for PVR and DTS\n"); +#endif void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) { @@ -70,7 +76,7 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) CI(use_icache, USE_ICACHE); CI(icache_tagbits, ICACHE_ADDR_TAG_BITS); CI(icache_write, ICACHE_ALLOW_WR); - CI(icache_line, ICACHE_LINE_LEN); + ci->icache_line_length = PVR_ICACHE_LINE_LEN(pvr) << 2; CI(icache_size, ICACHE_BYTE_SIZE); CI(icache_base, ICACHE_BASEADDR); CI(icache_high, ICACHE_HIGHADDR); @@ -78,11 +84,16 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) CI(use_dcache, USE_DCACHE); CI(dcache_tagbits, DCACHE_ADDR_TAG_BITS); CI(dcache_write, DCACHE_ALLOW_WR); - CI(dcache_line, DCACHE_LINE_LEN); + ci->dcache_line_length = PVR_DCACHE_LINE_LEN(pvr) << 2; CI(dcache_size, DCACHE_BYTE_SIZE); CI(dcache_base, DCACHE_BASEADDR); CI(dcache_high, DCACHE_HIGHADDR); + temp = PVR_DCACHE_USE_WRITEBACK(pvr); + if (ci->dcache_wb != temp) + err_printk("DCACHE WB"); + ci->dcache_wb = temp; + CI(use_dopb, D_OPB); CI(use_iopb, I_OPB); CI(use_dlmb, D_LMB); diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c index adb448f93d5fd3157c89b2336ca52488da6ecb42..6095aa6b5c88ef17d6cdab7d7393d49dfd0ee286 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-static.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c @@ -72,12 +72,12 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu) ci->use_icache = fcpu(cpu, "xlnx,use-icache"); ci->icache_tagbits = fcpu(cpu, "xlnx,addr-tag-bits"); ci->icache_write = fcpu(cpu, "xlnx,allow-icache-wr"); - ci->icache_line = fcpu(cpu, "xlnx,icache-line-len") << 2; - if (!ci->icache_line) { + ci->icache_line_length = fcpu(cpu, "xlnx,icache-line-len") << 2; + if (!ci->icache_line_length) { if (fcpu(cpu, "xlnx,icache-use-fsl")) - ci->icache_line = 4 << 2; + ci->icache_line_length = 4 << 2; else - ci->icache_line = 1 << 2; + ci->icache_line_length = 1 << 2; } ci->icache_size = fcpu(cpu, "i-cache-size"); ci->icache_base = fcpu(cpu, "i-cache-baseaddr"); @@ -86,16 +86,17 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu) ci->use_dcache = fcpu(cpu, "xlnx,use-dcache"); ci->dcache_tagbits = fcpu(cpu, "xlnx,dcache-addr-tag"); ci->dcache_write = fcpu(cpu, "xlnx,allow-dcache-wr"); - ci->dcache_line = fcpu(cpu, "xlnx,dcache-line-len") << 2; - if (!ci->dcache_line) { + ci->dcache_line_length = fcpu(cpu, "xlnx,dcache-line-len") << 2; + if (!ci->dcache_line_length) { if (fcpu(cpu, "xlnx,dcache-use-fsl")) - ci->dcache_line = 4 << 2; + ci->dcache_line_length = 4 << 2; else - ci->dcache_line = 1 << 2; + ci->dcache_line_length = 1 << 2; } ci->dcache_size = fcpu(cpu, "d-cache-size"); ci->dcache_base = fcpu(cpu, "d-cache-baseaddr"); ci->dcache_high = fcpu(cpu, "d-cache-highaddr"); + ci->dcache_wb = fcpu(cpu, "xlnx,dcache-use-writeback"); ci->use_dopb = fcpu(cpu, "xlnx,d-opb"); ci->use_iopb = fcpu(cpu, "xlnx,i-opb"); diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index 3539babc1c18ddb2ef59c3ae3e4c5ee2b571ca12..991d71311b0ebaad156a03e03f9f4f2cce277d30 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -29,11 +29,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = { {"7.20.a", 0x0c}, {"7.20.b", 0x0d}, {"7.20.c", 0x0e}, - /* FIXME There is no keycode defined in MBV for these versions */ - {"2.10.a", 0x10}, - {"3.00.a", 0x20}, - {"4.00.a", 0x30}, - {"4.00.b", 0x40}, + {"7.20.d", 0x0f}, + {"7.30.a", 0x10}, {NULL, 0}, }; diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c index 4dcfccdbc36480beec86d4fd24c31ccf0d8cdc6d..0c912b2a8e03ae72c1073ff94185595f18a3ab68 100644 --- a/arch/microblaze/kernel/cpu/mb.c +++ b/arch/microblaze/kernel/cpu/mb.c @@ -103,11 +103,15 @@ static int show_cpuinfo(struct seq_file *m, void *v) else count += seq_printf(m, "Icache:\t\tno\n"); - if (cpuinfo.use_dcache) + if (cpuinfo.use_dcache) { count += seq_printf(m, "Dcache:\t\t%ukB\n", cpuinfo.dcache_size >> 10); - else + if (cpuinfo.dcache_wb) + count += seq_printf(m, "\t\twrite-back\n"); + else + count += seq_printf(m, "\t\twrite-through\n"); + } else count += seq_printf(m, "Dcache:\t\tno\n"); count += seq_printf(m, diff --git a/arch/microblaze/kernel/cpu/pvr.c b/arch/microblaze/kernel/cpu/pvr.c index c9a4340ddd53d65a4cd171ea2d5622154208a72f..9bee9382bf74587031e01fde8e828f243683d147 100644 --- a/arch/microblaze/kernel/cpu/pvr.c +++ b/arch/microblaze/kernel/cpu/pvr.c @@ -45,7 +45,7 @@ int cpu_has_pvr(void) { - unsigned flags; + unsigned long flags; unsigned pvr0; local_save_flags(flags); diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 9083d85376a4dc57b6e7c535869eb4b3f11570f5..95b0855802dff0b342d77cfe279f1eaa23bf6828 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S @@ -208,8 +208,6 @@ ENTRY(_user_exception) lwi r1, r1, TS_THREAD_INFO /* get the thread info */ /* calculate kernel stack pointer */ addik r1, r1, THREAD_SIZE - PT_SIZE - swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */ - lwi r11, r0, PER_CPU(KM) /* load mode indicator */ 2: swi r11, r1, PT_MODE /* store the mode */ lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */ diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index e3ecb36dd554ebc3504e08ac369a29359e8c304f..3bad4ff494711c205b3536a686e4aa36d9913b94 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -31,6 +31,8 @@ #include #include +#undef DEBUG + /* The size of a state save frame. */ #define STATE_SAVE_SIZE (PT_SIZE + STATE_SAVE_ARG_SPACE) @@ -352,10 +354,12 @@ C_ENTRY(_user_exception): add r12, r12, r12; /* convert num -> ptr */ add r12, r12, r12; +#ifdef DEBUG /* Trac syscalls and stored them to r0_ram */ lwi r3, r12, 0x400 + r0_ram addi r3, r3, 1 swi r3, r12, 0x400 + r0_ram +#endif # Find and jump into the syscall handler. lwi r12, r12, sys_call_table @@ -496,17 +500,6 @@ C_ENTRY(sys_execve): brid microblaze_execve; /* Do real work (tail-call).*/ nop; -C_ENTRY(sys_rt_sigsuspend_wrapper): - swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - swi r4, r1, PTO+PT_R4; - la r7, r1, PTO; /* add user context as 3rd arg */ - brlid r15, sys_rt_sigsuspend; /* Do real work.*/ - nop; - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - lwi r4, r1, PTO+PT_R4; - bri ret_from_trap /* fall through will not work here due to align */ - nop; - C_ENTRY(sys_rt_sigreturn_wrapper): swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ swi r4, r1, PTO+PT_R4; @@ -711,15 +704,11 @@ C_ENTRY(ret_from_exc): * (in a possibly modified form) after do_signal returns. * store return registers separately because this macros is use * for others exceptions */ - swi r3, r1, PTO + PT_R3; - swi r4, r1, PTO + PT_R4; la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ add r6, r0, r0; /* Arg 2: sigset_t *oldset */ addi r7, r0, 0; /* Arg 3: int in_syscall */ bralid r15, do_signal; /* Handle any signals */ nop; - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - lwi r4, r1, PTO+PT_R4; /* Finally, return to user state. */ 1: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ diff --git a/arch/microblaze/kernel/ftrace.c b/arch/microblaze/kernel/ftrace.c new file mode 100644 index 0000000000000000000000000000000000000000..388b31ca65a1ed2c9d9314b57cdc23dbee2bf920 --- /dev/null +++ b/arch/microblaze/kernel/ftrace.c @@ -0,0 +1,237 @@ +/* + * Ftrace support for Microblaze. + * + * Copyright (C) 2009 Michal Simek + * Copyright (C) 2009 PetaLogix + * + * Based on MIPS and PowerPC ftrace code + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +/* + * Hook the return address and push it in the stack of return addrs + * in current thread info. + */ +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) +{ + unsigned long old; + int faulted, err; + struct ftrace_graph_ent trace; + unsigned long return_hooker = (unsigned long) + &return_to_handler; + + if (unlikely(atomic_read(¤t->tracing_graph_pause))) + return; + + /* + * Protect against fault, even if it shouldn't + * happen. This tool is too much intrusive to + * ignore such a protection. + */ + asm volatile(" 1: lwi %0, %2, 0; \ + 2: swi %3, %2, 0; \ + addik %1, r0, 0; \ + 3: \ + .section .fixup, \"ax\"; \ + 4: brid 3b; \ + addik %1, r0, 1; \ + .previous; \ + .section __ex_table,\"a\"; \ + .word 1b,4b; \ + .word 2b,4b; \ + .previous;" \ + : "=&r" (old), "=r" (faulted) + : "r" (parent), "r" (return_hooker) + ); + + if (unlikely(faulted)) { + ftrace_graph_stop(); + WARN_ON(1); + return; + } + + err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0); + if (err == -EBUSY) { + *parent = old; + return; + } + + trace.func = self_addr; + /* Only trace if the calling function expects to */ + if (!ftrace_graph_entry(&trace)) { + current->curr_ret_stack--; + *parent = old; + } +} +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + +#ifdef CONFIG_DYNAMIC_FTRACE +/* save value to addr - it is save to do it in asm */ +static int ftrace_modify_code(unsigned long addr, unsigned int value) +{ + int faulted = 0; + + __asm__ __volatile__(" 1: swi %2, %1, 0; \ + addik %0, r0, 0; \ + 2: \ + .section .fixup, \"ax\"; \ + 3: brid 2b; \ + addik %0, r0, 1; \ + .previous; \ + .section __ex_table,\"a\"; \ + .word 1b,3b; \ + .previous;" \ + : "=r" (faulted) + : "r" (addr), "r" (value) + ); + + if (unlikely(faulted)) + return -EFAULT; + + return 0; +} + +#define MICROBLAZE_NOP 0x80000000 +#define MICROBLAZE_BRI 0xb800000C + +static unsigned int recorded; /* if save was or not */ +static unsigned int imm; /* saving whole imm instruction */ + +/* There are two approaches howto solve ftrace_make nop function - look below */ +#undef USE_FTRACE_NOP + +#ifdef USE_FTRACE_NOP +static unsigned int bralid; /* saving whole bralid instruction */ +#endif + +int ftrace_make_nop(struct module *mod, + struct dyn_ftrace *rec, unsigned long addr) +{ + /* we have this part of code which we are working with + * b000c000 imm -16384 + * b9fc8e30 bralid r15, -29136 // c0008e30 <_mcount> + * 80000000 or r0, r0, r0 + * + * The first solution (!USE_FTRACE_NOP-could be called branch solution) + * b000c000 bri 12 (0xC - jump to any other instruction) + * b9fc8e30 bralid r15, -29136 // c0008e30 <_mcount> + * 80000000 or r0, r0, r0 + * any other instruction + * + * The second solution (USE_FTRACE_NOP) - no jump just nops + * 80000000 or r0, r0, r0 + * 80000000 or r0, r0, r0 + * 80000000 or r0, r0, r0 + */ + int ret = 0; + + if (recorded == 0) { + recorded = 1; + imm = *(unsigned int *)rec->ip; + pr_debug("%s: imm:0x%x\n", __func__, imm); +#ifdef USE_FTRACE_NOP + bralid = *(unsigned int *)(rec->ip + 4); + pr_debug("%s: bralid 0x%x\n", __func__, bralid); +#endif /* USE_FTRACE_NOP */ + } + +#ifdef USE_FTRACE_NOP + ret = ftrace_modify_code(rec->ip, MICROBLAZE_NOP); + ret += ftrace_modify_code(rec->ip + 4, MICROBLAZE_NOP); +#else /* USE_FTRACE_NOP */ + ret = ftrace_modify_code(rec->ip, MICROBLAZE_BRI); +#endif /* USE_FTRACE_NOP */ + return ret; +} + +static int ret_addr; /* initialized as 0 by default */ + +/* I believe that first is called ftrace_make_nop before this function */ +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) +{ + int ret; + ret_addr = addr; /* saving where the barrier jump is */ + pr_debug("%s: addr:0x%x, rec->ip: 0x%x, imm:0x%x\n", + __func__, (unsigned int)addr, (unsigned int)rec->ip, imm); + ret = ftrace_modify_code(rec->ip, imm); +#ifdef USE_FTRACE_NOP + pr_debug("%s: bralid:0x%x\n", __func__, bralid); + ret += ftrace_modify_code(rec->ip + 4, bralid); +#endif /* USE_FTRACE_NOP */ + return ret; +} + +int __init ftrace_dyn_arch_init(void *data) +{ + /* The return code is retured via data */ + *(unsigned long *)data = 0; + + return 0; +} + +int ftrace_update_ftrace_func(ftrace_func_t func) +{ + unsigned long ip = (unsigned long)(&ftrace_call); + unsigned int upper = (unsigned int)func; + unsigned int lower = (unsigned int)func; + int ret = 0; + + /* create proper saving to ftrace_call poll */ + upper = 0xb0000000 + (upper >> 16); /* imm func_upper */ + lower = 0x32800000 + (lower & 0xFFFF); /* addik r20, r0, func_lower */ + + pr_debug("%s: func=0x%x, ip=0x%x, upper=0x%x, lower=0x%x\n", + __func__, (unsigned int)func, (unsigned int)ip, upper, lower); + + /* save upper and lower code */ + ret = ftrace_modify_code(ip, upper); + ret += ftrace_modify_code(ip + 4, lower); + + /* We just need to remove the rtsd r15, 8 by NOP */ + BUG_ON(!ret_addr); + if (ret_addr) + ret += ftrace_modify_code(ret_addr, MICROBLAZE_NOP); + else + ret = 1; /* fault */ + + /* All changes are done - lets do caches consistent */ + flush_icache(); + return ret; +} + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +unsigned int old_jump; /* saving place for jump instruction */ + +int ftrace_enable_ftrace_graph_caller(void) +{ + unsigned int ret; + unsigned long ip = (unsigned long)(&ftrace_call_graph); + + old_jump = *(unsigned int *)ip; /* save jump over instruction */ + ret = ftrace_modify_code(ip, MICROBLAZE_NOP); + flush_icache(); + + pr_debug("%s: Replace instruction: 0x%x\n", __func__, old_jump); + return ret; +} + +int ftrace_disable_ftrace_graph_caller(void) +{ + unsigned int ret; + unsigned long ip = (unsigned long)(&ftrace_call_graph); + + ret = ftrace_modify_code(ip, old_jump); + flush_icache(); + + pr_debug("%s\n", __func__); + return ret; +} +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ +#endif /* CONFIG_DYNAMIC_FTRACE */ diff --git a/arch/microblaze/kernel/heartbeat.c b/arch/microblaze/kernel/heartbeat.c index 1bdf20222b92ba0ecdb0fe8b35488f7653ab6909..522751737cfad936fe5193a93fd0105c874c04cc 100644 --- a/arch/microblaze/kernel/heartbeat.c +++ b/arch/microblaze/kernel/heartbeat.c @@ -45,6 +45,7 @@ void heartbeat(void) void setup_heartbeat(void) { struct device_node *gpio = NULL; + int *prop; int j; char *gpio_list[] = { "xlnx,xps-gpio-1.00.a", @@ -58,10 +59,14 @@ void setup_heartbeat(void) break; } - base_addr = *(int *) of_get_property(gpio, "reg", NULL); - base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE); - printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr); + if (gpio) { + base_addr = *(int *) of_get_property(gpio, "reg", NULL); + base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE); + printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr); - if (*(int *) of_get_property(gpio, "xlnx,is-bidir", NULL)) - out_be32(base_addr + 4, 0); /* GPIO is configured as output */ + /* GPIO is configured as output */ + prop = (int *) of_get_property(gpio, "xlnx,is-bidir", NULL); + if (prop) + out_be32(base_addr + 4, 0); + } } diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c index 6eea6f92b84e19780b781bdad3da277fed57a4bb..03172c1da770c69eda75e8c72aca7a648c7ada53 100644 --- a/arch/microblaze/kernel/intc.c +++ b/arch/microblaze/kernel/intc.c @@ -42,8 +42,16 @@ unsigned int nr_irq; static void intc_enable_or_unmask(unsigned int irq) { + unsigned long mask = 1 << irq; pr_debug("enable_or_unmask: %d\n", irq); - out_be32(INTC_BASE + SIE, 1 << irq); + out_be32(INTC_BASE + SIE, mask); + + /* ack level irqs because they can't be acked during + * ack function since the handle_level_irq function + * acks the irq before calling the interrupt handler + */ + if (irq_desc[irq].status & IRQ_LEVEL) + out_be32(INTC_BASE + IAR, mask); } static void intc_disable_or_mask(unsigned int irq) diff --git a/arch/microblaze/kernel/mcount.S b/arch/microblaze/kernel/mcount.S new file mode 100644 index 0000000000000000000000000000000000000000..e7eaa7a8cbd34d2404fae12769b8b3b4365ff752 --- /dev/null +++ b/arch/microblaze/kernel/mcount.S @@ -0,0 +1,170 @@ +/* + * Low-level ftrace handling + * + * Copyright (C) 2009 Michal Simek + * Copyright (C) 2009 PetaLogix + * + * 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 + +#define NOALIGN_ENTRY(name) .globl name; name: + +/* FIXME MS: I think that I don't need to save all regs */ +#define SAVE_REGS \ + addik r1, r1, -120; \ + swi r2, r1, 4; \ + swi r3, r1, 8; \ + swi r4, r1, 12; \ + swi r5, r1, 116; \ + swi r6, r1, 16; \ + swi r7, r1, 20; \ + swi r8, r1, 24; \ + swi r9, r1, 28; \ + swi r10, r1, 32; \ + swi r11, r1, 36; \ + swi r12, r1, 40; \ + swi r13, r1, 44; \ + swi r14, r1, 48; \ + swi r16, r1, 52; \ + swi r17, r1, 56; \ + swi r18, r1, 60; \ + swi r19, r1, 64; \ + swi r20, r1, 68; \ + swi r21, r1, 72; \ + swi r22, r1, 76; \ + swi r23, r1, 80; \ + swi r24, r1, 84; \ + swi r25, r1, 88; \ + swi r26, r1, 92; \ + swi r27, r1, 96; \ + swi r28, r1, 100; \ + swi r29, r1, 104; \ + swi r30, r1, 108; \ + swi r31, r1, 112; + +#define RESTORE_REGS \ + lwi r2, r1, 4; \ + lwi r3, r1, 8; \ + lwi r4, r1, 12; \ + lwi r5, r1, 116; \ + lwi r6, r1, 16; \ + lwi r7, r1, 20; \ + lwi r8, r1, 24; \ + lwi r9, r1, 28; \ + lwi r10, r1, 32; \ + lwi r11, r1, 36; \ + lwi r12, r1, 40; \ + lwi r13, r1, 44; \ + lwi r14, r1, 48; \ + lwi r16, r1, 52; \ + lwi r17, r1, 56; \ + lwi r18, r1, 60; \ + lwi r19, r1, 64; \ + lwi r20, r1, 68; \ + lwi r21, r1, 72; \ + lwi r22, r1, 76; \ + lwi r23, r1, 80; \ + lwi r24, r1, 84; \ + lwi r25, r1, 88; \ + lwi r26, r1, 92; \ + lwi r27, r1, 96; \ + lwi r28, r1, 100; \ + lwi r29, r1, 104; \ + lwi r30, r1, 108; \ + lwi r31, r1, 112; \ + addik r1, r1, 120; + +ENTRY(ftrace_stub) + rtsd r15, 8; + nop; + +ENTRY(_mcount) +#ifdef CONFIG_DYNAMIC_FTRACE +ENTRY(ftrace_caller) + /* MS: It is just barrier which is removed from C code */ + rtsd r15, 8 + nop +#endif /* CONFIG_DYNAMIC_FTRACE */ + SAVE_REGS + swi r15, r1, 0; + /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST begin of checking */ + lwi r5, r0, function_trace_stop; + bneid r5, end; + nop; + /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST end of checking */ +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +#ifndef CONFIG_DYNAMIC_FTRACE + lwi r5, r0, ftrace_graph_return; + addik r6, r0, ftrace_stub; /* asm implementation */ + cmpu r5, r5, r6; /* ftrace_graph_return != ftrace_stub */ + beqid r5, end_graph_tracer; + nop; + + lwi r6, r0, ftrace_graph_entry; + addik r5, r0, ftrace_graph_entry_stub; /* implemented in C */ + cmpu r5, r5, r6; /* ftrace_graph_entry != ftrace_graph_entry_stub */ + beqid r5, end_graph_tracer; + nop; +#else /* CONFIG_DYNAMIC_FTRACE */ +NOALIGN_ENTRY(ftrace_call_graph) + /* MS: jump over graph function - replaced from C code */ + bri end_graph_tracer +#endif /* CONFIG_DYNAMIC_FTRACE */ + addik r5, r1, 120; /* MS: load parent addr */ + addik r6, r15, 0; /* MS: load current function addr */ + bralid r15, prepare_ftrace_return; + nop; + /* MS: graph was taken that's why - can jump over function trace */ + brid end; + nop; +end_graph_tracer: +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ +#ifndef CONFIG_DYNAMIC_FTRACE + /* MS: test function trace if is taken or not */ + lwi r20, r0, ftrace_trace_function; + addik r6, r0, ftrace_stub; + cmpu r5, r20, r6; /* ftrace_trace_function != ftrace_stub */ + beqid r5, end; /* MS: not taken -> jump over */ + nop; +#else /* CONFIG_DYNAMIC_FTRACE */ +NOALIGN_ENTRY(ftrace_call) +/* instruction for setup imm FUNC_part1, addik r20, r0, FUNC_part2 */ + nop + nop +#endif /* CONFIG_DYNAMIC_FTRACE */ +/* static normal trace */ + lwi r6, r1, 120; /* MS: load parent addr */ + addik r5, r15, 0; /* MS: load current function addr */ + /* MS: here is dependency on previous code */ + brald r15, r20; /* MS: jump to ftrace handler */ + nop; +end: + lwi r15, r1, 0; + RESTORE_REGS + + rtsd r15, 8; /* MS: jump back */ + nop; + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +ENTRY(return_to_handler) + nop; /* MS: just barrier for rtsd r15, 8 */ + nop; + SAVE_REGS + swi r15, r1, 0; + + /* MS: find out returning address */ + bralid r15, ftrace_return_to_handler; + nop; + + /* MS: return value from ftrace_return_to_handler is my returning addr + * must be before restore regs because I have to restore r3 content */ + addik r15, r3, 0; + RESTORE_REGS + + rtsd r15, 8; /* MS: jump back */ + nop; +#endif /* CONFIG_FUNCTION_TRACER */ diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c index 59ff20e33e0cde5b22b7f95fb0517323066c4440..bc4dcb7d3861c50aff24b152f37655c80c937d95 100644 --- a/arch/microblaze/kernel/microblaze_ksyms.c +++ b/arch/microblaze/kernel/microblaze_ksyms.c @@ -18,6 +18,7 @@ #include #include #include +#include #include /* @@ -47,3 +48,7 @@ extern void __umodsi3(void); EXPORT_SYMBOL(__umodsi3); extern char *_ebss; EXPORT_SYMBOL_GPL(_ebss); +#ifdef CONFIG_FUNCTION_TRACER +extern void _mcount(void); +EXPORT_SYMBOL(_mcount); +#endif diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index c592d475b3d890a50061f8f3b265c4516457d749..812f1bf06c9e5cbfb2a88222974e2931d20f9a24 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -15,6 +15,7 @@ #include #include #include +#include void show_regs(struct pt_regs *regs) { diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c new file mode 100644 index 0000000000000000000000000000000000000000..a1721a33042e3d17c25dbc3ec1fddd8d05402a18 --- /dev/null +++ b/arch/microblaze/kernel/reset.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2009 Michal Simek + * Copyright (C) 2009 PetaLogix + * + * 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 + +/* Trigger specific functions */ +#ifdef CONFIG_GPIOLIB + +#include + +static int handle; /* reset pin handle */ +static unsigned int reset_val; + +static int of_reset_gpio_handle(void) +{ + int ret; /* variable which stored handle reset gpio pin */ + struct device_node *root; /* root node */ + struct device_node *gpio; /* gpio node */ + struct of_gpio_chip *of_gc = NULL; + enum of_gpio_flags flags ; + const void *gpio_spec; + + /* find out root node */ + root = of_find_node_by_path("/"); + + /* give me handle for gpio node to be possible allocate pin */ + ret = of_parse_phandles_with_args(root, "hard-reset-gpios", + "#gpio-cells", 0, &gpio, &gpio_spec); + if (ret) { + pr_debug("%s: can't parse gpios property\n", __func__); + goto err0; + } + + of_gc = gpio->data; + if (!of_gc) { + pr_debug("%s: gpio controller %s isn't registered\n", + root->full_name, gpio->full_name); + ret = -ENODEV; + goto err1; + } + + ret = of_gc->xlate(of_gc, root, gpio_spec, &flags); + if (ret < 0) + goto err1; + + ret += of_gc->gc.base; +err1: + of_node_put(gpio); +err0: + pr_debug("%s exited with status %d\n", __func__, ret); + return ret; +} + +void of_platform_reset_gpio_probe(void) +{ + int ret; + handle = of_reset_gpio_handle(); + + if (!gpio_is_valid(handle)) { + printk(KERN_INFO "Skipping unavailable RESET gpio %d (%s)\n", + handle, "reset"); + } + + ret = gpio_request(handle, "reset"); + if (ret < 0) { + printk(KERN_INFO "GPIO pin is already allocated\n"); + return; + } + + /* get current setup value */ + reset_val = gpio_get_value(handle); + /* FIXME maybe worth to perform any action */ + pr_debug("Reset: Gpio output state: 0x%x\n", reset_val); + + /* Setup GPIO as output */ + ret = gpio_direction_output(handle, 0); + if (ret < 0) + goto err; + + /* Setup output direction */ + gpio_set_value(handle, 0); + + printk(KERN_INFO "RESET: Registered gpio device: %d, current val: %d\n", + handle, reset_val); + return; +err: + gpio_free(handle); + return; +} + + +static void gpio_system_reset(void) +{ + gpio_set_value(handle, 1 - reset_val); +} +#else +#define gpio_system_reset() do {} while (0) +void of_platform_reset_gpio_probe(void) +{ + return; +} +#endif + +void machine_restart(char *cmd) +{ + printk(KERN_NOTICE "Machine restart...\n"); + gpio_system_reset(); + dump_stack(); + while (1) + ; +} + +void machine_shutdown(void) +{ + printk(KERN_NOTICE "Machine shutdown...\n"); + while (1) + ; +} + +void machine_halt(void) +{ + printk(KERN_NOTICE "Machine halt...\n"); + while (1) + ; +} + +void machine_power_off(void) +{ + printk(KERN_NOTICE "Machine power off...\n"); + while (1) + ; +} diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index 8c1e0f4dcf18b63c6323a3b8042c68c3774621e0..5372b24ad049cf92cfd881927c21f5e559a54089 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -52,13 +52,12 @@ void __init setup_arch(char **cmdline_p) /* irq_early_init(); */ setup_cpuinfo(); - __invalidate_icache_all(); - __enable_icache(); + microblaze_cache_init(); - __invalidate_dcache_all(); - __enable_dcache(); + enable_dcache(); - panic_timeout = 120; + invalidate_icache(); + enable_icache(); setup_memory(); @@ -131,6 +130,8 @@ void __init machine_early_init(const char *cmdline, unsigned int ram, strlcpy(cmd_line, cmdline, COMMAND_LINE_SIZE); #endif + lockdep_init(); + /* initialize device tree for usage in early_printk */ early_init_devtree((void *)_fdt_start); @@ -186,32 +187,3 @@ static int microblaze_debugfs_init(void) } arch_initcall(microblaze_debugfs_init); #endif - -void machine_restart(char *cmd) -{ - printk(KERN_NOTICE "Machine restart...\n"); - dump_stack(); - while (1) - ; -} - -void machine_shutdown(void) -{ - printk(KERN_NOTICE "Machine shutdown...\n"); - while (1) - ; -} - -void machine_halt(void) -{ - printk(KERN_NOTICE "Machine halt...\n"); - while (1) - ; -} - -void machine_power_off(void) -{ - printk(KERN_NOTICE "Machine power off...\n"); - while (1) - ; -} diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 1c80e4fc40cef1fc0513951c449452ff23139c96..d8d3bb396cd6d7e4b0d82d52fa62960222662ab3 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -44,7 +44,6 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall); - asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs *regs) @@ -176,6 +175,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct rt_sigframe __user *frame; int err = 0; int signal; + unsigned long address = 0; +#ifdef CONFIG_MMU + pmd_t *pmdp; + pte_t *ptep; +#endif frame = get_sigframe(ka, regs, sizeof(*frame)); @@ -216,8 +220,29 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, Negative 8 offset because return is rtsd r15, 8 */ regs->r15 = ((unsigned long)frame->tramp)-8; - __invalidate_cache_sigtramp((unsigned long)frame->tramp); - + address = ((unsigned long)frame->tramp); +#ifdef CONFIG_MMU + pmdp = pmd_offset(pud_offset( + pgd_offset(current->mm, address), + address), address); + + preempt_disable(); + ptep = pte_offset_map(pmdp, address); + if (pte_present(*ptep)) { + address = (unsigned long) page_address(pte_page(*ptep)); + /* MS: I need add offset in page */ + address += ((unsigned long)frame->tramp) & ~PAGE_MASK; + /* MS address is virtual */ + address = virt_to_phys(address); + invalidate_icache_range(address, address + 8); + flush_dcache_range(address, address + 8); + } + pte_unmap(ptep); + preempt_enable(); +#else + flush_icache_range(address, address + 8); + flush_dcache_range(address, address + 8); +#endif if (err) goto give_sigsegv; @@ -233,6 +258,10 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, set_fs(USER_DS); + /* the tracer may want to single-step inside the handler */ + if (test_thread_flag(TIF_SINGLESTEP)) + ptrace_notify(SIGTRAP); + #ifdef DEBUG_SIG printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n", current->comm, current->pid, frame, regs->pc); diff --git a/arch/microblaze/kernel/stacktrace.c b/arch/microblaze/kernel/stacktrace.c new file mode 100644 index 0000000000000000000000000000000000000000..123692f22647f04f76dcc101281697c818edf1b8 --- /dev/null +++ b/arch/microblaze/kernel/stacktrace.c @@ -0,0 +1,65 @@ +/* + * Stack trace support for Microblaze. + * + * Copyright (C) 2009 Michal Simek + * Copyright (C) 2009 PetaLogix + * + * 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 + +/* FIXME initial support */ +void save_stack_trace(struct stack_trace *trace) +{ + unsigned long *sp; + unsigned long addr; + asm("addik %0, r1, 0" : "=r" (sp)); + + while (!kstack_end(sp)) { + addr = *sp++; + if (__kernel_text_address(addr)) { + if (trace->skip > 0) + trace->skip--; + else + trace->entries[trace->nr_entries++] = addr; + + if (trace->nr_entries >= trace->max_entries) + break; + } + } +} +EXPORT_SYMBOL_GPL(save_stack_trace); + +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +{ + unsigned int *sp; + unsigned long addr; + + struct thread_info *ti = task_thread_info(tsk); + + if (tsk == current) + asm("addik %0, r1, 0" : "=r" (sp)); + else + sp = (unsigned int *)ti->cpu_context.r1; + + while (!kstack_end(sp)) { + addr = *sp++; + if (__kernel_text_address(addr)) { + if (trace->skip > 0) + trace->skip--; + else + trace->entries[trace->nr_entries++] = addr; + + if (trace->nr_entries >= trace->max_entries) + break; + } + } +} +EXPORT_SYMBOL_GPL(save_stack_trace_tsk); diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c index 07cabed4b947fafbc4cab9d89201c2ba42aebfdf..9f3c205fb75b71c47086f21f9e80863b6dcd14df 100644 --- a/arch/microblaze/kernel/sys_microblaze.c +++ b/arch/microblaze/kernel/sys_microblaze.c @@ -62,46 +62,14 @@ out: return error; } -asmlinkage long -sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - struct file *file = NULL; - int ret = -EBADF; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) { - printk(KERN_INFO "no fd in mmap\r\n"); - goto out; - } - } - - down_write(¤t->mm->mmap_sem); - ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); -out: - return ret; -} - asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, off_t pgoff) { - int err = -EINVAL; - - if (pgoff & ~PAGE_MASK) { - printk(KERN_INFO "no pagemask in mmap\r\n"); - goto out; - } + if (pgoff & ~PAGE_MASK) + return -EINVAL; - err = sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); -out: - return err; + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); } /* diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index c1ab1dc10898b70e5ef6c9204dae740979c7d3e3..4088be7d4e292ed307cdf4539df4f2b5adfc06be 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -183,7 +183,7 @@ ENTRY(sys_call_table) .long sys_rt_sigpending .long sys_rt_sigtimedwait .long sys_rt_sigqueueinfo - .long sys_rt_sigsuspend_wrapper + .long sys_rt_sigsuspend .long sys_pread64 /* 180 */ .long sys_pwrite64 .long sys_chown @@ -196,7 +196,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* reserved for streams2 */ .long sys_vfork /* 190 */ .long sys_getrlimit - .long sys_mmap2 /* mmap2 */ + .long sys_mmap_pgoff /* mmap2 */ .long sys_truncate64 .long sys_ftruncate64 .long sys_stat64 /* 195 */ @@ -303,7 +303,7 @@ ENTRY(sys_call_table) .long sys_mkdirat .long sys_mknodat .long sys_fchownat - .long sys_ni_syscall + .long sys_futimesat .long sys_fstatat64 /* 300 */ .long sys_unlinkat .long sys_renameat diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index 5499deae7fa68cb155e4e6aefe9b53c0da8c7298..ed61b2f177192e79921fae4e95092374309a3c0f 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c @@ -183,6 +183,31 @@ static cycle_t microblaze_read(struct clocksource *cs) return (cycle_t) (in_be32(TIMER_BASE + TCR1)); } +static struct timecounter microblaze_tc = { + .cc = NULL, +}; + +static cycle_t microblaze_cc_read(const struct cyclecounter *cc) +{ + return microblaze_read(NULL); +} + +static struct cyclecounter microblaze_cc = { + .read = microblaze_cc_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 24, +}; + +int __init init_microblaze_timecounter(void) +{ + microblaze_cc.mult = div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC, + microblaze_cc.shift); + + timecounter_init(µblaze_tc, µblaze_cc, sched_clock()); + + return 0; +} + static struct clocksource clocksource_microblaze = { .name = "microblaze_clocksource", .rating = 300, @@ -204,6 +229,9 @@ static int __init microblaze_clocksource_init(void) out_be32(TIMER_BASE + TCSR1, in_be32(TIMER_BASE + TCSR1) & ~TCSR_ENT); /* start timer1 - up counting without interrupt */ out_be32(TIMER_BASE + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT); + + /* register timecounter - for ftrace support */ + init_microblaze_timecounter(); return 0; } diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S index e704188d7855ec6115ddef659505ffba6b6d5578..5ef619aad6341b8ecd6ca021c03dd4b74d418653 100644 --- a/arch/microblaze/kernel/vmlinux.lds.S +++ b/arch/microblaze/kernel/vmlinux.lds.S @@ -26,11 +26,12 @@ SECTIONS { _stext = . ; *(.text .text.*) *(.fixup) - EXIT_TEXT - EXIT_CALL + EXIT_TEXT + EXIT_CALL SCHED_TEXT LOCK_TEXT KPROBES_TEXT + IRQENTRY_TEXT . = ALIGN (4) ; _etext = . ; } @@ -86,6 +87,7 @@ SECTIONS { _KERNEL_SDA_BASE_ = _ssro + (_ssro_size / 2) ; } + . = ALIGN(PAGE_SIZE); __init_begin = .; INIT_TEXT_SECTION(PAGE_SIZE) diff --git a/arch/microblaze/lib/uaccess.c b/arch/microblaze/lib/uaccess.c index 8eb9df5a26c9f53ad53a298330039e1e88898295..a853fe089c44a402c4e53e41b65792ebca5c2f09 100644 --- a/arch/microblaze/lib/uaccess.c +++ b/arch/microblaze/lib/uaccess.c @@ -39,3 +39,10 @@ long strncpy_from_user(char *dst, const char __user *src, long count) __do_strncpy_from_user(dst, src, count, res); return res; } + +unsigned long __copy_tofrom_user(void __user *to, + const void __user *from, unsigned long size) +{ + memcpy(to, from, size); + return 0; +} diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index a44892e7cd5b7e2839976585e69bc8c274c21509..a57cedf36715f7511395b3066878731b107edb1e 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c @@ -41,6 +41,7 @@ char *klimit = _end; * have available. */ unsigned long memory_start; +EXPORT_SYMBOL(memory_start); unsigned long memory_end; /* due to mm/nommu.c */ unsigned long memory_size; diff --git a/arch/microblaze/mm/pgtable.c b/arch/microblaze/mm/pgtable.c index 46c4ca5d15c55f4d573ad9248c2eec1a9ab65478..2820081b21ab8bc4a9b87c5147f3516cfb674c4a 100644 --- a/arch/microblaze/mm/pgtable.c +++ b/arch/microblaze/mm/pgtable.c @@ -144,7 +144,6 @@ int map_page(unsigned long va, phys_addr_t pa, int flags) pmd_t *pd; pte_t *pg; int err = -ENOMEM; - /* spin_lock(&init_mm.page_table_lock); */ /* Use upper 10 bits of VA to index the first level map */ pd = pmd_offset(pgd_offset_k(va), va); /* Use middle 10 bits of VA to index the second-level map */ @@ -158,9 +157,7 @@ int map_page(unsigned long va, phys_addr_t pa, int flags) if (mem_init_done) flush_HPTE(0, va, pmd_val(*pd)); /* flush_HPTE(0, va, pg); */ - } - /* spin_unlock(&init_mm.page_table_lock); */ return err; } @@ -182,12 +179,6 @@ void __init adjust_total_lowmem(void) #endif } -static void show_tmem(unsigned long tmem) -{ - volatile unsigned long a; - a = a + tmem; -} - /* * Map in all of physical memory starting at CONFIG_KERNEL_START. */ @@ -197,7 +188,6 @@ void __init mapin_ram(void) v = CONFIG_KERNEL_START; p = memory_start; - show_tmem(memory_size); for (s = 0; s < memory_size; s += PAGE_SIZE) { f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED | _PAGE_HWEXEC; diff --git a/arch/microblaze/oprofile/Makefile b/arch/microblaze/oprofile/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..0d0348c8af976ceb8c860c9f06ad5b45ee2ba732 --- /dev/null +++ b/arch/microblaze/oprofile/Makefile @@ -0,0 +1,13 @@ +# +# arch/microblaze/oprofile/Makefile +# + +obj-$(CONFIG_OPROFILE) += oprofile.o + +DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ + oprof.o cpu_buffer.o buffer_sync.o \ + event_buffer.o oprofile_files.o \ + oprofilefs.o oprofile_stats.o \ + timer_int.o ) + +oprofile-y := $(DRIVER_OBJS) microblaze_oprofile.o diff --git a/arch/microblaze/oprofile/microblaze_oprofile.c b/arch/microblaze/oprofile/microblaze_oprofile.c new file mode 100644 index 0000000000000000000000000000000000000000..def17e59888efd6b0923e8228dfcfc0ea28ce9d5 --- /dev/null +++ b/arch/microblaze/oprofile/microblaze_oprofile.c @@ -0,0 +1,22 @@ +/* + * Microblaze oprofile code + * + * Copyright (C) 2009 Michal Simek + * Copyright (C) 2009 PetaLogix + * + * 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 + +int __init oprofile_arch_init(struct oprofile_operations *ops) +{ + return -1; +} + +void oprofile_arch_exit(void) +{ +} diff --git a/arch/microblaze/platform/Kconfig.platform b/arch/microblaze/platform/Kconfig.platform index 8e9b4752d3ff1def57e29b91a587f404e077928f..669c7eec293eb921689ba618a11d9e701ee626a3 100644 --- a/arch/microblaze/platform/Kconfig.platform +++ b/arch/microblaze/platform/Kconfig.platform @@ -53,31 +53,12 @@ config OPT_LIB_FUNCTION config OPT_LIB_ASM bool "Optimalized lib function ASM" - depends on OPT_LIB_FUNCTION + depends on OPT_LIB_FUNCTION && (XILINX_MICROBLAZE0_USE_BARREL = 1) default n help Allows turn on optimalized library function (memcpy and memmove). Function are written in asm code. -# This is still a bit broken - disabling for now JW 20070504 -config ALLOW_EDIT_AUTO - bool "Permit Display/edit of Kconfig.auto platform settings" - default n - help - Allows the editing of auto-generated platform settings from - the Kconfig.auto file. Obviously this does not change the - underlying hardware, so be very careful if you go editing - these settings. - - Also, if you enable this, and edit various Kconfig.auto - settings, YOUR CHANGES WILL BE LOST if you then disable it - again. You have been warned! - - If unsure, say no. - -comment "Automatic platform settings from Kconfig.auto" - depends on ALLOW_EDIT_AUTO - if PLATFORM_GENERIC=y source "arch/microblaze/platform/generic/Kconfig.auto" endif diff --git a/arch/microblaze/platform/generic/Kconfig.auto b/arch/microblaze/platform/generic/Kconfig.auto index fbca22d9c8b9bac47767f1b2f0e5fd1c48d1f8f1..5d86fc19029d412ed068ecff73c4010dde9841d0 100644 --- a/arch/microblaze/platform/generic/Kconfig.auto +++ b/arch/microblaze/platform/generic/Kconfig.auto @@ -21,7 +21,6 @@ # Definitions for MICROBLAZE0 comment "Definitions for MICROBLAZE0" - depends on ALLOW_EDIT_AUTO config KERNEL_BASE_ADDR hex "Physical address where Linux Kernel is" @@ -30,33 +29,33 @@ config KERNEL_BASE_ADDR BASE Address for kernel config XILINX_MICROBLAZE0_FAMILY - string "Targetted FPGA family" if ALLOW_EDIT_AUTO + string "Targetted FPGA family" default "virtex5" config XILINX_MICROBLAZE0_USE_MSR_INSTR - int "USE_MSR_INSTR range (0:1)" if ALLOW_EDIT_AUTO - default 1 + int "USE_MSR_INSTR range (0:1)" + default 0 config XILINX_MICROBLAZE0_USE_PCMP_INSTR - int "USE_PCMP_INSTR range (0:1)" if ALLOW_EDIT_AUTO - default 1 + int "USE_PCMP_INSTR range (0:1)" + default 0 config XILINX_MICROBLAZE0_USE_BARREL - int "USE_BARREL range (0:1)" if ALLOW_EDIT_AUTO - default 1 + int "USE_BARREL range (0:1)" + default 0 config XILINX_MICROBLAZE0_USE_DIV - int "USE_DIV range (0:1)" if ALLOW_EDIT_AUTO - default 1 + int "USE_DIV range (0:1)" + default 0 config XILINX_MICROBLAZE0_USE_HW_MUL - int "USE_HW_MUL values (0=NONE, 1=MUL32, 2=MUL64)" if ALLOW_EDIT_AUTO - default 2 + int "USE_HW_MUL values (0=NONE, 1=MUL32, 2=MUL64)" + default 0 config XILINX_MICROBLAZE0_USE_FPU - int "USE_FPU values (0=NONE, 1=BASIC, 2=EXTENDED)" if ALLOW_EDIT_AUTO - default 2 + int "USE_FPU values (0=NONE, 1=BASIC, 2=EXTENDED)" + default 0 config XILINX_MICROBLAZE0_HW_VER - string "Core version number" if ALLOW_EDIT_AUTO + string "Core version number" default 7.10.d diff --git a/arch/microblaze/platform/generic/system.dts b/arch/microblaze/platform/generic/system.dts index 29993f62b30a2c47abfb7c24a3ab5677c9142dc5..2d5c41767cd06ca146e0192df79e9fd9f06ef441 100644 --- a/arch/microblaze/platform/generic/system.dts +++ b/arch/microblaze/platform/generic/system.dts @@ -32,11 +32,16 @@ #address-cells = <1>; #size-cells = <1>; compatible = "xlnx,microblaze"; + hard-reset-gpios = <&LEDs_8Bit 2 1>; model = "testing"; DDR2_SDRAM: memory@90000000 { device_type = "memory"; reg = < 0x90000000 0x10000000 >; } ; + aliases { + ethernet0 = &Hard_Ethernet_MAC; + serial0 = &RS232_Uart_1; + } ; chosen { bootargs = "console=ttyUL0,115200 highres=on"; linux,stdout-path = "/plb@0/serial@84000000"; @@ -127,7 +132,7 @@ mb_plb: plb@0 { #address-cells = <1>; #size-cells = <1>; - compatible = "xlnx,plb-v46-1.03.a", "simple-bus"; + compatible = "xlnx,plb-v46-1.03.a", "xlnx,plb-v46-1.00.a", "simple-bus"; ranges ; FLASH: flash@a0000000 { bank-width = <2>; @@ -214,12 +219,12 @@ #size-cells = <1>; compatible = "xlnx,compound"; ethernet@81c00000 { - compatible = "xlnx,xps-ll-temac-1.01.b"; + compatible = "xlnx,xps-ll-temac-1.01.b", "xlnx,xps-ll-temac-1.00.a"; device_type = "network"; interrupt-parent = <&xps_intc_0>; interrupts = < 5 2 >; llink-connected = <&PIM3>; - local-mac-address = [ 02 00 00 00 00 00 ]; + local-mac-address = [ 00 0a 35 00 00 00 ]; reg = < 0x81c00000 0x40 >; xlnx,bus2core-clk-ratio = <0x1>; xlnx,phy-type = <0x1>; @@ -261,6 +266,33 @@ xlnx,is-dual = <0x0>; xlnx,tri-default = <0xffffffff>; xlnx,tri-default-2 = <0xffffffff>; + #gpio-cells = <2>; + gpio-controller; + } ; + + gpio-leds { + compatible = "gpio-leds"; + + heartbeat { + label = "Heartbeat"; + gpios = <&LEDs_8Bit 4 1>; + linux,default-trigger = "heartbeat"; + }; + + yellow { + label = "Yellow"; + gpios = <&LEDs_8Bit 5 1>; + }; + + red { + label = "Red"; + gpios = <&LEDs_8Bit 6 1>; + }; + + green { + label = "Green"; + gpios = <&LEDs_8Bit 7 1>; + }; } ; RS232_Uart_1: serial@84000000 { clock-frequency = <125000000>; diff --git a/arch/microblaze/platform/platform.c b/arch/microblaze/platform/platform.c index 56e0234fa34b444a235bd4b812861f3c9c3e96ad..5b89b58c5aedbc9d9f12aa5d6b2e541134101f6f 100644 --- a/arch/microblaze/platform/platform.c +++ b/arch/microblaze/platform/platform.c @@ -13,6 +13,7 @@ #include #include #include +#include static struct of_device_id xilinx_of_bus_ids[] __initdata = { { .compatible = "simple-bus", }, @@ -26,6 +27,7 @@ static struct of_device_id xilinx_of_bus_ids[] __initdata = { static int __init microblaze_device_probe(void) { of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL); + of_platform_reset_gpio_probe(); return 0; } device_initcall(microblaze_device_probe); diff --git a/arch/mips/include/asm/fcntl.h b/arch/mips/include/asm/fcntl.h index 2a52333a062d1879d6b06cc2ab1bb44fc67d95b4..7c6681aa2ab877a02f3dff8577c96bd2d9b11509 100644 --- a/arch/mips/include/asm/fcntl.h +++ b/arch/mips/include/asm/fcntl.h @@ -10,7 +10,7 @@ #define O_APPEND 0x0008 -#define O_SYNC 0x0010 +#define O_DSYNC 0x0010 /* used to be O_SYNC, see below */ #define O_NONBLOCK 0x0080 #define O_CREAT 0x0100 /* not fcntl */ #define O_TRUNC 0x0200 /* not fcntl */ @@ -18,6 +18,21 @@ #define O_NOCTTY 0x0800 /* not fcntl */ #define FASYNC 0x1000 /* fcntl, for BSD compatibility */ #define O_LARGEFILE 0x2000 /* allow large file opens */ +/* + * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using + * the O_SYNC flag. We continue to use the existing numerical value + * for O_DSYNC semantics now, but using the correct symbolic name for it. + * This new value is used to request true Posix O_SYNC semantics. It is + * defined in this strange way to make sure applications compiled against + * new headers get at least O_DSYNC semantics on older kernels. + * + * This has the nice side-effect that we can simply test for O_DSYNC + * wherever we do not care if O_DSYNC or O_SYNC is used. + * + * Note: __O_SYNC must never be used directly. + */ +#define __O_SYNC 0x4000 +#define O_SYNC (__O_SYNC|O_DSYNC) #define O_DIRECT 0x8000 /* direct disk access hint */ #define F_GETLK 14 diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c index ad4e017ed2f322e40d98f8c10304edb1be0e7970..80e2ba694babcd0d70bd8266a6be941996e2a8a8 100644 --- a/arch/mips/kernel/kspd.c +++ b/arch/mips/kernel/kspd.c @@ -82,6 +82,7 @@ static int sp_stopping; #define MTSP_O_SHLOCK 0x0010 #define MTSP_O_EXLOCK 0x0020 #define MTSP_O_ASYNC 0x0040 +/* XXX: check which of these is actually O_SYNC vs O_DSYNC */ #define MTSP_O_FSYNC O_SYNC #define MTSP_O_NOFOLLOW 0x0100 #define MTSP_O_SYNC 0x0080 diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 1a2793efdc4e2c45160f3ff71eca72082d180df9..f042563c924f66f9da2ef3a88f4e75032f55871f 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -67,28 +67,13 @@ SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, pgoff) { - struct file * file = NULL; unsigned long error; error = -EINVAL; if (pgoff & (~PAGE_MASK >> 12)) goto out; - pgoff >>= PAGE_SHIFT-12; - - if (!(flags & MAP_ANONYMOUS)) { - error = -EBADF; - file = fget(fd); - if (!file) - goto out; - } - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); - + error = sys_mmap_pgoff(addr, len, prot, flags, fd, + pgoff >> (PAGE_SHIFT-12)); out: return error; } diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index fe0d7980560368056e187dcc9f852b3218a08951..3f7f466190b481e62b7df738b10ef96477f1c059 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -93,7 +93,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, * We do not accept a shared mapping if it would violate * cache aliasing constraints. */ - if ((flags & MAP_SHARED) && (addr & shm_align_mask)) + if ((flags & MAP_SHARED) && + ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask)) return -EINVAL; return addr; } @@ -129,31 +130,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, } } -/* common code for old and new mmaps */ -static inline unsigned long -do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, - unsigned long flags, unsigned long fd, unsigned long pgoff) -{ - unsigned long error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, off_t, offset) @@ -164,7 +140,7 @@ SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len, if (offset & ~PAGE_MASK) goto out; - result = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + result = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); out: return result; @@ -177,7 +153,7 @@ SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len, if (pgoff & (~PAGE_MASK >> 12)) return -EINVAL; - return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12)); + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12)); } save_static_function(sys_fork); diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c index 7c92f79b64806caba9ae2168e10a9509f4580b36..e94ef158f9800630dd23a158dec374a6b861cbc0 100644 --- a/arch/mips/loongson/common/mem.c +++ b/arch/mips/loongson/common/mem.c @@ -26,7 +26,7 @@ void __init prom_init_memory(void) /* override of arch/mips/mm/cache.c: __uncached_access */ int __uncached_access(struct file *file, unsigned long addr) { - if (file->f_flags & O_SYNC) + if (file->f_flags & O_DSYNC) return 1; return addr >= __pa(high_memory) || diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 694d51f523d1fd8d5cbf057534e6031bf36f5327..102b2dfa542a7c2d6da79fff1f9382e768c3bf54 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -194,7 +194,7 @@ void __devinit cpu_cache_init(void) int __weak __uncached_access(struct file *file, unsigned long addr) { - if (file->f_flags & O_SYNC) + if (file->f_flags & O_DSYNC) return 1; return addr >= __pa(high_memory); diff --git a/arch/mn10300/include/asm/mman.h b/arch/mn10300/include/asm/mman.h index 8eebf89f5ab17884a98543f3b37a3b710355083b..db5c53da73ced573d66176a58d8e7b73580b5ae2 100644 --- a/arch/mn10300/include/asm/mman.h +++ b/arch/mn10300/include/asm/mman.h @@ -1 +1,6 @@ #include + +#define MIN_MAP_ADDR PAGE_SIZE /* minimum fixed mmap address */ + +#define arch_mmap_check(addr, len, flags) \ + (((flags) & MAP_FIXED && (addr) < MIN_MAP_ADDR) ? -EINVAL : 0) diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S index a94e7ea3faa69e634f50b4e7d2db6db0916b7a2f..c9ee6c009d795aa1fde9c44b2bc56b5a5f1beba5 100644 --- a/arch/mn10300/kernel/entry.S +++ b/arch/mn10300/kernel/entry.S @@ -578,7 +578,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* reserved for streams2 */ .long sys_vfork /* 190 */ .long sys_getrlimit - .long sys_mmap2 + .long sys_mmap_pgoff .long sys_truncate64 .long sys_ftruncate64 .long sys_stat64 /* 195 */ diff --git a/arch/mn10300/kernel/kprobes.c b/arch/mn10300/kernel/kprobes.c index dacafab00eb25c4645ffd787b0fc77730cf25859..67e6389d625a43a7cf62d4d1f5358233b5fef3d7 100644 --- a/arch/mn10300/kernel/kprobes.c +++ b/arch/mn10300/kernel/kprobes.c @@ -31,13 +31,13 @@ const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist); #define KPROBE_HIT_ACTIVE 0x00000001 #define KPROBE_HIT_SS 0x00000002 -static struct kprobe *current_kprobe; -static unsigned long current_kprobe_orig_pc; -static unsigned long current_kprobe_next_pc; -static int current_kprobe_ss_flags; +static struct kprobe *cur_kprobe; +static unsigned long cur_kprobe_orig_pc; +static unsigned long cur_kprobe_next_pc; +static int cur_kprobe_ss_flags; static unsigned long kprobe_status; -static kprobe_opcode_t current_kprobe_ss_buf[MAX_INSN_SIZE + 2]; -static unsigned long current_kprobe_bp_addr; +static kprobe_opcode_t cur_kprobe_ss_buf[MAX_INSN_SIZE + 2]; +static unsigned long cur_kprobe_bp_addr; DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; @@ -399,26 +399,25 @@ void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) { unsigned long nextpc; - current_kprobe_orig_pc = regs->pc; - memcpy(current_kprobe_ss_buf, &p->ainsn.insn[0], MAX_INSN_SIZE); - regs->pc = (unsigned long) current_kprobe_ss_buf; + cur_kprobe_orig_pc = regs->pc; + memcpy(cur_kprobe_ss_buf, &p->ainsn.insn[0], MAX_INSN_SIZE); + regs->pc = (unsigned long) cur_kprobe_ss_buf; - nextpc = find_nextpc(regs, ¤t_kprobe_ss_flags); - if (current_kprobe_ss_flags & SINGLESTEP_PCREL) - current_kprobe_next_pc = - current_kprobe_orig_pc + (nextpc - regs->pc); + nextpc = find_nextpc(regs, &cur_kprobe_ss_flags); + if (cur_kprobe_ss_flags & SINGLESTEP_PCREL) + cur_kprobe_next_pc = cur_kprobe_orig_pc + (nextpc - regs->pc); else - current_kprobe_next_pc = nextpc; + cur_kprobe_next_pc = nextpc; /* branching instructions need special handling */ - if (current_kprobe_ss_flags & SINGLESTEP_BRANCH) + if (cur_kprobe_ss_flags & SINGLESTEP_BRANCH) nextpc = singlestep_branch_setup(regs); - current_kprobe_bp_addr = nextpc; + cur_kprobe_bp_addr = nextpc; *(u8 *) nextpc = BREAKPOINT_INSTRUCTION; - mn10300_dcache_flush_range2((unsigned) current_kprobe_ss_buf, - sizeof(current_kprobe_ss_buf)); + mn10300_dcache_flush_range2((unsigned) cur_kprobe_ss_buf, + sizeof(cur_kprobe_ss_buf)); mn10300_icache_inv(); } @@ -440,7 +439,7 @@ static inline int __kprobes kprobe_handler(struct pt_regs *regs) disarm_kprobe(p, regs); ret = 1; } else { - p = current_kprobe; + p = cur_kprobe; if (p->break_handler && p->break_handler(p, regs)) goto ss_probe; } @@ -464,7 +463,7 @@ static inline int __kprobes kprobe_handler(struct pt_regs *regs) } kprobe_status = KPROBE_HIT_ACTIVE; - current_kprobe = p; + cur_kprobe = p; if (p->pre_handler(p, regs)) { /* handler has already set things up, so skip ss setup */ return 1; @@ -491,8 +490,8 @@ no_kprobe: static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) { /* we may need to fixup regs/stack after singlestepping a call insn */ - if (current_kprobe_ss_flags & SINGLESTEP_BRANCH) { - regs->pc = current_kprobe_orig_pc; + if (cur_kprobe_ss_flags & SINGLESTEP_BRANCH) { + regs->pc = cur_kprobe_orig_pc; switch (p->ainsn.insn[0]) { case 0xcd: /* CALL (d16,PC) */ *(unsigned *) regs->sp = regs->mdr = regs->pc + 5; @@ -523,8 +522,8 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) } } - regs->pc = current_kprobe_next_pc; - current_kprobe_bp_addr = 0; + regs->pc = cur_kprobe_next_pc; + cur_kprobe_bp_addr = 0; } static inline int __kprobes post_kprobe_handler(struct pt_regs *regs) @@ -532,10 +531,10 @@ static inline int __kprobes post_kprobe_handler(struct pt_regs *regs) if (!kprobe_running()) return 0; - if (current_kprobe->post_handler) - current_kprobe->post_handler(current_kprobe, regs, 0); + if (cur_kprobe->post_handler) + cur_kprobe->post_handler(cur_kprobe, regs, 0); - resume_execution(current_kprobe, regs); + resume_execution(cur_kprobe, regs); reset_current_kprobe(); preempt_enable_no_resched(); return 1; @@ -545,12 +544,12 @@ static inline int __kprobes post_kprobe_handler(struct pt_regs *regs) static inline int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) { - if (current_kprobe->fault_handler && - current_kprobe->fault_handler(current_kprobe, regs, trapnr)) + if (cur_kprobe->fault_handler && + cur_kprobe->fault_handler(cur_kprobe, regs, trapnr)) return 1; if (kprobe_status & KPROBE_HIT_SS) { - resume_execution(current_kprobe, regs); + resume_execution(cur_kprobe, regs); reset_current_kprobe(); preempt_enable_no_resched(); } @@ -567,7 +566,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, switch (val) { case DIE_BREAKPOINT: - if (current_kprobe_bp_addr != args->regs->pc) { + if (cur_kprobe_bp_addr != args->regs->pc) { if (kprobe_handler(args->regs)) return NOTIFY_STOP; } else { diff --git a/arch/mn10300/kernel/sys_mn10300.c b/arch/mn10300/kernel/sys_mn10300.c index 8ca5af00334cd1f30567f7c74218040aed7750e6..17cc6ce04e840f136cd18e2a569e957697c10cd2 100644 --- a/arch/mn10300/kernel/sys_mn10300.c +++ b/arch/mn10300/kernel/sys_mn10300.c @@ -23,47 +23,13 @@ #include -#define MIN_MAP_ADDR PAGE_SIZE /* minimum fixed mmap address */ - -/* - * memory mapping syscall - */ -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - struct file *file = NULL; - long error = -EINVAL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - if (flags & MAP_FIXED && addr < MIN_MAP_ADDR) - goto out; - - error = -EBADF; - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - asmlinkage long old_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long offset) { if (offset & ~PAGE_MASK) return -EINVAL; - return sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); } struct sel_arg_struct { diff --git a/arch/parisc/include/asm/fcntl.h b/arch/parisc/include/asm/fcntl.h index 1e1c824764ee1f0202c9012090e06f532eb75e42..f357fc693c89e2e8a51697310122b3fe7358a216 100644 --- a/arch/parisc/include/asm/fcntl.h +++ b/arch/parisc/include/asm/fcntl.h @@ -1,14 +1,13 @@ #ifndef _PARISC_FCNTL_H #define _PARISC_FCNTL_H -/* open/fcntl - O_SYNC is only implemented on blocks devices and on files - located on an ext2 file system */ #define O_APPEND 000000010 #define O_BLKSEEK 000000100 /* HPUX only */ #define O_CREAT 000000400 /* not fcntl */ #define O_EXCL 000002000 /* not fcntl */ #define O_LARGEFILE 000004000 -#define O_SYNC 000100000 +#define __O_SYNC 000100000 +#define O_SYNC (__O_SYNC|O_DSYNC) #define O_NONBLOCK 000200004 /* HPUX has separate NDELAY & NONBLOCK */ #define O_NOCTTY 000400000 /* not fcntl */ #define O_DSYNC 001000000 /* HPUX only */ diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 71b31957c8f13805c5a8da1c93c6061bf562f2a7..9147391afb03ef0590ae7a9167919c408dbd82e7 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -110,37 +110,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, return addr; } -static unsigned long do_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, unsigned long fd, - unsigned long pgoff) -{ - struct file * file = NULL; - unsigned long error = -EBADF; - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file != NULL) - fput(file); -out: - return error; -} - asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE we have. */ - return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12)); + return sys_mmap_pgoff(addr, len, prot, flags, fd, + pgoff >> (PAGE_SHIFT - 12)); } asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, @@ -148,7 +125,8 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, unsigned long offset) { if (!(offset & ~PAGE_MASK)) { - return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + return sys_mmap_pgoff(addr, len, prot, flags, fd, + offset >> PAGE_SHIFT); } else { return -EINVAL; } diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 2ba14e77296c8082e0670fbe6113ae9667286e39..0df57466e7834ab9dab978c5accccbdbfb4b0b04 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -56,6 +56,16 @@ config IRQ_PER_CPU bool default y +config NR_IRQS + int "Number of virtual interrupt numbers" + range 32 512 + default "512" + help + This defines the number of virtual interrupt numbers the kernel + can manage. Virtual interrupt numbers are what you see in + /proc/interrupts. If you configure your system to have too few, + drivers will fail to load or worse - handle with care. + config STACKTRACE_SUPPORT bool default y @@ -199,24 +209,14 @@ config DEFAULT_UIMAGE config REDBOOT bool -config HIBERNATE_32 - bool - depends on (PPC_PMAC && !SMP) || BROKEN - default y - -config HIBERNATE_64 - bool - depends on BROKEN || (PPC_PMAC64 && EXPERIMENTAL) - default y - config ARCH_HIBERNATION_POSSIBLE bool - depends on (PPC64 && HIBERNATE_64) || (PPC32 && HIBERNATE_32) default y config ARCH_SUSPEND_POSSIBLE def_bool y - depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx + depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \ + PPC_85xx || PPC_86xx config PPC_DCR_NATIVE bool @@ -320,6 +320,10 @@ config HOTPLUG_CPU Say N if you are unsure. +config ARCH_CPU_PROBE_RELEASE + def_bool y + depends on HOTPLUG_CPU + config ARCH_ENABLE_MEMORY_HOTPLUG def_bool y @@ -378,6 +382,19 @@ config IRQ_ALL_CPUS CPU. Generally saying Y is safe, although some problems have been reported with SMP Power Macintoshes with this option enabled. +config SPARSE_IRQ + bool "Support sparse irq numbering" + default y + help + This enables support for sparse irqs. This is useful for distro + kernels that want to define a high CONFIG_NR_CPUS value but still + want to have low kernel memory footprint on smaller machines. + + ( Sparse IRQs can also be beneficial on NUMA boxes, as they spread + out the irq_desc[] array in a more NUMA-friendly way. ) + + If you don't know what to do here, say Y. + config NUMA bool "NUMA support" depends on PPC64 @@ -652,6 +669,14 @@ config FSL_PCI select PPC_INDIRECT_PCI select PCI_QUIRKS +config FSL_PMC + bool + default y + depends on SUSPEND && (PPC_85xx || PPC_86xx) + help + Freescale MPC85xx/MPC86xx power management controller support + (suspend/resume). For MPC83xx see platforms/83xx/suspend.c + config 4xx_SOC bool diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts index c920170b7dfefd9d70bb29e1a2d71e6ccb860b88..cd56bb5b347b51b69d957419acec03d38e0857cc 100644 --- a/arch/powerpc/boot/dts/canyonlands.dts +++ b/arch/powerpc/boot/dts/canyonlands.dts @@ -352,6 +352,7 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII0>; @@ -381,6 +382,7 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII0>; diff --git a/arch/powerpc/boot/dts/eiger.dts b/arch/powerpc/boot/dts/eiger.dts index c4a934f2e8864929721301252e92e44f7a842319..48bcf7187924a3565e4777ac968ad98f6528c44d 100644 --- a/arch/powerpc/boot/dts/eiger.dts +++ b/arch/powerpc/boot/dts/eiger.dts @@ -316,6 +316,7 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII0>; @@ -345,6 +346,7 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII0>; @@ -375,6 +377,8 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; + tx-fifo-size-gige = <16384>; /* emac2&3 only */ phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII1>; @@ -403,6 +407,8 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; + tx-fifo-size-gige = <16384>; /* emac2&3 only */ phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII1>; diff --git a/arch/powerpc/boot/dts/gef_ppc9a.dts b/arch/powerpc/boot/dts/gef_ppc9a.dts index 910944edd886fdfa42994adedfbe4757668bd084..c86114e93f1e62400cf0fc9073c9645960471102 100644 --- a/arch/powerpc/boot/dts/gef_ppc9a.dts +++ b/arch/powerpc/boot/dts/gef_ppc9a.dts @@ -118,6 +118,12 @@ }; }; + nvram@3,0 { + device_type = "nvram"; + compatible = "simtek,stk14ca8"; + reg = <0x3 0x0 0x20000>; + }; + fpga@4,0 { compatible = "gef,ppc9a-fpga-regs"; reg = <0x4 0x0 0x40>; diff --git a/arch/powerpc/boot/dts/gef_sbc310.dts b/arch/powerpc/boot/dts/gef_sbc310.dts index 2107d3c7cfe1d61bb6632c9445cee03a301fcbb5..820c2b355ab1fddacf2cf8d059f4a0d729c2acb8 100644 --- a/arch/powerpc/boot/dts/gef_sbc310.dts +++ b/arch/powerpc/boot/dts/gef_sbc310.dts @@ -115,6 +115,12 @@ }; }; + nvram@3,0 { + device_type = "nvram"; + compatible = "simtek,stk14ca8"; + reg = <0x3 0x0 0x20000>; + }; + fpga@4,0 { compatible = "gef,fpga-regs"; reg = <0x4 0x0 0x40>; diff --git a/arch/powerpc/boot/dts/gef_sbc610.dts b/arch/powerpc/boot/dts/gef_sbc610.dts index 35a63183eeccbac072b9b4c58801340bd3f7f755..30911adefc8ebe361b467bfc2b5ecc0ce74d6426 100644 --- a/arch/powerpc/boot/dts/gef_sbc610.dts +++ b/arch/powerpc/boot/dts/gef_sbc610.dts @@ -84,6 +84,12 @@ 6 0 0xfd000000 0x00800000 // IO FPGA (8-bit) 7 0 0xfd800000 0x00800000>; // IO FPGA (32-bit) + nvram@3,0 { + device_type = "nvram"; + compatible = "simtek,stk14ca8"; + reg = <0x3 0x0 0x20000>; + }; + fpga@4,0 { compatible = "gef,fpga-regs"; reg = <0x4 0x0 0x40>; diff --git a/arch/powerpc/boot/dts/glacier.dts b/arch/powerpc/boot/dts/glacier.dts index f3787a27f6342a2d2a9c17738df5bac9e3a7bd37..f6f618939293ff95a0f20d1f19d3e115ee75529c 100644 --- a/arch/powerpc/boot/dts/glacier.dts +++ b/arch/powerpc/boot/dts/glacier.dts @@ -292,6 +292,7 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII0>; @@ -321,6 +322,7 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII0>; @@ -351,6 +353,8 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; + tx-fifo-size-gige = <16384>; /* emac2&3 only */ phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII1>; @@ -379,6 +383,8 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; + tx-fifo-size-gige = <16384>; /* emac2&3 only */ phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII1>; diff --git a/arch/powerpc/boot/dts/haleakala.dts b/arch/powerpc/boot/dts/haleakala.dts index 5b2a4947bf82c092a4797cf5a7d0e06a0a8b6eed..2b256694eca6b1c48d63dd31f3ca532eb8b741c8 100644 --- a/arch/powerpc/boot/dts/haleakala.dts +++ b/arch/powerpc/boot/dts/haleakala.dts @@ -226,6 +226,8 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; + tx-fifo-size-gige = <16384>; phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII0>; diff --git a/arch/powerpc/boot/dts/katmai.dts b/arch/powerpc/boot/dts/katmai.dts index 077819bc3cbd0744c822f6037a5de76ff2a7e142..51eb6ed5da2d1ff9b51283d410dc464eda87fc5e 100644 --- a/arch/powerpc/boot/dts/katmai.dts +++ b/arch/powerpc/boot/dts/katmai.dts @@ -16,7 +16,7 @@ / { #address-cells = <2>; - #size-cells = <1>; + #size-cells = <2>; model = "amcc,katmai"; compatible = "amcc,katmai"; dcr-parent = <&{/cpus/cpu@0}>; @@ -49,7 +49,7 @@ memory { device_type = "memory"; - reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by zImage */ + reg = <0x0 0x00000000 0x0 0x00000000>; /* Filled in by U-Boot */ }; UIC0: interrupt-controller0 { @@ -112,7 +112,15 @@ compatible = "ibm,plb-440spe", "ibm,plb-440gp", "ibm,plb4"; #address-cells = <2>; #size-cells = <1>; - ranges; + /* addr-child addr-parent size */ + ranges = <0x4 0xe0000000 0x4 0xe0000000 0x20000000 + 0xc 0x00000000 0xc 0x00000000 0x20000000 + 0xd 0x00000000 0xd 0x00000000 0x80000000 + 0xd 0x80000000 0xd 0x80000000 0x80000000 + 0xe 0x00000000 0xe 0x00000000 0x80000000 + 0xe 0x80000000 0xe 0x80000000 0x80000000 + 0xf 0x00000000 0xf 0x00000000 0x80000000 + 0xf 0x80000000 0xf 0x80000000 0x80000000>; clock-frequency = <0>; /* Filled in by zImage */ SDRAM0: sdram { @@ -245,8 +253,8 @@ ranges = <0x02000000 0x00000000 0x80000000 0x0000000d 0x80000000 0x00000000 0x80000000 0x01000000 0x00000000 0x00000000 0x0000000c 0x08000000 0x00000000 0x00010000>; - /* Inbound 2GB range starting at 0 */ - dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; + /* Inbound 4GB range starting at 0 */ + dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>; /* This drives busses 0 to 0xf */ bus-range = <0x0 0xf>; @@ -289,10 +297,10 @@ ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x00000000 0x00000000 0x80000000 0x01000000 0x00000000 0x00000000 0x0000000f 0x80000000 0x00000000 0x00010000>; - /* Inbound 2GB range starting at 0 */ - dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; + /* Inbound 4GB range starting at 0 */ + dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>; - /* This drives busses 10 to 0x1f */ + /* This drives busses 0x10 to 0x1f */ bus-range = <0x10 0x1f>; /* Legacy interrupts (note the weird polarity, the bridge seems @@ -330,10 +338,10 @@ ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x80000000 0x00000000 0x80000000 0x01000000 0x00000000 0x00000000 0x0000000f 0x80010000 0x00000000 0x00010000>; - /* Inbound 2GB range starting at 0 */ - dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; + /* Inbound 4GB range starting at 0 */ + dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>; - /* This drives busses 10 to 0x1f */ + /* This drives busses 0x20 to 0x2f */ bus-range = <0x20 0x2f>; /* Legacy interrupts (note the weird polarity, the bridge seems @@ -371,10 +379,10 @@ ranges = <0x02000000 0x00000000 0x80000000 0x0000000f 0x00000000 0x00000000 0x80000000 0x01000000 0x00000000 0x00000000 0x0000000f 0x80020000 0x00000000 0x00010000>; - /* Inbound 2GB range starting at 0 */ - dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; + /* Inbound 4GB range starting at 0 */ + dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>; - /* This drives busses 10 to 0x1f */ + /* This drives busses 0x30 to 0x3f */ bus-range = <0x30 0x3f>; /* Legacy interrupts (note the weird polarity, the bridge seems diff --git a/arch/powerpc/boot/dts/kilauea.dts b/arch/powerpc/boot/dts/kilauea.dts index c46561456ede3e25758b3ee57077036940d7ebe2..083e68eeaca4c5d4e3a7fdf3f11268ec62a6cbc1 100644 --- a/arch/powerpc/boot/dts/kilauea.dts +++ b/arch/powerpc/boot/dts/kilauea.dts @@ -272,6 +272,8 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; + tx-fifo-size-gige = <16384>; phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII0>; @@ -300,6 +302,8 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; + tx-fifo-size-gige = <16384>; phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII0>; diff --git a/arch/powerpc/boot/dts/kmeter1.dts b/arch/powerpc/boot/dts/kmeter1.dts index 167044f7de1d6e2102a02ee526f4ebeadeab607e..65b8b4f27efe1d6bdbbc3c44ba11806b1ce9f477 100644 --- a/arch/powerpc/boot/dts/kmeter1.dts +++ b/arch/powerpc/boot/dts/kmeter1.dts @@ -59,6 +59,13 @@ reg = <0xe0000000 0x00000200>; bus-frequency = <0>; /* Filled in by U-Boot */ + pmc: power@b00 { + compatible = "fsl,mpc8360-pmc", "fsl,mpc8349-pmc"; + reg = <0xb00 0x100 0xa00 0x100>; + interrupts = <80 0x8>; + interrupt-parent = <&ipic>; + }; + i2c@3000 { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/makalu.dts b/arch/powerpc/boot/dts/makalu.dts index ffc246e726709460c42244831c71a95cbfe603bb..63d48b632c84c8f3a2c9382eaddf578b0791338e 100644 --- a/arch/powerpc/boot/dts/makalu.dts +++ b/arch/powerpc/boot/dts/makalu.dts @@ -227,6 +227,8 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; + tx-fifo-size-gige = <16384>; phy-mode = "rgmii"; phy-map = <0x0000003f>; /* Start at 6 */ rgmii-device = <&RGMII0>; @@ -255,6 +257,8 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; + tx-fifo-size-gige = <16384>; phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII0>; diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts index 436c9c671dd9c86edabd0ca1054490e806b7c841..05ad8c98e52721e23a12f72a1221bc4004e4d148 100644 --- a/arch/powerpc/boot/dts/mpc832x_mds.dts +++ b/arch/powerpc/boot/dts/mpc832x_mds.dts @@ -79,6 +79,13 @@ reg = <0x200 0x100>; }; + pmc: power@b00 { + compatible = "fsl,mpc8323-pmc", "fsl,mpc8349-pmc"; + reg = <0xb00 0x100 0xa00 0x100>; + interrupts = <80 0x8>; + interrupt-parent = <&ipic>; + }; + i2c@3000 { #address-cells = <1>; #size-cells = <0>; @@ -163,6 +170,7 @@ fsl,channel-fifo-len = <24>; fsl,exec-units-mask = <0x4c>; fsl,descriptor-types-mask = <0x0122003f>; + sleep = <&pmc 0x03000000>; }; ipic: pic@700 { @@ -428,5 +436,6 @@ 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; + sleep = <&pmc 0x00010000>; }; }; diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts index 9a0952f74b812555b3208d877618f3ff00f57891..f4fadb23ad6f66d1e119b7d7000a4bfa8489df0e 100644 --- a/arch/powerpc/boot/dts/mpc832x_rdb.dts +++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts @@ -62,6 +62,13 @@ reg = <0x200 0x100>; }; + pmc: power@b00 { + compatible = "fsl,mpc8323-pmc", "fsl,mpc8349-pmc"; + reg = <0xb00 0x100 0xa00 0x100>; + interrupts = <80 0x8>; + interrupt-parent = <&ipic>; + }; + i2c@3000 { #address-cells = <1>; #size-cells = <0>; @@ -141,6 +148,7 @@ fsl,channel-fifo-len = <24>; fsl,exec-units-mask = <0x4c>; fsl,descriptor-types-mask = <0x0122003f>; + sleep = <&pmc 0x03000000>; }; ipic:pic@700 { @@ -360,5 +368,6 @@ 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; + sleep = <&pmc 0x00010000>; }; }; diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts index 39ff4c829cafd125e0db34484cea04df1a393e99..45cfa1c50a2a629614cd2909ac2f7d6bc18c6bb9 100644 --- a/arch/powerpc/boot/dts/mpc836x_mds.dts +++ b/arch/powerpc/boot/dts/mpc836x_mds.dts @@ -99,6 +99,13 @@ reg = <0x200 0x100>; }; + pmc: power@b00 { + compatible = "fsl,mpc8360-pmc", "fsl,mpc8349-pmc"; + reg = <0xb00 0x100 0xa00 0x100>; + interrupts = <80 0x8>; + interrupt-parent = <&ipic>; + }; + i2c@3000 { #address-cells = <1>; #size-cells = <0>; @@ -194,6 +201,7 @@ fsl,channel-fifo-len = <24>; fsl,exec-units-mask = <0x7e>; fsl,descriptor-types-mask = <0x01010ebf>; + sleep = <&pmc 0x03000000>; }; ipic: pic@700 { @@ -470,5 +478,6 @@ 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; + sleep = <&pmc 0x00010000>; }; }; diff --git a/arch/powerpc/boot/dts/mpc836x_rdk.dts b/arch/powerpc/boot/dts/mpc836x_rdk.dts index 6315d6fcc58aa87aeb0acc2617c9366a441a4f66..bdf4459677b14dcd55245bad4d83c9bea3322f44 100644 --- a/arch/powerpc/boot/dts/mpc836x_rdk.dts +++ b/arch/powerpc/boot/dts/mpc836x_rdk.dts @@ -71,6 +71,13 @@ reg = <0x200 0x100>; }; + pmc: power@b00 { + compatible = "fsl,mpc8360-pmc", "fsl,mpc8349-pmc"; + reg = <0xb00 0x100 0xa00 0x100>; + interrupts = <80 0x8>; + interrupt-parent = <&ipic>; + }; + i2c@3000 { #address-cells = <1>; #size-cells = <0>; @@ -161,6 +168,7 @@ fsl,channel-fifo-len = <24>; fsl,exec-units-mask = <0x7e>; fsl,descriptor-types-mask = <0x01010ebf>; + sleep = <&pmc 0x03000000>; }; ipic: interrupt-controller@700 { @@ -455,6 +463,7 @@ 0xa800 0 0 2 &ipic 20 8 0xa800 0 0 3 &ipic 21 8 0xa800 0 0 4 &ipic 18 8>; + sleep = <&pmc 0x00010000>; /* filled by u-boot */ bus-range = <0 0>; clock-frequency = <0>; diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts index 00c2bbda70134db027f1d169d9d1814c4317d545..6d892ba74e55f4125b55b2591dee798fd32ab552 100644 --- a/arch/powerpc/boot/dts/mpc8568mds.dts +++ b/arch/powerpc/boot/dts/mpc8568mds.dts @@ -40,6 +40,8 @@ i-cache-line-size = <32>; // 32 bytes d-cache-size = <0x8000>; // L1, 32K i-cache-size = <0x8000>; // L1, 32K + sleep = <&pmc 0x00008000 // core + &pmc 0x00004000>; // timebase timebase-frequency = <0>; bus-frequency = <0>; clock-frequency = <0>; @@ -94,31 +96,41 @@ interrupts = <16 2>; }; - i2c@3000 { + i2c-sleep-nexus { #address-cells = <1>; - #size-cells = <0>; - cell-index = <0>; - compatible = "fsl-i2c"; - reg = <0x3000 0x100>; - interrupts = <43 2>; - interrupt-parent = <&mpic>; - dfsrr; + #size-cells = <1>; + compatible = "simple-bus"; + sleep = <&pmc 0x00000004>; + ranges; - rtc@68 { - compatible = "dallas,ds1374"; - reg = <0x68>; + i2c@3000 { + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + compatible = "fsl-i2c"; + reg = <0x3000 0x100>; + interrupts = <43 2>; + interrupt-parent = <&mpic>; + dfsrr; + + rtc@68 { + compatible = "dallas,ds1374"; + reg = <0x68>; + interrupts = <3 1>; + interrupt-parent = <&mpic>; + }; }; - }; - i2c@3100 { - #address-cells = <1>; - #size-cells = <0>; - cell-index = <1>; - compatible = "fsl-i2c"; - reg = <0x3100 0x100>; - interrupts = <43 2>; - interrupt-parent = <&mpic>; - dfsrr; + i2c@3100 { + #address-cells = <1>; + #size-cells = <0>; + cell-index = <1>; + compatible = "fsl-i2c"; + reg = <0x3100 0x100>; + interrupts = <43 2>; + interrupt-parent = <&mpic>; + dfsrr; + }; }; dma@21300 { @@ -128,6 +140,8 @@ reg = <0x21300 0x4>; ranges = <0x0 0x21100 0x200>; cell-index = <0>; + sleep = <&pmc 0x00000400>; + dma-channel@0 { compatible = "fsl,mpc8568-dma-channel", "fsl,eloplus-dma-channel"; @@ -176,6 +190,7 @@ interrupt-parent = <&mpic>; tbi-handle = <&tbi0>; phy-handle = <&phy2>; + sleep = <&pmc 0x00000080>; mdio@520 { #address-cells = <1>; @@ -228,6 +243,7 @@ interrupt-parent = <&mpic>; tbi-handle = <&tbi1>; phy-handle = <&phy3>; + sleep = <&pmc 0x00000040>; mdio@520 { #address-cells = <1>; @@ -242,30 +258,47 @@ }; }; - serial0: serial@4500 { - cell-index = <0>; - device_type = "serial"; - compatible = "ns16550"; - reg = <0x4500 0x100>; - clock-frequency = <0>; - interrupts = <42 2>; - interrupt-parent = <&mpic>; + duart-sleep-nexus { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + sleep = <&pmc 0x00000002>; + ranges; + + serial0: serial@4500 { + cell-index = <0>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x4500 0x100>; + clock-frequency = <0>; + interrupts = <42 2>; + interrupt-parent = <&mpic>; + }; + + serial1: serial@4600 { + cell-index = <1>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x4600 0x100>; + clock-frequency = <0>; + interrupts = <42 2>; + interrupt-parent = <&mpic>; + }; }; - global-utilities@e0000 { //global utilities block - compatible = "fsl,mpc8548-guts"; + global-utilities@e0000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,mpc8568-guts", "fsl,mpc8548-guts"; reg = <0xe0000 0x1000>; + ranges = <0 0xe0000 0x1000>; fsl,has-rstcr; - }; - serial1: serial@4600 { - cell-index = <1>; - device_type = "serial"; - compatible = "ns16550"; - reg = <0x4600 0x100>; - clock-frequency = <0>; - interrupts = <42 2>; - interrupt-parent = <&mpic>; + pmc: power@70 { + compatible = "fsl,mpc8568-pmc", + "fsl,mpc8548-pmc"; + reg = <0x70 0x20>; + }; }; crypto@30000 { @@ -277,6 +310,7 @@ fsl,channel-fifo-len = <24>; fsl,exec-units-mask = <0xfe>; fsl,descriptor-types-mask = <0x12b0ebf>; + sleep = <&pmc 0x01000000>; }; mpic: pic@40000 { @@ -376,6 +410,7 @@ compatible = "fsl,qe"; ranges = <0x0 0xe0080000 0x40000>; reg = <0xe0080000 0x480>; + sleep = <&pmc 0x00000800>; brg-frequency = <0>; bus-frequency = <396000000>; fsl,qe-num-riscs = <2>; @@ -509,6 +544,7 @@ bus-range = <0 255>; ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000 0x1000000 0x0 0x0 0xe2000000 0x0 0x800000>; + sleep = <&pmc 0x80000000>; clock-frequency = <66666666>; #interrupt-cells = <1>; #size-cells = <2>; @@ -534,6 +570,7 @@ bus-range = <0 255>; ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000 0x1000000 0x0 0x0 0xe2800000 0x0 0x800000>; + sleep = <&pmc 0x20000000>; clock-frequency = <33333333>; #interrupt-cells = <1>; #size-cells = <2>; @@ -570,5 +607,7 @@ 55 2 /* msg2_tx */ 56 2 /* msg2_rx */>; interrupt-parent = <&mpic>; + sleep = <&pmc 0x00080000 /* controller */ + &pmc 0x00040000>; /* message unit */ }; }; diff --git a/arch/powerpc/boot/dts/mpc8569mds.dts b/arch/powerpc/boot/dts/mpc8569mds.dts index 1e3ec8f059bf9e6622ff2c71b4d163984ff586b4..795eb362fcf920c2d1fa1528f53ce71faa566298 100644 --- a/arch/powerpc/boot/dts/mpc8569mds.dts +++ b/arch/powerpc/boot/dts/mpc8569mds.dts @@ -41,6 +41,8 @@ i-cache-line-size = <32>; // 32 bytes d-cache-size = <0x8000>; // L1, 32K i-cache-size = <0x8000>; // L1, 32K + sleep = <&pmc 0x00008000 // core + &pmc 0x00004000>; // timebase timebase-frequency = <0>; bus-frequency = <0>; clock-frequency = <0>; @@ -59,6 +61,7 @@ reg = <0xe0005000 0x1000>; interrupts = <19 2>; interrupt-parent = <&mpic>; + sleep = <&pmc 0x08000000>; ranges = <0x0 0x0 0xfe000000 0x02000000 0x1 0x0 0xf8000000 0x00008000 @@ -158,51 +161,69 @@ interrupts = <18 2>; }; - i2c@3000 { + i2c-sleep-nexus { #address-cells = <1>; - #size-cells = <0>; - cell-index = <0>; - compatible = "fsl-i2c"; - reg = <0x3000 0x100>; - interrupts = <43 2>; - interrupt-parent = <&mpic>; - dfsrr; + #size-cells = <1>; + compatible = "simple-bus"; + sleep = <&pmc 0x00000004>; + ranges; + + i2c@3000 { + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + compatible = "fsl-i2c"; + reg = <0x3000 0x100>; + interrupts = <43 2>; + interrupt-parent = <&mpic>; + dfsrr; + + rtc@68 { + compatible = "dallas,ds1374"; + reg = <0x68>; + interrupts = <3 1>; + interrupt-parent = <&mpic>; + }; + }; - rtc@68 { - compatible = "dallas,ds1374"; - reg = <0x68>; + i2c@3100 { + #address-cells = <1>; + #size-cells = <0>; + cell-index = <1>; + compatible = "fsl-i2c"; + reg = <0x3100 0x100>; + interrupts = <43 2>; + interrupt-parent = <&mpic>; + dfsrr; }; }; - i2c@3100 { + duart-sleep-nexus { #address-cells = <1>; - #size-cells = <0>; - cell-index = <1>; - compatible = "fsl-i2c"; - reg = <0x3100 0x100>; - interrupts = <43 2>; - interrupt-parent = <&mpic>; - dfsrr; - }; + #size-cells = <1>; + compatible = "simple-bus"; + sleep = <&pmc 0x00000002>; + ranges; - serial0: serial@4500 { - cell-index = <0>; - device_type = "serial"; - compatible = "ns16550"; - reg = <0x4500 0x100>; - clock-frequency = <0>; - interrupts = <42 2>; - interrupt-parent = <&mpic>; - }; + serial0: serial@4500 { + cell-index = <0>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x4500 0x100>; + clock-frequency = <0>; + interrupts = <42 2>; + interrupt-parent = <&mpic>; + }; - serial1: serial@4600 { - cell-index = <1>; - device_type = "serial"; - compatible = "ns16550"; - reg = <0x4600 0x100>; - clock-frequency = <0>; - interrupts = <42 2>; - interrupt-parent = <&mpic>; + serial1: serial@4600 { + cell-index = <1>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x4600 0x100>; + clock-frequency = <0>; + interrupts = <42 2>; + interrupt-parent = <&mpic>; + }; }; L2: l2-cache-controller@20000 { @@ -260,6 +281,7 @@ reg = <0x2e000 0x1000>; interrupts = <72 0x8>; interrupt-parent = <&mpic>; + sleep = <&pmc 0x00200000>; /* Filled in by U-Boot */ clock-frequency = <0>; status = "disabled"; @@ -276,6 +298,7 @@ fsl,channel-fifo-len = <24>; fsl,exec-units-mask = <0xbfe>; fsl,descriptor-types-mask = <0x3ab0ebf>; + sleep = <&pmc 0x01000000>; }; mpic: pic@40000 { @@ -304,9 +327,18 @@ }; global-utilities@e0000 { - compatible = "fsl,mpc8569-guts"; + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,mpc8569-guts", "fsl,mpc8548-guts"; reg = <0xe0000 0x1000>; + ranges = <0 0xe0000 0x1000>; fsl,has-rstcr; + + pmc: power@70 { + compatible = "fsl,mpc8569-pmc", + "fsl,mpc8548-pmc"; + reg = <0x70 0x20>; + }; }; par_io@e0100 { @@ -422,6 +454,7 @@ compatible = "fsl,qe"; ranges = <0x0 0xe0080000 0x40000>; reg = <0xe0080000 0x480>; + sleep = <&pmc 0x00000800>; brg-frequency = <0>; bus-frequency = <0>; fsl,qe-num-riscs = <4>; @@ -684,6 +717,7 @@ bus-range = <0 255>; ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000 0x1000000 0x0 0x00000000 0xe2800000 0x0 0x00800000>; + sleep = <&pmc 0x20000000>; clock-frequency = <33333333>; pcie@0 { reg = <0x0 0x0 0x0 0x0 0x0>; @@ -714,5 +748,6 @@ 55 2 /* msg2_tx */ 56 2 /* msg2_rx */>; interrupt-parent = <&mpic>; + sleep = <&pmc 0x00080000>; }; }; diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts index f468d215f71675df5414339a4d79fd063a3772cf..9535ce68caaee41331554d2a330a783b503e6eb1 100644 --- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts +++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts @@ -35,6 +35,8 @@ i-cache-line-size = <32>; d-cache-size = <32768>; // L1 i-cache-size = <32768>; // L1 + sleep = <&pmc 0x00008000 0 // core + &pmc 0x00004000 0>; // timebase timebase-frequency = <0>; // From uboot bus-frequency = <0>; // From uboot clock-frequency = <0>; // From uboot @@ -60,6 +62,7 @@ 5 0 0xe8480000 0x00008000 6 0 0xe84c0000 0x00008000 3 0 0xe8000000 0x00000020>; + sleep = <&pmc 0x08000000 0>; flash@0,0 { compatible = "cfi-flash"; @@ -105,6 +108,8 @@ compatible = "fsl,fpga-pixis"; reg = <3 0 0x20>; ranges = <0 3 0 0x20>; + interrupt-parent = <&mpic>; + interrupts = <8 8>; sdcsr_pio: gpio-controller@a { #gpio-cells = <2>; @@ -163,6 +168,7 @@ reg = <0x3100 0x100>; interrupts = <43 2>; interrupt-parent = <&mpic>; + sleep = <&pmc 0x00000004 0>; dfsrr; }; @@ -174,6 +180,7 @@ clock-frequency = <0>; interrupts = <42 2>; interrupt-parent = <&mpic>; + sleep = <&pmc 0x00000002 0>; }; serial1: serial@4600 { @@ -184,6 +191,7 @@ clock-frequency = <0>; interrupts = <42 2>; interrupt-parent = <&mpic>; + sleep = <&pmc 0x00000008 0>; }; spi@7000 { @@ -196,6 +204,7 @@ interrupt-parent = <&mpic>; mode = "cpu"; gpios = <&sdcsr_pio 7 0>; + sleep = <&pmc 0x00000800 0>; mmc-slot@0 { compatible = "fsl,mpc8610hpcd-mmc-slot", @@ -213,6 +222,7 @@ reg = <0x2c000 100>; interrupts = <72 2>; interrupt-parent = <&mpic>; + sleep = <&pmc 0x04000000 0>; }; mpic: interrupt-controller@40000 { @@ -241,9 +251,18 @@ }; global-utilities@e0000 { + #address-cells = <1>; + #size-cells = <1>; compatible = "fsl,mpc8610-guts"; reg = <0xe0000 0x1000>; + ranges = <0 0xe0000 0x1000>; fsl,has-rstcr; + + pmc: power@70 { + compatible = "fsl,mpc8610-pmc", + "fsl,mpc8641d-pmc"; + reg = <0x70 0x20>; + }; }; wdt@e4000 { @@ -262,6 +281,7 @@ fsl,playback-dma = <&dma00>; fsl,capture-dma = <&dma01>; fsl,fifo-depth = <8>; + sleep = <&pmc 0 0x08000000>; }; ssi@16100 { @@ -271,6 +291,7 @@ interrupt-parent = <&mpic>; interrupts = <63 2>; fsl,fifo-depth = <8>; + sleep = <&pmc 0 0x04000000>; }; dma@21300 { @@ -280,6 +301,7 @@ cell-index = <0>; reg = <0x21300 0x4>; /* DMA general status register */ ranges = <0x0 0x21100 0x200>; + sleep = <&pmc 0x00000400 0>; dma00: dma-channel@0 { compatible = "fsl,mpc8610-dma-channel", @@ -322,6 +344,7 @@ cell-index = <1>; reg = <0xc300 0x4>; /* DMA general status register */ ranges = <0x0 0xc100 0x200>; + sleep = <&pmc 0x00000200 0>; dma-channel@0 { compatible = "fsl,mpc8610-dma-channel", @@ -369,6 +392,7 @@ bus-range = <0 0>; ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x10000000 0x01000000 0x0 0x00000000 0xe1000000 0x0 0x00100000>; + sleep = <&pmc 0x80000000 0>; clock-frequency = <33333333>; interrupt-parent = <&mpic>; interrupts = <24 2>; @@ -398,6 +422,7 @@ bus-range = <1 3>; ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000 0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>; + sleep = <&pmc 0x40000000 0>; clock-frequency = <33333333>; interrupt-parent = <&mpic>; interrupts = <26 2>; @@ -474,6 +499,7 @@ 0x0000 0 0 4 &mpic 7 1>; interrupt-parent = <&mpic>; interrupts = <25 2>; + sleep = <&pmc 0x20000000 0>; clock-frequency = <33333333>; }; }; diff --git a/arch/powerpc/boot/dts/p1020rdb.dts b/arch/powerpc/boot/dts/p1020rdb.dts new file mode 100644 index 0000000000000000000000000000000000000000..df5269093af8ceda1943b4eaf73b0f45ce9c1f3f --- /dev/null +++ b/arch/powerpc/boot/dts/p1020rdb.dts @@ -0,0 +1,477 @@ +/* + * P1020 RDB Device Tree Source + * + * Copyright 2009 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. + */ + +/dts-v1/; +/ { + model = "fsl,P1020"; + compatible = "fsl,P1020RDB"; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &serial0; + serial1 = &serial1; + pci0 = &pci0; + pci1 = &pci1; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + PowerPC,P1020@0 { + device_type = "cpu"; + reg = <0x0>; + next-level-cache = <&L2>; + }; + + PowerPC,P1020@1 { + device_type = "cpu"; + reg = <0x1>; + next-level-cache = <&L2>; + }; + }; + + memory { + device_type = "memory"; + }; + + localbus@ffe05000 { + #address-cells = <2>; + #size-cells = <1>; + compatible = "fsl,p1020-elbc", "fsl,elbc", "simple-bus"; + reg = <0 0xffe05000 0 0x1000>; + interrupts = <19 2>; + interrupt-parent = <&mpic>; + + /* NOR, NAND Flashes and Vitesse 5 port L2 switch */ + ranges = <0x0 0x0 0x0 0xef000000 0x01000000 + 0x1 0x0 0x0 0xffa00000 0x00040000 + 0x2 0x0 0x0 0xffb00000 0x00020000>; + + nor@0,0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "cfi-flash"; + reg = <0x0 0x0 0x1000000>; + bank-width = <2>; + device-width = <1>; + + partition@0 { + /* This location must not be altered */ + /* 256KB for Vitesse 7385 Switch firmware */ + reg = <0x0 0x00040000>; + label = "NOR (RO) Vitesse-7385 Firmware"; + read-only; + }; + + partition@40000 { + /* 256KB for DTB Image */ + reg = <0x00040000 0x00040000>; + label = "NOR (RO) DTB Image"; + read-only; + }; + + partition@80000 { + /* 3.5 MB for Linux Kernel Image */ + reg = <0x00080000 0x00380000>; + label = "NOR (RO) Linux Kernel Image"; + read-only; + }; + + partition@400000 { + /* 11MB for JFFS2 based Root file System */ + reg = <0x00400000 0x00b00000>; + label = "NOR (RW) JFFS2 Root File System"; + }; + + partition@f00000 { + /* This location must not be altered */ + /* 512KB for u-boot Bootloader Image */ + /* 512KB for u-boot Environment Variables */ + reg = <0x00f00000 0x00100000>; + label = "NOR (RO) U-Boot Image"; + read-only; + }; + }; + + nand@1,0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,p1020-fcm-nand", + "fsl,elbc-fcm-nand"; + reg = <0x1 0x0 0x40000>; + + partition@0 { + /* This location must not be altered */ + /* 1MB for u-boot Bootloader Image */ + reg = <0x0 0x00100000>; + label = "NAND (RO) U-Boot Image"; + read-only; + }; + + partition@100000 { + /* 1MB for DTB Image */ + reg = <0x00100000 0x00100000>; + label = "NAND (RO) DTB Image"; + read-only; + }; + + partition@200000 { + /* 4MB for Linux Kernel Image */ + reg = <0x00200000 0x00400000>; + label = "NAND (RO) Linux Kernel Image"; + read-only; + }; + + partition@600000 { + /* 4MB for Compressed Root file System Image */ + reg = <0x00600000 0x00400000>; + label = "NAND (RO) Compressed RFS Image"; + read-only; + }; + + partition@a00000 { + /* 7MB for JFFS2 based Root file System */ + reg = <0x00a00000 0x00700000>; + label = "NAND (RW) JFFS2 Root File System"; + }; + + partition@1100000 { + /* 15MB for JFFS2 based Root file System */ + reg = <0x01100000 0x00f00000>; + label = "NAND (RW) Writable User area"; + }; + }; + + L2switch@2,0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "vitesse-7385"; + reg = <0x2 0x0 0x20000>; + }; + + }; + + soc@ffe00000 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "soc"; + compatible = "fsl,p1020-immr", "simple-bus"; + ranges = <0x0 0x0 0xffe00000 0x100000>; + bus-frequency = <0>; // Filled out by uboot. + + ecm-law@0 { + compatible = "fsl,ecm-law"; + reg = <0x0 0x1000>; + fsl,num-laws = <12>; + }; + + ecm@1000 { + compatible = "fsl,p1020-ecm", "fsl,ecm"; + reg = <0x1000 0x1000>; + interrupts = <16 2>; + interrupt-parent = <&mpic>; + }; + + memory-controller@2000 { + compatible = "fsl,p1020-memory-controller"; + reg = <0x2000 0x1000>; + interrupt-parent = <&mpic>; + interrupts = <16 2>; + }; + + i2c@3000 { + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + compatible = "fsl-i2c"; + reg = <0x3000 0x100>; + interrupts = <43 2>; + interrupt-parent = <&mpic>; + dfsrr; + rtc@68 { + compatible = "dallas,ds1339"; + reg = <0x68>; + }; + }; + + i2c@3100 { + #address-cells = <1>; + #size-cells = <0>; + cell-index = <1>; + compatible = "fsl-i2c"; + reg = <0x3100 0x100>; + interrupts = <43 2>; + interrupt-parent = <&mpic>; + dfsrr; + }; + + serial0: serial@4500 { + cell-index = <0>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x4500 0x100>; + clock-frequency = <0>; + interrupts = <42 2>; + interrupt-parent = <&mpic>; + }; + + serial1: serial@4600 { + cell-index = <1>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x4600 0x100>; + clock-frequency = <0>; + interrupts = <42 2>; + interrupt-parent = <&mpic>; + }; + + spi@7000 { + cell-index = <0>; + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,espi"; + reg = <0x7000 0x1000>; + interrupts = <59 0x2>; + interrupt-parent = <&mpic>; + mode = "cpu"; + + fsl_m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,espi-flash"; + reg = <0>; + linux,modalias = "fsl_m25p80"; + modal = "s25sl128b"; + spi-max-frequency = <50000000>; + mode = <0>; + + partition@0 { + /* 512KB for u-boot Bootloader Image */ + reg = <0x0 0x00080000>; + label = "SPI (RO) U-Boot Image"; + read-only; + }; + + partition@80000 { + /* 512KB for DTB Image */ + reg = <0x00080000 0x00080000>; + label = "SPI (RO) DTB Image"; + read-only; + }; + + partition@100000 { + /* 4MB for Linux Kernel Image */ + reg = <0x00100000 0x00400000>; + label = "SPI (RO) Linux Kernel Image"; + read-only; + }; + + partition@500000 { + /* 4MB for Compressed RFS Image */ + reg = <0x00500000 0x00400000>; + label = "SPI (RO) Compressed RFS Image"; + read-only; + }; + + partition@900000 { + /* 7MB for JFFS2 based RFS */ + reg = <0x00900000 0x00700000>; + label = "SPI (RW) JFFS2 RFS"; + }; + }; + }; + + gpio: gpio-controller@f000 { + #gpio-cells = <2>; + compatible = "fsl,mpc8572-gpio"; + reg = <0xf000 0x100>; + interrupts = <47 0x2>; + interrupt-parent = <&mpic>; + gpio-controller; + }; + + L2: l2-cache-controller@20000 { + compatible = "fsl,p1020-l2-cache-controller"; + reg = <0x20000 0x1000>; + cache-line-size = <32>; // 32 bytes + cache-size = <0x40000>; // L2,256K + interrupt-parent = <&mpic>; + interrupts = <16 2>; + }; + + dma@21300 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,eloplus-dma"; + reg = <0x21300 0x4>; + ranges = <0x0 0x21100 0x200>; + cell-index = <0>; + dma-channel@0 { + compatible = "fsl,eloplus-dma-channel"; + reg = <0x0 0x80>; + cell-index = <0>; + interrupt-parent = <&mpic>; + interrupts = <20 2>; + }; + dma-channel@80 { + compatible = "fsl,eloplus-dma-channel"; + reg = <0x80 0x80>; + cell-index = <1>; + interrupt-parent = <&mpic>; + interrupts = <21 2>; + }; + dma-channel@100 { + compatible = "fsl,eloplus-dma-channel"; + reg = <0x100 0x80>; + cell-index = <2>; + interrupt-parent = <&mpic>; + interrupts = <22 2>; + }; + dma-channel@180 { + compatible = "fsl,eloplus-dma-channel"; + reg = <0x180 0x80>; + cell-index = <3>; + interrupt-parent = <&mpic>; + interrupts = <23 2>; + }; + }; + + usb@22000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl-usb2-dr"; + reg = <0x22000 0x1000>; + interrupt-parent = <&mpic>; + interrupts = <28 0x2>; + phy_type = "ulpi"; + }; + + usb@23000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl-usb2-dr"; + reg = <0x23000 0x1000>; + interrupt-parent = <&mpic>; + interrupts = <46 0x2>; + phy_type = "ulpi"; + }; + + sdhci@2e000 { + compatible = "fsl,p1020-esdhc", "fsl,esdhc"; + reg = <0x2e000 0x1000>; + interrupts = <72 0x2>; + interrupt-parent = <&mpic>; + /* Filled in by U-Boot */ + clock-frequency = <0>; + }; + + crypto@30000 { + compatible = "fsl,sec3.1", "fsl,sec3.0", "fsl,sec2.4", + "fsl,sec2.2", "fsl,sec2.1", "fsl,sec2.0"; + reg = <0x30000 0x10000>; + interrupts = <45 2 58 2>; + interrupt-parent = <&mpic>; + fsl,num-channels = <4>; + fsl,channel-fifo-len = <24>; + fsl,exec-units-mask = <0xbfe>; + fsl,descriptor-types-mask = <0x3ab0ebf>; + }; + + mpic: pic@40000 { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <0x40000 0x40000>; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + }; + + msi@41600 { + compatible = "fsl,p1020-msi", "fsl,mpic-msi"; + reg = <0x41600 0x80>; + msi-available-ranges = <0 0x100>; + interrupts = < + 0xe0 0 + 0xe1 0 + 0xe2 0 + 0xe3 0 + 0xe4 0 + 0xe5 0 + 0xe6 0 + 0xe7 0>; + interrupt-parent = <&mpic>; + }; + + global-utilities@e0000 { //global utilities block + compatible = "fsl,p1020-guts"; + reg = <0xe0000 0x1000>; + fsl,has-rstcr; + }; + }; + + pci0: pcie@ffe09000 { + compatible = "fsl,mpc8548-pcie"; + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <0 0xffe09000 0 0x1000>; + bus-range = <0 255>; + ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000 + 0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>; + clock-frequency = <33333333>; + interrupt-parent = <&mpic>; + interrupts = <16 2>; + pcie@0 { + reg = <0x0 0x0 0x0 0x0 0x0>; + #size-cells = <2>; + #address-cells = <3>; + device_type = "pci"; + ranges = <0x2000000 0x0 0xa0000000 + 0x2000000 0x0 0xa0000000 + 0x0 0x20000000 + + 0x1000000 0x0 0x0 + 0x1000000 0x0 0x0 + 0x0 0x100000>; + }; + }; + + pci1: pcie@ffe0a000 { + compatible = "fsl,mpc8548-pcie"; + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <0 0xffe0a000 0 0x1000>; + bus-range = <0 255>; + ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000 + 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>; + clock-frequency = <33333333>; + interrupt-parent = <&mpic>; + interrupts = <16 2>; + pcie@0 { + reg = <0x0 0x0 0x0 0x0 0x0>; + #size-cells = <2>; + #address-cells = <3>; + device_type = "pci"; + ranges = <0x2000000 0x0 0xc0000000 + 0x2000000 0x0 0xc0000000 + 0x0 0x20000000 + + 0x1000000 0x0 0x0 + 0x1000000 0x0 0x0 + 0x0 0x100000>; + }; + }; +}; diff --git a/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts b/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts new file mode 100644 index 0000000000000000000000000000000000000000..0fe93d0c8b2e853d2a33a51ab3bb8efe05dbfa97 --- /dev/null +++ b/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts @@ -0,0 +1,363 @@ +/* + * P2020 RDB Core0 Device Tree Source in CAMP mode. + * + * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache + * can be shared, all the other devices must be assigned to one core only. + * This dts file allows core0 to have memory, l2, i2c, spi, gpio, dma1, usb, + * eth1, eth2, sdhc, crypto, global-util, pci0. + * + * Copyright 2009 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. + */ + +/dts-v1/; +/ { + model = "fsl,P2020"; + compatible = "fsl,P2020RDB", "fsl,MPC85XXRDB-CAMP"; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + ethernet1 = &enet1; + ethernet2 = &enet2; + serial0 = &serial0; + pci0 = &pci0; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + PowerPC,P2020@0 { + device_type = "cpu"; + reg = <0x0>; + next-level-cache = <&L2>; + }; + }; + + memory { + device_type = "memory"; + }; + + soc@ffe00000 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "soc"; + compatible = "fsl,p2020-immr", "simple-bus"; + ranges = <0x0 0x0 0xffe00000 0x100000>; + bus-frequency = <0>; // Filled out by uboot. + + ecm-law@0 { + compatible = "fsl,ecm-law"; + reg = <0x0 0x1000>; + fsl,num-laws = <12>; + }; + + ecm@1000 { + compatible = "fsl,p2020-ecm", "fsl,ecm"; + reg = <0x1000 0x1000>; + interrupts = <17 2>; + interrupt-parent = <&mpic>; + }; + + memory-controller@2000 { + compatible = "fsl,p2020-memory-controller"; + reg = <0x2000 0x1000>; + interrupt-parent = <&mpic>; + interrupts = <18 2>; + }; + + i2c@3000 { + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + compatible = "fsl-i2c"; + reg = <0x3000 0x100>; + interrupts = <43 2>; + interrupt-parent = <&mpic>; + dfsrr; + rtc@68 { + compatible = "dallas,ds1339"; + reg = <0x68>; + }; + }; + + i2c@3100 { + #address-cells = <1>; + #size-cells = <0>; + cell-index = <1>; + compatible = "fsl-i2c"; + reg = <0x3100 0x100>; + interrupts = <43 2>; + interrupt-parent = <&mpic>; + dfsrr; + }; + + serial0: serial@4500 { + cell-index = <0>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x4500 0x100>; + clock-frequency = <0>; + }; + + spi@7000 { + cell-index = <0>; + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,espi"; + reg = <0x7000 0x1000>; + interrupts = <59 0x2>; + interrupt-parent = <&mpic>; + mode = "cpu"; + + fsl_m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,espi-flash"; + reg = <0>; + linux,modalias = "fsl_m25p80"; + modal = "s25sl128b"; + spi-max-frequency = <50000000>; + mode = <0>; + + partition@0 { + /* 512KB for u-boot Bootloader Image */ + reg = <0x0 0x00080000>; + label = "SPI (RO) U-Boot Image"; + read-only; + }; + + partition@80000 { + /* 512KB for DTB Image */ + reg = <0x00080000 0x00080000>; + label = "SPI (RO) DTB Image"; + read-only; + }; + + partition@100000 { + /* 4MB for Linux Kernel Image */ + reg = <0x00100000 0x00400000>; + label = "SPI (RO) Linux Kernel Image"; + read-only; + }; + + partition@500000 { + /* 4MB for Compressed RFS Image */ + reg = <0x00500000 0x00400000>; + label = "SPI (RO) Compressed RFS Image"; + read-only; + }; + + partition@900000 { + /* 7MB for JFFS2 based RFS */ + reg = <0x00900000 0x00700000>; + label = "SPI (RW) JFFS2 RFS"; + }; + }; + }; + + gpio: gpio-controller@f000 { + #gpio-cells = <2>; + compatible = "fsl,mpc8572-gpio"; + reg = <0xf000 0x100>; + interrupts = <47 0x2>; + interrupt-parent = <&mpic>; + gpio-controller; + }; + + L2: l2-cache-controller@20000 { + compatible = "fsl,p2020-l2-cache-controller"; + reg = <0x20000 0x1000>; + cache-line-size = <32>; // 32 bytes + cache-size = <0x80000>; // L2,512K + interrupt-parent = <&mpic>; + interrupts = <16 2>; + }; + + dma@21300 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,eloplus-dma"; + reg = <0x21300 0x4>; + ranges = <0x0 0x21100 0x200>; + cell-index = <0>; + dma-channel@0 { + compatible = "fsl,eloplus-dma-channel"; + reg = <0x0 0x80>; + cell-index = <0>; + interrupt-parent = <&mpic>; + interrupts = <20 2>; + }; + dma-channel@80 { + compatible = "fsl,eloplus-dma-channel"; + reg = <0x80 0x80>; + cell-index = <1>; + interrupt-parent = <&mpic>; + interrupts = <21 2>; + }; + dma-channel@100 { + compatible = "fsl,eloplus-dma-channel"; + reg = <0x100 0x80>; + cell-index = <2>; + interrupt-parent = <&mpic>; + interrupts = <22 2>; + }; + dma-channel@180 { + compatible = "fsl,eloplus-dma-channel"; + reg = <0x180 0x80>; + cell-index = <3>; + interrupt-parent = <&mpic>; + interrupts = <23 2>; + }; + }; + + usb@22000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl-usb2-dr"; + reg = <0x22000 0x1000>; + interrupt-parent = <&mpic>; + interrupts = <28 0x2>; + phy_type = "ulpi"; + }; + + mdio@24520 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,gianfar-mdio"; + reg = <0x24520 0x20>; + + phy0: ethernet-phy@0 { + interrupt-parent = <&mpic>; + interrupts = <3 1>; + reg = <0x0>; + }; + phy1: ethernet-phy@1 { + interrupt-parent = <&mpic>; + interrupts = <3 1>; + reg = <0x1>; + }; + }; + + mdio@25520 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,gianfar-tbi"; + reg = <0x26520 0x20>; + + tbi0: tbi-phy@11 { + reg = <0x11>; + device_type = "tbi-phy"; + }; + }; + + enet1: ethernet@25000 { + #address-cells = <1>; + #size-cells = <1>; + cell-index = <1>; + device_type = "network"; + model = "eTSEC"; + compatible = "gianfar"; + reg = <0x25000 0x1000>; + ranges = <0x0 0x25000 0x1000>; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <35 2 36 2 40 2>; + interrupt-parent = <&mpic>; + tbi-handle = <&tbi0>; + phy-handle = <&phy0>; + phy-connection-type = "sgmii"; + + }; + + enet2: ethernet@26000 { + #address-cells = <1>; + #size-cells = <1>; + cell-index = <2>; + device_type = "network"; + model = "eTSEC"; + compatible = "gianfar"; + reg = <0x26000 0x1000>; + ranges = <0x0 0x26000 0x1000>; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <31 2 32 2 33 2>; + interrupt-parent = <&mpic>; + phy-handle = <&phy1>; + phy-connection-type = "rgmii-id"; + }; + + sdhci@2e000 { + compatible = "fsl,p2020-esdhc", "fsl,esdhc"; + reg = <0x2e000 0x1000>; + interrupts = <72 0x2>; + interrupt-parent = <&mpic>; + /* Filled in by U-Boot */ + clock-frequency = <0>; + }; + + crypto@30000 { + compatible = "fsl,sec3.1", "fsl,sec3.0", "fsl,sec2.4", + "fsl,sec2.2", "fsl,sec2.1", "fsl,sec2.0"; + reg = <0x30000 0x10000>; + interrupts = <45 2 58 2>; + interrupt-parent = <&mpic>; + fsl,num-channels = <4>; + fsl,channel-fifo-len = <24>; + fsl,exec-units-mask = <0xbfe>; + fsl,descriptor-types-mask = <0x3ab0ebf>; + }; + + mpic: pic@40000 { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <0x40000 0x40000>; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + protected-sources = < + 42 76 77 78 79 /* serial1 , dma2 */ + 29 30 34 26 /* enet0, pci1 */ + 0xe0 0xe1 0xe2 0xe3 /* msi */ + 0xe4 0xe5 0xe6 0xe7 + >; + }; + + global-utilities@e0000 { + compatible = "fsl,p2020-guts"; + reg = <0xe0000 0x1000>; + fsl,has-rstcr; + }; + }; + + pci0: pcie@ffe09000 { + compatible = "fsl,mpc8548-pcie"; + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <0 0xffe09000 0 0x1000>; + bus-range = <0 255>; + ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000 + 0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>; + clock-frequency = <33333333>; + interrupt-parent = <&mpic>; + interrupts = <25 2>; + pcie@0 { + reg = <0x0 0x0 0x0 0x0 0x0>; + #size-cells = <2>; + #address-cells = <3>; + device_type = "pci"; + ranges = <0x2000000 0x0 0xa0000000 + 0x2000000 0x0 0xa0000000 + 0x0 0x20000000 + + 0x1000000 0x0 0x0 + 0x1000000 0x0 0x0 + 0x0 0x100000>; + }; + }; +}; diff --git a/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts b/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts new file mode 100644 index 0000000000000000000000000000000000000000..e95a51285328706c71621b0fbde402c71f2f83d2 --- /dev/null +++ b/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts @@ -0,0 +1,184 @@ +/* + * P2020 RDB Core1 Device Tree Source in CAMP mode. + * + * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache + * can be shared, all the other devices must be assigned to one core only. + * This dts allows core1 to have l2, dma2, eth0, pci1, msi. + * + * Please note to add "-b 1" for core1's dts compiling. + * + * Copyright 2009 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. + */ + +/dts-v1/; +/ { + model = "fsl,P2020"; + compatible = "fsl,P2020RDB", "fsl,MPC85XXRDB-CAMP"; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + ethernet0 = &enet0; + serial0 = &serial0; + pci1 = &pci1; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + PowerPC,P2020@1 { + device_type = "cpu"; + reg = <0x1>; + next-level-cache = <&L2>; + }; + }; + + memory { + device_type = "memory"; + }; + + soc@ffe00000 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "soc"; + compatible = "fsl,p2020-immr", "simple-bus"; + ranges = <0x0 0x0 0xffe00000 0x100000>; + bus-frequency = <0>; // Filled out by uboot. + + serial0: serial@4600 { + cell-index = <1>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x4600 0x100>; + clock-frequency = <0>; + }; + + dma@c300 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,eloplus-dma"; + reg = <0xc300 0x4>; + ranges = <0x0 0xc100 0x200>; + cell-index = <1>; + dma-channel@0 { + compatible = "fsl,eloplus-dma-channel"; + reg = <0x0 0x80>; + cell-index = <0>; + interrupt-parent = <&mpic>; + interrupts = <76 2>; + }; + dma-channel@80 { + compatible = "fsl,eloplus-dma-channel"; + reg = <0x80 0x80>; + cell-index = <1>; + interrupt-parent = <&mpic>; + interrupts = <77 2>; + }; + dma-channel@100 { + compatible = "fsl,eloplus-dma-channel"; + reg = <0x100 0x80>; + cell-index = <2>; + interrupt-parent = <&mpic>; + interrupts = <78 2>; + }; + dma-channel@180 { + compatible = "fsl,eloplus-dma-channel"; + reg = <0x180 0x80>; + cell-index = <3>; + interrupt-parent = <&mpic>; + interrupts = <79 2>; + }; + }; + + L2: l2-cache-controller@20000 { + compatible = "fsl,p2020-l2-cache-controller"; + reg = <0x20000 0x1000>; + cache-line-size = <32>; // 32 bytes + cache-size = <0x80000>; // L2,512K + interrupt-parent = <&mpic>; + }; + + + enet0: ethernet@24000 { + #address-cells = <1>; + #size-cells = <1>; + cell-index = <0>; + device_type = "network"; + model = "eTSEC"; + compatible = "gianfar"; + reg = <0x24000 0x1000>; + ranges = <0x0 0x24000 0x1000>; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <29 2 30 2 34 2>; + interrupt-parent = <&mpic>; + fixed-link = <1 1 1000 0 0>; + phy-connection-type = "rgmii-id"; + + }; + + mpic: pic@40000 { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <0x40000 0x40000>; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + protected-sources = < + 17 18 43 42 59 47 /*ecm, mem, i2c, serial0, spi,gpio */ + 16 20 21 22 23 28 /* L2, dma1, USB */ + 03 35 36 40 31 32 33 /* mdio, enet1, enet2 */ + 72 45 58 25 /* sdhci, crypto , pci */ + >; + }; + + msi@41600 { + compatible = "fsl,p2020-msi", "fsl,mpic-msi"; + reg = <0x41600 0x80>; + msi-available-ranges = <0 0x100>; + interrupts = < + 0xe0 0 + 0xe1 0 + 0xe2 0 + 0xe3 0 + 0xe4 0 + 0xe5 0 + 0xe6 0 + 0xe7 0>; + interrupt-parent = <&mpic>; + }; + }; + + pci1: pcie@ffe0a000 { + compatible = "fsl,mpc8548-pcie"; + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <0 0xffe0a000 0 0x1000>; + bus-range = <0 255>; + ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000 + 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>; + clock-frequency = <33333333>; + interrupt-parent = <&mpic>; + interrupts = <26 2>; + pcie@0 { + reg = <0x0 0x0 0x0 0x0 0x0>; + #size-cells = <2>; + #address-cells = <3>; + device_type = "pci"; + ranges = <0x2000000 0x0 0xc0000000 + 0x2000000 0x0 0xc0000000 + 0x0 0x20000000 + + 0x1000000 0x0 0x0 + 0x1000000 0x0 0x0 + 0x0 0x100000>; + }; + }; +}; diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts new file mode 100644 index 0000000000000000000000000000000000000000..6b29eab0536224b52493ee5dec3c9cc9fb3c5d61 --- /dev/null +++ b/arch/powerpc/boot/dts/p4080ds.dts @@ -0,0 +1,554 @@ +/* + * P4080DS Device Tree Source + * + * Copyright 2009 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. + */ + +/dts-v1/; + +/ { + model = "fsl,P4080DS"; + compatible = "fsl,P4080DS"; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + ccsr = &soc; + + serial0 = &serial0; + serial1 = &serial1; + serial2 = &serial2; + serial3 = &serial3; + pci0 = &pci0; + pci1 = &pci1; + pci2 = &pci2; + usb0 = &usb0; + usb1 = &usb1; + dma0 = &dma0; + dma1 = &dma1; + sdhc = &sdhc; + + rio0 = &rapidio0; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: PowerPC,4080@0 { + device_type = "cpu"; + reg = <0>; + next-level-cache = <&L2_0>; + L2_0: l2-cache { + }; + }; + cpu1: PowerPC,4080@1 { + device_type = "cpu"; + reg = <1>; + next-level-cache = <&L2_1>; + L2_1: l2-cache { + }; + }; + cpu2: PowerPC,4080@2 { + device_type = "cpu"; + reg = <2>; + next-level-cache = <&L2_2>; + L2_2: l2-cache { + }; + }; + cpu3: PowerPC,4080@3 { + device_type = "cpu"; + reg = <3>; + next-level-cache = <&L2_3>; + L2_3: l2-cache { + }; + }; + cpu4: PowerPC,4080@4 { + device_type = "cpu"; + reg = <4>; + next-level-cache = <&L2_4>; + L2_4: l2-cache { + }; + }; + cpu5: PowerPC,4080@5 { + device_type = "cpu"; + reg = <5>; + next-level-cache = <&L2_5>; + L2_5: l2-cache { + }; + }; + cpu6: PowerPC,4080@6 { + device_type = "cpu"; + reg = <6>; + next-level-cache = <&L2_6>; + L2_6: l2-cache { + }; + }; + cpu7: PowerPC,4080@7 { + device_type = "cpu"; + reg = <7>; + next-level-cache = <&L2_7>; + L2_7: l2-cache { + }; + }; + }; + + memory { + device_type = "memory"; + }; + + soc: soc@ffe000000 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "soc"; + compatible = "simple-bus"; + ranges = <0x00000000 0xf 0xfe000000 0x1000000>; + reg = <0xf 0xfe000000 0 0x00001000>; + + corenet-law@0 { + compatible = "fsl,corenet-law"; + reg = <0x0 0x1000>; + fsl,num-laws = <32>; + }; + + memory-controller@8000 { + compatible = "fsl,p4080-memory-controller"; + reg = <0x8000 0x1000>; + interrupt-parent = <&mpic>; + interrupts = <0x12 2>; + }; + + memory-controller@9000 { + compatible = "fsl,p4080-memory-controller"; + reg = <0x9000 0x1000>; + interrupt-parent = <&mpic>; + interrupts = <0x12 2>; + }; + + corenet-cf@18000 { + compatible = "fsl,corenet-cf"; + reg = <0x18000 0x1000>; + fsl,ccf-num-csdids = <32>; + fsl,ccf-num-snoopids = <32>; + }; + + iommu@20000 { + compatible = "fsl,p4080-pamu"; + reg = <0x20000 0x10000>; + interrupts = <24 2>; + interrupt-parent = <&mpic>; + }; + + mpic: pic@40000 { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <0x40000 0x40000>; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + }; + + dma0: dma@100300 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,p4080-dma", "fsl,eloplus-dma"; + reg = <0x100300 0x4>; + ranges = <0x0 0x100100 0x200>; + cell-index = <0>; + dma-channel@0 { + compatible = "fsl,p4080-dma-channel", + "fsl,eloplus-dma-channel"; + reg = <0x0 0x80>; + cell-index = <0>; + interrupt-parent = <&mpic>; + interrupts = <28 2>; + }; + dma-channel@80 { + compatible = "fsl,p4080-dma-channel", + "fsl,eloplus-dma-channel"; + reg = <0x80 0x80>; + cell-index = <1>; + interrupt-parent = <&mpic>; + interrupts = <29 2>; + }; + dma-channel@100 { + compatible = "fsl,p4080-dma-channel", + "fsl,eloplus-dma-channel"; + reg = <0x100 0x80>; + cell-index = <2>; + interrupt-parent = <&mpic>; + interrupts = <30 2>; + }; + dma-channel@180 { + compatible = "fsl,p4080-dma-channel", + "fsl,eloplus-dma-channel"; + reg = <0x180 0x80>; + cell-index = <3>; + interrupt-parent = <&mpic>; + interrupts = <31 2>; + }; + }; + + dma1: dma@101300 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,p4080-dma", "fsl,eloplus-dma"; + reg = <0x101300 0x4>; + ranges = <0x0 0x101100 0x200>; + cell-index = <1>; + dma-channel@0 { + compatible = "fsl,p4080-dma-channel", + "fsl,eloplus-dma-channel"; + reg = <0x0 0x80>; + cell-index = <0>; + interrupt-parent = <&mpic>; + interrupts = <32 2>; + }; + dma-channel@80 { + compatible = "fsl,p4080-dma-channel", + "fsl,eloplus-dma-channel"; + reg = <0x80 0x80>; + cell-index = <1>; + interrupt-parent = <&mpic>; + interrupts = <33 2>; + }; + dma-channel@100 { + compatible = "fsl,p4080-dma-channel", + "fsl,eloplus-dma-channel"; + reg = <0x100 0x80>; + cell-index = <2>; + interrupt-parent = <&mpic>; + interrupts = <34 2>; + }; + dma-channel@180 { + compatible = "fsl,p4080-dma-channel", + "fsl,eloplus-dma-channel"; + reg = <0x180 0x80>; + cell-index = <3>; + interrupt-parent = <&mpic>; + interrupts = <35 2>; + }; + }; + + spi@110000 { + cell-index = <0>; + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,espi"; + reg = <0x110000 0x1000>; + interrupts = <53 0x2>; + interrupt-parent = <&mpic>; + espi,num-ss-bits = <4>; + mode = "cpu"; + + fsl_m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,espi-flash"; + reg = <0>; + linux,modalias = "fsl_m25p80"; + spi-max-frequency = <40000000>; /* input clock */ + partition@u-boot { + label = "u-boot"; + reg = <0x00000000 0x00100000>; + read-only; + }; + partition@kernel { + label = "kernel"; + reg = <0x00100000 0x00500000>; + read-only; + }; + partition@dtb { + label = "dtb"; + reg = <0x00600000 0x00100000>; + read-only; + }; + partition@fs { + label = "file system"; + reg = <0x00700000 0x00900000>; + }; + }; + }; + + sdhc: sdhc@114000 { + compatible = "fsl,p4080-esdhc", "fsl,esdhc"; + reg = <0x114000 0x1000>; + interrupts = <48 2>; + interrupt-parent = <&mpic>; + }; + + i2c@118000 { + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + compatible = "fsl-i2c"; + reg = <0x118000 0x100>; + interrupts = <38 2>; + interrupt-parent = <&mpic>; + dfsrr; + }; + + i2c@118100 { + #address-cells = <1>; + #size-cells = <0>; + cell-index = <1>; + compatible = "fsl-i2c"; + reg = <0x118100 0x100>; + interrupts = <38 2>; + interrupt-parent = <&mpic>; + dfsrr; + eeprom@51 { + compatible = "at24,24c256"; + reg = <0x51>; + }; + eeprom@52 { + compatible = "at24,24c256"; + reg = <0x52>; + }; + rtc@68 { + compatible = "dallas,ds3232"; + reg = <0x68>; + interrupts = <0 0x1>; + interrupt-parent = <&mpic>; + }; + }; + + i2c@119000 { + #address-cells = <1>; + #size-cells = <0>; + cell-index = <2>; + compatible = "fsl-i2c"; + reg = <0x119000 0x100>; + interrupts = <39 2>; + interrupt-parent = <&mpic>; + dfsrr; + }; + + i2c@119100 { + #address-cells = <1>; + #size-cells = <0>; + cell-index = <3>; + compatible = "fsl-i2c"; + reg = <0x119100 0x100>; + interrupts = <39 2>; + interrupt-parent = <&mpic>; + dfsrr; + }; + + serial0: serial@11c500 { + cell-index = <0>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x11c500 0x100>; + clock-frequency = <0>; + interrupts = <36 2>; + interrupt-parent = <&mpic>; + }; + + serial1: serial@11c600 { + cell-index = <1>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x11c600 0x100>; + clock-frequency = <0>; + interrupts = <36 2>; + interrupt-parent = <&mpic>; + }; + + serial2: serial@11d500 { + cell-index = <2>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x11d500 0x100>; + clock-frequency = <0>; + interrupts = <37 2>; + interrupt-parent = <&mpic>; + }; + + serial3: serial@11d600 { + cell-index = <3>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x11d600 0x100>; + clock-frequency = <0>; + interrupts = <37 2>; + interrupt-parent = <&mpic>; + }; + + gpio0: gpio@130000 { + compatible = "fsl,p4080-gpio"; + reg = <0x130000 0x1000>; + interrupts = <55 2>; + interrupt-parent = <&mpic>; + #gpio-cells = <2>; + gpio-controller; + }; + + usb0: usb@210000 { + compatible = "fsl,p4080-usb2-mph", + "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph"; + reg = <0x210000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <&mpic>; + interrupts = <44 0x2>; + phy_type = "ulpi"; + }; + + usb1: usb@211000 { + compatible = "fsl,p4080-usb2-dr", + "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr"; + reg = <0x211000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <&mpic>; + interrupts = <45 0x2>; + dr_mode = "host"; + phy_type = "ulpi"; + }; + }; + + rapidio0: rapidio@ffe0c0000 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "fsl,rapidio-delta"; + reg = <0xf 0xfe0c0000 0 0x20000>; + ranges = <0 0 0xf 0xf5000000 0 0x01000000>; + interrupt-parent = <&mpic>; + /* err_irq bell_outb_irq bell_inb_irq + msg1_tx_irq msg1_rx_irq msg2_tx_irq msg2_rx_irq */ + interrupts = <16 2 56 2 57 2 60 2 61 2 62 2 63 2>; + }; + + localbus@ffe124000 { + compatible = "fsl,p4080-elbc", "fsl,elbc", "simple-bus"; + reg = <0xf 0xfe124000 0 0x1000>; + interrupts = <25 2>; + #address-cells = <2>; + #size-cells = <1>; + + ranges = <0 0 0xf 0xe8000000 0x08000000>; + + flash@0,0 { + compatible = "cfi-flash"; + reg = <0 0 0x08000000>; + bank-width = <2>; + device-width = <2>; + }; + }; + + pci0: pcie@ffe200000 { + compatible = "fsl,p4080-pcie"; + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <0xf 0xfe200000 0 0x1000>; + bus-range = <0x0 0xff>; + ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000 + 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>; + clock-frequency = <0x1fca055>; + interrupt-parent = <&mpic>; + interrupts = <16 2>; + + interrupt-map-mask = <0xf800 0 0 7>; + interrupt-map = < + /* IDSEL 0x0 */ + 0000 0 0 1 &mpic 40 1 + 0000 0 0 2 &mpic 1 1 + 0000 0 0 3 &mpic 2 1 + 0000 0 0 4 &mpic 3 1 + >; + pcie@0 { + reg = <0 0 0 0 0>; + #size-cells = <2>; + #address-cells = <3>; + device_type = "pci"; + ranges = <0x02000000 0 0xe0000000 + 0x02000000 0 0xe0000000 + 0 0x20000000 + + 0x01000000 0 0x00000000 + 0x01000000 0 0x00000000 + 0 0x00010000>; + }; + }; + + pci1: pcie@ffe201000 { + compatible = "fsl,p4080-pcie"; + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <0xf 0xfe201000 0 0x1000>; + bus-range = <0 0xff>; + ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000 + 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>; + clock-frequency = <0x1fca055>; + interrupt-parent = <&mpic>; + interrupts = <16 2>; + interrupt-map-mask = <0xf800 0 0 7>; + interrupt-map = < + /* IDSEL 0x0 */ + 0000 0 0 1 &mpic 41 1 + 0000 0 0 2 &mpic 5 1 + 0000 0 0 3 &mpic 6 1 + 0000 0 0 4 &mpic 7 1 + >; + pcie@0 { + reg = <0 0 0 0 0>; + #size-cells = <2>; + #address-cells = <3>; + device_type = "pci"; + ranges = <0x02000000 0 0xe0000000 + 0x02000000 0 0xe0000000 + 0 0x20000000 + + 0x01000000 0 0x00000000 + 0x01000000 0 0x00000000 + 0 0x00010000>; + }; + }; + + pci2: pcie@ffe202000 { + compatible = "fsl,p4080-pcie"; + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <0xf 0xfe202000 0 0x1000>; + bus-range = <0x0 0xff>; + ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000 + 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>; + clock-frequency = <0x1fca055>; + interrupt-parent = <&mpic>; + interrupts = <16 2>; + interrupt-map-mask = <0xf800 0 0 7>; + interrupt-map = < + /* IDSEL 0x0 */ + 0000 0 0 1 &mpic 42 1 + 0000 0 0 2 &mpic 9 1 + 0000 0 0 3 &mpic 10 1 + 0000 0 0 4 &mpic 11 1 + >; + pcie@0 { + reg = <0 0 0 0 0>; + #size-cells = <2>; + #address-cells = <3>; + device_type = "pci"; + ranges = <0x02000000 0 0xe0000000 + 0x02000000 0 0xe0000000 + 0 0x20000000 + + 0x01000000 0 0x00000000 + 0x01000000 0 0x00000000 + 0 0x00010000>; + }; + }; + +}; diff --git a/arch/powerpc/boot/dts/redwood.dts b/arch/powerpc/boot/dts/redwood.dts index ad402c48874144daab1ae2d04bf110cd3059dc20..d2af32e2bf7a78e83d1b700697f5aff8599b7cf6 100644 --- a/arch/powerpc/boot/dts/redwood.dts +++ b/arch/powerpc/boot/dts/redwood.dts @@ -226,6 +226,7 @@ max-frame-size = <9000>; rx-fifo-size = <4096>; tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; phy-mode = "rgmii"; phy-map = <0x00000000>; rgmii-device = <&RGMII0>; diff --git a/arch/powerpc/boot/dts/yosemite.dts b/arch/powerpc/boot/dts/yosemite.dts index 1fa3cb4c4ebb7fd352c3a73c6cdca89623a6df38..64923245f0e5adb8d481a62a49f95f709b8ed048 100644 --- a/arch/powerpc/boot/dts/yosemite.dts +++ b/arch/powerpc/boot/dts/yosemite.dts @@ -282,20 +282,10 @@ /* Inbound 2GB range starting at 0 */ dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; - /* Bamboo has all 4 IRQ pins tied together per slot */ interrupt-map-mask = <0xf800 0x0 0x0 0x0>; interrupt-map = < - /* IDSEL 1 */ - 0x800 0x0 0x0 0x0 &UIC0 0x1c 0x8 - - /* IDSEL 2 */ - 0x1000 0x0 0x0 0x0 &UIC0 0x1b 0x8 - - /* IDSEL 3 */ - 0x1800 0x0 0x0 0x0 &UIC0 0x1a 0x8 - - /* IDSEL 4 */ - 0x2000 0x0 0x0 0x0 &UIC0 0x19 0x8 + /* IDSEL 12 */ + 0x6000 0x0 0x0 0x0 &UIC0 0x19 0x8 >; }; }; diff --git a/arch/powerpc/configs/86xx/gef_ppc9a_defconfig b/arch/powerpc/configs/86xx/gef_ppc9a_defconfig index 28980738776caf28bd6486b6114afaaaeaa0d7e9..6cd2cd65c2cdfbefa7e71527a4cbbed4ae0a8f9a 100644 --- a/arch/powerpc/configs/86xx/gef_ppc9a_defconfig +++ b/arch/powerpc/configs/86xx/gef_ppc9a_defconfig @@ -218,7 +218,7 @@ CONFIG_MPIC=y # CONFIG_MPIC_WEIRD is not set # CONFIG_PPC_I8259 is not set # CONFIG_PPC_RTAS is not set -# CONFIG_MMIO_NVRAM is not set +CONFIG_MMIO_NVRAM=y # CONFIG_PPC_MPC106 is not set # CONFIG_PPC_970_NAP is not set # CONFIG_PPC_INDIRECT_IO is not set diff --git a/arch/powerpc/configs/86xx/gef_sbc310_defconfig b/arch/powerpc/configs/86xx/gef_sbc310_defconfig index e199d1cacbafdc89ab9928f1a160dd91da5cc5d2..a6a3768f73041e614089d960b49aa308d2889117 100644 --- a/arch/powerpc/configs/86xx/gef_sbc310_defconfig +++ b/arch/powerpc/configs/86xx/gef_sbc310_defconfig @@ -218,7 +218,7 @@ CONFIG_MPIC=y # CONFIG_MPIC_WEIRD is not set # CONFIG_PPC_I8259 is not set # CONFIG_PPC_RTAS is not set -# CONFIG_MMIO_NVRAM is not set +CONFIG_MMIO_NVRAM=y # CONFIG_PPC_MPC106 is not set # CONFIG_PPC_970_NAP is not set # CONFIG_PPC_INDIRECT_IO is not set diff --git a/arch/powerpc/configs/86xx/gef_sbc610_defconfig b/arch/powerpc/configs/86xx/gef_sbc610_defconfig index 3b0fbfb28efd008816d8585ca20e298617e013ad..1975d41e07632ee093ff437141f3e0406bd71beb 100644 --- a/arch/powerpc/configs/86xx/gef_sbc610_defconfig +++ b/arch/powerpc/configs/86xx/gef_sbc610_defconfig @@ -219,7 +219,7 @@ CONFIG_MPIC=y # CONFIG_MPIC_WEIRD is not set # CONFIG_PPC_I8259 is not set # CONFIG_PPC_RTAS is not set -# CONFIG_MMIO_NVRAM is not set +CONFIG_MMIO_NVRAM=y # CONFIG_PPC_MPC106 is not set # CONFIG_PPC_970_NAP is not set # CONFIG_PPC_INDIRECT_IO is not set @@ -1124,7 +1124,7 @@ CONFIG_UNIX98_PTYS=y # CONFIG_IPMI_HANDLER is not set CONFIG_HW_RANDOM=y # CONFIG_HW_RANDOM_TIMERIOMEM is not set -# CONFIG_NVRAM is not set +CONFIG_NVRAM=y # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set # CONFIG_RAW_DRIVER is not set diff --git a/arch/powerpc/include/asm/cpm.h b/arch/powerpc/include/asm/cpm.h index 24d79e3abd8e9499decfe8bb0b5bd50c94d9c0be..0835eb977ba9c31b5536e3e714545d2528f7a876 100644 --- a/arch/powerpc/include/asm/cpm.h +++ b/arch/powerpc/include/asm/cpm.h @@ -3,8 +3,47 @@ #include #include +#include #include +/* + * USB Controller pram common to QE and CPM. + */ +struct usb_ctlr { + u8 usb_usmod; + u8 usb_usadr; + u8 usb_uscom; + u8 res1[1]; + __be16 usb_usep[4]; + u8 res2[4]; + __be16 usb_usber; + u8 res3[2]; + __be16 usb_usbmr; + u8 res4[1]; + u8 usb_usbs; + /* Fields down below are QE-only */ + __be16 usb_ussft; + u8 res5[2]; + __be16 usb_usfrn; + u8 res6[0x22]; +} __attribute__ ((packed)); + +/* + * Function code bits, usually generic to devices. + */ +#ifdef CONFIG_CPM1 +#define CPMFCR_GBL ((u_char)0x00) /* Flag doesn't exist in CPM1 */ +#define CPMFCR_TC2 ((u_char)0x00) /* Flag doesn't exist in CPM1 */ +#define CPMFCR_DTB ((u_char)0x00) /* Flag doesn't exist in CPM1 */ +#define CPMFCR_BDB ((u_char)0x00) /* Flag doesn't exist in CPM1 */ +#else +#define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */ +#define CPMFCR_TC2 ((u_char)0x04) /* Transfer code 2 value */ +#define CPMFCR_DTB ((u_char)0x02) /* Use local bus for data when set */ +#define CPMFCR_BDB ((u_char)0x01) /* Use local bus for BD when set */ +#endif +#define CPMFCR_EB ((u_char)0x10) /* Set big endian byte order */ + /* Opcodes common to CPM1 and CPM2 */ #define CPM_CR_INIT_TRX ((ushort)0x0000) @@ -93,13 +132,56 @@ typedef struct cpm_buf_desc { #define BD_I2C_START (0x0400) int cpm_muram_init(void); + +#if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE) unsigned long cpm_muram_alloc(unsigned long size, unsigned long align); int cpm_muram_free(unsigned long offset); unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size); void __iomem *cpm_muram_addr(unsigned long offset); unsigned long cpm_muram_offset(void __iomem *addr); dma_addr_t cpm_muram_dma(void __iomem *addr); +#else +static inline unsigned long cpm_muram_alloc(unsigned long size, + unsigned long align) +{ + return -ENOSYS; +} + +static inline int cpm_muram_free(unsigned long offset) +{ + return -ENOSYS; +} + +static inline unsigned long cpm_muram_alloc_fixed(unsigned long offset, + unsigned long size) +{ + return -ENOSYS; +} + +static inline void __iomem *cpm_muram_addr(unsigned long offset) +{ + return NULL; +} + +static inline unsigned long cpm_muram_offset(void __iomem *addr) +{ + return -ENOSYS; +} + +static inline dma_addr_t cpm_muram_dma(void __iomem *addr) +{ + return 0; +} +#endif /* defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE) */ + +#ifdef CONFIG_CPM int cpm_command(u32 command, u8 opcode); +#else +static inline int cpm_command(u32 command, u8 opcode) +{ + return -ENOSYS; +} +#endif /* CONFIG_CPM */ int cpm2_gpiochip_add32(struct device_node *np); diff --git a/arch/powerpc/include/asm/cpm1.h b/arch/powerpc/include/asm/cpm1.h index 7685ffde882105fc81eba44d5a918309d5bbd66c..81b01192f4408f01c7da9553a49c5fb01ee31c10 100644 --- a/arch/powerpc/include/asm/cpm1.h +++ b/arch/powerpc/include/asm/cpm1.h @@ -478,51 +478,6 @@ typedef struct iic { char res2[2]; /* Reserved */ } iic_t; -/* SPI parameter RAM. -*/ -typedef struct spi { - ushort spi_rbase; /* Rx Buffer descriptor base address */ - ushort spi_tbase; /* Tx Buffer descriptor base address */ - u_char spi_rfcr; /* Rx function code */ - u_char spi_tfcr; /* Tx function code */ - ushort spi_mrblr; /* Max receive buffer length */ - uint spi_rstate; /* Internal */ - uint spi_rdp; /* Internal */ - ushort spi_rbptr; /* Internal */ - ushort spi_rbc; /* Internal */ - uint spi_rxtmp; /* Internal */ - uint spi_tstate; /* Internal */ - uint spi_tdp; /* Internal */ - ushort spi_tbptr; /* Internal */ - ushort spi_tbc; /* Internal */ - uint spi_txtmp; /* Internal */ - uint spi_res; - ushort spi_rpbase; /* Relocation pointer */ - ushort spi_res2; -} spi_t; - -/* SPI Mode register. -*/ -#define SPMODE_LOOP ((ushort)0x4000) /* Loopback */ -#define SPMODE_CI ((ushort)0x2000) /* Clock Invert */ -#define SPMODE_CP ((ushort)0x1000) /* Clock Phase */ -#define SPMODE_DIV16 ((ushort)0x0800) /* BRG/16 mode */ -#define SPMODE_REV ((ushort)0x0400) /* Reversed Data */ -#define SPMODE_MSTR ((ushort)0x0200) /* SPI Master */ -#define SPMODE_EN ((ushort)0x0100) /* Enable */ -#define SPMODE_LENMSK ((ushort)0x00f0) /* character length */ -#define SPMODE_LEN4 ((ushort)0x0030) /* 4 bits per char */ -#define SPMODE_LEN8 ((ushort)0x0070) /* 8 bits per char */ -#define SPMODE_LEN16 ((ushort)0x00f0) /* 16 bits per char */ -#define SPMODE_PMMSK ((ushort)0x000f) /* prescale modulus */ - -/* SPIE fields */ -#define SPIE_MME 0x20 -#define SPIE_TXE 0x10 -#define SPIE_BSY 0x04 -#define SPIE_TXB 0x02 -#define SPIE_RXB 0x01 - /* * RISC Controller Configuration Register definitons */ diff --git a/arch/powerpc/include/asm/cpm2.h b/arch/powerpc/include/asm/cpm2.h index 990ff191da8bdb6db1e55dfa06d092502b6ef036..f42e9baf3a4e743fddd9cf4bbc809f49aa1299d0 100644 --- a/arch/powerpc/include/asm/cpm2.h +++ b/arch/powerpc/include/asm/cpm2.h @@ -124,14 +124,6 @@ static inline void cpm2_fastbrg(uint brg, uint rate, int div16) __cpm2_setbrg(brg, rate, CPM2_BRG_INT_CLK, div16, CPM_BRG_EXTC_INT); } -/* Function code bits, usually generic to devices. -*/ -#define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */ -#define CPMFCR_EB ((u_char)0x10) /* Set big endian byte order */ -#define CPMFCR_TC2 ((u_char)0x04) /* Transfer code 2 value */ -#define CPMFCR_DTB ((u_char)0x02) /* Use local bus for data when set */ -#define CPMFCR_BDB ((u_char)0x01) /* Use local bus for BD when set */ - /* Parameter RAM offsets from the base. */ #define PROFF_SCC1 ((uint)0x8000) @@ -654,45 +646,6 @@ typedef struct iic { uint iic_txtmp; /* Internal */ } iic_t; -/* SPI parameter RAM. -*/ -typedef struct spi { - ushort spi_rbase; /* Rx Buffer descriptor base address */ - ushort spi_tbase; /* Tx Buffer descriptor base address */ - u_char spi_rfcr; /* Rx function code */ - u_char spi_tfcr; /* Tx function code */ - ushort spi_mrblr; /* Max receive buffer length */ - uint spi_rstate; /* Internal */ - uint spi_rdp; /* Internal */ - ushort spi_rbptr; /* Internal */ - ushort spi_rbc; /* Internal */ - uint spi_rxtmp; /* Internal */ - uint spi_tstate; /* Internal */ - uint spi_tdp; /* Internal */ - ushort spi_tbptr; /* Internal */ - ushort spi_tbc; /* Internal */ - uint spi_txtmp; /* Internal */ - uint spi_res; /* Tx temp. */ - uint spi_res1[4]; /* SDMA temp. */ -} spi_t; - -/* SPI Mode register. -*/ -#define SPMODE_LOOP ((ushort)0x4000) /* Loopback */ -#define SPMODE_CI ((ushort)0x2000) /* Clock Invert */ -#define SPMODE_CP ((ushort)0x1000) /* Clock Phase */ -#define SPMODE_DIV16 ((ushort)0x0800) /* BRG/16 mode */ -#define SPMODE_REV ((ushort)0x0400) /* Reversed Data */ -#define SPMODE_MSTR ((ushort)0x0200) /* SPI Master */ -#define SPMODE_EN ((ushort)0x0100) /* Enable */ -#define SPMODE_LENMSK ((ushort)0x00f0) /* character length */ -#define SPMODE_PMMSK ((ushort)0x000f) /* prescale modulus */ - -#define SPMODE_LEN(x) ((((x)-1)&0xF)<<4) -#define SPMODE_PM(x) ((x) &0xF) - -#define SPI_EB ((u_char)0x10) /* big endian byte order */ - /* IDMA parameter RAM */ typedef struct idma { diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index a98653b262312c6b3ca73b92089e7391e61527c2..57c4000719959cd4409d109f13d5cb723e70e95c 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h @@ -147,6 +147,7 @@ .globl label##_pSeries; \ label##_pSeries: \ HMT_MEDIUM; \ + DO_KVM n; \ mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) @@ -170,6 +171,7 @@ label##_pSeries: \ .globl label##_pSeries; \ label##_pSeries: \ HMT_MEDIUM; \ + DO_KVM n; \ mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \ mfspr r13,SPRN_SPRG_PACA; /* get paca address into r13 */ \ std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \ diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h index b1dafb6a9743938fdf4bc63bc0b771400122bc83..5856a66ab4047e02c1ce8ed09a69b7c6a2b209be 100644 --- a/arch/powerpc/include/asm/hugetlb.h +++ b/arch/powerpc/include/asm/hugetlb.h @@ -3,6 +3,10 @@ #include +pte_t *huge_pte_offset_and_shift(struct mm_struct *mm, + unsigned long addr, unsigned *shift); + +void flush_dcache_icache_hugepage(struct page *page); int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr, unsigned long len); @@ -11,12 +15,6 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr, unsigned long end, unsigned long floor, unsigned long ceiling); -void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, pte_t pte); - -pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, - pte_t *ptep); - /* * The version of vma_mmu_pagesize() in arch/powerpc/mm/hugetlbpage.c needs * to override the version in mm/hugetlb.c @@ -42,9 +40,26 @@ static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm) { } + +static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pte) +{ + set_pte_at(mm, addr, ptep, pte); +} + +static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) +{ + unsigned long old = pte_update(mm, addr, ptep, ~0UL, 1); + return __pte(old); +} + static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) { + pte_t pte; + pte = huge_ptep_get_and_clear(vma->vm_mm, addr, ptep); + flush_tlb_page(vma, addr); } static inline int huge_pte_none(pte_t pte) diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h index c27caac47ad1d6c92980ea78d13e03778053a13f..f0275818b95c216686765ec3c36a41c8d6132ca6 100644 --- a/arch/powerpc/include/asm/hvcall.h +++ b/arch/powerpc/include/asm/hvcall.h @@ -212,6 +212,19 @@ #define H_QUERY_INT_STATE 0x1E4 #define H_POLL_PENDING 0x1D8 #define H_ILLAN_ATTRIBUTES 0x244 +#define H_MODIFY_HEA_QP 0x250 +#define H_QUERY_HEA_QP 0x254 +#define H_QUERY_HEA 0x258 +#define H_QUERY_HEA_PORT 0x25C +#define H_MODIFY_HEA_PORT 0x260 +#define H_REG_BCMC 0x264 +#define H_DEREG_BCMC 0x268 +#define H_REGISTER_HEA_RPAGES 0x26C +#define H_DISABLE_AND_GET_HEA 0x270 +#define H_GET_HEA_INFO 0x274 +#define H_ALLOC_HEA_RESOURCE 0x278 +#define H_ADD_CONN 0x284 +#define H_DEL_CONN 0x288 #define H_JOIN 0x298 #define H_VASI_STATE 0x2A4 #define H_ENABLE_CRQ 0x2B0 diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index abbc2aaaced5bbc68d5be5699e9123a35cd99fdd..9f4c9d4f5803d10638b159abf8202e4283e5bca6 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h @@ -64,11 +64,6 @@ extern void iseries_handle_interrupts(void); get_paca()->hard_enabled = 0; \ } while(0) -static inline int irqs_disabled_flags(unsigned long flags) -{ - return flags == 0; -} - #else #if defined(CONFIG_BOOKE) diff --git a/arch/powerpc/include/asm/immap_cpm2.h b/arch/powerpc/include/asm/immap_cpm2.h index d4f069bf0e5753f4f223c42931681e375856de2d..7c64fda5357b641b203a78f65e035c2337f19992 100644 --- a/arch/powerpc/include/asm/immap_cpm2.h +++ b/arch/powerpc/include/asm/immap_cpm2.h @@ -549,7 +549,7 @@ typedef struct comm_proc { /* USB Controller. */ -typedef struct usb_ctlr { +typedef struct cpm_usb_ctlr { u8 usb_usmod; u8 usb_usadr; u8 usb_uscom; diff --git a/arch/powerpc/include/asm/immap_qe.h b/arch/powerpc/include/asm/immap_qe.h index c346d0bcd23044611e747be56b3b291361af8f3f..4e10f508570ac38bb63b6f6fc6c9cc39861c9da7 100644 --- a/arch/powerpc/include/asm/immap_qe.h +++ b/arch/powerpc/include/asm/immap_qe.h @@ -210,7 +210,7 @@ struct sir { } __attribute__ ((packed)); /* USB Controller */ -struct usb_ctlr { +struct qe_usb_ctlr { u8 usb_usmod; u8 usb_usadr; u8 usb_uscom; @@ -229,7 +229,7 @@ struct usb_ctlr { } __attribute__ ((packed)); /* MCC */ -struct mcc { +struct qe_mcc { __be32 mcce; /* MCC event register */ __be32 mccm; /* MCC mask register */ __be32 mccf; /* MCC configuration register */ @@ -431,9 +431,9 @@ struct qe_immap { struct qe_mux qmx; /* QE Multiplexer */ struct qe_timers qet; /* QE Timers */ struct spi spi[0x2]; /* spi */ - struct mcc mcc; /* mcc */ + struct qe_mcc mcc; /* mcc */ struct qe_brg brg; /* brg */ - struct usb_ctlr usb; /* USB */ + struct qe_usb_ctlr usb; /* USB */ struct si1 si1; /* SI */ u8 res11[0x800]; struct sir sir; /* SI Routing Tables */ diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h index bbcd1aaf3dfdfe79b00cc31e00850378139b1439..e054baef184599f2c13703ed688afb1d8fe0d3f6 100644 --- a/arch/powerpc/include/asm/irq.h +++ b/arch/powerpc/include/asm/irq.h @@ -17,8 +17,6 @@ #include -#define get_irq_desc(irq) (&irq_desc[(irq)]) - /* Define a way to iterate across irqs. */ #define for_each_irq(i) \ for ((i) = 0; (i) < NR_IRQS; ++(i)) @@ -34,12 +32,15 @@ extern atomic_t ppc_n_lost_interrupts; */ #define NO_IRQ_IGNORE ((unsigned int)-1) -/* Total number of virq in the platform (make it a CONFIG_* option ? */ -#define NR_IRQS 512 +/* Total number of virq in the platform */ +#define NR_IRQS CONFIG_NR_IRQS /* Number of irqs reserved for the legacy controller */ #define NUM_ISA_INTERRUPTS 16 +/* Same thing, used by the generic IRQ code */ +#define NR_IRQS_LEGACY NUM_ISA_INTERRUPTS + /* This type is the placeholder for a hardware interrupt number. It has to * be big enough to enclose whatever representation is used by a given * platform. @@ -99,7 +100,7 @@ struct irq_host_ops { * interrupt controller has for that line) */ int (*xlate)(struct irq_host *h, struct device_node *ctrler, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_type); }; @@ -313,7 +314,7 @@ extern void irq_free_virt(unsigned int virq, unsigned int count); * of the of_irq_map_*() functions. */ extern unsigned int irq_create_of_mapping(struct device_node *controller, - u32 *intspec, unsigned int intsize); + const u32 *intspec, unsigned int intsize); /** * irq_of_parse_and_map - Parse and Map an interrupt into linux virq space diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h index bb2de6aa5ce0e59b1d7a851b385e563c1358619e..81f3b0b5601ecf8c113d1c457e68463ad3f94fa6 100644 --- a/arch/powerpc/include/asm/kvm.h +++ b/arch/powerpc/include/asm/kvm.h @@ -46,6 +46,24 @@ struct kvm_regs { }; struct kvm_sregs { + __u32 pvr; + union { + struct { + __u64 sdr1; + struct { + struct { + __u64 slbe; + __u64 slbv; + } slb[64]; + } ppc64; + struct { + __u32 sr[16]; + __u64 ibat[8]; + __u64 dbat[8]; + } ppc32; + } s; + __u8 pad[1020]; + } u; }; struct kvm_fpu { diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h index 56bfae59837f761a03d4bb81a763281fbb224912..af2abe74f54440199fdccfeccdd2de085ec7a203 100644 --- a/arch/powerpc/include/asm/kvm_asm.h +++ b/arch/powerpc/include/asm/kvm_asm.h @@ -49,6 +49,46 @@ #define BOOKE_INTERRUPT_SPE_FP_ROUND 34 #define BOOKE_INTERRUPT_PERFORMANCE_MONITOR 35 +/* book3s */ + +#define BOOK3S_INTERRUPT_SYSTEM_RESET 0x100 +#define BOOK3S_INTERRUPT_MACHINE_CHECK 0x200 +#define BOOK3S_INTERRUPT_DATA_STORAGE 0x300 +#define BOOK3S_INTERRUPT_DATA_SEGMENT 0x380 +#define BOOK3S_INTERRUPT_INST_STORAGE 0x400 +#define BOOK3S_INTERRUPT_INST_SEGMENT 0x480 +#define BOOK3S_INTERRUPT_EXTERNAL 0x500 +#define BOOK3S_INTERRUPT_ALIGNMENT 0x600 +#define BOOK3S_INTERRUPT_PROGRAM 0x700 +#define BOOK3S_INTERRUPT_FP_UNAVAIL 0x800 +#define BOOK3S_INTERRUPT_DECREMENTER 0x900 +#define BOOK3S_INTERRUPT_SYSCALL 0xc00 +#define BOOK3S_INTERRUPT_TRACE 0xd00 +#define BOOK3S_INTERRUPT_PERFMON 0xf00 +#define BOOK3S_INTERRUPT_ALTIVEC 0xf20 +#define BOOK3S_INTERRUPT_VSX 0xf40 + +#define BOOK3S_IRQPRIO_SYSTEM_RESET 0 +#define BOOK3S_IRQPRIO_DATA_SEGMENT 1 +#define BOOK3S_IRQPRIO_INST_SEGMENT 2 +#define BOOK3S_IRQPRIO_DATA_STORAGE 3 +#define BOOK3S_IRQPRIO_INST_STORAGE 4 +#define BOOK3S_IRQPRIO_ALIGNMENT 5 +#define BOOK3S_IRQPRIO_PROGRAM 6 +#define BOOK3S_IRQPRIO_FP_UNAVAIL 7 +#define BOOK3S_IRQPRIO_ALTIVEC 8 +#define BOOK3S_IRQPRIO_VSX 9 +#define BOOK3S_IRQPRIO_SYSCALL 10 +#define BOOK3S_IRQPRIO_MACHINE_CHECK 11 +#define BOOK3S_IRQPRIO_DEBUG 12 +#define BOOK3S_IRQPRIO_EXTERNAL 13 +#define BOOK3S_IRQPRIO_DECREMENTER 14 +#define BOOK3S_IRQPRIO_PERFORMANCE_MONITOR 15 +#define BOOK3S_IRQPRIO_MAX 16 + +#define BOOK3S_HFLAG_DCBZ32 0x1 +#define BOOK3S_HFLAG_SLB 0x2 + #define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */ #define RESUME_FLAG_HOST (1<<1) /* Resume host? */ diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h new file mode 100644 index 0000000000000000000000000000000000000000..74b7369770d05b3f93a9c233e3815aef3ad51300 --- /dev/null +++ b/arch/powerpc/include/asm/kvm_book3s.h @@ -0,0 +1,139 @@ +/* + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright SUSE Linux Products GmbH 2009 + * + * Authors: Alexander Graf + */ + +#ifndef __ASM_KVM_BOOK3S_H__ +#define __ASM_KVM_BOOK3S_H__ + +#include +#include +#include + +struct kvmppc_slb { + u64 esid; + u64 vsid; + u64 orige; + u64 origv; + bool valid; + bool Ks; + bool Kp; + bool nx; + bool large; + bool class; +}; + +struct kvmppc_sr { + u32 raw; + u32 vsid; + bool Ks; + bool Kp; + bool nx; +}; + +struct kvmppc_bat { + u64 raw; + u32 bepi; + u32 bepi_mask; + bool vs; + bool vp; + u32 brpn; + u8 wimg; + u8 pp; +}; + +struct kvmppc_sid_map { + u64 guest_vsid; + u64 guest_esid; + u64 host_vsid; + bool valid; +}; + +#define SID_MAP_BITS 9 +#define SID_MAP_NUM (1 << SID_MAP_BITS) +#define SID_MAP_MASK (SID_MAP_NUM - 1) + +struct kvmppc_vcpu_book3s { + struct kvm_vcpu vcpu; + struct kvmppc_sid_map sid_map[SID_MAP_NUM]; + struct kvmppc_slb slb[64]; + struct { + u64 esid; + u64 vsid; + } slb_shadow[64]; + u8 slb_shadow_max; + struct kvmppc_sr sr[16]; + struct kvmppc_bat ibat[8]; + struct kvmppc_bat dbat[8]; + u64 hid[6]; + int slb_nr; + u64 sdr1; + u64 dsisr; + u64 hior; + u64 msr_mask; + u64 vsid_first; + u64 vsid_next; + u64 vsid_max; + int context_id; +}; + +#define CONTEXT_HOST 0 +#define CONTEXT_GUEST 1 +#define CONTEXT_GUEST_END 2 + +#define VSID_REAL 0xfffffffffff00000 +#define VSID_REAL_DR 0xffffffffffe00000 +#define VSID_REAL_IR 0xffffffffffd00000 +#define VSID_BAT 0xffffffffffc00000 +#define VSID_PR 0x8000000000000000 + +extern void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, u64 ea, u64 ea_mask); +extern void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 vp, u64 vp_mask); +extern void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, u64 pa_start, u64 pa_end); +extern void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 new_msr); +extern void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu); +extern void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu); +extern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte); +extern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr); +extern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu); +extern struct kvmppc_pte *kvmppc_mmu_find_pte(struct kvm_vcpu *vcpu, u64 ea, bool data); +extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr, bool data); +extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr); +extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec); +extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, + bool upper, u32 val); + +extern u32 kvmppc_trampoline_lowmem; +extern u32 kvmppc_trampoline_enter; + +static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu) +{ + return container_of(vcpu, struct kvmppc_vcpu_book3s, vcpu); +} + +static inline ulong dsisr(void) +{ + ulong r; + asm ( "mfdsisr %0 " : "=r" (r) ); + return r; +} + +extern void kvm_return_point(void); + +#define INS_DCBZ 0x7c0007ec + +#endif /* __ASM_KVM_BOOK3S_H__ */ diff --git a/arch/powerpc/include/asm/kvm_book3s_64_asm.h b/arch/powerpc/include/asm/kvm_book3s_64_asm.h new file mode 100644 index 0000000000000000000000000000000000000000..2e06ee8184ef8caef068ae2fc4496cb3404cc13c --- /dev/null +++ b/arch/powerpc/include/asm/kvm_book3s_64_asm.h @@ -0,0 +1,58 @@ +/* + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright SUSE Linux Products GmbH 2009 + * + * Authors: Alexander Graf + */ + +#ifndef __ASM_KVM_BOOK3S_ASM_H__ +#define __ASM_KVM_BOOK3S_ASM_H__ + +#ifdef CONFIG_KVM_BOOK3S_64_HANDLER + +#include + +.macro DO_KVM intno + .if (\intno == BOOK3S_INTERRUPT_SYSTEM_RESET) || \ + (\intno == BOOK3S_INTERRUPT_MACHINE_CHECK) || \ + (\intno == BOOK3S_INTERRUPT_DATA_STORAGE) || \ + (\intno == BOOK3S_INTERRUPT_INST_STORAGE) || \ + (\intno == BOOK3S_INTERRUPT_DATA_SEGMENT) || \ + (\intno == BOOK3S_INTERRUPT_INST_SEGMENT) || \ + (\intno == BOOK3S_INTERRUPT_EXTERNAL) || \ + (\intno == BOOK3S_INTERRUPT_ALIGNMENT) || \ + (\intno == BOOK3S_INTERRUPT_PROGRAM) || \ + (\intno == BOOK3S_INTERRUPT_FP_UNAVAIL) || \ + (\intno == BOOK3S_INTERRUPT_DECREMENTER) || \ + (\intno == BOOK3S_INTERRUPT_SYSCALL) || \ + (\intno == BOOK3S_INTERRUPT_TRACE) || \ + (\intno == BOOK3S_INTERRUPT_PERFMON) || \ + (\intno == BOOK3S_INTERRUPT_ALTIVEC) || \ + (\intno == BOOK3S_INTERRUPT_VSX) + + b kvmppc_trampoline_\intno +kvmppc_resume_\intno: + + .endif +.endm + +#else + +.macro DO_KVM intno +.endm + +#endif /* CONFIG_KVM_BOOK3S_64_HANDLER */ + +#endif /* __ASM_KVM_BOOK3S_ASM_H__ */ diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index c9c930ed11d71fbe55ed8a742c1857a1efdaa7e4..1201f62d0d73f23e2e75e9b9622499ca259359c7 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -21,7 +21,8 @@ #define __POWERPC_KVM_HOST_H__ #include -#include +#include +#include #include #include #include @@ -37,6 +38,8 @@ #define KVM_NR_PAGE_SIZES 1 #define KVM_PAGES_PER_HPAGE(x) (1UL<<31) +#define HPTEG_CACHE_NUM 1024 + struct kvm; struct kvm_run; struct kvm_vcpu; @@ -63,6 +66,17 @@ struct kvm_vcpu_stat { u32 dec_exits; u32 ext_intr_exits; u32 halt_wakeup; +#ifdef CONFIG_PPC64 + u32 pf_storage; + u32 pf_instruc; + u32 sp_storage; + u32 sp_instruc; + u32 queue_intr; + u32 ld; + u32 ld_slow; + u32 st; + u32 st_slow; +#endif }; enum kvm_exit_types { @@ -109,9 +123,53 @@ struct kvmppc_exit_timing { struct kvm_arch { }; +struct kvmppc_pte { + u64 eaddr; + u64 vpage; + u64 raddr; + bool may_read; + bool may_write; + bool may_execute; +}; + +struct kvmppc_mmu { + /* book3s_64 only */ + void (*slbmte)(struct kvm_vcpu *vcpu, u64 rb, u64 rs); + u64 (*slbmfee)(struct kvm_vcpu *vcpu, u64 slb_nr); + u64 (*slbmfev)(struct kvm_vcpu *vcpu, u64 slb_nr); + void (*slbie)(struct kvm_vcpu *vcpu, u64 slb_nr); + void (*slbia)(struct kvm_vcpu *vcpu); + /* book3s */ + void (*mtsrin)(struct kvm_vcpu *vcpu, u32 srnum, ulong value); + u32 (*mfsrin)(struct kvm_vcpu *vcpu, u32 srnum); + int (*xlate)(struct kvm_vcpu *vcpu, gva_t eaddr, struct kvmppc_pte *pte, bool data); + void (*reset_msr)(struct kvm_vcpu *vcpu); + void (*tlbie)(struct kvm_vcpu *vcpu, ulong addr, bool large); + int (*esid_to_vsid)(struct kvm_vcpu *vcpu, u64 esid, u64 *vsid); + u64 (*ea_to_vp)(struct kvm_vcpu *vcpu, gva_t eaddr, bool data); + bool (*is_dcbz32)(struct kvm_vcpu *vcpu); +}; + +struct hpte_cache { + u64 host_va; + u64 pfn; + ulong slot; + struct kvmppc_pte pte; +}; + struct kvm_vcpu_arch { - u32 host_stack; + ulong host_stack; u32 host_pid; +#ifdef CONFIG_PPC64 + ulong host_msr; + ulong host_r2; + void *host_retip; + ulong trampoline_lowmem; + ulong trampoline_enter; + ulong highmem_handler; + ulong host_paca_phys; + struct kvmppc_mmu mmu; +#endif u64 fpr[32]; ulong gpr[32]; @@ -123,6 +181,10 @@ struct kvm_vcpu_arch { ulong xer; ulong msr; +#ifdef CONFIG_PPC64 + ulong shadow_msr; + ulong hflags; +#endif u32 mmucr; ulong sprg0; ulong sprg1; @@ -149,6 +211,7 @@ struct kvm_vcpu_arch { u32 ivor[64]; ulong ivpr; u32 pir; + u32 pvr; u32 shadow_pid; u32 pid; @@ -174,6 +237,9 @@ struct kvm_vcpu_arch { #endif u32 last_inst; +#ifdef CONFIG_PPC64 + ulong fault_dsisr; +#endif ulong fault_dear; ulong fault_esr; gpa_t paddr_accessed; @@ -185,8 +251,15 @@ struct kvm_vcpu_arch { u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */ - struct timer_list dec_timer; + struct hrtimer dec_timer; + struct tasklet_struct tasklet; + u64 dec_jiffies; unsigned long pending_exceptions; + +#ifdef CONFIG_PPC64 + struct hpte_cache hpte_cache[HPTEG_CACHE_NUM]; + int hpte_cache_offset; +#endif }; #endif /* __POWERPC_KVM_HOST_H__ */ diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 2c6ee349df5e8cc9d5b286803a510a58b632ac9b..269ee46ab0285701f84411748a51e6f14c5b1018 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -39,6 +39,7 @@ enum emulation_result { extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); extern char kvmppc_handlers_start[]; extern unsigned long kvmppc_handler_len; +extern void kvmppc_handler_highmem(void); extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu); extern int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h index f78f65c38f054d8d7f56fafee268c33d793a62c4..14b592dfb4e824f691a71c248e2f60c6827dcf0e 100644 --- a/arch/powerpc/include/asm/lppaca.h +++ b/arch/powerpc/include/asm/lppaca.h @@ -100,7 +100,14 @@ struct lppaca { // Used to pass parms from the OS to PLIC for SetAsrAndRfid u64 saved_gpr3; // Saved GPR3 x20-x27 u64 saved_gpr4; // Saved GPR4 x28-x2F - u64 saved_gpr5; // Saved GPR5 x30-x37 + union { + u64 saved_gpr5; /* Saved GPR5 x30-x37 */ + struct { + u8 cede_latency_hint; /* x30 */ + u8 reserved[7]; /* x31-x36 */ + } fields; + } gpr5_dword; + u8 dtl_enable_mask; // Dispatch Trace Log mask x38-x38 u8 donate_dedicated_cpu; // Donate dedicated CPU cycles x39-x39 diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 9efa2be78331036ea4ae71cd10ba3aaff8141e84..9f0fc9e6ce0d1ded044bea9ba67a5475d2700156 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -266,6 +266,11 @@ struct machdep_calls { void (*suspend_disable_irqs)(void); void (*suspend_enable_irqs)(void); #endif + +#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE + ssize_t (*cpu_probe)(const char *, size_t); + ssize_t (*cpu_release)(const char *, size_t); +#endif }; extern void e500_idle(void); diff --git a/arch/powerpc/include/asm/macio.h b/arch/powerpc/include/asm/macio.h index 079c06eae4466d4319cafed887a6faa25d6cd930..a062c57696d080b99ae231a70a443ee075e443fc 100644 --- a/arch/powerpc/include/asm/macio.h +++ b/arch/powerpc/include/asm/macio.h @@ -39,6 +39,7 @@ struct macio_dev struct macio_bus *bus; /* macio bus this device is on */ struct macio_dev *media_bay; /* Device is part of a media bay */ struct of_device ofdev; + struct device_dma_parameters dma_parms; /* ide needs that */ int n_resources; struct resource resource[MACIO_DEV_COUNT_RESOURCES]; int n_interrupts; @@ -78,6 +79,8 @@ static inline unsigned long macio_resource_len(struct macio_dev *dev, int resour return res->end - res->start + 1; } +extern int macio_enable_devres(struct macio_dev *dev); + extern int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name); extern void macio_release_resource(struct macio_dev *dev, int resource_no); extern int macio_request_resources(struct macio_dev *dev, const char *name); @@ -131,6 +134,9 @@ struct macio_driver int (*resume)(struct macio_dev* dev); int (*shutdown)(struct macio_dev* dev); +#ifdef CONFIG_PMAC_MEDIABAY + void (*mediabay_event)(struct macio_dev* dev, int mb_state); +#endif struct device_driver driver; }; #define to_macio_driver(drv) container_of(drv,struct macio_driver, driver) diff --git a/arch/powerpc/include/asm/mediabay.h b/arch/powerpc/include/asm/mediabay.h index b2efb332580867aa1da0bec7074807f50259fb6e..11037a4133ee0fa9f8325cb5fb8bc1666c900373 100644 --- a/arch/powerpc/include/asm/mediabay.h +++ b/arch/powerpc/include/asm/mediabay.h @@ -17,26 +17,31 @@ #define MB_POWER 6 /* media bay contains a Power device (???) */ #define MB_NO 7 /* media bay contains nothing */ -/* Number of bays in the machine or 0 */ -extern int media_bay_count; +struct macio_dev; -#ifdef CONFIG_BLK_DEV_IDE_PMAC -#include +#ifdef CONFIG_PMAC_MEDIABAY -int check_media_bay_by_base(unsigned long base, int what); -/* called by IDE PMAC host driver to register IDE controller for media bay */ -int media_bay_set_ide_infos(struct device_node *which_bay, unsigned long base, - int irq, ide_hwif_t *hwif); +/* Check the content type of the bay, returns MB_NO if the bay is still + * transitionning + */ +extern int check_media_bay(struct macio_dev *bay); -int check_media_bay(struct device_node *which_bay, int what); +/* The ATA driver uses the calls below to temporarily hold on the + * media bay callbacks while initializing the interface + */ +extern void lock_media_bay(struct macio_dev *bay); +extern void unlock_media_bay(struct macio_dev *bay); #else -static inline int check_media_bay(struct device_node *which_bay, int what) +static inline int check_media_bay(struct macio_dev *bay) { - return -ENODEV; + return MB_NO; } +static inline void lock_media_bay(struct macio_dev *bay) { } +static inline void unlock_media_bay(struct macio_dev *bay) { } + #endif #endif /* __KERNEL__ */ diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h index bebe31c2e9072bbd79144fbb616672b092e4d84e..2102b214a87c9ab49b7540962c2faef15251f55c 100644 --- a/arch/powerpc/include/asm/mmu-hash64.h +++ b/arch/powerpc/include/asm/mmu-hash64.h @@ -173,14 +173,6 @@ extern unsigned long tce_alloc_start, tce_alloc_end; */ extern int mmu_ci_restrictions; -#ifdef CONFIG_HUGETLB_PAGE -/* - * The page size indexes of the huge pages for use by hugetlbfs - */ -extern unsigned int mmu_huge_psizes[MMU_PAGE_COUNT]; - -#endif /* CONFIG_HUGETLB_PAGE */ - /* * This function sets the AVPN and L fields of the HPTE appropriately * for the page size @@ -253,10 +245,11 @@ extern int __hash_page_64K(unsigned long ea, unsigned long access, unsigned long vsid, pte_t *ptep, unsigned long trap, unsigned int local, int ssize); struct mm_struct; +unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap); extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); -extern int hash_huge_page(struct mm_struct *mm, unsigned long access, - unsigned long ea, unsigned long vsid, int local, - unsigned long trap); +int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, + pte_t *ptep, unsigned long trap, int local, int ssize, + unsigned int shift, unsigned int mmu_psize); extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, unsigned long pstart, unsigned long prot, @@ -380,6 +373,38 @@ extern void slb_set_size(u16 size); #ifndef __ASSEMBLY__ +#ifdef CONFIG_PPC_SUBPAGE_PROT +/* + * For the sub-page protection option, we extend the PGD with one of + * these. Basically we have a 3-level tree, with the top level being + * the protptrs array. To optimize speed and memory consumption when + * only addresses < 4GB are being protected, pointers to the first + * four pages of sub-page protection words are stored in the low_prot + * array. + * Each page of sub-page protection words protects 1GB (4 bytes + * protects 64k). For the 3-level tree, each page of pointers then + * protects 8TB. + */ +struct subpage_prot_table { + unsigned long maxaddr; /* only addresses < this are protected */ + unsigned int **protptrs[2]; + unsigned int *low_prot[4]; +}; + +#define SBP_L1_BITS (PAGE_SHIFT - 2) +#define SBP_L2_BITS (PAGE_SHIFT - 3) +#define SBP_L1_COUNT (1 << SBP_L1_BITS) +#define SBP_L2_COUNT (1 << SBP_L2_BITS) +#define SBP_L2_SHIFT (PAGE_SHIFT + SBP_L1_BITS) +#define SBP_L3_SHIFT (SBP_L2_SHIFT + SBP_L2_BITS) + +extern void subpage_prot_free(struct mm_struct *mm); +extern void subpage_prot_init_new_context(struct mm_struct *mm); +#else +static inline void subpage_prot_free(struct mm_struct *mm) {} +static inline void subpage_prot_init_new_context(struct mm_struct *mm) { } +#endif /* CONFIG_PPC_SUBPAGE_PROT */ + typedef unsigned long mm_context_id_t; typedef struct { @@ -393,6 +418,9 @@ typedef struct { u16 sllp; /* SLB page size encoding */ #endif unsigned long vdso_base; +#ifdef CONFIG_PPC_SUBPAGE_PROT + struct subpage_prot_table spt; +#endif /* CONFIG_PPC_SUBPAGE_PROT */ } mm_context_t; diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index b34e94d9443583d1bd17729a1230e38adde53479..26383e0778aaaa143ad3aa793753204d5f8d7ca9 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -23,6 +23,8 @@ extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm); extern void set_context(unsigned long id, pgd_t *pgd); #ifdef CONFIG_PPC_BOOK3S_64 +extern int __init_new_context(void); +extern void __destroy_context(int context_id); static inline void mmu_context_init(void) { } #else extern void mmu_context_init(void); diff --git a/arch/powerpc/include/asm/mpc52xx.h b/arch/powerpc/include/asm/mpc52xx.h index 1b4f697abbddf0268e18506029da422eef214156..b664ce79a172cb91be4ef79486dbf59c3700fb44 100644 --- a/arch/powerpc/include/asm/mpc52xx.h +++ b/arch/powerpc/include/asm/mpc52xx.h @@ -276,6 +276,53 @@ extern int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv); extern unsigned int mpc52xx_get_xtal_freq(struct device_node *node); extern void mpc52xx_restart(char *cmd); +/* mpc52xx_gpt.c */ +struct mpc52xx_gpt_priv; +extern struct mpc52xx_gpt_priv *mpc52xx_gpt_from_irq(int irq); +extern int mpc52xx_gpt_start_timer(struct mpc52xx_gpt_priv *gpt, u64 period, + int continuous); +extern u64 mpc52xx_gpt_timer_period(struct mpc52xx_gpt_priv *gpt); +extern int mpc52xx_gpt_stop_timer(struct mpc52xx_gpt_priv *gpt); + +/* mpc52xx_lpbfifo.c */ +#define MPC52XX_LPBFIFO_FLAG_READ (0) +#define MPC52XX_LPBFIFO_FLAG_WRITE (1<<0) +#define MPC52XX_LPBFIFO_FLAG_NO_INCREMENT (1<<1) +#define MPC52XX_LPBFIFO_FLAG_NO_DMA (1<<2) +#define MPC52XX_LPBFIFO_FLAG_POLL_DMA (1<<3) + +struct mpc52xx_lpbfifo_request { + struct list_head list; + + /* localplus bus address */ + unsigned int cs; + size_t offset; + + /* Memory address */ + void *data; + phys_addr_t data_phys; + + /* Details of transfer */ + size_t size; + size_t pos; /* current position of transfer */ + int flags; + + /* What to do when finished */ + void (*callback)(struct mpc52xx_lpbfifo_request *); + + void *priv; /* Driver private data */ + + /* statistics */ + int irq_count; + int irq_ticks; + u8 last_byte; + int buffer_not_done_cnt; +}; + +extern int mpc52xx_lpbfifo_submit(struct mpc52xx_lpbfifo_request *req); +extern void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req); +extern void mpc52xx_lpbfifo_poll(void); + /* mpc52xx_pic.c */ extern void mpc52xx_init_irq(void); extern unsigned int mpc52xx_get_irq(void); diff --git a/arch/powerpc/include/asm/nvram.h b/arch/powerpc/include/asm/nvram.h index 6c587eddee59a3fd371dd83af6714d308c8d1aeb..850b72f27445ce7b0ec27ca12810182614e14fb3 100644 --- a/arch/powerpc/include/asm/nvram.h +++ b/arch/powerpc/include/asm/nvram.h @@ -73,7 +73,6 @@ extern int nvram_write_error_log(char * buff, int length, extern int nvram_read_error_log(char * buff, int length, unsigned int * err_type, unsigned int *err_seq); extern int nvram_clear_error_log(void); -extern struct nvram_partition *nvram_find_partition(int sig, const char *name); extern int pSeries_nvram_init(void); diff --git a/arch/powerpc/include/asm/pSeries_reconfig.h b/arch/powerpc/include/asm/pSeries_reconfig.h index e482e5352e69fccf95d721d4775fb4068e10d720..d4b4bfa26fb3515f535a3fb857ad67db877641c5 100644 --- a/arch/powerpc/include/asm/pSeries_reconfig.h +++ b/arch/powerpc/include/asm/pSeries_reconfig.h @@ -17,6 +17,7 @@ #ifdef CONFIG_PPC_PSERIES extern int pSeries_reconfig_notifier_register(struct notifier_block *); extern void pSeries_reconfig_notifier_unregister(struct notifier_block *); +extern struct blocking_notifier_head pSeries_reconfig_chain; #else /* !CONFIG_PPC_PSERIES */ static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb) { diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 7d8514ceceaeeb54314788ec2018fc375bace078..5e9b4ef71415c70b207769b8a9caa1ff486eea71 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -129,6 +129,15 @@ struct paca_struct { u64 system_time; /* accumulated system TB ticks */ u64 startpurr; /* PURR/TB value snapshot */ u64 startspurr; /* SPURR value snapshot */ + +#ifdef CONFIG_KVM_BOOK3S_64_HANDLER + struct { + u64 esid; + u64 vsid; + } kvm_slb[64]; /* guest SLB */ + u8 kvm_slb_max; /* highest used guest slb entry */ + u8 kvm_in_guest; /* are we inside the guest? */ +#endif }; extern struct paca_struct paca[]; diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h index ff24254990e11c4b64c35ee44f3ae664c36e8063..e96d52a516ba1bac8c0180a3eb75758bf55b919b 100644 --- a/arch/powerpc/include/asm/page.h +++ b/arch/powerpc/include/asm/page.h @@ -229,6 +229,20 @@ typedef unsigned long pgprot_t; #endif +typedef struct { signed long pd; } hugepd_t; +#define HUGEPD_SHIFT_MASK 0x3f + +#ifdef CONFIG_HUGETLB_PAGE +static inline int hugepd_ok(hugepd_t hpd) +{ + return (hpd.pd > 0); +} + +#define is_hugepd(pdep) (hugepd_ok(*((hugepd_t *)(pdep)))) +#else /* CONFIG_HUGETLB_PAGE */ +#define is_hugepd(pdep) 0 +#endif /* CONFIG_HUGETLB_PAGE */ + struct page; extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg); extern void copy_user_page(void *to, void *from, unsigned long vaddr, diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h index 3f17b83f55a18d8e4c8525136e257664414552f1..bfc4e027e2adf75640e99cd4c35555fc2834f3d8 100644 --- a/arch/powerpc/include/asm/page_64.h +++ b/arch/powerpc/include/asm/page_64.h @@ -90,7 +90,7 @@ extern unsigned int HPAGE_SHIFT; #define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) #define HPAGE_MASK (~(HPAGE_SIZE - 1)) #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) -#define HUGE_MAX_HSTATE 3 +#define HUGE_MAX_HSTATE (MMU_PAGE_COUNT-1) #endif /* __ASSEMBLY__ */ diff --git a/arch/powerpc/include/asm/pgalloc-32.h b/arch/powerpc/include/asm/pgalloc-32.h index c9500d666a1de37687346d7b7cfae5dd2f81ac7a..580cf73b96e8bd0971aad0245cfc26bdf137ddf3 100644 --- a/arch/powerpc/include/asm/pgalloc-32.h +++ b/arch/powerpc/include/asm/pgalloc-32.h @@ -3,7 +3,8 @@ #include -#define PTE_NONCACHE_NUM 0 /* dummy for now to share code w/ppc64 */ +/* For 32-bit, all levels of page tables are just drawn from get_free_page() */ +#define MAX_PGTABLE_INDEX_SIZE 0 extern void __bad_pte(pmd_t *pmd); @@ -36,11 +37,10 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr); -static inline void pgtable_free(pgtable_free_t pgf) +static inline void pgtable_free(void *table, unsigned index_size) { - void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK); - - free_page((unsigned long)p); + BUG_ON(index_size); /* 32-bit doesn't use this */ + free_page((unsigned long)table); } #define check_pgt_cache() do { } while (0) diff --git a/arch/powerpc/include/asm/pgalloc-64.h b/arch/powerpc/include/asm/pgalloc-64.h index e6f069c4f713a7b2c7ce76e3da593693d2fc1d79..605f5c5398d1d9e5acaecc32fd1cb2c27643acc4 100644 --- a/arch/powerpc/include/asm/pgalloc-64.h +++ b/arch/powerpc/include/asm/pgalloc-64.h @@ -11,27 +11,34 @@ #include #include -#ifndef CONFIG_PPC_SUBPAGE_PROT -static inline void subpage_prot_free(pgd_t *pgd) {} -#endif +/* + * Functions that deal with pagetables that could be at any level of + * the table need to be passed an "index_size" so they know how to + * handle allocation. For PTE pages (which are linked to a struct + * page for now, and drawn from the main get_free_pages() pool), the + * allocation size will be (2^index_size * sizeof(pointer)) and + * allocations are drawn from the kmem_cache in PGT_CACHE(index_size). + * + * The maximum index size needs to be big enough to allow any + * pagetable sizes we need, but small enough to fit in the low bits of + * any page table pointer. In other words all pagetables, even tiny + * ones, must be aligned to allow at least enough low 0 bits to + * contain this value. This value is also used as a mask, so it must + * be one less than a power of two. + */ +#define MAX_PGTABLE_INDEX_SIZE 0xf extern struct kmem_cache *pgtable_cache[]; - -#define PGD_CACHE_NUM 0 -#define PUD_CACHE_NUM 1 -#define PMD_CACHE_NUM 1 -#define HUGEPTE_CACHE_NUM 2 -#define PTE_NONCACHE_NUM 7 /* from GFP rather than kmem_cache */ +#define PGT_CACHE(shift) (pgtable_cache[(shift)-1]) static inline pgd_t *pgd_alloc(struct mm_struct *mm) { - return kmem_cache_alloc(pgtable_cache[PGD_CACHE_NUM], GFP_KERNEL); + return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL); } static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) { - subpage_prot_free(pgd); - kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd); + kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd); } #ifndef CONFIG_PPC_64K_PAGES @@ -40,13 +47,13 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) { - return kmem_cache_alloc(pgtable_cache[PUD_CACHE_NUM], + return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE), GFP_KERNEL|__GFP_REPEAT); } static inline void pud_free(struct mm_struct *mm, pud_t *pud) { - kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud); + kmem_cache_free(PGT_CACHE(PUD_INDEX_SIZE), pud); } static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) @@ -78,13 +85,13 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) { - return kmem_cache_alloc(pgtable_cache[PMD_CACHE_NUM], + return kmem_cache_alloc(PGT_CACHE(PMD_INDEX_SIZE), GFP_KERNEL|__GFP_REPEAT); } static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) { - kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd); + kmem_cache_free(PGT_CACHE(PMD_INDEX_SIZE), pmd); } static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, @@ -107,24 +114,22 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm, return page; } -static inline void pgtable_free(pgtable_free_t pgf) +static inline void pgtable_free(void *table, unsigned index_size) { - void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK); - int cachenum = pgf.val & PGF_CACHENUM_MASK; - - if (cachenum == PTE_NONCACHE_NUM) - free_page((unsigned long)p); - else - kmem_cache_free(pgtable_cache[cachenum], p); + if (!index_size) + free_page((unsigned long)table); + else { + BUG_ON(index_size > MAX_PGTABLE_INDEX_SIZE); + kmem_cache_free(PGT_CACHE(index_size), table); + } } -#define __pmd_free_tlb(tlb, pmd,addr) \ - pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \ - PMD_CACHE_NUM, PMD_TABLE_SIZE-1)) +#define __pmd_free_tlb(tlb, pmd, addr) \ + pgtable_free_tlb(tlb, pmd, PMD_INDEX_SIZE) #ifndef CONFIG_PPC_64K_PAGES #define __pud_free_tlb(tlb, pud, addr) \ - pgtable_free_tlb(tlb, pgtable_free_cache(pud, \ - PUD_CACHE_NUM, PUD_TABLE_SIZE-1)) + pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE) + #endif /* CONFIG_PPC_64K_PAGES */ #define check_pgt_cache() do { } while (0) diff --git a/arch/powerpc/include/asm/pgalloc.h b/arch/powerpc/include/asm/pgalloc.h index f2e812de7c3cb919f26074f79414a77271626429..abe8532bd14e4dfc27693cfadce3d49a78380881 100644 --- a/arch/powerpc/include/asm/pgalloc.h +++ b/arch/powerpc/include/asm/pgalloc.h @@ -24,25 +24,6 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage) __free_page(ptepage); } -typedef struct pgtable_free { - unsigned long val; -} pgtable_free_t; - -/* This needs to be big enough to allow for MMU_PAGE_COUNT + 2 to be stored - * and small enough to fit in the low bits of any naturally aligned page - * table cache entry. Arbitrarily set to 0x1f, that should give us some - * room to grow - */ -#define PGF_CACHENUM_MASK 0x1f - -static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, - unsigned long mask) -{ - BUG_ON(cachenum > PGF_CACHENUM_MASK); - - return (pgtable_free_t){.val = ((unsigned long) p & ~mask) | cachenum}; -} - #ifdef CONFIG_PPC64 #include #else @@ -50,12 +31,12 @@ static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, #endif #ifdef CONFIG_SMP -extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); +extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift); extern void pte_free_finish(void); #else /* CONFIG_SMP */ -static inline void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) +static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift) { - pgtable_free(pgf); + pgtable_free(table, shift); } static inline void pte_free_finish(void) { } #endif /* !CONFIG_SMP */ @@ -63,12 +44,9 @@ static inline void pte_free_finish(void) { } static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage, unsigned long address) { - pgtable_free_t pgf = pgtable_free_cache(page_address(ptepage), - PTE_NONCACHE_NUM, - PTE_TABLE_SIZE-1); tlb_flush_pgtable(tlb, address); pgtable_page_dtor(ptepage); - pgtable_free_tlb(tlb, pgf); + pgtable_free_tlb(tlb, page_address(ptepage), 0); } #endif /* __KERNEL__ */ diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h index 806abe7a3fa58c32523a167f90ad18a0ef5f8aa0..49865045d56f2559377a62c3938cb9656f76f360 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64.h +++ b/arch/powerpc/include/asm/pgtable-ppc64.h @@ -354,6 +354,7 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry) #define pgoff_to_pte(off) ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE}) #define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_RPN_SHIFT) +void pgtable_cache_add(unsigned shift, void (*ctor)(void *)); void pgtable_cache_init(void); /* @@ -378,7 +379,18 @@ void pgtable_cache_init(void); return pt; } -pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long address); +#ifdef CONFIG_HUGETLB_PAGE +pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, + unsigned *shift); +#else +static inline pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, + unsigned *shift) +{ + if (shift) + *shift = 0; + return find_linux_pte(pgdir, ea); +} +#endif /* !CONFIG_HUGETLB_PAGE */ #endif /* __ASSEMBLY__ */ diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index 2a5da069714e2e98e73ffbc4a8f7e20f84aa7a33..21207e54825b0566d5edf4c447c6d252ea76b497 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h @@ -211,6 +211,9 @@ extern void paging_init(void); */ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); +extern int gup_hugepd(hugepd_t *hugepd, unsigned pdshift, unsigned long addr, + unsigned long end, int write, struct page **pages, int *nr); + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/arch/powerpc/include/asm/pte-8xx.h b/arch/powerpc/include/asm/pte-8xx.h index dd5ea95fe61ecee232d69c511ca37b7f2401fa6a..d44826e4ff9772bf1a9b585d8466f03904030fc0 100644 --- a/arch/powerpc/include/asm/pte-8xx.h +++ b/arch/powerpc/include/asm/pte-8xx.h @@ -33,21 +33,21 @@ #define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */ #define _PAGE_SHARED 0x0004 /* No ASID (context) compare */ #define _PAGE_SPECIAL 0x0008 /* SW entry, forced to 0 by the TLB miss */ +#define _PAGE_DIRTY 0x0100 /* C: page changed */ -/* These five software bits must be masked out when the entry is loaded - * into the TLB. +/* These 4 software bits must be masked out when the entry is loaded + * into the TLB, 1 SW bit left(0x0080). */ #define _PAGE_GUARDED 0x0010 /* software: guarded access */ -#define _PAGE_DIRTY 0x0020 /* software: page changed */ -#define _PAGE_RW 0x0040 /* software: user write access allowed */ -#define _PAGE_ACCESSED 0x0080 /* software: page referenced */ +#define _PAGE_ACCESSED 0x0020 /* software: page referenced */ +#define _PAGE_WRITETHRU 0x0040 /* software: caching is write through */ /* Setting any bits in the nibble with the follow two controls will * require a TLB exception handler change. It is assumed unused bits * are always zero. */ -#define _PAGE_HWWRITE 0x0100 /* h/w write enable: never set in Linux PTE */ -#define _PAGE_USER 0x0800 /* One of the PP bits, the other is USER&~RW */ +#define _PAGE_RW 0x0400 /* lsb PP bits, inverted in HW */ +#define _PAGE_USER 0x0800 /* msb PP bits */ #define _PMD_PRESENT 0x0001 #define _PMD_BAD 0x0ff0 diff --git a/arch/powerpc/include/asm/pte-hash64-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h index 82b72207c51c9113600ce8b8fc5297115623142c..c4490f9c67c476bbb673def3ac75bb6249f6b470 100644 --- a/arch/powerpc/include/asm/pte-hash64-64k.h +++ b/arch/powerpc/include/asm/pte-hash64-64k.h @@ -76,41 +76,4 @@ remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \ __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN)) - -#ifdef CONFIG_PPC_SUBPAGE_PROT -/* - * For the sub-page protection option, we extend the PGD with one of - * these. Basically we have a 3-level tree, with the top level being - * the protptrs array. To optimize speed and memory consumption when - * only addresses < 4GB are being protected, pointers to the first - * four pages of sub-page protection words are stored in the low_prot - * array. - * Each page of sub-page protection words protects 1GB (4 bytes - * protects 64k). For the 3-level tree, each page of pointers then - * protects 8TB. - */ -struct subpage_prot_table { - unsigned long maxaddr; /* only addresses < this are protected */ - unsigned int **protptrs[2]; - unsigned int *low_prot[4]; -}; - -#undef PGD_TABLE_SIZE -#define PGD_TABLE_SIZE ((sizeof(pgd_t) << PGD_INDEX_SIZE) + \ - sizeof(struct subpage_prot_table)) - -#define SBP_L1_BITS (PAGE_SHIFT - 2) -#define SBP_L2_BITS (PAGE_SHIFT - 3) -#define SBP_L1_COUNT (1 << SBP_L1_BITS) -#define SBP_L2_COUNT (1 << SBP_L2_BITS) -#define SBP_L2_SHIFT (PAGE_SHIFT + SBP_L1_BITS) -#define SBP_L3_SHIFT (SBP_L2_SHIFT + SBP_L2_BITS) - -extern void subpage_prot_free(pgd_t *pgd); - -static inline struct subpage_prot_table *pgd_subpage_prot(pgd_t *pgd) -{ - return (struct subpage_prot_table *)(pgd + PTRS_PER_PGD); -} -#endif /* CONFIG_PPC_SUBPAGE_PROT */ #endif /* __ASSEMBLY__ */ diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h index f388f0ab193f469b738ad60233ad8b3efaa55e8b..0947b36e534cc886d7c6127c8ef6907b5571b8d3 100644 --- a/arch/powerpc/include/asm/qe.h +++ b/arch/powerpc/include/asm/qe.h @@ -87,7 +87,7 @@ extern spinlock_t cmxgcr_lock; /* Export QE common operations */ #ifdef CONFIG_QUICC_ENGINE -extern void __init qe_reset(void); +extern void qe_reset(void); #else static inline void qe_reset(void) {} #endif @@ -145,8 +145,17 @@ static inline void qe_pin_set_gpio(struct qe_pin *qe_pin) {} static inline void qe_pin_set_dedicated(struct qe_pin *pin) {} #endif /* CONFIG_QE_GPIO */ -/* QE internal API */ +#ifdef CONFIG_QUICC_ENGINE int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input); +#else +static inline int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, + u32 cmd_input) +{ + return -ENOSYS; +} +#endif /* CONFIG_QUICC_ENGINE */ + +/* QE internal API */ enum qe_clock qe_clock_source(const char *source); unsigned int qe_get_brg_clk(void); int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier); @@ -154,7 +163,28 @@ int qe_get_snum(void); void qe_put_snum(u8 snum); unsigned int qe_get_num_of_risc(void); unsigned int qe_get_num_of_snums(void); -int qe_alive_during_sleep(void); + +static inline int qe_alive_during_sleep(void) +{ + /* + * MPC8568E reference manual says: + * + * "...power down sequence waits for all I/O interfaces to become idle. + * In some applications this may happen eventually without actively + * shutting down interfaces, but most likely, software will have to + * take steps to shut down the eTSEC, QUICC Engine Block, and PCI + * interfaces before issuing the command (either the write to the core + * MSR[WE] as described above or writing to POWMGTCSR) to put the + * device into sleep state." + * + * MPC8569E reference manual has a similar paragraph. + */ +#ifdef CONFIG_PPC_85xx + return 0; +#else + return 1; +#endif +} /* we actually use cpm_muram implementation, define this for convenience */ #define qe_muram_init cpm_muram_init @@ -210,8 +240,15 @@ struct qe_firmware_info { u64 extended_modes; /* Extended modes */ }; +#ifdef CONFIG_QUICC_ENGINE /* Upload a firmware to the QE */ int qe_upload_firmware(const struct qe_firmware *firmware); +#else +static inline int qe_upload_firmware(const struct qe_firmware *firmware) +{ + return -ENOSYS; +} +#endif /* CONFIG_QUICC_ENGINE */ /* Obtain information on the uploaded firmware */ struct qe_firmware_info *qe_get_firmware_info(void); diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index d9ea8d39c3428fa88ef2c88fbab5e40d12e83fe5..1d3b270d30835c1f8d94b054b35584ad1d5c9c89 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -37,7 +37,7 @@ extern void cpu_die(void); extern void smp_send_debugger_break(int cpu); extern void smp_message_recv(int); -DECLARE_PER_CPU(unsigned int, pvr); +DECLARE_PER_CPU(unsigned int, cpu_pvr); #ifdef CONFIG_HOTPLUG_CPU extern void fixup_irqs(cpumask_t map); diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index c7d671a7d9a1d7ce79ec32341da4b1eba928cfbb..07d2d19ab5e9a59696dff7659d31cefb04343616 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h @@ -145,7 +145,7 @@ SYSCALL_SPU(setfsuid) SYSCALL_SPU(setfsgid) SYSCALL_SPU(llseek) COMPAT_SYS_SPU(getdents) -SYSX_SPU(sys_select,ppc32_select,ppc_select) +SYSX_SPU(sys_select,ppc32_select,sys_select) SYSCALL_SPU(flock) SYSCALL_SPU(msync) COMPAT_SYS_SPU(readv) diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index b23664a0b86c89c7c87bde645acf3a338dc9e279..c002b0410219a341c8fdc880baa8c0acc45bd683 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -42,10 +42,11 @@ obj-$(CONFIG_ALTIVEC) += vecemu.o obj-$(CONFIG_PPC_970_NAP) += idle_power4.o obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o obj-$(CONFIG_PPC_CLOCK) += clock.o -procfs-$(CONFIG_PPC64) := proc_ppc64.o +procfs-y := proc_powerpc.o obj-$(CONFIG_PROC_FS) += $(procfs-y) rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y) +obj-$(CONFIG_PPC_RTAS_DAEMON) += rtasd.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_RTAS_PROC) += rtas-proc.o obj-$(CONFIG_LPARCFG) += lparcfg.o diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 0812b0f414bbe486f38db00ab1a171c4810410ef..a6c2b63227b32aa8b891ce33b5c3b8acc8787be0 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -190,6 +190,11 @@ int main(void) DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset)); DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); +#ifdef CONFIG_KVM_BOOK3S_64_HANDLER + DEFINE(PACA_KVM_IN_GUEST, offsetof(struct paca_struct, kvm_in_guest)); + DEFINE(PACA_KVM_SLB, offsetof(struct paca_struct, kvm_slb)); + DEFINE(PACA_KVM_SLB_MAX, offsetof(struct paca_struct, kvm_slb_max)); +#endif #endif /* CONFIG_PPC64 */ /* RTAS */ @@ -398,14 +403,24 @@ int main(void) DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst)); DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear)); DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr)); + + /* book3s_64 */ +#ifdef CONFIG_PPC64 + DEFINE(VCPU_FAULT_DSISR, offsetof(struct kvm_vcpu, arch.fault_dsisr)); + DEFINE(VCPU_HOST_RETIP, offsetof(struct kvm_vcpu, arch.host_retip)); + DEFINE(VCPU_HOST_R2, offsetof(struct kvm_vcpu, arch.host_r2)); + DEFINE(VCPU_HOST_MSR, offsetof(struct kvm_vcpu, arch.host_msr)); + DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr)); + DEFINE(VCPU_TRAMPOLINE_LOWMEM, offsetof(struct kvm_vcpu, arch.trampoline_lowmem)); + DEFINE(VCPU_TRAMPOLINE_ENTER, offsetof(struct kvm_vcpu, arch.trampoline_enter)); + DEFINE(VCPU_HIGHMEM_HANDLER, offsetof(struct kvm_vcpu, arch.highmem_handler)); + DEFINE(VCPU_HFLAGS, offsetof(struct kvm_vcpu, arch.hflags)); +#endif #endif #ifdef CONFIG_44x DEFINE(PGD_T_LOG2, PGD_T_LOG2); DEFINE(PTE_T_LOG2, PTE_T_LOG2); #endif -#ifdef CONFIG_FSL_BOOKE - DEFINE(TLBCAM_SIZE, sizeof(struct tlbcam)); -#endif #ifdef CONFIG_KVM_EXIT_TIMING DEFINE(VCPU_TIMING_EXIT_TBU, offsetof(struct kvm_vcpu, diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 0a8439aafdd1ed26f78d61bc110703f32bd284c4..6f4613dd05ef05294e10f8cab83e243094f7f731 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c @@ -373,7 +373,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs) hard_irq_disable(); for_each_irq(i) { - struct irq_desc *desc = irq_desc + i; + struct irq_desc *desc = irq_to_desc(i); if (desc->status & IRQ_INPROGRESS) desc->chip->eoi(i); diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c index e96cbbd9b449874e09dc38288abead50c8db1673..59c928564a038e490e260fb28862f022659d4d6f 100644 --- a/arch/powerpc/kernel/dma-swiotlb.c +++ b/arch/powerpc/kernel/dma-swiotlb.c @@ -21,7 +21,6 @@ #include #include -int swiotlb __read_mostly; unsigned int ppc_swiotlb_enable; /* diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index c7eb4e0eb86cae27f3fcd510519d5177b124fa5e..e3be98ffe2a7246a37f280b8755e0d3d3117e24d 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -41,6 +41,7 @@ __start_interrupts: . = 0x200 _machine_check_pSeries: HMT_MEDIUM + DO_KVM 0x200 mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */ EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) @@ -48,6 +49,7 @@ _machine_check_pSeries: .globl data_access_pSeries data_access_pSeries: HMT_MEDIUM + DO_KVM 0x300 mtspr SPRN_SPRG_SCRATCH0,r13 BEGIN_FTR_SECTION mfspr r13,SPRN_SPRG_PACA @@ -77,6 +79,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_SLB) .globl data_access_slb_pSeries data_access_slb_pSeries: HMT_MEDIUM + DO_KVM 0x380 mtspr SPRN_SPRG_SCRATCH0,r13 mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */ std r3,PACA_EXSLB+EX_R3(r13) @@ -115,6 +118,7 @@ data_access_slb_pSeries: .globl instruction_access_slb_pSeries instruction_access_slb_pSeries: HMT_MEDIUM + DO_KVM 0x480 mtspr SPRN_SPRG_SCRATCH0,r13 mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */ std r3,PACA_EXSLB+EX_R3(r13) @@ -154,6 +158,7 @@ instruction_access_slb_pSeries: .globl system_call_pSeries system_call_pSeries: HMT_MEDIUM + DO_KVM 0xc00 BEGIN_FTR_SECTION cmpdi r0,0x1ebe beq- 1f @@ -187,14 +192,17 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) */ performance_monitor_pSeries_1: . = 0xf00 + DO_KVM 0xf00 b performance_monitor_pSeries altivec_unavailable_pSeries_1: . = 0xf20 + DO_KVM 0xf20 b altivec_unavailable_pSeries vsx_unavailable_pSeries_1: . = 0xf40 + DO_KVM 0xf40 b vsx_unavailable_pSeries #ifdef CONFIG_CBE_RAS diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index c38afdb45d7b066d2720d69a484f4c5a38ed71c0..9258074880221d48af37c37d1e8db69b3e378b47 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -37,6 +37,7 @@ #include #include #include +#include /* The physical memory is layed out such that the secondary processor * spin code sits at 0x0000...0x00ff. On server, the vectors follow @@ -165,6 +166,12 @@ exception_marker: #include "exceptions-64s.S" #endif +/* KVM trampoline code needs to be close to the interrupt handlers */ + +#ifdef CONFIG_KVM_BOOK3S_64_HANDLER +#include "../kvm/book3s_64_rmhandlers.S" +#endif + _GLOBAL(generic_secondary_thread_init) mr r24,r3 diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 6ded19d01891704ce0e49310812f5111afeb135c..678f98cd5e640c13c97b9edd60ebd721f9218c71 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -206,6 +206,8 @@ MachineCheck: EXCEPTION_PROLOG mfspr r4,SPRN_DAR stw r4,_DAR(r11) + li r5,0x00f0 + mtspr SPRN_DAR,r5 /* Tag DAR, to be used in DTLB Error */ mfspr r5,SPRN_DSISR stw r5,_DSISR(r11) addi r3,r1,STACK_FRAME_OVERHEAD @@ -222,6 +224,8 @@ DataAccess: stw r10,_DSISR(r11) mr r5,r10 mfspr r4,SPRN_DAR + li r10,0x00f0 + mtspr SPRN_DAR,r10 /* Tag DAR, to be used in DTLB Error */ EXC_XFER_EE_LITE(0x300, handle_page_fault) /* Instruction access exception. @@ -244,6 +248,8 @@ Alignment: EXCEPTION_PROLOG mfspr r4,SPRN_DAR stw r4,_DAR(r11) + li r5,0x00f0 + mtspr SPRN_DAR,r5 /* Tag DAR, to be used in DTLB Error */ mfspr r5,SPRN_DSISR stw r5,_DSISR(r11) addi r3,r1,STACK_FRAME_OVERHEAD @@ -333,26 +339,20 @@ InstructionTLBMiss: mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ lwz r10, 0(r11) /* Get the pte */ -#ifdef CONFIG_SWAP - /* do not set the _PAGE_ACCESSED bit of a non-present page */ - andi. r11, r10, _PAGE_PRESENT - beq 4f - ori r10, r10, _PAGE_ACCESSED - mfspr r11, SPRN_MD_TWC /* get the pte address again */ - stw r10, 0(r11) -4: -#else - ori r10, r10, _PAGE_ACCESSED - stw r10, 0(r11) -#endif + andi. r11, r10, _PAGE_ACCESSED | _PAGE_PRESENT + cmpwi cr0, r11, _PAGE_ACCESSED | _PAGE_PRESENT + bne- cr0, 2f + + /* Clear PP lsb, 0x400 */ + rlwinm r10, r10, 0, 22, 20 /* The Linux PTE won't go exactly into the MMU TLB. - * Software indicator bits 21, 22 and 28 must be clear. + * Software indicator bits 22 and 28 must be clear. * Software indicator bits 24, 25, 26, and 27 must be * set. All other Linux PTE bits control the behavior * of the MMU. */ -2: li r11, 0x00f0 + li r11, 0x00f0 rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ DO_8xx_CPU6(0x2d80, r3) mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ @@ -365,6 +365,22 @@ InstructionTLBMiss: lwz r3, 8(r0) #endif rfi +2: + mfspr r11, SPRN_SRR1 + /* clear all error bits as TLB Miss + * sets a few unconditionally + */ + rlwinm r11, r11, 0, 0xffff + mtspr SPRN_SRR1, r11 + + mfspr r10, SPRN_M_TW /* Restore registers */ + lwz r11, 0(r0) + mtcr r11 + lwz r11, 4(r0) +#ifdef CONFIG_8xx_CPU6 + lwz r3, 8(r0) +#endif + b InstructionAccess . = 0x1200 DataStoreTLBMiss: @@ -406,29 +422,45 @@ DataStoreTLBMiss: * above. */ rlwimi r11, r10, 0, 27, 27 + /* Insert the WriteThru flag into the TWC from the Linux PTE. + * It is bit 25 in the Linux PTE and bit 30 in the TWC + */ + rlwimi r11, r10, 32-5, 30, 30 DO_8xx_CPU6(0x3b80, r3) mtspr SPRN_MD_TWC, r11 -#ifdef CONFIG_SWAP - /* do not set the _PAGE_ACCESSED bit of a non-present page */ - andi. r11, r10, _PAGE_PRESENT - beq 4f - ori r10, r10, _PAGE_ACCESSED -4: - /* and update pte in table */ -#else - ori r10, r10, _PAGE_ACCESSED -#endif - mfspr r11, SPRN_MD_TWC /* get the pte address again */ - stw r10, 0(r11) + /* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set. + * We also need to know if the insn is a load/store, so: + * Clear _PAGE_PRESENT and load that which will + * trap into DTLB Error with store bit set accordinly. + */ + /* PRESENT=0x1, ACCESSED=0x20 + * r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5)); + * r10 = (r10 & ~PRESENT) | r11; + */ + rlwinm r11, r10, 32-5, _PAGE_PRESENT + and r11, r11, r10 + rlwimi r10, r11, 0, _PAGE_PRESENT + + /* Honour kernel RO, User NA */ + /* 0x200 == Extended encoding, bit 22 */ + /* r11 = (r10 & _PAGE_USER) >> 2 */ + rlwinm r11, r10, 32-2, 0x200 + or r10, r11, r10 + /* r11 = (r10 & _PAGE_RW) >> 1 */ + rlwinm r11, r10, 32-1, 0x200 + or r10, r11, r10 + /* invert RW and 0x200 bits */ + xori r10, r10, _PAGE_RW | 0x200 /* The Linux PTE won't go exactly into the MMU TLB. - * Software indicator bits 21, 22 and 28 must be clear. + * Software indicator bits 22 and 28 must be clear. * Software indicator bits 24, 25, 26, and 27 must be * set. All other Linux PTE bits control the behavior * of the MMU. */ 2: li r11, 0x00f0 + mtspr SPRN_DAR,r11 /* Tag DAR */ rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ DO_8xx_CPU6(0x3d80, r3) mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ @@ -469,97 +501,10 @@ DataTLBError: stw r10, 0(r0) stw r11, 4(r0) - /* First, make sure this was a store operation. - */ - mfspr r10, SPRN_DSISR - andis. r11, r10, 0x0200 /* If set, indicates store op */ - beq 2f - - /* The EA of a data TLB miss is automatically stored in the MD_EPN - * register. The EA of a data TLB error is automatically stored in - * the DAR, but not the MD_EPN register. We must copy the 20 most - * significant bits of the EA from the DAR to MD_EPN before we - * start walking the page tables. We also need to copy the CASID - * value from the M_CASID register. - * Addendum: The EA of a data TLB error is _supposed_ to be stored - * in DAR, but it seems that this doesn't happen in some cases, such - * as when the error is due to a dcbi instruction to a page with a - * TLB that doesn't have the changed bit set. In such cases, there - * does not appear to be any way to recover the EA of the error - * since it is neither in DAR nor MD_EPN. As a workaround, the - * _PAGE_HWWRITE bit is set for all kernel data pages when the PTEs - * are initialized in mapin_ram(). This will avoid the problem, - * assuming we only use the dcbi instruction on kernel addresses. - */ mfspr r10, SPRN_DAR - rlwinm r11, r10, 0, 0, 19 - ori r11, r11, MD_EVALID - mfspr r10, SPRN_M_CASID - rlwimi r11, r10, 0, 28, 31 - DO_8xx_CPU6(0x3780, r3) - mtspr SPRN_MD_EPN, r11 - - mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */ - - /* If we are faulting a kernel address, we have to use the - * kernel page tables. - */ - andi. r11, r10, 0x0800 - beq 3f - lis r11, swapper_pg_dir@h - ori r11, r11, swapper_pg_dir@l - rlwimi r10, r11, 0, 2, 19 -3: - lwz r11, 0(r10) /* Get the level 1 entry */ - rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ - beq 2f /* If zero, bail */ - - /* We have a pte table, so fetch the pte from the table. - */ - ori r11, r11, 1 /* Set valid bit in physical L2 page */ - DO_8xx_CPU6(0x3b80, r3) - mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ - mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ - lwz r10, 0(r11) /* Get the pte */ - - andi. r11, r10, _PAGE_RW /* Is it writeable? */ - beq 2f /* Bail out if not */ - - /* Update 'changed', among others. - */ -#ifdef CONFIG_SWAP - ori r10, r10, _PAGE_DIRTY|_PAGE_HWWRITE - /* do not set the _PAGE_ACCESSED bit of a non-present page */ - andi. r11, r10, _PAGE_PRESENT - beq 4f - ori r10, r10, _PAGE_ACCESSED -4: -#else - ori r10, r10, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE -#endif - mfspr r11, SPRN_MD_TWC /* Get pte address again */ - stw r10, 0(r11) /* and update pte in table */ - - /* The Linux PTE won't go exactly into the MMU TLB. - * Software indicator bits 21, 22 and 28 must be clear. - * Software indicator bits 24, 25, 26, and 27 must be - * set. All other Linux PTE bits control the behavior - * of the MMU. - */ - li r11, 0x00f0 - rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ - DO_8xx_CPU6(0x3d80, r3) - mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ - - mfspr r10, SPRN_M_TW /* Restore registers */ - lwz r11, 0(r0) - mtcr r11 - lwz r11, 4(r0) -#ifdef CONFIG_8xx_CPU6 - lwz r3, 8(r0) -#endif - rfi -2: + cmpwi cr0, r10, 0x00f0 + beq- FixupDAR /* must be a buggy dcbX, icbi insn. */ +DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR */ mfspr r10, SPRN_M_TW /* Restore registers */ lwz r11, 0(r0) mtcr r11 @@ -588,6 +533,140 @@ DataTLBError: . = 0x2000 +/* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions + * by decoding the registers used by the dcbx instruction and adding them. + * DAR is set to the calculated address and r10 also holds the EA on exit. + */ + /* define if you don't want to use self modifying code */ +#define NO_SELF_MODIFYING_CODE +FixupDAR:/* Entry point for dcbx workaround. */ + /* fetch instruction from memory. */ + mfspr r10, SPRN_SRR0 + DO_8xx_CPU6(0x3780, r3) + mtspr SPRN_MD_EPN, r10 + mfspr r11, SPRN_M_TWB /* Get level 1 table entry address */ + cmplwi cr0, r11, 0x0800 + blt- 3f /* Branch if user space */ + lis r11, (swapper_pg_dir-PAGE_OFFSET)@h + ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l + rlwimi r11, r10, 32-20, 0xffc /* r11 = r11&~0xffc|(r10>>20)&0xffc */ +3: lwz r11, 0(r11) /* Get the level 1 entry */ + DO_8xx_CPU6(0x3b80, r3) + mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ + mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ + lwz r11, 0(r11) /* Get the pte */ + /* concat physical page address(r11) and page offset(r10) */ + rlwimi r11, r10, 0, 20, 31 + lwz r11,0(r11) +/* Check if it really is a dcbx instruction. */ +/* dcbt and dcbtst does not generate DTLB Misses/Errors, + * no need to include them here */ + srwi r10, r11, 26 /* check if major OP code is 31 */ + cmpwi cr0, r10, 31 + bne- 141f + rlwinm r10, r11, 0, 21, 30 + cmpwi cr0, r10, 2028 /* Is dcbz? */ + beq+ 142f + cmpwi cr0, r10, 940 /* Is dcbi? */ + beq+ 142f + cmpwi cr0, r10, 108 /* Is dcbst? */ + beq+ 144f /* Fix up store bit! */ + cmpwi cr0, r10, 172 /* Is dcbf? */ + beq+ 142f + cmpwi cr0, r10, 1964 /* Is icbi? */ + beq+ 142f +141: mfspr r10, SPRN_DAR /* r10 must hold DAR at exit */ + b DARFixed /* Nope, go back to normal TLB processing */ + +144: mfspr r10, SPRN_DSISR + rlwinm r10, r10,0,7,5 /* Clear store bit for buggy dcbst insn */ + mtspr SPRN_DSISR, r10 +142: /* continue, it was a dcbx, dcbi instruction. */ +#ifdef CONFIG_8xx_CPU6 + lwz r3, 8(r0) /* restore r3 from memory */ +#endif +#ifndef NO_SELF_MODIFYING_CODE + andis. r10,r11,0x1f /* test if reg RA is r0 */ + li r10,modified_instr@l + dcbtst r0,r10 /* touch for store */ + rlwinm r11,r11,0,0,20 /* Zero lower 10 bits */ + oris r11,r11,640 /* Transform instr. to a "add r10,RA,RB" */ + ori r11,r11,532 + stw r11,0(r10) /* store add/and instruction */ + dcbf 0,r10 /* flush new instr. to memory. */ + icbi 0,r10 /* invalidate instr. cache line */ + lwz r11, 4(r0) /* restore r11 from memory */ + mfspr r10, SPRN_M_TW /* restore r10 from M_TW */ + isync /* Wait until new instr is loaded from memory */ +modified_instr: + .space 4 /* this is where the add instr. is stored */ + bne+ 143f + subf r10,r0,r10 /* r10=r10-r0, only if reg RA is r0 */ +143: mtdar r10 /* store faulting EA in DAR */ + b DARFixed /* Go back to normal TLB handling */ +#else + mfctr r10 + mtdar r10 /* save ctr reg in DAR */ + rlwinm r10, r11, 24, 24, 28 /* offset into jump table for reg RB */ + addi r10, r10, 150f@l /* add start of table */ + mtctr r10 /* load ctr with jump address */ + xor r10, r10, r10 /* sum starts at zero */ + bctr /* jump into table */ +150: + add r10, r10, r0 ;b 151f + add r10, r10, r1 ;b 151f + add r10, r10, r2 ;b 151f + add r10, r10, r3 ;b 151f + add r10, r10, r4 ;b 151f + add r10, r10, r5 ;b 151f + add r10, r10, r6 ;b 151f + add r10, r10, r7 ;b 151f + add r10, r10, r8 ;b 151f + add r10, r10, r9 ;b 151f + mtctr r11 ;b 154f /* r10 needs special handling */ + mtctr r11 ;b 153f /* r11 needs special handling */ + add r10, r10, r12 ;b 151f + add r10, r10, r13 ;b 151f + add r10, r10, r14 ;b 151f + add r10, r10, r15 ;b 151f + add r10, r10, r16 ;b 151f + add r10, r10, r17 ;b 151f + add r10, r10, r18 ;b 151f + add r10, r10, r19 ;b 151f + add r10, r10, r20 ;b 151f + add r10, r10, r21 ;b 151f + add r10, r10, r22 ;b 151f + add r10, r10, r23 ;b 151f + add r10, r10, r24 ;b 151f + add r10, r10, r25 ;b 151f + add r10, r10, r26 ;b 151f + add r10, r10, r27 ;b 151f + add r10, r10, r28 ;b 151f + add r10, r10, r29 ;b 151f + add r10, r10, r30 ;b 151f + add r10, r10, r31 +151: + rlwinm. r11,r11,19,24,28 /* offset into jump table for reg RA */ + beq 152f /* if reg RA is zero, don't add it */ + addi r11, r11, 150b@l /* add start of table */ + mtctr r11 /* load ctr with jump address */ + rlwinm r11,r11,0,16,10 /* make sure we don't execute this more than once */ + bctr /* jump into table */ +152: + mfdar r11 + mtctr r11 /* restore ctr reg from DAR */ + mtdar r10 /* save fault EA to DAR */ + b DARFixed /* Go back to normal TLB handling */ + + /* special handling for r10,r11 since these are modified already */ +153: lwz r11, 4(r0) /* load r11 from memory */ + b 155f +154: mfspr r11, SPRN_M_TW /* load r10 from M_TW */ +155: add r10, r10, r11 /* add it */ + mfctr r11 /* restore r11 */ + b 151b +#endif + .globl giveup_fpu giveup_fpu: blr diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 975788ca05d203eb1b24712ce3a640790cbf715f..7f4bd7f3b6af36bb5c87127b5c4be3d1be44c43d 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S @@ -943,28 +943,6 @@ _GLOBAL(__setup_e500mc_ivors) sync blr -/* - * extern void loadcam_entry(unsigned int index) - * - * Load TLBCAM[index] entry in to the L2 CAM MMU - */ -_GLOBAL(loadcam_entry) - lis r4,TLBCAM@ha - addi r4,r4,TLBCAM@l - mulli r5,r3,TLBCAM_SIZE - add r3,r5,r4 - lwz r4,0(r3) - mtspr SPRN_MAS0,r4 - lwz r4,4(r3) - mtspr SPRN_MAS1,r4 - lwz r4,8(r3) - mtspr SPRN_MAS2,r4 - lwz r4,12(r3) - mtspr SPRN_MAS3,r4 - tlbwe - isync - blr - /* * extern void giveup_altivec(struct task_struct *prev) * diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c index 1882bf419fa6f294db6adf46e15d2a428493c414..8dc7547c23775ecbf4442243fea98c3b443d6121 100644 --- a/arch/powerpc/kernel/io.c +++ b/arch/powerpc/kernel/io.c @@ -161,7 +161,7 @@ void _memcpy_fromio(void *dest, const volatile void __iomem *src, dest++; n--; } - while(n > 4) { + while(n >= 4) { *((u32 *)dest) = *((volatile u32 *)vsrc); eieio(); vsrc += 4; @@ -190,7 +190,7 @@ void _memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n) vdest++; n--; } - while(n > 4) { + while(n >= 4) { *((volatile u32 *)vdest) = *((volatile u32 *)src); src += 4; vdest += 4; diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 02a334662cc02148bf6f1cb9ba85cf118d799059..f6dca4f4b2955beba5e9d73221f9952569b4b51e 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -87,7 +87,10 @@ extern int tau_interrupts(int); #endif /* CONFIG_PPC32 */ #ifdef CONFIG_PPC64 + +#ifndef CONFIG_SPARSE_IRQ EXPORT_SYMBOL(irq_desc); +#endif int distribute_irqs = 1; @@ -189,33 +192,7 @@ int show_interrupts(struct seq_file *p, void *v) for_each_online_cpu(j) seq_printf(p, "CPU%d ", j); seq_putc(p, '\n'); - } - - if (i < NR_IRQS) { - desc = get_irq_desc(i); - spin_lock_irqsave(&desc->lock, flags); - action = desc->action; - if (!action || !action->handler) - goto skip; - seq_printf(p, "%3d: ", i); -#ifdef CONFIG_SMP - for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); -#else - seq_printf(p, "%10u ", kstat_irqs(i)); -#endif /* CONFIG_SMP */ - if (desc->chip) - seq_printf(p, " %s ", desc->chip->typename); - else - seq_puts(p, " None "); - seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); - 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(&desc->lock, flags); - } else if (i == NR_IRQS) { + } else if (i == nr_irqs) { #if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT) if (tau_initialized){ seq_puts(p, "TAU: "); @@ -225,30 +202,68 @@ skip: } #endif /* CONFIG_PPC32 && CONFIG_TAU_INT*/ seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); + + return 0; } + + desc = irq_to_desc(i); + if (!desc) + return 0; + + spin_lock_irqsave(&desc->lock, flags); + + action = desc->action; + if (!action || !action->handler) + goto skip; + + seq_printf(p, "%3d: ", i); +#ifdef CONFIG_SMP + for_each_online_cpu(j) + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); +#else + seq_printf(p, "%10u ", kstat_irqs(i)); +#endif /* CONFIG_SMP */ + + if (desc->chip) + seq_printf(p, " %s ", desc->chip->name); + else + seq_puts(p, " None "); + + seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); + 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(&desc->lock, flags); + return 0; } #ifdef CONFIG_HOTPLUG_CPU void fixup_irqs(cpumask_t map) { + struct irq_desc *desc; unsigned int irq; static int warned; for_each_irq(irq) { cpumask_t mask; - if (irq_desc[irq].status & IRQ_PER_CPU) + desc = irq_to_desc(irq); + if (desc && desc->status & IRQ_PER_CPU) continue; - cpumask_and(&mask, irq_desc[irq].affinity, &map); + cpumask_and(&mask, desc->affinity, &map); if (any_online_cpu(mask) == NR_CPUS) { printk("Breaking affinity for irq %i\n", irq); mask = map; } - if (irq_desc[irq].chip->set_affinity) - irq_desc[irq].chip->set_affinity(irq, &mask); - else if (irq_desc[irq].action && !(warned++)) + if (desc->chip->set_affinity) + desc->chip->set_affinity(irq, &mask); + else if (desc->action && !(warned++)) printk("Cannot set affinity for irq %i\n", irq); } @@ -275,7 +290,7 @@ static inline void handle_one_irq(unsigned int irq) return; } - desc = irq_desc + irq; + desc = irq_to_desc(irq); saved_sp_limit = current->thread.ksp_limit; irqtp->task = curtp->task; @@ -541,7 +556,7 @@ struct irq_host *irq_alloc_host(struct device_node *of_node, smp_wmb(); /* Clear norequest flags */ - get_irq_desc(i)->status &= ~IRQ_NOREQUEST; + irq_to_desc(i)->status &= ~IRQ_NOREQUEST; /* Legacy flags are left to default at this point, * one can then use irq_create_mapping() to @@ -607,8 +622,16 @@ void irq_set_virq_count(unsigned int count) static int irq_setup_virq(struct irq_host *host, unsigned int virq, irq_hw_number_t hwirq) { + struct irq_desc *desc; + + desc = irq_to_desc_alloc_node(virq, 0); + if (!desc) { + pr_debug("irq: -> allocating desc failed\n"); + goto error; + } + /* Clear IRQ_NOREQUEST flag */ - get_irq_desc(virq)->status &= ~IRQ_NOREQUEST; + desc->status &= ~IRQ_NOREQUEST; /* map it */ smp_wmb(); @@ -617,11 +640,14 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq, if (host->ops->map(host, virq, hwirq)) { pr_debug("irq: -> mapping failed, freeing\n"); - irq_free_virt(virq, 1); - return -1; + goto error; } return 0; + +error: + irq_free_virt(virq, 1); + return -1; } unsigned int irq_create_direct_mapping(struct irq_host *host) @@ -705,7 +731,7 @@ unsigned int irq_create_mapping(struct irq_host *host, EXPORT_SYMBOL_GPL(irq_create_mapping); unsigned int irq_create_of_mapping(struct device_node *controller, - u32 *intspec, unsigned int intsize) + const u32 *intspec, unsigned int intsize) { struct irq_host *host; irq_hw_number_t hwirq; @@ -738,7 +764,7 @@ unsigned int irq_create_of_mapping(struct device_node *controller, /* Set type if specified and different than the current one */ if (type != IRQ_TYPE_NONE && - type != (get_irq_desc(virq)->status & IRQF_TRIGGER_MASK)) + type != (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK)) set_irq_type(virq, type); return virq; } @@ -810,7 +836,7 @@ void irq_dispose_mapping(unsigned int virq) irq_map[virq].hwirq = host->inval_irq; /* Set some flags */ - get_irq_desc(virq)->status |= IRQ_NOREQUEST; + irq_to_desc(virq)->status |= IRQ_NOREQUEST; /* Free it */ irq_free_virt(virq, 1); @@ -1002,12 +1028,24 @@ void irq_free_virt(unsigned int virq, unsigned int count) spin_unlock_irqrestore(&irq_big_lock, flags); } -void irq_early_init(void) +int arch_early_irq_init(void) { - unsigned int i; + struct irq_desc *desc; + int i; + + for (i = 0; i < NR_IRQS; i++) { + desc = irq_to_desc(i); + if (desc) + desc->status |= IRQ_NOREQUEST; + } - for (i = 0; i < NR_IRQS; i++) - get_irq_desc(i)->status |= IRQ_NOREQUEST; + return 0; +} + +int arch_init_chip_data(struct irq_desc *desc, int node) +{ + desc->status |= IRQ_NOREQUEST; + return 0; } /* We need to create the radix trees late */ @@ -1069,16 +1107,19 @@ static int virq_debug_show(struct seq_file *m, void *private) seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq", "chip name", "host name"); - for (i = 1; i < NR_IRQS; i++) { - desc = get_irq_desc(i); + for (i = 1; i < nr_irqs; i++) { + desc = irq_to_desc(i); + if (!desc) + continue; + spin_lock_irqsave(&desc->lock, flags); if (desc->action && desc->action->handler) { seq_printf(m, "%5d ", i); seq_printf(m, "0x%05lx ", virq_to_hw(i)); - if (desc->chip && desc->chip->typename) - p = desc->chip->typename; + if (desc->chip && desc->chip->name) + p = desc->chip->name; else p = none; seq_printf(m, "%-15s ", p); diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index ed0ac4e4b8d8c82639625d67c8619d495bd9c9d2..79a00bb9c64ca86c77d1af2b8889683d710e434d 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c @@ -781,9 +781,9 @@ static int __init lparcfg_init(void) !firmware_has_feature(FW_FEATURE_ISERIES)) mode |= S_IWUSR; - ent = proc_create("ppc64/lparcfg", mode, NULL, &lparcfg_fops); + ent = proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_fops); if (!ent) { - printk(KERN_ERR "Failed to create ppc64/lparcfg\n"); + printk(KERN_ERR "Failed to create powerpc/lparcfg\n"); return -EIO; } diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index da9c0c4c10f3be383810f74ef01f55f5eced50b2..8649f536f8dfad573b9a76ce6e80698d186c2e57 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -502,15 +502,7 @@ _GLOBAL(clear_pages) li r0,PAGE_SIZE/L1_CACHE_BYTES slw r0,r0,r4 mtctr r0 -#ifdef CONFIG_8xx - li r4, 0 -1: stw r4, 0(r3) - stw r4, 4(r3) - stw r4, 8(r3) - stw r4, 12(r3) -#else 1: dcbz 0,r3 -#endif addi r3,r3,L1_CACHE_BYTES bdnz 1b blr @@ -535,15 +527,6 @@ _GLOBAL(copy_page) addi r3,r3,-4 addi r4,r4,-4 -#ifdef CONFIG_8xx - /* don't use prefetch on 8xx */ - li r0,4096/L1_CACHE_BYTES - mtctr r0 -1: COPY_16_BYTES - bdnz 1b - blr - -#else /* not 8xx, we can prefetch */ li r5,4 #if MAX_COPY_PREFETCH > 1 @@ -584,7 +567,6 @@ _GLOBAL(copy_page) li r0,MAX_COPY_PREFETCH li r11,4 b 2b -#endif /* CONFIG_8xx */ /* * void atomic_clear_mask(atomic_t mask, atomic_t *addr) diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 0ed31f2204826e2fa68315bd5bfe7be3cf3b10ba..ad461e735aec027b17e5004f04421228a1410ed9 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -139,8 +139,8 @@ out: } -static int dev_nvram_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long dev_nvram_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { switch(cmd) { #ifdef CONFIG_PPC_PMAC @@ -169,11 +169,11 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file, } const struct file_operations nvram_fops = { - .owner = THIS_MODULE, - .llseek = dev_nvram_llseek, - .read = dev_nvram_read, - .write = dev_nvram_write, - .ioctl = dev_nvram_ioctl, + .owner = THIS_MODULE, + .llseek = dev_nvram_llseek, + .read = dev_nvram_read, + .write = dev_nvram_write, + .unlocked_ioctl = dev_nvram_ioctl, }; static struct miscdevice nvram_dev = { @@ -184,7 +184,7 @@ static struct miscdevice nvram_dev = { #ifdef DEBUG_NVRAM -static void nvram_print_partitions(char * label) +static void __init nvram_print_partitions(char * label) { struct list_head * p; struct nvram_partition * tmp_part; @@ -202,7 +202,7 @@ static void nvram_print_partitions(char * label) #endif -static int nvram_write_header(struct nvram_partition * part) +static int __init nvram_write_header(struct nvram_partition * part) { loff_t tmp_index; int rc; @@ -214,7 +214,7 @@ static int nvram_write_header(struct nvram_partition * part) } -static unsigned char nvram_checksum(struct nvram_header *p) +static unsigned char __init nvram_checksum(struct nvram_header *p) { unsigned int c_sum, c_sum2; unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */ @@ -228,32 +228,7 @@ static unsigned char nvram_checksum(struct nvram_header *p) return c_sum; } - -/* - * Find an nvram partition, sig can be 0 for any - * partition or name can be NULL for any name, else - * tries to match both - */ -struct nvram_partition *nvram_find_partition(int sig, const char *name) -{ - struct nvram_partition * part; - struct list_head * p; - - list_for_each(p, &nvram_part->partition) { - part = list_entry(p, struct nvram_partition, partition); - - if (sig && part->header.signature != sig) - continue; - if (name && 0 != strncmp(name, part->header.name, 12)) - continue; - return part; - } - return NULL; -} -EXPORT_SYMBOL(nvram_find_partition); - - -static int nvram_remove_os_partition(void) +static int __init nvram_remove_os_partition(void) { struct list_head *i; struct list_head *j; @@ -319,7 +294,7 @@ static int nvram_remove_os_partition(void) * Will create a partition starting at the first free * space found if space has enough room. */ -static int nvram_create_os_partition(void) +static int __init nvram_create_os_partition(void) { struct nvram_partition *part; struct nvram_partition *new_part; @@ -422,7 +397,7 @@ static int nvram_create_os_partition(void) * 5.) If the max chunk cannot be allocated then try finding a chunk * that will satisfy the minum needed (NVRAM_MIN_REQ). */ -static int nvram_setup_partition(void) +static int __init nvram_setup_partition(void) { struct list_head * p; struct nvram_partition * part; @@ -480,7 +455,7 @@ static int nvram_setup_partition(void) } -static int nvram_scan_partitions(void) +static int __init nvram_scan_partitions(void) { loff_t cur_index = 0; struct nvram_header phead; @@ -706,6 +681,9 @@ int nvram_clear_error_log(void) int clear_word = ERR_FLAG_ALREADY_LOGGED; int rc; + if (nvram_error_log_index == -1) + return -1; + tmp_index = nvram_error_log_index; rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index); diff --git a/arch/powerpc/kernel/perf_callchain.c b/arch/powerpc/kernel/perf_callchain.c index 0a03cf70d24793a9d0295acd4dfaf8abf0b0dd59..a3c11cac3d7154d1381d77a83ec513e5c6601c11 100644 --- a/arch/powerpc/kernel/perf_callchain.c +++ b/arch/powerpc/kernel/perf_callchain.c @@ -119,13 +119,6 @@ static void perf_callchain_kernel(struct pt_regs *regs, } #ifdef CONFIG_PPC64 - -#ifdef CONFIG_HUGETLB_PAGE -#define is_huge_psize(pagesize) (HPAGE_SHIFT && mmu_huge_psizes[pagesize]) -#else -#define is_huge_psize(pagesize) 0 -#endif - /* * On 64-bit we don't want to invoke hash_page on user addresses from * interrupt context, so if the access faults, we read the page tables @@ -135,7 +128,7 @@ static int read_user_stack_slow(void __user *ptr, void *ret, int nb) { pgd_t *pgdir; pte_t *ptep, pte; - int pagesize; + unsigned shift; unsigned long addr = (unsigned long) ptr; unsigned long offset; unsigned long pfn; @@ -145,17 +138,14 @@ static int read_user_stack_slow(void __user *ptr, void *ret, int nb) if (!pgdir) return -EFAULT; - pagesize = get_slice_psize(current->mm, addr); + ptep = find_linux_pte_or_hugepte(pgdir, addr, &shift); + if (!shift) + shift = PAGE_SHIFT; /* align address to page boundary */ - offset = addr & ((1ul << mmu_psize_defs[pagesize].shift) - 1); + offset = addr & ((1UL << shift) - 1); addr -= offset; - if (is_huge_psize(pagesize)) - ptep = huge_pte_offset(current->mm, addr); - else - ptep = find_linux_pte(pgdir, addr); - if (ptep == NULL) return -EFAULT; pte = *ptep; @@ -497,11 +487,11 @@ static void perf_callchain_user_32(struct pt_regs *regs, * Since we can't get PMU interrupts inside a PMU interrupt handler, * we don't need separate irq and nmi entries here. */ -static DEFINE_PER_CPU(struct perf_callchain_entry, callchain); +static DEFINE_PER_CPU(struct perf_callchain_entry, cpu_perf_callchain); struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) { - struct perf_callchain_entry *entry = &__get_cpu_var(callchain); + struct perf_callchain_entry *entry = &__get_cpu_var(cpu_perf_callchain); entry->nr = 0; diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index c8b27bb4dbdec45eba0de471c106728bb892fdee..425451453e96d9cd7e14c6f20fdc6c852ec2f235 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -96,8 +96,6 @@ EXPORT_SYMBOL(copy_4K_page); EXPORT_SYMBOL(isa_io_base); EXPORT_SYMBOL(isa_mem_base); EXPORT_SYMBOL(pci_dram_offset); -EXPORT_SYMBOL(pci_alloc_consistent); -EXPORT_SYMBOL(pci_free_consistent); #endif /* CONFIG_PCI */ EXPORT_SYMBOL(start_thread); @@ -162,7 +160,6 @@ EXPORT_SYMBOL(screen_info); #ifdef CONFIG_PPC32 EXPORT_SYMBOL(timer_interrupt); -EXPORT_SYMBOL(irq_desc); EXPORT_SYMBOL(tb_ticks_per_jiffy); EXPORT_SYMBOL(cacheable_memcpy); EXPORT_SYMBOL(cacheable_memzero); diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_powerpc.c similarity index 87% rename from arch/powerpc/kernel/proc_ppc64.c rename to arch/powerpc/kernel/proc_powerpc.c index c647ddef40dc4dcf12865f834869101fa9bfb6da..1ed3b8d7981e4c4968c3ce6530b978883e8e030d 100644 --- a/arch/powerpc/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_powerpc.c @@ -28,55 +28,7 @@ #include #include -static loff_t page_map_seek( struct file *file, loff_t off, int whence); -static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, - loff_t *ppos); -static int page_map_mmap( struct file *file, struct vm_area_struct *vma ); - -static const struct file_operations page_map_fops = { - .llseek = page_map_seek, - .read = page_map_read, - .mmap = page_map_mmap -}; - -/* - * Create the ppc64 and ppc64/rtas directories early. This allows us to - * assume that they have been previously created in drivers. - */ -static int __init proc_ppc64_create(void) -{ - struct proc_dir_entry *root; - - root = proc_mkdir("ppc64", NULL); - if (!root) - return 1; - - if (!of_find_node_by_path("/rtas")) - return 0; - - if (!proc_mkdir("rtas", root)) - return 1; - - if (!proc_symlink("rtas", NULL, "ppc64/rtas")) - return 1; - - return 0; -} -core_initcall(proc_ppc64_create); - -static int __init proc_ppc64_init(void) -{ - struct proc_dir_entry *pde; - - pde = proc_create_data("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL, - &page_map_fops, vdso_data); - if (!pde) - return 1; - pde->size = PAGE_SIZE; - - return 0; -} -__initcall(proc_ppc64_init); +#ifdef CONFIG_PPC64 static loff_t page_map_seek( struct file *file, loff_t off, int whence) { @@ -120,3 +72,55 @@ static int page_map_mmap( struct file *file, struct vm_area_struct *vma ) return 0; } +static const struct file_operations page_map_fops = { + .llseek = page_map_seek, + .read = page_map_read, + .mmap = page_map_mmap +}; + + +static int __init proc_ppc64_init(void) +{ + struct proc_dir_entry *pde; + + pde = proc_create_data("powerpc/systemcfg", S_IFREG|S_IRUGO, NULL, + &page_map_fops, vdso_data); + if (!pde) + return 1; + pde->size = PAGE_SIZE; + + return 0; +} +__initcall(proc_ppc64_init); + +#endif /* CONFIG_PPC64 */ + +/* + * Create the ppc64 and ppc64/rtas directories early. This allows us to + * assume that they have been previously created in drivers. + */ +static int __init proc_ppc64_create(void) +{ + struct proc_dir_entry *root; + + root = proc_mkdir("powerpc", NULL); + if (!root) + return 1; + +#ifdef CONFIG_PPC64 + if (!proc_symlink("ppc64", NULL, "powerpc")) + pr_err("Failed to create link /proc/ppc64 -> /proc/powerpc\n"); +#endif + + if (!of_find_node_by_path("/rtas")) + return 0; + + if (!proc_mkdir("rtas", root)) + return 1; + + if (!proc_symlink("rtas", NULL, "powerpc/rtas")) + return 1; + + return 0; +} +core_initcall(proc_ppc64_create); diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 13011a96a9779b274e77447dd5b72dae4e56142a..a85117d5c9a4c3576ac60d0b774df2c43ca4f9fc 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -6,7 +6,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * /proc/ppc64/rtas/firmware_flash interface + * /proc/powerpc/rtas/firmware_flash interface * * This file implements a firmware_flash interface to pump a firmware * image into the kernel. At reboot time rtas_restart() will see the @@ -740,7 +740,7 @@ static int __init rtas_flash_init(void) return 1; } - firmware_flash_pde = create_flash_pde("ppc64/rtas/" + firmware_flash_pde = create_flash_pde("powerpc/rtas/" FIRMWARE_FLASH_NAME, &rtas_flash_operations); if (firmware_flash_pde == NULL) { @@ -754,7 +754,7 @@ static int __init rtas_flash_init(void) if (rc != 0) goto cleanup; - firmware_update_pde = create_flash_pde("ppc64/rtas/" + firmware_update_pde = create_flash_pde("powerpc/rtas/" FIRMWARE_UPDATE_NAME, &rtas_flash_operations); if (firmware_update_pde == NULL) { @@ -768,7 +768,7 @@ static int __init rtas_flash_init(void) if (rc != 0) goto cleanup; - validate_pde = create_flash_pde("ppc64/rtas/" VALIDATE_FLASH_NAME, + validate_pde = create_flash_pde("powerpc/rtas/" VALIDATE_FLASH_NAME, &validate_flash_operations); if (validate_pde == NULL) { rc = -ENOMEM; @@ -781,7 +781,7 @@ static int __init rtas_flash_init(void) if (rc != 0) goto cleanup; - manage_pde = create_flash_pde("ppc64/rtas/" MANAGE_FLASH_NAME, + manage_pde = create_flash_pde("powerpc/rtas/" MANAGE_FLASH_NAME, &manage_flash_operations); if (manage_pde == NULL) { rc = -ENOMEM; diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/kernel/rtasd.c similarity index 95% rename from arch/powerpc/platforms/pseries/rtasd.c rename to arch/powerpc/kernel/rtasd.c index b3cbac85592406011015a6c68a7dbd99663f151e..2e4832ab210802015ba04fcf31dab5c7dc8cd931 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c @@ -39,6 +39,7 @@ static unsigned long rtas_log_start; static unsigned long rtas_log_size; static int surveillance_timeout = -1; + static unsigned int rtas_error_log_max; static unsigned int rtas_error_log_buffer_max; @@ -213,9 +214,11 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) return; } +#ifdef CONFIG_PPC64 /* Write error to NVRAM */ if (logging_enabled && !(err_type & ERR_FLAG_BOOT)) nvram_write_error_log(buf, len, err_type, error_log_cnt); +#endif /* CONFIG_PPC64 */ /* * rtas errors can occur during boot, and we do want to capture @@ -264,7 +267,6 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) } - static int rtas_log_open(struct inode * inode, struct file * file) { return 0; @@ -300,6 +302,7 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf, return -ENOMEM; spin_lock_irqsave(&rtasd_log_lock, s); + /* if it's 0, then we know we got the last one (the one in NVRAM) */ while (rtas_log_size == 0) { if (file->f_flags & O_NONBLOCK) { @@ -313,7 +316,9 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf, error = -ENODATA; goto out; } +#ifdef CONFIG_PPC64 nvram_clear_error_log(); +#endif /* CONFIG_PPC64 */ spin_unlock_irqrestore(&rtasd_log_lock, s); error = wait_event_interruptible(rtas_log_wait, rtas_log_size); @@ -427,14 +432,11 @@ static void rtas_event_scan(struct work_struct *w) put_online_cpus(); } -static void start_event_scan(void) +#ifdef CONFIG_PPC64 +static void retreive_nvram_error_log(void) { - unsigned int err_type; - int rc; - - printk(KERN_DEBUG "RTAS daemon started\n"); - pr_debug("rtasd: will sleep for %d milliseconds\n", - (30000 / rtas_event_scan_rate)); + unsigned int err_type ; + int rc ; /* See if we have any error stored in NVRAM */ memset(logdata, 0, rtas_error_log_max); @@ -442,12 +444,26 @@ static void start_event_scan(void) &err_type, &error_log_cnt); /* We can use rtas_log_buf now */ logging_enabled = 1; - if (!rc) { if (err_type != ERR_FLAG_ALREADY_LOGGED) { pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0); } } +} +#else /* CONFIG_PPC64 */ +static void retreive_nvram_error_log(void) +{ +} +#endif /* CONFIG_PPC64 */ + +static void start_event_scan(void) +{ + printk(KERN_DEBUG "RTAS daemon started\n"); + pr_debug("rtasd: will sleep for %d milliseconds\n", + (30000 / rtas_event_scan_rate)); + + /* Retreive errors from nvram if any */ + retreive_nvram_error_log(); schedule_delayed_work_on(first_cpu(cpu_online_map), &event_scan_work, event_scan_delay); @@ -457,13 +473,13 @@ static int __init rtas_init(void) { struct proc_dir_entry *entry; - if (!machine_is(pseries)) + if (!machine_is(pseries) && !machine_is(chrp)) return 0; /* No RTAS */ event_scan = rtas_token("event-scan"); if (event_scan == RTAS_UNKNOWN_SERVICE) { - printk(KERN_DEBUG "rtasd: no event-scan on system\n"); + printk(KERN_INFO "rtasd: No event-scan on system\n"); return -ENODEV; } @@ -483,7 +499,7 @@ static int __init rtas_init(void) return -ENOMEM; } - entry = proc_create("ppc64/rtas/error_log", S_IRUSR, NULL, + entry = proc_create("powerpc/rtas/error_log", S_IRUSR, NULL, &proc_rtas_log_operations); if (!entry) printk(KERN_ERR "Failed to create error_log proc entry\n"); @@ -492,11 +508,16 @@ static int __init rtas_init(void) return 0; } +__initcall(rtas_init); static int __init surveillance_setup(char *str) { int i; + /* We only do surveillance on pseries */ + if (!machine_is(pseries)) + return 0; + if (get_option(&str,&i)) { if (i >= 0 && i <= 255) surveillance_timeout = i; @@ -504,6 +525,7 @@ static int __init surveillance_setup(char *str) return 1; } +__setup("surveillance=", surveillance_setup); static int __init rtasmsgs_setup(char *str) { @@ -514,6 +536,4 @@ static int __init rtasmsgs_setup(char *str) return 1; } -__initcall(rtas_init); -__setup("surveillance=", surveillance_setup); __setup("rtasmsgs=", rtasmsgs_setup); diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 845c72ab7357884c580a1c6f3f3217ed4987ee75..03dd6a248198c3247af741db5f154452b2c84f2c 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -157,7 +157,7 @@ extern u32 cpu_temp_both(unsigned long cpu); #endif /* CONFIG_TAU */ #ifdef CONFIG_SMP -DEFINE_PER_CPU(unsigned int, pvr); +DEFINE_PER_CPU(unsigned int, cpu_pvr); #endif static int show_cpuinfo(struct seq_file *m, void *v) @@ -209,7 +209,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) } #ifdef CONFIG_SMP - pvr = per_cpu(pvr, cpu_id); + pvr = per_cpu(cpu_pvr, cpu_id); #else pvr = mfspr(SPRN_PVR); #endif diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index df2c9e932b3714b8ef060ac204757157429a3029..6568406b2a3081c0e5c4c51b75129880fc241d73 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -356,11 +356,6 @@ void __init setup_system(void) */ initialize_cache_info(); - /* - * Initialize irq remapping subsystem - */ - irq_early_init(); - #ifdef CONFIG_PPC_RTAS /* * Initialize RTAS if available diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 9b86a74d281504cf255ae9a2f2b3e7b5009076fb..a521fb8a40ee2fcb206397cf490aab9550cf9c96 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -218,6 +218,9 @@ void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *)) static void stop_this_cpu(void *dummy) { + /* Remove this CPU */ + set_cpu_online(smp_processor_id(), false); + local_irq_disable(); while (1) ; @@ -232,7 +235,7 @@ struct thread_info *current_set[NR_CPUS]; static void __devinit smp_store_cpu_info(int id) { - per_cpu(pvr, id) = mfspr(SPRN_PVR); + per_cpu(cpu_pvr, id) = mfspr(SPRN_PVR); } static void __init smp_create_idle(unsigned int cpu) diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c index c04832c4a02e3965834a48adbaad9450e76ef378..3370e62e43d4eabe6e20d6ce5c9c2aa9522fc5cd 100644 --- a/arch/powerpc/kernel/syscalls.c +++ b/arch/powerpc/kernel/syscalls.c @@ -140,7 +140,6 @@ static inline unsigned long do_mmap2(unsigned long addr, size_t len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off, int shift) { - struct file * file = NULL; unsigned long ret = -EINVAL; if (!arch_validate_prot(prot)) @@ -151,20 +150,8 @@ static inline unsigned long do_mmap2(unsigned long addr, size_t len, goto out; off >>= shift; } - - ret = -EBADF; - if (!(flags & MAP_ANONYMOUS)) { - if (!(file = fget(fd))) - goto out; - } - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); - ret = do_mmap_pgoff(file, addr, len, prot, flags, off); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); + ret = sys_mmap_pgoff(addr, len, prot, flags, fd, off); out: return ret; } diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 956ab33fd73fb98096c16fb760dce8695aa6f873..e235e52dc4fed1f217164d70f7f9dc8555b81fd8 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -461,6 +461,25 @@ static void unregister_cpu_online(unsigned int cpu) cacheinfo_cpu_offline(cpu); } + +#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE +ssize_t arch_cpu_probe(const char *buf, size_t count) +{ + if (ppc_md.cpu_probe) + return ppc_md.cpu_probe(buf, count); + + return -EINVAL; +} + +ssize_t arch_cpu_release(const char *buf, size_t count) +{ + if (ppc_md.cpu_release) + return ppc_md.cpu_release(buf, count); + + return -EINVAL; +} +#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ + #endif /* CONFIG_HOTPLUG_CPU */ static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 674800b242d6167262178006c7f50afbe65c26ca..9ba2cc88591d66f276eaf81e5f3c31948312731d 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -269,6 +269,7 @@ void account_system_vtime(struct task_struct *tsk) per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled; local_irq_restore(flags); } +EXPORT_SYMBOL_GPL(account_system_vtime); /* * Transfer the user and system times accumulated in the paca diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 9d1f9354d6cafcf12fd7719d599615e31e55b2d9..804f0f30f227f692d949d49117b3c35da908fc6f 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -198,28 +198,6 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) info.si_code = code; info.si_addr = (void __user *) addr; force_sig_info(signr, &info, current); - - /* - * Init gets no signals that it doesn't have a handler for. - * That's all very well, but if it has caused a synchronous - * exception and we ignore the resulting signal, it will just - * generate the same exception over and over again and we get - * nowhere. Better to kill it and let the kernel panic. - */ - if (is_global_init(current)) { - __sighandler_t handler; - - spin_lock_irq(¤t->sighand->siglock); - handler = current->sighand->action[signr-1].sa.sa_handler; - spin_unlock_irq(¤t->sighand->siglock); - if (handler == SIG_DFL) { - /* init has generated a synchronous exception - and it doesn't have a handler for the signal */ - printk(KERN_CRIT "init has generated signal %d " - "but has no handler for it\n", signr); - do_exit(signr); - } - } } #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index 67b6916f0e942283553a2a5d3b5b82b6899fff19..fe460482fa68dff8d35d36e94eec996b2644e679 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S @@ -58,7 +58,7 @@ _GLOBAL(load_up_altivec) * all 1's */ mfspr r4,SPRN_VRSAVE - cmpdi 0,r4,0 + cmpwi 0,r4,0 bne+ 1f li r4,-1 mtspr SPRN_VRSAVE,r4 diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig index c2992684661389f9686a73b5fbf32e659a2886f9..07703f72330e1f0f468be6a0ce75d4b19a12daa8 100644 --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig @@ -21,6 +21,23 @@ config KVM select PREEMPT_NOTIFIERS select ANON_INODES +config KVM_BOOK3S_64_HANDLER + bool + +config KVM_BOOK3S_64 + tristate "KVM support for PowerPC book3s_64 processors" + depends on EXPERIMENTAL && PPC64 + select KVM + select KVM_BOOK3S_64_HANDLER + ---help--- + Support running unmodified book3s_64 and book3s_32 guest kernels + in virtual machines on book3s_64 host processors. + + This module provides access to the hardware capabilities through + a character device node named /dev/kvm. + + If unsure, say N. + config KVM_440 bool "KVM support for PowerPC 440 processors" depends on EXPERIMENTAL && 44x diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index 37655fe19f2f7431c946d2e6405d3d96aaf10fa1..56484d6523777582f3a44e84850ead22cb237d52 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile @@ -12,26 +12,45 @@ CFLAGS_44x_tlb.o := -I. CFLAGS_e500_tlb.o := -I. CFLAGS_emulate.o := -I. -kvm-objs := $(common-objs-y) powerpc.o emulate.o +common-objs-y += powerpc.o emulate.o obj-$(CONFIG_KVM_EXIT_TIMING) += timing.o -obj-$(CONFIG_KVM) += kvm.o +obj-$(CONFIG_KVM_BOOK3S_64_HANDLER) += book3s_64_exports.o AFLAGS_booke_interrupts.o := -I$(obj) kvm-440-objs := \ + $(common-objs-y) \ booke.o \ booke_emulate.o \ booke_interrupts.o \ 44x.o \ 44x_tlb.o \ 44x_emulate.o -obj-$(CONFIG_KVM_440) += kvm-440.o +kvm-objs-$(CONFIG_KVM_440) := $(kvm-440-objs) kvm-e500-objs := \ + $(common-objs-y) \ booke.o \ booke_emulate.o \ booke_interrupts.o \ e500.o \ e500_tlb.o \ e500_emulate.o -obj-$(CONFIG_KVM_E500) += kvm-e500.o +kvm-objs-$(CONFIG_KVM_E500) := $(kvm-e500-objs) + +kvm-book3s_64-objs := \ + $(common-objs-y) \ + book3s.o \ + book3s_64_emulate.o \ + book3s_64_interrupts.o \ + book3s_64_mmu_host.o \ + book3s_64_mmu.o \ + book3s_32_mmu.o +kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-objs) + +kvm-objs := $(kvm-objs-m) $(kvm-objs-y) + +obj-$(CONFIG_KVM_440) += kvm.o +obj-$(CONFIG_KVM_E500) += kvm.o +obj-$(CONFIG_KVM_BOOK3S_64) += kvm.o + diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c new file mode 100644 index 0000000000000000000000000000000000000000..3e294bd9b8c6d998ef262d013de4e02a3468fbca --- /dev/null +++ b/arch/powerpc/kvm/book3s.c @@ -0,0 +1,974 @@ +/* + * Copyright (C) 2009. SUSE Linux Products GmbH. All rights reserved. + * + * Authors: + * Alexander Graf + * Kevin Wolf + * + * Description: + * This file is derived from arch/powerpc/kvm/44x.c, + * by Hollis Blanchard . + * + * 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 + +#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU + +/* #define EXIT_DEBUG */ +/* #define EXIT_DEBUG_SIMPLE */ + +/* Without AGGRESSIVE_DEC we only fire off a DEC interrupt when DEC turns 0. + * When set, we retrigger a DEC interrupt after that if DEC <= 0. + * PPC32 Linux runs faster without AGGRESSIVE_DEC, PPC64 Linux requires it. */ + +/* #define AGGRESSIVE_DEC */ + +struct kvm_stats_debugfs_item debugfs_entries[] = { + { "exits", VCPU_STAT(sum_exits) }, + { "mmio", VCPU_STAT(mmio_exits) }, + { "sig", VCPU_STAT(signal_exits) }, + { "sysc", VCPU_STAT(syscall_exits) }, + { "inst_emu", VCPU_STAT(emulated_inst_exits) }, + { "dec", VCPU_STAT(dec_exits) }, + { "ext_intr", VCPU_STAT(ext_intr_exits) }, + { "queue_intr", VCPU_STAT(queue_intr) }, + { "halt_wakeup", VCPU_STAT(halt_wakeup) }, + { "pf_storage", VCPU_STAT(pf_storage) }, + { "sp_storage", VCPU_STAT(sp_storage) }, + { "pf_instruc", VCPU_STAT(pf_instruc) }, + { "sp_instruc", VCPU_STAT(sp_instruc) }, + { "ld", VCPU_STAT(ld) }, + { "ld_slow", VCPU_STAT(ld_slow) }, + { "st", VCPU_STAT(st) }, + { "st_slow", VCPU_STAT(st_slow) }, + { NULL } +}; + +void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu) +{ +} + +void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu) +{ +} + +void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) +{ + memcpy(get_paca()->kvm_slb, to_book3s(vcpu)->slb_shadow, sizeof(get_paca()->kvm_slb)); + get_paca()->kvm_slb_max = to_book3s(vcpu)->slb_shadow_max; +} + +void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) +{ + memcpy(to_book3s(vcpu)->slb_shadow, get_paca()->kvm_slb, sizeof(get_paca()->kvm_slb)); + to_book3s(vcpu)->slb_shadow_max = get_paca()->kvm_slb_max; +} + +#if defined(AGGRESSIVE_DEC) || defined(EXIT_DEBUG) +static u32 kvmppc_get_dec(struct kvm_vcpu *vcpu) +{ + u64 jd = mftb() - vcpu->arch.dec_jiffies; + return vcpu->arch.dec - jd; +} +#endif + +void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr) +{ + ulong old_msr = vcpu->arch.msr; + +#ifdef EXIT_DEBUG + printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr); +#endif + msr &= to_book3s(vcpu)->msr_mask; + vcpu->arch.msr = msr; + vcpu->arch.shadow_msr = msr | MSR_USER32; + vcpu->arch.shadow_msr &= ( MSR_VEC | MSR_VSX | MSR_FP | MSR_FE0 | + MSR_USER64 | MSR_SE | MSR_BE | MSR_DE | + MSR_FE1); + + if (msr & (MSR_WE|MSR_POW)) { + if (!vcpu->arch.pending_exceptions) { + kvm_vcpu_block(vcpu); + vcpu->stat.halt_wakeup++; + } + } + + if (((vcpu->arch.msr & (MSR_IR|MSR_DR)) != (old_msr & (MSR_IR|MSR_DR))) || + (vcpu->arch.msr & MSR_PR) != (old_msr & MSR_PR)) { + kvmppc_mmu_flush_segments(vcpu); + kvmppc_mmu_map_segment(vcpu, vcpu->arch.pc); + } +} + +void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags) +{ + vcpu->arch.srr0 = vcpu->arch.pc; + vcpu->arch.srr1 = vcpu->arch.msr | flags; + vcpu->arch.pc = to_book3s(vcpu)->hior + vec; + vcpu->arch.mmu.reset_msr(vcpu); +} + +void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec) +{ + unsigned int prio; + + vcpu->stat.queue_intr++; + switch (vec) { + case 0x100: prio = BOOK3S_IRQPRIO_SYSTEM_RESET; break; + case 0x200: prio = BOOK3S_IRQPRIO_MACHINE_CHECK; break; + case 0x300: prio = BOOK3S_IRQPRIO_DATA_STORAGE; break; + case 0x380: prio = BOOK3S_IRQPRIO_DATA_SEGMENT; break; + case 0x400: prio = BOOK3S_IRQPRIO_INST_STORAGE; break; + case 0x480: prio = BOOK3S_IRQPRIO_INST_SEGMENT; break; + case 0x500: prio = BOOK3S_IRQPRIO_EXTERNAL; break; + case 0x600: prio = BOOK3S_IRQPRIO_ALIGNMENT; break; + case 0x700: prio = BOOK3S_IRQPRIO_PROGRAM; break; + case 0x800: prio = BOOK3S_IRQPRIO_FP_UNAVAIL; break; + case 0x900: prio = BOOK3S_IRQPRIO_DECREMENTER; break; + case 0xc00: prio = BOOK3S_IRQPRIO_SYSCALL; break; + case 0xd00: prio = BOOK3S_IRQPRIO_DEBUG; break; + case 0xf20: prio = BOOK3S_IRQPRIO_ALTIVEC; break; + case 0xf40: prio = BOOK3S_IRQPRIO_VSX; break; + default: prio = BOOK3S_IRQPRIO_MAX; break; + } + + set_bit(prio, &vcpu->arch.pending_exceptions); +#ifdef EXIT_DEBUG + printk(KERN_INFO "Queueing interrupt %x\n", vec); +#endif +} + + +void kvmppc_core_queue_program(struct kvm_vcpu *vcpu) +{ + kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_PROGRAM); +} + +void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu) +{ + kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DECREMENTER); +} + +int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu) +{ + return test_bit(BOOK3S_INTERRUPT_DECREMENTER >> 7, &vcpu->arch.pending_exceptions); +} + +void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, + struct kvm_interrupt *irq) +{ + kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL); +} + +int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority) +{ + int deliver = 1; + int vec = 0; + + switch (priority) { + case BOOK3S_IRQPRIO_DECREMENTER: + deliver = vcpu->arch.msr & MSR_EE; + vec = BOOK3S_INTERRUPT_DECREMENTER; + break; + case BOOK3S_IRQPRIO_EXTERNAL: + deliver = vcpu->arch.msr & MSR_EE; + vec = BOOK3S_INTERRUPT_EXTERNAL; + break; + case BOOK3S_IRQPRIO_SYSTEM_RESET: + vec = BOOK3S_INTERRUPT_SYSTEM_RESET; + break; + case BOOK3S_IRQPRIO_MACHINE_CHECK: + vec = BOOK3S_INTERRUPT_MACHINE_CHECK; + break; + case BOOK3S_IRQPRIO_DATA_STORAGE: + vec = BOOK3S_INTERRUPT_DATA_STORAGE; + break; + case BOOK3S_IRQPRIO_INST_STORAGE: + vec = BOOK3S_INTERRUPT_INST_STORAGE; + break; + case BOOK3S_IRQPRIO_DATA_SEGMENT: + vec = BOOK3S_INTERRUPT_DATA_SEGMENT; + break; + case BOOK3S_IRQPRIO_INST_SEGMENT: + vec = BOOK3S_INTERRUPT_INST_SEGMENT; + break; + case BOOK3S_IRQPRIO_ALIGNMENT: + vec = BOOK3S_INTERRUPT_ALIGNMENT; + break; + case BOOK3S_IRQPRIO_PROGRAM: + vec = BOOK3S_INTERRUPT_PROGRAM; + break; + case BOOK3S_IRQPRIO_VSX: + vec = BOOK3S_INTERRUPT_VSX; + break; + case BOOK3S_IRQPRIO_ALTIVEC: + vec = BOOK3S_INTERRUPT_ALTIVEC; + break; + case BOOK3S_IRQPRIO_FP_UNAVAIL: + vec = BOOK3S_INTERRUPT_FP_UNAVAIL; + break; + case BOOK3S_IRQPRIO_SYSCALL: + vec = BOOK3S_INTERRUPT_SYSCALL; + break; + case BOOK3S_IRQPRIO_DEBUG: + vec = BOOK3S_INTERRUPT_TRACE; + break; + case BOOK3S_IRQPRIO_PERFORMANCE_MONITOR: + vec = BOOK3S_INTERRUPT_PERFMON; + break; + default: + deliver = 0; + printk(KERN_ERR "KVM: Unknown interrupt: 0x%x\n", priority); + break; + } + +#if 0 + printk(KERN_INFO "Deliver interrupt 0x%x? %x\n", vec, deliver); +#endif + + if (deliver) + kvmppc_inject_interrupt(vcpu, vec, 0ULL); + + return deliver; +} + +void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) +{ + unsigned long *pending = &vcpu->arch.pending_exceptions; + unsigned int priority; + + /* XXX be more clever here - no need to mftb() on every entry */ + /* Issue DEC again if it's still active */ +#ifdef AGGRESSIVE_DEC + if (vcpu->arch.msr & MSR_EE) + if (kvmppc_get_dec(vcpu) & 0x80000000) + kvmppc_core_queue_dec(vcpu); +#endif + +#ifdef EXIT_DEBUG + if (vcpu->arch.pending_exceptions) + printk(KERN_EMERG "KVM: Check pending: %lx\n", vcpu->arch.pending_exceptions); +#endif + priority = __ffs(*pending); + while (priority <= (sizeof(unsigned int) * 8)) { + if (kvmppc_book3s_irqprio_deliver(vcpu, priority)) { + clear_bit(priority, &vcpu->arch.pending_exceptions); + break; + } + + priority = find_next_bit(pending, + BITS_PER_BYTE * sizeof(*pending), + priority + 1); + } +} + +void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr) +{ + vcpu->arch.hflags &= ~BOOK3S_HFLAG_SLB; + vcpu->arch.pvr = pvr; + if ((pvr >= 0x330000) && (pvr < 0x70330000)) { + kvmppc_mmu_book3s_64_init(vcpu); + to_book3s(vcpu)->hior = 0xfff00000; + to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL; + } else { + kvmppc_mmu_book3s_32_init(vcpu); + to_book3s(vcpu)->hior = 0; + to_book3s(vcpu)->msr_mask = 0xffffffffULL; + } + + /* If we are in hypervisor level on 970, we can tell the CPU to + * treat DCBZ as 32 bytes store */ + vcpu->arch.hflags &= ~BOOK3S_HFLAG_DCBZ32; + if (vcpu->arch.mmu.is_dcbz32(vcpu) && (mfmsr() & MSR_HV) && + !strcmp(cur_cpu_spec->platform, "ppc970")) + vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32; + +} + +/* Book3s_32 CPUs always have 32 bytes cache line size, which Linux assumes. To + * make Book3s_32 Linux work on Book3s_64, we have to make sure we trap dcbz to + * emulate 32 bytes dcbz length. + * + * The Book3s_64 inventors also realized this case and implemented a special bit + * in the HID5 register, which is a hypervisor ressource. Thus we can't use it. + * + * My approach here is to patch the dcbz instruction on executing pages. + */ +static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte) +{ + bool touched = false; + hva_t hpage; + u32 *page; + int i; + + hpage = gfn_to_hva(vcpu->kvm, pte->raddr >> PAGE_SHIFT); + if (kvm_is_error_hva(hpage)) + return; + + hpage |= pte->raddr & ~PAGE_MASK; + hpage &= ~0xFFFULL; + + page = vmalloc(HW_PAGE_SIZE); + + if (copy_from_user(page, (void __user *)hpage, HW_PAGE_SIZE)) + goto out; + + for (i=0; i < HW_PAGE_SIZE / 4; i++) + if ((page[i] & 0xff0007ff) == INS_DCBZ) { + page[i] &= 0xfffffff7; // reserved instruction, so we trap + touched = true; + } + + if (touched) + copy_to_user((void __user *)hpage, page, HW_PAGE_SIZE); + +out: + vfree(page); +} + +static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data, + struct kvmppc_pte *pte) +{ + int relocated = (vcpu->arch.msr & (data ? MSR_DR : MSR_IR)); + int r; + + if (relocated) { + r = vcpu->arch.mmu.xlate(vcpu, eaddr, pte, data); + } else { + pte->eaddr = eaddr; + pte->raddr = eaddr & 0xffffffff; + pte->vpage = eaddr >> 12; + switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { + case 0: + pte->vpage |= VSID_REAL; + case MSR_DR: + pte->vpage |= VSID_REAL_DR; + case MSR_IR: + pte->vpage |= VSID_REAL_IR; + } + pte->may_read = true; + pte->may_write = true; + pte->may_execute = true; + r = 0; + } + + return r; +} + +static hva_t kvmppc_bad_hva(void) +{ + return PAGE_OFFSET; +} + +static hva_t kvmppc_pte_to_hva(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte, + bool read) +{ + hva_t hpage; + + if (read && !pte->may_read) + goto err; + + if (!read && !pte->may_write) + goto err; + + hpage = gfn_to_hva(vcpu->kvm, pte->raddr >> PAGE_SHIFT); + if (kvm_is_error_hva(hpage)) + goto err; + + return hpage | (pte->raddr & ~PAGE_MASK); +err: + return kvmppc_bad_hva(); +} + +int kvmppc_st(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr) +{ + struct kvmppc_pte pte; + hva_t hva = eaddr; + + vcpu->stat.st++; + + if (kvmppc_xlate(vcpu, eaddr, false, &pte)) + goto err; + + hva = kvmppc_pte_to_hva(vcpu, &pte, false); + if (kvm_is_error_hva(hva)) + goto err; + + if (copy_to_user((void __user *)hva, ptr, size)) { + printk(KERN_INFO "kvmppc_st at 0x%lx failed\n", hva); + goto err; + } + + return 0; + +err: + return -ENOENT; +} + +int kvmppc_ld(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr, + bool data) +{ + struct kvmppc_pte pte; + hva_t hva = eaddr; + + vcpu->stat.ld++; + + if (kvmppc_xlate(vcpu, eaddr, data, &pte)) + goto err; + + hva = kvmppc_pte_to_hva(vcpu, &pte, true); + if (kvm_is_error_hva(hva)) + goto err; + + if (copy_from_user(ptr, (void __user *)hva, size)) { + printk(KERN_INFO "kvmppc_ld at 0x%lx failed\n", hva); + goto err; + } + + return 0; + +err: + return -ENOENT; +} + +static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn) +{ + return kvm_is_visible_gfn(vcpu->kvm, gfn); +} + +int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, + ulong eaddr, int vec) +{ + bool data = (vec == BOOK3S_INTERRUPT_DATA_STORAGE); + int r = RESUME_GUEST; + int relocated; + int page_found = 0; + struct kvmppc_pte pte; + bool is_mmio = false; + + if ( vec == BOOK3S_INTERRUPT_DATA_STORAGE ) { + relocated = (vcpu->arch.msr & MSR_DR); + } else { + relocated = (vcpu->arch.msr & MSR_IR); + } + + /* Resolve real address if translation turned on */ + if (relocated) { + page_found = vcpu->arch.mmu.xlate(vcpu, eaddr, &pte, data); + } else { + pte.may_execute = true; + pte.may_read = true; + pte.may_write = true; + pte.raddr = eaddr & 0xffffffff; + pte.eaddr = eaddr; + pte.vpage = eaddr >> 12; + switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { + case 0: + pte.vpage |= VSID_REAL; + case MSR_DR: + pte.vpage |= VSID_REAL_DR; + case MSR_IR: + pte.vpage |= VSID_REAL_IR; + } + } + + if (vcpu->arch.mmu.is_dcbz32(vcpu) && + (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) { + /* + * If we do the dcbz hack, we have to NX on every execution, + * so we can patch the executing code. This renders our guest + * NX-less. + */ + pte.may_execute = !data; + } + + if (page_found == -ENOENT) { + /* Page not found in guest PTE entries */ + vcpu->arch.dear = vcpu->arch.fault_dear; + to_book3s(vcpu)->dsisr = vcpu->arch.fault_dsisr; + vcpu->arch.msr |= (vcpu->arch.shadow_msr & 0x00000000f8000000ULL); + kvmppc_book3s_queue_irqprio(vcpu, vec); + } else if (page_found == -EPERM) { + /* Storage protection */ + vcpu->arch.dear = vcpu->arch.fault_dear; + to_book3s(vcpu)->dsisr = vcpu->arch.fault_dsisr & ~DSISR_NOHPTE; + to_book3s(vcpu)->dsisr |= DSISR_PROTFAULT; + vcpu->arch.msr |= (vcpu->arch.shadow_msr & 0x00000000f8000000ULL); + kvmppc_book3s_queue_irqprio(vcpu, vec); + } else if (page_found == -EINVAL) { + /* Page not found in guest SLB */ + vcpu->arch.dear = vcpu->arch.fault_dear; + kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80); + } else if (!is_mmio && + kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) { + /* The guest's PTE is not mapped yet. Map on the host */ + kvmppc_mmu_map_page(vcpu, &pte); + if (data) + vcpu->stat.sp_storage++; + else if (vcpu->arch.mmu.is_dcbz32(vcpu) && + (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) + kvmppc_patch_dcbz(vcpu, &pte); + } else { + /* MMIO */ + vcpu->stat.mmio_exits++; + vcpu->arch.paddr_accessed = pte.raddr; + r = kvmppc_emulate_mmio(run, vcpu); + if ( r == RESUME_HOST_NV ) + r = RESUME_HOST; + if ( r == RESUME_GUEST_NV ) + r = RESUME_GUEST; + } + + return r; +} + +int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, + unsigned int exit_nr) +{ + int r = RESUME_HOST; + + vcpu->stat.sum_exits++; + + run->exit_reason = KVM_EXIT_UNKNOWN; + run->ready_for_interrupt_injection = 1; +#ifdef EXIT_DEBUG + printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | dar=0x%lx | dec=0x%x | msr=0x%lx\n", + exit_nr, vcpu->arch.pc, vcpu->arch.fault_dear, + kvmppc_get_dec(vcpu), vcpu->arch.msr); +#elif defined (EXIT_DEBUG_SIMPLE) + if ((exit_nr != 0x900) && (exit_nr != 0x500)) + printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | dar=0x%lx | msr=0x%lx\n", + exit_nr, vcpu->arch.pc, vcpu->arch.fault_dear, + vcpu->arch.msr); +#endif + kvm_resched(vcpu); + switch (exit_nr) { + case BOOK3S_INTERRUPT_INST_STORAGE: + vcpu->stat.pf_instruc++; + /* only care about PTEG not found errors, but leave NX alone */ + if (vcpu->arch.shadow_msr & 0x40000000) { + r = kvmppc_handle_pagefault(run, vcpu, vcpu->arch.pc, exit_nr); + vcpu->stat.sp_instruc++; + } else if (vcpu->arch.mmu.is_dcbz32(vcpu) && + (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) { + /* + * XXX If we do the dcbz hack we use the NX bit to flush&patch the page, + * so we can't use the NX bit inside the guest. Let's cross our fingers, + * that no guest that needs the dcbz hack does NX. + */ + kvmppc_mmu_pte_flush(vcpu, vcpu->arch.pc, ~0xFFFULL); + } else { + vcpu->arch.msr |= (vcpu->arch.shadow_msr & 0x58000000); + kvmppc_book3s_queue_irqprio(vcpu, exit_nr); + kvmppc_mmu_pte_flush(vcpu, vcpu->arch.pc, ~0xFFFULL); + r = RESUME_GUEST; + } + break; + case BOOK3S_INTERRUPT_DATA_STORAGE: + vcpu->stat.pf_storage++; + /* The only case we need to handle is missing shadow PTEs */ + if (vcpu->arch.fault_dsisr & DSISR_NOHPTE) { + r = kvmppc_handle_pagefault(run, vcpu, vcpu->arch.fault_dear, exit_nr); + } else { + vcpu->arch.dear = vcpu->arch.fault_dear; + to_book3s(vcpu)->dsisr = vcpu->arch.fault_dsisr; + kvmppc_book3s_queue_irqprio(vcpu, exit_nr); + kvmppc_mmu_pte_flush(vcpu, vcpu->arch.dear, ~0xFFFULL); + r = RESUME_GUEST; + } + break; + case BOOK3S_INTERRUPT_DATA_SEGMENT: + if (kvmppc_mmu_map_segment(vcpu, vcpu->arch.fault_dear) < 0) { + vcpu->arch.dear = vcpu->arch.fault_dear; + kvmppc_book3s_queue_irqprio(vcpu, + BOOK3S_INTERRUPT_DATA_SEGMENT); + } + r = RESUME_GUEST; + break; + case BOOK3S_INTERRUPT_INST_SEGMENT: + if (kvmppc_mmu_map_segment(vcpu, vcpu->arch.pc) < 0) { + kvmppc_book3s_queue_irqprio(vcpu, + BOOK3S_INTERRUPT_INST_SEGMENT); + } + r = RESUME_GUEST; + break; + /* We're good on these - the host merely wanted to get our attention */ + case BOOK3S_INTERRUPT_DECREMENTER: + vcpu->stat.dec_exits++; + r = RESUME_GUEST; + break; + case BOOK3S_INTERRUPT_EXTERNAL: + vcpu->stat.ext_intr_exits++; + r = RESUME_GUEST; + break; + case BOOK3S_INTERRUPT_PROGRAM: + { + enum emulation_result er; + + if (vcpu->arch.msr & MSR_PR) { +#ifdef EXIT_DEBUG + printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", vcpu->arch.pc, vcpu->arch.last_inst); +#endif + if ((vcpu->arch.last_inst & 0xff0007ff) != + (INS_DCBZ & 0xfffffff7)) { + kvmppc_book3s_queue_irqprio(vcpu, exit_nr); + r = RESUME_GUEST; + break; + } + } + + vcpu->stat.emulated_inst_exits++; + er = kvmppc_emulate_instruction(run, vcpu); + switch (er) { + case EMULATE_DONE: + r = RESUME_GUEST; + break; + case EMULATE_FAIL: + printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n", + __func__, vcpu->arch.pc, vcpu->arch.last_inst); + kvmppc_book3s_queue_irqprio(vcpu, exit_nr); + r = RESUME_GUEST; + break; + default: + BUG(); + } + break; + } + case BOOK3S_INTERRUPT_SYSCALL: +#ifdef EXIT_DEBUG + printk(KERN_INFO "Syscall Nr %d\n", (int)vcpu->arch.gpr[0]); +#endif + vcpu->stat.syscall_exits++; + kvmppc_book3s_queue_irqprio(vcpu, exit_nr); + r = RESUME_GUEST; + break; + case BOOK3S_INTERRUPT_MACHINE_CHECK: + case BOOK3S_INTERRUPT_FP_UNAVAIL: + case BOOK3S_INTERRUPT_TRACE: + case BOOK3S_INTERRUPT_ALTIVEC: + case BOOK3S_INTERRUPT_VSX: + kvmppc_book3s_queue_irqprio(vcpu, exit_nr); + r = RESUME_GUEST; + break; + default: + /* Ugh - bork here! What did we get? */ + printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | msr=0x%lx\n", exit_nr, vcpu->arch.pc, vcpu->arch.shadow_msr); + r = RESUME_HOST; + BUG(); + break; + } + + + if (!(r & RESUME_HOST)) { + /* To avoid clobbering exit_reason, only check for signals if + * we aren't already exiting to userspace for some other + * reason. */ + if (signal_pending(current)) { +#ifdef EXIT_DEBUG + printk(KERN_EMERG "KVM: Going back to host\n"); +#endif + vcpu->stat.signal_exits++; + run->exit_reason = KVM_EXIT_INTR; + r = -EINTR; + } else { + /* In case an interrupt came in that was triggered + * from userspace (like DEC), we need to check what + * to inject now! */ + kvmppc_core_deliver_interrupts(vcpu); + } + } + +#ifdef EXIT_DEBUG + printk(KERN_EMERG "KVM exit: vcpu=0x%p pc=0x%lx r=0x%x\n", vcpu, vcpu->arch.pc, r); +#endif + + return r; +} + +int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) +{ + return 0; +} + +int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) +{ + int i; + + regs->pc = vcpu->arch.pc; + regs->cr = vcpu->arch.cr; + regs->ctr = vcpu->arch.ctr; + regs->lr = vcpu->arch.lr; + regs->xer = vcpu->arch.xer; + regs->msr = vcpu->arch.msr; + regs->srr0 = vcpu->arch.srr0; + regs->srr1 = vcpu->arch.srr1; + regs->pid = vcpu->arch.pid; + regs->sprg0 = vcpu->arch.sprg0; + regs->sprg1 = vcpu->arch.sprg1; + regs->sprg2 = vcpu->arch.sprg2; + regs->sprg3 = vcpu->arch.sprg3; + regs->sprg5 = vcpu->arch.sprg4; + regs->sprg6 = vcpu->arch.sprg5; + regs->sprg7 = vcpu->arch.sprg6; + + for (i = 0; i < ARRAY_SIZE(regs->gpr); i++) + regs->gpr[i] = vcpu->arch.gpr[i]; + + return 0; +} + +int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) +{ + int i; + + vcpu->arch.pc = regs->pc; + vcpu->arch.cr = regs->cr; + vcpu->arch.ctr = regs->ctr; + vcpu->arch.lr = regs->lr; + vcpu->arch.xer = regs->xer; + kvmppc_set_msr(vcpu, regs->msr); + vcpu->arch.srr0 = regs->srr0; + vcpu->arch.srr1 = regs->srr1; + vcpu->arch.sprg0 = regs->sprg0; + vcpu->arch.sprg1 = regs->sprg1; + vcpu->arch.sprg2 = regs->sprg2; + vcpu->arch.sprg3 = regs->sprg3; + vcpu->arch.sprg5 = regs->sprg4; + vcpu->arch.sprg6 = regs->sprg5; + vcpu->arch.sprg7 = regs->sprg6; + + for (i = 0; i < ARRAY_SIZE(vcpu->arch.gpr); i++) + vcpu->arch.gpr[i] = regs->gpr[i]; + + return 0; +} + +int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, + struct kvm_sregs *sregs) +{ + struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); + int i; + + sregs->pvr = vcpu->arch.pvr; + + sregs->u.s.sdr1 = to_book3s(vcpu)->sdr1; + if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) { + for (i = 0; i < 64; i++) { + sregs->u.s.ppc64.slb[i].slbe = vcpu3s->slb[i].orige | i; + sregs->u.s.ppc64.slb[i].slbv = vcpu3s->slb[i].origv; + } + } else { + for (i = 0; i < 16; i++) { + sregs->u.s.ppc32.sr[i] = vcpu3s->sr[i].raw; + sregs->u.s.ppc32.sr[i] = vcpu3s->sr[i].raw; + } + for (i = 0; i < 8; i++) { + sregs->u.s.ppc32.ibat[i] = vcpu3s->ibat[i].raw; + sregs->u.s.ppc32.dbat[i] = vcpu3s->dbat[i].raw; + } + } + return 0; +} + +int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, + struct kvm_sregs *sregs) +{ + struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); + int i; + + kvmppc_set_pvr(vcpu, sregs->pvr); + + vcpu3s->sdr1 = sregs->u.s.sdr1; + if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) { + for (i = 0; i < 64; i++) { + vcpu->arch.mmu.slbmte(vcpu, sregs->u.s.ppc64.slb[i].slbv, + sregs->u.s.ppc64.slb[i].slbe); + } + } else { + for (i = 0; i < 16; i++) { + vcpu->arch.mmu.mtsrin(vcpu, i, sregs->u.s.ppc32.sr[i]); + } + for (i = 0; i < 8; i++) { + kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), false, + (u32)sregs->u.s.ppc32.ibat[i]); + kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), true, + (u32)(sregs->u.s.ppc32.ibat[i] >> 32)); + kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), false, + (u32)sregs->u.s.ppc32.dbat[i]); + kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), true, + (u32)(sregs->u.s.ppc32.dbat[i] >> 32)); + } + } + + /* Flush the MMU after messing with the segments */ + kvmppc_mmu_pte_flush(vcpu, 0, 0); + return 0; +} + +int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) +{ + return -ENOTSUPP; +} + +int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) +{ + return -ENOTSUPP; +} + +int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, + struct kvm_translation *tr) +{ + return 0; +} + +/* + * Get (and clear) the dirty memory log for a memory slot. + */ +int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, + struct kvm_dirty_log *log) +{ + struct kvm_memory_slot *memslot; + struct kvm_vcpu *vcpu; + ulong ga, ga_end; + int is_dirty = 0; + int r, n; + + down_write(&kvm->slots_lock); + + r = kvm_get_dirty_log(kvm, log, &is_dirty); + if (r) + goto out; + + /* If nothing is dirty, don't bother messing with page tables. */ + if (is_dirty) { + memslot = &kvm->memslots[log->slot]; + + ga = memslot->base_gfn << PAGE_SHIFT; + ga_end = ga + (memslot->npages << PAGE_SHIFT); + + kvm_for_each_vcpu(n, vcpu, kvm) + kvmppc_mmu_pte_pflush(vcpu, ga, ga_end); + + n = ALIGN(memslot->npages, BITS_PER_LONG) / 8; + memset(memslot->dirty_bitmap, 0, n); + } + + r = 0; +out: + up_write(&kvm->slots_lock); + return r; +} + +int kvmppc_core_check_processor_compat(void) +{ + return 0; +} + +struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) +{ + struct kvmppc_vcpu_book3s *vcpu_book3s; + struct kvm_vcpu *vcpu; + int err; + + vcpu_book3s = (struct kvmppc_vcpu_book3s *)__get_free_pages( GFP_KERNEL | __GFP_ZERO, + get_order(sizeof(struct kvmppc_vcpu_book3s))); + if (!vcpu_book3s) { + err = -ENOMEM; + goto out; + } + + vcpu = &vcpu_book3s->vcpu; + err = kvm_vcpu_init(vcpu, kvm, id); + if (err) + goto free_vcpu; + + vcpu->arch.host_retip = kvm_return_point; + vcpu->arch.host_msr = mfmsr(); + /* default to book3s_64 (970fx) */ + vcpu->arch.pvr = 0x3C0301; + kvmppc_set_pvr(vcpu, vcpu->arch.pvr); + vcpu_book3s->slb_nr = 64; + + /* remember where some real-mode handlers are */ + vcpu->arch.trampoline_lowmem = kvmppc_trampoline_lowmem; + vcpu->arch.trampoline_enter = kvmppc_trampoline_enter; + vcpu->arch.highmem_handler = (ulong)kvmppc_handler_highmem; + + vcpu->arch.shadow_msr = MSR_USER64; + + err = __init_new_context(); + if (err < 0) + goto free_vcpu; + vcpu_book3s->context_id = err; + + vcpu_book3s->vsid_max = ((vcpu_book3s->context_id + 1) << USER_ESID_BITS) - 1; + vcpu_book3s->vsid_first = vcpu_book3s->context_id << USER_ESID_BITS; + vcpu_book3s->vsid_next = vcpu_book3s->vsid_first; + + return vcpu; + +free_vcpu: + free_pages((long)vcpu_book3s, get_order(sizeof(struct kvmppc_vcpu_book3s))); +out: + return ERR_PTR(err); +} + +void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) +{ + struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); + + __destroy_context(vcpu_book3s->context_id); + kvm_vcpu_uninit(vcpu); + free_pages((long)vcpu_book3s, get_order(sizeof(struct kvmppc_vcpu_book3s))); +} + +extern int __kvmppc_vcpu_entry(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); +int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) +{ + int ret; + + /* No need to go into the guest when all we do is going out */ + if (signal_pending(current)) { + kvm_run->exit_reason = KVM_EXIT_INTR; + return -EINTR; + } + + /* XXX we get called with irq disabled - change that! */ + local_irq_enable(); + + ret = __kvmppc_vcpu_entry(kvm_run, vcpu); + + local_irq_disable(); + + return ret; +} + +static int kvmppc_book3s_init(void) +{ + return kvm_init(NULL, sizeof(struct kvmppc_vcpu_book3s), THIS_MODULE); +} + +static void kvmppc_book3s_exit(void) +{ + kvm_exit(); +} + +module_init(kvmppc_book3s_init); +module_exit(kvmppc_book3s_exit); diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c new file mode 100644 index 0000000000000000000000000000000000000000..faf99f20d993a89666f7fb2995c40c175be94ca7 --- /dev/null +++ b/arch/powerpc/kvm/book3s_32_mmu.c @@ -0,0 +1,372 @@ +/* + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright SUSE Linux Products GmbH 2009 + * + * Authors: Alexander Graf + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +/* #define DEBUG_MMU */ +/* #define DEBUG_MMU_PTE */ +/* #define DEBUG_MMU_PTE_IP 0xfff14c40 */ + +#ifdef DEBUG_MMU +#define dprintk(X...) printk(KERN_INFO X) +#else +#define dprintk(X...) do { } while(0) +#endif + +#ifdef DEBUG_PTE +#define dprintk_pte(X...) printk(KERN_INFO X) +#else +#define dprintk_pte(X...) do { } while(0) +#endif + +#define PTEG_FLAG_ACCESSED 0x00000100 +#define PTEG_FLAG_DIRTY 0x00000080 + +static inline bool check_debug_ip(struct kvm_vcpu *vcpu) +{ +#ifdef DEBUG_MMU_PTE_IP + return vcpu->arch.pc == DEBUG_MMU_PTE_IP; +#else + return true; +#endif +} + +static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr, + struct kvmppc_pte *pte, bool data); + +static struct kvmppc_sr *find_sr(struct kvmppc_vcpu_book3s *vcpu_book3s, gva_t eaddr) +{ + return &vcpu_book3s->sr[(eaddr >> 28) & 0xf]; +} + +static u64 kvmppc_mmu_book3s_32_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr, + bool data) +{ + struct kvmppc_sr *sre = find_sr(to_book3s(vcpu), eaddr); + struct kvmppc_pte pte; + + if (!kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, &pte, data)) + return pte.vpage; + + return (((u64)eaddr >> 12) & 0xffff) | (((u64)sre->vsid) << 16); +} + +static void kvmppc_mmu_book3s_32_reset_msr(struct kvm_vcpu *vcpu) +{ + kvmppc_set_msr(vcpu, 0); +} + +static hva_t kvmppc_mmu_book3s_32_get_pteg(struct kvmppc_vcpu_book3s *vcpu_book3s, + struct kvmppc_sr *sre, gva_t eaddr, + bool primary) +{ + u32 page, hash, pteg, htabmask; + hva_t r; + + page = (eaddr & 0x0FFFFFFF) >> 12; + htabmask = ((vcpu_book3s->sdr1 & 0x1FF) << 16) | 0xFFC0; + + hash = ((sre->vsid ^ page) << 6); + if (!primary) + hash = ~hash; + hash &= htabmask; + + pteg = (vcpu_book3s->sdr1 & 0xffff0000) | hash; + + dprintk("MMU: pc=0x%lx eaddr=0x%lx sdr1=0x%llx pteg=0x%x vsid=0x%x\n", + vcpu_book3s->vcpu.arch.pc, eaddr, vcpu_book3s->sdr1, pteg, + sre->vsid); + + r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT); + if (kvm_is_error_hva(r)) + return r; + return r | (pteg & ~PAGE_MASK); +} + +static u32 kvmppc_mmu_book3s_32_get_ptem(struct kvmppc_sr *sre, gva_t eaddr, + bool primary) +{ + return ((eaddr & 0x0fffffff) >> 22) | (sre->vsid << 7) | + (primary ? 0 : 0x40) | 0x80000000; +} + +static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr, + struct kvmppc_pte *pte, bool data) +{ + struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); + struct kvmppc_bat *bat; + int i; + + for (i = 0; i < 8; i++) { + if (data) + bat = &vcpu_book3s->dbat[i]; + else + bat = &vcpu_book3s->ibat[i]; + + if (vcpu->arch.msr & MSR_PR) { + if (!bat->vp) + continue; + } else { + if (!bat->vs) + continue; + } + + if (check_debug_ip(vcpu)) + { + dprintk_pte("%cBAT %02d: 0x%lx - 0x%x (0x%x)\n", + data ? 'd' : 'i', i, eaddr, bat->bepi, + bat->bepi_mask); + } + if ((eaddr & bat->bepi_mask) == bat->bepi) { + pte->raddr = bat->brpn | (eaddr & ~bat->bepi_mask); + pte->vpage = (eaddr >> 12) | VSID_BAT; + pte->may_read = bat->pp; + pte->may_write = bat->pp > 1; + pte->may_execute = true; + if (!pte->may_read) { + printk(KERN_INFO "BAT is not readable!\n"); + continue; + } + if (!pte->may_write) { + /* let's treat r/o BATs as not-readable for now */ + dprintk_pte("BAT is read-only!\n"); + continue; + } + + return 0; + } + } + + return -ENOENT; +} + +static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, + struct kvmppc_pte *pte, bool data, + bool primary) +{ + struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); + struct kvmppc_sr *sre; + hva_t ptegp; + u32 pteg[16]; + u64 ptem = 0; + int i; + int found = 0; + + sre = find_sr(vcpu_book3s, eaddr); + + dprintk_pte("SR 0x%lx: vsid=0x%x, raw=0x%x\n", eaddr >> 28, + sre->vsid, sre->raw); + + pte->vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data); + + ptegp = kvmppc_mmu_book3s_32_get_pteg(vcpu_book3s, sre, eaddr, primary); + if (kvm_is_error_hva(ptegp)) { + printk(KERN_INFO "KVM: Invalid PTEG!\n"); + goto no_page_found; + } + + ptem = kvmppc_mmu_book3s_32_get_ptem(sre, eaddr, primary); + + if(copy_from_user(pteg, (void __user *)ptegp, sizeof(pteg))) { + printk(KERN_ERR "KVM: Can't copy data from 0x%lx!\n", ptegp); + goto no_page_found; + } + + for (i=0; i<16; i+=2) { + if (ptem == pteg[i]) { + u8 pp; + + pte->raddr = (pteg[i+1] & ~(0xFFFULL)) | (eaddr & 0xFFF); + pp = pteg[i+1] & 3; + + if ((sre->Kp && (vcpu->arch.msr & MSR_PR)) || + (sre->Ks && !(vcpu->arch.msr & MSR_PR))) + pp |= 4; + + pte->may_write = false; + pte->may_read = false; + pte->may_execute = true; + switch (pp) { + case 0: + case 1: + case 2: + case 6: + pte->may_write = true; + case 3: + case 5: + case 7: + pte->may_read = true; + break; + } + + if ( !pte->may_read ) + continue; + + dprintk_pte("MMU: Found PTE -> %x %x - %x\n", + pteg[i], pteg[i+1], pp); + found = 1; + break; + } + } + + /* Update PTE C and A bits, so the guest's swapper knows we used the + page */ + if (found) { + u32 oldpte = pteg[i+1]; + + if (pte->may_read) + pteg[i+1] |= PTEG_FLAG_ACCESSED; + if (pte->may_write) + pteg[i+1] |= PTEG_FLAG_DIRTY; + else + dprintk_pte("KVM: Mapping read-only page!\n"); + + /* Write back into the PTEG */ + if (pteg[i+1] != oldpte) + copy_to_user((void __user *)ptegp, pteg, sizeof(pteg)); + + return 0; + } + +no_page_found: + + if (check_debug_ip(vcpu)) { + dprintk_pte("KVM MMU: No PTE found (sdr1=0x%llx ptegp=0x%lx)\n", + to_book3s(vcpu)->sdr1, ptegp); + for (i=0; i<16; i+=2) { + dprintk_pte(" %02d: 0x%x - 0x%x (0x%llx)\n", + i, pteg[i], pteg[i+1], ptem); + } + } + + return -ENOENT; +} + +static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, + struct kvmppc_pte *pte, bool data) +{ + int r; + + pte->eaddr = eaddr; + r = kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, pte, data); + if (r < 0) + r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, data, true); + if (r < 0) + r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, data, false); + + return r; +} + + +static u32 kvmppc_mmu_book3s_32_mfsrin(struct kvm_vcpu *vcpu, u32 srnum) +{ + return to_book3s(vcpu)->sr[srnum].raw; +} + +static void kvmppc_mmu_book3s_32_mtsrin(struct kvm_vcpu *vcpu, u32 srnum, + ulong value) +{ + struct kvmppc_sr *sre; + + sre = &to_book3s(vcpu)->sr[srnum]; + + /* Flush any left-over shadows from the previous SR */ + + /* XXX Not necessary? */ + /* kvmppc_mmu_pte_flush(vcpu, ((u64)sre->vsid) << 28, 0xf0000000ULL); */ + + /* And then put in the new SR */ + sre->raw = value; + sre->vsid = (value & 0x0fffffff); + sre->Ks = (value & 0x40000000) ? true : false; + sre->Kp = (value & 0x20000000) ? true : false; + sre->nx = (value & 0x10000000) ? true : false; + + /* Map the new segment */ + kvmppc_mmu_map_segment(vcpu, srnum << SID_SHIFT); +} + +static void kvmppc_mmu_book3s_32_tlbie(struct kvm_vcpu *vcpu, ulong ea, bool large) +{ + kvmppc_mmu_pte_flush(vcpu, ea, ~0xFFFULL); +} + +static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, u64 esid, + u64 *vsid) +{ + /* In case we only have one of MSR_IR or MSR_DR set, let's put + that in the real-mode context (and hope RM doesn't access + high memory) */ + switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { + case 0: + *vsid = (VSID_REAL >> 16) | esid; + break; + case MSR_IR: + *vsid = (VSID_REAL_IR >> 16) | esid; + break; + case MSR_DR: + *vsid = (VSID_REAL_DR >> 16) | esid; + break; + case MSR_DR|MSR_IR: + { + ulong ea; + ea = esid << SID_SHIFT; + *vsid = find_sr(to_book3s(vcpu), ea)->vsid; + break; + } + default: + BUG(); + } + + return 0; +} + +static bool kvmppc_mmu_book3s_32_is_dcbz32(struct kvm_vcpu *vcpu) +{ + return true; +} + + +void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu) +{ + struct kvmppc_mmu *mmu = &vcpu->arch.mmu; + + mmu->mtsrin = kvmppc_mmu_book3s_32_mtsrin; + mmu->mfsrin = kvmppc_mmu_book3s_32_mfsrin; + mmu->xlate = kvmppc_mmu_book3s_32_xlate; + mmu->reset_msr = kvmppc_mmu_book3s_32_reset_msr; + mmu->tlbie = kvmppc_mmu_book3s_32_tlbie; + mmu->esid_to_vsid = kvmppc_mmu_book3s_32_esid_to_vsid; + mmu->ea_to_vp = kvmppc_mmu_book3s_32_ea_to_vp; + mmu->is_dcbz32 = kvmppc_mmu_book3s_32_is_dcbz32; + + mmu->slbmte = NULL; + mmu->slbmfee = NULL; + mmu->slbmfev = NULL; + mmu->slbie = NULL; + mmu->slbia = NULL; +} diff --git a/arch/powerpc/kvm/book3s_64_emulate.c b/arch/powerpc/kvm/book3s_64_emulate.c new file mode 100644 index 0000000000000000000000000000000000000000..1027eac6d474fea3ae3a94efe6aca91cd48a594c --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_emulate.c @@ -0,0 +1,345 @@ +/* + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright SUSE Linux Products GmbH 2009 + * + * Authors: Alexander Graf + */ + +#include +#include +#include +#include + +#define OP_19_XOP_RFID 18 +#define OP_19_XOP_RFI 50 + +#define OP_31_XOP_MFMSR 83 +#define OP_31_XOP_MTMSR 146 +#define OP_31_XOP_MTMSRD 178 +#define OP_31_XOP_MTSRIN 242 +#define OP_31_XOP_TLBIEL 274 +#define OP_31_XOP_TLBIE 306 +#define OP_31_XOP_SLBMTE 402 +#define OP_31_XOP_SLBIE 434 +#define OP_31_XOP_SLBIA 498 +#define OP_31_XOP_MFSRIN 659 +#define OP_31_XOP_SLBMFEV 851 +#define OP_31_XOP_EIOIO 854 +#define OP_31_XOP_SLBMFEE 915 + +/* DCBZ is actually 1014, but we patch it to 1010 so we get a trap */ +#define OP_31_XOP_DCBZ 1010 + +int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, + unsigned int inst, int *advance) +{ + int emulated = EMULATE_DONE; + + switch (get_op(inst)) { + case 19: + switch (get_xop(inst)) { + case OP_19_XOP_RFID: + case OP_19_XOP_RFI: + vcpu->arch.pc = vcpu->arch.srr0; + kvmppc_set_msr(vcpu, vcpu->arch.srr1); + *advance = 0; + break; + + default: + emulated = EMULATE_FAIL; + break; + } + break; + case 31: + switch (get_xop(inst)) { + case OP_31_XOP_MFMSR: + vcpu->arch.gpr[get_rt(inst)] = vcpu->arch.msr; + break; + case OP_31_XOP_MTMSRD: + { + ulong rs = vcpu->arch.gpr[get_rs(inst)]; + if (inst & 0x10000) { + vcpu->arch.msr &= ~(MSR_RI | MSR_EE); + vcpu->arch.msr |= rs & (MSR_RI | MSR_EE); + } else + kvmppc_set_msr(vcpu, rs); + break; + } + case OP_31_XOP_MTMSR: + kvmppc_set_msr(vcpu, vcpu->arch.gpr[get_rs(inst)]); + break; + case OP_31_XOP_MFSRIN: + { + int srnum; + + srnum = (vcpu->arch.gpr[get_rb(inst)] >> 28) & 0xf; + if (vcpu->arch.mmu.mfsrin) { + u32 sr; + sr = vcpu->arch.mmu.mfsrin(vcpu, srnum); + vcpu->arch.gpr[get_rt(inst)] = sr; + } + break; + } + case OP_31_XOP_MTSRIN: + vcpu->arch.mmu.mtsrin(vcpu, + (vcpu->arch.gpr[get_rb(inst)] >> 28) & 0xf, + vcpu->arch.gpr[get_rs(inst)]); + break; + case OP_31_XOP_TLBIE: + case OP_31_XOP_TLBIEL: + { + bool large = (inst & 0x00200000) ? true : false; + ulong addr = vcpu->arch.gpr[get_rb(inst)]; + vcpu->arch.mmu.tlbie(vcpu, addr, large); + break; + } + case OP_31_XOP_EIOIO: + break; + case OP_31_XOP_SLBMTE: + if (!vcpu->arch.mmu.slbmte) + return EMULATE_FAIL; + + vcpu->arch.mmu.slbmte(vcpu, vcpu->arch.gpr[get_rs(inst)], + vcpu->arch.gpr[get_rb(inst)]); + break; + case OP_31_XOP_SLBIE: + if (!vcpu->arch.mmu.slbie) + return EMULATE_FAIL; + + vcpu->arch.mmu.slbie(vcpu, vcpu->arch.gpr[get_rb(inst)]); + break; + case OP_31_XOP_SLBIA: + if (!vcpu->arch.mmu.slbia) + return EMULATE_FAIL; + + vcpu->arch.mmu.slbia(vcpu); + break; + case OP_31_XOP_SLBMFEE: + if (!vcpu->arch.mmu.slbmfee) { + emulated = EMULATE_FAIL; + } else { + ulong t, rb; + + rb = vcpu->arch.gpr[get_rb(inst)]; + t = vcpu->arch.mmu.slbmfee(vcpu, rb); + vcpu->arch.gpr[get_rt(inst)] = t; + } + break; + case OP_31_XOP_SLBMFEV: + if (!vcpu->arch.mmu.slbmfev) { + emulated = EMULATE_FAIL; + } else { + ulong t, rb; + + rb = vcpu->arch.gpr[get_rb(inst)]; + t = vcpu->arch.mmu.slbmfev(vcpu, rb); + vcpu->arch.gpr[get_rt(inst)] = t; + } + break; + case OP_31_XOP_DCBZ: + { + ulong rb = vcpu->arch.gpr[get_rb(inst)]; + ulong ra = 0; + ulong addr; + u32 zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + if (get_ra(inst)) + ra = vcpu->arch.gpr[get_ra(inst)]; + + addr = (ra + rb) & ~31ULL; + if (!(vcpu->arch.msr & MSR_SF)) + addr &= 0xffffffff; + + if (kvmppc_st(vcpu, addr, 32, zeros)) { + vcpu->arch.dear = addr; + vcpu->arch.fault_dear = addr; + to_book3s(vcpu)->dsisr = DSISR_PROTFAULT | + DSISR_ISSTORE; + kvmppc_book3s_queue_irqprio(vcpu, + BOOK3S_INTERRUPT_DATA_STORAGE); + kvmppc_mmu_pte_flush(vcpu, addr, ~0xFFFULL); + } + + break; + } + default: + emulated = EMULATE_FAIL; + } + break; + default: + emulated = EMULATE_FAIL; + } + + return emulated; +} + +void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, bool upper, + u32 val) +{ + if (upper) { + /* Upper BAT */ + u32 bl = (val >> 2) & 0x7ff; + bat->bepi_mask = (~bl << 17); + bat->bepi = val & 0xfffe0000; + bat->vs = (val & 2) ? 1 : 0; + bat->vp = (val & 1) ? 1 : 0; + bat->raw = (bat->raw & 0xffffffff00000000ULL) | val; + } else { + /* Lower BAT */ + bat->brpn = val & 0xfffe0000; + bat->wimg = (val >> 3) & 0xf; + bat->pp = val & 3; + bat->raw = (bat->raw & 0x00000000ffffffffULL) | ((u64)val << 32); + } +} + +static void kvmppc_write_bat(struct kvm_vcpu *vcpu, int sprn, u32 val) +{ + struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); + struct kvmppc_bat *bat; + + switch (sprn) { + case SPRN_IBAT0U ... SPRN_IBAT3L: + bat = &vcpu_book3s->ibat[(sprn - SPRN_IBAT0U) / 2]; + break; + case SPRN_IBAT4U ... SPRN_IBAT7L: + bat = &vcpu_book3s->ibat[(sprn - SPRN_IBAT4U) / 2]; + break; + case SPRN_DBAT0U ... SPRN_DBAT3L: + bat = &vcpu_book3s->dbat[(sprn - SPRN_DBAT0U) / 2]; + break; + case SPRN_DBAT4U ... SPRN_DBAT7L: + bat = &vcpu_book3s->dbat[(sprn - SPRN_DBAT4U) / 2]; + break; + default: + BUG(); + } + + kvmppc_set_bat(vcpu, bat, !(sprn % 2), val); +} + +int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) +{ + int emulated = EMULATE_DONE; + + switch (sprn) { + case SPRN_SDR1: + to_book3s(vcpu)->sdr1 = vcpu->arch.gpr[rs]; + break; + case SPRN_DSISR: + to_book3s(vcpu)->dsisr = vcpu->arch.gpr[rs]; + break; + case SPRN_DAR: + vcpu->arch.dear = vcpu->arch.gpr[rs]; + break; + case SPRN_HIOR: + to_book3s(vcpu)->hior = vcpu->arch.gpr[rs]; + break; + case SPRN_IBAT0U ... SPRN_IBAT3L: + case SPRN_IBAT4U ... SPRN_IBAT7L: + case SPRN_DBAT0U ... SPRN_DBAT3L: + case SPRN_DBAT4U ... SPRN_DBAT7L: + kvmppc_write_bat(vcpu, sprn, (u32)vcpu->arch.gpr[rs]); + /* BAT writes happen so rarely that we're ok to flush + * everything here */ + kvmppc_mmu_pte_flush(vcpu, 0, 0); + break; + case SPRN_HID0: + to_book3s(vcpu)->hid[0] = vcpu->arch.gpr[rs]; + break; + case SPRN_HID1: + to_book3s(vcpu)->hid[1] = vcpu->arch.gpr[rs]; + break; + case SPRN_HID2: + to_book3s(vcpu)->hid[2] = vcpu->arch.gpr[rs]; + break; + case SPRN_HID4: + to_book3s(vcpu)->hid[4] = vcpu->arch.gpr[rs]; + break; + case SPRN_HID5: + to_book3s(vcpu)->hid[5] = vcpu->arch.gpr[rs]; + /* guest HID5 set can change is_dcbz32 */ + if (vcpu->arch.mmu.is_dcbz32(vcpu) && + (mfmsr() & MSR_HV)) + vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32; + break; + case SPRN_ICTC: + case SPRN_THRM1: + case SPRN_THRM2: + case SPRN_THRM3: + case SPRN_CTRLF: + case SPRN_CTRLT: + break; + default: + printk(KERN_INFO "KVM: invalid SPR write: %d\n", sprn); +#ifndef DEBUG_SPR + emulated = EMULATE_FAIL; +#endif + break; + } + + return emulated; +} + +int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) +{ + int emulated = EMULATE_DONE; + + switch (sprn) { + case SPRN_SDR1: + vcpu->arch.gpr[rt] = to_book3s(vcpu)->sdr1; + break; + case SPRN_DSISR: + vcpu->arch.gpr[rt] = to_book3s(vcpu)->dsisr; + break; + case SPRN_DAR: + vcpu->arch.gpr[rt] = vcpu->arch.dear; + break; + case SPRN_HIOR: + vcpu->arch.gpr[rt] = to_book3s(vcpu)->hior; + break; + case SPRN_HID0: + vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[0]; + break; + case SPRN_HID1: + vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[1]; + break; + case SPRN_HID2: + vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[2]; + break; + case SPRN_HID4: + vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[4]; + break; + case SPRN_HID5: + vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[5]; + break; + case SPRN_THRM1: + case SPRN_THRM2: + case SPRN_THRM3: + case SPRN_CTRLF: + case SPRN_CTRLT: + vcpu->arch.gpr[rt] = 0; + break; + default: + printk(KERN_INFO "KVM: invalid SPR read: %d\n", sprn); +#ifndef DEBUG_SPR + emulated = EMULATE_FAIL; +#endif + break; + } + + return emulated; +} + diff --git a/arch/powerpc/kvm/book3s_64_exports.c b/arch/powerpc/kvm/book3s_64_exports.c new file mode 100644 index 0000000000000000000000000000000000000000..5b2db38ed86cce3c1d69309308f0a49c63806ee4 --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_exports.c @@ -0,0 +1,24 @@ +/* + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright SUSE Linux Products GmbH 2009 + * + * Authors: Alexander Graf + */ + +#include +#include + +EXPORT_SYMBOL_GPL(kvmppc_trampoline_enter); +EXPORT_SYMBOL_GPL(kvmppc_trampoline_lowmem); diff --git a/arch/powerpc/kvm/book3s_64_interrupts.S b/arch/powerpc/kvm/book3s_64_interrupts.S new file mode 100644 index 0000000000000000000000000000000000000000..7b55d8094c8b372781bea6a2c35c689b0f273cc8 --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_interrupts.S @@ -0,0 +1,392 @@ +/* + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright SUSE Linux Products GmbH 2009 + * + * Authors: Alexander Graf + */ + +#include +#include +#include +#include +#include +#include + +#define KVMPPC_HANDLE_EXIT .kvmppc_handle_exit +#define ULONG_SIZE 8 +#define VCPU_GPR(n) (VCPU_GPRS + (n * ULONG_SIZE)) + +.macro mfpaca tmp_reg, src_reg, offset, vcpu_reg + ld \tmp_reg, (PACA_EXMC+\offset)(r13) + std \tmp_reg, VCPU_GPR(\src_reg)(\vcpu_reg) +.endm + +.macro DISABLE_INTERRUPTS + mfmsr r0 + rldicl r0,r0,48,1 + rotldi r0,r0,16 + mtmsrd r0,1 +.endm + +/***************************************************************************** + * * + * Guest entry / exit code that is in kernel module memory (highmem) * + * * + ****************************************************************************/ + +/* Registers: + * r3: kvm_run pointer + * r4: vcpu pointer + */ +_GLOBAL(__kvmppc_vcpu_entry) + +kvm_start_entry: + /* Write correct stack frame */ + mflr r0 + std r0,16(r1) + + /* Save host state to the stack */ + stdu r1, -SWITCH_FRAME_SIZE(r1) + + /* Save r3 (kvm_run) and r4 (vcpu) */ + SAVE_2GPRS(3, r1) + + /* Save non-volatile registers (r14 - r31) */ + SAVE_NVGPRS(r1) + + /* Save LR */ + mflr r14 + std r14, _LINK(r1) + +/* XXX optimize non-volatile loading away */ +kvm_start_lightweight: + + DISABLE_INTERRUPTS + + /* Save R1/R2 in the PACA */ + std r1, PACAR1(r13) + std r2, (PACA_EXMC+EX_SRR0)(r13) + ld r3, VCPU_HIGHMEM_HANDLER(r4) + std r3, PACASAVEDMSR(r13) + + /* Load non-volatile guest state from the vcpu */ + ld r14, VCPU_GPR(r14)(r4) + ld r15, VCPU_GPR(r15)(r4) + ld r16, VCPU_GPR(r16)(r4) + ld r17, VCPU_GPR(r17)(r4) + ld r18, VCPU_GPR(r18)(r4) + ld r19, VCPU_GPR(r19)(r4) + ld r20, VCPU_GPR(r20)(r4) + ld r21, VCPU_GPR(r21)(r4) + ld r22, VCPU_GPR(r22)(r4) + ld r23, VCPU_GPR(r23)(r4) + ld r24, VCPU_GPR(r24)(r4) + ld r25, VCPU_GPR(r25)(r4) + ld r26, VCPU_GPR(r26)(r4) + ld r27, VCPU_GPR(r27)(r4) + ld r28, VCPU_GPR(r28)(r4) + ld r29, VCPU_GPR(r29)(r4) + ld r30, VCPU_GPR(r30)(r4) + ld r31, VCPU_GPR(r31)(r4) + + ld r9, VCPU_PC(r4) /* r9 = vcpu->arch.pc */ + ld r10, VCPU_SHADOW_MSR(r4) /* r10 = vcpu->arch.shadow_msr */ + + ld r3, VCPU_TRAMPOLINE_ENTER(r4) + mtsrr0 r3 + + LOAD_REG_IMMEDIATE(r3, MSR_KERNEL & ~(MSR_IR | MSR_DR)) + mtsrr1 r3 + + /* Load guest state in the respective registers */ + lwz r3, VCPU_CR(r4) /* r3 = vcpu->arch.cr */ + stw r3, (PACA_EXMC + EX_CCR)(r13) + + ld r3, VCPU_CTR(r4) /* r3 = vcpu->arch.ctr */ + mtctr r3 /* CTR = r3 */ + + ld r3, VCPU_LR(r4) /* r3 = vcpu->arch.lr */ + mtlr r3 /* LR = r3 */ + + ld r3, VCPU_XER(r4) /* r3 = vcpu->arch.xer */ + std r3, (PACA_EXMC + EX_R3)(r13) + + /* Some guests may need to have dcbz set to 32 byte length. + * + * Usually we ensure that by patching the guest's instructions + * to trap on dcbz and emulate it in the hypervisor. + * + * If we can, we should tell the CPU to use 32 byte dcbz though, + * because that's a lot faster. + */ + + ld r3, VCPU_HFLAGS(r4) + rldicl. r3, r3, 0, 63 /* CR = ((r3 & 1) == 0) */ + beq no_dcbz32_on + + mfspr r3,SPRN_HID5 + ori r3, r3, 0x80 /* XXX HID5_dcbz32 = 0x80 */ + mtspr SPRN_HID5,r3 + +no_dcbz32_on: + /* Load guest GPRs */ + + ld r3, VCPU_GPR(r9)(r4) + std r3, (PACA_EXMC + EX_R9)(r13) + ld r3, VCPU_GPR(r10)(r4) + std r3, (PACA_EXMC + EX_R10)(r13) + ld r3, VCPU_GPR(r11)(r4) + std r3, (PACA_EXMC + EX_R11)(r13) + ld r3, VCPU_GPR(r12)(r4) + std r3, (PACA_EXMC + EX_R12)(r13) + ld r3, VCPU_GPR(r13)(r4) + std r3, (PACA_EXMC + EX_R13)(r13) + + ld r0, VCPU_GPR(r0)(r4) + ld r1, VCPU_GPR(r1)(r4) + ld r2, VCPU_GPR(r2)(r4) + ld r3, VCPU_GPR(r3)(r4) + ld r5, VCPU_GPR(r5)(r4) + ld r6, VCPU_GPR(r6)(r4) + ld r7, VCPU_GPR(r7)(r4) + ld r8, VCPU_GPR(r8)(r4) + ld r4, VCPU_GPR(r4)(r4) + + /* This sets the Magic value for the trampoline */ + + li r11, 1 + stb r11, PACA_KVM_IN_GUEST(r13) + + /* Jump to SLB patching handlder and into our guest */ + RFI + +/* + * This is the handler in module memory. It gets jumped at from the + * lowmem trampoline code, so it's basically the guest exit code. + * + */ + +.global kvmppc_handler_highmem +kvmppc_handler_highmem: + + /* + * Register usage at this point: + * + * R00 = guest R13 + * R01 = host R1 + * R02 = host R2 + * R10 = guest PC + * R11 = guest MSR + * R12 = exit handler id + * R13 = PACA + * PACA.exmc.R9 = guest R1 + * PACA.exmc.R10 = guest R10 + * PACA.exmc.R11 = guest R11 + * PACA.exmc.R12 = guest R12 + * PACA.exmc.R13 = guest R2 + * PACA.exmc.DAR = guest DAR + * PACA.exmc.DSISR = guest DSISR + * PACA.exmc.LR = guest instruction + * PACA.exmc.CCR = guest CR + * PACA.exmc.SRR0 = guest R0 + * + */ + + std r3, (PACA_EXMC+EX_R3)(r13) + + /* save the exit id in R3 */ + mr r3, r12 + + /* R12 = vcpu */ + ld r12, GPR4(r1) + + /* Now save the guest state */ + + std r0, VCPU_GPR(r13)(r12) + std r4, VCPU_GPR(r4)(r12) + std r5, VCPU_GPR(r5)(r12) + std r6, VCPU_GPR(r6)(r12) + std r7, VCPU_GPR(r7)(r12) + std r8, VCPU_GPR(r8)(r12) + std r9, VCPU_GPR(r9)(r12) + + /* get registers from PACA */ + mfpaca r5, r0, EX_SRR0, r12 + mfpaca r5, r3, EX_R3, r12 + mfpaca r5, r1, EX_R9, r12 + mfpaca r5, r10, EX_R10, r12 + mfpaca r5, r11, EX_R11, r12 + mfpaca r5, r12, EX_R12, r12 + mfpaca r5, r2, EX_R13, r12 + + lwz r5, (PACA_EXMC+EX_LR)(r13) + stw r5, VCPU_LAST_INST(r12) + + lwz r5, (PACA_EXMC+EX_CCR)(r13) + stw r5, VCPU_CR(r12) + + ld r5, VCPU_HFLAGS(r12) + rldicl. r5, r5, 0, 63 /* CR = ((r5 & 1) == 0) */ + beq no_dcbz32_off + + mfspr r5,SPRN_HID5 + rldimi r5,r5,6,56 + mtspr SPRN_HID5,r5 + +no_dcbz32_off: + + /* XXX maybe skip on lightweight? */ + std r14, VCPU_GPR(r14)(r12) + std r15, VCPU_GPR(r15)(r12) + std r16, VCPU_GPR(r16)(r12) + std r17, VCPU_GPR(r17)(r12) + std r18, VCPU_GPR(r18)(r12) + std r19, VCPU_GPR(r19)(r12) + std r20, VCPU_GPR(r20)(r12) + std r21, VCPU_GPR(r21)(r12) + std r22, VCPU_GPR(r22)(r12) + std r23, VCPU_GPR(r23)(r12) + std r24, VCPU_GPR(r24)(r12) + std r25, VCPU_GPR(r25)(r12) + std r26, VCPU_GPR(r26)(r12) + std r27, VCPU_GPR(r27)(r12) + std r28, VCPU_GPR(r28)(r12) + std r29, VCPU_GPR(r29)(r12) + std r30, VCPU_GPR(r30)(r12) + std r31, VCPU_GPR(r31)(r12) + + /* Restore non-volatile host registers (r14 - r31) */ + REST_NVGPRS(r1) + + /* Save guest PC (R10) */ + std r10, VCPU_PC(r12) + + /* Save guest msr (R11) */ + std r11, VCPU_SHADOW_MSR(r12) + + /* Save guest CTR (in R12) */ + mfctr r5 + std r5, VCPU_CTR(r12) + + /* Save guest LR */ + mflr r5 + std r5, VCPU_LR(r12) + + /* Save guest XER */ + mfxer r5 + std r5, VCPU_XER(r12) + + /* Save guest DAR */ + ld r5, (PACA_EXMC+EX_DAR)(r13) + std r5, VCPU_FAULT_DEAR(r12) + + /* Save guest DSISR */ + lwz r5, (PACA_EXMC+EX_DSISR)(r13) + std r5, VCPU_FAULT_DSISR(r12) + + /* Restore host msr -> SRR1 */ + ld r7, VCPU_HOST_MSR(r12) + mtsrr1 r7 + + /* Restore host IP -> SRR0 */ + ld r6, VCPU_HOST_RETIP(r12) + mtsrr0 r6 + + /* + * For some interrupts, we need to call the real Linux + * handler, so it can do work for us. This has to happen + * as if the interrupt arrived from the kernel though, + * so let's fake it here where most state is restored. + * + * Call Linux for hardware interrupts/decrementer + * r3 = address of interrupt handler (exit reason) + */ + + cmpwi r3, BOOK3S_INTERRUPT_EXTERNAL + beq call_linux_handler + cmpwi r3, BOOK3S_INTERRUPT_DECREMENTER + beq call_linux_handler + + /* Back to Interruptable Mode! (goto kvm_return_point) */ + RFI + +call_linux_handler: + + /* + * If we land here we need to jump back to the handler we + * came from. + * + * We have a page that we can access from real mode, so let's + * jump back to that and use it as a trampoline to get back into the + * interrupt handler! + * + * R3 still contains the exit code, + * R6 VCPU_HOST_RETIP and + * R7 VCPU_HOST_MSR + */ + + mtlr r3 + + ld r5, VCPU_TRAMPOLINE_LOWMEM(r12) + mtsrr0 r5 + LOAD_REG_IMMEDIATE(r5, MSR_KERNEL & ~(MSR_IR | MSR_DR)) + mtsrr1 r5 + + RFI + +.global kvm_return_point +kvm_return_point: + + /* Jump back to lightweight entry if we're supposed to */ + /* go back into the guest */ + mr r5, r3 + /* Restore r3 (kvm_run) and r4 (vcpu) */ + REST_2GPRS(3, r1) + bl KVMPPC_HANDLE_EXIT + +#if 0 /* XXX get lightweight exits back */ + cmpwi r3, RESUME_GUEST + bne kvm_exit_heavyweight + + /* put VCPU and KVM_RUN back into place and roll again! */ + REST_2GPRS(3, r1) + b kvm_start_lightweight + +kvm_exit_heavyweight: + /* Restore non-volatile host registers */ + ld r14, _LINK(r1) + mtlr r14 + REST_NVGPRS(r1) + + addi r1, r1, SWITCH_FRAME_SIZE +#else + ld r4, _LINK(r1) + mtlr r4 + + cmpwi r3, RESUME_GUEST + bne kvm_exit_heavyweight + + REST_2GPRS(3, r1) + + addi r1, r1, SWITCH_FRAME_SIZE + + b kvm_start_entry + +kvm_exit_heavyweight: + + addi r1, r1, SWITCH_FRAME_SIZE +#endif + + blr diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c new file mode 100644 index 0000000000000000000000000000000000000000..5598f88f142e6332877e7a4a84947fbba93b9dc6 --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_mmu.c @@ -0,0 +1,478 @@ +/* + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright SUSE Linux Products GmbH 2009 + * + * Authors: Alexander Graf + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +/* #define DEBUG_MMU */ + +#ifdef DEBUG_MMU +#define dprintk(X...) printk(KERN_INFO X) +#else +#define dprintk(X...) do { } while(0) +#endif + +static void kvmppc_mmu_book3s_64_reset_msr(struct kvm_vcpu *vcpu) +{ + kvmppc_set_msr(vcpu, MSR_SF); +} + +static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe( + struct kvmppc_vcpu_book3s *vcpu_book3s, + gva_t eaddr) +{ + int i; + u64 esid = GET_ESID(eaddr); + u64 esid_1t = GET_ESID_1T(eaddr); + + for (i = 0; i < vcpu_book3s->slb_nr; i++) { + u64 cmp_esid = esid; + + if (!vcpu_book3s->slb[i].valid) + continue; + + if (vcpu_book3s->slb[i].large) + cmp_esid = esid_1t; + + if (vcpu_book3s->slb[i].esid == cmp_esid) + return &vcpu_book3s->slb[i]; + } + + dprintk("KVM: No SLB entry found for 0x%lx [%llx | %llx]\n", + eaddr, esid, esid_1t); + for (i = 0; i < vcpu_book3s->slb_nr; i++) { + if (vcpu_book3s->slb[i].vsid) + dprintk(" %d: %c%c %llx %llx\n", i, + vcpu_book3s->slb[i].valid ? 'v' : ' ', + vcpu_book3s->slb[i].large ? 'l' : ' ', + vcpu_book3s->slb[i].esid, + vcpu_book3s->slb[i].vsid); + } + + return NULL; +} + +static u64 kvmppc_mmu_book3s_64_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr, + bool data) +{ + struct kvmppc_slb *slb; + + slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), eaddr); + if (!slb) + return 0; + + if (slb->large) + return (((u64)eaddr >> 12) & 0xfffffff) | + (((u64)slb->vsid) << 28); + + return (((u64)eaddr >> 12) & 0xffff) | (((u64)slb->vsid) << 16); +} + +static int kvmppc_mmu_book3s_64_get_pagesize(struct kvmppc_slb *slbe) +{ + return slbe->large ? 24 : 12; +} + +static u32 kvmppc_mmu_book3s_64_get_page(struct kvmppc_slb *slbe, gva_t eaddr) +{ + int p = kvmppc_mmu_book3s_64_get_pagesize(slbe); + return ((eaddr & 0xfffffff) >> p); +} + +static hva_t kvmppc_mmu_book3s_64_get_pteg( + struct kvmppc_vcpu_book3s *vcpu_book3s, + struct kvmppc_slb *slbe, gva_t eaddr, + bool second) +{ + u64 hash, pteg, htabsize; + u32 page; + hva_t r; + + page = kvmppc_mmu_book3s_64_get_page(slbe, eaddr); + htabsize = ((1 << ((vcpu_book3s->sdr1 & 0x1f) + 11)) - 1); + + hash = slbe->vsid ^ page; + if (second) + hash = ~hash; + hash &= ((1ULL << 39ULL) - 1ULL); + hash &= htabsize; + hash <<= 7ULL; + + pteg = vcpu_book3s->sdr1 & 0xfffffffffffc0000ULL; + pteg |= hash; + + dprintk("MMU: page=0x%x sdr1=0x%llx pteg=0x%llx vsid=0x%llx\n", + page, vcpu_book3s->sdr1, pteg, slbe->vsid); + + r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT); + if (kvm_is_error_hva(r)) + return r; + return r | (pteg & ~PAGE_MASK); +} + +static u64 kvmppc_mmu_book3s_64_get_avpn(struct kvmppc_slb *slbe, gva_t eaddr) +{ + int p = kvmppc_mmu_book3s_64_get_pagesize(slbe); + u64 avpn; + + avpn = kvmppc_mmu_book3s_64_get_page(slbe, eaddr); + avpn |= slbe->vsid << (28 - p); + + if (p < 24) + avpn >>= ((80 - p) - 56) - 8; + else + avpn <<= 8; + + return avpn; +} + +static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, + struct kvmppc_pte *gpte, bool data) +{ + struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); + struct kvmppc_slb *slbe; + hva_t ptegp; + u64 pteg[16]; + u64 avpn = 0; + int i; + u8 key = 0; + bool found = false; + bool perm_err = false; + int second = 0; + + slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu_book3s, eaddr); + if (!slbe) + goto no_seg_found; + +do_second: + ptegp = kvmppc_mmu_book3s_64_get_pteg(vcpu_book3s, slbe, eaddr, second); + if (kvm_is_error_hva(ptegp)) + goto no_page_found; + + avpn = kvmppc_mmu_book3s_64_get_avpn(slbe, eaddr); + + if(copy_from_user(pteg, (void __user *)ptegp, sizeof(pteg))) { + printk(KERN_ERR "KVM can't copy data from 0x%lx!\n", ptegp); + goto no_page_found; + } + + if ((vcpu->arch.msr & MSR_PR) && slbe->Kp) + key = 4; + else if (!(vcpu->arch.msr & MSR_PR) && slbe->Ks) + key = 4; + + for (i=0; i<16; i+=2) { + u64 v = pteg[i]; + u64 r = pteg[i+1]; + + /* Valid check */ + if (!(v & HPTE_V_VALID)) + continue; + /* Hash check */ + if ((v & HPTE_V_SECONDARY) != second) + continue; + + /* AVPN compare */ + if (HPTE_V_AVPN_VAL(avpn) == HPTE_V_AVPN_VAL(v)) { + u8 pp = (r & HPTE_R_PP) | key; + int eaddr_mask = 0xFFF; + + gpte->eaddr = eaddr; + gpte->vpage = kvmppc_mmu_book3s_64_ea_to_vp(vcpu, + eaddr, + data); + if (slbe->large) + eaddr_mask = 0xFFFFFF; + gpte->raddr = (r & HPTE_R_RPN) | (eaddr & eaddr_mask); + gpte->may_execute = ((r & HPTE_R_N) ? false : true); + gpte->may_read = false; + gpte->may_write = false; + + switch (pp) { + case 0: + case 1: + case 2: + case 6: + gpte->may_write = true; + /* fall through */ + case 3: + case 5: + case 7: + gpte->may_read = true; + break; + } + + if (!gpte->may_read) { + perm_err = true; + continue; + } + + dprintk("KVM MMU: Translated 0x%lx [0x%llx] -> 0x%llx " + "-> 0x%llx\n", + eaddr, avpn, gpte->vpage, gpte->raddr); + found = true; + break; + } + } + + /* Update PTE R and C bits, so the guest's swapper knows we used the + * page */ + if (found) { + u32 oldr = pteg[i+1]; + + if (gpte->may_read) { + /* Set the accessed flag */ + pteg[i+1] |= HPTE_R_R; + } + if (gpte->may_write) { + /* Set the dirty flag */ + pteg[i+1] |= HPTE_R_C; + } else { + dprintk("KVM: Mapping read-only page!\n"); + } + + /* Write back into the PTEG */ + if (pteg[i+1] != oldr) + copy_to_user((void __user *)ptegp, pteg, sizeof(pteg)); + + return 0; + } else { + dprintk("KVM MMU: No PTE found (ea=0x%lx sdr1=0x%llx " + "ptegp=0x%lx)\n", + eaddr, to_book3s(vcpu)->sdr1, ptegp); + for (i = 0; i < 16; i += 2) + dprintk(" %02d: 0x%llx - 0x%llx (0x%llx)\n", + i, pteg[i], pteg[i+1], avpn); + + if (!second) { + second = HPTE_V_SECONDARY; + goto do_second; + } + } + + +no_page_found: + + + if (perm_err) + return -EPERM; + + return -ENOENT; + +no_seg_found: + + dprintk("KVM MMU: Trigger segment fault\n"); + return -EINVAL; +} + +static void kvmppc_mmu_book3s_64_slbmte(struct kvm_vcpu *vcpu, u64 rs, u64 rb) +{ + struct kvmppc_vcpu_book3s *vcpu_book3s; + u64 esid, esid_1t; + int slb_nr; + struct kvmppc_slb *slbe; + + dprintk("KVM MMU: slbmte(0x%llx, 0x%llx)\n", rs, rb); + + vcpu_book3s = to_book3s(vcpu); + + esid = GET_ESID(rb); + esid_1t = GET_ESID_1T(rb); + slb_nr = rb & 0xfff; + + if (slb_nr > vcpu_book3s->slb_nr) + return; + + slbe = &vcpu_book3s->slb[slb_nr]; + + slbe->large = (rs & SLB_VSID_L) ? 1 : 0; + slbe->esid = slbe->large ? esid_1t : esid; + slbe->vsid = rs >> 12; + slbe->valid = (rb & SLB_ESID_V) ? 1 : 0; + slbe->Ks = (rs & SLB_VSID_KS) ? 1 : 0; + slbe->Kp = (rs & SLB_VSID_KP) ? 1 : 0; + slbe->nx = (rs & SLB_VSID_N) ? 1 : 0; + slbe->class = (rs & SLB_VSID_C) ? 1 : 0; + + slbe->orige = rb & (ESID_MASK | SLB_ESID_V); + slbe->origv = rs; + + /* Map the new segment */ + kvmppc_mmu_map_segment(vcpu, esid << SID_SHIFT); +} + +static u64 kvmppc_mmu_book3s_64_slbmfee(struct kvm_vcpu *vcpu, u64 slb_nr) +{ + struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); + struct kvmppc_slb *slbe; + + if (slb_nr > vcpu_book3s->slb_nr) + return 0; + + slbe = &vcpu_book3s->slb[slb_nr]; + + return slbe->orige; +} + +static u64 kvmppc_mmu_book3s_64_slbmfev(struct kvm_vcpu *vcpu, u64 slb_nr) +{ + struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); + struct kvmppc_slb *slbe; + + if (slb_nr > vcpu_book3s->slb_nr) + return 0; + + slbe = &vcpu_book3s->slb[slb_nr]; + + return slbe->origv; +} + +static void kvmppc_mmu_book3s_64_slbie(struct kvm_vcpu *vcpu, u64 ea) +{ + struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); + struct kvmppc_slb *slbe; + + dprintk("KVM MMU: slbie(0x%llx)\n", ea); + + slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu_book3s, ea); + + if (!slbe) + return; + + dprintk("KVM MMU: slbie(0x%llx, 0x%llx)\n", ea, slbe->esid); + + slbe->valid = false; + + kvmppc_mmu_map_segment(vcpu, ea); +} + +static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu) +{ + struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); + int i; + + dprintk("KVM MMU: slbia()\n"); + + for (i = 1; i < vcpu_book3s->slb_nr; i++) + vcpu_book3s->slb[i].valid = false; + + if (vcpu->arch.msr & MSR_IR) { + kvmppc_mmu_flush_segments(vcpu); + kvmppc_mmu_map_segment(vcpu, vcpu->arch.pc); + } +} + +static void kvmppc_mmu_book3s_64_mtsrin(struct kvm_vcpu *vcpu, u32 srnum, + ulong value) +{ + u64 rb = 0, rs = 0; + + /* ESID = srnum */ + rb |= (srnum & 0xf) << 28; + /* Set the valid bit */ + rb |= 1 << 27; + /* Index = ESID */ + rb |= srnum; + + /* VSID = VSID */ + rs |= (value & 0xfffffff) << 12; + /* flags = flags */ + rs |= ((value >> 27) & 0xf) << 9; + + kvmppc_mmu_book3s_64_slbmte(vcpu, rs, rb); +} + +static void kvmppc_mmu_book3s_64_tlbie(struct kvm_vcpu *vcpu, ulong va, + bool large) +{ + u64 mask = 0xFFFFFFFFFULL; + + dprintk("KVM MMU: tlbie(0x%lx)\n", va); + + if (large) + mask = 0xFFFFFF000ULL; + kvmppc_mmu_pte_vflush(vcpu, va >> 12, mask); +} + +static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, u64 esid, + u64 *vsid) +{ + switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { + case 0: + *vsid = (VSID_REAL >> 16) | esid; + break; + case MSR_IR: + *vsid = (VSID_REAL_IR >> 16) | esid; + break; + case MSR_DR: + *vsid = (VSID_REAL_DR >> 16) | esid; + break; + case MSR_DR|MSR_IR: + { + ulong ea; + struct kvmppc_slb *slb; + ea = esid << SID_SHIFT; + slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea); + if (slb) + *vsid = slb->vsid; + else + return -ENOENT; + + break; + } + default: + BUG(); + break; + } + + return 0; +} + +static bool kvmppc_mmu_book3s_64_is_dcbz32(struct kvm_vcpu *vcpu) +{ + return (to_book3s(vcpu)->hid[5] & 0x80); +} + +void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu) +{ + struct kvmppc_mmu *mmu = &vcpu->arch.mmu; + + mmu->mfsrin = NULL; + mmu->mtsrin = kvmppc_mmu_book3s_64_mtsrin; + mmu->slbmte = kvmppc_mmu_book3s_64_slbmte; + mmu->slbmfee = kvmppc_mmu_book3s_64_slbmfee; + mmu->slbmfev = kvmppc_mmu_book3s_64_slbmfev; + mmu->slbie = kvmppc_mmu_book3s_64_slbie; + mmu->slbia = kvmppc_mmu_book3s_64_slbia; + mmu->xlate = kvmppc_mmu_book3s_64_xlate; + mmu->reset_msr = kvmppc_mmu_book3s_64_reset_msr; + mmu->tlbie = kvmppc_mmu_book3s_64_tlbie; + mmu->esid_to_vsid = kvmppc_mmu_book3s_64_esid_to_vsid; + mmu->ea_to_vp = kvmppc_mmu_book3s_64_ea_to_vp; + mmu->is_dcbz32 = kvmppc_mmu_book3s_64_is_dcbz32; + + vcpu->arch.hflags |= BOOK3S_HFLAG_SLB; +} diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c new file mode 100644 index 0000000000000000000000000000000000000000..f2899b297ffdc79181e82cfdc333261ec67df0c6 --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_mmu_host.c @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2009 SUSE Linux Products GmbH. All rights reserved. + * + * Authors: + * Alexander Graf + * Kevin Wolf + * + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#define PTE_SIZE 12 +#define VSID_ALL 0 + +/* #define DEBUG_MMU */ +/* #define DEBUG_SLB */ + +#ifdef DEBUG_MMU +#define dprintk_mmu(a, ...) printk(KERN_INFO a, __VA_ARGS__) +#else +#define dprintk_mmu(a, ...) do { } while(0) +#endif + +#ifdef DEBUG_SLB +#define dprintk_slb(a, ...) printk(KERN_INFO a, __VA_ARGS__) +#else +#define dprintk_slb(a, ...) do { } while(0) +#endif + +static void invalidate_pte(struct hpte_cache *pte) +{ + dprintk_mmu("KVM: Flushing SPT %d: 0x%llx (0x%llx) -> 0x%llx\n", + i, pte->pte.eaddr, pte->pte.vpage, pte->host_va); + + ppc_md.hpte_invalidate(pte->slot, pte->host_va, + MMU_PAGE_4K, MMU_SEGSIZE_256M, + false); + pte->host_va = 0; + kvm_release_pfn_dirty(pte->pfn); +} + +void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, u64 guest_ea, u64 ea_mask) +{ + int i; + + dprintk_mmu("KVM: Flushing %d Shadow PTEs: 0x%llx & 0x%llx\n", + vcpu->arch.hpte_cache_offset, guest_ea, ea_mask); + BUG_ON(vcpu->arch.hpte_cache_offset > HPTEG_CACHE_NUM); + + guest_ea &= ea_mask; + for (i = 0; i < vcpu->arch.hpte_cache_offset; i++) { + struct hpte_cache *pte; + + pte = &vcpu->arch.hpte_cache[i]; + if (!pte->host_va) + continue; + + if ((pte->pte.eaddr & ea_mask) == guest_ea) { + invalidate_pte(pte); + } + } + + /* Doing a complete flush -> start from scratch */ + if (!ea_mask) + vcpu->arch.hpte_cache_offset = 0; +} + +void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 guest_vp, u64 vp_mask) +{ + int i; + + dprintk_mmu("KVM: Flushing %d Shadow vPTEs: 0x%llx & 0x%llx\n", + vcpu->arch.hpte_cache_offset, guest_vp, vp_mask); + BUG_ON(vcpu->arch.hpte_cache_offset > HPTEG_CACHE_NUM); + + guest_vp &= vp_mask; + for (i = 0; i < vcpu->arch.hpte_cache_offset; i++) { + struct hpte_cache *pte; + + pte = &vcpu->arch.hpte_cache[i]; + if (!pte->host_va) + continue; + + if ((pte->pte.vpage & vp_mask) == guest_vp) { + invalidate_pte(pte); + } + } +} + +void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, u64 pa_start, u64 pa_end) +{ + int i; + + dprintk_mmu("KVM: Flushing %d Shadow pPTEs: 0x%llx & 0x%llx\n", + vcpu->arch.hpte_cache_offset, guest_pa, pa_mask); + BUG_ON(vcpu->arch.hpte_cache_offset > HPTEG_CACHE_NUM); + + for (i = 0; i < vcpu->arch.hpte_cache_offset; i++) { + struct hpte_cache *pte; + + pte = &vcpu->arch.hpte_cache[i]; + if (!pte->host_va) + continue; + + if ((pte->pte.raddr >= pa_start) && + (pte->pte.raddr < pa_end)) { + invalidate_pte(pte); + } + } +} + +struct kvmppc_pte *kvmppc_mmu_find_pte(struct kvm_vcpu *vcpu, u64 ea, bool data) +{ + int i; + u64 guest_vp; + + guest_vp = vcpu->arch.mmu.ea_to_vp(vcpu, ea, false); + for (i=0; iarch.hpte_cache_offset; i++) { + struct hpte_cache *pte; + + pte = &vcpu->arch.hpte_cache[i]; + if (!pte->host_va) + continue; + + if (pte->pte.vpage == guest_vp) + return &pte->pte; + } + + return NULL; +} + +static int kvmppc_mmu_hpte_cache_next(struct kvm_vcpu *vcpu) +{ + if (vcpu->arch.hpte_cache_offset == HPTEG_CACHE_NUM) + kvmppc_mmu_pte_flush(vcpu, 0, 0); + + return vcpu->arch.hpte_cache_offset++; +} + +/* We keep 512 gvsid->hvsid entries, mapping the guest ones to the array using + * a hash, so we don't waste cycles on looping */ +static u16 kvmppc_sid_hash(struct kvm_vcpu *vcpu, u64 gvsid) +{ + return (u16)(((gvsid >> (SID_MAP_BITS * 7)) & SID_MAP_MASK) ^ + ((gvsid >> (SID_MAP_BITS * 6)) & SID_MAP_MASK) ^ + ((gvsid >> (SID_MAP_BITS * 5)) & SID_MAP_MASK) ^ + ((gvsid >> (SID_MAP_BITS * 4)) & SID_MAP_MASK) ^ + ((gvsid >> (SID_MAP_BITS * 3)) & SID_MAP_MASK) ^ + ((gvsid >> (SID_MAP_BITS * 2)) & SID_MAP_MASK) ^ + ((gvsid >> (SID_MAP_BITS * 1)) & SID_MAP_MASK) ^ + ((gvsid >> (SID_MAP_BITS * 0)) & SID_MAP_MASK)); +} + + +static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid) +{ + struct kvmppc_sid_map *map; + u16 sid_map_mask; + + if (vcpu->arch.msr & MSR_PR) + gvsid |= VSID_PR; + + sid_map_mask = kvmppc_sid_hash(vcpu, gvsid); + map = &to_book3s(vcpu)->sid_map[sid_map_mask]; + if (map->guest_vsid == gvsid) { + dprintk_slb("SLB: Searching 0x%llx -> 0x%llx\n", + gvsid, map->host_vsid); + return map; + } + + map = &to_book3s(vcpu)->sid_map[SID_MAP_MASK - sid_map_mask]; + if (map->guest_vsid == gvsid) { + dprintk_slb("SLB: Searching 0x%llx -> 0x%llx\n", + gvsid, map->host_vsid); + return map; + } + + dprintk_slb("SLB: Searching 0x%llx -> not found\n", gvsid); + return NULL; +} + +int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte) +{ + pfn_t hpaddr; + ulong hash, hpteg, va; + u64 vsid; + int ret; + int rflags = 0x192; + int vflags = 0; + int attempt = 0; + struct kvmppc_sid_map *map; + + /* Get host physical address for gpa */ + hpaddr = gfn_to_pfn(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT); + if (kvm_is_error_hva(hpaddr)) { + printk(KERN_INFO "Couldn't get guest page for gfn %llx!\n", orig_pte->eaddr); + return -EINVAL; + } + hpaddr <<= PAGE_SHIFT; +#if PAGE_SHIFT == 12 +#elif PAGE_SHIFT == 16 + hpaddr |= orig_pte->raddr & 0xf000; +#else +#error Unknown page size +#endif + + /* and write the mapping ea -> hpa into the pt */ + vcpu->arch.mmu.esid_to_vsid(vcpu, orig_pte->eaddr >> SID_SHIFT, &vsid); + map = find_sid_vsid(vcpu, vsid); + if (!map) { + kvmppc_mmu_map_segment(vcpu, orig_pte->eaddr); + map = find_sid_vsid(vcpu, vsid); + } + BUG_ON(!map); + + vsid = map->host_vsid; + va = hpt_va(orig_pte->eaddr, vsid, MMU_SEGSIZE_256M); + + if (!orig_pte->may_write) + rflags |= HPTE_R_PP; + else + mark_page_dirty(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT); + + if (!orig_pte->may_execute) + rflags |= HPTE_R_N; + + hash = hpt_hash(va, PTE_SIZE, MMU_SEGSIZE_256M); + +map_again: + hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); + + /* In case we tried normal mapping already, let's nuke old entries */ + if (attempt > 1) + if (ppc_md.hpte_remove(hpteg) < 0) + return -1; + + ret = ppc_md.hpte_insert(hpteg, va, hpaddr, rflags, vflags, MMU_PAGE_4K, MMU_SEGSIZE_256M); + + if (ret < 0) { + /* If we couldn't map a primary PTE, try a secondary */ +#ifdef USE_SECONDARY + hash = ~hash; + attempt++; + if (attempt % 2) + vflags = HPTE_V_SECONDARY; + else + vflags = 0; +#else + attempt = 2; +#endif + goto map_again; + } else { + int hpte_id = kvmppc_mmu_hpte_cache_next(vcpu); + struct hpte_cache *pte = &vcpu->arch.hpte_cache[hpte_id]; + + dprintk_mmu("KVM: %c%c Map 0x%llx: [%lx] 0x%lx (0x%llx) -> %lx\n", + ((rflags & HPTE_R_PP) == 3) ? '-' : 'w', + (rflags & HPTE_R_N) ? '-' : 'x', + orig_pte->eaddr, hpteg, va, orig_pte->vpage, hpaddr); + + pte->slot = hpteg + (ret & 7); + pte->host_va = va; + pte->pte = *orig_pte; + pte->pfn = hpaddr >> PAGE_SHIFT; + } + + return 0; +} + +static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid) +{ + struct kvmppc_sid_map *map; + struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); + u16 sid_map_mask; + static int backwards_map = 0; + + if (vcpu->arch.msr & MSR_PR) + gvsid |= VSID_PR; + + /* We might get collisions that trap in preceding order, so let's + map them differently */ + + sid_map_mask = kvmppc_sid_hash(vcpu, gvsid); + if (backwards_map) + sid_map_mask = SID_MAP_MASK - sid_map_mask; + + map = &to_book3s(vcpu)->sid_map[sid_map_mask]; + + /* Make sure we're taking the other map next time */ + backwards_map = !backwards_map; + + /* Uh-oh ... out of mappings. Let's flush! */ + if (vcpu_book3s->vsid_next == vcpu_book3s->vsid_max) { + vcpu_book3s->vsid_next = vcpu_book3s->vsid_first; + memset(vcpu_book3s->sid_map, 0, + sizeof(struct kvmppc_sid_map) * SID_MAP_NUM); + kvmppc_mmu_pte_flush(vcpu, 0, 0); + kvmppc_mmu_flush_segments(vcpu); + } + map->host_vsid = vcpu_book3s->vsid_next++; + + map->guest_vsid = gvsid; + map->valid = true; + + return map; +} + +static int kvmppc_mmu_next_segment(struct kvm_vcpu *vcpu, ulong esid) +{ + int i; + int max_slb_size = 64; + int found_inval = -1; + int r; + + if (!get_paca()->kvm_slb_max) + get_paca()->kvm_slb_max = 1; + + /* Are we overwriting? */ + for (i = 1; i < get_paca()->kvm_slb_max; i++) { + if (!(get_paca()->kvm_slb[i].esid & SLB_ESID_V)) + found_inval = i; + else if ((get_paca()->kvm_slb[i].esid & ESID_MASK) == esid) + return i; + } + + /* Found a spare entry that was invalidated before */ + if (found_inval > 0) + return found_inval; + + /* No spare invalid entry, so create one */ + + if (mmu_slb_size < 64) + max_slb_size = mmu_slb_size; + + /* Overflowing -> purge */ + if ((get_paca()->kvm_slb_max) == max_slb_size) + kvmppc_mmu_flush_segments(vcpu); + + r = get_paca()->kvm_slb_max; + get_paca()->kvm_slb_max++; + + return r; +} + +int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr) +{ + u64 esid = eaddr >> SID_SHIFT; + u64 slb_esid = (eaddr & ESID_MASK) | SLB_ESID_V; + u64 slb_vsid = SLB_VSID_USER; + u64 gvsid; + int slb_index; + struct kvmppc_sid_map *map; + + slb_index = kvmppc_mmu_next_segment(vcpu, eaddr & ESID_MASK); + + if (vcpu->arch.mmu.esid_to_vsid(vcpu, esid, &gvsid)) { + /* Invalidate an entry */ + get_paca()->kvm_slb[slb_index].esid = 0; + return -ENOENT; + } + + map = find_sid_vsid(vcpu, gvsid); + if (!map) + map = create_sid_map(vcpu, gvsid); + + map->guest_esid = esid; + + slb_vsid |= (map->host_vsid << 12); + slb_vsid &= ~SLB_VSID_KP; + slb_esid |= slb_index; + + get_paca()->kvm_slb[slb_index].esid = slb_esid; + get_paca()->kvm_slb[slb_index].vsid = slb_vsid; + + dprintk_slb("slbmte %#llx, %#llx\n", slb_vsid, slb_esid); + + return 0; +} + +void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu) +{ + get_paca()->kvm_slb_max = 1; + get_paca()->kvm_slb[0].esid = 0; +} + +void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) +{ + kvmppc_mmu_pte_flush(vcpu, 0, 0); +} diff --git a/arch/powerpc/kvm/book3s_64_rmhandlers.S b/arch/powerpc/kvm/book3s_64_rmhandlers.S new file mode 100644 index 0000000000000000000000000000000000000000..fb7dd2e9ac8863fdfc48be3088cd73dcb6337df4 --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_rmhandlers.S @@ -0,0 +1,131 @@ +/* + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright SUSE Linux Products GmbH 2009 + * + * Authors: Alexander Graf + */ + +#include +#include +#include +#include +#include +#include + +/***************************************************************************** + * * + * Real Mode handlers that need to be in low physical memory * + * * + ****************************************************************************/ + + +.macro INTERRUPT_TRAMPOLINE intno + +.global kvmppc_trampoline_\intno +kvmppc_trampoline_\intno: + + mtspr SPRN_SPRG_SCRATCH0, r13 /* Save r13 */ + + /* + * First thing to do is to find out if we're coming + * from a KVM guest or a Linux process. + * + * To distinguish, we check a magic byte in the PACA + */ + mfspr r13, SPRN_SPRG_PACA /* r13 = PACA */ + std r12, (PACA_EXMC + EX_R12)(r13) + mfcr r12 + stw r12, (PACA_EXMC + EX_CCR)(r13) + lbz r12, PACA_KVM_IN_GUEST(r13) + cmpwi r12, 0 + bne ..kvmppc_handler_hasmagic_\intno + /* No KVM guest? Then jump back to the Linux handler! */ + lwz r12, (PACA_EXMC + EX_CCR)(r13) + mtcr r12 + ld r12, (PACA_EXMC + EX_R12)(r13) + mfspr r13, SPRN_SPRG_SCRATCH0 /* r13 = original r13 */ + b kvmppc_resume_\intno /* Get back original handler */ + + /* Now we know we're handling a KVM guest */ +..kvmppc_handler_hasmagic_\intno: + /* Unset guest state */ + li r12, 0 + stb r12, PACA_KVM_IN_GUEST(r13) + + std r1, (PACA_EXMC+EX_R9)(r13) + std r10, (PACA_EXMC+EX_R10)(r13) + std r11, (PACA_EXMC+EX_R11)(r13) + std r2, (PACA_EXMC+EX_R13)(r13) + + mfsrr0 r10 + mfsrr1 r11 + + /* Restore R1/R2 so we can handle faults */ + ld r1, PACAR1(r13) + ld r2, (PACA_EXMC+EX_SRR0)(r13) + + /* Let's store which interrupt we're handling */ + li r12, \intno + + /* Jump into the SLB exit code that goes to the highmem handler */ + b kvmppc_handler_trampoline_exit + +.endm + +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_SYSTEM_RESET +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_MACHINE_CHECK +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_DATA_STORAGE +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_DATA_SEGMENT +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_INST_STORAGE +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_INST_SEGMENT +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_EXTERNAL +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_ALIGNMENT +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_PROGRAM +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_FP_UNAVAIL +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_DECREMENTER +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_SYSCALL +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_TRACE +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_PERFMON +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_ALTIVEC +INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_VSX + +/* + * This trampoline brings us back to a real mode handler + * + * Input Registers: + * + * R6 = SRR0 + * R7 = SRR1 + * LR = real-mode IP + * + */ +.global kvmppc_handler_lowmem_trampoline +kvmppc_handler_lowmem_trampoline: + + mtsrr0 r6 + mtsrr1 r7 + blr +kvmppc_handler_lowmem_trampoline_end: + +.global kvmppc_trampoline_lowmem +kvmppc_trampoline_lowmem: + .long kvmppc_handler_lowmem_trampoline - _stext + +.global kvmppc_trampoline_enter +kvmppc_trampoline_enter: + .long kvmppc_handler_trampoline_enter - _stext + +#include "book3s_64_slb.S" + diff --git a/arch/powerpc/kvm/book3s_64_slb.S b/arch/powerpc/kvm/book3s_64_slb.S new file mode 100644 index 0000000000000000000000000000000000000000..ecd237a03fd0be4fb6ec8f853a520ca5f7e0016e --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_slb.S @@ -0,0 +1,262 @@ +/* + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright SUSE Linux Products GmbH 2009 + * + * Authors: Alexander Graf + */ + +#define SHADOW_SLB_ESID(num) (SLBSHADOW_SAVEAREA + (num * 0x10)) +#define SHADOW_SLB_VSID(num) (SLBSHADOW_SAVEAREA + (num * 0x10) + 0x8) +#define UNBOLT_SLB_ENTRY(num) \ + ld r9, SHADOW_SLB_ESID(num)(r12); \ + /* Invalid? Skip. */; \ + rldicl. r0, r9, 37, 63; \ + beq slb_entry_skip_ ## num; \ + xoris r9, r9, SLB_ESID_V@h; \ + std r9, SHADOW_SLB_ESID(num)(r12); \ + slb_entry_skip_ ## num: + +#define REBOLT_SLB_ENTRY(num) \ + ld r10, SHADOW_SLB_ESID(num)(r11); \ + cmpdi r10, 0; \ + beq slb_exit_skip_1; \ + oris r10, r10, SLB_ESID_V@h; \ + ld r9, SHADOW_SLB_VSID(num)(r11); \ + slbmte r9, r10; \ + std r10, SHADOW_SLB_ESID(num)(r11); \ +slb_exit_skip_ ## num: + +/****************************************************************************** + * * + * Entry code * + * * + *****************************************************************************/ + +.global kvmppc_handler_trampoline_enter +kvmppc_handler_trampoline_enter: + + /* Required state: + * + * MSR = ~IR|DR + * R13 = PACA + * R9 = guest IP + * R10 = guest MSR + * R11 = free + * R12 = free + * PACA[PACA_EXMC + EX_R9] = guest R9 + * PACA[PACA_EXMC + EX_R10] = guest R10 + * PACA[PACA_EXMC + EX_R11] = guest R11 + * PACA[PACA_EXMC + EX_R12] = guest R12 + * PACA[PACA_EXMC + EX_R13] = guest R13 + * PACA[PACA_EXMC + EX_CCR] = guest CR + * PACA[PACA_EXMC + EX_R3] = guest XER + */ + + mtsrr0 r9 + mtsrr1 r10 + + mtspr SPRN_SPRG_SCRATCH0, r0 + + /* Remove LPAR shadow entries */ + +#if SLB_NUM_BOLTED == 3 + + ld r12, PACA_SLBSHADOWPTR(r13) + + /* Save off the first entry so we can slbie it later */ + ld r10, SHADOW_SLB_ESID(0)(r12) + ld r11, SHADOW_SLB_VSID(0)(r12) + + /* Remove bolted entries */ + UNBOLT_SLB_ENTRY(0) + UNBOLT_SLB_ENTRY(1) + UNBOLT_SLB_ENTRY(2) + +#else +#error unknown number of bolted entries +#endif + + /* Flush SLB */ + + slbia + + /* r0 = esid & ESID_MASK */ + rldicr r10, r10, 0, 35 + /* r0 |= CLASS_BIT(VSID) */ + rldic r12, r11, 56 - 36, 36 + or r10, r10, r12 + slbie r10 + + isync + + /* Fill SLB with our shadow */ + + lbz r12, PACA_KVM_SLB_MAX(r13) + mulli r12, r12, 16 + addi r12, r12, PACA_KVM_SLB + add r12, r12, r13 + + /* for (r11 = kvm_slb; r11 < kvm_slb + kvm_slb_size; r11+=slb_entry) */ + li r11, PACA_KVM_SLB + add r11, r11, r13 + +slb_loop_enter: + + ld r10, 0(r11) + + rldicl. r0, r10, 37, 63 + beq slb_loop_enter_skip + + ld r9, 8(r11) + slbmte r9, r10 + +slb_loop_enter_skip: + addi r11, r11, 16 + cmpd cr0, r11, r12 + blt slb_loop_enter + +slb_do_enter: + + /* Enter guest */ + + mfspr r0, SPRN_SPRG_SCRATCH0 + + ld r9, (PACA_EXMC+EX_R9)(r13) + ld r10, (PACA_EXMC+EX_R10)(r13) + ld r12, (PACA_EXMC+EX_R12)(r13) + + lwz r11, (PACA_EXMC+EX_CCR)(r13) + mtcr r11 + + ld r11, (PACA_EXMC+EX_R3)(r13) + mtxer r11 + + ld r11, (PACA_EXMC+EX_R11)(r13) + ld r13, (PACA_EXMC+EX_R13)(r13) + + RFI +kvmppc_handler_trampoline_enter_end: + + + +/****************************************************************************** + * * + * Exit code * + * * + *****************************************************************************/ + +.global kvmppc_handler_trampoline_exit +kvmppc_handler_trampoline_exit: + + /* Register usage at this point: + * + * SPRG_SCRATCH0 = guest R13 + * R01 = host R1 + * R02 = host R2 + * R10 = guest PC + * R11 = guest MSR + * R12 = exit handler id + * R13 = PACA + * PACA.exmc.CCR = guest CR + * PACA.exmc.R9 = guest R1 + * PACA.exmc.R10 = guest R10 + * PACA.exmc.R11 = guest R11 + * PACA.exmc.R12 = guest R12 + * PACA.exmc.R13 = guest R2 + * + */ + + /* Save registers */ + + std r0, (PACA_EXMC+EX_SRR0)(r13) + std r9, (PACA_EXMC+EX_R3)(r13) + std r10, (PACA_EXMC+EX_LR)(r13) + std r11, (PACA_EXMC+EX_DAR)(r13) + + /* + * In order for us to easily get the last instruction, + * we got the #vmexit at, we exploit the fact that the + * virtual layout is still the same here, so we can just + * ld from the guest's PC address + */ + + /* We only load the last instruction when it's safe */ + cmpwi r12, BOOK3S_INTERRUPT_DATA_STORAGE + beq ld_last_inst + cmpwi r12, BOOK3S_INTERRUPT_PROGRAM + beq ld_last_inst + + b no_ld_last_inst + +ld_last_inst: + /* Save off the guest instruction we're at */ + /* 1) enable paging for data */ + mfmsr r9 + ori r11, r9, MSR_DR /* Enable paging for data */ + mtmsr r11 + /* 2) fetch the instruction */ + lwz r0, 0(r10) + /* 3) disable paging again */ + mtmsr r9 + +no_ld_last_inst: + + /* Restore bolted entries from the shadow and fix it along the way */ + + /* We don't store anything in entry 0, so we don't need to take care of it */ + slbia + isync + +#if SLB_NUM_BOLTED == 3 + + ld r11, PACA_SLBSHADOWPTR(r13) + + REBOLT_SLB_ENTRY(0) + REBOLT_SLB_ENTRY(1) + REBOLT_SLB_ENTRY(2) + +#else +#error unknown number of bolted entries +#endif + +slb_do_exit: + + /* Restore registers */ + + ld r11, (PACA_EXMC+EX_DAR)(r13) + ld r10, (PACA_EXMC+EX_LR)(r13) + ld r9, (PACA_EXMC+EX_R3)(r13) + + /* Save last inst */ + stw r0, (PACA_EXMC+EX_LR)(r13) + + /* Save DAR and DSISR before going to paged mode */ + mfdar r0 + std r0, (PACA_EXMC+EX_DAR)(r13) + mfdsisr r0 + stw r0, (PACA_EXMC+EX_DSISR)(r13) + + /* RFI into the highmem handler */ + mfmsr r0 + ori r0, r0, MSR_IR|MSR_DR|MSR_RI /* Enable paging */ + mtsrr1 r0 + ld r0, PACASAVEDMSR(r13) /* Highmem handler address */ + mtsrr0 r0 + + mfspr r0, SPRN_SPRG_SCRATCH0 + + RFI +kvmppc_handler_trampoline_exit_end: + diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index e7bf4d029484df334b2c1a60df6a1559b1932769..06f5a9ecc42c9fc950666b44a177b7eadeb668ed 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -520,6 +520,11 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, return kvmppc_core_vcpu_translate(vcpu, tr); } +int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) +{ + return -ENOTSUPP; +} + int __init kvmppc_booke_init(void) { unsigned long ivor[16]; diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index 7737146af3fb4c181a188c479786f8349a02c9ca..4a9ac6640fadb93182d9ade73310f1af1e0c4b93 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c @@ -18,7 +18,7 @@ */ #include -#include +#include #include #include #include @@ -32,6 +32,7 @@ #include "trace.h" #define OP_TRAP 3 +#define OP_TRAP_64 2 #define OP_31_XOP_LWZX 23 #define OP_31_XOP_LBZX 87 @@ -64,19 +65,45 @@ #define OP_STH 44 #define OP_STHU 45 +#ifdef CONFIG_PPC64 +static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu) +{ + return 1; +} +#else +static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.tcr & TCR_DIE; +} +#endif + void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) { - if (vcpu->arch.tcr & TCR_DIE) { + unsigned long dec_nsec; + + pr_debug("mtDEC: %x\n", vcpu->arch.dec); +#ifdef CONFIG_PPC64 + /* POWER4+ triggers a dec interrupt if the value is < 0 */ + if (vcpu->arch.dec & 0x80000000) { + hrtimer_try_to_cancel(&vcpu->arch.dec_timer); + kvmppc_core_queue_dec(vcpu); + return; + } +#endif + if (kvmppc_dec_enabled(vcpu)) { /* The decrementer ticks at the same rate as the timebase, so * that's how we convert the guest DEC value to the number of * host ticks. */ - unsigned long nr_jiffies; - nr_jiffies = vcpu->arch.dec / tb_ticks_per_jiffy; - mod_timer(&vcpu->arch.dec_timer, - get_jiffies_64() + nr_jiffies); + hrtimer_try_to_cancel(&vcpu->arch.dec_timer); + dec_nsec = vcpu->arch.dec; + dec_nsec *= 1000; + dec_nsec /= tb_ticks_per_usec; + hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec), + HRTIMER_MODE_REL); + vcpu->arch.dec_jiffies = get_tb(); } else { - del_timer(&vcpu->arch.dec_timer); + hrtimer_try_to_cancel(&vcpu->arch.dec_timer); } } @@ -111,9 +138,15 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) /* this default type might be overwritten by subcategories */ kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); + pr_debug(KERN_INFO "Emulating opcode %d / %d\n", get_op(inst), get_xop(inst)); + switch (get_op(inst)) { case OP_TRAP: +#ifdef CONFIG_PPC64 + case OP_TRAP_64: +#else vcpu->arch.esr |= ESR_PTR; +#endif kvmppc_core_queue_program(vcpu); advance = 0; break; @@ -188,17 +221,19 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) case SPRN_SRR1: vcpu->arch.gpr[rt] = vcpu->arch.srr1; break; case SPRN_PVR: - vcpu->arch.gpr[rt] = mfspr(SPRN_PVR); break; + vcpu->arch.gpr[rt] = vcpu->arch.pvr; break; case SPRN_PIR: - vcpu->arch.gpr[rt] = mfspr(SPRN_PIR); break; + vcpu->arch.gpr[rt] = vcpu->vcpu_id; break; + case SPRN_MSSSR0: + vcpu->arch.gpr[rt] = 0; break; /* Note: mftb and TBRL/TBWL are user-accessible, so * the guest can always access the real TB anyways. * In fact, we probably will never see these traps. */ case SPRN_TBWL: - vcpu->arch.gpr[rt] = mftbl(); break; + vcpu->arch.gpr[rt] = get_tb() >> 32; break; case SPRN_TBWU: - vcpu->arch.gpr[rt] = mftbu(); break; + vcpu->arch.gpr[rt] = get_tb(); break; case SPRN_SPRG0: vcpu->arch.gpr[rt] = vcpu->arch.sprg0; break; @@ -211,6 +246,13 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) /* Note: SPRG4-7 are user-readable, so we don't get * a trap. */ + case SPRN_DEC: + { + u64 jd = get_tb() - vcpu->arch.dec_jiffies; + vcpu->arch.gpr[rt] = vcpu->arch.dec - jd; + pr_debug(KERN_INFO "mfDEC: %x - %llx = %lx\n", vcpu->arch.dec, jd, vcpu->arch.gpr[rt]); + break; + } default: emulated = kvmppc_core_emulate_mfspr(vcpu, sprn, rt); if (emulated == EMULATE_FAIL) { @@ -260,6 +302,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) case SPRN_TBWL: break; case SPRN_TBWU: break; + case SPRN_MSSSR0: break; + case SPRN_DEC: vcpu->arch.dec = vcpu->arch.gpr[rs]; kvmppc_emulate_dec(vcpu); diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 5902bbc2411e7db65097d006666254c9bc2b4edd..f06cf93b178ec2d037a39eeee202b567a42d6eb2 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -144,6 +145,9 @@ int kvm_dev_ioctl_check_extension(long ext) int r; switch (ext) { + case KVM_CAP_PPC_SEGSTATE: + r = 1; + break; case KVM_CAP_COALESCED_MMIO: r = KVM_COALESCED_MMIO_PAGE_OFFSET; break; @@ -209,10 +213,25 @@ static void kvmppc_decrementer_func(unsigned long data) } } +/* + * low level hrtimer wake routine. Because this runs in hardirq context + * we schedule a tasklet to do the real work. + */ +enum hrtimer_restart kvmppc_decrementer_wakeup(struct hrtimer *timer) +{ + struct kvm_vcpu *vcpu; + + vcpu = container_of(timer, struct kvm_vcpu, arch.dec_timer); + tasklet_schedule(&vcpu->arch.tasklet); + + return HRTIMER_NORESTART; +} + int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) { - setup_timer(&vcpu->arch.dec_timer, kvmppc_decrementer_func, - (unsigned long)vcpu); + hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); + tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu); + vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup; return 0; } @@ -410,11 +429,6 @@ out: return r; } -int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) -{ - return -ENOTSUPP; -} - long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { diff --git a/arch/powerpc/kvm/timing.c b/arch/powerpc/kvm/timing.c index 2aa371e30079ced2c7938133b355ae7ca54b7343..70378551c0cc1b0096383ba89b314a963654de1d 100644 --- a/arch/powerpc/kvm/timing.c +++ b/arch/powerpc/kvm/timing.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include diff --git a/arch/powerpc/kvm/trace.h b/arch/powerpc/kvm/trace.h index 67f219de04558e3abd15a249e94c8c4d4470bcc0..a8e8400180525b4e9a0c6894ddc100b286140626 100644 --- a/arch/powerpc/kvm/trace.h +++ b/arch/powerpc/kvm/trace.h @@ -12,8 +12,8 @@ * Tracepoint for guest mode entry. */ TRACE_EVENT(kvm_ppc_instr, - TP_PROTO(unsigned int inst, unsigned long pc, unsigned int emulate), - TP_ARGS(inst, pc, emulate), + TP_PROTO(unsigned int inst, unsigned long _pc, unsigned int emulate), + TP_ARGS(inst, _pc, emulate), TP_STRUCT__entry( __field( unsigned int, inst ) @@ -23,7 +23,7 @@ TRACE_EVENT(kvm_ppc_instr, TP_fast_assign( __entry->inst = inst; - __entry->pc = pc; + __entry->pc = _pc; __entry->emulate = emulate; ), diff --git a/arch/powerpc/lib/copy_32.S b/arch/powerpc/lib/copy_32.S index c657de59abca8c8dfd48417e12ecb49c3fd75c53..74a7f4130b4ce5ed34b797227568fa86545650b7 100644 --- a/arch/powerpc/lib/copy_32.S +++ b/arch/powerpc/lib/copy_32.S @@ -98,20 +98,7 @@ _GLOBAL(cacheable_memzero) bdnz 4b 3: mtctr r9 li r7,4 -#if !defined(CONFIG_8xx) 10: dcbz r7,r6 -#else -10: stw r4, 4(r6) - stw r4, 8(r6) - stw r4, 12(r6) - stw r4, 16(r6) -#if CACHE_LINE_SIZE >= 32 - stw r4, 20(r6) - stw r4, 24(r6) - stw r4, 28(r6) - stw r4, 32(r6) -#endif /* CACHE_LINE_SIZE */ -#endif addi r6,r6,CACHELINE_BYTES bdnz 10b clrlwi r5,r8,32-LG_CACHELINE_BYTES @@ -200,9 +187,7 @@ _GLOBAL(cacheable_memcpy) mtctr r0 beq 63f 53: -#if !defined(CONFIG_8xx) dcbz r11,r6 -#endif COPY_16_BYTES #if L1_CACHE_BYTES >= 32 COPY_16_BYTES @@ -356,14 +341,6 @@ _GLOBAL(__copy_tofrom_user) li r11,4 beq 63f -#ifdef CONFIG_8xx - /* Don't use prefetch on 8xx */ - mtctr r0 - li r0,0 -53: COPY_16_BYTES_WITHEX(0) - bdnz 53b - -#else /* not CONFIG_8xx */ /* Here we decide how far ahead to prefetch the source */ li r3,4 cmpwi r0,1 @@ -416,7 +393,6 @@ _GLOBAL(__copy_tofrom_user) li r3,4 li r7,0 bne 114b -#endif /* CONFIG_8xx */ 63: srwi. r0,r5,2 mtctr r0 diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 6fb8fc8d2feafb9993ccc3f7457d0ff76e1f2587..ce68708bbad53c016986eabf7dfe2ef08ba33a97 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile @@ -28,7 +28,10 @@ obj-$(CONFIG_44x) += 44x_mmu.o obj-$(CONFIG_FSL_BOOKE) += fsl_booke_mmu.o obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o obj-$(CONFIG_PPC_MM_SLICES) += slice.o -obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o +ifeq ($(CONFIG_HUGETLB_PAGE),y) +obj-y += hugetlbpage.o +obj-$(CONFIG_PPC_STD_MMU_64) += hugetlbpage-hash64.o +endif obj-$(CONFIG_PPC_SUBPAGE_PROT) += subpage-prot.o obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o obj-$(CONFIG_HIGHMEM) += highmem.o diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index e7dae82c12858162e25a0c1f1860235046fb16dc..26fb6b990b0a78704642e9e5999aed2dd3b6b945 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -40,7 +40,7 @@ #include #include #include - +#include #ifdef CONFIG_KPROBES static inline int notify_page_fault(struct pt_regs *regs) @@ -246,6 +246,12 @@ good_area: goto bad_area; #endif /* CONFIG_6xx */ #if defined(CONFIG_8xx) + /* 8xx sometimes need to load a invalid/non-present TLBs. + * These must be invalidated separately as linux mm don't. + */ + if (error_code & 0x40000000) /* no translation? */ + _tlbil_va(address, 0, 0, 0); + /* The MPC8xx seems to always set 0x80000000, which is * "undefined". Of those that can be set, this is the only * one which seems bad. diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index dc93e95b256eae04e248900e82858d94c8fe822a..fcfcb6e976c72c7a8da1b8d31aac474e08985282 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c @@ -54,26 +54,35 @@ #include "mmu_decl.h" -extern void loadcam_entry(unsigned int index); unsigned int tlbcam_index; -static unsigned long cam[CONFIG_LOWMEM_CAM_NUM]; -#define NUM_TLBCAMS (16) +#define NUM_TLBCAMS (64) #if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS) #error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS" #endif -struct tlbcam TLBCAM[NUM_TLBCAMS]; +struct tlbcam { + u32 MAS0; + u32 MAS1; + unsigned long MAS2; + u32 MAS3; + u32 MAS7; +} TLBCAM[NUM_TLBCAMS]; struct tlbcamrange { - unsigned long start; + unsigned long start; unsigned long limit; phys_addr_t phys; } tlbcam_addrs[NUM_TLBCAMS]; extern unsigned int tlbcam_index; +unsigned long tlbcam_sz(int idx) +{ + return tlbcam_addrs[idx].limit - tlbcam_addrs[idx].start + 1; +} + /* * Return PA for this VA if it is mapped by a CAM, or 0 */ @@ -94,23 +103,36 @@ unsigned long p_mapped_by_tlbcam(phys_addr_t pa) int b; for (b = 0; b < tlbcam_index; ++b) if (pa >= tlbcam_addrs[b].phys - && pa < (tlbcam_addrs[b].limit-tlbcam_addrs[b].start) + && pa < (tlbcam_addrs[b].limit-tlbcam_addrs[b].start) +tlbcam_addrs[b].phys) return tlbcam_addrs[b].start+(pa-tlbcam_addrs[b].phys); return 0; } +void loadcam_entry(int idx) +{ + mtspr(SPRN_MAS0, TLBCAM[idx].MAS0); + mtspr(SPRN_MAS1, TLBCAM[idx].MAS1); + mtspr(SPRN_MAS2, TLBCAM[idx].MAS2); + mtspr(SPRN_MAS3, TLBCAM[idx].MAS3); + + if (cur_cpu_spec->cpu_features & MMU_FTR_BIG_PHYS) + mtspr(SPRN_MAS7, TLBCAM[idx].MAS7); + + asm volatile("isync;tlbwe;isync" : : : "memory"); +} + /* * Set up one of the I/D BAT (block address translation) register pairs. * The parameters are not checked; in particular size must be a power * of 4 between 4k and 256M. */ -void settlbcam(int index, unsigned long virt, phys_addr_t phys, - unsigned int size, int flags, unsigned int pid) +static void settlbcam(int index, unsigned long virt, phys_addr_t phys, + unsigned long size, unsigned long flags, unsigned int pid) { unsigned int tsize, lz; - asm ("cntlzw %0,%1" : "=r" (lz) : "r" (size)); + asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (size)); tsize = 21 - lz; #ifdef CONFIG_SMP @@ -128,8 +150,10 @@ void settlbcam(int index, unsigned long virt, phys_addr_t phys, TLBCAM[index].MAS2 |= (flags & _PAGE_GUARDED) ? MAS2_G : 0; TLBCAM[index].MAS2 |= (flags & _PAGE_ENDIAN) ? MAS2_E : 0; - TLBCAM[index].MAS3 = (phys & PAGE_MASK) | MAS3_SX | MAS3_SR; + TLBCAM[index].MAS3 = (phys & MAS3_RPN) | MAS3_SX | MAS3_SR; TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_SW : 0); + if (cur_cpu_spec->cpu_features & MMU_FTR_BIG_PHYS) + TLBCAM[index].MAS7 = (u64)phys >> 32; #ifndef CONFIG_KGDB /* want user access for breakpoints */ if (flags & _PAGE_USER) { @@ -148,27 +172,44 @@ void settlbcam(int index, unsigned long virt, phys_addr_t phys, loadcam_entry(index); } -void invalidate_tlbcam_entry(int index) -{ - TLBCAM[index].MAS0 = MAS0_TLBSEL(1) | MAS0_ESEL(index); - TLBCAM[index].MAS1 = ~MAS1_VALID; - - loadcam_entry(index); -} - -unsigned long __init mmu_mapin_ram(void) +unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx) { + int i; unsigned long virt = PAGE_OFFSET; phys_addr_t phys = memstart_addr; + unsigned long amount_mapped = 0; + unsigned long max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf; + + /* Convert (4^max) kB to (2^max) bytes */ + max_cam = max_cam * 2 + 10; - while (tlbcam_index < ARRAY_SIZE(cam) && cam[tlbcam_index]) { - settlbcam(tlbcam_index, virt, phys, cam[tlbcam_index], PAGE_KERNEL_X, 0); - virt += cam[tlbcam_index]; - phys += cam[tlbcam_index]; - tlbcam_index++; + /* Calculate CAM values */ + for (i = 0; ram && i < max_cam_idx; i++) { + unsigned int camsize = __ilog2(ram) & ~1U; + unsigned int align = __ffs(virt | phys) & ~1U; + unsigned long cam_sz; + + if (camsize > align) + camsize = align; + if (camsize > max_cam) + camsize = max_cam; + + cam_sz = 1UL << camsize; + settlbcam(i, virt, phys, cam_sz, PAGE_KERNEL_X, 0); + + ram -= cam_sz; + amount_mapped += cam_sz; + virt += cam_sz; + phys += cam_sz; } + tlbcam_index = i; + + return amount_mapped; +} - return virt - PAGE_OFFSET; +unsigned long __init mmu_mapin_ram(void) +{ + return tlbcam_addrs[tlbcam_index - 1].limit - PAGE_OFFSET + 1; } /* @@ -179,46 +220,21 @@ void __init MMU_init_hw(void) flush_instruction_cache(); } -void __init -adjust_total_lowmem(void) +void __init adjust_total_lowmem(void) { - phys_addr_t ram; - unsigned int max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xff; - char buf[ARRAY_SIZE(cam) * 5 + 1], *p = buf; + unsigned long ram; int i; - unsigned long virt = PAGE_OFFSET & 0xffffffffUL; - unsigned long phys = memstart_addr & 0xffffffffUL; - - /* Convert (4^max) kB to (2^max) bytes */ - max_cam = max_cam * 2 + 10; /* adjust lowmem size to __max_low_memory */ ram = min((phys_addr_t)__max_low_memory, (phys_addr_t)total_lowmem); - /* Calculate CAM values */ - __max_low_memory = 0; - for (i = 0; ram && i < ARRAY_SIZE(cam); i++) { - unsigned int camsize = __ilog2(ram) & ~1U; - unsigned int align = __ffs(virt | phys) & ~1U; + __max_low_memory = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM); - if (camsize > align) - camsize = align; - if (camsize > max_cam) - camsize = max_cam; - - cam[i] = 1UL << camsize; - ram -= cam[i]; - __max_low_memory += cam[i]; - virt += cam[i]; - phys += cam[i]; - - p += sprintf(p, "%lu/", cam[i] >> 20); - } - for (; i < ARRAY_SIZE(cam); i++) - p += sprintf(p, "0/"); - p[-1] = '\0'; - - pr_info("Memory CAM mapping: %s Mb, residual: %dMb\n", buf, + pr_info("Memory CAM mapping: "); + for (i = 0; i < tlbcam_index - 1; i++) + pr_cont("%lu/", tlbcam_sz(i) >> 20); + pr_cont("%lu Mb, residual: %dMb\n", tlbcam_sz(tlbcam_index - 1) >> 20, (unsigned int)((total_lowmem - __max_low_memory) >> 20)); + __initial_memory_limit_addr = memstart_addr + __max_low_memory; } diff --git a/arch/powerpc/mm/gup.c b/arch/powerpc/mm/gup.c index bc122a120bf009c7b6457e56936d5e9f47071dd6..d7efdbf640c7d5e39cd8c3c55f79aa0b8ca64f10 100644 --- a/arch/powerpc/mm/gup.c +++ b/arch/powerpc/mm/gup.c @@ -55,57 +55,6 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr, return 1; } -#ifdef CONFIG_HUGETLB_PAGE -static noinline int gup_huge_pte(pte_t *ptep, struct hstate *hstate, - unsigned long *addr, unsigned long end, - int write, struct page **pages, int *nr) -{ - unsigned long mask; - unsigned long pte_end; - struct page *head, *page; - pte_t pte; - int refs; - - pte_end = (*addr + huge_page_size(hstate)) & huge_page_mask(hstate); - if (pte_end < end) - end = pte_end; - - pte = *ptep; - mask = _PAGE_PRESENT|_PAGE_USER; - if (write) - mask |= _PAGE_RW; - if ((pte_val(pte) & mask) != mask) - return 0; - /* hugepages are never "special" */ - VM_BUG_ON(!pfn_valid(pte_pfn(pte))); - - refs = 0; - head = pte_page(pte); - page = head + ((*addr & ~huge_page_mask(hstate)) >> PAGE_SHIFT); - do { - VM_BUG_ON(compound_head(page) != head); - pages[*nr] = page; - (*nr)++; - page++; - refs++; - } while (*addr += PAGE_SIZE, *addr != end); - - if (!page_cache_add_speculative(head, refs)) { - *nr -= refs; - return 0; - } - if (unlikely(pte_val(pte) != pte_val(*ptep))) { - /* Could be optimized better */ - while (*nr) { - put_page(page); - (*nr)--; - } - } - - return 1; -} -#endif /* CONFIG_HUGETLB_PAGE */ - static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end, int write, struct page **pages, int *nr) { @@ -119,7 +68,11 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end, next = pmd_addr_end(addr, end); if (pmd_none(pmd)) return 0; - if (!gup_pte_range(pmd, addr, next, write, pages, nr)) + if (is_hugepd(pmdp)) { + if (!gup_hugepd((hugepd_t *)pmdp, PMD_SHIFT, + addr, next, write, pages, nr)) + return 0; + } else if (!gup_pte_range(pmd, addr, next, write, pages, nr)) return 0; } while (pmdp++, addr = next, addr != end); @@ -139,7 +92,11 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end, next = pud_addr_end(addr, end); if (pud_none(pud)) return 0; - if (!gup_pmd_range(pud, addr, next, write, pages, nr)) + if (is_hugepd(pudp)) { + if (!gup_hugepd((hugepd_t *)pudp, PUD_SHIFT, + addr, next, write, pages, nr)) + return 0; + } else if (!gup_pmd_range(pud, addr, next, write, pages, nr)) return 0; } while (pudp++, addr = next, addr != end); @@ -154,10 +111,6 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, unsigned long next; pgd_t *pgdp; int nr = 0; -#ifdef CONFIG_PPC64 - unsigned int shift; - int psize; -#endif pr_devel("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read"); @@ -172,25 +125,6 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, pr_devel(" aligned: %lx .. %lx\n", start, end); -#ifdef CONFIG_HUGETLB_PAGE - /* We bail out on slice boundary crossing when hugetlb is - * enabled in order to not have to deal with two different - * page table formats - */ - if (addr < SLICE_LOW_TOP) { - if (end > SLICE_LOW_TOP) - goto slow_irqon; - - if (unlikely(GET_LOW_SLICE_INDEX(addr) != - GET_LOW_SLICE_INDEX(end - 1))) - goto slow_irqon; - } else { - if (unlikely(GET_HIGH_SLICE_INDEX(addr) != - GET_HIGH_SLICE_INDEX(end - 1))) - goto slow_irqon; - } -#endif /* CONFIG_HUGETLB_PAGE */ - /* * XXX: batch / limit 'nr', to avoid large irq off latency * needs some instrumenting to determine the common sizes used by @@ -210,54 +144,23 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, */ local_irq_disable(); -#ifdef CONFIG_PPC64 - /* Those bits are related to hugetlbfs implementation and only exist - * on 64-bit for now - */ - psize = get_slice_psize(mm, addr); - shift = mmu_psize_defs[psize].shift; -#endif /* CONFIG_PPC64 */ - -#ifdef CONFIG_HUGETLB_PAGE - if (unlikely(mmu_huge_psizes[psize])) { - pte_t *ptep; - unsigned long a = addr; - unsigned long sz = ((1UL) << shift); - struct hstate *hstate = size_to_hstate(sz); - - BUG_ON(!hstate); - /* - * XXX: could be optimized to avoid hstate - * lookup entirely (just use shift) - */ - - do { - VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, a)].shift); - ptep = huge_pte_offset(mm, a); - pr_devel(" %016lx: huge ptep %p\n", a, ptep); - if (!ptep || !gup_huge_pte(ptep, hstate, &a, end, write, pages, - &nr)) - goto slow; - } while (a != end); - } else -#endif /* CONFIG_HUGETLB_PAGE */ - { - pgdp = pgd_offset(mm, addr); - do { - pgd_t pgd = *pgdp; - -#ifdef CONFIG_PPC64 - VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, addr)].shift); -#endif - pr_devel(" %016lx: normal pgd %p\n", addr, - (void *)pgd_val(pgd)); - next = pgd_addr_end(addr, end); - if (pgd_none(pgd)) - goto slow; - if (!gup_pud_range(pgd, addr, next, write, pages, &nr)) + pgdp = pgd_offset(mm, addr); + do { + pgd_t pgd = *pgdp; + + pr_devel(" %016lx: normal pgd %p\n", addr, + (void *)pgd_val(pgd)); + next = pgd_addr_end(addr, end); + if (pgd_none(pgd)) + goto slow; + if (is_hugepd(pgdp)) { + if (!gup_hugepd((hugepd_t *)pgdp, PGDIR_SHIFT, + addr, next, write, pages, &nr)) goto slow; - } while (pgdp++, addr = next, addr != end); - } + } else if (!gup_pud_range(pgd, addr, next, write, pages, &nr)) + goto slow; + } while (pgdp++, addr = next, addr != end); + local_irq_enable(); VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT); diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 1ade7eb6ae00a3e8f352526f9b556cb05408943a..50f867d657dfd365de1f21f6bf3f7f6d762c4ccd 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -92,6 +92,7 @@ struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; struct hash_pte *htab_address; unsigned long htab_size_bytes; unsigned long htab_hash_mask; +EXPORT_SYMBOL_GPL(htab_hash_mask); int mmu_linear_psize = MMU_PAGE_4K; int mmu_virtual_psize = MMU_PAGE_4K; int mmu_vmalloc_psize = MMU_PAGE_4K; @@ -102,6 +103,7 @@ int mmu_io_psize = MMU_PAGE_4K; int mmu_kernel_ssize = MMU_SEGSIZE_256M; int mmu_highuser_ssize = MMU_SEGSIZE_256M; u16 mmu_slb_size = 64; +EXPORT_SYMBOL_GPL(mmu_slb_size); #ifdef CONFIG_HUGETLB_PAGE unsigned int HPAGE_SHIFT; #endif @@ -481,16 +483,6 @@ static void __init htab_init_page_sizes(void) #ifdef CONFIG_HUGETLB_PAGE /* Reserve 16G huge page memory sections for huge pages */ of_scan_flat_dt(htab_dt_scan_hugepage_blocks, NULL); - -/* Set default large page size. Currently, we pick 16M or 1M depending - * on what is available - */ - if (mmu_psize_defs[MMU_PAGE_16M].shift) - HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_16M].shift; - /* With 4k/4level pagetables, we can't (for now) cope with a - * huge page size < PMD_SIZE */ - else if (mmu_psize_defs[MMU_PAGE_1M].shift) - HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_1M].shift; #endif /* CONFIG_HUGETLB_PAGE */ } @@ -785,7 +777,7 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) /* page is dirty */ if (!test_bit(PG_arch_1, &page->flags) && !PageReserved(page)) { if (trap == 0x400) { - __flush_dcache_icache(page_address(page)); + flush_dcache_icache_page(page); set_bit(PG_arch_1, &page->flags); } else pp |= HPTE_R_N; @@ -843,9 +835,9 @@ void demote_segment_4k(struct mm_struct *mm, unsigned long addr) * Result is 0: full permissions, _PAGE_RW: read-only, * _PAGE_USER or _PAGE_USER|_PAGE_RW: no access. */ -static int subpage_protection(pgd_t *pgdir, unsigned long ea) +static int subpage_protection(struct mm_struct *mm, unsigned long ea) { - struct subpage_prot_table *spt = pgd_subpage_prot(pgdir); + struct subpage_prot_table *spt = &mm->context.spt; u32 spp = 0; u32 **sbpm, *sbpp; @@ -873,7 +865,7 @@ static int subpage_protection(pgd_t *pgdir, unsigned long ea) } #else /* CONFIG_PPC_SUBPAGE_PROT */ -static inline int subpage_protection(pgd_t *pgdir, unsigned long ea) +static inline int subpage_protection(struct mm_struct *mm, unsigned long ea) { return 0; } @@ -891,6 +883,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) unsigned long vsid; struct mm_struct *mm; pte_t *ptep; + unsigned hugeshift; const struct cpumask *tmp; int rc, user_region = 0, local = 0; int psize, ssize; @@ -943,30 +936,31 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) if (user_region && cpumask_equal(mm_cpumask(mm), tmp)) local = 1; -#ifdef CONFIG_HUGETLB_PAGE - /* Handle hugepage regions */ - if (HPAGE_SHIFT && mmu_huge_psizes[psize]) { - DBG_LOW(" -> huge page !\n"); - return hash_huge_page(mm, access, ea, vsid, local, trap); - } -#endif /* CONFIG_HUGETLB_PAGE */ - #ifndef CONFIG_PPC_64K_PAGES - /* If we use 4K pages and our psize is not 4K, then we are hitting - * a special driver mapping, we need to align the address before - * we fetch the PTE + /* If we use 4K pages and our psize is not 4K, then we might + * be hitting a special driver mapping, and need to align the + * address before we fetch the PTE. + * + * It could also be a hugepage mapping, in which case this is + * not necessary, but it's not harmful, either. */ if (psize != MMU_PAGE_4K) ea &= ~((1ul << mmu_psize_defs[psize].shift) - 1); #endif /* CONFIG_PPC_64K_PAGES */ /* Get PTE and page size from page tables */ - ptep = find_linux_pte(pgdir, ea); + ptep = find_linux_pte_or_hugepte(pgdir, ea, &hugeshift); if (ptep == NULL || !pte_present(*ptep)) { DBG_LOW(" no PTE !\n"); return 1; } +#ifdef CONFIG_HUGETLB_PAGE + if (hugeshift) + return __hash_page_huge(ea, access, vsid, ptep, trap, local, + ssize, hugeshift, psize); +#endif /* CONFIG_HUGETLB_PAGE */ + #ifndef CONFIG_PPC_64K_PAGES DBG_LOW(" i-pte: %016lx\n", pte_val(*ptep)); #else diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c new file mode 100644 index 0000000000000000000000000000000000000000..199539882f927620d6a435b92241e1f08f9aa4a1 --- /dev/null +++ b/arch/powerpc/mm/hugetlbpage-hash64.c @@ -0,0 +1,139 @@ +/* + * PPC64 Huge TLB Page Support for hash based MMUs (POWER4 and later) + * + * Copyright (C) 2003 David Gibson, IBM Corporation. + * + * Based on the IA-32 version: + * Copyright (C) 2002, Rohit Seth + */ + +#include +#include +#include +#include +#include +#include + +int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, + pte_t *ptep, unsigned long trap, int local, int ssize, + unsigned int shift, unsigned int mmu_psize) +{ + unsigned long old_pte, new_pte; + unsigned long va, rflags, pa, sz; + long slot; + int err = 1; + + BUG_ON(shift != mmu_psize_defs[mmu_psize].shift); + + /* Search the Linux page table for a match with va */ + va = hpt_va(ea, vsid, ssize); + + /* + * Check the user's access rights to the page. If access should be + * prevented then send the problem up to do_page_fault. + */ + if (unlikely(access & ~pte_val(*ptep))) + goto out; + /* + * At this point, we have a pte (old_pte) which can be used to build + * or update an HPTE. There are 2 cases: + * + * 1. There is a valid (present) pte with no associated HPTE (this is + * the most common case) + * 2. There is a valid (present) pte with an associated HPTE. The + * current values of the pp bits in the HPTE prevent access + * because we are doing software DIRTY bit management and the + * page is currently not DIRTY. + */ + + + do { + old_pte = pte_val(*ptep); + if (old_pte & _PAGE_BUSY) + goto out; + new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED; + } while(old_pte != __cmpxchg_u64((unsigned long *)ptep, + old_pte, new_pte)); + + rflags = 0x2 | (!(new_pte & _PAGE_RW)); + /* _PAGE_EXEC -> HW_NO_EXEC since it's inverted */ + rflags |= ((new_pte & _PAGE_EXEC) ? 0 : HPTE_R_N); + sz = ((1UL) << shift); + if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) + /* No CPU has hugepages but lacks no execute, so we + * don't need to worry about that case */ + rflags = hash_page_do_lazy_icache(rflags, __pte(old_pte), trap); + + /* Check if pte already has an hpte (case 2) */ + if (unlikely(old_pte & _PAGE_HASHPTE)) { + /* There MIGHT be an HPTE for this pte */ + unsigned long hash, slot; + + hash = hpt_hash(va, shift, ssize); + if (old_pte & _PAGE_F_SECOND) + hash = ~hash; + slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; + slot += (old_pte & _PAGE_F_GIX) >> 12; + + if (ppc_md.hpte_updatepp(slot, rflags, va, mmu_psize, + ssize, local) == -1) + old_pte &= ~_PAGE_HPTEFLAGS; + } + + if (likely(!(old_pte & _PAGE_HASHPTE))) { + unsigned long hash = hpt_hash(va, shift, ssize); + unsigned long hpte_group; + + pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT; + +repeat: + hpte_group = ((hash & htab_hash_mask) * + HPTES_PER_GROUP) & ~0x7UL; + + /* clear HPTE slot informations in new PTE */ +#ifdef CONFIG_PPC_64K_PAGES + new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HPTE_SUB0; +#else + new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE; +#endif + /* Add in WIMG bits */ + rflags |= (new_pte & (_PAGE_WRITETHRU | _PAGE_NO_CACHE | + _PAGE_COHERENT | _PAGE_GUARDED)); + + /* Insert into the hash table, primary slot */ + slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, 0, + mmu_psize, ssize); + + /* Primary is full, try the secondary */ + if (unlikely(slot == -1)) { + hpte_group = ((~hash & htab_hash_mask) * + HPTES_PER_GROUP) & ~0x7UL; + slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, + HPTE_V_SECONDARY, + mmu_psize, ssize); + if (slot == -1) { + if (mftb() & 0x1) + hpte_group = ((hash & htab_hash_mask) * + HPTES_PER_GROUP)&~0x7UL; + + ppc_md.hpte_remove(hpte_group); + goto repeat; + } + } + + if (unlikely(slot == -2)) + panic("hash_huge_page: pte_insert failed\n"); + + new_pte |= (slot << 12) & (_PAGE_F_SECOND | _PAGE_F_GIX); + } + + /* + * No need to use ldarx/stdcx here + */ + *ptep = __pte(new_pte & ~_PAGE_BUSY); + + err = 0; + + out: + return err; +} diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 90df6ffe3a43140fcbfcb5ceaa312fdb7c642319..123f7070238a3624287829f7f485d66c8f28a207 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -7,29 +7,17 @@ * Copyright (C) 2002, Rohit Seth */ -#include -#include #include +#include #include -#include -#include -#include -#include -#include +#include #include #include -#include -#include -#include -#include -#include #define PAGE_SHIFT_64K 16 #define PAGE_SHIFT_16M 24 #define PAGE_SHIFT_16G 34 -#define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT) -#define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT) #define MAX_NUMBER_GPAGES 1024 /* Tracks the 16G pages after the device tree is scanned and before the @@ -37,53 +25,17 @@ static unsigned long gpage_freearray[MAX_NUMBER_GPAGES]; static unsigned nr_gpages; -/* Array of valid huge page sizes - non-zero value(hugepte_shift) is - * stored for the huge page sizes that are valid. - */ -unsigned int mmu_huge_psizes[MMU_PAGE_COUNT] = { }; /* initialize all to 0 */ - -#define hugepte_shift mmu_huge_psizes -#define PTRS_PER_HUGEPTE(psize) (1 << hugepte_shift[psize]) -#define HUGEPTE_TABLE_SIZE(psize) (sizeof(pte_t) << hugepte_shift[psize]) - -#define HUGEPD_SHIFT(psize) (mmu_psize_to_shift(psize) \ - + hugepte_shift[psize]) -#define HUGEPD_SIZE(psize) (1UL << HUGEPD_SHIFT(psize)) -#define HUGEPD_MASK(psize) (~(HUGEPD_SIZE(psize)-1)) - -/* Subtract one from array size because we don't need a cache for 4K since - * is not a huge page size */ -#define HUGE_PGTABLE_INDEX(psize) (HUGEPTE_CACHE_NUM + psize - 1) -#define HUGEPTE_CACHE_NAME(psize) (huge_pgtable_cache_name[psize]) - -static const char *huge_pgtable_cache_name[MMU_PAGE_COUNT] = { - [MMU_PAGE_64K] = "hugepte_cache_64K", - [MMU_PAGE_1M] = "hugepte_cache_1M", - [MMU_PAGE_16M] = "hugepte_cache_16M", - [MMU_PAGE_16G] = "hugepte_cache_16G", -}; - /* Flag to mark huge PD pointers. This means pmd_bad() and pud_bad() * will choke on pointers to hugepte tables, which is handy for * catching screwups early. */ -#define HUGEPD_OK 0x1 - -typedef struct { unsigned long pd; } hugepd_t; - -#define hugepd_none(hpd) ((hpd).pd == 0) static inline int shift_to_mmu_psize(unsigned int shift) { - switch (shift) { -#ifndef CONFIG_PPC_64K_PAGES - case PAGE_SHIFT_64K: - return MMU_PAGE_64K; -#endif - case PAGE_SHIFT_16M: - return MMU_PAGE_16M; - case PAGE_SHIFT_16G: - return MMU_PAGE_16G; - } + int psize; + + for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) + if (mmu_psize_defs[psize].shift == shift) + return psize; return -1; } @@ -94,71 +46,126 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize) BUG(); } +#define hugepd_none(hpd) ((hpd).pd == 0) + static inline pte_t *hugepd_page(hugepd_t hpd) { - BUG_ON(!(hpd.pd & HUGEPD_OK)); - return (pte_t *)(hpd.pd & ~HUGEPD_OK); + BUG_ON(!hugepd_ok(hpd)); + return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | 0xc000000000000000); +} + +static inline unsigned int hugepd_shift(hugepd_t hpd) +{ + return hpd.pd & HUGEPD_SHIFT_MASK; } -static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr, - struct hstate *hstate) +static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr, unsigned pdshift) { - unsigned int shift = huge_page_shift(hstate); - int psize = shift_to_mmu_psize(shift); - unsigned long idx = ((addr >> shift) & (PTRS_PER_HUGEPTE(psize)-1)); + unsigned long idx = (addr & ((1UL << pdshift) - 1)) >> hugepd_shift(*hpdp); pte_t *dir = hugepd_page(*hpdp); return dir + idx; } +pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift) +{ + pgd_t *pg; + pud_t *pu; + pmd_t *pm; + hugepd_t *hpdp = NULL; + unsigned pdshift = PGDIR_SHIFT; + + if (shift) + *shift = 0; + + pg = pgdir + pgd_index(ea); + if (is_hugepd(pg)) { + hpdp = (hugepd_t *)pg; + } else if (!pgd_none(*pg)) { + pdshift = PUD_SHIFT; + pu = pud_offset(pg, ea); + if (is_hugepd(pu)) + hpdp = (hugepd_t *)pu; + else if (!pud_none(*pu)) { + pdshift = PMD_SHIFT; + pm = pmd_offset(pu, ea); + if (is_hugepd(pm)) + hpdp = (hugepd_t *)pm; + else if (!pmd_none(*pm)) { + return pte_offset_map(pm, ea); + } + } + } + + if (!hpdp) + return NULL; + + if (shift) + *shift = hugepd_shift(*hpdp); + return hugepte_offset(hpdp, ea, pdshift); +} + +pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) +{ + return find_linux_pte_or_hugepte(mm->pgd, addr, NULL); +} + static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, - unsigned long address, unsigned int psize) + unsigned long address, unsigned pdshift, unsigned pshift) { - pte_t *new = kmem_cache_zalloc(pgtable_cache[HUGE_PGTABLE_INDEX(psize)], - GFP_KERNEL|__GFP_REPEAT); + pte_t *new = kmem_cache_zalloc(PGT_CACHE(pdshift - pshift), + GFP_KERNEL|__GFP_REPEAT); + + BUG_ON(pshift > HUGEPD_SHIFT_MASK); + BUG_ON((unsigned long)new & HUGEPD_SHIFT_MASK); if (! new) return -ENOMEM; spin_lock(&mm->page_table_lock); if (!hugepd_none(*hpdp)) - kmem_cache_free(pgtable_cache[HUGE_PGTABLE_INDEX(psize)], new); + kmem_cache_free(PGT_CACHE(pdshift - pshift), new); else - hpdp->pd = (unsigned long)new | HUGEPD_OK; + hpdp->pd = ((unsigned long)new & ~0x8000000000000000) | pshift; spin_unlock(&mm->page_table_lock); return 0; } - -static pud_t *hpud_offset(pgd_t *pgd, unsigned long addr, struct hstate *hstate) -{ - if (huge_page_shift(hstate) < PUD_SHIFT) - return pud_offset(pgd, addr); - else - return (pud_t *) pgd; -} -static pud_t *hpud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long addr, - struct hstate *hstate) +pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz) { - if (huge_page_shift(hstate) < PUD_SHIFT) - return pud_alloc(mm, pgd, addr); - else - return (pud_t *) pgd; -} -static pmd_t *hpmd_offset(pud_t *pud, unsigned long addr, struct hstate *hstate) -{ - if (huge_page_shift(hstate) < PMD_SHIFT) - return pmd_offset(pud, addr); - else - return (pmd_t *) pud; -} -static pmd_t *hpmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr, - struct hstate *hstate) -{ - if (huge_page_shift(hstate) < PMD_SHIFT) - return pmd_alloc(mm, pud, addr); - else - return (pmd_t *) pud; + pgd_t *pg; + pud_t *pu; + pmd_t *pm; + hugepd_t *hpdp = NULL; + unsigned pshift = __ffs(sz); + unsigned pdshift = PGDIR_SHIFT; + + addr &= ~(sz-1); + + pg = pgd_offset(mm, addr); + if (pshift >= PUD_SHIFT) { + hpdp = (hugepd_t *)pg; + } else { + pdshift = PUD_SHIFT; + pu = pud_alloc(mm, pg, addr); + if (pshift >= PMD_SHIFT) { + hpdp = (hugepd_t *)pu; + } else { + pdshift = PMD_SHIFT; + pm = pmd_alloc(mm, pu, addr); + hpdp = (hugepd_t *)pm; + } + } + + if (!hpdp) + return NULL; + + BUG_ON(!hugepd_none(*hpdp) && !hugepd_ok(*hpdp)); + + if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr, pdshift, pshift)) + return NULL; + + return hugepte_offset(hpdp, addr, pdshift); } /* Build list of addresses of gigantic pages. This function is used in early @@ -192,94 +199,38 @@ int alloc_bootmem_huge_page(struct hstate *hstate) return 1; } - -/* Modelled after find_linux_pte() */ -pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) -{ - pgd_t *pg; - pud_t *pu; - pmd_t *pm; - - unsigned int psize; - unsigned int shift; - unsigned long sz; - struct hstate *hstate; - psize = get_slice_psize(mm, addr); - shift = mmu_psize_to_shift(psize); - sz = ((1UL) << shift); - hstate = size_to_hstate(sz); - - addr &= hstate->mask; - - pg = pgd_offset(mm, addr); - if (!pgd_none(*pg)) { - pu = hpud_offset(pg, addr, hstate); - if (!pud_none(*pu)) { - pm = hpmd_offset(pu, addr, hstate); - if (!pmd_none(*pm)) - return hugepte_offset((hugepd_t *)pm, addr, - hstate); - } - } - - return NULL; -} - -pte_t *huge_pte_alloc(struct mm_struct *mm, - unsigned long addr, unsigned long sz) -{ - pgd_t *pg; - pud_t *pu; - pmd_t *pm; - hugepd_t *hpdp = NULL; - struct hstate *hstate; - unsigned int psize; - hstate = size_to_hstate(sz); - - psize = get_slice_psize(mm, addr); - BUG_ON(!mmu_huge_psizes[psize]); - - addr &= hstate->mask; - - pg = pgd_offset(mm, addr); - pu = hpud_alloc(mm, pg, addr, hstate); - - if (pu) { - pm = hpmd_alloc(mm, pu, addr, hstate); - if (pm) - hpdp = (hugepd_t *)pm; - } - - if (! hpdp) - return NULL; - - if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr, psize)) - return NULL; - - return hugepte_offset(hpdp, addr, hstate); -} - int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep) { return 0; } -static void free_hugepte_range(struct mmu_gather *tlb, hugepd_t *hpdp, - unsigned int psize) +static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshift, + unsigned long start, unsigned long end, + unsigned long floor, unsigned long ceiling) { pte_t *hugepte = hugepd_page(*hpdp); + unsigned shift = hugepd_shift(*hpdp); + unsigned long pdmask = ~((1UL << pdshift) - 1); + + start &= pdmask; + if (start < floor) + return; + if (ceiling) { + ceiling &= pdmask; + if (! ceiling) + return; + } + if (end - 1 > ceiling - 1) + return; hpdp->pd = 0; tlb->need_flush = 1; - pgtable_free_tlb(tlb, pgtable_free_cache(hugepte, - HUGEPTE_CACHE_NUM+psize-1, - PGF_CACHENUM_MASK)); + pgtable_free_tlb(tlb, hugepte, pdshift - shift); } static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud, unsigned long addr, unsigned long end, - unsigned long floor, unsigned long ceiling, - unsigned int psize) + unsigned long floor, unsigned long ceiling) { pmd_t *pmd; unsigned long next; @@ -291,7 +242,8 @@ static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud, next = pmd_addr_end(addr, end); if (pmd_none(*pmd)) continue; - free_hugepte_range(tlb, (hugepd_t *)pmd, psize); + free_hugepd_range(tlb, (hugepd_t *)pmd, PMD_SHIFT, + addr, next, floor, ceiling); } while (pmd++, addr = next, addr != end); start &= PUD_MASK; @@ -317,23 +269,19 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd, pud_t *pud; unsigned long next; unsigned long start; - unsigned int shift; - unsigned int psize = get_slice_psize(tlb->mm, addr); - shift = mmu_psize_to_shift(psize); start = addr; pud = pud_offset(pgd, addr); do { next = pud_addr_end(addr, end); - if (shift < PMD_SHIFT) { + if (!is_hugepd(pud)) { if (pud_none_or_clear_bad(pud)) continue; hugetlb_free_pmd_range(tlb, pud, addr, next, floor, - ceiling, psize); + ceiling); } else { - if (pud_none(*pud)) - continue; - free_hugepte_range(tlb, (hugepd_t *)pud, psize); + free_hugepd_range(tlb, (hugepd_t *)pud, PUD_SHIFT, + addr, next, floor, ceiling); } } while (pud++, addr = next, addr != end); @@ -364,121 +312,56 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb, { pgd_t *pgd; unsigned long next; - unsigned long start; /* - * Comments below take from the normal free_pgd_range(). They - * apply here too. The tests against HUGEPD_MASK below are - * essential, because we *don't* test for this at the bottom - * level. Without them we'll attempt to free a hugepte table - * when we unmap just part of it, even if there are other - * active mappings using it. - * - * The next few lines have given us lots of grief... - * - * Why are we testing HUGEPD* at this top level? Because - * often there will be no work to do at all, and we'd prefer - * not to go all the way down to the bottom just to discover - * that. - * - * Why all these "- 1"s? Because 0 represents both the bottom - * of the address space and the top of it (using -1 for the - * top wouldn't help much: the masks would do the wrong thing). - * The rule is that addr 0 and floor 0 refer to the bottom of - * the address space, but end 0 and ceiling 0 refer to the top - * Comparisons need to use "end - 1" and "ceiling - 1" (though - * that end 0 case should be mythical). + * Because there are a number of different possible pagetable + * layouts for hugepage ranges, we limit knowledge of how + * things should be laid out to the allocation path + * (huge_pte_alloc(), above). Everything else works out the + * structure as it goes from information in the hugepd + * pointers. That means that we can't here use the + * optimization used in the normal page free_pgd_range(), of + * checking whether we're actually covering a large enough + * range to have to do anything at the top level of the walk + * instead of at the bottom. * - * Wherever addr is brought up or ceiling brought down, we - * must be careful to reject "the opposite 0" before it - * confuses the subsequent tests. But what about where end is - * brought down by HUGEPD_SIZE below? no, end can't go down to - * 0 there. - * - * Whereas we round start (addr) and ceiling down, by different - * masks at different levels, in order to test whether a table - * now has no other vmas using it, so can be freed, we don't - * bother to round floor or end up - the tests don't need that. + * To make sense of this, you should probably go read the big + * block comment at the top of the normal free_pgd_range(), + * too. */ - unsigned int psize = get_slice_psize(tlb->mm, addr); - - addr &= HUGEPD_MASK(psize); - if (addr < floor) { - addr += HUGEPD_SIZE(psize); - if (!addr) - return; - } - if (ceiling) { - ceiling &= HUGEPD_MASK(psize); - if (!ceiling) - return; - } - if (end - 1 > ceiling - 1) - end -= HUGEPD_SIZE(psize); - if (addr > end - 1) - return; - start = addr; pgd = pgd_offset(tlb->mm, addr); do { - psize = get_slice_psize(tlb->mm, addr); - BUG_ON(!mmu_huge_psizes[psize]); next = pgd_addr_end(addr, end); - if (mmu_psize_to_shift(psize) < PUD_SHIFT) { + if (!is_hugepd(pgd)) { if (pgd_none_or_clear_bad(pgd)) continue; hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling); } else { - if (pgd_none(*pgd)) - continue; - free_hugepte_range(tlb, (hugepd_t *)pgd, psize); + free_hugepd_range(tlb, (hugepd_t *)pgd, PGDIR_SHIFT, + addr, next, floor, ceiling); } } while (pgd++, addr = next, addr != end); } -void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, pte_t pte) -{ - if (pte_present(*ptep)) { - /* We open-code pte_clear because we need to pass the right - * argument to hpte_need_flush (huge / !huge). Might not be - * necessary anymore if we make hpte_need_flush() get the - * page size from the slices - */ - unsigned int psize = get_slice_psize(mm, addr); - unsigned int shift = mmu_psize_to_shift(psize); - unsigned long sz = ((1UL) << shift); - struct hstate *hstate = size_to_hstate(sz); - pte_update(mm, addr & hstate->mask, ptep, ~0UL, 1); - } - *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); -} - -pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, - pte_t *ptep) -{ - unsigned long old = pte_update(mm, addr, ptep, ~0UL, 1); - return __pte(old); -} - struct page * follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) { pte_t *ptep; struct page *page; - unsigned int mmu_psize = get_slice_psize(mm, address); + unsigned shift; + unsigned long mask; + + ptep = find_linux_pte_or_hugepte(mm->pgd, address, &shift); /* Verify it is a huge page else bail. */ - if (!mmu_huge_psizes[mmu_psize]) + if (!ptep || !shift) return ERR_PTR(-EINVAL); - ptep = huge_pte_offset(mm, address); + mask = (1UL << shift) - 1; page = pte_page(*ptep); - if (page) { - unsigned int shift = mmu_psize_to_shift(mmu_psize); - unsigned long sz = ((1UL) << shift); - page += (address % sz) / PAGE_SIZE; - } + if (page) + page += (address & mask) / PAGE_SIZE; return page; } @@ -501,6 +384,82 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address, return NULL; } +static noinline int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, + unsigned long end, int write, struct page **pages, int *nr) +{ + unsigned long mask; + unsigned long pte_end; + struct page *head, *page; + pte_t pte; + int refs; + + pte_end = (addr + sz) & ~(sz-1); + if (pte_end < end) + end = pte_end; + + pte = *ptep; + mask = _PAGE_PRESENT | _PAGE_USER; + if (write) + mask |= _PAGE_RW; + + if ((pte_val(pte) & mask) != mask) + return 0; + + /* hugepages are never "special" */ + VM_BUG_ON(!pfn_valid(pte_pfn(pte))); + + refs = 0; + head = pte_page(pte); + + page = head + ((addr & (sz-1)) >> PAGE_SHIFT); + do { + VM_BUG_ON(compound_head(page) != head); + pages[*nr] = page; + (*nr)++; + page++; + refs++; + } while (addr += PAGE_SIZE, addr != end); + + if (!page_cache_add_speculative(head, refs)) { + *nr -= refs; + return 0; + } + + if (unlikely(pte_val(pte) != pte_val(*ptep))) { + /* Could be optimized better */ + while (*nr) { + put_page(page); + (*nr)--; + } + } + + return 1; +} + +static unsigned long hugepte_addr_end(unsigned long addr, unsigned long end, + unsigned long sz) +{ + unsigned long __boundary = (addr + sz) & ~(sz-1); + return (__boundary - 1 < end - 1) ? __boundary : end; +} + +int gup_hugepd(hugepd_t *hugepd, unsigned pdshift, + unsigned long addr, unsigned long end, + int write, struct page **pages, int *nr) +{ + pte_t *ptep; + unsigned long sz = 1UL << hugepd_shift(*hugepd); + unsigned long next; + + ptep = hugepte_offset(hugepd, addr, pdshift); + do { + next = hugepte_addr_end(addr, end, sz); + if (!gup_hugepte(ptep, sz, addr, end, write, pages, nr)) + return 0; + } while (ptep++, addr = next, addr != end); + + return 1; +} unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, @@ -509,8 +468,6 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, struct hstate *hstate = hstate_file(file); int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate)); - if (!mmu_huge_psizes[mmu_psize]) - return -EINVAL; return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0); } @@ -521,229 +478,46 @@ unsigned long vma_mmu_pagesize(struct vm_area_struct *vma) return 1UL << mmu_psize_to_shift(psize); } -/* - * Called by asm hashtable.S for doing lazy icache flush - */ -static unsigned int hash_huge_page_do_lazy_icache(unsigned long rflags, - pte_t pte, int trap, unsigned long sz) +static int __init add_huge_page_size(unsigned long long size) { - struct page *page; - int i; - - if (!pfn_valid(pte_pfn(pte))) - return rflags; - - page = pte_page(pte); - - /* page is dirty */ - if (!test_bit(PG_arch_1, &page->flags) && !PageReserved(page)) { - if (trap == 0x400) { - for (i = 0; i < (sz / PAGE_SIZE); i++) - __flush_dcache_icache(page_address(page+i)); - set_bit(PG_arch_1, &page->flags); - } else { - rflags |= HPTE_R_N; - } - } - return rflags; -} + int shift = __ffs(size); + int mmu_psize; -int hash_huge_page(struct mm_struct *mm, unsigned long access, - unsigned long ea, unsigned long vsid, int local, - unsigned long trap) -{ - pte_t *ptep; - unsigned long old_pte, new_pte; - unsigned long va, rflags, pa, sz; - long slot; - int err = 1; - int ssize = user_segment_size(ea); - unsigned int mmu_psize; - int shift; - mmu_psize = get_slice_psize(mm, ea); - - if (!mmu_huge_psizes[mmu_psize]) - goto out; - ptep = huge_pte_offset(mm, ea); - - /* Search the Linux page table for a match with va */ - va = hpt_va(ea, vsid, ssize); + /* Check that it is a page size supported by the hardware and + * that it fits within pagetable and slice limits. */ + if (!is_power_of_2(size) + || (shift > SLICE_HIGH_SHIFT) || (shift <= PAGE_SHIFT)) + return -EINVAL; - /* - * If no pte found or not present, send the problem up to - * do_page_fault - */ - if (unlikely(!ptep || pte_none(*ptep))) - goto out; + if ((mmu_psize = shift_to_mmu_psize(shift)) < 0) + return -EINVAL; - /* - * Check the user's access rights to the page. If access should be - * prevented then send the problem up to do_page_fault. +#ifdef CONFIG_SPU_FS_64K_LS + /* Disable support for 64K huge pages when 64K SPU local store + * support is enabled as the current implementation conflicts. */ - if (unlikely(access & ~pte_val(*ptep))) - goto out; - /* - * At this point, we have a pte (old_pte) which can be used to build - * or update an HPTE. There are 2 cases: - * - * 1. There is a valid (present) pte with no associated HPTE (this is - * the most common case) - * 2. There is a valid (present) pte with an associated HPTE. The - * current values of the pp bits in the HPTE prevent access - * because we are doing software DIRTY bit management and the - * page is currently not DIRTY. - */ - - - do { - old_pte = pte_val(*ptep); - if (old_pte & _PAGE_BUSY) - goto out; - new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED; - } while(old_pte != __cmpxchg_u64((unsigned long *)ptep, - old_pte, new_pte)); - - rflags = 0x2 | (!(new_pte & _PAGE_RW)); - /* _PAGE_EXEC -> HW_NO_EXEC since it's inverted */ - rflags |= ((new_pte & _PAGE_EXEC) ? 0 : HPTE_R_N); - shift = mmu_psize_to_shift(mmu_psize); - sz = ((1UL) << shift); - if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) - /* No CPU has hugepages but lacks no execute, so we - * don't need to worry about that case */ - rflags = hash_huge_page_do_lazy_icache(rflags, __pte(old_pte), - trap, sz); - - /* Check if pte already has an hpte (case 2) */ - if (unlikely(old_pte & _PAGE_HASHPTE)) { - /* There MIGHT be an HPTE for this pte */ - unsigned long hash, slot; - - hash = hpt_hash(va, shift, ssize); - if (old_pte & _PAGE_F_SECOND) - hash = ~hash; - slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; - slot += (old_pte & _PAGE_F_GIX) >> 12; - - if (ppc_md.hpte_updatepp(slot, rflags, va, mmu_psize, - ssize, local) == -1) - old_pte &= ~_PAGE_HPTEFLAGS; - } - - if (likely(!(old_pte & _PAGE_HASHPTE))) { - unsigned long hash = hpt_hash(va, shift, ssize); - unsigned long hpte_group; - - pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT; - -repeat: - hpte_group = ((hash & htab_hash_mask) * - HPTES_PER_GROUP) & ~0x7UL; - - /* clear HPTE slot informations in new PTE */ -#ifdef CONFIG_PPC_64K_PAGES - new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HPTE_SUB0; -#else - new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE; -#endif - /* Add in WIMG bits */ - rflags |= (new_pte & (_PAGE_WRITETHRU | _PAGE_NO_CACHE | - _PAGE_COHERENT | _PAGE_GUARDED)); - - /* Insert into the hash table, primary slot */ - slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, 0, - mmu_psize, ssize); - - /* Primary is full, try the secondary */ - if (unlikely(slot == -1)) { - hpte_group = ((~hash & htab_hash_mask) * - HPTES_PER_GROUP) & ~0x7UL; - slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, - HPTE_V_SECONDARY, - mmu_psize, ssize); - if (slot == -1) { - if (mftb() & 0x1) - hpte_group = ((hash & htab_hash_mask) * - HPTES_PER_GROUP)&~0x7UL; - - ppc_md.hpte_remove(hpte_group); - goto repeat; - } - } - - if (unlikely(slot == -2)) - panic("hash_huge_page: pte_insert failed\n"); - - new_pte |= (slot << 12) & (_PAGE_F_SECOND | _PAGE_F_GIX); - } + if (shift == PAGE_SHIFT_64K) + return -EINVAL; +#endif /* CONFIG_SPU_FS_64K_LS */ - /* - * No need to use ldarx/stdcx here - */ - *ptep = __pte(new_pte & ~_PAGE_BUSY); + BUG_ON(mmu_psize_defs[mmu_psize].shift != shift); - err = 0; + /* Return if huge page size has already been setup */ + if (size_to_hstate(size)) + return 0; - out: - return err; -} + hugetlb_add_hstate(shift - PAGE_SHIFT); -static void __init set_huge_psize(int psize) -{ - /* Check that it is a page size supported by the hardware and - * that it fits within pagetable limits. */ - if (mmu_psize_defs[psize].shift && - mmu_psize_defs[psize].shift < SID_SHIFT_1T && - (mmu_psize_defs[psize].shift > MIN_HUGEPTE_SHIFT || - mmu_psize_defs[psize].shift == PAGE_SHIFT_64K || - mmu_psize_defs[psize].shift == PAGE_SHIFT_16G)) { - /* Return if huge page size has already been setup or is the - * same as the base page size. */ - if (mmu_huge_psizes[psize] || - mmu_psize_defs[psize].shift == PAGE_SHIFT) - return; - if (WARN_ON(HUGEPTE_CACHE_NAME(psize) == NULL)) - return; - hugetlb_add_hstate(mmu_psize_defs[psize].shift - PAGE_SHIFT); - - switch (mmu_psize_defs[psize].shift) { - case PAGE_SHIFT_64K: - /* We only allow 64k hpages with 4k base page, - * which was checked above, and always put them - * at the PMD */ - hugepte_shift[psize] = PMD_SHIFT; - break; - case PAGE_SHIFT_16M: - /* 16M pages can be at two different levels - * of pagestables based on base page size */ - if (PAGE_SHIFT == PAGE_SHIFT_64K) - hugepte_shift[psize] = PMD_SHIFT; - else /* 4k base page */ - hugepte_shift[psize] = PUD_SHIFT; - break; - case PAGE_SHIFT_16G: - /* 16G pages are always at PGD level */ - hugepte_shift[psize] = PGDIR_SHIFT; - break; - } - hugepte_shift[psize] -= mmu_psize_defs[psize].shift; - } else - hugepte_shift[psize] = 0; + return 0; } static int __init hugepage_setup_sz(char *str) { unsigned long long size; - int mmu_psize; - int shift; size = memparse(str, &str); - shift = __ffs(size); - mmu_psize = shift_to_mmu_psize(shift); - if (mmu_psize >= 0 && mmu_psize_defs[mmu_psize].shift) - set_huge_psize(mmu_psize); - else + if (add_huge_page_size(size) != 0) printk(KERN_WARNING "Invalid huge page size specified(%llu)\n", size); return 1; @@ -752,41 +526,55 @@ __setup("hugepagesz=", hugepage_setup_sz); static int __init hugetlbpage_init(void) { - unsigned int psize; + int psize; if (!cpu_has_feature(CPU_FTR_16M_PAGE)) return -ENODEV; - /* Add supported huge page sizes. Need to change HUGE_MAX_HSTATE - * and adjust PTE_NONCACHE_NUM if the number of supported huge page - * sizes changes. - */ - set_huge_psize(MMU_PAGE_16M); - set_huge_psize(MMU_PAGE_16G); + for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { + unsigned shift; + unsigned pdshift; - /* Temporarily disable support for 64K huge pages when 64K SPU local - * store support is enabled as the current implementation conflicts. - */ -#ifndef CONFIG_SPU_FS_64K_LS - set_huge_psize(MMU_PAGE_64K); -#endif + if (!mmu_psize_defs[psize].shift) + continue; - for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { - if (mmu_huge_psizes[psize]) { - pgtable_cache[HUGE_PGTABLE_INDEX(psize)] = - kmem_cache_create( - HUGEPTE_CACHE_NAME(psize), - HUGEPTE_TABLE_SIZE(psize), - HUGEPTE_TABLE_SIZE(psize), - 0, - NULL); - if (!pgtable_cache[HUGE_PGTABLE_INDEX(psize)]) - panic("hugetlbpage_init(): could not create %s"\ - "\n", HUGEPTE_CACHE_NAME(psize)); - } + shift = mmu_psize_to_shift(psize); + + if (add_huge_page_size(1ULL << shift) < 0) + continue; + + if (shift < PMD_SHIFT) + pdshift = PMD_SHIFT; + else if (shift < PUD_SHIFT) + pdshift = PUD_SHIFT; + else + pdshift = PGDIR_SHIFT; + + pgtable_cache_add(pdshift - shift, NULL); + if (!PGT_CACHE(pdshift - shift)) + panic("hugetlbpage_init(): could not create " + "pgtable cache for %d bit pagesize\n", shift); } + /* Set default large page size. Currently, we pick 16M or 1M + * depending on what is available + */ + if (mmu_psize_defs[MMU_PAGE_16M].shift) + HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_16M].shift; + else if (mmu_psize_defs[MMU_PAGE_1M].shift) + HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_1M].shift; + return 0; } module_init(hugetlbpage_init); + +void flush_dcache_icache_hugepage(struct page *page) +{ + int i; + + BUG_ON(!PageCompound(page)); + + for (i = 0; i < (1UL << compound_order(page)); i++) + __flush_dcache_icache(page_address(page+i)); +} diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 335c578b9cc324261a29a3a435036ef5178e9f96..776f28d02b6b0a163a6c5f8d6bde6532a350d38c 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -119,30 +120,63 @@ static void pmd_ctor(void *addr) memset(addr, 0, PMD_TABLE_SIZE); } -static const unsigned int pgtable_cache_size[2] = { - PGD_TABLE_SIZE, PMD_TABLE_SIZE -}; -static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { -#ifdef CONFIG_PPC_64K_PAGES - "pgd_cache", "pmd_cache", -#else - "pgd_cache", "pud_pmd_cache", -#endif /* CONFIG_PPC_64K_PAGES */ -}; - -#ifdef CONFIG_HUGETLB_PAGE -/* Hugepages need an extra cache per hugepagesize, initialized in - * hugetlbpage.c. We can't put into the tables above, because HPAGE_SHIFT - * is not compile time constant. */ -struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+MMU_PAGE_COUNT]; -#else -struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)]; -#endif +struct kmem_cache *pgtable_cache[MAX_PGTABLE_INDEX_SIZE]; + +/* + * Create a kmem_cache() for pagetables. This is not used for PTE + * pages - they're linked to struct page, come from the normal free + * pages pool and have a different entry size (see real_pte_t) to + * everything else. Caches created by this function are used for all + * the higher level pagetables, and for hugepage pagetables. + */ +void pgtable_cache_add(unsigned shift, void (*ctor)(void *)) +{ + char *name; + unsigned long table_size = sizeof(void *) << shift; + unsigned long align = table_size; + + /* When batching pgtable pointers for RCU freeing, we store + * the index size in the low bits. Table alignment must be + * big enough to fit it. + * + * Likewise, hugeapge pagetable pointers contain a (different) + * shift value in the low bits. All tables must be aligned so + * as to leave enough 0 bits in the address to contain it. */ + unsigned long minalign = max(MAX_PGTABLE_INDEX_SIZE + 1, + HUGEPD_SHIFT_MASK + 1); + struct kmem_cache *new; + + /* It would be nice if this was a BUILD_BUG_ON(), but at the + * moment, gcc doesn't seem to recognize is_power_of_2 as a + * constant expression, so so much for that. */ + BUG_ON(!is_power_of_2(minalign)); + BUG_ON((shift < 1) || (shift > MAX_PGTABLE_INDEX_SIZE)); + + if (PGT_CACHE(shift)) + return; /* Already have a cache of this size */ + + align = max_t(unsigned long, align, minalign); + name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift); + new = kmem_cache_create(name, table_size, align, 0, ctor); + PGT_CACHE(shift) = new; + + pr_debug("Allocated pgtable cache for order %d\n", shift); +} + void pgtable_cache_init(void) { - pgtable_cache[0] = kmem_cache_create(pgtable_cache_name[0], PGD_TABLE_SIZE, PGD_TABLE_SIZE, SLAB_PANIC, pgd_ctor); - pgtable_cache[1] = kmem_cache_create(pgtable_cache_name[1], PMD_TABLE_SIZE, PMD_TABLE_SIZE, SLAB_PANIC, pmd_ctor); + pgtable_cache_add(PGD_INDEX_SIZE, pgd_ctor); + pgtable_cache_add(PMD_INDEX_SIZE, pmd_ctor); + if (!PGT_CACHE(PGD_INDEX_SIZE) || !PGT_CACHE(PMD_INDEX_SIZE)) + panic("Couldn't allocate pgtable caches"); + + /* In all current configs, when the PUD index exists it's the + * same size as either the pgd or pmd index. Verify that the + * initialization above has also created a PUD cache. This + * will need re-examiniation if we add new possibilities for + * the pagetable layout. */ + BUG_ON(PUD_INDEX_SIZE && !PGT_CACHE(PUD_INDEX_SIZE)); } #ifdef CONFIG_SPARSEMEM_VMEMMAP diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 59736317bf0e87a1193910340dd338fb5e75c2ff..b9b152558f9c5de64d70399a37c1aa7dfd001706 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -417,18 +418,26 @@ EXPORT_SYMBOL(flush_dcache_page); void flush_dcache_icache_page(struct page *page) { +#ifdef CONFIG_HUGETLB_PAGE + if (PageCompound(page)) { + flush_dcache_icache_hugepage(page); + return; + } +#endif #ifdef CONFIG_BOOKE - void *start = kmap_atomic(page, KM_PPC_SYNC_ICACHE); - __flush_dcache_icache(start); - kunmap_atomic(start, KM_PPC_SYNC_ICACHE); + { + void *start = kmap_atomic(page, KM_PPC_SYNC_ICACHE); + __flush_dcache_icache(start); + kunmap_atomic(start, KM_PPC_SYNC_ICACHE); + } #elif defined(CONFIG_8xx) || defined(CONFIG_PPC64) /* On 8xx there is no need to kmap since highmem is not supported */ __flush_dcache_icache(page_address(page)); #else __flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT); #endif - } + void clear_user_page(void *page, unsigned long vaddr, struct page *pg) { clear_page(page); diff --git a/arch/powerpc/mm/mmu_context_hash64.c b/arch/powerpc/mm/mmu_context_hash64.c index dbeb86ac90cd79f01396eecbd72b98bc172253dc..b910d37aea1aa921b567b0d3a9054b76d9a22ec7 100644 --- a/arch/powerpc/mm/mmu_context_hash64.c +++ b/arch/powerpc/mm/mmu_context_hash64.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -32,7 +33,7 @@ static DEFINE_IDR(mmu_context_idr); #define NO_CONTEXT 0 #define MAX_CONTEXT ((1UL << 19) - 1) -int init_new_context(struct task_struct *tsk, struct mm_struct *mm) +int __init_new_context(void) { int index; int err; @@ -57,22 +58,41 @@ again: return -ENOMEM; } + return index; +} +EXPORT_SYMBOL_GPL(__init_new_context); + +int init_new_context(struct task_struct *tsk, struct mm_struct *mm) +{ + int index; + + index = __init_new_context(); + if (index < 0) + return index; + /* The old code would re-promote on fork, we don't do that * when using slices as it could cause problem promoting slices * that have been forced down to 4K */ if (slice_mm_new_context(mm)) slice_set_user_psize(mm, mmu_virtual_psize); + subpage_prot_init_new_context(mm); mm->context.id = index; return 0; } -void destroy_context(struct mm_struct *mm) +void __destroy_context(int context_id) { spin_lock(&mmu_context_lock); - idr_remove(&mmu_context_idr, mm->context.id); + idr_remove(&mmu_context_idr, context_id); spin_unlock(&mmu_context_lock); +} +EXPORT_SYMBOL_GPL(__destroy_context); +void destroy_context(struct mm_struct *mm) +{ + __destroy_context(mm->context.id); + subpage_prot_free(mm); mm->context.id = NO_CONTEXT; } diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index d2e5321d5ea6aba3a4d5827ca6f7fc2d7fe61c6a..e27a990af42dd37ffcb3d7f198e6483aceed2d2f 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h @@ -98,21 +98,10 @@ extern void _tlbia(void); #ifdef CONFIG_PPC32 -struct tlbcam { - u32 MAS0; - u32 MAS1; - u32 MAS2; - u32 MAS3; - u32 MAS7; -}; - extern void mapin_ram(void); extern int map_page(unsigned long va, phys_addr_t pa, int flags); extern void setbat(int index, unsigned long virt, phys_addr_t phys, unsigned int size, int flags); -extern void settlbcam(int index, unsigned long virt, phys_addr_t phys, - unsigned int size, int flags, unsigned int pid); -extern void invalidate_tlbcam_entry(int index); extern int __map_without_bats; extern unsigned long ioremap_base; diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index 53040931de322c5cf0df1955ad5aecd876b0f420..99df697c601acbd9a0fa3267cb313e7a21cd7303 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c @@ -49,12 +49,12 @@ struct pte_freelist_batch { struct rcu_head rcu; unsigned int index; - pgtable_free_t tables[0]; + unsigned long tables[0]; }; #define PTE_FREELIST_SIZE \ ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \ - / sizeof(pgtable_free_t)) + / sizeof(unsigned long)) static void pte_free_smp_sync(void *arg) { @@ -64,13 +64,13 @@ static void pte_free_smp_sync(void *arg) /* This is only called when we are critically out of memory * (and fail to get a page in pte_free_tlb). */ -static void pgtable_free_now(pgtable_free_t pgf) +static void pgtable_free_now(void *table, unsigned shift) { pte_freelist_forced_free++; smp_call_function(pte_free_smp_sync, NULL, 1); - pgtable_free(pgf); + pgtable_free(table, shift); } static void pte_free_rcu_callback(struct rcu_head *head) @@ -79,8 +79,12 @@ static void pte_free_rcu_callback(struct rcu_head *head) container_of(head, struct pte_freelist_batch, rcu); unsigned int i; - for (i = 0; i < batch->index; i++) - pgtable_free(batch->tables[i]); + for (i = 0; i < batch->index; i++) { + void *table = (void *)(batch->tables[i] & ~MAX_PGTABLE_INDEX_SIZE); + unsigned shift = batch->tables[i] & MAX_PGTABLE_INDEX_SIZE; + + pgtable_free(table, shift); + } free_page((unsigned long)batch); } @@ -91,25 +95,28 @@ static void pte_free_submit(struct pte_freelist_batch *batch) call_rcu(&batch->rcu, pte_free_rcu_callback); } -void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) +void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift) { /* This is safe since tlb_gather_mmu has disabled preemption */ struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); + unsigned long pgf; if (atomic_read(&tlb->mm->mm_users) < 2 || cpumask_equal(mm_cpumask(tlb->mm), cpumask_of(smp_processor_id()))){ - pgtable_free(pgf); + pgtable_free(table, shift); return; } if (*batchp == NULL) { *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC); if (*batchp == NULL) { - pgtable_free_now(pgf); + pgtable_free_now(table, shift); return; } (*batchp)->index = 0; } + BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE); + pgf = (unsigned long)table | shift; (*batchp)->tables[(*batchp)->index++] = pgf; if ((*batchp)->index == PTE_FREELIST_SIZE) { pte_free_submit(*batchp); diff --git a/arch/powerpc/mm/subpage-prot.c b/arch/powerpc/mm/subpage-prot.c index 4cafc0c33d0ac8cb6353c2bd6272e881488a674b..a040b81e93bdd6b49d16b77e4c8b04b0281c7bc6 100644 --- a/arch/powerpc/mm/subpage-prot.c +++ b/arch/powerpc/mm/subpage-prot.c @@ -24,9 +24,9 @@ * Also makes sure that the subpage_prot_table structure is * reinitialized for the next user. */ -void subpage_prot_free(pgd_t *pgd) +void subpage_prot_free(struct mm_struct *mm) { - struct subpage_prot_table *spt = pgd_subpage_prot(pgd); + struct subpage_prot_table *spt = &mm->context.spt; unsigned long i, j, addr; u32 **p; @@ -51,6 +51,13 @@ void subpage_prot_free(pgd_t *pgd) spt->maxaddr = 0; } +void subpage_prot_init_new_context(struct mm_struct *mm) +{ + struct subpage_prot_table *spt = &mm->context.spt; + + memset(spt, 0, sizeof(*spt)); +} + static void hpte_flush_range(struct mm_struct *mm, unsigned long addr, int npages) { @@ -87,7 +94,7 @@ static void hpte_flush_range(struct mm_struct *mm, unsigned long addr, static void subpage_prot_clear(unsigned long addr, unsigned long len) { struct mm_struct *mm = current->mm; - struct subpage_prot_table *spt = pgd_subpage_prot(mm->pgd); + struct subpage_prot_table *spt = &mm->context.spt; u32 **spm, *spp; int i, nw; unsigned long next, limit; @@ -136,7 +143,7 @@ static void subpage_prot_clear(unsigned long addr, unsigned long len) long sys_subpage_prot(unsigned long addr, unsigned long len, u32 __user *map) { struct mm_struct *mm = current->mm; - struct subpage_prot_table *spt = pgd_subpage_prot(mm->pgd); + struct subpage_prot_table *spt = &mm->context.spt; u32 **spm, *spp; int i, nw; unsigned long next, limit; diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c index 2b2f35f6985e561aaacf2ef515e654d0ba1985b4..282d9306361f58f3ba3443648f73dd6955a75fd4 100644 --- a/arch/powerpc/mm/tlb_hash64.c +++ b/arch/powerpc/mm/tlb_hash64.c @@ -53,11 +53,6 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr, i = batch->index; - /* We mask the address for the base page size. Huge pages will - * have applied their own masking already - */ - addr &= PAGE_MASK; - /* Get page size (maybe move back to caller). * * NOTE: when using special 64K mappings in 4K environment like @@ -75,6 +70,9 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr, } else psize = pte_pagesize_index(mm, addr, pte); + /* Mask the address for the correct page size */ + addr &= ~((1UL << mmu_psize_defs[psize].shift) - 1); + /* Build full vaddr */ if (!is_kernel_addr(addr)) { ssize = user_segment_size(addr); diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c index a6ce805666253d938fbfc986127d24ace67e3fda..da9b20a637690fb0bed45176ad668ad98cb0feb3 100644 --- a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c +++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c @@ -79,7 +79,7 @@ cpld_unmask_irq(unsigned int irq) } static struct irq_chip cpld_pic = { - .typename = " CPLD PIC ", + .name = " CPLD PIC ", .mask = cpld_mask_irq, .ack = cpld_mask_irq, .unmask = cpld_unmask_irq, @@ -132,7 +132,7 @@ static int cpld_pic_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw) { - get_irq_desc(virq)->status |= IRQ_LEVEL; + irq_to_desc(virq)->status |= IRQ_LEVEL; set_irq_chip_and_handler(virq, &cpld_pic, handle_level_irq); return 0; } diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig index 8b8e9560a315ed51127625b8544edc8a2f24b667..47ea1be1481bdeec198dfe09f9194e0c9201e47d 100644 --- a/arch/powerpc/platforms/52xx/Kconfig +++ b/arch/powerpc/platforms/52xx/Kconfig @@ -62,3 +62,8 @@ config PPC_MPC5200_GPIO select GENERIC_GPIO help Enable gpiolib support for mpc5200 based boards + +config PPC_MPC5200_LPBFIFO + tristate "MPC5200 LocalPlus bus FIFO driver" + depends on PPC_MPC52xx + select PPC_BESTCOMM_GEN_BD diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile index bfd4f52cf3dd785a3827e78bffcb7fcc6a168f5e..2bc8cd0c5cfc5b0edfaa2581ddcaead1e168374e 100644 --- a/arch/powerpc/platforms/52xx/Makefile +++ b/arch/powerpc/platforms/52xx/Makefile @@ -15,3 +15,4 @@ ifeq ($(CONFIG_PPC_LITE5200),y) endif obj-$(CONFIG_PPC_MPC5200_GPIO) += mpc52xx_gpio.o +obj-$(CONFIG_PPC_MPC5200_LPBFIFO) += mpc52xx_lpbfifo.o diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c index 68e4f1696d1488a663ef2480bae31fabd65aba32..cc0c854291d7397837f371d94a2922e7a7464c66 100644 --- a/arch/powerpc/platforms/52xx/media5200.c +++ b/arch/powerpc/platforms/52xx/media5200.c @@ -74,7 +74,7 @@ static void media5200_irq_mask(unsigned int virq) } static struct irq_chip media5200_irq_chip = { - .typename = "Media5200 FPGA", + .name = "Media5200 FPGA", .unmask = media5200_irq_unmask, .mask = media5200_irq_mask, .mask_ack = media5200_irq_mask, @@ -114,7 +114,7 @@ void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc) static int media5200_irq_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw) { - struct irq_desc *desc = get_irq_desc(virq); + struct irq_desc *desc = irq_to_desc(virq); pr_debug("%s: h=%p, virq=%i, hwirq=%i\n", __func__, h, virq, (int)hw); set_irq_chip_data(virq, &media5200_irq); @@ -127,7 +127,7 @@ static int media5200_irq_map(struct irq_host *h, unsigned int virq, } static int media5200_irq_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index bfbcd418e690a1746cad0730753b408e217b8673..6f8ebe1085b3c40701647ee8ba8e0da5a4a4b247 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c @@ -16,8 +16,14 @@ * output signals or measure input signals. * * This driver supports the GPIO and IRQ controller functions of the GPT - * device. Timer functions are not yet supported, nor is the watchdog - * timer. + * device. Timer functions are not yet supported. + * + * The timer gpt0 can be used as watchdog (wdt). If the wdt mode is used, + * this prevents the use of any gpt0 gpt function (i.e. they will fail with + * -EBUSY). Thus, the safety wdt function always has precedence over the gpt + * function. If the kernel has been compiled with CONFIG_WATCHDOG_NOWAYOUT, + * this means that gpt0 is locked in wdt mode until the next reboot - this + * may be a requirement in safety applications. * * To use the GPIO function, the following two properties must be added * to the device tree node for the gpt device (typically in the .dts file @@ -46,17 +52,24 @@ * the output mode. This driver does not change the output mode setting. */ +#include #include #include #include +#include +#include #include #include #include #include +#include +#include +#include +#include #include MODULE_DESCRIPTION("Freescale MPC52xx gpt driver"); -MODULE_AUTHOR("Sascha Hauer, Grant Likely"); +MODULE_AUTHOR("Sascha Hauer, Grant Likely, Albrecht Dreß"); MODULE_LICENSE("GPL"); /** @@ -66,18 +79,27 @@ MODULE_LICENSE("GPL"); * @lock: spinlock to coordinate between different functions. * @of_gc: of_gpio_chip instance structure; used when GPIO is enabled * @irqhost: Pointer to irq_host instance; used when IRQ mode is supported + * @wdt_mode: only relevant for gpt0: bit 0 (MPC52xx_GPT_CAN_WDT) indicates + * if the gpt may be used as wdt, bit 1 (MPC52xx_GPT_IS_WDT) indicates + * if the timer is actively used as wdt which blocks gpt functions */ struct mpc52xx_gpt_priv { + struct list_head list; /* List of all GPT devices */ struct device *dev; struct mpc52xx_gpt __iomem *regs; spinlock_t lock; struct irq_host *irqhost; + u32 ipb_freq; + u8 wdt_mode; #if defined(CONFIG_GPIOLIB) struct of_gpio_chip of_gc; #endif }; +LIST_HEAD(mpc52xx_gpt_list); +DEFINE_MUTEX(mpc52xx_gpt_list_mutex); + #define MPC52xx_GPT_MODE_MS_MASK (0x07) #define MPC52xx_GPT_MODE_MS_IC (0x01) #define MPC52xx_GPT_MODE_MS_OC (0x02) @@ -88,15 +110,25 @@ struct mpc52xx_gpt_priv { #define MPC52xx_GPT_MODE_GPIO_OUT_LOW (0x20) #define MPC52xx_GPT_MODE_GPIO_OUT_HIGH (0x30) +#define MPC52xx_GPT_MODE_COUNTER_ENABLE (0x1000) +#define MPC52xx_GPT_MODE_CONTINUOUS (0x0400) +#define MPC52xx_GPT_MODE_OPEN_DRAIN (0x0200) #define MPC52xx_GPT_MODE_IRQ_EN (0x0100) +#define MPC52xx_GPT_MODE_WDT_EN (0x8000) #define MPC52xx_GPT_MODE_ICT_MASK (0x030000) #define MPC52xx_GPT_MODE_ICT_RISING (0x010000) #define MPC52xx_GPT_MODE_ICT_FALLING (0x020000) #define MPC52xx_GPT_MODE_ICT_TOGGLE (0x030000) +#define MPC52xx_GPT_MODE_WDT_PING (0xa5) + #define MPC52xx_GPT_STATUS_IRQMASK (0x000f) +#define MPC52xx_GPT_CAN_WDT (1 << 0) +#define MPC52xx_GPT_IS_WDT (1 << 1) + + /* --------------------------------------------------------------------- * Cascaded interrupt controller hooks */ @@ -149,7 +181,7 @@ static int mpc52xx_gpt_irq_set_type(unsigned int virq, unsigned int flow_type) } static struct irq_chip mpc52xx_gpt_irq_chip = { - .typename = "MPC52xx GPT", + .name = "MPC52xx GPT", .unmask = mpc52xx_gpt_irq_unmask, .mask = mpc52xx_gpt_irq_mask, .ack = mpc52xx_gpt_irq_ack, @@ -182,7 +214,7 @@ static int mpc52xx_gpt_irq_map(struct irq_host *h, unsigned int virq, } static int mpc52xx_gpt_irq_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { @@ -190,7 +222,7 @@ static int mpc52xx_gpt_irq_xlate(struct irq_host *h, struct device_node *ct, dev_dbg(gpt->dev, "%s: flags=%i\n", __func__, intspec[0]); - if ((intsize < 1) || (intspec[0] < 1) || (intspec[0] > 3)) { + if ((intsize < 1) || (intspec[0] > 3)) { dev_err(gpt->dev, "bad irq specifier in %s\n", ct->full_name); return -EINVAL; } @@ -211,13 +243,11 @@ mpc52xx_gpt_irq_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node) { int cascade_virq; unsigned long flags; - - /* Only setup cascaded IRQ if device tree claims the GPT is - * an interrupt controller */ - if (!of_find_property(node, "interrupt-controller", NULL)) - return; + u32 mode; cascade_virq = irq_of_parse_and_map(node, 0); + if (!cascade_virq) + return; gpt->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, 1, &mpc52xx_gpt_irq_ops, -1); @@ -227,14 +257,16 @@ mpc52xx_gpt_irq_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node) } gpt->irqhost->host_data = gpt; - set_irq_data(cascade_virq, gpt); set_irq_chained_handler(cascade_virq, mpc52xx_gpt_irq_cascade); - /* Set to Input Capture mode */ + /* If the GPT is currently disabled, then change it to be in Input + * Capture mode. If the mode is non-zero, then the pin could be + * already in use for something. */ spin_lock_irqsave(&gpt->lock, flags); - clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_MS_MASK, - MPC52xx_GPT_MODE_MS_IC); + mode = in_be32(&gpt->regs->mode); + if ((mode & MPC52xx_GPT_MODE_MS_MASK) == 0) + out_be32(&gpt->regs->mode, mode | MPC52xx_GPT_MODE_MS_IC); spin_unlock_irqrestore(&gpt->lock, flags); dev_dbg(gpt->dev, "%s() complete. virq=%i\n", __func__, cascade_virq); @@ -335,6 +367,354 @@ static void mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *p, struct device_node *np) { } #endif /* defined(CONFIG_GPIOLIB) */ +/*********************************************************************** + * Timer API + */ + +/** + * mpc52xx_gpt_from_irq - Return the GPT device associated with an IRQ number + * @irq: irq of timer. + */ +struct mpc52xx_gpt_priv *mpc52xx_gpt_from_irq(int irq) +{ + struct mpc52xx_gpt_priv *gpt; + struct list_head *pos; + + /* Iterate over the list of timers looking for a matching device */ + mutex_lock(&mpc52xx_gpt_list_mutex); + list_for_each(pos, &mpc52xx_gpt_list) { + gpt = container_of(pos, struct mpc52xx_gpt_priv, list); + if (gpt->irqhost && irq == irq_linear_revmap(gpt->irqhost, 0)) { + mutex_unlock(&mpc52xx_gpt_list_mutex); + return gpt; + } + } + mutex_unlock(&mpc52xx_gpt_list_mutex); + + return NULL; +} +EXPORT_SYMBOL(mpc52xx_gpt_from_irq); + +static int mpc52xx_gpt_do_start(struct mpc52xx_gpt_priv *gpt, u64 period, + int continuous, int as_wdt) +{ + u32 clear, set; + u64 clocks; + u32 prescale; + unsigned long flags; + + clear = MPC52xx_GPT_MODE_MS_MASK | MPC52xx_GPT_MODE_CONTINUOUS; + set = MPC52xx_GPT_MODE_MS_GPIO | MPC52xx_GPT_MODE_COUNTER_ENABLE; + if (as_wdt) { + clear |= MPC52xx_GPT_MODE_IRQ_EN; + set |= MPC52xx_GPT_MODE_WDT_EN; + } else if (continuous) + set |= MPC52xx_GPT_MODE_CONTINUOUS; + + /* Determine the number of clocks in the requested period. 64 bit + * arithmatic is done here to preserve the precision until the value + * is scaled back down into the u32 range. Period is in 'ns', bus + * frequency is in Hz. */ + clocks = period * (u64)gpt->ipb_freq; + do_div(clocks, 1000000000); /* Scale it down to ns range */ + + /* This device cannot handle a clock count greater than 32 bits */ + if (clocks > 0xffffffff) + return -EINVAL; + + /* Calculate the prescaler and count values from the clocks value. + * 'clocks' is the number of clock ticks in the period. The timer + * has 16 bit precision and a 16 bit prescaler. Prescaler is + * calculated by integer dividing the clocks by 0x10000 (shifting + * down 16 bits) to obtain the smallest possible divisor for clocks + * to get a 16 bit count value. + * + * Note: the prescale register is '1' based, not '0' based. ie. a + * value of '1' means divide the clock by one. 0xffff divides the + * clock by 0xffff. '0x0000' does not divide by zero, but wraps + * around and divides by 0x10000. That is why prescale must be + * a u32 variable, not a u16, for this calculation. */ + prescale = (clocks >> 16) + 1; + do_div(clocks, prescale); + if (clocks > 0xffff) { + pr_err("calculation error; prescale:%x clocks:%llx\n", + prescale, clocks); + return -EINVAL; + } + + /* Set and enable the timer, reject an attempt to use a wdt as gpt */ + spin_lock_irqsave(&gpt->lock, flags); + if (as_wdt) + gpt->wdt_mode |= MPC52xx_GPT_IS_WDT; + else if ((gpt->wdt_mode & MPC52xx_GPT_IS_WDT) != 0) { + spin_unlock_irqrestore(&gpt->lock, flags); + return -EBUSY; + } + out_be32(&gpt->regs->count, prescale << 16 | clocks); + clrsetbits_be32(&gpt->regs->mode, clear, set); + spin_unlock_irqrestore(&gpt->lock, flags); + + return 0; +} + +/** + * mpc52xx_gpt_start_timer - Set and enable the GPT timer + * @gpt: Pointer to gpt private data structure + * @period: period of timer in ns; max. ~130s @ 33MHz IPB clock + * @continuous: set to 1 to make timer continuous free running + * + * An interrupt will be generated every time the timer fires + */ +int mpc52xx_gpt_start_timer(struct mpc52xx_gpt_priv *gpt, u64 period, + int continuous) +{ + return mpc52xx_gpt_do_start(gpt, period, continuous, 0); +} +EXPORT_SYMBOL(mpc52xx_gpt_start_timer); + +/** + * mpc52xx_gpt_stop_timer - Stop a gpt + * @gpt: Pointer to gpt private data structure + * + * Returns an error if attempting to stop a wdt + */ +int mpc52xx_gpt_stop_timer(struct mpc52xx_gpt_priv *gpt) +{ + unsigned long flags; + + /* reject the operation if the timer is used as watchdog (gpt 0 only) */ + spin_lock_irqsave(&gpt->lock, flags); + if ((gpt->wdt_mode & MPC52xx_GPT_IS_WDT) != 0) { + spin_unlock_irqrestore(&gpt->lock, flags); + return -EBUSY; + } + + clrbits32(&gpt->regs->mode, MPC52xx_GPT_MODE_COUNTER_ENABLE); + spin_unlock_irqrestore(&gpt->lock, flags); + return 0; +} +EXPORT_SYMBOL(mpc52xx_gpt_stop_timer); + +/** + * mpc52xx_gpt_timer_period - Read the timer period + * @gpt: Pointer to gpt private data structure + * + * Returns the timer period in ns + */ +u64 mpc52xx_gpt_timer_period(struct mpc52xx_gpt_priv *gpt) +{ + u64 period; + u64 prescale; + unsigned long flags; + + spin_lock_irqsave(&gpt->lock, flags); + period = in_be32(&gpt->regs->count); + spin_unlock_irqrestore(&gpt->lock, flags); + + prescale = period >> 16; + period &= 0xffff; + if (prescale == 0) + prescale = 0x10000; + period = period * prescale * 1000000000ULL; + do_div(period, (u64)gpt->ipb_freq); + return period; +} +EXPORT_SYMBOL(mpc52xx_gpt_timer_period); + +#if defined(CONFIG_MPC5200_WDT) +/*********************************************************************** + * Watchdog API for gpt0 + */ + +#define WDT_IDENTITY "mpc52xx watchdog on GPT0" + +/* wdt_is_active stores wether or not the /dev/watchdog device is opened */ +static unsigned long wdt_is_active; + +/* wdt-capable gpt */ +static struct mpc52xx_gpt_priv *mpc52xx_gpt_wdt; + +/* low-level wdt functions */ +static inline void mpc52xx_gpt_wdt_ping(struct mpc52xx_gpt_priv *gpt_wdt) +{ + unsigned long flags; + + spin_lock_irqsave(&gpt_wdt->lock, flags); + out_8((u8 *) &gpt_wdt->regs->mode, MPC52xx_GPT_MODE_WDT_PING); + spin_unlock_irqrestore(&gpt_wdt->lock, flags); +} + +/* wdt misc device api */ +static ssize_t mpc52xx_wdt_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + struct mpc52xx_gpt_priv *gpt_wdt = file->private_data; + mpc52xx_gpt_wdt_ping(gpt_wdt); + return 0; +} + +static struct watchdog_info mpc5200_wdt_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .identity = WDT_IDENTITY, +}; + +static long mpc52xx_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct mpc52xx_gpt_priv *gpt_wdt = file->private_data; + int __user *data = (int __user *)arg; + int timeout; + u64 real_timeout; + int ret = 0; + + switch (cmd) { + case WDIOC_GETSUPPORT: + ret = copy_to_user(data, &mpc5200_wdt_info, + sizeof(mpc5200_wdt_info)); + if (ret) + ret = -EFAULT; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + ret = put_user(0, data); + break; + + case WDIOC_KEEPALIVE: + mpc52xx_gpt_wdt_ping(gpt_wdt); + break; + + case WDIOC_SETTIMEOUT: + ret = get_user(timeout, data); + if (ret) + break; + real_timeout = (u64) timeout * 1000000000ULL; + ret = mpc52xx_gpt_do_start(gpt_wdt, real_timeout, 0, 1); + if (ret) + break; + /* fall through and return the timeout */ + + case WDIOC_GETTIMEOUT: + /* we need to round here as to avoid e.g. the following + * situation: + * - timeout requested is 1 second; + * - real timeout @33MHz is 999997090ns + * - the int divide by 10^9 will return 0. + */ + real_timeout = + mpc52xx_gpt_timer_period(gpt_wdt) + 500000000ULL; + do_div(real_timeout, 1000000000ULL); + timeout = (int) real_timeout; + ret = put_user(timeout, data); + break; + + default: + ret = -ENOTTY; + } + return ret; +} + +static int mpc52xx_wdt_open(struct inode *inode, struct file *file) +{ + int ret; + + /* sanity check */ + if (!mpc52xx_gpt_wdt) + return -ENODEV; + + /* /dev/watchdog can only be opened once */ + if (test_and_set_bit(0, &wdt_is_active)) + return -EBUSY; + + /* Set and activate the watchdog with 30 seconds timeout */ + ret = mpc52xx_gpt_do_start(mpc52xx_gpt_wdt, 30ULL * 1000000000ULL, + 0, 1); + if (ret) { + clear_bit(0, &wdt_is_active); + return ret; + } + + file->private_data = mpc52xx_gpt_wdt; + return nonseekable_open(inode, file); +} + +static int mpc52xx_wdt_release(struct inode *inode, struct file *file) +{ + /* note: releasing the wdt in NOWAYOUT-mode does not stop it */ +#if !defined(CONFIG_WATCHDOG_NOWAYOUT) + struct mpc52xx_gpt_priv *gpt_wdt = file->private_data; + unsigned long flags; + + spin_lock_irqsave(&gpt_wdt->lock, flags); + clrbits32(&gpt_wdt->regs->mode, + MPC52xx_GPT_MODE_COUNTER_ENABLE | MPC52xx_GPT_MODE_WDT_EN); + gpt_wdt->wdt_mode &= ~MPC52xx_GPT_IS_WDT; + spin_unlock_irqrestore(&gpt_wdt->lock, flags); +#endif + clear_bit(0, &wdt_is_active); + return 0; +} + + +static const struct file_operations mpc52xx_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = mpc52xx_wdt_write, + .unlocked_ioctl = mpc52xx_wdt_ioctl, + .open = mpc52xx_wdt_open, + .release = mpc52xx_wdt_release, +}; + +static struct miscdevice mpc52xx_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &mpc52xx_wdt_fops, +}; + +static int __devinit mpc52xx_gpt_wdt_init(void) +{ + int err; + + /* try to register the watchdog misc device */ + err = misc_register(&mpc52xx_wdt_miscdev); + if (err) + pr_err("%s: cannot register watchdog device\n", WDT_IDENTITY); + else + pr_info("%s: watchdog device registered\n", WDT_IDENTITY); + return err; +} + +static int mpc52xx_gpt_wdt_setup(struct mpc52xx_gpt_priv *gpt, + const u32 *period) +{ + u64 real_timeout; + + /* remember the gpt for the wdt operation */ + mpc52xx_gpt_wdt = gpt; + + /* configure the wdt if the device tree contained a timeout */ + if (!period || *period == 0) + return 0; + + real_timeout = (u64) *period * 1000000000ULL; + if (mpc52xx_gpt_do_start(gpt, real_timeout, 0, 1)) + dev_warn(gpt->dev, "starting as wdt failed\n"); + else + dev_info(gpt->dev, "watchdog set to %us timeout\n", *period); + return 0; +} + +#else + +static int __devinit mpc52xx_gpt_wdt_init(void) +{ + return 0; +} + +#define mpc52xx_gpt_wdt_setup(x, y) (0) + +#endif /* CONFIG_MPC5200_WDT */ + /* --------------------------------------------------------------------- * of_platform bus binding code */ @@ -349,6 +729,7 @@ static int __devinit mpc52xx_gpt_probe(struct of_device *ofdev, spin_lock_init(&gpt->lock); gpt->dev = &ofdev->dev; + gpt->ipb_freq = mpc5xxx_get_bus_frequency(ofdev->node); gpt->regs = of_iomap(ofdev->node, 0); if (!gpt->regs) { kfree(gpt); @@ -360,6 +741,26 @@ static int __devinit mpc52xx_gpt_probe(struct of_device *ofdev, mpc52xx_gpt_gpio_setup(gpt, ofdev->node); mpc52xx_gpt_irq_setup(gpt, ofdev->node); + mutex_lock(&mpc52xx_gpt_list_mutex); + list_add(&gpt->list, &mpc52xx_gpt_list); + mutex_unlock(&mpc52xx_gpt_list_mutex); + + /* check if this device could be a watchdog */ + if (of_get_property(ofdev->node, "fsl,has-wdt", NULL) || + of_get_property(ofdev->node, "has-wdt", NULL)) { + const u32 *on_boot_wdt; + + gpt->wdt_mode = MPC52xx_GPT_CAN_WDT; + on_boot_wdt = of_get_property(ofdev->node, "fsl,wdt-on-boot", + NULL); + if (on_boot_wdt) { + dev_info(gpt->dev, "used as watchdog\n"); + gpt->wdt_mode |= MPC52xx_GPT_IS_WDT; + } else + dev_info(gpt->dev, "can function as watchdog\n"); + mpc52xx_gpt_wdt_setup(gpt, on_boot_wdt); + } + return 0; } @@ -394,3 +795,4 @@ static int __init mpc52xx_gpt_init(void) /* Make sure GPIOs and IRQs get set up before anyone tries to use them */ subsys_initcall(mpc52xx_gpt_init); +device_initcall(mpc52xx_gpt_wdt_init); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c new file mode 100644 index 0000000000000000000000000000000000000000..929d017535a3cb583f13ac122f39cb5503e8478e --- /dev/null +++ b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c @@ -0,0 +1,560 @@ +/* + * LocalPlus Bus FIFO driver for the Freescale MPC52xx. + * + * Copyright (C) 2009 Secret Lab Technologies Ltd. + * + * This file is released under the GPLv2 + * + * Todo: + * - Add support for multiple requests to be queued. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +MODULE_AUTHOR("Grant Likely "); +MODULE_DESCRIPTION("MPC5200 LocalPlus FIFO device driver"); +MODULE_LICENSE("GPL"); + +#define LPBFIFO_REG_PACKET_SIZE (0x00) +#define LPBFIFO_REG_START_ADDRESS (0x04) +#define LPBFIFO_REG_CONTROL (0x08) +#define LPBFIFO_REG_ENABLE (0x0C) +#define LPBFIFO_REG_BYTES_DONE_STATUS (0x14) +#define LPBFIFO_REG_FIFO_DATA (0x40) +#define LPBFIFO_REG_FIFO_STATUS (0x44) +#define LPBFIFO_REG_FIFO_CONTROL (0x48) +#define LPBFIFO_REG_FIFO_ALARM (0x4C) + +struct mpc52xx_lpbfifo { + struct device *dev; + phys_addr_t regs_phys; + void __iomem *regs; + int irq; + spinlock_t lock; + + struct bcom_task *bcom_tx_task; + struct bcom_task *bcom_rx_task; + struct bcom_task *bcom_cur_task; + + /* Current state data */ + struct mpc52xx_lpbfifo_request *req; + int dma_irqs_enabled; +}; + +/* The MPC5200 has only one fifo, so only need one instance structure */ +static struct mpc52xx_lpbfifo lpbfifo; + +/** + * mpc52xx_lpbfifo_kick - Trigger the next block of data to be transfered + */ +static void mpc52xx_lpbfifo_kick(struct mpc52xx_lpbfifo_request *req) +{ + size_t transfer_size = req->size - req->pos; + struct bcom_bd *bd; + void __iomem *reg; + u32 *data; + int i; + int bit_fields; + int dma = !(req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA); + int write = req->flags & MPC52XX_LPBFIFO_FLAG_WRITE; + int poll_dma = req->flags & MPC52XX_LPBFIFO_FLAG_POLL_DMA; + + /* Set and clear the reset bits; is good practice in User Manual */ + out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); + + /* set master enable bit */ + out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x00000001); + if (!dma) { + /* While the FIFO can be setup for transfer sizes as large as + * 16M-1, the FIFO itself is only 512 bytes deep and it does + * not generate interrupts for FIFO full events (only transfer + * complete will raise an IRQ). Therefore when not using + * Bestcomm to drive the FIFO it needs to either be polled, or + * transfers need to constrained to the size of the fifo. + * + * This driver restricts the size of the transfer + */ + if (transfer_size > 512) + transfer_size = 512; + + /* Load the FIFO with data */ + if (write) { + reg = lpbfifo.regs + LPBFIFO_REG_FIFO_DATA; + data = req->data + req->pos; + for (i = 0; i < transfer_size; i += 4) + out_be32(reg, *data++); + } + + /* Unmask both error and completion irqs */ + out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x00000301); + } else { + /* Choose the correct direction + * + * Configure the watermarks so DMA will always complete correctly. + * It may be worth experimenting with the ALARM value to see if + * there is a performance impacit. However, if it is wrong there + * is a risk of DMA not transferring the last chunk of data + */ + if (write) { + out_be32(lpbfifo.regs + LPBFIFO_REG_FIFO_ALARM, 0x1e4); + out_8(lpbfifo.regs + LPBFIFO_REG_FIFO_CONTROL, 7); + lpbfifo.bcom_cur_task = lpbfifo.bcom_tx_task; + } else { + out_be32(lpbfifo.regs + LPBFIFO_REG_FIFO_ALARM, 0x1ff); + out_8(lpbfifo.regs + LPBFIFO_REG_FIFO_CONTROL, 0); + lpbfifo.bcom_cur_task = lpbfifo.bcom_rx_task; + + if (poll_dma) { + if (lpbfifo.dma_irqs_enabled) { + disable_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task)); + lpbfifo.dma_irqs_enabled = 0; + } + } else { + if (!lpbfifo.dma_irqs_enabled) { + enable_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task)); + lpbfifo.dma_irqs_enabled = 1; + } + } + } + + bd = bcom_prepare_next_buffer(lpbfifo.bcom_cur_task); + bd->status = transfer_size; + if (!write) { + /* + * In the DMA read case, the DMA doesn't complete, + * possibly due to incorrect watermarks in the ALARM + * and CONTROL regs. For now instead of trying to + * determine the right watermarks that will make this + * work, just increase the number of bytes the FIFO is + * expecting. + * + * When submitting another operation, the FIFO will get + * reset, so the condition of the FIFO waiting for a + * non-existent 4 bytes will get cleared. + */ + transfer_size += 4; /* BLECH! */ + } + bd->data[0] = req->data_phys + req->pos; + bcom_submit_next_buffer(lpbfifo.bcom_cur_task, NULL); + + /* error irq & master enabled bit */ + bit_fields = 0x00000201; + + /* Unmask irqs */ + if (write && (!poll_dma)) + bit_fields |= 0x00000100; /* completion irq too */ + out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, bit_fields); + } + + /* Set transfer size, width, chip select and READ mode */ + out_be32(lpbfifo.regs + LPBFIFO_REG_START_ADDRESS, + req->offset + req->pos); + out_be32(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, transfer_size); + + bit_fields = req->cs << 24 | 0x000008; + if (!write) + bit_fields |= 0x010000; /* read mode */ + out_be32(lpbfifo.regs + LPBFIFO_REG_CONTROL, bit_fields); + + /* Kick it off */ + out_8(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, 0x01); + if (dma) + bcom_enable(lpbfifo.bcom_cur_task); +} + +/** + * mpc52xx_lpbfifo_irq - IRQ handler for LPB FIFO + * + * On transmit, the dma completion irq triggers before the fifo completion + * triggers. Handle the dma completion here instead of the LPB FIFO Bestcomm + * task completion irq becuase everyting is not really done until the LPB FIFO + * completion irq triggers. + * + * In other words: + * For DMA, on receive, the "Fat Lady" is the bestcom completion irq. on + * transmit, the fifo completion irq is the "Fat Lady". The opera (or in this + * case the DMA/FIFO operation) is not finished until the "Fat Lady" sings. + * + * Reasons for entering this routine: + * 1) PIO mode rx and tx completion irq + * 2) DMA interrupt mode tx completion irq + * 3) DMA polled mode tx + * + * Exit conditions: + * 1) Transfer aborted + * 2) FIFO complete without DMA; more data to do + * 3) FIFO complete without DMA; all data transfered + * 4) FIFO complete using DMA + * + * Condition 1 can occur regardless of whether or not DMA is used. + * It requires executing the callback to report the error and exiting + * immediately. + * + * Condition 2 requires programming the FIFO with the next block of data + * + * Condition 3 requires executing the callback to report completion + * + * Condition 4 means the same as 3, except that we also retrieve the bcom + * buffer so DMA doesn't get clogged up. + * + * To make things trickier, the spinlock must be dropped before + * executing the callback, otherwise we could end up with a deadlock + * or nested spinlock condition. The out path is non-trivial, so + * extra fiddling is done to make sure all paths lead to the same + * outbound code. + */ +static irqreturn_t mpc52xx_lpbfifo_irq(int irq, void *dev_id) +{ + struct mpc52xx_lpbfifo_request *req; + u32 status = in_8(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS); + void __iomem *reg; + u32 *data; + int count, i; + int do_callback = 0; + u32 ts; + unsigned long flags; + int dma, write, poll_dma; + + spin_lock_irqsave(&lpbfifo.lock, flags); + ts = get_tbl(); + + req = lpbfifo.req; + if (!req) { + spin_unlock_irqrestore(&lpbfifo.lock, flags); + pr_err("bogus LPBFIFO IRQ\n"); + return IRQ_HANDLED; + } + + dma = !(req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA); + write = req->flags & MPC52XX_LPBFIFO_FLAG_WRITE; + poll_dma = req->flags & MPC52XX_LPBFIFO_FLAG_POLL_DMA; + + if (dma && !write) { + spin_unlock_irqrestore(&lpbfifo.lock, flags); + pr_err("bogus LPBFIFO IRQ (dma and not writting)\n"); + return IRQ_HANDLED; + } + + if ((status & 0x01) == 0) { + goto out; + } + + /* check abort bit */ + if (status & 0x10) { + out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); + do_callback = 1; + goto out; + } + + /* Read result from hardware */ + count = in_be32(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS); + count &= 0x00ffffff; + + if (!dma && !write) { + /* copy the data out of the FIFO */ + reg = lpbfifo.regs + LPBFIFO_REG_FIFO_DATA; + data = req->data + req->pos; + for (i = 0; i < count; i += 4) + *data++ = in_be32(reg); + } + + /* Update transfer position and count */ + req->pos += count; + + /* Decide what to do next */ + if (req->size - req->pos) + mpc52xx_lpbfifo_kick(req); /* more work to do */ + else + do_callback = 1; + + out: + /* Clear the IRQ */ + out_8(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS, 0x01); + + if (dma && (status & 0x11)) { + /* + * Count the DMA as complete only when the FIFO completion + * status or abort bits are set. + * + * (status & 0x01) should always be the case except sometimes + * when using polled DMA. + * + * (status & 0x10) {transfer aborted}: This case needs more + * testing. + */ + bcom_retrieve_buffer(lpbfifo.bcom_cur_task, &status, NULL); + } + req->last_byte = ((u8 *)req->data)[req->size - 1]; + + /* When the do_callback flag is set; it means the transfer is finished + * so set the FIFO as idle */ + if (do_callback) + lpbfifo.req = NULL; + + if (irq != 0) /* don't increment on polled case */ + req->irq_count++; + + req->irq_ticks += get_tbl() - ts; + spin_unlock_irqrestore(&lpbfifo.lock, flags); + + /* Spinlock is released; it is now safe to call the callback */ + if (do_callback && req->callback) + req->callback(req); + + return IRQ_HANDLED; +} + +/** + * mpc52xx_lpbfifo_bcom_irq - IRQ handler for LPB FIFO Bestcomm task + * + * Only used when receiving data. + */ +static irqreturn_t mpc52xx_lpbfifo_bcom_irq(int irq, void *dev_id) +{ + struct mpc52xx_lpbfifo_request *req; + unsigned long flags; + u32 status; + u32 ts; + + spin_lock_irqsave(&lpbfifo.lock, flags); + ts = get_tbl(); + + req = lpbfifo.req; + if (!req || (req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA)) { + spin_unlock_irqrestore(&lpbfifo.lock, flags); + return IRQ_HANDLED; + } + + if (irq != 0) /* don't increment on polled case */ + req->irq_count++; + + if (!bcom_buffer_done(lpbfifo.bcom_cur_task)) { + spin_unlock_irqrestore(&lpbfifo.lock, flags); + + req->buffer_not_done_cnt++; + if ((req->buffer_not_done_cnt % 1000) == 0) + pr_err("transfer stalled\n"); + + return IRQ_HANDLED; + } + + bcom_retrieve_buffer(lpbfifo.bcom_cur_task, &status, NULL); + + req->last_byte = ((u8 *)req->data)[req->size - 1]; + + req->pos = status & 0x00ffffff; + + /* Mark the FIFO as idle */ + lpbfifo.req = NULL; + + /* Release the lock before calling out to the callback. */ + req->irq_ticks += get_tbl() - ts; + spin_unlock_irqrestore(&lpbfifo.lock, flags); + + if (req->callback) + req->callback(req); + + return IRQ_HANDLED; +} + +/** + * mpc52xx_lpbfifo_bcom_poll - Poll for DMA completion + */ +void mpc52xx_lpbfifo_poll(void) +{ + struct mpc52xx_lpbfifo_request *req = lpbfifo.req; + int dma = !(req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA); + int write = req->flags & MPC52XX_LPBFIFO_FLAG_WRITE; + + /* + * For more information, see comments on the "Fat Lady" + */ + if (dma && write) + mpc52xx_lpbfifo_irq(0, NULL); + else + mpc52xx_lpbfifo_bcom_irq(0, NULL); +} +EXPORT_SYMBOL(mpc52xx_lpbfifo_poll); + +/** + * mpc52xx_lpbfifo_submit - Submit an LPB FIFO transfer request. + * @req: Pointer to request structure + */ +int mpc52xx_lpbfifo_submit(struct mpc52xx_lpbfifo_request *req) +{ + unsigned long flags; + + if (!lpbfifo.regs) + return -ENODEV; + + spin_lock_irqsave(&lpbfifo.lock, flags); + + /* If the req pointer is already set, then a transfer is in progress */ + if (lpbfifo.req) { + spin_unlock_irqrestore(&lpbfifo.lock, flags); + return -EBUSY; + } + + /* Setup the transfer */ + lpbfifo.req = req; + req->irq_count = 0; + req->irq_ticks = 0; + req->buffer_not_done_cnt = 0; + req->pos = 0; + + mpc52xx_lpbfifo_kick(req); + spin_unlock_irqrestore(&lpbfifo.lock, flags); + return 0; +} +EXPORT_SYMBOL(mpc52xx_lpbfifo_submit); + +void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req) +{ + unsigned long flags; + + spin_lock_irqsave(&lpbfifo.lock, flags); + if (lpbfifo.req == req) { + /* Put it into reset and clear the state */ + bcom_gen_bd_rx_reset(lpbfifo.bcom_rx_task); + bcom_gen_bd_tx_reset(lpbfifo.bcom_tx_task); + out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); + lpbfifo.req = NULL; + } + spin_unlock_irqrestore(&lpbfifo.lock, flags); +} +EXPORT_SYMBOL(mpc52xx_lpbfifo_abort); + +static int __devinit +mpc52xx_lpbfifo_probe(struct of_device *op, const struct of_device_id *match) +{ + struct resource res; + int rc = -ENOMEM; + + if (lpbfifo.dev != NULL) + return -ENOSPC; + + lpbfifo.irq = irq_of_parse_and_map(op->node, 0); + if (!lpbfifo.irq) + return -ENODEV; + + if (of_address_to_resource(op->node, 0, &res)) + return -ENODEV; + lpbfifo.regs_phys = res.start; + lpbfifo.regs = of_iomap(op->node, 0); + if (!lpbfifo.regs) + return -ENOMEM; + + spin_lock_init(&lpbfifo.lock); + + /* Put FIFO into reset */ + out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); + + /* Register the interrupt handler */ + rc = request_irq(lpbfifo.irq, mpc52xx_lpbfifo_irq, 0, + "mpc52xx-lpbfifo", &lpbfifo); + if (rc) + goto err_irq; + + /* Request the Bestcomm receive (fifo --> memory) task and IRQ */ + lpbfifo.bcom_rx_task = + bcom_gen_bd_rx_init(2, res.start + LPBFIFO_REG_FIFO_DATA, + BCOM_INITIATOR_SCLPC, BCOM_IPR_SCLPC, + 16*1024*1024); + if (!lpbfifo.bcom_rx_task) + goto err_bcom_rx; + + rc = request_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task), + mpc52xx_lpbfifo_bcom_irq, 0, + "mpc52xx-lpbfifo-rx", &lpbfifo); + if (rc) + goto err_bcom_rx_irq; + + /* Request the Bestcomm transmit (memory --> fifo) task and IRQ */ + lpbfifo.bcom_tx_task = + bcom_gen_bd_tx_init(2, res.start + LPBFIFO_REG_FIFO_DATA, + BCOM_INITIATOR_SCLPC, BCOM_IPR_SCLPC); + if (!lpbfifo.bcom_tx_task) + goto err_bcom_tx; + + lpbfifo.dev = &op->dev; + return 0; + + err_bcom_tx: + free_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task), &lpbfifo); + err_bcom_rx_irq: + bcom_gen_bd_rx_release(lpbfifo.bcom_rx_task); + err_bcom_rx: + err_irq: + iounmap(lpbfifo.regs); + lpbfifo.regs = NULL; + + dev_err(&op->dev, "mpc52xx_lpbfifo_probe() failed\n"); + return -ENODEV; +} + + +static int __devexit mpc52xx_lpbfifo_remove(struct of_device *op) +{ + if (lpbfifo.dev != &op->dev) + return 0; + + /* Put FIFO in reset */ + out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); + + /* Release the bestcomm transmit task */ + free_irq(bcom_get_task_irq(lpbfifo.bcom_tx_task), &lpbfifo); + bcom_gen_bd_tx_release(lpbfifo.bcom_tx_task); + + /* Release the bestcomm receive task */ + free_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task), &lpbfifo); + bcom_gen_bd_rx_release(lpbfifo.bcom_rx_task); + + free_irq(lpbfifo.irq, &lpbfifo); + iounmap(lpbfifo.regs); + lpbfifo.regs = NULL; + lpbfifo.dev = NULL; + + return 0; +} + +static struct of_device_id mpc52xx_lpbfifo_match[] __devinitconst = { + { .compatible = "fsl,mpc5200-lpbfifo", }, + {}, +}; + +static struct of_platform_driver mpc52xx_lpbfifo_driver = { + .owner = THIS_MODULE, + .name = "mpc52xx-lpbfifo", + .match_table = mpc52xx_lpbfifo_match, + .probe = mpc52xx_lpbfifo_probe, + .remove = __devexit_p(mpc52xx_lpbfifo_remove), +}; + +/*********************************************************************** + * Module init/exit + */ +static int __init mpc52xx_lpbfifo_init(void) +{ + pr_debug("Registering LocalPlus bus FIFO driver\n"); + return of_register_platform_driver(&mpc52xx_lpbfifo_driver); +} +module_init(mpc52xx_lpbfifo_init); + +static void __exit mpc52xx_lpbfifo_exit(void) +{ + pr_debug("Unregistering LocalPlus bus FIFO driver\n"); + of_unregister_platform_driver(&mpc52xx_lpbfifo_driver); +} +module_exit(mpc52xx_lpbfifo_exit); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 480f806fd0a9ce0f2818aecd4cb795ed8ab4610f..4bf4bf7b063ecabdc0c3d15fc11fbd21ca3aacc4 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c @@ -220,7 +220,7 @@ static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type) } static struct irq_chip mpc52xx_extirq_irqchip = { - .typename = "MPC52xx External", + .name = "MPC52xx External", .mask = mpc52xx_extirq_mask, .unmask = mpc52xx_extirq_unmask, .ack = mpc52xx_extirq_ack, @@ -258,7 +258,7 @@ static void mpc52xx_main_unmask(unsigned int virq) } static struct irq_chip mpc52xx_main_irqchip = { - .typename = "MPC52xx Main", + .name = "MPC52xx Main", .mask = mpc52xx_main_mask, .mask_ack = mpc52xx_main_mask, .unmask = mpc52xx_main_unmask, @@ -291,7 +291,7 @@ static void mpc52xx_periph_unmask(unsigned int virq) } static struct irq_chip mpc52xx_periph_irqchip = { - .typename = "MPC52xx Peripherals", + .name = "MPC52xx Peripherals", .mask = mpc52xx_periph_mask, .mask_ack = mpc52xx_periph_mask, .unmask = mpc52xx_periph_unmask, @@ -335,7 +335,7 @@ static void mpc52xx_sdma_ack(unsigned int virq) } static struct irq_chip mpc52xx_sdma_irqchip = { - .typename = "MPC52xx SDMA", + .name = "MPC52xx SDMA", .mask = mpc52xx_sdma_mask, .unmask = mpc52xx_sdma_unmask, .ack = mpc52xx_sdma_ack, @@ -355,7 +355,7 @@ static int mpc52xx_is_extirq(int l1, int l2) * mpc52xx_irqhost_xlate - translate virq# from device tree interrupts property */ static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c index 7ee979f323d18c2da64e8597973bba0823ed1e8b..9d962d7c72c114c94403b971ef6c168e2097e152 100644 --- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c +++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c @@ -69,7 +69,6 @@ static void pq2ads_pci_unmask_irq(unsigned int virq) } static struct irq_chip pq2ads_pci_ic = { - .typename = "PQ2 ADS PCI", .name = "PQ2 ADS PCI", .end = pq2ads_pci_unmask_irq, .mask = pq2ads_pci_mask_irq, @@ -107,7 +106,7 @@ static void pq2ads_pci_irq_demux(unsigned int irq, struct irq_desc *desc) static int pci_pic_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw) { - get_irq_desc(virq)->status |= IRQ_LEVEL; + irq_to_desc(virq)->status |= IRQ_LEVEL; set_irq_chip_data(virq, h->host_data); set_irq_chip_and_handler(virq, &pq2ads_pci_ic, handle_level_irq); return 0; diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index 567ded7c3b9be5fc3689be002e3e6163cdce3e8f..17f99745f0e459fbb26d0307833686ca2f61b362 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c @@ -74,7 +74,7 @@ static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk, prop = of_get_property(np, "mode", NULL); if (prop && !strcmp(prop, "cpu-qe")) - pdata.qe_mode = 1; + pdata.flags = SPI_QE_CPU_MODE; for (j = 0; j < num_board_infos; j++) { if (board_infos[j].bus_num == pdata.bus_num) diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c index 08e65fc8b98cfd4382f626b90badd3ddddf4e995..d306f07b9aa13ca6ee548ad8a56a436498f3cec0 100644 --- a/arch/powerpc/platforms/83xx/suspend.c +++ b/arch/powerpc/platforms/83xx/suspend.c @@ -96,6 +96,7 @@ int fsl_deep_sleep(void) { return deep_sleeping; } +EXPORT_SYMBOL(fsl_deep_sleep); static int mpc83xx_change_state(void) { diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index d3a975e8fd3e1c86bcfb913accb06c1e8bbb8c55..d95121894eb7d52dc5e56df8d61e2f5406d8b7cf 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -1,6 +1,7 @@ -menuconfig MPC85xx - bool "Machine Type" - depends on PPC_85xx +menuconfig FSL_SOC_BOOKE + bool "Freescale Book-E Machine Type" + depends on PPC_85xx || PPC_BOOK3E + select FSL_SOC select PPC_UDBG_16550 select MPIC select PPC_PCI_CHOICE @@ -8,7 +9,7 @@ menuconfig MPC85xx select SERIAL_8250_SHARE_IRQ if SERIAL_8250 default y -if MPC85xx +if FSL_SOC_BOOKE config MPC8540_ADS bool "Freescale MPC8540 ADS" @@ -144,7 +145,19 @@ config SBC8560 help This option enables support for the Wind River SBC8560 board -endif # MPC85xx +config P4080_DS + bool "Freescale P4080 DS" + select DEFAULT_UIMAGE + select PPC_FSL_BOOK3E + select PPC_E500MC + select PHYS_64BIT + select SWIOTLB + select MPC8xxx_GPIO + select HAS_RAPIDIO + help + This option enables support for the P4080 DS board + +endif # FSL_SOC_BOOKE config TQM85xx bool diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 9098aea0cf325c26e90c7c37f8d5b455c537ed72..387c128f2c8cb9523bf1174210280fb17f2ea9ac 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_MPC8536_DS) += mpc8536_ds.o obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o +obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o obj-$(CONFIG_STX_GP3) += stx_gp3.o obj-$(CONFIG_TQM85xx) += tqm85xx.o obj-$(CONFIG_SBC8560) += sbc8560.o diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c new file mode 100644 index 0000000000000000000000000000000000000000..534c2ecc89d904dfeff5448009f24405624522d4 --- /dev/null +++ b/arch/powerpc/platforms/85xx/corenet_ds.c @@ -0,0 +1,125 @@ +/* + * Corenet based SoC DS Setup + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * Copyright 2009 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 + +void __init corenet_ds_pic_init(void) +{ + struct mpic *mpic; + struct resource r; + struct device_node *np = NULL; + unsigned int flags = MPIC_PRIMARY | MPIC_BIG_ENDIAN | + MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU; + + np = of_find_node_by_type(np, "open-pic"); + + if (np == NULL) { + printk(KERN_ERR "Could not find open-pic node\n"); + return; + } + + if (of_address_to_resource(np, 0, &r)) { + printk(KERN_ERR "Failed to map mpic register space\n"); + of_node_put(np); + return; + } + + if (ppc_md.get_irq == mpic_get_coreint_irq) + flags |= MPIC_ENABLE_COREINT; + + mpic = mpic_alloc(np, r.start, flags, 0, 256, " OpenPIC "); + BUG_ON(mpic == NULL); + + mpic_init(mpic); +} + +#ifdef CONFIG_PCI +static int primary_phb_addr; +#endif + +/* + * Setup the architecture + */ +#ifdef CONFIG_SMP +void __init mpc85xx_smp_init(void); +#endif + +void __init corenet_ds_setup_arch(void) +{ +#ifdef CONFIG_PCI + struct device_node *np; + struct pci_controller *hose; +#endif + dma_addr_t max = 0xffffffff; + +#ifdef CONFIG_SMP + mpc85xx_smp_init(); +#endif + +#ifdef CONFIG_PCI + for_each_compatible_node(np, "pci", "fsl,p4080-pcie") { + struct resource rsrc; + of_address_to_resource(np, 0, &rsrc); + if ((rsrc.start & 0xfffff) == primary_phb_addr) + fsl_add_bridge(np, 1); + else + fsl_add_bridge(np, 0); + + hose = pci_find_hose_for_OF_device(np); + max = min(max, hose->dma_window_base_cur + + hose->dma_window_size); + } +#endif + +#ifdef CONFIG_SWIOTLB + if (lmb_end_of_DRAM() > max) { + ppc_swiotlb_enable = 1; + set_pci_dma_ops(&swiotlb_dma_ops); + ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; + } +#endif + pr_info("%s board from Freescale Semiconductor\n", ppc_md.name); +} + +static const struct of_device_id of_device_ids[] __devinitconst = { + { + .compatible = "simple-bus" + }, + { + .compatible = "fsl,rapidio-delta", + }, + {} +}; + +int __init corenet_ds_publish_devices(void) +{ + return of_platform_bus_probe(NULL, of_device_ids, NULL); +} diff --git a/arch/powerpc/platforms/85xx/corenet_ds.h b/arch/powerpc/platforms/85xx/corenet_ds.h new file mode 100644 index 0000000000000000000000000000000000000000..ddd700b23031e62f79bb395ce67f11f55a33c42f --- /dev/null +++ b/arch/powerpc/platforms/85xx/corenet_ds.h @@ -0,0 +1,19 @@ +/* + * Corenet based SoC DS Setup + * + * Copyright 2009 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 version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef CORENET_DS_H +#define CORENET_DS_H + +extern void __init corenet_ds_pic_init(void); +extern void __init corenet_ds_setup_arch(void); +extern int __init corenet_ds_publish_devices(void); + +#endif diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 3909d57b86e3aed43d2101db2b3fb25ad5d7d004..c5028a2e5a58510b9aa634c2cf09a114c096e373 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -301,6 +301,7 @@ static struct of_device_id mpc85xx_ids[] = { { .compatible = "fsl,qe", }, { .compatible = "gianfar", }, { .compatible = "fsl,rapidio-delta", }, + { .compatible = "fsl,mpc8548-guts", }, {}, }; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c index c8468de4acf656d96a98bf30790ba4b8bd9ed7fb..088f30b0c0883557ebe2d56a1bc2cf9ea2606753 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c @@ -44,6 +44,7 @@ void __init mpc85xx_rdb_pic_init(void) struct mpic *mpic; struct resource r; struct device_node *np; + unsigned long root = of_get_flat_dt_root(); np = of_find_node_by_type(NULL, "open-pic"); if (np == NULL) { @@ -57,11 +58,18 @@ void __init mpc85xx_rdb_pic_init(void) return; } - mpic = mpic_alloc(np, r.start, + if (of_flat_dt_is_compatible(root, "fsl,85XXRDB-CAMP")) { + mpic = mpic_alloc(np, r.start, + MPIC_PRIMARY | + MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS, + 0, 256, " OpenPIC "); + } else { + mpic = mpic_alloc(np, r.start, MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU, 0, 256, " OpenPIC "); + } BUG_ON(mpic == NULL); of_node_put(np); @@ -113,6 +121,7 @@ static int __init mpc85xxrdb_publish_devices(void) return of_platform_bus_probe(NULL, mpc85xxrdb_ids, NULL); } machine_device_initcall(p2020_rdb, mpc85xxrdb_publish_devices); +machine_device_initcall(p1020_rdb, mpc85xxrdb_publish_devices); /* * Called very early, device-tree isn't unflattened @@ -126,6 +135,15 @@ static int __init p2020_rdb_probe(void) return 0; } +static int __init p1020_rdb_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + if (of_flat_dt_is_compatible(root, "fsl,P1020RDB")) + return 1; + return 0; +} + define_machine(p2020_rdb) { .name = "P2020 RDB", .probe = p2020_rdb_probe, @@ -139,3 +157,17 @@ define_machine(p2020_rdb) { .calibrate_decr = generic_calibrate_decr, .progress = udbg_progress, }; + +define_machine(p1020_rdb) { + .name = "P1020 RDB", + .probe = p1020_rdb_probe, + .setup_arch = mpc85xx_rdb_setup_arch, + .init_IRQ = mpc85xx_rdb_pic_init, +#ifdef CONFIG_PCI + .pcibios_fixup_bus = fsl_pcibios_fixup_bus, +#endif + .get_irq = mpic_get_irq, + .restart = fsl_rstcr_restart, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/85xx/p4080_ds.c b/arch/powerpc/platforms/85xx/p4080_ds.c new file mode 100644 index 0000000000000000000000000000000000000000..84170460497ba19e3607c0efc9f4f3b4c2038508 --- /dev/null +++ b/arch/powerpc/platforms/85xx/p4080_ds.c @@ -0,0 +1,74 @@ +/* + * P4080 DS Setup + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * Copyright 2009 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 "corenet_ds.h" + +#ifdef CONFIG_PCI +static int primary_phb_addr; +#endif + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init p4080_ds_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + if (of_flat_dt_is_compatible(root, "fsl,P4080DS")) { +#ifdef CONFIG_PCI + /* treat PCIe1 as primary, + * shouldn't matter as we have no ISA on the board + */ + primary_phb_addr = 0x0000; +#endif + return 1; + } else { + return 0; + } +} + +define_machine(p4080_ds) { + .name = "P4080 DS", + .probe = p4080_ds_probe, + .setup_arch = corenet_ds_setup_arch, + .init_IRQ = corenet_ds_pic_init, +#ifdef CONFIG_PCI + .pcibios_fixup_bus = fsl_pcibios_fixup_bus, +#endif + .get_irq = mpic_get_coreint_irq, + .restart = fsl_rstcr_restart, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; + +machine_device_initcall(p4080_ds, corenet_ds_publish_devices); +machine_arch_initcall(p4080_ds, swiotlb_setup_bus_notifier); diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c index 60edf63d0157fbab56b6cdc473a15dfe01af3c9c..e5da5f62b24af4ef2a71b67455ce179f3a879896 100644 --- a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c +++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c @@ -232,7 +232,7 @@ static int socrates_fpga_pic_set_type(unsigned int virq, } static struct irq_chip socrates_fpga_pic_chip = { - .typename = " FPGA-PIC ", + .name = " FPGA-PIC ", .ack = socrates_fpga_pic_ack, .mask = socrates_fpga_pic_mask, .mask_ack = socrates_fpga_pic_mask_ack, @@ -245,7 +245,7 @@ static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hwirq) { /* All interrupts are LEVEL sensitive */ - get_irq_desc(virq)->status |= IRQ_LEVEL; + irq_to_desc(virq)->status |= IRQ_LEVEL; set_irq_chip_and_handler(virq, &socrates_fpga_pic_chip, handle_fasteoi_irq); @@ -253,7 +253,7 @@ static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq, } static int socrates_fpga_pic_host_xlate(struct irq_host *h, - struct device_node *ct, u32 *intspec, unsigned int intsize, + struct device_node *ct, const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { struct socrates_fpga_irq_info *fpga_irq = &fpga_irqs[intspec[0]]; diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 9c7b64a3402b69fc90c87c9f9a958b70092f6116..2bbfd530d6d8d26b09c6d0f311b83e339a5a224c 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -35,6 +35,7 @@ config MPC8610_HPCD config GEF_PPC9A bool "GE Fanuc PPC9A" select DEFAULT_UIMAGE + select MMIO_NVRAM select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB help @@ -43,6 +44,7 @@ config GEF_PPC9A config GEF_SBC310 bool "GE Fanuc SBC310" select DEFAULT_UIMAGE + select MMIO_NVRAM select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB help @@ -51,6 +53,7 @@ config GEF_SBC310 config GEF_SBC610 bool "GE Fanuc SBC610" select DEFAULT_UIMAGE + select MMIO_NVRAM select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select HAS_RAPIDIO diff --git a/arch/powerpc/platforms/86xx/gef_pic.c b/arch/powerpc/platforms/86xx/gef_pic.c index 50d0a2b6380954ac253707dd6c3cffc8d4465f4a..0110a8736d331976757de19ada74a1dd895cead2 100644 --- a/arch/powerpc/platforms/86xx/gef_pic.c +++ b/arch/powerpc/platforms/86xx/gef_pic.c @@ -149,7 +149,7 @@ static void gef_pic_unmask(unsigned int virq) } static struct irq_chip gef_pic_chip = { - .typename = "gefp", + .name = "gefp", .mask = gef_pic_mask, .mask_ack = gef_pic_mask_ack, .unmask = gef_pic_unmask, @@ -163,14 +163,14 @@ static int gef_pic_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hwirq) { /* All interrupts are LEVEL sensitive */ - get_irq_desc(virq)->status |= IRQ_LEVEL; + irq_to_desc(virq)->status |= IRQ_LEVEL; set_irq_chip_and_handler(virq, &gef_pic_chip, handle_level_irq); return 0; } static int gef_pic_host_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c index 287f7bd17dd9027067dfdcd96dd26f48a269bbb8..a792e5d858131510735557327f790d155b8d9ed9 100644 --- a/arch/powerpc/platforms/86xx/gef_ppc9a.c +++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -95,6 +96,10 @@ static void __init gef_ppc9a_setup_arch(void) printk(KERN_WARNING "Unable to map board registers\n"); of_node_put(regs); } + +#if defined(CONFIG_MMIO_NVRAM) + mmio_nvram_init(); +#endif } /* Return the PCB revision */ diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c index 90754e752bd827bafeb0680526cb6be41c55bee6..6a1a613836c27293c1c438e051252ba8bf122182 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc310.c +++ b/arch/powerpc/platforms/86xx/gef_sbc310.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -95,6 +96,10 @@ static void __init gef_sbc310_setup_arch(void) printk(KERN_WARNING "Unable to map board registers\n"); of_node_put(regs); } + +#if defined(CONFIG_MMIO_NVRAM) + mmio_nvram_init(); +#endif } /* Return the PCB revision */ diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c index 72b31a6010a0dd9a302662d562e8106e97c2cd69..e10688a0fc4eb9cb839142d81ea2558363db9b0a 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc610.c +++ b/arch/powerpc/platforms/86xx/gef_sbc610.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -95,6 +96,10 @@ static void __init gef_sbc610_setup_arch(void) printk(KERN_WARNING "Unable to map board registers\n"); of_node_put(regs); } + +#if defined(CONFIG_MMIO_NVRAM) + mmio_nvram_init(); +#endif } /* Return the PCB revision */ diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c index 627908a4cd77a974324bcdf3686c104624bdd340..5abe137f630926dc6ea8ab33d364a2af8f34f926 100644 --- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c +++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -41,10 +42,46 @@ #include "mpc86xx.h" +static struct device_node *pixis_node; static unsigned char *pixis_bdcfg0, *pixis_arch; +#ifdef CONFIG_SUSPEND +static irqreturn_t mpc8610_sw9_irq(int irq, void *data) +{ + pr_debug("%s: PIXIS' event (sw9/wakeup) IRQ handled\n", __func__); + return IRQ_HANDLED; +} + +static void __init mpc8610_suspend_init(void) +{ + int irq; + int ret; + + if (!pixis_node) + return; + + irq = irq_of_parse_and_map(pixis_node, 0); + if (!irq) { + pr_err("%s: can't map pixis event IRQ.\n", __func__); + return; + } + + ret = request_irq(irq, mpc8610_sw9_irq, 0, "sw9/wakeup", NULL); + if (ret) { + pr_err("%s: can't request pixis event IRQ: %d\n", + __func__, ret); + irq_dispose_mapping(irq); + } + + enable_irq_wake(irq); +} +#else +static inline void mpc8610_suspend_init(void) { } +#endif /* CONFIG_SUSPEND */ + static struct of_device_id __initdata mpc8610_ids[] = { { .compatible = "fsl,mpc8610-immr", }, + { .compatible = "fsl,mpc8610-guts", }, { .compatible = "simple-bus", }, { .compatible = "gianfar", }, {} @@ -55,6 +92,9 @@ static int __init mpc8610_declare_of_platform_devices(void) /* Firstly, register PIXIS GPIOs. */ simple_gpiochip_init("fsl,fpga-pixis-gpio-bank"); + /* Enable wakeup on PIXIS' event IRQ. */ + mpc8610_suspend_init(); + /* Without this call, the SSI device driver won't get probed. */ of_platform_bus_probe(NULL, mpc8610_ids, NULL); @@ -250,10 +290,10 @@ static void __init mpc86xx_hpcd_setup_arch(void) diu_ops.set_sysfs_monitor_port = mpc8610hpcd_set_sysfs_monitor_port; #endif - np = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis"); - if (np) { - of_address_to_resource(np, 0, &r); - of_node_put(np); + pixis_node = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis"); + if (pixis_node) { + of_address_to_resource(pixis_node, 0, &r); + of_node_put(pixis_node); pixis = ioremap(r.start, 32); if (!pixis) { printk(KERN_ERR "Err: can't map FPGA cfg register!\n"); diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c index 385acfc48397b8f2d2577326b78b49bb68b100f1..242954c4293f64fcc6222a15de3eb6df6e8c0941 100644 --- a/arch/powerpc/platforms/8xx/m8xx_setup.c +++ b/arch/powerpc/platforms/8xx/m8xx_setup.c @@ -222,7 +222,7 @@ static void cpm_cascade(unsigned int irq, struct irq_desc *desc) int cascade_irq; if ((cascade_irq = cpm_get_irq()) >= 0) { - struct irq_desc *cdesc = irq_desc + cascade_irq; + struct irq_desc *cdesc = irq_to_desc(cascade_irq); generic_handle_irq(cascade_irq); cdesc->chip->eoi(cascade_irq); diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 04a8061045c4feb3991945be7d619f849ea8320c..d1663db7810f3809fd6ea7658299d15d6425c347 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -86,6 +86,11 @@ config RTAS_ERROR_LOGGING depends on PPC_RTAS default n +config PPC_RTAS_DAEMON + bool + depends on PPC_RTAS + default n + config RTAS_PROC bool "Proc interface to RTAS" depends on PPC_RTAS @@ -255,7 +260,7 @@ config QE_GPIO config CPM2 bool "Enable support for the CPM2 (Communications Processor Module)" - depends on MPC85xx || 8260 + depends on (FSL_SOC_BOOKE && PPC32) || 8260 select CPM select PPC_LIB_RHEAP select PPC_PCI_CHOICE @@ -300,7 +305,7 @@ source "arch/powerpc/sysdev/bestcomm/Kconfig" config MPC8xxx_GPIO bool "MPC8xxx GPIO support" - depends on PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || PPC_85xx || PPC_86xx + depends on PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || FSL_SOC_BOOKE || PPC_86xx select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB help diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index e382cae678b880c9e57a754ea02695d3c07285e6..2eab27a94cc9451e0ab2c9b9e726c91a8ebb6155 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype @@ -28,8 +28,6 @@ config PPC_BOOK3S_32 config PPC_85xx bool "Freescale 85xx" select E500 - select FSL_SOC - select MPC85xx config PPC_8xx bool "Freescale 8xx" @@ -138,6 +136,14 @@ config PPC_FPU bool default y if PPC64 +config FSL_EMB_PERFMON + bool "Freescale Embedded Perfmon" + depends on E500 || PPC_83xx + help + This is the Performance Monitor support found on the e500 core + and some e300 cores (c3 and c4). Select this only if your + core supports the Embedded Performance Monitor APU + config 4xx bool depends on 40x || 44x @@ -153,13 +159,6 @@ config FSL_BOOKE depends on E200 || E500 default y -config FSL_EMB_PERFMON - bool "Freescale Embedded Perfmon" - depends on E500 || PPC_83xx - help - This is the Performance Monitor support found on the e500 core - and some e300 cores (c3 and c4). Select this only if your - core supports the Embedded Performance Monitor APU config PTE_64BIT bool diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index a6812ee00100e52869a0b52bb252fba49d13e0e7..fdb9f0b0d7a864f4a96bc6170cbc488ee88c4848 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -12,7 +12,7 @@ obj-$(CONFIG_PPC_MPC52xx) += 52xx/ obj-$(CONFIG_PPC_8xx) += 8xx/ obj-$(CONFIG_PPC_82xx) += 82xx/ obj-$(CONFIG_PPC_83xx) += 83xx/ -obj-$(CONFIG_PPC_85xx) += 85xx/ +obj-$(CONFIG_FSL_SOC_BOOKE) += 85xx/ obj-$(CONFIG_PPC_86xx) += 86xx/ obj-$(CONFIG_PPC_PSERIES) += pseries/ obj-$(CONFIG_PPC_ISERIES) += iseries/ diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index a86c34b3bb843b716459bad934054be9292adabc..96fe896f6df34707587d2694f8dcff13e7d369c9 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c @@ -312,7 +312,7 @@ static struct irq_chip msic_irq_chip = { .mask = mask_msi_irq, .unmask = unmask_msi_irq, .shutdown = unmask_msi_irq, - .typename = "AXON-MSI", + .name = "AXON-MSI", }; static int msic_host_map(struct irq_host *h, unsigned int virq, diff --git a/arch/powerpc/platforms/cell/beat_interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c index 72254848a228e86923e19310915091a3cdce632b..36052a9ebcda68e7fb4f5380309f684d1f9df47f 100644 --- a/arch/powerpc/platforms/cell/beat_interrupt.c +++ b/arch/powerpc/platforms/cell/beat_interrupt.c @@ -110,7 +110,7 @@ static void beatic_end_irq(unsigned int irq_plug) } static struct irq_chip beatic_pic = { - .typename = " CELL-BEAT ", + .name = " CELL-BEAT ", .unmask = beatic_unmask_irq, .mask = beatic_mask_irq, .eoi = beatic_end_irq, @@ -136,7 +136,7 @@ static void beatic_pic_host_unmap(struct irq_host *h, unsigned int virq) static int beatic_pic_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw) { - struct irq_desc *desc = get_irq_desc(virq); + struct irq_desc *desc = irq_to_desc(virq); int64_t err; err = beat_construct_and_connect_irq_plug(virq, hw); @@ -166,11 +166,11 @@ static void beatic_pic_host_remap(struct irq_host *h, unsigned int virq, * Note: We have only 1 entry to translate. */ static int beatic_pic_host_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { - u64 *intspec2 = (u64 *)intspec; + const u64 *intspec2 = (const u64 *)intspec; *out_hwirq = *intspec2; *out_flags |= IRQ_TYPE_LEVEL_LOW; diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 882e47080e74f493523399a0b1e7703c09b7b999..7267effc8078b53265e43898a7551f6adf2523d8 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -54,7 +54,7 @@ struct iic { struct device_node *node; }; -static DEFINE_PER_CPU(struct iic, iic); +static DEFINE_PER_CPU(struct iic, cpu_iic); #define IIC_NODE_COUNT 2 static struct irq_host *iic_host; @@ -82,13 +82,13 @@ static void iic_unmask(unsigned int irq) static void iic_eoi(unsigned int irq) { - struct iic *iic = &__get_cpu_var(iic); + struct iic *iic = &__get_cpu_var(cpu_iic); out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]); BUG_ON(iic->eoi_ptr < 0); } static struct irq_chip iic_chip = { - .typename = " CELL-IIC ", + .name = " CELL-IIC ", .mask = iic_mask, .unmask = iic_unmask, .eoi = iic_eoi, @@ -133,7 +133,7 @@ static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc) static struct irq_chip iic_ioexc_chip = { - .typename = " CELL-IOEX", + .name = " CELL-IOEX", .mask = iic_mask, .unmask = iic_unmask, .eoi = iic_ioexc_eoi, @@ -146,7 +146,7 @@ static unsigned int iic_get_irq(void) struct iic *iic; unsigned int virq; - iic = &__get_cpu_var(iic); + iic = &__get_cpu_var(cpu_iic); *(unsigned long *) &pending = in_be64((u64 __iomem *) &iic->regs->pending_destr); if (!(pending.flags & CBE_IIC_IRQ_VALID)) @@ -161,12 +161,12 @@ static unsigned int iic_get_irq(void) void iic_setup_cpu(void) { - out_be64(&__get_cpu_var(iic).regs->prio, 0xff); + out_be64(&__get_cpu_var(cpu_iic).regs->prio, 0xff); } u8 iic_get_target_id(int cpu) { - return per_cpu(iic, cpu).target_id; + return per_cpu(cpu_iic, cpu).target_id; } EXPORT_SYMBOL_GPL(iic_get_target_id); @@ -181,7 +181,7 @@ static inline int iic_ipi_to_irq(int ipi) void iic_cause_IPI(int cpu, int mesg) { - out_be64(&per_cpu(iic, cpu).regs->generate, (0xf - mesg) << 4); + out_be64(&per_cpu(cpu_iic, cpu).regs->generate, (0xf - mesg) << 4); } struct irq_host *iic_get_irq_host(int node) @@ -297,7 +297,7 @@ static int iic_host_map(struct irq_host *h, unsigned int virq, } static int iic_host_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { @@ -348,7 +348,7 @@ static void __init init_one_iic(unsigned int hw_cpu, unsigned long addr, /* XXX FIXME: should locate the linux CPU number from the HW cpu * number properly. We are lucky for now */ - struct iic *iic = &per_cpu(iic, hw_cpu); + struct iic *iic = &per_cpu(cpu_iic, hw_cpu); iic->regs = ioremap(addr, sizeof(struct cbe_iic_thread_regs)); BUG_ON(iic->regs == NULL); diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 4e5655624ae877f1e0c8de8eaac716fba9db4f21..01244f254a115ee32ff3019222b61abdc470a987 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c @@ -102,7 +102,7 @@ static void spider_ack_irq(unsigned int virq) /* Reset edge detection logic if necessary */ - if (get_irq_desc(virq)->status & IRQ_LEVEL) + if (irq_to_desc(virq)->status & IRQ_LEVEL) return; /* Only interrupts 47 to 50 can be set to edge */ @@ -119,7 +119,7 @@ static int spider_set_irq_type(unsigned int virq, unsigned int type) struct spider_pic *pic = spider_virq_to_pic(virq); unsigned int hw = irq_map[virq].hwirq; void __iomem *cfg = spider_get_irq_config(pic, hw); - struct irq_desc *desc = get_irq_desc(virq); + struct irq_desc *desc = irq_to_desc(virq); u32 old_mask; u32 ic; @@ -168,7 +168,7 @@ static int spider_set_irq_type(unsigned int virq, unsigned int type) } static struct irq_chip spider_pic = { - .typename = " SPIDER ", + .name = " SPIDER ", .unmask = spider_unmask_irq, .mask = spider_mask_irq, .ack = spider_ack_irq, @@ -187,7 +187,7 @@ static int spider_host_map(struct irq_host *h, unsigned int virq, } static int spider_host_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 884e8bcec499ff13718b7bb09f4148467cb6d22d..64a4c2d85f7cbd22671544a7ec3a65aac6fb37e9 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -2494,7 +2494,7 @@ static ssize_t spufs_switch_log_read(struct file *file, char __user *buf, struct spu_context *ctx = SPUFS_I(inode)->i_ctx; int error = 0, cnt = 0; - if (!buf || len < 0) + if (!buf) return -EINVAL; error = spu_acquire(ctx); diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig index 37d438bd5b7a10f29a9b40eafc8f2edf1cc5ffe1..bc0b0efdc5fe81c3969349d2814ebe3a665484b9 100644 --- a/arch/powerpc/platforms/chrp/Kconfig +++ b/arch/powerpc/platforms/chrp/Kconfig @@ -5,6 +5,8 @@ config PPC_CHRP select PPC_I8259 select PPC_INDIRECT_PCI select PPC_RTAS + select PPC_RTAS_DAEMON + select RTAS_ERROR_LOGGING select PPC_MPC106 select PPC_UDBG_16550 select PPC_NATIVE diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index cd4ad9aea760d966505a977d9d92e5a7f1f33e38..52f3df3b4ca0a6a196e1712e6038a303661b7aed 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -364,19 +364,6 @@ void __init chrp_setup_arch(void) if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0); } -void -chrp_event_scan(unsigned long unused) -{ - unsigned char log[1024]; - int ret = 0; - - /* XXX: we should loop until the hardware says no more error logs -- Cort */ - rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0, - __pa(log), 1024); - mod_timer(&__get_cpu_var(heartbeat_timer), - jiffies + event_scan_interval); -} - static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc) { unsigned int cascade_irq = i8259_irq(); @@ -568,9 +555,6 @@ void __init chrp_init_IRQ(void) void __init chrp_init2(void) { - struct device_node *device; - const unsigned int *p = NULL; - #ifdef CONFIG_NVRAM chrp_nvram_init(); #endif @@ -582,40 +566,6 @@ chrp_init2(void) request_region(0x80,0x10,"dma page reg"); request_region(0xc0,0x20,"dma2"); - /* Get the event scan rate for the rtas so we know how - * often it expects a heartbeat. -- Cort - */ - device = of_find_node_by_name(NULL, "rtas"); - if (device) - p = of_get_property(device, "rtas-event-scan-rate", NULL); - if (p && *p) { - /* - * Arrange to call chrp_event_scan at least *p times - * per minute. We use 59 rather than 60 here so that - * the rate will be slightly higher than the minimum. - * This all assumes we don't do hotplug CPU on any - * machine that needs the event scans done. - */ - unsigned long interval, offset; - int cpu, ncpus; - struct timer_list *timer; - - interval = HZ * 59 / *p; - offset = HZ; - ncpus = num_online_cpus(); - event_scan_interval = ncpus * interval; - for (cpu = 0; cpu < ncpus; ++cpu) { - timer = &per_cpu(heartbeat_timer, cpu); - setup_timer(timer, chrp_event_scan, 0); - timer->expires = jiffies + offset; - add_timer_on(timer, cpu); - offset += interval; - } - printk("RTAS Event Scan Rate: %u (%lu jiffies)\n", - *p, interval); - } - of_node_put(device); - if (ppc_md.progress) ppc_md.progress(" Have fun! ", 0x7777); } diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c index f99c6c4b698559ece7f60e6bb41a5ef4fd0e66bd..3ae66ab9d5e7f2082c810fd5bc588cc50ed36f82 100644 --- a/arch/powerpc/platforms/iseries/htab.c +++ b/arch/powerpc/platforms/iseries/htab.c @@ -19,8 +19,7 @@ #include "call_hpt.h" -static spinlock_t iSeries_hlocks[64] __cacheline_aligned_in_smp = - { [0 ... 63] = SPIN_LOCK_UNLOCKED}; +static spinlock_t iSeries_hlocks[64] __cacheline_aligned_in_smp; /* * Very primitive algorithm for picking up a lock @@ -245,6 +244,11 @@ static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va, void __init hpte_init_iSeries(void) { + int i; + + for (i = 0; i < ARRAY_SIZE(iSeries_hlocks); i++) + spin_lock_init(&iSeries_hlocks[i]); + ppc_md.hpte_invalidate = iSeries_hpte_invalidate; ppc_md.hpte_updatepp = iSeries_hpte_updatepp; ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp; diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 94f44475883685cdb6a6c2a940baac2c24c53622..07762259c60a864e598608eb5fb298eab7c57a8c 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -214,7 +214,7 @@ void __init iSeries_activate_IRQs() unsigned long flags; for_each_irq (irq) { - struct irq_desc *desc = get_irq_desc(irq); + struct irq_desc *desc = irq_to_desc(irq); if (desc && desc->chip && desc->chip->startup) { spin_lock_irqsave(&desc->lock, flags); @@ -273,7 +273,7 @@ static void iseries_end_IRQ(unsigned int irq) } static struct irq_chip iseries_pic = { - .typename = "iSeries irq controller", + .name = "iSeries irq controller", .startup = iseries_startup_IRQ, .shutdown = iseries_shutdown_IRQ, .unmask = iseries_enable_IRQ, diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index d212006a5b3c0d4ca5213acdf1d02e0939add083..09e827296276e24d3fa32ea728adcb040f95a8c1 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -152,12 +152,12 @@ static unsigned int pmac_startup_irq(unsigned int virq) unsigned long bit = 1UL << (src & 0x1f); int i = src >> 5; - spin_lock_irqsave(&pmac_pic_lock, flags); - if ((irq_desc[virq].status & IRQ_LEVEL) == 0) + spin_lock_irqsave(&pmac_pic_lock, flags); + if ((irq_to_desc(virq)->status & IRQ_LEVEL) == 0) out_le32(&pmac_irq_hw[i]->ack, bit); __set_bit(src, ppc_cached_irq_mask); __pmac_set_irq_mask(src, 0); - spin_unlock_irqrestore(&pmac_pic_lock, flags); + spin_unlock_irqrestore(&pmac_pic_lock, flags); return 0; } @@ -195,7 +195,7 @@ static int pmac_retrigger(unsigned int virq) } static struct irq_chip pmac_pic = { - .typename = " PMAC-PIC ", + .name = " PMAC-PIC ", .startup = pmac_startup_irq, .mask = pmac_mask_irq, .ack = pmac_ack_irq, @@ -285,7 +285,7 @@ static int pmac_pic_host_match(struct irq_host *h, struct device_node *node) static int pmac_pic_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw) { - struct irq_desc *desc = get_irq_desc(virq); + struct irq_desc *desc = irq_to_desc(virq); int level; if (hw >= max_irqs) @@ -303,7 +303,7 @@ static int pmac_pic_host_map(struct irq_host *h, unsigned int virq, } static int pmac_pic_host_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c index 8ec5ccf76b19e02f7e14385cf757ab558ba9662c..59d9712d7364ad3117fe558aecd4bd91068892ac 100644 --- a/arch/powerpc/platforms/ps3/interrupt.c +++ b/arch/powerpc/platforms/ps3/interrupt.c @@ -152,7 +152,7 @@ static void ps3_chip_eoi(unsigned int virq) */ static struct irq_chip ps3_irq_chip = { - .typename = "ps3", + .name = "ps3", .mask = ps3_chip_mask, .unmask = ps3_chip_unmask, .eoi = ps3_chip_eoi, diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c index 189a25b80735cb7c6731b3ce5d7ab9cd24ca605e..e81b028a2a48d8aca2efd0dcd7357ee9b4e9e62e 100644 --- a/arch/powerpc/platforms/ps3/mm.c +++ b/arch/powerpc/platforms/ps3/mm.c @@ -34,7 +34,7 @@ #if defined(DEBUG) #define DBG udbg_printf #else -#define DBG pr_debug +#define DBG pr_devel #endif enum { diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index f0e6f28427bdb00bf30d0164bbc751ad964b4c3b..27554c807fd503ffea29fb966438ce2f6e229052 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -4,6 +4,7 @@ config PPC_PSERIES select MPIC select PPC_I8259 select PPC_RTAS + select PPC_RTAS_DAEMON select RTAS_ERROR_LOGGING select PPC_UDBG_16550 select PPC_NATIVE @@ -59,7 +60,7 @@ config PPC_SMLPAR config CMM tristate "Collaborative memory management" - depends on PPC_SMLPAR && !CRASH_DUMP + depends on PPC_SMLPAR default y help Select this option, if you want to enable the kernel interface diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 790c0b872d4fc617594ba826dcbeab9fb1d3d837..0ff5174ae4f5a7da1acc7774d6b2016d0949a9aa 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -7,8 +7,8 @@ EXTRA_CFLAGS += -DDEBUG endif obj-y := lpar.o hvCall.o nvram.o reconfig.o \ - setup.o iommu.o ras.o rtasd.o \ - firmware.o power.o + setup.o iommu.o ras.o \ + firmware.o power.o dlpar.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_XICS) += xics.o obj-$(CONFIG_SCANLOG) += scanlog.o diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c index 6567439fe78dda4512e0524332255df66b5816a1..bcdcf0ccc8d799ffde04e138e1b6fa2736d968e2 100644 --- a/arch/powerpc/platforms/pseries/cmm.c +++ b/arch/powerpc/platforms/pseries/cmm.c @@ -229,8 +229,9 @@ static void cmm_get_mpp(void) { int rc; struct hvcall_mpp_data mpp_data; - unsigned long active_pages_target; - signed long page_loan_request; + signed long active_pages_target, page_loan_request, target; + signed long total_pages = totalram_pages + loaned_pages; + signed long min_mem_pages = (min_mem_mb * 1024 * 1024) / PAGE_SIZE; rc = h_get_mpp(&mpp_data); @@ -238,17 +239,25 @@ static void cmm_get_mpp(void) return; page_loan_request = div_s64((s64)mpp_data.loan_request, PAGE_SIZE); - loaned_pages_target = page_loan_request + loaned_pages; - if (loaned_pages_target > oom_freed_pages) - loaned_pages_target -= oom_freed_pages; + target = page_loan_request + (signed long)loaned_pages; + + if (target < 0 || total_pages < min_mem_pages) + target = 0; + + if (target > oom_freed_pages) + target -= oom_freed_pages; else - loaned_pages_target = 0; + target = 0; + + active_pages_target = total_pages - target; + + if (min_mem_pages > active_pages_target) + target = total_pages - min_mem_pages; - active_pages_target = totalram_pages + loaned_pages - loaned_pages_target; + if (target < 0) + target = 0; - if ((min_mem_mb * 1024 * 1024) > (active_pages_target * PAGE_SIZE)) - loaned_pages_target = totalram_pages + loaned_pages - - ((min_mem_mb * 1024 * 1024) / PAGE_SIZE); + loaned_pages_target = target; cmm_dbg("delta = %ld, loaned = %lu, target = %lu, oom = %lu, totalram = %lu\n", page_loan_request, loaned_pages, loaned_pages_target, diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c new file mode 100644 index 0000000000000000000000000000000000000000..12df9e8812a9f258c864d01a255647ffe4c1b41e --- /dev/null +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -0,0 +1,558 @@ +/* + * Support for dynamic reconfiguration for PCI, Memory, and CPU + * Hotplug and Dynamic Logical Partitioning on RPA platforms. + * + * Copyright (C) 2009 Nathan Fontenot + * Copyright (C) 2009 IBM Corporation + * + * 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 "offline_states.h" + +#include +#include +#include +#include +#include + +struct cc_workarea { + u32 drc_index; + u32 zero; + u32 name_offset; + u32 prop_length; + u32 prop_offset; +}; + +static void dlpar_free_cc_property(struct property *prop) +{ + kfree(prop->name); + kfree(prop->value); + kfree(prop); +} + +static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa) +{ + struct property *prop; + char *name; + char *value; + + prop = kzalloc(sizeof(*prop), GFP_KERNEL); + if (!prop) + return NULL; + + name = (char *)ccwa + ccwa->name_offset; + prop->name = kstrdup(name, GFP_KERNEL); + + prop->length = ccwa->prop_length; + value = (char *)ccwa + ccwa->prop_offset; + prop->value = kzalloc(prop->length, GFP_KERNEL); + if (!prop->value) { + dlpar_free_cc_property(prop); + return NULL; + } + + memcpy(prop->value, value, prop->length); + return prop; +} + +static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa) +{ + struct device_node *dn; + char *name; + + dn = kzalloc(sizeof(*dn), GFP_KERNEL); + if (!dn) + return NULL; + + /* The configure connector reported name does not contain a + * preceeding '/', so we allocate a buffer large enough to + * prepend this to the full_name. + */ + name = (char *)ccwa + ccwa->name_offset; + dn->full_name = kmalloc(strlen(name) + 2, GFP_KERNEL); + if (!dn->full_name) { + kfree(dn); + return NULL; + } + + sprintf(dn->full_name, "/%s", name); + return dn; +} + +static void dlpar_free_one_cc_node(struct device_node *dn) +{ + struct property *prop; + + while (dn->properties) { + prop = dn->properties; + dn->properties = prop->next; + dlpar_free_cc_property(prop); + } + + kfree(dn->full_name); + kfree(dn); +} + +static void dlpar_free_cc_nodes(struct device_node *dn) +{ + if (dn->child) + dlpar_free_cc_nodes(dn->child); + + if (dn->sibling) + dlpar_free_cc_nodes(dn->sibling); + + dlpar_free_one_cc_node(dn); +} + +#define NEXT_SIBLING 1 +#define NEXT_CHILD 2 +#define NEXT_PROPERTY 3 +#define PREV_PARENT 4 +#define MORE_MEMORY 5 +#define CALL_AGAIN -2 +#define ERR_CFG_USE -9003 + +struct device_node *dlpar_configure_connector(u32 drc_index) +{ + struct device_node *dn; + struct device_node *first_dn = NULL; + struct device_node *last_dn = NULL; + struct property *property; + struct property *last_property = NULL; + struct cc_workarea *ccwa; + int cc_token; + int rc; + + cc_token = rtas_token("ibm,configure-connector"); + if (cc_token == RTAS_UNKNOWN_SERVICE) + return NULL; + + spin_lock(&rtas_data_buf_lock); + ccwa = (struct cc_workarea *)&rtas_data_buf[0]; + ccwa->drc_index = drc_index; + ccwa->zero = 0; + + rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL); + while (rc) { + switch (rc) { + case NEXT_SIBLING: + dn = dlpar_parse_cc_node(ccwa); + if (!dn) + goto cc_error; + + dn->parent = last_dn->parent; + last_dn->sibling = dn; + last_dn = dn; + break; + + case NEXT_CHILD: + dn = dlpar_parse_cc_node(ccwa); + if (!dn) + goto cc_error; + + if (!first_dn) + first_dn = dn; + else { + dn->parent = last_dn; + if (last_dn) + last_dn->child = dn; + } + + last_dn = dn; + break; + + case NEXT_PROPERTY: + property = dlpar_parse_cc_property(ccwa); + if (!property) + goto cc_error; + + if (!last_dn->properties) + last_dn->properties = property; + else + last_property->next = property; + + last_property = property; + break; + + case PREV_PARENT: + last_dn = last_dn->parent; + break; + + case CALL_AGAIN: + break; + + case MORE_MEMORY: + case ERR_CFG_USE: + default: + printk(KERN_ERR "Unexpected Error (%d) " + "returned from configure-connector\n", rc); + goto cc_error; + } + + rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL); + } + + spin_unlock(&rtas_data_buf_lock); + return first_dn; + +cc_error: + if (first_dn) + dlpar_free_cc_nodes(first_dn); + spin_unlock(&rtas_data_buf_lock); + return NULL; +} + +static struct device_node *derive_parent(const char *path) +{ + struct device_node *parent; + char *last_slash; + + last_slash = strrchr(path, '/'); + if (last_slash == path) { + parent = of_find_node_by_path("/"); + } else { + char *parent_path; + int parent_path_len = last_slash - path + 1; + parent_path = kmalloc(parent_path_len, GFP_KERNEL); + if (!parent_path) + return NULL; + + strlcpy(parent_path, path, parent_path_len); + parent = of_find_node_by_path(parent_path); + kfree(parent_path); + } + + return parent; +} + +int dlpar_attach_node(struct device_node *dn) +{ + struct proc_dir_entry *ent; + int rc; + + of_node_set_flag(dn, OF_DYNAMIC); + kref_init(&dn->kref); + dn->parent = derive_parent(dn->full_name); + if (!dn->parent) + return -ENOMEM; + + rc = blocking_notifier_call_chain(&pSeries_reconfig_chain, + PSERIES_RECONFIG_ADD, dn); + if (rc == NOTIFY_BAD) { + printk(KERN_ERR "Failed to add device node %s\n", + dn->full_name); + return -ENOMEM; /* For now, safe to assume kmalloc failure */ + } + + of_attach_node(dn); + +#ifdef CONFIG_PROC_DEVICETREE + ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde); + if (ent) + proc_device_tree_add_node(dn, ent); +#endif + + of_node_put(dn->parent); + return 0; +} + +int dlpar_detach_node(struct device_node *dn) +{ + struct device_node *parent = dn->parent; + struct property *prop = dn->properties; + +#ifdef CONFIG_PROC_DEVICETREE + while (prop) { + remove_proc_entry(prop->name, dn->pde); + prop = prop->next; + } + + if (dn->pde) + remove_proc_entry(dn->pde->name, parent->pde); +#endif + + blocking_notifier_call_chain(&pSeries_reconfig_chain, + PSERIES_RECONFIG_REMOVE, dn); + of_detach_node(dn); + of_node_put(dn); /* Must decrement the refcount */ + + return 0; +} + +#define DR_ENTITY_SENSE 9003 +#define DR_ENTITY_PRESENT 1 +#define DR_ENTITY_UNUSABLE 2 +#define ALLOCATION_STATE 9003 +#define ALLOC_UNUSABLE 0 +#define ALLOC_USABLE 1 +#define ISOLATION_STATE 9001 +#define ISOLATE 0 +#define UNISOLATE 1 + +int dlpar_acquire_drc(u32 drc_index) +{ + int dr_status, rc; + + rc = rtas_call(rtas_token("get-sensor-state"), 2, 2, &dr_status, + DR_ENTITY_SENSE, drc_index); + if (rc || dr_status != DR_ENTITY_UNUSABLE) + return -1; + + rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_USABLE); + if (rc) + return rc; + + rc = rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE); + if (rc) { + rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE); + return rc; + } + + return 0; +} + +int dlpar_release_drc(u32 drc_index) +{ + int dr_status, rc; + + rc = rtas_call(rtas_token("get-sensor-state"), 2, 2, &dr_status, + DR_ENTITY_SENSE, drc_index); + if (rc || dr_status != DR_ENTITY_PRESENT) + return -1; + + rc = rtas_set_indicator(ISOLATION_STATE, drc_index, ISOLATE); + if (rc) + return rc; + + rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE); + if (rc) { + rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE); + return rc; + } + + return 0; +} + +#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE + +static DEFINE_MUTEX(pseries_cpu_hotplug_mutex); + +void cpu_hotplug_driver_lock() +{ + mutex_lock(&pseries_cpu_hotplug_mutex); +} + +void cpu_hotplug_driver_unlock() +{ + mutex_unlock(&pseries_cpu_hotplug_mutex); +} + +static int dlpar_online_cpu(struct device_node *dn) +{ + int rc = 0; + unsigned int cpu; + int len, nthreads, i; + const u32 *intserv; + + intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len); + if (!intserv) + return -EINVAL; + + nthreads = len / sizeof(u32); + + cpu_maps_update_begin(); + for (i = 0; i < nthreads; i++) { + for_each_present_cpu(cpu) { + if (get_hard_smp_processor_id(cpu) != intserv[i]) + continue; + BUG_ON(get_cpu_current_state(cpu) + != CPU_STATE_OFFLINE); + cpu_maps_update_done(); + rc = cpu_up(cpu); + if (rc) + goto out; + cpu_maps_update_begin(); + + break; + } + if (cpu == num_possible_cpus()) + printk(KERN_WARNING "Could not find cpu to online " + "with physical id 0x%x\n", intserv[i]); + } + cpu_maps_update_done(); + +out: + return rc; + +} + +static ssize_t dlpar_cpu_probe(const char *buf, size_t count) +{ + struct device_node *dn; + unsigned long drc_index; + char *cpu_name; + int rc; + + cpu_hotplug_driver_lock(); + rc = strict_strtoul(buf, 0, &drc_index); + if (rc) { + rc = -EINVAL; + goto out; + } + + dn = dlpar_configure_connector(drc_index); + if (!dn) { + rc = -EINVAL; + goto out; + } + + /* configure-connector reports cpus as living in the base + * directory of the device tree. CPUs actually live in the + * cpus directory so we need to fixup the full_name. + */ + cpu_name = kzalloc(strlen(dn->full_name) + strlen("/cpus") + 1, + GFP_KERNEL); + if (!cpu_name) { + dlpar_free_cc_nodes(dn); + rc = -ENOMEM; + goto out; + } + + sprintf(cpu_name, "/cpus%s", dn->full_name); + kfree(dn->full_name); + dn->full_name = cpu_name; + + rc = dlpar_acquire_drc(drc_index); + if (rc) { + dlpar_free_cc_nodes(dn); + rc = -EINVAL; + goto out; + } + + rc = dlpar_attach_node(dn); + if (rc) { + dlpar_release_drc(drc_index); + dlpar_free_cc_nodes(dn); + } + + rc = dlpar_online_cpu(dn); +out: + cpu_hotplug_driver_unlock(); + + return rc ? rc : count; +} + +static int dlpar_offline_cpu(struct device_node *dn) +{ + int rc = 0; + unsigned int cpu; + int len, nthreads, i; + const u32 *intserv; + + intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len); + if (!intserv) + return -EINVAL; + + nthreads = len / sizeof(u32); + + cpu_maps_update_begin(); + for (i = 0; i < nthreads; i++) { + for_each_present_cpu(cpu) { + if (get_hard_smp_processor_id(cpu) != intserv[i]) + continue; + + if (get_cpu_current_state(cpu) == CPU_STATE_OFFLINE) + break; + + if (get_cpu_current_state(cpu) == CPU_STATE_ONLINE) { + cpu_maps_update_done(); + rc = cpu_down(cpu); + if (rc) + goto out; + cpu_maps_update_begin(); + break; + + } + + /* + * The cpu is in CPU_STATE_INACTIVE. + * Upgrade it's state to CPU_STATE_OFFLINE. + */ + set_preferred_offline_state(cpu, CPU_STATE_OFFLINE); + BUG_ON(plpar_hcall_norets(H_PROD, intserv[i]) + != H_SUCCESS); + __cpu_die(cpu); + break; + } + if (cpu == num_possible_cpus()) + printk(KERN_WARNING "Could not find cpu to offline " + "with physical id 0x%x\n", intserv[i]); + } + cpu_maps_update_done(); + +out: + return rc; + +} + +static ssize_t dlpar_cpu_release(const char *buf, size_t count) +{ + struct device_node *dn; + const u32 *drc_index; + int rc; + + dn = of_find_node_by_path(buf); + if (!dn) + return -EINVAL; + + drc_index = of_get_property(dn, "ibm,my-drc-index", NULL); + if (!drc_index) { + of_node_put(dn); + return -EINVAL; + } + + cpu_hotplug_driver_lock(); + rc = dlpar_offline_cpu(dn); + if (rc) { + of_node_put(dn); + rc = -EINVAL; + goto out; + } + + rc = dlpar_release_drc(*drc_index); + if (rc) { + of_node_put(dn); + goto out; + } + + rc = dlpar_detach_node(dn); + if (rc) { + dlpar_acquire_drc(*drc_index); + goto out; + } + + of_node_put(dn); +out: + cpu_hotplug_driver_unlock(); + return rc ? rc : count; +} + +static int __init pseries_dlpar_init(void) +{ + ppc_md.cpu_probe = dlpar_cpu_probe; + ppc_md.cpu_release = dlpar_cpu_release; + + return 0; +} +machine_device_initcall(pseries, pseries_dlpar_init); + +#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c index 937a544a236d5e1a58be64b821d23bb20e965c63..c5f3116b6ca524e8b08aff7193ca796ccd089e00 100644 --- a/arch/powerpc/platforms/pseries/dtl.c +++ b/arch/powerpc/platforms/pseries/dtl.c @@ -54,7 +54,7 @@ struct dtl { int buf_entries; u64 last_idx; }; -static DEFINE_PER_CPU(struct dtl, dtl); +static DEFINE_PER_CPU(struct dtl, cpu_dtl); /* * Dispatch trace log event mask: @@ -261,7 +261,7 @@ static int dtl_init(void) /* set up the per-cpu log structures */ for_each_possible_cpu(i) { - struct dtl *dtl = &per_cpu(dtl, i); + struct dtl *dtl = &per_cpu(cpu_dtl, i); dtl->cpu = i; rc = dtl_setup_file(dtl); diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 0e8db6771252a2f3dcb4c28891e0f6d2958389a0..ef8e45448480836bba0097606e6dca9c92afb6a3 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -63,22 +63,6 @@ static void print_device_node_tree(struct pci_dn *pdn, int dent) } #endif -/** - * irq_in_use - return true if this irq is being used - */ -static int irq_in_use(unsigned int irq) -{ - int rc = 0; - unsigned long flags; - struct irq_desc *desc = irq_desc + irq; - - spin_lock_irqsave(&desc->lock, flags); - if (desc->action) - rc = 1; - spin_unlock_irqrestore(&desc->lock, flags); - return rc; -} - /** * eeh_disable_irq - disable interrupt for the recovering device */ @@ -93,7 +77,7 @@ static void eeh_disable_irq(struct pci_dev *dev) if (dev->msi_enabled || dev->msix_enabled) return; - if (!irq_in_use(dev->irq)) + if (!irq_has_action(dev->irq)) return; PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED; diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index ebff6d9a4e395ae0088da5a26e99459cedc2f0f5..6ea4698d9176dc08b9ec73f139e5e25544693555 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -30,6 +30,7 @@ #include #include "xics.h" #include "plpar_wrappers.h" +#include "offline_states.h" /* This version can't take the spinlock, because it never returns */ static struct rtas_args rtas_stop_self_args = { @@ -39,6 +40,55 @@ static struct rtas_args rtas_stop_self_args = { .rets = &rtas_stop_self_args.args[0], }; +static DEFINE_PER_CPU(enum cpu_state_vals, preferred_offline_state) = + CPU_STATE_OFFLINE; +static DEFINE_PER_CPU(enum cpu_state_vals, current_state) = CPU_STATE_OFFLINE; + +static enum cpu_state_vals default_offline_state = CPU_STATE_OFFLINE; + +static int cede_offline_enabled __read_mostly = 1; + +/* + * Enable/disable cede_offline when available. + */ +static int __init setup_cede_offline(char *str) +{ + if (!strcmp(str, "off")) + cede_offline_enabled = 0; + else if (!strcmp(str, "on")) + cede_offline_enabled = 1; + else + return 0; + return 1; +} + +__setup("cede_offline=", setup_cede_offline); + +enum cpu_state_vals get_cpu_current_state(int cpu) +{ + return per_cpu(current_state, cpu); +} + +void set_cpu_current_state(int cpu, enum cpu_state_vals state) +{ + per_cpu(current_state, cpu) = state; +} + +enum cpu_state_vals get_preferred_offline_state(int cpu) +{ + return per_cpu(preferred_offline_state, cpu); +} + +void set_preferred_offline_state(int cpu, enum cpu_state_vals state) +{ + per_cpu(preferred_offline_state, cpu) = state; +} + +void set_default_offline_state(int cpu) +{ + per_cpu(preferred_offline_state, cpu) = default_offline_state; +} + static void rtas_stop_self(void) { struct rtas_args *args = &rtas_stop_self_args; @@ -56,11 +106,61 @@ static void rtas_stop_self(void) static void pseries_mach_cpu_die(void) { + unsigned int cpu = smp_processor_id(); + unsigned int hwcpu = hard_smp_processor_id(); + u8 cede_latency_hint = 0; + local_irq_disable(); idle_task_exit(); xics_teardown_cpu(); - unregister_slb_shadow(hard_smp_processor_id(), __pa(get_slb_shadow())); - rtas_stop_self(); + + if (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) { + set_cpu_current_state(cpu, CPU_STATE_INACTIVE); + cede_latency_hint = 2; + + get_lppaca()->idle = 1; + if (!get_lppaca()->shared_proc) + get_lppaca()->donate_dedicated_cpu = 1; + + printk(KERN_INFO + "cpu %u (hwid %u) ceding for offline with hint %d\n", + cpu, hwcpu, cede_latency_hint); + while (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) { + extended_cede_processor(cede_latency_hint); + printk(KERN_INFO "cpu %u (hwid %u) returned from cede.\n", + cpu, hwcpu); + printk(KERN_INFO + "Decrementer value = %x Timebase value = %llx\n", + get_dec(), get_tb()); + } + + printk(KERN_INFO "cpu %u (hwid %u) got prodded to go online\n", + cpu, hwcpu); + + if (!get_lppaca()->shared_proc) + get_lppaca()->donate_dedicated_cpu = 0; + get_lppaca()->idle = 0; + } + + if (get_preferred_offline_state(cpu) == CPU_STATE_ONLINE) { + unregister_slb_shadow(hwcpu, __pa(get_slb_shadow())); + + /* + * NOTE: Calling start_secondary() here for now to + * start new context. + * However, need to do it cleanly by resetting the + * stack pointer. + */ + start_secondary(); + + } else if (get_preferred_offline_state(cpu) == CPU_STATE_OFFLINE) { + + set_cpu_current_state(cpu, CPU_STATE_OFFLINE); + unregister_slb_shadow(hard_smp_processor_id(), + __pa(get_slb_shadow())); + rtas_stop_self(); + } + /* Should never get here... */ BUG(); for(;;); @@ -106,18 +206,43 @@ static int pseries_cpu_disable(void) return 0; } +/* + * pseries_cpu_die: Wait for the cpu to die. + * @cpu: logical processor id of the CPU whose death we're awaiting. + * + * This function is called from the context of the thread which is performing + * the cpu-offline. Here we wait for long enough to allow the cpu in question + * to self-destroy so that the cpu-offline thread can send the CPU_DEAD + * notifications. + * + * OTOH, pseries_mach_cpu_die() is called by the @cpu when it wants to + * self-destruct. + */ static void pseries_cpu_die(unsigned int cpu) { int tries; - int cpu_status; + int cpu_status = 1; unsigned int pcpu = get_hard_smp_processor_id(cpu); - for (tries = 0; tries < 25; tries++) { - cpu_status = query_cpu_stopped(pcpu); - if (cpu_status == 0 || cpu_status == -1) - break; - cpu_relax(); + if (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) { + cpu_status = 1; + for (tries = 0; tries < 1000; tries++) { + if (get_cpu_current_state(cpu) == CPU_STATE_INACTIVE) { + cpu_status = 0; + break; + } + cpu_relax(); + } + } else if (get_preferred_offline_state(cpu) == CPU_STATE_OFFLINE) { + + for (tries = 0; tries < 25; tries++) { + cpu_status = query_cpu_stopped(pcpu); + if (cpu_status == 0 || cpu_status == -1) + break; + cpu_relax(); + } } + if (cpu_status != 0) { printk("Querying DEAD? cpu %i (%i) shows %i\n", cpu, pcpu, cpu_status); @@ -252,10 +377,41 @@ static struct notifier_block pseries_smp_nb = { .notifier_call = pseries_smp_notifier, }; +#define MAX_CEDE_LATENCY_LEVELS 4 +#define CEDE_LATENCY_PARAM_LENGTH 10 +#define CEDE_LATENCY_PARAM_MAX_LENGTH \ + (MAX_CEDE_LATENCY_LEVELS * CEDE_LATENCY_PARAM_LENGTH * sizeof(char)) +#define CEDE_LATENCY_TOKEN 45 + +static char cede_parameters[CEDE_LATENCY_PARAM_MAX_LENGTH]; + +static int parse_cede_parameters(void) +{ + int call_status; + + memset(cede_parameters, 0, CEDE_LATENCY_PARAM_MAX_LENGTH); + call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1, + NULL, + CEDE_LATENCY_TOKEN, + __pa(cede_parameters), + CEDE_LATENCY_PARAM_MAX_LENGTH); + + if (call_status != 0) + printk(KERN_INFO "CEDE_LATENCY: \ + %s %s Error calling get-system-parameter(0x%x)\n", + __FILE__, __func__, call_status); + else + printk(KERN_INFO "CEDE_LATENCY: \ + get-system-parameter successful.\n"); + + return call_status; +} + static int __init pseries_cpu_hotplug_init(void) { struct device_node *np; const char *typep; + int cpu; for_each_node_by_name(np, "interrupt-controller") { typep = of_get_property(np, "compatible", NULL); @@ -283,8 +439,16 @@ static int __init pseries_cpu_hotplug_init(void) smp_ops->cpu_die = pseries_cpu_die; /* Processors can be added/removed only on LPAR */ - if (firmware_has_feature(FW_FEATURE_LPAR)) + if (firmware_has_feature(FW_FEATURE_LPAR)) { pSeries_reconfig_notifier_register(&pseries_smp_nb); + cpu_maps_update_begin(); + if (cede_offline_enabled && parse_cede_parameters() == 0) { + default_offline_state = CPU_STATE_INACTIVE; + for_each_online_cpu(cpu) + set_default_offline_state(cpu); + } + cpu_maps_update_done(); + } return 0; } diff --git a/arch/powerpc/platforms/pseries/offline_states.h b/arch/powerpc/platforms/pseries/offline_states.h new file mode 100644 index 0000000000000000000000000000000000000000..22574e0d9d91d69417d5a11282d5722844c685a9 --- /dev/null +++ b/arch/powerpc/platforms/pseries/offline_states.h @@ -0,0 +1,18 @@ +#ifndef _OFFLINE_STATES_H_ +#define _OFFLINE_STATES_H_ + +/* Cpu offline states go here */ +enum cpu_state_vals { + CPU_STATE_OFFLINE, + CPU_STATE_INACTIVE, + CPU_STATE_ONLINE, + CPU_MAX_OFFLINE_STATES +}; + +extern enum cpu_state_vals get_cpu_current_state(int cpu); +extern void set_cpu_current_state(int cpu, enum cpu_state_vals state); +extern enum cpu_state_vals get_preferred_offline_state(int cpu); +extern void set_preferred_offline_state(int cpu, enum cpu_state_vals state); +extern void set_default_offline_state(int cpu); +extern int start_secondary(void); +#endif diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h index a24a6b2333b2388521989ac5ac2b38365a61e6ab..0603c91538ae1aeed09d42c4902625199ed98e7a 100644 --- a/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h @@ -9,11 +9,33 @@ static inline long poll_pending(void) return plpar_hcall_norets(H_POLL_PENDING); } +static inline u8 get_cede_latency_hint(void) +{ + return get_lppaca()->gpr5_dword.fields.cede_latency_hint; +} + +static inline void set_cede_latency_hint(u8 latency_hint) +{ + get_lppaca()->gpr5_dword.fields.cede_latency_hint = latency_hint; +} + static inline long cede_processor(void) { return plpar_hcall_norets(H_CEDE); } +static inline long extended_cede_processor(unsigned long latency_hint) +{ + long rc; + u8 old_latency_hint = get_cede_latency_hint(); + + set_cede_latency_hint(latency_hint); + rc = cede_processor(); + set_cede_latency_hint(old_latency_hint); + + return rc; +} + static inline long vpa_call(unsigned long flags, unsigned long cpu, unsigned long vpa) { diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 2e2bbe120b908ec2816067214006f969f6504492..a2305d29bbbdb822f89cb64041f66e245aaf9ad9 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -96,7 +96,7 @@ static struct device_node *derive_parent(const char *path) return parent; } -static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); +BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); int pSeries_reconfig_notifier_register(struct notifier_block *nb) { @@ -184,7 +184,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np) } /* - * /proc/ppc64/ofdt - yucky binary interface for adding and removing + * /proc/powerpc/ofdt - yucky binary interface for adding and removing * OF device nodes. Should be deprecated as soon as we get an * in-kernel wrapper for the RTAS ibm,configure-connector call. */ @@ -543,7 +543,7 @@ static const struct file_operations ofdt_fops = { .write = ofdt_write }; -/* create /proc/ppc64/ofdt write-only by root */ +/* create /proc/powerpc/ofdt write-only by root */ static int proc_ppc64_create_ofdt(void) { struct proc_dir_entry *ent; @@ -551,7 +551,7 @@ static int proc_ppc64_create_ofdt(void) if (!machine_is(pseries)) return 0; - ent = proc_create("ppc64/ofdt", S_IWUSR, NULL, &ofdt_fops); + ent = proc_create("powerpc/ofdt", S_IWUSR, NULL, &ofdt_fops); if (ent) ent->size = 0; diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index 417eca79df697ed35eb9b29d41ef15cd1a1891b2..1b45c458f952fc6da9cb0b9e3ebb63416023ae06 100644 --- a/arch/powerpc/platforms/pseries/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c @@ -13,7 +13,7 @@ * of this data using this driver. A dump exists if the device-tree * /chosen/ibm,scan-log-data property exists. * - * This driver exports /proc/ppc64/scan-log-dump which can be read. + * This driver exports /proc/powerpc/scan-log-dump which can be read. * The driver supports only sequential reads. * * The driver looks at a write to the driver for the single word "reset". @@ -186,7 +186,7 @@ static int __init scanlog_init(void) if (!data) goto err; - ent = proc_create_data("ppc64/rtas/scan-log-dump", S_IRUSR, NULL, + ent = proc_create_data("powerpc/rtas/scan-log-dump", S_IRUSR, NULL, &scanlog_fops, data); if (!ent) goto err; diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 440000cc71307ac83df8ac251af13085c910aec6..8868c012268a45ebf348d41dcc023699ee0954e8 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -48,6 +48,7 @@ #include "plpar_wrappers.h" #include "pseries.h" #include "xics.h" +#include "offline_states.h" /* @@ -84,6 +85,9 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) /* Fixup atomic count: it exited inside IRQ handler. */ task_thread_info(paca[lcpu].__current)->preempt_count = 0; + if (get_cpu_current_state(lcpu) == CPU_STATE_INACTIVE) + goto out; + /* * If the RTAS start-cpu token does not exist then presume the * cpu is already spinning. @@ -98,6 +102,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) return 0; } +out: return 1; } @@ -111,12 +116,16 @@ static void __devinit smp_xics_setup_cpu(int cpu) vpa_init(cpu); cpu_clear(cpu, of_spin_map); + set_cpu_current_state(cpu, CPU_STATE_ONLINE); + set_default_offline_state(cpu); } #endif /* CONFIG_XICS */ static void __devinit smp_pSeries_kick_cpu(int nr) { + long rc; + unsigned long hcpuid; BUG_ON(nr < 0 || nr >= NR_CPUS); if (!smp_startup_cpu(nr)) @@ -128,6 +137,16 @@ static void __devinit smp_pSeries_kick_cpu(int nr) * the processor will continue on to secondary_start */ paca[nr].cpu_start = 1; + + set_preferred_offline_state(nr, CPU_STATE_ONLINE); + + if (get_cpu_current_state(nr) == CPU_STATE_INACTIVE) { + hcpuid = get_hard_smp_processor_id(nr); + rc = plpar_hcall_norets(H_PROD, hcpuid); + if (rc != H_SUCCESS) + panic("Error: Prod to wake up processor %d Ret= %ld\n", + nr, rc); + } } static int smp_pSeries_cpu_bootable(unsigned int nr) diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index b9bf0eedccf27a18eefd3c640d44cc37f16b1708..7d01b58f3989042e162ba11a534030e94574d7d5 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,12 @@ static struct irq_host *xics_host; */ #define IPI_PRIORITY 4 +/* The least favored priority */ +#define LOWEST_PRIORITY 0xFF + +/* The number of priorities defined above */ +#define MAX_NUM_PRIORITIES 3 + static unsigned int default_server = 0xFF; static unsigned int default_distrib_server = 0; static unsigned int interrupt_server_size = 8; @@ -56,6 +63,12 @@ static int ibm_set_xive; static int ibm_int_on; static int ibm_int_off; +struct xics_cppr { + unsigned char stack[MAX_NUM_PRIORITIES]; + int index; +}; + +static DEFINE_PER_CPU(struct xics_cppr, xics_cppr); /* Direct hardware low level accessors */ @@ -157,7 +170,7 @@ static int get_irq_server(unsigned int virq, unsigned int strict_check) cpumask_t cpumask; cpumask_t tmp = CPU_MASK_NONE; - cpumask_copy(&cpumask, irq_desc[virq].affinity); + cpumask_copy(&cpumask, irq_to_desc(virq)->affinity); if (!distribute_irqs) return default_server; @@ -284,6 +297,19 @@ static inline unsigned int xics_xirr_vector(unsigned int xirr) return xirr & 0x00ffffff; } +static void push_cppr(unsigned int vec) +{ + struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); + + if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1)) + return; + + if (vec == XICS_IPI) + os_cppr->stack[++os_cppr->index] = IPI_PRIORITY; + else + os_cppr->stack[++os_cppr->index] = DEFAULT_PRIORITY; +} + static unsigned int xics_get_irq_direct(void) { unsigned int xirr = direct_xirr_info_get(); @@ -294,8 +320,10 @@ static unsigned int xics_get_irq_direct(void) return NO_IRQ; irq = irq_radix_revmap_lookup(xics_host, vec); - if (likely(irq != NO_IRQ)) + if (likely(irq != NO_IRQ)) { + push_cppr(vec); return irq; + } /* We don't have a linux mapping, so have rtas mask it. */ xics_mask_unknown_vec(vec); @@ -315,8 +343,10 @@ static unsigned int xics_get_irq_lpar(void) return NO_IRQ; irq = irq_radix_revmap_lookup(xics_host, vec); - if (likely(irq != NO_IRQ)) + if (likely(irq != NO_IRQ)) { + push_cppr(vec); return irq; + } /* We don't have a linux mapping, so have RTAS mask it. */ xics_mask_unknown_vec(vec); @@ -326,12 +356,22 @@ static unsigned int xics_get_irq_lpar(void) return NO_IRQ; } +static unsigned char pop_cppr(void) +{ + struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); + + if (WARN_ON(os_cppr->index < 1)) + return LOWEST_PRIORITY; + + return os_cppr->stack[--os_cppr->index]; +} + static void xics_eoi_direct(unsigned int virq) { unsigned int irq = (unsigned int)irq_map[virq].hwirq; iosync(); - direct_xirr_info_set((0xff << 24) | irq); + direct_xirr_info_set((pop_cppr() << 24) | irq); } static void xics_eoi_lpar(unsigned int virq) @@ -339,7 +379,7 @@ static void xics_eoi_lpar(unsigned int virq) unsigned int irq = (unsigned int)irq_map[virq].hwirq; iosync(); - lpar_xirr_info_set((0xff << 24) | irq); + lpar_xirr_info_set((pop_cppr() << 24) | irq); } static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask) @@ -388,7 +428,7 @@ static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask) } static struct irq_chip xics_pic_direct = { - .typename = " XICS ", + .name = " XICS ", .startup = xics_startup, .mask = xics_mask_irq, .unmask = xics_unmask_irq, @@ -397,7 +437,7 @@ static struct irq_chip xics_pic_direct = { }; static struct irq_chip xics_pic_lpar = { - .typename = " XICS ", + .name = " XICS ", .startup = xics_startup, .mask = xics_mask_irq, .unmask = xics_unmask_irq, @@ -428,13 +468,13 @@ static int xics_host_map(struct irq_host *h, unsigned int virq, /* Insert the interrupt mapping into the radix tree for fast lookup */ irq_radix_revmap_insert(xics_host, virq, hw); - get_irq_desc(virq)->status |= IRQ_LEVEL; + irq_to_desc(virq)->status |= IRQ_LEVEL; set_irq_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq); return 0; } static int xics_host_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { @@ -746,6 +786,12 @@ void __init xics_init_IRQ(void) static void xics_set_cpu_priority(unsigned char cppr) { + struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); + + BUG_ON(os_cppr->index != 0); + + os_cppr->stack[os_cppr->index] = cppr; + if (firmware_has_feature(FW_FEATURE_LPAR)) lpar_cppr_info(cppr); else @@ -772,7 +818,7 @@ static void xics_set_cpu_giq(unsigned int gserver, unsigned int join) void xics_setup_cpu(void) { - xics_set_cpu_priority(0xff); + xics_set_cpu_priority(LOWEST_PRIORITY); xics_set_cpu_giq(default_distrib_server, 1); } @@ -852,7 +898,7 @@ void xics_migrate_irqs_away(void) /* We need to get IPIs still. */ if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) continue; - desc = get_irq_desc(virq); + desc = irq_to_desc(virq); /* We only need to migrate enabled IRQS */ if (desc == NULL || desc->chip == NULL @@ -881,7 +927,7 @@ void xics_migrate_irqs_away(void) virq, cpu); /* Reset affinity to all cpus */ - cpumask_setall(irq_desc[virq].affinity); + cpumask_setall(irq_to_desc(virq)->affinity); desc->chip->set_affinity(virq, cpu_all_mask); unlock: spin_unlock_irqrestore(&desc->lock, flags); diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 9d4b17462f1308815b29a18368fbb14b37d9e9e6..5642924fb9fb437637d4fe963253ce9d0b75a58d 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y) +obj-$(CONFIG_FSL_PMC) += fsl_pmc.o obj-$(CONFIG_FSL_LBC) += fsl_lbc.o obj-$(CONFIG_FSL_GTM) += fsl_gtm.o obj-$(CONFIG_MPC8xxx_GPIO) += mpc8xxx_gpio.o diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c index 82424cd7e1287bcc009b81f2327b078229a6050f..a4b41dbde128ca261146cbde35de5ae9fe26d76c 100644 --- a/arch/powerpc/sysdev/cpm1.c +++ b/arch/powerpc/sysdev/cpm1.c @@ -77,7 +77,7 @@ static void cpm_end_irq(unsigned int irq) } static struct irq_chip cpm_pic = { - .typename = " CPM PIC ", + .name = " CPM PIC ", .mask = cpm_mask_irq, .unmask = cpm_unmask_irq, .eoi = cpm_end_irq, @@ -102,7 +102,7 @@ static int cpm_pic_host_map(struct irq_host *h, unsigned int virq, { pr_debug("cpm_pic_host_map(%d, 0x%lx)\n", virq, hw); - get_irq_desc(virq)->status |= IRQ_LEVEL; + irq_to_desc(virq)->status |= IRQ_LEVEL; set_irq_chip_and_handler(virq, &cpm_pic, handle_fasteoi_irq); return 0; } diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c index 78f1f7cca0a017ba6ee17d83065ba1544f0dbb71..971483f0dfacd9f104246045a9300b80014ebe98 100644 --- a/arch/powerpc/sysdev/cpm2_pic.c +++ b/arch/powerpc/sysdev/cpm2_pic.c @@ -115,11 +115,13 @@ static void cpm2_ack(unsigned int virq) static void cpm2_end_irq(unsigned int virq) { + struct irq_desc *desc; int bit, word; unsigned int irq_nr = virq_to_hw(virq); - if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) - && irq_desc[irq_nr].action) { + desc = irq_to_desc(irq_nr); + if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)) + && desc->action) { bit = irq_to_siubit[irq_nr]; word = irq_to_siureg[irq_nr]; @@ -138,7 +140,7 @@ static void cpm2_end_irq(unsigned int virq) static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) { unsigned int src = virq_to_hw(virq); - struct irq_desc *desc = get_irq_desc(virq); + struct irq_desc *desc = irq_to_desc(virq); unsigned int vold, vnew, edibit; if (flow_type == IRQ_TYPE_NONE) @@ -182,7 +184,7 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) } static struct irq_chip cpm2_pic = { - .typename = " CPM2 SIU ", + .name = " CPM2 SIU ", .mask = cpm2_mask_irq, .unmask = cpm2_unmask_irq, .ack = cpm2_ack, @@ -210,13 +212,13 @@ static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq, { pr_debug("cpm2_pic_host_map(%d, 0x%lx)\n", virq, hw); - get_irq_desc(virq)->status |= IRQ_LEVEL; + irq_to_desc(virq)->status |= IRQ_LEVEL; set_irq_chip_and_handler(virq, &cpm2_pic, handle_level_irq); return 0; } static int cpm2_pic_host_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { *out_hwirq = intspec[0]; diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c index e4b6d66d93dedfe610193950ac74021dc797048d..9de72c96e6d1b9718631d9a63a9f8e326b133796 100644 --- a/arch/powerpc/sysdev/cpm_common.c +++ b/arch/powerpc/sysdev/cpm_common.c @@ -72,7 +72,7 @@ static phys_addr_t muram_pbase; /* Max address size we deal with */ #define OF_MAX_ADDR_CELLS 4 -int __init cpm_muram_init(void) +int cpm_muram_init(void) { struct device_node *np; struct resource r; @@ -81,6 +81,9 @@ int __init cpm_muram_init(void) int i = 0; int ret = 0; + if (muram_pbase) + return 0; + spin_lock_init(&cpm_muram_lock); /* initialize the info header */ rh_init(&cpm_muram_info, 1, diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index da38a1ff97bb47b0b58955191313dbec4b233ea5..62e50258cdef9e9ca9a320b0dbc613c4e3fed446 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -47,7 +47,7 @@ static struct irq_chip fsl_msi_chip = { .mask = mask_msi_irq, .unmask = unmask_msi_irq, .ack = fsl_msi_end_irq, - .typename = " FSL-MSI ", + .name = " FSL-MSI ", }; static int fsl_msi_host_map(struct irq_host *h, unsigned int virq, @@ -55,7 +55,7 @@ static int fsl_msi_host_map(struct irq_host *h, unsigned int virq, { struct irq_chip *chip = &fsl_msi_chip; - get_irq_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING; + irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING; set_irq_chip_and_handler(virq, chip, handle_edge_irq); diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index ae88b1448018391d29b6aea018161cd80d708995..4e3a3e345ab33cd5b8d435c3415e244e664f70c7 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -56,7 +56,7 @@ static int __init fsl_pcie_check_link(struct pci_controller *hose) return 0; } -#if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) +#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) static int __init setup_one_atmu(struct ccsr_pci __iomem *pci, unsigned int index, const struct resource *res, resource_size_t offset) @@ -392,9 +392,23 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1011E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1011, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_header); -#endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */ +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080, quirk_fsl_pcie_header); +#endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */ #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x) DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314E, quirk_fsl_pcie_header); diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c new file mode 100644 index 0000000000000000000000000000000000000000..a7635a993dca545c144c3183201337f89997eaa1 --- /dev/null +++ b/arch/powerpc/sysdev/fsl_pmc.c @@ -0,0 +1,88 @@ +/* + * Suspend/resume support + * + * Copyright 2009 MontaVista Software, Inc. + * + * Author: Anton Vorontsov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 pmc_regs { + __be32 devdisr; + __be32 devdisr2; + __be32 :32; + __be32 :32; + __be32 pmcsr; +#define PMCSR_SLP (1 << 17) +}; + +static struct device *pmc_dev; +static struct pmc_regs __iomem *pmc_regs; + +static int pmc_suspend_enter(suspend_state_t state) +{ + int ret; + + setbits32(&pmc_regs->pmcsr, PMCSR_SLP); + /* At this point, the CPU is asleep. */ + + /* Upon resume, wait for SLP bit to be clear. */ + ret = spin_event_timeout((in_be32(&pmc_regs->pmcsr) & PMCSR_SLP) == 0, + 10000, 10) ? 0 : -ETIMEDOUT; + if (ret) + dev_err(pmc_dev, "tired waiting for SLP bit to clear\n"); + return ret; +} + +static int pmc_suspend_valid(suspend_state_t state) +{ + if (state != PM_SUSPEND_STANDBY) + return 0; + return 1; +} + +static struct platform_suspend_ops pmc_suspend_ops = { + .valid = pmc_suspend_valid, + .enter = pmc_suspend_enter, +}; + +static int pmc_probe(struct of_device *ofdev, const struct of_device_id *id) +{ + pmc_regs = of_iomap(ofdev->node, 0); + if (!pmc_regs) + return -ENOMEM; + + pmc_dev = &ofdev->dev; + suspend_set_ops(&pmc_suspend_ops); + return 0; +} + +static const struct of_device_id pmc_ids[] = { + { .compatible = "fsl,mpc8548-pmc", }, + { .compatible = "fsl,mpc8641d-pmc", }, + { }, +}; + +static struct of_platform_driver pmc_driver = { + .driver.name = "fsl-pmc", + .match_table = pmc_ids, + .probe = pmc_probe, +}; + +static int __init pmc_init(void) +{ + return of_register_platform_driver(&pmc_driver); +} +device_initcall(pmc_init); diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index adca4affcf1f7086d652c592dfe719a414594e08..b91f7acdda6f72aa09d49669258d18e2d9527a73 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -372,7 +372,7 @@ err: arch_initcall(fsl_usb_of_init); -#if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) +#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) static __be32 __iomem *rstcr; static int __init setup_rstcr(void) diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c index a96584ab33dda7e9e8140bf1db9bae897364545d..0a55db8a5a2912ae1f7a55b87d4a0fe05aa8d045 100644 --- a/arch/powerpc/sysdev/i8259.c +++ b/arch/powerpc/sysdev/i8259.c @@ -135,7 +135,7 @@ static void i8259_unmask_irq(unsigned int irq_nr) } static struct irq_chip i8259_pic = { - .typename = " i8259 ", + .name = " i8259 ", .mask = i8259_mask_irq, .disable = i8259_mask_irq, .unmask = i8259_unmask_irq, @@ -175,12 +175,12 @@ static int i8259_host_map(struct irq_host *h, unsigned int virq, /* We block the internal cascade */ if (hw == 2) - get_irq_desc(virq)->status |= IRQ_NOREQUEST; + irq_to_desc(virq)->status |= IRQ_NOREQUEST; /* We use the level handler only for now, we might want to * be more cautious here but that works for now */ - get_irq_desc(virq)->status |= IRQ_LEVEL; + irq_to_desc(virq)->status |= IRQ_LEVEL; set_irq_chip_and_handler(virq, &i8259_pic, handle_level_irq); return 0; } @@ -198,7 +198,7 @@ static void i8259_host_unmap(struct irq_host *h, unsigned int virq) } static int i8259_host_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { static unsigned char map_isa_senses[4] = { diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index cb7689c4bfbd5e7f3578a78961e3a0293f20de8b..28cdddd2f89e6265aca60a1ec8f41ba68b66caa9 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c @@ -605,7 +605,7 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) { struct ipic *ipic = ipic_from_irq(virq); unsigned int src = ipic_irq_to_hw(virq); - struct irq_desc *desc = get_irq_desc(virq); + struct irq_desc *desc = irq_to_desc(virq); unsigned int vold, vnew, edibit; if (flow_type == IRQ_TYPE_NONE) @@ -660,7 +660,7 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) /* level interrupts and edge interrupts have different ack operations */ static struct irq_chip ipic_level_irq_chip = { - .typename = " IPIC ", + .name = " IPIC ", .unmask = ipic_unmask_irq, .mask = ipic_mask_irq, .mask_ack = ipic_mask_irq, @@ -668,7 +668,7 @@ static struct irq_chip ipic_level_irq_chip = { }; static struct irq_chip ipic_edge_irq_chip = { - .typename = " IPIC ", + .name = " IPIC ", .unmask = ipic_unmask_irq, .mask = ipic_mask_irq, .mask_ack = ipic_mask_irq_and_ack, @@ -697,7 +697,7 @@ static int ipic_host_map(struct irq_host *h, unsigned int virq, } static int ipic_host_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c index 5d2d5522ef416846a0ba9bf8073c05652227d4c7..69bd6f4dff83a3f67ee1a8e3d1c958cd293d48a2 100644 --- a/arch/powerpc/sysdev/mpc8xx_pic.c +++ b/arch/powerpc/sysdev/mpc8xx_pic.c @@ -72,7 +72,7 @@ static void mpc8xx_end_irq(unsigned int virq) static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type) { - struct irq_desc *desc = get_irq_desc(virq); + struct irq_desc *desc = irq_to_desc(virq); desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; @@ -94,7 +94,7 @@ static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type) } static struct irq_chip mpc8xx_pic = { - .typename = " MPC8XX SIU ", + .name = " MPC8XX SIU ", .unmask = mpc8xx_unmask_irq, .mask = mpc8xx_mask_irq, .ack = mpc8xx_ack, @@ -130,7 +130,7 @@ static int mpc8xx_pic_host_map(struct irq_host *h, unsigned int virq, static int mpc8xx_pic_host_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { static unsigned char map_pic_senses[4] = { diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 30c44e6b0413e5981f2500fab9c4ad1c8a3a493a..aa9d06e5925b1ead712a073670600781ab23a2b9 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -572,7 +572,7 @@ static int irq_choose_cpu(unsigned int virt_irq) cpumask_t mask; int cpuid; - cpumask_copy(&mask, irq_desc[virt_irq].affinity); + cpumask_copy(&mask, irq_to_desc(virt_irq)->affinity); if (cpus_equal(mask, CPU_MASK_ALL)) { static int irq_rover; static DEFINE_SPINLOCK(irq_rover_lock); @@ -621,7 +621,7 @@ static struct mpic *mpic_find(unsigned int irq) if (irq < NUM_ISA_INTERRUPTS) return NULL; - return irq_desc[irq].chip_data; + return irq_to_desc(irq)->chip_data; } /* Determine if the linux irq is an IPI */ @@ -648,14 +648,14 @@ static inline u32 mpic_physmask(u32 cpumask) /* Get the mpic structure from the IPI number */ static inline struct mpic * mpic_from_ipi(unsigned int ipi) { - return irq_desc[ipi].chip_data; + return irq_to_desc(ipi)->chip_data; } #endif /* Get the mpic structure from the irq number */ static inline struct mpic * mpic_from_irq(unsigned int irq) { - return irq_desc[irq].chip_data; + return irq_to_desc(irq)->chip_data; } /* Send an EOI */ @@ -735,7 +735,7 @@ static void mpic_unmask_ht_irq(unsigned int irq) mpic_unmask_irq(irq); - if (irq_desc[irq].status & IRQ_LEVEL) + if (irq_to_desc(irq)->status & IRQ_LEVEL) mpic_ht_end_irq(mpic, src); } @@ -745,7 +745,7 @@ static unsigned int mpic_startup_ht_irq(unsigned int irq) unsigned int src = mpic_irq_to_hw(irq); mpic_unmask_irq(irq); - mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status); + mpic_startup_ht_interrupt(mpic, src, irq_to_desc(irq)->status); return 0; } @@ -755,7 +755,7 @@ static void mpic_shutdown_ht_irq(unsigned int irq) struct mpic *mpic = mpic_from_irq(irq); unsigned int src = mpic_irq_to_hw(irq); - mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status); + mpic_shutdown_ht_interrupt(mpic, src, irq_to_desc(irq)->status); mpic_mask_irq(irq); } @@ -772,7 +772,7 @@ static void mpic_end_ht_irq(unsigned int irq) * latched another edge interrupt coming in anyway */ - if (irq_desc[irq].status & IRQ_LEVEL) + if (irq_to_desc(irq)->status & IRQ_LEVEL) mpic_ht_end_irq(mpic, src); mpic_eoi(mpic); } @@ -856,7 +856,7 @@ int mpic_set_irq_type(unsigned int virq, unsigned int flow_type) { struct mpic *mpic = mpic_from_irq(virq); unsigned int src = mpic_irq_to_hw(virq); - struct irq_desc *desc = get_irq_desc(virq); + struct irq_desc *desc = irq_to_desc(virq); unsigned int vecpri, vold, vnew; DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n", @@ -994,7 +994,7 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq, } static int mpic_host_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { @@ -1062,19 +1062,19 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->name = name; mpic->hc_irq = mpic_irq_chip; - mpic->hc_irq.typename = name; + mpic->hc_irq.name = name; if (flags & MPIC_PRIMARY) mpic->hc_irq.set_affinity = mpic_set_affinity; #ifdef CONFIG_MPIC_U3_HT_IRQS mpic->hc_ht_irq = mpic_irq_ht_chip; - mpic->hc_ht_irq.typename = name; + mpic->hc_ht_irq.name = name; if (flags & MPIC_PRIMARY) mpic->hc_ht_irq.set_affinity = mpic_set_affinity; #endif /* CONFIG_MPIC_U3_HT_IRQS */ #ifdef CONFIG_SMP mpic->hc_ipi = mpic_ipi_chip; - mpic->hc_ipi.typename = name; + mpic->hc_ipi.name = name; #endif /* CONFIG_SMP */ mpic->flags = flags; diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c index 656cb772b6910458392cc2cc0c5001fced632189..0f6ab06f8474bdd55c009c60a8833b919d2b6ce3 100644 --- a/arch/powerpc/sysdev/mpic_pasemi_msi.c +++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c @@ -60,7 +60,7 @@ static struct irq_chip mpic_pasemi_msi_chip = { .eoi = mpic_end_irq, .set_type = mpic_set_irq_type, .set_affinity = mpic_set_affinity, - .typename = "PASEMI-MSI ", + .name = "PASEMI-MSI ", }; static int pasemi_msi_check_device(struct pci_dev *pdev, int nvec, int type) diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c index 0a8f5a9e87c94d48b040735d156d1e6ff298ee62..d3caf23e6312662b2030a52f5cb39249971e517b 100644 --- a/arch/powerpc/sysdev/mpic_u3msi.c +++ b/arch/powerpc/sysdev/mpic_u3msi.c @@ -42,7 +42,7 @@ static struct irq_chip mpic_u3msi_chip = { .eoi = mpic_end_irq, .set_type = mpic_set_irq_type, .set_affinity = mpic_set_affinity, - .typename = "MPIC-U3MSI", + .name = "MPIC-U3MSI", }; static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos) diff --git a/arch/powerpc/sysdev/mv64x60_pic.c b/arch/powerpc/sysdev/mv64x60_pic.c index 2aa4ed066db11bcec9bcfa7127b3b7c50eb9b8d9..485b92477d7c19de26fb09403fd1e7d6a5f99a6c 100644 --- a/arch/powerpc/sysdev/mv64x60_pic.c +++ b/arch/powerpc/sysdev/mv64x60_pic.c @@ -213,7 +213,7 @@ static int mv64x60_host_map(struct irq_host *h, unsigned int virq, { int level1; - get_irq_desc(virq)->status |= IRQ_LEVEL; + irq_to_desc(virq)->status |= IRQ_LEVEL; level1 = (hwirq & MV64x60_LEVEL1_MASK) >> MV64x60_LEVEL1_OFFSET; BUG_ON(level1 > MV64x60_LEVEL1_GPP); diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 464271bea6c95852e9640d7c6c573269259d2333..149393c02c3f117b0f2f9d7e2387b5c83fffcdcf 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -65,19 +67,6 @@ static unsigned int qe_num_of_snum; static phys_addr_t qebase = -1; -int qe_alive_during_sleep(void) -{ - static int ret = -1; - - if (ret != -1) - return ret; - - ret = !of_find_compatible_node(NULL, NULL, "fsl,mpc8569-pmc"); - - return ret; -} -EXPORT_SYMBOL(qe_alive_during_sleep); - phys_addr_t get_qe_base(void) { struct device_node *qe; @@ -104,7 +93,7 @@ phys_addr_t get_qe_base(void) EXPORT_SYMBOL(get_qe_base); -void __init qe_reset(void) +void qe_reset(void) { if (qe_immr == NULL) qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE); @@ -330,16 +319,18 @@ EXPORT_SYMBOL(qe_put_snum); static int qe_sdma_init(void) { struct sdma __iomem *sdma = &qe_immr->sdma; - unsigned long sdma_buf_offset; + static unsigned long sdma_buf_offset = (unsigned long)-ENOMEM; if (!sdma) return -ENODEV; /* allocate 2 internal temporary buffers (512 bytes size each) for * the SDMA */ - sdma_buf_offset = qe_muram_alloc(512 * 2, 4096); - if (IS_ERR_VALUE(sdma_buf_offset)) - return -ENOMEM; + if (IS_ERR_VALUE(sdma_buf_offset)) { + sdma_buf_offset = qe_muram_alloc(512 * 2, 4096); + if (IS_ERR_VALUE(sdma_buf_offset)) + return -ENOMEM; + } out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK); out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK | @@ -349,7 +340,7 @@ static int qe_sdma_init(void) } /* The maximum number of RISCs we support */ -#define MAX_QE_RISC 2 +#define MAX_QE_RISC 4 /* Firmware information stored here for qe_get_firmware_info() */ static struct qe_firmware_info qe_firmware_info; @@ -658,3 +649,35 @@ unsigned int qe_get_num_of_snums(void) return num_of_snums; } EXPORT_SYMBOL(qe_get_num_of_snums); + +#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) +static int qe_resume(struct of_device *ofdev) +{ + if (!qe_alive_during_sleep()) + qe_reset(); + return 0; +} + +static int qe_probe(struct of_device *ofdev, const struct of_device_id *id) +{ + return 0; +} + +static const struct of_device_id qe_ids[] = { + { .compatible = "fsl,qe", }, + { }, +}; + +static struct of_platform_driver qe_driver = { + .driver.name = "fsl-qe", + .match_table = qe_ids, + .probe = qe_probe, + .resume = qe_resume, +}; + +static int __init qe_drv_init(void) +{ + return of_register_platform_driver(&qe_driver); +} +device_initcall(qe_drv_init); +#endif /* defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) */ diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c index 3faa42e03a85af05a379efaa2f103093b6d5fb9a..2acc928d192062a7c50089c5dce154189bfaa923 100644 --- a/arch/powerpc/sysdev/qe_lib/qe_ic.c +++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c @@ -189,7 +189,7 @@ static inline void qe_ic_write(volatile __be32 __iomem * base, unsigned int reg static inline struct qe_ic *qe_ic_from_irq(unsigned int virq) { - return irq_desc[virq].chip_data; + return irq_to_desc(virq)->chip_data; } #define virq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) @@ -237,7 +237,7 @@ static void qe_ic_mask_irq(unsigned int virq) } static struct irq_chip qe_ic_irq_chip = { - .typename = " QEIC ", + .name = " QEIC ", .unmask = qe_ic_unmask_irq, .mask = qe_ic_mask_irq, .mask_ack = qe_ic_mask_irq, @@ -263,7 +263,7 @@ static int qe_ic_host_map(struct irq_host *h, unsigned int virq, chip = &qe_ic->hc_irq; set_irq_chip_data(virq, qe_ic); - get_irq_desc(virq)->status |= IRQ_LEVEL; + irq_to_desc(virq)->status |= IRQ_LEVEL; set_irq_chip_and_handler(virq, chip, handle_level_irq); @@ -271,7 +271,7 @@ static int qe_ic_host_map(struct irq_host *h, unsigned int virq, } static int qe_ic_host_xlate(struct irq_host *h, struct device_node *ct, - u32 * intspec, unsigned int intsize, + const u32 * intspec, unsigned int intsize, irq_hw_number_t * out_hwirq, unsigned int *out_flags) { diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c index cf244a419e9650cd631189a26b59455a64ef5f3b..595034cfb85aa34cfad606da9e2a458b16a3f23a 100644 --- a/arch/powerpc/sysdev/tsi108_pci.c +++ b/arch/powerpc/sysdev/tsi108_pci.c @@ -376,7 +376,7 @@ static void tsi108_pci_irq_end(u_int irq) */ static struct irq_chip tsi108_pci_irq = { - .typename = "tsi108_PCI_int", + .name = "tsi108_PCI_int", .mask = tsi108_pci_irq_disable, .ack = tsi108_pci_irq_ack, .end = tsi108_pci_irq_end, @@ -384,7 +384,7 @@ static struct irq_chip tsi108_pci_irq = { }; static int pci_irq_host_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { *out_hwirq = intspec[0]; @@ -398,7 +398,7 @@ static int pci_irq_host_map(struct irq_host *h, unsigned int virq, DBG("%s(%d, 0x%lx)\n", __func__, virq, hw); if ((virq >= 1) && (virq <= 4)){ irq = virq + IRQ_PCI_INTAD_BASE - 1; - get_irq_desc(irq)->status |= IRQ_LEVEL; + irq_to_desc(irq)->status |= IRQ_LEVEL; set_irq_chip(irq, &tsi108_pci_irq); } return 0; diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c index 466ce9ace1270ec881a4ae2f18e92a70648af40b..7d10074b3304616cc983f316c2fad491bbb90fc4 100644 --- a/arch/powerpc/sysdev/uic.c +++ b/arch/powerpc/sysdev/uic.c @@ -57,7 +57,7 @@ struct uic { static void uic_unmask_irq(unsigned int virq) { - struct irq_desc *desc = get_irq_desc(virq); + struct irq_desc *desc = irq_to_desc(virq); struct uic *uic = get_irq_chip_data(virq); unsigned int src = uic_irq_to_hw(virq); unsigned long flags; @@ -101,7 +101,7 @@ static void uic_ack_irq(unsigned int virq) static void uic_mask_ack_irq(unsigned int virq) { - struct irq_desc *desc = get_irq_desc(virq); + struct irq_desc *desc = irq_to_desc(virq); struct uic *uic = get_irq_chip_data(virq); unsigned int src = uic_irq_to_hw(virq); unsigned long flags; @@ -129,7 +129,7 @@ static int uic_set_irq_type(unsigned int virq, unsigned int flow_type) { struct uic *uic = get_irq_chip_data(virq); unsigned int src = uic_irq_to_hw(virq); - struct irq_desc *desc = get_irq_desc(virq); + struct irq_desc *desc = irq_to_desc(virq); unsigned long flags; int trigger, polarity; u32 tr, pr, mask; @@ -177,7 +177,7 @@ static int uic_set_irq_type(unsigned int virq, unsigned int flow_type) } static struct irq_chip uic_irq_chip = { - .typename = " UIC ", + .name = " UIC ", .unmask = uic_unmask_irq, .mask = uic_mask_irq, .mask_ack = uic_mask_ack_irq, @@ -202,7 +202,7 @@ static int uic_host_map(struct irq_host *h, unsigned int virq, } static int uic_host_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_type) { diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c index 40edad520770e335c1afc7a7af0463f159972ef4..1e0ccfaf403e8f88fb660748cefe9fe652e5c2ef 100644 --- a/arch/powerpc/sysdev/xilinx_intc.c +++ b/arch/powerpc/sysdev/xilinx_intc.c @@ -79,7 +79,7 @@ static void xilinx_intc_mask(unsigned int virq) static int xilinx_intc_set_type(unsigned int virq, unsigned int flow_type) { - struct irq_desc *desc = get_irq_desc(virq); + struct irq_desc *desc = irq_to_desc(virq); desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; @@ -106,7 +106,7 @@ static void xilinx_intc_level_unmask(unsigned int virq) } static struct irq_chip xilinx_intc_level_irqchip = { - .typename = "Xilinx Level INTC", + .name = "Xilinx Level INTC", .mask = xilinx_intc_mask, .mask_ack = xilinx_intc_mask, .unmask = xilinx_intc_level_unmask, @@ -133,7 +133,7 @@ static void xilinx_intc_edge_ack(unsigned int virq) } static struct irq_chip xilinx_intc_edge_irqchip = { - .typename = "Xilinx Edge INTC", + .name = "Xilinx Edge INTC", .mask = xilinx_intc_mask, .unmask = xilinx_intc_edge_unmask, .ack = xilinx_intc_edge_ack, @@ -148,7 +148,7 @@ static struct irq_chip xilinx_intc_edge_irqchip = { * xilinx_intc_xlate - translate virq# from device tree interrupts property */ static int xilinx_intc_xlate(struct irq_host *h, struct device_node *ct, - u32 *intspec, unsigned int intsize, + const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_flags) { diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index bdbe96c8a7e4574c7304e12688e3c3e68ad71a9c..4e6152c13764e173aa7811c249c8a359b5a60a5c 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -1641,7 +1641,8 @@ static void super_regs(void) ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1); printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n", ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4); - printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5); + printf(" Saved Gpr5=%.16lx \n", + ptrLpPaca->gpr5_dword.saved_gpr5); } #endif diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 25c31d681402f1c43e140232dd8c7cbfa6166a0f..22c9e557bb22b9f79b275fe3707f27cb133e6c8c 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -624,38 +624,6 @@ struct mmap_arg_struct_emu31 { u32 offset; }; -/* common code for old and new mmaps */ -static inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - struct file * file = NULL; - unsigned long error = -EBADF; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) { - /* Result is out of bounds. */ - do_munmap(current->mm, addr, len); - error = -ENOMEM; - } - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - - asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg) { @@ -669,7 +637,8 @@ old32_mmap(struct mmap_arg_struct_emu31 __user *arg) if (a.offset & ~PAGE_MASK) goto out; - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, + a.offset >> PAGE_SHIFT); out: return error; } @@ -682,7 +651,7 @@ sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) if (copy_from_user(&a, arg, sizeof(a))) goto out; - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); out: return error; } diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c index e9d94f61d5002639645e59cd45683acc2c52038a..86a74c9c9e63c2b7d377ee7c725d7381377ae0a3 100644 --- a/arch/s390/kernel/sys_s390.c +++ b/arch/s390/kernel/sys_s390.c @@ -32,32 +32,6 @@ #include #include "entry.h" -/* common code for old and new mmaps */ -static inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - long error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - /* * Perform the select(nd, in, out, ex, tv) and mmap() system * calls. Linux for S/390 isn't able to handle more than 5 @@ -81,7 +55,7 @@ SYSCALL_DEFINE1(mmap2, struct mmap_arg_struct __user *, arg) if (copy_from_user(&a, arg, sizeof(a))) goto out; - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); out: return error; } @@ -98,7 +72,7 @@ SYSCALL_DEFINE1(s390_old_mmap, struct mmap_arg_struct __user *, arg) if (a.offset & ~PAGE_MASK) goto out; - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); out: return error; } diff --git a/arch/score/kernel/sys_score.c b/arch/score/kernel/sys_score.c index 00124946986615ff8dc133dfc298f2fd2a80b34c..856ed68a58e6103efd22d0496cb2884438f8cfa0 100644 --- a/arch/score/kernel/sys_score.c +++ b/arch/score/kernel/sys_score.c @@ -36,34 +36,16 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { - int error = -EBADF; - struct file *file = NULL; - - if (pgoff & (~PAGE_MASK >> 12)) - return -EINVAL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - return error; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); - - return error; + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); } asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, - unsigned long flags, unsigned long fd, off_t pgoff) + unsigned long flags, unsigned long fd, off_t offset) { - return sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); + if (unlikely(offset & ~PAGE_MASK)) + return -EINVAL; + return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); } asmlinkage long diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c index 8aa5d1ceaf14b225934d4ec8e0860bbfcdf298ef..71399cde03b52c3cca26612075d7ebae4e2c1a68 100644 --- a/arch/sh/kernel/sys_sh.c +++ b/arch/sh/kernel/sys_sh.c @@ -28,37 +28,13 @@ #include #include -static inline long -do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, - unsigned long flags, int fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file *file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - asmlinkage int old_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, int fd, unsigned long off) { if (off & ~PAGE_MASK) return -EINVAL; - return do_mmap2(addr, len, prot, flags, fd, off>>PAGE_SHIFT); + return sys_mmap_pgoff(addr, len, prot, flags, fd, off>>PAGE_SHIFT); } asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, @@ -74,7 +50,7 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, pgoff >>= PAGE_SHIFT - 12; - return do_mmap2(addr, len, prot, flags, fd, pgoff); + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); } /* diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c index d2984fa42d3d0ee69fce3a3e0a7e4fa24323c835..afeb710ec5c35d06926717a7f666f373ea366887 100644 --- a/arch/sh/mm/mmap.c +++ b/arch/sh/mm/mmap.c @@ -54,7 +54,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, /* We do not accept a shared mapping if it would violate * cache aliasing constraints. */ - if ((flags & MAP_SHARED) && (addr & shm_align_mask)) + if ((flags & MAP_SHARED) && + ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask)) return -EINVAL; return addr; } diff --git a/arch/sparc/include/asm/fcntl.h b/arch/sparc/include/asm/fcntl.h index d4d9c9d852c3d6324621689995fe637c51cdaa94..3b9cfb39175e7dba1122ce9d8250b28eaa994c78 100644 --- a/arch/sparc/include/asm/fcntl.h +++ b/arch/sparc/include/asm/fcntl.h @@ -1,14 +1,12 @@ #ifndef _SPARC_FCNTL_H #define _SPARC_FCNTL_H -/* open/fcntl - O_SYNC is only implemented on blocks devices and on files - located on an ext2 file system */ #define O_APPEND 0x0008 #define FASYNC 0x0040 /* fcntl, for BSD compatibility */ #define O_CREAT 0x0200 /* not fcntl */ #define O_TRUNC 0x0400 /* not fcntl */ #define O_EXCL 0x0800 /* not fcntl */ -#define O_SYNC 0x2000 +#define O_DSYNC 0x2000 /* used to be O_SYNC, see below */ #define O_NONBLOCK 0x4000 #if defined(__sparc__) && defined(__arch64__) #define O_NDELAY 0x0004 @@ -20,6 +18,21 @@ #define O_DIRECT 0x100000 /* direct disk access hint */ #define O_NOATIME 0x200000 #define O_CLOEXEC 0x400000 +/* + * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using + * the O_SYNC flag. We continue to use the existing numerical value + * for O_DSYNC semantics now, but using the correct symbolic name for it. + * This new value is used to request true Posix O_SYNC semantics. It is + * defined in this strange way to make sure applications compiled against + * new headers get at least O_DSYNC semantics on older kernels. + * + * This has the nice side-effect that we can simply test for O_DSYNC + * wherever we do not care if O_DSYNC or O_SYNC is used. + * + * Note: __O_SYNC must never be used directly. + */ +#define __O_SYNC 0x800000 +#define O_SYNC (__O_SYNC|O_DSYNC) #define F_GETOWN 5 /* for sockets. */ #define F_SETOWN 6 /* for sockets. */ diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci_64.h index b63e51c3c3ee2fdb959b13f5e0fd9511bc344d09..b0576df6ec832ab6996436a6a554dbb2dcd62257 100644 --- a/arch/sparc/include/asm/pci_64.h +++ b/arch/sparc/include/asm/pci_64.h @@ -16,8 +16,6 @@ #define PCI_IRQ_NONE 0xffffffff -#define PCI_CACHE_LINE_BYTES 64 - static inline void pcibios_set_master(struct pci_dev *dev) { /* No special bus mastering setup handling */ diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c index b129611590a449f61de21fdcaa803eefbf7eb6fe..f30f4a1ead23d373afb51161f3303dfeae9fbe17 100644 --- a/arch/sparc/kernel/nmi.c +++ b/arch/sparc/kernel/nmi.c @@ -47,7 +47,7 @@ static DEFINE_PER_CPU(short, wd_enabled); static int endflag __initdata; static DEFINE_PER_CPU(unsigned int, last_irq_sum); -static DEFINE_PER_CPU(local_t, alert_counter); +static DEFINE_PER_CPU(long, alert_counter); static DEFINE_PER_CPU(int, nmi_touch); void touch_nmi_watchdog(void) @@ -112,13 +112,13 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) touched = 1; } if (!touched && __get_cpu_var(last_irq_sum) == sum) { - local_inc(&__get_cpu_var(alert_counter)); - if (local_read(&__get_cpu_var(alert_counter)) == 30 * nmi_hz) + __this_cpu_inc(per_cpu_var(alert_counter)); + if (__this_cpu_read(per_cpu_var(alert_counter)) == 30 * nmi_hz) die_nmi("BUG: NMI Watchdog detected LOCKUP", regs, panic_on_timeout); } else { __get_cpu_var(last_irq_sum) = sum; - local_set(&__get_cpu_var(alert_counter), 0); + __this_cpu_write(per_cpu_var(alert_counter), 0); } if (__get_cpu_var(wd_enabled)) { write_pic(picl_value(nmi_hz)); diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index c68648662802a122932ccece24ad31c250ddb77c..b85374f7cf945f3d4760dbd6fe739455ea52b33b 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -1081,3 +1081,10 @@ void pci_resource_to_user(const struct pci_dev *pdev, int bar, *start = rp->start - offset; *end = rp->end - offset; } + +static int __init pcibios_init(void) +{ + pci_dfl_cache_line_size = 64 >> 2; + return 0; +} +subsys_initcall(pcibios_init); diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index 00abe87e5b51af8c5a5a059893ef7196b7d77883..dc0ac197e7e294310a1a2d5f15ddbf455b0394a2 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c @@ -564,28 +564,6 @@ asmlinkage long sparc32_open(const char __user *filename, return do_sys_open(AT_FDCWD, filename, flags, mode); } -extern unsigned long do_mremap(unsigned long addr, - unsigned long old_len, unsigned long new_len, - unsigned long flags, unsigned long new_addr); - -asmlinkage unsigned long sys32_mremap(unsigned long addr, - unsigned long old_len, unsigned long new_len, - unsigned long flags, u32 __new_addr) -{ - unsigned long ret = -EINVAL; - unsigned long new_addr = __new_addr; - - if (unlikely(sparc_mmap_check(addr, old_len))) - goto out; - if (unlikely(sparc_mmap_check(new_addr, new_len))) - goto out; - down_write(¤t->mm->mmap_sem); - ret = do_mremap(addr, old_len, new_len, flags, new_addr); - up_write(¤t->mm->mmap_sem); -out: - return ret; -} - long sys32_lookup_dcookie(unsigned long cookie_high, unsigned long cookie_low, char __user *buf, size_t len) diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c index 03035c852a43f8e751f5bb8ba16e3f767c9bc9fb..3a82e65d8db2072b9f4b3d9a2edb9faf55c263a7 100644 --- a/arch/sparc/kernel/sys_sparc_32.c +++ b/arch/sparc/kernel/sys_sparc_32.c @@ -45,7 +45,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi /* We do not accept a shared mapping if it would violate * cache aliasing constraints. */ - if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1))) + if ((flags & MAP_SHARED) && + ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) return -EINVAL; return addr; } @@ -79,15 +80,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi } } -asmlinkage unsigned long sparc_brk(unsigned long brk) -{ - if(ARCH_SUN4C) { - if ((brk & 0xe0000000) != (current->mm->brk & 0xe0000000)) - return current->mm->brk; - } - return sys_brk(brk); -} - /* * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though. @@ -234,31 +226,6 @@ int sparc_mmap_check(unsigned long addr, unsigned long len) } /* Linux version of mmap */ -static unsigned long do_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, unsigned long fd, - unsigned long pgoff) -{ - struct file * file = NULL; - unsigned long retval = -EBADF; - - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - len = PAGE_ALIGN(len); - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); - retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return retval; -} asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, @@ -266,14 +233,16 @@ asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len, { /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE we have. */ - return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12)); + return sys_mmap_pgoff(addr, len, prot, flags, fd, + pgoff >> (PAGE_SHIFT - 12)); } asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off) { - return do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT); + /* no alignment check? */ + return sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); } long sparc_remap_file_pages(unsigned long start, unsigned long size, @@ -287,27 +256,6 @@ long sparc_remap_file_pages(unsigned long start, unsigned long size, (pgoff >> (PAGE_SHIFT - 12)), flags); } -extern unsigned long do_mremap(unsigned long addr, - unsigned long old_len, unsigned long new_len, - unsigned long flags, unsigned long new_addr); - -asmlinkage unsigned long sparc_mremap(unsigned long addr, - unsigned long old_len, unsigned long new_len, - unsigned long flags, unsigned long new_addr) -{ - unsigned long ret = -EINVAL; - - if (unlikely(sparc_mmap_check(addr, old_len))) - goto out; - if (unlikely(sparc_mmap_check(new_addr, new_len))) - goto out; - down_write(¤t->mm->mmap_sem); - ret = do_mremap(addr, old_len, new_len, flags, new_addr); - up_write(¤t->mm->mmap_sem); -out: - return ret; -} - /* we come to here via sys_nis_syscall so it can setup the regs argument */ asmlinkage unsigned long c_sys_nis_syscall (struct pt_regs *regs) diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index e2d102447a43e5c57f8cb64a136763795ddf192b..cfa0e19abe3bd62b2e0f64f2b5b5d15499b0b9c9 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -317,10 +317,14 @@ bottomup: unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags) { unsigned long align_goal, addr = -ENOMEM; + unsigned long (*get_area)(struct file *, unsigned long, + unsigned long, unsigned long, unsigned long); + + get_area = current->mm->get_unmapped_area; if (flags & MAP_FIXED) { /* Ok, don't mess with it. */ - return get_unmapped_area(NULL, orig_addr, len, pgoff, flags); + return get_area(NULL, orig_addr, len, pgoff, flags); } flags &= ~MAP_SHARED; @@ -333,7 +337,7 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u align_goal = (64UL * 1024); do { - addr = get_unmapped_area(NULL, orig_addr, len + (align_goal - PAGE_SIZE), pgoff, flags); + addr = get_area(NULL, orig_addr, len + (align_goal - PAGE_SIZE), pgoff, flags); if (!(addr & ~PAGE_MASK)) { addr = (addr + (align_goal - 1UL)) & ~(align_goal - 1UL); break; @@ -351,7 +355,7 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u * be obtained. */ if (addr & ~PAGE_MASK) - addr = get_unmapped_area(NULL, orig_addr, len, pgoff, flags); + addr = get_area(NULL, orig_addr, len, pgoff, flags); return addr; } @@ -399,18 +403,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm) } } -SYSCALL_DEFINE1(sparc_brk, unsigned long, brk) -{ - /* People could try to be nasty and use ta 0x6d in 32bit programs */ - if (test_thread_flag(TIF_32BIT) && brk >= STACK_TOP32) - return current->mm->brk; - - if (unlikely(straddles_64bit_va_hole(current->mm->brk, brk))) - return current->mm->brk; - - return sys_brk(brk); -} - /* * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though. @@ -568,23 +560,13 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, off) { - struct file * file = NULL; - unsigned long retval = -EBADF; - - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - len = PAGE_ALIGN(len); + unsigned long retval = -EINVAL; - down_write(¤t->mm->mmap_sem); - retval = do_mmap(file, addr, len, prot, flags, off); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); + if ((off + PAGE_ALIGN(len)) < off) + goto out; + if (off & ~PAGE_MASK) + goto out; + retval = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); out: return retval; } @@ -614,12 +596,6 @@ SYSCALL_DEFINE5(64_mremap, unsigned long, addr, unsigned long, old_len, if (test_thread_flag(TIF_32BIT)) goto out; - if (unlikely(new_len >= VA_EXCLUDE_START)) - goto out; - if (unlikely(sparc_mmap_check(addr, old_len))) - goto out; - if (unlikely(sparc_mmap_check(new_addr, new_len))) - goto out; down_write(¤t->mm->mmap_sem); ret = do_mremap(addr, old_len, new_len, flags, new_addr); diff --git a/arch/sparc/kernel/systbls.h b/arch/sparc/kernel/systbls.h index a63c5d2d984917e242441d8b85f856f109f07661..d2f999ae2b85a04495d31ab2c77ad91924342f5a 100644 --- a/arch/sparc/kernel/systbls.h +++ b/arch/sparc/kernel/systbls.h @@ -9,7 +9,6 @@ struct new_utsname; extern asmlinkage unsigned long sys_getpagesize(void); -extern asmlinkage unsigned long sparc_brk(unsigned long brk); extern asmlinkage long sparc_pipe(struct pt_regs *regs); extern asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second, diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index ceb1530f8aa66c00b4b016beb836f6cb14d2e85d..801fc8e5a0e87cf20fc58550b4f603a6e4085723 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S @@ -19,7 +19,7 @@ sys_call_table: /*0*/ .long sys_restart_syscall, sys_exit, sys_fork, sys_read, sys_write /*5*/ .long sys_open, sys_close, sys_wait4, sys_creat, sys_link /*10*/ .long sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys_mknod -/*15*/ .long sys_chmod, sys_lchown16, sparc_brk, sys_nis_syscall, sys_lseek +/*15*/ .long sys_chmod, sys_lchown16, sys_brk, sys_nis_syscall, sys_lseek /*20*/ .long sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16 /*25*/ .long sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause /*30*/ .long sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice @@ -67,7 +67,7 @@ sys_call_table: /*235*/ .long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall /*240*/ .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler /*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep -/*250*/ .long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl +/*250*/ .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl /*255*/ .long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep /*260*/ .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun /*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index cc8e7862e95a9b7da663d1b5c831929392b52554..e575b46bd7a9ebd84eb29578ef0e04952d07fff2 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -21,7 +21,7 @@ sys_call_table32: /*0*/ .word sys_restart_syscall, sys32_exit, sys_fork, sys_read, sys_write /*5*/ .word sys32_open, sys_close, sys32_wait4, sys32_creat, sys_link /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod -/*15*/ .word sys_chmod, sys_lchown16, sys_sparc_brk, sys32_perfctr, sys32_lseek +/*15*/ .word sys_chmod, sys_lchown16, sys_brk, sys32_perfctr, sys32_lseek /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16 /*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice @@ -68,7 +68,7 @@ sys_call_table32: .word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall /*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep -/*250*/ .word sys32_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl +/*250*/ .word sys_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl .word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep /*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy @@ -96,7 +96,7 @@ sys_call_table: /*0*/ .word sys_restart_syscall, sparc_exit, sys_fork, sys_read, sys_write /*5*/ .word sys_open, sys_close, sys_wait4, sys_creat, sys_link /*10*/ .word sys_unlink, sys_nis_syscall, sys_chdir, sys_chown, sys_mknod -/*15*/ .word sys_chmod, sys_lchown, sys_sparc_brk, sys_perfctr, sys_lseek +/*15*/ .word sys_chmod, sys_lchown, sys_brk, sys_perfctr, sys_lseek /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid /*25*/ .word sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall /*30*/ .word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index a4625c7b2bf990a78dc49f5785b48393dba00baf..cccab850c27ec221a5bf6d13a9e155a580c40a40 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -8,6 +8,7 @@ #include "linux/mm.h" #include "linux/sched.h" #include "linux/utsname.h" +#include "linux/syscalls.h" #include "asm/current.h" #include "asm/mman.h" #include "asm/uaccess.h" @@ -37,31 +38,6 @@ long sys_vfork(void) return ret; } -/* common code for old and new mmaps */ -long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - long error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); - out: - return error; -} - long old_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long offset) @@ -70,7 +46,7 @@ long old_mmap(unsigned long addr, unsigned long len, if (offset & ~PAGE_MASK) goto out; - err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + err = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); out: return err; } diff --git a/arch/um/sys-i386/shared/sysdep/syscalls.h b/arch/um/sys-i386/shared/sysdep/syscalls.h index 905698197e35fc2f4fd612b0495bd846d3253a65..e7787679e3174b2cd891a27f8a9a380f0a390be7 100644 --- a/arch/um/sys-i386/shared/sysdep/syscalls.h +++ b/arch/um/sys-i386/shared/sysdep/syscalls.h @@ -20,7 +20,3 @@ extern syscall_handler_t *sys_call_table[]; #define EXECUTE_SYSCALL(syscall, regs) \ ((long (*)(struct syscall_args)) \ (*sys_call_table[syscall]))(SYSCALL_ARGS(®s->regs)) - -extern long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff); diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 731318e5ac1d44e011f29aa42ced5225904fd924..bc01e3ebfeb29bfbfe6d60b42276bc6565cf2e66 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -187,8 +187,8 @@ config HAVE_MMIOTRACE_SUPPORT def_bool y config X86_DECODER_SELFTEST - bool "x86 instruction decoder selftest" - depends on DEBUG_KERNEL + bool "x86 instruction decoder selftest" + depends on DEBUG_KERNEL && KPROBES ---help--- Perform x86 instruction decoder selftests at build time. This option is useful for checking the sanity of x86 instruction diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 4eefdca9832b4430931907096cf9f616e820f87f..53147ad85b967018e2f164de0cca11c00e04dbf9 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -696,7 +696,7 @@ ia32_sys_call_table: .quad quiet_ni_syscall /* streams2 */ .quad stub32_vfork /* 190 */ .quad compat_sys_getrlimit - .quad sys32_mmap2 + .quad sys_mmap_pgoff .quad sys32_truncate64 .quad sys32_ftruncate64 .quad sys32_stat64 /* 195 */ diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index df82c0e48dedff5c7ac9ac8d89ea96be2599e3af..422572c7792389d0174fbc2933aba31d34111d88 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c @@ -155,9 +155,6 @@ struct mmap_arg_struct { asmlinkage long sys32_mmap(struct mmap_arg_struct __user *arg) { struct mmap_arg_struct a; - struct file *file = NULL; - unsigned long retval; - struct mm_struct *mm ; if (copy_from_user(&a, arg, sizeof(a))) return -EFAULT; @@ -165,22 +162,8 @@ asmlinkage long sys32_mmap(struct mmap_arg_struct __user *arg) if (a.offset & ~PAGE_MASK) return -EINVAL; - if (!(a.flags & MAP_ANONYMOUS)) { - file = fget(a.fd); - if (!file) - return -EBADF; - } - - mm = current->mm; - down_write(&mm->mmap_sem); - retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, + return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset>>PAGE_SHIFT); - if (file) - fput(file); - - up_write(&mm->mmap_sem); - - return retval; } asmlinkage long sys32_mprotect(unsigned long start, size_t len, @@ -483,30 +466,6 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, return ret; } -asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - struct mm_struct *mm = current->mm; - unsigned long error; - struct file *file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - return -EBADF; - } - - down_write(&mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(&mm->mmap_sem); - - if (file) - fput(file); - return error; -} - asmlinkage long sys32_olduname(struct oldold_utsname __user *name) { char *arch = "x86_64"; diff --git a/arch/x86/include/asm/amd_iommu_proto.h b/arch/x86/include/asm/amd_iommu_proto.h index 84786fb9a23b8b29aeaa4d1455b91ab1cd273626..4d817f9e6e770b582e66b72788d31ebc091c766a 100644 --- a/arch/x86/include/asm/amd_iommu_proto.h +++ b/arch/x86/include/asm/amd_iommu_proto.h @@ -28,7 +28,9 @@ extern void amd_iommu_flush_all_domains(void); extern void amd_iommu_flush_all_devices(void); extern void amd_iommu_apply_erratum_63(u16 devid); extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu); - +extern int amd_iommu_init_devices(void); +extern void amd_iommu_uninit_devices(void); +extern void amd_iommu_init_notifier(void); #ifndef CONFIG_AMD_IOMMU_STATS static inline void amd_iommu_stats_init(void) { } diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 6a635bd39867bd8c996229790bf3197b8b3b9d5f..4611f085cd4304ce18a2ebdf3cb1c09778f03fa8 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -113,7 +113,7 @@ */ #define LOCAL_PENDING_VECTOR 0xec -#define UV_BAU_MESSAGE 0xec +#define UV_BAU_MESSAGE 0xea /* * Self IPI vector for machine checks diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 5bef931f8b1410f535e71faa1cdb64092390d593..2d228fc9b4b7642958e963e464b2b924435bebc4 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -244,6 +244,9 @@ do { \ #define write_rdtscp_aux(val) wrmsr(0xc0000103, (val), 0) +struct msr *msrs_alloc(void); +void msrs_free(struct msr *msrs); + #ifdef CONFIG_SMP int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index b399988eee3a3105e60be5fe760089d6cf57d3f0..b4bf9a942ed0810418613f75b156e328fc0fd5d9 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h @@ -118,11 +118,27 @@ extern int __init pcibios_init(void); /* pci-mmconfig.c */ +/* "PCI MMCONFIG %04x [bus %02x-%02x]" */ +#define PCI_MMCFG_RESOURCE_NAME_LEN (22 + 4 + 2 + 2) + +struct pci_mmcfg_region { + struct list_head list; + struct resource res; + u64 address; + char __iomem *virt; + u16 segment; + u8 start_bus; + u8 end_bus; + char name[PCI_MMCFG_RESOURCE_NAME_LEN]; +}; + extern int __init pci_mmcfg_arch_init(void); extern void __init pci_mmcfg_arch_free(void); +extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus); + +extern struct list_head pci_mmcfg_list; -extern struct acpi_mcfg_allocation *pci_mmcfg_config; -extern int pci_mmcfg_config_num; +#define PCI_MMCFG_BUS_OFFSET(bus) ((bus) << 20) /* * AMD Fam10h CPUs are buggy, and cannot access MMIO config space diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index b65a36defeb737434f8823c21c625f14db8e6347..0c44196b78ac82ec706220182acfc485b6d8fb87 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -74,31 +74,31 @@ extern void __bad_percpu_size(void); #define percpu_to_op(op, var, val) \ do { \ - typedef typeof(var) T__; \ + typedef typeof(var) pto_T__; \ if (0) { \ - T__ tmp__; \ - tmp__ = (val); \ + pto_T__ pto_tmp__; \ + pto_tmp__ = (val); \ } \ switch (sizeof(var)) { \ case 1: \ asm(op "b %1,"__percpu_arg(0) \ : "+m" (var) \ - : "qi" ((T__)(val))); \ + : "qi" ((pto_T__)(val))); \ break; \ case 2: \ asm(op "w %1,"__percpu_arg(0) \ : "+m" (var) \ - : "ri" ((T__)(val))); \ + : "ri" ((pto_T__)(val))); \ break; \ case 4: \ asm(op "l %1,"__percpu_arg(0) \ : "+m" (var) \ - : "ri" ((T__)(val))); \ + : "ri" ((pto_T__)(val))); \ break; \ case 8: \ asm(op "q %1,"__percpu_arg(0) \ : "+m" (var) \ - : "re" ((T__)(val))); \ + : "re" ((pto_T__)(val))); \ break; \ default: __bad_percpu_size(); \ } \ @@ -106,31 +106,31 @@ do { \ #define percpu_from_op(op, var, constraint) \ ({ \ - typeof(var) ret__; \ + typeof(var) pfo_ret__; \ switch (sizeof(var)) { \ case 1: \ asm(op "b "__percpu_arg(1)",%0" \ - : "=q" (ret__) \ + : "=q" (pfo_ret__) \ : constraint); \ break; \ case 2: \ asm(op "w "__percpu_arg(1)",%0" \ - : "=r" (ret__) \ + : "=r" (pfo_ret__) \ : constraint); \ break; \ case 4: \ asm(op "l "__percpu_arg(1)",%0" \ - : "=r" (ret__) \ + : "=r" (pfo_ret__) \ : constraint); \ break; \ case 8: \ asm(op "q "__percpu_arg(1)",%0" \ - : "=r" (ret__) \ + : "=r" (pfo_ret__) \ : constraint); \ break; \ default: __bad_percpu_size(); \ } \ - ret__; \ + pfo_ret__; \ }) /* @@ -153,6 +153,84 @@ do { \ #define percpu_or(var, val) percpu_to_op("or", per_cpu__##var, val) #define percpu_xor(var, val) percpu_to_op("xor", per_cpu__##var, val) +#define __this_cpu_read_1(pcp) percpu_from_op("mov", (pcp), "m"(pcp)) +#define __this_cpu_read_2(pcp) percpu_from_op("mov", (pcp), "m"(pcp)) +#define __this_cpu_read_4(pcp) percpu_from_op("mov", (pcp), "m"(pcp)) + +#define __this_cpu_write_1(pcp, val) percpu_to_op("mov", (pcp), val) +#define __this_cpu_write_2(pcp, val) percpu_to_op("mov", (pcp), val) +#define __this_cpu_write_4(pcp, val) percpu_to_op("mov", (pcp), val) +#define __this_cpu_add_1(pcp, val) percpu_to_op("add", (pcp), val) +#define __this_cpu_add_2(pcp, val) percpu_to_op("add", (pcp), val) +#define __this_cpu_add_4(pcp, val) percpu_to_op("add", (pcp), val) +#define __this_cpu_and_1(pcp, val) percpu_to_op("and", (pcp), val) +#define __this_cpu_and_2(pcp, val) percpu_to_op("and", (pcp), val) +#define __this_cpu_and_4(pcp, val) percpu_to_op("and", (pcp), val) +#define __this_cpu_or_1(pcp, val) percpu_to_op("or", (pcp), val) +#define __this_cpu_or_2(pcp, val) percpu_to_op("or", (pcp), val) +#define __this_cpu_or_4(pcp, val) percpu_to_op("or", (pcp), val) +#define __this_cpu_xor_1(pcp, val) percpu_to_op("xor", (pcp), val) +#define __this_cpu_xor_2(pcp, val) percpu_to_op("xor", (pcp), val) +#define __this_cpu_xor_4(pcp, val) percpu_to_op("xor", (pcp), val) + +#define this_cpu_read_1(pcp) percpu_from_op("mov", (pcp), "m"(pcp)) +#define this_cpu_read_2(pcp) percpu_from_op("mov", (pcp), "m"(pcp)) +#define this_cpu_read_4(pcp) percpu_from_op("mov", (pcp), "m"(pcp)) +#define this_cpu_write_1(pcp, val) percpu_to_op("mov", (pcp), val) +#define this_cpu_write_2(pcp, val) percpu_to_op("mov", (pcp), val) +#define this_cpu_write_4(pcp, val) percpu_to_op("mov", (pcp), val) +#define this_cpu_add_1(pcp, val) percpu_to_op("add", (pcp), val) +#define this_cpu_add_2(pcp, val) percpu_to_op("add", (pcp), val) +#define this_cpu_add_4(pcp, val) percpu_to_op("add", (pcp), val) +#define this_cpu_and_1(pcp, val) percpu_to_op("and", (pcp), val) +#define this_cpu_and_2(pcp, val) percpu_to_op("and", (pcp), val) +#define this_cpu_and_4(pcp, val) percpu_to_op("and", (pcp), val) +#define this_cpu_or_1(pcp, val) percpu_to_op("or", (pcp), val) +#define this_cpu_or_2(pcp, val) percpu_to_op("or", (pcp), val) +#define this_cpu_or_4(pcp, val) percpu_to_op("or", (pcp), val) +#define this_cpu_xor_1(pcp, val) percpu_to_op("xor", (pcp), val) +#define this_cpu_xor_2(pcp, val) percpu_to_op("xor", (pcp), val) +#define this_cpu_xor_4(pcp, val) percpu_to_op("xor", (pcp), val) + +#define irqsafe_cpu_add_1(pcp, val) percpu_to_op("add", (pcp), val) +#define irqsafe_cpu_add_2(pcp, val) percpu_to_op("add", (pcp), val) +#define irqsafe_cpu_add_4(pcp, val) percpu_to_op("add", (pcp), val) +#define irqsafe_cpu_and_1(pcp, val) percpu_to_op("and", (pcp), val) +#define irqsafe_cpu_and_2(pcp, val) percpu_to_op("and", (pcp), val) +#define irqsafe_cpu_and_4(pcp, val) percpu_to_op("and", (pcp), val) +#define irqsafe_cpu_or_1(pcp, val) percpu_to_op("or", (pcp), val) +#define irqsafe_cpu_or_2(pcp, val) percpu_to_op("or", (pcp), val) +#define irqsafe_cpu_or_4(pcp, val) percpu_to_op("or", (pcp), val) +#define irqsafe_cpu_xor_1(pcp, val) percpu_to_op("xor", (pcp), val) +#define irqsafe_cpu_xor_2(pcp, val) percpu_to_op("xor", (pcp), val) +#define irqsafe_cpu_xor_4(pcp, val) percpu_to_op("xor", (pcp), val) + +/* + * Per cpu atomic 64 bit operations are only available under 64 bit. + * 32 bit must fall back to generic operations. + */ +#ifdef CONFIG_X86_64 +#define __this_cpu_read_8(pcp) percpu_from_op("mov", (pcp), "m"(pcp)) +#define __this_cpu_write_8(pcp, val) percpu_to_op("mov", (pcp), val) +#define __this_cpu_add_8(pcp, val) percpu_to_op("add", (pcp), val) +#define __this_cpu_and_8(pcp, val) percpu_to_op("and", (pcp), val) +#define __this_cpu_or_8(pcp, val) percpu_to_op("or", (pcp), val) +#define __this_cpu_xor_8(pcp, val) percpu_to_op("xor", (pcp), val) + +#define this_cpu_read_8(pcp) percpu_from_op("mov", (pcp), "m"(pcp)) +#define this_cpu_write_8(pcp, val) percpu_to_op("mov", (pcp), val) +#define this_cpu_add_8(pcp, val) percpu_to_op("add", (pcp), val) +#define this_cpu_and_8(pcp, val) percpu_to_op("and", (pcp), val) +#define this_cpu_or_8(pcp, val) percpu_to_op("or", (pcp), val) +#define this_cpu_xor_8(pcp, val) percpu_to_op("xor", (pcp), val) + +#define irqsafe_cpu_add_8(pcp, val) percpu_to_op("add", (pcp), val) +#define irqsafe_cpu_and_8(pcp, val) percpu_to_op("and", (pcp), val) +#define irqsafe_cpu_or_8(pcp, val) percpu_to_op("or", (pcp), val) +#define irqsafe_cpu_xor_8(pcp, val) percpu_to_op("xor", (pcp), val) + +#endif + /* This is not atomic against other CPUs -- CPU preemption needs to be off */ #define x86_test_and_clear_bit_percpu(bit, var) \ ({ \ diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h index 9af9decb38c35fd1a109839e096701a549dd258d..4a5a089e1c6273c7d7a633a5be1b3e64c7e9a6db 100644 --- a/arch/x86/include/asm/sys_ia32.h +++ b/arch/x86/include/asm/sys_ia32.h @@ -57,9 +57,6 @@ asmlinkage long sys32_pwrite(unsigned int, char __user *, u32, u32, u32); asmlinkage long sys32_personality(unsigned long); asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32); -asmlinkage long sys32_mmap2(unsigned long, unsigned long, unsigned long, - unsigned long, unsigned long, unsigned long); - struct oldold_utsname; struct old_utsname; asmlinkage long sys32_olduname(struct oldold_utsname __user *); diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h index 372b76edd63f69053c76bcf7501eb71c35bb8f93..1bb6e395881c3fb43dec70cad2aac7ac7aeb3b4e 100644 --- a/arch/x86/include/asm/syscalls.h +++ b/arch/x86/include/asm/syscalls.h @@ -55,8 +55,6 @@ struct sel_arg_struct; struct oldold_utsname; struct old_utsname; -asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long, - unsigned long, unsigned long, unsigned long); asmlinkage int old_mmap(struct mmap_arg_struct __user *); asmlinkage int old_select(struct sel_arg_struct __user *); asmlinkage int sys_ipc(uint, int, int, int, void __user *, long); diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index 022a84386de8cf1c45b5aa45f3d721153c72edc2..ecb544e65382893970f2090dd3bb341d03583f4a 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h @@ -23,6 +23,7 @@ struct task_struct *__switch_to(struct task_struct *prev, struct tss_struct; void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, struct tss_struct *tss); +extern void show_regs_common(void); #ifdef CONFIG_X86_32 diff --git a/arch/x86/include/asm/trampoline.h b/arch/x86/include/asm/trampoline.h index 90f06c25221d792dab33f662c25012b7d0c39f59..cb507bb05d7923a32d9134e61a938fdba184a2c9 100644 --- a/arch/x86/include/asm/trampoline.h +++ b/arch/x86/include/asm/trampoline.h @@ -16,7 +16,6 @@ extern unsigned long initial_code; extern unsigned long initial_gs; #define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE) -#define TRAMPOLINE_BASE 0x6000 extern unsigned long setup_trampoline(void); extern void __init reserve_trampoline_memory(void); diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h index d5b7e90c0edfd3ca1bf7d05e3f4c4e642f8e6fb7..396ff4cc8ed480b7bc306f63091b88f6dda00442 100644 --- a/arch/x86/include/asm/xen/hypervisor.h +++ b/arch/x86/include/asm/xen/hypervisor.h @@ -37,31 +37,4 @@ extern struct shared_info *HYPERVISOR_shared_info; extern struct start_info *xen_start_info; -enum xen_domain_type { - XEN_NATIVE, /* running on bare hardware */ - XEN_PV_DOMAIN, /* running in a PV domain */ - XEN_HVM_DOMAIN, /* running in a Xen hvm domain */ -}; - -#ifdef CONFIG_XEN -extern enum xen_domain_type xen_domain_type; -#else -#define xen_domain_type XEN_NATIVE -#endif - -#define xen_domain() (xen_domain_type != XEN_NATIVE) -#define xen_pv_domain() (xen_domain() && \ - xen_domain_type == XEN_PV_DOMAIN) -#define xen_hvm_domain() (xen_domain() && \ - xen_domain_type == XEN_HVM_DOMAIN) - -#ifdef CONFIG_XEN_DOM0 -#include - -#define xen_initial_domain() (xen_pv_domain() && \ - xen_start_info->flags & SIF_INITDOMAIN) -#else /* !CONFIG_XEN_DOM0 */ -#define xen_initial_domain() (0) -#endif /* CONFIG_XEN_DOM0 */ - #endif /* _ASM_X86_XEN_HYPERVISOR_H */ diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 1c0fb4d4ad556c5daf51f623151b051577f3a966..b990b5cc95418df45f1c94f1b748cb5d59d45e1c 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -166,6 +166,43 @@ static void iommu_uninit_device(struct device *dev) { kfree(dev->archdata.iommu); } + +void __init amd_iommu_uninit_devices(void) +{ + struct pci_dev *pdev = NULL; + + for_each_pci_dev(pdev) { + + if (!check_device(&pdev->dev)) + continue; + + iommu_uninit_device(&pdev->dev); + } +} + +int __init amd_iommu_init_devices(void) +{ + struct pci_dev *pdev = NULL; + int ret = 0; + + for_each_pci_dev(pdev) { + + if (!check_device(&pdev->dev)) + continue; + + ret = iommu_init_device(&pdev->dev); + if (ret) + goto out_free; + } + + return 0; + +out_free: + + amd_iommu_uninit_devices(); + + return ret; +} #ifdef CONFIG_AMD_IOMMU_STATS /* @@ -1587,6 +1624,11 @@ static struct notifier_block device_nb = { .notifier_call = device_change_notifier, }; +void amd_iommu_init_notifier(void) +{ + bus_register_notifier(&pci_bus_type, &device_nb); +} + /***************************************************************************** * * The next functions belong to the dma_ops mapping/unmapping code. @@ -2145,8 +2187,6 @@ static void prealloc_protection_domains(void) if (!check_device(&dev->dev)) continue; - iommu_init_device(&dev->dev); - /* Is there already any domain for it? */ if (domain_for_device(&dev->dev)) continue; @@ -2215,8 +2255,6 @@ int __init amd_iommu_init_dma_ops(void) register_iommu(&amd_iommu_ops); - bus_register_notifier(&pci_bus_type, &device_nb); - amd_iommu_stats_init(); return 0; diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 7ffc39965233ce570a7b734f12636ce05e403d1e..1dca9c34eaeb4417ebe336810edb648a738a5e1a 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -1274,6 +1274,10 @@ static int __init amd_iommu_init(void) if (ret) goto free; + ret = amd_iommu_init_devices(); + if (ret) + goto free; + if (iommu_pass_through) ret = amd_iommu_init_passthrough(); else @@ -1281,6 +1285,8 @@ static int __init amd_iommu_init(void) if (ret) goto free; + amd_iommu_init_notifier(); + enable_iommus(); if (iommu_pass_through) @@ -1296,6 +1302,9 @@ out: return ret; free: + + amd_iommu_uninit_devices(); + free_pages((unsigned long)amd_iommu_pd_alloc_bitmap, get_order(MAX_DOMAIN_ID/8)); @@ -1336,6 +1345,9 @@ void __init amd_iommu_detect(void) iommu_detected = 1; amd_iommu_detected = 1; x86_init.iommu.iommu_init = amd_iommu_init; + + /* Make sure ACS will be enabled */ + pci_request_acs(); } } diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index e0dfb6856aa297ef9349dc36c3b5cef93b5abbf0..3704997e8b2573bda630720f4c47bd4a7ec3b8c5 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c @@ -280,7 +280,8 @@ void __init early_gart_iommu_check(void) * or BIOS forget to put that in reserved. * try to update e820 to make that region as reserved. */ - int i, fix, slot; + u32 agp_aper_base = 0, agp_aper_order = 0; + int i, fix, slot, valid_agp = 0; u32 ctl; u32 aper_size = 0, aper_order = 0, last_aper_order = 0; u64 aper_base = 0, last_aper_base = 0; @@ -290,6 +291,8 @@ void __init early_gart_iommu_check(void) return; /* This is mostly duplicate of iommu_hole_init */ + agp_aper_base = search_agp_bridge(&agp_aper_order, &valid_agp); + fix = 0; for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { int bus; @@ -342,10 +345,10 @@ void __init early_gart_iommu_check(void) } } - if (!fix) + if (valid_agp) return; - /* different nodes have different setting, disable them all at first*/ + /* disable them all at first */ for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { int bus; int dev_base, dev_limit; @@ -458,8 +461,6 @@ out: if (aper_alloc) { /* Got the aperture from the AGP bridge */ - } else if (!valid_agp) { - /* Do nothing */ } else if ((!no_iommu && max_pfn > MAX_DMA32_PFN) || force_iommu || valid_agp || diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index efb2b9cd132c79f4c8a60f8973ae2995d3c3ccb8..aa57c079c98f6c345e91313e37f3f52e8d3f26bb 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1341,7 +1341,7 @@ void enable_x2apic(void) rdmsr(MSR_IA32_APICBASE, msr, msr2); if (!(msr & X2APIC_ENABLE)) { - pr_info("Enabling x2apic\n"); + printk_once(KERN_INFO "Enabling x2apic\n"); wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0); } } diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c index d9acc3bee0f4328aa3ef88eb8086ba90cc59ef9c..e31b9ffe25f5e1f84c62593c8441f765f80c0158 100644 --- a/arch/x86/kernel/apic/apic_noop.c +++ b/arch/x86/kernel/apic/apic_noop.c @@ -127,7 +127,7 @@ static u32 noop_apic_read(u32 reg) static void noop_apic_write(u32 reg, u32 v) { - WARN_ON_ONCE((cpu_has_apic || !disable_apic)); + WARN_ON_ONCE(cpu_has_apic && !disable_apic); } struct apic apic_noop = { diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index e85f8fb7f8e7d008e7acdb4e78c8f5cd6a9cd5f4..dd2b5f26464364611bf603f10689289630bdd00e 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -27,6 +27,9 @@ * * http://www.unisys.com */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -223,9 +226,9 @@ static int parse_unisys_oem(char *oemptr) mip_addr = val; mip = (struct mip_reg *)val; mip_reg = __va(mip); - pr_debug("es7000_mipcfg: host_reg = 0x%lx \n", + pr_debug("host_reg = 0x%lx\n", (unsigned long)host_reg); - pr_debug("es7000_mipcfg: mip_reg = 0x%lx \n", + pr_debug("mip_reg = 0x%lx\n", (unsigned long)mip_reg); success++; break; @@ -401,7 +404,7 @@ static void es7000_enable_apic_mode(void) if (!es7000_plat) return; - printk(KERN_INFO "ES7000: Enabling APIC mode.\n"); + pr_info("Enabling APIC mode.\n"); memset(&es7000_mip_reg, 0, sizeof(struct mip_reg)); es7000_mip_reg.off_0x00 = MIP_SW_APIC; es7000_mip_reg.off_0x38 = MIP_VALID; @@ -514,8 +517,7 @@ static void es7000_setup_apic_routing(void) { int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id()); - printk(KERN_INFO - "Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n", + pr_info("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n", (apic_version[apic] == 0x14) ? "Physical Cluster" : "Logical Cluster", nr_ioapics, cpumask_bits(es7000_target_cpus())[0]); diff --git a/arch/x86/kernel/apic/nmi.c b/arch/x86/kernel/apic/nmi.c index 6389432a9dbf7f07a0dd08b4e67857c6ec899d6d..0159a69396cba449a424190459a02d83a3f417d8 100644 --- a/arch/x86/kernel/apic/nmi.c +++ b/arch/x86/kernel/apic/nmi.c @@ -361,7 +361,7 @@ void stop_apic_nmi_watchdog(void *unused) */ static DEFINE_PER_CPU(unsigned, last_irq_sum); -static DEFINE_PER_CPU(local_t, alert_counter); +static DEFINE_PER_CPU(long, alert_counter); static DEFINE_PER_CPU(int, nmi_touch); void touch_nmi_watchdog(void) @@ -438,8 +438,8 @@ nmi_watchdog_tick(struct pt_regs *regs, unsigned reason) * Ayiee, looks like this CPU is stuck ... * wait a few IRQs (5 seconds) before doing the oops ... */ - local_inc(&__get_cpu_var(alert_counter)); - if (local_read(&__get_cpu_var(alert_counter)) == 5 * nmi_hz) + __this_cpu_inc(per_cpu_var(alert_counter)); + if (__this_cpu_read(per_cpu_var(alert_counter)) == 5 * nmi_hz) /* * die_nmi will return ONLY if NOTIFY_STOP happens.. */ @@ -447,7 +447,7 @@ nmi_watchdog_tick(struct pt_regs *regs, unsigned reason) regs, panic_on_timeout); } else { __get_cpu_var(last_irq_sum) = sum; - local_set(&__get_cpu_var(alert_counter), 0); + __this_cpu_write(per_cpu_var(alert_counter), 0); } /* see if the nmi watchdog went off */ diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index c965e5212714ee66cfe04e847544e213f44a7b2d..468489b57aae6d8d3eefabc0a27358f6e9553112 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c @@ -74,6 +74,7 @@ void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) unsigned int eax, ebx, ecx, edx, sub_index; unsigned int ht_mask_width, core_plus_mask_width; unsigned int core_select_mask, core_level_siblings; + static bool printed; if (c->cpuid_level < 0xb) return; @@ -127,12 +128,14 @@ void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) c->x86_max_cores = (core_level_siblings / smp_num_siblings); - - printk(KERN_INFO "CPU: Physical Processor ID: %d\n", - c->phys_proc_id); - if (c->x86_max_cores > 1) - printk(KERN_INFO "CPU: Processor Core ID: %d\n", - c->cpu_core_id); + if (!printed) { + printk(KERN_INFO "CPU: Physical Processor ID: %d\n", + c->phys_proc_id); + if (c->x86_max_cores > 1) + printk(KERN_INFO "CPU: Processor Core ID: %d\n", + c->cpu_core_id); + printed = 1; + } return; #endif } diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 7128b3799cecdd8c2f708124e1939c0686224511..8dc3ea145c975a3eebfbb1510f30c9ffa7b48e06 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -375,8 +375,6 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) node = nearby_node(apicid); } numa_set_node(cpu, node); - - printk(KERN_INFO "CPU %d/0x%x -> Node %d\n", cpu, apicid, node); #endif } diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index c1afa990a6c84bf49229a9c50052b063b9731236..4868e4a951eeec310c10d06428d60c49e2fe79b5 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -427,6 +427,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) #ifdef CONFIG_X86_HT u32 eax, ebx, ecx, edx; int index_msb, core_bits; + static bool printed; if (!cpu_has(c, X86_FEATURE_HT)) return; @@ -442,7 +443,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) smp_num_siblings = (ebx & 0xff0000) >> 16; if (smp_num_siblings == 1) { - printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); + printk_once(KERN_INFO "CPU0: Hyper-Threading is disabled\n"); goto out; } @@ -469,11 +470,12 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) ((1 << core_bits) - 1); out: - if ((c->x86_max_cores * smp_num_siblings) > 1) { + if (!printed && (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); + printed = 1; } #endif } @@ -1093,7 +1095,7 @@ static void clear_all_debug_regs(void) void __cpuinit cpu_init(void) { - struct orig_ist *orig_ist; + struct orig_ist *oist; struct task_struct *me; struct tss_struct *t; unsigned long v; @@ -1102,7 +1104,7 @@ void __cpuinit cpu_init(void) cpu = stack_smp_processor_id(); t = &per_cpu(init_tss, cpu); - orig_ist = &per_cpu(orig_ist, cpu); + oist = &per_cpu(orig_ist, cpu); #ifdef CONFIG_NUMA if (cpu != 0 && percpu_read(node_number) == 0 && @@ -1115,7 +1117,7 @@ void __cpuinit cpu_init(void) if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) panic("CPU#%d already initialized!\n", cpu); - printk(KERN_INFO "Initializing CPU#%d\n", cpu); + pr_debug("Initializing CPU#%d\n", cpu); clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); @@ -1143,12 +1145,12 @@ void __cpuinit cpu_init(void) /* * set up and load the per-CPU TSS */ - if (!orig_ist->ist[0]) { + if (!oist->ist[0]) { char *estacks = per_cpu(exception_stacks, cpu); for (v = 0; v < N_EXCEPTION_STACKS; v++) { estacks += exception_stack_sizes[v]; - orig_ist->ist[v] = t->x86_tss.ist[v] = + oist->ist[v] = t->x86_tss.ist[v] = (unsigned long)estacks; } } diff --git a/arch/x86/kernel/cpu/cpu_debug.c b/arch/x86/kernel/cpu/cpu_debug.c index dca325c0399960c4bdacc7659d3f04dbfbbdd541..b368cd862997d7cbcfb0b425fb9f1d45e136e9d0 100644 --- a/arch/x86/kernel/cpu/cpu_debug.c +++ b/arch/x86/kernel/cpu/cpu_debug.c @@ -30,9 +30,9 @@ #include #include -static DEFINE_PER_CPU(struct cpu_cpuX_base [CPU_REG_ALL_BIT], cpu_arr); -static DEFINE_PER_CPU(struct cpu_private * [MAX_CPU_FILES], priv_arr); -static DEFINE_PER_CPU(int, cpu_priv_count); +static DEFINE_PER_CPU(struct cpu_cpuX_base [CPU_REG_ALL_BIT], cpud_arr); +static DEFINE_PER_CPU(struct cpu_private * [MAX_CPU_FILES], cpud_priv_arr); +static DEFINE_PER_CPU(int, cpud_priv_count); static DEFINE_MUTEX(cpu_debug_lock); @@ -531,7 +531,7 @@ static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg, /* Already intialized */ if (file == CPU_INDEX_BIT) - if (per_cpu(cpu_arr[type].init, cpu)) + if (per_cpu(cpud_arr[type].init, cpu)) return 0; priv = kzalloc(sizeof(*priv), GFP_KERNEL); @@ -543,8 +543,8 @@ static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg, priv->reg = reg; priv->file = file; mutex_lock(&cpu_debug_lock); - per_cpu(priv_arr[type], cpu) = priv; - per_cpu(cpu_priv_count, cpu)++; + per_cpu(cpud_priv_arr[type], cpu) = priv; + per_cpu(cpud_priv_count, cpu)++; mutex_unlock(&cpu_debug_lock); if (file) @@ -552,10 +552,10 @@ static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg, dentry, (void *)priv, &cpu_fops); else { debugfs_create_file(cpu_base[type].name, S_IRUGO, - per_cpu(cpu_arr[type].dentry, cpu), + per_cpu(cpud_arr[type].dentry, cpu), (void *)priv, &cpu_fops); mutex_lock(&cpu_debug_lock); - per_cpu(cpu_arr[type].init, cpu) = 1; + per_cpu(cpud_arr[type].init, cpu) = 1; mutex_unlock(&cpu_debug_lock); } @@ -615,7 +615,7 @@ static int cpu_init_allreg(unsigned cpu, struct dentry *dentry) if (!is_typeflag_valid(cpu, cpu_base[type].flag)) continue; cpu_dentry = debugfs_create_dir(cpu_base[type].name, dentry); - per_cpu(cpu_arr[type].dentry, cpu) = cpu_dentry; + per_cpu(cpud_arr[type].dentry, cpu) = cpu_dentry; if (type < CPU_TSS_BIT) err = cpu_init_msr(cpu, type, cpu_dentry); @@ -647,11 +647,11 @@ static int cpu_init_cpu(void) err = cpu_init_allreg(cpu, cpu_dentry); pr_info("cpu%d(%d) debug files %d\n", - cpu, nr_cpu_ids, per_cpu(cpu_priv_count, cpu)); - if (per_cpu(cpu_priv_count, cpu) > MAX_CPU_FILES) { + cpu, nr_cpu_ids, per_cpu(cpud_priv_count, cpu)); + if (per_cpu(cpud_priv_count, cpu) > MAX_CPU_FILES) { pr_err("Register files count %d exceeds limit %d\n", - per_cpu(cpu_priv_count, cpu), MAX_CPU_FILES); - per_cpu(cpu_priv_count, cpu) = MAX_CPU_FILES; + per_cpu(cpud_priv_count, cpu), MAX_CPU_FILES); + per_cpu(cpud_priv_count, cpu) = MAX_CPU_FILES; err = -ENFILE; } if (err) @@ -676,8 +676,8 @@ static void __exit cpu_debug_exit(void) debugfs_remove_recursive(cpu_debugfs_dir); for (cpu = 0; cpu < nr_cpu_ids; cpu++) - for (i = 0; i < per_cpu(cpu_priv_count, cpu); i++) - kfree(per_cpu(priv_arr[i], cpu)); + for (i = 0; i < per_cpu(cpud_priv_count, cpu); i++) + kfree(per_cpu(cpud_priv_arr[i], cpu)); } module_init(cpu_debug_init); diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 8b581d3905cb47214af854582e24a379fac444f3..f28decf8dde3990626f493e5d962bfea9d48e59f 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -68,9 +68,9 @@ struct acpi_cpufreq_data { unsigned int cpu_feature; }; -static DEFINE_PER_CPU(struct acpi_cpufreq_data *, drv_data); +static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data); -static DEFINE_PER_CPU(struct aperfmperf, old_perf); +static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf); /* acpi_perf_data is a pointer to percpu data. */ static struct acpi_processor_performance *acpi_perf_data; @@ -214,14 +214,14 @@ static u32 get_cur_val(const struct cpumask *mask) if (unlikely(cpumask_empty(mask))) return 0; - switch (per_cpu(drv_data, cpumask_first(mask))->cpu_feature) { + switch (per_cpu(acfreq_data, cpumask_first(mask))->cpu_feature) { case SYSTEM_INTEL_MSR_CAPABLE: cmd.type = SYSTEM_INTEL_MSR_CAPABLE; cmd.addr.msr.reg = MSR_IA32_PERF_STATUS; break; case SYSTEM_IO_CAPABLE: cmd.type = SYSTEM_IO_CAPABLE; - perf = per_cpu(drv_data, cpumask_first(mask))->acpi_data; + perf = per_cpu(acfreq_data, cpumask_first(mask))->acpi_data; cmd.addr.io.port = perf->control_register.address; cmd.addr.io.bit_width = perf->control_register.bit_width; break; @@ -268,8 +268,8 @@ static unsigned int get_measured_perf(struct cpufreq_policy *policy, if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1)) return 0; - ratio = calc_aperfmperf_ratio(&per_cpu(old_perf, cpu), &perf); - per_cpu(old_perf, cpu) = perf; + ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf); + per_cpu(acfreq_old_perf, cpu) = perf; retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT; @@ -278,7 +278,7 @@ static unsigned int get_measured_perf(struct cpufreq_policy *policy, static unsigned int get_cur_freq_on_cpu(unsigned int cpu) { - struct acpi_cpufreq_data *data = per_cpu(drv_data, cpu); + struct acpi_cpufreq_data *data = per_cpu(acfreq_data, cpu); unsigned int freq; unsigned int cached_freq; @@ -322,7 +322,7 @@ static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq, static int acpi_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { - struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu); + struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu); struct acpi_processor_performance *perf; struct cpufreq_freqs freqs; struct drv_cmd cmd; @@ -416,7 +416,7 @@ out: static int acpi_cpufreq_verify(struct cpufreq_policy *policy) { - struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu); + struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu); dprintk("acpi_cpufreq_verify\n"); @@ -574,7 +574,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) return -ENOMEM; data->acpi_data = per_cpu_ptr(acpi_perf_data, cpu); - per_cpu(drv_data, cpu) = data; + per_cpu(acfreq_data, cpu) = data; if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; @@ -725,20 +725,20 @@ err_unreg: acpi_processor_unregister_performance(perf, cpu); err_free: kfree(data); - per_cpu(drv_data, cpu) = NULL; + per_cpu(acfreq_data, cpu) = NULL; return result; } static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy) { - struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu); + struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu); dprintk("acpi_cpufreq_cpu_exit\n"); if (data) { cpufreq_frequency_table_put_attr(policy->cpu); - per_cpu(drv_data, policy->cpu) = NULL; + per_cpu(acfreq_data, policy->cpu) = NULL; acpi_processor_unregister_performance(data->acpi_data, policy->cpu); kfree(data); @@ -749,7 +749,7 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy) static int acpi_cpufreq_resume(struct cpufreq_policy *policy) { - struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu); + struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu); dprintk("acpi_cpufreq_resume\n"); @@ -764,14 +764,15 @@ static struct freq_attr *acpi_cpufreq_attr[] = { }; 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, + .bios_limit = acpi_processor_get_bios_limit, + .init = acpi_cpufreq_cpu_init, + .exit = acpi_cpufreq_cpu_exit, + .resume = acpi_cpufreq_resume, + .name = "acpi-cpufreq", + .owner = THIS_MODULE, + .attr = acpi_cpufreq_attr, }; static int __init acpi_cpufreq_init(void) diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c index f10dea409f40c3755754fbad0ae1b91eb6d1f604..cb01dac267d3de14486db1bf3ed081be5999a45e 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c @@ -164,7 +164,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) } /* cpuinfo and default policy values */ - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cpuinfo.transition_latency = 200000; policy->cur = busfreq * max_multiplier; result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio); diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c index d47c775eb0abce217593a99cd06dba2f87125977..9a97116f89e5ebc4805db1c608c5e79e96d847f5 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c @@ -714,14 +714,17 @@ static struct freq_attr *powernow_table_attr[] = { }; static struct cpufreq_driver powernow_driver = { - .verify = powernow_verify, - .target = powernow_target, - .get = powernow_get, - .init = powernow_cpu_init, - .exit = powernow_cpu_exit, - .name = "powernow-k7", - .owner = THIS_MODULE, - .attr = powernow_table_attr, + .verify = powernow_verify, + .target = powernow_target, + .get = powernow_get, +#ifdef CONFIG_X86_POWERNOW_K7_ACPI + .bios_limit = acpi_processor_get_bios_limit, +#endif + .init = powernow_cpu_init, + .exit = powernow_cpu_exit, + .name = "powernow-k7", + .owner = THIS_MODULE, + .attr = powernow_table_attr, }; static int __init powernow_init(void) diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 3f12dabeab525d2de56321c6dc1a1a6817d8db7a..a9df9441a9a240cd138b6492896cc0788a04cf1b 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -1118,7 +1118,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relation) { - cpumask_t oldmask; + cpumask_var_t oldmask; struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu); u32 checkfid; u32 checkvid; @@ -1131,9 +1131,13 @@ static int powernowk8_target(struct cpufreq_policy *pol, checkfid = data->currfid; checkvid = data->currvid; - /* only run on specific CPU from here on */ - oldmask = current->cpus_allowed; - set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu)); + /* only run on specific CPU from here on. */ + /* This is poor form: use a workqueue or smp_call_function_single */ + if (!alloc_cpumask_var(&oldmask, GFP_KERNEL)) + return -ENOMEM; + + cpumask_copy(oldmask, tsk_cpumask(current)); + set_cpus_allowed_ptr(current, cpumask_of(pol->cpu)); if (smp_processor_id() != pol->cpu) { printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu); @@ -1193,7 +1197,8 @@ static int powernowk8_target(struct cpufreq_policy *pol, ret = 0; err_out: - set_cpus_allowed_ptr(current, &oldmask); + set_cpus_allowed_ptr(current, oldmask); + free_cpumask_var(oldmask); return ret; } @@ -1393,14 +1398,15 @@ static struct freq_attr *powernow_k8_attr[] = { }; static struct cpufreq_driver cpufreq_amd64_driver = { - .verify = powernowk8_verify, - .target = powernowk8_target, - .init = powernowk8_cpu_init, - .exit = __devexit_p(powernowk8_cpu_exit), - .get = powernowk8_get, - .name = "powernow-k8", - .owner = THIS_MODULE, - .attr = powernow_k8_attr, + .verify = powernowk8_verify, + .target = powernowk8_target, + .bios_limit = acpi_processor_get_bios_limit, + .init = powernowk8_cpu_init, + .exit = __devexit_p(powernowk8_cpu_exit), + .get = powernowk8_get, + .name = "powernow-k8", + .owner = THIS_MODULE, + .attr = powernow_k8_attr, }; /* driver entry point for init */ diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c index 3ae5a7a3a500dc2ddf392ba730736ade952057d7..2ce8e0b5cc541b38052f4c2075fbd021f745ba06 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c @@ -39,7 +39,7 @@ static struct pci_dev *speedstep_chipset_dev; /* speedstep_processor */ -static unsigned int speedstep_processor; +static enum speedstep_processor speedstep_processor; static u32 pmbase; diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c index f4c290b8482f8718cb876095f227fc5cb58e7320..ad0083abfa23f7fcdc30c4a5e8d0ada72214db92 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c @@ -34,7 +34,7 @@ static int relaxed_check; * GET PROCESSOR CORE SPEED IN KHZ * *********************************************************************/ -static unsigned int pentium3_get_frequency(unsigned int processor) +static unsigned int pentium3_get_frequency(enum speedstep_processor processor) { /* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */ struct { @@ -227,7 +227,7 @@ static unsigned int pentium4_get_frequency(void) /* Warning: may get called from smp_call_function_single. */ -unsigned int speedstep_get_frequency(unsigned int processor) +unsigned int speedstep_get_frequency(enum speedstep_processor processor) { switch (processor) { case SPEEDSTEP_CPU_PCORE: @@ -380,7 +380,7 @@ EXPORT_SYMBOL_GPL(speedstep_detect_processor); * DETECT SPEEDSTEP SPEEDS * *********************************************************************/ -unsigned int speedstep_get_freqs(unsigned int processor, +unsigned int speedstep_get_freqs(enum speedstep_processor processor, unsigned int *low_speed, unsigned int *high_speed, unsigned int *transition_latency, diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.h b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.h index 2b6c04e5a30429a011a78f20e74bf7413548f6ad..70d9cea1219df63eb37db0b325a03a483f842d7d 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.h +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.h @@ -11,18 +11,18 @@ /* processors */ - -#define SPEEDSTEP_CPU_PIII_C_EARLY 0x00000001 /* Coppermine core */ -#define SPEEDSTEP_CPU_PIII_C 0x00000002 /* Coppermine core */ -#define SPEEDSTEP_CPU_PIII_T 0x00000003 /* Tualatin core */ -#define SPEEDSTEP_CPU_P4M 0x00000004 /* P4-M */ - +enum speedstep_processor { + SPEEDSTEP_CPU_PIII_C_EARLY = 0x00000001, /* Coppermine core */ + SPEEDSTEP_CPU_PIII_C = 0x00000002, /* Coppermine core */ + SPEEDSTEP_CPU_PIII_T = 0x00000003, /* Tualatin core */ + SPEEDSTEP_CPU_P4M = 0x00000004, /* P4-M */ /* the following processors are not speedstep-capable and are not auto-detected * in speedstep_detect_processor(). However, their speed can be detected using * the speedstep_get_frequency() call. */ -#define SPEEDSTEP_CPU_PM 0xFFFFFF03 /* Pentium M */ -#define SPEEDSTEP_CPU_P4D 0xFFFFFF04 /* desktop P4 */ -#define SPEEDSTEP_CPU_PCORE 0xFFFFFF05 /* Core */ + SPEEDSTEP_CPU_PM = 0xFFFFFF03, /* Pentium M */ + SPEEDSTEP_CPU_P4D = 0xFFFFFF04, /* desktop P4 */ + SPEEDSTEP_CPU_PCORE = 0xFFFFFF05, /* Core */ +}; /* speedstep states -- only two of them */ @@ -31,10 +31,10 @@ /* detect a speedstep-capable processor */ -extern unsigned int speedstep_detect_processor (void); +extern enum speedstep_processor speedstep_detect_processor(void); /* detect the current speed (in khz) of the processor */ -extern unsigned int speedstep_get_frequency(unsigned int processor); +extern unsigned int speedstep_get_frequency(enum speedstep_processor processor); /* detect the low and high speeds of the processor. The callback @@ -42,7 +42,7 @@ extern unsigned int speedstep_get_frequency(unsigned int processor); * SPEEDSTEP_LOW; the second argument is zero so that no * cpufreq_notify_transition calls are initiated. */ -extern unsigned int speedstep_get_freqs(unsigned int processor, +extern unsigned int speedstep_get_freqs(enum speedstep_processor processor, unsigned int *low_speed, unsigned int *high_speed, unsigned int *transition_latency, diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c index befea088e4f58b472259f955a8304e5c834e083f..04d73c114e4944d4bcceaa577c82b8f9545a9a53 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c @@ -35,7 +35,7 @@ static int smi_cmd; static unsigned int smi_sig; /* info about the processor */ -static unsigned int speedstep_processor; +static enum speedstep_processor speedstep_processor; /* * There are only two frequency states for each processor. Values diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index c900b73f92246d77cac96de3f9bd77685cf5d167..9c31e8b09d2c2676c29f87a68442e56878d6bece 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -270,8 +270,6 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) node = cpu_to_node(cpu); } numa_set_node(cpu, node); - - printk(KERN_INFO "CPU %d/0x%x -> Node %d\n", cpu, apicid, node); #endif } diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 6c40f6b5b340b031192232bdc946d62c7076d0cc..fc6c8ef92dcc5f0bd9c846b2597f0463e50209af 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -499,26 +499,27 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) #ifdef CONFIG_SYSFS /* pointer to _cpuid4_info array (for each cache leaf) */ -static DEFINE_PER_CPU(struct _cpuid4_info *, cpuid4_info); -#define CPUID4_INFO_IDX(x, y) (&((per_cpu(cpuid4_info, x))[y])) +static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info); +#define CPUID4_INFO_IDX(x, y) (&((per_cpu(ici_cpuid4_info, x))[y])) #ifdef CONFIG_SMP static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) { struct _cpuid4_info *this_leaf, *sibling_leaf; unsigned long num_threads_sharing; - int index_msb, i; + int index_msb, i, sibling; struct cpuinfo_x86 *c = &cpu_data(cpu); if ((index == 3) && (c->x86_vendor == X86_VENDOR_AMD)) { - struct cpuinfo_x86 *d; - for_each_online_cpu(i) { - if (!per_cpu(cpuid4_info, i)) + for_each_cpu(i, c->llc_shared_map) { + if (!per_cpu(ici_cpuid4_info, i)) continue; - d = &cpu_data(i); this_leaf = CPUID4_INFO_IDX(i, index); - cpumask_copy(to_cpumask(this_leaf->shared_cpu_map), - d->llc_shared_map); + for_each_cpu(sibling, c->llc_shared_map) { + if (!cpu_online(sibling)) + continue; + set_bit(sibling, this_leaf->shared_cpu_map); + } } return; } @@ -535,7 +536,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) c->apicid >> index_msb) { cpumask_set_cpu(i, to_cpumask(this_leaf->shared_cpu_map)); - if (i != cpu && per_cpu(cpuid4_info, i)) { + if (i != cpu && per_cpu(ici_cpuid4_info, i)) { sibling_leaf = CPUID4_INFO_IDX(i, index); cpumask_set_cpu(cpu, to_cpumask( @@ -574,8 +575,8 @@ static void __cpuinit free_cache_attributes(unsigned int cpu) for (i = 0; i < num_cache_leaves; i++) cache_remove_shared_cpu_map(cpu, i); - kfree(per_cpu(cpuid4_info, cpu)); - per_cpu(cpuid4_info, cpu) = NULL; + kfree(per_cpu(ici_cpuid4_info, cpu)); + per_cpu(ici_cpuid4_info, cpu) = NULL; } static int @@ -614,15 +615,15 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu) if (num_cache_leaves == 0) return -ENOENT; - per_cpu(cpuid4_info, cpu) = kzalloc( + per_cpu(ici_cpuid4_info, cpu) = kzalloc( sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL); - if (per_cpu(cpuid4_info, cpu) == NULL) + if (per_cpu(ici_cpuid4_info, cpu) == NULL) return -ENOMEM; smp_call_function_single(cpu, get_cpu_leaves, &retval, true); if (retval) { - kfree(per_cpu(cpuid4_info, cpu)); - per_cpu(cpuid4_info, cpu) = NULL; + kfree(per_cpu(ici_cpuid4_info, cpu)); + per_cpu(ici_cpuid4_info, cpu) = NULL; } return retval; @@ -634,7 +635,7 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu) extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */ /* pointer to kobject for cpuX/cache */ -static DEFINE_PER_CPU(struct kobject *, cache_kobject); +static DEFINE_PER_CPU(struct kobject *, ici_cache_kobject); struct _index_kobject { struct kobject kobj; @@ -643,8 +644,8 @@ struct _index_kobject { }; /* pointer to array of kobjects for cpuX/cache/indexY */ -static DEFINE_PER_CPU(struct _index_kobject *, index_kobject); -#define INDEX_KOBJECT_PTR(x, y) (&((per_cpu(index_kobject, x))[y])) +static DEFINE_PER_CPU(struct _index_kobject *, ici_index_kobject); +#define INDEX_KOBJECT_PTR(x, y) (&((per_cpu(ici_index_kobject, x))[y])) #define show_one_plus(file_name, object, val) \ static ssize_t show_##file_name \ @@ -863,10 +864,10 @@ static struct kobj_type ktype_percpu_entry = { static void __cpuinit cpuid4_cache_sysfs_exit(unsigned int cpu) { - kfree(per_cpu(cache_kobject, cpu)); - kfree(per_cpu(index_kobject, cpu)); - per_cpu(cache_kobject, cpu) = NULL; - per_cpu(index_kobject, cpu) = NULL; + kfree(per_cpu(ici_cache_kobject, cpu)); + kfree(per_cpu(ici_index_kobject, cpu)); + per_cpu(ici_cache_kobject, cpu) = NULL; + per_cpu(ici_index_kobject, cpu) = NULL; free_cache_attributes(cpu); } @@ -882,14 +883,14 @@ static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu) return err; /* Allocate all required memory */ - per_cpu(cache_kobject, cpu) = + per_cpu(ici_cache_kobject, cpu) = kzalloc(sizeof(struct kobject), GFP_KERNEL); - if (unlikely(per_cpu(cache_kobject, cpu) == NULL)) + if (unlikely(per_cpu(ici_cache_kobject, cpu) == NULL)) goto err_out; - per_cpu(index_kobject, cpu) = kzalloc( + per_cpu(ici_index_kobject, cpu) = kzalloc( sizeof(struct _index_kobject) * num_cache_leaves, GFP_KERNEL); - if (unlikely(per_cpu(index_kobject, cpu) == NULL)) + if (unlikely(per_cpu(ici_index_kobject, cpu) == NULL)) goto err_out; return 0; @@ -913,7 +914,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) if (unlikely(retval < 0)) return retval; - retval = kobject_init_and_add(per_cpu(cache_kobject, cpu), + retval = kobject_init_and_add(per_cpu(ici_cache_kobject, cpu), &ktype_percpu_entry, &sys_dev->kobj, "%s", "cache"); if (retval < 0) { @@ -927,12 +928,12 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) this_object->index = i; retval = kobject_init_and_add(&(this_object->kobj), &ktype_cache, - per_cpu(cache_kobject, cpu), + per_cpu(ici_cache_kobject, cpu), "index%1lu", i); if (unlikely(retval)) { for (j = 0; j < i; j++) kobject_put(&(INDEX_KOBJECT_PTR(cpu, j)->kobj)); - kobject_put(per_cpu(cache_kobject, cpu)); + kobject_put(per_cpu(ici_cache_kobject, cpu)); cpuid4_cache_sysfs_exit(cpu); return retval; } @@ -940,7 +941,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) } cpumask_set_cpu(cpu, to_cpumask(cache_dev_map)); - kobject_uevent(per_cpu(cache_kobject, cpu), KOBJ_ADD); + kobject_uevent(per_cpu(ici_cache_kobject, cpu), KOBJ_ADD); return 0; } @@ -949,7 +950,7 @@ static void __cpuinit cache_remove_dev(struct sys_device * sys_dev) unsigned int cpu = sys_dev->id; unsigned long i; - if (per_cpu(cpuid4_info, cpu) == NULL) + if (per_cpu(ici_cpuid4_info, cpu) == NULL) return; if (!cpumask_test_cpu(cpu, to_cpumask(cache_dev_map))) return; @@ -957,7 +958,7 @@ static void __cpuinit cache_remove_dev(struct sys_device * sys_dev) for (i = 0; i < num_cache_leaves; i++) kobject_put(&(INDEX_KOBJECT_PTR(cpu, i)->kobj)); - kobject_put(per_cpu(cache_kobject, cpu)); + kobject_put(per_cpu(ici_cache_kobject, cpu)); cpuid4_cache_sysfs_exit(cpu); } diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index d7ebf25d10ed2570ae72f06a7365b14399e9e677..a8aacd4b513c4ac1c8eaeb712806b3fcc208eaee 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1388,13 +1388,14 @@ static void __mcheck_cpu_init_timer(void) struct timer_list *t = &__get_cpu_var(mce_timer); int *n = &__get_cpu_var(mce_next_interval); + setup_timer(t, mce_start_timer, smp_processor_id()); + if (mce_ignore_ce) return; *n = check_interval * HZ; if (!*n) return; - setup_timer(t, mce_start_timer, smp_processor_id()); t->expires = round_jiffies(jiffies + *n); add_timer_on(t, smp_processor_id()); } @@ -1928,7 +1929,7 @@ error2: sysdev_remove_file(&per_cpu(mce_dev, cpu), &mce_banks[j].attr); error: while (--i >= 0) - sysdev_remove_file(&per_cpu(mce_dev, cpu), &mce_banks[i].attr); + sysdev_remove_file(&per_cpu(mce_dev, cpu), mce_attrs[i]); sysdev_unregister(&per_cpu(mce_dev, cpu)); diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 4fef985fc221622623473c25e9abadda053095c9..81c499eceb21d88f62499a86cb9b0034d8519858 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -256,6 +256,16 @@ asmlinkage void smp_thermal_interrupt(struct pt_regs *regs) ack_APIC_irq(); } +/* Thermal monitoring depends on APIC, ACPI and clock modulation */ +static int intel_thermal_supported(struct cpuinfo_x86 *c) +{ + if (!cpu_has_apic) + return 0; + if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC)) + return 0; + return 1; +} + void __init mcheck_intel_therm_init(void) { /* @@ -263,8 +273,7 @@ void __init mcheck_intel_therm_init(void) * LVT value on BSP and use that value to restore APs' thermal LVT * entry BIOS programmed later */ - if (cpu_has(&boot_cpu_data, X86_FEATURE_ACPI) && - cpu_has(&boot_cpu_data, X86_FEATURE_ACC)) + if (intel_thermal_supported(&boot_cpu_data)) lvtthmr_init = apic_read(APIC_LVTTHMR); } @@ -274,8 +283,7 @@ void intel_init_thermal(struct cpuinfo_x86 *c) int tm2 = 0; u32 l, h; - /* Thermal monitoring depends on ACPI and clock modulation*/ - if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC)) + if (!intel_thermal_supported(c)) return; /* @@ -339,8 +347,8 @@ void intel_init_thermal(struct cpuinfo_x86 *c) l = apic_read(APIC_LVTTHMR); apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); - printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n", - cpu, tm2 ? "TM2" : "TM1"); + printk_once(KERN_INFO "CPU0: Thermal monitoring enabled (%s)\n", + tm2 ? "TM2" : "TM1"); /* enable thermal throttle processing */ atomic_set(&therm_throt_en, 1); diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index ab1a8a89b984ef0e9c7ea31ff791ef272fa8103f..45506d5dd8df7e06f0e35ae8c0db18927ffc00e6 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1632,6 +1632,7 @@ static void intel_pmu_drain_bts_buffer(struct cpu_hw_events *cpuc) data.period = event->hw.last_period; data.addr = 0; + data.raw = NULL; regs.ip = 0; /* @@ -1749,6 +1750,7 @@ static int p6_pmu_handle_irq(struct pt_regs *regs) u64 val; data.addr = 0; + data.raw = NULL; cpuc = &__get_cpu_var(cpu_hw_events); @@ -1794,6 +1796,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) u64 ack, status; data.addr = 0; + data.raw = NULL; cpuc = &__get_cpu_var(cpu_hw_events); @@ -1857,6 +1860,7 @@ static int amd_pmu_handle_irq(struct pt_regs *regs) u64 val; data.addr = 0; + data.raw = NULL; cpuc = &__get_cpu_var(cpu_hw_events); @@ -2062,12 +2066,6 @@ static __init int p6_pmu_init(void) x86_pmu = p6_pmu; - if (!cpu_has_apic) { - pr_info("no APIC, boot with the \"lapic\" boot parameter to force-enable it.\n"); - pr_info("no hardware sampling interrupt available.\n"); - x86_pmu.apic = 0; - } - return 0; } @@ -2159,6 +2157,16 @@ static __init int amd_pmu_init(void) return 0; } +static void __init pmu_check_apic(void) +{ + if (cpu_has_apic) + return; + + x86_pmu.apic = 0; + pr_info("no APIC, boot with the \"lapic\" boot parameter to force-enable it.\n"); + pr_info("no hardware sampling interrupt available.\n"); +} + void __init init_hw_perf_events(void) { int err; @@ -2180,6 +2188,8 @@ void __init init_hw_perf_events(void) return; } + pmu_check_apic(); + pr_cont("%s PMU driver.\n", x86_pmu.name); if (x86_pmu.num_events > X86_PMC_MAX_GENERIC) { @@ -2287,7 +2297,7 @@ void callchain_store(struct perf_callchain_entry *entry, u64 ip) static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry); static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_nmi_entry); -static DEFINE_PER_CPU(int, in_nmi_frame); +static DEFINE_PER_CPU(int, in_ignored_frame); static void @@ -2303,8 +2313,9 @@ static void backtrace_warning(void *data, char *msg) static int backtrace_stack(void *data, char *name) { - per_cpu(in_nmi_frame, smp_processor_id()) = - x86_is_stack_id(NMI_STACK, name); + per_cpu(in_ignored_frame, smp_processor_id()) = + x86_is_stack_id(NMI_STACK, name) || + x86_is_stack_id(DEBUG_STACK, name); return 0; } @@ -2313,7 +2324,7 @@ static void backtrace_address(void *data, unsigned long addr, int reliable) { struct perf_callchain_entry *entry = data; - if (per_cpu(in_nmi_frame, smp_processor_id())) + if (per_cpu(in_ignored_frame, smp_processor_id())) return; if (reliable) diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index ef42a038f1a640ed43231e9a3bad1c6e741eff29..1c47390dd0e51ef7ccbd4698302a2b19bcf7ee20 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c @@ -265,13 +265,13 @@ struct ds_context { int cpu; }; -static DEFINE_PER_CPU(struct ds_context *, cpu_context); +static DEFINE_PER_CPU(struct ds_context *, cpu_ds_context); static struct ds_context *ds_get_context(struct task_struct *task, int cpu) { struct ds_context **p_context = - (task ? &task->thread.ds_ctx : &per_cpu(cpu_context, cpu)); + (task ? &task->thread.ds_ctx : &per_cpu(cpu_ds_context, cpu)); struct ds_context *context = NULL; struct ds_context *new_context = NULL; diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 8e740934bd1f56307b1cc8b7c318bdaeeda5b9d5..b13af53883aabe04504b402739a280bacf087424 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -103,6 +103,35 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, return NULL; } +static inline int +in_irq_stack(unsigned long *stack, unsigned long *irq_stack, + unsigned long *irq_stack_end) +{ + return (stack >= irq_stack && stack < irq_stack_end); +} + +/* + * We are returning from the irq stack and go to the previous one. + * If the previous stack is also in the irq stack, then bp in the first + * frame of the irq stack points to the previous, interrupted one. + * Otherwise we have another level of indirection: We first save + * the bp of the previous stack, then we switch the stack to the irq one + * and save a new bp that links to the previous one. + * (See save_args()) + */ +static inline unsigned long +fixup_bp_irq_link(unsigned long bp, unsigned long *stack, + unsigned long *irq_stack, unsigned long *irq_stack_end) +{ +#ifdef CONFIG_FRAME_POINTER + struct stack_frame *frame = (struct stack_frame *)bp; + + if (!in_irq_stack(stack, irq_stack, irq_stack_end)) + return (unsigned long)frame->next_frame; +#endif + return bp; +} + /* * x86-64 can have up to three kernel stacks: * process stack @@ -175,7 +204,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, irq_stack = irq_stack_end - (IRQ_STACK_SIZE - 64) / sizeof(*irq_stack); - if (stack >= irq_stack && stack < irq_stack_end) { + if (in_irq_stack(stack, irq_stack, irq_stack_end)) { if (ops->stack(data, "IRQ") < 0) break; bp = print_context_stack(tinfo, stack, bp, @@ -186,6 +215,8 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, * pointer (index -1 to end) in the IRQ stack: */ stack = (unsigned long *) (irq_stack_end[-1]); + bp = fixup_bp_irq_link(bp, stack, irq_stack, + irq_stack_end); irq_stack_end = NULL; ops->stack(data, "EOI"); continue; diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index d17d482a04f4c84edd4e87229372b52621e5d1c8..f50447d961c0fc1b1ff3a8e7e7283663863c558f 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -732,7 +732,16 @@ struct early_res { char overlap_ok; }; static struct early_res early_res[MAX_EARLY_RES] __initdata = { - { 0, PAGE_SIZE, "BIOS data page" }, /* BIOS data page */ + { 0, PAGE_SIZE, "BIOS data page", 1 }, /* BIOS data page */ +#ifdef CONFIG_X86_32 + /* + * But first pinch a few for the stack/trampoline stuff + * FIXME: Don't need the extra page at 4K, but need to fix + * trampoline before removing it. (see the GDT stuff) + */ + { PAGE_SIZE, PAGE_SIZE, "EX TRAMPOLINE", 1 }, +#endif + {} }; diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 63bca794c8f99c0f95aeecf858cacf288ad2d44a..673f693fb45131aec07012fb71233b5459e3788f 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1076,10 +1076,10 @@ ENTRY(\sym) TRACE_IRQS_OFF movq %rsp,%rdi /* pt_regs pointer */ xorl %esi,%esi /* no error code */ - PER_CPU(init_tss, %rbp) - subq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%rbp) + PER_CPU(init_tss, %r12) + subq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%r12) call \do_sym - addq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%rbp) + addq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%r12) jmp paranoid_exit /* %ebx: no swapgs flag */ CFI_ENDPROC END(\sym) diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index 4f8e2507e8f3cad33a71d5fdb98f068d977c6aae..5051b94c906986b80bc0c4ff62394fd5d2f3a962 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c @@ -29,8 +29,6 @@ static void __init i386_default_early_setup(void) void __init i386_start_kernel(void) { - reserve_trampoline_memory(); - reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS"); #ifdef CONFIG_BLK_DEV_INITRD diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 0b06cd778fd9c73884f8c1cffc5a359ec4f9c425..b5a9896ca1e74be8805c4f5384ffc8d50f6589b6 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -98,8 +98,6 @@ void __init x86_64_start_reservations(char *real_mode_data) { copy_bootdata(__va(real_mode_data)); - reserve_trampoline_memory(); - reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS"); #ifdef CONFIG_BLK_DEV_INITRD diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c index d42f65ac492766ecaeb60944b4ae573f5bf6f0bf..05d5fec64a9475855e224012dbb54a9d82b1ee4c 100644 --- a/arch/x86/kernel/hw_breakpoint.c +++ b/arch/x86/kernel/hw_breakpoint.c @@ -362,8 +362,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp, return ret; } - if (bp->callback) - ret = arch_store_info(bp); + ret = arch_store_info(bp); if (ret < 0) return ret; @@ -519,7 +518,7 @@ static int __kprobes hw_breakpoint_handler(struct die_args *args) break; } - (bp->callback)(bp, args->regs); + perf_bp_event(bp, args->regs); rcu_read_unlock(); } diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 20a5b3689463c6df5d26b98fcfcb2f43fca5b851..dd74fe7273b120643bf2f4a7563295afde009233 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -86,9 +86,15 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) gdb_regs[GDB_DS] = regs->ds; gdb_regs[GDB_ES] = regs->es; gdb_regs[GDB_CS] = regs->cs; - gdb_regs[GDB_SS] = __KERNEL_DS; gdb_regs[GDB_FS] = 0xFFFF; gdb_regs[GDB_GS] = 0xFFFF; + if (user_mode_vm(regs)) { + gdb_regs[GDB_SS] = regs->ss; + gdb_regs[GDB_SP] = regs->sp; + } else { + gdb_regs[GDB_SS] = __KERNEL_DS; + gdb_regs[GDB_SP] = kernel_stack_pointer(regs); + } #else gdb_regs[GDB_R8] = regs->r8; gdb_regs[GDB_R9] = regs->r9; @@ -101,8 +107,8 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) gdb_regs32[GDB_PS] = regs->flags; gdb_regs32[GDB_CS] = regs->cs; gdb_regs32[GDB_SS] = regs->ss; -#endif gdb_regs[GDB_SP] = kernel_stack_pointer(regs); +#endif } /** @@ -220,8 +226,7 @@ static void kgdb_correct_hw_break(void) dr7 |= ((breakinfo[breakno].len << 2) | breakinfo[breakno].type) << ((breakno << 2) + 16); - if (breakno >= 0 && breakno <= 3) - set_debugreg(breakinfo[breakno].addr, breakno); + set_debugreg(breakinfo[breakno].addr, breakno); } else { if ((dr7 & breakbit) && !breakinfo[breakno].enabled) { @@ -395,7 +400,6 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, /* set the trace bit if we're stepping */ if (remcomInBuffer[0] == 's') { linux_regs->flags |= X86_EFLAGS_TF; - kgdb_single_step = 1; atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id()); } diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 63123d902103e2ca88f0de3e00319d6f25021b71..37542b67c57e4299738d609c3e44206be251304e 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -13,6 +13,9 @@ * Licensed under the terms of the GNU General Public * License version 2. See file COPYING for details. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -81,7 +84,7 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) memset(csig, 0, sizeof(*csig)); rdmsr(MSR_AMD64_PATCH_LEVEL, csig->rev, dummy); - pr_info("microcode: CPU%d: patch_level=0x%x\n", cpu, csig->rev); + pr_info("CPU%d: patch_level=0x%x\n", cpu, csig->rev); return 0; } @@ -111,8 +114,8 @@ static int get_matching_microcode(int cpu, void *mc, int rev) /* ucode might be chipset specific -- currently we don't support this */ if (mc_header->nb_dev_id || mc_header->sb_dev_id) { - pr_err(KERN_ERR "microcode: CPU%d: loading of chipset " - "specific code not yet supported\n", cpu); + pr_err("CPU%d: loading of chipset specific code not yet supported\n", + cpu); return 0; } @@ -141,12 +144,12 @@ static int apply_microcode_amd(int cpu) /* check current patch id and patch's id for match */ if (rev != mc_amd->hdr.patch_id) { - pr_err("microcode: CPU%d: update failed " - "(for patch_level=0x%x)\n", cpu, mc_amd->hdr.patch_id); + pr_err("CPU%d: update failed (for patch_level=0x%x)\n", + cpu, mc_amd->hdr.patch_id); return -1; } - pr_info("microcode: CPU%d: updated (new patch_level=0x%x)\n", cpu, rev); + pr_info("CPU%d: updated (new patch_level=0x%x)\n", cpu, rev); uci->cpu_sig.rev = rev; return 0; @@ -169,15 +172,14 @@ get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size) return NULL; if (section_hdr[0] != UCODE_UCODE_TYPE) { - pr_err("microcode: error: invalid type field in " - "container file section header\n"); + pr_err("error: invalid type field in container file section header\n"); return NULL; } total_size = (unsigned long) (section_hdr[4] + (section_hdr[5] << 8)); if (total_size > size || total_size > UCODE_MAX_SIZE) { - pr_err("microcode: error: size mismatch\n"); + pr_err("error: size mismatch\n"); return NULL; } @@ -206,14 +208,13 @@ static int install_equiv_cpu_table(const u8 *buf) size = buf_pos[2]; if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE || !size) { - pr_err("microcode: error: invalid type field in " - "container file section header\n"); + pr_err("error: invalid type field in container file section header\n"); return 0; } equiv_cpu_table = (struct equiv_cpu_entry *) vmalloc(size); if (!equiv_cpu_table) { - pr_err("microcode: failed to allocate equivalent CPU table\n"); + pr_err("failed to allocate equivalent CPU table\n"); return 0; } @@ -246,7 +247,7 @@ generic_load_microcode(int cpu, const u8 *data, size_t size) offset = install_equiv_cpu_table(ucode_ptr); if (!offset) { - pr_err("microcode: failed to create equivalent cpu table\n"); + pr_err("failed to create equivalent cpu table\n"); return UCODE_ERROR; } @@ -277,8 +278,7 @@ generic_load_microcode(int cpu, const u8 *data, size_t size) if (!leftover) { vfree(uci->mc); uci->mc = new_mc; - pr_debug("microcode: CPU%d found a matching microcode " - "update with version 0x%x (current=0x%x)\n", + pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n", cpu, new_rev, uci->cpu_sig.rev); } else { vfree(new_mc); @@ -300,7 +300,7 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device) return UCODE_NFOUND; if (*(u32 *)firmware->data != UCODE_MAGIC) { - pr_err("microcode: invalid UCODE_MAGIC (0x%08x)\n", + pr_err("invalid UCODE_MAGIC (0x%08x)\n", *(u32 *)firmware->data); return UCODE_ERROR; } @@ -313,8 +313,7 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device) static enum ucode_state request_microcode_user(int cpu, const void __user *buf, size_t size) { - pr_info("microcode: AMD microcode update via " - "/dev/cpu/microcode not supported\n"); + pr_info("AMD microcode update via /dev/cpu/microcode not supported\n"); return UCODE_ERROR; } @@ -334,14 +333,13 @@ void init_microcode_amd(struct device *device) WARN_ON(c->x86_vendor != X86_VENDOR_AMD); if (c->x86 < 0x10) { - pr_warning("microcode: AMD CPU family 0x%x not supported\n", - c->x86); + pr_warning("AMD CPU family 0x%x not supported\n", c->x86); return; } supported_cpu = 1; if (request_firmware(&firmware, fw_name, device)) - pr_err("microcode: failed to load file %s\n", fw_name); + pr_err("failed to load file %s\n", fw_name); } void fini_microcode_amd(void) diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index e68aae3978694ec5b83bf45058691a00b8a95da4..844c02c65fcb158addce87804737e63a1bd82ae2 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -70,6 +70,9 @@ * Fix sigmatch() macro to handle old CPUs with pf == 0. * Thanks to Stuart Swales for pointing out this bug. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -209,7 +212,7 @@ static ssize_t microcode_write(struct file *file, const char __user *buf, ssize_t ret = -EINVAL; if ((len >> PAGE_SHIFT) > totalram_pages) { - pr_err("microcode: too much data (max %ld pages)\n", totalram_pages); + pr_err("too much data (max %ld pages)\n", totalram_pages); return ret; } @@ -244,7 +247,7 @@ static int __init microcode_dev_init(void) error = misc_register(µcode_dev); if (error) { - pr_err("microcode: can't misc_register on minor=%d\n", MICROCODE_MINOR); + pr_err("can't misc_register on minor=%d\n", MICROCODE_MINOR); return error; } @@ -359,7 +362,7 @@ static enum ucode_state microcode_resume_cpu(int cpu) if (!uci->mc) return UCODE_NFOUND; - pr_debug("microcode: CPU%d updated upon resume\n", cpu); + pr_debug("CPU%d updated upon resume\n", cpu); apply_microcode_on_target(cpu); return UCODE_OK; @@ -379,7 +382,7 @@ static enum ucode_state microcode_init_cpu(int cpu) ustate = microcode_ops->request_microcode_fw(cpu, µcode_pdev->dev); if (ustate == UCODE_OK) { - pr_debug("microcode: CPU%d updated upon init\n", cpu); + pr_debug("CPU%d updated upon init\n", cpu); apply_microcode_on_target(cpu); } @@ -406,7 +409,7 @@ static int mc_sysdev_add(struct sys_device *sys_dev) if (!cpu_online(cpu)) return 0; - pr_debug("microcode: CPU%d added\n", cpu); + pr_debug("CPU%d added\n", cpu); err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); if (err) @@ -425,7 +428,7 @@ static int mc_sysdev_remove(struct sys_device *sys_dev) if (!cpu_online(cpu)) return 0; - pr_debug("microcode: CPU%d removed\n", cpu); + pr_debug("CPU%d removed\n", cpu); microcode_fini_cpu(cpu); sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); return 0; @@ -473,15 +476,15 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) microcode_update_cpu(cpu); case CPU_DOWN_FAILED: case CPU_DOWN_FAILED_FROZEN: - pr_debug("microcode: CPU%d added\n", cpu); + pr_debug("CPU%d added\n", cpu); if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) - pr_err("microcode: Failed to create group for CPU%d\n", cpu); + pr_err("Failed to create group for CPU%d\n", cpu); break; case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE_FROZEN: /* Suspend is in progress, only remove the interface */ sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); - pr_debug("microcode: CPU%d removed\n", cpu); + pr_debug("CPU%d removed\n", cpu); break; case CPU_DEAD: case CPU_UP_CANCELED_FROZEN: @@ -507,7 +510,7 @@ static int __init microcode_init(void) microcode_ops = init_amd_microcode(); if (!microcode_ops) { - pr_err("microcode: no support for this CPU vendor\n"); + pr_err("no support for this CPU vendor\n"); return -ENODEV; } @@ -541,8 +544,7 @@ static int __init microcode_init(void) register_hotcpu_notifier(&mc_cpu_notifier); pr_info("Microcode Update Driver: v" MICROCODE_VERSION - " ," - " Peter Oruba\n"); + " , Peter Oruba\n"); return 0; } diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 0d334ddd0a9642a2c05485e9e31394f8b1e98a3b..ebd193e476ca8812fa81a06e0def726d486d6239 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -70,6 +70,9 @@ * Fix sigmatch() macro to handle old CPUs with pf == 0. * Thanks to Stuart Swales for pointing out this bug. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -146,8 +149,7 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || cpu_has(c, X86_FEATURE_IA64)) { - printk(KERN_ERR "microcode: CPU%d not a capable Intel " - "processor\n", cpu_num); + pr_err("CPU%d not a capable Intel processor\n", cpu_num); return -1; } @@ -165,8 +167,8 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) /* get the current revision from MSR 0x8B */ rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev); - printk(KERN_INFO "microcode: CPU%d sig=0x%x, pf=0x%x, revision=0x%x\n", - cpu_num, csig->sig, csig->pf, csig->rev); + pr_info("CPU%d sig=0x%x, pf=0x%x, revision=0x%x\n", + cpu_num, csig->sig, csig->pf, csig->rev); return 0; } @@ -194,28 +196,24 @@ static int microcode_sanity_check(void *mc) data_size = get_datasize(mc_header); if (data_size + MC_HEADER_SIZE > total_size) { - printk(KERN_ERR "microcode: error! " - "Bad data size in microcode data file\n"); + pr_err("error! Bad data size in microcode data file\n"); return -EINVAL; } if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { - printk(KERN_ERR "microcode: error! " - "Unknown microcode update format\n"); + pr_err("error! Unknown microcode update format\n"); return -EINVAL; } ext_table_size = total_size - (MC_HEADER_SIZE + data_size); if (ext_table_size) { if ((ext_table_size < EXT_HEADER_SIZE) || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { - printk(KERN_ERR "microcode: error! " - "Small exttable size in microcode data file\n"); + pr_err("error! Small exttable size in microcode data file\n"); return -EINVAL; } ext_header = mc + MC_HEADER_SIZE + data_size; if (ext_table_size != exttable_size(ext_header)) { - printk(KERN_ERR "microcode: error! " - "Bad exttable size in microcode data file\n"); + pr_err("error! Bad exttable size in microcode data file\n"); return -EFAULT; } ext_sigcount = ext_header->count; @@ -230,8 +228,7 @@ static int microcode_sanity_check(void *mc) while (i--) ext_table_sum += ext_tablep[i]; if (ext_table_sum) { - printk(KERN_WARNING "microcode: aborting, " - "bad extended signature table checksum\n"); + pr_warning("aborting, bad extended signature table checksum\n"); return -EINVAL; } } @@ -242,7 +239,7 @@ static int microcode_sanity_check(void *mc) while (i--) orig_sum += ((int *)mc)[i]; if (orig_sum) { - printk(KERN_ERR "microcode: aborting, bad checksum\n"); + pr_err("aborting, bad checksum\n"); return -EINVAL; } if (!ext_table_size) @@ -255,7 +252,7 @@ static int microcode_sanity_check(void *mc) - (mc_header->sig + mc_header->pf + mc_header->cksum) + (ext_sig->sig + ext_sig->pf + ext_sig->cksum); if (sum) { - printk(KERN_ERR "microcode: aborting, bad checksum\n"); + pr_err("aborting, bad checksum\n"); return -EINVAL; } } @@ -327,13 +324,11 @@ static int apply_microcode(int cpu) rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); if (val[1] != mc_intel->hdr.rev) { - printk(KERN_ERR "microcode: CPU%d update " - "to revision 0x%x failed\n", - cpu_num, mc_intel->hdr.rev); + pr_err("CPU%d update to revision 0x%x failed\n", + cpu_num, mc_intel->hdr.rev); return -1; } - printk(KERN_INFO "microcode: CPU%d updated to revision " - "0x%x, date = %04x-%02x-%02x \n", + pr_info("CPU%d updated to revision 0x%x, date = %04x-%02x-%02x \n", cpu_num, val[1], mc_intel->hdr.date & 0xffff, mc_intel->hdr.date >> 24, @@ -362,8 +357,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, mc_size = get_totalsize(&mc_header); if (!mc_size || mc_size > leftover) { - printk(KERN_ERR "microcode: error!" - "Bad data in microcode data file\n"); + pr_err("error! Bad data in microcode data file\n"); break; } @@ -405,9 +399,8 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, vfree(uci->mc); uci->mc = (struct microcode_intel *)new_mc; - pr_debug("microcode: CPU%d found a matching microcode update with" - " version 0x%x (current=0x%x)\n", - cpu, new_rev, uci->cpu_sig.rev); + pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n", + cpu, new_rev, uci->cpu_sig.rev); out: return state; } @@ -429,7 +422,7 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device) c->x86, c->x86_model, c->x86_mask); if (request_firmware(&firmware, name, device)) { - pr_debug("microcode: data file %s load failed\n", name); + pr_debug("data file %s load failed\n", name); return UCODE_NFOUND; } diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 35a57c963df94ecd34cea14601edb81b5c780038..40b54ceb68b560dc61ec81b5d7222298057bb133 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -945,9 +945,6 @@ void __init early_reserve_e820_mpc_new(void) { if (enable_update_mptable && alloc_mptable) { u64 startt = 0; -#ifdef CONFIG_X86_TRAMPOLINE - startt = TRAMPOLINE_BASE; -#endif mpc_new_phys = early_reserve_e820(startt, mpc_new_length, 4); } } diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index afcc58b69c7c8579c11f08405621b85919f88663..fcc2f2bfa39ca17e608fb2c395472494f45a91eb 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -120,11 +120,14 @@ static void __init dma32_free_bootmem(void) void __init pci_iommu_alloc(void) { + int use_swiotlb; + + use_swiotlb = pci_swiotlb_init(); #ifdef CONFIG_X86_64 /* free the range so iommu could get some range less than 4G */ dma32_free_bootmem(); #endif - if (pci_swiotlb_init()) + if (use_swiotlb) return; gart_iommu_hole_init(); diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index e6a0d402f1714dec4aff2e160b0eff255ea5307b..56c0e730d3fe7bd09913d092c01f009f94f53974 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -710,7 +710,8 @@ static void gart_iommu_shutdown(void) struct pci_dev *dev; int i; - if (no_agp) + /* don't shutdown it if there is AGP installed */ + if (!no_agp) return; for (i = 0; i < num_k8_northbridges; i++) { diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 5e2ba634ea155759cec36d5581ff131ad0784a68..7a7bd4e3ec49b5f42056137f6c56165809303c98 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -90,6 +92,25 @@ void exit_thread(void) } } +void show_regs_common(void) +{ + const char *board, *product; + + board = dmi_get_system_info(DMI_BOARD_NAME); + if (!board) + board = ""; + product = dmi_get_system_info(DMI_PRODUCT_NAME); + if (!product) + product = ""; + + printk("\n"); + printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s %s/%s\n", + current->pid, current->comm, print_tainted(), + init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), + init_utsname()->version, board, product); +} + void flush_thread(void) { struct task_struct *tsk = current; diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 075580b3568283609a3a1034aefe58994bd0782f..120b88797a75af8d44bfb2b4e092b3dd055ed4a3 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -35,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -128,7 +126,6 @@ void __show_regs(struct pt_regs *regs, int all) unsigned long d0, d1, d2, d3, d6, d7; unsigned long sp; unsigned short ss, gs; - const char *board; if (user_mode_vm(regs)) { sp = regs->sp; @@ -140,16 +137,7 @@ void __show_regs(struct pt_regs *regs, int all) savesegment(gs, gs); } - printk("\n"); - - board = dmi_get_system_info(DMI_PRODUCT_NAME); - if (!board) - board = ""; - printk("Pid: %d, comm: %s %s (%s %.*s) %s\n", - task_pid_nr(current), current->comm, - print_tainted(), init_utsname()->release, - (int)strcspn(init_utsname()->version, " "), - init_utsname()->version, board); + show_regs_common(); printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n", (u16)regs->cs, regs->ip, regs->flags, diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index c95c8f4e790ad8da17241ff55226e911832e01a3..e5ab0cd0ef36e5516207fbb96974c53e5b35e9d1 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -38,7 +37,6 @@ #include #include #include -#include #include #include @@ -163,18 +161,8 @@ void __show_regs(struct pt_regs *regs, int all) unsigned long d0, d1, d2, d3, d6, d7; unsigned int fsindex, gsindex; unsigned int ds, cs, es; - const char *board; - - printk("\n"); - print_modules(); - board = dmi_get_system_info(DMI_PRODUCT_NAME); - if (!board) - board = ""; - printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s %s\n", - current->pid, current->comm, print_tainted(), - init_utsname()->release, - (int)strcspn(init_utsname()->version, " "), - init_utsname()->version, board); + + show_regs_common(); printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); printk_address(regs->ip, 1); printk(KERN_INFO "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 04d182a7cfdbd6e3c88c41658f6d0a91878e6366..7079ddaf0731e949d99940f7a036d82f3b613954 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -555,7 +555,9 @@ static int genregs_set(struct task_struct *target, return ret; } -static void ptrace_triggered(struct perf_event *bp, void *data) +static void ptrace_triggered(struct perf_event *bp, int nmi, + struct perf_sample_data *data, + struct pt_regs *regs) { int i; struct thread_struct *thread = &(current->thread); @@ -593,13 +595,13 @@ static unsigned long ptrace_get_dr7(struct perf_event *bp[]) return dr7; } -static struct perf_event * +static int ptrace_modify_breakpoint(struct perf_event *bp, int len, int type, struct task_struct *tsk, int disabled) { int err; int gen_len, gen_type; - DEFINE_BREAKPOINT_ATTR(attr); + struct perf_event_attr attr; /* * We shoud have at least an inactive breakpoint at this @@ -607,18 +609,18 @@ ptrace_modify_breakpoint(struct perf_event *bp, int len, int type, * written the address register first */ if (!bp) - return ERR_PTR(-EINVAL); + return -EINVAL; err = arch_bp_generic_fields(len, type, &gen_len, &gen_type); if (err) - return ERR_PTR(err); + return err; attr = bp->attr; attr.bp_len = gen_len; attr.bp_type = gen_type; attr.disabled = disabled; - return modify_user_hw_breakpoint(bp, &attr, bp->callback, tsk); + return modify_user_hw_breakpoint(bp, &attr); } /* @@ -656,28 +658,17 @@ restore: if (!second_pass) continue; - thread->ptrace_bps[i] = NULL; - bp = ptrace_modify_breakpoint(bp, len, type, + rc = ptrace_modify_breakpoint(bp, len, type, tsk, 1); - if (IS_ERR(bp)) { - rc = PTR_ERR(bp); - thread->ptrace_bps[i] = NULL; + if (rc) break; - } - thread->ptrace_bps[i] = bp; } continue; } - bp = ptrace_modify_breakpoint(bp, len, type, tsk, 0); - - /* Incorrect bp, or we have a bug in bp API */ - if (IS_ERR(bp)) { - rc = PTR_ERR(bp); - thread->ptrace_bps[i] = NULL; + rc = ptrace_modify_breakpoint(bp, len, type, tsk, 0); + if (rc) break; - } - thread->ptrace_bps[i] = bp; } /* * Make a second pass to free the remaining unused breakpoints @@ -721,9 +712,10 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr, { struct perf_event *bp; struct thread_struct *t = &tsk->thread; - DEFINE_BREAKPOINT_ATTR(attr); + struct perf_event_attr attr; if (!t->ptrace_bps[nr]) { + hw_breakpoint_init(&attr); /* * Put stub len and type to register (reserve) an inactive but * correct bp @@ -734,26 +726,32 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr, attr.disabled = 1; bp = register_user_hw_breakpoint(&attr, ptrace_triggered, tsk); + + /* + * CHECKME: the previous code returned -EIO if the addr wasn't + * a valid task virtual addr. The new one will return -EINVAL in + * this case. + * -EINVAL may be what we want for in-kernel breakpoints users, + * but -EIO looks better for ptrace, since we refuse a register + * writing for the user. And anyway this is the previous + * behaviour. + */ + if (IS_ERR(bp)) + return PTR_ERR(bp); + + t->ptrace_bps[nr] = bp; } else { + int err; + bp = t->ptrace_bps[nr]; - t->ptrace_bps[nr] = NULL; attr = bp->attr; attr.bp_addr = addr; - bp = modify_user_hw_breakpoint(bp, &attr, bp->callback, tsk); + err = modify_user_hw_breakpoint(bp, &attr); + if (err) + return err; } - /* - * CHECKME: the previous code returned -EIO if the addr wasn't a - * valid task virtual addr. The new one will return -EINVAL in this - * case. - * -EINVAL may be what we want for in-kernel breakpoints users, but - * -EIO looks better for ptrace, since we refuse a register writing - * for the user. And anyway this is the previous behaviour. - */ - if (IS_ERR(bp)) - return PTR_ERR(bp); - t->ptrace_bps[nr] = bp; return 0; } diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 2b97fc5b124e42b13029c6293147682a3e6d1272..1545bc0c98454ebebc070fef0cd62f89be69cb4a 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -259,6 +259,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "SBC-FITPC2"), }, }, + { /* Handle problems with rebooting on ASUS P4S800 */ + .callback = set_bios_reboot, + .ident = "ASUS P4S800", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "P4S800"), + }, + }, { } }; diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 946a311a25c9f894a152e2feba14935dfb5a1bbf..f7b8b9894b226fd8498ab5f886381f68be2541c2 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -73,6 +73,7 @@ #include #include +#include #include #include #include @@ -875,6 +876,13 @@ void __init setup_arch(char **cmdline_p) reserve_brk(); + /* + * Find and reserve possible boot-time SMP configuration: + */ + find_smp_config(); + + reserve_trampoline_memory(); + #ifdef CONFIG_ACPI_SLEEP /* * Reserve low memory region for sleep support. @@ -921,11 +929,6 @@ void __init setup_arch(char **cmdline_p) early_acpi_boot_init(); - /* - * Find and reserve possible boot-time SMP configuration: - */ - find_smp_config(); - #ifdef CONFIG_ACPI_NUMA /* * Parse SRAT to discover nodes. diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index d559af913e1f89c40de010c1a936cdeab15f9751..35abcb8b00e9fb45087ae671d7e1320db8b26a88 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -1,3 +1,5 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -20,9 +22,9 @@ #include #ifdef CONFIG_DEBUG_PER_CPU_MAPS -# define DBG(x...) printk(KERN_DEBUG x) +# define DBG(fmt, ...) pr_dbg(fmt, ##__VA_ARGS__) #else -# define DBG(x...) +# define DBG(fmt, ...) do { if (0) pr_dbg(fmt, ##__VA_ARGS__); } while (0) #endif DEFINE_PER_CPU(int, cpu_number); @@ -116,8 +118,8 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size, } else { ptr = __alloc_bootmem_node_nopanic(NODE_DATA(node), size, align, goal); - pr_debug("per cpu data for cpu%d %lu bytes on node%d at " - "%016lx\n", cpu, size, node, __pa(ptr)); + pr_debug("per cpu data for cpu%d %lu bytes on node%d at %016lx\n", + cpu, size, node, __pa(ptr)); } return ptr; #else @@ -198,8 +200,7 @@ void __init setup_per_cpu_areas(void) pcpu_cpu_distance, pcpu_fc_alloc, pcpu_fc_free); if (rc < 0) - pr_warning("PERCPU: %s allocator failed (%d), " - "falling back to page size\n", + pr_warning("%s allocator failed (%d), falling back to page size\n", pcpu_fc_names[pcpu_chosen_fc], rc); } if (rc < 0) diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 324f2a44c22127ac7592bc759bc907b4e6d6d3c7..678d0b8c26f3152c67a833f3e782cb15c9d0a61b 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -671,6 +671,26 @@ static void __cpuinit do_fork_idle(struct work_struct *work) complete(&c_idle->done); } +/* reduce the number of lines printed when booting a large cpu count system */ +static void __cpuinit announce_cpu(int cpu, int apicid) +{ + static int current_node = -1; + int node = cpu_to_node(cpu); + + if (system_state == SYSTEM_BOOTING) { + if (node != current_node) { + if (current_node > (-1)) + pr_cont(" Ok.\n"); + current_node = node; + pr_info("Booting Node %3d, Processors ", node); + } + pr_cont(" #%d%s", cpu, cpu == (nr_cpu_ids - 1) ? " Ok.\n" : ""); + return; + } else + pr_info("Booting Node %d Processor %d APIC 0x%x\n", + node, cpu, apicid); +} + /* * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad * (ie clustered apic addressing mode), this is a LOGICAL apic ID. @@ -687,7 +707,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), }; - INIT_WORK(&c_idle.work, do_fork_idle); + INIT_WORK_ON_STACK(&c_idle.work, do_fork_idle); alternatives_smp_switch(1); @@ -713,6 +733,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) if (IS_ERR(c_idle.idle)) { printk("failed fork for CPU %d\n", cpu); + destroy_work_on_stack(&c_idle.work); return PTR_ERR(c_idle.idle); } @@ -736,9 +757,8 @@ do_rest: /* start_ip had better be page-aligned! */ start_ip = setup_trampoline(); - /* So we see what's up */ - printk(KERN_INFO "Booting processor %d APIC 0x%x ip 0x%lx\n", - cpu, apicid, start_ip); + /* So we see what's up */ + announce_cpu(cpu, apicid); /* * This grunge runs the startup process for @@ -787,21 +807,17 @@ do_rest: udelay(100); } - if (cpumask_test_cpu(cpu, cpu_callin_mask)) { - /* number CPUs logically, starting from 1 (BSP is 0) */ - pr_debug("OK.\n"); - printk(KERN_INFO "CPU%d: ", cpu); - print_cpu_info(&cpu_data(cpu)); - pr_debug("CPU has booted.\n"); - } else { + if (cpumask_test_cpu(cpu, cpu_callin_mask)) + pr_debug("CPU%d: has booted.\n", cpu); + else { boot_error = 1; if (*((volatile unsigned char *)trampoline_base) == 0xA5) /* trampoline started but...? */ - printk(KERN_ERR "Stuck ??\n"); + pr_err("CPU%d: Stuck ??\n", cpu); else /* trampoline code not run */ - printk(KERN_ERR "Not responding.\n"); + pr_err("CPU%d: Not responding.\n", cpu); if (apic->inquire_remote_apic) apic->inquire_remote_apic(apicid); } @@ -831,6 +847,7 @@ do_rest: smpboot_restore_warm_reset_vector(); } + destroy_work_on_stack(&c_idle.work); return boot_error; } @@ -1291,14 +1308,16 @@ void native_cpu_die(unsigned int cpu) for (i = 0; i < 10; i++) { /* They ack this in play_dead by setting CPU_DEAD */ if (per_cpu(cpu_state, cpu) == CPU_DEAD) { - printk(KERN_INFO "CPU %d is now offline\n", cpu); + if (system_state == SYSTEM_RUNNING) + pr_info("CPU %u is now offline\n", cpu); + if (1 == num_online_cpus()) alternatives_smp_switch(0); return; } msleep(100); } - printk(KERN_ERR "CPU %u didn't die...\n", cpu); + pr_err("CPU %u didn't die...\n", cpu); } void play_dead_common(void) diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c index 1884a8d12bfaf130d99d7f9602268c5a7048271d..dee1ff7cba581829b6540b436dbbff4b5958ff4f 100644 --- a/arch/x86/kernel/sys_i386_32.c +++ b/arch/x86/kernel/sys_i386_32.c @@ -24,31 +24,6 @@ #include -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file *file = NULL; - struct mm_struct *mm = current->mm; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(&mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(&mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - /* * Perform the select(nd, in, out, ex, tv) and mmap() system * calls. Linux/i386 didn't use to be able to handle more than @@ -77,7 +52,7 @@ asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) if (a.offset & ~PAGE_MASK) goto out; - err = sys_mmap2(a.addr, a.len, a.prot, a.flags, + err = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); out: return err; diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 45e00eb09c3a7037692656cee85fe8d8c2e396fe..8aa2057efd12618aa20874b8a71fc40527cc6819 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c @@ -23,26 +23,11 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, unsigned long, fd, unsigned long, off) { long error; - struct file *file; - error = -EINVAL; if (off & ~PAGE_MASK) goto out; - error = -EBADF; - file = NULL; - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, off >> PAGE_SHIFT); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); + error = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); out: return error; } diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S index 70c2125d55b97c5a4e0bd9b25ae6f2cfe9374e14..15228b5d3eb7bf6c75954095f1c73677bc096ca7 100644 --- a/arch/x86/kernel/syscall_table_32.S +++ b/arch/x86/kernel/syscall_table_32.S @@ -191,7 +191,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* reserved for streams2 */ .long ptregs_vfork /* 190 */ .long sys_getrlimit - .long sys_mmap2 + .long sys_mmap_pgoff .long sys_truncate64 .long sys_ftruncate64 .long sys_stat64 /* 195 */ diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c index cd022121cab611629ec9b04de51677e44bef3567..c652ef62742df62340d03465231e88885c8d5329 100644 --- a/arch/x86/kernel/trampoline.c +++ b/arch/x86/kernel/trampoline.c @@ -12,21 +12,19 @@ #endif /* ready for x86_64 and x86 */ -unsigned char *__trampinitdata trampoline_base = __va(TRAMPOLINE_BASE); +unsigned char *__trampinitdata trampoline_base; void __init reserve_trampoline_memory(void) { -#ifdef CONFIG_X86_32 - /* - * But first pinch a few for the stack/trampoline stuff - * FIXME: Don't need the extra page at 4K, but need to fix - * trampoline before removing it. (see the GDT stuff) - */ - reserve_early(PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE"); -#endif + unsigned long mem; + /* Has to be in very low memory so we can execute real-mode AP code. */ - reserve_early(TRAMPOLINE_BASE, TRAMPOLINE_BASE + TRAMPOLINE_SIZE, - "TRAMPOLINE"); + mem = find_e820_area(0, 1<<20, TRAMPOLINE_SIZE, PAGE_SIZE); + if (mem == -1L) + panic("Cannot allocate trampoline\n"); + + trampoline_base = __va(mem); + reserve_early(mem, mem + TRAMPOLINE_SIZE, "TRAMPOLINE"); } /* diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index fab7440c9bb2c84fc4b83d2e8346e6b82afce211..296aba49472ae3cdcf7580bc79d60d83ed48ce3e 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c @@ -29,6 +29,8 @@ * Based on QEMU and Xen. */ +#define pr_fmt(fmt) "pit: " fmt + #include #include "irq.h" @@ -262,7 +264,7 @@ void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu) static void destroy_pit_timer(struct kvm_timer *pt) { - pr_debug("pit: execute del timer!\n"); + pr_debug("execute del timer!\n"); hrtimer_cancel(&pt->timer); } @@ -284,7 +286,7 @@ static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period) interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ); - pr_debug("pit: create pit timer, interval is %llu nsec\n", interval); + pr_debug("create pit timer, interval is %llu nsec\n", interval); /* TODO The new value only affected after the retriggered */ hrtimer_cancel(&pt->timer); @@ -309,7 +311,7 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val) WARN_ON(!mutex_is_locked(&ps->lock)); - pr_debug("pit: load_count val is %d, channel is %d\n", val, channel); + pr_debug("load_count val is %d, channel is %d\n", val, channel); /* * The largest possible initial count is 0; this is equivalent @@ -395,8 +397,8 @@ static int pit_ioport_write(struct kvm_io_device *this, mutex_lock(&pit_state->lock); if (val != 0) - pr_debug("pit: write addr is 0x%x, len is %d, val is 0x%x\n", - (unsigned int)addr, len, val); + pr_debug("write addr is 0x%x, len is %d, val is 0x%x\n", + (unsigned int)addr, len, val); if (addr == 3) { channel = val >> 6; diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 3de0b37ec038673c3a70b4f14be7dcd5656dfcfe..1d9b33843c80ef521dc059697285cfed06cfd7d7 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -316,7 +316,7 @@ static void svm_hardware_disable(void *garbage) static int svm_hardware_enable(void *garbage) { - struct svm_cpu_data *svm_data; + struct svm_cpu_data *sd; uint64_t efer; struct descriptor_table gdt_descr; struct desc_struct *gdt; @@ -331,63 +331,61 @@ static int svm_hardware_enable(void *garbage) me); return -EINVAL; } - svm_data = per_cpu(svm_data, me); + sd = per_cpu(svm_data, me); - if (!svm_data) { + if (!sd) { printk(KERN_ERR "svm_hardware_enable: svm_data is NULL on %d\n", me); return -EINVAL; } - svm_data->asid_generation = 1; - svm_data->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1; - svm_data->next_asid = svm_data->max_asid + 1; + sd->asid_generation = 1; + sd->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1; + sd->next_asid = sd->max_asid + 1; kvm_get_gdt(&gdt_descr); gdt = (struct desc_struct *)gdt_descr.base; - svm_data->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS); + sd->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS); wrmsrl(MSR_EFER, efer | EFER_SVME); - wrmsrl(MSR_VM_HSAVE_PA, - page_to_pfn(svm_data->save_area) << PAGE_SHIFT); + wrmsrl(MSR_VM_HSAVE_PA, page_to_pfn(sd->save_area) << PAGE_SHIFT); return 0; } static void svm_cpu_uninit(int cpu) { - struct svm_cpu_data *svm_data - = per_cpu(svm_data, raw_smp_processor_id()); + struct svm_cpu_data *sd = per_cpu(svm_data, raw_smp_processor_id()); - if (!svm_data) + if (!sd) return; per_cpu(svm_data, raw_smp_processor_id()) = NULL; - __free_page(svm_data->save_area); - kfree(svm_data); + __free_page(sd->save_area); + kfree(sd); } static int svm_cpu_init(int cpu) { - struct svm_cpu_data *svm_data; + struct svm_cpu_data *sd; int r; - svm_data = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL); - if (!svm_data) + sd = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL); + if (!sd) return -ENOMEM; - svm_data->cpu = cpu; - svm_data->save_area = alloc_page(GFP_KERNEL); + sd->cpu = cpu; + sd->save_area = alloc_page(GFP_KERNEL); r = -ENOMEM; - if (!svm_data->save_area) + if (!sd->save_area) goto err_1; - per_cpu(svm_data, cpu) = svm_data; + per_cpu(svm_data, cpu) = sd; return 0; err_1: - kfree(svm_data); + kfree(sd); return r; } @@ -1092,16 +1090,16 @@ static void save_host_msrs(struct kvm_vcpu *vcpu) #endif } -static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *svm_data) +static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd) { - if (svm_data->next_asid > svm_data->max_asid) { - ++svm_data->asid_generation; - svm_data->next_asid = 1; + if (sd->next_asid > sd->max_asid) { + ++sd->asid_generation; + sd->next_asid = 1; svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID; } - svm->asid_generation = svm_data->asid_generation; - svm->vmcb->control.asid = svm_data->next_asid++; + svm->asid_generation = sd->asid_generation; + svm->vmcb->control.asid = sd->next_asid++; } static unsigned long svm_get_dr(struct kvm_vcpu *vcpu, int dr) @@ -2429,8 +2427,8 @@ static void reload_tss(struct kvm_vcpu *vcpu) { int cpu = raw_smp_processor_id(); - struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu); - svm_data->tss_desc->type = 9; /* available 32/64-bit TSS */ + struct svm_cpu_data *sd = per_cpu(svm_data, cpu); + sd->tss_desc->type = 9; /* available 32/64-bit TSS */ load_TR_desc(); } @@ -2438,12 +2436,12 @@ static void pre_svm_run(struct vcpu_svm *svm) { int cpu = raw_smp_processor_id(); - struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu); + struct svm_cpu_data *sd = per_cpu(svm_data, cpu); svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING; /* FIXME: handle wraparound of asid_generation */ - if (svm->asid_generation != svm_data->asid_generation) - new_asid(svm, svm_data); + if (svm->asid_generation != sd->asid_generation) + new_asid(svm, sd); } static void svm_inject_nmi(struct kvm_vcpu *vcpu) diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index a2d6472895fb309884d442b100502447fcb4c5e9..45b20e486c2f40e5895cb288851d0f2d3f7f59ab 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -5,7 +5,7 @@ inat_tables_script = $(srctree)/arch/x86/tools/gen-insn-attr-x86.awk inat_tables_maps = $(srctree)/arch/x86/lib/x86-opcode-map.txt quiet_cmd_inat_tables = GEN $@ - cmd_inat_tables = $(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ + cmd_inat_tables = $(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@ $(obj)/inat-tables.c: $(inat_tables_script) $(inat_tables_maps) $(call cmd,inat_tables) @@ -20,7 +20,7 @@ lib-y := delay.o lib-y += thunk_$(BITS).o lib-y += usercopy_$(BITS).o getuser.o putuser.o lib-y += memcpy_$(BITS).o -lib-y += insn.o inat.o +lib-$(CONFIG_KPROBES) += insn.o inat.o obj-y += msr-reg.o msr-reg-export.o diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c index 41628b104b9e9ed0bd59724de5ef7d1d131f7aef..872834177937231b5ff9c55965e77929b0d55b98 100644 --- a/arch/x86/lib/msr.c +++ b/arch/x86/lib/msr.c @@ -7,7 +7,6 @@ struct msr_info { u32 msr_no; struct msr reg; struct msr *msrs; - int off; int err; }; @@ -18,7 +17,7 @@ static void __rdmsr_on_cpu(void *info) int this_cpu = raw_smp_processor_id(); if (rv->msrs) - reg = &rv->msrs[this_cpu - rv->off]; + reg = per_cpu_ptr(rv->msrs, this_cpu); else reg = &rv->reg; @@ -32,7 +31,7 @@ static void __wrmsr_on_cpu(void *info) int this_cpu = raw_smp_processor_id(); if (rv->msrs) - reg = &rv->msrs[this_cpu - rv->off]; + reg = per_cpu_ptr(rv->msrs, this_cpu); else reg = &rv->reg; @@ -80,7 +79,6 @@ static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no, memset(&rv, 0, sizeof(rv)); - rv.off = cpumask_first(mask); rv.msrs = msrs; rv.msr_no = msr_no; @@ -120,6 +118,26 @@ void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs) } EXPORT_SYMBOL(wrmsr_on_cpus); +struct msr *msrs_alloc(void) +{ + struct msr *msrs = NULL; + + msrs = alloc_percpu(struct msr); + if (!msrs) { + pr_warning("%s: error allocating msrs\n", __func__); + return NULL; + } + + return msrs; +} +EXPORT_SYMBOL(msrs_alloc); + +void msrs_free(struct msr *msrs) +{ + free_percpu(msrs); +} +EXPORT_SYMBOL(msrs_free); + /* These "safe" variants are slower and should be used when the target MSR may not actually exist. */ static void __rdmsr_safe_on_cpu(void *info) diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c index 07bcc309cfdac8f48bbad39a1bc863c5e4d5dd78..c0f6198565eb63592a3cbebaf7c8e538e987b157 100644 --- a/arch/x86/mm/kmmio.c +++ b/arch/x86/mm/kmmio.c @@ -5,6 +5,8 @@ * 2008 Pekka Paalanen */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -136,7 +138,7 @@ static int clear_page_presence(struct kmmio_fault_page *f, bool clear) pte_t *pte = lookup_address(f->page, &level); if (!pte) { - pr_err("kmmio: no pte for page 0x%08lx\n", f->page); + pr_err("no pte for page 0x%08lx\n", f->page); return -1; } @@ -148,7 +150,7 @@ static int clear_page_presence(struct kmmio_fault_page *f, bool clear) clear_pte_presence(pte, clear, &f->old_presence); break; default: - pr_err("kmmio: unexpected page level 0x%x.\n", level); + pr_err("unexpected page level 0x%x.\n", level); return -1; } @@ -170,13 +172,14 @@ static int clear_page_presence(struct kmmio_fault_page *f, bool clear) static int arm_kmmio_fault_page(struct kmmio_fault_page *f) { int ret; - WARN_ONCE(f->armed, KERN_ERR "kmmio page already armed.\n"); + WARN_ONCE(f->armed, KERN_ERR pr_fmt("kmmio page already armed.\n")); if (f->armed) { - pr_warning("kmmio double-arm: page 0x%08lx, ref %d, old %d\n", - f->page, f->count, !!f->old_presence); + pr_warning("double-arm: page 0x%08lx, ref %d, old %d\n", + f->page, f->count, !!f->old_presence); } ret = clear_page_presence(f, true); - WARN_ONCE(ret < 0, KERN_ERR "kmmio arming 0x%08lx failed.\n", f->page); + WARN_ONCE(ret < 0, KERN_ERR pr_fmt("arming 0x%08lx failed.\n"), + f->page); f->armed = true; return ret; } @@ -240,24 +243,21 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr) * condition needs handling by do_page_fault(), the * page really not being present is the most common. */ - pr_debug("kmmio: secondary hit for 0x%08lx CPU %d.\n", - addr, smp_processor_id()); + pr_debug("secondary hit for 0x%08lx CPU %d.\n", + addr, smp_processor_id()); if (!faultpage->old_presence) - pr_info("kmmio: unexpected secondary hit for " - "address 0x%08lx on CPU %d.\n", addr, - smp_processor_id()); + pr_info("unexpected secondary hit for address 0x%08lx on CPU %d.\n", + addr, smp_processor_id()); } else { /* * Prevent overwriting already in-flight context. * This should not happen, let's hope disarming at * least prevents a panic. */ - pr_emerg("kmmio: recursive probe hit on CPU %d, " - "for address 0x%08lx. Ignoring.\n", - smp_processor_id(), addr); - pr_emerg("kmmio: previous hit was at 0x%08lx.\n", - ctx->addr); + pr_emerg("recursive probe hit on CPU %d, for address 0x%08lx. Ignoring.\n", + smp_processor_id(), addr); + pr_emerg("previous hit was at 0x%08lx.\n", ctx->addr); disarm_kmmio_fault_page(faultpage); } goto no_kmmio_ctx; @@ -316,8 +316,8 @@ static int post_kmmio_handler(unsigned long condition, struct pt_regs *regs) * something external causing them (f.e. using a debugger while * mmio tracing enabled), or erroneous behaviour */ - pr_warning("kmmio: unexpected debug trap on CPU %d.\n", - smp_processor_id()); + pr_warning("unexpected debug trap on CPU %d.\n", + smp_processor_id()); goto out; } @@ -425,7 +425,7 @@ int register_kmmio_probe(struct kmmio_probe *p) list_add_rcu(&p->list, &kmmio_probes); while (size < size_lim) { if (add_kmmio_fault_page(p->addr + size)) - pr_err("kmmio: Unable to set page fault.\n"); + pr_err("Unable to set page fault.\n"); size += PAGE_SIZE; } out: @@ -490,7 +490,7 @@ static void remove_kmmio_fault_pages(struct rcu_head *head) * 2. remove_kmmio_fault_pages() * Remove the pages from kmmio_page_table. * 3. rcu_free_kmmio_fault_pages() - * Actally free the kmmio_fault_page structs as with RCU. + * Actually free the kmmio_fault_page structs as with RCU. */ void unregister_kmmio_probe(struct kmmio_probe *p) { @@ -511,7 +511,7 @@ void unregister_kmmio_probe(struct kmmio_probe *p) drelease = kmalloc(sizeof(*drelease), GFP_ATOMIC); if (!drelease) { - pr_crit("kmmio: leaking kmmio_fault_page objects.\n"); + pr_crit("leaking kmmio_fault_page objects.\n"); return; } drelease->release_list = release_list; diff --git a/arch/x86/mm/mmio-mod.c b/arch/x86/mm/mmio-mod.c index 132772a8ec57a66c629ad5719431fa6c08d95d98..34a3291ca1038969be2657ce8cc7e49fd64a4381 100644 --- a/arch/x86/mm/mmio-mod.c +++ b/arch/x86/mm/mmio-mod.c @@ -19,6 +19,9 @@ * * Derived from the read-mod example from relay-examples by Tom Zanussi. */ + +#define pr_fmt(fmt) "mmiotrace: " fmt + #define DEBUG 1 #include @@ -36,8 +39,6 @@ #include "pf_in.h" -#define NAME "mmiotrace: " - struct trap_reason { unsigned long addr; unsigned long ip; @@ -96,17 +97,18 @@ static void print_pte(unsigned long address) pte_t *pte = lookup_address(address, &level); if (!pte) { - pr_err(NAME "Error in %s: no pte for page 0x%08lx\n", - __func__, address); + pr_err("Error in %s: no pte for page 0x%08lx\n", + __func__, address); return; } if (level == PG_LEVEL_2M) { - pr_emerg(NAME "4MB pages are not currently supported: " - "0x%08lx\n", address); + pr_emerg("4MB pages are not currently supported: 0x%08lx\n", + address); BUG(); } - pr_info(NAME "pte for 0x%lx: 0x%llx 0x%llx\n", address, + pr_info("pte for 0x%lx: 0x%llx 0x%llx\n", + address, (unsigned long long)pte_val(*pte), (unsigned long long)pte_val(*pte) & _PAGE_PRESENT); } @@ -118,22 +120,21 @@ static void print_pte(unsigned long address) static void die_kmmio_nesting_error(struct pt_regs *regs, unsigned long addr) { const struct trap_reason *my_reason = &get_cpu_var(pf_reason); - pr_emerg(NAME "unexpected fault for address: 0x%08lx, " - "last fault for address: 0x%08lx\n", - addr, my_reason->addr); + pr_emerg("unexpected fault for address: 0x%08lx, last fault for address: 0x%08lx\n", + addr, my_reason->addr); print_pte(addr); print_symbol(KERN_EMERG "faulting IP is at %s\n", regs->ip); print_symbol(KERN_EMERG "last faulting IP was at %s\n", my_reason->ip); #ifdef __i386__ pr_emerg("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", - regs->ax, regs->bx, regs->cx, regs->dx); + regs->ax, regs->bx, regs->cx, regs->dx); pr_emerg("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", - regs->si, regs->di, regs->bp, regs->sp); + regs->si, regs->di, regs->bp, regs->sp); #else pr_emerg("rax: %016lx rcx: %016lx rdx: %016lx\n", - regs->ax, regs->cx, regs->dx); + regs->ax, regs->cx, regs->dx); pr_emerg("rsi: %016lx rdi: %016lx rbp: %016lx rsp: %016lx\n", - regs->si, regs->di, regs->bp, regs->sp); + regs->si, regs->di, regs->bp, regs->sp); #endif put_cpu_var(pf_reason); BUG(); @@ -213,7 +214,7 @@ static void post(struct kmmio_probe *p, unsigned long condition, /* this should always return the active_trace count to 0 */ my_reason->active_traces--; if (my_reason->active_traces) { - pr_emerg(NAME "unexpected post handler"); + pr_emerg("unexpected post handler"); BUG(); } @@ -244,7 +245,7 @@ static void ioremap_trace_core(resource_size_t offset, unsigned long size, }; if (!trace) { - pr_err(NAME "kmalloc failed in ioremap\n"); + pr_err("kmalloc failed in ioremap\n"); return; } @@ -282,8 +283,8 @@ void mmiotrace_ioremap(resource_size_t offset, unsigned long size, if (!is_enabled()) /* recheck and proper locking in *_core() */ return; - pr_debug(NAME "ioremap_*(0x%llx, 0x%lx) = %p\n", - (unsigned long long)offset, size, addr); + pr_debug("ioremap_*(0x%llx, 0x%lx) = %p\n", + (unsigned long long)offset, size, addr); if ((filter_offset) && (offset != filter_offset)) return; ioremap_trace_core(offset, size, addr); @@ -301,7 +302,7 @@ static void iounmap_trace_core(volatile void __iomem *addr) struct remap_trace *tmp; struct remap_trace *found_trace = NULL; - pr_debug(NAME "Unmapping %p.\n", addr); + pr_debug("Unmapping %p.\n", addr); spin_lock_irq(&trace_lock); if (!is_enabled()) @@ -363,9 +364,8 @@ static void clear_trace_list(void) * Caller also ensures is_enabled() cannot change. */ list_for_each_entry(trace, &trace_list, list) { - pr_notice(NAME "purging non-iounmapped " - "trace @0x%08lx, size 0x%lx.\n", - trace->probe.addr, trace->probe.len); + pr_notice("purging non-iounmapped trace @0x%08lx, size 0x%lx.\n", + trace->probe.addr, trace->probe.len); if (!nommiotrace) unregister_kmmio_probe(&trace->probe); } @@ -387,7 +387,7 @@ static void enter_uniprocessor(void) if (downed_cpus == NULL && !alloc_cpumask_var(&downed_cpus, GFP_KERNEL)) { - pr_notice(NAME "Failed to allocate mask\n"); + pr_notice("Failed to allocate mask\n"); goto out; } @@ -395,20 +395,19 @@ static void enter_uniprocessor(void) cpumask_copy(downed_cpus, cpu_online_mask); cpumask_clear_cpu(cpumask_first(cpu_online_mask), downed_cpus); if (num_online_cpus() > 1) - pr_notice(NAME "Disabling non-boot CPUs...\n"); + pr_notice("Disabling non-boot CPUs...\n"); put_online_cpus(); for_each_cpu(cpu, downed_cpus) { err = cpu_down(cpu); if (!err) - pr_info(NAME "CPU%d is down.\n", cpu); + pr_info("CPU%d is down.\n", cpu); else - pr_err(NAME "Error taking CPU%d down: %d\n", cpu, err); + pr_err("Error taking CPU%d down: %d\n", cpu, err); } out: if (num_online_cpus() > 1) - pr_warning(NAME "multiple CPUs still online, " - "may miss events.\n"); + pr_warning("multiple CPUs still online, may miss events.\n"); } /* __ref because leave_uniprocessor calls cpu_up which is __cpuinit, @@ -420,13 +419,13 @@ static void __ref leave_uniprocessor(void) if (downed_cpus == NULL || cpumask_weight(downed_cpus) == 0) return; - pr_notice(NAME "Re-enabling CPUs...\n"); + pr_notice("Re-enabling CPUs...\n"); for_each_cpu(cpu, downed_cpus) { err = cpu_up(cpu); if (!err) - pr_info(NAME "enabled CPU%d.\n", cpu); + pr_info("enabled CPU%d.\n", cpu); else - pr_err(NAME "cannot re-enable CPU%d: %d\n", cpu, err); + pr_err("cannot re-enable CPU%d: %d\n", cpu, err); } } @@ -434,8 +433,8 @@ static void __ref leave_uniprocessor(void) static void enter_uniprocessor(void) { if (num_online_cpus() > 1) - pr_warning(NAME "multiple CPUs are online, may miss events. " - "Suggest booting with maxcpus=1 kernel argument.\n"); + pr_warning("multiple CPUs are online, may miss events. " + "Suggest booting with maxcpus=1 kernel argument.\n"); } static void leave_uniprocessor(void) @@ -450,13 +449,13 @@ void enable_mmiotrace(void) goto out; if (nommiotrace) - pr_info(NAME "MMIO tracing disabled.\n"); + pr_info("MMIO tracing disabled.\n"); kmmio_init(); enter_uniprocessor(); spin_lock_irq(&trace_lock); atomic_inc(&mmiotrace_enabled); spin_unlock_irq(&trace_lock); - pr_info(NAME "enabled.\n"); + pr_info("enabled.\n"); out: mutex_unlock(&mmiotrace_mutex); } @@ -475,7 +474,7 @@ void disable_mmiotrace(void) clear_trace_list(); /* guarantees: no more kmmio callbacks */ leave_uniprocessor(); kmmio_cleanup(); - pr_info(NAME "disabled.\n"); + pr_info("disabled.\n"); out: mutex_unlock(&mmiotrace_mutex); } diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 66b55d6e69ed8d74f2479ab567a6ddab4829ae05..ae9648eb1c7f44b919cf93ef7d8f008714409f4e 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -704,9 +704,8 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, if (!range_is_allowed(pfn, size)) return 0; - if (file->f_flags & O_SYNC) { + if (file->f_flags & O_DSYNC) flags = _PAGE_CACHE_UC_MINUS; - } #ifdef CONFIG_X86_32 /* diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile index d49202e740eaf5a224897e4991c9eec951657918..564b008a51c7abdee986f03c1ccfe3a09894a93a 100644 --- a/arch/x86/pci/Makefile +++ b/arch/x86/pci/Makefile @@ -15,3 +15,8 @@ obj-$(CONFIG_X86_NUMAQ) += numaq_32.o obj-y += common.o early.o obj-y += amd_bus.o +obj-$(CONFIG_X86_64) += bus_numa.o intel_bus.o + +ifeq ($(CONFIG_PCI_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 1014eb4bfc37ac15cec9e3b24b3f980a1a52e7d9..959e548a7039e81a85cdd0e7eb114a86f91a05c5 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -7,6 +7,7 @@ #include struct pci_root_info { + struct acpi_device *bridge; char *name; unsigned int res_num; struct resource *res; @@ -58,6 +59,30 @@ bus_has_transparent_bridge(struct pci_bus *bus) return false; } +static void +align_resource(struct acpi_device *bridge, struct resource *res) +{ + int align = (res->flags & IORESOURCE_MEM) ? 16 : 4; + + /* + * Host bridge windows are not BARs, but the decoders on the PCI side + * that claim this address space have starting alignment and length + * constraints, so fix any obvious BIOS goofs. + */ + if (!IS_ALIGNED(res->start, align)) { + dev_printk(KERN_DEBUG, &bridge->dev, + "host bridge window %pR invalid; " + "aligning start to %d-byte boundary\n", res, align); + res->start &= ~(align - 1); + } + if (!IS_ALIGNED(res->end + 1, align)) { + dev_printk(KERN_DEBUG, &bridge->dev, + "host bridge window %pR invalid; " + "aligning end to %d-byte boundary\n", res, align); + res->end = ALIGN(res->end, align) - 1; + } +} + static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data) { @@ -91,11 +116,12 @@ setup_resource(struct acpi_resource *acpi_res, void *data) start = addr.minimum + addr.translation_offset; end = start + addr.address_length - 1; if (info->res_num >= max_root_bus_resources) { - printk(KERN_WARNING "PCI: Failed to allocate 0x%lx-0x%lx " - "from %s for %s due to _CRS returning more than " - "%d resource descriptors\n", (unsigned long) start, - (unsigned long) end, root->name, info->name, - max_root_bus_resources); + if (pci_probe & PCI_USE__CRS) + printk(KERN_WARNING "PCI: Failed to allocate " + "0x%lx-0x%lx from %s for %s due to _CRS " + "returning more than %d resource descriptors\n", + (unsigned long) start, (unsigned long) end, + root->name, info->name, max_root_bus_resources); return AE_OK; } @@ -105,14 +131,28 @@ setup_resource(struct acpi_resource *acpi_res, void *data) res->start = start; res->end = end; res->child = NULL; + align_resource(info->bridge, res); + + if (!(pci_probe & PCI_USE__CRS)) { + dev_printk(KERN_DEBUG, &info->bridge->dev, + "host bridge window %pR (ignored)\n", res); + return AE_OK; + } if (insert_resource(root, res)) { - printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx " - "from %s for %s\n", (unsigned long) res->start, - (unsigned long) res->end, root->name, info->name); + dev_err(&info->bridge->dev, + "can't allocate host bridge window %pR\n", res); } else { info->bus->resource[info->res_num] = res; info->res_num++; + if (addr.translation_offset) + dev_info(&info->bridge->dev, "host bridge window %pR " + "(PCI address [%#llx-%#llx])\n", + res, res->start - addr.translation_offset, + res->end - addr.translation_offset); + else + dev_info(&info->bridge->dev, + "host bridge window %pR\n", res); } return AE_OK; } @@ -124,6 +164,12 @@ get_current_resources(struct acpi_device *device, int busnum, struct pci_root_info info; size_t size; + if (!(pci_probe & PCI_USE__CRS)) + dev_info(&device->dev, + "ignoring host bridge windows from ACPI; " + "boot with \"pci=use_crs\" to use them\n"); + + info.bridge = device; info.bus = bus; info.res_num = 0; acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource, @@ -163,8 +209,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do #endif if (domain && !pci_domains_supported) { - printk(KERN_WARNING "PCI: Multiple domains not supported " - "(dom %d, bus %d)\n", domain, busnum); + printk(KERN_WARNING "pci_bus %04x:%02x: " + "ignored (multiple domains not supported)\n", + domain, busnum); return NULL; } @@ -188,7 +235,8 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do */ sd = kzalloc(sizeof(*sd), GFP_KERNEL); if (!sd) { - printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum); + printk(KERN_WARNING "pci_bus %04x:%02x: " + "ignored (out of memory)\n", domain, busnum); return NULL; } @@ -209,9 +257,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do } else { bus = pci_create_bus(NULL, busnum, &pci_root_ops, sd); if (bus) { - if (pci_probe & PCI_USE__CRS) - get_current_resources(device, busnum, domain, - bus); + get_current_resources(device, busnum, domain, bus); bus->subordinate = pci_scan_child_bus(bus); } } diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index 572ee9782f2afdf75ca1af76ae172ce01ec9a3a8..95ecbd495955094ac22c7502fe992ea2af7ad444 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c @@ -6,10 +6,10 @@ #ifdef CONFIG_X86_64 #include -#include -#include #endif +#include "bus_numa.h" + /* * This discovers the pcibus <-> node mapping on AMD K8. * also get peer root bus resource for io,mmio @@ -17,67 +17,6 @@ #ifdef CONFIG_X86_64 -/* - * sub bus (transparent) will use entres from 3 to store extra from root, - * so need to make sure have enought slot there, increase PCI_BUS_NUM_RESOURCES? - */ -#define RES_NUM 16 -struct pci_root_info { - char name[12]; - unsigned int res_num; - struct resource res[RES_NUM]; - int bus_min; - int bus_max; - int node; - int link; -}; - -/* 4 at this time, it may become to 32 */ -#define PCI_ROOT_NR 4 -static int pci_root_num; -static struct pci_root_info pci_root_info[PCI_ROOT_NR]; - -void x86_pci_root_bus_res_quirks(struct pci_bus *b) -{ - int i; - int j; - struct pci_root_info *info; - - /* don't go for it if _CRS is used already */ - if (b->resource[0] != &ioport_resource || - b->resource[1] != &iomem_resource) - return; - - /* if only one root bus, don't need to anything */ - if (pci_root_num < 2) - return; - - for (i = 0; i < pci_root_num; i++) { - if (pci_root_info[i].bus_min == b->number) - break; - } - - if (i == pci_root_num) - return; - - printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n", - b->number); - - info = &pci_root_info[i]; - for (j = 0; j < info->res_num; j++) { - struct resource *res; - struct resource *root; - - res = &info->res[j]; - b->resource[j] = res; - if (res->flags & IORESOURCE_IO) - root = &ioport_resource; - else - root = &iomem_resource; - insert_resource(root, res); - } -} - #define RANGE_NUM 16 struct res_range { @@ -130,52 +69,6 @@ static void __init update_range(struct res_range *range, size_t start, } } -static void __init update_res(struct pci_root_info *info, size_t start, - size_t end, unsigned long flags, int merge) -{ - int i; - struct resource *res; - - if (!merge) - goto addit; - - /* try to merge it with old one */ - for (i = 0; i < info->res_num; i++) { - size_t final_start, final_end; - size_t common_start, common_end; - - res = &info->res[i]; - if (res->flags != flags) - continue; - - common_start = max((size_t)res->start, start); - common_end = min((size_t)res->end, end); - if (common_start > common_end + 1) - continue; - - final_start = min((size_t)res->start, start); - final_end = max((size_t)res->end, end); - - res->start = final_start; - res->end = final_end; - return; - } - -addit: - - /* need to add that */ - if (info->res_num >= RES_NUM) - return; - - res = &info->res[info->res_num]; - res->name = info->name; - res->flags = flags; - res->start = start; - res->end = end; - res->child = NULL; - info->res_num++; -} - struct pci_hostbridge_probe { u32 bus; u32 slot; @@ -230,7 +123,6 @@ static int __init early_fill_mp_bus_info(void) int j; unsigned bus; unsigned slot; - int found; int node; int link; int def_node; @@ -247,7 +139,7 @@ static int __init early_fill_mp_bus_info(void) if (!early_pci_allowed()) return -1; - found = 0; + found_all_numa_early = 0; for (i = 0; i < ARRAY_SIZE(pci_probes); i++) { u32 id; u16 device; @@ -261,12 +153,12 @@ static int __init early_fill_mp_bus_info(void) device = (id>>16) & 0xffff; if (pci_probes[i].vendor == vendor && pci_probes[i].device == device) { - found = 1; + found_all_numa_early = 1; break; } } - if (!found) + if (!found_all_numa_early) return 0; pci_root_num = 0; @@ -488,7 +380,7 @@ static int __init early_fill_mp_bus_info(void) info = &pci_root_info[i]; res_num = info->res_num; busnum = info->bus_min; - printk(KERN_DEBUG "bus: [%02x,%02x] on node %x link %x\n", + printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n", info->bus_min, info->bus_max, info->node, info->link); for (j = 0; j < res_num; j++) { res = &info->res[j]; diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c new file mode 100644 index 0000000000000000000000000000000000000000..145df00e038759499d2b70b97babf24255fa8285 --- /dev/null +++ b/arch/x86/pci/bus_numa.c @@ -0,0 +1,101 @@ +#include +#include + +#include "bus_numa.h" + +int pci_root_num; +struct pci_root_info pci_root_info[PCI_ROOT_NR]; +int found_all_numa_early; + +void x86_pci_root_bus_res_quirks(struct pci_bus *b) +{ + int i; + int j; + struct pci_root_info *info; + + /* don't go for it if _CRS is used already */ + if (b->resource[0] != &ioport_resource || + b->resource[1] != &iomem_resource) + return; + + if (!pci_root_num) + return; + + /* for amd, if only one root bus, don't need to do anything */ + if (pci_root_num < 2 && found_all_numa_early) + return; + + for (i = 0; i < pci_root_num; i++) { + if (pci_root_info[i].bus_min == b->number) + break; + } + + if (i == pci_root_num) + return; + + printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n", + b->number); + + info = &pci_root_info[i]; + for (j = 0; j < info->res_num; j++) { + struct resource *res; + struct resource *root; + + res = &info->res[j]; + b->resource[j] = res; + if (res->flags & IORESOURCE_IO) + root = &ioport_resource; + else + root = &iomem_resource; + insert_resource(root, res); + } +} + +void __init update_res(struct pci_root_info *info, size_t start, + size_t end, unsigned long flags, int merge) +{ + int i; + struct resource *res; + + if (start > end) + return; + + if (!merge) + goto addit; + + /* try to merge it with old one */ + for (i = 0; i < info->res_num; i++) { + size_t final_start, final_end; + size_t common_start, common_end; + + res = &info->res[i]; + if (res->flags != flags) + continue; + + common_start = max((size_t)res->start, start); + common_end = min((size_t)res->end, end); + if (common_start > common_end + 1) + continue; + + final_start = min((size_t)res->start, start); + final_end = max((size_t)res->end, end); + + res->start = final_start; + res->end = final_end; + return; + } + +addit: + + /* need to add that */ + if (info->res_num >= RES_NUM) + return; + + res = &info->res[info->res_num]; + res->name = info->name; + res->flags = flags; + res->start = start; + res->end = end; + res->child = NULL; + info->res_num++; +} diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h new file mode 100644 index 0000000000000000000000000000000000000000..adbc23fe82acc4fbcde63a5821838eab4567f0f7 --- /dev/null +++ b/arch/x86/pci/bus_numa.h @@ -0,0 +1,27 @@ +#ifdef CONFIG_X86_64 + +/* + * sub bus (transparent) will use entres from 3 to store extra from + * root, so need to make sure we have enough slot there, Should we + * increase PCI_BUS_NUM_RESOURCES? + */ +#define RES_NUM 16 +struct pci_root_info { + char name[12]; + unsigned int res_num; + struct resource res[RES_NUM]; + int bus_min; + int bus_max; + int node; + int link; +}; + +/* 4 at this time, it may become to 32 */ +#define PCI_ROOT_NR 4 +extern int pci_root_num; +extern struct pci_root_info pci_root_info[PCI_ROOT_NR]; +extern int found_all_numa_early; + +extern void update_res(struct pci_root_info *info, size_t start, + size_t end, unsigned long flags, int merge); +#endif diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 1331fcf261433b72c9d0a4620326a3898f1761fa..d2552c68e94d9670a7086c2eca1258a453c1a516 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -410,8 +410,6 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum) return bus; } -extern u8 pci_cache_line_size; - int __init pcibios_init(void) { struct cpuinfo_x86 *c = &boot_cpu_data; @@ -422,15 +420,19 @@ int __init pcibios_init(void) } /* - * Assume PCI cacheline size of 32 bytes for all x86s except K7/K8 - * and P4. It's also good for 386/486s (which actually have 16) + * Set PCI cacheline size to that of the CPU if the CPU has reported it. + * (For older CPUs that don't support cpuid, we se it to 32 bytes + * It's also good for 386/486s (which actually have 16) * as quite a few PCI devices do not support smaller values. */ - pci_cache_line_size = 32 >> 2; - if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD) - pci_cache_line_size = 64 >> 2; /* K7 & K8 */ - else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL) - pci_cache_line_size = 128 >> 2; /* P4 */ + if (c->x86_clflush_size > 0) { + pci_dfl_cache_line_size = c->x86_clflush_size >> 2; + printk(KERN_DEBUG "PCI: pci_cache_line_size set to %d bytes\n", + pci_dfl_cache_line_size << 2); + } else { + pci_dfl_cache_line_size = 32 >> 2; + printk(KERN_DEBUG "PCI: Unknown cacheline size. Setting to 32 bytes\n"); + } pcibios_resource_survey(); diff --git a/arch/x86/pci/early.c b/arch/x86/pci/early.c index aaf26ae58cd5cadb73ae168cd7f46edf9cc2b4f3..d1067d539bee2da24fb260ac64b2162ecf63d17b 100644 --- a/arch/x86/pci/early.c +++ b/arch/x86/pci/early.c @@ -12,8 +12,6 @@ u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset) u32 v; outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); v = inl(0xcfc); - if (v != 0xffffffff) - pr_debug("%x reading 4 from %x: %x\n", slot, offset, v); return v; } @@ -22,7 +20,6 @@ u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset) u8 v; outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); v = inb(0xcfc + (offset&3)); - pr_debug("%x reading 1 from %x: %x\n", slot, offset, v); return v; } @@ -31,28 +28,24 @@ u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset) u16 v; outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); v = inw(0xcfc + (offset&2)); - pr_debug("%x reading 2 from %x: %x\n", slot, offset, v); return v; } void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset, u32 val) { - pr_debug("%x writing to %x: %x\n", slot, offset, val); outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); outl(val, 0xcfc); } void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val) { - pr_debug("%x writing to %x: %x\n", slot, offset, val); outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); outb(val, 0xcfc + (offset&3)); } void write_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset, u16 val) { - pr_debug("%x writing to %x: %x\n", slot, offset, val); outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); outw(val, 0xcfc + (offset&2)); } diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index b22d13b0c71d0f538cd25f2643490d0bf2fa86a3..5dc9e8c63fcdedb26a096d48efcf2392cd8f8209 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -129,7 +129,9 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) continue; if (!r->start || pci_claim_resource(dev, idx) < 0) { - dev_info(&dev->dev, "BAR %d: can't allocate resource\n", idx); + dev_info(&dev->dev, + "can't reserve window %pR\n", + r); /* * Something is wrong with the region. * Invalidate the resource to prevent @@ -144,16 +146,29 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) } } +struct pci_check_idx_range { + int start; + int end; +}; + static void __init pcibios_allocate_resources(int pass) { struct pci_dev *dev = NULL; - int idx, disabled; + int idx, disabled, i; u16 command; struct resource *r; + struct pci_check_idx_range idx_range[] = { + { PCI_STD_RESOURCES, PCI_STD_RESOURCE_END }, +#ifdef CONFIG_PCI_IOV + { PCI_IOV_RESOURCES, PCI_IOV_RESOURCE_END }, +#endif + }; + for_each_pci_dev(dev) { pci_read_config_word(dev, PCI_COMMAND, &command); - for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { + for (i = 0; i < ARRAY_SIZE(idx_range); i++) + for (idx = idx_range[i].start; idx <= idx_range[i].end; idx++) { r = &dev->resource[idx]; if (r->parent) /* Already allocated */ continue; @@ -164,12 +179,12 @@ static void __init pcibios_allocate_resources(int pass) else disabled = !(command & PCI_COMMAND_MEMORY); if (pass == disabled) { - dev_dbg(&dev->dev, "resource %#08llx-%#08llx (f=%lx, d=%d, p=%d)\n", - (unsigned long long) r->start, - (unsigned long long) r->end, - r->flags, disabled, pass); + dev_dbg(&dev->dev, + "BAR %d: reserving %pr (d=%d, p=%d)\n", + idx, r, disabled, pass); if (pci_claim_resource(dev, idx) < 0) { - dev_info(&dev->dev, "BAR %d: can't allocate resource\n", idx); + dev_info(&dev->dev, + "can't reserve %pR\n", r); /* We'll assign a new address later */ r->end -= r->start; r->start = 0; @@ -182,7 +197,7 @@ static void __init pcibios_allocate_resources(int pass) /* Turn the ROM off, leave the resource region, * but keep it unregistered. */ u32 reg; - dev_dbg(&dev->dev, "disabling ROM\n"); + dev_dbg(&dev->dev, "disabling ROM %pR\n", r); r->flags &= ~IORESOURCE_ROM_ENABLE; pci_read_config_dword(dev, dev->rom_base_reg, ®); @@ -282,6 +297,15 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, return -EINVAL; prot = pgprot_val(vma->vm_page_prot); + + /* + * Return error if pat is not enabled and write_combine is requested. + * Caller can followup with UC MINUS request and add a WC mtrr if there + * is a free mtrr slot. + */ + if (!pat_enabled && write_combine) + return -EINVAL; + if (pat_enabled && write_combine) prot |= _PAGE_CACHE_WC; else if (pat_enabled || boot_cpu_data.x86 > 3) diff --git a/arch/x86/pci/intel_bus.c b/arch/x86/pci/intel_bus.c new file mode 100644 index 0000000000000000000000000000000000000000..b7a55dc55d13f65b9921400b5a53cbd4ee9213f7 --- /dev/null +++ b/arch/x86/pci/intel_bus.c @@ -0,0 +1,90 @@ +/* + * to read io range from IOH pci conf, need to do it after mmconfig is there + */ + +#include +#include +#include +#include +#include + +#include "bus_numa.h" + +static inline void print_ioh_resources(struct pci_root_info *info) +{ + int res_num; + int busnum; + int i; + + printk(KERN_DEBUG "IOH bus: [%02x, %02x]\n", + info->bus_min, info->bus_max); + res_num = info->res_num; + busnum = info->bus_min; + for (i = 0; i < res_num; i++) { + struct resource *res; + + res = &info->res[i]; + printk(KERN_DEBUG "IOH bus: %02x index %x %s: [%llx, %llx]\n", + busnum, i, + (res->flags & IORESOURCE_IO) ? "io port" : + "mmio", + res->start, res->end); + } +} + +#define IOH_LIO 0x108 +#define IOH_LMMIOL 0x10c +#define IOH_LMMIOH 0x110 +#define IOH_LMMIOH_BASEU 0x114 +#define IOH_LMMIOH_LIMITU 0x118 +#define IOH_LCFGBUS 0x11c + +static void __devinit pci_root_bus_res(struct pci_dev *dev) +{ + u16 word; + u32 dword; + struct pci_root_info *info; + u16 io_base, io_end; + u32 mmiol_base, mmiol_end; + u64 mmioh_base, mmioh_end; + int bus_base, bus_end; + + if (pci_root_num >= PCI_ROOT_NR) { + printk(KERN_DEBUG "intel_bus.c: PCI_ROOT_NR is too small\n"); + return; + } + + info = &pci_root_info[pci_root_num]; + pci_root_num++; + + pci_read_config_word(dev, IOH_LCFGBUS, &word); + bus_base = (word & 0xff); + bus_end = (word & 0xff00) >> 8; + sprintf(info->name, "PCI Bus #%02x", bus_base); + info->bus_min = bus_base; + info->bus_max = bus_end; + + pci_read_config_word(dev, IOH_LIO, &word); + io_base = (word & 0xf0) << (12 - 4); + io_end = (word & 0xf000) | 0xfff; + update_res(info, io_base, io_end, IORESOURCE_IO, 0); + + pci_read_config_dword(dev, IOH_LMMIOL, &dword); + mmiol_base = (dword & 0xff00) << (24 - 8); + mmiol_end = (dword & 0xff000000) | 0xffffff; + update_res(info, mmiol_base, mmiol_end, IORESOURCE_MEM, 0); + + pci_read_config_dword(dev, IOH_LMMIOH, &dword); + mmioh_base = ((u64)(dword & 0xfc00)) << (26 - 10); + mmioh_end = ((u64)(dword & 0xfc000000) | 0x3ffffff); + pci_read_config_dword(dev, IOH_LMMIOH_BASEU, &dword); + mmioh_base |= ((u64)(dword & 0x7ffff)) << 32; + pci_read_config_dword(dev, IOH_LMMIOH_LIMITU, &dword); + mmioh_end |= ((u64)(dword & 0x7ffff)) << 32; + update_res(info, mmioh_base, mmioh_end, IORESOURCE_MEM, 0); + + print_ioh_resources(info); +} + +/* intel IOH */ +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, pci_root_bus_res); diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 602c172d3bd5a5c44685893071b32b2d8827c023..b19d1e54201ee95a80d8123e9ba26716811c52fe 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -15,48 +15,98 @@ #include #include #include -#include +#include #include #include #include #define PREFIX "PCI: " -/* aperture is up to 256MB but BIOS may reserve less */ -#define MMCONFIG_APER_MIN (2 * 1024*1024) -#define MMCONFIG_APER_MAX (256 * 1024*1024) - /* Indicate if the mmcfg resources have been placed into the resource table. */ static int __initdata pci_mmcfg_resources_inserted; -static __init int extend_mmcfg(int num) +LIST_HEAD(pci_mmcfg_list); + +static __init void pci_mmconfig_remove(struct pci_mmcfg_region *cfg) { - struct acpi_mcfg_allocation *new; - int new_num = pci_mmcfg_config_num + num; + if (cfg->res.parent) + release_resource(&cfg->res); + list_del(&cfg->list); + kfree(cfg); +} - new = kzalloc(sizeof(pci_mmcfg_config[0]) * new_num, GFP_KERNEL); - if (!new) - return -1; +static __init void free_all_mmcfg(void) +{ + struct pci_mmcfg_region *cfg, *tmp; - if (pci_mmcfg_config) { - memcpy(new, pci_mmcfg_config, - sizeof(pci_mmcfg_config[0]) * new_num); - kfree(pci_mmcfg_config); + pci_mmcfg_arch_free(); + list_for_each_entry_safe(cfg, tmp, &pci_mmcfg_list, list) + pci_mmconfig_remove(cfg); +} + +static __init void list_add_sorted(struct pci_mmcfg_region *new) +{ + struct pci_mmcfg_region *cfg; + + /* keep list sorted by segment and starting bus number */ + list_for_each_entry(cfg, &pci_mmcfg_list, list) { + if (cfg->segment > new->segment || + (cfg->segment == new->segment && + cfg->start_bus >= new->start_bus)) { + list_add_tail(&new->list, &cfg->list); + return; + } } - pci_mmcfg_config = new; + list_add_tail(&new->list, &pci_mmcfg_list); +} - return 0; +static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start, + int end, u64 addr) +{ + struct pci_mmcfg_region *new; + int num_buses; + struct resource *res; + + if (addr == 0) + return NULL; + + new = kzalloc(sizeof(*new), GFP_KERNEL); + if (!new) + return NULL; + + new->address = addr; + new->segment = segment; + new->start_bus = start; + new->end_bus = end; + + list_add_sorted(new); + + num_buses = end - start + 1; + res = &new->res; + res->start = addr + PCI_MMCFG_BUS_OFFSET(start); + res->end = addr + PCI_MMCFG_BUS_OFFSET(num_buses) - 1; + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + snprintf(new->name, PCI_MMCFG_RESOURCE_NAME_LEN, + "PCI MMCONFIG %04x [bus %02x-%02x]", segment, start, end); + res->name = new->name; + + printk(KERN_INFO PREFIX "MMCONFIG for domain %04x [bus %02x-%02x] at " + "%pR (base %#lx)\n", segment, start, end, &new->res, + (unsigned long) addr); + + return new; } -static __init void fill_one_mmcfg(u64 addr, int segment, int start, int end) +struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus) { - int i = pci_mmcfg_config_num; + struct pci_mmcfg_region *cfg; - pci_mmcfg_config_num++; - pci_mmcfg_config[i].address = addr; - pci_mmcfg_config[i].pci_segment = segment; - pci_mmcfg_config[i].start_bus_number = start; - pci_mmcfg_config[i].end_bus_number = end; + list_for_each_entry(cfg, &pci_mmcfg_list, list) + if (cfg->segment == segment && + cfg->start_bus <= bus && bus <= cfg->end_bus) + return cfg; + + return NULL; } static const char __init *pci_mmcfg_e7520(void) @@ -68,11 +118,9 @@ static const char __init *pci_mmcfg_e7520(void) if (win == 0x0000 || win == 0xf000) return NULL; - if (extend_mmcfg(1) == -1) + if (pci_mmconfig_add(0, 0, 255, win << 16) == NULL) return NULL; - fill_one_mmcfg(win << 16, 0, 0, 255); - return "Intel Corporation E7520 Memory Controller Hub"; } @@ -114,11 +162,9 @@ static const char __init *pci_mmcfg_intel_945(void) if ((pciexbar & mask) >= 0xf0000000U) return NULL; - if (extend_mmcfg(1) == -1) + if (pci_mmconfig_add(0, 0, (len >> 20) - 1, pciexbar & mask) == NULL) return NULL; - fill_one_mmcfg(pciexbar & mask, 0, 0, (len >> 20) - 1); - return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub"; } @@ -127,7 +173,7 @@ static const char __init *pci_mmcfg_amd_fam10h(void) u32 low, high, address; u64 base, msr; int i; - unsigned segnbits = 0, busnbits; + unsigned segnbits = 0, busnbits, end_bus; if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF)) return NULL; @@ -161,11 +207,13 @@ static const char __init *pci_mmcfg_amd_fam10h(void) busnbits = 8; } - if (extend_mmcfg(1 << segnbits) == -1) - return NULL; - + end_bus = (1 << busnbits) - 1; for (i = 0; i < (1 << segnbits); i++) - fill_one_mmcfg(base + (1<<28) * i, i, 0, (1 << busnbits) - 1); + if (pci_mmconfig_add(i, 0, end_bus, + base + (1<<28) * i) == NULL) { + free_all_mmcfg(); + return NULL; + } return "AMD Family 10h NB"; } @@ -190,7 +238,7 @@ static const char __init *pci_mmcfg_nvidia_mcp55(void) /* * do check if amd fam10h already took over */ - if (!acpi_disabled || pci_mmcfg_config_num || mcp55_checked) + if (!acpi_disabled || !list_empty(&pci_mmcfg_list) || mcp55_checked) return NULL; mcp55_checked = true; @@ -213,16 +261,14 @@ static const char __init *pci_mmcfg_nvidia_mcp55(void) if (!(extcfg & extcfg_enable_mask)) continue; - if (extend_mmcfg(1) == -1) - continue; - size_index = (extcfg & extcfg_size_mask) >> extcfg_size_shift; base = extcfg & extcfg_base_mask[size_index]; /* base could > 4G */ base <<= extcfg_base_lshift; start = (extcfg & extcfg_start_mask) >> extcfg_start_shift; end = start + extcfg_sizebus[size_index] - 1; - fill_one_mmcfg(base, 0, start, end); + if (pci_mmconfig_add(0, start, end, base) == NULL) + continue; mcp55_mmconf_found++; } @@ -253,45 +299,27 @@ static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = { 0x0369, pci_mmcfg_nvidia_mcp55 }, }; -static int __init cmp_mmcfg(const void *x1, const void *x2) -{ - const typeof(pci_mmcfg_config[0]) *m1 = x1; - const typeof(pci_mmcfg_config[0]) *m2 = x2; - int start1, start2; - - start1 = m1->start_bus_number; - start2 = m2->start_bus_number; - - return start1 - start2; -} - static void __init pci_mmcfg_check_end_bus_number(void) { - int i; - typeof(pci_mmcfg_config[0]) *cfg, *cfgx; - - /* sort them at first */ - sort(pci_mmcfg_config, pci_mmcfg_config_num, - sizeof(pci_mmcfg_config[0]), cmp_mmcfg, NULL); + struct pci_mmcfg_region *cfg, *cfgx; /* last one*/ - if (pci_mmcfg_config_num > 0) { - i = pci_mmcfg_config_num - 1; - cfg = &pci_mmcfg_config[i]; - if (cfg->end_bus_number < cfg->start_bus_number) - cfg->end_bus_number = 255; - } + cfg = list_entry(pci_mmcfg_list.prev, typeof(*cfg), list); + if (cfg) + if (cfg->end_bus < cfg->start_bus) + cfg->end_bus = 255; - /* don't overlap please */ - for (i = 0; i < pci_mmcfg_config_num - 1; i++) { - cfg = &pci_mmcfg_config[i]; - cfgx = &pci_mmcfg_config[i+1]; + if (list_is_singular(&pci_mmcfg_list)) + return; - if (cfg->end_bus_number < cfg->start_bus_number) - cfg->end_bus_number = 255; + /* don't overlap please */ + list_for_each_entry(cfg, &pci_mmcfg_list, list) { + if (cfg->end_bus < cfg->start_bus) + cfg->end_bus = 255; - if (cfg->end_bus_number >= cfgx->start_bus_number) - cfg->end_bus_number = cfgx->start_bus_number - 1; + cfgx = list_entry(cfg->list.next, typeof(*cfg), list); + if (cfg != cfgx && cfg->end_bus >= cfgx->start_bus) + cfg->end_bus = cfgx->start_bus - 1; } } @@ -306,8 +334,7 @@ static int __init pci_mmcfg_check_hostbridge(void) if (!raw_pci_ops) return 0; - pci_mmcfg_config_num = 0; - pci_mmcfg_config = NULL; + free_all_mmcfg(); for (i = 0; i < ARRAY_SIZE(pci_mmcfg_probes); i++) { bus = pci_mmcfg_probes[i].bus; @@ -322,45 +349,22 @@ static int __init pci_mmcfg_check_hostbridge(void) name = pci_mmcfg_probes[i].probe(); if (name) - printk(KERN_INFO "PCI: Found %s with MMCONFIG support.\n", + printk(KERN_INFO PREFIX "%s with MMCONFIG support\n", name); } /* some end_bus_number is crazy, fix it */ pci_mmcfg_check_end_bus_number(); - return pci_mmcfg_config_num != 0; + return !list_empty(&pci_mmcfg_list); } static void __init pci_mmcfg_insert_resources(void) { -#define PCI_MMCFG_RESOURCE_NAME_LEN 24 - int i; - struct resource *res; - char *names; - unsigned num_buses; - - res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res), - pci_mmcfg_config_num, GFP_KERNEL); - if (!res) { - printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n"); - return; - } + struct pci_mmcfg_region *cfg; - names = (void *)&res[pci_mmcfg_config_num]; - for (i = 0; i < pci_mmcfg_config_num; i++, res++) { - struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i]; - num_buses = cfg->end_bus_number - cfg->start_bus_number + 1; - res->name = names; - snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, - "PCI MMCONFIG %u [%02x-%02x]", cfg->pci_segment, - cfg->start_bus_number, cfg->end_bus_number); - res->start = cfg->address + (cfg->start_bus_number << 20); - res->end = res->start + (num_buses << 20) - 1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; - insert_resource(&iomem_resource, res); - names += PCI_MMCFG_RESOURCE_NAME_LEN; - } + list_for_each_entry(cfg, &pci_mmcfg_list, list) + insert_resource(&iomem_resource, &cfg->res); /* Mark that the resources have been inserted. */ pci_mmcfg_resources_inserted = 1; @@ -437,11 +441,12 @@ static int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used) typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type); static int __init is_mmconf_reserved(check_reserved_t is_reserved, - u64 addr, u64 size, int i, - typeof(pci_mmcfg_config[0]) *cfg, int with_e820) + struct pci_mmcfg_region *cfg, int with_e820) { + u64 addr = cfg->res.start; + u64 size = resource_size(&cfg->res); u64 old_size = size; - int valid = 0; + int valid = 0, num_buses; while (!is_reserved(addr, addr + size, E820_RESERVED)) { size >>= 1; @@ -450,19 +455,25 @@ static int __init is_mmconf_reserved(check_reserved_t is_reserved, } if (size >= (16UL<<20) || size == old_size) { - printk(KERN_NOTICE - "PCI: MCFG area at %Lx reserved in %s\n", - addr, with_e820?"E820":"ACPI motherboard resources"); + printk(KERN_INFO PREFIX "MMCONFIG at %pR reserved in %s\n", + &cfg->res, + with_e820 ? "E820" : "ACPI motherboard resources"); valid = 1; if (old_size != size) { - /* update end_bus_number */ - cfg->end_bus_number = cfg->start_bus_number + ((size>>20) - 1); - printk(KERN_NOTICE "PCI: updated MCFG configuration %d: base %lx " - "segment %hu buses %u - %u\n", - i, (unsigned long)cfg->address, cfg->pci_segment, - (unsigned int)cfg->start_bus_number, - (unsigned int)cfg->end_bus_number); + /* update end_bus */ + cfg->end_bus = cfg->start_bus + ((size>>20) - 1); + num_buses = cfg->end_bus - cfg->start_bus + 1; + cfg->res.end = cfg->res.start + + PCI_MMCFG_BUS_OFFSET(num_buses) - 1; + snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN, + "PCI MMCONFIG %04x [bus %02x-%02x]", + cfg->segment, cfg->start_bus, cfg->end_bus); + printk(KERN_INFO PREFIX + "MMCONFIG for %04x [bus%02x-%02x] " + "at %pR (base %#lx) (size reduced!)\n", + cfg->segment, cfg->start_bus, cfg->end_bus, + &cfg->res, (unsigned long) cfg->address); } } @@ -471,45 +482,26 @@ static int __init is_mmconf_reserved(check_reserved_t is_reserved, static void __init pci_mmcfg_reject_broken(int early) { - typeof(pci_mmcfg_config[0]) *cfg; - int i; + struct pci_mmcfg_region *cfg; - if ((pci_mmcfg_config_num == 0) || - (pci_mmcfg_config == NULL) || - (pci_mmcfg_config[0].address == 0)) - return; - - for (i = 0; i < pci_mmcfg_config_num; i++) { + list_for_each_entry(cfg, &pci_mmcfg_list, list) { int valid = 0; - u64 addr, size; - - cfg = &pci_mmcfg_config[i]; - addr = cfg->start_bus_number; - addr <<= 20; - addr += cfg->address; - size = cfg->end_bus_number + 1 - cfg->start_bus_number; - size <<= 20; - printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx " - "segment %hu buses %u - %u\n", - i, (unsigned long)cfg->address, cfg->pci_segment, - (unsigned int)cfg->start_bus_number, - (unsigned int)cfg->end_bus_number); if (!early && !acpi_disabled) - valid = is_mmconf_reserved(is_acpi_reserved, addr, size, i, cfg, 0); + valid = is_mmconf_reserved(is_acpi_reserved, cfg, 0); if (valid) continue; if (!early) - printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not" - " reserved in ACPI motherboard resources\n", - cfg->address); + printk(KERN_ERR FW_BUG PREFIX + "MMCONFIG at %pR not reserved in " + "ACPI motherboard resources\n", &cfg->res); /* Don't try to do this check unless configuration type 1 is available. how about type 2 ?*/ if (raw_pci_ops) - valid = is_mmconf_reserved(e820_all_mapped, addr, size, i, cfg, 1); + valid = is_mmconf_reserved(e820_all_mapped, cfg, 1); if (!valid) goto reject; @@ -518,34 +510,41 @@ static void __init pci_mmcfg_reject_broken(int early) return; reject: - printk(KERN_INFO "PCI: Not using MMCONFIG.\n"); - pci_mmcfg_arch_free(); - kfree(pci_mmcfg_config); - pci_mmcfg_config = NULL; - pci_mmcfg_config_num = 0; + printk(KERN_INFO PREFIX "not using MMCONFIG\n"); + free_all_mmcfg(); } static int __initdata known_bridge; -static int acpi_mcfg_64bit_base_addr __initdata = FALSE; +static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg, + struct acpi_mcfg_allocation *cfg) +{ + int year; -/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ -struct acpi_mcfg_allocation *pci_mmcfg_config; -int pci_mmcfg_config_num; + if (cfg->address < 0xFFFFFFFF) + return 0; -static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg) -{ if (!strcmp(mcfg->header.oem_id, "SGI")) - acpi_mcfg_64bit_base_addr = TRUE; + return 0; - return 0; + if (mcfg->header.revision >= 1) { + if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && + year >= 2010) + return 0; + } + + printk(KERN_ERR PREFIX "MCFG region for %04x [bus %02x-%02x] at %#llx " + "is above 4GB, ignored\n", cfg->pci_segment, + cfg->start_bus_number, cfg->end_bus_number, cfg->address); + return -EINVAL; } static int __init pci_parse_mcfg(struct acpi_table_header *header) { struct acpi_table_mcfg *mcfg; + struct acpi_mcfg_allocation *cfg_table, *cfg; unsigned long i; - int config_size; + int entries; if (!header) return -EINVAL; @@ -553,38 +552,33 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header) mcfg = (struct acpi_table_mcfg *)header; /* how many config structures do we have */ - pci_mmcfg_config_num = 0; + free_all_mmcfg(); + entries = 0; i = header->length - sizeof(struct acpi_table_mcfg); while (i >= sizeof(struct acpi_mcfg_allocation)) { - ++pci_mmcfg_config_num; + entries++; i -= sizeof(struct acpi_mcfg_allocation); }; - if (pci_mmcfg_config_num == 0) { + if (entries == 0) { printk(KERN_ERR PREFIX "MMCONFIG has no entries\n"); return -ENODEV; } - config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config); - pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL); - if (!pci_mmcfg_config) { - printk(KERN_WARNING PREFIX - "No memory for MCFG config tables\n"); - return -ENOMEM; - } - - memcpy(pci_mmcfg_config, &mcfg[1], config_size); - - acpi_mcfg_oem_check(mcfg); - - for (i = 0; i < pci_mmcfg_config_num; ++i) { - if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) && - !acpi_mcfg_64bit_base_addr) { - printk(KERN_ERR PREFIX - "MMCONFIG not in low 4GB of memory\n"); - kfree(pci_mmcfg_config); - pci_mmcfg_config_num = 0; + cfg_table = (struct acpi_mcfg_allocation *) &mcfg[1]; + for (i = 0; i < entries; i++) { + cfg = &cfg_table[i]; + if (acpi_mcfg_check_entry(mcfg, cfg)) { + free_all_mmcfg(); return -ENODEV; } + + if (pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number, + cfg->end_bus_number, cfg->address) == NULL) { + printk(KERN_WARNING PREFIX + "no memory for MCFG entries\n"); + free_all_mmcfg(); + return -ENOMEM; + } } return 0; @@ -614,9 +608,7 @@ static void __init __pci_mmcfg_init(int early) pci_mmcfg_reject_broken(early); - if ((pci_mmcfg_config_num == 0) || - (pci_mmcfg_config == NULL) || - (pci_mmcfg_config[0].address == 0)) + if (list_empty(&pci_mmcfg_list)) return; if (pci_mmcfg_arch_init()) @@ -648,9 +640,7 @@ static int __init pci_mmcfg_late_insert_resources(void) */ if ((pci_mmcfg_resources_inserted == 1) || (pci_probe & PCI_PROBE_MMCONF) == 0 || - (pci_mmcfg_config_num == 0) || - (pci_mmcfg_config == NULL) || - (pci_mmcfg_config[0].address == 0)) + list_empty(&pci_mmcfg_list)) return 1; /* diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c index f10a7e94a84c51d9b87a041a19b3c7b89b283d8b..90d5fd476ed4fe3a093b514f095ca3d237023f54 100644 --- a/arch/x86/pci/mmconfig_32.c +++ b/arch/x86/pci/mmconfig_32.c @@ -27,18 +27,10 @@ static int mmcfg_last_accessed_cpu; */ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) { - struct acpi_mcfg_allocation *cfg; - int cfg_num; - - for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) { - cfg = &pci_mmcfg_config[cfg_num]; - if (cfg->pci_segment == seg && - (cfg->start_bus_number <= bus) && - (cfg->end_bus_number >= bus)) - return cfg->address; - } + struct pci_mmcfg_region *cfg = pci_mmconfig_lookup(seg, bus); - /* Fall back to type 0 */ + if (cfg) + return cfg->address; return 0; } @@ -47,7 +39,7 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) */ static void pci_exp_set_dev_base(unsigned int base, int bus, int devfn) { - u32 dev_base = base | (bus << 20) | (devfn << 12); + u32 dev_base = base | PCI_MMCFG_BUS_OFFSET(bus) | (devfn << 12); int cpu = smp_processor_id(); if (dev_base != mmcfg_last_accessed_device || cpu != mmcfg_last_accessed_cpu) { diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c index 94349f8b2f964b969f7cc576ad92a50cfac75049..e783841bd1d7c42ea8ca4607d884ffe1e65ba97f 100644 --- a/arch/x86/pci/mmconfig_64.c +++ b/arch/x86/pci/mmconfig_64.c @@ -12,38 +12,15 @@ #include #include -/* Static virtual mapping of the MMCONFIG aperture */ -struct mmcfg_virt { - struct acpi_mcfg_allocation *cfg; - char __iomem *virt; -}; -static struct mmcfg_virt *pci_mmcfg_virt; - -static char __iomem *get_virt(unsigned int seg, unsigned bus) -{ - struct acpi_mcfg_allocation *cfg; - int cfg_num; - - for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) { - cfg = pci_mmcfg_virt[cfg_num].cfg; - if (cfg->pci_segment == seg && - (cfg->start_bus_number <= bus) && - (cfg->end_bus_number >= bus)) - return pci_mmcfg_virt[cfg_num].virt; - } - - /* Fall back to type 0 */ - return NULL; -} +#define PREFIX "PCI: " static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) { - char __iomem *addr; + struct pci_mmcfg_region *cfg = pci_mmconfig_lookup(seg, bus); - addr = get_virt(seg, bus); - if (!addr) - return NULL; - return addr + ((bus << 20) | (devfn << 12)); + if (cfg && cfg->virt) + return cfg->virt + (PCI_MMCFG_BUS_OFFSET(bus) | (devfn << 12)); + return NULL; } static int pci_mmcfg_read(unsigned int seg, unsigned int bus, @@ -109,42 +86,30 @@ static struct pci_raw_ops pci_mmcfg = { .write = pci_mmcfg_write, }; -static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg) +static void __iomem * __init mcfg_ioremap(struct pci_mmcfg_region *cfg) { void __iomem *addr; u64 start, size; + int num_buses; - start = cfg->start_bus_number; - start <<= 20; - start += cfg->address; - size = cfg->end_bus_number + 1 - cfg->start_bus_number; - size <<= 20; + start = cfg->address + PCI_MMCFG_BUS_OFFSET(cfg->start_bus); + num_buses = cfg->end_bus - cfg->start_bus + 1; + size = PCI_MMCFG_BUS_OFFSET(num_buses); addr = ioremap_nocache(start, size); - if (addr) { - printk(KERN_INFO "PCI: Using MMCONFIG at %Lx - %Lx\n", - start, start + size - 1); - addr -= cfg->start_bus_number << 20; - } + if (addr) + addr -= PCI_MMCFG_BUS_OFFSET(cfg->start_bus); return addr; } int __init pci_mmcfg_arch_init(void) { - int i; - pci_mmcfg_virt = kzalloc(sizeof(*pci_mmcfg_virt) * - pci_mmcfg_config_num, GFP_KERNEL); - if (pci_mmcfg_virt == NULL) { - printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n"); - return 0; - } + struct pci_mmcfg_region *cfg; - for (i = 0; i < pci_mmcfg_config_num; ++i) { - pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i]; - pci_mmcfg_virt[i].virt = mcfg_ioremap(&pci_mmcfg_config[i]); - if (!pci_mmcfg_virt[i].virt) { - printk(KERN_ERR "PCI: Cannot map mmconfig aperture for " - "segment %d\n", - pci_mmcfg_config[i].pci_segment); + list_for_each_entry(cfg, &pci_mmcfg_list, list) { + cfg->virt = mcfg_ioremap(cfg); + if (!cfg->virt) { + printk(KERN_ERR PREFIX "can't map MMCONFIG at %pR\n", + &cfg->res); pci_mmcfg_arch_free(); return 0; } @@ -155,19 +120,12 @@ int __init pci_mmcfg_arch_init(void) void __init pci_mmcfg_arch_free(void) { - int i; - - if (pci_mmcfg_virt == NULL) - return; + struct pci_mmcfg_region *cfg; - for (i = 0; i < pci_mmcfg_config_num; ++i) { - if (pci_mmcfg_virt[i].virt) { - iounmap(pci_mmcfg_virt[i].virt + (pci_mmcfg_virt[i].cfg->start_bus_number << 20)); - pci_mmcfg_virt[i].virt = NULL; - pci_mmcfg_virt[i].cfg = NULL; + list_for_each_entry(cfg, &pci_mmcfg_list, list) { + if (cfg->virt) { + iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus)); + cfg->virt = NULL; } } - - kfree(pci_mmcfg_virt); - pci_mmcfg_virt = NULL; } diff --git a/arch/x86/tools/test_get_len.c b/arch/x86/tools/test_get_len.c index d8214dc03fa7a46e4dc2c9408b8674a13017e1e0..bee8d6ac2691769b127439afdf60582b4260563c 100644 --- a/arch/x86/tools/test_get_len.c +++ b/arch/x86/tools/test_get_len.c @@ -113,7 +113,7 @@ int main(int argc, char **argv) char line[BUFSIZE], sym[BUFSIZE] = ""; unsigned char insn_buf[16]; struct insn insn; - int insns = 0, c; + int insns = 0; int warnings = 0; parse_args(argc, argv); diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index c462cea8ef095f10d5a3c70877c43edc45954406..2b26dd5930c6e82e87f0e20505ab5954e6213a83 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -27,7 +27,9 @@ #include #include #include +#include +#include #include #include #include @@ -138,24 +140,23 @@ static void xen_vcpu_setup(int cpu) */ void xen_vcpu_restore(void) { - if (have_vcpu_info_placement) { - int cpu; + int cpu; - for_each_online_cpu(cpu) { - bool other_cpu = (cpu != smp_processor_id()); + for_each_online_cpu(cpu) { + bool other_cpu = (cpu != smp_processor_id()); - if (other_cpu && - HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL)) - BUG(); + if (other_cpu && + HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL)) + BUG(); - xen_vcpu_setup(cpu); + xen_setup_runstate_info(cpu); - if (other_cpu && - HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL)) - BUG(); - } + if (have_vcpu_info_placement) + xen_vcpu_setup(cpu); - BUG_ON(!have_vcpu_info_placement); + if (other_cpu && + HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL)) + BUG(); } } @@ -1176,10 +1177,16 @@ asmlinkage void __init xen_start_kernel(void) add_preferred_console("xenboot", 0, NULL); add_preferred_console("tty", 0, NULL); add_preferred_console("hvc", 0, NULL); + } else { + /* Make sure ACS will be enabled */ + pci_request_acs(); } + xen_raw_console_write("about to get started...\n"); + xen_setup_runstate_info(0); + /* Start the world */ #ifdef CONFIG_X86_32 i386_start_kernel(); diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 3bf7b1d250ce986d02bc44de0bd2086f6e37b824..bf4cd6bfe959f1037431668c71a263050098f35a 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -185,7 +185,7 @@ static inline unsigned p2m_index(unsigned long pfn) } /* Build the parallel p2m_top_mfn structures */ -static void __init xen_build_mfn_list_list(void) +void xen_build_mfn_list_list(void) { unsigned pfn, idx; diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 738da0cb0d8b0622d1fba7decf51f54692a32da7..563d20504988ef7671cf600cdc2762f00418a4c8 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -35,10 +35,10 @@ cpumask_var_t xen_cpu_initialized_map; -static DEFINE_PER_CPU(int, resched_irq); -static DEFINE_PER_CPU(int, callfunc_irq); -static DEFINE_PER_CPU(int, callfuncsingle_irq); -static DEFINE_PER_CPU(int, debug_irq) = -1; +static DEFINE_PER_CPU(int, xen_resched_irq); +static DEFINE_PER_CPU(int, xen_callfunc_irq); +static DEFINE_PER_CPU(int, xen_callfuncsingle_irq); +static DEFINE_PER_CPU(int, xen_debug_irq) = -1; static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id); static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id); @@ -103,7 +103,7 @@ static int xen_smp_intr_init(unsigned int cpu) NULL); if (rc < 0) goto fail; - per_cpu(resched_irq, cpu) = rc; + per_cpu(xen_resched_irq, cpu) = rc; callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu); rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR, @@ -114,7 +114,7 @@ static int xen_smp_intr_init(unsigned int cpu) NULL); if (rc < 0) goto fail; - per_cpu(callfunc_irq, cpu) = rc; + per_cpu(xen_callfunc_irq, cpu) = rc; debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu); rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt, @@ -122,7 +122,7 @@ static int xen_smp_intr_init(unsigned int cpu) debug_name, NULL); if (rc < 0) goto fail; - per_cpu(debug_irq, cpu) = rc; + per_cpu(xen_debug_irq, cpu) = rc; callfunc_name = kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu); rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR, @@ -133,19 +133,20 @@ static int xen_smp_intr_init(unsigned int cpu) NULL); if (rc < 0) goto fail; - per_cpu(callfuncsingle_irq, cpu) = rc; + per_cpu(xen_callfuncsingle_irq, cpu) = rc; return 0; fail: - if (per_cpu(resched_irq, cpu) >= 0) - unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL); - if (per_cpu(callfunc_irq, cpu) >= 0) - unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL); - if (per_cpu(debug_irq, cpu) >= 0) - unbind_from_irqhandler(per_cpu(debug_irq, cpu), NULL); - if (per_cpu(callfuncsingle_irq, cpu) >= 0) - unbind_from_irqhandler(per_cpu(callfuncsingle_irq, cpu), NULL); + if (per_cpu(xen_resched_irq, cpu) >= 0) + unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu), NULL); + if (per_cpu(xen_callfunc_irq, cpu) >= 0) + unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL); + if (per_cpu(xen_debug_irq, cpu) >= 0) + unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL); + if (per_cpu(xen_callfuncsingle_irq, cpu) >= 0) + unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), + NULL); return rc; } @@ -295,6 +296,7 @@ static int __cpuinit xen_cpu_up(unsigned int cpu) (unsigned long)task_stack_page(idle) - KERNEL_STACK_OFFSET + THREAD_SIZE; #endif + xen_setup_runstate_info(cpu); xen_setup_timer(cpu); xen_init_lock_cpu(cpu); @@ -348,10 +350,10 @@ static void xen_cpu_die(unsigned int cpu) current->state = TASK_UNINTERRUPTIBLE; schedule_timeout(HZ/10); } - unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL); - unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL); - unbind_from_irqhandler(per_cpu(debug_irq, cpu), NULL); - unbind_from_irqhandler(per_cpu(callfuncsingle_irq, cpu), NULL); + unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu), NULL); + unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL); + unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL); + unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL); xen_uninit_lock_cpu(cpu); xen_teardown_timer(cpu); diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c index 95be7b434724c5067214dc416367633c522a69bb..987267f79bf5154648cb729cedf29e712fa58ab3 100644 --- a/arch/x86/xen/suspend.c +++ b/arch/x86/xen/suspend.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -27,6 +28,8 @@ void xen_pre_suspend(void) void xen_post_suspend(int suspend_cancelled) { + xen_build_mfn_list_list(); + xen_setup_shared_info(); if (suspend_cancelled) { @@ -44,7 +47,19 @@ void xen_post_suspend(int suspend_cancelled) } +static void xen_vcpu_notify_restore(void *data) +{ + unsigned long reason = (unsigned long)data; + + /* Boot processor notified via generic timekeeping_resume() */ + if ( smp_processor_id() == 0) + return; + + clockevents_notify(reason, NULL); +} + void xen_arch_resume(void) { - /* nothing */ + smp_call_function(xen_vcpu_notify_restore, + (void *)CLOCK_EVT_NOTIFY_RESUME, 1); } diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 0a5aa44299a51fac214833fe00c68d947ee92367..0d3f07cd1b5fe9aee977674b11b0beb311e25eb0 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -31,14 +31,14 @@ #define NS_PER_TICK (1000000000LL / HZ) /* runstate info updated by Xen */ -static DEFINE_PER_CPU(struct vcpu_runstate_info, runstate); +static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate); /* snapshots of runstate info */ -static DEFINE_PER_CPU(struct vcpu_runstate_info, runstate_snapshot); +static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate_snapshot); /* unused ns of stolen and blocked time */ -static DEFINE_PER_CPU(u64, residual_stolen); -static DEFINE_PER_CPU(u64, residual_blocked); +static DEFINE_PER_CPU(u64, xen_residual_stolen); +static DEFINE_PER_CPU(u64, xen_residual_blocked); /* return an consistent snapshot of 64-bit time/counter value */ static u64 get64(const u64 *p) @@ -79,7 +79,7 @@ static void get_runstate_snapshot(struct vcpu_runstate_info *res) BUG_ON(preemptible()); - state = &__get_cpu_var(runstate); + state = &__get_cpu_var(xen_runstate); /* * The runstate info is always updated by the hypervisor on @@ -97,14 +97,14 @@ static void get_runstate_snapshot(struct vcpu_runstate_info *res) /* return true when a vcpu could run but has no real cpu to run on */ bool xen_vcpu_stolen(int vcpu) { - return per_cpu(runstate, vcpu).state == RUNSTATE_runnable; + return per_cpu(xen_runstate, vcpu).state == RUNSTATE_runnable; } -static void setup_runstate_info(int cpu) +void xen_setup_runstate_info(int cpu) { struct vcpu_register_runstate_memory_area area; - area.addr.v = &per_cpu(runstate, cpu); + area.addr.v = &per_cpu(xen_runstate, cpu); if (HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, cpu, &area)) @@ -122,7 +122,7 @@ static void do_stolen_accounting(void) WARN_ON(state.state != RUNSTATE_running); - snap = &__get_cpu_var(runstate_snapshot); + snap = &__get_cpu_var(xen_runstate_snapshot); /* work out how much time the VCPU has not been runn*ing* */ blocked = state.time[RUNSTATE_blocked] - snap->time[RUNSTATE_blocked]; @@ -133,24 +133,24 @@ static void do_stolen_accounting(void) /* Add the appropriate number of ticks of stolen time, including any left-overs from last time. */ - stolen = runnable + offline + __get_cpu_var(residual_stolen); + stolen = runnable + offline + __get_cpu_var(xen_residual_stolen); if (stolen < 0) stolen = 0; ticks = iter_div_u64_rem(stolen, NS_PER_TICK, &stolen); - __get_cpu_var(residual_stolen) = stolen; + __get_cpu_var(xen_residual_stolen) = stolen; account_steal_ticks(ticks); /* Add the appropriate number of ticks of blocked time, including any left-overs from last time. */ - blocked += __get_cpu_var(residual_blocked); + blocked += __get_cpu_var(xen_residual_blocked); if (blocked < 0) blocked = 0; ticks = iter_div_u64_rem(blocked, NS_PER_TICK, &blocked); - __get_cpu_var(residual_blocked) = blocked; + __get_cpu_var(xen_residual_blocked) = blocked; account_idle_ticks(ticks); } @@ -434,7 +434,7 @@ void xen_setup_timer(int cpu) name = ""; irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt, - IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, + IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER, name, NULL); evt = &per_cpu(xen_clock_events, cpu); @@ -442,8 +442,6 @@ void xen_setup_timer(int cpu) evt->cpumask = cpumask_of(cpu); evt->irq = irq; - - setup_runstate_info(cpu); } void xen_teardown_timer(int cpu) @@ -494,6 +492,7 @@ __init void xen_time_init(void) setup_force_cpu_cap(X86_FEATURE_TSC); + xen_setup_runstate_info(cpu); xen_setup_timer(cpu); xen_setup_cpu_clockevents(); } diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S index 02f496a8dbaa250d40f843456b8ac10fc183fe14..53adefda4275330a810b6d883b6ad8b58a72730c 100644 --- a/arch/x86/xen/xen-asm_64.S +++ b/arch/x86/xen/xen-asm_64.S @@ -96,7 +96,7 @@ ENTRY(xen_sysret32) pushq $__USER32_CS pushq %rcx - pushq $VGCF_in_syscall + pushq $0 1: jmp hypercall_iret ENDPATCH(xen_sysret32) RELOC(xen_sysret32, 1b+1) @@ -151,7 +151,7 @@ ENTRY(xen_syscall32_target) ENTRY(xen_sysenter_target) lea 16(%rsp), %rsp /* strip %rcx, %r11 */ mov $-ENOSYS, %rax - pushq $VGCF_in_syscall + pushq $0 jmp hypercall_iret ENDPROC(xen_syscall32_target) ENDPROC(xen_sysenter_target) diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 355fa6b99c9c402e80d8443d2b94647436062c7a..f9153a300bcee998e1f78f95a202cc9036df79ca 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -25,6 +25,7 @@ extern struct shared_info *HYPERVISOR_shared_info; void xen_setup_mfn_list_list(void); void xen_setup_shared_info(void); +void xen_build_mfn_list_list(void); void xen_setup_machphys_mapping(void); pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn); void xen_ident_map_ISA(void); @@ -41,6 +42,7 @@ void __init xen_build_dynamic_phys_to_machine(void); void xen_init_irq_ops(void); void xen_setup_timer(int cpu); +void xen_setup_runstate_info(int cpu); void xen_teardown_timer(int cpu); cycle_t xen_clocksource_read(void); void xen_setup_cpu_clockevents(void); diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h index 05cebf8f62b195f7c86ffd601d0331cb65a29d1b..4352dbe1186ae07d571abe2c1031f94e73df24ac 100644 --- a/arch/xtensa/include/asm/syscall.h +++ b/arch/xtensa/include/asm/syscall.h @@ -13,8 +13,6 @@ struct sigaction; asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*); asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*); asmlinkage long xtensa_pipe(int __user *); -asmlinkage long xtensa_mmap2(unsigned long, unsigned long, unsigned long, - unsigned long, unsigned long, unsigned long); asmlinkage long xtensa_ptrace(long, long, long, long); asmlinkage long xtensa_sigreturn(struct pt_regs*); asmlinkage long xtensa_rt_sigreturn(struct pt_regs*); diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h index 4e55dc763021376d8dde31d4c333dd0ca4c495bc..fbf318b3af3e3b688515e7b4e26dd5d0097ef1ff 100644 --- a/arch/xtensa/include/asm/unistd.h +++ b/arch/xtensa/include/asm/unistd.h @@ -189,7 +189,7 @@ __SYSCALL( 79, sys_fremovexattr, 2) /* File Map / Shared Memory Operations */ #define __NR_mmap2 80 -__SYSCALL( 80, xtensa_mmap2, 6) +__SYSCALL( 80, sys_mmap_pgoff, 6) #define __NR_munmap 81 __SYSCALL( 81, sys_munmap, 2) #define __NR_mprotect 82 diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c index ac15ecbdf9199871f3e31ef7e013fd62e1ce3b06..1e67bab775c18fc47a79d6701c30264d20350377 100644 --- a/arch/xtensa/kernel/syscall.c +++ b/arch/xtensa/kernel/syscall.c @@ -57,31 +57,6 @@ asmlinkage long xtensa_pipe(int __user *userfds) return error; } - -asmlinkage long xtensa_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg) { unsigned long ret; diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index 4c559cf7da2d8c13c0a0529f5ae2e458b65257d1..e60a1f57022f358a6ca1e61119ed8e71f547bcbf 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -196,7 +196,7 @@ static const struct file_operations rs_proc_fops = { .release = single_release, }; -static struct tty_operations serial_ops = { +static const struct tty_operations serial_ops = { .open = rs_open, .close = rs_close, .write = rs_write, diff --git a/crypto/cryptd.c b/crypto/cryptd.c index f8ae0d94a6471e0703bfc24900f88dfeb1fc8be7..704c141153236917288ee7a09c12ce8b037754d8 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -99,7 +99,7 @@ static int cryptd_enqueue_request(struct cryptd_queue *queue, struct cryptd_cpu_queue *cpu_queue; cpu = get_cpu(); - cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu); + cpu_queue = this_cpu_ptr(queue->cpu_queue); err = crypto_enqueue_request(&cpu_queue->queue, request); queue_work_on(cpu, kcrypto_wq, &cpu_queue->work); put_cpu(); diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 7702118509a0a6e848bee454a983f0ec42e9522b..c7b10b4298e991320cd45af4fcc5168118d4e4b3 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -19,6 +19,7 @@ obj-y += acpi.o \ # All the builtin files are in the "acpi." module_param namespace. acpi-y += osl.o utils.o reboot.o +acpi-y += hest.o # sleep related files acpi-y += wakeup.o diff --git a/drivers/acpi/hest.c b/drivers/acpi/hest.c new file mode 100644 index 0000000000000000000000000000000000000000..4bb18c980ac6ec938408b46ee220108eff496985 --- /dev/null +++ b/drivers/acpi/hest.c @@ -0,0 +1,135 @@ +#include +#include + +#define PREFIX "ACPI: " + +static inline unsigned long parse_acpi_hest_ia_machine_check(struct acpi_hest_ia_machine_check *p) +{ + return sizeof(*p) + + (sizeof(struct acpi_hest_ia_error_bank) * p->num_hardware_banks); +} + +static inline unsigned long parse_acpi_hest_ia_corrected(struct acpi_hest_ia_corrected *p) +{ + return sizeof(*p) + + (sizeof(struct acpi_hest_ia_error_bank) * p->num_hardware_banks); +} + +static inline unsigned long parse_acpi_hest_ia_nmi(struct acpi_hest_ia_nmi *p) +{ + return sizeof(*p); +} + +static inline unsigned long parse_acpi_hest_generic(struct acpi_hest_generic *p) +{ + return sizeof(*p); +} + +static inline unsigned int hest_match_pci(struct acpi_hest_aer_common *p, struct pci_dev *pci) +{ + return (0 == pci_domain_nr(pci->bus) && + p->bus == pci->bus->number && + p->device == PCI_SLOT(pci->devfn) && + p->function == PCI_FUNC(pci->devfn)); +} + +static unsigned long parse_acpi_hest_aer(void *hdr, int type, struct pci_dev *pci, int *firmware_first) +{ + struct acpi_hest_aer_common *p = hdr + sizeof(struct acpi_hest_header); + unsigned long rc=0; + u8 pcie_type = 0; + u8 bridge = 0; + switch (type) { + case ACPI_HEST_TYPE_AER_ROOT_PORT: + rc = sizeof(struct acpi_hest_aer_root); + pcie_type = PCI_EXP_TYPE_ROOT_PORT; + break; + case ACPI_HEST_TYPE_AER_ENDPOINT: + rc = sizeof(struct acpi_hest_aer); + pcie_type = PCI_EXP_TYPE_ENDPOINT; + break; + case ACPI_HEST_TYPE_AER_BRIDGE: + rc = sizeof(struct acpi_hest_aer_bridge); + if ((pci->class >> 16) == PCI_BASE_CLASS_BRIDGE) + bridge = 1; + break; + } + + if (p->flags & ACPI_HEST_GLOBAL) { + if ((pci->is_pcie && (pci->pcie_type == pcie_type)) || bridge) + *firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); + } + else + if (hest_match_pci(p, pci)) + *firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); + return rc; +} + +static int acpi_hest_firmware_first(struct acpi_table_header *stdheader, struct pci_dev *pci) +{ + struct acpi_table_hest *hest = (struct acpi_table_hest *)stdheader; + void *p = (void *)hest + sizeof(*hest); /* defined by the ACPI 4.0 spec */ + struct acpi_hest_header *hdr = p; + + int i; + int firmware_first = 0; + static unsigned char printed_unused = 0; + static unsigned char printed_reserved = 0; + + for (i=0, hdr=p; p < (((void *)hest) + hest->header.length) && i < hest->error_source_count; i++) { + switch (hdr->type) { + case ACPI_HEST_TYPE_IA32_CHECK: + p += parse_acpi_hest_ia_machine_check(p); + break; + case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: + p += parse_acpi_hest_ia_corrected(p); + break; + case ACPI_HEST_TYPE_IA32_NMI: + p += parse_acpi_hest_ia_nmi(p); + break; + /* These three should never appear */ + case ACPI_HEST_TYPE_NOT_USED3: + case ACPI_HEST_TYPE_NOT_USED4: + case ACPI_HEST_TYPE_NOT_USED5: + if (!printed_unused) { + printk(KERN_DEBUG PREFIX + "HEST Error Source list contains an obsolete type (%d).\n", hdr->type); + printed_unused = 1; + } + break; + case ACPI_HEST_TYPE_AER_ROOT_PORT: + case ACPI_HEST_TYPE_AER_ENDPOINT: + case ACPI_HEST_TYPE_AER_BRIDGE: + p += parse_acpi_hest_aer(p, hdr->type, pci, &firmware_first); + break; + case ACPI_HEST_TYPE_GENERIC_ERROR: + p += parse_acpi_hest_generic(p); + break; + /* These should never appear either */ + case ACPI_HEST_TYPE_RESERVED: + default: + if (!printed_reserved) { + printk(KERN_DEBUG PREFIX + "HEST Error Source list contains a reserved type (%d).\n", hdr->type); + printed_reserved = 1; + } + break; + } + } + return firmware_first; +} + +int acpi_hest_firmware_first_pci(struct pci_dev *pci) +{ + acpi_status status = AE_NOT_FOUND; + struct acpi_table_header *hest = NULL; + status = acpi_get_table(ACPI_SIG_HEST, 1, &hest); + + if (ACPI_SUCCESS(status)) { + if (acpi_hest_firmware_first(hest, pci)) { + return 1; + } + } + return 0; +} +EXPORT_SYMBOL_GPL(acpi_hest_firmware_first_pci); diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 8ba0ed0b9ddbc912684d398e2eda14357920aed4..01e366d2b6fb14475e0b6074b886fd8b55877348 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -167,6 +167,19 @@ int acpi_processor_ppc_has_changed(struct acpi_processor *pr) return cpufreq_update_policy(pr->id); } +int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) +{ + struct acpi_processor *pr; + + pr = per_cpu(processors, cpu); + if (!pr || !pr->performance || !pr->performance->state_count) + return -ENODEV; + *limit = pr->performance->states[pr->performance_platform_limit]. + core_frequency * 1000; + return 0; +} +EXPORT_SYMBOL(acpi_processor_get_bios_limit); + void acpi_processor_ppc_init(void) { if (!cpufreq_register_notifier diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 676f08b004b31c18e73e5a624d0dec1febba0d90..85844d053846fbed820ab8fb22a4db8b7cfc57ee 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -790,5 +790,15 @@ config PATA_BF54X If unsure, say N. +config PATA_MACIO + tristate "Apple PowerMac/PowerBook internal 'MacIO' IDE" + depends on PPC_PMAC + help + Most IDE capable PowerMacs have IDE busses driven by a variant + of this controller which is part of the Apple chipset used on + most PowerMac models. Some models have multiple busses using + different chipsets, though generally, MacIO is one of them. + + endif # ATA_SFF endif # ATA diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index d909435e9d817528d2dbbece5ff74d58573f826c..fc936d4471d62bb70dbf8431919c7576479a15ac 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_SATA_MV) += sata_mv.o obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o obj-$(CONFIG_PDC_ADMA) += pdc_adma.o obj-$(CONFIG_SATA_FSL) += sata_fsl.o +obj-$(CONFIG_PATA_MACIO) += pata_macio.o obj-$(CONFIG_PATA_ALI) += pata_ali.o obj-$(CONFIG_PATA_AMD) += pata_amd.o diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c new file mode 100644 index 0000000000000000000000000000000000000000..4cc7bbd10ec20d441311b655ee1323801bfcb7c3 --- /dev/null +++ b/drivers/ata/pata_macio.c @@ -0,0 +1,1427 @@ +/* + * Libata based driver for Apple "macio" family of PATA controllers + * + * Copyright 2008/2009 Benjamin Herrenschmidt, IBM Corp + * + * + * Some bits and pieces from drivers/ide/ppc/pmac.c + * + */ + +#undef DEBUG +#undef DEBUG_DMA + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG_DMA +#define dev_dbgdma(dev, format, arg...) \ + dev_printk(KERN_DEBUG , dev , format , ## arg) +#else +#define dev_dbgdma(dev, format, arg...) \ + ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; }) +#endif + +#define DRV_NAME "pata_macio" +#define DRV_VERSION "0.9" + +/* Models of macio ATA controller */ +enum { + controller_ohare, /* OHare based */ + controller_heathrow, /* Heathrow/Paddington */ + controller_kl_ata3, /* KeyLargo ATA-3 */ + controller_kl_ata4, /* KeyLargo ATA-4 */ + controller_un_ata6, /* UniNorth2 ATA-6 */ + controller_k2_ata6, /* K2 ATA-6 */ + controller_sh_ata6, /* Shasta ATA-6 */ +}; + +static const char* macio_ata_names[] = { + "OHare ATA", /* OHare based */ + "Heathrow ATA", /* Heathrow/Paddington */ + "KeyLargo ATA-3", /* KeyLargo ATA-3 (MDMA only) */ + "KeyLargo ATA-4", /* KeyLargo ATA-4 (UDMA/66) */ + "UniNorth ATA-6", /* UniNorth2 ATA-6 (UDMA/100) */ + "K2 ATA-6", /* K2 ATA-6 (UDMA/100) */ + "Shasta ATA-6", /* Shasta ATA-6 (UDMA/133) */ +}; + +/* + * Extra registers, both 32-bit little-endian + */ +#define IDE_TIMING_CONFIG 0x200 +#define IDE_INTERRUPT 0x300 + +/* Kauai (U2) ATA has different register setup */ +#define IDE_KAUAI_PIO_CONFIG 0x200 +#define IDE_KAUAI_ULTRA_CONFIG 0x210 +#define IDE_KAUAI_POLL_CONFIG 0x220 + +/* + * Timing configuration register definitions + */ + +/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */ +#define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS) +#define SYSCLK_TICKS_66(t) (((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS) +#define IDE_SYSCLK_NS 30 /* 33Mhz cell */ +#define IDE_SYSCLK_66_NS 15 /* 66Mhz cell */ + +/* 133Mhz cell, found in shasta. + * See comments about 100 Mhz Uninorth 2... + * Note that PIO_MASK and MDMA_MASK seem to overlap, that's just + * weird and I don't now why .. at this stage + */ +#define TR_133_PIOREG_PIO_MASK 0xff000fff +#define TR_133_PIOREG_MDMA_MASK 0x00fff800 +#define TR_133_UDMAREG_UDMA_MASK 0x0003ffff +#define TR_133_UDMAREG_UDMA_EN 0x00000001 + +/* 100Mhz cell, found in Uninorth 2 and K2. It appears as a pci device + * (106b/0033) on uninorth or K2 internal PCI bus and it's clock is + * controlled like gem or fw. It appears to be an evolution of keylargo + * ATA4 with a timing register extended to 2x32bits registers (one + * for PIO & MWDMA and one for UDMA, and a similar DBDMA channel. + * It has it's own local feature control register as well. + * + * After scratching my mind over the timing values, at least for PIO + * and MDMA, I think I've figured the format of the timing register, + * though I use pre-calculated tables for UDMA as usual... + */ +#define TR_100_PIO_ADDRSETUP_MASK 0xff000000 /* Size of field unknown */ +#define TR_100_PIO_ADDRSETUP_SHIFT 24 +#define TR_100_MDMA_MASK 0x00fff000 +#define TR_100_MDMA_RECOVERY_MASK 0x00fc0000 +#define TR_100_MDMA_RECOVERY_SHIFT 18 +#define TR_100_MDMA_ACCESS_MASK 0x0003f000 +#define TR_100_MDMA_ACCESS_SHIFT 12 +#define TR_100_PIO_MASK 0xff000fff +#define TR_100_PIO_RECOVERY_MASK 0x00000fc0 +#define TR_100_PIO_RECOVERY_SHIFT 6 +#define TR_100_PIO_ACCESS_MASK 0x0000003f +#define TR_100_PIO_ACCESS_SHIFT 0 + +#define TR_100_UDMAREG_UDMA_MASK 0x0000ffff +#define TR_100_UDMAREG_UDMA_EN 0x00000001 + + +/* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on + * 40 connector cable and to 4 on 80 connector one. + * Clock unit is 15ns (66Mhz) + * + * 3 Values can be programmed: + * - Write data setup, which appears to match the cycle time. They + * also call it DIOW setup. + * - Ready to pause time (from spec) + * - Address setup. That one is weird. I don't see where exactly + * it fits in UDMA cycles, I got it's name from an obscure piece + * of commented out code in Darwin. They leave it to 0, we do as + * well, despite a comment that would lead to think it has a + * min value of 45ns. + * Apple also add 60ns to the write data setup (or cycle time ?) on + * reads. + */ +#define TR_66_UDMA_MASK 0xfff00000 +#define TR_66_UDMA_EN 0x00100000 /* Enable Ultra mode for DMA */ +#define TR_66_PIO_ADDRSETUP_MASK 0xe0000000 /* Address setup */ +#define TR_66_PIO_ADDRSETUP_SHIFT 29 +#define TR_66_UDMA_RDY2PAUS_MASK 0x1e000000 /* Ready 2 pause time */ +#define TR_66_UDMA_RDY2PAUS_SHIFT 25 +#define TR_66_UDMA_WRDATASETUP_MASK 0x01e00000 /* Write data setup time */ +#define TR_66_UDMA_WRDATASETUP_SHIFT 21 +#define TR_66_MDMA_MASK 0x000ffc00 +#define TR_66_MDMA_RECOVERY_MASK 0x000f8000 +#define TR_66_MDMA_RECOVERY_SHIFT 15 +#define TR_66_MDMA_ACCESS_MASK 0x00007c00 +#define TR_66_MDMA_ACCESS_SHIFT 10 +#define TR_66_PIO_MASK 0xe00003ff +#define TR_66_PIO_RECOVERY_MASK 0x000003e0 +#define TR_66_PIO_RECOVERY_SHIFT 5 +#define TR_66_PIO_ACCESS_MASK 0x0000001f +#define TR_66_PIO_ACCESS_SHIFT 0 + +/* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo + * Can do pio & mdma modes, clock unit is 30ns (33Mhz) + * + * The access time and recovery time can be programmed. Some older + * Darwin code base limit OHare to 150ns cycle time. I decided to do + * the same here fore safety against broken old hardware ;) + * The HalfTick bit, when set, adds half a clock (15ns) to the access + * time and removes one from recovery. It's not supported on KeyLargo + * implementation afaik. The E bit appears to be set for PIO mode 0 and + * is used to reach long timings used in this mode. + */ +#define TR_33_MDMA_MASK 0x003ff800 +#define TR_33_MDMA_RECOVERY_MASK 0x001f0000 +#define TR_33_MDMA_RECOVERY_SHIFT 16 +#define TR_33_MDMA_ACCESS_MASK 0x0000f800 +#define TR_33_MDMA_ACCESS_SHIFT 11 +#define TR_33_MDMA_HALFTICK 0x00200000 +#define TR_33_PIO_MASK 0x000007ff +#define TR_33_PIO_E 0x00000400 +#define TR_33_PIO_RECOVERY_MASK 0x000003e0 +#define TR_33_PIO_RECOVERY_SHIFT 5 +#define TR_33_PIO_ACCESS_MASK 0x0000001f +#define TR_33_PIO_ACCESS_SHIFT 0 + +/* + * Interrupt register definitions. Only present on newer cells + * (Keylargo and later afaik) so we don't use it. + */ +#define IDE_INTR_DMA 0x80000000 +#define IDE_INTR_DEVICE 0x40000000 + +/* + * FCR Register on Kauai. Not sure what bit 0x4 is ... + */ +#define KAUAI_FCR_UATA_MAGIC 0x00000004 +#define KAUAI_FCR_UATA_RESET_N 0x00000002 +#define KAUAI_FCR_UATA_ENABLE 0x00000001 + + +/* Allow up to 256 DBDMA commands per xfer */ +#define MAX_DCMDS 256 + +/* Don't let a DMA segment go all the way to 64K */ +#define MAX_DBDMA_SEG 0xff00 + + +/* + * Wait 1s for disk to answer on IDE bus after a hard reset + * of the device (via GPIO/FCR). + * + * Some devices seem to "pollute" the bus even after dropping + * the BSY bit (typically some combo drives slave on the UDMA + * bus) after a hard reset. Since we hard reset all drives on + * KeyLargo ATA66, we have to keep that delay around. I may end + * up not hard resetting anymore on these and keep the delay only + * for older interfaces instead (we have to reset when coming + * from MacOS...) --BenH. + */ +#define IDE_WAKEUP_DELAY_MS 1000 + +struct pata_macio_timing; + +struct pata_macio_priv { + int kind; + int aapl_bus_id; + int mediabay : 1; + struct device_node *node; + struct macio_dev *mdev; + struct pci_dev *pdev; + struct device *dev; + int irq; + u32 treg[2][2]; + void __iomem *tfregs; + void __iomem *kauai_fcr; + struct dbdma_cmd * dma_table_cpu; + dma_addr_t dma_table_dma; + struct ata_host *host; + const struct pata_macio_timing *timings; +}; + +/* Previous variants of this driver used to calculate timings + * for various variants of the chip and use tables for others. + * + * Not only was this confusing, but in addition, it isn't clear + * whether our calculation code was correct. It didn't entirely + * match the darwin code and whatever documentation I could find + * on these cells + * + * I decided to entirely rely on a table instead for this version + * of the driver. Also, because I don't really care about derated + * modes and really old HW other than making it work, I'm not going + * to calculate / snoop timing values for something else than the + * standard modes. + */ +struct pata_macio_timing { + int mode; + u32 reg1; /* Bits to set in first timing reg */ + u32 reg2; /* Bits to set in second timing reg */ +}; + +static const struct pata_macio_timing pata_macio_ohare_timings[] = { + { XFER_PIO_0, 0x00000526, 0, }, + { XFER_PIO_1, 0x00000085, 0, }, + { XFER_PIO_2, 0x00000025, 0, }, + { XFER_PIO_3, 0x00000025, 0, }, + { XFER_PIO_4, 0x00000025, 0, }, + { XFER_MW_DMA_0, 0x00074000, 0, }, + { XFER_MW_DMA_1, 0x00221000, 0, }, + { XFER_MW_DMA_2, 0x00211000, 0, }, + { -1, 0, 0 } +}; + +static const struct pata_macio_timing pata_macio_heathrow_timings[] = { + { XFER_PIO_0, 0x00000526, 0, }, + { XFER_PIO_1, 0x00000085, 0, }, + { XFER_PIO_2, 0x00000025, 0, }, + { XFER_PIO_3, 0x00000025, 0, }, + { XFER_PIO_4, 0x00000025, 0, }, + { XFER_MW_DMA_0, 0x00074000, 0, }, + { XFER_MW_DMA_1, 0x00221000, 0, }, + { XFER_MW_DMA_2, 0x00211000, 0, }, + { -1, 0, 0 } +}; + +static const struct pata_macio_timing pata_macio_kl33_timings[] = { + { XFER_PIO_0, 0x00000526, 0, }, + { XFER_PIO_1, 0x00000085, 0, }, + { XFER_PIO_2, 0x00000025, 0, }, + { XFER_PIO_3, 0x00000025, 0, }, + { XFER_PIO_4, 0x00000025, 0, }, + { XFER_MW_DMA_0, 0x00084000, 0, }, + { XFER_MW_DMA_1, 0x00021800, 0, }, + { XFER_MW_DMA_2, 0x00011800, 0, }, + { -1, 0, 0 } +}; + +static const struct pata_macio_timing pata_macio_kl66_timings[] = { + { XFER_PIO_0, 0x0000038c, 0, }, + { XFER_PIO_1, 0x0000020a, 0, }, + { XFER_PIO_2, 0x00000127, 0, }, + { XFER_PIO_3, 0x000000c6, 0, }, + { XFER_PIO_4, 0x00000065, 0, }, + { XFER_MW_DMA_0, 0x00084000, 0, }, + { XFER_MW_DMA_1, 0x00029800, 0, }, + { XFER_MW_DMA_2, 0x00019400, 0, }, + { XFER_UDMA_0, 0x19100000, 0, }, + { XFER_UDMA_1, 0x14d00000, 0, }, + { XFER_UDMA_2, 0x10900000, 0, }, + { XFER_UDMA_3, 0x0c700000, 0, }, + { XFER_UDMA_4, 0x0c500000, 0, }, + { -1, 0, 0 } +}; + +static const struct pata_macio_timing pata_macio_kauai_timings[] = { + { XFER_PIO_0, 0x08000a92, 0, }, + { XFER_PIO_1, 0x0800060f, 0, }, + { XFER_PIO_2, 0x0800038b, 0, }, + { XFER_PIO_3, 0x05000249, 0, }, + { XFER_PIO_4, 0x04000148, 0, }, + { XFER_MW_DMA_0, 0x00618000, 0, }, + { XFER_MW_DMA_1, 0x00209000, 0, }, + { XFER_MW_DMA_2, 0x00148000, 0, }, + { XFER_UDMA_0, 0, 0x000070c1, }, + { XFER_UDMA_1, 0, 0x00005d81, }, + { XFER_UDMA_2, 0, 0x00004a61, }, + { XFER_UDMA_3, 0, 0x00003a51, }, + { XFER_UDMA_4, 0, 0x00002a31, }, + { XFER_UDMA_5, 0, 0x00002921, }, + { -1, 0, 0 } +}; + +static const struct pata_macio_timing pata_macio_shasta_timings[] = { + { XFER_PIO_0, 0x0a000c97, 0, }, + { XFER_PIO_1, 0x07000712, 0, }, + { XFER_PIO_2, 0x040003cd, 0, }, + { XFER_PIO_3, 0x0500028b, 0, }, + { XFER_PIO_4, 0x0400010a, 0, }, + { XFER_MW_DMA_0, 0x00820800, 0, }, + { XFER_MW_DMA_1, 0x0028b000, 0, }, + { XFER_MW_DMA_2, 0x001ca000, 0, }, + { XFER_UDMA_0, 0, 0x00035901, }, + { XFER_UDMA_1, 0, 0x000348b1, }, + { XFER_UDMA_2, 0, 0x00033881, }, + { XFER_UDMA_3, 0, 0x00033861, }, + { XFER_UDMA_4, 0, 0x00033841, }, + { XFER_UDMA_5, 0, 0x00033031, }, + { XFER_UDMA_6, 0, 0x00033021, }, + { -1, 0, 0 } +}; + +static const struct pata_macio_timing *pata_macio_find_timing( + struct pata_macio_priv *priv, + int mode) +{ + int i; + + for (i = 0; priv->timings[i].mode > 0; i++) { + if (priv->timings[i].mode == mode) + return &priv->timings[i]; + } + return NULL; +} + + +static void pata_macio_apply_timings(struct ata_port *ap, unsigned int device) +{ + struct pata_macio_priv *priv = ap->private_data; + void __iomem *rbase = ap->ioaddr.cmd_addr; + + if (priv->kind == controller_sh_ata6 || + priv->kind == controller_un_ata6 || + priv->kind == controller_k2_ata6) { + writel(priv->treg[device][0], rbase + IDE_KAUAI_PIO_CONFIG); + writel(priv->treg[device][1], rbase + IDE_KAUAI_ULTRA_CONFIG); + } else + writel(priv->treg[device][0], rbase + IDE_TIMING_CONFIG); +} + +static void pata_macio_dev_select(struct ata_port *ap, unsigned int device) +{ + ata_sff_dev_select(ap, device); + + /* Apply timings */ + pata_macio_apply_timings(ap, device); +} + +static void pata_macio_set_timings(struct ata_port *ap, + struct ata_device *adev) +{ + struct pata_macio_priv *priv = ap->private_data; + const struct pata_macio_timing *t; + + dev_dbg(priv->dev, "Set timings: DEV=%d,PIO=0x%x (%s),DMA=0x%x (%s)\n", + adev->devno, + adev->pio_mode, + ata_mode_string(ata_xfer_mode2mask(adev->pio_mode)), + adev->dma_mode, + ata_mode_string(ata_xfer_mode2mask(adev->dma_mode))); + + /* First clear timings */ + priv->treg[adev->devno][0] = priv->treg[adev->devno][1] = 0; + + /* Now get the PIO timings */ + t = pata_macio_find_timing(priv, adev->pio_mode); + if (t == NULL) { + dev_warn(priv->dev, "Invalid PIO timing requested: 0x%x\n", + adev->pio_mode); + t = pata_macio_find_timing(priv, XFER_PIO_0); + } + BUG_ON(t == NULL); + + /* PIO timings only ever use the first treg */ + priv->treg[adev->devno][0] |= t->reg1; + + /* Now get DMA timings */ + t = pata_macio_find_timing(priv, adev->dma_mode); + if (t == NULL || (t->reg1 == 0 && t->reg2 == 0)) { + dev_dbg(priv->dev, "DMA timing not set yet, using MW_DMA_0\n"); + t = pata_macio_find_timing(priv, XFER_MW_DMA_0); + } + BUG_ON(t == NULL); + + /* DMA timings can use both tregs */ + priv->treg[adev->devno][0] |= t->reg1; + priv->treg[adev->devno][1] |= t->reg2; + + dev_dbg(priv->dev, " -> %08x %08x\n", + priv->treg[adev->devno][0], + priv->treg[adev->devno][1]); + + /* Apply to hardware */ + pata_macio_apply_timings(ap, adev->devno); +} + +/* + * Blast some well known "safe" values to the timing registers at init or + * wakeup from sleep time, before we do real calculation + */ +static void pata_macio_default_timings(struct pata_macio_priv *priv) +{ + unsigned int value, value2 = 0; + + switch(priv->kind) { + case controller_sh_ata6: + value = 0x0a820c97; + value2 = 0x00033031; + break; + case controller_un_ata6: + case controller_k2_ata6: + value = 0x08618a92; + value2 = 0x00002921; + break; + case controller_kl_ata4: + value = 0x0008438c; + break; + case controller_kl_ata3: + value = 0x00084526; + break; + case controller_heathrow: + case controller_ohare: + default: + value = 0x00074526; + break; + } + priv->treg[0][0] = priv->treg[1][0] = value; + priv->treg[0][1] = priv->treg[1][1] = value2; +} + +static int pata_macio_cable_detect(struct ata_port *ap) +{ + struct pata_macio_priv *priv = ap->private_data; + + /* Get cable type from device-tree */ + if (priv->kind == controller_kl_ata4 || + priv->kind == controller_un_ata6 || + priv->kind == controller_k2_ata6 || + priv->kind == controller_sh_ata6) { + const char* cable = of_get_property(priv->node, "cable-type", + NULL); + struct device_node *root = of_find_node_by_path("/"); + const char *model = of_get_property(root, "model", NULL); + + if (cable && !strncmp(cable, "80-", 3)) { + /* Some drives fail to detect 80c cable in PowerBook + * These machine use proprietary short IDE cable + * anyway + */ + if (!strncmp(model, "PowerBook", 9)) + return ATA_CBL_PATA40_SHORT; + else + return ATA_CBL_PATA80; + } + } + + /* G5's seem to have incorrect cable type in device-tree. + * Let's assume they always have a 80 conductor cable, this seem to + * be always the case unless the user mucked around + */ + if (of_device_is_compatible(priv->node, "K2-UATA") || + of_device_is_compatible(priv->node, "shasta-ata")) + return ATA_CBL_PATA80; + + /* Anything else is 40 connectors */ + return ATA_CBL_PATA40; +} + +static void pata_macio_qc_prep(struct ata_queued_cmd *qc) +{ + unsigned int write = (qc->tf.flags & ATA_TFLAG_WRITE); + struct ata_port *ap = qc->ap; + struct pata_macio_priv *priv = ap->private_data; + struct scatterlist *sg; + struct dbdma_cmd *table; + unsigned int si, pi; + + dev_dbgdma(priv->dev, "%s: qc %p flags %lx, write %d dev %d\n", + __func__, qc, qc->flags, write, qc->dev->devno); + + if (!(qc->flags & ATA_QCFLAG_DMAMAP)) + return; + + table = (struct dbdma_cmd *) priv->dma_table_cpu; + + pi = 0; + for_each_sg(qc->sg, sg, qc->n_elem, si) { + u32 addr, sg_len, len; + + /* determine if physical DMA addr spans 64K boundary. + * Note h/w doesn't support 64-bit, so we unconditionally + * truncate dma_addr_t to u32. + */ + addr = (u32) sg_dma_address(sg); + sg_len = sg_dma_len(sg); + + while (sg_len) { + /* table overflow should never happen */ + BUG_ON (pi++ >= MAX_DCMDS); + + len = (sg_len < MAX_DBDMA_SEG) ? sg_len : MAX_DBDMA_SEG; + st_le16(&table->command, write ? OUTPUT_MORE: INPUT_MORE); + st_le16(&table->req_count, len); + st_le32(&table->phy_addr, addr); + table->cmd_dep = 0; + table->xfer_status = 0; + table->res_count = 0; + addr += len; + sg_len -= len; + ++table; + } + } + + /* Should never happen according to Tejun */ + BUG_ON(!pi); + + /* Convert the last command to an input/output */ + table--; + st_le16(&table->command, write ? OUTPUT_LAST: INPUT_LAST); + table++; + + /* Add the stop command to the end of the list */ + memset(table, 0, sizeof(struct dbdma_cmd)); + st_le16(&table->command, DBDMA_STOP); + + dev_dbgdma(priv->dev, "%s: %d DMA list entries\n", __func__, pi); +} + + +static void pata_macio_freeze(struct ata_port *ap) +{ + struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; + + if (dma_regs) { + unsigned int timeout = 1000000; + + /* Make sure DMA controller is stopped */ + writel((RUN|PAUSE|FLUSH|WAKE|DEAD) << 16, &dma_regs->control); + while (--timeout && (readl(&dma_regs->status) & RUN)) + udelay(1); + } + + ata_sff_freeze(ap); +} + + +static void pata_macio_bmdma_setup(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct pata_macio_priv *priv = ap->private_data; + struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; + int dev = qc->dev->devno; + + dev_dbgdma(priv->dev, "%s: qc %p\n", __func__, qc); + + /* Make sure DMA commands updates are visible */ + writel(priv->dma_table_dma, &dma_regs->cmdptr); + + /* On KeyLargo 66Mhz cell, we need to add 60ns to wrDataSetup on + * UDMA reads + */ + if (priv->kind == controller_kl_ata4 && + (priv->treg[dev][0] & TR_66_UDMA_EN)) { + void __iomem *rbase = ap->ioaddr.cmd_addr; + u32 reg = priv->treg[dev][0]; + + if (!(qc->tf.flags & ATA_TFLAG_WRITE)) + reg += 0x00800000; + writel(reg, rbase + IDE_TIMING_CONFIG); + } + + /* issue r/w command */ + ap->ops->sff_exec_command(ap, &qc->tf); +} + +static void pata_macio_bmdma_start(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct pata_macio_priv *priv = ap->private_data; + struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; + + dev_dbgdma(priv->dev, "%s: qc %p\n", __func__, qc); + + writel((RUN << 16) | RUN, &dma_regs->control); + /* Make sure it gets to the controller right now */ + (void)readl(&dma_regs->control); +} + +static void pata_macio_bmdma_stop(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct pata_macio_priv *priv = ap->private_data; + struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; + unsigned int timeout = 1000000; + + dev_dbgdma(priv->dev, "%s: qc %p\n", __func__, qc); + + /* Stop the DMA engine and wait for it to full halt */ + writel (((RUN|WAKE|DEAD) << 16), &dma_regs->control); + while (--timeout && (readl(&dma_regs->status) & RUN)) + udelay(1); +} + +static u8 pata_macio_bmdma_status(struct ata_port *ap) +{ + struct pata_macio_priv *priv = ap->private_data; + struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; + u32 dstat, rstat = ATA_DMA_INTR; + unsigned long timeout = 0; + + dstat = readl(&dma_regs->status); + + dev_dbgdma(priv->dev, "%s: dstat=%x\n", __func__, dstat); + + /* We have two things to deal with here: + * + * - The dbdma won't stop if the command was started + * but completed with an error without transferring all + * datas. This happens when bad blocks are met during + * a multi-block transfer. + * + * - The dbdma fifo hasn't yet finished flushing to + * to system memory when the disk interrupt occurs. + * + */ + + /* First check for errors */ + if ((dstat & (RUN|DEAD)) != RUN) + rstat |= ATA_DMA_ERR; + + /* If ACTIVE is cleared, the STOP command has been hit and + * the transfer is complete. If not, we have to flush the + * channel. + */ + if ((dstat & ACTIVE) == 0) + return rstat; + + dev_dbgdma(priv->dev, "%s: DMA still active, flushing...\n", __func__); + + /* If dbdma didn't execute the STOP command yet, the + * active bit is still set. We consider that we aren't + * sharing interrupts (which is hopefully the case with + * those controllers) and so we just try to flush the + * channel for pending data in the fifo + */ + udelay(1); + writel((FLUSH << 16) | FLUSH, &dma_regs->control); + for (;;) { + udelay(1); + dstat = readl(&dma_regs->status); + if ((dstat & FLUSH) == 0) + break; + if (++timeout > 1000) { + dev_warn(priv->dev, "timeout flushing DMA\n"); + rstat |= ATA_DMA_ERR; + break; + } + } + return rstat; +} + +/* port_start is when we allocate the DMA command list */ +static int pata_macio_port_start(struct ata_port *ap) +{ + struct pata_macio_priv *priv = ap->private_data; + + if (ap->ioaddr.bmdma_addr == NULL) + return 0; + + /* Allocate space for the DBDMA commands. + * + * The +2 is +1 for the stop command and +1 to allow for + * aligning the start address to a multiple of 16 bytes. + */ + priv->dma_table_cpu = + dmam_alloc_coherent(priv->dev, + (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), + &priv->dma_table_dma, GFP_KERNEL); + if (priv->dma_table_cpu == NULL) { + dev_err(priv->dev, "Unable to allocate DMA command list\n"); + ap->ioaddr.bmdma_addr = NULL; + } + return 0; +} + +static void pata_macio_irq_clear(struct ata_port *ap) +{ + struct pata_macio_priv *priv = ap->private_data; + + /* Nothing to do here */ + + dev_dbgdma(priv->dev, "%s\n", __func__); +} + +static void pata_macio_reset_hw(struct pata_macio_priv *priv, int resume) +{ + dev_dbg(priv->dev, "Enabling & resetting... \n"); + + if (priv->mediabay) + return; + + if (priv->kind == controller_ohare && !resume) { + /* The code below is having trouble on some ohare machines + * (timing related ?). Until I can put my hand on one of these + * units, I keep the old way + */ + ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, priv->node, 0, 1); + } else { + int rc; + + /* Reset and enable controller */ + rc = ppc_md.feature_call(PMAC_FTR_IDE_RESET, + priv->node, priv->aapl_bus_id, 1); + ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, + priv->node, priv->aapl_bus_id, 1); + msleep(10); + /* Only bother waiting if there's a reset control */ + if (rc == 0) { + ppc_md.feature_call(PMAC_FTR_IDE_RESET, + priv->node, priv->aapl_bus_id, 0); + msleep(IDE_WAKEUP_DELAY_MS); + } + } + + /* If resuming a PCI device, restore the config space here */ + if (priv->pdev && resume) { + int rc; + + pci_restore_state(priv->pdev); + rc = pcim_enable_device(priv->pdev); + if (rc) + dev_printk(KERN_ERR, &priv->pdev->dev, + "Failed to enable device after resume (%d)\n", rc); + else + pci_set_master(priv->pdev); + } + + /* On Kauai, initialize the FCR. We don't perform a reset, doesn't really + * seem necessary and speeds up the boot process + */ + if (priv->kauai_fcr) + writel(KAUAI_FCR_UATA_MAGIC | + KAUAI_FCR_UATA_RESET_N | + KAUAI_FCR_UATA_ENABLE, priv->kauai_fcr); +} + +/* Hook the standard slave config to fixup some HW related alignment + * restrictions + */ +static int pata_macio_slave_config(struct scsi_device *sdev) +{ + struct ata_port *ap = ata_shost_to_port(sdev->host); + struct pata_macio_priv *priv = ap->private_data; + struct ata_device *dev; + u16 cmd; + int rc; + + /* First call original */ + rc = ata_scsi_slave_config(sdev); + if (rc) + return rc; + + /* This is lifted from sata_nv */ + dev = &ap->link.device[sdev->id]; + + /* OHare has issues with non cache aligned DMA on some chipsets */ + if (priv->kind == controller_ohare) { + blk_queue_update_dma_alignment(sdev->request_queue, 31); + blk_queue_update_dma_pad(sdev->request_queue, 31); + + /* Tell the world about it */ + ata_dev_printk(dev, KERN_INFO, "OHare alignment limits applied\n"); + return 0; + } + + /* We only have issues with ATAPI */ + if (dev->class != ATA_DEV_ATAPI) + return 0; + + /* Shasta and K2 seem to have "issues" with reads ... */ + if (priv->kind == controller_sh_ata6 || priv->kind == controller_k2_ata6) { + /* Allright these are bad, apply restrictions */ + blk_queue_update_dma_alignment(sdev->request_queue, 15); + blk_queue_update_dma_pad(sdev->request_queue, 15); + + /* We enable MWI and hack cache line size directly here, this + * is specific to this chipset and not normal values, we happen + * to somewhat know what we are doing here (which is basically + * to do the same Apple does and pray they did not get it wrong :-) + */ + BUG_ON(!priv->pdev); + pci_write_config_byte(priv->pdev, PCI_CACHE_LINE_SIZE, 0x08); + pci_read_config_word(priv->pdev, PCI_COMMAND, &cmd); + pci_write_config_word(priv->pdev, PCI_COMMAND, + cmd | PCI_COMMAND_INVALIDATE); + + /* Tell the world about it */ + ata_dev_printk(dev, KERN_INFO, + "K2/Shasta alignment limits applied\n"); + } + + return 0; +} + +#ifdef CONFIG_PM + +static int pata_macio_do_suspend(struct pata_macio_priv *priv, pm_message_t mesg) +{ + int rc; + + /* First, core libata suspend to do most of the work */ + rc = ata_host_suspend(priv->host, mesg); + if (rc) + return rc; + + /* Restore to default timings */ + pata_macio_default_timings(priv); + + /* Mask interrupt. Not strictly necessary but old driver did + * it and I'd rather not change that here */ + disable_irq(priv->irq); + + /* The media bay will handle itself just fine */ + if (priv->mediabay) + return 0; + + /* Kauai has bus control FCRs directly here */ + if (priv->kauai_fcr) { + u32 fcr = readl(priv->kauai_fcr); + fcr &= ~(KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE); + writel(fcr, priv->kauai_fcr); + } + + /* For PCI, save state and disable DMA. No need to call + * pci_set_power_state(), the HW doesn't do D states that + * way, the platform code will take care of suspending the + * ASIC properly + */ + if (priv->pdev) { + pci_save_state(priv->pdev); + pci_disable_device(priv->pdev); + } + + /* Disable the bus on older machines and the cell on kauai */ + ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, priv->node, + priv->aapl_bus_id, 0); + + return 0; +} + +static int pata_macio_do_resume(struct pata_macio_priv *priv) +{ + /* Reset and re-enable the HW */ + pata_macio_reset_hw(priv, 1); + + /* Sanitize drive timings */ + pata_macio_apply_timings(priv->host->ports[0], 0); + + /* We want our IRQ back ! */ + enable_irq(priv->irq); + + /* Let the libata core take it from there */ + ata_host_resume(priv->host); + + return 0; +} + +#endif /* CONFIG_PM */ + +static struct scsi_host_template pata_macio_sht = { + ATA_BASE_SHT(DRV_NAME), + .sg_tablesize = MAX_DCMDS, + /* We may not need that strict one */ + .dma_boundary = ATA_DMA_BOUNDARY, + .slave_configure = pata_macio_slave_config, +}; + +static struct ata_port_operations pata_macio_ops = { + .inherits = &ata_sff_port_ops, + + .freeze = pata_macio_freeze, + .set_piomode = pata_macio_set_timings, + .set_dmamode = pata_macio_set_timings, + .cable_detect = pata_macio_cable_detect, + .sff_dev_select = pata_macio_dev_select, + .qc_prep = pata_macio_qc_prep, + .mode_filter = ata_bmdma_mode_filter, + .bmdma_setup = pata_macio_bmdma_setup, + .bmdma_start = pata_macio_bmdma_start, + .bmdma_stop = pata_macio_bmdma_stop, + .bmdma_status = pata_macio_bmdma_status, + .port_start = pata_macio_port_start, + .sff_irq_clear = pata_macio_irq_clear, +}; + +static void __devinit pata_macio_invariants(struct pata_macio_priv *priv) +{ + const int *bidp; + + /* Identify the type of controller */ + if (of_device_is_compatible(priv->node, "shasta-ata")) { + priv->kind = controller_sh_ata6; + priv->timings = pata_macio_shasta_timings; + } else if (of_device_is_compatible(priv->node, "kauai-ata")) { + priv->kind = controller_un_ata6; + priv->timings = pata_macio_kauai_timings; + } else if (of_device_is_compatible(priv->node, "K2-UATA")) { + priv->kind = controller_k2_ata6; + priv->timings = pata_macio_kauai_timings; + } else if (of_device_is_compatible(priv->node, "keylargo-ata")) { + if (strcmp(priv->node->name, "ata-4") == 0) { + priv->kind = controller_kl_ata4; + priv->timings = pata_macio_kl66_timings; + } else { + priv->kind = controller_kl_ata3; + priv->timings = pata_macio_kl33_timings; + } + } else if (of_device_is_compatible(priv->node, "heathrow-ata")) { + priv->kind = controller_heathrow; + priv->timings = pata_macio_heathrow_timings; + } else { + priv->kind = controller_ohare; + priv->timings = pata_macio_ohare_timings; + } + + /* XXX FIXME --- setup priv->mediabay here */ + + /* Get Apple bus ID (for clock and ASIC control) */ + bidp = of_get_property(priv->node, "AAPL,bus-id", NULL); + priv->aapl_bus_id = bidp ? *bidp : 0; + + /* Fixup missing Apple bus ID in case of media-bay */ + if (priv->mediabay && bidp == 0) + priv->aapl_bus_id = 1; +} + +static void __devinit pata_macio_setup_ios(struct ata_ioports *ioaddr, + void __iomem * base, + void __iomem * dma) +{ + /* cmd_addr is the base of regs for that port */ + ioaddr->cmd_addr = base; + + /* taskfile registers */ + ioaddr->data_addr = base + (ATA_REG_DATA << 4); + ioaddr->error_addr = base + (ATA_REG_ERR << 4); + ioaddr->feature_addr = base + (ATA_REG_FEATURE << 4); + ioaddr->nsect_addr = base + (ATA_REG_NSECT << 4); + ioaddr->lbal_addr = base + (ATA_REG_LBAL << 4); + ioaddr->lbam_addr = base + (ATA_REG_LBAM << 4); + ioaddr->lbah_addr = base + (ATA_REG_LBAH << 4); + ioaddr->device_addr = base + (ATA_REG_DEVICE << 4); + ioaddr->status_addr = base + (ATA_REG_STATUS << 4); + ioaddr->command_addr = base + (ATA_REG_CMD << 4); + ioaddr->altstatus_addr = base + 0x160; + ioaddr->ctl_addr = base + 0x160; + ioaddr->bmdma_addr = dma; +} + +static void __devinit pmac_macio_calc_timing_masks(struct pata_macio_priv *priv, + struct ata_port_info *pinfo) +{ + int i = 0; + + pinfo->pio_mask = 0; + pinfo->mwdma_mask = 0; + pinfo->udma_mask = 0; + + while (priv->timings[i].mode > 0) { + unsigned int mask = 1U << (priv->timings[i].mode & 0x0f); + switch(priv->timings[i].mode & 0xf0) { + case 0x00: /* PIO */ + pinfo->pio_mask |= (mask >> 8); + break; + case 0x20: /* MWDMA */ + pinfo->mwdma_mask |= mask; + break; + case 0x40: /* UDMA */ + pinfo->udma_mask |= mask; + break; + } + i++; + } + dev_dbg(priv->dev, "Supported masks: PIO=%lx, MWDMA=%lx, UDMA=%lx\n", + pinfo->pio_mask, pinfo->mwdma_mask, pinfo->udma_mask); +} + +static int __devinit pata_macio_common_init(struct pata_macio_priv *priv, + resource_size_t tfregs, + resource_size_t dmaregs, + resource_size_t fcregs, + unsigned long irq) +{ + struct ata_port_info pinfo; + const struct ata_port_info *ppi[] = { &pinfo, NULL }; + void __iomem *dma_regs = NULL; + + /* Fill up privates with various invariants collected from the + * device-tree + */ + pata_macio_invariants(priv); + + /* Make sure we have sane initial timings in the cache */ + pata_macio_default_timings(priv); + + /* Not sure what the real max is but we know it's less than 64K, let's + * use 64K minus 256 + */ + dma_set_max_seg_size(priv->dev, MAX_DBDMA_SEG); + + /* Allocate libata host for 1 port */ + memset(&pinfo, 0, sizeof(struct ata_port_info)); + pmac_macio_calc_timing_masks(priv, &pinfo); + pinfo.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO | + ATA_FLAG_NO_LEGACY; + pinfo.port_ops = &pata_macio_ops; + pinfo.private_data = priv; + + priv->host = ata_host_alloc_pinfo(priv->dev, ppi, 1); + if (priv->host == NULL) { + dev_err(priv->dev, "Failed to allocate ATA port structure\n"); + return -ENOMEM; + } + + /* Setup the private data in host too */ + priv->host->private_data = priv; + + /* Map base registers */ + priv->tfregs = devm_ioremap(priv->dev, tfregs, 0x100); + if (priv->tfregs == NULL) { + dev_err(priv->dev, "Failed to map ATA ports\n"); + return -ENOMEM; + } + priv->host->iomap = &priv->tfregs; + + /* Map DMA regs */ + if (dmaregs != 0) { + dma_regs = devm_ioremap(priv->dev, dmaregs, + sizeof(struct dbdma_regs)); + if (dma_regs == NULL) + dev_warn(priv->dev, "Failed to map ATA DMA registers\n"); + } + + /* If chip has local feature control, map those regs too */ + if (fcregs != 0) { + priv->kauai_fcr = devm_ioremap(priv->dev, fcregs, 4); + if (priv->kauai_fcr == NULL) { + dev_err(priv->dev, "Failed to map ATA FCR register\n"); + return -ENOMEM; + } + } + + /* Setup port data structure */ + pata_macio_setup_ios(&priv->host->ports[0]->ioaddr, + priv->tfregs, dma_regs); + priv->host->ports[0]->private_data = priv; + + /* hard-reset the controller */ + pata_macio_reset_hw(priv, 0); + pata_macio_apply_timings(priv->host->ports[0], 0); + + /* Enable bus master if necessary */ + if (priv->pdev && dma_regs) + pci_set_master(priv->pdev); + + dev_info(priv->dev, "Activating pata-macio chipset %s, Apple bus ID %d\n", + macio_ata_names[priv->kind], priv->aapl_bus_id); + + /* Start it up */ + priv->irq = irq; + return ata_host_activate(priv->host, irq, ata_sff_interrupt, 0, + &pata_macio_sht); +} + +static int __devinit pata_macio_attach(struct macio_dev *mdev, + const struct of_device_id *match) +{ + struct pata_macio_priv *priv; + resource_size_t tfregs, dmaregs = 0; + unsigned long irq; + int rc; + + /* Check for broken device-trees */ + if (macio_resource_count(mdev) == 0) { + dev_err(&mdev->ofdev.dev, + "No addresses for controller\n"); + return -ENXIO; + } + + /* Enable managed resources */ + macio_enable_devres(mdev); + + /* Allocate and init private data structure */ + priv = devm_kzalloc(&mdev->ofdev.dev, + sizeof(struct pata_macio_priv), GFP_KERNEL); + if (priv == NULL) { + dev_err(&mdev->ofdev.dev, + "Failed to allocate private memory\n"); + return -ENOMEM; + } + priv->node = of_node_get(mdev->ofdev.node); + priv->mdev = mdev; + priv->dev = &mdev->ofdev.dev; + + /* Request memory resource for taskfile registers */ + if (macio_request_resource(mdev, 0, "pata-macio")) { + dev_err(&mdev->ofdev.dev, + "Cannot obtain taskfile resource\n"); + return -EBUSY; + } + tfregs = macio_resource_start(mdev, 0); + + /* Request resources for DMA registers if any */ + if (macio_resource_count(mdev) >= 2) { + if (macio_request_resource(mdev, 1, "pata-macio-dma")) + dev_err(&mdev->ofdev.dev, + "Cannot obtain DMA resource\n"); + else + dmaregs = macio_resource_start(mdev, 1); + } + + /* + * Fixup missing IRQ for some old implementations with broken + * device-trees. + * + * This is a bit bogus, it should be fixed in the device-tree itself, + * via the existing macio fixups, based on the type of interrupt + * controller in the machine. However, I have no test HW for this case, + * and this trick works well enough on those old machines... + */ + if (macio_irq_count(mdev) == 0) { + dev_warn(&mdev->ofdev.dev, + "No interrupts for controller, using 13\n"); + irq = irq_create_mapping(NULL, 13); + } else + irq = macio_irq(mdev, 0); + + /* Prevvent media bay callbacks until fully registered */ + lock_media_bay(priv->mdev->media_bay); + + /* Get register addresses and call common initialization */ + rc = pata_macio_common_init(priv, + tfregs, /* Taskfile regs */ + dmaregs, /* DBDMA regs */ + 0, /* Feature control */ + irq); + unlock_media_bay(priv->mdev->media_bay); + + return rc; +} + +static int __devexit pata_macio_detach(struct macio_dev *mdev) +{ + struct ata_host *host = macio_get_drvdata(mdev); + struct pata_macio_priv *priv = host->private_data; + + lock_media_bay(priv->mdev->media_bay); + + /* Make sure the mediabay callback doesn't try to access + * dead stuff + */ + priv->host->private_data = NULL; + + ata_host_detach(host); + + unlock_media_bay(priv->mdev->media_bay); + + return 0; +} + +#ifdef CONFIG_PM + +static int pata_macio_suspend(struct macio_dev *mdev, pm_message_t mesg) +{ + struct ata_host *host = macio_get_drvdata(mdev); + + return pata_macio_do_suspend(host->private_data, mesg); +} + +static int pata_macio_resume(struct macio_dev *mdev) +{ + struct ata_host *host = macio_get_drvdata(mdev); + + return pata_macio_do_resume(host->private_data); +} + +#endif /* CONFIG_PM */ + +#ifdef CONFIG_PMAC_MEDIABAY +static void pata_macio_mb_event(struct macio_dev* mdev, int mb_state) +{ + struct ata_host *host = macio_get_drvdata(mdev); + struct ata_port *ap; + struct ata_eh_info *ehi; + struct ata_device *dev; + unsigned long flags; + + if (!host || !host->private_data) + return; + ap = host->ports[0]; + spin_lock_irqsave(ap->lock, flags); + ehi = &ap->link.eh_info; + if (mb_state == MB_CD) { + ata_ehi_push_desc(ehi, "mediabay plug"); + ata_ehi_hotplugged(ehi); + ata_port_freeze(ap); + } else { + ata_ehi_push_desc(ehi, "mediabay unplug"); + ata_for_each_dev(dev, &ap->link, ALL) + dev->flags |= ATA_DFLAG_DETACH; + ata_port_abort(ap); + } + spin_unlock_irqrestore(ap->lock, flags); + +} +#endif /* CONFIG_PMAC_MEDIABAY */ + + +static int __devinit pata_macio_pci_attach(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct pata_macio_priv *priv; + struct device_node *np; + resource_size_t rbase; + + /* We cannot use a MacIO controller without its OF device node */ + np = pci_device_to_OF_node(pdev); + if (np == NULL) { + dev_err(&pdev->dev, + "Cannot find OF device node for controller\n"); + return -ENODEV; + } + + /* Check that it can be enabled */ + if (pcim_enable_device(pdev)) { + dev_err(&pdev->dev, + "Cannot enable controller PCI device\n"); + return -ENXIO; + } + + /* Allocate and init private data structure */ + priv = devm_kzalloc(&pdev->dev, + sizeof(struct pata_macio_priv), GFP_KERNEL); + if (priv == NULL) { + dev_err(&pdev->dev, + "Failed to allocate private memory\n"); + return -ENOMEM; + } + priv->node = of_node_get(np); + priv->pdev = pdev; + priv->dev = &pdev->dev; + + /* Get MMIO regions */ + if (pci_request_regions(pdev, "pata-macio")) { + dev_err(&pdev->dev, + "Cannot obtain PCI resources\n"); + return -EBUSY; + } + + /* Get register addresses and call common initialization */ + rbase = pci_resource_start(pdev, 0); + if (pata_macio_common_init(priv, + rbase + 0x2000, /* Taskfile regs */ + rbase + 0x1000, /* DBDMA regs */ + rbase, /* Feature control */ + pdev->irq)) + return -ENXIO; + + return 0; +} + +static void __devexit pata_macio_pci_detach(struct pci_dev *pdev) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + + ata_host_detach(host); +} + +#ifdef CONFIG_PM + +static int pata_macio_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + + return pata_macio_do_suspend(host->private_data, mesg); +} + +static int pata_macio_pci_resume(struct pci_dev *pdev) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + + return pata_macio_do_resume(host->private_data); +} + +#endif /* CONFIG_PM */ + +static struct of_device_id pata_macio_match[] = +{ + { + .name = "IDE", + }, + { + .name = "ATA", + }, + { + .type = "ide", + }, + { + .type = "ata", + }, + {}, +}; + +static struct macio_driver pata_macio_driver = +{ + .name = "pata-macio", + .match_table = pata_macio_match, + .probe = pata_macio_attach, + .remove = pata_macio_detach, +#ifdef CONFIG_PM + .suspend = pata_macio_suspend, + .resume = pata_macio_resume, +#endif +#ifdef CONFIG_PMAC_MEDIABAY + .mediabay_event = pata_macio_mb_event, +#endif + .driver = { + .owner = THIS_MODULE, + }, +}; + +static const struct pci_device_id pata_macio_pci_match[] = { + { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA), 0 }, + { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100), 0 }, + { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100), 0 }, + { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_SH_ATA), 0 }, + { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA), 0 }, + {}, +}; + +static struct pci_driver pata_macio_pci_driver = { + .name = "pata-pci-macio", + .id_table = pata_macio_pci_match, + .probe = pata_macio_pci_attach, + .remove = pata_macio_pci_detach, +#ifdef CONFIG_PM + .suspend = pata_macio_pci_suspend, + .resume = pata_macio_pci_resume, +#endif + .driver = { + .owner = THIS_MODULE, + }, +}; +MODULE_DEVICE_TABLE(pci, pata_macio_pci_match); + + +static int __init pata_macio_init(void) +{ + int rc; + + if (!machine_is(powermac)) + return -ENODEV; + + rc = pci_register_driver(&pata_macio_pci_driver); + if (rc) + return rc; + rc = macio_register_driver(&pata_macio_driver); + if (rc) { + pci_unregister_driver(&pata_macio_pci_driver); + return rc; + } + return 0; +} + +static void __exit pata_macio_exit(void) +{ + macio_unregister_driver(&pata_macio_driver); + pci_unregister_driver(&pata_macio_pci_driver); +} + +module_init(pata_macio_init); +module_exit(pata_macio_exit); + +MODULE_AUTHOR("Benjamin Herrenschmidt"); +MODULE_DESCRIPTION("Apple MacIO PATA driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); diff --git a/drivers/atm/he.c b/drivers/atm/he.c index e90665876c4774ffa92cbccee1629c10f388ad80..e8c6529dc366a6401730d4b16d12a98597d6ab0b 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -2505,7 +2505,7 @@ he_close(struct atm_vcc *vcc) * TBRQ, the host issues the close command to the adapter. */ - while (((tx_inuse = atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) > 0) && + while (((tx_inuse = atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) > 1) && (retry < MAX_RETRY)) { msleep(sleep); if (sleep < 250) @@ -2514,7 +2514,7 @@ he_close(struct atm_vcc *vcc) ++retry; } - if (tx_inuse) + if (tx_inuse > 1) hprintk("close tx cid 0x%x tx_inuse = %d\n", cid, tx_inuse); /* 2.3.1.1 generic close operations with flush */ diff --git a/drivers/base/core.c b/drivers/base/core.c index 6bee6af8d8e1d74b574640e44013c2ccf7c51bd2..f1290cbd1350ebaa8d28e2c015cb403728374862 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -56,7 +56,14 @@ static inline int device_is_not_partition(struct device *dev) */ const char *dev_driver_string(const struct device *dev) { - return dev->driver ? dev->driver->name : + struct device_driver *drv; + + /* dev->driver can change to NULL underneath us because of unbinding, + * so be careful about accessing it. dev->bus and dev->class should + * never change once they are set, so they don't need special care. + */ + drv = ACCESS_ONCE(dev->driver); + return drv ? drv->name : (dev->bus ? dev->bus->name : (dev->class ? dev->class->name : "")); } @@ -986,6 +993,8 @@ done: AttrsError: device_remove_class_symlinks(dev); SymlinkError: + if (MAJOR(dev->devt)) + devtmpfs_delete_node(dev); if (MAJOR(dev->devt)) device_remove_sys_dev_entry(dev); devtattrError: @@ -1728,8 +1737,5 @@ void device_shutdown(void) dev->driver->shutdown(dev); } } - kobject_put(sysfs_dev_char_kobj); - kobject_put(sysfs_dev_block_kobj); - kobject_put(dev_kobj); async_synchronize_full(); } diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index e62a4ccea54d0c4a3dc6dcd84eb107e557bcb54c..958bd1540c303d92f84cbcea016c7da4c0ce925c 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -35,6 +35,7 @@ static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribut struct cpu *cpu = container_of(dev, struct cpu, sysdev); ssize_t ret; + cpu_hotplug_driver_lock(); switch (buf[0]) { case '0': ret = cpu_down(cpu->sysdev.id); @@ -49,6 +50,7 @@ static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribut default: ret = -EINVAL; } + cpu_hotplug_driver_unlock(); if (ret >= 0) ret = count; @@ -72,6 +74,38 @@ void unregister_cpu(struct cpu *cpu) per_cpu(cpu_sys_devices, logical_cpu) = NULL; return; } + +#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE +static ssize_t cpu_probe_store(struct class *class, const char *buf, + size_t count) +{ + return arch_cpu_probe(buf, count); +} + +static ssize_t cpu_release_store(struct class *class, const char *buf, + size_t count) +{ + return arch_cpu_release(buf, count); +} + +static CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); +static CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store); + +int __init cpu_probe_release_init(void) +{ + int rc; + + rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj, + &class_attr_probe.attr); + if (!rc) + rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj, + &class_attr_release.attr); + + return rc; +} +device_initcall(cpu_probe_release_init); +#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ + #else /* ... !CONFIG_HOTPLUG_CPU */ static inline void register_cpu_control(struct cpu *cpu) { @@ -97,7 +131,7 @@ static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute * boot up and this data does not change there after. Hence this * operation should be safe. No locking required. */ - addr = __pa(per_cpu_ptr(crash_notes, cpunum)); + addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpunum)); rc = sprintf(buf, "%Lx\n", addr); return rc; } diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index a1cb5afe6801f87ac9e139de4e542258e6381d90..50375bb8e51d921582aa2685bdfe551acdc60ca2 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -32,6 +32,8 @@ static int dev_mount = 1; static int dev_mount; #endif +static rwlock_t dirlock; + static int __init mount_param(char *str) { dev_mount = simple_strtoul(str, NULL, 0); @@ -74,47 +76,35 @@ static int dev_mkdir(const char *name, mode_t mode) dentry = lookup_create(&nd, 1); if (!IS_ERR(dentry)) { err = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); + if (!err) + /* mark as kernel-created inode */ + dentry->d_inode->i_private = &dev_mnt; dput(dentry); } else { err = PTR_ERR(dentry); } - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); return err; } static int create_path(const char *nodepath) { - char *path; - struct nameidata nd; - int err = 0; - - path = kstrdup(nodepath, GFP_KERNEL); - if (!path) - return -ENOMEM; - - err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, - path, LOOKUP_PARENT, &nd); - if (err == 0) { - struct dentry *dentry; - - /* create directory right away */ - dentry = lookup_create(&nd, 1); - if (!IS_ERR(dentry)) { - err = vfs_mkdir(nd.path.dentry->d_inode, - dentry, 0755); - dput(dentry); - } - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + int err; - path_put(&nd.path); - } else if (err == -ENOENT) { + read_lock(&dirlock); + err = dev_mkdir(nodepath, 0755); + if (err == -ENOENT) { + char *path; char *s; /* parent directories do not exist, create them */ + path = kstrdup(nodepath, GFP_KERNEL); + if (!path) + return -ENOMEM; s = path; - while (1) { + for (;;) { s = strchr(s, '/'); if (!s) break; @@ -125,9 +115,9 @@ static int create_path(const char *nodepath) s[0] = '/'; s++; } + kfree(path); } - - kfree(path); + read_unlock(&dirlock); return err; } @@ -156,34 +146,40 @@ int devtmpfs_create_node(struct device *dev) mode |= S_IFCHR; curr_cred = override_creds(&init_cred); + err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, nodename, LOOKUP_PARENT, &nd); if (err == -ENOENT) { - /* create missing parent directories */ create_path(nodename); err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, nodename, LOOKUP_PARENT, &nd); - if (err) - goto out; } + if (err) + goto out; dentry = lookup_create(&nd, 0); if (!IS_ERR(dentry)) { - int umask; - - umask = sys_umask(0000); err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, dev->devt); - sys_umask(umask); - /* mark as kernel created inode */ - if (!err) + if (!err) { + struct iattr newattrs; + + /* fixup possibly umasked mode */ + newattrs.ia_mode = mode; + newattrs.ia_valid = ATTR_MODE; + mutex_lock(&dentry->d_inode->i_mutex); + notify_change(dentry, &newattrs); + mutex_unlock(&dentry->d_inode->i_mutex); + + /* mark as kernel-created inode */ dentry->d_inode->i_private = &dev_mnt; + } dput(dentry); } else { err = PTR_ERR(dentry); } - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); out: kfree(tmp); @@ -205,16 +201,21 @@ static int dev_rmdir(const char *name) mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); if (!IS_ERR(dentry)) { - if (dentry->d_inode) - err = vfs_rmdir(nd.path.dentry->d_inode, dentry); - else + if (dentry->d_inode) { + if (dentry->d_inode->i_private == &dev_mnt) + err = vfs_rmdir(nd.path.dentry->d_inode, + dentry); + else + err = -EPERM; + } else { err = -ENOENT; + } dput(dentry); } else { err = PTR_ERR(dentry); } - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); return err; } @@ -228,7 +229,8 @@ static int delete_path(const char *nodepath) if (!path) return -ENOMEM; - while (1) { + write_lock(&dirlock); + for (;;) { char *base; base = strrchr(path, '/'); @@ -239,6 +241,7 @@ static int delete_path(const char *nodepath) if (err) break; } + write_unlock(&dirlock); kfree(path); return err; @@ -322,9 +325,8 @@ out: * If configured, or requested by the commandline, devtmpfs will be * auto-mounted after the kernel mounted the root filesystem. */ -int devtmpfs_mount(const char *mountpoint) +int devtmpfs_mount(const char *mntdir) { - struct path path; int err; if (!dev_mount) @@ -333,15 +335,11 @@ int devtmpfs_mount(const char *mountpoint) if (!dev_mnt) return 0; - err = kern_path(mountpoint, LOOKUP_FOLLOW, &path); - if (err) - return err; - err = do_add_mount(dev_mnt, &path, 0, NULL); + err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL); if (err) printk(KERN_INFO "devtmpfs: error mounting %i\n", err); else printk(KERN_INFO "devtmpfs: mounted\n"); - path_put(&path); return err; } @@ -354,6 +352,8 @@ int __init devtmpfs_init(void) int err; struct vfsmount *mnt; + rwlock_init(&dirlock); + err = register_filesystem(&dev_fs_type); if (err) { printk(KERN_ERR "devtmpfs: unable to register devtmpfs " @@ -361,7 +361,7 @@ int __init devtmpfs_init(void) return err; } - mnt = kern_mount(&dev_fs_type); + mnt = kern_mount_data(&dev_fs_type, "mode=0755"); if (IS_ERR(mnt)) { err = PTR_ERR(mnt); printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err); diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 7376367bcb8053dec4951945f916d47c882fd59a..a95024166b66c0eb82a4fc6d070a4ad923544c81 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -601,12 +601,9 @@ request_firmware_work_func(void *arg) } ret = _request_firmware(&fw, fw_work->name, fw_work->device, fw_work->uevent); - if (ret < 0) - fw_work->cont(NULL, fw_work->context); - else { - fw_work->cont(fw, fw_work->context); - release_firmware(fw); - } + + fw_work->cont(fw, fw_work->context); + module_put(fw_work->module); kfree(fw_work); return ret; @@ -619,6 +616,7 @@ request_firmware_work_func(void *arg) * is non-zero else the firmware copy must be done manually. * @name: name of firmware file * @device: device for which firmware is being loaded + * @gfp: allocation flags * @context: will be passed over to @cont, and * @fw may be %NULL if firmware request fails. * @cont: function will be called asynchronously when the firmware @@ -631,12 +629,12 @@ request_firmware_work_func(void *arg) int request_firmware_nowait( struct module *module, int uevent, - const char *name, struct device *device, void *context, + const char *name, struct device *device, gfp_t gfp, void *context, void (*cont)(const struct firmware *fw, void *context)) { struct task_struct *task; struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work), - GFP_ATOMIC); + gfp); if (!fw_work) return -ENOMEM; diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 4fa954b07ac4ada384d27ffba6b293c22651febd..9d2ee25deaf5cb13811b45e071e835bc615fa6b9 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1000,7 +1000,7 @@ static __initdata LIST_HEAD(early_platform_device_list); int __init early_platform_driver_register(struct early_platform_driver *epdrv, char *buf) { - unsigned long index; + char *tmp; int n; /* Simply add the driver to the end of the global list. @@ -1019,13 +1019,28 @@ int __init early_platform_driver_register(struct early_platform_driver *epdrv, if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) { list_move(&epdrv->list, &early_platform_driver_list); - if (!strcmp(buf, epdrv->pdrv->driver.name)) + /* Allow passing parameters after device name */ + if (buf[n] == '\0' || buf[n] == ',') epdrv->requested_id = -1; - else if (buf[n] == '.' && strict_strtoul(&buf[n + 1], 10, - &index) == 0) - epdrv->requested_id = index; - else - epdrv->requested_id = EARLY_PLATFORM_ID_ERROR; + else { + epdrv->requested_id = simple_strtoul(&buf[n + 1], + &tmp, 10); + + if (buf[n] != '.' || (tmp == &buf[n + 1])) { + epdrv->requested_id = EARLY_PLATFORM_ID_ERROR; + n = 0; + } else + n += strcspn(&buf[n + 1], ",") + 1; + } + + if (buf[n] == ',') + n++; + + if (epdrv->bufsize) { + memcpy(epdrv->buffer, &buf[n], + min_t(int, epdrv->bufsize, strlen(&buf[n]) + 1)); + epdrv->buffer[epdrv->bufsize - 1] = '\0'; + } } return 0; diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index 6380ad8d91bd71a374fd5ace2a63be8b532f48cf..59ca2b77b574dd70956e6d818a63831c12fb6636 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -200,7 +200,7 @@ struct floppy_state { int ejected; wait_queue_head_t wait; int wanted; - struct device_node* media_bay; /* NULL when not in bay */ + struct macio_dev *mdev; char dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)]; }; @@ -303,14 +303,13 @@ static int swim3_readbit(struct floppy_state *fs, int bit) static void do_fd_request(struct request_queue * q) { int i; - for(i=0;imdev->media_bay && + check_media_bay(fs->mdev->media_bay) != MB_FD) continue; -#endif /* CONFIG_PMAC_MEDIABAY */ - start_request(&floppy_states[i]); + start_request(fs); } } @@ -849,10 +848,9 @@ static int floppy_ioctl(struct block_device *bdev, fmode_t mode, if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)) return -EPERM; -#ifdef CONFIG_PMAC_MEDIABAY - if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) + if (fs->mdev->media_bay && + check_media_bay(fs->mdev->media_bay) != MB_FD) return -ENXIO; -#endif switch (cmd) { case FDEJECT: @@ -876,10 +874,9 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) int n, err = 0; if (fs->ref_count == 0) { -#ifdef CONFIG_PMAC_MEDIABAY - if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) + if (fs->mdev->media_bay && + check_media_bay(fs->mdev->media_bay) != MB_FD) return -ENXIO; -#endif out_8(&sw->setup, S_IBM_DRIVE | S_FCLK_DIV2); out_8(&sw->control_bic, 0xff); out_8(&sw->mode, 0x95); @@ -963,10 +960,9 @@ static int floppy_revalidate(struct gendisk *disk) struct swim3 __iomem *sw; int ret, n; -#ifdef CONFIG_PMAC_MEDIABAY - if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) + if (fs->mdev->media_bay && + check_media_bay(fs->mdev->media_bay) != MB_FD) return -ENXIO; -#endif sw = fs->swim3; grab_drive(fs, revalidating, 0); @@ -1009,7 +1005,6 @@ static const struct block_device_operations floppy_fops = { static int swim3_add_device(struct macio_dev *mdev, int index) { struct device_node *swim = mdev->ofdev.node; - struct device_node *mediabay; struct floppy_state *fs = &floppy_states[index]; int rc = -EBUSY; @@ -1036,9 +1031,7 @@ static int swim3_add_device(struct macio_dev *mdev, int index) } dev_set_drvdata(&mdev->ofdev.dev, fs); - mediabay = (strcasecmp(swim->parent->type, "media-bay") == 0) ? - swim->parent : NULL; - if (mediabay == NULL) + if (mdev->media_bay == NULL) pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 1); memset(fs, 0, sizeof(*fs)); @@ -1068,7 +1061,7 @@ static int swim3_add_device(struct macio_dev *mdev, int index) fs->secpercyl = 36; fs->secpertrack = 18; fs->total_secs = 2880; - fs->media_bay = mediabay; + fs->mdev = mdev; init_waitqueue_head(&fs->wait); fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space); @@ -1093,7 +1086,7 @@ static int swim3_add_device(struct macio_dev *mdev, int index) init_timer(&fs->timeout); printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count, - mediabay ? "in media bay" : ""); + mdev->media_bay ? "in media bay" : ""); return 0; diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index b8578bb3f4c9c4393c83be80ddaa36eccc073264..05a31e55d27817bed3f8157c91389c31f0adb1f8 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -42,6 +42,7 @@ #include #include +#include #include #include #include diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 44bc8bbabf5474948d59eb8ce15cff6bef11b819..4d29059967517f2a54c02eabc55ef76f84ba1855 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -1066,7 +1066,7 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message) return 0; spin_lock_irq(&data->txlock); - if (!(interface_to_usbdev(intf)->auto_pm && data->tx_in_flight)) { + if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) { set_bit(BTUSB_SUSPENDING, &data->flags); spin_unlock_irq(&data->txlock); } else { diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 6aad99ec4e0f12626038c0d93c0a025b4d7d4b4d..6f31c947210093c756d0b516dbf5743f1b7a0c84 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -201,19 +201,6 @@ config DIGIEPCA To compile this driver as a module, choose M here: the module will be called epca. -config ESPSERIAL - tristate "Hayes ESP serial port support" - depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API && BROKEN - help - This is a driver which supports Hayes ESP serial ports. Both single - port cards and multiport cards are supported. Make sure to read - . - - To compile this driver as a module, choose M here: the - module will be called esp. - - If unsure, say N. - config MOXA_INTELLIO tristate "Moxa Intellio support" depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 19a79dd79eee0008503552ac41a14881205d87cd..f957edf7e45d2074bff77e2ac49a7edbe64cd98b 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -18,7 +18,6 @@ obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o obj-$(CONFIG_AUDIT) += tty_audit.o obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o -obj-$(CONFIG_ESPSERIAL) += esp.o obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 3cb56a049e249eed3eac9abb7d0e0c012fae067c..30c36ac2cd00e068fbb26b2a54f7e3fe96c5b597 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -36,10 +36,10 @@ #define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12 #define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC #define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE -#define PCI_DEVICE_ID_INTEL_IGDGM_HB 0xA010 -#define PCI_DEVICE_ID_INTEL_IGDGM_IG 0xA011 -#define PCI_DEVICE_ID_INTEL_IGDG_HB 0xA000 -#define PCI_DEVICE_ID_INTEL_IGDG_IG 0xA001 +#define PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB 0xA010 +#define PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG 0xA011 +#define PCI_DEVICE_ID_INTEL_PINEVIEW_HB 0xA000 +#define PCI_DEVICE_ID_INTEL_PINEVIEW_IG 0xA001 #define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0 #define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2 #define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0 @@ -50,20 +50,20 @@ #define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42 #define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40 #define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42 -#define PCI_DEVICE_ID_INTEL_IGD_E_HB 0x2E00 -#define PCI_DEVICE_ID_INTEL_IGD_E_IG 0x2E02 +#define PCI_DEVICE_ID_INTEL_EAGLELAKE_HB 0x2E00 +#define PCI_DEVICE_ID_INTEL_EAGLELAKE_IG 0x2E02 #define PCI_DEVICE_ID_INTEL_Q45_HB 0x2E10 #define PCI_DEVICE_ID_INTEL_Q45_IG 0x2E12 #define PCI_DEVICE_ID_INTEL_G45_HB 0x2E20 #define PCI_DEVICE_ID_INTEL_G45_IG 0x2E22 #define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30 #define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32 -#define PCI_DEVICE_ID_INTEL_IGDNG_D_HB 0x0040 -#define PCI_DEVICE_ID_INTEL_IGDNG_D_IG 0x0042 -#define PCI_DEVICE_ID_INTEL_IGDNG_M_HB 0x0044 -#define PCI_DEVICE_ID_INTEL_IGDNG_MA_HB 0x0062 -#define PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB 0x006a -#define PCI_DEVICE_ID_INTEL_IGDNG_M_IG 0x0046 +#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040 +#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042 +#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044 +#define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 +#define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a +#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046 /* cover 915 and 945 variants */ #define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \ @@ -83,22 +83,22 @@ #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDGM_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDG_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB) -#define IS_IGD (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDGM_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDG_HB) +#define IS_PINEVIEW (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB) -#define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_E_HB || \ +#define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_B43_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_D_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_M_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MA_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB) extern int agp_memory_reserved; @@ -178,6 +178,7 @@ static struct _intel_private { * popup and for the GTT. */ int gtt_entries; /* i830+ */ + int gtt_total_size; union { void __iomem *i9xx_flush_page; void *i8xx_flush_page; @@ -653,7 +654,7 @@ static void intel_i830_init_gtt_entries(void) size = 512; } size += 4; /* add in BIOS popup space */ - } else if (IS_G33 && !IS_IGD) { + } else if (IS_G33 && !IS_PINEVIEW) { /* G33's GTT size defined in gmch_ctrl */ switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { case G33_PGETBL_SIZE_1M: @@ -669,7 +670,7 @@ static void intel_i830_init_gtt_entries(void) size = 512; } size += 4; - } else if (IS_G4X || IS_IGD) { + } else if (IS_G4X || IS_PINEVIEW) { /* On 4 series hardware, GTT stolen is separate from graphics * stolen, ignore it in stolen gtt entries counting. However, * 4KB of the stolen memory doesn't get mapped to the GTT. @@ -1153,7 +1154,7 @@ static int intel_i915_configure(void) readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ if (agp_bridge->driver->needs_scratch_page) { - for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) { + for (i = intel_private.gtt_entries; i < intel_private.gtt_total_size; i++) { writel(agp_bridge->scratch_page, intel_private.gtt+i); } readl(intel_private.gtt+i-1); /* PCI Posting. */ @@ -1308,6 +1309,8 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) if (!intel_private.gtt) return -ENOMEM; + intel_private.gtt_total_size = gtt_map_size / 4; + temp &= 0xfff80000; intel_private.registers = ioremap(temp, 128 * 4096); @@ -1352,15 +1355,15 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) { switch (agp_bridge->dev->device) { case PCI_DEVICE_ID_INTEL_GM45_HB: - case PCI_DEVICE_ID_INTEL_IGD_E_HB: + case PCI_DEVICE_ID_INTEL_EAGLELAKE_HB: case PCI_DEVICE_ID_INTEL_Q45_HB: case PCI_DEVICE_ID_INTEL_G45_HB: case PCI_DEVICE_ID_INTEL_G41_HB: case PCI_DEVICE_ID_INTEL_B43_HB: - case PCI_DEVICE_ID_INTEL_IGDNG_D_HB: - case PCI_DEVICE_ID_INTEL_IGDNG_M_HB: - case PCI_DEVICE_ID_INTEL_IGDNG_MA_HB: - case PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB: + case PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB: + case PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB: + case PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB: + case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB: *gtt_offset = *gtt_size = MB(2); break; default: @@ -1395,6 +1398,8 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) if (!intel_private.gtt) return -ENOMEM; + intel_private.gtt_total_size = gtt_size / 4; + intel_private.registers = ioremap(temp, 128 * 4096); if (!intel_private.registers) { iounmap(intel_private.gtt); @@ -2340,14 +2345,14 @@ static const struct intel_driver_description { NULL, &intel_g33_driver }, { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33", NULL, &intel_g33_driver }, - { PCI_DEVICE_ID_INTEL_IGDGM_HB, PCI_DEVICE_ID_INTEL_IGDGM_IG, 0, "IGD", + { PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "Pineview", NULL, &intel_g33_driver }, - { PCI_DEVICE_ID_INTEL_IGDG_HB, PCI_DEVICE_ID_INTEL_IGDG_IG, 0, "IGD", + { PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "Pineview", NULL, &intel_g33_driver }, { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0, - "Mobile Intel® GM45 Express", NULL, &intel_i965_driver }, - { PCI_DEVICE_ID_INTEL_IGD_E_HB, PCI_DEVICE_ID_INTEL_IGD_E_IG, 0, - "Intel Integrated Graphics Device", NULL, &intel_i965_driver }, + "GM45", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_EAGLELAKE_HB, PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, 0, + "Eaglelake", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_Q45_HB, PCI_DEVICE_ID_INTEL_Q45_IG, 0, "Q45/Q43", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_G45_HB, PCI_DEVICE_ID_INTEL_G45_IG, 0, @@ -2356,14 +2361,14 @@ static const struct intel_driver_description { "B43", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0, "G41", NULL, &intel_i965_driver }, - { PCI_DEVICE_ID_INTEL_IGDNG_D_HB, PCI_DEVICE_ID_INTEL_IGDNG_D_IG, 0, - "IGDNG/D", NULL, &intel_i965_driver }, - { PCI_DEVICE_ID_INTEL_IGDNG_M_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0, - "IGDNG/M", NULL, &intel_i965_driver }, - { PCI_DEVICE_ID_INTEL_IGDNG_MA_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0, - "IGDNG/MA", NULL, &intel_i965_driver }, - { PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0, - "IGDNG/MC2", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 0, + "Ironlake/D", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0, + "Ironlake/M", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0, + "Ironlake/MA", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0, + "Ironlake/MC2", NULL, &intel_i965_driver }, { 0, 0, 0, NULL, NULL, NULL } }; @@ -2545,8 +2550,8 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_82945G_HB), ID(PCI_DEVICE_ID_INTEL_82945GM_HB), ID(PCI_DEVICE_ID_INTEL_82945GME_HB), - ID(PCI_DEVICE_ID_INTEL_IGDGM_HB), - ID(PCI_DEVICE_ID_INTEL_IGDG_HB), + ID(PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB), + ID(PCI_DEVICE_ID_INTEL_PINEVIEW_HB), ID(PCI_DEVICE_ID_INTEL_82946GZ_HB), ID(PCI_DEVICE_ID_INTEL_82G35_HB), ID(PCI_DEVICE_ID_INTEL_82965Q_HB), @@ -2557,15 +2562,15 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_Q35_HB), ID(PCI_DEVICE_ID_INTEL_Q33_HB), ID(PCI_DEVICE_ID_INTEL_GM45_HB), - ID(PCI_DEVICE_ID_INTEL_IGD_E_HB), + ID(PCI_DEVICE_ID_INTEL_EAGLELAKE_HB), ID(PCI_DEVICE_ID_INTEL_Q45_HB), ID(PCI_DEVICE_ID_INTEL_G45_HB), ID(PCI_DEVICE_ID_INTEL_G41_HB), ID(PCI_DEVICE_ID_INTEL_B43_HB), - ID(PCI_DEVICE_ID_INTEL_IGDNG_D_HB), - ID(PCI_DEVICE_ID_INTEL_IGDNG_M_HB), - ID(PCI_DEVICE_ID_INTEL_IGDNG_MA_HB), - ID(PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB), + ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB), + ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), + ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), + ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), { } }; diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 703959eba45a37d9b914fcf0b19e717f7bd88f2b..d89da4ac061f2d0c3aea71b51666039b203537ec 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -144,16 +144,13 @@ static int uninorth_configure(void) return 0; } -static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, - int type) +static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, int type) { - int i, j, num_entries; + int i, num_entries; void *temp; + u32 *gp; int mask_type; - temp = agp_bridge->current_size; - num_entries = A_SIZE_32(temp)->num_entries; - if (type != mem->type) return -EINVAL; @@ -163,49 +160,12 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, return -EINVAL; } - if ((pg_start + mem->page_count) > num_entries) - return -EINVAL; - - j = pg_start; - - while (j < (pg_start + mem->page_count)) { - if (agp_bridge->gatt_table[j]) - return -EBUSY; - j++; - } - - for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { - agp_bridge->gatt_table[j] = - cpu_to_le32((page_to_phys(mem->pages[i]) & 0xFFFFF000UL) | 0x1UL); - flush_dcache_range((unsigned long)__va(page_to_phys(mem->pages[i])), - (unsigned long)__va(page_to_phys(mem->pages[i]))+0x1000); - } - (void)in_le32((volatile u32*)&agp_bridge->gatt_table[pg_start]); - mb(); - - uninorth_tlbflush(mem); - return 0; -} - -static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type) -{ - int i, num_entries; - void *temp; - u32 *gp; - int mask_type; + if (mem->page_count == 0) + return 0; temp = agp_bridge->current_size; num_entries = A_SIZE_32(temp)->num_entries; - if (type != mem->type) - return -EINVAL; - - mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); - if (mask_type != 0) { - /* We know nothing of memory types */ - return -EINVAL; - } - if ((pg_start + mem->page_count) > num_entries) return -EINVAL; @@ -213,14 +173,18 @@ static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type) for (i = 0; i < mem->page_count; ++i) { if (gp[i]) { dev_info(&agp_bridge->dev->dev, - "u3_insert_memory: entry 0x%x occupied (%x)\n", + "uninorth_insert_memory: entry 0x%x occupied (%x)\n", i, gp[i]); return -EBUSY; } } for (i = 0; i < mem->page_count; i++) { - gp[i] = (page_to_phys(mem->pages[i]) >> PAGE_SHIFT) | 0x80000000UL; + if (is_u3) + gp[i] = (page_to_phys(mem->pages[i]) >> PAGE_SHIFT) | 0x80000000UL; + else + gp[i] = cpu_to_le32((page_to_phys(mem->pages[i]) & 0xFFFFF000UL) | + 0x1UL); flush_dcache_range((unsigned long)__va(page_to_phys(mem->pages[i])), (unsigned long)__va(page_to_phys(mem->pages[i]))+0x1000); } @@ -230,14 +194,23 @@ static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type) return 0; } -int u3_remove_memory(struct agp_memory *mem, off_t pg_start, int type) +int uninorth_remove_memory(struct agp_memory *mem, off_t pg_start, int type) { size_t i; u32 *gp; + int mask_type; + + if (type != mem->type) + return -EINVAL; - if (type != 0 || mem->type != 0) + mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); + if (mask_type != 0) { /* We know nothing of memory types */ return -EINVAL; + } + + if (mem->page_count == 0) + return 0; gp = (u32 *) &agp_bridge->gatt_table[pg_start]; for (i = 0; i < mem->page_count; ++i) @@ -536,7 +509,7 @@ const struct agp_bridge_driver uninorth_agp_driver = { .create_gatt_table = uninorth_create_gatt_table, .free_gatt_table = uninorth_free_gatt_table, .insert_memory = uninorth_insert_memory, - .remove_memory = agp_generic_remove_memory, + .remove_memory = uninorth_remove_memory, .alloc_by_type = agp_generic_alloc_by_type, .free_by_type = agp_generic_free_by_type, .agp_alloc_page = agp_generic_alloc_page, @@ -562,8 +535,8 @@ const struct agp_bridge_driver u3_agp_driver = { .agp_enable = uninorth_agp_enable, .create_gatt_table = uninorth_create_gatt_table, .free_gatt_table = uninorth_free_gatt_table, - .insert_memory = u3_insert_memory, - .remove_memory = u3_remove_memory, + .insert_memory = uninorth_insert_memory, + .remove_memory = uninorth_remove_memory, .alloc_by_type = agp_generic_alloc_by_type, .free_by_type = agp_generic_free_by_type, .agp_alloc_page = agp_generic_alloc_page, diff --git a/drivers/char/bfin_jtag_comm.c b/drivers/char/bfin_jtag_comm.c index 1d7c34c73b202594467bdac85fde9f634fdfc552..2628c7415ea863b07b0caa5064bbf0c0c42f3dfb 100644 --- a/drivers/char/bfin_jtag_comm.c +++ b/drivers/char/bfin_jtag_comm.c @@ -226,7 +226,7 @@ bfin_jc_wait_until_sent(struct tty_struct *tty, int timeout) } } -static struct tty_operations bfin_jc_ops = { +static const struct tty_operations bfin_jc_ops = { .open = bfin_jc_open, .close = bfin_jc_close, .write = bfin_jc_write, diff --git a/drivers/char/epca.c b/drivers/char/epca.c index dde5134713e23f88fe185e2f4216cd9ad62ebfac..17b044a71e026fc8c943de8ea5bf64c852abc75c 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -935,7 +935,7 @@ static int info_open(struct tty_struct *tty, struct file *filp) return 0; } -static struct tty_operations info_ops = { +static const struct tty_operations info_ops = { .open = info_open, .ioctl = info_ioctl, }; diff --git a/drivers/char/esp.c b/drivers/char/esp.c deleted file mode 100644 index b19d43cd9542d772513c4c4b70b83f2a14cdf8e7..0000000000000000000000000000000000000000 --- a/drivers/char/esp.c +++ /dev/null @@ -1,2533 +0,0 @@ -/* - * esp.c - driver for Hayes ESP serial cards - * - * --- Notices from serial.c, upon which this driver is based --- - * - * Copyright (C) 1991, 1992 Linus Torvalds - * - * Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92. Now - * much more extensible to support other serial cards based on the - * 16450/16550A UART's. Added support for the AST FourPort and the - * Accent Async board. - * - * set_serial_info fixed to set the flags, custom divisor, and uart - * type fields. Fix suggested by Michael K. Johnson 12/12/92. - * - * 11/95: TIOCMIWAIT, TIOCGICOUNT by Angelo Haritsis - * - * 03/96: Modularised by Angelo Haritsis - * - * rs_set_termios fixed to look also for changes of the input - * flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK. - * Bernd Anhäupl 05/17/96. - * - * --- End of notices from serial.c --- - * - * Support for the ESP serial card by Andrew J. Robinson - * (Card detection routine taken from a patch - * by Dennis J. Boylan). Patches to allow use with 2.1.x contributed - * by Chris Faylor. - * - * Most recent changes: (Andrew J. Robinson) - * Support for PIO mode. This allows the driver to work properly with - * multiport cards. - * - * Arnaldo Carvalho de Melo - - * several cleanups, use module_init/module_exit, etc - * - * This module exports the following rs232 io functions: - * - * int espserial_init(void); - */ - -#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 - -#define NR_PORTS 64 /* maximum number of ports */ -#define NR_PRIMARY 8 /* maximum number of primary ports */ -#define REGION_SIZE 8 /* size of io region to request */ - -/* The following variables can be set by giving module options */ -static int irq[NR_PRIMARY]; /* IRQ for each base port */ -static unsigned int divisor[NR_PRIMARY]; /* custom divisor for each port */ -static unsigned int dma = ESP_DMA_CHANNEL; /* DMA channel */ -static unsigned int rx_trigger = ESP_RX_TRIGGER; -static unsigned int tx_trigger = ESP_TX_TRIGGER; -static unsigned int flow_off = ESP_FLOW_OFF; -static unsigned int flow_on = ESP_FLOW_ON; -static unsigned int rx_timeout = ESP_RX_TMOUT; -static unsigned int pio_threshold = ESP_PIO_THRESHOLD; - -MODULE_LICENSE("GPL"); - -module_param_array(irq, int, NULL, 0); -module_param_array(divisor, uint, NULL, 0); -module_param(dma, uint, 0); -module_param(rx_trigger, uint, 0); -module_param(tx_trigger, uint, 0); -module_param(flow_off, uint, 0); -module_param(flow_on, uint, 0); -module_param(rx_timeout, uint, 0); -module_param(pio_threshold, uint, 0); - -/* END */ - -static char *dma_buffer; -static int dma_bytes; -static struct esp_pio_buffer *free_pio_buf; - -#define DMA_BUFFER_SZ 1024 - -#define WAKEUP_CHARS 1024 - -static char serial_name[] __initdata = "ESP serial driver"; -static char serial_version[] __initdata = "2.2"; - -static struct tty_driver *esp_driver; - -/* - * Serial driver configuration section. Here are the various options: - * - * SERIAL_PARANOIA_CHECK - * Check the magic number for the esp_structure where - * ever possible. - */ - -#undef SERIAL_PARANOIA_CHECK -#define SERIAL_DO_RESTART - -#undef SERIAL_DEBUG_INTR -#undef SERIAL_DEBUG_OPEN -#undef SERIAL_DEBUG_FLOW - -#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) -#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ - tty->name, info->port.flags, \ - serial_driver.refcount, \ - info->port.count, tty->count, s) -#else -#define DBG_CNT(s) -#endif - -static struct esp_struct *ports; - -static void change_speed(struct esp_struct *info); -static void rs_wait_until_sent(struct tty_struct *, int); - -/* - * The ESP card has a clock rate of 14.7456 MHz (that is, 2**ESPC_SCALE - * times the normal 1.8432 Mhz clock of most serial boards). - */ -#define BASE_BAUD ((1843200 / 16) * (1 << ESPC_SCALE)) - -/* Standard COM flags (except for COM4, because of the 8514 problem) */ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) - -static inline int serial_paranoia_check(struct esp_struct *info, - char *name, const char *routine) -{ -#ifdef SERIAL_PARANOIA_CHECK - static const char badmagic[] = KERN_WARNING - "Warning: bad magic number for serial struct (%s) in %s\n"; - static const char badinfo[] = KERN_WARNING - "Warning: null esp_struct for (%s) in %s\n"; - - if (!info) { - printk(badinfo, name, routine); - return 1; - } - if (info->magic != ESP_MAGIC) { - printk(badmagic, name, routine); - return 1; - } -#endif - return 0; -} - -static inline unsigned int serial_in(struct esp_struct *info, int offset) -{ - return inb(info->io_port + offset); -} - -static inline void serial_out(struct esp_struct *info, int offset, - unsigned char value) -{ - outb(value, info->io_port+offset); -} - -/* - * ------------------------------------------------------------ - * rs_stop() and rs_start() - * - * This routines are called before setting or resetting tty->stopped. - * They enable or disable transmitter interrupts, as necessary. - * ------------------------------------------------------------ - */ -static void rs_stop(struct tty_struct *tty) -{ - struct esp_struct *info = tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_stop")) - return; - - spin_lock_irqsave(&info->lock, flags); - if (info->IER & UART_IER_THRI) { - info->IER &= ~UART_IER_THRI; - serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); - serial_out(info, UART_ESI_CMD2, info->IER); - } - spin_unlock_irqrestore(&info->lock, flags); -} - -static void rs_start(struct tty_struct *tty) -{ - struct esp_struct *info = tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_start")) - return; - - spin_lock_irqsave(&info->lock, flags); - if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) { - info->IER |= UART_IER_THRI; - serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); - serial_out(info, UART_ESI_CMD2, info->IER); - } - spin_unlock_irqrestore(&info->lock, flags); -} - -/* - * ---------------------------------------------------------------------- - * - * Here starts the interrupt handling routines. All of the following - * subroutines are declared as inline and are folded into - * rs_interrupt(). They were separated out for readability's sake. - * - * Note: rs_interrupt() is a "fast" interrupt, which means that it - * runs with interrupts turned off. People who may want to modify - * rs_interrupt() should try to keep the interrupt handler as fast as - * possible. After you are done making modifications, it is not a bad - * idea to do: - * - * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c - * - * and look at the resulting assemble code in serial.s. - * - * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 - * ----------------------------------------------------------------------- - */ - -static DEFINE_SPINLOCK(pio_lock); - -static inline struct esp_pio_buffer *get_pio_buffer(void) -{ - struct esp_pio_buffer *buf; - unsigned long flags; - - spin_lock_irqsave(&pio_lock, flags); - if (free_pio_buf) { - buf = free_pio_buf; - free_pio_buf = buf->next; - } else { - buf = kmalloc(sizeof(struct esp_pio_buffer), GFP_ATOMIC); - } - spin_unlock_irqrestore(&pio_lock, flags); - return buf; -} - -static inline void release_pio_buffer(struct esp_pio_buffer *buf) -{ - unsigned long flags; - spin_lock_irqsave(&pio_lock, flags); - buf->next = free_pio_buf; - free_pio_buf = buf; - spin_unlock_irqrestore(&pio_lock, flags); -} - -static inline void receive_chars_pio(struct esp_struct *info, int num_bytes) -{ - struct tty_struct *tty = info->port.tty; - int i; - struct esp_pio_buffer *pio_buf; - struct esp_pio_buffer *err_buf; - unsigned char status_mask; - - pio_buf = get_pio_buffer(); - - if (!pio_buf) - return; - - err_buf = get_pio_buffer(); - - if (!err_buf) { - release_pio_buffer(pio_buf); - return; - } - - status_mask = (info->read_status_mask >> 2) & 0x07; - - for (i = 0; i < num_bytes - 1; i += 2) { - *((unsigned short *)(pio_buf->data + i)) = - inw(info->io_port + UART_ESI_RX); - err_buf->data[i] = serial_in(info, UART_ESI_RWS); - err_buf->data[i + 1] = (err_buf->data[i] >> 3) & status_mask; - err_buf->data[i] &= status_mask; - } - - if (num_bytes & 0x0001) { - pio_buf->data[num_bytes - 1] = serial_in(info, UART_ESI_RX); - err_buf->data[num_bytes - 1] = - (serial_in(info, UART_ESI_RWS) >> 3) & status_mask; - } - - /* make sure everything is still ok since interrupts were enabled */ - tty = info->port.tty; - - if (!tty) { - release_pio_buffer(pio_buf); - release_pio_buffer(err_buf); - info->stat_flags &= ~ESP_STAT_RX_TIMEOUT; - return; - } - - status_mask = (info->ignore_status_mask >> 2) & 0x07; - - for (i = 0; i < num_bytes; i++) { - if (!(err_buf->data[i] & status_mask)) { - int flag = 0; - - if (err_buf->data[i] & 0x04) { - flag = TTY_BREAK; - if (info->port.flags & ASYNC_SAK) - do_SAK(tty); - } else if (err_buf->data[i] & 0x02) - flag = TTY_FRAME; - else if (err_buf->data[i] & 0x01) - flag = TTY_PARITY; - tty_insert_flip_char(tty, pio_buf->data[i], flag); - } - } - - tty_schedule_flip(tty); - - info->stat_flags &= ~ESP_STAT_RX_TIMEOUT; - release_pio_buffer(pio_buf); - release_pio_buffer(err_buf); -} - -static void program_isa_dma(int dma, int dir, unsigned long addr, int len) -{ - unsigned long flags; - - flags = claim_dma_lock(); - disable_dma(dma); - clear_dma_ff(dma); - set_dma_mode(dma, dir); - set_dma_addr(dma, addr); - set_dma_count(dma, len); - enable_dma(dma); - release_dma_lock(flags); -} - -static void receive_chars_dma(struct esp_struct *info, int num_bytes) -{ - info->stat_flags &= ~ESP_STAT_RX_TIMEOUT; - dma_bytes = num_bytes; - info->stat_flags |= ESP_STAT_DMA_RX; - - program_isa_dma(dma, DMA_MODE_READ, isa_virt_to_bus(dma_buffer), - dma_bytes); - serial_out(info, UART_ESI_CMD1, ESI_START_DMA_RX); -} - -static inline void receive_chars_dma_done(struct esp_struct *info, - int status) -{ - struct tty_struct *tty = info->port.tty; - int num_bytes; - unsigned long flags; - - flags = claim_dma_lock(); - disable_dma(dma); - clear_dma_ff(dma); - - info->stat_flags &= ~ESP_STAT_DMA_RX; - num_bytes = dma_bytes - get_dma_residue(dma); - release_dma_lock(flags); - - info->icount.rx += num_bytes; - - if (num_bytes > 0) { - tty_insert_flip_string(tty, dma_buffer, num_bytes - 1); - - status &= (0x1c & info->read_status_mask); - - /* Is the status significant or do we throw the last byte ? */ - if (!(status & info->ignore_status_mask)) { - int statflag = 0; - - if (status & 0x10) { - statflag = TTY_BREAK; - (info->icount.brk)++; - if (info->port.flags & ASYNC_SAK) - do_SAK(tty); - } else if (status & 0x08) { - statflag = TTY_FRAME; - info->icount.frame++; - } else if (status & 0x04) { - statflag = TTY_PARITY; - info->icount.parity++; - } - tty_insert_flip_char(tty, dma_buffer[num_bytes - 1], - statflag); - } - tty_schedule_flip(tty); - } - - if (dma_bytes != num_bytes) { - num_bytes = dma_bytes - num_bytes; - dma_bytes = 0; - receive_chars_dma(info, num_bytes); - } else - dma_bytes = 0; -} - -/* Caller must hold info->lock */ - -static inline void transmit_chars_pio(struct esp_struct *info, - int space_avail) -{ - int i; - struct esp_pio_buffer *pio_buf; - - pio_buf = get_pio_buffer(); - - if (!pio_buf) - return; - - while (space_avail && info->xmit_cnt) { - if (info->xmit_tail + space_avail <= ESP_XMIT_SIZE) { - memcpy(pio_buf->data, - &(info->xmit_buf[info->xmit_tail]), - space_avail); - } else { - i = ESP_XMIT_SIZE - info->xmit_tail; - memcpy(pio_buf->data, - &(info->xmit_buf[info->xmit_tail]), i); - memcpy(&(pio_buf->data[i]), info->xmit_buf, - space_avail - i); - } - - info->xmit_cnt -= space_avail; - info->xmit_tail = (info->xmit_tail + space_avail) & - (ESP_XMIT_SIZE - 1); - - for (i = 0; i < space_avail - 1; i += 2) { - outw(*((unsigned short *)(pio_buf->data + i)), - info->io_port + UART_ESI_TX); - } - - if (space_avail & 0x0001) - serial_out(info, UART_ESI_TX, - pio_buf->data[space_avail - 1]); - - if (info->xmit_cnt) { - serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); - serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL); - space_avail = serial_in(info, UART_ESI_STAT1) << 8; - space_avail |= serial_in(info, UART_ESI_STAT2); - - if (space_avail > info->xmit_cnt) - space_avail = info->xmit_cnt; - } - } - - if (info->xmit_cnt < WAKEUP_CHARS) { - if (info->port.tty) - tty_wakeup(info->port.tty); - -#ifdef SERIAL_DEBUG_INTR - printk("THRE..."); -#endif - - if (info->xmit_cnt <= 0) { - info->IER &= ~UART_IER_THRI; - serial_out(info, UART_ESI_CMD1, - ESI_SET_SRV_MASK); - serial_out(info, UART_ESI_CMD2, info->IER); - } - } - - release_pio_buffer(pio_buf); -} - -/* Caller must hold info->lock */ -static inline void transmit_chars_dma(struct esp_struct *info, int num_bytes) -{ - dma_bytes = num_bytes; - - if (info->xmit_tail + dma_bytes <= ESP_XMIT_SIZE) { - memcpy(dma_buffer, &(info->xmit_buf[info->xmit_tail]), - dma_bytes); - } else { - int i = ESP_XMIT_SIZE - info->xmit_tail; - memcpy(dma_buffer, &(info->xmit_buf[info->xmit_tail]), - i); - memcpy(&(dma_buffer[i]), info->xmit_buf, dma_bytes - i); - } - - info->xmit_cnt -= dma_bytes; - info->xmit_tail = (info->xmit_tail + dma_bytes) & (ESP_XMIT_SIZE - 1); - - if (info->xmit_cnt < WAKEUP_CHARS) { - if (info->port.tty) - tty_wakeup(info->port.tty); - -#ifdef SERIAL_DEBUG_INTR - printk("THRE..."); -#endif - - if (info->xmit_cnt <= 0) { - info->IER &= ~UART_IER_THRI; - serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); - serial_out(info, UART_ESI_CMD2, info->IER); - } - } - - info->stat_flags |= ESP_STAT_DMA_TX; - - program_isa_dma(dma, DMA_MODE_WRITE, isa_virt_to_bus(dma_buffer), - dma_bytes); - serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX); -} - -static inline void transmit_chars_dma_done(struct esp_struct *info) -{ - int num_bytes; - unsigned long flags; - - flags = claim_dma_lock(); - disable_dma(dma); - clear_dma_ff(dma); - - num_bytes = dma_bytes - get_dma_residue(dma); - info->icount.tx += dma_bytes; - release_dma_lock(flags); - - if (dma_bytes != num_bytes) { - dma_bytes -= num_bytes; - memmove(dma_buffer, dma_buffer + num_bytes, dma_bytes); - - program_isa_dma(dma, DMA_MODE_WRITE, - isa_virt_to_bus(dma_buffer), dma_bytes); - - serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX); - } else { - dma_bytes = 0; - info->stat_flags &= ~ESP_STAT_DMA_TX; - } -} - -static void check_modem_status(struct esp_struct *info) -{ - int status; - - serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); - status = serial_in(info, UART_ESI_STAT2); - - if (status & UART_MSR_ANY_DELTA) { - /* update input line counters */ - if (status & UART_MSR_TERI) - info->icount.rng++; - if (status & UART_MSR_DDSR) - info->icount.dsr++; - if (status & UART_MSR_DDCD) - info->icount.dcd++; - if (status & UART_MSR_DCTS) - info->icount.cts++; - wake_up_interruptible(&info->port.delta_msr_wait); - } - - if ((info->port.flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { -#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) - printk("ttys%d CD now %s...", info->line, - (status & UART_MSR_DCD) ? "on" : "off"); -#endif - if (status & UART_MSR_DCD) - wake_up_interruptible(&info->port.open_wait); - else { -#ifdef SERIAL_DEBUG_OPEN - printk("scheduling hangup..."); -#endif - tty_hangup(info->port.tty); - } - } -} - -/* - * This is the serial driver's interrupt routine - */ -static irqreturn_t rs_interrupt_single(int irq, void *dev_id) -{ - struct esp_struct *info; - unsigned err_status; - unsigned int scratch; - -#ifdef SERIAL_DEBUG_INTR - printk("rs_interrupt_single(%d)...", irq); -#endif - info = (struct esp_struct *)dev_id; - err_status = 0; - scratch = serial_in(info, UART_ESI_SID); - - spin_lock(&info->lock); - - if (!info->port.tty) { - spin_unlock(&info->lock); - return IRQ_NONE; - } - - if (scratch & 0x04) { /* error */ - serial_out(info, UART_ESI_CMD1, ESI_GET_ERR_STAT); - err_status = serial_in(info, UART_ESI_STAT1); - serial_in(info, UART_ESI_STAT2); - - if (err_status & 0x01) - info->stat_flags |= ESP_STAT_RX_TIMEOUT; - - if (err_status & 0x20) /* UART status */ - check_modem_status(info); - - if (err_status & 0x80) /* Start break */ - wake_up_interruptible(&info->break_wait); - } - - if ((scratch & 0x88) || /* DMA completed or timed out */ - (err_status & 0x1c) /* receive error */) { - if (info->stat_flags & ESP_STAT_DMA_RX) - receive_chars_dma_done(info, err_status); - else if (info->stat_flags & ESP_STAT_DMA_TX) - transmit_chars_dma_done(info); - } - - if (!(info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) && - ((scratch & 0x01) || (info->stat_flags & ESP_STAT_RX_TIMEOUT)) && - (info->IER & UART_IER_RDI)) { - int num_bytes; - - serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); - serial_out(info, UART_ESI_CMD1, ESI_GET_RX_AVAIL); - num_bytes = serial_in(info, UART_ESI_STAT1) << 8; - num_bytes |= serial_in(info, UART_ESI_STAT2); - - num_bytes = tty_buffer_request_room(info->port.tty, num_bytes); - - if (num_bytes) { - if (dma_bytes || - (info->stat_flags & ESP_STAT_USE_PIO) || - (num_bytes <= info->config.pio_threshold)) - receive_chars_pio(info, num_bytes); - else - receive_chars_dma(info, num_bytes); - } - } - - if (!(info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) && - (scratch & 0x02) && (info->IER & UART_IER_THRI)) { - if ((info->xmit_cnt <= 0) || info->port.tty->stopped) { - info->IER &= ~UART_IER_THRI; - serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); - serial_out(info, UART_ESI_CMD2, info->IER); - } else { - int num_bytes; - - serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); - serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL); - num_bytes = serial_in(info, UART_ESI_STAT1) << 8; - num_bytes |= serial_in(info, UART_ESI_STAT2); - - if (num_bytes > info->xmit_cnt) - num_bytes = info->xmit_cnt; - - if (num_bytes) { - if (dma_bytes || - (info->stat_flags & ESP_STAT_USE_PIO) || - (num_bytes <= info->config.pio_threshold)) - transmit_chars_pio(info, num_bytes); - else - transmit_chars_dma(info, num_bytes); - } - } - } - - info->last_active = jiffies; - -#ifdef SERIAL_DEBUG_INTR - printk("end.\n"); -#endif - spin_unlock(&info->lock); - return IRQ_HANDLED; -} - -/* - * ------------------------------------------------------------------- - * Here ends the serial interrupt routines. - * ------------------------------------------------------------------- - */ - -/* - * --------------------------------------------------------------- - * Low level utility subroutines for the serial driver: routines to - * figure out the appropriate timeout for an interrupt chain, routines - * to initialize and startup a serial port, and routines to shutdown a - * serial port. Useful stuff like that. - * - * Caller should hold lock - * --------------------------------------------------------------- - */ - -static void esp_basic_init(struct esp_struct *info) -{ - /* put ESPC in enhanced mode */ - serial_out(info, UART_ESI_CMD1, ESI_SET_MODE); - - if (info->stat_flags & ESP_STAT_NEVER_DMA) - serial_out(info, UART_ESI_CMD2, 0x01); - else - serial_out(info, UART_ESI_CMD2, 0x31); - - /* disable interrupts for now */ - serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); - serial_out(info, UART_ESI_CMD2, 0x00); - - /* set interrupt and DMA channel */ - serial_out(info, UART_ESI_CMD1, ESI_SET_IRQ); - - if (info->stat_flags & ESP_STAT_NEVER_DMA) - serial_out(info, UART_ESI_CMD2, 0x01); - else - serial_out(info, UART_ESI_CMD2, (dma << 4) | 0x01); - - serial_out(info, UART_ESI_CMD1, ESI_SET_ENH_IRQ); - - if (info->line % 8) /* secondary port */ - serial_out(info, UART_ESI_CMD2, 0x0d); /* shared */ - else if (info->irq == 9) - serial_out(info, UART_ESI_CMD2, 0x02); - else - serial_out(info, UART_ESI_CMD2, info->irq); - - /* set error status mask (check this) */ - serial_out(info, UART_ESI_CMD1, ESI_SET_ERR_MASK); - - if (info->stat_flags & ESP_STAT_NEVER_DMA) - serial_out(info, UART_ESI_CMD2, 0xa1); - else - serial_out(info, UART_ESI_CMD2, 0xbd); - - serial_out(info, UART_ESI_CMD2, 0x00); - - /* set DMA timeout */ - serial_out(info, UART_ESI_CMD1, ESI_SET_DMA_TMOUT); - serial_out(info, UART_ESI_CMD2, 0xff); - - /* set FIFO trigger levels */ - serial_out(info, UART_ESI_CMD1, ESI_SET_TRIGGER); - serial_out(info, UART_ESI_CMD2, info->config.rx_trigger >> 8); - serial_out(info, UART_ESI_CMD2, info->config.rx_trigger); - serial_out(info, UART_ESI_CMD2, info->config.tx_trigger >> 8); - serial_out(info, UART_ESI_CMD2, info->config.tx_trigger); - - /* Set clock scaling and wait states */ - serial_out(info, UART_ESI_CMD1, ESI_SET_PRESCALAR); - serial_out(info, UART_ESI_CMD2, 0x04 | ESPC_SCALE); - - /* set reinterrupt pacing */ - serial_out(info, UART_ESI_CMD1, ESI_SET_REINTR); - serial_out(info, UART_ESI_CMD2, 0xff); -} - -static int startup(struct esp_struct *info) -{ - unsigned long flags; - int retval = 0; - unsigned int num_chars; - - spin_lock_irqsave(&info->lock, flags); - - if (info->port.flags & ASYNC_INITIALIZED) - goto out; - - if (!info->xmit_buf) { - info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_ATOMIC); - retval = -ENOMEM; - if (!info->xmit_buf) - goto out; - } - -#ifdef SERIAL_DEBUG_OPEN - printk(KERN_DEBUG "starting up ttys%d (irq %d)...", - info->line, info->irq); -#endif - - /* Flush the RX buffer. Using the ESI flush command may cause */ - /* wild interrupts, so read all the data instead. */ - - serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); - serial_out(info, UART_ESI_CMD1, ESI_GET_RX_AVAIL); - num_chars = serial_in(info, UART_ESI_STAT1) << 8; - num_chars |= serial_in(info, UART_ESI_STAT2); - - while (num_chars > 1) { - inw(info->io_port + UART_ESI_RX); - num_chars -= 2; - } - - if (num_chars) - serial_in(info, UART_ESI_RX); - - /* set receive character timeout */ - serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT); - serial_out(info, UART_ESI_CMD2, info->config.rx_timeout); - - /* clear all flags except the "never DMA" flag */ - info->stat_flags &= ESP_STAT_NEVER_DMA; - - if (info->stat_flags & ESP_STAT_NEVER_DMA) - info->stat_flags |= ESP_STAT_USE_PIO; - - spin_unlock_irqrestore(&info->lock, flags); - - /* - * Allocate the IRQ - */ - - retval = request_irq(info->irq, rs_interrupt_single, IRQF_SHARED, - "esp serial", info); - - if (retval) { - if (capable(CAP_SYS_ADMIN)) { - if (info->port.tty) - set_bit(TTY_IO_ERROR, - &info->port.tty->flags); - retval = 0; - } - goto out_unlocked; - } - - if (!(info->stat_flags & ESP_STAT_USE_PIO) && !dma_buffer) { - dma_buffer = (char *)__get_dma_pages( - GFP_KERNEL, get_order(DMA_BUFFER_SZ)); - - /* use PIO mode if DMA buf/chan cannot be allocated */ - if (!dma_buffer) - info->stat_flags |= ESP_STAT_USE_PIO; - else if (request_dma(dma, "esp serial")) { - free_pages((unsigned long)dma_buffer, - get_order(DMA_BUFFER_SZ)); - dma_buffer = NULL; - info->stat_flags |= ESP_STAT_USE_PIO; - } - - } - - info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; - - spin_lock_irqsave(&info->lock, flags); - serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); - serial_out(info, UART_ESI_CMD2, UART_MCR); - serial_out(info, UART_ESI_CMD2, info->MCR); - - /* - * Finally, enable interrupts - */ - /* info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; */ - info->IER = UART_IER_RLSI | UART_IER_RDI | UART_IER_DMA_TMOUT | - UART_IER_DMA_TC; - serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); - serial_out(info, UART_ESI_CMD2, info->IER); - - if (info->port.tty) - clear_bit(TTY_IO_ERROR, &info->port.tty->flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - spin_unlock_irqrestore(&info->lock, flags); - - /* - * Set up the tty->alt_speed kludge - */ - if (info->port.tty) { - if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->port.tty->alt_speed = 57600; - if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->port.tty->alt_speed = 115200; - if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->port.tty->alt_speed = 230400; - if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->port.tty->alt_speed = 460800; - } - - /* - * set the speed of the serial port - */ - change_speed(info); - info->port.flags |= ASYNC_INITIALIZED; - return 0; - -out: - spin_unlock_irqrestore(&info->lock, flags); -out_unlocked: - return retval; -} - -/* - * 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 shutdown(struct esp_struct *info) -{ - unsigned long flags, f; - - if (!(info->port.flags & ASYNC_INITIALIZED)) - return; - -#ifdef SERIAL_DEBUG_OPEN - printk("Shutting down serial port %d (irq %d)....", info->line, - info->irq); -#endif - - spin_lock_irqsave(&info->lock, flags); - /* - * clear delta_msr_wait queue to avoid mem leaks: we may free the irq - * here so the queue might never be waken up - */ - wake_up_interruptible(&info->port.delta_msr_wait); - wake_up_interruptible(&info->break_wait); - - /* stop a DMA transfer on the port being closed */ - /* DMA lock is higher priority always */ - if (info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) { - f = claim_dma_lock(); - disable_dma(dma); - clear_dma_ff(dma); - release_dma_lock(f); - - dma_bytes = 0; - } - - /* - * Free the IRQ - */ - free_irq(info->irq, info); - - if (dma_buffer) { - struct esp_struct *current_port = ports; - - while (current_port) { - if ((current_port != info) && - (current_port->port.flags & ASYNC_INITIALIZED)) - break; - - current_port = current_port->next_port; - } - - if (!current_port) { - free_dma(dma); - free_pages((unsigned long)dma_buffer, - get_order(DMA_BUFFER_SZ)); - dma_buffer = NULL; - } - } - - if (info->xmit_buf) { - free_page((unsigned long) info->xmit_buf); - info->xmit_buf = NULL; - } - - info->IER = 0; - serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); - serial_out(info, UART_ESI_CMD2, 0x00); - - if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) - info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); - - info->MCR &= ~UART_MCR_OUT2; - serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); - serial_out(info, UART_ESI_CMD2, UART_MCR); - serial_out(info, UART_ESI_CMD2, info->MCR); - - if (info->port.tty) - set_bit(TTY_IO_ERROR, &info->port.tty->flags); - - info->port.flags &= ~ASYNC_INITIALIZED; - spin_unlock_irqrestore(&info->lock, flags); -} - -/* - * This routine is called to set the UART divisor registers to match - * the specified baud rate for a serial port. - */ -static void change_speed(struct esp_struct *info) -{ - unsigned short port; - int quot = 0; - unsigned cflag, cval; - int baud, bits; - unsigned char flow1 = 0, flow2 = 0; - unsigned long flags; - - if (!info->port.tty || !info->port.tty->termios) - return; - cflag = info->port.tty->termios->c_cflag; - port = info->io_port; - - /* byte size and parity */ - switch (cflag & CSIZE) { - case CS5: cval = 0x00; bits = 7; break; - case CS6: cval = 0x01; bits = 8; break; - case CS7: cval = 0x02; bits = 9; break; - case CS8: cval = 0x03; bits = 10; break; - default: cval = 0x00; bits = 7; break; - } - if (cflag & CSTOPB) { - cval |= 0x04; - bits++; - } - if (cflag & PARENB) { - cval |= UART_LCR_PARITY; - bits++; - } - if (!(cflag & PARODD)) - cval |= UART_LCR_EPAR; -#ifdef CMSPAR - if (cflag & CMSPAR) - cval |= UART_LCR_SPAR; -#endif - baud = tty_get_baud_rate(info->port.tty); - if (baud == 38400 && - ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) - quot = info->custom_divisor; - else { - if (baud == 134) /* Special case since 134 is really 134.5 */ - quot = (2*BASE_BAUD / 269); - else if (baud) - quot = BASE_BAUD / baud; - } - /* If the quotient is ever zero, default to 9600 bps */ - if (!quot) - quot = BASE_BAUD / 9600; - - if (baud) { - /* Actual rate */ - baud = BASE_BAUD/quot; - tty_encode_baud_rate(info->port.tty, baud, baud); - } - info->timeout = ((1024 * HZ * bits * quot) / BASE_BAUD) + (HZ / 50); - - /* CTS flow control flag and modem status interrupts */ - /* info->IER &= ~UART_IER_MSI; */ - if (cflag & CRTSCTS) { - info->port.flags |= ASYNC_CTS_FLOW; - /* info->IER |= UART_IER_MSI; */ - flow1 = 0x04; - flow2 = 0x10; - } else - info->port.flags &= ~ASYNC_CTS_FLOW; - if (cflag & CLOCAL) - info->port.flags &= ~ASYNC_CHECK_CD; - else - info->port.flags |= ASYNC_CHECK_CD; - - /* - * Set up parity check flag - */ - info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; - if (I_INPCK(info->port.tty)) - info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; - if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) - info->read_status_mask |= UART_LSR_BI; - - info->ignore_status_mask = 0; -#if 0 - /* This should be safe, but for some broken bits of hardware... */ - if (I_IGNPAR(info->port.tty)) { - info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; - info->read_status_mask |= UART_LSR_PE | UART_LSR_FE; - } -#endif - if (I_IGNBRK(info->port.tty)) { - info->ignore_status_mask |= UART_LSR_BI; - info->read_status_mask |= UART_LSR_BI; - /* - * If we're ignore parity and break indicators, ignore - * overruns too. (For real raw support). - */ - if (I_IGNPAR(info->port.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; - } - } - - if (I_IXOFF(info->port.tty)) - flow1 |= 0x81; - - spin_lock_irqsave(&info->lock, flags); - /* set baud */ - serial_out(info, UART_ESI_CMD1, ESI_SET_BAUD); - serial_out(info, UART_ESI_CMD2, quot >> 8); - serial_out(info, UART_ESI_CMD2, quot & 0xff); - - /* set data bits, parity, etc. */ - serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); - serial_out(info, UART_ESI_CMD2, UART_LCR); - serial_out(info, UART_ESI_CMD2, cval); - - /* Enable flow control */ - serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_CNTL); - serial_out(info, UART_ESI_CMD2, flow1); - serial_out(info, UART_ESI_CMD2, flow2); - - /* set flow control characters (XON/XOFF only) */ - if (I_IXOFF(info->port.tty)) { - serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_CHARS); - serial_out(info, UART_ESI_CMD2, START_CHAR(info->port.tty)); - serial_out(info, UART_ESI_CMD2, STOP_CHAR(info->port.tty)); - serial_out(info, UART_ESI_CMD2, 0x10); - serial_out(info, UART_ESI_CMD2, 0x21); - switch (cflag & CSIZE) { - case CS5: - serial_out(info, UART_ESI_CMD2, 0x1f); - break; - case CS6: - serial_out(info, UART_ESI_CMD2, 0x3f); - break; - case CS7: - case CS8: - serial_out(info, UART_ESI_CMD2, 0x7f); - break; - default: - serial_out(info, UART_ESI_CMD2, 0xff); - break; - } - } - - /* Set high/low water */ - serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_LVL); - serial_out(info, UART_ESI_CMD2, info->config.flow_off >> 8); - serial_out(info, UART_ESI_CMD2, info->config.flow_off); - serial_out(info, UART_ESI_CMD2, info->config.flow_on >> 8); - serial_out(info, UART_ESI_CMD2, info->config.flow_on); - - spin_unlock_irqrestore(&info->lock, flags); -} - -static int rs_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct esp_struct *info = tty->driver_data; - unsigned long flags; - int ret = 0; - - if (serial_paranoia_check(info, tty->name, "rs_put_char")) - return 0; - - if (!info->xmit_buf) - return 0; - - spin_lock_irqsave(&info->lock, flags); - if (info->xmit_cnt < ESP_XMIT_SIZE - 1) { - info->xmit_buf[info->xmit_head++] = ch; - info->xmit_head &= ESP_XMIT_SIZE-1; - info->xmit_cnt++; - ret = 1; - } - spin_unlock_irqrestore(&info->lock, flags); - return ret; -} - -static void rs_flush_chars(struct tty_struct *tty) -{ - struct esp_struct *info = tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) - return; - - spin_lock_irqsave(&info->lock, flags); - - if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf) - goto out; - - if (!(info->IER & UART_IER_THRI)) { - info->IER |= UART_IER_THRI; - serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); - serial_out(info, UART_ESI_CMD2, info->IER); - } -out: - spin_unlock_irqrestore(&info->lock, flags); -} - -static int rs_write(struct tty_struct *tty, - const unsigned char *buf, int count) -{ - int c, t, ret = 0; - struct esp_struct *info = tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_write")) - return 0; - - if (!info->xmit_buf) - return 0; - - while (1) { - /* Thanks to R. Wolff for suggesting how to do this with */ - /* interrupts enabled */ - - c = count; - t = ESP_XMIT_SIZE - info->xmit_cnt - 1; - - if (t < c) - c = t; - - t = ESP_XMIT_SIZE - info->xmit_head; - - if (t < c) - c = t; - - if (c <= 0) - break; - - memcpy(info->xmit_buf + info->xmit_head, buf, c); - - info->xmit_head = (info->xmit_head + c) & (ESP_XMIT_SIZE-1); - info->xmit_cnt += c; - buf += c; - count -= c; - ret += c; - } - - spin_lock_irqsave(&info->lock, flags); - - if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) { - info->IER |= UART_IER_THRI; - serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); - serial_out(info, UART_ESI_CMD2, info->IER); - } - - spin_unlock_irqrestore(&info->lock, flags); - return ret; -} - -static int rs_write_room(struct tty_struct *tty) -{ - struct esp_struct *info = tty->driver_data; - int ret; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_write_room")) - return 0; - - spin_lock_irqsave(&info->lock, flags); - - ret = ESP_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - spin_unlock_irqrestore(&info->lock, flags); - return ret; -} - -static int rs_chars_in_buffer(struct tty_struct *tty) -{ - struct esp_struct *info = tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) - return 0; - return info->xmit_cnt; -} - -static void rs_flush_buffer(struct tty_struct *tty) -{ - struct esp_struct *info = tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) - return; - spin_lock_irqsave(&info->lock, flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - spin_unlock_irqrestore(&info->lock, flags); - tty_wakeup(tty); -} - -/* - * ------------------------------------------------------------ - * rs_throttle() - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - * ------------------------------------------------------------ - */ -static void rs_throttle(struct tty_struct *tty) -{ - struct esp_struct *info = tty->driver_data; - unsigned long flags; -#ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - printk("throttle %s: %d....\n", tty_name(tty, buf), - tty_chars_in_buffer(tty)); -#endif - - if (serial_paranoia_check(info, tty->name, "rs_throttle")) - return; - - spin_lock_irqsave(&info->lock, flags); - info->IER &= ~UART_IER_RDI; - serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); - serial_out(info, UART_ESI_CMD2, info->IER); - serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT); - serial_out(info, UART_ESI_CMD2, 0x00); - spin_unlock_irqrestore(&info->lock, flags); -} - -static void rs_unthrottle(struct tty_struct *tty) -{ - struct esp_struct *info = tty->driver_data; - unsigned long flags; -#ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - printk(KERN_DEBUG "unthrottle %s: %d....\n", tty_name(tty, buf), - tty_chars_in_buffer(tty)); -#endif - - if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) - return; - - spin_lock_irqsave(&info->lock, flags); - info->IER |= UART_IER_RDI; - serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); - serial_out(info, UART_ESI_CMD2, info->IER); - serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT); - serial_out(info, UART_ESI_CMD2, info->config.rx_timeout); - spin_unlock_irqrestore(&info->lock, flags); -} - -/* - * ------------------------------------------------------------ - * rs_ioctl() and friends - * ------------------------------------------------------------ - */ - -static int get_serial_info(struct esp_struct *info, - struct serial_struct __user *retinfo) -{ - struct serial_struct tmp; - - lock_kernel(); - memset(&tmp, 0, sizeof(tmp)); - tmp.type = PORT_16550A; - tmp.line = info->line; - tmp.port = info->io_port; - tmp.irq = info->irq; - tmp.flags = info->port.flags; - tmp.xmit_fifo_size = 1024; - tmp.baud_base = BASE_BAUD; - tmp.close_delay = info->close_delay; - tmp.closing_wait = info->closing_wait; - tmp.custom_divisor = info->custom_divisor; - tmp.hub6 = 0; - unlock_kernel(); - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - return 0; -} - -static int get_esp_config(struct esp_struct *info, - struct hayes_esp_config __user *retinfo) -{ - struct hayes_esp_config tmp; - - if (!retinfo) - return -EFAULT; - - memset(&tmp, 0, sizeof(tmp)); - lock_kernel(); - tmp.rx_timeout = info->config.rx_timeout; - tmp.rx_trigger = info->config.rx_trigger; - tmp.tx_trigger = info->config.tx_trigger; - tmp.flow_off = info->config.flow_off; - tmp.flow_on = info->config.flow_on; - tmp.pio_threshold = info->config.pio_threshold; - tmp.dma_channel = (info->stat_flags & ESP_STAT_NEVER_DMA ? 0 : dma); - unlock_kernel(); - - return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; -} - -static int set_serial_info(struct esp_struct *info, - struct serial_struct __user *new_info) -{ - struct serial_struct new_serial; - struct esp_struct old_info; - unsigned int change_irq; - int retval = 0; - struct esp_struct *current_async; - - if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) - return -EFAULT; - old_info = *info; - - if ((new_serial.type != PORT_16550A) || - (new_serial.hub6) || - (info->io_port != new_serial.port) || - (new_serial.baud_base != BASE_BAUD) || - (new_serial.irq > 15) || - (new_serial.irq < 2) || - (new_serial.irq == 6) || - (new_serial.irq == 8) || - (new_serial.irq == 13)) - return -EINVAL; - - change_irq = new_serial.irq != info->irq; - - if (change_irq && (info->line % 8)) - return -EINVAL; - - if (!capable(CAP_SYS_ADMIN)) { - if (change_irq || - (new_serial.close_delay != info->close_delay) || - ((new_serial.flags & ~ASYNC_USR_MASK) != - (info->port.flags & ~ASYNC_USR_MASK))) - return -EPERM; - info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - info->custom_divisor = new_serial.custom_divisor; - } else { - if (new_serial.irq == 2) - new_serial.irq = 9; - - if (change_irq) { - current_async = ports; - - while (current_async) { - if ((current_async->line >= info->line) && - (current_async->line < (info->line + 8))) { - if (current_async == info) { - if (current_async->port.count > 1) - return -EBUSY; - } else if (current_async->port.count) - return -EBUSY; - } - - current_async = current_async->next_port; - } - } - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - - info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - info->custom_divisor = new_serial.custom_divisor; - info->close_delay = new_serial.close_delay * HZ/100; - info->closing_wait = new_serial.closing_wait * HZ/100; - - if (change_irq) { - /* - * We need to shutdown the serial port at the old - * port/irq combination. - */ - shutdown(info); - - current_async = ports; - - while (current_async) { - if ((current_async->line >= info->line) && - (current_async->line < (info->line + 8))) - current_async->irq = new_serial.irq; - - current_async = current_async->next_port; - } - - serial_out(info, UART_ESI_CMD1, ESI_SET_ENH_IRQ); - if (info->irq == 9) - serial_out(info, UART_ESI_CMD2, 0x02); - else - serial_out(info, UART_ESI_CMD2, info->irq); - } - } - - if (info->port.flags & ASYNC_INITIALIZED) { - if (((old_info.port.flags & ASYNC_SPD_MASK) != - (info->port.flags & ASYNC_SPD_MASK)) || - (old_info.custom_divisor != info->custom_divisor)) { - if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->port.tty->alt_speed = 57600; - if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->port.tty->alt_speed = 115200; - if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->port.tty->alt_speed = 230400; - if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->port.tty->alt_speed = 460800; - change_speed(info); - } - } else - retval = startup(info); - - return retval; -} - -static int set_esp_config(struct esp_struct *info, - struct hayes_esp_config __user *new_info) -{ - struct hayes_esp_config new_config; - unsigned int change_dma; - int retval = 0; - struct esp_struct *current_async; - unsigned long flags; - - /* Perhaps a non-sysadmin user should be able to do some of these */ - /* operations. I haven't decided yet. */ - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - if (copy_from_user(&new_config, new_info, sizeof(new_config))) - return -EFAULT; - - if ((new_config.flow_on >= new_config.flow_off) || - (new_config.rx_trigger < 1) || - (new_config.tx_trigger < 1) || - (new_config.flow_off < 1) || - (new_config.flow_on < 1) || - (new_config.rx_trigger > 1023) || - (new_config.tx_trigger > 1023) || - (new_config.flow_off > 1023) || - (new_config.flow_on > 1023) || - (new_config.pio_threshold < 0) || - (new_config.pio_threshold > 1024)) - return -EINVAL; - - if ((new_config.dma_channel != 1) && (new_config.dma_channel != 3)) - new_config.dma_channel = 0; - - if (info->stat_flags & ESP_STAT_NEVER_DMA) - change_dma = new_config.dma_channel; - else - change_dma = (new_config.dma_channel != dma); - - if (change_dma) { - if (new_config.dma_channel) { - /* PIO mode to DMA mode transition OR */ - /* change current DMA channel */ - current_async = ports; - - while (current_async) { - if (current_async == info) { - if (current_async->port.count > 1) - return -EBUSY; - } else if (current_async->port.count) - return -EBUSY; - - current_async = current_async->next_port; - } - - shutdown(info); - dma = new_config.dma_channel; - info->stat_flags &= ~ESP_STAT_NEVER_DMA; - - /* all ports must use the same DMA channel */ - - spin_lock_irqsave(&info->lock, flags); - current_async = ports; - - while (current_async) { - esp_basic_init(current_async); - current_async = current_async->next_port; - } - spin_unlock_irqrestore(&info->lock, flags); - } else { - /* DMA mode to PIO mode only */ - if (info->port.count > 1) - return -EBUSY; - - shutdown(info); - spin_lock_irqsave(&info->lock, flags); - info->stat_flags |= ESP_STAT_NEVER_DMA; - esp_basic_init(info); - spin_unlock_irqrestore(&info->lock, flags); - } - } - - info->config.pio_threshold = new_config.pio_threshold; - - if ((new_config.flow_off != info->config.flow_off) || - (new_config.flow_on != info->config.flow_on)) { - info->config.flow_off = new_config.flow_off; - info->config.flow_on = new_config.flow_on; - - spin_lock_irqsave(&info->lock, flags); - serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_LVL); - serial_out(info, UART_ESI_CMD2, new_config.flow_off >> 8); - serial_out(info, UART_ESI_CMD2, new_config.flow_off); - serial_out(info, UART_ESI_CMD2, new_config.flow_on >> 8); - serial_out(info, UART_ESI_CMD2, new_config.flow_on); - spin_unlock_irqrestore(&info->lock, flags); - } - - if ((new_config.rx_trigger != info->config.rx_trigger) || - (new_config.tx_trigger != info->config.tx_trigger)) { - info->config.rx_trigger = new_config.rx_trigger; - info->config.tx_trigger = new_config.tx_trigger; - spin_lock_irqsave(&info->lock, flags); - serial_out(info, UART_ESI_CMD1, ESI_SET_TRIGGER); - serial_out(info, UART_ESI_CMD2, - new_config.rx_trigger >> 8); - serial_out(info, UART_ESI_CMD2, new_config.rx_trigger); - serial_out(info, UART_ESI_CMD2, - new_config.tx_trigger >> 8); - serial_out(info, UART_ESI_CMD2, new_config.tx_trigger); - spin_unlock_irqrestore(&info->lock, flags); - } - - if (new_config.rx_timeout != info->config.rx_timeout) { - info->config.rx_timeout = new_config.rx_timeout; - spin_lock_irqsave(&info->lock, flags); - - if (info->IER & UART_IER_RDI) { - serial_out(info, UART_ESI_CMD1, - ESI_SET_RX_TIMEOUT); - serial_out(info, UART_ESI_CMD2, - new_config.rx_timeout); - } - - spin_unlock_irqrestore(&info->lock, flags); - } - - if (!(info->port.flags & ASYNC_INITIALIZED)) - retval = startup(info); - - return retval; -} - -/* - * 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 an RS485 driver to be written in user space. - */ -static int get_lsr_info(struct esp_struct *info, unsigned int __user *value) -{ - unsigned char status; - unsigned int result; - unsigned long flags; - - spin_lock_irqsave(&info->lock, flags); - serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); - status = serial_in(info, UART_ESI_STAT1); - spin_unlock_irqrestore(&info->lock, flags); - result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); - return put_user(result, value); -} - - -static int esp_tiocmget(struct tty_struct *tty, struct file *file) -{ - struct esp_struct *info = tty->driver_data; - unsigned char control, status; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, __func__)) - return -ENODEV; - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - control = info->MCR; - - spin_lock_irqsave(&info->lock, flags); - serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); - status = serial_in(info, UART_ESI_STAT2); - spin_unlock_irqrestore(&info->lock, 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); -} - -static int esp_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) -{ - struct esp_struct *info = tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, __func__)) - return -ENODEV; - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - spin_lock_irqsave(&info->lock, flags); - - 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; - - serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); - serial_out(info, UART_ESI_CMD2, UART_MCR); - serial_out(info, UART_ESI_CMD2, info->MCR); - - spin_unlock_irqrestore(&info->lock, flags); - return 0; -} - -/* - * rs_break() --- routine which turns the break handling on or off - */ -static int esp_break(struct tty_struct *tty, int break_state) -{ - struct esp_struct *info = tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "esp_break")) - return -EINVAL; - - if (break_state == -1) { - spin_lock_irqsave(&info->lock, flags); - serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK); - serial_out(info, UART_ESI_CMD2, 0x01); - spin_unlock_irqrestore(&info->lock, flags); - - /* FIXME - new style wait needed here */ - interruptible_sleep_on(&info->break_wait); - } else { - spin_lock_irqsave(&info->lock, flags); - serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK); - serial_out(info, UART_ESI_CMD2, 0x00); - spin_unlock_irqrestore(&info->lock, flags); - } - return 0; -} - -static int rs_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct esp_struct *info = tty->driver_data; - struct async_icount cprev, cnow; /* kernel counter temps */ - struct serial_icounter_struct __user *p_cuser; /* user space */ - void __user *argp = (void __user *)arg; - unsigned long flags; - int ret; - - if (serial_paranoia_check(info, tty->name, "rs_ioctl")) - return -ENODEV; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && - (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT) && - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT) && - (cmd != TIOCGHAYESESP) && (cmd != TIOCSHAYESESP)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case TIOCGSERIAL: - return get_serial_info(info, argp); - case TIOCSSERIAL: - lock_kernel(); - ret = set_serial_info(info, argp); - unlock_kernel(); - return ret; - case TIOCSERGWILD: - return put_user(0L, (unsigned long __user *)argp); - case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info(info, argp); - case TIOCSERSWILD: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - return 0; - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - spin_lock_irqsave(&info->lock, flags); - cprev = info->icount; /* note the counters on entry */ - spin_unlock_irqrestore(&info->lock, flags); - while (1) { - /* FIXME: convert to new style wakeup */ - interruptible_sleep_on(&info->port.delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - spin_lock_irqsave(&info->lock, flags); - cnow = info->icount; /* atomic copy */ - spin_unlock_irqrestore(&info->lock, flags); - if (cnow.rng == cprev.rng && - cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && - cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - 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))) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ - case TIOCGICOUNT: - spin_lock_irqsave(&info->lock, flags); - cnow = info->icount; - spin_unlock_irqrestore(&info->lock, flags); - p_cuser = argp; - if (put_user(cnow.cts, &p_cuser->cts) || - put_user(cnow.dsr, &p_cuser->dsr) || - put_user(cnow.rng, &p_cuser->rng) || - put_user(cnow.dcd, &p_cuser->dcd)) - return -EFAULT; - return 0; - case TIOCGHAYESESP: - return get_esp_config(info, argp); - case TIOCSHAYESESP: - lock_kernel(); - ret = set_esp_config(info, argp); - unlock_kernel(); - return ret; - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) -{ - struct esp_struct *info = tty->driver_data; - unsigned long flags; - - change_speed(info); - - spin_lock_irqsave(&info->lock, flags); - - /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && - !(tty->termios->c_cflag & CBAUD)) { - info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); - serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); - serial_out(info, UART_ESI_CMD2, UART_MCR); - serial_out(info, UART_ESI_CMD2, info->MCR); - } - - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - (tty->termios->c_cflag & CBAUD)) { - info->MCR |= (UART_MCR_DTR | UART_MCR_RTS); - serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); - serial_out(info, UART_ESI_CMD2, UART_MCR); - serial_out(info, UART_ESI_CMD2, info->MCR); - } - - spin_unlock_irqrestore(&info->lock, flags); - - /* Handle turning of CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - rs_start(tty); - } -} - -/* - * ------------------------------------------------------------ - * rs_close() - * - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we unlink its - * async structure from the interrupt chain if necessary, and we free - * that IRQ if nothing is left in the chain. - * ------------------------------------------------------------ - */ -static void rs_close(struct tty_struct *tty, struct file *filp) -{ - struct esp_struct *info = tty->driver_data; - unsigned long flags; - - if (!info || serial_paranoia_check(info, tty->name, "rs_close")) - return; - - spin_lock_irqsave(&info->lock, flags); - - if (tty_hung_up_p(filp)) { - DBG_CNT("before DEC-hung"); - goto out; - } - -#ifdef SERIAL_DEBUG_OPEN - printk(KERN_DEBUG "rs_close ttys%d, count = %d\n", - info->line, info->port.count); -#endif - if (tty->count == 1 && info->port.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_DEBUG "rs_close: bad serial port count; tty->count is 1, info->port.count is %d\n", info->port.count); - info->port.count = 1; - } - if (--info->port.count < 0) { - printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n", - info->line, info->port.count); - info->port.count = 0; - } - if (info->port.count) { - DBG_CNT("before DEC-2"); - goto out; - } - info->port.flags |= ASYNC_CLOSING; - - spin_unlock_irqrestore(&info->lock, flags); - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->closing_wait); - /* - * 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. - */ - /* info->IER &= ~UART_IER_RLSI; */ - info->IER &= ~UART_IER_RDI; - info->read_status_mask &= ~UART_LSR_DR; - if (info->port.flags & ASYNC_INITIALIZED) { - - spin_lock_irqsave(&info->lock, flags); - serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); - serial_out(info, UART_ESI_CMD2, info->IER); - - /* disable receive timeout */ - serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT); - serial_out(info, UART_ESI_CMD2, 0x00); - - spin_unlock_irqrestore(&info->lock, flags); - - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - rs_wait_until_sent(tty, info->timeout); - } - shutdown(info); - rs_flush_buffer(tty); - tty_ldisc_flush(tty); - tty->closing = 0; - info->port.tty = NULL; - - if (info->port.blocked_open) { - if (info->close_delay) - msleep_interruptible(jiffies_to_msecs(info->close_delay)); - wake_up_interruptible(&info->port.open_wait); - } - info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&info->port.close_wait); - return; - -out: - spin_unlock_irqrestore(&info->lock, flags); -} - -static void rs_wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct esp_struct *info = tty->driver_data; - unsigned long orig_jiffies, char_time; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) - return; - - orig_jiffies = jiffies; - char_time = ((info->timeout - HZ / 50) / 1024) / 5; - - if (!char_time) - char_time = 1; - - spin_lock_irqsave(&info->lock, flags); - serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); - serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL); - - while ((serial_in(info, UART_ESI_STAT1) != 0x03) || - (serial_in(info, UART_ESI_STAT2) != 0xff)) { - - spin_unlock_irqrestore(&info->lock, flags); - msleep_interruptible(jiffies_to_msecs(char_time)); - - if (signal_pending(current)) - return; - - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - return; - - spin_lock_irqsave(&info->lock, flags); - serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); - serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL); - } - spin_unlock_irqrestore(&info->lock, flags); - set_current_state(TASK_RUNNING); -} - -/* - * esp_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -static void esp_hangup(struct tty_struct *tty) -{ - struct esp_struct *info = tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "esp_hangup")) - return; - - rs_flush_buffer(tty); - shutdown(info); - info->port.count = 0; - info->port.flags &= ~ASYNC_NORMAL_ACTIVE; - info->port.tty = NULL; - wake_up_interruptible(&info->port.open_wait); -} - -static int esp_carrier_raised(struct tty_port *port) -{ - struct esp_struct *info = container_of(port, struct esp_struct, port); - serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); - if (serial_in(info, UART_ESI_STAT2) & UART_MSR_DCD) - return 1; - return 0; -} - -/* - * ------------------------------------------------------------ - * esp_open() and friends - * ------------------------------------------------------------ - */ -static int block_til_ready(struct tty_struct *tty, struct file *filp, - struct esp_struct *info) -{ - DECLARE_WAITQUEUE(wait, current); - int retval; - int do_clocal = 0; - unsigned long flags; - int cd; - struct tty_port *port = &info->port; - - /* - * 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) || - (port->flags & ASYNC_CLOSING)) { - if (port->flags & ASYNC_CLOSING) - interruptible_sleep_on(&port->close_wait); -#ifdef SERIAL_DO_RESTART - if (port->flags & ASYNC_HUP_NOTIFY) - return -EAGAIN; - else - return -ERESTARTSYS; -#else - return -EAGAIN; -#endif - } - - /* - * If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - port->flags |= 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, port->count is dropped by one, so that - * rs_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&port->open_wait, &wait); -#ifdef SERIAL_DEBUG_OPEN - printk(KERN_DEBUG "block_til_ready before block: ttys%d, count = %d\n", - info->line, port->count); -#endif - spin_lock_irqsave(&info->lock, flags); - if (!tty_hung_up_p(filp)) - port->count--; - port->blocked_open++; - while (1) { - if ((tty->termios->c_cflag & CBAUD)) { - unsigned int scratch; - - serial_out(info, UART_ESI_CMD1, ESI_READ_UART); - serial_out(info, UART_ESI_CMD2, UART_MCR); - scratch = serial_in(info, UART_ESI_STAT1); - serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); - serial_out(info, UART_ESI_CMD2, UART_MCR); - serial_out(info, UART_ESI_CMD2, - scratch | UART_MCR_DTR | UART_MCR_RTS); - } - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(port->flags & ASYNC_INITIALIZED)) { -#ifdef SERIAL_DO_RESTART - if (port->flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; -#else - retval = -EAGAIN; -#endif - break; - } - - cd = tty_port_carrier_raised(port); - - if (!(port->flags & ASYNC_CLOSING) && - (do_clocal)) - break; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } -#ifdef SERIAL_DEBUG_OPEN - printk(KERN_DEBUG "block_til_ready blocking: ttys%d, count = %d\n", - info->line, port->count); -#endif - spin_unlock_irqrestore(&info->lock, flags); - schedule(); - spin_lock_irqsave(&info->lock, flags); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&port->open_wait, &wait); - if (!tty_hung_up_p(filp)) - port->count++; - port->blocked_open--; - spin_unlock_irqrestore(&info->lock, flags); -#ifdef SERIAL_DEBUG_OPEN - printk(KERN_DEBUG "block_til_ready after blocking: ttys%d, count = %d\n", - info->line, port->count); -#endif - if (retval) - return retval; - port->flags |= 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 esp_open(struct tty_struct *tty, struct file *filp) -{ - struct esp_struct *info; - int retval, line; - unsigned long flags; - - line = tty->index; - if ((line < 0) || (line >= NR_PORTS)) - return -ENODEV; - - /* find the port in the chain */ - - info = ports; - - while (info && (info->line != line)) - info = info->next_port; - - if (!info) { - serial_paranoia_check(info, tty->name, "esp_open"); - return -ENODEV; - } - -#ifdef SERIAL_DEBUG_OPEN - printk(KERN_DEBUG "esp_open %s, count = %d\n", tty->name, info->port.count); -#endif - spin_lock_irqsave(&info->lock, flags); - info->port.count++; - tty->driver_data = info; - info->port.tty = tty; - - spin_unlock_irqrestore(&info->lock, flags); - - /* - * Start up serial port - */ - retval = startup(info); - if (retval) - return retval; - - retval = block_til_ready(tty, filp, info); - if (retval) { -#ifdef SERIAL_DEBUG_OPEN - printk(KERN_DEBUG "esp_open returning after block_til_ready with %d\n", - retval); -#endif - return retval; - } -#ifdef SERIAL_DEBUG_OPEN - printk(KERN_DEBUG "esp_open %s successful...", tty->name); -#endif - return 0; -} - -/* - * --------------------------------------------------------------------- - * espserial_init() and friends - * - * espserial_init() is called at boot-time to initialize the serial driver. - * --------------------------------------------------------------------- - */ - -/* - * This routine prints out the appropriate serial driver version - * number, and identifies which options were configured into this - * driver. - */ - -static void __init show_serial_version(void) -{ - printk(KERN_INFO "%s version %s (DMA %u)\n", - serial_name, serial_version, dma); -} - -/* - * This routine is called by espserial_init() to initialize a specific serial - * port. - */ -static int autoconfig(struct esp_struct *info) -{ - int port_detected = 0; - unsigned long flags; - - if (!request_region(info->io_port, REGION_SIZE, "esp serial")) - return -EIO; - - spin_lock_irqsave(&info->lock, flags); - /* - * Check for ESP card - */ - - if (serial_in(info, UART_ESI_BASE) == 0xf3) { - serial_out(info, UART_ESI_CMD1, 0x00); - serial_out(info, UART_ESI_CMD1, 0x01); - - if ((serial_in(info, UART_ESI_STAT2) & 0x70) == 0x20) { - port_detected = 1; - - if (!(info->irq)) { - serial_out(info, UART_ESI_CMD1, 0x02); - - if (serial_in(info, UART_ESI_STAT1) & 0x01) - info->irq = 3; - else - info->irq = 4; - } - - - /* put card in enhanced mode */ - /* this prevents access through */ - /* the "old" IO ports */ - esp_basic_init(info); - - /* clear out MCR */ - serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); - serial_out(info, UART_ESI_CMD2, UART_MCR); - serial_out(info, UART_ESI_CMD2, 0x00); - } - } - if (!port_detected) - release_region(info->io_port, REGION_SIZE); - - spin_unlock_irqrestore(&info->lock, flags); - return (port_detected); -} - -static const struct tty_operations esp_ops = { - .open = esp_open, - .close = rs_close, - .write = rs_write, - .put_char = rs_put_char, - .flush_chars = rs_flush_chars, - .write_room = rs_write_room, - .chars_in_buffer = rs_chars_in_buffer, - .flush_buffer = rs_flush_buffer, - .ioctl = rs_ioctl, - .throttle = rs_throttle, - .unthrottle = rs_unthrottle, - .set_termios = rs_set_termios, - .stop = rs_stop, - .start = rs_start, - .hangup = esp_hangup, - .break_ctl = esp_break, - .wait_until_sent = rs_wait_until_sent, - .tiocmget = esp_tiocmget, - .tiocmset = esp_tiocmset, -}; - -static const struct tty_port_operations esp_port_ops = { - .esp_carrier_raised, -}; - -/* - * The serial driver boot-time initialization code! - */ -static int __init espserial_init(void) -{ - int i, offset; - struct esp_struct *info; - struct esp_struct *last_primary = NULL; - int esp[] = { 0x100, 0x140, 0x180, 0x200, 0x240, 0x280, 0x300, 0x380 }; - - esp_driver = alloc_tty_driver(NR_PORTS); - if (!esp_driver) - return -ENOMEM; - - for (i = 0; i < NR_PRIMARY; i++) { - if (irq[i] != 0) { - if ((irq[i] < 2) || (irq[i] > 15) || (irq[i] == 6) || - (irq[i] == 8) || (irq[i] == 13)) - irq[i] = 0; - else if (irq[i] == 2) - irq[i] = 9; - } - } - - if ((dma != 1) && (dma != 3)) - dma = 0; - - if ((rx_trigger < 1) || (rx_trigger > 1023)) - rx_trigger = 768; - - if ((tx_trigger < 1) || (tx_trigger > 1023)) - tx_trigger = 768; - - if ((flow_off < 1) || (flow_off > 1023)) - flow_off = 1016; - - if ((flow_on < 1) || (flow_on > 1023)) - flow_on = 944; - - if ((rx_timeout < 0) || (rx_timeout > 255)) - rx_timeout = 128; - - if (flow_on >= flow_off) - flow_on = flow_off - 1; - - show_serial_version(); - - /* Initialize the tty_driver structure */ - - esp_driver->owner = THIS_MODULE; - esp_driver->name = "ttyP"; - esp_driver->major = ESP_IN_MAJOR; - esp_driver->minor_start = 0; - esp_driver->type = TTY_DRIVER_TYPE_SERIAL; - esp_driver->subtype = SERIAL_TYPE_NORMAL; - esp_driver->init_termios = tty_std_termios; - esp_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - esp_driver->init_termios.c_ispeed = 9600; - esp_driver->init_termios.c_ospeed = 9600; - esp_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(esp_driver, &esp_ops); - if (tty_register_driver(esp_driver)) { - printk(KERN_ERR "Couldn't register esp serial driver"); - put_tty_driver(esp_driver); - return 1; - } - - info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL); - - if (!info) { - printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n"); - tty_unregister_driver(esp_driver); - put_tty_driver(esp_driver); - return 1; - } - - spin_lock_init(&info->lock); - /* rx_trigger, tx_trigger are needed by autoconfig */ - info->config.rx_trigger = rx_trigger; - info->config.tx_trigger = tx_trigger; - - i = 0; - offset = 0; - - do { - tty_port_init(&info->port); - info->port.ops = &esp_port_ops; - info->io_port = esp[i] + offset; - info->irq = irq[i]; - info->line = (i * 8) + (offset / 8); - - if (!autoconfig(info)) { - i++; - offset = 0; - continue; - } - - info->custom_divisor = (divisor[i] >> (offset / 2)) & 0xf; - info->port.flags = STD_COM_FLAGS; - if (info->custom_divisor) - info->port.flags |= ASYNC_SPD_CUST; - info->magic = ESP_MAGIC; - info->close_delay = 5*HZ/10; - info->closing_wait = 30*HZ; - info->config.rx_timeout = rx_timeout; - info->config.flow_on = flow_on; - info->config.flow_off = flow_off; - info->config.pio_threshold = pio_threshold; - info->next_port = ports; - init_waitqueue_head(&info->break_wait); - ports = info; - printk(KERN_INFO "ttyP%d at 0x%04x (irq = %d) is an ESP ", - info->line, info->io_port, info->irq); - - if (info->line % 8) { - printk("secondary port\n"); - /* 8 port cards can't do DMA */ - info->stat_flags |= ESP_STAT_NEVER_DMA; - - if (last_primary) - last_primary->stat_flags |= ESP_STAT_NEVER_DMA; - } else { - printk("primary port\n"); - last_primary = info; - irq[i] = info->irq; - } - - if (!dma) - info->stat_flags |= ESP_STAT_NEVER_DMA; - - info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL); - if (!info) { - printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n"); - /* allow use of the already detected ports */ - return 0; - } - - spin_lock_init(&info->lock); - /* rx_trigger, tx_trigger are needed by autoconfig */ - info->config.rx_trigger = rx_trigger; - info->config.tx_trigger = tx_trigger; - - if (offset == 56) { - i++; - offset = 0; - } else { - offset += 8; - } - } while (i < NR_PRIMARY); - - /* free the last port memory allocation */ - kfree(info); - - return 0; -} - -static void __exit espserial_exit(void) -{ - int e1; - struct esp_struct *temp_async; - struct esp_pio_buffer *pio_buf; - - e1 = tty_unregister_driver(esp_driver); - if (e1) - printk(KERN_ERR "esp: failed to unregister driver (%d)\n", e1); - put_tty_driver(esp_driver); - - while (ports) { - if (ports->io_port) - release_region(ports->io_port, REGION_SIZE); - temp_async = ports->next_port; - kfree(ports); - ports = temp_async; - } - - if (dma_buffer) - free_pages((unsigned long)dma_buffer, - get_order(DMA_BUFFER_SZ)); - - while (free_pio_buf) { - pio_buf = free_pio_buf->next; - kfree(free_pio_buf); - free_pio_buf = pio_buf; - } -} - -module_init(espserial_init); -module_exit(espserial_exit); diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index a632f25f144a8509b91d92ea4660636d9a998a69..416d3423150d8d037dce7a459eb8a5fc44a64fc8 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -832,6 +832,7 @@ int hvc_remove(struct hvc_struct *hp) tty_hangup(tty); return 0; } +EXPORT_SYMBOL_GPL(hvc_remove); /* Driver initialization: called as soon as someone uses hvc_alloc(). */ static int hvc_init(void) diff --git a/drivers/char/hvc_xen.c b/drivers/char/hvc_xen.c index a6ee32b599a880c13f3595fa43aaa9717b7fb1f0..b1a71638c772b8ed5be135408c612130d7b2ec8b 100644 --- a/drivers/char/hvc_xen.c +++ b/drivers/char/hvc_xen.c @@ -25,6 +25,8 @@ #include #include + +#include #include #include #include diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 426bfdd7f3e0221d07498f7b30c9aab7d6904a48..300d5bd6cd0602fc57f160d00757d64fb49e2e6a 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -793,35 +793,30 @@ static inline void isicom_setup_board(struct isi_board *bp) { int channel; struct isi_port *port; - unsigned long flags; - spin_lock_irqsave(&bp->card_lock, flags); - if (bp->status & BOARD_ACTIVE) { - spin_unlock_irqrestore(&bp->card_lock, flags); - return; + bp->count++; + if (!(bp->status & BOARD_INIT)) { + port = bp->ports; + for (channel = 0; channel < bp->port_count; channel++, port++) + drop_dtr_rts(port); } - port = bp->ports; - bp->status |= BOARD_ACTIVE; - for (channel = 0; channel < bp->port_count; channel++, port++) - drop_dtr_rts(port); - spin_unlock_irqrestore(&bp->card_lock, flags); + bp->status |= BOARD_ACTIVE | BOARD_INIT; } -static int isicom_setup_port(struct tty_struct *tty) +/* Activate and thus setup board are protected from races against shutdown + by the tty_port mutex */ + +static int isicom_activate(struct tty_port *tport, struct tty_struct *tty) { - struct isi_port *port = tty->driver_data; + struct isi_port *port = container_of(tport, struct isi_port, port); struct isi_board *card = port->card; unsigned long flags; - if (port->port.flags & ASYNC_INITIALIZED) - return 0; - if (tty_port_alloc_xmit_buf(&port->port) < 0) + if (tty_port_alloc_xmit_buf(tport) < 0) return -ENOMEM; spin_lock_irqsave(&card->card_lock, flags); - clear_bit(TTY_IO_ERROR, &tty->flags); - if (port->port.count == 1) - card->count++; + isicom_setup_board(card); port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; @@ -832,9 +827,7 @@ static int isicom_setup_port(struct tty_struct *tty) outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base); InterruptTheCard(card->base); } - isicom_config_port(tty); - port->port.flags |= ASYNC_INITIALIZED; spin_unlock_irqrestore(&card->card_lock, flags); return 0; @@ -871,85 +864,37 @@ static struct tty_port *isicom_find_port(struct tty_struct *tty) return &port->port; } - + static int isicom_open(struct tty_struct *tty, struct file *filp) { struct isi_port *port; struct isi_board *card; struct tty_port *tport; - int error = 0; tport = isicom_find_port(tty); if (tport == NULL) return -ENODEV; port = container_of(tport, struct isi_port, port); card = &isi_card[BOARD(tty->index)]; - isicom_setup_board(card); - /* FIXME: locking on port.count etc */ - port->port.count++; - tty->driver_data = port; - tty_port_tty_set(&port->port, tty); - /* FIXME: Locking on Initialized flag */ - if (!test_bit(ASYNCB_INITIALIZED, &tport->flags)) - error = isicom_setup_port(tty); - if (error == 0) - error = tty_port_block_til_ready(&port->port, tty, filp); - return error; + return tty_port_open(tport, tty, filp); } /* close et all */ -static inline void isicom_shutdown_board(struct isi_board *bp) -{ - if (bp->status & BOARD_ACTIVE) - bp->status &= ~BOARD_ACTIVE; -} - /* card->lock HAS to be held */ static void isicom_shutdown_port(struct isi_port *port) { struct isi_board *card = port->card; - struct tty_struct *tty; - - tty = tty_port_tty_get(&port->port); - - if (!(port->port.flags & ASYNC_INITIALIZED)) { - tty_kref_put(tty); - return; - } - - tty_port_free_xmit_buf(&port->port); - port->port.flags &= ~ASYNC_INITIALIZED; - /* 3rd October 2000 : Vinayak P Risbud */ - tty_port_tty_set(&port->port, NULL); - - /*Fix done by Anil .S on 30-04-2001 - remote login through isi port has dtr toggle problem - due to which the carrier drops before the password prompt - appears on the remote end. Now we drop the dtr only if the - HUPCL(Hangup on close) flag is set for the tty*/ - - if (C_HUPCL(tty)) - /* drop dtr on this port */ - drop_dtr(port); - - /* any other port uninits */ - if (tty) - set_bit(TTY_IO_ERROR, &tty->flags); if (--card->count < 0) { pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n", card->base, card->count); card->count = 0; } - - /* last port was closed, shutdown that boad too */ - if (C_HUPCL(tty)) { - if (!card->count) - isicom_shutdown_board(card); - } - tty_kref_put(tty); + /* last port was closed, shutdown that board too */ + if (!card->count) + card->status &= BOARD_ACTIVE; } static void isicom_flush_buffer(struct tty_struct *tty) @@ -968,7 +913,7 @@ static void isicom_flush_buffer(struct tty_struct *tty) tty_wakeup(tty); } -static void isicom_close_port(struct tty_port *port) +static void isicom_shutdown(struct tty_port *port) { struct isi_port *ip = container_of(port, struct isi_port, port); struct isi_board *card = ip->card; @@ -977,12 +922,11 @@ static void isicom_close_port(struct tty_port *port) /* indicate to the card that no more data can be received on this port */ spin_lock_irqsave(&card->card_lock, flags); - if (port->flags & ASYNC_INITIALIZED) { - card->port_status &= ~(1 << ip->channel); - outw(card->port_status, card->base + 0x02); - } + card->port_status &= ~(1 << ip->channel); + outw(card->port_status, card->base + 0x02); isicom_shutdown_port(ip); spin_unlock_irqrestore(&card->card_lock, flags); + tty_port_free_xmit_buf(port); } static void isicom_close(struct tty_struct *tty, struct file *filp) @@ -991,12 +935,7 @@ static void isicom_close(struct tty_struct *tty, struct file *filp) struct tty_port *port = &ip->port; if (isicom_paranoia_check(ip, tty->name, "isicom_close")) return; - - if (tty_port_close_start(port, tty, filp) == 0) - return; - isicom_close_port(port); - isicom_flush_buffer(tty); - tty_port_close_end(port, tty); + tty_port_close(port, tty, filp); } /* write et all */ @@ -1326,15 +1265,9 @@ static void isicom_start(struct tty_struct *tty) static void isicom_hangup(struct tty_struct *tty) { struct isi_port *port = tty->driver_data; - unsigned long flags; if (isicom_paranoia_check(port, tty->name, "isicom_hangup")) return; - - spin_lock_irqsave(&port->card->card_lock, flags); - isicom_shutdown_port(port); - spin_unlock_irqrestore(&port->card->card_lock, flags); - tty_port_hangup(&port->port); } @@ -1367,6 +1300,8 @@ static const struct tty_operations isicom_ops = { static const struct tty_port_operations isicom_port_ops = { .carrier_raised = isicom_carrier_raised, .dtr_rts = isicom_dtr_rts, + .activate = isicom_activate, + .shutdown = isicom_shutdown, }; static int __devinit reset_card(struct pci_dev *pdev, diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 402838f4083e31091fe2480490c8a3ac0e42efa6..4cd6c527ee4141929c2257e9798a7c51cab45a6b 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -213,7 +213,6 @@ static int stli_shared; * with the slave. Most of them need to be updated atomically, so always * use the bit setting operations (unless protected by cli/sti). */ -#define ST_INITIALIZING 1 #define ST_OPENING 2 #define ST_CLOSING 3 #define ST_CMDING 4 @@ -621,7 +620,7 @@ static int stli_brdinit(struct stlibrd *brdp); static int stli_startbrd(struct stlibrd *brdp); static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp); static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp); -static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); +static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg); static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp); static void stli_poll(unsigned long arg); static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); @@ -704,7 +703,7 @@ static const struct file_operations stli_fsiomem = { .owner = THIS_MODULE, .read = stli_memread, .write = stli_memwrite, - .ioctl = stli_memioctl, + .unlocked_ioctl = stli_memioctl, }; /*****************************************************************************/ @@ -783,13 +782,32 @@ static int stli_parsebrd(struct stlconf *confp, char **argp) /*****************************************************************************/ +/* + * On the first open of the device setup the port hardware, and + * initialize the per port data structure. Since initializing the port + * requires several commands to the board we will need to wait for any + * other open that is already initializing the port. + * + * Locking: protected by the port mutex. + */ + +static int stli_activate(struct tty_port *port, struct tty_struct *tty) +{ + struct stliport *portp = container_of(port, struct stliport, port); + struct stlibrd *brdp = stli_brds[portp->brdnr]; + int rc; + + if ((rc = stli_initopen(tty, brdp, portp)) >= 0) + clear_bit(TTY_IO_ERROR, &tty->flags); + wake_up_interruptible(&portp->raw_wait); + return rc; +} + static int stli_open(struct tty_struct *tty, struct file *filp) { struct stlibrd *brdp; struct stliport *portp; - struct tty_port *port; unsigned int minordev, brdnr, portnr; - int rc; minordev = tty->index; brdnr = MINOR2BRD(minordev); @@ -809,95 +827,56 @@ static int stli_open(struct tty_struct *tty, struct file *filp) return -ENODEV; if (portp->devnr < 1) return -ENODEV; - port = &portp->port; - -/* - * On the first open of the device setup the port hardware, and - * initialize the per port data structure. Since initializing the port - * requires several commands to the board we will need to wait for any - * other open that is already initializing the port. - * - * Review - locking - */ - tty_port_tty_set(port, tty); - tty->driver_data = portp; - port->count++; - - wait_event_interruptible(portp->raw_wait, - !test_bit(ST_INITIALIZING, &portp->state)); - if (signal_pending(current)) - return -ERESTARTSYS; - - if ((portp->port.flags & ASYNC_INITIALIZED) == 0) { - set_bit(ST_INITIALIZING, &portp->state); - if ((rc = stli_initopen(tty, brdp, portp)) >= 0) { - /* Locking */ - port->flags |= ASYNC_INITIALIZED; - clear_bit(TTY_IO_ERROR, &tty->flags); - } - clear_bit(ST_INITIALIZING, &portp->state); - wake_up_interruptible(&portp->raw_wait); - if (rc < 0) - return rc; - } - return tty_port_block_til_ready(&portp->port, tty, filp); + return tty_port_open(&portp->port, tty, filp); } + /*****************************************************************************/ -static void stli_close(struct tty_struct *tty, struct file *filp) +static void stli_shutdown(struct tty_port *port) { struct stlibrd *brdp; - struct stliport *portp; - struct tty_port *port; + unsigned long ftype; unsigned long flags; + struct stliport *portp = container_of(port, struct stliport, port); - portp = tty->driver_data; - if (portp == NULL) + if (portp->brdnr >= stli_nrbrds) return; - port = &portp->port; - - if (tty_port_close_start(port, tty, filp) == 0) + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) return; -/* - * May want to wait for data to drain before closing. The BUSY flag - * keeps track of whether we are still transmitting or not. It is - * updated by messages from the slave - indicating when all chars - * really have drained. - */ - spin_lock_irqsave(&stli_lock, flags); - if (tty == stli_txcooktty) - stli_flushchars(tty); - spin_unlock_irqrestore(&stli_lock, flags); - - /* We end up doing this twice for the moment. This needs looking at - eventually. Note we still use portp->closing_wait as a result */ - if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, portp->closing_wait); + /* + * May want to wait for data to drain before closing. The BUSY + * flag keeps track of whether we are still transmitting or not. + * It is updated by messages from the slave - indicating when all + * chars really have drained. + */ - /* FIXME: port locking here needs attending to */ - port->flags &= ~ASYNC_INITIALIZED; + if (!test_bit(ST_CLOSING, &portp->state)) + stli_rawclose(brdp, portp, 0, 0); - brdp = stli_brds[portp->brdnr]; - stli_rawclose(brdp, portp, 0, 0); - if (tty->termios->c_cflag & HUPCL) { - stli_mkasysigs(&portp->asig, 0, 0); - if (test_bit(ST_CMDING, &portp->state)) - set_bit(ST_DOSIGS, &portp->state); - else - stli_sendcmd(brdp, portp, A_SETSIGNALS, &portp->asig, - sizeof(asysigs_t), 0); - } + spin_lock_irqsave(&stli_lock, flags); clear_bit(ST_TXBUSY, &portp->state); clear_bit(ST_RXSTOP, &portp->state); - set_bit(TTY_IO_ERROR, &tty->flags); - tty_ldisc_flush(tty); - set_bit(ST_DOFLUSHRX, &portp->state); - stli_flushbuffer(tty); + spin_unlock_irqrestore(&stli_lock, flags); - tty_port_close_end(port, tty); - tty_port_tty_set(port, NULL); + ftype = FLUSHTX | FLUSHRX; + stli_cmdwait(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0); +} + +static void stli_close(struct tty_struct *tty, struct file *filp) +{ + struct stliport *portp = tty->driver_data; + unsigned long flags; + if (portp == NULL) + return; + spin_lock_irqsave(&stli_lock, flags); + /* Flush any internal buffering out first */ + if (tty == stli_txcooktty) + stli_flushchars(tty); + spin_unlock_irqrestore(&stli_lock, flags); + tty_port_close(&portp->port, tty, filp); } /*****************************************************************************/ @@ -1724,6 +1703,7 @@ static void stli_start(struct tty_struct *tty) /*****************************************************************************/ + /* * Hangup this port. This is pretty much like closing the port, only * a little more brutal. No waiting for data to drain. Shutdown the @@ -1733,47 +1713,8 @@ static void stli_start(struct tty_struct *tty) static void stli_hangup(struct tty_struct *tty) { - struct stliport *portp; - struct stlibrd *brdp; - struct tty_port *port; - unsigned long flags; - - portp = tty->driver_data; - if (portp == NULL) - return; - if (portp->brdnr >= stli_nrbrds) - return; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return; - port = &portp->port; - - spin_lock_irqsave(&port->lock, flags); - port->flags &= ~ASYNC_INITIALIZED; - spin_unlock_irqrestore(&port->lock, flags); - - if (!test_bit(ST_CLOSING, &portp->state)) - stli_rawclose(brdp, portp, 0, 0); - - spin_lock_irqsave(&stli_lock, flags); - if (tty->termios->c_cflag & HUPCL) { - stli_mkasysigs(&portp->asig, 0, 0); - if (test_bit(ST_CMDING, &portp->state)) { - set_bit(ST_DOSIGS, &portp->state); - set_bit(ST_DOFLUSHTX, &portp->state); - set_bit(ST_DOFLUSHRX, &portp->state); - } else { - stli_sendcmd(brdp, portp, A_SETSIGNALSF, - &portp->asig, sizeof(asysigs_t), 0); - } - } - - clear_bit(ST_TXBUSY, &portp->state); - clear_bit(ST_RXSTOP, &portp->state); - set_bit(TTY_IO_ERROR, &tty->flags); - spin_unlock_irqrestore(&stli_lock, flags); - - tty_port_hangup(port); + struct stliport *portp = tty->driver_data; + tty_port_hangup(&portp->port); } /*****************************************************************************/ @@ -4311,7 +4252,7 @@ static int stli_getbrdstruct(struct stlibrd __user *arg) * reset it, and start/stop it. */ -static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) +static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) { struct stlibrd *brdp; int brdnr, rc, done; @@ -4356,7 +4297,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un * Now handle the board specific ioctls. These all depend on the * minor number of the device they were called from. */ - brdnr = iminor(ip); + brdnr = iminor(fp->f_dentry->d_inode); if (brdnr >= STL_MAXBRDS) return -ENODEV; brdp = stli_brds[brdnr]; @@ -4420,6 +4361,8 @@ static const struct tty_operations stli_ops = { static const struct tty_port_operations stli_port_ops = { .carrier_raised = stli_carrier_raised, .dtr_rts = stli_dtr_rts, + .activate = stli_activate, + .shutdown = stli_shutdown, }; /*****************************************************************************/ diff --git a/drivers/char/lp.c b/drivers/char/lp.c index e444c2dba160870658b8ac45910ba79b85d12419..938a3a2738866c71e42b7d8112b29966cdf3417c 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -127,6 +127,7 @@ #include #include #include +#include #include #undef LP_STATS @@ -571,13 +572,11 @@ static int lp_release(struct inode * inode, struct file * file) return 0; } -static int lp_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int lp_do_ioctl(unsigned int minor, unsigned int cmd, + unsigned long arg, void __user *argp) { - unsigned int minor = iminor(inode); int status; int retval = 0; - void __user *argp = (void __user *)arg; #ifdef LP_DEBUG printk(KERN_DEBUG "lp%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg); @@ -587,9 +586,6 @@ static int lp_ioctl(struct inode *inode, struct file *file, if ((LP_F(minor) & LP_EXIST) == 0) return -ENODEV; switch ( cmd ) { - struct timeval par_timeout; - long to_jiffies; - case LPTIME: LP_TIME(minor) = arg * HZ/100; break; @@ -652,34 +648,101 @@ static int lp_ioctl(struct inode *inode, struct file *file, return -EFAULT; break; - case LPSETTIMEOUT: - if (copy_from_user (&par_timeout, argp, - sizeof (struct timeval))) { - return -EFAULT; - } - /* Convert to jiffies, place in lp_table */ - if ((par_timeout.tv_sec < 0) || - (par_timeout.tv_usec < 0)) { - return -EINVAL; - } - to_jiffies = DIV_ROUND_UP(par_timeout.tv_usec, 1000000/HZ); - to_jiffies += par_timeout.tv_sec * (long) HZ; - if (to_jiffies <= 0) { - return -EINVAL; - } - lp_table[minor].timeout = to_jiffies; - break; - default: retval = -EINVAL; } return retval; } +static int lp_set_timeout(unsigned int minor, struct timeval *par_timeout) +{ + long to_jiffies; + + /* Convert to jiffies, place in lp_table */ + if ((par_timeout->tv_sec < 0) || + (par_timeout->tv_usec < 0)) { + return -EINVAL; + } + to_jiffies = DIV_ROUND_UP(par_timeout->tv_usec, 1000000/HZ); + to_jiffies += par_timeout->tv_sec * (long) HZ; + if (to_jiffies <= 0) { + return -EINVAL; + } + lp_table[minor].timeout = to_jiffies; + return 0; +} + +static long lp_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned int minor; + struct timeval par_timeout; + int ret; + + minor = iminor(file->f_path.dentry->d_inode); + lock_kernel(); + switch (cmd) { + case LPSETTIMEOUT: + if (copy_from_user(&par_timeout, (void __user *)arg, + sizeof (struct timeval))) { + ret = -EFAULT; + break; + } + ret = lp_set_timeout(minor, &par_timeout); + break; + default: + ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg); + break; + } + unlock_kernel(); + + return ret; +} + +#ifdef CONFIG_COMPAT +static long lp_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned int minor; + struct timeval par_timeout; + struct compat_timeval __user *tc; + int ret; + + minor = iminor(file->f_path.dentry->d_inode); + lock_kernel(); + switch (cmd) { + case LPSETTIMEOUT: + tc = compat_ptr(arg); + if (get_user(par_timeout.tv_sec, &tc->tv_sec) || + get_user(par_timeout.tv_usec, &tc->tv_usec)) { + ret = -EFAULT; + break; + } + ret = lp_set_timeout(minor, &par_timeout); + break; +#ifdef LP_STATS + case LPGETSTATS: + /* FIXME: add an implementation if you set LP_STATS */ + ret = -EINVAL; + break; +#endif + default: + ret = lp_do_ioctl(minor, cmd, arg, compat_ptr(arg)); + break; + } + unlock_kernel(); + + return ret; +} +#endif + static const struct file_operations lp_fops = { .owner = THIS_MODULE, .write = lp_write, - .ioctl = lp_ioctl, + .unlocked_ioctl = lp_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = lp_compat_ioctl, +#endif .open = lp_open, .release = lp_release, #ifdef CONFIG_PARPORT_1284 diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 30eff80fed6f93290e41d0b0080b0c95fe89b4db..fba76fb55abfd302bbd87e6433ed858b8b5d2c4d 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -43,7 +43,7 @@ static inline int uncached_access(struct file *file, unsigned long addr) { #if defined(CONFIG_IA64) /* - * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases. + * On ia64, we ignore O_DSYNC because we cannot tolerate memory attribute aliases. */ return !(efi_mem_attributes(addr) & EFI_MEMORY_WB); #elif defined(CONFIG_MIPS) @@ -56,9 +56,9 @@ static inline int uncached_access(struct file *file, unsigned long addr) #else /* * Accessing memory above the top the kernel knows about or through a file pointer - * that was marked O_SYNC will be done non-cached. + * that was marked O_DSYNC will be done non-cached. */ - if (file->f_flags & O_SYNC) + if (file->f_flags & O_DSYNC) return 1; return addr >= __pa(high_memory); #endif diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index dd0083bbb64addaea9b286ac8d5a914a474625ea..63ee3bbc1ce4169654624980c3281e28fe84ae7c 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -139,7 +138,7 @@ struct moxa_port { int cflag; unsigned long statusflags; - u8 DCDState; + u8 DCDState; /* Protected by the port lock */ u8 lineCtrl; u8 lowChkFlag; }; @@ -151,10 +150,9 @@ struct mon_str { }; /* statusflags */ -#define TXSTOPPED 0x1 -#define LOWWAIT 0x2 -#define EMPTYWAIT 0x4 -#define THROTTLE 0x8 +#define TXSTOPPED 1 +#define LOWWAIT 2 +#define EMPTYWAIT 3 #define SERIAL_DO_RESTART @@ -165,6 +163,7 @@ static struct mon_str moxaLog; static unsigned int moxaFuncTout = HZ / 2; static unsigned int moxaLowWaterChk; static DEFINE_MUTEX(moxa_openlock); +static DEFINE_SPINLOCK(moxa_lock); /* Variables for insmod */ #ifdef MODULE static unsigned long baseaddr[MAX_BOARDS]; @@ -194,8 +193,6 @@ static int moxa_write(struct tty_struct *, const unsigned char *, int); static int moxa_write_room(struct tty_struct *); static void moxa_flush_buffer(struct tty_struct *); static int moxa_chars_in_buffer(struct tty_struct *); -static void moxa_throttle(struct tty_struct *); -static void moxa_unthrottle(struct tty_struct *); static void moxa_set_termios(struct tty_struct *, struct ktermios *); static void moxa_stop(struct tty_struct *); static void moxa_start(struct tty_struct *); @@ -205,9 +202,9 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static void moxa_poll(unsigned long); static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); -static void moxa_setup_empty_event(struct tty_struct *); -static void moxa_shut_down(struct tty_struct *); +static void moxa_shutdown(struct tty_port *); static int moxa_carrier_raised(struct tty_port *); +static void moxa_dtr_rts(struct tty_port *, int); /* * moxa board interface functions: */ @@ -234,6 +231,8 @@ static void MoxaSetFifo(struct moxa_port *port, int enable); * I/O functions */ +static DEFINE_SPINLOCK(moxafunc_lock); + static void moxa_wait_finish(void __iomem *ofsAddr) { unsigned long end = jiffies + moxaFuncTout; @@ -247,9 +246,25 @@ static void moxa_wait_finish(void __iomem *ofsAddr) static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg) { + unsigned long flags; + spin_lock_irqsave(&moxafunc_lock, flags); writew(arg, ofsAddr + FuncArg); writew(cmd, ofsAddr + FuncCode); moxa_wait_finish(ofsAddr); + spin_unlock_irqrestore(&moxafunc_lock, flags); +} + +static int moxafuncret(void __iomem *ofsAddr, u16 cmd, u16 arg) +{ + unsigned long flags; + u16 ret; + spin_lock_irqsave(&moxafunc_lock, flags); + writew(arg, ofsAddr + FuncArg); + writew(cmd, ofsAddr + FuncCode); + moxa_wait_finish(ofsAddr); + ret = readw(ofsAddr + FuncArg); + spin_unlock_irqrestore(&moxafunc_lock, flags); + return ret; } static void moxa_low_water_check(void __iomem *ofsAddr) @@ -299,22 +314,20 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, struct moxa_port *p; unsigned int i, j; - mutex_lock(&moxa_openlock); for (i = 0; i < MAX_BOARDS; i++) { p = moxa_boards[i].ports; for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { memset(&tmp, 0, sizeof(tmp)); + spin_lock_bh(&moxa_lock); if (moxa_boards[i].ready) { tmp.inq = MoxaPortRxQueue(p); tmp.outq = MoxaPortTxQueue(p); } - if (copy_to_user(argm, &tmp, sizeof(tmp))) { - mutex_unlock(&moxa_openlock); + spin_unlock_bh(&moxa_lock); + if (copy_to_user(argm, &tmp, sizeof(tmp))) return -EFAULT; - } } } - mutex_unlock(&moxa_openlock); break; } case MOXA_GET_OQUEUE: status = MoxaPortTxQueue(ch); @@ -330,16 +343,20 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, struct moxa_port *p; unsigned int i, j; - mutex_lock(&moxa_openlock); for (i = 0; i < MAX_BOARDS; i++) { p = moxa_boards[i].ports; for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { struct tty_struct *ttyp; memset(&tmp, 0, sizeof(tmp)); - if (!moxa_boards[i].ready) + spin_lock_bh(&moxa_lock); + if (!moxa_boards[i].ready) { + spin_unlock_bh(&moxa_lock); goto copy; + } status = MoxaPortLineStatus(p); + spin_unlock_bh(&moxa_lock); + if (status & 1) tmp.cts = 1; if (status & 2) @@ -354,24 +371,21 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, tmp.cflag = ttyp->termios->c_cflag; tty_kref_put(tty); copy: - if (copy_to_user(argm, &tmp, sizeof(tmp))) { - mutex_unlock(&moxa_openlock); + if (copy_to_user(argm, &tmp, sizeof(tmp))) return -EFAULT; - } } } - mutex_unlock(&moxa_openlock); break; } case TIOCGSERIAL: - mutex_lock(&moxa_openlock); + mutex_lock(&ch->port.mutex); ret = moxa_get_serial_info(ch, argp); - mutex_unlock(&moxa_openlock); + mutex_unlock(&ch->port.mutex); break; case TIOCSSERIAL: - mutex_lock(&moxa_openlock); + mutex_lock(&ch->port.mutex); ret = moxa_set_serial_info(ch, argp); - mutex_unlock(&moxa_openlock); + mutex_unlock(&ch->port.mutex); break; default: ret = -ENOIOCTLCMD; @@ -396,8 +410,6 @@ static const struct tty_operations moxa_ops = { .flush_buffer = moxa_flush_buffer, .chars_in_buffer = moxa_chars_in_buffer, .ioctl = moxa_ioctl, - .throttle = moxa_throttle, - .unthrottle = moxa_unthrottle, .set_termios = moxa_set_termios, .stop = moxa_stop, .start = moxa_start, @@ -409,11 +421,12 @@ static const struct tty_operations moxa_ops = { static const struct tty_port_operations moxa_port_ops = { .carrier_raised = moxa_carrier_raised, + .dtr_rts = moxa_dtr_rts, + .shutdown = moxa_shutdown, }; static struct tty_driver *moxaDriver; static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); -static DEFINE_SPINLOCK(moxa_lock); /* * HW init @@ -1112,14 +1125,12 @@ static void __exit moxa_exit(void) module_init(moxa_init); module_exit(moxa_exit); -static void moxa_close_port(struct tty_struct *tty) +static void moxa_shutdown(struct tty_port *port) { - struct moxa_port *ch = tty->driver_data; - moxa_shut_down(tty); + struct moxa_port *ch = container_of(port, struct moxa_port, port); + MoxaPortDisable(ch); MoxaPortFlushData(ch, 2); - ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; - tty->driver_data = NULL; - tty_port_tty_set(&ch->port, NULL); + clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); } static int moxa_carrier_raised(struct tty_port *port) @@ -1127,45 +1138,19 @@ static int moxa_carrier_raised(struct tty_port *port) struct moxa_port *ch = container_of(port, struct moxa_port, port); int dcd; - spin_lock_bh(&moxa_lock); + spin_lock_irq(&port->lock); dcd = ch->DCDState; - spin_unlock_bh(&moxa_lock); + spin_unlock_irq(&port->lock); return dcd; } -static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, - struct moxa_port *ch) +static void moxa_dtr_rts(struct tty_port *port, int onoff) { - struct tty_port *port = &ch->port; - DEFINE_WAIT(wait); - int retval = 0; - u8 dcd; - - while (1) { - prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp)) { -#ifdef SERIAL_DO_RESTART - retval = -ERESTARTSYS; -#else - retval = -EAGAIN; -#endif - break; - } - dcd = tty_port_carrier_raised(port); - if (dcd) - break; - - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - schedule(); - } - finish_wait(&port->open_wait, &wait); - - return retval; + struct moxa_port *ch = container_of(port, struct moxa_port, port); + MoxaPortLineCtrl(ch, onoff, onoff); } + static int moxa_open(struct tty_struct *tty, struct file *filp) { struct moxa_board_conf *brd; @@ -1194,6 +1179,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) ch->port.count++; tty->driver_data = ch; tty_port_tty_set(&ch->port, tty); + mutex_lock(&ch->port.mutex); if (!(ch->port.flags & ASYNC_INITIALIZED)) { ch->statusflags = 0; moxa_set_tty_param(tty, tty->termios); @@ -1202,58 +1188,20 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) MoxaSetFifo(ch, ch->type == PORT_16550A); ch->port.flags |= ASYNC_INITIALIZED; } + mutex_unlock(&ch->port.mutex); mutex_unlock(&moxa_openlock); - retval = 0; - if (!(filp->f_flags & O_NONBLOCK) && !C_CLOCAL(tty)) - retval = moxa_block_till_ready(tty, filp, ch); - mutex_lock(&moxa_openlock); - if (retval) { - if (ch->port.count) /* 0 means already hung up... */ - if (--ch->port.count == 0) - moxa_close_port(tty); - } else - ch->port.flags |= ASYNC_NORMAL_ACTIVE; - mutex_unlock(&moxa_openlock); - + retval = tty_port_block_til_ready(&ch->port, tty, filp); + if (retval == 0) + set_bit(ASYNCB_NORMAL_ACTIVE, &ch->port.flags); return retval; } static void moxa_close(struct tty_struct *tty, struct file *filp) { - struct moxa_port *ch; - int port; - - port = tty->index; - if (port == MAX_PORTS || tty_hung_up_p(filp)) - return; - - mutex_lock(&moxa_openlock); - ch = tty->driver_data; - if (ch == NULL) - goto unlock; - if (tty->count == 1 && ch->port.count != 1) { - printk(KERN_WARNING "moxa_close: bad serial port count; " - "tty->count is 1, ch->port.count is %d\n", ch->port.count); - ch->port.count = 1; - } - if (--ch->port.count < 0) { - printk(KERN_WARNING "moxa_close: bad serial port count, " - "device=%s\n", tty->name); - ch->port.count = 0; - } - if (ch->port.count) - goto unlock; - + struct moxa_port *ch = tty->driver_data; ch->cflag = tty->termios->c_cflag; - if (ch->port.flags & ASYNC_INITIALIZED) { - moxa_setup_empty_event(tty); - tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ - } - - moxa_close_port(tty); -unlock: - mutex_unlock(&moxa_openlock); + tty_port_close(&ch->port, tty, filp); } static int moxa_write(struct tty_struct *tty, @@ -1269,7 +1217,7 @@ static int moxa_write(struct tty_struct *tty, len = MoxaPortWriteData(tty, buf, count); spin_unlock_bh(&moxa_lock); - ch->statusflags |= LOWWAIT; + set_bit(LOWWAIT, &ch->statusflags); return len; } @@ -1300,40 +1248,21 @@ static int moxa_chars_in_buffer(struct tty_struct *tty) struct moxa_port *ch = tty->driver_data; int chars; - /* - * Sigh...I have to check if driver_data is NULL here, because - * if an open() fails, the TTY subsystem eventually calls - * tty_wait_until_sent(), which calls the driver's chars_in_buffer() - * routine. And since the open() failed, we return 0 here. TDJ - */ - if (ch == NULL) - return 0; - lock_kernel(); chars = MoxaPortTxQueue(ch); - if (chars) { + if (chars) /* * Make it possible to wakeup anything waiting for output * in tty_ioctl.c, etc. */ - if (!(ch->statusflags & EMPTYWAIT)) - moxa_setup_empty_event(tty); - } - unlock_kernel(); + set_bit(EMPTYWAIT, &ch->statusflags); return chars; } static int moxa_tiocmget(struct tty_struct *tty, struct file *file) { - struct moxa_port *ch; + struct moxa_port *ch = tty->driver_data; int flag = 0, dtr, rts; - mutex_lock(&moxa_openlock); - ch = tty->driver_data; - if (!ch) { - mutex_unlock(&moxa_openlock); - return -EINVAL; - } - MoxaPortGetLineOut(ch, &dtr, &rts); if (dtr) flag |= TIOCM_DTR; @@ -1346,7 +1275,6 @@ static int moxa_tiocmget(struct tty_struct *tty, struct file *file) flag |= TIOCM_DSR; if (dtr & 4) flag |= TIOCM_CD; - mutex_unlock(&moxa_openlock); return flag; } @@ -1379,20 +1307,6 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, return 0; } -static void moxa_throttle(struct tty_struct *tty) -{ - struct moxa_port *ch = tty->driver_data; - - ch->statusflags |= THROTTLE; -} - -static void moxa_unthrottle(struct tty_struct *tty) -{ - struct moxa_port *ch = tty->driver_data; - - ch->statusflags &= ~THROTTLE; -} - static void moxa_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { @@ -1412,7 +1326,7 @@ static void moxa_stop(struct tty_struct *tty) if (ch == NULL) return; MoxaPortTxDisable(ch); - ch->statusflags |= TXSTOPPED; + set_bit(TXSTOPPED, &ch->statusflags); } @@ -1427,38 +1341,32 @@ static void moxa_start(struct tty_struct *tty) return; MoxaPortTxEnable(ch); - ch->statusflags &= ~TXSTOPPED; + clear_bit(TXSTOPPED, &ch->statusflags); } static void moxa_hangup(struct tty_struct *tty) { - struct moxa_port *ch; - - mutex_lock(&moxa_openlock); - ch = tty->driver_data; - if (ch == NULL) { - mutex_unlock(&moxa_openlock); - return; - } - ch->port.count = 0; - moxa_close_port(tty); - mutex_unlock(&moxa_openlock); - - wake_up_interruptible(&ch->port.open_wait); + struct moxa_port *ch = tty->driver_data; + tty_port_hangup(&ch->port); } static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) { struct tty_struct *tty; + unsigned long flags; dcd = !!dcd; + spin_lock_irqsave(&p->port.lock, flags); if (dcd != p->DCDState) { + p->DCDState = dcd; + spin_unlock_irqrestore(&p->port.lock, flags); tty = tty_port_tty_get(&p->port); if (tty && C_CLOCAL(tty) && !dcd) tty_hangup(tty); tty_kref_put(tty); } - p->DCDState = dcd; + else + spin_unlock_irqrestore(&p->port.lock, flags); } static int moxa_poll_port(struct moxa_port *p, unsigned int handle, @@ -1470,24 +1378,24 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle, u16 intr; if (tty) { - if ((p->statusflags & EMPTYWAIT) && + if (test_bit(EMPTYWAIT, &p->statusflags) && MoxaPortTxQueue(p) == 0) { - p->statusflags &= ~EMPTYWAIT; + clear_bit(EMPTYWAIT, &p->statusflags); tty_wakeup(tty); } - if ((p->statusflags & LOWWAIT) && !tty->stopped && + if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped && MoxaPortTxQueue(p) <= WAKEUP_CHARS) { - p->statusflags &= ~LOWWAIT; + clear_bit(LOWWAIT, &p->statusflags); tty_wakeup(tty); } - if (inited && !(p->statusflags & THROTTLE) && + if (inited && !test_bit(TTY_THROTTLED, &tty->flags) && MoxaPortRxQueue(p) > 0) { /* RX */ MoxaPortReadData(p); tty_schedule_flip(tty); } } else { - p->statusflags &= ~EMPTYWAIT; + clear_bit(EMPTYWAIT, &p->statusflags); MoxaPortFlushData(p, 0); /* flush RX */ } @@ -1588,35 +1496,6 @@ static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_term tty_encode_baud_rate(tty, baud, baud); } -static void moxa_setup_empty_event(struct tty_struct *tty) -{ - struct moxa_port *ch = tty->driver_data; - - spin_lock_bh(&moxa_lock); - ch->statusflags |= EMPTYWAIT; - spin_unlock_bh(&moxa_lock); -} - -static void moxa_shut_down(struct tty_struct *tty) -{ - struct moxa_port *ch = tty->driver_data; - - if (!(ch->port.flags & ASYNC_INITIALIZED)) - return; - - MoxaPortDisable(ch); - - /* - * If we're a modem control device and HUPCL is on, drop RTS & DTR. - */ - if (C_HUPCL(tty)) - MoxaPortLineCtrl(ch, 0, 0); - - spin_lock_bh(&moxa_lock); - ch->port.flags &= ~ASYNC_INITIALIZED; - spin_unlock_bh(&moxa_lock); -} - /***************************************************************************** * Driver level functions: * *****************************************************************************/ @@ -1918,10 +1797,12 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, baud = MoxaPortSetBaud(port, baud); if (termio->c_iflag & (IXON | IXOFF | IXANY)) { + spin_lock_irq(&moxafunc_lock); writeb(termio->c_cc[VSTART], ofsAddr + FuncArg); writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); writeb(FC_SetXonXoff, ofsAddr + FuncCode); moxa_wait_finish(ofsAddr); + spin_unlock_irq(&moxafunc_lock); } return baud; @@ -1974,18 +1855,14 @@ static int MoxaPortLineStatus(struct moxa_port *port) int val; ofsAddr = port->tableAddr; - if (MOXA_IS_320(port->board)) { - moxafunc(ofsAddr, FC_LineStatus, 0); - val = readw(ofsAddr + FuncArg); - } else { + if (MOXA_IS_320(port->board)) + val = moxafuncret(ofsAddr, FC_LineStatus, 0); + else val = readw(ofsAddr + FlagStat) >> 4; - } val &= 0x0B; if (val & 8) val |= 4; - spin_lock_bh(&moxa_lock); moxa_new_dcdstate(port, val & 8); - spin_unlock_bh(&moxa_lock); val &= 7; return val; } diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 5e28d39b9e8196e306fabc6df4eb1ce58e6c9f70..3d923065d9a29ca1381023d132759bcb4b735ed2 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -856,9 +855,9 @@ static void mxser_check_modem_status(struct tty_struct *tty, } } -static int mxser_startup(struct tty_struct *tty) +static int mxser_activate(struct tty_port *port, struct tty_struct *tty) { - struct mxser_port *info = tty->driver_data; + struct mxser_port *info = container_of(port, struct mxser_port, port); unsigned long page; unsigned long flags; @@ -868,22 +867,13 @@ static int mxser_startup(struct tty_struct *tty) spin_lock_irqsave(&info->slock, flags); - if (info->port.flags & ASYNC_INITIALIZED) { - free_page(page); - spin_unlock_irqrestore(&info->slock, flags); - return 0; - } - if (!info->ioaddr || !info->type) { set_bit(TTY_IO_ERROR, &tty->flags); free_page(page); spin_unlock_irqrestore(&info->slock, flags); return 0; } - if (info->port.xmit_buf) - free_page(page); - else - info->port.xmit_buf = (unsigned char *) page; + info->port.xmit_buf = (unsigned char *) page; /* * Clear the FIFO buffers and disable them @@ -951,24 +941,19 @@ static int mxser_startup(struct tty_struct *tty) * and set the speed of the serial port */ mxser_change_speed(tty, NULL); - info->port.flags |= ASYNC_INITIALIZED; spin_unlock_irqrestore(&info->slock, flags); return 0; } /* - * This routine will shutdown a serial port; interrupts maybe disabled, and - * DTR is dropped if the hangup on close termio flag is on. + * This routine will shutdown a serial port */ -static void mxser_shutdown(struct tty_struct *tty) +static void mxser_shutdown_port(struct tty_port *port) { - struct mxser_port *info = tty->driver_data; + struct mxser_port *info = container_of(port, struct mxser_port, port); unsigned long flags; - if (!(info->port.flags & ASYNC_INITIALIZED)) - return; - spin_lock_irqsave(&info->slock, flags); /* @@ -978,7 +963,7 @@ static void mxser_shutdown(struct tty_struct *tty) wake_up_interruptible(&info->port.delta_msr_wait); /* - * Free the IRQ, if necessary + * Free the xmit buffer, if necessary */ if (info->port.xmit_buf) { free_page((unsigned long) info->port.xmit_buf); @@ -988,10 +973,6 @@ static void mxser_shutdown(struct tty_struct *tty) info->IER = 0; outb(0x00, info->ioaddr + UART_IER); - if (tty->termios->c_cflag & HUPCL) - info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS); - outb(info->MCR, info->ioaddr + UART_MCR); - /* clear Rx/Tx FIFO's */ if (info->board->chip_flag) outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | @@ -1004,9 +985,6 @@ static void mxser_shutdown(struct tty_struct *tty) /* read data port to reset things */ (void) inb(info->ioaddr + UART_RX); - set_bit(TTY_IO_ERROR, &tty->flags); - - info->port.flags &= ~ASYNC_INITIALIZED; if (info->board->chip_flag) SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); @@ -1023,8 +1001,7 @@ static void mxser_shutdown(struct tty_struct *tty) static int mxser_open(struct tty_struct *tty, struct file *filp) { struct mxser_port *info; - unsigned long flags; - int retval, line; + int line; line = tty->index; if (line == MXSER_PORTS) @@ -1035,23 +1012,7 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) if (!info->ioaddr) return -ENODEV; - tty->driver_data = info; - tty_port_tty_set(&info->port, tty); - /* - * Start up serial port - */ - spin_lock_irqsave(&info->port.lock, flags); - info->port.count++; - spin_unlock_irqrestore(&info->port.lock, flags); - retval = mxser_startup(tty); - if (retval) - return retval; - - retval = tty_port_block_til_ready(&info->port, tty, filp); - if (retval) - return retval; - - return 0; + return tty_port_open(&info->port, tty, filp); } static void mxser_flush_buffer(struct tty_struct *tty) @@ -1075,18 +1036,10 @@ static void mxser_flush_buffer(struct tty_struct *tty) } -static void mxser_close_port(struct tty_struct *tty, struct tty_port *port) +static void mxser_close_port(struct tty_port *port) { struct mxser_port *info = container_of(port, struct mxser_port, port); unsigned long timeout; - /* - * Save the termios structure, since this port may have - * separate termios for callout and dialin. - * - * FIXME: Can this go ? - */ - if (port->flags & ASYNC_NORMAL_ACTIVE) - info->normal_termios = *tty->termios; /* * At this point we stop accepting input. To do this, we * disable the receive line status interrupts, and tell the @@ -1097,22 +1050,18 @@ static void mxser_close_port(struct tty_struct *tty, struct tty_port *port) if (info->board->chip_flag) info->IER &= ~MOXA_MUST_RECV_ISR; - if (port->flags & ASYNC_INITIALIZED) { - outb(info->IER, info->ioaddr + UART_IER); - /* - * 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 (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { - schedule_timeout_interruptible(5); - if (time_after(jiffies, timeout)) - break; - } + outb(info->IER, info->ioaddr + UART_IER); + /* + * 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 (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { + schedule_timeout_interruptible(5); + if (time_after(jiffies, timeout)) + break; } - mxser_shutdown(tty); - } /* @@ -1130,8 +1079,12 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) return; if (tty_port_close_start(port, tty, filp) == 0) return; - mxser_close_port(tty, port); + mutex_lock(&port->mutex); + mxser_close_port(port); mxser_flush_buffer(tty); + mxser_shutdown_port(port); + clear_bit(ASYNCB_INITIALIZED, &port->flags); + mutex_unlock(&port->mutex); /* Right now the tty_port set is done outside of the close_end helper as we don't yet have everyone using refcounts */ tty_port_close_end(port, tty); @@ -1275,6 +1228,7 @@ static int mxser_set_serial_info(struct tty_struct *tty, struct serial_struct __user *new_info) { struct mxser_port *info = tty->driver_data; + struct tty_port *port = &info->port; struct serial_struct new_serial; speed_t baud; unsigned long sl_flags; @@ -1290,7 +1244,7 @@ static int mxser_set_serial_info(struct tty_struct *tty, new_serial.port != info->ioaddr) return -EINVAL; - flags = info->port.flags & ASYNC_SPD_MASK; + flags = port->flags & ASYNC_SPD_MASK; if (!capable(CAP_SYS_ADMIN)) { if ((new_serial.baud_base != info->baud_base) || @@ -1304,16 +1258,17 @@ static int mxser_set_serial_info(struct tty_struct *tty, * OK, past this point, all the error checking has been done. * At this point, we start making changes..... */ - info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) | + port->flags = ((port->flags & ~ASYNC_FLAGS) | (new_serial.flags & ASYNC_FLAGS)); - info->port.close_delay = new_serial.close_delay * HZ / 100; - info->port.closing_wait = new_serial.closing_wait * HZ / 100; - tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) - ? 1 : 0; - if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && + port->close_delay = new_serial.close_delay * HZ / 100; + port->closing_wait = new_serial.closing_wait * HZ / 100; + tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && (new_serial.baud_base != info->baud_base || new_serial.custom_divisor != info->custom_divisor)) { + if (new_serial.custom_divisor == 0) + return -EINVAL; baud = new_serial.baud_base / new_serial.custom_divisor; tty_encode_baud_rate(tty, baud, baud); } @@ -1323,15 +1278,17 @@ static int mxser_set_serial_info(struct tty_struct *tty, process_txrx_fifo(info); - if (info->port.flags & ASYNC_INITIALIZED) { - if (flags != (info->port.flags & ASYNC_SPD_MASK)) { + if (test_bit(ASYNCB_INITIALIZED, &port->flags)) { + if (flags != (port->flags & ASYNC_SPD_MASK)) { spin_lock_irqsave(&info->slock, sl_flags); mxser_change_speed(tty, NULL); spin_unlock_irqrestore(&info->slock, sl_flags); } - } else - retval = mxser_startup(tty); - + } else { + retval = mxser_activate(port, tty); + if (retval == 0) + set_bit(ASYNCB_INITIALIZED, &port->flags); + } return retval; } @@ -1520,7 +1477,8 @@ static int __init mxser_read_register(int port, unsigned short *regs) static int mxser_ioctl_special(unsigned int cmd, void __user *argp) { - struct mxser_port *port; + struct mxser_port *ip; + struct tty_port *port; struct tty_struct *tty; int result, status; unsigned int i, j; @@ -1536,38 +1494,39 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) case MOXA_CHKPORTENABLE: result = 0; - lock_kernel(); for (i = 0; i < MXSER_BOARDS; i++) for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) if (mxser_boards[i].ports[j].ioaddr) result |= (1 << i); - unlock_kernel(); return put_user(result, (unsigned long __user *)argp); case MOXA_GETDATACOUNT: - lock_kernel(); + /* The receive side is locked by port->slock but it isn't + clear that an exact snapshot is worth copying here */ if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) ret = -EFAULT; - unlock_kernel(); return ret; case MOXA_GETMSTATUS: { struct mxser_mstatus ms, __user *msu = argp; - lock_kernel(); for (i = 0; i < MXSER_BOARDS; i++) for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { - port = &mxser_boards[i].ports[j]; + ip = &mxser_boards[i].ports[j]; + port = &ip->port; memset(&ms, 0, sizeof(ms)); - if (!port->ioaddr) + mutex_lock(&port->mutex); + if (!ip->ioaddr) goto copy; - tty = tty_port_tty_get(&port->port); + tty = tty_port_tty_get(port); if (!tty || !tty->termios) - ms.cflag = port->normal_termios.c_cflag; + ms.cflag = ip->normal_termios.c_cflag; else ms.cflag = tty->termios->c_cflag; tty_kref_put(tty); - status = inb(port->ioaddr + UART_MSR); + spin_lock_irq(&ip->slock); + status = inb(ip->ioaddr + UART_MSR); + spin_unlock_irq(&ip->slock); if (status & UART_MSR_DCD) ms.dcd = 1; if (status & UART_MSR_DSR) @@ -1575,13 +1534,11 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) if (status & UART_MSR_CTS) ms.cts = 1; copy: - if (copy_to_user(msu, &ms, sizeof(ms))) { - unlock_kernel(); + mutex_unlock(&port->mutex); + if (copy_to_user(msu, &ms, sizeof(ms))) return -EFAULT; - } msu++; } - unlock_kernel(); return 0; } case MOXA_ASPP_MON_EXT: { @@ -1593,41 +1550,48 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) if (!me) return -ENOMEM; - lock_kernel(); for (i = 0, p = 0; i < MXSER_BOARDS; i++) { for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { if (p >= ARRAY_SIZE(me->rx_cnt)) { i = MXSER_BOARDS; break; } - port = &mxser_boards[i].ports[j]; - if (!port->ioaddr) + ip = &mxser_boards[i].ports[j]; + port = &ip->port; + + mutex_lock(&port->mutex); + if (!ip->ioaddr) { + mutex_unlock(&port->mutex); continue; + } - status = mxser_get_msr(port->ioaddr, 0, p); + spin_lock_irq(&ip->slock); + status = mxser_get_msr(ip->ioaddr, 0, p); if (status & UART_MSR_TERI) - port->icount.rng++; + ip->icount.rng++; if (status & UART_MSR_DDSR) - port->icount.dsr++; + ip->icount.dsr++; if (status & UART_MSR_DDCD) - port->icount.dcd++; + ip->icount.dcd++; if (status & UART_MSR_DCTS) - port->icount.cts++; + ip->icount.cts++; - port->mon_data.modem_status = status; - me->rx_cnt[p] = port->mon_data.rxcnt; - me->tx_cnt[p] = port->mon_data.txcnt; - me->up_rxcnt[p] = port->mon_data.up_rxcnt; - me->up_txcnt[p] = port->mon_data.up_txcnt; + ip->mon_data.modem_status = status; + me->rx_cnt[p] = ip->mon_data.rxcnt; + me->tx_cnt[p] = ip->mon_data.txcnt; + me->up_rxcnt[p] = ip->mon_data.up_rxcnt; + me->up_txcnt[p] = ip->mon_data.up_txcnt; me->modem_status[p] = - port->mon_data.modem_status; - tty = tty_port_tty_get(&port->port); + ip->mon_data.modem_status; + spin_unlock_irq(&ip->slock); + + tty = tty_port_tty_get(&ip->port); if (!tty || !tty->termios) { - cflag = port->normal_termios.c_cflag; - iflag = port->normal_termios.c_iflag; - me->baudrate[p] = tty_termios_baud_rate(&port->normal_termios); + cflag = ip->normal_termios.c_cflag; + iflag = ip->normal_termios.c_iflag; + me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios); } else { cflag = tty->termios->c_cflag; iflag = tty->termios->c_iflag; @@ -1646,16 +1610,15 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) if (iflag & (IXON | IXOFF)) me->flowctrl[p] |= 0x0C; - if (port->type == PORT_16550A) + if (ip->type == PORT_16550A) me->fifo[p] = 1; - opmode = inb(port->opmode_ioaddr) >> - ((p % 4) * 2); + opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2); opmode &= OP_MODE_MASK; me->iftype[p] = opmode; + mutex_unlock(&port->mutex); } } - unlock_kernel(); if (copy_to_user(argp, me, sizeof(*me))) ret = -EFAULT; kfree(me); @@ -1692,6 +1655,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { struct mxser_port *info = tty->driver_data; + struct tty_port *port = &info->port; struct async_icount cnow; unsigned long flags; void __user *argp = (void __user *)arg; @@ -1716,20 +1680,20 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, opmode != RS422_MODE && opmode != RS485_4WIRE_MODE) return -EFAULT; - lock_kernel(); mask = ModeMask[p]; shiftbit = p * 2; + spin_lock_irq(&info->slock); val = inb(info->opmode_ioaddr); val &= mask; val |= (opmode << shiftbit); outb(val, info->opmode_ioaddr); - unlock_kernel(); + spin_unlock_irq(&info->slock); } else { - lock_kernel(); shiftbit = p * 2; + spin_lock_irq(&info->slock); opmode = inb(info->opmode_ioaddr) >> shiftbit; + spin_unlock_irq(&info->slock); opmode &= OP_MODE_MASK; - unlock_kernel(); if (put_user(opmode, (int __user *)argp)) return -EFAULT; } @@ -1742,14 +1706,14 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, switch (cmd) { case TIOCGSERIAL: - lock_kernel(); + mutex_lock(&port->mutex); retval = mxser_get_serial_info(tty, argp); - unlock_kernel(); + mutex_unlock(&port->mutex); return retval; case TIOCSSERIAL: - lock_kernel(); + mutex_lock(&port->mutex); retval = mxser_set_serial_info(tty, argp); - unlock_kernel(); + mutex_unlock(&port->mutex); return retval; case TIOCSERGETLSR: /* Get line status register */ return mxser_get_lsr_info(info, argp); @@ -1795,31 +1759,33 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, case MOXA_HighSpeedOn: return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); case MOXA_SDS_RSTICOUNTER: - lock_kernel(); + spin_lock_irq(&info->slock); info->mon_data.rxcnt = 0; info->mon_data.txcnt = 0; - unlock_kernel(); + spin_unlock_irq(&info->slock); return 0; case MOXA_ASPP_OQUEUE:{ int len, lsr; - lock_kernel(); len = mxser_chars_in_buffer(tty); + spin_lock(&info->slock); lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE; + spin_unlock_irq(&info->slock); len += (lsr ? 0 : 1); - unlock_kernel(); return put_user(len, (int __user *)argp); } case MOXA_ASPP_MON: { int mcr, status; - lock_kernel(); + spin_lock(&info->slock); status = mxser_get_msr(info->ioaddr, 1, tty->index); mxser_check_modem_status(tty, info, status); mcr = inb(info->ioaddr + UART_MCR); + spin_unlock(&info->slock); + if (mcr & MOXA_MUST_MCR_XON_FLAG) info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; else @@ -1834,7 +1800,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; else info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; - unlock_kernel(); + if (copy_to_user(argp, &info->mon_data, sizeof(struct mxser_mon))) return -EFAULT; @@ -1993,6 +1959,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) { struct mxser_port *info = tty->driver_data; unsigned long orig_jiffies, char_time; + unsigned long flags; int lsr; if (info->type == PORT_UNKNOWN) @@ -2032,19 +1999,21 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) timeout, char_time); printk("jiff=%lu...", jiffies); #endif - lock_kernel(); + spin_lock_irqsave(&info->slock, flags); while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk("lsr = %d (jiff=%lu)...", lsr, jiffies); #endif + spin_unlock_irqrestore(&info->slock, flags); schedule_timeout_interruptible(char_time); + spin_lock_irqsave(&info->slock, flags); if (signal_pending(current)) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) break; } + spin_unlock_irqrestore(&info->slock, flags); set_current_state(TASK_RUNNING); - unlock_kernel(); #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); @@ -2059,7 +2028,6 @@ static void mxser_hangup(struct tty_struct *tty) struct mxser_port *info = tty->driver_data; mxser_flush_buffer(tty); - mxser_shutdown(tty); tty_port_hangup(&info->port); } @@ -2363,6 +2331,8 @@ static const struct tty_operations mxser_ops = { struct tty_port_operations mxser_port_ops = { .carrier_raised = mxser_carrier_raised, .dtr_rts = mxser_dtr_rts, + .activate = mxser_activate, + .shutdown = mxser_shutdown_port, }; /* diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 4008e2ce73c1a37e14ec5e8939d9b3a2ee59efde..fdbcc9fd6d3143a00810fd664d77379ee083717b 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -264,10 +264,16 @@ static ssize_t nvram_write(struct file *file, const char __user *buf, unsigned char contents[NVRAM_BYTES]; unsigned i = *ppos; unsigned char *tmp; - int len; - len = (NVRAM_BYTES - i) < count ? (NVRAM_BYTES - i) : count; - if (copy_from_user(contents, buf, len)) + if (i >= NVRAM_BYTES) + return 0; /* Past EOF */ + + if (count > NVRAM_BYTES - i) + count = NVRAM_BYTES - i; + if (count > NVRAM_BYTES) + return -EFAULT; /* Can't happen, but prove it to gcc */ + + if (copy_from_user(contents, buf, count)) return -EFAULT; spin_lock_irq(&rtc_lock); @@ -275,7 +281,7 @@ static ssize_t nvram_write(struct file *file, const char __user *buf, if (!__nvram_check_checksum()) goto checksum_err; - for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp) + for (tmp = contents; count--; ++i, ++tmp) __nvram_write_byte(*tmp, i); __nvram_set_checksum(); diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index 674b3ab3587d505458fbdb802fc0a7cbcdf7d2eb..2bb7874a6899d5afee7e1bc65c154f63ee482287 100644 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ b/drivers/char/pcmcia/ipwireless/tty.c @@ -603,7 +603,7 @@ void ipwireless_tty_free(struct ipw_tty *tty) } } -static struct tty_operations tty_ops = { +static const struct tty_operations tty_ops = { .open = ipw_open, .close = ipw_close, .hangup = ipw_hangup, diff --git a/drivers/char/pty.c b/drivers/char/pty.c index d86c0bc05c1c7839b4db8873daf96a21fd32cfe8..385c44b3034f4000df9d8a4ad917f3e030c4a143 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -659,7 +659,7 @@ static int __ptmx_open(struct inode *inode, struct file *filp) if (!retval) return 0; out1: - tty_release_dev(filp); + tty_release(inode, filp); return retval; out: devpts_kill_index(inode, index); diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 3cfa22d469e0cd7f74e01b416f428dc3be508add..0a8d1e56c99362e0da9b1df06c2452d30341d006 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -793,26 +793,21 @@ static void rc_change_speed(struct tty_struct *tty, struct riscom_board *bp, } /* Must be called with interrupts enabled */ -static int rc_setup_port(struct tty_struct *tty, struct riscom_board *bp, - struct riscom_port *port) +static int rc_activate_port(struct tty_port *port, struct tty_struct *tty) { + struct riscom_port *rp = container_of(port, struct riscom_port, port); + struct riscom_board *bp = port_Board(rp); unsigned long flags; - if (port->port.flags & ASYNC_INITIALIZED) - return 0; - - if (tty_port_alloc_xmit_buf(&port->port) < 0) + if (tty_port_alloc_xmit_buf(port) < 0) return -ENOMEM; spin_lock_irqsave(&riscom_lock, flags); clear_bit(TTY_IO_ERROR, &tty->flags); - if (port->port.count == 1) - bp->count++; - port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; - rc_change_speed(tty, bp, port); - port->port.flags |= ASYNC_INITIALIZED; - + bp->count++; + rp->xmit_cnt = rp->xmit_head = rp->xmit_tail = 0; + rc_change_speed(tty, bp, rp); spin_unlock_irqrestore(&riscom_lock, flags); return 0; } @@ -821,9 +816,6 @@ static int rc_setup_port(struct tty_struct *tty, struct riscom_board *bp, static void rc_shutdown_port(struct tty_struct *tty, struct riscom_board *bp, struct riscom_port *port) { - if (!(port->port.flags & ASYNC_INITIALIZED)) - return; - #ifdef RC_REPORT_OVERRUN printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n", board_No(bp), port_No(port), port->overrun); @@ -840,11 +832,6 @@ static void rc_shutdown_port(struct tty_struct *tty, } #endif tty_port_free_xmit_buf(&port->port); - if (C_HUPCL(tty)) { - /* Drop DTR */ - bp->DTR |= (1u << port_No(port)); - rc_out(bp, RC_DTR, bp->DTR); - } /* Select port */ rc_out(bp, CD180_CAR, port_No(port)); @@ -856,7 +843,6 @@ static void rc_shutdown_port(struct tty_struct *tty, rc_out(bp, CD180_IER, port->IER); set_bit(TTY_IO_ERROR, &tty->flags); - port->port.flags &= ~ASYNC_INITIALIZED; if (--bp->count < 0) { printk(KERN_INFO "rc%d: rc_shutdown_port: " @@ -889,6 +875,20 @@ static int carrier_raised(struct tty_port *port) return CD; } +static void dtr_rts(struct tty_port *port, int onoff) +{ + struct riscom_port *p = container_of(port, struct riscom_port, port); + struct riscom_board *bp = port_Board(p); + unsigned long flags; + + spin_lock_irqsave(&riscom_lock, flags); + bp->DTR &= ~(1u << port_No(p)); + if (onoff == 0) + bp->DTR |= (1u << port_No(p)); + rc_out(bp, RC_DTR, bp->DTR); + spin_unlock_irqrestore(&riscom_lock, flags); +} + static int rc_open(struct tty_struct *tty, struct file *filp) { int board; @@ -909,14 +909,7 @@ static int rc_open(struct tty_struct *tty, struct file *filp) if (error) return error; - port->port.count++; - tty->driver_data = port; - tty_port_tty_set(&port->port, tty); - - error = rc_setup_port(tty, bp, port); - if (error == 0) - error = tty_port_block_til_ready(&port->port, tty, filp); - return error; + return tty_port_open(&port->port, tty, filp); } static void rc_flush_buffer(struct tty_struct *tty) @@ -950,24 +943,23 @@ static void rc_close_port(struct tty_port *port) spin_lock_irqsave(&riscom_lock, flags); rp->IER &= ~IER_RXD; - if (port->flags & ASYNC_INITIALIZED) { - rp->IER &= ~IER_TXRDY; - rp->IER |= IER_TXEMPTY; - rc_out(bp, CD180_CAR, port_No(rp)); - rc_out(bp, CD180_IER, rp->IER); - /* - * 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 (rp->IER & IER_TXEMPTY) { - spin_unlock_irqrestore(&riscom_lock, flags); - msleep_interruptible(jiffies_to_msecs(rp->timeout)); - spin_lock_irqsave(&riscom_lock, flags); - if (time_after(jiffies, timeout)) - break; - } + + rp->IER &= ~IER_TXRDY; + rp->IER |= IER_TXEMPTY; + rc_out(bp, CD180_CAR, port_No(rp)); + rc_out(bp, CD180_IER, rp->IER); + /* + * 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 (rp->IER & IER_TXEMPTY) { + spin_unlock_irqrestore(&riscom_lock, flags); + msleep_interruptible(jiffies_to_msecs(rp->timeout)); + spin_lock_irqsave(&riscom_lock, flags); + if (time_after(jiffies, timeout)) + break; } rc_shutdown_port(port->tty, bp, rp); spin_unlock_irqrestore(&riscom_lock, flags); @@ -1354,7 +1346,6 @@ static void rc_hangup(struct tty_struct *tty) if (rc_paranoia_check(port, tty->name, "rc_hangup")) return; - rc_shutdown_port(tty, port_Board(port), port); tty_port_hangup(&port->port); } @@ -1401,7 +1392,9 @@ static const struct tty_operations riscom_ops = { static const struct tty_port_operations riscom_port_ops = { .carrier_raised = carrier_raised, + .dtr_rts = dtr_rts, .shutdown = rc_close_port, + .activate = rc_activate_port, }; diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index db6dcfa35ba0dc44e183f33c5ded7b3a4f0e6051..0e511d61f544eac34417456e509d86bedfd13624 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -407,7 +407,7 @@ static unsigned int stl_baudrates[] = { * Declare all those functions in this driver! */ -static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); +static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg); static int stl_brdinit(struct stlbrd *brdp); static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); @@ -607,7 +607,7 @@ static unsigned int sc26198_baudtable[] = { */ static const struct file_operations stl_fsiomem = { .owner = THIS_MODULE, - .ioctl = stl_memioctl, + .unlocked_ioctl = stl_memioctl, }; static struct class *stallion_class; @@ -702,6 +702,24 @@ static struct stlbrd *stl_allocbrd(void) /*****************************************************************************/ +static int stl_activate(struct tty_port *port, struct tty_struct *tty) +{ + struct stlport *portp = container_of(port, struct stlport, port); + if (!portp->tx.buf) { + portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); + if (!portp->tx.buf) + return -ENOMEM; + portp->tx.head = portp->tx.buf; + portp->tx.tail = portp->tx.buf; + } + stl_setport(portp, tty->termios); + portp->sigs = stl_getsignals(portp); + stl_setsignals(portp, 1, 1); + stl_enablerxtx(portp, 1, 1); + stl_startrxtx(portp, 1, 0); + return 0; +} + static int stl_open(struct tty_struct *tty, struct file *filp) { struct stlport *portp; @@ -737,32 +755,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp) if (portp == NULL) return -ENODEV; port = &portp->port; + return tty_port_open(&portp->port, tty, filp); -/* - * On the first open of the device setup the port hardware, and - * initialize the per port data structure. - */ - tty_port_tty_set(port, tty); - tty->driver_data = portp; - port->count++; - - if ((port->flags & ASYNC_INITIALIZED) == 0) { - if (!portp->tx.buf) { - portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); - if (!portp->tx.buf) - return -ENOMEM; - portp->tx.head = portp->tx.buf; - portp->tx.tail = portp->tx.buf; - } - stl_setport(portp, tty->termios); - portp->sigs = stl_getsignals(portp); - stl_setsignals(portp, 1, 1); - stl_enablerxtx(portp, 1, 1); - stl_startrxtx(portp, 1, 0); - clear_bit(TTY_IO_ERROR, &tty->flags); - port->flags |= ASYNC_INITIALIZED; - } - return tty_port_block_til_ready(port, tty, filp); } /*****************************************************************************/ @@ -826,38 +820,12 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) /*****************************************************************************/ -static void stl_close(struct tty_struct *tty, struct file *filp) +static void stl_shutdown(struct tty_port *port) { - struct stlport *portp; - struct tty_port *port; - unsigned long flags; - - pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); - - portp = tty->driver_data; - BUG_ON(portp == NULL); - - port = &portp->port; - - if (tty_port_close_start(port, tty, filp) == 0) - return; -/* - * May want to wait for any data to drain before closing. The BUSY - * flag keeps track of whether we are still sending or not - it is - * very accurate for the cd1400, not quite so for the sc26198. - * (The sc26198 has no "end-of-data" interrupt only empty FIFO) - */ - stl_waituntilsent(tty, (HZ / 2)); - - spin_lock_irqsave(&port->lock, flags); - portp->port.flags &= ~ASYNC_INITIALIZED; - spin_unlock_irqrestore(&port->lock, flags); - + struct stlport *portp = container_of(port, struct stlport, port); stl_disableintrs(portp); - if (tty->termios->c_cflag & HUPCL) - stl_setsignals(portp, 0, 0); stl_enablerxtx(portp, 0, 0); - stl_flushbuffer(tty); + stl_flush(portp); portp->istate = 0; if (portp->tx.buf != NULL) { kfree(portp->tx.buf); @@ -865,9 +833,16 @@ static void stl_close(struct tty_struct *tty, struct file *filp) portp->tx.head = NULL; portp->tx.tail = NULL; } +} + +static void stl_close(struct tty_struct *tty, struct file *filp) +{ + struct stlport*portp; + pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); - tty_port_close_end(port, tty); - tty_port_tty_set(port, NULL); + portp = tty->driver_data; + BUG_ON(portp == NULL); + tty_port_close(&portp->port, tty, filp); } /*****************************************************************************/ @@ -1314,35 +1289,12 @@ static void stl_stop(struct tty_struct *tty) static void stl_hangup(struct tty_struct *tty) { - struct stlport *portp; - struct tty_port *port; - unsigned long flags; - + struct stlport *portp = tty->driver_data; pr_debug("stl_hangup(tty=%p)\n", tty); - portp = tty->driver_data; if (portp == NULL) return; - port = &portp->port; - - spin_lock_irqsave(&port->lock, flags); - port->flags &= ~ASYNC_INITIALIZED; - spin_unlock_irqrestore(&port->lock, flags); - - stl_disableintrs(portp); - if (tty->termios->c_cflag & HUPCL) - stl_setsignals(portp, 0, 0); - stl_enablerxtx(portp, 0, 0); - stl_flushbuffer(tty); - portp->istate = 0; - set_bit(TTY_IO_ERROR, &tty->flags); - if (portp->tx.buf != NULL) { - kfree(portp->tx.buf); - portp->tx.buf = NULL; - portp->tx.head = NULL; - portp->tx.tail = NULL; - } - tty_port_hangup(port); + tty_port_hangup(&portp->port); } /*****************************************************************************/ @@ -2486,18 +2438,19 @@ static int stl_getbrdstruct(struct stlbrd __user *arg) * collection. */ -static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) +static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) { int brdnr, rc; void __user *argp = (void __user *)arg; - pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg); + pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg); - brdnr = iminor(ip); + brdnr = iminor(fp->f_dentry->d_inode); if (brdnr >= STL_MAXBRDS) return -ENODEV; rc = 0; + lock_kernel(); switch (cmd) { case COM_GETPORTSTATS: rc = stl_getportstats(NULL, NULL, argp); @@ -2518,7 +2471,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns rc = -ENOIOCTLCMD; break; } - + unlock_kernel(); return rc; } @@ -2549,6 +2502,8 @@ static const struct tty_operations stl_ops = { static const struct tty_port_operations stl_port_ops = { .carrier_raised = stl_carrier_raised, .dtr_rts = stl_dtr_rts, + .activate = stl_activate, + .shutdown = stl_shutdown, }; /*****************************************************************************/ diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 59499ee0fe6a11850eb851ad829dbb1a1b0d6dbc..f15df40bc318fc90fd9825fab91a10a528e2d617 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -142,7 +142,6 @@ ssize_t redirected_tty_write(struct file *, const char __user *, size_t, loff_t *); static unsigned int tty_poll(struct file *, poll_table *); static int tty_open(struct inode *, struct file *); -static int tty_release(struct inode *, struct file *); long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg); #ifdef CONFIG_COMPAT static long tty_compat_ioctl(struct file *file, unsigned int cmd, @@ -506,8 +505,6 @@ static void do_tty_hangup(struct work_struct *work) if (!tty) return; - /* inuse_filps is protected by the single kernel lock */ - lock_kernel(); spin_lock(&redirect_lock); if (redirect && redirect->private_data == tty) { @@ -516,7 +513,10 @@ static void do_tty_hangup(struct work_struct *work) } spin_unlock(&redirect_lock); + /* inuse_filps is protected by the single kernel lock */ + lock_kernel(); check_tty_count(tty, "do_tty_hangup"); + file_list_lock(); /* This breaks for file handles being sent over AF_UNIX sockets ? */ list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) { @@ -708,6 +708,8 @@ void disassociate_ctty(int on_exit) struct tty_struct *tty; struct pid *tty_pgrp = NULL; + if (!current->signal->leader) + return; tty = get_current_tty(); if (tty) { @@ -773,8 +775,7 @@ void no_tty(void) { struct task_struct *tsk = current; lock_kernel(); - if (tsk->signal->leader) - disassociate_ctty(0); + disassociate_ctty(0); unlock_kernel(); proc_clear_tty(tsk); } @@ -1017,14 +1018,16 @@ out: void tty_write_message(struct tty_struct *tty, char *msg) { - lock_kernel(); if (tty) { mutex_lock(&tty->atomic_write_lock); - if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) + lock_kernel(); + if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { + unlock_kernel(); tty->ops->write(tty, msg, strlen(msg)); + } else + unlock_kernel(); tty_write_unlock(tty); } - unlock_kernel(); return; } @@ -1202,14 +1205,21 @@ static int tty_driver_install_tty(struct tty_driver *driver, struct tty_struct *tty) { int idx = tty->index; + int ret; - if (driver->ops->install) - return driver->ops->install(driver, tty); + if (driver->ops->install) { + lock_kernel(); + ret = driver->ops->install(driver, tty); + unlock_kernel(); + return ret; + } if (tty_init_termios(tty) == 0) { + lock_kernel(); tty_driver_kref_get(driver); tty->count++; driver->ttys[idx] = tty; + unlock_kernel(); return 0; } return -ENOMEM; @@ -1302,10 +1312,14 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, struct tty_struct *tty; int retval; + lock_kernel(); /* Check if pty master is being opened multiple times */ if (driver->subtype == PTY_TYPE_MASTER && - (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) + (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { + unlock_kernel(); return ERR_PTR(-EIO); + } + unlock_kernel(); /* * First time open is complex, especially for PTY devices. @@ -1335,7 +1349,6 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, * If we fail here just call release_tty to clean up. No need * to decrement the use counts, as release_tty doesn't care. */ - retval = tty_ldisc_setup(tty, tty->link); if (retval) goto release_mem_out; @@ -1350,7 +1363,9 @@ release_mem_out: if (printk_ratelimit()) printk(KERN_INFO "tty_init_dev: ldisc open failed, " "clearing slot %d\n", idx); + lock_kernel(); release_tty(tty, idx); + unlock_kernel(); return ERR_PTR(retval); } @@ -1464,7 +1479,17 @@ static void release_tty(struct tty_struct *tty, int idx) tty_kref_put(tty); } -/* +/** + * tty_release - vfs callback for close + * @inode: inode of tty + * @filp: file pointer for handle to tty + * + * Called the last time each file handle is closed that references + * this tty. There may however be several such references. + * + * Locking: + * Takes bkl. See tty_release_dev + * * Even releasing the tty structures is a tricky business.. We have * to be very careful that the structures are all released at the * same time, as interrupts might otherwise get the wrong pointers. @@ -1472,20 +1497,20 @@ static void release_tty(struct tty_struct *tty, int idx) * WSH 09/09/97: rewritten to avoid some nasty race conditions that could * lead to double frees or releasing memory still in use. */ -void tty_release_dev(struct file *filp) + +int tty_release(struct inode *inode, struct file *filp) { struct tty_struct *tty, *o_tty; int pty_master, tty_closing, o_tty_closing, do_sleep; int devpts; int idx; char buf[64]; - struct inode *inode; - inode = filp->f_path.dentry->d_inode; tty = (struct tty_struct *)filp->private_data; if (tty_paranoia_check(tty, inode, "tty_release_dev")) - return; + return 0; + lock_kernel(); check_tty_count(tty, "tty_release_dev"); tty_fasync(-1, filp, 0); @@ -1500,19 +1525,22 @@ void tty_release_dev(struct file *filp) if (idx < 0 || idx >= tty->driver->num) { printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " "free (%s)\n", tty->name); - return; + unlock_kernel(); + return 0; } if (!devpts) { if (tty != tty->driver->ttys[idx]) { + unlock_kernel(); printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " "for (%s)\n", idx, tty->name); - return; + return 0; } if (tty->termios != tty->driver->termios[idx]) { + unlock_kernel(); printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " "for (%s)\n", idx, tty->name); - return; + return 0; } } #endif @@ -1526,26 +1554,30 @@ void tty_release_dev(struct file *filp) if (tty->driver->other && !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { if (o_tty != tty->driver->other->ttys[idx]) { + unlock_kernel(); printk(KERN_DEBUG "tty_release_dev: other->table[%d] " "not o_tty for (%s)\n", idx, tty->name); - return; + return 0 ; } if (o_tty->termios != tty->driver->other->termios[idx]) { + unlock_kernel(); printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " "not o_termios for (%s)\n", idx, tty->name); - return; + return 0; } if (o_tty->link != tty) { + unlock_kernel(); printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); - return; + return 0; } } #endif if (tty->ops->close) tty->ops->close(tty, filp); + unlock_kernel(); /* * Sanity check: if tty->count is going to zero, there shouldn't be * any waiters on tty->read_wait or tty->write_wait. We test the @@ -1568,6 +1600,7 @@ void tty_release_dev(struct file *filp) opens on /dev/tty */ mutex_lock(&tty_mutex); + lock_kernel(); tty_closing = tty->count <= 1; o_tty_closing = o_tty && (o_tty->count <= (pty_master ? 1 : 0)); @@ -1598,6 +1631,7 @@ void tty_release_dev(struct file *filp) printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " "active!\n", tty_name(tty, buf)); + unlock_kernel(); mutex_unlock(&tty_mutex); schedule(); } @@ -1661,8 +1695,10 @@ void tty_release_dev(struct file *filp) mutex_unlock(&tty_mutex); /* check whether both sides are closing ... */ - if (!tty_closing || (o_tty && !o_tty_closing)) - return; + if (!tty_closing || (o_tty && !o_tty_closing)) { + unlock_kernel(); + return 0; + } #ifdef TTY_DEBUG_HANGUP printk(KERN_DEBUG "freeing tty structure..."); @@ -1680,10 +1716,12 @@ void tty_release_dev(struct file *filp) /* Make this pty number available for reallocation */ if (devpts) devpts_kill_index(inode, idx); + unlock_kernel(); + return 0; } /** - * __tty_open - open a tty device + * tty_open - open a tty device * @inode: inode of device file * @filp: file pointer to tty * @@ -1703,7 +1741,7 @@ void tty_release_dev(struct file *filp) * ->siglock protects ->signal/->sighand */ -static int __tty_open(struct inode *inode, struct file *filp) +static int tty_open(struct inode *inode, struct file *filp) { struct tty_struct *tty = NULL; int noctty, retval; @@ -1720,10 +1758,12 @@ retry_open: retval = 0; mutex_lock(&tty_mutex); + lock_kernel(); if (device == MKDEV(TTYAUX_MAJOR, 0)) { tty = get_current_tty(); if (!tty) { + unlock_kernel(); mutex_unlock(&tty_mutex); return -ENXIO; } @@ -1755,12 +1795,14 @@ retry_open: goto got_driver; } } + unlock_kernel(); mutex_unlock(&tty_mutex); return -ENODEV; } driver = get_tty_driver(device, &index); if (!driver) { + unlock_kernel(); mutex_unlock(&tty_mutex); return -ENODEV; } @@ -1770,6 +1812,7 @@ got_driver: tty = tty_driver_lookup_tty(driver, inode, index); if (IS_ERR(tty)) { + unlock_kernel(); mutex_unlock(&tty_mutex); return PTR_ERR(tty); } @@ -1784,8 +1827,10 @@ got_driver: mutex_unlock(&tty_mutex); tty_driver_kref_put(driver); - if (IS_ERR(tty)) + if (IS_ERR(tty)) { + unlock_kernel(); return PTR_ERR(tty); + } filp->private_data = tty; file_move(filp, &tty->tty_files); @@ -1813,11 +1858,15 @@ got_driver: printk(KERN_DEBUG "error %d in opening %s...", retval, tty->name); #endif - tty_release_dev(filp); - if (retval != -ERESTARTSYS) + tty_release(inode, filp); + if (retval != -ERESTARTSYS) { + unlock_kernel(); return retval; - if (signal_pending(current)) + } + if (signal_pending(current)) { + unlock_kernel(); return retval; + } schedule(); /* * Need to reset f_op in case a hangup happened. @@ -1826,8 +1875,11 @@ got_driver: filp->f_op = &tty_fops; goto retry_open; } + unlock_kernel(); + mutex_lock(&tty_mutex); + lock_kernel(); spin_lock_irq(¤t->sighand->siglock); if (!noctty && current->signal->leader && @@ -1835,44 +1887,13 @@ got_driver: tty->session == NULL) __proc_set_tty(current, tty); spin_unlock_irq(¤t->sighand->siglock); + unlock_kernel(); mutex_unlock(&tty_mutex); return 0; } -/* BKL pushdown: scary code avoidance wrapper */ -static int tty_open(struct inode *inode, struct file *filp) -{ - int ret; - - lock_kernel(); - ret = __tty_open(inode, filp); - unlock_kernel(); - return ret; -} - - -/** - * tty_release - vfs callback for close - * @inode: inode of tty - * @filp: file pointer for handle to tty - * - * Called the last time each file handle is closed that references - * this tty. There may however be several such references. - * - * Locking: - * Takes bkl. See tty_release_dev - */ - -static int tty_release(struct inode *inode, struct file *filp) -{ - lock_kernel(); - tty_release_dev(filp); - unlock_kernel(); - return 0; -} - /** * tty_poll - check tty status * @filp: file being polled @@ -2317,9 +2338,7 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) if (get_user(ldisc, p)) return -EFAULT; - lock_kernel(); ret = tty_set_ldisc(tty, ldisc); - unlock_kernel(); return ret; } diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index feb55075819bab4f7d9f75ce11f7aa7232ba9dc1..3f653f7d849f07f256fa4ae0e0d11376d0e07825 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c @@ -34,6 +34,8 @@ #include #include +#include /* For the moment */ + #include #include @@ -443,8 +445,14 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) { WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); - if (ld->ops->open) - return ld->ops->open(tty); + if (ld->ops->open) { + int ret; + /* BKL here locks verus a hangup event */ + lock_kernel(); + ret = ld->ops->open(tty); + unlock_kernel(); + return ret; + } return 0; } @@ -545,6 +553,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (IS_ERR(new_ldisc)) return PTR_ERR(new_ldisc); + lock_kernel(); /* * We need to look at the tty locking here for pty/tty pairs * when both sides try to change in parallel. @@ -558,10 +567,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) */ if (tty->ldisc->ops->num == ldisc) { + unlock_kernel(); tty_ldisc_put(new_ldisc); return 0; } + unlock_kernel(); /* * Problem: What do we do if this blocks ? * We could deadlock here @@ -582,6 +593,9 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); mutex_lock(&tty->ldisc_mutex); } + + lock_kernel(); + set_bit(TTY_LDISC_CHANGING, &tty->flags); /* @@ -592,6 +606,8 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) tty->receive_room = 0; o_ldisc = tty->ldisc; + + unlock_kernel(); /* * Make sure we don't change while someone holds a * reference to the line discipline. The TTY_LDISC bit @@ -617,12 +633,14 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) flush_scheduled_work(); mutex_lock(&tty->ldisc_mutex); + lock_kernel(); if (test_bit(TTY_HUPPED, &tty->flags)) { /* We were raced by the hangup method. It will have stomped the ldisc data and closed the ldisc down */ clear_bit(TTY_LDISC_CHANGING, &tty->flags); mutex_unlock(&tty->ldisc_mutex); tty_ldisc_put(new_ldisc); + unlock_kernel(); return -EIO; } @@ -664,6 +682,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (o_work) schedule_delayed_work(&o_tty->buf.work, 1); mutex_unlock(&tty->ldisc_mutex); + unlock_kernel(); return retval; } diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index c63f3d33914a7def6b4e49d2f3d33a25dbf8fc0c..be492dd664370a787b6da7a2b294b3bf53451de6 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c @@ -25,19 +25,21 @@ void tty_port_init(struct tty_port *port) init_waitqueue_head(&port->close_wait); init_waitqueue_head(&port->delta_msr_wait); mutex_init(&port->mutex); + mutex_init(&port->buf_mutex); spin_lock_init(&port->lock); port->close_delay = (50 * HZ) / 100; port->closing_wait = (3000 * HZ) / 100; + kref_init(&port->kref); } EXPORT_SYMBOL(tty_port_init); int tty_port_alloc_xmit_buf(struct tty_port *port) { /* We may sleep in get_zeroed_page() */ - mutex_lock(&port->mutex); + mutex_lock(&port->buf_mutex); if (port->xmit_buf == NULL) port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); - mutex_unlock(&port->mutex); + mutex_unlock(&port->buf_mutex); if (port->xmit_buf == NULL) return -ENOMEM; return 0; @@ -46,15 +48,32 @@ EXPORT_SYMBOL(tty_port_alloc_xmit_buf); void tty_port_free_xmit_buf(struct tty_port *port) { - mutex_lock(&port->mutex); + mutex_lock(&port->buf_mutex); if (port->xmit_buf != NULL) { free_page((unsigned long)port->xmit_buf); port->xmit_buf = NULL; } - mutex_unlock(&port->mutex); + mutex_unlock(&port->buf_mutex); } EXPORT_SYMBOL(tty_port_free_xmit_buf); +static void tty_port_destructor(struct kref *kref) +{ + struct tty_port *port = container_of(kref, struct tty_port, kref); + if (port->xmit_buf) + free_page((unsigned long)port->xmit_buf); + if (port->ops->destruct) + port->ops->destruct(port); + else + kfree(port); +} + +void tty_port_put(struct tty_port *port) +{ + if (port) + kref_put(&port->kref, tty_port_destructor); +} +EXPORT_SYMBOL(tty_port_put); /** * tty_port_tty_get - get a tty reference @@ -99,10 +118,11 @@ EXPORT_SYMBOL(tty_port_tty_set); static void tty_port_shutdown(struct tty_port *port) { + mutex_lock(&port->mutex); if (port->ops->shutdown && test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) port->ops->shutdown(port); - + mutex_unlock(&port->mutex); } /** @@ -120,8 +140,10 @@ void tty_port_hangup(struct tty_port *port) spin_lock_irqsave(&port->lock, flags); port->count = 0; port->flags &= ~ASYNC_NORMAL_ACTIVE; - if (port->tty) + if (port->tty) { + set_bit(TTY_IO_ERROR, &port->tty->flags); tty_kref_put(port->tty); + } port->tty = NULL; spin_unlock_irqrestore(&port->lock, flags); wake_up_interruptible(&port->open_wait); @@ -198,7 +220,7 @@ EXPORT_SYMBOL(tty_port_lower_dtr_rts); * management of these lines. Note that the dtr/rts raise is done each * iteration as a hangup may have previously dropped them while we wait. */ - + int tty_port_block_til_ready(struct tty_port *port, struct tty_struct *tty, struct file *filp) { @@ -253,7 +275,8 @@ int tty_port_block_til_ready(struct tty_port *port, tty_port_raise_dtr_rts(port); prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); - /* Check for a hangup or uninitialised port. Return accordingly */ + /* Check for a hangup or uninitialised port. + Return accordingly */ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { if (port->flags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; @@ -285,11 +308,11 @@ int tty_port_block_til_ready(struct tty_port *port, port->flags |= ASYNC_NORMAL_ACTIVE; spin_unlock_irqrestore(&port->lock, flags); return retval; - } EXPORT_SYMBOL(tty_port_block_til_ready); -int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp) +int tty_port_close_start(struct tty_port *port, + struct tty_struct *tty, struct file *filp) { unsigned long flags; @@ -299,7 +322,7 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f return 0; } - if( tty->count == 1 && port->count != 1) { + if (tty->count == 1 && port->count != 1) { printk(KERN_WARNING "tty_port_close_start: tty->count = 1 port count = %d.\n", port->count); @@ -331,12 +354,20 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f long timeout; if (bps > 1200) - timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps, - HZ / 10); + timeout = max_t(long, + (HZ * 10 * port->drain_delay) / bps, HZ / 10); else timeout = 2 * HZ; schedule_timeout_interruptible(timeout); } + /* Flush the ldisc buffering */ + tty_ldisc_flush(tty); + + /* Drop DTR/RTS if HUPCL is set. This causes any attached modem to + hang up the line */ + if (tty->termios->c_cflag & HUPCL) + tty_port_lower_dtr_rts(port); + /* Don't call port->drop for the last reference. Callers will want to drop the last active reference in ->shutdown() or the tty shutdown path */ @@ -348,11 +379,6 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) { unsigned long flags; - tty_ldisc_flush(tty); - - if (tty->termios->c_cflag & HUPCL) - tty_port_lower_dtr_rts(port); - spin_lock_irqsave(&port->lock, flags); tty->closing = 0; @@ -377,7 +403,42 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty, if (tty_port_close_start(port, tty, filp) == 0) return; tty_port_shutdown(port); + set_bit(TTY_IO_ERROR, &tty->flags); tty_port_close_end(port, tty); tty_port_tty_set(port, NULL); } EXPORT_SYMBOL(tty_port_close); + +int tty_port_open(struct tty_port *port, struct tty_struct *tty, + struct file *filp) +{ + spin_lock_irq(&port->lock); + if (!tty_hung_up_p(filp)) + ++port->count; + spin_unlock_irq(&port->lock); + tty_port_tty_set(port, tty); + + /* + * Do the device-specific open only if the hardware isn't + * already initialized. Serialize open and shutdown using the + * port mutex. + */ + + mutex_lock(&port->mutex); + + if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) { + clear_bit(TTY_IO_ERROR, &tty->flags); + if (port->ops->activate) { + int retval = port->ops->activate(port, tty); + if (retval) { + mutex_unlock(&port->mutex); + return retval; + } + } + set_bit(ASYNCB_INITIALIZED, &port->flags); + } + mutex_unlock(&port->mutex); + return tty_port_block_til_ready(port, tty, filp); +} + +EXPORT_SYMBOL(tty_port_open); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index ff57c40e9b8b94905ca090e79698390a66ad2583..67bc2ece7b4b508da7855937a01eb388cd33ab5b 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -64,14 +64,14 @@ static DEFINE_SPINLOCK(cpufreq_driver_lock); * - Lock should not be held across * __cpufreq_governor(data, CPUFREQ_GOV_STOP); */ -static DEFINE_PER_CPU(int, policy_cpu); +static DEFINE_PER_CPU(int, cpufreq_policy_cpu); static DEFINE_PER_CPU(struct rw_semaphore, cpu_policy_rwsem); #define lock_policy_rwsem(mode, cpu) \ int lock_policy_rwsem_##mode \ (int cpu) \ { \ - int policy_cpu = per_cpu(policy_cpu, cpu); \ + int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu); \ BUG_ON(policy_cpu == -1); \ down_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu)); \ if (unlikely(!cpu_online(cpu))) { \ @@ -90,7 +90,7 @@ EXPORT_SYMBOL_GPL(lock_policy_rwsem_write); void unlock_policy_rwsem_read(int cpu) { - int policy_cpu = per_cpu(policy_cpu, cpu); + int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu); BUG_ON(policy_cpu == -1); up_read(&per_cpu(cpu_policy_rwsem, policy_cpu)); } @@ -98,7 +98,7 @@ EXPORT_SYMBOL_GPL(unlock_policy_rwsem_read); void unlock_policy_rwsem_write(int cpu) { - int policy_cpu = per_cpu(policy_cpu, cpu); + int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu); BUG_ON(policy_cpu == -1); up_write(&per_cpu(cpu_policy_rwsem, policy_cpu)); } @@ -647,6 +647,21 @@ static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf) return policy->governor->show_setspeed(policy, buf); } +/** + * show_scaling_driver - show the current cpufreq HW/BIOS limitation + */ +static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) +{ + unsigned int limit; + int ret; + if (cpufreq_driver->bios_limit) { + ret = cpufreq_driver->bios_limit(policy->cpu, &limit); + if (!ret) + return sprintf(buf, "%u\n", limit); + } + return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); +} + #define define_one_ro(_name) \ static struct freq_attr _name = \ __ATTR(_name, 0444, show_##_name, NULL) @@ -666,6 +681,7 @@ define_one_ro(cpuinfo_transition_latency); define_one_ro(scaling_available_governors); define_one_ro(scaling_driver); define_one_ro(scaling_cur_freq); +define_one_ro(bios_limit); define_one_ro(related_cpus); define_one_ro(affected_cpus); define_one_rw(scaling_min_freq); @@ -767,8 +783,9 @@ static struct kobj_type ktype_cpufreq = { * 0: Success * Positive: When we have a managed CPU and the sysfs got symlinked */ -int cpufreq_add_dev_policy(unsigned int cpu, struct cpufreq_policy *policy, - struct sys_device *sys_dev) +static int cpufreq_add_dev_policy(unsigned int cpu, + struct cpufreq_policy *policy, + struct sys_device *sys_dev) { int ret = 0; #ifdef CONFIG_SMP @@ -801,7 +818,7 @@ int cpufreq_add_dev_policy(unsigned int cpu, struct cpufreq_policy *policy, /* Set proper policy_cpu */ unlock_policy_rwsem_write(cpu); - per_cpu(policy_cpu, cpu) = managed_policy->cpu; + per_cpu(cpufreq_policy_cpu, cpu) = managed_policy->cpu; if (lock_policy_rwsem_write(cpu) < 0) { /* Should not go through policy unlock path */ @@ -842,7 +859,8 @@ int cpufreq_add_dev_policy(unsigned int cpu, struct cpufreq_policy *policy, /* symlink affected CPUs */ -int cpufreq_add_dev_symlink(unsigned int cpu, struct cpufreq_policy *policy) +static int cpufreq_add_dev_symlink(unsigned int cpu, + struct cpufreq_policy *policy) { unsigned int j; int ret = 0; @@ -869,8 +887,9 @@ int cpufreq_add_dev_symlink(unsigned int cpu, struct cpufreq_policy *policy) return ret; } -int cpufreq_add_dev_interface(unsigned int cpu, struct cpufreq_policy *policy, - struct sys_device *sys_dev) +static int cpufreq_add_dev_interface(unsigned int cpu, + struct cpufreq_policy *policy, + struct sys_device *sys_dev) { struct cpufreq_policy new_policy; struct freq_attr **drv_attr; @@ -902,13 +921,18 @@ int cpufreq_add_dev_interface(unsigned int cpu, struct cpufreq_policy *policy, if (ret) goto err_out_kobj_put; } + if (cpufreq_driver->bios_limit) { + ret = sysfs_create_file(&policy->kobj, &bios_limit.attr); + if (ret) + goto err_out_kobj_put; + } spin_lock_irqsave(&cpufreq_driver_lock, flags); for_each_cpu(j, policy->cpus) { if (!cpu_online(j)) continue; per_cpu(cpufreq_cpu_data, j) = policy; - per_cpu(policy_cpu, j) = policy->cpu; + per_cpu(cpufreq_policy_cpu, j) = policy->cpu; } spin_unlock_irqrestore(&cpufreq_driver_lock, flags); @@ -996,7 +1020,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) cpumask_copy(policy->cpus, cpumask_of(cpu)); /* Initially set CPU itself as the policy_cpu */ - per_cpu(policy_cpu, cpu) = cpu; + per_cpu(cpufreq_policy_cpu, cpu) = cpu; ret = (lock_policy_rwsem_write(cpu) < 0); WARN_ON(ret); @@ -1978,7 +2002,7 @@ static int __init cpufreq_core_init(void) int cpu; for_each_possible_cpu(cpu) { - per_cpu(policy_cpu, cpu) = -1; + per_cpu(cpufreq_policy_cpu, cpu) = -1; init_rwsem(&per_cpu(cpu_policy_rwsem, cpu)); } diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index c7b081b839ffe1fb37df117fb2f0395467383ec4..599a40b25cb06e26e14734e4af00efde52b57822 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -164,20 +164,22 @@ static struct notifier_block dbs_cpufreq_notifier_block = { }; /************************** sysfs interface ************************/ -static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) +static ssize_t show_sampling_rate_max(struct kobject *kobj, + struct attribute *attr, char *buf) { printk_once(KERN_INFO "CPUFREQ: conservative sampling_rate_max " "sysfs file is deprecated - used by: %s\n", current->comm); return sprintf(buf, "%u\n", -1U); } -static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf) +static ssize_t show_sampling_rate_min(struct kobject *kobj, + struct attribute *attr, char *buf) { return sprintf(buf, "%u\n", min_sampling_rate); } #define define_one_ro(_name) \ -static struct freq_attr _name = \ +static struct global_attr _name = \ __ATTR(_name, 0444, show_##_name, NULL) define_one_ro(sampling_rate_max); @@ -186,7 +188,7 @@ define_one_ro(sampling_rate_min); /* cpufreq_conservative Governor Tunables */ #define show_one(file_name, object) \ static ssize_t show_##file_name \ -(struct cpufreq_policy *unused, char *buf) \ +(struct kobject *kobj, struct attribute *attr, char *buf) \ { \ return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ } @@ -197,8 +199,40 @@ show_one(down_threshold, down_threshold); show_one(ignore_nice_load, ignore_nice); show_one(freq_step, freq_step); -static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, - const char *buf, size_t count) +/*** delete after deprecation time ***/ +#define DEPRECATION_MSG(file_name) \ + printk_once(KERN_INFO "CPUFREQ: Per core conservative sysfs " \ + "interface is deprecated - " #file_name "\n"); + +#define show_one_old(file_name) \ +static ssize_t show_##file_name##_old \ +(struct cpufreq_policy *unused, char *buf) \ +{ \ + printk_once(KERN_INFO "CPUFREQ: Per core conservative sysfs " \ + "interface is deprecated - " #file_name "\n"); \ + return show_##file_name(NULL, NULL, buf); \ +} +show_one_old(sampling_rate); +show_one_old(sampling_down_factor); +show_one_old(up_threshold); +show_one_old(down_threshold); +show_one_old(ignore_nice_load); +show_one_old(freq_step); +show_one_old(sampling_rate_min); +show_one_old(sampling_rate_max); + +#define define_one_ro_old(object, _name) \ +static struct freq_attr object = \ +__ATTR(_name, 0444, show_##_name##_old, NULL) + +define_one_ro_old(sampling_rate_min_old, sampling_rate_min); +define_one_ro_old(sampling_rate_max_old, sampling_rate_max); + +/*** delete after deprecation time ***/ + +static ssize_t store_sampling_down_factor(struct kobject *a, + struct attribute *b, + const char *buf, size_t count) { unsigned int input; int ret; @@ -214,8 +248,8 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, return count; } -static ssize_t store_sampling_rate(struct cpufreq_policy *unused, - const char *buf, size_t count) +static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { unsigned int input; int ret; @@ -231,8 +265,8 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused, return count; } -static ssize_t store_up_threshold(struct cpufreq_policy *unused, - const char *buf, size_t count) +static ssize_t store_up_threshold(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { unsigned int input; int ret; @@ -251,8 +285,8 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, return count; } -static ssize_t store_down_threshold(struct cpufreq_policy *unused, - const char *buf, size_t count) +static ssize_t store_down_threshold(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { unsigned int input; int ret; @@ -272,8 +306,8 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused, return count; } -static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, - const char *buf, size_t count) +static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { unsigned int input; int ret; @@ -308,8 +342,8 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, return count; } -static ssize_t store_freq_step(struct cpufreq_policy *policy, - const char *buf, size_t count) +static ssize_t store_freq_step(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { unsigned int input; int ret; @@ -331,7 +365,7 @@ static ssize_t store_freq_step(struct cpufreq_policy *policy, } #define define_one_rw(_name) \ -static struct freq_attr _name = \ +static struct global_attr _name = \ __ATTR(_name, 0644, show_##_name, store_##_name) define_one_rw(sampling_rate); @@ -358,6 +392,53 @@ static struct attribute_group dbs_attr_group = { .name = "conservative", }; +/*** delete after deprecation time ***/ + +#define write_one_old(file_name) \ +static ssize_t store_##file_name##_old \ +(struct cpufreq_policy *unused, const char *buf, size_t count) \ +{ \ + printk_once(KERN_INFO "CPUFREQ: Per core conservative sysfs " \ + "interface is deprecated - " #file_name "\n"); \ + return store_##file_name(NULL, NULL, buf, count); \ +} +write_one_old(sampling_rate); +write_one_old(sampling_down_factor); +write_one_old(up_threshold); +write_one_old(down_threshold); +write_one_old(ignore_nice_load); +write_one_old(freq_step); + +#define define_one_rw_old(object, _name) \ +static struct freq_attr object = \ +__ATTR(_name, 0644, show_##_name##_old, store_##_name##_old) + +define_one_rw_old(sampling_rate_old, sampling_rate); +define_one_rw_old(sampling_down_factor_old, sampling_down_factor); +define_one_rw_old(up_threshold_old, up_threshold); +define_one_rw_old(down_threshold_old, down_threshold); +define_one_rw_old(ignore_nice_load_old, ignore_nice_load); +define_one_rw_old(freq_step_old, freq_step); + +static struct attribute *dbs_attributes_old[] = { + &sampling_rate_max_old.attr, + &sampling_rate_min_old.attr, + &sampling_rate_old.attr, + &sampling_down_factor_old.attr, + &up_threshold_old.attr, + &down_threshold_old.attr, + &ignore_nice_load_old.attr, + &freq_step_old.attr, + NULL +}; + +static struct attribute_group dbs_attr_group_old = { + .attrs = dbs_attributes_old, + .name = "conservative", +}; + +/*** delete after deprecation time ***/ + /************************** sysfs end ************************/ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) @@ -530,7 +611,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, mutex_lock(&dbs_mutex); - rc = sysfs_create_group(&policy->kobj, &dbs_attr_group); + rc = sysfs_create_group(&policy->kobj, &dbs_attr_group_old); if (rc) { mutex_unlock(&dbs_mutex); return rc; @@ -564,6 +645,13 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if (latency == 0) latency = 1; + rc = sysfs_create_group(cpufreq_global_kobject, + &dbs_attr_group); + if (rc) { + mutex_unlock(&dbs_mutex); + return rc; + } + /* * conservative does not implement micro like ondemand * governor, thus we are bound to jiffes/HZ @@ -591,7 +679,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, dbs_timer_exit(this_dbs_info); mutex_lock(&dbs_mutex); - sysfs_remove_group(&policy->kobj, &dbs_attr_group); + sysfs_remove_group(&policy->kobj, &dbs_attr_group_old); dbs_enable--; mutex_destroy(&this_dbs_info->timer_mutex); @@ -605,6 +693,9 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, CPUFREQ_TRANSITION_NOTIFIER); mutex_unlock(&dbs_mutex); + if (!dbs_enable) + sysfs_remove_group(cpufreq_global_kobject, + &dbs_attr_group); break; diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index a9bd3a05a684548cc7f36aa34fe8a1057d2bfbb3..05432216e2246ac4d4c78a665e3e63ec67370015 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -174,7 +174,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, } EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); -static DEFINE_PER_CPU(struct cpufreq_frequency_table *, show_table); +static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table); /** * show_available_freqs - show available frequencies for the specified CPU */ @@ -185,10 +185,10 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf) ssize_t count = 0; struct cpufreq_frequency_table *table; - if (!per_cpu(show_table, cpu)) + if (!per_cpu(cpufreq_show_table, cpu)) return -ENODEV; - table = per_cpu(show_table, cpu); + table = per_cpu(cpufreq_show_table, cpu); for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { if (table[i].frequency == CPUFREQ_ENTRY_INVALID) @@ -217,20 +217,20 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, unsigned int cpu) { dprintk("setting show_table for cpu %u to %p\n", cpu, table); - per_cpu(show_table, cpu) = table; + per_cpu(cpufreq_show_table, cpu) = table; } EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr); void cpufreq_frequency_table_put_attr(unsigned int cpu) { dprintk("clearing show_table for cpu %u\n", cpu); - per_cpu(show_table, cpu) = NULL; + per_cpu(cpufreq_show_table, cpu) = NULL; } EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr); struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu) { - return per_cpu(show_table, cpu); + return per_cpu(cpufreq_show_table, cpu); } EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table); diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 84c51e17726966c196ac53ce05671e972f65b98a..8c2f3703ec855f27a6863cb964c5d58a9d01dfa2 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -64,7 +64,7 @@ struct aes_ctx { u32 *D; }; -static DEFINE_PER_CPU(struct cword *, last_cword); +static DEFINE_PER_CPU(struct cword *, paes_last_cword); /* Tells whether the ACE is capable to generate the extended key for a given key_len. */ @@ -152,9 +152,9 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, ok: for_each_online_cpu(cpu) - if (&ctx->cword.encrypt == per_cpu(last_cword, cpu) || - &ctx->cword.decrypt == per_cpu(last_cword, cpu)) - per_cpu(last_cword, cpu) = NULL; + if (&ctx->cword.encrypt == per_cpu(paes_last_cword, cpu) || + &ctx->cword.decrypt == per_cpu(paes_last_cword, cpu)) + per_cpu(paes_last_cword, cpu) = NULL; return 0; } @@ -166,7 +166,7 @@ static inline void padlock_reset_key(struct cword *cword) { int cpu = raw_smp_processor_id(); - if (cword != per_cpu(last_cword, cpu)) + if (cword != per_cpu(paes_last_cword, cpu)) #ifndef CONFIG_X86_64 asm volatile ("pushfl; popfl"); #else @@ -176,7 +176,7 @@ static inline void padlock_reset_key(struct cword *cword) static inline void padlock_store_cword(struct cword *cword) { - per_cpu(last_cword, raw_smp_processor_id()) = cword; + per_cpu(paes_last_cword, raw_smp_processor_id()) = cword; } /* diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 8f99354082ceaa169f7ac081594bc83b0c003478..6f51a0a7a8bbdbca798f53293516e178ead5f4d2 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -326,14 +326,7 @@ arch_initcall(dma_channel_table_init); */ struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type) { - struct dma_chan *chan; - int cpu; - - cpu = get_cpu(); - chan = per_cpu_ptr(channel_table[tx_type], cpu)->chan; - put_cpu(); - - return chan; + return this_cpu_read(channel_table[tx_type]->chan); } EXPORT_SYMBOL(dma_find_channel); @@ -857,7 +850,6 @@ dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest, struct dma_async_tx_descriptor *tx; dma_addr_t dma_dest, dma_src; dma_cookie_t cookie; - int cpu; unsigned long flags; dma_src = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE); @@ -876,10 +868,10 @@ dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest, tx->callback = NULL; cookie = tx->tx_submit(tx); - cpu = get_cpu(); - per_cpu_ptr(chan->local, cpu)->bytes_transferred += len; - per_cpu_ptr(chan->local, cpu)->memcpy_count++; - put_cpu(); + preempt_disable(); + __this_cpu_add(chan->local->bytes_transferred, len); + __this_cpu_inc(chan->local->memcpy_count); + preempt_enable(); return cookie; } @@ -906,7 +898,6 @@ dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page, struct dma_async_tx_descriptor *tx; dma_addr_t dma_dest, dma_src; dma_cookie_t cookie; - int cpu; unsigned long flags; dma_src = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE); @@ -923,10 +914,10 @@ dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page, tx->callback = NULL; cookie = tx->tx_submit(tx); - cpu = get_cpu(); - per_cpu_ptr(chan->local, cpu)->bytes_transferred += len; - per_cpu_ptr(chan->local, cpu)->memcpy_count++; - put_cpu(); + preempt_disable(); + __this_cpu_add(chan->local->bytes_transferred, len); + __this_cpu_inc(chan->local->memcpy_count); + preempt_enable(); return cookie; } @@ -955,7 +946,6 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg, struct dma_async_tx_descriptor *tx; dma_addr_t dma_dest, dma_src; dma_cookie_t cookie; - int cpu; unsigned long flags; dma_src = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE); @@ -973,10 +963,10 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg, tx->callback = NULL; cookie = tx->tx_submit(tx); - cpu = get_cpu(); - per_cpu_ptr(chan->local, cpu)->bytes_transferred += len; - per_cpu_ptr(chan->local, cpu)->memcpy_count++; - put_cpu(); + preempt_disable(); + __this_cpu_add(chan->local->bytes_transferred, len); + __this_cpu_inc(chan->local->memcpy_count); + preempt_enable(); return cookie; } diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index a38831c8264995ab506428ccda6124a732dc636a..df5b68433f3464ab4a03f4ee5453864946364275 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -13,32 +13,56 @@ module_param(report_gart_errors, int, 0644); static int ecc_enable_override; module_param(ecc_enable_override, int, 0644); +static struct msr *msrs; + /* Lookup table for all possible MC control instances */ struct amd64_pvt; static struct mem_ctl_info *mci_lookup[EDAC_MAX_NUMNODES]; static struct amd64_pvt *pvt_lookup[EDAC_MAX_NUMNODES]; /* - * See F2x80 for K8 and F2x[1,0]80 for Fam10 and later. The table below is only - * for DDR2 DRAM mapping. + * Address to DRAM bank mapping: see F2x80 for K8 and F2x[1,0]80 for Fam10 and + * later. */ -u32 revf_quad_ddr2_shift[] = { - 0, /* 0000b NULL DIMM (128mb) */ - 28, /* 0001b 256mb */ - 29, /* 0010b 512mb */ - 29, /* 0011b 512mb */ - 29, /* 0100b 512mb */ - 30, /* 0101b 1gb */ - 30, /* 0110b 1gb */ - 31, /* 0111b 2gb */ - 31, /* 1000b 2gb */ - 32, /* 1001b 4gb */ - 32, /* 1010b 4gb */ - 33, /* 1011b 8gb */ - 0, /* 1100b future */ - 0, /* 1101b future */ - 0, /* 1110b future */ - 0 /* 1111b future */ +static int ddr2_dbam_revCG[] = { + [0] = 32, + [1] = 64, + [2] = 128, + [3] = 256, + [4] = 512, + [5] = 1024, + [6] = 2048, +}; + +static int ddr2_dbam_revD[] = { + [0] = 32, + [1] = 64, + [2 ... 3] = 128, + [4] = 256, + [5] = 512, + [6] = 256, + [7] = 512, + [8 ... 9] = 1024, + [10] = 2048, +}; + +static int ddr2_dbam[] = { [0] = 128, + [1] = 256, + [2 ... 4] = 512, + [5 ... 6] = 1024, + [7 ... 8] = 2048, + [9 ... 10] = 4096, + [11] = 8192, +}; + +static int ddr3_dbam[] = { [0] = -1, + [1] = 256, + [2] = 512, + [3 ... 4] = -1, + [5 ... 6] = 1024, + [7 ... 8] = 2048, + [9 ... 10] = 4096, + [11] = 8192, }; /* @@ -164,11 +188,9 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw) { struct amd64_pvt *pvt = mci->pvt_info; u32 scrubval = 0; - int status = -1, i, ret = 0; + int status = -1, i; - ret = pci_read_config_dword(pvt->misc_f3_ctl, K8_SCRCTRL, &scrubval); - if (ret) - debugf0("Reading K8_SCRCTRL failed\n"); + amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_SCRCTRL, &scrubval); scrubval = scrubval & 0x001F; @@ -189,7 +211,7 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw) /* Map from a CSROW entry to the mask entry that operates on it */ static inline u32 amd64_map_to_dcs_mask(struct amd64_pvt *pvt, int csrow) { - if (boot_cpu_data.x86 == 0xf && pvt->ext_model < OPTERON_CPU_REV_F) + if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_F) return csrow; else return csrow >> 1; @@ -437,7 +459,7 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, u64 base; /* only revE and later have the DRAM Hole Address Register */ - if (boot_cpu_data.x86 == 0xf && pvt->ext_model < OPTERON_CPU_REV_E) { + if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_E) { debugf1(" revision %d for node %d does not support DHAR\n", pvt->ext_model, pvt->mc_node_id); return 1; @@ -743,21 +765,6 @@ static void find_csrow_limits(struct mem_ctl_info *mci, int csrow, *input_addr_max = base | mask | pvt->dcs_mask_notused; } -/* - * Extract error address from MCA NB Address Low (section 3.6.4.5) and MCA NB - * Address High (section 3.6.4.6) register values and return the result. Address - * is located in the info structure (nbeah and nbeal), the encoding is device - * specific. - */ -static u64 extract_error_address(struct mem_ctl_info *mci, - struct err_regs *info) -{ - struct amd64_pvt *pvt = mci->pvt_info; - - return pvt->ops->get_error_address(mci, info); -} - - /* Map the Error address to a PAGE and PAGE OFFSET. */ static inline void error_address_to_page_and_offset(u64 error_address, u32 *page, u32 *offset) @@ -787,7 +794,7 @@ static int sys_addr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr) return csrow; } -static int get_channel_from_ecc_syndrome(unsigned short syndrome); +static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16); static void amd64_cpu_display_info(struct amd64_pvt *pvt) { @@ -797,7 +804,7 @@ static void amd64_cpu_display_info(struct amd64_pvt *pvt) edac_printk(KERN_DEBUG, EDAC_MC, "F10h CPU detected\n"); else if (boot_cpu_data.x86 == 0xf) edac_printk(KERN_DEBUG, EDAC_MC, "%s detected\n", - (pvt->ext_model >= OPTERON_CPU_REV_F) ? + (pvt->ext_model >= K8_REV_F) ? "Rev F or later" : "Rev E or earlier"); else /* we'll hardly ever ever get here */ @@ -813,7 +820,7 @@ static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt) int bit; enum dev_type edac_cap = EDAC_FLAG_NONE; - bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= OPTERON_CPU_REV_F) + bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= K8_REV_F) ? 19 : 17; @@ -824,111 +831,86 @@ static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt) } -static void f10_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt, - int ganged); +static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt); + +static void amd64_dump_dramcfg_low(u32 dclr, int chan) +{ + debugf1("F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr); + + debugf1(" DIMM type: %sbuffered; all DIMMs support ECC: %s\n", + (dclr & BIT(16)) ? "un" : "", + (dclr & BIT(19)) ? "yes" : "no"); + + debugf1(" PAR/ERR parity: %s\n", + (dclr & BIT(8)) ? "enabled" : "disabled"); + + debugf1(" DCT 128bit mode width: %s\n", + (dclr & BIT(11)) ? "128b" : "64b"); + + debugf1(" x4 logical DIMMs present: L0: %s L1: %s L2: %s L3: %s\n", + (dclr & BIT(12)) ? "yes" : "no", + (dclr & BIT(13)) ? "yes" : "no", + (dclr & BIT(14)) ? "yes" : "no", + (dclr & BIT(15)) ? "yes" : "no"); +} /* Display and decode various NB registers for debug purposes. */ static void amd64_dump_misc_regs(struct amd64_pvt *pvt) { int ganged; - debugf1(" nbcap:0x%8.08x DctDualCap=%s DualNode=%s 8-Node=%s\n", - pvt->nbcap, - (pvt->nbcap & K8_NBCAP_DCT_DUAL) ? "True" : "False", - (pvt->nbcap & K8_NBCAP_DUAL_NODE) ? "True" : "False", - (pvt->nbcap & K8_NBCAP_8_NODE) ? "True" : "False"); - debugf1(" ECC Capable=%s ChipKill Capable=%s\n", - (pvt->nbcap & K8_NBCAP_SECDED) ? "True" : "False", - (pvt->nbcap & K8_NBCAP_CHIPKILL) ? "True" : "False"); - debugf1(" DramCfg0-low=0x%08x DIMM-ECC=%s Parity=%s Width=%s\n", - pvt->dclr0, - (pvt->dclr0 & BIT(19)) ? "Enabled" : "Disabled", - (pvt->dclr0 & BIT(8)) ? "Enabled" : "Disabled", - (pvt->dclr0 & BIT(11)) ? "128b" : "64b"); - debugf1(" DIMM x4 Present: L0=%s L1=%s L2=%s L3=%s DIMM Type=%s\n", - (pvt->dclr0 & BIT(12)) ? "Y" : "N", - (pvt->dclr0 & BIT(13)) ? "Y" : "N", - (pvt->dclr0 & BIT(14)) ? "Y" : "N", - (pvt->dclr0 & BIT(15)) ? "Y" : "N", - (pvt->dclr0 & BIT(16)) ? "UN-Buffered" : "Buffered"); - - - debugf1(" online-spare: 0x%8.08x\n", pvt->online_spare); + debugf1("F3xE8 (NB Cap): 0x%08x\n", pvt->nbcap); - if (boot_cpu_data.x86 == 0xf) { - debugf1(" dhar: 0x%8.08x Base=0x%08x Offset=0x%08x\n", - pvt->dhar, dhar_base(pvt->dhar), - k8_dhar_offset(pvt->dhar)); - debugf1(" DramHoleValid=%s\n", - (pvt->dhar & DHAR_VALID) ? "True" : "False"); + debugf1(" NB two channel DRAM capable: %s\n", + (pvt->nbcap & K8_NBCAP_DCT_DUAL) ? "yes" : "no"); - debugf1(" dbam-dkt: 0x%8.08x\n", pvt->dbam0); + debugf1(" ECC capable: %s, ChipKill ECC capable: %s\n", + (pvt->nbcap & K8_NBCAP_SECDED) ? "yes" : "no", + (pvt->nbcap & K8_NBCAP_CHIPKILL) ? "yes" : "no"); - /* everything below this point is Fam10h and above */ - return; + amd64_dump_dramcfg_low(pvt->dclr0, 0); - } else { - debugf1(" dhar: 0x%8.08x Base=0x%08x Offset=0x%08x\n", - pvt->dhar, dhar_base(pvt->dhar), - f10_dhar_offset(pvt->dhar)); - debugf1(" DramMemHoistValid=%s DramHoleValid=%s\n", - (pvt->dhar & F10_DRAM_MEM_HOIST_VALID) ? - "True" : "False", - (pvt->dhar & DHAR_VALID) ? - "True" : "False"); - } + debugf1("F3xB0 (Online Spare): 0x%08x\n", pvt->online_spare); - /* Only if NOT ganged does dcl1 have valid info */ - if (!dct_ganging_enabled(pvt)) { - debugf1(" DramCfg1-low=0x%08x DIMM-ECC=%s Parity=%s " - "Width=%s\n", pvt->dclr1, - (pvt->dclr1 & BIT(19)) ? "Enabled" : "Disabled", - (pvt->dclr1 & BIT(8)) ? "Enabled" : "Disabled", - (pvt->dclr1 & BIT(11)) ? "128b" : "64b"); - debugf1(" DIMM x4 Present: L0=%s L1=%s L2=%s L3=%s " - "DIMM Type=%s\n", - (pvt->dclr1 & BIT(12)) ? "Y" : "N", - (pvt->dclr1 & BIT(13)) ? "Y" : "N", - (pvt->dclr1 & BIT(14)) ? "Y" : "N", - (pvt->dclr1 & BIT(15)) ? "Y" : "N", - (pvt->dclr1 & BIT(16)) ? "UN-Buffered" : "Buffered"); + debugf1("F1xF0 (DRAM Hole Address): 0x%08x, base: 0x%08x, " + "offset: 0x%08x\n", + pvt->dhar, + dhar_base(pvt->dhar), + (boot_cpu_data.x86 == 0xf) ? k8_dhar_offset(pvt->dhar) + : f10_dhar_offset(pvt->dhar)); + + debugf1(" DramHoleValid: %s\n", + (pvt->dhar & DHAR_VALID) ? "yes" : "no"); + + /* everything below this point is Fam10h and above */ + if (boot_cpu_data.x86 == 0xf) { + amd64_debug_display_dimm_sizes(0, pvt); + return; } + /* Only if NOT ganged does dclr1 have valid info */ + if (!dct_ganging_enabled(pvt)) + amd64_dump_dramcfg_low(pvt->dclr1, 1); + /* * Determine if ganged and then dump memory sizes for first controller, * and if NOT ganged dump info for 2nd controller. */ ganged = dct_ganging_enabled(pvt); - f10_debug_display_dimm_sizes(0, pvt, ganged); + amd64_debug_display_dimm_sizes(0, pvt); if (!ganged) - f10_debug_display_dimm_sizes(1, pvt, ganged); + amd64_debug_display_dimm_sizes(1, pvt); } /* Read in both of DBAM registers */ static void amd64_read_dbam_reg(struct amd64_pvt *pvt) { - int err = 0; - unsigned int reg; - - reg = DBAM0; - err = pci_read_config_dword(pvt->dram_f2_ctl, reg, &pvt->dbam0); - if (err) - goto err_reg; - - if (boot_cpu_data.x86 >= 0x10) { - reg = DBAM1; - err = pci_read_config_dword(pvt->dram_f2_ctl, reg, &pvt->dbam1); - - if (err) - goto err_reg; - } - - return; + amd64_read_pci_cfg(pvt->dram_f2_ctl, DBAM0, &pvt->dbam0); -err_reg: - debugf0("Error reading F2x%03x.\n", reg); + if (boot_cpu_data.x86 >= 0x10) + amd64_read_pci_cfg(pvt->dram_f2_ctl, DBAM1, &pvt->dbam1); } /* @@ -963,7 +945,7 @@ err_reg: static void amd64_set_dct_base_and_mask(struct amd64_pvt *pvt) { - if (boot_cpu_data.x86 == 0xf && pvt->ext_model < OPTERON_CPU_REV_F) { + if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_F) { pvt->dcsb_base = REV_E_DCSB_BASE_BITS; pvt->dcsm_mask = REV_E_DCSM_MASK_BITS; pvt->dcs_mask_notused = REV_E_DCS_NOTUSED_BITS; @@ -991,28 +973,21 @@ static void amd64_set_dct_base_and_mask(struct amd64_pvt *pvt) */ static void amd64_read_dct_base_mask(struct amd64_pvt *pvt) { - int cs, reg, err = 0; + int cs, reg; amd64_set_dct_base_and_mask(pvt); for (cs = 0; cs < pvt->cs_count; cs++) { reg = K8_DCSB0 + (cs * 4); - err = pci_read_config_dword(pvt->dram_f2_ctl, reg, - &pvt->dcsb0[cs]); - if (unlikely(err)) - debugf0("Reading K8_DCSB0[%d] failed\n", cs); - else + if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg, &pvt->dcsb0[cs])) debugf0(" DCSB0[%d]=0x%08x reg: F2x%x\n", cs, pvt->dcsb0[cs], reg); /* If DCT are NOT ganged, then read in DCT1's base */ if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) { reg = F10_DCSB1 + (cs * 4); - err = pci_read_config_dword(pvt->dram_f2_ctl, reg, - &pvt->dcsb1[cs]); - if (unlikely(err)) - debugf0("Reading F10_DCSB1[%d] failed\n", cs); - else + if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg, + &pvt->dcsb1[cs])) debugf0(" DCSB1[%d]=0x%08x reg: F2x%x\n", cs, pvt->dcsb1[cs], reg); } else { @@ -1022,26 +997,20 @@ static void amd64_read_dct_base_mask(struct amd64_pvt *pvt) for (cs = 0; cs < pvt->num_dcsm; cs++) { reg = K8_DCSM0 + (cs * 4); - err = pci_read_config_dword(pvt->dram_f2_ctl, reg, - &pvt->dcsm0[cs]); - if (unlikely(err)) - debugf0("Reading K8_DCSM0 failed\n"); - else + if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg, &pvt->dcsm0[cs])) debugf0(" DCSM0[%d]=0x%08x reg: F2x%x\n", cs, pvt->dcsm0[cs], reg); /* If DCT are NOT ganged, then read in DCT1's mask */ if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) { reg = F10_DCSM1 + (cs * 4); - err = pci_read_config_dword(pvt->dram_f2_ctl, reg, - &pvt->dcsm1[cs]); - if (unlikely(err)) - debugf0("Reading F10_DCSM1[%d] failed\n", cs); - else + if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg, + &pvt->dcsm1[cs])) debugf0(" DCSM1[%d]=0x%08x reg: F2x%x\n", cs, pvt->dcsm1[cs], reg); - } else + } else { pvt->dcsm1[cs] = 0; + } } } @@ -1049,18 +1018,16 @@ static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt) { enum mem_type type; - if (boot_cpu_data.x86 >= 0x10 || pvt->ext_model >= OPTERON_CPU_REV_F) { - /* Rev F and later */ - type = (pvt->dclr0 & BIT(16)) ? MEM_DDR2 : MEM_RDDR2; + if (boot_cpu_data.x86 >= 0x10 || pvt->ext_model >= K8_REV_F) { + if (pvt->dchr0 & DDR3_MODE) + type = (pvt->dclr0 & BIT(16)) ? MEM_DDR3 : MEM_RDDR3; + else + type = (pvt->dclr0 & BIT(16)) ? MEM_DDR2 : MEM_RDDR2; } else { - /* Rev E and earlier */ type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR; } - debugf1(" Memory type is: %s\n", - (type == MEM_DDR2) ? "MEM_DDR2" : - (type == MEM_RDDR2) ? "MEM_RDDR2" : - (type == MEM_DDR) ? "MEM_DDR" : "MEM_RDDR"); + debugf1(" Memory type is: %s\n", edac_mem_types[type]); return type; } @@ -1078,11 +1045,11 @@ static int k8_early_channel_count(struct amd64_pvt *pvt) { int flag, err = 0; - err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); + err = amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); if (err) return err; - if ((boot_cpu_data.x86_model >> 4) >= OPTERON_CPU_REV_F) { + if ((boot_cpu_data.x86_model >> 4) >= K8_REV_F) { /* RevF (NPT) and later */ flag = pvt->dclr0 & F10_WIDTH_128; } else { @@ -1114,22 +1081,15 @@ static void k8_read_dram_base_limit(struct amd64_pvt *pvt, int dram) { u32 low; u32 off = dram << 3; /* 8 bytes between DRAM entries */ - int err; - err = pci_read_config_dword(pvt->addr_f1_ctl, - K8_DRAM_BASE_LOW + off, &low); - if (err) - debugf0("Reading K8_DRAM_BASE_LOW failed\n"); + amd64_read_pci_cfg(pvt->addr_f1_ctl, K8_DRAM_BASE_LOW + off, &low); /* Extract parts into separate data entries */ pvt->dram_base[dram] = ((u64) low & 0xFFFF0000) << 8; pvt->dram_IntlvEn[dram] = (low >> 8) & 0x7; pvt->dram_rw_en[dram] = (low & 0x3); - err = pci_read_config_dword(pvt->addr_f1_ctl, - K8_DRAM_LIMIT_LOW + off, &low); - if (err) - debugf0("Reading K8_DRAM_LIMIT_LOW failed\n"); + amd64_read_pci_cfg(pvt->addr_f1_ctl, K8_DRAM_LIMIT_LOW + off, &low); /* * Extract parts into separate data entries. Limit is the HIGHEST memory @@ -1142,7 +1102,7 @@ static void k8_read_dram_base_limit(struct amd64_pvt *pvt, int dram) static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, struct err_regs *info, - u64 SystemAddress) + u64 sys_addr) { struct mem_ctl_info *src_mci; unsigned short syndrome; @@ -1155,7 +1115,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, /* CHIPKILL enabled */ if (info->nbcfg & K8_NBCFG_CHIPKILL) { - channel = get_channel_from_ecc_syndrome(syndrome); + channel = get_channel_from_ecc_syndrome(mci, syndrome); if (channel < 0) { /* * Syndrome didn't map, so we don't know which of the @@ -1177,64 +1137,46 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, * was obtained from email communication with someone at AMD. * (Wish the email was placed in this comment - norsk) */ - channel = ((SystemAddress & BIT(3)) != 0); + channel = ((sys_addr & BIT(3)) != 0); } /* * Find out which node the error address belongs to. This may be * different from the node that detected the error. */ - src_mci = find_mc_by_sys_addr(mci, SystemAddress); + src_mci = find_mc_by_sys_addr(mci, sys_addr); if (!src_mci) { amd64_mc_printk(mci, KERN_ERR, "failed to map error address 0x%lx to a node\n", - (unsigned long)SystemAddress); + (unsigned long)sys_addr); edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); return; } - /* Now map the SystemAddress to a CSROW */ - csrow = sys_addr_to_csrow(src_mci, SystemAddress); + /* Now map the sys_addr to a CSROW */ + csrow = sys_addr_to_csrow(src_mci, sys_addr); if (csrow < 0) { edac_mc_handle_ce_no_info(src_mci, EDAC_MOD_STR); } else { - error_address_to_page_and_offset(SystemAddress, &page, &offset); + error_address_to_page_and_offset(sys_addr, &page, &offset); edac_mc_handle_ce(src_mci, page, offset, syndrome, csrow, channel, EDAC_MOD_STR); } } -/* - * determrine the number of PAGES in for this DIMM's size based on its DRAM - * Address Mapping. - * - * First step is to calc the number of bits to shift a value of 1 left to - * indicate show many pages. Start with the DBAM value as the starting bits, - * then proceed to adjust those shift bits, based on CPU rev and the table. - * See BKDG on the DBAM - */ -static int k8_dbam_map_to_pages(struct amd64_pvt *pvt, int dram_map) +static int k8_dbam_to_chip_select(struct amd64_pvt *pvt, int cs_mode) { - int nr_pages; + int *dbam_map; - if (pvt->ext_model >= OPTERON_CPU_REV_F) { - nr_pages = 1 << (revf_quad_ddr2_shift[dram_map] - PAGE_SHIFT); - } else { - /* - * RevE and less section; this line is tricky. It collapses the - * table used by RevD and later to one that matches revisions CG - * and earlier. - */ - dram_map -= (pvt->ext_model >= OPTERON_CPU_REV_D) ? - (dram_map > 8 ? 4 : (dram_map > 5 ? - 3 : (dram_map > 2 ? 1 : 0))) : 0; - - /* 25 shift is 32MiB minimum DIMM size in RevE and prior */ - nr_pages = 1 << (dram_map + 25 - PAGE_SHIFT); - } + if (pvt->ext_model >= K8_REV_F) + dbam_map = ddr2_dbam; + else if (pvt->ext_model >= K8_REV_D) + dbam_map = ddr2_dbam_revD; + else + dbam_map = ddr2_dbam_revCG; - return nr_pages; + return dbam_map[cs_mode]; } /* @@ -1248,34 +1190,24 @@ static int k8_dbam_map_to_pages(struct amd64_pvt *pvt, int dram_map) static int f10_early_channel_count(struct amd64_pvt *pvt) { int dbams[] = { DBAM0, DBAM1 }; - int err = 0, channels = 0; - int i, j; + int i, j, channels = 0; u32 dbam; - err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); - if (err) - goto err_reg; - - err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_1, &pvt->dclr1); - if (err) - goto err_reg; - /* If we are in 128 bit mode, then we are using 2 channels */ if (pvt->dclr0 & F10_WIDTH_128) { - debugf0("Data WIDTH is 128 bits - 2 channels\n"); channels = 2; return channels; } /* - * Need to check if in UN-ganged mode: In such, there are 2 channels, - * but they are NOT in 128 bit mode and thus the above 'dcl0' status bit - * will be OFF. + * Need to check if in unganged mode: In such, there are 2 channels, + * but they are not in 128 bit mode and thus the above 'dclr0' status + * bit will be OFF. * * Need to check DCT0[0] and DCT1[0] to see if only one of them has * their CSEnable bit on. If so, then SINGLE DIMM case. */ - debugf0("Data WIDTH is NOT 128 bits - need more decoding\n"); + debugf0("Data width is not 128 bits - need more decoding\n"); /* * Check DRAM Bank Address Mapping values for each DIMM to see if there @@ -1283,8 +1215,7 @@ static int f10_early_channel_count(struct amd64_pvt *pvt) * both controllers since DIMMs can be placed in either one. */ for (i = 0; i < ARRAY_SIZE(dbams); i++) { - err = pci_read_config_dword(pvt->dram_f2_ctl, dbams[i], &dbam); - if (err) + if (amd64_read_pci_cfg(pvt->dram_f2_ctl, dbams[i], &dbam)) goto err_reg; for (j = 0; j < 4; j++) { @@ -1295,6 +1226,9 @@ static int f10_early_channel_count(struct amd64_pvt *pvt) } } + if (channels > 2) + channels = 2; + debugf0("MCT channel count: %d\n", channels); return channels; @@ -1304,9 +1238,16 @@ err_reg: } -static int f10_dbam_map_to_pages(struct amd64_pvt *pvt, int dram_map) +static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, int cs_mode) { - return 1 << (revf_quad_ddr2_shift[dram_map] - PAGE_SHIFT); + int *dbam_map; + + if (pvt->dchr0 & DDR3_MODE || pvt->dchr1 & DDR3_MODE) + dbam_map = ddr3_dbam; + else + dbam_map = ddr2_dbam; + + return dbam_map[cs_mode]; } /* Enable extended configuration access via 0xCF8 feature */ @@ -1314,7 +1255,7 @@ static void amd64_setup(struct amd64_pvt *pvt) { u32 reg; - pci_read_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, ®); + amd64_read_pci_cfg(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, ®); pvt->flags.cf8_extcfg = !!(reg & F10_NB_CFG_LOW_ENABLE_EXT_CFG); reg |= F10_NB_CFG_LOW_ENABLE_EXT_CFG; @@ -1326,7 +1267,7 @@ static void amd64_teardown(struct amd64_pvt *pvt) { u32 reg; - pci_read_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, ®); + amd64_read_pci_cfg(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, ®); reg &= ~F10_NB_CFG_LOW_ENABLE_EXT_CFG; if (pvt->flags.cf8_extcfg) @@ -1355,10 +1296,10 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) high_offset = F10_DRAM_BASE_HIGH + (dram << 3); /* read the 'raw' DRAM BASE Address register */ - pci_read_config_dword(pvt->addr_f1_ctl, low_offset, &low_base); + amd64_read_pci_cfg(pvt->addr_f1_ctl, low_offset, &low_base); /* Read from the ECS data register */ - pci_read_config_dword(pvt->addr_f1_ctl, high_offset, &high_base); + amd64_read_pci_cfg(pvt->addr_f1_ctl, high_offset, &high_base); /* Extract parts into separate data entries */ pvt->dram_rw_en[dram] = (low_base & 0x3); @@ -1375,13 +1316,10 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3); /* read the 'raw' LIMIT registers */ - pci_read_config_dword(pvt->addr_f1_ctl, low_offset, &low_limit); + amd64_read_pci_cfg(pvt->addr_f1_ctl, low_offset, &low_limit); /* Read from the ECS data register for the HIGH portion */ - pci_read_config_dword(pvt->addr_f1_ctl, high_offset, &high_limit); - - debugf0(" HW Regs: BASE=0x%08x-%08x LIMIT= 0x%08x-%08x\n", - high_base, low_base, high_limit, low_limit); + amd64_read_pci_cfg(pvt->addr_f1_ctl, high_offset, &high_limit); pvt->dram_DstNode[dram] = (low_limit & 0x7); pvt->dram_IntlvSel[dram] = (low_limit >> 8) & 0x7; @@ -1397,32 +1335,35 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) { - int err = 0; - err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCTL_SEL_LOW, - &pvt->dram_ctl_select_low); - if (err) { - debugf0("Reading F10_DCTL_SEL_LOW failed\n"); - } else { - debugf0("DRAM_DCTL_SEL_LOW=0x%x DctSelBaseAddr=0x%x\n", - pvt->dram_ctl_select_low, dct_sel_baseaddr(pvt)); - - debugf0(" DRAM DCTs are=%s DRAM Is=%s DRAM-Ctl-" - "sel-hi-range=%s\n", - (dct_ganging_enabled(pvt) ? "GANGED" : "NOT GANGED"), - (dct_dram_enabled(pvt) ? "Enabled" : "Disabled"), - (dct_high_range_enabled(pvt) ? "Enabled" : "Disabled")); - - debugf0(" DctDatIntLv=%s MemCleared=%s DctSelIntLvAddr=0x%x\n", - (dct_data_intlv_enabled(pvt) ? "Enabled" : "Disabled"), - (dct_memory_cleared(pvt) ? "True " : "False "), + if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCTL_SEL_LOW, + &pvt->dram_ctl_select_low)) { + debugf0("F2x110 (DCTL Sel. Low): 0x%08x, " + "High range addresses at: 0x%x\n", + pvt->dram_ctl_select_low, + dct_sel_baseaddr(pvt)); + + debugf0(" DCT mode: %s, All DCTs on: %s\n", + (dct_ganging_enabled(pvt) ? "ganged" : "unganged"), + (dct_dram_enabled(pvt) ? "yes" : "no")); + + if (!dct_ganging_enabled(pvt)) + debugf0(" Address range split per DCT: %s\n", + (dct_high_range_enabled(pvt) ? "yes" : "no")); + + debugf0(" DCT data interleave for ECC: %s, " + "DRAM cleared since last warm reset: %s\n", + (dct_data_intlv_enabled(pvt) ? "enabled" : "disabled"), + (dct_memory_cleared(pvt) ? "yes" : "no")); + + debugf0(" DCT channel interleave: %s, " + "DCT interleave bits selector: 0x%x\n", + (dct_interleave_enabled(pvt) ? "enabled" : "disabled"), dct_sel_interleave_addr(pvt)); } - err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCTL_SEL_HIGH, - &pvt->dram_ctl_select_high); - if (err) - debugf0("Reading F10_DCTL_SEL_HIGH failed\n"); + amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCTL_SEL_HIGH, + &pvt->dram_ctl_select_high); } /* @@ -1706,10 +1647,11 @@ static int f10_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr, } /* - * This the F10h reference code from AMD to map a @sys_addr to NodeID, - * CSROW, Channel. + * For reference see "2.8.5 Routing DRAM Requests" in F10 BKDG. This code maps + * a @sys_addr to NodeID, DCT (channel) and chip select (CSROW). * - * The @sys_addr is usually an error address received from the hardware. + * The @sys_addr is usually an error address received from the hardware + * (MCX_ADDR). */ static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci, struct err_regs *info, @@ -1722,133 +1664,76 @@ static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci, csrow = f10_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan); - if (csrow >= 0) { - error_address_to_page_and_offset(sys_addr, &page, &offset); - - syndrome = HIGH_SYNDROME(info->nbsl) << 8; - syndrome |= LOW_SYNDROME(info->nbsh); - - /* - * Is CHIPKILL on? If so, then we can attempt to use the - * syndrome to isolate which channel the error was on. - */ - if (pvt->nbcfg & K8_NBCFG_CHIPKILL) - chan = get_channel_from_ecc_syndrome(syndrome); - - if (chan >= 0) { - edac_mc_handle_ce(mci, page, offset, syndrome, - csrow, chan, EDAC_MOD_STR); - } else { - /* - * Channel unknown, report all channels on this - * CSROW as failed. - */ - for (chan = 0; chan < mci->csrows[csrow].nr_channels; - chan++) { - edac_mc_handle_ce(mci, page, offset, - syndrome, - csrow, chan, - EDAC_MOD_STR); - } - } - - } else { + if (csrow < 0) { edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); + return; } -} -/* - * Input (@index) is the DBAM DIMM value (1 of 4) used as an index into a shift - * table (revf_quad_ddr2_shift) which starts at 128MB DIMM size. Index of 0 - * indicates an empty DIMM slot, as reported by Hardware on empty slots. - * - * Normalize to 128MB by subracting 27 bit shift. - */ -static int map_dbam_to_csrow_size(int index) -{ - int mega_bytes = 0; + error_address_to_page_and_offset(sys_addr, &page, &offset); - if (index > 0 && index <= DBAM_MAX_VALUE) - mega_bytes = ((128 << (revf_quad_ddr2_shift[index]-27))); + syndrome = HIGH_SYNDROME(info->nbsl) << 8; + syndrome |= LOW_SYNDROME(info->nbsh); + + /* + * We need the syndromes for channel detection only when we're + * ganged. Otherwise @chan should already contain the channel at + * this point. + */ + if (dct_ganging_enabled(pvt) && pvt->nbcfg & K8_NBCFG_CHIPKILL) + chan = get_channel_from_ecc_syndrome(mci, syndrome); - return mega_bytes; + if (chan >= 0) + edac_mc_handle_ce(mci, page, offset, syndrome, csrow, chan, + EDAC_MOD_STR); + else + /* + * Channel unknown, report all channels on this CSROW as failed. + */ + for (chan = 0; chan < mci->csrows[csrow].nr_channels; chan++) + edac_mc_handle_ce(mci, page, offset, syndrome, + csrow, chan, EDAC_MOD_STR); } /* - * debug routine to display the memory sizes of a DIMM (ganged or not) and it + * debug routine to display the memory sizes of all logical DIMMs and its * CSROWs as well */ -static void f10_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt, - int ganged) +static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt) { int dimm, size0, size1; u32 dbam; u32 *dcsb; - debugf1(" dbam%d: 0x%8.08x CSROW is %s\n", ctrl, - ctrl ? pvt->dbam1 : pvt->dbam0, - ganged ? "GANGED - dbam1 not used" : "NON-GANGED"); + if (boot_cpu_data.x86 == 0xf) { + /* K8 families < revF not supported yet */ + if (pvt->ext_model < K8_REV_F) + return; + else + WARN_ON(ctrl != 0); + } + + debugf1("F2x%d80 (DRAM Bank Address Mapping): 0x%08x\n", + ctrl, ctrl ? pvt->dbam1 : pvt->dbam0); dbam = ctrl ? pvt->dbam1 : pvt->dbam0; dcsb = ctrl ? pvt->dcsb1 : pvt->dcsb0; + edac_printk(KERN_DEBUG, EDAC_MC, "DCT%d chip selects:\n", ctrl); + /* Dump memory sizes for DIMM and its CSROWs */ for (dimm = 0; dimm < 4; dimm++) { size0 = 0; if (dcsb[dimm*2] & K8_DCSB_CS_ENABLE) - size0 = map_dbam_to_csrow_size(DBAM_DIMM(dimm, dbam)); + size0 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam)); size1 = 0; if (dcsb[dimm*2 + 1] & K8_DCSB_CS_ENABLE) - size1 = map_dbam_to_csrow_size(DBAM_DIMM(dimm, dbam)); - - debugf1(" CTRL-%d DIMM-%d=%5dMB CSROW-%d=%5dMB " - "CSROW-%d=%5dMB\n", - ctrl, - dimm, - size0 + size1, - dimm * 2, - size0, - dimm * 2 + 1, - size1); - } -} - -/* - * Very early hardware probe on pci_probe thread to determine if this module - * supports the hardware. - * - * Return: - * 0 for OK - * 1 for error - */ -static int f10_probe_valid_hardware(struct amd64_pvt *pvt) -{ - int ret = 0; - - /* - * If we are on a DDR3 machine, we don't know yet if - * we support that properly at this time - */ - if ((pvt->dchr0 & F10_DCHR_Ddr3Mode) || - (pvt->dchr1 & F10_DCHR_Ddr3Mode)) { - - amd64_printk(KERN_WARNING, - "%s() This machine is running with DDR3 memory. " - "This is not currently supported. " - "DCHR0=0x%x DCHR1=0x%x\n", - __func__, pvt->dchr0, pvt->dchr1); - - amd64_printk(KERN_WARNING, - " Contact '%s' module MAINTAINER to help add" - " support.\n", - EDAC_MOD_STR); - - ret = 1; + size1 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam)); + edac_printk(KERN_DEBUG, EDAC_MC, " %d: %5dMB %d: %5dMB\n", + dimm * 2, size0, dimm * 2 + 1, size1); } - return ret; } /* @@ -1868,11 +1753,11 @@ static struct amd64_family_type amd64_family_types[] = { .addr_f1_ctl = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP, .misc_f3_ctl = PCI_DEVICE_ID_AMD_K8_NB_MISC, .ops = { - .early_channel_count = k8_early_channel_count, - .get_error_address = k8_get_error_address, - .read_dram_base_limit = k8_read_dram_base_limit, - .map_sysaddr_to_csrow = k8_map_sysaddr_to_csrow, - .dbam_map_to_pages = k8_dbam_map_to_pages, + .early_channel_count = k8_early_channel_count, + .get_error_address = k8_get_error_address, + .read_dram_base_limit = k8_read_dram_base_limit, + .map_sysaddr_to_csrow = k8_map_sysaddr_to_csrow, + .dbam_to_cs = k8_dbam_to_chip_select, } }, [F10_CPUS] = { @@ -1880,13 +1765,12 @@ static struct amd64_family_type amd64_family_types[] = { .addr_f1_ctl = PCI_DEVICE_ID_AMD_10H_NB_MAP, .misc_f3_ctl = PCI_DEVICE_ID_AMD_10H_NB_MISC, .ops = { - .probe_valid_hardware = f10_probe_valid_hardware, - .early_channel_count = f10_early_channel_count, - .get_error_address = f10_get_error_address, - .read_dram_base_limit = f10_read_dram_base_limit, - .read_dram_ctl_register = f10_read_dram_ctl_register, - .map_sysaddr_to_csrow = f10_map_sysaddr_to_csrow, - .dbam_map_to_pages = f10_dbam_map_to_pages, + .early_channel_count = f10_early_channel_count, + .get_error_address = f10_get_error_address, + .read_dram_base_limit = f10_read_dram_base_limit, + .read_dram_ctl_register = f10_read_dram_ctl_register, + .map_sysaddr_to_csrow = f10_map_sysaddr_to_csrow, + .dbam_to_cs = f10_dbam_to_chip_select, } }, [F11_CPUS] = { @@ -1894,13 +1778,12 @@ static struct amd64_family_type amd64_family_types[] = { .addr_f1_ctl = PCI_DEVICE_ID_AMD_11H_NB_MAP, .misc_f3_ctl = PCI_DEVICE_ID_AMD_11H_NB_MISC, .ops = { - .probe_valid_hardware = f10_probe_valid_hardware, - .early_channel_count = f10_early_channel_count, - .get_error_address = f10_get_error_address, - .read_dram_base_limit = f10_read_dram_base_limit, - .read_dram_ctl_register = f10_read_dram_ctl_register, - .map_sysaddr_to_csrow = f10_map_sysaddr_to_csrow, - .dbam_map_to_pages = f10_dbam_map_to_pages, + .early_channel_count = f10_early_channel_count, + .get_error_address = f10_get_error_address, + .read_dram_base_limit = f10_read_dram_base_limit, + .read_dram_ctl_register = f10_read_dram_ctl_register, + .map_sysaddr_to_csrow = f10_map_sysaddr_to_csrow, + .dbam_to_cs = f10_dbam_to_chip_select, } }, }; @@ -1923,142 +1806,170 @@ static struct pci_dev *pci_get_related_function(unsigned int vendor, } /* - * syndrome mapping table for ECC ChipKill devices - * - * The comment in each row is the token (nibble) number that is in error. - * The least significant nibble of the syndrome is the mask for the bits - * that are in error (need to be toggled) for the particular nibble. - * - * Each row contains 16 entries. - * The first entry (0th) is the channel number for that row of syndromes. - * The remaining 15 entries are the syndromes for the respective Error - * bit mask index. + * These are tables of eigenvectors (one per line) which can be used for the + * construction of the syndrome tables. The modified syndrome search algorithm + * uses those to find the symbol in error and thus the DIMM. * - * 1st index entry is 0x0001 mask, indicating that the rightmost bit is the - * bit in error. - * The 2nd index entry is 0x0010 that the second bit is damaged. - * The 3rd index entry is 0x0011 indicating that the rightmost 2 bits - * are damaged. - * Thus so on until index 15, 0x1111, whose entry has the syndrome - * indicating that all 4 bits are damaged. - * - * A search is performed on this table looking for a given syndrome. - * - * See the AMD documentation for ECC syndromes. This ECC table is valid - * across all the versions of the AMD64 processors. - * - * A fast lookup is to use the LAST four bits of the 16-bit syndrome as a - * COLUMN index, then search all ROWS of that column, looking for a match - * with the input syndrome. The ROW value will be the token number. - * - * The 0'th entry on that row, can be returned as the CHANNEL (0 or 1) of this - * error. + * Algorithm courtesy of Ross LaFetra from AMD. */ -#define NUMBER_ECC_ROWS 36 -static const unsigned short ecc_chipkill_syndromes[NUMBER_ECC_ROWS][16] = { - /* Channel 0 syndromes */ - {/*0*/ 0, 0xe821, 0x7c32, 0x9413, 0xbb44, 0x5365, 0xc776, 0x2f57, - 0xdd88, 0x35a9, 0xa1ba, 0x499b, 0x66cc, 0x8eed, 0x1afe, 0xf2df }, - {/*1*/ 0, 0x5d31, 0xa612, 0xfb23, 0x9584, 0xc8b5, 0x3396, 0x6ea7, - 0xeac8, 0xb7f9, 0x4cda, 0x11eb, 0x7f4c, 0x227d, 0xd95e, 0x846f }, - {/*2*/ 0, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f }, - {/*3*/ 0, 0x2021, 0x3032, 0x1013, 0x4044, 0x6065, 0x7076, 0x5057, - 0x8088, 0xa0a9, 0xb0ba, 0x909b, 0xc0cc, 0xe0ed, 0xf0fe, 0xd0df }, - {/*4*/ 0, 0x5041, 0xa082, 0xf0c3, 0x9054, 0xc015, 0x30d6, 0x6097, - 0xe0a8, 0xb0e9, 0x402a, 0x106b, 0x70fc, 0x20bd, 0xd07e, 0x803f }, - {/*5*/ 0, 0xbe21, 0xd732, 0x6913, 0x2144, 0x9f65, 0xf676, 0x4857, - 0x3288, 0x8ca9, 0xe5ba, 0x5b9b, 0x13cc, 0xaded, 0xc4fe, 0x7adf }, - {/*6*/ 0, 0x4951, 0x8ea2, 0xc7f3, 0x5394, 0x1ac5, 0xdd36, 0x9467, - 0xa1e8, 0xe8b9, 0x2f4a, 0x661b, 0xf27c, 0xbb2d, 0x7cde, 0x358f }, - {/*7*/ 0, 0x74e1, 0x9872, 0xec93, 0xd6b4, 0xa255, 0x4ec6, 0x3a27, - 0x6bd8, 0x1f39, 0xf3aa, 0x874b, 0xbd6c, 0xc98d, 0x251e, 0x51ff }, - {/*8*/ 0, 0x15c1, 0x2a42, 0x3f83, 0xcef4, 0xdb35, 0xe4b6, 0xf177, - 0x4758, 0x5299, 0x6d1a, 0x78db, 0x89ac, 0x9c6d, 0xa3ee, 0xb62f }, - {/*9*/ 0, 0x3d01, 0x1602, 0x2b03, 0x8504, 0xb805, 0x9306, 0xae07, - 0xca08, 0xf709, 0xdc0a, 0xe10b, 0x4f0c, 0x720d, 0x590e, 0x640f }, - {/*a*/ 0, 0x9801, 0xec02, 0x7403, 0x6b04, 0xf305, 0x8706, 0x1f07, - 0xbd08, 0x2509, 0x510a, 0xc90b, 0xd60c, 0x4e0d, 0x3a0e, 0xa20f }, - {/*b*/ 0, 0xd131, 0x6212, 0xb323, 0x3884, 0xe9b5, 0x5a96, 0x8ba7, - 0x1cc8, 0xcdf9, 0x7eda, 0xafeb, 0x244c, 0xf57d, 0x465e, 0x976f }, - {/*c*/ 0, 0xe1d1, 0x7262, 0x93b3, 0xb834, 0x59e5, 0xca56, 0x2b87, - 0xdc18, 0x3dc9, 0xae7a, 0x4fab, 0x542c, 0x85fd, 0x164e, 0xf79f }, - {/*d*/ 0, 0x6051, 0xb0a2, 0xd0f3, 0x1094, 0x70c5, 0xa036, 0xc067, - 0x20e8, 0x40b9, 0x904a, 0x601b, 0x307c, 0x502d, 0x80de, 0xe08f }, - {/*e*/ 0, 0xa4c1, 0xf842, 0x5c83, 0xe6f4, 0x4235, 0x1eb6, 0xba77, - 0x7b58, 0xdf99, 0x831a, 0x27db, 0x9dac, 0x396d, 0x65ee, 0xc12f }, - {/*f*/ 0, 0x11c1, 0x2242, 0x3383, 0xc8f4, 0xd935, 0xeab6, 0xfb77, - 0x4c58, 0x5d99, 0x6e1a, 0x7fdb, 0x84ac, 0x956d, 0xa6ee, 0xb72f }, - - /* Channel 1 syndromes */ - {/*10*/ 1, 0x45d1, 0x8a62, 0xcfb3, 0x5e34, 0x1be5, 0xd456, 0x9187, - 0xa718, 0xe2c9, 0x2d7a, 0x68ab, 0xf92c, 0xbcfd, 0x734e, 0x369f }, - {/*11*/ 1, 0x63e1, 0xb172, 0xd293, 0x14b4, 0x7755, 0xa5c6, 0xc627, - 0x28d8, 0x4b39, 0x99aa, 0xfa4b, 0x3c6c, 0x5f8d, 0x8d1e, 0xeeff }, - {/*12*/ 1, 0xb741, 0xd982, 0x6ec3, 0x2254, 0x9515, 0xfbd6, 0x4c97, - 0x33a8, 0x84e9, 0xea2a, 0x5d6b, 0x11fc, 0xa6bd, 0xc87e, 0x7f3f }, - {/*13*/ 1, 0xdd41, 0x6682, 0xbbc3, 0x3554, 0xe815, 0x53d6, 0xce97, - 0x1aa8, 0xc7e9, 0x7c2a, 0xa1fb, 0x2ffc, 0xf2bd, 0x497e, 0x943f }, - {/*14*/ 1, 0x2bd1, 0x3d62, 0x16b3, 0x4f34, 0x64e5, 0x7256, 0x5987, - 0x8518, 0xaec9, 0xb87a, 0x93ab, 0xca2c, 0xe1fd, 0xf74e, 0xdc9f }, - {/*15*/ 1, 0x83c1, 0xc142, 0x4283, 0xa4f4, 0x2735, 0x65b6, 0xe677, - 0xf858, 0x7b99, 0x391a, 0xbadb, 0x5cac, 0xdf6d, 0x9dee, 0x1e2f }, - {/*16*/ 1, 0x8fd1, 0xc562, 0x4ab3, 0xa934, 0x26e5, 0x6c56, 0xe387, - 0xfe18, 0x71c9, 0x3b7a, 0xb4ab, 0x572c, 0xd8fd, 0x924e, 0x1d9f }, - {/*17*/ 1, 0x4791, 0x89e2, 0xce73, 0x5264, 0x15f5, 0xdb86, 0x9c17, - 0xa3b8, 0xe429, 0x2a5a, 0x6dcb, 0xf1dc, 0xb64d, 0x783e, 0x3faf }, - {/*18*/ 1, 0x5781, 0xa9c2, 0xfe43, 0x92a4, 0xc525, 0x3b66, 0x6ce7, - 0xe3f8, 0xb479, 0x4a3a, 0x1dbb, 0x715c, 0x26dd, 0xd89e, 0x8f1f }, - {/*19*/ 1, 0xbf41, 0xd582, 0x6ac3, 0x2954, 0x9615, 0xfcd6, 0x4397, - 0x3ea8, 0x81e9, 0xeb2a, 0x546b, 0x17fc, 0xa8bd, 0xc27e, 0x7d3f }, - {/*1a*/ 1, 0x9891, 0xe1e2, 0x7273, 0x6464, 0xf7f5, 0x8586, 0x1617, - 0xb8b8, 0x2b29, 0x595a, 0xcacb, 0xdcdc, 0x4f4d, 0x3d3e, 0xaeaf }, - {/*1b*/ 1, 0xcce1, 0x4472, 0x8893, 0xfdb4, 0x3f55, 0xb9c6, 0x7527, - 0x56d8, 0x9a39, 0x12aa, 0xde4b, 0xab6c, 0x678d, 0xef1e, 0x23ff }, - {/*1c*/ 1, 0xa761, 0xf9b2, 0x5ed3, 0xe214, 0x4575, 0x1ba6, 0xbcc7, - 0x7328, 0xd449, 0x8a9a, 0x2dfb, 0x913c, 0x365d, 0x688e, 0xcfef }, - {/*1d*/ 1, 0xff61, 0x55b2, 0xaad3, 0x7914, 0x8675, 0x2ca6, 0xd3c7, - 0x9e28, 0x6149, 0xcb9a, 0x34fb, 0xe73c, 0x185d, 0xb28e, 0x4def }, - {/*1e*/ 1, 0x5451, 0xa8a2, 0xfcf3, 0x9694, 0xc2c5, 0x3e36, 0x6a67, - 0xebe8, 0xbfb9, 0x434a, 0x171b, 0x7d7c, 0x292d, 0xd5de, 0x818f }, - {/*1f*/ 1, 0x6fc1, 0xb542, 0xda83, 0x19f4, 0x7635, 0xacb6, 0xc377, - 0x2e58, 0x4199, 0x9b1a, 0xf4db, 0x37ac, 0x586d, 0x82ee, 0xed2f }, - - /* ECC bits are also in the set of tokens and they too can go bad - * first 2 cover channel 0, while the second 2 cover channel 1 - */ - {/*20*/ 0, 0xbe01, 0xd702, 0x6903, 0x2104, 0x9f05, 0xf606, 0x4807, - 0x3208, 0x8c09, 0xe50a, 0x5b0b, 0x130c, 0xad0d, 0xc40e, 0x7a0f }, - {/*21*/ 0, 0x4101, 0x8202, 0xc303, 0x5804, 0x1905, 0xda06, 0x9b07, - 0xac08, 0xed09, 0x2e0a, 0x6f0b, 0x640c, 0xb50d, 0x760e, 0x370f }, - {/*22*/ 1, 0xc441, 0x4882, 0x8cc3, 0xf654, 0x3215, 0xbed6, 0x7a97, - 0x5ba8, 0x9fe9, 0x132a, 0xd76b, 0xadfc, 0x69bd, 0xe57e, 0x213f }, - {/*23*/ 1, 0x7621, 0x9b32, 0xed13, 0xda44, 0xac65, 0x4176, 0x3757, - 0x6f88, 0x19a9, 0xf4ba, 0x829b, 0xb5cc, 0xc3ed, 0x2efe, 0x58df } +static u16 x4_vectors[] = { + 0x2f57, 0x1afe, 0x66cc, 0xdd88, + 0x11eb, 0x3396, 0x7f4c, 0xeac8, + 0x0001, 0x0002, 0x0004, 0x0008, + 0x1013, 0x3032, 0x4044, 0x8088, + 0x106b, 0x30d6, 0x70fc, 0xe0a8, + 0x4857, 0xc4fe, 0x13cc, 0x3288, + 0x1ac5, 0x2f4a, 0x5394, 0xa1e8, + 0x1f39, 0x251e, 0xbd6c, 0x6bd8, + 0x15c1, 0x2a42, 0x89ac, 0x4758, + 0x2b03, 0x1602, 0x4f0c, 0xca08, + 0x1f07, 0x3a0e, 0x6b04, 0xbd08, + 0x8ba7, 0x465e, 0x244c, 0x1cc8, + 0x2b87, 0x164e, 0x642c, 0xdc18, + 0x40b9, 0x80de, 0x1094, 0x20e8, + 0x27db, 0x1eb6, 0x9dac, 0x7b58, + 0x11c1, 0x2242, 0x84ac, 0x4c58, + 0x1be5, 0x2d7a, 0x5e34, 0xa718, + 0x4b39, 0x8d1e, 0x14b4, 0x28d8, + 0x4c97, 0xc87e, 0x11fc, 0x33a8, + 0x8e97, 0x497e, 0x2ffc, 0x1aa8, + 0x16b3, 0x3d62, 0x4f34, 0x8518, + 0x1e2f, 0x391a, 0x5cac, 0xf858, + 0x1d9f, 0x3b7a, 0x572c, 0xfe18, + 0x15f5, 0x2a5a, 0x5264, 0xa3b8, + 0x1dbb, 0x3b66, 0x715c, 0xe3f8, + 0x4397, 0xc27e, 0x17fc, 0x3ea8, + 0x1617, 0x3d3e, 0x6464, 0xb8b8, + 0x23ff, 0x12aa, 0xab6c, 0x56d8, + 0x2dfb, 0x1ba6, 0x913c, 0x7328, + 0x185d, 0x2ca6, 0x7914, 0x9e28, + 0x171b, 0x3e36, 0x7d7c, 0xebe8, + 0x4199, 0x82ee, 0x19f4, 0x2e58, + 0x4807, 0xc40e, 0x130c, 0x3208, + 0x1905, 0x2e0a, 0x5804, 0xac08, + 0x213f, 0x132a, 0xadfc, 0x5ba8, + 0x19a9, 0x2efe, 0xb5cc, 0x6f88, }; -/* - * Given the syndrome argument, scan each of the channel tables for a syndrome - * match. Depending on which table it is found, return the channel number. - */ -static int get_channel_from_ecc_syndrome(unsigned short syndrome) +static u16 x8_vectors[] = { + 0x0145, 0x028a, 0x2374, 0x43c8, 0xa1f0, 0x0520, 0x0a40, 0x1480, + 0x0211, 0x0422, 0x0844, 0x1088, 0x01b0, 0x44e0, 0x23c0, 0xed80, + 0x1011, 0x0116, 0x022c, 0x0458, 0x08b0, 0x8c60, 0x2740, 0x4e80, + 0x0411, 0x0822, 0x1044, 0x0158, 0x02b0, 0x2360, 0x46c0, 0xab80, + 0x0811, 0x1022, 0x012c, 0x0258, 0x04b0, 0x4660, 0x8cc0, 0x2780, + 0x2071, 0x40e2, 0xa0c4, 0x0108, 0x0210, 0x0420, 0x0840, 0x1080, + 0x4071, 0x80e2, 0x0104, 0x0208, 0x0410, 0x0820, 0x1040, 0x2080, + 0x8071, 0x0102, 0x0204, 0x0408, 0x0810, 0x1020, 0x2040, 0x4080, + 0x019d, 0x03d6, 0x136c, 0x2198, 0x50b0, 0xb2e0, 0x0740, 0x0e80, + 0x0189, 0x03ea, 0x072c, 0x0e58, 0x1cb0, 0x56e0, 0x37c0, 0xf580, + 0x01fd, 0x0376, 0x06ec, 0x0bb8, 0x1110, 0x2220, 0x4440, 0x8880, + 0x0163, 0x02c6, 0x1104, 0x0758, 0x0eb0, 0x2be0, 0x6140, 0xc280, + 0x02fd, 0x01c6, 0x0b5c, 0x1108, 0x07b0, 0x25a0, 0x8840, 0x6180, + 0x0801, 0x012e, 0x025c, 0x04b8, 0x1370, 0x26e0, 0x57c0, 0xb580, + 0x0401, 0x0802, 0x015c, 0x02b8, 0x22b0, 0x13e0, 0x7140, 0xe280, + 0x0201, 0x0402, 0x0804, 0x01b8, 0x11b0, 0x31a0, 0x8040, 0x7180, + 0x0101, 0x0202, 0x0404, 0x0808, 0x1010, 0x2020, 0x4040, 0x8080, + 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, +}; + +static int decode_syndrome(u16 syndrome, u16 *vectors, int num_vecs, + int v_dim) { - int row; - int column; + unsigned int i, err_sym; - /* Determine column to scan */ - column = syndrome & 0xF; + for (err_sym = 0; err_sym < num_vecs / v_dim; err_sym++) { + u16 s = syndrome; + int v_idx = err_sym * v_dim; + int v_end = (err_sym + 1) * v_dim; - /* Scan all rows, looking for syndrome, or end of table */ - for (row = 0; row < NUMBER_ECC_ROWS; row++) { - if (ecc_chipkill_syndromes[row][column] == syndrome) - return ecc_chipkill_syndromes[row][0]; + /* walk over all 16 bits of the syndrome */ + for (i = 1; i < (1U << 16); i <<= 1) { + + /* if bit is set in that eigenvector... */ + if (v_idx < v_end && vectors[v_idx] & i) { + u16 ev_comp = vectors[v_idx++]; + + /* ... and bit set in the modified syndrome, */ + if (s & i) { + /* remove it. */ + s ^= ev_comp; + + if (!s) + return err_sym; + } + + } else if (s & i) + /* can't get to zero, move to next symbol */ + break; + } } debugf0("syndrome(%x) not found\n", syndrome); return -1; } +static int map_err_sym_to_channel(int err_sym, int sym_size) +{ + if (sym_size == 4) + switch (err_sym) { + case 0x20: + case 0x21: + return 0; + break; + case 0x22: + case 0x23: + return 1; + break; + default: + return err_sym >> 4; + break; + } + /* x8 symbols */ + else + switch (err_sym) { + /* imaginary bits not in a DIMM */ + case 0x10: + WARN(1, KERN_ERR "Invalid error symbol: 0x%x\n", + err_sym); + return -1; + break; + + case 0x11: + return 0; + break; + case 0x12: + return 1; + break; + default: + return err_sym >> 3; + break; + } + return -1; +} + +static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome) +{ + struct amd64_pvt *pvt = mci->pvt_info; + u32 value = 0; + int err_sym = 0; + + amd64_read_pci_cfg(pvt->misc_f3_ctl, 0x180, &value); + + /* F3x180[EccSymbolSize]=1, x8 symbols */ + if (boot_cpu_data.x86 == 0x10 && + boot_cpu_data.x86_model > 7 && + value & BIT(25)) { + err_sym = decode_syndrome(syndrome, x8_vectors, + ARRAY_SIZE(x8_vectors), 8); + return map_err_sym_to_channel(err_sym, 8); + } else { + err_sym = decode_syndrome(syndrome, x4_vectors, + ARRAY_SIZE(x4_vectors), 4); + return map_err_sym_to_channel(err_sym, 4); + } +} + /* * Check for valid error in the NB Status High register. If so, proceed to read * NB Status Low, NB Address Low and NB Address High registers and store data @@ -2073,40 +1984,24 @@ static int amd64_get_error_info_regs(struct mem_ctl_info *mci, { struct amd64_pvt *pvt; struct pci_dev *misc_f3_ctl; - int err = 0; pvt = mci->pvt_info; misc_f3_ctl = pvt->misc_f3_ctl; - err = pci_read_config_dword(misc_f3_ctl, K8_NBSH, ®s->nbsh); - if (err) - goto err_reg; + if (amd64_read_pci_cfg(misc_f3_ctl, K8_NBSH, ®s->nbsh)) + return 0; if (!(regs->nbsh & K8_NBSH_VALID_BIT)) return 0; /* valid error, read remaining error information registers */ - err = pci_read_config_dword(misc_f3_ctl, K8_NBSL, ®s->nbsl); - if (err) - goto err_reg; - - err = pci_read_config_dword(misc_f3_ctl, K8_NBEAL, ®s->nbeal); - if (err) - goto err_reg; - - err = pci_read_config_dword(misc_f3_ctl, K8_NBEAH, ®s->nbeah); - if (err) - goto err_reg; - - err = pci_read_config_dword(misc_f3_ctl, K8_NBCFG, ®s->nbcfg); - if (err) - goto err_reg; + if (amd64_read_pci_cfg(misc_f3_ctl, K8_NBSL, ®s->nbsl) || + amd64_read_pci_cfg(misc_f3_ctl, K8_NBEAL, ®s->nbeal) || + amd64_read_pci_cfg(misc_f3_ctl, K8_NBEAH, ®s->nbeah) || + amd64_read_pci_cfg(misc_f3_ctl, K8_NBCFG, ®s->nbcfg)) + return 0; return 1; - -err_reg: - debugf0("Reading error info register failed\n"); - return 0; } /* @@ -2184,7 +2079,7 @@ static void amd64_handle_ce(struct mem_ctl_info *mci, struct err_regs *info) { struct amd64_pvt *pvt = mci->pvt_info; - u64 SystemAddress; + u64 sys_addr; /* Ensure that the Error Address is VALID */ if ((info->nbsh & K8_NBSH_VALID_ERROR_ADDR) == 0) { @@ -2194,22 +2089,23 @@ static void amd64_handle_ce(struct mem_ctl_info *mci, return; } - SystemAddress = extract_error_address(mci, info); + sys_addr = pvt->ops->get_error_address(mci, info); amd64_mc_printk(mci, KERN_ERR, - "CE ERROR_ADDRESS= 0x%llx\n", SystemAddress); + "CE ERROR_ADDRESS= 0x%llx\n", sys_addr); - pvt->ops->map_sysaddr_to_csrow(mci, info, SystemAddress); + pvt->ops->map_sysaddr_to_csrow(mci, info, sys_addr); } /* Handle any Un-correctable Errors (UEs) */ static void amd64_handle_ue(struct mem_ctl_info *mci, struct err_regs *info) { + struct amd64_pvt *pvt = mci->pvt_info; + struct mem_ctl_info *log_mci, *src_mci = NULL; int csrow; - u64 SystemAddress; + u64 sys_addr; u32 page, offset; - struct mem_ctl_info *log_mci, *src_mci = NULL; log_mci = mci; @@ -2220,31 +2116,31 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, return; } - SystemAddress = extract_error_address(mci, info); + sys_addr = pvt->ops->get_error_address(mci, info); /* * Find out which node the error address belongs to. This may be * different from the node that detected the error. */ - src_mci = find_mc_by_sys_addr(mci, SystemAddress); + src_mci = find_mc_by_sys_addr(mci, sys_addr); if (!src_mci) { amd64_mc_printk(mci, KERN_CRIT, "ERROR ADDRESS (0x%lx) value NOT mapped to a MC\n", - (unsigned long)SystemAddress); + (unsigned long)sys_addr); edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); return; } log_mci = src_mci; - csrow = sys_addr_to_csrow(log_mci, SystemAddress); + csrow = sys_addr_to_csrow(log_mci, sys_addr); if (csrow < 0) { amd64_mc_printk(mci, KERN_CRIT, "ERROR_ADDRESS (0x%lx) value NOT mapped to 'csrow'\n", - (unsigned long)SystemAddress); + (unsigned long)sys_addr); edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); } else { - error_address_to_page_and_offset(SystemAddress, &page, &offset); + error_address_to_page_and_offset(sys_addr, &page, &offset); edac_mc_handle_ue(log_mci, page, offset, csrow, EDAC_MOD_STR); } } @@ -2384,30 +2280,26 @@ static void amd64_free_mc_sibling_devices(struct amd64_pvt *pvt) static void amd64_read_mc_registers(struct amd64_pvt *pvt) { u64 msr_val; - int dram, err = 0; + int dram; /* * Retrieve TOP_MEM and TOP_MEM2; no masking off of reserved bits since * those are Read-As-Zero */ - rdmsrl(MSR_K8_TOP_MEM1, msr_val); - pvt->top_mem = msr_val >> 23; - debugf0(" TOP_MEM=0x%08llx\n", pvt->top_mem); + rdmsrl(MSR_K8_TOP_MEM1, pvt->top_mem); + debugf0(" TOP_MEM: 0x%016llx\n", pvt->top_mem); /* check first whether TOP_MEM2 is enabled */ rdmsrl(MSR_K8_SYSCFG, msr_val); if (msr_val & (1U << 21)) { - rdmsrl(MSR_K8_TOP_MEM2, msr_val); - pvt->top_mem2 = msr_val >> 23; - debugf0(" TOP_MEM2=0x%08llx\n", pvt->top_mem2); + rdmsrl(MSR_K8_TOP_MEM2, pvt->top_mem2); + debugf0(" TOP_MEM2: 0x%016llx\n", pvt->top_mem2); } else debugf0(" TOP_MEM2 disabled.\n"); amd64_cpu_display_info(pvt); - err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCAP, &pvt->nbcap); - if (err) - goto err_reg; + amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCAP, &pvt->nbcap); if (pvt->ops->read_dram_ctl_register) pvt->ops->read_dram_ctl_register(pvt); @@ -2425,13 +2317,12 @@ static void amd64_read_mc_registers(struct amd64_pvt *pvt) * debug output block away. */ if (pvt->dram_rw_en[dram] != 0) { - debugf1(" DRAM_BASE[%d]: 0x%8.08x-%8.08x " - "DRAM_LIMIT: 0x%8.08x-%8.08x\n", + debugf1(" DRAM-BASE[%d]: 0x%016llx " + "DRAM-LIMIT: 0x%016llx\n", dram, - (u32)(pvt->dram_base[dram] >> 32), - (u32)(pvt->dram_base[dram] & 0xFFFFFFFF), - (u32)(pvt->dram_limit[dram] >> 32), - (u32)(pvt->dram_limit[dram] & 0xFFFFFFFF)); + pvt->dram_base[dram], + pvt->dram_limit[dram]); + debugf1(" IntlvEn=%s %s %s " "IntlvSel=%d DstNode=%d\n", pvt->dram_IntlvEn[dram] ? @@ -2445,44 +2336,20 @@ static void amd64_read_mc_registers(struct amd64_pvt *pvt) amd64_read_dct_base_mask(pvt); - err = pci_read_config_dword(pvt->addr_f1_ctl, K8_DHAR, &pvt->dhar); - if (err) - goto err_reg; - + amd64_read_pci_cfg(pvt->addr_f1_ctl, K8_DHAR, &pvt->dhar); amd64_read_dbam_reg(pvt); - err = pci_read_config_dword(pvt->misc_f3_ctl, - F10_ONLINE_SPARE, &pvt->online_spare); - if (err) - goto err_reg; + amd64_read_pci_cfg(pvt->misc_f3_ctl, + F10_ONLINE_SPARE, &pvt->online_spare); - err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); - if (err) - goto err_reg; - - err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCHR_0, &pvt->dchr0); - if (err) - goto err_reg; + amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); + amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_0, &pvt->dchr0); if (!dct_ganging_enabled(pvt)) { - err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_1, - &pvt->dclr1); - if (err) - goto err_reg; - - err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCHR_1, - &pvt->dchr1); - if (err) - goto err_reg; + amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_1, &pvt->dclr1); + amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_1, &pvt->dchr1); } - amd64_dump_misc_regs(pvt); - - return; - -err_reg: - debugf0("Reading an MC register failed\n"); - } /* @@ -2521,7 +2388,7 @@ err_reg: */ static u32 amd64_csrow_nr_pages(int csrow_nr, struct amd64_pvt *pvt) { - u32 dram_map, nr_pages; + u32 cs_mode, nr_pages; /* * The math on this doesn't look right on the surface because x/2*4 can @@ -2530,9 +2397,9 @@ static u32 amd64_csrow_nr_pages(int csrow_nr, struct amd64_pvt *pvt) * number of bits to shift the DBAM register to extract the proper CSROW * field. */ - dram_map = (pvt->dbam0 >> ((csrow_nr / 2) * 4)) & 0xF; + cs_mode = (pvt->dbam0 >> ((csrow_nr / 2) * 4)) & 0xF; - nr_pages = pvt->ops->dbam_map_to_pages(pvt, dram_map); + nr_pages = pvt->ops->dbam_to_cs(pvt, cs_mode) << (20 - PAGE_SHIFT); /* * If dual channel then double the memory size of single channel. @@ -2540,7 +2407,7 @@ static u32 amd64_csrow_nr_pages(int csrow_nr, struct amd64_pvt *pvt) */ nr_pages <<= (pvt->channel_count - 1); - debugf0(" (csrow=%d) DBAM map index= %d\n", csrow_nr, dram_map); + debugf0(" (csrow=%d) DBAM map index= %d\n", csrow_nr, cs_mode); debugf0(" nr_pages= %u channel-count = %d\n", nr_pages, pvt->channel_count); @@ -2556,13 +2423,11 @@ static int amd64_init_csrows(struct mem_ctl_info *mci) struct csrow_info *csrow; struct amd64_pvt *pvt; u64 input_addr_min, input_addr_max, sys_addr; - int i, err = 0, empty = 1; + int i, empty = 1; pvt = mci->pvt_info; - err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &pvt->nbcfg); - if (err) - debugf0("Reading K8_NBCFG failed\n"); + amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &pvt->nbcfg); debugf0("NBCFG= 0x%x CHIPKILL= %s DRAM ECC= %s\n", pvt->nbcfg, (pvt->nbcfg & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", @@ -2618,6 +2483,90 @@ static int amd64_init_csrows(struct mem_ctl_info *mci) return empty; } +/* get all cores on this DCT */ +static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, int nid) +{ + int cpu; + + for_each_online_cpu(cpu) + if (amd_get_nb_id(cpu) == nid) + cpumask_set_cpu(cpu, mask); +} + +/* check MCG_CTL on all the cpus on this node */ +static bool amd64_nb_mce_bank_enabled_on_node(int nid) +{ + cpumask_var_t mask; + int cpu, nbe; + bool ret = false; + + if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) { + amd64_printk(KERN_WARNING, "%s: error allocating mask\n", + __func__); + return false; + } + + get_cpus_on_this_dct_cpumask(mask, nid); + + rdmsr_on_cpus(mask, MSR_IA32_MCG_CTL, msrs); + + for_each_cpu(cpu, mask) { + struct msr *reg = per_cpu_ptr(msrs, cpu); + nbe = reg->l & K8_MSR_MCGCTL_NBE; + + debugf0("core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n", + cpu, reg->q, + (nbe ? "enabled" : "disabled")); + + if (!nbe) + goto out; + } + ret = true; + +out: + free_cpumask_var(mask); + return ret; +} + +static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on) +{ + cpumask_var_t cmask; + int cpu; + + if (!zalloc_cpumask_var(&cmask, GFP_KERNEL)) { + amd64_printk(KERN_WARNING, "%s: error allocating mask\n", + __func__); + return false; + } + + get_cpus_on_this_dct_cpumask(cmask, pvt->mc_node_id); + + rdmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs); + + for_each_cpu(cpu, cmask) { + + struct msr *reg = per_cpu_ptr(msrs, cpu); + + if (on) { + if (reg->l & K8_MSR_MCGCTL_NBE) + pvt->flags.ecc_report = 1; + + reg->l |= K8_MSR_MCGCTL_NBE; + } else { + /* + * Turn off ECC reporting only when it was off before + */ + if (!pvt->flags.ecc_report) + reg->l &= ~K8_MSR_MCGCTL_NBE; + } + } + wrmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs); + + free_cpumask_var(cmask); + + return 0; +} + /* * Only if 'ecc_enable_override' is set AND BIOS had ECC disabled, do "we" * enable it. @@ -2625,24 +2574,16 @@ static int amd64_init_csrows(struct mem_ctl_info *mci) static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci) { struct amd64_pvt *pvt = mci->pvt_info; - const cpumask_t *cpumask = cpumask_of_node(pvt->mc_node_id); - int cpu, idx = 0, err = 0; - struct msr msrs[cpumask_weight(cpumask)]; - u32 value; - u32 mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; + u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; if (!ecc_enable_override) return; - memset(msrs, 0, sizeof(msrs)); - amd64_printk(KERN_WARNING, "'ecc_enable_override' parameter is active, " "Enabling AMD ECC hardware now: CAUTION\n"); - err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCTL, &value); - if (err) - debugf0("Reading K8_NBCTL failed\n"); + amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCTL, &value); /* turn on UECCn and CECCEn bits */ pvt->old_nbctl = value & mask; @@ -2651,20 +2592,11 @@ static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci) value |= mask; pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value); - rdmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs); + if (amd64_toggle_ecc_err_reporting(pvt, ON)) + amd64_printk(KERN_WARNING, "Error enabling ECC reporting over " + "MCGCTL!\n"); - for_each_cpu(cpu, cpumask) { - if (msrs[idx].l & K8_MSR_MCGCTL_NBE) - set_bit(idx, &pvt->old_mcgctl); - - msrs[idx].l |= K8_MSR_MCGCTL_NBE; - idx++; - } - wrmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs); - - err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &value); - if (err) - debugf0("Reading K8_NBCFG failed\n"); + amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value); debugf0("NBCFG(1)= 0x%x CHIPKILL= %s ECC_ENABLE= %s\n", value, (value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", @@ -2679,9 +2611,7 @@ static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci) value |= K8_NBCFG_ECC_ENABLE; pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCFG, value); - err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &value); - if (err) - debugf0("Reading K8_NBCFG failed\n"); + amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value); if (!(value & K8_NBCFG_ECC_ENABLE)) { amd64_printk(KERN_WARNING, @@ -2701,86 +2631,21 @@ static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci) static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt) { - const cpumask_t *cpumask = cpumask_of_node(pvt->mc_node_id); - int cpu, idx = 0, err = 0; - struct msr msrs[cpumask_weight(cpumask)]; - u32 value; - u32 mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; + u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; if (!pvt->nbctl_mcgctl_saved) return; - memset(msrs, 0, sizeof(msrs)); - - err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCTL, &value); - if (err) - debugf0("Reading K8_NBCTL failed\n"); + amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCTL, &value); value &= ~mask; value |= pvt->old_nbctl; /* restore the NB Enable MCGCTL bit */ pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value); - rdmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs); - - for_each_cpu(cpu, cpumask) { - msrs[idx].l &= ~K8_MSR_MCGCTL_NBE; - msrs[idx].l |= - test_bit(idx, &pvt->old_mcgctl) << K8_MSR_MCGCTL_NBE; - idx++; - } - - wrmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs); -} - -/* get all cores on this DCT */ -static void get_cpus_on_this_dct_cpumask(cpumask_t *mask, int nid) -{ - int cpu; - - for_each_online_cpu(cpu) - if (amd_get_nb_id(cpu) == nid) - cpumask_set_cpu(cpu, mask); -} - -/* check MCG_CTL on all the cpus on this node */ -static bool amd64_nb_mce_bank_enabled_on_node(int nid) -{ - cpumask_t mask; - struct msr *msrs; - int cpu, nbe, idx = 0; - bool ret = false; - - cpumask_clear(&mask); - - get_cpus_on_this_dct_cpumask(&mask, nid); - - msrs = kzalloc(sizeof(struct msr) * cpumask_weight(&mask), GFP_KERNEL); - if (!msrs) { - amd64_printk(KERN_WARNING, "%s: error allocating msrs\n", - __func__); - return false; - } - - rdmsr_on_cpus(&mask, MSR_IA32_MCG_CTL, msrs); - - for_each_cpu(cpu, &mask) { - nbe = msrs[idx].l & K8_MSR_MCGCTL_NBE; - - debugf0("core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n", - cpu, msrs[idx].q, - (nbe ? "enabled" : "disabled")); - - if (!nbe) - goto out; - - idx++; - } - ret = true; - -out: - kfree(msrs); - return ret; + if (amd64_toggle_ecc_err_reporting(pvt, OFF)) + amd64_printk(KERN_WARNING, "Error restoring ECC reporting over " + "MCGCTL!\n"); } /* @@ -2797,13 +2662,10 @@ static const char *ecc_warning = static int amd64_check_ecc_enabled(struct amd64_pvt *pvt) { u32 value; - int err = 0; u8 ecc_enabled = 0; bool nb_mce_en = false; - err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &value); - if (err) - debugf0("Reading K8_NBCTL failed\n"); + amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value); ecc_enabled = !!(value & K8_NBCFG_ECC_ENABLE); if (!ecc_enabled) @@ -2909,7 +2771,6 @@ static int amd64_probe_one_instance(struct pci_dev *dram_f2_ctl, pvt->ext_model = boot_cpu_data.x86_model >> 4; pvt->mc_type_index = mc_type_index; pvt->ops = family_ops(mc_type_index); - pvt->old_mcgctl = 0; /* * We have the dram_f2_ctl device as an argument, now go reserve its @@ -2959,17 +2820,10 @@ static int amd64_init_2nd_stage(struct amd64_pvt *pvt) { int node_id = pvt->mc_node_id; struct mem_ctl_info *mci; - int ret, err = 0; + int ret = -ENODEV; amd64_read_mc_registers(pvt); - ret = -ENODEV; - if (pvt->ops->probe_valid_hardware) { - err = pvt->ops->probe_valid_hardware(pvt); - if (err) - goto err_exit; - } - /* * We need to determine how many memory channels there are. Then use * that information for calculating the size of the dynamic instance @@ -3165,6 +3019,8 @@ static int __init amd64_edac_init(void) if (cache_k8_northbridges() < 0) return err; + msrs = msrs_alloc(); + err = pci_register_driver(&amd64_pci_driver); if (err) return err; @@ -3200,6 +3056,9 @@ static void __exit amd64_edac_exit(void) edac_pci_release_generic_ctl(amd64_ctl_pci); pci_unregister_driver(&amd64_pci_driver); + + msrs_free(msrs); + msrs = NULL; } module_init(amd64_edac_init); diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index c6f359a85207e24552baac189270cb3702173b51..41bc561e5981feaafc6091a7dd5c849199fbfdbd 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -129,24 +129,22 @@ * sections 3.5.4 and 3.5.5 for more information. */ -#define EDAC_AMD64_VERSION " Ver: 3.2.0 " __DATE__ +#define EDAC_AMD64_VERSION " Ver: 3.3.0 " __DATE__ #define EDAC_MOD_STR "amd64_edac" #define EDAC_MAX_NUMNODES 8 /* Extended Model from CPUID, for CPU Revision numbers */ -#define OPTERON_CPU_LE_REV_C 0 -#define OPTERON_CPU_REV_D 1 -#define OPTERON_CPU_REV_E 2 - -/* NPT processors have the following Extended Models */ -#define OPTERON_CPU_REV_F 4 -#define OPTERON_CPU_REV_FA 5 +#define K8_REV_D 1 +#define K8_REV_E 2 +#define K8_REV_F 4 /* Hardware limit on ChipSelect rows per MC and processors per system */ #define MAX_CS_COUNT 8 #define DRAM_REG_COUNT 8 +#define ON true +#define OFF false /* * PCI-defined configuration space registers @@ -241,7 +239,7 @@ #define F10_DCHR_1 0x194 #define F10_DCHR_FOUR_RANK_DIMM BIT(18) -#define F10_DCHR_Ddr3Mode BIT(8) +#define DDR3_MODE BIT(8) #define F10_DCHR_MblMode BIT(6) @@ -382,14 +380,9 @@ enum { #define K8_NBCAP_CORES (BIT(12)|BIT(13)) #define K8_NBCAP_CHIPKILL BIT(4) #define K8_NBCAP_SECDED BIT(3) -#define K8_NBCAP_8_NODE BIT(2) -#define K8_NBCAP_DUAL_NODE BIT(1) #define K8_NBCAP_DCT_DUAL BIT(0) -/* - * MSR Regs - */ -#define K8_MSR_MCGCTL 0x017b +/* MSRs */ #define K8_MSR_MCGCTL_NBE BIT(4) #define K8_MSR_MC4CTL 0x0410 @@ -487,7 +480,6 @@ struct amd64_pvt { /* Save old hw registers' values before we modified them */ u32 nbctl_mcgctl_saved; /* When true, following 2 are valid */ u32 old_nbctl; - unsigned long old_mcgctl; /* per core on this node */ /* MC Type Index value: socket F vs Family 10h */ u32 mc_type_index; @@ -495,6 +487,7 @@ struct amd64_pvt { /* misc settings */ struct flags { unsigned long cf8_extcfg:1; + unsigned long ecc_report:1; } flags; }; @@ -504,7 +497,6 @@ struct scrubrate { }; extern struct scrubrate scrubrates[23]; -extern u32 revf_quad_ddr2_shift[16]; extern const char *tt_msgs[4]; extern const char *ll_msgs[4]; extern const char *rrrr_msgs[16]; @@ -534,17 +526,15 @@ extern struct mcidev_sysfs_attribute amd64_dbg_attrs[NUM_DBG_ATTRS], * functions and per device encoding/decoding logic. */ struct low_ops { - int (*probe_valid_hardware)(struct amd64_pvt *pvt); - int (*early_channel_count)(struct amd64_pvt *pvt); - - u64 (*get_error_address)(struct mem_ctl_info *mci, - struct err_regs *info); - void (*read_dram_base_limit)(struct amd64_pvt *pvt, int dram); - void (*read_dram_ctl_register)(struct amd64_pvt *pvt); - void (*map_sysaddr_to_csrow)(struct mem_ctl_info *mci, - struct err_regs *info, - u64 SystemAddr); - int (*dbam_map_to_pages)(struct amd64_pvt *pvt, int dram_map); + int (*early_channel_count) (struct amd64_pvt *pvt); + + u64 (*get_error_address) (struct mem_ctl_info *mci, + struct err_regs *info); + void (*read_dram_base_limit) (struct amd64_pvt *pvt, int dram); + void (*read_dram_ctl_register) (struct amd64_pvt *pvt); + void (*map_sysaddr_to_csrow) (struct mem_ctl_info *mci, + struct err_regs *info, u64 SystemAddr); + int (*dbam_to_cs) (struct amd64_pvt *pvt, int cs_mode); }; struct amd64_family_type { @@ -566,6 +556,22 @@ static inline struct low_ops *family_ops(int index) return &amd64_family_types[index].ops; } +static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset, + u32 *val, const char *func) +{ + int err = 0; + + err = pci_read_config_dword(pdev, offset, val); + if (err) + amd64_printk(KERN_WARNING, "%s: error reading F%dx%x.\n", + func, PCI_FUNC(pdev->devfn), offset); + + return err; +} + +#define amd64_read_pci_cfg(pdev, offset, val) \ + amd64_read_pci_cfg_dword(pdev, offset, val, __func__) + /* * For future CPU versions, verify the following as new 'slow' rates appear and * modify the necessary skip values for the supported CPU. diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 12f355cafdbedf780283d64efe56bdb0a1a684fc..001b2e797fb383a3c4f43f805a160d2bffc3b9d6 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -74,6 +74,7 @@ #ifdef CONFIG_EDAC_DEBUG extern int edac_debug_level; +extern const char *edac_mem_types[]; #ifndef CONFIG_EDAC_DEBUG_VERBOSE #define edac_debug_printk(level, fmt, arg...) \ diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index b629c41756f0324b348827cb1e1975d1cdefe7c9..3630308e7b811a66f398193eae71cc12f5d7383f 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -76,6 +76,30 @@ static void edac_mc_dump_mci(struct mem_ctl_info *mci) debugf3("\tpvt_info = %p\n\n", mci->pvt_info); } +/* + * keep those in sync with the enum mem_type + */ +const char *edac_mem_types[] = { + "Empty csrow", + "Reserved csrow type", + "Unknown csrow type", + "Fast page mode RAM", + "Extended data out RAM", + "Burst Extended data out RAM", + "Single data rate SDRAM", + "Registered single data rate SDRAM", + "Double data rate SDRAM", + "Registered Double data rate SDRAM", + "Rambus DRAM", + "Unbuffered DDR2 RAM", + "Fully buffered DDR2", + "Registered DDR2 RAM", + "Rambus XDR", + "Unbuffered DDR3 RAM", + "Registered DDR3 RAM", +}; +EXPORT_SYMBOL_GPL(edac_mem_types); + #endif /* CONFIG_EDAC_DEBUG */ /* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'. diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c index 689cc6a6214df3b2f9aecb04aedabeaa2779955d..c693fcc2213c67181126df50168071f1b0210413 100644 --- a/drivers/edac/edac_mce_amd.c +++ b/drivers/edac/edac_mce_amd.c @@ -306,7 +306,7 @@ void amd_decode_nb_mce(int node_id, struct err_regs *regs, int handle_errors) * value encoding has changed so interpret those differently */ if ((boot_cpu_data.x86 == 0x10) && - (boot_cpu_data.x86_model > 8)) { + (boot_cpu_data.x86_model > 7)) { if (regs->nbsh & K8_NBSH_ERR_CPU_VAL) pr_cont(", core: %u\n", (u8)(regs->nbsh & 0xf)); } else { diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index ae4556f0c0c14aac573610566764230d77333321..96768e160866a55ac4e2a1a5ef1fdd412c2133f2 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2218,6 +2218,13 @@ static int ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, page = payload >> PAGE_SHIFT; offset = payload & ~PAGE_MASK; rest = p->payload_length; + /* + * The controllers I've tested have not worked correctly when + * second_req_count is zero. Rather than do something we know won't + * work, return an error + */ + if (rest == 0) + return -EINVAL; /* FIXME: make packet-per-buffer/dual-buffer a context option */ while (rest > 0) { @@ -2271,7 +2278,7 @@ static int ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, unsigned long payload) { struct iso_context *ctx = container_of(base, struct iso_context, base); - struct descriptor *d = NULL, *pd = NULL; + struct descriptor *d, *pd; struct fw_iso_packet *p = packet; dma_addr_t d_bus, page_bus; u32 z, header_z, rest; @@ -2309,8 +2316,9 @@ static int ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, d->data_address = cpu_to_le32(d_bus + (z * sizeof(*d))); rest = payload_per_buffer; + pd = d; for (j = 1; j < z; j++) { - pd = d + j; + pd++; pd->control = cpu_to_le16(DESCRIPTOR_STATUS | DESCRIPTOR_INPUT_MORE); diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index b4704e150b284cd6347e30585759aeae1fc3af63..b3a0cf57442e440c55d6da83f6213969715448a5 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -544,9 +544,12 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) { rbu_data.entry_created = 0; - if (!fw || !fw->size) + if (!fw) return; + if (!fw->size) + goto out; + spin_lock(&rbu_data.lock); if (!strcmp(image_type, "mono")) { if (!img_update_realloc(fw->size)) @@ -568,6 +571,8 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) } else pr_debug("invalid image type specified.\n"); spin_unlock(&rbu_data.lock); + out: + release_firmware(fw); } static ssize_t read_rbu_image_type(struct kobject *kobj, @@ -615,7 +620,7 @@ static ssize_t write_rbu_image_type(struct kobject *kobj, spin_unlock(&rbu_data.lock); req_firm_rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, "dell_rbu", - &rbu_device->dev, &context, + &rbu_device->dev, GFP_KERNEL, &context, callbackfn_rbu); if (req_firm_rc) { printk(KERN_ERR diff --git a/drivers/gpio/adp5520-gpio.c b/drivers/gpio/adp5520-gpio.c index ad05bbc7ffd5ad98705d8ab6c349f5004cfd7b3a..0f93105873cd263b61bb9c2af47007622e6c2f33 100644 --- a/drivers/gpio/adp5520-gpio.c +++ b/drivers/gpio/adp5520-gpio.c @@ -34,9 +34,9 @@ static int adp5520_gpio_get_value(struct gpio_chip *chip, unsigned off) */ if (test_bit(off, &dev->output)) - adp5520_read(dev->master, GPIO_OUT, ®_val); + adp5520_read(dev->master, ADP5520_GPIO_OUT, ®_val); else - adp5520_read(dev->master, GPIO_IN, ®_val); + adp5520_read(dev->master, ADP5520_GPIO_IN, ®_val); return !!(reg_val & dev->lut[off]); } @@ -48,9 +48,9 @@ static void adp5520_gpio_set_value(struct gpio_chip *chip, dev = container_of(chip, struct adp5520_gpio, gpio_chip); if (val) - adp5520_set_bits(dev->master, GPIO_OUT, dev->lut[off]); + adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]); else - adp5520_clr_bits(dev->master, GPIO_OUT, dev->lut[off]); + adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]); } static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off) @@ -60,7 +60,8 @@ static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off) clear_bit(off, &dev->output); - return adp5520_clr_bits(dev->master, GPIO_CFG_2, dev->lut[off]); + return adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_2, + dev->lut[off]); } static int adp5520_gpio_direction_output(struct gpio_chip *chip, @@ -73,18 +74,21 @@ static int adp5520_gpio_direction_output(struct gpio_chip *chip, set_bit(off, &dev->output); if (val) - ret |= adp5520_set_bits(dev->master, GPIO_OUT, dev->lut[off]); + ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, + dev->lut[off]); else - ret |= adp5520_clr_bits(dev->master, GPIO_OUT, dev->lut[off]); + ret |= adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, + dev->lut[off]); - ret |= adp5520_set_bits(dev->master, GPIO_CFG_2, dev->lut[off]); + ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_CFG_2, + dev->lut[off]); return ret; } static int __devinit adp5520_gpio_probe(struct platform_device *pdev) { - struct adp5520_gpio_platfrom_data *pdata = pdev->dev.platform_data; + struct adp5520_gpio_platform_data *pdata = pdev->dev.platform_data; struct adp5520_gpio *dev; struct gpio_chip *gc; int ret, i, gpios; @@ -129,20 +133,20 @@ static int __devinit adp5520_gpio_probe(struct platform_device *pdev) gc->label = pdev->name; gc->owner = THIS_MODULE; - ret = adp5520_clr_bits(dev->master, GPIO_CFG_1, + ret = adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_1, pdata->gpio_en_mask); - if (pdata->gpio_en_mask & GPIO_C3) - ctl_mask |= C3_MODE; + if (pdata->gpio_en_mask & ADP5520_GPIO_C3) + ctl_mask |= ADP5520_C3_MODE; - if (pdata->gpio_en_mask & GPIO_R3) - ctl_mask |= R3_MODE; + if (pdata->gpio_en_mask & ADP5520_GPIO_R3) + ctl_mask |= ADP5520_R3_MODE; if (ctl_mask) - ret = adp5520_set_bits(dev->master, LED_CONTROL, + ret = adp5520_set_bits(dev->master, ADP5520_LED_CONTROL, ctl_mask); - ret |= adp5520_set_bits(dev->master, GPIO_PULLUP, + ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_PULLUP, pdata->gpio_pullup_mask); if (ret) { diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c index 49384a7c54920399e2d629d3e87b6986b3a964eb..7fe881e2bdfb7c4cb5044b12bb9b5160ba8d47a4 100644 --- a/drivers/gpio/twl4030-gpio.c +++ b/drivers/gpio/twl4030-gpio.c @@ -34,7 +34,7 @@ #include #include -#include +#include /* @@ -80,7 +80,7 @@ static unsigned int gpio_usage_count; */ static inline int gpio_twl4030_write(u8 address, u8 data) { - return twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, data, address); + return twl_i2c_write_u8(TWL4030_MODULE_GPIO, data, address); } /*----------------------------------------------------------------------*/ @@ -117,7 +117,7 @@ static inline int gpio_twl4030_read(u8 address) u8 data; int ret = 0; - ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address); + ret = twl_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address); return (ret < 0) ? ret : data; } @@ -142,7 +142,7 @@ static void twl4030_led_set_value(int led, int value) cached_leden &= ~mask; else cached_leden |= mask; - status = twl4030_i2c_write_u8(TWL4030_MODULE_LED, cached_leden, + status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden, TWL4030_LED_LEDEN); mutex_unlock(&gpio_lock); } @@ -223,23 +223,23 @@ static int twl_request(struct gpio_chip *chip, unsigned offset) } /* initialize PWM to always-drive */ - status = twl4030_i2c_write_u8(module, 0x7f, + status = twl_i2c_write_u8(module, 0x7f, TWL4030_PWMx_PWMxOFF); if (status < 0) goto done; - status = twl4030_i2c_write_u8(module, 0x7f, + status = twl_i2c_write_u8(module, 0x7f, TWL4030_PWMx_PWMxON); if (status < 0) goto done; /* init LED to not-driven (high) */ module = TWL4030_MODULE_LED; - status = twl4030_i2c_read_u8(module, &cached_leden, + status = twl_i2c_read_u8(module, &cached_leden, TWL4030_LED_LEDEN); if (status < 0) goto done; cached_leden &= ~ledclr_mask; - status = twl4030_i2c_write_u8(module, cached_leden, + status = twl_i2c_write_u8(module, cached_leden, TWL4030_LED_LEDEN); if (status < 0) goto done; @@ -370,7 +370,7 @@ static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs) message[i] = bit_mask; } - return twl4030_i2c_write(TWL4030_MODULE_GPIO, message, + return twl_i2c_write(TWL4030_MODULE_GPIO, message, REG_GPIOPUPDCTR1, 5); } @@ -387,7 +387,7 @@ static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd) debounce >>= 8; message[3] = (debounce & 0x03); - return twl4030_i2c_write(TWL4030_MODULE_GPIO, message, + return twl_i2c_write(TWL4030_MODULE_GPIO, message, REG_GPIO_DEBEN1, 3); } diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/wm831x-gpio.c index f9c09a54ec7fb66047bed59fcb4fc5548cee9b2c..b4468b616890ea07ee7058366950047b5aebc89d 100644 --- a/drivers/gpio/wm831x-gpio.c +++ b/drivers/gpio/wm831x-gpio.c @@ -22,8 +22,7 @@ #include #include #include - -#define WM831X_GPIO_MAX 16 +#include struct wm831x_gpio { struct wm831x *wm831x; @@ -80,6 +79,17 @@ static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) value << offset); } +static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); + struct wm831x *wm831x = wm831x_gpio->wm831x; + + if (!wm831x->irq_base) + return -EINVAL; + + return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset; +} + #ifdef CONFIG_DEBUG_FS static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) { @@ -175,6 +185,7 @@ static struct gpio_chip template_chip = { .get = wm831x_gpio_get, .direction_output = wm831x_gpio_direction_out, .set = wm831x_gpio_set, + .to_irq = wm831x_gpio_to_irq, .dbg_show = wm831x_gpio_dbg_show, .can_sleep = 1, }; @@ -192,7 +203,7 @@ static int __devinit wm831x_gpio_probe(struct platform_device *pdev) wm831x_gpio->wm831x = wm831x; wm831x_gpio->gpio_chip = template_chip; - wm831x_gpio->gpio_chip.ngpio = WM831X_GPIO_MAX; + wm831x_gpio->gpio_chip.ngpio = wm831x->num_gpio; wm831x_gpio->gpio_chip.dev = &pdev->dev; if (pdata && pdata->gpio_base) wm831x_gpio->gpio_chip.base = pdata->gpio_base; diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 3c8827a7aabd35a962a16cdcd245f2be03c7608b..470ef6779db33d11e2bcbc60610f8671c34d10ef 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -15,7 +15,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ drm-$(CONFIG_COMPAT) += drm_ioc32.o -drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o +drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o @@ -31,3 +31,5 @@ obj-$(CONFIG_DRM_I915) += i915/ obj-$(CONFIG_DRM_SIS) += sis/ obj-$(CONFIG_DRM_SAVAGE)+= savage/ obj-$(CONFIG_DRM_VIA) +=via/ +obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/ +obj-y += i2c/ diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3f7c500b2115a180e76a773adec19491f0120b06..5124401f266a168ea5202acfe24684ae9a339b1a 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -125,6 +125,15 @@ static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, drm_tv_subconnector_enum_list) +static struct drm_prop_enum_list drm_dirty_info_enum_list[] = { + { DRM_MODE_DIRTY_OFF, "Off" }, + { DRM_MODE_DIRTY_ON, "On" }, + { DRM_MODE_DIRTY_ANNOTATE, "Annotate" }, +}; + +DRM_ENUM_NAME_FN(drm_get_dirty_info_name, + drm_dirty_info_enum_list) + struct drm_conn_prop_enum_list { int type; char *name; @@ -247,7 +256,8 @@ static void drm_mode_object_put(struct drm_device *dev, mutex_unlock(&dev->mode_config.idr_mutex); } -void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) +struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, + uint32_t id, uint32_t type) { struct drm_mode_object *obj = NULL; @@ -801,6 +811,36 @@ int drm_mode_create_dithering_property(struct drm_device *dev) } EXPORT_SYMBOL(drm_mode_create_dithering_property); +/** + * drm_mode_create_dirty_property - create dirty property + * @dev: DRM device + * + * Called by a driver the first time it's needed, must be attached to desired + * connectors. + */ +int drm_mode_create_dirty_info_property(struct drm_device *dev) +{ + struct drm_property *dirty_info; + int i; + + if (dev->mode_config.dirty_info_property) + return 0; + + dirty_info = + drm_property_create(dev, DRM_MODE_PROP_ENUM | + DRM_MODE_PROP_IMMUTABLE, + "dirty", + ARRAY_SIZE(drm_dirty_info_enum_list)); + for (i = 0; i < ARRAY_SIZE(drm_dirty_info_enum_list); i++) + drm_property_add_enum(dirty_info, i, + drm_dirty_info_enum_list[i].type, + drm_dirty_info_enum_list[i].name); + dev->mode_config.dirty_info_property = dirty_info; + + return 0; +} +EXPORT_SYMBOL(drm_mode_create_dirty_info_property); + /** * drm_mode_config_init - initialize DRM mode_configuration structure * @dev: DRM device @@ -1753,6 +1793,71 @@ out: return ret; } +int drm_mode_dirtyfb_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_clip_rect __user *clips_ptr; + struct drm_clip_rect *clips = NULL; + struct drm_mode_fb_dirty_cmd *r = data; + struct drm_mode_object *obj; + struct drm_framebuffer *fb; + unsigned flags; + int num_clips; + int ret = 0; + + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); + if (!obj) { + DRM_ERROR("invalid framebuffer id\n"); + ret = -EINVAL; + goto out_err1; + } + fb = obj_to_fb(obj); + + num_clips = r->num_clips; + clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr; + + if (!num_clips != !clips_ptr) { + ret = -EINVAL; + goto out_err1; + } + + flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags; + + /* If userspace annotates copy, clips must come in pairs */ + if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) { + ret = -EINVAL; + goto out_err1; + } + + if (num_clips && clips_ptr) { + clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); + if (!clips) { + ret = -ENOMEM; + goto out_err1; + } + + ret = copy_from_user(clips, clips_ptr, + num_clips * sizeof(*clips)); + if (ret) + goto out_err2; + } + + if (fb->funcs->dirty) { + ret = fb->funcs->dirty(fb, flags, r->color, clips, num_clips); + } else { + ret = -ENOSYS; + goto out_err2; + } + +out_err2: + kfree(clips); +out_err1: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + + /** * drm_fb_release - remove and free the FBs on this file * @filp: file * from the ioctl @@ -2478,3 +2583,72 @@ out: mutex_unlock(&dev->mode_config.mutex); return ret; } + +int drm_mode_page_flip_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_crtc_page_flip *page_flip = data; + struct drm_mode_object *obj; + struct drm_crtc *crtc; + struct drm_framebuffer *fb; + struct drm_pending_vblank_event *e = NULL; + unsigned long flags; + int ret = -EINVAL; + + if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || + page_flip->reserved != 0) + return -EINVAL; + + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) + goto out; + crtc = obj_to_crtc(obj); + + if (crtc->funcs->page_flip == NULL) + goto out; + + obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB); + if (!obj) + goto out; + fb = obj_to_fb(obj); + + if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { + ret = -ENOMEM; + spin_lock_irqsave(&dev->event_lock, flags); + if (file_priv->event_space < sizeof e->event) { + spin_unlock_irqrestore(&dev->event_lock, flags); + goto out; + } + file_priv->event_space -= sizeof e->event; + spin_unlock_irqrestore(&dev->event_lock, flags); + + e = kzalloc(sizeof *e, GFP_KERNEL); + if (e == NULL) { + spin_lock_irqsave(&dev->event_lock, flags); + file_priv->event_space += sizeof e->event; + spin_unlock_irqrestore(&dev->event_lock, flags); + goto out; + } + + e->event.base.type = DRM_EVENT_FLIP_COMPLETE; + e->event.base.length = sizeof e->event; + e->event.user_data = page_flip->user_data; + e->base.event = &e->event.base; + e->base.file_priv = file_priv; + e->base.destroy = + (void (*) (struct drm_pending_event *)) kfree; + } + + ret = crtc->funcs->page_flip(crtc, fb, e); + if (ret) { + spin_lock_irqsave(&dev->event_lock, flags); + file_priv->event_space += sizeof e->event; + spin_unlock_irqrestore(&dev->event_lock, flags); + kfree(e); + } + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index bbfd110a71684079a2ff5fcd0afc791e23a2a365..4231d6db72ec41dd0556d506f7a6d96c426b6c3c 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -109,7 +109,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, count = (*connector_funcs->get_modes)(connector); if (!count) { - count = drm_add_modes_noedid(connector, 800, 600); + count = drm_add_modes_noedid(connector, 1024, 768); if (!count) return 0; } @@ -1020,6 +1020,9 @@ bool drm_helper_initial_config(struct drm_device *dev) { int count = 0; + /* disable all the possible outputs/crtcs before entering KMS mode */ + drm_helper_disable_unused_functions(dev); + drm_fb_helper_parse_command_line(dev); count = drm_helper_probe_connector_modes(dev, diff --git a/drivers/gpu/drm/i915/intel_dp_i2c.c b/drivers/gpu/drm/drm_dp_i2c_helper.c similarity index 79% rename from drivers/gpu/drm/i915/intel_dp_i2c.c rename to drivers/gpu/drm/drm_dp_i2c_helper.c index a63b6f57d2d4eccf9b22f9cb2bd4c0d1cb229d44..548887c8506fa018139c2d83b29a50fd90c2b436 100644 --- a/drivers/gpu/drm/i915/intel_dp_i2c.c +++ b/drivers/gpu/drm/drm_dp_i2c_helper.c @@ -28,84 +28,20 @@ #include #include #include -#include "intel_dp.h" +#include "drm_dp_helper.h" #include "drmP.h" /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ - -#define MODE_I2C_START 1 -#define MODE_I2C_WRITE 2 -#define MODE_I2C_READ 4 -#define MODE_I2C_STOP 8 - static int i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, uint8_t write_byte, uint8_t *read_byte) { struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; - uint16_t address = algo_data->address; - uint8_t msg[5]; - uint8_t reply[2]; - int msg_bytes; - int reply_bytes; int ret; - - /* Set up the command byte */ - if (mode & MODE_I2C_READ) - msg[0] = AUX_I2C_READ << 4; - else - msg[0] = AUX_I2C_WRITE << 4; - - if (!(mode & MODE_I2C_STOP)) - msg[0] |= AUX_I2C_MOT << 4; - - msg[1] = address >> 8; - msg[2] = address; - - switch (mode) { - case MODE_I2C_WRITE: - msg[3] = 0; - msg[4] = write_byte; - msg_bytes = 5; - reply_bytes = 1; - break; - case MODE_I2C_READ: - msg[3] = 0; - msg_bytes = 4; - reply_bytes = 2; - break; - default: - msg_bytes = 3; - reply_bytes = 1; - break; - } - - for (;;) { - ret = (*algo_data->aux_ch)(adapter, - msg, msg_bytes, - reply, reply_bytes); - if (ret < 0) { - DRM_DEBUG("aux_ch failed %d\n", ret); - return ret; - } - switch (reply[0] & AUX_I2C_REPLY_MASK) { - case AUX_I2C_REPLY_ACK: - if (mode == MODE_I2C_READ) { - *read_byte = reply[1]; - } - return reply_bytes - 1; - case AUX_I2C_REPLY_NACK: - DRM_DEBUG("aux_ch nack\n"); - return -EREMOTEIO; - case AUX_I2C_REPLY_DEFER: - DRM_DEBUG("aux_ch defer\n"); - udelay(100); - break; - default: - DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]); - return -EREMOTEIO; - } - } + + ret = (*algo_data->aux_ch)(adapter, mode, + write_byte, read_byte); + return ret; } /* @@ -224,7 +160,7 @@ i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter, if (ret >= 0) ret = num; i2c_algo_dp_aux_stop(adapter, reading); - DRM_DEBUG("dp_aux_xfer return %d\n", ret); + DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret); return ret; } diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index a75ca63deea65c09d5b5b0d46265daf9482157fe..ff2f1042cb44f96c39ecc260e51f3eeff4126fea 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -145,6 +145,8 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW) }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) @@ -365,6 +367,29 @@ static void __exit drm_core_exit(void) module_init(drm_core_init); module_exit(drm_core_exit); +/** + * Copy and IOCTL return string to user space + */ +static int drm_copy_field(char *buf, size_t *buf_len, const char *value) +{ + int len; + + /* don't overflow userbuf */ + len = strlen(value); + if (len > *buf_len) + len = *buf_len; + + /* let userspace know exact length of driver value (which could be + * larger than the userspace-supplied buffer) */ + *buf_len = strlen(value); + + /* finally, try filling in the userbuf */ + if (len && buf) + if (copy_to_user(buf, value, len)) + return -EFAULT; + return 0; +} + /** * Get version information * @@ -380,16 +405,21 @@ static int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_version *version = data; - int len; + int err; version->version_major = dev->driver->major; version->version_minor = dev->driver->minor; version->version_patchlevel = dev->driver->patchlevel; - DRM_COPY(version->name, dev->driver->name); - DRM_COPY(version->date, dev->driver->date); - DRM_COPY(version->desc, dev->driver->desc); - - return 0; + err = drm_copy_field(version->name, &version->name_len, + dev->driver->name); + if (!err) + err = drm_copy_field(version->date, &version->date_len, + dev->driver->date); + if (!err) + err = drm_copy_field(version->desc, &version->desc_len, + dev->driver->desc); + + return err; } /** diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index b54ba63d506e0350abbf53acd50420cbeb79f7c3..c39b26f1abed050aed19d27407d1890035bd17d9 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -123,18 +123,20 @@ static const u8 edid_header[] = { */ static bool edid_is_valid(struct edid *edid) { - int i; + int i, score = 0; u8 csum = 0; u8 *raw_edid = (u8 *)edid; - if (memcmp(edid->header, edid_header, sizeof(edid_header))) - goto bad; - if (edid->version != 1) { - DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); + for (i = 0; i < sizeof(edid_header); i++) + if (raw_edid[i] == edid_header[i]) + score++; + + if (score == 8) ; + else if (score >= 6) { + DRM_DEBUG("Fixing EDID header, your hardware may be failing\n"); + memcpy(raw_edid, edid_header, sizeof(edid_header)); + } else goto bad; - } - if (edid->revision > 4) - DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n"); for (i = 0; i < EDID_LENGTH; i++) csum += raw_edid[i]; @@ -143,6 +145,14 @@ static bool edid_is_valid(struct edid *edid) goto bad; } + if (edid->version != 1) { + DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); + goto bad; + } + + if (edid->revision > 4) + DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n"); + return 1; bad: @@ -481,16 +491,17 @@ static struct drm_display_mode drm_dmt_modes[] = { 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, }; +static const int drm_num_dmt_modes = + sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); static struct drm_display_mode *drm_find_dmt(struct drm_device *dev, int hsize, int vsize, int fresh) { - int i, count; + int i; struct drm_display_mode *ptr, *mode; - count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); mode = NULL; - for (i = 0; i < count; i++) { + for (i = 0; i < drm_num_dmt_modes; i++) { ptr = &drm_dmt_modes[i]; if (hsize == ptr->hdisplay && vsize == ptr->vdisplay && @@ -834,8 +845,165 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid return modes; } +/* + * XXX fix this for: + * - GTF secondary curve formula + * - EDID 1.4 range offsets + * - CVT extended bits + */ +static bool +mode_in_range(struct drm_display_mode *mode, struct detailed_timing *timing) +{ + struct detailed_data_monitor_range *range; + int hsync, vrefresh; + + range = &timing->data.other_data.data.range; + + hsync = drm_mode_hsync(mode); + vrefresh = drm_mode_vrefresh(mode); + + if (hsync < range->min_hfreq_khz || hsync > range->max_hfreq_khz) + return false; + + if (vrefresh < range->min_vfreq || vrefresh > range->max_vfreq) + return false; + + if (range->pixel_clock_mhz && range->pixel_clock_mhz != 0xff) { + /* be forgiving since it's in units of 10MHz */ + int max_clock = range->pixel_clock_mhz * 10 + 9; + max_clock *= 1000; + if (mode->clock > max_clock) + return false; + } + + return true; +} + +/* + * XXX If drm_dmt_modes ever regrows the CVT-R modes (and it will) this will + * need to account for them. + */ +static int drm_gtf_modes_for_range(struct drm_connector *connector, + struct detailed_timing *timing) +{ + int i, modes = 0; + struct drm_display_mode *newmode; + struct drm_device *dev = connector->dev; + + for (i = 0; i < drm_num_dmt_modes; i++) { + if (mode_in_range(drm_dmt_modes + i, timing)) { + newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]); + if (newmode) { + drm_mode_probed_add(connector, newmode); + modes++; + } + } + } + + return modes; +} + +static int drm_cvt_modes(struct drm_connector *connector, + struct detailed_timing *timing) +{ + int i, j, modes = 0; + struct drm_display_mode *newmode; + struct drm_device *dev = connector->dev; + struct cvt_timing *cvt; + const int rates[] = { 60, 85, 75, 60, 50 }; + + for (i = 0; i < 4; i++) { + int width, height; + cvt = &(timing->data.other_data.data.cvt[i]); + + height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 8) + 1) * 2; + switch (cvt->code[1] & 0xc0) { + case 0x00: + width = height * 4 / 3; + break; + case 0x40: + width = height * 16 / 9; + break; + case 0x80: + width = height * 16 / 10; + break; + case 0xc0: + width = height * 15 / 9; + break; + } + + for (j = 1; j < 5; j++) { + if (cvt->code[2] & (1 << j)) { + newmode = drm_cvt_mode(dev, width, height, + rates[j], j == 0, + false, false); + if (newmode) { + drm_mode_probed_add(connector, newmode); + modes++; + } + } + } + } + + return modes; +} + +static int add_detailed_modes(struct drm_connector *connector, + struct detailed_timing *timing, + struct edid *edid, u32 quirks, int preferred) +{ + int i, modes = 0; + struct detailed_non_pixel *data = &timing->data.other_data; + int timing_level = standard_timing_level(edid); + int gtf = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF); + struct drm_display_mode *newmode; + struct drm_device *dev = connector->dev; + + if (timing->pixel_clock) { + newmode = drm_mode_detailed(dev, edid, timing, quirks); + if (!newmode) + return 0; + + if (preferred) + newmode->type |= DRM_MODE_TYPE_PREFERRED; + + drm_mode_probed_add(connector, newmode); + return 1; + } + + /* other timing types */ + switch (data->type) { + case EDID_DETAIL_MONITOR_RANGE: + if (gtf) + modes += drm_gtf_modes_for_range(connector, timing); + break; + case EDID_DETAIL_STD_MODES: + /* Six modes per detailed section */ + for (i = 0; i < 6; i++) { + struct std_timing *std; + struct drm_display_mode *newmode; + + std = &data->data.timings[i]; + newmode = drm_mode_std(dev, std, edid->revision, + timing_level); + if (newmode) { + drm_mode_probed_add(connector, newmode); + modes++; + } + } + break; + case EDID_DETAIL_CVT_3BYTE: + modes += drm_cvt_modes(connector, timing); + break; + default: + break; + } + + return modes; +} + /** - * add_detailed_modes - get detailed mode info from EDID data + * add_detailed_info - get detailed mode info from EDID data * @connector: attached connector * @edid: EDID block to scan * @quirks: quirks to apply @@ -846,67 +1014,24 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid static int add_detailed_info(struct drm_connector *connector, struct edid *edid, u32 quirks) { - struct drm_device *dev = connector->dev; - int i, j, modes = 0; - int timing_level; - - timing_level = standard_timing_level(edid); + int i, modes = 0; for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { struct detailed_timing *timing = &edid->detailed_timings[i]; - struct detailed_non_pixel *data = &timing->data.other_data; - struct drm_display_mode *newmode; - - /* X server check is version 1.1 or higher */ - if (edid->version == 1 && edid->revision >= 1 && - !timing->pixel_clock) { - /* Other timing or info */ - switch (data->type) { - case EDID_DETAIL_MONITOR_SERIAL: - break; - case EDID_DETAIL_MONITOR_STRING: - break; - case EDID_DETAIL_MONITOR_RANGE: - /* Get monitor range data */ - break; - case EDID_DETAIL_MONITOR_NAME: - break; - case EDID_DETAIL_MONITOR_CPDATA: - break; - case EDID_DETAIL_STD_MODES: - for (j = 0; j < 6; i++) { - struct std_timing *std; - struct drm_display_mode *newmode; - - std = &data->data.timings[j]; - newmode = drm_mode_std(dev, std, - edid->revision, - timing_level); - if (newmode) { - drm_mode_probed_add(connector, newmode); - modes++; - } - } - break; - default: - break; - } - } else { - newmode = drm_mode_detailed(dev, edid, timing, quirks); - if (!newmode) - continue; + int preferred = (i == 0) && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING); - /* First detailed mode is preferred */ - if (i == 0 && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING)) - newmode->type |= DRM_MODE_TYPE_PREFERRED; - drm_mode_probed_add(connector, newmode); + /* In 1.0, only timings are allowed */ + if (!timing->pixel_clock && edid->version == 1 && + edid->revision == 0) + continue; - modes++; - } + modes += add_detailed_modes(connector, timing, edid, quirks, + preferred); } return modes; } + /** * add_detailed_mode_eedid - get detailed mode info from addtional timing * EDID block @@ -920,12 +1045,9 @@ static int add_detailed_info(struct drm_connector *connector, static int add_detailed_info_eedid(struct drm_connector *connector, struct edid *edid, u32 quirks) { - struct drm_device *dev = connector->dev; - int i, j, modes = 0; + int i, modes = 0; char *edid_ext = NULL; struct detailed_timing *timing; - struct detailed_non_pixel *data; - struct drm_display_mode *newmode; int edid_ext_num; int start_offset, end_offset; int timing_level; @@ -976,51 +1098,7 @@ static int add_detailed_info_eedid(struct drm_connector *connector, for (i = start_offset; i < end_offset; i += sizeof(struct detailed_timing)) { timing = (struct detailed_timing *)(edid_ext + i); - data = &timing->data.other_data; - /* Detailed mode timing */ - if (timing->pixel_clock) { - newmode = drm_mode_detailed(dev, edid, timing, quirks); - if (!newmode) - continue; - - drm_mode_probed_add(connector, newmode); - - modes++; - continue; - } - - /* Other timing or info */ - switch (data->type) { - case EDID_DETAIL_MONITOR_SERIAL: - break; - case EDID_DETAIL_MONITOR_STRING: - break; - case EDID_DETAIL_MONITOR_RANGE: - /* Get monitor range data */ - break; - case EDID_DETAIL_MONITOR_NAME: - break; - case EDID_DETAIL_MONITOR_CPDATA: - break; - case EDID_DETAIL_STD_MODES: - /* Five modes per detailed section */ - for (j = 0; j < 5; i++) { - struct std_timing *std; - struct drm_display_mode *newmode; - - std = &data->data.timings[j]; - newmode = drm_mode_std(dev, std, - edid->revision, - timing_level); - if (newmode) { - drm_mode_probed_add(connector, newmode); - modes++; - } - } - break; - default: - break; - } + modes += add_detailed_modes(connector, timing, edid, quirks, 0); } return modes; @@ -1066,19 +1144,19 @@ static int drm_ddc_read_edid(struct drm_connector *connector, struct i2c_adapter *adapter, char *buf, int len) { - int ret; + int i; - ret = drm_do_probe_ddc_edid(adapter, buf, len); - if (ret != 0) { - goto end; - } - if (!edid_is_valid((struct edid *)buf)) { - dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", - drm_get_connector_name(connector)); - ret = -1; + for (i = 0; i < 4; i++) { + if (drm_do_probe_ddc_edid(adapter, buf, len)) + return -1; + if (edid_is_valid((struct edid *)buf)) + return 0; } -end: - return ret; + + /* repeated checksum failures; warn, but carry on */ + dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", + drm_get_connector_name(connector)); + return -1; } /** @@ -1296,6 +1374,8 @@ int drm_add_modes_noedid(struct drm_connector *connector, ptr->vdisplay > vdisplay) continue; } + if (drm_mode_vrefresh(ptr) > 61) + continue; mode = drm_mode_duplicate(dev, ptr); if (mode) { drm_mode_probed_add(connector, mode); diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 65ef011fa8ba093297d9e94983db2d0236d2a842..1b49fa055f4f39c2e8f363793a9feeea902ac105 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -373,11 +373,9 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode) mutex_unlock(&dev->mode_config.mutex); } } - if (dpms_mode == DRM_MODE_DPMS_OFF) { - mutex_lock(&dev->mode_config.mutex); - crtc_funcs->dpms(crtc, dpms_mode); - mutex_unlock(&dev->mode_config.mutex); - } + mutex_lock(&dev->mode_config.mutex); + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); + mutex_unlock(&dev->mode_config.mutex); } } } @@ -385,18 +383,23 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode) int drm_fb_helper_blank(int blank, struct fb_info *info) { switch (blank) { + /* Display: On; HSync: On, VSync: On */ case FB_BLANK_UNBLANK: drm_fb_helper_on(info); break; + /* Display: Off; HSync: On, VSync: On */ case FB_BLANK_NORMAL: - drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY); + drm_fb_helper_off(info, DRM_MODE_DPMS_ON); break; + /* Display: Off; HSync: Off, VSync: On */ case FB_BLANK_HSYNC_SUSPEND: drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY); break; + /* Display: Off; HSync: On, VSync: Off */ case FB_BLANK_VSYNC_SUSPEND: drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND); break; + /* Display: Off; HSync: Off, VSync: Off */ case FB_BLANK_POWERDOWN: drm_fb_helper_off(info, DRM_MODE_DPMS_OFF); break; @@ -905,8 +908,13 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev, if (new_fb) { info->var.pixclock = 0; - if (register_framebuffer(info) < 0) + ret = fb_alloc_cmap(&info->cmap, modeset->crtc->gamma_size, 0); + if (ret) + return ret; + if (register_framebuffer(info) < 0) { + fb_dealloc_cmap(&info->cmap); return -EINVAL; + } } else { drm_fb_helper_set_par(info); } @@ -936,6 +944,7 @@ void drm_fb_helper_free(struct drm_fb_helper *helper) unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); } drm_fb_helper_crtc_free(helper); + fb_dealloc_cmap(&helper->fb->fbdev->cmap); } EXPORT_SYMBOL(drm_fb_helper_free); diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 251bc0e3b5ecd92acbb0244634ca46787bb0284d..08d14df3bb422d41bd561eea171d4cd91a662a3e 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -257,6 +257,9 @@ static int drm_open_helper(struct inode *inode, struct file *filp, INIT_LIST_HEAD(&priv->lhead); INIT_LIST_HEAD(&priv->fbs); + INIT_LIST_HEAD(&priv->event_list); + init_waitqueue_head(&priv->event_wait); + priv->event_space = 4096; /* set aside 4k for event buffer */ if (dev->driver->driver_features & DRIVER_GEM) drm_gem_open(dev, priv); @@ -297,6 +300,18 @@ static int drm_open_helper(struct inode *inode, struct file *filp, goto out_free; } } + mutex_lock(&dev->struct_mutex); + if (dev->driver->master_set) { + ret = dev->driver->master_set(dev, priv, true); + if (ret) { + /* drop both references if this fails */ + drm_master_put(&priv->minor->master); + drm_master_put(&priv->master); + mutex_unlock(&dev->struct_mutex); + goto out_free; + } + } + mutex_unlock(&dev->struct_mutex); } else { /* get a reference to the master */ priv->master = drm_master_get(priv->minor->master); @@ -413,6 +428,30 @@ static void drm_master_release(struct drm_device *dev, struct file *filp) } } +static void drm_events_release(struct drm_file *file_priv) +{ + struct drm_device *dev = file_priv->minor->dev; + struct drm_pending_event *e, *et; + struct drm_pending_vblank_event *v, *vt; + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + + /* Remove pending flips */ + list_for_each_entry_safe(v, vt, &dev->vblank_event_list, base.link) + if (v->base.file_priv == file_priv) { + list_del(&v->base.link); + drm_vblank_put(dev, v->pipe); + v->base.destroy(&v->base); + } + + /* Remove unconsumed events */ + list_for_each_entry_safe(e, et, &file_priv->event_list, link) + e->destroy(e); + + spin_unlock_irqrestore(&dev->event_lock, flags); +} + /** * Release file. * @@ -451,6 +490,8 @@ int drm_release(struct inode *inode, struct file *filp) if (file_priv->minor->master) drm_master_release(dev, filp); + drm_events_release(file_priv); + if (dev->driver->driver_features & DRIVER_GEM) drm_gem_release(dev, file_priv); @@ -504,6 +545,8 @@ int drm_release(struct inode *inode, struct file *filp) if (file_priv->minor->master == file_priv->master) { /* drop the reference held my the minor */ + if (dev->driver->master_drop) + dev->driver->master_drop(dev, file_priv, true); drm_master_put(&file_priv->minor->master); } } @@ -544,9 +587,74 @@ int drm_release(struct inode *inode, struct file *filp) } EXPORT_SYMBOL(drm_release); -/** No-op. */ +static bool +drm_dequeue_event(struct drm_file *file_priv, + size_t total, size_t max, struct drm_pending_event **out) +{ + struct drm_device *dev = file_priv->minor->dev; + struct drm_pending_event *e; + unsigned long flags; + bool ret = false; + + spin_lock_irqsave(&dev->event_lock, flags); + + *out = NULL; + if (list_empty(&file_priv->event_list)) + goto out; + e = list_first_entry(&file_priv->event_list, + struct drm_pending_event, link); + if (e->event->length + total > max) + goto out; + + file_priv->event_space += e->event->length; + list_del(&e->link); + *out = e; + ret = true; + +out: + spin_unlock_irqrestore(&dev->event_lock, flags); + return ret; +} + +ssize_t drm_read(struct file *filp, char __user *buffer, + size_t count, loff_t *offset) +{ + struct drm_file *file_priv = filp->private_data; + struct drm_pending_event *e; + size_t total; + ssize_t ret; + + ret = wait_event_interruptible(file_priv->event_wait, + !list_empty(&file_priv->event_list)); + if (ret < 0) + return ret; + + total = 0; + while (drm_dequeue_event(file_priv, total, count, &e)) { + if (copy_to_user(buffer + total, + e->event, e->event->length)) { + total = -EFAULT; + break; + } + + total += e->event->length; + e->destroy(e); + } + + return total; +} +EXPORT_SYMBOL(drm_read); + unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) { - return 0; + struct drm_file *file_priv = filp->private_data; + unsigned int mask = 0; + + poll_wait(filp, &file_priv->event_wait, wait); + + if (!list_empty(&file_priv->event_list)) + mask |= POLLIN | POLLRDNORM; + + return mask; } EXPORT_SYMBOL(drm_poll); diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 0a6f0b3bdc787eae8c29f54086dcb089f586b5c9..7998ee66b3179889273a87b3c1198ce3d0b41d70 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -429,15 +429,21 @@ int drm_vblank_get(struct drm_device *dev, int crtc) spin_lock_irqsave(&dev->vbl_lock, irqflags); /* Going from 0->1 means we have to enable interrupts again */ - if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 && - !dev->vblank_enabled[crtc]) { - ret = dev->driver->enable_vblank(dev, crtc); - DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); - if (ret) + if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) { + if (!dev->vblank_enabled[crtc]) { + ret = dev->driver->enable_vblank(dev, crtc); + DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); + if (ret) + atomic_dec(&dev->vblank_refcount[crtc]); + else { + dev->vblank_enabled[crtc] = 1; + drm_update_vblank_count(dev, crtc); + } + } + } else { + if (!dev->vblank_enabled[crtc]) { atomic_dec(&dev->vblank_refcount[crtc]); - else { - dev->vblank_enabled[crtc] = 1; - drm_update_vblank_count(dev, crtc); + ret = -EINVAL; } } spin_unlock_irqrestore(&dev->vbl_lock, irqflags); @@ -464,6 +470,18 @@ void drm_vblank_put(struct drm_device *dev, int crtc) } EXPORT_SYMBOL(drm_vblank_put); +void drm_vblank_off(struct drm_device *dev, int crtc) +{ + unsigned long irqflags; + + spin_lock_irqsave(&dev->vbl_lock, irqflags); + DRM_WAKEUP(&dev->vbl_queue[crtc]); + dev->vblank_enabled[crtc] = 0; + dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); +} +EXPORT_SYMBOL(drm_vblank_off); + /** * drm_vblank_pre_modeset - account for vblanks across mode sets * @dev: DRM device @@ -550,6 +568,63 @@ out: return ret; } +static int drm_queue_vblank_event(struct drm_device *dev, int pipe, + union drm_wait_vblank *vblwait, + struct drm_file *file_priv) +{ + struct drm_pending_vblank_event *e; + struct timeval now; + unsigned long flags; + unsigned int seq; + + e = kzalloc(sizeof *e, GFP_KERNEL); + if (e == NULL) + return -ENOMEM; + + e->pipe = pipe; + e->event.base.type = DRM_EVENT_VBLANK; + e->event.base.length = sizeof e->event; + e->event.user_data = vblwait->request.signal; + e->base.event = &e->event.base; + e->base.file_priv = file_priv; + e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; + + do_gettimeofday(&now); + spin_lock_irqsave(&dev->event_lock, flags); + + if (file_priv->event_space < sizeof e->event) { + spin_unlock_irqrestore(&dev->event_lock, flags); + kfree(e); + return -ENOMEM; + } + + file_priv->event_space -= sizeof e->event; + seq = drm_vblank_count(dev, pipe); + if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) && + (seq - vblwait->request.sequence) <= (1 << 23)) { + vblwait->request.sequence = seq + 1; + vblwait->reply.sequence = vblwait->request.sequence; + } + + DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n", + vblwait->request.sequence, seq, pipe); + + e->event.sequence = vblwait->request.sequence; + if ((seq - vblwait->request.sequence) <= (1 << 23)) { + e->event.tv_sec = now.tv_sec; + e->event.tv_usec = now.tv_usec; + drm_vblank_put(dev, e->pipe); + list_add_tail(&e->base.link, &e->base.file_priv->event_list); + wake_up_interruptible(&e->base.file_priv->event_wait); + } else { + list_add_tail(&e->base.link, &dev->vblank_event_list); + } + + spin_unlock_irqrestore(&dev->event_lock, flags); + + return 0; +} + /** * Wait for VBLANK. * @@ -609,6 +684,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data, goto done; } + if (flags & _DRM_VBLANK_EVENT) + return drm_queue_vblank_event(dev, crtc, vblwait, file_priv); + if ((flags & _DRM_VBLANK_NEXTONMISS) && (seq - vblwait->request.sequence) <= (1<<23)) { vblwait->request.sequence = seq + 1; @@ -641,6 +719,38 @@ done: return ret; } +void drm_handle_vblank_events(struct drm_device *dev, int crtc) +{ + struct drm_pending_vblank_event *e, *t; + struct timeval now; + unsigned long flags; + unsigned int seq; + + do_gettimeofday(&now); + seq = drm_vblank_count(dev, crtc); + + spin_lock_irqsave(&dev->event_lock, flags); + + list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { + if (e->pipe != crtc) + continue; + if ((seq - e->event.sequence) > (1<<23)) + continue; + + DRM_DEBUG("vblank event on %d, current %d\n", + e->event.sequence, seq); + + e->event.sequence = seq; + e->event.tv_sec = now.tv_sec; + e->event.tv_usec = now.tv_usec; + drm_vblank_put(dev, e->pipe); + list_move_tail(&e->base.link, &e->base.file_priv->event_list); + wake_up_interruptible(&e->base.file_priv->event_wait); + } + + spin_unlock_irqrestore(&dev->event_lock, flags); +} + /** * drm_handle_vblank - handle a vblank event * @dev: DRM device @@ -651,7 +761,11 @@ done: */ void drm_handle_vblank(struct drm_device *dev, int crtc) { + if (!dev->num_crtcs) + return; + atomic_inc(&dev->_vblank_count[crtc]); DRM_WAKEUP(&dev->vbl_queue[crtc]); + drm_handle_vblank_events(dev, crtc); } EXPORT_SYMBOL(drm_handle_vblank); diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 97dc5a4f0de42604463ac99a7a161c33b2d3550f..d7d7eac3ddd264c1104027fae06f6b48c57fedfb 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -226,6 +226,44 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, } EXPORT_SYMBOL(drm_mm_get_block_generic); +struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node, + unsigned long size, + unsigned alignment, + unsigned long start, + unsigned long end, + int atomic) +{ + struct drm_mm_node *align_splitoff = NULL; + unsigned tmp = 0; + unsigned wasted = 0; + + if (node->start < start) + wasted += start - node->start; + if (alignment) + tmp = ((node->start + wasted) % alignment); + + if (tmp) + wasted += alignment - tmp; + if (wasted) { + align_splitoff = drm_mm_split_at_start(node, wasted, atomic); + if (unlikely(align_splitoff == NULL)) + return NULL; + } + + if (node->size == size) { + list_del_init(&node->fl_entry); + node->free = 0; + } else { + node = drm_mm_split_at_start(node, size, atomic); + } + + if (align_splitoff) + drm_mm_put_block(align_splitoff); + + return node; +} +EXPORT_SYMBOL(drm_mm_get_block_range_generic); + /* * Put a block. Merge with the previous and / or next block if they are free. * Otherwise add to the free stack. @@ -331,6 +369,56 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, } EXPORT_SYMBOL(drm_mm_search_free); +struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, + unsigned long size, + unsigned alignment, + unsigned long start, + unsigned long end, + int best_match) +{ + struct list_head *list; + const struct list_head *free_stack = &mm->fl_entry; + struct drm_mm_node *entry; + struct drm_mm_node *best; + unsigned long best_size; + unsigned wasted; + + best = NULL; + best_size = ~0UL; + + list_for_each(list, free_stack) { + entry = list_entry(list, struct drm_mm_node, fl_entry); + wasted = 0; + + if (entry->size < size) + continue; + + if (entry->start > end || (entry->start+entry->size) < start) + continue; + + if (entry->start < start) + wasted += start - entry->start; + + if (alignment) { + register unsigned tmp = (entry->start + wasted) % alignment; + if (tmp) + wasted += alignment - tmp; + } + + if (entry->size >= size + wasted) { + if (!best_match) + return entry; + if (size < best_size) { + best = entry; + best_size = entry->size; + } + } + } + + return best; +} +EXPORT_SYMBOL(drm_mm_search_free_in_range); + int drm_mm_clean(struct drm_mm * mm) { struct list_head *head = &mm->ml_entry; @@ -381,6 +469,26 @@ void drm_mm_takedown(struct drm_mm * mm) } EXPORT_SYMBOL(drm_mm_takedown); +void drm_mm_debug_table(struct drm_mm *mm, const char *prefix) +{ + struct drm_mm_node *entry; + int total_used = 0, total_free = 0, total = 0; + + list_for_each_entry(entry, &mm->ml_entry, ml_entry) { + printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n", + prefix, entry->start, entry->start + entry->size, + entry->size, entry->free ? "free" : "used"); + total += entry->size; + if (entry->free) + total_free += entry->size; + else + total_used += entry->size; + } + printk(KERN_DEBUG "%s total: %d, used %d free %d\n", prefix, total, + total_used, total_free); +} +EXPORT_SYMBOL(drm_mm_debug_table); + #if defined(CONFIG_DEBUG_FS) int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) { @@ -395,7 +503,7 @@ int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) else total_used += entry->size; } - seq_printf(m, "total: %d, used %d free %d\n", total, total_free, total_used); + seq_printf(m, "total: %d, used %d free %d\n", total, total_used, total_free); return 0; } EXPORT_SYMBOL(drm_mm_dump_table); diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 51f677215f1dbcaa72e3f4ffe25142c32ee9120c..6d81a02463a311c1121a4e6d273e23c32117f824 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -553,6 +553,32 @@ int drm_mode_height(struct drm_display_mode *mode) } EXPORT_SYMBOL(drm_mode_height); +/** drm_mode_hsync - get the hsync of a mode + * @mode: mode + * + * LOCKING: + * None. + * + * Return @modes's hsync rate in kHz, rounded to the nearest int. + */ +int drm_mode_hsync(struct drm_display_mode *mode) +{ + unsigned int calc_val; + + if (mode->hsync) + return mode->hsync; + + if (mode->htotal < 0) + return 0; + + calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */ + calc_val += 500; /* round to 1000Hz */ + calc_val /= 1000; /* truncate to kHz */ + + return calc_val; +} +EXPORT_SYMBOL(drm_mode_hsync); + /** * drm_mode_vrefresh - get the vrefresh of a mode * @mode: mode @@ -560,7 +586,7 @@ EXPORT_SYMBOL(drm_mode_height); * LOCKING: * None. * - * Return @mode's vrefresh rate or calculate it if necessary. + * Return @mode's vrefresh rate in Hz or calculate it if necessary. * * FIXME: why is this needed? shouldn't vrefresh be set already? * diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 55bb8a82d6127cb5d1ec3bea675e0001de593122..ad73e141afdbd8096e2908d75e5849962ae1f069 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -128,6 +128,7 @@ struct drm_master *drm_master_get(struct drm_master *master) kref_get(&master->refcount); return master; } +EXPORT_SYMBOL(drm_master_get); static void drm_master_destroy(struct kref *kref) { @@ -170,10 +171,13 @@ void drm_master_put(struct drm_master **master) kref_put(&(*master)->refcount, drm_master_destroy); *master = NULL; } +EXPORT_SYMBOL(drm_master_put); int drm_setmaster_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { + int ret = 0; + if (file_priv->is_master) return 0; @@ -188,6 +192,13 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, mutex_lock(&dev->struct_mutex); file_priv->minor->master = drm_master_get(file_priv->master); file_priv->is_master = 1; + if (dev->driver->master_set) { + ret = dev->driver->master_set(dev, file_priv, false); + if (unlikely(ret != 0)) { + file_priv->is_master = 0; + drm_master_put(&file_priv->minor->master); + } + } mutex_unlock(&dev->struct_mutex); } @@ -204,6 +215,8 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data, return -EINVAL; mutex_lock(&dev->struct_mutex); + if (dev->driver->master_drop) + dev->driver->master_drop(dev, file_priv, false); drm_master_put(&file_priv->minor->master); file_priv->is_master = 0; mutex_unlock(&dev->struct_mutex); @@ -220,9 +233,11 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, INIT_LIST_HEAD(&dev->ctxlist); INIT_LIST_HEAD(&dev->vmalist); INIT_LIST_HEAD(&dev->maplist); + INIT_LIST_HEAD(&dev->vblank_event_list); spin_lock_init(&dev->count_lock); spin_lock_init(&dev->drw_lock); + spin_lock_init(&dev->event_lock); init_timer(&dev->timer); mutex_init(&dev->struct_mutex); mutex_init(&dev->ctxlist_mutex); diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..6d2abaf35ba22641a3a8e2d6677ff64fb5571b6e --- /dev/null +++ b/drivers/gpu/drm/i2c/Makefile @@ -0,0 +1,4 @@ +ccflags-y := -Iinclude/drm + +ch7006-y := ch7006_drv.o ch7006_mode.o +obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c new file mode 100644 index 0000000000000000000000000000000000000000..9422a74c8b54148b881b6dac265339194ba24ece --- /dev/null +++ b/drivers/gpu/drm/i2c/ch7006_drv.c @@ -0,0 +1,531 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "ch7006_priv.h" + +/* DRM encoder functions */ + +static void ch7006_encoder_set_config(struct drm_encoder *encoder, + void *params) +{ + struct ch7006_priv *priv = to_ch7006_priv(encoder); + + priv->params = params; +} + +static void ch7006_encoder_destroy(struct drm_encoder *encoder) +{ + struct ch7006_priv *priv = to_ch7006_priv(encoder); + + drm_property_destroy(encoder->dev, priv->scale_property); + + kfree(priv); + to_encoder_slave(encoder)->slave_priv = NULL; + + drm_i2c_encoder_destroy(encoder); +} + +static void ch7006_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct ch7006_state *state = &priv->state; + + ch7006_dbg(client, "\n"); + + if (mode == priv->last_dpms) + return; + priv->last_dpms = mode; + + ch7006_setup_power_state(encoder); + + ch7006_load_reg(client, state, CH7006_POWER); +} + +static void ch7006_encoder_save(struct drm_encoder *encoder) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + + ch7006_dbg(client, "\n"); + + ch7006_state_save(client, &priv->saved_state); +} + +static void ch7006_encoder_restore(struct drm_encoder *encoder) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + + ch7006_dbg(client, "\n"); + + ch7006_state_load(client, &priv->saved_state); +} + +static bool ch7006_encoder_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct ch7006_priv *priv = to_ch7006_priv(encoder); + + /* The ch7006 is painfully picky with the input timings so no + * custom modes for now... */ + + priv->mode = ch7006_lookup_mode(encoder, mode); + + return !!priv->mode; +} + +static int ch7006_encoder_mode_valid(struct drm_encoder *encoder, + struct drm_display_mode *mode) +{ + if (ch7006_lookup_mode(encoder, mode)) + return MODE_OK; + else + return MODE_BAD; +} + +static void ch7006_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *drm_mode, + struct drm_display_mode *adjusted_mode) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct ch7006_encoder_params *params = priv->params; + struct ch7006_state *state = &priv->state; + uint8_t *regs = state->regs; + struct ch7006_mode *mode = priv->mode; + struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; + int start_active; + + ch7006_dbg(client, "\n"); + + regs[CH7006_DISPMODE] = norm->dispmode | mode->dispmode; + regs[CH7006_BWIDTH] = 0; + regs[CH7006_INPUT_FORMAT] = bitf(CH7006_INPUT_FORMAT_FORMAT, + params->input_format); + + regs[CH7006_CLKMODE] = CH7006_CLKMODE_SUBC_LOCK + | bitf(CH7006_CLKMODE_XCM, params->xcm) + | bitf(CH7006_CLKMODE_PCM, params->pcm); + if (params->clock_mode) + regs[CH7006_CLKMODE] |= CH7006_CLKMODE_MASTER; + if (params->clock_edge) + regs[CH7006_CLKMODE] |= CH7006_CLKMODE_POS_EDGE; + + start_active = (drm_mode->htotal & ~0x7) - (drm_mode->hsync_start & ~0x7); + regs[CH7006_POV] = bitf(CH7006_POV_START_ACTIVE_8, start_active); + regs[CH7006_START_ACTIVE] = bitf(CH7006_START_ACTIVE_0, start_active); + + regs[CH7006_INPUT_SYNC] = 0; + if (params->sync_direction) + regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_OUTPUT; + if (params->sync_encoding) + regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_EMBEDDED; + if (drm_mode->flags & DRM_MODE_FLAG_PVSYNC) + regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_PVSYNC; + if (drm_mode->flags & DRM_MODE_FLAG_PHSYNC) + regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_PHSYNC; + + regs[CH7006_DETECT] = 0; + regs[CH7006_BCLKOUT] = 0; + + regs[CH7006_SUBC_INC3] = 0; + if (params->pout_level) + regs[CH7006_SUBC_INC3] |= CH7006_SUBC_INC3_POUT_3_3V; + + regs[CH7006_SUBC_INC4] = 0; + if (params->active_detect) + regs[CH7006_SUBC_INC4] |= CH7006_SUBC_INC4_DS_INPUT; + + regs[CH7006_PLL_CONTROL] = priv->saved_state.regs[CH7006_PLL_CONTROL]; + + ch7006_setup_levels(encoder); + ch7006_setup_subcarrier(encoder); + ch7006_setup_pll(encoder); + ch7006_setup_power_state(encoder); + ch7006_setup_properties(encoder); + + ch7006_state_load(client, state); +} + +static enum drm_connector_status ch7006_encoder_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct ch7006_state *state = &priv->state; + int det; + + ch7006_dbg(client, "\n"); + + ch7006_save_reg(client, state, CH7006_DETECT); + ch7006_save_reg(client, state, CH7006_POWER); + ch7006_save_reg(client, state, CH7006_CLKMODE); + + ch7006_write(client, CH7006_POWER, CH7006_POWER_RESET | + bitfs(CH7006_POWER_LEVEL, NORMAL)); + ch7006_write(client, CH7006_CLKMODE, CH7006_CLKMODE_MASTER); + + ch7006_write(client, CH7006_DETECT, CH7006_DETECT_SENSE); + + ch7006_write(client, CH7006_DETECT, 0); + + det = ch7006_read(client, CH7006_DETECT); + + ch7006_load_reg(client, state, CH7006_CLKMODE); + ch7006_load_reg(client, state, CH7006_POWER); + ch7006_load_reg(client, state, CH7006_DETECT); + + if ((det & (CH7006_DETECT_SVIDEO_Y_TEST| + CH7006_DETECT_SVIDEO_C_TEST| + CH7006_DETECT_CVBS_TEST)) == 0) + priv->subconnector = DRM_MODE_SUBCONNECTOR_SCART; + else if ((det & (CH7006_DETECT_SVIDEO_Y_TEST| + CH7006_DETECT_SVIDEO_C_TEST)) == 0) + priv->subconnector = DRM_MODE_SUBCONNECTOR_SVIDEO; + else if ((det & CH7006_DETECT_CVBS_TEST) == 0) + priv->subconnector = DRM_MODE_SUBCONNECTOR_Composite; + else + priv->subconnector = DRM_MODE_SUBCONNECTOR_Unknown; + + drm_connector_property_set_value(connector, + encoder->dev->mode_config.tv_subconnector_property, + priv->subconnector); + + return priv->subconnector ? connector_status_connected : + connector_status_disconnected; +} + +static int ch7006_encoder_get_modes(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct ch7006_mode *mode; + int n = 0; + + for (mode = ch7006_modes; mode->mode.clock; mode++) { + if (~mode->valid_scales & 1<scale || + ~mode->valid_norms & 1<norm) + continue; + + drm_mode_probed_add(connector, + drm_mode_duplicate(encoder->dev, &mode->mode)); + + n++; + } + + return n; +} + +static int ch7006_encoder_create_resources(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct drm_device *dev = encoder->dev; + struct drm_mode_config *conf = &dev->mode_config; + + drm_mode_create_tv_properties(dev, NUM_TV_NORMS, ch7006_tv_norm_names); + + priv->scale_property = drm_property_create(dev, DRM_MODE_PROP_RANGE, + "scale", 2); + priv->scale_property->values[0] = 0; + priv->scale_property->values[1] = 2; + + drm_connector_attach_property(connector, conf->tv_select_subconnector_property, + priv->select_subconnector); + drm_connector_attach_property(connector, conf->tv_subconnector_property, + priv->subconnector); + drm_connector_attach_property(connector, conf->tv_left_margin_property, + priv->hmargin); + drm_connector_attach_property(connector, conf->tv_bottom_margin_property, + priv->vmargin); + drm_connector_attach_property(connector, conf->tv_mode_property, + priv->norm); + drm_connector_attach_property(connector, conf->tv_brightness_property, + priv->brightness); + drm_connector_attach_property(connector, conf->tv_contrast_property, + priv->contrast); + drm_connector_attach_property(connector, conf->tv_flicker_reduction_property, + priv->flicker); + drm_connector_attach_property(connector, priv->scale_property, + priv->scale); + + return 0; +} + +static int ch7006_encoder_set_property(struct drm_encoder *encoder, + struct drm_connector *connector, + struct drm_property *property, + uint64_t val) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct ch7006_state *state = &priv->state; + struct drm_mode_config *conf = &encoder->dev->mode_config; + struct drm_crtc *crtc = encoder->crtc; + bool modes_changed = false; + + ch7006_dbg(client, "\n"); + + if (property == conf->tv_select_subconnector_property) { + priv->select_subconnector = val; + + ch7006_setup_power_state(encoder); + + ch7006_load_reg(client, state, CH7006_POWER); + + } else if (property == conf->tv_left_margin_property) { + priv->hmargin = val; + + ch7006_setup_properties(encoder); + + ch7006_load_reg(client, state, CH7006_POV); + ch7006_load_reg(client, state, CH7006_HPOS); + + } else if (property == conf->tv_bottom_margin_property) { + priv->vmargin = val; + + ch7006_setup_properties(encoder); + + ch7006_load_reg(client, state, CH7006_POV); + ch7006_load_reg(client, state, CH7006_VPOS); + + } else if (property == conf->tv_mode_property) { + if (connector->dpms != DRM_MODE_DPMS_OFF) + return -EINVAL; + + priv->norm = val; + + modes_changed = true; + + } else if (property == conf->tv_brightness_property) { + priv->brightness = val; + + ch7006_setup_levels(encoder); + + ch7006_load_reg(client, state, CH7006_BLACK_LEVEL); + + } else if (property == conf->tv_contrast_property) { + priv->contrast = val; + + ch7006_setup_properties(encoder); + + ch7006_load_reg(client, state, CH7006_CONTRAST); + + } else if (property == conf->tv_flicker_reduction_property) { + priv->flicker = val; + + ch7006_setup_properties(encoder); + + ch7006_load_reg(client, state, CH7006_FFILTER); + + } else if (property == priv->scale_property) { + if (connector->dpms != DRM_MODE_DPMS_OFF) + return -EINVAL; + + priv->scale = val; + + modes_changed = true; + + } else { + return -EINVAL; + } + + if (modes_changed) { + drm_helper_probe_single_connector_modes(connector, 0, 0); + + /* Disable the crtc to ensure a full modeset is + * performed whenever it's turned on again. */ + if (crtc) { + struct drm_mode_set modeset = { + .crtc = crtc, + }; + + crtc->funcs->set_config(&modeset); + } + } + + return 0; +} + +static struct drm_encoder_slave_funcs ch7006_encoder_funcs = { + .set_config = ch7006_encoder_set_config, + .destroy = ch7006_encoder_destroy, + .dpms = ch7006_encoder_dpms, + .save = ch7006_encoder_save, + .restore = ch7006_encoder_restore, + .mode_fixup = ch7006_encoder_mode_fixup, + .mode_valid = ch7006_encoder_mode_valid, + .mode_set = ch7006_encoder_mode_set, + .detect = ch7006_encoder_detect, + .get_modes = ch7006_encoder_get_modes, + .create_resources = ch7006_encoder_create_resources, + .set_property = ch7006_encoder_set_property, +}; + + +/* I2C driver functions */ + +static int ch7006_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + uint8_t addr = CH7006_VERSION_ID; + uint8_t val; + int ret; + + ch7006_dbg(client, "\n"); + + ret = i2c_master_send(client, &addr, sizeof(addr)); + if (ret < 0) + goto fail; + + ret = i2c_master_recv(client, &val, sizeof(val)); + if (ret < 0) + goto fail; + + ch7006_info(client, "Detected version ID: %x\n", val); + + return 0; + +fail: + ch7006_err(client, "Error %d reading version ID\n", ret); + + return -ENODEV; +} + +static int ch7006_remove(struct i2c_client *client) +{ + ch7006_dbg(client, "\n"); + + return 0; +} + +static int ch7006_encoder_init(struct i2c_client *client, + struct drm_device *dev, + struct drm_encoder_slave *encoder) +{ + struct ch7006_priv *priv; + int i; + + ch7006_dbg(client, "\n"); + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + encoder->slave_priv = priv; + encoder->slave_funcs = &ch7006_encoder_funcs; + + priv->norm = TV_NORM_PAL; + priv->select_subconnector = DRM_MODE_SUBCONNECTOR_Automatic; + priv->subconnector = DRM_MODE_SUBCONNECTOR_Unknown; + priv->scale = 1; + priv->contrast = 50; + priv->brightness = 50; + priv->flicker = 50; + priv->hmargin = 50; + priv->vmargin = 50; + priv->last_dpms = -1; + + if (ch7006_tv_norm) { + for (i = 0; i < NUM_TV_NORMS; i++) { + if (!strcmp(ch7006_tv_norm_names[i], ch7006_tv_norm)) { + priv->norm = i; + break; + } + } + + if (i == NUM_TV_NORMS) + ch7006_err(client, "Invalid TV norm setting \"%s\".\n", + ch7006_tv_norm); + } + + if (ch7006_scale >= 0 && ch7006_scale <= 2) + priv->scale = ch7006_scale; + else + ch7006_err(client, "Invalid scale setting \"%d\".\n", + ch7006_scale); + + return 0; +} + +static struct i2c_device_id ch7006_ids[] = { + { "ch7006", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ch7006_ids); + +static struct drm_i2c_encoder_driver ch7006_driver = { + .i2c_driver = { + .probe = ch7006_probe, + .remove = ch7006_remove, + + .driver = { + .name = "ch7006", + }, + + .id_table = ch7006_ids, + }, + + .encoder_init = ch7006_encoder_init, +}; + + +/* Module initialization */ + +static int __init ch7006_init(void) +{ + return drm_i2c_encoder_register(THIS_MODULE, &ch7006_driver); +} + +static void __exit ch7006_exit(void) +{ + drm_i2c_encoder_unregister(&ch7006_driver); +} + +int ch7006_debug; +module_param_named(debug, ch7006_debug, int, 0600); +MODULE_PARM_DESC(debug, "Enable debug output."); + +char *ch7006_tv_norm; +module_param_named(tv_norm, ch7006_tv_norm, charp, 0600); +MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" + "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, PAL-60, NTSC-M, NTSC-J.\n" + "\t\tDefault: PAL"); + +int ch7006_scale = 1; +module_param_named(scale, ch7006_scale, int, 0600); +MODULE_PARM_DESC(scale, "Default scale.\n" + "\t\tSupported: 0 -> Select video modes with a higher blanking ratio.\n" + "\t\t\t1 -> Select default video modes.\n" + "\t\t\t2 -> Select video modes with a lower blanking ratio."); + +MODULE_AUTHOR("Francisco Jerez "); +MODULE_DESCRIPTION("Chrontel ch7006 TV encoder driver"); +MODULE_LICENSE("GPL and additional rights"); + +module_init(ch7006_init); +module_exit(ch7006_exit); diff --git a/drivers/gpu/drm/i2c/ch7006_mode.c b/drivers/gpu/drm/i2c/ch7006_mode.c new file mode 100644 index 0000000000000000000000000000000000000000..87f5445092e84198d303d35b9ac7a2d956b2b149 --- /dev/null +++ b/drivers/gpu/drm/i2c/ch7006_mode.c @@ -0,0 +1,473 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "ch7006_priv.h" + +char *ch7006_tv_norm_names[] = { + [TV_NORM_PAL] = "PAL", + [TV_NORM_PAL_M] = "PAL-M", + [TV_NORM_PAL_N] = "PAL-N", + [TV_NORM_PAL_NC] = "PAL-Nc", + [TV_NORM_PAL_60] = "PAL-60", + [TV_NORM_NTSC_M] = "NTSC-M", + [TV_NORM_NTSC_J] = "NTSC-J", +}; + +#define NTSC_LIKE_TIMINGS .vrefresh = 60 * fixed1/1.001, \ + .vdisplay = 480, \ + .vtotal = 525, \ + .hvirtual = 660 + +#define PAL_LIKE_TIMINGS .vrefresh = 50 * fixed1, \ + .vdisplay = 576, \ + .vtotal = 625, \ + .hvirtual = 810 + +struct ch7006_tv_norm_info ch7006_tv_norms[] = { + [TV_NORM_NTSC_M] = { + NTSC_LIKE_TIMINGS, + .black_level = 0.339 * fixed1, + .subc_freq = 3579545 * fixed1, + .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, NTSC), + .voffset = 0, + }, + [TV_NORM_NTSC_J] = { + NTSC_LIKE_TIMINGS, + .black_level = 0.286 * fixed1, + .subc_freq = 3579545 * fixed1, + .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, NTSC_J), + .voffset = 0, + }, + [TV_NORM_PAL] = { + PAL_LIKE_TIMINGS, + .black_level = 0.3 * fixed1, + .subc_freq = 4433618.75 * fixed1, + .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL), + .voffset = 0, + }, + [TV_NORM_PAL_M] = { + NTSC_LIKE_TIMINGS, + .black_level = 0.339 * fixed1, + .subc_freq = 3575611.433 * fixed1, + .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL_M), + .voffset = 16, + }, + + /* The following modes seem to work right but they're + * undocumented */ + + [TV_NORM_PAL_N] = { + PAL_LIKE_TIMINGS, + .black_level = 0.339 * fixed1, + .subc_freq = 4433618.75 * fixed1, + .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL), + .voffset = 0, + }, + [TV_NORM_PAL_NC] = { + PAL_LIKE_TIMINGS, + .black_level = 0.3 * fixed1, + .subc_freq = 3582056.25 * fixed1, + .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL), + .voffset = 0, + }, + [TV_NORM_PAL_60] = { + NTSC_LIKE_TIMINGS, + .black_level = 0.3 * fixed1, + .subc_freq = 4433618.75 * fixed1, + .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL_M), + .voffset = 16, + }, +}; + +#define __MODE(f, hd, vd, ht, vt, hsynp, vsynp, \ + subc, scale, scale_mask, norm_mask, e_hd, e_vd) { \ + .mode = { \ + .name = #hd "x" #vd, \ + .status = 0, \ + .type = DRM_MODE_TYPE_DRIVER, \ + .clock = f, \ + .hdisplay = hd, \ + .hsync_start = e_hd + 16, \ + .hsync_end = e_hd + 80, \ + .htotal = ht, \ + .hskew = 0, \ + .vdisplay = vd, \ + .vsync_start = vd + 10, \ + .vsync_end = vd + 26, \ + .vtotal = vt, \ + .vscan = 0, \ + .flags = DRM_MODE_FLAG_##hsynp##HSYNC | \ + DRM_MODE_FLAG_##vsynp##VSYNC, \ + .vrefresh = 0, \ + }, \ + .enc_hdisp = e_hd, \ + .enc_vdisp = e_vd, \ + .subc_coeff = subc * fixed1, \ + .dispmode = bitfs(CH7006_DISPMODE_SCALING_RATIO, scale) | \ + bitfs(CH7006_DISPMODE_INPUT_RES, e_hd##x##e_vd), \ + .valid_scales = scale_mask, \ + .valid_norms = norm_mask \ + } + +#define MODE(f, hd, vd, ht, vt, hsynp, vsynp, \ + subc, scale, scale_mask, norm_mask) \ + __MODE(f, hd, vd, ht, vt, hsynp, vsynp, subc, scale, \ + scale_mask, norm_mask, hd, vd) + +#define NTSC_LIKE (1 << TV_NORM_NTSC_M | 1 << TV_NORM_NTSC_J | \ + 1 << TV_NORM_PAL_M | 1 << TV_NORM_PAL_60) + +#define PAL_LIKE (1 << TV_NORM_PAL | 1 << TV_NORM_PAL_N | 1 << TV_NORM_PAL_NC) + +struct ch7006_mode ch7006_modes[] = { + MODE(21000, 512, 384, 840, 500, N, N, 181.797557582, 5_4, 0x6, PAL_LIKE), + MODE(26250, 512, 384, 840, 625, N, N, 145.438046066, 1_1, 0x1, PAL_LIKE), + MODE(20140, 512, 384, 800, 420, N, N, 213.257083791, 5_4, 0x4, NTSC_LIKE), + MODE(24671, 512, 384, 784, 525, N, N, 174.0874153, 1_1, 0x3, NTSC_LIKE), + MODE(28125, 720, 400, 1125, 500, N, N, 135.742176298, 5_4, 0x6, PAL_LIKE), + MODE(34875, 720, 400, 1116, 625, N, N, 109.469496898, 1_1, 0x1, PAL_LIKE), + MODE(23790, 720, 400, 945, 420, N, N, 160.475642016, 5_4, 0x4, NTSC_LIKE), + MODE(29455, 720, 400, 936, 525, N, N, 129.614941843, 1_1, 0x3, NTSC_LIKE), + MODE(25000, 640, 400, 1000, 500, N, N, 152.709948279, 5_4, 0x6, PAL_LIKE), + MODE(31500, 640, 400, 1008, 625, N, N, 121.198371646, 1_1, 0x1, PAL_LIKE), + MODE(21147, 640, 400, 840, 420, N, N, 180.535097338, 5_4, 0x4, NTSC_LIKE), + MODE(26434, 640, 400, 840, 525, N, N, 144.42807787, 1_1, 0x2, NTSC_LIKE), + MODE(30210, 640, 400, 840, 600, N, N, 126.374568276, 7_8, 0x1, NTSC_LIKE), + MODE(21000, 640, 480, 840, 500, N, N, 181.797557582, 5_4, 0x4, PAL_LIKE), + MODE(26250, 640, 480, 840, 625, N, N, 145.438046066, 1_1, 0x2, PAL_LIKE), + MODE(31500, 640, 480, 840, 750, N, N, 121.198371646, 5_6, 0x1, PAL_LIKE), + MODE(24671, 640, 480, 784, 525, N, N, 174.0874153, 1_1, 0x4, NTSC_LIKE), + MODE(28196, 640, 480, 784, 600, N, N, 152.326488422, 7_8, 0x2, NTSC_LIKE), + MODE(30210, 640, 480, 800, 630, N, N, 142.171389101, 5_6, 0x1, NTSC_LIKE), + __MODE(29500, 720, 576, 944, 625, P, P, 145.592111636, 1_1, 0x7, PAL_LIKE, 800, 600), + MODE(36000, 800, 600, 960, 750, P, P, 119.304647022, 5_6, 0x6, PAL_LIKE), + MODE(39000, 800, 600, 936, 836, P, P, 110.127366499, 3_4, 0x1, PAL_LIKE), + MODE(39273, 800, 600, 1040, 630, P, P, 145.816809399, 5_6, 0x4, NTSC_LIKE), + MODE(43636, 800, 600, 1040, 700, P, P, 131.235128487, 3_4, 0x2, NTSC_LIKE), + MODE(47832, 800, 600, 1064, 750, P, P, 119.723275165, 7_10, 0x1, NTSC_LIKE), + {} +}; + +struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, + struct drm_display_mode *drm_mode) +{ + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct ch7006_mode *mode; + + for (mode = ch7006_modes; mode->mode.clock; mode++) { + + if (~mode->valid_norms & 1<norm) + continue; + + if (mode->mode.hdisplay != drm_mode->hdisplay || + mode->mode.vdisplay != drm_mode->vdisplay || + mode->mode.vtotal != drm_mode->vtotal || + mode->mode.htotal != drm_mode->htotal || + mode->mode.clock != drm_mode->clock) + continue; + + return mode; + } + + return NULL; +} + +/* Some common HW state calculation code */ + +void ch7006_setup_levels(struct drm_encoder *encoder) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + uint8_t *regs = priv->state.regs; + struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; + int gain; + int black_level; + + /* Set DAC_GAIN if the voltage drop between white and black is + * high enough. */ + if (norm->black_level < 339*fixed1/1000) { + gain = 76; + + regs[CH7006_INPUT_FORMAT] |= CH7006_INPUT_FORMAT_DAC_GAIN; + } else { + gain = 71; + + regs[CH7006_INPUT_FORMAT] &= ~CH7006_INPUT_FORMAT_DAC_GAIN; + } + + black_level = round_fixed(norm->black_level*26625)/gain; + + /* Correct it with the specified brightness. */ + black_level = interpolate(90, black_level, 208, priv->brightness); + + regs[CH7006_BLACK_LEVEL] = bitf(CH7006_BLACK_LEVEL_0, black_level); + + ch7006_dbg(client, "black level: %d\n", black_level); +} + +void ch7006_setup_subcarrier(struct drm_encoder *encoder) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct ch7006_state *state = &priv->state; + struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; + struct ch7006_mode *mode = priv->mode; + uint32_t subc_inc; + + subc_inc = round_fixed((mode->subc_coeff >> 8) + * (norm->subc_freq >> 24)); + + setbitf(state, CH7006_SUBC_INC0, 28, subc_inc); + setbitf(state, CH7006_SUBC_INC1, 24, subc_inc); + setbitf(state, CH7006_SUBC_INC2, 20, subc_inc); + setbitf(state, CH7006_SUBC_INC3, 16, subc_inc); + setbitf(state, CH7006_SUBC_INC4, 12, subc_inc); + setbitf(state, CH7006_SUBC_INC5, 8, subc_inc); + setbitf(state, CH7006_SUBC_INC6, 4, subc_inc); + setbitf(state, CH7006_SUBC_INC7, 0, subc_inc); + + ch7006_dbg(client, "subcarrier inc: %u\n", subc_inc); +} + +void ch7006_setup_pll(struct drm_encoder *encoder) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + uint8_t *regs = priv->state.regs; + struct ch7006_mode *mode = priv->mode; + int n, best_n = 0; + int m, best_m = 0; + int freq, best_freq = 0; + + for (n = 0; n < CH7006_MAXN; n++) { + for (m = 0; m < CH7006_MAXM; m++) { + freq = CH7006_FREQ0*(n+2)/(m+2); + + if (abs(freq - mode->mode.clock) < + abs(best_freq - mode->mode.clock)) { + best_freq = freq; + best_n = n; + best_m = m; + } + } + } + + regs[CH7006_PLLOV] = bitf(CH7006_PLLOV_N_8, best_n) | + bitf(CH7006_PLLOV_M_8, best_m); + + regs[CH7006_PLLM] = bitf(CH7006_PLLM_0, best_m); + regs[CH7006_PLLN] = bitf(CH7006_PLLN_0, best_n); + + if (best_n < 108) + regs[CH7006_PLL_CONTROL] |= CH7006_PLL_CONTROL_CAPACITOR; + else + regs[CH7006_PLL_CONTROL] &= ~CH7006_PLL_CONTROL_CAPACITOR; + + ch7006_dbg(client, "n=%d m=%d f=%d c=%d\n", + best_n, best_m, best_freq, best_n < 108); +} + +void ch7006_setup_power_state(struct drm_encoder *encoder) +{ + struct ch7006_priv *priv = to_ch7006_priv(encoder); + uint8_t *power = &priv->state.regs[CH7006_POWER]; + int subconnector; + + subconnector = priv->select_subconnector ? priv->select_subconnector : + priv->subconnector; + + *power = CH7006_POWER_RESET; + + if (priv->last_dpms == DRM_MODE_DPMS_ON) { + switch (subconnector) { + case DRM_MODE_SUBCONNECTOR_SVIDEO: + *power |= bitfs(CH7006_POWER_LEVEL, CVBS_OFF); + break; + case DRM_MODE_SUBCONNECTOR_Composite: + *power |= bitfs(CH7006_POWER_LEVEL, SVIDEO_OFF); + break; + case DRM_MODE_SUBCONNECTOR_SCART: + *power |= bitfs(CH7006_POWER_LEVEL, NORMAL) | + CH7006_POWER_SCART; + break; + } + + } else { + *power |= bitfs(CH7006_POWER_LEVEL, FULL_POWER_OFF); + } +} + +void ch7006_setup_properties(struct drm_encoder *encoder) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct ch7006_state *state = &priv->state; + struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; + struct ch7006_mode *ch_mode = priv->mode; + struct drm_display_mode *mode = &ch_mode->mode; + uint8_t *regs = state->regs; + int flicker, contrast, hpos, vpos; + uint64_t scale, aspect; + + flicker = interpolate(0, 2, 3, priv->flicker); + regs[CH7006_FFILTER] = bitf(CH7006_FFILTER_TEXT, flicker) | + bitf(CH7006_FFILTER_LUMA, flicker) | + bitf(CH7006_FFILTER_CHROMA, 1); + + contrast = interpolate(0, 5, 7, priv->contrast); + regs[CH7006_CONTRAST] = bitf(CH7006_CONTRAST_0, contrast); + + scale = norm->vtotal*fixed1; + do_div(scale, mode->vtotal); + + aspect = ch_mode->enc_hdisp*fixed1; + do_div(aspect, ch_mode->enc_vdisp); + + hpos = round_fixed((norm->hvirtual * aspect - mode->hdisplay * scale) + * priv->hmargin * mode->vtotal) / norm->vtotal / 100 / 4; + + setbitf(state, CH7006_POV, HPOS_8, hpos); + setbitf(state, CH7006_HPOS, 0, hpos); + + vpos = max(0, norm->vdisplay - round_fixed(mode->vdisplay*scale) + + norm->voffset) * priv->vmargin / 100 / 2; + + setbitf(state, CH7006_POV, VPOS_8, vpos); + setbitf(state, CH7006_VPOS, 0, vpos); + + ch7006_dbg(client, "hpos: %d, vpos: %d\n", hpos, vpos); +} + +/* HW access functions */ + +void ch7006_write(struct i2c_client *client, uint8_t addr, uint8_t val) +{ + uint8_t buf[] = {addr, val}; + int ret; + + ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); + if (ret < 0) + ch7006_err(client, "Error %d writing to subaddress 0x%x\n", + ret, addr); +} + +uint8_t ch7006_read(struct i2c_client *client, uint8_t addr) +{ + uint8_t val; + int ret; + + ret = i2c_master_send(client, &addr, sizeof(addr)); + if (ret < 0) + goto fail; + + ret = i2c_master_recv(client, &val, sizeof(val)); + if (ret < 0) + goto fail; + + return val; + +fail: + ch7006_err(client, "Error %d reading from subaddress 0x%x\n", + ret, addr); + return 0; +} + +void ch7006_state_load(struct i2c_client *client, + struct ch7006_state *state) +{ + ch7006_load_reg(client, state, CH7006_POWER); + + ch7006_load_reg(client, state, CH7006_DISPMODE); + ch7006_load_reg(client, state, CH7006_FFILTER); + ch7006_load_reg(client, state, CH7006_BWIDTH); + ch7006_load_reg(client, state, CH7006_INPUT_FORMAT); + ch7006_load_reg(client, state, CH7006_CLKMODE); + ch7006_load_reg(client, state, CH7006_START_ACTIVE); + ch7006_load_reg(client, state, CH7006_POV); + ch7006_load_reg(client, state, CH7006_BLACK_LEVEL); + ch7006_load_reg(client, state, CH7006_HPOS); + ch7006_load_reg(client, state, CH7006_VPOS); + ch7006_load_reg(client, state, CH7006_INPUT_SYNC); + ch7006_load_reg(client, state, CH7006_DETECT); + ch7006_load_reg(client, state, CH7006_CONTRAST); + ch7006_load_reg(client, state, CH7006_PLLOV); + ch7006_load_reg(client, state, CH7006_PLLM); + ch7006_load_reg(client, state, CH7006_PLLN); + ch7006_load_reg(client, state, CH7006_BCLKOUT); + ch7006_load_reg(client, state, CH7006_SUBC_INC0); + ch7006_load_reg(client, state, CH7006_SUBC_INC1); + ch7006_load_reg(client, state, CH7006_SUBC_INC2); + ch7006_load_reg(client, state, CH7006_SUBC_INC3); + ch7006_load_reg(client, state, CH7006_SUBC_INC4); + ch7006_load_reg(client, state, CH7006_SUBC_INC5); + ch7006_load_reg(client, state, CH7006_SUBC_INC6); + ch7006_load_reg(client, state, CH7006_SUBC_INC7); + ch7006_load_reg(client, state, CH7006_PLL_CONTROL); + ch7006_load_reg(client, state, CH7006_CALC_SUBC_INC0); + + /* I don't know what this is for, but otherwise I get no + * signal. + */ + ch7006_write(client, 0x3d, 0x0); +} + +void ch7006_state_save(struct i2c_client *client, + struct ch7006_state *state) +{ + ch7006_save_reg(client, state, CH7006_POWER); + + ch7006_save_reg(client, state, CH7006_DISPMODE); + ch7006_save_reg(client, state, CH7006_FFILTER); + ch7006_save_reg(client, state, CH7006_BWIDTH); + ch7006_save_reg(client, state, CH7006_INPUT_FORMAT); + ch7006_save_reg(client, state, CH7006_CLKMODE); + ch7006_save_reg(client, state, CH7006_START_ACTIVE); + ch7006_save_reg(client, state, CH7006_POV); + ch7006_save_reg(client, state, CH7006_BLACK_LEVEL); + ch7006_save_reg(client, state, CH7006_HPOS); + ch7006_save_reg(client, state, CH7006_VPOS); + ch7006_save_reg(client, state, CH7006_INPUT_SYNC); + ch7006_save_reg(client, state, CH7006_DETECT); + ch7006_save_reg(client, state, CH7006_CONTRAST); + ch7006_save_reg(client, state, CH7006_PLLOV); + ch7006_save_reg(client, state, CH7006_PLLM); + ch7006_save_reg(client, state, CH7006_PLLN); + ch7006_save_reg(client, state, CH7006_BCLKOUT); + ch7006_save_reg(client, state, CH7006_SUBC_INC0); + ch7006_save_reg(client, state, CH7006_SUBC_INC1); + ch7006_save_reg(client, state, CH7006_SUBC_INC2); + ch7006_save_reg(client, state, CH7006_SUBC_INC3); + ch7006_save_reg(client, state, CH7006_SUBC_INC4); + ch7006_save_reg(client, state, CH7006_SUBC_INC5); + ch7006_save_reg(client, state, CH7006_SUBC_INC6); + ch7006_save_reg(client, state, CH7006_SUBC_INC7); + ch7006_save_reg(client, state, CH7006_PLL_CONTROL); + ch7006_save_reg(client, state, CH7006_CALC_SUBC_INC0); + + state->regs[CH7006_FFILTER] = (state->regs[CH7006_FFILTER] & 0xf0) | + (state->regs[CH7006_FFILTER] & 0x0c) >> 2 | + (state->regs[CH7006_FFILTER] & 0x03) << 2; +} diff --git a/drivers/gpu/drm/i2c/ch7006_priv.h b/drivers/gpu/drm/i2c/ch7006_priv.h new file mode 100644 index 0000000000000000000000000000000000000000..b06d3d93d8acb3facfb607691a2d61f11409a025 --- /dev/null +++ b/drivers/gpu/drm/i2c/ch7006_priv.h @@ -0,0 +1,344 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +#ifndef __DRM_I2C_CH7006_PRIV_H__ +#define __DRM_I2C_CH7006_PRIV_H__ + +#include "drmP.h" +#include "drm_crtc_helper.h" +#include "drm_encoder_slave.h" +#include "i2c/ch7006.h" + +typedef int64_t fixed; +#define fixed1 (1LL << 32) + +enum ch7006_tv_norm { + TV_NORM_PAL, + TV_NORM_PAL_M, + TV_NORM_PAL_N, + TV_NORM_PAL_NC, + TV_NORM_PAL_60, + TV_NORM_NTSC_M, + TV_NORM_NTSC_J, + NUM_TV_NORMS +}; + +struct ch7006_tv_norm_info { + fixed vrefresh; + int vdisplay; + int vtotal; + int hvirtual; + + fixed subc_freq; + fixed black_level; + + uint32_t dispmode; + int voffset; +}; + +struct ch7006_mode { + struct drm_display_mode mode; + + int enc_hdisp; + int enc_vdisp; + + fixed subc_coeff; + uint32_t dispmode; + + uint32_t valid_scales; + uint32_t valid_norms; +}; + +struct ch7006_state { + uint8_t regs[0x26]; +}; + +struct ch7006_priv { + struct ch7006_encoder_params *params; + struct ch7006_mode *mode; + + struct ch7006_state state; + struct ch7006_state saved_state; + + struct drm_property *scale_property; + + int select_subconnector; + int subconnector; + int hmargin; + int vmargin; + enum ch7006_tv_norm norm; + int brightness; + int contrast; + int flicker; + int scale; + + int last_dpms; +}; + +#define to_ch7006_priv(x) \ + ((struct ch7006_priv *)to_encoder_slave(x)->slave_priv) + +extern int ch7006_debug; +extern char *ch7006_tv_norm; +extern int ch7006_scale; + +extern char *ch7006_tv_norm_names[]; +extern struct ch7006_tv_norm_info ch7006_tv_norms[]; +extern struct ch7006_mode ch7006_modes[]; + +struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, + struct drm_display_mode *drm_mode); + +void ch7006_setup_levels(struct drm_encoder *encoder); +void ch7006_setup_subcarrier(struct drm_encoder *encoder); +void ch7006_setup_pll(struct drm_encoder *encoder); +void ch7006_setup_power_state(struct drm_encoder *encoder); +void ch7006_setup_properties(struct drm_encoder *encoder); + +void ch7006_write(struct i2c_client *client, uint8_t addr, uint8_t val); +uint8_t ch7006_read(struct i2c_client *client, uint8_t addr); + +void ch7006_state_load(struct i2c_client *client, + struct ch7006_state *state); +void ch7006_state_save(struct i2c_client *client, + struct ch7006_state *state); + +/* Some helper macros */ + +#define ch7006_dbg(client, format, ...) do { \ + if (ch7006_debug) \ + dev_printk(KERN_DEBUG, &client->dev, \ + "%s: " format, __func__, ## __VA_ARGS__); \ + } while (0) +#define ch7006_info(client, format, ...) \ + dev_info(&client->dev, format, __VA_ARGS__) +#define ch7006_err(client, format, ...) \ + dev_err(&client->dev, format, __VA_ARGS__) + +#define __mask(src, bitfield) \ + (((2 << (1 ? bitfield)) - 1) & ~((1 << (0 ? bitfield)) - 1)) +#define mask(bitfield) __mask(bitfield) + +#define __bitf(src, bitfield, x) \ + (((x) >> (src) << (0 ? bitfield)) & __mask(src, bitfield)) +#define bitf(bitfield, x) __bitf(bitfield, x) +#define bitfs(bitfield, s) __bitf(bitfield, bitfield##_##s) +#define setbitf(state, reg, bitfield, x) \ + state->regs[reg] = (state->regs[reg] & ~mask(reg##_##bitfield)) \ + | bitf(reg##_##bitfield, x) + +#define __unbitf(src, bitfield, x) \ + ((x & __mask(src, bitfield)) >> (0 ? bitfield) << (src)) +#define unbitf(bitfield, x) __unbitf(bitfield, x) + +static inline int interpolate(int y0, int y1, int y2, int x) +{ + return y1 + (x < 50 ? y1 - y0 : y2 - y1) * (x - 50) / 50; +} + +static inline int32_t round_fixed(fixed x) +{ + return (x + fixed1/2) >> 32; +} + +#define ch7006_load_reg(client, state, reg) ch7006_write(client, reg, state->regs[reg]) +#define ch7006_save_reg(client, state, reg) state->regs[reg] = ch7006_read(client, reg) + +/* Fixed hardware specs */ + +#define CH7006_FREQ0 14318 +#define CH7006_MAXN 650 +#define CH7006_MAXM 315 + +/* Register definitions */ + +#define CH7006_DISPMODE 0x00 +#define CH7006_DISPMODE_INPUT_RES 0, 7:5 +#define CH7006_DISPMODE_INPUT_RES_512x384 0x0 +#define CH7006_DISPMODE_INPUT_RES_720x400 0x1 +#define CH7006_DISPMODE_INPUT_RES_640x400 0x2 +#define CH7006_DISPMODE_INPUT_RES_640x480 0x3 +#define CH7006_DISPMODE_INPUT_RES_800x600 0x4 +#define CH7006_DISPMODE_INPUT_RES_NATIVE 0x5 +#define CH7006_DISPMODE_OUTPUT_STD 0, 4:3 +#define CH7006_DISPMODE_OUTPUT_STD_PAL 0x0 +#define CH7006_DISPMODE_OUTPUT_STD_NTSC 0x1 +#define CH7006_DISPMODE_OUTPUT_STD_PAL_M 0x2 +#define CH7006_DISPMODE_OUTPUT_STD_NTSC_J 0x3 +#define CH7006_DISPMODE_SCALING_RATIO 0, 2:0 +#define CH7006_DISPMODE_SCALING_RATIO_5_4 0x0 +#define CH7006_DISPMODE_SCALING_RATIO_1_1 0x1 +#define CH7006_DISPMODE_SCALING_RATIO_7_8 0x2 +#define CH7006_DISPMODE_SCALING_RATIO_5_6 0x3 +#define CH7006_DISPMODE_SCALING_RATIO_3_4 0x4 +#define CH7006_DISPMODE_SCALING_RATIO_7_10 0x5 + +#define CH7006_FFILTER 0x01 +#define CH7006_FFILTER_TEXT 0, 5:4 +#define CH7006_FFILTER_LUMA 0, 3:2 +#define CH7006_FFILTER_CHROMA 0, 1:0 +#define CH7006_FFILTER_CHROMA_NO_DCRAWL 0x3 + +#define CH7006_BWIDTH 0x03 +#define CH7006_BWIDTH_5L_FFILER (1 << 7) +#define CH7006_BWIDTH_CVBS_NO_CHROMA (1 << 6) +#define CH7006_BWIDTH_CHROMA 0, 5:4 +#define CH7006_BWIDTH_SVIDEO_YPEAK (1 << 3) +#define CH7006_BWIDTH_SVIDEO_LUMA 0, 2:1 +#define CH7006_BWIDTH_CVBS_LUMA 0, 0:0 + +#define CH7006_INPUT_FORMAT 0x04 +#define CH7006_INPUT_FORMAT_DAC_GAIN (1 << 6) +#define CH7006_INPUT_FORMAT_RGB_PASS_THROUGH (1 << 5) +#define CH7006_INPUT_FORMAT_FORMAT 0, 3:0 +#define CH7006_INPUT_FORMAT_FORMAT_RGB16 0x0 +#define CH7006_INPUT_FORMAT_FORMAT_YCrCb24m16 0x1 +#define CH7006_INPUT_FORMAT_FORMAT_RGB24m16 0x2 +#define CH7006_INPUT_FORMAT_FORMAT_RGB15 0x3 +#define CH7006_INPUT_FORMAT_FORMAT_RGB24m12C 0x4 +#define CH7006_INPUT_FORMAT_FORMAT_RGB24m12I 0x5 +#define CH7006_INPUT_FORMAT_FORMAT_RGB24m8 0x6 +#define CH7006_INPUT_FORMAT_FORMAT_RGB16m8 0x7 +#define CH7006_INPUT_FORMAT_FORMAT_RGB15m8 0x8 +#define CH7006_INPUT_FORMAT_FORMAT_YCrCb24m8 0x9 + +#define CH7006_CLKMODE 0x06 +#define CH7006_CLKMODE_SUBC_LOCK (1 << 7) +#define CH7006_CLKMODE_MASTER (1 << 6) +#define CH7006_CLKMODE_POS_EDGE (1 << 4) +#define CH7006_CLKMODE_XCM 0, 3:2 +#define CH7006_CLKMODE_PCM 0, 1:0 + +#define CH7006_START_ACTIVE 0x07 +#define CH7006_START_ACTIVE_0 0, 7:0 + +#define CH7006_POV 0x08 +#define CH7006_POV_START_ACTIVE_8 8, 2:2 +#define CH7006_POV_HPOS_8 8, 1:1 +#define CH7006_POV_VPOS_8 8, 0:0 + +#define CH7006_BLACK_LEVEL 0x09 +#define CH7006_BLACK_LEVEL_0 0, 7:0 + +#define CH7006_HPOS 0x0a +#define CH7006_HPOS_0 0, 7:0 + +#define CH7006_VPOS 0x0b +#define CH7006_VPOS_0 0, 7:0 + +#define CH7006_INPUT_SYNC 0x0d +#define CH7006_INPUT_SYNC_EMBEDDED (1 << 3) +#define CH7006_INPUT_SYNC_OUTPUT (1 << 2) +#define CH7006_INPUT_SYNC_PVSYNC (1 << 1) +#define CH7006_INPUT_SYNC_PHSYNC (1 << 0) + +#define CH7006_POWER 0x0e +#define CH7006_POWER_SCART (1 << 4) +#define CH7006_POWER_RESET (1 << 3) +#define CH7006_POWER_LEVEL 0, 2:0 +#define CH7006_POWER_LEVEL_CVBS_OFF 0x0 +#define CH7006_POWER_LEVEL_POWER_OFF 0x1 +#define CH7006_POWER_LEVEL_SVIDEO_OFF 0x2 +#define CH7006_POWER_LEVEL_NORMAL 0x3 +#define CH7006_POWER_LEVEL_FULL_POWER_OFF 0x4 + +#define CH7006_DETECT 0x10 +#define CH7006_DETECT_SVIDEO_Y_TEST (1 << 3) +#define CH7006_DETECT_SVIDEO_C_TEST (1 << 2) +#define CH7006_DETECT_CVBS_TEST (1 << 1) +#define CH7006_DETECT_SENSE (1 << 0) + +#define CH7006_CONTRAST 0x11 +#define CH7006_CONTRAST_0 0, 2:0 + +#define CH7006_PLLOV 0x13 +#define CH7006_PLLOV_N_8 8, 2:1 +#define CH7006_PLLOV_M_8 8, 0:0 + +#define CH7006_PLLM 0x14 +#define CH7006_PLLM_0 0, 7:0 + +#define CH7006_PLLN 0x15 +#define CH7006_PLLN_0 0, 7:0 + +#define CH7006_BCLKOUT 0x17 + +#define CH7006_SUBC_INC0 0x18 +#define CH7006_SUBC_INC0_28 28, 3:0 + +#define CH7006_SUBC_INC1 0x19 +#define CH7006_SUBC_INC1_24 24, 3:0 + +#define CH7006_SUBC_INC2 0x1a +#define CH7006_SUBC_INC2_20 20, 3:0 + +#define CH7006_SUBC_INC3 0x1b +#define CH7006_SUBC_INC3_GPIO1_VAL (1 << 7) +#define CH7006_SUBC_INC3_GPIO0_VAL (1 << 6) +#define CH7006_SUBC_INC3_POUT_3_3V (1 << 5) +#define CH7006_SUBC_INC3_POUT_INV (1 << 4) +#define CH7006_SUBC_INC3_16 16, 3:0 + +#define CH7006_SUBC_INC4 0x1c +#define CH7006_SUBC_INC4_GPIO1_IN (1 << 7) +#define CH7006_SUBC_INC4_GPIO0_IN (1 << 6) +#define CH7006_SUBC_INC4_DS_INPUT (1 << 4) +#define CH7006_SUBC_INC4_12 12, 3:0 + +#define CH7006_SUBC_INC5 0x1d +#define CH7006_SUBC_INC5_8 8, 3:0 + +#define CH7006_SUBC_INC6 0x1e +#define CH7006_SUBC_INC6_4 4, 3:0 + +#define CH7006_SUBC_INC7 0x1f +#define CH7006_SUBC_INC7_0 0, 3:0 + +#define CH7006_PLL_CONTROL 0x20 +#define CH7006_PLL_CONTROL_CPI (1 << 5) +#define CH7006_PLL_CONTROL_CAPACITOR (1 << 4) +#define CH7006_PLL_CONTROL_7STAGES (1 << 3) +#define CH7006_PLL_CONTROL_DIGITAL_5V (1 << 2) +#define CH7006_PLL_CONTROL_ANALOG_5V (1 << 1) +#define CH7006_PLL_CONTROL_MEMORY_5V (1 << 0) + +#define CH7006_CALC_SUBC_INC0 0x21 +#define CH7006_CALC_SUBC_INC0_24 24, 4:3 +#define CH7006_CALC_SUBC_INC0_HYST 0, 2:1 +#define CH7006_CALC_SUBC_INC0_AUTO (1 << 0) + +#define CH7006_CALC_SUBC_INC1 0x22 +#define CH7006_CALC_SUBC_INC1_16 16, 7:0 + +#define CH7006_CALC_SUBC_INC2 0x23 +#define CH7006_CALC_SUBC_INC2_8 8, 7:0 + +#define CH7006_CALC_SUBC_INC3 0x24 +#define CH7006_CALC_SUBC_INC3_0 0, 7:0 + +#define CH7006_VERSION_ID 0x25 + +#endif diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index fa7b9be096bc8b25ea17bca96dee8447828bf191..9929f84ec3e1f34f9602df622af224bd21188ebb 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -15,7 +15,6 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ intel_lvds.o \ intel_bios.o \ intel_dp.o \ - intel_dp_i2c.o \ intel_hdmi.o \ intel_sdvo.o \ intel_modes.o \ @@ -23,6 +22,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ intel_fb.o \ intel_tv.o \ intel_dvo.o \ + intel_overlay.o \ dvo_ch7xxx.o \ dvo_ch7017.o \ dvo_ivch.o \ diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c index 621815b531dbba427b87e1290589a7de6a94fd6b..1184c14ba87d85b4a68599cb6fb85e0488ec2972 100644 --- a/drivers/gpu/drm/i915/dvo_ch7017.c +++ b/drivers/gpu/drm/i915/dvo_ch7017.c @@ -249,7 +249,8 @@ static bool ch7017_init(struct intel_dvo_device *dvo, if (val != CH7017_DEVICE_ID_VALUE && val != CH7018_DEVICE_ID_VALUE && val != CH7019_DEVICE_ID_VALUE) { - DRM_DEBUG("ch701x not detected, got %d: from %s Slave %d.\n", + DRM_DEBUG_KMS("ch701x not detected, got %d: from %s " + "Slave %d.\n", val, i2cbus->adapter.name,dvo->slave_addr); goto fail; } @@ -284,7 +285,7 @@ static void ch7017_mode_set(struct intel_dvo_device *dvo, uint8_t horizontal_active_pixel_output, vertical_active_line_output; uint8_t active_input_line_output; - DRM_DEBUG("Registers before mode setting\n"); + DRM_DEBUG_KMS("Registers before mode setting\n"); ch7017_dump_regs(dvo); /* LVDS PLL settings from page 75 of 7017-7017ds.pdf*/ @@ -346,7 +347,7 @@ static void ch7017_mode_set(struct intel_dvo_device *dvo, /* Turn the LVDS back on with new settings. */ ch7017_write(dvo, CH7017_LVDS_POWER_DOWN, lvds_power_down); - DRM_DEBUG("Registers after mode setting\n"); + DRM_DEBUG_KMS("Registers after mode setting\n"); ch7017_dump_regs(dvo); } @@ -386,7 +387,7 @@ static void ch7017_dump_regs(struct intel_dvo_device *dvo) #define DUMP(reg) \ do { \ ch7017_read(dvo, reg, &val); \ - DRM_DEBUG(#reg ": %02x\n", val); \ + DRM_DEBUG_KMS(#reg ": %02x\n", val); \ } while (0) DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT); diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c index a9b8962896801ffe674bafe06685e9e40f846036..d56ff5cc22b25cfb82959c4002b8ff03f56687c2 100644 --- a/drivers/gpu/drm/i915/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c @@ -152,7 +152,7 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) }; if (!ch7xxx->quiet) { - DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", + DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", addr, i2cbus->adapter.name, dvo->slave_addr); } return false; @@ -179,7 +179,7 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) return true; if (!ch7xxx->quiet) { - DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", + DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", addr, i2cbus->adapter.name, dvo->slave_addr); } @@ -207,7 +207,8 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, name = ch7xxx_get_id(vendor); if (!name) { - DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", + DRM_DEBUG_KMS("ch7xxx not detected; got 0x%02x from %s " + "slave %d.\n", vendor, adapter->name, dvo->slave_addr); goto out; } @@ -217,13 +218,14 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, goto out; if (device != CH7xxx_DID) { - DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", + DRM_DEBUG_KMS("ch7xxx not detected; got 0x%02x from %s " + "slave %d.\n", vendor, adapter->name, dvo->slave_addr); goto out; } ch7xxx->quiet = false; - DRM_DEBUG("Detected %s chipset, vendor/device ID 0x%02x/0x%02x\n", + DRM_DEBUG_KMS("Detected %s chipset, vendor/device ID 0x%02x/0x%02x\n", name, vendor, device); return true; out: @@ -315,8 +317,8 @@ static void ch7xxx_dump_regs(struct intel_dvo_device *dvo) for (i = 0; i < CH7xxx_NUM_REGS; i++) { if ((i % 8) == 0 ) - DRM_DEBUG("\n %02X: ", i); - DRM_DEBUG("%02X ", ch7xxx->mode_reg.regs[i]); + DRM_LOG_KMS("\n %02X: ", i); + DRM_LOG_KMS("%02X ", ch7xxx->mode_reg.regs[i]); } } diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c index aa176f9921fe2c772ade093f67d970647b175f34..24169e528f0f56fea5fc8a9ab5d78e27579f625c 100644 --- a/drivers/gpu/drm/i915/dvo_ivch.c +++ b/drivers/gpu/drm/i915/dvo_ivch.c @@ -202,7 +202,8 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) }; if (!priv->quiet) { - DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", + DRM_DEBUG_KMS("Unable to read register 0x%02x from " + "%s:%02x.\n", addr, i2cbus->adapter.name, dvo->slave_addr); } return false; @@ -230,7 +231,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) return true; if (!priv->quiet) { - DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", + DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", addr, i2cbus->adapter.name, dvo->slave_addr); } @@ -261,7 +262,7 @@ static bool ivch_init(struct intel_dvo_device *dvo, * the address it's responding on. */ if ((temp & VR00_BASE_ADDRESS_MASK) != dvo->slave_addr) { - DRM_DEBUG("ivch detect failed due to address mismatch " + DRM_DEBUG_KMS("ivch detect failed due to address mismatch " "(%d vs %d)\n", (temp & VR00_BASE_ADDRESS_MASK), dvo->slave_addr); goto out; @@ -367,41 +368,41 @@ static void ivch_dump_regs(struct intel_dvo_device *dvo) uint16_t val; ivch_read(dvo, VR00, &val); - DRM_DEBUG("VR00: 0x%04x\n", val); + DRM_LOG_KMS("VR00: 0x%04x\n", val); ivch_read(dvo, VR01, &val); - DRM_DEBUG("VR01: 0x%04x\n", val); + DRM_LOG_KMS("VR01: 0x%04x\n", val); ivch_read(dvo, VR30, &val); - DRM_DEBUG("VR30: 0x%04x\n", val); + DRM_LOG_KMS("VR30: 0x%04x\n", val); ivch_read(dvo, VR40, &val); - DRM_DEBUG("VR40: 0x%04x\n", val); + DRM_LOG_KMS("VR40: 0x%04x\n", val); /* GPIO registers */ ivch_read(dvo, VR80, &val); - DRM_DEBUG("VR80: 0x%04x\n", val); + DRM_LOG_KMS("VR80: 0x%04x\n", val); ivch_read(dvo, VR81, &val); - DRM_DEBUG("VR81: 0x%04x\n", val); + DRM_LOG_KMS("VR81: 0x%04x\n", val); ivch_read(dvo, VR82, &val); - DRM_DEBUG("VR82: 0x%04x\n", val); + DRM_LOG_KMS("VR82: 0x%04x\n", val); ivch_read(dvo, VR83, &val); - DRM_DEBUG("VR83: 0x%04x\n", val); + DRM_LOG_KMS("VR83: 0x%04x\n", val); ivch_read(dvo, VR84, &val); - DRM_DEBUG("VR84: 0x%04x\n", val); + DRM_LOG_KMS("VR84: 0x%04x\n", val); ivch_read(dvo, VR85, &val); - DRM_DEBUG("VR85: 0x%04x\n", val); + DRM_LOG_KMS("VR85: 0x%04x\n", val); ivch_read(dvo, VR86, &val); - DRM_DEBUG("VR86: 0x%04x\n", val); + DRM_LOG_KMS("VR86: 0x%04x\n", val); ivch_read(dvo, VR87, &val); - DRM_DEBUG("VR87: 0x%04x\n", val); + DRM_LOG_KMS("VR87: 0x%04x\n", val); ivch_read(dvo, VR88, &val); - DRM_DEBUG("VR88: 0x%04x\n", val); + DRM_LOG_KMS("VR88: 0x%04x\n", val); /* Scratch register 0 - AIM Panel type */ ivch_read(dvo, VR8E, &val); - DRM_DEBUG("VR8E: 0x%04x\n", val); + DRM_LOG_KMS("VR8E: 0x%04x\n", val); /* Scratch register 1 - Status register */ ivch_read(dvo, VR8F, &val); - DRM_DEBUG("VR8F: 0x%04x\n", val); + DRM_LOG_KMS("VR8F: 0x%04x\n", val); } static void ivch_save(struct intel_dvo_device *dvo) diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c index e1c1f7341e5cff60a15fb568e7a0dd322782ef91..0001c13f0a805edc55239147fb442488b51709ea 100644 --- a/drivers/gpu/drm/i915/dvo_sil164.c +++ b/drivers/gpu/drm/i915/dvo_sil164.c @@ -105,7 +105,7 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) }; if (!sil->quiet) { - DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", + DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", addr, i2cbus->adapter.name, dvo->slave_addr); } return false; @@ -131,7 +131,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) return true; if (!sil->quiet) { - DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", + DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", addr, i2cbus->adapter.name, dvo->slave_addr); } @@ -158,7 +158,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, goto out; if (ch != (SIL164_VID & 0xff)) { - DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", + DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n", ch, adapter->name, dvo->slave_addr); goto out; } @@ -167,13 +167,13 @@ static bool sil164_init(struct intel_dvo_device *dvo, goto out; if (ch != (SIL164_DID & 0xff)) { - DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", + DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n", ch, adapter->name, dvo->slave_addr); goto out; } sil->quiet = false; - DRM_DEBUG("init sil164 dvo controller successfully!\n"); + DRM_DEBUG_KMS("init sil164 dvo controller successfully!\n"); return true; out: @@ -241,15 +241,15 @@ static void sil164_dump_regs(struct intel_dvo_device *dvo) uint8_t val; sil164_readb(dvo, SIL164_FREQ_LO, &val); - DRM_DEBUG("SIL164_FREQ_LO: 0x%02x\n", val); + DRM_LOG_KMS("SIL164_FREQ_LO: 0x%02x\n", val); sil164_readb(dvo, SIL164_FREQ_HI, &val); - DRM_DEBUG("SIL164_FREQ_HI: 0x%02x\n", val); + DRM_LOG_KMS("SIL164_FREQ_HI: 0x%02x\n", val); sil164_readb(dvo, SIL164_REG8, &val); - DRM_DEBUG("SIL164_REG8: 0x%02x\n", val); + DRM_LOG_KMS("SIL164_REG8: 0x%02x\n", val); sil164_readb(dvo, SIL164_REG9, &val); - DRM_DEBUG("SIL164_REG9: 0x%02x\n", val); + DRM_LOG_KMS("SIL164_REG9: 0x%02x\n", val); sil164_readb(dvo, SIL164_REGC, &val); - DRM_DEBUG("SIL164_REGC: 0x%02x\n", val); + DRM_LOG_KMS("SIL164_REGC: 0x%02x\n", val); } static void sil164_save(struct intel_dvo_device *dvo) diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c index 9ecc907384ec339d312ca31c5ea26a2a0636aedf..c7c391bc116a6a22ed830a64be2a48514e114eb9 100644 --- a/drivers/gpu/drm/i915/dvo_tfp410.c +++ b/drivers/gpu/drm/i915/dvo_tfp410.c @@ -130,7 +130,7 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) }; if (!tfp->quiet) { - DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", + DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", addr, i2cbus->adapter.name, dvo->slave_addr); } return false; @@ -156,7 +156,7 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) return true; if (!tfp->quiet) { - DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", + DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", addr, i2cbus->adapter.name, dvo->slave_addr); } @@ -191,13 +191,15 @@ static bool tfp410_init(struct intel_dvo_device *dvo, tfp->quiet = true; if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) { - DRM_DEBUG("tfp410 not detected got VID %X: from %s Slave %d.\n", + DRM_DEBUG_KMS("tfp410 not detected got VID %X: from %s " + "Slave %d.\n", id, adapter->name, dvo->slave_addr); goto out; } if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) { - DRM_DEBUG("tfp410 not detected got DID %X: from %s Slave %d.\n", + DRM_DEBUG_KMS("tfp410 not detected got DID %X: from %s " + "Slave %d.\n", id, adapter->name, dvo->slave_addr); goto out; } @@ -262,33 +264,33 @@ static void tfp410_dump_regs(struct intel_dvo_device *dvo) uint8_t val, val2; tfp410_readb(dvo, TFP410_REV, &val); - DRM_DEBUG("TFP410_REV: 0x%02X\n", val); + DRM_LOG_KMS("TFP410_REV: 0x%02X\n", val); tfp410_readb(dvo, TFP410_CTL_1, &val); - DRM_DEBUG("TFP410_CTL1: 0x%02X\n", val); + DRM_LOG_KMS("TFP410_CTL1: 0x%02X\n", val); tfp410_readb(dvo, TFP410_CTL_2, &val); - DRM_DEBUG("TFP410_CTL2: 0x%02X\n", val); + DRM_LOG_KMS("TFP410_CTL2: 0x%02X\n", val); tfp410_readb(dvo, TFP410_CTL_3, &val); - DRM_DEBUG("TFP410_CTL3: 0x%02X\n", val); + DRM_LOG_KMS("TFP410_CTL3: 0x%02X\n", val); tfp410_readb(dvo, TFP410_USERCFG, &val); - DRM_DEBUG("TFP410_USERCFG: 0x%02X\n", val); + DRM_LOG_KMS("TFP410_USERCFG: 0x%02X\n", val); tfp410_readb(dvo, TFP410_DE_DLY, &val); - DRM_DEBUG("TFP410_DE_DLY: 0x%02X\n", val); + DRM_LOG_KMS("TFP410_DE_DLY: 0x%02X\n", val); tfp410_readb(dvo, TFP410_DE_CTL, &val); - DRM_DEBUG("TFP410_DE_CTL: 0x%02X\n", val); + DRM_LOG_KMS("TFP410_DE_CTL: 0x%02X\n", val); tfp410_readb(dvo, TFP410_DE_TOP, &val); - DRM_DEBUG("TFP410_DE_TOP: 0x%02X\n", val); + DRM_LOG_KMS("TFP410_DE_TOP: 0x%02X\n", val); tfp410_readb(dvo, TFP410_DE_CNT_LO, &val); tfp410_readb(dvo, TFP410_DE_CNT_HI, &val2); - DRM_DEBUG("TFP410_DE_CNT: 0x%02X%02X\n", val2, val); + DRM_LOG_KMS("TFP410_DE_CNT: 0x%02X%02X\n", val2, val); tfp410_readb(dvo, TFP410_DE_LIN_LO, &val); tfp410_readb(dvo, TFP410_DE_LIN_HI, &val2); - DRM_DEBUG("TFP410_DE_LIN: 0x%02X%02X\n", val2, val); + DRM_LOG_KMS("TFP410_DE_LIN: 0x%02X%02X\n", val2, val); tfp410_readb(dvo, TFP410_H_RES_LO, &val); tfp410_readb(dvo, TFP410_H_RES_HI, &val2); - DRM_DEBUG("TFP410_H_RES: 0x%02X%02X\n", val2, val); + DRM_LOG_KMS("TFP410_H_RES: 0x%02X%02X\n", val2, val); tfp410_readb(dvo, TFP410_V_RES_LO, &val); tfp410_readb(dvo, TFP410_V_RES_HI, &val2); - DRM_DEBUG("TFP410_V_RES: 0x%02X%02X\n", val2, val); + DRM_LOG_KMS("TFP410_V_RES: 0x%02X%02X\n", val2, val); } static void tfp410_save(struct intel_dvo_device *dvo) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 26bf0552b3cb572cf3c03b7c63e3a338573eddad..18476bf0b5805add492f00178baa2a96829d7ecc 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -27,6 +27,7 @@ */ #include +#include #include "drmP.h" #include "drm.h" #include "i915_drm.h" @@ -96,13 +97,14 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) { struct drm_gem_object *obj = obj_priv->obj; - seq_printf(m, " %p: %s %8zd %08x %08x %d %s", + seq_printf(m, " %p: %s %8zd %08x %08x %d%s%s", obj, get_pin_flag(obj_priv), obj->size, obj->read_domains, obj->write_domain, obj_priv->last_rendering_seqno, - obj_priv->dirty ? "dirty" : ""); + obj_priv->dirty ? " dirty" : "", + obj_priv->madv == I915_MADV_DONTNEED ? " purgeable" : ""); if (obj->name) seq_printf(m, " (name: %d)", obj->name); @@ -160,7 +162,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; - if (!IS_IGDNG(dev)) { + if (!IS_IRONLAKE(dev)) { seq_printf(m, "Interrupt enable: %08x\n", I915_READ(IER)); seq_printf(m, "Interrupt identity: %08x\n", @@ -412,6 +414,109 @@ static int i915_registers_info(struct seq_file *m, void *data) { return 0; } +static int +i915_wedged_open(struct inode *inode, + struct file *filp) +{ + filp->private_data = inode->i_private; + return 0; +} + +static ssize_t +i915_wedged_read(struct file *filp, + char __user *ubuf, + size_t max, + loff_t *ppos) +{ + struct drm_device *dev = filp->private_data; + drm_i915_private_t *dev_priv = dev->dev_private; + char buf[80]; + int len; + + len = snprintf(buf, sizeof (buf), + "wedged : %d\n", + atomic_read(&dev_priv->mm.wedged)); + + return simple_read_from_buffer(ubuf, max, ppos, buf, len); +} + +static ssize_t +i915_wedged_write(struct file *filp, + const char __user *ubuf, + size_t cnt, + loff_t *ppos) +{ + struct drm_device *dev = filp->private_data; + drm_i915_private_t *dev_priv = dev->dev_private; + char buf[20]; + int val = 1; + + if (cnt > 0) { + if (cnt > sizeof (buf) - 1) + return -EINVAL; + + if (copy_from_user(buf, ubuf, cnt)) + return -EFAULT; + buf[cnt] = 0; + + val = simple_strtoul(buf, NULL, 0); + } + + DRM_INFO("Manually setting wedged to %d\n", val); + + atomic_set(&dev_priv->mm.wedged, val); + if (val) { + DRM_WAKEUP(&dev_priv->irq_queue); + queue_work(dev_priv->wq, &dev_priv->error_work); + } + + return cnt; +} + +static const struct file_operations i915_wedged_fops = { + .owner = THIS_MODULE, + .open = i915_wedged_open, + .read = i915_wedged_read, + .write = i915_wedged_write, +}; + +/* As the drm_debugfs_init() routines are called before dev->dev_private is + * allocated we need to hook into the minor for release. */ +static int +drm_add_fake_info_node(struct drm_minor *minor, + struct dentry *ent, + const void *key) +{ + struct drm_info_node *node; + + node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL); + if (node == NULL) { + debugfs_remove(ent); + return -ENOMEM; + } + + node->minor = minor; + node->dent = ent; + node->info_ent = (void *) key; + list_add(&node->list, &minor->debugfs_nodes.list); + + return 0; +} + +static int i915_wedged_create(struct dentry *root, struct drm_minor *minor) +{ + struct drm_device *dev = minor->dev; + struct dentry *ent; + + ent = debugfs_create_file("i915_wedged", + S_IRUGO | S_IWUSR, + root, dev, + &i915_wedged_fops); + if (IS_ERR(ent)) + return PTR_ERR(ent); + + return drm_add_fake_info_node(minor, ent, &i915_wedged_fops); +} static struct drm_info_list i915_debugfs_list[] = { {"i915_regs", i915_registers_info, 0}, @@ -432,6 +537,12 @@ static struct drm_info_list i915_debugfs_list[] = { int i915_debugfs_init(struct drm_minor *minor) { + int ret; + + ret = i915_wedged_create(minor->debugfs_root, minor); + if (ret) + return ret; + return drm_debugfs_create_files(i915_debugfs_list, I915_DEBUGFS_ENTRIES, minor->debugfs_root, minor); @@ -441,7 +552,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor) { drm_debugfs_remove_files(i915_debugfs_list, I915_DEBUGFS_ENTRIES, minor); + drm_debugfs_remove_files((struct drm_info_list *) &i915_wedged_fops, + 1, minor); } #endif /* CONFIG_DEBUG_FS */ - diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index e5b138be45fa1d363ad95285d6f1ff7aeb6ae832..701bfeac7f5702f3774a86b1c1f156fd1abf3e9a 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -807,6 +807,12 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_NUM_FENCES_AVAIL: value = dev_priv->num_fence_regs - dev_priv->fence_reg_start; break; + case I915_PARAM_HAS_OVERLAY: + value = dev_priv->overlay ? 1 : 0; + break; + case I915_PARAM_HAS_PAGEFLIPPING: + value = 1; + break; default: DRM_DEBUG_DRIVER("Unknown parameter %d\n", param->param); @@ -962,7 +968,7 @@ static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size, * Some of the preallocated space is taken by the GTT * and popup. GTT is 1K per MB of aperture size, and popup is 4K. */ - if (IS_G4X(dev) || IS_IGD(dev) || IS_IGDNG(dev)) + if (IS_G4X(dev) || IS_PINEVIEW(dev) || IS_IRONLAKE(dev)) overhead = 4096; else overhead = (*aperture_size / 1024) + 4096; @@ -1048,7 +1054,7 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev, int gtt_offset, gtt_size; if (IS_I965G(dev)) { - if (IS_G4X(dev) || IS_IGDNG(dev)) { + if (IS_G4X(dev) || IS_IRONLAKE(dev)) { gtt_offset = 2*1024*1024; gtt_size = 2*1024*1024; } else { @@ -1070,7 +1076,7 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev, entry = *(volatile u32 *)(gtt + (gtt_addr / 1024)); - DRM_DEBUG("GTT addr: 0x%08lx, PTE: 0x%08lx\n", gtt_addr, entry); + DRM_DEBUG_DRIVER("GTT addr: 0x%08lx, PTE: 0x%08lx\n", gtt_addr, entry); /* Mask out these reserved bits on this hardware. */ if (!IS_I9XX(dev) || IS_I915G(dev) || IS_I915GM(dev) || @@ -1096,7 +1102,7 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev, phys =(entry & PTE_ADDRESS_MASK) | ((uint64_t)(entry & PTE_ADDRESS_MASK_HIGH) << (32 - 4)); - DRM_DEBUG("GTT addr: 0x%08lx, phys addr: 0x%08lx\n", gtt_addr, phys); + DRM_DEBUG_DRIVER("GTT addr: 0x%08lx, phys addr: 0x%08lx\n", gtt_addr, phys); return phys; } @@ -1306,7 +1312,7 @@ static void i915_get_mem_freq(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; u32 tmp; - if (!IS_IGD(dev)) + if (!IS_PINEVIEW(dev)) return; tmp = I915_READ(CLKCFG); @@ -1413,7 +1419,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (ret) goto out_iomapfree; - dev_priv->wq = create_workqueue("i915"); + dev_priv->wq = create_singlethread_workqueue("i915"); if (dev_priv->wq == NULL) { DRM_ERROR("Failed to create our workqueue.\n"); ret = -ENOMEM; @@ -1434,7 +1440,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev->driver->get_vblank_counter = i915_get_vblank_counter; dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ - if (IS_G4X(dev) || IS_IGDNG(dev)) { + if (IS_G4X(dev) || IS_IRONLAKE(dev)) { dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ dev->driver->get_vblank_counter = gm45_get_vblank_counter; } @@ -1489,9 +1495,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) } /* Must be done after probing outputs */ - /* FIXME: verify on IGDNG */ - if (!IS_IGDNG(dev)) - intel_opregion_init(dev, 0); + intel_opregion_init(dev, 0); setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, (unsigned long) dev); @@ -1525,6 +1529,15 @@ int i915_driver_unload(struct drm_device *dev) } if (drm_core_check_feature(dev, DRIVER_MODESET)) { + /* + * free the memory space allocated for the child device + * config parsed from VBT + */ + if (dev_priv->child_dev && dev_priv->child_dev_num) { + kfree(dev_priv->child_dev); + dev_priv->child_dev = NULL; + dev_priv->child_dev_num = 0; + } drm_irq_uninstall(dev); vga_client_register(dev->pdev, NULL, NULL, NULL); } @@ -1535,8 +1548,7 @@ int i915_driver_unload(struct drm_device *dev) if (dev_priv->regs != NULL) iounmap(dev_priv->regs); - if (!IS_IGDNG(dev)) - intel_opregion_free(dev, 0); + intel_opregion_free(dev, 0); if (drm_core_check_feature(dev, DRIVER_MODESET)) { intel_modeset_cleanup(dev); @@ -1548,6 +1560,8 @@ int i915_driver_unload(struct drm_device *dev) mutex_unlock(&dev->struct_mutex); drm_mm_takedown(&dev_priv->vram); i915_gem_lastclose(dev); + + intel_cleanup_overlay(dev); } pci_dev_put(dev_priv->bridge_dev); @@ -1656,6 +1670,8 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0), DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, 0), + DRM_IOCTL_DEF(DRM_I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 7f436ec075f6221df8ee6beafebae603054be003..2fa217862058d849fe3b5723cf578297777cbe53 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -333,6 +333,7 @@ static struct drm_driver driver = { .mmap = drm_gem_mmap, .poll = drm_poll, .fasync = drm_fasync, + .read = drm_read, #ifdef CONFIG_COMPAT .compat_ioctl = i915_compat_ioctl, #endif diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a725f6591192e2216798fc4dcf04108125795b3e..fbecac72f5bb1ba08477486d5f89914e164f98d2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -170,6 +170,8 @@ struct drm_i915_display_funcs { /* clock gating init */ }; +struct intel_overlay; + typedef struct drm_i915_private { struct drm_device *dev; @@ -187,6 +189,7 @@ typedef struct drm_i915_private { unsigned int status_gfx_addr; drm_local_map_t hws_map; struct drm_gem_object *hws_obj; + struct drm_gem_object *pwrctx; struct resource mch_res; @@ -206,11 +209,13 @@ typedef struct drm_i915_private { /** Cached value of IMR to avoid reads in updating the bitfield */ u32 irq_mask_reg; u32 pipestat[2]; - /** splitted irq regs for graphics and display engine on IGDNG, + /** splitted irq regs for graphics and display engine on Ironlake, irq_mask_reg is still used for display irq. */ u32 gt_irq_mask_reg; u32 gt_irq_enable_reg; u32 de_irq_enable_reg; + u32 pch_irq_mask_reg; + u32 pch_irq_enable_reg; u32 hotplug_supported_mask; struct work_struct hotplug_work; @@ -240,6 +245,9 @@ typedef struct drm_i915_private { struct intel_opregion opregion; + /* overlay */ + struct intel_overlay *overlay; + /* LVDS info */ int backlight_duty_cycle; /* restore backlight to this value */ bool panel_wants_dither; @@ -258,7 +266,7 @@ typedef struct drm_i915_private { struct notifier_block lid_notifier; - int crt_ddc_bus; /* -1 = unknown, else GPIO to use for CRT DDC */ + int crt_ddc_bus; /* 0 = unknown, else GPIO to use for CRT DDC */ struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ int num_fence_regs; /* 8 on pre-965, 16 otherwise */ @@ -280,6 +288,7 @@ typedef struct drm_i915_private { u32 saveDSPBCNTR; u32 saveDSPARB; u32 saveRENDERSTANDBY; + u32 savePWRCTXA; u32 saveHWS; u32 savePIPEACONF; u32 savePIPEBCONF; @@ -374,8 +383,6 @@ typedef struct drm_i915_private { u32 saveFDI_RXA_IMR; u32 saveFDI_RXB_IMR; u32 saveCACHE_MODE_0; - u32 saveD_STATE; - u32 saveDSPCLK_GATE_D; u32 saveMI_ARB_STATE; u32 saveSWF0[16]; u32 saveSWF1[16]; @@ -539,13 +546,21 @@ typedef struct drm_i915_private { /* indicate whether the LVDS_BORDER should be enabled or not */ unsigned int lvds_border_bits; + struct drm_crtc *plane_to_crtc_mapping[2]; + struct drm_crtc *pipe_to_crtc_mapping[2]; + wait_queue_head_t pending_flip_queue; + /* Reclocking support */ bool render_reclock_avail; bool lvds_downclock_avail; + /* indicates the reduced downclock for LVDS*/ + int lvds_downclock; struct work_struct idle_work; struct timer_list idle_timer; bool busy; u16 orig_clock; + int child_dev_num; + struct child_device_config *child_dev; } drm_i915_private_t; /** driver private structure attached to each drm_gem_object */ @@ -638,6 +653,13 @@ struct drm_i915_gem_object { * Advice: are the backing pages purgeable? */ int madv; + + /** + * Number of crtcs where this object is currently the fb, but + * will be page flipped away on the next vblank. When it + * reaches 0, dev_priv->pending_flip_queue will be woken up. + */ + atomic_t pending_flip; }; /** @@ -738,6 +760,8 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); void i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); +void intel_enable_asle (struct drm_device *dev); + /* i915_mem.c */ extern int i915_mem_alloc(struct drm_device *dev, void *data, @@ -813,6 +837,9 @@ void i915_gem_cleanup_ringbuffer(struct drm_device *dev); int i915_gem_do_init(struct drm_device *dev, unsigned long start, unsigned long end); int i915_gem_idle(struct drm_device *dev); +uint32_t i915_add_request(struct drm_device *dev, struct drm_file *file_priv, + uint32_t flush_domains); +int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write); @@ -824,6 +851,7 @@ void i915_gem_free_all_phys_object(struct drm_device *dev); int i915_gem_object_get_pages(struct drm_gem_object *obj); void i915_gem_object_put_pages(struct drm_gem_object *obj); void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv); +void i915_gem_object_flush_write_domain(struct drm_gem_object *obj); void i915_gem_shrinker_init(void); void i915_gem_shrinker_exit(void); @@ -863,11 +891,13 @@ extern int i915_restore_state(struct drm_device *dev); extern int intel_opregion_init(struct drm_device *dev, int resume); extern void intel_opregion_free(struct drm_device *dev, int suspend); extern void opregion_asle_intr(struct drm_device *dev); +extern void ironlake_opregion_gse_intr(struct drm_device *dev); extern void opregion_enable_asle(struct drm_device *dev); #else static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; } static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; } static inline void opregion_asle_intr(struct drm_device *dev) { return; } +static inline void ironlake_opregion_gse_intr(struct drm_device *dev) { return; } static inline void opregion_enable_asle(struct drm_device *dev) { return; } #endif @@ -955,8 +985,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define IS_I830(dev) ((dev)->pci_device == 0x3577) #define IS_845G(dev) ((dev)->pci_device == 0x2562) #define IS_I85X(dev) ((dev)->pci_device == 0x3582) -#define IS_I855(dev) ((dev)->pci_device == 0x3582) #define IS_I865G(dev) ((dev)->pci_device == 0x2572) +#define IS_I8XX(dev) (IS_I830(dev) || IS_845G(dev) || IS_I85X(dev) || IS_I865G(dev)) #define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a) #define IS_I915GM(dev) ((dev)->pci_device == 0x2592) @@ -990,47 +1020,51 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); (dev)->pci_device == 0x2E42 || \ IS_GM45(dev)) -#define IS_IGDG(dev) ((dev)->pci_device == 0xa001) -#define IS_IGDGM(dev) ((dev)->pci_device == 0xa011) -#define IS_IGD(dev) (IS_IGDG(dev) || IS_IGDGM(dev)) +#define IS_PINEVIEW_G(dev) ((dev)->pci_device == 0xa001) +#define IS_PINEVIEW_M(dev) ((dev)->pci_device == 0xa011) +#define IS_PINEVIEW(dev) (IS_PINEVIEW_G(dev) || IS_PINEVIEW_M(dev)) #define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \ (dev)->pci_device == 0x29B2 || \ (dev)->pci_device == 0x29D2 || \ - (IS_IGD(dev))) + (IS_PINEVIEW(dev))) -#define IS_IGDNG_D(dev) ((dev)->pci_device == 0x0042) -#define IS_IGDNG_M(dev) ((dev)->pci_device == 0x0046) -#define IS_IGDNG(dev) (IS_IGDNG_D(dev) || IS_IGDNG_M(dev)) +#define IS_IRONLAKE_D(dev) ((dev)->pci_device == 0x0042) +#define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046) +#define IS_IRONLAKE(dev) (IS_IRONLAKE_D(dev) || IS_IRONLAKE_M(dev)) #define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \ IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev) || \ - IS_IGDNG(dev)) + IS_IRONLAKE(dev)) #define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \ IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev) || \ - IS_IGD(dev) || IS_IGDNG_M(dev)) + IS_PINEVIEW(dev) || IS_IRONLAKE_M(dev)) #define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev) || \ - IS_IGDNG(dev)) + IS_IRONLAKE(dev)) /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte * rows, which changed the alignment requirements and fence programming. */ #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \ IS_I915GM(dev))) -#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev)) -#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev)) -#define SUPPORTS_EDP(dev) (IS_IGDNG_M(dev)) +#define SUPPORTS_DIGITAL_OUTPUTS(dev) (IS_I9XX(dev) && !IS_PINEVIEW(dev)) +#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) +#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) +#define SUPPORTS_EDP(dev) (IS_IRONLAKE_M(dev)) +#define SUPPORTS_TV(dev) (IS_I9XX(dev) && IS_MOBILE(dev) && \ + !IS_IRONLAKE(dev) && !IS_PINEVIEW(dev)) #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev) || IS_I965G(dev)) /* dsparb controlled by hw only */ -#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev)) +#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) -#define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IGDNG(dev)) -#define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IGDNG(dev)) +#define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IRONLAKE(dev)) +#define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) #define I915_HAS_FBC(dev) (IS_MOBILE(dev) && \ (IS_I9XX(dev) || IS_GM45(dev)) && \ - !IS_IGD(dev) && \ - !IS_IGDNG(dev)) + !IS_PINEVIEW(dev) && \ + !IS_IRONLAKE(dev)) +#define I915_HAS_RC6(dev) (IS_I965GM(dev) || IS_GM45(dev) || IS_IRONLAKE_M(dev)) #define PRIMARY_RINGBUFFER_SIZE (128*1024) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a2a3fa5999236c70f5c14ec91456fb52f644e044..8c463cf2050a8dfc57e308a6d8376670c84fd45a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1288,6 +1288,7 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) list->hash.key = list->file_offset_node->start; if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) { DRM_ERROR("failed to add to map hash\n"); + ret = -ENOMEM; goto out_free_mm; } @@ -1583,7 +1584,7 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj) * * Returned sequence numbers are nonzero on success. */ -static uint32_t +uint32_t i915_add_request(struct drm_device *dev, struct drm_file *file_priv, uint32_t flush_domains) { @@ -1617,7 +1618,7 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, OUT_RING(MI_USER_INTERRUPT); ADVANCE_LP_RING(); - DRM_DEBUG("%d\n", seqno); + DRM_DEBUG_DRIVER("%d\n", seqno); request->seqno = seqno; request->emitted_jiffies = jiffies; @@ -1820,12 +1821,8 @@ i915_gem_retire_work_handler(struct work_struct *work) mutex_unlock(&dev->struct_mutex); } -/** - * Waits for a sequence number to be signaled, and cleans up the - * request and object lists appropriately for that event. - */ -static int -i915_wait_request(struct drm_device *dev, uint32_t seqno) +int +i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible) { drm_i915_private_t *dev_priv = dev->dev_private; u32 ier; @@ -1837,7 +1834,7 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno) return -EIO; if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) { - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) ier = I915_READ(DEIER) | I915_READ(GTIER); else ier = I915_READ(IER); @@ -1852,10 +1849,15 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno) dev_priv->mm.waiting_gem_seqno = seqno; i915_user_irq_get(dev); - ret = wait_event_interruptible(dev_priv->irq_queue, - i915_seqno_passed(i915_get_gem_seqno(dev), - seqno) || - atomic_read(&dev_priv->mm.wedged)); + if (interruptible) + ret = wait_event_interruptible(dev_priv->irq_queue, + i915_seqno_passed(i915_get_gem_seqno(dev), seqno) || + atomic_read(&dev_priv->mm.wedged)); + else + wait_event(dev_priv->irq_queue, + i915_seqno_passed(i915_get_gem_seqno(dev), seqno) || + atomic_read(&dev_priv->mm.wedged)); + i915_user_irq_put(dev); dev_priv->mm.waiting_gem_seqno = 0; @@ -1879,6 +1881,16 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno) return ret; } +/** + * Waits for a sequence number to be signaled, and cleans up the + * request and object lists appropriately for that event. + */ +static int +i915_wait_request(struct drm_device *dev, uint32_t seqno) +{ + return i915_do_wait_request(dev, seqno, 1); +} + static void i915_gem_flush(struct drm_device *dev, uint32_t invalidate_domains, @@ -1947,7 +1959,7 @@ i915_gem_flush(struct drm_device *dev, #endif BEGIN_LP_RING(2); OUT_RING(cmd); - OUT_RING(0); /* noop */ + OUT_RING(MI_NOOP); ADVANCE_LP_RING(); } } @@ -2760,6 +2772,22 @@ i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj) old_write_domain); } +void +i915_gem_object_flush_write_domain(struct drm_gem_object *obj) +{ + switch (obj->write_domain) { + case I915_GEM_DOMAIN_GTT: + i915_gem_object_flush_gtt_write_domain(obj); + break; + case I915_GEM_DOMAIN_CPU: + i915_gem_object_flush_cpu_write_domain(obj); + break; + default: + i915_gem_object_flush_gpu_write_domain(obj); + break; + } +} + /** * Moves a single object to the GTT read, and possibly write domain. * @@ -3525,6 +3553,41 @@ i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer *exec, return 0; } +static int +i915_gem_wait_for_pending_flip(struct drm_device *dev, + struct drm_gem_object **object_list, + int count) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj_priv; + DEFINE_WAIT(wait); + int i, ret = 0; + + for (;;) { + prepare_to_wait(&dev_priv->pending_flip_queue, + &wait, TASK_INTERRUPTIBLE); + for (i = 0; i < count; i++) { + obj_priv = object_list[i]->driver_private; + if (atomic_read(&obj_priv->pending_flip) > 0) + break; + } + if (i == count) + break; + + if (!signal_pending(current)) { + mutex_unlock(&dev->struct_mutex); + schedule(); + mutex_lock(&dev->struct_mutex); + continue; + } + ret = -ERESTARTSYS; + break; + } + finish_wait(&dev_priv->pending_flip_queue, &wait); + + return ret; +} + int i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -3540,7 +3603,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, int ret, ret2, i, pinned = 0; uint64_t exec_offset; uint32_t seqno, flush_domains, reloc_index; - int pin_tries; + int pin_tries, flips; #if WATCH_EXEC DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", @@ -3552,8 +3615,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, return -EINVAL; } /* Copy in the exec list from userland */ - exec_list = drm_calloc_large(sizeof(*exec_list), args->buffer_count); - object_list = drm_calloc_large(sizeof(*object_list), args->buffer_count); + exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count); + object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count); if (exec_list == NULL || object_list == NULL) { DRM_ERROR("Failed to allocate exec or object list " "for %d buffers\n", @@ -3598,20 +3661,19 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, i915_verify_inactive(dev, __FILE__, __LINE__); if (atomic_read(&dev_priv->mm.wedged)) { - DRM_ERROR("Execbuf while wedged\n"); mutex_unlock(&dev->struct_mutex); ret = -EIO; goto pre_mutex_err; } if (dev_priv->mm.suspended) { - DRM_ERROR("Execbuf while VT-switched.\n"); mutex_unlock(&dev->struct_mutex); ret = -EBUSY; goto pre_mutex_err; } /* Look up object handles */ + flips = 0; for (i = 0; i < args->buffer_count; i++) { object_list[i] = drm_gem_object_lookup(dev, file_priv, exec_list[i].handle); @@ -3630,6 +3692,14 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, goto err; } obj_priv->in_execbuffer = true; + flips += atomic_read(&obj_priv->pending_flip); + } + + if (flips > 0) { + ret = i915_gem_wait_for_pending_flip(dev, object_list, + args->buffer_count); + if (ret) + goto err; } /* Pin and relocate */ @@ -4356,7 +4426,7 @@ i915_gem_init_hws(struct drm_device *dev) memset(dev_priv->hw_status_page, 0, PAGE_SIZE); I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr); I915_READ(HWS_PGA); /* posting read */ - DRM_DEBUG("hws offset: 0x%08x\n", dev_priv->status_gfx_addr); + DRM_DEBUG_DRIVER("hws offset: 0x%08x\n", dev_priv->status_gfx_addr); return 0; } @@ -4614,8 +4684,8 @@ i915_gem_load(struct drm_device *dev) for (i = 0; i < 8; i++) I915_WRITE(FENCE_REG_945_8 + (i * 4), 0); } - i915_gem_detect_bit_6_swizzle(dev); + init_waitqueue_head(&dev_priv->pending_flip_queue); } /* @@ -4790,7 +4860,7 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, user_data = (char __user *) (uintptr_t) args->data_ptr; obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; - DRM_DEBUG("obj_addr %p, %lld\n", obj_addr, args->size); + DRM_DEBUG_DRIVER("obj_addr %p, %lld\n", obj_addr, args->size); ret = copy_from_user(obj_addr, user_data, args->size); if (ret) return -EFAULT; diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 200e398453ca5305987a2d851a5361ba29d7bba2..30d6af6c09bbe33e2fc8a333252b838f1817488c 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -121,7 +121,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev) 0, pcibios_align_resource, dev_priv->bridge_dev); if (ret) { - DRM_DEBUG("failed bus alloc: %d\n", ret); + DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret); dev_priv->mch_res.start = 0; goto out; } @@ -209,8 +209,8 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; bool need_disable; - if (IS_IGDNG(dev)) { - /* On IGDNG whatever DRAM config, GPU always do + if (IS_IRONLAKE(dev)) { + /* On Ironlake whatever DRAM config, GPU always do * same swizzling setup. */ swizzle_x = I915_BIT_6_SWIZZLE_9_10; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index aa7fd82aa6eb343afa3fdb4b7088104f311f00d9..85f4c5de97e2d438d3c05bd942ff0deb481e64eb 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -43,10 +43,13 @@ * we leave them always unmasked in IMR and then control enabling them through * PIPESTAT alone. */ -#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \ - I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | \ - I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) +#define I915_INTERRUPT_ENABLE_FIX \ + (I915_ASLE_INTERRUPT | \ + I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | \ + I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | \ + I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT | \ + I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) /** Interrupts that we mask and unmask at runtime. */ #define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT) @@ -61,7 +64,7 @@ DRM_I915_VBLANK_PIPE_B) void -igdng_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) +ironlake_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) { if ((dev_priv->gt_irq_mask_reg & mask) != 0) { dev_priv->gt_irq_mask_reg &= ~mask; @@ -71,7 +74,7 @@ igdng_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) } static inline void -igdng_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) +ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) { if ((dev_priv->gt_irq_mask_reg & mask) != mask) { dev_priv->gt_irq_mask_reg |= mask; @@ -82,7 +85,7 @@ igdng_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) /* For display hotplug interrupt */ void -igdng_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) +ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) { if ((dev_priv->irq_mask_reg & mask) != 0) { dev_priv->irq_mask_reg &= ~mask; @@ -92,7 +95,7 @@ igdng_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) } static inline void -igdng_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask) +ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask) { if ((dev_priv->irq_mask_reg & mask) != mask) { dev_priv->irq_mask_reg |= mask; @@ -156,6 +159,20 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) } } +/** + * intel_enable_asle - enable ASLE interrupt for OpRegion + */ +void intel_enable_asle (struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + + if (IS_IRONLAKE(dev)) + ironlake_enable_display_irq(dev_priv, DE_GSE); + else + i915_enable_pipestat(dev_priv, 1, + I915_LEGACY_BLC_EVENT_ENABLE); +} + /** * i915_pipe_enabled - check if a pipe is enabled * @dev: DRM device @@ -191,7 +208,8 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; if (!i915_pipe_enabled(dev, pipe)) { - DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe); + DRM_DEBUG_DRIVER("trying to get vblank count for disabled " + "pipe %d\n", pipe); return 0; } @@ -220,7 +238,8 @@ u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45; if (!i915_pipe_enabled(dev, pipe)) { - DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe); + DRM_DEBUG_DRIVER("trying to get vblank count for disabled " + "pipe %d\n", pipe); return 0; } @@ -250,12 +269,12 @@ static void i915_hotplug_work_func(struct work_struct *work) drm_sysfs_hotplug_event(dev); } -irqreturn_t igdng_irq_handler(struct drm_device *dev) +irqreturn_t ironlake_irq_handler(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret = IRQ_NONE; - u32 de_iir, gt_iir, de_ier; - u32 new_de_iir, new_gt_iir; + u32 de_iir, gt_iir, de_ier, pch_iir; + u32 new_de_iir, new_gt_iir, new_pch_iir; struct drm_i915_master_private *master_priv; /* disable master interrupt before clearing iir */ @@ -265,13 +284,18 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) de_iir = I915_READ(DEIIR); gt_iir = I915_READ(GTIIR); + pch_iir = I915_READ(SDEIIR); for (;;) { - if (de_iir == 0 && gt_iir == 0) + if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) break; ret = IRQ_HANDLED; + /* should clear PCH hotplug event before clear CPU irq */ + I915_WRITE(SDEIIR, pch_iir); + new_pch_iir = I915_READ(SDEIIR); + I915_WRITE(DEIIR, de_iir); new_de_iir = I915_READ(DEIIR); I915_WRITE(GTIIR, gt_iir); @@ -291,8 +315,18 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) DRM_WAKEUP(&dev_priv->irq_queue); } + if (de_iir & DE_GSE) + ironlake_opregion_gse_intr(dev); + + /* check event from PCH */ + if ((de_iir & DE_PCH_EVENT) && + (pch_iir & SDE_HOTPLUG_MASK)) { + queue_work(dev_priv->wq, &dev_priv->hotplug_work); + } + de_iir = new_de_iir; gt_iir = new_gt_iir; + pch_iir = new_pch_iir; } I915_WRITE(DEIER, de_ier); @@ -317,19 +351,19 @@ static void i915_error_work_func(struct work_struct *work) char *reset_event[] = { "RESET=1", NULL }; char *reset_done_event[] = { "ERROR=0", NULL }; - DRM_DEBUG("generating error event\n"); + DRM_DEBUG_DRIVER("generating error event\n"); kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event); if (atomic_read(&dev_priv->mm.wedged)) { if (IS_I965G(dev)) { - DRM_DEBUG("resetting chip\n"); + DRM_DEBUG_DRIVER("resetting chip\n"); kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); if (!i965_reset(dev, GDRST_RENDER)) { atomic_set(&dev_priv->mm.wedged, 0); kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event); } } else { - printk("reboot required\n"); + DRM_DEBUG_DRIVER("reboot required\n"); } } } @@ -355,7 +389,7 @@ static void i915_capture_error_state(struct drm_device *dev) error = kmalloc(sizeof(*error), GFP_ATOMIC); if (!error) { - DRM_DEBUG("out ot memory, not capturing error state\n"); + DRM_DEBUG_DRIVER("out ot memory, not capturing error state\n"); goto out; } @@ -512,7 +546,6 @@ static void i915_handle_error(struct drm_device *dev, bool wedged) /* * Wakeup waiting processes so they don't hang */ - printk("i915: Waking up sleeping processes\n"); DRM_WAKEUP(&dev_priv->irq_queue); } @@ -535,8 +568,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) atomic_inc(&dev_priv->irq_received); - if (IS_IGDNG(dev)) - return igdng_irq_handler(dev); + if (IS_IRONLAKE(dev)) + return ironlake_irq_handler(dev); iir = I915_READ(IIR); @@ -568,14 +601,14 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) */ if (pipea_stats & 0x8000ffff) { if (pipea_stats & PIPE_FIFO_UNDERRUN_STATUS) - DRM_DEBUG("pipe a underrun\n"); + DRM_DEBUG_DRIVER("pipe a underrun\n"); I915_WRITE(PIPEASTAT, pipea_stats); irq_received = 1; } if (pipeb_stats & 0x8000ffff) { if (pipeb_stats & PIPE_FIFO_UNDERRUN_STATUS) - DRM_DEBUG("pipe b underrun\n"); + DRM_DEBUG_DRIVER("pipe b underrun\n"); I915_WRITE(PIPEBSTAT, pipeb_stats); irq_received = 1; } @@ -591,7 +624,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) (iir & I915_DISPLAY_PORT_INTERRUPT)) { u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); - DRM_DEBUG("hotplug event received, stat 0x%08x\n", + DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n", hotplug_status); if (hotplug_status & dev_priv->hotplug_supported_mask) queue_work(dev_priv->wq, @@ -599,27 +632,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); I915_READ(PORT_HOTPLUG_STAT); - - /* EOS interrupts occurs */ - if (IS_IGD(dev) && - (hotplug_status & CRT_EOS_INT_STATUS)) { - u32 temp; - - DRM_DEBUG("EOS interrupt occurs\n"); - /* status is already cleared */ - temp = I915_READ(ADPA); - temp &= ~ADPA_DAC_ENABLE; - I915_WRITE(ADPA, temp); - - temp = I915_READ(PORT_HOTPLUG_EN); - temp &= ~CRT_EOS_INT_EN; - I915_WRITE(PORT_HOTPLUG_EN, temp); - - temp = I915_READ(PORT_HOTPLUG_STAT); - if (temp & CRT_EOS_INT_STATUS) - I915_WRITE(PORT_HOTPLUG_STAT, - CRT_EOS_INT_STATUS); - } } I915_WRITE(IIR, iir); @@ -641,14 +653,22 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); } + if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) + intel_prepare_page_flip(dev, 0); + + if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) + intel_prepare_page_flip(dev, 1); + if (pipea_stats & vblank_status) { vblank++; drm_handle_vblank(dev, 0); + intel_finish_page_flip(dev, 0); } if (pipeb_stats & vblank_status) { vblank++; drm_handle_vblank(dev, 1); + intel_finish_page_flip(dev, 1); } if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) || @@ -684,7 +704,7 @@ static int i915_emit_irq(struct drm_device * dev) i915_kernel_lost_context(dev); - DRM_DEBUG("\n"); + DRM_DEBUG_DRIVER("\n"); dev_priv->counter++; if (dev_priv->counter > 0x7FFFFFFFUL) @@ -709,8 +729,8 @@ void i915_user_irq_get(struct drm_device *dev) spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) { - if (IS_IGDNG(dev)) - igdng_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT); + if (IS_IRONLAKE(dev)) + ironlake_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT); else i915_enable_irq(dev_priv, I915_USER_INTERRUPT); } @@ -725,8 +745,8 @@ void i915_user_irq_put(struct drm_device *dev) spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0); if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { - if (IS_IGDNG(dev)) - igdng_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT); + if (IS_IRONLAKE(dev)) + ironlake_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT); else i915_disable_irq(dev_priv, I915_USER_INTERRUPT); } @@ -749,7 +769,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; int ret = 0; - DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr, + DRM_DEBUG_DRIVER("irq_nr=%d breadcrumb=%d\n", irq_nr, READ_BREADCRUMB(dev_priv)); if (READ_BREADCRUMB(dev_priv) >= irq_nr) { @@ -832,7 +852,7 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) if (!(pipeconf & PIPEACONF_ENABLE)) return -EINVAL; - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) return 0; spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); @@ -854,7 +874,7 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) return; spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); @@ -868,7 +888,7 @@ void i915_enable_interrupt (struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - if (!IS_IGDNG(dev)) + if (!IS_IRONLAKE(dev)) opregion_enable_asle(dev); dev_priv->irq_enabled = 1; } @@ -976,7 +996,7 @@ void i915_hangcheck_elapsed(unsigned long data) /* drm_dma.h hooks */ -static void igdng_irq_preinstall(struct drm_device *dev) +static void ironlake_irq_preinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -992,14 +1012,21 @@ static void igdng_irq_preinstall(struct drm_device *dev) I915_WRITE(GTIMR, 0xffffffff); I915_WRITE(GTIER, 0x0); (void) I915_READ(GTIER); + + /* south display irq */ + I915_WRITE(SDEIMR, 0xffffffff); + I915_WRITE(SDEIER, 0x0); + (void) I915_READ(SDEIER); } -static int igdng_irq_postinstall(struct drm_device *dev) +static int ironlake_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; /* enable kind of interrupts always enabled */ - u32 display_mask = DE_MASTER_IRQ_CONTROL /*| DE_PCH_EVENT */; + u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT; u32 render_mask = GT_USER_INTERRUPT; + u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | + SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; dev_priv->irq_mask_reg = ~display_mask; dev_priv->de_irq_enable_reg = display_mask; @@ -1019,6 +1046,14 @@ static int igdng_irq_postinstall(struct drm_device *dev) I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg); (void) I915_READ(GTIER); + dev_priv->pch_irq_mask_reg = ~hotplug_mask; + dev_priv->pch_irq_enable_reg = hotplug_mask; + + I915_WRITE(SDEIIR, I915_READ(SDEIIR)); + I915_WRITE(SDEIMR, dev_priv->pch_irq_mask_reg); + I915_WRITE(SDEIER, dev_priv->pch_irq_enable_reg); + (void) I915_READ(SDEIER); + return 0; } @@ -1031,8 +1066,8 @@ void i915_driver_irq_preinstall(struct drm_device * dev) INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); INIT_WORK(&dev_priv->error_work, i915_error_work_func); - if (IS_IGDNG(dev)) { - igdng_irq_preinstall(dev); + if (IS_IRONLAKE(dev)) { + ironlake_irq_preinstall(dev); return; } @@ -1059,8 +1094,8 @@ int i915_driver_irq_postinstall(struct drm_device *dev) dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; - if (IS_IGDNG(dev)) - return igdng_irq_postinstall(dev); + if (IS_IRONLAKE(dev)) + return ironlake_irq_postinstall(dev); /* Unmask the interrupts that we always want on. */ dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX; @@ -1120,7 +1155,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev) return 0; } -static void igdng_irq_uninstall(struct drm_device *dev) +static void ironlake_irq_uninstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; I915_WRITE(HWSTAM, 0xffffffff); @@ -1143,8 +1178,8 @@ void i915_driver_irq_uninstall(struct drm_device * dev) dev_priv->vblank_pipe = 0; - if (IS_IGDNG(dev)) { - igdng_irq_uninstall(dev); + if (IS_IRONLAKE(dev)) { + ironlake_irq_uninstall(dev); return; } diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c index 2d5193556d3f48315714d190c686325e950644b0..7cc8410239cb7855ac732fdf6946cdd059c8ab48 100644 --- a/drivers/gpu/drm/i915/i915_opregion.c +++ b/drivers/gpu/drm/i915/i915_opregion.c @@ -118,6 +118,10 @@ struct opregion_asle { #define ASLE_BACKLIGHT_FAIL (2<<12) #define ASLE_PFIT_FAIL (2<<14) #define ASLE_PWM_FREQ_FAIL (2<<16) +#define ASLE_ALS_ILLUM_FAILED (1<<10) +#define ASLE_BACKLIGHT_FAILED (1<<12) +#define ASLE_PFIT_FAILED (1<<14) +#define ASLE_PWM_FREQ_FAILED (1<<16) /* ASLE backlight brightness to set */ #define ASLE_BCLP_VALID (1<<31) @@ -163,7 +167,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) if (IS_I965G(dev) && (blc_pwm_ctl2 & BLM_COMBINATION_MODE)) pci_write_config_dword(dev->pdev, PCI_LBPC, bclp); else { - if (IS_IGD(dev)) { + if (IS_PINEVIEW(dev)) { blc_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1); max_backlight = (blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> BACKLIGHT_MODULATION_FREQ_SHIFT; @@ -224,7 +228,7 @@ void opregion_asle_intr(struct drm_device *dev) asle_req = asle->aslc & ASLE_REQ_MSK; if (!asle_req) { - DRM_DEBUG("non asle set request??\n"); + DRM_DEBUG_DRIVER("non asle set request??\n"); return; } @@ -243,6 +247,73 @@ void opregion_asle_intr(struct drm_device *dev) asle->aslc = asle_stat; } +static u32 asle_set_backlight_ironlake(struct drm_device *dev, u32 bclp) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct opregion_asle *asle = dev_priv->opregion.asle; + u32 cpu_pwm_ctl, pch_pwm_ctl2; + u32 max_backlight, level; + + if (!(bclp & ASLE_BCLP_VALID)) + return ASLE_BACKLIGHT_FAILED; + + bclp &= ASLE_BCLP_MSK; + if (bclp < 0 || bclp > 255) + return ASLE_BACKLIGHT_FAILED; + + cpu_pwm_ctl = I915_READ(BLC_PWM_CPU_CTL); + pch_pwm_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); + /* get the max PWM frequency */ + max_backlight = (pch_pwm_ctl2 >> 16) & BACKLIGHT_DUTY_CYCLE_MASK; + /* calculate the expected PMW frequency */ + level = (bclp * max_backlight) / 255; + /* reserve the high 16 bits */ + cpu_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK); + /* write the updated PWM frequency */ + I915_WRITE(BLC_PWM_CPU_CTL, cpu_pwm_ctl | level); + + asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID; + + return 0; +} + +void ironlake_opregion_gse_intr(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct opregion_asle *asle = dev_priv->opregion.asle; + u32 asle_stat = 0; + u32 asle_req; + + if (!asle) + return; + + asle_req = asle->aslc & ASLE_REQ_MSK; + + if (!asle_req) { + DRM_DEBUG_DRIVER("non asle set request??\n"); + return; + } + + if (asle_req & ASLE_SET_ALS_ILLUM) { + DRM_DEBUG_DRIVER("Illum is not supported\n"); + asle_stat |= ASLE_ALS_ILLUM_FAILED; + } + + if (asle_req & ASLE_SET_BACKLIGHT) + asle_stat |= asle_set_backlight_ironlake(dev, asle->bclp); + + if (asle_req & ASLE_SET_PFIT) { + DRM_DEBUG_DRIVER("Pfit is not supported\n"); + asle_stat |= ASLE_PFIT_FAILED; + } + + if (asle_req & ASLE_SET_PWM_FREQ) { + DRM_DEBUG_DRIVER("PWM freq is not supported\n"); + asle_stat |= ASLE_PWM_FREQ_FAILED; + } + + asle->aslc = asle_stat; +} #define ASLE_ALS_EN (1<<0) #define ASLE_BLC_EN (1<<1) #define ASLE_PFIT_EN (1<<2) @@ -258,8 +329,7 @@ void opregion_enable_asle(struct drm_device *dev) unsigned long irqflags; spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); - i915_enable_pipestat(dev_priv, 1, - I915_LEGACY_BLC_EVENT_ENABLE); + intel_enable_asle(dev); spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); } @@ -361,9 +431,9 @@ int intel_opregion_init(struct drm_device *dev, int resume) int err = 0; pci_read_config_dword(dev->pdev, PCI_ASLS, &asls); - DRM_DEBUG("graphic opregion physical addr: 0x%x\n", asls); + DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls); if (asls == 0) { - DRM_DEBUG("ACPI OpRegion not supported!\n"); + DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n"); return -ENOTSUPP; } @@ -373,30 +443,30 @@ int intel_opregion_init(struct drm_device *dev, int resume) opregion->header = base; if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) { - DRM_DEBUG("opregion signature mismatch\n"); + DRM_DEBUG_DRIVER("opregion signature mismatch\n"); err = -EINVAL; goto err_out; } mboxes = opregion->header->mboxes; if (mboxes & MBOX_ACPI) { - DRM_DEBUG("Public ACPI methods supported\n"); + DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); opregion->acpi = base + OPREGION_ACPI_OFFSET; if (drm_core_check_feature(dev, DRIVER_MODESET)) intel_didl_outputs(dev); } else { - DRM_DEBUG("Public ACPI methods not supported\n"); + DRM_DEBUG_DRIVER("Public ACPI methods not supported\n"); err = -ENOTSUPP; goto err_out; } opregion->enabled = 1; if (mboxes & MBOX_SWSCI) { - DRM_DEBUG("SWSCI supported\n"); + DRM_DEBUG_DRIVER("SWSCI supported\n"); opregion->swsci = base + OPREGION_SWSCI_OFFSET; } if (mboxes & MBOX_ASLE) { - DRM_DEBUG("ASLE supported\n"); + DRM_DEBUG_DRIVER("ASLE supported\n"); opregion->asle = base + OPREGION_ASLE_OFFSET; opregion_enable_asle(dev); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1687edf68795a088751d3f68e41afb01db496b0c..974b3cf706184d46c4cc170cc1c606ccda75e561 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -140,6 +140,7 @@ #define MI_NOOP MI_INSTR(0, 0) #define MI_USER_INTERRUPT MI_INSTR(0x02, 0) #define MI_WAIT_FOR_EVENT MI_INSTR(0x03, 0) +#define MI_WAIT_FOR_OVERLAY_FLIP (1<<16) #define MI_WAIT_FOR_PLANE_B_FLIP (1<<6) #define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) #define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1) @@ -151,7 +152,13 @@ #define MI_END_SCENE (1 << 4) /* flush binner and incr scene count */ #define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0) #define MI_REPORT_HEAD MI_INSTR(0x07, 0) +#define MI_OVERLAY_FLIP MI_INSTR(0x11,0) +#define MI_OVERLAY_CONTINUE (0x0<<21) +#define MI_OVERLAY_ON (0x1<<21) +#define MI_OVERLAY_OFF (0x2<<21) #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0) +#define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) +#define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) #define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) #define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */ #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) @@ -260,6 +267,8 @@ #define HWS_PGA 0x02080 #define HWS_ADDRESS_MASK 0xfffff000 #define HWS_START_ADDRESS_SHIFT 4 +#define PWRCTXA 0x2088 /* 965GM+ only */ +#define PWRCTX_EN (1<<0) #define IPEIR 0x02088 #define IPEHR 0x0208c #define INSTDONE 0x02090 @@ -405,6 +414,13 @@ # define GPIO_DATA_VAL_IN (1 << 12) # define GPIO_DATA_PULLUP_DISABLE (1 << 13) +#define GMBUS0 0x5100 +#define GMBUS1 0x5104 +#define GMBUS2 0x5108 +#define GMBUS3 0x510c +#define GMBUS4 0x5110 +#define GMBUS5 0x5120 + /* * Clock control & power management */ @@ -435,7 +451,7 @@ #define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ #define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ -#define DPLL_FPA01_P1_POST_DIV_MASK_IGD 0x00ff8000 /* IGD */ +#define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */ #define I915_FIFO_UNDERRUN_STATUS (1UL<<31) #define I915_CRC_ERROR_ENABLE (1UL<<29) @@ -512,7 +528,7 @@ */ #define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000 #define DPLL_FPA01_P1_POST_DIV_SHIFT 16 -#define DPLL_FPA01_P1_POST_DIV_SHIFT_IGD 15 +#define DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW 15 /* i830, required in DVO non-gang */ #define PLL_P2_DIVIDE_BY_4 (1 << 23) #define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ @@ -522,7 +538,7 @@ #define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) #define PLL_REF_INPUT_MASK (3 << 13) #define PLL_LOAD_PULSE_PHASE_SHIFT 9 -/* IGDNG */ +/* Ironlake */ # define PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT 9 # define PLL_REF_SDVO_HDMI_MULTIPLIER_MASK (7 << 9) # define PLL_REF_SDVO_HDMI_MULTIPLIER(x) (((x)-1) << 9) @@ -586,12 +602,12 @@ #define FPB0 0x06048 #define FPB1 0x0604c #define FP_N_DIV_MASK 0x003f0000 -#define FP_N_IGD_DIV_MASK 0x00ff0000 +#define FP_N_PINEVIEW_DIV_MASK 0x00ff0000 #define FP_N_DIV_SHIFT 16 #define FP_M1_DIV_MASK 0x00003f00 #define FP_M1_DIV_SHIFT 8 #define FP_M2_DIV_MASK 0x0000003f -#define FP_M2_IGD_DIV_MASK 0x000000ff +#define FP_M2_PINEVIEW_DIV_MASK 0x000000ff #define FP_M2_DIV_SHIFT 0 #define DPLL_TEST 0x606c #define DPLLB_TEST_SDVO_DIV_1 (0 << 22) @@ -769,7 +785,8 @@ /** GM965 GM45 render standby register */ #define MCHBAR_RENDER_STANDBY 0x111B8 - +#define RCX_SW_EXIT (1<<23) +#define RSX_STATUS_MASK 0x00700000 #define PEG_BAND_GAP_DATA 0x14d68 /* @@ -844,7 +861,6 @@ #define SDVOB_HOTPLUG_INT_EN (1 << 26) #define SDVOC_HOTPLUG_INT_EN (1 << 25) #define TV_HOTPLUG_INT_EN (1 << 18) -#define CRT_EOS_INT_EN (1 << 10) #define CRT_HOTPLUG_INT_EN (1 << 9) #define CRT_HOTPLUG_FORCE_DETECT (1 << 3) #define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8) @@ -868,7 +884,6 @@ HDMID_HOTPLUG_INT_EN | \ SDVOB_HOTPLUG_INT_EN | \ SDVOC_HOTPLUG_INT_EN | \ - TV_HOTPLUG_INT_EN | \ CRT_HOTPLUG_INT_EN) @@ -879,7 +894,6 @@ #define DPC_HOTPLUG_INT_STATUS (1 << 28) #define HDMID_HOTPLUG_INT_STATUS (1 << 27) #define DPD_HOTPLUG_INT_STATUS (1 << 27) -#define CRT_EOS_INT_STATUS (1 << 12) #define CRT_HOTPLUG_INT_STATUS (1 << 11) #define TV_HOTPLUG_INT_STATUS (1 << 10) #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) @@ -1620,7 +1634,7 @@ #define DP_CLOCK_OUTPUT_ENABLE (1 << 13) #define DP_SCRAMBLING_DISABLE (1 << 12) -#define DP_SCRAMBLING_DISABLE_IGDNG (1 << 7) +#define DP_SCRAMBLING_DISABLE_IRONLAKE (1 << 7) /** limit RGB values to avoid confusing TVs */ #define DP_COLOR_RANGE_16_235 (1 << 8) @@ -1808,7 +1822,7 @@ #define DSPFW3 0x7003c #define DSPFW_HPLL_SR_EN (1<<31) #define DSPFW_CURSOR_SR_SHIFT 24 -#define IGD_SELF_REFRESH_EN (1<<30) +#define PINEVIEW_SELF_REFRESH_EN (1<<30) /* FIFO watermark sizes etc */ #define G4X_FIFO_LINE_SIZE 64 @@ -1824,16 +1838,16 @@ #define G4X_MAX_WM 0x3f #define I915_MAX_WM 0x3f -#define IGD_DISPLAY_FIFO 512 /* in 64byte unit */ -#define IGD_FIFO_LINE_SIZE 64 -#define IGD_MAX_WM 0x1ff -#define IGD_DFT_WM 0x3f -#define IGD_DFT_HPLLOFF_WM 0 -#define IGD_GUARD_WM 10 -#define IGD_CURSOR_FIFO 64 -#define IGD_CURSOR_MAX_WM 0x3f -#define IGD_CURSOR_DFT_WM 0 -#define IGD_CURSOR_GUARD_WM 5 +#define PINEVIEW_DISPLAY_FIFO 512 /* in 64byte unit */ +#define PINEVIEW_FIFO_LINE_SIZE 64 +#define PINEVIEW_MAX_WM 0x1ff +#define PINEVIEW_DFT_WM 0x3f +#define PINEVIEW_DFT_HPLLOFF_WM 0 +#define PINEVIEW_GUARD_WM 10 +#define PINEVIEW_CURSOR_FIFO 64 +#define PINEVIEW_CURSOR_MAX_WM 0x3f +#define PINEVIEW_CURSOR_DFT_WM 0 +#define PINEVIEW_CURSOR_GUARD_WM 5 /* * The two pipe frame counter registers are not synchronized, so @@ -1907,6 +1921,7 @@ #define DISPPLANE_16BPP (0x5<<26) #define DISPPLANE_32BPP_NO_ALPHA (0x6<<26) #define DISPPLANE_32BPP (0x7<<26) +#define DISPPLANE_32BPP_30BIT_NO_ALPHA (0xa<<26) #define DISPPLANE_STEREO_ENABLE (1<<25) #define DISPPLANE_STEREO_DISABLE 0 #define DISPPLANE_SEL_PIPE_MASK (1<<24) @@ -1918,7 +1933,7 @@ #define DISPPLANE_NO_LINE_DOUBLE 0 #define DISPPLANE_STEREO_POLARITY_FIRST 0 #define DISPPLANE_STEREO_POLARITY_SECOND (1<<18) -#define DISPPLANE_TRICKLE_FEED_DISABLE (1<<14) /* IGDNG */ +#define DISPPLANE_TRICKLE_FEED_DISABLE (1<<14) /* Ironlake */ #define DISPPLANE_TILED (1<<10) #define DSPAADDR 0x70184 #define DSPASTRIDE 0x70188 @@ -1971,7 +1986,7 @@ # define VGA_2X_MODE (1 << 30) # define VGA_PIPE_B_SELECT (1 << 29) -/* IGDNG */ +/* Ironlake */ #define CPU_VGACNTRL 0x41000 @@ -2117,6 +2132,7 @@ #define SDE_PORTC_HOTPLUG (1 << 9) #define SDE_PORTB_HOTPLUG (1 << 8) #define SDE_SDVOB_HOTPLUG (1 << 6) +#define SDE_HOTPLUG_MASK (0xf << 8) #define SDEISR 0xc4000 #define SDEIMR 0xc4004 @@ -2157,6 +2173,13 @@ #define PCH_GPIOE 0xc5020 #define PCH_GPIOF 0xc5024 +#define PCH_GMBUS0 0xc5100 +#define PCH_GMBUS1 0xc5104 +#define PCH_GMBUS2 0xc5108 +#define PCH_GMBUS3 0xc510c +#define PCH_GMBUS4 0xc5110 +#define PCH_GMBUS5 0xc5120 + #define PCH_DPLL_A 0xc6014 #define PCH_DPLL_B 0xc6018 @@ -2292,7 +2315,7 @@ #define FDI_DP_PORT_WIDTH_X3 (2<<19) #define FDI_DP_PORT_WIDTH_X4 (3<<19) #define FDI_TX_ENHANCE_FRAME_ENABLE (1<<18) -/* IGDNG: hardwired to 1 */ +/* Ironlake: hardwired to 1 */ #define FDI_TX_PLL_ENABLE (1<<14) /* both Tx and Rx */ #define FDI_SCRAMBLING_ENABLE (0<<7) diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 6eec8171a44e55f6000ec5545b8f4733c4cbe86a..d5ebb00a9d49de32e379afb8602d46d279799e65 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -27,14 +27,14 @@ #include "drmP.h" #include "drm.h" #include "i915_drm.h" -#include "i915_drv.h" +#include "intel_drv.h" static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; u32 dpll_reg; - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { dpll_reg = (pipe == PIPE_A) ? PCH_DPLL_A: PCH_DPLL_B; } else { dpll_reg = (pipe == PIPE_A) ? DPLL_A: DPLL_B; @@ -53,7 +53,7 @@ static void i915_save_palette(struct drm_device *dev, enum pipe pipe) if (!i915_pipe_enabled(dev, pipe)) return; - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B; if (pipe == PIPE_A) @@ -75,7 +75,7 @@ static void i915_restore_palette(struct drm_device *dev, enum pipe pipe) if (!i915_pipe_enabled(dev, pipe)) return; - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B; if (pipe == PIPE_A) @@ -239,7 +239,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) if (drm_core_check_feature(dev, DRIVER_MODESET)) return; - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL); dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL); } @@ -247,7 +247,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) /* Pipe & plane A info */ dev_priv->savePIPEACONF = I915_READ(PIPEACONF); dev_priv->savePIPEASRC = I915_READ(PIPEASRC); - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { dev_priv->saveFPA0 = I915_READ(PCH_FPA0); dev_priv->saveFPA1 = I915_READ(PCH_FPA1); dev_priv->saveDPLL_A = I915_READ(PCH_DPLL_A); @@ -256,7 +256,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) dev_priv->saveFPA1 = I915_READ(FPA1); dev_priv->saveDPLL_A = I915_READ(DPLL_A); } - if (IS_I965G(dev) && !IS_IGDNG(dev)) + if (IS_I965G(dev) && !IS_IRONLAKE(dev)) dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD); dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A); dev_priv->saveHBLANK_A = I915_READ(HBLANK_A); @@ -264,10 +264,10 @@ static void i915_save_modeset_reg(struct drm_device *dev) dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A); dev_priv->saveVBLANK_A = I915_READ(VBLANK_A); dev_priv->saveVSYNC_A = I915_READ(VSYNC_A); - if (!IS_IGDNG(dev)) + if (!IS_IRONLAKE(dev)) dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A); - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { dev_priv->savePIPEA_DATA_M1 = I915_READ(PIPEA_DATA_M1); dev_priv->savePIPEA_DATA_N1 = I915_READ(PIPEA_DATA_N1); dev_priv->savePIPEA_LINK_M1 = I915_READ(PIPEA_LINK_M1); @@ -304,7 +304,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) /* Pipe & plane B info */ dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF); dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC); - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { dev_priv->saveFPB0 = I915_READ(PCH_FPB0); dev_priv->saveFPB1 = I915_READ(PCH_FPB1); dev_priv->saveDPLL_B = I915_READ(PCH_DPLL_B); @@ -313,7 +313,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) dev_priv->saveFPB1 = I915_READ(FPB1); dev_priv->saveDPLL_B = I915_READ(DPLL_B); } - if (IS_I965G(dev) && !IS_IGDNG(dev)) + if (IS_I965G(dev) && !IS_IRONLAKE(dev)) dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD); dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B); dev_priv->saveHBLANK_B = I915_READ(HBLANK_B); @@ -321,10 +321,10 @@ static void i915_save_modeset_reg(struct drm_device *dev) dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B); dev_priv->saveVBLANK_B = I915_READ(VBLANK_B); dev_priv->saveVSYNC_B = I915_READ(VSYNC_B); - if (!IS_IGDNG(dev)) + if (!IS_IRONLAKE(dev)) dev_priv->saveBCLRPAT_B = I915_READ(BCLRPAT_B); - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { dev_priv->savePIPEB_DATA_M1 = I915_READ(PIPEB_DATA_M1); dev_priv->savePIPEB_DATA_N1 = I915_READ(PIPEB_DATA_N1); dev_priv->savePIPEB_LINK_M1 = I915_READ(PIPEB_LINK_M1); @@ -369,7 +369,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) if (drm_core_check_feature(dev, DRIVER_MODESET)) return; - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { dpll_a_reg = PCH_DPLL_A; dpll_b_reg = PCH_DPLL_B; fpa0_reg = PCH_FPA0; @@ -385,7 +385,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) fpb1_reg = FPB1; } - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { I915_WRITE(PCH_DREF_CONTROL, dev_priv->savePCH_DREF_CONTROL); I915_WRITE(DISP_ARB_CTL, dev_priv->saveDISP_ARB_CTL); } @@ -402,7 +402,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) /* Actually enable it */ I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A); DRM_UDELAY(150); - if (IS_I965G(dev) && !IS_IGDNG(dev)) + if (IS_I965G(dev) && !IS_IRONLAKE(dev)) I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); DRM_UDELAY(150); @@ -413,10 +413,10 @@ static void i915_restore_modeset_reg(struct drm_device *dev) I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A); I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A); I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A); - if (!IS_IGDNG(dev)) + if (!IS_IRONLAKE(dev)) I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { I915_WRITE(PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1); I915_WRITE(PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1); I915_WRITE(PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1); @@ -467,7 +467,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) /* Actually enable it */ I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B); DRM_UDELAY(150); - if (IS_I965G(dev) && !IS_IGDNG(dev)) + if (IS_I965G(dev) && !IS_IRONLAKE(dev)) I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); DRM_UDELAY(150); @@ -478,10 +478,10 @@ static void i915_restore_modeset_reg(struct drm_device *dev) I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B); I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); - if (!IS_IGDNG(dev)) + if (!IS_IRONLAKE(dev)) I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { I915_WRITE(PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1); I915_WRITE(PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1); I915_WRITE(PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1); @@ -546,14 +546,14 @@ void i915_save_display(struct drm_device *dev) dev_priv->saveCURSIZE = I915_READ(CURSIZE); /* CRT state */ - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { dev_priv->saveADPA = I915_READ(PCH_ADPA); } else { dev_priv->saveADPA = I915_READ(ADPA); } /* LVDS state */ - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { dev_priv->savePP_CONTROL = I915_READ(PCH_PP_CONTROL); dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1); dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2); @@ -571,10 +571,10 @@ void i915_save_display(struct drm_device *dev) dev_priv->saveLVDS = I915_READ(LVDS); } - if (!IS_I830(dev) && !IS_845G(dev) && !IS_IGDNG(dev)) + if (!IS_I830(dev) && !IS_845G(dev) && !IS_IRONLAKE(dev)) dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL); - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { dev_priv->savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS); dev_priv->savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS); dev_priv->savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR); @@ -614,7 +614,7 @@ void i915_save_display(struct drm_device *dev) dev_priv->saveVGA0 = I915_READ(VGA0); dev_priv->saveVGA1 = I915_READ(VGA1); dev_priv->saveVGA_PD = I915_READ(VGA_PD); - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) dev_priv->saveVGACNTRL = I915_READ(CPU_VGACNTRL); else dev_priv->saveVGACNTRL = I915_READ(VGACNTRL); @@ -656,24 +656,24 @@ void i915_restore_display(struct drm_device *dev) I915_WRITE(CURSIZE, dev_priv->saveCURSIZE); /* CRT state */ - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) I915_WRITE(PCH_ADPA, dev_priv->saveADPA); else I915_WRITE(ADPA, dev_priv->saveADPA); /* LVDS state */ - if (IS_I965G(dev) && !IS_IGDNG(dev)) + if (IS_I965G(dev) && !IS_IRONLAKE(dev)) I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2); - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { I915_WRITE(PCH_LVDS, dev_priv->saveLVDS); } else if (IS_MOBILE(dev) && !IS_I830(dev)) I915_WRITE(LVDS, dev_priv->saveLVDS); - if (!IS_I830(dev) && !IS_845G(dev) && !IS_IGDNG(dev)) + if (!IS_I830(dev) && !IS_845G(dev) && !IS_IRONLAKE(dev)) I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL); - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->saveBLC_PWM_CTL); I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->saveBLC_PWM_CTL2); I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->saveBLC_CPU_PWM_CTL); @@ -713,7 +713,7 @@ void i915_restore_display(struct drm_device *dev) } /* VGA state */ - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) I915_WRITE(CPU_VGACNTRL, dev_priv->saveVGACNTRL); else I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL); @@ -733,8 +733,10 @@ int i915_save_state(struct drm_device *dev) pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); /* Render Standby */ - if (IS_I965G(dev) && IS_MOBILE(dev)) + if (I915_HAS_RC6(dev)) { dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); + dev_priv->savePWRCTXA = I915_READ(PWRCTXA); + } /* Hardware status page */ dev_priv->saveHWS = I915_READ(HWS_PGA); @@ -742,7 +744,7 @@ int i915_save_state(struct drm_device *dev) i915_save_display(dev); /* Interrupt state */ - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { dev_priv->saveDEIER = I915_READ(DEIER); dev_priv->saveDEIMR = I915_READ(DEIMR); dev_priv->saveGTIER = I915_READ(GTIER); @@ -754,10 +756,6 @@ int i915_save_state(struct drm_device *dev) dev_priv->saveIMR = I915_READ(IMR); } - /* Clock gating state */ - dev_priv->saveD_STATE = I915_READ(D_STATE); - dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D); /* Not sure about this */ - /* Cache mode state */ dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); @@ -796,8 +794,10 @@ int i915_restore_state(struct drm_device *dev) pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); /* Render Standby */ - if (IS_I965G(dev) && IS_MOBILE(dev)) + if (I915_HAS_RC6(dev)) { I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY); + I915_WRITE(PWRCTXA, dev_priv->savePWRCTXA); + } /* Hardware status page */ I915_WRITE(HWS_PGA, dev_priv->saveHWS); @@ -817,7 +817,7 @@ int i915_restore_state(struct drm_device *dev) i915_restore_display(dev); /* Interrupt state */ - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { I915_WRITE(DEIER, dev_priv->saveDEIER); I915_WRITE(DEIMR, dev_priv->saveDEIMR); I915_WRITE(GTIER, dev_priv->saveGTIER); @@ -830,8 +830,7 @@ int i915_restore_state(struct drm_device *dev) } /* Clock gating state */ - I915_WRITE (D_STATE, dev_priv->saveD_STATE); - I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D); + intel_init_clock_gating(dev); /* Cache mode state */ I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); @@ -846,6 +845,9 @@ int i915_restore_state(struct drm_device *dev) for (i = 0; i < 3; i++) I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]); + /* I2C state */ + intel_i2c_reset_gmbus(dev); + return 0; } diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 96cd256e60e6fd117ed00cf0f54503cc5312fadf..f275677475801badaa2be08f7c8abd2c5ed96251 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -114,6 +114,8 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, struct lvds_dvo_timing *dvo_timing; struct drm_display_mode *panel_fixed_mode; int lfp_data_size, dvo_timing_offset; + int i, temp_downclock; + struct drm_display_mode *temp_mode; /* Defaults if we can't find VBT info */ dev_priv->lvds_dither = 0; @@ -159,9 +161,49 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; - DRM_DEBUG("Found panel mode in BIOS VBT tables:\n"); + DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n"); drm_mode_debug_printmodeline(panel_fixed_mode); + temp_mode = kzalloc(sizeof(*temp_mode), GFP_KERNEL); + temp_downclock = panel_fixed_mode->clock; + /* + * enumerate the LVDS panel timing info entry in VBT to check whether + * the LVDS downclock is found. + */ + for (i = 0; i < 16; i++) { + entry = (struct bdb_lvds_lfp_data_entry *) + ((uint8_t *)lvds_lfp_data->data + (lfp_data_size * i)); + dvo_timing = (struct lvds_dvo_timing *) + ((unsigned char *)entry + dvo_timing_offset); + + fill_detail_timing_data(temp_mode, dvo_timing); + + if (temp_mode->hdisplay == panel_fixed_mode->hdisplay && + temp_mode->hsync_start == panel_fixed_mode->hsync_start && + temp_mode->hsync_end == panel_fixed_mode->hsync_end && + temp_mode->htotal == panel_fixed_mode->htotal && + temp_mode->vdisplay == panel_fixed_mode->vdisplay && + temp_mode->vsync_start == panel_fixed_mode->vsync_start && + temp_mode->vsync_end == panel_fixed_mode->vsync_end && + temp_mode->vtotal == panel_fixed_mode->vtotal && + temp_mode->clock < temp_downclock) { + /* + * downclock is already found. But we expect + * to find the lower downclock. + */ + temp_downclock = temp_mode->clock; + } + /* clear it to zero */ + memset(temp_mode, 0, sizeof(*temp_mode)); + } + kfree(temp_mode); + if (temp_downclock < panel_fixed_mode->clock) { + dev_priv->lvds_downclock_avail = 1; + dev_priv->lvds_downclock = temp_downclock; + DRM_DEBUG_KMS("LVDS downclock is found in VBT. ", + "Normal Clock %dKHz, downclock %dKHz\n", + temp_downclock, panel_fixed_mode->clock); + } return; } @@ -217,7 +259,7 @@ parse_general_features(struct drm_i915_private *dev_priv, if (IS_I85X(dev_priv->dev)) dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48; - else if (IS_IGDNG(dev_priv->dev)) + else if (IS_IRONLAKE(dev_priv->dev)) dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 120; else @@ -241,22 +283,18 @@ parse_general_definitions(struct drm_i915_private *dev_priv, GPIOF, }; - /* Set sensible defaults in case we can't find the general block - or it is the wrong chipset */ - dev_priv->crt_ddc_bus = -1; - general = find_section(bdb, BDB_GENERAL_DEFINITIONS); if (general) { u16 block_size = get_blocksize(general); if (block_size >= sizeof(*general)) { int bus_pin = general->crt_ddc_gmbus_pin; - DRM_DEBUG("crt_ddc_bus_pin: %d\n", bus_pin); + DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); if ((bus_pin >= 1) && (bus_pin <= 6)) { dev_priv->crt_ddc_bus = crt_bus_map_table[bus_pin-1]; } } else { - DRM_DEBUG("BDB_GD too small (%d). Invalid.\n", + DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", block_size); } } @@ -274,7 +312,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); if (!p_defs) { - DRM_DEBUG("No general definition block is found\n"); + DRM_DEBUG_KMS("No general definition block is found\n"); return; } /* judge whether the size of child device meets the requirements. @@ -284,7 +322,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, */ if (p_defs->child_dev_size != sizeof(*p_child)) { /* different child dev size . Ignore it */ - DRM_DEBUG("different child size is found. Invalid.\n"); + DRM_DEBUG_KMS("different child size is found. Invalid.\n"); return; } /* get the block size of general definitions */ @@ -310,11 +348,11 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, if (p_child->dvo_port != DEVICE_PORT_DVOB && p_child->dvo_port != DEVICE_PORT_DVOC) { /* skip the incorrect SDVO port */ - DRM_DEBUG("Incorrect SDVO port. Skip it \n"); + DRM_DEBUG_KMS("Incorrect SDVO port. Skip it \n"); continue; } - DRM_DEBUG("the SDVO device with slave addr %2x is found on " - "%s port\n", + DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on" + " %s port\n", p_child->slave_addr, (p_child->dvo_port == DEVICE_PORT_DVOB) ? "SDVOB" : "SDVOC"); @@ -325,21 +363,21 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, p_mapping->dvo_wiring = p_child->dvo_wiring; p_mapping->initialized = 1; } else { - DRM_DEBUG("Maybe one SDVO port is shared by " + DRM_DEBUG_KMS("Maybe one SDVO port is shared by " "two SDVO device.\n"); } if (p_child->slave2_addr) { /* Maybe this is a SDVO device with multiple inputs */ /* And the mapping info is not added */ - DRM_DEBUG("there exists the slave2_addr. Maybe this " - "is a SDVO device with multiple inputs.\n"); + DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this" + " is a SDVO device with multiple inputs.\n"); } count++; } if (!count) { /* No SDVO device info is found */ - DRM_DEBUG("No SDVO device info is found in VBT\n"); + DRM_DEBUG_KMS("No SDVO device info is found in VBT\n"); } return; } @@ -366,6 +404,70 @@ parse_driver_features(struct drm_i915_private *dev_priv, dev_priv->render_reclock_avail = true; } +static void +parse_device_mapping(struct drm_i915_private *dev_priv, + struct bdb_header *bdb) +{ + struct bdb_general_definitions *p_defs; + struct child_device_config *p_child, *child_dev_ptr; + int i, child_device_num, count; + u16 block_size; + + p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); + if (!p_defs) { + DRM_DEBUG_KMS("No general definition block is found\n"); + return; + } + /* judge whether the size of child device meets the requirements. + * If the child device size obtained from general definition block + * is different with sizeof(struct child_device_config), skip the + * parsing of sdvo device info + */ + if (p_defs->child_dev_size != sizeof(*p_child)) { + /* different child dev size . Ignore it */ + DRM_DEBUG_KMS("different child size is found. Invalid.\n"); + return; + } + /* get the block size of general definitions */ + block_size = get_blocksize(p_defs); + /* get the number of child device */ + child_device_num = (block_size - sizeof(*p_defs)) / + sizeof(*p_child); + count = 0; + /* get the number of child device that is present */ + for (i = 0; i < child_device_num; i++) { + p_child = &(p_defs->devices[i]); + if (!p_child->device_type) { + /* skip the device block if device type is invalid */ + continue; + } + count++; + } + if (!count) { + DRM_DEBUG_KMS("no child dev is parsed from VBT \n"); + return; + } + dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL); + if (!dev_priv->child_dev) { + DRM_DEBUG_KMS("No memory space for child device\n"); + return; + } + + dev_priv->child_dev_num = count; + count = 0; + for (i = 0; i < child_device_num; i++) { + p_child = &(p_defs->devices[i]); + if (!p_child->device_type) { + /* skip the device block if device type is invalid */ + continue; + } + child_dev_ptr = dev_priv->child_dev + count; + count++; + memcpy((void *)child_dev_ptr, (void *)p_child, + sizeof(*p_child)); + } + return; +} /** * intel_init_bios - initialize VBIOS settings & find VBT * @dev: DRM device @@ -417,6 +519,7 @@ intel_init_bios(struct drm_device *dev) parse_lfp_panel_data(dev_priv, bdb); parse_sdvo_panel_data(dev_priv, bdb); parse_sdvo_device_mapping(dev_priv, bdb); + parse_device_mapping(dev_priv, bdb); parse_driver_features(dev_priv, bdb); pci_unmap_rom(pdev, bios); diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 0f8e5f69ac7a315eb8eb8c4b9f377a87cc8e5f6c..425ac9d7f724792cce3e36f90122f3e644aceca3 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -549,4 +549,21 @@ bool intel_init_bios(struct drm_device *dev); #define SWF14_APM_STANDBY 0x1 #define SWF14_APM_RESTORE 0x0 +/* Add the device class for LFP, TV, HDMI */ +#define DEVICE_TYPE_INT_LFP 0x1022 +#define DEVICE_TYPE_INT_TV 0x1009 +#define DEVICE_TYPE_HDMI 0x60D2 +#define DEVICE_TYPE_DP 0x68C6 +#define DEVICE_TYPE_eDP 0x78C6 + +/* define the DVO port for HDMI output type */ +#define DVO_B 1 +#define DVO_C 2 +#define DVO_D 3 + +/* define the PORT for DP output type */ +#define PORT_IDPB 7 +#define PORT_IDPC 8 +#define PORT_IDPD 9 + #endif /* _I830_BIOS_H_ */ diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index e5051446c48e12ff14f5d504fbc3bdef72c8b2b8..9f3d3e56341488fc8f18900bd6cf96836e8ad7f5 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -39,7 +39,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) struct drm_i915_private *dev_priv = dev->dev_private; u32 temp, reg; - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) reg = PCH_ADPA; else reg = ADPA; @@ -64,34 +64,6 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) } I915_WRITE(reg, temp); - - if (IS_IGD(dev)) { - if (mode == DRM_MODE_DPMS_OFF) { - /* turn off DAC */ - temp = I915_READ(PORT_HOTPLUG_EN); - temp &= ~CRT_EOS_INT_EN; - I915_WRITE(PORT_HOTPLUG_EN, temp); - - temp = I915_READ(PORT_HOTPLUG_STAT); - if (temp & CRT_EOS_INT_STATUS) - I915_WRITE(PORT_HOTPLUG_STAT, - CRT_EOS_INT_STATUS); - } else { - /* turn on DAC. EOS interrupt must be enabled after DAC - * is enabled, so it sounds not good to enable it in - * i915_driver_irq_postinstall() - * wait 12.5ms after DAC is enabled - */ - msleep(13); - temp = I915_READ(PORT_HOTPLUG_STAT); - if (temp & CRT_EOS_INT_STATUS) - I915_WRITE(PORT_HOTPLUG_STAT, - CRT_EOS_INT_STATUS); - temp = I915_READ(PORT_HOTPLUG_EN); - temp |= CRT_EOS_INT_EN; - I915_WRITE(PORT_HOTPLUG_EN, temp); - } - } } static int intel_crt_mode_valid(struct drm_connector *connector, @@ -141,7 +113,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, else dpll_md_reg = DPLL_B_MD; - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) adpa_reg = PCH_ADPA; else adpa_reg = ADPA; @@ -150,7 +122,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, * Disable separate mode multiplier used when cloning SDVO to CRT * XXX this needs to be adjusted when we really are cloning */ - if (IS_I965G(dev) && !IS_IGDNG(dev)) { + if (IS_I965G(dev) && !IS_IRONLAKE(dev)) { dpll_md = I915_READ(dpll_md_reg); I915_WRITE(dpll_md_reg, dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); @@ -164,18 +136,18 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, if (intel_crtc->pipe == 0) { adpa |= ADPA_PIPE_A_SELECT; - if (!IS_IGDNG(dev)) + if (!IS_IRONLAKE(dev)) I915_WRITE(BCLRPAT_A, 0); } else { adpa |= ADPA_PIPE_B_SELECT; - if (!IS_IGDNG(dev)) + if (!IS_IRONLAKE(dev)) I915_WRITE(BCLRPAT_B, 0); } I915_WRITE(adpa_reg, adpa); } -static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector) +static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -194,7 +166,7 @@ static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector) ADPA_CRT_HOTPLUG_ENABLE | ADPA_CRT_HOTPLUG_FORCE_TRIGGER); - DRM_DEBUG("pch crt adpa 0x%x", adpa); + DRM_DEBUG_KMS("pch crt adpa 0x%x", adpa); I915_WRITE(PCH_ADPA, adpa); while ((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) != 0) @@ -227,8 +199,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) u32 hotplug_en; int i, tries = 0; - if (IS_IGDNG(dev)) - return intel_igdng_crt_detect_hotplug(connector); + if (IS_IRONLAKE(dev)) + return intel_ironlake_crt_detect_hotplug(connector); /* * On 4 series desktop, CRT detect sequence need to be done twice @@ -549,12 +521,12 @@ void intel_crt_init(struct drm_device *dev) &intel_output->enc); /* Set up the DDC bus. */ - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) i2c_reg = PCH_GPIOA; else { i2c_reg = GPIOA; /* Use VBT information for CRT DDC if available */ - if (dev_priv->crt_ddc_bus != -1) + if (dev_priv->crt_ddc_bus != 0) i2c_reg = dev_priv->crt_ddc_bus; } intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A"); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 099f420de57a2350d1da373cd7059b8305776e0a..52cd9b006da21a5c749c97952d9431a8450d497c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -32,7 +32,7 @@ #include "intel_drv.h" #include "i915_drm.h" #include "i915_drv.h" -#include "intel_dp.h" +#include "drm_dp_helper.h" #include "drm_crtc_helper.h" @@ -102,32 +102,32 @@ struct intel_limit { #define I9XX_DOT_MAX 400000 #define I9XX_VCO_MIN 1400000 #define I9XX_VCO_MAX 2800000 -#define IGD_VCO_MIN 1700000 -#define IGD_VCO_MAX 3500000 +#define PINEVIEW_VCO_MIN 1700000 +#define PINEVIEW_VCO_MAX 3500000 #define I9XX_N_MIN 1 #define I9XX_N_MAX 6 -/* IGD's Ncounter is a ring counter */ -#define IGD_N_MIN 3 -#define IGD_N_MAX 6 +/* Pineview's Ncounter is a ring counter */ +#define PINEVIEW_N_MIN 3 +#define PINEVIEW_N_MAX 6 #define I9XX_M_MIN 70 #define I9XX_M_MAX 120 -#define IGD_M_MIN 2 -#define IGD_M_MAX 256 +#define PINEVIEW_M_MIN 2 +#define PINEVIEW_M_MAX 256 #define I9XX_M1_MIN 10 #define I9XX_M1_MAX 22 #define I9XX_M2_MIN 5 #define I9XX_M2_MAX 9 -/* IGD M1 is reserved, and must be 0 */ -#define IGD_M1_MIN 0 -#define IGD_M1_MAX 0 -#define IGD_M2_MIN 0 -#define IGD_M2_MAX 254 +/* Pineview M1 is reserved, and must be 0 */ +#define PINEVIEW_M1_MIN 0 +#define PINEVIEW_M1_MAX 0 +#define PINEVIEW_M2_MIN 0 +#define PINEVIEW_M2_MAX 254 #define I9XX_P_SDVO_DAC_MIN 5 #define I9XX_P_SDVO_DAC_MAX 80 #define I9XX_P_LVDS_MIN 7 #define I9XX_P_LVDS_MAX 98 -#define IGD_P_LVDS_MIN 7 -#define IGD_P_LVDS_MAX 112 +#define PINEVIEW_P_LVDS_MIN 7 +#define PINEVIEW_P_LVDS_MAX 112 #define I9XX_P1_MIN 1 #define I9XX_P1_MAX 8 #define I9XX_P2_SDVO_DAC_SLOW 10 @@ -234,33 +234,33 @@ struct intel_limit { #define G4X_P2_DISPLAY_PORT_FAST 10 #define G4X_P2_DISPLAY_PORT_LIMIT 0 -/* IGDNG */ +/* Ironlake */ /* as we calculate clock using (register_value + 2) for N/M1/M2, so here the range value for them is (actual_value-2). */ -#define IGDNG_DOT_MIN 25000 -#define IGDNG_DOT_MAX 350000 -#define IGDNG_VCO_MIN 1760000 -#define IGDNG_VCO_MAX 3510000 -#define IGDNG_N_MIN 1 -#define IGDNG_N_MAX 5 -#define IGDNG_M_MIN 79 -#define IGDNG_M_MAX 118 -#define IGDNG_M1_MIN 12 -#define IGDNG_M1_MAX 23 -#define IGDNG_M2_MIN 5 -#define IGDNG_M2_MAX 9 -#define IGDNG_P_SDVO_DAC_MIN 5 -#define IGDNG_P_SDVO_DAC_MAX 80 -#define IGDNG_P_LVDS_MIN 28 -#define IGDNG_P_LVDS_MAX 112 -#define IGDNG_P1_MIN 1 -#define IGDNG_P1_MAX 8 -#define IGDNG_P2_SDVO_DAC_SLOW 10 -#define IGDNG_P2_SDVO_DAC_FAST 5 -#define IGDNG_P2_LVDS_SLOW 14 /* single channel */ -#define IGDNG_P2_LVDS_FAST 7 /* double channel */ -#define IGDNG_P2_DOT_LIMIT 225000 /* 225Mhz */ +#define IRONLAKE_DOT_MIN 25000 +#define IRONLAKE_DOT_MAX 350000 +#define IRONLAKE_VCO_MIN 1760000 +#define IRONLAKE_VCO_MAX 3510000 +#define IRONLAKE_N_MIN 1 +#define IRONLAKE_N_MAX 5 +#define IRONLAKE_M_MIN 79 +#define IRONLAKE_M_MAX 118 +#define IRONLAKE_M1_MIN 12 +#define IRONLAKE_M1_MAX 23 +#define IRONLAKE_M2_MIN 5 +#define IRONLAKE_M2_MAX 9 +#define IRONLAKE_P_SDVO_DAC_MIN 5 +#define IRONLAKE_P_SDVO_DAC_MAX 80 +#define IRONLAKE_P_LVDS_MIN 28 +#define IRONLAKE_P_LVDS_MAX 112 +#define IRONLAKE_P1_MIN 1 +#define IRONLAKE_P1_MAX 8 +#define IRONLAKE_P2_SDVO_DAC_SLOW 10 +#define IRONLAKE_P2_SDVO_DAC_FAST 5 +#define IRONLAKE_P2_LVDS_SLOW 14 /* single channel */ +#define IRONLAKE_P2_LVDS_FAST 7 /* double channel */ +#define IRONLAKE_P2_DOT_LIMIT 225000 /* 225Mhz */ static bool intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, @@ -272,15 +272,15 @@ static bool intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock); static bool -intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock); +intel_ironlake_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, + int target, int refclk, intel_clock_t *best_clock); static bool intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock); static bool -intel_find_pll_igdng_dp(const intel_limit_t *, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock); +intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc, + int target, int refclk, intel_clock_t *best_clock); static const intel_limit_t intel_limits_i8xx_dvo = { .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, @@ -453,13 +453,13 @@ static const intel_limit_t intel_limits_g4x_display_port = { .find_pll = intel_find_pll_g4x_dp, }; -static const intel_limit_t intel_limits_igd_sdvo = { +static const intel_limit_t intel_limits_pineview_sdvo = { .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, - .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, - .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, - .m = { .min = IGD_M_MIN, .max = IGD_M_MAX }, - .m1 = { .min = IGD_M1_MIN, .max = IGD_M1_MAX }, - .m2 = { .min = IGD_M2_MIN, .max = IGD_M2_MAX }, + .vco = { .min = PINEVIEW_VCO_MIN, .max = PINEVIEW_VCO_MAX }, + .n = { .min = PINEVIEW_N_MIN, .max = PINEVIEW_N_MAX }, + .m = { .min = PINEVIEW_M_MIN, .max = PINEVIEW_M_MAX }, + .m1 = { .min = PINEVIEW_M1_MIN, .max = PINEVIEW_M1_MAX }, + .m2 = { .min = PINEVIEW_M2_MIN, .max = PINEVIEW_M2_MAX }, .p = { .min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX }, .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, @@ -468,59 +468,59 @@ static const intel_limit_t intel_limits_igd_sdvo = { .find_reduced_pll = intel_find_best_reduced_PLL, }; -static const intel_limit_t intel_limits_igd_lvds = { +static const intel_limit_t intel_limits_pineview_lvds = { .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, - .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, - .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, - .m = { .min = IGD_M_MIN, .max = IGD_M_MAX }, - .m1 = { .min = IGD_M1_MIN, .max = IGD_M1_MAX }, - .m2 = { .min = IGD_M2_MIN, .max = IGD_M2_MAX }, - .p = { .min = IGD_P_LVDS_MIN, .max = IGD_P_LVDS_MAX }, + .vco = { .min = PINEVIEW_VCO_MIN, .max = PINEVIEW_VCO_MAX }, + .n = { .min = PINEVIEW_N_MIN, .max = PINEVIEW_N_MAX }, + .m = { .min = PINEVIEW_M_MIN, .max = PINEVIEW_M_MAX }, + .m1 = { .min = PINEVIEW_M1_MIN, .max = PINEVIEW_M1_MAX }, + .m2 = { .min = PINEVIEW_M2_MIN, .max = PINEVIEW_M2_MAX }, + .p = { .min = PINEVIEW_P_LVDS_MIN, .max = PINEVIEW_P_LVDS_MAX }, .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, - /* IGD only supports single-channel mode. */ + /* Pineview only supports single-channel mode. */ .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, .find_pll = intel_find_best_PLL, .find_reduced_pll = intel_find_best_reduced_PLL, }; -static const intel_limit_t intel_limits_igdng_sdvo = { - .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, - .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, - .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, - .m = { .min = IGDNG_M_MIN, .max = IGDNG_M_MAX }, - .m1 = { .min = IGDNG_M1_MIN, .max = IGDNG_M1_MAX }, - .m2 = { .min = IGDNG_M2_MIN, .max = IGDNG_M2_MAX }, - .p = { .min = IGDNG_P_SDVO_DAC_MIN, .max = IGDNG_P_SDVO_DAC_MAX }, - .p1 = { .min = IGDNG_P1_MIN, .max = IGDNG_P1_MAX }, - .p2 = { .dot_limit = IGDNG_P2_DOT_LIMIT, - .p2_slow = IGDNG_P2_SDVO_DAC_SLOW, - .p2_fast = IGDNG_P2_SDVO_DAC_FAST }, - .find_pll = intel_igdng_find_best_PLL, +static const intel_limit_t intel_limits_ironlake_sdvo = { + .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, + .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, + .n = { .min = IRONLAKE_N_MIN, .max = IRONLAKE_N_MAX }, + .m = { .min = IRONLAKE_M_MIN, .max = IRONLAKE_M_MAX }, + .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, + .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, + .p = { .min = IRONLAKE_P_SDVO_DAC_MIN, .max = IRONLAKE_P_SDVO_DAC_MAX }, + .p1 = { .min = IRONLAKE_P1_MIN, .max = IRONLAKE_P1_MAX }, + .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, + .p2_slow = IRONLAKE_P2_SDVO_DAC_SLOW, + .p2_fast = IRONLAKE_P2_SDVO_DAC_FAST }, + .find_pll = intel_ironlake_find_best_PLL, }; -static const intel_limit_t intel_limits_igdng_lvds = { - .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, - .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, - .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, - .m = { .min = IGDNG_M_MIN, .max = IGDNG_M_MAX }, - .m1 = { .min = IGDNG_M1_MIN, .max = IGDNG_M1_MAX }, - .m2 = { .min = IGDNG_M2_MIN, .max = IGDNG_M2_MAX }, - .p = { .min = IGDNG_P_LVDS_MIN, .max = IGDNG_P_LVDS_MAX }, - .p1 = { .min = IGDNG_P1_MIN, .max = IGDNG_P1_MAX }, - .p2 = { .dot_limit = IGDNG_P2_DOT_LIMIT, - .p2_slow = IGDNG_P2_LVDS_SLOW, - .p2_fast = IGDNG_P2_LVDS_FAST }, - .find_pll = intel_igdng_find_best_PLL, +static const intel_limit_t intel_limits_ironlake_lvds = { + .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, + .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, + .n = { .min = IRONLAKE_N_MIN, .max = IRONLAKE_N_MAX }, + .m = { .min = IRONLAKE_M_MIN, .max = IRONLAKE_M_MAX }, + .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, + .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, + .p = { .min = IRONLAKE_P_LVDS_MIN, .max = IRONLAKE_P_LVDS_MAX }, + .p1 = { .min = IRONLAKE_P1_MIN, .max = IRONLAKE_P1_MAX }, + .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, + .p2_slow = IRONLAKE_P2_LVDS_SLOW, + .p2_fast = IRONLAKE_P2_LVDS_FAST }, + .find_pll = intel_ironlake_find_best_PLL, }; -static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc) +static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc) { const intel_limit_t *limit; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) - limit = &intel_limits_igdng_lvds; + limit = &intel_limits_ironlake_lvds; else - limit = &intel_limits_igdng_sdvo; + limit = &intel_limits_ironlake_sdvo; return limit; } @@ -557,20 +557,20 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; const intel_limit_t *limit; - if (IS_IGDNG(dev)) - limit = intel_igdng_limit(crtc); + if (IS_IRONLAKE(dev)) + limit = intel_ironlake_limit(crtc); else if (IS_G4X(dev)) { limit = intel_g4x_limit(crtc); - } else if (IS_I9XX(dev) && !IS_IGD(dev)) { + } else if (IS_I9XX(dev) && !IS_PINEVIEW(dev)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) limit = &intel_limits_i9xx_lvds; else limit = &intel_limits_i9xx_sdvo; - } else if (IS_IGD(dev)) { + } else if (IS_PINEVIEW(dev)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) - limit = &intel_limits_igd_lvds; + limit = &intel_limits_pineview_lvds; else - limit = &intel_limits_igd_sdvo; + limit = &intel_limits_pineview_sdvo; } else { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) limit = &intel_limits_i8xx_lvds; @@ -580,8 +580,8 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) return limit; } -/* m1 is reserved as 0 in IGD, n is a ring counter */ -static void igd_clock(int refclk, intel_clock_t *clock) +/* m1 is reserved as 0 in Pineview, n is a ring counter */ +static void pineview_clock(int refclk, intel_clock_t *clock) { clock->m = clock->m2 + 2; clock->p = clock->p1 * clock->p2; @@ -591,8 +591,8 @@ static void igd_clock(int refclk, intel_clock_t *clock) static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock) { - if (IS_IGD(dev)) { - igd_clock(refclk, clock); + if (IS_PINEVIEW(dev)) { + pineview_clock(refclk, clock); return; } clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); @@ -657,7 +657,7 @@ static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock) INTELPllInvalid ("m2 out of range\n"); if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) INTELPllInvalid ("m1 out of range\n"); - if (clock->m1 <= clock->m2 && !IS_IGD(dev)) + if (clock->m1 <= clock->m2 && !IS_PINEVIEW(dev)) INTELPllInvalid ("m1 <= m2\n"); if (clock->m < limit->m.min || limit->m.max < clock->m) INTELPllInvalid ("m out of range\n"); @@ -706,16 +706,17 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, memset (best_clock, 0, sizeof (*best_clock)); - for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) { - for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; - clock.m1++) { - for (clock.m2 = limit->m2.min; - clock.m2 <= limit->m2.max; clock.m2++) { - /* m1 is always 0 in IGD */ - if (clock.m2 >= clock.m1 && !IS_IGD(dev)) - break; - for (clock.n = limit->n.min; - clock.n <= limit->n.max; clock.n++) { + for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; + clock.m1++) { + for (clock.m2 = limit->m2.min; + clock.m2 <= limit->m2.max; clock.m2++) { + /* m1 is always 0 in Pineview */ + if (clock.m2 >= clock.m1 && !IS_PINEVIEW(dev)) + break; + for (clock.n = limit->n.min; + clock.n <= limit->n.max; clock.n++) { + for (clock.p1 = limit->p1.min; + clock.p1 <= limit->p1.max; clock.p1++) { int this_err; intel_clock(dev, refclk, &clock); @@ -751,8 +752,8 @@ intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) { - /* m1 is always 0 in IGD */ - if (clock.m2 >= clock.m1 && !IS_IGD(dev)) + /* m1 is always 0 in Pineview */ + if (clock.m2 >= clock.m1 && !IS_PINEVIEW(dev)) break; for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) { @@ -833,8 +834,8 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, } static bool -intel_find_pll_igdng_dp(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock) +intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, + int target, int refclk, intel_clock_t *best_clock) { struct drm_device *dev = crtc->dev; intel_clock_t clock; @@ -857,8 +858,8 @@ intel_find_pll_igdng_dp(const intel_limit_t *limit, struct drm_crtc *crtc, } static bool -intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock) +intel_ironlake_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, + int target, int refclk, intel_clock_t *best_clock) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -871,7 +872,7 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, return true; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) - return intel_find_pll_igdng_dp(limit, crtc, target, + return intel_find_pll_ironlake_dp(limit, crtc, target, refclk, best_clock); if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { @@ -949,7 +950,7 @@ void intel_wait_for_vblank(struct drm_device *dev) { /* Wait for 20ms, i.e. one cycle at 50hz. */ - mdelay(20); + msleep(20); } /* Parameters have changed, update FBC info */ @@ -994,7 +995,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) fbc_ctl |= dev_priv->cfb_fence; I915_WRITE(FBC_CONTROL, fbc_ctl); - DRM_DEBUG("enabled FBC, pitch %ld, yoff %d, plane %d, ", + DRM_DEBUG_KMS("enabled FBC, pitch %ld, yoff %d, plane %d, ", dev_priv->cfb_pitch, crtc->y, dev_priv->cfb_plane); } @@ -1017,7 +1018,7 @@ void i8xx_disable_fbc(struct drm_device *dev) intel_wait_for_vblank(dev); - DRM_DEBUG("disabled FBC\n"); + DRM_DEBUG_KMS("disabled FBC\n"); } static bool i8xx_fbc_enabled(struct drm_crtc *crtc) @@ -1062,7 +1063,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) /* enable it... */ I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN); - DRM_DEBUG("enabled fbc on plane %d\n", intel_crtc->plane); + DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); } void g4x_disable_fbc(struct drm_device *dev) @@ -1076,7 +1077,7 @@ void g4x_disable_fbc(struct drm_device *dev) I915_WRITE(DPFC_CONTROL, dpfc_ctl); intel_wait_for_vblank(dev); - DRM_DEBUG("disabled FBC\n"); + DRM_DEBUG_KMS("disabled FBC\n"); } static bool g4x_fbc_enabled(struct drm_crtc *crtc) @@ -1141,25 +1142,27 @@ static void intel_update_fbc(struct drm_crtc *crtc, * - going to an unsupported config (interlace, pixel multiply, etc.) */ if (intel_fb->obj->size > dev_priv->cfb_size) { - DRM_DEBUG("framebuffer too large, disabling compression\n"); + DRM_DEBUG_KMS("framebuffer too large, disabling " + "compression\n"); goto out_disable; } if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || (mode->flags & DRM_MODE_FLAG_DBLSCAN)) { - DRM_DEBUG("mode incompatible with compression, disabling\n"); + DRM_DEBUG_KMS("mode incompatible with compression, " + "disabling\n"); goto out_disable; } if ((mode->hdisplay > 2048) || (mode->vdisplay > 1536)) { - DRM_DEBUG("mode too large for compression, disabling\n"); + DRM_DEBUG_KMS("mode too large for compression, disabling\n"); goto out_disable; } if ((IS_I915GM(dev) || IS_I945GM(dev)) && plane != 0) { - DRM_DEBUG("plane not 0, disabling compression\n"); + DRM_DEBUG_KMS("plane not 0, disabling compression\n"); goto out_disable; } if (obj_priv->tiling_mode != I915_TILING_X) { - DRM_DEBUG("framebuffer not tiled, disabling compression\n"); + DRM_DEBUG_KMS("framebuffer not tiled, disabling compression\n"); goto out_disable; } @@ -1181,12 +1184,56 @@ static void intel_update_fbc(struct drm_crtc *crtc, return; out_disable: - DRM_DEBUG("unsupported config, disabling FBC\n"); + DRM_DEBUG_KMS("unsupported config, disabling FBC\n"); /* Multiple disables should be harmless */ if (dev_priv->display.fbc_enabled(crtc)) dev_priv->display.disable_fbc(dev); } +static int +intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj) +{ + struct drm_i915_gem_object *obj_priv = obj->driver_private; + u32 alignment; + int ret; + + switch (obj_priv->tiling_mode) { + case I915_TILING_NONE: + alignment = 64 * 1024; + break; + case I915_TILING_X: + /* pin() will align the object as required by fence */ + alignment = 0; + break; + case I915_TILING_Y: + /* FIXME: Is this true? */ + DRM_ERROR("Y tiled not allowed for scan out buffers\n"); + return -EINVAL; + default: + BUG(); + } + + ret = i915_gem_object_pin(obj, alignment); + if (ret != 0) + return ret; + + /* Install a fence for tiled scan-out. Pre-i965 always needs a + * fence, whereas 965+ only requires a fence if using + * framebuffer compression. For simplicity, we always install + * a fence as the cost is not that onerous. + */ + if (obj_priv->fence_reg == I915_FENCE_REG_NONE && + obj_priv->tiling_mode != I915_TILING_NONE) { + ret = i915_gem_object_get_fence_reg(obj); + if (ret != 0) { + i915_gem_object_unpin(obj); + return ret; + } + } + + return 0; +} + static int intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) @@ -1206,12 +1253,12 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE; int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF); int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; - u32 dspcntr, alignment; + u32 dspcntr; int ret; /* no fb bound */ if (!crtc->fb) { - DRM_DEBUG("No FB bound\n"); + DRM_DEBUG_KMS("No FB bound\n"); return 0; } @@ -1228,24 +1275,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, obj = intel_fb->obj; obj_priv = obj->driver_private; - switch (obj_priv->tiling_mode) { - case I915_TILING_NONE: - alignment = 64 * 1024; - break; - case I915_TILING_X: - /* pin() will align the object as required by fence */ - alignment = 0; - break; - case I915_TILING_Y: - /* FIXME: Is this true? */ - DRM_ERROR("Y tiled not allowed for scan out buffers\n"); - return -EINVAL; - default: - BUG(); - } - mutex_lock(&dev->struct_mutex); - ret = i915_gem_object_pin(obj, alignment); + ret = intel_pin_and_fence_fb_obj(dev, obj); if (ret != 0) { mutex_unlock(&dev->struct_mutex); return ret; @@ -1258,20 +1289,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return ret; } - /* Install a fence for tiled scan-out. Pre-i965 always needs a fence, - * whereas 965+ only requires a fence if using framebuffer compression. - * For simplicity, we always install a fence as the cost is not that onerous. - */ - if (obj_priv->fence_reg == I915_FENCE_REG_NONE && - obj_priv->tiling_mode != I915_TILING_NONE) { - ret = i915_gem_object_get_fence_reg(obj); - if (ret != 0) { - i915_gem_object_unpin(obj); - mutex_unlock(&dev->struct_mutex); - return ret; - } - } - dspcntr = I915_READ(dspcntr_reg); /* Mask out pixel format bits in case we change it */ dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; @@ -1287,7 +1304,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, break; case 24: case 32: - dspcntr |= DISPPLANE_32BPP_NO_ALPHA; + if (crtc->fb->depth == 30) + dspcntr |= DISPPLANE_32BPP_30BIT_NO_ALPHA; + else + dspcntr |= DISPPLANE_32BPP_NO_ALPHA; break; default: DRM_ERROR("Unknown color depth\n"); @@ -1302,7 +1322,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, dspcntr &= ~DISPPLANE_TILED; } - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) /* must disable */ dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; @@ -1311,7 +1331,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, Start = obj_priv->gtt_offset; Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); - DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); + DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); I915_WRITE(dspstride, crtc->fb->pitch); if (IS_I965G(dev)) { I915_WRITE(dspbase, Offset); @@ -1363,7 +1383,7 @@ static void i915_disable_vga (struct drm_device *dev) u8 sr1; u32 vga_reg; - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) vga_reg = CPU_VGACNTRL; else vga_reg = VGACNTRL; @@ -1379,19 +1399,19 @@ static void i915_disable_vga (struct drm_device *dev) I915_WRITE(vga_reg, VGA_DISP_DISABLE); } -static void igdng_disable_pll_edp (struct drm_crtc *crtc) +static void ironlake_disable_pll_edp (struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 dpa_ctl; - DRM_DEBUG("\n"); + DRM_DEBUG_KMS("\n"); dpa_ctl = I915_READ(DP_A); dpa_ctl &= ~DP_PLL_ENABLE; I915_WRITE(DP_A, dpa_ctl); } -static void igdng_enable_pll_edp (struct drm_crtc *crtc) +static void ironlake_enable_pll_edp (struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -1404,13 +1424,13 @@ static void igdng_enable_pll_edp (struct drm_crtc *crtc) } -static void igdng_set_pll_edp (struct drm_crtc *crtc, int clock) +static void ironlake_set_pll_edp (struct drm_crtc *crtc, int clock) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 dpa_ctl; - DRM_DEBUG("eDP PLL enable for clock %d\n", clock); + DRM_DEBUG_KMS("eDP PLL enable for clock %d\n", clock); dpa_ctl = I915_READ(DP_A); dpa_ctl &= ~DP_PLL_FREQ_MASK; @@ -1440,7 +1460,7 @@ static void igdng_set_pll_edp (struct drm_crtc *crtc, int clock) udelay(500); } -static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) +static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -1481,10 +1501,19 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: - DRM_DEBUG("crtc %d dpms on\n", pipe); + DRM_DEBUG_KMS("crtc %d dpms on\n", pipe); + + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { + temp = I915_READ(PCH_LVDS); + if ((temp & LVDS_PORT_EN) == 0) { + I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN); + POSTING_READ(PCH_LVDS); + } + } + if (HAS_eDP) { /* enable eDP PLL */ - igdng_enable_pll_edp(crtc); + ironlake_enable_pll_edp(crtc); } else { /* enable PCH DPLL */ temp = I915_READ(pch_dpll_reg); @@ -1501,7 +1530,7 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) I915_READ(fdi_rx_reg); udelay(200); - /* Enable CPU FDI TX PLL, always on for IGDNG */ + /* Enable CPU FDI TX PLL, always on for Ironlake */ temp = I915_READ(fdi_tx_reg); if ((temp & FDI_TX_PLL_ENABLE) == 0) { I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE); @@ -1568,12 +1597,13 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) udelay(150); temp = I915_READ(fdi_rx_iir_reg); - DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp); + DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); if ((temp & FDI_RX_BIT_LOCK) == 0) { for (j = 0; j < tries; j++) { temp = I915_READ(fdi_rx_iir_reg); - DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp); + DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", + temp); if (temp & FDI_RX_BIT_LOCK) break; udelay(200); @@ -1582,11 +1612,11 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) I915_WRITE(fdi_rx_iir_reg, temp | FDI_RX_BIT_LOCK); else - DRM_DEBUG("train 1 fail\n"); + DRM_DEBUG_KMS("train 1 fail\n"); } else { I915_WRITE(fdi_rx_iir_reg, temp | FDI_RX_BIT_LOCK); - DRM_DEBUG("train 1 ok 2!\n"); + DRM_DEBUG_KMS("train 1 ok 2!\n"); } temp = I915_READ(fdi_tx_reg); temp &= ~FDI_LINK_TRAIN_NONE; @@ -1601,12 +1631,13 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) udelay(150); temp = I915_READ(fdi_rx_iir_reg); - DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp); + DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); if ((temp & FDI_RX_SYMBOL_LOCK) == 0) { for (j = 0; j < tries; j++) { temp = I915_READ(fdi_rx_iir_reg); - DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp); + DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", + temp); if (temp & FDI_RX_SYMBOL_LOCK) break; udelay(200); @@ -1614,15 +1645,15 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) if (j != tries) { I915_WRITE(fdi_rx_iir_reg, temp | FDI_RX_SYMBOL_LOCK); - DRM_DEBUG("train 2 ok 1!\n"); + DRM_DEBUG_KMS("train 2 ok 1!\n"); } else - DRM_DEBUG("train 2 fail\n"); + DRM_DEBUG_KMS("train 2 fail\n"); } else { I915_WRITE(fdi_rx_iir_reg, temp | FDI_RX_SYMBOL_LOCK); - DRM_DEBUG("train 2 ok 2!\n"); + DRM_DEBUG_KMS("train 2 ok 2!\n"); } - DRM_DEBUG("train done\n"); + DRM_DEBUG_KMS("train done\n"); /* set transcoder timing */ I915_WRITE(trans_htot_reg, I915_READ(cpu_htot_reg)); @@ -1664,9 +1695,7 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) break; case DRM_MODE_DPMS_OFF: - DRM_DEBUG("crtc %d dpms off\n", pipe); - - i915_disable_vga(dev); + DRM_DEBUG_KMS("crtc %d dpms off\n", pipe); /* Disable display plane */ temp = I915_READ(dspcntr_reg); @@ -1677,6 +1706,8 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) I915_READ(dspbase_reg); } + i915_disable_vga(dev); + /* disable cpu pipe, disable after all planes disabled */ temp = I915_READ(pipeconf_reg); if ((temp & PIPEACONF_ENABLE) != 0) { @@ -1690,16 +1721,23 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) udelay(500); continue; } else { - DRM_DEBUG("pipe %d off delay\n", pipe); + DRM_DEBUG_KMS("pipe %d off delay\n", + pipe); break; } } } else - DRM_DEBUG("crtc %d is disabled\n", pipe); + DRM_DEBUG_KMS("crtc %d is disabled\n", pipe); - if (HAS_eDP) { - igdng_disable_pll_edp(crtc); + udelay(100); + + /* Disable PF */ + temp = I915_READ(pf_ctl_reg); + if ((temp & PF_ENABLE) != 0) { + I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE); + I915_READ(pf_ctl_reg); } + I915_WRITE(pf_win_size, 0); /* disable CPU FDI tx and PCH FDI rx */ temp = I915_READ(fdi_tx_reg); @@ -1725,6 +1763,13 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) udelay(100); + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { + temp = I915_READ(PCH_LVDS); + I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN); + I915_READ(PCH_LVDS); + udelay(100); + } + /* disable PCH transcoder */ temp = I915_READ(transconf_reg); if ((temp & TRANS_ENABLE) != 0) { @@ -1738,12 +1783,15 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) udelay(500); continue; } else { - DRM_DEBUG("transcoder %d off delay\n", pipe); + DRM_DEBUG_KMS("transcoder %d off " + "delay\n", pipe); break; } } } + udelay(100); + /* disable PCH DPLL */ temp = I915_READ(pch_dpll_reg); if ((temp & DPLL_VCO_ENABLE) != 0) { @@ -1751,14 +1799,20 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) I915_READ(pch_dpll_reg); } - temp = I915_READ(fdi_rx_reg); - if ((temp & FDI_RX_PLL_ENABLE) != 0) { - temp &= ~FDI_SEL_PCDCLK; - temp &= ~FDI_RX_PLL_ENABLE; - I915_WRITE(fdi_rx_reg, temp); - I915_READ(fdi_rx_reg); + if (HAS_eDP) { + ironlake_disable_pll_edp(crtc); } + temp = I915_READ(fdi_rx_reg); + temp &= ~FDI_SEL_PCDCLK; + I915_WRITE(fdi_rx_reg, temp); + I915_READ(fdi_rx_reg); + + temp = I915_READ(fdi_rx_reg); + temp &= ~FDI_RX_PLL_ENABLE; + I915_WRITE(fdi_rx_reg, temp); + I915_READ(fdi_rx_reg); + /* Disable CPU FDI TX PLL */ temp = I915_READ(fdi_tx_reg); if ((temp & FDI_TX_PLL_ENABLE) != 0) { @@ -1767,20 +1821,43 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) udelay(100); } - /* Disable PF */ - temp = I915_READ(pf_ctl_reg); - if ((temp & PF_ENABLE) != 0) { - I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE); - I915_READ(pf_ctl_reg); - } - I915_WRITE(pf_win_size, 0); - /* Wait for the clocks to turn off. */ - udelay(150); + udelay(100); break; } } +static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable) +{ + struct intel_overlay *overlay; + int ret; + + if (!enable && intel_crtc->overlay) { + overlay = intel_crtc->overlay; + mutex_lock(&overlay->dev->struct_mutex); + for (;;) { + ret = intel_overlay_switch_off(overlay); + if (ret == 0) + break; + + ret = intel_overlay_recover_from_interrupt(overlay, 0); + if (ret != 0) { + /* overlay doesn't react anymore. Usually + * results in a black screen and an unkillable + * X server. */ + BUG(); + overlay->hw_wedged = HW_WEDGED; + break; + } + } + mutex_unlock(&overlay->dev->struct_mutex); + } + /* Let userspace switch the overlay on again. In most cases userspace + * has to recompute where to put it anyway. */ + + return; +} + static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; @@ -1839,12 +1916,14 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) intel_update_fbc(crtc, &crtc->mode); /* Give the overlay scaler a chance to enable if it's on this pipe */ - //intel_crtc_dpms_video(crtc, true); TODO + intel_crtc_dpms_overlay(intel_crtc, true); break; case DRM_MODE_DPMS_OFF: intel_update_watermarks(dev); + /* Give the overlay scaler a chance to disable if it's on this pipe */ - //intel_crtc_dpms_video(crtc, FALSE); TODO + intel_crtc_dpms_overlay(intel_crtc, false); + drm_vblank_off(dev, pipe); if (dev_priv->cfb_plane == plane && dev_priv->display.disable_fbc) @@ -1963,7 +2042,7 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = crtc->dev; - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { /* FDI link clock is fixed at 2.7G */ if (mode->clock * 3 > 27000 * 4) return MODE_CLOCK_HIGH; @@ -2039,7 +2118,7 @@ static int i830_get_display_clock_speed(struct drm_device *dev) * Return the pipe currently connected to the panel fitter, * or -1 if the panel fitter is not present or not in use */ -static int intel_panel_fitter_pipe (struct drm_device *dev) +int intel_panel_fitter_pipe (struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 pfit_control; @@ -2083,9 +2162,8 @@ fdi_reduce_ratio(u32 *num, u32 *den) #define LINK_N 0x80000 static void -igdng_compute_m_n(int bits_per_pixel, int nlanes, - int pixel_clock, int link_clock, - struct fdi_m_n *m_n) +ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock, + int link_clock, struct fdi_m_n *m_n) { u64 temp; @@ -2113,34 +2191,34 @@ struct intel_watermark_params { unsigned long cacheline_size; }; -/* IGD has different values for various configs */ -static struct intel_watermark_params igd_display_wm = { - IGD_DISPLAY_FIFO, - IGD_MAX_WM, - IGD_DFT_WM, - IGD_GUARD_WM, - IGD_FIFO_LINE_SIZE +/* Pineview has different values for various configs */ +static struct intel_watermark_params pineview_display_wm = { + PINEVIEW_DISPLAY_FIFO, + PINEVIEW_MAX_WM, + PINEVIEW_DFT_WM, + PINEVIEW_GUARD_WM, + PINEVIEW_FIFO_LINE_SIZE }; -static struct intel_watermark_params igd_display_hplloff_wm = { - IGD_DISPLAY_FIFO, - IGD_MAX_WM, - IGD_DFT_HPLLOFF_WM, - IGD_GUARD_WM, - IGD_FIFO_LINE_SIZE +static struct intel_watermark_params pineview_display_hplloff_wm = { + PINEVIEW_DISPLAY_FIFO, + PINEVIEW_MAX_WM, + PINEVIEW_DFT_HPLLOFF_WM, + PINEVIEW_GUARD_WM, + PINEVIEW_FIFO_LINE_SIZE }; -static struct intel_watermark_params igd_cursor_wm = { - IGD_CURSOR_FIFO, - IGD_CURSOR_MAX_WM, - IGD_CURSOR_DFT_WM, - IGD_CURSOR_GUARD_WM, - IGD_FIFO_LINE_SIZE, +static struct intel_watermark_params pineview_cursor_wm = { + PINEVIEW_CURSOR_FIFO, + PINEVIEW_CURSOR_MAX_WM, + PINEVIEW_CURSOR_DFT_WM, + PINEVIEW_CURSOR_GUARD_WM, + PINEVIEW_FIFO_LINE_SIZE, }; -static struct intel_watermark_params igd_cursor_hplloff_wm = { - IGD_CURSOR_FIFO, - IGD_CURSOR_MAX_WM, - IGD_CURSOR_DFT_WM, - IGD_CURSOR_GUARD_WM, - IGD_FIFO_LINE_SIZE +static struct intel_watermark_params pineview_cursor_hplloff_wm = { + PINEVIEW_CURSOR_FIFO, + PINEVIEW_CURSOR_MAX_WM, + PINEVIEW_CURSOR_DFT_WM, + PINEVIEW_CURSOR_GUARD_WM, + PINEVIEW_FIFO_LINE_SIZE }; static struct intel_watermark_params g4x_wm_info = { G4X_FIFO_SIZE, @@ -2213,11 +2291,11 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz, 1000; entries_required /= wm->cacheline_size; - DRM_DEBUG("FIFO entries required for mode: %d\n", entries_required); + DRM_DEBUG_KMS("FIFO entries required for mode: %d\n", entries_required); wm_size = wm->fifo_size - (entries_required + wm->guard_size); - DRM_DEBUG("FIFO watermark level: %d\n", wm_size); + DRM_DEBUG_KMS("FIFO watermark level: %d\n", wm_size); /* Don't promote wm_size to unsigned... */ if (wm_size > (long)wm->max_wm) @@ -2279,50 +2357,50 @@ static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb, return latency; } - DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n"); + DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n"); return NULL; } -static void igd_disable_cxsr(struct drm_device *dev) +static void pineview_disable_cxsr(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 reg; /* deactivate cxsr */ reg = I915_READ(DSPFW3); - reg &= ~(IGD_SELF_REFRESH_EN); + reg &= ~(PINEVIEW_SELF_REFRESH_EN); I915_WRITE(DSPFW3, reg); DRM_INFO("Big FIFO is disabled\n"); } -static void igd_enable_cxsr(struct drm_device *dev, unsigned long clock, - int pixel_size) +static void pineview_enable_cxsr(struct drm_device *dev, unsigned long clock, + int pixel_size) { struct drm_i915_private *dev_priv = dev->dev_private; u32 reg; unsigned long wm; struct cxsr_latency *latency; - latency = intel_get_cxsr_latency(IS_IGDG(dev), dev_priv->fsb_freq, + latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->fsb_freq, dev_priv->mem_freq); if (!latency) { - DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n"); - igd_disable_cxsr(dev); + DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n"); + pineview_disable_cxsr(dev); return; } /* Display SR */ - wm = intel_calculate_wm(clock, &igd_display_wm, pixel_size, + wm = intel_calculate_wm(clock, &pineview_display_wm, pixel_size, latency->display_sr); reg = I915_READ(DSPFW1); reg &= 0x7fffff; reg |= wm << 23; I915_WRITE(DSPFW1, reg); - DRM_DEBUG("DSPFW1 register is %x\n", reg); + DRM_DEBUG_KMS("DSPFW1 register is %x\n", reg); /* cursor SR */ - wm = intel_calculate_wm(clock, &igd_cursor_wm, pixel_size, + wm = intel_calculate_wm(clock, &pineview_cursor_wm, pixel_size, latency->cursor_sr); reg = I915_READ(DSPFW3); reg &= ~(0x3f << 24); @@ -2330,7 +2408,7 @@ static void igd_enable_cxsr(struct drm_device *dev, unsigned long clock, I915_WRITE(DSPFW3, reg); /* Display HPLL off SR */ - wm = intel_calculate_wm(clock, &igd_display_hplloff_wm, + wm = intel_calculate_wm(clock, &pineview_display_hplloff_wm, latency->display_hpll_disable, I915_FIFO_LINE_SIZE); reg = I915_READ(DSPFW3); reg &= 0xfffffe00; @@ -2338,17 +2416,17 @@ static void igd_enable_cxsr(struct drm_device *dev, unsigned long clock, I915_WRITE(DSPFW3, reg); /* cursor HPLL off SR */ - wm = intel_calculate_wm(clock, &igd_cursor_hplloff_wm, pixel_size, + wm = intel_calculate_wm(clock, &pineview_cursor_hplloff_wm, pixel_size, latency->cursor_hpll_disable); reg = I915_READ(DSPFW3); reg &= ~(0x3f << 16); reg |= (wm & 0x3f) << 16; I915_WRITE(DSPFW3, reg); - DRM_DEBUG("DSPFW3 register is %x\n", reg); + DRM_DEBUG_KMS("DSPFW3 register is %x\n", reg); /* activate cxsr */ reg = I915_READ(DSPFW3); - reg |= IGD_SELF_REFRESH_EN; + reg |= PINEVIEW_SELF_REFRESH_EN; I915_WRITE(DSPFW3, reg); DRM_INFO("Big FIFO is enabled\n"); @@ -2384,8 +2462,8 @@ static int i9xx_get_fifo_size(struct drm_device *dev, int plane) size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) - (dsparb & 0x7f); - DRM_DEBUG("FIFO size - (0x%08x) %s: %d\n", dsparb, plane ? "B" : "A", - size); + DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, + plane ? "B" : "A", size); return size; } @@ -2403,8 +2481,8 @@ static int i85x_get_fifo_size(struct drm_device *dev, int plane) (dsparb & 0x1ff); size >>= 1; /* Convert to cachelines */ - DRM_DEBUG("FIFO size - (0x%08x) %s: %d\n", dsparb, plane ? "B" : "A", - size); + DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, + plane ? "B" : "A", size); return size; } @@ -2418,7 +2496,8 @@ static int i845_get_fifo_size(struct drm_device *dev, int plane) size = dsparb & 0x7f; size >>= 2; /* Convert to cachelines */ - DRM_DEBUG("FIFO size - (0x%08x) %s: %d\n", dsparb, plane ? "B" : "A", + DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, + plane ? "B" : "A", size); return size; @@ -2433,8 +2512,8 @@ static int i830_get_fifo_size(struct drm_device *dev, int plane) size = dsparb & 0x7f; size >>= 1; /* Convert to cachelines */ - DRM_DEBUG("FIFO size - (0x%08x) %s: %d\n", dsparb, plane ? "B" : "A", - size); + DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, + plane ? "B" : "A", size); return size; } @@ -2509,15 +2588,39 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock, (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); } -static void i965_update_wm(struct drm_device *dev, int unused, int unused2, - int unused3, int unused4) +static void i965_update_wm(struct drm_device *dev, int planea_clock, + int planeb_clock, int sr_hdisplay, int pixel_size) { struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long line_time_us; + int sr_clock, sr_entries, srwm = 1; + + /* Calc sr entries for one plane configs */ + if (sr_hdisplay && (!planea_clock || !planeb_clock)) { + /* self-refresh has much higher latency */ + const static int sr_latency_ns = 12000; + + sr_clock = planea_clock ? planea_clock : planeb_clock; + line_time_us = ((sr_hdisplay * 1000) / sr_clock); + + /* Use ns/us then divide to preserve precision */ + sr_entries = (((sr_latency_ns / line_time_us) + 1) * + pixel_size * sr_hdisplay) / 1000; + sr_entries = roundup(sr_entries / I915_FIFO_LINE_SIZE, 1); + DRM_DEBUG("self-refresh entries: %d\n", sr_entries); + srwm = I945_FIFO_SIZE - sr_entries; + if (srwm < 0) + srwm = 1; + srwm &= 0x3f; + I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); + } - DRM_DEBUG("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR 8\n"); + DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n", + srwm); /* 965 has limitations... */ - I915_WRITE(DSPFW1, (8 << 16) | (8 << 8) | (8 << 0)); + I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) | (8 << 16) | (8 << 8) | + (8 << 0)); I915_WRITE(DSPFW2, (8 << 8) | (8 << 0)); } @@ -2553,7 +2656,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, pixel_size, latency_ns); planeb_wm = intel_calculate_wm(planeb_clock, &planeb_params, pixel_size, latency_ns); - DRM_DEBUG("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); + DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); /* * Overlay gets an aggressive default since video jitter is bad. @@ -2573,14 +2676,14 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, sr_entries = (((sr_latency_ns / line_time_us) + 1) * pixel_size * sr_hdisplay) / 1000; sr_entries = roundup(sr_entries / cacheline_size, 1); - DRM_DEBUG("self-refresh entries: %d\n", sr_entries); + DRM_DEBUG_KMS("self-refresh entries: %d\n", sr_entries); srwm = total_size - sr_entries; if (srwm < 0) srwm = 1; I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f)); } - DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", + DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", planea_wm, planeb_wm, cwm, srwm); fwater_lo = ((planeb_wm & 0x3f) << 16) | (planea_wm & 0x3f); @@ -2607,7 +2710,7 @@ static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused, pixel_size, latency_ns); fwater_lo |= (3<<8) | planea_wm; - DRM_DEBUG("Setting FIFO watermarks - A: %d\n", planea_wm); + DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d\n", planea_wm); I915_WRITE(FW_BLC, fwater_lo); } @@ -2661,11 +2764,11 @@ static void intel_update_watermarks(struct drm_device *dev) if (crtc->enabled) { enabled++; if (intel_crtc->plane == 0) { - DRM_DEBUG("plane A (pipe %d) clock: %d\n", + DRM_DEBUG_KMS("plane A (pipe %d) clock: %d\n", intel_crtc->pipe, crtc->mode.clock); planea_clock = crtc->mode.clock; } else { - DRM_DEBUG("plane B (pipe %d) clock: %d\n", + DRM_DEBUG_KMS("plane B (pipe %d) clock: %d\n", intel_crtc->pipe, crtc->mode.clock); planeb_clock = crtc->mode.clock; } @@ -2682,10 +2785,10 @@ static void intel_update_watermarks(struct drm_device *dev) return; /* Single plane configs can enable self refresh */ - if (enabled == 1 && IS_IGD(dev)) - igd_enable_cxsr(dev, sr_clock, pixel_size); - else if (IS_IGD(dev)) - igd_disable_cxsr(dev); + if (enabled == 1 && IS_PINEVIEW(dev)) + pineview_enable_cxsr(dev, sr_clock, pixel_size); + else if (IS_PINEVIEW(dev)) + pineview_disable_cxsr(dev); dev_priv->display.update_wm(dev, planea_clock, planeb_clock, sr_hdisplay, pixel_size); @@ -2779,10 +2882,11 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2) { refclk = dev_priv->lvds_ssc_freq * 1000; - DRM_DEBUG("using SSC reference clock of %d MHz\n", refclk / 1000); + DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", + refclk / 1000); } else if (IS_I9XX(dev)) { refclk = 96000; - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) refclk = 120000; /* 120Mhz refclk */ } else { refclk = 48000; @@ -2802,14 +2906,25 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, return -EINVAL; } - if (limit->find_reduced_pll && dev_priv->lvds_downclock_avail) { + if (is_lvds && limit->find_reduced_pll && + dev_priv->lvds_downclock_avail) { memcpy(&reduced_clock, &clock, sizeof(intel_clock_t)); has_reduced_clock = limit->find_reduced_pll(limit, crtc, - (adjusted_mode->clock*3/4), + dev_priv->lvds_downclock, refclk, &reduced_clock); + if (has_reduced_clock && (clock.p != reduced_clock.p)) { + /* + * If the different P is found, it means that we can't + * switch the display clock by using the FP0/FP1. + * In such case we will disable the LVDS downclock + * feature. + */ + DRM_DEBUG_KMS("Different P is found for " + "LVDS clock/downclock\n"); + has_reduced_clock = 0; + } } - /* SDVO TV has fixed PLL values depend on its clock range, this mirrors vbios setting. */ if (is_sdvo && is_tv) { @@ -2831,7 +2946,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, } /* FDI link */ - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { int lane, link_bw, bpp; /* eDP doesn't require FDI link, so just set DP M/N according to current link config */ @@ -2873,8 +2988,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, bpp = 24; } - igdng_compute_m_n(bpp, lane, target_clock, - link_bw, &m_n); + ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n); } /* Ironlake: try to setup display ref clock before DPLL @@ -2882,7 +2996,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, * PCH B stepping, previous chipset stepping should be * ignoring this setting. */ - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { temp = I915_READ(PCH_DREF_CONTROL); /* Always enable nonspread source */ temp &= ~DREF_NONSPREAD_SOURCE_MASK; @@ -2917,7 +3031,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, } } - if (IS_IGD(dev)) { + if (IS_PINEVIEW(dev)) { fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; if (has_reduced_clock) fp2 = (1 << reduced_clock.n) << 16 | @@ -2929,7 +3043,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, reduced_clock.m2; } - if (!IS_IGDNG(dev)) + if (!IS_IRONLAKE(dev)) dpll = DPLL_VGA_MODE_DIS; if (IS_I9XX(dev)) { @@ -2942,19 +3056,19 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; - else if (IS_IGDNG(dev)) + else if (IS_IRONLAKE(dev)) dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; } if (is_dp) dpll |= DPLL_DVO_HIGH_SPEED; /* compute bitmask from p1 value */ - if (IS_IGD(dev)) - dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_IGD; + if (IS_PINEVIEW(dev)) + dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW; else { dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; /* also FPA1 */ - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; if (IS_G4X(dev) && has_reduced_clock) dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; @@ -2973,7 +3087,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; break; } - if (IS_I965G(dev) && !IS_IGDNG(dev)) + if (IS_I965G(dev) && !IS_IRONLAKE(dev)) dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); } else { if (is_lvds) { @@ -3005,9 +3119,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, /* Set up the display plane register */ dspcntr = DISPPLANE_GAMMA_ENABLE; - /* IGDNG's plane is forced to pipe, bit 24 is to + /* Ironlake's plane is forced to pipe, bit 24 is to enable color space conversion */ - if (!IS_IGDNG(dev)) { + if (!IS_IRONLAKE(dev)) { if (pipe == 0) dspcntr &= ~DISPPLANE_SEL_PIPE_MASK; else @@ -3034,20 +3148,20 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, /* Disable the panel fitter if it was on our pipe */ - if (!IS_IGDNG(dev) && intel_panel_fitter_pipe(dev) == pipe) + if (!IS_IRONLAKE(dev) && intel_panel_fitter_pipe(dev) == pipe) I915_WRITE(PFIT_CONTROL, 0); - DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); + DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); drm_mode_debug_printmodeline(mode); - /* assign to IGDNG registers */ - if (IS_IGDNG(dev)) { + /* assign to Ironlake registers */ + if (IS_IRONLAKE(dev)) { fp_reg = pch_fp_reg; dpll_reg = pch_dpll_reg; } if (is_edp) { - igdng_disable_pll_edp(crtc); + ironlake_disable_pll_edp(crtc); } else if ((dpll & DPLL_VCO_ENABLE)) { I915_WRITE(fp_reg, fp); I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); @@ -3062,7 +3176,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, if (is_lvds) { u32 lvds; - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) lvds_reg = PCH_LVDS; lvds = I915_READ(lvds_reg); @@ -3095,7 +3209,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, /* Wait for the clocks to stabilize. */ udelay(150); - if (IS_I965G(dev) && !IS_IGDNG(dev)) { + if (IS_I965G(dev) && !IS_IRONLAKE(dev)) { if (is_sdvo) { sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | @@ -3115,14 +3229,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(fp_reg + 4, fp2); intel_crtc->lowfreq_avail = true; if (HAS_PIPE_CXSR(dev)) { - DRM_DEBUG("enabling CxSR downclocking\n"); + DRM_DEBUG_KMS("enabling CxSR downclocking\n"); pipeconf |= PIPECONF_CXSR_DOWNCLOCK; } } else { I915_WRITE(fp_reg + 4, fp); intel_crtc->lowfreq_avail = false; if (HAS_PIPE_CXSR(dev)) { - DRM_DEBUG("disabling CxSR downclocking\n"); + DRM_DEBUG_KMS("disabling CxSR downclocking\n"); pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; } } @@ -3142,21 +3256,21 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, /* pipesrc and dspsize control the size that is scaled from, which should * always be the user's requested size. */ - if (!IS_IGDNG(dev)) { + if (!IS_IRONLAKE(dev)) { I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); I915_WRITE(dsppos_reg, 0); } I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { I915_WRITE(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m); I915_WRITE(data_n1_reg, TU_SIZE(m_n.tu) | m_n.gmch_n); I915_WRITE(link_m1_reg, m_n.link_m); I915_WRITE(link_n1_reg, m_n.link_n); if (is_edp) { - igdng_set_pll_edp(crtc, adjusted_mode->clock); + ironlake_set_pll_edp(crtc, adjusted_mode->clock); } else { /* enable FDI RX PLL too */ temp = I915_READ(fdi_rx_reg); @@ -3170,7 +3284,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, intel_wait_for_vblank(dev); - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { /* enable address swizzle for tiling buffer */ temp = I915_READ(DISP_ARB_CTL); I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING); @@ -3204,8 +3318,8 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) if (!crtc->enabled) return; - /* use legacy palette for IGDNG */ - if (IS_IGDNG(dev)) + /* use legacy palette for Ironlake */ + if (IS_IRONLAKE(dev)) palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A : LGC_PALETTE_B; @@ -3234,11 +3348,11 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, size_t addr; int ret; - DRM_DEBUG("\n"); + DRM_DEBUG_KMS("\n"); /* if we want to turn off the cursor ignore width and height */ if (!handle) { - DRM_DEBUG("cursor off\n"); + DRM_DEBUG_KMS("cursor off\n"); if (IS_MOBILE(dev) || IS_I9XX(dev)) { temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); temp |= CURSOR_MODE_DISABLE; @@ -3546,18 +3660,18 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) fp = I915_READ((pipe == 0) ? FPA1 : FPB1); clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; - if (IS_IGD(dev)) { - clock.n = ffs((fp & FP_N_IGD_DIV_MASK) >> FP_N_DIV_SHIFT) - 1; - clock.m2 = (fp & FP_M2_IGD_DIV_MASK) >> FP_M2_DIV_SHIFT; + if (IS_PINEVIEW(dev)) { + clock.n = ffs((fp & FP_N_PINEVIEW_DIV_MASK) >> FP_N_DIV_SHIFT) - 1; + clock.m2 = (fp & FP_M2_PINEVIEW_DIV_MASK) >> FP_M2_DIV_SHIFT; } else { clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; } if (IS_I9XX(dev)) { - if (IS_IGD(dev)) - clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_IGD) >> - DPLL_FPA01_P1_POST_DIV_SHIFT_IGD); + if (IS_PINEVIEW(dev)) + clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >> + DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW); else clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >> DPLL_FPA01_P1_POST_DIV_SHIFT); @@ -3572,7 +3686,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) 7 : 14; break; default: - DRM_DEBUG("Unknown DPLL mode %08x in programmed " + DRM_DEBUG_KMS("Unknown DPLL mode %08x in programmed " "mode\n", (int)(dpll & DPLL_MODE_MASK)); return 0; } @@ -3658,7 +3772,7 @@ static void intel_gpu_idle_timer(unsigned long arg) struct drm_device *dev = (struct drm_device *)arg; drm_i915_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("idle timer fired, downclocking\n"); + DRM_DEBUG_DRIVER("idle timer fired, downclocking\n"); dev_priv->busy = false; @@ -3669,11 +3783,11 @@ void intel_increase_renderclock(struct drm_device *dev, bool schedule) { drm_i915_private_t *dev_priv = dev->dev_private; - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) return; if (!dev_priv->render_reclock_avail) { - DRM_DEBUG("not reclocking render clock\n"); + DRM_DEBUG_DRIVER("not reclocking render clock\n"); return; } @@ -3682,7 +3796,7 @@ void intel_increase_renderclock(struct drm_device *dev, bool schedule) pci_write_config_word(dev->pdev, GCFGC, dev_priv->orig_clock); else if (IS_I85X(dev)) pci_write_config_word(dev->pdev, HPLLCC, dev_priv->orig_clock); - DRM_DEBUG("increasing render clock frequency\n"); + DRM_DEBUG_DRIVER("increasing render clock frequency\n"); /* Schedule downclock */ if (schedule) @@ -3694,11 +3808,11 @@ void intel_decrease_renderclock(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) return; if (!dev_priv->render_reclock_avail) { - DRM_DEBUG("not reclocking render clock\n"); + DRM_DEBUG_DRIVER("not reclocking render clock\n"); return; } @@ -3758,7 +3872,7 @@ void intel_decrease_renderclock(struct drm_device *dev) pci_write_config_word(dev->pdev, HPLLCC, hpllcc); } - DRM_DEBUG("decreasing render clock frequency\n"); + DRM_DEBUG_DRIVER("decreasing render clock frequency\n"); } /* Note that no increase function is needed for this - increase_renderclock() @@ -3766,7 +3880,7 @@ void intel_decrease_renderclock(struct drm_device *dev) */ void intel_decrease_displayclock(struct drm_device *dev) { - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) return; if (IS_I945G(dev) || IS_I945GM(dev) || IS_I915G(dev) || @@ -3792,7 +3906,7 @@ static void intel_crtc_idle_timer(unsigned long arg) struct drm_crtc *crtc = &intel_crtc->base; drm_i915_private_t *dev_priv = crtc->dev->dev_private; - DRM_DEBUG("idle timer fired, downclocking\n"); + DRM_DEBUG_DRIVER("idle timer fired, downclocking\n"); intel_crtc->busy = false; @@ -3808,14 +3922,14 @@ static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule) int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; int dpll = I915_READ(dpll_reg); - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) return; if (!dev_priv->lvds_downclock_avail) return; if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) { - DRM_DEBUG("upclocking LVDS\n"); + DRM_DEBUG_DRIVER("upclocking LVDS\n"); /* Unlock panel regs */ I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16)); @@ -3826,7 +3940,7 @@ static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule) intel_wait_for_vblank(dev); dpll = I915_READ(dpll_reg); if (dpll & DISPLAY_RATE_SELECT_FPA1) - DRM_DEBUG("failed to upclock LVDS!\n"); + DRM_DEBUG_DRIVER("failed to upclock LVDS!\n"); /* ...and lock them again */ I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3); @@ -3847,7 +3961,7 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc) int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; int dpll = I915_READ(dpll_reg); - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) return; if (!dev_priv->lvds_downclock_avail) @@ -3858,7 +3972,7 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc) * the manual case. */ if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) { - DRM_DEBUG("downclocking LVDS\n"); + DRM_DEBUG_DRIVER("downclocking LVDS\n"); /* Unlock panel regs */ I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16)); @@ -3869,7 +3983,7 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc) intel_wait_for_vblank(dev); dpll = I915_READ(dpll_reg); if (!(dpll & DISPLAY_RATE_SELECT_FPA1)) - DRM_DEBUG("failed to downclock LVDS!\n"); + DRM_DEBUG_DRIVER("failed to downclock LVDS!\n"); /* ...and lock them again */ I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3); @@ -3936,8 +4050,13 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj) if (!drm_core_check_feature(dev, DRIVER_MODESET)) return; - dev_priv->busy = true; - intel_increase_renderclock(dev, true); + if (!dev_priv->busy) { + dev_priv->busy = true; + intel_increase_renderclock(dev, true); + } else { + mod_timer(&dev_priv->idle_timer, jiffies + + msecs_to_jiffies(GPU_IDLE_TIMEOUT)); + } list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (!crtc->fb) @@ -3967,6 +4086,158 @@ static void intel_crtc_destroy(struct drm_crtc *crtc) kfree(intel_crtc); } +struct intel_unpin_work { + struct work_struct work; + struct drm_device *dev; + struct drm_gem_object *obj; + struct drm_pending_vblank_event *event; + int pending; +}; + +static void intel_unpin_work_fn(struct work_struct *__work) +{ + struct intel_unpin_work *work = + container_of(__work, struct intel_unpin_work, work); + + mutex_lock(&work->dev->struct_mutex); + i915_gem_object_unpin(work->obj); + drm_gem_object_unreference(work->obj); + mutex_unlock(&work->dev->struct_mutex); + kfree(work); +} + +void intel_finish_page_flip(struct drm_device *dev, int pipe) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_unpin_work *work; + struct drm_i915_gem_object *obj_priv; + struct drm_pending_vblank_event *e; + struct timeval now; + unsigned long flags; + + /* Ignore early vblank irqs */ + if (intel_crtc == NULL) + return; + + spin_lock_irqsave(&dev->event_lock, flags); + work = intel_crtc->unpin_work; + if (work == NULL || !work->pending) { + spin_unlock_irqrestore(&dev->event_lock, flags); + return; + } + + intel_crtc->unpin_work = NULL; + drm_vblank_put(dev, intel_crtc->pipe); + + if (work->event) { + e = work->event; + do_gettimeofday(&now); + e->event.sequence = drm_vblank_count(dev, intel_crtc->pipe); + e->event.tv_sec = now.tv_sec; + e->event.tv_usec = now.tv_usec; + list_add_tail(&e->base.link, + &e->base.file_priv->event_list); + wake_up_interruptible(&e->base.file_priv->event_wait); + } + + spin_unlock_irqrestore(&dev->event_lock, flags); + + obj_priv = work->obj->driver_private; + if (atomic_dec_and_test(&obj_priv->pending_flip)) + DRM_WAKEUP(&dev_priv->pending_flip_queue); + schedule_work(&work->work); +} + +void intel_prepare_page_flip(struct drm_device *dev, int plane) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = + to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]); + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + if (intel_crtc->unpin_work) + intel_crtc->unpin_work->pending = 1; + spin_unlock_irqrestore(&dev->event_lock, flags); +} + +static int intel_crtc_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_framebuffer *intel_fb; + struct drm_i915_gem_object *obj_priv; + struct drm_gem_object *obj; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_unpin_work *work; + unsigned long flags; + int ret; + RING_LOCALS; + + work = kzalloc(sizeof *work, GFP_KERNEL); + if (work == NULL) + return -ENOMEM; + + mutex_lock(&dev->struct_mutex); + + work->event = event; + work->dev = crtc->dev; + intel_fb = to_intel_framebuffer(crtc->fb); + work->obj = intel_fb->obj; + INIT_WORK(&work->work, intel_unpin_work_fn); + + /* We borrow the event spin lock for protecting unpin_work */ + spin_lock_irqsave(&dev->event_lock, flags); + if (intel_crtc->unpin_work) { + spin_unlock_irqrestore(&dev->event_lock, flags); + kfree(work); + mutex_unlock(&dev->struct_mutex); + return -EBUSY; + } + intel_crtc->unpin_work = work; + spin_unlock_irqrestore(&dev->event_lock, flags); + + intel_fb = to_intel_framebuffer(fb); + obj = intel_fb->obj; + + ret = intel_pin_and_fence_fb_obj(dev, obj); + if (ret != 0) { + kfree(work); + mutex_unlock(&dev->struct_mutex); + return ret; + } + + /* Reference the old fb object for the scheduled work. */ + drm_gem_object_reference(work->obj); + + crtc->fb = fb; + i915_gem_object_flush_write_domain(obj); + drm_vblank_get(dev, intel_crtc->pipe); + obj_priv = obj->driver_private; + atomic_inc(&obj_priv->pending_flip); + + BEGIN_LP_RING(4); + OUT_RING(MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + OUT_RING(fb->pitch); + if (IS_I965G(dev)) { + OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode); + OUT_RING((fb->width << 16) | fb->height); + } else { + OUT_RING(obj_priv->gtt_offset); + OUT_RING(MI_NOOP); + } + ADVANCE_LP_RING(); + + mutex_unlock(&dev->struct_mutex); + + return 0; +} + static const struct drm_crtc_helper_funcs intel_helper_funcs = { .dpms = intel_crtc_dpms, .mode_fixup = intel_crtc_mode_fixup, @@ -3983,11 +4254,13 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .gamma_set = intel_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, .destroy = intel_crtc_destroy, + .page_flip = intel_crtc_page_flip, }; static void intel_crtc_init(struct drm_device *dev, int pipe) { + drm_i915_private_t *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc; int i; @@ -4010,10 +4283,15 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) intel_crtc->pipe = pipe; intel_crtc->plane = pipe; if (IS_MOBILE(dev) && (IS_I9XX(dev) && !IS_I965G(dev))) { - DRM_DEBUG("swapping pipes & planes for FBC\n"); + DRM_DEBUG_KMS("swapping pipes & planes for FBC\n"); intel_crtc->plane = ((pipe == 0) ? 1 : 0); } + BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || + dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL); + dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base; + dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; + intel_crtc->cursor_addr = 0; intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF; drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); @@ -4090,7 +4368,7 @@ static void intel_setup_outputs(struct drm_device *dev) if (IS_MOBILE(dev) && !IS_I830(dev)) intel_lvds_init(dev); - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { int found; if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED)) @@ -4118,7 +4396,7 @@ static void intel_setup_outputs(struct drm_device *dev) if (I915_READ(PCH_DP_D) & DP_DETECTED) intel_dp_init(dev, PCH_DP_D); - } else if (IS_I9XX(dev)) { + } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) { bool found = false; if (I915_READ(SDVOB) & SDVO_DETECTED) { @@ -4145,10 +4423,10 @@ static void intel_setup_outputs(struct drm_device *dev) if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED)) intel_dp_init(dev, DP_D); - } else + } else if (IS_I8XX(dev)) intel_dvo_init(dev); - if (IS_I9XX(dev) && IS_MOBILE(dev) && !IS_IGDNG(dev)) + if (SUPPORTS_TV(dev)) intel_tv_init(dev); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { @@ -4257,7 +4535,7 @@ void intel_init_clock_gating(struct drm_device *dev) * Disable clock gating reported to work incorrectly according to the * specs, but enable as much else as we can. */ - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { return; } else if (IS_G4X(dev)) { uint32_t dspclk_gate; @@ -4291,11 +4569,52 @@ void intel_init_clock_gating(struct drm_device *dev) dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING | DSTATE_DOT_CLOCK_GATING; I915_WRITE(D_STATE, dstate); - } else if (IS_I855(dev) || IS_I865G(dev)) { + } else if (IS_I85X(dev) || IS_I865G(dev)) { I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE); } else if (IS_I830(dev)) { I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); } + + /* + * GPU can automatically power down the render unit if given a page + * to save state. + */ + if (I915_HAS_RC6(dev)) { + struct drm_gem_object *pwrctx; + struct drm_i915_gem_object *obj_priv; + int ret; + + if (dev_priv->pwrctx) { + obj_priv = dev_priv->pwrctx->driver_private; + } else { + pwrctx = drm_gem_object_alloc(dev, 4096); + if (!pwrctx) { + DRM_DEBUG("failed to alloc power context, " + "RC6 disabled\n"); + goto out; + } + + ret = i915_gem_object_pin(pwrctx, 4096); + if (ret) { + DRM_ERROR("failed to pin power context: %d\n", + ret); + drm_gem_object_unreference(pwrctx); + goto out; + } + + i915_gem_object_set_to_gtt_domain(pwrctx, 1); + + dev_priv->pwrctx = pwrctx; + obj_priv = pwrctx->driver_private; + } + + I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN); + I915_WRITE(MCHBAR_RENDER_STANDBY, + I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT); + } + +out: + return; } /* Set up chip specific display functions */ @@ -4304,8 +4623,8 @@ static void intel_init_display(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; /* We always want a DPMS function */ - if (IS_IGDNG(dev)) - dev_priv->display.dpms = igdng_crtc_dpms; + if (IS_IRONLAKE(dev)) + dev_priv->display.dpms = ironlake_crtc_dpms; else dev_priv->display.dpms = i9xx_crtc_dpms; @@ -4324,13 +4643,13 @@ static void intel_init_display(struct drm_device *dev) } /* Returns the core display clock speed */ - if (IS_I945G(dev)) + if (IS_I945G(dev) || (IS_G33(dev) && ! IS_PINEVIEW_M(dev))) dev_priv->display.get_display_clock_speed = i945_get_display_clock_speed; else if (IS_I915G(dev)) dev_priv->display.get_display_clock_speed = i915_get_display_clock_speed; - else if (IS_I945GM(dev) || IS_845G(dev) || IS_IGDGM(dev)) + else if (IS_I945GM(dev) || IS_845G(dev) || IS_PINEVIEW_M(dev)) dev_priv->display.get_display_clock_speed = i9xx_misc_get_display_clock_speed; else if (IS_I915GM(dev)) @@ -4339,7 +4658,7 @@ static void intel_init_display(struct drm_device *dev) else if (IS_I865G(dev)) dev_priv->display.get_display_clock_speed = i865_get_display_clock_speed; - else if (IS_I855(dev)) + else if (IS_I85X(dev)) dev_priv->display.get_display_clock_speed = i855_get_display_clock_speed; else /* 852, 830 */ @@ -4347,7 +4666,7 @@ static void intel_init_display(struct drm_device *dev) i830_get_display_clock_speed; /* For FIFO watermark updates */ - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) dev_priv->display.update_wm = NULL; else if (IS_G4X(dev)) dev_priv->display.update_wm = g4x_update_wm; @@ -4403,7 +4722,7 @@ void intel_modeset_init(struct drm_device *dev) num_pipe = 2; else num_pipe = 1; - DRM_DEBUG("%d display pipe%s available.\n", + DRM_DEBUG_KMS("%d display pipe%s available.\n", num_pipe, num_pipe > 1 ? "s" : ""); if (IS_I85X(dev)) @@ -4422,6 +4741,15 @@ void intel_modeset_init(struct drm_device *dev) INIT_WORK(&dev_priv->idle_work, intel_idle_update); setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, (unsigned long)dev); + + intel_setup_overlay(dev); + + if (IS_PINEVIEW(dev) && !intel_get_cxsr_latency(IS_PINEVIEW_G(dev), + dev_priv->fsb_freq, + dev_priv->mem_freq)) + DRM_INFO("failed to find known CxSR latency " + "(found fsb freq %d, mem freq %d), disabling CxSR\n", + dev_priv->fsb_freq, dev_priv->mem_freq); } void intel_modeset_cleanup(struct drm_device *dev) @@ -4445,11 +4773,21 @@ void intel_modeset_cleanup(struct drm_device *dev) intel_increase_renderclock(dev, false); del_timer_sync(&dev_priv->idle_timer); - mutex_unlock(&dev->struct_mutex); - if (dev_priv->display.disable_fbc) dev_priv->display.disable_fbc(dev); + if (dev_priv->pwrctx) { + struct drm_i915_gem_object *obj_priv; + + obj_priv = dev_priv->pwrctx->driver_private; + I915_WRITE(PWRCTXA, obj_priv->gtt_offset &~ PWRCTX_EN); + I915_READ(PWRCTXA); + i915_gem_object_unpin(dev_priv->pwrctx); + drm_gem_object_unreference(dev_priv->pwrctx); + } + + mutex_unlock(&dev->struct_mutex); + drm_mode_config_cleanup(dev); } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d83447557f9bde0d4932107096600d685a0202ab..4e7aa8b7b938ba36ea101b4284a577c60b7145c0 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -33,7 +33,8 @@ #include "intel_drv.h" #include "i915_drm.h" #include "i915_drv.h" -#include "intel_dp.h" +#include "drm_dp_helper.h" + #define DP_LINK_STATUS_SIZE 6 #define DP_LINK_CHECK_TIMEOUT (10 * 1000) @@ -223,8 +224,8 @@ intel_dp_aux_ch(struct intel_output *intel_output, */ if (IS_eDP(intel_output)) aux_clock_divider = 225; /* eDP input clock at 450Mhz */ - else if (IS_IGDNG(dev)) - aux_clock_divider = 62; /* IGDNG: input clock fixed at 125Mhz */ + else if (IS_IRONLAKE(dev)) + aux_clock_divider = 62; /* IRL input clock fixed at 125Mhz */ else aux_clock_divider = intel_hrawclk(dev) / 2; @@ -282,7 +283,7 @@ intel_dp_aux_ch(struct intel_output *intel_output, /* Timeouts occur when the device isn't connected, so they're * "normal" -- don't fill the kernel log with these */ if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { - DRM_DEBUG("dp_aux_ch timeout status 0x%08x\n", status); + DRM_DEBUG_KMS("dp_aux_ch timeout status 0x%08x\n", status); return -ETIMEDOUT; } @@ -382,17 +383,77 @@ intel_dp_aux_native_read(struct intel_output *intel_output, } static int -intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, - uint8_t *send, int send_bytes, - uint8_t *recv, int recv_bytes) +intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, + uint8_t write_byte, uint8_t *read_byte) { + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; struct intel_dp_priv *dp_priv = container_of(adapter, struct intel_dp_priv, adapter); struct intel_output *intel_output = dp_priv->intel_output; + uint16_t address = algo_data->address; + uint8_t msg[5]; + uint8_t reply[2]; + int msg_bytes; + int reply_bytes; + int ret; + + /* Set up the command byte */ + if (mode & MODE_I2C_READ) + msg[0] = AUX_I2C_READ << 4; + else + msg[0] = AUX_I2C_WRITE << 4; + + if (!(mode & MODE_I2C_STOP)) + msg[0] |= AUX_I2C_MOT << 4; - return intel_dp_aux_ch(intel_output, - send, send_bytes, recv, recv_bytes); + msg[1] = address >> 8; + msg[2] = address; + + switch (mode) { + case MODE_I2C_WRITE: + msg[3] = 0; + msg[4] = write_byte; + msg_bytes = 5; + reply_bytes = 1; + break; + case MODE_I2C_READ: + msg[3] = 0; + msg_bytes = 4; + reply_bytes = 2; + break; + default: + msg_bytes = 3; + reply_bytes = 1; + break; + } + + for (;;) { + ret = intel_dp_aux_ch(intel_output, + msg, msg_bytes, + reply, reply_bytes); + if (ret < 0) { + DRM_DEBUG_KMS("aux_ch failed %d\n", ret); + return ret; + } + switch (reply[0] & AUX_I2C_REPLY_MASK) { + case AUX_I2C_REPLY_ACK: + if (mode == MODE_I2C_READ) { + *read_byte = reply[1]; + } + return reply_bytes - 1; + case AUX_I2C_REPLY_NACK: + DRM_DEBUG_KMS("aux_ch nack\n"); + return -EREMOTEIO; + case AUX_I2C_REPLY_DEFER: + DRM_DEBUG_KMS("aux_ch defer\n"); + udelay(100); + break; + default: + DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]); + return -EREMOTEIO; + } + } } static int @@ -435,7 +496,8 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, dp_priv->link_bw = bws[clock]; dp_priv->lane_count = lane_count; adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); - DRM_DEBUG("Display port link bw %02x lane count %d clock %d\n", + DRM_DEBUG_KMS("Display port link bw %02x lane " + "count %d clock %d\n", dp_priv->link_bw, dp_priv->lane_count, adjusted_mode->clock); return true; @@ -514,7 +576,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, intel_dp_compute_m_n(3, lane_count, mode->clock, adjusted_mode->clock, &m_n); - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { if (intel_crtc->pipe == 0) { I915_WRITE(TRANSA_DATA_M1, ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | @@ -606,23 +668,23 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, } } -static void igdng_edp_backlight_on (struct drm_device *dev) +static void ironlake_edp_backlight_on (struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 pp; - DRM_DEBUG("\n"); + DRM_DEBUG_KMS("\n"); pp = I915_READ(PCH_PP_CONTROL); pp |= EDP_BLC_ENABLE; I915_WRITE(PCH_PP_CONTROL, pp); } -static void igdng_edp_backlight_off (struct drm_device *dev) +static void ironlake_edp_backlight_off (struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 pp; - DRM_DEBUG("\n"); + DRM_DEBUG_KMS("\n"); pp = I915_READ(PCH_PP_CONTROL); pp &= ~EDP_BLC_ENABLE; I915_WRITE(PCH_PP_CONTROL, pp); @@ -641,13 +703,13 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) if (dp_reg & DP_PORT_EN) { intel_dp_link_down(intel_output, dp_priv->DP); if (IS_eDP(intel_output)) - igdng_edp_backlight_off(dev); + ironlake_edp_backlight_off(dev); } } else { if (!(dp_reg & DP_PORT_EN)) { intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); if (IS_eDP(intel_output)) - igdng_edp_backlight_on(dev); + ironlake_edp_backlight_on(dev); } } dp_priv->dpms_mode = mode; @@ -1010,7 +1072,7 @@ intel_dp_link_down(struct intel_output *intel_output, uint32_t DP) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_dp_priv *dp_priv = intel_output->dev_priv; - DRM_DEBUG("\n"); + DRM_DEBUG_KMS("\n"); if (IS_eDP(intel_output)) { DP &= ~DP_PLL_ENABLE; @@ -1071,7 +1133,7 @@ intel_dp_check_link_status(struct intel_output *intel_output) } static enum drm_connector_status -igdng_dp_detect(struct drm_connector *connector) +ironlake_dp_detect(struct drm_connector *connector) { struct intel_output *intel_output = to_intel_output(connector); struct intel_dp_priv *dp_priv = intel_output->dev_priv; @@ -1106,8 +1168,8 @@ intel_dp_detect(struct drm_connector *connector) dp_priv->has_audio = false; - if (IS_IGDNG(dev)) - return igdng_dp_detect(connector); + if (IS_IRONLAKE(dev)) + return ironlake_dp_detect(connector); temp = I915_READ(PORT_HOTPLUG_EN); @@ -1227,7 +1289,53 @@ intel_dp_hot_plug(struct intel_output *intel_output) if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON) intel_dp_check_link_status(intel_output); } - +/* + * Enumerate the child dev array parsed from VBT to check whether + * the given DP is present. + * If it is present, return 1. + * If it is not present, return false. + * If no child dev is parsed from VBT, it is assumed that the given + * DP is present. + */ +static int dp_is_present_in_vbt(struct drm_device *dev, int dp_reg) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct child_device_config *p_child; + int i, dp_port, ret; + + if (!dev_priv->child_dev_num) + return 1; + + dp_port = 0; + if (dp_reg == DP_B || dp_reg == PCH_DP_B) + dp_port = PORT_IDPB; + else if (dp_reg == DP_C || dp_reg == PCH_DP_C) + dp_port = PORT_IDPC; + else if (dp_reg == DP_D || dp_reg == PCH_DP_D) + dp_port = PORT_IDPD; + + ret = 0; + for (i = 0; i < dev_priv->child_dev_num; i++) { + p_child = dev_priv->child_dev + i; + /* + * If the device type is not DP, continue. + */ + if (p_child->device_type != DEVICE_TYPE_DP && + p_child->device_type != DEVICE_TYPE_eDP) + continue; + /* Find the eDP port */ + if (dp_reg == DP_A && p_child->device_type == DEVICE_TYPE_eDP) { + ret = 1; + break; + } + /* Find the DP port */ + if (p_child->dvo_port == dp_port) { + ret = 1; + break; + } + } + return ret; +} void intel_dp_init(struct drm_device *dev, int output_reg) { @@ -1237,6 +1345,10 @@ intel_dp_init(struct drm_device *dev, int output_reg) struct intel_dp_priv *dp_priv; const char *name = NULL; + if (!dp_is_present_in_vbt(dev, output_reg)) { + DRM_DEBUG_KMS("DP is not present. Ignore it\n"); + return; + } intel_output = kcalloc(sizeof(struct intel_output) + sizeof(struct intel_dp_priv), 1, GFP_KERNEL); if (!intel_output) @@ -1254,11 +1366,11 @@ intel_dp_init(struct drm_device *dev, int output_reg) else intel_output->type = INTEL_OUTPUT_DISPLAYPORT; - if (output_reg == DP_B) + if (output_reg == DP_B || output_reg == PCH_DP_B) intel_output->clone_mask = (1 << INTEL_DP_B_CLONE_BIT); - else if (output_reg == DP_C) + else if (output_reg == DP_C || output_reg == PCH_DP_C) intel_output->clone_mask = (1 << INTEL_DP_C_CLONE_BIT); - else if (output_reg == DP_D) + else if (output_reg == DP_D || output_reg == PCH_DP_D) intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT); if (IS_eDP(intel_output)) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ef61fe9507e2e86a67ffc2dea1503ac409dbc855..a51573da1ff601f5cd868adf7485249b3708d45a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -110,6 +110,32 @@ struct intel_output { int clone_mask; }; +struct intel_crtc; +struct intel_overlay { + struct drm_device *dev; + struct intel_crtc *crtc; + struct drm_i915_gem_object *vid_bo; + struct drm_i915_gem_object *old_vid_bo; + int active; + int pfit_active; + u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */ + u32 color_key; + u32 brightness, contrast, saturation; + u32 old_xscale, old_yscale; + /* register access */ + u32 flip_addr; + struct drm_i915_gem_object *reg_bo; + void *virt_addr; + /* flip handling */ + uint32_t last_flip_req; + int hw_wedged; +#define HW_WEDGED 1 +#define NEEDS_WAIT_FOR_FLIP 2 +#define RELEASE_OLD_VID 3 +#define SWITCH_OFF_STAGE_1 4 +#define SWITCH_OFF_STAGE_2 5 +}; + struct intel_crtc { struct drm_crtc base; enum pipe pipe; @@ -121,6 +147,8 @@ struct intel_crtc { bool busy; /* is scanout buffer being updated frequently? */ struct timer_list idle_timer; bool lowfreq_avail; + struct intel_overlay *overlay; + struct intel_unpin_work *unpin_work; }; #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) @@ -134,6 +162,8 @@ void intel_i2c_destroy(struct i2c_adapter *adapter); int intel_ddc_get_modes(struct intel_output *intel_output); extern bool intel_ddc_probe(struct intel_output *intel_output); void intel_i2c_quirk_set(struct drm_device *dev, bool enable); +void intel_i2c_reset_gmbus(struct drm_device *dev); + extern void intel_crt_init(struct drm_device *dev); extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); extern bool intel_sdvo_init(struct drm_device *dev, int output_device); @@ -148,6 +178,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, extern void intel_edp_link_config (struct intel_output *, int *, int *); +extern int intel_panel_fitter_pipe (struct drm_device *dev); extern void intel_crtc_load_lut(struct drm_crtc *crtc); extern void intel_encoder_prepare (struct drm_encoder *encoder); extern void intel_encoder_commit (struct drm_encoder *encoder); @@ -177,10 +208,23 @@ extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno); extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, int regno); +extern void intel_init_clock_gating(struct drm_device *dev); extern int intel_framebuffer_create(struct drm_device *dev, struct drm_mode_fb_cmd *mode_cmd, struct drm_framebuffer **fb, struct drm_gem_object *obj); +extern void intel_prepare_page_flip(struct drm_device *dev, int plane); +extern void intel_finish_page_flip(struct drm_device *dev, int pipe); + +extern void intel_setup_overlay(struct drm_device *dev); +extern void intel_cleanup_overlay(struct drm_device *dev); +extern int intel_overlay_switch_off(struct intel_overlay *overlay); +extern int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, + int interruptible); +extern int intel_overlay_put_image(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int intel_overlay_attrs(struct drm_device *dev, void *data, + struct drm_file *file_priv); #endif /* __INTEL_DRV_H__ */ diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 40fcf6fdef3887c4cdf41d070f430ccd7c4ba952..371d753e362bf425e32dcc188454ee560a2cace7 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -230,8 +230,9 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, par->intel_fb = intel_fb; /* To allow resizeing without swapping buffers */ - DRM_DEBUG("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width, - intel_fb->base.height, obj_priv->gtt_offset, fbo); + DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", + intel_fb->base.width, intel_fb->base.height, + obj_priv->gtt_offset, fbo); mutex_unlock(&dev->struct_mutex); return 0; @@ -249,7 +250,7 @@ int intelfb_probe(struct drm_device *dev) { int ret; - DRM_DEBUG("\n"); + DRM_DEBUG_KMS("\n"); ret = drm_fb_helper_single_fb_probe(dev, 32, intelfb_create); return ret; } diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index c33451aec1bd647a601c7f256fd805598fb42d01..f04dbbe7d4005c6b123bfedc3dde6bc43bda9d18 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -82,7 +82,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) /* HW workaround, need to toggle enable bit off and on for 12bpc, but * we do this anyway which shows more stable in testing. */ - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE); POSTING_READ(hdmi_priv->sdvox_reg); } @@ -99,7 +99,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) /* HW workaround, need to write this twice for issue that may result * in first write getting masked. */ - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { I915_WRITE(hdmi_priv->sdvox_reg, temp); POSTING_READ(hdmi_priv->sdvox_reg); } @@ -225,7 +225,52 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { .destroy = intel_hdmi_enc_destroy, }; - +/* + * Enumerate the child dev array parsed from VBT to check whether + * the given HDMI is present. + * If it is present, return 1. + * If it is not present, return false. + * If no child dev is parsed from VBT, it assumes that the given + * HDMI is present. + */ +static int hdmi_is_present_in_vbt(struct drm_device *dev, int hdmi_reg) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct child_device_config *p_child; + int i, hdmi_port, ret; + + if (!dev_priv->child_dev_num) + return 1; + + if (hdmi_reg == SDVOB) + hdmi_port = DVO_B; + else if (hdmi_reg == SDVOC) + hdmi_port = DVO_C; + else if (hdmi_reg == HDMIB) + hdmi_port = DVO_B; + else if (hdmi_reg == HDMIC) + hdmi_port = DVO_C; + else if (hdmi_reg == HDMID) + hdmi_port = DVO_D; + else + return 0; + + ret = 0; + for (i = 0; i < dev_priv->child_dev_num; i++) { + p_child = dev_priv->child_dev + i; + /* + * If the device type is not HDMI, continue. + */ + if (p_child->device_type != DEVICE_TYPE_HDMI) + continue; + /* Find the HDMI port */ + if (p_child->dvo_port == hdmi_port) { + ret = 1; + break; + } + } + return ret; +} void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -233,6 +278,10 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) struct intel_output *intel_output; struct intel_hdmi_priv *hdmi_priv; + if (!hdmi_is_present_in_vbt(dev, sdvox_reg)) { + DRM_DEBUG_KMS("HDMI is not present. Ignored it \n"); + return; + } intel_output = kcalloc(sizeof(struct intel_output) + sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); if (!intel_output) diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index c7eab724c418ed5a406ca711bdcadda8874881fc..8673c735b8ab1b7fc669d5c2fd730f06d95ff66d 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -39,7 +39,7 @@ void intel_i2c_quirk_set(struct drm_device *dev, bool enable) struct drm_i915_private *dev_priv = dev->dev_private; /* When using bit bashing for I2C, this bit needs to be set to 1 */ - if (!IS_IGD(dev)) + if (!IS_PINEVIEW(dev)) return; if (enable) I915_WRITE(DSPCLK_GATE_D, @@ -118,6 +118,23 @@ static void set_data(void *data, int state_high) udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ } +/* Clears the GMBUS setup. Our driver doesn't make use of the GMBUS I2C + * engine, but if the BIOS leaves it enabled, then that can break our use + * of the bit-banging I2C interfaces. This is notably the case with the + * Mac Mini in EFI mode. + */ +void +intel_i2c_reset_gmbus(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (IS_IRONLAKE(dev)) { + I915_WRITE(PCH_GMBUS0, 0); + } else { + I915_WRITE(GMBUS0, 0); + } +} + /** * intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg * @dev: DRM device @@ -168,6 +185,8 @@ struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, if(i2c_bit_add_bus(&chan->adapter)) goto out_free; + intel_i2c_reset_gmbus(dev); + /* JJJ: raise SCL and SDA? */ intel_i2c_quirk_set(dev, true); set_data(chan, 1); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index eb365021bb5a0ccae6e22116fbd6dbf04b536c2b..3118ce274e67a6f2723e21a6c3bd873c160405d1 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -56,7 +56,7 @@ static void intel_lvds_set_backlight(struct drm_device *dev, int level) struct drm_i915_private *dev_priv = dev->dev_private; u32 blc_pwm_ctl, reg; - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) reg = BLC_PWM_CPU_CTL; else reg = BLC_PWM_CTL; @@ -74,7 +74,7 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; u32 reg; - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) reg = BLC_PWM_PCH_CTL2; else reg = BLC_PWM_CTL; @@ -91,7 +91,7 @@ static void intel_lvds_set_power(struct drm_device *dev, bool on) struct drm_i915_private *dev_priv = dev->dev_private; u32 pp_status, ctl_reg, status_reg; - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { ctl_reg = PCH_PP_CONTROL; status_reg = PCH_PP_STATUS; } else { @@ -137,7 +137,7 @@ static void intel_lvds_save(struct drm_connector *connector) u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; u32 pwm_ctl_reg; - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { pp_on_reg = PCH_PP_ON_DELAYS; pp_off_reg = PCH_PP_OFF_DELAYS; pp_ctl_reg = PCH_PP_CONTROL; @@ -174,7 +174,7 @@ static void intel_lvds_restore(struct drm_connector *connector) u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; u32 pwm_ctl_reg; - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { pp_on_reg = PCH_PP_ON_DELAYS; pp_off_reg = PCH_PP_OFF_DELAYS; pp_ctl_reg = PCH_PP_CONTROL; @@ -297,7 +297,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, } /* full screen scale for now */ - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) goto out; /* 965+ wants fuzzy fitting */ @@ -327,7 +327,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, * to register description and PRM. * Change the value here to see the borders for debugging */ - if (!IS_IGDNG(dev)) { + if (!IS_IRONLAKE(dev)) { I915_WRITE(BCLRPAT_A, 0); I915_WRITE(BCLRPAT_B, 0); } @@ -548,7 +548,7 @@ static void intel_lvds_prepare(struct drm_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; u32 reg; - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) reg = BLC_PWM_CPU_CTL; else reg = BLC_PWM_CTL; @@ -587,7 +587,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, * settings. */ - if (IS_IGDNG(dev)) + if (IS_IRONLAKE(dev)) return; /* @@ -913,6 +913,101 @@ static int intel_lid_present(void) } #endif +/** + * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID + * @dev: drm device + * @connector: LVDS connector + * + * Find the reduced downclock for LVDS in EDID. + */ +static void intel_find_lvds_downclock(struct drm_device *dev, + struct drm_connector *connector) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_display_mode *scan, *panel_fixed_mode; + int temp_downclock; + + panel_fixed_mode = dev_priv->panel_fixed_mode; + temp_downclock = panel_fixed_mode->clock; + + mutex_lock(&dev->mode_config.mutex); + list_for_each_entry(scan, &connector->probed_modes, head) { + /* + * If one mode has the same resolution with the fixed_panel + * mode while they have the different refresh rate, it means + * that the reduced downclock is found for the LVDS. In such + * case we can set the different FPx0/1 to dynamically select + * between low and high frequency. + */ + if (scan->hdisplay == panel_fixed_mode->hdisplay && + scan->hsync_start == panel_fixed_mode->hsync_start && + scan->hsync_end == panel_fixed_mode->hsync_end && + scan->htotal == panel_fixed_mode->htotal && + scan->vdisplay == panel_fixed_mode->vdisplay && + scan->vsync_start == panel_fixed_mode->vsync_start && + scan->vsync_end == panel_fixed_mode->vsync_end && + scan->vtotal == panel_fixed_mode->vtotal) { + if (scan->clock < temp_downclock) { + /* + * The downclock is already found. But we + * expect to find the lower downclock. + */ + temp_downclock = scan->clock; + } + } + } + mutex_unlock(&dev->mode_config.mutex); + if (temp_downclock < panel_fixed_mode->clock) { + /* We found the downclock for LVDS. */ + dev_priv->lvds_downclock_avail = 1; + dev_priv->lvds_downclock = temp_downclock; + DRM_DEBUG_KMS("LVDS downclock is found in EDID. " + "Normal clock %dKhz, downclock %dKhz\n", + panel_fixed_mode->clock, temp_downclock); + } + return; +} + +/* + * Enumerate the child dev array parsed from VBT to check whether + * the LVDS is present. + * If it is present, return 1. + * If it is not present, return false. + * If no child dev is parsed from VBT, it assumes that the LVDS is present. + * Note: The addin_offset should also be checked for LVDS panel. + * Only when it is non-zero, it is assumed that it is present. + */ +static int lvds_is_present_in_vbt(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct child_device_config *p_child; + int i, ret; + + if (!dev_priv->child_dev_num) + return 1; + + ret = 0; + for (i = 0; i < dev_priv->child_dev_num; i++) { + p_child = dev_priv->child_dev + i; + /* + * If the device type is not LFP, continue. + * If the device type is 0x22, it is also regarded as LFP. + */ + if (p_child->device_type != DEVICE_TYPE_INT_LFP && + p_child->device_type != DEVICE_TYPE_LFP) + continue; + + /* The addin_offset should be checked. Only when it is + * non-zero, it is regarded as present. + */ + if (p_child->addin_offset) { + ret = 1; + break; + } + } + return ret; +} + /** * intel_lvds_init - setup LVDS connectors on this device * @dev: drm device @@ -936,21 +1031,20 @@ void intel_lvds_init(struct drm_device *dev) if (dmi_check_system(intel_no_lvds)) return; - /* Assume that any device without an ACPI LID device also doesn't - * have an integrated LVDS. We would be better off parsing the BIOS - * to get a reliable indicator, but that code isn't written yet. - * - * In the case of all-in-one desktops using LVDS that we've seen, - * they're using SDVO LVDS. + /* + * Assume LVDS is present if there's an ACPI lid device or if the + * device is present in the VBT. */ - if (!intel_lid_present()) + if (!lvds_is_present_in_vbt(dev) && !intel_lid_present()) { + DRM_DEBUG_KMS("LVDS is not present in VBT and no lid detected\n"); return; + } - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) return; if (dev_priv->edp_support) { - DRM_DEBUG("disable LVDS for eDP support\n"); + DRM_DEBUG_KMS("disable LVDS for eDP support\n"); return; } gpio = PCH_GPIOC; @@ -1023,6 +1117,7 @@ void intel_lvds_init(struct drm_device *dev) dev_priv->panel_fixed_mode = drm_mode_duplicate(dev, scan); mutex_unlock(&dev->mode_config.mutex); + intel_find_lvds_downclock(dev, connector); goto out; } mutex_unlock(&dev->mode_config.mutex); @@ -1047,8 +1142,8 @@ void intel_lvds_init(struct drm_device *dev) * correct mode. */ - /* IGDNG: FIXME if still fail, not try pipe mode now */ - if (IS_IGDNG(dev)) + /* Ironlake: FIXME if still fail, not try pipe mode now */ + if (IS_IRONLAKE(dev)) goto failed; lvds = I915_READ(LVDS); @@ -1069,7 +1164,7 @@ void intel_lvds_init(struct drm_device *dev) goto failed; out: - if (IS_IGDNG(dev)) { + if (IS_IRONLAKE(dev)) { u32 pwm; /* make sure PWM is enabled */ pwm = I915_READ(BLC_PWM_CPU_CTL2); @@ -1082,7 +1177,7 @@ out: } dev_priv->lid_notifier.notifier_call = intel_lid_notify; if (acpi_lid_notifier_register(&dev_priv->lid_notifier)) { - DRM_DEBUG("lid notifier registration failed\n"); + DRM_DEBUG_KMS("lid notifier registration failed\n"); dev_priv->lid_notifier.notifier_call = NULL; } drm_sysfs_connector_add(connector); @@ -1093,5 +1188,6 @@ failed: if (intel_output->ddc_bus) intel_i2c_destroy(intel_output->ddc_bus); drm_connector_cleanup(connector); + drm_encoder_cleanup(encoder); kfree(intel_output); } diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c new file mode 100644 index 0000000000000000000000000000000000000000..2639591c72e97c74be2e6c4783b3be38f673ff04 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -0,0 +1,1416 @@ +/* + * Copyright © 2009 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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. + * + * Authors: + * Daniel Vetter + * + * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c + */ +#include "drmP.h" +#include "drm.h" +#include "i915_drm.h" +#include "i915_drv.h" +#include "i915_reg.h" +#include "intel_drv.h" + +/* Limits for overlay size. According to intel doc, the real limits are: + * Y width: 4095, UV width (planar): 2047, Y height: 2047, + * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use + * the mininum of both. */ +#define IMAGE_MAX_WIDTH 2048 +#define IMAGE_MAX_HEIGHT 2046 /* 2 * 1023 */ +/* on 830 and 845 these large limits result in the card hanging */ +#define IMAGE_MAX_WIDTH_LEGACY 1024 +#define IMAGE_MAX_HEIGHT_LEGACY 1088 + +/* overlay register definitions */ +/* OCMD register */ +#define OCMD_TILED_SURFACE (0x1<<19) +#define OCMD_MIRROR_MASK (0x3<<17) +#define OCMD_MIRROR_MODE (0x3<<17) +#define OCMD_MIRROR_HORIZONTAL (0x1<<17) +#define OCMD_MIRROR_VERTICAL (0x2<<17) +#define OCMD_MIRROR_BOTH (0x3<<17) +#define OCMD_BYTEORDER_MASK (0x3<<14) /* zero for YUYV or FOURCC YUY2 */ +#define OCMD_UV_SWAP (0x1<<14) /* YVYU */ +#define OCMD_Y_SWAP (0x2<<14) /* UYVY or FOURCC UYVY */ +#define OCMD_Y_AND_UV_SWAP (0x3<<14) /* VYUY */ +#define OCMD_SOURCE_FORMAT_MASK (0xf<<10) +#define OCMD_RGB_888 (0x1<<10) /* not in i965 Intel docs */ +#define OCMD_RGB_555 (0x2<<10) /* not in i965 Intel docs */ +#define OCMD_RGB_565 (0x3<<10) /* not in i965 Intel docs */ +#define OCMD_YUV_422_PACKED (0x8<<10) +#define OCMD_YUV_411_PACKED (0x9<<10) /* not in i965 Intel docs */ +#define OCMD_YUV_420_PLANAR (0xc<<10) +#define OCMD_YUV_422_PLANAR (0xd<<10) +#define OCMD_YUV_410_PLANAR (0xe<<10) /* also 411 */ +#define OCMD_TVSYNCFLIP_PARITY (0x1<<9) +#define OCMD_TVSYNCFLIP_ENABLE (0x1<<7) +#define OCMD_BUF_TYPE_MASK (Ox1<<5) +#define OCMD_BUF_TYPE_FRAME (0x0<<5) +#define OCMD_BUF_TYPE_FIELD (0x1<<5) +#define OCMD_TEST_MODE (0x1<<4) +#define OCMD_BUFFER_SELECT (0x3<<2) +#define OCMD_BUFFER0 (0x0<<2) +#define OCMD_BUFFER1 (0x1<<2) +#define OCMD_FIELD_SELECT (0x1<<2) +#define OCMD_FIELD0 (0x0<<1) +#define OCMD_FIELD1 (0x1<<1) +#define OCMD_ENABLE (0x1<<0) + +/* OCONFIG register */ +#define OCONF_PIPE_MASK (0x1<<18) +#define OCONF_PIPE_A (0x0<<18) +#define OCONF_PIPE_B (0x1<<18) +#define OCONF_GAMMA2_ENABLE (0x1<<16) +#define OCONF_CSC_MODE_BT601 (0x0<<5) +#define OCONF_CSC_MODE_BT709 (0x1<<5) +#define OCONF_CSC_BYPASS (0x1<<4) +#define OCONF_CC_OUT_8BIT (0x1<<3) +#define OCONF_TEST_MODE (0x1<<2) +#define OCONF_THREE_LINE_BUFFER (0x1<<0) +#define OCONF_TWO_LINE_BUFFER (0x0<<0) + +/* DCLRKM (dst-key) register */ +#define DST_KEY_ENABLE (0x1<<31) +#define CLK_RGB24_MASK 0x0 +#define CLK_RGB16_MASK 0x070307 +#define CLK_RGB15_MASK 0x070707 +#define CLK_RGB8I_MASK 0xffffff + +#define RGB16_TO_COLORKEY(c) \ + (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3)) +#define RGB15_TO_COLORKEY(c) \ + (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3)) + +/* overlay flip addr flag */ +#define OFC_UPDATE 0x1 + +/* polyphase filter coefficients */ +#define N_HORIZ_Y_TAPS 5 +#define N_VERT_Y_TAPS 3 +#define N_HORIZ_UV_TAPS 3 +#define N_VERT_UV_TAPS 3 +#define N_PHASES 17 +#define MAX_TAPS 5 + +/* memory bufferd overlay registers */ +struct overlay_registers { + u32 OBUF_0Y; + u32 OBUF_1Y; + u32 OBUF_0U; + u32 OBUF_0V; + u32 OBUF_1U; + u32 OBUF_1V; + u32 OSTRIDE; + u32 YRGB_VPH; + u32 UV_VPH; + u32 HORZ_PH; + u32 INIT_PHS; + u32 DWINPOS; + u32 DWINSZ; + u32 SWIDTH; + u32 SWIDTHSW; + u32 SHEIGHT; + u32 YRGBSCALE; + u32 UVSCALE; + u32 OCLRC0; + u32 OCLRC1; + u32 DCLRKV; + u32 DCLRKM; + u32 SCLRKVH; + u32 SCLRKVL; + u32 SCLRKEN; + u32 OCONFIG; + u32 OCMD; + u32 RESERVED1; /* 0x6C */ + u32 OSTART_0Y; + u32 OSTART_1Y; + u32 OSTART_0U; + u32 OSTART_0V; + u32 OSTART_1U; + u32 OSTART_1V; + u32 OTILEOFF_0Y; + u32 OTILEOFF_1Y; + u32 OTILEOFF_0U; + u32 OTILEOFF_0V; + u32 OTILEOFF_1U; + u32 OTILEOFF_1V; + u32 FASTHSCALE; /* 0xA0 */ + u32 UVSCALEV; /* 0xA4 */ + u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */ + u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */ + u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES]; + u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */ + u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES]; + u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */ + u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES]; + u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */ + u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES]; +}; + +/* overlay flip addr flag */ +#define OFC_UPDATE 0x1 + +#define OVERLAY_NONPHYSICAL(dev) (IS_G33(dev) || IS_I965G(dev)) +#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev)) + + +static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_overlay *overlay) +{ + drm_i915_private_t *dev_priv = overlay->dev->dev_private; + struct overlay_registers *regs; + + /* no recursive mappings */ + BUG_ON(overlay->virt_addr); + + if (OVERLAY_NONPHYSICAL(overlay->dev)) { + regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, + overlay->reg_bo->gtt_offset); + + if (!regs) { + DRM_ERROR("failed to map overlay regs in GTT\n"); + return NULL; + } + } else + regs = overlay->reg_bo->phys_obj->handle->vaddr; + + return overlay->virt_addr = regs; +} + +static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay) +{ + struct drm_device *dev = overlay->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + + if (OVERLAY_NONPHYSICAL(overlay->dev)) + io_mapping_unmap_atomic(overlay->virt_addr); + + overlay->virt_addr = NULL; + + I915_READ(OVADD); /* flush wc cashes */ + + return; +} + +/* overlay needs to be disable in OCMD reg */ +static int intel_overlay_on(struct intel_overlay *overlay) +{ + struct drm_device *dev = overlay->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + int ret; + RING_LOCALS; + + BUG_ON(overlay->active); + + overlay->active = 1; + overlay->hw_wedged = NEEDS_WAIT_FOR_FLIP; + + BEGIN_LP_RING(6); + OUT_RING(MI_FLUSH); + OUT_RING(MI_NOOP); + OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON); + OUT_RING(overlay->flip_addr | OFC_UPDATE); + OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); + + overlay->last_flip_req = i915_add_request(dev, NULL, 0); + if (overlay->last_flip_req == 0) + return -ENOMEM; + + ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); + if (ret != 0) + return ret; + + overlay->hw_wedged = 0; + overlay->last_flip_req = 0; + return 0; +} + +/* overlay needs to be enabled in OCMD reg */ +static void intel_overlay_continue(struct intel_overlay *overlay, + bool load_polyphase_filter) +{ + struct drm_device *dev = overlay->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + u32 flip_addr = overlay->flip_addr; + u32 tmp; + RING_LOCALS; + + BUG_ON(!overlay->active); + + if (load_polyphase_filter) + flip_addr |= OFC_UPDATE; + + /* check for underruns */ + tmp = I915_READ(DOVSTA); + if (tmp & (1 << 17)) + DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp); + + BEGIN_LP_RING(4); + OUT_RING(MI_FLUSH); + OUT_RING(MI_NOOP); + OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); + OUT_RING(flip_addr); + ADVANCE_LP_RING(); + + overlay->last_flip_req = i915_add_request(dev, NULL, 0); +} + +static int intel_overlay_wait_flip(struct intel_overlay *overlay) +{ + struct drm_device *dev = overlay->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + int ret; + u32 tmp; + RING_LOCALS; + + if (overlay->last_flip_req != 0) { + ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); + if (ret == 0) { + overlay->last_flip_req = 0; + + tmp = I915_READ(ISR); + + if (!(tmp & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT)) + return 0; + } + } + + /* synchronous slowpath */ + overlay->hw_wedged = RELEASE_OLD_VID; + + BEGIN_LP_RING(2); + OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); + + overlay->last_flip_req = i915_add_request(dev, NULL, 0); + if (overlay->last_flip_req == 0) + return -ENOMEM; + + ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); + if (ret != 0) + return ret; + + overlay->hw_wedged = 0; + overlay->last_flip_req = 0; + return 0; +} + +/* overlay needs to be disabled in OCMD reg */ +static int intel_overlay_off(struct intel_overlay *overlay) +{ + u32 flip_addr = overlay->flip_addr; + struct drm_device *dev = overlay->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + int ret; + RING_LOCALS; + + BUG_ON(!overlay->active); + + /* According to intel docs the overlay hw may hang (when switching + * off) without loading the filter coeffs. It is however unclear whether + * this applies to the disabling of the overlay or to the switching off + * of the hw. Do it in both cases */ + flip_addr |= OFC_UPDATE; + + /* wait for overlay to go idle */ + overlay->hw_wedged = SWITCH_OFF_STAGE_1; + + BEGIN_LP_RING(6); + OUT_RING(MI_FLUSH); + OUT_RING(MI_NOOP); + OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); + OUT_RING(flip_addr); + OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); + + overlay->last_flip_req = i915_add_request(dev, NULL, 0); + if (overlay->last_flip_req == 0) + return -ENOMEM; + + ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); + if (ret != 0) + return ret; + + /* turn overlay off */ + overlay->hw_wedged = SWITCH_OFF_STAGE_2; + + BEGIN_LP_RING(6); + OUT_RING(MI_FLUSH); + OUT_RING(MI_NOOP); + OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); + OUT_RING(flip_addr); + OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); + + overlay->last_flip_req = i915_add_request(dev, NULL, 0); + if (overlay->last_flip_req == 0) + return -ENOMEM; + + ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); + if (ret != 0) + return ret; + + overlay->hw_wedged = 0; + overlay->last_flip_req = 0; + return ret; +} + +static void intel_overlay_off_tail(struct intel_overlay *overlay) +{ + struct drm_gem_object *obj; + + /* never have the overlay hw on without showing a frame */ + BUG_ON(!overlay->vid_bo); + obj = overlay->vid_bo->obj; + + i915_gem_object_unpin(obj); + drm_gem_object_unreference(obj); + overlay->vid_bo = NULL; + + overlay->crtc->overlay = NULL; + overlay->crtc = NULL; + overlay->active = 0; +} + +/* recover from an interruption due to a signal + * We have to be careful not to repeat work forever an make forward progess. */ +int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, + int interruptible) +{ + struct drm_device *dev = overlay->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_gem_object *obj; + u32 flip_addr; + int ret; + RING_LOCALS; + + if (overlay->hw_wedged == HW_WEDGED) + return -EIO; + + if (overlay->last_flip_req == 0) { + overlay->last_flip_req = i915_add_request(dev, NULL, 0); + if (overlay->last_flip_req == 0) + return -ENOMEM; + } + + ret = i915_do_wait_request(dev, overlay->last_flip_req, interruptible); + if (ret != 0) + return ret; + + switch (overlay->hw_wedged) { + case RELEASE_OLD_VID: + obj = overlay->old_vid_bo->obj; + i915_gem_object_unpin(obj); + drm_gem_object_unreference(obj); + overlay->old_vid_bo = NULL; + break; + case SWITCH_OFF_STAGE_1: + flip_addr = overlay->flip_addr; + flip_addr |= OFC_UPDATE; + + overlay->hw_wedged = SWITCH_OFF_STAGE_2; + + BEGIN_LP_RING(6); + OUT_RING(MI_FLUSH); + OUT_RING(MI_NOOP); + OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); + OUT_RING(flip_addr); + OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); + + overlay->last_flip_req = i915_add_request(dev, NULL, 0); + if (overlay->last_flip_req == 0) + return -ENOMEM; + + ret = i915_do_wait_request(dev, overlay->last_flip_req, + interruptible); + if (ret != 0) + return ret; + + case SWITCH_OFF_STAGE_2: + intel_overlay_off_tail(overlay); + break; + default: + BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP); + } + + overlay->hw_wedged = 0; + overlay->last_flip_req = 0; + return 0; +} + +/* Wait for pending overlay flip and release old frame. + * Needs to be called before the overlay register are changed + * via intel_overlay_(un)map_regs_atomic */ +static int intel_overlay_release_old_vid(struct intel_overlay *overlay) +{ + int ret; + struct drm_gem_object *obj; + + /* only wait if there is actually an old frame to release to + * guarantee forward progress */ + if (!overlay->old_vid_bo) + return 0; + + ret = intel_overlay_wait_flip(overlay); + if (ret != 0) + return ret; + + obj = overlay->old_vid_bo->obj; + i915_gem_object_unpin(obj); + drm_gem_object_unreference(obj); + overlay->old_vid_bo = NULL; + + return 0; +} + +struct put_image_params { + int format; + short dst_x; + short dst_y; + short dst_w; + short dst_h; + short src_w; + short src_scan_h; + short src_scan_w; + short src_h; + short stride_Y; + short stride_UV; + int offset_Y; + int offset_U; + int offset_V; +}; + +static int packed_depth_bytes(u32 format) +{ + switch (format & I915_OVERLAY_DEPTH_MASK) { + case I915_OVERLAY_YUV422: + return 4; + case I915_OVERLAY_YUV411: + /* return 6; not implemented */ + default: + return -EINVAL; + } +} + +static int packed_width_bytes(u32 format, short width) +{ + switch (format & I915_OVERLAY_DEPTH_MASK) { + case I915_OVERLAY_YUV422: + return width << 1; + default: + return -EINVAL; + } +} + +static int uv_hsubsampling(u32 format) +{ + switch (format & I915_OVERLAY_DEPTH_MASK) { + case I915_OVERLAY_YUV422: + case I915_OVERLAY_YUV420: + return 2; + case I915_OVERLAY_YUV411: + case I915_OVERLAY_YUV410: + return 4; + default: + return -EINVAL; + } +} + +static int uv_vsubsampling(u32 format) +{ + switch (format & I915_OVERLAY_DEPTH_MASK) { + case I915_OVERLAY_YUV420: + case I915_OVERLAY_YUV410: + return 2; + case I915_OVERLAY_YUV422: + case I915_OVERLAY_YUV411: + return 1; + default: + return -EINVAL; + } +} + +static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width) +{ + u32 mask, shift, ret; + if (IS_I9XX(dev)) { + mask = 0x3f; + shift = 6; + } else { + mask = 0x1f; + shift = 5; + } + ret = ((offset + width + mask) >> shift) - (offset >> shift); + if (IS_I9XX(dev)) + ret <<= 1; + ret -=1; + return ret << 2; +} + +static const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = { + 0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0, + 0x3000, 0xb500, 0x19d0, 0x1880, 0xb440, + 0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0, + 0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380, + 0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320, + 0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0, + 0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260, + 0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200, + 0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0, + 0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160, + 0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120, + 0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0, + 0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0, + 0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060, + 0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040, + 0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020, + 0xb000, 0x3000, 0x0800, 0x3000, 0xb000}; +static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = { + 0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60, + 0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40, + 0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880, + 0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00, + 0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0, + 0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0, + 0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240, + 0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0, + 0x3000, 0x0800, 0x3000}; + +static void update_polyphase_filter(struct overlay_registers *regs) +{ + memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs)); + memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs)); +} + +static bool update_scaling_factors(struct intel_overlay *overlay, + struct overlay_registers *regs, + struct put_image_params *params) +{ + /* fixed point with a 12 bit shift */ + u32 xscale, yscale, xscale_UV, yscale_UV; +#define FP_SHIFT 12 +#define FRACT_MASK 0xfff + bool scale_changed = false; + int uv_hscale = uv_hsubsampling(params->format); + int uv_vscale = uv_vsubsampling(params->format); + + if (params->dst_w > 1) + xscale = ((params->src_scan_w - 1) << FP_SHIFT) + /(params->dst_w); + else + xscale = 1 << FP_SHIFT; + + if (params->dst_h > 1) + yscale = ((params->src_scan_h - 1) << FP_SHIFT) + /(params->dst_h); + else + yscale = 1 << FP_SHIFT; + + /*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/ + xscale_UV = xscale/uv_hscale; + yscale_UV = yscale/uv_vscale; + /* make the Y scale to UV scale ratio an exact multiply */ + xscale = xscale_UV * uv_hscale; + yscale = yscale_UV * uv_vscale; + /*} else { + xscale_UV = 0; + yscale_UV = 0; + }*/ + + if (xscale != overlay->old_xscale || yscale != overlay->old_yscale) + scale_changed = true; + overlay->old_xscale = xscale; + overlay->old_yscale = yscale; + + regs->YRGBSCALE = ((yscale & FRACT_MASK) << 20) + | ((xscale >> FP_SHIFT) << 16) + | ((xscale & FRACT_MASK) << 3); + regs->UVSCALE = ((yscale_UV & FRACT_MASK) << 20) + | ((xscale_UV >> FP_SHIFT) << 16) + | ((xscale_UV & FRACT_MASK) << 3); + regs->UVSCALEV = ((yscale >> FP_SHIFT) << 16) + | ((yscale_UV >> FP_SHIFT) << 0); + + if (scale_changed) + update_polyphase_filter(regs); + + return scale_changed; +} + +static void update_colorkey(struct intel_overlay *overlay, + struct overlay_registers *regs) +{ + u32 key = overlay->color_key; + switch (overlay->crtc->base.fb->bits_per_pixel) { + case 8: + regs->DCLRKV = 0; + regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE; + case 16: + if (overlay->crtc->base.fb->depth == 15) { + regs->DCLRKV = RGB15_TO_COLORKEY(key); + regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE; + } else { + regs->DCLRKV = RGB16_TO_COLORKEY(key); + regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE; + } + case 24: + case 32: + regs->DCLRKV = key; + regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE; + } +} + +static u32 overlay_cmd_reg(struct put_image_params *params) +{ + u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0; + + if (params->format & I915_OVERLAY_YUV_PLANAR) { + switch (params->format & I915_OVERLAY_DEPTH_MASK) { + case I915_OVERLAY_YUV422: + cmd |= OCMD_YUV_422_PLANAR; + break; + case I915_OVERLAY_YUV420: + cmd |= OCMD_YUV_420_PLANAR; + break; + case I915_OVERLAY_YUV411: + case I915_OVERLAY_YUV410: + cmd |= OCMD_YUV_410_PLANAR; + break; + } + } else { /* YUV packed */ + switch (params->format & I915_OVERLAY_DEPTH_MASK) { + case I915_OVERLAY_YUV422: + cmd |= OCMD_YUV_422_PACKED; + break; + case I915_OVERLAY_YUV411: + cmd |= OCMD_YUV_411_PACKED; + break; + } + + switch (params->format & I915_OVERLAY_SWAP_MASK) { + case I915_OVERLAY_NO_SWAP: + break; + case I915_OVERLAY_UV_SWAP: + cmd |= OCMD_UV_SWAP; + break; + case I915_OVERLAY_Y_SWAP: + cmd |= OCMD_Y_SWAP; + break; + case I915_OVERLAY_Y_AND_UV_SWAP: + cmd |= OCMD_Y_AND_UV_SWAP; + break; + } + } + + return cmd; +} + +int intel_overlay_do_put_image(struct intel_overlay *overlay, + struct drm_gem_object *new_bo, + struct put_image_params *params) +{ + int ret, tmp_width; + struct overlay_registers *regs; + bool scale_changed = false; + struct drm_i915_gem_object *bo_priv = new_bo->driver_private; + struct drm_device *dev = overlay->dev; + + BUG_ON(!mutex_is_locked(&dev->struct_mutex)); + BUG_ON(!mutex_is_locked(&dev->mode_config.mutex)); + BUG_ON(!overlay); + + ret = intel_overlay_release_old_vid(overlay); + if (ret != 0) + return ret; + + ret = i915_gem_object_pin(new_bo, PAGE_SIZE); + if (ret != 0) + return ret; + + ret = i915_gem_object_set_to_gtt_domain(new_bo, 0); + if (ret != 0) + goto out_unpin; + + if (!overlay->active) { + regs = intel_overlay_map_regs_atomic(overlay); + if (!regs) { + ret = -ENOMEM; + goto out_unpin; + } + regs->OCONFIG = OCONF_CC_OUT_8BIT; + if (IS_I965GM(overlay->dev)) + regs->OCONFIG |= OCONF_CSC_MODE_BT709; + regs->OCONFIG |= overlay->crtc->pipe == 0 ? + OCONF_PIPE_A : OCONF_PIPE_B; + intel_overlay_unmap_regs_atomic(overlay); + + ret = intel_overlay_on(overlay); + if (ret != 0) + goto out_unpin; + } + + regs = intel_overlay_map_regs_atomic(overlay); + if (!regs) { + ret = -ENOMEM; + goto out_unpin; + } + + regs->DWINPOS = (params->dst_y << 16) | params->dst_x; + regs->DWINSZ = (params->dst_h << 16) | params->dst_w; + + if (params->format & I915_OVERLAY_YUV_PACKED) + tmp_width = packed_width_bytes(params->format, params->src_w); + else + tmp_width = params->src_w; + + regs->SWIDTH = params->src_w; + regs->SWIDTHSW = calc_swidthsw(overlay->dev, + params->offset_Y, tmp_width); + regs->SHEIGHT = params->src_h; + regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y; + regs->OSTRIDE = params->stride_Y; + + if (params->format & I915_OVERLAY_YUV_PLANAR) { + int uv_hscale = uv_hsubsampling(params->format); + int uv_vscale = uv_vsubsampling(params->format); + u32 tmp_U, tmp_V; + regs->SWIDTH |= (params->src_w/uv_hscale) << 16; + tmp_U = calc_swidthsw(overlay->dev, params->offset_U, + params->src_w/uv_hscale); + tmp_V = calc_swidthsw(overlay->dev, params->offset_V, + params->src_w/uv_hscale); + regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16; + regs->SHEIGHT |= (params->src_h/uv_vscale) << 16; + regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U; + regs->OBUF_0V = bo_priv->gtt_offset + params->offset_V; + regs->OSTRIDE |= params->stride_UV << 16; + } + + scale_changed = update_scaling_factors(overlay, regs, params); + + update_colorkey(overlay, regs); + + regs->OCMD = overlay_cmd_reg(params); + + intel_overlay_unmap_regs_atomic(overlay); + + intel_overlay_continue(overlay, scale_changed); + + overlay->old_vid_bo = overlay->vid_bo; + overlay->vid_bo = new_bo->driver_private; + + return 0; + +out_unpin: + i915_gem_object_unpin(new_bo); + return ret; +} + +int intel_overlay_switch_off(struct intel_overlay *overlay) +{ + int ret; + struct overlay_registers *regs; + struct drm_device *dev = overlay->dev; + + BUG_ON(!mutex_is_locked(&dev->struct_mutex)); + BUG_ON(!mutex_is_locked(&dev->mode_config.mutex)); + + if (overlay->hw_wedged) { + ret = intel_overlay_recover_from_interrupt(overlay, 1); + if (ret != 0) + return ret; + } + + if (!overlay->active) + return 0; + + ret = intel_overlay_release_old_vid(overlay); + if (ret != 0) + return ret; + + regs = intel_overlay_map_regs_atomic(overlay); + regs->OCMD = 0; + intel_overlay_unmap_regs_atomic(overlay); + + ret = intel_overlay_off(overlay); + if (ret != 0) + return ret; + + intel_overlay_off_tail(overlay); + + return 0; +} + +static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, + struct intel_crtc *crtc) +{ + drm_i915_private_t *dev_priv = overlay->dev->dev_private; + u32 pipeconf; + int pipeconf_reg = (crtc->pipe == 0) ? PIPEACONF : PIPEBCONF; + + if (!crtc->base.enabled || crtc->dpms_mode != DRM_MODE_DPMS_ON) + return -EINVAL; + + pipeconf = I915_READ(pipeconf_reg); + + /* can't use the overlay with double wide pipe */ + if (!IS_I965G(overlay->dev) && pipeconf & PIPEACONF_DOUBLE_WIDE) + return -EINVAL; + + return 0; +} + +static void update_pfit_vscale_ratio(struct intel_overlay *overlay) +{ + struct drm_device *dev = overlay->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + u32 ratio; + u32 pfit_control = I915_READ(PFIT_CONTROL); + + /* XXX: This is not the same logic as in the xorg driver, but more in + * line with the intel documentation for the i965 */ + if (!IS_I965G(dev) && (pfit_control & VERT_AUTO_SCALE)) { + ratio = I915_READ(PFIT_AUTO_RATIOS) >> PFIT_VERT_SCALE_SHIFT; + } else { /* on i965 use the PGM reg to read out the autoscaler values */ + ratio = I915_READ(PFIT_PGM_RATIOS); + if (IS_I965G(dev)) + ratio >>= PFIT_VERT_SCALE_SHIFT_965; + else + ratio >>= PFIT_VERT_SCALE_SHIFT; + } + + overlay->pfit_vscale_ratio = ratio; +} + +static int check_overlay_dst(struct intel_overlay *overlay, + struct drm_intel_overlay_put_image *rec) +{ + struct drm_display_mode *mode = &overlay->crtc->base.mode; + + if ((rec->dst_x < mode->crtc_hdisplay) + && (rec->dst_x + rec->dst_width + <= mode->crtc_hdisplay) + && (rec->dst_y < mode->crtc_vdisplay) + && (rec->dst_y + rec->dst_height + <= mode->crtc_vdisplay)) + return 0; + else + return -EINVAL; +} + +static int check_overlay_scaling(struct put_image_params *rec) +{ + u32 tmp; + + /* downscaling limit is 8.0 */ + tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16; + if (tmp > 7) + return -EINVAL; + tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16; + if (tmp > 7) + return -EINVAL; + + return 0; +} + +static int check_overlay_src(struct drm_device *dev, + struct drm_intel_overlay_put_image *rec, + struct drm_gem_object *new_bo) +{ + u32 stride_mask; + int depth; + int uv_hscale = uv_hsubsampling(rec->flags); + int uv_vscale = uv_vsubsampling(rec->flags); + size_t tmp; + + /* check src dimensions */ + if (IS_845G(dev) || IS_I830(dev)) { + if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY + || rec->src_width > IMAGE_MAX_WIDTH_LEGACY) + return -EINVAL; + } else { + if (rec->src_height > IMAGE_MAX_HEIGHT + || rec->src_width > IMAGE_MAX_WIDTH) + return -EINVAL; + } + /* better safe than sorry, use 4 as the maximal subsampling ratio */ + if (rec->src_height < N_VERT_Y_TAPS*4 + || rec->src_width < N_HORIZ_Y_TAPS*4) + return -EINVAL; + + /* check alingment constrains */ + switch (rec->flags & I915_OVERLAY_TYPE_MASK) { + case I915_OVERLAY_RGB: + /* not implemented */ + return -EINVAL; + case I915_OVERLAY_YUV_PACKED: + depth = packed_depth_bytes(rec->flags); + if (uv_vscale != 1) + return -EINVAL; + if (depth < 0) + return depth; + /* ignore UV planes */ + rec->stride_UV = 0; + rec->offset_U = 0; + rec->offset_V = 0; + /* check pixel alignment */ + if (rec->offset_Y % depth) + return -EINVAL; + break; + case I915_OVERLAY_YUV_PLANAR: + if (uv_vscale < 0 || uv_hscale < 0) + return -EINVAL; + /* no offset restrictions for planar formats */ + break; + default: + return -EINVAL; + } + + if (rec->src_width % uv_hscale) + return -EINVAL; + + /* stride checking */ + stride_mask = 63; + + if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask) + return -EINVAL; + if (IS_I965G(dev) && rec->stride_Y < 512) + return -EINVAL; + + tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ? + 4 : 8; + if (rec->stride_Y > tmp*1024 || rec->stride_UV > 2*1024) + return -EINVAL; + + /* check buffer dimensions */ + switch (rec->flags & I915_OVERLAY_TYPE_MASK) { + case I915_OVERLAY_RGB: + case I915_OVERLAY_YUV_PACKED: + /* always 4 Y values per depth pixels */ + if (packed_width_bytes(rec->flags, rec->src_width) + > rec->stride_Y) + return -EINVAL; + + tmp = rec->stride_Y*rec->src_height; + if (rec->offset_Y + tmp > new_bo->size) + return -EINVAL; + break; + case I915_OVERLAY_YUV_PLANAR: + if (rec->src_width > rec->stride_Y) + return -EINVAL; + if (rec->src_width/uv_hscale > rec->stride_UV) + return -EINVAL; + + tmp = rec->stride_Y*rec->src_height; + if (rec->offset_Y + tmp > new_bo->size) + return -EINVAL; + tmp = rec->stride_UV*rec->src_height; + tmp /= uv_vscale; + if (rec->offset_U + tmp > new_bo->size + || rec->offset_V + tmp > new_bo->size) + return -EINVAL; + break; + } + + return 0; +} + +int intel_overlay_put_image(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_intel_overlay_put_image *put_image_rec = data; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_overlay *overlay; + struct drm_mode_object *drmmode_obj; + struct intel_crtc *crtc; + struct drm_gem_object *new_bo; + struct put_image_params *params; + int ret; + + if (!dev_priv) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + + overlay = dev_priv->overlay; + if (!overlay) { + DRM_DEBUG("userspace bug: no overlay\n"); + return -ENODEV; + } + + if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) { + mutex_lock(&dev->mode_config.mutex); + mutex_lock(&dev->struct_mutex); + + ret = intel_overlay_switch_off(overlay); + + mutex_unlock(&dev->struct_mutex); + mutex_unlock(&dev->mode_config.mutex); + + return ret; + } + + params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL); + if (!params) + return -ENOMEM; + + drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id, + DRM_MODE_OBJECT_CRTC); + if (!drmmode_obj) + return -ENOENT; + crtc = to_intel_crtc(obj_to_crtc(drmmode_obj)); + + new_bo = drm_gem_object_lookup(dev, file_priv, + put_image_rec->bo_handle); + if (!new_bo) + return -ENOENT; + + mutex_lock(&dev->mode_config.mutex); + mutex_lock(&dev->struct_mutex); + + if (overlay->hw_wedged) { + ret = intel_overlay_recover_from_interrupt(overlay, 1); + if (ret != 0) + goto out_unlock; + } + + if (overlay->crtc != crtc) { + struct drm_display_mode *mode = &crtc->base.mode; + ret = intel_overlay_switch_off(overlay); + if (ret != 0) + goto out_unlock; + + ret = check_overlay_possible_on_crtc(overlay, crtc); + if (ret != 0) + goto out_unlock; + + overlay->crtc = crtc; + crtc->overlay = overlay; + + if (intel_panel_fitter_pipe(dev) == crtc->pipe + /* and line to wide, i.e. one-line-mode */ + && mode->hdisplay > 1024) { + overlay->pfit_active = 1; + update_pfit_vscale_ratio(overlay); + } else + overlay->pfit_active = 0; + } + + ret = check_overlay_dst(overlay, put_image_rec); + if (ret != 0) + goto out_unlock; + + if (overlay->pfit_active) { + params->dst_y = ((((u32)put_image_rec->dst_y) << 12) / + overlay->pfit_vscale_ratio); + /* shifting right rounds downwards, so add 1 */ + params->dst_h = ((((u32)put_image_rec->dst_height) << 12) / + overlay->pfit_vscale_ratio) + 1; + } else { + params->dst_y = put_image_rec->dst_y; + params->dst_h = put_image_rec->dst_height; + } + params->dst_x = put_image_rec->dst_x; + params->dst_w = put_image_rec->dst_width; + + params->src_w = put_image_rec->src_width; + params->src_h = put_image_rec->src_height; + params->src_scan_w = put_image_rec->src_scan_width; + params->src_scan_h = put_image_rec->src_scan_height; + if (params->src_scan_h > params->src_h + || params->src_scan_w > params->src_w) { + ret = -EINVAL; + goto out_unlock; + } + + ret = check_overlay_src(dev, put_image_rec, new_bo); + if (ret != 0) + goto out_unlock; + params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK; + params->stride_Y = put_image_rec->stride_Y; + params->stride_UV = put_image_rec->stride_UV; + params->offset_Y = put_image_rec->offset_Y; + params->offset_U = put_image_rec->offset_U; + params->offset_V = put_image_rec->offset_V; + + /* Check scaling after src size to prevent a divide-by-zero. */ + ret = check_overlay_scaling(params); + if (ret != 0) + goto out_unlock; + + ret = intel_overlay_do_put_image(overlay, new_bo, params); + if (ret != 0) + goto out_unlock; + + mutex_unlock(&dev->struct_mutex); + mutex_unlock(&dev->mode_config.mutex); + + kfree(params); + + return 0; + +out_unlock: + mutex_unlock(&dev->struct_mutex); + mutex_unlock(&dev->mode_config.mutex); + drm_gem_object_unreference(new_bo); + kfree(params); + + return ret; +} + +static void update_reg_attrs(struct intel_overlay *overlay, + struct overlay_registers *regs) +{ + regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff); + regs->OCLRC1 = overlay->saturation; +} + +static bool check_gamma_bounds(u32 gamma1, u32 gamma2) +{ + int i; + + if (gamma1 & 0xff000000 || gamma2 & 0xff000000) + return false; + + for (i = 0; i < 3; i++) { + if (((gamma1 >> i * 8) & 0xff) >= ((gamma2 >> i*8) & 0xff)) + return false; + } + + return true; +} + +static bool check_gamma5_errata(u32 gamma5) +{ + int i; + + for (i = 0; i < 3; i++) { + if (((gamma5 >> i*8) & 0xff) == 0x80) + return false; + } + + return true; +} + +static int check_gamma(struct drm_intel_overlay_attrs *attrs) +{ + if (!check_gamma_bounds(0, attrs->gamma0) + || !check_gamma_bounds(attrs->gamma0, attrs->gamma1) + || !check_gamma_bounds(attrs->gamma1, attrs->gamma2) + || !check_gamma_bounds(attrs->gamma2, attrs->gamma3) + || !check_gamma_bounds(attrs->gamma3, attrs->gamma4) + || !check_gamma_bounds(attrs->gamma4, attrs->gamma5) + || !check_gamma_bounds(attrs->gamma5, 0x00ffffff)) + return -EINVAL; + if (!check_gamma5_errata(attrs->gamma5)) + return -EINVAL; + return 0; +} + +int intel_overlay_attrs(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_intel_overlay_attrs *attrs = data; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_overlay *overlay; + struct overlay_registers *regs; + int ret; + + if (!dev_priv) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + + overlay = dev_priv->overlay; + if (!overlay) { + DRM_DEBUG("userspace bug: no overlay\n"); + return -ENODEV; + } + + mutex_lock(&dev->mode_config.mutex); + mutex_lock(&dev->struct_mutex); + + if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) { + attrs->color_key = overlay->color_key; + attrs->brightness = overlay->brightness; + attrs->contrast = overlay->contrast; + attrs->saturation = overlay->saturation; + + if (IS_I9XX(dev)) { + attrs->gamma0 = I915_READ(OGAMC0); + attrs->gamma1 = I915_READ(OGAMC1); + attrs->gamma2 = I915_READ(OGAMC2); + attrs->gamma3 = I915_READ(OGAMC3); + attrs->gamma4 = I915_READ(OGAMC4); + attrs->gamma5 = I915_READ(OGAMC5); + } + ret = 0; + } else { + overlay->color_key = attrs->color_key; + if (attrs->brightness >= -128 && attrs->brightness <= 127) { + overlay->brightness = attrs->brightness; + } else { + ret = -EINVAL; + goto out_unlock; + } + if (attrs->contrast <= 255) { + overlay->contrast = attrs->contrast; + } else { + ret = -EINVAL; + goto out_unlock; + } + if (attrs->saturation <= 1023) { + overlay->saturation = attrs->saturation; + } else { + ret = -EINVAL; + goto out_unlock; + } + + regs = intel_overlay_map_regs_atomic(overlay); + if (!regs) { + ret = -ENOMEM; + goto out_unlock; + } + + update_reg_attrs(overlay, regs); + + intel_overlay_unmap_regs_atomic(overlay); + + if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) { + if (!IS_I9XX(dev)) { + ret = -EINVAL; + goto out_unlock; + } + + if (overlay->active) { + ret = -EBUSY; + goto out_unlock; + } + + ret = check_gamma(attrs); + if (ret != 0) + goto out_unlock; + + I915_WRITE(OGAMC0, attrs->gamma0); + I915_WRITE(OGAMC1, attrs->gamma1); + I915_WRITE(OGAMC2, attrs->gamma2); + I915_WRITE(OGAMC3, attrs->gamma3); + I915_WRITE(OGAMC4, attrs->gamma4); + I915_WRITE(OGAMC5, attrs->gamma5); + } + ret = 0; + } + +out_unlock: + mutex_unlock(&dev->struct_mutex); + mutex_unlock(&dev->mode_config.mutex); + + return ret; +} + +void intel_setup_overlay(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_overlay *overlay; + struct drm_gem_object *reg_bo; + struct overlay_registers *regs; + int ret; + + if (!OVERLAY_EXISTS(dev)) + return; + + overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL); + if (!overlay) + return; + overlay->dev = dev; + + reg_bo = drm_gem_object_alloc(dev, PAGE_SIZE); + if (!reg_bo) + goto out_free; + overlay->reg_bo = reg_bo->driver_private; + + if (OVERLAY_NONPHYSICAL(dev)) { + ret = i915_gem_object_pin(reg_bo, PAGE_SIZE); + if (ret) { + DRM_ERROR("failed to pin overlay register bo\n"); + goto out_free_bo; + } + overlay->flip_addr = overlay->reg_bo->gtt_offset; + } else { + ret = i915_gem_attach_phys_object(dev, reg_bo, + I915_GEM_PHYS_OVERLAY_REGS); + if (ret) { + DRM_ERROR("failed to attach phys overlay regs\n"); + goto out_free_bo; + } + overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr; + } + + /* init all values */ + overlay->color_key = 0x0101fe; + overlay->brightness = -19; + overlay->contrast = 75; + overlay->saturation = 146; + + regs = intel_overlay_map_regs_atomic(overlay); + if (!regs) + goto out_free_bo; + + memset(regs, 0, sizeof(struct overlay_registers)); + update_polyphase_filter(regs); + + update_reg_attrs(overlay, regs); + + intel_overlay_unmap_regs_atomic(overlay); + + dev_priv->overlay = overlay; + DRM_INFO("initialized overlay support\n"); + return; + +out_free_bo: + drm_gem_object_unreference(reg_bo); +out_free: + kfree(overlay); + return; +} + +void intel_cleanup_overlay(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + + if (dev_priv->overlay) { + /* The bo's should be free'd by the generic code already. + * Furthermore modesetting teardown happens beforehand so the + * hardware should be off already */ + BUG_ON(dev_priv->overlay->active); + + kfree(dev_priv->overlay); + } +} diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index e7fa3279e2f82539e8357b5f6942af4731af2132..24a3dc99716c5c8e5490ded0abd503312a544f2a 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -36,8 +36,6 @@ #include "i915_drv.h" #include "intel_sdvo_regs.h" -#undef SDVO_DEBUG - static char *tv_format_names[] = { "NTSC_M" , "NTSC_J" , "NTSC_443", "PAL_B" , "PAL_D" , "PAL_G" , @@ -356,7 +354,6 @@ static const struct _sdvo_cmd_name { #define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC") #define SDVO_PRIV(output) ((struct intel_sdvo_priv *) (output)->dev_priv) -#ifdef SDVO_DEBUG static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd, void *args, int args_len) { @@ -379,9 +376,6 @@ static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd, DRM_LOG_KMS("(%02X)", cmd); DRM_LOG_KMS("\n"); } -#else -#define intel_sdvo_debug_write(o, c, a, l) -#endif static void intel_sdvo_write_cmd(struct intel_output *intel_output, u8 cmd, void *args, int args_len) @@ -398,7 +392,6 @@ static void intel_sdvo_write_cmd(struct intel_output *intel_output, u8 cmd, intel_sdvo_write_byte(intel_output, SDVO_I2C_OPCODE, cmd); } -#ifdef SDVO_DEBUG static const char *cmd_status_names[] = { "Power on", "Success", @@ -427,9 +420,6 @@ static void intel_sdvo_debug_response(struct intel_output *intel_output, DRM_LOG_KMS("(??? %d)", status); DRM_LOG_KMS("\n"); } -#else -#define intel_sdvo_debug_response(o, r, l, s) -#endif static u8 intel_sdvo_read_response(struct intel_output *intel_output, void *response, int response_len) @@ -1627,6 +1617,10 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); + if (sdvo_priv->is_tv) { + /* add 30ms delay when the output type is SDVO-TV */ + mdelay(30); + } status = intel_sdvo_read_response(intel_output, &response, 2); DRM_DEBUG_KMS("SDVO response %d %d\n", response & 0xff, response >> 8); diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 9ca917931afbc27db9e0b1ac6de6488f4d625b18..552ec110b74197c2394058ef4c89b144bc3e3137 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1213,20 +1213,17 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, tv_ctl |= TV_TRILEVEL_SYNC; if (tv_mode->pal_burst) tv_ctl |= TV_PAL_BURST; + scctl1 = 0; - /* dda1 implies valid video levels */ - if (tv_mode->dda1_inc) { + if (tv_mode->dda1_inc) scctl1 |= TV_SC_DDA1_EN; - } - if (tv_mode->dda2_inc) scctl1 |= TV_SC_DDA2_EN; - if (tv_mode->dda3_inc) scctl1 |= TV_SC_DDA3_EN; - scctl1 |= tv_mode->sc_reset; - scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT; + if (video_levels) + scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT; scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT; scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT | @@ -1416,16 +1413,16 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output) * 0 0 0 Component */ if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) { - DRM_DEBUG("Detected Composite TV connection\n"); + DRM_DEBUG_KMS("Detected Composite TV connection\n"); type = DRM_MODE_CONNECTOR_Composite; } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) { - DRM_DEBUG("Detected S-Video TV connection\n"); + DRM_DEBUG_KMS("Detected S-Video TV connection\n"); type = DRM_MODE_CONNECTOR_SVIDEO; } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) { - DRM_DEBUG("Detected Component TV connection\n"); + DRM_DEBUG_KMS("Detected Component TV connection\n"); type = DRM_MODE_CONNECTOR_Component; } else { - DRM_DEBUG("No TV connection detected\n"); + DRM_DEBUG_KMS("No TV connection detected\n"); type = -1; } @@ -1702,6 +1699,41 @@ static const struct drm_encoder_funcs intel_tv_enc_funcs = { .destroy = intel_tv_enc_destroy, }; +/* + * Enumerate the child dev array parsed from VBT to check whether + * the integrated TV is present. + * If it is present, return 1. + * If it is not present, return false. + * If no child dev is parsed from VBT, it assumes that the TV is present. + */ +static int tv_is_present_in_vbt(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct child_device_config *p_child; + int i, ret; + + if (!dev_priv->child_dev_num) + return 1; + + ret = 0; + for (i = 0; i < dev_priv->child_dev_num; i++) { + p_child = dev_priv->child_dev + i; + /* + * If the device type is not TV, continue. + */ + if (p_child->device_type != DEVICE_TYPE_INT_TV && + p_child->device_type != DEVICE_TYPE_TV) + continue; + /* Only when the addin_offset is non-zero, it is regarded + * as present. + */ + if (p_child->addin_offset) { + ret = 1; + break; + } + } + return ret; +} void intel_tv_init(struct drm_device *dev) @@ -1717,6 +1749,10 @@ intel_tv_init(struct drm_device *dev) if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) return; + if (!tv_is_present_in_vbt(dev)) { + DRM_DEBUG_KMS("Integrated TV is not present.\n"); + return; + } /* Even if we have an encoder we may not have a connector */ if (!dev_priv->int_tv_support) return; diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..d823e63195162fbc7cf3b750daf5da3be14baf73 --- /dev/null +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -0,0 +1,44 @@ +config DRM_NOUVEAU + tristate "Nouveau (nVidia) cards" + depends on DRM + select FW_LOADER + select DRM_KMS_HELPER + select DRM_TTM + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB + select FRAMEBUFFER_CONSOLE if !EMBEDDED + select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT + help + Choose this option for open-source nVidia support. + +config DRM_NOUVEAU_BACKLIGHT + bool "Support for backlight control" + depends on DRM_NOUVEAU + default y + help + Say Y here if you want to control the backlight of your display + (e.g. a laptop panel). + +config DRM_NOUVEAU_DEBUG + bool "Build in Nouveau's debugfs support" + depends on DRM_NOUVEAU && DEBUG_FS + default y + help + Say Y here if you want Nouveau to output debugging information + via debugfs. + +menu "I2C encoder or helper chips" + depends on DRM + +config DRM_I2C_CH7006 + tristate "Chrontel ch7006 TV encoder" + default m if DRM_NOUVEAU + help + Support for Chrontel ch7006 and similar TV encoders, found + on some nVidia video cards. + + This driver is currently only useful if you're also using + the nouveau driver. +endmenu diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1d90d4d0144f593aecc5c9194ddc65eded6b4acc --- /dev/null +++ b/drivers/gpu/drm/nouveau/Makefile @@ -0,0 +1,31 @@ +# +# Makefile for the drm device driver. This driver provides support for the +# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. + +ccflags-y := -Iinclude/drm +nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ + nouveau_object.o nouveau_irq.o nouveau_notifier.o \ + nouveau_sgdma.o nouveau_dma.o \ + nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ + nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ + nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ + nouveau_dp.o \ + nv04_timer.o \ + nv04_mc.o nv40_mc.o nv50_mc.o \ + nv04_fb.o nv10_fb.o nv40_fb.o \ + nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \ + nv04_graph.o nv10_graph.o nv20_graph.o \ + nv40_graph.o nv50_graph.o \ + nv04_instmem.o nv50_instmem.o \ + nv50_crtc.o nv50_dac.o nv50_sor.o \ + nv50_cursor.o nv50_display.o nv50_fbcon.o \ + nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ + nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \ + nv17_gpio.o + +nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o +nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o +nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o +nouveau-$(CONFIG_ACPI) += nouveau_acpi.o + +obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c new file mode 100644 index 0000000000000000000000000000000000000000..1cf488247a16a59a49adac684d640c80ceba62f7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include + +#include "drmP.h" +#include "drm.h" +#include "drm_sarea.h" +#include "drm_crtc_helper.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nv50_display.h" + +#define NOUVEAU_DSM_SUPPORTED 0x00 +#define NOUVEAU_DSM_SUPPORTED_FUNCTIONS 0x00 + +#define NOUVEAU_DSM_ACTIVE 0x01 +#define NOUVEAU_DSM_ACTIVE_QUERY 0x00 + +#define NOUVEAU_DSM_LED 0x02 +#define NOUVEAU_DSM_LED_STATE 0x00 +#define NOUVEAU_DSM_LED_OFF 0x10 +#define NOUVEAU_DSM_LED_STAMINA 0x11 +#define NOUVEAU_DSM_LED_SPEED 0x12 + +#define NOUVEAU_DSM_POWER 0x03 +#define NOUVEAU_DSM_POWER_STATE 0x00 +#define NOUVEAU_DSM_POWER_SPEED 0x01 +#define NOUVEAU_DSM_POWER_STAMINA 0x02 + +static int nouveau_dsm(struct drm_device *dev, int func, int arg, int *result) +{ + static char muid[] = { + 0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D, + 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4, + }; + + struct pci_dev *pdev = dev->pdev; + struct acpi_handle *handle; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_object_list input; + union acpi_object params[4]; + union acpi_object *obj; + int err; + + handle = DEVICE_ACPI_HANDLE(&pdev->dev); + + if (!handle) + return -ENODEV; + + input.count = 4; + input.pointer = params; + params[0].type = ACPI_TYPE_BUFFER; + params[0].buffer.length = sizeof(muid); + params[0].buffer.pointer = (char *)muid; + params[1].type = ACPI_TYPE_INTEGER; + params[1].integer.value = 0x00000102; + params[2].type = ACPI_TYPE_INTEGER; + params[2].integer.value = func; + params[3].type = ACPI_TYPE_INTEGER; + params[3].integer.value = arg; + + err = acpi_evaluate_object(handle, "_DSM", &input, &output); + if (err) { + NV_INFO(dev, "failed to evaluate _DSM: %d\n", err); + return err; + } + + obj = (union acpi_object *)output.pointer; + + if (obj->type == ACPI_TYPE_INTEGER) + if (obj->integer.value == 0x80000002) + return -ENODEV; + + if (obj->type == ACPI_TYPE_BUFFER) { + if (obj->buffer.length == 4 && result) { + *result = 0; + *result |= obj->buffer.pointer[0]; + *result |= (obj->buffer.pointer[1] << 8); + *result |= (obj->buffer.pointer[2] << 16); + *result |= (obj->buffer.pointer[3] << 24); + } + } + + kfree(output.pointer); + return 0; +} + +int nouveau_hybrid_setup(struct drm_device *dev) +{ + int result; + + if (nouveau_dsm(dev, NOUVEAU_DSM_ACTIVE, NOUVEAU_DSM_ACTIVE_QUERY, + &result)) + return -ENODEV; + + NV_INFO(dev, "_DSM hardware status gave 0x%x\n", result); + + if (result & 0x1) { /* Stamina mode - disable the external GPU */ + nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_STAMINA, + NULL); + nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_STAMINA, + NULL); + } else { /* Ensure that the external GPU is enabled */ + nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_SPEED, NULL); + nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_SPEED, + NULL); + } + + return 0; +} + +bool nouveau_dsm_probe(struct drm_device *dev) +{ + int support = 0; + + if (nouveau_dsm(dev, NOUVEAU_DSM_SUPPORTED, + NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &support)) + return false; + + if (!support) + return false; + + return true; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c new file mode 100644 index 0000000000000000000000000000000000000000..20564f8cb0ec45f2fa13f82aa69c6bea375600e5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2009 Red Hat + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +/* + * Authors: + * Matthew Garrett + * + * Register locations derived from NVClock by Roderick Colenbrander + */ + +#include + +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_reg.h" + +static int nv40_get_intensity(struct backlight_device *bd) +{ + struct drm_device *dev = bl_get_data(bd); + int val = (nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK) + >> 16; + + return val; +} + +static int nv40_set_intensity(struct backlight_device *bd) +{ + struct drm_device *dev = bl_get_data(bd); + int val = bd->props.brightness; + int reg = nv_rd32(dev, NV40_PMC_BACKLIGHT); + + nv_wr32(dev, NV40_PMC_BACKLIGHT, + (val << 16) | (reg & ~NV40_PMC_BACKLIGHT_MASK)); + + return 0; +} + +static struct backlight_ops nv40_bl_ops = { + .options = BL_CORE_SUSPENDRESUME, + .get_brightness = nv40_get_intensity, + .update_status = nv40_set_intensity, +}; + +static int nv50_get_intensity(struct backlight_device *bd) +{ + struct drm_device *dev = bl_get_data(bd); + + return nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT); +} + +static int nv50_set_intensity(struct backlight_device *bd) +{ + struct drm_device *dev = bl_get_data(bd); + int val = bd->props.brightness; + + nv_wr32(dev, NV50_PDISPLAY_SOR_BACKLIGHT, + val | NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE); + return 0; +} + +static struct backlight_ops nv50_bl_ops = { + .options = BL_CORE_SUSPENDRESUME, + .get_brightness = nv50_get_intensity, + .update_status = nv50_set_intensity, +}; + +static int nouveau_nv40_backlight_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct backlight_device *bd; + + if (!(nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK)) + return 0; + + bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev, + &nv40_bl_ops); + if (IS_ERR(bd)) + return PTR_ERR(bd); + + dev_priv->backlight = bd; + bd->props.max_brightness = 31; + bd->props.brightness = nv40_get_intensity(bd); + backlight_update_status(bd); + + return 0; +} + +static int nouveau_nv50_backlight_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct backlight_device *bd; + + if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT)) + return 0; + + bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev, + &nv50_bl_ops); + if (IS_ERR(bd)) + return PTR_ERR(bd); + + dev_priv->backlight = bd; + bd->props.max_brightness = 1025; + bd->props.brightness = nv50_get_intensity(bd); + backlight_update_status(bd); + return 0; +} + +int nouveau_backlight_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + switch (dev_priv->card_type) { + case NV_40: + return nouveau_nv40_backlight_init(dev); + case NV_50: + return nouveau_nv50_backlight_init(dev); + default: + break; + } + + return 0; +} + +void nouveau_backlight_exit(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->backlight) { + backlight_device_unregister(dev_priv->backlight); + dev_priv->backlight = NULL; + } +} diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c new file mode 100644 index 0000000000000000000000000000000000000000..5eec5ed69489ef3546d32e159f4dde2fb39db183 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -0,0 +1,6095 @@ +/* + * Copyright 2005-2006 Erik Waling + * Copyright 2006 Stephane Marchesin + * Copyright 2007-2009 Stuart Bennett + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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 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 "drmP.h" +#define NV_DEBUG_NOTRACE +#include "nouveau_drv.h" +#include "nouveau_hw.h" + +/* these defines are made up */ +#define NV_CIO_CRE_44_HEADA 0x0 +#define NV_CIO_CRE_44_HEADB 0x3 +#define FEATURE_MOBILE 0x10 /* also FEATURE_QUADRO for BMP */ +#define LEGACY_I2C_CRT 0x80 +#define LEGACY_I2C_PANEL 0x81 +#define LEGACY_I2C_TV 0x82 + +#define EDID1_LEN 128 + +#define BIOSLOG(sip, fmt, arg...) NV_DEBUG(sip->dev, fmt, ##arg) +#define LOG_OLD_VALUE(x) + +#define ROM16(x) le16_to_cpu(*(uint16_t *)&(x)) +#define ROM32(x) le32_to_cpu(*(uint32_t *)&(x)) + +struct init_exec { + bool execute; + bool repeat; +}; + +static bool nv_cksum(const uint8_t *data, unsigned int length) +{ + /* + * There's a few checksums in the BIOS, so here's a generic checking + * function. + */ + int i; + uint8_t sum = 0; + + for (i = 0; i < length; i++) + sum += data[i]; + + if (sum) + return true; + + return false; +} + +static int +score_vbios(struct drm_device *dev, const uint8_t *data, const bool writeable) +{ + if (!(data[0] == 0x55 && data[1] == 0xAA)) { + NV_TRACEWARN(dev, "... BIOS signature not found\n"); + return 0; + } + + if (nv_cksum(data, data[2] * 512)) { + NV_TRACEWARN(dev, "... BIOS checksum invalid\n"); + /* if a ro image is somewhat bad, it's probably all rubbish */ + return writeable ? 2 : 1; + } else + NV_TRACE(dev, "... appears to be valid\n"); + + return 3; +} + +static void load_vbios_prom(struct drm_device *dev, uint8_t *data) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t pci_nv_20, save_pci_nv_20; + int pcir_ptr; + int i; + + if (dev_priv->card_type >= NV_50) + pci_nv_20 = 0x88050; + else + pci_nv_20 = NV_PBUS_PCI_NV_20; + + /* enable ROM access */ + save_pci_nv_20 = nvReadMC(dev, pci_nv_20); + nvWriteMC(dev, pci_nv_20, + save_pci_nv_20 & ~NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED); + + /* bail if no rom signature */ + if (nv_rd08(dev, NV_PROM_OFFSET) != 0x55 || + nv_rd08(dev, NV_PROM_OFFSET + 1) != 0xaa) + goto out; + + /* additional check (see note below) - read PCI record header */ + pcir_ptr = nv_rd08(dev, NV_PROM_OFFSET + 0x18) | + nv_rd08(dev, NV_PROM_OFFSET + 0x19) << 8; + if (nv_rd08(dev, NV_PROM_OFFSET + pcir_ptr) != 'P' || + nv_rd08(dev, NV_PROM_OFFSET + pcir_ptr + 1) != 'C' || + nv_rd08(dev, NV_PROM_OFFSET + pcir_ptr + 2) != 'I' || + nv_rd08(dev, NV_PROM_OFFSET + pcir_ptr + 3) != 'R') + goto out; + + /* on some 6600GT/6800LE prom reads are messed up. nvclock alleges a + * a good read may be obtained by waiting or re-reading (cargocult: 5x) + * each byte. we'll hope pramin has something usable instead + */ + for (i = 0; i < NV_PROM_SIZE; i++) + data[i] = nv_rd08(dev, NV_PROM_OFFSET + i); + +out: + /* disable ROM access */ + nvWriteMC(dev, pci_nv_20, + save_pci_nv_20 | NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED); +} + +static void load_vbios_pramin(struct drm_device *dev, uint8_t *data) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t old_bar0_pramin = 0; + int i; + + if (dev_priv->card_type >= NV_50) { + uint32_t vbios_vram = (nv_rd32(dev, 0x619f04) & ~0xff) << 8; + + if (!vbios_vram) + vbios_vram = (nv_rd32(dev, 0x1700) << 16) + 0xf0000; + + old_bar0_pramin = nv_rd32(dev, 0x1700); + nv_wr32(dev, 0x1700, vbios_vram >> 16); + } + + /* bail if no rom signature */ + if (nv_rd08(dev, NV_PRAMIN_OFFSET) != 0x55 || + nv_rd08(dev, NV_PRAMIN_OFFSET + 1) != 0xaa) + goto out; + + for (i = 0; i < NV_PROM_SIZE; i++) + data[i] = nv_rd08(dev, NV_PRAMIN_OFFSET + i); + +out: + if (dev_priv->card_type >= NV_50) + nv_wr32(dev, 0x1700, old_bar0_pramin); +} + +static void load_vbios_pci(struct drm_device *dev, uint8_t *data) +{ + void __iomem *rom = NULL; + size_t rom_len; + int ret; + + ret = pci_enable_rom(dev->pdev); + if (ret) + return; + + rom = pci_map_rom(dev->pdev, &rom_len); + if (!rom) + goto out; + memcpy_fromio(data, rom, rom_len); + pci_unmap_rom(dev->pdev, rom); + +out: + pci_disable_rom(dev->pdev); +} + +struct methods { + const char desc[8]; + void (*loadbios)(struct drm_device *, uint8_t *); + const bool rw; + int score; +}; + +static struct methods nv04_methods[] = { + { "PROM", load_vbios_prom, false }, + { "PRAMIN", load_vbios_pramin, true }, + { "PCIROM", load_vbios_pci, true }, + { } +}; + +static struct methods nv50_methods[] = { + { "PRAMIN", load_vbios_pramin, true }, + { "PROM", load_vbios_prom, false }, + { "PCIROM", load_vbios_pci, true }, + { } +}; + +static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct methods *methods, *method; + int testscore = 3; + + if (nouveau_vbios) { + method = nv04_methods; + while (method->loadbios) { + if (!strcasecmp(nouveau_vbios, method->desc)) + break; + method++; + } + + if (method->loadbios) { + NV_INFO(dev, "Attempting to use BIOS image from %s\n", + method->desc); + + method->loadbios(dev, data); + if (score_vbios(dev, data, method->rw)) + return true; + } + + NV_ERROR(dev, "VBIOS source \'%s\' invalid\n", nouveau_vbios); + } + + if (dev_priv->card_type < NV_50) + methods = nv04_methods; + else + methods = nv50_methods; + + method = methods; + while (method->loadbios) { + NV_TRACE(dev, "Attempting to load BIOS image from %s\n", + method->desc); + data[0] = data[1] = 0; /* avoid reuse of previous image */ + method->loadbios(dev, data); + method->score = score_vbios(dev, data, method->rw); + if (method->score == testscore) + return true; + method++; + } + + while (--testscore > 0) { + method = methods; + while (method->loadbios) { + if (method->score == testscore) { + NV_TRACE(dev, "Using BIOS image from %s\n", + method->desc); + method->loadbios(dev, data); + return true; + } + method++; + } + } + + NV_ERROR(dev, "No valid BIOS image found\n"); + return false; +} + +struct init_tbl_entry { + char *name; + uint8_t id; + int length; + int length_offset; + int length_multiplier; + bool (*handler)(struct nvbios *, uint16_t, struct init_exec *); +}; + +struct bit_entry { + uint8_t id[2]; + uint16_t length; + uint16_t offset; +}; + +static int parse_init_table(struct nvbios *, unsigned int, struct init_exec *); + +#define MACRO_INDEX_SIZE 2 +#define MACRO_SIZE 8 +#define CONDITION_SIZE 12 +#define IO_FLAG_CONDITION_SIZE 9 +#define IO_CONDITION_SIZE 5 +#define MEM_INIT_SIZE 66 + +static void still_alive(void) +{ +#if 0 + sync(); + msleep(2); +#endif +} + +static uint32_t +munge_reg(struct nvbios *bios, uint32_t reg) +{ + struct drm_nouveau_private *dev_priv = bios->dev->dev_private; + struct dcb_entry *dcbent = bios->display.output; + + if (dev_priv->card_type < NV_50) + return reg; + + if (reg & 0x40000000) { + BUG_ON(!dcbent); + + reg += (ffs(dcbent->or) - 1) * 0x800; + if ((reg & 0x20000000) && !(dcbent->sorconf.link & 1)) + reg += 0x00000080; + } + + reg &= ~0x60000000; + return reg; +} + +static int +valid_reg(struct nvbios *bios, uint32_t reg) +{ + struct drm_nouveau_private *dev_priv = bios->dev->dev_private; + struct drm_device *dev = bios->dev; + + /* C51 has misaligned regs on purpose. Marvellous */ + if (reg & 0x2 || (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51)) { + NV_ERROR(dev, "========== misaligned reg 0x%08X ==========\n", + reg); + return 0; + } + /* + * Warn on C51 regs that have not been verified accessible in + * mmiotracing + */ + if (reg & 0x1 && dev_priv->VBIOS.pub.chip_version == 0x51 && + reg != 0x130d && reg != 0x1311 && reg != 0x60081d) + NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n", + reg); + + /* Trust the init scripts on G80 */ + if (dev_priv->card_type >= NV_50) + return 1; + + #define WITHIN(x, y, z) ((x >= y) && (x < y + z)) + if (WITHIN(reg, NV_PMC_OFFSET, NV_PMC_SIZE)) + return 1; + if (WITHIN(reg, NV_PBUS_OFFSET, NV_PBUS_SIZE)) + return 1; + if (WITHIN(reg, NV_PFIFO_OFFSET, NV_PFIFO_SIZE)) + return 1; + if (dev_priv->VBIOS.pub.chip_version >= 0x30 && + (WITHIN(reg, 0x4000, 0x600) || reg == 0x00004600)) + return 1; + if (dev_priv->VBIOS.pub.chip_version >= 0x40 && + WITHIN(reg, 0xc000, 0x48)) + return 1; + if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0000d204) + return 1; + if (dev_priv->VBIOS.pub.chip_version >= 0x40) { + if (reg == 0x00011014 || reg == 0x00020328) + return 1; + if (WITHIN(reg, 0x88000, NV_PBUS_SIZE)) /* new PBUS */ + return 1; + } + if (WITHIN(reg, NV_PFB_OFFSET, NV_PFB_SIZE)) + return 1; + if (WITHIN(reg, NV_PEXTDEV_OFFSET, NV_PEXTDEV_SIZE)) + return 1; + if (WITHIN(reg, NV_PCRTC0_OFFSET, NV_PCRTC0_SIZE * 2)) + return 1; + if (WITHIN(reg, NV_PRAMDAC0_OFFSET, NV_PRAMDAC0_SIZE * 2)) + return 1; + if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0070fff0) + return 1; + if (dev_priv->VBIOS.pub.chip_version == 0x51 && + WITHIN(reg, NV_PRAMIN_OFFSET, NV_PRAMIN_SIZE)) + return 1; + #undef WITHIN + + NV_ERROR(dev, "========== unknown reg 0x%08X ==========\n", reg); + + return 0; +} + +static bool +valid_idx_port(struct nvbios *bios, uint16_t port) +{ + struct drm_nouveau_private *dev_priv = bios->dev->dev_private; + struct drm_device *dev = bios->dev; + + /* + * If adding more ports here, the read/write functions below will need + * updating so that the correct mmio range (PRMCIO, PRMDIO, PRMVIO) is + * used for the port in question + */ + if (dev_priv->card_type < NV_50) { + if (port == NV_CIO_CRX__COLOR) + return true; + if (port == NV_VIO_SRX) + return true; + } else { + if (port == NV_CIO_CRX__COLOR) + return true; + } + + NV_ERROR(dev, "========== unknown indexed io port 0x%04X ==========\n", + port); + + return false; +} + +static bool +valid_port(struct nvbios *bios, uint16_t port) +{ + struct drm_device *dev = bios->dev; + + /* + * If adding more ports here, the read/write functions below will need + * updating so that the correct mmio range (PRMCIO, PRMDIO, PRMVIO) is + * used for the port in question + */ + if (port == NV_VIO_VSE2) + return true; + + NV_ERROR(dev, "========== unknown io port 0x%04X ==========\n", port); + + return false; +} + +static uint32_t +bios_rd32(struct nvbios *bios, uint32_t reg) +{ + uint32_t data; + + reg = munge_reg(bios, reg); + if (!valid_reg(bios, reg)) + return 0; + + /* + * C51 sometimes uses regs with bit0 set in the address. For these + * cases there should exist a translation in a BIOS table to an IO + * port address which the BIOS uses for accessing the reg + * + * These only seem to appear for the power control regs to a flat panel, + * and the GPIO regs at 0x60081*. In C51 mmio traces the normal regs + * for 0x1308 and 0x1310 are used - hence the mask below. An S3 + * suspend-resume mmio trace from a C51 will be required to see if this + * is true for the power microcode in 0x14.., or whether the direct IO + * port access method is needed + */ + if (reg & 0x1) + reg &= ~0x1; + + data = nv_rd32(bios->dev, reg); + + BIOSLOG(bios, " Read: Reg: 0x%08X, Data: 0x%08X\n", reg, data); + + return data; +} + +static void +bios_wr32(struct nvbios *bios, uint32_t reg, uint32_t data) +{ + struct drm_nouveau_private *dev_priv = bios->dev->dev_private; + + reg = munge_reg(bios, reg); + if (!valid_reg(bios, reg)) + return; + + /* see note in bios_rd32 */ + if (reg & 0x1) + reg &= 0xfffffffe; + + LOG_OLD_VALUE(bios_rd32(bios, reg)); + BIOSLOG(bios, " Write: Reg: 0x%08X, Data: 0x%08X\n", reg, data); + + if (dev_priv->VBIOS.execute) { + still_alive(); + nv_wr32(bios->dev, reg, data); + } +} + +static uint8_t +bios_idxprt_rd(struct nvbios *bios, uint16_t port, uint8_t index) +{ + struct drm_nouveau_private *dev_priv = bios->dev->dev_private; + struct drm_device *dev = bios->dev; + uint8_t data; + + if (!valid_idx_port(bios, port)) + return 0; + + if (dev_priv->card_type < NV_50) { + if (port == NV_VIO_SRX) + data = NVReadVgaSeq(dev, bios->state.crtchead, index); + else /* assume NV_CIO_CRX__COLOR */ + data = NVReadVgaCrtc(dev, bios->state.crtchead, index); + } else { + uint32_t data32; + + data32 = bios_rd32(bios, NV50_PDISPLAY_VGACRTC(index & ~3)); + data = (data32 >> ((index & 3) << 3)) & 0xff; + } + + BIOSLOG(bios, " Indexed IO read: Port: 0x%04X, Index: 0x%02X, " + "Head: 0x%02X, Data: 0x%02X\n", + port, index, bios->state.crtchead, data); + return data; +} + +static void +bios_idxprt_wr(struct nvbios *bios, uint16_t port, uint8_t index, uint8_t data) +{ + struct drm_nouveau_private *dev_priv = bios->dev->dev_private; + struct drm_device *dev = bios->dev; + + if (!valid_idx_port(bios, port)) + return; + + /* + * The current head is maintained in the nvbios member state.crtchead. + * We trap changes to CR44 and update the head variable and hence the + * register set written. + * As CR44 only exists on CRTC0, we update crtchead to head0 in advance + * of the write, and to head1 after the write + */ + if (port == NV_CIO_CRX__COLOR && index == NV_CIO_CRE_44 && + data != NV_CIO_CRE_44_HEADB) + bios->state.crtchead = 0; + + LOG_OLD_VALUE(bios_idxprt_rd(bios, port, index)); + BIOSLOG(bios, " Indexed IO write: Port: 0x%04X, Index: 0x%02X, " + "Head: 0x%02X, Data: 0x%02X\n", + port, index, bios->state.crtchead, data); + + if (bios->execute && dev_priv->card_type < NV_50) { + still_alive(); + if (port == NV_VIO_SRX) + NVWriteVgaSeq(dev, bios->state.crtchead, index, data); + else /* assume NV_CIO_CRX__COLOR */ + NVWriteVgaCrtc(dev, bios->state.crtchead, index, data); + } else + if (bios->execute) { + uint32_t data32, shift = (index & 3) << 3; + + still_alive(); + + data32 = bios_rd32(bios, NV50_PDISPLAY_VGACRTC(index & ~3)); + data32 &= ~(0xff << shift); + data32 |= (data << shift); + bios_wr32(bios, NV50_PDISPLAY_VGACRTC(index & ~3), data32); + } + + if (port == NV_CIO_CRX__COLOR && + index == NV_CIO_CRE_44 && data == NV_CIO_CRE_44_HEADB) + bios->state.crtchead = 1; +} + +static uint8_t +bios_port_rd(struct nvbios *bios, uint16_t port) +{ + uint8_t data, head = bios->state.crtchead; + + if (!valid_port(bios, port)) + return 0; + + data = NVReadPRMVIO(bios->dev, head, NV_PRMVIO0_OFFSET + port); + + BIOSLOG(bios, " IO read: Port: 0x%04X, Head: 0x%02X, Data: 0x%02X\n", + port, head, data); + + return data; +} + +static void +bios_port_wr(struct nvbios *bios, uint16_t port, uint8_t data) +{ + int head = bios->state.crtchead; + + if (!valid_port(bios, port)) + return; + + LOG_OLD_VALUE(bios_port_rd(bios, port)); + BIOSLOG(bios, " IO write: Port: 0x%04X, Head: 0x%02X, Data: 0x%02X\n", + port, head, data); + + if (!bios->execute) + return; + + still_alive(); + NVWritePRMVIO(bios->dev, head, NV_PRMVIO0_OFFSET + port, data); +} + +static bool +io_flag_condition_met(struct nvbios *bios, uint16_t offset, uint8_t cond) +{ + /* + * The IO flag condition entry has 2 bytes for the CRTC port; 1 byte + * for the CRTC index; 1 byte for the mask to apply to the value + * retrieved from the CRTC; 1 byte for the shift right to apply to the + * masked CRTC value; 2 bytes for the offset to the flag array, to + * which the shifted value is added; 1 byte for the mask applied to the + * value read from the flag array; and 1 byte for the value to compare + * against the masked byte from the flag table. + */ + + uint16_t condptr = bios->io_flag_condition_tbl_ptr + cond * IO_FLAG_CONDITION_SIZE; + uint16_t crtcport = ROM16(bios->data[condptr]); + uint8_t crtcindex = bios->data[condptr + 2]; + uint8_t mask = bios->data[condptr + 3]; + uint8_t shift = bios->data[condptr + 4]; + uint16_t flagarray = ROM16(bios->data[condptr + 5]); + uint8_t flagarraymask = bios->data[condptr + 7]; + uint8_t cmpval = bios->data[condptr + 8]; + uint8_t data; + + BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, " + "Shift: 0x%02X, FlagArray: 0x%04X, FAMask: 0x%02X, " + "Cmpval: 0x%02X\n", + offset, crtcport, crtcindex, mask, shift, flagarray, flagarraymask, cmpval); + + data = bios_idxprt_rd(bios, crtcport, crtcindex); + + data = bios->data[flagarray + ((data & mask) >> shift)]; + data &= flagarraymask; + + BIOSLOG(bios, "0x%04X: Checking if 0x%02X equals 0x%02X\n", + offset, data, cmpval); + + return (data == cmpval); +} + +static bool +bios_condition_met(struct nvbios *bios, uint16_t offset, uint8_t cond) +{ + /* + * The condition table entry has 4 bytes for the address of the + * register to check, 4 bytes for a mask to apply to the register and + * 4 for a test comparison value + */ + + uint16_t condptr = bios->condition_tbl_ptr + cond * CONDITION_SIZE; + uint32_t reg = ROM32(bios->data[condptr]); + uint32_t mask = ROM32(bios->data[condptr + 4]); + uint32_t cmpval = ROM32(bios->data[condptr + 8]); + uint32_t data; + + BIOSLOG(bios, "0x%04X: Cond: 0x%02X, Reg: 0x%08X, Mask: 0x%08X\n", + offset, cond, reg, mask); + + data = bios_rd32(bios, reg) & mask; + + BIOSLOG(bios, "0x%04X: Checking if 0x%08X equals 0x%08X\n", + offset, data, cmpval); + + return (data == cmpval); +} + +static bool +io_condition_met(struct nvbios *bios, uint16_t offset, uint8_t cond) +{ + /* + * The IO condition entry has 2 bytes for the IO port address; 1 byte + * for the index to write to io_port; 1 byte for the mask to apply to + * the byte read from io_port+1; and 1 byte for the value to compare + * against the masked byte. + */ + + uint16_t condptr = bios->io_condition_tbl_ptr + cond * IO_CONDITION_SIZE; + uint16_t io_port = ROM16(bios->data[condptr]); + uint8_t port_index = bios->data[condptr + 2]; + uint8_t mask = bios->data[condptr + 3]; + uint8_t cmpval = bios->data[condptr + 4]; + + uint8_t data = bios_idxprt_rd(bios, io_port, port_index) & mask; + + BIOSLOG(bios, "0x%04X: Checking if 0x%02X equals 0x%02X\n", + offset, data, cmpval); + + return (data == cmpval); +} + +static int +nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t reg0 = nv_rd32(dev, reg + 0); + uint32_t reg1 = nv_rd32(dev, reg + 4); + struct nouveau_pll_vals pll; + struct pll_lims pll_limits; + int ret; + + ret = get_pll_limits(dev, reg, &pll_limits); + if (ret) + return ret; + + clk = nouveau_calc_pll_mnp(dev, &pll_limits, clk, &pll); + if (!clk) + return -ERANGE; + + reg0 = (reg0 & 0xfff8ffff) | (pll.log2P << 16); + reg1 = (reg1 & 0xffff0000) | (pll.N1 << 8) | pll.M1; + + if (dev_priv->VBIOS.execute) { + still_alive(); + nv_wr32(dev, reg + 4, reg1); + nv_wr32(dev, reg + 0, reg0); + } + + return 0; +} + +static int +setPLL(struct nvbios *bios, uint32_t reg, uint32_t clk) +{ + struct drm_device *dev = bios->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + /* clk in kHz */ + struct pll_lims pll_lim; + struct nouveau_pll_vals pllvals; + int ret; + + if (dev_priv->card_type >= NV_50) + return nv50_pll_set(dev, reg, clk); + + /* high regs (such as in the mac g5 table) are not -= 4 */ + ret = get_pll_limits(dev, reg > 0x405c ? reg : reg - 4, &pll_lim); + if (ret) + return ret; + + clk = nouveau_calc_pll_mnp(dev, &pll_lim, clk, &pllvals); + if (!clk) + return -ERANGE; + + if (bios->execute) { + still_alive(); + nouveau_hw_setpll(dev, reg, &pllvals); + } + + return 0; +} + +static int dcb_entry_idx_from_crtchead(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + + /* + * For the results of this function to be correct, CR44 must have been + * set (using bios_idxprt_wr to set crtchead), CR58 set for CR57 = 0, + * and the DCB table parsed, before the script calling the function is + * run. run_digital_op_script is example of how to do such setup + */ + + uint8_t dcb_entry = NVReadVgaCrtc5758(dev, bios->state.crtchead, 0); + + if (dcb_entry > bios->bdcb.dcb.entries) { + NV_ERROR(dev, "CR58 doesn't have a valid DCB entry currently " + "(%02X)\n", dcb_entry); + dcb_entry = 0x7f; /* unused / invalid marker */ + } + + return dcb_entry; +} + +static struct nouveau_i2c_chan * +init_i2c_device_find(struct drm_device *dev, int i2c_index) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct bios_parsed_dcb *bdcb = &dev_priv->VBIOS.bdcb; + + if (i2c_index == 0xff) { + /* note: dcb_entry_idx_from_crtchead needs pre-script set-up */ + int idx = dcb_entry_idx_from_crtchead(dev), shift = 0; + int default_indices = bdcb->i2c_default_indices; + + if (idx != 0x7f && bdcb->dcb.entry[idx].i2c_upper_default) + shift = 4; + + i2c_index = (default_indices >> shift) & 0xf; + } + if (i2c_index == 0x80) /* g80+ */ + i2c_index = bdcb->i2c_default_indices & 0xf; + + return nouveau_i2c_find(dev, i2c_index); +} + +static uint32_t get_tmds_index_reg(struct drm_device *dev, uint8_t mlv) +{ + /* + * For mlv < 0x80, it is an index into a table of TMDS base addresses. + * For mlv == 0x80 use the "or" value of the dcb_entry indexed by + * CR58 for CR57 = 0 to index a table of offsets to the basic + * 0x6808b0 address. + * For mlv == 0x81 use the "or" value of the dcb_entry indexed by + * CR58 for CR57 = 0 to index a table of offsets to the basic + * 0x6808b0 address, and then flip the offset by 8. + */ + + struct drm_nouveau_private *dev_priv = dev->dev_private; + const int pramdac_offset[13] = { + 0, 0, 0x8, 0, 0x2000, 0, 0, 0, 0x2008, 0, 0, 0, 0x2000 }; + const uint32_t pramdac_table[4] = { + 0x6808b0, 0x6808b8, 0x6828b0, 0x6828b8 }; + + if (mlv >= 0x80) { + int dcb_entry, dacoffset; + + /* note: dcb_entry_idx_from_crtchead needs pre-script set-up */ + dcb_entry = dcb_entry_idx_from_crtchead(dev); + if (dcb_entry == 0x7f) + return 0; + dacoffset = pramdac_offset[ + dev_priv->VBIOS.bdcb.dcb.entry[dcb_entry].or]; + if (mlv == 0x81) + dacoffset ^= 8; + return 0x6808b0 + dacoffset; + } else { + if (mlv > ARRAY_SIZE(pramdac_table)) { + NV_ERROR(dev, "Magic Lookup Value too big (%02X)\n", + mlv); + return 0; + } + return pramdac_table[mlv]; + } +} + +static bool +init_io_restrict_prog(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_IO_RESTRICT_PROG opcode: 0x32 ('2') + * + * offset (8 bit): opcode + * offset + 1 (16 bit): CRTC port + * offset + 3 (8 bit): CRTC index + * offset + 4 (8 bit): mask + * offset + 5 (8 bit): shift + * offset + 6 (8 bit): count + * offset + 7 (32 bit): register + * offset + 11 (32 bit): configuration 1 + * ... + * + * Starting at offset + 11 there are "count" 32 bit values. + * To find out which value to use read index "CRTC index" on "CRTC + * port", AND this value with "mask" and then bit shift right "shift" + * bits. Read the appropriate value using this index and write to + * "register" + */ + + uint16_t crtcport = ROM16(bios->data[offset + 1]); + uint8_t crtcindex = bios->data[offset + 3]; + uint8_t mask = bios->data[offset + 4]; + uint8_t shift = bios->data[offset + 5]; + uint8_t count = bios->data[offset + 6]; + uint32_t reg = ROM32(bios->data[offset + 7]); + uint8_t config; + uint32_t configval; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, " + "Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n", + offset, crtcport, crtcindex, mask, shift, count, reg); + + config = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) >> shift; + if (config > count) { + NV_ERROR(bios->dev, + "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", + offset, config, count); + return false; + } + + configval = ROM32(bios->data[offset + 11 + config * 4]); + + BIOSLOG(bios, "0x%04X: Writing config %02X\n", offset, config); + + bios_wr32(bios, reg, configval); + + return true; +} + +static bool +init_repeat(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_REPEAT opcode: 0x33 ('3') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): count + * + * Execute script following this opcode up to INIT_REPEAT_END + * "count" times + */ + + uint8_t count = bios->data[offset + 1]; + uint8_t i; + + /* no iexec->execute check by design */ + + BIOSLOG(bios, "0x%04X: Repeating following segment %d times\n", + offset, count); + + iexec->repeat = true; + + /* + * count - 1, as the script block will execute once when we leave this + * opcode -- this is compatible with bios behaviour as: + * a) the block is always executed at least once, even if count == 0 + * b) the bios interpreter skips to the op following INIT_END_REPEAT, + * while we don't + */ + for (i = 0; i < count - 1; i++) + parse_init_table(bios, offset + 2, iexec); + + iexec->repeat = false; + + return true; +} + +static bool +init_io_restrict_pll(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_IO_RESTRICT_PLL opcode: 0x34 ('4') + * + * offset (8 bit): opcode + * offset + 1 (16 bit): CRTC port + * offset + 3 (8 bit): CRTC index + * offset + 4 (8 bit): mask + * offset + 5 (8 bit): shift + * offset + 6 (8 bit): IO flag condition index + * offset + 7 (8 bit): count + * offset + 8 (32 bit): register + * offset + 12 (16 bit): frequency 1 + * ... + * + * Starting at offset + 12 there are "count" 16 bit frequencies (10kHz). + * Set PLL register "register" to coefficients for frequency n, + * selected by reading index "CRTC index" of "CRTC port" ANDed with + * "mask" and shifted right by "shift". + * + * If "IO flag condition index" > 0, and condition met, double + * frequency before setting it. + */ + + uint16_t crtcport = ROM16(bios->data[offset + 1]); + uint8_t crtcindex = bios->data[offset + 3]; + uint8_t mask = bios->data[offset + 4]; + uint8_t shift = bios->data[offset + 5]; + int8_t io_flag_condition_idx = bios->data[offset + 6]; + uint8_t count = bios->data[offset + 7]; + uint32_t reg = ROM32(bios->data[offset + 8]); + uint8_t config; + uint16_t freq; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, " + "Shift: 0x%02X, IO Flag Condition: 0x%02X, " + "Count: 0x%02X, Reg: 0x%08X\n", + offset, crtcport, crtcindex, mask, shift, + io_flag_condition_idx, count, reg); + + config = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) >> shift; + if (config > count) { + NV_ERROR(bios->dev, + "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", + offset, config, count); + return false; + } + + freq = ROM16(bios->data[offset + 12 + config * 2]); + + if (io_flag_condition_idx > 0) { + if (io_flag_condition_met(bios, offset, io_flag_condition_idx)) { + BIOSLOG(bios, "0x%04X: Condition fulfilled -- " + "frequency doubled\n", offset); + freq *= 2; + } else + BIOSLOG(bios, "0x%04X: Condition not fulfilled -- " + "frequency unchanged\n", offset); + } + + BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %d0kHz\n", + offset, reg, config, freq); + + setPLL(bios, reg, freq * 10); + + return true; +} + +static bool +init_end_repeat(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_END_REPEAT opcode: 0x36 ('6') + * + * offset (8 bit): opcode + * + * Marks the end of the block for INIT_REPEAT to repeat + */ + + /* no iexec->execute check by design */ + + /* + * iexec->repeat flag necessary to go past INIT_END_REPEAT opcode when + * we're not in repeat mode + */ + if (iexec->repeat) + return false; + + return true; +} + +static bool +init_copy(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_COPY opcode: 0x37 ('7') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): register + * offset + 5 (8 bit): shift + * offset + 6 (8 bit): srcmask + * offset + 7 (16 bit): CRTC port + * offset + 9 (8 bit): CRTC index + * offset + 10 (8 bit): mask + * + * Read index "CRTC index" on "CRTC port", AND with "mask", OR with + * (REGVAL("register") >> "shift" & "srcmask") and write-back to CRTC + * port + */ + + uint32_t reg = ROM32(bios->data[offset + 1]); + uint8_t shift = bios->data[offset + 5]; + uint8_t srcmask = bios->data[offset + 6]; + uint16_t crtcport = ROM16(bios->data[offset + 7]); + uint8_t crtcindex = bios->data[offset + 9]; + uint8_t mask = bios->data[offset + 10]; + uint32_t data; + uint8_t crtcdata; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%02X, " + "Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X\n", + offset, reg, shift, srcmask, crtcport, crtcindex, mask); + + data = bios_rd32(bios, reg); + + if (shift < 0x80) + data >>= shift; + else + data <<= (0x100 - shift); + + data &= srcmask; + + crtcdata = bios_idxprt_rd(bios, crtcport, crtcindex) & mask; + crtcdata |= (uint8_t)data; + bios_idxprt_wr(bios, crtcport, crtcindex, crtcdata); + + return true; +} + +static bool +init_not(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_NOT opcode: 0x38 ('8') + * + * offset (8 bit): opcode + * + * Invert the current execute / no-execute condition (i.e. "else") + */ + if (iexec->execute) + BIOSLOG(bios, "0x%04X: ------ Skipping following commands ------\n", offset); + else + BIOSLOG(bios, "0x%04X: ------ Executing following commands ------\n", offset); + + iexec->execute = !iexec->execute; + return true; +} + +static bool +init_io_flag_condition(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_IO_FLAG_CONDITION opcode: 0x39 ('9') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): condition number + * + * Check condition "condition number" in the IO flag condition table. + * If condition not met skip subsequent opcodes until condition is + * inverted (INIT_NOT), or we hit INIT_RESUME + */ + + uint8_t cond = bios->data[offset + 1]; + + if (!iexec->execute) + return true; + + if (io_flag_condition_met(bios, offset, cond)) + BIOSLOG(bios, "0x%04X: Condition fulfilled -- continuing to execute\n", offset); + else { + BIOSLOG(bios, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset); + iexec->execute = false; + } + + return true; +} + +static bool +init_idx_addr_latched(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_INDEX_ADDRESS_LATCHED opcode: 0x49 ('I') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): control register + * offset + 5 (32 bit): data register + * offset + 9 (32 bit): mask + * offset + 13 (32 bit): data + * offset + 17 (8 bit): count + * offset + 18 (8 bit): address 1 + * offset + 19 (8 bit): data 1 + * ... + * + * For each of "count" address and data pairs, write "data n" to + * "data register", read the current value of "control register", + * and write it back once ANDed with "mask", ORed with "data", + * and ORed with "address n" + */ + + uint32_t controlreg = ROM32(bios->data[offset + 1]); + uint32_t datareg = ROM32(bios->data[offset + 5]); + uint32_t mask = ROM32(bios->data[offset + 9]); + uint32_t data = ROM32(bios->data[offset + 13]); + uint8_t count = bios->data[offset + 17]; + uint32_t value; + int i; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: ControlReg: 0x%08X, DataReg: 0x%08X, " + "Mask: 0x%08X, Data: 0x%08X, Count: 0x%02X\n", + offset, controlreg, datareg, mask, data, count); + + for (i = 0; i < count; i++) { + uint8_t instaddress = bios->data[offset + 18 + i * 2]; + uint8_t instdata = bios->data[offset + 19 + i * 2]; + + BIOSLOG(bios, "0x%04X: Address: 0x%02X, Data: 0x%02X\n", + offset, instaddress, instdata); + + bios_wr32(bios, datareg, instdata); + value = bios_rd32(bios, controlreg) & mask; + value |= data; + value |= instaddress; + bios_wr32(bios, controlreg, value); + } + + return true; +} + +static bool +init_io_restrict_pll2(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_IO_RESTRICT_PLL2 opcode: 0x4A ('J') + * + * offset (8 bit): opcode + * offset + 1 (16 bit): CRTC port + * offset + 3 (8 bit): CRTC index + * offset + 4 (8 bit): mask + * offset + 5 (8 bit): shift + * offset + 6 (8 bit): count + * offset + 7 (32 bit): register + * offset + 11 (32 bit): frequency 1 + * ... + * + * Starting at offset + 11 there are "count" 32 bit frequencies (kHz). + * Set PLL register "register" to coefficients for frequency n, + * selected by reading index "CRTC index" of "CRTC port" ANDed with + * "mask" and shifted right by "shift". + */ + + uint16_t crtcport = ROM16(bios->data[offset + 1]); + uint8_t crtcindex = bios->data[offset + 3]; + uint8_t mask = bios->data[offset + 4]; + uint8_t shift = bios->data[offset + 5]; + uint8_t count = bios->data[offset + 6]; + uint32_t reg = ROM32(bios->data[offset + 7]); + uint8_t config; + uint32_t freq; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, " + "Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n", + offset, crtcport, crtcindex, mask, shift, count, reg); + + if (!reg) + return true; + + config = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) >> shift; + if (config > count) { + NV_ERROR(bios->dev, + "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", + offset, config, count); + return false; + } + + freq = ROM32(bios->data[offset + 11 + config * 4]); + + BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %dkHz\n", + offset, reg, config, freq); + + setPLL(bios, reg, freq); + + return true; +} + +static bool +init_pll2(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_PLL2 opcode: 0x4B ('K') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): register + * offset + 5 (32 bit): freq + * + * Set PLL register "register" to coefficients for frequency "freq" + */ + + uint32_t reg = ROM32(bios->data[offset + 1]); + uint32_t freq = ROM32(bios->data[offset + 5]); + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Reg: 0x%04X, Freq: %dkHz\n", + offset, reg, freq); + + setPLL(bios, reg, freq); + return true; +} + +static bool +init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_I2C_BYTE opcode: 0x4C ('L') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): DCB I2C table entry index + * offset + 2 (8 bit): I2C slave address + * offset + 3 (8 bit): count + * offset + 4 (8 bit): I2C register 1 + * offset + 5 (8 bit): mask 1 + * offset + 6 (8 bit): data 1 + * ... + * + * For each of "count" registers given by "I2C register n" on the device + * addressed by "I2C slave address" on the I2C bus given by + * "DCB I2C table entry index", read the register, AND the result with + * "mask n" and OR it with "data n" before writing it back to the device + */ + + uint8_t i2c_index = bios->data[offset + 1]; + uint8_t i2c_address = bios->data[offset + 2]; + uint8_t count = bios->data[offset + 3]; + struct nouveau_i2c_chan *chan; + struct i2c_msg msg; + int i; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, " + "Count: 0x%02X\n", + offset, i2c_index, i2c_address, count); + + chan = init_i2c_device_find(bios->dev, i2c_index); + if (!chan) + return false; + + for (i = 0; i < count; i++) { + uint8_t i2c_reg = bios->data[offset + 4 + i * 3]; + uint8_t mask = bios->data[offset + 5 + i * 3]; + uint8_t data = bios->data[offset + 6 + i * 3]; + uint8_t value; + + msg.addr = i2c_address; + msg.flags = I2C_M_RD; + msg.len = 1; + msg.buf = &value; + if (i2c_transfer(&chan->adapter, &msg, 1) != 1) + return false; + + BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, " + "Mask: 0x%02X, Data: 0x%02X\n", + offset, i2c_reg, value, mask, data); + + value = (value & mask) | data; + + if (bios->execute) { + msg.addr = i2c_address; + msg.flags = 0; + msg.len = 1; + msg.buf = &value; + if (i2c_transfer(&chan->adapter, &msg, 1) != 1) + return false; + } + } + + return true; +} + +static bool +init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_ZM_I2C_BYTE opcode: 0x4D ('M') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): DCB I2C table entry index + * offset + 2 (8 bit): I2C slave address + * offset + 3 (8 bit): count + * offset + 4 (8 bit): I2C register 1 + * offset + 5 (8 bit): data 1 + * ... + * + * For each of "count" registers given by "I2C register n" on the device + * addressed by "I2C slave address" on the I2C bus given by + * "DCB I2C table entry index", set the register to "data n" + */ + + uint8_t i2c_index = bios->data[offset + 1]; + uint8_t i2c_address = bios->data[offset + 2]; + uint8_t count = bios->data[offset + 3]; + struct nouveau_i2c_chan *chan; + struct i2c_msg msg; + int i; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, " + "Count: 0x%02X\n", + offset, i2c_index, i2c_address, count); + + chan = init_i2c_device_find(bios->dev, i2c_index); + if (!chan) + return false; + + for (i = 0; i < count; i++) { + uint8_t i2c_reg = bios->data[offset + 4 + i * 2]; + uint8_t data = bios->data[offset + 5 + i * 2]; + + BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Data: 0x%02X\n", + offset, i2c_reg, data); + + if (bios->execute) { + msg.addr = i2c_address; + msg.flags = 0; + msg.len = 1; + msg.buf = &data; + if (i2c_transfer(&chan->adapter, &msg, 1) != 1) + return false; + } + } + + return true; +} + +static bool +init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_ZM_I2C opcode: 0x4E ('N') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): DCB I2C table entry index + * offset + 2 (8 bit): I2C slave address + * offset + 3 (8 bit): count + * offset + 4 (8 bit): data 1 + * ... + * + * Send "count" bytes ("data n") to the device addressed by "I2C slave + * address" on the I2C bus given by "DCB I2C table entry index" + */ + + uint8_t i2c_index = bios->data[offset + 1]; + uint8_t i2c_address = bios->data[offset + 2]; + uint8_t count = bios->data[offset + 3]; + struct nouveau_i2c_chan *chan; + struct i2c_msg msg; + uint8_t data[256]; + int i; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, " + "Count: 0x%02X\n", + offset, i2c_index, i2c_address, count); + + chan = init_i2c_device_find(bios->dev, i2c_index); + if (!chan) + return false; + + for (i = 0; i < count; i++) { + data[i] = bios->data[offset + 4 + i]; + + BIOSLOG(bios, "0x%04X: Data: 0x%02X\n", offset, data[i]); + } + + if (bios->execute) { + msg.addr = i2c_address; + msg.flags = 0; + msg.len = count; + msg.buf = data; + if (i2c_transfer(&chan->adapter, &msg, 1) != 1) + return false; + } + + return true; +} + +static bool +init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_TMDS opcode: 0x4F ('O') (non-canon name) + * + * offset (8 bit): opcode + * offset + 1 (8 bit): magic lookup value + * offset + 2 (8 bit): TMDS address + * offset + 3 (8 bit): mask + * offset + 4 (8 bit): data + * + * Read the data reg for TMDS address "TMDS address", AND it with mask + * and OR it with data, then write it back + * "magic lookup value" determines which TMDS base address register is + * used -- see get_tmds_index_reg() + */ + + uint8_t mlv = bios->data[offset + 1]; + uint32_t tmdsaddr = bios->data[offset + 2]; + uint8_t mask = bios->data[offset + 3]; + uint8_t data = bios->data[offset + 4]; + uint32_t reg, value; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: MagicLookupValue: 0x%02X, TMDSAddr: 0x%02X, " + "Mask: 0x%02X, Data: 0x%02X\n", + offset, mlv, tmdsaddr, mask, data); + + reg = get_tmds_index_reg(bios->dev, mlv); + if (!reg) + return false; + + bios_wr32(bios, reg, + tmdsaddr | NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE); + value = (bios_rd32(bios, reg + 4) & mask) | data; + bios_wr32(bios, reg + 4, value); + bios_wr32(bios, reg, tmdsaddr); + + return true; +} + +static bool +init_zm_tmds_group(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_ZM_TMDS_GROUP opcode: 0x50 ('P') (non-canon name) + * + * offset (8 bit): opcode + * offset + 1 (8 bit): magic lookup value + * offset + 2 (8 bit): count + * offset + 3 (8 bit): addr 1 + * offset + 4 (8 bit): data 1 + * ... + * + * For each of "count" TMDS address and data pairs write "data n" to + * "addr n". "magic lookup value" determines which TMDS base address + * register is used -- see get_tmds_index_reg() + */ + + uint8_t mlv = bios->data[offset + 1]; + uint8_t count = bios->data[offset + 2]; + uint32_t reg; + int i; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: MagicLookupValue: 0x%02X, Count: 0x%02X\n", + offset, mlv, count); + + reg = get_tmds_index_reg(bios->dev, mlv); + if (!reg) + return false; + + for (i = 0; i < count; i++) { + uint8_t tmdsaddr = bios->data[offset + 3 + i * 2]; + uint8_t tmdsdata = bios->data[offset + 4 + i * 2]; + + bios_wr32(bios, reg + 4, tmdsdata); + bios_wr32(bios, reg, tmdsaddr); + } + + return true; +} + +static bool +init_cr_idx_adr_latch(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_CR_INDEX_ADDRESS_LATCHED opcode: 0x51 ('Q') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): CRTC index1 + * offset + 2 (8 bit): CRTC index2 + * offset + 3 (8 bit): baseaddr + * offset + 4 (8 bit): count + * offset + 5 (8 bit): data 1 + * ... + * + * For each of "count" address and data pairs, write "baseaddr + n" to + * "CRTC index1" and "data n" to "CRTC index2" + * Once complete, restore initial value read from "CRTC index1" + */ + uint8_t crtcindex1 = bios->data[offset + 1]; + uint8_t crtcindex2 = bios->data[offset + 2]; + uint8_t baseaddr = bios->data[offset + 3]; + uint8_t count = bios->data[offset + 4]; + uint8_t oldaddr, data; + int i; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Index1: 0x%02X, Index2: 0x%02X, " + "BaseAddr: 0x%02X, Count: 0x%02X\n", + offset, crtcindex1, crtcindex2, baseaddr, count); + + oldaddr = bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, crtcindex1); + + for (i = 0; i < count; i++) { + bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex1, + baseaddr + i); + data = bios->data[offset + 5 + i]; + bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex2, data); + } + + bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex1, oldaddr); + + return true; +} + +static bool +init_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_CR opcode: 0x52 ('R') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): CRTC index + * offset + 2 (8 bit): mask + * offset + 3 (8 bit): data + * + * Assign the value of at "CRTC index" ANDed with mask and ORed with + * data back to "CRTC index" + */ + + uint8_t crtcindex = bios->data[offset + 1]; + uint8_t mask = bios->data[offset + 2]; + uint8_t data = bios->data[offset + 3]; + uint8_t value; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Index: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n", + offset, crtcindex, mask, data); + + value = bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, crtcindex) & mask; + value |= data; + bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex, value); + + return true; +} + +static bool +init_zm_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_ZM_CR opcode: 0x53 ('S') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): CRTC index + * offset + 2 (8 bit): value + * + * Assign "value" to CRTC register with index "CRTC index". + */ + + uint8_t crtcindex = ROM32(bios->data[offset + 1]); + uint8_t data = bios->data[offset + 2]; + + if (!iexec->execute) + return true; + + bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex, data); + + return true; +} + +static bool +init_zm_cr_group(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_ZM_CR_GROUP opcode: 0x54 ('T') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): count + * offset + 2 (8 bit): CRTC index 1 + * offset + 3 (8 bit): value 1 + * ... + * + * For "count", assign "value n" to CRTC register with index + * "CRTC index n". + */ + + uint8_t count = bios->data[offset + 1]; + int i; + + if (!iexec->execute) + return true; + + for (i = 0; i < count; i++) + init_zm_cr(bios, offset + 2 + 2 * i - 1, iexec); + + return true; +} + +static bool +init_condition_time(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_CONDITION_TIME opcode: 0x56 ('V') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): condition number + * offset + 2 (8 bit): retries / 50 + * + * Check condition "condition number" in the condition table. + * Bios code then sleeps for 2ms if the condition is not met, and + * repeats up to "retries" times, but on one C51 this has proved + * insufficient. In mmiotraces the driver sleeps for 20ms, so we do + * this, and bail after "retries" times, or 2s, whichever is less. + * If still not met after retries, clear execution flag for this table. + */ + + uint8_t cond = bios->data[offset + 1]; + uint16_t retries = bios->data[offset + 2] * 50; + unsigned cnt; + + if (!iexec->execute) + return true; + + if (retries > 100) + retries = 100; + + BIOSLOG(bios, "0x%04X: Condition: 0x%02X, Retries: 0x%02X\n", + offset, cond, retries); + + if (!bios->execute) /* avoid 2s delays when "faking" execution */ + retries = 1; + + for (cnt = 0; cnt < retries; cnt++) { + if (bios_condition_met(bios, offset, cond)) { + BIOSLOG(bios, "0x%04X: Condition met, continuing\n", + offset); + break; + } else { + BIOSLOG(bios, "0x%04X: " + "Condition not met, sleeping for 20ms\n", + offset); + msleep(20); + } + } + + if (!bios_condition_met(bios, offset, cond)) { + NV_WARN(bios->dev, + "0x%04X: Condition still not met after %dms, " + "skipping following opcodes\n", offset, 20 * retries); + iexec->execute = false; + } + + return true; +} + +static bool +init_zm_reg_sequence(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_ZM_REG_SEQUENCE opcode: 0x58 ('X') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): base register + * offset + 5 (8 bit): count + * offset + 6 (32 bit): value 1 + * ... + * + * Starting at offset + 6 there are "count" 32 bit values. + * For "count" iterations set "base register" + 4 * current_iteration + * to "value current_iteration" + */ + + uint32_t basereg = ROM32(bios->data[offset + 1]); + uint32_t count = bios->data[offset + 5]; + int i; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: BaseReg: 0x%08X, Count: 0x%02X\n", + offset, basereg, count); + + for (i = 0; i < count; i++) { + uint32_t reg = basereg + i * 4; + uint32_t data = ROM32(bios->data[offset + 6 + i * 4]); + + bios_wr32(bios, reg, data); + } + + return true; +} + +static bool +init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_SUB_DIRECT opcode: 0x5B ('[') + * + * offset (8 bit): opcode + * offset + 1 (16 bit): subroutine offset (in bios) + * + * Calls a subroutine that will execute commands until INIT_DONE + * is found. + */ + + uint16_t sub_offset = ROM16(bios->data[offset + 1]); + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Executing subroutine at 0x%04X\n", + offset, sub_offset); + + parse_init_table(bios, sub_offset, iexec); + + BIOSLOG(bios, "0x%04X: End of 0x%04X subroutine\n", offset, sub_offset); + + return true; +} + +static bool +init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_COPY_NV_REG opcode: 0x5F ('_') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): src reg + * offset + 5 (8 bit): shift + * offset + 6 (32 bit): src mask + * offset + 10 (32 bit): xor + * offset + 14 (32 bit): dst reg + * offset + 18 (32 bit): dst mask + * + * Shift REGVAL("src reg") right by (signed) "shift", AND result with + * "src mask", then XOR with "xor". Write this OR'd with + * (REGVAL("dst reg") AND'd with "dst mask") to "dst reg" + */ + + uint32_t srcreg = *((uint32_t *)(&bios->data[offset + 1])); + uint8_t shift = bios->data[offset + 5]; + uint32_t srcmask = *((uint32_t *)(&bios->data[offset + 6])); + uint32_t xor = *((uint32_t *)(&bios->data[offset + 10])); + uint32_t dstreg = *((uint32_t *)(&bios->data[offset + 14])); + uint32_t dstmask = *((uint32_t *)(&bios->data[offset + 18])); + uint32_t srcvalue, dstvalue; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: SrcReg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%08X, " + "Xor: 0x%08X, DstReg: 0x%08X, DstMask: 0x%08X\n", + offset, srcreg, shift, srcmask, xor, dstreg, dstmask); + + srcvalue = bios_rd32(bios, srcreg); + + if (shift < 0x80) + srcvalue >>= shift; + else + srcvalue <<= (0x100 - shift); + + srcvalue = (srcvalue & srcmask) ^ xor; + + dstvalue = bios_rd32(bios, dstreg) & dstmask; + + bios_wr32(bios, dstreg, dstvalue | srcvalue); + + return true; +} + +static bool +init_zm_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_ZM_INDEX_IO opcode: 0x62 ('b') + * + * offset (8 bit): opcode + * offset + 1 (16 bit): CRTC port + * offset + 3 (8 bit): CRTC index + * offset + 4 (8 bit): data + * + * Write "data" to index "CRTC index" of "CRTC port" + */ + uint16_t crtcport = ROM16(bios->data[offset + 1]); + uint8_t crtcindex = bios->data[offset + 3]; + uint8_t data = bios->data[offset + 4]; + + if (!iexec->execute) + return true; + + bios_idxprt_wr(bios, crtcport, crtcindex, data); + + return true; +} + +static bool +init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_COMPUTE_MEM opcode: 0x63 ('c') + * + * offset (8 bit): opcode + * + * This opcode is meant to set NV_PFB_CFG0 (0x100200) appropriately so + * that the hardware can correctly calculate how much VRAM it has + * (and subsequently report that value in NV_PFB_CSTATUS (0x10020C)) + * + * The implementation of this opcode in general consists of two parts: + * 1) determination of the memory bus width + * 2) determination of how many of the card's RAM pads have ICs attached + * + * 1) is done by a cunning combination of writes to offsets 0x1c and + * 0x3c in the framebuffer, and seeing whether the written values are + * read back correctly. This then affects bits 4-7 of NV_PFB_CFG0 + * + * 2) is done by a cunning combination of writes to an offset slightly + * less than the maximum memory reported by NV_PFB_CSTATUS, then seeing + * if the test pattern can be read back. This then affects bits 12-15 of + * NV_PFB_CFG0 + * + * In this context a "cunning combination" may include multiple reads + * and writes to varying locations, often alternating the test pattern + * and 0, doubtless to make sure buffers are filled, residual charges + * on tracks are removed etc. + * + * Unfortunately, the "cunning combination"s mentioned above, and the + * changes to the bits in NV_PFB_CFG0 differ with nearly every bios + * trace I have. + * + * Therefore, we cheat and assume the value of NV_PFB_CFG0 with which + * we started was correct, and use that instead + */ + + /* no iexec->execute check by design */ + + /* + * This appears to be a NOP on G8x chipsets, both io logs of the VBIOS + * and kmmio traces of the binary driver POSTing the card show nothing + * being done for this opcode. why is it still listed in the table?! + */ + + struct drm_nouveau_private *dev_priv = bios->dev->dev_private; + + if (dev_priv->card_type >= NV_50) + return true; + + /* + * On every card I've seen, this step gets done for us earlier in + * the init scripts + uint8_t crdata = bios_idxprt_rd(dev, NV_VIO_SRX, 0x01); + bios_idxprt_wr(dev, NV_VIO_SRX, 0x01, crdata | 0x20); + */ + + /* + * This also has probably been done in the scripts, but an mmio trace of + * s3 resume shows nvidia doing it anyway (unlike the NV_VIO_SRX write) + */ + bios_wr32(bios, NV_PFB_REFCTRL, NV_PFB_REFCTRL_VALID_1); + + /* write back the saved configuration value */ + bios_wr32(bios, NV_PFB_CFG0, bios->state.saved_nv_pfb_cfg0); + + return true; +} + +static bool +init_reset(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_RESET opcode: 0x65 ('e') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): register + * offset + 5 (32 bit): value1 + * offset + 9 (32 bit): value2 + * + * Assign "value1" to "register", then assign "value2" to "register" + */ + + uint32_t reg = ROM32(bios->data[offset + 1]); + uint32_t value1 = ROM32(bios->data[offset + 5]); + uint32_t value2 = ROM32(bios->data[offset + 9]); + uint32_t pci_nv_19, pci_nv_20; + + /* no iexec->execute check by design */ + + pci_nv_19 = bios_rd32(bios, NV_PBUS_PCI_NV_19); + bios_wr32(bios, NV_PBUS_PCI_NV_19, 0); + bios_wr32(bios, reg, value1); + + udelay(10); + + bios_wr32(bios, reg, value2); + bios_wr32(bios, NV_PBUS_PCI_NV_19, pci_nv_19); + + pci_nv_20 = bios_rd32(bios, NV_PBUS_PCI_NV_20); + pci_nv_20 &= ~NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED; /* 0xfffffffe */ + bios_wr32(bios, NV_PBUS_PCI_NV_20, pci_nv_20); + + return true; +} + +static bool +init_configure_mem(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_CONFIGURE_MEM opcode: 0x66 ('f') + * + * offset (8 bit): opcode + * + * Equivalent to INIT_DONE on bios version 3 or greater. + * For early bios versions, sets up the memory registers, using values + * taken from the memory init table + */ + + /* no iexec->execute check by design */ + + uint16_t meminitoffs = bios->legacy.mem_init_tbl_ptr + MEM_INIT_SIZE * (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_SCRATCH4__INDEX) >> 4); + uint16_t seqtbloffs = bios->legacy.sdr_seq_tbl_ptr, meminitdata = meminitoffs + 6; + uint32_t reg, data; + + if (bios->major_version > 2) + return false; + + bios_idxprt_wr(bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX, bios_idxprt_rd( + bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX) | 0x20); + + if (bios->data[meminitoffs] & 1) + seqtbloffs = bios->legacy.ddr_seq_tbl_ptr; + + for (reg = ROM32(bios->data[seqtbloffs]); + reg != 0xffffffff; + reg = ROM32(bios->data[seqtbloffs += 4])) { + + switch (reg) { + case NV_PFB_PRE: + data = NV_PFB_PRE_CMD_PRECHARGE; + break; + case NV_PFB_PAD: + data = NV_PFB_PAD_CKE_NORMAL; + break; + case NV_PFB_REF: + data = NV_PFB_REF_CMD_REFRESH; + break; + default: + data = ROM32(bios->data[meminitdata]); + meminitdata += 4; + if (data == 0xffffffff) + continue; + } + + bios_wr32(bios, reg, data); + } + + return true; +} + +static bool +init_configure_clk(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_CONFIGURE_CLK opcode: 0x67 ('g') + * + * offset (8 bit): opcode + * + * Equivalent to INIT_DONE on bios version 3 or greater. + * For early bios versions, sets up the NVClk and MClk PLLs, using + * values taken from the memory init table + */ + + /* no iexec->execute check by design */ + + uint16_t meminitoffs = bios->legacy.mem_init_tbl_ptr + MEM_INIT_SIZE * (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_SCRATCH4__INDEX) >> 4); + int clock; + + if (bios->major_version > 2) + return false; + + clock = ROM16(bios->data[meminitoffs + 4]) * 10; + setPLL(bios, NV_PRAMDAC_NVPLL_COEFF, clock); + + clock = ROM16(bios->data[meminitoffs + 2]) * 10; + if (bios->data[meminitoffs] & 1) /* DDR */ + clock *= 2; + setPLL(bios, NV_PRAMDAC_MPLL_COEFF, clock); + + return true; +} + +static bool +init_configure_preinit(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_CONFIGURE_PREINIT opcode: 0x68 ('h') + * + * offset (8 bit): opcode + * + * Equivalent to INIT_DONE on bios version 3 or greater. + * For early bios versions, does early init, loading ram and crystal + * configuration from straps into CR3C + */ + + /* no iexec->execute check by design */ + + uint32_t straps = bios_rd32(bios, NV_PEXTDEV_BOOT_0); + uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & (1 << 6)); + + if (bios->major_version > 2) + return false; + + bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, + NV_CIO_CRE_SCRATCH4__INDEX, cr3c); + + return true; +} + +static bool +init_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_IO opcode: 0x69 ('i') + * + * offset (8 bit): opcode + * offset + 1 (16 bit): CRTC port + * offset + 3 (8 bit): mask + * offset + 4 (8 bit): data + * + * Assign ((IOVAL("crtc port") & "mask") | "data") to "crtc port" + */ + + struct drm_nouveau_private *dev_priv = bios->dev->dev_private; + uint16_t crtcport = ROM16(bios->data[offset + 1]); + uint8_t mask = bios->data[offset + 3]; + uint8_t data = bios->data[offset + 4]; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Port: 0x%04X, Mask: 0x%02X, Data: 0x%02X\n", + offset, crtcport, mask, data); + + /* + * I have no idea what this does, but NVIDIA do this magic sequence + * in the places where this INIT_IO happens.. + */ + if (dev_priv->card_type >= NV_50 && crtcport == 0x3c3 && data == 1) { + int i; + + bios_wr32(bios, 0x614100, (bios_rd32( + bios, 0x614100) & 0x0fffffff) | 0x00800000); + + bios_wr32(bios, 0x00e18c, bios_rd32( + bios, 0x00e18c) | 0x00020000); + + bios_wr32(bios, 0x614900, (bios_rd32( + bios, 0x614900) & 0x0fffffff) | 0x00800000); + + bios_wr32(bios, 0x000200, bios_rd32( + bios, 0x000200) & ~0x40000000); + + mdelay(10); + + bios_wr32(bios, 0x00e18c, bios_rd32( + bios, 0x00e18c) & ~0x00020000); + + bios_wr32(bios, 0x000200, bios_rd32( + bios, 0x000200) | 0x40000000); + + bios_wr32(bios, 0x614100, 0x00800018); + bios_wr32(bios, 0x614900, 0x00800018); + + mdelay(10); + + bios_wr32(bios, 0x614100, 0x10000018); + bios_wr32(bios, 0x614900, 0x10000018); + + for (i = 0; i < 3; i++) + bios_wr32(bios, 0x614280 + (i*0x800), bios_rd32( + bios, 0x614280 + (i*0x800)) & 0xf0f0f0f0); + + for (i = 0; i < 2; i++) + bios_wr32(bios, 0x614300 + (i*0x800), bios_rd32( + bios, 0x614300 + (i*0x800)) & 0xfffff0f0); + + for (i = 0; i < 3; i++) + bios_wr32(bios, 0x614380 + (i*0x800), bios_rd32( + bios, 0x614380 + (i*0x800)) & 0xfffff0f0); + + for (i = 0; i < 2; i++) + bios_wr32(bios, 0x614200 + (i*0x800), bios_rd32( + bios, 0x614200 + (i*0x800)) & 0xfffffff0); + + for (i = 0; i < 2; i++) + bios_wr32(bios, 0x614108 + (i*0x800), bios_rd32( + bios, 0x614108 + (i*0x800)) & 0x0fffffff); + return true; + } + + bios_port_wr(bios, crtcport, (bios_port_rd(bios, crtcport) & mask) | + data); + return true; +} + +static bool +init_sub(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_SUB opcode: 0x6B ('k') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): script number + * + * Execute script number "script number", as a subroutine + */ + + uint8_t sub = bios->data[offset + 1]; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Calling script %d\n", offset, sub); + + parse_init_table(bios, + ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]), + iexec); + + BIOSLOG(bios, "0x%04X: End of script %d\n", offset, sub); + + return true; +} + +static bool +init_ram_condition(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_RAM_CONDITION opcode: 0x6D ('m') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): mask + * offset + 2 (8 bit): cmpval + * + * Test if (NV_PFB_BOOT_0 & "mask") equals "cmpval". + * If condition not met skip subsequent opcodes until condition is + * inverted (INIT_NOT), or we hit INIT_RESUME + */ + + uint8_t mask = bios->data[offset + 1]; + uint8_t cmpval = bios->data[offset + 2]; + uint8_t data; + + if (!iexec->execute) + return true; + + data = bios_rd32(bios, NV_PFB_BOOT_0) & mask; + + BIOSLOG(bios, "0x%04X: Checking if 0x%08X equals 0x%08X\n", + offset, data, cmpval); + + if (data == cmpval) + BIOSLOG(bios, "0x%04X: Condition fulfilled -- continuing to execute\n", offset); + else { + BIOSLOG(bios, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset); + iexec->execute = false; + } + + return true; +} + +static bool +init_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_NV_REG opcode: 0x6E ('n') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): register + * offset + 5 (32 bit): mask + * offset + 9 (32 bit): data + * + * Assign ((REGVAL("register") & "mask") | "data") to "register" + */ + + uint32_t reg = ROM32(bios->data[offset + 1]); + uint32_t mask = ROM32(bios->data[offset + 5]); + uint32_t data = ROM32(bios->data[offset + 9]); + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Mask: 0x%08X, Data: 0x%08X\n", + offset, reg, mask, data); + + bios_wr32(bios, reg, (bios_rd32(bios, reg) & mask) | data); + + return true; +} + +static bool +init_macro(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_MACRO opcode: 0x6F ('o') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): macro number + * + * Look up macro index "macro number" in the macro index table. + * The macro index table entry has 1 byte for the index in the macro + * table, and 1 byte for the number of times to repeat the macro. + * The macro table entry has 4 bytes for the register address and + * 4 bytes for the value to write to that register + */ + + uint8_t macro_index_tbl_idx = bios->data[offset + 1]; + uint16_t tmp = bios->macro_index_tbl_ptr + (macro_index_tbl_idx * MACRO_INDEX_SIZE); + uint8_t macro_tbl_idx = bios->data[tmp]; + uint8_t count = bios->data[tmp + 1]; + uint32_t reg, data; + int i; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Macro: 0x%02X, MacroTableIndex: 0x%02X, " + "Count: 0x%02X\n", + offset, macro_index_tbl_idx, macro_tbl_idx, count); + + for (i = 0; i < count; i++) { + uint16_t macroentryptr = bios->macro_tbl_ptr + (macro_tbl_idx + i) * MACRO_SIZE; + + reg = ROM32(bios->data[macroentryptr]); + data = ROM32(bios->data[macroentryptr + 4]); + + bios_wr32(bios, reg, data); + } + + return true; +} + +static bool +init_done(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_DONE opcode: 0x71 ('q') + * + * offset (8 bit): opcode + * + * End the current script + */ + + /* mild retval abuse to stop parsing this table */ + return false; +} + +static bool +init_resume(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_RESUME opcode: 0x72 ('r') + * + * offset (8 bit): opcode + * + * End the current execute / no-execute condition + */ + + if (iexec->execute) + return true; + + iexec->execute = true; + BIOSLOG(bios, "0x%04X: ---- Executing following commands ----\n", offset); + + return true; +} + +static bool +init_time(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_TIME opcode: 0x74 ('t') + * + * offset (8 bit): opcode + * offset + 1 (16 bit): time + * + * Sleep for "time" microseconds. + */ + + unsigned time = ROM16(bios->data[offset + 1]); + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X microseconds\n", + offset, time); + + if (time < 1000) + udelay(time); + else + msleep((time + 900) / 1000); + + return true; +} + +static bool +init_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_CONDITION opcode: 0x75 ('u') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): condition number + * + * Check condition "condition number" in the condition table. + * If condition not met skip subsequent opcodes until condition is + * inverted (INIT_NOT), or we hit INIT_RESUME + */ + + uint8_t cond = bios->data[offset + 1]; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Condition: 0x%02X\n", offset, cond); + + if (bios_condition_met(bios, offset, cond)) + BIOSLOG(bios, "0x%04X: Condition fulfilled -- continuing to execute\n", offset); + else { + BIOSLOG(bios, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset); + iexec->execute = false; + } + + return true; +} + +static bool +init_io_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_IO_CONDITION opcode: 0x76 + * + * offset (8 bit): opcode + * offset + 1 (8 bit): condition number + * + * Check condition "condition number" in the io condition table. + * If condition not met skip subsequent opcodes until condition is + * inverted (INIT_NOT), or we hit INIT_RESUME + */ + + uint8_t cond = bios->data[offset + 1]; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: IO condition: 0x%02X\n", offset, cond); + + if (io_condition_met(bios, offset, cond)) + BIOSLOG(bios, "0x%04X: Condition fulfilled -- continuing to execute\n", offset); + else { + BIOSLOG(bios, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset); + iexec->execute = false; + } + + return true; +} + +static bool +init_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_INDEX_IO opcode: 0x78 ('x') + * + * offset (8 bit): opcode + * offset + 1 (16 bit): CRTC port + * offset + 3 (8 bit): CRTC index + * offset + 4 (8 bit): mask + * offset + 5 (8 bit): data + * + * Read value at index "CRTC index" on "CRTC port", AND with "mask", + * OR with "data", write-back + */ + + uint16_t crtcport = ROM16(bios->data[offset + 1]); + uint8_t crtcindex = bios->data[offset + 3]; + uint8_t mask = bios->data[offset + 4]; + uint8_t data = bios->data[offset + 5]; + uint8_t value; + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, " + "Data: 0x%02X\n", + offset, crtcport, crtcindex, mask, data); + + value = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) | data; + bios_idxprt_wr(bios, crtcport, crtcindex, value); + + return true; +} + +static bool +init_pll(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_PLL opcode: 0x79 ('y') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): register + * offset + 5 (16 bit): freq + * + * Set PLL register "register" to coefficients for frequency (10kHz) + * "freq" + */ + + uint32_t reg = ROM32(bios->data[offset + 1]); + uint16_t freq = ROM16(bios->data[offset + 5]); + + if (!iexec->execute) + return true; + + BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Freq: %d0kHz\n", offset, reg, freq); + + setPLL(bios, reg, freq * 10); + + return true; +} + +static bool +init_zm_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_ZM_REG opcode: 0x7A ('z') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): register + * offset + 5 (32 bit): value + * + * Assign "value" to "register" + */ + + uint32_t reg = ROM32(bios->data[offset + 1]); + uint32_t value = ROM32(bios->data[offset + 5]); + + if (!iexec->execute) + return true; + + if (reg == 0x000200) + value |= 1; + + bios_wr32(bios, reg, value); + + return true; +} + +static bool +init_ram_restrict_pll(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_RAM_RESTRICT_PLL opcode: 0x87 ('') + * + * offset (8 bit): opcode + * offset + 1 (8 bit): PLL type + * offset + 2 (32 bit): frequency 0 + * + * Uses the RAMCFG strap of PEXTDEV_BOOT as an index into the table at + * ram_restrict_table_ptr. The value read from there is used to select + * a frequency from the table starting at 'frequency 0' to be + * programmed into the PLL corresponding to 'type'. + * + * The PLL limits table on cards using this opcode has a mapping of + * 'type' to the relevant registers. + */ + + struct drm_device *dev = bios->dev; + uint32_t strap = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) & 0x0000003c) >> 2; + uint8_t index = bios->data[bios->ram_restrict_tbl_ptr + strap]; + uint8_t type = bios->data[offset + 1]; + uint32_t freq = ROM32(bios->data[offset + 2 + (index * 4)]); + uint8_t *pll_limits = &bios->data[bios->pll_limit_tbl_ptr], *entry; + int i; + + if (!iexec->execute) + return true; + + if (!bios->pll_limit_tbl_ptr || (pll_limits[0] & 0xf0) != 0x30) { + NV_ERROR(dev, "PLL limits table not version 3.x\n"); + return true; /* deliberate, allow default clocks to remain */ + } + + entry = pll_limits + pll_limits[1]; + for (i = 0; i < pll_limits[3]; i++, entry += pll_limits[2]) { + if (entry[0] == type) { + uint32_t reg = ROM32(entry[3]); + + BIOSLOG(bios, "0x%04X: " + "Type %02x Reg 0x%08x Freq %dKHz\n", + offset, type, reg, freq); + + setPLL(bios, reg, freq); + return true; + } + } + + NV_ERROR(dev, "PLL type 0x%02x not found in PLL limits table", type); + return true; +} + +static bool +init_8c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_8C opcode: 0x8C ('') + * + * NOP so far.... + * + */ + + return true; +} + +static bool +init_8d(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_8D opcode: 0x8D ('') + * + * NOP so far.... + * + */ + + return true; +} + +static bool +init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_GPIO opcode: 0x8E ('') + * + * offset (8 bit): opcode + * + * Loop over all entries in the DCB GPIO table, and initialise + * each GPIO according to various values listed in each entry + */ + + const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; + const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; + const uint8_t *gpio_table = &bios->data[bios->bdcb.gpio_table_ptr]; + const uint8_t *gpio_entry; + int i; + + if (bios->bdcb.version != 0x40) { + NV_ERROR(bios->dev, "DCB table not version 4.0\n"); + return false; + } + + if (!bios->bdcb.gpio_table_ptr) { + NV_WARN(bios->dev, "Invalid pointer to INIT_8E table\n"); + return false; + } + + gpio_entry = gpio_table + gpio_table[1]; + for (i = 0; i < gpio_table[2]; i++, gpio_entry += gpio_table[3]) { + uint32_t entry = ROM32(gpio_entry[0]), r, s, v; + int line = (entry & 0x0000001f); + + BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, entry); + + if ((entry & 0x0000ff00) == 0x0000ff00) + continue; + + r = nv50_gpio_reg[line >> 3]; + s = (line & 0x07) << 2; + v = bios_rd32(bios, r) & ~(0x00000003 << s); + if (entry & 0x01000000) + v |= (((entry & 0x60000000) >> 29) ^ 2) << s; + else + v |= (((entry & 0x18000000) >> 27) ^ 2) << s; + bios_wr32(bios, r, v); + + r = nv50_gpio_ctl[line >> 4]; + s = (line & 0x0f); + v = bios_rd32(bios, r) & ~(0x00010001 << s); + switch ((entry & 0x06000000) >> 25) { + case 1: + v |= (0x00000001 << s); + break; + case 2: + v |= (0x00010000 << s); + break; + default: + break; + } + bios_wr32(bios, r, v); + } + + return true; +} + +/* hack to avoid moving the itbl_entry array before this function */ +int init_ram_restrict_zm_reg_group_blocklen; + +static bool +init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_RAM_RESTRICT_ZM_REG_GROUP opcode: 0x8F ('') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): reg + * offset + 5 (8 bit): regincrement + * offset + 6 (8 bit): count + * offset + 7 (32 bit): value 1,1 + * ... + * + * Use the RAMCFG strap of PEXTDEV_BOOT as an index into the table at + * ram_restrict_table_ptr. The value read from here is 'n', and + * "value 1,n" gets written to "reg". This repeats "count" times and on + * each iteration 'm', "reg" increases by "regincrement" and + * "value m,n" is used. The extent of n is limited by a number read + * from the 'M' BIT table, herein called "blocklen" + */ + + uint32_t reg = ROM32(bios->data[offset + 1]); + uint8_t regincrement = bios->data[offset + 5]; + uint8_t count = bios->data[offset + 6]; + uint32_t strap_ramcfg, data; + uint16_t blocklen; + uint8_t index; + int i; + + /* previously set by 'M' BIT table */ + blocklen = init_ram_restrict_zm_reg_group_blocklen; + + if (!iexec->execute) + return true; + + if (!blocklen) { + NV_ERROR(bios->dev, + "0x%04X: Zero block length - has the M table " + "been parsed?\n", offset); + return false; + } + + strap_ramcfg = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 2) & 0xf; + index = bios->data[bios->ram_restrict_tbl_ptr + strap_ramcfg]; + + BIOSLOG(bios, "0x%04X: Reg: 0x%08X, RegIncrement: 0x%02X, " + "Count: 0x%02X, StrapRamCfg: 0x%02X, Index: 0x%02X\n", + offset, reg, regincrement, count, strap_ramcfg, index); + + for (i = 0; i < count; i++) { + data = ROM32(bios->data[offset + 7 + index * 4 + blocklen * i]); + + bios_wr32(bios, reg, data); + + reg += regincrement; + } + + return true; +} + +static bool +init_copy_zm_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_COPY_ZM_REG opcode: 0x90 ('') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): src reg + * offset + 5 (32 bit): dst reg + * + * Put contents of "src reg" into "dst reg" + */ + + uint32_t srcreg = ROM32(bios->data[offset + 1]); + uint32_t dstreg = ROM32(bios->data[offset + 5]); + + if (!iexec->execute) + return true; + + bios_wr32(bios, dstreg, bios_rd32(bios, srcreg)); + + return true; +} + +static bool +init_zm_reg_group_addr_latched(struct nvbios *bios, uint16_t offset, + struct init_exec *iexec) +{ + /* + * INIT_ZM_REG_GROUP_ADDRESS_LATCHED opcode: 0x91 ('') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): dst reg + * offset + 5 (8 bit): count + * offset + 6 (32 bit): data 1 + * ... + * + * For each of "count" values write "data n" to "dst reg" + */ + + uint32_t reg = ROM32(bios->data[offset + 1]); + uint8_t count = bios->data[offset + 5]; + int i; + + if (!iexec->execute) + return true; + + for (i = 0; i < count; i++) { + uint32_t data = ROM32(bios->data[offset + 6 + 4 * i]); + bios_wr32(bios, reg, data); + } + + return true; +} + +static bool +init_reserved(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_RESERVED opcode: 0x92 ('') + * + * offset (8 bit): opcode + * + * Seemingly does nothing + */ + + return true; +} + +static bool +init_96(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_96 opcode: 0x96 ('') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): sreg + * offset + 5 (8 bit): sshift + * offset + 6 (8 bit): smask + * offset + 7 (8 bit): index + * offset + 8 (32 bit): reg + * offset + 12 (32 bit): mask + * offset + 16 (8 bit): shift + * + */ + + uint16_t xlatptr = bios->init96_tbl_ptr + (bios->data[offset + 7] * 2); + uint32_t reg = ROM32(bios->data[offset + 8]); + uint32_t mask = ROM32(bios->data[offset + 12]); + uint32_t val; + + val = bios_rd32(bios, ROM32(bios->data[offset + 1])); + if (bios->data[offset + 5] < 0x80) + val >>= bios->data[offset + 5]; + else + val <<= (0x100 - bios->data[offset + 5]); + val &= bios->data[offset + 6]; + + val = bios->data[ROM16(bios->data[xlatptr]) + val]; + val <<= bios->data[offset + 16]; + + if (!iexec->execute) + return true; + + bios_wr32(bios, reg, (bios_rd32(bios, reg) & mask) | val); + return true; +} + +static bool +init_97(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_97 opcode: 0x97 ('') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): register + * offset + 5 (32 bit): mask + * offset + 9 (32 bit): value + * + * Adds "value" to "register" preserving the fields specified + * by "mask" + */ + + uint32_t reg = ROM32(bios->data[offset + 1]); + uint32_t mask = ROM32(bios->data[offset + 5]); + uint32_t add = ROM32(bios->data[offset + 9]); + uint32_t val; + + val = bios_rd32(bios, reg); + val = (val & mask) | ((val + add) & ~mask); + + if (!iexec->execute) + return true; + + bios_wr32(bios, reg, val); + return true; +} + +static bool +init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_AUXCH opcode: 0x98 ('') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): address + * offset + 5 (8 bit): count + * offset + 6 (8 bit): mask 0 + * offset + 7 (8 bit): data 0 + * ... + * + */ + + struct drm_device *dev = bios->dev; + struct nouveau_i2c_chan *auxch; + uint32_t addr = ROM32(bios->data[offset + 1]); + uint8_t len = bios->data[offset + 5]; + int ret, i; + + if (!bios->display.output) { + NV_ERROR(dev, "INIT_AUXCH: no active output\n"); + return false; + } + + auxch = init_i2c_device_find(dev, bios->display.output->i2c_index); + if (!auxch) { + NV_ERROR(dev, "INIT_AUXCH: couldn't get auxch %d\n", + bios->display.output->i2c_index); + return false; + } + + if (!iexec->execute) + return true; + + offset += 6; + for (i = 0; i < len; i++, offset += 2) { + uint8_t data; + + ret = nouveau_dp_auxch(auxch, 9, addr, &data, 1); + if (ret) { + NV_ERROR(dev, "INIT_AUXCH: rd auxch fail %d\n", ret); + return false; + } + + data &= bios->data[offset + 0]; + data |= bios->data[offset + 1]; + + ret = nouveau_dp_auxch(auxch, 8, addr, &data, 1); + if (ret) { + NV_ERROR(dev, "INIT_AUXCH: wr auxch fail %d\n", ret); + return false; + } + } + + return true; +} + +static bool +init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) +{ + /* + * INIT_ZM_AUXCH opcode: 0x99 ('') + * + * offset (8 bit): opcode + * offset + 1 (32 bit): address + * offset + 5 (8 bit): count + * offset + 6 (8 bit): data 0 + * ... + * + */ + + struct drm_device *dev = bios->dev; + struct nouveau_i2c_chan *auxch; + uint32_t addr = ROM32(bios->data[offset + 1]); + uint8_t len = bios->data[offset + 5]; + int ret, i; + + if (!bios->display.output) { + NV_ERROR(dev, "INIT_ZM_AUXCH: no active output\n"); + return false; + } + + auxch = init_i2c_device_find(dev, bios->display.output->i2c_index); + if (!auxch) { + NV_ERROR(dev, "INIT_ZM_AUXCH: couldn't get auxch %d\n", + bios->display.output->i2c_index); + return false; + } + + if (!iexec->execute) + return true; + + offset += 6; + for (i = 0; i < len; i++, offset++) { + ret = nouveau_dp_auxch(auxch, 8, addr, &bios->data[offset], 1); + if (ret) { + NV_ERROR(dev, "INIT_ZM_AUXCH: wr auxch fail %d\n", ret); + return false; + } + } + + return true; +} + +static struct init_tbl_entry itbl_entry[] = { + /* command name , id , length , offset , mult , command handler */ + /* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */ + { "INIT_IO_RESTRICT_PROG" , 0x32, 11 , 6 , 4 , init_io_restrict_prog }, + { "INIT_REPEAT" , 0x33, 2 , 0 , 0 , init_repeat }, + { "INIT_IO_RESTRICT_PLL" , 0x34, 12 , 7 , 2 , init_io_restrict_pll }, + { "INIT_END_REPEAT" , 0x36, 1 , 0 , 0 , init_end_repeat }, + { "INIT_COPY" , 0x37, 11 , 0 , 0 , init_copy }, + { "INIT_NOT" , 0x38, 1 , 0 , 0 , init_not }, + { "INIT_IO_FLAG_CONDITION" , 0x39, 2 , 0 , 0 , init_io_flag_condition }, + { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, 18 , 17 , 2 , init_idx_addr_latched }, + { "INIT_IO_RESTRICT_PLL2" , 0x4A, 11 , 6 , 4 , init_io_restrict_pll2 }, + { "INIT_PLL2" , 0x4B, 9 , 0 , 0 , init_pll2 }, + { "INIT_I2C_BYTE" , 0x4C, 4 , 3 , 3 , init_i2c_byte }, + { "INIT_ZM_I2C_BYTE" , 0x4D, 4 , 3 , 2 , init_zm_i2c_byte }, + { "INIT_ZM_I2C" , 0x4E, 4 , 3 , 1 , init_zm_i2c }, + { "INIT_TMDS" , 0x4F, 5 , 0 , 0 , init_tmds }, + { "INIT_ZM_TMDS_GROUP" , 0x50, 3 , 2 , 2 , init_zm_tmds_group }, + { "INIT_CR_INDEX_ADDRESS_LATCHED" , 0x51, 5 , 4 , 1 , init_cr_idx_adr_latch }, + { "INIT_CR" , 0x52, 4 , 0 , 0 , init_cr }, + { "INIT_ZM_CR" , 0x53, 3 , 0 , 0 , init_zm_cr }, + { "INIT_ZM_CR_GROUP" , 0x54, 2 , 1 , 2 , init_zm_cr_group }, + { "INIT_CONDITION_TIME" , 0x56, 3 , 0 , 0 , init_condition_time }, + { "INIT_ZM_REG_SEQUENCE" , 0x58, 6 , 5 , 4 , init_zm_reg_sequence }, + /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */ + { "INIT_SUB_DIRECT" , 0x5B, 3 , 0 , 0 , init_sub_direct }, + { "INIT_COPY_NV_REG" , 0x5F, 22 , 0 , 0 , init_copy_nv_reg }, + { "INIT_ZM_INDEX_IO" , 0x62, 5 , 0 , 0 , init_zm_index_io }, + { "INIT_COMPUTE_MEM" , 0x63, 1 , 0 , 0 , init_compute_mem }, + { "INIT_RESET" , 0x65, 13 , 0 , 0 , init_reset }, + { "INIT_CONFIGURE_MEM" , 0x66, 1 , 0 , 0 , init_configure_mem }, + { "INIT_CONFIGURE_CLK" , 0x67, 1 , 0 , 0 , init_configure_clk }, + { "INIT_CONFIGURE_PREINIT" , 0x68, 1 , 0 , 0 , init_configure_preinit }, + { "INIT_IO" , 0x69, 5 , 0 , 0 , init_io }, + { "INIT_SUB" , 0x6B, 2 , 0 , 0 , init_sub }, + { "INIT_RAM_CONDITION" , 0x6D, 3 , 0 , 0 , init_ram_condition }, + { "INIT_NV_REG" , 0x6E, 13 , 0 , 0 , init_nv_reg }, + { "INIT_MACRO" , 0x6F, 2 , 0 , 0 , init_macro }, + { "INIT_DONE" , 0x71, 1 , 0 , 0 , init_done }, + { "INIT_RESUME" , 0x72, 1 , 0 , 0 , init_resume }, + /* INIT_RAM_CONDITION2 (0x73, 9, 0, 0) removed due to no example of use */ + { "INIT_TIME" , 0x74, 3 , 0 , 0 , init_time }, + { "INIT_CONDITION" , 0x75, 2 , 0 , 0 , init_condition }, + { "INIT_IO_CONDITION" , 0x76, 2 , 0 , 0 , init_io_condition }, + { "INIT_INDEX_IO" , 0x78, 6 , 0 , 0 , init_index_io }, + { "INIT_PLL" , 0x79, 7 , 0 , 0 , init_pll }, + { "INIT_ZM_REG" , 0x7A, 9 , 0 , 0 , init_zm_reg }, + /* INIT_RAM_RESTRICT_PLL's length is adjusted by the BIT M table */ + { "INIT_RAM_RESTRICT_PLL" , 0x87, 2 , 0 , 0 , init_ram_restrict_pll }, + { "INIT_8C" , 0x8C, 1 , 0 , 0 , init_8c }, + { "INIT_8D" , 0x8D, 1 , 0 , 0 , init_8d }, + { "INIT_GPIO" , 0x8E, 1 , 0 , 0 , init_gpio }, + /* INIT_RAM_RESTRICT_ZM_REG_GROUP's mult is loaded by M table in BIT */ + { "INIT_RAM_RESTRICT_ZM_REG_GROUP" , 0x8F, 7 , 6 , 0 , init_ram_restrict_zm_reg_group }, + { "INIT_COPY_ZM_REG" , 0x90, 9 , 0 , 0 , init_copy_zm_reg }, + { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, 6 , 5 , 4 , init_zm_reg_group_addr_latched }, + { "INIT_RESERVED" , 0x92, 1 , 0 , 0 , init_reserved }, + { "INIT_96" , 0x96, 17 , 0 , 0 , init_96 }, + { "INIT_97" , 0x97, 13 , 0 , 0 , init_97 }, + { "INIT_AUXCH" , 0x98, 6 , 5 , 2 , init_auxch }, + { "INIT_ZM_AUXCH" , 0x99, 6 , 5 , 1 , init_zm_auxch }, + { NULL , 0 , 0 , 0 , 0 , NULL } +}; + +static unsigned int get_init_table_entry_length(struct nvbios *bios, unsigned int offset, int i) +{ + /* Calculates the length of a given init table entry. */ + return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier; +} + +#define MAX_TABLE_OPS 1000 + +static int +parse_init_table(struct nvbios *bios, unsigned int offset, + struct init_exec *iexec) +{ + /* + * Parses all commands in an init table. + * + * We start out executing all commands found in the init table. Some + * opcodes may change the status of iexec->execute to SKIP, which will + * cause the following opcodes to perform no operation until the value + * is changed back to EXECUTE. + */ + + int count = 0, i; + uint8_t id; + + /* + * Loop until INIT_DONE causes us to break out of the loop + * (or until offset > bios length just in case... ) + * (and no more than MAX_TABLE_OPS iterations, just in case... ) + */ + while ((offset < bios->length) && (count++ < MAX_TABLE_OPS)) { + id = bios->data[offset]; + + /* Find matching id in itbl_entry */ + for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++) + ; + + if (itbl_entry[i].name) { + BIOSLOG(bios, "0x%04X: [ (0x%02X) - %s ]\n", + offset, itbl_entry[i].id, itbl_entry[i].name); + + /* execute eventual command handler */ + if (itbl_entry[i].handler) + if (!(*itbl_entry[i].handler)(bios, offset, iexec)) + break; + } else { + NV_ERROR(bios->dev, + "0x%04X: Init table command not found: " + "0x%02X\n", offset, id); + return -ENOENT; + } + + /* + * Add the offset of the current command including all data + * of that command. The offset will then be pointing on the + * next op code. + */ + offset += get_init_table_entry_length(bios, offset, i); + } + + if (offset >= bios->length) + NV_WARN(bios->dev, + "Offset 0x%04X greater than known bios image length. " + "Corrupt image?\n", offset); + if (count >= MAX_TABLE_OPS) + NV_WARN(bios->dev, + "More than %d opcodes to a table is unlikely, " + "is the bios image corrupt?\n", MAX_TABLE_OPS); + + return 0; +} + +static void +parse_init_tables(struct nvbios *bios) +{ + /* Loops and calls parse_init_table() for each present table. */ + + int i = 0; + uint16_t table; + struct init_exec iexec = {true, false}; + + if (bios->old_style_init) { + if (bios->init_script_tbls_ptr) + parse_init_table(bios, bios->init_script_tbls_ptr, &iexec); + if (bios->extra_init_script_tbl_ptr) + parse_init_table(bios, bios->extra_init_script_tbl_ptr, &iexec); + + return; + } + + while ((table = ROM16(bios->data[bios->init_script_tbls_ptr + i]))) { + NV_INFO(bios->dev, + "Parsing VBIOS init table %d at offset 0x%04X\n", + i / 2, table); + BIOSLOG(bios, "0x%04X: ------ Executing following commands ------\n", table); + + parse_init_table(bios, table, &iexec); + i += 2; + } +} + +static uint16_t clkcmptable(struct nvbios *bios, uint16_t clktable, int pxclk) +{ + int compare_record_len, i = 0; + uint16_t compareclk, scriptptr = 0; + + if (bios->major_version < 5) /* pre BIT */ + compare_record_len = 3; + else + compare_record_len = 4; + + do { + compareclk = ROM16(bios->data[clktable + compare_record_len * i]); + if (pxclk >= compareclk * 10) { + if (bios->major_version < 5) { + uint8_t tmdssub = bios->data[clktable + 2 + compare_record_len * i]; + scriptptr = ROM16(bios->data[bios->init_script_tbls_ptr + tmdssub * 2]); + } else + scriptptr = ROM16(bios->data[clktable + 2 + compare_record_len * i]); + break; + } + i++; + } while (compareclk); + + return scriptptr; +} + +static void +run_digital_op_script(struct drm_device *dev, uint16_t scriptptr, + struct dcb_entry *dcbent, int head, bool dl) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + struct init_exec iexec = {true, false}; + + NV_TRACE(dev, "0x%04X: Parsing digital output script table\n", + scriptptr); + bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_44, + head ? NV_CIO_CRE_44_HEADB : NV_CIO_CRE_44_HEADA); + /* note: if dcb entries have been merged, index may be misleading */ + NVWriteVgaCrtc5758(dev, head, 0, dcbent->index); + parse_init_table(bios, scriptptr, &iexec); + + nv04_dfp_bind_head(dev, dcbent, head, dl); +} + +static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entry *dcbent, int head, enum LVDS_script script) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + uint8_t sub = bios->data[bios->fp.xlated_entry + script] + (bios->fp.link_c_increment && dcbent->or & OUTPUT_C ? 1 : 0); + uint16_t scriptofs = ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]); + + if (!bios->fp.xlated_entry || !sub || !scriptofs) + return -EINVAL; + + run_digital_op_script(dev, scriptofs, dcbent, head, bios->fp.dual_link); + + if (script == LVDS_PANEL_OFF) { + /* off-on delay in ms */ + msleep(ROM16(bios->data[bios->fp.xlated_entry + 7])); + } +#ifdef __powerpc__ + /* Powerbook specific quirks */ + if (script == LVDS_RESET && ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0329)) + nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72); + if ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0189 || (dev->pci_device & 0xffff) == 0x0329) { + if (script == LVDS_PANEL_ON) { + bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) | (1 << 31)); + bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1); + } + if (script == LVDS_PANEL_OFF) { + bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) & ~(1 << 31)); + bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3); + } + } +#endif + + return 0; +} + +static int run_lvds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, enum LVDS_script script, int pxclk) +{ + /* + * The BIT LVDS table's header has the information to setup the + * necessary registers. Following the standard 4 byte header are: + * A bitmask byte and a dual-link transition pxclk value for use in + * selecting the init script when not using straps; 4 script pointers + * for panel power, selected by output and on/off; and 8 table pointers + * for panel init, the needed one determined by output, and bits in the + * conf byte. These tables are similar to the TMDS tables, consisting + * of a list of pxclks and script pointers. + */ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + unsigned int outputset = (dcbent->or == 4) ? 1 : 0; + uint16_t scriptptr = 0, clktable; + uint8_t clktableptr = 0; + + /* + * For now we assume version 3.0 table - g80 support will need some + * changes + */ + + switch (script) { + case LVDS_INIT: + return -ENOSYS; + case LVDS_BACKLIGHT_ON: + case LVDS_PANEL_ON: + scriptptr = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 7 + outputset * 2]); + break; + case LVDS_BACKLIGHT_OFF: + case LVDS_PANEL_OFF: + scriptptr = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 11 + outputset * 2]); + break; + case LVDS_RESET: + if (dcbent->lvdsconf.use_straps_for_mode) { + if (bios->fp.dual_link) + clktableptr += 2; + if (bios->fp.BITbit1) + clktableptr++; + } else { + /* using EDID */ + uint8_t fallback = bios->data[bios->fp.lvdsmanufacturerpointer + 4]; + int fallbackcmpval = (dcbent->or == 4) ? 4 : 1; + + if (bios->fp.dual_link) { + clktableptr += 2; + fallbackcmpval *= 2; + } + if (fallbackcmpval & fallback) + clktableptr++; + } + + /* adding outputset * 8 may not be correct */ + clktable = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 15 + clktableptr * 2 + outputset * 8]); + if (!clktable) { + NV_ERROR(dev, "Pixel clock comparison table not found\n"); + return -ENOENT; + } + scriptptr = clkcmptable(bios, clktable, pxclk); + } + + if (!scriptptr) { + NV_ERROR(dev, "LVDS output init script not found\n"); + return -ENOENT; + } + run_digital_op_script(dev, scriptptr, dcbent, head, bios->fp.dual_link); + + return 0; +} + +int call_lvds_script(struct drm_device *dev, struct dcb_entry *dcbent, int head, enum LVDS_script script, int pxclk) +{ + /* + * LVDS operations are multiplexed in an effort to present a single API + * which works with two vastly differing underlying structures. + * This acts as the demux + */ + + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer]; + uint32_t sel_clk_binding, sel_clk; + int ret; + + if (bios->fp.last_script_invoc == (script << 1 | head) || !lvds_ver || + (lvds_ver >= 0x30 && script == LVDS_INIT)) + return 0; + + if (!bios->fp.lvds_init_run) { + bios->fp.lvds_init_run = true; + call_lvds_script(dev, dcbent, head, LVDS_INIT, pxclk); + } + + if (script == LVDS_PANEL_ON && bios->fp.reset_after_pclk_change) + call_lvds_script(dev, dcbent, head, LVDS_RESET, pxclk); + if (script == LVDS_RESET && bios->fp.power_off_for_reset) + call_lvds_script(dev, dcbent, head, LVDS_PANEL_OFF, pxclk); + + NV_TRACE(dev, "Calling LVDS script %d:\n", script); + + /* don't let script change pll->head binding */ + sel_clk_binding = bios_rd32(bios, NV_PRAMDAC_SEL_CLK) & 0x50000; + + if (lvds_ver < 0x30) + ret = call_lvds_manufacturer_script(dev, dcbent, head, script); + else + ret = run_lvds_table(dev, dcbent, head, script, pxclk); + + bios->fp.last_script_invoc = (script << 1 | head); + + sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000; + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding); + /* some scripts set a value in NV_PBUS_POWERCTRL_2 and break video overlay */ + nvWriteMC(dev, NV_PBUS_POWERCTRL_2, 0); + + return ret; +} + +struct lvdstableheader { + uint8_t lvds_ver, headerlen, recordlen; +}; + +static int parse_lvds_manufacturer_table_header(struct drm_device *dev, struct nvbios *bios, struct lvdstableheader *lth) +{ + /* + * BMP version (0xa) LVDS table has a simple header of version and + * record length. The BIT LVDS table has the typical BIT table header: + * version byte, header length byte, record length byte, and a byte for + * the maximum number of records that can be held in the table. + */ + + uint8_t lvds_ver, headerlen, recordlen; + + memset(lth, 0, sizeof(struct lvdstableheader)); + + if (bios->fp.lvdsmanufacturerpointer == 0x0) { + NV_ERROR(dev, "Pointer to LVDS manufacturer table invalid\n"); + return -EINVAL; + } + + lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer]; + + switch (lvds_ver) { + case 0x0a: /* pre NV40 */ + headerlen = 2; + recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1]; + break; + case 0x30: /* NV4x */ + headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1]; + if (headerlen < 0x1f) { + NV_ERROR(dev, "LVDS table header not understood\n"); + return -EINVAL; + } + recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2]; + break; + case 0x40: /* G80/G90 */ + headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1]; + if (headerlen < 0x7) { + NV_ERROR(dev, "LVDS table header not understood\n"); + return -EINVAL; + } + recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2]; + break; + default: + NV_ERROR(dev, + "LVDS table revision %d.%d not currently supported\n", + lvds_ver >> 4, lvds_ver & 0xf); + return -ENOSYS; + } + + lth->lvds_ver = lvds_ver; + lth->headerlen = headerlen; + lth->recordlen = recordlen; + + return 0; +} + +static int +get_fp_strap(struct drm_device *dev, struct nvbios *bios) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* + * The fp strap is normally dictated by the "User Strap" in + * PEXTDEV_BOOT_0[20:16], but on BMP cards when bit 2 of the + * Internal_Flags struct at 0x48 is set, the user strap gets overriden + * by the PCI subsystem ID during POST, but not before the previous user + * strap has been committed to CR58 for CR57=0xf on head A, which may be + * read and used instead + */ + + if (bios->major_version < 5 && bios->data[0x48] & 0x4) + return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf; + + if (dev_priv->card_type >= NV_50) + return (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 24) & 0xf; + else + return (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 16) & 0xf; +} + +static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) +{ + uint8_t *fptable; + uint8_t fptable_ver, headerlen = 0, recordlen, fpentries = 0xf, fpindex; + int ret, ofs, fpstrapping; + struct lvdstableheader lth; + + if (bios->fp.fptablepointer == 0x0) { + /* Apple cards don't have the fp table; the laptops use DDC */ + /* The table is also missing on some x86 IGPs */ +#ifndef __powerpc__ + NV_ERROR(dev, "Pointer to flat panel table invalid\n"); +#endif + bios->pub.digital_min_front_porch = 0x4b; + return 0; + } + + fptable = &bios->data[bios->fp.fptablepointer]; + fptable_ver = fptable[0]; + + switch (fptable_ver) { + /* + * BMP version 0x5.0x11 BIOSen have version 1 like tables, but no + * version field, and miss one of the spread spectrum/PWM bytes. + * This could affect early GF2Go parts (not seen any appropriate ROMs + * though). Here we assume that a version of 0x05 matches this case + * (combining with a BMP version check would be better), as the + * common case for the panel type field is 0x0005, and that is in + * fact what we are reading the first byte of. + */ + case 0x05: /* some NV10, 11, 15, 16 */ + recordlen = 42; + ofs = -1; + break; + case 0x10: /* some NV15/16, and NV11+ */ + recordlen = 44; + ofs = 0; + break; + case 0x20: /* NV40+ */ + headerlen = fptable[1]; + recordlen = fptable[2]; + fpentries = fptable[3]; + /* + * fptable[4] is the minimum + * RAMDAC_FP_HCRTC -> RAMDAC_FP_HSYNC_START gap + */ + bios->pub.digital_min_front_porch = fptable[4]; + ofs = -7; + break; + default: + NV_ERROR(dev, + "FP table revision %d.%d not currently supported\n", + fptable_ver >> 4, fptable_ver & 0xf); + return -ENOSYS; + } + + if (!bios->is_mobile) /* !mobile only needs digital_min_front_porch */ + return 0; + + ret = parse_lvds_manufacturer_table_header(dev, bios, <h); + if (ret) + return ret; + + if (lth.lvds_ver == 0x30 || lth.lvds_ver == 0x40) { + bios->fp.fpxlatetableptr = bios->fp.lvdsmanufacturerpointer + + lth.headerlen + 1; + bios->fp.xlatwidth = lth.recordlen; + } + if (bios->fp.fpxlatetableptr == 0x0) { + NV_ERROR(dev, "Pointer to flat panel xlat table invalid\n"); + return -EINVAL; + } + + fpstrapping = get_fp_strap(dev, bios); + + fpindex = bios->data[bios->fp.fpxlatetableptr + + fpstrapping * bios->fp.xlatwidth]; + + if (fpindex > fpentries) { + NV_ERROR(dev, "Bad flat panel table index\n"); + return -ENOENT; + } + + /* nv4x cards need both a strap value and fpindex of 0xf to use DDC */ + if (lth.lvds_ver > 0x10) + bios->pub.fp_no_ddc = fpstrapping != 0xf || fpindex != 0xf; + + /* + * If either the strap or xlated fpindex value are 0xf there is no + * panel using a strap-derived bios mode present. this condition + * includes, but is different from, the DDC panel indicator above + */ + if (fpstrapping == 0xf || fpindex == 0xf) + return 0; + + bios->fp.mode_ptr = bios->fp.fptablepointer + headerlen + + recordlen * fpindex + ofs; + + NV_TRACE(dev, "BIOS FP mode: %dx%d (%dkHz pixel clock)\n", + ROM16(bios->data[bios->fp.mode_ptr + 11]) + 1, + ROM16(bios->data[bios->fp.mode_ptr + 25]) + 1, + ROM16(bios->data[bios->fp.mode_ptr + 7]) * 10); + + return 0; +} + +bool nouveau_bios_fp_mode(struct drm_device *dev, struct drm_display_mode *mode) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + uint8_t *mode_entry = &bios->data[bios->fp.mode_ptr]; + + if (!mode) /* just checking whether we can produce a mode */ + return bios->fp.mode_ptr; + + memset(mode, 0, sizeof(struct drm_display_mode)); + /* + * For version 1.0 (version in byte 0): + * bytes 1-2 are "panel type", including bits on whether Colour/mono, + * single/dual link, and type (TFT etc.) + * bytes 3-6 are bits per colour in RGBX + */ + mode->clock = ROM16(mode_entry[7]) * 10; + /* bytes 9-10 is HActive */ + mode->hdisplay = ROM16(mode_entry[11]) + 1; + /* + * bytes 13-14 is HValid Start + * bytes 15-16 is HValid End + */ + mode->hsync_start = ROM16(mode_entry[17]) + 1; + mode->hsync_end = ROM16(mode_entry[19]) + 1; + mode->htotal = ROM16(mode_entry[21]) + 1; + /* bytes 23-24, 27-30 similarly, but vertical */ + mode->vdisplay = ROM16(mode_entry[25]) + 1; + mode->vsync_start = ROM16(mode_entry[31]) + 1; + mode->vsync_end = ROM16(mode_entry[33]) + 1; + mode->vtotal = ROM16(mode_entry[35]) + 1; + mode->flags |= (mode_entry[37] & 0x10) ? + DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; + mode->flags |= (mode_entry[37] & 0x1) ? + DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; + /* + * bytes 38-39 relate to spread spectrum settings + * bytes 40-43 are something to do with PWM + */ + + mode->status = MODE_OK; + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + drm_mode_set_name(mode); + return bios->fp.mode_ptr; +} + +int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, bool *if_is_24bit) +{ + /* + * The LVDS table header is (mostly) described in + * parse_lvds_manufacturer_table_header(): the BIT header additionally + * contains the dual-link transition pxclk (in 10s kHz), at byte 5 - if + * straps are not being used for the panel, this specifies the frequency + * at which modes should be set up in the dual link style. + * + * Following the header, the BMP (ver 0xa) table has several records, + * indexed by a seperate xlat table, indexed in turn by the fp strap in + * EXTDEV_BOOT. Each record had a config byte, followed by 6 script + * numbers for use by INIT_SUB which controlled panel init and power, + * and finally a dword of ms to sleep between power off and on + * operations. + * + * In the BIT versions, the table following the header serves as an + * integrated config and xlat table: the records in the table are + * indexed by the FP strap nibble in EXTDEV_BOOT, and each record has + * two bytes - the first as a config byte, the second for indexing the + * fp mode table pointed to by the BIT 'D' table + * + * DDC is not used until after card init, so selecting the correct table + * entry and setting the dual link flag for EDID equipped panels, + * requiring tests against the native-mode pixel clock, cannot be done + * until later, when this function should be called with non-zero pxclk + */ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + int fpstrapping = get_fp_strap(dev, bios), lvdsmanufacturerindex = 0; + struct lvdstableheader lth; + uint16_t lvdsofs; + int ret, chip_version = bios->pub.chip_version; + + ret = parse_lvds_manufacturer_table_header(dev, bios, <h); + if (ret) + return ret; + + switch (lth.lvds_ver) { + case 0x0a: /* pre NV40 */ + lvdsmanufacturerindex = bios->data[ + bios->fp.fpxlatemanufacturertableptr + + fpstrapping]; + + /* we're done if this isn't the EDID panel case */ + if (!pxclk) + break; + + if (chip_version < 0x25) { + /* nv17 behaviour + * + * It seems the old style lvds script pointer is reused + * to select 18/24 bit colour depth for EDID panels. + */ + lvdsmanufacturerindex = + (bios->legacy.lvds_single_a_script_ptr & 1) ? + 2 : 0; + if (pxclk >= bios->fp.duallink_transition_clk) + lvdsmanufacturerindex++; + } else if (chip_version < 0x30) { + /* nv28 behaviour (off-chip encoder) + * + * nv28 does a complex dance of first using byte 121 of + * the EDID to choose the lvdsmanufacturerindex, then + * later attempting to match the EDID manufacturer and + * product IDs in a table (signature 'pidt' (panel id + * table?)), setting an lvdsmanufacturerindex of 0 and + * an fp strap of the match index (or 0xf if none) + */ + lvdsmanufacturerindex = 0; + } else { + /* nv31, nv34 behaviour */ + lvdsmanufacturerindex = 0; + if (pxclk >= bios->fp.duallink_transition_clk) + lvdsmanufacturerindex = 2; + if (pxclk >= 140000) + lvdsmanufacturerindex = 3; + } + + /* + * nvidia set the high nibble of (cr57=f, cr58) to + * lvdsmanufacturerindex in this case; we don't + */ + break; + case 0x30: /* NV4x */ + case 0x40: /* G80/G90 */ + lvdsmanufacturerindex = fpstrapping; + break; + default: + NV_ERROR(dev, "LVDS table revision not currently supported\n"); + return -ENOSYS; + } + + lvdsofs = bios->fp.xlated_entry = bios->fp.lvdsmanufacturerpointer + lth.headerlen + lth.recordlen * lvdsmanufacturerindex; + switch (lth.lvds_ver) { + case 0x0a: + bios->fp.power_off_for_reset = bios->data[lvdsofs] & 1; + bios->fp.reset_after_pclk_change = bios->data[lvdsofs] & 2; + bios->fp.dual_link = bios->data[lvdsofs] & 4; + bios->fp.link_c_increment = bios->data[lvdsofs] & 8; + *if_is_24bit = bios->data[lvdsofs] & 16; + break; + case 0x30: + /* + * My money would be on there being a 24 bit interface bit in + * this table, but I have no example of a laptop bios with a + * 24 bit panel to confirm that. Hence we shout loudly if any + * bit other than bit 0 is set (I've not even seen bit 1) + */ + if (bios->data[lvdsofs] > 1) + NV_ERROR(dev, + "You have a very unusual laptop display; please report it\n"); + /* + * No sign of the "power off for reset" or "reset for panel + * on" bits, but it's safer to assume we should + */ + bios->fp.power_off_for_reset = true; + bios->fp.reset_after_pclk_change = true; + /* + * It's ok lvdsofs is wrong for nv4x edid case; dual_link is + * over-written, and BITbit1 isn't used + */ + bios->fp.dual_link = bios->data[lvdsofs] & 1; + bios->fp.BITbit1 = bios->data[lvdsofs] & 2; + bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10; + break; + case 0x40: + bios->fp.dual_link = bios->data[lvdsofs] & 1; + bios->fp.if_is_24bit = bios->data[lvdsofs] & 2; + bios->fp.strapless_is_24bit = bios->data[bios->fp.lvdsmanufacturerpointer + 4]; + bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10; + break; + } + + /* set dual_link flag for EDID case */ + if (pxclk && (chip_version < 0x25 || chip_version > 0x28)) + bios->fp.dual_link = (pxclk >= bios->fp.duallink_transition_clk); + + *dl = bios->fp.dual_link; + + return 0; +} + +static uint8_t * +bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent, + uint16_t record, int record_len, int record_nr) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + uint32_t entry; + uint16_t table; + int i, v; + + for (i = 0; i < record_nr; i++, record += record_len) { + table = ROM16(bios->data[record]); + if (!table) + continue; + entry = ROM32(bios->data[table]); + + v = (entry & 0x000f0000) >> 16; + if (!(v & dcbent->or)) + continue; + + v = (entry & 0x000000f0) >> 4; + if (v != dcbent->location) + continue; + + v = (entry & 0x0000000f); + if (v != dcbent->type) + continue; + + return &bios->data[table]; + } + + return NULL; +} + +void * +nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent, + int *length) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + uint8_t *table; + + if (!bios->display.dp_table_ptr) { + NV_ERROR(dev, "No pointer to DisplayPort table\n"); + return NULL; + } + table = &bios->data[bios->display.dp_table_ptr]; + + if (table[0] != 0x21) { + NV_ERROR(dev, "DisplayPort table version 0x%02x unknown\n", + table[0]); + return NULL; + } + + *length = table[4]; + return bios_output_config_match(dev, dcbent, + bios->display.dp_table_ptr + table[1], + table[2], table[3]); +} + +int +nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + uint32_t sub, int pxclk) +{ + /* + * The display script table is located by the BIT 'U' table. + * + * It contains an array of pointers to various tables describing + * a particular output type. The first 32-bits of the output + * tables contains similar information to a DCB entry, and is + * used to decide whether that particular table is suitable for + * the output you want to access. + * + * The "record header length" field here seems to indicate the + * offset of the first configuration entry in the output tables. + * This is 10 on most cards I've seen, but 12 has been witnessed + * on DP cards, and there's another script pointer within the + * header. + * + * offset + 0 ( 8 bits): version + * offset + 1 ( 8 bits): header length + * offset + 2 ( 8 bits): record length + * offset + 3 ( 8 bits): number of records + * offset + 4 ( 8 bits): record header length + * offset + 5 (16 bits): pointer to first output script table + */ + + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct init_exec iexec = {true, false}; + struct nvbios *bios = &dev_priv->VBIOS; + uint8_t *table = &bios->data[bios->display.script_table_ptr]; + uint8_t *otable = NULL; + uint16_t script; + int i = 0; + + if (!bios->display.script_table_ptr) { + NV_ERROR(dev, "No pointer to output script table\n"); + return 1; + } + + /* + * Nothing useful has been in any of the pre-2.0 tables I've seen, + * so until they are, we really don't need to care. + */ + if (table[0] < 0x20) + return 1; + + if (table[0] != 0x20 && table[0] != 0x21) { + NV_ERROR(dev, "Output script table version 0x%02x unknown\n", + table[0]); + return 1; + } + + /* + * The output script tables describing a particular output type + * look as follows: + * + * offset + 0 (32 bits): output this table matches (hash of DCB) + * offset + 4 ( 8 bits): unknown + * offset + 5 ( 8 bits): number of configurations + * offset + 6 (16 bits): pointer to some script + * offset + 8 (16 bits): pointer to some script + * + * headerlen == 10 + * offset + 10 : configuration 0 + * + * headerlen == 12 + * offset + 10 : pointer to some script + * offset + 12 : configuration 0 + * + * Each config entry is as follows: + * + * offset + 0 (16 bits): unknown, assumed to be a match value + * offset + 2 (16 bits): pointer to script table (clock set?) + * offset + 4 (16 bits): pointer to script table (reset?) + * + * There doesn't appear to be a count value to say how many + * entries exist in each script table, instead, a 0 value in + * the first 16-bit word seems to indicate both the end of the + * list and the default entry. The second 16-bit word in the + * script tables is a pointer to the script to execute. + */ + + NV_DEBUG(dev, "Searching for output entry for %d %d %d\n", + dcbent->type, dcbent->location, dcbent->or); + otable = bios_output_config_match(dev, dcbent, table[1] + + bios->display.script_table_ptr, + table[2], table[3]); + if (!otable) { + NV_ERROR(dev, "Couldn't find matching output script table\n"); + return 1; + } + + if (pxclk < -2 || pxclk > 0) { + /* Try to find matching script table entry */ + for (i = 0; i < otable[5]; i++) { + if (ROM16(otable[table[4] + i*6]) == sub) + break; + } + + if (i == otable[5]) { + NV_ERROR(dev, "Table 0x%04x not found for %d/%d, " + "using first\n", + sub, dcbent->type, dcbent->or); + i = 0; + } + } + + bios->display.output = dcbent; + + if (pxclk == 0) { + script = ROM16(otable[6]); + if (!script) { + NV_DEBUG(dev, "output script 0 not found\n"); + return 1; + } + + NV_TRACE(dev, "0x%04X: parsing output script 0\n", script); + parse_init_table(bios, script, &iexec); + } else + if (pxclk == -1) { + script = ROM16(otable[8]); + if (!script) { + NV_DEBUG(dev, "output script 1 not found\n"); + return 1; + } + + NV_TRACE(dev, "0x%04X: parsing output script 1\n", script); + parse_init_table(bios, script, &iexec); + } else + if (pxclk == -2) { + if (table[4] >= 12) + script = ROM16(otable[10]); + else + script = 0; + if (!script) { + NV_DEBUG(dev, "output script 2 not found\n"); + return 1; + } + + NV_TRACE(dev, "0x%04X: parsing output script 2\n", script); + parse_init_table(bios, script, &iexec); + } else + if (pxclk > 0) { + script = ROM16(otable[table[4] + i*6 + 2]); + if (script) + script = clkcmptable(bios, script, pxclk); + if (!script) { + NV_ERROR(dev, "clock script 0 not found\n"); + return 1; + } + + NV_TRACE(dev, "0x%04X: parsing clock script 0\n", script); + parse_init_table(bios, script, &iexec); + } else + if (pxclk < 0) { + script = ROM16(otable[table[4] + i*6 + 4]); + if (script) + script = clkcmptable(bios, script, -pxclk); + if (!script) { + NV_DEBUG(dev, "clock script 1 not found\n"); + return 1; + } + + NV_TRACE(dev, "0x%04X: parsing clock script 1\n", script); + parse_init_table(bios, script, &iexec); + } + + return 0; +} + + +int run_tmds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, int pxclk) +{ + /* + * the pxclk parameter is in kHz + * + * This runs the TMDS regs setting code found on BIT bios cards + * + * For ffs(or) == 1 use the first table, for ffs(or) == 2 and + * ffs(or) == 3, use the second. + */ + + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + int cv = bios->pub.chip_version; + uint16_t clktable = 0, scriptptr; + uint32_t sel_clk_binding, sel_clk; + + /* pre-nv17 off-chip tmds uses scripts, post nv17 doesn't */ + if (cv >= 0x17 && cv != 0x1a && cv != 0x20 && + dcbent->location != DCB_LOC_ON_CHIP) + return 0; + + switch (ffs(dcbent->or)) { + case 1: + clktable = bios->tmds.output0_script_ptr; + break; + case 2: + case 3: + clktable = bios->tmds.output1_script_ptr; + break; + } + + if (!clktable) { + NV_ERROR(dev, "Pixel clock comparison table not found\n"); + return -EINVAL; + } + + scriptptr = clkcmptable(bios, clktable, pxclk); + + if (!scriptptr) { + NV_ERROR(dev, "TMDS output init script not found\n"); + return -ENOENT; + } + + /* don't let script change pll->head binding */ + sel_clk_binding = bios_rd32(bios, NV_PRAMDAC_SEL_CLK) & 0x50000; + run_digital_op_script(dev, scriptptr, dcbent, head, pxclk >= 165000); + sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000; + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding); + + return 0; +} + +int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims *pll_lim) +{ + /* + * PLL limits table + * + * Version 0x10: NV30, NV31 + * One byte header (version), one record of 24 bytes + * Version 0x11: NV36 - Not implemented + * Seems to have same record style as 0x10, but 3 records rather than 1 + * Version 0x20: Found on Geforce 6 cards + * Trivial 4 byte BIT header. 31 (0x1f) byte record length + * Version 0x21: Found on Geforce 7, 8 and some Geforce 6 cards + * 5 byte header, fifth byte of unknown purpose. 35 (0x23) byte record + * length in general, some (integrated) have an extra configuration byte + * Version 0x30: Found on Geforce 8, separates the register mapping + * from the limits tables. + */ + + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + int cv = bios->pub.chip_version, pllindex = 0; + uint8_t pll_lim_ver = 0, headerlen = 0, recordlen = 0, entries = 0; + uint32_t crystal_strap_mask, crystal_straps; + + if (!bios->pll_limit_tbl_ptr) { + if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 || + cv >= 0x40) { + NV_ERROR(dev, "Pointer to PLL limits table invalid\n"); + return -EINVAL; + } + } else + pll_lim_ver = bios->data[bios->pll_limit_tbl_ptr]; + + crystal_strap_mask = 1 << 6; + /* open coded dev->twoHeads test */ + if (cv > 0x10 && cv != 0x15 && cv != 0x1a && cv != 0x20) + crystal_strap_mask |= 1 << 22; + crystal_straps = nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & + crystal_strap_mask; + + switch (pll_lim_ver) { + /* + * We use version 0 to indicate a pre limit table bios (single stage + * pll) and load the hard coded limits instead. + */ + case 0: + break; + case 0x10: + case 0x11: + /* + * Strictly v0x11 has 3 entries, but the last two don't seem + * to get used. + */ + headerlen = 1; + recordlen = 0x18; + entries = 1; + pllindex = 0; + break; + case 0x20: + case 0x21: + case 0x30: + case 0x40: + headerlen = bios->data[bios->pll_limit_tbl_ptr + 1]; + recordlen = bios->data[bios->pll_limit_tbl_ptr + 2]; + entries = bios->data[bios->pll_limit_tbl_ptr + 3]; + break; + default: + NV_ERROR(dev, "PLL limits table revision 0x%X not currently " + "supported\n", pll_lim_ver); + return -ENOSYS; + } + + /* initialize all members to zero */ + memset(pll_lim, 0, sizeof(struct pll_lims)); + + if (pll_lim_ver == 0x10 || pll_lim_ver == 0x11) { + uint8_t *pll_rec = &bios->data[bios->pll_limit_tbl_ptr + headerlen + recordlen * pllindex]; + + pll_lim->vco1.minfreq = ROM32(pll_rec[0]); + pll_lim->vco1.maxfreq = ROM32(pll_rec[4]); + pll_lim->vco2.minfreq = ROM32(pll_rec[8]); + pll_lim->vco2.maxfreq = ROM32(pll_rec[12]); + pll_lim->vco1.min_inputfreq = ROM32(pll_rec[16]); + pll_lim->vco2.min_inputfreq = ROM32(pll_rec[20]); + pll_lim->vco1.max_inputfreq = pll_lim->vco2.max_inputfreq = INT_MAX; + + /* these values taken from nv30/31/36 */ + pll_lim->vco1.min_n = 0x1; + if (cv == 0x36) + pll_lim->vco1.min_n = 0x5; + pll_lim->vco1.max_n = 0xff; + pll_lim->vco1.min_m = 0x1; + pll_lim->vco1.max_m = 0xd; + pll_lim->vco2.min_n = 0x4; + /* + * On nv30, 31, 36 (i.e. all cards with two stage PLLs with this + * table version (apart from nv35)), N2 is compared to + * maxN2 (0x46) and 10 * maxM2 (0x4), so set maxN2 to 0x28 and + * save a comparison + */ + pll_lim->vco2.max_n = 0x28; + if (cv == 0x30 || cv == 0x35) + /* only 5 bits available for N2 on nv30/35 */ + pll_lim->vco2.max_n = 0x1f; + pll_lim->vco2.min_m = 0x1; + pll_lim->vco2.max_m = 0x4; + pll_lim->max_log2p = 0x7; + pll_lim->max_usable_log2p = 0x6; + } else if (pll_lim_ver == 0x20 || pll_lim_ver == 0x21) { + uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen; + uint32_t reg = 0; /* default match */ + uint8_t *pll_rec; + int i; + + /* + * First entry is default match, if nothing better. warn if + * reg field nonzero + */ + if (ROM32(bios->data[plloffs])) + NV_WARN(dev, "Default PLL limit entry has non-zero " + "register field\n"); + + if (limit_match > MAX_PLL_TYPES) + /* we've been passed a reg as the match */ + reg = limit_match; + else /* limit match is a pll type */ + for (i = 1; i < entries && !reg; i++) { + uint32_t cmpreg = ROM32(bios->data[plloffs + recordlen * i]); + + if (limit_match == NVPLL && + (cmpreg == NV_PRAMDAC_NVPLL_COEFF || cmpreg == 0x4000)) + reg = cmpreg; + if (limit_match == MPLL && + (cmpreg == NV_PRAMDAC_MPLL_COEFF || cmpreg == 0x4020)) + reg = cmpreg; + if (limit_match == VPLL1 && + (cmpreg == NV_PRAMDAC_VPLL_COEFF || cmpreg == 0x4010)) + reg = cmpreg; + if (limit_match == VPLL2 && + (cmpreg == NV_RAMDAC_VPLL2 || cmpreg == 0x4018)) + reg = cmpreg; + } + + for (i = 1; i < entries; i++) + if (ROM32(bios->data[plloffs + recordlen * i]) == reg) { + pllindex = i; + break; + } + + pll_rec = &bios->data[plloffs + recordlen * pllindex]; + + BIOSLOG(bios, "Loading PLL limits for reg 0x%08x\n", + pllindex ? reg : 0); + + /* + * Frequencies are stored in tables in MHz, kHz are more + * useful, so we convert. + */ + + /* What output frequencies can each VCO generate? */ + pll_lim->vco1.minfreq = ROM16(pll_rec[4]) * 1000; + pll_lim->vco1.maxfreq = ROM16(pll_rec[6]) * 1000; + pll_lim->vco2.minfreq = ROM16(pll_rec[8]) * 1000; + pll_lim->vco2.maxfreq = ROM16(pll_rec[10]) * 1000; + + /* What input frequencies they accept (past the m-divider)? */ + pll_lim->vco1.min_inputfreq = ROM16(pll_rec[12]) * 1000; + pll_lim->vco2.min_inputfreq = ROM16(pll_rec[14]) * 1000; + pll_lim->vco1.max_inputfreq = ROM16(pll_rec[16]) * 1000; + pll_lim->vco2.max_inputfreq = ROM16(pll_rec[18]) * 1000; + + /* What values are accepted as multiplier and divider? */ + pll_lim->vco1.min_n = pll_rec[20]; + pll_lim->vco1.max_n = pll_rec[21]; + pll_lim->vco1.min_m = pll_rec[22]; + pll_lim->vco1.max_m = pll_rec[23]; + pll_lim->vco2.min_n = pll_rec[24]; + pll_lim->vco2.max_n = pll_rec[25]; + pll_lim->vco2.min_m = pll_rec[26]; + pll_lim->vco2.max_m = pll_rec[27]; + + pll_lim->max_usable_log2p = pll_lim->max_log2p = pll_rec[29]; + if (pll_lim->max_log2p > 0x7) + /* pll decoding in nv_hw.c assumes never > 7 */ + NV_WARN(dev, "Max log2 P value greater than 7 (%d)\n", + pll_lim->max_log2p); + if (cv < 0x60) + pll_lim->max_usable_log2p = 0x6; + pll_lim->log2p_bias = pll_rec[30]; + + if (recordlen > 0x22) + pll_lim->refclk = ROM32(pll_rec[31]); + + if (recordlen > 0x23 && pll_rec[35]) + NV_WARN(dev, + "Bits set in PLL configuration byte (%x)\n", + pll_rec[35]); + + /* C51 special not seen elsewhere */ + if (cv == 0x51 && !pll_lim->refclk) { + uint32_t sel_clk = bios_rd32(bios, NV_PRAMDAC_SEL_CLK); + + if (((limit_match == NV_PRAMDAC_VPLL_COEFF || limit_match == VPLL1) && sel_clk & 0x20) || + ((limit_match == NV_RAMDAC_VPLL2 || limit_match == VPLL2) && sel_clk & 0x80)) { + if (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_CHIP_ID_INDEX) < 0xa3) + pll_lim->refclk = 200000; + else + pll_lim->refclk = 25000; + } + } + } else if (pll_lim_ver == 0x30) { /* ver 0x30 */ + uint8_t *entry = &bios->data[bios->pll_limit_tbl_ptr + headerlen]; + uint8_t *record = NULL; + int i; + + BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", + limit_match); + + for (i = 0; i < entries; i++, entry += recordlen) { + if (ROM32(entry[3]) == limit_match) { + record = &bios->data[ROM16(entry[1])]; + break; + } + } + + if (!record) { + NV_ERROR(dev, "Register 0x%08x not found in PLL " + "limits table", limit_match); + return -ENOENT; + } + + pll_lim->vco1.minfreq = ROM16(record[0]) * 1000; + pll_lim->vco1.maxfreq = ROM16(record[2]) * 1000; + pll_lim->vco2.minfreq = ROM16(record[4]) * 1000; + pll_lim->vco2.maxfreq = ROM16(record[6]) * 1000; + pll_lim->vco1.min_inputfreq = ROM16(record[8]) * 1000; + pll_lim->vco2.min_inputfreq = ROM16(record[10]) * 1000; + pll_lim->vco1.max_inputfreq = ROM16(record[12]) * 1000; + pll_lim->vco2.max_inputfreq = ROM16(record[14]) * 1000; + pll_lim->vco1.min_n = record[16]; + pll_lim->vco1.max_n = record[17]; + pll_lim->vco1.min_m = record[18]; + pll_lim->vco1.max_m = record[19]; + pll_lim->vco2.min_n = record[20]; + pll_lim->vco2.max_n = record[21]; + pll_lim->vco2.min_m = record[22]; + pll_lim->vco2.max_m = record[23]; + pll_lim->max_usable_log2p = pll_lim->max_log2p = record[25]; + pll_lim->log2p_bias = record[27]; + pll_lim->refclk = ROM32(record[28]); + } else if (pll_lim_ver) { /* ver 0x40 */ + uint8_t *entry = &bios->data[bios->pll_limit_tbl_ptr + headerlen]; + uint8_t *record = NULL; + int i; + + BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", + limit_match); + + for (i = 0; i < entries; i++, entry += recordlen) { + if (ROM32(entry[3]) == limit_match) { + record = &bios->data[ROM16(entry[1])]; + break; + } + } + + if (!record) { + NV_ERROR(dev, "Register 0x%08x not found in PLL " + "limits table", limit_match); + return -ENOENT; + } + + pll_lim->vco1.minfreq = ROM16(record[0]) * 1000; + pll_lim->vco1.maxfreq = ROM16(record[2]) * 1000; + pll_lim->vco1.min_inputfreq = ROM16(record[4]) * 1000; + pll_lim->vco1.max_inputfreq = ROM16(record[6]) * 1000; + pll_lim->vco1.min_m = record[8]; + pll_lim->vco1.max_m = record[9]; + pll_lim->vco1.min_n = record[10]; + pll_lim->vco1.max_n = record[11]; + pll_lim->min_p = record[12]; + pll_lim->max_p = record[13]; + /* where did this go to?? */ + if (limit_match == 0x00614100 || limit_match == 0x00614900) + pll_lim->refclk = 27000; + else + pll_lim->refclk = 100000; + } + + /* + * By now any valid limit table ought to have set a max frequency for + * vco1, so if it's zero it's either a pre limit table bios, or one + * with an empty limit table (seen on nv18) + */ + if (!pll_lim->vco1.maxfreq) { + pll_lim->vco1.minfreq = bios->fminvco; + pll_lim->vco1.maxfreq = bios->fmaxvco; + pll_lim->vco1.min_inputfreq = 0; + pll_lim->vco1.max_inputfreq = INT_MAX; + pll_lim->vco1.min_n = 0x1; + pll_lim->vco1.max_n = 0xff; + pll_lim->vco1.min_m = 0x1; + if (crystal_straps == 0) { + /* nv05 does this, nv11 doesn't, nv10 unknown */ + if (cv < 0x11) + pll_lim->vco1.min_m = 0x7; + pll_lim->vco1.max_m = 0xd; + } else { + if (cv < 0x11) + pll_lim->vco1.min_m = 0x8; + pll_lim->vco1.max_m = 0xe; + } + if (cv < 0x17 || cv == 0x1a || cv == 0x20) + pll_lim->max_log2p = 4; + else + pll_lim->max_log2p = 5; + pll_lim->max_usable_log2p = pll_lim->max_log2p; + } + + if (!pll_lim->refclk) + switch (crystal_straps) { + case 0: + pll_lim->refclk = 13500; + break; + case (1 << 6): + pll_lim->refclk = 14318; + break; + case (1 << 22): + pll_lim->refclk = 27000; + break; + case (1 << 22 | 1 << 6): + pll_lim->refclk = 25000; + break; + } + +#if 0 /* for easy debugging */ + ErrorF("pll.vco1.minfreq: %d\n", pll_lim->vco1.minfreq); + ErrorF("pll.vco1.maxfreq: %d\n", pll_lim->vco1.maxfreq); + ErrorF("pll.vco2.minfreq: %d\n", pll_lim->vco2.minfreq); + ErrorF("pll.vco2.maxfreq: %d\n", pll_lim->vco2.maxfreq); + + ErrorF("pll.vco1.min_inputfreq: %d\n", pll_lim->vco1.min_inputfreq); + ErrorF("pll.vco1.max_inputfreq: %d\n", pll_lim->vco1.max_inputfreq); + ErrorF("pll.vco2.min_inputfreq: %d\n", pll_lim->vco2.min_inputfreq); + ErrorF("pll.vco2.max_inputfreq: %d\n", pll_lim->vco2.max_inputfreq); + + ErrorF("pll.vco1.min_n: %d\n", pll_lim->vco1.min_n); + ErrorF("pll.vco1.max_n: %d\n", pll_lim->vco1.max_n); + ErrorF("pll.vco1.min_m: %d\n", pll_lim->vco1.min_m); + ErrorF("pll.vco1.max_m: %d\n", pll_lim->vco1.max_m); + ErrorF("pll.vco2.min_n: %d\n", pll_lim->vco2.min_n); + ErrorF("pll.vco2.max_n: %d\n", pll_lim->vco2.max_n); + ErrorF("pll.vco2.min_m: %d\n", pll_lim->vco2.min_m); + ErrorF("pll.vco2.max_m: %d\n", pll_lim->vco2.max_m); + + ErrorF("pll.max_log2p: %d\n", pll_lim->max_log2p); + ErrorF("pll.log2p_bias: %d\n", pll_lim->log2p_bias); + + ErrorF("pll.refclk: %d\n", pll_lim->refclk); +#endif + + return 0; +} + +static void parse_bios_version(struct drm_device *dev, struct nvbios *bios, uint16_t offset) +{ + /* + * offset + 0 (8 bits): Micro version + * offset + 1 (8 bits): Minor version + * offset + 2 (8 bits): Chip version + * offset + 3 (8 bits): Major version + */ + + bios->major_version = bios->data[offset + 3]; + bios->pub.chip_version = bios->data[offset + 2]; + NV_TRACE(dev, "Bios version %02x.%02x.%02x.%02x\n", + bios->data[offset + 3], bios->data[offset + 2], + bios->data[offset + 1], bios->data[offset]); +} + +static void parse_script_table_pointers(struct nvbios *bios, uint16_t offset) +{ + /* + * Parses the init table segment for pointers used in script execution. + * + * offset + 0 (16 bits): init script tables pointer + * offset + 2 (16 bits): macro index table pointer + * offset + 4 (16 bits): macro table pointer + * offset + 6 (16 bits): condition table pointer + * offset + 8 (16 bits): io condition table pointer + * offset + 10 (16 bits): io flag condition table pointer + * offset + 12 (16 bits): init function table pointer + */ + + bios->init_script_tbls_ptr = ROM16(bios->data[offset]); + bios->macro_index_tbl_ptr = ROM16(bios->data[offset + 2]); + bios->macro_tbl_ptr = ROM16(bios->data[offset + 4]); + bios->condition_tbl_ptr = ROM16(bios->data[offset + 6]); + bios->io_condition_tbl_ptr = ROM16(bios->data[offset + 8]); + bios->io_flag_condition_tbl_ptr = ROM16(bios->data[offset + 10]); + bios->init_function_tbl_ptr = ROM16(bios->data[offset + 12]); +} + +static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) +{ + /* + * Parses the load detect values for g80 cards. + * + * offset + 0 (16 bits): loadval table pointer + */ + + uint16_t load_table_ptr; + uint8_t version, headerlen, entrylen, num_entries; + + if (bitentry->length != 3) { + NV_ERROR(dev, "Do not understand BIT A table\n"); + return -EINVAL; + } + + load_table_ptr = ROM16(bios->data[bitentry->offset]); + + if (load_table_ptr == 0x0) { + NV_ERROR(dev, "Pointer to BIT loadval table invalid\n"); + return -EINVAL; + } + + version = bios->data[load_table_ptr]; + + if (version != 0x10) { + NV_ERROR(dev, "BIT loadval table version %d.%d not supported\n", + version >> 4, version & 0xF); + return -ENOSYS; + } + + headerlen = bios->data[load_table_ptr + 1]; + entrylen = bios->data[load_table_ptr + 2]; + num_entries = bios->data[load_table_ptr + 3]; + + if (headerlen != 4 || entrylen != 4 || num_entries != 2) { + NV_ERROR(dev, "Do not understand BIT loadval table\n"); + return -EINVAL; + } + + /* First entry is normal dac, 2nd tv-out perhaps? */ + bios->pub.dactestval = ROM32(bios->data[load_table_ptr + headerlen]) & 0x3ff; + + return 0; +} + +static int parse_bit_C_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) +{ + /* + * offset + 8 (16 bits): PLL limits table pointer + * + * There's more in here, but that's unknown. + */ + + if (bitentry->length < 10) { + NV_ERROR(dev, "Do not understand BIT C table\n"); + return -EINVAL; + } + + bios->pll_limit_tbl_ptr = ROM16(bios->data[bitentry->offset + 8]); + + return 0; +} + +static int parse_bit_display_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) +{ + /* + * Parses the flat panel table segment that the bit entry points to. + * Starting at bitentry->offset: + * + * offset + 0 (16 bits): ??? table pointer - seems to have 18 byte + * records beginning with a freq. + * offset + 2 (16 bits): mode table pointer + */ + + if (bitentry->length != 4) { + NV_ERROR(dev, "Do not understand BIT display table\n"); + return -EINVAL; + } + + bios->fp.fptablepointer = ROM16(bios->data[bitentry->offset + 2]); + + return 0; +} + +static int parse_bit_init_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) +{ + /* + * Parses the init table segment that the bit entry points to. + * + * See parse_script_table_pointers for layout + */ + + if (bitentry->length < 14) { + NV_ERROR(dev, "Do not understand init table\n"); + return -EINVAL; + } + + parse_script_table_pointers(bios, bitentry->offset); + + if (bitentry->length >= 16) + bios->some_script_ptr = ROM16(bios->data[bitentry->offset + 14]); + if (bitentry->length >= 18) + bios->init96_tbl_ptr = ROM16(bios->data[bitentry->offset + 16]); + + return 0; +} + +static int parse_bit_i_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) +{ + /* + * BIT 'i' (info?) table + * + * offset + 0 (32 bits): BIOS version dword (as in B table) + * offset + 5 (8 bits): BIOS feature byte (same as for BMP?) + * offset + 13 (16 bits): pointer to table containing DAC load + * detection comparison values + * + * There's other things in the table, purpose unknown + */ + + uint16_t daccmpoffset; + uint8_t dacver, dacheaderlen; + + if (bitentry->length < 6) { + NV_ERROR(dev, "BIT i table too short for needed information\n"); + return -EINVAL; + } + + parse_bios_version(dev, bios, bitentry->offset); + + /* + * bit 4 seems to indicate a mobile bios (doesn't suffer from BMP's + * Quadro identity crisis), other bits possibly as for BMP feature byte + */ + bios->feature_byte = bios->data[bitentry->offset + 5]; + bios->is_mobile = bios->feature_byte & FEATURE_MOBILE; + + if (bitentry->length < 15) { + NV_WARN(dev, "BIT i table not long enough for DAC load " + "detection comparison table\n"); + return -EINVAL; + } + + daccmpoffset = ROM16(bios->data[bitentry->offset + 13]); + + /* doesn't exist on g80 */ + if (!daccmpoffset) + return 0; + + /* + * The first value in the table, following the header, is the + * comparison value, the second entry is a comparison value for + * TV load detection. + */ + + dacver = bios->data[daccmpoffset]; + dacheaderlen = bios->data[daccmpoffset + 1]; + + if (dacver != 0x00 && dacver != 0x10) { + NV_WARN(dev, "DAC load detection comparison table version " + "%d.%d not known\n", dacver >> 4, dacver & 0xf); + return -ENOSYS; + } + + bios->pub.dactestval = ROM32(bios->data[daccmpoffset + dacheaderlen]); + bios->pub.tvdactestval = ROM32(bios->data[daccmpoffset + dacheaderlen + 4]); + + return 0; +} + +static int parse_bit_lvds_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) +{ + /* + * Parses the LVDS table segment that the bit entry points to. + * Starting at bitentry->offset: + * + * offset + 0 (16 bits): LVDS strap xlate table pointer + */ + + if (bitentry->length != 2) { + NV_ERROR(dev, "Do not understand BIT LVDS table\n"); + return -EINVAL; + } + + /* + * No idea if it's still called the LVDS manufacturer table, but + * the concept's close enough. + */ + bios->fp.lvdsmanufacturerpointer = ROM16(bios->data[bitentry->offset]); + + return 0; +} + +static int +parse_bit_M_tbl_entry(struct drm_device *dev, struct nvbios *bios, + struct bit_entry *bitentry) +{ + /* + * offset + 2 (8 bits): number of options in an + * INIT_RAM_RESTRICT_ZM_REG_GROUP opcode option set + * offset + 3 (16 bits): pointer to strap xlate table for RAM + * restrict option selection + * + * There's a bunch of bits in this table other than the RAM restrict + * stuff that we don't use - their use currently unknown + */ + + uint16_t rr_strap_xlat; + uint8_t rr_group_count; + int i; + + /* + * Older bios versions don't have a sufficiently long table for + * what we want + */ + if (bitentry->length < 0x5) + return 0; + + if (bitentry->id[1] < 2) { + rr_group_count = bios->data[bitentry->offset + 2]; + rr_strap_xlat = ROM16(bios->data[bitentry->offset + 3]); + } else { + rr_group_count = bios->data[bitentry->offset + 0]; + rr_strap_xlat = ROM16(bios->data[bitentry->offset + 1]); + } + + /* adjust length of INIT_87 */ + for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != 0x87); i++); + itbl_entry[i].length += rr_group_count * 4; + + /* set up multiplier for INIT_RAM_RESTRICT_ZM_REG_GROUP */ + for (; itbl_entry[i].name && (itbl_entry[i].id != 0x8f); i++); + itbl_entry[i].length_multiplier = rr_group_count * 4; + + init_ram_restrict_zm_reg_group_blocklen = itbl_entry[i].length_multiplier; + bios->ram_restrict_tbl_ptr = rr_strap_xlat; + + return 0; +} + +static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) +{ + /* + * Parses the pointer to the TMDS table + * + * Starting at bitentry->offset: + * + * offset + 0 (16 bits): TMDS table pointer + * + * The TMDS table is typically found just before the DCB table, with a + * characteristic signature of 0x11,0x13 (1.1 being version, 0x13 being + * length?) + * + * At offset +7 is a pointer to a script, which I don't know how to + * run yet. + * At offset +9 is a pointer to another script, likewise + * Offset +11 has a pointer to a table where the first word is a pxclk + * frequency and the second word a pointer to a script, which should be + * run if the comparison pxclk frequency is less than the pxclk desired. + * This repeats for decreasing comparison frequencies + * Offset +13 has a pointer to a similar table + * The selection of table (and possibly +7/+9 script) is dictated by + * "or" from the DCB. + */ + + uint16_t tmdstableptr, script1, script2; + + if (bitentry->length != 2) { + NV_ERROR(dev, "Do not understand BIT TMDS table\n"); + return -EINVAL; + } + + tmdstableptr = ROM16(bios->data[bitentry->offset]); + + if (tmdstableptr == 0x0) { + NV_ERROR(dev, "Pointer to TMDS table invalid\n"); + return -EINVAL; + } + + /* nv50+ has v2.0, but we don't parse it atm */ + if (bios->data[tmdstableptr] != 0x11) { + NV_WARN(dev, + "TMDS table revision %d.%d not currently supported\n", + bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf); + return -ENOSYS; + } + + /* + * These two scripts are odd: they don't seem to get run even when + * they are not stubbed. + */ + script1 = ROM16(bios->data[tmdstableptr + 7]); + script2 = ROM16(bios->data[tmdstableptr + 9]); + if (bios->data[script1] != 'q' || bios->data[script2] != 'q') + NV_WARN(dev, "TMDS table script pointers not stubbed\n"); + + bios->tmds.output0_script_ptr = ROM16(bios->data[tmdstableptr + 11]); + bios->tmds.output1_script_ptr = ROM16(bios->data[tmdstableptr + 13]); + + return 0; +} + +static int +parse_bit_U_tbl_entry(struct drm_device *dev, struct nvbios *bios, + struct bit_entry *bitentry) +{ + /* + * Parses the pointer to the G80 output script tables + * + * Starting at bitentry->offset: + * + * offset + 0 (16 bits): output script table pointer + */ + + uint16_t outputscripttableptr; + + if (bitentry->length != 3) { + NV_ERROR(dev, "Do not understand BIT U table\n"); + return -EINVAL; + } + + outputscripttableptr = ROM16(bios->data[bitentry->offset]); + bios->display.script_table_ptr = outputscripttableptr; + return 0; +} + +static int +parse_bit_displayport_tbl_entry(struct drm_device *dev, struct nvbios *bios, + struct bit_entry *bitentry) +{ + bios->display.dp_table_ptr = ROM16(bios->data[bitentry->offset]); + return 0; +} + +struct bit_table { + const char id; + int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *); +}; + +#define BIT_TABLE(id, funcid) ((struct bit_table){ id, parse_bit_##funcid##_tbl_entry }) + +static int +parse_bit_table(struct nvbios *bios, const uint16_t bitoffset, + struct bit_table *table) +{ + struct drm_device *dev = bios->dev; + uint8_t maxentries = bios->data[bitoffset + 4]; + int i, offset; + struct bit_entry bitentry; + + for (i = 0, offset = bitoffset + 6; i < maxentries; i++, offset += 6) { + bitentry.id[0] = bios->data[offset]; + + if (bitentry.id[0] != table->id) + continue; + + bitentry.id[1] = bios->data[offset + 1]; + bitentry.length = ROM16(bios->data[offset + 2]); + bitentry.offset = ROM16(bios->data[offset + 4]); + + return table->parse_fn(dev, bios, &bitentry); + } + + NV_INFO(dev, "BIT table '%c' not found\n", table->id); + return -ENOSYS; +} + +static int +parse_bit_structure(struct nvbios *bios, const uint16_t bitoffset) +{ + int ret; + + /* + * The only restriction on parsing order currently is having 'i' first + * for use of bios->*_version or bios->feature_byte while parsing; + * functions shouldn't be actually *doing* anything apart from pulling + * data from the image into the bios struct, thus no interdependencies + */ + ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('i', i)); + if (ret) /* info? */ + return ret; + if (bios->major_version >= 0x60) /* g80+ */ + parse_bit_table(bios, bitoffset, &BIT_TABLE('A', A)); + ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('C', C)); + if (ret) + return ret; + parse_bit_table(bios, bitoffset, &BIT_TABLE('D', display)); + ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('I', init)); + if (ret) + return ret; + parse_bit_table(bios, bitoffset, &BIT_TABLE('M', M)); /* memory? */ + parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds)); + parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds)); + parse_bit_table(bios, bitoffset, &BIT_TABLE('U', U)); + parse_bit_table(bios, bitoffset, &BIT_TABLE('d', displayport)); + + return 0; +} + +static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsigned int offset) +{ + /* + * Parses the BMP structure for useful things, but does not act on them + * + * offset + 5: BMP major version + * offset + 6: BMP minor version + * offset + 9: BMP feature byte + * offset + 10: BCD encoded BIOS version + * + * offset + 18: init script table pointer (for bios versions < 5.10h) + * offset + 20: extra init script table pointer (for bios + * versions < 5.10h) + * + * offset + 24: memory init table pointer (used on early bios versions) + * offset + 26: SDR memory sequencing setup data table + * offset + 28: DDR memory sequencing setup data table + * + * offset + 54: index of I2C CRTC pair to use for CRT output + * offset + 55: index of I2C CRTC pair to use for TV output + * offset + 56: index of I2C CRTC pair to use for flat panel output + * offset + 58: write CRTC index for I2C pair 0 + * offset + 59: read CRTC index for I2C pair 0 + * offset + 60: write CRTC index for I2C pair 1 + * offset + 61: read CRTC index for I2C pair 1 + * + * offset + 67: maximum internal PLL frequency (single stage PLL) + * offset + 71: minimum internal PLL frequency (single stage PLL) + * + * offset + 75: script table pointers, as described in + * parse_script_table_pointers + * + * offset + 89: TMDS single link output A table pointer + * offset + 91: TMDS single link output B table pointer + * offset + 95: LVDS single link output A table pointer + * offset + 105: flat panel timings table pointer + * offset + 107: flat panel strapping translation table pointer + * offset + 117: LVDS manufacturer panel config table pointer + * offset + 119: LVDS manufacturer strapping translation table pointer + * + * offset + 142: PLL limits table pointer + * + * offset + 156: minimum pixel clock for LVDS dual link + */ + + uint8_t *bmp = &bios->data[offset], bmp_version_major, bmp_version_minor; + uint16_t bmplength; + uint16_t legacy_scripts_offset, legacy_i2c_offset; + + /* load needed defaults in case we can't parse this info */ + bios->bdcb.dcb.i2c[0].write = NV_CIO_CRE_DDC_WR__INDEX; + bios->bdcb.dcb.i2c[0].read = NV_CIO_CRE_DDC_STATUS__INDEX; + bios->bdcb.dcb.i2c[1].write = NV_CIO_CRE_DDC0_WR__INDEX; + bios->bdcb.dcb.i2c[1].read = NV_CIO_CRE_DDC0_STATUS__INDEX; + bios->pub.digital_min_front_porch = 0x4b; + bios->fmaxvco = 256000; + bios->fminvco = 128000; + bios->fp.duallink_transition_clk = 90000; + + bmp_version_major = bmp[5]; + bmp_version_minor = bmp[6]; + + NV_TRACE(dev, "BMP version %d.%d\n", + bmp_version_major, bmp_version_minor); + + /* + * Make sure that 0x36 is blank and can't be mistaken for a DCB + * pointer on early versions + */ + if (bmp_version_major < 5) + *(uint16_t *)&bios->data[0x36] = 0; + + /* + * Seems that the minor version was 1 for all major versions prior + * to 5. Version 6 could theoretically exist, but I suspect BIT + * happened instead. + */ + if ((bmp_version_major < 5 && bmp_version_minor != 1) || bmp_version_major > 5) { + NV_ERROR(dev, "You have an unsupported BMP version. " + "Please send in your bios\n"); + return -ENOSYS; + } + + if (bmp_version_major == 0) + /* nothing that's currently useful in this version */ + return 0; + else if (bmp_version_major == 1) + bmplength = 44; /* exact for 1.01 */ + else if (bmp_version_major == 2) + bmplength = 48; /* exact for 2.01 */ + else if (bmp_version_major == 3) + bmplength = 54; + /* guessed - mem init tables added in this version */ + else if (bmp_version_major == 4 || bmp_version_minor < 0x1) + /* don't know if 5.0 exists... */ + bmplength = 62; + /* guessed - BMP I2C indices added in version 4*/ + else if (bmp_version_minor < 0x6) + bmplength = 67; /* exact for 5.01 */ + else if (bmp_version_minor < 0x10) + bmplength = 75; /* exact for 5.06 */ + else if (bmp_version_minor == 0x10) + bmplength = 89; /* exact for 5.10h */ + else if (bmp_version_minor < 0x14) + bmplength = 118; /* exact for 5.11h */ + else if (bmp_version_minor < 0x24) + /* + * Not sure of version where pll limits came in; + * certainly exist by 0x24 though. + */ + /* length not exact: this is long enough to get lvds members */ + bmplength = 123; + else if (bmp_version_minor < 0x27) + /* + * Length not exact: this is long enough to get pll limit + * member + */ + bmplength = 144; + else + /* + * Length not exact: this is long enough to get dual link + * transition clock. + */ + bmplength = 158; + + /* checksum */ + if (nv_cksum(bmp, 8)) { + NV_ERROR(dev, "Bad BMP checksum\n"); + return -EINVAL; + } + + /* + * Bit 4 seems to indicate either a mobile bios or a quadro card -- + * mobile behaviour consistent (nv11+), quadro only seen nv18gl-nv36gl + * (not nv10gl), bit 5 that the flat panel tables are present, and + * bit 6 a tv bios. + */ + bios->feature_byte = bmp[9]; + + parse_bios_version(dev, bios, offset + 10); + + if (bmp_version_major < 5 || bmp_version_minor < 0x10) + bios->old_style_init = true; + legacy_scripts_offset = 18; + if (bmp_version_major < 2) + legacy_scripts_offset -= 4; + bios->init_script_tbls_ptr = ROM16(bmp[legacy_scripts_offset]); + bios->extra_init_script_tbl_ptr = ROM16(bmp[legacy_scripts_offset + 2]); + + if (bmp_version_major > 2) { /* appears in BMP 3 */ + bios->legacy.mem_init_tbl_ptr = ROM16(bmp[24]); + bios->legacy.sdr_seq_tbl_ptr = ROM16(bmp[26]); + bios->legacy.ddr_seq_tbl_ptr = ROM16(bmp[28]); + } + + legacy_i2c_offset = 0x48; /* BMP version 2 & 3 */ + if (bmplength > 61) + legacy_i2c_offset = offset + 54; + bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset]; + bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1]; + bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2]; + bios->bdcb.dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4]; + bios->bdcb.dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5]; + bios->bdcb.dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6]; + bios->bdcb.dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7]; + + if (bmplength > 74) { + bios->fmaxvco = ROM32(bmp[67]); + bios->fminvco = ROM32(bmp[71]); + } + if (bmplength > 88) + parse_script_table_pointers(bios, offset + 75); + if (bmplength > 94) { + bios->tmds.output0_script_ptr = ROM16(bmp[89]); + bios->tmds.output1_script_ptr = ROM16(bmp[91]); + /* + * Never observed in use with lvds scripts, but is reused for + * 18/24 bit panel interface default for EDID equipped panels + * (if_is_24bit not set directly to avoid any oscillation). + */ + bios->legacy.lvds_single_a_script_ptr = ROM16(bmp[95]); + } + if (bmplength > 108) { + bios->fp.fptablepointer = ROM16(bmp[105]); + bios->fp.fpxlatetableptr = ROM16(bmp[107]); + bios->fp.xlatwidth = 1; + } + if (bmplength > 120) { + bios->fp.lvdsmanufacturerpointer = ROM16(bmp[117]); + bios->fp.fpxlatemanufacturertableptr = ROM16(bmp[119]); + } + if (bmplength > 143) + bios->pll_limit_tbl_ptr = ROM16(bmp[142]); + + if (bmplength > 157) + bios->fp.duallink_transition_clk = ROM16(bmp[156]) * 10; + + return 0; +} + +static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len) +{ + int i, j; + + for (i = 0; i <= (n - len); i++) { + for (j = 0; j < len; j++) + if (data[i + j] != str[j]) + break; + if (j == len) + return i; + } + + return 0; +} + +static int +read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, int index, struct dcb_i2c_entry *i2c) +{ + uint8_t dcb_i2c_ver = dcb_version, headerlen = 0, entry_len = 4; + int i2c_entries = DCB_MAX_NUM_I2C_ENTRIES; + int recordoffset = 0, rdofs = 1, wrofs = 0; + uint8_t port_type = 0; + + if (!i2ctable) + return -EINVAL; + + if (dcb_version >= 0x30) { + if (i2ctable[0] != dcb_version) /* necessary? */ + NV_WARN(dev, + "DCB I2C table version mismatch (%02X vs %02X)\n", + i2ctable[0], dcb_version); + dcb_i2c_ver = i2ctable[0]; + headerlen = i2ctable[1]; + if (i2ctable[2] <= DCB_MAX_NUM_I2C_ENTRIES) + i2c_entries = i2ctable[2]; + else + NV_WARN(dev, + "DCB I2C table has more entries than indexable " + "(%d entries, max index 15)\n", i2ctable[2]); + entry_len = i2ctable[3]; + /* [4] is i2c_default_indices, read in parse_dcb_table() */ + } + /* + * It's your own fault if you call this function on a DCB 1.1 BIOS -- + * the test below is for DCB 1.2 + */ + if (dcb_version < 0x14) { + recordoffset = 2; + rdofs = 0; + wrofs = 1; + } + + if (index == 0xf) + return 0; + if (index > i2c_entries) { + NV_ERROR(dev, "DCB I2C index too big (%d > %d)\n", + index, i2ctable[2]); + return -ENOENT; + } + if (i2ctable[headerlen + entry_len * index + 3] == 0xff) { + NV_ERROR(dev, "DCB I2C entry invalid\n"); + return -EINVAL; + } + + if (dcb_i2c_ver >= 0x30) { + port_type = i2ctable[headerlen + recordoffset + 3 + entry_len * index]; + + /* + * Fixup for chips using same address offset for read and + * write. + */ + if (port_type == 4) /* seen on C51 */ + rdofs = wrofs = 1; + if (port_type >= 5) /* G80+ */ + rdofs = wrofs = 0; + } + + if (dcb_i2c_ver >= 0x40 && port_type != 5 && port_type != 6) + NV_WARN(dev, "DCB I2C table has port type %d\n", port_type); + + i2c->port_type = port_type; + i2c->read = i2ctable[headerlen + recordoffset + rdofs + entry_len * index]; + i2c->write = i2ctable[headerlen + recordoffset + wrofs + entry_len * index]; + + return 0; +} + +static struct dcb_gpio_entry * +new_gpio_entry(struct nvbios *bios) +{ + struct parsed_dcb_gpio *gpio = &bios->bdcb.gpio; + + return &gpio->entry[gpio->entries++]; +} + +struct dcb_gpio_entry * +nouveau_bios_gpio_entry(struct drm_device *dev, enum dcb_gpio_tag tag) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + int i; + + for (i = 0; i < bios->bdcb.gpio.entries; i++) { + if (bios->bdcb.gpio.entry[i].tag != tag) + continue; + + return &bios->bdcb.gpio.entry[i]; + } + + return NULL; +} + +static void +parse_dcb30_gpio_entry(struct nvbios *bios, uint16_t offset) +{ + struct dcb_gpio_entry *gpio; + uint16_t ent = ROM16(bios->data[offset]); + uint8_t line = ent & 0x1f, + tag = ent >> 5 & 0x3f, + flags = ent >> 11 & 0x1f; + + if (tag == 0x3f) + return; + + gpio = new_gpio_entry(bios); + + gpio->tag = tag; + gpio->line = line; + gpio->invert = flags != 4; +} + +static void +parse_dcb40_gpio_entry(struct nvbios *bios, uint16_t offset) +{ + struct dcb_gpio_entry *gpio; + uint32_t ent = ROM32(bios->data[offset]); + uint8_t line = ent & 0x1f, + tag = ent >> 8 & 0xff; + + if (tag == 0xff) + return; + + gpio = new_gpio_entry(bios); + + /* Currently unused, we may need more fields parsed at some + * point. */ + gpio->tag = tag; + gpio->line = line; +} + +static void +parse_dcb_gpio_table(struct nvbios *bios) +{ + struct drm_device *dev = bios->dev; + uint16_t gpio_table_ptr = bios->bdcb.gpio_table_ptr; + uint8_t *gpio_table = &bios->data[gpio_table_ptr]; + int header_len = gpio_table[1], + entries = gpio_table[2], + entry_len = gpio_table[3]; + void (*parse_entry)(struct nvbios *, uint16_t) = NULL; + int i; + + if (bios->bdcb.version >= 0x40) { + if (gpio_table_ptr && entry_len != 4) { + NV_WARN(dev, "Invalid DCB GPIO table entry length.\n"); + return; + } + + parse_entry = parse_dcb40_gpio_entry; + + } else if (bios->bdcb.version >= 0x30) { + if (gpio_table_ptr && entry_len != 2) { + NV_WARN(dev, "Invalid DCB GPIO table entry length.\n"); + return; + } + + parse_entry = parse_dcb30_gpio_entry; + + } else if (bios->bdcb.version >= 0x22) { + /* + * DCBs older than v3.0 don't really have a GPIO + * table, instead they keep some GPIO info at fixed + * locations. + */ + uint16_t dcbptr = ROM16(bios->data[0x36]); + uint8_t *tvdac_gpio = &bios->data[dcbptr - 5]; + + if (tvdac_gpio[0] & 1) { + struct dcb_gpio_entry *gpio = new_gpio_entry(bios); + + gpio->tag = DCB_GPIO_TVDAC0; + gpio->line = tvdac_gpio[1] >> 4; + gpio->invert = tvdac_gpio[0] & 2; + } + } + + if (!gpio_table_ptr) + return; + + if (entries > DCB_MAX_NUM_GPIO_ENTRIES) { + NV_WARN(dev, "Too many entries in the DCB GPIO table.\n"); + entries = DCB_MAX_NUM_GPIO_ENTRIES; + } + + for (i = 0; i < entries; i++) + parse_entry(bios, gpio_table_ptr + header_len + entry_len * i); +} + +struct dcb_connector_table_entry * +nouveau_bios_connector_entry(struct drm_device *dev, int index) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + struct dcb_connector_table_entry *cte; + + if (index >= bios->bdcb.connector.entries) + return NULL; + + cte = &bios->bdcb.connector.entry[index]; + if (cte->type == 0xff) + return NULL; + + return cte; +} + +static void +parse_dcb_connector_table(struct nvbios *bios) +{ + struct drm_device *dev = bios->dev; + struct dcb_connector_table *ct = &bios->bdcb.connector; + struct dcb_connector_table_entry *cte; + uint8_t *conntab = &bios->data[bios->bdcb.connector_table_ptr]; + uint8_t *entry; + int i; + + if (!bios->bdcb.connector_table_ptr) { + NV_DEBUG(dev, "No DCB connector table present\n"); + return; + } + + NV_INFO(dev, "DCB connector table: VHER 0x%02x %d %d %d\n", + conntab[0], conntab[1], conntab[2], conntab[3]); + if ((conntab[0] != 0x30 && conntab[0] != 0x40) || + (conntab[3] != 2 && conntab[3] != 4)) { + NV_ERROR(dev, " Unknown! Please report.\n"); + return; + } + + ct->entries = conntab[2]; + + entry = conntab + conntab[1]; + cte = &ct->entry[0]; + for (i = 0; i < conntab[2]; i++, entry += conntab[3], cte++) { + if (conntab[3] == 2) + cte->entry = ROM16(entry[0]); + else + cte->entry = ROM32(entry[0]); + cte->type = (cte->entry & 0x000000ff) >> 0; + cte->index = (cte->entry & 0x00000f00) >> 8; + switch (cte->entry & 0x00033000) { + case 0x00001000: + cte->gpio_tag = 0x07; + break; + case 0x00002000: + cte->gpio_tag = 0x08; + break; + case 0x00010000: + cte->gpio_tag = 0x51; + break; + case 0x00020000: + cte->gpio_tag = 0x52; + break; + default: + cte->gpio_tag = 0xff; + break; + } + + if (cte->type == 0xff) + continue; + + NV_INFO(dev, " %d: 0x%08x: type 0x%02x idx %d tag 0x%02x\n", + i, cte->entry, cte->type, cte->index, cte->gpio_tag); + } +} + +static struct dcb_entry *new_dcb_entry(struct parsed_dcb *dcb) +{ + struct dcb_entry *entry = &dcb->entry[dcb->entries]; + + memset(entry, 0, sizeof(struct dcb_entry)); + entry->index = dcb->entries++; + + return entry; +} + +static void fabricate_vga_output(struct parsed_dcb *dcb, int i2c, int heads) +{ + struct dcb_entry *entry = new_dcb_entry(dcb); + + entry->type = 0; + entry->i2c_index = i2c; + entry->heads = heads; + entry->location = DCB_LOC_ON_CHIP; + /* "or" mostly unused in early gen crt modesetting, 0 is fine */ +} + +static void fabricate_dvi_i_output(struct parsed_dcb *dcb, bool twoHeads) +{ + struct dcb_entry *entry = new_dcb_entry(dcb); + + entry->type = 2; + entry->i2c_index = LEGACY_I2C_PANEL; + entry->heads = twoHeads ? 3 : 1; + entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */ + entry->or = 1; /* means |0x10 gets set on CRE_LCD__INDEX */ + entry->duallink_possible = false; /* SiI164 and co. are single link */ + +#if 0 + /* + * For dvi-a either crtc probably works, but my card appears to only + * support dvi-d. "nvidia" still attempts to program it for dvi-a, + * doing the full fp output setup (program 0x6808.. fp dimension regs, + * setting 0x680848 to 0x10000111 to enable, maybe setting 0x680880); + * the monitor picks up the mode res ok and lights up, but no pixel + * data appears, so the board manufacturer probably connected up the + * sync lines, but missed the video traces / components + * + * with this introduction, dvi-a left as an exercise for the reader. + */ + fabricate_vga_output(dcb, LEGACY_I2C_PANEL, entry->heads); +#endif +} + +static void fabricate_tv_output(struct parsed_dcb *dcb, bool twoHeads) +{ + struct dcb_entry *entry = new_dcb_entry(dcb); + + entry->type = 1; + entry->i2c_index = LEGACY_I2C_TV; + entry->heads = twoHeads ? 3 : 1; + entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */ +} + +static bool +parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb, + uint32_t conn, uint32_t conf, struct dcb_entry *entry) +{ + entry->type = conn & 0xf; + entry->i2c_index = (conn >> 4) & 0xf; + entry->heads = (conn >> 8) & 0xf; + if (bdcb->version >= 0x40) + entry->connector = (conn >> 12) & 0xf; + entry->bus = (conn >> 16) & 0xf; + entry->location = (conn >> 20) & 0x3; + entry->or = (conn >> 24) & 0xf; + /* + * Normal entries consist of a single bit, but dual link has the + * next most significant bit set too + */ + entry->duallink_possible = + ((1 << (ffs(entry->or) - 1)) * 3 == entry->or); + + switch (entry->type) { + case OUTPUT_ANALOG: + /* + * Although the rest of a CRT conf dword is usually + * zeros, mac biosen have stuff there so we must mask + */ + entry->crtconf.maxfreq = (bdcb->version < 0x30) ? + (conf & 0xffff) * 10 : + (conf & 0xff) * 10000; + break; + case OUTPUT_LVDS: + { + uint32_t mask; + if (conf & 0x1) + entry->lvdsconf.use_straps_for_mode = true; + if (bdcb->version < 0x22) { + mask = ~0xd; + /* + * The laptop in bug 14567 lies and claims to not use + * straps when it does, so assume all DCB 2.0 laptops + * use straps, until a broken EDID using one is produced + */ + entry->lvdsconf.use_straps_for_mode = true; + /* + * Both 0x4 and 0x8 show up in v2.0 tables; assume they + * mean the same thing (probably wrong, but might work) + */ + if (conf & 0x4 || conf & 0x8) + entry->lvdsconf.use_power_scripts = true; + } else { + mask = ~0x5; + if (conf & 0x4) + entry->lvdsconf.use_power_scripts = true; + } + if (conf & mask) { + /* + * Until we even try to use these on G8x, it's + * useless reporting unknown bits. They all are. + */ + if (bdcb->version >= 0x40) + break; + + NV_ERROR(dev, "Unknown LVDS configuration bits, " + "please report\n"); + } + break; + } + case OUTPUT_TV: + { + if (bdcb->version >= 0x30) + entry->tvconf.has_component_output = conf & (0x8 << 4); + else + entry->tvconf.has_component_output = false; + + break; + } + case OUTPUT_DP: + entry->dpconf.sor.link = (conf & 0x00000030) >> 4; + entry->dpconf.link_bw = (conf & 0x00e00000) >> 21; + switch ((conf & 0x0f000000) >> 24) { + case 0xf: + entry->dpconf.link_nr = 4; + break; + case 0x3: + entry->dpconf.link_nr = 2; + break; + default: + entry->dpconf.link_nr = 1; + break; + } + break; + case OUTPUT_TMDS: + entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4; + break; + case 0xe: + /* weird g80 mobile type that "nv" treats as a terminator */ + bdcb->dcb.entries--; + return false; + } + + /* unsure what DCB version introduces this, 3.0? */ + if (conf & 0x100000) + entry->i2c_upper_default = true; + + return true; +} + +static bool +parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb, + uint32_t conn, uint32_t conf, struct dcb_entry *entry) +{ + if (conn != 0xf0003f00 && conn != 0xf2247f10 && conn != 0xf2204001 && + conn != 0xf2204301 && conn != 0xf2204311 && conn != 0xf2208001 && + conn != 0xf2244001 && conn != 0xf2244301 && conn != 0xf2244311 && + conn != 0xf4204011 && conn != 0xf4208011 && conn != 0xf4248011 && + conn != 0xf2045ff2 && conn != 0xf2045f14 && conn != 0xf207df14 && + conn != 0xf2205004 && conn != 0xf2209004) { + NV_ERROR(dev, "Unknown DCB 1.5 entry, please report\n"); + + /* cause output setting to fail for !TV, so message is seen */ + if ((conn & 0xf) != 0x1) + dcb->entries = 0; + + return false; + } + /* most of the below is a "best guess" atm */ + entry->type = conn & 0xf; + if (entry->type == 2) + /* another way of specifying straps based lvds... */ + entry->type = OUTPUT_LVDS; + if (entry->type == 4) { /* digital */ + if (conn & 0x10) + entry->type = OUTPUT_LVDS; + else + entry->type = OUTPUT_TMDS; + } + /* what's in bits 5-13? could be some encoder maker thing, in tv case */ + entry->i2c_index = (conn >> 14) & 0xf; + /* raw heads field is in range 0-1, so move to 1-2 */ + entry->heads = ((conn >> 18) & 0x7) + 1; + entry->location = (conn >> 21) & 0xf; + /* unused: entry->bus = (conn >> 25) & 0x7; */ + /* set or to be same as heads -- hopefully safe enough */ + entry->or = entry->heads; + entry->duallink_possible = false; + + switch (entry->type) { + case OUTPUT_ANALOG: + entry->crtconf.maxfreq = (conf & 0xffff) * 10; + break; + case OUTPUT_LVDS: + /* + * This is probably buried in conn's unknown bits. + * This will upset EDID-ful models, if they exist + */ + entry->lvdsconf.use_straps_for_mode = true; + entry->lvdsconf.use_power_scripts = true; + break; + case OUTPUT_TMDS: + /* + * Invent a DVI-A output, by copying the fields of the DVI-D + * output; reported to work by math_b on an NV20(!). + */ + fabricate_vga_output(dcb, entry->i2c_index, entry->heads); + break; + case OUTPUT_TV: + entry->tvconf.has_component_output = false; + break; + } + + return true; +} + +static bool parse_dcb_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb, + uint32_t conn, uint32_t conf) +{ + struct dcb_entry *entry = new_dcb_entry(&bdcb->dcb); + bool ret; + + if (bdcb->version >= 0x20) + ret = parse_dcb20_entry(dev, bdcb, conn, conf, entry); + else + ret = parse_dcb15_entry(dev, &bdcb->dcb, conn, conf, entry); + if (!ret) + return ret; + + read_dcb_i2c_entry(dev, bdcb->version, bdcb->i2c_table, + entry->i2c_index, &bdcb->dcb.i2c[entry->i2c_index]); + + return true; +} + +static +void merge_like_dcb_entries(struct drm_device *dev, struct parsed_dcb *dcb) +{ + /* + * DCB v2.0 lists each output combination separately. + * Here we merge compatible entries to have fewer outputs, with + * more options + */ + + int i, newentries = 0; + + for (i = 0; i < dcb->entries; i++) { + struct dcb_entry *ient = &dcb->entry[i]; + int j; + + for (j = i + 1; j < dcb->entries; j++) { + struct dcb_entry *jent = &dcb->entry[j]; + + if (jent->type == 100) /* already merged entry */ + continue; + + /* merge heads field when all other fields the same */ + if (jent->i2c_index == ient->i2c_index && + jent->type == ient->type && + jent->location == ient->location && + jent->or == ient->or) { + NV_TRACE(dev, "Merging DCB entries %d and %d\n", + i, j); + ient->heads |= jent->heads; + jent->type = 100; /* dummy value */ + } + } + } + + /* Compact entries merged into others out of dcb */ + for (i = 0; i < dcb->entries; i++) { + if (dcb->entry[i].type == 100) + continue; + + if (newentries != i) { + dcb->entry[newentries] = dcb->entry[i]; + dcb->entry[newentries].index = newentries; + } + newentries++; + } + + dcb->entries = newentries; +} + +static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) +{ + struct bios_parsed_dcb *bdcb = &bios->bdcb; + struct parsed_dcb *dcb; + uint16_t dcbptr, i2ctabptr = 0; + uint8_t *dcbtable; + uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES; + bool configblock = true; + int recordlength = 8, confofs = 4; + int i; + + dcb = bios->pub.dcb = &bdcb->dcb; + dcb->entries = 0; + + /* get the offset from 0x36 */ + dcbptr = ROM16(bios->data[0x36]); + + if (dcbptr == 0x0) { + NV_WARN(dev, "No output data (DCB) found in BIOS, " + "assuming a CRT output exists\n"); + /* this situation likely means a really old card, pre DCB */ + fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1); + + if (nv04_tv_identify(dev, + bios->legacy.i2c_indices.tv) >= 0) + fabricate_tv_output(dcb, twoHeads); + + return 0; + } + + dcbtable = &bios->data[dcbptr]; + + /* get DCB version */ + bdcb->version = dcbtable[0]; + NV_TRACE(dev, "Found Display Configuration Block version %d.%d\n", + bdcb->version >> 4, bdcb->version & 0xf); + + if (bdcb->version >= 0x20) { /* NV17+ */ + uint32_t sig; + + if (bdcb->version >= 0x30) { /* NV40+ */ + headerlen = dcbtable[1]; + entries = dcbtable[2]; + recordlength = dcbtable[3]; + i2ctabptr = ROM16(dcbtable[4]); + sig = ROM32(dcbtable[6]); + bdcb->gpio_table_ptr = ROM16(dcbtable[10]); + bdcb->connector_table_ptr = ROM16(dcbtable[20]); + } else { + i2ctabptr = ROM16(dcbtable[2]); + sig = ROM32(dcbtable[4]); + headerlen = 8; + } + + if (sig != 0x4edcbdcb) { + NV_ERROR(dev, "Bad Display Configuration Block " + "signature (%08X)\n", sig); + return -EINVAL; + } + } else if (bdcb->version >= 0x15) { /* some NV11 and NV20 */ + char sig[8] = { 0 }; + + strncpy(sig, (char *)&dcbtable[-7], 7); + i2ctabptr = ROM16(dcbtable[2]); + recordlength = 10; + confofs = 6; + + if (strcmp(sig, "DEV_REC")) { + NV_ERROR(dev, "Bad Display Configuration Block " + "signature (%s)\n", sig); + return -EINVAL; + } + } else { + /* + * v1.4 (some NV15/16, NV11+) seems the same as v1.5, but always + * has the same single (crt) entry, even when tv-out present, so + * the conclusion is this version cannot really be used. + * v1.2 tables (some NV6/10, and NV15+) normally have the same + * 5 entries, which are not specific to the card and so no use. + * v1.2 does have an I2C table that read_dcb_i2c_table can + * handle, but cards exist (nv11 in #14821) with a bad i2c table + * pointer, so use the indices parsed in parse_bmp_structure. + * v1.1 (NV5+, maybe some NV4) is entirely unhelpful + */ + NV_TRACEWARN(dev, "No useful information in BIOS output table; " + "adding all possible outputs\n"); + fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1); + + /* + * Attempt to detect TV before DVI because the test + * for the former is more accurate and it rules the + * latter out. + */ + if (nv04_tv_identify(dev, + bios->legacy.i2c_indices.tv) >= 0) + fabricate_tv_output(dcb, twoHeads); + + else if (bios->tmds.output0_script_ptr || + bios->tmds.output1_script_ptr) + fabricate_dvi_i_output(dcb, twoHeads); + + return 0; + } + + if (!i2ctabptr) + NV_WARN(dev, "No pointer to DCB I2C port table\n"); + else { + bdcb->i2c_table = &bios->data[i2ctabptr]; + if (bdcb->version >= 0x30) + bdcb->i2c_default_indices = bdcb->i2c_table[4]; + } + + parse_dcb_gpio_table(bios); + parse_dcb_connector_table(bios); + + if (entries > DCB_MAX_NUM_ENTRIES) + entries = DCB_MAX_NUM_ENTRIES; + + for (i = 0; i < entries; i++) { + uint32_t connection, config = 0; + + connection = ROM32(dcbtable[headerlen + recordlength * i]); + if (configblock) + config = ROM32(dcbtable[headerlen + confofs + recordlength * i]); + + /* seen on an NV11 with DCB v1.5 */ + if (connection == 0x00000000) + break; + + /* seen on an NV17 with DCB v2.0 */ + if (connection == 0xffffffff) + break; + + if ((connection & 0x0000000f) == 0x0000000f) + continue; + + NV_TRACEWARN(dev, "Raw DCB entry %d: %08x %08x\n", + dcb->entries, connection, config); + + if (!parse_dcb_entry(dev, bdcb, connection, config)) + break; + } + + /* + * apart for v2.1+ not being known for requiring merging, this + * guarantees dcbent->index is the index of the entry in the rom image + */ + if (bdcb->version < 0x21) + merge_like_dcb_entries(dev, dcb); + + return dcb->entries ? 0 : -ENXIO; +} + +static void +fixup_legacy_connector(struct nvbios *bios) +{ + struct bios_parsed_dcb *bdcb = &bios->bdcb; + struct parsed_dcb *dcb = &bdcb->dcb; + int high = 0, i; + + /* + * DCB 3.0 also has the table in most cases, but there are some cards + * where the table is filled with stub entries, and the DCB entriy + * indices are all 0. We don't need the connector indices on pre-G80 + * chips (yet?) so limit the use to DCB 4.0 and above. + */ + if (bdcb->version >= 0x40) + return; + + /* + * No known connector info before v3.0, so make it up. the rule here + * is: anything on the same i2c bus is considered to be on the same + * connector. any output without an associated i2c bus is assigned + * its own unique connector index. + */ + for (i = 0; i < dcb->entries; i++) { + if (dcb->entry[i].i2c_index == 0xf) + continue; + + /* + * Ignore the I2C index for on-chip TV-out, as there + * are cards with bogus values (nv31m in bug 23212), + * and it's otherwise useless. + */ + if (dcb->entry[i].type == OUTPUT_TV && + dcb->entry[i].location == DCB_LOC_ON_CHIP) { + dcb->entry[i].i2c_index = 0xf; + continue; + } + + dcb->entry[i].connector = dcb->entry[i].i2c_index; + if (dcb->entry[i].connector > high) + high = dcb->entry[i].connector; + } + + for (i = 0; i < dcb->entries; i++) { + if (dcb->entry[i].i2c_index != 0xf) + continue; + + dcb->entry[i].connector = ++high; + } +} + +static void +fixup_legacy_i2c(struct nvbios *bios) +{ + struct parsed_dcb *dcb = &bios->bdcb.dcb; + int i; + + for (i = 0; i < dcb->entries; i++) { + if (dcb->entry[i].i2c_index == LEGACY_I2C_CRT) + dcb->entry[i].i2c_index = bios->legacy.i2c_indices.crt; + if (dcb->entry[i].i2c_index == LEGACY_I2C_PANEL) + dcb->entry[i].i2c_index = bios->legacy.i2c_indices.panel; + if (dcb->entry[i].i2c_index == LEGACY_I2C_TV) + dcb->entry[i].i2c_index = bios->legacy.i2c_indices.tv; + } +} + +static int load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bios, uint16_t hwsq_offset, int entry) +{ + /* + * The header following the "HWSQ" signature has the number of entries, + * and the entry size + * + * An entry consists of a dword to write to the sequencer control reg + * (0x00001304), followed by the ucode bytes, written sequentially, + * starting at reg 0x00001400 + */ + + uint8_t bytes_to_write; + uint16_t hwsq_entry_offset; + int i; + + if (bios->data[hwsq_offset] <= entry) { + NV_ERROR(dev, "Too few entries in HW sequencer table for " + "requested entry\n"); + return -ENOENT; + } + + bytes_to_write = bios->data[hwsq_offset + 1]; + + if (bytes_to_write != 36) { + NV_ERROR(dev, "Unknown HW sequencer entry size\n"); + return -EINVAL; + } + + NV_TRACE(dev, "Loading NV17 power sequencing microcode\n"); + + hwsq_entry_offset = hwsq_offset + 2 + entry * bytes_to_write; + + /* set sequencer control */ + bios_wr32(bios, 0x00001304, ROM32(bios->data[hwsq_entry_offset])); + bytes_to_write -= 4; + + /* write ucode */ + for (i = 0; i < bytes_to_write; i += 4) + bios_wr32(bios, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4])); + + /* twiddle NV_PBUS_DEBUG_4 */ + bios_wr32(bios, NV_PBUS_DEBUG_4, bios_rd32(bios, NV_PBUS_DEBUG_4) | 0x18); + + return 0; +} + +static int load_nv17_hw_sequencer_ucode(struct drm_device *dev, + struct nvbios *bios) +{ + /* + * BMP based cards, from NV17, need a microcode loading to correctly + * control the GPIO etc for LVDS panels + * + * BIT based cards seem to do this directly in the init scripts + * + * The microcode entries are found by the "HWSQ" signature. + */ + + const uint8_t hwsq_signature[] = { 'H', 'W', 'S', 'Q' }; + const int sz = sizeof(hwsq_signature); + int hwsq_offset; + + hwsq_offset = findstr(bios->data, bios->length, hwsq_signature, sz); + if (!hwsq_offset) + return 0; + + /* always use entry 0? */ + return load_nv17_hwsq_ucode_entry(dev, bios, hwsq_offset + sz, 0); +} + +uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + const uint8_t edid_sig[] = { + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; + uint16_t offset = 0; + uint16_t newoffset; + int searchlen = NV_PROM_SIZE; + + if (bios->fp.edid) + return bios->fp.edid; + + while (searchlen) { + newoffset = findstr(&bios->data[offset], searchlen, + edid_sig, 8); + if (!newoffset) + return NULL; + offset += newoffset; + if (!nv_cksum(&bios->data[offset], EDID1_LEN)) + break; + + searchlen -= offset; + offset++; + } + + NV_TRACE(dev, "Found EDID in BIOS\n"); + + return bios->fp.edid = &bios->data[offset]; +} + +void +nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, + struct dcb_entry *dcbent) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + struct init_exec iexec = { true, false }; + + bios->display.output = dcbent; + parse_init_table(bios, table, &iexec); + bios->display.output = NULL; +} + +static bool NVInitVBIOS(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + + memset(bios, 0, sizeof(struct nvbios)); + bios->dev = dev; + + if (!NVShadowVBIOS(dev, bios->data)) + return false; + + bios->length = NV_PROM_SIZE; + return true; +} + +static int nouveau_parse_vbios_struct(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + const uint8_t bit_signature[] = { 0xff, 0xb8, 'B', 'I', 'T' }; + const uint8_t bmp_signature[] = { 0xff, 0x7f, 'N', 'V', 0x0 }; + int offset; + + offset = findstr(bios->data, bios->length, + bit_signature, sizeof(bit_signature)); + if (offset) { + NV_TRACE(dev, "BIT BIOS found\n"); + return parse_bit_structure(bios, offset + 6); + } + + offset = findstr(bios->data, bios->length, + bmp_signature, sizeof(bmp_signature)); + if (offset) { + NV_TRACE(dev, "BMP BIOS found\n"); + return parse_bmp_structure(dev, bios, offset); + } + + NV_ERROR(dev, "No known BIOS signature found\n"); + return -ENODEV; +} + +int +nouveau_run_vbios_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + int i, ret = 0; + + NVLockVgaCrtcs(dev, false); + if (nv_two_heads(dev)) + NVSetOwner(dev, bios->state.crtchead); + + if (bios->major_version < 5) /* BMP only */ + load_nv17_hw_sequencer_ucode(dev, bios); + + if (bios->execute) { + bios->fp.last_script_invoc = 0; + bios->fp.lvds_init_run = false; + } + + parse_init_tables(bios); + + /* + * Runs some additional script seen on G8x VBIOSen. The VBIOS' + * parser will run this right after the init tables, the binary + * driver appears to run it at some point later. + */ + if (bios->some_script_ptr) { + struct init_exec iexec = {true, false}; + + NV_INFO(dev, "Parsing VBIOS init table at offset 0x%04X\n", + bios->some_script_ptr); + parse_init_table(bios, bios->some_script_ptr, &iexec); + } + + if (dev_priv->card_type >= NV_50) { + for (i = 0; i < bios->bdcb.dcb.entries; i++) { + nouveau_bios_run_display_table(dev, + &bios->bdcb.dcb.entry[i], + 0, 0); + } + } + + NVLockVgaCrtcs(dev, true); + + return ret; +} + +static void +nouveau_bios_i2c_devices_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + struct dcb_i2c_entry *entry; + int i; + + entry = &bios->bdcb.dcb.i2c[0]; + for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++, entry++) + nouveau_i2c_fini(dev, entry); +} + +int +nouveau_bios_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + uint32_t saved_nv_pextdev_boot_0; + bool was_locked; + int ret; + + dev_priv->vbios = &bios->pub; + + if (!NVInitVBIOS(dev)) + return -ENODEV; + + ret = nouveau_parse_vbios_struct(dev); + if (ret) + return ret; + + ret = parse_dcb_table(dev, bios, nv_two_heads(dev)); + if (ret) + return ret; + + fixup_legacy_i2c(bios); + fixup_legacy_connector(bios); + + if (!bios->major_version) /* we don't run version 0 bios */ + return 0; + + /* these will need remembering across a suspend */ + saved_nv_pextdev_boot_0 = bios_rd32(bios, NV_PEXTDEV_BOOT_0); + bios->state.saved_nv_pfb_cfg0 = bios_rd32(bios, NV_PFB_CFG0); + + /* init script execution disabled */ + bios->execute = false; + + /* ... unless card isn't POSTed already */ + if (dev_priv->card_type >= NV_10 && + NVReadVgaCrtc(dev, 0, 0x00) == 0 && + NVReadVgaCrtc(dev, 0, 0x1a) == 0) { + NV_INFO(dev, "Adaptor not initialised\n"); + if (dev_priv->card_type < NV_50) { + NV_ERROR(dev, "Unable to POST this chipset\n"); + return -ENODEV; + } + + NV_INFO(dev, "Running VBIOS init tables\n"); + bios->execute = true; + } + + bios_wr32(bios, NV_PEXTDEV_BOOT_0, saved_nv_pextdev_boot_0); + + ret = nouveau_run_vbios_init(dev); + if (ret) { + dev_priv->vbios = NULL; + return ret; + } + + /* feature_byte on BMP is poor, but init always sets CR4B */ + was_locked = NVLockVgaCrtcs(dev, false); + if (bios->major_version < 5) + bios->is_mobile = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_4B) & 0x40; + + /* all BIT systems need p_f_m_t for digital_min_front_porch */ + if (bios->is_mobile || bios->major_version >= 5) + ret = parse_fp_mode_table(dev, bios); + NVLockVgaCrtcs(dev, was_locked); + + /* allow subsequent scripts to execute */ + bios->execute = true; + + return 0; +} + +void +nouveau_bios_takedown(struct drm_device *dev) +{ + nouveau_bios_i2c_devices_takedown(dev); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h new file mode 100644 index 0000000000000000000000000000000000000000..1d5f10bd78ed00d9e3dcf5124c467073fe333c30 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -0,0 +1,289 @@ +/* + * Copyright 2007-2008 Nouveau Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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. + */ + +#ifndef __NOUVEAU_BIOS_H__ +#define __NOUVEAU_BIOS_H__ + +#include "nvreg.h" +#include "nouveau_i2c.h" + +#define DCB_MAX_NUM_ENTRIES 16 +#define DCB_MAX_NUM_I2C_ENTRIES 16 +#define DCB_MAX_NUM_GPIO_ENTRIES 32 +#define DCB_MAX_NUM_CONNECTOR_ENTRIES 16 + +#define DCB_LOC_ON_CHIP 0 + +struct dcb_entry { + int index; /* may not be raw dcb index if merging has happened */ + uint8_t type; + uint8_t i2c_index; + uint8_t heads; + uint8_t connector; + uint8_t bus; + uint8_t location; + uint8_t or; + bool duallink_possible; + union { + struct sor_conf { + int link; + } sorconf; + struct { + int maxfreq; + } crtconf; + struct { + struct sor_conf sor; + bool use_straps_for_mode; + bool use_power_scripts; + } lvdsconf; + struct { + bool has_component_output; + } tvconf; + struct { + struct sor_conf sor; + int link_nr; + int link_bw; + } dpconf; + struct { + struct sor_conf sor; + } tmdsconf; + }; + bool i2c_upper_default; +}; + +struct dcb_i2c_entry { + uint8_t port_type; + uint8_t read, write; + struct nouveau_i2c_chan *chan; +}; + +struct parsed_dcb { + int entries; + struct dcb_entry entry[DCB_MAX_NUM_ENTRIES]; + struct dcb_i2c_entry i2c[DCB_MAX_NUM_I2C_ENTRIES]; +}; + +enum dcb_gpio_tag { + DCB_GPIO_TVDAC0 = 0xc, + DCB_GPIO_TVDAC1 = 0x2d, +}; + +struct dcb_gpio_entry { + enum dcb_gpio_tag tag; + int line; + bool invert; +}; + +struct parsed_dcb_gpio { + int entries; + struct dcb_gpio_entry entry[DCB_MAX_NUM_GPIO_ENTRIES]; +}; + +struct dcb_connector_table_entry { + uint32_t entry; + uint8_t type; + uint8_t index; + uint8_t gpio_tag; +}; + +struct dcb_connector_table { + int entries; + struct dcb_connector_table_entry entry[DCB_MAX_NUM_CONNECTOR_ENTRIES]; +}; + +struct bios_parsed_dcb { + uint8_t version; + + struct parsed_dcb dcb; + + uint8_t *i2c_table; + uint8_t i2c_default_indices; + + uint16_t gpio_table_ptr; + struct parsed_dcb_gpio gpio; + uint16_t connector_table_ptr; + struct dcb_connector_table connector; +}; + +enum nouveau_encoder_type { + OUTPUT_ANALOG = 0, + OUTPUT_TV = 1, + OUTPUT_TMDS = 2, + OUTPUT_LVDS = 3, + OUTPUT_DP = 6, + OUTPUT_ANY = -1 +}; + +enum nouveau_or { + OUTPUT_A = (1 << 0), + OUTPUT_B = (1 << 1), + OUTPUT_C = (1 << 2) +}; + +enum LVDS_script { + /* Order *does* matter here */ + LVDS_INIT = 1, + LVDS_RESET, + LVDS_BACKLIGHT_ON, + LVDS_BACKLIGHT_OFF, + LVDS_PANEL_ON, + LVDS_PANEL_OFF +}; + +/* changing these requires matching changes to reg tables in nv_get_clock */ +#define MAX_PLL_TYPES 4 +enum pll_types { + NVPLL, + MPLL, + VPLL1, + VPLL2 +}; + +struct pll_lims { + struct { + int minfreq; + int maxfreq; + int min_inputfreq; + int max_inputfreq; + + uint8_t min_m; + uint8_t max_m; + uint8_t min_n; + uint8_t max_n; + } vco1, vco2; + + uint8_t max_log2p; + /* + * for most pre nv50 cards setting a log2P of 7 (the common max_log2p + * value) is no different to 6 (at least for vplls) so allowing the MNP + * calc to use 7 causes the generated clock to be out by a factor of 2. + * however, max_log2p cannot be fixed-up during parsing as the + * unmodified max_log2p value is still needed for setting mplls, hence + * an additional max_usable_log2p member + */ + uint8_t max_usable_log2p; + uint8_t log2p_bias; + + uint8_t min_p; + uint8_t max_p; + + int refclk; +}; + +struct nouveau_bios_info { + struct parsed_dcb *dcb; + + uint8_t chip_version; + + uint32_t dactestval; + uint32_t tvdactestval; + uint8_t digital_min_front_porch; + bool fp_no_ddc; +}; + +struct nvbios { + struct drm_device *dev; + struct nouveau_bios_info pub; + + uint8_t data[NV_PROM_SIZE]; + unsigned int length; + bool execute; + + uint8_t major_version; + uint8_t feature_byte; + bool is_mobile; + + uint32_t fmaxvco, fminvco; + + bool old_style_init; + uint16_t init_script_tbls_ptr; + uint16_t extra_init_script_tbl_ptr; + uint16_t macro_index_tbl_ptr; + uint16_t macro_tbl_ptr; + uint16_t condition_tbl_ptr; + uint16_t io_condition_tbl_ptr; + uint16_t io_flag_condition_tbl_ptr; + uint16_t init_function_tbl_ptr; + + uint16_t pll_limit_tbl_ptr; + uint16_t ram_restrict_tbl_ptr; + + uint16_t some_script_ptr; /* BIT I + 14 */ + uint16_t init96_tbl_ptr; /* BIT I + 16 */ + + struct bios_parsed_dcb bdcb; + + struct { + int crtchead; + /* these need remembering across suspend */ + uint32_t saved_nv_pfb_cfg0; + } state; + + struct { + struct dcb_entry *output; + uint16_t script_table_ptr; + uint16_t dp_table_ptr; + } display; + + struct { + uint16_t fptablepointer; /* also used by tmds */ + uint16_t fpxlatetableptr; + int xlatwidth; + uint16_t lvdsmanufacturerpointer; + uint16_t fpxlatemanufacturertableptr; + uint16_t mode_ptr; + uint16_t xlated_entry; + bool power_off_for_reset; + bool reset_after_pclk_change; + bool dual_link; + bool link_c_increment; + bool BITbit1; + bool if_is_24bit; + int duallink_transition_clk; + uint8_t strapless_is_24bit; + uint8_t *edid; + + /* will need resetting after suspend */ + int last_script_invoc; + bool lvds_init_run; + } fp; + + struct { + uint16_t output0_script_ptr; + uint16_t output1_script_ptr; + } tmds; + + struct { + uint16_t mem_init_tbl_ptr; + uint16_t sdr_seq_tbl_ptr; + uint16_t ddr_seq_tbl_ptr; + + struct { + uint8_t crt, tv, panel; + } i2c_indices; + + uint16_t lvds_single_a_script_ptr; + } legacy; +}; + +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c new file mode 100644 index 0000000000000000000000000000000000000000..320a14bceb99e70735ebfe8cc4ea33c16689e7c8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -0,0 +1,671 @@ +/* + * Copyright 2007 Dave Airlied + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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. + */ +/* + * Authors: Dave Airlied + * Ben Skeggs + * Jeremy Kolb + */ + +#include "drmP.h" + +#include "nouveau_drm.h" +#include "nouveau_drv.h" +#include "nouveau_dma.h" + +static void +nouveau_bo_del_ttm(struct ttm_buffer_object *bo) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct nouveau_bo *nvbo = nouveau_bo(bo); + + ttm_bo_kunmap(&nvbo->kmap); + + if (unlikely(nvbo->gem)) + DRM_ERROR("bo %p still attached to GEM object\n", bo); + + spin_lock(&dev_priv->ttm.bo_list_lock); + list_del(&nvbo->head); + spin_unlock(&dev_priv->ttm.bo_list_lock); + kfree(nvbo); +} + +int +nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, + int size, int align, uint32_t flags, uint32_t tile_mode, + uint32_t tile_flags, bool no_vm, bool mappable, + struct nouveau_bo **pnvbo) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_bo *nvbo; + int ret, n = 0; + + nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL); + if (!nvbo) + return -ENOMEM; + INIT_LIST_HEAD(&nvbo->head); + INIT_LIST_HEAD(&nvbo->entry); + nvbo->mappable = mappable; + nvbo->no_vm = no_vm; + nvbo->tile_mode = tile_mode; + nvbo->tile_flags = tile_flags; + + /* + * Some of the tile_flags have a periodic structure of N*4096 bytes, + * align to to that as well as the page size. Overallocate memory to + * avoid corruption of other buffer objects. + */ + switch (tile_flags) { + case 0x1800: + case 0x2800: + case 0x4800: + case 0x7a00: + if (dev_priv->chipset >= 0xA0) { + /* This is based on high end cards with 448 bits + * memory bus, could be different elsewhere.*/ + size += 6 * 28672; + /* 8 * 28672 is the actual alignment requirement, + * but we must also align to page size. */ + align = 2 * 8 * 28672; + } else if (dev_priv->chipset >= 0x90) { + size += 3 * 16384; + align = 12 * 16834; + } else { + size += 3 * 8192; + /* 12 * 8192 is the actual alignment requirement, + * but we must also align to page size. */ + align = 2 * 12 * 8192; + } + break; + default: + break; + } + + align >>= PAGE_SHIFT; + + size = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); + if (dev_priv->card_type == NV_50) { + size = (size + 65535) & ~65535; + if (align < (65536 / PAGE_SIZE)) + align = (65536 / PAGE_SIZE); + } + + if (flags & TTM_PL_FLAG_VRAM) + nvbo->placements[n++] = TTM_PL_FLAG_VRAM | TTM_PL_MASK_CACHING; + if (flags & TTM_PL_FLAG_TT) + nvbo->placements[n++] = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; + nvbo->placement.fpfn = 0; + nvbo->placement.lpfn = mappable ? dev_priv->fb_mappable_pages : 0; + nvbo->placement.placement = nvbo->placements; + nvbo->placement.busy_placement = nvbo->placements; + nvbo->placement.num_placement = n; + nvbo->placement.num_busy_placement = n; + + nvbo->channel = chan; + nouveau_bo_placement_set(nvbo, flags); + ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size, + ttm_bo_type_device, &nvbo->placement, align, 0, + false, NULL, size, nouveau_bo_del_ttm); + nvbo->channel = NULL; + if (ret) { + /* ttm will call nouveau_bo_del_ttm if it fails.. */ + return ret; + } + + spin_lock(&dev_priv->ttm.bo_list_lock); + list_add_tail(&nvbo->head, &dev_priv->ttm.bo_list); + spin_unlock(&dev_priv->ttm.bo_list_lock); + *pnvbo = nvbo; + return 0; +} + +void +nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t memtype) +{ + int n = 0; + + if (memtype & TTM_PL_FLAG_VRAM) + nvbo->placements[n++] = TTM_PL_FLAG_VRAM | TTM_PL_MASK_CACHING; + if (memtype & TTM_PL_FLAG_TT) + nvbo->placements[n++] = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; + if (memtype & TTM_PL_FLAG_SYSTEM) + nvbo->placements[n++] = TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING; + nvbo->placement.placement = nvbo->placements; + nvbo->placement.busy_placement = nvbo->placements; + nvbo->placement.num_placement = n; + nvbo->placement.num_busy_placement = n; +} + +int +nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); + struct ttm_buffer_object *bo = &nvbo->bo; + int ret, i; + + if (nvbo->pin_refcnt && !(memtype & (1 << bo->mem.mem_type))) { + NV_ERROR(nouveau_bdev(bo->bdev)->dev, + "bo %p pinned elsewhere: 0x%08x vs 0x%08x\n", bo, + 1 << bo->mem.mem_type, memtype); + return -EINVAL; + } + + if (nvbo->pin_refcnt++) + return 0; + + ret = ttm_bo_reserve(bo, false, false, false, 0); + if (ret) + goto out; + + nouveau_bo_placement_set(nvbo, memtype); + for (i = 0; i < nvbo->placement.num_placement; i++) + nvbo->placements[i] |= TTM_PL_FLAG_NO_EVICT; + + ret = ttm_bo_validate(bo, &nvbo->placement, false, false); + if (ret == 0) { + switch (bo->mem.mem_type) { + case TTM_PL_VRAM: + dev_priv->fb_aper_free -= bo->mem.size; + break; + case TTM_PL_TT: + dev_priv->gart_info.aper_free -= bo->mem.size; + break; + default: + break; + } + } + ttm_bo_unreserve(bo); +out: + if (unlikely(ret)) + nvbo->pin_refcnt--; + return ret; +} + +int +nouveau_bo_unpin(struct nouveau_bo *nvbo) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); + struct ttm_buffer_object *bo = &nvbo->bo; + int ret, i; + + if (--nvbo->pin_refcnt) + return 0; + + ret = ttm_bo_reserve(bo, false, false, false, 0); + if (ret) + return ret; + + for (i = 0; i < nvbo->placement.num_placement; i++) + nvbo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT; + + ret = ttm_bo_validate(bo, &nvbo->placement, false, false); + if (ret == 0) { + switch (bo->mem.mem_type) { + case TTM_PL_VRAM: + dev_priv->fb_aper_free += bo->mem.size; + break; + case TTM_PL_TT: + dev_priv->gart_info.aper_free += bo->mem.size; + break; + default: + break; + } + } + + ttm_bo_unreserve(bo); + return ret; +} + +int +nouveau_bo_map(struct nouveau_bo *nvbo) +{ + int ret; + + ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0); + if (ret) + return ret; + + ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages, &nvbo->kmap); + ttm_bo_unreserve(&nvbo->bo); + return ret; +} + +void +nouveau_bo_unmap(struct nouveau_bo *nvbo) +{ + ttm_bo_kunmap(&nvbo->kmap); +} + +u16 +nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index) +{ + bool is_iomem; + u16 *mem = ttm_kmap_obj_virtual(&nvbo->kmap, &is_iomem); + mem = &mem[index]; + if (is_iomem) + return ioread16_native((void __force __iomem *)mem); + else + return *mem; +} + +void +nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val) +{ + bool is_iomem; + u16 *mem = ttm_kmap_obj_virtual(&nvbo->kmap, &is_iomem); + mem = &mem[index]; + if (is_iomem) + iowrite16_native(val, (void __force __iomem *)mem); + else + *mem = val; +} + +u32 +nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index) +{ + bool is_iomem; + u32 *mem = ttm_kmap_obj_virtual(&nvbo->kmap, &is_iomem); + mem = &mem[index]; + if (is_iomem) + return ioread32_native((void __force __iomem *)mem); + else + return *mem; +} + +void +nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val) +{ + bool is_iomem; + u32 *mem = ttm_kmap_obj_virtual(&nvbo->kmap, &is_iomem); + mem = &mem[index]; + if (is_iomem) + iowrite32_native(val, (void __force __iomem *)mem); + else + *mem = val; +} + +static struct ttm_backend * +nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); + struct drm_device *dev = dev_priv->dev; + + switch (dev_priv->gart_info.type) { + case NOUVEAU_GART_AGP: + return ttm_agp_backend_init(bdev, dev->agp->bridge); + case NOUVEAU_GART_SGDMA: + return nouveau_sgdma_init_ttm(dev); + default: + NV_ERROR(dev, "Unknown GART type %d\n", + dev_priv->gart_info.type); + break; + } + + return NULL; +} + +static int +nouveau_bo_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags) +{ + /* We'll do this from user space. */ + return 0; +} + +static int +nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, + struct ttm_mem_type_manager *man) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); + struct drm_device *dev = dev_priv->dev; + + switch (type) { + case TTM_PL_SYSTEM: + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; + man->available_caching = TTM_PL_MASK_CACHING; + man->default_caching = TTM_PL_FLAG_CACHED; + break; + case TTM_PL_VRAM: + man->flags = TTM_MEMTYPE_FLAG_FIXED | + TTM_MEMTYPE_FLAG_MAPPABLE | + TTM_MEMTYPE_FLAG_NEEDS_IOREMAP; + man->available_caching = TTM_PL_FLAG_UNCACHED | + TTM_PL_FLAG_WC; + man->default_caching = TTM_PL_FLAG_WC; + + man->io_addr = NULL; + man->io_offset = drm_get_resource_start(dev, 1); + man->io_size = drm_get_resource_len(dev, 1); + if (man->io_size > nouveau_mem_fb_amount(dev)) + man->io_size = nouveau_mem_fb_amount(dev); + + man->gpu_offset = dev_priv->vm_vram_base; + break; + case TTM_PL_TT: + switch (dev_priv->gart_info.type) { + case NOUVEAU_GART_AGP: + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | + TTM_MEMTYPE_FLAG_NEEDS_IOREMAP; + man->available_caching = TTM_PL_FLAG_UNCACHED; + man->default_caching = TTM_PL_FLAG_UNCACHED; + break; + case NOUVEAU_GART_SGDMA: + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | + TTM_MEMTYPE_FLAG_CMA; + man->available_caching = TTM_PL_MASK_CACHING; + man->default_caching = TTM_PL_FLAG_CACHED; + break; + default: + NV_ERROR(dev, "Unknown GART type: %d\n", + dev_priv->gart_info.type); + return -EINVAL; + } + + man->io_offset = dev_priv->gart_info.aper_base; + man->io_size = dev_priv->gart_info.aper_size; + man->io_addr = NULL; + man->gpu_offset = dev_priv->vm_gart_base; + break; + default: + NV_ERROR(dev, "Unsupported memory type %u\n", (unsigned)type); + return -EINVAL; + } + return 0; +} + +static void +nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) +{ + struct nouveau_bo *nvbo = nouveau_bo(bo); + + switch (bo->mem.mem_type) { + default: + nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_SYSTEM); + break; + } +} + + +/* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access + * TTM_PL_{VRAM,TT} directly. + */ +static int +nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, + struct nouveau_bo *nvbo, bool evict, bool no_wait, + struct ttm_mem_reg *new_mem) +{ + struct nouveau_fence *fence = NULL; + int ret; + + ret = nouveau_fence_new(chan, &fence, true); + if (ret) + return ret; + + ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, + evict, no_wait, new_mem); + nouveau_fence_unref((void *)&fence); + return ret; +} + +static inline uint32_t +nouveau_bo_mem_ctxdma(struct nouveau_bo *nvbo, struct nouveau_channel *chan, + struct ttm_mem_reg *mem) +{ + if (chan == nouveau_bdev(nvbo->bo.bdev)->channel) { + if (mem->mem_type == TTM_PL_TT) + return NvDmaGART; + return NvDmaVRAM; + } + + if (mem->mem_type == TTM_PL_TT) + return chan->gart_handle; + return chan->vram_handle; +} + +static int +nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, int no_wait, + struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) +{ + struct nouveau_bo *nvbo = nouveau_bo(bo); + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct nouveau_channel *chan; + uint64_t src_offset, dst_offset; + uint32_t page_count; + int ret; + + chan = nvbo->channel; + if (!chan || nvbo->tile_flags || nvbo->no_vm) { + chan = dev_priv->channel; + if (!chan) + return -EINVAL; + } + + src_offset = old_mem->mm_node->start << PAGE_SHIFT; + dst_offset = new_mem->mm_node->start << PAGE_SHIFT; + if (chan != dev_priv->channel) { + if (old_mem->mem_type == TTM_PL_TT) + src_offset += dev_priv->vm_gart_base; + else + src_offset += dev_priv->vm_vram_base; + + if (new_mem->mem_type == TTM_PL_TT) + dst_offset += dev_priv->vm_gart_base; + else + dst_offset += dev_priv->vm_vram_base; + } + + ret = RING_SPACE(chan, 3); + if (ret) + return ret; + BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_SOURCE, 2); + OUT_RING(chan, nouveau_bo_mem_ctxdma(nvbo, chan, old_mem)); + OUT_RING(chan, nouveau_bo_mem_ctxdma(nvbo, chan, new_mem)); + + if (dev_priv->card_type >= NV_50) { + ret = RING_SPACE(chan, 4); + if (ret) + return ret; + BEGIN_RING(chan, NvSubM2MF, 0x0200, 1); + OUT_RING(chan, 1); + BEGIN_RING(chan, NvSubM2MF, 0x021c, 1); + OUT_RING(chan, 1); + } + + page_count = new_mem->num_pages; + while (page_count) { + int line_count = (page_count > 2047) ? 2047 : page_count; + + if (dev_priv->card_type >= NV_50) { + ret = RING_SPACE(chan, 3); + if (ret) + return ret; + BEGIN_RING(chan, NvSubM2MF, 0x0238, 2); + OUT_RING(chan, upper_32_bits(src_offset)); + OUT_RING(chan, upper_32_bits(dst_offset)); + } + ret = RING_SPACE(chan, 11); + if (ret) + return ret; + BEGIN_RING(chan, NvSubM2MF, + NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + OUT_RING(chan, lower_32_bits(src_offset)); + OUT_RING(chan, lower_32_bits(dst_offset)); + OUT_RING(chan, PAGE_SIZE); /* src_pitch */ + OUT_RING(chan, PAGE_SIZE); /* dst_pitch */ + OUT_RING(chan, PAGE_SIZE); /* line_length */ + OUT_RING(chan, line_count); + OUT_RING(chan, (1<<8)|(1<<0)); + OUT_RING(chan, 0); + BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1); + OUT_RING(chan, 0); + + page_count -= line_count; + src_offset += (PAGE_SIZE * line_count); + dst_offset += (PAGE_SIZE * line_count); + } + + return nouveau_bo_move_accel_cleanup(chan, nvbo, evict, no_wait, new_mem); +} + +static int +nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, + bool no_wait, struct ttm_mem_reg *new_mem) +{ + u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; + struct ttm_placement placement; + struct ttm_mem_reg tmp_mem; + int ret; + + placement.fpfn = placement.lpfn = 0; + placement.num_placement = placement.num_busy_placement = 1; + placement.placement = &placement_memtype; + + tmp_mem = *new_mem; + tmp_mem.mm_node = NULL; + ret = ttm_bo_mem_space(bo, &placement, &tmp_mem, intr, no_wait); + if (ret) + return ret; + + ret = ttm_tt_bind(bo->ttm, &tmp_mem); + if (ret) + goto out; + + ret = nouveau_bo_move_m2mf(bo, true, no_wait, &bo->mem, &tmp_mem); + if (ret) + goto out; + + ret = ttm_bo_move_ttm(bo, evict, no_wait, new_mem); +out: + if (tmp_mem.mm_node) { + spin_lock(&bo->bdev->glob->lru_lock); + drm_mm_put_block(tmp_mem.mm_node); + spin_unlock(&bo->bdev->glob->lru_lock); + } + + return ret; +} + +static int +nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, + bool no_wait, struct ttm_mem_reg *new_mem) +{ + u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; + struct ttm_placement placement; + struct ttm_mem_reg tmp_mem; + int ret; + + placement.fpfn = placement.lpfn = 0; + placement.num_placement = placement.num_busy_placement = 1; + placement.placement = &placement_memtype; + + tmp_mem = *new_mem; + tmp_mem.mm_node = NULL; + ret = ttm_bo_mem_space(bo, &placement, &tmp_mem, intr, no_wait); + if (ret) + return ret; + + ret = ttm_bo_move_ttm(bo, evict, no_wait, &tmp_mem); + if (ret) + goto out; + + ret = nouveau_bo_move_m2mf(bo, true, no_wait, &bo->mem, new_mem); + if (ret) + goto out; + +out: + if (tmp_mem.mm_node) { + spin_lock(&bo->bdev->glob->lru_lock); + drm_mm_put_block(tmp_mem.mm_node); + spin_unlock(&bo->bdev->glob->lru_lock); + } + + return ret; +} + +static int +nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, + bool no_wait, struct ttm_mem_reg *new_mem) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct nouveau_bo *nvbo = nouveau_bo(bo); + struct drm_device *dev = dev_priv->dev; + struct ttm_mem_reg *old_mem = &bo->mem; + int ret; + + if (dev_priv->card_type == NV_50 && new_mem->mem_type == TTM_PL_VRAM && + !nvbo->no_vm) { + uint64_t offset = new_mem->mm_node->start << PAGE_SHIFT; + + ret = nv50_mem_vm_bind_linear(dev, + offset + dev_priv->vm_vram_base, + new_mem->size, nvbo->tile_flags, + offset); + if (ret) + return ret; + } + + if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE) + return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); + + if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { + BUG_ON(bo->mem.mm_node != NULL); + bo->mem = *new_mem; + new_mem->mm_node = NULL; + return 0; + } + + if (new_mem->mem_type == TTM_PL_SYSTEM) { + if (old_mem->mem_type == TTM_PL_SYSTEM) + return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); + if (nouveau_bo_move_flipd(bo, evict, intr, no_wait, new_mem)) + return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); + } else if (old_mem->mem_type == TTM_PL_SYSTEM) { + if (nouveau_bo_move_flips(bo, evict, intr, no_wait, new_mem)) + return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); + } else { + if (nouveau_bo_move_m2mf(bo, evict, no_wait, old_mem, new_mem)) + return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); + } + + return 0; +} + +static int +nouveau_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp) +{ + return 0; +} + +struct ttm_bo_driver nouveau_bo_driver = { + .create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry, + .invalidate_caches = nouveau_bo_invalidate_caches, + .init_mem_type = nouveau_bo_init_mem_type, + .evict_flags = nouveau_bo_evict_flags, + .move = nouveau_bo_move, + .verify_access = nouveau_bo_verify_access, + .sync_obj_signaled = nouveau_fence_signalled, + .sync_obj_wait = nouveau_fence_wait, + .sync_obj_flush = nouveau_fence_flush, + .sync_obj_unref = nouveau_fence_unref, + .sync_obj_ref = nouveau_fence_ref, +}; + diff --git a/drivers/gpu/drm/nouveau/nouveau_calc.c b/drivers/gpu/drm/nouveau/nouveau_calc.c new file mode 100644 index 0000000000000000000000000000000000000000..ee2b84504d050f2fd68f66a8254c366485816405 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_calc.c @@ -0,0 +1,478 @@ +/* + * Copyright 1993-2003 NVIDIA, Corporation + * Copyright 2007-2009 Stuart Bennett + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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 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 "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_hw.h" + +/****************************************************************************\ +* * +* The video arbitration routines calculate some "magic" numbers. Fixes * +* the snow seen when accessing the framebuffer without it. * +* It just works (I hope). * +* * +\****************************************************************************/ + +struct nv_fifo_info { + int lwm; + int burst; +}; + +struct nv_sim_state { + int pclk_khz; + int mclk_khz; + int nvclk_khz; + int bpp; + int mem_page_miss; + int mem_latency; + int memory_type; + int memory_width; + int two_heads; +}; + +static void +nv04_calc_arb(struct nv_fifo_info *fifo, struct nv_sim_state *arb) +{ + int pagemiss, cas, width, bpp; + int nvclks, mclks, pclks, crtpagemiss; + int found, mclk_extra, mclk_loop, cbs, m1, p1; + int mclk_freq, pclk_freq, nvclk_freq; + int us_m, us_n, us_p, crtc_drain_rate; + int cpm_us, us_crt, clwm; + + pclk_freq = arb->pclk_khz; + mclk_freq = arb->mclk_khz; + nvclk_freq = arb->nvclk_khz; + pagemiss = arb->mem_page_miss; + cas = arb->mem_latency; + width = arb->memory_width >> 6; + bpp = arb->bpp; + cbs = 128; + + pclks = 2; + nvclks = 10; + mclks = 13 + cas; + mclk_extra = 3; + found = 0; + + while (!found) { + found = 1; + + mclk_loop = mclks + mclk_extra; + us_m = mclk_loop * 1000 * 1000 / mclk_freq; + us_n = nvclks * 1000 * 1000 / nvclk_freq; + us_p = nvclks * 1000 * 1000 / pclk_freq; + + crtc_drain_rate = pclk_freq * bpp / 8; + crtpagemiss = 2; + crtpagemiss += 1; + cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq; + us_crt = cpm_us + us_m + us_n + us_p; + clwm = us_crt * crtc_drain_rate / (1000 * 1000); + clwm++; + + m1 = clwm + cbs - 512; + p1 = m1 * pclk_freq / mclk_freq; + p1 = p1 * bpp / 8; + if ((p1 < m1 && m1 > 0) || clwm > 519) { + found = !mclk_extra; + mclk_extra--; + } + if (clwm < 384) + clwm = 384; + + fifo->lwm = clwm; + fifo->burst = cbs; + } +} + +static void +nv10_calc_arb(struct nv_fifo_info *fifo, struct nv_sim_state *arb) +{ + int fill_rate, drain_rate; + int pclks, nvclks, mclks, xclks; + int pclk_freq, nvclk_freq, mclk_freq; + int fill_lat, extra_lat; + int max_burst_o, max_burst_l; + int fifo_len, min_lwm, max_lwm; + const int burst_lat = 80; /* Maximum allowable latency due + * to the CRTC FIFO burst. (ns) */ + + pclk_freq = arb->pclk_khz; + nvclk_freq = arb->nvclk_khz; + mclk_freq = arb->mclk_khz; + + fill_rate = mclk_freq * arb->memory_width / 8; /* kB/s */ + drain_rate = pclk_freq * arb->bpp / 8; /* kB/s */ + + fifo_len = arb->two_heads ? 1536 : 1024; /* B */ + + /* Fixed FIFO refill latency. */ + + pclks = 4; /* lwm detect. */ + + nvclks = 3 /* lwm -> sync. */ + + 2 /* fbi bus cycles (1 req + 1 busy) */ + + 1 /* 2 edge sync. may be very close to edge so + * just put one. */ + + 1 /* fbi_d_rdv_n */ + + 1 /* Fbi_d_rdata */ + + 1; /* crtfifo load */ + + mclks = 1 /* 2 edge sync. may be very close to edge so + * just put one. */ + + 1 /* arb_hp_req */ + + 5 /* tiling pipeline */ + + 2 /* latency fifo */ + + 2 /* memory request to fbio block */ + + 7; /* data returned from fbio block */ + + /* Need to accumulate 256 bits for read */ + mclks += (arb->memory_type == 0 ? 2 : 1) + * arb->memory_width / 32; + + fill_lat = mclks * 1000 * 1000 / mclk_freq /* minimum mclk latency */ + + nvclks * 1000 * 1000 / nvclk_freq /* nvclk latency */ + + pclks * 1000 * 1000 / pclk_freq; /* pclk latency */ + + /* Conditional FIFO refill latency. */ + + xclks = 2 * arb->mem_page_miss + mclks /* Extra latency due to + * the overlay. */ + + 2 * arb->mem_page_miss /* Extra pagemiss latency. */ + + (arb->bpp == 32 ? 8 : 4); /* Margin of error. */ + + extra_lat = xclks * 1000 * 1000 / mclk_freq; + + if (arb->two_heads) + /* Account for another CRTC. */ + extra_lat += fill_lat + extra_lat + burst_lat; + + /* FIFO burst */ + + /* Max burst not leading to overflows. */ + max_burst_o = (1 + fifo_len - extra_lat * drain_rate / (1000 * 1000)) + * (fill_rate / 1000) / ((fill_rate - drain_rate) / 1000); + fifo->burst = min(max_burst_o, 1024); + + /* Max burst value with an acceptable latency. */ + max_burst_l = burst_lat * fill_rate / (1000 * 1000); + fifo->burst = min(max_burst_l, fifo->burst); + + fifo->burst = rounddown_pow_of_two(fifo->burst); + + /* FIFO low watermark */ + + min_lwm = (fill_lat + extra_lat) * drain_rate / (1000 * 1000) + 1; + max_lwm = fifo_len - fifo->burst + + fill_lat * drain_rate / (1000 * 1000) + + fifo->burst * drain_rate / fill_rate; + + fifo->lwm = min_lwm + 10 * (max_lwm - min_lwm) / 100; /* Empirical. */ +} + +static void +nv04_update_arb(struct drm_device *dev, int VClk, int bpp, + int *burst, int *lwm) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv_fifo_info fifo_data; + struct nv_sim_state sim_data; + int MClk = nouveau_hw_get_clock(dev, MPLL); + int NVClk = nouveau_hw_get_clock(dev, NVPLL); + uint32_t cfg1 = nvReadFB(dev, NV_PFB_CFG1); + + sim_data.pclk_khz = VClk; + sim_data.mclk_khz = MClk; + sim_data.nvclk_khz = NVClk; + sim_data.bpp = bpp; + sim_data.two_heads = nv_two_heads(dev); + if ((dev->pci_device & 0xffff) == 0x01a0 /*CHIPSET_NFORCE*/ || + (dev->pci_device & 0xffff) == 0x01f0 /*CHIPSET_NFORCE2*/) { + uint32_t type; + + pci_read_config_dword(pci_get_bus_and_slot(0, 1), 0x7c, &type); + + sim_data.memory_type = (type >> 12) & 1; + sim_data.memory_width = 64; + sim_data.mem_latency = 3; + sim_data.mem_page_miss = 10; + } else { + sim_data.memory_type = nvReadFB(dev, NV_PFB_CFG0) & 0x1; + sim_data.memory_width = (nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64; + sim_data.mem_latency = cfg1 & 0xf; + sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1); + } + + if (dev_priv->card_type == NV_04) + nv04_calc_arb(&fifo_data, &sim_data); + else + nv10_calc_arb(&fifo_data, &sim_data); + + *burst = ilog2(fifo_data.burst >> 4); + *lwm = fifo_data.lwm >> 3; +} + +static void +nv30_update_arb(int *burst, int *lwm) +{ + unsigned int fifo_size, burst_size, graphics_lwm; + + fifo_size = 2048; + burst_size = 512; + graphics_lwm = fifo_size - burst_size; + + *burst = ilog2(burst_size >> 5); + *lwm = graphics_lwm >> 3; +} + +void +nouveau_calc_arb(struct drm_device *dev, int vclk, int bpp, int *burst, int *lwm) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->card_type < NV_30) + nv04_update_arb(dev, vclk, bpp, burst, lwm); + else if ((dev->pci_device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ || + (dev->pci_device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) { + *burst = 128; + *lwm = 0x0480; + } else + nv30_update_arb(burst, lwm); +} + +static int +getMNP_single(struct drm_device *dev, struct pll_lims *pll_lim, int clk, + struct nouveau_pll_vals *bestpv) +{ + /* Find M, N and P for a single stage PLL + * + * Note that some bioses (NV3x) have lookup tables of precomputed MNP + * values, but we're too lazy to use those atm + * + * "clk" parameter in kHz + * returns calculated clock + */ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int cv = dev_priv->vbios->chip_version; + int minvco = pll_lim->vco1.minfreq, maxvco = pll_lim->vco1.maxfreq; + int minM = pll_lim->vco1.min_m, maxM = pll_lim->vco1.max_m; + int minN = pll_lim->vco1.min_n, maxN = pll_lim->vco1.max_n; + int minU = pll_lim->vco1.min_inputfreq; + int maxU = pll_lim->vco1.max_inputfreq; + int minP = pll_lim->max_p ? pll_lim->min_p : 0; + int maxP = pll_lim->max_p ? pll_lim->max_p : pll_lim->max_usable_log2p; + int crystal = pll_lim->refclk; + int M, N, thisP, P; + int clkP, calcclk; + int delta, bestdelta = INT_MAX; + int bestclk = 0; + + /* this division verified for nv20, nv18, nv28 (Haiku), and nv34 */ + /* possibly correlated with introduction of 27MHz crystal */ + if (dev_priv->card_type < NV_50) { + if (cv < 0x17 || cv == 0x1a || cv == 0x20) { + if (clk > 250000) + maxM = 6; + if (clk > 340000) + maxM = 2; + } else if (cv < 0x40) { + if (clk > 150000) + maxM = 6; + if (clk > 200000) + maxM = 4; + if (clk > 340000) + maxM = 2; + } + } + + P = pll_lim->max_p ? maxP : (1 << maxP); + if ((clk * P) < minvco) { + minvco = clk * maxP; + maxvco = minvco * 2; + } + + if (clk + clk/200 > maxvco) /* +0.5% */ + maxvco = clk + clk/200; + + /* NV34 goes maxlog2P->0, NV20 goes 0->maxlog2P */ + for (thisP = minP; thisP <= maxP; thisP++) { + P = pll_lim->max_p ? thisP : (1 << thisP); + clkP = clk * P; + + if (clkP < minvco) + continue; + if (clkP > maxvco) + return bestclk; + + for (M = minM; M <= maxM; M++) { + if (crystal/M < minU) + return bestclk; + if (crystal/M > maxU) + continue; + + /* add crystal/2 to round better */ + N = (clkP * M + crystal/2) / crystal; + + if (N < minN) + continue; + if (N > maxN) + break; + + /* more rounding additions */ + calcclk = ((N * crystal + P/2) / P + M/2) / M; + delta = abs(calcclk - clk); + /* we do an exhaustive search rather than terminating + * on an optimality condition... + */ + if (delta < bestdelta) { + bestdelta = delta; + bestclk = calcclk; + bestpv->N1 = N; + bestpv->M1 = M; + bestpv->log2P = thisP; + if (delta == 0) /* except this one */ + return bestclk; + } + } + } + + return bestclk; +} + +static int +getMNP_double(struct drm_device *dev, struct pll_lims *pll_lim, int clk, + struct nouveau_pll_vals *bestpv) +{ + /* Find M, N and P for a two stage PLL + * + * Note that some bioses (NV30+) have lookup tables of precomputed MNP + * values, but we're too lazy to use those atm + * + * "clk" parameter in kHz + * returns calculated clock + */ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int chip_version = dev_priv->vbios->chip_version; + int minvco1 = pll_lim->vco1.minfreq, maxvco1 = pll_lim->vco1.maxfreq; + int minvco2 = pll_lim->vco2.minfreq, maxvco2 = pll_lim->vco2.maxfreq; + int minU1 = pll_lim->vco1.min_inputfreq, minU2 = pll_lim->vco2.min_inputfreq; + int maxU1 = pll_lim->vco1.max_inputfreq, maxU2 = pll_lim->vco2.max_inputfreq; + int minM1 = pll_lim->vco1.min_m, maxM1 = pll_lim->vco1.max_m; + int minN1 = pll_lim->vco1.min_n, maxN1 = pll_lim->vco1.max_n; + int minM2 = pll_lim->vco2.min_m, maxM2 = pll_lim->vco2.max_m; + int minN2 = pll_lim->vco2.min_n, maxN2 = pll_lim->vco2.max_n; + int maxlog2P = pll_lim->max_usable_log2p; + int crystal = pll_lim->refclk; + bool fixedgain2 = (minM2 == maxM2 && minN2 == maxN2); + int M1, N1, M2, N2, log2P; + int clkP, calcclk1, calcclk2, calcclkout; + int delta, bestdelta = INT_MAX; + int bestclk = 0; + + int vco2 = (maxvco2 - maxvco2/200) / 2; + for (log2P = 0; clk && log2P < maxlog2P && clk <= (vco2 >> log2P); log2P++) + ; + clkP = clk << log2P; + + if (maxvco2 < clk + clk/200) /* +0.5% */ + maxvco2 = clk + clk/200; + + for (M1 = minM1; M1 <= maxM1; M1++) { + if (crystal/M1 < minU1) + return bestclk; + if (crystal/M1 > maxU1) + continue; + + for (N1 = minN1; N1 <= maxN1; N1++) { + calcclk1 = crystal * N1 / M1; + if (calcclk1 < minvco1) + continue; + if (calcclk1 > maxvco1) + break; + + for (M2 = minM2; M2 <= maxM2; M2++) { + if (calcclk1/M2 < minU2) + break; + if (calcclk1/M2 > maxU2) + continue; + + /* add calcclk1/2 to round better */ + N2 = (clkP * M2 + calcclk1/2) / calcclk1; + if (N2 < minN2) + continue; + if (N2 > maxN2) + break; + + if (!fixedgain2) { + if (chip_version < 0x60) + if (N2/M2 < 4 || N2/M2 > 10) + continue; + + calcclk2 = calcclk1 * N2 / M2; + if (calcclk2 < minvco2) + break; + if (calcclk2 > maxvco2) + continue; + } else + calcclk2 = calcclk1; + + calcclkout = calcclk2 >> log2P; + delta = abs(calcclkout - clk); + /* we do an exhaustive search rather than terminating + * on an optimality condition... + */ + if (delta < bestdelta) { + bestdelta = delta; + bestclk = calcclkout; + bestpv->N1 = N1; + bestpv->M1 = M1; + bestpv->N2 = N2; + bestpv->M2 = M2; + bestpv->log2P = log2P; + if (delta == 0) /* except this one */ + return bestclk; + } + } + } + } + + return bestclk; +} + +int +nouveau_calc_pll_mnp(struct drm_device *dev, struct pll_lims *pll_lim, int clk, + struct nouveau_pll_vals *pv) +{ + int outclk; + + if (!pll_lim->vco2.maxfreq) + outclk = getMNP_single(dev, pll_lim, clk, pv); + else + outclk = getMNP_double(dev, pll_lim, clk, pv); + + if (!outclk) + NV_ERROR(dev, "Could not find a compatible set of PLL values\n"); + + return outclk; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c new file mode 100644 index 0000000000000000000000000000000000000000..9aaa972f882248002d59b4d02d7bbc8f47ba17b8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -0,0 +1,468 @@ +/* + * Copyright 2005-2006 Stephane Marchesin + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_dma.h" + +static int +nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_bo *pb = chan->pushbuf_bo; + struct nouveau_gpuobj *pushbuf = NULL; + uint32_t start = pb->bo.mem.mm_node->start << PAGE_SHIFT; + int ret; + + if (pb->bo.mem.mem_type == TTM_PL_TT) { + ret = nouveau_gpuobj_gart_dma_new(chan, 0, + dev_priv->gart_info.aper_size, + NV_DMA_ACCESS_RO, &pushbuf, + NULL); + chan->pushbuf_base = start; + } else + if (dev_priv->card_type != NV_04) { + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, + dev_priv->fb_available_size, + NV_DMA_ACCESS_RO, + NV_DMA_TARGET_VIDMEM, &pushbuf); + chan->pushbuf_base = start; + } else { + /* NV04 cmdbuf hack, from original ddx.. not sure of it's + * exact reason for existing :) PCI access to cmdbuf in + * VRAM. + */ + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, + drm_get_resource_start(dev, 1), + dev_priv->fb_available_size, + NV_DMA_ACCESS_RO, + NV_DMA_TARGET_PCI, &pushbuf); + chan->pushbuf_base = start; + } + + ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf, &chan->pushbuf); + if (ret) { + NV_ERROR(dev, "Error referencing pushbuf ctxdma: %d\n", ret); + if (pushbuf != dev_priv->gart_info.sg_ctxdma) + nouveau_gpuobj_del(dev, &pushbuf); + return ret; + } + + return 0; +} + +static struct nouveau_bo * +nouveau_channel_user_pushbuf_alloc(struct drm_device *dev) +{ + struct nouveau_bo *pushbuf = NULL; + int location, ret; + + if (nouveau_vram_pushbuf) + location = TTM_PL_FLAG_VRAM; + else + location = TTM_PL_FLAG_TT; + + ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, false, + true, &pushbuf); + if (ret) { + NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret); + return NULL; + } + + ret = nouveau_bo_pin(pushbuf, location); + if (ret) { + NV_ERROR(dev, "error pinning DMA push buffer: %d\n", ret); + nouveau_bo_ref(NULL, &pushbuf); + return NULL; + } + + return pushbuf; +} + +/* allocates and initializes a fifo for user space consumption */ +int +nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, + struct drm_file *file_priv, + uint32_t vram_handle, uint32_t tt_handle) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + struct nouveau_channel *chan; + int channel, user; + int ret; + + /* + * Alright, here is the full story + * Nvidia cards have multiple hw fifo contexts (praise them for that, + * no complicated crash-prone context switches) + * We allocate a new context for each app and let it write to it + * directly (woo, full userspace command submission !) + * When there are no more contexts, you lost + */ + for (channel = 0; channel < pfifo->channels; channel++) { + if (dev_priv->fifos[channel] == NULL) + break; + } + + /* no more fifos. you lost. */ + if (channel == pfifo->channels) + return -EINVAL; + + dev_priv->fifos[channel] = kzalloc(sizeof(struct nouveau_channel), + GFP_KERNEL); + if (!dev_priv->fifos[channel]) + return -ENOMEM; + dev_priv->fifo_alloc_count++; + chan = dev_priv->fifos[channel]; + INIT_LIST_HEAD(&chan->nvsw.vbl_wait); + INIT_LIST_HEAD(&chan->fence.pending); + chan->dev = dev; + chan->id = channel; + chan->file_priv = file_priv; + chan->vram_handle = vram_handle; + chan->gart_handle = tt_handle; + + NV_INFO(dev, "Allocating FIFO number %d\n", channel); + + /* Allocate DMA push buffer */ + chan->pushbuf_bo = nouveau_channel_user_pushbuf_alloc(dev); + if (!chan->pushbuf_bo) { + ret = -ENOMEM; + NV_ERROR(dev, "pushbuf %d\n", ret); + nouveau_channel_free(chan); + return ret; + } + + /* Locate channel's user control regs */ + if (dev_priv->card_type < NV_40) + user = NV03_USER(channel); + else + if (dev_priv->card_type < NV_50) + user = NV40_USER(channel); + else + user = NV50_USER(channel); + + chan->user = ioremap(pci_resource_start(dev->pdev, 0) + user, + PAGE_SIZE); + if (!chan->user) { + NV_ERROR(dev, "ioremap of regs failed.\n"); + nouveau_channel_free(chan); + return -ENOMEM; + } + chan->user_put = 0x40; + chan->user_get = 0x44; + + /* Allocate space for per-channel fixed notifier memory */ + ret = nouveau_notifier_init_channel(chan); + if (ret) { + NV_ERROR(dev, "ntfy %d\n", ret); + nouveau_channel_free(chan); + return ret; + } + + /* Setup channel's default objects */ + ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle); + if (ret) { + NV_ERROR(dev, "gpuobj %d\n", ret); + nouveau_channel_free(chan); + return ret; + } + + /* Create a dma object for the push buffer */ + ret = nouveau_channel_pushbuf_ctxdma_init(chan); + if (ret) { + NV_ERROR(dev, "pbctxdma %d\n", ret); + nouveau_channel_free(chan); + return ret; + } + + /* disable the fifo caches */ + pfifo->reassign(dev, false); + + /* Create a graphics context for new channel */ + ret = pgraph->create_context(chan); + if (ret) { + nouveau_channel_free(chan); + return ret; + } + + /* Construct inital RAMFC for new channel */ + ret = pfifo->create_context(chan); + if (ret) { + nouveau_channel_free(chan); + return ret; + } + + pfifo->reassign(dev, true); + + ret = nouveau_dma_init(chan); + if (!ret) + ret = nouveau_fence_init(chan); + if (ret) { + nouveau_channel_free(chan); + return ret; + } + + nouveau_debugfs_channel_init(chan); + + NV_INFO(dev, "%s: initialised FIFO %d\n", __func__, channel); + *chan_ret = chan; + return 0; +} + +int +nouveau_channel_idle(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->engine; + uint32_t caches; + int idle; + + if (!chan) { + NV_ERROR(dev, "no channel...\n"); + return 1; + } + + caches = nv_rd32(dev, NV03_PFIFO_CACHES); + nv_wr32(dev, NV03_PFIFO_CACHES, caches & ~1); + + if (engine->fifo.channel_id(dev) != chan->id) { + struct nouveau_gpuobj *ramfc = + chan->ramfc ? chan->ramfc->gpuobj : NULL; + + if (!ramfc) { + NV_ERROR(dev, "No RAMFC for channel %d\n", chan->id); + return 1; + } + + engine->instmem.prepare_access(dev, false); + if (nv_ro32(dev, ramfc, 0) != nv_ro32(dev, ramfc, 1)) + idle = 0; + else + idle = 1; + engine->instmem.finish_access(dev); + } else { + idle = (nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET) == + nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); + } + + nv_wr32(dev, NV03_PFIFO_CACHES, caches); + return idle; +} + +/* stops a fifo */ +void +nouveau_channel_free(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + unsigned long flags; + int ret; + + NV_INFO(dev, "%s: freeing fifo %d\n", __func__, chan->id); + + nouveau_debugfs_channel_fini(chan); + + /* Give outstanding push buffers a chance to complete */ + spin_lock_irqsave(&chan->fence.lock, flags); + nouveau_fence_update(chan); + spin_unlock_irqrestore(&chan->fence.lock, flags); + if (chan->fence.sequence != chan->fence.sequence_ack) { + struct nouveau_fence *fence = NULL; + + ret = nouveau_fence_new(chan, &fence, true); + if (ret == 0) { + ret = nouveau_fence_wait(fence, NULL, false, false); + nouveau_fence_unref((void *)&fence); + } + + if (ret) + NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id); + } + + /* Ensure all outstanding fences are signaled. They should be if the + * above attempts at idling were OK, but if we failed this'll tell TTM + * we're done with the buffers. + */ + nouveau_fence_fini(chan); + + /* Ensure the channel is no longer active on the GPU */ + pfifo->reassign(dev, false); + + if (pgraph->channel(dev) == chan) { + pgraph->fifo_access(dev, false); + pgraph->unload_context(dev); + pgraph->fifo_access(dev, true); + } + pgraph->destroy_context(chan); + + if (pfifo->channel_id(dev) == chan->id) { + pfifo->disable(dev); + pfifo->unload_context(dev); + pfifo->enable(dev); + } + pfifo->destroy_context(chan); + + pfifo->reassign(dev, true); + + /* Release the channel's resources */ + nouveau_gpuobj_ref_del(dev, &chan->pushbuf); + if (chan->pushbuf_bo) { + nouveau_bo_unpin(chan->pushbuf_bo); + nouveau_bo_ref(NULL, &chan->pushbuf_bo); + } + nouveau_gpuobj_channel_takedown(chan); + nouveau_notifier_takedown_channel(chan); + if (chan->user) + iounmap(chan->user); + + dev_priv->fifos[chan->id] = NULL; + dev_priv->fifo_alloc_count--; + kfree(chan); +} + +/* cleans up all the fifos from file_priv */ +void +nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->engine; + int i; + + NV_DEBUG(dev, "clearing FIFO enables from file_priv\n"); + for (i = 0; i < engine->fifo.channels; i++) { + struct nouveau_channel *chan = dev_priv->fifos[i]; + + if (chan && chan->file_priv == file_priv) + nouveau_channel_free(chan); + } +} + +int +nouveau_channel_owner(struct drm_device *dev, struct drm_file *file_priv, + int channel) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->engine; + + if (channel >= engine->fifo.channels) + return 0; + if (dev_priv->fifos[channel] == NULL) + return 0; + + return (dev_priv->fifos[channel]->file_priv == file_priv); +} + +/*********************************** + * ioctls wrapping the functions + ***********************************/ + +static int +nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_channel_alloc *init = data; + struct nouveau_channel *chan; + int ret; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + + if (dev_priv->engine.graph.accel_blocked) + return -ENODEV; + + if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) + return -EINVAL; + + ret = nouveau_channel_alloc(dev, &chan, file_priv, + init->fb_ctxdma_handle, + init->tt_ctxdma_handle); + if (ret) + return ret; + init->channel = chan->id; + + init->subchan[0].handle = NvM2MF; + if (dev_priv->card_type < NV_50) + init->subchan[0].grclass = 0x0039; + else + init->subchan[0].grclass = 0x5039; + init->nr_subchan = 1; + + /* Named memory object area */ + ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem, + &init->notifier_handle); + if (ret) { + nouveau_channel_free(chan); + return ret; + } + + return 0; +} + +static int +nouveau_ioctl_fifo_free(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_channel_free *cfree = data; + struct nouveau_channel *chan; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan); + + nouveau_channel_free(chan); + return 0; +} + +/*********************************** + * finally, the ioctl table + ***********************************/ + +struct drm_ioctl_desc nouveau_ioctls[] = { + DRM_IOCTL_DEF(DRM_NOUVEAU_CARD_INIT, nouveau_ioctl_card_init, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PUSHBUF_CALL, nouveau_gem_ioctl_pushbuf_call, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PIN, nouveau_gem_ioctl_pin, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_UNPIN, nouveau_gem_ioctl_unpin, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PUSHBUF_CALL2, nouveau_gem_ioctl_pushbuf_call2, DRM_AUTH), +}; + +int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c new file mode 100644 index 0000000000000000000000000000000000000000..032cf098fa1c7cc8b8c5e22b8429aa061c9607d0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -0,0 +1,824 @@ +/* + * Copyright (C) 2008 Maarten Maathuis. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm_edid.h" +#include "drm_crtc_helper.h" +#include "nouveau_reg.h" +#include "nouveau_drv.h" +#include "nouveau_encoder.h" +#include "nouveau_crtc.h" +#include "nouveau_connector.h" +#include "nouveau_hw.h" + +static inline struct drm_encoder_slave_funcs * +get_slave_funcs(struct nouveau_encoder *enc) +{ + return to_encoder_slave(to_drm_encoder(enc))->slave_funcs; +} + +static struct nouveau_encoder * +find_encoder_by_type(struct drm_connector *connector, int type) +{ + struct drm_device *dev = connector->dev; + struct nouveau_encoder *nv_encoder; + struct drm_mode_object *obj; + int i, id; + + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + id = connector->encoder_ids[i]; + if (!id) + break; + + obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER); + if (!obj) + continue; + nv_encoder = nouveau_encoder(obj_to_encoder(obj)); + + if (type == OUTPUT_ANY || nv_encoder->dcb->type == type) + return nv_encoder; + } + + return NULL; +} + +struct nouveau_connector * +nouveau_encoder_connector_get(struct nouveau_encoder *encoder) +{ + struct drm_device *dev = to_drm_encoder(encoder)->dev; + struct drm_connector *drm_connector; + + list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) { + if (drm_connector->encoder == to_drm_encoder(encoder)) + return nouveau_connector(drm_connector); + } + + return NULL; +} + + +static void +nouveau_connector_destroy(struct drm_connector *drm_connector) +{ + struct nouveau_connector *connector = nouveau_connector(drm_connector); + struct drm_device *dev = connector->base.dev; + + NV_DEBUG(dev, "\n"); + + if (!connector) + return; + + drm_sysfs_connector_remove(drm_connector); + drm_connector_cleanup(drm_connector); + kfree(drm_connector); +} + +static void +nouveau_connector_ddc_prepare(struct drm_connector *connector, int *flags) +{ + struct drm_nouveau_private *dev_priv = connector->dev->dev_private; + + if (dev_priv->card_type >= NV_50) + return; + + *flags = 0; + if (NVLockVgaCrtcs(dev_priv->dev, false)) + *flags |= 1; + if (nv_heads_tied(dev_priv->dev)) + *flags |= 2; + + if (*flags & 2) + NVSetOwner(dev_priv->dev, 0); /* necessary? */ +} + +static void +nouveau_connector_ddc_finish(struct drm_connector *connector, int flags) +{ + struct drm_nouveau_private *dev_priv = connector->dev->dev_private; + + if (dev_priv->card_type >= NV_50) + return; + + if (flags & 2) + NVSetOwner(dev_priv->dev, 4); + if (flags & 1) + NVLockVgaCrtcs(dev_priv->dev, true); +} + +static struct nouveau_i2c_chan * +nouveau_connector_ddc_detect(struct drm_connector *connector, + struct nouveau_encoder **pnv_encoder) +{ + struct drm_device *dev = connector->dev; + uint8_t out_buf[] = { 0x0, 0x0}, buf[2]; + int ret, flags, i; + + struct i2c_msg msgs[] = { + { + .addr = 0x50, + .flags = 0, + .len = 1, + .buf = out_buf, + }, + { + .addr = 0x50, + .flags = I2C_M_RD, + .len = 1, + .buf = buf, + } + }; + + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + struct nouveau_i2c_chan *i2c = NULL; + struct nouveau_encoder *nv_encoder; + struct drm_mode_object *obj; + int id; + + id = connector->encoder_ids[i]; + if (!id) + break; + + obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER); + if (!obj) + continue; + nv_encoder = nouveau_encoder(obj_to_encoder(obj)); + + if (nv_encoder->dcb->i2c_index < 0xf) + i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); + if (!i2c) + continue; + + nouveau_connector_ddc_prepare(connector, &flags); + ret = i2c_transfer(&i2c->adapter, msgs, 2); + nouveau_connector_ddc_finish(connector, flags); + + if (ret == 2) { + *pnv_encoder = nv_encoder; + return i2c; + } + } + + return NULL; +} + +static void +nouveau_connector_set_encoder(struct drm_connector *connector, + struct nouveau_encoder *nv_encoder) +{ + struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct drm_nouveau_private *dev_priv = connector->dev->dev_private; + struct drm_device *dev = connector->dev; + + if (nv_connector->detected_encoder == nv_encoder) + return; + nv_connector->detected_encoder = nv_encoder; + + if (nv_encoder->dcb->type == OUTPUT_LVDS || + nv_encoder->dcb->type == OUTPUT_TMDS) { + connector->doublescan_allowed = false; + connector->interlace_allowed = false; + } else { + connector->doublescan_allowed = true; + if (dev_priv->card_type == NV_20 || + (dev_priv->card_type == NV_10 && + (dev->pci_device & 0x0ff0) != 0x0100 && + (dev->pci_device & 0x0ff0) != 0x0150)) + /* HW is broken */ + connector->interlace_allowed = false; + else + connector->interlace_allowed = true; + } + + if (connector->connector_type == DRM_MODE_CONNECTOR_DVII) { + drm_connector_property_set_value(connector, + dev->mode_config.dvi_i_subconnector_property, + nv_encoder->dcb->type == OUTPUT_TMDS ? + DRM_MODE_SUBCONNECTOR_DVID : + DRM_MODE_SUBCONNECTOR_DVIA); + } +} + +static enum drm_connector_status +nouveau_connector_detect(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct nouveau_encoder *nv_encoder = NULL; + struct nouveau_i2c_chan *i2c; + int type, flags; + + if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) + nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); + if (nv_encoder && nv_connector->native_mode) { + nouveau_connector_set_encoder(connector, nv_encoder); + return connector_status_connected; + } + + i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); + if (i2c) { + nouveau_connector_ddc_prepare(connector, &flags); + nv_connector->edid = drm_get_edid(connector, &i2c->adapter); + nouveau_connector_ddc_finish(connector, flags); + drm_mode_connector_update_edid_property(connector, + nv_connector->edid); + if (!nv_connector->edid) { + NV_ERROR(dev, "DDC responded, but no EDID for %s\n", + drm_get_connector_name(connector)); + return connector_status_disconnected; + } + + if (nv_encoder->dcb->type == OUTPUT_DP && + !nouveau_dp_detect(to_drm_encoder(nv_encoder))) { + NV_ERROR(dev, "Detected %s, but failed init\n", + drm_get_connector_name(connector)); + return connector_status_disconnected; + } + + /* Override encoder type for DVI-I based on whether EDID + * says the display is digital or analog, both use the + * same i2c channel so the value returned from ddc_detect + * isn't necessarily correct. + */ + if (connector->connector_type == DRM_MODE_CONNECTOR_DVII) { + if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL) + type = OUTPUT_TMDS; + else + type = OUTPUT_ANALOG; + + nv_encoder = find_encoder_by_type(connector, type); + if (!nv_encoder) { + NV_ERROR(dev, "Detected %d encoder on %s, " + "but no object!\n", type, + drm_get_connector_name(connector)); + return connector_status_disconnected; + } + } + + nouveau_connector_set_encoder(connector, nv_encoder); + return connector_status_connected; + } + + nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); + if (!nv_encoder) + nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); + if (nv_encoder) { + struct drm_encoder *encoder = to_drm_encoder(nv_encoder); + struct drm_encoder_helper_funcs *helper = + encoder->helper_private; + + if (helper->detect(encoder, connector) == + connector_status_connected) { + nouveau_connector_set_encoder(connector, nv_encoder); + return connector_status_connected; + } + + } + + return connector_status_disconnected; +} + +static void +nouveau_connector_force(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct nouveau_encoder *nv_encoder; + int type; + + if (connector->connector_type == DRM_MODE_CONNECTOR_DVII) { + if (connector->force == DRM_FORCE_ON_DIGITAL) + type = OUTPUT_TMDS; + else + type = OUTPUT_ANALOG; + } else + type = OUTPUT_ANY; + + nv_encoder = find_encoder_by_type(connector, type); + if (!nv_encoder) { + NV_ERROR(dev, "can't find encoder to force %s on!\n", + drm_get_connector_name(connector)); + connector->status = connector_status_disconnected; + return; + } + + nouveau_connector_set_encoder(connector, nv_encoder); +} + +static int +nouveau_connector_set_property(struct drm_connector *connector, + struct drm_property *property, uint64_t value) +{ + struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; + struct drm_device *dev = connector->dev; + int ret; + + /* Scaling mode */ + if (property == dev->mode_config.scaling_mode_property) { + struct nouveau_crtc *nv_crtc = NULL; + bool modeset = false; + + switch (value) { + case DRM_MODE_SCALE_NONE: + case DRM_MODE_SCALE_FULLSCREEN: + case DRM_MODE_SCALE_CENTER: + case DRM_MODE_SCALE_ASPECT: + break; + default: + return -EINVAL; + } + + /* LVDS always needs gpu scaling */ + if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS && + value == DRM_MODE_SCALE_NONE) + return -EINVAL; + + /* Changing between GPU and panel scaling requires a full + * modeset + */ + if ((nv_connector->scaling_mode == DRM_MODE_SCALE_NONE) || + (value == DRM_MODE_SCALE_NONE)) + modeset = true; + nv_connector->scaling_mode = value; + + if (connector->encoder && connector->encoder->crtc) + nv_crtc = nouveau_crtc(connector->encoder->crtc); + if (!nv_crtc) + return 0; + + if (modeset || !nv_crtc->set_scale) { + ret = drm_crtc_helper_set_mode(&nv_crtc->base, + &nv_crtc->base.mode, + nv_crtc->base.x, + nv_crtc->base.y, NULL); + if (!ret) + return -EINVAL; + } else { + ret = nv_crtc->set_scale(nv_crtc, value, true); + if (ret) + return ret; + } + + return 0; + } + + /* Dithering */ + if (property == dev->mode_config.dithering_mode_property) { + struct nouveau_crtc *nv_crtc = NULL; + + if (value == DRM_MODE_DITHERING_ON) + nv_connector->use_dithering = true; + else + nv_connector->use_dithering = false; + + if (connector->encoder && connector->encoder->crtc) + nv_crtc = nouveau_crtc(connector->encoder->crtc); + + if (!nv_crtc || !nv_crtc->set_dither) + return 0; + + return nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, + true); + } + + if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV) + return get_slave_funcs(nv_encoder)-> + set_property(to_drm_encoder(nv_encoder), connector, property, value); + + return -EINVAL; +} + +static struct drm_display_mode * +nouveau_connector_native_mode(struct nouveau_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_display_mode *mode, *largest = NULL; + int high_w = 0, high_h = 0, high_v = 0; + + /* Use preferred mode if there is one.. */ + list_for_each_entry(mode, &connector->base.probed_modes, head) { + if (mode->type & DRM_MODE_TYPE_PREFERRED) { + NV_DEBUG(dev, "native mode from preferred\n"); + return drm_mode_duplicate(dev, mode); + } + } + + /* Otherwise, take the resolution with the largest width, then height, + * then vertical refresh + */ + list_for_each_entry(mode, &connector->base.probed_modes, head) { + if (mode->hdisplay < high_w) + continue; + + if (mode->hdisplay == high_w && mode->vdisplay < high_h) + continue; + + if (mode->hdisplay == high_w && mode->vdisplay == high_h && + mode->vrefresh < high_v) + continue; + + high_w = mode->hdisplay; + high_h = mode->vdisplay; + high_v = mode->vrefresh; + largest = mode; + } + + NV_DEBUG(dev, "native mode from largest: %dx%d@%d\n", + high_w, high_h, high_v); + return largest ? drm_mode_duplicate(dev, largest) : NULL; +} + +struct moderec { + int hdisplay; + int vdisplay; +}; + +static struct moderec scaler_modes[] = { + { 1920, 1200 }, + { 1920, 1080 }, + { 1680, 1050 }, + { 1600, 1200 }, + { 1400, 1050 }, + { 1280, 1024 }, + { 1280, 960 }, + { 1152, 864 }, + { 1024, 768 }, + { 800, 600 }, + { 720, 400 }, + { 640, 480 }, + { 640, 400 }, + { 640, 350 }, + {} +}; + +static int +nouveau_connector_scaler_modes_add(struct drm_connector *connector) +{ + struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct drm_display_mode *native = nv_connector->native_mode, *m; + struct drm_device *dev = connector->dev; + struct moderec *mode = &scaler_modes[0]; + int modes = 0; + + if (!native) + return 0; + + while (mode->hdisplay) { + if (mode->hdisplay <= native->hdisplay && + mode->vdisplay <= native->vdisplay) { + m = drm_cvt_mode(dev, mode->hdisplay, mode->vdisplay, + drm_mode_vrefresh(native), false, + false, false); + if (!m) + continue; + + m->type |= DRM_MODE_TYPE_DRIVER; + + drm_mode_probed_add(connector, m); + modes++; + } + + mode++; + } + + return modes; +} + +static int +nouveau_connector_get_modes(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; + int ret = 0; + + /* If we're not LVDS, destroy the previous native mode, the attached + * monitor could have changed. + */ + if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && + nv_connector->native_mode) { + drm_mode_destroy(dev, nv_connector->native_mode); + nv_connector->native_mode = NULL; + } + + if (nv_connector->edid) + ret = drm_add_edid_modes(connector, nv_connector->edid); + + /* Find the native mode if this is a digital panel, if we didn't + * find any modes through DDC previously add the native mode to + * the list of modes. + */ + if (!nv_connector->native_mode) + nv_connector->native_mode = + nouveau_connector_native_mode(nv_connector); + if (ret == 0 && nv_connector->native_mode) { + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(dev, nv_connector->native_mode); + drm_mode_probed_add(connector, mode); + ret = 1; + } + + if (nv_encoder->dcb->type == OUTPUT_TV) + ret = get_slave_funcs(nv_encoder)-> + get_modes(to_drm_encoder(nv_encoder), connector); + + if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) + ret += nouveau_connector_scaler_modes_add(connector); + + return ret; +} + +static int +nouveau_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct drm_nouveau_private *dev_priv = connector->dev->dev_private; + struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; + unsigned min_clock = 25000, max_clock = min_clock; + unsigned clock = mode->clock; + + switch (nv_encoder->dcb->type) { + case OUTPUT_LVDS: + BUG_ON(!nv_connector->native_mode); + if (mode->hdisplay > nv_connector->native_mode->hdisplay || + mode->vdisplay > nv_connector->native_mode->vdisplay) + return MODE_PANEL; + + min_clock = 0; + max_clock = 400000; + break; + case OUTPUT_TMDS: + if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) || + (dev_priv->card_type < NV_50 && + !nv_encoder->dcb->duallink_possible)) + max_clock = 165000; + else + max_clock = 330000; + break; + case OUTPUT_ANALOG: + max_clock = nv_encoder->dcb->crtconf.maxfreq; + if (!max_clock) + max_clock = 350000; + break; + case OUTPUT_TV: + return get_slave_funcs(nv_encoder)-> + mode_valid(to_drm_encoder(nv_encoder), mode); + case OUTPUT_DP: + if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7) + max_clock = nv_encoder->dp.link_nr * 270000; + else + max_clock = nv_encoder->dp.link_nr * 162000; + + clock *= 3; + break; + } + + if (clock < min_clock) + return MODE_CLOCK_LOW; + + if (clock > max_clock) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static struct drm_encoder * +nouveau_connector_best_encoder(struct drm_connector *connector) +{ + struct nouveau_connector *nv_connector = nouveau_connector(connector); + + if (nv_connector->detected_encoder) + return to_drm_encoder(nv_connector->detected_encoder); + + return NULL; +} + +static const struct drm_connector_helper_funcs +nouveau_connector_helper_funcs = { + .get_modes = nouveau_connector_get_modes, + .mode_valid = nouveau_connector_mode_valid, + .best_encoder = nouveau_connector_best_encoder, +}; + +static const struct drm_connector_funcs +nouveau_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .save = NULL, + .restore = NULL, + .detect = nouveau_connector_detect, + .destroy = nouveau_connector_destroy, + .fill_modes = drm_helper_probe_single_connector_modes, + .set_property = nouveau_connector_set_property, + .force = nouveau_connector_force +}; + +static int +nouveau_connector_create_lvds(struct drm_device *dev, + struct drm_connector *connector) +{ + struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_i2c_chan *i2c = NULL; + struct nouveau_encoder *nv_encoder; + struct drm_display_mode native, *mode, *temp; + bool dummy, if_is_24bit = false; + int ret, flags; + + nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); + if (!nv_encoder) + return -ENODEV; + + ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &if_is_24bit); + if (ret) { + NV_ERROR(dev, "Error parsing LVDS table, disabling LVDS\n"); + return ret; + } + nv_connector->use_dithering = !if_is_24bit; + + /* Firstly try getting EDID over DDC, if allowed and I2C channel + * is available. + */ + if (!dev_priv->VBIOS.pub.fp_no_ddc && nv_encoder->dcb->i2c_index < 0xf) + i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); + + if (i2c) { + nouveau_connector_ddc_prepare(connector, &flags); + nv_connector->edid = drm_get_edid(connector, &i2c->adapter); + nouveau_connector_ddc_finish(connector, flags); + } + + /* If no EDID found above, and the VBIOS indicates a hardcoded + * modeline is avalilable for the panel, set it as the panel's + * native mode and exit. + */ + if (!nv_connector->edid && nouveau_bios_fp_mode(dev, &native) && + (nv_encoder->dcb->lvdsconf.use_straps_for_mode || + dev_priv->VBIOS.pub.fp_no_ddc)) { + nv_connector->native_mode = drm_mode_duplicate(dev, &native); + goto out; + } + + /* Still nothing, some VBIOS images have a hardcoded EDID block + * stored for the panel stored in them. + */ + if (!nv_connector->edid && !nv_connector->native_mode && + !dev_priv->VBIOS.pub.fp_no_ddc) { + nv_connector->edid = + (struct edid *)nouveau_bios_embedded_edid(dev); + } + + if (!nv_connector->edid) + goto out; + + /* We didn't find/use a panel mode from the VBIOS, so parse the EDID + * block and look for the preferred mode there. + */ + ret = drm_add_edid_modes(connector, nv_connector->edid); + if (ret == 0) + goto out; + nv_connector->detected_encoder = nv_encoder; + nv_connector->native_mode = nouveau_connector_native_mode(nv_connector); + list_for_each_entry_safe(mode, temp, &connector->probed_modes, head) + drm_mode_remove(connector, mode); + +out: + if (!nv_connector->native_mode) { + NV_ERROR(dev, "LVDS present in DCB table, but couldn't " + "determine its native mode. Disabling.\n"); + return -ENODEV; + } + + drm_mode_connector_update_edid_property(connector, nv_connector->edid); + return 0; +} + +int +nouveau_connector_create(struct drm_device *dev, int index, int type) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_connector *nv_connector = NULL; + struct drm_connector *connector; + struct drm_encoder *encoder; + int ret; + + NV_DEBUG(dev, "\n"); + + nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL); + if (!nv_connector) + return -ENOMEM; + nv_connector->dcb = nouveau_bios_connector_entry(dev, index); + connector = &nv_connector->base; + + switch (type) { + case DRM_MODE_CONNECTOR_VGA: + NV_INFO(dev, "Detected a VGA connector\n"); + break; + case DRM_MODE_CONNECTOR_DVID: + NV_INFO(dev, "Detected a DVI-D connector\n"); + break; + case DRM_MODE_CONNECTOR_DVII: + NV_INFO(dev, "Detected a DVI-I connector\n"); + break; + case DRM_MODE_CONNECTOR_LVDS: + NV_INFO(dev, "Detected a LVDS connector\n"); + break; + case DRM_MODE_CONNECTOR_TV: + NV_INFO(dev, "Detected a TV connector\n"); + break; + case DRM_MODE_CONNECTOR_DisplayPort: + NV_INFO(dev, "Detected a DisplayPort connector\n"); + break; + default: + NV_ERROR(dev, "Unknown connector, this is not good.\n"); + break; + } + + /* defaults, will get overridden in detect() */ + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + + drm_connector_init(dev, connector, &nouveau_connector_funcs, type); + drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); + + /* Init DVI-I specific properties */ + if (type == DRM_MODE_CONNECTOR_DVII) { + drm_mode_create_dvi_i_properties(dev); + drm_connector_attach_property(connector, dev->mode_config.dvi_i_subconnector_property, 0); + drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0); + } + + if (type != DRM_MODE_CONNECTOR_LVDS) + nv_connector->use_dithering = false; + + if (type == DRM_MODE_CONNECTOR_DVID || + type == DRM_MODE_CONNECTOR_DVII || + type == DRM_MODE_CONNECTOR_LVDS || + type == DRM_MODE_CONNECTOR_DisplayPort) { + nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN; + + drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, + nv_connector->scaling_mode); + drm_connector_attach_property(connector, dev->mode_config.dithering_mode_property, + nv_connector->use_dithering ? DRM_MODE_DITHERING_ON + : DRM_MODE_DITHERING_OFF); + + } else { + nv_connector->scaling_mode = DRM_MODE_SCALE_NONE; + + if (type == DRM_MODE_CONNECTOR_VGA && + dev_priv->card_type >= NV_50) { + drm_connector_attach_property(connector, + dev->mode_config.scaling_mode_property, + nv_connector->scaling_mode); + } + } + + /* attach encoders */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + if (nv_encoder->dcb->connector != index) + continue; + + if (get_slave_funcs(nv_encoder)) + get_slave_funcs(nv_encoder)->create_resources(encoder, connector); + + drm_mode_connector_attach_encoder(connector, encoder); + } + + drm_sysfs_connector_add(connector); + + if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { + ret = nouveau_connector_create_lvds(dev, connector); + if (ret) { + connector->funcs->destroy(connector); + return ret; + } + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h new file mode 100644 index 0000000000000000000000000000000000000000..728b8090e5ff87ed39f3f91337344dbbe727e011 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008 Maarten Maathuis. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +#ifndef __NOUVEAU_CONNECTOR_H__ +#define __NOUVEAU_CONNECTOR_H__ + +#include "drm_edid.h" +#include "nouveau_i2c.h" + +struct nouveau_connector { + struct drm_connector base; + + struct dcb_connector_table_entry *dcb; + + int scaling_mode; + bool use_dithering; + + struct nouveau_encoder *detected_encoder; + struct edid *edid; + struct drm_display_mode *native_mode; +}; + +static inline struct nouveau_connector *nouveau_connector( + struct drm_connector *con) +{ + return container_of(con, struct nouveau_connector, base); +} + +int nouveau_connector_create(struct drm_device *dev, int i2c_index, int type); + +#endif /* __NOUVEAU_CONNECTOR_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h new file mode 100644 index 0000000000000000000000000000000000000000..49fa7b2d257e8e739391720ffaf66e8eea86ee45 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2008 Maarten Maathuis. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +#ifndef __NOUVEAU_CRTC_H__ +#define __NOUVEAU_CRTC_H__ + +struct nouveau_crtc { + struct drm_crtc base; + + int index; + + struct drm_display_mode *mode; + + uint32_t dpms_saved_fp_control; + uint32_t fp_users; + int saturation; + int sharpness; + int last_dpms; + + struct { + int cpp; + bool blanked; + uint32_t offset; + uint32_t tile_flags; + } fb; + + struct { + struct nouveau_bo *nvbo; + bool visible; + uint32_t offset; + void (*set_offset)(struct nouveau_crtc *, uint32_t offset); + void (*set_pos)(struct nouveau_crtc *, int x, int y); + void (*hide)(struct nouveau_crtc *, bool update); + void (*show)(struct nouveau_crtc *, bool update); + } cursor; + + struct { + struct nouveau_bo *nvbo; + uint16_t r[256]; + uint16_t g[256]; + uint16_t b[256]; + int depth; + } lut; + + int (*set_dither)(struct nouveau_crtc *crtc, bool on, bool update); + int (*set_scale)(struct nouveau_crtc *crtc, int mode, bool update); +}; + +static inline struct nouveau_crtc *nouveau_crtc(struct drm_crtc *crtc) +{ + return container_of(crtc, struct nouveau_crtc, base); +} + +static inline struct drm_crtc *to_drm_crtc(struct nouveau_crtc *crtc) +{ + return &crtc->base; +} + +int nv50_crtc_create(struct drm_device *dev, int index); +int nv50_cursor_init(struct nouveau_crtc *); +void nv50_cursor_fini(struct nouveau_crtc *); +int nv50_crtc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file_priv, + uint32_t buffer_handle, uint32_t width, + uint32_t height); +int nv50_crtc_cursor_move(struct drm_crtc *drm_crtc, int x, int y); + +int nv04_cursor_init(struct nouveau_crtc *); + +struct nouveau_connector * +nouveau_crtc_connector_get(struct nouveau_crtc *crtc); + +#endif /* __NOUVEAU_CRTC_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c new file mode 100644 index 0000000000000000000000000000000000000000..d79db3698f16699e5edd3a9432357cb7b1cc10f5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2009 Red Hat + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +/* + * Authors: + * Ben Skeggs + */ + +#include + +#include "drmP.h" +#include "nouveau_drv.h" + +static int +nouveau_debugfs_channel_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct nouveau_channel *chan = node->info_ent->data; + + seq_printf(m, "channel id : %d\n", chan->id); + + seq_printf(m, "cpu fifo state:\n"); + seq_printf(m, " base: 0x%08x\n", chan->pushbuf_base); + seq_printf(m, " max: 0x%08x\n", chan->dma.max << 2); + seq_printf(m, " cur: 0x%08x\n", chan->dma.cur << 2); + seq_printf(m, " put: 0x%08x\n", chan->dma.put << 2); + seq_printf(m, " free: 0x%08x\n", chan->dma.free << 2); + + seq_printf(m, "gpu fifo state:\n"); + seq_printf(m, " get: 0x%08x\n", + nvchan_rd32(chan, chan->user_get)); + seq_printf(m, " put: 0x%08x\n", + nvchan_rd32(chan, chan->user_put)); + + seq_printf(m, "last fence : %d\n", chan->fence.sequence); + seq_printf(m, "last signalled: %d\n", chan->fence.sequence_ack); + return 0; +} + +int +nouveau_debugfs_channel_init(struct nouveau_channel *chan) +{ + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct drm_minor *minor = chan->dev->primary; + int ret; + + if (!dev_priv->debugfs.channel_root) { + dev_priv->debugfs.channel_root = + debugfs_create_dir("channel", minor->debugfs_root); + if (!dev_priv->debugfs.channel_root) + return -ENOENT; + } + + snprintf(chan->debugfs.name, 32, "%d", chan->id); + chan->debugfs.info.name = chan->debugfs.name; + chan->debugfs.info.show = nouveau_debugfs_channel_info; + chan->debugfs.info.driver_features = 0; + chan->debugfs.info.data = chan; + + ret = drm_debugfs_create_files(&chan->debugfs.info, 1, + dev_priv->debugfs.channel_root, + chan->dev->primary); + if (ret == 0) + chan->debugfs.active = true; + return ret; +} + +void +nouveau_debugfs_channel_fini(struct nouveau_channel *chan) +{ + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + + if (!chan->debugfs.active) + return; + + drm_debugfs_remove_files(&chan->debugfs.info, 1, chan->dev->primary); + chan->debugfs.active = false; + + if (chan == dev_priv->channel) { + debugfs_remove(dev_priv->debugfs.channel_root); + dev_priv->debugfs.channel_root = NULL; + } +} + +static int +nouveau_debugfs_chipset_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_minor *minor = node->minor; + struct drm_device *dev = minor->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t ppci_0; + + ppci_0 = nv_rd32(dev, dev_priv->chipset >= 0x40 ? 0x88000 : 0x1800); + + seq_printf(m, "PMC_BOOT_0: 0x%08x\n", nv_rd32(dev, NV03_PMC_BOOT_0)); + seq_printf(m, "PCI ID : 0x%04x:0x%04x\n", + ppci_0 & 0xffff, ppci_0 >> 16); + return 0; +} + +static int +nouveau_debugfs_memory_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_minor *minor = node->minor; + struct drm_device *dev = minor->dev; + + seq_printf(m, "VRAM total: %dKiB\n", + (int)(nouveau_mem_fb_amount(dev) >> 10)); + return 0; +} + +static struct drm_info_list nouveau_debugfs_list[] = { + { "chipset", nouveau_debugfs_chipset_info, 0, NULL }, + { "memory", nouveau_debugfs_memory_info, 0, NULL }, +}; +#define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list) + +int +nouveau_debugfs_init(struct drm_minor *minor) +{ + drm_debugfs_create_files(nouveau_debugfs_list, NOUVEAU_DEBUGFS_ENTRIES, + minor->debugfs_root, minor); + return 0; +} + +void +nouveau_debugfs_takedown(struct drm_minor *minor) +{ + drm_debugfs_remove_files(nouveau_debugfs_list, NOUVEAU_DEBUGFS_ENTRIES, + minor); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c new file mode 100644 index 0000000000000000000000000000000000000000..dfc94391d71edafddb16df529f3efc054f5d011c --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2008 Maarten Maathuis. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm_crtc_helper.h" +#include "nouveau_drv.h" +#include "nouveau_fb.h" +#include "nouveau_fbcon.h" + +static void +nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) +{ + struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); + struct drm_device *dev = drm_fb->dev; + + if (drm_fb->fbdev) + nouveau_fbcon_remove(dev, drm_fb); + + if (fb->nvbo) { + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(fb->nvbo->gem); + mutex_unlock(&dev->struct_mutex); + } + + drm_framebuffer_cleanup(drm_fb); + kfree(fb); +} + +static int +nouveau_user_framebuffer_create_handle(struct drm_framebuffer *drm_fb, + struct drm_file *file_priv, + unsigned int *handle) +{ + struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); + + return drm_gem_handle_create(file_priv, fb->nvbo->gem, handle); +} + +static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = { + .destroy = nouveau_user_framebuffer_destroy, + .create_handle = nouveau_user_framebuffer_create_handle, +}; + +struct drm_framebuffer * +nouveau_framebuffer_create(struct drm_device *dev, struct nouveau_bo *nvbo, + struct drm_mode_fb_cmd *mode_cmd) +{ + struct nouveau_framebuffer *fb; + int ret; + + fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL); + if (!fb) + return NULL; + + ret = drm_framebuffer_init(dev, &fb->base, &nouveau_framebuffer_funcs); + if (ret) { + kfree(fb); + return NULL; + } + + drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); + + fb->nvbo = nvbo; + return &fb->base; +} + +static struct drm_framebuffer * +nouveau_user_framebuffer_create(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_mode_fb_cmd *mode_cmd) +{ + struct drm_framebuffer *fb; + struct drm_gem_object *gem; + + gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); + if (!gem) + return NULL; + + fb = nouveau_framebuffer_create(dev, nouveau_gem_object(gem), mode_cmd); + if (!fb) { + drm_gem_object_unreference(gem); + return NULL; + } + + return fb; +} + +const struct drm_mode_config_funcs nouveau_mode_config_funcs = { + .fb_create = nouveau_user_framebuffer_create, + .fb_changed = nouveau_fbcon_probe, +}; + diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c new file mode 100644 index 0000000000000000000000000000000000000000..703553687b205a543b7d0963744a87ba0a58e3d0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_dma.h" + +int +nouveau_dma_init(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *m2mf = NULL; + int ret, i; + + /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ + ret = nouveau_gpuobj_gr_new(chan, dev_priv->card_type < NV_50 ? + 0x0039 : 0x5039, &m2mf); + if (ret) + return ret; + + ret = nouveau_gpuobj_ref_add(dev, chan, NvM2MF, m2mf, NULL); + if (ret) + return ret; + + /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */ + ret = nouveau_notifier_alloc(chan, NvNotify0, 32, &chan->m2mf_ntfy); + if (ret) + return ret; + + /* Map push buffer */ + ret = nouveau_bo_map(chan->pushbuf_bo); + if (ret) + return ret; + + /* Map M2MF notifier object - fbcon. */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + ret = nouveau_bo_map(chan->notifier_bo); + if (ret) + return ret; + } + + /* Initialise DMA vars */ + chan->dma.max = (chan->pushbuf_bo->bo.mem.size >> 2) - 2; + chan->dma.put = 0; + chan->dma.cur = chan->dma.put; + chan->dma.free = chan->dma.max - chan->dma.cur; + + /* Insert NOPS for NOUVEAU_DMA_SKIPS */ + ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); + if (ret) + return ret; + + for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) + OUT_RING(chan, 0); + + /* Initialise NV_MEMORY_TO_MEMORY_FORMAT */ + ret = RING_SPACE(chan, 4); + if (ret) + return ret; + BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1); + OUT_RING(chan, NvM2MF); + BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); + OUT_RING(chan, NvNotify0); + + /* Sit back and pray the channel works.. */ + FIRE_RING(chan); + + return 0; +} + +void +OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords) +{ + bool is_iomem; + u32 *mem = ttm_kmap_obj_virtual(&chan->pushbuf_bo->kmap, &is_iomem); + mem = &mem[chan->dma.cur]; + if (is_iomem) + memcpy_toio((void __force __iomem *)mem, data, nr_dwords * 4); + else + memcpy(mem, data, nr_dwords * 4); + chan->dma.cur += nr_dwords; +} + +static inline bool +READ_GET(struct nouveau_channel *chan, uint32_t *get) +{ + uint32_t val; + + val = nvchan_rd32(chan, chan->user_get); + if (val < chan->pushbuf_base || + val >= chan->pushbuf_base + chan->pushbuf_bo->bo.mem.size) { + /* meaningless to dma_wait() except to know whether the + * GPU has stalled or not + */ + *get = val; + return false; + } + + *get = (val - chan->pushbuf_base) >> 2; + return true; +} + +int +nouveau_dma_wait(struct nouveau_channel *chan, int size) +{ + uint32_t get, prev_get = 0, cnt = 0; + bool get_valid; + + while (chan->dma.free < size) { + /* reset counter as long as GET is still advancing, this is + * to avoid misdetecting a GPU lockup if the GPU happens to + * just be processing an operation that takes a long time + */ + get_valid = READ_GET(chan, &get); + if (get != prev_get) { + prev_get = get; + cnt = 0; + } + + if ((++cnt & 0xff) == 0) { + DRM_UDELAY(1); + if (cnt > 100000) + return -EBUSY; + } + + /* loop until we have a usable GET pointer. the value + * we read from the GPU may be outside the main ring if + * PFIFO is processing a buffer called from the main ring, + * discard these values until something sensible is seen. + * + * the other case we discard GET is while the GPU is fetching + * from the SKIPS area, so the code below doesn't have to deal + * with some fun corner cases. + */ + if (!get_valid || get < NOUVEAU_DMA_SKIPS) + continue; + + if (get <= chan->dma.cur) { + /* engine is fetching behind us, or is completely + * idle (GET == PUT) so we have free space up until + * the end of the push buffer + * + * we can only hit that path once per call due to + * looping back to the beginning of the push buffer, + * we'll hit the fetching-ahead-of-us path from that + * point on. + * + * the *one* exception to that rule is if we read + * GET==PUT, in which case the below conditional will + * always succeed and break us out of the wait loop. + */ + chan->dma.free = chan->dma.max - chan->dma.cur; + if (chan->dma.free >= size) + break; + + /* not enough space left at the end of the push buffer, + * instruct the GPU to jump back to the start right + * after processing the currently pending commands. + */ + OUT_RING(chan, chan->pushbuf_base | 0x20000000); + WRITE_PUT(NOUVEAU_DMA_SKIPS); + + /* we're now submitting commands at the start of + * the push buffer. + */ + chan->dma.cur = + chan->dma.put = NOUVEAU_DMA_SKIPS; + } + + /* engine fetching ahead of us, we have space up until the + * current GET pointer. the "- 1" is to ensure there's + * space left to emit a jump back to the beginning of the + * push buffer if we require it. we can never get GET == PUT + * here, so this is safe. + */ + chan->dma.free = get - chan->dma.cur - 1; + } + + return 0; +} + diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h new file mode 100644 index 0000000000000000000000000000000000000000..04e85d8f757e80ccb5d62769b6596762d209e174 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_dma.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +#ifndef __NOUVEAU_DMA_H__ +#define __NOUVEAU_DMA_H__ + +#ifndef NOUVEAU_DMA_DEBUG +#define NOUVEAU_DMA_DEBUG 0 +#endif + +/* + * There's a hw race condition where you can't jump to your PUT offset, + * to avoid this we jump to offset + SKIPS and fill the difference with + * NOPs. + * + * xf86-video-nv configures the DMA fetch size to 32 bytes, and uses + * a SKIPS value of 8. Lets assume that the race condition is to do + * with writing into the fetch area, we configure a fetch size of 128 + * bytes so we need a larger SKIPS value. + */ +#define NOUVEAU_DMA_SKIPS (128 / 4) + +/* Hardcoded object assignments to subchannels (subchannel id). */ +enum { + NvSubM2MF = 0, + NvSub2D = 1, + NvSubCtxSurf2D = 1, + NvSubGdiRect = 2, + NvSubImageBlit = 3 +}; + +/* Object handles. */ +enum { + NvM2MF = 0x80000001, + NvDmaFB = 0x80000002, + NvDmaTT = 0x80000003, + NvDmaVRAM = 0x80000004, + NvDmaGART = 0x80000005, + NvNotify0 = 0x80000006, + Nv2D = 0x80000007, + NvCtxSurf2D = 0x80000008, + NvRop = 0x80000009, + NvImagePatt = 0x8000000a, + NvClipRect = 0x8000000b, + NvGdiRect = 0x8000000c, + NvImageBlit = 0x8000000d, + + /* G80+ display objects */ + NvEvoVRAM = 0x01000000, + NvEvoFB16 = 0x01000001, + NvEvoFB32 = 0x01000002 +}; + +#define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039 +#define NV_MEMORY_TO_MEMORY_FORMAT_NAME 0x00000000 +#define NV_MEMORY_TO_MEMORY_FORMAT_SET_REF 0x00000050 +#define NV_MEMORY_TO_MEMORY_FORMAT_NOP 0x00000100 +#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104 +#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE 0x00000000 +#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE_LE_AWAKEN 0x00000001 +#define NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY 0x00000180 +#define NV_MEMORY_TO_MEMORY_FORMAT_DMA_SOURCE 0x00000184 +#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c + +#define NV50_MEMORY_TO_MEMORY_FORMAT 0x00005039 +#define NV50_MEMORY_TO_MEMORY_FORMAT_UNK200 0x00000200 +#define NV50_MEMORY_TO_MEMORY_FORMAT_UNK21C 0x0000021c +#define NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH 0x00000238 +#define NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_OUT_HIGH 0x0000023c + +static __must_check inline int +RING_SPACE(struct nouveau_channel *chan, int size) +{ + if (chan->dma.free < size) { + int ret; + + ret = nouveau_dma_wait(chan, size); + if (ret) + return ret; + } + + chan->dma.free -= size; + return 0; +} + +static inline void +OUT_RING(struct nouveau_channel *chan, int data) +{ + if (NOUVEAU_DMA_DEBUG) { + NV_INFO(chan->dev, "Ch%d/0x%08x: 0x%08x\n", + chan->id, chan->dma.cur << 2, data); + } + + nouveau_bo_wr32(chan->pushbuf_bo, chan->dma.cur++, data); +} + +extern void +OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords); + +static inline void +BEGIN_RING(struct nouveau_channel *chan, int subc, int mthd, int size) +{ + OUT_RING(chan, (subc << 13) | (size << 18) | mthd); +} + +#define WRITE_PUT(val) do { \ + DRM_MEMORYBARRIER(); \ + nouveau_bo_rd32(chan->pushbuf_bo, 0); \ + nvchan_wr32(chan, chan->user_put, ((val) << 2) + chan->pushbuf_base); \ +} while (0) + +static inline void +FIRE_RING(struct nouveau_channel *chan) +{ + if (NOUVEAU_DMA_DEBUG) { + NV_INFO(chan->dev, "Ch%d/0x%08x: PUSH!\n", + chan->id, chan->dma.cur << 2); + } + + if (chan->dma.cur == chan->dma.put) + return; + chan->accel_done = true; + + WRITE_PUT(chan->dma.cur); + chan->dma.put = chan->dma.cur; +} + +static inline void +WIND_RING(struct nouveau_channel *chan) +{ + chan->dma.cur = chan->dma.put; +} + +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c new file mode 100644 index 0000000000000000000000000000000000000000..de61f4640e126218f406bfec08083c7326ee9ab6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -0,0 +1,569 @@ +/* + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Authors: Ben Skeggs + */ + +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_i2c.h" +#include "nouveau_encoder.h" + +static int +auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size) +{ + struct drm_device *dev = encoder->dev; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_i2c_chan *auxch; + int ret; + + auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); + if (!auxch) + return -ENODEV; + + ret = nouveau_dp_auxch(auxch, 9, address, buf, size); + if (ret) + return ret; + + return 0; +} + +static int +auxch_wr(struct drm_encoder *encoder, int address, uint8_t *buf, int size) +{ + struct drm_device *dev = encoder->dev; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_i2c_chan *auxch; + int ret; + + auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); + if (!auxch) + return -ENODEV; + + ret = nouveau_dp_auxch(auxch, 8, address, buf, size); + return ret; +} + +static int +nouveau_dp_lane_count_set(struct drm_encoder *encoder, uint8_t cmd) +{ + struct drm_device *dev = encoder->dev; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + uint32_t tmp; + int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); + + tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); + tmp &= ~(NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED | + NV50_SOR_DP_CTRL_LANE_MASK); + tmp |= ((1 << (cmd & DP_LANE_COUNT_MASK)) - 1) << 16; + if (cmd & DP_LANE_COUNT_ENHANCED_FRAME_EN) + tmp |= NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED; + nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); + + return auxch_wr(encoder, DP_LANE_COUNT_SET, &cmd, 1); +} + +static int +nouveau_dp_link_bw_set(struct drm_encoder *encoder, uint8_t cmd) +{ + struct drm_device *dev = encoder->dev; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + uint32_t tmp; + int reg = 0x614300 + (nv_encoder->or * 0x800); + + tmp = nv_rd32(dev, reg); + tmp &= 0xfff3ffff; + if (cmd == DP_LINK_BW_2_7) + tmp |= 0x00040000; + nv_wr32(dev, reg, tmp); + + return auxch_wr(encoder, DP_LINK_BW_SET, &cmd, 1); +} + +static int +nouveau_dp_link_train_set(struct drm_encoder *encoder, int pattern) +{ + struct drm_device *dev = encoder->dev; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + uint32_t tmp; + uint8_t cmd; + int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); + int ret; + + tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); + tmp &= ~NV50_SOR_DP_CTRL_TRAINING_PATTERN; + tmp |= (pattern << 24); + nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); + + ret = auxch_rd(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1); + if (ret) + return ret; + cmd &= ~DP_TRAINING_PATTERN_MASK; + cmd |= (pattern & DP_TRAINING_PATTERN_MASK); + return auxch_wr(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1); +} + +static int +nouveau_dp_max_voltage_swing(struct drm_encoder *encoder) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct bit_displayport_encoder_table_entry *dpse; + struct bit_displayport_encoder_table *dpe; + int i, dpe_headerlen, max_vs = 0; + + dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); + if (!dpe) + return false; + dpse = (void *)((char *)dpe + dpe_headerlen); + + for (i = 0; i < dpe_headerlen; i++, dpse++) { + if (dpse->vs_level > max_vs) + max_vs = dpse->vs_level; + } + + return max_vs; +} + +static int +nouveau_dp_max_pre_emphasis(struct drm_encoder *encoder, int vs) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct bit_displayport_encoder_table_entry *dpse; + struct bit_displayport_encoder_table *dpe; + int i, dpe_headerlen, max_pre = 0; + + dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); + if (!dpe) + return false; + dpse = (void *)((char *)dpe + dpe_headerlen); + + for (i = 0; i < dpe_headerlen; i++, dpse++) { + if (dpse->vs_level != vs) + continue; + + if (dpse->pre_level > max_pre) + max_pre = dpse->pre_level; + } + + return max_pre; +} + +static bool +nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct bit_displayport_encoder_table_entry *dpse; + struct bit_displayport_encoder_table *dpe; + int ret, i, dpe_headerlen, vs = 0, pre = 0; + uint8_t request[2]; + + dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); + if (!dpe) + return false; + dpse = (void *)((char *)dpe + dpe_headerlen); + + ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); + if (ret) + return false; + + NV_DEBUG(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]); + + /* Keep all lanes at the same level.. */ + for (i = 0; i < nv_encoder->dp.link_nr; i++) { + int lane_req = (request[i >> 1] >> ((i & 1) << 2)) & 0xf; + int lane_vs = lane_req & 3; + int lane_pre = (lane_req >> 2) & 3; + + if (lane_vs > vs) + vs = lane_vs; + if (lane_pre > pre) + pre = lane_pre; + } + + if (vs >= nouveau_dp_max_voltage_swing(encoder)) { + vs = nouveau_dp_max_voltage_swing(encoder); + vs |= 4; + } + + if (pre >= nouveau_dp_max_pre_emphasis(encoder, vs & 3)) { + pre = nouveau_dp_max_pre_emphasis(encoder, vs & 3); + pre |= 4; + } + + /* Update the configuration for all lanes.. */ + for (i = 0; i < nv_encoder->dp.link_nr; i++) + config[i] = (pre << 3) | vs; + + return true; +} + +static bool +nouveau_dp_link_train_commit(struct drm_encoder *encoder, uint8_t *config) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct bit_displayport_encoder_table_entry *dpse; + struct bit_displayport_encoder_table *dpe; + int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); + int dpe_headerlen, ret, i; + + NV_DEBUG(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n", + config[0], config[1], config[2], config[3]); + + dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); + if (!dpe) + return false; + dpse = (void *)((char *)dpe + dpe_headerlen); + + for (i = 0; i < dpe->record_nr; i++, dpse++) { + if (dpse->vs_level == (config[0] & 3) && + dpse->pre_level == ((config[0] >> 3) & 3)) + break; + } + BUG_ON(i == dpe->record_nr); + + for (i = 0; i < nv_encoder->dp.link_nr; i++) { + const int shift[4] = { 16, 8, 0, 24 }; + uint32_t mask = 0xff << shift[i]; + uint32_t reg0, reg1, reg2; + + reg0 = nv_rd32(dev, NV50_SOR_DP_UNK118(or, link)) & ~mask; + reg0 |= (dpse->reg0 << shift[i]); + reg1 = nv_rd32(dev, NV50_SOR_DP_UNK120(or, link)) & ~mask; + reg1 |= (dpse->reg1 << shift[i]); + reg2 = nv_rd32(dev, NV50_SOR_DP_UNK130(or, link)) & 0xffff00ff; + reg2 |= (dpse->reg2 << 8); + nv_wr32(dev, NV50_SOR_DP_UNK118(or, link), reg0); + nv_wr32(dev, NV50_SOR_DP_UNK120(or, link), reg1); + nv_wr32(dev, NV50_SOR_DP_UNK130(or, link), reg2); + } + + ret = auxch_wr(encoder, DP_TRAINING_LANE0_SET, config, 4); + if (ret) + return false; + + return true; +} + +bool +nouveau_dp_link_train(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + uint8_t config[4]; + uint8_t status[3]; + bool cr_done, cr_max_vs, eq_done; + int ret = 0, i, tries, voltage; + + NV_DEBUG(dev, "link training!!\n"); +train: + cr_done = eq_done = false; + + /* set link configuration */ + NV_DEBUG(dev, "\tbegin train: bw %d, lanes %d\n", + nv_encoder->dp.link_bw, nv_encoder->dp.link_nr); + + ret = nouveau_dp_link_bw_set(encoder, nv_encoder->dp.link_bw); + if (ret) + return false; + + config[0] = nv_encoder->dp.link_nr; + if (nv_encoder->dp.dpcd_version >= 0x11) + config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + + ret = nouveau_dp_lane_count_set(encoder, config[0]); + if (ret) + return false; + + /* clock recovery */ + NV_DEBUG(dev, "\tbegin cr\n"); + ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_1); + if (ret) + goto stop; + + tries = 0; + voltage = -1; + memset(config, 0x00, sizeof(config)); + for (;;) { + if (!nouveau_dp_link_train_commit(encoder, config)) + break; + + udelay(100); + + ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 2); + if (ret) + break; + NV_DEBUG(dev, "\t\tstatus: 0x%02x 0x%02x\n", + status[0], status[1]); + + cr_done = true; + cr_max_vs = false; + for (i = 0; i < nv_encoder->dp.link_nr; i++) { + int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; + + if (!(lane & DP_LANE_CR_DONE)) { + cr_done = false; + if (config[i] & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED) + cr_max_vs = true; + break; + } + } + + if ((config[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { + voltage = config[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + tries = 0; + } + + if (cr_done || cr_max_vs || (++tries == 5)) + break; + + if (!nouveau_dp_link_train_adjust(encoder, config)) + break; + } + + if (!cr_done) + goto stop; + + /* channel equalisation */ + NV_DEBUG(dev, "\tbegin eq\n"); + ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_2); + if (ret) + goto stop; + + for (tries = 0; tries <= 5; tries++) { + udelay(400); + + ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 3); + if (ret) + break; + NV_DEBUG(dev, "\t\tstatus: 0x%02x 0x%02x\n", + status[0], status[1]); + + eq_done = true; + if (!(status[2] & DP_INTERLANE_ALIGN_DONE)) + eq_done = false; + + for (i = 0; eq_done && i < nv_encoder->dp.link_nr; i++) { + int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; + + if (!(lane & DP_LANE_CR_DONE)) { + cr_done = false; + break; + } + + if (!(lane & DP_LANE_CHANNEL_EQ_DONE) || + !(lane & DP_LANE_SYMBOL_LOCKED)) { + eq_done = false; + break; + } + } + + if (eq_done || !cr_done) + break; + + if (!nouveau_dp_link_train_adjust(encoder, config) || + !nouveau_dp_link_train_commit(encoder, config)) + break; + } + +stop: + /* end link training */ + ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_DISABLE); + if (ret) + return false; + + /* retry at a lower setting, if possible */ + if (!ret && !(eq_done && cr_done)) { + NV_DEBUG(dev, "\twe failed\n"); + if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62) { + NV_DEBUG(dev, "retry link training at low rate\n"); + nv_encoder->dp.link_bw = DP_LINK_BW_1_62; + goto train; + } + } + + return eq_done; +} + +bool +nouveau_dp_detect(struct drm_encoder *encoder) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + uint8_t dpcd[4]; + int ret; + + ret = auxch_rd(encoder, 0x0000, dpcd, 4); + if (ret) + return false; + + NV_DEBUG(dev, "encoder: link_bw %d, link_nr %d\n" + "display: link_bw %d, link_nr %d version 0x%02x\n", + nv_encoder->dcb->dpconf.link_bw, + nv_encoder->dcb->dpconf.link_nr, + dpcd[1], dpcd[2] & 0x0f, dpcd[0]); + + nv_encoder->dp.dpcd_version = dpcd[0]; + + nv_encoder->dp.link_bw = dpcd[1]; + if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62 && + !nv_encoder->dcb->dpconf.link_bw) + nv_encoder->dp.link_bw = DP_LINK_BW_1_62; + + nv_encoder->dp.link_nr = dpcd[2] & 0xf; + if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr) + nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; + + return true; +} + +int +nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, + uint8_t *data, int data_nr) +{ + struct drm_device *dev = auxch->dev; + uint32_t tmp, ctrl, stat = 0, data32[4] = {}; + int ret = 0, i, index = auxch->rd; + + NV_DEBUG(dev, "ch %d cmd %d addr 0x%x len %d\n", index, cmd, addr, data_nr); + + tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); + nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp | 0x00100000); + tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); + if (!(tmp & 0x01000000)) { + NV_ERROR(dev, "expected bit 24 == 1, got 0x%08x\n", tmp); + ret = -EIO; + goto out; + } + + for (i = 0; i < 3; i++) { + tmp = nv_rd32(dev, NV50_AUXCH_STAT(auxch->rd)); + if (tmp & NV50_AUXCH_STAT_STATE_READY) + break; + udelay(100); + } + + if (i == 3) { + ret = -EBUSY; + goto out; + } + + if (!(cmd & 1)) { + memcpy(data32, data, data_nr); + for (i = 0; i < 4; i++) { + NV_DEBUG(dev, "wr %d: 0x%08x\n", i, data32[i]); + nv_wr32(dev, NV50_AUXCH_DATA_OUT(index, i), data32[i]); + } + } + + nv_wr32(dev, NV50_AUXCH_ADDR(index), addr); + ctrl = nv_rd32(dev, NV50_AUXCH_CTRL(index)); + ctrl &= ~(NV50_AUXCH_CTRL_CMD | NV50_AUXCH_CTRL_LEN); + ctrl |= (cmd << NV50_AUXCH_CTRL_CMD_SHIFT); + ctrl |= ((data_nr - 1) << NV50_AUXCH_CTRL_LEN_SHIFT); + + for (;;) { + nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000); + nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl); + nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000); + if (!nv_wait(NV50_AUXCH_CTRL(index), 0x00010000, 0x00000000)) { + NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n", + nv_rd32(dev, NV50_AUXCH_CTRL(index))); + return -EBUSY; + } + + udelay(400); + + stat = nv_rd32(dev, NV50_AUXCH_STAT(index)); + if ((stat & NV50_AUXCH_STAT_REPLY_AUX) != + NV50_AUXCH_STAT_REPLY_AUX_DEFER) + break; + } + + if (cmd & 1) { + for (i = 0; i < 4; i++) { + data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i)); + NV_DEBUG(dev, "rd %d: 0x%08x\n", i, data32[i]); + } + memcpy(data, data32, data_nr); + } + +out: + tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); + nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp & ~0x00100000); + tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); + if (tmp & 0x01000000) { + NV_ERROR(dev, "expected bit 24 == 0, got 0x%08x\n", tmp); + ret = -EIO; + } + + udelay(400); + + return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY); +} + +int +nouveau_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, + uint8_t write_byte, uint8_t *read_byte) +{ + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; + struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adapter; + struct drm_device *dev = auxch->dev; + int ret = 0, cmd, addr = algo_data->address; + uint8_t *buf; + + if (mode == MODE_I2C_READ) { + cmd = AUX_I2C_READ; + buf = read_byte; + } else { + cmd = (mode & MODE_I2C_READ) ? AUX_I2C_READ : AUX_I2C_WRITE; + buf = &write_byte; + } + + if (!(mode & MODE_I2C_STOP)) + cmd |= AUX_I2C_MOT; + + if (mode & MODE_I2C_START) + return 1; + + for (;;) { + ret = nouveau_dp_auxch(auxch, cmd, addr, buf, 1); + if (ret < 0) + return ret; + + switch (ret & NV50_AUXCH_STAT_REPLY_I2C) { + case NV50_AUXCH_STAT_REPLY_I2C_ACK: + return 1; + case NV50_AUXCH_STAT_REPLY_I2C_NACK: + return -EREMOTEIO; + case NV50_AUXCH_STAT_REPLY_I2C_DEFER: + udelay(100); + break; + default: + NV_ERROR(dev, "invalid auxch status: 0x%08x\n", ret); + return -EREMOTEIO; + } + } +} + diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c new file mode 100644 index 0000000000000000000000000000000000000000..35249c35118fc2ca4f9d6b6ae81d2ae64dbd1a57 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -0,0 +1,405 @@ +/* + * Copyright 2005 Stephane Marchesin. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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 + +#include "drmP.h" +#include "drm.h" +#include "drm_crtc_helper.h" +#include "nouveau_drv.h" +#include "nouveau_hw.h" +#include "nouveau_fb.h" +#include "nouveau_fbcon.h" +#include "nv50_display.h" + +#include "drm_pciids.h" + +MODULE_PARM_DESC(noagp, "Disable AGP"); +int nouveau_noagp; +module_param_named(noagp, nouveau_noagp, int, 0400); + +MODULE_PARM_DESC(modeset, "Enable kernel modesetting"); +static int nouveau_modeset = -1; /* kms */ +module_param_named(modeset, nouveau_modeset, int, 0400); + +MODULE_PARM_DESC(vbios, "Override default VBIOS location"); +char *nouveau_vbios; +module_param_named(vbios, nouveau_vbios, charp, 0400); + +MODULE_PARM_DESC(vram_pushbuf, "Force DMA push buffers to be in VRAM"); +int nouveau_vram_pushbuf; +module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); + +MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM"); +int nouveau_vram_notify; +module_param_named(vram_notify, nouveau_vram_notify, int, 0400); + +MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)"); +int nouveau_duallink = 1; +module_param_named(duallink, nouveau_duallink, int, 0400); + +MODULE_PARM_DESC(uscript_lvds, "LVDS output script table ID (>=GeForce 8)"); +int nouveau_uscript_lvds = -1; +module_param_named(uscript_lvds, nouveau_uscript_lvds, int, 0400); + +MODULE_PARM_DESC(uscript_tmds, "TMDS output script table ID (>=GeForce 8)"); +int nouveau_uscript_tmds = -1; +module_param_named(uscript_tmds, nouveau_uscript_tmds, int, 0400); + +MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" + "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n" + "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n" + "\t\tDefault: PAL\n" + "\t\t*NOTE* Ignored for cards with external TV encoders."); +char *nouveau_tv_norm; +module_param_named(tv_norm, nouveau_tv_norm, charp, 0400); + +MODULE_PARM_DESC(reg_debug, "Register access debug bitmask:\n" + "\t\t0x1 mc, 0x2 video, 0x4 fb, 0x8 extdev,\n" + "\t\t0x10 crtc, 0x20 ramdac, 0x40 vgacrtc, 0x80 rmvio,\n" + "\t\t0x100 vgaattr, 0x200 EVO (G80+). "); +int nouveau_reg_debug; +module_param_named(reg_debug, nouveau_reg_debug, int, 0600); + +int nouveau_fbpercrtc; +#if 0 +module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); +#endif + +static struct pci_device_id pciidlist[] = { + { + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), + .class = PCI_BASE_CLASS_DISPLAY << 16, + .class_mask = 0xff << 16, + }, + { + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA_SGS, PCI_ANY_ID), + .class = PCI_BASE_CLASS_DISPLAY << 16, + .class_mask = 0xff << 16, + }, + {} +}; + +MODULE_DEVICE_TABLE(pci, pciidlist); + +static struct drm_driver driver; + +static int __devinit +nouveau_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + return drm_get_dev(pdev, ent, &driver); +} + +static void +nouveau_pci_remove(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + + drm_put_dev(dev); +} + +static int +nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + struct nouveau_channel *chan; + struct drm_crtc *crtc; + uint32_t fbdev_flags; + int ret, i; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -ENODEV; + + if (pm_state.event == PM_EVENT_PRETHAW) + return 0; + + fbdev_flags = dev_priv->fbdev_info->flags; + dev_priv->fbdev_info->flags |= FBINFO_HWACCEL_DISABLED; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_framebuffer *nouveau_fb; + + nouveau_fb = nouveau_framebuffer(crtc->fb); + if (!nouveau_fb || !nouveau_fb->nvbo) + continue; + + nouveau_bo_unpin(nouveau_fb->nvbo); + } + + NV_INFO(dev, "Evicting buffers...\n"); + ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); + + NV_INFO(dev, "Idling channels...\n"); + for (i = 0; i < pfifo->channels; i++) { + struct nouveau_fence *fence = NULL; + + chan = dev_priv->fifos[i]; + if (!chan || (dev_priv->card_type >= NV_50 && + chan == dev_priv->fifos[0])) + continue; + + ret = nouveau_fence_new(chan, &fence, true); + if (ret == 0) { + ret = nouveau_fence_wait(fence, NULL, false, false); + nouveau_fence_unref((void *)&fence); + } + + if (ret) { + NV_ERROR(dev, "Failed to idle channel %d for suspend\n", + chan->id); + } + } + + pgraph->fifo_access(dev, false); + nouveau_wait_for_idle(dev); + pfifo->reassign(dev, false); + pfifo->disable(dev); + pfifo->unload_context(dev); + pgraph->unload_context(dev); + + NV_INFO(dev, "Suspending GPU objects...\n"); + ret = nouveau_gpuobj_suspend(dev); + if (ret) { + NV_ERROR(dev, "... failed: %d\n", ret); + goto out_abort; + } + + ret = pinstmem->suspend(dev); + if (ret) { + NV_ERROR(dev, "... failed: %d\n", ret); + nouveau_gpuobj_suspend_cleanup(dev); + goto out_abort; + } + + NV_INFO(dev, "And we're gone!\n"); + pci_save_state(pdev); + if (pm_state.event == PM_EVENT_SUSPEND) { + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + } + + acquire_console_sem(); + fb_set_suspend(dev_priv->fbdev_info, 1); + release_console_sem(); + dev_priv->fbdev_info->flags = fbdev_flags; + return 0; + +out_abort: + NV_INFO(dev, "Re-enabling acceleration..\n"); + pfifo->enable(dev); + pfifo->reassign(dev, true); + pgraph->fifo_access(dev, true); + return ret; +} + +static int +nouveau_pci_resume(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->engine; + struct drm_crtc *crtc; + uint32_t fbdev_flags; + int ret, i; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -ENODEV; + + fbdev_flags = dev_priv->fbdev_info->flags; + dev_priv->fbdev_info->flags |= FBINFO_HWACCEL_DISABLED; + + NV_INFO(dev, "We're back, enabling device...\n"); + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + if (pci_enable_device(pdev)) + return -1; + pci_set_master(dev->pdev); + + NV_INFO(dev, "POSTing device...\n"); + ret = nouveau_run_vbios_init(dev); + if (ret) + return ret; + + if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { + ret = nouveau_mem_init_agp(dev); + if (ret) { + NV_ERROR(dev, "error reinitialising AGP: %d\n", ret); + return ret; + } + } + + NV_INFO(dev, "Reinitialising engines...\n"); + engine->instmem.resume(dev); + engine->mc.init(dev); + engine->timer.init(dev); + engine->fb.init(dev); + engine->graph.init(dev); + engine->fifo.init(dev); + + NV_INFO(dev, "Restoring GPU objects...\n"); + nouveau_gpuobj_resume(dev); + + nouveau_irq_postinstall(dev); + + /* Re-write SKIPS, they'll have been lost over the suspend */ + if (nouveau_vram_pushbuf) { + struct nouveau_channel *chan; + int j; + + for (i = 0; i < dev_priv->engine.fifo.channels; i++) { + chan = dev_priv->fifos[i]; + if (!chan) + continue; + + for (j = 0; j < NOUVEAU_DMA_SKIPS; j++) + nouveau_bo_wr32(chan->pushbuf_bo, i, 0); + } + } + + NV_INFO(dev, "Restoring mode...\n"); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_framebuffer *nouveau_fb; + + nouveau_fb = nouveau_framebuffer(crtc->fb); + if (!nouveau_fb || !nouveau_fb->nvbo) + continue; + + nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM); + } + + if (dev_priv->card_type < NV_50) { + nv04_display_restore(dev); + NVLockVgaCrtcs(dev, false); + } else + nv50_display_init(dev); + + /* Force CLUT to get re-loaded during modeset */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + + nv_crtc->lut.depth = 0; + } + + acquire_console_sem(); + fb_set_suspend(dev_priv->fbdev_info, 0); + release_console_sem(); + + nouveau_fbcon_zfill(dev); + + drm_helper_resume_force_mode(dev); + dev_priv->fbdev_info->flags = fbdev_flags; + return 0; +} + +static struct drm_driver driver = { + .driver_features = + DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | + DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM, + .load = nouveau_load, + .firstopen = nouveau_firstopen, + .lastclose = nouveau_lastclose, + .unload = nouveau_unload, + .preclose = nouveau_preclose, +#if defined(CONFIG_DRM_NOUVEAU_DEBUG) + .debugfs_init = nouveau_debugfs_init, + .debugfs_cleanup = nouveau_debugfs_takedown, +#endif + .irq_preinstall = nouveau_irq_preinstall, + .irq_postinstall = nouveau_irq_postinstall, + .irq_uninstall = nouveau_irq_uninstall, + .irq_handler = nouveau_irq_handler, + .reclaim_buffers = drm_core_reclaim_buffers, + .get_map_ofs = drm_core_get_map_ofs, + .get_reg_ofs = drm_core_get_reg_ofs, + .ioctls = nouveau_ioctls, + .fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .ioctl = drm_ioctl, + .mmap = nouveau_ttm_mmap, + .poll = drm_poll, + .fasync = drm_fasync, +#if defined(CONFIG_COMPAT) + .compat_ioctl = nouveau_compat_ioctl, +#endif + }, + .pci_driver = { + .name = DRIVER_NAME, + .id_table = pciidlist, + .probe = nouveau_pci_probe, + .remove = nouveau_pci_remove, + .suspend = nouveau_pci_suspend, + .resume = nouveau_pci_resume + }, + + .gem_init_object = nouveau_gem_object_new, + .gem_free_object = nouveau_gem_object_del, + + .name = DRIVER_NAME, + .desc = DRIVER_DESC, +#ifdef GIT_REVISION + .date = GIT_REVISION, +#else + .date = DRIVER_DATE, +#endif + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, +}; + +static int __init nouveau_init(void) +{ + driver.num_ioctls = nouveau_max_ioctl; + + if (nouveau_modeset == -1) { +#ifdef CONFIG_VGA_CONSOLE + if (vgacon_text_force()) + nouveau_modeset = 0; + else +#endif + nouveau_modeset = 1; + } + + if (nouveau_modeset == 1) + driver.driver_features |= DRIVER_MODESET; + + return drm_init(&driver); +} + +static void __exit nouveau_exit(void) +{ + drm_exit(&driver); +} + +module_init(nouveau_init); +module_exit(nouveau_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h new file mode 100644 index 0000000000000000000000000000000000000000..88b4c7b77e7fb0929d0323243a5099e0d9be3f1c --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -0,0 +1,1286 @@ +/* + * Copyright 2005 Stephane Marchesin. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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. + */ + +#ifndef __NOUVEAU_DRV_H__ +#define __NOUVEAU_DRV_H__ + +#define DRIVER_AUTHOR "Stephane Marchesin" +#define DRIVER_EMAIL "dri-devel@lists.sourceforge.net" + +#define DRIVER_NAME "nouveau" +#define DRIVER_DESC "nVidia Riva/TNT/GeForce" +#define DRIVER_DATE "20090420" + +#define DRIVER_MAJOR 0 +#define DRIVER_MINOR 0 +#define DRIVER_PATCHLEVEL 15 + +#define NOUVEAU_FAMILY 0x0000FFFF +#define NOUVEAU_FLAGS 0xFFFF0000 + +#include "ttm/ttm_bo_api.h" +#include "ttm/ttm_bo_driver.h" +#include "ttm/ttm_placement.h" +#include "ttm/ttm_memory.h" +#include "ttm/ttm_module.h" + +struct nouveau_fpriv { + struct ttm_object_file *tfile; +}; + +#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) + +#include "nouveau_drm.h" +#include "nouveau_reg.h" +#include "nouveau_bios.h" + +#define MAX_NUM_DCB_ENTRIES 16 + +#define NOUVEAU_MAX_CHANNEL_NR 128 + +#define NV50_VM_MAX_VRAM (2*1024*1024*1024ULL) +#define NV50_VM_BLOCK (512*1024*1024ULL) +#define NV50_VM_VRAM_NR (NV50_VM_MAX_VRAM / NV50_VM_BLOCK) + +struct nouveau_bo { + struct ttm_buffer_object bo; + struct ttm_placement placement; + u32 placements[3]; + struct ttm_bo_kmap_obj kmap; + struct list_head head; + + /* protected by ttm_bo_reserve() */ + struct drm_file *reserved_by; + struct list_head entry; + int pbbo_index; + + struct nouveau_channel *channel; + + bool mappable; + bool no_vm; + + uint32_t tile_mode; + uint32_t tile_flags; + + struct drm_gem_object *gem; + struct drm_file *cpu_filp; + int pin_refcnt; +}; + +static inline struct nouveau_bo * +nouveau_bo(struct ttm_buffer_object *bo) +{ + return container_of(bo, struct nouveau_bo, bo); +} + +static inline struct nouveau_bo * +nouveau_gem_object(struct drm_gem_object *gem) +{ + return gem ? gem->driver_private : NULL; +} + +/* TODO: submit equivalent to TTM generic API upstream? */ +static inline void __iomem * +nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo) +{ + bool is_iomem; + void __iomem *ioptr = (void __force __iomem *)ttm_kmap_obj_virtual( + &nvbo->kmap, &is_iomem); + WARN_ON_ONCE(ioptr && !is_iomem); + return ioptr; +} + +struct mem_block { + struct mem_block *next; + struct mem_block *prev; + uint64_t start; + uint64_t size; + struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ +}; + +enum nouveau_flags { + NV_NFORCE = 0x10000000, + NV_NFORCE2 = 0x20000000 +}; + +#define NVOBJ_ENGINE_SW 0 +#define NVOBJ_ENGINE_GR 1 +#define NVOBJ_ENGINE_DISPLAY 2 +#define NVOBJ_ENGINE_INT 0xdeadbeef + +#define NVOBJ_FLAG_ALLOW_NO_REFS (1 << 0) +#define NVOBJ_FLAG_ZERO_ALLOC (1 << 1) +#define NVOBJ_FLAG_ZERO_FREE (1 << 2) +#define NVOBJ_FLAG_FAKE (1 << 3) +struct nouveau_gpuobj { + struct list_head list; + + struct nouveau_channel *im_channel; + struct mem_block *im_pramin; + struct nouveau_bo *im_backing; + uint32_t im_backing_start; + uint32_t *im_backing_suspend; + int im_bound; + + uint32_t flags; + int refcount; + + uint32_t engine; + uint32_t class; + + void (*dtor)(struct drm_device *, struct nouveau_gpuobj *); + void *priv; +}; + +struct nouveau_gpuobj_ref { + struct list_head list; + + struct nouveau_gpuobj *gpuobj; + uint32_t instance; + + struct nouveau_channel *channel; + int handle; +}; + +struct nouveau_channel { + struct drm_device *dev; + int id; + + /* owner of this fifo */ + struct drm_file *file_priv; + /* mapping of the fifo itself */ + struct drm_local_map *map; + + /* mapping of the regs controling the fifo */ + void __iomem *user; + uint32_t user_get; + uint32_t user_put; + + /* Fencing */ + struct { + /* lock protects the pending list only */ + spinlock_t lock; + struct list_head pending; + uint32_t sequence; + uint32_t sequence_ack; + uint32_t last_sequence_irq; + } fence; + + /* DMA push buffer */ + struct nouveau_gpuobj_ref *pushbuf; + struct nouveau_bo *pushbuf_bo; + uint32_t pushbuf_base; + + /* Notifier memory */ + struct nouveau_bo *notifier_bo; + struct mem_block *notifier_heap; + + /* PFIFO context */ + struct nouveau_gpuobj_ref *ramfc; + struct nouveau_gpuobj_ref *cache; + + /* PGRAPH context */ + /* XXX may be merge 2 pointers as private data ??? */ + struct nouveau_gpuobj_ref *ramin_grctx; + void *pgraph_ctx; + + /* NV50 VM */ + struct nouveau_gpuobj *vm_pd; + struct nouveau_gpuobj_ref *vm_gart_pt; + struct nouveau_gpuobj_ref *vm_vram_pt[NV50_VM_VRAM_NR]; + + /* Objects */ + struct nouveau_gpuobj_ref *ramin; /* Private instmem */ + struct mem_block *ramin_heap; /* Private PRAMIN heap */ + struct nouveau_gpuobj_ref *ramht; /* Hash table */ + struct list_head ramht_refs; /* Objects referenced by RAMHT */ + + /* GPU object info for stuff used in-kernel (mm_enabled) */ + uint32_t m2mf_ntfy; + uint32_t vram_handle; + uint32_t gart_handle; + bool accel_done; + + /* Push buffer state (only for drm's channel on !mm_enabled) */ + struct { + int max; + int free; + int cur; + int put; + /* access via pushbuf_bo */ + } dma; + + uint32_t sw_subchannel[8]; + + struct { + struct nouveau_gpuobj *vblsem; + uint32_t vblsem_offset; + uint32_t vblsem_rval; + struct list_head vbl_wait; + } nvsw; + + struct { + bool active; + char name[32]; + struct drm_info_list info; + } debugfs; +}; + +struct nouveau_instmem_engine { + void *priv; + + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); + int (*suspend)(struct drm_device *dev); + void (*resume)(struct drm_device *dev); + + int (*populate)(struct drm_device *, struct nouveau_gpuobj *, + uint32_t *size); + void (*clear)(struct drm_device *, struct nouveau_gpuobj *); + int (*bind)(struct drm_device *, struct nouveau_gpuobj *); + int (*unbind)(struct drm_device *, struct nouveau_gpuobj *); + void (*prepare_access)(struct drm_device *, bool write); + void (*finish_access)(struct drm_device *); +}; + +struct nouveau_mc_engine { + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); +}; + +struct nouveau_timer_engine { + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); + uint64_t (*read)(struct drm_device *dev); +}; + +struct nouveau_fb_engine { + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); +}; + +struct nouveau_fifo_engine { + void *priv; + + int channels; + + int (*init)(struct drm_device *); + void (*takedown)(struct drm_device *); + + void (*disable)(struct drm_device *); + void (*enable)(struct drm_device *); + bool (*reassign)(struct drm_device *, bool enable); + + int (*channel_id)(struct drm_device *); + + int (*create_context)(struct nouveau_channel *); + void (*destroy_context)(struct nouveau_channel *); + int (*load_context)(struct nouveau_channel *); + int (*unload_context)(struct drm_device *); +}; + +struct nouveau_pgraph_object_method { + int id; + int (*exec)(struct nouveau_channel *chan, int grclass, int mthd, + uint32_t data); +}; + +struct nouveau_pgraph_object_class { + int id; + bool software; + struct nouveau_pgraph_object_method *methods; +}; + +struct nouveau_pgraph_engine { + struct nouveau_pgraph_object_class *grclass; + bool accel_blocked; + void *ctxprog; + void *ctxvals; + + int (*init)(struct drm_device *); + void (*takedown)(struct drm_device *); + + void (*fifo_access)(struct drm_device *, bool); + + struct nouveau_channel *(*channel)(struct drm_device *); + int (*create_context)(struct nouveau_channel *); + void (*destroy_context)(struct nouveau_channel *); + int (*load_context)(struct nouveau_channel *); + int (*unload_context)(struct drm_device *); +}; + +struct nouveau_engine { + struct nouveau_instmem_engine instmem; + struct nouveau_mc_engine mc; + struct nouveau_timer_engine timer; + struct nouveau_fb_engine fb; + struct nouveau_pgraph_engine graph; + struct nouveau_fifo_engine fifo; +}; + +struct nouveau_pll_vals { + union { + struct { +#ifdef __BIG_ENDIAN + uint8_t N1, M1, N2, M2; +#else + uint8_t M1, N1, M2, N2; +#endif + }; + struct { + uint16_t NM1, NM2; + } __attribute__((packed)); + }; + int log2P; + + int refclk; +}; + +enum nv04_fp_display_regs { + FP_DISPLAY_END, + FP_TOTAL, + FP_CRTC, + FP_SYNC_START, + FP_SYNC_END, + FP_VALID_START, + FP_VALID_END +}; + +struct nv04_crtc_reg { + unsigned char MiscOutReg; /* */ + uint8_t CRTC[0x9f]; + uint8_t CR58[0x10]; + uint8_t Sequencer[5]; + uint8_t Graphics[9]; + uint8_t Attribute[21]; + unsigned char DAC[768]; /* Internal Colorlookuptable */ + + /* PCRTC regs */ + uint32_t fb_start; + uint32_t crtc_cfg; + uint32_t cursor_cfg; + uint32_t gpio_ext; + uint32_t crtc_830; + uint32_t crtc_834; + uint32_t crtc_850; + uint32_t crtc_eng_ctrl; + + /* PRAMDAC regs */ + uint32_t nv10_cursync; + struct nouveau_pll_vals pllvals; + uint32_t ramdac_gen_ctrl; + uint32_t ramdac_630; + uint32_t ramdac_634; + uint32_t tv_setup; + uint32_t tv_vtotal; + uint32_t tv_vskew; + uint32_t tv_vsync_delay; + uint32_t tv_htotal; + uint32_t tv_hskew; + uint32_t tv_hsync_delay; + uint32_t tv_hsync_delay2; + uint32_t fp_horiz_regs[7]; + uint32_t fp_vert_regs[7]; + uint32_t dither; + uint32_t fp_control; + uint32_t dither_regs[6]; + uint32_t fp_debug_0; + uint32_t fp_debug_1; + uint32_t fp_debug_2; + uint32_t fp_margin_color; + uint32_t ramdac_8c0; + uint32_t ramdac_a20; + uint32_t ramdac_a24; + uint32_t ramdac_a34; + uint32_t ctv_regs[38]; +}; + +struct nv04_output_reg { + uint32_t output; + int head; +}; + +struct nv04_mode_state { + uint32_t bpp; + uint32_t width; + uint32_t height; + uint32_t interlace; + uint32_t repaint0; + uint32_t repaint1; + uint32_t screen; + uint32_t scale; + uint32_t dither; + uint32_t extra; + uint32_t fifo; + uint32_t pixel; + uint32_t horiz; + int arbitration0; + int arbitration1; + uint32_t pll; + uint32_t pllB; + uint32_t vpll; + uint32_t vpll2; + uint32_t vpllB; + uint32_t vpll2B; + uint32_t pllsel; + uint32_t sel_clk; + uint32_t general; + uint32_t crtcOwner; + uint32_t head; + uint32_t head2; + uint32_t cursorConfig; + uint32_t cursor0; + uint32_t cursor1; + uint32_t cursor2; + uint32_t timingH; + uint32_t timingV; + uint32_t displayV; + uint32_t crtcSync; + + struct nv04_crtc_reg crtc_reg[2]; +}; + +enum nouveau_card_type { + NV_04 = 0x00, + NV_10 = 0x10, + NV_20 = 0x20, + NV_30 = 0x30, + NV_40 = 0x40, + NV_50 = 0x50, +}; + +struct drm_nouveau_private { + struct drm_device *dev; + enum { + NOUVEAU_CARD_INIT_DOWN, + NOUVEAU_CARD_INIT_DONE, + NOUVEAU_CARD_INIT_FAILED + } init_state; + + /* the card type, takes NV_* as values */ + enum nouveau_card_type card_type; + /* exact chipset, derived from NV_PMC_BOOT_0 */ + int chipset; + int flags; + + void __iomem *mmio; + void __iomem *ramin; + uint32_t ramin_size; + + struct workqueue_struct *wq; + struct work_struct irq_work; + + struct list_head vbl_waiting; + + struct { + struct ttm_global_reference mem_global_ref; + struct ttm_bo_global_ref bo_global_ref; + struct ttm_bo_device bdev; + spinlock_t bo_list_lock; + struct list_head bo_list; + atomic_t validate_sequence; + } ttm; + + struct fb_info *fbdev_info; + + int fifo_alloc_count; + struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR]; + + struct nouveau_engine engine; + struct nouveau_channel *channel; + + /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ + struct nouveau_gpuobj *ramht; + uint32_t ramin_rsvd_vram; + uint32_t ramht_offset; + uint32_t ramht_size; + uint32_t ramht_bits; + uint32_t ramfc_offset; + uint32_t ramfc_size; + uint32_t ramro_offset; + uint32_t ramro_size; + + /* base physical adresses */ + uint64_t fb_phys; + uint64_t fb_available_size; + uint64_t fb_mappable_pages; + uint64_t fb_aper_free; + + struct { + enum { + NOUVEAU_GART_NONE = 0, + NOUVEAU_GART_AGP, + NOUVEAU_GART_SGDMA + } type; + uint64_t aper_base; + uint64_t aper_size; + uint64_t aper_free; + + struct nouveau_gpuobj *sg_ctxdma; + struct page *sg_dummy_page; + dma_addr_t sg_dummy_bus; + + /* nottm hack */ + struct drm_ttm_backend *sg_be; + unsigned long sg_handle; + } gart_info; + + /* G8x/G9x virtual address space */ + uint64_t vm_gart_base; + uint64_t vm_gart_size; + uint64_t vm_vram_base; + uint64_t vm_vram_size; + uint64_t vm_end; + struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; + int vm_vram_pt_nr; + + /* the mtrr covering the FB */ + int fb_mtrr; + + struct mem_block *ramin_heap; + + /* context table pointed to be NV_PGRAPH_CHANNEL_CTX_TABLE (0x400780) */ + uint32_t ctx_table_size; + struct nouveau_gpuobj_ref *ctx_table; + + struct list_head gpuobj_list; + + struct nvbios VBIOS; + struct nouveau_bios_info *vbios; + + struct nv04_mode_state mode_reg; + struct nv04_mode_state saved_reg; + uint32_t saved_vga_font[4][16384]; + uint32_t crtc_owner; + uint32_t dac_users[4]; + + struct nouveau_suspend_resume { + uint32_t fifo_mode; + uint32_t graph_ctx_control; + uint32_t graph_state; + uint32_t *ramin_copy; + uint64_t ramin_size; + } susres; + + struct backlight_device *backlight; + bool acpi_dsm; + + struct nouveau_channel *evo; + + struct { + struct dentry *channel_root; + } debugfs; +}; + +static inline struct drm_nouveau_private * +nouveau_bdev(struct ttm_bo_device *bd) +{ + return container_of(bd, struct drm_nouveau_private, ttm.bdev); +} + +static inline int +nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo) +{ + struct nouveau_bo *prev; + + if (!pnvbo) + return -EINVAL; + prev = *pnvbo; + + *pnvbo = ref ? nouveau_bo(ttm_bo_reference(&ref->bo)) : NULL; + if (prev) { + struct ttm_buffer_object *bo = &prev->bo; + + ttm_bo_unref(&bo); + } + + return 0; +} + +#define NOUVEAU_CHECK_INITIALISED_WITH_RETURN do { \ + struct drm_nouveau_private *nv = dev->dev_private; \ + if (nv->init_state != NOUVEAU_CARD_INIT_DONE) { \ + NV_ERROR(dev, "called without init\n"); \ + return -EINVAL; \ + } \ +} while (0) + +#define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id, cl, ch) do { \ + struct drm_nouveau_private *nv = dev->dev_private; \ + if (!nouveau_channel_owner(dev, (cl), (id))) { \ + NV_ERROR(dev, "pid %d doesn't own channel %d\n", \ + DRM_CURRENTPID, (id)); \ + return -EPERM; \ + } \ + (ch) = nv->fifos[(id)]; \ +} while (0) + +/* nouveau_drv.c */ +extern int nouveau_noagp; +extern int nouveau_duallink; +extern int nouveau_uscript_lvds; +extern int nouveau_uscript_tmds; +extern int nouveau_vram_pushbuf; +extern int nouveau_vram_notify; +extern int nouveau_fbpercrtc; +extern char *nouveau_tv_norm; +extern int nouveau_reg_debug; +extern char *nouveau_vbios; + +/* nouveau_state.c */ +extern void nouveau_preclose(struct drm_device *dev, struct drm_file *); +extern int nouveau_load(struct drm_device *, unsigned long flags); +extern int nouveau_firstopen(struct drm_device *); +extern void nouveau_lastclose(struct drm_device *); +extern int nouveau_unload(struct drm_device *); +extern int nouveau_ioctl_getparam(struct drm_device *, void *data, + struct drm_file *); +extern int nouveau_ioctl_setparam(struct drm_device *, void *data, + struct drm_file *); +extern bool nouveau_wait_until(struct drm_device *, uint64_t timeout, + uint32_t reg, uint32_t mask, uint32_t val); +extern bool nouveau_wait_for_idle(struct drm_device *); +extern int nouveau_card_init(struct drm_device *); +extern int nouveau_ioctl_card_init(struct drm_device *, void *data, + struct drm_file *); +extern int nouveau_ioctl_suspend(struct drm_device *, void *data, + struct drm_file *); +extern int nouveau_ioctl_resume(struct drm_device *, void *data, + struct drm_file *); + +/* nouveau_mem.c */ +extern int nouveau_mem_init_heap(struct mem_block **, uint64_t start, + uint64_t size); +extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *, + uint64_t size, int align2, + struct drm_file *, int tail); +extern void nouveau_mem_takedown(struct mem_block **heap); +extern void nouveau_mem_free_block(struct mem_block *); +extern uint64_t nouveau_mem_fb_amount(struct drm_device *); +extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap); +extern int nouveau_mem_init(struct drm_device *); +extern int nouveau_mem_init_agp(struct drm_device *); +extern void nouveau_mem_close(struct drm_device *); +extern int nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt, + uint32_t size, uint32_t flags, + uint64_t phys); +extern void nv50_mem_vm_unbind(struct drm_device *, uint64_t virt, + uint32_t size); + +/* nouveau_notifier.c */ +extern int nouveau_notifier_init_channel(struct nouveau_channel *); +extern void nouveau_notifier_takedown_channel(struct nouveau_channel *); +extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, + int cout, uint32_t *offset); +extern int nouveau_notifier_offset(struct nouveau_gpuobj *, uint32_t *); +extern int nouveau_ioctl_notifier_alloc(struct drm_device *, void *data, + struct drm_file *); +extern int nouveau_ioctl_notifier_free(struct drm_device *, void *data, + struct drm_file *); + +/* nouveau_channel.c */ +extern struct drm_ioctl_desc nouveau_ioctls[]; +extern int nouveau_max_ioctl; +extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *); +extern int nouveau_channel_owner(struct drm_device *, struct drm_file *, + int channel); +extern int nouveau_channel_alloc(struct drm_device *dev, + struct nouveau_channel **chan, + struct drm_file *file_priv, + uint32_t fb_ctxdma, uint32_t tt_ctxdma); +extern void nouveau_channel_free(struct nouveau_channel *); +extern int nouveau_channel_idle(struct nouveau_channel *chan); + +/* nouveau_object.c */ +extern int nouveau_gpuobj_early_init(struct drm_device *); +extern int nouveau_gpuobj_init(struct drm_device *); +extern void nouveau_gpuobj_takedown(struct drm_device *); +extern void nouveau_gpuobj_late_takedown(struct drm_device *); +extern int nouveau_gpuobj_suspend(struct drm_device *dev); +extern void nouveau_gpuobj_suspend_cleanup(struct drm_device *dev); +extern void nouveau_gpuobj_resume(struct drm_device *dev); +extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, + uint32_t vram_h, uint32_t tt_h); +extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *); +extern int nouveau_gpuobj_new(struct drm_device *, struct nouveau_channel *, + uint32_t size, int align, uint32_t flags, + struct nouveau_gpuobj **); +extern int nouveau_gpuobj_del(struct drm_device *, struct nouveau_gpuobj **); +extern int nouveau_gpuobj_ref_add(struct drm_device *, struct nouveau_channel *, + uint32_t handle, struct nouveau_gpuobj *, + struct nouveau_gpuobj_ref **); +extern int nouveau_gpuobj_ref_del(struct drm_device *, + struct nouveau_gpuobj_ref **); +extern int nouveau_gpuobj_ref_find(struct nouveau_channel *, uint32_t handle, + struct nouveau_gpuobj_ref **ref_ret); +extern int nouveau_gpuobj_new_ref(struct drm_device *, + struct nouveau_channel *alloc_chan, + struct nouveau_channel *ref_chan, + uint32_t handle, uint32_t size, int align, + uint32_t flags, struct nouveau_gpuobj_ref **); +extern int nouveau_gpuobj_new_fake(struct drm_device *, + uint32_t p_offset, uint32_t b_offset, + uint32_t size, uint32_t flags, + struct nouveau_gpuobj **, + struct nouveau_gpuobj_ref**); +extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class, + uint64_t offset, uint64_t size, int access, + int target, struct nouveau_gpuobj **); +extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *, + uint64_t offset, uint64_t size, + int access, struct nouveau_gpuobj **, + uint32_t *o_ret); +extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class, + struct nouveau_gpuobj **); +extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, + struct drm_file *); +extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data, + struct drm_file *); + +/* nouveau_irq.c */ +extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); +extern void nouveau_irq_preinstall(struct drm_device *); +extern int nouveau_irq_postinstall(struct drm_device *); +extern void nouveau_irq_uninstall(struct drm_device *); + +/* nouveau_sgdma.c */ +extern int nouveau_sgdma_init(struct drm_device *); +extern void nouveau_sgdma_takedown(struct drm_device *); +extern int nouveau_sgdma_get_page(struct drm_device *, uint32_t offset, + uint32_t *page); +extern struct ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *); + +/* nouveau_debugfs.c */ +#if defined(CONFIG_DRM_NOUVEAU_DEBUG) +extern int nouveau_debugfs_init(struct drm_minor *); +extern void nouveau_debugfs_takedown(struct drm_minor *); +extern int nouveau_debugfs_channel_init(struct nouveau_channel *); +extern void nouveau_debugfs_channel_fini(struct nouveau_channel *); +#else +static inline int +nouveau_debugfs_init(struct drm_minor *minor) +{ + return 0; +} + +static inline void nouveau_debugfs_takedown(struct drm_minor *minor) +{ +} + +static inline int +nouveau_debugfs_channel_init(struct nouveau_channel *chan) +{ + return 0; +} + +static inline void +nouveau_debugfs_channel_fini(struct nouveau_channel *chan) +{ +} +#endif + +/* nouveau_dma.c */ +extern int nouveau_dma_init(struct nouveau_channel *); +extern int nouveau_dma_wait(struct nouveau_channel *, int size); + +/* nouveau_acpi.c */ +#ifdef CONFIG_ACPI +extern int nouveau_hybrid_setup(struct drm_device *dev); +extern bool nouveau_dsm_probe(struct drm_device *dev); +#else +static inline int nouveau_hybrid_setup(struct drm_device *dev) +{ + return 0; +} +static inline bool nouveau_dsm_probe(struct drm_device *dev) +{ + return false; +} +#endif + +/* nouveau_backlight.c */ +#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT +extern int nouveau_backlight_init(struct drm_device *); +extern void nouveau_backlight_exit(struct drm_device *); +#else +static inline int nouveau_backlight_init(struct drm_device *dev) +{ + return 0; +} + +static inline void nouveau_backlight_exit(struct drm_device *dev) { } +#endif + +/* nouveau_bios.c */ +extern int nouveau_bios_init(struct drm_device *); +extern void nouveau_bios_takedown(struct drm_device *dev); +extern int nouveau_run_vbios_init(struct drm_device *); +extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table, + struct dcb_entry *); +extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *, + enum dcb_gpio_tag); +extern struct dcb_connector_table_entry * +nouveau_bios_connector_entry(struct drm_device *, int index); +extern int get_pll_limits(struct drm_device *, uint32_t limit_match, + struct pll_lims *); +extern int nouveau_bios_run_display_table(struct drm_device *, + struct dcb_entry *, + uint32_t script, int pxclk); +extern void *nouveau_bios_dp_table(struct drm_device *, struct dcb_entry *, + int *length); +extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); +extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *); +extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk, + bool *dl, bool *if_is_24bit); +extern int run_tmds_table(struct drm_device *, struct dcb_entry *, + int head, int pxclk); +extern int call_lvds_script(struct drm_device *, struct dcb_entry *, int head, + enum LVDS_script, int pxclk); + +/* nouveau_ttm.c */ +int nouveau_ttm_global_init(struct drm_nouveau_private *); +void nouveau_ttm_global_release(struct drm_nouveau_private *); +int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); + +/* nouveau_dp.c */ +int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, + uint8_t *data, int data_nr); +bool nouveau_dp_detect(struct drm_encoder *); +bool nouveau_dp_link_train(struct drm_encoder *); + +/* nv04_fb.c */ +extern int nv04_fb_init(struct drm_device *); +extern void nv04_fb_takedown(struct drm_device *); + +/* nv10_fb.c */ +extern int nv10_fb_init(struct drm_device *); +extern void nv10_fb_takedown(struct drm_device *); + +/* nv40_fb.c */ +extern int nv40_fb_init(struct drm_device *); +extern void nv40_fb_takedown(struct drm_device *); + +/* nv04_fifo.c */ +extern int nv04_fifo_init(struct drm_device *); +extern void nv04_fifo_disable(struct drm_device *); +extern void nv04_fifo_enable(struct drm_device *); +extern bool nv04_fifo_reassign(struct drm_device *, bool); +extern int nv04_fifo_channel_id(struct drm_device *); +extern int nv04_fifo_create_context(struct nouveau_channel *); +extern void nv04_fifo_destroy_context(struct nouveau_channel *); +extern int nv04_fifo_load_context(struct nouveau_channel *); +extern int nv04_fifo_unload_context(struct drm_device *); + +/* nv10_fifo.c */ +extern int nv10_fifo_init(struct drm_device *); +extern int nv10_fifo_channel_id(struct drm_device *); +extern int nv10_fifo_create_context(struct nouveau_channel *); +extern void nv10_fifo_destroy_context(struct nouveau_channel *); +extern int nv10_fifo_load_context(struct nouveau_channel *); +extern int nv10_fifo_unload_context(struct drm_device *); + +/* nv40_fifo.c */ +extern int nv40_fifo_init(struct drm_device *); +extern int nv40_fifo_create_context(struct nouveau_channel *); +extern void nv40_fifo_destroy_context(struct nouveau_channel *); +extern int nv40_fifo_load_context(struct nouveau_channel *); +extern int nv40_fifo_unload_context(struct drm_device *); + +/* nv50_fifo.c */ +extern int nv50_fifo_init(struct drm_device *); +extern void nv50_fifo_takedown(struct drm_device *); +extern int nv50_fifo_channel_id(struct drm_device *); +extern int nv50_fifo_create_context(struct nouveau_channel *); +extern void nv50_fifo_destroy_context(struct nouveau_channel *); +extern int nv50_fifo_load_context(struct nouveau_channel *); +extern int nv50_fifo_unload_context(struct drm_device *); + +/* nv04_graph.c */ +extern struct nouveau_pgraph_object_class nv04_graph_grclass[]; +extern int nv04_graph_init(struct drm_device *); +extern void nv04_graph_takedown(struct drm_device *); +extern void nv04_graph_fifo_access(struct drm_device *, bool); +extern struct nouveau_channel *nv04_graph_channel(struct drm_device *); +extern int nv04_graph_create_context(struct nouveau_channel *); +extern void nv04_graph_destroy_context(struct nouveau_channel *); +extern int nv04_graph_load_context(struct nouveau_channel *); +extern int nv04_graph_unload_context(struct drm_device *); +extern void nv04_graph_context_switch(struct drm_device *); + +/* nv10_graph.c */ +extern struct nouveau_pgraph_object_class nv10_graph_grclass[]; +extern int nv10_graph_init(struct drm_device *); +extern void nv10_graph_takedown(struct drm_device *); +extern struct nouveau_channel *nv10_graph_channel(struct drm_device *); +extern int nv10_graph_create_context(struct nouveau_channel *); +extern void nv10_graph_destroy_context(struct nouveau_channel *); +extern int nv10_graph_load_context(struct nouveau_channel *); +extern int nv10_graph_unload_context(struct drm_device *); +extern void nv10_graph_context_switch(struct drm_device *); + +/* nv20_graph.c */ +extern struct nouveau_pgraph_object_class nv20_graph_grclass[]; +extern struct nouveau_pgraph_object_class nv30_graph_grclass[]; +extern int nv20_graph_create_context(struct nouveau_channel *); +extern void nv20_graph_destroy_context(struct nouveau_channel *); +extern int nv20_graph_load_context(struct nouveau_channel *); +extern int nv20_graph_unload_context(struct drm_device *); +extern int nv20_graph_init(struct drm_device *); +extern void nv20_graph_takedown(struct drm_device *); +extern int nv30_graph_init(struct drm_device *); + +/* nv40_graph.c */ +extern struct nouveau_pgraph_object_class nv40_graph_grclass[]; +extern int nv40_graph_init(struct drm_device *); +extern void nv40_graph_takedown(struct drm_device *); +extern struct nouveau_channel *nv40_graph_channel(struct drm_device *); +extern int nv40_graph_create_context(struct nouveau_channel *); +extern void nv40_graph_destroy_context(struct nouveau_channel *); +extern int nv40_graph_load_context(struct nouveau_channel *); +extern int nv40_graph_unload_context(struct drm_device *); +extern int nv40_grctx_init(struct drm_device *); +extern void nv40_grctx_fini(struct drm_device *); +extern void nv40_grctx_vals_load(struct drm_device *, struct nouveau_gpuobj *); + +/* nv50_graph.c */ +extern struct nouveau_pgraph_object_class nv50_graph_grclass[]; +extern int nv50_graph_init(struct drm_device *); +extern void nv50_graph_takedown(struct drm_device *); +extern void nv50_graph_fifo_access(struct drm_device *, bool); +extern struct nouveau_channel *nv50_graph_channel(struct drm_device *); +extern int nv50_graph_create_context(struct nouveau_channel *); +extern void nv50_graph_destroy_context(struct nouveau_channel *); +extern int nv50_graph_load_context(struct nouveau_channel *); +extern int nv50_graph_unload_context(struct drm_device *); +extern void nv50_graph_context_switch(struct drm_device *); + +/* nv04_instmem.c */ +extern int nv04_instmem_init(struct drm_device *); +extern void nv04_instmem_takedown(struct drm_device *); +extern int nv04_instmem_suspend(struct drm_device *); +extern void nv04_instmem_resume(struct drm_device *); +extern int nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, + uint32_t *size); +extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); +extern int nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); +extern int nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); +extern void nv04_instmem_prepare_access(struct drm_device *, bool write); +extern void nv04_instmem_finish_access(struct drm_device *); + +/* nv50_instmem.c */ +extern int nv50_instmem_init(struct drm_device *); +extern void nv50_instmem_takedown(struct drm_device *); +extern int nv50_instmem_suspend(struct drm_device *); +extern void nv50_instmem_resume(struct drm_device *); +extern int nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, + uint32_t *size); +extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); +extern int nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); +extern int nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); +extern void nv50_instmem_prepare_access(struct drm_device *, bool write); +extern void nv50_instmem_finish_access(struct drm_device *); + +/* nv04_mc.c */ +extern int nv04_mc_init(struct drm_device *); +extern void nv04_mc_takedown(struct drm_device *); + +/* nv40_mc.c */ +extern int nv40_mc_init(struct drm_device *); +extern void nv40_mc_takedown(struct drm_device *); + +/* nv50_mc.c */ +extern int nv50_mc_init(struct drm_device *); +extern void nv50_mc_takedown(struct drm_device *); + +/* nv04_timer.c */ +extern int nv04_timer_init(struct drm_device *); +extern uint64_t nv04_timer_read(struct drm_device *); +extern void nv04_timer_takedown(struct drm_device *); + +extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); + +/* nv04_dac.c */ +extern int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry); +extern enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, + struct drm_connector *connector); +extern int nv04_dac_output_offset(struct drm_encoder *encoder); +extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable); + +/* nv04_dfp.c */ +extern int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry); +extern int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent); +extern void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent, + int head, bool dl); +extern void nv04_dfp_disable(struct drm_device *dev, int head); +extern void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode); + +/* nv04_tv.c */ +extern int nv04_tv_identify(struct drm_device *dev, int i2c_index); +extern int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry); + +/* nv17_tv.c */ +extern int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry); +extern enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, + struct drm_connector *connector, + uint32_t pin_mask); + +/* nv04_display.c */ +extern int nv04_display_create(struct drm_device *); +extern void nv04_display_destroy(struct drm_device *); +extern void nv04_display_restore(struct drm_device *); + +/* nv04_crtc.c */ +extern int nv04_crtc_create(struct drm_device *, int index); + +/* nouveau_bo.c */ +extern struct ttm_bo_driver nouveau_bo_driver; +extern int nouveau_bo_new(struct drm_device *, struct nouveau_channel *, + int size, int align, uint32_t flags, + uint32_t tile_mode, uint32_t tile_flags, + bool no_vm, bool mappable, struct nouveau_bo **); +extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags); +extern int nouveau_bo_unpin(struct nouveau_bo *); +extern int nouveau_bo_map(struct nouveau_bo *); +extern void nouveau_bo_unmap(struct nouveau_bo *); +extern void nouveau_bo_placement_set(struct nouveau_bo *, uint32_t memtype); +extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index); +extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); +extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); +extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); + +/* nouveau_fence.c */ +struct nouveau_fence; +extern int nouveau_fence_init(struct nouveau_channel *); +extern void nouveau_fence_fini(struct nouveau_channel *); +extern void nouveau_fence_update(struct nouveau_channel *); +extern int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **, + bool emit); +extern int nouveau_fence_emit(struct nouveau_fence *); +struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *); +extern bool nouveau_fence_signalled(void *obj, void *arg); +extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); +extern int nouveau_fence_flush(void *obj, void *arg); +extern void nouveau_fence_unref(void **obj); +extern void *nouveau_fence_ref(void *obj); +extern void nouveau_fence_handler(struct drm_device *dev, int channel); + +/* nouveau_gem.c */ +extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, + int size, int align, uint32_t flags, + uint32_t tile_mode, uint32_t tile_flags, + bool no_vm, bool mappable, struct nouveau_bo **); +extern int nouveau_gem_object_new(struct drm_gem_object *); +extern void nouveau_gem_object_del(struct drm_gem_object *); +extern int nouveau_gem_ioctl_new(struct drm_device *, void *, + struct drm_file *); +extern int nouveau_gem_ioctl_pushbuf(struct drm_device *, void *, + struct drm_file *); +extern int nouveau_gem_ioctl_pushbuf_call(struct drm_device *, void *, + struct drm_file *); +extern int nouveau_gem_ioctl_pushbuf_call2(struct drm_device *, void *, + struct drm_file *); +extern int nouveau_gem_ioctl_pin(struct drm_device *, void *, + struct drm_file *); +extern int nouveau_gem_ioctl_unpin(struct drm_device *, void *, + struct drm_file *); +extern int nouveau_gem_ioctl_tile(struct drm_device *, void *, + struct drm_file *); +extern int nouveau_gem_ioctl_cpu_prep(struct drm_device *, void *, + struct drm_file *); +extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *, + struct drm_file *); +extern int nouveau_gem_ioctl_info(struct drm_device *, void *, + struct drm_file *); + +/* nv17_gpio.c */ +int nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); +int nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); + +#ifndef ioread32_native +#ifdef __BIG_ENDIAN +#define ioread16_native ioread16be +#define iowrite16_native iowrite16be +#define ioread32_native ioread32be +#define iowrite32_native iowrite32be +#else /* def __BIG_ENDIAN */ +#define ioread16_native ioread16 +#define iowrite16_native iowrite16 +#define ioread32_native ioread32 +#define iowrite32_native iowrite32 +#endif /* def __BIG_ENDIAN else */ +#endif /* !ioread32_native */ + +/* channel control reg access */ +static inline u32 nvchan_rd32(struct nouveau_channel *chan, unsigned reg) +{ + return ioread32_native(chan->user + reg); +} + +static inline void nvchan_wr32(struct nouveau_channel *chan, + unsigned reg, u32 val) +{ + iowrite32_native(val, chan->user + reg); +} + +/* register access */ +static inline u32 nv_rd32(struct drm_device *dev, unsigned reg) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + return ioread32_native(dev_priv->mmio + reg); +} + +static inline void nv_wr32(struct drm_device *dev, unsigned reg, u32 val) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + iowrite32_native(val, dev_priv->mmio + reg); +} + +static inline u8 nv_rd08(struct drm_device *dev, unsigned reg) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + return ioread8(dev_priv->mmio + reg); +} + +static inline void nv_wr08(struct drm_device *dev, unsigned reg, u8 val) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + iowrite8(val, dev_priv->mmio + reg); +} + +#define nv_wait(reg, mask, val) \ + nouveau_wait_until(dev, 2000000000ULL, (reg), (mask), (val)) + +/* PRAMIN access */ +static inline u32 nv_ri32(struct drm_device *dev, unsigned offset) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + return ioread32_native(dev_priv->ramin + offset); +} + +static inline void nv_wi32(struct drm_device *dev, unsigned offset, u32 val) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + iowrite32_native(val, dev_priv->ramin + offset); +} + +/* object access */ +static inline u32 nv_ro32(struct drm_device *dev, struct nouveau_gpuobj *obj, + unsigned index) +{ + return nv_ri32(dev, obj->im_pramin->start + index * 4); +} + +static inline void nv_wo32(struct drm_device *dev, struct nouveau_gpuobj *obj, + unsigned index, u32 val) +{ + nv_wi32(dev, obj->im_pramin->start + index * 4, val); +} + +/* + * Logging + * Argument d is (struct drm_device *). + */ +#define NV_PRINTK(level, d, fmt, arg...) \ + printk(level "[" DRM_NAME "] " DRIVER_NAME " %s: " fmt, \ + pci_name(d->pdev), ##arg) +#ifndef NV_DEBUG_NOTRACE +#define NV_DEBUG(d, fmt, arg...) do { \ + if (drm_debug) { \ + NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__, \ + __LINE__, ##arg); \ + } \ +} while (0) +#else +#define NV_DEBUG(d, fmt, arg...) do { \ + if (drm_debug) \ + NV_PRINTK(KERN_DEBUG, d, fmt, ##arg); \ +} while (0) +#endif +#define NV_ERROR(d, fmt, arg...) NV_PRINTK(KERN_ERR, d, fmt, ##arg) +#define NV_INFO(d, fmt, arg...) NV_PRINTK(KERN_INFO, d, fmt, ##arg) +#define NV_TRACEWARN(d, fmt, arg...) NV_PRINTK(KERN_NOTICE, d, fmt, ##arg) +#define NV_TRACE(d, fmt, arg...) NV_PRINTK(KERN_INFO, d, fmt, ##arg) +#define NV_WARN(d, fmt, arg...) NV_PRINTK(KERN_WARNING, d, fmt, ##arg) + +/* nouveau_reg_debug bitmask */ +enum { + NOUVEAU_REG_DEBUG_MC = 0x1, + NOUVEAU_REG_DEBUG_VIDEO = 0x2, + NOUVEAU_REG_DEBUG_FB = 0x4, + NOUVEAU_REG_DEBUG_EXTDEV = 0x8, + NOUVEAU_REG_DEBUG_CRTC = 0x10, + NOUVEAU_REG_DEBUG_RAMDAC = 0x20, + NOUVEAU_REG_DEBUG_VGACRTC = 0x40, + NOUVEAU_REG_DEBUG_RMVIO = 0x80, + NOUVEAU_REG_DEBUG_VGAATTR = 0x100, + NOUVEAU_REG_DEBUG_EVO = 0x200, +}; + +#define NV_REG_DEBUG(type, dev, fmt, arg...) do { \ + if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_##type) \ + NV_PRINTK(KERN_DEBUG, dev, "%s: " fmt, __func__, ##arg); \ +} while (0) + +static inline bool +nv_two_heads(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + const int impl = dev->pci_device & 0x0ff0; + + if (dev_priv->card_type >= NV_10 && impl != 0x0100 && + impl != 0x0150 && impl != 0x01a0 && impl != 0x0200) + return true; + + return false; +} + +static inline bool +nv_gf4_disp_arch(struct drm_device *dev) +{ + return nv_two_heads(dev) && (dev->pci_device & 0x0ff0) != 0x0110; +} + +static inline bool +nv_two_reg_pll(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + const int impl = dev->pci_device & 0x0ff0; + + if (impl == 0x0310 || impl == 0x0340 || dev_priv->card_type >= NV_40) + return true; + return false; +} + +#define NV50_NVSW 0x0000506e +#define NV50_NVSW_DMA_SEMAPHORE 0x00000060 +#define NV50_NVSW_SEMAPHORE_OFFSET 0x00000064 +#define NV50_NVSW_SEMAPHORE_ACQUIRE 0x00000068 +#define NV50_NVSW_SEMAPHORE_RELEASE 0x0000006c +#define NV50_NVSW_DMA_VBLSEM 0x0000018c +#define NV50_NVSW_VBLSEM_OFFSET 0x00000400 +#define NV50_NVSW_VBLSEM_RELEASE_VALUE 0x00000404 +#define NV50_NVSW_VBLSEM_RELEASE 0x00000408 + +#endif /* __NOUVEAU_DRV_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h new file mode 100644 index 0000000000000000000000000000000000000000..bc4a24029ed12a4ee5a59857975791a867699054 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2008 Maarten Maathuis. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +#ifndef __NOUVEAU_ENCODER_H__ +#define __NOUVEAU_ENCODER_H__ + +#include "drm_encoder_slave.h" +#include "nouveau_drv.h" + +#define NV_DPMS_CLEARED 0x80 + +struct nouveau_encoder { + struct drm_encoder_slave base; + + struct dcb_entry *dcb; + int or; + + struct drm_display_mode mode; + int last_dpms; + + struct nv04_output_reg restore; + + void (*disconnect)(struct nouveau_encoder *encoder); + + union { + struct { + int dpcd_version; + int link_nr; + int link_bw; + } dp; + }; +}; + +static inline struct nouveau_encoder *nouveau_encoder(struct drm_encoder *enc) +{ + struct drm_encoder_slave *slave = to_encoder_slave(enc); + + return container_of(slave, struct nouveau_encoder, base); +} + +static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc) +{ + return &enc->base.base; +} + +struct nouveau_connector * +nouveau_encoder_connector_get(struct nouveau_encoder *encoder); +int nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry); +int nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry); + +struct bit_displayport_encoder_table { + uint32_t match; + uint8_t record_nr; + uint8_t unknown; + uint16_t script0; + uint16_t script1; + uint16_t unknown_table; +} __attribute__ ((packed)); + +struct bit_displayport_encoder_table_entry { + uint8_t vs_level; + uint8_t pre_level; + uint8_t reg0; + uint8_t reg1; + uint8_t reg2; +} __attribute__ ((packed)); + +#endif /* __NOUVEAU_ENCODER_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h new file mode 100644 index 0000000000000000000000000000000000000000..4a3f31aa1949641ae8daf265e3417141055b93fa --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_fb.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008 Maarten Maathuis. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +#ifndef __NOUVEAU_FB_H__ +#define __NOUVEAU_FB_H__ + +struct nouveau_framebuffer { + struct drm_framebuffer base; + struct nouveau_bo *nvbo; +}; + +static inline struct nouveau_framebuffer * +nouveau_framebuffer(struct drm_framebuffer *fb) +{ + return container_of(fb, struct nouveau_framebuffer, base); +} + +extern const struct drm_mode_config_funcs nouveau_mode_config_funcs; + +struct drm_framebuffer * +nouveau_framebuffer_create(struct drm_device *, struct nouveau_bo *, + struct drm_mode_fb_cmd *); + +#endif /* __NOUVEAU_FB_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c new file mode 100644 index 0000000000000000000000000000000000000000..36e8c5e4503afac7db84f6cac4d9836ed31ee3e8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -0,0 +1,380 @@ +/* + * Copyright © 2007 David Airlie + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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. + * + * Authors: + * David Airlie + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" +#include "drm_crtc_helper.h" +#include "drm_fb_helper.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_crtc.h" +#include "nouveau_fb.h" +#include "nouveau_fbcon.h" +#include "nouveau_dma.h" + +static int +nouveau_fbcon_sync(struct fb_info *info) +{ + struct nouveau_fbcon_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->channel; + int ret, i; + + if (!chan->accel_done || + info->state != FBINFO_STATE_RUNNING || + info->flags & FBINFO_HWACCEL_DISABLED) + return 0; + + if (RING_SPACE(chan, 4)) { + NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + info->flags |= FBINFO_HWACCEL_DISABLED; + return 0; + } + + BEGIN_RING(chan, 0, 0x0104, 1); + OUT_RING(chan, 0); + BEGIN_RING(chan, 0, 0x0100, 1); + OUT_RING(chan, 0); + nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy + 3, 0xffffffff); + FIRE_RING(chan); + + ret = -EBUSY; + for (i = 0; i < 100000; i++) { + if (!nouveau_bo_rd32(chan->notifier_bo, chan->m2mf_ntfy + 3)) { + ret = 0; + break; + } + DRM_UDELAY(1); + } + + if (ret) { + NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + info->flags |= FBINFO_HWACCEL_DISABLED; + return 0; + } + + chan->accel_done = false; + return 0; +} + +static struct fb_ops nouveau_fbcon_ops = { + .owner = THIS_MODULE, + .fb_check_var = drm_fb_helper_check_var, + .fb_set_par = drm_fb_helper_set_par, + .fb_setcolreg = drm_fb_helper_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_sync = nouveau_fbcon_sync, + .fb_pan_display = drm_fb_helper_pan_display, + .fb_blank = drm_fb_helper_blank, + .fb_setcmap = drm_fb_helper_setcmap, +}; + +static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, + u16 blue, int regno) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + + nv_crtc->lut.r[regno] = red; + nv_crtc->lut.g[regno] = green; + nv_crtc->lut.b[regno] = blue; +} + +static void nouveau_fbcon_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, int regno) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + + *red = nv_crtc->lut.r[regno]; + *green = nv_crtc->lut.g[regno]; + *blue = nv_crtc->lut.b[regno]; +} + +static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { + .gamma_set = nouveau_fbcon_gamma_set, + .gamma_get = nouveau_fbcon_gamma_get +}; + +#if defined(__i386__) || defined(__x86_64__) +static bool +nouveau_fbcon_has_vesafb_or_efifb(struct drm_device *dev) +{ + struct pci_dev *pdev = dev->pdev; + int ramin; + + if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB && + screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) + return false; + + if (screen_info.lfb_base < pci_resource_start(pdev, 1)) + goto not_fb; + + if (screen_info.lfb_base + screen_info.lfb_size >= + pci_resource_start(pdev, 1) + pci_resource_len(pdev, 1)) + goto not_fb; + + return true; +not_fb: + ramin = 2; + if (pci_resource_len(pdev, ramin) == 0) { + ramin = 3; + if (pci_resource_len(pdev, ramin) == 0) + return false; + } + + if (screen_info.lfb_base < pci_resource_start(pdev, ramin)) + return false; + + if (screen_info.lfb_base + screen_info.lfb_size >= + pci_resource_start(pdev, ramin) + pci_resource_len(pdev, ramin)) + return false; + + return true; +} +#endif + +void +nouveau_fbcon_zfill(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct fb_info *info = dev_priv->fbdev_info; + struct fb_fillrect rect; + + /* Clear the entire fbcon. The drm will program every connector + * with it's preferred mode. If the sizes differ, one display will + * quite likely have garbage around the console. + */ + rect.dx = rect.dy = 0; + rect.width = info->var.xres_virtual; + rect.height = info->var.yres_virtual; + rect.color = 0; + rect.rop = ROP_COPY; + info->fbops->fb_fillrect(info, &rect); +} + +static int +nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width, + uint32_t fb_height, uint32_t surface_width, + uint32_t surface_height, uint32_t surface_depth, + uint32_t surface_bpp, struct drm_framebuffer **pfb) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct fb_info *info; + struct nouveau_fbcon_par *par; + struct drm_framebuffer *fb; + struct nouveau_framebuffer *nouveau_fb; + struct nouveau_bo *nvbo; + struct drm_mode_fb_cmd mode_cmd; + struct device *device = &dev->pdev->dev; + int size, ret; + + mode_cmd.width = surface_width; + mode_cmd.height = surface_height; + + mode_cmd.bpp = surface_bpp; + mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3); + mode_cmd.pitch = ALIGN(mode_cmd.pitch, 256); + mode_cmd.depth = surface_depth; + + size = mode_cmd.pitch * mode_cmd.height; + size = ALIGN(size, PAGE_SIZE); + + ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM, + 0, 0x0000, false, true, &nvbo); + if (ret) { + NV_ERROR(dev, "failed to allocate framebuffer\n"); + goto out; + } + + ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM); + if (ret) { + NV_ERROR(dev, "failed to pin fb: %d\n", ret); + nouveau_bo_ref(NULL, &nvbo); + goto out; + } + + ret = nouveau_bo_map(nvbo); + if (ret) { + NV_ERROR(dev, "failed to map fb: %d\n", ret); + nouveau_bo_unpin(nvbo); + nouveau_bo_ref(NULL, &nvbo); + goto out; + } + + mutex_lock(&dev->struct_mutex); + + fb = nouveau_framebuffer_create(dev, nvbo, &mode_cmd); + if (!fb) { + ret = -ENOMEM; + NV_ERROR(dev, "failed to allocate fb.\n"); + goto out_unref; + } + + list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list); + + nouveau_fb = nouveau_framebuffer(fb); + *pfb = fb; + + info = framebuffer_alloc(sizeof(struct nouveau_fbcon_par), device); + if (!info) { + ret = -ENOMEM; + goto out_unref; + } + + par = info->par; + par->helper.funcs = &nouveau_fbcon_helper_funcs; + par->helper.dev = dev; + ret = drm_fb_helper_init_crtc_count(&par->helper, 2, 4); + if (ret) + goto out_unref; + dev_priv->fbdev_info = info; + + strcpy(info->fix.id, "nouveaufb"); + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | + FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; + info->fbops = &nouveau_fbcon_ops; + info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - + dev_priv->vm_vram_base; + info->fix.smem_len = size; + + info->screen_base = nvbo_kmap_obj_iovirtual(nouveau_fb->nvbo); + info->screen_size = size; + + drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); + drm_fb_helper_fill_var(info, fb, fb_width, fb_height); + + /* FIXME: we really shouldn't expose mmio space at all */ + info->fix.mmio_start = pci_resource_start(dev->pdev, 1); + info->fix.mmio_len = pci_resource_len(dev->pdev, 1); + + /* Set aperture base/size for vesafb takeover */ +#if defined(__i386__) || defined(__x86_64__) + if (nouveau_fbcon_has_vesafb_or_efifb(dev)) { + /* Some NVIDIA VBIOS' are stupid and decide to put the + * framebuffer in the middle of the PRAMIN BAR for + * whatever reason. We need to know the exact lfb_base + * to get vesafb kicked off, and the only reliable way + * we have left is to find out lfb_base the same way + * vesafb did. + */ + info->aperture_base = screen_info.lfb_base; + info->aperture_size = screen_info.lfb_size; + if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB) + info->aperture_size *= 65536; + } else +#endif + { + info->aperture_base = info->fix.mmio_start; + info->aperture_size = info->fix.mmio_len; + } + + info->pixmap.size = 64*1024; + info->pixmap.buf_align = 8; + info->pixmap.access_align = 32; + info->pixmap.flags = FB_PIXMAP_SYSTEM; + info->pixmap.scan_align = 1; + + fb->fbdev = info; + + par->nouveau_fb = nouveau_fb; + par->dev = dev; + + switch (dev_priv->card_type) { + case NV_50: + nv50_fbcon_accel_init(info); + break; + default: + nv04_fbcon_accel_init(info); + break; + }; + + nouveau_fbcon_zfill(dev); + + /* To allow resizeing without swapping buffers */ + NV_INFO(dev, "allocated %dx%d fb: 0x%lx, bo %p\n", + nouveau_fb->base.width, + nouveau_fb->base.height, + nvbo->bo.offset, nvbo); + + mutex_unlock(&dev->struct_mutex); + return 0; + +out_unref: + mutex_unlock(&dev->struct_mutex); +out: + return ret; +} + +int +nouveau_fbcon_probe(struct drm_device *dev) +{ + NV_DEBUG(dev, "\n"); + + return drm_fb_helper_single_fb_probe(dev, 32, nouveau_fbcon_create); +} + +int +nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb) +{ + struct nouveau_framebuffer *nouveau_fb = nouveau_framebuffer(fb); + struct fb_info *info; + + if (!fb) + return -EINVAL; + + info = fb->fbdev; + if (info) { + struct nouveau_fbcon_par *par = info->par; + + unregister_framebuffer(info); + nouveau_bo_unmap(nouveau_fb->nvbo); + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(nouveau_fb->nvbo->gem); + nouveau_fb->nvbo = NULL; + mutex_unlock(&dev->struct_mutex); + if (par) + drm_fb_helper_free(&par->helper); + framebuffer_release(info); + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h new file mode 100644 index 0000000000000000000000000000000000000000..8531140fedbc7ae2c15a5f4308e19fa680a91c25 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008 Maarten Maathuis. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +#ifndef __NOUVEAU_FBCON_H__ +#define __NOUVEAU_FBCON_H__ + +#include "drm_fb_helper.h" + +struct nouveau_fbcon_par { + struct drm_fb_helper helper; + struct drm_device *dev; + struct nouveau_framebuffer *nouveau_fb; +}; + +int nouveau_fbcon_probe(struct drm_device *dev); +int nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb); +void nouveau_fbcon_restore(void); +void nouveau_fbcon_zfill(struct drm_device *dev); + +int nv04_fbcon_accel_init(struct fb_info *info); +int nv50_fbcon_accel_init(struct fb_info *info); + +#endif /* __NV50_FBCON_H__ */ + diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c new file mode 100644 index 0000000000000000000000000000000000000000..0cff7eb3690a494b14e24bdb882712ca83a63806 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm.h" + +#include "nouveau_drv.h" +#include "nouveau_dma.h" + +#define USE_REFCNT (dev_priv->card_type >= NV_10) + +struct nouveau_fence { + struct nouveau_channel *channel; + struct kref refcount; + struct list_head entry; + + uint32_t sequence; + bool signalled; +}; + +static inline struct nouveau_fence * +nouveau_fence(void *sync_obj) +{ + return (struct nouveau_fence *)sync_obj; +} + +static void +nouveau_fence_del(struct kref *ref) +{ + struct nouveau_fence *fence = + container_of(ref, struct nouveau_fence, refcount); + + kfree(fence); +} + +void +nouveau_fence_update(struct nouveau_channel *chan) +{ + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct list_head *entry, *tmp; + struct nouveau_fence *fence; + uint32_t sequence; + + if (USE_REFCNT) + sequence = nvchan_rd32(chan, 0x48); + else + sequence = chan->fence.last_sequence_irq; + + if (chan->fence.sequence_ack == sequence) + return; + chan->fence.sequence_ack = sequence; + + list_for_each_safe(entry, tmp, &chan->fence.pending) { + fence = list_entry(entry, struct nouveau_fence, entry); + + sequence = fence->sequence; + fence->signalled = true; + list_del(&fence->entry); + kref_put(&fence->refcount, nouveau_fence_del); + + if (sequence == chan->fence.sequence_ack) + break; + } +} + +int +nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence, + bool emit) +{ + struct nouveau_fence *fence; + int ret = 0; + + fence = kzalloc(sizeof(*fence), GFP_KERNEL); + if (!fence) + return -ENOMEM; + kref_init(&fence->refcount); + fence->channel = chan; + + if (emit) + ret = nouveau_fence_emit(fence); + + if (ret) + nouveau_fence_unref((void *)&fence); + *pfence = fence; + return ret; +} + +struct nouveau_channel * +nouveau_fence_channel(struct nouveau_fence *fence) +{ + return fence ? fence->channel : NULL; +} + +int +nouveau_fence_emit(struct nouveau_fence *fence) +{ + struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private; + struct nouveau_channel *chan = fence->channel; + unsigned long flags; + int ret; + + ret = RING_SPACE(chan, 2); + if (ret) + return ret; + + if (unlikely(chan->fence.sequence == chan->fence.sequence_ack - 1)) { + spin_lock_irqsave(&chan->fence.lock, flags); + nouveau_fence_update(chan); + spin_unlock_irqrestore(&chan->fence.lock, flags); + + BUG_ON(chan->fence.sequence == + chan->fence.sequence_ack - 1); + } + + fence->sequence = ++chan->fence.sequence; + + kref_get(&fence->refcount); + spin_lock_irqsave(&chan->fence.lock, flags); + list_add_tail(&fence->entry, &chan->fence.pending); + spin_unlock_irqrestore(&chan->fence.lock, flags); + + BEGIN_RING(chan, NvSubM2MF, USE_REFCNT ? 0x0050 : 0x0150, 1); + OUT_RING(chan, fence->sequence); + FIRE_RING(chan); + + return 0; +} + +void +nouveau_fence_unref(void **sync_obj) +{ + struct nouveau_fence *fence = nouveau_fence(*sync_obj); + + if (fence) + kref_put(&fence->refcount, nouveau_fence_del); + *sync_obj = NULL; +} + +void * +nouveau_fence_ref(void *sync_obj) +{ + struct nouveau_fence *fence = nouveau_fence(sync_obj); + + kref_get(&fence->refcount); + return sync_obj; +} + +bool +nouveau_fence_signalled(void *sync_obj, void *sync_arg) +{ + struct nouveau_fence *fence = nouveau_fence(sync_obj); + struct nouveau_channel *chan = fence->channel; + unsigned long flags; + + if (fence->signalled) + return true; + + spin_lock_irqsave(&chan->fence.lock, flags); + nouveau_fence_update(chan); + spin_unlock_irqrestore(&chan->fence.lock, flags); + return fence->signalled; +} + +int +nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) +{ + unsigned long timeout = jiffies + (3 * DRM_HZ); + int ret = 0; + + __set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); + + while (1) { + if (nouveau_fence_signalled(sync_obj, sync_arg)) + break; + + if (time_after_eq(jiffies, timeout)) { + ret = -EBUSY; + break; + } + + if (lazy) + schedule_timeout(1); + + if (intr && signal_pending(current)) { + ret = -ERESTART; + break; + } + } + + __set_current_state(TASK_RUNNING); + + return ret; +} + +int +nouveau_fence_flush(void *sync_obj, void *sync_arg) +{ + return 0; +} + +void +nouveau_fence_handler(struct drm_device *dev, int channel) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = NULL; + + if (channel >= 0 && channel < dev_priv->engine.fifo.channels) + chan = dev_priv->fifos[channel]; + + if (chan) { + spin_lock_irq(&chan->fence.lock); + nouveau_fence_update(chan); + spin_unlock_irq(&chan->fence.lock); + } +} + +int +nouveau_fence_init(struct nouveau_channel *chan) +{ + INIT_LIST_HEAD(&chan->fence.pending); + spin_lock_init(&chan->fence.lock); + return 0; +} + +void +nouveau_fence_fini(struct nouveau_channel *chan) +{ + struct list_head *entry, *tmp; + struct nouveau_fence *fence; + + list_for_each_safe(entry, tmp, &chan->fence.pending) { + fence = list_entry(entry, struct nouveau_fence, entry); + + fence->signalled = true; + list_del(&fence->entry); + kref_put(&fence->refcount, nouveau_fence_del); + } +} + diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c new file mode 100644 index 0000000000000000000000000000000000000000..11f831f0ddc5373f17eb3fb95a20fdac355baa22 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -0,0 +1,992 @@ +/* + * Copyright (C) 2008 Ben Skeggs. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm.h" + +#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_dma.h" + +#define nouveau_gem_pushbuf_sync(chan) 0 + +int +nouveau_gem_object_new(struct drm_gem_object *gem) +{ + return 0; +} + +void +nouveau_gem_object_del(struct drm_gem_object *gem) +{ + struct nouveau_bo *nvbo = gem->driver_private; + struct ttm_buffer_object *bo = &nvbo->bo; + + if (!nvbo) + return; + nvbo->gem = NULL; + + if (unlikely(nvbo->cpu_filp)) + ttm_bo_synccpu_write_release(bo); + + if (unlikely(nvbo->pin_refcnt)) { + nvbo->pin_refcnt = 1; + nouveau_bo_unpin(nvbo); + } + + ttm_bo_unref(&bo); +} + +int +nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan, + int size, int align, uint32_t flags, uint32_t tile_mode, + uint32_t tile_flags, bool no_vm, bool mappable, + struct nouveau_bo **pnvbo) +{ + struct nouveau_bo *nvbo; + int ret; + + ret = nouveau_bo_new(dev, chan, size, align, flags, tile_mode, + tile_flags, no_vm, mappable, pnvbo); + if (ret) + return ret; + nvbo = *pnvbo; + + nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size); + if (!nvbo->gem) { + nouveau_bo_ref(NULL, pnvbo); + return -ENOMEM; + } + + nvbo->bo.persistant_swap_storage = nvbo->gem->filp; + nvbo->gem->driver_private = nvbo; + return 0; +} + +static int +nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep) +{ + struct nouveau_bo *nvbo = nouveau_gem_object(gem); + + if (nvbo->bo.mem.mem_type == TTM_PL_TT) + rep->domain = NOUVEAU_GEM_DOMAIN_GART; + else + rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; + + rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; + rep->offset = nvbo->bo.offset; + rep->map_handle = nvbo->mappable ? nvbo->bo.addr_space_offset : 0; + rep->tile_mode = nvbo->tile_mode; + rep->tile_flags = nvbo->tile_flags; + return 0; +} + +static bool +nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags) { + switch (tile_flags) { + case 0x0000: + case 0x1800: + case 0x2800: + case 0x4800: + case 0x7000: + case 0x7400: + case 0x7a00: + case 0xe000: + break; + default: + NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags); + return false; + } + + return true; +} + +int +nouveau_gem_ioctl_new(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_gem_new *req = data; + struct nouveau_bo *nvbo = NULL; + struct nouveau_channel *chan = NULL; + uint32_t flags = 0; + int ret = 0; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + + if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) + dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; + + if (req->channel_hint) { + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel_hint, + file_priv, chan); + } + + if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM) + flags |= TTM_PL_FLAG_VRAM; + if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART) + flags |= TTM_PL_FLAG_TT; + if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU) + flags |= TTM_PL_FLAG_SYSTEM; + + if (!nouveau_gem_tile_flags_valid(dev, req->info.tile_flags)) + return -EINVAL; + + ret = nouveau_gem_new(dev, chan, req->info.size, req->align, flags, + req->info.tile_mode, req->info.tile_flags, false, + (req->info.domain & NOUVEAU_GEM_DOMAIN_MAPPABLE), + &nvbo); + if (ret) + return ret; + + ret = nouveau_gem_info(nvbo->gem, &req->info); + if (ret) + goto out; + + ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle); +out: + mutex_lock(&dev->struct_mutex); + drm_gem_object_handle_unreference(nvbo->gem); + mutex_unlock(&dev->struct_mutex); + + if (ret) + drm_gem_object_unreference(nvbo->gem); + return ret; +} + +static int +nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains, + uint32_t write_domains, uint32_t valid_domains) +{ + struct nouveau_bo *nvbo = gem->driver_private; + struct ttm_buffer_object *bo = &nvbo->bo; + uint64_t flags; + + if (!valid_domains || (!read_domains && !write_domains)) + return -EINVAL; + + if (write_domains) { + if ((valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) && + (write_domains & NOUVEAU_GEM_DOMAIN_VRAM)) + flags = TTM_PL_FLAG_VRAM; + else + if ((valid_domains & NOUVEAU_GEM_DOMAIN_GART) && + (write_domains & NOUVEAU_GEM_DOMAIN_GART)) + flags = TTM_PL_FLAG_TT; + else + return -EINVAL; + } else { + if ((valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) && + (read_domains & NOUVEAU_GEM_DOMAIN_VRAM) && + bo->mem.mem_type == TTM_PL_VRAM) + flags = TTM_PL_FLAG_VRAM; + else + if ((valid_domains & NOUVEAU_GEM_DOMAIN_GART) && + (read_domains & NOUVEAU_GEM_DOMAIN_GART) && + bo->mem.mem_type == TTM_PL_TT) + flags = TTM_PL_FLAG_TT; + else + if ((valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) && + (read_domains & NOUVEAU_GEM_DOMAIN_VRAM)) + flags = TTM_PL_FLAG_VRAM; + else + flags = TTM_PL_FLAG_TT; + } + + nouveau_bo_placement_set(nvbo, flags); + return 0; +} + +struct validate_op { + struct nouveau_fence *fence; + struct list_head vram_list; + struct list_head gart_list; + struct list_head both_list; +}; + +static void +validate_fini_list(struct list_head *list, struct nouveau_fence *fence) +{ + struct list_head *entry, *tmp; + struct nouveau_bo *nvbo; + + list_for_each_safe(entry, tmp, list) { + nvbo = list_entry(entry, struct nouveau_bo, entry); + if (likely(fence)) { + struct nouveau_fence *prev_fence; + + spin_lock(&nvbo->bo.lock); + prev_fence = nvbo->bo.sync_obj; + nvbo->bo.sync_obj = nouveau_fence_ref(fence); + spin_unlock(&nvbo->bo.lock); + nouveau_fence_unref((void *)&prev_fence); + } + + list_del(&nvbo->entry); + nvbo->reserved_by = NULL; + ttm_bo_unreserve(&nvbo->bo); + drm_gem_object_unreference(nvbo->gem); + } +} + +static void +validate_fini(struct validate_op *op, bool success) +{ + struct nouveau_fence *fence = op->fence; + + if (unlikely(!success)) + op->fence = NULL; + + validate_fini_list(&op->vram_list, op->fence); + validate_fini_list(&op->gart_list, op->fence); + validate_fini_list(&op->both_list, op->fence); + nouveau_fence_unref((void *)&fence); +} + +static int +validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, + struct drm_nouveau_gem_pushbuf_bo *pbbo, + int nr_buffers, struct validate_op *op) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t sequence; + int trycnt = 0; + int ret, i; + + sequence = atomic_add_return(1, &dev_priv->ttm.validate_sequence); +retry: + if (++trycnt > 100000) { + NV_ERROR(dev, "%s failed and gave up.\n", __func__); + return -EINVAL; + } + + for (i = 0; i < nr_buffers; i++) { + struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[i]; + struct drm_gem_object *gem; + struct nouveau_bo *nvbo; + + gem = drm_gem_object_lookup(dev, file_priv, b->handle); + if (!gem) { + NV_ERROR(dev, "Unknown handle 0x%08x\n", b->handle); + validate_fini(op, NULL); + return -EINVAL; + } + nvbo = gem->driver_private; + + if (nvbo->reserved_by && nvbo->reserved_by == file_priv) { + NV_ERROR(dev, "multiple instances of buffer %d on " + "validation list\n", b->handle); + validate_fini(op, NULL); + return -EINVAL; + } + + ret = ttm_bo_reserve(&nvbo->bo, false, false, true, sequence); + if (ret) { + validate_fini(op, NULL); + if (ret == -EAGAIN) + ret = ttm_bo_wait_unreserved(&nvbo->bo, false); + drm_gem_object_unreference(gem); + if (ret) + return ret; + goto retry; + } + + nvbo->reserved_by = file_priv; + nvbo->pbbo_index = i; + if ((b->valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) && + (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART)) + list_add_tail(&nvbo->entry, &op->both_list); + else + if (b->valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) + list_add_tail(&nvbo->entry, &op->vram_list); + else + if (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART) + list_add_tail(&nvbo->entry, &op->gart_list); + else { + NV_ERROR(dev, "invalid valid domains: 0x%08x\n", + b->valid_domains); + validate_fini(op, NULL); + return -EINVAL; + } + + if (unlikely(atomic_read(&nvbo->bo.cpu_writers) > 0)) { + validate_fini(op, NULL); + + if (nvbo->cpu_filp == file_priv) { + NV_ERROR(dev, "bo %p mapped by process trying " + "to validate it!\n", nvbo); + return -EINVAL; + } + + ret = ttm_bo_wait_cpu(&nvbo->bo, false); + if (ret == -ERESTART) + ret = -EAGAIN; + if (ret) + return ret; + goto retry; + } + } + + return 0; +} + +static int +validate_list(struct nouveau_channel *chan, struct list_head *list, + struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr) +{ + struct drm_nouveau_gem_pushbuf_bo __user *upbbo = + (void __force __user *)(uintptr_t)user_pbbo_ptr; + struct nouveau_bo *nvbo; + int ret, relocs = 0; + + list_for_each_entry(nvbo, list, entry) { + struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; + struct nouveau_fence *prev_fence = nvbo->bo.sync_obj; + + if (prev_fence && nouveau_fence_channel(prev_fence) != chan) { + spin_lock(&nvbo->bo.lock); + ret = ttm_bo_wait(&nvbo->bo, false, false, false); + spin_unlock(&nvbo->bo.lock); + if (unlikely(ret)) + return ret; + } + + ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains, + b->write_domains, + b->valid_domains); + if (unlikely(ret)) + return ret; + + nvbo->channel = chan; + ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, + false, false); + nvbo->channel = NULL; + if (unlikely(ret)) + return ret; + + if (nvbo->bo.offset == b->presumed_offset && + ((nvbo->bo.mem.mem_type == TTM_PL_VRAM && + b->presumed_domain & NOUVEAU_GEM_DOMAIN_VRAM) || + (nvbo->bo.mem.mem_type == TTM_PL_TT && + b->presumed_domain & NOUVEAU_GEM_DOMAIN_GART))) + continue; + + if (nvbo->bo.mem.mem_type == TTM_PL_TT) + b->presumed_domain = NOUVEAU_GEM_DOMAIN_GART; + else + b->presumed_domain = NOUVEAU_GEM_DOMAIN_VRAM; + b->presumed_offset = nvbo->bo.offset; + b->presumed_ok = 0; + relocs++; + + if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index], b, sizeof(*b))) + return -EFAULT; + } + + return relocs; +} + +static int +nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, + struct drm_file *file_priv, + struct drm_nouveau_gem_pushbuf_bo *pbbo, + uint64_t user_buffers, int nr_buffers, + struct validate_op *op, int *apply_relocs) +{ + int ret, relocs = 0; + + INIT_LIST_HEAD(&op->vram_list); + INIT_LIST_HEAD(&op->gart_list); + INIT_LIST_HEAD(&op->both_list); + + ret = nouveau_fence_new(chan, &op->fence, false); + if (ret) + return ret; + + if (nr_buffers == 0) + return 0; + + ret = validate_init(chan, file_priv, pbbo, nr_buffers, op); + if (unlikely(ret)) + return ret; + + ret = validate_list(chan, &op->vram_list, pbbo, user_buffers); + if (unlikely(ret < 0)) { + validate_fini(op, NULL); + return ret; + } + relocs += ret; + + ret = validate_list(chan, &op->gart_list, pbbo, user_buffers); + if (unlikely(ret < 0)) { + validate_fini(op, NULL); + return ret; + } + relocs += ret; + + ret = validate_list(chan, &op->both_list, pbbo, user_buffers); + if (unlikely(ret < 0)) { + validate_fini(op, NULL); + return ret; + } + relocs += ret; + + *apply_relocs = relocs; + return 0; +} + +static inline void * +u_memcpya(uint64_t user, unsigned nmemb, unsigned size) +{ + void *mem; + void __user *userptr = (void __force __user *)(uintptr_t)user; + + mem = kmalloc(nmemb * size, GFP_KERNEL); + if (!mem) + return ERR_PTR(-ENOMEM); + + if (DRM_COPY_FROM_USER(mem, userptr, nmemb * size)) { + kfree(mem); + return ERR_PTR(-EFAULT); + } + + return mem; +} + +static int +nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo, + struct drm_nouveau_gem_pushbuf_bo *bo, + int nr_relocs, uint64_t ptr_relocs, + int nr_dwords, int first_dword, + uint32_t *pushbuf, bool is_iomem) +{ + struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL; + struct drm_device *dev = chan->dev; + int ret = 0, i; + + reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc)); + if (IS_ERR(reloc)) + return PTR_ERR(reloc); + + for (i = 0; i < nr_relocs; i++) { + struct drm_nouveau_gem_pushbuf_reloc *r = &reloc[i]; + struct drm_nouveau_gem_pushbuf_bo *b; + uint32_t data; + + if (r->bo_index >= nr_bo || r->reloc_index < first_dword || + r->reloc_index >= first_dword + nr_dwords) { + NV_ERROR(dev, "Bad relocation %d\n", i); + NV_ERROR(dev, " bo: %d max %d\n", r->bo_index, nr_bo); + NV_ERROR(dev, " id: %d max %d\n", r->reloc_index, nr_dwords); + ret = -EINVAL; + break; + } + + b = &bo[r->bo_index]; + if (b->presumed_ok) + continue; + + if (r->flags & NOUVEAU_GEM_RELOC_LOW) + data = b->presumed_offset + r->data; + else + if (r->flags & NOUVEAU_GEM_RELOC_HIGH) + data = (b->presumed_offset + r->data) >> 32; + else + data = r->data; + + if (r->flags & NOUVEAU_GEM_RELOC_OR) { + if (b->presumed_domain == NOUVEAU_GEM_DOMAIN_GART) + data |= r->tor; + else + data |= r->vor; + } + + if (is_iomem) + iowrite32_native(data, (void __force __iomem *) + &pushbuf[r->reloc_index]); + else + pushbuf[r->reloc_index] = data; + } + + kfree(reloc); + return ret; +} + +int +nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_gem_pushbuf *req = data; + struct drm_nouveau_gem_pushbuf_bo *bo = NULL; + struct nouveau_channel *chan; + struct validate_op op; + uint32_t *pushbuf = NULL; + int ret = 0, do_reloc = 0, i; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan); + + if (req->nr_dwords >= chan->dma.max || + req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS || + req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS) { + NV_ERROR(dev, "Pushbuf config exceeds limits:\n"); + NV_ERROR(dev, " dwords : %d max %d\n", req->nr_dwords, + chan->dma.max - 1); + NV_ERROR(dev, " buffers: %d max %d\n", req->nr_buffers, + NOUVEAU_GEM_MAX_BUFFERS); + NV_ERROR(dev, " relocs : %d max %d\n", req->nr_relocs, + NOUVEAU_GEM_MAX_RELOCS); + return -EINVAL; + } + + pushbuf = u_memcpya(req->dwords, req->nr_dwords, sizeof(uint32_t)); + if (IS_ERR(pushbuf)) + return PTR_ERR(pushbuf); + + bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo)); + if (IS_ERR(bo)) { + kfree(pushbuf); + return PTR_ERR(bo); + } + + mutex_lock(&dev->struct_mutex); + + /* Validate buffer list */ + ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers, + req->nr_buffers, &op, &do_reloc); + if (ret) + goto out; + + /* Apply any relocations that are required */ + if (do_reloc) { + ret = nouveau_gem_pushbuf_reloc_apply(chan, req->nr_buffers, + bo, req->nr_relocs, + req->relocs, + req->nr_dwords, 0, + pushbuf, false); + if (ret) + goto out; + } + + /* Emit push buffer to the hw + */ + ret = RING_SPACE(chan, req->nr_dwords); + if (ret) + goto out; + + OUT_RINGp(chan, pushbuf, req->nr_dwords); + + ret = nouveau_fence_emit(op.fence); + if (ret) { + NV_ERROR(dev, "error fencing pushbuf: %d\n", ret); + WIND_RING(chan); + goto out; + } + + if (nouveau_gem_pushbuf_sync(chan)) { + ret = nouveau_fence_wait(op.fence, NULL, false, false); + if (ret) { + for (i = 0; i < req->nr_dwords; i++) + NV_ERROR(dev, "0x%08x\n", pushbuf[i]); + NV_ERROR(dev, "^^ above push buffer is fail :(\n"); + } + } + +out: + validate_fini(&op, ret == 0); + mutex_unlock(&dev->struct_mutex); + kfree(pushbuf); + kfree(bo); + return ret; +} + +#define PUSHBUF_CAL (dev_priv->card_type >= NV_20) + +int +nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_gem_pushbuf_call *req = data; + struct drm_nouveau_gem_pushbuf_bo *bo = NULL; + struct nouveau_channel *chan; + struct drm_gem_object *gem; + struct nouveau_bo *pbbo; + struct validate_op op; + int i, ret = 0, do_reloc = 0; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan); + + if (unlikely(req->handle == 0)) + goto out_next; + + if (req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS || + req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS) { + NV_ERROR(dev, "Pushbuf config exceeds limits:\n"); + NV_ERROR(dev, " buffers: %d max %d\n", req->nr_buffers, + NOUVEAU_GEM_MAX_BUFFERS); + NV_ERROR(dev, " relocs : %d max %d\n", req->nr_relocs, + NOUVEAU_GEM_MAX_RELOCS); + return -EINVAL; + } + + bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo)); + if (IS_ERR(bo)) + return PTR_ERR(bo); + + mutex_lock(&dev->struct_mutex); + + /* Validate buffer list */ + ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers, + req->nr_buffers, &op, &do_reloc); + if (ret) { + NV_ERROR(dev, "validate: %d\n", ret); + goto out; + } + + /* Validate DMA push buffer */ + gem = drm_gem_object_lookup(dev, file_priv, req->handle); + if (!gem) { + NV_ERROR(dev, "Unknown pb handle 0x%08x\n", req->handle); + ret = -EINVAL; + goto out; + } + pbbo = nouveau_gem_object(gem); + + ret = ttm_bo_reserve(&pbbo->bo, false, false, true, + chan->fence.sequence); + if (ret) { + NV_ERROR(dev, "resv pb: %d\n", ret); + drm_gem_object_unreference(gem); + goto out; + } + + nouveau_bo_placement_set(pbbo, 1 << chan->pushbuf_bo->bo.mem.mem_type); + ret = ttm_bo_validate(&pbbo->bo, &pbbo->placement, false, false); + if (ret) { + NV_ERROR(dev, "validate pb: %d\n", ret); + ttm_bo_unreserve(&pbbo->bo); + drm_gem_object_unreference(gem); + goto out; + } + + list_add_tail(&pbbo->entry, &op.both_list); + + /* If presumed return address doesn't match, we need to map the + * push buffer and fix it.. + */ + if (!PUSHBUF_CAL) { + uint32_t retaddy; + + if (chan->dma.free < 4 + NOUVEAU_DMA_SKIPS) { + ret = nouveau_dma_wait(chan, 4 + NOUVEAU_DMA_SKIPS); + if (ret) { + NV_ERROR(dev, "jmp_space: %d\n", ret); + goto out; + } + } + + retaddy = chan->pushbuf_base + ((chan->dma.cur + 2) << 2); + retaddy |= 0x20000000; + if (retaddy != req->suffix0) { + req->suffix0 = retaddy; + do_reloc = 1; + } + } + + /* Apply any relocations that are required */ + if (do_reloc) { + void *pbvirt; + bool is_iomem; + ret = ttm_bo_kmap(&pbbo->bo, 0, pbbo->bo.mem.num_pages, + &pbbo->kmap); + if (ret) { + NV_ERROR(dev, "kmap pb: %d\n", ret); + goto out; + } + + pbvirt = ttm_kmap_obj_virtual(&pbbo->kmap, &is_iomem); + ret = nouveau_gem_pushbuf_reloc_apply(chan, req->nr_buffers, bo, + req->nr_relocs, + req->relocs, + req->nr_dwords, + req->offset / 4, + pbvirt, is_iomem); + + if (!PUSHBUF_CAL) { + nouveau_bo_wr32(pbbo, + req->offset / 4 + req->nr_dwords - 2, + req->suffix0); + } + + ttm_bo_kunmap(&pbbo->kmap); + if (ret) { + NV_ERROR(dev, "reloc apply: %d\n", ret); + goto out; + } + } + + if (PUSHBUF_CAL) { + ret = RING_SPACE(chan, 2); + if (ret) { + NV_ERROR(dev, "cal_space: %d\n", ret); + goto out; + } + OUT_RING(chan, ((pbbo->bo.mem.mm_node->start << PAGE_SHIFT) + + req->offset) | 2); + OUT_RING(chan, 0); + } else { + ret = RING_SPACE(chan, 2 + NOUVEAU_DMA_SKIPS); + if (ret) { + NV_ERROR(dev, "jmp_space: %d\n", ret); + goto out; + } + OUT_RING(chan, ((pbbo->bo.mem.mm_node->start << PAGE_SHIFT) + + req->offset) | 0x20000000); + OUT_RING(chan, 0); + + /* Space the jumps apart with NOPs. */ + for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) + OUT_RING(chan, 0); + } + + ret = nouveau_fence_emit(op.fence); + if (ret) { + NV_ERROR(dev, "error fencing pushbuf: %d\n", ret); + WIND_RING(chan); + goto out; + } + +out: + validate_fini(&op, ret == 0); + mutex_unlock(&dev->struct_mutex); + kfree(bo); + +out_next: + if (PUSHBUF_CAL) { + req->suffix0 = 0x00020000; + req->suffix1 = 0x00000000; + } else { + req->suffix0 = 0x20000000 | + (chan->pushbuf_base + ((chan->dma.cur + 2) << 2)); + req->suffix1 = 0x00000000; + } + + return ret; +} + +int +nouveau_gem_ioctl_pushbuf_call2(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_gem_pushbuf_call *req = data; + + req->vram_available = dev_priv->fb_aper_free; + req->gart_available = dev_priv->gart_info.aper_free; + + return nouveau_gem_ioctl_pushbuf_call(dev, data, file_priv); +} + +static inline uint32_t +domain_to_ttm(struct nouveau_bo *nvbo, uint32_t domain) +{ + uint32_t flags = 0; + + if (domain & NOUVEAU_GEM_DOMAIN_VRAM) + flags |= TTM_PL_FLAG_VRAM; + if (domain & NOUVEAU_GEM_DOMAIN_GART) + flags |= TTM_PL_FLAG_TT; + + return flags; +} + +int +nouveau_gem_ioctl_pin(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_gem_pin *req = data; + struct drm_gem_object *gem; + struct nouveau_bo *nvbo; + int ret = 0; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + NV_ERROR(dev, "pin only allowed without kernel modesetting\n"); + return -EINVAL; + } + + if (!DRM_SUSER(DRM_CURPROC)) + return -EPERM; + + gem = drm_gem_object_lookup(dev, file_priv, req->handle); + if (!gem) + return -EINVAL; + nvbo = nouveau_gem_object(gem); + + ret = nouveau_bo_pin(nvbo, domain_to_ttm(nvbo, req->domain)); + if (ret) + goto out; + + req->offset = nvbo->bo.offset; + if (nvbo->bo.mem.mem_type == TTM_PL_TT) + req->domain = NOUVEAU_GEM_DOMAIN_GART; + else + req->domain = NOUVEAU_GEM_DOMAIN_VRAM; + +out: + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(gem); + mutex_unlock(&dev->struct_mutex); + + return ret; +} + +int +nouveau_gem_ioctl_unpin(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_gem_pin *req = data; + struct drm_gem_object *gem; + int ret; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + gem = drm_gem_object_lookup(dev, file_priv, req->handle); + if (!gem) + return -EINVAL; + + ret = nouveau_bo_unpin(nouveau_gem_object(gem)); + + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(gem); + mutex_unlock(&dev->struct_mutex); + + return ret; +} + +int +nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_gem_cpu_prep *req = data; + struct drm_gem_object *gem; + struct nouveau_bo *nvbo; + bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT); + int ret = -EINVAL; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + + gem = drm_gem_object_lookup(dev, file_priv, req->handle); + if (!gem) + return ret; + nvbo = nouveau_gem_object(gem); + + if (nvbo->cpu_filp) { + if (nvbo->cpu_filp == file_priv) + goto out; + + ret = ttm_bo_wait_cpu(&nvbo->bo, no_wait); + if (ret == -ERESTART) + ret = -EAGAIN; + if (ret) + goto out; + } + + if (req->flags & NOUVEAU_GEM_CPU_PREP_NOBLOCK) { + ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait); + } else { + ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait); + if (ret == -ERESTART) + ret = -EAGAIN; + else + if (ret == 0) + nvbo->cpu_filp = file_priv; + } + +out: + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(gem); + mutex_unlock(&dev->struct_mutex); + return ret; +} + +int +nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_gem_cpu_prep *req = data; + struct drm_gem_object *gem; + struct nouveau_bo *nvbo; + int ret = -EINVAL; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + + gem = drm_gem_object_lookup(dev, file_priv, req->handle); + if (!gem) + return ret; + nvbo = nouveau_gem_object(gem); + + if (nvbo->cpu_filp != file_priv) + goto out; + nvbo->cpu_filp = NULL; + + ttm_bo_synccpu_write_release(&nvbo->bo); + ret = 0; + +out: + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(gem); + mutex_unlock(&dev->struct_mutex); + return ret; +} + +int +nouveau_gem_ioctl_info(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_gem_info *req = data; + struct drm_gem_object *gem; + int ret; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + + gem = drm_gem_object_lookup(dev, file_priv, req->handle); + if (!gem) + return -EINVAL; + + ret = nouveau_gem_info(gem, req); + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(gem); + mutex_unlock(&dev->struct_mutex); + return ret; +} + diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c new file mode 100644 index 0000000000000000000000000000000000000000..dc46792a5c96b9f10daf90d4ef83b17a5fdc3f2e --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_hw.c @@ -0,0 +1,1080 @@ +/* + * Copyright 2006 Dave Airlie + * Copyright 2007 Maarten Maathuis + * Copyright 2007-2009 Stuart Bennett + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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 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 "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_hw.h" + +#define CHIPSET_NFORCE 0x01a0 +#define CHIPSET_NFORCE2 0x01f0 + +/* + * misc hw access wrappers/control functions + */ + +void +NVWriteVgaSeq(struct drm_device *dev, int head, uint8_t index, uint8_t value) +{ + NVWritePRMVIO(dev, head, NV_PRMVIO_SRX, index); + NVWritePRMVIO(dev, head, NV_PRMVIO_SR, value); +} + +uint8_t +NVReadVgaSeq(struct drm_device *dev, int head, uint8_t index) +{ + NVWritePRMVIO(dev, head, NV_PRMVIO_SRX, index); + return NVReadPRMVIO(dev, head, NV_PRMVIO_SR); +} + +void +NVWriteVgaGr(struct drm_device *dev, int head, uint8_t index, uint8_t value) +{ + NVWritePRMVIO(dev, head, NV_PRMVIO_GRX, index); + NVWritePRMVIO(dev, head, NV_PRMVIO_GX, value); +} + +uint8_t +NVReadVgaGr(struct drm_device *dev, int head, uint8_t index) +{ + NVWritePRMVIO(dev, head, NV_PRMVIO_GRX, index); + return NVReadPRMVIO(dev, head, NV_PRMVIO_GX); +} + +/* CR44 takes values 0 (head A), 3 (head B) and 4 (heads tied) + * it affects only the 8 bit vga io regs, which we access using mmio at + * 0xc{0,2}3c*, 0x60{1,3}3*, and 0x68{1,3}3d* + * in general, the set value of cr44 does not matter: reg access works as + * expected and values can be set for the appropriate head by using a 0x2000 + * offset as required + * however: + * a) pre nv40, the head B range of PRMVIO regs at 0xc23c* was not exposed and + * cr44 must be set to 0 or 3 for accessing values on the correct head + * through the common 0xc03c* addresses + * b) in tied mode (4) head B is programmed to the values set on head A, and + * access using the head B addresses can have strange results, ergo we leave + * tied mode in init once we know to what cr44 should be restored on exit + * + * the owner parameter is slightly abused: + * 0 and 1 are treated as head values and so the set value is (owner * 3) + * other values are treated as literal values to set + */ +void +NVSetOwner(struct drm_device *dev, int owner) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (owner == 1) + owner *= 3; + + if (dev_priv->chipset == 0x11) { + /* This might seem stupid, but the blob does it and + * omitting it often locks the system up. + */ + NVReadVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX); + NVReadVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX); + } + + /* CR44 is always changed on CRTC0 */ + NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_44, owner); + + if (dev_priv->chipset == 0x11) { /* set me harder */ + NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner); + NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner); + } +} + +void +NVBlankScreen(struct drm_device *dev, int head, bool blank) +{ + unsigned char seq1; + + if (nv_two_heads(dev)) + NVSetOwner(dev, head); + + seq1 = NVReadVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX); + + NVVgaSeqReset(dev, head, true); + if (blank) + NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 | 0x20); + else + NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 & ~0x20); + NVVgaSeqReset(dev, head, false); +} + +/* + * PLL setting + */ + +static int +powerctrl_1_shift(int chip_version, int reg) +{ + int shift = -4; + + if (chip_version < 0x17 || chip_version == 0x1a || chip_version == 0x20) + return shift; + + switch (reg) { + case NV_RAMDAC_VPLL2: + shift += 4; + case NV_PRAMDAC_VPLL_COEFF: + shift += 4; + case NV_PRAMDAC_MPLL_COEFF: + shift += 4; + case NV_PRAMDAC_NVPLL_COEFF: + shift += 4; + } + + /* + * the shift for vpll regs is only used for nv3x chips with a single + * stage pll + */ + if (shift > 4 && (chip_version < 0x32 || chip_version == 0x35 || + chip_version == 0x36 || chip_version >= 0x40)) + shift = -4; + + return shift; +} + +static void +setPLL_single(struct drm_device *dev, uint32_t reg, struct nouveau_pll_vals *pv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int chip_version = dev_priv->vbios->chip_version; + uint32_t oldpll = NVReadRAMDAC(dev, 0, reg); + int oldN = (oldpll >> 8) & 0xff, oldM = oldpll & 0xff; + uint32_t pll = (oldpll & 0xfff80000) | pv->log2P << 16 | pv->NM1; + uint32_t saved_powerctrl_1 = 0; + int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg); + + if (oldpll == pll) + return; /* already set */ + + if (shift_powerctrl_1 >= 0) { + saved_powerctrl_1 = nvReadMC(dev, NV_PBUS_POWERCTRL_1); + nvWriteMC(dev, NV_PBUS_POWERCTRL_1, + (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | + 1 << shift_powerctrl_1); + } + + if (oldM && pv->M1 && (oldN / oldM < pv->N1 / pv->M1)) + /* upclock -- write new post divider first */ + NVWriteRAMDAC(dev, 0, reg, pv->log2P << 16 | (oldpll & 0xffff)); + else + /* downclock -- write new NM first */ + NVWriteRAMDAC(dev, 0, reg, (oldpll & 0xffff0000) | pv->NM1); + + if (chip_version < 0x17 && chip_version != 0x11) + /* wait a bit on older chips */ + msleep(64); + NVReadRAMDAC(dev, 0, reg); + + /* then write the other half as well */ + NVWriteRAMDAC(dev, 0, reg, pll); + + if (shift_powerctrl_1 >= 0) + nvWriteMC(dev, NV_PBUS_POWERCTRL_1, saved_powerctrl_1); +} + +static uint32_t +new_ramdac580(uint32_t reg1, bool ss, uint32_t ramdac580) +{ + bool head_a = (reg1 == NV_PRAMDAC_VPLL_COEFF); + + if (ss) /* single stage pll mode */ + ramdac580 |= head_a ? NV_RAMDAC_580_VPLL1_ACTIVE : + NV_RAMDAC_580_VPLL2_ACTIVE; + else + ramdac580 &= head_a ? ~NV_RAMDAC_580_VPLL1_ACTIVE : + ~NV_RAMDAC_580_VPLL2_ACTIVE; + + return ramdac580; +} + +static void +setPLL_double_highregs(struct drm_device *dev, uint32_t reg1, + struct nouveau_pll_vals *pv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int chip_version = dev_priv->vbios->chip_version; + bool nv3035 = chip_version == 0x30 || chip_version == 0x35; + uint32_t reg2 = reg1 + ((reg1 == NV_RAMDAC_VPLL2) ? 0x5c : 0x70); + uint32_t oldpll1 = NVReadRAMDAC(dev, 0, reg1); + uint32_t oldpll2 = !nv3035 ? NVReadRAMDAC(dev, 0, reg2) : 0; + uint32_t pll1 = (oldpll1 & 0xfff80000) | pv->log2P << 16 | pv->NM1; + uint32_t pll2 = (oldpll2 & 0x7fff0000) | 1 << 31 | pv->NM2; + uint32_t oldramdac580 = 0, ramdac580 = 0; + bool single_stage = !pv->NM2 || pv->N2 == pv->M2; /* nv41+ only */ + uint32_t saved_powerctrl_1 = 0, savedc040 = 0; + int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg1); + + /* model specific additions to generic pll1 and pll2 set up above */ + if (nv3035) { + pll1 = (pll1 & 0xfcc7ffff) | (pv->N2 & 0x18) << 21 | + (pv->N2 & 0x7) << 19 | 8 << 4 | (pv->M2 & 7) << 4; + pll2 = 0; + } + if (chip_version > 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) { /* !nv40 */ + oldramdac580 = NVReadRAMDAC(dev, 0, NV_PRAMDAC_580); + ramdac580 = new_ramdac580(reg1, single_stage, oldramdac580); + if (oldramdac580 != ramdac580) + oldpll1 = ~0; /* force mismatch */ + if (single_stage) + /* magic value used by nvidia in single stage mode */ + pll2 |= 0x011f; + } + if (chip_version > 0x70) + /* magic bits set by the blob (but not the bios) on g71-73 */ + pll1 = (pll1 & 0x7fffffff) | (single_stage ? 0x4 : 0xc) << 28; + + if (oldpll1 == pll1 && oldpll2 == pll2) + return; /* already set */ + + if (shift_powerctrl_1 >= 0) { + saved_powerctrl_1 = nvReadMC(dev, NV_PBUS_POWERCTRL_1); + nvWriteMC(dev, NV_PBUS_POWERCTRL_1, + (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | + 1 << shift_powerctrl_1); + } + + if (chip_version >= 0x40) { + int shift_c040 = 14; + + switch (reg1) { + case NV_PRAMDAC_MPLL_COEFF: + shift_c040 += 2; + case NV_PRAMDAC_NVPLL_COEFF: + shift_c040 += 2; + case NV_RAMDAC_VPLL2: + shift_c040 += 2; + case NV_PRAMDAC_VPLL_COEFF: + shift_c040 += 2; + } + + savedc040 = nvReadMC(dev, 0xc040); + if (shift_c040 != 14) + nvWriteMC(dev, 0xc040, savedc040 & ~(3 << shift_c040)); + } + + if (oldramdac580 != ramdac580) + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_580, ramdac580); + + if (!nv3035) + NVWriteRAMDAC(dev, 0, reg2, pll2); + NVWriteRAMDAC(dev, 0, reg1, pll1); + + if (shift_powerctrl_1 >= 0) + nvWriteMC(dev, NV_PBUS_POWERCTRL_1, saved_powerctrl_1); + if (chip_version >= 0x40) + nvWriteMC(dev, 0xc040, savedc040); +} + +static void +setPLL_double_lowregs(struct drm_device *dev, uint32_t NMNMreg, + struct nouveau_pll_vals *pv) +{ + /* When setting PLLs, there is a merry game of disabling and enabling + * various bits of hardware during the process. This function is a + * synthesis of six nv4x traces, nearly each card doing a subtly + * different thing. With luck all the necessary bits for each card are + * combined herein. Without luck it deviates from each card's formula + * so as to not work on any :) + */ + + uint32_t Preg = NMNMreg - 4; + bool mpll = Preg == 0x4020; + uint32_t oldPval = nvReadMC(dev, Preg); + uint32_t NMNM = pv->NM2 << 16 | pv->NM1; + uint32_t Pval = (oldPval & (mpll ? ~(0x11 << 16) : ~(1 << 16))) | + 0xc << 28 | pv->log2P << 16; + uint32_t saved4600 = 0; + /* some cards have different maskc040s */ + uint32_t maskc040 = ~(3 << 14), savedc040; + bool single_stage = !pv->NM2 || pv->N2 == pv->M2; + + if (nvReadMC(dev, NMNMreg) == NMNM && (oldPval & 0xc0070000) == Pval) + return; + + if (Preg == 0x4000) + maskc040 = ~0x333; + if (Preg == 0x4058) + maskc040 = ~(0xc << 24); + + if (mpll) { + struct pll_lims pll_lim; + uint8_t Pval2; + + if (get_pll_limits(dev, Preg, &pll_lim)) + return; + + Pval2 = pv->log2P + pll_lim.log2p_bias; + if (Pval2 > pll_lim.max_log2p) + Pval2 = pll_lim.max_log2p; + Pval |= 1 << 28 | Pval2 << 20; + + saved4600 = nvReadMC(dev, 0x4600); + nvWriteMC(dev, 0x4600, saved4600 | 8 << 28); + } + if (single_stage) + Pval |= mpll ? 1 << 12 : 1 << 8; + + nvWriteMC(dev, Preg, oldPval | 1 << 28); + nvWriteMC(dev, Preg, Pval & ~(4 << 28)); + if (mpll) { + Pval |= 8 << 20; + nvWriteMC(dev, 0x4020, Pval & ~(0xc << 28)); + nvWriteMC(dev, 0x4038, Pval & ~(0xc << 28)); + } + + savedc040 = nvReadMC(dev, 0xc040); + nvWriteMC(dev, 0xc040, savedc040 & maskc040); + + nvWriteMC(dev, NMNMreg, NMNM); + if (NMNMreg == 0x4024) + nvWriteMC(dev, 0x403c, NMNM); + + nvWriteMC(dev, Preg, Pval); + if (mpll) { + Pval &= ~(8 << 20); + nvWriteMC(dev, 0x4020, Pval); + nvWriteMC(dev, 0x4038, Pval); + nvWriteMC(dev, 0x4600, saved4600); + } + + nvWriteMC(dev, 0xc040, savedc040); + + if (mpll) { + nvWriteMC(dev, 0x4020, Pval & ~(1 << 28)); + nvWriteMC(dev, 0x4038, Pval & ~(1 << 28)); + } +} + +void +nouveau_hw_setpll(struct drm_device *dev, uint32_t reg1, + struct nouveau_pll_vals *pv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int cv = dev_priv->vbios->chip_version; + + if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 || + cv >= 0x40) { + if (reg1 > 0x405c) + setPLL_double_highregs(dev, reg1, pv); + else + setPLL_double_lowregs(dev, reg1, pv); + } else + setPLL_single(dev, reg1, pv); +} + +/* + * PLL getting + */ + +static void +nouveau_hw_decode_pll(struct drm_device *dev, uint32_t reg1, uint32_t pll1, + uint32_t pll2, struct nouveau_pll_vals *pllvals) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* to force parsing as single stage (i.e. nv40 vplls) pass pll2 as 0 */ + + /* log2P is & 0x7 as never more than 7, and nv30/35 only uses 3 bits */ + pllvals->log2P = (pll1 >> 16) & 0x7; + pllvals->N2 = pllvals->M2 = 1; + + if (reg1 <= 0x405c) { + pllvals->NM1 = pll2 & 0xffff; + /* single stage NVPLL and VPLLs use 1 << 8, MPLL uses 1 << 12 */ + if (!(pll1 & 0x1100)) + pllvals->NM2 = pll2 >> 16; + } else { + pllvals->NM1 = pll1 & 0xffff; + if (nv_two_reg_pll(dev) && pll2 & NV31_RAMDAC_ENABLE_VCO2) + pllvals->NM2 = pll2 & 0xffff; + else if (dev_priv->chipset == 0x30 || dev_priv->chipset == 0x35) { + pllvals->M1 &= 0xf; /* only 4 bits */ + if (pll1 & NV30_RAMDAC_ENABLE_VCO2) { + pllvals->M2 = (pll1 >> 4) & 0x7; + pllvals->N2 = ((pll1 >> 21) & 0x18) | + ((pll1 >> 19) & 0x7); + } + } + } +} + +int +nouveau_hw_get_pllvals(struct drm_device *dev, enum pll_types plltype, + struct nouveau_pll_vals *pllvals) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + const uint32_t nv04_regs[MAX_PLL_TYPES] = { NV_PRAMDAC_NVPLL_COEFF, + NV_PRAMDAC_MPLL_COEFF, + NV_PRAMDAC_VPLL_COEFF, + NV_RAMDAC_VPLL2 }; + const uint32_t nv40_regs[MAX_PLL_TYPES] = { 0x4000, + 0x4020, + NV_PRAMDAC_VPLL_COEFF, + NV_RAMDAC_VPLL2 }; + uint32_t reg1, pll1, pll2 = 0; + struct pll_lims pll_lim; + int ret; + + if (dev_priv->card_type < NV_40) + reg1 = nv04_regs[plltype]; + else + reg1 = nv40_regs[plltype]; + + pll1 = nvReadMC(dev, reg1); + + if (reg1 <= 0x405c) + pll2 = nvReadMC(dev, reg1 + 4); + else if (nv_two_reg_pll(dev)) { + uint32_t reg2 = reg1 + (reg1 == NV_RAMDAC_VPLL2 ? 0x5c : 0x70); + + pll2 = nvReadMC(dev, reg2); + } + + if (dev_priv->card_type == 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) { + uint32_t ramdac580 = NVReadRAMDAC(dev, 0, NV_PRAMDAC_580); + + /* check whether vpll has been forced into single stage mode */ + if (reg1 == NV_PRAMDAC_VPLL_COEFF) { + if (ramdac580 & NV_RAMDAC_580_VPLL1_ACTIVE) + pll2 = 0; + } else + if (ramdac580 & NV_RAMDAC_580_VPLL2_ACTIVE) + pll2 = 0; + } + + nouveau_hw_decode_pll(dev, reg1, pll1, pll2, pllvals); + + ret = get_pll_limits(dev, plltype, &pll_lim); + if (ret) + return ret; + + pllvals->refclk = pll_lim.refclk; + + return 0; +} + +int +nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pv) +{ + /* Avoid divide by zero if called at an inappropriate time */ + if (!pv->M1 || !pv->M2) + return 0; + + return pv->N1 * pv->N2 * pv->refclk / (pv->M1 * pv->M2) >> pv->log2P; +} + +int +nouveau_hw_get_clock(struct drm_device *dev, enum pll_types plltype) +{ + struct nouveau_pll_vals pllvals; + + if (plltype == MPLL && (dev->pci_device & 0x0ff0) == CHIPSET_NFORCE) { + uint32_t mpllP; + + pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP); + if (!mpllP) + mpllP = 4; + + return 400000 / mpllP; + } else + if (plltype == MPLL && (dev->pci_device & 0xff0) == CHIPSET_NFORCE2) { + uint32_t clock; + + pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock); + return clock; + } + + nouveau_hw_get_pllvals(dev, plltype, &pllvals); + + return nouveau_hw_pllvals_to_clk(&pllvals); +} + +static void +nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) +{ + /* the vpll on an unused head can come up with a random value, way + * beyond the pll limits. for some reason this causes the chip to + * lock up when reading the dac palette regs, so set a valid pll here + * when such a condition detected. only seen on nv11 to date + */ + + struct pll_lims pll_lim; + struct nouveau_pll_vals pv; + uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF; + + if (get_pll_limits(dev, head ? VPLL2 : VPLL1, &pll_lim)) + return; + nouveau_hw_get_pllvals(dev, head ? VPLL2 : VPLL1, &pv); + + if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m && + pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n && + pv.log2P <= pll_lim.max_log2p) + return; + + NV_WARN(dev, "VPLL %d outwith limits, attempting to fix\n", head + 1); + + /* set lowest clock within static limits */ + pv.M1 = pll_lim.vco1.max_m; + pv.N1 = pll_lim.vco1.min_n; + pv.log2P = pll_lim.max_usable_log2p; + nouveau_hw_setpll(dev, pllreg, &pv); +} + +/* + * vga font save/restore + */ + +static void nouveau_vga_font_io(struct drm_device *dev, + void __iomem *iovram, + bool save, unsigned plane) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + unsigned i; + + NVWriteVgaSeq(dev, 0, NV_VIO_SR_PLANE_MASK_INDEX, 1 << plane); + NVWriteVgaGr(dev, 0, NV_VIO_GX_READ_MAP_INDEX, plane); + for (i = 0; i < 16384; i++) { + if (save) { + dev_priv->saved_vga_font[plane][i] = + ioread32_native(iovram + i * 4); + } else { + iowrite32_native(dev_priv->saved_vga_font[plane][i], + iovram + i * 4); + } + } +} + +void +nouveau_hw_save_vga_fonts(struct drm_device *dev, bool save) +{ + uint8_t misc, gr4, gr5, gr6, seq2, seq4; + bool graphicsmode; + unsigned plane; + void __iomem *iovram; + + if (nv_two_heads(dev)) + NVSetOwner(dev, 0); + + NVSetEnablePalette(dev, 0, true); + graphicsmode = NVReadVgaAttr(dev, 0, NV_CIO_AR_MODE_INDEX) & 1; + NVSetEnablePalette(dev, 0, false); + + if (graphicsmode) /* graphics mode => framebuffer => no need to save */ + return; + + NV_INFO(dev, "%sing VGA fonts\n", save ? "Sav" : "Restor"); + + /* map first 64KiB of VRAM, holds VGA fonts etc */ + iovram = ioremap(pci_resource_start(dev->pdev, 1), 65536); + if (!iovram) { + NV_ERROR(dev, "Failed to map VRAM, " + "cannot save/restore VGA fonts.\n"); + return; + } + + if (nv_two_heads(dev)) + NVBlankScreen(dev, 1, true); + NVBlankScreen(dev, 0, true); + + /* save control regs */ + misc = NVReadPRMVIO(dev, 0, NV_PRMVIO_MISC__READ); + seq2 = NVReadVgaSeq(dev, 0, NV_VIO_SR_PLANE_MASK_INDEX); + seq4 = NVReadVgaSeq(dev, 0, NV_VIO_SR_MEM_MODE_INDEX); + gr4 = NVReadVgaGr(dev, 0, NV_VIO_GX_READ_MAP_INDEX); + gr5 = NVReadVgaGr(dev, 0, NV_VIO_GX_MODE_INDEX); + gr6 = NVReadVgaGr(dev, 0, NV_VIO_GX_MISC_INDEX); + + NVWritePRMVIO(dev, 0, NV_PRMVIO_MISC__WRITE, 0x67); + NVWriteVgaSeq(dev, 0, NV_VIO_SR_MEM_MODE_INDEX, 0x6); + NVWriteVgaGr(dev, 0, NV_VIO_GX_MODE_INDEX, 0x0); + NVWriteVgaGr(dev, 0, NV_VIO_GX_MISC_INDEX, 0x5); + + /* store font in planes 0..3 */ + for (plane = 0; plane < 4; plane++) + nouveau_vga_font_io(dev, iovram, save, plane); + + /* restore control regs */ + NVWritePRMVIO(dev, 0, NV_PRMVIO_MISC__WRITE, misc); + NVWriteVgaGr(dev, 0, NV_VIO_GX_READ_MAP_INDEX, gr4); + NVWriteVgaGr(dev, 0, NV_VIO_GX_MODE_INDEX, gr5); + NVWriteVgaGr(dev, 0, NV_VIO_GX_MISC_INDEX, gr6); + NVWriteVgaSeq(dev, 0, NV_VIO_SR_PLANE_MASK_INDEX, seq2); + NVWriteVgaSeq(dev, 0, NV_VIO_SR_MEM_MODE_INDEX, seq4); + + if (nv_two_heads(dev)) + NVBlankScreen(dev, 1, false); + NVBlankScreen(dev, 0, false); + + iounmap(iovram); +} + +/* + * mode state save/load + */ + +static void +rd_cio_state(struct drm_device *dev, int head, + struct nv04_crtc_reg *crtcstate, int index) +{ + crtcstate->CRTC[index] = NVReadVgaCrtc(dev, head, index); +} + +static void +wr_cio_state(struct drm_device *dev, int head, + struct nv04_crtc_reg *crtcstate, int index) +{ + NVWriteVgaCrtc(dev, head, index, crtcstate->CRTC[index]); +} + +static void +nv_save_state_ramdac(struct drm_device *dev, int head, + struct nv04_mode_state *state) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_crtc_reg *regp = &state->crtc_reg[head]; + int i; + + if (dev_priv->card_type >= NV_10) + regp->nv10_cursync = NVReadRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC); + + nouveau_hw_get_pllvals(dev, head ? VPLL2 : VPLL1, ®p->pllvals); + state->pllsel = NVReadRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT); + if (nv_two_heads(dev)) + state->sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK); + if (dev_priv->chipset == 0x11) + regp->dither = NVReadRAMDAC(dev, head, NV_RAMDAC_DITHER_NV11); + + regp->ramdac_gen_ctrl = NVReadRAMDAC(dev, head, NV_PRAMDAC_GENERAL_CONTROL); + + if (nv_gf4_disp_arch(dev)) + regp->ramdac_630 = NVReadRAMDAC(dev, head, NV_PRAMDAC_630); + if (dev_priv->chipset >= 0x30) + regp->ramdac_634 = NVReadRAMDAC(dev, head, NV_PRAMDAC_634); + + regp->tv_setup = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP); + regp->tv_vtotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_VTOTAL); + regp->tv_vskew = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_VSKEW); + regp->tv_vsync_delay = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_VSYNC_DELAY); + regp->tv_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_HTOTAL); + regp->tv_hskew = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_HSKEW); + regp->tv_hsync_delay = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_HSYNC_DELAY); + regp->tv_hsync_delay2 = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_HSYNC_DELAY2); + + for (i = 0; i < 7; i++) { + uint32_t ramdac_reg = NV_PRAMDAC_FP_VDISPLAY_END + (i * 4); + regp->fp_vert_regs[i] = NVReadRAMDAC(dev, head, ramdac_reg); + regp->fp_horiz_regs[i] = NVReadRAMDAC(dev, head, ramdac_reg + 0x20); + } + + if (nv_gf4_disp_arch(dev)) { + regp->dither = NVReadRAMDAC(dev, head, NV_RAMDAC_FP_DITHER); + for (i = 0; i < 3; i++) { + regp->dither_regs[i] = NVReadRAMDAC(dev, head, NV_PRAMDAC_850 + i * 4); + regp->dither_regs[i + 3] = NVReadRAMDAC(dev, head, NV_PRAMDAC_85C + i * 4); + } + } + + regp->fp_control = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL); + regp->fp_debug_0 = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_0); + if (!nv_gf4_disp_arch(dev) && head == 0) { + /* early chips don't allow access to PRAMDAC_TMDS_* without + * the head A FPCLK on (nv11 even locks up) */ + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_FP_DEBUG_0, regp->fp_debug_0 & + ~NV_PRAMDAC_FP_DEBUG_0_PWRDOWN_FPCLK); + } + regp->fp_debug_1 = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_1); + regp->fp_debug_2 = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_2); + + regp->fp_margin_color = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_MARGIN_COLOR); + + if (nv_gf4_disp_arch(dev)) + regp->ramdac_8c0 = NVReadRAMDAC(dev, head, NV_PRAMDAC_8C0); + + if (dev_priv->card_type == NV_40) { + regp->ramdac_a20 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A20); + regp->ramdac_a24 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A24); + regp->ramdac_a34 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A34); + + for (i = 0; i < 38; i++) + regp->ctv_regs[i] = NVReadRAMDAC(dev, head, + NV_PRAMDAC_CTV + 4*i); + } +} + +static void +nv_load_state_ramdac(struct drm_device *dev, int head, + struct nv04_mode_state *state) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_crtc_reg *regp = &state->crtc_reg[head]; + uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF; + int i; + + if (dev_priv->card_type >= NV_10) + NVWriteRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync); + + nouveau_hw_setpll(dev, pllreg, ®p->pllvals); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel); + if (nv_two_heads(dev)) + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, state->sel_clk); + if (dev_priv->chipset == 0x11) + NVWriteRAMDAC(dev, head, NV_RAMDAC_DITHER_NV11, regp->dither); + + NVWriteRAMDAC(dev, head, NV_PRAMDAC_GENERAL_CONTROL, regp->ramdac_gen_ctrl); + + if (nv_gf4_disp_arch(dev)) + NVWriteRAMDAC(dev, head, NV_PRAMDAC_630, regp->ramdac_630); + if (dev_priv->chipset >= 0x30) + NVWriteRAMDAC(dev, head, NV_PRAMDAC_634, regp->ramdac_634); + + NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP, regp->tv_setup); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_VTOTAL, regp->tv_vtotal); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_VSKEW, regp->tv_vskew); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_VSYNC_DELAY, regp->tv_vsync_delay); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_HTOTAL, regp->tv_htotal); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_HSKEW, regp->tv_hskew); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_HSYNC_DELAY, regp->tv_hsync_delay); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_HSYNC_DELAY2, regp->tv_hsync_delay2); + + for (i = 0; i < 7; i++) { + uint32_t ramdac_reg = NV_PRAMDAC_FP_VDISPLAY_END + (i * 4); + + NVWriteRAMDAC(dev, head, ramdac_reg, regp->fp_vert_regs[i]); + NVWriteRAMDAC(dev, head, ramdac_reg + 0x20, regp->fp_horiz_regs[i]); + } + + if (nv_gf4_disp_arch(dev)) { + NVWriteRAMDAC(dev, head, NV_RAMDAC_FP_DITHER, regp->dither); + for (i = 0; i < 3; i++) { + NVWriteRAMDAC(dev, head, NV_PRAMDAC_850 + i * 4, regp->dither_regs[i]); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_85C + i * 4, regp->dither_regs[i + 3]); + } + } + + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL, regp->fp_control); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_0, regp->fp_debug_0); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_1, regp->fp_debug_1); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_2, regp->fp_debug_2); + + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_MARGIN_COLOR, regp->fp_margin_color); + + if (nv_gf4_disp_arch(dev)) + NVWriteRAMDAC(dev, head, NV_PRAMDAC_8C0, regp->ramdac_8c0); + + if (dev_priv->card_type == NV_40) { + NVWriteRAMDAC(dev, head, NV_PRAMDAC_A20, regp->ramdac_a20); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_A24, regp->ramdac_a24); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_A34, regp->ramdac_a34); + + for (i = 0; i < 38; i++) + NVWriteRAMDAC(dev, head, + NV_PRAMDAC_CTV + 4*i, regp->ctv_regs[i]); + } +} + +static void +nv_save_state_vga(struct drm_device *dev, int head, + struct nv04_mode_state *state) +{ + struct nv04_crtc_reg *regp = &state->crtc_reg[head]; + int i; + + regp->MiscOutReg = NVReadPRMVIO(dev, head, NV_PRMVIO_MISC__READ); + + for (i = 0; i < 25; i++) + rd_cio_state(dev, head, regp, i); + + NVSetEnablePalette(dev, head, true); + for (i = 0; i < 21; i++) + regp->Attribute[i] = NVReadVgaAttr(dev, head, i); + NVSetEnablePalette(dev, head, false); + + for (i = 0; i < 9; i++) + regp->Graphics[i] = NVReadVgaGr(dev, head, i); + + for (i = 0; i < 5; i++) + regp->Sequencer[i] = NVReadVgaSeq(dev, head, i); +} + +static void +nv_load_state_vga(struct drm_device *dev, int head, + struct nv04_mode_state *state) +{ + struct nv04_crtc_reg *regp = &state->crtc_reg[head]; + int i; + + NVWritePRMVIO(dev, head, NV_PRMVIO_MISC__WRITE, regp->MiscOutReg); + + for (i = 0; i < 5; i++) + NVWriteVgaSeq(dev, head, i, regp->Sequencer[i]); + + nv_lock_vga_crtc_base(dev, head, false); + for (i = 0; i < 25; i++) + wr_cio_state(dev, head, regp, i); + nv_lock_vga_crtc_base(dev, head, true); + + for (i = 0; i < 9; i++) + NVWriteVgaGr(dev, head, i, regp->Graphics[i]); + + NVSetEnablePalette(dev, head, true); + for (i = 0; i < 21; i++) + NVWriteVgaAttr(dev, head, i, regp->Attribute[i]); + NVSetEnablePalette(dev, head, false); +} + +static void +nv_save_state_ext(struct drm_device *dev, int head, + struct nv04_mode_state *state) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_crtc_reg *regp = &state->crtc_reg[head]; + int i; + + rd_cio_state(dev, head, regp, NV_CIO_CRE_LCD__INDEX); + rd_cio_state(dev, head, regp, NV_CIO_CRE_RPC0_INDEX); + rd_cio_state(dev, head, regp, NV_CIO_CRE_RPC1_INDEX); + rd_cio_state(dev, head, regp, NV_CIO_CRE_LSR_INDEX); + rd_cio_state(dev, head, regp, NV_CIO_CRE_PIXEL_INDEX); + rd_cio_state(dev, head, regp, NV_CIO_CRE_HEB__INDEX); + rd_cio_state(dev, head, regp, NV_CIO_CRE_ENH_INDEX); + + rd_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); + rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); + rd_cio_state(dev, head, regp, NV_CIO_CRE_21); + if (dev_priv->card_type >= NV_30) + rd_cio_state(dev, head, regp, NV_CIO_CRE_47); + rd_cio_state(dev, head, regp, NV_CIO_CRE_49); + rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); + rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); + rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX); + rd_cio_state(dev, head, regp, NV_CIO_CRE_ILACE__INDEX); + + if (dev_priv->card_type >= NV_10) { + regp->crtc_830 = NVReadCRTC(dev, head, NV_PCRTC_830); + regp->crtc_834 = NVReadCRTC(dev, head, NV_PCRTC_834); + + if (dev_priv->card_type >= NV_30) + regp->gpio_ext = NVReadCRTC(dev, head, NV_PCRTC_GPIO_EXT); + + if (dev_priv->card_type == NV_40) + regp->crtc_850 = NVReadCRTC(dev, head, NV_PCRTC_850); + + if (nv_two_heads(dev)) + regp->crtc_eng_ctrl = NVReadCRTC(dev, head, NV_PCRTC_ENGINE_CTRL); + regp->cursor_cfg = NVReadCRTC(dev, head, NV_PCRTC_CURSOR_CONFIG); + } + + regp->crtc_cfg = NVReadCRTC(dev, head, NV_PCRTC_CONFIG); + + rd_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH3__INDEX); + rd_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH4__INDEX); + if (dev_priv->card_type >= NV_10) { + rd_cio_state(dev, head, regp, NV_CIO_CRE_EBR_INDEX); + rd_cio_state(dev, head, regp, NV_CIO_CRE_CSB); + rd_cio_state(dev, head, regp, NV_CIO_CRE_4B); + rd_cio_state(dev, head, regp, NV_CIO_CRE_TVOUT_LATENCY); + } + /* NV11 and NV20 don't have this, they stop at 0x52. */ + if (nv_gf4_disp_arch(dev)) { + rd_cio_state(dev, head, regp, NV_CIO_CRE_53); + rd_cio_state(dev, head, regp, NV_CIO_CRE_54); + + for (i = 0; i < 0x10; i++) + regp->CR58[i] = NVReadVgaCrtc5758(dev, head, i); + rd_cio_state(dev, head, regp, NV_CIO_CRE_59); + rd_cio_state(dev, head, regp, NV_CIO_CRE_5B); + + rd_cio_state(dev, head, regp, NV_CIO_CRE_85); + rd_cio_state(dev, head, regp, NV_CIO_CRE_86); + } + + regp->fb_start = NVReadCRTC(dev, head, NV_PCRTC_START); +} + +static void +nv_load_state_ext(struct drm_device *dev, int head, + struct nv04_mode_state *state) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_crtc_reg *regp = &state->crtc_reg[head]; + uint32_t reg900; + int i; + + if (dev_priv->card_type >= NV_10) { + if (nv_two_heads(dev)) + /* setting ENGINE_CTRL (EC) *must* come before + * CIO_CRE_LCD, as writing CRE_LCD sets bits 16 & 17 in + * EC that should not be overwritten by writing stale EC + */ + NVWriteCRTC(dev, head, NV_PCRTC_ENGINE_CTRL, regp->crtc_eng_ctrl); + + nvWriteVIDEO(dev, NV_PVIDEO_STOP, 1); + nvWriteVIDEO(dev, NV_PVIDEO_INTR_EN, 0); + nvWriteVIDEO(dev, NV_PVIDEO_OFFSET_BUFF(0), 0); + nvWriteVIDEO(dev, NV_PVIDEO_OFFSET_BUFF(1), 0); + nvWriteVIDEO(dev, NV_PVIDEO_LIMIT(0), dev_priv->fb_available_size - 1); + nvWriteVIDEO(dev, NV_PVIDEO_LIMIT(1), dev_priv->fb_available_size - 1); + nvWriteVIDEO(dev, NV_PVIDEO_UVPLANE_LIMIT(0), dev_priv->fb_available_size - 1); + nvWriteVIDEO(dev, NV_PVIDEO_UVPLANE_LIMIT(1), dev_priv->fb_available_size - 1); + nvWriteMC(dev, NV_PBUS_POWERCTRL_2, 0); + + NVWriteCRTC(dev, head, NV_PCRTC_CURSOR_CONFIG, regp->cursor_cfg); + NVWriteCRTC(dev, head, NV_PCRTC_830, regp->crtc_830); + NVWriteCRTC(dev, head, NV_PCRTC_834, regp->crtc_834); + + if (dev_priv->card_type >= NV_30) + NVWriteCRTC(dev, head, NV_PCRTC_GPIO_EXT, regp->gpio_ext); + + if (dev_priv->card_type == NV_40) { + NVWriteCRTC(dev, head, NV_PCRTC_850, regp->crtc_850); + + reg900 = NVReadRAMDAC(dev, head, NV_PRAMDAC_900); + if (regp->crtc_cfg == NV_PCRTC_CONFIG_START_ADDRESS_HSYNC) + NVWriteRAMDAC(dev, head, NV_PRAMDAC_900, reg900 | 0x10000); + else + NVWriteRAMDAC(dev, head, NV_PRAMDAC_900, reg900 & ~0x10000); + } + } + + NVWriteCRTC(dev, head, NV_PCRTC_CONFIG, regp->crtc_cfg); + + wr_cio_state(dev, head, regp, NV_CIO_CRE_RPC0_INDEX); + wr_cio_state(dev, head, regp, NV_CIO_CRE_RPC1_INDEX); + wr_cio_state(dev, head, regp, NV_CIO_CRE_LSR_INDEX); + wr_cio_state(dev, head, regp, NV_CIO_CRE_PIXEL_INDEX); + wr_cio_state(dev, head, regp, NV_CIO_CRE_LCD__INDEX); + wr_cio_state(dev, head, regp, NV_CIO_CRE_HEB__INDEX); + wr_cio_state(dev, head, regp, NV_CIO_CRE_ENH_INDEX); + wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); + wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); + if (dev_priv->card_type >= NV_30) + wr_cio_state(dev, head, regp, NV_CIO_CRE_47); + + wr_cio_state(dev, head, regp, NV_CIO_CRE_49); + wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); + wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); + wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX); + if (dev_priv->card_type == NV_40) + nv_fix_nv40_hw_cursor(dev, head); + wr_cio_state(dev, head, regp, NV_CIO_CRE_ILACE__INDEX); + + wr_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH3__INDEX); + wr_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH4__INDEX); + if (dev_priv->card_type >= NV_10) { + wr_cio_state(dev, head, regp, NV_CIO_CRE_EBR_INDEX); + wr_cio_state(dev, head, regp, NV_CIO_CRE_CSB); + wr_cio_state(dev, head, regp, NV_CIO_CRE_4B); + wr_cio_state(dev, head, regp, NV_CIO_CRE_TVOUT_LATENCY); + } + /* NV11 and NV20 stop at 0x52. */ + if (nv_gf4_disp_arch(dev)) { + if (dev_priv->card_type == NV_10) { + /* Not waiting for vertical retrace before modifying + CRE_53/CRE_54 causes lockups. */ + nouveau_wait_until(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8); + nouveau_wait_until(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0); + } + + wr_cio_state(dev, head, regp, NV_CIO_CRE_53); + wr_cio_state(dev, head, regp, NV_CIO_CRE_54); + + for (i = 0; i < 0x10; i++) + NVWriteVgaCrtc5758(dev, head, i, regp->CR58[i]); + wr_cio_state(dev, head, regp, NV_CIO_CRE_59); + wr_cio_state(dev, head, regp, NV_CIO_CRE_5B); + + wr_cio_state(dev, head, regp, NV_CIO_CRE_85); + wr_cio_state(dev, head, regp, NV_CIO_CRE_86); + } + + NVWriteCRTC(dev, head, NV_PCRTC_START, regp->fb_start); + + /* Setting 1 on this value gives you interrupts for every vblank period. */ + NVWriteCRTC(dev, head, NV_PCRTC_INTR_EN_0, 0); + NVWriteCRTC(dev, head, NV_PCRTC_INTR_0, NV_PCRTC_INTR_0_VBLANK); +} + +static void +nv_save_state_palette(struct drm_device *dev, int head, + struct nv04_mode_state *state) +{ + int head_offset = head * NV_PRMDIO_SIZE, i; + + nv_wr08(dev, NV_PRMDIO_PIXEL_MASK + head_offset, + NV_PRMDIO_PIXEL_MASK_MASK); + nv_wr08(dev, NV_PRMDIO_READ_MODE_ADDRESS + head_offset, 0x0); + + for (i = 0; i < 768; i++) { + state->crtc_reg[head].DAC[i] = nv_rd08(dev, + NV_PRMDIO_PALETTE_DATA + head_offset); + } + + NVSetEnablePalette(dev, head, false); +} + +void +nouveau_hw_load_state_palette(struct drm_device *dev, int head, + struct nv04_mode_state *state) +{ + int head_offset = head * NV_PRMDIO_SIZE, i; + + nv_wr08(dev, NV_PRMDIO_PIXEL_MASK + head_offset, + NV_PRMDIO_PIXEL_MASK_MASK); + nv_wr08(dev, NV_PRMDIO_WRITE_MODE_ADDRESS + head_offset, 0x0); + + for (i = 0; i < 768; i++) { + nv_wr08(dev, NV_PRMDIO_PALETTE_DATA + head_offset, + state->crtc_reg[head].DAC[i]); + } + + NVSetEnablePalette(dev, head, false); +} + +void nouveau_hw_save_state(struct drm_device *dev, int head, + struct nv04_mode_state *state) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->chipset == 0x11) + /* NB: no attempt is made to restore the bad pll later on */ + nouveau_hw_fix_bad_vpll(dev, head); + nv_save_state_ramdac(dev, head, state); + nv_save_state_vga(dev, head, state); + nv_save_state_palette(dev, head, state); + nv_save_state_ext(dev, head, state); +} + +void nouveau_hw_load_state(struct drm_device *dev, int head, + struct nv04_mode_state *state) +{ + NVVgaProtect(dev, head, true); + nv_load_state_ramdac(dev, head, state); + nv_load_state_ext(dev, head, state); + nouveau_hw_load_state_palette(dev, head, state); + nv_load_state_vga(dev, head, state); + NVVgaProtect(dev, head, false); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.h b/drivers/gpu/drm/nouveau/nouveau_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..869130f83602f6cf027a2329eb7be49eafb88ccc --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_hw.h @@ -0,0 +1,455 @@ +/* + * Copyright 2008 Stuart Bennett + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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 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. + */ + +#ifndef __NOUVEAU_HW_H__ +#define __NOUVEAU_HW_H__ + +#include "drmP.h" +#include "nouveau_drv.h" + +#define MASK(field) ( \ + (0xffffffff >> (31 - ((1 ? field) - (0 ? field)))) << (0 ? field)) + +#define XLATE(src, srclowbit, outfield) ( \ + (((src) >> (srclowbit)) << (0 ? outfield)) & MASK(outfield)) + +void NVWriteVgaSeq(struct drm_device *, int head, uint8_t index, uint8_t value); +uint8_t NVReadVgaSeq(struct drm_device *, int head, uint8_t index); +void NVWriteVgaGr(struct drm_device *, int head, uint8_t index, uint8_t value); +uint8_t NVReadVgaGr(struct drm_device *, int head, uint8_t index); +void NVSetOwner(struct drm_device *, int owner); +void NVBlankScreen(struct drm_device *, int head, bool blank); +void nouveau_hw_setpll(struct drm_device *, uint32_t reg1, + struct nouveau_pll_vals *pv); +int nouveau_hw_get_pllvals(struct drm_device *, enum pll_types plltype, + struct nouveau_pll_vals *pllvals); +int nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pllvals); +int nouveau_hw_get_clock(struct drm_device *, enum pll_types plltype); +void nouveau_hw_save_vga_fonts(struct drm_device *, bool save); +void nouveau_hw_save_state(struct drm_device *, int head, + struct nv04_mode_state *state); +void nouveau_hw_load_state(struct drm_device *, int head, + struct nv04_mode_state *state); +void nouveau_hw_load_state_palette(struct drm_device *, int head, + struct nv04_mode_state *state); + +/* nouveau_calc.c */ +extern void nouveau_calc_arb(struct drm_device *, int vclk, int bpp, + int *burst, int *lwm); +extern int nouveau_calc_pll_mnp(struct drm_device *, struct pll_lims *pll_lim, + int clk, struct nouveau_pll_vals *pv); + +static inline uint32_t +nvReadMC(struct drm_device *dev, uint32_t reg) +{ + uint32_t val = nv_rd32(dev, reg); + NV_REG_DEBUG(MC, dev, "reg %08x val %08x\n", reg, val); + return val; +} + +static inline void +nvWriteMC(struct drm_device *dev, uint32_t reg, uint32_t val) +{ + NV_REG_DEBUG(MC, dev, "reg %08x val %08x\n", reg, val); + nv_wr32(dev, reg, val); +} + +static inline uint32_t +nvReadVIDEO(struct drm_device *dev, uint32_t reg) +{ + uint32_t val = nv_rd32(dev, reg); + NV_REG_DEBUG(VIDEO, dev, "reg %08x val %08x\n", reg, val); + return val; +} + +static inline void +nvWriteVIDEO(struct drm_device *dev, uint32_t reg, uint32_t val) +{ + NV_REG_DEBUG(VIDEO, dev, "reg %08x val %08x\n", reg, val); + nv_wr32(dev, reg, val); +} + +static inline uint32_t +nvReadFB(struct drm_device *dev, uint32_t reg) +{ + uint32_t val = nv_rd32(dev, reg); + NV_REG_DEBUG(FB, dev, "reg %08x val %08x\n", reg, val); + return val; +} + +static inline void +nvWriteFB(struct drm_device *dev, uint32_t reg, uint32_t val) +{ + NV_REG_DEBUG(FB, dev, "reg %08x val %08x\n", reg, val); + nv_wr32(dev, reg, val); +} + +static inline uint32_t +nvReadEXTDEV(struct drm_device *dev, uint32_t reg) +{ + uint32_t val = nv_rd32(dev, reg); + NV_REG_DEBUG(EXTDEV, dev, "reg %08x val %08x\n", reg, val); + return val; +} + +static inline void +nvWriteEXTDEV(struct drm_device *dev, uint32_t reg, uint32_t val) +{ + NV_REG_DEBUG(EXTDEV, dev, "reg %08x val %08x\n", reg, val); + nv_wr32(dev, reg, val); +} + +static inline uint32_t NVReadCRTC(struct drm_device *dev, + int head, uint32_t reg) +{ + uint32_t val; + if (head) + reg += NV_PCRTC0_SIZE; + val = nv_rd32(dev, reg); + NV_REG_DEBUG(CRTC, dev, "head %d reg %08x val %08x\n", head, reg, val); + return val; +} + +static inline void NVWriteCRTC(struct drm_device *dev, + int head, uint32_t reg, uint32_t val) +{ + if (head) + reg += NV_PCRTC0_SIZE; + NV_REG_DEBUG(CRTC, dev, "head %d reg %08x val %08x\n", head, reg, val); + nv_wr32(dev, reg, val); +} + +static inline uint32_t NVReadRAMDAC(struct drm_device *dev, + int head, uint32_t reg) +{ + uint32_t val; + if (head) + reg += NV_PRAMDAC0_SIZE; + val = nv_rd32(dev, reg); + NV_REG_DEBUG(RAMDAC, dev, "head %d reg %08x val %08x\n", + head, reg, val); + return val; +} + +static inline void NVWriteRAMDAC(struct drm_device *dev, + int head, uint32_t reg, uint32_t val) +{ + if (head) + reg += NV_PRAMDAC0_SIZE; + NV_REG_DEBUG(RAMDAC, dev, "head %d reg %08x val %08x\n", + head, reg, val); + nv_wr32(dev, reg, val); +} + +static inline uint8_t nv_read_tmds(struct drm_device *dev, + int or, int dl, uint8_t address) +{ + int ramdac = (or & OUTPUT_C) >> 2; + + NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8, + NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | address); + return NVReadRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8); +} + +static inline void nv_write_tmds(struct drm_device *dev, + int or, int dl, uint8_t address, + uint8_t data) +{ + int ramdac = (or & OUTPUT_C) >> 2; + + NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8, data); + NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8, address); +} + +static inline void NVWriteVgaCrtc(struct drm_device *dev, + int head, uint8_t index, uint8_t value) +{ + NV_REG_DEBUG(VGACRTC, dev, "head %d index 0x%02x data 0x%02x\n", + head, index, value); + nv_wr08(dev, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); + nv_wr08(dev, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value); +} + +static inline uint8_t NVReadVgaCrtc(struct drm_device *dev, + int head, uint8_t index) +{ + uint8_t val; + nv_wr08(dev, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); + val = nv_rd08(dev, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE); + NV_REG_DEBUG(VGACRTC, dev, "head %d index 0x%02x data 0x%02x\n", + head, index, val); + return val; +} + +/* CR57 and CR58 are a fun pair of regs. CR57 provides an index (0-0xf) for CR58 + * I suspect they in fact do nothing, but are merely a way to carry useful + * per-head variables around + * + * Known uses: + * CR57 CR58 + * 0x00 index to the appropriate dcb entry (or 7f for inactive) + * 0x02 dcb entry's "or" value (or 00 for inactive) + * 0x03 bit0 set for dual link (LVDS, possibly elsewhere too) + * 0x08 or 0x09 pxclk in MHz + * 0x0f laptop panel info - low nibble for PEXTDEV_BOOT_0 strap + * high nibble for xlat strap value + */ + +static inline void +NVWriteVgaCrtc5758(struct drm_device *dev, int head, uint8_t index, uint8_t value) +{ + NVWriteVgaCrtc(dev, head, NV_CIO_CRE_57, index); + NVWriteVgaCrtc(dev, head, NV_CIO_CRE_58, value); +} + +static inline uint8_t NVReadVgaCrtc5758(struct drm_device *dev, int head, uint8_t index) +{ + NVWriteVgaCrtc(dev, head, NV_CIO_CRE_57, index); + return NVReadVgaCrtc(dev, head, NV_CIO_CRE_58); +} + +static inline uint8_t NVReadPRMVIO(struct drm_device *dev, + int head, uint32_t reg) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint8_t val; + + /* Only NV4x have two pvio ranges; other twoHeads cards MUST call + * NVSetOwner for the relevant head to be programmed */ + if (head && dev_priv->card_type == NV_40) + reg += NV_PRMVIO_SIZE; + + val = nv_rd08(dev, reg); + NV_REG_DEBUG(RMVIO, dev, "head %d reg %08x val %02x\n", head, reg, val); + return val; +} + +static inline void NVWritePRMVIO(struct drm_device *dev, + int head, uint32_t reg, uint8_t value) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* Only NV4x have two pvio ranges; other twoHeads cards MUST call + * NVSetOwner for the relevant head to be programmed */ + if (head && dev_priv->card_type == NV_40) + reg += NV_PRMVIO_SIZE; + + NV_REG_DEBUG(RMVIO, dev, "head %d reg %08x val %02x\n", + head, reg, value); + nv_wr08(dev, reg, value); +} + +static inline void NVSetEnablePalette(struct drm_device *dev, int head, bool enable) +{ + nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); + nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20); +} + +static inline bool NVGetEnablePalette(struct drm_device *dev, int head) +{ + nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); + return !(nv_rd08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20); +} + +static inline void NVWriteVgaAttr(struct drm_device *dev, + int head, uint8_t index, uint8_t value) +{ + if (NVGetEnablePalette(dev, head)) + index &= ~0x20; + else + index |= 0x20; + + nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); + NV_REG_DEBUG(VGAATTR, dev, "head %d index 0x%02x data 0x%02x\n", + head, index, value); + nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); + nv_wr08(dev, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value); +} + +static inline uint8_t NVReadVgaAttr(struct drm_device *dev, + int head, uint8_t index) +{ + uint8_t val; + if (NVGetEnablePalette(dev, head)) + index &= ~0x20; + else + index |= 0x20; + + nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); + nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); + val = nv_rd08(dev, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE); + NV_REG_DEBUG(VGAATTR, dev, "head %d index 0x%02x data 0x%02x\n", + head, index, val); + return val; +} + +static inline void NVVgaSeqReset(struct drm_device *dev, int head, bool start) +{ + NVWriteVgaSeq(dev, head, NV_VIO_SR_RESET_INDEX, start ? 0x1 : 0x3); +} + +static inline void NVVgaProtect(struct drm_device *dev, int head, bool protect) +{ + uint8_t seq1 = NVReadVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX); + + if (protect) { + NVVgaSeqReset(dev, head, true); + NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 | 0x20); + } else { + /* Reenable sequencer, then turn on screen */ + NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 & ~0x20); /* reenable display */ + NVVgaSeqReset(dev, head, false); + } + NVSetEnablePalette(dev, head, protect); +} + +static inline bool +nv_heads_tied(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->chipset == 0x11) + return !!(nvReadMC(dev, NV_PBUS_DEBUG_1) & (1 << 28)); + + return NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44) & 0x4; +} + +/* makes cr0-7 on the specified head read-only */ +static inline bool +nv_lock_vga_crtc_base(struct drm_device *dev, int head, bool lock) +{ + uint8_t cr11 = NVReadVgaCrtc(dev, head, NV_CIO_CR_VRE_INDEX); + bool waslocked = cr11 & 0x80; + + if (lock) + cr11 |= 0x80; + else + cr11 &= ~0x80; + NVWriteVgaCrtc(dev, head, NV_CIO_CR_VRE_INDEX, cr11); + + return waslocked; +} + +static inline void +nv_lock_vga_crtc_shadow(struct drm_device *dev, int head, int lock) +{ + /* shadow lock: connects 0x60?3d? regs to "real" 0x3d? regs + * bit7: unlocks HDT, HBS, HBE, HRS, HRE, HEB + * bit6: seems to have some effect on CR09 (double scan, VBS_9) + * bit5: unlocks HDE + * bit4: unlocks VDE + * bit3: unlocks VDT, OVL, VRS, ?VRE?, VBS, VBE, LSR, EBR + * bit2: same as bit 1 of 0x60?804 + * bit0: same as bit 0 of 0x60?804 + */ + + uint8_t cr21 = lock; + + if (lock < 0) + /* 0xfa is generic "unlock all" mask */ + cr21 = NVReadVgaCrtc(dev, head, NV_CIO_CRE_21) | 0xfa; + + NVWriteVgaCrtc(dev, head, NV_CIO_CRE_21, cr21); +} + +/* renders the extended crtc regs (cr19+) on all crtcs impervious: + * immutable and unreadable + */ +static inline bool +NVLockVgaCrtcs(struct drm_device *dev, bool lock) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + bool waslocked = !NVReadVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX); + + NVWriteVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX, + lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE); + /* NV11 has independently lockable extended crtcs, except when tied */ + if (dev_priv->chipset == 0x11 && !nv_heads_tied(dev)) + NVWriteVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX, + lock ? NV_CIO_SR_LOCK_VALUE : + NV_CIO_SR_UNLOCK_RW_VALUE); + + return waslocked; +} + +/* nv04 cursor max dimensions of 32x32 (A1R5G5B5) */ +#define NV04_CURSOR_SIZE 32 +/* limit nv10 cursors to 64x64 (ARGB8) (we could go to 64x255) */ +#define NV10_CURSOR_SIZE 64 + +static inline int nv_cursor_width(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + return dev_priv->card_type >= NV_10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE; +} + +static inline void +nv_fix_nv40_hw_cursor(struct drm_device *dev, int head) +{ + /* on some nv40 (such as the "true" (in the NV_PFB_BOOT_0 sense) nv40, + * the gf6800gt) a hardware bug requires a write to PRAMDAC_CURSOR_POS + * for changes to the CRTC CURCTL regs to take effect, whether changing + * the pixmap location, or just showing/hiding the cursor + */ + uint32_t curpos = NVReadRAMDAC(dev, head, NV_PRAMDAC_CU_START_POS); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_CU_START_POS, curpos); +} + +static inline void +nv_show_cursor(struct drm_device *dev, int head, bool show) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint8_t *curctl1 = + &dev_priv->mode_reg.crtc_reg[head].CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX]; + + if (show) + *curctl1 |= MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE); + else + *curctl1 &= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE); + NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, *curctl1); + + if (dev_priv->card_type == NV_40) + nv_fix_nv40_hw_cursor(dev, head); +} + +static inline uint32_t +nv_pitch_align(struct drm_device *dev, uint32_t width, int bpp) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int mask; + + if (bpp == 15) + bpp = 16; + if (bpp == 24) + bpp = 8; + + /* Alignment requirements taken from the Haiku driver */ + if (dev_priv->card_type == NV_04) + mask = 128 / bpp - 1; + else + mask = 512 / bpp - 1; + + return (width + mask) & ~mask; +} + +#endif /* __NOUVEAU_HW_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..70e994d281223ef9c69a563d14959c8959851bad --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c @@ -0,0 +1,269 @@ +/* + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Authors: Ben Skeggs + */ + +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_i2c.h" +#include "nouveau_hw.h" + +static void +nv04_i2c_setscl(void *data, int state) +{ + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + uint8_t val; + + val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xd0) | (state ? 0x20 : 0); + NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01); +} + +static void +nv04_i2c_setsda(void *data, int state) +{ + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + uint8_t val; + + val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xe0) | (state ? 0x10 : 0); + NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01); +} + +static int +nv04_i2c_getscl(void *data) +{ + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + + return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 4); +} + +static int +nv04_i2c_getsda(void *data) +{ + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + + return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 8); +} + +static void +nv4e_i2c_setscl(void *data, int state) +{ + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + uint8_t val; + + val = (nv_rd32(dev, i2c->wr) & 0xd0) | (state ? 0x20 : 0); + nv_wr32(dev, i2c->wr, val | 0x01); +} + +static void +nv4e_i2c_setsda(void *data, int state) +{ + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + uint8_t val; + + val = (nv_rd32(dev, i2c->wr) & 0xe0) | (state ? 0x10 : 0); + nv_wr32(dev, i2c->wr, val | 0x01); +} + +static int +nv4e_i2c_getscl(void *data) +{ + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + + return !!((nv_rd32(dev, i2c->rd) >> 16) & 4); +} + +static int +nv4e_i2c_getsda(void *data) +{ + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + + return !!((nv_rd32(dev, i2c->rd) >> 16) & 8); +} + +static int +nv50_i2c_getscl(void *data) +{ + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + + return !!(nv_rd32(dev, i2c->rd) & 1); +} + + +static int +nv50_i2c_getsda(void *data) +{ + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + + return !!(nv_rd32(dev, i2c->rd) & 2); +} + +static void +nv50_i2c_setscl(void *data, int state) +{ + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + + nv_wr32(dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); +} + +static void +nv50_i2c_setsda(void *data, int state) +{ + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + + nv_wr32(dev, i2c->wr, + (nv_rd32(dev, i2c->rd) & 1) | 4 | (state ? 2 : 0)); + i2c->data = state; +} + +static const uint32_t nv50_i2c_port[] = { + 0x00e138, 0x00e150, 0x00e168, 0x00e180, + 0x00e254, 0x00e274, 0x00e764, 0x00e780, + 0x00e79c, 0x00e7b8 +}; +#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) + +int +nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_i2c_chan *i2c; + int ret; + + if (entry->chan) + return -EEXIST; + + if (dev_priv->card_type == NV_50 && entry->read >= NV50_I2C_PORTS) { + NV_ERROR(dev, "unknown i2c port %d\n", entry->read); + return -EINVAL; + } + + i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); + if (i2c == NULL) + return -ENOMEM; + + switch (entry->port_type) { + case 0: + i2c->algo.bit.setsda = nv04_i2c_setsda; + i2c->algo.bit.setscl = nv04_i2c_setscl; + i2c->algo.bit.getsda = nv04_i2c_getsda; + i2c->algo.bit.getscl = nv04_i2c_getscl; + i2c->rd = entry->read; + i2c->wr = entry->write; + break; + case 4: + i2c->algo.bit.setsda = nv4e_i2c_setsda; + i2c->algo.bit.setscl = nv4e_i2c_setscl; + i2c->algo.bit.getsda = nv4e_i2c_getsda; + i2c->algo.bit.getscl = nv4e_i2c_getscl; + i2c->rd = 0x600800 + entry->read; + i2c->wr = 0x600800 + entry->write; + break; + case 5: + i2c->algo.bit.setsda = nv50_i2c_setsda; + i2c->algo.bit.setscl = nv50_i2c_setscl; + i2c->algo.bit.getsda = nv50_i2c_getsda; + i2c->algo.bit.getscl = nv50_i2c_getscl; + i2c->rd = nv50_i2c_port[entry->read]; + i2c->wr = i2c->rd; + break; + case 6: + i2c->rd = entry->read; + i2c->wr = entry->write; + break; + default: + NV_ERROR(dev, "DCB I2C port type %d unknown\n", + entry->port_type); + kfree(i2c); + return -EINVAL; + } + + snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), + "nouveau-%s-%d", pci_name(dev->pdev), index); + i2c->adapter.owner = THIS_MODULE; + i2c->adapter.dev.parent = &dev->pdev->dev; + i2c->dev = dev; + i2c_set_adapdata(&i2c->adapter, i2c); + + if (entry->port_type < 6) { + i2c->adapter.algo_data = &i2c->algo.bit; + i2c->algo.bit.udelay = 40; + i2c->algo.bit.timeout = usecs_to_jiffies(5000); + i2c->algo.bit.data = i2c; + ret = i2c_bit_add_bus(&i2c->adapter); + } else { + i2c->adapter.algo_data = &i2c->algo.dp; + i2c->algo.dp.running = false; + i2c->algo.dp.address = 0; + i2c->algo.dp.aux_ch = nouveau_dp_i2c_aux_ch; + ret = i2c_dp_aux_add_bus(&i2c->adapter); + } + + if (ret) { + NV_ERROR(dev, "Failed to register i2c %d\n", index); + kfree(i2c); + return ret; + } + + entry->chan = i2c; + return 0; +} + +void +nouveau_i2c_fini(struct drm_device *dev, struct dcb_i2c_entry *entry) +{ + if (!entry->chan) + return; + + i2c_del_adapter(&entry->chan->adapter); + kfree(entry->chan); + entry->chan = NULL; +} + +struct nouveau_i2c_chan * +nouveau_i2c_find(struct drm_device *dev, int index) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + + if (index > DCB_MAX_NUM_I2C_ENTRIES) + return NULL; + + if (!bios->bdcb.dcb.i2c[index].chan) { + if (nouveau_i2c_init(dev, &bios->bdcb.dcb.i2c[index], index)) + return NULL; + } + + return bios->bdcb.dcb.i2c[index].chan; +} + diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h new file mode 100644 index 0000000000000000000000000000000000000000..c8eaf7a9fcbbad17b7bea504d0613f2e6c75de9e --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h @@ -0,0 +1,52 @@ +/* + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + */ + +#ifndef __NOUVEAU_I2C_H__ +#define __NOUVEAU_I2C_H__ + +#include +#include +#include +#include "drm_dp_helper.h" + +struct dcb_i2c_entry; + +struct nouveau_i2c_chan { + struct i2c_adapter adapter; + struct drm_device *dev; + union { + struct i2c_algo_bit_data bit; + struct i2c_algo_dp_aux_data dp; + } algo; + unsigned rd; + unsigned wr; + unsigned data; +}; + +int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index); +void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *); +struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index); + +int nouveau_dp_i2c_aux_ch(struct i2c_adapter *, int mode, uint8_t write_byte, + uint8_t *read_byte); + +#endif /* __NOUVEAU_I2C_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_ioc32.c b/drivers/gpu/drm/nouveau/nouveau_ioc32.c new file mode 100644 index 0000000000000000000000000000000000000000..a2c30f4611ba52b3ad6a0856fcf5e5b83d4cf629 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_ioc32.c @@ -0,0 +1,72 @@ +/** + * \file mga_ioc32.c + * + * 32-bit ioctl compatibility routines for the MGA DRM. + * + * \author Dave Airlie with code from patches by Egbert Eich + * + * + * Copyright (C) Paul Mackerras 2005 + * Copyright (C) Egbert Eich 2003,2004 + * Copyright (C) Dave Airlie 2005 + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 AUTHOR 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 + +#include "drmP.h" +#include "drm.h" + +#include "nouveau_drv.h" + +/** + * Called whenever a 32-bit process running under a 64-bit kernel + * performs an ioctl on /dev/dri/card. + * + * \param filp file pointer. + * \param cmd command. + * \param arg user argument. + * \return zero on success or negative number on failure. + */ +long nouveau_compat_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + unsigned int nr = DRM_IOCTL_NR(cmd); + drm_ioctl_compat_t *fn = NULL; + int ret; + + if (nr < DRM_COMMAND_BASE) + return drm_compat_ioctl(filp, cmd, arg); + +#if 0 + if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls)) + fn = nouveau_compat_ioctls[nr - DRM_COMMAND_BASE]; +#endif + lock_kernel(); /* XXX for now */ + if (fn != NULL) + ret = (*fn)(filp, cmd, arg); + else + ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + unlock_kernel(); + + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c new file mode 100644 index 0000000000000000000000000000000000000000..370c72c968d186ce779306ae20552ef4a6cab715 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -0,0 +1,702 @@ +/* + * Copyright (C) 2006 Ben Skeggs. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +/* + * Authors: + * Ben Skeggs + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drm.h" +#include "nouveau_drv.h" +#include "nouveau_reg.h" +#include + +/* needed for hotplug irq */ +#include "nouveau_connector.h" +#include "nv50_display.h" + +void +nouveau_irq_preinstall(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* Master disable */ + nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); + + if (dev_priv->card_type == NV_50) { + INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); + INIT_LIST_HEAD(&dev_priv->vbl_waiting); + } +} + +int +nouveau_irq_postinstall(struct drm_device *dev) +{ + /* Master enable */ + nv_wr32(dev, NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE); + return 0; +} + +void +nouveau_irq_uninstall(struct drm_device *dev) +{ + /* Master disable */ + nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); +} + +static int +nouveau_call_method(struct nouveau_channel *chan, int class, int mthd, int data) +{ + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct nouveau_pgraph_object_method *grm; + struct nouveau_pgraph_object_class *grc; + + grc = dev_priv->engine.graph.grclass; + while (grc->id) { + if (grc->id == class) + break; + grc++; + } + + if (grc->id != class || !grc->methods) + return -ENOENT; + + grm = grc->methods; + while (grm->id) { + if (grm->id == mthd) + return grm->exec(chan, class, mthd, data); + grm++; + } + + return -ENOENT; +} + +static bool +nouveau_fifo_swmthd(struct nouveau_channel *chan, uint32_t addr, uint32_t data) +{ + struct drm_device *dev = chan->dev; + const int subc = (addr >> 13) & 0x7; + const int mthd = addr & 0x1ffc; + + if (mthd == 0x0000) { + struct nouveau_gpuobj_ref *ref = NULL; + + if (nouveau_gpuobj_ref_find(chan, data, &ref)) + return false; + + if (ref->gpuobj->engine != NVOBJ_ENGINE_SW) + return false; + + chan->sw_subchannel[subc] = ref->gpuobj->class; + nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_rd32(dev, + NV04_PFIFO_CACHE1_ENGINE) & ~(0xf << subc * 4)); + return true; + } + + /* hw object */ + if (nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE) & (1 << (subc*4))) + return false; + + if (nouveau_call_method(chan, chan->sw_subchannel[subc], mthd, data)) + return false; + + return true; +} + +static void +nouveau_fifo_irq_handler(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->engine; + uint32_t status, reassign; + int cnt = 0; + + reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1; + while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) { + struct nouveau_channel *chan = NULL; + uint32_t chid, get; + + nv_wr32(dev, NV03_PFIFO_CACHES, 0); + + chid = engine->fifo.channel_id(dev); + if (chid >= 0 && chid < engine->fifo.channels) + chan = dev_priv->fifos[chid]; + get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET); + + if (status & NV_PFIFO_INTR_CACHE_ERROR) { + uint32_t mthd, data; + int ptr; + + /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before + * wrapping on my G80 chips, but CACHE1 isn't big + * enough for this much data.. Tests show that it + * wraps around to the start at GET=0x800.. No clue + * as to why.. + */ + ptr = (get & 0x7ff) >> 2; + + if (dev_priv->card_type < NV_40) { + mthd = nv_rd32(dev, + NV04_PFIFO_CACHE1_METHOD(ptr)); + data = nv_rd32(dev, + NV04_PFIFO_CACHE1_DATA(ptr)); + } else { + mthd = nv_rd32(dev, + NV40_PFIFO_CACHE1_METHOD(ptr)); + data = nv_rd32(dev, + NV40_PFIFO_CACHE1_DATA(ptr)); + } + + if (!chan || !nouveau_fifo_swmthd(chan, mthd, data)) { + NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d " + "Mthd 0x%04x Data 0x%08x\n", + chid, (mthd >> 13) & 7, mthd & 0x1ffc, + data); + } + + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0); + nv_wr32(dev, NV03_PFIFO_INTR_0, + NV_PFIFO_INTR_CACHE_ERROR); + + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, + nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) & ~1); + nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, + nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) | 1); + nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); + + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, + nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + + status &= ~NV_PFIFO_INTR_CACHE_ERROR; + } + + if (status & NV_PFIFO_INTR_DMA_PUSHER) { + NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d\n", chid); + + status &= ~NV_PFIFO_INTR_DMA_PUSHER; + nv_wr32(dev, NV03_PFIFO_INTR_0, + NV_PFIFO_INTR_DMA_PUSHER); + + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000); + if (nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT) != get) + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, + get + 4); + } + + if (status) { + NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", + status, chid); + nv_wr32(dev, NV03_PFIFO_INTR_0, status); + status = 0; + } + + nv_wr32(dev, NV03_PFIFO_CACHES, reassign); + } + + if (status) { + NV_INFO(dev, "PFIFO still angry after %d spins, halt\n", cnt); + nv_wr32(dev, 0x2140, 0); + nv_wr32(dev, 0x140, 0); + } + + nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING); +} + +struct nouveau_bitfield_names { + uint32_t mask; + const char *name; +}; + +static struct nouveau_bitfield_names nstatus_names[] = +{ + { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, + { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, + { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, + { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" } +}; + +static struct nouveau_bitfield_names nstatus_names_nv10[] = +{ + { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, + { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, + { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, + { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" } +}; + +static struct nouveau_bitfield_names nsource_names[] = +{ + { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" }, + { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, + { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" }, + { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" }, + { NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" }, + { NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" }, + { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" }, + { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" }, + { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" }, + { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" }, + { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" }, + { NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" }, + { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" }, + { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" }, + { NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" }, + { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" }, + { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" }, + { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" }, + { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" }, +}; + +static void +nouveau_print_bitfield_names_(uint32_t value, + const struct nouveau_bitfield_names *namelist, + const int namelist_len) +{ + /* + * Caller must have already printed the KERN_* log level for us. + * Also the caller is responsible for adding the newline. + */ + int i; + for (i = 0; i < namelist_len; ++i) { + uint32_t mask = namelist[i].mask; + if (value & mask) { + printk(" %s", namelist[i].name); + value &= ~mask; + } + } + if (value) + printk(" (unknown bits 0x%08x)", value); +} +#define nouveau_print_bitfield_names(val, namelist) \ + nouveau_print_bitfield_names_((val), (namelist), ARRAY_SIZE(namelist)) + + +static int +nouveau_graph_chid_from_grctx(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t inst; + int i; + + if (dev_priv->card_type < NV_40) + return dev_priv->engine.fifo.channels; + else + if (dev_priv->card_type < NV_50) { + inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 4; + + for (i = 0; i < dev_priv->engine.fifo.channels; i++) { + struct nouveau_channel *chan = dev_priv->fifos[i]; + + if (!chan || !chan->ramin_grctx) + continue; + + if (inst == chan->ramin_grctx->instance) + break; + } + } else { + inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 12; + + for (i = 0; i < dev_priv->engine.fifo.channels; i++) { + struct nouveau_channel *chan = dev_priv->fifos[i]; + + if (!chan || !chan->ramin) + continue; + + if (inst == chan->ramin->instance) + break; + } + } + + + return i; +} + +static int +nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->engine; + int channel; + + if (dev_priv->card_type < NV_10) + channel = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0xf; + else + if (dev_priv->card_type < NV_40) + channel = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; + else + channel = nouveau_graph_chid_from_grctx(dev); + + if (channel >= engine->fifo.channels || !dev_priv->fifos[channel]) { + NV_ERROR(dev, "AIII, invalid/inactive channel id %d\n", channel); + return -EINVAL; + } + + *channel_ret = channel; + return 0; +} + +struct nouveau_pgraph_trap { + int channel; + int class; + int subc, mthd, size; + uint32_t data, data2; + uint32_t nsource, nstatus; +}; + +static void +nouveau_graph_trap_info(struct drm_device *dev, + struct nouveau_pgraph_trap *trap) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t address; + + trap->nsource = trap->nstatus = 0; + if (dev_priv->card_type < NV_50) { + trap->nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); + trap->nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); + } + + if (nouveau_graph_trapped_channel(dev, &trap->channel)) + trap->channel = -1; + address = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); + + trap->mthd = address & 0x1FFC; + trap->data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); + if (dev_priv->card_type < NV_10) { + trap->subc = (address >> 13) & 0x7; + } else { + trap->subc = (address >> 16) & 0x7; + trap->data2 = nv_rd32(dev, NV10_PGRAPH_TRAPPED_DATA_HIGH); + } + + if (dev_priv->card_type < NV_10) + trap->class = nv_rd32(dev, 0x400180 + trap->subc*4) & 0xFF; + else if (dev_priv->card_type < NV_40) + trap->class = nv_rd32(dev, 0x400160 + trap->subc*4) & 0xFFF; + else if (dev_priv->card_type < NV_50) + trap->class = nv_rd32(dev, 0x400160 + trap->subc*4) & 0xFFFF; + else + trap->class = nv_rd32(dev, 0x400814); +} + +static void +nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id, + struct nouveau_pgraph_trap *trap) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t nsource = trap->nsource, nstatus = trap->nstatus; + + NV_INFO(dev, "%s - nSource:", id); + nouveau_print_bitfield_names(nsource, nsource_names); + printk(", nStatus:"); + if (dev_priv->card_type < NV_10) + nouveau_print_bitfield_names(nstatus, nstatus_names); + else + nouveau_print_bitfield_names(nstatus, nstatus_names_nv10); + printk("\n"); + + NV_INFO(dev, "%s - Ch %d/%d Class 0x%04x Mthd 0x%04x " + "Data 0x%08x:0x%08x\n", + id, trap->channel, trap->subc, + trap->class, trap->mthd, + trap->data2, trap->data); +} + +static int +nouveau_pgraph_intr_swmthd(struct drm_device *dev, + struct nouveau_pgraph_trap *trap) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (trap->channel < 0 || + trap->channel >= dev_priv->engine.fifo.channels || + !dev_priv->fifos[trap->channel]) + return -ENODEV; + + return nouveau_call_method(dev_priv->fifos[trap->channel], + trap->class, trap->mthd, trap->data); +} + +static inline void +nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource) +{ + struct nouveau_pgraph_trap trap; + int unhandled = 0; + + nouveau_graph_trap_info(dev, &trap); + + if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { + if (nouveau_pgraph_intr_swmthd(dev, &trap)) + unhandled = 1; + } else { + unhandled = 1; + } + + if (unhandled) + nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap); +} + +static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); + +static int nouveau_ratelimit(void) +{ + return __ratelimit(&nouveau_ratelimit_state); +} + + +static inline void +nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource) +{ + struct nouveau_pgraph_trap trap; + int unhandled = 0; + + nouveau_graph_trap_info(dev, &trap); + trap.nsource = nsource; + + if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { + if (nouveau_pgraph_intr_swmthd(dev, &trap)) + unhandled = 1; + } else { + unhandled = 1; + } + + if (unhandled && nouveau_ratelimit()) + nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR", &trap); +} + +static inline void +nouveau_pgraph_intr_context_switch(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->engine; + uint32_t chid; + + chid = engine->fifo.channel_id(dev); + NV_DEBUG(dev, "PGRAPH context switch interrupt channel %x\n", chid); + + switch (dev_priv->card_type) { + case NV_04: + nv04_graph_context_switch(dev); + break; + case NV_10: + nv10_graph_context_switch(dev); + break; + default: + NV_ERROR(dev, "Context switch not implemented\n"); + break; + } +} + +static void +nouveau_pgraph_irq_handler(struct drm_device *dev) +{ + uint32_t status; + + while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) { + uint32_t nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); + + if (status & NV_PGRAPH_INTR_NOTIFY) { + nouveau_pgraph_intr_notify(dev, nsource); + + status &= ~NV_PGRAPH_INTR_NOTIFY; + nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY); + } + + if (status & NV_PGRAPH_INTR_ERROR) { + nouveau_pgraph_intr_error(dev, nsource); + + status &= ~NV_PGRAPH_INTR_ERROR; + nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR); + } + + if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) { + nouveau_pgraph_intr_context_switch(dev); + + status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + nv_wr32(dev, NV03_PGRAPH_INTR, + NV_PGRAPH_INTR_CONTEXT_SWITCH); + } + + if (status) { + NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n", status); + nv_wr32(dev, NV03_PGRAPH_INTR, status); + } + + if ((nv_rd32(dev, NV04_PGRAPH_FIFO) & (1 << 0)) == 0) + nv_wr32(dev, NV04_PGRAPH_FIFO, 1); + } + + nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); +} + +static void +nv50_pgraph_irq_handler(struct drm_device *dev) +{ + uint32_t status, nsource; + + status = nv_rd32(dev, NV03_PGRAPH_INTR); + nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); + + if (status & 0x00000001) { + nouveau_pgraph_intr_notify(dev, nsource); + status &= ~0x00000001; + nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000001); + } + + if (status & 0x00000010) { + nouveau_pgraph_intr_error(dev, nsource | + NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD); + + status &= ~0x00000010; + nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000010); + } + + if (status & 0x00001000) { + nv_wr32(dev, 0x400500, 0x00000000); + nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); + nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev, + NV40_PGRAPH_INTR_EN) & ~NV_PGRAPH_INTR_CONTEXT_SWITCH); + nv_wr32(dev, 0x400500, 0x00010001); + + nv50_graph_context_switch(dev); + + status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + } + + if (status & 0x00100000) { + nouveau_pgraph_intr_error(dev, nsource | + NV03_PGRAPH_NSOURCE_DATA_ERROR); + + status &= ~0x00100000; + nv_wr32(dev, NV03_PGRAPH_INTR, 0x00100000); + } + + if (status & 0x00200000) { + int r; + + nouveau_pgraph_intr_error(dev, nsource | + NV03_PGRAPH_NSOURCE_PROTECTION_ERROR); + + NV_ERROR(dev, "magic set 1:\n"); + for (r = 0x408900; r <= 0x408910; r += 4) + NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r)); + nv_wr32(dev, 0x408900, nv_rd32(dev, 0x408904) | 0xc0000000); + for (r = 0x408e08; r <= 0x408e24; r += 4) + NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r)); + nv_wr32(dev, 0x408e08, nv_rd32(dev, 0x408e08) | 0xc0000000); + + NV_ERROR(dev, "magic set 2:\n"); + for (r = 0x409900; r <= 0x409910; r += 4) + NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r)); + nv_wr32(dev, 0x409900, nv_rd32(dev, 0x409904) | 0xc0000000); + for (r = 0x409e08; r <= 0x409e24; r += 4) + NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r)); + nv_wr32(dev, 0x409e08, nv_rd32(dev, 0x409e08) | 0xc0000000); + + status &= ~0x00200000; + nv_wr32(dev, NV03_PGRAPH_NSOURCE, nsource); + nv_wr32(dev, NV03_PGRAPH_INTR, 0x00200000); + } + + if (status) { + NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n", status); + nv_wr32(dev, NV03_PGRAPH_INTR, status); + } + + { + const int isb = (1 << 16) | (1 << 0); + + if ((nv_rd32(dev, 0x400500) & isb) != isb) + nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | isb); + } + + nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); +} + +static void +nouveau_crtc_irq_handler(struct drm_device *dev, int crtc) +{ + if (crtc & 1) + nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK); + + if (crtc & 2) + nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK); +} + +irqreturn_t +nouveau_irq_handler(DRM_IRQ_ARGS) +{ + struct drm_device *dev = (struct drm_device *)arg; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t status, fbdev_flags = 0; + + status = nv_rd32(dev, NV03_PMC_INTR_0); + if (!status) + return IRQ_NONE; + + if (dev_priv->fbdev_info) { + fbdev_flags = dev_priv->fbdev_info->flags; + dev_priv->fbdev_info->flags |= FBINFO_HWACCEL_DISABLED; + } + + if (status & NV_PMC_INTR_0_PFIFO_PENDING) { + nouveau_fifo_irq_handler(dev); + status &= ~NV_PMC_INTR_0_PFIFO_PENDING; + } + + if (status & NV_PMC_INTR_0_PGRAPH_PENDING) { + if (dev_priv->card_type >= NV_50) + nv50_pgraph_irq_handler(dev); + else + nouveau_pgraph_irq_handler(dev); + + status &= ~NV_PMC_INTR_0_PGRAPH_PENDING; + } + + if (status & NV_PMC_INTR_0_CRTCn_PENDING) { + nouveau_crtc_irq_handler(dev, (status>>24)&3); + status &= ~NV_PMC_INTR_0_CRTCn_PENDING; + } + + if (status & (NV_PMC_INTR_0_NV50_DISPLAY_PENDING | + NV_PMC_INTR_0_NV50_I2C_PENDING)) { + nv50_display_irq_handler(dev); + status &= ~(NV_PMC_INTR_0_NV50_DISPLAY_PENDING | + NV_PMC_INTR_0_NV50_I2C_PENDING); + } + + if (status) + NV_ERROR(dev, "Unhandled PMC INTR status bits 0x%08x\n", status); + + if (dev_priv->fbdev_info) + dev_priv->fbdev_info->flags = fbdev_flags; + + return IRQ_HANDLED; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c new file mode 100644 index 0000000000000000000000000000000000000000..02755712ed3d3aa03641478f52c0ef65ab7b9a29 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -0,0 +1,568 @@ +/* + * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + * Copyright 2005 Stephane Marchesin + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 AND/OR THEIR SUPPLIERS 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. + * + * Authors: + * Keith Whitwell + */ + + +#include "drmP.h" +#include "drm.h" +#include "drm_sarea.h" +#include "nouveau_drv.h" + +static struct mem_block * +split_block(struct mem_block *p, uint64_t start, uint64_t size, + struct drm_file *file_priv) +{ + /* Maybe cut off the start of an existing block */ + if (start > p->start) { + struct mem_block *newblock = + kmalloc(sizeof(*newblock), GFP_KERNEL); + if (!newblock) + goto out; + newblock->start = start; + newblock->size = p->size - (start - p->start); + newblock->file_priv = NULL; + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + p->size -= newblock->size; + p = newblock; + } + + /* Maybe cut off the end of an existing block */ + if (size < p->size) { + struct mem_block *newblock = + kmalloc(sizeof(*newblock), GFP_KERNEL); + if (!newblock) + goto out; + newblock->start = start + size; + newblock->size = p->size - size; + newblock->file_priv = NULL; + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + p->size = size; + } + +out: + /* Our block is in the middle */ + p->file_priv = file_priv; + return p; +} + +struct mem_block * +nouveau_mem_alloc_block(struct mem_block *heap, uint64_t size, + int align2, struct drm_file *file_priv, int tail) +{ + struct mem_block *p; + uint64_t mask = (1 << align2) - 1; + + if (!heap) + return NULL; + + if (tail) { + list_for_each_prev(p, heap) { + uint64_t start = ((p->start + p->size) - size) & ~mask; + + if (p->file_priv == NULL && start >= p->start && + start + size <= p->start + p->size) + return split_block(p, start, size, file_priv); + } + } else { + list_for_each(p, heap) { + uint64_t start = (p->start + mask) & ~mask; + + if (p->file_priv == NULL && + start + size <= p->start + p->size) + return split_block(p, start, size, file_priv); + } + } + + return NULL; +} + +void nouveau_mem_free_block(struct mem_block *p) +{ + p->file_priv = NULL; + + /* Assumes a single contiguous range. Needs a special file_priv in + * 'heap' to stop it being subsumed. + */ + if (p->next->file_priv == NULL) { + struct mem_block *q = p->next; + p->size += q->size; + p->next = q->next; + p->next->prev = p; + kfree(q); + } + + if (p->prev->file_priv == NULL) { + struct mem_block *q = p->prev; + q->size += p->size; + q->next = p->next; + q->next->prev = q; + kfree(p); + } +} + +/* Initialize. How to check for an uninitialized heap? + */ +int nouveau_mem_init_heap(struct mem_block **heap, uint64_t start, + uint64_t size) +{ + struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL); + + if (!blocks) + return -ENOMEM; + + *heap = kmalloc(sizeof(**heap), GFP_KERNEL); + if (!*heap) { + kfree(blocks); + return -ENOMEM; + } + + blocks->start = start; + blocks->size = size; + blocks->file_priv = NULL; + blocks->next = blocks->prev = *heap; + + memset(*heap, 0, sizeof(**heap)); + (*heap)->file_priv = (struct drm_file *) -1; + (*heap)->next = (*heap)->prev = blocks; + return 0; +} + +/* + * Free all blocks associated with the releasing file_priv + */ +void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap) +{ + struct mem_block *p; + + if (!heap || !heap->next) + return; + + list_for_each(p, heap) { + if (p->file_priv == file_priv) + p->file_priv = NULL; + } + + /* Assumes a single contiguous range. Needs a special file_priv in + * 'heap' to stop it being subsumed. + */ + list_for_each(p, heap) { + while ((p->file_priv == NULL) && + (p->next->file_priv == NULL) && + (p->next != heap)) { + struct mem_block *q = p->next; + p->size += q->size; + p->next = q->next; + p->next->prev = p; + kfree(q); + } + } +} + +/* + * NV50 VM helpers + */ +int +nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, + uint32_t flags, uint64_t phys) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj **pgt; + unsigned psz, pfl, pages; + + if (virt >= dev_priv->vm_gart_base && + (virt + size) < (dev_priv->vm_gart_base + dev_priv->vm_gart_size)) { + psz = 12; + pgt = &dev_priv->gart_info.sg_ctxdma; + pfl = 0x21; + virt -= dev_priv->vm_gart_base; + } else + if (virt >= dev_priv->vm_vram_base && + (virt + size) < (dev_priv->vm_vram_base + dev_priv->vm_vram_size)) { + psz = 16; + pgt = dev_priv->vm_vram_pt; + pfl = 0x01; + virt -= dev_priv->vm_vram_base; + } else { + NV_ERROR(dev, "Invalid address: 0x%16llx-0x%16llx\n", + virt, virt + size - 1); + return -EINVAL; + } + + pages = size >> psz; + + dev_priv->engine.instmem.prepare_access(dev, true); + if (flags & 0x80000000) { + while (pages--) { + struct nouveau_gpuobj *pt = pgt[virt >> 29]; + unsigned pte = ((virt & 0x1fffffffULL) >> psz) << 1; + + nv_wo32(dev, pt, pte++, 0x00000000); + nv_wo32(dev, pt, pte++, 0x00000000); + + virt += (1 << psz); + } + } else { + while (pages--) { + struct nouveau_gpuobj *pt = pgt[virt >> 29]; + unsigned pte = ((virt & 0x1fffffffULL) >> psz) << 1; + unsigned offset_h = upper_32_bits(phys) & 0xff; + unsigned offset_l = lower_32_bits(phys); + + nv_wo32(dev, pt, pte++, offset_l | pfl); + nv_wo32(dev, pt, pte++, offset_h | flags); + + phys += (1 << psz); + virt += (1 << psz); + } + } + dev_priv->engine.instmem.finish_access(dev); + + nv_wr32(dev, 0x100c80, 0x00050001); + if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { + NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); + NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); + return -EBUSY; + } + + nv_wr32(dev, 0x100c80, 0x00000001); + if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { + NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); + NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); + return -EBUSY; + } + + return 0; +} + +void +nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) +{ + nv50_mem_vm_bind_linear(dev, virt, size, 0x80000000, 0); +} + +/* + * Cleanup everything + */ +void nouveau_mem_takedown(struct mem_block **heap) +{ + struct mem_block *p; + + if (!*heap) + return; + + for (p = (*heap)->next; p != *heap;) { + struct mem_block *q = p; + p = p->next; + kfree(q); + } + + kfree(*heap); + *heap = NULL; +} + +void nouveau_mem_close(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->ttm.bdev.man[TTM_PL_PRIV0].has_type) + ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_PRIV0); + ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); + + ttm_bo_device_release(&dev_priv->ttm.bdev); + + nouveau_ttm_global_release(dev_priv); + + if (drm_core_has_AGP(dev) && dev->agp && + drm_core_check_feature(dev, DRIVER_MODESET)) { + struct drm_agp_mem *entry, *tempe; + + /* Remove AGP resources, but leave dev->agp + intact until drv_cleanup is called. */ + list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) { + if (entry->bound) + drm_unbind_agp(entry->memory); + drm_free_agp(entry->memory, entry->pages); + kfree(entry); + } + INIT_LIST_HEAD(&dev->agp->memory); + + if (dev->agp->acquired) + drm_agp_release(dev); + + dev->agp->acquired = 0; + dev->agp->enabled = 0; + } + + if (dev_priv->fb_mtrr) { + drm_mtrr_del(dev_priv->fb_mtrr, drm_get_resource_start(dev, 1), + drm_get_resource_len(dev, 1), DRM_MTRR_WC); + dev_priv->fb_mtrr = 0; + } +} + +/*XXX won't work on BSD because of pci_read_config_dword */ +static uint32_t +nouveau_mem_fb_amount_igp(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct pci_dev *bridge; + uint32_t mem; + + bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); + if (!bridge) { + NV_ERROR(dev, "no bridge device\n"); + return 0; + } + + if (dev_priv->flags&NV_NFORCE) { + pci_read_config_dword(bridge, 0x7C, &mem); + return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024; + } else + if (dev_priv->flags&NV_NFORCE2) { + pci_read_config_dword(bridge, 0x84, &mem); + return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024; + } + + NV_ERROR(dev, "impossible!\n"); + return 0; +} + +/* returns the amount of FB ram in bytes */ +uint64_t nouveau_mem_fb_amount(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t boot0; + + switch (dev_priv->card_type) { + case NV_04: + boot0 = nv_rd32(dev, NV03_BOOT_0); + if (boot0 & 0x00000100) + return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024; + + switch (boot0 & NV03_BOOT_0_RAM_AMOUNT) { + case NV04_BOOT_0_RAM_AMOUNT_32MB: + return 32 * 1024 * 1024; + case NV04_BOOT_0_RAM_AMOUNT_16MB: + return 16 * 1024 * 1024; + case NV04_BOOT_0_RAM_AMOUNT_8MB: + return 8 * 1024 * 1024; + case NV04_BOOT_0_RAM_AMOUNT_4MB: + return 4 * 1024 * 1024; + } + break; + case NV_10: + case NV_20: + case NV_30: + case NV_40: + case NV_50: + default: + if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) { + return nouveau_mem_fb_amount_igp(dev); + } else { + uint64_t mem; + mem = (nv_rd32(dev, NV04_FIFO_DATA) & + NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK) >> + NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT; + return mem * 1024 * 1024; + } + break; + } + + NV_ERROR(dev, + "Unable to detect video ram size. Please report your setup to " + DRIVER_EMAIL "\n"); + return 0; +} + +static void nouveau_mem_reset_agp(struct drm_device *dev) +{ + uint32_t saved_pci_nv_1, saved_pci_nv_19, pmc_enable; + + saved_pci_nv_1 = nv_rd32(dev, NV04_PBUS_PCI_NV_1); + saved_pci_nv_19 = nv_rd32(dev, NV04_PBUS_PCI_NV_19); + + /* clear busmaster bit */ + nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~0x4); + /* clear SBA and AGP bits */ + nv_wr32(dev, NV04_PBUS_PCI_NV_19, saved_pci_nv_19 & 0xfffff0ff); + + /* power cycle pgraph, if enabled */ + pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE); + if (pmc_enable & NV_PMC_ENABLE_PGRAPH) { + nv_wr32(dev, NV03_PMC_ENABLE, + pmc_enable & ~NV_PMC_ENABLE_PGRAPH); + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | + NV_PMC_ENABLE_PGRAPH); + } + + /* and restore (gives effect of resetting AGP) */ + nv_wr32(dev, NV04_PBUS_PCI_NV_19, saved_pci_nv_19); + nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1); +} + +int +nouveau_mem_init_agp(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_agp_info info; + struct drm_agp_mode mode; + int ret; + + if (nouveau_noagp) + return 0; + + nouveau_mem_reset_agp(dev); + + if (!dev->agp->acquired) { + ret = drm_agp_acquire(dev); + if (ret) { + NV_ERROR(dev, "Unable to acquire AGP: %d\n", ret); + return ret; + } + } + + ret = drm_agp_info(dev, &info); + if (ret) { + NV_ERROR(dev, "Unable to get AGP info: %d\n", ret); + return ret; + } + + /* see agp.h for the AGPSTAT_* modes available */ + mode.mode = info.mode; + ret = drm_agp_enable(dev, mode); + if (ret) { + NV_ERROR(dev, "Unable to enable AGP: %d\n", ret); + return ret; + } + + dev_priv->gart_info.type = NOUVEAU_GART_AGP; + dev_priv->gart_info.aper_base = info.aperture_base; + dev_priv->gart_info.aper_size = info.aperture_size; + return 0; +} + +int +nouveau_mem_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; + int ret, dma_bits = 32; + + dev_priv->fb_phys = drm_get_resource_start(dev, 1); + dev_priv->gart_info.type = NOUVEAU_GART_NONE; + + if (dev_priv->card_type >= NV_50 && + pci_dma_supported(dev->pdev, DMA_BIT_MASK(40))) + dma_bits = 40; + + ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); + if (ret) { + NV_ERROR(dev, "Error setting DMA mask: %d\n", ret); + return ret; + } + + ret = nouveau_ttm_global_init(dev_priv); + if (ret) + return ret; + + ret = ttm_bo_device_init(&dev_priv->ttm.bdev, + dev_priv->ttm.bo_global_ref.ref.object, + &nouveau_bo_driver, DRM_FILE_PAGE_OFFSET, + dma_bits <= 32 ? true : false); + if (ret) { + NV_ERROR(dev, "Error initialising bo driver: %d\n", ret); + return ret; + } + + INIT_LIST_HEAD(&dev_priv->ttm.bo_list); + spin_lock_init(&dev_priv->ttm.bo_list_lock); + + dev_priv->fb_available_size = nouveau_mem_fb_amount(dev); + + dev_priv->fb_mappable_pages = dev_priv->fb_available_size; + if (dev_priv->fb_mappable_pages > drm_get_resource_len(dev, 1)) + dev_priv->fb_mappable_pages = drm_get_resource_len(dev, 1); + dev_priv->fb_mappable_pages >>= PAGE_SHIFT; + + NV_INFO(dev, "%d MiB VRAM\n", (int)(dev_priv->fb_available_size >> 20)); + + /* remove reserved space at end of vram from available amount */ + dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram; + dev_priv->fb_aper_free = dev_priv->fb_available_size; + + /* mappable vram */ + ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM, + dev_priv->fb_available_size >> PAGE_SHIFT); + if (ret) { + NV_ERROR(dev, "Failed VRAM mm init: %d\n", ret); + return ret; + } + + /* GART */ +#if !defined(__powerpc__) && !defined(__ia64__) + if (drm_device_is_agp(dev) && dev->agp) { + ret = nouveau_mem_init_agp(dev); + if (ret) + NV_ERROR(dev, "Error initialising AGP: %d\n", ret); + } +#endif + + if (dev_priv->gart_info.type == NOUVEAU_GART_NONE) { + ret = nouveau_sgdma_init(dev); + if (ret) { + NV_ERROR(dev, "Error initialising PCI(E): %d\n", ret); + return ret; + } + } + + NV_INFO(dev, "%d MiB GART (aperture)\n", + (int)(dev_priv->gart_info.aper_size >> 20)); + dev_priv->gart_info.aper_free = dev_priv->gart_info.aper_size; + + ret = ttm_bo_init_mm(bdev, TTM_PL_TT, + dev_priv->gart_info.aper_size >> PAGE_SHIFT); + if (ret) { + NV_ERROR(dev, "Failed TT mm init: %d\n", ret); + return ret; + } + + dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1), + drm_get_resource_len(dev, 1), + DRM_MTRR_WC); + return 0; +} + + diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c new file mode 100644 index 0000000000000000000000000000000000000000..6c66a34b63453bc599c31a1eb8d4103bd307cfc2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +int +nouveau_notifier_init_channel(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct nouveau_bo *ntfy = NULL; + int ret; + + ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, nouveau_vram_notify ? + TTM_PL_FLAG_VRAM : TTM_PL_FLAG_TT, + 0, 0x0000, false, true, &ntfy); + if (ret) + return ret; + + ret = nouveau_bo_pin(ntfy, TTM_PL_FLAG_VRAM); + if (ret) + goto out_err; + + ret = nouveau_bo_map(ntfy); + if (ret) + goto out_err; + + ret = nouveau_mem_init_heap(&chan->notifier_heap, 0, ntfy->bo.mem.size); + if (ret) + goto out_err; + + chan->notifier_bo = ntfy; +out_err: + if (ret) { + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(ntfy->gem); + mutex_unlock(&dev->struct_mutex); + } + + return ret; +} + +void +nouveau_notifier_takedown_channel(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + + if (!chan->notifier_bo) + return; + + nouveau_bo_unmap(chan->notifier_bo); + mutex_lock(&dev->struct_mutex); + nouveau_bo_unpin(chan->notifier_bo); + drm_gem_object_unreference(chan->notifier_bo->gem); + mutex_unlock(&dev->struct_mutex); + nouveau_mem_takedown(&chan->notifier_heap); +} + +static void +nouveau_notifier_gpuobj_dtor(struct drm_device *dev, + struct nouveau_gpuobj *gpuobj) +{ + NV_DEBUG(dev, "\n"); + + if (gpuobj->priv) + nouveau_mem_free_block(gpuobj->priv); +} + +int +nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, + int size, uint32_t *b_offset) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *nobj = NULL; + struct mem_block *mem; + uint32_t offset; + int target, ret; + + if (!chan->notifier_heap) { + NV_ERROR(dev, "Channel %d doesn't have a notifier heap!\n", + chan->id); + return -EINVAL; + } + + mem = nouveau_mem_alloc_block(chan->notifier_heap, size, 0, + (struct drm_file *)-2, 0); + if (!mem) { + NV_ERROR(dev, "Channel %d notifier block full\n", chan->id); + return -ENOMEM; + } + + offset = chan->notifier_bo->bo.mem.mm_node->start << PAGE_SHIFT; + if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) { + target = NV_DMA_TARGET_VIDMEM; + } else + if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_TT) { + if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA && + dev_priv->card_type < NV_50) { + ret = nouveau_sgdma_get_page(dev, offset, &offset); + if (ret) + return ret; + target = NV_DMA_TARGET_PCI; + } else { + target = NV_DMA_TARGET_AGP; + } + } else { + NV_ERROR(dev, "Bad DMA target, mem_type %d!\n", + chan->notifier_bo->bo.mem.mem_type); + return -EINVAL; + } + offset += mem->start; + + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, + mem->size, NV_DMA_ACCESS_RW, target, + &nobj); + if (ret) { + nouveau_mem_free_block(mem); + NV_ERROR(dev, "Error creating notifier ctxdma: %d\n", ret); + return ret; + } + nobj->dtor = nouveau_notifier_gpuobj_dtor; + nobj->priv = mem; + + ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL); + if (ret) { + nouveau_gpuobj_del(dev, &nobj); + nouveau_mem_free_block(mem); + NV_ERROR(dev, "Error referencing notifier ctxdma: %d\n", ret); + return ret; + } + + *b_offset = mem->start; + return 0; +} + +int +nouveau_notifier_offset(struct nouveau_gpuobj *nobj, uint32_t *poffset) +{ + if (!nobj || nobj->dtor != nouveau_notifier_gpuobj_dtor) + return -EINVAL; + + if (poffset) { + struct mem_block *mem = nobj->priv; + + if (*poffset >= mem->size) + return false; + + *poffset += mem->start; + } + + return 0; +} + +int +nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_notifierobj_alloc *na = data; + struct nouveau_channel *chan; + int ret; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan); + + ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset); + if (ret) + return ret; + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c new file mode 100644 index 0000000000000000000000000000000000000000..93379bb81beae845a0a91a769537cd90b790d87c --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_object.c @@ -0,0 +1,1294 @@ +/* + * Copyright (C) 2006 Ben Skeggs. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +/* + * Authors: + * Ben Skeggs + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +/* NVidia uses context objects to drive drawing operations. + + Context objects can be selected into 8 subchannels in the FIFO, + and then used via DMA command buffers. + + A context object is referenced by a user defined handle (CARD32). The HW + looks up graphics objects in a hash table in the instance RAM. + + An entry in the hash table consists of 2 CARD32. The first CARD32 contains + the handle, the second one a bitfield, that contains the address of the + object in instance RAM. + + The format of the second CARD32 seems to be: + + NV4 to NV30: + + 15: 0 instance_addr >> 4 + 17:16 engine (here uses 1 = graphics) + 28:24 channel id (here uses 0) + 31 valid (use 1) + + NV40: + + 15: 0 instance_addr >> 4 (maybe 19-0) + 21:20 engine (here uses 1 = graphics) + I'm unsure about the other bits, but using 0 seems to work. + + The key into the hash table depends on the object handle and channel id and + is given as: +*/ +static uint32_t +nouveau_ramht_hash_handle(struct drm_device *dev, int channel, uint32_t handle) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t hash = 0; + int i; + + NV_DEBUG(dev, "ch%d handle=0x%08x\n", channel, handle); + + for (i = 32; i > 0; i -= dev_priv->ramht_bits) { + hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1)); + handle >>= dev_priv->ramht_bits; + } + + if (dev_priv->card_type < NV_50) + hash ^= channel << (dev_priv->ramht_bits - 4); + hash <<= 3; + + NV_DEBUG(dev, "hash=0x%08x\n", hash); + return hash; +} + +static int +nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht, + uint32_t offset) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t ctx = nv_ro32(dev, ramht, (offset + 4)/4); + + if (dev_priv->card_type < NV_40) + return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0); + return (ctx != 0); +} + +static int +nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; + struct nouveau_channel *chan = ref->channel; + struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL; + uint32_t ctx, co, ho; + + if (!ramht) { + NV_ERROR(dev, "No hash table!\n"); + return -EINVAL; + } + + if (dev_priv->card_type < NV_40) { + ctx = NV_RAMHT_CONTEXT_VALID | (ref->instance >> 4) | + (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | + (ref->gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); + } else + if (dev_priv->card_type < NV_50) { + ctx = (ref->instance >> 4) | + (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | + (ref->gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); + } else { + if (ref->gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { + ctx = (ref->instance << 10) | 2; + } else { + ctx = (ref->instance >> 4) | + ((ref->gpuobj->engine << + NV40_RAMHT_CONTEXT_ENGINE_SHIFT)); + } + } + + instmem->prepare_access(dev, true); + co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); + do { + if (!nouveau_ramht_entry_valid(dev, ramht, co)) { + NV_DEBUG(dev, + "insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n", + chan->id, co, ref->handle, ctx); + nv_wo32(dev, ramht, (co + 0)/4, ref->handle); + nv_wo32(dev, ramht, (co + 4)/4, ctx); + + list_add_tail(&ref->list, &chan->ramht_refs); + instmem->finish_access(dev); + return 0; + } + NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", + chan->id, co, nv_ro32(dev, ramht, co/4)); + + co += 8; + if (co >= dev_priv->ramht_size) + co = 0; + } while (co != ho); + instmem->finish_access(dev); + + NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id); + return -ENOMEM; +} + +static void +nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; + struct nouveau_channel *chan = ref->channel; + struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL; + uint32_t co, ho; + + if (!ramht) { + NV_ERROR(dev, "No hash table!\n"); + return; + } + + instmem->prepare_access(dev, true); + co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); + do { + if (nouveau_ramht_entry_valid(dev, ramht, co) && + (ref->handle == nv_ro32(dev, ramht, (co/4)))) { + NV_DEBUG(dev, + "remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n", + chan->id, co, ref->handle, + nv_ro32(dev, ramht, (co + 4))); + nv_wo32(dev, ramht, (co + 0)/4, 0x00000000); + nv_wo32(dev, ramht, (co + 4)/4, 0x00000000); + + list_del(&ref->list); + instmem->finish_access(dev); + return; + } + + co += 8; + if (co >= dev_priv->ramht_size) + co = 0; + } while (co != ho); + list_del(&ref->list); + instmem->finish_access(dev); + + NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", + chan->id, ref->handle); +} + +int +nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, + uint32_t size, int align, uint32_t flags, + struct nouveau_gpuobj **gpuobj_ret) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->engine; + struct nouveau_gpuobj *gpuobj; + struct mem_block *pramin = NULL; + int ret; + + NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n", + chan ? chan->id : -1, size, align, flags); + + if (!dev_priv || !gpuobj_ret || *gpuobj_ret != NULL) + return -EINVAL; + + gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); + if (!gpuobj) + return -ENOMEM; + NV_DEBUG(dev, "gpuobj %p\n", gpuobj); + gpuobj->flags = flags; + gpuobj->im_channel = chan; + + list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); + + /* Choose between global instmem heap, and per-channel private + * instmem heap. On ramin_heap) { + NV_DEBUG(dev, "private heap\n"); + pramin = chan->ramin_heap; + } else + if (dev_priv->card_type < NV_50) { + NV_DEBUG(dev, "global heap fallback\n"); + pramin = dev_priv->ramin_heap; + } + } else { + NV_DEBUG(dev, "global heap\n"); + pramin = dev_priv->ramin_heap; + } + + if (!pramin) { + NV_ERROR(dev, "No PRAMIN heap!\n"); + return -EINVAL; + } + + if (!chan) { + ret = engine->instmem.populate(dev, gpuobj, &size); + if (ret) { + nouveau_gpuobj_del(dev, &gpuobj); + return ret; + } + } + + /* Allocate a chunk of the PRAMIN aperture */ + gpuobj->im_pramin = nouveau_mem_alloc_block(pramin, size, + drm_order(align), + (struct drm_file *)-2, 0); + if (!gpuobj->im_pramin) { + nouveau_gpuobj_del(dev, &gpuobj); + return -ENOMEM; + } + + if (!chan) { + ret = engine->instmem.bind(dev, gpuobj); + if (ret) { + nouveau_gpuobj_del(dev, &gpuobj); + return ret; + } + } + + if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { + int i; + + engine->instmem.prepare_access(dev, true); + for (i = 0; i < gpuobj->im_pramin->size; i += 4) + nv_wo32(dev, gpuobj, i/4, 0); + engine->instmem.finish_access(dev); + } + + *gpuobj_ret = gpuobj; + return 0; +} + +int +nouveau_gpuobj_early_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + NV_DEBUG(dev, "\n"); + + INIT_LIST_HEAD(&dev_priv->gpuobj_list); + + return 0; +} + +int +nouveau_gpuobj_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + NV_DEBUG(dev, "\n"); + + if (dev_priv->card_type < NV_50) { + ret = nouveau_gpuobj_new_fake(dev, + dev_priv->ramht_offset, ~0, dev_priv->ramht_size, + NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ALLOW_NO_REFS, + &dev_priv->ramht, NULL); + if (ret) + return ret; + } + + return 0; +} + +void +nouveau_gpuobj_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + NV_DEBUG(dev, "\n"); + + nouveau_gpuobj_del(dev, &dev_priv->ramht); +} + +void +nouveau_gpuobj_late_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = NULL; + struct list_head *entry, *tmp; + + NV_DEBUG(dev, "\n"); + + list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) { + gpuobj = list_entry(entry, struct nouveau_gpuobj, list); + + NV_ERROR(dev, "gpuobj %p still exists at takedown, refs=%d\n", + gpuobj, gpuobj->refcount); + gpuobj->refcount = 0; + nouveau_gpuobj_del(dev, &gpuobj); + } +} + +int +nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->engine; + struct nouveau_gpuobj *gpuobj; + int i; + + NV_DEBUG(dev, "gpuobj %p\n", pgpuobj ? *pgpuobj : NULL); + + if (!dev_priv || !pgpuobj || !(*pgpuobj)) + return -EINVAL; + gpuobj = *pgpuobj; + + if (gpuobj->refcount != 0) { + NV_ERROR(dev, "gpuobj refcount is %d\n", gpuobj->refcount); + return -EINVAL; + } + + if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) { + engine->instmem.prepare_access(dev, true); + for (i = 0; i < gpuobj->im_pramin->size; i += 4) + nv_wo32(dev, gpuobj, i/4, 0); + engine->instmem.finish_access(dev); + } + + if (gpuobj->dtor) + gpuobj->dtor(dev, gpuobj); + + if (gpuobj->im_backing && !(gpuobj->flags & NVOBJ_FLAG_FAKE)) + engine->instmem.clear(dev, gpuobj); + + if (gpuobj->im_pramin) { + if (gpuobj->flags & NVOBJ_FLAG_FAKE) + kfree(gpuobj->im_pramin); + else + nouveau_mem_free_block(gpuobj->im_pramin); + } + + list_del(&gpuobj->list); + + *pgpuobj = NULL; + kfree(gpuobj); + return 0; +} + +static int +nouveau_gpuobj_instance_get(struct drm_device *dev, + struct nouveau_channel *chan, + struct nouveau_gpuobj *gpuobj, uint32_t *inst) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *cpramin; + + /* card_type < NV_50) { + *inst = gpuobj->im_pramin->start; + return 0; + } + + if (chan && gpuobj->im_channel != chan) { + NV_ERROR(dev, "Channel mismatch: obj %d, ref %d\n", + gpuobj->im_channel->id, chan->id); + return -EINVAL; + } + + /* NV50 channel-local instance */ + if (chan) { + cpramin = chan->ramin->gpuobj; + *inst = gpuobj->im_pramin->start - cpramin->im_pramin->start; + return 0; + } + + /* NV50 global (VRAM) instance */ + if (!gpuobj->im_channel) { + /* ...from global heap */ + if (!gpuobj->im_backing) { + NV_ERROR(dev, "AII, no VRAM backing gpuobj\n"); + return -EINVAL; + } + *inst = gpuobj->im_backing_start; + return 0; + } else { + /* ...from local heap */ + cpramin = gpuobj->im_channel->ramin->gpuobj; + *inst = cpramin->im_backing_start + + (gpuobj->im_pramin->start - cpramin->im_pramin->start); + return 0; + } + + return -EINVAL; +} + +int +nouveau_gpuobj_ref_add(struct drm_device *dev, struct nouveau_channel *chan, + uint32_t handle, struct nouveau_gpuobj *gpuobj, + struct nouveau_gpuobj_ref **ref_ret) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj_ref *ref; + uint32_t instance; + int ret; + + NV_DEBUG(dev, "ch%d h=0x%08x gpuobj=%p\n", + chan ? chan->id : -1, handle, gpuobj); + + if (!dev_priv || !gpuobj || (ref_ret && *ref_ret != NULL)) + return -EINVAL; + + if (!chan && !ref_ret) + return -EINVAL; + + if (gpuobj->engine == NVOBJ_ENGINE_SW && !gpuobj->im_pramin) { + /* sw object */ + instance = 0x40; + } else { + ret = nouveau_gpuobj_instance_get(dev, chan, gpuobj, &instance); + if (ret) + return ret; + } + + ref = kzalloc(sizeof(*ref), GFP_KERNEL); + if (!ref) + return -ENOMEM; + INIT_LIST_HEAD(&ref->list); + ref->gpuobj = gpuobj; + ref->channel = chan; + ref->instance = instance; + + if (!ref_ret) { + ref->handle = handle; + + ret = nouveau_ramht_insert(dev, ref); + if (ret) { + kfree(ref); + return ret; + } + } else { + ref->handle = ~0; + *ref_ret = ref; + } + + ref->gpuobj->refcount++; + return 0; +} + +int nouveau_gpuobj_ref_del(struct drm_device *dev, struct nouveau_gpuobj_ref **pref) +{ + struct nouveau_gpuobj_ref *ref; + + NV_DEBUG(dev, "ref %p\n", pref ? *pref : NULL); + + if (!dev || !pref || *pref == NULL) + return -EINVAL; + ref = *pref; + + if (ref->handle != ~0) + nouveau_ramht_remove(dev, ref); + + if (ref->gpuobj) { + ref->gpuobj->refcount--; + + if (ref->gpuobj->refcount == 0) { + if (!(ref->gpuobj->flags & NVOBJ_FLAG_ALLOW_NO_REFS)) + nouveau_gpuobj_del(dev, &ref->gpuobj); + } + } + + *pref = NULL; + kfree(ref); + return 0; +} + +int +nouveau_gpuobj_new_ref(struct drm_device *dev, + struct nouveau_channel *oc, struct nouveau_channel *rc, + uint32_t handle, uint32_t size, int align, + uint32_t flags, struct nouveau_gpuobj_ref **ref) +{ + struct nouveau_gpuobj *gpuobj = NULL; + int ret; + + ret = nouveau_gpuobj_new(dev, oc, size, align, flags, &gpuobj); + if (ret) + return ret; + + ret = nouveau_gpuobj_ref_add(dev, rc, handle, gpuobj, ref); + if (ret) { + nouveau_gpuobj_del(dev, &gpuobj); + return ret; + } + + return 0; +} + +int +nouveau_gpuobj_ref_find(struct nouveau_channel *chan, uint32_t handle, + struct nouveau_gpuobj_ref **ref_ret) +{ + struct nouveau_gpuobj_ref *ref; + struct list_head *entry, *tmp; + + list_for_each_safe(entry, tmp, &chan->ramht_refs) { + ref = list_entry(entry, struct nouveau_gpuobj_ref, list); + + if (ref->handle == handle) { + if (ref_ret) + *ref_ret = ref; + return 0; + } + } + + return -EINVAL; +} + +int +nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset, + uint32_t b_offset, uint32_t size, + uint32_t flags, struct nouveau_gpuobj **pgpuobj, + struct nouveau_gpuobj_ref **pref) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = NULL; + int i; + + NV_DEBUG(dev, + "p_offset=0x%08x b_offset=0x%08x size=0x%08x flags=0x%08x\n", + p_offset, b_offset, size, flags); + + gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); + if (!gpuobj) + return -ENOMEM; + NV_DEBUG(dev, "gpuobj %p\n", gpuobj); + gpuobj->im_channel = NULL; + gpuobj->flags = flags | NVOBJ_FLAG_FAKE; + + list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); + + if (p_offset != ~0) { + gpuobj->im_pramin = kzalloc(sizeof(struct mem_block), + GFP_KERNEL); + if (!gpuobj->im_pramin) { + nouveau_gpuobj_del(dev, &gpuobj); + return -ENOMEM; + } + gpuobj->im_pramin->start = p_offset; + gpuobj->im_pramin->size = size; + } + + if (b_offset != ~0) { + gpuobj->im_backing = (struct nouveau_bo *)-1; + gpuobj->im_backing_start = b_offset; + } + + if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { + dev_priv->engine.instmem.prepare_access(dev, true); + for (i = 0; i < gpuobj->im_pramin->size; i += 4) + nv_wo32(dev, gpuobj, i/4, 0); + dev_priv->engine.instmem.finish_access(dev); + } + + if (pref) { + i = nouveau_gpuobj_ref_add(dev, NULL, 0, gpuobj, pref); + if (i) { + nouveau_gpuobj_del(dev, &gpuobj); + return i; + } + } + + if (pgpuobj) + *pgpuobj = gpuobj; + return 0; +} + + +static uint32_t +nouveau_gpuobj_class_instmem_size(struct drm_device *dev, int class) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /*XXX: dodgy hack for now */ + if (dev_priv->card_type >= NV_50) + return 24; + if (dev_priv->card_type >= NV_40) + return 32; + return 16; +} + +/* + DMA objects are used to reference a piece of memory in the + framebuffer, PCI or AGP address space. Each object is 16 bytes big + and looks as follows: + + entry[0] + 11:0 class (seems like I can always use 0 here) + 12 page table present? + 13 page entry linear? + 15:14 access: 0 rw, 1 ro, 2 wo + 17:16 target: 0 NV memory, 1 NV memory tiled, 2 PCI, 3 AGP + 31:20 dma adjust (bits 0-11 of the address) + entry[1] + dma limit (size of transfer) + entry[X] + 1 0 readonly, 1 readwrite + 31:12 dma frame address of the page (bits 12-31 of the address) + entry[N] + page table terminator, same value as the first pte, as does nvidia + rivatv uses 0xffffffff + + Non linear page tables need a list of frame addresses afterwards, + the rivatv project has some info on this. + + The method below creates a DMA object in instance RAM and returns a handle + to it that can be used to set up context objects. +*/ +int +nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, + uint64_t offset, uint64_t size, int access, + int target, struct nouveau_gpuobj **gpuobj) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; + int ret; + + NV_DEBUG(dev, "ch%d class=0x%04x offset=0x%llx size=0x%llx\n", + chan->id, class, offset, size); + NV_DEBUG(dev, "access=%d target=%d\n", access, target); + + switch (target) { + case NV_DMA_TARGET_AGP: + offset += dev_priv->gart_info.aper_base; + break; + default: + break; + } + + ret = nouveau_gpuobj_new(dev, chan, + nouveau_gpuobj_class_instmem_size(dev, class), + 16, NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, gpuobj); + if (ret) { + NV_ERROR(dev, "Error creating gpuobj: %d\n", ret); + return ret; + } + + instmem->prepare_access(dev, true); + + if (dev_priv->card_type < NV_50) { + uint32_t frame, adjust, pte_flags = 0; + + if (access != NV_DMA_ACCESS_RO) + pte_flags |= (1<<1); + adjust = offset & 0x00000fff; + frame = offset & ~0x00000fff; + + nv_wo32(dev, *gpuobj, 0, ((1<<12) | (1<<13) | + (adjust << 20) | + (access << 14) | + (target << 16) | + class)); + nv_wo32(dev, *gpuobj, 1, size - 1); + nv_wo32(dev, *gpuobj, 2, frame | pte_flags); + nv_wo32(dev, *gpuobj, 3, frame | pte_flags); + } else { + uint64_t limit = offset + size - 1; + uint32_t flags0, flags5; + + if (target == NV_DMA_TARGET_VIDMEM) { + flags0 = 0x00190000; + flags5 = 0x00010000; + } else { + flags0 = 0x7fc00000; + flags5 = 0x00080000; + } + + nv_wo32(dev, *gpuobj, 0, flags0 | class); + nv_wo32(dev, *gpuobj, 1, lower_32_bits(limit)); + nv_wo32(dev, *gpuobj, 2, lower_32_bits(offset)); + nv_wo32(dev, *gpuobj, 3, ((upper_32_bits(limit) & 0xff) << 24) | + (upper_32_bits(offset) & 0xff)); + nv_wo32(dev, *gpuobj, 5, flags5); + } + + instmem->finish_access(dev); + + (*gpuobj)->engine = NVOBJ_ENGINE_SW; + (*gpuobj)->class = class; + return 0; +} + +int +nouveau_gpuobj_gart_dma_new(struct nouveau_channel *chan, + uint64_t offset, uint64_t size, int access, + struct nouveau_gpuobj **gpuobj, + uint32_t *o_ret) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + if (dev_priv->gart_info.type == NOUVEAU_GART_AGP || + (dev_priv->card_type >= NV_50 && + dev_priv->gart_info.type == NOUVEAU_GART_SGDMA)) { + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, + offset + dev_priv->vm_gart_base, + size, access, NV_DMA_TARGET_AGP, + gpuobj); + if (o_ret) + *o_ret = 0; + } else + if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA) { + *gpuobj = dev_priv->gart_info.sg_ctxdma; + if (offset & ~0xffffffffULL) { + NV_ERROR(dev, "obj offset exceeds 32-bits\n"); + return -EINVAL; + } + if (o_ret) + *o_ret = (uint32_t)offset; + ret = (*gpuobj != NULL) ? 0 : -EINVAL; + } else { + NV_ERROR(dev, "Invalid GART type %d\n", dev_priv->gart_info.type); + return -EINVAL; + } + + return ret; +} + +/* Context objects in the instance RAM have the following structure. + * On NV40 they are 32 byte long, on NV30 and smaller 16 bytes. + + NV4 - NV30: + + entry[0] + 11:0 class + 12 chroma key enable + 13 user clip enable + 14 swizzle enable + 17:15 patch config: + scrcopy_and, rop_and, blend_and, scrcopy, srccopy_pre, blend_pre + 18 synchronize enable + 19 endian: 1 big, 0 little + 21:20 dither mode + 23 single step enable + 24 patch status: 0 invalid, 1 valid + 25 context_surface 0: 1 valid + 26 context surface 1: 1 valid + 27 context pattern: 1 valid + 28 context rop: 1 valid + 29,30 context beta, beta4 + entry[1] + 7:0 mono format + 15:8 color format + 31:16 notify instance address + entry[2] + 15:0 dma 0 instance address + 31:16 dma 1 instance address + entry[3] + dma method traps + + NV40: + No idea what the exact format is. Here's what can be deducted: + + entry[0]: + 11:0 class (maybe uses more bits here?) + 17 user clip enable + 21:19 patch config + 25 patch status valid ? + entry[1]: + 15:0 DMA notifier (maybe 20:0) + entry[2]: + 15:0 DMA 0 instance (maybe 20:0) + 24 big endian + entry[3]: + 15:0 DMA 1 instance (maybe 20:0) + entry[4]: + entry[5]: + set to 0? +*/ +int +nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, + struct nouveau_gpuobj **gpuobj) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class); + + ret = nouveau_gpuobj_new(dev, chan, + nouveau_gpuobj_class_instmem_size(dev, class), + 16, + NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, + gpuobj); + if (ret) { + NV_ERROR(dev, "Error creating gpuobj: %d\n", ret); + return ret; + } + + dev_priv->engine.instmem.prepare_access(dev, true); + if (dev_priv->card_type >= NV_50) { + nv_wo32(dev, *gpuobj, 0, class); + nv_wo32(dev, *gpuobj, 5, 0x00010000); + } else { + switch (class) { + case NV_CLASS_NULL: + nv_wo32(dev, *gpuobj, 0, 0x00001030); + nv_wo32(dev, *gpuobj, 1, 0xFFFFFFFF); + break; + default: + if (dev_priv->card_type >= NV_40) { + nv_wo32(dev, *gpuobj, 0, class); +#ifdef __BIG_ENDIAN + nv_wo32(dev, *gpuobj, 2, 0x01000000); +#endif + } else { +#ifdef __BIG_ENDIAN + nv_wo32(dev, *gpuobj, 0, class | 0x00080000); +#else + nv_wo32(dev, *gpuobj, 0, class); +#endif + } + } + } + dev_priv->engine.instmem.finish_access(dev); + + (*gpuobj)->engine = NVOBJ_ENGINE_GR; + (*gpuobj)->class = class; + return 0; +} + +static int +nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, + struct nouveau_gpuobj **gpuobj_ret) +{ + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct nouveau_gpuobj *gpuobj; + + if (!chan || !gpuobj_ret || *gpuobj_ret != NULL) + return -EINVAL; + + gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); + if (!gpuobj) + return -ENOMEM; + gpuobj->engine = NVOBJ_ENGINE_SW; + gpuobj->class = class; + + list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); + *gpuobj_ret = gpuobj; + return 0; +} + +static int +nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *pramin = NULL; + uint32_t size; + uint32_t base; + int ret; + + NV_DEBUG(dev, "ch%d\n", chan->id); + + /* Base amount for object storage (4KiB enough?) */ + size = 0x1000; + base = 0; + + /* PGRAPH context */ + + if (dev_priv->card_type == NV_50) { + /* Various fixed table thingos */ + size += 0x1400; /* mostly unknown stuff */ + size += 0x4000; /* vm pd */ + base = 0x6000; + /* RAMHT, not sure about setting size yet, 32KiB to be safe */ + size += 0x8000; + /* RAMFC */ + size += 0x1000; + /* PGRAPH context */ + size += 0x70000; + } + + NV_DEBUG(dev, "ch%d PRAMIN size: 0x%08x bytes, base alloc=0x%08x\n", + chan->id, size, base); + ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0, + &chan->ramin); + if (ret) { + NV_ERROR(dev, "Error allocating channel PRAMIN: %d\n", ret); + return ret; + } + pramin = chan->ramin->gpuobj; + + ret = nouveau_mem_init_heap(&chan->ramin_heap, + pramin->im_pramin->start + base, size); + if (ret) { + NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret); + nouveau_gpuobj_ref_del(dev, &chan->ramin); + return ret; + } + + return 0; +} + +int +nouveau_gpuobj_channel_init(struct nouveau_channel *chan, + uint32_t vram_h, uint32_t tt_h) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; + struct nouveau_gpuobj *vram = NULL, *tt = NULL; + int ret, i; + + INIT_LIST_HEAD(&chan->ramht_refs); + + NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); + + /* Reserve a block of PRAMIN for the channel + *XXX: maybe on card_type == NV_50) { + ret = nouveau_gpuobj_channel_init_pramin(chan); + if (ret) { + NV_ERROR(dev, "init pramin\n"); + return ret; + } + } + + /* NV50 VM + * - Allocate per-channel page-directory + * - Map GART and VRAM into the channel's address space at the + * locations determined during init. + */ + if (dev_priv->card_type >= NV_50) { + uint32_t vm_offset, pde; + + instmem->prepare_access(dev, true); + + vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200; + vm_offset += chan->ramin->gpuobj->im_pramin->start; + + ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000, + 0, &chan->vm_pd, NULL); + if (ret) { + instmem->finish_access(dev); + return ret; + } + for (i = 0; i < 0x4000; i += 8) { + nv_wo32(dev, chan->vm_pd, (i+0)/4, 0x00000000); + nv_wo32(dev, chan->vm_pd, (i+4)/4, 0xdeadcafe); + } + + pde = (dev_priv->vm_gart_base / (512*1024*1024)) * 2; + ret = nouveau_gpuobj_ref_add(dev, NULL, 0, + dev_priv->gart_info.sg_ctxdma, + &chan->vm_gart_pt); + if (ret) { + instmem->finish_access(dev); + return ret; + } + nv_wo32(dev, chan->vm_pd, pde++, + chan->vm_gart_pt->instance | 0x03); + nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); + + pde = (dev_priv->vm_vram_base / (512*1024*1024)) * 2; + for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { + ret = nouveau_gpuobj_ref_add(dev, NULL, 0, + dev_priv->vm_vram_pt[i], + &chan->vm_vram_pt[i]); + if (ret) { + instmem->finish_access(dev); + return ret; + } + + nv_wo32(dev, chan->vm_pd, pde++, + chan->vm_vram_pt[i]->instance | 0x61); + nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); + } + + instmem->finish_access(dev); + } + + /* RAMHT */ + if (dev_priv->card_type < NV_50) { + ret = nouveau_gpuobj_ref_add(dev, NULL, 0, dev_priv->ramht, + &chan->ramht); + if (ret) + return ret; + } else { + ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, + 0x8000, 16, + NVOBJ_FLAG_ZERO_ALLOC, + &chan->ramht); + if (ret) + return ret; + } + + /* VRAM ctxdma */ + if (dev_priv->card_type >= NV_50) { + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, + 0, dev_priv->vm_end, + NV_DMA_ACCESS_RW, + NV_DMA_TARGET_AGP, &vram); + if (ret) { + NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); + return ret; + } + } else { + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, + 0, dev_priv->fb_available_size, + NV_DMA_ACCESS_RW, + NV_DMA_TARGET_VIDMEM, &vram); + if (ret) { + NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); + return ret; + } + } + + ret = nouveau_gpuobj_ref_add(dev, chan, vram_h, vram, NULL); + if (ret) { + NV_ERROR(dev, "Error referencing VRAM ctxdma: %d\n", ret); + return ret; + } + + /* TT memory ctxdma */ + if (dev_priv->card_type >= NV_50) { + tt = vram; + } else + if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) { + ret = nouveau_gpuobj_gart_dma_new(chan, 0, + dev_priv->gart_info.aper_size, + NV_DMA_ACCESS_RW, &tt, NULL); + } else { + NV_ERROR(dev, "Invalid GART type %d\n", dev_priv->gart_info.type); + ret = -EINVAL; + } + + if (ret) { + NV_ERROR(dev, "Error creating TT ctxdma: %d\n", ret); + return ret; + } + + ret = nouveau_gpuobj_ref_add(dev, chan, tt_h, tt, NULL); + if (ret) { + NV_ERROR(dev, "Error referencing TT ctxdma: %d\n", ret); + return ret; + } + + return 0; +} + +void +nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) +{ + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct drm_device *dev = chan->dev; + struct list_head *entry, *tmp; + struct nouveau_gpuobj_ref *ref; + int i; + + NV_DEBUG(dev, "ch%d\n", chan->id); + + if (!chan->ramht_refs.next) + return; + + list_for_each_safe(entry, tmp, &chan->ramht_refs) { + ref = list_entry(entry, struct nouveau_gpuobj_ref, list); + + nouveau_gpuobj_ref_del(dev, &ref); + } + + nouveau_gpuobj_ref_del(dev, &chan->ramht); + + nouveau_gpuobj_del(dev, &chan->vm_pd); + nouveau_gpuobj_ref_del(dev, &chan->vm_gart_pt); + for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) + nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]); + + if (chan->ramin_heap) + nouveau_mem_takedown(&chan->ramin_heap); + if (chan->ramin) + nouveau_gpuobj_ref_del(dev, &chan->ramin); + +} + +int +nouveau_gpuobj_suspend(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj; + int i; + + if (dev_priv->card_type < NV_50) { + dev_priv->susres.ramin_copy = vmalloc(dev_priv->ramin_rsvd_vram); + if (!dev_priv->susres.ramin_copy) + return -ENOMEM; + + for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4) + dev_priv->susres.ramin_copy[i/4] = nv_ri32(dev, i); + return 0; + } + + list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { + if (!gpuobj->im_backing || (gpuobj->flags & NVOBJ_FLAG_FAKE)) + continue; + + gpuobj->im_backing_suspend = vmalloc(gpuobj->im_pramin->size); + if (!gpuobj->im_backing_suspend) { + nouveau_gpuobj_resume(dev); + return -ENOMEM; + } + + dev_priv->engine.instmem.prepare_access(dev, false); + for (i = 0; i < gpuobj->im_pramin->size / 4; i++) + gpuobj->im_backing_suspend[i] = nv_ro32(dev, gpuobj, i); + dev_priv->engine.instmem.finish_access(dev); + } + + return 0; +} + +void +nouveau_gpuobj_suspend_cleanup(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj; + + if (dev_priv->card_type < NV_50) { + vfree(dev_priv->susres.ramin_copy); + dev_priv->susres.ramin_copy = NULL; + return; + } + + list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { + if (!gpuobj->im_backing_suspend) + continue; + + vfree(gpuobj->im_backing_suspend); + gpuobj->im_backing_suspend = NULL; + } +} + +void +nouveau_gpuobj_resume(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj; + int i; + + if (dev_priv->card_type < NV_50) { + for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4) + nv_wi32(dev, i, dev_priv->susres.ramin_copy[i/4]); + nouveau_gpuobj_suspend_cleanup(dev); + return; + } + + list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { + if (!gpuobj->im_backing_suspend) + continue; + + dev_priv->engine.instmem.prepare_access(dev, true); + for (i = 0; i < gpuobj->im_pramin->size / 4; i++) + nv_wo32(dev, gpuobj, i, gpuobj->im_backing_suspend[i]); + dev_priv->engine.instmem.finish_access(dev); + } + + nouveau_gpuobj_suspend_cleanup(dev); +} + +int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_grobj_alloc *init = data; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_pgraph_object_class *grc; + struct nouveau_gpuobj *gr = NULL; + struct nouveau_channel *chan; + int ret; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan); + + if (init->handle == ~0) + return -EINVAL; + + grc = pgraph->grclass; + while (grc->id) { + if (grc->id == init->class) + break; + grc++; + } + + if (!grc->id) { + NV_ERROR(dev, "Illegal object class: 0x%x\n", init->class); + return -EPERM; + } + + if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) == 0) + return -EEXIST; + + if (!grc->software) + ret = nouveau_gpuobj_gr_new(chan, grc->id, &gr); + else + ret = nouveau_gpuobj_sw_new(chan, grc->id, &gr); + + if (ret) { + NV_ERROR(dev, "Error creating object: %d (%d/0x%08x)\n", + ret, init->channel, init->handle); + return ret; + } + + ret = nouveau_gpuobj_ref_add(dev, chan, init->handle, gr, NULL); + if (ret) { + NV_ERROR(dev, "Error referencing object: %d (%d/0x%08x)\n", + ret, init->channel, init->handle); + nouveau_gpuobj_del(dev, &gr); + return ret; + } + + return 0; +} + +int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_gpuobj_free *objfree = data; + struct nouveau_gpuobj_ref *ref; + struct nouveau_channel *chan; + int ret; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan); + + ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref); + if (ret) + return ret; + nouveau_gpuobj_ref_del(dev, &ref); + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h new file mode 100644 index 0000000000000000000000000000000000000000..fa1b0e7165b9956ea3581c378ba61f13c75afb36 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_reg.h @@ -0,0 +1,836 @@ + + +#define NV03_BOOT_0 0x00100000 +# define NV03_BOOT_0_RAM_AMOUNT 0x00000003 +# define NV03_BOOT_0_RAM_AMOUNT_8MB 0x00000000 +# define NV03_BOOT_0_RAM_AMOUNT_2MB 0x00000001 +# define NV03_BOOT_0_RAM_AMOUNT_4MB 0x00000002 +# define NV03_BOOT_0_RAM_AMOUNT_8MB_SDRAM 0x00000003 +# define NV04_BOOT_0_RAM_AMOUNT_32MB 0x00000000 +# define NV04_BOOT_0_RAM_AMOUNT_4MB 0x00000001 +# define NV04_BOOT_0_RAM_AMOUNT_8MB 0x00000002 +# define NV04_BOOT_0_RAM_AMOUNT_16MB 0x00000003 + +#define NV04_FIFO_DATA 0x0010020c +# define NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000 +# define NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20 + +#define NV_RAMIN 0x00700000 + +#define NV_RAMHT_HANDLE_OFFSET 0 +#define NV_RAMHT_CONTEXT_OFFSET 4 +# define NV_RAMHT_CONTEXT_VALID (1<<31) +# define NV_RAMHT_CONTEXT_CHANNEL_SHIFT 24 +# define NV_RAMHT_CONTEXT_ENGINE_SHIFT 16 +# define NV_RAMHT_CONTEXT_ENGINE_SOFTWARE 0 +# define NV_RAMHT_CONTEXT_ENGINE_GRAPHICS 1 +# define NV_RAMHT_CONTEXT_INSTANCE_SHIFT 0 +# define NV40_RAMHT_CONTEXT_CHANNEL_SHIFT 23 +# define NV40_RAMHT_CONTEXT_ENGINE_SHIFT 20 +# define NV40_RAMHT_CONTEXT_INSTANCE_SHIFT 0 + +/* DMA object defines */ +#define NV_DMA_ACCESS_RW 0 +#define NV_DMA_ACCESS_RO 1 +#define NV_DMA_ACCESS_WO 2 +#define NV_DMA_TARGET_VIDMEM 0 +#define NV_DMA_TARGET_PCI 2 +#define NV_DMA_TARGET_AGP 3 +/* The following is not a real value used by the card, it's changed by + * nouveau_object_dma_create */ +#define NV_DMA_TARGET_PCI_NONLINEAR 8 + +/* Some object classes we care about in the drm */ +#define NV_CLASS_DMA_FROM_MEMORY 0x00000002 +#define NV_CLASS_DMA_TO_MEMORY 0x00000003 +#define NV_CLASS_NULL 0x00000030 +#define NV_CLASS_DMA_IN_MEMORY 0x0000003D + +#define NV03_USER(i) (0x00800000+(i*NV03_USER_SIZE)) +#define NV03_USER__SIZE 16 +#define NV10_USER__SIZE 32 +#define NV03_USER_SIZE 0x00010000 +#define NV03_USER_DMA_PUT(i) (0x00800040+(i*NV03_USER_SIZE)) +#define NV03_USER_DMA_PUT__SIZE 16 +#define NV10_USER_DMA_PUT__SIZE 32 +#define NV03_USER_DMA_GET(i) (0x00800044+(i*NV03_USER_SIZE)) +#define NV03_USER_DMA_GET__SIZE 16 +#define NV10_USER_DMA_GET__SIZE 32 +#define NV03_USER_REF_CNT(i) (0x00800048+(i*NV03_USER_SIZE)) +#define NV03_USER_REF_CNT__SIZE 16 +#define NV10_USER_REF_CNT__SIZE 32 + +#define NV40_USER(i) (0x00c00000+(i*NV40_USER_SIZE)) +#define NV40_USER_SIZE 0x00001000 +#define NV40_USER_DMA_PUT(i) (0x00c00040+(i*NV40_USER_SIZE)) +#define NV40_USER_DMA_PUT__SIZE 32 +#define NV40_USER_DMA_GET(i) (0x00c00044+(i*NV40_USER_SIZE)) +#define NV40_USER_DMA_GET__SIZE 32 +#define NV40_USER_REF_CNT(i) (0x00c00048+(i*NV40_USER_SIZE)) +#define NV40_USER_REF_CNT__SIZE 32 + +#define NV50_USER(i) (0x00c00000+(i*NV50_USER_SIZE)) +#define NV50_USER_SIZE 0x00002000 +#define NV50_USER_DMA_PUT(i) (0x00c00040+(i*NV50_USER_SIZE)) +#define NV50_USER_DMA_PUT__SIZE 128 +#define NV50_USER_DMA_GET(i) (0x00c00044+(i*NV50_USER_SIZE)) +#define NV50_USER_DMA_GET__SIZE 128 +#define NV50_USER_REF_CNT(i) (0x00c00048+(i*NV50_USER_SIZE)) +#define NV50_USER_REF_CNT__SIZE 128 + +#define NV03_FIFO_SIZE 0x8000UL + +#define NV03_PMC_BOOT_0 0x00000000 +#define NV03_PMC_BOOT_1 0x00000004 +#define NV03_PMC_INTR_0 0x00000100 +# define NV_PMC_INTR_0_PFIFO_PENDING (1<<8) +# define NV_PMC_INTR_0_PGRAPH_PENDING (1<<12) +# define NV_PMC_INTR_0_NV50_I2C_PENDING (1<<21) +# define NV_PMC_INTR_0_CRTC0_PENDING (1<<24) +# define NV_PMC_INTR_0_CRTC1_PENDING (1<<25) +# define NV_PMC_INTR_0_NV50_DISPLAY_PENDING (1<<26) +# define NV_PMC_INTR_0_CRTCn_PENDING (3<<24) +#define NV03_PMC_INTR_EN_0 0x00000140 +# define NV_PMC_INTR_EN_0_MASTER_ENABLE (1<<0) +#define NV03_PMC_ENABLE 0x00000200 +# define NV_PMC_ENABLE_PFIFO (1<<8) +# define NV_PMC_ENABLE_PGRAPH (1<<12) +/* Disabling the below bit breaks newer (G7X only?) mobile chipsets, + * the card will hang early on in the X init process. + */ +# define NV_PMC_ENABLE_UNK13 (1<<13) +#define NV40_PMC_BACKLIGHT 0x000015f0 +# define NV40_PMC_BACKLIGHT_MASK 0x001f0000 +#define NV40_PMC_1700 0x00001700 +#define NV40_PMC_1704 0x00001704 +#define NV40_PMC_1708 0x00001708 +#define NV40_PMC_170C 0x0000170C + +/* probably PMC ? */ +#define NV50_PUNK_BAR0_PRAMIN 0x00001700 +#define NV50_PUNK_BAR_CFG_BASE 0x00001704 +#define NV50_PUNK_BAR_CFG_BASE_VALID (1<<30) +#define NV50_PUNK_BAR1_CTXDMA 0x00001708 +#define NV50_PUNK_BAR1_CTXDMA_VALID (1<<31) +#define NV50_PUNK_BAR3_CTXDMA 0x0000170C +#define NV50_PUNK_BAR3_CTXDMA_VALID (1<<31) +#define NV50_PUNK_UNK1710 0x00001710 + +#define NV04_PBUS_PCI_NV_1 0x00001804 +#define NV04_PBUS_PCI_NV_19 0x0000184C +#define NV04_PBUS_PCI_NV_20 0x00001850 +# define NV04_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED (0 << 0) +# define NV04_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED (1 << 0) + +#define NV04_PTIMER_INTR_0 0x00009100 +#define NV04_PTIMER_INTR_EN_0 0x00009140 +#define NV04_PTIMER_NUMERATOR 0x00009200 +#define NV04_PTIMER_DENOMINATOR 0x00009210 +#define NV04_PTIMER_TIME_0 0x00009400 +#define NV04_PTIMER_TIME_1 0x00009410 +#define NV04_PTIMER_ALARM_0 0x00009420 + +#define NV04_PFB_CFG0 0x00100200 +#define NV04_PFB_CFG1 0x00100204 +#define NV40_PFB_020C 0x0010020C +#define NV10_PFB_TILE(i) (0x00100240 + (i*16)) +#define NV10_PFB_TILE__SIZE 8 +#define NV10_PFB_TLIMIT(i) (0x00100244 + (i*16)) +#define NV10_PFB_TSIZE(i) (0x00100248 + (i*16)) +#define NV10_PFB_TSTATUS(i) (0x0010024C + (i*16)) +#define NV10_PFB_CLOSE_PAGE2 0x0010033C +#define NV40_PFB_TILE(i) (0x00100600 + (i*16)) +#define NV40_PFB_TILE__SIZE_0 12 +#define NV40_PFB_TILE__SIZE_1 15 +#define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16)) +#define NV40_PFB_TSIZE(i) (0x00100608 + (i*16)) +#define NV40_PFB_TSTATUS(i) (0x0010060C + (i*16)) +#define NV40_PFB_UNK_800 0x00100800 + +#define NV04_PGRAPH_DEBUG_0 0x00400080 +#define NV04_PGRAPH_DEBUG_1 0x00400084 +#define NV04_PGRAPH_DEBUG_2 0x00400088 +#define NV04_PGRAPH_DEBUG_3 0x0040008c +#define NV10_PGRAPH_DEBUG_4 0x00400090 +#define NV03_PGRAPH_INTR 0x00400100 +#define NV03_PGRAPH_NSTATUS 0x00400104 +# define NV04_PGRAPH_NSTATUS_STATE_IN_USE (1<<11) +# define NV04_PGRAPH_NSTATUS_INVALID_STATE (1<<12) +# define NV04_PGRAPH_NSTATUS_BAD_ARGUMENT (1<<13) +# define NV04_PGRAPH_NSTATUS_PROTECTION_FAULT (1<<14) +# define NV10_PGRAPH_NSTATUS_STATE_IN_USE (1<<23) +# define NV10_PGRAPH_NSTATUS_INVALID_STATE (1<<24) +# define NV10_PGRAPH_NSTATUS_BAD_ARGUMENT (1<<25) +# define NV10_PGRAPH_NSTATUS_PROTECTION_FAULT (1<<26) +#define NV03_PGRAPH_NSOURCE 0x00400108 +# define NV03_PGRAPH_NSOURCE_NOTIFICATION (1<<0) +# define NV03_PGRAPH_NSOURCE_DATA_ERROR (1<<1) +# define NV03_PGRAPH_NSOURCE_PROTECTION_ERROR (1<<2) +# define NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION (1<<3) +# define NV03_PGRAPH_NSOURCE_LIMIT_COLOR (1<<4) +# define NV03_PGRAPH_NSOURCE_LIMIT_ZETA (1<<5) +# define NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD (1<<6) +# define NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION (1<<7) +# define NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION (1<<8) +# define NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION (1<<9) +# define NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION (1<<10) +# define NV03_PGRAPH_NSOURCE_STATE_INVALID (1<<11) +# define NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY (1<<12) +# define NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE (1<<13) +# define NV03_PGRAPH_NSOURCE_METHOD_CNT (1<<14) +# define NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION (1<<15) +# define NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION (1<<16) +# define NV03_PGRAPH_NSOURCE_DMA_WIDTH_A (1<<17) +# define NV03_PGRAPH_NSOURCE_DMA_WIDTH_B (1<<18) +#define NV03_PGRAPH_INTR_EN 0x00400140 +#define NV40_PGRAPH_INTR_EN 0x0040013C +# define NV_PGRAPH_INTR_NOTIFY (1<<0) +# define NV_PGRAPH_INTR_MISSING_HW (1<<4) +# define NV_PGRAPH_INTR_CONTEXT_SWITCH (1<<12) +# define NV_PGRAPH_INTR_BUFFER_NOTIFY (1<<16) +# define NV_PGRAPH_INTR_ERROR (1<<20) +#define NV10_PGRAPH_CTX_CONTROL 0x00400144 +#define NV10_PGRAPH_CTX_USER 0x00400148 +#define NV10_PGRAPH_CTX_SWITCH1 0x0040014C +#define NV10_PGRAPH_CTX_SWITCH2 0x00400150 +#define NV10_PGRAPH_CTX_SWITCH3 0x00400154 +#define NV10_PGRAPH_CTX_SWITCH4 0x00400158 +#define NV10_PGRAPH_CTX_SWITCH5 0x0040015C +#define NV04_PGRAPH_CTX_SWITCH1 0x00400160 +#define NV10_PGRAPH_CTX_CACHE1 0x00400160 +#define NV04_PGRAPH_CTX_SWITCH2 0x00400164 +#define NV04_PGRAPH_CTX_SWITCH3 0x00400168 +#define NV04_PGRAPH_CTX_SWITCH4 0x0040016C +#define NV04_PGRAPH_CTX_CONTROL 0x00400170 +#define NV04_PGRAPH_CTX_USER 0x00400174 +#define NV04_PGRAPH_CTX_CACHE1 0x00400180 +#define NV10_PGRAPH_CTX_CACHE2 0x00400180 +#define NV03_PGRAPH_CTX_CONTROL 0x00400190 +#define NV03_PGRAPH_CTX_USER 0x00400194 +#define NV04_PGRAPH_CTX_CACHE2 0x004001A0 +#define NV10_PGRAPH_CTX_CACHE3 0x004001A0 +#define NV04_PGRAPH_CTX_CACHE3 0x004001C0 +#define NV10_PGRAPH_CTX_CACHE4 0x004001C0 +#define NV04_PGRAPH_CTX_CACHE4 0x004001E0 +#define NV10_PGRAPH_CTX_CACHE5 0x004001E0 +#define NV40_PGRAPH_CTXCTL_0304 0x00400304 +#define NV40_PGRAPH_CTXCTL_0304_XFER_CTX 0x00000001 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT 0x00400308 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_MASK 0xff000000 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT 24 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK 0x00ffffff +#define NV40_PGRAPH_CTXCTL_0310 0x00400310 +#define NV40_PGRAPH_CTXCTL_0310_XFER_SAVE 0x00000020 +#define NV40_PGRAPH_CTXCTL_0310_XFER_LOAD 0x00000040 +#define NV40_PGRAPH_CTXCTL_030C 0x0040030c +#define NV40_PGRAPH_CTXCTL_UCODE_INDEX 0x00400324 +#define NV40_PGRAPH_CTXCTL_UCODE_DATA 0x00400328 +#define NV40_PGRAPH_CTXCTL_CUR 0x0040032c +#define NV40_PGRAPH_CTXCTL_CUR_LOADED 0x01000000 +#define NV40_PGRAPH_CTXCTL_CUR_INSTANCE 0x000FFFFF +#define NV40_PGRAPH_CTXCTL_NEXT 0x00400330 +#define NV40_PGRAPH_CTXCTL_NEXT_INSTANCE 0x000fffff +#define NV50_PGRAPH_CTXCTL_CUR 0x0040032c +#define NV50_PGRAPH_CTXCTL_CUR_LOADED 0x80000000 +#define NV50_PGRAPH_CTXCTL_CUR_INSTANCE 0x00ffffff +#define NV50_PGRAPH_CTXCTL_NEXT 0x00400330 +#define NV50_PGRAPH_CTXCTL_NEXT_INSTANCE 0x00ffffff +#define NV03_PGRAPH_ABS_X_RAM 0x00400400 +#define NV03_PGRAPH_ABS_Y_RAM 0x00400480 +#define NV03_PGRAPH_X_MISC 0x00400500 +#define NV03_PGRAPH_Y_MISC 0x00400504 +#define NV04_PGRAPH_VALID1 0x00400508 +#define NV04_PGRAPH_SOURCE_COLOR 0x0040050C +#define NV04_PGRAPH_MISC24_0 0x00400510 +#define NV03_PGRAPH_XY_LOGIC_MISC0 0x00400514 +#define NV03_PGRAPH_XY_LOGIC_MISC1 0x00400518 +#define NV03_PGRAPH_XY_LOGIC_MISC2 0x0040051C +#define NV03_PGRAPH_XY_LOGIC_MISC3 0x00400520 +#define NV03_PGRAPH_CLIPX_0 0x00400524 +#define NV03_PGRAPH_CLIPX_1 0x00400528 +#define NV03_PGRAPH_CLIPY_0 0x0040052C +#define NV03_PGRAPH_CLIPY_1 0x00400530 +#define NV03_PGRAPH_ABS_ICLIP_XMAX 0x00400534 +#define NV03_PGRAPH_ABS_ICLIP_YMAX 0x00400538 +#define NV03_PGRAPH_ABS_UCLIP_XMIN 0x0040053C +#define NV03_PGRAPH_ABS_UCLIP_YMIN 0x00400540 +#define NV03_PGRAPH_ABS_UCLIP_XMAX 0x00400544 +#define NV03_PGRAPH_ABS_UCLIP_YMAX 0x00400548 +#define NV03_PGRAPH_ABS_UCLIPA_XMIN 0x00400560 +#define NV03_PGRAPH_ABS_UCLIPA_YMIN 0x00400564 +#define NV03_PGRAPH_ABS_UCLIPA_XMAX 0x00400568 +#define NV03_PGRAPH_ABS_UCLIPA_YMAX 0x0040056C +#define NV04_PGRAPH_MISC24_1 0x00400570 +#define NV04_PGRAPH_MISC24_2 0x00400574 +#define NV04_PGRAPH_VALID2 0x00400578 +#define NV04_PGRAPH_PASSTHRU_0 0x0040057C +#define NV04_PGRAPH_PASSTHRU_1 0x00400580 +#define NV04_PGRAPH_PASSTHRU_2 0x00400584 +#define NV10_PGRAPH_DIMX_TEXTURE 0x00400588 +#define NV10_PGRAPH_WDIMX_TEXTURE 0x0040058C +#define NV04_PGRAPH_COMBINE_0_ALPHA 0x00400590 +#define NV04_PGRAPH_COMBINE_0_COLOR 0x00400594 +#define NV04_PGRAPH_COMBINE_1_ALPHA 0x00400598 +#define NV04_PGRAPH_COMBINE_1_COLOR 0x0040059C +#define NV04_PGRAPH_FORMAT_0 0x004005A8 +#define NV04_PGRAPH_FORMAT_1 0x004005AC +#define NV04_PGRAPH_FILTER_0 0x004005B0 +#define NV04_PGRAPH_FILTER_1 0x004005B4 +#define NV03_PGRAPH_MONO_COLOR0 0x00400600 +#define NV04_PGRAPH_ROP3 0x00400604 +#define NV04_PGRAPH_BETA_AND 0x00400608 +#define NV04_PGRAPH_BETA_PREMULT 0x0040060C +#define NV04_PGRAPH_LIMIT_VIOL_PIX 0x00400610 +#define NV04_PGRAPH_FORMATS 0x00400618 +#define NV10_PGRAPH_DEBUG_2 0x00400620 +#define NV04_PGRAPH_BOFFSET0 0x00400640 +#define NV04_PGRAPH_BOFFSET1 0x00400644 +#define NV04_PGRAPH_BOFFSET2 0x00400648 +#define NV04_PGRAPH_BOFFSET3 0x0040064C +#define NV04_PGRAPH_BOFFSET4 0x00400650 +#define NV04_PGRAPH_BOFFSET5 0x00400654 +#define NV04_PGRAPH_BBASE0 0x00400658 +#define NV04_PGRAPH_BBASE1 0x0040065C +#define NV04_PGRAPH_BBASE2 0x00400660 +#define NV04_PGRAPH_BBASE3 0x00400664 +#define NV04_PGRAPH_BBASE4 0x00400668 +#define NV04_PGRAPH_BBASE5 0x0040066C +#define NV04_PGRAPH_BPITCH0 0x00400670 +#define NV04_PGRAPH_BPITCH1 0x00400674 +#define NV04_PGRAPH_BPITCH2 0x00400678 +#define NV04_PGRAPH_BPITCH3 0x0040067C +#define NV04_PGRAPH_BPITCH4 0x00400680 +#define NV04_PGRAPH_BLIMIT0 0x00400684 +#define NV04_PGRAPH_BLIMIT1 0x00400688 +#define NV04_PGRAPH_BLIMIT2 0x0040068C +#define NV04_PGRAPH_BLIMIT3 0x00400690 +#define NV04_PGRAPH_BLIMIT4 0x00400694 +#define NV04_PGRAPH_BLIMIT5 0x00400698 +#define NV04_PGRAPH_BSWIZZLE2 0x0040069C +#define NV04_PGRAPH_BSWIZZLE5 0x004006A0 +#define NV03_PGRAPH_STATUS 0x004006B0 +#define NV04_PGRAPH_STATUS 0x00400700 +#define NV04_PGRAPH_TRAPPED_ADDR 0x00400704 +#define NV04_PGRAPH_TRAPPED_DATA 0x00400708 +#define NV04_PGRAPH_SURFACE 0x0040070C +#define NV10_PGRAPH_TRAPPED_DATA_HIGH 0x0040070C +#define NV04_PGRAPH_STATE 0x00400710 +#define NV10_PGRAPH_SURFACE 0x00400710 +#define NV04_PGRAPH_NOTIFY 0x00400714 +#define NV10_PGRAPH_STATE 0x00400714 +#define NV10_PGRAPH_NOTIFY 0x00400718 + +#define NV04_PGRAPH_FIFO 0x00400720 + +#define NV04_PGRAPH_BPIXEL 0x00400724 +#define NV10_PGRAPH_RDI_INDEX 0x00400750 +#define NV04_PGRAPH_FFINTFC_ST2 0x00400754 +#define NV10_PGRAPH_RDI_DATA 0x00400754 +#define NV04_PGRAPH_DMA_PITCH 0x00400760 +#define NV10_PGRAPH_FFINTFC_ST2 0x00400764 +#define NV04_PGRAPH_DVD_COLORFMT 0x00400764 +#define NV04_PGRAPH_SCALED_FORMAT 0x00400768 +#define NV10_PGRAPH_DMA_PITCH 0x00400770 +#define NV10_PGRAPH_DVD_COLORFMT 0x00400774 +#define NV10_PGRAPH_SCALED_FORMAT 0x00400778 +#define NV20_PGRAPH_CHANNEL_CTX_TABLE 0x00400780 +#define NV20_PGRAPH_CHANNEL_CTX_POINTER 0x00400784 +#define NV20_PGRAPH_CHANNEL_CTX_XFER 0x00400788 +#define NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD 0x00000001 +#define NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE 0x00000002 +#define NV04_PGRAPH_PATT_COLOR0 0x00400800 +#define NV04_PGRAPH_PATT_COLOR1 0x00400804 +#define NV04_PGRAPH_PATTERN 0x00400808 +#define NV04_PGRAPH_PATTERN_SHAPE 0x00400810 +#define NV04_PGRAPH_CHROMA 0x00400814 +#define NV04_PGRAPH_CONTROL0 0x00400818 +#define NV04_PGRAPH_CONTROL1 0x0040081C +#define NV04_PGRAPH_CONTROL2 0x00400820 +#define NV04_PGRAPH_BLEND 0x00400824 +#define NV04_PGRAPH_STORED_FMT 0x00400830 +#define NV04_PGRAPH_PATT_COLORRAM 0x00400900 +#define NV40_PGRAPH_TILE0(i) (0x00400900 + (i*16)) +#define NV40_PGRAPH_TLIMIT0(i) (0x00400904 + (i*16)) +#define NV40_PGRAPH_TSIZE0(i) (0x00400908 + (i*16)) +#define NV40_PGRAPH_TSTATUS0(i) (0x0040090C + (i*16)) +#define NV10_PGRAPH_TILE(i) (0x00400B00 + (i*16)) +#define NV10_PGRAPH_TLIMIT(i) (0x00400B04 + (i*16)) +#define NV10_PGRAPH_TSIZE(i) (0x00400B08 + (i*16)) +#define NV10_PGRAPH_TSTATUS(i) (0x00400B0C + (i*16)) +#define NV04_PGRAPH_U_RAM 0x00400D00 +#define NV47_PGRAPH_TILE0(i) (0x00400D00 + (i*16)) +#define NV47_PGRAPH_TLIMIT0(i) (0x00400D04 + (i*16)) +#define NV47_PGRAPH_TSIZE0(i) (0x00400D08 + (i*16)) +#define NV47_PGRAPH_TSTATUS0(i) (0x00400D0C + (i*16)) +#define NV04_PGRAPH_V_RAM 0x00400D40 +#define NV04_PGRAPH_W_RAM 0x00400D80 +#define NV10_PGRAPH_COMBINER0_IN_ALPHA 0x00400E40 +#define NV10_PGRAPH_COMBINER1_IN_ALPHA 0x00400E44 +#define NV10_PGRAPH_COMBINER0_IN_RGB 0x00400E48 +#define NV10_PGRAPH_COMBINER1_IN_RGB 0x00400E4C +#define NV10_PGRAPH_COMBINER_COLOR0 0x00400E50 +#define NV10_PGRAPH_COMBINER_COLOR1 0x00400E54 +#define NV10_PGRAPH_COMBINER0_OUT_ALPHA 0x00400E58 +#define NV10_PGRAPH_COMBINER1_OUT_ALPHA 0x00400E5C +#define NV10_PGRAPH_COMBINER0_OUT_RGB 0x00400E60 +#define NV10_PGRAPH_COMBINER1_OUT_RGB 0x00400E64 +#define NV10_PGRAPH_COMBINER_FINAL0 0x00400E68 +#define NV10_PGRAPH_COMBINER_FINAL1 0x00400E6C +#define NV10_PGRAPH_WINDOWCLIP_HORIZONTAL 0x00400F00 +#define NV10_PGRAPH_WINDOWCLIP_VERTICAL 0x00400F20 +#define NV10_PGRAPH_XFMODE0 0x00400F40 +#define NV10_PGRAPH_XFMODE1 0x00400F44 +#define NV10_PGRAPH_GLOBALSTATE0 0x00400F48 +#define NV10_PGRAPH_GLOBALSTATE1 0x00400F4C +#define NV10_PGRAPH_PIPE_ADDRESS 0x00400F50 +#define NV10_PGRAPH_PIPE_DATA 0x00400F54 +#define NV04_PGRAPH_DMA_START_0 0x00401000 +#define NV04_PGRAPH_DMA_START_1 0x00401004 +#define NV04_PGRAPH_DMA_LENGTH 0x00401008 +#define NV04_PGRAPH_DMA_MISC 0x0040100C +#define NV04_PGRAPH_DMA_DATA_0 0x00401020 +#define NV04_PGRAPH_DMA_DATA_1 0x00401024 +#define NV04_PGRAPH_DMA_RM 0x00401030 +#define NV04_PGRAPH_DMA_A_XLATE_INST 0x00401040 +#define NV04_PGRAPH_DMA_A_CONTROL 0x00401044 +#define NV04_PGRAPH_DMA_A_LIMIT 0x00401048 +#define NV04_PGRAPH_DMA_A_TLB_PTE 0x0040104C +#define NV04_PGRAPH_DMA_A_TLB_TAG 0x00401050 +#define NV04_PGRAPH_DMA_A_ADJ_OFFSET 0x00401054 +#define NV04_PGRAPH_DMA_A_OFFSET 0x00401058 +#define NV04_PGRAPH_DMA_A_SIZE 0x0040105C +#define NV04_PGRAPH_DMA_A_Y_SIZE 0x00401060 +#define NV04_PGRAPH_DMA_B_XLATE_INST 0x00401080 +#define NV04_PGRAPH_DMA_B_CONTROL 0x00401084 +#define NV04_PGRAPH_DMA_B_LIMIT 0x00401088 +#define NV04_PGRAPH_DMA_B_TLB_PTE 0x0040108C +#define NV04_PGRAPH_DMA_B_TLB_TAG 0x00401090 +#define NV04_PGRAPH_DMA_B_ADJ_OFFSET 0x00401094 +#define NV04_PGRAPH_DMA_B_OFFSET 0x00401098 +#define NV04_PGRAPH_DMA_B_SIZE 0x0040109C +#define NV04_PGRAPH_DMA_B_Y_SIZE 0x004010A0 +#define NV40_PGRAPH_TILE1(i) (0x00406900 + (i*16)) +#define NV40_PGRAPH_TLIMIT1(i) (0x00406904 + (i*16)) +#define NV40_PGRAPH_TSIZE1(i) (0x00406908 + (i*16)) +#define NV40_PGRAPH_TSTATUS1(i) (0x0040690C + (i*16)) + + +/* It's a guess that this works on NV03. Confirmed on NV04, though */ +#define NV04_PFIFO_DELAY_0 0x00002040 +#define NV04_PFIFO_DMA_TIMESLICE 0x00002044 +#define NV04_PFIFO_NEXT_CHANNEL 0x00002050 +#define NV03_PFIFO_INTR_0 0x00002100 +#define NV03_PFIFO_INTR_EN_0 0x00002140 +# define NV_PFIFO_INTR_CACHE_ERROR (1<<0) +# define NV_PFIFO_INTR_RUNOUT (1<<4) +# define NV_PFIFO_INTR_RUNOUT_OVERFLOW (1<<8) +# define NV_PFIFO_INTR_DMA_PUSHER (1<<12) +# define NV_PFIFO_INTR_DMA_PT (1<<16) +# define NV_PFIFO_INTR_SEMAPHORE (1<<20) +# define NV_PFIFO_INTR_ACQUIRE_TIMEOUT (1<<24) +#define NV03_PFIFO_RAMHT 0x00002210 +#define NV03_PFIFO_RAMFC 0x00002214 +#define NV03_PFIFO_RAMRO 0x00002218 +#define NV40_PFIFO_RAMFC 0x00002220 +#define NV03_PFIFO_CACHES 0x00002500 +#define NV04_PFIFO_MODE 0x00002504 +#define NV04_PFIFO_DMA 0x00002508 +#define NV04_PFIFO_SIZE 0x0000250c +#define NV50_PFIFO_CTX_TABLE(c) (0x2600+(c)*4) +#define NV50_PFIFO_CTX_TABLE__SIZE 128 +#define NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED (1<<31) +#define NV50_PFIFO_CTX_TABLE_UNK30_BAD (1<<30) +#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80 0x0FFFFFFF +#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84 0x00FFFFFF +#define NV03_PFIFO_CACHE0_PUSH0 0x00003000 +#define NV03_PFIFO_CACHE0_PULL0 0x00003040 +#define NV04_PFIFO_CACHE0_PULL0 0x00003050 +#define NV04_PFIFO_CACHE0_PULL1 0x00003054 +#define NV03_PFIFO_CACHE1_PUSH0 0x00003200 +#define NV03_PFIFO_CACHE1_PUSH1 0x00003204 +#define NV03_PFIFO_CACHE1_PUSH1_DMA (1<<8) +#define NV40_PFIFO_CACHE1_PUSH1_DMA (1<<16) +#define NV03_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000000f +#define NV10_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000001f +#define NV50_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000007f +#define NV03_PFIFO_CACHE1_PUT 0x00003210 +#define NV04_PFIFO_CACHE1_DMA_PUSH 0x00003220 +#define NV04_PFIFO_CACHE1_DMA_FETCH 0x00003224 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_8_BYTES 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_16_BYTES 0x00000008 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_24_BYTES 0x00000010 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_32_BYTES 0x00000018 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_40_BYTES 0x00000020 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_48_BYTES 0x00000028 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_56_BYTES 0x00000030 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_64_BYTES 0x00000038 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_72_BYTES 0x00000040 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_80_BYTES 0x00000048 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_88_BYTES 0x00000050 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_96_BYTES 0x00000058 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_104_BYTES 0x00000060 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES 0x00000068 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_120_BYTES 0x00000070 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES 0x00000078 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_136_BYTES 0x00000080 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_144_BYTES 0x00000088 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_152_BYTES 0x00000090 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_160_BYTES 0x00000098 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_168_BYTES 0x000000A0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_176_BYTES 0x000000A8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_184_BYTES 0x000000B0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_192_BYTES 0x000000B8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_200_BYTES 0x000000C0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_208_BYTES 0x000000C8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_216_BYTES 0x000000D0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_224_BYTES 0x000000D8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_232_BYTES 0x000000E0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_240_BYTES 0x000000E8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_248_BYTES 0x000000F0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_256_BYTES 0x000000F8 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE 0x0000E000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_32_BYTES 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_64_BYTES 0x00002000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_96_BYTES 0x00004000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES 0x00006000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_160_BYTES 0x00008000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_192_BYTES 0x0000A000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_224_BYTES 0x0000C000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_256_BYTES 0x0000E000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS 0x001F0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_0 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_1 0x00010000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_2 0x00020000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_3 0x00030000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 0x00040000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_5 0x00050000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_6 0x00060000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_7 0x00070000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 0x00080000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_9 0x00090000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_10 0x000A0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_11 0x000B0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_12 0x000C0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_13 0x000D0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_14 0x000E0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_15 0x000F0000 +# define NV_PFIFO_CACHE1_ENDIAN 0x80000000 +# define NV_PFIFO_CACHE1_LITTLE_ENDIAN 0x7FFFFFFF +# define NV_PFIFO_CACHE1_BIG_ENDIAN 0x80000000 +#define NV04_PFIFO_CACHE1_DMA_STATE 0x00003228 +#define NV04_PFIFO_CACHE1_DMA_INSTANCE 0x0000322c +#define NV04_PFIFO_CACHE1_DMA_CTL 0x00003230 +#define NV04_PFIFO_CACHE1_DMA_PUT 0x00003240 +#define NV04_PFIFO_CACHE1_DMA_GET 0x00003244 +#define NV10_PFIFO_CACHE1_REF_CNT 0x00003248 +#define NV10_PFIFO_CACHE1_DMA_SUBROUTINE 0x0000324C +#define NV03_PFIFO_CACHE1_PULL0 0x00003240 +#define NV04_PFIFO_CACHE1_PULL0 0x00003250 +#define NV03_PFIFO_CACHE1_PULL1 0x00003250 +#define NV04_PFIFO_CACHE1_PULL1 0x00003254 +#define NV04_PFIFO_CACHE1_HASH 0x00003258 +#define NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT 0x00003260 +#define NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP 0x00003264 +#define NV10_PFIFO_CACHE1_ACQUIRE_VALUE 0x00003268 +#define NV10_PFIFO_CACHE1_SEMAPHORE 0x0000326C +#define NV03_PFIFO_CACHE1_GET 0x00003270 +#define NV04_PFIFO_CACHE1_ENGINE 0x00003280 +#define NV04_PFIFO_CACHE1_DMA_DCOUNT 0x000032A0 +#define NV40_PFIFO_GRCTX_INSTANCE 0x000032E0 +#define NV40_PFIFO_UNK32E4 0x000032E4 +#define NV04_PFIFO_CACHE1_METHOD(i) (0x00003800+(i*8)) +#define NV04_PFIFO_CACHE1_DATA(i) (0x00003804+(i*8)) +#define NV40_PFIFO_CACHE1_METHOD(i) (0x00090000+(i*8)) +#define NV40_PFIFO_CACHE1_DATA(i) (0x00090004+(i*8)) + +#define NV_CRTC0_INTSTAT 0x00600100 +#define NV_CRTC0_INTEN 0x00600140 +#define NV_CRTC1_INTSTAT 0x00602100 +#define NV_CRTC1_INTEN 0x00602140 +# define NV_CRTC_INTR_VBLANK (1<<0) + +#define NV04_PRAMIN 0x00700000 + +/* Fifo commands. These are not regs, neither masks */ +#define NV03_FIFO_CMD_JUMP 0x20000000 +#define NV03_FIFO_CMD_JUMP_OFFSET_MASK 0x1ffffffc +#define NV03_FIFO_CMD_REWIND (NV03_FIFO_CMD_JUMP | (0 & NV03_FIFO_CMD_JUMP_OFFSET_MASK)) + +/* This is a partial import from rules-ng, a few things may be duplicated. + * Eventually we should completely import everything from rules-ng. + * For the moment check rules-ng for docs. + */ + +#define NV50_PMC 0x00000000 +#define NV50_PMC__LEN 0x1 +#define NV50_PMC__ESIZE 0x2000 +# define NV50_PMC_BOOT_0 0x00000000 +# define NV50_PMC_BOOT_0_REVISION 0x000000ff +# define NV50_PMC_BOOT_0_REVISION__SHIFT 0 +# define NV50_PMC_BOOT_0_ARCH 0x0ff00000 +# define NV50_PMC_BOOT_0_ARCH__SHIFT 20 +# define NV50_PMC_INTR_0 0x00000100 +# define NV50_PMC_INTR_0_PFIFO (1<<8) +# define NV50_PMC_INTR_0_PGRAPH (1<<12) +# define NV50_PMC_INTR_0_PTIMER (1<<20) +# define NV50_PMC_INTR_0_HOTPLUG (1<<21) +# define NV50_PMC_INTR_0_DISPLAY (1<<26) +# define NV50_PMC_INTR_EN_0 0x00000140 +# define NV50_PMC_INTR_EN_0_MASTER (1<<0) +# define NV50_PMC_INTR_EN_0_MASTER_DISABLED (0<<0) +# define NV50_PMC_INTR_EN_0_MASTER_ENABLED (1<<0) +# define NV50_PMC_ENABLE 0x00000200 +# define NV50_PMC_ENABLE_PFIFO (1<<8) +# define NV50_PMC_ENABLE_PGRAPH (1<<12) + +#define NV50_PCONNECTOR 0x0000e000 +#define NV50_PCONNECTOR__LEN 0x1 +#define NV50_PCONNECTOR__ESIZE 0x1000 +# define NV50_PCONNECTOR_HOTPLUG_INTR 0x0000e050 +# define NV50_PCONNECTOR_HOTPLUG_INTR_PLUG_I2C0 (1<<0) +# define NV50_PCONNECTOR_HOTPLUG_INTR_PLUG_I2C1 (1<<1) +# define NV50_PCONNECTOR_HOTPLUG_INTR_PLUG_I2C2 (1<<2) +# define NV50_PCONNECTOR_HOTPLUG_INTR_PLUG_I2C3 (1<<3) +# define NV50_PCONNECTOR_HOTPLUG_INTR_UNPLUG_I2C0 (1<<16) +# define NV50_PCONNECTOR_HOTPLUG_INTR_UNPLUG_I2C1 (1<<17) +# define NV50_PCONNECTOR_HOTPLUG_INTR_UNPLUG_I2C2 (1<<18) +# define NV50_PCONNECTOR_HOTPLUG_INTR_UNPLUG_I2C3 (1<<19) +# define NV50_PCONNECTOR_HOTPLUG_CTRL 0x0000e054 +# define NV50_PCONNECTOR_HOTPLUG_CTRL_PLUG_I2C0 (1<<0) +# define NV50_PCONNECTOR_HOTPLUG_CTRL_PLUG_I2C1 (1<<1) +# define NV50_PCONNECTOR_HOTPLUG_CTRL_PLUG_I2C2 (1<<2) +# define NV50_PCONNECTOR_HOTPLUG_CTRL_PLUG_I2C3 (1<<3) +# define NV50_PCONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C0 (1<<16) +# define NV50_PCONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C1 (1<<17) +# define NV50_PCONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C2 (1<<18) +# define NV50_PCONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C3 (1<<19) +# define NV50_PCONNECTOR_HOTPLUG_STATE 0x0000e104 +# define NV50_PCONNECTOR_HOTPLUG_STATE_PIN_CONNECTED_I2C0 (1<<2) +# define NV50_PCONNECTOR_HOTPLUG_STATE_PIN_CONNECTED_I2C1 (1<<6) +# define NV50_PCONNECTOR_HOTPLUG_STATE_PIN_CONNECTED_I2C2 (1<<10) +# define NV50_PCONNECTOR_HOTPLUG_STATE_PIN_CONNECTED_I2C3 (1<<14) +# define NV50_PCONNECTOR_I2C_PORT_0 0x0000e138 +# define NV50_PCONNECTOR_I2C_PORT_1 0x0000e150 +# define NV50_PCONNECTOR_I2C_PORT_2 0x0000e168 +# define NV50_PCONNECTOR_I2C_PORT_3 0x0000e180 +# define NV50_PCONNECTOR_I2C_PORT_4 0x0000e240 +# define NV50_PCONNECTOR_I2C_PORT_5 0x0000e258 + +#define NV50_AUXCH_DATA_OUT(i,n) ((n) * 4 + (i) * 0x50 + 0x0000e4c0) +#define NV50_AUXCH_DATA_OUT__SIZE 4 +#define NV50_AUXCH_DATA_IN(i,n) ((n) * 4 + (i) * 0x50 + 0x0000e4d0) +#define NV50_AUXCH_DATA_IN__SIZE 4 +#define NV50_AUXCH_ADDR(i) ((i) * 0x50 + 0x0000e4e0) +#define NV50_AUXCH_CTRL(i) ((i) * 0x50 + 0x0000e4e4) +#define NV50_AUXCH_CTRL_LINKSTAT 0x01000000 +#define NV50_AUXCH_CTRL_LINKSTAT_NOT_READY 0x00000000 +#define NV50_AUXCH_CTRL_LINKSTAT_READY 0x01000000 +#define NV50_AUXCH_CTRL_LINKEN 0x00100000 +#define NV50_AUXCH_CTRL_LINKEN_DISABLED 0x00000000 +#define NV50_AUXCH_CTRL_LINKEN_ENABLED 0x00100000 +#define NV50_AUXCH_CTRL_EXEC 0x00010000 +#define NV50_AUXCH_CTRL_EXEC_COMPLETE 0x00000000 +#define NV50_AUXCH_CTRL_EXEC_IN_PROCESS 0x00010000 +#define NV50_AUXCH_CTRL_CMD 0x0000f000 +#define NV50_AUXCH_CTRL_CMD_SHIFT 12 +#define NV50_AUXCH_CTRL_LEN 0x0000000f +#define NV50_AUXCH_CTRL_LEN_SHIFT 0 +#define NV50_AUXCH_STAT(i) ((i) * 0x50 + 0x0000e4e8) +#define NV50_AUXCH_STAT_STATE 0x10000000 +#define NV50_AUXCH_STAT_STATE_NOT_READY 0x00000000 +#define NV50_AUXCH_STAT_STATE_READY 0x10000000 +#define NV50_AUXCH_STAT_REPLY 0x000f0000 +#define NV50_AUXCH_STAT_REPLY_AUX 0x00030000 +#define NV50_AUXCH_STAT_REPLY_AUX_ACK 0x00000000 +#define NV50_AUXCH_STAT_REPLY_AUX_NACK 0x00010000 +#define NV50_AUXCH_STAT_REPLY_AUX_DEFER 0x00020000 +#define NV50_AUXCH_STAT_REPLY_I2C 0x000c0000 +#define NV50_AUXCH_STAT_REPLY_I2C_ACK 0x00000000 +#define NV50_AUXCH_STAT_REPLY_I2C_NACK 0x00040000 +#define NV50_AUXCH_STAT_REPLY_I2C_DEFER 0x00080000 +#define NV50_AUXCH_STAT_COUNT 0x0000001f + +#define NV50_PBUS 0x00088000 +#define NV50_PBUS__LEN 0x1 +#define NV50_PBUS__ESIZE 0x1000 +# define NV50_PBUS_PCI_ID 0x00088000 +# define NV50_PBUS_PCI_ID_VENDOR_ID 0x0000ffff +# define NV50_PBUS_PCI_ID_VENDOR_ID__SHIFT 0 +# define NV50_PBUS_PCI_ID_DEVICE_ID 0xffff0000 +# define NV50_PBUS_PCI_ID_DEVICE_ID__SHIFT 16 + +#define NV50_PFB 0x00100000 +#define NV50_PFB__LEN 0x1 +#define NV50_PFB__ESIZE 0x1000 + +#define NV50_PEXTDEV 0x00101000 +#define NV50_PEXTDEV__LEN 0x1 +#define NV50_PEXTDEV__ESIZE 0x1000 + +#define NV50_PROM 0x00300000 +#define NV50_PROM__LEN 0x1 +#define NV50_PROM__ESIZE 0x10000 + +#define NV50_PGRAPH 0x00400000 +#define NV50_PGRAPH__LEN 0x1 +#define NV50_PGRAPH__ESIZE 0x10000 + +#define NV50_PDISPLAY 0x00610000 +#define NV50_PDISPLAY_OBJECTS 0x00610010 +#define NV50_PDISPLAY_INTR_0 0x00610020 +#define NV50_PDISPLAY_INTR_1 0x00610024 +#define NV50_PDISPLAY_INTR_1_VBLANK_CRTC 0x0000000c +#define NV50_PDISPLAY_INTR_1_VBLANK_CRTC_SHIFT 2 +#define NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(n) (1 << ((n) + 2)) +#define NV50_PDISPLAY_INTR_1_VBLANK_CRTC_0 0x00000004 +#define NV50_PDISPLAY_INTR_1_VBLANK_CRTC_1 0x00000008 +#define NV50_PDISPLAY_INTR_1_CLK_UNK10 0x00000010 +#define NV50_PDISPLAY_INTR_1_CLK_UNK20 0x00000020 +#define NV50_PDISPLAY_INTR_1_CLK_UNK40 0x00000040 +#define NV50_PDISPLAY_INTR_EN 0x0061002c +#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC 0x0000000c +#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(n) (1 << ((n) + 2)) +#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_0 0x00000004 +#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_1 0x00000008 +#define NV50_PDISPLAY_INTR_EN_CLK_UNK10 0x00000010 +#define NV50_PDISPLAY_INTR_EN_CLK_UNK20 0x00000020 +#define NV50_PDISPLAY_INTR_EN_CLK_UNK40 0x00000040 +#define NV50_PDISPLAY_UNK30_CTRL 0x00610030 +#define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK0 0x00000200 +#define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK1 0x00000400 +#define NV50_PDISPLAY_UNK30_CTRL_PENDING 0x80000000 +#define NV50_PDISPLAY_TRAPPED_ADDR 0x00610080 +#define NV50_PDISPLAY_TRAPPED_DATA 0x00610084 +#define NV50_PDISPLAY_CHANNEL_STAT(i) ((i) * 0x10 + 0x00610200) +#define NV50_PDISPLAY_CHANNEL_STAT_DMA 0x00000010 +#define NV50_PDISPLAY_CHANNEL_STAT_DMA_DISABLED 0x00000000 +#define NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED 0x00000010 +#define NV50_PDISPLAY_CHANNEL_DMA_CB(i) ((i) * 0x10 + 0x00610204) +#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION 0x00000002 +#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM 0x00000000 +#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_SYSTEM 0x00000002 +#define NV50_PDISPLAY_CHANNEL_DMA_CB_VALID 0x00000001 +#define NV50_PDISPLAY_CHANNEL_UNK2(i) ((i) * 0x10 + 0x00610208) +#define NV50_PDISPLAY_CHANNEL_UNK3(i) ((i) * 0x10 + 0x0061020c) + +#define NV50_PDISPLAY_CURSOR 0x00610270 +#define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i) ((i) * 0x10 + 0x00610270) +#define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON 0x00000001 +#define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS 0x00030000 +#define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE 0x00010000 + +#define NV50_PDISPLAY_CTRL_STATE 0x00610300 +#define NV50_PDISPLAY_CTRL_STATE_PENDING 0x80000000 +#define NV50_PDISPLAY_CTRL_STATE_METHOD 0x00001ffc +#define NV50_PDISPLAY_CTRL_STATE_ENABLE 0x00000001 +#define NV50_PDISPLAY_CTRL_VAL 0x00610304 +#define NV50_PDISPLAY_UNK_380 0x00610380 +#define NV50_PDISPLAY_RAM_AMOUNT 0x00610384 +#define NV50_PDISPLAY_UNK_388 0x00610388 +#define NV50_PDISPLAY_UNK_38C 0x0061038c + +#define NV50_PDISPLAY_CRTC_P(i, r) ((i) * 0x540 + NV50_PDISPLAY_CRTC_##r) +#define NV50_PDISPLAY_CRTC_C(i, r) (4 + (i) * 0x540 + NV50_PDISPLAY_CRTC_##r) +#define NV50_PDISPLAY_CRTC_UNK_0A18 /* mthd 0x0900 */ 0x00610a18 +#define NV50_PDISPLAY_CRTC_CLUT_MODE 0x00610a24 +#define NV50_PDISPLAY_CRTC_INTERLACE 0x00610a48 +#define NV50_PDISPLAY_CRTC_SCALE_CTRL 0x00610a50 +#define NV50_PDISPLAY_CRTC_CURSOR_CTRL 0x00610a58 +#define NV50_PDISPLAY_CRTC_UNK0A78 /* mthd 0x0904 */ 0x00610a78 +#define NV50_PDISPLAY_CRTC_UNK0AB8 0x00610ab8 +#define NV50_PDISPLAY_CRTC_DEPTH 0x00610ac8 +#define NV50_PDISPLAY_CRTC_CLOCK 0x00610ad0 +#define NV50_PDISPLAY_CRTC_COLOR_CTRL 0x00610ae0 +#define NV50_PDISPLAY_CRTC_SYNC_START_TO_BLANK_END 0x00610ae8 +#define NV50_PDISPLAY_CRTC_MODE_UNK1 0x00610af0 +#define NV50_PDISPLAY_CRTC_DISPLAY_TOTAL 0x00610af8 +#define NV50_PDISPLAY_CRTC_SYNC_DURATION 0x00610b00 +#define NV50_PDISPLAY_CRTC_MODE_UNK2 0x00610b08 +#define NV50_PDISPLAY_CRTC_UNK_0B10 /* mthd 0x0828 */ 0x00610b10 +#define NV50_PDISPLAY_CRTC_FB_SIZE 0x00610b18 +#define NV50_PDISPLAY_CRTC_FB_PITCH 0x00610b20 +#define NV50_PDISPLAY_CRTC_FB_PITCH_LINEAR 0x00100000 +#define NV50_PDISPLAY_CRTC_FB_POS 0x00610b28 +#define NV50_PDISPLAY_CRTC_SCALE_CENTER_OFFSET 0x00610b38 +#define NV50_PDISPLAY_CRTC_REAL_RES 0x00610b40 +#define NV50_PDISPLAY_CRTC_SCALE_RES1 0x00610b48 +#define NV50_PDISPLAY_CRTC_SCALE_RES2 0x00610b50 + +#define NV50_PDISPLAY_DAC_MODE_CTRL_P(i) (0x00610b58 + (i) * 0x8) +#define NV50_PDISPLAY_DAC_MODE_CTRL_C(i) (0x00610b5c + (i) * 0x8) +#define NV50_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610b70 + (i) * 0x8) +#define NV50_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610b74 + (i) * 0x8) +#define NV50_PDISPLAY_DAC_MODE_CTRL2_P(i) (0x00610bdc + (i) * 0x8) +#define NV50_PDISPLAY_DAC_MODE_CTRL2_C(i) (0x00610be0 + (i) * 0x8) + +#define NV90_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610794 + (i) * 0x8) +#define NV90_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610798 + (i) * 0x8) +#define NV90_PDISPLAY_DAC_MODE_CTRL_P(i) (0x00610b58 + (i) * 0x8) +#define NV90_PDISPLAY_DAC_MODE_CTRL_C(i) (0x00610b5c + (i) * 0x8) +#define NV90_PDISPLAY_DAC_MODE_CTRL2_P(i) (0x00610b80 + (i) * 0x8) +#define NV90_PDISPLAY_DAC_MODE_CTRL2_C(i) (0x00610b84 + (i) * 0x8) + +#define NV50_PDISPLAY_CRTC_CLK 0x00614000 +#define NV50_PDISPLAY_CRTC_CLK_CTRL1(i) ((i) * 0x800 + 0x614100) +#define NV50_PDISPLAY_CRTC_CLK_CTRL1_CONNECTED 0x00000600 +#define NV50_PDISPLAY_CRTC_CLK_VPLL_A(i) ((i) * 0x800 + 0x614104) +#define NV50_PDISPLAY_CRTC_CLK_VPLL_B(i) ((i) * 0x800 + 0x614108) +#define NV50_PDISPLAY_CRTC_CLK_CTRL2(i) ((i) * 0x800 + 0x614200) + +#define NV50_PDISPLAY_DAC_CLK 0x00614000 +#define NV50_PDISPLAY_DAC_CLK_CTRL2(i) ((i) * 0x800 + 0x614280) + +#define NV50_PDISPLAY_SOR_CLK 0x00614000 +#define NV50_PDISPLAY_SOR_CLK_CTRL2(i) ((i) * 0x800 + 0x614300) + +#define NV50_PDISPLAY_VGACRTC(r) ((r) + 0x619400) + +#define NV50_PDISPLAY_DAC 0x0061a000 +#define NV50_PDISPLAY_DAC_DPMS_CTRL(i) (0x0061a004 + (i) * 0x800) +#define NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF 0x00000001 +#define NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF 0x00000004 +#define NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED 0x00000010 +#define NV50_PDISPLAY_DAC_DPMS_CTRL_OFF 0x00000040 +#define NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING 0x80000000 +#define NV50_PDISPLAY_DAC_LOAD_CTRL(i) (0x0061a00c + (i) * 0x800) +#define NV50_PDISPLAY_DAC_LOAD_CTRL_ACTIVE 0x00100000 +#define NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT 0x38000000 +#define NV50_PDISPLAY_DAC_LOAD_CTRL_DONE 0x80000000 +#define NV50_PDISPLAY_DAC_CLK_CTRL1(i) (0x0061a010 + (i) * 0x800) +#define NV50_PDISPLAY_DAC_CLK_CTRL1_CONNECTED 0x00000600 + +#define NV50_PDISPLAY_SOR 0x0061c000 +#define NV50_PDISPLAY_SOR_DPMS_CTRL(i) (0x0061c004 + (i) * 0x800) +#define NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING 0x80000000 +#define NV50_PDISPLAY_SOR_DPMS_CTRL_ON 0x00000001 +#define NV50_PDISPLAY_SOR_CLK_CTRL1(i) (0x0061c008 + (i) * 0x800) +#define NV50_PDISPLAY_SOR_CLK_CTRL1_CONNECTED 0x00000600 +#define NV50_PDISPLAY_SOR_DPMS_STATE(i) (0x0061c030 + (i) * 0x800) +#define NV50_PDISPLAY_SOR_DPMS_STATE_ACTIVE 0x00030000 +#define NV50_PDISPLAY_SOR_DPMS_STATE_BLANKED 0x00080000 +#define NV50_PDISPLAY_SOR_DPMS_STATE_WAIT 0x10000000 +#define NV50_PDISPLAY_SOR_BACKLIGHT 0x0061c084 +#define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000 +#define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff +#define NV50_SOR_DP_CTRL(i,l) (0x0061c10c + (i) * 0x800 + (l) * 0x80) +#define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000 +#define NV50_SOR_DP_CTRL_LANE_MASK 0x001f0000 +#define NV50_SOR_DP_CTRL_LANE_0_ENABLED 0x00010000 +#define NV50_SOR_DP_CTRL_LANE_1_ENABLED 0x00020000 +#define NV50_SOR_DP_CTRL_LANE_2_ENABLED 0x00040000 +#define NV50_SOR_DP_CTRL_LANE_3_ENABLED 0x00080000 +#define NV50_SOR_DP_CTRL_TRAINING_PATTERN 0x0f000000 +#define NV50_SOR_DP_CTRL_TRAINING_PATTERN_DISABLED 0x00000000 +#define NV50_SOR_DP_CTRL_TRAINING_PATTERN_1 0x01000000 +#define NV50_SOR_DP_CTRL_TRAINING_PATTERN_2 0x02000000 +#define NV50_SOR_DP_UNK118(i,l) (0x0061c118 + (i) * 0x800 + (l) * 0x80) +#define NV50_SOR_DP_UNK120(i,l) (0x0061c120 + (i) * 0x800 + (l) * 0x80) +#define NV50_SOR_DP_UNK130(i,l) (0x0061c130 + (i) * 0x800 + (l) * 0x80) + +#define NV50_PDISPLAY_USER(i) ((i) * 0x1000 + 0x00640000) +#define NV50_PDISPLAY_USER_PUT(i) ((i) * 0x1000 + 0x00640000) +#define NV50_PDISPLAY_USER_GET(i) ((i) * 0x1000 + 0x00640004) + +#define NV50_PDISPLAY_CURSOR_USER 0x00647000 +#define NV50_PDISPLAY_CURSOR_USER_POS_CTRL(i) ((i) * 0x1000 + 0x00647080) +#define NV50_PDISPLAY_CURSOR_USER_POS(i) ((i) * 0x1000 + 0x00647084) diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c new file mode 100644 index 0000000000000000000000000000000000000000..4c7f1e403e804633ef086417275e7b48a5f127a2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -0,0 +1,321 @@ +#include "drmP.h" +#include "nouveau_drv.h" +#include + +#define NV_CTXDMA_PAGE_SHIFT 12 +#define NV_CTXDMA_PAGE_SIZE (1 << NV_CTXDMA_PAGE_SHIFT) +#define NV_CTXDMA_PAGE_MASK (NV_CTXDMA_PAGE_SIZE - 1) + +struct nouveau_sgdma_be { + struct ttm_backend backend; + struct drm_device *dev; + + dma_addr_t *pages; + unsigned nr_pages; + + unsigned pte_start; + bool bound; +}; + +static int +nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages, + struct page **pages, struct page *dummy_read_page) +{ + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct drm_device *dev = nvbe->dev; + + NV_DEBUG(nvbe->dev, "num_pages = %ld\n", num_pages); + + if (nvbe->pages) + return -EINVAL; + + nvbe->pages = kmalloc(sizeof(dma_addr_t) * num_pages, GFP_KERNEL); + if (!nvbe->pages) + return -ENOMEM; + + nvbe->nr_pages = 0; + while (num_pages--) { + nvbe->pages[nvbe->nr_pages] = + pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(dev->pdev, + nvbe->pages[nvbe->nr_pages])) { + be->func->clear(be); + return -EFAULT; + } + + nvbe->nr_pages++; + } + + return 0; +} + +static void +nouveau_sgdma_clear(struct ttm_backend *be) +{ + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct drm_device *dev = nvbe->dev; + + NV_DEBUG(nvbe->dev, "\n"); + + if (nvbe && nvbe->pages) { + if (nvbe->bound) + be->func->unbind(be); + + while (nvbe->nr_pages--) { + pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages], + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + } + kfree(nvbe->pages); + nvbe->pages = NULL; + nvbe->nr_pages = 0; + } +} + +static inline unsigned +nouveau_sgdma_pte(struct drm_device *dev, uint64_t offset) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + unsigned pte = (offset >> NV_CTXDMA_PAGE_SHIFT); + + if (dev_priv->card_type < NV_50) + return pte + 2; + + return pte << 1; +} + +static int +nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) +{ + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct drm_device *dev = nvbe->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; + unsigned i, j, pte; + + NV_DEBUG(dev, "pg=0x%lx\n", mem->mm_node->start); + + dev_priv->engine.instmem.prepare_access(nvbe->dev, true); + pte = nouveau_sgdma_pte(nvbe->dev, mem->mm_node->start << PAGE_SHIFT); + nvbe->pte_start = pte; + for (i = 0; i < nvbe->nr_pages; i++) { + dma_addr_t dma_offset = nvbe->pages[i]; + uint32_t offset_l = lower_32_bits(dma_offset); + uint32_t offset_h = upper_32_bits(dma_offset); + + for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) { + if (dev_priv->card_type < NV_50) + nv_wo32(dev, gpuobj, pte++, offset_l | 3); + else { + nv_wo32(dev, gpuobj, pte++, offset_l | 0x21); + nv_wo32(dev, gpuobj, pte++, offset_h & 0xff); + } + + dma_offset += NV_CTXDMA_PAGE_SIZE; + } + } + dev_priv->engine.instmem.finish_access(nvbe->dev); + + if (dev_priv->card_type == NV_50) { + nv_wr32(dev, 0x100c80, 0x00050001); + if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { + NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); + NV_ERROR(dev, "0x100c80 = 0x%08x\n", + nv_rd32(dev, 0x100c80)); + return -EBUSY; + } + + nv_wr32(dev, 0x100c80, 0x00000001); + if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { + NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); + NV_ERROR(dev, "0x100c80 = 0x%08x\n", + nv_rd32(dev, 0x100c80)); + return -EBUSY; + } + } + + nvbe->bound = true; + return 0; +} + +static int +nouveau_sgdma_unbind(struct ttm_backend *be) +{ + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct drm_device *dev = nvbe->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; + unsigned i, j, pte; + + NV_DEBUG(dev, "\n"); + + if (!nvbe->bound) + return 0; + + dev_priv->engine.instmem.prepare_access(nvbe->dev, true); + pte = nvbe->pte_start; + for (i = 0; i < nvbe->nr_pages; i++) { + dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus; + + for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) { + if (dev_priv->card_type < NV_50) + nv_wo32(dev, gpuobj, pte++, dma_offset | 3); + else { + nv_wo32(dev, gpuobj, pte++, dma_offset | 0x21); + nv_wo32(dev, gpuobj, pte++, 0x00000000); + } + + dma_offset += NV_CTXDMA_PAGE_SIZE; + } + } + dev_priv->engine.instmem.finish_access(nvbe->dev); + + nvbe->bound = false; + return 0; +} + +static void +nouveau_sgdma_destroy(struct ttm_backend *be) +{ + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + + if (be) { + NV_DEBUG(nvbe->dev, "\n"); + + if (nvbe) { + if (nvbe->pages) + be->func->clear(be); + kfree(nvbe); + } + } +} + +static struct ttm_backend_func nouveau_sgdma_backend = { + .populate = nouveau_sgdma_populate, + .clear = nouveau_sgdma_clear, + .bind = nouveau_sgdma_bind, + .unbind = nouveau_sgdma_unbind, + .destroy = nouveau_sgdma_destroy +}; + +struct ttm_backend * +nouveau_sgdma_init_ttm(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_sgdma_be *nvbe; + + if (!dev_priv->gart_info.sg_ctxdma) + return NULL; + + nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL); + if (!nvbe) + return NULL; + + nvbe->dev = dev; + + nvbe->backend.func = &nouveau_sgdma_backend; + + return &nvbe->backend; +} + +int +nouveau_sgdma_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = NULL; + uint32_t aper_size, obj_size; + int i, ret; + + if (dev_priv->card_type < NV_50) { + aper_size = (64 * 1024 * 1024); + obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4; + obj_size += 8; /* ctxdma header */ + } else { + /* 1 entire VM page table */ + aper_size = (512 * 1024 * 1024); + obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 8; + } + + ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, + NVOBJ_FLAG_ALLOW_NO_REFS | + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &gpuobj); + if (ret) { + NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); + return ret; + } + + dev_priv->gart_info.sg_dummy_page = + alloc_page(GFP_KERNEL|__GFP_DMA32); + set_bit(PG_locked, &dev_priv->gart_info.sg_dummy_page->flags); + dev_priv->gart_info.sg_dummy_bus = + pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + + dev_priv->engine.instmem.prepare_access(dev, true); + if (dev_priv->card_type < NV_50) { + /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and + * confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE + * on those cards? */ + nv_wo32(dev, gpuobj, 0, NV_CLASS_DMA_IN_MEMORY | + (1 << 12) /* PT present */ | + (0 << 13) /* PT *not* linear */ | + (NV_DMA_ACCESS_RW << 14) | + (NV_DMA_TARGET_PCI << 16)); + nv_wo32(dev, gpuobj, 1, aper_size - 1); + for (i = 2; i < 2 + (aper_size >> 12); i++) { + nv_wo32(dev, gpuobj, i, + dev_priv->gart_info.sg_dummy_bus | 3); + } + } else { + for (i = 0; i < obj_size; i += 8) { + nv_wo32(dev, gpuobj, (i+0)/4, + dev_priv->gart_info.sg_dummy_bus | 0x21); + nv_wo32(dev, gpuobj, (i+4)/4, 0); + } + } + dev_priv->engine.instmem.finish_access(dev); + + dev_priv->gart_info.type = NOUVEAU_GART_SGDMA; + dev_priv->gart_info.aper_base = 0; + dev_priv->gart_info.aper_size = aper_size; + dev_priv->gart_info.sg_ctxdma = gpuobj; + return 0; +} + +void +nouveau_sgdma_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->gart_info.sg_dummy_page) { + pci_unmap_page(dev->pdev, dev_priv->gart_info.sg_dummy_bus, + NV_CTXDMA_PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + unlock_page(dev_priv->gart_info.sg_dummy_page); + __free_page(dev_priv->gart_info.sg_dummy_page); + dev_priv->gart_info.sg_dummy_page = NULL; + dev_priv->gart_info.sg_dummy_bus = 0; + } + + nouveau_gpuobj_del(dev, &dev_priv->gart_info.sg_ctxdma); +} + +int +nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; + struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; + int pte; + + pte = (offset >> NV_CTXDMA_PAGE_SHIFT); + if (dev_priv->card_type < NV_50) { + instmem->prepare_access(dev, false); + *page = nv_ro32(dev, gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK; + instmem->finish_access(dev); + return 0; + } + + NV_ERROR(dev, "Unimplemented on NV50\n"); + return -EINVAL; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c new file mode 100644 index 0000000000000000000000000000000000000000..2ed41d339f6a6e8edcb4c474d3566cc8e515c6ed --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -0,0 +1,811 @@ +/* + * Copyright 2005 Stephane Marchesin + * Copyright 2008 Stuart Bennett + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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 +#include "drmP.h" +#include "drm.h" +#include "drm_sarea.h" +#include "drm_crtc_helper.h" +#include + +#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nv50_display.h" + +static int nouveau_stub_init(struct drm_device *dev) { return 0; } +static void nouveau_stub_takedown(struct drm_device *dev) {} + +static int nouveau_init_engine_ptrs(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->engine; + + switch (dev_priv->chipset & 0xf0) { + case 0x00: + engine->instmem.init = nv04_instmem_init; + engine->instmem.takedown = nv04_instmem_takedown; + engine->instmem.suspend = nv04_instmem_suspend; + engine->instmem.resume = nv04_instmem_resume; + engine->instmem.populate = nv04_instmem_populate; + engine->instmem.clear = nv04_instmem_clear; + engine->instmem.bind = nv04_instmem_bind; + engine->instmem.unbind = nv04_instmem_unbind; + engine->instmem.prepare_access = nv04_instmem_prepare_access; + engine->instmem.finish_access = nv04_instmem_finish_access; + engine->mc.init = nv04_mc_init; + engine->mc.takedown = nv04_mc_takedown; + engine->timer.init = nv04_timer_init; + engine->timer.read = nv04_timer_read; + engine->timer.takedown = nv04_timer_takedown; + engine->fb.init = nv04_fb_init; + engine->fb.takedown = nv04_fb_takedown; + engine->graph.grclass = nv04_graph_grclass; + engine->graph.init = nv04_graph_init; + engine->graph.takedown = nv04_graph_takedown; + engine->graph.fifo_access = nv04_graph_fifo_access; + engine->graph.channel = nv04_graph_channel; + engine->graph.create_context = nv04_graph_create_context; + engine->graph.destroy_context = nv04_graph_destroy_context; + engine->graph.load_context = nv04_graph_load_context; + engine->graph.unload_context = nv04_graph_unload_context; + engine->fifo.channels = 16; + engine->fifo.init = nv04_fifo_init; + engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.disable = nv04_fifo_disable; + engine->fifo.enable = nv04_fifo_enable; + engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.channel_id = nv04_fifo_channel_id; + engine->fifo.create_context = nv04_fifo_create_context; + engine->fifo.destroy_context = nv04_fifo_destroy_context; + engine->fifo.load_context = nv04_fifo_load_context; + engine->fifo.unload_context = nv04_fifo_unload_context; + break; + case 0x10: + engine->instmem.init = nv04_instmem_init; + engine->instmem.takedown = nv04_instmem_takedown; + engine->instmem.suspend = nv04_instmem_suspend; + engine->instmem.resume = nv04_instmem_resume; + engine->instmem.populate = nv04_instmem_populate; + engine->instmem.clear = nv04_instmem_clear; + engine->instmem.bind = nv04_instmem_bind; + engine->instmem.unbind = nv04_instmem_unbind; + engine->instmem.prepare_access = nv04_instmem_prepare_access; + engine->instmem.finish_access = nv04_instmem_finish_access; + engine->mc.init = nv04_mc_init; + engine->mc.takedown = nv04_mc_takedown; + engine->timer.init = nv04_timer_init; + engine->timer.read = nv04_timer_read; + engine->timer.takedown = nv04_timer_takedown; + engine->fb.init = nv10_fb_init; + engine->fb.takedown = nv10_fb_takedown; + engine->graph.grclass = nv10_graph_grclass; + engine->graph.init = nv10_graph_init; + engine->graph.takedown = nv10_graph_takedown; + engine->graph.channel = nv10_graph_channel; + engine->graph.create_context = nv10_graph_create_context; + engine->graph.destroy_context = nv10_graph_destroy_context; + engine->graph.fifo_access = nv04_graph_fifo_access; + engine->graph.load_context = nv10_graph_load_context; + engine->graph.unload_context = nv10_graph_unload_context; + engine->fifo.channels = 32; + engine->fifo.init = nv10_fifo_init; + engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.disable = nv04_fifo_disable; + engine->fifo.enable = nv04_fifo_enable; + engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.channel_id = nv10_fifo_channel_id; + engine->fifo.create_context = nv10_fifo_create_context; + engine->fifo.destroy_context = nv10_fifo_destroy_context; + engine->fifo.load_context = nv10_fifo_load_context; + engine->fifo.unload_context = nv10_fifo_unload_context; + break; + case 0x20: + engine->instmem.init = nv04_instmem_init; + engine->instmem.takedown = nv04_instmem_takedown; + engine->instmem.suspend = nv04_instmem_suspend; + engine->instmem.resume = nv04_instmem_resume; + engine->instmem.populate = nv04_instmem_populate; + engine->instmem.clear = nv04_instmem_clear; + engine->instmem.bind = nv04_instmem_bind; + engine->instmem.unbind = nv04_instmem_unbind; + engine->instmem.prepare_access = nv04_instmem_prepare_access; + engine->instmem.finish_access = nv04_instmem_finish_access; + engine->mc.init = nv04_mc_init; + engine->mc.takedown = nv04_mc_takedown; + engine->timer.init = nv04_timer_init; + engine->timer.read = nv04_timer_read; + engine->timer.takedown = nv04_timer_takedown; + engine->fb.init = nv10_fb_init; + engine->fb.takedown = nv10_fb_takedown; + engine->graph.grclass = nv20_graph_grclass; + engine->graph.init = nv20_graph_init; + engine->graph.takedown = nv20_graph_takedown; + engine->graph.channel = nv10_graph_channel; + engine->graph.create_context = nv20_graph_create_context; + engine->graph.destroy_context = nv20_graph_destroy_context; + engine->graph.fifo_access = nv04_graph_fifo_access; + engine->graph.load_context = nv20_graph_load_context; + engine->graph.unload_context = nv20_graph_unload_context; + engine->fifo.channels = 32; + engine->fifo.init = nv10_fifo_init; + engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.disable = nv04_fifo_disable; + engine->fifo.enable = nv04_fifo_enable; + engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.channel_id = nv10_fifo_channel_id; + engine->fifo.create_context = nv10_fifo_create_context; + engine->fifo.destroy_context = nv10_fifo_destroy_context; + engine->fifo.load_context = nv10_fifo_load_context; + engine->fifo.unload_context = nv10_fifo_unload_context; + break; + case 0x30: + engine->instmem.init = nv04_instmem_init; + engine->instmem.takedown = nv04_instmem_takedown; + engine->instmem.suspend = nv04_instmem_suspend; + engine->instmem.resume = nv04_instmem_resume; + engine->instmem.populate = nv04_instmem_populate; + engine->instmem.clear = nv04_instmem_clear; + engine->instmem.bind = nv04_instmem_bind; + engine->instmem.unbind = nv04_instmem_unbind; + engine->instmem.prepare_access = nv04_instmem_prepare_access; + engine->instmem.finish_access = nv04_instmem_finish_access; + engine->mc.init = nv04_mc_init; + engine->mc.takedown = nv04_mc_takedown; + engine->timer.init = nv04_timer_init; + engine->timer.read = nv04_timer_read; + engine->timer.takedown = nv04_timer_takedown; + engine->fb.init = nv10_fb_init; + engine->fb.takedown = nv10_fb_takedown; + engine->graph.grclass = nv30_graph_grclass; + engine->graph.init = nv30_graph_init; + engine->graph.takedown = nv20_graph_takedown; + engine->graph.fifo_access = nv04_graph_fifo_access; + engine->graph.channel = nv10_graph_channel; + engine->graph.create_context = nv20_graph_create_context; + engine->graph.destroy_context = nv20_graph_destroy_context; + engine->graph.load_context = nv20_graph_load_context; + engine->graph.unload_context = nv20_graph_unload_context; + engine->fifo.channels = 32; + engine->fifo.init = nv10_fifo_init; + engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.disable = nv04_fifo_disable; + engine->fifo.enable = nv04_fifo_enable; + engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.channel_id = nv10_fifo_channel_id; + engine->fifo.create_context = nv10_fifo_create_context; + engine->fifo.destroy_context = nv10_fifo_destroy_context; + engine->fifo.load_context = nv10_fifo_load_context; + engine->fifo.unload_context = nv10_fifo_unload_context; + break; + case 0x40: + case 0x60: + engine->instmem.init = nv04_instmem_init; + engine->instmem.takedown = nv04_instmem_takedown; + engine->instmem.suspend = nv04_instmem_suspend; + engine->instmem.resume = nv04_instmem_resume; + engine->instmem.populate = nv04_instmem_populate; + engine->instmem.clear = nv04_instmem_clear; + engine->instmem.bind = nv04_instmem_bind; + engine->instmem.unbind = nv04_instmem_unbind; + engine->instmem.prepare_access = nv04_instmem_prepare_access; + engine->instmem.finish_access = nv04_instmem_finish_access; + engine->mc.init = nv40_mc_init; + engine->mc.takedown = nv40_mc_takedown; + engine->timer.init = nv04_timer_init; + engine->timer.read = nv04_timer_read; + engine->timer.takedown = nv04_timer_takedown; + engine->fb.init = nv40_fb_init; + engine->fb.takedown = nv40_fb_takedown; + engine->graph.grclass = nv40_graph_grclass; + engine->graph.init = nv40_graph_init; + engine->graph.takedown = nv40_graph_takedown; + engine->graph.fifo_access = nv04_graph_fifo_access; + engine->graph.channel = nv40_graph_channel; + engine->graph.create_context = nv40_graph_create_context; + engine->graph.destroy_context = nv40_graph_destroy_context; + engine->graph.load_context = nv40_graph_load_context; + engine->graph.unload_context = nv40_graph_unload_context; + engine->fifo.channels = 32; + engine->fifo.init = nv40_fifo_init; + engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.disable = nv04_fifo_disable; + engine->fifo.enable = nv04_fifo_enable; + engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.channel_id = nv10_fifo_channel_id; + engine->fifo.create_context = nv40_fifo_create_context; + engine->fifo.destroy_context = nv40_fifo_destroy_context; + engine->fifo.load_context = nv40_fifo_load_context; + engine->fifo.unload_context = nv40_fifo_unload_context; + break; + case 0x50: + case 0x80: /* gotta love NVIDIA's consistency.. */ + case 0x90: + case 0xA0: + engine->instmem.init = nv50_instmem_init; + engine->instmem.takedown = nv50_instmem_takedown; + engine->instmem.suspend = nv50_instmem_suspend; + engine->instmem.resume = nv50_instmem_resume; + engine->instmem.populate = nv50_instmem_populate; + engine->instmem.clear = nv50_instmem_clear; + engine->instmem.bind = nv50_instmem_bind; + engine->instmem.unbind = nv50_instmem_unbind; + engine->instmem.prepare_access = nv50_instmem_prepare_access; + engine->instmem.finish_access = nv50_instmem_finish_access; + engine->mc.init = nv50_mc_init; + engine->mc.takedown = nv50_mc_takedown; + engine->timer.init = nv04_timer_init; + engine->timer.read = nv04_timer_read; + engine->timer.takedown = nv04_timer_takedown; + engine->fb.init = nouveau_stub_init; + engine->fb.takedown = nouveau_stub_takedown; + engine->graph.grclass = nv50_graph_grclass; + engine->graph.init = nv50_graph_init; + engine->graph.takedown = nv50_graph_takedown; + engine->graph.fifo_access = nv50_graph_fifo_access; + engine->graph.channel = nv50_graph_channel; + engine->graph.create_context = nv50_graph_create_context; + engine->graph.destroy_context = nv50_graph_destroy_context; + engine->graph.load_context = nv50_graph_load_context; + engine->graph.unload_context = nv50_graph_unload_context; + engine->fifo.channels = 128; + engine->fifo.init = nv50_fifo_init; + engine->fifo.takedown = nv50_fifo_takedown; + engine->fifo.disable = nv04_fifo_disable; + engine->fifo.enable = nv04_fifo_enable; + engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.channel_id = nv50_fifo_channel_id; + engine->fifo.create_context = nv50_fifo_create_context; + engine->fifo.destroy_context = nv50_fifo_destroy_context; + engine->fifo.load_context = nv50_fifo_load_context; + engine->fifo.unload_context = nv50_fifo_unload_context; + break; + default: + NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); + return 1; + } + + return 0; +} + +static unsigned int +nouveau_vga_set_decode(void *priv, bool state) +{ + if (state) + return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | + VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; + else + return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; +} + +int +nouveau_card_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine; + struct nouveau_gpuobj *gpuobj; + int ret; + + NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state); + + if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE) + return 0; + + vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); + + /* Initialise internal driver API hooks */ + ret = nouveau_init_engine_ptrs(dev); + if (ret) + return ret; + engine = &dev_priv->engine; + dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED; + + /* Parse BIOS tables / Run init tables if card not POSTed */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + ret = nouveau_bios_init(dev); + if (ret) + return ret; + } + + ret = nouveau_gpuobj_early_init(dev); + if (ret) + return ret; + + /* Initialise instance memory, must happen before mem_init so we + * know exactly how much VRAM we're able to use for "normal" + * purposes. + */ + ret = engine->instmem.init(dev); + if (ret) + return ret; + + /* Setup the memory manager */ + ret = nouveau_mem_init(dev); + if (ret) + return ret; + + ret = nouveau_gpuobj_init(dev); + if (ret) + return ret; + + /* PMC */ + ret = engine->mc.init(dev); + if (ret) + return ret; + + /* PTIMER */ + ret = engine->timer.init(dev); + if (ret) + return ret; + + /* PFB */ + ret = engine->fb.init(dev); + if (ret) + return ret; + + /* PGRAPH */ + ret = engine->graph.init(dev); + if (ret) + return ret; + + /* PFIFO */ + ret = engine->fifo.init(dev); + if (ret) + return ret; + + /* this call irq_preinstall, register irq handler and + * call irq_postinstall + */ + ret = drm_irq_install(dev); + if (ret) + return ret; + + ret = drm_vblank_init(dev, 0); + if (ret) + return ret; + + /* what about PVIDEO/PCRTC/PRAMDAC etc? */ + + ret = nouveau_channel_alloc(dev, &dev_priv->channel, + (struct drm_file *)-2, + NvDmaFB, NvDmaTT); + if (ret) + return ret; + + gpuobj = NULL; + ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, + 0, nouveau_mem_fb_amount(dev), + NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, + &gpuobj); + if (ret) + return ret; + + ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM, + gpuobj, NULL); + if (ret) { + nouveau_gpuobj_del(dev, &gpuobj); + return ret; + } + + gpuobj = NULL; + ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0, + dev_priv->gart_info.aper_size, + NV_DMA_ACCESS_RW, &gpuobj, NULL); + if (ret) + return ret; + + ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART, + gpuobj, NULL); + if (ret) { + nouveau_gpuobj_del(dev, &gpuobj); + return ret; + } + + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + if (dev_priv->card_type >= NV_50) { + ret = nv50_display_create(dev); + if (ret) + return ret; + } else { + ret = nv04_display_create(dev); + if (ret) + return ret; + } + } + + ret = nouveau_backlight_init(dev); + if (ret) + NV_ERROR(dev, "Error %d registering backlight\n", ret); + + dev_priv->init_state = NOUVEAU_CARD_INIT_DONE; + + if (drm_core_check_feature(dev, DRIVER_MODESET)) + drm_helper_initial_config(dev); + + return 0; +} + +static void nouveau_card_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->engine; + + NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state); + + if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) { + nouveau_backlight_exit(dev); + + if (dev_priv->channel) { + nouveau_channel_free(dev_priv->channel); + dev_priv->channel = NULL; + } + + engine->fifo.takedown(dev); + engine->graph.takedown(dev); + engine->fb.takedown(dev); + engine->timer.takedown(dev); + engine->mc.takedown(dev); + + mutex_lock(&dev->struct_mutex); + ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); + mutex_unlock(&dev->struct_mutex); + nouveau_sgdma_takedown(dev); + + nouveau_gpuobj_takedown(dev); + nouveau_mem_close(dev); + engine->instmem.takedown(dev); + + if (drm_core_check_feature(dev, DRIVER_MODESET)) + drm_irq_uninstall(dev); + + nouveau_gpuobj_late_takedown(dev); + nouveau_bios_takedown(dev); + + vga_client_register(dev->pdev, NULL, NULL, NULL); + + dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; + } +} + +/* here a client dies, release the stuff that was allocated for its + * file_priv */ +void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv) +{ + nouveau_channel_cleanup(dev, file_priv); +} + +/* first module load, setup the mmio/fb mapping */ +/* KMS: we need mmio at load time, not when the first drm client opens. */ +int nouveau_firstopen(struct drm_device *dev) +{ + return 0; +} + +/* if we have an OF card, copy vbios to RAMIN */ +static void nouveau_OF_copy_vbios_to_ramin(struct drm_device *dev) +{ +#if defined(__powerpc__) + int size, i; + const uint32_t *bios; + struct device_node *dn = pci_device_to_OF_node(dev->pdev); + if (!dn) { + NV_INFO(dev, "Unable to get the OF node\n"); + return; + } + + bios = of_get_property(dn, "NVDA,BMP", &size); + if (bios) { + for (i = 0; i < size; i += 4) + nv_wi32(dev, i, bios[i/4]); + NV_INFO(dev, "OF bios successfully copied (%d bytes)\n", size); + } else { + NV_INFO(dev, "Unable to get the OF bios\n"); + } +#endif +} + +int nouveau_load(struct drm_device *dev, unsigned long flags) +{ + struct drm_nouveau_private *dev_priv; + uint32_t reg0; + resource_size_t mmio_start_offs; + + dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); + if (!dev_priv) + return -ENOMEM; + dev->dev_private = dev_priv; + dev_priv->dev = dev; + + dev_priv->flags = flags & NOUVEAU_FLAGS; + dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; + + NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", + dev->pci_vendor, dev->pci_device, dev->pdev->class); + + dev_priv->acpi_dsm = nouveau_dsm_probe(dev); + + if (dev_priv->acpi_dsm) + nouveau_hybrid_setup(dev); + + dev_priv->wq = create_workqueue("nouveau"); + if (!dev_priv->wq) + return -EINVAL; + + /* resource 0 is mmio regs */ + /* resource 1 is linear FB */ + /* resource 2 is RAMIN (mmio regs + 0x1000000) */ + /* resource 6 is bios */ + + /* map the mmio regs */ + mmio_start_offs = pci_resource_start(dev->pdev, 0); + dev_priv->mmio = ioremap(mmio_start_offs, 0x00800000); + if (!dev_priv->mmio) { + NV_ERROR(dev, "Unable to initialize the mmio mapping. " + "Please report your setup to " DRIVER_EMAIL "\n"); + return -EINVAL; + } + NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", + (unsigned long long)mmio_start_offs); + +#ifdef __BIG_ENDIAN + /* Put the card in BE mode if it's not */ + if (nv_rd32(dev, NV03_PMC_BOOT_1)) + nv_wr32(dev, NV03_PMC_BOOT_1, 0x00000001); + + DRM_MEMORYBARRIER(); +#endif + + /* Time to determine the card architecture */ + reg0 = nv_rd32(dev, NV03_PMC_BOOT_0); + + /* We're dealing with >=NV10 */ + if ((reg0 & 0x0f000000) > 0) { + /* Bit 27-20 contain the architecture in hex */ + dev_priv->chipset = (reg0 & 0xff00000) >> 20; + /* NV04 or NV05 */ + } else if ((reg0 & 0xff00fff0) == 0x20004000) { + dev_priv->chipset = 0x04; + } else + dev_priv->chipset = 0xff; + + switch (dev_priv->chipset & 0xf0) { + case 0x00: + case 0x10: + case 0x20: + case 0x30: + dev_priv->card_type = dev_priv->chipset & 0xf0; + break; + case 0x40: + case 0x60: + dev_priv->card_type = NV_40; + break; + case 0x50: + case 0x80: + case 0x90: + case 0xa0: + dev_priv->card_type = NV_50; + break; + default: + NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0); + return -EINVAL; + } + + NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", + dev_priv->card_type, reg0); + + /* map larger RAMIN aperture on NV40 cards */ + dev_priv->ramin = NULL; + if (dev_priv->card_type >= NV_40) { + int ramin_bar = 2; + if (pci_resource_len(dev->pdev, ramin_bar) == 0) + ramin_bar = 3; + + dev_priv->ramin_size = pci_resource_len(dev->pdev, ramin_bar); + dev_priv->ramin = ioremap( + pci_resource_start(dev->pdev, ramin_bar), + dev_priv->ramin_size); + if (!dev_priv->ramin) { + NV_ERROR(dev, "Failed to init RAMIN mapping, " + "limited instance memory available\n"); + } + } + + /* On older cards (or if the above failed), create a map covering + * the BAR0 PRAMIN aperture */ + if (!dev_priv->ramin) { + dev_priv->ramin_size = 1 * 1024 * 1024; + dev_priv->ramin = ioremap(mmio_start_offs + NV_RAMIN, + dev_priv->ramin_size); + if (!dev_priv->ramin) { + NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n"); + return -ENOMEM; + } + } + + nouveau_OF_copy_vbios_to_ramin(dev); + + /* Special flags */ + if (dev->pci_device == 0x01a0) + dev_priv->flags |= NV_NFORCE; + else if (dev->pci_device == 0x01f0) + dev_priv->flags |= NV_NFORCE2; + + /* For kernel modesetting, init card now and bring up fbcon */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + int ret = nouveau_card_init(dev); + if (ret) + return ret; + } + + return 0; +} + +static void nouveau_close(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* In the case of an error dev_priv may not be be allocated yet */ + if (dev_priv && dev_priv->card_type) + nouveau_card_takedown(dev); +} + +/* KMS: we need mmio at load time, not when the first drm client opens. */ +void nouveau_lastclose(struct drm_device *dev) +{ + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return; + + nouveau_close(dev); +} + +int nouveau_unload(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + if (dev_priv->card_type >= NV_50) + nv50_display_destroy(dev); + else + nv04_display_destroy(dev); + nouveau_close(dev); + } + + iounmap(dev_priv->mmio); + iounmap(dev_priv->ramin); + + kfree(dev_priv); + dev->dev_private = NULL; + return 0; +} + +int +nouveau_ioctl_card_init(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return nouveau_card_init(dev); +} + +int nouveau_ioctl_getparam(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_getparam *getparam = data; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + + switch (getparam->param) { + case NOUVEAU_GETPARAM_CHIPSET_ID: + getparam->value = dev_priv->chipset; + break; + case NOUVEAU_GETPARAM_PCI_VENDOR: + getparam->value = dev->pci_vendor; + break; + case NOUVEAU_GETPARAM_PCI_DEVICE: + getparam->value = dev->pci_device; + break; + case NOUVEAU_GETPARAM_BUS_TYPE: + if (drm_device_is_agp(dev)) + getparam->value = NV_AGP; + else if (drm_device_is_pcie(dev)) + getparam->value = NV_PCIE; + else + getparam->value = NV_PCI; + break; + case NOUVEAU_GETPARAM_FB_PHYSICAL: + getparam->value = dev_priv->fb_phys; + break; + case NOUVEAU_GETPARAM_AGP_PHYSICAL: + getparam->value = dev_priv->gart_info.aper_base; + break; + case NOUVEAU_GETPARAM_PCI_PHYSICAL: + if (dev->sg) { + getparam->value = (unsigned long)dev->sg->virtual; + } else { + NV_ERROR(dev, "Requested PCIGART address, " + "while no PCIGART was created\n"); + return -EINVAL; + } + break; + case NOUVEAU_GETPARAM_FB_SIZE: + getparam->value = dev_priv->fb_available_size; + break; + case NOUVEAU_GETPARAM_AGP_SIZE: + getparam->value = dev_priv->gart_info.aper_size; + break; + case NOUVEAU_GETPARAM_VM_VRAM_BASE: + getparam->value = dev_priv->vm_vram_base; + break; + default: + NV_ERROR(dev, "unknown parameter %lld\n", getparam->param); + return -EINVAL; + } + + return 0; +} + +int +nouveau_ioctl_setparam(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_setparam *setparam = data; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + + switch (setparam->param) { + default: + NV_ERROR(dev, "unknown parameter %lld\n", setparam->param); + return -EINVAL; + } + + return 0; +} + +/* Wait until (value(reg) & mask) == val, up until timeout has hit */ +bool nouveau_wait_until(struct drm_device *dev, uint64_t timeout, + uint32_t reg, uint32_t mask, uint32_t val) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; + uint64_t start = ptimer->read(dev); + + do { + if ((nv_rd32(dev, reg) & mask) == val) + return true; + } while (ptimer->read(dev) - start < timeout); + + return false; +} + +/* Waits for PGRAPH to go completely idle */ +bool nouveau_wait_for_idle(struct drm_device *dev) +{ + if (!nv_wait(NV04_PGRAPH_STATUS, 0xffffffff, 0x00000000)) { + NV_ERROR(dev, "PGRAPH idle timed out with status 0x%08x\n", + nv_rd32(dev, NV04_PGRAPH_STATUS)); + return false; + } + + return true; +} + diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c new file mode 100644 index 0000000000000000000000000000000000000000..187eb84e4da5269527911556dd0a48335d2b9eae --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA, + * All Rights Reserved. + * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA, + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "drmP.h" + +#include "nouveau_drv.h" + +static struct vm_operations_struct nouveau_ttm_vm_ops; +static const struct vm_operations_struct *ttm_vm_ops; + +static int +nouveau_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct ttm_buffer_object *bo = vma->vm_private_data; + int ret; + + if (unlikely(bo == NULL)) + return VM_FAULT_NOPAGE; + + ret = ttm_vm_ops->fault(vma, vmf); + return ret; +} + +int +nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct drm_file *file_priv = filp->private_data; + struct drm_nouveau_private *dev_priv = + file_priv->minor->dev->dev_private; + int ret; + + if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) + return drm_mmap(filp, vma); + + ret = ttm_bo_mmap(filp, vma, &dev_priv->ttm.bdev); + if (unlikely(ret != 0)) + return ret; + + if (unlikely(ttm_vm_ops == NULL)) { + ttm_vm_ops = vma->vm_ops; + nouveau_ttm_vm_ops = *ttm_vm_ops; + nouveau_ttm_vm_ops.fault = &nouveau_ttm_fault; + } + + vma->vm_ops = &nouveau_ttm_vm_ops; + return 0; +} + +static int +nouveau_ttm_mem_global_init(struct ttm_global_reference *ref) +{ + return ttm_mem_global_init(ref->object); +} + +static void +nouveau_ttm_mem_global_release(struct ttm_global_reference *ref) +{ + ttm_mem_global_release(ref->object); +} + +int +nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) +{ + struct ttm_global_reference *global_ref; + int ret; + + global_ref = &dev_priv->ttm.mem_global_ref; + global_ref->global_type = TTM_GLOBAL_TTM_MEM; + global_ref->size = sizeof(struct ttm_mem_global); + global_ref->init = &nouveau_ttm_mem_global_init; + global_ref->release = &nouveau_ttm_mem_global_release; + + ret = ttm_global_item_ref(global_ref); + if (unlikely(ret != 0)) { + DRM_ERROR("Failed setting up TTM memory accounting\n"); + dev_priv->ttm.mem_global_ref.release = NULL; + return ret; + } + + dev_priv->ttm.bo_global_ref.mem_glob = global_ref->object; + global_ref = &dev_priv->ttm.bo_global_ref.ref; + global_ref->global_type = TTM_GLOBAL_TTM_BO; + global_ref->size = sizeof(struct ttm_bo_global); + global_ref->init = &ttm_bo_global_init; + global_ref->release = &ttm_bo_global_release; + + ret = ttm_global_item_ref(global_ref); + if (unlikely(ret != 0)) { + DRM_ERROR("Failed setting up TTM BO subsystem\n"); + ttm_global_item_unref(&dev_priv->ttm.mem_global_ref); + dev_priv->ttm.mem_global_ref.release = NULL; + return ret; + } + + return 0; +} + +void +nouveau_ttm_global_release(struct drm_nouveau_private *dev_priv) +{ + if (dev_priv->ttm.mem_global_ref.release == NULL) + return; + + ttm_global_item_unref(&dev_priv->ttm.bo_global_ref.ref); + ttm_global_item_unref(&dev_priv->ttm.mem_global_ref); + dev_priv->ttm.mem_global_ref.release = NULL; +} + diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c new file mode 100644 index 0000000000000000000000000000000000000000..b91363606055dc0834f89ad6bab718dad44cbfd7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c @@ -0,0 +1,1002 @@ +/* + * Copyright 1993-2003 NVIDIA, Corporation + * Copyright 2006 Dave Airlie + * Copyright 2007 Maarten Maathuis + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 "drmP.h" +#include "drm_crtc_helper.h" + +#include "nouveau_drv.h" +#include "nouveau_encoder.h" +#include "nouveau_connector.h" +#include "nouveau_crtc.h" +#include "nouveau_fb.h" +#include "nouveau_hw.h" +#include "nvreg.h" + +static int +nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb); + +static void +crtc_wr_cio_state(struct drm_crtc *crtc, struct nv04_crtc_reg *crtcstate, int index) +{ + NVWriteVgaCrtc(crtc->dev, nouveau_crtc(crtc)->index, index, + crtcstate->CRTC[index]); +} + +static void nv_crtc_set_digital_vibrance(struct drm_crtc *crtc, int level) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; + struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index]; + + regp->CRTC[NV_CIO_CRE_CSB] = nv_crtc->saturation = level; + if (nv_crtc->saturation && nv_gf4_disp_arch(crtc->dev)) { + regp->CRTC[NV_CIO_CRE_CSB] = 0x80; + regp->CRTC[NV_CIO_CRE_5B] = nv_crtc->saturation << 2; + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_5B); + } + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_CSB); +} + +static void nv_crtc_set_image_sharpening(struct drm_crtc *crtc, int level) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; + struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index]; + + nv_crtc->sharpness = level; + if (level < 0) /* blur is in hw range 0x3f -> 0x20 */ + level += 0x40; + regp->ramdac_634 = level; + NVWriteRAMDAC(crtc->dev, nv_crtc->index, NV_PRAMDAC_634, regp->ramdac_634); +} + +#define PLLSEL_VPLL1_MASK \ + (NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_VPLL \ + | NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB2) +#define PLLSEL_VPLL2_MASK \ + (NV_PRAMDAC_PLL_COEFF_SELECT_PLL_SOURCE_VPLL2 \ + | NV_PRAMDAC_PLL_COEFF_SELECT_VCLK2_RATIO_DB2) +#define PLLSEL_TV_MASK \ + (NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1 \ + | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1 \ + | NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK2 \ + | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK2) + +/* NV4x 0x40.. pll notes: + * gpu pll: 0x4000 + 0x4004 + * ?gpu? pll: 0x4008 + 0x400c + * vpll1: 0x4010 + 0x4014 + * vpll2: 0x4018 + 0x401c + * mpll: 0x4020 + 0x4024 + * mpll: 0x4038 + 0x403c + * + * the first register of each pair has some unknown details: + * bits 0-7: redirected values from elsewhere? (similar to PLL_SETUP_CONTROL?) + * bits 20-23: (mpll) something to do with post divider? + * bits 28-31: related to single stage mode? (bit 8/12) + */ + +static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mode * mode, int dot_clock) +{ + struct drm_device *dev = crtc->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct nv04_mode_state *state = &dev_priv->mode_reg; + struct nv04_crtc_reg *regp = &state->crtc_reg[nv_crtc->index]; + struct nouveau_pll_vals *pv = ®p->pllvals; + struct pll_lims pll_lim; + + if (get_pll_limits(dev, nv_crtc->index ? VPLL2 : VPLL1, &pll_lim)) + return; + + /* NM2 == 0 is used to determine single stage mode on two stage plls */ + pv->NM2 = 0; + + /* for newer nv4x the blob uses only the first stage of the vpll below a + * certain clock. for a certain nv4b this is 150MHz. since the max + * output frequency of the first stage for this card is 300MHz, it is + * assumed the threshold is given by vco1 maxfreq/2 + */ + /* for early nv4x, specifically nv40 and *some* nv43 (devids 0 and 6, + * not 8, others unknown), the blob always uses both plls. no problem + * has yet been observed in allowing the use a single stage pll on all + * nv43 however. the behaviour of single stage use is untested on nv40 + */ + if (dev_priv->chipset > 0x40 && dot_clock <= (pll_lim.vco1.maxfreq / 2)) + memset(&pll_lim.vco2, 0, sizeof(pll_lim.vco2)); + + if (!nouveau_calc_pll_mnp(dev, &pll_lim, dot_clock, pv)) + return; + + state->pllsel &= PLLSEL_VPLL1_MASK | PLLSEL_VPLL2_MASK | PLLSEL_TV_MASK; + + /* The blob uses this always, so let's do the same */ + if (dev_priv->card_type == NV_40) + state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_USE_VPLL2_TRUE; + /* again nv40 and some nv43 act more like nv3x as described above */ + if (dev_priv->chipset < 0x41) + state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_MPLL | + NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_NVPLL; + state->pllsel |= nv_crtc->index ? PLLSEL_VPLL2_MASK : PLLSEL_VPLL1_MASK; + + if (pv->NM2) + NV_TRACE(dev, "vpll: n1 %d n2 %d m1 %d m2 %d log2p %d\n", + pv->N1, pv->N2, pv->M1, pv->M2, pv->log2P); + else + NV_TRACE(dev, "vpll: n %d m %d log2p %d\n", + pv->N1, pv->M1, pv->log2P); + + nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset); +} + +static void +nv_crtc_dpms(struct drm_crtc *crtc, int mode) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct drm_device *dev = crtc->dev; + unsigned char seq1 = 0, crtc17 = 0; + unsigned char crtc1A; + + NV_TRACE(dev, "Setting dpms mode %d on CRTC %d\n", mode, + nv_crtc->index); + + if (nv_crtc->last_dpms == mode) /* Don't do unnecesary mode changes. */ + return; + + nv_crtc->last_dpms = mode; + + if (nv_two_heads(dev)) + NVSetOwner(dev, nv_crtc->index); + + /* nv4ref indicates these two RPC1 bits inhibit h/v sync */ + crtc1A = NVReadVgaCrtc(dev, nv_crtc->index, + NV_CIO_CRE_RPC1_INDEX) & ~0xC0; + switch (mode) { + case DRM_MODE_DPMS_STANDBY: + /* Screen: Off; HSync: Off, VSync: On -- Not Supported */ + seq1 = 0x20; + crtc17 = 0x80; + crtc1A |= 0x80; + break; + case DRM_MODE_DPMS_SUSPEND: + /* Screen: Off; HSync: On, VSync: Off -- Not Supported */ + seq1 = 0x20; + crtc17 = 0x80; + crtc1A |= 0x40; + break; + case DRM_MODE_DPMS_OFF: + /* Screen: Off; HSync: Off, VSync: Off */ + seq1 = 0x20; + crtc17 = 0x00; + crtc1A |= 0xC0; + break; + case DRM_MODE_DPMS_ON: + default: + /* Screen: On; HSync: On, VSync: On */ + seq1 = 0x00; + crtc17 = 0x80; + break; + } + + NVVgaSeqReset(dev, nv_crtc->index, true); + /* Each head has it's own sequencer, so we can turn it off when we want */ + seq1 |= (NVReadVgaSeq(dev, nv_crtc->index, NV_VIO_SR_CLOCK_INDEX) & ~0x20); + NVWriteVgaSeq(dev, nv_crtc->index, NV_VIO_SR_CLOCK_INDEX, seq1); + crtc17 |= (NVReadVgaCrtc(dev, nv_crtc->index, NV_CIO_CR_MODE_INDEX) & ~0x80); + mdelay(10); + NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CR_MODE_INDEX, crtc17); + NVVgaSeqReset(dev, nv_crtc->index, false); + + NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A); +} + +static bool +nv_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static void +nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) +{ + struct drm_device *dev = crtc->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index]; + struct drm_framebuffer *fb = crtc->fb; + + /* Calculate our timings */ + int horizDisplay = (mode->crtc_hdisplay >> 3) - 1; + int horizStart = (mode->crtc_hsync_start >> 3) - 1; + int horizEnd = (mode->crtc_hsync_end >> 3) - 1; + int horizTotal = (mode->crtc_htotal >> 3) - 5; + int horizBlankStart = (mode->crtc_hdisplay >> 3) - 1; + int horizBlankEnd = (mode->crtc_htotal >> 3) - 1; + int vertDisplay = mode->crtc_vdisplay - 1; + int vertStart = mode->crtc_vsync_start - 1; + int vertEnd = mode->crtc_vsync_end - 1; + int vertTotal = mode->crtc_vtotal - 2; + int vertBlankStart = mode->crtc_vdisplay - 1; + int vertBlankEnd = mode->crtc_vtotal - 1; + + struct drm_encoder *encoder; + bool fp_output = false; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + if (encoder->crtc == crtc && + (nv_encoder->dcb->type == OUTPUT_LVDS || + nv_encoder->dcb->type == OUTPUT_TMDS)) + fp_output = true; + } + + if (fp_output) { + vertStart = vertTotal - 3; + vertEnd = vertTotal - 2; + vertBlankStart = vertStart; + horizStart = horizTotal - 5; + horizEnd = horizTotal - 2; + horizBlankEnd = horizTotal + 4; +#if 0 + if (dev->overlayAdaptor && dev_priv->card_type >= NV_10) + /* This reportedly works around some video overlay bandwidth problems */ + horizTotal += 2; +#endif + } + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + vertTotal |= 1; + +#if 0 + ErrorF("horizDisplay: 0x%X \n", horizDisplay); + ErrorF("horizStart: 0x%X \n", horizStart); + ErrorF("horizEnd: 0x%X \n", horizEnd); + ErrorF("horizTotal: 0x%X \n", horizTotal); + ErrorF("horizBlankStart: 0x%X \n", horizBlankStart); + ErrorF("horizBlankEnd: 0x%X \n", horizBlankEnd); + ErrorF("vertDisplay: 0x%X \n", vertDisplay); + ErrorF("vertStart: 0x%X \n", vertStart); + ErrorF("vertEnd: 0x%X \n", vertEnd); + ErrorF("vertTotal: 0x%X \n", vertTotal); + ErrorF("vertBlankStart: 0x%X \n", vertBlankStart); + ErrorF("vertBlankEnd: 0x%X \n", vertBlankEnd); +#endif + + /* + * compute correct Hsync & Vsync polarity + */ + if ((mode->flags & (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC)) + && (mode->flags & (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))) { + + regp->MiscOutReg = 0x23; + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + regp->MiscOutReg |= 0x40; + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + regp->MiscOutReg |= 0x80; + } else { + int vdisplay = mode->vdisplay; + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) + vdisplay *= 2; + if (mode->vscan > 1) + vdisplay *= mode->vscan; + if (vdisplay < 400) + regp->MiscOutReg = 0xA3; /* +hsync -vsync */ + else if (vdisplay < 480) + regp->MiscOutReg = 0x63; /* -hsync +vsync */ + else if (vdisplay < 768) + regp->MiscOutReg = 0xE3; /* -hsync -vsync */ + else + regp->MiscOutReg = 0x23; /* +hsync +vsync */ + } + + regp->MiscOutReg |= (mode->clock_index & 0x03) << 2; + + /* + * Time Sequencer + */ + regp->Sequencer[NV_VIO_SR_RESET_INDEX] = 0x00; + /* 0x20 disables the sequencer */ + if (mode->flags & DRM_MODE_FLAG_CLKDIV2) + regp->Sequencer[NV_VIO_SR_CLOCK_INDEX] = 0x29; + else + regp->Sequencer[NV_VIO_SR_CLOCK_INDEX] = 0x21; + regp->Sequencer[NV_VIO_SR_PLANE_MASK_INDEX] = 0x0F; + regp->Sequencer[NV_VIO_SR_CHAR_MAP_INDEX] = 0x00; + regp->Sequencer[NV_VIO_SR_MEM_MODE_INDEX] = 0x0E; + + /* + * CRTC + */ + regp->CRTC[NV_CIO_CR_HDT_INDEX] = horizTotal; + regp->CRTC[NV_CIO_CR_HDE_INDEX] = horizDisplay; + regp->CRTC[NV_CIO_CR_HBS_INDEX] = horizBlankStart; + regp->CRTC[NV_CIO_CR_HBE_INDEX] = (1 << 7) | + XLATE(horizBlankEnd, 0, NV_CIO_CR_HBE_4_0); + regp->CRTC[NV_CIO_CR_HRS_INDEX] = horizStart; + regp->CRTC[NV_CIO_CR_HRE_INDEX] = XLATE(horizBlankEnd, 5, NV_CIO_CR_HRE_HBE_5) | + XLATE(horizEnd, 0, NV_CIO_CR_HRE_4_0); + regp->CRTC[NV_CIO_CR_VDT_INDEX] = vertTotal; + regp->CRTC[NV_CIO_CR_OVL_INDEX] = XLATE(vertStart, 9, NV_CIO_CR_OVL_VRS_9) | + XLATE(vertDisplay, 9, NV_CIO_CR_OVL_VDE_9) | + XLATE(vertTotal, 9, NV_CIO_CR_OVL_VDT_9) | + (1 << 4) | + XLATE(vertBlankStart, 8, NV_CIO_CR_OVL_VBS_8) | + XLATE(vertStart, 8, NV_CIO_CR_OVL_VRS_8) | + XLATE(vertDisplay, 8, NV_CIO_CR_OVL_VDE_8) | + XLATE(vertTotal, 8, NV_CIO_CR_OVL_VDT_8); + regp->CRTC[NV_CIO_CR_RSAL_INDEX] = 0x00; + regp->CRTC[NV_CIO_CR_CELL_HT_INDEX] = ((mode->flags & DRM_MODE_FLAG_DBLSCAN) ? MASK(NV_CIO_CR_CELL_HT_SCANDBL) : 0) | + 1 << 6 | + XLATE(vertBlankStart, 9, NV_CIO_CR_CELL_HT_VBS_9); + regp->CRTC[NV_CIO_CR_CURS_ST_INDEX] = 0x00; + regp->CRTC[NV_CIO_CR_CURS_END_INDEX] = 0x00; + regp->CRTC[NV_CIO_CR_SA_HI_INDEX] = 0x00; + regp->CRTC[NV_CIO_CR_SA_LO_INDEX] = 0x00; + regp->CRTC[NV_CIO_CR_TCOFF_HI_INDEX] = 0x00; + regp->CRTC[NV_CIO_CR_TCOFF_LO_INDEX] = 0x00; + regp->CRTC[NV_CIO_CR_VRS_INDEX] = vertStart; + regp->CRTC[NV_CIO_CR_VRE_INDEX] = 1 << 5 | XLATE(vertEnd, 0, NV_CIO_CR_VRE_3_0); + regp->CRTC[NV_CIO_CR_VDE_INDEX] = vertDisplay; + /* framebuffer can be larger than crtc scanout area. */ + regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = fb->pitch / 8; + regp->CRTC[NV_CIO_CR_ULINE_INDEX] = 0x00; + regp->CRTC[NV_CIO_CR_VBS_INDEX] = vertBlankStart; + regp->CRTC[NV_CIO_CR_VBE_INDEX] = vertBlankEnd; + regp->CRTC[NV_CIO_CR_MODE_INDEX] = 0x43; + regp->CRTC[NV_CIO_CR_LCOMP_INDEX] = 0xff; + + /* + * Some extended CRTC registers (they are not saved with the rest of the vga regs). + */ + + /* framebuffer can be larger than crtc scanout area. */ + regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = XLATE(fb->pitch / 8, 8, NV_CIO_CRE_RPC0_OFFSET_10_8); + regp->CRTC[NV_CIO_CRE_RPC1_INDEX] = mode->crtc_hdisplay < 1280 ? + MASK(NV_CIO_CRE_RPC1_LARGE) : 0x00; + regp->CRTC[NV_CIO_CRE_LSR_INDEX] = XLATE(horizBlankEnd, 6, NV_CIO_CRE_LSR_HBE_6) | + XLATE(vertBlankStart, 10, NV_CIO_CRE_LSR_VBS_10) | + XLATE(vertStart, 10, NV_CIO_CRE_LSR_VRS_10) | + XLATE(vertDisplay, 10, NV_CIO_CRE_LSR_VDE_10) | + XLATE(vertTotal, 10, NV_CIO_CRE_LSR_VDT_10); + regp->CRTC[NV_CIO_CRE_HEB__INDEX] = XLATE(horizStart, 8, NV_CIO_CRE_HEB_HRS_8) | + XLATE(horizBlankStart, 8, NV_CIO_CRE_HEB_HBS_8) | + XLATE(horizDisplay, 8, NV_CIO_CRE_HEB_HDE_8) | + XLATE(horizTotal, 8, NV_CIO_CRE_HEB_HDT_8); + regp->CRTC[NV_CIO_CRE_EBR_INDEX] = XLATE(vertBlankStart, 11, NV_CIO_CRE_EBR_VBS_11) | + XLATE(vertStart, 11, NV_CIO_CRE_EBR_VRS_11) | + XLATE(vertDisplay, 11, NV_CIO_CRE_EBR_VDE_11) | + XLATE(vertTotal, 11, NV_CIO_CRE_EBR_VDT_11); + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { + horizTotal = (horizTotal >> 1) & ~1; + regp->CRTC[NV_CIO_CRE_ILACE__INDEX] = horizTotal; + regp->CRTC[NV_CIO_CRE_HEB__INDEX] |= XLATE(horizTotal, 8, NV_CIO_CRE_HEB_ILC_8); + } else + regp->CRTC[NV_CIO_CRE_ILACE__INDEX] = 0xff; /* interlace off */ + + /* + * Graphics Display Controller + */ + regp->Graphics[NV_VIO_GX_SR_INDEX] = 0x00; + regp->Graphics[NV_VIO_GX_SREN_INDEX] = 0x00; + regp->Graphics[NV_VIO_GX_CCOMP_INDEX] = 0x00; + regp->Graphics[NV_VIO_GX_ROP_INDEX] = 0x00; + regp->Graphics[NV_VIO_GX_READ_MAP_INDEX] = 0x00; + regp->Graphics[NV_VIO_GX_MODE_INDEX] = 0x40; /* 256 color mode */ + regp->Graphics[NV_VIO_GX_MISC_INDEX] = 0x05; /* map 64k mem + graphic mode */ + regp->Graphics[NV_VIO_GX_DONT_CARE_INDEX] = 0x0F; + regp->Graphics[NV_VIO_GX_BIT_MASK_INDEX] = 0xFF; + + regp->Attribute[0] = 0x00; /* standard colormap translation */ + regp->Attribute[1] = 0x01; + regp->Attribute[2] = 0x02; + regp->Attribute[3] = 0x03; + regp->Attribute[4] = 0x04; + regp->Attribute[5] = 0x05; + regp->Attribute[6] = 0x06; + regp->Attribute[7] = 0x07; + regp->Attribute[8] = 0x08; + regp->Attribute[9] = 0x09; + regp->Attribute[10] = 0x0A; + regp->Attribute[11] = 0x0B; + regp->Attribute[12] = 0x0C; + regp->Attribute[13] = 0x0D; + regp->Attribute[14] = 0x0E; + regp->Attribute[15] = 0x0F; + regp->Attribute[NV_CIO_AR_MODE_INDEX] = 0x01; /* Enable graphic mode */ + /* Non-vga */ + regp->Attribute[NV_CIO_AR_OSCAN_INDEX] = 0x00; + regp->Attribute[NV_CIO_AR_PLANE_INDEX] = 0x0F; /* enable all color planes */ + regp->Attribute[NV_CIO_AR_HPP_INDEX] = 0x00; + regp->Attribute[NV_CIO_AR_CSEL_INDEX] = 0x00; +} + +/** + * Sets up registers for the given mode/adjusted_mode pair. + * + * The clocks, CRTCs and outputs attached to this CRTC must be off. + * + * This shouldn't enable any clocks, CRTCs, or outputs, but they should + * be easily turned on/off after this. + */ +static void +nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) +{ + struct drm_device *dev = crtc->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index]; + struct nv04_crtc_reg *savep = &dev_priv->saved_reg.crtc_reg[nv_crtc->index]; + struct drm_encoder *encoder; + bool lvds_output = false, tmds_output = false, tv_output = false, + off_chip_digital = false; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + bool digital = false; + + if (encoder->crtc != crtc) + continue; + + if (nv_encoder->dcb->type == OUTPUT_LVDS) + digital = lvds_output = true; + if (nv_encoder->dcb->type == OUTPUT_TV) + tv_output = true; + if (nv_encoder->dcb->type == OUTPUT_TMDS) + digital = tmds_output = true; + if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP && digital) + off_chip_digital = true; + } + + /* Registers not directly related to the (s)vga mode */ + + /* What is the meaning of this register? */ + /* A few popular values are 0x18, 0x1c, 0x38, 0x3c */ + regp->CRTC[NV_CIO_CRE_ENH_INDEX] = savep->CRTC[NV_CIO_CRE_ENH_INDEX] & ~(1<<5); + + regp->crtc_eng_ctrl = 0; + /* Except for rare conditions I2C is enabled on the primary crtc */ + if (nv_crtc->index == 0) + regp->crtc_eng_ctrl |= NV_CRTC_FSEL_I2C; +#if 0 + /* Set overlay to desired crtc. */ + if (dev->overlayAdaptor) { + NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(dev); + if (pPriv->overlayCRTC == nv_crtc->index) + regp->crtc_eng_ctrl |= NV_CRTC_FSEL_OVERLAY; + } +#endif + + /* ADDRESS_SPACE_PNVM is the same as setting HCUR_ASI */ + regp->cursor_cfg = NV_PCRTC_CURSOR_CONFIG_CUR_LINES_64 | + NV_PCRTC_CURSOR_CONFIG_CUR_PIXELS_64 | + NV_PCRTC_CURSOR_CONFIG_ADDRESS_SPACE_PNVM; + if (dev_priv->chipset >= 0x11) + regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_CUR_BPP_32; + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) + regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE; + + /* Unblock some timings */ + regp->CRTC[NV_CIO_CRE_53] = 0; + regp->CRTC[NV_CIO_CRE_54] = 0; + + /* 0x00 is disabled, 0x11 is lvds, 0x22 crt and 0x88 tmds */ + if (lvds_output) + regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x11; + else if (tmds_output) + regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x88; + else + regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x22; + + /* These values seem to vary */ + /* This register seems to be used by the bios to make certain decisions on some G70 cards? */ + regp->CRTC[NV_CIO_CRE_SCRATCH4__INDEX] = savep->CRTC[NV_CIO_CRE_SCRATCH4__INDEX]; + + nv_crtc_set_digital_vibrance(crtc, nv_crtc->saturation); + + /* probably a scratch reg, but kept for cargo-cult purposes: + * bit0: crtc0?, head A + * bit6: lvds, head A + * bit7: (only in X), head A + */ + if (nv_crtc->index == 0) + regp->CRTC[NV_CIO_CRE_4B] = savep->CRTC[NV_CIO_CRE_4B] | 0x80; + + /* The blob seems to take the current value from crtc 0, add 4 to that + * and reuse the old value for crtc 1 */ + regp->CRTC[NV_CIO_CRE_TVOUT_LATENCY] = dev_priv->saved_reg.crtc_reg[0].CRTC[NV_CIO_CRE_TVOUT_LATENCY]; + if (!nv_crtc->index) + regp->CRTC[NV_CIO_CRE_TVOUT_LATENCY] += 4; + + /* the blob sometimes sets |= 0x10 (which is the same as setting |= + * 1 << 30 on 0x60.830), for no apparent reason */ + regp->CRTC[NV_CIO_CRE_59] = off_chip_digital; + + regp->crtc_830 = mode->crtc_vdisplay - 3; + regp->crtc_834 = mode->crtc_vdisplay - 1; + + if (dev_priv->card_type == NV_40) + /* This is what the blob does */ + regp->crtc_850 = NVReadCRTC(dev, 0, NV_PCRTC_850); + + if (dev_priv->card_type >= NV_30) + regp->gpio_ext = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT); + + regp->crtc_cfg = NV_PCRTC_CONFIG_START_ADDRESS_HSYNC; + + /* Some misc regs */ + if (dev_priv->card_type == NV_40) { + regp->CRTC[NV_CIO_CRE_85] = 0xFF; + regp->CRTC[NV_CIO_CRE_86] = 0x1; + } + + regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->fb->depth + 1) / 8; + /* Enable slaved mode (called MODE_TV in nv4ref.h) */ + if (lvds_output || tmds_output || tv_output) + regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (1 << 7); + + /* Generic PRAMDAC regs */ + + if (dev_priv->card_type >= NV_10) + /* Only bit that bios and blob set. */ + regp->nv10_cursync = (1 << 25); + + regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS | + NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL | + NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON; + if (crtc->fb->depth == 16) + regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; + if (dev_priv->chipset >= 0x11) + regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG; + + regp->ramdac_630 = 0; /* turn off green mode (tv test pattern?) */ + regp->tv_setup = 0; + + nv_crtc_set_image_sharpening(crtc, nv_crtc->sharpness); + + /* Some values the blob sets */ + regp->ramdac_8c0 = 0x100; + regp->ramdac_a20 = 0x0; + regp->ramdac_a24 = 0xfffff; + regp->ramdac_a34 = 0x1; +} + +/** + * Sets up registers for the given mode/adjusted_mode pair. + * + * The clocks, CRTCs and outputs attached to this CRTC must be off. + * + * This shouldn't enable any clocks, CRTCs, or outputs, but they should + * be easily turned on/off after this. + */ +static int +nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, struct drm_framebuffer *old_fb) +{ + struct drm_device *dev = crtc->dev; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct drm_nouveau_private *dev_priv = dev->dev_private; + + NV_DEBUG(dev, "CTRC mode on CRTC %d:\n", nv_crtc->index); + drm_mode_debug_printmodeline(adjusted_mode); + + /* unlock must come after turning off FP_TG_CONTROL in output_prepare */ + nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1); + + nv_crtc_mode_set_vga(crtc, adjusted_mode); + /* calculated in nv04_dfp_prepare, nv40 needs it written before calculating PLLs */ + if (dev_priv->card_type == NV_40) + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, dev_priv->mode_reg.sel_clk); + nv_crtc_mode_set_regs(crtc, adjusted_mode); + nv_crtc_calc_state_ext(crtc, mode, adjusted_mode->clock); + return 0; +} + +static void nv_crtc_save(struct drm_crtc *crtc) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; + struct nv04_mode_state *state = &dev_priv->mode_reg; + struct nv04_crtc_reg *crtc_state = &state->crtc_reg[nv_crtc->index]; + struct nv04_mode_state *saved = &dev_priv->saved_reg; + struct nv04_crtc_reg *crtc_saved = &saved->crtc_reg[nv_crtc->index]; + + if (nv_two_heads(crtc->dev)) + NVSetOwner(crtc->dev, nv_crtc->index); + + nouveau_hw_save_state(crtc->dev, nv_crtc->index, saved); + + /* init some state to saved value */ + state->sel_clk = saved->sel_clk & ~(0x5 << 16); + crtc_state->CRTC[NV_CIO_CRE_LCD__INDEX] = crtc_saved->CRTC[NV_CIO_CRE_LCD__INDEX]; + state->pllsel = saved->pllsel & ~(PLLSEL_VPLL1_MASK | PLLSEL_VPLL2_MASK | PLLSEL_TV_MASK); + crtc_state->gpio_ext = crtc_saved->gpio_ext; +} + +static void nv_crtc_restore(struct drm_crtc *crtc) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; + int head = nv_crtc->index; + uint8_t saved_cr21 = dev_priv->saved_reg.crtc_reg[head].CRTC[NV_CIO_CRE_21]; + + if (nv_two_heads(crtc->dev)) + NVSetOwner(crtc->dev, head); + + nouveau_hw_load_state(crtc->dev, head, &dev_priv->saved_reg); + nv_lock_vga_crtc_shadow(crtc->dev, head, saved_cr21); + + nv_crtc->last_dpms = NV_DPMS_CLEARED; +} + +static void nv_crtc_prepare(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct drm_crtc_helper_funcs *funcs = crtc->helper_private; + + if (nv_two_heads(dev)) + NVSetOwner(dev, nv_crtc->index); + + funcs->dpms(crtc, DRM_MODE_DPMS_OFF); + + NVBlankScreen(dev, nv_crtc->index, true); + + /* Some more preperation. */ + NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_CONFIG, NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA); + if (dev_priv->card_type == NV_40) { + uint32_t reg900 = NVReadRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900); + NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900, reg900 & ~0x10000); + } +} + +static void nv_crtc_commit(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_crtc_helper_funcs *funcs = crtc->helper_private; + struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + + nouveau_hw_load_state(dev, nv_crtc->index, &dev_priv->mode_reg); + nv04_crtc_mode_set_base(crtc, crtc->x, crtc->y, NULL); + +#ifdef __BIG_ENDIAN + /* turn on LFB swapping */ + { + uint8_t tmp = NVReadVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RCR); + tmp |= MASK(NV_CIO_CRE_RCR_ENDIAN_BIG); + NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RCR, tmp); + } +#endif + + funcs->dpms(crtc, DRM_MODE_DPMS_ON); +} + +static void nv_crtc_destroy(struct drm_crtc *crtc) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + + NV_DEBUG(crtc->dev, "\n"); + + if (!nv_crtc) + return; + + drm_crtc_cleanup(crtc); + + nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); + kfree(nv_crtc); +} + +static void +nv_crtc_gamma_load(struct drm_crtc *crtc) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct drm_device *dev = nv_crtc->base.dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct rgb { uint8_t r, g, b; } __attribute__((packed)) *rgbs; + int i; + + rgbs = (struct rgb *)dev_priv->mode_reg.crtc_reg[nv_crtc->index].DAC; + for (i = 0; i < 256; i++) { + rgbs[i].r = nv_crtc->lut.r[i] >> 8; + rgbs[i].g = nv_crtc->lut.g[i] >> 8; + rgbs[i].b = nv_crtc->lut.b[i] >> 8; + } + + nouveau_hw_load_state_palette(dev, nv_crtc->index, &dev_priv->mode_reg); +} + +static void +nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t size) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + int i; + + if (size != 256) + return; + + for (i = 0; i < 256; i++) { + nv_crtc->lut.r[i] = r[i]; + nv_crtc->lut.g[i] = g[i]; + nv_crtc->lut.b[i] = b[i]; + } + + /* We need to know the depth before we upload, but it's possible to + * get called before a framebuffer is bound. If this is the case, + * mark the lut values as dirty by setting depth==0, and it'll be + * uploaded on the first mode_set_base() + */ + if (!nv_crtc->base.fb) { + nv_crtc->lut.depth = 0; + return; + } + + nv_crtc_gamma_load(crtc); +} + +static int +nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index]; + struct drm_framebuffer *drm_fb = nv_crtc->base.fb; + struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); + int arb_burst, arb_lwm; + int ret; + + ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM); + if (ret) + return ret; + + if (old_fb) { + struct nouveau_framebuffer *ofb = nouveau_framebuffer(old_fb); + nouveau_bo_unpin(ofb->nvbo); + } + + nv_crtc->fb.offset = fb->nvbo->bo.offset; + + if (nv_crtc->lut.depth != drm_fb->depth) { + nv_crtc->lut.depth = drm_fb->depth; + nv_crtc_gamma_load(crtc); + } + + /* Update the framebuffer format. */ + regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] &= ~3; + regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->fb->depth + 1) / 8; + regp->ramdac_gen_ctrl &= ~NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; + if (crtc->fb->depth == 16) + regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_PIXEL_INDEX); + NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_GENERAL_CONTROL, + regp->ramdac_gen_ctrl); + + regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = drm_fb->pitch >> 3; + regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = + XLATE(drm_fb->pitch >> 3, 8, NV_CIO_CRE_RPC0_OFFSET_10_8); + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_RPC0_INDEX); + crtc_wr_cio_state(crtc, regp, NV_CIO_CR_OFFSET_INDEX); + + /* Update the framebuffer location. */ + regp->fb_start = nv_crtc->fb.offset & ~3; + regp->fb_start += (y * drm_fb->pitch) + (x * drm_fb->bits_per_pixel / 8); + NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_START, regp->fb_start); + + /* Update the arbitration parameters. */ + nouveau_calc_arb(dev, crtc->mode.clock, drm_fb->bits_per_pixel, + &arb_burst, &arb_lwm); + + regp->CRTC[NV_CIO_CRE_FF_INDEX] = arb_burst; + regp->CRTC[NV_CIO_CRE_FFLWM__INDEX] = arb_lwm & 0xff; + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX); + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX); + + if (dev_priv->card_type >= NV_30) { + regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8; + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47); + } + + return 0; +} + +static void nv04_cursor_upload(struct drm_device *dev, struct nouveau_bo *src, + struct nouveau_bo *dst) +{ + int width = nv_cursor_width(dev); + uint32_t pixel; + int i, j; + + for (i = 0; i < width; i++) { + for (j = 0; j < width; j++) { + pixel = nouveau_bo_rd32(src, i*64 + j); + + nouveau_bo_wr16(dst, i*width + j, (pixel & 0x80000000) >> 16 + | (pixel & 0xf80000) >> 9 + | (pixel & 0xf800) >> 6 + | (pixel & 0xf8) >> 3); + } + } +} + +static void nv11_cursor_upload(struct drm_device *dev, struct nouveau_bo *src, + struct nouveau_bo *dst) +{ + uint32_t pixel; + int alpha, i; + + /* nv11+ supports premultiplied (PM), or non-premultiplied (NPM) alpha + * cursors (though NPM in combination with fp dithering may not work on + * nv11, from "nv" driver history) + * NPM mode needs NV_PCRTC_CURSOR_CONFIG_ALPHA_BLEND set and is what the + * blob uses, however we get given PM cursors so we use PM mode + */ + for (i = 0; i < 64 * 64; i++) { + pixel = nouveau_bo_rd32(src, i); + + /* hw gets unhappy if alpha <= rgb values. for a PM image "less + * than" shouldn't happen; fix "equal to" case by adding one to + * alpha channel (slightly inaccurate, but so is attempting to + * get back to NPM images, due to limits of integer precision) + */ + alpha = pixel >> 24; + if (alpha > 0 && alpha < 255) + pixel = (pixel & 0x00ffffff) | ((alpha + 1) << 24); + +#ifdef __BIG_ENDIAN + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->chipset == 0x11) { + pixel = ((pixel & 0x000000ff) << 24) | + ((pixel & 0x0000ff00) << 8) | + ((pixel & 0x00ff0000) >> 8) | + ((pixel & 0xff000000) >> 24); + } + } +#endif + + nouveau_bo_wr32(dst, i, pixel); + } +} + +static int +nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, + uint32_t buffer_handle, uint32_t width, uint32_t height) +{ + struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; + struct drm_device *dev = dev_priv->dev; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct nouveau_bo *cursor = NULL; + struct drm_gem_object *gem; + int ret = 0; + + if (width != 64 || height != 64) + return -EINVAL; + + if (!buffer_handle) { + nv_crtc->cursor.hide(nv_crtc, true); + return 0; + } + + gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); + if (!gem) + return -EINVAL; + cursor = nouveau_gem_object(gem); + + ret = nouveau_bo_map(cursor); + if (ret) + goto out; + + if (dev_priv->chipset >= 0x11) + nv11_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo); + else + nv04_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo); + + nouveau_bo_unmap(cursor); + nv_crtc->cursor.offset = nv_crtc->cursor.nvbo->bo.offset; + nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset); + nv_crtc->cursor.show(nv_crtc, true); +out: + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(gem); + mutex_unlock(&dev->struct_mutex); + return ret; +} + +static int +nv04_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + + nv_crtc->cursor.set_pos(nv_crtc, x, y); + return 0; +} + +static const struct drm_crtc_funcs nv04_crtc_funcs = { + .save = nv_crtc_save, + .restore = nv_crtc_restore, + .cursor_set = nv04_crtc_cursor_set, + .cursor_move = nv04_crtc_cursor_move, + .gamma_set = nv_crtc_gamma_set, + .set_config = drm_crtc_helper_set_config, + .destroy = nv_crtc_destroy, +}; + +static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = { + .dpms = nv_crtc_dpms, + .prepare = nv_crtc_prepare, + .commit = nv_crtc_commit, + .mode_fixup = nv_crtc_mode_fixup, + .mode_set = nv_crtc_mode_set, + .mode_set_base = nv04_crtc_mode_set_base, + .load_lut = nv_crtc_gamma_load, +}; + +int +nv04_crtc_create(struct drm_device *dev, int crtc_num) +{ + struct nouveau_crtc *nv_crtc; + int ret, i; + + nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); + if (!nv_crtc) + return -ENOMEM; + + for (i = 0; i < 256; i++) { + nv_crtc->lut.r[i] = i << 8; + nv_crtc->lut.g[i] = i << 8; + nv_crtc->lut.b[i] = i << 8; + } + nv_crtc->lut.depth = 0; + + nv_crtc->index = crtc_num; + nv_crtc->last_dpms = NV_DPMS_CLEARED; + + drm_crtc_init(dev, &nv_crtc->base, &nv04_crtc_funcs); + drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs); + drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); + + ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, + 0, 0x0000, false, true, &nv_crtc->cursor.nvbo); + if (!ret) { + ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); + if (!ret) + ret = nouveau_bo_map(nv_crtc->cursor.nvbo); + if (ret) + nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); + } + + nv04_cursor_init(nv_crtc); + + return 0; +} + diff --git a/drivers/gpu/drm/nouveau/nv04_cursor.c b/drivers/gpu/drm/nouveau/nv04_cursor.c new file mode 100644 index 0000000000000000000000000000000000000000..89a91b9d8b258d54e24c2b3725727824c7a18df0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_cursor.c @@ -0,0 +1,70 @@ +#include "drmP.h" +#include "drm_mode.h" +#include "nouveau_reg.h" +#include "nouveau_drv.h" +#include "nouveau_crtc.h" +#include "nouveau_hw.h" + +static void +nv04_cursor_show(struct nouveau_crtc *nv_crtc, bool update) +{ + nv_show_cursor(nv_crtc->base.dev, nv_crtc->index, true); +} + +static void +nv04_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) +{ + nv_show_cursor(nv_crtc->base.dev, nv_crtc->index, false); +} + +static void +nv04_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y) +{ + NVWriteRAMDAC(nv_crtc->base.dev, nv_crtc->index, + NV_PRAMDAC_CU_START_POS, + XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) | + XLATE(x, 0, NV_PRAMDAC_CU_START_POS_X)); +} + +static void +crtc_wr_cio_state(struct drm_crtc *crtc, struct nv04_crtc_reg *crtcstate, int index) +{ + NVWriteVgaCrtc(crtc->dev, nouveau_crtc(crtc)->index, index, + crtcstate->CRTC[index]); +} + +static void +nv04_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) +{ + struct drm_device *dev = nv_crtc->base.dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index]; + struct drm_crtc *crtc = &nv_crtc->base; + + regp->CRTC[NV_CIO_CRE_HCUR_ADDR0_INDEX] = + MASK(NV_CIO_CRE_HCUR_ASI) | + XLATE(offset, 17, NV_CIO_CRE_HCUR_ADDR0_ADR); + regp->CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX] = + XLATE(offset, 11, NV_CIO_CRE_HCUR_ADDR1_ADR); + if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN) + regp->CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX] |= + MASK(NV_CIO_CRE_HCUR_ADDR1_CUR_DBL); + regp->CRTC[NV_CIO_CRE_HCUR_ADDR2_INDEX] = offset >> 24; + + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX); + if (dev_priv->card_type == NV_40) + nv_fix_nv40_hw_cursor(dev, nv_crtc->index); +} + +int +nv04_cursor_init(struct nouveau_crtc *crtc) +{ + crtc->cursor.set_offset = nv04_cursor_set_offset; + crtc->cursor.set_pos = nv04_cursor_set_pos; + crtc->cursor.hide = nv04_cursor_hide; + crtc->cursor.show = nv04_cursor_show; + return 0; +} + diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c new file mode 100644 index 0000000000000000000000000000000000000000..a5fa51714e874e8ee5e60bf200516095ebf2d950 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -0,0 +1,528 @@ +/* + * Copyright 2003 NVIDIA, Corporation + * Copyright 2006 Dave Airlie + * Copyright 2007 Maarten Maathuis + * Copyright 2007-2009 Stuart Bennett + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 "drmP.h" +#include "drm_crtc_helper.h" + +#include "nouveau_drv.h" +#include "nouveau_encoder.h" +#include "nouveau_connector.h" +#include "nouveau_crtc.h" +#include "nouveau_hw.h" +#include "nvreg.h" + +int nv04_dac_output_offset(struct drm_encoder *encoder) +{ + struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + int offset = 0; + + if (dcb->or & (8 | OUTPUT_C)) + offset += 0x68; + if (dcb->or & (8 | OUTPUT_B)) + offset += 0x2000; + + return offset; +} + +/* + * arbitrary limit to number of sense oscillations tolerated in one sample + * period (observed to be at least 13 in "nvidia") + */ +#define MAX_HBLANK_OSC 20 + +/* + * arbitrary limit to number of conflicting sample pairs to tolerate at a + * voltage step (observed to be at least 5 in "nvidia") + */ +#define MAX_SAMPLE_PAIRS 10 + +static int sample_load_twice(struct drm_device *dev, bool sense[2]) +{ + int i; + + for (i = 0; i < 2; i++) { + bool sense_a, sense_b, sense_b_prime; + int j = 0; + + /* + * wait for bit 0 clear -- out of hblank -- (say reg value 0x4), + * then wait for transition 0x4->0x5->0x4: enter hblank, leave + * hblank again + * use a 10ms timeout (guards against crtc being inactive, in + * which case blank state would never change) + */ + if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR, + 0x00000001, 0x00000000)) + return -EBUSY; + if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR, + 0x00000001, 0x00000001)) + return -EBUSY; + if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR, + 0x00000001, 0x00000000)) + return -EBUSY; + + udelay(100); + /* when level triggers, sense is _LO_ */ + sense_a = nv_rd08(dev, NV_PRMCIO_INP0) & 0x10; + + /* take another reading until it agrees with sense_a... */ + do { + udelay(100); + sense_b = nv_rd08(dev, NV_PRMCIO_INP0) & 0x10; + if (sense_a != sense_b) { + sense_b_prime = + nv_rd08(dev, NV_PRMCIO_INP0) & 0x10; + if (sense_b == sense_b_prime) { + /* ... unless two consecutive subsequent + * samples agree; sense_a is replaced */ + sense_a = sense_b; + /* force mis-match so we loop */ + sense_b = !sense_a; + } + } + } while ((sense_a != sense_b) && ++j < MAX_HBLANK_OSC); + + if (j == MAX_HBLANK_OSC) + /* with so much oscillation, default to sense:LO */ + sense[i] = false; + else + sense[i] = sense_a; + } + + return 0; +} + +static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + uint8_t saved_seq1, saved_pi, saved_rpc1; + uint8_t saved_palette0[3], saved_palette_mask; + uint32_t saved_rtest_ctrl, saved_rgen_ctrl; + int i; + uint8_t blue; + bool sense = true; + + /* + * for this detection to work, there needs to be a mode set up on the + * CRTC. this is presumed to be the case + */ + + if (nv_two_heads(dev)) + /* only implemented for head A for now */ + NVSetOwner(dev, 0); + + saved_seq1 = NVReadVgaSeq(dev, 0, NV_VIO_SR_CLOCK_INDEX); + NVWriteVgaSeq(dev, 0, NV_VIO_SR_CLOCK_INDEX, saved_seq1 & ~0x20); + + saved_rtest_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL, + saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF); + + msleep(10); + + saved_pi = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX); + NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX, + saved_pi & ~(0x80 | MASK(NV_CIO_CRE_PIXEL_FORMAT))); + saved_rpc1 = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX); + NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1 & ~0xc0); + + nv_wr08(dev, NV_PRMDIO_READ_MODE_ADDRESS, 0x0); + for (i = 0; i < 3; i++) + saved_palette0[i] = nv_rd08(dev, NV_PRMDIO_PALETTE_DATA); + saved_palette_mask = nv_rd08(dev, NV_PRMDIO_PIXEL_MASK); + nv_wr08(dev, NV_PRMDIO_PIXEL_MASK, 0); + + saved_rgen_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL, + (saved_rgen_ctrl & ~(NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS | + NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_75OHM)) | + NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON); + + blue = 8; /* start of test range */ + + do { + bool sense_pair[2]; + + nv_wr08(dev, NV_PRMDIO_WRITE_MODE_ADDRESS, 0); + nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, 0); + nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, 0); + /* testing blue won't find monochrome monitors. I don't care */ + nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, blue); + + i = 0; + /* take sample pairs until both samples in the pair agree */ + do { + if (sample_load_twice(dev, sense_pair)) + goto out; + } while ((sense_pair[0] != sense_pair[1]) && + ++i < MAX_SAMPLE_PAIRS); + + if (i == MAX_SAMPLE_PAIRS) + /* too much oscillation defaults to LO */ + sense = false; + else + sense = sense_pair[0]; + + /* + * if sense goes LO before blue ramps to 0x18, monitor is not connected. + * ergo, if blue gets to 0x18, monitor must be connected + */ + } while (++blue < 0x18 && sense); + +out: + nv_wr08(dev, NV_PRMDIO_PIXEL_MASK, saved_palette_mask); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL, saved_rgen_ctrl); + nv_wr08(dev, NV_PRMDIO_WRITE_MODE_ADDRESS, 0); + for (i = 0; i < 3; i++) + nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, saved_palette0[i]); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL, saved_rtest_ctrl); + NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX, saved_pi); + NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1); + NVWriteVgaSeq(dev, 0, NV_VIO_SR_CLOCK_INDEX, saved_seq1); + + if (blue == 0x18) { + NV_TRACE(dev, "Load detected on head A\n"); + return connector_status_connected; + } + + return connector_status_disconnected; +} + +enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + uint32_t testval, regoffset = nv04_dac_output_offset(encoder); + uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, + saved_rtest_ctrl, saved_gpio0, saved_gpio1, temp, routput; + int head, present = 0; + +#define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20) + if (dcb->type == OUTPUT_TV) { + testval = RGB_TEST_DATA(0xa0, 0xa0, 0xa0); + + if (dev_priv->vbios->tvdactestval) + testval = dev_priv->vbios->tvdactestval; + } else { + testval = RGB_TEST_DATA(0x140, 0x140, 0x140); /* 0x94050140 */ + + if (dev_priv->vbios->dactestval) + testval = dev_priv->vbios->dactestval; + } + + saved_rtest_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, + saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF); + + saved_powerctrl_2 = nvReadMC(dev, NV_PBUS_POWERCTRL_2); + + nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff); + if (regoffset == 0x68) { + saved_powerctrl_4 = nvReadMC(dev, NV_PBUS_POWERCTRL_4); + nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf); + } + + saved_gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1); + saved_gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0); + + nv17_gpio_set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV); + nv17_gpio_set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV); + + msleep(4); + + saved_routput = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset); + head = (saved_routput & 0x100) >> 8; +#if 0 + /* if there's a spare crtc, using it will minimise flicker for the case + * where the in-use crtc is in use by an off-chip tmds encoder */ + if (xf86_config->crtc[head]->enabled && !xf86_config->crtc[head ^ 1]->enabled) + head ^= 1; +#endif + /* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */ + routput = (saved_routput & 0xfffffece) | head << 8; + + if (dev_priv->card_type >= NV_40) { + if (dcb->type == OUTPUT_TV) + routput |= 0x1a << 16; + else + routput &= ~(0x1a << 16); + } + + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, routput); + msleep(1); + + temp = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, temp | 1); + + NVWriteRAMDAC(dev, head, NV_PRAMDAC_TESTPOINT_DATA, + NV_PRAMDAC_TESTPOINT_DATA_NOTBLANK | testval); + temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL, + temp | NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED); + msleep(5); + + temp = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); + + if (dcb->type == OUTPUT_TV) + present = (nv17_tv_detect(encoder, connector, temp) + == connector_status_connected); + else + present = temp & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI; + + temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL, + temp & ~NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_TESTPOINT_DATA, 0); + + /* bios does something more complex for restoring, but I think this is good enough */ + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, saved_routput); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl); + if (regoffset == 0x68) + nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4); + nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); + + nv17_gpio_set(dev, DCB_GPIO_TVDAC1, saved_gpio1); + nv17_gpio_set(dev, DCB_GPIO_TVDAC0, saved_gpio0); + + if (present) { + NV_INFO(dev, "Load detected on output %c\n", '@' + ffs(dcb->or)); + return connector_status_connected; + } + + return connector_status_disconnected; +} + + +static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static void nv04_dac_prepare(struct drm_encoder *encoder) +{ + struct drm_encoder_helper_funcs *helper = encoder->helper_private; + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int head = nouveau_crtc(encoder->crtc)->index; + struct nv04_crtc_reg *crtcstate = dev_priv->mode_reg.crtc_reg; + + helper->dpms(encoder, DRM_MODE_DPMS_OFF); + + nv04_dfp_disable(dev, head); + + /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f) + * at LCD__INDEX which we don't alter + */ + if (!(crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] & 0x44)) + crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] = 0; +} + + +static void nv04_dac_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int head = nouveau_crtc(encoder->crtc)->index; + + NV_TRACE(dev, "%s called for encoder %d\n", __func__, + nv_encoder->dcb->index); + + if (nv_gf4_disp_arch(dev)) { + struct drm_encoder *rebind; + uint32_t dac_offset = nv04_dac_output_offset(encoder); + uint32_t otherdac; + + /* bit 16-19 are bits that are set on some G70 cards, + * but don't seem to have much effect */ + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + dac_offset, + head << 8 | NV_PRAMDAC_DACCLK_SEL_DACCLK); + /* force any other vga encoders to bind to the other crtc */ + list_for_each_entry(rebind, &dev->mode_config.encoder_list, head) { + if (rebind == encoder + || nouveau_encoder(rebind)->dcb->type != OUTPUT_ANALOG) + continue; + + dac_offset = nv04_dac_output_offset(rebind); + otherdac = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + dac_offset); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + dac_offset, + (otherdac & ~0x0100) | (head ^ 1) << 8); + } + } + + /* This could use refinement for flatpanels, but it should work this way */ + if (dev_priv->chipset < 0x44) + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000); + else + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); +} + +static void nv04_dac_commit(struct drm_encoder *encoder) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); + struct drm_encoder_helper_funcs *helper = encoder->helper_private; + + helper->dpms(encoder, DRM_MODE_DPMS_ON); + + NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), + nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); +} + +void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) +{ + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + + if (nv_gf4_disp_arch(dev)) { + uint32_t *dac_users = &dev_priv->dac_users[ffs(dcb->or) - 1]; + int dacclk_off = NV_PRAMDAC_DACCLK + nv04_dac_output_offset(encoder); + uint32_t dacclk = NVReadRAMDAC(dev, 0, dacclk_off); + + if (enable) { + *dac_users |= 1 << dcb->index; + NVWriteRAMDAC(dev, 0, dacclk_off, dacclk | NV_PRAMDAC_DACCLK_SEL_DACCLK); + + } else { + *dac_users &= ~(1 << dcb->index); + if (!*dac_users) + NVWriteRAMDAC(dev, 0, dacclk_off, + dacclk & ~NV_PRAMDAC_DACCLK_SEL_DACCLK); + } + } +} + +static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + if (nv_encoder->last_dpms == mode) + return; + nv_encoder->last_dpms = mode; + + NV_INFO(dev, "Setting dpms mode %d on vga encoder (output %d)\n", + mode, nv_encoder->dcb->index); + + nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); +} + +static void nv04_dac_save(struct drm_encoder *encoder) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + + if (nv_gf4_disp_arch(dev)) + nv_encoder->restore.output = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + + nv04_dac_output_offset(encoder)); +} + +static void nv04_dac_restore(struct drm_encoder *encoder) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + + if (nv_gf4_disp_arch(dev)) + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + nv04_dac_output_offset(encoder), + nv_encoder->restore.output); + + nv_encoder->last_dpms = NV_DPMS_CLEARED; +} + +static void nv04_dac_destroy(struct drm_encoder *encoder) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + NV_DEBUG(encoder->dev, "\n"); + + drm_encoder_cleanup(encoder); + kfree(nv_encoder); +} + +static const struct drm_encoder_helper_funcs nv04_dac_helper_funcs = { + .dpms = nv04_dac_dpms, + .save = nv04_dac_save, + .restore = nv04_dac_restore, + .mode_fixup = nv04_dac_mode_fixup, + .prepare = nv04_dac_prepare, + .commit = nv04_dac_commit, + .mode_set = nv04_dac_mode_set, + .detect = nv04_dac_detect +}; + +static const struct drm_encoder_helper_funcs nv17_dac_helper_funcs = { + .dpms = nv04_dac_dpms, + .save = nv04_dac_save, + .restore = nv04_dac_restore, + .mode_fixup = nv04_dac_mode_fixup, + .prepare = nv04_dac_prepare, + .commit = nv04_dac_commit, + .mode_set = nv04_dac_mode_set, + .detect = nv17_dac_detect +}; + +static const struct drm_encoder_funcs nv04_dac_funcs = { + .destroy = nv04_dac_destroy, +}; + +int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry) +{ + const struct drm_encoder_helper_funcs *helper; + struct drm_encoder *encoder; + struct nouveau_encoder *nv_encoder = NULL; + + nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); + if (!nv_encoder) + return -ENOMEM; + + encoder = to_drm_encoder(nv_encoder); + + nv_encoder->dcb = entry; + nv_encoder->or = ffs(entry->or) - 1; + + if (nv_gf4_disp_arch(dev)) + helper = &nv17_dac_helper_funcs; + else + helper = &nv04_dac_helper_funcs; + + drm_encoder_init(dev, encoder, &nv04_dac_funcs, DRM_MODE_ENCODER_DAC); + drm_encoder_helper_add(encoder, helper); + + encoder->possible_crtcs = entry->heads; + encoder->possible_clones = 0; + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c new file mode 100644 index 0000000000000000000000000000000000000000..e5b33339d595f262dd024a7d2349a48d9471b1b2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -0,0 +1,621 @@ +/* + * Copyright 2003 NVIDIA, Corporation + * Copyright 2006 Dave Airlie + * Copyright 2007 Maarten Maathuis + * Copyright 2007-2009 Stuart Bennett + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 "drmP.h" +#include "drm_crtc_helper.h" + +#include "nouveau_drv.h" +#include "nouveau_encoder.h" +#include "nouveau_connector.h" +#include "nouveau_crtc.h" +#include "nouveau_hw.h" +#include "nvreg.h" + +#define FP_TG_CONTROL_ON (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | \ + NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | \ + NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS) +#define FP_TG_CONTROL_OFF (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_DISABLE | \ + NV_PRAMDAC_FP_TG_CONTROL_HSYNC_DISABLE | \ + NV_PRAMDAC_FP_TG_CONTROL_VSYNC_DISABLE) + +static inline bool is_fpc_off(uint32_t fpc) +{ + return ((fpc & (FP_TG_CONTROL_ON | FP_TG_CONTROL_OFF)) == + FP_TG_CONTROL_OFF); +} + +int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent) +{ + /* special case of nv_read_tmds to find crtc associated with an output. + * this does not give a correct answer for off-chip dvi, but there's no + * use for such an answer anyway + */ + int ramdac = (dcbent->or & OUTPUT_C) >> 2; + + NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL, + NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | 0x4); + return ((NVReadRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA) & 0x8) >> 3) ^ ramdac; +} + +void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent, + int head, bool dl) +{ + /* The BIOS scripts don't do this for us, sadly + * Luckily we do know the values ;-) + * + * head < 0 indicates we wish to force a setting with the overrideval + * (for VT restore etc.) + */ + + int ramdac = (dcbent->or & OUTPUT_C) >> 2; + uint8_t tmds04 = 0x80; + + if (head != ramdac) + tmds04 = 0x88; + + if (dcbent->type == OUTPUT_LVDS) + tmds04 |= 0x01; + + nv_write_tmds(dev, dcbent->or, 0, 0x04, tmds04); + + if (dl) /* dual link */ + nv_write_tmds(dev, dcbent->or, 1, 0x04, tmds04 ^ 0x08); +} + +void nv04_dfp_disable(struct drm_device *dev, int head) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_crtc_reg *crtcstate = dev_priv->mode_reg.crtc_reg; + + if (NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL) & + FP_TG_CONTROL_ON) { + /* digital remnants must be cleaned before new crtc + * values programmed. delay is time for the vga stuff + * to realise it's in control again + */ + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL, + FP_TG_CONTROL_OFF); + msleep(50); + } + /* don't inadvertently turn it on when state written later */ + crtcstate[head].fp_control = FP_TG_CONTROL_OFF; +} + +void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc; + struct nouveau_crtc *nv_crtc; + uint32_t *fpc; + + if (mode == DRM_MODE_DPMS_ON) { + nv_crtc = nouveau_crtc(encoder->crtc); + fpc = &dev_priv->mode_reg.crtc_reg[nv_crtc->index].fp_control; + + if (is_fpc_off(*fpc)) { + /* using saved value is ok, as (is_digital && dpms_on && + * fp_control==OFF) is (at present) *only* true when + * fpc's most recent change was by below "off" code + */ + *fpc = nv_crtc->dpms_saved_fp_control; + } + + nv_crtc->fp_users |= 1 << nouveau_encoder(encoder)->dcb->index; + NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_FP_TG_CONTROL, *fpc); + } else { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + nv_crtc = nouveau_crtc(crtc); + fpc = &dev_priv->mode_reg.crtc_reg[nv_crtc->index].fp_control; + + nv_crtc->fp_users &= ~(1 << nouveau_encoder(encoder)->dcb->index); + if (!is_fpc_off(*fpc) && !nv_crtc->fp_users) { + nv_crtc->dpms_saved_fp_control = *fpc; + /* cut the FP output */ + *fpc &= ~FP_TG_CONTROL_ON; + *fpc |= FP_TG_CONTROL_OFF; + NVWriteRAMDAC(dev, nv_crtc->index, + NV_PRAMDAC_FP_TG_CONTROL, *fpc); + } + } + } +} + +static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder); + + /* For internal panels and gpu scaling on DVI we need the native mode */ + if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) { + if (!nv_connector->native_mode) + return false; + nv_encoder->mode = *nv_connector->native_mode; + adjusted_mode->clock = nv_connector->native_mode->clock; + } else { + nv_encoder->mode = *adjusted_mode; + } + + return true; +} + +static void nv04_dfp_prepare_sel_clk(struct drm_device *dev, + struct nouveau_encoder *nv_encoder, int head) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_mode_state *state = &dev_priv->mode_reg; + uint32_t bits1618 = nv_encoder->dcb->or & OUTPUT_A ? 0x10000 : 0x40000; + + if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP) + return; + + /* SEL_CLK is only used on the primary ramdac + * It toggles spread spectrum PLL output and sets the bindings of PLLs + * to heads on digital outputs + */ + if (head) + state->sel_clk |= bits1618; + else + state->sel_clk &= ~bits1618; + + /* nv30: + * bit 0 NVClk spread spectrum on/off + * bit 2 MemClk spread spectrum on/off + * bit 4 PixClk1 spread spectrum on/off toggle + * bit 6 PixClk2 spread spectrum on/off toggle + * + * nv40 (observations from bios behaviour and mmio traces): + * bits 4&6 as for nv30 + * bits 5&7 head dependent as for bits 4&6, but do not appear with 4&6; + * maybe a different spread mode + * bits 8&10 seen on dual-link dvi outputs, purpose unknown (set by POST scripts) + * The logic behind turning spread spectrum on/off in the first place, + * and which bit-pair to use, is unclear on nv40 (for earlier cards, the fp table + * entry has the necessary info) + */ + if (nv_encoder->dcb->type == OUTPUT_LVDS && dev_priv->saved_reg.sel_clk & 0xf0) { + int shift = (dev_priv->saved_reg.sel_clk & 0x50) ? 0 : 1; + + state->sel_clk &= ~0xf0; + state->sel_clk |= (head ? 0x40 : 0x10) << shift; + } +} + +static void nv04_dfp_prepare(struct drm_encoder *encoder) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_encoder_helper_funcs *helper = encoder->helper_private; + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int head = nouveau_crtc(encoder->crtc)->index; + struct nv04_crtc_reg *crtcstate = dev_priv->mode_reg.crtc_reg; + uint8_t *cr_lcd = &crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX]; + uint8_t *cr_lcd_oth = &crtcstate[head ^ 1].CRTC[NV_CIO_CRE_LCD__INDEX]; + + helper->dpms(encoder, DRM_MODE_DPMS_OFF); + + nv04_dfp_prepare_sel_clk(dev, nv_encoder, head); + + /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f) + * at LCD__INDEX which we don't alter + */ + if (!(*cr_lcd & 0x44)) { + *cr_lcd = 0x3; + + if (nv_two_heads(dev)) { + if (nv_encoder->dcb->location == DCB_LOC_ON_CHIP) + *cr_lcd |= head ? 0x0 : 0x8; + else { + *cr_lcd |= (nv_encoder->dcb->or << 4) & 0x30; + if (nv_encoder->dcb->type == OUTPUT_LVDS) + *cr_lcd |= 0x30; + if ((*cr_lcd & 0x30) == (*cr_lcd_oth & 0x30)) { + /* avoid being connected to both crtcs */ + *cr_lcd_oth &= ~0x30; + NVWriteVgaCrtc(dev, head ^ 1, + NV_CIO_CRE_LCD__INDEX, + *cr_lcd_oth); + } + } + } + } +} + + +static void nv04_dfp_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); + struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index]; + struct nv04_crtc_reg *savep = &dev_priv->saved_reg.crtc_reg[nv_crtc->index]; + struct nouveau_connector *nv_connector = nouveau_crtc_connector_get(nv_crtc); + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_display_mode *output_mode = &nv_encoder->mode; + uint32_t mode_ratio, panel_ratio; + + NV_DEBUG(dev, "Output mode on CRTC %d:\n", nv_crtc->index); + drm_mode_debug_printmodeline(output_mode); + + /* Initialize the FP registers in this CRTC. */ + regp->fp_horiz_regs[FP_DISPLAY_END] = output_mode->hdisplay - 1; + regp->fp_horiz_regs[FP_TOTAL] = output_mode->htotal - 1; + if (!nv_gf4_disp_arch(dev) || + (output_mode->hsync_start - output_mode->hdisplay) >= + dev_priv->vbios->digital_min_front_porch) + regp->fp_horiz_regs[FP_CRTC] = output_mode->hdisplay; + else + regp->fp_horiz_regs[FP_CRTC] = output_mode->hsync_start - dev_priv->vbios->digital_min_front_porch - 1; + regp->fp_horiz_regs[FP_SYNC_START] = output_mode->hsync_start - 1; + regp->fp_horiz_regs[FP_SYNC_END] = output_mode->hsync_end - 1; + regp->fp_horiz_regs[FP_VALID_START] = output_mode->hskew; + regp->fp_horiz_regs[FP_VALID_END] = output_mode->hdisplay - 1; + + regp->fp_vert_regs[FP_DISPLAY_END] = output_mode->vdisplay - 1; + regp->fp_vert_regs[FP_TOTAL] = output_mode->vtotal - 1; + regp->fp_vert_regs[FP_CRTC] = output_mode->vtotal - 5 - 1; + regp->fp_vert_regs[FP_SYNC_START] = output_mode->vsync_start - 1; + regp->fp_vert_regs[FP_SYNC_END] = output_mode->vsync_end - 1; + regp->fp_vert_regs[FP_VALID_START] = 0; + regp->fp_vert_regs[FP_VALID_END] = output_mode->vdisplay - 1; + + /* bit26: a bit seen on some g7x, no as yet discernable purpose */ + regp->fp_control = NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | + (savep->fp_control & (1 << 26 | NV_PRAMDAC_FP_TG_CONTROL_READ_PROG)); + /* Deal with vsync/hsync polarity */ + /* LVDS screens do set this, but modes with +ve syncs are very rare */ + if (output_mode->flags & DRM_MODE_FLAG_PVSYNC) + regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS; + if (output_mode->flags & DRM_MODE_FLAG_PHSYNC) + regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS; + /* panel scaling first, as native would get set otherwise */ + if (nv_connector->scaling_mode == DRM_MODE_SCALE_NONE || + nv_connector->scaling_mode == DRM_MODE_SCALE_CENTER) /* panel handles it */ + regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_CENTER; + else if (adjusted_mode->hdisplay == output_mode->hdisplay && + adjusted_mode->vdisplay == output_mode->vdisplay) /* native mode */ + regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_NATIVE; + else /* gpu needs to scale */ + regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_SCALE; + if (nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT) + regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12; + if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP && + output_mode->clock > 165000) + regp->fp_control |= (2 << 24); + if (nv_encoder->dcb->type == OUTPUT_LVDS) { + bool duallink, dummy; + + nouveau_bios_parse_lvds_table(dev, nv_connector->native_mode-> + clock, &duallink, &dummy); + if (duallink) + regp->fp_control |= (8 << 28); + } else + if (output_mode->clock > 165000) + regp->fp_control |= (8 << 28); + + regp->fp_debug_0 = NV_PRAMDAC_FP_DEBUG_0_YWEIGHT_ROUND | + NV_PRAMDAC_FP_DEBUG_0_XWEIGHT_ROUND | + NV_PRAMDAC_FP_DEBUG_0_YINTERP_BILINEAR | + NV_PRAMDAC_FP_DEBUG_0_XINTERP_BILINEAR | + NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED | + NV_PRAMDAC_FP_DEBUG_0_YSCALE_ENABLE | + NV_PRAMDAC_FP_DEBUG_0_XSCALE_ENABLE; + + /* We want automatic scaling */ + regp->fp_debug_1 = 0; + /* This can override HTOTAL and VTOTAL */ + regp->fp_debug_2 = 0; + + /* Use 20.12 fixed point format to avoid floats */ + mode_ratio = (1 << 12) * adjusted_mode->hdisplay / adjusted_mode->vdisplay; + panel_ratio = (1 << 12) * output_mode->hdisplay / output_mode->vdisplay; + /* if ratios are equal, SCALE_ASPECT will automatically (and correctly) + * get treated the same as SCALE_FULLSCREEN */ + if (nv_connector->scaling_mode == DRM_MODE_SCALE_ASPECT && + mode_ratio != panel_ratio) { + uint32_t diff, scale; + bool divide_by_2 = nv_gf4_disp_arch(dev); + + if (mode_ratio < panel_ratio) { + /* vertical needs to expand to glass size (automatic) + * horizontal needs to be scaled at vertical scale factor + * to maintain aspect */ + + scale = (1 << 12) * adjusted_mode->vdisplay / output_mode->vdisplay; + regp->fp_debug_1 = NV_PRAMDAC_FP_DEBUG_1_XSCALE_TESTMODE_ENABLE | + XLATE(scale, divide_by_2, NV_PRAMDAC_FP_DEBUG_1_XSCALE_VALUE); + + /* restrict area of screen used, horizontally */ + diff = output_mode->hdisplay - + output_mode->vdisplay * mode_ratio / (1 << 12); + regp->fp_horiz_regs[FP_VALID_START] += diff / 2; + regp->fp_horiz_regs[FP_VALID_END] -= diff / 2; + } + + if (mode_ratio > panel_ratio) { + /* horizontal needs to expand to glass size (automatic) + * vertical needs to be scaled at horizontal scale factor + * to maintain aspect */ + + scale = (1 << 12) * adjusted_mode->hdisplay / output_mode->hdisplay; + regp->fp_debug_1 = NV_PRAMDAC_FP_DEBUG_1_YSCALE_TESTMODE_ENABLE | + XLATE(scale, divide_by_2, NV_PRAMDAC_FP_DEBUG_1_YSCALE_VALUE); + + /* restrict area of screen used, vertically */ + diff = output_mode->vdisplay - + (1 << 12) * output_mode->hdisplay / mode_ratio; + regp->fp_vert_regs[FP_VALID_START] += diff / 2; + regp->fp_vert_regs[FP_VALID_END] -= diff / 2; + } + } + + /* Output property. */ + if (nv_connector->use_dithering) { + if (dev_priv->chipset == 0x11) + regp->dither = savep->dither | 0x00010000; + else { + int i; + regp->dither = savep->dither | 0x00000001; + for (i = 0; i < 3; i++) { + regp->dither_regs[i] = 0xe4e4e4e4; + regp->dither_regs[i + 3] = 0x44444444; + } + } + } else { + if (dev_priv->chipset != 0x11) { + /* reset them */ + int i; + for (i = 0; i < 3; i++) { + regp->dither_regs[i] = savep->dither_regs[i]; + regp->dither_regs[i + 3] = savep->dither_regs[i + 3]; + } + } + regp->dither = savep->dither; + } + + regp->fp_margin_color = 0; +} + +static void nv04_dfp_commit(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_encoder_helper_funcs *helper = encoder->helper_private; + struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct dcb_entry *dcbe = nv_encoder->dcb; + int head = nouveau_crtc(encoder->crtc)->index; + + NV_TRACE(dev, "%s called for encoder %d\n", __func__, nv_encoder->dcb->index); + + if (dcbe->type == OUTPUT_TMDS) + run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock); + else if (dcbe->type == OUTPUT_LVDS) + call_lvds_script(dev, dcbe, head, LVDS_RESET, nv_encoder->mode.clock); + + /* update fp_control state for any changes made by scripts, + * so correct value is written at DPMS on */ + dev_priv->mode_reg.crtc_reg[head].fp_control = + NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL); + + /* This could use refinement for flatpanels, but it should work this way */ + if (dev_priv->chipset < 0x44) + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000); + else + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); + + helper->dpms(encoder, DRM_MODE_DPMS_ON); + + NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), + nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); +} + +static inline bool is_powersaving_dpms(int mode) +{ + return (mode != DRM_MODE_DPMS_ON); +} + +static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_crtc *crtc = encoder->crtc; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + bool was_powersaving = is_powersaving_dpms(nv_encoder->last_dpms); + + if (nv_encoder->last_dpms == mode) + return; + nv_encoder->last_dpms = mode; + + NV_INFO(dev, "Setting dpms mode %d on lvds encoder (output %d)\n", + mode, nv_encoder->dcb->index); + + if (was_powersaving && is_powersaving_dpms(mode)) + return; + + if (nv_encoder->dcb->lvdsconf.use_power_scripts) { + struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder); + + /* when removing an output, crtc may not be set, but PANEL_OFF + * must still be run + */ + int head = crtc ? nouveau_crtc(crtc)->index : + nv04_dfp_get_bound_head(dev, nv_encoder->dcb); + + if (mode == DRM_MODE_DPMS_ON) { + if (!nv_connector->native_mode) { + NV_ERROR(dev, "Not turning on LVDS without native mode\n"); + return; + } + call_lvds_script(dev, nv_encoder->dcb, head, + LVDS_PANEL_ON, nv_connector->native_mode->clock); + } else + /* pxclk of 0 is fine for PANEL_OFF, and for a + * disconnected LVDS encoder there is no native_mode + */ + call_lvds_script(dev, nv_encoder->dcb, head, + LVDS_PANEL_OFF, 0); + } + + nv04_dfp_update_fp_control(encoder, mode); + + if (mode == DRM_MODE_DPMS_ON) + nv04_dfp_prepare_sel_clk(dev, nv_encoder, nouveau_crtc(crtc)->index); + else { + dev_priv->mode_reg.sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK); + dev_priv->mode_reg.sel_clk &= ~0xf0; + } + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, dev_priv->mode_reg.sel_clk); +} + +static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + if (nv_encoder->last_dpms == mode) + return; + nv_encoder->last_dpms = mode; + + NV_INFO(dev, "Setting dpms mode %d on tmds encoder (output %d)\n", + mode, nv_encoder->dcb->index); + + nv04_dfp_update_fp_control(encoder, mode); +} + +static void nv04_dfp_save(struct drm_encoder *encoder) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + + if (nv_two_heads(dev)) + nv_encoder->restore.head = + nv04_dfp_get_bound_head(dev, nv_encoder->dcb); +} + +static void nv04_dfp_restore(struct drm_encoder *encoder) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int head = nv_encoder->restore.head; + + if (nv_encoder->dcb->type == OUTPUT_LVDS) { + struct drm_display_mode *native_mode = nouveau_encoder_connector_get(nv_encoder)->native_mode; + if (native_mode) + call_lvds_script(dev, nv_encoder->dcb, head, LVDS_PANEL_ON, + native_mode->clock); + else + NV_ERROR(dev, "Not restoring LVDS without native mode\n"); + + } else if (nv_encoder->dcb->type == OUTPUT_TMDS) { + int clock = nouveau_hw_pllvals_to_clk + (&dev_priv->saved_reg.crtc_reg[head].pllvals); + + run_tmds_table(dev, nv_encoder->dcb, head, clock); + } + + nv_encoder->last_dpms = NV_DPMS_CLEARED; +} + +static void nv04_dfp_destroy(struct drm_encoder *encoder) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + NV_DEBUG(encoder->dev, "\n"); + + drm_encoder_cleanup(encoder); + kfree(nv_encoder); +} + +static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { + .dpms = nv04_lvds_dpms, + .save = nv04_dfp_save, + .restore = nv04_dfp_restore, + .mode_fixup = nv04_dfp_mode_fixup, + .prepare = nv04_dfp_prepare, + .commit = nv04_dfp_commit, + .mode_set = nv04_dfp_mode_set, + .detect = NULL, +}; + +static const struct drm_encoder_helper_funcs nv04_tmds_helper_funcs = { + .dpms = nv04_tmds_dpms, + .save = nv04_dfp_save, + .restore = nv04_dfp_restore, + .mode_fixup = nv04_dfp_mode_fixup, + .prepare = nv04_dfp_prepare, + .commit = nv04_dfp_commit, + .mode_set = nv04_dfp_mode_set, + .detect = NULL, +}; + +static const struct drm_encoder_funcs nv04_dfp_funcs = { + .destroy = nv04_dfp_destroy, +}; + +int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry) +{ + const struct drm_encoder_helper_funcs *helper; + struct drm_encoder *encoder; + struct nouveau_encoder *nv_encoder = NULL; + int type; + + switch (entry->type) { + case OUTPUT_TMDS: + type = DRM_MODE_ENCODER_TMDS; + helper = &nv04_tmds_helper_funcs; + break; + case OUTPUT_LVDS: + type = DRM_MODE_ENCODER_LVDS; + helper = &nv04_lvds_helper_funcs; + break; + default: + return -EINVAL; + } + + nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); + if (!nv_encoder) + return -ENOMEM; + + encoder = to_drm_encoder(nv_encoder); + + nv_encoder->dcb = entry; + nv_encoder->or = ffs(entry->or) - 1; + + drm_encoder_init(dev, encoder, &nv04_dfp_funcs, type); + drm_encoder_helper_add(encoder, helper); + + encoder->possible_crtcs = entry->heads; + encoder->possible_clones = 0; + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c new file mode 100644 index 0000000000000000000000000000000000000000..b47c757ff48b3d9294de8bf6b2efd43cc90281ff --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_display.c @@ -0,0 +1,288 @@ +/* + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Author: Ben Skeggs + */ + +#include "drmP.h" +#include "drm.h" +#include "drm_crtc_helper.h" + +#include "nouveau_drv.h" +#include "nouveau_fb.h" +#include "nouveau_hw.h" +#include "nouveau_encoder.h" +#include "nouveau_connector.h" + +#define MULTIPLE_ENCODERS(e) (e & (e - 1)) + +static void +nv04_display_store_initial_head_owner(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->chipset != 0x11) { + dev_priv->crtc_owner = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44); + goto ownerknown; + } + + /* reading CR44 is broken on nv11, so we attempt to infer it */ + if (nvReadMC(dev, NV_PBUS_DEBUG_1) & (1 << 28)) /* heads tied, restore both */ + dev_priv->crtc_owner = 0x4; + else { + uint8_t slaved_on_A, slaved_on_B; + bool tvA = false; + bool tvB = false; + + NVLockVgaCrtcs(dev, false); + + slaved_on_B = NVReadVgaCrtc(dev, 1, NV_CIO_CRE_PIXEL_INDEX) & + 0x80; + if (slaved_on_B) + tvB = !(NVReadVgaCrtc(dev, 1, NV_CIO_CRE_LCD__INDEX) & + MASK(NV_CIO_CRE_LCD_LCD_SELECT)); + + slaved_on_A = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX) & + 0x80; + if (slaved_on_A) + tvA = !(NVReadVgaCrtc(dev, 0, NV_CIO_CRE_LCD__INDEX) & + MASK(NV_CIO_CRE_LCD_LCD_SELECT)); + + NVLockVgaCrtcs(dev, true); + + if (slaved_on_A && !tvA) + dev_priv->crtc_owner = 0x0; + else if (slaved_on_B && !tvB) + dev_priv->crtc_owner = 0x3; + else if (slaved_on_A) + dev_priv->crtc_owner = 0x0; + else if (slaved_on_B) + dev_priv->crtc_owner = 0x3; + else + dev_priv->crtc_owner = 0x0; + } + +ownerknown: + NV_INFO(dev, "Initial CRTC_OWNER is %d\n", dev_priv->crtc_owner); + + /* we need to ensure the heads are not tied henceforth, or reading any + * 8 bit reg on head B will fail + * setting a single arbitrary head solves that */ + NVSetOwner(dev, 0); +} + +int +nv04_display_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct parsed_dcb *dcb = dev_priv->vbios->dcb; + struct drm_encoder *encoder; + struct drm_crtc *crtc; + uint16_t connector[16] = { 0 }; + int i, ret; + + NV_DEBUG(dev, "\n"); + + if (nv_two_heads(dev)) + nv04_display_store_initial_head_owner(dev); + + drm_mode_config_init(dev); + drm_mode_create_scaling_mode_property(dev); + drm_mode_create_dithering_property(dev); + + dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; + + dev->mode_config.min_width = 0; + dev->mode_config.min_height = 0; + switch (dev_priv->card_type) { + case NV_04: + dev->mode_config.max_width = 2048; + dev->mode_config.max_height = 2048; + break; + default: + dev->mode_config.max_width = 4096; + dev->mode_config.max_height = 4096; + break; + } + + dev->mode_config.fb_base = dev_priv->fb_phys; + + nv04_crtc_create(dev, 0); + if (nv_two_heads(dev)) + nv04_crtc_create(dev, 1); + + for (i = 0; i < dcb->entries; i++) { + struct dcb_entry *dcbent = &dcb->entry[i]; + + switch (dcbent->type) { + case OUTPUT_ANALOG: + ret = nv04_dac_create(dev, dcbent); + break; + case OUTPUT_LVDS: + case OUTPUT_TMDS: + ret = nv04_dfp_create(dev, dcbent); + break; + case OUTPUT_TV: + if (dcbent->location == DCB_LOC_ON_CHIP) + ret = nv17_tv_create(dev, dcbent); + else + ret = nv04_tv_create(dev, dcbent); + break; + default: + NV_WARN(dev, "DCB type %d not known\n", dcbent->type); + continue; + } + + if (ret) + continue; + + connector[dcbent->connector] |= (1 << dcbent->type); + } + + for (i = 0; i < dcb->entries; i++) { + struct dcb_entry *dcbent = &dcb->entry[i]; + uint16_t encoders; + int type; + + encoders = connector[dcbent->connector]; + if (!(encoders & (1 << dcbent->type))) + continue; + connector[dcbent->connector] = 0; + + switch (dcbent->type) { + case OUTPUT_ANALOG: + if (!MULTIPLE_ENCODERS(encoders)) + type = DRM_MODE_CONNECTOR_VGA; + else + type = DRM_MODE_CONNECTOR_DVII; + break; + case OUTPUT_TMDS: + if (!MULTIPLE_ENCODERS(encoders)) + type = DRM_MODE_CONNECTOR_DVID; + else + type = DRM_MODE_CONNECTOR_DVII; + break; + case OUTPUT_LVDS: + type = DRM_MODE_CONNECTOR_LVDS; +#if 0 + /* don't create i2c adapter when lvds ddc not allowed */ + if (dcbent->lvdsconf.use_straps_for_mode || + dev_priv->vbios->fp_no_ddc) + i2c_index = 0xf; +#endif + break; + case OUTPUT_TV: + type = DRM_MODE_CONNECTOR_TV; + break; + default: + type = DRM_MODE_CONNECTOR_Unknown; + continue; + } + + nouveau_connector_create(dev, dcbent->connector, type); + } + + /* Save previous state */ + NVLockVgaCrtcs(dev, false); + + nouveau_hw_save_vga_fonts(dev, 1); + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + crtc->funcs->save(crtc); + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct drm_encoder_helper_funcs *func = encoder->helper_private; + + func->save(encoder); + } + + return 0; +} + +void +nv04_display_destroy(struct drm_device *dev) +{ + struct drm_encoder *encoder; + struct drm_crtc *crtc; + + NV_DEBUG(dev, "\n"); + + /* Turn every CRTC off. */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct drm_mode_set modeset = { + .crtc = crtc, + }; + + crtc->funcs->set_config(&modeset); + } + + /* Restore state */ + NVLockVgaCrtcs(dev, false); + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct drm_encoder_helper_funcs *func = encoder->helper_private; + + func->restore(encoder); + } + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + crtc->funcs->restore(crtc); + + nouveau_hw_save_vga_fonts(dev, 0); + + drm_mode_config_cleanup(dev); +} + +void +nv04_display_restore(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_encoder *encoder; + struct drm_crtc *crtc; + + NVLockVgaCrtcs(dev, false); + + /* meh.. modeset apparently doesn't setup all the regs and depends + * on pre-existing state, for now load the state of the card *before* + * nouveau was loaded, and then do a modeset. + * + * best thing to do probably is to make save/restore routines not + * save/restore "pre-load" state, but more general so we can save + * on suspend too. + */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct drm_encoder_helper_funcs *func = encoder->helper_private; + + func->restore(encoder); + } + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + crtc->funcs->restore(crtc); + + if (nv_two_heads(dev)) { + NV_INFO(dev, "Restoring CRTC_OWNER to %d.\n", + dev_priv->crtc_owner); + NVSetOwner(dev, dev_priv->crtc_owner); + } + + NVLockVgaCrtcs(dev, true); +} + diff --git a/drivers/gpu/drm/nouveau/nv04_fb.c b/drivers/gpu/drm/nouveau/nv04_fb.c new file mode 100644 index 0000000000000000000000000000000000000000..638cf601c427af2293f7065e73bd2fe45b5276b1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_fb.c @@ -0,0 +1,21 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv04_fb_init(struct drm_device *dev) +{ + /* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows + * nvidia reading PFB_CFG_0, then writing back its original value. + * (which was 0x701114 in this case) + */ + + nv_wr32(dev, NV04_PFB_CFG0, 0x1114); + return 0; +} + +void +nv04_fb_takedown(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c new file mode 100644 index 0000000000000000000000000000000000000000..09a31071ee587e585eb6b2eb192ec7f12d9043c9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c @@ -0,0 +1,316 @@ +/* + * Copyright 2009 Ben Skeggs + * Copyright 2008 Stuart Bennett + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_dma.h" +#include "nouveau_fbcon.h" + +static void +nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) +{ + struct nouveau_fbcon_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->channel; + + if (info->state != FBINFO_STATE_RUNNING) + return; + + if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 4)) { + NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + info->flags |= FBINFO_HWACCEL_DISABLED; + } + + if (info->flags & FBINFO_HWACCEL_DISABLED) { + cfb_copyarea(info, region); + return; + } + + BEGIN_RING(chan, NvSubImageBlit, 0x0300, 3); + OUT_RING(chan, (region->sy << 16) | region->sx); + OUT_RING(chan, (region->dy << 16) | region->dx); + OUT_RING(chan, (region->height << 16) | region->width); + FIRE_RING(chan); +} + +static void +nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +{ + struct nouveau_fbcon_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->channel; + uint32_t color = ((uint32_t *) info->pseudo_palette)[rect->color]; + + if (info->state != FBINFO_STATE_RUNNING) + return; + + if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) { + NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + info->flags |= FBINFO_HWACCEL_DISABLED; + } + + if (info->flags & FBINFO_HWACCEL_DISABLED) { + cfb_fillrect(info, rect); + return; + } + + BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1); + OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3); + BEGIN_RING(chan, NvSubGdiRect, 0x03fc, 1); + OUT_RING(chan, color); + BEGIN_RING(chan, NvSubGdiRect, 0x0400, 2); + OUT_RING(chan, (rect->dx << 16) | rect->dy); + OUT_RING(chan, (rect->width << 16) | rect->height); + FIRE_RING(chan); +} + +static void +nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) +{ + struct nouveau_fbcon_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->channel; + uint32_t fg; + uint32_t bg; + uint32_t dsize; + uint32_t width; + uint32_t *data = (uint32_t *)image->data; + + if (info->state != FBINFO_STATE_RUNNING) + return; + + if (image->depth != 1) { + cfb_imageblit(info, image); + return; + } + + if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 8)) { + NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + info->flags |= FBINFO_HWACCEL_DISABLED; + } + + if (info->flags & FBINFO_HWACCEL_DISABLED) { + cfb_imageblit(info, image); + return; + } + + width = (image->width + 31) & ~31; + dsize = (width * image->height) >> 5; + + if (info->fix.visual == FB_VISUAL_TRUECOLOR || + info->fix.visual == FB_VISUAL_DIRECTCOLOR) { + fg = ((uint32_t *) info->pseudo_palette)[image->fg_color]; + bg = ((uint32_t *) info->pseudo_palette)[image->bg_color]; + } else { + fg = image->fg_color; + bg = image->bg_color; + } + + BEGIN_RING(chan, NvSubGdiRect, 0x0be4, 7); + OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff)); + OUT_RING(chan, ((image->dy + image->height) << 16) | + ((image->dx + image->width) & 0xffff)); + OUT_RING(chan, bg); + OUT_RING(chan, fg); + OUT_RING(chan, (image->height << 16) | image->width); + OUT_RING(chan, (image->height << 16) | width); + OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff)); + + while (dsize) { + int iter_len = dsize > 128 ? 128 : dsize; + + if (RING_SPACE(chan, iter_len + 1)) { + NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + info->flags |= FBINFO_HWACCEL_DISABLED; + cfb_imageblit(info, image); + return; + } + + BEGIN_RING(chan, NvSubGdiRect, 0x0c00, iter_len); + OUT_RINGp(chan, data, iter_len); + data += iter_len; + dsize -= iter_len; + } + + FIRE_RING(chan); +} + +static int +nv04_fbcon_grobj_new(struct drm_device *dev, int class, uint32_t handle) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *obj = NULL; + int ret; + + ret = nouveau_gpuobj_gr_new(dev_priv->channel, class, &obj); + if (ret) + return ret; + + ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, handle, obj, NULL); + if (ret) + return ret; + + return 0; +} + +int +nv04_fbcon_accel_init(struct fb_info *info) +{ + struct nouveau_fbcon_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->channel; + int surface_fmt, pattern_fmt, rect_fmt; + int ret; + + switch (info->var.bits_per_pixel) { + case 8: + surface_fmt = 1; + pattern_fmt = 3; + rect_fmt = 3; + break; + case 16: + surface_fmt = 4; + pattern_fmt = 1; + rect_fmt = 1; + break; + case 32: + switch (info->var.transp.length) { + case 0: /* depth 24 */ + case 8: /* depth 32 */ + break; + default: + return -EINVAL; + } + + surface_fmt = 6; + pattern_fmt = 3; + rect_fmt = 3; + break; + default: + return -EINVAL; + } + + ret = nv04_fbcon_grobj_new(dev, dev_priv->card_type >= NV_10 ? + 0x0062 : 0x0042, NvCtxSurf2D); + if (ret) + return ret; + + ret = nv04_fbcon_grobj_new(dev, 0x0019, NvClipRect); + if (ret) + return ret; + + ret = nv04_fbcon_grobj_new(dev, 0x0043, NvRop); + if (ret) + return ret; + + ret = nv04_fbcon_grobj_new(dev, 0x0044, NvImagePatt); + if (ret) + return ret; + + ret = nv04_fbcon_grobj_new(dev, 0x004a, NvGdiRect); + if (ret) + return ret; + + ret = nv04_fbcon_grobj_new(dev, dev_priv->card_type >= NV_10 ? + 0x009f : 0x005f, NvImageBlit); + if (ret) + return ret; + + if (RING_SPACE(chan, 49)) { + NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + info->flags |= FBINFO_HWACCEL_DISABLED; + return 0; + } + + BEGIN_RING(chan, 1, 0x0000, 1); + OUT_RING(chan, NvCtxSurf2D); + BEGIN_RING(chan, 1, 0x0184, 2); + OUT_RING(chan, NvDmaFB); + OUT_RING(chan, NvDmaFB); + BEGIN_RING(chan, 1, 0x0300, 4); + OUT_RING(chan, surface_fmt); + OUT_RING(chan, info->fix.line_length | (info->fix.line_length << 16)); + OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base); + OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base); + + BEGIN_RING(chan, 1, 0x0000, 1); + OUT_RING(chan, NvRop); + BEGIN_RING(chan, 1, 0x0300, 1); + OUT_RING(chan, 0x55); + + BEGIN_RING(chan, 1, 0x0000, 1); + OUT_RING(chan, NvImagePatt); + BEGIN_RING(chan, 1, 0x0300, 8); + OUT_RING(chan, pattern_fmt); +#ifdef __BIG_ENDIAN + OUT_RING(chan, 2); +#else + OUT_RING(chan, 1); +#endif + OUT_RING(chan, 0); + OUT_RING(chan, 1); + OUT_RING(chan, ~0); + OUT_RING(chan, ~0); + OUT_RING(chan, ~0); + OUT_RING(chan, ~0); + + BEGIN_RING(chan, 1, 0x0000, 1); + OUT_RING(chan, NvClipRect); + BEGIN_RING(chan, 1, 0x0300, 2); + OUT_RING(chan, 0); + OUT_RING(chan, (info->var.yres_virtual << 16) | info->var.xres_virtual); + + BEGIN_RING(chan, NvSubImageBlit, 0x0000, 1); + OUT_RING(chan, NvImageBlit); + BEGIN_RING(chan, NvSubImageBlit, 0x019c, 1); + OUT_RING(chan, NvCtxSurf2D); + BEGIN_RING(chan, NvSubImageBlit, 0x02fc, 1); + OUT_RING(chan, 3); + + BEGIN_RING(chan, NvSubGdiRect, 0x0000, 1); + OUT_RING(chan, NvGdiRect); + BEGIN_RING(chan, NvSubGdiRect, 0x0198, 1); + OUT_RING(chan, NvCtxSurf2D); + BEGIN_RING(chan, NvSubGdiRect, 0x0188, 2); + OUT_RING(chan, NvImagePatt); + OUT_RING(chan, NvRop); + BEGIN_RING(chan, NvSubGdiRect, 0x0304, 1); + OUT_RING(chan, 1); + BEGIN_RING(chan, NvSubGdiRect, 0x0300, 1); + OUT_RING(chan, rect_fmt); + BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1); + OUT_RING(chan, 3); + + FIRE_RING(chan); + + info->fbops->fb_fillrect = nv04_fbcon_fillrect; + info->fbops->fb_copyarea = nv04_fbcon_copyarea; + info->fbops->fb_imageblit = nv04_fbcon_imageblit; + return 0; +} + diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c new file mode 100644 index 0000000000000000000000000000000000000000..0c3cd53c73138142bf34e5f78b9ddfddf90bca7c --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_fifo.c @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +#define NV04_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV04_RAMFC__SIZE)) +#define NV04_RAMFC__SIZE 32 +#define NV04_RAMFC_DMA_PUT 0x00 +#define NV04_RAMFC_DMA_GET 0x04 +#define NV04_RAMFC_DMA_INSTANCE 0x08 +#define NV04_RAMFC_DMA_STATE 0x0C +#define NV04_RAMFC_DMA_FETCH 0x10 +#define NV04_RAMFC_ENGINE 0x14 +#define NV04_RAMFC_PULL1_ENGINE 0x18 + +#define RAMFC_WR(offset, val) nv_wo32(dev, chan->ramfc->gpuobj, \ + NV04_RAMFC_##offset/4, (val)) +#define RAMFC_RD(offset) nv_ro32(dev, chan->ramfc->gpuobj, \ + NV04_RAMFC_##offset/4) + +void +nv04_fifo_disable(struct drm_device *dev) +{ + uint32_t tmp; + + tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, tmp & ~1); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 0); + tmp = nv_rd32(dev, NV03_PFIFO_CACHE1_PULL1); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, tmp & ~1); +} + +void +nv04_fifo_enable(struct drm_device *dev) +{ + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); +} + +bool +nv04_fifo_reassign(struct drm_device *dev, bool enable) +{ + uint32_t reassign = nv_rd32(dev, NV03_PFIFO_CACHES); + + nv_wr32(dev, NV03_PFIFO_CACHES, enable ? 1 : 0); + return (reassign == 1); +} + +int +nv04_fifo_channel_id(struct drm_device *dev) +{ + return nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & + NV03_PFIFO_CACHE1_PUSH1_CHID_MASK; +} + +int +nv04_fifo_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + ret = nouveau_gpuobj_new_fake(dev, NV04_RAMFC(chan->id), ~0, + NV04_RAMFC__SIZE, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, + NULL, &chan->ramfc); + if (ret) + return ret; + + /* Setup initial state */ + dev_priv->engine.instmem.prepare_access(dev, true); + RAMFC_WR(DMA_PUT, chan->pushbuf_base); + RAMFC_WR(DMA_GET, chan->pushbuf_base); + RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4); + RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + 0)); + dev_priv->engine.instmem.finish_access(dev); + + /* enable the fifo dma operation */ + nv_wr32(dev, NV04_PFIFO_MODE, + nv_rd32(dev, NV04_PFIFO_MODE) | (1 << chan->id)); + return 0; +} + +void +nv04_fifo_destroy_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + + nv_wr32(dev, NV04_PFIFO_MODE, + nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); + + nouveau_gpuobj_ref_del(dev, &chan->ramfc); +} + +static void +nv04_fifo_do_load_context(struct drm_device *dev, int chid) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t fc = NV04_RAMFC(chid), tmp; + + dev_priv->engine.instmem.prepare_access(dev, false); + + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0)); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4)); + tmp = nv_ri32(dev, fc + 8); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE, tmp & 0xFFFF); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT, tmp >> 16); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, nv_ri32(dev, fc + 12)); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_FETCH, nv_ri32(dev, fc + 16)); + nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 20)); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 24)); + + dev_priv->engine.instmem.finish_access(dev); + + nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); +} + +int +nv04_fifo_load_context(struct nouveau_channel *chan) +{ + uint32_t tmp; + + nv_wr32(chan->dev, NV03_PFIFO_CACHE1_PUSH1, + NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id); + nv04_fifo_do_load_context(chan->dev, chan->id); + nv_wr32(chan->dev, NV04_PFIFO_CACHE1_DMA_PUSH, 1); + + /* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */ + tmp = nv_rd32(chan->dev, NV04_PFIFO_CACHE1_DMA_CTL) & ~(1 << 31); + nv_wr32(chan->dev, NV04_PFIFO_CACHE1_DMA_CTL, tmp); + + return 0; +} + +int +nv04_fifo_unload_context(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + struct nouveau_channel *chan = NULL; + uint32_t tmp; + int chid; + + chid = pfifo->channel_id(dev); + if (chid < 0 || chid >= dev_priv->engine.fifo.channels) + return 0; + + chan = dev_priv->fifos[chid]; + if (!chan) { + NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid); + return -EINVAL; + } + + dev_priv->engine.instmem.prepare_access(dev, true); + RAMFC_WR(DMA_PUT, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); + RAMFC_WR(DMA_GET, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); + tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16; + tmp |= nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE); + RAMFC_WR(DMA_INSTANCE, tmp); + RAMFC_WR(DMA_STATE, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_STATE)); + RAMFC_WR(DMA_FETCH, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH)); + RAMFC_WR(ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE)); + RAMFC_WR(PULL1_ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1)); + dev_priv->engine.instmem.finish_access(dev); + + nv04_fifo_do_load_context(dev, pfifo->channels - 1); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1); + return 0; +} + +static void +nv04_fifo_init_reset(struct drm_device *dev) +{ + nv_wr32(dev, NV03_PMC_ENABLE, + nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PFIFO); + nv_wr32(dev, NV03_PMC_ENABLE, + nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PFIFO); + + nv_wr32(dev, 0x003224, 0x000f0078); + nv_wr32(dev, 0x002044, 0x0101ffff); + nv_wr32(dev, 0x002040, 0x000000ff); + nv_wr32(dev, 0x002500, 0x00000000); + nv_wr32(dev, 0x003000, 0x00000000); + nv_wr32(dev, 0x003050, 0x00000000); + nv_wr32(dev, 0x003200, 0x00000000); + nv_wr32(dev, 0x003250, 0x00000000); + nv_wr32(dev, 0x003220, 0x00000000); + + nv_wr32(dev, 0x003250, 0x00000000); + nv_wr32(dev, 0x003270, 0x00000000); + nv_wr32(dev, 0x003210, 0x00000000); +} + +static void +nv04_fifo_init_ramxx(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((dev_priv->ramht_bits - 9) << 16) | + (dev_priv->ramht_offset >> 8)); + nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8); + nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc_offset >> 8); +} + +static void +nv04_fifo_init_intr(struct drm_device *dev) +{ + nv_wr32(dev, 0x002100, 0xffffffff); + nv_wr32(dev, 0x002140, 0xffffffff); +} + +int +nv04_fifo_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + int i; + + nv04_fifo_init_reset(dev); + nv04_fifo_init_ramxx(dev); + + nv04_fifo_do_load_context(dev, pfifo->channels - 1); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1); + + nv04_fifo_init_intr(dev); + pfifo->enable(dev); + + for (i = 0; i < dev_priv->engine.fifo.channels; i++) { + if (dev_priv->fifos[i]) { + uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); + nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); + } + } + + return 0; +} + diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c new file mode 100644 index 0000000000000000000000000000000000000000..396ee92118f6e9605edb2d73961a626960b45e0c --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_graph.c @@ -0,0 +1,579 @@ +/* + * Copyright 2007 Stephane Marchesin + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm.h" +#include "nouveau_drm.h" +#include "nouveau_drv.h" + +static uint32_t nv04_graph_ctx_regs[] = { + NV04_PGRAPH_CTX_SWITCH1, + NV04_PGRAPH_CTX_SWITCH2, + NV04_PGRAPH_CTX_SWITCH3, + NV04_PGRAPH_CTX_SWITCH4, + NV04_PGRAPH_CTX_CACHE1, + NV04_PGRAPH_CTX_CACHE2, + NV04_PGRAPH_CTX_CACHE3, + NV04_PGRAPH_CTX_CACHE4, + 0x00400184, + 0x004001a4, + 0x004001c4, + 0x004001e4, + 0x00400188, + 0x004001a8, + 0x004001c8, + 0x004001e8, + 0x0040018c, + 0x004001ac, + 0x004001cc, + 0x004001ec, + 0x00400190, + 0x004001b0, + 0x004001d0, + 0x004001f0, + 0x00400194, + 0x004001b4, + 0x004001d4, + 0x004001f4, + 0x00400198, + 0x004001b8, + 0x004001d8, + 0x004001f8, + 0x0040019c, + 0x004001bc, + 0x004001dc, + 0x004001fc, + 0x00400174, + NV04_PGRAPH_DMA_START_0, + NV04_PGRAPH_DMA_START_1, + NV04_PGRAPH_DMA_LENGTH, + NV04_PGRAPH_DMA_MISC, + NV04_PGRAPH_DMA_PITCH, + NV04_PGRAPH_BOFFSET0, + NV04_PGRAPH_BBASE0, + NV04_PGRAPH_BLIMIT0, + NV04_PGRAPH_BOFFSET1, + NV04_PGRAPH_BBASE1, + NV04_PGRAPH_BLIMIT1, + NV04_PGRAPH_BOFFSET2, + NV04_PGRAPH_BBASE2, + NV04_PGRAPH_BLIMIT2, + NV04_PGRAPH_BOFFSET3, + NV04_PGRAPH_BBASE3, + NV04_PGRAPH_BLIMIT3, + NV04_PGRAPH_BOFFSET4, + NV04_PGRAPH_BBASE4, + NV04_PGRAPH_BLIMIT4, + NV04_PGRAPH_BOFFSET5, + NV04_PGRAPH_BBASE5, + NV04_PGRAPH_BLIMIT5, + NV04_PGRAPH_BPITCH0, + NV04_PGRAPH_BPITCH1, + NV04_PGRAPH_BPITCH2, + NV04_PGRAPH_BPITCH3, + NV04_PGRAPH_BPITCH4, + NV04_PGRAPH_SURFACE, + NV04_PGRAPH_STATE, + NV04_PGRAPH_BSWIZZLE2, + NV04_PGRAPH_BSWIZZLE5, + NV04_PGRAPH_BPIXEL, + NV04_PGRAPH_NOTIFY, + NV04_PGRAPH_PATT_COLOR0, + NV04_PGRAPH_PATT_COLOR1, + NV04_PGRAPH_PATT_COLORRAM+0x00, + NV04_PGRAPH_PATT_COLORRAM+0x01, + NV04_PGRAPH_PATT_COLORRAM+0x02, + NV04_PGRAPH_PATT_COLORRAM+0x03, + NV04_PGRAPH_PATT_COLORRAM+0x04, + NV04_PGRAPH_PATT_COLORRAM+0x05, + NV04_PGRAPH_PATT_COLORRAM+0x06, + NV04_PGRAPH_PATT_COLORRAM+0x07, + NV04_PGRAPH_PATT_COLORRAM+0x08, + NV04_PGRAPH_PATT_COLORRAM+0x09, + NV04_PGRAPH_PATT_COLORRAM+0x0A, + NV04_PGRAPH_PATT_COLORRAM+0x0B, + NV04_PGRAPH_PATT_COLORRAM+0x0C, + NV04_PGRAPH_PATT_COLORRAM+0x0D, + NV04_PGRAPH_PATT_COLORRAM+0x0E, + NV04_PGRAPH_PATT_COLORRAM+0x0F, + NV04_PGRAPH_PATT_COLORRAM+0x10, + NV04_PGRAPH_PATT_COLORRAM+0x11, + NV04_PGRAPH_PATT_COLORRAM+0x12, + NV04_PGRAPH_PATT_COLORRAM+0x13, + NV04_PGRAPH_PATT_COLORRAM+0x14, + NV04_PGRAPH_PATT_COLORRAM+0x15, + NV04_PGRAPH_PATT_COLORRAM+0x16, + NV04_PGRAPH_PATT_COLORRAM+0x17, + NV04_PGRAPH_PATT_COLORRAM+0x18, + NV04_PGRAPH_PATT_COLORRAM+0x19, + NV04_PGRAPH_PATT_COLORRAM+0x1A, + NV04_PGRAPH_PATT_COLORRAM+0x1B, + NV04_PGRAPH_PATT_COLORRAM+0x1C, + NV04_PGRAPH_PATT_COLORRAM+0x1D, + NV04_PGRAPH_PATT_COLORRAM+0x1E, + NV04_PGRAPH_PATT_COLORRAM+0x1F, + NV04_PGRAPH_PATT_COLORRAM+0x20, + NV04_PGRAPH_PATT_COLORRAM+0x21, + NV04_PGRAPH_PATT_COLORRAM+0x22, + NV04_PGRAPH_PATT_COLORRAM+0x23, + NV04_PGRAPH_PATT_COLORRAM+0x24, + NV04_PGRAPH_PATT_COLORRAM+0x25, + NV04_PGRAPH_PATT_COLORRAM+0x26, + NV04_PGRAPH_PATT_COLORRAM+0x27, + NV04_PGRAPH_PATT_COLORRAM+0x28, + NV04_PGRAPH_PATT_COLORRAM+0x29, + NV04_PGRAPH_PATT_COLORRAM+0x2A, + NV04_PGRAPH_PATT_COLORRAM+0x2B, + NV04_PGRAPH_PATT_COLORRAM+0x2C, + NV04_PGRAPH_PATT_COLORRAM+0x2D, + NV04_PGRAPH_PATT_COLORRAM+0x2E, + NV04_PGRAPH_PATT_COLORRAM+0x2F, + NV04_PGRAPH_PATT_COLORRAM+0x30, + NV04_PGRAPH_PATT_COLORRAM+0x31, + NV04_PGRAPH_PATT_COLORRAM+0x32, + NV04_PGRAPH_PATT_COLORRAM+0x33, + NV04_PGRAPH_PATT_COLORRAM+0x34, + NV04_PGRAPH_PATT_COLORRAM+0x35, + NV04_PGRAPH_PATT_COLORRAM+0x36, + NV04_PGRAPH_PATT_COLORRAM+0x37, + NV04_PGRAPH_PATT_COLORRAM+0x38, + NV04_PGRAPH_PATT_COLORRAM+0x39, + NV04_PGRAPH_PATT_COLORRAM+0x3A, + NV04_PGRAPH_PATT_COLORRAM+0x3B, + NV04_PGRAPH_PATT_COLORRAM+0x3C, + NV04_PGRAPH_PATT_COLORRAM+0x3D, + NV04_PGRAPH_PATT_COLORRAM+0x3E, + NV04_PGRAPH_PATT_COLORRAM+0x3F, + NV04_PGRAPH_PATTERN, + 0x0040080c, + NV04_PGRAPH_PATTERN_SHAPE, + 0x00400600, + NV04_PGRAPH_ROP3, + NV04_PGRAPH_CHROMA, + NV04_PGRAPH_BETA_AND, + NV04_PGRAPH_BETA_PREMULT, + NV04_PGRAPH_CONTROL0, + NV04_PGRAPH_CONTROL1, + NV04_PGRAPH_CONTROL2, + NV04_PGRAPH_BLEND, + NV04_PGRAPH_STORED_FMT, + NV04_PGRAPH_SOURCE_COLOR, + 0x00400560, + 0x00400568, + 0x00400564, + 0x0040056c, + 0x00400400, + 0x00400480, + 0x00400404, + 0x00400484, + 0x00400408, + 0x00400488, + 0x0040040c, + 0x0040048c, + 0x00400410, + 0x00400490, + 0x00400414, + 0x00400494, + 0x00400418, + 0x00400498, + 0x0040041c, + 0x0040049c, + 0x00400420, + 0x004004a0, + 0x00400424, + 0x004004a4, + 0x00400428, + 0x004004a8, + 0x0040042c, + 0x004004ac, + 0x00400430, + 0x004004b0, + 0x00400434, + 0x004004b4, + 0x00400438, + 0x004004b8, + 0x0040043c, + 0x004004bc, + 0x00400440, + 0x004004c0, + 0x00400444, + 0x004004c4, + 0x00400448, + 0x004004c8, + 0x0040044c, + 0x004004cc, + 0x00400450, + 0x004004d0, + 0x00400454, + 0x004004d4, + 0x00400458, + 0x004004d8, + 0x0040045c, + 0x004004dc, + 0x00400460, + 0x004004e0, + 0x00400464, + 0x004004e4, + 0x00400468, + 0x004004e8, + 0x0040046c, + 0x004004ec, + 0x00400470, + 0x004004f0, + 0x00400474, + 0x004004f4, + 0x00400478, + 0x004004f8, + 0x0040047c, + 0x004004fc, + 0x0040053c, + 0x00400544, + 0x00400540, + 0x00400548, + 0x00400560, + 0x00400568, + 0x00400564, + 0x0040056c, + 0x00400534, + 0x00400538, + 0x00400514, + 0x00400518, + 0x0040051c, + 0x00400520, + 0x00400524, + 0x00400528, + 0x0040052c, + 0x00400530, + 0x00400d00, + 0x00400d40, + 0x00400d80, + 0x00400d04, + 0x00400d44, + 0x00400d84, + 0x00400d08, + 0x00400d48, + 0x00400d88, + 0x00400d0c, + 0x00400d4c, + 0x00400d8c, + 0x00400d10, + 0x00400d50, + 0x00400d90, + 0x00400d14, + 0x00400d54, + 0x00400d94, + 0x00400d18, + 0x00400d58, + 0x00400d98, + 0x00400d1c, + 0x00400d5c, + 0x00400d9c, + 0x00400d20, + 0x00400d60, + 0x00400da0, + 0x00400d24, + 0x00400d64, + 0x00400da4, + 0x00400d28, + 0x00400d68, + 0x00400da8, + 0x00400d2c, + 0x00400d6c, + 0x00400dac, + 0x00400d30, + 0x00400d70, + 0x00400db0, + 0x00400d34, + 0x00400d74, + 0x00400db4, + 0x00400d38, + 0x00400d78, + 0x00400db8, + 0x00400d3c, + 0x00400d7c, + 0x00400dbc, + 0x00400590, + 0x00400594, + 0x00400598, + 0x0040059c, + 0x004005a8, + 0x004005ac, + 0x004005b0, + 0x004005b4, + 0x004005c0, + 0x004005c4, + 0x004005c8, + 0x004005cc, + 0x004005d0, + 0x004005d4, + 0x004005d8, + 0x004005dc, + 0x004005e0, + NV04_PGRAPH_PASSTHRU_0, + NV04_PGRAPH_PASSTHRU_1, + NV04_PGRAPH_PASSTHRU_2, + NV04_PGRAPH_DVD_COLORFMT, + NV04_PGRAPH_SCALED_FORMAT, + NV04_PGRAPH_MISC24_0, + NV04_PGRAPH_MISC24_1, + NV04_PGRAPH_MISC24_2, + 0x00400500, + 0x00400504, + NV04_PGRAPH_VALID1, + NV04_PGRAPH_VALID2 + + +}; + +struct graph_state { + int nv04[ARRAY_SIZE(nv04_graph_ctx_regs)]; +}; + +struct nouveau_channel * +nv04_graph_channel(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int chid = dev_priv->engine.fifo.channels; + + if (nv_rd32(dev, NV04_PGRAPH_CTX_CONTROL) & 0x00010000) + chid = nv_rd32(dev, NV04_PGRAPH_CTX_USER) >> 24; + + if (chid >= dev_priv->engine.fifo.channels) + return NULL; + + return dev_priv->fifos[chid]; +} + +void +nv04_graph_context_switch(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_channel *chan = NULL; + int chid; + + pgraph->fifo_access(dev, false); + nouveau_wait_for_idle(dev); + + /* If previous context is valid, we need to save it */ + pgraph->unload_context(dev); + + /* Load context for next channel */ + chid = dev_priv->engine.fifo.channel_id(dev); + chan = dev_priv->fifos[chid]; + if (chan) + nv04_graph_load_context(chan); + + pgraph->fifo_access(dev, true); +} + +int nv04_graph_create_context(struct nouveau_channel *chan) +{ + struct graph_state *pgraph_ctx; + NV_DEBUG(chan->dev, "nv04_graph_context_create %d\n", chan->id); + + chan->pgraph_ctx = pgraph_ctx = kzalloc(sizeof(*pgraph_ctx), + GFP_KERNEL); + if (pgraph_ctx == NULL) + return -ENOMEM; + + /* dev_priv->fifos[channel].pgraph_ctx_user = channel << 24; */ + pgraph_ctx->nv04[0] = 0x0001ffff; + /* is it really needed ??? */ +#if 0 + dev_priv->fifos[channel].pgraph_ctx[1] = + nv_rd32(dev, NV_PGRAPH_DEBUG_4); + dev_priv->fifos[channel].pgraph_ctx[2] = + nv_rd32(dev, 0x004006b0); +#endif + return 0; +} + +void nv04_graph_destroy_context(struct nouveau_channel *chan) +{ + struct graph_state *pgraph_ctx = chan->pgraph_ctx; + + kfree(pgraph_ctx); + chan->pgraph_ctx = NULL; +} + +int nv04_graph_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct graph_state *pgraph_ctx = chan->pgraph_ctx; + uint32_t tmp; + int i; + + for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) + nv_wr32(dev, nv04_graph_ctx_regs[i], pgraph_ctx->nv04[i]); + + nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10010100); + nv_wr32(dev, NV04_PGRAPH_CTX_USER, chan->id << 24); + tmp = nv_rd32(dev, NV04_PGRAPH_FFINTFC_ST2); + nv_wr32(dev, NV04_PGRAPH_FFINTFC_ST2, tmp & 0x000fffff); + return 0; +} + +int +nv04_graph_unload_context(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_channel *chan = NULL; + struct graph_state *ctx; + uint32_t tmp; + int i; + + chan = pgraph->channel(dev); + if (!chan) + return 0; + ctx = chan->pgraph_ctx; + + for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) + ctx->nv04[i] = nv_rd32(dev, nv04_graph_ctx_regs[i]); + + nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10000000); + tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff; + tmp |= (dev_priv->engine.fifo.channels - 1) << 24; + nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp); + return 0; +} + +int nv04_graph_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t tmp; + + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & + ~NV_PMC_ENABLE_PGRAPH); + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | + NV_PMC_ENABLE_PGRAPH); + + /* Enable PGRAPH interrupts */ + nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF); + nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + + nv_wr32(dev, NV04_PGRAPH_VALID1, 0); + nv_wr32(dev, NV04_PGRAPH_VALID2, 0); + /*nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x000001FF); + nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/ + nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x1231c000); + /*1231C000 blob, 001 haiku*/ + //*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/ + nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x72111100); + /*0x72111100 blob , 01 haiku*/ + /*nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/ + nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f071); + /*haiku same*/ + + /*nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/ + nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xf0d4ff31); + /*haiku and blob 10d4*/ + + nv_wr32(dev, NV04_PGRAPH_STATE , 0xFFFFFFFF); + nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL , 0x10000100); + tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff; + tmp |= dev_priv->engine.fifo.channels << 24; + nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp); + + /* These don't belong here, they're part of a per-channel context */ + nv_wr32(dev, NV04_PGRAPH_PATTERN_SHAPE, 0x00000000); + nv_wr32(dev, NV04_PGRAPH_BETA_AND , 0xFFFFFFFF); + + return 0; +} + +void nv04_graph_takedown(struct drm_device *dev) +{ +} + +void +nv04_graph_fifo_access(struct drm_device *dev, bool enabled) +{ + if (enabled) + nv_wr32(dev, NV04_PGRAPH_FIFO, + nv_rd32(dev, NV04_PGRAPH_FIFO) | 1); + else + nv_wr32(dev, NV04_PGRAPH_FIFO, + nv_rd32(dev, NV04_PGRAPH_FIFO) & ~1); +} + +static int +nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass, + int mthd, uint32_t data) +{ + chan->fence.last_sequence_irq = data; + nouveau_fence_handler(chan->dev, chan->id); + return 0; +} + +static int +nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass, + int mthd, uint32_t data) +{ + struct drm_device *dev = chan->dev; + uint32_t instance = nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff; + int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; + uint32_t tmp; + + tmp = nv_ri32(dev, instance); + tmp &= ~0x00038000; + tmp |= ((data & 7) << 15); + + nv_wi32(dev, instance, tmp); + nv_wr32(dev, NV04_PGRAPH_CTX_SWITCH1, tmp); + nv_wr32(dev, NV04_PGRAPH_CTX_CACHE1 + subc, tmp); + return 0; +} + +static struct nouveau_pgraph_object_method nv04_graph_mthds_m2mf[] = { + { 0x0150, nv04_graph_mthd_set_ref }, + {} +}; + +static struct nouveau_pgraph_object_method nv04_graph_mthds_set_operation[] = { + { 0x02fc, nv04_graph_mthd_set_operation }, + {}, +}; + +struct nouveau_pgraph_object_class nv04_graph_grclass[] = { + { 0x0039, false, nv04_graph_mthds_m2mf }, + { 0x004a, false, nv04_graph_mthds_set_operation }, /* gdirect */ + { 0x005f, false, nv04_graph_mthds_set_operation }, /* imageblit */ + { 0x0061, false, nv04_graph_mthds_set_operation }, /* ifc */ + { 0x0077, false, nv04_graph_mthds_set_operation }, /* sifm */ + { 0x0030, false, NULL }, /* null */ + { 0x0042, false, NULL }, /* surf2d */ + { 0x0043, false, NULL }, /* rop */ + { 0x0012, false, NULL }, /* beta1 */ + { 0x0072, false, NULL }, /* beta4 */ + { 0x0019, false, NULL }, /* cliprect */ + { 0x0044, false, NULL }, /* pattern */ + { 0x0052, false, NULL }, /* swzsurf */ + { 0x0053, false, NULL }, /* surf3d */ + { 0x0054, false, NULL }, /* tex_tri */ + { 0x0055, false, NULL }, /* multitex_tri */ + {} +}; + diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c new file mode 100644 index 0000000000000000000000000000000000000000..a20c206625a2616f64b6601efa959ee4b9badd77 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_instmem.c @@ -0,0 +1,208 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +/* returns the size of fifo context */ +static int +nouveau_fifo_ctx_size(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->chipset >= 0x40) + return 128; + else + if (dev_priv->chipset >= 0x17) + return 64; + + return 32; +} + +static void +nv04_instmem_determine_amount(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + /* Figure out how much instance memory we need */ + if (dev_priv->card_type >= NV_40) { + /* We'll want more instance memory than this on some NV4x cards. + * There's a 16MB aperture to play with that maps onto the end + * of vram. For now, only reserve a small piece until we know + * more about what each chipset requires. + */ + switch (dev_priv->chipset & 0xf0) { + case 0x40: + case 0x47: + case 0x49: + case 0x4b: + dev_priv->ramin_rsvd_vram = (2 * 1024 * 1024); + break; + default: + dev_priv->ramin_rsvd_vram = (1 * 1024 * 1024); + break; + } + } else { + /*XXX: what *are* the limits on ramin_rsvd_vram = (512 * 1024); + } + NV_DEBUG(dev, "RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram >> 10); + + /* Clear all of it, except the BIOS image that's in the first 64KiB */ + dev_priv->engine.instmem.prepare_access(dev, true); + for (i = 64 * 1024; i < dev_priv->ramin_rsvd_vram; i += 4) + nv_wi32(dev, i, 0x00000000); + dev_priv->engine.instmem.finish_access(dev); +} + +static void +nv04_instmem_configure_fixed_tables(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->engine; + + /* FIFO hash table (RAMHT) + * use 4k hash table at RAMIN+0x10000 + * TODO: extend the hash table + */ + dev_priv->ramht_offset = 0x10000; + dev_priv->ramht_bits = 9; + dev_priv->ramht_size = (1 << dev_priv->ramht_bits); /* nr entries */ + dev_priv->ramht_size *= 8; /* 2 32-bit values per entry in RAMHT */ + NV_DEBUG(dev, "RAMHT offset=0x%x, size=%d\n", dev_priv->ramht_offset, + dev_priv->ramht_size); + + /* FIFO runout table (RAMRO) - 512k at 0x11200 */ + dev_priv->ramro_offset = 0x11200; + dev_priv->ramro_size = 512; + NV_DEBUG(dev, "RAMRO offset=0x%x, size=%d\n", dev_priv->ramro_offset, + dev_priv->ramro_size); + + /* FIFO context table (RAMFC) + * NV40 : Not sure exactly how to position RAMFC on some cards, + * 0x30002 seems to position it at RAMIN+0x20000 on these + * cards. RAMFC is 4kb (32 fifos, 128byte entries). + * Others: Position RAMFC at RAMIN+0x11400 + */ + dev_priv->ramfc_size = engine->fifo.channels * + nouveau_fifo_ctx_size(dev); + switch (dev_priv->card_type) { + case NV_40: + dev_priv->ramfc_offset = 0x20000; + break; + case NV_30: + case NV_20: + case NV_10: + case NV_04: + default: + dev_priv->ramfc_offset = 0x11400; + break; + } + NV_DEBUG(dev, "RAMFC offset=0x%x, size=%d\n", dev_priv->ramfc_offset, + dev_priv->ramfc_size); +} + +int nv04_instmem_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t offset; + int ret = 0; + + nv04_instmem_determine_amount(dev); + nv04_instmem_configure_fixed_tables(dev); + + /* Create a heap to manage RAMIN allocations, we don't allocate + * the space that was reserved for RAMHT/FC/RO. + */ + offset = dev_priv->ramfc_offset + dev_priv->ramfc_size; + + /* It appears RAMRO (or something?) is controlled by 0x2220/0x2230 + * on certain NV4x chipsets as well as RAMFC. When 0x2230 == 0 + * ("new style" control) the upper 16-bits of 0x2220 points at this + * other mysterious table that's clobbering important things. + * + * We're now pointing this at RAMIN+0x30000 to avoid RAMFC getting + * smashed to pieces on us, so reserve 0x30000-0x40000 too.. + */ + if (dev_priv->card_type >= NV_40) { + if (offset < 0x40000) + offset = 0x40000; + } + + ret = nouveau_mem_init_heap(&dev_priv->ramin_heap, + offset, dev_priv->ramin_rsvd_vram - offset); + if (ret) { + dev_priv->ramin_heap = NULL; + NV_ERROR(dev, "Failed to init RAMIN heap\n"); + } + + return ret; +} + +void +nv04_instmem_takedown(struct drm_device *dev) +{ +} + +int +nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, uint32_t *sz) +{ + if (gpuobj->im_backing) + return -EINVAL; + + return 0; +} + +void +nv04_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (gpuobj && gpuobj->im_backing) { + if (gpuobj->im_bound) + dev_priv->engine.instmem.unbind(dev, gpuobj); + gpuobj->im_backing = NULL; + } +} + +int +nv04_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +{ + if (!gpuobj->im_pramin || gpuobj->im_bound) + return -EINVAL; + + gpuobj->im_bound = 1; + return 0; +} + +int +nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +{ + if (gpuobj->im_bound == 0) + return -EINVAL; + + gpuobj->im_bound = 0; + return 0; +} + +void +nv04_instmem_prepare_access(struct drm_device *dev, bool write) +{ +} + +void +nv04_instmem_finish_access(struct drm_device *dev) +{ +} + +int +nv04_instmem_suspend(struct drm_device *dev) +{ + return 0; +} + +void +nv04_instmem_resume(struct drm_device *dev) +{ +} + diff --git a/drivers/gpu/drm/nouveau/nv04_mc.c b/drivers/gpu/drm/nouveau/nv04_mc.c new file mode 100644 index 0000000000000000000000000000000000000000..617ed1e052692cc6f80746560e0b2d494c58d776 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_mc.c @@ -0,0 +1,20 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv04_mc_init(struct drm_device *dev) +{ + /* Power up everything, resetting each individual unit will + * be done later if needed. + */ + + nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF); + return 0; +} + +void +nv04_mc_takedown(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/nv04_timer.c b/drivers/gpu/drm/nouveau/nv04_timer.c new file mode 100644 index 0000000000000000000000000000000000000000..1d09ddd573996dc94fce652a591c1779be641f2b --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_timer.c @@ -0,0 +1,51 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv04_timer_init(struct drm_device *dev) +{ + nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000); + nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF); + + /* Just use the pre-existing values when possible for now; these regs + * are not written in nv (driver writer missed a /4 on the address), and + * writing 8 and 3 to the correct regs breaks the timings on the LVDS + * hardware sequencing microcode. + * A correct solution (involving calculations with the GPU PLL) can + * be done when kernel modesetting lands + */ + if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) || + !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) { + nv_wr32(dev, NV04_PTIMER_NUMERATOR, 0x00000008); + nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 0x00000003); + } + + return 0; +} + +uint64_t +nv04_timer_read(struct drm_device *dev) +{ + uint32_t low; + /* From kmmio dumps on nv28 this looks like how the blob does this. + * It reads the high dword twice, before and after. + * The only explanation seems to be that the 64-bit timer counter + * advances between high and low dword reads and may corrupt the + * result. Not confirmed. + */ + uint32_t high2 = nv_rd32(dev, NV04_PTIMER_TIME_1); + uint32_t high1; + do { + high1 = high2; + low = nv_rd32(dev, NV04_PTIMER_TIME_0); + high2 = nv_rd32(dev, NV04_PTIMER_TIME_1); + } while (high1 != high2); + return (((uint64_t)high2) << 32) | (uint64_t)low; +} + +void +nv04_timer_takedown(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c new file mode 100644 index 0000000000000000000000000000000000000000..9c63099e9c428a74f04f23095950d181c631c142 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_tv.c @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_encoder.h" +#include "nouveau_connector.h" +#include "nouveau_crtc.h" +#include "nouveau_hw.h" +#include "drm_crtc_helper.h" + +#include "i2c/ch7006.h" + +static struct { + struct i2c_board_info board_info; + struct drm_encoder_funcs funcs; + struct drm_encoder_helper_funcs hfuncs; + void *params; + +} nv04_tv_encoder_info[] = { + { + .board_info = { I2C_BOARD_INFO("ch7006", 0x75) }, + .params = &(struct ch7006_encoder_params) { + CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER, + 0, 0, 0, + CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED, + CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC + }, + }, +}; + +static bool probe_i2c_addr(struct i2c_adapter *adapter, int addr) +{ + struct i2c_msg msg = { + .addr = addr, + .len = 0, + }; + + return i2c_transfer(adapter, &msg, 1) == 1; +} + +int nv04_tv_identify(struct drm_device *dev, int i2c_index) +{ + struct nouveau_i2c_chan *i2c; + bool was_locked; + int i, ret; + + NV_TRACE(dev, "Probing TV encoders on I2C bus: %d\n", i2c_index); + + i2c = nouveau_i2c_find(dev, i2c_index); + if (!i2c) + return -ENODEV; + + was_locked = NVLockVgaCrtcs(dev, false); + + for (i = 0; i < ARRAY_SIZE(nv04_tv_encoder_info); i++) { + if (probe_i2c_addr(&i2c->adapter, + nv04_tv_encoder_info[i].board_info.addr)) { + ret = i; + break; + } + } + + if (i < ARRAY_SIZE(nv04_tv_encoder_info)) { + NV_TRACE(dev, "Detected TV encoder: %s\n", + nv04_tv_encoder_info[i].board_info.type); + + } else { + NV_TRACE(dev, "No TV encoders found.\n"); + i = -ENODEV; + } + + NVLockVgaCrtcs(dev, was_locked); + return i; +} + +#define PLLSEL_TV_CRTC1_MASK \ + (NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1 \ + | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1) +#define PLLSEL_TV_CRTC2_MASK \ + (NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK2 \ + | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK2) + +static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_mode_state *state = &dev_priv->mode_reg; + uint8_t crtc1A; + + NV_INFO(dev, "Setting dpms mode %d on TV encoder (output %d)\n", + mode, nv_encoder->dcb->index); + + state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); + + if (mode == DRM_MODE_DPMS_ON) { + int head = nouveau_crtc(encoder->crtc)->index; + crtc1A = NVReadVgaCrtc(dev, head, NV_CIO_CRE_RPC1_INDEX); + + state->pllsel |= head ? PLLSEL_TV_CRTC2_MASK : + PLLSEL_TV_CRTC1_MASK; + + /* Inhibit hsync */ + crtc1A |= 0x80; + + NVWriteVgaCrtc(dev, head, NV_CIO_CRE_RPC1_INDEX, crtc1A); + } + + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel); + + to_encoder_slave(encoder)->slave_funcs->dpms(encoder, mode); +} + +static void nv04_tv_bind(struct drm_device *dev, int head, bool bind) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_crtc_reg *state = &dev_priv->mode_reg.crtc_reg[head]; + + state->tv_setup = 0; + + if (bind) { + state->CRTC[NV_CIO_CRE_LCD__INDEX] = 0; + state->CRTC[NV_CIO_CRE_49] |= 0x10; + } else { + state->CRTC[NV_CIO_CRE_49] &= ~0x10; + } + + NVWriteVgaCrtc(dev, head, NV_CIO_CRE_LCD__INDEX, + state->CRTC[NV_CIO_CRE_LCD__INDEX]); + NVWriteVgaCrtc(dev, head, NV_CIO_CRE_49, + state->CRTC[NV_CIO_CRE_49]); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP, + state->tv_setup); +} + +static void nv04_tv_prepare(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + int head = nouveau_crtc(encoder->crtc)->index; + struct drm_encoder_helper_funcs *helper = encoder->helper_private; + + helper->dpms(encoder, DRM_MODE_DPMS_OFF); + + nv04_dfp_disable(dev, head); + + if (nv_two_heads(dev)) + nv04_tv_bind(dev, head ^ 1, false); + + nv04_tv_bind(dev, head, true); +} + +static void nv04_tv_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); + struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index]; + + regp->tv_htotal = adjusted_mode->htotal; + regp->tv_vtotal = adjusted_mode->vtotal; + + /* These delay the TV signals with respect to the VGA port, + * they might be useful if we ever allow a CRTC to drive + * multiple outputs. + */ + regp->tv_hskew = 1; + regp->tv_hsync_delay = 1; + regp->tv_hsync_delay2 = 64; + regp->tv_vskew = 1; + regp->tv_vsync_delay = 1; + + to_encoder_slave(encoder)->slave_funcs->mode_set(encoder, mode, adjusted_mode); +} + +static void nv04_tv_commit(struct drm_encoder *encoder) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); + struct drm_encoder_helper_funcs *helper = encoder->helper_private; + + helper->dpms(encoder, DRM_MODE_DPMS_ON); + + NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, + '@' + ffs(nv_encoder->dcb->or)); +} + +static void nv04_tv_destroy(struct drm_encoder *encoder) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + to_encoder_slave(encoder)->slave_funcs->destroy(encoder); + + drm_encoder_cleanup(encoder); + + kfree(nv_encoder); +} + +int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry) +{ + struct nouveau_encoder *nv_encoder; + struct drm_encoder *encoder; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct i2c_adapter *adap; + struct drm_encoder_funcs *funcs = NULL; + struct drm_encoder_helper_funcs *hfuncs = NULL; + struct drm_encoder_slave_funcs *sfuncs = NULL; + int i2c_index = entry->i2c_index; + int type, ret; + bool was_locked; + + /* Ensure that we can talk to this encoder */ + type = nv04_tv_identify(dev, i2c_index); + if (type < 0) + return type; + + /* Allocate the necessary memory */ + nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); + if (!nv_encoder) + return -ENOMEM; + + /* Initialize the common members */ + encoder = to_drm_encoder(nv_encoder); + + funcs = &nv04_tv_encoder_info[type].funcs; + hfuncs = &nv04_tv_encoder_info[type].hfuncs; + + drm_encoder_init(dev, encoder, funcs, DRM_MODE_ENCODER_TVDAC); + drm_encoder_helper_add(encoder, hfuncs); + + encoder->possible_crtcs = entry->heads; + encoder->possible_clones = 0; + + nv_encoder->dcb = entry; + nv_encoder->or = ffs(entry->or) - 1; + + /* Run the slave-specific initialization */ + adap = &dev_priv->vbios->dcb->i2c[i2c_index].chan->adapter; + + was_locked = NVLockVgaCrtcs(dev, false); + + ret = drm_i2c_encoder_init(encoder->dev, to_encoder_slave(encoder), adap, + &nv04_tv_encoder_info[type].board_info); + + NVLockVgaCrtcs(dev, was_locked); + + if (ret < 0) + goto fail; + + /* Fill the function pointers */ + sfuncs = to_encoder_slave(encoder)->slave_funcs; + + *funcs = (struct drm_encoder_funcs) { + .destroy = nv04_tv_destroy, + }; + + *hfuncs = (struct drm_encoder_helper_funcs) { + .dpms = nv04_tv_dpms, + .save = sfuncs->save, + .restore = sfuncs->restore, + .mode_fixup = sfuncs->mode_fixup, + .prepare = nv04_tv_prepare, + .commit = nv04_tv_commit, + .mode_set = nv04_tv_mode_set, + .detect = sfuncs->detect, + }; + + /* Set the slave encoder configuration */ + sfuncs->set_config(encoder, nv04_tv_encoder_info[type].params); + + return 0; + +fail: + drm_encoder_cleanup(encoder); + + kfree(nv_encoder); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nv10_fb.c b/drivers/gpu/drm/nouveau/nv10_fb.c new file mode 100644 index 0000000000000000000000000000000000000000..79e2d104d70a0176bffa23d46b25ff68749d8265 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv10_fb.c @@ -0,0 +1,24 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv10_fb_init(struct drm_device *dev) +{ + uint32_t fb_bar_size; + int i; + + fb_bar_size = drm_get_resource_len(dev, 0) - 1; + for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { + nv_wr32(dev, NV10_PFB_TILE(i), 0); + nv_wr32(dev, NV10_PFB_TLIMIT(i), fb_bar_size); + } + + return 0; +} + +void +nv10_fb_takedown(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/nv10_fifo.c b/drivers/gpu/drm/nouveau/nv10_fifo.c new file mode 100644 index 0000000000000000000000000000000000000000..7aeabf262bc0a43affe3c1fdad393e9301d95263 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv10_fifo.c @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +#define NV10_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV10_RAMFC__SIZE)) +#define NV10_RAMFC__SIZE ((dev_priv->chipset) >= 0x17 ? 64 : 32) + +int +nv10_fifo_channel_id(struct drm_device *dev) +{ + return nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & + NV10_PFIFO_CACHE1_PUSH1_CHID_MASK; +} + +int +nv10_fifo_create_context(struct nouveau_channel *chan) +{ + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct drm_device *dev = chan->dev; + uint32_t fc = NV10_RAMFC(chan->id); + int ret; + + ret = nouveau_gpuobj_new_fake(dev, NV10_RAMFC(chan->id), ~0, + NV10_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, NULL, &chan->ramfc); + if (ret) + return ret; + + /* Fill entries that are seen filled in dumps of nvidia driver just + * after channel's is put into DMA mode + */ + dev_priv->engine.instmem.prepare_access(dev, true); + nv_wi32(dev, fc + 0, chan->pushbuf_base); + nv_wi32(dev, fc + 4, chan->pushbuf_base); + nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4); + nv_wi32(dev, fc + 20, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + 0); + dev_priv->engine.instmem.finish_access(dev); + + /* enable the fifo dma operation */ + nv_wr32(dev, NV04_PFIFO_MODE, + nv_rd32(dev, NV04_PFIFO_MODE) | (1 << chan->id)); + return 0; +} + +void +nv10_fifo_destroy_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + + nv_wr32(dev, NV04_PFIFO_MODE, + nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); + + nouveau_gpuobj_ref_del(dev, &chan->ramfc); +} + +static void +nv10_fifo_do_load_context(struct drm_device *dev, int chid) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t fc = NV10_RAMFC(chid), tmp; + + dev_priv->engine.instmem.prepare_access(dev, false); + + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0)); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4)); + nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8)); + + tmp = nv_ri32(dev, fc + 12); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE, tmp & 0xFFFF); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT, tmp >> 16); + + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, nv_ri32(dev, fc + 16)); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_FETCH, nv_ri32(dev, fc + 20)); + nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 24)); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 28)); + + if (dev_priv->chipset < 0x17) + goto out; + + nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_VALUE, nv_ri32(dev, fc + 32)); + tmp = nv_ri32(dev, fc + 36); + nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP, tmp); + nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT, nv_ri32(dev, fc + 40)); + nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, nv_ri32(dev, fc + 44)); + nv_wr32(dev, NV10_PFIFO_CACHE1_DMA_SUBROUTINE, nv_ri32(dev, fc + 48)); + +out: + dev_priv->engine.instmem.finish_access(dev); + + nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); +} + +int +nv10_fifo_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + uint32_t tmp; + + nv10_fifo_do_load_context(dev, chan->id); + + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, + NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 1); + + /* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */ + tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_CTL) & ~(1 << 31); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_CTL, tmp); + + return 0; +} + +int +nv10_fifo_unload_context(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + uint32_t fc, tmp; + int chid; + + chid = pfifo->channel_id(dev); + if (chid < 0 || chid >= dev_priv->engine.fifo.channels) + return 0; + fc = NV10_RAMFC(chid); + + dev_priv->engine.instmem.prepare_access(dev, true); + + nv_wi32(dev, fc + 0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); + nv_wi32(dev, fc + 4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); + nv_wi32(dev, fc + 8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT)); + tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE) & 0xFFFF; + tmp |= (nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16); + nv_wi32(dev, fc + 12, tmp); + nv_wi32(dev, fc + 16, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_STATE)); + nv_wi32(dev, fc + 20, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH)); + nv_wi32(dev, fc + 24, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE)); + nv_wi32(dev, fc + 28, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1)); + + if (dev_priv->chipset < 0x17) + goto out; + + nv_wi32(dev, fc + 32, nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_VALUE)); + tmp = nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP); + nv_wi32(dev, fc + 36, tmp); + nv_wi32(dev, fc + 40, nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT)); + nv_wi32(dev, fc + 44, nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE)); + nv_wi32(dev, fc + 48, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); + +out: + dev_priv->engine.instmem.finish_access(dev); + + nv10_fifo_do_load_context(dev, pfifo->channels - 1); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1); + return 0; +} + +static void +nv10_fifo_init_reset(struct drm_device *dev) +{ + nv_wr32(dev, NV03_PMC_ENABLE, + nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PFIFO); + nv_wr32(dev, NV03_PMC_ENABLE, + nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PFIFO); + + nv_wr32(dev, 0x003224, 0x000f0078); + nv_wr32(dev, 0x002044, 0x0101ffff); + nv_wr32(dev, 0x002040, 0x000000ff); + nv_wr32(dev, 0x002500, 0x00000000); + nv_wr32(dev, 0x003000, 0x00000000); + nv_wr32(dev, 0x003050, 0x00000000); + + nv_wr32(dev, 0x003258, 0x00000000); + nv_wr32(dev, 0x003210, 0x00000000); + nv_wr32(dev, 0x003270, 0x00000000); +} + +static void +nv10_fifo_init_ramxx(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((dev_priv->ramht_bits - 9) << 16) | + (dev_priv->ramht_offset >> 8)); + nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8); + + if (dev_priv->chipset < 0x17) { + nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc_offset >> 8); + } else { + nv_wr32(dev, NV03_PFIFO_RAMFC, (dev_priv->ramfc_offset >> 8) | + (1 << 16) /* 64 Bytes entry*/); + /* XXX nvidia blob set bit 18, 21,23 for nv20 & nv30 */ + } +} + +static void +nv10_fifo_init_intr(struct drm_device *dev) +{ + nv_wr32(dev, 0x002100, 0xffffffff); + nv_wr32(dev, 0x002140, 0xffffffff); +} + +int +nv10_fifo_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + int i; + + nv10_fifo_init_reset(dev); + nv10_fifo_init_ramxx(dev); + + nv10_fifo_do_load_context(dev, pfifo->channels - 1); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1); + + nv10_fifo_init_intr(dev); + pfifo->enable(dev); + pfifo->reassign(dev, true); + + for (i = 0; i < dev_priv->engine.fifo.channels; i++) { + if (dev_priv->fifos[i]) { + uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); + nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); + } + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c new file mode 100644 index 0000000000000000000000000000000000000000..6bf6804bb0efee1c5f525d833b34d711e1762ac5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv10_graph.c @@ -0,0 +1,892 @@ +/* + * Copyright 2007 Matthieu CASTET + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm.h" +#include "nouveau_drm.h" +#include "nouveau_drv.h" + +#define NV10_FIFO_NUMBER 32 + +struct pipe_state { + uint32_t pipe_0x0000[0x040/4]; + uint32_t pipe_0x0040[0x010/4]; + uint32_t pipe_0x0200[0x0c0/4]; + uint32_t pipe_0x4400[0x080/4]; + uint32_t pipe_0x6400[0x3b0/4]; + uint32_t pipe_0x6800[0x2f0/4]; + uint32_t pipe_0x6c00[0x030/4]; + uint32_t pipe_0x7000[0x130/4]; + uint32_t pipe_0x7400[0x0c0/4]; + uint32_t pipe_0x7800[0x0c0/4]; +}; + +static int nv10_graph_ctx_regs[] = { + NV10_PGRAPH_CTX_SWITCH1, + NV10_PGRAPH_CTX_SWITCH2, + NV10_PGRAPH_CTX_SWITCH3, + NV10_PGRAPH_CTX_SWITCH4, + NV10_PGRAPH_CTX_SWITCH5, + NV10_PGRAPH_CTX_CACHE1, /* 8 values from 0x400160 to 0x40017c */ + NV10_PGRAPH_CTX_CACHE2, /* 8 values from 0x400180 to 0x40019c */ + NV10_PGRAPH_CTX_CACHE3, /* 8 values from 0x4001a0 to 0x4001bc */ + NV10_PGRAPH_CTX_CACHE4, /* 8 values from 0x4001c0 to 0x4001dc */ + NV10_PGRAPH_CTX_CACHE5, /* 8 values from 0x4001e0 to 0x4001fc */ + 0x00400164, + 0x00400184, + 0x004001a4, + 0x004001c4, + 0x004001e4, + 0x00400168, + 0x00400188, + 0x004001a8, + 0x004001c8, + 0x004001e8, + 0x0040016c, + 0x0040018c, + 0x004001ac, + 0x004001cc, + 0x004001ec, + 0x00400170, + 0x00400190, + 0x004001b0, + 0x004001d0, + 0x004001f0, + 0x00400174, + 0x00400194, + 0x004001b4, + 0x004001d4, + 0x004001f4, + 0x00400178, + 0x00400198, + 0x004001b8, + 0x004001d8, + 0x004001f8, + 0x0040017c, + 0x0040019c, + 0x004001bc, + 0x004001dc, + 0x004001fc, + NV10_PGRAPH_CTX_USER, + NV04_PGRAPH_DMA_START_0, + NV04_PGRAPH_DMA_START_1, + NV04_PGRAPH_DMA_LENGTH, + NV04_PGRAPH_DMA_MISC, + NV10_PGRAPH_DMA_PITCH, + NV04_PGRAPH_BOFFSET0, + NV04_PGRAPH_BBASE0, + NV04_PGRAPH_BLIMIT0, + NV04_PGRAPH_BOFFSET1, + NV04_PGRAPH_BBASE1, + NV04_PGRAPH_BLIMIT1, + NV04_PGRAPH_BOFFSET2, + NV04_PGRAPH_BBASE2, + NV04_PGRAPH_BLIMIT2, + NV04_PGRAPH_BOFFSET3, + NV04_PGRAPH_BBASE3, + NV04_PGRAPH_BLIMIT3, + NV04_PGRAPH_BOFFSET4, + NV04_PGRAPH_BBASE4, + NV04_PGRAPH_BLIMIT4, + NV04_PGRAPH_BOFFSET5, + NV04_PGRAPH_BBASE5, + NV04_PGRAPH_BLIMIT5, + NV04_PGRAPH_BPITCH0, + NV04_PGRAPH_BPITCH1, + NV04_PGRAPH_BPITCH2, + NV04_PGRAPH_BPITCH3, + NV04_PGRAPH_BPITCH4, + NV10_PGRAPH_SURFACE, + NV10_PGRAPH_STATE, + NV04_PGRAPH_BSWIZZLE2, + NV04_PGRAPH_BSWIZZLE5, + NV04_PGRAPH_BPIXEL, + NV10_PGRAPH_NOTIFY, + NV04_PGRAPH_PATT_COLOR0, + NV04_PGRAPH_PATT_COLOR1, + NV04_PGRAPH_PATT_COLORRAM, /* 64 values from 0x400900 to 0x4009fc */ + 0x00400904, + 0x00400908, + 0x0040090c, + 0x00400910, + 0x00400914, + 0x00400918, + 0x0040091c, + 0x00400920, + 0x00400924, + 0x00400928, + 0x0040092c, + 0x00400930, + 0x00400934, + 0x00400938, + 0x0040093c, + 0x00400940, + 0x00400944, + 0x00400948, + 0x0040094c, + 0x00400950, + 0x00400954, + 0x00400958, + 0x0040095c, + 0x00400960, + 0x00400964, + 0x00400968, + 0x0040096c, + 0x00400970, + 0x00400974, + 0x00400978, + 0x0040097c, + 0x00400980, + 0x00400984, + 0x00400988, + 0x0040098c, + 0x00400990, + 0x00400994, + 0x00400998, + 0x0040099c, + 0x004009a0, + 0x004009a4, + 0x004009a8, + 0x004009ac, + 0x004009b0, + 0x004009b4, + 0x004009b8, + 0x004009bc, + 0x004009c0, + 0x004009c4, + 0x004009c8, + 0x004009cc, + 0x004009d0, + 0x004009d4, + 0x004009d8, + 0x004009dc, + 0x004009e0, + 0x004009e4, + 0x004009e8, + 0x004009ec, + 0x004009f0, + 0x004009f4, + 0x004009f8, + 0x004009fc, + NV04_PGRAPH_PATTERN, /* 2 values from 0x400808 to 0x40080c */ + 0x0040080c, + NV04_PGRAPH_PATTERN_SHAPE, + NV03_PGRAPH_MONO_COLOR0, + NV04_PGRAPH_ROP3, + NV04_PGRAPH_CHROMA, + NV04_PGRAPH_BETA_AND, + NV04_PGRAPH_BETA_PREMULT, + 0x00400e70, + 0x00400e74, + 0x00400e78, + 0x00400e7c, + 0x00400e80, + 0x00400e84, + 0x00400e88, + 0x00400e8c, + 0x00400ea0, + 0x00400ea4, + 0x00400ea8, + 0x00400e90, + 0x00400e94, + 0x00400e98, + 0x00400e9c, + NV10_PGRAPH_WINDOWCLIP_HORIZONTAL, /* 8 values from 0x400f00-0x400f1c */ + NV10_PGRAPH_WINDOWCLIP_VERTICAL, /* 8 values from 0x400f20-0x400f3c */ + 0x00400f04, + 0x00400f24, + 0x00400f08, + 0x00400f28, + 0x00400f0c, + 0x00400f2c, + 0x00400f10, + 0x00400f30, + 0x00400f14, + 0x00400f34, + 0x00400f18, + 0x00400f38, + 0x00400f1c, + 0x00400f3c, + NV10_PGRAPH_XFMODE0, + NV10_PGRAPH_XFMODE1, + NV10_PGRAPH_GLOBALSTATE0, + NV10_PGRAPH_GLOBALSTATE1, + NV04_PGRAPH_STORED_FMT, + NV04_PGRAPH_SOURCE_COLOR, + NV03_PGRAPH_ABS_X_RAM, /* 32 values from 0x400400 to 0x40047c */ + NV03_PGRAPH_ABS_Y_RAM, /* 32 values from 0x400480 to 0x4004fc */ + 0x00400404, + 0x00400484, + 0x00400408, + 0x00400488, + 0x0040040c, + 0x0040048c, + 0x00400410, + 0x00400490, + 0x00400414, + 0x00400494, + 0x00400418, + 0x00400498, + 0x0040041c, + 0x0040049c, + 0x00400420, + 0x004004a0, + 0x00400424, + 0x004004a4, + 0x00400428, + 0x004004a8, + 0x0040042c, + 0x004004ac, + 0x00400430, + 0x004004b0, + 0x00400434, + 0x004004b4, + 0x00400438, + 0x004004b8, + 0x0040043c, + 0x004004bc, + 0x00400440, + 0x004004c0, + 0x00400444, + 0x004004c4, + 0x00400448, + 0x004004c8, + 0x0040044c, + 0x004004cc, + 0x00400450, + 0x004004d0, + 0x00400454, + 0x004004d4, + 0x00400458, + 0x004004d8, + 0x0040045c, + 0x004004dc, + 0x00400460, + 0x004004e0, + 0x00400464, + 0x004004e4, + 0x00400468, + 0x004004e8, + 0x0040046c, + 0x004004ec, + 0x00400470, + 0x004004f0, + 0x00400474, + 0x004004f4, + 0x00400478, + 0x004004f8, + 0x0040047c, + 0x004004fc, + NV03_PGRAPH_ABS_UCLIP_XMIN, + NV03_PGRAPH_ABS_UCLIP_XMAX, + NV03_PGRAPH_ABS_UCLIP_YMIN, + NV03_PGRAPH_ABS_UCLIP_YMAX, + 0x00400550, + 0x00400558, + 0x00400554, + 0x0040055c, + NV03_PGRAPH_ABS_UCLIPA_XMIN, + NV03_PGRAPH_ABS_UCLIPA_XMAX, + NV03_PGRAPH_ABS_UCLIPA_YMIN, + NV03_PGRAPH_ABS_UCLIPA_YMAX, + NV03_PGRAPH_ABS_ICLIP_XMAX, + NV03_PGRAPH_ABS_ICLIP_YMAX, + NV03_PGRAPH_XY_LOGIC_MISC0, + NV03_PGRAPH_XY_LOGIC_MISC1, + NV03_PGRAPH_XY_LOGIC_MISC2, + NV03_PGRAPH_XY_LOGIC_MISC3, + NV03_PGRAPH_CLIPX_0, + NV03_PGRAPH_CLIPX_1, + NV03_PGRAPH_CLIPY_0, + NV03_PGRAPH_CLIPY_1, + NV10_PGRAPH_COMBINER0_IN_ALPHA, + NV10_PGRAPH_COMBINER1_IN_ALPHA, + NV10_PGRAPH_COMBINER0_IN_RGB, + NV10_PGRAPH_COMBINER1_IN_RGB, + NV10_PGRAPH_COMBINER_COLOR0, + NV10_PGRAPH_COMBINER_COLOR1, + NV10_PGRAPH_COMBINER0_OUT_ALPHA, + NV10_PGRAPH_COMBINER1_OUT_ALPHA, + NV10_PGRAPH_COMBINER0_OUT_RGB, + NV10_PGRAPH_COMBINER1_OUT_RGB, + NV10_PGRAPH_COMBINER_FINAL0, + NV10_PGRAPH_COMBINER_FINAL1, + 0x00400e00, + 0x00400e04, + 0x00400e08, + 0x00400e0c, + 0x00400e10, + 0x00400e14, + 0x00400e18, + 0x00400e1c, + 0x00400e20, + 0x00400e24, + 0x00400e28, + 0x00400e2c, + 0x00400e30, + 0x00400e34, + 0x00400e38, + 0x00400e3c, + NV04_PGRAPH_PASSTHRU_0, + NV04_PGRAPH_PASSTHRU_1, + NV04_PGRAPH_PASSTHRU_2, + NV10_PGRAPH_DIMX_TEXTURE, + NV10_PGRAPH_WDIMX_TEXTURE, + NV10_PGRAPH_DVD_COLORFMT, + NV10_PGRAPH_SCALED_FORMAT, + NV04_PGRAPH_MISC24_0, + NV04_PGRAPH_MISC24_1, + NV04_PGRAPH_MISC24_2, + NV03_PGRAPH_X_MISC, + NV03_PGRAPH_Y_MISC, + NV04_PGRAPH_VALID1, + NV04_PGRAPH_VALID2, +}; + +static int nv17_graph_ctx_regs[] = { + NV10_PGRAPH_DEBUG_4, + 0x004006b0, + 0x00400eac, + 0x00400eb0, + 0x00400eb4, + 0x00400eb8, + 0x00400ebc, + 0x00400ec0, + 0x00400ec4, + 0x00400ec8, + 0x00400ecc, + 0x00400ed0, + 0x00400ed4, + 0x00400ed8, + 0x00400edc, + 0x00400ee0, + 0x00400a00, + 0x00400a04, +}; + +struct graph_state { + int nv10[ARRAY_SIZE(nv10_graph_ctx_regs)]; + int nv17[ARRAY_SIZE(nv17_graph_ctx_regs)]; + struct pipe_state pipe_state; +}; + +static void nv10_graph_save_pipe(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct graph_state *pgraph_ctx = chan->pgraph_ctx; + struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state; + int i; +#define PIPE_SAVE(addr) \ + do { \ + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ + for (i = 0; i < ARRAY_SIZE(fifo_pipe_state->pipe_##addr); i++) \ + fifo_pipe_state->pipe_##addr[i] = nv_rd32(dev, NV10_PGRAPH_PIPE_DATA); \ + } while (0) + + PIPE_SAVE(0x4400); + PIPE_SAVE(0x0200); + PIPE_SAVE(0x6400); + PIPE_SAVE(0x6800); + PIPE_SAVE(0x6c00); + PIPE_SAVE(0x7000); + PIPE_SAVE(0x7400); + PIPE_SAVE(0x7800); + PIPE_SAVE(0x0040); + PIPE_SAVE(0x0000); + +#undef PIPE_SAVE +} + +static void nv10_graph_load_pipe(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct graph_state *pgraph_ctx = chan->pgraph_ctx; + struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state; + int i; + uint32_t xfmode0, xfmode1; +#define PIPE_RESTORE(addr) \ + do { \ + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ + for (i = 0; i < ARRAY_SIZE(fifo_pipe_state->pipe_##addr); i++) \ + nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, fifo_pipe_state->pipe_##addr[i]); \ + } while (0) + + + nouveau_wait_for_idle(dev); + /* XXX check haiku comments */ + xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0); + xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1); + nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000); + nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000); + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); + for (i = 0; i < 4; i++) + nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + for (i = 0; i < 4; i++) + nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); + + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); + for (i = 0; i < 3; i++) + nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); + for (i = 0; i < 3; i++) + nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); + + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); + nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008); + + + PIPE_RESTORE(0x0200); + nouveau_wait_for_idle(dev); + + /* restore XFMODE */ + nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0); + nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1); + PIPE_RESTORE(0x6400); + PIPE_RESTORE(0x6800); + PIPE_RESTORE(0x6c00); + PIPE_RESTORE(0x7000); + PIPE_RESTORE(0x7400); + PIPE_RESTORE(0x7800); + PIPE_RESTORE(0x4400); + PIPE_RESTORE(0x0000); + PIPE_RESTORE(0x0040); + nouveau_wait_for_idle(dev); + +#undef PIPE_RESTORE +} + +static void nv10_graph_create_pipe(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct graph_state *pgraph_ctx = chan->pgraph_ctx; + struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state; + uint32_t *fifo_pipe_state_addr; + int i; +#define PIPE_INIT(addr) \ + do { \ + fifo_pipe_state_addr = fifo_pipe_state->pipe_##addr; \ + } while (0) +#define PIPE_INIT_END(addr) \ + do { \ + uint32_t *__end_addr = fifo_pipe_state->pipe_##addr + \ + ARRAY_SIZE(fifo_pipe_state->pipe_##addr); \ + if (fifo_pipe_state_addr != __end_addr) \ + NV_ERROR(dev, "incomplete pipe init for 0x%x : %p/%p\n", \ + addr, fifo_pipe_state_addr, __end_addr); \ + } while (0) +#define NV_WRITE_PIPE_INIT(value) *(fifo_pipe_state_addr++) = value + + PIPE_INIT(0x0200); + for (i = 0; i < 48; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x0200); + + PIPE_INIT(0x6400); + for (i = 0; i < 211; i++) + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x40000000); + NV_WRITE_PIPE_INIT(0x40000000); + NV_WRITE_PIPE_INIT(0x40000000); + NV_WRITE_PIPE_INIT(0x40000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f000000); + NV_WRITE_PIPE_INIT(0x3f000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x3f800000); + PIPE_INIT_END(0x6400); + + PIPE_INIT(0x6800); + for (i = 0; i < 162; i++) + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); + for (i = 0; i < 25; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x6800); + + PIPE_INIT(0x6c00); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0xbf800000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x6c00); + + PIPE_INIT(0x7000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + for (i = 0; i < 35; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x7000); + + PIPE_INIT(0x7400); + for (i = 0; i < 48; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x7400); + + PIPE_INIT(0x7800); + for (i = 0; i < 48; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x7800); + + PIPE_INIT(0x4400); + for (i = 0; i < 32; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x4400); + + PIPE_INIT(0x0000); + for (i = 0; i < 16; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x0000); + + PIPE_INIT(0x0040); + for (i = 0; i < 4; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x0040); + +#undef PIPE_INIT +#undef PIPE_INIT_END +#undef NV_WRITE_PIPE_INIT +} + +static int nv10_graph_ctx_regs_find_offset(struct drm_device *dev, int reg) +{ + int i; + for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) { + if (nv10_graph_ctx_regs[i] == reg) + return i; + } + NV_ERROR(dev, "unknow offset nv10_ctx_regs %d\n", reg); + return -1; +} + +static int nv17_graph_ctx_regs_find_offset(struct drm_device *dev, int reg) +{ + int i; + for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) { + if (nv17_graph_ctx_regs[i] == reg) + return i; + } + NV_ERROR(dev, "unknow offset nv17_ctx_regs %d\n", reg); + return -1; +} + +int nv10_graph_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct graph_state *pgraph_ctx = chan->pgraph_ctx; + uint32_t tmp; + int i; + + for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) + nv_wr32(dev, nv10_graph_ctx_regs[i], pgraph_ctx->nv10[i]); + if (dev_priv->chipset >= 0x17) { + for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) + nv_wr32(dev, nv17_graph_ctx_regs[i], + pgraph_ctx->nv17[i]); + } + + nv10_graph_load_pipe(chan); + + nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100); + tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER); + nv_wr32(dev, NV10_PGRAPH_CTX_USER, (tmp & 0xffffff) | chan->id << 24); + tmp = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2); + nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, tmp & 0xcfffffff); + return 0; +} + +int +nv10_graph_unload_context(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + struct nouveau_channel *chan; + struct graph_state *ctx; + uint32_t tmp; + int i; + + chan = pgraph->channel(dev); + if (!chan) + return 0; + ctx = chan->pgraph_ctx; + + for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) + ctx->nv10[i] = nv_rd32(dev, nv10_graph_ctx_regs[i]); + + if (dev_priv->chipset >= 0x17) { + for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) + ctx->nv17[i] = nv_rd32(dev, nv17_graph_ctx_regs[i]); + } + + nv10_graph_save_pipe(chan); + + nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000); + tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; + tmp |= (pfifo->channels - 1) << 24; + nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp); + return 0; +} + +void +nv10_graph_context_switch(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_channel *chan = NULL; + int chid; + + pgraph->fifo_access(dev, false); + nouveau_wait_for_idle(dev); + + /* If previous context is valid, we need to save it */ + nv10_graph_unload_context(dev); + + /* Load context for next channel */ + chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; + chan = dev_priv->fifos[chid]; + if (chan) + nv10_graph_load_context(chan); + + pgraph->fifo_access(dev, true); +} + +#define NV_WRITE_CTX(reg, val) do { \ + int offset = nv10_graph_ctx_regs_find_offset(dev, reg); \ + if (offset > 0) \ + pgraph_ctx->nv10[offset] = val; \ + } while (0) + +#define NV17_WRITE_CTX(reg, val) do { \ + int offset = nv17_graph_ctx_regs_find_offset(dev, reg); \ + if (offset > 0) \ + pgraph_ctx->nv17[offset] = val; \ + } while (0) + +struct nouveau_channel * +nv10_graph_channel(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int chid = dev_priv->engine.fifo.channels; + + if (nv_rd32(dev, NV10_PGRAPH_CTX_CONTROL) & 0x00010000) + chid = nv_rd32(dev, NV10_PGRAPH_CTX_USER) >> 24; + + if (chid >= dev_priv->engine.fifo.channels) + return NULL; + + return dev_priv->fifos[chid]; +} + +int nv10_graph_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct graph_state *pgraph_ctx; + + NV_DEBUG(dev, "nv10_graph_context_create %d\n", chan->id); + + chan->pgraph_ctx = pgraph_ctx = kzalloc(sizeof(*pgraph_ctx), + GFP_KERNEL); + if (pgraph_ctx == NULL) + return -ENOMEM; + + + NV_WRITE_CTX(0x00400e88, 0x08000000); + NV_WRITE_CTX(0x00400e9c, 0x4b7fffff); + NV_WRITE_CTX(NV03_PGRAPH_XY_LOGIC_MISC0, 0x0001ffff); + NV_WRITE_CTX(0x00400e10, 0x00001000); + NV_WRITE_CTX(0x00400e14, 0x00001000); + NV_WRITE_CTX(0x00400e30, 0x00080008); + NV_WRITE_CTX(0x00400e34, 0x00080008); + if (dev_priv->chipset >= 0x17) { + /* is it really needed ??? */ + NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4, + nv_rd32(dev, NV10_PGRAPH_DEBUG_4)); + NV17_WRITE_CTX(0x004006b0, nv_rd32(dev, 0x004006b0)); + NV17_WRITE_CTX(0x00400eac, 0x0fff0000); + NV17_WRITE_CTX(0x00400eb0, 0x0fff0000); + NV17_WRITE_CTX(0x00400ec0, 0x00000080); + NV17_WRITE_CTX(0x00400ed0, 0x00000080); + } + NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->id << 24); + + nv10_graph_create_pipe(chan); + return 0; +} + +void nv10_graph_destroy_context(struct nouveau_channel *chan) +{ + struct graph_state *pgraph_ctx = chan->pgraph_ctx; + + kfree(pgraph_ctx); + chan->pgraph_ctx = NULL; +} + +int nv10_graph_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t tmp; + int i; + + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & + ~NV_PMC_ENABLE_PGRAPH); + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | + NV_PMC_ENABLE_PGRAPH); + + nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + + nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000); + nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x00118700); + /* nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */ + nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x25f92ad9); + nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0x55DE0830 | + (1<<29) | + (1<<31)); + if (dev_priv->chipset >= 0x17) { + nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x1f000000); + nv_wr32(dev, 0x004006b0, 0x40000020); + } else + nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000); + + /* copy tile info from PFB */ + for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { + nv_wr32(dev, NV10_PGRAPH_TILE(i), + nv_rd32(dev, NV10_PFB_TILE(i))); + nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), + nv_rd32(dev, NV10_PFB_TLIMIT(i))); + nv_wr32(dev, NV10_PGRAPH_TSIZE(i), + nv_rd32(dev, NV10_PFB_TSIZE(i))); + nv_wr32(dev, NV10_PGRAPH_TSTATUS(i), + nv_rd32(dev, NV10_PFB_TSTATUS(i))); + } + + nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH1, 0x00000000); + nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH2, 0x00000000); + nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH3, 0x00000000); + nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH4, 0x00000000); + nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); + + tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; + tmp |= (dev_priv->engine.fifo.channels - 1) << 24; + nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp); + nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); + nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, 0x08000000); + + return 0; +} + +void nv10_graph_takedown(struct drm_device *dev) +{ +} + +struct nouveau_pgraph_object_class nv10_graph_grclass[] = { + { 0x0030, false, NULL }, /* null */ + { 0x0039, false, NULL }, /* m2mf */ + { 0x004a, false, NULL }, /* gdirect */ + { 0x005f, false, NULL }, /* imageblit */ + { 0x009f, false, NULL }, /* imageblit (nv12) */ + { 0x008a, false, NULL }, /* ifc */ + { 0x0089, false, NULL }, /* sifm */ + { 0x0062, false, NULL }, /* surf2d */ + { 0x0043, false, NULL }, /* rop */ + { 0x0012, false, NULL }, /* beta1 */ + { 0x0072, false, NULL }, /* beta4 */ + { 0x0019, false, NULL }, /* cliprect */ + { 0x0044, false, NULL }, /* pattern */ + { 0x0052, false, NULL }, /* swzsurf */ + { 0x0093, false, NULL }, /* surf3d */ + { 0x0094, false, NULL }, /* tex_tri */ + { 0x0095, false, NULL }, /* multitex_tri */ + { 0x0056, false, NULL }, /* celcius (nv10) */ + { 0x0096, false, NULL }, /* celcius (nv11) */ + { 0x0099, false, NULL }, /* celcius (nv17) */ + {} +}; diff --git a/drivers/gpu/drm/nouveau/nv17_gpio.c b/drivers/gpu/drm/nouveau/nv17_gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..2e58c331e9b7dcc6830a63d3d8988d375a9d5179 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv17_gpio.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_hw.h" + +static bool +get_gpio_location(struct dcb_gpio_entry *ent, uint32_t *reg, uint32_t *shift, + uint32_t *mask) +{ + if (ent->line < 2) { + *reg = NV_PCRTC_GPIO; + *shift = ent->line * 16; + *mask = 0x11; + + } else if (ent->line < 10) { + *reg = NV_PCRTC_GPIO_EXT; + *shift = (ent->line - 2) * 4; + *mask = 0x3; + + } else if (ent->line < 14) { + *reg = NV_PCRTC_850; + *shift = (ent->line - 10) * 4; + *mask = 0x3; + + } else { + return false; + } + + return true; +} + +int +nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) +{ + struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); + uint32_t reg, shift, mask, value; + + if (!ent) + return -ENODEV; + + if (!get_gpio_location(ent, ®, &shift, &mask)) + return -ENODEV; + + value = NVReadCRTC(dev, 0, reg) >> shift; + + return (ent->invert ? 1 : 0) ^ (value & 1); +} + +int +nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) +{ + struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); + uint32_t reg, shift, mask, value; + + if (!ent) + return -ENODEV; + + if (!get_gpio_location(ent, ®, &shift, &mask)) + return -ENODEV; + + value = ((ent->invert ? 1 : 0) ^ (state ? 1 : 0)) << shift; + mask = ~(mask << shift); + + NVWriteCRTC(dev, 0, reg, value | (NVReadCRTC(dev, 0, reg) & mask)); + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c new file mode 100644 index 0000000000000000000000000000000000000000..46cfd9c604782f507332f4d1b092842e88692893 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv17_tv.c @@ -0,0 +1,681 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm_crtc_helper.h" +#include "nouveau_drv.h" +#include "nouveau_encoder.h" +#include "nouveau_connector.h" +#include "nouveau_crtc.h" +#include "nouveau_hw.h" +#include "nv17_tv.h" + +enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, + struct drm_connector *connector, + uint32_t pin_mask) +{ + struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); + + tv_enc->pin_mask = pin_mask >> 28 & 0xe; + + switch (tv_enc->pin_mask) { + case 0x2: + case 0x4: + tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Composite; + break; + case 0xc: + tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SVIDEO; + break; + case 0xe: + if (nouveau_encoder(encoder)->dcb->tvconf.has_component_output) + tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Component; + else + tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SCART; + break; + default: + tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Unknown; + break; + } + + drm_connector_property_set_value(connector, + encoder->dev->mode_config.tv_subconnector_property, + tv_enc->subconnector); + + return tv_enc->subconnector ? connector_status_connected : + connector_status_disconnected; +} + +static const struct { + int hdisplay; + int vdisplay; +} modes[] = { + { 640, 400 }, + { 640, 480 }, + { 720, 480 }, + { 720, 576 }, + { 800, 600 }, + { 1024, 768 }, + { 1280, 720 }, + { 1280, 1024 }, + { 1920, 1080 } +}; + +static int nv17_tv_get_modes(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); + struct drm_display_mode *mode; + struct drm_display_mode *output_mode; + int n = 0; + int i; + + if (tv_norm->kind != CTV_ENC_MODE) { + struct drm_display_mode *tv_mode; + + for (tv_mode = nv17_tv_modes; tv_mode->hdisplay; tv_mode++) { + mode = drm_mode_duplicate(encoder->dev, tv_mode); + + mode->clock = tv_norm->tv_enc_mode.vrefresh * + mode->htotal / 1000 * + mode->vtotal / 1000; + + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) + mode->clock *= 2; + + if (mode->hdisplay == tv_norm->tv_enc_mode.hdisplay && + mode->vdisplay == tv_norm->tv_enc_mode.vdisplay) + mode->type |= DRM_MODE_TYPE_PREFERRED; + + drm_mode_probed_add(connector, mode); + n++; + } + return n; + } + + /* tv_norm->kind == CTV_ENC_MODE */ + output_mode = &tv_norm->ctv_enc_mode.mode; + for (i = 0; i < ARRAY_SIZE(modes); i++) { + if (modes[i].hdisplay > output_mode->hdisplay || + modes[i].vdisplay > output_mode->vdisplay) + continue; + + if (modes[i].hdisplay == output_mode->hdisplay && + modes[i].vdisplay == output_mode->vdisplay) { + mode = drm_mode_duplicate(encoder->dev, output_mode); + mode->type |= DRM_MODE_TYPE_PREFERRED; + } else { + mode = drm_cvt_mode(encoder->dev, modes[i].hdisplay, + modes[i].vdisplay, 60, false, + output_mode->flags & DRM_MODE_FLAG_INTERLACE, + false); + } + + /* CVT modes are sometimes unsuitable... */ + if (output_mode->hdisplay <= 720 + || output_mode->hdisplay >= 1920) { + mode->htotal = output_mode->htotal; + mode->hsync_start = (mode->hdisplay + (mode->htotal + - mode->hdisplay) * 9 / 10) & ~7; + mode->hsync_end = mode->hsync_start + 8; + } + if (output_mode->vdisplay >= 1024) { + mode->vtotal = output_mode->vtotal; + mode->vsync_start = output_mode->vsync_start; + mode->vsync_end = output_mode->vsync_end; + } + + mode->type |= DRM_MODE_TYPE_DRIVER; + drm_mode_probed_add(connector, mode); + n++; + } + return n; +} + +static int nv17_tv_mode_valid(struct drm_encoder *encoder, + struct drm_display_mode *mode) +{ + struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); + + if (tv_norm->kind == CTV_ENC_MODE) { + struct drm_display_mode *output_mode = + &tv_norm->ctv_enc_mode.mode; + + if (mode->clock > 400000) + return MODE_CLOCK_HIGH; + + if (mode->hdisplay > output_mode->hdisplay || + mode->vdisplay > output_mode->vdisplay) + return MODE_BAD; + + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) != + (output_mode->flags & DRM_MODE_FLAG_INTERLACE)) + return MODE_NO_INTERLACE; + + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) + return MODE_NO_DBLESCAN; + + } else { + const int vsync_tolerance = 600; + + if (mode->clock > 70000) + return MODE_CLOCK_HIGH; + + if (abs(drm_mode_vrefresh(mode) * 1000 - + tv_norm->tv_enc_mode.vrefresh) > vsync_tolerance) + return MODE_VSYNC; + + /* The encoder takes care of the actual interlacing */ + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + return MODE_NO_INTERLACE; + } + + return MODE_OK; +} + +static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); + + if (tv_norm->kind == CTV_ENC_MODE) + adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock; + else + adjusted_mode->clock = 90000; + + return true; +} + +static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct nv17_tv_state *regs = &to_tv_enc(encoder)->state; + struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); + + if (nouveau_encoder(encoder)->last_dpms == mode) + return; + nouveau_encoder(encoder)->last_dpms = mode; + + NV_TRACE(dev, "Setting dpms mode %d on TV encoder (output %d)\n", + mode, nouveau_encoder(encoder)->dcb->index); + + regs->ptv_200 &= ~1; + + if (tv_norm->kind == CTV_ENC_MODE) { + nv04_dfp_update_fp_control(encoder, mode); + + } else { + nv04_dfp_update_fp_control(encoder, DRM_MODE_DPMS_OFF); + + if (mode == DRM_MODE_DPMS_ON) + regs->ptv_200 |= 1; + } + + nv_load_ptv(dev, regs, 200); + + nv17_gpio_set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON); + nv17_gpio_set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON); + + nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); +} + +static void nv17_tv_prepare(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_encoder_helper_funcs *helper = encoder->helper_private; + struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); + int head = nouveau_crtc(encoder->crtc)->index; + uint8_t *cr_lcd = &dev_priv->mode_reg.crtc_reg[head].CRTC[ + NV_CIO_CRE_LCD__INDEX]; + uint32_t dacclk_off = NV_PRAMDAC_DACCLK + + nv04_dac_output_offset(encoder); + uint32_t dacclk; + + helper->dpms(encoder, DRM_MODE_DPMS_OFF); + + nv04_dfp_disable(dev, head); + + /* Unbind any FP encoders from this head if we need the FP + * stuff enabled. */ + if (tv_norm->kind == CTV_ENC_MODE) { + struct drm_encoder *enc; + + list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { + struct dcb_entry *dcb = nouveau_encoder(enc)->dcb; + + if ((dcb->type == OUTPUT_TMDS || + dcb->type == OUTPUT_LVDS) && + !enc->crtc && + nv04_dfp_get_bound_head(dev, dcb) == head) { + nv04_dfp_bind_head(dev, dcb, head ^ 1, + dev_priv->VBIOS.fp.dual_link); + } + } + + } + + /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f) + * at LCD__INDEX which we don't alter + */ + if (!(*cr_lcd & 0x44)) { + if (tv_norm->kind == CTV_ENC_MODE) + *cr_lcd = 0x1 | (head ? 0x0 : 0x8); + else + *cr_lcd = 0; + } + + /* Set the DACCLK register */ + dacclk = (NVReadRAMDAC(dev, 0, dacclk_off) & ~0x30) | 0x1; + + if (dev_priv->card_type == NV_40) + dacclk |= 0x1a << 16; + + if (tv_norm->kind == CTV_ENC_MODE) { + dacclk |= 0x20; + + if (head) + dacclk |= 0x100; + else + dacclk &= ~0x100; + + } else { + dacclk |= 0x10; + + } + + NVWriteRAMDAC(dev, 0, dacclk_off, dacclk); +} + +static void nv17_tv_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *drm_mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int head = nouveau_crtc(encoder->crtc)->index; + struct nv04_crtc_reg *regs = &dev_priv->mode_reg.crtc_reg[head]; + struct nv17_tv_state *tv_regs = &to_tv_enc(encoder)->state; + struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); + int i; + + regs->CRTC[NV_CIO_CRE_53] = 0x40; /* FP_HTIMING */ + regs->CRTC[NV_CIO_CRE_54] = 0; /* FP_VTIMING */ + regs->ramdac_630 = 0x2; /* turn off green mode (tv test pattern?) */ + regs->tv_setup = 1; + regs->ramdac_8c0 = 0x0; + + if (tv_norm->kind == TV_ENC_MODE) { + tv_regs->ptv_200 = 0x13111100; + if (head) + tv_regs->ptv_200 |= 0x10; + + tv_regs->ptv_20c = 0x808010; + tv_regs->ptv_304 = 0x2d00000; + tv_regs->ptv_600 = 0x0; + tv_regs->ptv_60c = 0x0; + tv_regs->ptv_610 = 0x1e00000; + + if (tv_norm->tv_enc_mode.vdisplay == 576) { + tv_regs->ptv_508 = 0x1200000; + tv_regs->ptv_614 = 0x33; + + } else if (tv_norm->tv_enc_mode.vdisplay == 480) { + tv_regs->ptv_508 = 0xf00000; + tv_regs->ptv_614 = 0x13; + } + + if (dev_priv->card_type >= NV_30) { + tv_regs->ptv_500 = 0xe8e0; + tv_regs->ptv_504 = 0x1710; + tv_regs->ptv_604 = 0x0; + tv_regs->ptv_608 = 0x0; + } else { + if (tv_norm->tv_enc_mode.vdisplay == 576) { + tv_regs->ptv_604 = 0x20; + tv_regs->ptv_608 = 0x10; + tv_regs->ptv_500 = 0x19710; + tv_regs->ptv_504 = 0x68f0; + + } else if (tv_norm->tv_enc_mode.vdisplay == 480) { + tv_regs->ptv_604 = 0x10; + tv_regs->ptv_608 = 0x20; + tv_regs->ptv_500 = 0x4b90; + tv_regs->ptv_504 = 0x1b480; + } + } + + for (i = 0; i < 0x40; i++) + tv_regs->tv_enc[i] = tv_norm->tv_enc_mode.tv_enc[i]; + + } else { + struct drm_display_mode *output_mode = + &tv_norm->ctv_enc_mode.mode; + + /* The registers in PRAMDAC+0xc00 control some timings and CSC + * parameters for the CTV encoder (It's only used for "HD" TV + * modes, I don't think I have enough working to guess what + * they exactly mean...), it's probably connected at the + * output of the FP encoder, but it also needs the analog + * encoder in its OR enabled and routed to the head it's + * using. It's enabled with the DACCLK register, bits [5:4]. + */ + for (i = 0; i < 38; i++) + regs->ctv_regs[i] = tv_norm->ctv_enc_mode.ctv_regs[i]; + + regs->fp_horiz_regs[FP_DISPLAY_END] = output_mode->hdisplay - 1; + regs->fp_horiz_regs[FP_TOTAL] = output_mode->htotal - 1; + regs->fp_horiz_regs[FP_SYNC_START] = + output_mode->hsync_start - 1; + regs->fp_horiz_regs[FP_SYNC_END] = output_mode->hsync_end - 1; + regs->fp_horiz_regs[FP_CRTC] = output_mode->hdisplay + + max((output_mode->hdisplay-600)/40 - 1, 1); + + regs->fp_vert_regs[FP_DISPLAY_END] = output_mode->vdisplay - 1; + regs->fp_vert_regs[FP_TOTAL] = output_mode->vtotal - 1; + regs->fp_vert_regs[FP_SYNC_START] = + output_mode->vsync_start - 1; + regs->fp_vert_regs[FP_SYNC_END] = output_mode->vsync_end - 1; + regs->fp_vert_regs[FP_CRTC] = output_mode->vdisplay - 1; + + regs->fp_control = NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | + NV_PRAMDAC_FP_TG_CONTROL_READ_PROG | + NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12; + + if (output_mode->flags & DRM_MODE_FLAG_PVSYNC) + regs->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS; + if (output_mode->flags & DRM_MODE_FLAG_PHSYNC) + regs->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS; + + regs->fp_debug_0 = NV_PRAMDAC_FP_DEBUG_0_YWEIGHT_ROUND | + NV_PRAMDAC_FP_DEBUG_0_XWEIGHT_ROUND | + NV_PRAMDAC_FP_DEBUG_0_YINTERP_BILINEAR | + NV_PRAMDAC_FP_DEBUG_0_XINTERP_BILINEAR | + NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED | + NV_PRAMDAC_FP_DEBUG_0_YSCALE_ENABLE | + NV_PRAMDAC_FP_DEBUG_0_XSCALE_ENABLE; + + regs->fp_debug_2 = 0; + + regs->fp_margin_color = 0x801080; + + } +} + +static void nv17_tv_commit(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_encoder_helper_funcs *helper = encoder->helper_private; + + if (get_tv_norm(encoder)->kind == TV_ENC_MODE) { + nv17_tv_update_rescaler(encoder); + nv17_tv_update_properties(encoder); + } else { + nv17_ctv_update_rescaler(encoder); + } + + nv17_tv_state_load(dev, &to_tv_enc(encoder)->state); + + /* This could use refinement for flatpanels, but it should work */ + if (dev_priv->chipset < 0x44) + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + + nv04_dac_output_offset(encoder), + 0xf0000000); + else + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + + nv04_dac_output_offset(encoder), + 0x00100000); + + helper->dpms(encoder, DRM_MODE_DPMS_ON); + + NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + drm_get_connector_name( + &nouveau_encoder_connector_get(nv_encoder)->base), + nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); +} + +static void nv17_tv_save(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); + + nouveau_encoder(encoder)->restore.output = + NVReadRAMDAC(dev, 0, + NV_PRAMDAC_DACCLK + + nv04_dac_output_offset(encoder)); + + nv17_tv_state_save(dev, &tv_enc->saved_state); + + tv_enc->state.ptv_200 = tv_enc->saved_state.ptv_200; +} + +static void nv17_tv_restore(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + + nv04_dac_output_offset(encoder), + nouveau_encoder(encoder)->restore.output); + + nv17_tv_state_load(dev, &to_tv_enc(encoder)->saved_state); +} + +static int nv17_tv_create_resources(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct drm_mode_config *conf = &dev->mode_config; + struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); + struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + int num_tv_norms = dcb->tvconf.has_component_output ? NUM_TV_NORMS : + NUM_LD_TV_NORMS; + int i; + + if (nouveau_tv_norm) { + for (i = 0; i < num_tv_norms; i++) { + if (!strcmp(nv17_tv_norm_names[i], nouveau_tv_norm)) { + tv_enc->tv_norm = i; + break; + } + } + + if (i == num_tv_norms) + NV_WARN(dev, "Invalid TV norm setting \"%s\"\n", + nouveau_tv_norm); + } + + drm_mode_create_tv_properties(dev, num_tv_norms, nv17_tv_norm_names); + + drm_connector_attach_property(connector, + conf->tv_select_subconnector_property, + tv_enc->select_subconnector); + drm_connector_attach_property(connector, + conf->tv_subconnector_property, + tv_enc->subconnector); + drm_connector_attach_property(connector, + conf->tv_mode_property, + tv_enc->tv_norm); + drm_connector_attach_property(connector, + conf->tv_flicker_reduction_property, + tv_enc->flicker); + drm_connector_attach_property(connector, + conf->tv_saturation_property, + tv_enc->saturation); + drm_connector_attach_property(connector, + conf->tv_hue_property, + tv_enc->hue); + drm_connector_attach_property(connector, + conf->tv_overscan_property, + tv_enc->overscan); + + return 0; +} + +static int nv17_tv_set_property(struct drm_encoder *encoder, + struct drm_connector *connector, + struct drm_property *property, + uint64_t val) +{ + struct drm_mode_config *conf = &encoder->dev->mode_config; + struct drm_crtc *crtc = encoder->crtc; + struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); + struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); + bool modes_changed = false; + + if (property == conf->tv_overscan_property) { + tv_enc->overscan = val; + if (encoder->crtc) { + if (tv_norm->kind == CTV_ENC_MODE) + nv17_ctv_update_rescaler(encoder); + else + nv17_tv_update_rescaler(encoder); + } + + } else if (property == conf->tv_saturation_property) { + if (tv_norm->kind != TV_ENC_MODE) + return -EINVAL; + + tv_enc->saturation = val; + nv17_tv_update_properties(encoder); + + } else if (property == conf->tv_hue_property) { + if (tv_norm->kind != TV_ENC_MODE) + return -EINVAL; + + tv_enc->hue = val; + nv17_tv_update_properties(encoder); + + } else if (property == conf->tv_flicker_reduction_property) { + if (tv_norm->kind != TV_ENC_MODE) + return -EINVAL; + + tv_enc->flicker = val; + if (encoder->crtc) + nv17_tv_update_rescaler(encoder); + + } else if (property == conf->tv_mode_property) { + if (connector->dpms != DRM_MODE_DPMS_OFF) + return -EINVAL; + + tv_enc->tv_norm = val; + + modes_changed = true; + + } else if (property == conf->tv_select_subconnector_property) { + if (tv_norm->kind != TV_ENC_MODE) + return -EINVAL; + + tv_enc->select_subconnector = val; + nv17_tv_update_properties(encoder); + + } else { + return -EINVAL; + } + + if (modes_changed) { + drm_helper_probe_single_connector_modes(connector, 0, 0); + + /* Disable the crtc to ensure a full modeset is + * performed whenever it's turned on again. */ + if (crtc) { + struct drm_mode_set modeset = { + .crtc = crtc, + }; + + crtc->funcs->set_config(&modeset); + } + } + + return 0; +} + +static void nv17_tv_destroy(struct drm_encoder *encoder) +{ + struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); + + NV_DEBUG(encoder->dev, "\n"); + + drm_encoder_cleanup(encoder); + kfree(tv_enc); +} + +static struct drm_encoder_helper_funcs nv17_tv_helper_funcs = { + .dpms = nv17_tv_dpms, + .save = nv17_tv_save, + .restore = nv17_tv_restore, + .mode_fixup = nv17_tv_mode_fixup, + .prepare = nv17_tv_prepare, + .commit = nv17_tv_commit, + .mode_set = nv17_tv_mode_set, + .detect = nv17_dac_detect, +}; + +static struct drm_encoder_slave_funcs nv17_tv_slave_funcs = { + .get_modes = nv17_tv_get_modes, + .mode_valid = nv17_tv_mode_valid, + .create_resources = nv17_tv_create_resources, + .set_property = nv17_tv_set_property, +}; + +static struct drm_encoder_funcs nv17_tv_funcs = { + .destroy = nv17_tv_destroy, +}; + +int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry) +{ + struct drm_encoder *encoder; + struct nv17_tv_encoder *tv_enc = NULL; + + tv_enc = kzalloc(sizeof(*tv_enc), GFP_KERNEL); + if (!tv_enc) + return -ENOMEM; + + tv_enc->overscan = 50; + tv_enc->flicker = 50; + tv_enc->saturation = 50; + tv_enc->hue = 0; + tv_enc->tv_norm = TV_NORM_PAL; + tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Unknown; + tv_enc->select_subconnector = DRM_MODE_SUBCONNECTOR_Automatic; + tv_enc->pin_mask = 0; + + encoder = to_drm_encoder(&tv_enc->base); + + tv_enc->base.dcb = entry; + tv_enc->base.or = ffs(entry->or) - 1; + + drm_encoder_init(dev, encoder, &nv17_tv_funcs, DRM_MODE_ENCODER_TVDAC); + drm_encoder_helper_add(encoder, &nv17_tv_helper_funcs); + to_encoder_slave(encoder)->slave_funcs = &nv17_tv_slave_funcs; + + encoder->possible_crtcs = entry->heads; + encoder->possible_clones = 0; + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nv17_tv.h b/drivers/gpu/drm/nouveau/nv17_tv.h new file mode 100644 index 0000000000000000000000000000000000000000..c00977cedabd6654e446965fbff7b94d782a9670 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv17_tv.h @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +#ifndef __NV17_TV_H__ +#define __NV17_TV_H__ + +struct nv17_tv_state { + uint8_t tv_enc[0x40]; + + uint32_t hfilter[4][7]; + uint32_t hfilter2[4][7]; + uint32_t vfilter[4][7]; + + uint32_t ptv_200; + uint32_t ptv_204; + uint32_t ptv_208; + uint32_t ptv_20c; + uint32_t ptv_304; + uint32_t ptv_500; + uint32_t ptv_504; + uint32_t ptv_508; + uint32_t ptv_600; + uint32_t ptv_604; + uint32_t ptv_608; + uint32_t ptv_60c; + uint32_t ptv_610; + uint32_t ptv_614; +}; + +enum nv17_tv_norm{ + TV_NORM_PAL, + TV_NORM_PAL_M, + TV_NORM_PAL_N, + TV_NORM_PAL_NC, + TV_NORM_NTSC_M, + TV_NORM_NTSC_J, + NUM_LD_TV_NORMS, + TV_NORM_HD480I = NUM_LD_TV_NORMS, + TV_NORM_HD480P, + TV_NORM_HD576I, + TV_NORM_HD576P, + TV_NORM_HD720P, + TV_NORM_HD1080I, + NUM_TV_NORMS +}; + +struct nv17_tv_encoder { + struct nouveau_encoder base; + + struct nv17_tv_state state; + struct nv17_tv_state saved_state; + + int overscan; + int flicker; + int saturation; + int hue; + enum nv17_tv_norm tv_norm; + int subconnector; + int select_subconnector; + uint32_t pin_mask; +}; +#define to_tv_enc(x) container_of(nouveau_encoder(x), \ + struct nv17_tv_encoder, base) + +extern char *nv17_tv_norm_names[NUM_TV_NORMS]; + +extern struct nv17_tv_norm_params { + enum { + TV_ENC_MODE, + CTV_ENC_MODE, + } kind; + + union { + struct { + int hdisplay; + int vdisplay; + int vrefresh; /* mHz */ + + uint8_t tv_enc[0x40]; + } tv_enc_mode; + + struct { + struct drm_display_mode mode; + + uint32_t ctv_regs[38]; + } ctv_enc_mode; + }; + +} nv17_tv_norms[NUM_TV_NORMS]; +#define get_tv_norm(enc) (&nv17_tv_norms[to_tv_enc(enc)->tv_norm]) + +extern struct drm_display_mode nv17_tv_modes[]; + +static inline int interpolate(int y0, int y1, int y2, int x) +{ + return y1 + (x < 50 ? y1 - y0 : y2 - y1) * (x - 50) / 50; +} + +void nv17_tv_state_save(struct drm_device *dev, struct nv17_tv_state *state); +void nv17_tv_state_load(struct drm_device *dev, struct nv17_tv_state *state); +void nv17_tv_update_properties(struct drm_encoder *encoder); +void nv17_tv_update_rescaler(struct drm_encoder *encoder); +void nv17_ctv_update_rescaler(struct drm_encoder *encoder); + +/* TV hardware access functions */ + +static inline void nv_write_ptv(struct drm_device *dev, uint32_t reg, uint32_t val) +{ + nv_wr32(dev, reg, val); +} + +static inline uint32_t nv_read_ptv(struct drm_device *dev, uint32_t reg) +{ + return nv_rd32(dev, reg); +} + +static inline void nv_write_tv_enc(struct drm_device *dev, uint8_t reg, uint8_t val) +{ + nv_write_ptv(dev, NV_PTV_TV_INDEX, reg); + nv_write_ptv(dev, NV_PTV_TV_DATA, val); +} + +static inline uint8_t nv_read_tv_enc(struct drm_device *dev, uint8_t reg) +{ + nv_write_ptv(dev, NV_PTV_TV_INDEX, reg); + return nv_read_ptv(dev, NV_PTV_TV_DATA); +} + +#define nv_load_ptv(dev, state, reg) nv_write_ptv(dev, NV_PTV_OFFSET + 0x##reg, state->ptv_##reg) +#define nv_save_ptv(dev, state, reg) state->ptv_##reg = nv_read_ptv(dev, NV_PTV_OFFSET + 0x##reg) +#define nv_load_tv_enc(dev, state, reg) nv_write_tv_enc(dev, 0x##reg, state->tv_enc[0x##reg]) + +#endif diff --git a/drivers/gpu/drm/nouveau/nv17_tv_modes.c b/drivers/gpu/drm/nouveau/nv17_tv_modes.c new file mode 100644 index 0000000000000000000000000000000000000000..d64683d97e0d044a192a8a42146a13aa4a08a4b4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv17_tv_modes.c @@ -0,0 +1,583 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm_crtc_helper.h" +#include "nouveau_drv.h" +#include "nouveau_encoder.h" +#include "nouveau_crtc.h" +#include "nouveau_hw.h" +#include "nv17_tv.h" + +char *nv17_tv_norm_names[NUM_TV_NORMS] = { + [TV_NORM_PAL] = "PAL", + [TV_NORM_PAL_M] = "PAL-M", + [TV_NORM_PAL_N] = "PAL-N", + [TV_NORM_PAL_NC] = "PAL-Nc", + [TV_NORM_NTSC_M] = "NTSC-M", + [TV_NORM_NTSC_J] = "NTSC-J", + [TV_NORM_HD480I] = "hd480i", + [TV_NORM_HD480P] = "hd480p", + [TV_NORM_HD576I] = "hd576i", + [TV_NORM_HD576P] = "hd576p", + [TV_NORM_HD720P] = "hd720p", + [TV_NORM_HD1080I] = "hd1080i" +}; + +/* TV standard specific parameters */ + +struct nv17_tv_norm_params nv17_tv_norms[NUM_TV_NORMS] = { + [TV_NORM_PAL] = { TV_ENC_MODE, { + .tv_enc_mode = { 720, 576, 50000, { + 0x2a, 0x9, 0x8a, 0xcb, 0x0, 0x0, 0xb, 0x18, + 0x7e, 0x40, 0x8a, 0x35, 0x27, 0x0, 0x34, 0x3, + 0x3e, 0x3, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x9c, + 0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x3, + 0xd3, 0x4, 0xd4, 0x1, 0x2, 0x0, 0xa, 0x5, + 0x0, 0x1a, 0xff, 0x3, 0x18, 0xf, 0x78, 0x0, + 0x0, 0xb4, 0x0, 0x15, 0x49, 0x10, 0x0, 0x9b, + 0xbd, 0x15, 0x5, 0x15, 0x3e, 0x3, 0x0, 0x0 + } } } }, + + [TV_NORM_PAL_M] = { TV_ENC_MODE, { + .tv_enc_mode = { 720, 480, 59940, { + 0x21, 0xe6, 0xef, 0xe3, 0x0, 0x0, 0xb, 0x18, + 0x7e, 0x44, 0x76, 0x32, 0x25, 0x0, 0x3c, 0x0, + 0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x83, + 0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1, + 0xc5, 0x4, 0xc5, 0x1, 0x2, 0x0, 0xa, 0x5, + 0x0, 0x18, 0xff, 0x3, 0x20, 0xf, 0x78, 0x0, + 0x0, 0xb4, 0x0, 0x15, 0x40, 0x10, 0x0, 0x9c, + 0xc8, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0 + } } } }, + + [TV_NORM_PAL_N] = { TV_ENC_MODE, { + .tv_enc_mode = { 720, 576, 50000, { + 0x2a, 0x9, 0x8a, 0xcb, 0x0, 0x0, 0xb, 0x18, + 0x7e, 0x40, 0x8a, 0x32, 0x25, 0x0, 0x3c, 0x0, + 0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x9c, + 0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1, + 0xc5, 0x4, 0xc5, 0x1, 0x2, 0x0, 0xa, 0x5, + 0x0, 0x1a, 0xff, 0x3, 0x18, 0xf, 0x78, 0x0, + 0x0, 0xb4, 0x0, 0x15, 0x49, 0x10, 0x0, 0x9b, + 0xbd, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0 + } } } }, + + [TV_NORM_PAL_NC] = { TV_ENC_MODE, { + .tv_enc_mode = { 720, 576, 50000, { + 0x21, 0xf6, 0x94, 0x46, 0x0, 0x0, 0xb, 0x18, + 0x7e, 0x44, 0x8a, 0x35, 0x27, 0x0, 0x34, 0x3, + 0x3e, 0x3, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x9c, + 0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x3, + 0xd3, 0x4, 0xd4, 0x1, 0x2, 0x0, 0xa, 0x5, + 0x0, 0x1a, 0xff, 0x3, 0x18, 0xf, 0x78, 0x0, + 0x0, 0xb4, 0x0, 0x15, 0x49, 0x10, 0x0, 0x9b, + 0xbd, 0x15, 0x5, 0x15, 0x3e, 0x3, 0x0, 0x0 + } } } }, + + [TV_NORM_NTSC_M] = { TV_ENC_MODE, { + .tv_enc_mode = { 720, 480, 59940, { + 0x21, 0xf0, 0x7c, 0x1f, 0x0, 0x0, 0xb, 0x18, + 0x7e, 0x44, 0x76, 0x48, 0x0, 0x0, 0x3c, 0x0, + 0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x83, + 0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1, + 0xc5, 0x4, 0xc5, 0x1, 0x2, 0x0, 0xa, 0x5, + 0x0, 0x16, 0xff, 0x3, 0x20, 0xf, 0x78, 0x0, + 0x0, 0xb4, 0x0, 0x15, 0x4, 0x10, 0x0, 0x9c, + 0xc8, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0 + } } } }, + + [TV_NORM_NTSC_J] = { TV_ENC_MODE, { + .tv_enc_mode = { 720, 480, 59940, { + 0x21, 0xf0, 0x7c, 0x1f, 0x0, 0x0, 0xb, 0x18, + 0x7e, 0x44, 0x76, 0x48, 0x0, 0x0, 0x32, 0x0, + 0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x83, + 0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1, + 0xcf, 0x4, 0xcf, 0x1, 0x2, 0x0, 0xa, 0x5, + 0x0, 0x16, 0xff, 0x3, 0x20, 0xf, 0x78, 0x0, + 0x0, 0xb4, 0x0, 0x15, 0x4, 0x10, 0x0, 0xa4, + 0xc8, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0 + } } } }, + + [TV_NORM_HD480I] = { TV_ENC_MODE, { + .tv_enc_mode = { 720, 480, 59940, { + 0x21, 0xf0, 0x7c, 0x1f, 0x0, 0x0, 0xb, 0x18, + 0x7e, 0x44, 0x76, 0x48, 0x0, 0x0, 0x32, 0x0, + 0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x83, + 0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1, + 0xcf, 0x4, 0xcf, 0x1, 0x2, 0x0, 0xa, 0x5, + 0x0, 0x16, 0xff, 0x3, 0x20, 0xf, 0x78, 0x0, + 0x0, 0xb4, 0x0, 0x15, 0x4, 0x10, 0x0, 0xa4, + 0xc8, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0 + } } } }, + + [TV_NORM_HD576I] = { TV_ENC_MODE, { + .tv_enc_mode = { 720, 576, 50000, { + 0x2a, 0x9, 0x8a, 0xcb, 0x0, 0x0, 0xb, 0x18, + 0x7e, 0x40, 0x8a, 0x35, 0x27, 0x0, 0x34, 0x3, + 0x3e, 0x3, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x9c, + 0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x3, + 0xd3, 0x4, 0xd4, 0x1, 0x2, 0x0, 0xa, 0x5, + 0x0, 0x1a, 0xff, 0x3, 0x18, 0xf, 0x78, 0x0, + 0x0, 0xb4, 0x0, 0x15, 0x49, 0x10, 0x0, 0x9b, + 0xbd, 0x15, 0x5, 0x15, 0x3e, 0x3, 0x0, 0x0 + } } } }, + + + [TV_NORM_HD480P] = { CTV_ENC_MODE, { + .ctv_enc_mode = { + .mode = { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, + 720, 735, 743, 858, 0, 480, 490, 494, 525, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + .ctv_regs = { 0x3540000, 0x0, 0x0, 0x314, + 0x354003a, 0x40000, 0x6f0344, 0x18100000, + 0x10160004, 0x10060005, 0x1006000c, 0x10060020, + 0x10060021, 0x140e0022, 0x10060202, 0x1802020a, + 0x1810020b, 0x10000fff, 0x10000fff, 0x10000fff, + 0x10000fff, 0x10000fff, 0x10000fff, 0x70, + 0x3ff0000, 0x57, 0x2e001e, 0x258012c, + 0xa0aa04ec, 0x30, 0x80960019, 0x12c0300, + 0x2019, 0x600, 0x32060019, 0x0, 0x0, 0x400 + } } } }, + + [TV_NORM_HD576P] = { CTV_ENC_MODE, { + .ctv_enc_mode = { + .mode = { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, + 720, 730, 738, 864, 0, 576, 581, 585, 625, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + .ctv_regs = { 0x3540000, 0x0, 0x0, 0x314, + 0x354003a, 0x40000, 0x6f0344, 0x18100000, + 0x10060001, 0x10060009, 0x10060026, 0x10060027, + 0x140e0028, 0x10060268, 0x1810026d, 0x10000fff, + 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, + 0x10000fff, 0x10000fff, 0x10000fff, 0x69, + 0x3ff0000, 0x57, 0x2e001e, 0x258012c, + 0xa0aa04ec, 0x30, 0x80960019, 0x12c0300, + 0x2019, 0x600, 0x32060019, 0x0, 0x0, 0x400 + } } } }, + + [TV_NORM_HD720P] = { CTV_ENC_MODE, { + .ctv_enc_mode = { + .mode = { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, + 1280, 1349, 1357, 1650, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + .ctv_regs = { 0x1260394, 0x0, 0x0, 0x622, + 0x66b0021, 0x6004a, 0x1210626, 0x8170000, + 0x70004, 0x70016, 0x70017, 0x40f0018, + 0x702e8, 0x81702ed, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x0, + 0x2e40001, 0x58, 0x2e001e, 0x258012c, + 0xa0aa04ec, 0x30, 0x810c0039, 0x12c0300, + 0xc0002039, 0x600, 0x32060039, 0x0, 0x0, 0x0 + } } } }, + + [TV_NORM_HD1080I] = { CTV_ENC_MODE, { + .ctv_enc_mode = { + .mode = { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, + 1920, 1961, 2049, 2200, 0, 1080, 1084, 1088, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC + | DRM_MODE_FLAG_INTERLACE) }, + .ctv_regs = { 0xac0420, 0x44c0478, 0x4a4, 0x4fc0868, + 0x8940028, 0x60054, 0xe80870, 0xbf70000, + 0xbc70004, 0x70005, 0x70012, 0x70013, + 0x40f0014, 0x70230, 0xbf70232, 0xbf70233, + 0x1c70237, 0x70238, 0x70244, 0x70245, + 0x40f0246, 0x70462, 0x1f70464, 0x0, + 0x2e40001, 0x58, 0x2e001e, 0x258012c, + 0xa0aa04ec, 0x30, 0x815f004c, 0x12c0300, + 0xc000204c, 0x600, 0x3206004c, 0x0, 0x0, 0x0 + } } } } +}; + +/* + * The following is some guesswork on how the TV encoder flicker + * filter/rescaler works: + * + * It seems to use some sort of resampling filter, it is controlled + * through the registers at NV_PTV_HFILTER and NV_PTV_VFILTER, they + * control the horizontal and vertical stage respectively, there is + * also NV_PTV_HFILTER2 the blob fills identically to NV_PTV_HFILTER, + * but they seem to do nothing. A rough guess might be that they could + * be used to independently control the filtering of each interlaced + * field, but I don't know how they are enabled. The whole filtering + * process seems to be disabled with bits 26:27 of PTV_200, but we + * aren't doing that. + * + * The layout of both register sets is the same: + * + * A: [BASE+0x18]...[BASE+0x0] [BASE+0x58]..[BASE+0x40] + * B: [BASE+0x34]...[BASE+0x1c] [BASE+0x74]..[BASE+0x5c] + * + * Each coefficient is stored in bits [31],[15:9] in two's complement + * format. They seem to be some kind of weights used in a low-pass + * filter. Both A and B coefficients are applied to the 14 nearest + * samples on each side (Listed from nearest to furthermost. They + * roughly cover 2 framebuffer pixels on each side). They are + * probably multiplied with some more hardwired weights before being + * used: B-coefficients are applied the same on both sides, + * A-coefficients are inverted before being applied to the opposite + * side. + * + * After all the hassle, I got the following formula by empirical + * means... + */ + +#define calc_overscan(o) interpolate(0x100, 0xe1, 0xc1, o) + +#define id1 (1LL << 8) +#define id2 (1LL << 16) +#define id3 (1LL << 24) +#define id4 (1LL << 32) +#define id5 (1LL << 48) + +static struct filter_params{ + int64_t k1; + int64_t ki; + int64_t ki2; + int64_t ki3; + int64_t kr; + int64_t kir; + int64_t ki2r; + int64_t ki3r; + int64_t kf; + int64_t kif; + int64_t ki2f; + int64_t ki3f; + int64_t krf; + int64_t kirf; + int64_t ki2rf; + int64_t ki3rf; +} fparams[2][4] = { + /* Horizontal filter parameters */ + { + {64.311690 * id5, -39.516924 * id5, 6.586143 * id5, 0.000002 * id5, + 0.051285 * id4, 26.168746 * id4, -4.361449 * id4, -0.000001 * id4, + 9.308169 * id3, 78.180965 * id3, -13.030158 * id3, -0.000001 * id3, + -8.801540 * id1, -46.572890 * id1, 7.762145 * id1, -0.000000 * id1}, + {-44.565569 * id5, -68.081246 * id5, 39.812074 * id5, -4.009316 * id5, + 29.832207 * id4, 50.047322 * id4, -25.380017 * id4, 2.546422 * id4, + 104.605622 * id3, 141.908641 * id3, -74.322319 * id3, 7.484316 * id3, + -37.081621 * id1, -90.397510 * id1, 42.784229 * id1, -4.289952 * id1}, + {-56.793244 * id5, 31.153584 * id5, -5.192247 * id5, -0.000003 * id5, + 33.541131 * id4, -34.149302 * id4, 5.691537 * id4, 0.000002 * id4, + 87.196610 * id3, -88.995169 * id3, 14.832456 * id3, 0.000012 * id3, + 17.288138 * id1, 71.864786 * id1, -11.977408 * id1, -0.000009 * id1}, + {51.787796 * id5, 21.211771 * id5, -18.993730 * id5, 1.853310 * id5, + -41.470726 * id4, -17.775823 * id4, 13.057821 * id4, -1.15823 * id4, + -154.235673 * id3, -44.878641 * id3, 40.656077 * id3, -3.695595 * id3, + 112.201065 * id1, 39.992155 * id1, -25.155714 * id1, 2.113984 * id1}, + }, + + /* Vertical filter parameters */ + { + {67.601979 * id5, 0.428319 * id5, -0.071318 * id5, -0.000012 * id5, + -3.402339 * id4, 0.000209 * id4, -0.000092 * id4, 0.000010 * id4, + -9.180996 * id3, 6.111270 * id3, -1.024457 * id3, 0.001043 * id3, + 6.060315 * id1, -0.017425 * id1, 0.007830 * id1, -0.000869 * id1}, + {6.755647 * id5, 5.841348 * id5, 1.469734 * id5, -0.149656 * id5, + 8.293120 * id4, -1.192888 * id4, -0.947652 * id4, 0.094507 * id4, + 37.526655 * id3, 10.257875 * id3, -10.823275 * id3, 1.081497 * id3, + -2.361928 * id1, -2.059432 * id1, 1.840671 * id1, -0.168100 * id1}, + {-14.780391 * id5, -16.042148 * id5, 2.673692 * id5, -0.000000 * id5, + 39.541978 * id4, 5.680053 * id4, -0.946676 * id4, 0.000000 * id4, + 152.994486 * id3, 12.625439 * id3, -2.119579 * id3, 0.002708 * id3, + -38.125089 * id1, -0.855880 * id1, 0.155359 * id1, -0.002245 * id1}, + {-27.476193 * id5, -1.454976 * id5, 1.286557 * id5, 0.025346 * id5, + 20.687300 * id4, 3.014003 * id4, -0.557786 * id4, -0.01311 * id4, + 60.008737 * id3, -0.738273 * id3, 5.408217 * id3, -0.796798 * id3, + -17.296835 * id1, 4.438577 * id1, -2.809420 * id1, 0.385491 * id1}, + } +}; + +static void tv_setup_filter(struct drm_encoder *encoder) +{ + struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); + struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); + struct drm_display_mode *mode = &encoder->crtc->mode; + uint32_t (*filters[])[4][7] = {&tv_enc->state.hfilter, + &tv_enc->state.vfilter}; + int i, j, k; + int32_t overscan = calc_overscan(tv_enc->overscan); + int64_t flicker = (tv_enc->flicker - 50) * (id3 / 100); + uint64_t rs[] = {mode->hdisplay * id3, + mode->vdisplay * id3}; + + do_div(rs[0], overscan * tv_norm->tv_enc_mode.hdisplay); + do_div(rs[1], overscan * tv_norm->tv_enc_mode.vdisplay); + + for (k = 0; k < 2; k++) { + rs[k] = max((int64_t)rs[k], id2); + + for (j = 0; j < 4; j++) { + struct filter_params *p = &fparams[k][j]; + + for (i = 0; i < 7; i++) { + int64_t c = (p->k1 + p->ki*i + p->ki2*i*i + p->ki3*i*i*i) + + (p->kr + p->kir*i + p->ki2r*i*i + p->ki3r*i*i*i)*rs[k] + + (p->kf + p->kif*i + p->ki2f*i*i + p->ki3f*i*i*i)*flicker + + (p->krf + p->kirf*i + p->ki2rf*i*i + p->ki3rf*i*i*i)*flicker*rs[k]; + + (*filters[k])[j][i] = (c + id5/2) >> 39 & (0x1 << 31 | 0x7f << 9); + } + } + } +} + +/* Hardware state saving/restoring */ + +static void tv_save_filter(struct drm_device *dev, uint32_t base, uint32_t regs[4][7]) +{ + int i, j; + uint32_t offsets[] = { base, base + 0x1c, base + 0x40, base + 0x5c }; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 7; j++) + regs[i][j] = nv_read_ptv(dev, offsets[i]+4*j); + } +} + +static void tv_load_filter(struct drm_device *dev, uint32_t base, uint32_t regs[4][7]) +{ + int i, j; + uint32_t offsets[] = { base, base + 0x1c, base + 0x40, base + 0x5c }; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 7; j++) + nv_write_ptv(dev, offsets[i]+4*j, regs[i][j]); + } +} + +void nv17_tv_state_save(struct drm_device *dev, struct nv17_tv_state *state) +{ + int i; + + for (i = 0; i < 0x40; i++) + state->tv_enc[i] = nv_read_tv_enc(dev, i); + + tv_save_filter(dev, NV_PTV_HFILTER, state->hfilter); + tv_save_filter(dev, NV_PTV_HFILTER2, state->hfilter2); + tv_save_filter(dev, NV_PTV_VFILTER, state->vfilter); + + nv_save_ptv(dev, state, 200); + nv_save_ptv(dev, state, 204); + nv_save_ptv(dev, state, 208); + nv_save_ptv(dev, state, 20c); + nv_save_ptv(dev, state, 304); + nv_save_ptv(dev, state, 500); + nv_save_ptv(dev, state, 504); + nv_save_ptv(dev, state, 508); + nv_save_ptv(dev, state, 600); + nv_save_ptv(dev, state, 604); + nv_save_ptv(dev, state, 608); + nv_save_ptv(dev, state, 60c); + nv_save_ptv(dev, state, 610); + nv_save_ptv(dev, state, 614); +} + +void nv17_tv_state_load(struct drm_device *dev, struct nv17_tv_state *state) +{ + int i; + + for (i = 0; i < 0x40; i++) + nv_write_tv_enc(dev, i, state->tv_enc[i]); + + tv_load_filter(dev, NV_PTV_HFILTER, state->hfilter); + tv_load_filter(dev, NV_PTV_HFILTER2, state->hfilter2); + tv_load_filter(dev, NV_PTV_VFILTER, state->vfilter); + + nv_load_ptv(dev, state, 200); + nv_load_ptv(dev, state, 204); + nv_load_ptv(dev, state, 208); + nv_load_ptv(dev, state, 20c); + nv_load_ptv(dev, state, 304); + nv_load_ptv(dev, state, 500); + nv_load_ptv(dev, state, 504); + nv_load_ptv(dev, state, 508); + nv_load_ptv(dev, state, 600); + nv_load_ptv(dev, state, 604); + nv_load_ptv(dev, state, 608); + nv_load_ptv(dev, state, 60c); + nv_load_ptv(dev, state, 610); + nv_load_ptv(dev, state, 614); + + /* This is required for some settings to kick in. */ + nv_write_tv_enc(dev, 0x3e, 1); + nv_write_tv_enc(dev, 0x3e, 0); +} + +/* Timings similar to the ones the blob sets */ + +struct drm_display_mode nv17_tv_modes[] = { + { DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 0, + 320, 344, 392, 560, 0, 200, 200, 202, 220, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC + | DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_CLKDIV2) }, + { DRM_MODE("320x240", DRM_MODE_TYPE_DRIVER, 0, + 320, 344, 392, 560, 0, 240, 240, 246, 263, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC + | DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_CLKDIV2) }, + { DRM_MODE("400x300", DRM_MODE_TYPE_DRIVER, 0, + 400, 432, 496, 640, 0, 300, 300, 303, 314, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC + | DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_CLKDIV2) }, + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 0, + 640, 672, 768, 880, 0, 480, 480, 492, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 0, + 720, 752, 872, 960, 0, 480, 480, 493, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 0, + 720, 776, 856, 960, 0, 576, 576, 588, 597, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 0, + 800, 840, 920, 1040, 0, 600, 600, 604, 618, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 0, + 1024, 1064, 1200, 1344, 0, 768, 768, 777, 806, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + {} +}; + +void nv17_tv_update_properties(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); + struct nv17_tv_state *regs = &tv_enc->state; + struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); + int subconnector = tv_enc->select_subconnector ? + tv_enc->select_subconnector : + tv_enc->subconnector; + + switch (subconnector) { + case DRM_MODE_SUBCONNECTOR_Composite: + { + regs->ptv_204 = 0x2; + + /* The composite connector may be found on either pin. */ + if (tv_enc->pin_mask & 0x4) + regs->ptv_204 |= 0x010000; + else if (tv_enc->pin_mask & 0x2) + regs->ptv_204 |= 0x100000; + else + regs->ptv_204 |= 0x110000; + + regs->tv_enc[0x7] = 0x10; + break; + } + case DRM_MODE_SUBCONNECTOR_SVIDEO: + regs->ptv_204 = 0x11012; + regs->tv_enc[0x7] = 0x18; + break; + + case DRM_MODE_SUBCONNECTOR_Component: + regs->ptv_204 = 0x111333; + regs->tv_enc[0x7] = 0x14; + break; + + case DRM_MODE_SUBCONNECTOR_SCART: + regs->ptv_204 = 0x111012; + regs->tv_enc[0x7] = 0x18; + break; + } + + regs->tv_enc[0x20] = interpolate(0, tv_norm->tv_enc_mode.tv_enc[0x20], 255, + tv_enc->saturation); + regs->tv_enc[0x22] = interpolate(0, tv_norm->tv_enc_mode.tv_enc[0x22], 255, + tv_enc->saturation); + regs->tv_enc[0x25] = tv_enc->hue * 255 / 100; + + nv_load_ptv(dev, regs, 204); + nv_load_tv_enc(dev, regs, 7); + nv_load_tv_enc(dev, regs, 20); + nv_load_tv_enc(dev, regs, 22); + nv_load_tv_enc(dev, regs, 25); +} + +void nv17_tv_update_rescaler(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); + struct nv17_tv_state *regs = &tv_enc->state; + + regs->ptv_208 = 0x40 | (calc_overscan(tv_enc->overscan) << 8); + + tv_setup_filter(encoder); + + nv_load_ptv(dev, regs, 208); + tv_load_filter(dev, NV_PTV_HFILTER, regs->hfilter); + tv_load_filter(dev, NV_PTV_HFILTER2, regs->hfilter2); + tv_load_filter(dev, NV_PTV_VFILTER, regs->vfilter); +} + +void nv17_ctv_update_rescaler(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); + int head = nouveau_crtc(encoder->crtc)->index; + struct nv04_crtc_reg *regs = &dev_priv->mode_reg.crtc_reg[head]; + struct drm_display_mode *crtc_mode = &encoder->crtc->mode; + struct drm_display_mode *output_mode = &get_tv_norm(encoder)->ctv_enc_mode.mode; + int overscan, hmargin, vmargin, hratio, vratio; + + /* The rescaler doesn't do the right thing for interlaced modes. */ + if (output_mode->flags & DRM_MODE_FLAG_INTERLACE) + overscan = 100; + else + overscan = tv_enc->overscan; + + hmargin = (output_mode->hdisplay - crtc_mode->hdisplay) / 2; + vmargin = (output_mode->vdisplay - crtc_mode->vdisplay) / 2; + + hmargin = interpolate(0, min(hmargin, output_mode->hdisplay/20), hmargin, + overscan); + vmargin = interpolate(0, min(vmargin, output_mode->vdisplay/20), vmargin, + overscan); + + hratio = crtc_mode->hdisplay * 0x800 / (output_mode->hdisplay - 2*hmargin); + vratio = crtc_mode->vdisplay * 0x800 / (output_mode->vdisplay - 2*vmargin) & ~3; + + regs->fp_horiz_regs[FP_VALID_START] = hmargin; + regs->fp_horiz_regs[FP_VALID_END] = output_mode->hdisplay - hmargin - 1; + regs->fp_vert_regs[FP_VALID_START] = vmargin; + regs->fp_vert_regs[FP_VALID_END] = output_mode->vdisplay - vmargin - 1; + + regs->fp_debug_1 = NV_PRAMDAC_FP_DEBUG_1_YSCALE_TESTMODE_ENABLE | + XLATE(vratio, 0, NV_PRAMDAC_FP_DEBUG_1_YSCALE_VALUE) | + NV_PRAMDAC_FP_DEBUG_1_XSCALE_TESTMODE_ENABLE | + XLATE(hratio, 0, NV_PRAMDAC_FP_DEBUG_1_XSCALE_VALUE); + + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HVALID_START, + regs->fp_horiz_regs[FP_VALID_START]); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HVALID_END, + regs->fp_horiz_regs[FP_VALID_END]); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_VVALID_START, + regs->fp_vert_regs[FP_VALID_START]); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_VVALID_END, + regs->fp_vert_regs[FP_VALID_END]); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_1, regs->fp_debug_1); +} diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c new file mode 100644 index 0000000000000000000000000000000000000000..18ba74f19703f15100df2da20629b6e0b2523740 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv20_graph.c @@ -0,0 +1,780 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +/* + * NV20 + * ----- + * There are 3 families : + * NV20 is 0x10de:0x020* + * NV25/28 is 0x10de:0x025* / 0x10de:0x028* + * NV2A is 0x10de:0x02A0 + * + * NV30 + * ----- + * There are 3 families : + * NV30/31 is 0x10de:0x030* / 0x10de:0x031* + * NV34 is 0x10de:0x032* + * NV35/36 is 0x10de:0x033* / 0x10de:0x034* + * + * Not seen in the wild, no dumps (probably NV35) : + * NV37 is 0x10de:0x00fc, 0x10de:0x00fd + * NV38 is 0x10de:0x0333, 0x10de:0x00fe + * + */ + +#define NV20_GRCTX_SIZE (3580*4) +#define NV25_GRCTX_SIZE (3529*4) +#define NV2A_GRCTX_SIZE (3500*4) + +#define NV30_31_GRCTX_SIZE (24392) +#define NV34_GRCTX_SIZE (18140) +#define NV35_36_GRCTX_SIZE (22396) + +static void +nv20_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + int i; + + nv_wo32(dev, ctx, 0x033c/4, 0xffff0000); + nv_wo32(dev, ctx, 0x03a0/4, 0x0fff0000); + nv_wo32(dev, ctx, 0x03a4/4, 0x0fff0000); + nv_wo32(dev, ctx, 0x047c/4, 0x00000101); + nv_wo32(dev, ctx, 0x0490/4, 0x00000111); + nv_wo32(dev, ctx, 0x04a8/4, 0x44400000); + for (i = 0x04d4; i <= 0x04e0; i += 4) + nv_wo32(dev, ctx, i/4, 0x00030303); + for (i = 0x04f4; i <= 0x0500; i += 4) + nv_wo32(dev, ctx, i/4, 0x00080000); + for (i = 0x050c; i <= 0x0518; i += 4) + nv_wo32(dev, ctx, i/4, 0x01012000); + for (i = 0x051c; i <= 0x0528; i += 4) + nv_wo32(dev, ctx, i/4, 0x000105b8); + for (i = 0x052c; i <= 0x0538; i += 4) + nv_wo32(dev, ctx, i/4, 0x00080008); + for (i = 0x055c; i <= 0x0598; i += 4) + nv_wo32(dev, ctx, i/4, 0x07ff0000); + nv_wo32(dev, ctx, 0x05a4/4, 0x4b7fffff); + nv_wo32(dev, ctx, 0x05fc/4, 0x00000001); + nv_wo32(dev, ctx, 0x0604/4, 0x00004000); + nv_wo32(dev, ctx, 0x0610/4, 0x00000001); + nv_wo32(dev, ctx, 0x0618/4, 0x00040000); + nv_wo32(dev, ctx, 0x061c/4, 0x00010000); + for (i = 0x1c1c; i <= 0x248c; i += 16) { + nv_wo32(dev, ctx, (i + 0)/4, 0x10700ff9); + nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c); + nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b); + } + nv_wo32(dev, ctx, 0x281c/4, 0x3f800000); + nv_wo32(dev, ctx, 0x2830/4, 0x3f800000); + nv_wo32(dev, ctx, 0x285c/4, 0x40000000); + nv_wo32(dev, ctx, 0x2860/4, 0x3f800000); + nv_wo32(dev, ctx, 0x2864/4, 0x3f000000); + nv_wo32(dev, ctx, 0x286c/4, 0x40000000); + nv_wo32(dev, ctx, 0x2870/4, 0x3f800000); + nv_wo32(dev, ctx, 0x2878/4, 0xbf800000); + nv_wo32(dev, ctx, 0x2880/4, 0xbf800000); + nv_wo32(dev, ctx, 0x34a4/4, 0x000fe000); + nv_wo32(dev, ctx, 0x3530/4, 0x000003f8); + nv_wo32(dev, ctx, 0x3540/4, 0x002fe000); + for (i = 0x355c; i <= 0x3578; i += 4) + nv_wo32(dev, ctx, i/4, 0x001c527c); +} + +static void +nv25_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + int i; + + nv_wo32(dev, ctx, 0x035c/4, 0xffff0000); + nv_wo32(dev, ctx, 0x03c0/4, 0x0fff0000); + nv_wo32(dev, ctx, 0x03c4/4, 0x0fff0000); + nv_wo32(dev, ctx, 0x049c/4, 0x00000101); + nv_wo32(dev, ctx, 0x04b0/4, 0x00000111); + nv_wo32(dev, ctx, 0x04c8/4, 0x00000080); + nv_wo32(dev, ctx, 0x04cc/4, 0xffff0000); + nv_wo32(dev, ctx, 0x04d0/4, 0x00000001); + nv_wo32(dev, ctx, 0x04e4/4, 0x44400000); + nv_wo32(dev, ctx, 0x04fc/4, 0x4b800000); + for (i = 0x0510; i <= 0x051c; i += 4) + nv_wo32(dev, ctx, i/4, 0x00030303); + for (i = 0x0530; i <= 0x053c; i += 4) + nv_wo32(dev, ctx, i/4, 0x00080000); + for (i = 0x0548; i <= 0x0554; i += 4) + nv_wo32(dev, ctx, i/4, 0x01012000); + for (i = 0x0558; i <= 0x0564; i += 4) + nv_wo32(dev, ctx, i/4, 0x000105b8); + for (i = 0x0568; i <= 0x0574; i += 4) + nv_wo32(dev, ctx, i/4, 0x00080008); + for (i = 0x0598; i <= 0x05d4; i += 4) + nv_wo32(dev, ctx, i/4, 0x07ff0000); + nv_wo32(dev, ctx, 0x05e0/4, 0x4b7fffff); + nv_wo32(dev, ctx, 0x0620/4, 0x00000080); + nv_wo32(dev, ctx, 0x0624/4, 0x30201000); + nv_wo32(dev, ctx, 0x0628/4, 0x70605040); + nv_wo32(dev, ctx, 0x062c/4, 0xb0a09080); + nv_wo32(dev, ctx, 0x0630/4, 0xf0e0d0c0); + nv_wo32(dev, ctx, 0x0664/4, 0x00000001); + nv_wo32(dev, ctx, 0x066c/4, 0x00004000); + nv_wo32(dev, ctx, 0x0678/4, 0x00000001); + nv_wo32(dev, ctx, 0x0680/4, 0x00040000); + nv_wo32(dev, ctx, 0x0684/4, 0x00010000); + for (i = 0x1b04; i <= 0x2374; i += 16) { + nv_wo32(dev, ctx, (i + 0)/4, 0x10700ff9); + nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c); + nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b); + } + nv_wo32(dev, ctx, 0x2704/4, 0x3f800000); + nv_wo32(dev, ctx, 0x2718/4, 0x3f800000); + nv_wo32(dev, ctx, 0x2744/4, 0x40000000); + nv_wo32(dev, ctx, 0x2748/4, 0x3f800000); + nv_wo32(dev, ctx, 0x274c/4, 0x3f000000); + nv_wo32(dev, ctx, 0x2754/4, 0x40000000); + nv_wo32(dev, ctx, 0x2758/4, 0x3f800000); + nv_wo32(dev, ctx, 0x2760/4, 0xbf800000); + nv_wo32(dev, ctx, 0x2768/4, 0xbf800000); + nv_wo32(dev, ctx, 0x308c/4, 0x000fe000); + nv_wo32(dev, ctx, 0x3108/4, 0x000003f8); + nv_wo32(dev, ctx, 0x3468/4, 0x002fe000); + for (i = 0x3484; i <= 0x34a0; i += 4) + nv_wo32(dev, ctx, i/4, 0x001c527c); +} + +static void +nv2a_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + int i; + + nv_wo32(dev, ctx, 0x033c/4, 0xffff0000); + nv_wo32(dev, ctx, 0x03a0/4, 0x0fff0000); + nv_wo32(dev, ctx, 0x03a4/4, 0x0fff0000); + nv_wo32(dev, ctx, 0x047c/4, 0x00000101); + nv_wo32(dev, ctx, 0x0490/4, 0x00000111); + nv_wo32(dev, ctx, 0x04a8/4, 0x44400000); + for (i = 0x04d4; i <= 0x04e0; i += 4) + nv_wo32(dev, ctx, i/4, 0x00030303); + for (i = 0x04f4; i <= 0x0500; i += 4) + nv_wo32(dev, ctx, i/4, 0x00080000); + for (i = 0x050c; i <= 0x0518; i += 4) + nv_wo32(dev, ctx, i/4, 0x01012000); + for (i = 0x051c; i <= 0x0528; i += 4) + nv_wo32(dev, ctx, i/4, 0x000105b8); + for (i = 0x052c; i <= 0x0538; i += 4) + nv_wo32(dev, ctx, i/4, 0x00080008); + for (i = 0x055c; i <= 0x0598; i += 4) + nv_wo32(dev, ctx, i/4, 0x07ff0000); + nv_wo32(dev, ctx, 0x05a4/4, 0x4b7fffff); + nv_wo32(dev, ctx, 0x05fc/4, 0x00000001); + nv_wo32(dev, ctx, 0x0604/4, 0x00004000); + nv_wo32(dev, ctx, 0x0610/4, 0x00000001); + nv_wo32(dev, ctx, 0x0618/4, 0x00040000); + nv_wo32(dev, ctx, 0x061c/4, 0x00010000); + for (i = 0x1a9c; i <= 0x22fc; i += 16) { /*XXX: check!! */ + nv_wo32(dev, ctx, (i + 0)/4, 0x10700ff9); + nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c); + nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b); + } + nv_wo32(dev, ctx, 0x269c/4, 0x3f800000); + nv_wo32(dev, ctx, 0x26b0/4, 0x3f800000); + nv_wo32(dev, ctx, 0x26dc/4, 0x40000000); + nv_wo32(dev, ctx, 0x26e0/4, 0x3f800000); + nv_wo32(dev, ctx, 0x26e4/4, 0x3f000000); + nv_wo32(dev, ctx, 0x26ec/4, 0x40000000); + nv_wo32(dev, ctx, 0x26f0/4, 0x3f800000); + nv_wo32(dev, ctx, 0x26f8/4, 0xbf800000); + nv_wo32(dev, ctx, 0x2700/4, 0xbf800000); + nv_wo32(dev, ctx, 0x3024/4, 0x000fe000); + nv_wo32(dev, ctx, 0x30a0/4, 0x000003f8); + nv_wo32(dev, ctx, 0x33fc/4, 0x002fe000); + for (i = 0x341c; i <= 0x3438; i += 4) + nv_wo32(dev, ctx, i/4, 0x001c527c); +} + +static void +nv30_31_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + int i; + + nv_wo32(dev, ctx, 0x0410/4, 0x00000101); + nv_wo32(dev, ctx, 0x0424/4, 0x00000111); + nv_wo32(dev, ctx, 0x0428/4, 0x00000060); + nv_wo32(dev, ctx, 0x0444/4, 0x00000080); + nv_wo32(dev, ctx, 0x0448/4, 0xffff0000); + nv_wo32(dev, ctx, 0x044c/4, 0x00000001); + nv_wo32(dev, ctx, 0x0460/4, 0x44400000); + nv_wo32(dev, ctx, 0x048c/4, 0xffff0000); + for (i = 0x04e0; i < 0x04e8; i += 4) + nv_wo32(dev, ctx, i/4, 0x0fff0000); + nv_wo32(dev, ctx, 0x04ec/4, 0x00011100); + for (i = 0x0508; i < 0x0548; i += 4) + nv_wo32(dev, ctx, i/4, 0x07ff0000); + nv_wo32(dev, ctx, 0x0550/4, 0x4b7fffff); + nv_wo32(dev, ctx, 0x058c/4, 0x00000080); + nv_wo32(dev, ctx, 0x0590/4, 0x30201000); + nv_wo32(dev, ctx, 0x0594/4, 0x70605040); + nv_wo32(dev, ctx, 0x0598/4, 0xb8a89888); + nv_wo32(dev, ctx, 0x059c/4, 0xf8e8d8c8); + nv_wo32(dev, ctx, 0x05b0/4, 0xb0000000); + for (i = 0x0600; i < 0x0640; i += 4) + nv_wo32(dev, ctx, i/4, 0x00010588); + for (i = 0x0640; i < 0x0680; i += 4) + nv_wo32(dev, ctx, i/4, 0x00030303); + for (i = 0x06c0; i < 0x0700; i += 4) + nv_wo32(dev, ctx, i/4, 0x0008aae4); + for (i = 0x0700; i < 0x0740; i += 4) + nv_wo32(dev, ctx, i/4, 0x01012000); + for (i = 0x0740; i < 0x0780; i += 4) + nv_wo32(dev, ctx, i/4, 0x00080008); + nv_wo32(dev, ctx, 0x085c/4, 0x00040000); + nv_wo32(dev, ctx, 0x0860/4, 0x00010000); + for (i = 0x0864; i < 0x0874; i += 4) + nv_wo32(dev, ctx, i/4, 0x00040004); + for (i = 0x1f18; i <= 0x3088 ; i += 16) { + nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9); + nv_wo32(dev, ctx, i/4 + 1, 0x0436086c); + nv_wo32(dev, ctx, i/4 + 2, 0x000c001b); + } + for (i = 0x30b8; i < 0x30c8; i += 4) + nv_wo32(dev, ctx, i/4, 0x0000ffff); + nv_wo32(dev, ctx, 0x344c/4, 0x3f800000); + nv_wo32(dev, ctx, 0x3808/4, 0x3f800000); + nv_wo32(dev, ctx, 0x381c/4, 0x3f800000); + nv_wo32(dev, ctx, 0x3848/4, 0x40000000); + nv_wo32(dev, ctx, 0x384c/4, 0x3f800000); + nv_wo32(dev, ctx, 0x3850/4, 0x3f000000); + nv_wo32(dev, ctx, 0x3858/4, 0x40000000); + nv_wo32(dev, ctx, 0x385c/4, 0x3f800000); + nv_wo32(dev, ctx, 0x3864/4, 0xbf800000); + nv_wo32(dev, ctx, 0x386c/4, 0xbf800000); +} + +static void +nv34_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + int i; + + nv_wo32(dev, ctx, 0x040c/4, 0x01000101); + nv_wo32(dev, ctx, 0x0420/4, 0x00000111); + nv_wo32(dev, ctx, 0x0424/4, 0x00000060); + nv_wo32(dev, ctx, 0x0440/4, 0x00000080); + nv_wo32(dev, ctx, 0x0444/4, 0xffff0000); + nv_wo32(dev, ctx, 0x0448/4, 0x00000001); + nv_wo32(dev, ctx, 0x045c/4, 0x44400000); + nv_wo32(dev, ctx, 0x0480/4, 0xffff0000); + for (i = 0x04d4; i < 0x04dc; i += 4) + nv_wo32(dev, ctx, i/4, 0x0fff0000); + nv_wo32(dev, ctx, 0x04e0/4, 0x00011100); + for (i = 0x04fc; i < 0x053c; i += 4) + nv_wo32(dev, ctx, i/4, 0x07ff0000); + nv_wo32(dev, ctx, 0x0544/4, 0x4b7fffff); + nv_wo32(dev, ctx, 0x057c/4, 0x00000080); + nv_wo32(dev, ctx, 0x0580/4, 0x30201000); + nv_wo32(dev, ctx, 0x0584/4, 0x70605040); + nv_wo32(dev, ctx, 0x0588/4, 0xb8a89888); + nv_wo32(dev, ctx, 0x058c/4, 0xf8e8d8c8); + nv_wo32(dev, ctx, 0x05a0/4, 0xb0000000); + for (i = 0x05f0; i < 0x0630; i += 4) + nv_wo32(dev, ctx, i/4, 0x00010588); + for (i = 0x0630; i < 0x0670; i += 4) + nv_wo32(dev, ctx, i/4, 0x00030303); + for (i = 0x06b0; i < 0x06f0; i += 4) + nv_wo32(dev, ctx, i/4, 0x0008aae4); + for (i = 0x06f0; i < 0x0730; i += 4) + nv_wo32(dev, ctx, i/4, 0x01012000); + for (i = 0x0730; i < 0x0770; i += 4) + nv_wo32(dev, ctx, i/4, 0x00080008); + nv_wo32(dev, ctx, 0x0850/4, 0x00040000); + nv_wo32(dev, ctx, 0x0854/4, 0x00010000); + for (i = 0x0858; i < 0x0868; i += 4) + nv_wo32(dev, ctx, i/4, 0x00040004); + for (i = 0x15ac; i <= 0x271c ; i += 16) { + nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9); + nv_wo32(dev, ctx, i/4 + 1, 0x0436086c); + nv_wo32(dev, ctx, i/4 + 2, 0x000c001b); + } + for (i = 0x274c; i < 0x275c; i += 4) + nv_wo32(dev, ctx, i/4, 0x0000ffff); + nv_wo32(dev, ctx, 0x2ae0/4, 0x3f800000); + nv_wo32(dev, ctx, 0x2e9c/4, 0x3f800000); + nv_wo32(dev, ctx, 0x2eb0/4, 0x3f800000); + nv_wo32(dev, ctx, 0x2edc/4, 0x40000000); + nv_wo32(dev, ctx, 0x2ee0/4, 0x3f800000); + nv_wo32(dev, ctx, 0x2ee4/4, 0x3f000000); + nv_wo32(dev, ctx, 0x2eec/4, 0x40000000); + nv_wo32(dev, ctx, 0x2ef0/4, 0x3f800000); + nv_wo32(dev, ctx, 0x2ef8/4, 0xbf800000); + nv_wo32(dev, ctx, 0x2f00/4, 0xbf800000); +} + +static void +nv35_36_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + int i; + + nv_wo32(dev, ctx, 0x040c/4, 0x00000101); + nv_wo32(dev, ctx, 0x0420/4, 0x00000111); + nv_wo32(dev, ctx, 0x0424/4, 0x00000060); + nv_wo32(dev, ctx, 0x0440/4, 0x00000080); + nv_wo32(dev, ctx, 0x0444/4, 0xffff0000); + nv_wo32(dev, ctx, 0x0448/4, 0x00000001); + nv_wo32(dev, ctx, 0x045c/4, 0x44400000); + nv_wo32(dev, ctx, 0x0488/4, 0xffff0000); + for (i = 0x04dc; i < 0x04e4; i += 4) + nv_wo32(dev, ctx, i/4, 0x0fff0000); + nv_wo32(dev, ctx, 0x04e8/4, 0x00011100); + for (i = 0x0504; i < 0x0544; i += 4) + nv_wo32(dev, ctx, i/4, 0x07ff0000); + nv_wo32(dev, ctx, 0x054c/4, 0x4b7fffff); + nv_wo32(dev, ctx, 0x0588/4, 0x00000080); + nv_wo32(dev, ctx, 0x058c/4, 0x30201000); + nv_wo32(dev, ctx, 0x0590/4, 0x70605040); + nv_wo32(dev, ctx, 0x0594/4, 0xb8a89888); + nv_wo32(dev, ctx, 0x0598/4, 0xf8e8d8c8); + nv_wo32(dev, ctx, 0x05ac/4, 0xb0000000); + for (i = 0x0604; i < 0x0644; i += 4) + nv_wo32(dev, ctx, i/4, 0x00010588); + for (i = 0x0644; i < 0x0684; i += 4) + nv_wo32(dev, ctx, i/4, 0x00030303); + for (i = 0x06c4; i < 0x0704; i += 4) + nv_wo32(dev, ctx, i/4, 0x0008aae4); + for (i = 0x0704; i < 0x0744; i += 4) + nv_wo32(dev, ctx, i/4, 0x01012000); + for (i = 0x0744; i < 0x0784; i += 4) + nv_wo32(dev, ctx, i/4, 0x00080008); + nv_wo32(dev, ctx, 0x0860/4, 0x00040000); + nv_wo32(dev, ctx, 0x0864/4, 0x00010000); + for (i = 0x0868; i < 0x0878; i += 4) + nv_wo32(dev, ctx, i/4, 0x00040004); + for (i = 0x1f1c; i <= 0x308c ; i += 16) { + nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9); + nv_wo32(dev, ctx, i/4 + 1, 0x0436086c); + nv_wo32(dev, ctx, i/4 + 2, 0x000c001b); + } + for (i = 0x30bc; i < 0x30cc; i += 4) + nv_wo32(dev, ctx, i/4, 0x0000ffff); + nv_wo32(dev, ctx, 0x3450/4, 0x3f800000); + nv_wo32(dev, ctx, 0x380c/4, 0x3f800000); + nv_wo32(dev, ctx, 0x3820/4, 0x3f800000); + nv_wo32(dev, ctx, 0x384c/4, 0x40000000); + nv_wo32(dev, ctx, 0x3850/4, 0x3f800000); + nv_wo32(dev, ctx, 0x3854/4, 0x3f000000); + nv_wo32(dev, ctx, 0x385c/4, 0x40000000); + nv_wo32(dev, ctx, 0x3860/4, 0x3f800000); + nv_wo32(dev, ctx, 0x3868/4, 0xbf800000); + nv_wo32(dev, ctx, 0x3870/4, 0xbf800000); +} + +int +nv20_graph_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *); + unsigned int ctx_size; + unsigned int idoffs = 0x28/4; + int ret; + + switch (dev_priv->chipset) { + case 0x20: + ctx_size = NV20_GRCTX_SIZE; + ctx_init = nv20_graph_context_init; + idoffs = 0; + break; + case 0x25: + case 0x28: + ctx_size = NV25_GRCTX_SIZE; + ctx_init = nv25_graph_context_init; + break; + case 0x2a: + ctx_size = NV2A_GRCTX_SIZE; + ctx_init = nv2a_graph_context_init; + idoffs = 0; + break; + case 0x30: + case 0x31: + ctx_size = NV30_31_GRCTX_SIZE; + ctx_init = nv30_31_graph_context_init; + break; + case 0x34: + ctx_size = NV34_GRCTX_SIZE; + ctx_init = nv34_graph_context_init; + break; + case 0x35: + case 0x36: + ctx_size = NV35_36_GRCTX_SIZE; + ctx_init = nv35_36_graph_context_init; + break; + default: + ctx_size = 0; + ctx_init = nv35_36_graph_context_init; + NV_ERROR(dev, "Please contact the devs if you want your NV%x" + " card to work\n", dev_priv->chipset); + return -ENOSYS; + break; + } + + ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16, + NVOBJ_FLAG_ZERO_ALLOC, + &chan->ramin_grctx); + if (ret) + return ret; + + /* Initialise default context values */ + dev_priv->engine.instmem.prepare_access(dev, true); + ctx_init(dev, chan->ramin_grctx->gpuobj); + + /* nv20: nv_wo32(dev, chan->ramin_grctx->gpuobj, 10, chan->id<<24); */ + nv_wo32(dev, chan->ramin_grctx->gpuobj, idoffs, + (chan->id << 24) | 0x1); /* CTX_USER */ + + nv_wo32(dev, dev_priv->ctx_table->gpuobj, chan->id, + chan->ramin_grctx->instance >> 4); + + dev_priv->engine.instmem.finish_access(dev); + return 0; +} + +void +nv20_graph_destroy_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (chan->ramin_grctx) + nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); + + dev_priv->engine.instmem.prepare_access(dev, true); + nv_wo32(dev, dev_priv->ctx_table->gpuobj, chan->id, 0); + dev_priv->engine.instmem.finish_access(dev); +} + +int +nv20_graph_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + uint32_t inst; + + if (!chan->ramin_grctx) + return -EINVAL; + inst = chan->ramin_grctx->instance >> 4; + + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER, + NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD); + nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100); + + nouveau_wait_for_idle(dev); + return 0; +} + +int +nv20_graph_unload_context(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + struct nouveau_channel *chan; + uint32_t inst, tmp; + + chan = pgraph->channel(dev); + if (!chan) + return 0; + inst = chan->ramin_grctx->instance >> 4; + + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER, + NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE); + + nouveau_wait_for_idle(dev); + + nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000); + tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; + tmp |= (pfifo->channels - 1) << 24; + nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp); + return 0; +} + +static void +nv20_graph_rdi(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i, writecount = 32; + uint32_t rdi_index = 0x2c80000; + + if (dev_priv->chipset == 0x20) { + rdi_index = 0x3d0000; + writecount = 15; + } + + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, rdi_index); + for (i = 0; i < writecount; i++) + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, 0); + + nouveau_wait_for_idle(dev); +} + +int +nv20_graph_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = + (struct drm_nouveau_private *)dev->dev_private; + uint32_t tmp, vramsz; + int ret, i; + + nv_wr32(dev, NV03_PMC_ENABLE, + nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); + nv_wr32(dev, NV03_PMC_ENABLE, + nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); + + if (!dev_priv->ctx_table) { + /* Create Context Pointer Table */ + dev_priv->ctx_table_size = 32 * 4; + ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, + dev_priv->ctx_table_size, 16, + NVOBJ_FLAG_ZERO_ALLOC, + &dev_priv->ctx_table); + if (ret) + return ret; + } + + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, + dev_priv->ctx_table->instance >> 4); + + nv20_graph_rdi(dev); + + nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + + nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000); + nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x00118700); + nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xF3CE0475); /* 0x4 = auto ctx switch */ + nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000); + nv_wr32(dev, 0x40009C , 0x00000040); + + if (dev_priv->chipset >= 0x25) { + nv_wr32(dev, 0x400890, 0x00080000); + nv_wr32(dev, 0x400610, 0x304B1FB6); + nv_wr32(dev, 0x400B80, 0x18B82880); + nv_wr32(dev, 0x400B84, 0x44000000); + nv_wr32(dev, 0x400098, 0x40000080); + nv_wr32(dev, 0x400B88, 0x000000ff); + } else { + nv_wr32(dev, 0x400880, 0x00080000); /* 0x0008c7df */ + nv_wr32(dev, 0x400094, 0x00000005); + nv_wr32(dev, 0x400B80, 0x45CAA208); /* 0x45eae20e */ + nv_wr32(dev, 0x400B84, 0x24000000); + nv_wr32(dev, 0x400098, 0x00000040); + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00038); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030); + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E10038); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030); + } + + /* copy tile info from PFB */ + for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { + nv_wr32(dev, 0x00400904 + i * 0x10, + nv_rd32(dev, NV10_PFB_TLIMIT(i))); + /* which is NV40_PGRAPH_TLIMIT0(i) ?? */ + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + i * 4); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, + nv_rd32(dev, NV10_PFB_TLIMIT(i))); + nv_wr32(dev, 0x00400908 + i * 0x10, + nv_rd32(dev, NV10_PFB_TSIZE(i))); + /* which is NV40_PGRAPH_TSIZE0(i) ?? */ + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + i * 4); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, + nv_rd32(dev, NV10_PFB_TSIZE(i))); + nv_wr32(dev, 0x00400900 + i * 0x10, + nv_rd32(dev, NV10_PFB_TILE(i))); + /* which is NV40_PGRAPH_TILE0(i) ?? */ + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + i * 4); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, + nv_rd32(dev, NV10_PFB_TILE(i))); + } + for (i = 0; i < 8; i++) { + nv_wr32(dev, 0x400980 + i * 4, nv_rd32(dev, 0x100300 + i * 4)); + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0090 + i * 4); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, + nv_rd32(dev, 0x100300 + i * 4)); + } + nv_wr32(dev, 0x4009a0, nv_rd32(dev, 0x100324)); + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA000C); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, nv_rd32(dev, 0x100324)); + + nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); + nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); + + tmp = nv_rd32(dev, NV10_PGRAPH_SURFACE) & 0x0007ff00; + nv_wr32(dev, NV10_PGRAPH_SURFACE, tmp); + tmp = nv_rd32(dev, NV10_PGRAPH_SURFACE) | 0x00020100; + nv_wr32(dev, NV10_PGRAPH_SURFACE, tmp); + + /* begin RAM config */ + vramsz = drm_get_resource_len(dev, 0) - 1; + nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); + nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA , nv_rd32(dev, NV04_PFB_CFG0)); + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA , nv_rd32(dev, NV04_PFB_CFG1)); + nv_wr32(dev, 0x400820, 0); + nv_wr32(dev, 0x400824, 0); + nv_wr32(dev, 0x400864, vramsz - 1); + nv_wr32(dev, 0x400868, vramsz - 1); + + /* interesting.. the below overwrites some of the tile setup above.. */ + nv_wr32(dev, 0x400B20, 0x00000000); + nv_wr32(dev, 0x400B04, 0xFFFFFFFF); + + nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_XMIN, 0); + nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_YMIN, 0); + nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff); + nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff); + + return 0; +} + +void +nv20_graph_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nouveau_gpuobj_ref_del(dev, &dev_priv->ctx_table); +} + +int +nv30_graph_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret, i; + + nv_wr32(dev, NV03_PMC_ENABLE, + nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); + nv_wr32(dev, NV03_PMC_ENABLE, + nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); + + if (!dev_priv->ctx_table) { + /* Create Context Pointer Table */ + dev_priv->ctx_table_size = 32 * 4; + ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, + dev_priv->ctx_table_size, 16, + NVOBJ_FLAG_ZERO_ALLOC, + &dev_priv->ctx_table); + if (ret) + return ret; + } + + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, + dev_priv->ctx_table->instance >> 4); + + nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + + nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000); + nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x401287c0); + nv_wr32(dev, 0x400890, 0x01b463ff); + nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xf2de0475); + nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00008000); + nv_wr32(dev, NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04bdff6); + nv_wr32(dev, 0x400B80, 0x1003d888); + nv_wr32(dev, 0x400B84, 0x0c000000); + nv_wr32(dev, 0x400098, 0x00000000); + nv_wr32(dev, 0x40009C, 0x0005ad00); + nv_wr32(dev, 0x400B88, 0x62ff00ff); /* suspiciously like PGRAPH_DEBUG_2 */ + nv_wr32(dev, 0x4000a0, 0x00000000); + nv_wr32(dev, 0x4000a4, 0x00000008); + nv_wr32(dev, 0x4008a8, 0xb784a400); + nv_wr32(dev, 0x400ba0, 0x002f8685); + nv_wr32(dev, 0x400ba4, 0x00231f3f); + nv_wr32(dev, 0x4008a4, 0x40000020); + + if (dev_priv->chipset == 0x34) { + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00200201); + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0008); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000008); + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000032); + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00004); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000002); + } + + nv_wr32(dev, 0x4000c0, 0x00000016); + + /* copy tile info from PFB */ + for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { + nv_wr32(dev, 0x00400904 + i * 0x10, + nv_rd32(dev, NV10_PFB_TLIMIT(i))); + /* which is NV40_PGRAPH_TLIMIT0(i) ?? */ + nv_wr32(dev, 0x00400908 + i * 0x10, + nv_rd32(dev, NV10_PFB_TSIZE(i))); + /* which is NV40_PGRAPH_TSIZE0(i) ?? */ + nv_wr32(dev, 0x00400900 + i * 0x10, + nv_rd32(dev, NV10_PFB_TILE(i))); + /* which is NV40_PGRAPH_TILE0(i) ?? */ + } + + nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); + nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); + nv_wr32(dev, 0x0040075c , 0x00000001); + + /* begin RAM config */ + /* vramsz = drm_get_resource_len(dev, 0) - 1; */ + nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); + nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); + if (dev_priv->chipset != 0x34) { + nv_wr32(dev, 0x400750, 0x00EA0000); + nv_wr32(dev, 0x400754, nv_rd32(dev, NV04_PFB_CFG0)); + nv_wr32(dev, 0x400750, 0x00EA0004); + nv_wr32(dev, 0x400754, nv_rd32(dev, NV04_PFB_CFG1)); + } + + return 0; +} + +struct nouveau_pgraph_object_class nv20_graph_grclass[] = { + { 0x0030, false, NULL }, /* null */ + { 0x0039, false, NULL }, /* m2mf */ + { 0x004a, false, NULL }, /* gdirect */ + { 0x009f, false, NULL }, /* imageblit (nv12) */ + { 0x008a, false, NULL }, /* ifc */ + { 0x0089, false, NULL }, /* sifm */ + { 0x0062, false, NULL }, /* surf2d */ + { 0x0043, false, NULL }, /* rop */ + { 0x0012, false, NULL }, /* beta1 */ + { 0x0072, false, NULL }, /* beta4 */ + { 0x0019, false, NULL }, /* cliprect */ + { 0x0044, false, NULL }, /* pattern */ + { 0x009e, false, NULL }, /* swzsurf */ + { 0x0096, false, NULL }, /* celcius */ + { 0x0097, false, NULL }, /* kelvin (nv20) */ + { 0x0597, false, NULL }, /* kelvin (nv25) */ + {} +}; + +struct nouveau_pgraph_object_class nv30_graph_grclass[] = { + { 0x0030, false, NULL }, /* null */ + { 0x0039, false, NULL }, /* m2mf */ + { 0x004a, false, NULL }, /* gdirect */ + { 0x009f, false, NULL }, /* imageblit (nv12) */ + { 0x008a, false, NULL }, /* ifc */ + { 0x038a, false, NULL }, /* ifc (nv30) */ + { 0x0089, false, NULL }, /* sifm */ + { 0x0389, false, NULL }, /* sifm (nv30) */ + { 0x0062, false, NULL }, /* surf2d */ + { 0x0362, false, NULL }, /* surf2d (nv30) */ + { 0x0043, false, NULL }, /* rop */ + { 0x0012, false, NULL }, /* beta1 */ + { 0x0072, false, NULL }, /* beta4 */ + { 0x0019, false, NULL }, /* cliprect */ + { 0x0044, false, NULL }, /* pattern */ + { 0x039e, false, NULL }, /* swzsurf */ + { 0x0397, false, NULL }, /* rankine (nv30) */ + { 0x0497, false, NULL }, /* rankine (nv35) */ + { 0x0697, false, NULL }, /* rankine (nv34) */ + {} +}; + diff --git a/drivers/gpu/drm/nouveau/nv40_fb.c b/drivers/gpu/drm/nouveau/nv40_fb.c new file mode 100644 index 0000000000000000000000000000000000000000..ca1d27107a8e4a5a2c097b26aa4882aebfd0b841 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv40_fb.c @@ -0,0 +1,62 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv40_fb_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t fb_bar_size, tmp; + int num_tiles; + int i; + + /* This is strictly a NV4x register (don't know about NV5x). */ + /* The blob sets these to all kinds of values, and they mess up our setup. */ + /* I got value 0x52802 instead. For some cards the blob even sets it back to 0x1. */ + /* Note: the blob doesn't read this value, so i'm pretty sure this is safe for all cards. */ + /* Any idea what this is? */ + nv_wr32(dev, NV40_PFB_UNK_800, 0x1); + + switch (dev_priv->chipset) { + case 0x40: + case 0x45: + tmp = nv_rd32(dev, NV10_PFB_CLOSE_PAGE2); + nv_wr32(dev, NV10_PFB_CLOSE_PAGE2, tmp & ~(1 << 15)); + num_tiles = NV10_PFB_TILE__SIZE; + break; + case 0x46: /* G72 */ + case 0x47: /* G70 */ + case 0x49: /* G71 */ + case 0x4b: /* G73 */ + case 0x4c: /* C51 (G7X version) */ + num_tiles = NV40_PFB_TILE__SIZE_1; + break; + default: + num_tiles = NV40_PFB_TILE__SIZE_0; + break; + } + + fb_bar_size = drm_get_resource_len(dev, 0) - 1; + switch (dev_priv->chipset) { + case 0x40: + for (i = 0; i < num_tiles; i++) { + nv_wr32(dev, NV10_PFB_TILE(i), 0); + nv_wr32(dev, NV10_PFB_TLIMIT(i), fb_bar_size); + } + break; + default: + for (i = 0; i < num_tiles; i++) { + nv_wr32(dev, NV40_PFB_TILE(i), 0); + nv_wr32(dev, NV40_PFB_TLIMIT(i), fb_bar_size); + } + break; + } + + return 0; +} + +void +nv40_fb_takedown(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/nv40_fifo.c b/drivers/gpu/drm/nouveau/nv40_fifo.c new file mode 100644 index 0000000000000000000000000000000000000000..b4f19ccb8b41a2c9f96f460b734aa2971bdd9ca8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv40_fifo.c @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +#define NV40_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV40_RAMFC__SIZE)) +#define NV40_RAMFC__SIZE 128 + +int +nv40_fifo_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t fc = NV40_RAMFC(chan->id); + int ret; + + ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(chan->id), ~0, + NV40_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, NULL, &chan->ramfc); + if (ret) + return ret; + + dev_priv->engine.instmem.prepare_access(dev, true); + nv_wi32(dev, fc + 0, chan->pushbuf_base); + nv_wi32(dev, fc + 4, chan->pushbuf_base); + nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4); + nv_wi32(dev, fc + 24, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + 0x30000000 /* no idea.. */); + nv_wi32(dev, fc + 56, chan->ramin_grctx->instance >> 4); + nv_wi32(dev, fc + 60, 0x0001FFFF); + dev_priv->engine.instmem.finish_access(dev); + + /* enable the fifo dma operation */ + nv_wr32(dev, NV04_PFIFO_MODE, + nv_rd32(dev, NV04_PFIFO_MODE) | (1 << chan->id)); + return 0; +} + +void +nv40_fifo_destroy_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + + nv_wr32(dev, NV04_PFIFO_MODE, + nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); + + if (chan->ramfc) + nouveau_gpuobj_ref_del(dev, &chan->ramfc); +} + +static void +nv40_fifo_do_load_context(struct drm_device *dev, int chid) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t fc = NV40_RAMFC(chid), tmp, tmp2; + + dev_priv->engine.instmem.prepare_access(dev, false); + + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0)); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4)); + nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8)); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE, nv_ri32(dev, fc + 12)); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT, nv_ri32(dev, fc + 16)); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, nv_ri32(dev, fc + 20)); + + /* No idea what 0x2058 is.. */ + tmp = nv_ri32(dev, fc + 24); + tmp2 = nv_rd32(dev, 0x2058) & 0xFFF; + tmp2 |= (tmp & 0x30000000); + nv_wr32(dev, 0x2058, tmp2); + tmp &= ~0x30000000; + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_FETCH, tmp); + + nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 28)); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 32)); + nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_VALUE, nv_ri32(dev, fc + 36)); + tmp = nv_ri32(dev, fc + 40); + nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP, tmp); + nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT, nv_ri32(dev, fc + 44)); + nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, nv_ri32(dev, fc + 48)); + nv_wr32(dev, NV10_PFIFO_CACHE1_DMA_SUBROUTINE, nv_ri32(dev, fc + 52)); + nv_wr32(dev, NV40_PFIFO_GRCTX_INSTANCE, nv_ri32(dev, fc + 56)); + + /* Don't clobber the TIMEOUT_ENABLED flag when restoring from RAMFC */ + tmp = nv_rd32(dev, NV04_PFIFO_DMA_TIMESLICE) & ~0x1FFFF; + tmp |= nv_ri32(dev, fc + 60) & 0x1FFFF; + nv_wr32(dev, NV04_PFIFO_DMA_TIMESLICE, tmp); + + nv_wr32(dev, 0x32e4, nv_ri32(dev, fc + 64)); + /* NVIDIA does this next line twice... */ + nv_wr32(dev, 0x32e8, nv_ri32(dev, fc + 68)); + nv_wr32(dev, 0x2088, nv_ri32(dev, fc + 76)); + nv_wr32(dev, 0x3300, nv_ri32(dev, fc + 80)); + + dev_priv->engine.instmem.finish_access(dev); + + nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); +} + +int +nv40_fifo_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + uint32_t tmp; + + nv40_fifo_do_load_context(dev, chan->id); + + /* Set channel active, and in DMA mode */ + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, + NV40_PFIFO_CACHE1_PUSH1_DMA | chan->id); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 1); + + /* Reset DMA_CTL_AT_INFO to INVALID */ + tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_CTL) & ~(1 << 31); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_CTL, tmp); + + return 0; +} + +int +nv40_fifo_unload_context(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + uint32_t fc, tmp; + int chid; + + chid = pfifo->channel_id(dev); + if (chid < 0 || chid >= dev_priv->engine.fifo.channels) + return 0; + fc = NV40_RAMFC(chid); + + dev_priv->engine.instmem.prepare_access(dev, true); + nv_wi32(dev, fc + 0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); + nv_wi32(dev, fc + 4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); + nv_wi32(dev, fc + 8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT)); + nv_wi32(dev, fc + 12, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE)); + nv_wi32(dev, fc + 16, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT)); + nv_wi32(dev, fc + 20, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_STATE)); + tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH); + tmp |= nv_rd32(dev, 0x2058) & 0x30000000; + nv_wi32(dev, fc + 24, tmp); + nv_wi32(dev, fc + 28, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE)); + nv_wi32(dev, fc + 32, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1)); + nv_wi32(dev, fc + 36, nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_VALUE)); + tmp = nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP); + nv_wi32(dev, fc + 40, tmp); + nv_wi32(dev, fc + 44, nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT)); + nv_wi32(dev, fc + 48, nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE)); + /* NVIDIA read 0x3228 first, then write DMA_GET here.. maybe something + * more involved depending on the value of 0x3228? + */ + nv_wi32(dev, fc + 52, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); + nv_wi32(dev, fc + 56, nv_rd32(dev, NV40_PFIFO_GRCTX_INSTANCE)); + nv_wi32(dev, fc + 60, nv_rd32(dev, NV04_PFIFO_DMA_TIMESLICE) & 0x1ffff); + /* No idea what the below is for exactly, ripped from a mmio-trace */ + nv_wi32(dev, fc + 64, nv_rd32(dev, NV40_PFIFO_UNK32E4)); + /* NVIDIA do this next line twice.. bug? */ + nv_wi32(dev, fc + 68, nv_rd32(dev, 0x32e8)); + nv_wi32(dev, fc + 76, nv_rd32(dev, 0x2088)); + nv_wi32(dev, fc + 80, nv_rd32(dev, 0x3300)); +#if 0 /* no real idea which is PUT/GET in UNK_48.. */ + tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_GET); + tmp |= (nv_rd32(dev, NV04_PFIFO_CACHE1_PUT) << 16); + nv_wi32(dev, fc + 72, tmp); +#endif + dev_priv->engine.instmem.finish_access(dev); + + nv40_fifo_do_load_context(dev, pfifo->channels - 1); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, + NV40_PFIFO_CACHE1_PUSH1_DMA | (pfifo->channels - 1)); + return 0; +} + +static void +nv40_fifo_init_reset(struct drm_device *dev) +{ + int i; + + nv_wr32(dev, NV03_PMC_ENABLE, + nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PFIFO); + nv_wr32(dev, NV03_PMC_ENABLE, + nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PFIFO); + + nv_wr32(dev, 0x003224, 0x000f0078); + nv_wr32(dev, 0x003210, 0x00000000); + nv_wr32(dev, 0x003270, 0x00000000); + nv_wr32(dev, 0x003240, 0x00000000); + nv_wr32(dev, 0x003244, 0x00000000); + nv_wr32(dev, 0x003258, 0x00000000); + nv_wr32(dev, 0x002504, 0x00000000); + for (i = 0; i < 16; i++) + nv_wr32(dev, 0x002510 + (i * 4), 0x00000000); + nv_wr32(dev, 0x00250c, 0x0000ffff); + nv_wr32(dev, 0x002048, 0x00000000); + nv_wr32(dev, 0x003228, 0x00000000); + nv_wr32(dev, 0x0032e8, 0x00000000); + nv_wr32(dev, 0x002410, 0x00000000); + nv_wr32(dev, 0x002420, 0x00000000); + nv_wr32(dev, 0x002058, 0x00000001); + nv_wr32(dev, 0x00221c, 0x00000000); + /* something with 0x2084, read/modify/write, no change */ + nv_wr32(dev, 0x002040, 0x000000ff); + nv_wr32(dev, 0x002500, 0x00000000); + nv_wr32(dev, 0x003200, 0x00000000); + + nv_wr32(dev, NV04_PFIFO_DMA_TIMESLICE, 0x2101ffff); +} + +static void +nv40_fifo_init_ramxx(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((dev_priv->ramht_bits - 9) << 16) | + (dev_priv->ramht_offset >> 8)); + nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8); + + switch (dev_priv->chipset) { + case 0x47: + case 0x49: + case 0x4b: + nv_wr32(dev, 0x2230, 1); + break; + default: + break; + } + + switch (dev_priv->chipset) { + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x45: + case 0x47: + case 0x48: + case 0x49: + case 0x4b: + nv_wr32(dev, NV40_PFIFO_RAMFC, 0x30002); + break; + default: + nv_wr32(dev, 0x2230, 0); + nv_wr32(dev, NV40_PFIFO_RAMFC, + ((nouveau_mem_fb_amount(dev) - 512 * 1024 + + dev_priv->ramfc_offset) >> 16) | (3 << 16)); + break; + } +} + +static void +nv40_fifo_init_intr(struct drm_device *dev) +{ + nv_wr32(dev, 0x002100, 0xffffffff); + nv_wr32(dev, 0x002140, 0xffffffff); +} + +int +nv40_fifo_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + int i; + + nv40_fifo_init_reset(dev); + nv40_fifo_init_ramxx(dev); + + nv40_fifo_do_load_context(dev, pfifo->channels - 1); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1); + + nv40_fifo_init_intr(dev); + pfifo->enable(dev); + pfifo->reassign(dev, true); + + for (i = 0; i < dev_priv->engine.fifo.channels; i++) { + if (dev_priv->fifos[i]) { + uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); + nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); + } + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c new file mode 100644 index 0000000000000000000000000000000000000000..d3e0a2a6acf8e982d5077ce587b8c4982973e77d --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv40_graph.c @@ -0,0 +1,560 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +MODULE_FIRMWARE("nouveau/nv40.ctxprog"); +MODULE_FIRMWARE("nouveau/nv40.ctxvals"); +MODULE_FIRMWARE("nouveau/nv41.ctxprog"); +MODULE_FIRMWARE("nouveau/nv41.ctxvals"); +MODULE_FIRMWARE("nouveau/nv42.ctxprog"); +MODULE_FIRMWARE("nouveau/nv42.ctxvals"); +MODULE_FIRMWARE("nouveau/nv43.ctxprog"); +MODULE_FIRMWARE("nouveau/nv43.ctxvals"); +MODULE_FIRMWARE("nouveau/nv44.ctxprog"); +MODULE_FIRMWARE("nouveau/nv44.ctxvals"); +MODULE_FIRMWARE("nouveau/nv46.ctxprog"); +MODULE_FIRMWARE("nouveau/nv46.ctxvals"); +MODULE_FIRMWARE("nouveau/nv47.ctxprog"); +MODULE_FIRMWARE("nouveau/nv47.ctxvals"); +MODULE_FIRMWARE("nouveau/nv49.ctxprog"); +MODULE_FIRMWARE("nouveau/nv49.ctxvals"); +MODULE_FIRMWARE("nouveau/nv4a.ctxprog"); +MODULE_FIRMWARE("nouveau/nv4a.ctxvals"); +MODULE_FIRMWARE("nouveau/nv4b.ctxprog"); +MODULE_FIRMWARE("nouveau/nv4b.ctxvals"); +MODULE_FIRMWARE("nouveau/nv4c.ctxprog"); +MODULE_FIRMWARE("nouveau/nv4c.ctxvals"); +MODULE_FIRMWARE("nouveau/nv4e.ctxprog"); +MODULE_FIRMWARE("nouveau/nv4e.ctxvals"); + +struct nouveau_channel * +nv40_graph_channel(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t inst; + int i; + + inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); + if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) + return NULL; + inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4; + + for (i = 0; i < dev_priv->engine.fifo.channels; i++) { + struct nouveau_channel *chan = dev_priv->fifos[i]; + + if (chan && chan->ramin_grctx && + chan->ramin_grctx->instance == inst) + return chan; + } + + return NULL; +} + +int +nv40_graph_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *ctx; + int ret; + + /* Allocate a 175KiB block of PRAMIN to store the context. This + * is massive overkill for a lot of chipsets, but it should be safe + * until we're able to implement this properly (will happen at more + * or less the same time we're able to write our own context programs. + */ + ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 175*1024, 16, + NVOBJ_FLAG_ZERO_ALLOC, + &chan->ramin_grctx); + if (ret) + return ret; + ctx = chan->ramin_grctx->gpuobj; + + /* Initialise default context values */ + dev_priv->engine.instmem.prepare_access(dev, true); + nv40_grctx_vals_load(dev, ctx); + nv_wo32(dev, ctx, 0, ctx->im_pramin->start); + dev_priv->engine.instmem.finish_access(dev); + + return 0; +} + +void +nv40_graph_destroy_context(struct nouveau_channel *chan) +{ + nouveau_gpuobj_ref_del(chan->dev, &chan->ramin_grctx); +} + +static int +nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) +{ + uint32_t old_cp, tv = 1000, tmp; + int i; + + old_cp = nv_rd32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER); + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); + + tmp = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0310); + tmp |= save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE : + NV40_PGRAPH_CTXCTL_0310_XFER_LOAD; + nv_wr32(dev, NV40_PGRAPH_CTXCTL_0310, tmp); + + tmp = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0304); + tmp |= NV40_PGRAPH_CTXCTL_0304_XFER_CTX; + nv_wr32(dev, NV40_PGRAPH_CTXCTL_0304, tmp); + + nouveau_wait_for_idle(dev); + + for (i = 0; i < tv; i++) { + if (nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C) == 0) + break; + } + + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp); + + if (i == tv) { + uint32_t ucstat = nv_rd32(dev, NV40_PGRAPH_CTXCTL_UCODE_STAT); + NV_ERROR(dev, "Failed: Instance=0x%08x Save=%d\n", inst, save); + NV_ERROR(dev, "IP: 0x%02x, Opcode: 0x%08x\n", + ucstat >> NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT, + ucstat & NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK); + NV_ERROR(dev, "0x40030C = 0x%08x\n", + nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C)); + return -EBUSY; + } + + return 0; +} + +/* Restore the context for a specific channel into PGRAPH */ +int +nv40_graph_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + uint32_t inst; + int ret; + + if (!chan->ramin_grctx) + return -EINVAL; + inst = chan->ramin_grctx->instance >> 4; + + ret = nv40_graph_transfer_context(dev, inst, 0); + if (ret) + return ret; + + /* 0x40032C, no idea of it's exact function. Could simply be a + * record of the currently active PGRAPH context. It's currently + * unknown as to what bit 24 does. The nv ddx has it set, so we will + * set it here too. + */ + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); + nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, + (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) | + NV40_PGRAPH_CTXCTL_CUR_LOADED); + /* 0x32E0 records the instance address of the active FIFO's PGRAPH + * context. If at any time this doesn't match 0x40032C, you will + * recieve PGRAPH_INTR_CONTEXT_SWITCH + */ + nv_wr32(dev, NV40_PFIFO_GRCTX_INSTANCE, inst); + return 0; +} + +int +nv40_graph_unload_context(struct drm_device *dev) +{ + uint32_t inst; + int ret; + + inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); + if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) + return 0; + inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE; + + ret = nv40_graph_transfer_context(dev, inst, 1); + + nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst); + return ret; +} + +struct nouveau_ctxprog { + uint32_t signature; + uint8_t version; + uint16_t length; + uint32_t data[]; +} __attribute__ ((packed)); + +struct nouveau_ctxvals { + uint32_t signature; + uint8_t version; + uint32_t length; + struct { + uint32_t offset; + uint32_t value; + } data[]; +} __attribute__ ((packed)); + +int +nv40_grctx_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + const int chipset = dev_priv->chipset; + const struct firmware *fw; + const struct nouveau_ctxprog *cp; + const struct nouveau_ctxvals *cv; + char name[32]; + int ret, i; + + pgraph->accel_blocked = true; + + if (!pgraph->ctxprog) { + sprintf(name, "nouveau/nv%02x.ctxprog", chipset); + ret = request_firmware(&fw, name, &dev->pdev->dev); + if (ret) { + NV_ERROR(dev, "No ctxprog for NV%02x\n", chipset); + return ret; + } + + pgraph->ctxprog = kmalloc(fw->size, GFP_KERNEL); + if (!pgraph->ctxprog) { + NV_ERROR(dev, "OOM copying ctxprog\n"); + release_firmware(fw); + return -ENOMEM; + } + memcpy(pgraph->ctxprog, fw->data, fw->size); + + cp = pgraph->ctxprog; + if (cp->signature != 0x5043564e || cp->version != 0 || + cp->length != ((fw->size - 7) / 4)) { + NV_ERROR(dev, "ctxprog invalid\n"); + release_firmware(fw); + nv40_grctx_fini(dev); + return -EINVAL; + } + release_firmware(fw); + } + + if (!pgraph->ctxvals) { + sprintf(name, "nouveau/nv%02x.ctxvals", chipset); + ret = request_firmware(&fw, name, &dev->pdev->dev); + if (ret) { + NV_ERROR(dev, "No ctxvals for NV%02x\n", chipset); + nv40_grctx_fini(dev); + return ret; + } + + pgraph->ctxvals = kmalloc(fw->size, GFP_KERNEL); + if (!pgraph->ctxprog) { + NV_ERROR(dev, "OOM copying ctxprog\n"); + release_firmware(fw); + nv40_grctx_fini(dev); + return -ENOMEM; + } + memcpy(pgraph->ctxvals, fw->data, fw->size); + + cv = (void *)pgraph->ctxvals; + if (cv->signature != 0x5643564e || cv->version != 0 || + cv->length != ((fw->size - 9) / 8)) { + NV_ERROR(dev, "ctxvals invalid\n"); + release_firmware(fw); + nv40_grctx_fini(dev); + return -EINVAL; + } + release_firmware(fw); + } + + cp = pgraph->ctxprog; + + nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); + for (i = 0; i < cp->length; i++) + nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp->data[i]); + + pgraph->accel_blocked = false; + return 0; +} + +void +nv40_grctx_fini(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + + if (pgraph->ctxprog) { + kfree(pgraph->ctxprog); + pgraph->ctxprog = NULL; + } + + if (pgraph->ctxvals) { + kfree(pgraph->ctxprog); + pgraph->ctxvals = NULL; + } +} + +void +nv40_grctx_vals_load(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_ctxvals *cv = pgraph->ctxvals; + int i; + + if (!cv) + return; + + for (i = 0; i < cv->length; i++) + nv_wo32(dev, ctx, cv->data[i].offset, cv->data[i].value); +} + +/* + * G70 0x47 + * G71 0x49 + * NV45 0x48 + * G72[M] 0x46 + * G73 0x4b + * C51_G7X 0x4c + * C51 0x4e + */ +int +nv40_graph_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = + (struct drm_nouveau_private *)dev->dev_private; + uint32_t vramsz, tmp; + int i, j; + + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & + ~NV_PMC_ENABLE_PGRAPH); + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | + NV_PMC_ENABLE_PGRAPH); + + nv40_grctx_init(dev); + + /* No context present currently */ + nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); + + nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); + + nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000); + nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x401287c0); + nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xe0de8055); + nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00008000); + nv_wr32(dev, NV04_PGRAPH_LIMIT_VIOL_PIX, 0x00be3c5f); + + nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100); + nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); + + j = nv_rd32(dev, 0x1540) & 0xff; + if (j) { + for (i = 0; !(j & 1); j >>= 1, i++) + ; + nv_wr32(dev, 0x405000, i); + } + + if (dev_priv->chipset == 0x40) { + nv_wr32(dev, 0x4009b0, 0x83280fff); + nv_wr32(dev, 0x4009b4, 0x000000a0); + } else { + nv_wr32(dev, 0x400820, 0x83280eff); + nv_wr32(dev, 0x400824, 0x000000a0); + } + + switch (dev_priv->chipset) { + case 0x40: + case 0x45: + nv_wr32(dev, 0x4009b8, 0x0078e366); + nv_wr32(dev, 0x4009bc, 0x0000014c); + break; + case 0x41: + case 0x42: /* pciid also 0x00Cx */ + /* case 0x0120: XXX (pciid) */ + nv_wr32(dev, 0x400828, 0x007596ff); + nv_wr32(dev, 0x40082c, 0x00000108); + break; + case 0x43: + nv_wr32(dev, 0x400828, 0x0072cb77); + nv_wr32(dev, 0x40082c, 0x00000108); + break; + case 0x44: + case 0x46: /* G72 */ + case 0x4a: + case 0x4c: /* G7x-based C51 */ + case 0x4e: + nv_wr32(dev, 0x400860, 0); + nv_wr32(dev, 0x400864, 0); + break; + case 0x47: /* G70 */ + case 0x49: /* G71 */ + case 0x4b: /* G73 */ + nv_wr32(dev, 0x400828, 0x07830610); + nv_wr32(dev, 0x40082c, 0x0000016A); + break; + default: + break; + } + + nv_wr32(dev, 0x400b38, 0x2ffff800); + nv_wr32(dev, 0x400b3c, 0x00006000); + + /* copy tile info from PFB */ + switch (dev_priv->chipset) { + case 0x40: /* vanilla NV40 */ + for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { + tmp = nv_rd32(dev, NV10_PFB_TILE(i)); + nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp); + nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp); + tmp = nv_rd32(dev, NV10_PFB_TLIMIT(i)); + nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp); + nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp); + tmp = nv_rd32(dev, NV10_PFB_TSIZE(i)); + nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp); + nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp); + tmp = nv_rd32(dev, NV10_PFB_TSTATUS(i)); + nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp); + nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp); + } + break; + case 0x44: + case 0x4a: + case 0x4e: /* NV44-based cores don't have 0x406900? */ + for (i = 0; i < NV40_PFB_TILE__SIZE_0; i++) { + tmp = nv_rd32(dev, NV40_PFB_TILE(i)); + nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp); + tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i)); + nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp); + tmp = nv_rd32(dev, NV40_PFB_TSIZE(i)); + nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp); + tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i)); + nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp); + } + break; + case 0x46: + case 0x47: + case 0x49: + case 0x4b: /* G7X-based cores */ + for (i = 0; i < NV40_PFB_TILE__SIZE_1; i++) { + tmp = nv_rd32(dev, NV40_PFB_TILE(i)); + nv_wr32(dev, NV47_PGRAPH_TILE0(i), tmp); + nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp); + tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i)); + nv_wr32(dev, NV47_PGRAPH_TLIMIT0(i), tmp); + nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp); + tmp = nv_rd32(dev, NV40_PFB_TSIZE(i)); + nv_wr32(dev, NV47_PGRAPH_TSIZE0(i), tmp); + nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp); + tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i)); + nv_wr32(dev, NV47_PGRAPH_TSTATUS0(i), tmp); + nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp); + } + break; + default: /* everything else */ + for (i = 0; i < NV40_PFB_TILE__SIZE_0; i++) { + tmp = nv_rd32(dev, NV40_PFB_TILE(i)); + nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp); + nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp); + tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i)); + nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp); + nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp); + tmp = nv_rd32(dev, NV40_PFB_TSIZE(i)); + nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp); + nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp); + tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i)); + nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp); + nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp); + } + break; + } + + /* begin RAM config */ + vramsz = drm_get_resource_len(dev, 0) - 1; + switch (dev_priv->chipset) { + case 0x40: + nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); + nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); + nv_wr32(dev, 0x4069A4, nv_rd32(dev, NV04_PFB_CFG0)); + nv_wr32(dev, 0x4069A8, nv_rd32(dev, NV04_PFB_CFG1)); + nv_wr32(dev, 0x400820, 0); + nv_wr32(dev, 0x400824, 0); + nv_wr32(dev, 0x400864, vramsz); + nv_wr32(dev, 0x400868, vramsz); + break; + default: + switch (dev_priv->chipset) { + case 0x46: + case 0x47: + case 0x49: + case 0x4b: + nv_wr32(dev, 0x400DF0, nv_rd32(dev, NV04_PFB_CFG0)); + nv_wr32(dev, 0x400DF4, nv_rd32(dev, NV04_PFB_CFG1)); + break; + default: + nv_wr32(dev, 0x4009F0, nv_rd32(dev, NV04_PFB_CFG0)); + nv_wr32(dev, 0x4009F4, nv_rd32(dev, NV04_PFB_CFG1)); + break; + } + nv_wr32(dev, 0x4069F0, nv_rd32(dev, NV04_PFB_CFG0)); + nv_wr32(dev, 0x4069F4, nv_rd32(dev, NV04_PFB_CFG1)); + nv_wr32(dev, 0x400840, 0); + nv_wr32(dev, 0x400844, 0); + nv_wr32(dev, 0x4008A0, vramsz); + nv_wr32(dev, 0x4008A4, vramsz); + break; + } + + return 0; +} + +void nv40_graph_takedown(struct drm_device *dev) +{ +} + +struct nouveau_pgraph_object_class nv40_graph_grclass[] = { + { 0x0030, false, NULL }, /* null */ + { 0x0039, false, NULL }, /* m2mf */ + { 0x004a, false, NULL }, /* gdirect */ + { 0x009f, false, NULL }, /* imageblit (nv12) */ + { 0x008a, false, NULL }, /* ifc */ + { 0x0089, false, NULL }, /* sifm */ + { 0x3089, false, NULL }, /* sifm (nv40) */ + { 0x0062, false, NULL }, /* surf2d */ + { 0x3062, false, NULL }, /* surf2d (nv40) */ + { 0x0043, false, NULL }, /* rop */ + { 0x0012, false, NULL }, /* beta1 */ + { 0x0072, false, NULL }, /* beta4 */ + { 0x0019, false, NULL }, /* cliprect */ + { 0x0044, false, NULL }, /* pattern */ + { 0x309e, false, NULL }, /* swzsurf */ + { 0x4097, false, NULL }, /* curie (nv40) */ + { 0x4497, false, NULL }, /* curie (nv44) */ + {} +}; + diff --git a/drivers/gpu/drm/nouveau/nv40_mc.c b/drivers/gpu/drm/nouveau/nv40_mc.c new file mode 100644 index 0000000000000000000000000000000000000000..2a3495e848e9b96e548339e5d41eb1fd5a7c2985 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv40_mc.c @@ -0,0 +1,38 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv40_mc_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t tmp; + + /* Power up everything, resetting each individual unit will + * be done later if needed. + */ + nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF); + + switch (dev_priv->chipset) { + case 0x44: + case 0x46: /* G72 */ + case 0x4e: + case 0x4c: /* C51_G7X */ + tmp = nv_rd32(dev, NV40_PFB_020C); + nv_wr32(dev, NV40_PMC_1700, tmp); + nv_wr32(dev, NV40_PMC_1704, 0); + nv_wr32(dev, NV40_PMC_1708, 0); + nv_wr32(dev, NV40_PMC_170C, tmp); + break; + default: + break; + } + + return 0; +} + +void +nv40_mc_takedown(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c new file mode 100644 index 0000000000000000000000000000000000000000..f8e28a1e44e785747b1a7da74a1247bc5b92002b --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c @@ -0,0 +1,769 @@ +/* + * Copyright (C) 2008 Maarten Maathuis. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm_mode.h" +#include "drm_crtc_helper.h" + +#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) +#include "nouveau_reg.h" +#include "nouveau_drv.h" +#include "nouveau_hw.h" +#include "nouveau_encoder.h" +#include "nouveau_crtc.h" +#include "nouveau_fb.h" +#include "nouveau_connector.h" +#include "nv50_display.h" + +static void +nv50_crtc_lut_load(struct drm_crtc *crtc) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo); + int i; + + NV_DEBUG(crtc->dev, "\n"); + + for (i = 0; i < 256; i++) { + writew(nv_crtc->lut.r[i] >> 2, lut + 8*i + 0); + writew(nv_crtc->lut.g[i] >> 2, lut + 8*i + 2); + writew(nv_crtc->lut.b[i] >> 2, lut + 8*i + 4); + } + + if (nv_crtc->lut.depth == 30) { + writew(nv_crtc->lut.r[i - 1] >> 2, lut + 8*i + 0); + writew(nv_crtc->lut.g[i - 1] >> 2, lut + 8*i + 2); + writew(nv_crtc->lut.b[i - 1] >> 2, lut + 8*i + 4); + } +} + +int +nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) +{ + struct drm_device *dev = nv_crtc->base.dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *evo = dev_priv->evo; + int index = nv_crtc->index, ret; + + NV_DEBUG(dev, "index %d\n", nv_crtc->index); + NV_DEBUG(dev, "%s\n", blanked ? "blanked" : "unblanked"); + + if (blanked) { + nv_crtc->cursor.hide(nv_crtc, false); + + ret = RING_SPACE(evo, dev_priv->chipset != 0x50 ? 7 : 5); + if (ret) { + NV_ERROR(dev, "no space while blanking crtc\n"); + return ret; + } + BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2); + OUT_RING(evo, NV50_EVO_CRTC_CLUT_MODE_BLANK); + OUT_RING(evo, 0); + if (dev_priv->chipset != 0x50) { + BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); + OUT_RING(evo, NV84_EVO_CRTC_CLUT_DMA_HANDLE_NONE); + } + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1); + OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE); + } else { + if (nv_crtc->cursor.visible) + nv_crtc->cursor.show(nv_crtc, false); + else + nv_crtc->cursor.hide(nv_crtc, false); + + ret = RING_SPACE(evo, dev_priv->chipset != 0x50 ? 10 : 8); + if (ret) { + NV_ERROR(dev, "no space while unblanking crtc\n"); + return ret; + } + BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2); + OUT_RING(evo, nv_crtc->lut.depth == 8 ? + NV50_EVO_CRTC_CLUT_MODE_OFF : + NV50_EVO_CRTC_CLUT_MODE_ON); + OUT_RING(evo, (nv_crtc->lut.nvbo->bo.mem.mm_node->start << + PAGE_SHIFT) >> 8); + if (dev_priv->chipset != 0x50) { + BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); + OUT_RING(evo, NvEvoVRAM); + } + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, FB_OFFSET), 2); + OUT_RING(evo, nv_crtc->fb.offset >> 8); + OUT_RING(evo, 0); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1); + if (dev_priv->chipset != 0x50) + if (nv_crtc->fb.tile_flags == 0x7a00) + OUT_RING(evo, NvEvoFB32); + else + if (nv_crtc->fb.tile_flags == 0x7000) + OUT_RING(evo, NvEvoFB16); + else + OUT_RING(evo, NvEvoVRAM); + else + OUT_RING(evo, NvEvoVRAM); + } + + nv_crtc->fb.blanked = blanked; + return 0; +} + +static int +nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) +{ + struct drm_device *dev = nv_crtc->base.dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *evo = dev_priv->evo; + int ret; + + NV_DEBUG(dev, "\n"); + + ret = RING_SPACE(evo, 2 + (update ? 2 : 0)); + if (ret) { + NV_ERROR(dev, "no space while setting dither\n"); + return ret; + } + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, DITHER_CTRL), 1); + if (on) + OUT_RING(evo, NV50_EVO_CRTC_DITHER_CTRL_ON); + else + OUT_RING(evo, NV50_EVO_CRTC_DITHER_CTRL_OFF); + + if (update) { + BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); + OUT_RING(evo, 0); + FIRE_RING(evo); + } + + return 0; +} + +struct nouveau_connector * +nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) +{ + struct drm_device *dev = nv_crtc->base.dev; + struct drm_connector *connector; + struct drm_crtc *crtc = to_drm_crtc(nv_crtc); + + /* The safest approach is to find an encoder with the right crtc, that + * is also linked to a connector. */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->encoder) + if (connector->encoder->crtc == crtc) + return nouveau_connector(connector); + } + + return NULL; +} + +static int +nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update) +{ + struct nouveau_connector *nv_connector = + nouveau_crtc_connector_get(nv_crtc); + struct drm_device *dev = nv_crtc->base.dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *evo = dev_priv->evo; + struct drm_display_mode *native_mode = NULL; + struct drm_display_mode *mode = &nv_crtc->base.mode; + uint32_t outX, outY, horiz, vert; + int ret; + + NV_DEBUG(dev, "\n"); + + switch (scaling_mode) { + case DRM_MODE_SCALE_NONE: + break; + default: + if (!nv_connector || !nv_connector->native_mode) { + NV_ERROR(dev, "No native mode, forcing panel scaling\n"); + scaling_mode = DRM_MODE_SCALE_NONE; + } else { + native_mode = nv_connector->native_mode; + } + break; + } + + switch (scaling_mode) { + case DRM_MODE_SCALE_ASPECT: + horiz = (native_mode->hdisplay << 19) / mode->hdisplay; + vert = (native_mode->vdisplay << 19) / mode->vdisplay; + + if (vert > horiz) { + outX = (mode->hdisplay * horiz) >> 19; + outY = (mode->vdisplay * horiz) >> 19; + } else { + outX = (mode->hdisplay * vert) >> 19; + outY = (mode->vdisplay * vert) >> 19; + } + break; + case DRM_MODE_SCALE_FULLSCREEN: + outX = native_mode->hdisplay; + outY = native_mode->vdisplay; + break; + case DRM_MODE_SCALE_CENTER: + case DRM_MODE_SCALE_NONE: + default: + outX = mode->hdisplay; + outY = mode->vdisplay; + break; + } + + ret = RING_SPACE(evo, update ? 7 : 5); + if (ret) + return ret; + + /* Got a better name for SCALER_ACTIVE? */ + /* One day i've got to really figure out why this is needed. */ + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_CTRL), 1); + if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) || + (mode->flags & DRM_MODE_FLAG_INTERLACE) || + mode->hdisplay != outX || mode->vdisplay != outY) { + OUT_RING(evo, NV50_EVO_CRTC_SCALE_CTRL_ACTIVE); + } else { + OUT_RING(evo, NV50_EVO_CRTC_SCALE_CTRL_INACTIVE); + } + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_RES1), 2); + OUT_RING(evo, outY << 16 | outX); + OUT_RING(evo, outY << 16 | outX); + + if (update) { + BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); + OUT_RING(evo, 0); + FIRE_RING(evo); + } + + return 0; +} + +int +nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) +{ + uint32_t pll_reg = NV50_PDISPLAY_CRTC_CLK_CTRL1(head); + struct nouveau_pll_vals pll; + struct pll_lims limits; + uint32_t reg1, reg2; + int ret; + + ret = get_pll_limits(dev, pll_reg, &limits); + if (ret) + return ret; + + ret = nouveau_calc_pll_mnp(dev, &limits, pclk, &pll); + if (ret <= 0) + return ret; + + if (limits.vco2.maxfreq) { + reg1 = nv_rd32(dev, pll_reg + 4) & 0xff00ff00; + reg2 = nv_rd32(dev, pll_reg + 8) & 0x8000ff00; + nv_wr32(dev, pll_reg, 0x10000611); + nv_wr32(dev, pll_reg + 4, reg1 | (pll.M1 << 16) | pll.N1); + nv_wr32(dev, pll_reg + 8, + reg2 | (pll.log2P << 28) | (pll.M2 << 16) | pll.N2); + } else { + reg1 = nv_rd32(dev, pll_reg + 4) & 0xffc00000; + nv_wr32(dev, pll_reg, 0x50000610); + nv_wr32(dev, pll_reg + 4, reg1 | + (pll.log2P << 16) | (pll.M1 << 8) | pll.N1); + } + + return 0; +} + +static void +nv50_crtc_destroy(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + + NV_DEBUG(dev, "\n"); + + if (!crtc) + return; + + drm_crtc_cleanup(&nv_crtc->base); + + nv50_cursor_fini(nv_crtc); + + nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); + nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); + kfree(nv_crtc->mode); + kfree(nv_crtc); +} + +int +nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, + uint32_t buffer_handle, uint32_t width, uint32_t height) +{ + struct drm_device *dev = crtc->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct nouveau_bo *cursor = NULL; + struct drm_gem_object *gem; + int ret = 0, i; + + if (width != 64 || height != 64) + return -EINVAL; + + if (!buffer_handle) { + nv_crtc->cursor.hide(nv_crtc, true); + return 0; + } + + gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); + if (!gem) + return -EINVAL; + cursor = nouveau_gem_object(gem); + + ret = nouveau_bo_map(cursor); + if (ret) + goto out; + + /* The simple will do for now. */ + for (i = 0; i < 64 * 64; i++) + nouveau_bo_wr32(nv_crtc->cursor.nvbo, i, nouveau_bo_rd32(cursor, i)); + + nouveau_bo_unmap(cursor); + + nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset - + dev_priv->vm_vram_base); + nv_crtc->cursor.show(nv_crtc, true); + +out: + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(gem); + mutex_unlock(&dev->struct_mutex); + return ret; +} + +int +nv50_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + + nv_crtc->cursor.set_pos(nv_crtc, x, y); + return 0; +} + +static void +nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, + uint32_t size) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + int i; + + if (size != 256) + return; + + for (i = 0; i < 256; i++) { + nv_crtc->lut.r[i] = r[i]; + nv_crtc->lut.g[i] = g[i]; + nv_crtc->lut.b[i] = b[i]; + } + + /* We need to know the depth before we upload, but it's possible to + * get called before a framebuffer is bound. If this is the case, + * mark the lut values as dirty by setting depth==0, and it'll be + * uploaded on the first mode_set_base() + */ + if (!nv_crtc->base.fb) { + nv_crtc->lut.depth = 0; + return; + } + + nv50_crtc_lut_load(crtc); +} + +static void +nv50_crtc_save(struct drm_crtc *crtc) +{ + NV_ERROR(crtc->dev, "!!\n"); +} + +static void +nv50_crtc_restore(struct drm_crtc *crtc) +{ + NV_ERROR(crtc->dev, "!!\n"); +} + +static const struct drm_crtc_funcs nv50_crtc_funcs = { + .save = nv50_crtc_save, + .restore = nv50_crtc_restore, + .cursor_set = nv50_crtc_cursor_set, + .cursor_move = nv50_crtc_cursor_move, + .gamma_set = nv50_crtc_gamma_set, + .set_config = drm_crtc_helper_set_config, + .destroy = nv50_crtc_destroy, +}; + +static void +nv50_crtc_dpms(struct drm_crtc *crtc, int mode) +{ +} + +static void +nv50_crtc_prepare(struct drm_crtc *crtc) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_encoder *encoder; + + NV_DEBUG(dev, "index %d\n", nv_crtc->index); + + /* Disconnect all unused encoders. */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + if (drm_helper_encoder_in_use(encoder)) + continue; + + nv_encoder->disconnect(nv_encoder); + } + + nv50_crtc_blank(nv_crtc, true); +} + +static void +nv50_crtc_commit(struct drm_crtc *crtc) +{ + struct drm_crtc *crtc2; + struct drm_device *dev = crtc->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *evo = dev_priv->evo; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + int ret; + + NV_DEBUG(dev, "index %d\n", nv_crtc->index); + + nv50_crtc_blank(nv_crtc, false); + + /* Explicitly blank all unused crtc's. */ + list_for_each_entry(crtc2, &dev->mode_config.crtc_list, head) { + if (!drm_helper_crtc_in_use(crtc2)) + nv50_crtc_blank(nouveau_crtc(crtc2), true); + } + + ret = RING_SPACE(evo, 2); + if (ret) { + NV_ERROR(dev, "no space while committing crtc\n"); + return; + } + BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); + OUT_RING(evo, 0); + FIRE_RING(evo); +} + +static bool +nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static int +nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb, bool update) +{ + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct drm_device *dev = nv_crtc->base.dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *evo = dev_priv->evo; + struct drm_framebuffer *drm_fb = nv_crtc->base.fb; + struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); + int ret, format; + + NV_DEBUG(dev, "index %d\n", nv_crtc->index); + + switch (drm_fb->depth) { + case 8: + format = NV50_EVO_CRTC_FB_DEPTH_8; + break; + case 15: + format = NV50_EVO_CRTC_FB_DEPTH_15; + break; + case 16: + format = NV50_EVO_CRTC_FB_DEPTH_16; + break; + case 24: + case 32: + format = NV50_EVO_CRTC_FB_DEPTH_24; + break; + case 30: + format = NV50_EVO_CRTC_FB_DEPTH_30; + break; + default: + NV_ERROR(dev, "unknown depth %d\n", drm_fb->depth); + return -EINVAL; + } + + ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM); + if (ret) + return ret; + + if (old_fb) { + struct nouveau_framebuffer *ofb = nouveau_framebuffer(old_fb); + nouveau_bo_unpin(ofb->nvbo); + } + + nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base; + nv_crtc->fb.tile_flags = fb->nvbo->tile_flags; + nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; + if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) { + ret = RING_SPACE(evo, 2); + if (ret) + return ret; + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1); + if (nv_crtc->fb.tile_flags == 0x7a00) + OUT_RING(evo, NvEvoFB32); + else + if (nv_crtc->fb.tile_flags == 0x7000) + OUT_RING(evo, NvEvoFB16); + else + OUT_RING(evo, NvEvoVRAM); + } + + ret = RING_SPACE(evo, 12); + if (ret) + return ret; + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_OFFSET), 5); + OUT_RING(evo, nv_crtc->fb.offset >> 8); + OUT_RING(evo, 0); + OUT_RING(evo, (drm_fb->height << 16) | drm_fb->width); + if (!nv_crtc->fb.tile_flags) { + OUT_RING(evo, drm_fb->pitch | (1 << 20)); + } else { + OUT_RING(evo, ((drm_fb->pitch / 4) << 4) | + fb->nvbo->tile_mode); + } + if (dev_priv->chipset == 0x50) + OUT_RING(evo, (fb->nvbo->tile_flags << 8) | format); + else + OUT_RING(evo, format); + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLUT_MODE), 1); + OUT_RING(evo, fb->base.depth == 8 ? + NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON); + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1); + OUT_RING(evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1); + OUT_RING(evo, (y << 16) | x); + + if (nv_crtc->lut.depth != fb->base.depth) { + nv_crtc->lut.depth = fb->base.depth; + nv50_crtc_lut_load(crtc); + } + + if (update) { + ret = RING_SPACE(evo, 2); + if (ret) + return ret; + BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); + OUT_RING(evo, 0); + FIRE_RING(evo); + } + + return 0; +} + +static int +nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, int x, int y, + struct drm_framebuffer *old_fb) +{ + struct drm_device *dev = crtc->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *evo = dev_priv->evo; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct nouveau_connector *nv_connector = NULL; + uint32_t hsync_dur, vsync_dur, hsync_start_to_end, vsync_start_to_end; + uint32_t hunk1, vunk1, vunk2a, vunk2b; + int ret; + + /* Find the connector attached to this CRTC */ + nv_connector = nouveau_crtc_connector_get(nv_crtc); + + *nv_crtc->mode = *adjusted_mode; + + NV_DEBUG(dev, "index %d\n", nv_crtc->index); + + hsync_dur = adjusted_mode->hsync_end - adjusted_mode->hsync_start; + vsync_dur = adjusted_mode->vsync_end - adjusted_mode->vsync_start; + hsync_start_to_end = adjusted_mode->htotal - adjusted_mode->hsync_start; + vsync_start_to_end = adjusted_mode->vtotal - adjusted_mode->vsync_start; + /* I can't give this a proper name, anyone else can? */ + hunk1 = adjusted_mode->htotal - + adjusted_mode->hsync_start + adjusted_mode->hdisplay; + vunk1 = adjusted_mode->vtotal - + adjusted_mode->vsync_start + adjusted_mode->vdisplay; + /* Another strange value, this time only for interlaced adjusted_modes. */ + vunk2a = 2 * adjusted_mode->vtotal - + adjusted_mode->vsync_start + adjusted_mode->vdisplay; + vunk2b = adjusted_mode->vtotal - + adjusted_mode->vsync_start + adjusted_mode->vtotal; + + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { + vsync_dur /= 2; + vsync_start_to_end /= 2; + vunk1 /= 2; + vunk2a /= 2; + vunk2b /= 2; + /* magic */ + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) { + vsync_start_to_end -= 1; + vunk1 -= 1; + vunk2a -= 1; + vunk2b -= 1; + } + } + + ret = RING_SPACE(evo, 17); + if (ret) + return ret; + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLOCK), 2); + OUT_RING(evo, adjusted_mode->clock | 0x800000); + OUT_RING(evo, (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 0); + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, DISPLAY_START), 5); + OUT_RING(evo, 0); + OUT_RING(evo, (adjusted_mode->vtotal << 16) | adjusted_mode->htotal); + OUT_RING(evo, (vsync_dur - 1) << 16 | (hsync_dur - 1)); + OUT_RING(evo, (vsync_start_to_end - 1) << 16 | + (hsync_start_to_end - 1)); + OUT_RING(evo, (vunk1 - 1) << 16 | (hunk1 - 1)); + + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, UNK0824), 1); + OUT_RING(evo, (vunk2b - 1) << 16 | (vunk2a - 1)); + } else { + OUT_RING(evo, 0); + OUT_RING(evo, 0); + } + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, UNK082C), 1); + OUT_RING(evo, 0); + + /* This is the actual resolution of the mode. */ + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, REAL_RES), 1); + OUT_RING(evo, (mode->vdisplay << 16) | mode->hdisplay); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_CENTER_OFFSET), 1); + OUT_RING(evo, NV50_EVO_CRTC_SCALE_CENTER_OFFSET_VAL(0, 0)); + + nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false); + nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false); + + return nv50_crtc_do_mode_set_base(crtc, x, y, old_fb, false); +} + +static int +nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) +{ + return nv50_crtc_do_mode_set_base(crtc, x, y, old_fb, true); +} + +static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { + .dpms = nv50_crtc_dpms, + .prepare = nv50_crtc_prepare, + .commit = nv50_crtc_commit, + .mode_fixup = nv50_crtc_mode_fixup, + .mode_set = nv50_crtc_mode_set, + .mode_set_base = nv50_crtc_mode_set_base, + .load_lut = nv50_crtc_lut_load, +}; + +int +nv50_crtc_create(struct drm_device *dev, int index) +{ + struct nouveau_crtc *nv_crtc = NULL; + int ret, i; + + NV_DEBUG(dev, "\n"); + + nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); + if (!nv_crtc) + return -ENOMEM; + + nv_crtc->mode = kzalloc(sizeof(*nv_crtc->mode), GFP_KERNEL); + if (!nv_crtc->mode) { + kfree(nv_crtc); + return -ENOMEM; + } + + /* Default CLUT parameters, will be activated on the hw upon + * first mode set. + */ + for (i = 0; i < 256; i++) { + nv_crtc->lut.r[i] = i << 8; + nv_crtc->lut.g[i] = i << 8; + nv_crtc->lut.b[i] = i << 8; + } + nv_crtc->lut.depth = 0; + + ret = nouveau_bo_new(dev, NULL, 4096, 0x100, TTM_PL_FLAG_VRAM, + 0, 0x0000, false, true, &nv_crtc->lut.nvbo); + if (!ret) { + ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); + if (!ret) + ret = nouveau_bo_map(nv_crtc->lut.nvbo); + if (ret) + nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); + } + + if (ret) { + kfree(nv_crtc->mode); + kfree(nv_crtc); + return ret; + } + + nv_crtc->index = index; + + /* set function pointers */ + nv_crtc->set_dither = nv50_crtc_set_dither; + nv_crtc->set_scale = nv50_crtc_set_scale; + + drm_crtc_init(dev, &nv_crtc->base, &nv50_crtc_funcs); + drm_crtc_helper_add(&nv_crtc->base, &nv50_crtc_helper_funcs); + drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); + + ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, + 0, 0x0000, false, true, &nv_crtc->cursor.nvbo); + if (!ret) { + ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); + if (!ret) + ret = nouveau_bo_map(nv_crtc->cursor.nvbo); + if (ret) + nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); + } + + nv50_cursor_init(nv_crtc); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c new file mode 100644 index 0000000000000000000000000000000000000000..e2e79a8f220d0df652d379c35191a2e90f5b0c08 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_cursor.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2008 Maarten Maathuis. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm_mode.h" + +#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) +#include "nouveau_reg.h" +#include "nouveau_drv.h" +#include "nouveau_crtc.h" +#include "nv50_display.h" + +static void +nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) +{ + struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private; + struct nouveau_channel *evo = dev_priv->evo; + struct drm_device *dev = nv_crtc->base.dev; + int ret; + + NV_DEBUG(dev, "\n"); + + if (update && nv_crtc->cursor.visible) + return; + + ret = RING_SPACE(evo, (dev_priv->chipset != 0x50 ? 5 : 3) + update * 2); + if (ret) { + NV_ERROR(dev, "no space while unhiding cursor\n"); + return; + } + + if (dev_priv->chipset != 0x50) { + BEGIN_RING(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1); + OUT_RING(evo, NvEvoVRAM); + } + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CURSOR_CTRL), 2); + OUT_RING(evo, NV50_EVO_CRTC_CURSOR_CTRL_SHOW); + OUT_RING(evo, nv_crtc->cursor.offset >> 8); + + if (update) { + BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); + OUT_RING(evo, 0); + FIRE_RING(evo); + nv_crtc->cursor.visible = true; + } +} + +static void +nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) +{ + struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private; + struct nouveau_channel *evo = dev_priv->evo; + struct drm_device *dev = nv_crtc->base.dev; + int ret; + + NV_DEBUG(dev, "\n"); + + if (update && !nv_crtc->cursor.visible) + return; + + ret = RING_SPACE(evo, (dev_priv->chipset != 0x50 ? 5 : 3) + update * 2); + if (ret) { + NV_ERROR(dev, "no space while hiding cursor\n"); + return; + } + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CURSOR_CTRL), 2); + OUT_RING(evo, NV50_EVO_CRTC_CURSOR_CTRL_HIDE); + OUT_RING(evo, 0); + if (dev_priv->chipset != 0x50) { + BEGIN_RING(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1); + OUT_RING(evo, NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE); + } + + if (update) { + BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); + OUT_RING(evo, 0); + FIRE_RING(evo); + nv_crtc->cursor.visible = false; + } +} + +static void +nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y) +{ + struct drm_device *dev = nv_crtc->base.dev; + + nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index), + ((y & 0xFFFF) << 16) | (x & 0xFFFF)); + /* Needed to make the cursor move. */ + nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS_CTRL(nv_crtc->index), 0); +} + +static void +nv50_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) +{ + NV_DEBUG(nv_crtc->base.dev, "\n"); + if (offset == nv_crtc->cursor.offset) + return; + + nv_crtc->cursor.offset = offset; + if (nv_crtc->cursor.visible) { + nv_crtc->cursor.visible = false; + nv_crtc->cursor.show(nv_crtc, true); + } +} + +int +nv50_cursor_init(struct nouveau_crtc *nv_crtc) +{ + nv_crtc->cursor.set_offset = nv50_cursor_set_offset; + nv_crtc->cursor.set_pos = nv50_cursor_set_pos; + nv_crtc->cursor.hide = nv50_cursor_hide; + nv_crtc->cursor.show = nv50_cursor_show; + return 0; +} + +void +nv50_cursor_fini(struct nouveau_crtc *nv_crtc) +{ + struct drm_device *dev = nv_crtc->base.dev; + int idx = nv_crtc->index; + + NV_DEBUG(dev, "\n"); + + nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0); + if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), + NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { + NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); + NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", + nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx))); + } +} + diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c new file mode 100644 index 0000000000000000000000000000000000000000..fb5838e3be24038d1db8c460ba2fdb8c8f8596e7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_dac.c @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2008 Maarten Maathuis. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm_crtc_helper.h" + +#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) +#include "nouveau_reg.h" +#include "nouveau_drv.h" +#include "nouveau_dma.h" +#include "nouveau_encoder.h" +#include "nouveau_connector.h" +#include "nouveau_crtc.h" +#include "nv50_display.h" + +static void +nv50_dac_disconnect(struct nouveau_encoder *nv_encoder) +{ + struct drm_device *dev = to_drm_encoder(nv_encoder)->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *evo = dev_priv->evo; + int ret; + + NV_DEBUG(dev, "Disconnecting DAC %d\n", nv_encoder->or); + + ret = RING_SPACE(evo, 2); + if (ret) { + NV_ERROR(dev, "no space while disconnecting DAC\n"); + return; + } + BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1); + OUT_RING(evo, 0); +} + +static enum drm_connector_status +nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + enum drm_connector_status status = connector_status_disconnected; + uint32_t dpms_state, load_pattern, load_state; + int or = nv_encoder->or; + + nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 0x00000001); + dpms_state = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)); + + nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), + 0x00150000 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); + if (!nv_wait(NV50_PDISPLAY_DAC_DPMS_CTRL(or), + NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { + NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); + NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, + nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or))); + return status; + } + + /* Use bios provided value if possible. */ + if (dev_priv->vbios->dactestval) { + load_pattern = dev_priv->vbios->dactestval; + NV_DEBUG(dev, "Using bios provided load_pattern of %d\n", + load_pattern); + } else { + load_pattern = 340; + NV_DEBUG(dev, "Using default load_pattern of %d\n", + load_pattern); + } + + nv_wr32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or), + NV50_PDISPLAY_DAC_LOAD_CTRL_ACTIVE | load_pattern); + mdelay(45); /* give it some time to process */ + load_state = nv_rd32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or)); + + nv_wr32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or), 0); + nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), dpms_state | + NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); + + if ((load_state & NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT) == + NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT) + status = connector_status_connected; + + if (status == connector_status_connected) + NV_DEBUG(dev, "Load was detected on output with or %d\n", or); + else + NV_DEBUG(dev, "Load was not detected on output with or %d\n", or); + + return status; +} + +static void +nv50_dac_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + uint32_t val; + int or = nv_encoder->or; + + NV_DEBUG(dev, "or %d mode %d\n", or, mode); + + /* wait for it to be done */ + if (!nv_wait(NV50_PDISPLAY_DAC_DPMS_CTRL(or), + NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { + NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); + NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, + nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or))); + return; + } + + val = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)) & ~0x7F; + + if (mode != DRM_MODE_DPMS_ON) + val |= NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED; + + switch (mode) { + case DRM_MODE_DPMS_STANDBY: + val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF; + break; + case DRM_MODE_DPMS_SUSPEND: + val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF; + break; + case DRM_MODE_DPMS_OFF: + val |= NV50_PDISPLAY_DAC_DPMS_CTRL_OFF; + val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF; + val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF; + break; + default: + break; + } + + nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), val | + NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); +} + +static void +nv50_dac_save(struct drm_encoder *encoder) +{ + NV_ERROR(encoder->dev, "!!\n"); +} + +static void +nv50_dac_restore(struct drm_encoder *encoder) +{ + NV_ERROR(encoder->dev, "!!\n"); +} + +static bool +nv50_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_connector *connector; + + NV_DEBUG(encoder->dev, "or %d\n", nv_encoder->or); + + connector = nouveau_encoder_connector_get(nv_encoder); + if (!connector) { + NV_ERROR(encoder->dev, "Encoder has no connector\n"); + return false; + } + + if (connector->scaling_mode != DRM_MODE_SCALE_NONE && + connector->native_mode) { + int id = adjusted_mode->base.id; + *adjusted_mode = *connector->native_mode; + adjusted_mode->base.id = id; + } + + return true; +} + +static void +nv50_dac_prepare(struct drm_encoder *encoder) +{ +} + +static void +nv50_dac_commit(struct drm_encoder *encoder) +{ +} + +static void +nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *evo = dev_priv->evo; + struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); + uint32_t mode_ctl = 0, mode_ctl2 = 0; + int ret; + + NV_DEBUG(dev, "or %d\n", nv_encoder->or); + + nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON); + + if (crtc->index == 1) + mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC1; + else + mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC0; + + /* Lacking a working tv-out, this is not a 100% sure. */ + if (nv_encoder->dcb->type == OUTPUT_ANALOG) + mode_ctl |= 0x40; + else + if (nv_encoder->dcb->type == OUTPUT_TV) + mode_ctl |= 0x100; + + if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) + mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NHSYNC; + + if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) + mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NVSYNC; + + ret = RING_SPACE(evo, 3); + if (ret) { + NV_ERROR(dev, "no space while connecting DAC\n"); + return; + } + BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2); + OUT_RING(evo, mode_ctl); + OUT_RING(evo, mode_ctl2); +} + +static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = { + .dpms = nv50_dac_dpms, + .save = nv50_dac_save, + .restore = nv50_dac_restore, + .mode_fixup = nv50_dac_mode_fixup, + .prepare = nv50_dac_prepare, + .commit = nv50_dac_commit, + .mode_set = nv50_dac_mode_set, + .detect = nv50_dac_detect +}; + +static void +nv50_dac_destroy(struct drm_encoder *encoder) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + if (!encoder) + return; + + NV_DEBUG(encoder->dev, "\n"); + + drm_encoder_cleanup(encoder); + kfree(nv_encoder); +} + +static const struct drm_encoder_funcs nv50_dac_encoder_funcs = { + .destroy = nv50_dac_destroy, +}; + +int +nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry) +{ + struct nouveau_encoder *nv_encoder; + struct drm_encoder *encoder; + + NV_DEBUG(dev, "\n"); + NV_INFO(dev, "Detected a DAC output\n"); + + nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); + if (!nv_encoder) + return -ENOMEM; + encoder = to_drm_encoder(nv_encoder); + + nv_encoder->dcb = entry; + nv_encoder->or = ffs(entry->or) - 1; + + nv_encoder->disconnect = nv50_dac_disconnect; + + drm_encoder_init(dev, encoder, &nv50_dac_encoder_funcs, + DRM_MODE_ENCODER_DAC); + drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs); + + encoder->possible_crtcs = entry->heads; + encoder->possible_clones = 0; + return 0; +} + diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c new file mode 100644 index 0000000000000000000000000000000000000000..12c5ee63495b3a59e99c15b64a0e4d91b02640e7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -0,0 +1,1015 @@ +/* + * Copyright (C) 2008 Maarten Maathuis. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "nv50_display.h" +#include "nouveau_crtc.h" +#include "nouveau_encoder.h" +#include "nouveau_connector.h" +#include "nouveau_fb.h" +#include "drm_crtc_helper.h" + +static void +nv50_evo_channel_del(struct nouveau_channel **pchan) +{ + struct nouveau_channel *chan = *pchan; + + if (!chan) + return; + *pchan = NULL; + + nouveau_gpuobj_channel_takedown(chan); + nouveau_bo_ref(NULL, &chan->pushbuf_bo); + + if (chan->user) + iounmap(chan->user); + + kfree(chan); +} + +static int +nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name, + uint32_t tile_flags, uint32_t magic_flags, + uint32_t offset, uint32_t limit) +{ + struct drm_nouveau_private *dev_priv = evo->dev->dev_private; + struct drm_device *dev = evo->dev; + struct nouveau_gpuobj *obj = NULL; + int ret; + + ret = nouveau_gpuobj_new(dev, evo, 6*4, 32, 0, &obj); + if (ret) + return ret; + obj->engine = NVOBJ_ENGINE_DISPLAY; + + ret = nouveau_gpuobj_ref_add(dev, evo, name, obj, NULL); + if (ret) { + nouveau_gpuobj_del(dev, &obj); + return ret; + } + + dev_priv->engine.instmem.prepare_access(dev, true); + nv_wo32(dev, obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); + nv_wo32(dev, obj, 1, limit); + nv_wo32(dev, obj, 2, offset); + nv_wo32(dev, obj, 3, 0x00000000); + nv_wo32(dev, obj, 4, 0x00000000); + nv_wo32(dev, obj, 5, 0x00010000); + dev_priv->engine.instmem.finish_access(dev); + + return 0; +} + +static int +nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan; + int ret; + + chan = kzalloc(sizeof(struct nouveau_channel), GFP_KERNEL); + if (!chan) + return -ENOMEM; + *pchan = chan; + + chan->id = -1; + chan->dev = dev; + chan->user_get = 4; + chan->user_put = 0; + + INIT_LIST_HEAD(&chan->ramht_refs); + + ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 32768, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin); + if (ret) { + NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); + nv50_evo_channel_del(pchan); + return ret; + } + + ret = nouveau_mem_init_heap(&chan->ramin_heap, chan->ramin->gpuobj-> + im_pramin->start, 32768); + if (ret) { + NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); + nv50_evo_channel_del(pchan); + return ret; + } + + ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 4096, 16, + 0, &chan->ramht); + if (ret) { + NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); + nv50_evo_channel_del(pchan); + return ret; + } + + if (dev_priv->chipset != 0x50) { + ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB16, 0x70, 0x19, + 0, 0xffffffff); + if (ret) { + nv50_evo_channel_del(pchan); + return ret; + } + + + ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB32, 0x7a, 0x19, + 0, 0xffffffff); + if (ret) { + nv50_evo_channel_del(pchan); + return ret; + } + } + + ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoVRAM, 0, 0x19, + 0, nouveau_mem_fb_amount(dev)); + if (ret) { + nv50_evo_channel_del(pchan); + return ret; + } + + ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, + false, true, &chan->pushbuf_bo); + if (ret == 0) + ret = nouveau_bo_pin(chan->pushbuf_bo, TTM_PL_FLAG_VRAM); + if (ret) { + NV_ERROR(dev, "Error creating EVO DMA push buffer: %d\n", ret); + nv50_evo_channel_del(pchan); + return ret; + } + + ret = nouveau_bo_map(chan->pushbuf_bo); + if (ret) { + NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret); + nv50_evo_channel_del(pchan); + return ret; + } + + chan->user = ioremap(pci_resource_start(dev->pdev, 0) + + NV50_PDISPLAY_USER(0), PAGE_SIZE); + if (!chan->user) { + NV_ERROR(dev, "Error mapping EVO control regs.\n"); + nv50_evo_channel_del(pchan); + return -ENOMEM; + } + + return 0; +} + +int +nv50_display_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; + struct nouveau_channel *evo = dev_priv->evo; + struct drm_connector *connector; + uint32_t val, ram_amount, hpd_en[2]; + uint64_t start; + int ret, i; + + NV_DEBUG(dev, "\n"); + + nv_wr32(dev, 0x00610184, nv_rd32(dev, 0x00614004)); + /* + * I think the 0x006101XX range is some kind of main control area + * that enables things. + */ + /* CRTC? */ + for (i = 0; i < 2; i++) { + val = nv_rd32(dev, 0x00616100 + (i * 0x800)); + nv_wr32(dev, 0x00610190 + (i * 0x10), val); + val = nv_rd32(dev, 0x00616104 + (i * 0x800)); + nv_wr32(dev, 0x00610194 + (i * 0x10), val); + val = nv_rd32(dev, 0x00616108 + (i * 0x800)); + nv_wr32(dev, 0x00610198 + (i * 0x10), val); + val = nv_rd32(dev, 0x0061610c + (i * 0x800)); + nv_wr32(dev, 0x0061019c + (i * 0x10), val); + } + /* DAC */ + for (i = 0; i < 3; i++) { + val = nv_rd32(dev, 0x0061a000 + (i * 0x800)); + nv_wr32(dev, 0x006101d0 + (i * 0x04), val); + } + /* SOR */ + for (i = 0; i < 4; i++) { + val = nv_rd32(dev, 0x0061c000 + (i * 0x800)); + nv_wr32(dev, 0x006101e0 + (i * 0x04), val); + } + /* Something not yet in use, tv-out maybe. */ + for (i = 0; i < 3; i++) { + val = nv_rd32(dev, 0x0061e000 + (i * 0x800)); + nv_wr32(dev, 0x006101f0 + (i * 0x04), val); + } + + for (i = 0; i < 3; i++) { + nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(i), 0x00550000 | + NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); + nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(i), 0x00000001); + } + + /* This used to be in crtc unblank, but seems out of place there. */ + nv_wr32(dev, NV50_PDISPLAY_UNK_380, 0); + /* RAM is clamped to 256 MiB. */ + ram_amount = nouveau_mem_fb_amount(dev); + NV_DEBUG(dev, "ram_amount %d\n", ram_amount); + if (ram_amount > 256*1024*1024) + ram_amount = 256*1024*1024; + nv_wr32(dev, NV50_PDISPLAY_RAM_AMOUNT, ram_amount - 1); + nv_wr32(dev, NV50_PDISPLAY_UNK_388, 0x150000); + nv_wr32(dev, NV50_PDISPLAY_UNK_38C, 0); + + /* The precise purpose is unknown, i suspect it has something to do + * with text mode. + */ + if (nv_rd32(dev, NV50_PDISPLAY_INTR_1) & 0x100) { + nv_wr32(dev, NV50_PDISPLAY_INTR_1, 0x100); + nv_wr32(dev, 0x006194e8, nv_rd32(dev, 0x006194e8) & ~1); + if (!nv_wait(0x006194e8, 2, 0)) { + NV_ERROR(dev, "timeout: (0x6194e8 & 2) != 0\n"); + NV_ERROR(dev, "0x6194e8 = 0x%08x\n", + nv_rd32(dev, 0x6194e8)); + return -EBUSY; + } + } + + /* taken from nv bug #12637, attempts to un-wedge the hw if it's + * stuck in some unspecified state + */ + start = ptimer->read(dev); + nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x2b00); + while ((val = nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))) & 0x1e0000) { + if ((val & 0x9f0000) == 0x20000) + nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), + val | 0x800000); + + if ((val & 0x3f0000) == 0x30000) + nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), + val | 0x200000); + + if (ptimer->read(dev) - start > 1000000000ULL) { + NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) != 0\n"); + NV_ERROR(dev, "0x610200 = 0x%08x\n", val); + return -EBUSY; + } + } + + nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, NV50_PDISPLAY_CTRL_STATE_ENABLE); + nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1000b03); + if (!nv_wait(NV50_PDISPLAY_CHANNEL_STAT(0), 0x40000000, 0x40000000)) { + NV_ERROR(dev, "timeout: (0x610200 & 0x40000000) == 0x40000000\n"); + NV_ERROR(dev, "0x610200 = 0x%08x\n", + nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); + return -EBUSY; + } + + for (i = 0; i < 2; i++) { + nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000); + if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), + NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { + NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); + NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", + nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); + return -EBUSY; + } + + nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), + NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON); + if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), + NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, + NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE)) { + NV_ERROR(dev, "timeout: " + "CURSOR_CTRL2_STATUS_ACTIVE(%d)\n", i); + NV_ERROR(dev, "CURSOR_CTRL2(%d) = 0x%08x\n", i, + nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); + return -EBUSY; + } + } + + nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->instance >> 8) | 9); + + /* initialise fifo */ + nv_wr32(dev, NV50_PDISPLAY_CHANNEL_DMA_CB(0), + ((evo->pushbuf_bo->bo.mem.mm_node->start << PAGE_SHIFT) >> 8) | + NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM | + NV50_PDISPLAY_CHANNEL_DMA_CB_VALID); + nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK2(0), 0x00010000); + nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK3(0), 0x00000002); + if (!nv_wait(0x610200, 0x80000000, 0x00000000)) { + NV_ERROR(dev, "timeout: (0x610200 & 0x80000000) == 0\n"); + NV_ERROR(dev, "0x610200 = 0x%08x\n", nv_rd32(dev, 0x610200)); + return -EBUSY; + } + nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), + (nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0)) & ~0x00000003) | + NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED); + nv_wr32(dev, NV50_PDISPLAY_USER_PUT(0), 0); + nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x01000003 | + NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED); + nv_wr32(dev, 0x610300, nv_rd32(dev, 0x610300) & ~1); + + evo->dma.max = (4096/4) - 2; + evo->dma.put = 0; + evo->dma.cur = evo->dma.put; + evo->dma.free = evo->dma.max - evo->dma.cur; + + ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS); + if (ret) + return ret; + + for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) + OUT_RING(evo, 0); + + ret = RING_SPACE(evo, 11); + if (ret) + return ret; + BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2); + OUT_RING(evo, NV50_EVO_UNK84_NOTIFY_DISABLED); + OUT_RING(evo, NV50_EVO_DMA_NOTIFY_HANDLE_NONE); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, FB_DMA), 1); + OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK0800), 1); + OUT_RING(evo, 0); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, DISPLAY_START), 1); + OUT_RING(evo, 0); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1); + OUT_RING(evo, 0); + FIRE_RING(evo); + if (!nv_wait(0x640004, 0xffffffff, evo->dma.put << 2)) + NV_ERROR(dev, "evo pushbuf stalled\n"); + + /* enable clock change interrupts. */ + nv_wr32(dev, 0x610028, 0x00010001); + nv_wr32(dev, NV50_PDISPLAY_INTR_EN, (NV50_PDISPLAY_INTR_EN_CLK_UNK10 | + NV50_PDISPLAY_INTR_EN_CLK_UNK20 | + NV50_PDISPLAY_INTR_EN_CLK_UNK40)); + + /* enable hotplug interrupts */ + hpd_en[0] = hpd_en[1] = 0; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct nouveau_connector *conn = nouveau_connector(connector); + struct dcb_gpio_entry *gpio; + + if (connector->connector_type != DRM_MODE_CONNECTOR_DVII && + connector->connector_type != DRM_MODE_CONNECTOR_DVID && + connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) + continue; + + gpio = nouveau_bios_gpio_entry(dev, conn->dcb->gpio_tag); + if (!gpio) + continue; + + hpd_en[gpio->line >> 4] |= (0x00010001 << (gpio->line & 0xf)); + } + + nv_wr32(dev, 0xe054, 0xffffffff); + nv_wr32(dev, 0xe050, hpd_en[0]); + if (dev_priv->chipset >= 0x90) { + nv_wr32(dev, 0xe074, 0xffffffff); + nv_wr32(dev, 0xe070, hpd_en[1]); + } + + return 0; +} + +static int nv50_display_disable(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_crtc *drm_crtc; + int ret, i; + + NV_DEBUG(dev, "\n"); + + list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_crtc *crtc = nouveau_crtc(drm_crtc); + + nv50_crtc_blank(crtc, true); + } + + ret = RING_SPACE(dev_priv->evo, 2); + if (ret == 0) { + BEGIN_RING(dev_priv->evo, 0, NV50_EVO_UPDATE, 1); + OUT_RING(dev_priv->evo, 0); + } + FIRE_RING(dev_priv->evo); + + /* Almost like ack'ing a vblank interrupt, maybe in the spirit of + * cleaning up? + */ + list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_crtc *crtc = nouveau_crtc(drm_crtc); + uint32_t mask = NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(crtc->index); + + if (!crtc->base.enabled) + continue; + + nv_wr32(dev, NV50_PDISPLAY_INTR_1, mask); + if (!nv_wait(NV50_PDISPLAY_INTR_1, mask, mask)) { + NV_ERROR(dev, "timeout: (0x610024 & 0x%08x) == " + "0x%08x\n", mask, mask); + NV_ERROR(dev, "0x610024 = 0x%08x\n", + nv_rd32(dev, NV50_PDISPLAY_INTR_1)); + } + } + + nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0); + nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, 0); + if (!nv_wait(NV50_PDISPLAY_CHANNEL_STAT(0), 0x1e0000, 0)) { + NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) == 0\n"); + NV_ERROR(dev, "0x610200 = 0x%08x\n", + nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); + } + + for (i = 0; i < 3; i++) { + if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_STATE(i), + NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { + NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", i); + NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", i, + nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(i))); + } + } + + /* disable interrupts. */ + nv_wr32(dev, NV50_PDISPLAY_INTR_EN, 0x00000000); + + /* disable hotplug interrupts */ + nv_wr32(dev, 0xe054, 0xffffffff); + nv_wr32(dev, 0xe050, 0x00000000); + if (dev_priv->chipset >= 0x90) { + nv_wr32(dev, 0xe074, 0xffffffff); + nv_wr32(dev, 0xe070, 0x00000000); + } + return 0; +} + +int nv50_display_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct parsed_dcb *dcb = dev_priv->vbios->dcb; + uint32_t connector[16] = {}; + int ret, i; + + NV_DEBUG(dev, "\n"); + + /* init basic kernel modesetting */ + drm_mode_config_init(dev); + + /* Initialise some optional connector properties. */ + drm_mode_create_scaling_mode_property(dev); + drm_mode_create_dithering_property(dev); + + dev->mode_config.min_width = 0; + dev->mode_config.min_height = 0; + + dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; + + dev->mode_config.max_width = 8192; + dev->mode_config.max_height = 8192; + + dev->mode_config.fb_base = dev_priv->fb_phys; + + /* Create EVO channel */ + ret = nv50_evo_channel_new(dev, &dev_priv->evo); + if (ret) { + NV_ERROR(dev, "Error creating EVO channel: %d\n", ret); + return ret; + } + + /* Create CRTC objects */ + for (i = 0; i < 2; i++) + nv50_crtc_create(dev, i); + + /* We setup the encoders from the BIOS table */ + for (i = 0 ; i < dcb->entries; i++) { + struct dcb_entry *entry = &dcb->entry[i]; + + if (entry->location != DCB_LOC_ON_CHIP) { + NV_WARN(dev, "Off-chip encoder %d/%d unsupported\n", + entry->type, ffs(entry->or) - 1); + continue; + } + + switch (entry->type) { + case OUTPUT_TMDS: + case OUTPUT_LVDS: + case OUTPUT_DP: + nv50_sor_create(dev, entry); + break; + case OUTPUT_ANALOG: + nv50_dac_create(dev, entry); + break; + default: + NV_WARN(dev, "DCB encoder %d unknown\n", entry->type); + continue; + } + + connector[entry->connector] |= (1 << entry->type); + } + + /* It appears that DCB 3.0+ VBIOS has a connector table, however, + * I'm not 100% certain how to decode it correctly yet so just + * look at what encoders are present on each connector index and + * attempt to derive the connector type from that. + */ + for (i = 0 ; i < dcb->entries; i++) { + struct dcb_entry *entry = &dcb->entry[i]; + uint16_t encoders; + int type; + + encoders = connector[entry->connector]; + if (!(encoders & (1 << entry->type))) + continue; + connector[entry->connector] = 0; + + if (encoders & (1 << OUTPUT_DP)) { + type = DRM_MODE_CONNECTOR_DisplayPort; + } else if (encoders & (1 << OUTPUT_TMDS)) { + if (encoders & (1 << OUTPUT_ANALOG)) + type = DRM_MODE_CONNECTOR_DVII; + else + type = DRM_MODE_CONNECTOR_DVID; + } else if (encoders & (1 << OUTPUT_ANALOG)) { + type = DRM_MODE_CONNECTOR_VGA; + } else if (encoders & (1 << OUTPUT_LVDS)) { + type = DRM_MODE_CONNECTOR_LVDS; + } else { + type = DRM_MODE_CONNECTOR_Unknown; + } + + if (type == DRM_MODE_CONNECTOR_Unknown) + continue; + + nouveau_connector_create(dev, entry->connector, type); + } + + ret = nv50_display_init(dev); + if (ret) + return ret; + + return 0; +} + +int nv50_display_destroy(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + NV_DEBUG(dev, "\n"); + + drm_mode_config_cleanup(dev); + + nv50_display_disable(dev); + nv50_evo_channel_del(&dev_priv->evo); + + return 0; +} + +static inline uint32_t +nv50_display_mode_ctrl(struct drm_device *dev, bool sor, int or) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t mc; + + if (sor) { + if (dev_priv->chipset < 0x90 || + dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0) + mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_P(or)); + else + mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_P(or)); + } else { + mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_P(or)); + } + + return mc; +} + +static int +nv50_display_irq_head(struct drm_device *dev, int *phead, + struct dcb_entry **pdcbent) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t unk30 = nv_rd32(dev, NV50_PDISPLAY_UNK30_CTRL); + uint32_t dac = 0, sor = 0; + int head, i, or = 0, type = OUTPUT_ANY; + + /* We're assuming that head 0 *or* head 1 will be active here, + * and not both. I'm not sure if the hw will even signal both + * ever, but it definitely shouldn't for us as we commit each + * CRTC separately, and submission will be blocked by the GPU + * until we handle each in turn. + */ + NV_DEBUG(dev, "0x610030: 0x%08x\n", unk30); + head = ffs((unk30 >> 9) & 3) - 1; + if (head < 0) + return -EINVAL; + + /* This assumes CRTCs are never bound to multiple encoders, which + * should be the case. + */ + for (i = 0; i < 3 && type == OUTPUT_ANY; i++) { + uint32_t mc = nv50_display_mode_ctrl(dev, false, i); + if (!(mc & (1 << head))) + continue; + + switch ((mc >> 8) & 0xf) { + case 0: type = OUTPUT_ANALOG; break; + case 1: type = OUTPUT_TV; break; + default: + NV_ERROR(dev, "unknown dac mode_ctrl: 0x%08x\n", dac); + return -1; + } + + or = i; + } + + for (i = 0; i < 4 && type == OUTPUT_ANY; i++) { + uint32_t mc = nv50_display_mode_ctrl(dev, true, i); + if (!(mc & (1 << head))) + continue; + + switch ((mc >> 8) & 0xf) { + case 0: type = OUTPUT_LVDS; break; + case 1: type = OUTPUT_TMDS; break; + case 2: type = OUTPUT_TMDS; break; + case 5: type = OUTPUT_TMDS; break; + case 8: type = OUTPUT_DP; break; + case 9: type = OUTPUT_DP; break; + default: + NV_ERROR(dev, "unknown sor mode_ctrl: 0x%08x\n", sor); + return -1; + } + + or = i; + } + + NV_DEBUG(dev, "type %d, or %d\n", type, or); + if (type == OUTPUT_ANY) { + NV_ERROR(dev, "unknown encoder!!\n"); + return -1; + } + + for (i = 0; i < dev_priv->vbios->dcb->entries; i++) { + struct dcb_entry *dcbent = &dev_priv->vbios->dcb->entry[i]; + + if (dcbent->type != type) + continue; + + if (!(dcbent->or & (1 << or))) + continue; + + *phead = head; + *pdcbent = dcbent; + return 0; + } + + NV_ERROR(dev, "no DCB entry for %d %d\n", dac != 0, or); + return 0; +} + +static uint32_t +nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent, + int pxclk) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->VBIOS; + uint32_t mc, script = 0, or; + + or = ffs(dcbent->or) - 1; + mc = nv50_display_mode_ctrl(dev, dcbent->type != OUTPUT_ANALOG, or); + switch (dcbent->type) { + case OUTPUT_LVDS: + script = (mc >> 8) & 0xf; + if (bios->pub.fp_no_ddc) { + if (bios->fp.dual_link) + script |= 0x0100; + if (bios->fp.if_is_24bit) + script |= 0x0200; + } else { + if (pxclk >= bios->fp.duallink_transition_clk) { + script |= 0x0100; + if (bios->fp.strapless_is_24bit & 2) + script |= 0x0200; + } else + if (bios->fp.strapless_is_24bit & 1) + script |= 0x0200; + } + + if (nouveau_uscript_lvds >= 0) { + NV_INFO(dev, "override script 0x%04x with 0x%04x " + "for output LVDS-%d\n", script, + nouveau_uscript_lvds, or); + script = nouveau_uscript_lvds; + } + break; + case OUTPUT_TMDS: + script = (mc >> 8) & 0xf; + if (pxclk >= 165000) + script |= 0x0100; + + if (nouveau_uscript_tmds >= 0) { + NV_INFO(dev, "override script 0x%04x with 0x%04x " + "for output TMDS-%d\n", script, + nouveau_uscript_tmds, or); + script = nouveau_uscript_tmds; + } + break; + case OUTPUT_DP: + script = (mc >> 8) & 0xf; + break; + case OUTPUT_ANALOG: + script = 0xff; + break; + default: + NV_ERROR(dev, "modeset on unsupported output type!\n"); + break; + } + + return script; +} + +static void +nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan; + struct list_head *entry, *tmp; + + list_for_each_safe(entry, tmp, &dev_priv->vbl_waiting) { + chan = list_entry(entry, struct nouveau_channel, nvsw.vbl_wait); + + nouveau_bo_wr32(chan->notifier_bo, chan->nvsw.vblsem_offset, + chan->nvsw.vblsem_rval); + list_del(&chan->nvsw.vbl_wait); + } +} + +static void +nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr) +{ + intr &= NV50_PDISPLAY_INTR_1_VBLANK_CRTC; + + if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_0) + nv50_display_vblank_crtc_handler(dev, 0); + + if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_1) + nv50_display_vblank_crtc_handler(dev, 1); + + nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev, + NV50_PDISPLAY_INTR_EN) & ~intr); + nv_wr32(dev, NV50_PDISPLAY_INTR_1, intr); +} + +static void +nv50_display_unk10_handler(struct drm_device *dev) +{ + struct dcb_entry *dcbent; + int head, ret; + + ret = nv50_display_irq_head(dev, &head, &dcbent); + if (ret) + goto ack; + + nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8); + + nouveau_bios_run_display_table(dev, dcbent, 0, -1); + +ack: + nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK10); + nv_wr32(dev, 0x610030, 0x80000000); +} + +static void +nv50_display_unk20_handler(struct drm_device *dev) +{ + struct dcb_entry *dcbent; + uint32_t tmp, pclk, script; + int head, or, ret; + + ret = nv50_display_irq_head(dev, &head, &dcbent); + if (ret) + goto ack; + or = ffs(dcbent->or) - 1; + pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff; + script = nv50_display_script_select(dev, dcbent, pclk); + + NV_DEBUG(dev, "head %d pxclk: %dKHz\n", head, pclk); + + if (dcbent->type != OUTPUT_DP) + nouveau_bios_run_display_table(dev, dcbent, 0, -2); + + nv50_crtc_set_clock(dev, head, pclk); + + nouveau_bios_run_display_table(dev, dcbent, script, pclk); + + tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head)); + tmp &= ~0x000000f; + nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head), tmp); + + if (dcbent->type != OUTPUT_ANALOG) { + tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or)); + tmp &= ~0x00000f0f; + if (script & 0x0100) + tmp |= 0x00000101; + nv_wr32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or), tmp); + } else { + nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); + } + +ack: + nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); + nv_wr32(dev, 0x610030, 0x80000000); +} + +static void +nv50_display_unk40_handler(struct drm_device *dev) +{ + struct dcb_entry *dcbent; + int head, pclk, script, ret; + + ret = nv50_display_irq_head(dev, &head, &dcbent); + if (ret) + goto ack; + pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff; + script = nv50_display_script_select(dev, dcbent, pclk); + + nouveau_bios_run_display_table(dev, dcbent, script, -pclk); + +ack: + nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK40); + nv_wr32(dev, 0x610030, 0x80000000); + nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) | 8); +} + +void +nv50_display_irq_handler_bh(struct work_struct *work) +{ + struct drm_nouveau_private *dev_priv = + container_of(work, struct drm_nouveau_private, irq_work); + struct drm_device *dev = dev_priv->dev; + + for (;;) { + uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); + uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1); + + NV_DEBUG(dev, "PDISPLAY_INTR_BH 0x%08x 0x%08x\n", intr0, intr1); + + if (intr1 & NV50_PDISPLAY_INTR_1_CLK_UNK10) + nv50_display_unk10_handler(dev); + else + if (intr1 & NV50_PDISPLAY_INTR_1_CLK_UNK20) + nv50_display_unk20_handler(dev); + else + if (intr1 & NV50_PDISPLAY_INTR_1_CLK_UNK40) + nv50_display_unk40_handler(dev); + else + break; + } + + nv_wr32(dev, NV03_PMC_INTR_EN_0, 1); +} + +static void +nv50_display_error_handler(struct drm_device *dev) +{ + uint32_t addr, data; + + nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000); + addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR); + data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA); + + NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x (0x%04x 0x%02x)\n", + 0, addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf); + + nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000); +} + +static void +nv50_display_irq_hotplug(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_connector *connector; + const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; + uint32_t unplug_mask, plug_mask, change_mask; + uint32_t hpd0, hpd1 = 0; + + hpd0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); + if (dev_priv->chipset >= 0x90) + hpd1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); + + plug_mask = (hpd0 & 0x0000ffff) | (hpd1 << 16); + unplug_mask = (hpd0 >> 16) | (hpd1 & 0xffff0000); + change_mask = plug_mask | unplug_mask; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct drm_encoder_helper_funcs *helper; + struct nouveau_connector *nv_connector = + nouveau_connector(connector); + struct nouveau_encoder *nv_encoder; + struct dcb_gpio_entry *gpio; + uint32_t reg; + bool plugged; + + if (!nv_connector->dcb) + continue; + + gpio = nouveau_bios_gpio_entry(dev, nv_connector->dcb->gpio_tag); + if (!gpio || !(change_mask & (1 << gpio->line))) + continue; + + reg = nv_rd32(dev, gpio_reg[gpio->line >> 3]); + plugged = !!(reg & (4 << ((gpio->line & 7) << 2))); + NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un", + drm_get_connector_name(connector)) ; + + if (!connector->encoder || !connector->encoder->crtc || + !connector->encoder->crtc->enabled) + continue; + nv_encoder = nouveau_encoder(connector->encoder); + helper = connector->encoder->helper_private; + + if (nv_encoder->dcb->type != OUTPUT_DP) + continue; + + if (plugged) + helper->dpms(connector->encoder, DRM_MODE_DPMS_ON); + else + helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF); + } + + nv_wr32(dev, 0xe054, nv_rd32(dev, 0xe054)); + if (dev_priv->chipset >= 0x90) + nv_wr32(dev, 0xe074, nv_rd32(dev, 0xe074)); +} + +void +nv50_display_irq_handler(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t delayed = 0; + + while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) + nv50_display_irq_hotplug(dev); + + while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { + uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); + uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1); + uint32_t clock; + + NV_DEBUG(dev, "PDISPLAY_INTR 0x%08x 0x%08x\n", intr0, intr1); + + if (!intr0 && !(intr1 & ~delayed)) + break; + + if (intr0 & 0x00010000) { + nv50_display_error_handler(dev); + intr0 &= ~0x00010000; + } + + if (intr1 & NV50_PDISPLAY_INTR_1_VBLANK_CRTC) { + nv50_display_vblank_handler(dev, intr1); + intr1 &= ~NV50_PDISPLAY_INTR_1_VBLANK_CRTC; + } + + clock = (intr1 & (NV50_PDISPLAY_INTR_1_CLK_UNK10 | + NV50_PDISPLAY_INTR_1_CLK_UNK20 | + NV50_PDISPLAY_INTR_1_CLK_UNK40)); + if (clock) { + nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); + if (!work_pending(&dev_priv->irq_work)) + queue_work(dev_priv->wq, &dev_priv->irq_work); + delayed |= clock; + intr1 &= ~clock; + } + + if (intr0) { + NV_ERROR(dev, "unknown PDISPLAY_INTR_0: 0x%08x\n", intr0); + nv_wr32(dev, NV50_PDISPLAY_INTR_0, intr0); + } + + if (intr1) { + NV_ERROR(dev, + "unknown PDISPLAY_INTR_1: 0x%08x\n", intr1); + nv_wr32(dev, NV50_PDISPLAY_INTR_1, intr1); + } + } +} + diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h new file mode 100644 index 0000000000000000000000000000000000000000..3ae8d0725f635d8b41b0e797f5b1b30f4c7a79d5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_display.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2008 Maarten Maathuis. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +#ifndef __NV50_DISPLAY_H__ +#define __NV50_DISPLAY_H__ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_dma.h" +#include "nouveau_reg.h" +#include "nouveau_crtc.h" +#include "nv50_evo.h" + +void nv50_display_irq_handler(struct drm_device *dev); +void nv50_display_irq_handler_bh(struct work_struct *work); +int nv50_display_init(struct drm_device *dev); +int nv50_display_create(struct drm_device *dev); +int nv50_display_destroy(struct drm_device *dev); +int nv50_crtc_blank(struct nouveau_crtc *, bool blank); +int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); + +#endif /* __NV50_DISPLAY_H__ */ diff --git a/drivers/gpu/drm/nouveau/nv50_evo.h b/drivers/gpu/drm/nouveau/nv50_evo.h new file mode 100644 index 0000000000000000000000000000000000000000..aae13343bcec92582e8e5de70a3395b7cdc29de9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_evo.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2008 Maarten Maathuis. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +#define NV50_EVO_UPDATE 0x00000080 +#define NV50_EVO_UNK84 0x00000084 +#define NV50_EVO_UNK84_NOTIFY 0x40000000 +#define NV50_EVO_UNK84_NOTIFY_DISABLED 0x00000000 +#define NV50_EVO_UNK84_NOTIFY_ENABLED 0x40000000 +#define NV50_EVO_DMA_NOTIFY 0x00000088 +#define NV50_EVO_DMA_NOTIFY_HANDLE 0xffffffff +#define NV50_EVO_DMA_NOTIFY_HANDLE_NONE 0x00000000 +#define NV50_EVO_UNK8C 0x0000008C + +#define NV50_EVO_DAC(n, r) ((n) * 0x80 + NV50_EVO_DAC_##r) +#define NV50_EVO_DAC_MODE_CTRL 0x00000400 +#define NV50_EVO_DAC_MODE_CTRL_CRTC0 0x00000001 +#define NV50_EVO_DAC_MODE_CTRL_CRTC1 0x00000002 +#define NV50_EVO_DAC_MODE_CTRL2 0x00000404 +#define NV50_EVO_DAC_MODE_CTRL2_NHSYNC 0x00000001 +#define NV50_EVO_DAC_MODE_CTRL2_NVSYNC 0x00000002 + +#define NV50_EVO_SOR(n, r) ((n) * 0x40 + NV50_EVO_SOR_##r) +#define NV50_EVO_SOR_MODE_CTRL 0x00000600 +#define NV50_EVO_SOR_MODE_CTRL_CRTC0 0x00000001 +#define NV50_EVO_SOR_MODE_CTRL_CRTC1 0x00000002 +#define NV50_EVO_SOR_MODE_CTRL_TMDS 0x00000100 +#define NV50_EVO_SOR_MODE_CTRL_TMDS_DUAL_LINK 0x00000400 +#define NV50_EVO_SOR_MODE_CTRL_NHSYNC 0x00001000 +#define NV50_EVO_SOR_MODE_CTRL_NVSYNC 0x00002000 + +#define NV50_EVO_CRTC(n, r) ((n) * 0x400 + NV50_EVO_CRTC_##r) +#define NV84_EVO_CRTC(n, r) ((n) * 0x400 + NV84_EVO_CRTC_##r) +#define NV50_EVO_CRTC_UNK0800 0x00000800 +#define NV50_EVO_CRTC_CLOCK 0x00000804 +#define NV50_EVO_CRTC_INTERLACE 0x00000808 +#define NV50_EVO_CRTC_DISPLAY_START 0x00000810 +#define NV50_EVO_CRTC_DISPLAY_TOTAL 0x00000814 +#define NV50_EVO_CRTC_SYNC_DURATION 0x00000818 +#define NV50_EVO_CRTC_SYNC_START_TO_BLANK_END 0x0000081c +#define NV50_EVO_CRTC_UNK0820 0x00000820 +#define NV50_EVO_CRTC_UNK0824 0x00000824 +#define NV50_EVO_CRTC_UNK082C 0x0000082c +#define NV50_EVO_CRTC_CLUT_MODE 0x00000840 +/* You can't have a palette in 8 bit mode (=OFF) */ +#define NV50_EVO_CRTC_CLUT_MODE_BLANK 0x00000000 +#define NV50_EVO_CRTC_CLUT_MODE_OFF 0x80000000 +#define NV50_EVO_CRTC_CLUT_MODE_ON 0xC0000000 +#define NV50_EVO_CRTC_CLUT_OFFSET 0x00000844 +#define NV84_EVO_CRTC_CLUT_DMA 0x0000085C +#define NV84_EVO_CRTC_CLUT_DMA_HANDLE 0xffffffff +#define NV84_EVO_CRTC_CLUT_DMA_HANDLE_NONE 0x00000000 +#define NV50_EVO_CRTC_FB_OFFSET 0x00000860 +#define NV50_EVO_CRTC_FB_SIZE 0x00000868 +#define NV50_EVO_CRTC_FB_CONFIG 0x0000086c +#define NV50_EVO_CRTC_FB_CONFIG_MODE 0x00100000 +#define NV50_EVO_CRTC_FB_CONFIG_MODE_TILE 0x00000000 +#define NV50_EVO_CRTC_FB_CONFIG_MODE_PITCH 0x00100000 +#define NV50_EVO_CRTC_FB_DEPTH 0x00000870 +#define NV50_EVO_CRTC_FB_DEPTH_8 0x00001e00 +#define NV50_EVO_CRTC_FB_DEPTH_15 0x0000e900 +#define NV50_EVO_CRTC_FB_DEPTH_16 0x0000e800 +#define NV50_EVO_CRTC_FB_DEPTH_24 0x0000cf00 +#define NV50_EVO_CRTC_FB_DEPTH_30 0x0000d100 +#define NV50_EVO_CRTC_FB_DMA 0x00000874 +#define NV50_EVO_CRTC_FB_DMA_HANDLE 0xffffffff +#define NV50_EVO_CRTC_FB_DMA_HANDLE_NONE 0x00000000 +#define NV50_EVO_CRTC_CURSOR_CTRL 0x00000880 +#define NV50_EVO_CRTC_CURSOR_CTRL_HIDE 0x05000000 +#define NV50_EVO_CRTC_CURSOR_CTRL_SHOW 0x85000000 +#define NV50_EVO_CRTC_CURSOR_OFFSET 0x00000884 +#define NV84_EVO_CRTC_CURSOR_DMA 0x0000089c +#define NV84_EVO_CRTC_CURSOR_DMA_HANDLE 0xffffffff +#define NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE 0x00000000 +#define NV50_EVO_CRTC_DITHER_CTRL 0x000008a0 +#define NV50_EVO_CRTC_DITHER_CTRL_OFF 0x00000000 +#define NV50_EVO_CRTC_DITHER_CTRL_ON 0x00000011 +#define NV50_EVO_CRTC_SCALE_CTRL 0x000008a4 +#define NV50_EVO_CRTC_SCALE_CTRL_INACTIVE 0x00000000 +#define NV50_EVO_CRTC_SCALE_CTRL_ACTIVE 0x00000009 +#define NV50_EVO_CRTC_COLOR_CTRL 0x000008a8 +#define NV50_EVO_CRTC_COLOR_CTRL_COLOR 0x00040000 +#define NV50_EVO_CRTC_FB_POS 0x000008c0 +#define NV50_EVO_CRTC_REAL_RES 0x000008c8 +#define NV50_EVO_CRTC_SCALE_CENTER_OFFSET 0x000008d4 +#define NV50_EVO_CRTC_SCALE_CENTER_OFFSET_VAL(x, y) \ + ((((unsigned)y << 16) & 0xFFFF0000) | (((unsigned)x) & 0x0000FFFF)) +/* Both of these are needed, otherwise nothing happens. */ +#define NV50_EVO_CRTC_SCALE_RES1 0x000008d8 +#define NV50_EVO_CRTC_SCALE_RES2 0x000008dc + diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c new file mode 100644 index 0000000000000000000000000000000000000000..6bcc6d39e9b0bac9560b2e424c73f884bcb4b5c7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c @@ -0,0 +1,273 @@ +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_dma.h" +#include "nouveau_fbcon.h" + +static void +nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +{ + struct nouveau_fbcon_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->channel; + + if (info->state != FBINFO_STATE_RUNNING) + return; + + if (!(info->flags & FBINFO_HWACCEL_DISABLED) && + RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11)) { + NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + + info->flags |= FBINFO_HWACCEL_DISABLED; + } + + if (info->flags & FBINFO_HWACCEL_DISABLED) { + cfb_fillrect(info, rect); + return; + } + + if (rect->rop != ROP_COPY) { + BEGIN_RING(chan, NvSub2D, 0x02ac, 1); + OUT_RING(chan, 1); + } + BEGIN_RING(chan, NvSub2D, 0x0588, 1); + OUT_RING(chan, rect->color); + BEGIN_RING(chan, NvSub2D, 0x0600, 4); + OUT_RING(chan, rect->dx); + OUT_RING(chan, rect->dy); + OUT_RING(chan, rect->dx + rect->width); + OUT_RING(chan, rect->dy + rect->height); + if (rect->rop != ROP_COPY) { + BEGIN_RING(chan, NvSub2D, 0x02ac, 1); + OUT_RING(chan, 3); + } + FIRE_RING(chan); +} + +static void +nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) +{ + struct nouveau_fbcon_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->channel; + + if (info->state != FBINFO_STATE_RUNNING) + return; + + if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 12)) { + NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + + info->flags |= FBINFO_HWACCEL_DISABLED; + } + + if (info->flags & FBINFO_HWACCEL_DISABLED) { + cfb_copyarea(info, region); + return; + } + + BEGIN_RING(chan, NvSub2D, 0x0110, 1); + OUT_RING(chan, 0); + BEGIN_RING(chan, NvSub2D, 0x08b0, 4); + OUT_RING(chan, region->dx); + OUT_RING(chan, region->dy); + OUT_RING(chan, region->width); + OUT_RING(chan, region->height); + BEGIN_RING(chan, NvSub2D, 0x08d0, 4); + OUT_RING(chan, 0); + OUT_RING(chan, region->sx); + OUT_RING(chan, 0); + OUT_RING(chan, region->sy); + FIRE_RING(chan); +} + +static void +nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) +{ + struct nouveau_fbcon_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->channel; + uint32_t width, dwords, *data = (uint32_t *)image->data; + uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); + uint32_t *palette = info->pseudo_palette; + + if (info->state != FBINFO_STATE_RUNNING) + return; + + if (image->depth != 1) { + cfb_imageblit(info, image); + return; + } + + if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 11)) { + NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + info->flags |= FBINFO_HWACCEL_DISABLED; + } + + if (info->flags & FBINFO_HWACCEL_DISABLED) { + cfb_imageblit(info, image); + return; + } + + width = (image->width + 31) & ~31; + dwords = (width * image->height) >> 5; + + BEGIN_RING(chan, NvSub2D, 0x0814, 2); + if (info->fix.visual == FB_VISUAL_TRUECOLOR || + info->fix.visual == FB_VISUAL_DIRECTCOLOR) { + OUT_RING(chan, palette[image->bg_color] | mask); + OUT_RING(chan, palette[image->fg_color] | mask); + } else { + OUT_RING(chan, image->bg_color); + OUT_RING(chan, image->fg_color); + } + BEGIN_RING(chan, NvSub2D, 0x0838, 2); + OUT_RING(chan, image->width); + OUT_RING(chan, image->height); + BEGIN_RING(chan, NvSub2D, 0x0850, 4); + OUT_RING(chan, 0); + OUT_RING(chan, image->dx); + OUT_RING(chan, 0); + OUT_RING(chan, image->dy); + + while (dwords) { + int push = dwords > 2047 ? 2047 : dwords; + + if (RING_SPACE(chan, push + 1)) { + NV_ERROR(dev, + "GPU lockup - switching to software fbcon\n"); + info->flags |= FBINFO_HWACCEL_DISABLED; + cfb_imageblit(info, image); + return; + } + + dwords -= push; + + BEGIN_RING(chan, NvSub2D, 0x40000860, push); + OUT_RINGp(chan, data, push); + data += push; + } + + FIRE_RING(chan); +} + +int +nv50_fbcon_accel_init(struct fb_info *info) +{ + struct nouveau_fbcon_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->channel; + struct nouveau_gpuobj *eng2d = NULL; + int ret, format; + + switch (info->var.bits_per_pixel) { + case 8: + format = 0xf3; + break; + case 15: + format = 0xf8; + break; + case 16: + format = 0xe8; + break; + case 32: + switch (info->var.transp.length) { + case 0: /* depth 24 */ + case 8: /* depth 32, just use 24.. */ + format = 0xe6; + break; + case 2: /* depth 30 */ + format = 0xd1; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + ret = nouveau_gpuobj_gr_new(dev_priv->channel, 0x502d, &eng2d); + if (ret) + return ret; + + ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, Nv2D, eng2d, NULL); + if (ret) + return ret; + + ret = RING_SPACE(chan, 59); + if (ret) { + NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + return ret; + } + + BEGIN_RING(chan, NvSub2D, 0x0000, 1); + OUT_RING(chan, Nv2D); + BEGIN_RING(chan, NvSub2D, 0x0180, 4); + OUT_RING(chan, NvNotify0); + OUT_RING(chan, chan->vram_handle); + OUT_RING(chan, chan->vram_handle); + OUT_RING(chan, chan->vram_handle); + BEGIN_RING(chan, NvSub2D, 0x0290, 1); + OUT_RING(chan, 0); + BEGIN_RING(chan, NvSub2D, 0x0888, 1); + OUT_RING(chan, 1); + BEGIN_RING(chan, NvSub2D, 0x02ac, 1); + OUT_RING(chan, 3); + BEGIN_RING(chan, NvSub2D, 0x02a0, 1); + OUT_RING(chan, 0x55); + BEGIN_RING(chan, NvSub2D, 0x08c0, 4); + OUT_RING(chan, 0); + OUT_RING(chan, 1); + OUT_RING(chan, 0); + OUT_RING(chan, 1); + BEGIN_RING(chan, NvSub2D, 0x0580, 2); + OUT_RING(chan, 4); + OUT_RING(chan, format); + BEGIN_RING(chan, NvSub2D, 0x02e8, 2); + OUT_RING(chan, 2); + OUT_RING(chan, 1); + BEGIN_RING(chan, NvSub2D, 0x0804, 1); + OUT_RING(chan, format); + BEGIN_RING(chan, NvSub2D, 0x0800, 1); + OUT_RING(chan, 1); + BEGIN_RING(chan, NvSub2D, 0x0808, 3); + OUT_RING(chan, 0); + OUT_RING(chan, 0); + OUT_RING(chan, 0); + BEGIN_RING(chan, NvSub2D, 0x081c, 1); + OUT_RING(chan, 1); + BEGIN_RING(chan, NvSub2D, 0x0840, 4); + OUT_RING(chan, 0); + OUT_RING(chan, 1); + OUT_RING(chan, 0); + OUT_RING(chan, 1); + BEGIN_RING(chan, NvSub2D, 0x0200, 2); + OUT_RING(chan, format); + OUT_RING(chan, 1); + BEGIN_RING(chan, NvSub2D, 0x0214, 5); + OUT_RING(chan, info->fix.line_length); + OUT_RING(chan, info->var.xres_virtual); + OUT_RING(chan, info->var.yres_virtual); + OUT_RING(chan, 0); + OUT_RING(chan, info->fix.smem_start - dev_priv->fb_phys + + dev_priv->vm_vram_base); + BEGIN_RING(chan, NvSub2D, 0x0230, 2); + OUT_RING(chan, format); + OUT_RING(chan, 1); + BEGIN_RING(chan, NvSub2D, 0x0244, 5); + OUT_RING(chan, info->fix.line_length); + OUT_RING(chan, info->var.xres_virtual); + OUT_RING(chan, info->var.yres_virtual); + OUT_RING(chan, 0); + OUT_RING(chan, info->fix.smem_start - dev_priv->fb_phys + + dev_priv->vm_vram_base); + + info->fbops->fb_fillrect = nv50_fbcon_fillrect; + info->fbops->fb_copyarea = nv50_fbcon_copyarea; + info->fbops->fb_imageblit = nv50_fbcon_imageblit; + return 0; +} + diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c new file mode 100644 index 0000000000000000000000000000000000000000..77ae1aaa0bcea90babc84b8b202318f101c2e7af --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c @@ -0,0 +1,494 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +struct nv50_fifo_priv { + struct nouveau_gpuobj_ref *thingo[2]; + int cur_thingo; +}; + +#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50) + +static void +nv50_fifo_init_thingo(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_fifo_priv *priv = dev_priv->engine.fifo.priv; + struct nouveau_gpuobj_ref *cur; + int i, nr; + + NV_DEBUG(dev, "\n"); + + cur = priv->thingo[priv->cur_thingo]; + priv->cur_thingo = !priv->cur_thingo; + + /* We never schedule channel 0 or 127 */ + dev_priv->engine.instmem.prepare_access(dev, true); + for (i = 1, nr = 0; i < 127; i++) { + if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc) + nv_wo32(dev, cur->gpuobj, nr++, i); + } + dev_priv->engine.instmem.finish_access(dev); + + nv_wr32(dev, 0x32f4, cur->instance >> 12); + nv_wr32(dev, 0x32ec, nr); + nv_wr32(dev, 0x2500, 0x101); +} + +static int +nv50_fifo_channel_enable(struct drm_device *dev, int channel, bool nt) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->fifos[channel]; + uint32_t inst; + + NV_DEBUG(dev, "ch%d\n", channel); + + if (!chan->ramfc) + return -EINVAL; + + if (IS_G80) + inst = chan->ramfc->instance >> 12; + else + inst = chan->ramfc->instance >> 8; + nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), + inst | NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED); + + if (!nt) + nv50_fifo_init_thingo(dev); + return 0; +} + +static void +nv50_fifo_channel_disable(struct drm_device *dev, int channel, bool nt) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t inst; + + NV_DEBUG(dev, "ch%d, nt=%d\n", channel, nt); + + if (IS_G80) + inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80; + else + inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84; + nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), inst); + + if (!nt) + nv50_fifo_init_thingo(dev); +} + +static void +nv50_fifo_init_reset(struct drm_device *dev) +{ + uint32_t pmc_e = NV_PMC_ENABLE_PFIFO; + + NV_DEBUG(dev, "\n"); + + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e); + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | pmc_e); +} + +static void +nv50_fifo_init_intr(struct drm_device *dev) +{ + NV_DEBUG(dev, "\n"); + + nv_wr32(dev, NV03_PFIFO_INTR_0, 0xFFFFFFFF); + nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF); +} + +static void +nv50_fifo_init_context_table(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + NV_DEBUG(dev, "\n"); + + for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++) { + if (dev_priv->fifos[i]) + nv50_fifo_channel_enable(dev, i, true); + else + nv50_fifo_channel_disable(dev, i, true); + } + + nv50_fifo_init_thingo(dev); +} + +static void +nv50_fifo_init_regs__nv(struct drm_device *dev) +{ + NV_DEBUG(dev, "\n"); + + nv_wr32(dev, 0x250c, 0x6f3cfc34); +} + +static void +nv50_fifo_init_regs(struct drm_device *dev) +{ + NV_DEBUG(dev, "\n"); + + nv_wr32(dev, 0x2500, 0); + nv_wr32(dev, 0x3250, 0); + nv_wr32(dev, 0x3220, 0); + nv_wr32(dev, 0x3204, 0); + nv_wr32(dev, 0x3210, 0); + nv_wr32(dev, 0x3270, 0); + + /* Enable dummy channels setup by nv50_instmem.c */ + nv50_fifo_channel_enable(dev, 0, true); + nv50_fifo_channel_enable(dev, 127, true); +} + +int +nv50_fifo_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_fifo_priv *priv; + int ret; + + NV_DEBUG(dev, "\n"); + + priv = dev_priv->engine.fifo.priv; + if (priv) { + priv->cur_thingo = !priv->cur_thingo; + goto just_reset; + } + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + dev_priv->engine.fifo.priv = priv; + + ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo[0]); + if (ret) { + NV_ERROR(dev, "error creating thingo0: %d\n", ret); + return ret; + } + + ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo[1]); + if (ret) { + NV_ERROR(dev, "error creating thingo1: %d\n", ret); + return ret; + } + +just_reset: + nv50_fifo_init_reset(dev); + nv50_fifo_init_intr(dev); + nv50_fifo_init_context_table(dev); + nv50_fifo_init_regs__nv(dev); + nv50_fifo_init_regs(dev); + dev_priv->engine.fifo.enable(dev); + dev_priv->engine.fifo.reassign(dev, true); + + return 0; +} + +void +nv50_fifo_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_fifo_priv *priv = dev_priv->engine.fifo.priv; + + NV_DEBUG(dev, "\n"); + + if (!priv) + return; + + nouveau_gpuobj_ref_del(dev, &priv->thingo[0]); + nouveau_gpuobj_ref_del(dev, &priv->thingo[1]); + + dev_priv->engine.fifo.priv = NULL; + kfree(priv); +} + +int +nv50_fifo_channel_id(struct drm_device *dev) +{ + return nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & + NV50_PFIFO_CACHE1_PUSH1_CHID_MASK; +} + +int +nv50_fifo_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *ramfc = NULL; + int ret; + + NV_DEBUG(dev, "ch%d\n", chan->id); + + if (IS_G80) { + uint32_t ramin_poffset = chan->ramin->gpuobj->im_pramin->start; + uint32_t ramin_voffset = chan->ramin->gpuobj->im_backing_start; + + ret = nouveau_gpuobj_new_fake(dev, ramin_poffset, ramin_voffset, + 0x100, NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &ramfc, + &chan->ramfc); + if (ret) + return ret; + + ret = nouveau_gpuobj_new_fake(dev, ramin_poffset + 0x0400, + ramin_voffset + 0x0400, 4096, + 0, NULL, &chan->cache); + if (ret) + return ret; + } else { + ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100, 256, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, + &chan->ramfc); + if (ret) + return ret; + ramfc = chan->ramfc->gpuobj; + + ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 4096, 256, + 0, &chan->cache); + if (ret) + return ret; + } + + dev_priv->engine.instmem.prepare_access(dev, true); + + nv_wo32(dev, ramfc, 0x08/4, chan->pushbuf_base); + nv_wo32(dev, ramfc, 0x10/4, chan->pushbuf_base); + nv_wo32(dev, ramfc, 0x48/4, chan->pushbuf->instance >> 4); + nv_wo32(dev, ramfc, 0x80/4, (0xc << 24) | (chan->ramht->instance >> 4)); + nv_wo32(dev, ramfc, 0x3c/4, 0x00086078); + nv_wo32(dev, ramfc, 0x44/4, 0x2101ffff); + nv_wo32(dev, ramfc, 0x60/4, 0x7fffffff); + nv_wo32(dev, ramfc, 0x40/4, 0x00000000); + nv_wo32(dev, ramfc, 0x7c/4, 0x30000001); + nv_wo32(dev, ramfc, 0x78/4, 0x00000000); + nv_wo32(dev, ramfc, 0x4c/4, 0xffffffff); + + if (!IS_G80) { + nv_wo32(dev, chan->ramin->gpuobj, 0, chan->id); + nv_wo32(dev, chan->ramin->gpuobj, 1, + chan->ramfc->instance >> 8); + + nv_wo32(dev, ramfc, 0x88/4, chan->cache->instance >> 10); + nv_wo32(dev, ramfc, 0x98/4, chan->ramin->instance >> 12); + } + + dev_priv->engine.instmem.finish_access(dev); + + ret = nv50_fifo_channel_enable(dev, chan->id, false); + if (ret) { + NV_ERROR(dev, "error enabling ch%d: %d\n", chan->id, ret); + nouveau_gpuobj_ref_del(dev, &chan->ramfc); + return ret; + } + + return 0; +} + +void +nv50_fifo_destroy_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + + NV_DEBUG(dev, "ch%d\n", chan->id); + + nouveau_gpuobj_ref_del(dev, &chan->ramfc); + nouveau_gpuobj_ref_del(dev, &chan->cache); + + nv50_fifo_channel_disable(dev, chan->id, false); + + /* Dummy channel, also used on ch 127 */ + if (chan->id == 0) + nv50_fifo_channel_disable(dev, 127, false); +} + +int +nv50_fifo_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *ramfc = chan->ramfc->gpuobj; + struct nouveau_gpuobj *cache = chan->cache->gpuobj; + int ptr, cnt; + + NV_DEBUG(dev, "ch%d\n", chan->id); + + dev_priv->engine.instmem.prepare_access(dev, false); + + nv_wr32(dev, 0x3330, nv_ro32(dev, ramfc, 0x00/4)); + nv_wr32(dev, 0x3334, nv_ro32(dev, ramfc, 0x04/4)); + nv_wr32(dev, 0x3240, nv_ro32(dev, ramfc, 0x08/4)); + nv_wr32(dev, 0x3320, nv_ro32(dev, ramfc, 0x0c/4)); + nv_wr32(dev, 0x3244, nv_ro32(dev, ramfc, 0x10/4)); + nv_wr32(dev, 0x3328, nv_ro32(dev, ramfc, 0x14/4)); + nv_wr32(dev, 0x3368, nv_ro32(dev, ramfc, 0x18/4)); + nv_wr32(dev, 0x336c, nv_ro32(dev, ramfc, 0x1c/4)); + nv_wr32(dev, 0x3370, nv_ro32(dev, ramfc, 0x20/4)); + nv_wr32(dev, 0x3374, nv_ro32(dev, ramfc, 0x24/4)); + nv_wr32(dev, 0x3378, nv_ro32(dev, ramfc, 0x28/4)); + nv_wr32(dev, 0x337c, nv_ro32(dev, ramfc, 0x2c/4)); + nv_wr32(dev, 0x3228, nv_ro32(dev, ramfc, 0x30/4)); + nv_wr32(dev, 0x3364, nv_ro32(dev, ramfc, 0x34/4)); + nv_wr32(dev, 0x32a0, nv_ro32(dev, ramfc, 0x38/4)); + nv_wr32(dev, 0x3224, nv_ro32(dev, ramfc, 0x3c/4)); + nv_wr32(dev, 0x324c, nv_ro32(dev, ramfc, 0x40/4)); + nv_wr32(dev, 0x2044, nv_ro32(dev, ramfc, 0x44/4)); + nv_wr32(dev, 0x322c, nv_ro32(dev, ramfc, 0x48/4)); + nv_wr32(dev, 0x3234, nv_ro32(dev, ramfc, 0x4c/4)); + nv_wr32(dev, 0x3340, nv_ro32(dev, ramfc, 0x50/4)); + nv_wr32(dev, 0x3344, nv_ro32(dev, ramfc, 0x54/4)); + nv_wr32(dev, 0x3280, nv_ro32(dev, ramfc, 0x58/4)); + nv_wr32(dev, 0x3254, nv_ro32(dev, ramfc, 0x5c/4)); + nv_wr32(dev, 0x3260, nv_ro32(dev, ramfc, 0x60/4)); + nv_wr32(dev, 0x3264, nv_ro32(dev, ramfc, 0x64/4)); + nv_wr32(dev, 0x3268, nv_ro32(dev, ramfc, 0x68/4)); + nv_wr32(dev, 0x326c, nv_ro32(dev, ramfc, 0x6c/4)); + nv_wr32(dev, 0x32e4, nv_ro32(dev, ramfc, 0x70/4)); + nv_wr32(dev, 0x3248, nv_ro32(dev, ramfc, 0x74/4)); + nv_wr32(dev, 0x2088, nv_ro32(dev, ramfc, 0x78/4)); + nv_wr32(dev, 0x2058, nv_ro32(dev, ramfc, 0x7c/4)); + nv_wr32(dev, 0x2210, nv_ro32(dev, ramfc, 0x80/4)); + + cnt = nv_ro32(dev, ramfc, 0x84/4); + for (ptr = 0; ptr < cnt; ptr++) { + nv_wr32(dev, NV40_PFIFO_CACHE1_METHOD(ptr), + nv_ro32(dev, cache, (ptr * 2) + 0)); + nv_wr32(dev, NV40_PFIFO_CACHE1_DATA(ptr), + nv_ro32(dev, cache, (ptr * 2) + 1)); + } + nv_wr32(dev, 0x3210, cnt << 2); + nv_wr32(dev, 0x3270, 0); + + /* guessing that all the 0x34xx regs aren't on NV50 */ + if (!IS_G80) { + nv_wr32(dev, 0x340c, nv_ro32(dev, ramfc, 0x88/4)); + nv_wr32(dev, 0x3400, nv_ro32(dev, ramfc, 0x8c/4)); + nv_wr32(dev, 0x3404, nv_ro32(dev, ramfc, 0x90/4)); + nv_wr32(dev, 0x3408, nv_ro32(dev, ramfc, 0x94/4)); + nv_wr32(dev, 0x3410, nv_ro32(dev, ramfc, 0x98/4)); + } + + dev_priv->engine.instmem.finish_access(dev); + + nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16)); + return 0; +} + +int +nv50_fifo_unload_context(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + struct nouveau_gpuobj *ramfc, *cache; + struct nouveau_channel *chan = NULL; + int chid, get, put, ptr; + + NV_DEBUG(dev, "\n"); + + chid = pfifo->channel_id(dev); + if (chid < 0 || chid >= dev_priv->engine.fifo.channels) + return 0; + + chan = dev_priv->fifos[chid]; + if (!chan) { + NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid); + return -EINVAL; + } + NV_DEBUG(dev, "ch%d\n", chan->id); + ramfc = chan->ramfc->gpuobj; + cache = chan->cache->gpuobj; + + dev_priv->engine.instmem.prepare_access(dev, true); + + nv_wo32(dev, ramfc, 0x00/4, nv_rd32(dev, 0x3330)); + nv_wo32(dev, ramfc, 0x04/4, nv_rd32(dev, 0x3334)); + nv_wo32(dev, ramfc, 0x08/4, nv_rd32(dev, 0x3240)); + nv_wo32(dev, ramfc, 0x0c/4, nv_rd32(dev, 0x3320)); + nv_wo32(dev, ramfc, 0x10/4, nv_rd32(dev, 0x3244)); + nv_wo32(dev, ramfc, 0x14/4, nv_rd32(dev, 0x3328)); + nv_wo32(dev, ramfc, 0x18/4, nv_rd32(dev, 0x3368)); + nv_wo32(dev, ramfc, 0x1c/4, nv_rd32(dev, 0x336c)); + nv_wo32(dev, ramfc, 0x20/4, nv_rd32(dev, 0x3370)); + nv_wo32(dev, ramfc, 0x24/4, nv_rd32(dev, 0x3374)); + nv_wo32(dev, ramfc, 0x28/4, nv_rd32(dev, 0x3378)); + nv_wo32(dev, ramfc, 0x2c/4, nv_rd32(dev, 0x337c)); + nv_wo32(dev, ramfc, 0x30/4, nv_rd32(dev, 0x3228)); + nv_wo32(dev, ramfc, 0x34/4, nv_rd32(dev, 0x3364)); + nv_wo32(dev, ramfc, 0x38/4, nv_rd32(dev, 0x32a0)); + nv_wo32(dev, ramfc, 0x3c/4, nv_rd32(dev, 0x3224)); + nv_wo32(dev, ramfc, 0x40/4, nv_rd32(dev, 0x324c)); + nv_wo32(dev, ramfc, 0x44/4, nv_rd32(dev, 0x2044)); + nv_wo32(dev, ramfc, 0x48/4, nv_rd32(dev, 0x322c)); + nv_wo32(dev, ramfc, 0x4c/4, nv_rd32(dev, 0x3234)); + nv_wo32(dev, ramfc, 0x50/4, nv_rd32(dev, 0x3340)); + nv_wo32(dev, ramfc, 0x54/4, nv_rd32(dev, 0x3344)); + nv_wo32(dev, ramfc, 0x58/4, nv_rd32(dev, 0x3280)); + nv_wo32(dev, ramfc, 0x5c/4, nv_rd32(dev, 0x3254)); + nv_wo32(dev, ramfc, 0x60/4, nv_rd32(dev, 0x3260)); + nv_wo32(dev, ramfc, 0x64/4, nv_rd32(dev, 0x3264)); + nv_wo32(dev, ramfc, 0x68/4, nv_rd32(dev, 0x3268)); + nv_wo32(dev, ramfc, 0x6c/4, nv_rd32(dev, 0x326c)); + nv_wo32(dev, ramfc, 0x70/4, nv_rd32(dev, 0x32e4)); + nv_wo32(dev, ramfc, 0x74/4, nv_rd32(dev, 0x3248)); + nv_wo32(dev, ramfc, 0x78/4, nv_rd32(dev, 0x2088)); + nv_wo32(dev, ramfc, 0x7c/4, nv_rd32(dev, 0x2058)); + nv_wo32(dev, ramfc, 0x80/4, nv_rd32(dev, 0x2210)); + + put = (nv_rd32(dev, NV03_PFIFO_CACHE1_PUT) & 0x7ff) >> 2; + get = (nv_rd32(dev, NV03_PFIFO_CACHE1_GET) & 0x7ff) >> 2; + ptr = 0; + while (put != get) { + nv_wo32(dev, cache, ptr++, + nv_rd32(dev, NV40_PFIFO_CACHE1_METHOD(get))); + nv_wo32(dev, cache, ptr++, + nv_rd32(dev, NV40_PFIFO_CACHE1_DATA(get))); + get = (get + 1) & 0x1ff; + } + + /* guessing that all the 0x34xx regs aren't on NV50 */ + if (!IS_G80) { + nv_wo32(dev, ramfc, 0x84/4, ptr >> 1); + nv_wo32(dev, ramfc, 0x88/4, nv_rd32(dev, 0x340c)); + nv_wo32(dev, ramfc, 0x8c/4, nv_rd32(dev, 0x3400)); + nv_wo32(dev, ramfc, 0x90/4, nv_rd32(dev, 0x3404)); + nv_wo32(dev, ramfc, 0x94/4, nv_rd32(dev, 0x3408)); + nv_wo32(dev, ramfc, 0x98/4, nv_rd32(dev, 0x3410)); + } + + dev_priv->engine.instmem.finish_access(dev); + + /*XXX: probably reload ch127 (NULL) state back too */ + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, 127); + return 0; +} + diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c new file mode 100644 index 0000000000000000000000000000000000000000..177d8229336f1d59806411ddd02a9ca86540d6ec --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_graph.c @@ -0,0 +1,385 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +MODULE_FIRMWARE("nouveau/nv50.ctxprog"); +MODULE_FIRMWARE("nouveau/nv50.ctxvals"); +MODULE_FIRMWARE("nouveau/nv84.ctxprog"); +MODULE_FIRMWARE("nouveau/nv84.ctxvals"); +MODULE_FIRMWARE("nouveau/nv86.ctxprog"); +MODULE_FIRMWARE("nouveau/nv86.ctxvals"); +MODULE_FIRMWARE("nouveau/nv92.ctxprog"); +MODULE_FIRMWARE("nouveau/nv92.ctxvals"); +MODULE_FIRMWARE("nouveau/nv94.ctxprog"); +MODULE_FIRMWARE("nouveau/nv94.ctxvals"); +MODULE_FIRMWARE("nouveau/nv96.ctxprog"); +MODULE_FIRMWARE("nouveau/nv96.ctxvals"); +MODULE_FIRMWARE("nouveau/nv98.ctxprog"); +MODULE_FIRMWARE("nouveau/nv98.ctxvals"); +MODULE_FIRMWARE("nouveau/nva0.ctxprog"); +MODULE_FIRMWARE("nouveau/nva0.ctxvals"); +MODULE_FIRMWARE("nouveau/nva5.ctxprog"); +MODULE_FIRMWARE("nouveau/nva5.ctxvals"); +MODULE_FIRMWARE("nouveau/nva8.ctxprog"); +MODULE_FIRMWARE("nouveau/nva8.ctxvals"); +MODULE_FIRMWARE("nouveau/nvaa.ctxprog"); +MODULE_FIRMWARE("nouveau/nvaa.ctxvals"); +MODULE_FIRMWARE("nouveau/nvac.ctxprog"); +MODULE_FIRMWARE("nouveau/nvac.ctxvals"); + +#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50) + +static void +nv50_graph_init_reset(struct drm_device *dev) +{ + uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21); + + NV_DEBUG(dev, "\n"); + + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e); + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | pmc_e); +} + +static void +nv50_graph_init_intr(struct drm_device *dev) +{ + NV_DEBUG(dev, "\n"); + + nv_wr32(dev, NV03_PGRAPH_INTR, 0xffffffff); + nv_wr32(dev, 0x400138, 0xffffffff); + nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xffffffff); +} + +static void +nv50_graph_init_regs__nv(struct drm_device *dev) +{ + NV_DEBUG(dev, "\n"); + + nv_wr32(dev, 0x400804, 0xc0000000); + nv_wr32(dev, 0x406800, 0xc0000000); + nv_wr32(dev, 0x400c04, 0xc0000000); + nv_wr32(dev, 0x401804, 0xc0000000); + nv_wr32(dev, 0x405018, 0xc0000000); + nv_wr32(dev, 0x402000, 0xc0000000); + + nv_wr32(dev, 0x400108, 0xffffffff); + + nv_wr32(dev, 0x400824, 0x00004000); + nv_wr32(dev, 0x400500, 0x00010001); +} + +static void +nv50_graph_init_regs(struct drm_device *dev) +{ + NV_DEBUG(dev, "\n"); + + nv_wr32(dev, NV04_PGRAPH_DEBUG_3, + (1 << 2) /* HW_CONTEXT_SWITCH_ENABLED */); + nv_wr32(dev, 0x402ca8, 0x800); +} + +static int +nv50_graph_init_ctxctl(struct drm_device *dev) +{ + NV_DEBUG(dev, "\n"); + + nv40_grctx_init(dev); + + nv_wr32(dev, 0x400320, 4); + nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0); + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, 0); + return 0; +} + +int +nv50_graph_init(struct drm_device *dev) +{ + int ret; + + NV_DEBUG(dev, "\n"); + + nv50_graph_init_reset(dev); + nv50_graph_init_regs__nv(dev); + nv50_graph_init_regs(dev); + nv50_graph_init_intr(dev); + + ret = nv50_graph_init_ctxctl(dev); + if (ret) + return ret; + + return 0; +} + +void +nv50_graph_takedown(struct drm_device *dev) +{ + NV_DEBUG(dev, "\n"); + nv40_grctx_fini(dev); +} + +void +nv50_graph_fifo_access(struct drm_device *dev, bool enabled) +{ + const uint32_t mask = 0x00010001; + + if (enabled) + nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | mask); + else + nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) & ~mask); +} + +struct nouveau_channel * +nv50_graph_channel(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t inst; + int i; + + inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR); + if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED)) + return NULL; + inst = (inst & NV50_PGRAPH_CTXCTL_CUR_INSTANCE) << 12; + + for (i = 0; i < dev_priv->engine.fifo.channels; i++) { + struct nouveau_channel *chan = dev_priv->fifos[i]; + + if (chan && chan->ramin && chan->ramin->instance == inst) + return chan; + } + + return NULL; +} + +int +nv50_graph_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *ramin = chan->ramin->gpuobj; + struct nouveau_gpuobj *ctx; + uint32_t grctx_size = 0x70000; + int hdr, ret; + + NV_DEBUG(dev, "ch%d\n", chan->id); + + ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, grctx_size, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); + if (ret) + return ret; + ctx = chan->ramin_grctx->gpuobj; + + hdr = IS_G80 ? 0x200 : 0x20; + dev_priv->engine.instmem.prepare_access(dev, true); + nv_wo32(dev, ramin, (hdr + 0x00)/4, 0x00190002); + nv_wo32(dev, ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance + + grctx_size - 1); + nv_wo32(dev, ramin, (hdr + 0x08)/4, chan->ramin_grctx->instance); + nv_wo32(dev, ramin, (hdr + 0x0c)/4, 0); + nv_wo32(dev, ramin, (hdr + 0x10)/4, 0); + nv_wo32(dev, ramin, (hdr + 0x14)/4, 0x00010000); + dev_priv->engine.instmem.finish_access(dev); + + dev_priv->engine.instmem.prepare_access(dev, true); + nv40_grctx_vals_load(dev, ctx); + nv_wo32(dev, ctx, 0x00000/4, chan->ramin->instance >> 12); + if ((dev_priv->chipset & 0xf0) == 0xa0) + nv_wo32(dev, ctx, 0x00004/4, 0x00000000); + else + nv_wo32(dev, ctx, 0x0011c/4, 0x00000000); + dev_priv->engine.instmem.finish_access(dev); + + return 0; +} + +void +nv50_graph_destroy_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i, hdr = IS_G80 ? 0x200 : 0x20; + + NV_DEBUG(dev, "ch%d\n", chan->id); + + if (!chan->ramin || !chan->ramin->gpuobj) + return; + + dev_priv->engine.instmem.prepare_access(dev, true); + for (i = hdr; i < hdr + 24; i += 4) + nv_wo32(dev, chan->ramin->gpuobj, i/4, 0); + dev_priv->engine.instmem.finish_access(dev); + + nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); +} + +static int +nv50_graph_do_load_context(struct drm_device *dev, uint32_t inst) +{ + uint32_t fifo = nv_rd32(dev, 0x400500); + + nv_wr32(dev, 0x400500, fifo & ~1); + nv_wr32(dev, 0x400784, inst); + nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x40); + nv_wr32(dev, 0x400320, nv_rd32(dev, 0x400320) | 0x11); + nv_wr32(dev, 0x400040, 0xffffffff); + (void)nv_rd32(dev, 0x400040); + nv_wr32(dev, 0x400040, 0x00000000); + nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 1); + + if (nouveau_wait_for_idle(dev)) + nv_wr32(dev, 0x40032c, inst | (1<<31)); + nv_wr32(dev, 0x400500, fifo); + + return 0; +} + +int +nv50_graph_load_context(struct nouveau_channel *chan) +{ + uint32_t inst = chan->ramin->instance >> 12; + + NV_DEBUG(chan->dev, "ch%d\n", chan->id); + return nv50_graph_do_load_context(chan->dev, inst); +} + +int +nv50_graph_unload_context(struct drm_device *dev) +{ + uint32_t inst, fifo = nv_rd32(dev, 0x400500); + + inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR); + if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED)) + return 0; + inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE; + + nv_wr32(dev, 0x400500, fifo & ~1); + nv_wr32(dev, 0x400784, inst); + nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20); + nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 0x01); + nouveau_wait_for_idle(dev); + nv_wr32(dev, 0x400500, fifo); + + nv_wr32(dev, NV50_PGRAPH_CTXCTL_CUR, inst); + return 0; +} + +void +nv50_graph_context_switch(struct drm_device *dev) +{ + uint32_t inst; + + nv50_graph_unload_context(dev); + + inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_NEXT); + inst &= NV50_PGRAPH_CTXCTL_NEXT_INSTANCE; + nv50_graph_do_load_context(dev, inst); + + nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev, + NV40_PGRAPH_INTR_EN) | NV_PGRAPH_INTR_CONTEXT_SWITCH); +} + +static int +nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, int grclass, + int mthd, uint32_t data) +{ + struct nouveau_gpuobj_ref *ref = NULL; + + if (nouveau_gpuobj_ref_find(chan, data, &ref)) + return -ENOENT; + + if (nouveau_notifier_offset(ref->gpuobj, NULL)) + return -EINVAL; + + chan->nvsw.vblsem = ref->gpuobj; + chan->nvsw.vblsem_offset = ~0; + return 0; +} + +static int +nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan, int grclass, + int mthd, uint32_t data) +{ + if (nouveau_notifier_offset(chan->nvsw.vblsem, &data)) + return -ERANGE; + + chan->nvsw.vblsem_offset = data >> 2; + return 0; +} + +static int +nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan, int grclass, + int mthd, uint32_t data) +{ + chan->nvsw.vblsem_rval = data; + return 0; +} + +static int +nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan, int grclass, + int mthd, uint32_t data) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (!chan->nvsw.vblsem || chan->nvsw.vblsem_offset == ~0 || data > 1) + return -EINVAL; + + if (!(nv_rd32(dev, NV50_PDISPLAY_INTR_EN) & + NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data))) { + nv_wr32(dev, NV50_PDISPLAY_INTR_1, + NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(data)); + nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev, + NV50_PDISPLAY_INTR_EN) | + NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data)); + } + + list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting); + return 0; +} + +static struct nouveau_pgraph_object_method nv50_graph_nvsw_methods[] = { + { 0x018c, nv50_graph_nvsw_dma_vblsem }, + { 0x0400, nv50_graph_nvsw_vblsem_offset }, + { 0x0404, nv50_graph_nvsw_vblsem_release_val }, + { 0x0408, nv50_graph_nvsw_vblsem_release }, + {} +}; + +struct nouveau_pgraph_object_class nv50_graph_grclass[] = { + { 0x506e, true, nv50_graph_nvsw_methods }, /* nvsw */ + { 0x0030, false, NULL }, /* null */ + { 0x5039, false, NULL }, /* m2mf */ + { 0x502d, false, NULL }, /* 2d */ + { 0x50c0, false, NULL }, /* compute */ + { 0x5097, false, NULL }, /* tesla (nv50) */ + { 0x8297, false, NULL }, /* tesla (nv80/nv90) */ + { 0x8397, false, NULL }, /* tesla (nva0) */ + { 0x8597, false, NULL }, /* tesla (nva8) */ + {} +}; diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c new file mode 100644 index 0000000000000000000000000000000000000000..94400f777e7f9bd1d83eb73890bf23450fb7bfa6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c @@ -0,0 +1,509 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +struct nv50_instmem_priv { + uint32_t save1700[5]; /* 0x1700->0x1710 */ + + struct nouveau_gpuobj_ref *pramin_pt; + struct nouveau_gpuobj_ref *pramin_bar; + struct nouveau_gpuobj_ref *fb_bar; + + bool last_access_wr; +}; + +#define NV50_INSTMEM_PAGE_SHIFT 12 +#define NV50_INSTMEM_PAGE_SIZE (1 << NV50_INSTMEM_PAGE_SHIFT) +#define NV50_INSTMEM_PT_SIZE(a) (((a) >> 12) << 3) + +/*NOTE: - Assumes 0x1700 already covers the correct MiB of PRAMIN + */ +#define BAR0_WI32(g, o, v) do { \ + uint32_t offset; \ + if ((g)->im_backing) { \ + offset = (g)->im_backing_start; \ + } else { \ + offset = chan->ramin->gpuobj->im_backing_start; \ + offset += (g)->im_pramin->start; \ + } \ + offset += (o); \ + nv_wr32(dev, NV_RAMIN + (offset & 0xfffff), (v)); \ +} while (0) + +int +nv50_instmem_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan; + uint32_t c_offset, c_size, c_ramfc, c_vmpd, c_base, pt_size; + struct nv50_instmem_priv *priv; + int ret, i; + uint32_t v, save_nv001700; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + dev_priv->engine.instmem.priv = priv; + + /* Save state, will restore at takedown. */ + for (i = 0x1700; i <= 0x1710; i += 4) + priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i); + + /* Reserve the last MiB of VRAM, we should probably try to avoid + * setting up the below tables over the top of the VBIOS image at + * some point. + */ + dev_priv->ramin_rsvd_vram = 1 << 20; + c_offset = nouveau_mem_fb_amount(dev) - dev_priv->ramin_rsvd_vram; + c_size = 128 << 10; + c_vmpd = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x1400 : 0x200; + c_ramfc = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x0 : 0x20; + c_base = c_vmpd + 0x4000; + pt_size = NV50_INSTMEM_PT_SIZE(dev_priv->ramin_size); + + NV_DEBUG(dev, " Rsvd VRAM base: 0x%08x\n", c_offset); + NV_DEBUG(dev, " VBIOS image: 0x%08x\n", + (nv_rd32(dev, 0x619f04) & ~0xff) << 8); + NV_DEBUG(dev, " Aperture size: %d MiB\n", dev_priv->ramin_size >> 20); + NV_DEBUG(dev, " PT size: %d KiB\n", pt_size >> 10); + + /* Determine VM layout, we need to do this first to make sure + * we allocate enough memory for all the page tables. + */ + dev_priv->vm_gart_base = roundup(NV50_VM_BLOCK, NV50_VM_BLOCK); + dev_priv->vm_gart_size = NV50_VM_BLOCK; + + dev_priv->vm_vram_base = dev_priv->vm_gart_base + dev_priv->vm_gart_size; + dev_priv->vm_vram_size = nouveau_mem_fb_amount(dev); + if (dev_priv->vm_vram_size > NV50_VM_MAX_VRAM) + dev_priv->vm_vram_size = NV50_VM_MAX_VRAM; + dev_priv->vm_vram_size = roundup(dev_priv->vm_vram_size, NV50_VM_BLOCK); + dev_priv->vm_vram_pt_nr = dev_priv->vm_vram_size / NV50_VM_BLOCK; + + dev_priv->vm_end = dev_priv->vm_vram_base + dev_priv->vm_vram_size; + + NV_DEBUG(dev, "NV50VM: GART 0x%016llx-0x%016llx\n", + dev_priv->vm_gart_base, + dev_priv->vm_gart_base + dev_priv->vm_gart_size - 1); + NV_DEBUG(dev, "NV50VM: VRAM 0x%016llx-0x%016llx\n", + dev_priv->vm_vram_base, + dev_priv->vm_vram_base + dev_priv->vm_vram_size - 1); + + c_size += dev_priv->vm_vram_pt_nr * (NV50_VM_BLOCK / 65536 * 8); + + /* Map BAR0 PRAMIN aperture over the memory we want to use */ + save_nv001700 = nv_rd32(dev, NV50_PUNK_BAR0_PRAMIN); + nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, (c_offset >> 16)); + + /* Create a fake channel, and use it as our "dummy" channels 0/127. + * The main reason for creating a channel is so we can use the gpuobj + * code. However, it's probably worth noting that NVIDIA also setup + * their channels 0/127 with the same values they configure here. + * So, there may be some other reason for doing this. + * + * Have to create the entire channel manually, as the real channel + * creation code assumes we have PRAMIN access, and we don't until + * we're done here. + */ + chan = kzalloc(sizeof(*chan), GFP_KERNEL); + if (!chan) + return -ENOMEM; + chan->id = 0; + chan->dev = dev; + chan->file_priv = (struct drm_file *)-2; + dev_priv->fifos[0] = dev_priv->fifos[127] = chan; + + /* Channel's PRAMIN object + heap */ + ret = nouveau_gpuobj_new_fake(dev, 0, c_offset, c_size, 0, + NULL, &chan->ramin); + if (ret) + return ret; + + if (nouveau_mem_init_heap(&chan->ramin_heap, c_base, c_size - c_base)) + return -ENOMEM; + + /* RAMFC + zero channel's PRAMIN up to start of VM pagedir */ + ret = nouveau_gpuobj_new_fake(dev, c_ramfc, c_offset + c_ramfc, + 0x4000, 0, NULL, &chan->ramfc); + if (ret) + return ret; + + for (i = 0; i < c_vmpd; i += 4) + BAR0_WI32(chan->ramin->gpuobj, i, 0); + + /* VM page directory */ + ret = nouveau_gpuobj_new_fake(dev, c_vmpd, c_offset + c_vmpd, + 0x4000, 0, &chan->vm_pd, NULL); + if (ret) + return ret; + for (i = 0; i < 0x4000; i += 8) { + BAR0_WI32(chan->vm_pd, i + 0x00, 0x00000000); + BAR0_WI32(chan->vm_pd, i + 0x04, 0x00000000); + } + + /* PRAMIN page table, cheat and map into VM at 0x0000000000. + * We map the entire fake channel into the start of the PRAMIN BAR + */ + ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pt_size, 0x1000, + 0, &priv->pramin_pt); + if (ret) + return ret; + + for (i = 0, v = c_offset; i < pt_size; i += 8, v += 0x1000) { + if (v < (c_offset + c_size)) + BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, v | 1); + else + BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, 0x00000009); + BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000); + } + + BAR0_WI32(chan->vm_pd, 0x00, priv->pramin_pt->instance | 0x63); + BAR0_WI32(chan->vm_pd, 0x04, 0x00000000); + + /* VRAM page table(s), mapped into VM at +1GiB */ + for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { + ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, + NV50_VM_BLOCK/65536*8, 0, 0, + &chan->vm_vram_pt[i]); + if (ret) { + NV_ERROR(dev, "Error creating VRAM page tables: %d\n", + ret); + dev_priv->vm_vram_pt_nr = i; + return ret; + } + dev_priv->vm_vram_pt[i] = chan->vm_vram_pt[i]->gpuobj; + + for (v = 0; v < dev_priv->vm_vram_pt[i]->im_pramin->size; + v += 4) + BAR0_WI32(dev_priv->vm_vram_pt[i], v, 0); + + BAR0_WI32(chan->vm_pd, 0x10 + (i*8), + chan->vm_vram_pt[i]->instance | 0x61); + BAR0_WI32(chan->vm_pd, 0x14 + (i*8), 0); + } + + /* DMA object for PRAMIN BAR */ + ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 6*4, 16, 0, + &priv->pramin_bar); + if (ret) + return ret; + BAR0_WI32(priv->pramin_bar->gpuobj, 0x00, 0x7fc00000); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x04, dev_priv->ramin_size - 1); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x08, 0x00000000); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x0c, 0x00000000); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x10, 0x00000000); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x14, 0x00000000); + + /* DMA object for FB BAR */ + ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 6*4, 16, 0, + &priv->fb_bar); + if (ret) + return ret; + BAR0_WI32(priv->fb_bar->gpuobj, 0x00, 0x7fc00000); + BAR0_WI32(priv->fb_bar->gpuobj, 0x04, 0x40000000 + + drm_get_resource_len(dev, 1) - 1); + BAR0_WI32(priv->fb_bar->gpuobj, 0x08, 0x40000000); + BAR0_WI32(priv->fb_bar->gpuobj, 0x0c, 0x00000000); + BAR0_WI32(priv->fb_bar->gpuobj, 0x10, 0x00000000); + BAR0_WI32(priv->fb_bar->gpuobj, 0x14, 0x00000000); + + /* Poke the relevant regs, and pray it works :) */ + nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12)); + nv_wr32(dev, NV50_PUNK_UNK1710, 0); + nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12) | + NV50_PUNK_BAR_CFG_BASE_VALID); + nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->fb_bar->instance >> 4) | + NV50_PUNK_BAR1_CTXDMA_VALID); + nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->instance >> 4) | + NV50_PUNK_BAR3_CTXDMA_VALID); + + for (i = 0; i < 8; i++) + nv_wr32(dev, 0x1900 + (i*4), 0); + + /* Assume that praying isn't enough, check that we can re-read the + * entire fake channel back from the PRAMIN BAR */ + dev_priv->engine.instmem.prepare_access(dev, false); + for (i = 0; i < c_size; i += 4) { + if (nv_rd32(dev, NV_RAMIN + i) != nv_ri32(dev, i)) { + NV_ERROR(dev, "Error reading back PRAMIN at 0x%08x\n", + i); + dev_priv->engine.instmem.finish_access(dev); + return -EINVAL; + } + } + dev_priv->engine.instmem.finish_access(dev); + + nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, save_nv001700); + + /* Global PRAMIN heap */ + if (nouveau_mem_init_heap(&dev_priv->ramin_heap, + c_size, dev_priv->ramin_size - c_size)) { + dev_priv->ramin_heap = NULL; + NV_ERROR(dev, "Failed to init RAMIN heap\n"); + } + + /*XXX: incorrect, but needed to make hash func "work" */ + dev_priv->ramht_offset = 0x10000; + dev_priv->ramht_bits = 9; + dev_priv->ramht_size = (1 << dev_priv->ramht_bits); + return 0; +} + +void +nv50_instmem_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; + struct nouveau_channel *chan = dev_priv->fifos[0]; + int i; + + NV_DEBUG(dev, "\n"); + + if (!priv) + return; + + /* Restore state from before init */ + for (i = 0x1700; i <= 0x1710; i += 4) + nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]); + + nouveau_gpuobj_ref_del(dev, &priv->fb_bar); + nouveau_gpuobj_ref_del(dev, &priv->pramin_bar); + nouveau_gpuobj_ref_del(dev, &priv->pramin_pt); + + /* Destroy dummy channel */ + if (chan) { + for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { + nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]); + dev_priv->vm_vram_pt[i] = NULL; + } + dev_priv->vm_vram_pt_nr = 0; + + nouveau_gpuobj_del(dev, &chan->vm_pd); + nouveau_gpuobj_ref_del(dev, &chan->ramfc); + nouveau_gpuobj_ref_del(dev, &chan->ramin); + nouveau_mem_takedown(&chan->ramin_heap); + + dev_priv->fifos[0] = dev_priv->fifos[127] = NULL; + kfree(chan); + } + + dev_priv->engine.instmem.priv = NULL; + kfree(priv); +} + +int +nv50_instmem_suspend(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->fifos[0]; + struct nouveau_gpuobj *ramin = chan->ramin->gpuobj; + int i; + + ramin->im_backing_suspend = vmalloc(ramin->im_pramin->size); + if (!ramin->im_backing_suspend) + return -ENOMEM; + + for (i = 0; i < ramin->im_pramin->size; i += 4) + ramin->im_backing_suspend[i/4] = nv_ri32(dev, i); + return 0; +} + +void +nv50_instmem_resume(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; + struct nouveau_channel *chan = dev_priv->fifos[0]; + struct nouveau_gpuobj *ramin = chan->ramin->gpuobj; + int i; + + nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, (ramin->im_backing_start >> 16)); + for (i = 0; i < ramin->im_pramin->size; i += 4) + BAR0_WI32(ramin, i, ramin->im_backing_suspend[i/4]); + vfree(ramin->im_backing_suspend); + ramin->im_backing_suspend = NULL; + + /* Poke the relevant regs, and pray it works :) */ + nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12)); + nv_wr32(dev, NV50_PUNK_UNK1710, 0); + nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12) | + NV50_PUNK_BAR_CFG_BASE_VALID); + nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->fb_bar->instance >> 4) | + NV50_PUNK_BAR1_CTXDMA_VALID); + nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->instance >> 4) | + NV50_PUNK_BAR3_CTXDMA_VALID); + + for (i = 0; i < 8; i++) + nv_wr32(dev, 0x1900 + (i*4), 0); +} + +int +nv50_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, + uint32_t *sz) +{ + int ret; + + if (gpuobj->im_backing) + return -EINVAL; + + *sz = (*sz + (NV50_INSTMEM_PAGE_SIZE-1)) & ~(NV50_INSTMEM_PAGE_SIZE-1); + if (*sz == 0) + return -EINVAL; + + ret = nouveau_bo_new(dev, NULL, *sz, 0, TTM_PL_FLAG_VRAM, 0, 0x0000, + true, false, &gpuobj->im_backing); + if (ret) { + NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret); + return ret; + } + + ret = nouveau_bo_pin(gpuobj->im_backing, TTM_PL_FLAG_VRAM); + if (ret) { + NV_ERROR(dev, "error pinning PRAMIN backing VRAM: %d\n", ret); + nouveau_bo_ref(NULL, &gpuobj->im_backing); + return ret; + } + + gpuobj->im_backing_start = gpuobj->im_backing->bo.mem.mm_node->start; + gpuobj->im_backing_start <<= PAGE_SHIFT; + + return 0; +} + +void +nv50_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (gpuobj && gpuobj->im_backing) { + if (gpuobj->im_bound) + dev_priv->engine.instmem.unbind(dev, gpuobj); + nouveau_bo_unpin(gpuobj->im_backing); + nouveau_bo_ref(NULL, &gpuobj->im_backing); + gpuobj->im_backing = NULL; + } +} + +int +nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; + uint32_t pte, pte_end, vram; + + if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) + return -EINVAL; + + NV_DEBUG(dev, "st=0x%0llx sz=0x%0llx\n", + gpuobj->im_pramin->start, gpuobj->im_pramin->size); + + pte = (gpuobj->im_pramin->start >> 12) << 3; + pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte; + vram = gpuobj->im_backing_start; + + NV_DEBUG(dev, "pramin=0x%llx, pte=%d, pte_end=%d\n", + gpuobj->im_pramin->start, pte, pte_end); + NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); + + dev_priv->engine.instmem.prepare_access(dev, true); + while (pte < pte_end) { + nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 0)/4, vram | 1); + nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000); + + pte += 8; + vram += NV50_INSTMEM_PAGE_SIZE; + } + dev_priv->engine.instmem.finish_access(dev); + + nv_wr32(dev, 0x100c80, 0x00040001); + if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { + NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (1)\n"); + NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); + return -EBUSY; + } + + nv_wr32(dev, 0x100c80, 0x00060001); + if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { + NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); + NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); + return -EBUSY; + } + + gpuobj->im_bound = 1; + return 0; +} + +int +nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; + uint32_t pte, pte_end; + + if (gpuobj->im_bound == 0) + return -EINVAL; + + pte = (gpuobj->im_pramin->start >> 12) << 3; + pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte; + + dev_priv->engine.instmem.prepare_access(dev, true); + while (pte < pte_end) { + nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 0)/4, 0x00000009); + nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000); + pte += 8; + } + dev_priv->engine.instmem.finish_access(dev); + + gpuobj->im_bound = 0; + return 0; +} + +void +nv50_instmem_prepare_access(struct drm_device *dev, bool write) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; + + priv->last_access_wr = write; +} + +void +nv50_instmem_finish_access(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; + + if (priv->last_access_wr) { + nv_wr32(dev, 0x070000, 0x00000001); + if (!nv_wait(0x070000, 0x00000001, 0x00000000)) + NV_ERROR(dev, "PRAMIN flush timeout\n"); + } +} + diff --git a/drivers/gpu/drm/nouveau/nv50_mc.c b/drivers/gpu/drm/nouveau/nv50_mc.c new file mode 100644 index 0000000000000000000000000000000000000000..e0a9c3faa202f71fe8d4b6e41cc8c8d0d7c685ce --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_mc.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +int +nv50_mc_init(struct drm_device *dev) +{ + nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF); + return 0; +} + +void nv50_mc_takedown(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c new file mode 100644 index 0000000000000000000000000000000000000000..8c280463a6648bff4cd1e093bb4ea2643339a1a2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_sor.c @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2008 Maarten Maathuis. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h" +#include "drm_crtc_helper.h" + +#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) +#include "nouveau_reg.h" +#include "nouveau_drv.h" +#include "nouveau_dma.h" +#include "nouveau_encoder.h" +#include "nouveau_connector.h" +#include "nouveau_crtc.h" +#include "nv50_display.h" + +static void +nv50_sor_disconnect(struct nouveau_encoder *nv_encoder) +{ + struct drm_device *dev = to_drm_encoder(nv_encoder)->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *evo = dev_priv->evo; + int ret; + + NV_DEBUG(dev, "Disconnecting SOR %d\n", nv_encoder->or); + + ret = RING_SPACE(evo, 2); + if (ret) { + NV_ERROR(dev, "no space while disconnecting SOR\n"); + return; + } + BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); + OUT_RING(evo, 0); +} + +static void +nv50_sor_dp_link_train(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct bit_displayport_encoder_table *dpe; + int dpe_headerlen; + + dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); + if (!dpe) { + NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or); + return; + } + + if (dpe->script0) { + NV_DEBUG(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); + nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0), + nv_encoder->dcb); + } + + if (!nouveau_dp_link_train(encoder)) + NV_ERROR(dev, "SOR-%d: link training failed\n", nv_encoder->or); + + if (dpe->script1) { + NV_DEBUG(dev, "SOR-%d: running DP script 1\n", nv_encoder->or); + nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1), + nv_encoder->dcb); + } +} + +static void +nv50_sor_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + uint32_t val; + int or = nv_encoder->or; + + NV_DEBUG(dev, "or %d mode %d\n", or, mode); + + /* wait for it to be done */ + if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or), + NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) { + NV_ERROR(dev, "timeout: SOR_DPMS_CTRL_PENDING(%d) == 0\n", or); + NV_ERROR(dev, "SOR_DPMS_CTRL(%d) = 0x%08x\n", or, + nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or))); + } + + val = nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or)); + + if (mode == DRM_MODE_DPMS_ON) + val |= NV50_PDISPLAY_SOR_DPMS_CTRL_ON; + else + val &= ~NV50_PDISPLAY_SOR_DPMS_CTRL_ON; + + nv_wr32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or), val | + NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING); + if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_STATE(or), + NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { + NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", or); + NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", or, + nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or))); + } + + if (nv_encoder->dcb->type == OUTPUT_DP && mode == DRM_MODE_DPMS_ON) + nv50_sor_dp_link_train(encoder); +} + +static void +nv50_sor_save(struct drm_encoder *encoder) +{ + NV_ERROR(encoder->dev, "!!\n"); +} + +static void +nv50_sor_restore(struct drm_encoder *encoder) +{ + NV_ERROR(encoder->dev, "!!\n"); +} + +static bool +nv50_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_connector *connector; + + NV_DEBUG(encoder->dev, "or %d\n", nv_encoder->or); + + connector = nouveau_encoder_connector_get(nv_encoder); + if (!connector) { + NV_ERROR(encoder->dev, "Encoder has no connector\n"); + return false; + } + + if (connector->scaling_mode != DRM_MODE_SCALE_NONE && + connector->native_mode) { + int id = adjusted_mode->base.id; + *adjusted_mode = *connector->native_mode; + adjusted_mode->base.id = id; + } + + return true; +} + +static void +nv50_sor_prepare(struct drm_encoder *encoder) +{ +} + +static void +nv50_sor_commit(struct drm_encoder *encoder) +{ +} + +static void +nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; + struct nouveau_channel *evo = dev_priv->evo; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); + uint32_t mode_ctl = 0; + int ret; + + NV_DEBUG(dev, "or %d\n", nv_encoder->or); + + nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); + + switch (nv_encoder->dcb->type) { + case OUTPUT_TMDS: + if (nv_encoder->dcb->sorconf.link & 1) { + if (adjusted_mode->clock < 165000) + mode_ctl = 0x0100; + else + mode_ctl = 0x0500; + } else + mode_ctl = 0x0200; + break; + case OUTPUT_DP: + mode_ctl |= 0x00050000; + if (nv_encoder->dcb->sorconf.link & 1) + mode_ctl |= 0x00000800; + else + mode_ctl |= 0x00000900; + break; + default: + break; + } + + if (crtc->index == 1) + mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC1; + else + mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC0; + + if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) + mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NHSYNC; + + if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) + mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC; + + ret = RING_SPACE(evo, 2); + if (ret) { + NV_ERROR(dev, "no space while connecting SOR\n"); + return; + } + BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); + OUT_RING(evo, mode_ctl); +} + +static const struct drm_encoder_helper_funcs nv50_sor_helper_funcs = { + .dpms = nv50_sor_dpms, + .save = nv50_sor_save, + .restore = nv50_sor_restore, + .mode_fixup = nv50_sor_mode_fixup, + .prepare = nv50_sor_prepare, + .commit = nv50_sor_commit, + .mode_set = nv50_sor_mode_set, + .detect = NULL +}; + +static void +nv50_sor_destroy(struct drm_encoder *encoder) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + if (!encoder) + return; + + NV_DEBUG(encoder->dev, "\n"); + + drm_encoder_cleanup(encoder); + + kfree(nv_encoder); +} + +static const struct drm_encoder_funcs nv50_sor_encoder_funcs = { + .destroy = nv50_sor_destroy, +}; + +int +nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry) +{ + struct nouveau_encoder *nv_encoder = NULL; + struct drm_encoder *encoder; + bool dum; + int type; + + NV_DEBUG(dev, "\n"); + + switch (entry->type) { + case OUTPUT_TMDS: + NV_INFO(dev, "Detected a TMDS output\n"); + type = DRM_MODE_ENCODER_TMDS; + break; + case OUTPUT_LVDS: + NV_INFO(dev, "Detected a LVDS output\n"); + type = DRM_MODE_ENCODER_LVDS; + + if (nouveau_bios_parse_lvds_table(dev, 0, &dum, &dum)) { + NV_ERROR(dev, "Failed parsing LVDS table\n"); + return -EINVAL; + } + break; + case OUTPUT_DP: + NV_INFO(dev, "Detected a DP output\n"); + type = DRM_MODE_ENCODER_TMDS; + break; + default: + return -EINVAL; + } + + nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); + if (!nv_encoder) + return -ENOMEM; + encoder = to_drm_encoder(nv_encoder); + + nv_encoder->dcb = entry; + nv_encoder->or = ffs(entry->or) - 1; + + nv_encoder->disconnect = nv50_sor_disconnect; + + drm_encoder_init(dev, encoder, &nv50_sor_encoder_funcs, type); + drm_encoder_helper_add(encoder, &nv50_sor_helper_funcs); + + encoder->possible_crtcs = entry->heads; + encoder->possible_clones = 0; + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvreg.h b/drivers/gpu/drm/nouveau/nvreg.h new file mode 100644 index 0000000000000000000000000000000000000000..5998c35237b0c6ed5657a1f85b443a5903de1537 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvreg.h @@ -0,0 +1,535 @@ +/* $XConsortium: nvreg.h /main/2 1996/10/28 05:13:41 kaleb $ */ +/* + * Copyright 1996-1997 David J. McKay + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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 + * DAVID J. MCKAY 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. + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nvreg.h,v 1.6 2002/01/25 21:56:06 tsi Exp $ */ + +#ifndef __NVREG_H_ +#define __NVREG_H_ + +#define NV_PMC_OFFSET 0x00000000 +#define NV_PMC_SIZE 0x00001000 + +#define NV_PBUS_OFFSET 0x00001000 +#define NV_PBUS_SIZE 0x00001000 + +#define NV_PFIFO_OFFSET 0x00002000 +#define NV_PFIFO_SIZE 0x00002000 + +#define NV_HDIAG_OFFSET 0x00005000 +#define NV_HDIAG_SIZE 0x00001000 + +#define NV_PRAM_OFFSET 0x00006000 +#define NV_PRAM_SIZE 0x00001000 + +#define NV_PVIDEO_OFFSET 0x00008000 +#define NV_PVIDEO_SIZE 0x00001000 + +#define NV_PTIMER_OFFSET 0x00009000 +#define NV_PTIMER_SIZE 0x00001000 + +#define NV_PPM_OFFSET 0x0000A000 +#define NV_PPM_SIZE 0x00001000 + +#define NV_PTV_OFFSET 0x0000D000 +#define NV_PTV_SIZE 0x00001000 + +#define NV_PRMVGA_OFFSET 0x000A0000 +#define NV_PRMVGA_SIZE 0x00020000 + +#define NV_PRMVIO0_OFFSET 0x000C0000 +#define NV_PRMVIO_SIZE 0x00002000 +#define NV_PRMVIO1_OFFSET 0x000C2000 + +#define NV_PFB_OFFSET 0x00100000 +#define NV_PFB_SIZE 0x00001000 + +#define NV_PEXTDEV_OFFSET 0x00101000 +#define NV_PEXTDEV_SIZE 0x00001000 + +#define NV_PME_OFFSET 0x00200000 +#define NV_PME_SIZE 0x00001000 + +#define NV_PROM_OFFSET 0x00300000 +#define NV_PROM_SIZE 0x00010000 + +#define NV_PGRAPH_OFFSET 0x00400000 +#define NV_PGRAPH_SIZE 0x00010000 + +#define NV_PCRTC0_OFFSET 0x00600000 +#define NV_PCRTC0_SIZE 0x00002000 /* empirical */ + +#define NV_PRMCIO0_OFFSET 0x00601000 +#define NV_PRMCIO_SIZE 0x00002000 +#define NV_PRMCIO1_OFFSET 0x00603000 + +#define NV50_DISPLAY_OFFSET 0x00610000 +#define NV50_DISPLAY_SIZE 0x0000FFFF + +#define NV_PRAMDAC0_OFFSET 0x00680000 +#define NV_PRAMDAC0_SIZE 0x00002000 + +#define NV_PRMDIO0_OFFSET 0x00681000 +#define NV_PRMDIO_SIZE 0x00002000 +#define NV_PRMDIO1_OFFSET 0x00683000 + +#define NV_PRAMIN_OFFSET 0x00700000 +#define NV_PRAMIN_SIZE 0x00100000 + +#define NV_FIFO_OFFSET 0x00800000 +#define NV_FIFO_SIZE 0x00800000 + +#define NV_PMC_BOOT_0 0x00000000 +#define NV_PMC_ENABLE 0x00000200 + +#define NV_VIO_VSE2 0x000003c3 +#define NV_VIO_SRX 0x000003c4 + +#define NV_CIO_CRX__COLOR 0x000003d4 +#define NV_CIO_CR__COLOR 0x000003d5 + +#define NV_PBUS_DEBUG_1 0x00001084 +#define NV_PBUS_DEBUG_4 0x00001098 +#define NV_PBUS_DEBUG_DUALHEAD_CTL 0x000010f0 +#define NV_PBUS_POWERCTRL_1 0x00001584 +#define NV_PBUS_POWERCTRL_2 0x00001588 +#define NV_PBUS_POWERCTRL_4 0x00001590 +#define NV_PBUS_PCI_NV_19 0x0000184C +#define NV_PBUS_PCI_NV_20 0x00001850 +# define NV_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED (0 << 0) +# define NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED (1 << 0) + +#define NV_PFIFO_RAMHT 0x00002210 + +#define NV_PTV_TV_INDEX 0x0000d220 +#define NV_PTV_TV_DATA 0x0000d224 +#define NV_PTV_HFILTER 0x0000d310 +#define NV_PTV_HFILTER2 0x0000d390 +#define NV_PTV_VFILTER 0x0000d510 + +#define NV_PRMVIO_MISC__WRITE 0x000c03c2 +#define NV_PRMVIO_SRX 0x000c03c4 +#define NV_PRMVIO_SR 0x000c03c5 +# define NV_VIO_SR_RESET_INDEX 0x00 +# define NV_VIO_SR_CLOCK_INDEX 0x01 +# define NV_VIO_SR_PLANE_MASK_INDEX 0x02 +# define NV_VIO_SR_CHAR_MAP_INDEX 0x03 +# define NV_VIO_SR_MEM_MODE_INDEX 0x04 +#define NV_PRMVIO_MISC__READ 0x000c03cc +#define NV_PRMVIO_GRX 0x000c03ce +#define NV_PRMVIO_GX 0x000c03cf +# define NV_VIO_GX_SR_INDEX 0x00 +# define NV_VIO_GX_SREN_INDEX 0x01 +# define NV_VIO_GX_CCOMP_INDEX 0x02 +# define NV_VIO_GX_ROP_INDEX 0x03 +# define NV_VIO_GX_READ_MAP_INDEX 0x04 +# define NV_VIO_GX_MODE_INDEX 0x05 +# define NV_VIO_GX_MISC_INDEX 0x06 +# define NV_VIO_GX_DONT_CARE_INDEX 0x07 +# define NV_VIO_GX_BIT_MASK_INDEX 0x08 + +#define NV_PFB_BOOT_0 0x00100000 +#define NV_PFB_CFG0 0x00100200 +#define NV_PFB_CFG1 0x00100204 +#define NV_PFB_CSTATUS 0x0010020C +#define NV_PFB_REFCTRL 0x00100210 +# define NV_PFB_REFCTRL_VALID_1 (1 << 31) +#define NV_PFB_PAD 0x0010021C +# define NV_PFB_PAD_CKE_NORMAL (1 << 0) +#define NV_PFB_TILE_NV10 0x00100240 +#define NV_PFB_TILE_SIZE_NV10 0x00100244 +#define NV_PFB_REF 0x001002D0 +# define NV_PFB_REF_CMD_REFRESH (1 << 0) +#define NV_PFB_PRE 0x001002D4 +# define NV_PFB_PRE_CMD_PRECHARGE (1 << 0) +#define NV_PFB_CLOSE_PAGE2 0x0010033C +#define NV_PFB_TILE_NV40 0x00100600 +#define NV_PFB_TILE_SIZE_NV40 0x00100604 + +#define NV_PEXTDEV_BOOT_0 0x00101000 +# define NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT (8 << 12) +#define NV_PEXTDEV_BOOT_3 0x0010100c + +#define NV_PCRTC_INTR_0 0x00600100 +# define NV_PCRTC_INTR_0_VBLANK (1 << 0) +#define NV_PCRTC_INTR_EN_0 0x00600140 +#define NV_PCRTC_START 0x00600800 +#define NV_PCRTC_CONFIG 0x00600804 +# define NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA (1 << 0) +# define NV_PCRTC_CONFIG_START_ADDRESS_HSYNC (2 << 0) +#define NV_PCRTC_CURSOR_CONFIG 0x00600810 +# define NV_PCRTC_CURSOR_CONFIG_ENABLE_ENABLE (1 << 0) +# define NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE (1 << 4) +# define NV_PCRTC_CURSOR_CONFIG_ADDRESS_SPACE_PNVM (1 << 8) +# define NV_PCRTC_CURSOR_CONFIG_CUR_BPP_32 (1 << 12) +# define NV_PCRTC_CURSOR_CONFIG_CUR_PIXELS_64 (1 << 16) +# define NV_PCRTC_CURSOR_CONFIG_CUR_LINES_32 (2 << 24) +# define NV_PCRTC_CURSOR_CONFIG_CUR_LINES_64 (4 << 24) +# define NV_PCRTC_CURSOR_CONFIG_CUR_BLEND_ALPHA (1 << 28) + +/* note: PCRTC_GPIO is not available on nv10, and in fact aliases 0x600810 */ +#define NV_PCRTC_GPIO 0x00600818 +#define NV_PCRTC_GPIO_EXT 0x0060081c +#define NV_PCRTC_830 0x00600830 +#define NV_PCRTC_834 0x00600834 +#define NV_PCRTC_850 0x00600850 +#define NV_PCRTC_ENGINE_CTRL 0x00600860 +# define NV_CRTC_FSEL_I2C (1 << 4) +# define NV_CRTC_FSEL_OVERLAY (1 << 12) + +#define NV_PRMCIO_ARX 0x006013c0 +#define NV_PRMCIO_AR__WRITE 0x006013c0 +#define NV_PRMCIO_AR__READ 0x006013c1 +# define NV_CIO_AR_MODE_INDEX 0x10 +# define NV_CIO_AR_OSCAN_INDEX 0x11 +# define NV_CIO_AR_PLANE_INDEX 0x12 +# define NV_CIO_AR_HPP_INDEX 0x13 +# define NV_CIO_AR_CSEL_INDEX 0x14 +#define NV_PRMCIO_INP0 0x006013c2 +#define NV_PRMCIO_CRX__COLOR 0x006013d4 +#define NV_PRMCIO_CR__COLOR 0x006013d5 + /* Standard VGA CRTC registers */ +# define NV_CIO_CR_HDT_INDEX 0x00 /* horizontal display total */ +# define NV_CIO_CR_HDE_INDEX 0x01 /* horizontal display end */ +# define NV_CIO_CR_HBS_INDEX 0x02 /* horizontal blanking start */ +# define NV_CIO_CR_HBE_INDEX 0x03 /* horizontal blanking end */ +# define NV_CIO_CR_HBE_4_0 4:0 +# define NV_CIO_CR_HRS_INDEX 0x04 /* horizontal retrace start */ +# define NV_CIO_CR_HRE_INDEX 0x05 /* horizontal retrace end */ +# define NV_CIO_CR_HRE_4_0 4:0 +# define NV_CIO_CR_HRE_HBE_5 7:7 +# define NV_CIO_CR_VDT_INDEX 0x06 /* vertical display total */ +# define NV_CIO_CR_OVL_INDEX 0x07 /* overflow bits */ +# define NV_CIO_CR_OVL_VDT_8 0:0 +# define NV_CIO_CR_OVL_VDE_8 1:1 +# define NV_CIO_CR_OVL_VRS_8 2:2 +# define NV_CIO_CR_OVL_VBS_8 3:3 +# define NV_CIO_CR_OVL_VDT_9 5:5 +# define NV_CIO_CR_OVL_VDE_9 6:6 +# define NV_CIO_CR_OVL_VRS_9 7:7 +# define NV_CIO_CR_RSAL_INDEX 0x08 /* normally "preset row scan" */ +# define NV_CIO_CR_CELL_HT_INDEX 0x09 /* cell height?! normally "max scan line" */ +# define NV_CIO_CR_CELL_HT_VBS_9 5:5 +# define NV_CIO_CR_CELL_HT_SCANDBL 7:7 +# define NV_CIO_CR_CURS_ST_INDEX 0x0a /* cursor start */ +# define NV_CIO_CR_CURS_END_INDEX 0x0b /* cursor end */ +# define NV_CIO_CR_SA_HI_INDEX 0x0c /* screen start address high */ +# define NV_CIO_CR_SA_LO_INDEX 0x0d /* screen start address low */ +# define NV_CIO_CR_TCOFF_HI_INDEX 0x0e /* cursor offset high */ +# define NV_CIO_CR_TCOFF_LO_INDEX 0x0f /* cursor offset low */ +# define NV_CIO_CR_VRS_INDEX 0x10 /* vertical retrace start */ +# define NV_CIO_CR_VRE_INDEX 0x11 /* vertical retrace end */ +# define NV_CIO_CR_VRE_3_0 3:0 +# define NV_CIO_CR_VDE_INDEX 0x12 /* vertical display end */ +# define NV_CIO_CR_OFFSET_INDEX 0x13 /* sets screen pitch */ +# define NV_CIO_CR_ULINE_INDEX 0x14 /* underline location */ +# define NV_CIO_CR_VBS_INDEX 0x15 /* vertical blank start */ +# define NV_CIO_CR_VBE_INDEX 0x16 /* vertical blank end */ +# define NV_CIO_CR_MODE_INDEX 0x17 /* crtc mode control */ +# define NV_CIO_CR_LCOMP_INDEX 0x18 /* line compare */ + /* Extended VGA CRTC registers */ +# define NV_CIO_CRE_RPC0_INDEX 0x19 /* repaint control 0 */ +# define NV_CIO_CRE_RPC0_OFFSET_10_8 7:5 +# define NV_CIO_CRE_RPC1_INDEX 0x1a /* repaint control 1 */ +# define NV_CIO_CRE_RPC1_LARGE 2:2 +# define NV_CIO_CRE_FF_INDEX 0x1b /* fifo control */ +# define NV_CIO_CRE_ENH_INDEX 0x1c /* enhanced? */ +# define NV_CIO_SR_LOCK_INDEX 0x1f /* crtc lock */ +# define NV_CIO_SR_UNLOCK_RW_VALUE 0x57 +# define NV_CIO_SR_LOCK_VALUE 0x99 +# define NV_CIO_CRE_FFLWM__INDEX 0x20 /* fifo low water mark */ +# define NV_CIO_CRE_21 0x21 /* vga shadow crtc lock */ +# define NV_CIO_CRE_LSR_INDEX 0x25 /* ? */ +# define NV_CIO_CRE_LSR_VDT_10 0:0 +# define NV_CIO_CRE_LSR_VDE_10 1:1 +# define NV_CIO_CRE_LSR_VRS_10 2:2 +# define NV_CIO_CRE_LSR_VBS_10 3:3 +# define NV_CIO_CRE_LSR_HBE_6 4:4 +# define NV_CIO_CR_ARX_INDEX 0x26 /* attribute index -- ro copy of 0x60.3c0 */ +# define NV_CIO_CRE_CHIP_ID_INDEX 0x27 /* chip revision */ +# define NV_CIO_CRE_PIXEL_INDEX 0x28 +# define NV_CIO_CRE_PIXEL_FORMAT 1:0 +# define NV_CIO_CRE_HEB__INDEX 0x2d /* horizontal extra bits? */ +# define NV_CIO_CRE_HEB_HDT_8 0:0 +# define NV_CIO_CRE_HEB_HDE_8 1:1 +# define NV_CIO_CRE_HEB_HBS_8 2:2 +# define NV_CIO_CRE_HEB_HRS_8 3:3 +# define NV_CIO_CRE_HEB_ILC_8 4:4 +# define NV_CIO_CRE_2E 0x2e /* some scratch or dummy reg to force writes to sink in */ +# define NV_CIO_CRE_HCUR_ADDR2_INDEX 0x2f /* cursor */ +# define NV_CIO_CRE_HCUR_ADDR0_INDEX 0x30 /* pixmap */ +# define NV_CIO_CRE_HCUR_ADDR0_ADR 6:0 +# define NV_CIO_CRE_HCUR_ASI 7:7 +# define NV_CIO_CRE_HCUR_ADDR1_INDEX 0x31 /* address */ +# define NV_CIO_CRE_HCUR_ADDR1_ENABLE 0:0 +# define NV_CIO_CRE_HCUR_ADDR1_CUR_DBL 1:1 +# define NV_CIO_CRE_HCUR_ADDR1_ADR 7:2 +# define NV_CIO_CRE_LCD__INDEX 0x33 +# define NV_CIO_CRE_LCD_LCD_SELECT 0:0 +# define NV_CIO_CRE_DDC0_STATUS__INDEX 0x36 +# define NV_CIO_CRE_DDC0_WR__INDEX 0x37 +# define NV_CIO_CRE_ILACE__INDEX 0x39 /* interlace */ +# define NV_CIO_CRE_SCRATCH3__INDEX 0x3b +# define NV_CIO_CRE_SCRATCH4__INDEX 0x3c +# define NV_CIO_CRE_DDC_STATUS__INDEX 0x3e +# define NV_CIO_CRE_DDC_WR__INDEX 0x3f +# define NV_CIO_CRE_EBR_INDEX 0x41 /* extra bits ? (vertical) */ +# define NV_CIO_CRE_EBR_VDT_11 0:0 +# define NV_CIO_CRE_EBR_VDE_11 2:2 +# define NV_CIO_CRE_EBR_VRS_11 4:4 +# define NV_CIO_CRE_EBR_VBS_11 6:6 +# define NV_CIO_CRE_43 0x43 +# define NV_CIO_CRE_44 0x44 /* head control */ +# define NV_CIO_CRE_CSB 0x45 /* colour saturation boost */ +# define NV_CIO_CRE_RCR 0x46 +# define NV_CIO_CRE_RCR_ENDIAN_BIG 7:7 +# define NV_CIO_CRE_47 0x47 /* extended fifo lwm, used on nv30+ */ +# define NV_CIO_CRE_49 0x49 +# define NV_CIO_CRE_4B 0x4b /* given patterns in 0x[2-3][a-c] regs, probably scratch 6 */ +# define NV_CIO_CRE_TVOUT_LATENCY 0x52 +# define NV_CIO_CRE_53 0x53 /* `fp_htiming' according to Haiku */ +# define NV_CIO_CRE_54 0x54 /* `fp_vtiming' according to Haiku */ +# define NV_CIO_CRE_57 0x57 /* index reg for cr58 */ +# define NV_CIO_CRE_58 0x58 /* data reg for cr57 */ +# define NV_CIO_CRE_59 0x59 /* related to on/off-chip-ness of digital outputs */ +# define NV_CIO_CRE_5B 0x5B /* newer colour saturation reg */ +# define NV_CIO_CRE_85 0x85 +# define NV_CIO_CRE_86 0x86 +#define NV_PRMCIO_INP0__COLOR 0x006013da + +#define NV_PRAMDAC_CU_START_POS 0x00680300 +# define NV_PRAMDAC_CU_START_POS_X 15:0 +# define NV_PRAMDAC_CU_START_POS_Y 31:16 +#define NV_RAMDAC_NV10_CURSYNC 0x00680404 + +#define NV_PRAMDAC_NVPLL_COEFF 0x00680500 +#define NV_PRAMDAC_MPLL_COEFF 0x00680504 +#define NV_PRAMDAC_VPLL_COEFF 0x00680508 +# define NV30_RAMDAC_ENABLE_VCO2 (8 << 4) + +#define NV_PRAMDAC_PLL_COEFF_SELECT 0x0068050c +# define NV_PRAMDAC_PLL_COEFF_SELECT_USE_VPLL2_TRUE (4 << 0) +# define NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_MPLL (1 << 8) +# define NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_VPLL (2 << 8) +# define NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_NVPLL (4 << 8) +# define NV_PRAMDAC_PLL_COEFF_SELECT_PLL_SOURCE_VPLL2 (8 << 8) +# define NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1 (1 << 16) +# define NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1 (2 << 16) +# define NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK2 (4 << 16) +# define NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK2 (8 << 16) +# define NV_PRAMDAC_PLL_COEFF_SELECT_TV_CLK_SOURCE_VIP (1 << 20) +# define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB2 (1 << 28) +# define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK2_RATIO_DB2 (2 << 28) + +#define NV_PRAMDAC_PLL_SETUP_CONTROL 0x00680510 +#define NV_RAMDAC_VPLL2 0x00680520 +#define NV_PRAMDAC_SEL_CLK 0x00680524 +#define NV_RAMDAC_DITHER_NV11 0x00680528 +#define NV_PRAMDAC_DACCLK 0x0068052c +# define NV_PRAMDAC_DACCLK_SEL_DACCLK (1 << 0) + +#define NV_RAMDAC_NVPLL_B 0x00680570 +#define NV_RAMDAC_MPLL_B 0x00680574 +#define NV_RAMDAC_VPLL_B 0x00680578 +#define NV_RAMDAC_VPLL2_B 0x0068057c +# define NV31_RAMDAC_ENABLE_VCO2 (8 << 28) +#define NV_PRAMDAC_580 0x00680580 +# define NV_RAMDAC_580_VPLL1_ACTIVE (1 << 8) +# define NV_RAMDAC_580_VPLL2_ACTIVE (1 << 28) + +#define NV_PRAMDAC_GENERAL_CONTROL 0x00680600 +# define NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON (3 << 4) +# define NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL (1 << 8) +# define NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL (1 << 12) +# define NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_75OHM (2 << 16) +# define NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS (1 << 20) +# define NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG (2 << 28) +#define NV_PRAMDAC_TEST_CONTROL 0x00680608 +# define NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED (1 << 12) +# define NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF (1 << 16) +# define NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI (1 << 28) +#define NV_PRAMDAC_TESTPOINT_DATA 0x00680610 +# define NV_PRAMDAC_TESTPOINT_DATA_NOTBLANK (8 << 28) +#define NV_PRAMDAC_630 0x00680630 +#define NV_PRAMDAC_634 0x00680634 + +#define NV_PRAMDAC_TV_SETUP 0x00680700 +#define NV_PRAMDAC_TV_VTOTAL 0x00680720 +#define NV_PRAMDAC_TV_VSKEW 0x00680724 +#define NV_PRAMDAC_TV_VSYNC_DELAY 0x00680728 +#define NV_PRAMDAC_TV_HTOTAL 0x0068072c +#define NV_PRAMDAC_TV_HSKEW 0x00680730 +#define NV_PRAMDAC_TV_HSYNC_DELAY 0x00680734 +#define NV_PRAMDAC_TV_HSYNC_DELAY2 0x00680738 + +#define NV_PRAMDAC_TV_SETUP 0x00680700 + +#define NV_PRAMDAC_FP_VDISPLAY_END 0x00680800 +#define NV_PRAMDAC_FP_VTOTAL 0x00680804 +#define NV_PRAMDAC_FP_VCRTC 0x00680808 +#define NV_PRAMDAC_FP_VSYNC_START 0x0068080c +#define NV_PRAMDAC_FP_VSYNC_END 0x00680810 +#define NV_PRAMDAC_FP_VVALID_START 0x00680814 +#define NV_PRAMDAC_FP_VVALID_END 0x00680818 +#define NV_PRAMDAC_FP_HDISPLAY_END 0x00680820 +#define NV_PRAMDAC_FP_HTOTAL 0x00680824 +#define NV_PRAMDAC_FP_HCRTC 0x00680828 +#define NV_PRAMDAC_FP_HSYNC_START 0x0068082c +#define NV_PRAMDAC_FP_HSYNC_END 0x00680830 +#define NV_PRAMDAC_FP_HVALID_START 0x00680834 +#define NV_PRAMDAC_FP_HVALID_END 0x00680838 + +#define NV_RAMDAC_FP_DITHER 0x0068083c +#define NV_PRAMDAC_FP_TG_CONTROL 0x00680848 +# define NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS (1 << 0) +# define NV_PRAMDAC_FP_TG_CONTROL_VSYNC_DISABLE (2 << 0) +# define NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS (1 << 4) +# define NV_PRAMDAC_FP_TG_CONTROL_HSYNC_DISABLE (2 << 4) +# define NV_PRAMDAC_FP_TG_CONTROL_MODE_SCALE (0 << 8) +# define NV_PRAMDAC_FP_TG_CONTROL_MODE_CENTER (1 << 8) +# define NV_PRAMDAC_FP_TG_CONTROL_MODE_NATIVE (2 << 8) +# define NV_PRAMDAC_FP_TG_CONTROL_READ_PROG (1 << 20) +# define NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12 (1 << 24) +# define NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS (1 << 28) +# define NV_PRAMDAC_FP_TG_CONTROL_DISPEN_DISABLE (2 << 28) +#define NV_PRAMDAC_FP_MARGIN_COLOR 0x0068084c +#define NV_PRAMDAC_850 0x00680850 +#define NV_PRAMDAC_85C 0x0068085c +#define NV_PRAMDAC_FP_DEBUG_0 0x00680880 +# define NV_PRAMDAC_FP_DEBUG_0_XSCALE_ENABLE (1 << 0) +# define NV_PRAMDAC_FP_DEBUG_0_YSCALE_ENABLE (1 << 4) +/* This doesn't seem to be essential for tmds, but still often set */ +# define NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED (8 << 4) +# define NV_PRAMDAC_FP_DEBUG_0_XINTERP_BILINEAR (1 << 8) +# define NV_PRAMDAC_FP_DEBUG_0_YINTERP_BILINEAR (1 << 12) +# define NV_PRAMDAC_FP_DEBUG_0_XWEIGHT_ROUND (1 << 20) +# define NV_PRAMDAC_FP_DEBUG_0_YWEIGHT_ROUND (1 << 24) +# define NV_PRAMDAC_FP_DEBUG_0_PWRDOWN_FPCLK (1 << 28) +#define NV_PRAMDAC_FP_DEBUG_1 0x00680884 +# define NV_PRAMDAC_FP_DEBUG_1_XSCALE_VALUE 11:0 +# define NV_PRAMDAC_FP_DEBUG_1_XSCALE_TESTMODE_ENABLE (1 << 12) +# define NV_PRAMDAC_FP_DEBUG_1_YSCALE_VALUE 27:16 +# define NV_PRAMDAC_FP_DEBUG_1_YSCALE_TESTMODE_ENABLE (1 << 28) +#define NV_PRAMDAC_FP_DEBUG_2 0x00680888 +#define NV_PRAMDAC_FP_DEBUG_3 0x0068088C + +/* see NV_PRAMDAC_INDIR_TMDS in rules.xml */ +#define NV_PRAMDAC_FP_TMDS_CONTROL 0x006808b0 +# define NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE (1 << 16) +#define NV_PRAMDAC_FP_TMDS_DATA 0x006808b4 + +#define NV_PRAMDAC_8C0 0x006808c0 + +/* Some kind of switch */ +#define NV_PRAMDAC_900 0x00680900 +#define NV_PRAMDAC_A20 0x00680A20 +#define NV_PRAMDAC_A24 0x00680A24 +#define NV_PRAMDAC_A34 0x00680A34 + +#define NV_PRAMDAC_CTV 0x00680c00 + +/* names fabricated from NV_USER_DAC info */ +#define NV_PRMDIO_PIXEL_MASK 0x006813c6 +# define NV_PRMDIO_PIXEL_MASK_MASK 0xff +#define NV_PRMDIO_READ_MODE_ADDRESS 0x006813c7 +#define NV_PRMDIO_WRITE_MODE_ADDRESS 0x006813c8 +#define NV_PRMDIO_PALETTE_DATA 0x006813c9 + +#define NV_PGRAPH_DEBUG_0 0x00400080 +#define NV_PGRAPH_DEBUG_1 0x00400084 +#define NV_PGRAPH_DEBUG_2_NV04 0x00400088 +#define NV_PGRAPH_DEBUG_2 0x00400620 +#define NV_PGRAPH_DEBUG_3 0x0040008c +#define NV_PGRAPH_DEBUG_4 0x00400090 +#define NV_PGRAPH_INTR 0x00400100 +#define NV_PGRAPH_INTR_EN 0x00400140 +#define NV_PGRAPH_CTX_CONTROL 0x00400144 +#define NV_PGRAPH_CTX_CONTROL_NV04 0x00400170 +#define NV_PGRAPH_ABS_UCLIP_XMIN 0x0040053C +#define NV_PGRAPH_ABS_UCLIP_YMIN 0x00400540 +#define NV_PGRAPH_ABS_UCLIP_XMAX 0x00400544 +#define NV_PGRAPH_ABS_UCLIP_YMAX 0x00400548 +#define NV_PGRAPH_BETA_AND 0x00400608 +#define NV_PGRAPH_LIMIT_VIOL_PIX 0x00400610 +#define NV_PGRAPH_BOFFSET0 0x00400640 +#define NV_PGRAPH_BOFFSET1 0x00400644 +#define NV_PGRAPH_BOFFSET2 0x00400648 +#define NV_PGRAPH_BLIMIT0 0x00400684 +#define NV_PGRAPH_BLIMIT1 0x00400688 +#define NV_PGRAPH_BLIMIT2 0x0040068c +#define NV_PGRAPH_STATUS 0x00400700 +#define NV_PGRAPH_SURFACE 0x00400710 +#define NV_PGRAPH_STATE 0x00400714 +#define NV_PGRAPH_FIFO 0x00400720 +#define NV_PGRAPH_PATTERN_SHAPE 0x00400810 +#define NV_PGRAPH_TILE 0x00400b00 + +#define NV_PVIDEO_INTR_EN 0x00008140 +#define NV_PVIDEO_BUFFER 0x00008700 +#define NV_PVIDEO_STOP 0x00008704 +#define NV_PVIDEO_UVPLANE_BASE(buff) (0x00008800+(buff)*4) +#define NV_PVIDEO_UVPLANE_LIMIT(buff) (0x00008808+(buff)*4) +#define NV_PVIDEO_UVPLANE_OFFSET_BUFF(buff) (0x00008820+(buff)*4) +#define NV_PVIDEO_BASE(buff) (0x00008900+(buff)*4) +#define NV_PVIDEO_LIMIT(buff) (0x00008908+(buff)*4) +#define NV_PVIDEO_LUMINANCE(buff) (0x00008910+(buff)*4) +#define NV_PVIDEO_CHROMINANCE(buff) (0x00008918+(buff)*4) +#define NV_PVIDEO_OFFSET_BUFF(buff) (0x00008920+(buff)*4) +#define NV_PVIDEO_SIZE_IN(buff) (0x00008928+(buff)*4) +#define NV_PVIDEO_POINT_IN(buff) (0x00008930+(buff)*4) +#define NV_PVIDEO_DS_DX(buff) (0x00008938+(buff)*4) +#define NV_PVIDEO_DT_DY(buff) (0x00008940+(buff)*4) +#define NV_PVIDEO_POINT_OUT(buff) (0x00008948+(buff)*4) +#define NV_PVIDEO_SIZE_OUT(buff) (0x00008950+(buff)*4) +#define NV_PVIDEO_FORMAT(buff) (0x00008958+(buff)*4) +# define NV_PVIDEO_FORMAT_PLANAR (1 << 0) +# define NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8 (1 << 16) +# define NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY (1 << 20) +# define NV_PVIDEO_FORMAT_MATRIX_ITURBT709 (1 << 24) +#define NV_PVIDEO_COLOR_KEY 0x00008B00 + +/* NV04 overlay defines from VIDIX & Haiku */ +#define NV_PVIDEO_INTR_EN_0 0x00680140 +#define NV_PVIDEO_STEP_SIZE 0x00680200 +#define NV_PVIDEO_CONTROL_Y 0x00680204 +#define NV_PVIDEO_CONTROL_X 0x00680208 +#define NV_PVIDEO_BUFF0_START_ADDRESS 0x0068020c +#define NV_PVIDEO_BUFF0_PITCH_LENGTH 0x00680214 +#define NV_PVIDEO_BUFF0_OFFSET 0x0068021c +#define NV_PVIDEO_BUFF1_START_ADDRESS 0x00680210 +#define NV_PVIDEO_BUFF1_PITCH_LENGTH 0x00680218 +#define NV_PVIDEO_BUFF1_OFFSET 0x00680220 +#define NV_PVIDEO_OE_STATE 0x00680224 +#define NV_PVIDEO_SU_STATE 0x00680228 +#define NV_PVIDEO_RM_STATE 0x0068022c +#define NV_PVIDEO_WINDOW_START 0x00680230 +#define NV_PVIDEO_WINDOW_SIZE 0x00680234 +#define NV_PVIDEO_FIFO_THRES_SIZE 0x00680238 +#define NV_PVIDEO_FIFO_BURST_LENGTH 0x0068023c +#define NV_PVIDEO_KEY 0x00680240 +#define NV_PVIDEO_OVERLAY 0x00680244 +#define NV_PVIDEO_RED_CSC_OFFSET 0x00680280 +#define NV_PVIDEO_GREEN_CSC_OFFSET 0x00680284 +#define NV_PVIDEO_BLUE_CSC_OFFSET 0x00680288 +#define NV_PVIDEO_CSC_ADJUST 0x0068028c + +#endif diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index b5713eedd6e1c32fce1fc320b23a81b3bfa5d495..feb52eee43147a8ad0e8b6ffc87d7825cb3444e2 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile @@ -49,7 +49,7 @@ radeon-y += radeon_device.o radeon_kms.o \ radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \ rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \ r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ - r600_blit_kms.o radeon_pm.o + r600_blit_kms.o radeon_pm.o atombios_dp.o radeon-$(CONFIG_COMPAT) += radeon_ioc32.o diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index d67c42555ab9b826b4f18a7a91fa30e02b2522ae..6578d19dff93dafa2d910eaeaebe0cf2247c197f 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -263,10 +263,10 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr, case ATOM_ARG_FB: idx = U8(*ptr); (*ptr)++; + val = gctx->scratch[((gctx->fb_base + idx) / 4)]; if (print) DEBUG("FB[0x%02X]", idx); - printk(KERN_INFO "FB access is not implemented.\n"); - return 0; + break; case ATOM_ARG_IMM: switch (align) { case ATOM_SRC_DWORD: @@ -488,9 +488,9 @@ static void atom_put_dst(atom_exec_context *ctx, int arg, uint8_t attr, case ATOM_ARG_FB: idx = U8(*ptr); (*ptr)++; + gctx->scratch[((gctx->fb_base + idx) / 4)] = val; DEBUG("FB[0x%02X]", idx); - printk(KERN_INFO "FB access is not implemented.\n"); - return; + break; case ATOM_ARG_PLL: idx = U8(*ptr); (*ptr)++; @@ -1214,3 +1214,28 @@ void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev, *crev = CU8(idx + 3); return; } + +int atom_allocate_fb_scratch(struct atom_context *ctx) +{ + int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware); + uint16_t data_offset; + int usage_bytes; + struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage; + + atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset); + + firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset); + + DRM_DEBUG("atom firmware requested %08x %dkb\n", + firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware, + firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb); + + usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024; + if (usage_bytes == 0) + usage_bytes = 20 * 1024; + /* allocate some scratch memory */ + ctx->scratch = kzalloc(usage_bytes, GFP_KERNEL); + if (!ctx->scratch) + return -ENOMEM; + return 0; +} diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h index e6eb38f2bcaeaafaeeb64014ee2b98c8f73068a3..6671848e5ea1012ff0961a72e31f689a6f83f3d7 100644 --- a/drivers/gpu/drm/radeon/atom.h +++ b/drivers/gpu/drm/radeon/atom.h @@ -132,6 +132,7 @@ struct atom_context { uint8_t shift; int cs_equal, cs_above; int io_mode; + uint32_t *scratch; }; extern int atom_debug; @@ -142,6 +143,7 @@ int atom_asic_init(struct atom_context *); void atom_destroy(struct atom_context *); void atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start); void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *frev, uint8_t *crev); +int atom_allocate_fb_scratch(struct atom_context *ctx); #include "atom-types.h" #include "atombios.h" #include "ObjectID.h" diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 6643afc36cea54dae9fd549e2e0713f5eb815bf2..5f48515c77a78cadd95c604403c2ddb0aa32d2cf 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -2680,7 +2680,7 @@ typedef struct _ATOM_I2C_RECORD { typedef struct _ATOM_HPD_INT_RECORD { ATOM_COMMON_RECORD_HEADER sheader; UCHAR ucHPDIntGPIOID; /* Corresponding block in GPIO_PIN_INFO table gives the pin info */ - UCHAR ucPluggged_PinState; + UCHAR ucPlugged_PinState; } ATOM_HPD_INT_RECORD; typedef struct _ATOM_OUTPUT_PROTECTION_RECORD { diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index c15287a590ffca7395784f78ff763883b1e739ce..260fcf59f00ca86d61efe9091e0e4fc1d267775a 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -241,6 +241,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); switch (mode) { case DRM_MODE_DPMS_ON: @@ -248,20 +249,19 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) if (ASIC_IS_DCE3(rdev)) atombios_enable_crtc_memreq(crtc, 1); atombios_blank_crtc(crtc, 0); + drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); + radeon_crtc_load_lut(crtc); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: + drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); atombios_blank_crtc(crtc, 1); if (ASIC_IS_DCE3(rdev)) atombios_enable_crtc_memreq(crtc, 0); atombios_enable_crtc(crtc, 0); break; } - - if (mode != DRM_MODE_DPMS_OFF) { - radeon_crtc_load_lut(crtc); - } } static void @@ -457,9 +457,8 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; - if (!ASIC_IS_AVIVO(rdev) - && (encoder->encoder_type == - DRM_MODE_ENCODER_LVDS)) + if (encoder->encoder_type == + DRM_MODE_ENCODER_LVDS) pll_flags |= RADEON_PLL_USE_REF_DIV; } radeon_encoder = to_radeon_encoder(encoder); @@ -500,8 +499,18 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) else pll = &rdev->clock.p2pll; - radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, - &ref_div, &post_div, pll_flags); + if (ASIC_IS_AVIVO(rdev)) { + if (radeon_new_pll) + radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock, + &fb_div, &frac_fb_div, + &ref_div, &post_div, pll_flags); + else + radeon_compute_pll(pll, adjusted_clock, &pll_clock, + &fb_div, &frac_fb_div, + &ref_div, &post_div, pll_flags); + } else + radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, + &ref_div, &post_div, pll_flags); index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, @@ -574,21 +583,32 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, struct radeon_device *rdev = dev->dev_private; struct radeon_framebuffer *radeon_fb; struct drm_gem_object *obj; - struct drm_radeon_gem_object *obj_priv; + struct radeon_bo *rbo; uint64_t fb_location; uint32_t fb_format, fb_pitch_pixels, tiling_flags; + int r; - if (!crtc->fb) - return -EINVAL; + /* no fb bound */ + if (!crtc->fb) { + DRM_DEBUG("No FB bound\n"); + return 0; + } radeon_fb = to_radeon_framebuffer(crtc->fb); + /* Pin framebuffer & get tilling informations */ obj = radeon_fb->obj; - obj_priv = obj->driver_private; - - if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &fb_location)) { + rbo = obj->driver_private; + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location); + if (unlikely(r != 0)) { + radeon_bo_unreserve(rbo); return -EINVAL; } + radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); + radeon_bo_unreserve(rbo); switch (crtc->fb->bits_per_pixel) { case 8: @@ -618,8 +638,6 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, return -EINVAL; } - radeon_object_get_tiling_flags(obj->driver_private, - &tiling_flags, NULL); if (tiling_flags & RADEON_TILING_MACRO) fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE; @@ -674,7 +692,12 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, if (old_fb && old_fb != crtc->fb) { radeon_fb = to_radeon_framebuffer(old_fb); - radeon_gem_object_unpin(radeon_fb->obj); + rbo = radeon_fb->obj->driver_private; + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + radeon_bo_unpin(rbo); + radeon_bo_unreserve(rbo); } /* Bytes per pixel may have changed */ diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c new file mode 100644 index 0000000000000000000000000000000000000000..0d63c4436e7cdc0db11a99657463d6f8537becdb --- /dev/null +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -0,0 +1,790 @@ +/* + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Authors: Dave Airlie + * Alex Deucher + */ +#include "drmP.h" +#include "radeon_drm.h" +#include "radeon.h" + +#include "atom.h" +#include "atom-bits.h" +#include "drm_dp_helper.h" + +/* move these to drm_dp_helper.c/h */ +#define DP_LINK_CONFIGURATION_SIZE 9 +#define DP_LINK_STATUS_SIZE 6 +#define DP_DPCD_SIZE 8 + +static char *voltage_names[] = { + "0.4V", "0.6V", "0.8V", "1.2V" +}; +static char *pre_emph_names[] = { + "0dB", "3.5dB", "6dB", "9.5dB" +}; + +static const int dp_clocks[] = { + 54000, /* 1 lane, 1.62 Ghz */ + 90000, /* 1 lane, 2.70 Ghz */ + 108000, /* 2 lane, 1.62 Ghz */ + 180000, /* 2 lane, 2.70 Ghz */ + 216000, /* 4 lane, 1.62 Ghz */ + 360000, /* 4 lane, 2.70 Ghz */ +}; + +static const int num_dp_clocks = sizeof(dp_clocks) / sizeof(int); + +/* common helper functions */ +static int dp_lanes_for_mode_clock(u8 dpcd[DP_DPCD_SIZE], int mode_clock) +{ + int i; + u8 max_link_bw; + u8 max_lane_count; + + if (!dpcd) + return 0; + + max_link_bw = dpcd[DP_MAX_LINK_RATE]; + max_lane_count = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; + + switch (max_link_bw) { + case DP_LINK_BW_1_62: + default: + for (i = 0; i < num_dp_clocks; i++) { + if (i % 2) + continue; + switch (max_lane_count) { + case 1: + if (i > 1) + return 0; + break; + case 2: + if (i > 3) + return 0; + break; + case 4: + default: + break; + } + if (dp_clocks[i] > mode_clock) { + if (i < 2) + return 1; + else if (i < 4) + return 2; + else + return 4; + } + } + break; + case DP_LINK_BW_2_7: + for (i = 0; i < num_dp_clocks; i++) { + switch (max_lane_count) { + case 1: + if (i > 1) + return 0; + break; + case 2: + if (i > 3) + return 0; + break; + case 4: + default: + break; + } + if (dp_clocks[i] > mode_clock) { + if (i < 2) + return 1; + else if (i < 4) + return 2; + else + return 4; + } + } + break; + } + + return 0; +} + +static int dp_link_clock_for_mode_clock(u8 dpcd[DP_DPCD_SIZE], int mode_clock) +{ + int i; + u8 max_link_bw; + u8 max_lane_count; + + if (!dpcd) + return 0; + + max_link_bw = dpcd[DP_MAX_LINK_RATE]; + max_lane_count = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; + + switch (max_link_bw) { + case DP_LINK_BW_1_62: + default: + for (i = 0; i < num_dp_clocks; i++) { + if (i % 2) + continue; + switch (max_lane_count) { + case 1: + if (i > 1) + return 0; + break; + case 2: + if (i > 3) + return 0; + break; + case 4: + default: + break; + } + if (dp_clocks[i] > mode_clock) + return 162000; + } + break; + case DP_LINK_BW_2_7: + for (i = 0; i < num_dp_clocks; i++) { + switch (max_lane_count) { + case 1: + if (i > 1) + return 0; + break; + case 2: + if (i > 3) + return 0; + break; + case 4: + default: + break; + } + if (dp_clocks[i] > mode_clock) + return (i % 2) ? 270000 : 162000; + } + } + + return 0; +} + +int dp_mode_valid(u8 dpcd[DP_DPCD_SIZE], int mode_clock) +{ + int lanes = dp_lanes_for_mode_clock(dpcd, mode_clock); + int bw = dp_lanes_for_mode_clock(dpcd, mode_clock); + + if ((lanes == 0) || (bw == 0)) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static u8 dp_link_status(u8 link_status[DP_LINK_STATUS_SIZE], int r) +{ + return link_status[r - DP_LANE0_1_STATUS]; +} + +static u8 dp_get_lane_status(u8 link_status[DP_LINK_STATUS_SIZE], + int lane) +{ + int i = DP_LANE0_1_STATUS + (lane >> 1); + int s = (lane & 1) * 4; + u8 l = dp_link_status(link_status, i); + return (l >> s) & 0xf; +} + +static bool dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE], + int lane_count) +{ + int lane; + u8 lane_status; + + for (lane = 0; lane < lane_count; lane++) { + lane_status = dp_get_lane_status(link_status, lane); + if ((lane_status & DP_LANE_CR_DONE) == 0) + return false; + } + return true; +} + +static bool dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE], + int lane_count) +{ + u8 lane_align; + u8 lane_status; + int lane; + + lane_align = dp_link_status(link_status, + DP_LANE_ALIGN_STATUS_UPDATED); + if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) + return false; + for (lane = 0; lane < lane_count; lane++) { + lane_status = dp_get_lane_status(link_status, lane); + if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS) + return false; + } + return true; +} + +static u8 dp_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE], + int lane) + +{ + int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); + int s = ((lane & 1) ? + DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : + DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); + u8 l = dp_link_status(link_status, i); + + return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; +} + +static u8 dp_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE], + int lane) +{ + int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); + int s = ((lane & 1) ? + DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : + DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); + u8 l = dp_link_status(link_status, i); + + return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; +} + +/* XXX fix me -- chip specific */ +#define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 +static u8 dp_pre_emphasis_max(u8 voltage_swing) +{ + switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_600: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_800: + return DP_TRAIN_PRE_EMPHASIS_3_5; + case DP_TRAIN_VOLTAGE_SWING_1200: + default: + return DP_TRAIN_PRE_EMPHASIS_0; + } +} + +static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], + int lane_count, + u8 train_set[4]) +{ + u8 v = 0; + u8 p = 0; + int lane; + + for (lane = 0; lane < lane_count; lane++) { + u8 this_v = dp_get_adjust_request_voltage(link_status, lane); + u8 this_p = dp_get_adjust_request_pre_emphasis(link_status, lane); + + DRM_DEBUG("requested signal parameters: lane %d voltage %s pre_emph %s\n", + lane, + voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT], + pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); + + if (this_v > v) + v = this_v; + if (this_p > p) + p = this_p; + } + + if (v >= DP_VOLTAGE_MAX) + v = DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED; + + if (p >= dp_pre_emphasis_max(v)) + p = dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + + DRM_DEBUG("using signal parameters: voltage %s pre_emph %s\n", + voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT], + pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); + + for (lane = 0; lane < 4; lane++) + train_set[lane] = v | p; +} + + +/* radeon aux chan functions */ +bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes, + int num_bytes, u8 *read_byte, + u8 read_buf_len, u8 delay) +{ + struct drm_device *dev = chan->dev; + struct radeon_device *rdev = dev->dev_private; + PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); + unsigned char *base; + + memset(&args, 0, sizeof(args)); + + base = (unsigned char *)rdev->mode_info.atom_context->scratch; + + memcpy(base, req_bytes, num_bytes); + + args.lpAuxRequest = 0; + args.lpDataOut = 16; + args.ucDataOutLen = 0; + args.ucChannelID = chan->rec.i2c_id; + args.ucDelay = delay / 10; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + if (args.ucReplyStatus) { + DRM_DEBUG("failed to get auxch %02x%02x %02x %02x 0x%02x %02x\n", + req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], + chan->rec.i2c_id, args.ucReplyStatus); + return false; + } + + if (args.ucDataOutLen && read_byte && read_buf_len) { + if (read_buf_len < args.ucDataOutLen) { + DRM_ERROR("Buffer to small for return answer %d %d\n", + read_buf_len, args.ucDataOutLen); + return false; + } + { + int len = min(read_buf_len, args.ucDataOutLen); + memcpy(read_byte, base + 16, len); + } + } + return true; +} + +bool radeon_dp_aux_native_write(struct radeon_connector *radeon_connector, uint16_t address, + uint8_t send_bytes, uint8_t *send) +{ + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + u8 msg[20]; + u8 msg_len, dp_msg_len; + bool ret; + + dp_msg_len = 4; + msg[0] = address; + msg[1] = address >> 8; + msg[2] = AUX_NATIVE_WRITE << 4; + dp_msg_len += send_bytes; + msg[3] = (dp_msg_len << 4) | (send_bytes - 1); + + if (send_bytes > 16) + return false; + + memcpy(&msg[4], send, send_bytes); + msg_len = 4 + send_bytes; + ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, msg, msg_len, NULL, 0, 0); + return ret; +} + +bool radeon_dp_aux_native_read(struct radeon_connector *radeon_connector, uint16_t address, + uint8_t delay, uint8_t expected_bytes, + uint8_t *read_p) +{ + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + u8 msg[20]; + u8 msg_len, dp_msg_len; + bool ret = false; + msg_len = 4; + dp_msg_len = 4; + msg[0] = address; + msg[1] = address >> 8; + msg[2] = AUX_NATIVE_READ << 4; + msg[3] = (dp_msg_len) << 4; + msg[3] |= expected_bytes - 1; + + ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, msg, msg_len, read_p, expected_bytes, delay); + return ret; +} + +/* radeon dp functions */ +static u8 radeon_dp_encoder_service(struct radeon_device *rdev, int action, int dp_clock, + uint8_t ucconfig, uint8_t lane_num) +{ + DP_ENCODER_SERVICE_PARAMETERS args; + int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); + + memset(&args, 0, sizeof(args)); + args.ucLinkClock = dp_clock / 10; + args.ucConfig = ucconfig; + args.ucAction = action; + args.ucLaneNum = lane_num; + args.ucStatus = 0; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + return args.ucStatus; +} + +u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector) +{ + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + struct drm_device *dev = radeon_connector->base.dev; + struct radeon_device *rdev = dev->dev_private; + + return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0, + dig_connector->dp_i2c_bus->rec.i2c_id, 0); +} + +bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) +{ + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + u8 msg[25]; + int ret; + + ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, 0, 8, msg); + if (ret) { + memcpy(dig_connector->dpcd, msg, 8); + { + int i; + DRM_DEBUG("DPCD: "); + for (i = 0; i < 8; i++) + DRM_DEBUG("%02x ", msg[i]); + DRM_DEBUG("\n"); + } + return true; + } + dig_connector->dpcd[0] = 0; + return false; +} + +void radeon_dp_set_link_config(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct radeon_connector *radeon_connector; + struct radeon_connector_atom_dig *dig_connector; + + if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) + return; + + radeon_connector = to_radeon_connector(connector); + if (!radeon_connector->con_priv) + return; + dig_connector = radeon_connector->con_priv; + + dig_connector->dp_clock = + dp_link_clock_for_mode_clock(dig_connector->dpcd, mode->clock); + dig_connector->dp_lane_count = + dp_lanes_for_mode_clock(dig_connector->dpcd, mode->clock); +} + +int radeon_dp_mode_valid_helper(struct radeon_connector *radeon_connector, + struct drm_display_mode *mode) +{ + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + + return dp_mode_valid(dig_connector->dpcd, mode->clock); +} + +static bool atom_dp_get_link_status(struct radeon_connector *radeon_connector, + u8 link_status[DP_LINK_STATUS_SIZE]) +{ + int ret; + ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, 100, + DP_LINK_STATUS_SIZE, link_status); + if (!ret) { + DRM_ERROR("displayport link status failed\n"); + return false; + } + + DRM_DEBUG("link status %02x %02x %02x %02x %02x %02x\n", + link_status[0], link_status[1], link_status[2], + link_status[3], link_status[4], link_status[5]); + return true; +} + +bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) +{ + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + u8 link_status[DP_LINK_STATUS_SIZE]; + + if (!atom_dp_get_link_status(radeon_connector, link_status)) + return false; + if (dp_channel_eq_ok(link_status, dig_connector->dp_lane_count)) + return false; + return true; +} + +static void dp_set_power(struct radeon_connector *radeon_connector, u8 power_state) +{ + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + + if (dig_connector->dpcd[0] >= 0x11) { + radeon_dp_aux_native_write(radeon_connector, DP_SET_POWER, 1, + &power_state); + } +} + +static void dp_set_downspread(struct radeon_connector *radeon_connector, u8 downspread) +{ + radeon_dp_aux_native_write(radeon_connector, DP_DOWNSPREAD_CTRL, 1, + &downspread); +} + +static void dp_set_link_bw_lanes(struct radeon_connector *radeon_connector, + u8 link_configuration[DP_LINK_CONFIGURATION_SIZE]) +{ + radeon_dp_aux_native_write(radeon_connector, DP_LINK_BW_SET, 2, + link_configuration); +} + +static void dp_update_dpvs_emph(struct radeon_connector *radeon_connector, + struct drm_encoder *encoder, + u8 train_set[4]) +{ + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + int i; + + for (i = 0; i < dig_connector->dp_lane_count; i++) + atombios_dig_transmitter_setup(encoder, + ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH, + i, train_set[i]); + + radeon_dp_aux_native_write(radeon_connector, DP_TRAINING_LANE0_SET, + dig_connector->dp_lane_count, train_set); +} + +static void dp_set_training(struct radeon_connector *radeon_connector, + u8 training) +{ + radeon_dp_aux_native_write(radeon_connector, DP_TRAINING_PATTERN_SET, + 1, &training); +} + +void dp_link_train(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig; + struct radeon_connector *radeon_connector; + struct radeon_connector_atom_dig *dig_connector; + int enc_id = 0; + bool clock_recovery, channel_eq; + u8 link_status[DP_LINK_STATUS_SIZE]; + u8 link_configuration[DP_LINK_CONFIGURATION_SIZE]; + u8 tries, voltage; + u8 train_set[4]; + int i; + + if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) + return; + + if (!radeon_encoder->enc_priv) + return; + dig = radeon_encoder->enc_priv; + + radeon_connector = to_radeon_connector(connector); + if (!radeon_connector->con_priv) + return; + dig_connector = radeon_connector->con_priv; + + if (ASIC_IS_DCE32(rdev)) { + if (dig->dig_block) + enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER; + else + enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER; + if (dig_connector->linkb) + enc_id |= ATOM_DP_CONFIG_LINK_B; + else + enc_id |= ATOM_DP_CONFIG_LINK_A; + } else { + if (dig_connector->linkb) + enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER | ATOM_DP_CONFIG_LINK_B; + else + enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER | ATOM_DP_CONFIG_LINK_A; + } + + memset(link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); + if (dig_connector->dp_clock == 270000) + link_configuration[0] = DP_LINK_BW_2_7; + else + link_configuration[0] = DP_LINK_BW_1_62; + link_configuration[1] = dig_connector->dp_lane_count; + if (dig_connector->dpcd[0] >= 0x11) + link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + + /* power up the sink */ + dp_set_power(radeon_connector, DP_SET_POWER_D0); + /* disable the training pattern on the sink */ + dp_set_training(radeon_connector, DP_TRAINING_PATTERN_DISABLE); + /* set link bw and lanes on the sink */ + dp_set_link_bw_lanes(radeon_connector, link_configuration); + /* disable downspread on the sink */ + dp_set_downspread(radeon_connector, 0); + /* start training on the source */ + radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_START, + dig_connector->dp_clock, enc_id, 0); + /* set training pattern 1 on the source */ + radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, + dig_connector->dp_clock, enc_id, 0); + + /* set initial vs/emph */ + memset(train_set, 0, 4); + udelay(400); + /* set training pattern 1 on the sink */ + dp_set_training(radeon_connector, DP_TRAINING_PATTERN_1); + + dp_update_dpvs_emph(radeon_connector, encoder, train_set); + + /* clock recovery loop */ + clock_recovery = false; + tries = 0; + voltage = 0xff; + for (;;) { + udelay(100); + if (!atom_dp_get_link_status(radeon_connector, link_status)) + break; + + if (dp_clock_recovery_ok(link_status, dig_connector->dp_lane_count)) { + clock_recovery = true; + break; + } + + for (i = 0; i < dig_connector->dp_lane_count; i++) { + if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) + break; + } + if (i == dig_connector->dp_lane_count) { + DRM_ERROR("clock recovery reached max voltage\n"); + break; + } + + if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { + ++tries; + if (tries == 5) { + DRM_ERROR("clock recovery tried 5 times\n"); + break; + } + } else + tries = 0; + + voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + + /* Compute new train_set as requested by sink */ + dp_get_adjust_train(link_status, dig_connector->dp_lane_count, train_set); + dp_update_dpvs_emph(radeon_connector, encoder, train_set); + } + if (!clock_recovery) + DRM_ERROR("clock recovery failed\n"); + else + DRM_DEBUG("clock recovery at voltage %d pre-emphasis %d\n", + train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, + (train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> + DP_TRAIN_PRE_EMPHASIS_SHIFT); + + + /* set training pattern 2 on the sink */ + dp_set_training(radeon_connector, DP_TRAINING_PATTERN_2); + /* set training pattern 2 on the source */ + radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, + dig_connector->dp_clock, enc_id, 1); + + /* channel equalization loop */ + tries = 0; + channel_eq = false; + for (;;) { + udelay(400); + if (!atom_dp_get_link_status(radeon_connector, link_status)) + break; + + if (dp_channel_eq_ok(link_status, dig_connector->dp_lane_count)) { + channel_eq = true; + break; + } + + /* Try 5 times */ + if (tries > 5) { + DRM_ERROR("channel eq failed: 5 tries\n"); + break; + } + + /* Compute new train_set as requested by sink */ + dp_get_adjust_train(link_status, dig_connector->dp_lane_count, train_set); + dp_update_dpvs_emph(radeon_connector, encoder, train_set); + + tries++; + } + + if (!channel_eq) + DRM_ERROR("channel eq failed\n"); + else + DRM_DEBUG("channel eq at voltage %d pre-emphasis %d\n", + train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, + (train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) + >> DP_TRAIN_PRE_EMPHASIS_SHIFT); + + /* disable the training pattern on the sink */ + dp_set_training(radeon_connector, DP_TRAINING_PATTERN_DISABLE); + + radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, + dig_connector->dp_clock, enc_id, 0); +} + +int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, + uint8_t write_byte, uint8_t *read_byte) +{ + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; + struct radeon_i2c_chan *auxch = (struct radeon_i2c_chan *)adapter; + int ret = 0; + uint16_t address = algo_data->address; + uint8_t msg[5]; + uint8_t reply[2]; + int msg_len, dp_msg_len; + int reply_bytes; + + /* Set up the command byte */ + if (mode & MODE_I2C_READ) + msg[2] = AUX_I2C_READ << 4; + else + msg[2] = AUX_I2C_WRITE << 4; + + if (!(mode & MODE_I2C_STOP)) + msg[2] |= AUX_I2C_MOT << 4; + + msg[0] = address; + msg[1] = address >> 8; + + reply_bytes = 1; + + msg_len = 4; + dp_msg_len = 3; + switch (mode) { + case MODE_I2C_WRITE: + msg[4] = write_byte; + msg_len++; + dp_msg_len += 2; + break; + case MODE_I2C_READ: + dp_msg_len += 1; + break; + default: + break; + } + + msg[3] = (dp_msg_len) << 4; + ret = radeon_process_aux_ch(auxch, msg, msg_len, reply, reply_bytes, 0); + + if (ret) { + if (read_byte) + *read_byte = reply[0]; + return reply_bytes; + } + return -EREMOTEIO; +} + diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index c9e93eabcf16a7c877b9064e7fa86c2f4010cb2b..824cc6480a0654125aae84fc9f5286cde4f3e27b 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -65,6 +65,95 @@ MODULE_FIRMWARE(FIRMWARE_R520); * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ +/* hpd for digital panel detect/disconnect */ +bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) +{ + bool connected = false; + + switch (hpd) { + case RADEON_HPD_1: + if (RREG32(RADEON_FP_GEN_CNTL) & RADEON_FP_DETECT_SENSE) + connected = true; + break; + case RADEON_HPD_2: + if (RREG32(RADEON_FP2_GEN_CNTL) & RADEON_FP2_DETECT_SENSE) + connected = true; + break; + default: + break; + } + return connected; +} + +void r100_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd) +{ + u32 tmp; + bool connected = r100_hpd_sense(rdev, hpd); + + switch (hpd) { + case RADEON_HPD_1: + tmp = RREG32(RADEON_FP_GEN_CNTL); + if (connected) + tmp &= ~RADEON_FP_DETECT_INT_POL; + else + tmp |= RADEON_FP_DETECT_INT_POL; + WREG32(RADEON_FP_GEN_CNTL, tmp); + break; + case RADEON_HPD_2: + tmp = RREG32(RADEON_FP2_GEN_CNTL); + if (connected) + tmp &= ~RADEON_FP2_DETECT_INT_POL; + else + tmp |= RADEON_FP2_DETECT_INT_POL; + WREG32(RADEON_FP2_GEN_CNTL, tmp); + break; + default: + break; + } +} + +void r100_hpd_init(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + rdev->irq.hpd[0] = true; + break; + case RADEON_HPD_2: + rdev->irq.hpd[1] = true; + break; + default: + break; + } + } + r100_irq_set(rdev); +} + +void r100_hpd_fini(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + rdev->irq.hpd[0] = false; + break; + case RADEON_HPD_2: + rdev->irq.hpd[1] = false; + break; + default: + break; + } + } +} + /* * PCI GART */ @@ -94,6 +183,15 @@ int r100_pci_gart_init(struct radeon_device *rdev) return radeon_gart_table_ram_alloc(rdev); } +/* required on r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ +void r100_enable_bm(struct radeon_device *rdev) +{ + uint32_t tmp; + /* Enable bus mastering */ + tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; + WREG32(RADEON_BUS_CNTL, tmp); +} + int r100_pci_gart_enable(struct radeon_device *rdev) { uint32_t tmp; @@ -105,9 +203,6 @@ int r100_pci_gart_enable(struct radeon_device *rdev) WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_location); tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; WREG32(RADEON_AIC_HI_ADDR, tmp); - /* Enable bus mastering */ - tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; - WREG32(RADEON_BUS_CNTL, tmp); /* set PCI GART page-table base address */ WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr); tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN; @@ -157,6 +252,12 @@ int r100_irq_set(struct radeon_device *rdev) if (rdev->irq.crtc_vblank_int[1]) { tmp |= RADEON_CRTC2_VBLANK_MASK; } + if (rdev->irq.hpd[0]) { + tmp |= RADEON_FP_DETECT_MASK; + } + if (rdev->irq.hpd[1]) { + tmp |= RADEON_FP2_DETECT_MASK; + } WREG32(RADEON_GEN_INT_CNTL, tmp); return 0; } @@ -175,8 +276,9 @@ void r100_irq_disable(struct radeon_device *rdev) static inline uint32_t r100_irq_ack(struct radeon_device *rdev) { uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); - uint32_t irq_mask = RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT | - RADEON_CRTC2_VBLANK_STAT; + uint32_t irq_mask = RADEON_SW_INT_TEST | + RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT | + RADEON_FP_DETECT_STAT | RADEON_FP2_DETECT_STAT; if (irqs) { WREG32(RADEON_GEN_INT_STATUS, irqs); @@ -187,6 +289,7 @@ static inline uint32_t r100_irq_ack(struct radeon_device *rdev) int r100_irq_process(struct radeon_device *rdev) { uint32_t status, msi_rearm; + bool queue_hotplug = false; status = r100_irq_ack(rdev); if (!status) { @@ -207,8 +310,18 @@ int r100_irq_process(struct radeon_device *rdev) if (status & RADEON_CRTC2_VBLANK_STAT) { drm_handle_vblank(rdev->ddev, 1); } + if (status & RADEON_FP_DETECT_STAT) { + queue_hotplug = true; + DRM_DEBUG("HPD1\n"); + } + if (status & RADEON_FP2_DETECT_STAT) { + queue_hotplug = true; + DRM_DEBUG("HPD2\n"); + } status = r100_irq_ack(rdev); } + if (queue_hotplug) + queue_work(rdev->wq, &rdev->hotplug_work); if (rdev->msi_enabled) { switch (rdev->family) { case CHIP_RS400: @@ -255,24 +368,27 @@ int r100_wb_init(struct radeon_device *rdev) int r; if (rdev->wb.wb_obj == NULL) { - r = radeon_object_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, - true, - RADEON_GEM_DOMAIN_GTT, - false, &rdev->wb.wb_obj); + r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true, + RADEON_GEM_DOMAIN_GTT, + &rdev->wb.wb_obj); if (r) { - DRM_ERROR("radeon: failed to create WB buffer (%d).\n", r); + dev_err(rdev->dev, "(%d) create WB buffer failed\n", r); return r; } - r = radeon_object_pin(rdev->wb.wb_obj, - RADEON_GEM_DOMAIN_GTT, - &rdev->wb.gpu_addr); + r = radeon_bo_reserve(rdev->wb.wb_obj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT, + &rdev->wb.gpu_addr); if (r) { - DRM_ERROR("radeon: failed to pin WB buffer (%d).\n", r); + dev_err(rdev->dev, "(%d) pin WB buffer failed\n", r); + radeon_bo_unreserve(rdev->wb.wb_obj); return r; } - r = radeon_object_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); + r = radeon_bo_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); + radeon_bo_unreserve(rdev->wb.wb_obj); if (r) { - DRM_ERROR("radeon: failed to map WB buffer (%d).\n", r); + dev_err(rdev->dev, "(%d) map WB buffer failed\n", r); return r; } } @@ -290,11 +406,19 @@ void r100_wb_disable(struct radeon_device *rdev) void r100_wb_fini(struct radeon_device *rdev) { + int r; + r100_wb_disable(rdev); if (rdev->wb.wb_obj) { - radeon_object_kunmap(rdev->wb.wb_obj); - radeon_object_unpin(rdev->wb.wb_obj); - radeon_object_unref(&rdev->wb.wb_obj); + r = radeon_bo_reserve(rdev->wb.wb_obj, false); + if (unlikely(r != 0)) { + dev_err(rdev->dev, "(%d) can't finish WB\n", r); + return; + } + radeon_bo_kunmap(rdev->wb.wb_obj); + radeon_bo_unpin(rdev->wb.wb_obj); + radeon_bo_unreserve(rdev->wb.wb_obj); + radeon_bo_unref(&rdev->wb.wb_obj); rdev->wb.wb = NULL; rdev->wb.wb_obj = NULL; } @@ -1288,17 +1412,17 @@ static int r100_packet0_check(struct radeon_cs_parser *p, int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt, - struct radeon_object *robj) + struct radeon_bo *robj) { unsigned idx; u32 value; idx = pkt->idx + 1; value = radeon_get_ib_value(p, idx + 2); - if ((value + 1) > radeon_object_size(robj)) { + if ((value + 1) > radeon_bo_size(robj)) { DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER " "(need %u have %lu) !\n", value + 1, - radeon_object_size(robj)); + radeon_bo_size(robj)); return -EINVAL; } return 0; @@ -1583,6 +1707,14 @@ void r100_gpu_init(struct radeon_device *rdev) r100_hdp_reset(rdev); } +void r100_hdp_flush(struct radeon_device *rdev) +{ + u32 tmp; + tmp = RREG32(RADEON_HOST_PATH_CNTL); + tmp |= RADEON_HDP_READ_BUFFER_INVALIDATE; + WREG32(RADEON_HOST_PATH_CNTL, tmp); +} + void r100_hdp_reset(struct radeon_device *rdev) { uint32_t tmp; @@ -1650,6 +1782,17 @@ int r100_gpu_reset(struct radeon_device *rdev) return 0; } +void r100_set_common_regs(struct radeon_device *rdev) +{ + /* set these so they don't interfere with anything */ + WREG32(RADEON_OV0_SCALE_CNTL, 0); + WREG32(RADEON_SUBPIC_CNTL, 0); + WREG32(RADEON_VIPH_CONTROL, 0); + WREG32(RADEON_I2C_CNTL_1, 0); + WREG32(RADEON_DVI_I2C_CNTL_1, 0); + WREG32(RADEON_CAP0_TRIG_CNTL, 0); + WREG32(RADEON_CAP1_TRIG_CNTL, 0); +} /* * VRAM info @@ -2594,7 +2737,7 @@ static int r100_cs_track_cube(struct radeon_device *rdev, struct r100_cs_track *track, unsigned idx) { unsigned face, w, h; - struct radeon_object *cube_robj; + struct radeon_bo *cube_robj; unsigned long size; for (face = 0; face < 5; face++) { @@ -2607,9 +2750,9 @@ static int r100_cs_track_cube(struct radeon_device *rdev, size += track->textures[idx].cube_info[face].offset; - if (size > radeon_object_size(cube_robj)) { + if (size > radeon_bo_size(cube_robj)) { DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", - size, radeon_object_size(cube_robj)); + size, radeon_bo_size(cube_robj)); r100_cs_track_texture_print(&track->textures[idx]); return -1; } @@ -2620,7 +2763,7 @@ static int r100_cs_track_cube(struct radeon_device *rdev, static int r100_cs_track_texture_check(struct radeon_device *rdev, struct r100_cs_track *track) { - struct radeon_object *robj; + struct radeon_bo *robj; unsigned long size; unsigned u, i, w, h; int ret; @@ -2676,9 +2819,9 @@ static int r100_cs_track_texture_check(struct radeon_device *rdev, "%u\n", track->textures[u].tex_coord_type, u); return -EINVAL; } - if (size > radeon_object_size(robj)) { + if (size > radeon_bo_size(robj)) { DRM_ERROR("Texture of unit %u needs %lu bytes but is " - "%lu\n", u, size, radeon_object_size(robj)); + "%lu\n", u, size, radeon_bo_size(robj)); r100_cs_track_texture_print(&track->textures[u]); return -EINVAL; } @@ -2700,10 +2843,10 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) } size = track->cb[i].pitch * track->cb[i].cpp * track->maxy; size += track->cb[i].offset; - if (size > radeon_object_size(track->cb[i].robj)) { + if (size > radeon_bo_size(track->cb[i].robj)) { DRM_ERROR("[drm] Buffer too small for color buffer %d " "(need %lu have %lu) !\n", i, size, - radeon_object_size(track->cb[i].robj)); + radeon_bo_size(track->cb[i].robj)); DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n", i, track->cb[i].pitch, track->cb[i].cpp, track->cb[i].offset, track->maxy); @@ -2717,10 +2860,10 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) } size = track->zb.pitch * track->zb.cpp * track->maxy; size += track->zb.offset; - if (size > radeon_object_size(track->zb.robj)) { + if (size > radeon_bo_size(track->zb.robj)) { DRM_ERROR("[drm] Buffer too small for z buffer " "(need %lu have %lu) !\n", size, - radeon_object_size(track->zb.robj)); + radeon_bo_size(track->zb.robj)); DRM_ERROR("[drm] zbuffer (%u %u %u %u)\n", track->zb.pitch, track->zb.cpp, track->zb.offset, track->maxy); @@ -2738,11 +2881,12 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) "bound\n", prim_walk, i); return -EINVAL; } - if (size > radeon_object_size(track->arrays[i].robj)) { - DRM_ERROR("(PW %u) Vertex array %u need %lu dwords " - "have %lu dwords\n", prim_walk, i, - size >> 2, - radeon_object_size(track->arrays[i].robj) >> 2); + if (size > radeon_bo_size(track->arrays[i].robj)) { + dev_err(rdev->dev, "(PW %u) Vertex array %u " + "need %lu dwords have %lu dwords\n", + prim_walk, i, size >> 2, + radeon_bo_size(track->arrays[i].robj) + >> 2); DRM_ERROR("Max indices %u\n", track->max_indx); return -EINVAL; } @@ -2756,10 +2900,12 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) "bound\n", prim_walk, i); return -EINVAL; } - if (size > radeon_object_size(track->arrays[i].robj)) { - DRM_ERROR("(PW %u) Vertex array %u need %lu dwords " - "have %lu dwords\n", prim_walk, i, size >> 2, - radeon_object_size(track->arrays[i].robj) >> 2); + if (size > radeon_bo_size(track->arrays[i].robj)) { + dev_err(rdev->dev, "(PW %u) Vertex array %u " + "need %lu dwords have %lu dwords\n", + prim_walk, i, size >> 2, + radeon_bo_size(track->arrays[i].robj) + >> 2); return -EINVAL; } } @@ -3101,6 +3247,9 @@ static int r100_startup(struct radeon_device *rdev) { int r; + /* set common regs */ + r100_set_common_regs(rdev); + /* program mc */ r100_mc_program(rdev); /* Resume clock */ r100_clock_startup(rdev); @@ -3108,13 +3257,13 @@ static int r100_startup(struct radeon_device *rdev) r100_gpu_init(rdev); /* Initialize GART (initialize after TTM so we can allocate * memory through TTM but finalize after TTM) */ + r100_enable_bm(rdev); if (rdev->flags & RADEON_IS_PCI) { r = r100_pci_gart_enable(rdev); if (r) return r; } /* Enable IRQ */ - rdev->irq.sw_int = true; r100_irq_set(rdev); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); @@ -3150,6 +3299,8 @@ int r100_resume(struct radeon_device *rdev) radeon_combios_asic_init(rdev->ddev); /* Resume clock after posting */ r100_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); return r100_startup(rdev); } @@ -3174,7 +3325,7 @@ void r100_fini(struct radeon_device *rdev) r100_pci_gart_fini(rdev); radeon_irq_kms_fini(rdev); radeon_fence_driver_fini(rdev); - radeon_object_fini(rdev); + radeon_bo_fini(rdev); radeon_atombios_fini(rdev); kfree(rdev->bios); rdev->bios = NULL; @@ -3242,10 +3393,8 @@ int r100_init(struct radeon_device *rdev) RREG32(R_0007C0_CP_STAT)); } /* check if cards are posted or not */ - if (!radeon_card_posted(rdev) && rdev->bios) { - DRM_INFO("GPU not posted. posting now...\n"); - radeon_combios_asic_init(rdev->ddev); - } + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; /* Set asic errata */ r100_errata(rdev); /* Initialize clocks */ @@ -3264,7 +3413,7 @@ int r100_init(struct radeon_device *rdev) if (r) return r; /* Memory manager */ - r = radeon_object_init(rdev); + r = radeon_bo_init(rdev); if (r) return r; if (rdev->flags & RADEON_IS_PCI) { diff --git a/drivers/gpu/drm/radeon/r100_track.h b/drivers/gpu/drm/radeon/r100_track.h index 0daf0d76a891b240874ba9637ff2fc4c9dda5b6a..ca50903dd2bbff85d8c886f00886e36219f2f961 100644 --- a/drivers/gpu/drm/radeon/r100_track.h +++ b/drivers/gpu/drm/radeon/r100_track.h @@ -10,26 +10,26 @@ * CS functions */ struct r100_cs_track_cb { - struct radeon_object *robj; + struct radeon_bo *robj; unsigned pitch; unsigned cpp; unsigned offset; }; struct r100_cs_track_array { - struct radeon_object *robj; + struct radeon_bo *robj; unsigned esize; }; struct r100_cs_cube_info { - struct radeon_object *robj; - unsigned offset; + struct radeon_bo *robj; + unsigned offset; unsigned width; unsigned height; }; struct r100_cs_track_texture { - struct radeon_object *robj; + struct radeon_bo *robj; struct r100_cs_cube_info cube_info[5]; /* info for 5 non-primary faces */ unsigned pitch; unsigned width; diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 2f43ee8e40480cc2895c663fec62751570a1332f..83378c39d0e3abf207aa60e80f910f34c5fc0162 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -137,14 +137,19 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev) void rv370_pcie_gart_disable(struct radeon_device *rdev) { - uint32_t tmp; + u32 tmp; + int r; tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN); if (rdev->gart.table.vram.robj) { - radeon_object_kunmap(rdev->gart.table.vram.robj); - radeon_object_unpin(rdev->gart.table.vram.robj); + r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); + if (likely(r == 0)) { + radeon_bo_kunmap(rdev->gart.table.vram.robj); + radeon_bo_unpin(rdev->gart.table.vram.robj); + radeon_bo_unreserve(rdev->gart.table.vram.robj); + } } } @@ -1181,6 +1186,9 @@ static int r300_startup(struct radeon_device *rdev) { int r; + /* set common regs */ + r100_set_common_regs(rdev); + /* program mc */ r300_mc_program(rdev); /* Resume clock */ r300_clock_startup(rdev); @@ -1193,13 +1201,18 @@ static int r300_startup(struct radeon_device *rdev) if (r) return r; } + + if (rdev->family == CHIP_R300 || + rdev->family == CHIP_R350 || + rdev->family == CHIP_RV350) + r100_enable_bm(rdev); + if (rdev->flags & RADEON_IS_PCI) { r = r100_pci_gart_enable(rdev); if (r) return r; } /* Enable IRQ */ - rdev->irq.sw_int = true; r100_irq_set(rdev); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); @@ -1237,6 +1250,8 @@ int r300_resume(struct radeon_device *rdev) radeon_combios_asic_init(rdev->ddev); /* Resume clock after posting */ r300_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); return r300_startup(rdev); } @@ -1265,7 +1280,7 @@ void r300_fini(struct radeon_device *rdev) r100_pci_gart_fini(rdev); radeon_irq_kms_fini(rdev); radeon_fence_driver_fini(rdev); - radeon_object_fini(rdev); + radeon_bo_fini(rdev); radeon_atombios_fini(rdev); kfree(rdev->bios); rdev->bios = NULL; @@ -1303,10 +1318,8 @@ int r300_init(struct radeon_device *rdev) RREG32(R_0007C0_CP_STAT)); } /* check if cards are posted or not */ - if (!radeon_card_posted(rdev) && rdev->bios) { - DRM_INFO("GPU not posted. posting now...\n"); - radeon_combios_asic_init(rdev->ddev); - } + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; /* Set asic errata */ r300_errata(rdev); /* Initialize clocks */ @@ -1325,7 +1338,7 @@ int r300_init(struct radeon_device *rdev) if (r) return r; /* Memory manager */ - r = radeon_object_init(rdev); + r = radeon_bo_init(rdev); if (r) return r; if (rdev->flags & RADEON_IS_PCIE) { diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 1cefdbcc0850236e6cc035b54d3ab14356ac8acd..c05a7270cf0c619fb6f20225c455bf58969ada19 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -169,6 +169,9 @@ static int r420_startup(struct radeon_device *rdev) { int r; + /* set common regs */ + r100_set_common_regs(rdev); + /* program mc */ r300_mc_program(rdev); /* Resume clock */ r420_clock_resume(rdev); @@ -186,7 +189,6 @@ static int r420_startup(struct radeon_device *rdev) } r420_pipes_init(rdev); /* Enable IRQ */ - rdev->irq.sw_int = true; r100_irq_set(rdev); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); @@ -229,7 +231,8 @@ int r420_resume(struct radeon_device *rdev) } /* Resume clock after posting */ r420_clock_resume(rdev); - + /* Initialize surface registers */ + radeon_surface_init(rdev); return r420_startup(rdev); } @@ -258,7 +261,7 @@ void r420_fini(struct radeon_device *rdev) radeon_agp_fini(rdev); radeon_irq_kms_fini(rdev); radeon_fence_driver_fini(rdev); - radeon_object_fini(rdev); + radeon_bo_fini(rdev); if (rdev->is_atom_bios) { radeon_atombios_fini(rdev); } else { @@ -301,14 +304,9 @@ int r420_init(struct radeon_device *rdev) RREG32(R_0007C0_CP_STAT)); } /* check if cards are posted or not */ - if (!radeon_card_posted(rdev) && rdev->bios) { - DRM_INFO("GPU not posted. posting now...\n"); - if (rdev->is_atom_bios) { - atom_asic_init(rdev->mode_info.atom_context); - } else { - radeon_combios_asic_init(rdev->ddev); - } - } + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; + /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); /* Initialize power management */ @@ -331,10 +329,13 @@ int r420_init(struct radeon_device *rdev) return r; } /* Memory manager */ - r = radeon_object_init(rdev); + r = radeon_bo_init(rdev); if (r) { return r; } + if (rdev->family == CHIP_R420) + r100_enable_bm(rdev); + if (rdev->flags & RADEON_IS_PCIE) { r = rv370_pcie_gart_init(rdev); if (r) diff --git a/drivers/gpu/drm/radeon/r500_reg.h b/drivers/gpu/drm/radeon/r500_reg.h index 7baa739555634dbc5f8b76fbe7d22b7321767d27..74ad89bdf2b5f0bb6660a12e2607c4b982b458d3 100644 --- a/drivers/gpu/drm/radeon/r500_reg.h +++ b/drivers/gpu/drm/radeon/r500_reg.h @@ -716,6 +716,8 @@ #define AVIVO_DVOA_BIT_DEPTH_CONTROL 0x7988 +#define AVIVO_DC_GPIO_HPD_A 0x7e94 + #define AVIVO_GPIO_0 0x7e30 #define AVIVO_GPIO_1 0x7e40 #define AVIVO_GPIO_2 0x7e50 diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index f7435185c0a6fcd165c076608bbae74d913d7920..0f3843b6dac7669991d4d638c6f002d7204a9054 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -185,7 +185,6 @@ static int r520_startup(struct radeon_device *rdev) return r; } /* Enable IRQ */ - rdev->irq.sw_int = true; rs600_irq_set(rdev); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); @@ -221,6 +220,8 @@ int r520_resume(struct radeon_device *rdev) atom_asic_init(rdev->mode_info.atom_context); /* Resume clock after posting */ rv515_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); return r520_startup(rdev); } @@ -254,6 +255,9 @@ int r520_init(struct radeon_device *rdev) RREG32(R_0007C0_CP_STAT)); } /* check if cards are posted or not */ + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; + if (!radeon_card_posted(rdev) && rdev->bios) { DRM_INFO("GPU not posted. posting now...\n"); atom_asic_init(rdev->mode_info.atom_context); @@ -277,7 +281,7 @@ int r520_init(struct radeon_device *rdev) if (r) return r; /* Memory manager */ - r = radeon_object_init(rdev); + r = radeon_bo_init(rdev); if (r) return r; r = rv370_pcie_gart_init(rdev); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 6740ed24358f710f92d9ccfd0e475d1d485a798c..36656bd110bfda3e00473d8830f7b373098fe49d 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -38,8 +38,10 @@ #define PFP_UCODE_SIZE 576 #define PM4_UCODE_SIZE 1792 +#define RLC_UCODE_SIZE 768 #define R700_PFP_UCODE_SIZE 848 #define R700_PM4_UCODE_SIZE 1360 +#define R700_RLC_UCODE_SIZE 1024 /* Firmware Names */ MODULE_FIRMWARE("radeon/R600_pfp.bin"); @@ -62,6 +64,8 @@ MODULE_FIRMWARE("radeon/RV730_pfp.bin"); MODULE_FIRMWARE("radeon/RV730_me.bin"); MODULE_FIRMWARE("radeon/RV710_pfp.bin"); MODULE_FIRMWARE("radeon/RV710_me.bin"); +MODULE_FIRMWARE("radeon/R600_rlc.bin"); +MODULE_FIRMWARE("radeon/R700_rlc.bin"); int r600_debugfs_mc_info_init(struct radeon_device *rdev); @@ -70,6 +74,281 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev); void r600_gpu_init(struct radeon_device *rdev); void r600_fini(struct radeon_device *rdev); +/* hpd for digital panel detect/disconnect */ +bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) +{ + bool connected = false; + + if (ASIC_IS_DCE3(rdev)) { + switch (hpd) { + case RADEON_HPD_1: + if (RREG32(DC_HPD1_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case RADEON_HPD_2: + if (RREG32(DC_HPD2_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case RADEON_HPD_3: + if (RREG32(DC_HPD3_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case RADEON_HPD_4: + if (RREG32(DC_HPD4_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + /* DCE 3.2 */ + case RADEON_HPD_5: + if (RREG32(DC_HPD5_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case RADEON_HPD_6: + if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + default: + break; + } + } else { + switch (hpd) { + case RADEON_HPD_1: + if (RREG32(DC_HOT_PLUG_DETECT1_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) + connected = true; + break; + case RADEON_HPD_2: + if (RREG32(DC_HOT_PLUG_DETECT2_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) + connected = true; + break; + case RADEON_HPD_3: + if (RREG32(DC_HOT_PLUG_DETECT3_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) + connected = true; + break; + default: + break; + } + } + return connected; +} + +void r600_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd) +{ + u32 tmp; + bool connected = r600_hpd_sense(rdev, hpd); + + if (ASIC_IS_DCE3(rdev)) { + switch (hpd) { + case RADEON_HPD_1: + tmp = RREG32(DC_HPD1_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD1_INT_CONTROL, tmp); + break; + case RADEON_HPD_2: + tmp = RREG32(DC_HPD2_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD2_INT_CONTROL, tmp); + break; + case RADEON_HPD_3: + tmp = RREG32(DC_HPD3_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD3_INT_CONTROL, tmp); + break; + case RADEON_HPD_4: + tmp = RREG32(DC_HPD4_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD4_INT_CONTROL, tmp); + break; + case RADEON_HPD_5: + tmp = RREG32(DC_HPD5_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD5_INT_CONTROL, tmp); + break; + /* DCE 3.2 */ + case RADEON_HPD_6: + tmp = RREG32(DC_HPD6_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD6_INT_CONTROL, tmp); + break; + default: + break; + } + } else { + switch (hpd) { + case RADEON_HPD_1: + tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL); + if (connected) + tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; + else + tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; + WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); + break; + case RADEON_HPD_2: + tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL); + if (connected) + tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; + else + tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; + WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); + break; + case RADEON_HPD_3: + tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL); + if (connected) + tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; + else + tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; + WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); + break; + default: + break; + } + } +} + +void r600_hpd_init(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + + if (ASIC_IS_DCE3(rdev)) { + u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa); + if (ASIC_IS_DCE32(rdev)) + tmp |= DC_HPDx_EN; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + WREG32(DC_HPD1_CONTROL, tmp); + rdev->irq.hpd[0] = true; + break; + case RADEON_HPD_2: + WREG32(DC_HPD2_CONTROL, tmp); + rdev->irq.hpd[1] = true; + break; + case RADEON_HPD_3: + WREG32(DC_HPD3_CONTROL, tmp); + rdev->irq.hpd[2] = true; + break; + case RADEON_HPD_4: + WREG32(DC_HPD4_CONTROL, tmp); + rdev->irq.hpd[3] = true; + break; + /* DCE 3.2 */ + case RADEON_HPD_5: + WREG32(DC_HPD5_CONTROL, tmp); + rdev->irq.hpd[4] = true; + break; + case RADEON_HPD_6: + WREG32(DC_HPD6_CONTROL, tmp); + rdev->irq.hpd[5] = true; + break; + default: + break; + } + } + } else { + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); + rdev->irq.hpd[0] = true; + break; + case RADEON_HPD_2: + WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN); + rdev->irq.hpd[1] = true; + break; + case RADEON_HPD_3: + WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN); + rdev->irq.hpd[2] = true; + break; + default: + break; + } + } + } + r600_irq_set(rdev); +} + +void r600_hpd_fini(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + + if (ASIC_IS_DCE3(rdev)) { + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + WREG32(DC_HPD1_CONTROL, 0); + rdev->irq.hpd[0] = false; + break; + case RADEON_HPD_2: + WREG32(DC_HPD2_CONTROL, 0); + rdev->irq.hpd[1] = false; + break; + case RADEON_HPD_3: + WREG32(DC_HPD3_CONTROL, 0); + rdev->irq.hpd[2] = false; + break; + case RADEON_HPD_4: + WREG32(DC_HPD4_CONTROL, 0); + rdev->irq.hpd[3] = false; + break; + /* DCE 3.2 */ + case RADEON_HPD_5: + WREG32(DC_HPD5_CONTROL, 0); + rdev->irq.hpd[4] = false; + break; + case RADEON_HPD_6: + WREG32(DC_HPD6_CONTROL, 0); + rdev->irq.hpd[5] = false; + break; + default: + break; + } + } + } else { + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0); + rdev->irq.hpd[0] = false; + break; + case RADEON_HPD_2: + WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0); + rdev->irq.hpd[1] = false; + break; + case RADEON_HPD_3: + WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0); + rdev->irq.hpd[2] = false; + break; + default: + break; + } + } + } +} + /* * R600 PCIE GART */ @@ -180,7 +459,7 @@ int r600_pcie_gart_enable(struct radeon_device *rdev) void r600_pcie_gart_disable(struct radeon_device *rdev) { u32 tmp; - int i; + int i, r; /* Disable all tables */ for (i = 0; i < 7; i++) @@ -208,8 +487,12 @@ void r600_pcie_gart_disable(struct radeon_device *rdev) WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp); WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp); if (rdev->gart.table.vram.robj) { - radeon_object_kunmap(rdev->gart.table.vram.robj); - radeon_object_unpin(rdev->gart.table.vram.robj); + r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); + if (likely(r == 0)) { + radeon_bo_kunmap(rdev->gart.table.vram.robj); + radeon_bo_unpin(rdev->gart.table.vram.robj); + radeon_bo_unreserve(rdev->gart.table.vram.robj); + } } } @@ -1101,6 +1384,10 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) (void)RREG32(PCIE_PORT_DATA); } +void r600_hdp_flush(struct radeon_device *rdev) +{ + WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); +} /* * CP & Ring @@ -1110,11 +1397,12 @@ void r600_cp_stop(struct radeon_device *rdev) WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); } -int r600_cp_init_microcode(struct radeon_device *rdev) +int r600_init_microcode(struct radeon_device *rdev) { struct platform_device *pdev; const char *chip_name; - size_t pfp_req_size, me_req_size; + const char *rlc_chip_name; + size_t pfp_req_size, me_req_size, rlc_req_size; char fw_name[30]; int err; @@ -1128,30 +1416,62 @@ int r600_cp_init_microcode(struct radeon_device *rdev) } switch (rdev->family) { - case CHIP_R600: chip_name = "R600"; break; - case CHIP_RV610: chip_name = "RV610"; break; - case CHIP_RV630: chip_name = "RV630"; break; - case CHIP_RV620: chip_name = "RV620"; break; - case CHIP_RV635: chip_name = "RV635"; break; - case CHIP_RV670: chip_name = "RV670"; break; + case CHIP_R600: + chip_name = "R600"; + rlc_chip_name = "R600"; + break; + case CHIP_RV610: + chip_name = "RV610"; + rlc_chip_name = "R600"; + break; + case CHIP_RV630: + chip_name = "RV630"; + rlc_chip_name = "R600"; + break; + case CHIP_RV620: + chip_name = "RV620"; + rlc_chip_name = "R600"; + break; + case CHIP_RV635: + chip_name = "RV635"; + rlc_chip_name = "R600"; + break; + case CHIP_RV670: + chip_name = "RV670"; + rlc_chip_name = "R600"; + break; case CHIP_RS780: - case CHIP_RS880: chip_name = "RS780"; break; - case CHIP_RV770: chip_name = "RV770"; break; + case CHIP_RS880: + chip_name = "RS780"; + rlc_chip_name = "R600"; + break; + case CHIP_RV770: + chip_name = "RV770"; + rlc_chip_name = "R700"; + break; case CHIP_RV730: - case CHIP_RV740: chip_name = "RV730"; break; - case CHIP_RV710: chip_name = "RV710"; break; + case CHIP_RV740: + chip_name = "RV730"; + rlc_chip_name = "R700"; + break; + case CHIP_RV710: + chip_name = "RV710"; + rlc_chip_name = "R700"; + break; default: BUG(); } if (rdev->family >= CHIP_RV770) { pfp_req_size = R700_PFP_UCODE_SIZE * 4; me_req_size = R700_PM4_UCODE_SIZE * 4; + rlc_req_size = R700_RLC_UCODE_SIZE * 4; } else { pfp_req_size = PFP_UCODE_SIZE * 4; me_req_size = PM4_UCODE_SIZE * 12; + rlc_req_size = RLC_UCODE_SIZE * 4; } - DRM_INFO("Loading %s CP Microcode\n", chip_name); + DRM_INFO("Loading %s Microcode\n", chip_name); snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); err = request_firmware(&rdev->pfp_fw, fw_name, &pdev->dev); @@ -1175,6 +1495,18 @@ int r600_cp_init_microcode(struct radeon_device *rdev) rdev->me_fw->size, fw_name); err = -EINVAL; } + + snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", rlc_chip_name); + err = request_firmware(&rdev->rlc_fw, fw_name, &pdev->dev); + if (err) + goto out; + if (rdev->rlc_fw->size != rlc_req_size) { + printk(KERN_ERR + "r600_rlc: Bogus length %zu in firmware \"%s\"\n", + rdev->rlc_fw->size, fw_name); + err = -EINVAL; + } + out: platform_device_unregister(pdev); @@ -1187,6 +1519,8 @@ out: rdev->pfp_fw = NULL; release_firmware(rdev->me_fw); rdev->me_fw = NULL; + release_firmware(rdev->rlc_fw); + rdev->rlc_fw = NULL; } return err; } @@ -1381,10 +1715,16 @@ int r600_ring_test(struct radeon_device *rdev) void r600_wb_disable(struct radeon_device *rdev) { + int r; + WREG32(SCRATCH_UMSK, 0); if (rdev->wb.wb_obj) { - radeon_object_kunmap(rdev->wb.wb_obj); - radeon_object_unpin(rdev->wb.wb_obj); + r = radeon_bo_reserve(rdev->wb.wb_obj, false); + if (unlikely(r != 0)) + return; + radeon_bo_kunmap(rdev->wb.wb_obj); + radeon_bo_unpin(rdev->wb.wb_obj); + radeon_bo_unreserve(rdev->wb.wb_obj); } } @@ -1392,7 +1732,7 @@ void r600_wb_fini(struct radeon_device *rdev) { r600_wb_disable(rdev); if (rdev->wb.wb_obj) { - radeon_object_unref(&rdev->wb.wb_obj); + radeon_bo_unref(&rdev->wb.wb_obj); rdev->wb.wb = NULL; rdev->wb.wb_obj = NULL; } @@ -1403,22 +1743,29 @@ int r600_wb_enable(struct radeon_device *rdev) int r; if (rdev->wb.wb_obj == NULL) { - r = radeon_object_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true, - RADEON_GEM_DOMAIN_GTT, false, &rdev->wb.wb_obj); + r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true, + RADEON_GEM_DOMAIN_GTT, &rdev->wb.wb_obj); if (r) { - dev_warn(rdev->dev, "failed to create WB buffer (%d).\n", r); + dev_warn(rdev->dev, "(%d) create WB bo failed\n", r); return r; } - r = radeon_object_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT, + r = radeon_bo_reserve(rdev->wb.wb_obj, false); + if (unlikely(r != 0)) { + r600_wb_fini(rdev); + return r; + } + r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT, &rdev->wb.gpu_addr); if (r) { - dev_warn(rdev->dev, "failed to pin WB buffer (%d).\n", r); + radeon_bo_unreserve(rdev->wb.wb_obj); + dev_warn(rdev->dev, "(%d) pin WB bo failed\n", r); r600_wb_fini(rdev); return r; } - r = radeon_object_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); + r = radeon_bo_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); + radeon_bo_unreserve(rdev->wb.wb_obj); if (r) { - dev_warn(rdev->dev, "failed to map WB buffer (%d).\n", r); + dev_warn(rdev->dev, "(%d) map WB bo failed\n", r); r600_wb_fini(rdev); return r; } @@ -1433,10 +1780,14 @@ int r600_wb_enable(struct radeon_device *rdev) void r600_fence_ring_emit(struct radeon_device *rdev, struct radeon_fence *fence) { + /* Also consider EVENT_WRITE_EOP. it handles the interrupts + timestamps + events */ /* Emit fence sequence & fire IRQ */ radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); radeon_ring_write(rdev, fence->seq); + /* CP_INTERRUPT packet 3 no longer exists, use packet 0 */ + radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0)); + radeon_ring_write(rdev, RB_INT_STAT); } int r600_copy_dma(struct radeon_device *rdev, @@ -1459,18 +1810,6 @@ int r600_copy_blit(struct radeon_device *rdev, return 0; } -int r600_irq_process(struct radeon_device *rdev) -{ - /* FIXME: implement */ - return 0; -} - -int r600_irq_set(struct radeon_device *rdev) -{ - /* FIXME: implement */ - return 0; -} - int r600_set_surface_reg(struct radeon_device *rdev, int reg, uint32_t tiling_flags, uint32_t pitch, uint32_t offset, uint32_t obj_size) @@ -1506,6 +1845,14 @@ int r600_startup(struct radeon_device *rdev) { int r; + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { + r = r600_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + r600_mc_program(rdev); if (rdev->flags & RADEON_IS_AGP) { r600_agp_enable(rdev); @@ -1516,13 +1863,26 @@ int r600_startup(struct radeon_device *rdev) } r600_gpu_init(rdev); - r = radeon_object_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, - &rdev->r600_blit.shader_gpu_addr); + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, + &rdev->r600_blit.shader_gpu_addr); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); if (r) { - DRM_ERROR("failed to pin blit object %d\n", r); + dev_err(rdev->dev, "(%d) pin blit object failed\n", r); return r; } + /* Enable IRQ */ + r = r600_irq_init(rdev); + if (r) { + DRM_ERROR("radeon: IH init failed (%d).\n", r); + radeon_irq_kms_fini(rdev); + return r; + } + r600_irq_set(rdev); + r = radeon_ring_init(rdev, rdev->cp.ring_size); if (r) return r; @@ -1583,13 +1943,19 @@ int r600_resume(struct radeon_device *rdev) int r600_suspend(struct radeon_device *rdev) { + int r; + /* FIXME: we should wait for ring to be empty */ r600_cp_stop(rdev); rdev->cp.ready = false; r600_wb_disable(rdev); r600_pcie_gart_disable(rdev); /* unpin shaders bo */ - radeon_object_unpin(rdev->r600_blit.shader_obj); + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (unlikely(r != 0)) + return r; + radeon_bo_unpin(rdev->r600_blit.shader_obj); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); return 0; } @@ -1627,7 +1993,11 @@ int r600_init(struct radeon_device *rdev) if (r) return r; /* Post card if necessary */ - if (!r600_card_posted(rdev) && rdev->bios) { + if (!r600_card_posted(rdev)) { + if (!rdev->bios) { + dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); + return -EINVAL; + } DRM_INFO("GPU not posted. posting now...\n"); atom_asic_init(rdev->mode_info.atom_context); } @@ -1650,31 +2020,31 @@ int r600_init(struct radeon_device *rdev) if (r) return r; /* Memory manager */ - r = radeon_object_init(rdev); + r = radeon_bo_init(rdev); if (r) return r; + + r = radeon_irq_kms_init(rdev); + if (r) + return r; + rdev->cp.ring_obj = NULL; r600_ring_init(rdev, 1024 * 1024); - if (!rdev->me_fw || !rdev->pfp_fw) { - r = r600_cp_init_microcode(rdev); - if (r) { - DRM_ERROR("Failed to load firmware!\n"); - return r; - } - } + rdev->ih.ring_obj = NULL; + r600_ih_ring_init(rdev, 64 * 1024); r = r600_pcie_gart_init(rdev); if (r) return r; - rdev->accel_working = true; r = r600_blit_init(rdev); if (r) { - DRM_ERROR("radeon: failled blitter (%d).\n", r); + DRM_ERROR("radeon: failed blitter (%d).\n", r); return r; } + rdev->accel_working = true; r = r600_startup(rdev); if (r) { r600_suspend(rdev); @@ -1686,12 +2056,12 @@ int r600_init(struct radeon_device *rdev) if (rdev->accel_working) { r = radeon_ib_pool_init(rdev); if (r) { - DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r); + DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); rdev->accel_working = false; } r = r600_ib_test(rdev); if (r) { - DRM_ERROR("radeon: failled testing IB (%d).\n", r); + DRM_ERROR("radeon: failed testing IB (%d).\n", r); rdev->accel_working = false; } } @@ -1704,6 +2074,8 @@ void r600_fini(struct radeon_device *rdev) r600_suspend(rdev); r600_blit_fini(rdev); + r600_irq_fini(rdev); + radeon_irq_kms_fini(rdev); radeon_ring_fini(rdev); r600_wb_fini(rdev); r600_pcie_gart_fini(rdev); @@ -1712,7 +2084,7 @@ void r600_fini(struct radeon_device *rdev) radeon_clocks_fini(rdev); if (rdev->flags & RADEON_IS_AGP) radeon_agp_fini(rdev); - radeon_object_fini(rdev); + radeon_bo_fini(rdev); radeon_atombios_fini(rdev); kfree(rdev->bios); rdev->bios = NULL; @@ -1798,8 +2170,657 @@ int r600_ib_test(struct radeon_device *rdev) return r; } +/* + * Interrupts + * + * Interrupts use a ring buffer on r6xx/r7xx hardware. It works pretty + * the same as the CP ring buffer, but in reverse. Rather than the CPU + * writing to the ring and the GPU consuming, the GPU writes to the ring + * and host consumes. As the host irq handler processes interrupts, it + * increments the rptr. When the rptr catches up with the wptr, all the + * current interrupts have been processed. + */ + +void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size) +{ + u32 rb_bufsz; + + /* Align ring size */ + rb_bufsz = drm_order(ring_size / 4); + ring_size = (1 << rb_bufsz) * 4; + rdev->ih.ring_size = ring_size; + rdev->ih.align_mask = 4 - 1; +} + +static int r600_ih_ring_alloc(struct radeon_device *rdev, unsigned ring_size) +{ + int r; + + rdev->ih.ring_size = ring_size; + /* Allocate ring buffer */ + if (rdev->ih.ring_obj == NULL) { + r = radeon_bo_create(rdev, NULL, rdev->ih.ring_size, + true, + RADEON_GEM_DOMAIN_GTT, + &rdev->ih.ring_obj); + if (r) { + DRM_ERROR("radeon: failed to create ih ring buffer (%d).\n", r); + return r; + } + r = radeon_bo_reserve(rdev->ih.ring_obj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->ih.ring_obj, + RADEON_GEM_DOMAIN_GTT, + &rdev->ih.gpu_addr); + if (r) { + radeon_bo_unreserve(rdev->ih.ring_obj); + DRM_ERROR("radeon: failed to pin ih ring buffer (%d).\n", r); + return r; + } + r = radeon_bo_kmap(rdev->ih.ring_obj, + (void **)&rdev->ih.ring); + radeon_bo_unreserve(rdev->ih.ring_obj); + if (r) { + DRM_ERROR("radeon: failed to map ih ring buffer (%d).\n", r); + return r; + } + } + rdev->ih.ptr_mask = (rdev->cp.ring_size / 4) - 1; + rdev->ih.rptr = 0; + + return 0; +} + +static void r600_ih_ring_fini(struct radeon_device *rdev) +{ + int r; + if (rdev->ih.ring_obj) { + r = radeon_bo_reserve(rdev->ih.ring_obj, false); + if (likely(r == 0)) { + radeon_bo_kunmap(rdev->ih.ring_obj); + radeon_bo_unpin(rdev->ih.ring_obj); + radeon_bo_unreserve(rdev->ih.ring_obj); + } + radeon_bo_unref(&rdev->ih.ring_obj); + rdev->ih.ring = NULL; + rdev->ih.ring_obj = NULL; + } +} + +static void r600_rlc_stop(struct radeon_device *rdev) +{ + + if (rdev->family >= CHIP_RV770) { + /* r7xx asics need to soft reset RLC before halting */ + WREG32(SRBM_SOFT_RESET, SOFT_RESET_RLC); + RREG32(SRBM_SOFT_RESET); + udelay(15000); + WREG32(SRBM_SOFT_RESET, 0); + RREG32(SRBM_SOFT_RESET); + } + + WREG32(RLC_CNTL, 0); +} + +static void r600_rlc_start(struct radeon_device *rdev) +{ + WREG32(RLC_CNTL, RLC_ENABLE); +} + +static int r600_rlc_init(struct radeon_device *rdev) +{ + u32 i; + const __be32 *fw_data; + + if (!rdev->rlc_fw) + return -EINVAL; + + r600_rlc_stop(rdev); + + WREG32(RLC_HB_BASE, 0); + WREG32(RLC_HB_CNTL, 0); + WREG32(RLC_HB_RPTR, 0); + WREG32(RLC_HB_WPTR, 0); + WREG32(RLC_HB_WPTR_LSB_ADDR, 0); + WREG32(RLC_HB_WPTR_MSB_ADDR, 0); + WREG32(RLC_MC_CNTL, 0); + WREG32(RLC_UCODE_CNTL, 0); + + fw_data = (const __be32 *)rdev->rlc_fw->data; + if (rdev->family >= CHIP_RV770) { + for (i = 0; i < R700_RLC_UCODE_SIZE; i++) { + WREG32(RLC_UCODE_ADDR, i); + WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); + } + } else { + for (i = 0; i < RLC_UCODE_SIZE; i++) { + WREG32(RLC_UCODE_ADDR, i); + WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); + } + } + WREG32(RLC_UCODE_ADDR, 0); + + r600_rlc_start(rdev); + + return 0; +} + +static void r600_enable_interrupts(struct radeon_device *rdev) +{ + u32 ih_cntl = RREG32(IH_CNTL); + u32 ih_rb_cntl = RREG32(IH_RB_CNTL); + + ih_cntl |= ENABLE_INTR; + ih_rb_cntl |= IH_RB_ENABLE; + WREG32(IH_CNTL, ih_cntl); + WREG32(IH_RB_CNTL, ih_rb_cntl); + rdev->ih.enabled = true; +} + +static void r600_disable_interrupts(struct radeon_device *rdev) +{ + u32 ih_rb_cntl = RREG32(IH_RB_CNTL); + u32 ih_cntl = RREG32(IH_CNTL); + + ih_rb_cntl &= ~IH_RB_ENABLE; + ih_cntl &= ~ENABLE_INTR; + WREG32(IH_RB_CNTL, ih_rb_cntl); + WREG32(IH_CNTL, ih_cntl); + /* set rptr, wptr to 0 */ + WREG32(IH_RB_RPTR, 0); + WREG32(IH_RB_WPTR, 0); + rdev->ih.enabled = false; + rdev->ih.wptr = 0; + rdev->ih.rptr = 0; +} + +static void r600_disable_interrupt_state(struct radeon_device *rdev) +{ + u32 tmp; + + WREG32(CP_INT_CNTL, 0); + WREG32(GRBM_INT_CNTL, 0); + WREG32(DxMODE_INT_MASK, 0); + if (ASIC_IS_DCE3(rdev)) { + WREG32(DCE3_DACA_AUTODETECT_INT_CONTROL, 0); + WREG32(DCE3_DACB_AUTODETECT_INT_CONTROL, 0); + tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD1_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD2_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD3_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD4_INT_CONTROL, tmp); + if (ASIC_IS_DCE32(rdev)) { + tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD5_INT_CONTROL, 0); + tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD6_INT_CONTROL, 0); + } + } else { + WREG32(DACA_AUTODETECT_INT_CONTROL, 0); + WREG32(DACB_AUTODETECT_INT_CONTROL, 0); + tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; + WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, 0); + tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; + WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, 0); + tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; + WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, 0); + } +} + +int r600_irq_init(struct radeon_device *rdev) +{ + int ret = 0; + int rb_bufsz; + u32 interrupt_cntl, ih_cntl, ih_rb_cntl; + + /* allocate ring */ + ret = r600_ih_ring_alloc(rdev, rdev->ih.ring_size); + if (ret) + return ret; + + /* disable irqs */ + r600_disable_interrupts(rdev); + + /* init rlc */ + ret = r600_rlc_init(rdev); + if (ret) { + r600_ih_ring_fini(rdev); + return ret; + } + + /* setup interrupt control */ + /* set dummy read address to ring address */ + WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8); + interrupt_cntl = RREG32(INTERRUPT_CNTL); + /* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi + * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN + */ + interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE; + /* IH_REQ_NONSNOOP_EN=1 if ring is in non-cacheable memory, e.g., vram */ + interrupt_cntl &= ~IH_REQ_NONSNOOP_EN; + WREG32(INTERRUPT_CNTL, interrupt_cntl); + + WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8); + rb_bufsz = drm_order(rdev->ih.ring_size / 4); + + ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE | + IH_WPTR_OVERFLOW_CLEAR | + (rb_bufsz << 1)); + /* WPTR writeback, not yet */ + /*ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE;*/ + WREG32(IH_RB_WPTR_ADDR_LO, 0); + WREG32(IH_RB_WPTR_ADDR_HI, 0); + + WREG32(IH_RB_CNTL, ih_rb_cntl); + + /* set rptr, wptr to 0 */ + WREG32(IH_RB_RPTR, 0); + WREG32(IH_RB_WPTR, 0); + + /* Default settings for IH_CNTL (disabled at first) */ + ih_cntl = MC_WRREQ_CREDIT(0x10) | MC_WR_CLEAN_CNT(0x10); + /* RPTR_REARM only works if msi's are enabled */ + if (rdev->msi_enabled) + ih_cntl |= RPTR_REARM; + +#ifdef __BIG_ENDIAN + ih_cntl |= IH_MC_SWAP(IH_MC_SWAP_32BIT); +#endif + WREG32(IH_CNTL, ih_cntl); + + /* force the active interrupt state to all disabled */ + r600_disable_interrupt_state(rdev); + + /* enable irqs */ + r600_enable_interrupts(rdev); + + return ret; +} + +void r600_irq_fini(struct radeon_device *rdev) +{ + r600_disable_interrupts(rdev); + r600_rlc_stop(rdev); + r600_ih_ring_fini(rdev); +} + +int r600_irq_set(struct radeon_device *rdev) +{ + u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; + u32 mode_int = 0; + u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; + + /* don't enable anything if the ih is disabled */ + if (!rdev->ih.enabled) + return 0; + + if (ASIC_IS_DCE3(rdev)) { + hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN; + if (ASIC_IS_DCE32(rdev)) { + hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; + } + } else { + hpd1 = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd2 = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN; + } + + if (rdev->irq.sw_int) { + DRM_DEBUG("r600_irq_set: sw int\n"); + cp_int_cntl |= RB_INT_ENABLE; + } + if (rdev->irq.crtc_vblank_int[0]) { + DRM_DEBUG("r600_irq_set: vblank 0\n"); + mode_int |= D1MODE_VBLANK_INT_MASK; + } + if (rdev->irq.crtc_vblank_int[1]) { + DRM_DEBUG("r600_irq_set: vblank 1\n"); + mode_int |= D2MODE_VBLANK_INT_MASK; + } + if (rdev->irq.hpd[0]) { + DRM_DEBUG("r600_irq_set: hpd 1\n"); + hpd1 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[1]) { + DRM_DEBUG("r600_irq_set: hpd 2\n"); + hpd2 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[2]) { + DRM_DEBUG("r600_irq_set: hpd 3\n"); + hpd3 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[3]) { + DRM_DEBUG("r600_irq_set: hpd 4\n"); + hpd4 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[4]) { + DRM_DEBUG("r600_irq_set: hpd 5\n"); + hpd5 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[5]) { + DRM_DEBUG("r600_irq_set: hpd 6\n"); + hpd6 |= DC_HPDx_INT_EN; + } + + WREG32(CP_INT_CNTL, cp_int_cntl); + WREG32(DxMODE_INT_MASK, mode_int); + if (ASIC_IS_DCE3(rdev)) { + WREG32(DC_HPD1_INT_CONTROL, hpd1); + WREG32(DC_HPD2_INT_CONTROL, hpd2); + WREG32(DC_HPD3_INT_CONTROL, hpd3); + WREG32(DC_HPD4_INT_CONTROL, hpd4); + if (ASIC_IS_DCE32(rdev)) { + WREG32(DC_HPD5_INT_CONTROL, hpd5); + WREG32(DC_HPD6_INT_CONTROL, hpd6); + } + } else { + WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); + WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); + WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3); + } + + return 0; +} + +static inline void r600_irq_ack(struct radeon_device *rdev, + u32 *disp_int, + u32 *disp_int_cont, + u32 *disp_int_cont2) +{ + u32 tmp; + + if (ASIC_IS_DCE3(rdev)) { + *disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); + *disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE); + *disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2); + } else { + *disp_int = RREG32(DISP_INTERRUPT_STATUS); + *disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); + *disp_int_cont2 = 0; + } + + if (*disp_int & LB_D1_VBLANK_INTERRUPT) + WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); + if (*disp_int & LB_D1_VLINE_INTERRUPT) + WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK); + if (*disp_int & LB_D2_VBLANK_INTERRUPT) + WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); + if (*disp_int & LB_D2_VLINE_INTERRUPT) + WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK); + if (*disp_int & DC_HPD1_INTERRUPT) { + if (ASIC_IS_DCE3(rdev)) { + tmp = RREG32(DC_HPD1_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD1_INT_CONTROL, tmp); + } else { + tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); + } + } + if (*disp_int & DC_HPD2_INTERRUPT) { + if (ASIC_IS_DCE3(rdev)) { + tmp = RREG32(DC_HPD2_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD2_INT_CONTROL, tmp); + } else { + tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); + } + } + if (*disp_int_cont & DC_HPD3_INTERRUPT) { + if (ASIC_IS_DCE3(rdev)) { + tmp = RREG32(DC_HPD3_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD3_INT_CONTROL, tmp); + } else { + tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); + } + } + if (*disp_int_cont & DC_HPD4_INTERRUPT) { + tmp = RREG32(DC_HPD4_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD4_INT_CONTROL, tmp); + } + if (ASIC_IS_DCE32(rdev)) { + if (*disp_int_cont2 & DC_HPD5_INTERRUPT) { + tmp = RREG32(DC_HPD5_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD5_INT_CONTROL, tmp); + } + if (*disp_int_cont2 & DC_HPD6_INTERRUPT) { + tmp = RREG32(DC_HPD5_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD6_INT_CONTROL, tmp); + } + } +} + +void r600_irq_disable(struct radeon_device *rdev) +{ + u32 disp_int, disp_int_cont, disp_int_cont2; + + r600_disable_interrupts(rdev); + /* Wait and acknowledge irq */ + mdelay(1); + r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2); + r600_disable_interrupt_state(rdev); +} + +static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) +{ + u32 wptr, tmp; + /* XXX use writeback */ + wptr = RREG32(IH_RB_WPTR); + if (wptr & RB_OVERFLOW) { + WARN_ON(1); + /* XXX deal with overflow */ + DRM_ERROR("IH RB overflow\n"); + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_WPTR_OVERFLOW_CLEAR; + WREG32(IH_RB_CNTL, tmp); + } + wptr = wptr & WPTR_OFFSET_MASK; + + return wptr; +} + +/* r600 IV Ring + * Each IV ring entry is 128 bits: + * [7:0] - interrupt source id + * [31:8] - reserved + * [59:32] - interrupt source data + * [127:60] - reserved + * + * The basic interrupt vector entries + * are decoded as follows: + * src_id src_data description + * 1 0 D1 Vblank + * 1 1 D1 Vline + * 5 0 D2 Vblank + * 5 1 D2 Vline + * 19 0 FP Hot plug detection A + * 19 1 FP Hot plug detection B + * 19 2 DAC A auto-detection + * 19 3 DAC B auto-detection + * 176 - CP_INT RB + * 177 - CP_INT IB1 + * 178 - CP_INT IB2 + * 181 - EOP Interrupt + * 233 - GUI Idle + * + * Note, these are based on r600 and may need to be + * adjusted or added to on newer asics + */ + +int r600_irq_process(struct radeon_device *rdev) +{ + u32 wptr = r600_get_ih_wptr(rdev); + u32 rptr = rdev->ih.rptr; + u32 src_id, src_data; + u32 last_entry = rdev->ih.ring_size - 16; + u32 ring_index, disp_int, disp_int_cont, disp_int_cont2; + unsigned long flags; + bool queue_hotplug = false; + + DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + + spin_lock_irqsave(&rdev->ih.lock, flags); + + if (rptr == wptr) { + spin_unlock_irqrestore(&rdev->ih.lock, flags); + return IRQ_NONE; + } + if (rdev->shutdown) { + spin_unlock_irqrestore(&rdev->ih.lock, flags); + return IRQ_NONE; + } + +restart_ih: + /* display interrupts */ + r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2); + + rdev->ih.wptr = wptr; + while (rptr != wptr) { + /* wptr/rptr are in bytes! */ + ring_index = rptr / 4; + src_id = rdev->ih.ring[ring_index] & 0xff; + src_data = rdev->ih.ring[ring_index + 1] & 0xfffffff; + + switch (src_id) { + case 1: /* D1 vblank/vline */ + switch (src_data) { + case 0: /* D1 vblank */ + if (disp_int & LB_D1_VBLANK_INTERRUPT) { + drm_handle_vblank(rdev->ddev, 0); + disp_int &= ~LB_D1_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D1 vblank\n"); + } + break; + case 1: /* D1 vline */ + if (disp_int & LB_D1_VLINE_INTERRUPT) { + disp_int &= ~LB_D1_VLINE_INTERRUPT; + DRM_DEBUG("IH: D1 vline\n"); + } + break; + default: + DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 5: /* D2 vblank/vline */ + switch (src_data) { + case 0: /* D2 vblank */ + if (disp_int & LB_D2_VBLANK_INTERRUPT) { + drm_handle_vblank(rdev->ddev, 1); + disp_int &= ~LB_D2_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D2 vblank\n"); + } + break; + case 1: /* D1 vline */ + if (disp_int & LB_D2_VLINE_INTERRUPT) { + disp_int &= ~LB_D2_VLINE_INTERRUPT; + DRM_DEBUG("IH: D2 vline\n"); + } + break; + default: + DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 19: /* HPD/DAC hotplug */ + switch (src_data) { + case 0: + if (disp_int & DC_HPD1_INTERRUPT) { + disp_int &= ~DC_HPD1_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD1\n"); + } + break; + case 1: + if (disp_int & DC_HPD2_INTERRUPT) { + disp_int &= ~DC_HPD2_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD2\n"); + } + break; + case 4: + if (disp_int_cont & DC_HPD3_INTERRUPT) { + disp_int_cont &= ~DC_HPD3_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD3\n"); + } + break; + case 5: + if (disp_int_cont & DC_HPD4_INTERRUPT) { + disp_int_cont &= ~DC_HPD4_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD4\n"); + } + break; + case 10: + if (disp_int_cont2 & DC_HPD5_INTERRUPT) { + disp_int_cont &= ~DC_HPD5_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD5\n"); + } + break; + case 12: + if (disp_int_cont2 & DC_HPD6_INTERRUPT) { + disp_int_cont &= ~DC_HPD6_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD6\n"); + } + break; + default: + DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 176: /* CP_INT in ring buffer */ + case 177: /* CP_INT in IB1 */ + case 178: /* CP_INT in IB2 */ + DRM_DEBUG("IH: CP int: 0x%08x\n", src_data); + radeon_fence_process(rdev); + break; + case 181: /* CP EOP event */ + DRM_DEBUG("IH: CP EOP\n"); + break; + default: + DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + + /* wptr/rptr are in bytes! */ + if (rptr == last_entry) + rptr = 0; + else + rptr += 16; + } + /* make sure wptr hasn't changed while processing */ + wptr = r600_get_ih_wptr(rdev); + if (wptr != rdev->ih.wptr) + goto restart_ih; + if (queue_hotplug) + queue_work(rdev->wq, &rdev->hotplug_work); + rdev->ih.rptr = rptr; + WREG32(IH_RB_RPTR, rdev->ih.rptr); + spin_unlock_irqrestore(&rdev->ih.lock, flags); + return IRQ_HANDLED; +} /* * Debugfs info @@ -1811,21 +2832,21 @@ static int r600_debugfs_cp_ring_info(struct seq_file *m, void *data) struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; struct radeon_device *rdev = dev->dev_private; - uint32_t rdp, wdp; unsigned count, i, j; radeon_ring_free_size(rdev); - rdp = RREG32(CP_RB_RPTR); - wdp = RREG32(CP_RB_WPTR); - count = (rdp + rdev->cp.ring_size - wdp) & rdev->cp.ptr_mask; + count = (rdev->cp.ring_size / 4) - rdev->cp.ring_free_dw; seq_printf(m, "CP_STAT 0x%08x\n", RREG32(CP_STAT)); - seq_printf(m, "CP_RB_WPTR 0x%08x\n", wdp); - seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp); + seq_printf(m, "CP_RB_WPTR 0x%08x\n", RREG32(CP_RB_WPTR)); + seq_printf(m, "CP_RB_RPTR 0x%08x\n", RREG32(CP_RB_RPTR)); + seq_printf(m, "driver's copy of the CP_RB_WPTR 0x%08x\n", rdev->cp.wptr); + seq_printf(m, "driver's copy of the CP_RB_RPTR 0x%08x\n", rdev->cp.rptr); seq_printf(m, "%u free dwords in ring\n", rdev->cp.ring_free_dw); seq_printf(m, "%u dwords in ring\n", count); + i = rdev->cp.rptr; for (j = 0; j <= count; j++) { - i = (rdp + j) & rdev->cp.ptr_mask; seq_printf(m, "r[%04d]=0x%08x\n", i, rdev->cp.ring[i]); + i = (i + 1) & rdev->cp.ptr_mask; } return 0; } diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index dbf716e1fbf30acb57455d79b6423e36db5aa91c..9aecafb51b660947bfd2d2d7d93e92c3b3be1788 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c @@ -473,9 +473,8 @@ int r600_blit_init(struct radeon_device *rdev) obj_size += r6xx_ps_size * 4; obj_size = ALIGN(obj_size, 256); - r = radeon_object_create(rdev, NULL, obj_size, - true, RADEON_GEM_DOMAIN_VRAM, - false, &rdev->r600_blit.shader_obj); + r = radeon_bo_create(rdev, NULL, obj_size, true, RADEON_GEM_DOMAIN_VRAM, + &rdev->r600_blit.shader_obj); if (r) { DRM_ERROR("r600 failed to allocate shader\n"); return r; @@ -485,12 +484,14 @@ int r600_blit_init(struct radeon_device *rdev) obj_size, rdev->r600_blit.vs_offset, rdev->r600_blit.ps_offset); - r = radeon_object_kmap(rdev->r600_blit.shader_obj, &ptr); + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_kmap(rdev->r600_blit.shader_obj, &ptr); if (r) { DRM_ERROR("failed to map blit object %d\n", r); return r; } - if (rdev->family >= CHIP_RV770) memcpy_toio(ptr + rdev->r600_blit.state_offset, r7xx_default_state, rdev->r600_blit.state_len * 4); @@ -500,19 +501,26 @@ int r600_blit_init(struct radeon_device *rdev) if (num_packet2s) memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), packet2s, num_packet2s * 4); - - memcpy(ptr + rdev->r600_blit.vs_offset, r6xx_vs, r6xx_vs_size * 4); memcpy(ptr + rdev->r600_blit.ps_offset, r6xx_ps, r6xx_ps_size * 4); - - radeon_object_kunmap(rdev->r600_blit.shader_obj); + radeon_bo_kunmap(rdev->r600_blit.shader_obj); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); return 0; } void r600_blit_fini(struct radeon_device *rdev) { - radeon_object_unpin(rdev->r600_blit.shader_obj); - radeon_object_unref(&rdev->r600_blit.shader_obj); + int r; + + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (unlikely(r != 0)) { + dev_err(rdev->dev, "(%d) can't finish r600 blit\n", r); + goto out_unref; + } + radeon_bo_unpin(rdev->r600_blit.shader_obj); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); +out_unref: + radeon_bo_unref(&rdev->r600_blit.shader_obj); } int r600_vb_ib_get(struct radeon_device *rdev) @@ -569,9 +577,9 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes) ring_size = num_loops * dwords_per_loop; /* set default + shaders */ ring_size += 40; /* shaders + def state */ - ring_size += 3; /* fence emit for VB IB */ + ring_size += 5; /* fence emit for VB IB */ ring_size += 5; /* done copy */ - ring_size += 3; /* fence emit for done copy */ + ring_size += 5; /* fence emit for done copy */ r = radeon_ring_lock(rdev, ring_size); WARN_ON(r); diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 27ab428b149bbccc6c077e6a648c991ebaddcd2a..05894edadab46c81d76d235c415ef7e22df57d9e 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -456,7 +456,215 @@ #define WAIT_2D_IDLECLEAN_bit (1 << 16) #define WAIT_3D_IDLECLEAN_bit (1 << 17) - +#define IH_RB_CNTL 0x3e00 +# define IH_RB_ENABLE (1 << 0) +# define IH_IB_SIZE(x) ((x) << 1) /* log2 */ +# define IH_RB_FULL_DRAIN_ENABLE (1 << 6) +# define IH_WPTR_WRITEBACK_ENABLE (1 << 8) +# define IH_WPTR_WRITEBACK_TIMER(x) ((x) << 9) /* log2 */ +# define IH_WPTR_OVERFLOW_ENABLE (1 << 16) +# define IH_WPTR_OVERFLOW_CLEAR (1 << 31) +#define IH_RB_BASE 0x3e04 +#define IH_RB_RPTR 0x3e08 +#define IH_RB_WPTR 0x3e0c +# define RB_OVERFLOW (1 << 0) +# define WPTR_OFFSET_MASK 0x3fffc +#define IH_RB_WPTR_ADDR_HI 0x3e10 +#define IH_RB_WPTR_ADDR_LO 0x3e14 +#define IH_CNTL 0x3e18 +# define ENABLE_INTR (1 << 0) +# define IH_MC_SWAP(x) ((x) << 2) +# define IH_MC_SWAP_NONE 0 +# define IH_MC_SWAP_16BIT 1 +# define IH_MC_SWAP_32BIT 2 +# define IH_MC_SWAP_64BIT 3 +# define RPTR_REARM (1 << 4) +# define MC_WRREQ_CREDIT(x) ((x) << 15) +# define MC_WR_CLEAN_CNT(x) ((x) << 20) + +#define RLC_CNTL 0x3f00 +# define RLC_ENABLE (1 << 0) +#define RLC_HB_BASE 0x3f10 +#define RLC_HB_CNTL 0x3f0c +#define RLC_HB_RPTR 0x3f20 +#define RLC_HB_WPTR 0x3f1c +#define RLC_HB_WPTR_LSB_ADDR 0x3f14 +#define RLC_HB_WPTR_MSB_ADDR 0x3f18 +#define RLC_MC_CNTL 0x3f44 +#define RLC_UCODE_CNTL 0x3f48 +#define RLC_UCODE_ADDR 0x3f2c +#define RLC_UCODE_DATA 0x3f30 + +#define SRBM_SOFT_RESET 0xe60 +# define SOFT_RESET_RLC (1 << 13) + +#define CP_INT_CNTL 0xc124 +# define CNTX_BUSY_INT_ENABLE (1 << 19) +# define CNTX_EMPTY_INT_ENABLE (1 << 20) +# define SCRATCH_INT_ENABLE (1 << 25) +# define TIME_STAMP_INT_ENABLE (1 << 26) +# define IB2_INT_ENABLE (1 << 29) +# define IB1_INT_ENABLE (1 << 30) +# define RB_INT_ENABLE (1 << 31) +#define CP_INT_STATUS 0xc128 +# define SCRATCH_INT_STAT (1 << 25) +# define TIME_STAMP_INT_STAT (1 << 26) +# define IB2_INT_STAT (1 << 29) +# define IB1_INT_STAT (1 << 30) +# define RB_INT_STAT (1 << 31) + +#define GRBM_INT_CNTL 0x8060 +# define RDERR_INT_ENABLE (1 << 0) +# define WAIT_COUNT_TIMEOUT_INT_ENABLE (1 << 1) +# define GUI_IDLE_INT_ENABLE (1 << 19) + +#define INTERRUPT_CNTL 0x5468 +# define IH_DUMMY_RD_OVERRIDE (1 << 0) +# define IH_DUMMY_RD_EN (1 << 1) +# define IH_REQ_NONSNOOP_EN (1 << 3) +# define GEN_IH_INT_EN (1 << 8) +#define INTERRUPT_CNTL2 0x546c + +#define D1MODE_VBLANK_STATUS 0x6534 +#define D2MODE_VBLANK_STATUS 0x6d34 +# define DxMODE_VBLANK_OCCURRED (1 << 0) +# define DxMODE_VBLANK_ACK (1 << 4) +# define DxMODE_VBLANK_STAT (1 << 12) +# define DxMODE_VBLANK_INTERRUPT (1 << 16) +# define DxMODE_VBLANK_INTERRUPT_TYPE (1 << 17) +#define D1MODE_VLINE_STATUS 0x653c +#define D2MODE_VLINE_STATUS 0x6d3c +# define DxMODE_VLINE_OCCURRED (1 << 0) +# define DxMODE_VLINE_ACK (1 << 4) +# define DxMODE_VLINE_STAT (1 << 12) +# define DxMODE_VLINE_INTERRUPT (1 << 16) +# define DxMODE_VLINE_INTERRUPT_TYPE (1 << 17) +#define DxMODE_INT_MASK 0x6540 +# define D1MODE_VBLANK_INT_MASK (1 << 0) +# define D1MODE_VLINE_INT_MASK (1 << 4) +# define D2MODE_VBLANK_INT_MASK (1 << 8) +# define D2MODE_VLINE_INT_MASK (1 << 12) +#define DCE3_DISP_INTERRUPT_STATUS 0x7ddc +# define DC_HPD1_INTERRUPT (1 << 18) +# define DC_HPD2_INTERRUPT (1 << 19) +#define DISP_INTERRUPT_STATUS 0x7edc +# define LB_D1_VLINE_INTERRUPT (1 << 2) +# define LB_D2_VLINE_INTERRUPT (1 << 3) +# define LB_D1_VBLANK_INTERRUPT (1 << 4) +# define LB_D2_VBLANK_INTERRUPT (1 << 5) +# define DACA_AUTODETECT_INTERRUPT (1 << 16) +# define DACB_AUTODETECT_INTERRUPT (1 << 17) +# define DC_HOT_PLUG_DETECT1_INTERRUPT (1 << 18) +# define DC_HOT_PLUG_DETECT2_INTERRUPT (1 << 19) +# define DC_I2C_SW_DONE_INTERRUPT (1 << 20) +# define DC_I2C_HW_DONE_INTERRUPT (1 << 21) +#define DISP_INTERRUPT_STATUS_CONTINUE 0x7ee8 +#define DCE3_DISP_INTERRUPT_STATUS_CONTINUE 0x7de8 +# define DC_HPD4_INTERRUPT (1 << 14) +# define DC_HPD4_RX_INTERRUPT (1 << 15) +# define DC_HPD3_INTERRUPT (1 << 28) +# define DC_HPD1_RX_INTERRUPT (1 << 29) +# define DC_HPD2_RX_INTERRUPT (1 << 30) +#define DCE3_DISP_INTERRUPT_STATUS_CONTINUE2 0x7dec +# define DC_HPD3_RX_INTERRUPT (1 << 0) +# define DIGA_DP_VID_STREAM_DISABLE_INTERRUPT (1 << 1) +# define DIGA_DP_STEER_FIFO_OVERFLOW_INTERRUPT (1 << 2) +# define DIGB_DP_VID_STREAM_DISABLE_INTERRUPT (1 << 3) +# define DIGB_DP_STEER_FIFO_OVERFLOW_INTERRUPT (1 << 4) +# define AUX1_SW_DONE_INTERRUPT (1 << 5) +# define AUX1_LS_DONE_INTERRUPT (1 << 6) +# define AUX2_SW_DONE_INTERRUPT (1 << 7) +# define AUX2_LS_DONE_INTERRUPT (1 << 8) +# define AUX3_SW_DONE_INTERRUPT (1 << 9) +# define AUX3_LS_DONE_INTERRUPT (1 << 10) +# define AUX4_SW_DONE_INTERRUPT (1 << 11) +# define AUX4_LS_DONE_INTERRUPT (1 << 12) +# define DIGA_DP_FAST_TRAINING_COMPLETE_INTERRUPT (1 << 13) +# define DIGB_DP_FAST_TRAINING_COMPLETE_INTERRUPT (1 << 14) +/* DCE 3.2 */ +# define AUX5_SW_DONE_INTERRUPT (1 << 15) +# define AUX5_LS_DONE_INTERRUPT (1 << 16) +# define AUX6_SW_DONE_INTERRUPT (1 << 17) +# define AUX6_LS_DONE_INTERRUPT (1 << 18) +# define DC_HPD5_INTERRUPT (1 << 19) +# define DC_HPD5_RX_INTERRUPT (1 << 20) +# define DC_HPD6_INTERRUPT (1 << 21) +# define DC_HPD6_RX_INTERRUPT (1 << 22) + +#define DACA_AUTO_DETECT_CONTROL 0x7828 +#define DACB_AUTO_DETECT_CONTROL 0x7a28 +#define DCE3_DACA_AUTO_DETECT_CONTROL 0x7028 +#define DCE3_DACB_AUTO_DETECT_CONTROL 0x7128 +# define DACx_AUTODETECT_MODE(x) ((x) << 0) +# define DACx_AUTODETECT_MODE_NONE 0 +# define DACx_AUTODETECT_MODE_CONNECT 1 +# define DACx_AUTODETECT_MODE_DISCONNECT 2 +# define DACx_AUTODETECT_FRAME_TIME_COUNTER(x) ((x) << 8) +/* bit 18 = R/C, 17 = G/Y, 16 = B/Comp */ +# define DACx_AUTODETECT_CHECK_MASK(x) ((x) << 16) + +#define DCE3_DACA_AUTODETECT_INT_CONTROL 0x7038 +#define DCE3_DACB_AUTODETECT_INT_CONTROL 0x7138 +#define DACA_AUTODETECT_INT_CONTROL 0x7838 +#define DACB_AUTODETECT_INT_CONTROL 0x7a38 +# define DACx_AUTODETECT_ACK (1 << 0) +# define DACx_AUTODETECT_INT_ENABLE (1 << 16) + +#define DC_HOT_PLUG_DETECT1_CONTROL 0x7d00 +#define DC_HOT_PLUG_DETECT2_CONTROL 0x7d10 +#define DC_HOT_PLUG_DETECT3_CONTROL 0x7d24 +# define DC_HOT_PLUG_DETECTx_EN (1 << 0) + +#define DC_HOT_PLUG_DETECT1_INT_STATUS 0x7d04 +#define DC_HOT_PLUG_DETECT2_INT_STATUS 0x7d14 +#define DC_HOT_PLUG_DETECT3_INT_STATUS 0x7d28 +# define DC_HOT_PLUG_DETECTx_INT_STATUS (1 << 0) +# define DC_HOT_PLUG_DETECTx_SENSE (1 << 1) + +/* DCE 3.0 */ +#define DC_HPD1_INT_STATUS 0x7d00 +#define DC_HPD2_INT_STATUS 0x7d0c +#define DC_HPD3_INT_STATUS 0x7d18 +#define DC_HPD4_INT_STATUS 0x7d24 +/* DCE 3.2 */ +#define DC_HPD5_INT_STATUS 0x7dc0 +#define DC_HPD6_INT_STATUS 0x7df4 +# define DC_HPDx_INT_STATUS (1 << 0) +# define DC_HPDx_SENSE (1 << 1) +# define DC_HPDx_RX_INT_STATUS (1 << 8) + +#define DC_HOT_PLUG_DETECT1_INT_CONTROL 0x7d08 +#define DC_HOT_PLUG_DETECT2_INT_CONTROL 0x7d18 +#define DC_HOT_PLUG_DETECT3_INT_CONTROL 0x7d2c +# define DC_HOT_PLUG_DETECTx_INT_ACK (1 << 0) +# define DC_HOT_PLUG_DETECTx_INT_POLARITY (1 << 8) +# define DC_HOT_PLUG_DETECTx_INT_EN (1 << 16) +/* DCE 3.0 */ +#define DC_HPD1_INT_CONTROL 0x7d04 +#define DC_HPD2_INT_CONTROL 0x7d10 +#define DC_HPD3_INT_CONTROL 0x7d1c +#define DC_HPD4_INT_CONTROL 0x7d28 +/* DCE 3.2 */ +#define DC_HPD5_INT_CONTROL 0x7dc4 +#define DC_HPD6_INT_CONTROL 0x7df8 +# define DC_HPDx_INT_ACK (1 << 0) +# define DC_HPDx_INT_POLARITY (1 << 8) +# define DC_HPDx_INT_EN (1 << 16) +# define DC_HPDx_RX_INT_ACK (1 << 20) +# define DC_HPDx_RX_INT_EN (1 << 24) + +/* DCE 3.0 */ +#define DC_HPD1_CONTROL 0x7d08 +#define DC_HPD2_CONTROL 0x7d14 +#define DC_HPD3_CONTROL 0x7d20 +#define DC_HPD4_CONTROL 0x7d2c +/* DCE 3.2 */ +#define DC_HPD5_CONTROL 0x7dc8 +#define DC_HPD6_CONTROL 0x7dfc +# define DC_HPDx_CONNECTION_TIMER(x) ((x) << 0) +# define DC_HPDx_RX_INT_TIMER(x) ((x) << 16) +/* DCE 3.2 */ +# define DC_HPDx_EN (1 << 28) /* * PM4 @@ -500,7 +708,6 @@ #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 -#define PACKET3_CP_INTERRUPT 0x40 #define PACKET3_SURFACE_SYNC 0x43 # define PACKET3_CB0_DEST_BASE_ENA (1 << 6) # define PACKET3_TC_ACTION_ENA (1 << 23) @@ -674,4 +881,5 @@ #define S_000E60_SOFT_RESET_TSC(x) (((x) & 1) << 16) #define S_000E60_SOFT_RESET_VMC(x) (((x) & 1) << 17) +#define R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480 #endif diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 224506a2f7b1ae6d53d5b68347a4a7889a262a2c..c938bb54123cd0a15e531ee661bd35361ad780e0 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -28,8 +28,6 @@ #ifndef __RADEON_H__ #define __RADEON_H__ -#include "radeon_object.h" - /* TODO: Here are things that needs to be done : * - surface allocator & initializer : (bit like scratch reg) should * initialize HDP_ stuff on RS600, R600, R700 hw, well anythings @@ -67,6 +65,11 @@ #include #include +#include +#include +#include +#include + #include "radeon_family.h" #include "radeon_mode.h" #include "radeon_reg.h" @@ -85,6 +88,7 @@ extern int radeon_benchmarking; extern int radeon_testing; extern int radeon_connector_table; extern int radeon_tv; +extern int radeon_new_pll; /* * Copy from radeon_drv.h so we don't have to include both and have conflicting @@ -186,76 +190,62 @@ void radeon_fence_unref(struct radeon_fence **fence); * Tiling registers */ struct radeon_surface_reg { - struct radeon_object *robj; + struct radeon_bo *bo; }; #define RADEON_GEM_MAX_SURFACES 8 /* - * Radeon buffer. + * TTM. */ -struct radeon_object; +struct radeon_mman { + struct ttm_bo_global_ref bo_global_ref; + struct ttm_global_reference mem_global_ref; + bool mem_global_referenced; + struct ttm_bo_device bdev; +}; + +struct radeon_bo { + /* Protected by gem.mutex */ + struct list_head list; + /* Protected by tbo.reserved */ + u32 placements[3]; + struct ttm_placement placement; + struct ttm_buffer_object tbo; + struct ttm_bo_kmap_obj kmap; + unsigned pin_count; + void *kptr; + u32 tiling_flags; + u32 pitch; + int surface_reg; + /* Constant after initialization */ + struct radeon_device *rdev; + struct drm_gem_object *gobj; +}; -struct radeon_object_list { +struct radeon_bo_list { struct list_head list; - struct radeon_object *robj; + struct radeon_bo *bo; uint64_t gpu_offset; unsigned rdomain; unsigned wdomain; - uint32_t tiling_flags; + u32 tiling_flags; }; -int radeon_object_init(struct radeon_device *rdev); -void radeon_object_fini(struct radeon_device *rdev); -int radeon_object_create(struct radeon_device *rdev, - struct drm_gem_object *gobj, - unsigned long size, - bool kernel, - uint32_t domain, - bool interruptible, - struct radeon_object **robj_ptr); -int radeon_object_kmap(struct radeon_object *robj, void **ptr); -void radeon_object_kunmap(struct radeon_object *robj); -void radeon_object_unref(struct radeon_object **robj); -int radeon_object_pin(struct radeon_object *robj, uint32_t domain, - uint64_t *gpu_addr); -void radeon_object_unpin(struct radeon_object *robj); -int radeon_object_wait(struct radeon_object *robj); -int radeon_object_busy_domain(struct radeon_object *robj, uint32_t *cur_placement); -int radeon_object_evict_vram(struct radeon_device *rdev); -int radeon_object_mmap(struct radeon_object *robj, uint64_t *offset); -void radeon_object_force_delete(struct radeon_device *rdev); -void radeon_object_list_add_object(struct radeon_object_list *lobj, - struct list_head *head); -int radeon_object_list_validate(struct list_head *head, void *fence); -void radeon_object_list_unvalidate(struct list_head *head); -void radeon_object_list_clean(struct list_head *head); -int radeon_object_fbdev_mmap(struct radeon_object *robj, - struct vm_area_struct *vma); -unsigned long radeon_object_size(struct radeon_object *robj); -void radeon_object_clear_surface_reg(struct radeon_object *robj); -int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved, - bool force_drop); -void radeon_object_set_tiling_flags(struct radeon_object *robj, - uint32_t tiling_flags, uint32_t pitch); -void radeon_object_get_tiling_flags(struct radeon_object *robj, uint32_t *tiling_flags, uint32_t *pitch); -void radeon_bo_move_notify(struct ttm_buffer_object *bo, - struct ttm_mem_reg *mem); -void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo); /* * GEM objects. */ struct radeon_gem { + struct mutex mutex; struct list_head objects; }; int radeon_gem_init(struct radeon_device *rdev); void radeon_gem_fini(struct radeon_device *rdev); int radeon_gem_object_create(struct radeon_device *rdev, int size, - int alignment, int initial_domain, - bool discardable, bool kernel, - bool interruptible, - struct drm_gem_object **obj); + int alignment, int initial_domain, + bool discardable, bool kernel, + struct drm_gem_object **obj); int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain, uint64_t *gpu_addr); void radeon_gem_object_unpin(struct drm_gem_object *obj); @@ -271,7 +261,7 @@ struct radeon_gart_table_ram { }; struct radeon_gart_table_vram { - struct radeon_object *robj; + struct radeon_bo *robj; volatile uint32_t *ptr; }; @@ -352,11 +342,16 @@ struct radeon_irq { bool sw_int; /* FIXME: use a define max crtc rather than hardcode it */ bool crtc_vblank_int[2]; + /* FIXME: use defines for max hpd/dacs */ + bool hpd[6]; + spinlock_t sw_lock; + int sw_refcount; }; int radeon_irq_kms_init(struct radeon_device *rdev); void radeon_irq_kms_fini(struct radeon_device *rdev); - +void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev); +void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev); /* * CP & ring. @@ -376,7 +371,7 @@ struct radeon_ib { */ struct radeon_ib_pool { struct mutex mutex; - struct radeon_object *robj; + struct radeon_bo *robj; struct list_head scheduled_ibs; struct radeon_ib ibs[RADEON_IB_POOL_SIZE]; bool ready; @@ -384,7 +379,7 @@ struct radeon_ib_pool { }; struct radeon_cp { - struct radeon_object *ring_obj; + struct radeon_bo *ring_obj; volatile uint32_t *ring; unsigned rptr; unsigned wptr; @@ -399,8 +394,25 @@ struct radeon_cp { bool ready; }; +/* + * R6xx+ IH ring + */ +struct r600_ih { + struct radeon_bo *ring_obj; + volatile uint32_t *ring; + unsigned rptr; + unsigned wptr; + unsigned wptr_old; + unsigned ring_size; + uint64_t gpu_addr; + uint32_t align_mask; + uint32_t ptr_mask; + spinlock_t lock; + bool enabled; +}; + struct r600_blit { - struct radeon_object *shader_obj; + struct radeon_bo *shader_obj; u64 shader_gpu_addr; u32 vs_offset, ps_offset; u32 state_offset; @@ -430,8 +442,8 @@ void radeon_ring_fini(struct radeon_device *rdev); */ struct radeon_cs_reloc { struct drm_gem_object *gobj; - struct radeon_object *robj; - struct radeon_object_list lobj; + struct radeon_bo *robj; + struct radeon_bo_list lobj; uint32_t handle; uint32_t flags; }; @@ -527,7 +539,7 @@ void radeon_agp_fini(struct radeon_device *rdev); * Writeback */ struct radeon_wb { - struct radeon_object *wb_obj; + struct radeon_bo *wb_obj; volatile uint32_t *wb; uint64_t gpu_addr; }; @@ -639,6 +651,11 @@ struct radeon_asic { uint32_t offset, uint32_t obj_size); int (*clear_surface_reg)(struct radeon_device *rdev, int reg); void (*bandwidth_update)(struct radeon_device *rdev); + void (*hdp_flush)(struct radeon_device *rdev); + void (*hpd_init)(struct radeon_device *rdev); + void (*hpd_fini)(struct radeon_device *rdev); + bool (*hpd_sense)(struct radeon_device *rdev, enum radeon_hpd_id hpd); + void (*hpd_set_polarity)(struct radeon_device *rdev, enum radeon_hpd_id hpd); }; /* @@ -751,9 +768,9 @@ struct radeon_device { uint8_t *bios; bool is_atom_bios; uint16_t bios_header_start; - struct radeon_object *stollen_vga_memory; + struct radeon_bo *stollen_vga_memory; struct fb_info *fbdev_info; - struct radeon_object *fbdev_robj; + struct radeon_bo *fbdev_rbo; struct radeon_framebuffer *fbdev_rfb; /* Register mmio */ resource_size_t rmmio_base; @@ -791,8 +808,12 @@ struct radeon_device { struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES]; const struct firmware *me_fw; /* all family ME firmware */ const struct firmware *pfp_fw; /* r6/700 PFP firmware */ + const struct firmware *rlc_fw; /* r6/700 RLC firmware */ struct r600_blit r600_blit; int msi_enabled; /* msi enabled */ + struct r600_ih ih; /* r6/700 interrupt ring */ + struct workqueue_struct *wq; + struct work_struct hotplug_work; }; int radeon_device_init(struct radeon_device *rdev, @@ -829,6 +850,10 @@ static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32 } } +/* + * Cast helper + */ +#define to_radeon_fence(p) ((struct radeon_fence *)(p)) /* * Registers read & write functions. @@ -965,18 +990,24 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) #define radeon_get_engine_clock(rdev) (rdev)->asic->get_engine_clock((rdev)) #define radeon_set_engine_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e)) #define radeon_get_memory_clock(rdev) (rdev)->asic->get_memory_clock((rdev)) -#define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e)) +#define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_memory_clock((rdev), (e)) #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l)) #define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e)) #define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s))) #define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r))) #define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev)) +#define radeon_hdp_flush(rdev) (rdev)->asic->hdp_flush((rdev)) +#define radeon_hpd_init(rdev) (rdev)->asic->hpd_init((rdev)) +#define radeon_hpd_fini(rdev) (rdev)->asic->hpd_fini((rdev)) +#define radeon_hpd_sense(rdev, hpd) (rdev)->asic->hpd_sense((rdev), (hpd)) +#define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd)) /* Common functions */ extern int radeon_gart_table_vram_pin(struct radeon_device *rdev); extern int radeon_modeset_init(struct radeon_device *rdev); extern void radeon_modeset_fini(struct radeon_device *rdev); extern bool radeon_card_posted(struct radeon_device *rdev); +extern bool radeon_boot_test_post_card(struct radeon_device *rdev); extern int radeon_clocks_init(struct radeon_device *rdev); extern void radeon_clocks_fini(struct radeon_device *rdev); extern void radeon_scratch_init(struct radeon_device *rdev); @@ -984,6 +1015,7 @@ extern void radeon_surface_init(struct radeon_device *rdev); extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data); extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable); extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable); +extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain); /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ struct r100_mc_save { @@ -1021,7 +1053,7 @@ extern int r100_cp_reset(struct radeon_device *rdev); extern void r100_vga_render_disable(struct radeon_device *rdev); extern int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt, - struct radeon_object *robj); + struct radeon_bo *robj); extern int r100_cs_parse_packet0(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt, const unsigned *auth, unsigned n, @@ -1029,6 +1061,8 @@ extern int r100_cs_parse_packet0(struct radeon_cs_parser *p, extern int r100_cs_packet_parse(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt, unsigned idx); +extern void r100_enable_bm(struct radeon_device *rdev); +extern void r100_set_common_regs(struct radeon_device *rdev); /* rv200,rv250,rv280 */ extern void r200_set_safe_registers(struct radeon_device *rdev); @@ -1104,7 +1138,14 @@ extern void r600_wb_disable(struct radeon_device *rdev); extern void r600_scratch_init(struct radeon_device *rdev); extern int r600_blit_init(struct radeon_device *rdev); extern void r600_blit_fini(struct radeon_device *rdev); -extern int r600_cp_init_microcode(struct radeon_device *rdev); +extern int r600_init_microcode(struct radeon_device *rdev); extern int r600_gpu_reset(struct radeon_device *rdev); +/* r600 irq */ +extern int r600_irq_init(struct radeon_device *rdev); +extern void r600_irq_fini(struct radeon_device *rdev); +extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size); +extern int r600_irq_set(struct radeon_device *rdev); + +#include "radeon_object.h" #endif diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index c18fbee387d7c1efb0e6c905fc7550b4a907c45a..636116bedcb49e554878c2cc8a51d496ae6b8764 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -76,6 +76,12 @@ int r100_clear_surface_reg(struct radeon_device *rdev, int reg); void r100_bandwidth_update(struct radeon_device *rdev); void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); int r100_ring_test(struct radeon_device *rdev); +void r100_hdp_flush(struct radeon_device *rdev); +void r100_hpd_init(struct radeon_device *rdev); +void r100_hpd_fini(struct radeon_device *rdev); +bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); +void r100_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd); static struct radeon_asic r100_asic = { .init = &r100_init, @@ -107,6 +113,11 @@ static struct radeon_asic r100_asic = { .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, .bandwidth_update = &r100_bandwidth_update, + .hdp_flush = &r100_hdp_flush, + .hpd_init = &r100_hpd_init, + .hpd_fini = &r100_hpd_fini, + .hpd_sense = &r100_hpd_sense, + .hpd_set_polarity = &r100_hpd_set_polarity, }; @@ -162,6 +173,11 @@ static struct radeon_asic r300_asic = { .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, .bandwidth_update = &r100_bandwidth_update, + .hdp_flush = &r100_hdp_flush, + .hpd_init = &r100_hpd_init, + .hpd_fini = &r100_hpd_fini, + .hpd_sense = &r100_hpd_sense, + .hpd_set_polarity = &r100_hpd_set_polarity, }; /* @@ -201,6 +217,11 @@ static struct radeon_asic r420_asic = { .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, .bandwidth_update = &r100_bandwidth_update, + .hdp_flush = &r100_hdp_flush, + .hpd_init = &r100_hpd_init, + .hpd_fini = &r100_hpd_fini, + .hpd_sense = &r100_hpd_sense, + .hpd_set_polarity = &r100_hpd_set_polarity, }; @@ -245,6 +266,11 @@ static struct radeon_asic rs400_asic = { .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, .bandwidth_update = &r100_bandwidth_update, + .hdp_flush = &r100_hdp_flush, + .hpd_init = &r100_hpd_init, + .hpd_fini = &r100_hpd_fini, + .hpd_sense = &r100_hpd_sense, + .hpd_set_polarity = &r100_hpd_set_polarity, }; @@ -263,6 +289,12 @@ int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg); void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void rs600_bandwidth_update(struct radeon_device *rdev); +void rs600_hpd_init(struct radeon_device *rdev); +void rs600_hpd_fini(struct radeon_device *rdev); +bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); +void rs600_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd); + static struct radeon_asic rs600_asic = { .init = &rs600_init, .fini = &rs600_fini, @@ -291,6 +323,11 @@ static struct radeon_asic rs600_asic = { .set_pcie_lanes = NULL, .set_clock_gating = &radeon_atom_set_clock_gating, .bandwidth_update = &rs600_bandwidth_update, + .hdp_flush = &r100_hdp_flush, + .hpd_init = &rs600_hpd_init, + .hpd_fini = &rs600_hpd_fini, + .hpd_sense = &rs600_hpd_sense, + .hpd_set_polarity = &rs600_hpd_set_polarity, }; @@ -334,6 +371,11 @@ static struct radeon_asic rs690_asic = { .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, .bandwidth_update = &rs690_bandwidth_update, + .hdp_flush = &r100_hdp_flush, + .hpd_init = &rs600_hpd_init, + .hpd_fini = &rs600_hpd_fini, + .hpd_sense = &rs600_hpd_sense, + .hpd_set_polarity = &rs600_hpd_set_polarity, }; @@ -381,6 +423,11 @@ static struct radeon_asic rv515_asic = { .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, .bandwidth_update = &rv515_bandwidth_update, + .hdp_flush = &r100_hdp_flush, + .hpd_init = &rs600_hpd_init, + .hpd_fini = &rs600_hpd_fini, + .hpd_sense = &rs600_hpd_sense, + .hpd_set_polarity = &rs600_hpd_set_polarity, }; @@ -419,6 +466,11 @@ static struct radeon_asic r520_asic = { .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, .bandwidth_update = &rv515_bandwidth_update, + .hdp_flush = &r100_hdp_flush, + .hpd_init = &rs600_hpd_init, + .hpd_fini = &rs600_hpd_fini, + .hpd_sense = &rs600_hpd_sense, + .hpd_set_polarity = &rs600_hpd_set_polarity, }; /* @@ -455,6 +507,12 @@ int r600_ring_test(struct radeon_device *rdev); int r600_copy_blit(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_pages, struct radeon_fence *fence); +void r600_hdp_flush(struct radeon_device *rdev); +void r600_hpd_init(struct radeon_device *rdev); +void r600_hpd_fini(struct radeon_device *rdev); +bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); +void r600_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd); static struct radeon_asic r600_asic = { .init = &r600_init, @@ -470,6 +528,7 @@ static struct radeon_asic r600_asic = { .ring_ib_execute = &r600_ring_ib_execute, .irq_set = &r600_irq_set, .irq_process = &r600_irq_process, + .get_vblank_counter = &rs600_get_vblank_counter, .fence_ring_emit = &r600_fence_ring_emit, .cs_parse = &r600_cs_parse, .copy_blit = &r600_copy_blit, @@ -484,6 +543,11 @@ static struct radeon_asic r600_asic = { .set_surface_reg = r600_set_surface_reg, .clear_surface_reg = r600_clear_surface_reg, .bandwidth_update = &rv515_bandwidth_update, + .hdp_flush = &r600_hdp_flush, + .hpd_init = &r600_hpd_init, + .hpd_fini = &r600_hpd_fini, + .hpd_sense = &r600_hpd_sense, + .hpd_set_polarity = &r600_hpd_set_polarity, }; /* @@ -509,6 +573,7 @@ static struct radeon_asic rv770_asic = { .ring_ib_execute = &r600_ring_ib_execute, .irq_set = &r600_irq_set, .irq_process = &r600_irq_process, + .get_vblank_counter = &rs600_get_vblank_counter, .fence_ring_emit = &r600_fence_ring_emit, .cs_parse = &r600_cs_parse, .copy_blit = &r600_copy_blit, @@ -523,6 +588,11 @@ static struct radeon_asic rv770_asic = { .set_surface_reg = r600_set_surface_reg, .clear_surface_reg = r600_clear_surface_reg, .bandwidth_update = &rv515_bandwidth_update, + .hdp_flush = &r600_hdp_flush, + .hpd_init = &r600_hpd_init, + .hpd_fini = &r600_hpd_fini, + .hpd_sense = &r600_hpd_sense, + .hpd_set_polarity = &r600_hpd_set_polarity, }; #endif diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 2ed88a820935fd26c0877e061b9bc82505535e26..12a0c760e7ff1c09dd4dc07135e804a37f52d0ea 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -47,7 +47,8 @@ radeon_add_atom_connector(struct drm_device *dev, int connector_type, struct radeon_i2c_bus_rec *i2c_bus, bool linkb, uint32_t igp_lane_info, - uint16_t connector_object_id); + uint16_t connector_object_id, + struct radeon_hpd *hpd); /* from radeon_legacy_encoder.c */ extern void @@ -60,16 +61,16 @@ union atom_supported_devices { struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1; }; -static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device - *dev, uint8_t id) +static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev, + uint8_t id) { - struct radeon_device *rdev = dev->dev_private; struct atom_context *ctx = rdev->mode_info.atom_context; - ATOM_GPIO_I2C_ASSIGMENT gpio; + ATOM_GPIO_I2C_ASSIGMENT *gpio; struct radeon_i2c_bus_rec i2c; int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); struct _ATOM_GPIO_I2C_INFO *i2c_info; uint16_t data_offset; + int i; memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); i2c.valid = false; @@ -78,34 +79,121 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset); - gpio = i2c_info->asGPIO_Info[id]; - - i2c.mask_clk_reg = le16_to_cpu(gpio.usClkMaskRegisterIndex) * 4; - i2c.mask_data_reg = le16_to_cpu(gpio.usDataMaskRegisterIndex) * 4; - i2c.put_clk_reg = le16_to_cpu(gpio.usClkEnRegisterIndex) * 4; - i2c.put_data_reg = le16_to_cpu(gpio.usDataEnRegisterIndex) * 4; - i2c.get_clk_reg = le16_to_cpu(gpio.usClkY_RegisterIndex) * 4; - i2c.get_data_reg = le16_to_cpu(gpio.usDataY_RegisterIndex) * 4; - i2c.a_clk_reg = le16_to_cpu(gpio.usClkA_RegisterIndex) * 4; - i2c.a_data_reg = le16_to_cpu(gpio.usDataA_RegisterIndex) * 4; - i2c.mask_clk_mask = (1 << gpio.ucClkMaskShift); - i2c.mask_data_mask = (1 << gpio.ucDataMaskShift); - i2c.put_clk_mask = (1 << gpio.ucClkEnShift); - i2c.put_data_mask = (1 << gpio.ucDataEnShift); - i2c.get_clk_mask = (1 << gpio.ucClkY_Shift); - i2c.get_data_mask = (1 << gpio.ucDataY_Shift); - i2c.a_clk_mask = (1 << gpio.ucClkA_Shift); - i2c.a_data_mask = (1 << gpio.ucDataA_Shift); - i2c.valid = true; + + for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { + gpio = &i2c_info->asGPIO_Info[i]; + + if (gpio->sucI2cId.ucAccess == id) { + i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; + i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; + i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; + i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; + i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; + i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; + i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; + i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; + i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); + i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); + i2c.en_clk_mask = (1 << gpio->ucClkEnShift); + i2c.en_data_mask = (1 << gpio->ucDataEnShift); + i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); + i2c.y_data_mask = (1 << gpio->ucDataY_Shift); + i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); + i2c.a_data_mask = (1 << gpio->ucDataA_Shift); + + if (gpio->sucI2cId.sbfAccess.bfHW_Capable) + i2c.hw_capable = true; + else + i2c.hw_capable = false; + + if (gpio->sucI2cId.ucAccess == 0xa0) + i2c.mm_i2c = true; + else + i2c.mm_i2c = false; + + i2c.i2c_id = gpio->sucI2cId.ucAccess; + + i2c.valid = true; + } + } return i2c; } +static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev, + u8 id) +{ + struct atom_context *ctx = rdev->mode_info.atom_context; + struct radeon_gpio_rec gpio; + int index = GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT); + struct _ATOM_GPIO_PIN_LUT *gpio_info; + ATOM_GPIO_PIN_ASSIGNMENT *pin; + u16 data_offset, size; + int i, num_indices; + + memset(&gpio, 0, sizeof(struct radeon_gpio_rec)); + gpio.valid = false; + + atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset); + + gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset); + + num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / sizeof(ATOM_GPIO_PIN_ASSIGNMENT); + + for (i = 0; i < num_indices; i++) { + pin = &gpio_info->asGPIO_Pin[i]; + if (id == pin->ucGPIO_ID) { + gpio.id = pin->ucGPIO_ID; + gpio.reg = pin->usGpioPin_AIndex * 4; + gpio.mask = (1 << pin->ucGpioPinBitShift); + gpio.valid = true; + break; + } + } + + return gpio; +} + +static struct radeon_hpd radeon_atom_get_hpd_info_from_gpio(struct radeon_device *rdev, + struct radeon_gpio_rec *gpio) +{ + struct radeon_hpd hpd; + hpd.gpio = *gpio; + if (gpio->reg == AVIVO_DC_GPIO_HPD_A) { + switch(gpio->mask) { + case (1 << 0): + hpd.hpd = RADEON_HPD_1; + break; + case (1 << 8): + hpd.hpd = RADEON_HPD_2; + break; + case (1 << 16): + hpd.hpd = RADEON_HPD_3; + break; + case (1 << 24): + hpd.hpd = RADEON_HPD_4; + break; + case (1 << 26): + hpd.hpd = RADEON_HPD_5; + break; + case (1 << 28): + hpd.hpd = RADEON_HPD_6; + break; + default: + hpd.hpd = RADEON_HPD_NONE; + break; + } + } else + hpd.hpd = RADEON_HPD_NONE; + return hpd; +} + static bool radeon_atom_apply_quirks(struct drm_device *dev, uint32_t supported_device, int *connector_type, struct radeon_i2c_bus_rec *i2c_bus, - uint16_t *line_mux) + uint16_t *line_mux, + struct radeon_hpd *hpd) { /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ @@ -135,6 +223,23 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, } } + /* HIS X1300 is DVI+VGA, not DVI+DVI */ + if ((dev->pdev->device == 0x7146) && + (dev->pdev->subsystem_vendor == 0x17af) && + (dev->pdev->subsystem_device == 0x2058)) { + if (supported_device == ATOM_DEVICE_DFP1_SUPPORT) + return false; + } + + /* Gigabyte X1300 is DVI+VGA, not DVI+DVI */ + if ((dev->pdev->device == 0x7142) && + (dev->pdev->subsystem_vendor == 0x1458) && + (dev->pdev->subsystem_device == 0x2134)) { + if (supported_device == ATOM_DEVICE_DFP1_SUPPORT) + return false; + } + + /* Funky macbooks */ if ((dev->pdev->device == 0x71C5) && (dev->pdev->subsystem_vendor == 0x106b) && @@ -172,6 +277,15 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, } } + /* Acer laptop reports DVI-D as DVI-I */ + if ((dev->pdev->device == 0x95c4) && + (dev->pdev->subsystem_vendor == 0x1025) && + (dev->pdev->subsystem_device == 0x013c)) { + if ((*connector_type == DRM_MODE_CONNECTOR_DVII) && + (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) + *connector_type = DRM_MODE_CONNECTOR_DVID; + } + return true; } @@ -240,16 +354,18 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) struct radeon_mode_info *mode_info = &rdev->mode_info; struct atom_context *ctx = mode_info->atom_context; int index = GetIndexIntoMasterTable(DATA, Object_Header); - uint16_t size, data_offset; - uint8_t frev, crev, line_mux = 0; + u16 size, data_offset; + u8 frev, crev; ATOM_CONNECTOR_OBJECT_TABLE *con_obj; ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; ATOM_OBJECT_HEADER *obj_header; int i, j, path_size, device_support; int connector_type; - uint16_t igp_lane_info, conn_id, connector_object_id; + u16 igp_lane_info, conn_id, connector_object_id; bool linkb; struct radeon_i2c_bus_rec ddc_bus; + struct radeon_gpio_rec gpio; + struct radeon_hpd hpd; atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset); @@ -276,7 +392,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) path = (ATOM_DISPLAY_OBJECT_PATH *) addr; path_size += le16_to_cpu(path->usSize); linkb = false; - if (device_support & le16_to_cpu(path->usDeviceTag)) { uint8_t con_obj_id, con_obj_num, con_obj_type; @@ -377,10 +492,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) } } - /* look up gpio for ddc */ + /* look up gpio for ddc, hpd */ if ((le16_to_cpu(path->usDeviceTag) & - (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) - == 0) { + (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) { for (j = 0; j < con_obj->ucNumberOfObjects; j++) { if (le16_to_cpu(path->usConnObjectId) == le16_to_cpu(con_obj->asObjects[j]. @@ -394,21 +508,34 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) asObjects[j]. usRecordOffset)); ATOM_I2C_RECORD *i2c_record; + ATOM_HPD_INT_RECORD *hpd_record; + ATOM_I2C_ID_CONFIG_ACCESS *i2c_config; + hpd.hpd = RADEON_HPD_NONE; while (record->ucRecordType > 0 && record-> ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { - switch (record-> - ucRecordType) { + switch (record->ucRecordType) { case ATOM_I2C_RECORD_TYPE: i2c_record = - (ATOM_I2C_RECORD - *) record; - line_mux = - i2c_record-> - sucI2cId. - bfI2C_LineMux; + (ATOM_I2C_RECORD *) + record; + i2c_config = + (ATOM_I2C_ID_CONFIG_ACCESS *) + &i2c_record->sucI2cId; + ddc_bus = radeon_lookup_i2c_gpio(rdev, + i2c_config-> + ucAccess); + break; + case ATOM_HPD_INT_RECORD_TYPE: + hpd_record = + (ATOM_HPD_INT_RECORD *) + record; + gpio = radeon_lookup_gpio(rdev, + hpd_record->ucHPDIntGPIOID); + hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio); + hpd.plugged_state = hpd_record->ucPlugged_PinState; break; } record = @@ -421,24 +548,16 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) break; } } - } else - line_mux = 0; - - if ((le16_to_cpu(path->usDeviceTag) == - ATOM_DEVICE_TV1_SUPPORT) - || (le16_to_cpu(path->usDeviceTag) == - ATOM_DEVICE_TV2_SUPPORT) - || (le16_to_cpu(path->usDeviceTag) == - ATOM_DEVICE_CV_SUPPORT)) + } else { + hpd.hpd = RADEON_HPD_NONE; ddc_bus.valid = false; - else - ddc_bus = radeon_lookup_gpio(dev, line_mux); + } conn_id = le16_to_cpu(path->usConnObjectId); if (!radeon_atom_apply_quirks (dev, le16_to_cpu(path->usDeviceTag), &connector_type, - &ddc_bus, &conn_id)) + &ddc_bus, &conn_id, &hpd)) continue; radeon_add_atom_connector(dev, @@ -447,7 +566,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) usDeviceTag), connector_type, &ddc_bus, linkb, igp_lane_info, - connector_object_id); + connector_object_id, + &hpd); } } @@ -502,6 +622,7 @@ struct bios_connector { uint16_t devices; int connector_type; struct radeon_i2c_bus_rec ddc_bus; + struct radeon_hpd hpd; }; bool radeon_get_atom_connector_info_from_supported_devices_table(struct @@ -517,7 +638,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct uint16_t device_support; uint8_t dac; union atom_supported_devices *supported_devices; - int i, j; + int i, j, max_device; struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE]; atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset); @@ -527,7 +648,12 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct device_support = le16_to_cpu(supported_devices->info.usDeviceSupport); - for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { + if (frev > 1) + max_device = ATOM_MAX_SUPPORTED_DEVICE; + else + max_device = ATOM_MAX_SUPPORTED_DEVICE_INFO; + + for (i = 0; i < max_device; i++) { ATOM_CONNECTOR_INFO_I2C ci = supported_devices->info.asConnInfo[i]; @@ -553,22 +679,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC; - if ((rdev->family == CHIP_RS690) || - (rdev->family == CHIP_RS740)) { - if ((i == ATOM_DEVICE_DFP2_INDEX) - && (ci.sucI2cId.sbfAccess.bfI2C_LineMux == 2)) - bios_connectors[i].line_mux = - ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1; - else if ((i == ATOM_DEVICE_DFP3_INDEX) - && (ci.sucI2cId.sbfAccess.bfI2C_LineMux == 1)) - bios_connectors[i].line_mux = - ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1; - else - bios_connectors[i].line_mux = - ci.sucI2cId.sbfAccess.bfI2C_LineMux; - } else - bios_connectors[i].line_mux = - ci.sucI2cId.sbfAccess.bfI2C_LineMux; + bios_connectors[i].line_mux = + ci.sucI2cId.ucAccess; /* give tv unique connector ids */ if (i == ATOM_DEVICE_TV1_INDEX) { @@ -582,8 +694,30 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct bios_connectors[i].line_mux = 52; } else bios_connectors[i].ddc_bus = - radeon_lookup_gpio(dev, - bios_connectors[i].line_mux); + radeon_lookup_i2c_gpio(rdev, + bios_connectors[i].line_mux); + + if ((crev > 1) && (frev > 1)) { + u8 isb = supported_devices->info_2d1.asIntSrcInfo[i].ucIntSrcBitmap; + switch (isb) { + case 0x4: + bios_connectors[i].hpd.hpd = RADEON_HPD_1; + break; + case 0xa: + bios_connectors[i].hpd.hpd = RADEON_HPD_2; + break; + default: + bios_connectors[i].hpd.hpd = RADEON_HPD_NONE; + break; + } + } else { + if (i == ATOM_DEVICE_DFP1_INDEX) + bios_connectors[i].hpd.hpd = RADEON_HPD_1; + else if (i == ATOM_DEVICE_DFP2_INDEX) + bios_connectors[i].hpd.hpd = RADEON_HPD_2; + else + bios_connectors[i].hpd.hpd = RADEON_HPD_NONE; + } /* Always set the connector type to VGA for CRT1/CRT2. if they are * shared with a DVI port, we'll pick up the DVI connector when we @@ -595,7 +729,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct if (!radeon_atom_apply_quirks (dev, (1 << i), &bios_connectors[i].connector_type, - &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux)) + &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux, + &bios_connectors[i].hpd)) continue; bios_connectors[i].valid = true; @@ -617,9 +752,9 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct } /* combine shared connectors */ - for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { + for (i = 0; i < max_device; i++) { if (bios_connectors[i].valid) { - for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { + for (j = 0; j < max_device; j++) { if (bios_connectors[j].valid && (i != j)) { if (bios_connectors[i].line_mux == bios_connectors[j].line_mux) { @@ -643,6 +778,10 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct bios_connectors[i]. connector_type = DRM_MODE_CONNECTOR_DVII; + if (bios_connectors[j].devices & + (ATOM_DEVICE_DFP_SUPPORT)) + bios_connectors[i].hpd = + bios_connectors[j].hpd; bios_connectors[j]. valid = false; } @@ -653,7 +792,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct } /* add the connectors */ - for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { + for (i = 0; i < max_device; i++) { if (bios_connectors[i].valid) { uint16_t connector_object_id = atombios_get_connector_object_id(dev, @@ -666,7 +805,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct connector_type, &bios_connectors[i].ddc_bus, false, 0, - connector_object_id); + connector_object_id, + &bios_connectors[i].hpd); } } @@ -731,7 +871,8 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) * pre-DCE 3.0 r6xx hardware. This might need to be adjusted per * family. */ - p1pll->pll_out_min = 64800; + if (!radeon_new_pll) + p1pll->pll_out_min = 64800; } p1pll->pll_in_min = @@ -861,6 +1002,7 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info; uint8_t frev, crev; struct radeon_atom_ss *ss = NULL; + int i; if (id > ATOM_MAX_SS_ENTRY) return NULL; @@ -878,12 +1020,17 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct if (!ss) return NULL; - ss->percentage = le16_to_cpu(ss_info->asSS_Info[id].usSpreadSpectrumPercentage); - ss->type = ss_info->asSS_Info[id].ucSpreadSpectrumType; - ss->step = ss_info->asSS_Info[id].ucSS_Step; - ss->delay = ss_info->asSS_Info[id].ucSS_Delay; - ss->range = ss_info->asSS_Info[id].ucSS_Range; - ss->refdiv = ss_info->asSS_Info[id].ucRecommendedRef_Div; + for (i = 0; i < ATOM_MAX_SS_ENTRY; i++) { + if (ss_info->asSS_Info[i].ucSS_Id == id) { + ss->percentage = + le16_to_cpu(ss_info->asSS_Info[i].usSpreadSpectrumPercentage); + ss->type = ss_info->asSS_Info[i].ucSpreadSpectrumType; + ss->step = ss_info->asSS_Info[i].ucSS_Step; + ss->delay = ss_info->asSS_Info[i].ucSS_Delay; + ss->range = ss_info->asSS_Info[i].ucSS_Range; + ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div; + } + } } return ss; } @@ -901,7 +1048,7 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct struct radeon_device *rdev = dev->dev_private; struct radeon_mode_info *mode_info = &rdev->mode_info; int index = GetIndexIntoMasterTable(DATA, LVDS_Info); - uint16_t data_offset; + uint16_t data_offset, misc; union lvds_info *lvds_info; uint8_t frev, crev; struct radeon_encoder_atom_dig *lvds = NULL; @@ -940,6 +1087,19 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct lvds->panel_pwr_delay = le16_to_cpu(lvds_info->info.usOffDelayInMs); lvds->lvds_misc = lvds_info->info.ucLVDS_Misc; + + misc = le16_to_cpu(lvds_info->info.sLCDTiming.susModeMiscInfo.usAccess); + if (misc & ATOM_VSYNC_POLARITY) + lvds->native_mode.flags |= DRM_MODE_FLAG_NVSYNC; + if (misc & ATOM_HSYNC_POLARITY) + lvds->native_mode.flags |= DRM_MODE_FLAG_NHSYNC; + if (misc & ATOM_COMPOSITESYNC) + lvds->native_mode.flags |= DRM_MODE_FLAG_CSYNC; + if (misc & ATOM_INTERLACE) + lvds->native_mode.flags |= DRM_MODE_FLAG_INTERLACE; + if (misc & ATOM_DOUBLE_CLOCK_MODE) + lvds->native_mode.flags |= DRM_MODE_FLAG_DBLSCAN; + /* set crtc values */ drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V); diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c index 10bd50a7db8745c4637c8215e0ea70361305a879..4ddfd4b5bc5118b616caf464f81c7099eeee3c4c 100644 --- a/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c @@ -29,8 +29,8 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize, unsigned sdomain, unsigned ddomain) { - struct radeon_object *dobj = NULL; - struct radeon_object *sobj = NULL; + struct radeon_bo *dobj = NULL; + struct radeon_bo *sobj = NULL; struct radeon_fence *fence = NULL; uint64_t saddr, daddr; unsigned long start_jiffies; @@ -41,19 +41,27 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize, size = bsize; n = 1024; - r = radeon_object_create(rdev, NULL, size, true, sdomain, false, &sobj); + r = radeon_bo_create(rdev, NULL, size, true, sdomain, &sobj); if (r) { goto out_cleanup; } - r = radeon_object_pin(sobj, sdomain, &saddr); + r = radeon_bo_reserve(sobj, false); + if (unlikely(r != 0)) + goto out_cleanup; + r = radeon_bo_pin(sobj, sdomain, &saddr); + radeon_bo_unreserve(sobj); if (r) { goto out_cleanup; } - r = radeon_object_create(rdev, NULL, size, true, ddomain, false, &dobj); + r = radeon_bo_create(rdev, NULL, size, true, ddomain, &dobj); if (r) { goto out_cleanup; } - r = radeon_object_pin(dobj, ddomain, &daddr); + r = radeon_bo_reserve(dobj, false); + if (unlikely(r != 0)) + goto out_cleanup; + r = radeon_bo_pin(dobj, ddomain, &daddr); + radeon_bo_unreserve(dobj); if (r) { goto out_cleanup; } @@ -109,12 +117,20 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize, } out_cleanup: if (sobj) { - radeon_object_unpin(sobj); - radeon_object_unref(&sobj); + r = radeon_bo_reserve(sobj, false); + if (likely(r == 0)) { + radeon_bo_unpin(sobj); + radeon_bo_unreserve(sobj); + } + radeon_bo_unref(&sobj); } if (dobj) { - radeon_object_unpin(dobj); - radeon_object_unref(&dobj); + r = radeon_bo_reserve(dobj, false); + if (likely(r == 0)) { + radeon_bo_unpin(dobj); + radeon_bo_unreserve(dobj); + } + radeon_bo_unref(&dobj); } if (fence) { radeon_fence_unref(&fence); diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index a81354167621c1fd64d81dd0ff6f6e8ab6c2afc4..b062109efbeea60b99b4a5b8a368df6b58d59691 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c @@ -44,6 +44,10 @@ uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev) ref_div = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK; + + if (ref_div == 0) + return 0; + sclk = fb_div / ref_div; post_div = RREG32_PLL(RADEON_SCLK_CNTL) & RADEON_SCLK_SRC_SEL_MASK; @@ -70,6 +74,10 @@ static uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev) ref_div = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK; + + if (ref_div == 0) + return 0; + mclk = fb_div / ref_div; post_div = RREG32_PLL(RADEON_MCLK_CNTL) & 0x7; @@ -98,8 +106,19 @@ void radeon_get_clock_info(struct drm_device *dev) ret = radeon_combios_get_clock_info(dev); if (ret) { - if (p1pll->reference_div < 2) - p1pll->reference_div = 12; + if (p1pll->reference_div < 2) { + if (!ASIC_IS_AVIVO(rdev)) { + u32 tmp = RREG32_PLL(RADEON_PPLL_REF_DIV); + if (ASIC_IS_R300(rdev)) + p1pll->reference_div = + (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT; + else + p1pll->reference_div = tmp & RADEON_PPLL_REF_DIV_MASK; + if (p1pll->reference_div < 2) + p1pll->reference_div = 12; + } else + p1pll->reference_div = 12; + } if (p2pll->reference_div < 2) p2pll->reference_div = 12; if (rdev->family < CHIP_RS600) { diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 5253cbf6db1f693e8fb6843d5a6e1d0122635e3b..c5021a3445de0dbafb59cff662a39d19f1a256f7 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -50,7 +50,8 @@ radeon_add_legacy_connector(struct drm_device *dev, uint32_t supported_device, int connector_type, struct radeon_i2c_bus_rec *i2c_bus, - uint16_t connector_object_id); + uint16_t connector_object_id, + struct radeon_hpd *hpd); /* from radeon_legacy_encoder.c */ extern void @@ -442,38 +443,70 @@ static uint16_t combios_get_table_offset(struct drm_device *dev, } -struct radeon_i2c_bus_rec combios_setup_i2c_bus(int ddc_line) +static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev, + int ddc_line) { struct radeon_i2c_bus_rec i2c; - i2c.mask_clk_mask = RADEON_GPIO_EN_1; - i2c.mask_data_mask = RADEON_GPIO_EN_0; - i2c.a_clk_mask = RADEON_GPIO_A_1; - i2c.a_data_mask = RADEON_GPIO_A_0; - i2c.put_clk_mask = RADEON_GPIO_EN_1; - i2c.put_data_mask = RADEON_GPIO_EN_0; - i2c.get_clk_mask = RADEON_GPIO_Y_1; - i2c.get_data_mask = RADEON_GPIO_Y_0; - if ((ddc_line == RADEON_LCD_GPIO_MASK) || - (ddc_line == RADEON_MDGPIO_EN_REG)) { - i2c.mask_clk_reg = ddc_line; - i2c.mask_data_reg = ddc_line; - i2c.a_clk_reg = ddc_line; - i2c.a_data_reg = ddc_line; - i2c.put_clk_reg = ddc_line; - i2c.put_data_reg = ddc_line; - i2c.get_clk_reg = ddc_line + 4; - i2c.get_data_reg = ddc_line + 4; + if (ddc_line == RADEON_GPIOPAD_MASK) { + i2c.mask_clk_reg = RADEON_GPIOPAD_MASK; + i2c.mask_data_reg = RADEON_GPIOPAD_MASK; + i2c.a_clk_reg = RADEON_GPIOPAD_A; + i2c.a_data_reg = RADEON_GPIOPAD_A; + i2c.en_clk_reg = RADEON_GPIOPAD_EN; + i2c.en_data_reg = RADEON_GPIOPAD_EN; + i2c.y_clk_reg = RADEON_GPIOPAD_Y; + i2c.y_data_reg = RADEON_GPIOPAD_Y; + } else if (ddc_line == RADEON_MDGPIO_MASK) { + i2c.mask_clk_reg = RADEON_MDGPIO_MASK; + i2c.mask_data_reg = RADEON_MDGPIO_MASK; + i2c.a_clk_reg = RADEON_MDGPIO_A; + i2c.a_data_reg = RADEON_MDGPIO_A; + i2c.en_clk_reg = RADEON_MDGPIO_EN; + i2c.en_data_reg = RADEON_MDGPIO_EN; + i2c.y_clk_reg = RADEON_MDGPIO_Y; + i2c.y_data_reg = RADEON_MDGPIO_Y; } else { + i2c.mask_clk_mask = RADEON_GPIO_EN_1; + i2c.mask_data_mask = RADEON_GPIO_EN_0; + i2c.a_clk_mask = RADEON_GPIO_A_1; + i2c.a_data_mask = RADEON_GPIO_A_0; + i2c.en_clk_mask = RADEON_GPIO_EN_1; + i2c.en_data_mask = RADEON_GPIO_EN_0; + i2c.y_clk_mask = RADEON_GPIO_Y_1; + i2c.y_data_mask = RADEON_GPIO_Y_0; + i2c.mask_clk_reg = ddc_line; i2c.mask_data_reg = ddc_line; i2c.a_clk_reg = ddc_line; i2c.a_data_reg = ddc_line; - i2c.put_clk_reg = ddc_line; - i2c.put_data_reg = ddc_line; - i2c.get_clk_reg = ddc_line; - i2c.get_data_reg = ddc_line; + i2c.en_clk_reg = ddc_line; + i2c.en_data_reg = ddc_line; + i2c.y_clk_reg = ddc_line; + i2c.y_data_reg = ddc_line; + } + + if (rdev->family < CHIP_R200) + i2c.hw_capable = false; + else { + switch (ddc_line) { + case RADEON_GPIO_VGA_DDC: + case RADEON_GPIO_DVI_DDC: + i2c.hw_capable = true; + break; + case RADEON_GPIO_MONID: + /* hw i2c on RADEON_GPIO_MONID doesn't seem to work + * reliably on some pre-r4xx hardware; not sure why. + */ + i2c.hw_capable = false; + break; + default: + i2c.hw_capable = false; + break; + } } + i2c.mm_i2c = false; + i2c.i2c_id = 0; if (ddc_line) i2c.valid = true; @@ -495,7 +528,7 @@ bool radeon_combios_get_clock_info(struct drm_device *dev) uint16_t sclk, mclk; if (rdev->bios == NULL) - return NULL; + return false; pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE); if (pll_info) { @@ -993,8 +1026,8 @@ static const struct radeon_tmds_pll default_tmds_pll[CHIP_LAST][4] = { {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_R420 */ {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_R423 */ {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_RV410 */ - {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /* CHIP_RS400 */ - {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /* CHIP_RS480 */ + { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, /* CHIP_RS400 */ + { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, /* CHIP_RS480 */ }; bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder, @@ -1028,7 +1061,6 @@ bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder, tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE); if (tmds_info) { - ver = RBIOS8(tmds_info); DRM_INFO("DFP table revision: %d\n", ver); if (ver == 3) { @@ -1063,51 +1095,139 @@ bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder, tmds->tmds_pll[i].value); } } - } else + } else { DRM_INFO("No TMDS info found in BIOS\n"); + return false; + } return true; } -struct radeon_encoder_int_tmds *radeon_combios_get_tmds_info(struct radeon_encoder *encoder) +bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder, + struct radeon_encoder_ext_tmds *tmds) { - struct radeon_encoder_int_tmds *tmds = NULL; - bool ret; + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_i2c_bus_rec i2c_bus; - tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL); + /* default for macs */ + i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); + tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); - if (!tmds) - return NULL; - - ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds); - if (ret == false) - radeon_legacy_get_tmds_info_from_table(encoder, tmds); + /* XXX some macs have duallink chips */ + switch (rdev->mode_info.connector_table) { + case CT_POWERBOOK_EXTERNAL: + case CT_MINI_EXTERNAL: + default: + tmds->dvo_chip = DVO_SIL164; + tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */ + break; + } - return tmds; + return true; } -void radeon_combios_get_ext_tmds_info(struct radeon_encoder *encoder) +bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder, + struct radeon_encoder_ext_tmds *tmds) { struct drm_device *dev = encoder->base.dev; struct radeon_device *rdev = dev->dev_private; - uint16_t ext_tmds_info; - uint8_t ver; + uint16_t offset; + uint8_t ver, id, blocks, clk, data; + int i; + enum radeon_combios_ddc gpio; + struct radeon_i2c_bus_rec i2c_bus; if (rdev->bios == NULL) - return; + return false; - ext_tmds_info = - combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); - if (ext_tmds_info) { - ver = RBIOS8(ext_tmds_info); - DRM_INFO("External TMDS Table revision: %d\n", ver); - // TODO + tmds->i2c_bus = NULL; + if (rdev->flags & RADEON_IS_IGP) { + offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); + if (offset) { + ver = RBIOS8(offset); + DRM_INFO("GPIO Table revision: %d\n", ver); + blocks = RBIOS8(offset + 2); + for (i = 0; i < blocks; i++) { + id = RBIOS8(offset + 3 + (i * 5) + 0); + if (id == 136) { + clk = RBIOS8(offset + 3 + (i * 5) + 3); + data = RBIOS8(offset + 3 + (i * 5) + 4); + i2c_bus.valid = true; + i2c_bus.mask_clk_mask = (1 << clk); + i2c_bus.mask_data_mask = (1 << data); + i2c_bus.a_clk_mask = (1 << clk); + i2c_bus.a_data_mask = (1 << data); + i2c_bus.en_clk_mask = (1 << clk); + i2c_bus.en_data_mask = (1 << data); + i2c_bus.y_clk_mask = (1 << clk); + i2c_bus.y_data_mask = (1 << data); + i2c_bus.mask_clk_reg = RADEON_GPIOPAD_MASK; + i2c_bus.mask_data_reg = RADEON_GPIOPAD_MASK; + i2c_bus.a_clk_reg = RADEON_GPIOPAD_A; + i2c_bus.a_data_reg = RADEON_GPIOPAD_A; + i2c_bus.en_clk_reg = RADEON_GPIOPAD_EN; + i2c_bus.en_data_reg = RADEON_GPIOPAD_EN; + i2c_bus.y_clk_reg = RADEON_GPIOPAD_Y; + i2c_bus.y_data_reg = RADEON_GPIOPAD_Y; + tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); + tmds->dvo_chip = DVO_SIL164; + tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */ + break; + } + } + } + } else { + offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); + if (offset) { + ver = RBIOS8(offset); + DRM_INFO("External TMDS Table revision: %d\n", ver); + tmds->slave_addr = RBIOS8(offset + 4 + 2); + tmds->slave_addr >>= 1; /* 7 bit addressing */ + gpio = RBIOS8(offset + 4 + 3); + switch (gpio) { + case DDC_MONID: + i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); + tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); + break; + case DDC_DVI: + i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); + break; + case DDC_VGA: + i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); + break; + case DDC_CRT2: + /* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */ + if (rdev->family >= CHIP_R300) + i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); + else + i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); + tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); + break; + case DDC_LCD: /* MM i2c */ + DRM_ERROR("MM i2c requires hw i2c engine\n"); + break; + default: + DRM_ERROR("Unsupported gpio %d\n", gpio); + break; + } + } } + + if (!tmds->i2c_bus) { + DRM_INFO("No valid Ext TMDS info found in BIOS\n"); + return false; + } + + return true; } bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; struct radeon_i2c_bus_rec ddc_i2c; + struct radeon_hpd hpd; rdev->mode_info.connector_table = radeon_connector_table; if (rdev->mode_info.connector_table == CT_NONE) { @@ -1168,7 +1288,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) /* these are the most common settings */ if (rdev->flags & RADEON_SINGLE_CRTC) { /* VGA - primary dac */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_CRT1_SUPPORT, @@ -1178,10 +1299,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_CRT1_SUPPORT, DRM_MODE_CONNECTOR_VGA, &ddc_i2c, - CONNECTOR_OBJECT_ID_VGA); + CONNECTOR_OBJECT_ID_VGA, + &hpd); } else if (rdev->flags & RADEON_IS_MOBILITY) { /* LVDS */ - ddc_i2c = combios_setup_i2c_bus(RADEON_LCD_GPIO_MASK); + ddc_i2c = combios_setup_i2c_bus(rdev, 0); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_LCD1_SUPPORT, @@ -1191,10 +1314,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_LCD1_SUPPORT, DRM_MODE_CONNECTOR_LVDS, &ddc_i2c, - CONNECTOR_OBJECT_ID_LVDS); + CONNECTOR_OBJECT_ID_LVDS, + &hpd); /* VGA - primary dac */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_CRT1_SUPPORT, @@ -1204,10 +1329,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_CRT1_SUPPORT, DRM_MODE_CONNECTOR_VGA, &ddc_i2c, - CONNECTOR_OBJECT_ID_VGA); + CONNECTOR_OBJECT_ID_VGA, + &hpd); } else { /* DVI-I - tv dac, int tmds */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + hpd.hpd = RADEON_HPD_1; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_DFP1_SUPPORT, @@ -1223,10 +1350,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_CRT2_SUPPORT, DRM_MODE_CONNECTOR_DVII, &ddc_i2c, - CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I); + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); /* VGA - primary dac */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_CRT1_SUPPORT, @@ -1236,11 +1365,14 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_CRT1_SUPPORT, DRM_MODE_CONNECTOR_VGA, &ddc_i2c, - CONNECTOR_OBJECT_ID_VGA); + CONNECTOR_OBJECT_ID_VGA, + &hpd); } if (rdev->family != CHIP_R100 && rdev->family != CHIP_R200) { /* TV - tv dac */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_TV1_SUPPORT, @@ -1250,14 +1382,16 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_TV1_SUPPORT, DRM_MODE_CONNECTOR_SVIDEO, &ddc_i2c, - CONNECTOR_OBJECT_ID_SVIDEO); + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); } break; case CT_IBOOK: DRM_INFO("Connector Table: %d (ibook)\n", rdev->mode_info.connector_table); /* LVDS */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_LCD1_SUPPORT, @@ -1265,9 +1399,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_LCD1_SUPPORT); radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, DRM_MODE_CONNECTOR_LVDS, &ddc_i2c, - CONNECTOR_OBJECT_ID_LVDS); + CONNECTOR_OBJECT_ID_LVDS, + &hpd); /* VGA - TV DAC */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_CRT2_SUPPORT, @@ -1275,8 +1411,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_CRT2_SUPPORT); radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT, DRM_MODE_CONNECTOR_VGA, &ddc_i2c, - CONNECTOR_OBJECT_ID_VGA); + CONNECTOR_OBJECT_ID_VGA, + &hpd); /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_TV1_SUPPORT, @@ -1285,13 +1424,15 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, DRM_MODE_CONNECTOR_SVIDEO, &ddc_i2c, - CONNECTOR_OBJECT_ID_SVIDEO); + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); break; case CT_POWERBOOK_EXTERNAL: DRM_INFO("Connector Table: %d (powerbook external tmds)\n", rdev->mode_info.connector_table); /* LVDS */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_LCD1_SUPPORT, @@ -1299,9 +1440,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_LCD1_SUPPORT); radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, DRM_MODE_CONNECTOR_LVDS, &ddc_i2c, - CONNECTOR_OBJECT_ID_LVDS); + CONNECTOR_OBJECT_ID_LVDS, + &hpd); /* DVI-I - primary dac, ext tmds */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + hpd.hpd = RADEON_HPD_2; /* ??? */ radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_DFP2_SUPPORT, @@ -1317,8 +1460,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_DFP2_SUPPORT | ATOM_DEVICE_CRT1_SUPPORT, DRM_MODE_CONNECTOR_DVII, &ddc_i2c, - CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I); + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, + &hpd); /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_TV1_SUPPORT, @@ -1327,13 +1473,15 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, DRM_MODE_CONNECTOR_SVIDEO, &ddc_i2c, - CONNECTOR_OBJECT_ID_SVIDEO); + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); break; case CT_POWERBOOK_INTERNAL: DRM_INFO("Connector Table: %d (powerbook internal tmds)\n", rdev->mode_info.connector_table); /* LVDS */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_LCD1_SUPPORT, @@ -1341,9 +1489,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_LCD1_SUPPORT); radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, DRM_MODE_CONNECTOR_LVDS, &ddc_i2c, - CONNECTOR_OBJECT_ID_LVDS); + CONNECTOR_OBJECT_ID_LVDS, + &hpd); /* DVI-I - primary dac, int tmds */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + hpd.hpd = RADEON_HPD_1; /* ??? */ radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_DFP1_SUPPORT, @@ -1358,8 +1508,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_DFP1_SUPPORT | ATOM_DEVICE_CRT1_SUPPORT, DRM_MODE_CONNECTOR_DVII, &ddc_i2c, - CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I); + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_TV1_SUPPORT, @@ -1368,13 +1521,15 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, DRM_MODE_CONNECTOR_SVIDEO, &ddc_i2c, - CONNECTOR_OBJECT_ID_SVIDEO); + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); break; case CT_POWERBOOK_VGA: DRM_INFO("Connector Table: %d (powerbook vga)\n", rdev->mode_info.connector_table); /* LVDS */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_LCD1_SUPPORT, @@ -1382,9 +1537,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_LCD1_SUPPORT); radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, DRM_MODE_CONNECTOR_LVDS, &ddc_i2c, - CONNECTOR_OBJECT_ID_LVDS); + CONNECTOR_OBJECT_ID_LVDS, + &hpd); /* VGA - primary dac */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_CRT1_SUPPORT, @@ -1392,8 +1549,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_CRT1_SUPPORT); radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT, DRM_MODE_CONNECTOR_VGA, &ddc_i2c, - CONNECTOR_OBJECT_ID_VGA); + CONNECTOR_OBJECT_ID_VGA, + &hpd); /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_TV1_SUPPORT, @@ -1402,13 +1562,15 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, DRM_MODE_CONNECTOR_SVIDEO, &ddc_i2c, - CONNECTOR_OBJECT_ID_SVIDEO); + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); break; case CT_MINI_EXTERNAL: DRM_INFO("Connector Table: %d (mini external tmds)\n", rdev->mode_info.connector_table); /* DVI-I - tv dac, ext tmds */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); + hpd.hpd = RADEON_HPD_2; /* ??? */ radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_DFP2_SUPPORT, @@ -1424,8 +1586,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_DFP2_SUPPORT | ATOM_DEVICE_CRT2_SUPPORT, DRM_MODE_CONNECTOR_DVII, &ddc_i2c, - CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I); + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_TV1_SUPPORT, @@ -1434,13 +1599,15 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT, DRM_MODE_CONNECTOR_SVIDEO, &ddc_i2c, - CONNECTOR_OBJECT_ID_SVIDEO); + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); break; case CT_MINI_INTERNAL: DRM_INFO("Connector Table: %d (mini internal tmds)\n", rdev->mode_info.connector_table); /* DVI-I - tv dac, int tmds */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); + hpd.hpd = RADEON_HPD_1; /* ??? */ radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_DFP1_SUPPORT, @@ -1455,8 +1622,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_DFP1_SUPPORT | ATOM_DEVICE_CRT2_SUPPORT, DRM_MODE_CONNECTOR_DVII, &ddc_i2c, - CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I); + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_TV1_SUPPORT, @@ -1465,13 +1635,15 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT, DRM_MODE_CONNECTOR_SVIDEO, &ddc_i2c, - CONNECTOR_OBJECT_ID_SVIDEO); + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); break; case CT_IMAC_G5_ISIGHT: DRM_INFO("Connector Table: %d (imac g5 isight)\n", rdev->mode_info.connector_table); /* DVI-D - int tmds */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); + hpd.hpd = RADEON_HPD_1; /* ??? */ radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_DFP1_SUPPORT, @@ -1479,9 +1651,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_DFP1_SUPPORT); radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_DFP1_SUPPORT, DRM_MODE_CONNECTOR_DVID, &ddc_i2c, - CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D); + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D, + &hpd); /* VGA - tv dac */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_CRT2_SUPPORT, @@ -1489,8 +1663,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_CRT2_SUPPORT); radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT, DRM_MODE_CONNECTOR_VGA, &ddc_i2c, - CONNECTOR_OBJECT_ID_VGA); + CONNECTOR_OBJECT_ID_VGA, + &hpd); /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_TV1_SUPPORT, @@ -1499,13 +1676,15 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, DRM_MODE_CONNECTOR_SVIDEO, &ddc_i2c, - CONNECTOR_OBJECT_ID_SVIDEO); + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); break; case CT_EMAC: DRM_INFO("Connector Table: %d (emac)\n", rdev->mode_info.connector_table); /* VGA - primary dac */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_CRT1_SUPPORT, @@ -1513,9 +1692,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_CRT1_SUPPORT); radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT, DRM_MODE_CONNECTOR_VGA, &ddc_i2c, - CONNECTOR_OBJECT_ID_VGA); + CONNECTOR_OBJECT_ID_VGA, + &hpd); /* VGA - tv dac */ - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_CRT2_SUPPORT, @@ -1523,8 +1704,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ATOM_DEVICE_CRT2_SUPPORT); radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT, DRM_MODE_CONNECTOR_VGA, &ddc_i2c, - CONNECTOR_OBJECT_ID_VGA); + CONNECTOR_OBJECT_ID_VGA, + &hpd); /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, ATOM_DEVICE_TV1_SUPPORT, @@ -1533,7 +1717,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, DRM_MODE_CONNECTOR_SVIDEO, &ddc_i2c, - CONNECTOR_OBJECT_ID_SVIDEO); + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); break; default: DRM_INFO("Connector table: %d (invalid)\n", @@ -1550,7 +1735,8 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev, int bios_index, enum radeon_combios_connector *legacy_connector, - struct radeon_i2c_bus_rec *ddc_i2c) + struct radeon_i2c_bus_rec *ddc_i2c, + struct radeon_hpd *hpd) { struct radeon_device *rdev = dev->dev_private; @@ -1558,29 +1744,26 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev, if ((rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) && ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC) - *ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID); + *ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); else if ((rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) && ddc_i2c->mask_clk_reg == RADEON_GPIO_MONID) { - ddc_i2c->valid = true; + *ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIOPAD_MASK); ddc_i2c->mask_clk_mask = (0x20 << 8); ddc_i2c->mask_data_mask = 0x80; ddc_i2c->a_clk_mask = (0x20 << 8); ddc_i2c->a_data_mask = 0x80; - ddc_i2c->put_clk_mask = (0x20 << 8); - ddc_i2c->put_data_mask = 0x80; - ddc_i2c->get_clk_mask = (0x20 << 8); - ddc_i2c->get_data_mask = 0x80; - ddc_i2c->mask_clk_reg = RADEON_GPIOPAD_MASK; - ddc_i2c->mask_data_reg = RADEON_GPIOPAD_MASK; - ddc_i2c->a_clk_reg = RADEON_GPIOPAD_A; - ddc_i2c->a_data_reg = RADEON_GPIOPAD_A; - ddc_i2c->put_clk_reg = RADEON_GPIOPAD_EN; - ddc_i2c->put_data_reg = RADEON_GPIOPAD_EN; - ddc_i2c->get_clk_reg = RADEON_LCD_GPIO_Y_REG; - ddc_i2c->get_data_reg = RADEON_LCD_GPIO_Y_REG; + ddc_i2c->en_clk_mask = (0x20 << 8); + ddc_i2c->en_data_mask = 0x80; + ddc_i2c->y_clk_mask = (0x20 << 8); + ddc_i2c->y_data_mask = 0x80; } + /* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */ + if ((rdev->family >= CHIP_R300) && + ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC) + *ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + /* Certain IBM chipset RN50s have a BIOS reporting two VGAs, one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */ if (dev->pdev->device == 0x515e && @@ -1624,6 +1807,12 @@ static bool radeon_apply_legacy_tv_quirks(struct drm_device *dev) dev->pdev->subsystem_device == 0x280a) return false; + /* MSI S270 has non-existent TV port */ + if (dev->pdev->device == 0x5955 && + dev->pdev->subsystem_vendor == 0x1462 && + dev->pdev->subsystem_device == 0x0131) + return false; + return true; } @@ -1671,6 +1860,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) enum radeon_combios_connector connector; int i = 0; struct radeon_i2c_bus_rec ddc_i2c; + struct radeon_hpd hpd; if (rdev->bios == NULL) return false; @@ -1691,26 +1881,40 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) switch (ddc_type) { case DDC_MONID: ddc_i2c = - combios_setup_i2c_bus(RADEON_GPIO_MONID); + combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); break; case DDC_DVI: ddc_i2c = - combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); + combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); break; case DDC_VGA: ddc_i2c = - combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); + combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); break; case DDC_CRT2: ddc_i2c = - combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); + combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); break; default: break; } + switch (connector) { + case CONNECTOR_PROPRIETARY_LEGACY: + case CONNECTOR_DVI_I_LEGACY: + case CONNECTOR_DVI_D_LEGACY: + if ((tmp >> 4) & 0x1) + hpd.hpd = RADEON_HPD_2; + else + hpd.hpd = RADEON_HPD_1; + break; + default: + hpd.hpd = RADEON_HPD_NONE; + break; + } + if (!radeon_apply_legacy_quirks(dev, i, &connector, - &ddc_i2c)) + &ddc_i2c, &hpd)) continue; switch (connector) { @@ -1727,7 +1931,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) legacy_connector_convert [connector], &ddc_i2c, - CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D); + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D, + &hpd); break; case CONNECTOR_CRT_LEGACY: if (tmp & 0x1) { @@ -1753,7 +1958,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) legacy_connector_convert [connector], &ddc_i2c, - CONNECTOR_OBJECT_ID_VGA); + CONNECTOR_OBJECT_ID_VGA, + &hpd); break; case CONNECTOR_DVI_I_LEGACY: devices = 0; @@ -1799,7 +2005,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) legacy_connector_convert [connector], &ddc_i2c, - connector_object_id); + connector_object_id, + &hpd); break; case CONNECTOR_DVI_D_LEGACY: if ((tmp >> 4) & 0x1) { @@ -1817,7 +2024,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) legacy_connector_convert [connector], &ddc_i2c, - connector_object_id); + connector_object_id, + &hpd); break; case CONNECTOR_CTV_LEGACY: case CONNECTOR_STV_LEGACY: @@ -1832,7 +2040,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) legacy_connector_convert [connector], &ddc_i2c, - CONNECTOR_OBJECT_ID_SVIDEO); + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); break; default: DRM_ERROR("Unknown connector type: %d\n", @@ -1858,14 +2067,16 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) 0), ATOM_DEVICE_DFP1_SUPPORT); - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_DFP1_SUPPORT, DRM_MODE_CONNECTOR_DVII, &ddc_i2c, - CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I); + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); } else { uint16_t crt_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE); @@ -1876,13 +2087,15 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) ATOM_DEVICE_CRT1_SUPPORT, 1), ATOM_DEVICE_CRT1_SUPPORT); - ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT, DRM_MODE_CONNECTOR_VGA, &ddc_i2c, - CONNECTOR_OBJECT_ID_VGA); + CONNECTOR_OBJECT_ID_VGA, + &hpd); } else { DRM_DEBUG("No connector info found\n"); return false; @@ -1910,27 +2123,27 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) case DDC_MONID: ddc_i2c = combios_setup_i2c_bus - (RADEON_GPIO_MONID); + (rdev, RADEON_GPIO_MONID); break; case DDC_DVI: ddc_i2c = combios_setup_i2c_bus - (RADEON_GPIO_DVI_DDC); + (rdev, RADEON_GPIO_DVI_DDC); break; case DDC_VGA: ddc_i2c = combios_setup_i2c_bus - (RADEON_GPIO_VGA_DDC); + (rdev, RADEON_GPIO_VGA_DDC); break; case DDC_CRT2: ddc_i2c = combios_setup_i2c_bus - (RADEON_GPIO_CRT2_DDC); + (rdev, RADEON_GPIO_CRT2_DDC); break; case DDC_LCD: ddc_i2c = combios_setup_i2c_bus - (RADEON_LCD_GPIO_MASK); + (rdev, RADEON_GPIOPAD_MASK); ddc_i2c.mask_clk_mask = RBIOS32(lcd_ddc_info + 3); ddc_i2c.mask_data_mask = @@ -1939,19 +2152,19 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) RBIOS32(lcd_ddc_info + 3); ddc_i2c.a_data_mask = RBIOS32(lcd_ddc_info + 7); - ddc_i2c.put_clk_mask = + ddc_i2c.en_clk_mask = RBIOS32(lcd_ddc_info + 3); - ddc_i2c.put_data_mask = + ddc_i2c.en_data_mask = RBIOS32(lcd_ddc_info + 7); - ddc_i2c.get_clk_mask = + ddc_i2c.y_clk_mask = RBIOS32(lcd_ddc_info + 3); - ddc_i2c.get_data_mask = + ddc_i2c.y_data_mask = RBIOS32(lcd_ddc_info + 7); break; case DDC_GPIO: ddc_i2c = combios_setup_i2c_bus - (RADEON_MDGPIO_EN_REG); + (rdev, RADEON_MDGPIO_MASK); ddc_i2c.mask_clk_mask = RBIOS32(lcd_ddc_info + 3); ddc_i2c.mask_data_mask = @@ -1960,13 +2173,13 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) RBIOS32(lcd_ddc_info + 3); ddc_i2c.a_data_mask = RBIOS32(lcd_ddc_info + 7); - ddc_i2c.put_clk_mask = + ddc_i2c.en_clk_mask = RBIOS32(lcd_ddc_info + 3); - ddc_i2c.put_data_mask = + ddc_i2c.en_data_mask = RBIOS32(lcd_ddc_info + 7); - ddc_i2c.get_clk_mask = + ddc_i2c.y_clk_mask = RBIOS32(lcd_ddc_info + 3); - ddc_i2c.get_data_mask = + ddc_i2c.y_data_mask = RBIOS32(lcd_ddc_info + 7); break; default: @@ -1977,12 +2190,14 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) } else ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_connector(dev, 5, ATOM_DEVICE_LCD1_SUPPORT, DRM_MODE_CONNECTOR_LVDS, &ddc_i2c, - CONNECTOR_OBJECT_ID_LVDS); + CONNECTOR_OBJECT_ID_LVDS, + &hpd); } } @@ -1993,6 +2208,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) if (tv_info) { if (RBIOS8(tv_info + 6) == 'T') { if (radeon_apply_legacy_tv_quirks(dev)) { + hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id (dev, @@ -2003,7 +2219,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) ATOM_DEVICE_TV1_SUPPORT, DRM_MODE_CONNECTOR_SVIDEO, &ddc_i2c, - CONNECTOR_OBJECT_ID_SVIDEO); + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); } } } @@ -2014,6 +2231,193 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) return true; } +void radeon_external_tmds_setup(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv; + + if (!tmds) + return; + + switch (tmds->dvo_chip) { + case DVO_SIL164: + /* sil 164 */ + radeon_i2c_do_lock(tmds->i2c_bus, 1); + radeon_i2c_sw_put_byte(tmds->i2c_bus, + tmds->slave_addr, + 0x08, 0x30); + radeon_i2c_sw_put_byte(tmds->i2c_bus, + tmds->slave_addr, + 0x09, 0x00); + radeon_i2c_sw_put_byte(tmds->i2c_bus, + tmds->slave_addr, + 0x0a, 0x90); + radeon_i2c_sw_put_byte(tmds->i2c_bus, + tmds->slave_addr, + 0x0c, 0x89); + radeon_i2c_sw_put_byte(tmds->i2c_bus, + tmds->slave_addr, + 0x08, 0x3b); + radeon_i2c_do_lock(tmds->i2c_bus, 0); + break; + case DVO_SIL1178: + /* sil 1178 - untested */ + /* + * 0x0f, 0x44 + * 0x0f, 0x4c + * 0x0e, 0x01 + * 0x0a, 0x80 + * 0x09, 0x30 + * 0x0c, 0xc9 + * 0x0d, 0x70 + * 0x08, 0x32 + * 0x08, 0x33 + */ + break; + default: + break; + } + +} + +bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint16_t offset; + uint8_t blocks, slave_addr, rev; + uint32_t index, id; + uint32_t reg, val, and_mask, or_mask; + struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv; + + if (rdev->bios == NULL) + return false; + + if (!tmds) + return false; + + if (rdev->flags & RADEON_IS_IGP) { + offset = combios_get_table_offset(dev, COMBIOS_TMDS_POWER_ON_TABLE); + rev = RBIOS8(offset); + if (offset) { + rev = RBIOS8(offset); + if (rev > 1) { + blocks = RBIOS8(offset + 3); + index = offset + 4; + while (blocks > 0) { + id = RBIOS16(index); + index += 2; + switch (id >> 13) { + case 0: + reg = (id & 0x1fff) * 4; + val = RBIOS32(index); + index += 4; + WREG32(reg, val); + break; + case 2: + reg = (id & 0x1fff) * 4; + and_mask = RBIOS32(index); + index += 4; + or_mask = RBIOS32(index); + index += 4; + val = RREG32(reg); + val = (val & and_mask) | or_mask; + WREG32(reg, val); + break; + case 3: + val = RBIOS16(index); + index += 2; + udelay(val); + break; + case 4: + val = RBIOS16(index); + index += 2; + udelay(val * 1000); + break; + case 6: + slave_addr = id & 0xff; + slave_addr >>= 1; /* 7 bit addressing */ + index++; + reg = RBIOS8(index); + index++; + val = RBIOS8(index); + index++; + radeon_i2c_do_lock(tmds->i2c_bus, 1); + radeon_i2c_sw_put_byte(tmds->i2c_bus, + slave_addr, + reg, val); + radeon_i2c_do_lock(tmds->i2c_bus, 0); + break; + default: + DRM_ERROR("Unknown id %d\n", id >> 13); + break; + } + blocks--; + } + return true; + } + } + } else { + offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); + if (offset) { + index = offset + 10; + id = RBIOS16(index); + while (id != 0xffff) { + index += 2; + switch (id >> 13) { + case 0: + reg = (id & 0x1fff) * 4; + val = RBIOS32(index); + WREG32(reg, val); + break; + case 2: + reg = (id & 0x1fff) * 4; + and_mask = RBIOS32(index); + index += 4; + or_mask = RBIOS32(index); + index += 4; + val = RREG32(reg); + val = (val & and_mask) | or_mask; + WREG32(reg, val); + break; + case 4: + val = RBIOS16(index); + index += 2; + udelay(val); + break; + case 5: + reg = id & 0x1fff; + and_mask = RBIOS32(index); + index += 4; + or_mask = RBIOS32(index); + index += 4; + val = RREG32_PLL(reg); + val = (val & and_mask) | or_mask; + WREG32_PLL(reg, val); + break; + case 6: + reg = id & 0x1fff; + val = RBIOS8(index); + index += 1; + radeon_i2c_do_lock(tmds->i2c_bus, 1); + radeon_i2c_sw_put_byte(tmds->i2c_bus, + tmds->slave_addr, + reg, val); + radeon_i2c_do_lock(tmds->i2c_bus, 0); + break; + default: + DRM_ERROR("Unknown id %d\n", id >> 13); + break; + } + id = RBIOS16(index); + } + return true; + } + } + return false; +} + static void combios_parse_mmio_table(struct drm_device *dev, uint16_t offset) { struct radeon_device *rdev = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 29763ceae3af9de8dc2067ff38e0ac63d59fe75e..5eece186e03c5ae388bed2b6c5421365c9004538 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -40,6 +40,26 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector, struct drm_encoder *encoder, bool connected); +void radeon_connector_hotplug(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + + if (radeon_connector->hpd.hpd != RADEON_HPD_NONE) + radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); + + if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { + if (radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_DISPLAYPORT) { + if (radeon_dp_needs_link_train(radeon_connector)) { + if (connector->encoder) + dp_link_train(connector->encoder, connector); + } + } + } + +} + static void radeon_property_change_mode(struct drm_encoder *encoder) { struct drm_crtc *crtc = encoder->crtc; @@ -445,10 +465,10 @@ static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connec ret = connector_status_connected; else { if (radeon_connector->ddc_bus) { - radeon_i2c_do_lock(radeon_connector, 1); + radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); - radeon_i2c_do_lock(radeon_connector, 0); + radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); if (radeon_connector->edid) ret = connector_status_connected; } @@ -553,17 +573,17 @@ static enum drm_connector_status radeon_vga_detect(struct drm_connector *connect if (!encoder) ret = connector_status_disconnected; - radeon_i2c_do_lock(radeon_connector, 1); + radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); dret = radeon_ddc_probe(radeon_connector); - radeon_i2c_do_lock(radeon_connector, 0); + radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); if (dret) { if (radeon_connector->edid) { kfree(radeon_connector->edid); radeon_connector->edid = NULL; } - radeon_i2c_do_lock(radeon_connector, 1); + radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); - radeon_i2c_do_lock(radeon_connector, 0); + radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); if (!radeon_connector->edid) { DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", @@ -708,17 +728,17 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect enum drm_connector_status ret = connector_status_disconnected; bool dret; - radeon_i2c_do_lock(radeon_connector, 1); + radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); dret = radeon_ddc_probe(radeon_connector); - radeon_i2c_do_lock(radeon_connector, 0); + radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); if (dret) { if (radeon_connector->edid) { kfree(radeon_connector->edid); radeon_connector->edid = NULL; } - radeon_i2c_do_lock(radeon_connector, 1); + radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); - radeon_i2c_do_lock(radeon_connector, 0); + radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); if (!radeon_connector->edid) { DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", @@ -735,6 +755,39 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect ret = connector_status_disconnected; } else ret = connector_status_connected; + + /* multiple connectors on the same encoder with the same ddc line + * This tends to be HDMI and DVI on the same encoder with the + * same ddc line. If the edid says HDMI, consider the HDMI port + * connected and the DVI port disconnected. If the edid doesn't + * say HDMI, vice versa. + */ + if (radeon_connector->shared_ddc && connector_status_connected) { + struct drm_device *dev = connector->dev; + struct drm_connector *list_connector; + struct radeon_connector *list_radeon_connector; + list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) { + if (connector == list_connector) + continue; + list_radeon_connector = to_radeon_connector(list_connector); + if (radeon_connector->devices == list_radeon_connector->devices) { + if (drm_detect_hdmi_monitor(radeon_connector->edid)) { + if (connector->connector_type == DRM_MODE_CONNECTOR_DVID) { + kfree(radeon_connector->edid); + radeon_connector->edid = NULL; + ret = connector_status_disconnected; + } + } else { + if ((connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) || + (connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)) { + kfree(radeon_connector->edid); + radeon_connector->edid = NULL; + ret = connector_status_disconnected; + } + } + } + } + } } } @@ -863,6 +916,91 @@ struct drm_connector_funcs radeon_dvi_connector_funcs = { .force = radeon_dvi_force, }; +static void radeon_dp_connector_destroy(struct drm_connector *connector) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; + + if (radeon_connector->ddc_bus) + radeon_i2c_destroy(radeon_connector->ddc_bus); + if (radeon_connector->edid) + kfree(radeon_connector->edid); + if (radeon_dig_connector->dp_i2c_bus) + radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus); + kfree(radeon_connector->con_priv); + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(connector); +} + +static int radeon_dp_get_modes(struct drm_connector *connector) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + int ret; + + ret = radeon_ddc_get_modes(radeon_connector); + return ret; +} + +static enum drm_connector_status radeon_dp_detect(struct drm_connector *connector) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + enum drm_connector_status ret = connector_status_disconnected; + struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; + u8 sink_type; + + if (radeon_connector->edid) { + kfree(radeon_connector->edid); + radeon_connector->edid = NULL; + } + + sink_type = radeon_dp_getsinktype(radeon_connector); + if (sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { + if (radeon_dp_getdpcd(radeon_connector)) { + radeon_dig_connector->dp_sink_type = sink_type; + ret = connector_status_connected; + } + } else { + radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); + if (radeon_ddc_probe(radeon_connector)) { + radeon_dig_connector->dp_sink_type = sink_type; + ret = connector_status_connected; + } + radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); + } + + return ret; +} + +static int radeon_dp_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; + + /* XXX check mode bandwidth */ + + if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) + return radeon_dp_mode_valid_helper(radeon_connector, mode); + else + return MODE_OK; +} + +struct drm_connector_helper_funcs radeon_dp_connector_helper_funcs = { + .get_modes = radeon_dp_get_modes, + .mode_valid = radeon_dp_mode_valid, + .best_encoder = radeon_dvi_encoder, +}; + +struct drm_connector_funcs radeon_dp_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .detect = radeon_dp_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .set_property = radeon_connector_set_property, + .destroy = radeon_dp_connector_destroy, + .force = radeon_dvi_force, +}; + void radeon_add_atom_connector(struct drm_device *dev, uint32_t connector_id, @@ -871,7 +1009,8 @@ radeon_add_atom_connector(struct drm_device *dev, struct radeon_i2c_bus_rec *i2c_bus, bool linkb, uint32_t igp_lane_info, - uint16_t connector_object_id) + uint16_t connector_object_id, + struct radeon_hpd *hpd) { struct radeon_device *rdev = dev->dev_private; struct drm_connector *connector; @@ -911,6 +1050,7 @@ radeon_add_atom_connector(struct drm_device *dev, radeon_connector->devices = supported_device; radeon_connector->shared_ddc = shared_ddc; radeon_connector->connector_object_id = connector_object_id; + radeon_connector->hpd = *hpd; switch (connector_type) { case DRM_MODE_CONNECTOR_VGA: drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); @@ -963,10 +1103,12 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.coherent_mode_property, 1); - radeon_connector->dac_load_detect = true; - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.load_detect_property, - 1); + if (connector_type == DRM_MODE_CONNECTOR_DVII) { + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + } break; case DRM_MODE_CONNECTOR_HDMIA: case DRM_MODE_CONNECTOR_HDMIB: @@ -997,16 +1139,23 @@ radeon_add_atom_connector(struct drm_device *dev, radeon_dig_connector->linkb = linkb; radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_connector->con_priv = radeon_dig_connector; - drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); - ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); + drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); + ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); if (ret) goto failed; if (i2c_bus->valid) { + /* add DP i2c bus */ + radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); + if (!radeon_dig_connector->dp_i2c_bus) + goto failed; radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); if (!radeon_connector->ddc_bus) goto failed; } subpixel_order = SubPixelHorizontalRGB; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.coherent_mode_property, + 1); break; case DRM_MODE_CONNECTOR_SVIDEO: case DRM_MODE_CONNECTOR_Composite: @@ -1020,6 +1169,9 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.load_detect_property, 1); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.tv_std_property, + 1); } break; case DRM_MODE_CONNECTOR_LVDS: @@ -1038,7 +1190,6 @@ radeon_add_atom_connector(struct drm_device *dev, if (!radeon_connector->ddc_bus) goto failed; } - drm_mode_create_scaling_mode_property(dev); drm_connector_attach_property(&radeon_connector->base, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN); @@ -1063,7 +1214,8 @@ radeon_add_legacy_connector(struct drm_device *dev, uint32_t supported_device, int connector_type, struct radeon_i2c_bus_rec *i2c_bus, - uint16_t connector_object_id) + uint16_t connector_object_id, + struct radeon_hpd *hpd) { struct radeon_device *rdev = dev->dev_private; struct drm_connector *connector; @@ -1093,6 +1245,7 @@ radeon_add_legacy_connector(struct drm_device *dev, radeon_connector->connector_id = connector_id; radeon_connector->devices = supported_device; radeon_connector->connector_object_id = connector_object_id; + radeon_connector->hpd = *hpd; switch (connector_type) { case DRM_MODE_CONNECTOR_VGA: drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); @@ -1160,6 +1313,9 @@ radeon_add_legacy_connector(struct drm_device *dev, drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.load_detect_property, 1); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.tv_std_property, + 1); } break; case DRM_MODE_CONNECTOR_LVDS: diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 4f7afc79dd82c6db776c55a656c38cd450bb575a..0b2f9c2ad2c16a38814286e848135894f17e12c4 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -1941,8 +1941,8 @@ struct drm_buf *radeon_freelist_get(struct drm_device * dev) for (t = 0; t < dev_priv->usec_timeout; t++) { u32 done_age = GET_SCRATCH(dev_priv, 1); DRM_DEBUG("done_age = %d\n", done_age); - for (i = start; i < dma->buf_count; i++) { - buf = dma->buflist[i]; + for (i = 0; i < dma->buf_count; i++) { + buf = dma->buflist[start]; buf_priv = buf->dev_private; if (buf->file_priv == NULL || (buf->pending && buf_priv->age <= @@ -1951,7 +1951,8 @@ struct drm_buf *radeon_freelist_get(struct drm_device * dev) buf->pending = 0; return buf; } - start = 0; + if (++start >= dma->buf_count) + start = 0; } if (t) { @@ -1960,47 +1961,9 @@ struct drm_buf *radeon_freelist_get(struct drm_device * dev) } } - DRM_DEBUG("returning NULL!\n"); return NULL; } -#if 0 -struct drm_buf *radeon_freelist_get(struct drm_device * dev) -{ - struct drm_device_dma *dma = dev->dma; - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_buf_priv_t *buf_priv; - struct drm_buf *buf; - int i, t; - int start; - u32 done_age; - - done_age = radeon_read_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1)); - if (++dev_priv->last_buf >= dma->buf_count) - dev_priv->last_buf = 0; - - start = dev_priv->last_buf; - dev_priv->stats.freelist_loops++; - - for (t = 0; t < 2; t++) { - for (i = start; i < dma->buf_count; i++) { - buf = dma->buflist[i]; - buf_priv = buf->dev_private; - if (buf->file_priv == 0 || (buf->pending && - buf_priv->age <= - done_age)) { - dev_priv->stats.requested_bufs++; - buf->pending = 0; - return buf; - } - } - start = 0; - } - - return NULL; -} -#endif - void radeon_freelist_reset(struct drm_device * dev) { struct drm_device_dma *dma = dev->dma; diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 5ab2cf96a26498a3d29aba7fe18ed6c46716b161..65590a0f1d93f431c2a0a9585caa6e04b68e6e09 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -76,17 +76,17 @@ int radeon_cs_parser_relocs(struct radeon_cs_parser *p) } p->relocs_ptr[i] = &p->relocs[i]; p->relocs[i].robj = p->relocs[i].gobj->driver_private; - p->relocs[i].lobj.robj = p->relocs[i].robj; + p->relocs[i].lobj.bo = p->relocs[i].robj; p->relocs[i].lobj.rdomain = r->read_domains; p->relocs[i].lobj.wdomain = r->write_domain; p->relocs[i].handle = r->handle; p->relocs[i].flags = r->flags; INIT_LIST_HEAD(&p->relocs[i].lobj.list); - radeon_object_list_add_object(&p->relocs[i].lobj, - &p->validated); + radeon_bo_list_add_object(&p->relocs[i].lobj, + &p->validated); } } - return radeon_object_list_validate(&p->validated, p->ib->fence); + return radeon_bo_list_validate(&p->validated, p->ib->fence); } int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) @@ -190,9 +190,10 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error) unsigned i; if (error) { - radeon_object_list_unvalidate(&parser->validated); + radeon_bo_list_unvalidate(&parser->validated, + parser->ib->fence); } else { - radeon_object_list_clean(&parser->validated); + radeon_bo_list_unreserve(&parser->validated); } for (i = 0; i < parser->nrelocs; i++) { if (parser->relocs[i].gobj) { diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 41bb76fbe734f282dadbfee6d70ba1e046e6ecee..02bcdb1240c0ffe73253ddf37a02dfa4546f1944 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -44,10 +44,11 @@ void radeon_surface_init(struct radeon_device *rdev) if (rdev->family < CHIP_R600) { int i; - for (i = 0; i < 8; i++) { - WREG32(RADEON_SURFACE0_INFO + - i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), - 0); + for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) { + if (rdev->surface_regs[i].bo) + radeon_bo_get_surface_reg(rdev->surface_regs[i].bo); + else + radeon_clear_surface_reg(rdev, i); } /* enable surfaces */ WREG32(RADEON_SURFACE_CNTL, 0); @@ -208,6 +209,24 @@ bool radeon_card_posted(struct radeon_device *rdev) } +bool radeon_boot_test_post_card(struct radeon_device *rdev) +{ + if (radeon_card_posted(rdev)) + return true; + + if (rdev->bios) { + DRM_INFO("GPU not posted. posting now...\n"); + if (rdev->is_atom_bios) + atom_asic_init(rdev->mode_info.atom_context); + else + radeon_combios_asic_init(rdev->ddev); + return true; + } else { + dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); + return false; + } +} + int radeon_dummy_page_init(struct radeon_device *rdev) { rdev->dummy_page.page = alloc_page(GFP_DMA32 | GFP_KERNEL | __GFP_ZERO); @@ -463,12 +482,16 @@ int radeon_atombios_init(struct radeon_device *rdev) rdev->mode_info.atom_context = atom_parse(atom_card_info, rdev->bios); radeon_atom_initialize_bios_scratch_regs(rdev->ddev); + atom_allocate_fb_scratch(rdev->mode_info.atom_context); return 0; } void radeon_atombios_fini(struct radeon_device *rdev) { - kfree(rdev->mode_info.atom_context); + if (rdev->mode_info.atom_context) { + kfree(rdev->mode_info.atom_context->scratch); + kfree(rdev->mode_info.atom_context); + } kfree(rdev->mode_info.atom_card_info); } @@ -544,16 +567,24 @@ int radeon_device_init(struct radeon_device *rdev, mutex_init(&rdev->cs_mutex); mutex_init(&rdev->ib_pool.mutex); mutex_init(&rdev->cp.mutex); + if (rdev->family >= CHIP_R600) + spin_lock_init(&rdev->ih.lock); + mutex_init(&rdev->gem.mutex); rwlock_init(&rdev->fence_drv.lock); INIT_LIST_HEAD(&rdev->gem.objects); + /* setup workqueue */ + rdev->wq = create_workqueue("radeon"); + if (rdev->wq == NULL) + return -ENOMEM; + /* Set asic functions */ r = radeon_asic_init(rdev); if (r) { return r; } - if (radeon_agpmode == -1) { + if (rdev->flags & RADEON_IS_AGP && radeon_agpmode == -1) { radeon_agp_disable(rdev); } @@ -620,6 +651,7 @@ void radeon_device_fini(struct radeon_device *rdev) DRM_INFO("radeon: finishing device.\n"); rdev->shutdown = true; radeon_fini(rdev); + destroy_workqueue(rdev->wq); vga_client_register(rdev->pdev, NULL, NULL, NULL); iounmap(rdev->rmmio); rdev->rmmio = NULL; @@ -633,6 +665,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) { struct radeon_device *rdev = dev->dev_private; struct drm_crtc *crtc; + int r; if (dev == NULL || rdev == NULL) { return -ENODEV; @@ -643,26 +676,31 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) /* unpin the front buffers */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); - struct radeon_object *robj; + struct radeon_bo *robj; if (rfb == NULL || rfb->obj == NULL) { continue; } robj = rfb->obj->driver_private; - if (robj != rdev->fbdev_robj) { - radeon_object_unpin(robj); + if (robj != rdev->fbdev_rbo) { + r = radeon_bo_reserve(robj, false); + if (unlikely(r == 0)) { + radeon_bo_unpin(robj); + radeon_bo_unreserve(robj); + } } } /* evict vram memory */ - radeon_object_evict_vram(rdev); + radeon_bo_evict_vram(rdev); /* wait for gpu to finish processing current batch */ radeon_fence_wait_last(rdev); radeon_save_bios_scratch_regs(rdev); radeon_suspend(rdev); + radeon_hpd_fini(rdev); /* evict remaining vram memory */ - radeon_object_evict_vram(rdev); + radeon_bo_evict_vram(rdev); pci_save_state(dev->pdev); if (state.event == PM_EVENT_SUSPEND) { @@ -695,6 +733,8 @@ int radeon_resume_kms(struct drm_device *dev) fb_set_suspend(rdev->fbdev_info, 0); release_console_sem(); + /* reset hpd state */ + radeon_hpd_init(rdev); /* blat the mode back in */ drm_helper_resume_force_mode(dev); return 0; diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index c85df4afcb7ac09e2f89ec21f116a7ee4bdfaa39..a133b833e45d46de500a0de9d9ccb89cbc0df8ab 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -250,6 +250,16 @@ static const char *connector_names[13] = { "HDMI-B", }; +static const char *hpd_names[7] = { + "NONE", + "HPD1", + "HPD2", + "HPD3", + "HPD4", + "HPD5", + "HPD6", +}; + static void radeon_print_display_setup(struct drm_device *dev) { struct drm_connector *connector; @@ -264,16 +274,18 @@ static void radeon_print_display_setup(struct drm_device *dev) radeon_connector = to_radeon_connector(connector); DRM_INFO("Connector %d:\n", i); DRM_INFO(" %s\n", connector_names[connector->connector_type]); + if (radeon_connector->hpd.hpd != RADEON_HPD_NONE) + DRM_INFO(" %s\n", hpd_names[radeon_connector->hpd.hpd]); if (radeon_connector->ddc_bus) DRM_INFO(" DDC: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", radeon_connector->ddc_bus->rec.mask_clk_reg, radeon_connector->ddc_bus->rec.mask_data_reg, radeon_connector->ddc_bus->rec.a_clk_reg, radeon_connector->ddc_bus->rec.a_data_reg, - radeon_connector->ddc_bus->rec.put_clk_reg, - radeon_connector->ddc_bus->rec.put_data_reg, - radeon_connector->ddc_bus->rec.get_clk_reg, - radeon_connector->ddc_bus->rec.get_data_reg); + radeon_connector->ddc_bus->rec.en_clk_reg, + radeon_connector->ddc_bus->rec.en_data_reg, + radeon_connector->ddc_bus->rec.y_clk_reg, + radeon_connector->ddc_bus->rec.y_data_reg); DRM_INFO(" Encoders:\n"); list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { radeon_encoder = to_radeon_encoder(encoder); @@ -324,6 +336,7 @@ static bool radeon_setup_enc_conn(struct drm_device *dev) ret = radeon_get_legacy_connector_info_from_table(dev); } if (ret) { + radeon_setup_encoder_clones(dev); radeon_print_display_setup(dev); list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) radeon_ddc_dump(drm_connector); @@ -336,12 +349,17 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) { int ret = 0; + if (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) { + struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; + if (dig->dp_i2c_bus) + radeon_connector->edid = drm_get_edid(&radeon_connector->base, &dig->dp_i2c_bus->adapter); + } if (!radeon_connector->ddc_bus) return -1; if (!radeon_connector->edid) { - radeon_i2c_do_lock(radeon_connector, 1); + radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); - radeon_i2c_do_lock(radeon_connector, 0); + radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); } if (radeon_connector->edid) { @@ -361,9 +379,9 @@ static int radeon_ddc_dump(struct drm_connector *connector) if (!radeon_connector->ddc_bus) return -1; - radeon_i2c_do_lock(radeon_connector, 1); + radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); - radeon_i2c_do_lock(radeon_connector, 0); + radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); if (edid) { kfree(edid); } @@ -542,6 +560,98 @@ void radeon_compute_pll(struct radeon_pll *pll, *post_div_p = best_post_div; } +void radeon_compute_pll_avivo(struct radeon_pll *pll, + uint64_t freq, + uint32_t *dot_clock_p, + uint32_t *fb_div_p, + uint32_t *frac_fb_div_p, + uint32_t *ref_div_p, + uint32_t *post_div_p, + int flags) +{ + fixed20_12 m, n, frac_n, p, f_vco, f_pclk, best_freq; + fixed20_12 pll_out_max, pll_out_min; + fixed20_12 pll_in_max, pll_in_min; + fixed20_12 reference_freq; + fixed20_12 error, ffreq, a, b; + + pll_out_max.full = rfixed_const(pll->pll_out_max); + pll_out_min.full = rfixed_const(pll->pll_out_min); + pll_in_max.full = rfixed_const(pll->pll_in_max); + pll_in_min.full = rfixed_const(pll->pll_in_min); + reference_freq.full = rfixed_const(pll->reference_freq); + do_div(freq, 10); + ffreq.full = rfixed_const(freq); + error.full = rfixed_const(100 * 100); + + /* max p */ + p.full = rfixed_div(pll_out_max, ffreq); + p.full = rfixed_floor(p); + + /* min m */ + m.full = rfixed_div(reference_freq, pll_in_max); + m.full = rfixed_ceil(m); + + while (1) { + n.full = rfixed_div(ffreq, reference_freq); + n.full = rfixed_mul(n, m); + n.full = rfixed_mul(n, p); + + f_vco.full = rfixed_div(n, m); + f_vco.full = rfixed_mul(f_vco, reference_freq); + + f_pclk.full = rfixed_div(f_vco, p); + + if (f_pclk.full > ffreq.full) + error.full = f_pclk.full - ffreq.full; + else + error.full = ffreq.full - f_pclk.full; + error.full = rfixed_div(error, f_pclk); + a.full = rfixed_const(100 * 100); + error.full = rfixed_mul(error, a); + + a.full = rfixed_mul(m, p); + a.full = rfixed_div(n, a); + best_freq.full = rfixed_mul(reference_freq, a); + + if (rfixed_trunc(error) < 25) + break; + + a.full = rfixed_const(1); + m.full = m.full + a.full; + a.full = rfixed_div(reference_freq, m); + if (a.full >= pll_in_min.full) + continue; + + m.full = rfixed_div(reference_freq, pll_in_max); + m.full = rfixed_ceil(m); + a.full= rfixed_const(1); + p.full = p.full - a.full; + a.full = rfixed_mul(p, ffreq); + if (a.full >= pll_out_min.full) + continue; + else { + DRM_ERROR("Unable to find pll dividers\n"); + break; + } + } + + a.full = rfixed_const(10); + b.full = rfixed_mul(n, a); + + frac_n.full = rfixed_floor(n); + frac_n.full = rfixed_mul(frac_n, a); + frac_n.full = b.full - frac_n.full; + + *dot_clock_p = rfixed_trunc(best_freq); + *fb_div_p = rfixed_trunc(n); + *frac_fb_div_p = rfixed_trunc(frac_n); + *ref_div_p = rfixed_trunc(m); + *post_div_p = rfixed_trunc(p); + + DRM_DEBUG("%u %d.%d, %d, %d\n", *dot_clock_p * 10, *fb_div_p, *frac_fb_div_p, *ref_div_p, *post_div_p); +} + static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) { struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); @@ -642,7 +752,7 @@ int radeon_modeset_create_props(struct radeon_device *rdev) return -ENOMEM; rdev->mode_info.coherent_mode_property->values[0] = 0; - rdev->mode_info.coherent_mode_property->values[0] = 1; + rdev->mode_info.coherent_mode_property->values[1] = 1; } if (!ASIC_IS_AVIVO(rdev)) { @@ -666,7 +776,7 @@ int radeon_modeset_create_props(struct radeon_device *rdev) if (!rdev->mode_info.load_detect_property) return -ENOMEM; rdev->mode_info.load_detect_property->values[0] = 0; - rdev->mode_info.load_detect_property->values[0] = 1; + rdev->mode_info.load_detect_property->values[1] = 1; drm_mode_create_scaling_mode_property(rdev->ddev); @@ -723,6 +833,8 @@ int radeon_modeset_init(struct radeon_device *rdev) if (!ret) { return ret; } + /* initialize hpd */ + radeon_hpd_init(rdev); drm_helper_initial_config(rdev->ddev); return 0; } @@ -730,6 +842,7 @@ int radeon_modeset_init(struct radeon_device *rdev) void radeon_modeset_fini(struct radeon_device *rdev) { if (rdev->mode_info.mode_config_initialized) { + radeon_hpd_fini(rdev); drm_mode_config_cleanup(rdev->ddev); rdev->mode_info.mode_config_initialized = false; } @@ -750,9 +863,17 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, if (encoder->crtc != crtc) continue; if (first) { - radeon_crtc->rmx_type = radeon_encoder->rmx_type; + /* set scaling */ + if (radeon_encoder->rmx_type == RMX_OFF) + radeon_crtc->rmx_type = RMX_OFF; + else if (mode->hdisplay < radeon_encoder->native_mode.hdisplay || + mode->vdisplay < radeon_encoder->native_mode.vdisplay) + radeon_crtc->rmx_type = radeon_encoder->rmx_type; + else + radeon_crtc->rmx_type = RMX_OFF; + /* copy native mode */ memcpy(&radeon_crtc->native_mode, - &radeon_encoder->native_mode, + &radeon_encoder->native_mode, sizeof(struct drm_display_mode)); first = false; } else { diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 7f50fb864af8e6e2804f266d24a60aac1194051e..c5c45e626d7430d90b1ea06623fde8be2608f33c 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -86,6 +86,7 @@ int radeon_benchmarking = 0; int radeon_testing = 0; int radeon_connector_table = 0; int radeon_tv = 1; +int radeon_new_pll = 1; MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); module_param_named(no_wb, radeon_no_wb, int, 0444); @@ -120,6 +121,9 @@ module_param_named(connector_table, radeon_connector_table, int, 0444); MODULE_PARM_DESC(tv, "TV enable (0 = disable)"); module_param_named(tv, radeon_tv, int, 0444); +MODULE_PARM_DESC(new_pll, "Select new PLL code for AVIVO chips"); +module_param_named(new_pll, radeon_new_pll, int, 0444); + static int radeon_suspend(struct drm_device *dev, pm_message_t state) { drm_radeon_private_t *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 350962e0f346f483b02d04d37f48efb3219c2ed0..e13785282a825bbdbae44bb65fa02e3c93b8173b 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -1104,7 +1104,6 @@ extern u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index); # define R600_IT_WAIT_REG_MEM 0x00003C00 # define R600_IT_MEM_WRITE 0x00003D00 # define R600_IT_INDIRECT_BUFFER 0x00003200 -# define R600_IT_CP_INTERRUPT 0x00004000 # define R600_IT_SURFACE_SYNC 0x00004300 # define R600_CB0_DEST_BASE_ENA (1 << 6) # define R600_TC_ACTION_ENA (1 << 23) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index d42bc512d75a8cd1c6a8ae3e91443a67d8121f74..b4f23ec932014367bac60edbac898e0d7f1ae760 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -35,6 +35,51 @@ extern int atom_debug; bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, struct drm_display_mode *mode); +static uint32_t radeon_encoder_clones(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *clone_encoder; + uint32_t index_mask = 0; + int count; + + /* DIG routing gets problematic */ + if (rdev->family >= CHIP_R600) + return index_mask; + /* LVDS/TV are too wacky */ + if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) + return index_mask; + /* DVO requires 2x ppll clocks depending on tmds chip */ + if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) + return index_mask; + + count = -1; + list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) { + struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder); + count++; + + if (clone_encoder == encoder) + continue; + if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT)) + continue; + if (radeon_clone->devices & ATOM_DEVICE_DFP2_SUPPORT) + continue; + else + index_mask |= (1 << count); + } + return index_mask; +} + +void radeon_setup_encoder_clones(struct drm_device *dev) +{ + struct drm_encoder *encoder; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + encoder->possible_clones = radeon_encoder_clones(encoder); + } +} + uint32_t radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t dac) { @@ -163,29 +208,6 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder) return NULL; } -/* used for both atom and legacy */ -void radeon_rmx_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct drm_device *dev = encoder->dev; - struct radeon_device *rdev = dev->dev_private; - struct drm_display_mode *native_mode = &radeon_encoder->native_mode; - - if (mode->hdisplay < native_mode->hdisplay || - mode->vdisplay < native_mode->vdisplay) { - int mode_id = adjusted_mode->base.id; - *adjusted_mode = *native_mode; - if (!ASIC_IS_AVIVO(rdev)) { - adjusted_mode->hdisplay = mode->hdisplay; - adjusted_mode->vdisplay = mode->vdisplay; - } - adjusted_mode->base.id = mode_id; - } -} - - static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -198,14 +220,24 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, radeon_encoder_set_active_device(encoder); drm_mode_set_crtcinfo(adjusted_mode, 0); - if (radeon_encoder->rmx_type != RMX_OFF) - radeon_rmx_mode_fixup(encoder, mode, adjusted_mode); - /* hw bug */ if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2))) adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2; + /* get the native mode for LVDS */ + if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { + struct drm_display_mode *native_mode = &radeon_encoder->native_mode; + int mode_id = adjusted_mode->base.id; + *adjusted_mode = *native_mode; + if (!ASIC_IS_AVIVO(rdev)) { + adjusted_mode->hdisplay = mode->hdisplay; + adjusted_mode->vdisplay = mode->vdisplay; + } + adjusted_mode->base.id = mode_id; + } + + /* get the native mode for TV */ if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) { struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; if (tv_dac) { @@ -218,6 +250,12 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, } } + if (ASIC_IS_DCE3(rdev) && + (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT))) { + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + radeon_dp_set_link_config(connector, mode); + } + return true; } @@ -392,7 +430,7 @@ union lvds_encoder_control { LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2; }; -static void +void atombios_digital_setup(struct drm_encoder *encoder, int action) { struct drm_device *dev = encoder->dev; @@ -522,6 +560,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) { struct drm_connector *connector; struct radeon_connector *radeon_connector; + struct radeon_connector_atom_dig *radeon_dig_connector; connector = radeon_get_connector_for_encoder(encoder); if (!connector) @@ -551,10 +590,10 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) return ATOM_ENCODER_MODE_LVDS; break; case DRM_MODE_CONNECTOR_DisplayPort: - /*if (radeon_output->MonType == MT_DP) - return ATOM_ENCODER_MODE_DP; - else*/ - if (drm_detect_hdmi_monitor(radeon_connector->edid)) + radeon_dig_connector = radeon_connector->con_priv; + if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) + return ATOM_ENCODER_MODE_DP; + else if (drm_detect_hdmi_monitor(radeon_connector->edid)) return ATOM_ENCODER_MODE_HDMI; else return ATOM_ENCODER_MODE_DVI; @@ -573,6 +612,30 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) } } +/* + * DIG Encoder/Transmitter Setup + * + * DCE 3.0/3.1 + * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA. + * Supports up to 3 digital outputs + * - 2 DIG encoder blocks. + * DIG1 can drive UNIPHY link A or link B + * DIG2 can drive UNIPHY link B or LVTMA + * + * DCE 3.2 + * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B). + * Supports up to 5 digital outputs + * - 2 DIG encoder blocks. + * DIG1/2 can drive UNIPHY0/1/2 link A or link B + * + * Routing + * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links) + * Examples: + * crtc0 -> dig2 -> LVTMA links A+B -> TMDS/HDMI + * crtc1 -> dig1 -> UNIPHY0 link B -> DP + * crtc0 -> dig1 -> UNIPHY2 link A -> LVDS + * crtc1 -> dig2 -> UNIPHY1 link B+A -> TMDS/HDMI + */ static void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) { @@ -614,10 +677,17 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) } else { switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); + /* XXX doesn't really matter which dig encoder we pick as long as it's + * not already in use + */ + if (dig_connector->linkb) + index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); + else + index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); num = 1; break; case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + /* Only dig2 encoder can drive LVTMA */ index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); num = 2; break; @@ -652,18 +722,21 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) } } - if (radeon_encoder->pixel_clock > 165000) { - args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B; + args.ucEncoderMode = atombios_get_encoder_mode(encoder); + + if (args.ucEncoderMode == ATOM_ENCODER_MODE_DP) { + if (dig_connector->dp_clock == 270000) + args.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; + args.ucLaneNum = dig_connector->dp_lane_count; + } else if (radeon_encoder->pixel_clock > 165000) args.ucLaneNum = 8; - } else { - if (dig_connector->linkb) - args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; - else - args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; + else args.ucLaneNum = 4; - } - args.ucEncoderMode = atombios_get_encoder_mode(encoder); + if (dig_connector->linkb) + args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; + else + args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); @@ -674,8 +747,8 @@ union dig_transmitter_control { DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; }; -static void -atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action) +void +atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -687,6 +760,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action) struct drm_connector *connector; struct radeon_connector *radeon_connector; struct radeon_connector_atom_dig *dig_connector; + bool is_dp = false; connector = radeon_get_connector_for_encoder(encoder); if (!connector) @@ -704,6 +778,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action) dig_connector = radeon_connector->con_priv; + if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) + is_dp = true; + memset(&args, 0, sizeof(args)); if (ASIC_IS_DCE32(rdev)) @@ -724,17 +801,23 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action) args.v1.ucAction = action; if (action == ATOM_TRANSMITTER_ACTION_INIT) { args.v1.usInitInfo = radeon_connector->connector_object_id; + } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { + args.v1.asMode.ucLaneSel = lane_num; + args.v1.asMode.ucLaneSet = lane_set; } else { - if (radeon_encoder->pixel_clock > 165000) + if (is_dp) + args.v1.usPixelClock = + cpu_to_le16(dig_connector->dp_clock / 10); + else if (radeon_encoder->pixel_clock > 165000) args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); else args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); } if (ASIC_IS_DCE32(rdev)) { - if (radeon_encoder->pixel_clock > 165000) - args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); if (dig->dig_block) args.v2.acConfig.ucEncoderSel = 1; + if (dig_connector->linkb) + args.v2.acConfig.ucLinkSel = 1; switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: @@ -751,7 +834,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action) break; } - if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + if (is_dp) + args.v2.acConfig.fCoherentMode = 1; + else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { if (dig->coherent_mode) args.v2.acConfig.fCoherentMode = 1; } @@ -760,17 +845,20 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action) switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; + /* XXX doesn't really matter which dig encoder we pick as long as it's + * not already in use + */ + if (dig_connector->linkb) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; + else + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; if (rdev->flags & RADEON_IS_IGP) { if (radeon_encoder->pixel_clock > 165000) { - args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | - ATOM_TRANSMITTER_CONFIG_LINKA_B); if (dig_connector->igp_lane_info & 0x3) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; else if (dig_connector->igp_lane_info & 0xc) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; } else { - args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; if (dig_connector->igp_lane_info & 0x1) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; else if (dig_connector->igp_lane_info & 0x2) @@ -780,35 +868,25 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action) else if (dig_connector->igp_lane_info & 0x8) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; } - } else { - if (radeon_encoder->pixel_clock > 165000) - args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | - ATOM_TRANSMITTER_CONFIG_LINKA_B | - ATOM_TRANSMITTER_CONFIG_LANE_0_7); - else { - if (dig_connector->linkb) - args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3; - else - args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; - } } break; case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + /* Only dig2 encoder can drive LVTMA */ args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; - if (radeon_encoder->pixel_clock > 165000) - args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | - ATOM_TRANSMITTER_CONFIG_LINKA_B | - ATOM_TRANSMITTER_CONFIG_LANE_0_7); - else { - if (dig_connector->linkb) - args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3; - else - args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; - } break; } - if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + if (radeon_encoder->pixel_clock > 165000) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; + + if (dig_connector->linkb) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; + else + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; + + if (is_dp) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; + else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { if (dig->coherent_mode) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; } @@ -918,12 +996,16 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) if (is_dig) { switch (mode) { case DRM_MODE_DPMS_ON: - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); + { + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + dp_link_train(encoder, connector); + } break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); break; } } else { @@ -1025,13 +1107,33 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; else args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; - } else - args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; + } else { + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + struct radeon_connector_atom_dig *dig_connector; + + connector = radeon_get_connector_for_encoder(encoder); + if (!connector) + return; + radeon_connector = to_radeon_connector(connector); + if (!radeon_connector->con_priv) + return; + dig_connector = radeon_connector->con_priv; + + /* XXX doesn't really matter which dig encoder we pick as long as it's + * not already in use + */ + if (dig_connector->linkb) + args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; + else + args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; + } break; case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; break; case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + /* Only dig2 encoder can drive LVTMA */ args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; break; case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: @@ -1104,11 +1206,14 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); - if (radeon_encoder->enc_priv) { - struct radeon_encoder_atom_dig *dig; + if (radeon_encoder->active_device & + (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { + if (radeon_encoder->enc_priv) { + struct radeon_encoder_atom_dig *dig; - dig = radeon_encoder->enc_priv; - dig->dig_block = radeon_crtc->crtc_id; + dig = radeon_encoder->enc_priv; + dig->dig_block = radeon_crtc->crtc_id; + } } radeon_encoder->pixel_clock = adjusted_mode->clock; @@ -1134,14 +1239,14 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: /* disable the encoder and transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); atombios_dig_encoder_setup(encoder, ATOM_DISABLE); /* setup and enable the encoder and transmitter */ atombios_dig_encoder_setup(encoder, ATOM_ENABLE); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); break; case ENCODER_OBJECT_ID_INTERNAL_DDI: atombios_ddia_setup(encoder, ATOM_ENABLE); @@ -1354,7 +1459,6 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su encoder->possible_crtcs = 0x1; else encoder->possible_crtcs = 0x3; - encoder->possible_clones = 0; radeon_encoder->enc_priv = NULL; diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index d10eb43645c89e85f4a2675aacb1ee94bf27560c..3ba213d1b06c28a96d81b3f3fc38d21a4cbd660d 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -140,7 +140,7 @@ int radeonfb_create(struct drm_device *dev, struct radeon_framebuffer *rfb; struct drm_mode_fb_cmd mode_cmd; struct drm_gem_object *gobj = NULL; - struct radeon_object *robj = NULL; + struct radeon_bo *rbo = NULL; struct device *device = &rdev->pdev->dev; int size, aligned_size, ret; u64 fb_gpuaddr; @@ -168,14 +168,14 @@ int radeonfb_create(struct drm_device *dev, ret = radeon_gem_object_create(rdev, aligned_size, 0, RADEON_GEM_DOMAIN_VRAM, false, ttm_bo_type_kernel, - false, &gobj); + &gobj); if (ret) { printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n", surface_width, surface_height); ret = -ENOMEM; goto out; } - robj = gobj->driver_private; + rbo = gobj->driver_private; if (fb_tiled) tiling_flags = RADEON_TILING_MACRO; @@ -192,8 +192,13 @@ int radeonfb_create(struct drm_device *dev, } #endif - if (tiling_flags) - radeon_object_set_tiling_flags(robj, tiling_flags | RADEON_TILING_SURFACE, mode_cmd.pitch); + if (tiling_flags) { + ret = radeon_bo_set_tiling_flags(rbo, + tiling_flags | RADEON_TILING_SURFACE, + mode_cmd.pitch); + if (ret) + dev_err(rdev->dev, "FB failed to set tiling flags\n"); + } mutex_lock(&rdev->ddev->struct_mutex); fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj); if (fb == NULL) { @@ -201,10 +206,19 @@ int radeonfb_create(struct drm_device *dev, ret = -ENOMEM; goto out_unref; } - ret = radeon_object_pin(robj, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr); + ret = radeon_bo_reserve(rbo, false); + if (unlikely(ret != 0)) + goto out_unref; + ret = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr); + if (ret) { + radeon_bo_unreserve(rbo); + goto out_unref; + } + if (fb_tiled) + radeon_bo_check_tiling(rbo, 0, 0); + ret = radeon_bo_kmap(rbo, &fbptr); + radeon_bo_unreserve(rbo); if (ret) { - printk(KERN_ERR "failed to pin framebuffer\n"); - ret = -ENOMEM; goto out_unref; } @@ -213,7 +227,7 @@ int radeonfb_create(struct drm_device *dev, *fb_p = fb; rfb = to_radeon_framebuffer(fb); rdev->fbdev_rfb = rfb; - rdev->fbdev_robj = robj; + rdev->fbdev_rbo = rbo; info = framebuffer_alloc(sizeof(struct radeon_fb_device), device); if (info == NULL) { @@ -234,15 +248,7 @@ int radeonfb_create(struct drm_device *dev, if (ret) goto out_unref; - if (fb_tiled) - radeon_object_check_tiling(robj, 0, 0); - - ret = radeon_object_kmap(robj, &fbptr); - if (ret) { - goto out_unref; - } - - memset_io(fbptr, 0, aligned_size); + memset_io(fbptr, 0xff, aligned_size); strcpy(info->fix.id, "radeondrmfb"); @@ -288,8 +294,12 @@ int radeonfb_create(struct drm_device *dev, return 0; out_unref: - if (robj) { - radeon_object_kunmap(robj); + if (rbo) { + ret = radeon_bo_reserve(rbo, false); + if (likely(ret == 0)) { + radeon_bo_kunmap(rbo); + radeon_bo_unreserve(rbo); + } } if (fb && ret) { list_del(&fb->filp_head); @@ -321,14 +331,22 @@ int radeon_parse_options(char *options) int radeonfb_probe(struct drm_device *dev) { - return drm_fb_helper_single_fb_probe(dev, 32, &radeonfb_create); + struct radeon_device *rdev = dev->dev_private; + int bpp_sel = 32; + + /* select 8 bpp console on RN50 or 16MB cards */ + if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024)) + bpp_sel = 8; + + return drm_fb_helper_single_fb_probe(dev, bpp_sel, &radeonfb_create); } int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) { struct fb_info *info; struct radeon_framebuffer *rfb = to_radeon_framebuffer(fb); - struct radeon_object *robj; + struct radeon_bo *rbo; + int r; if (!fb) { return -EINVAL; @@ -336,10 +354,14 @@ int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) info = fb->fbdev; if (info) { struct radeon_fb_device *rfbdev = info->par; - robj = rfb->obj->driver_private; + rbo = rfb->obj->driver_private; unregister_framebuffer(info); - radeon_object_kunmap(robj); - radeon_object_unpin(robj); + r = radeon_bo_reserve(rbo, false); + if (likely(r == 0)) { + radeon_bo_kunmap(rbo); + radeon_bo_unpin(rbo); + radeon_bo_unreserve(rbo); + } drm_fb_helper_free(&rfbdev->helper); framebuffer_release(info); } diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 3beb26d747196b74700c08e2cb51a324868581bf..cb4cd97ae39fa811d9bf68912f709b47270fe0d1 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -168,37 +168,6 @@ bool radeon_fence_signaled(struct radeon_fence *fence) return signaled; } -int r600_fence_wait(struct radeon_fence *fence, bool intr, bool lazy) -{ - struct radeon_device *rdev; - int ret = 0; - - rdev = fence->rdev; - - __set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); - - while (1) { - if (radeon_fence_signaled(fence)) - break; - - if (time_after_eq(jiffies, fence->timeout)) { - ret = -EBUSY; - break; - } - - if (lazy) - schedule_timeout(1); - - if (intr && signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - } - __set_current_state(TASK_RUNNING); - return ret; -} - - int radeon_fence_wait(struct radeon_fence *fence, bool intr) { struct radeon_device *rdev; @@ -216,13 +185,6 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr) return 0; } - if (rdev->family >= CHIP_R600) { - r = r600_fence_wait(fence, intr, 0); - if (r == -ERESTARTSYS) - return -EBUSY; - return r; - } - retry: cur_jiffies = jiffies; timeout = HZ / 100; @@ -231,14 +193,17 @@ retry: } if (intr) { + radeon_irq_kms_sw_irq_get(rdev); r = wait_event_interruptible_timeout(rdev->fence_drv.queue, radeon_fence_signaled(fence), timeout); - if (unlikely(r == -ERESTARTSYS)) { - return -EBUSY; - } + radeon_irq_kms_sw_irq_put(rdev); + if (unlikely(r < 0)) + return r; } else { + radeon_irq_kms_sw_irq_get(rdev); r = wait_event_timeout(rdev->fence_drv.queue, radeon_fence_signaled(fence), timeout); + radeon_irq_kms_sw_irq_put(rdev); } if (unlikely(!radeon_fence_signaled(fence))) { if (unlikely(r == 0)) { diff --git a/drivers/gpu/drm/radeon/radeon_fixed.h b/drivers/gpu/drm/radeon/radeon_fixed.h index 90187d1738479c26c32214cb809c184c2c9b1187..3d4d84e078ac14d1cd40c4b3b74250b9faeb5ede 100644 --- a/drivers/gpu/drm/radeon/radeon_fixed.h +++ b/drivers/gpu/drm/radeon/radeon_fixed.h @@ -38,6 +38,23 @@ typedef union rfixed { #define fixed_init_half(A) { .full = rfixed_const_half((A)) } #define rfixed_trunc(A) ((A).full >> 12) +static inline u32 rfixed_floor(fixed20_12 A) +{ + u32 non_frac = rfixed_trunc(A); + + return rfixed_const(non_frac); +} + +static inline u32 rfixed_ceil(fixed20_12 A) +{ + u32 non_frac = rfixed_trunc(A); + + if (A.full > rfixed_const(non_frac)) + return rfixed_const(non_frac + 1); + else + return rfixed_const(non_frac); +} + static inline u32 rfixed_div(fixed20_12 A, fixed20_12 B) { u64 tmp = ((u64)A.full << 13); diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index a68d7566178cb2b0e0469a97d06a7806d73ecfe2..e73d56e83fa68760e6a14dd70d74fcd1473ed0ea 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -78,11 +78,9 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev) int r; if (rdev->gart.table.vram.robj == NULL) { - r = radeon_object_create(rdev, NULL, - rdev->gart.table_size, - true, - RADEON_GEM_DOMAIN_VRAM, - false, &rdev->gart.table.vram.robj); + r = radeon_bo_create(rdev, NULL, rdev->gart.table_size, + true, RADEON_GEM_DOMAIN_VRAM, + &rdev->gart.table.vram.robj); if (r) { return r; } @@ -95,32 +93,38 @@ int radeon_gart_table_vram_pin(struct radeon_device *rdev) uint64_t gpu_addr; int r; - r = radeon_object_pin(rdev->gart.table.vram.robj, - RADEON_GEM_DOMAIN_VRAM, &gpu_addr); - if (r) { - radeon_object_unref(&rdev->gart.table.vram.robj); + r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); + if (unlikely(r != 0)) return r; - } - r = radeon_object_kmap(rdev->gart.table.vram.robj, - (void **)&rdev->gart.table.vram.ptr); + r = radeon_bo_pin(rdev->gart.table.vram.robj, + RADEON_GEM_DOMAIN_VRAM, &gpu_addr); if (r) { - radeon_object_unpin(rdev->gart.table.vram.robj); - radeon_object_unref(&rdev->gart.table.vram.robj); - DRM_ERROR("radeon: failed to map gart vram table.\n"); + radeon_bo_unreserve(rdev->gart.table.vram.robj); return r; } + r = radeon_bo_kmap(rdev->gart.table.vram.robj, + (void **)&rdev->gart.table.vram.ptr); + if (r) + radeon_bo_unpin(rdev->gart.table.vram.robj); + radeon_bo_unreserve(rdev->gart.table.vram.robj); rdev->gart.table_addr = gpu_addr; - return 0; + return r; } void radeon_gart_table_vram_free(struct radeon_device *rdev) { + int r; + if (rdev->gart.table.vram.robj == NULL) { return; } - radeon_object_kunmap(rdev->gart.table.vram.robj); - radeon_object_unpin(rdev->gart.table.vram.robj); - radeon_object_unref(&rdev->gart.table.vram.robj); + r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); + if (likely(r == 0)) { + radeon_bo_kunmap(rdev->gart.table.vram.robj); + radeon_bo_unpin(rdev->gart.table.vram.robj); + radeon_bo_unreserve(rdev->gart.table.vram.robj); + } + radeon_bo_unref(&rdev->gart.table.vram.robj); } diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index d880edf254dbad63a73e99ee7c05de40757e9ecc..2944486871b04c0968a88da9e298d487c5ca9f7e 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -38,22 +38,21 @@ int radeon_gem_object_init(struct drm_gem_object *obj) void radeon_gem_object_free(struct drm_gem_object *gobj) { - struct radeon_object *robj = gobj->driver_private; + struct radeon_bo *robj = gobj->driver_private; gobj->driver_private = NULL; if (robj) { - radeon_object_unref(&robj); + radeon_bo_unref(&robj); } } int radeon_gem_object_create(struct radeon_device *rdev, int size, - int alignment, int initial_domain, - bool discardable, bool kernel, - bool interruptible, - struct drm_gem_object **obj) + int alignment, int initial_domain, + bool discardable, bool kernel, + struct drm_gem_object **obj) { struct drm_gem_object *gobj; - struct radeon_object *robj; + struct radeon_bo *robj; int r; *obj = NULL; @@ -65,8 +64,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size, if (alignment < PAGE_SIZE) { alignment = PAGE_SIZE; } - r = radeon_object_create(rdev, gobj, size, kernel, initial_domain, - interruptible, &robj); + r = radeon_bo_create(rdev, gobj, size, kernel, initial_domain, &robj); if (r) { DRM_ERROR("Failed to allocate GEM object (%d, %d, %u)\n", size, initial_domain, alignment); @@ -83,33 +81,33 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size, int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain, uint64_t *gpu_addr) { - struct radeon_object *robj = obj->driver_private; - uint32_t flags; + struct radeon_bo *robj = obj->driver_private; + int r; - switch (pin_domain) { - case RADEON_GEM_DOMAIN_VRAM: - flags = TTM_PL_FLAG_VRAM; - break; - case RADEON_GEM_DOMAIN_GTT: - flags = TTM_PL_FLAG_TT; - break; - default: - flags = TTM_PL_FLAG_SYSTEM; - break; - } - return radeon_object_pin(robj, flags, gpu_addr); + r = radeon_bo_reserve(robj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(robj, pin_domain, gpu_addr); + radeon_bo_unreserve(robj); + return r; } void radeon_gem_object_unpin(struct drm_gem_object *obj) { - struct radeon_object *robj = obj->driver_private; - radeon_object_unpin(robj); + struct radeon_bo *robj = obj->driver_private; + int r; + + r = radeon_bo_reserve(robj, false); + if (likely(r == 0)) { + radeon_bo_unpin(robj); + radeon_bo_unreserve(robj); + } } int radeon_gem_set_domain(struct drm_gem_object *gobj, uint32_t rdomain, uint32_t wdomain) { - struct radeon_object *robj; + struct radeon_bo *robj; uint32_t domain; int r; @@ -127,11 +125,12 @@ int radeon_gem_set_domain(struct drm_gem_object *gobj, } if (domain == RADEON_GEM_DOMAIN_CPU) { /* Asking for cpu access wait for object idle */ - r = radeon_object_wait(robj); + r = radeon_bo_wait(robj, NULL, false); if (r) { printk(KERN_ERR "Failed to wait for object !\n"); return r; } + radeon_hdp_flush(robj->rdev); } return 0; } @@ -144,7 +143,7 @@ int radeon_gem_init(struct radeon_device *rdev) void radeon_gem_fini(struct radeon_device *rdev) { - radeon_object_force_delete(rdev); + radeon_bo_force_delete(rdev); } @@ -158,9 +157,13 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, struct drm_radeon_gem_info *args = data; args->vram_size = rdev->mc.real_vram_size; - /* FIXME: report somethings that makes sense */ - args->vram_visible = rdev->mc.real_vram_size - (4 * 1024 * 1024); - args->gart_size = rdev->mc.gtt_size; + args->vram_visible = rdev->mc.real_vram_size; + if (rdev->stollen_vga_memory) + args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory); + if (rdev->fbdev_rbo) + args->vram_visible -= radeon_bo_size(rdev->fbdev_rbo); + args->gart_size = rdev->mc.gtt_size - rdev->cp.ring_size - 4096 - + RADEON_IB_POOL_SIZE*64*1024; return 0; } @@ -192,8 +195,8 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, /* create a gem object to contain this object in */ args->size = roundup(args->size, PAGE_SIZE); r = radeon_gem_object_create(rdev, args->size, args->alignment, - args->initial_domain, false, - false, true, &gobj); + args->initial_domain, false, + false, &gobj); if (r) { return r; } @@ -218,7 +221,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, * just validate the BO into a certain domain */ struct drm_radeon_gem_set_domain *args = data; struct drm_gem_object *gobj; - struct radeon_object *robj; + struct radeon_bo *robj; int r; /* for now if someone requests domain CPU - @@ -244,19 +247,18 @@ int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, { struct drm_radeon_gem_mmap *args = data; struct drm_gem_object *gobj; - struct radeon_object *robj; - int r; + struct radeon_bo *robj; gobj = drm_gem_object_lookup(dev, filp, args->handle); if (gobj == NULL) { return -EINVAL; } robj = gobj->driver_private; - r = radeon_object_mmap(robj, &args->addr_ptr); + args->addr_ptr = radeon_bo_mmap_offset(robj); mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(gobj); mutex_unlock(&dev->struct_mutex); - return r; + return 0; } int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, @@ -264,16 +266,16 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, { struct drm_radeon_gem_busy *args = data; struct drm_gem_object *gobj; - struct radeon_object *robj; + struct radeon_bo *robj; int r; - uint32_t cur_placement; + uint32_t cur_placement = 0; gobj = drm_gem_object_lookup(dev, filp, args->handle); if (gobj == NULL) { return -EINVAL; } robj = gobj->driver_private; - r = radeon_object_busy_domain(robj, &cur_placement); + r = radeon_bo_wait(robj, &cur_placement, true); switch (cur_placement) { case TTM_PL_VRAM: args->domain = RADEON_GEM_DOMAIN_VRAM; @@ -297,7 +299,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, { struct drm_radeon_gem_wait_idle *args = data; struct drm_gem_object *gobj; - struct radeon_object *robj; + struct radeon_bo *robj; int r; gobj = drm_gem_object_lookup(dev, filp, args->handle); @@ -305,10 +307,11 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, return -EINVAL; } robj = gobj->driver_private; - r = radeon_object_wait(robj); + r = radeon_bo_wait(robj, NULL, false); mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(gobj); mutex_unlock(&dev->struct_mutex); + radeon_hdp_flush(robj->rdev); return r; } @@ -317,7 +320,7 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, { struct drm_radeon_gem_set_tiling *args = data; struct drm_gem_object *gobj; - struct radeon_object *robj; + struct radeon_bo *robj; int r = 0; DRM_DEBUG("%d \n", args->handle); @@ -325,7 +328,7 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, if (gobj == NULL) return -EINVAL; robj = gobj->driver_private; - radeon_object_set_tiling_flags(robj, args->tiling_flags, args->pitch); + r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch); mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(gobj); mutex_unlock(&dev->struct_mutex); @@ -337,16 +340,19 @@ int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, { struct drm_radeon_gem_get_tiling *args = data; struct drm_gem_object *gobj; - struct radeon_object *robj; + struct radeon_bo *rbo; int r = 0; DRM_DEBUG("\n"); gobj = drm_gem_object_lookup(dev, filp, args->handle); if (gobj == NULL) return -EINVAL; - robj = gobj->driver_private; - radeon_object_get_tiling_flags(robj, &args->tiling_flags, - &args->pitch); + rbo = gobj->driver_private; + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + radeon_bo_get_tiling_flags(rbo, &args->tiling_flags, &args->pitch); + radeon_bo_unreserve(rbo); mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(gobj); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index dd438d32e5c050464bedf31062d19eae67498c78..da3da1e89d002eff60cbd5d7df5ea84e94648a94 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -59,35 +59,43 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector) } -void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state) +void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state) { - struct radeon_device *rdev = radeon_connector->base.dev->dev_private; + struct radeon_device *rdev = i2c->dev->dev_private; + struct radeon_i2c_bus_rec *rec = &i2c->rec; uint32_t temp; - struct radeon_i2c_bus_rec *rec = &radeon_connector->ddc_bus->rec; /* RV410 appears to have a bug where the hw i2c in reset * holds the i2c port in a bad state - switch hw i2c away before * doing DDC - do this for all r200s/r300s/r400s for safety sake */ - if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) { - if (rec->a_clk_reg == RADEON_GPIO_MONID) { - WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST | - R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1))); - } else { - WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST | - R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3))); + if (rec->hw_capable) { + if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) { + if (rec->a_clk_reg == RADEON_GPIO_MONID) { + WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST | + R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1))); + } else { + WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST | + R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3))); + } } } - if (lock_state) { - temp = RREG32(rec->a_clk_reg); - temp &= ~(rec->a_clk_mask); - WREG32(rec->a_clk_reg, temp); - - temp = RREG32(rec->a_data_reg); - temp &= ~(rec->a_data_mask); - WREG32(rec->a_data_reg, temp); - } + /* clear the output pin values */ + temp = RREG32(rec->a_clk_reg) & ~rec->a_clk_mask; + WREG32(rec->a_clk_reg, temp); + + temp = RREG32(rec->a_data_reg) & ~rec->a_data_mask; + WREG32(rec->a_data_reg, temp); + + /* set the pins to input */ + temp = RREG32(rec->en_clk_reg) & ~rec->en_clk_mask; + WREG32(rec->en_clk_reg, temp); + + temp = RREG32(rec->en_data_reg) & ~rec->en_data_mask; + WREG32(rec->en_data_reg, temp); + + /* mask the gpio pins for software use */ temp = RREG32(rec->mask_clk_reg); if (lock_state) temp |= rec->mask_clk_mask; @@ -112,8 +120,9 @@ static int get_clock(void *i2c_priv) struct radeon_i2c_bus_rec *rec = &i2c->rec; uint32_t val; - val = RREG32(rec->get_clk_reg); - val &= rec->get_clk_mask; + /* read the value off the pin */ + val = RREG32(rec->y_clk_reg); + val &= rec->y_clk_mask; return (val != 0); } @@ -126,8 +135,10 @@ static int get_data(void *i2c_priv) struct radeon_i2c_bus_rec *rec = &i2c->rec; uint32_t val; - val = RREG32(rec->get_data_reg); - val &= rec->get_data_mask; + /* read the value off the pin */ + val = RREG32(rec->y_data_reg); + val &= rec->y_data_mask; + return (val != 0); } @@ -138,9 +149,10 @@ static void set_clock(void *i2c_priv, int clock) struct radeon_i2c_bus_rec *rec = &i2c->rec; uint32_t val; - val = RREG32(rec->put_clk_reg) & (uint32_t)~(rec->put_clk_mask); - val |= clock ? 0 : rec->put_clk_mask; - WREG32(rec->put_clk_reg, val); + /* set pin direction */ + val = RREG32(rec->en_clk_reg) & ~rec->en_clk_mask; + val |= clock ? 0 : rec->en_clk_mask; + WREG32(rec->en_clk_reg, val); } static void set_data(void *i2c_priv, int data) @@ -150,14 +162,15 @@ static void set_data(void *i2c_priv, int data) struct radeon_i2c_bus_rec *rec = &i2c->rec; uint32_t val; - val = RREG32(rec->put_data_reg) & (uint32_t)~(rec->put_data_mask); - val |= data ? 0 : rec->put_data_mask; - WREG32(rec->put_data_reg, val); + /* set pin direction */ + val = RREG32(rec->en_data_reg) & ~rec->en_data_mask; + val |= data ? 0 : rec->en_data_mask; + WREG32(rec->en_data_reg, val); } struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, - struct radeon_i2c_bus_rec *rec, - const char *name) + struct radeon_i2c_bus_rec *rec, + const char *name) { struct radeon_i2c_chan *i2c; int ret; @@ -167,20 +180,19 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, return NULL; i2c->adapter.owner = THIS_MODULE; - i2c->adapter.algo_data = &i2c->algo; i2c->dev = dev; - i2c->algo.setsda = set_data; - i2c->algo.setscl = set_clock; - i2c->algo.getsda = get_data; - i2c->algo.getscl = get_clock; - i2c->algo.udelay = 20; + i2c_set_adapdata(&i2c->adapter, i2c); + i2c->adapter.algo_data = &i2c->algo.bit; + i2c->algo.bit.setsda = set_data; + i2c->algo.bit.setscl = set_clock; + i2c->algo.bit.getsda = get_data; + i2c->algo.bit.getscl = get_clock; + i2c->algo.bit.udelay = 20; /* vesa says 2.2 ms is enough, 1 jiffy doesn't seem to always * make this, 2 jiffies is a lot more reliable */ - i2c->algo.timeout = 2; - i2c->algo.data = i2c; + i2c->algo.bit.timeout = 2; + i2c->algo.bit.data = i2c; i2c->rec = *rec; - i2c_set_adapdata(&i2c->adapter, i2c); - ret = i2c_bit_add_bus(&i2c->adapter); if (ret) { DRM_INFO("Failed to register i2c %s\n", name); @@ -194,6 +206,38 @@ out_free: } +struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, + struct radeon_i2c_bus_rec *rec, + const char *name) +{ + struct radeon_i2c_chan *i2c; + int ret; + + i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL); + if (i2c == NULL) + return NULL; + + i2c->rec = *rec; + i2c->adapter.owner = THIS_MODULE; + i2c->dev = dev; + i2c_set_adapdata(&i2c->adapter, i2c); + i2c->adapter.algo_data = &i2c->algo.dp; + i2c->algo.dp.aux_ch = radeon_dp_i2c_aux_ch; + i2c->algo.dp.address = 0; + ret = i2c_dp_aux_add_bus(&i2c->adapter); + if (ret) { + DRM_INFO("Failed to register i2c %s\n", name); + goto out_free; + } + + return i2c; +out_free: + kfree(i2c); + return NULL; + +} + + void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) { if (!i2c) @@ -207,3 +251,59 @@ struct drm_encoder *radeon_best_encoder(struct drm_connector *connector) { return NULL; } + +void radeon_i2c_sw_get_byte(struct radeon_i2c_chan *i2c_bus, + u8 slave_addr, + u8 addr, + u8 *val) +{ + u8 out_buf[2]; + u8 in_buf[2]; + struct i2c_msg msgs[] = { + { + .addr = slave_addr, + .flags = 0, + .len = 1, + .buf = out_buf, + }, + { + .addr = slave_addr, + .flags = I2C_M_RD, + .len = 1, + .buf = in_buf, + } + }; + + out_buf[0] = addr; + out_buf[1] = 0; + + if (i2c_transfer(&i2c_bus->adapter, msgs, 2) == 2) { + *val = in_buf[0]; + DRM_DEBUG("val = 0x%02x\n", *val); + } else { + DRM_ERROR("i2c 0x%02x 0x%02x read failed\n", + addr, *val); + } +} + +void radeon_i2c_sw_put_byte(struct radeon_i2c_chan *i2c_bus, + u8 slave_addr, + u8 addr, + u8 val) +{ + uint8_t out_buf[2]; + struct i2c_msg msg = { + .addr = slave_addr, + .flags = 0, + .len = 2, + .buf = out_buf, + }; + + out_buf[0] = addr; + out_buf[1] = val; + + if (i2c_transfer(&i2c_bus->adapter, &msg, 1) != 1) + DRM_ERROR("i2c 0x%02x 0x%02x write failed\n", + addr, val); +} + diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index a0fe6232dcb6fc8b9ab803ce4b5b7111fae435de..9223296fe37be087253481647ca32c3f3e657061 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -39,11 +39,32 @@ irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) return radeon_irq_process(rdev); } +/* + * Handle hotplug events outside the interrupt handler proper. + */ +static void radeon_hotplug_work_func(struct work_struct *work) +{ + struct radeon_device *rdev = container_of(work, struct radeon_device, + hotplug_work); + struct drm_device *dev = rdev->ddev; + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector *connector; + + if (mode_config->num_connector) { + list_for_each_entry(connector, &mode_config->connector_list, head) + radeon_connector_hotplug(connector); + } + /* Just fire off a uevent and let userspace tell us what to do */ + drm_sysfs_hotplug_event(dev); +} + void radeon_driver_irq_preinstall_kms(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; unsigned i; + INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); + /* Disable *all* interrupts */ rdev->irq.sw_int = false; for (i = 0; i < 2; i++) { @@ -87,17 +108,25 @@ int radeon_irq_kms_init(struct radeon_device *rdev) if (rdev->flags & RADEON_SINGLE_CRTC) num_crtc = 1; - + spin_lock_init(&rdev->irq.sw_lock); r = drm_vblank_init(rdev->ddev, num_crtc); if (r) { return r; } /* enable msi */ rdev->msi_enabled = 0; - if (rdev->family >= CHIP_RV380) { + /* MSIs don't seem to work on my rs780; + * not sure about rs880 or other rs780s. + * Needs more investigation. + */ + if ((rdev->family >= CHIP_RV380) && + (rdev->family != CHIP_RS780) && + (rdev->family != CHIP_RS880)) { int ret = pci_enable_msi(rdev->pdev); - if (!ret) + if (!ret) { rdev->msi_enabled = 1; + DRM_INFO("radeon: using MSI.\n"); + } } drm_irq_install(rdev->ddev); rdev->irq.installed = true; @@ -114,3 +143,29 @@ void radeon_irq_kms_fini(struct radeon_device *rdev) pci_disable_msi(rdev->pdev); } } + +void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev) +{ + unsigned long irqflags; + + spin_lock_irqsave(&rdev->irq.sw_lock, irqflags); + if (rdev->ddev->irq_enabled && (++rdev->irq.sw_refcount == 1)) { + rdev->irq.sw_int = true; + radeon_irq_set(rdev); + } + spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); +} + +void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev) +{ + unsigned long irqflags; + + spin_lock_irqsave(&rdev->irq.sw_lock, irqflags); + BUG_ON(rdev->ddev->irq_enabled && rdev->irq.sw_refcount <= 0); + if (rdev->ddev->irq_enabled && (--rdev->irq.sw_refcount == 0)) { + rdev->irq.sw_int = false; + radeon_irq_set(rdev); + } + spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); +} + diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index ba128621057a64eb0801e56fae4093dfb51f46f2..f23b05606eb53f6fbe2f79de24f9613e318683ce 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -30,10 +30,19 @@ #include "radeon.h" #include "radeon_drm.h" +int radeon_driver_unload_kms(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + + if (rdev == NULL) + return 0; + radeon_modeset_fini(rdev); + radeon_device_fini(rdev); + kfree(rdev); + dev->dev_private = NULL; + return 0; +} -/* - * Driver load/unload - */ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) { struct radeon_device *rdev; @@ -62,31 +71,20 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) */ r = radeon_device_init(rdev, dev, dev->pdev, flags); if (r) { - DRM_ERROR("Fatal error while trying to initialize radeon.\n"); - return r; + dev_err(&dev->pdev->dev, "Fatal error during GPU init\n"); + goto out; } /* Again modeset_init should fail only on fatal error * otherwise it should provide enough functionalities * for shadowfb to run */ r = radeon_modeset_init(rdev); - if (r) { - return r; - } - return 0; -} - -int radeon_driver_unload_kms(struct drm_device *dev) -{ - struct radeon_device *rdev = dev->dev_private; - - if (rdev == NULL) - return 0; - radeon_modeset_fini(rdev); - radeon_device_fini(rdev); - kfree(rdev); - dev->dev_private = NULL; - return 0; + if (r) + dev_err(&dev->pdev->dev, "Fatal error during modeset init\n"); +out: + if (r) + radeon_driver_unload_kms(dev); + return r; } diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 8d0b7aa87fa4da95ee94415460641e974686e1b0..b82ede98e152d114b6f5fe8b015e28785b9d3092 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -30,6 +30,18 @@ #include "radeon.h" #include "atom.h" +static void radeon_overscan_setup(struct drm_crtc *crtc, + struct drm_display_mode *mode) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + + WREG32(RADEON_OVR_CLR + radeon_crtc->crtc_offset, 0); + WREG32(RADEON_OVR_WID_LEFT_RIGHT + radeon_crtc->crtc_offset, 0); + WREG32(RADEON_OVR_WID_TOP_BOTTOM + radeon_crtc->crtc_offset, 0); +} + static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -292,8 +304,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) uint32_t mask; if (radeon_crtc->crtc_id) - mask = (RADEON_CRTC2_EN | - RADEON_CRTC2_DISP_DIS | + mask = (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_REQ_EN_B); @@ -305,7 +316,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) switch (mode) { case DRM_MODE_DPMS_ON: if (radeon_crtc->crtc_id) - WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~mask); + WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~(RADEON_CRTC2_EN | mask)); else { WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN | RADEON_CRTC_DISP_REQ_EN_B)); @@ -319,7 +330,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_OFF: drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); if (radeon_crtc->crtc_id) - WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~mask); + WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~(RADEON_CRTC2_EN | mask)); else { WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN | RADEON_CRTC_DISP_REQ_EN_B)); @@ -400,14 +411,21 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct radeon_framebuffer *radeon_fb; struct drm_gem_object *obj; + struct radeon_bo *rbo; uint64_t base; uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0; uint32_t crtc_pitch, pitch_pixels; uint32_t tiling_flags; int format; uint32_t gen_cntl_reg, gen_cntl_val; + int r; DRM_DEBUG("\n"); + /* no fb bound */ + if (!crtc->fb) { + DRM_DEBUG("No FB bound\n"); + return 0; + } radeon_fb = to_radeon_framebuffer(crtc->fb); @@ -431,10 +449,22 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, return false; } + /* Pin framebuffer & get tilling informations */ obj = radeon_fb->obj; - if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &base)) { + rbo = obj->driver_private; + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &base); + if (unlikely(r != 0)) { + radeon_bo_unreserve(rbo); return -EINVAL; } + radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); + radeon_bo_unreserve(rbo); + if (tiling_flags & RADEON_TILING_MICRO) + DRM_ERROR("trying to scanout microtiled buffer\n"); + /* if scanout was in GTT this really wouldn't work */ /* crtc offset is from display base addr not FB location */ radeon_crtc->legacy_display_base_addr = rdev->mc.vram_location; @@ -449,10 +479,6 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, (crtc->fb->bits_per_pixel * 8)); crtc_pitch |= crtc_pitch << 16; - radeon_object_get_tiling_flags(obj->driver_private, - &tiling_flags, NULL); - if (tiling_flags & RADEON_TILING_MICRO) - DRM_ERROR("trying to scanout microtiled buffer\n"); if (tiling_flags & RADEON_TILING_MACRO) { if (ASIC_IS_R300(rdev)) @@ -530,7 +556,12 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, if (old_fb && old_fb != crtc->fb) { radeon_fb = to_radeon_framebuffer(old_fb); - radeon_gem_object_unpin(radeon_fb->obj); + rbo = radeon_fb->obj->driver_private; + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + radeon_bo_unpin(rbo); + radeon_bo_unreserve(rbo); } /* Bytes per pixel may have changed */ @@ -642,12 +673,8 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod uint32_t crtc2_gen_cntl; uint32_t disp2_merge_cntl; - /* check to see if TV DAC is enabled for another crtc and keep it enabled */ - if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_CRT2_ON) - crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON; - else - crtc2_gen_cntl = 0; - + /* if TV DAC is enabled for another crtc and keep it enabled */ + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0x00718080; crtc2_gen_cntl |= ((format << 8) | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS @@ -676,7 +703,8 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod uint32_t crtc_ext_cntl; uint32_t disp_merge_cntl; - crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN + crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0x00718000; + crtc_gen_cntl |= (RADEON_CRTC_EXT_DISP_EN | (format << 8) | RADEON_CRTC_DISP_REQ_EN_B | ((mode->flags & DRM_MODE_FLAG_DBLSCAN) @@ -779,15 +807,17 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv; - if (lvds) { - if (lvds->use_bios_dividers) { - pll_ref_div = lvds->panel_ref_divider; - pll_fb_post_div = (lvds->panel_fb_divider | - (lvds->panel_post_divider << 16)); - htotal_cntl = 0; - use_bios_divs = true; + if (!rdev->is_atom_bios) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv; + if (lvds) { + if (lvds->use_bios_dividers) { + pll_ref_div = lvds->panel_ref_divider; + pll_fb_post_div = (lvds->panel_fb_divider | + (lvds->panel_post_divider << 16)); + htotal_cntl = 0; + use_bios_divs = true; + } } } pll_flags |= RADEON_PLL_USE_REF_DIV; @@ -1027,6 +1057,7 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc, radeon_crtc_set_base(crtc, x, y, old_fb); radeon_set_crtc_timing(crtc, adjusted_mode); radeon_set_pll(crtc, adjusted_mode); + radeon_overscan_setup(crtc, adjusted_mode); if (radeon_crtc->crtc_id == 0) { radeon_legacy_rmx_mode_set(crtc, mode, adjusted_mode); } else { @@ -1042,12 +1073,29 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc, static void radeon_crtc_prepare(struct drm_crtc *crtc) { - radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + struct drm_device *dev = crtc->dev; + struct drm_crtc *crtci; + + /* + * The hardware wedges sometimes if you reconfigure one CRTC + * whilst another is running (see fdo bug #24611). + */ + list_for_each_entry(crtci, &dev->mode_config.crtc_list, head) + radeon_crtc_dpms(crtci, DRM_MODE_DPMS_OFF); } static void radeon_crtc_commit(struct drm_crtc *crtc) { - radeon_crtc_dpms(crtc, DRM_MODE_DPMS_ON); + struct drm_device *dev = crtc->dev; + struct drm_crtc *crtci; + + /* + * Reenable the CRTCs that should be running. + */ + list_for_each_entry(crtci, &dev->mode_config.crtc_list, head) { + if (crtci->enabled) + radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON); + } } static const struct drm_crtc_helper_funcs legacy_helper_funcs = { diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 00382122869b9c94dfeeff68c1f6a4d5ec2ad821..df00515e81fa20870d73e9d797b5b19e681758b5 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -136,7 +136,14 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN; lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL); - if ((!rdev->is_atom_bios)) { + if (rdev->is_atom_bios) { + /* LVDS_GEN_CNTL parameters are computed in LVDSEncoderControl + * need to call that on resume to set up the reg properly. + */ + radeon_encoder->pixel_clock = adjusted_mode->clock; + atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE); + lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); + } else { struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv; if (lvds) { DRM_DEBUG("bios LVDS_GEN_CNTL: 0x%x\n", lvds->lvds_gen_cntl); @@ -147,8 +154,7 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, (lvds->panel_blon_delay << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT)); } else lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); - } else - lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); + } lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | @@ -184,9 +190,9 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); } -static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); @@ -194,15 +200,22 @@ static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder, radeon_encoder_set_active_device(encoder); drm_mode_set_crtcinfo(adjusted_mode, 0); - if (radeon_encoder->rmx_type != RMX_OFF) - radeon_rmx_mode_fixup(encoder, mode, adjusted_mode); + /* get the native mode for LVDS */ + if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { + struct drm_display_mode *native_mode = &radeon_encoder->native_mode; + int mode_id = adjusted_mode->base.id; + *adjusted_mode = *native_mode; + adjusted_mode->hdisplay = mode->hdisplay; + adjusted_mode->vdisplay = mode->vdisplay; + adjusted_mode->base.id = mode_id; + } return true; } static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = { .dpms = radeon_legacy_lvds_dpms, - .mode_fixup = radeon_legacy_lvds_mode_fixup, + .mode_fixup = radeon_legacy_mode_fixup, .prepare = radeon_legacy_lvds_prepare, .mode_set = radeon_legacy_lvds_mode_set, .commit = radeon_legacy_lvds_commit, @@ -214,17 +227,6 @@ static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = { .destroy = radeon_enc_destroy, }; -static bool radeon_legacy_primary_dac_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - /* set the active encoder to connector routing */ - radeon_encoder_set_active_device(encoder); - drm_mode_set_crtcinfo(adjusted_mode, 0); - - return true; -} - static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; @@ -410,7 +412,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc static const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = { .dpms = radeon_legacy_primary_dac_dpms, - .mode_fixup = radeon_legacy_primary_dac_mode_fixup, + .mode_fixup = radeon_legacy_mode_fixup, .prepare = radeon_legacy_primary_dac_prepare, .mode_set = radeon_legacy_primary_dac_mode_set, .commit = radeon_legacy_primary_dac_commit, @@ -423,16 +425,6 @@ static const struct drm_encoder_funcs radeon_legacy_primary_dac_enc_funcs = { .destroy = radeon_enc_destroy, }; -static bool radeon_legacy_tmds_int_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - - drm_mode_set_crtcinfo(adjusted_mode, 0); - - return true; -} - static void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; @@ -584,7 +576,7 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder, static const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs = { .dpms = radeon_legacy_tmds_int_dpms, - .mode_fixup = radeon_legacy_tmds_int_mode_fixup, + .mode_fixup = radeon_legacy_mode_fixup, .prepare = radeon_legacy_tmds_int_prepare, .mode_set = radeon_legacy_tmds_int_mode_set, .commit = radeon_legacy_tmds_int_commit, @@ -596,17 +588,6 @@ static const struct drm_encoder_funcs radeon_legacy_tmds_int_enc_funcs = { .destroy = radeon_enc_destroy, }; -static bool radeon_legacy_tmds_ext_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - /* set the active encoder to connector routing */ - radeon_encoder_set_active_device(encoder); - drm_mode_set_crtcinfo(adjusted_mode, 0); - - return true; -} - static void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; @@ -697,6 +678,8 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, /*if (mode->clock > 165000) fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;*/ } + if (!radeon_combios_external_tmds_setup(encoder)) + radeon_external_tmds_setup(encoder); } if (radeon_crtc->crtc_id == 0) { @@ -724,9 +707,22 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); } +static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv; + if (tmds) { + if (tmds->i2c_bus) + radeon_i2c_destroy(tmds->i2c_bus); + } + kfree(radeon_encoder->enc_priv); + drm_encoder_cleanup(encoder); + kfree(radeon_encoder); +} + static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs = { .dpms = radeon_legacy_tmds_ext_dpms, - .mode_fixup = radeon_legacy_tmds_ext_mode_fixup, + .mode_fixup = radeon_legacy_mode_fixup, .prepare = radeon_legacy_tmds_ext_prepare, .mode_set = radeon_legacy_tmds_ext_mode_set, .commit = radeon_legacy_tmds_ext_commit, @@ -735,20 +731,9 @@ static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs static const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = { - .destroy = radeon_enc_destroy, + .destroy = radeon_ext_tmds_enc_destroy, }; -static bool radeon_legacy_tv_dac_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - /* set the active encoder to connector routing */ - radeon_encoder_set_active_device(encoder); - drm_mode_set_crtcinfo(adjusted_mode, 0); - - return true; -} - static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; @@ -1265,7 +1250,7 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder static const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs = { .dpms = radeon_legacy_tv_dac_dpms, - .mode_fixup = radeon_legacy_tv_dac_mode_fixup, + .mode_fixup = radeon_legacy_mode_fixup, .prepare = radeon_legacy_tv_dac_prepare, .mode_set = radeon_legacy_tv_dac_mode_set, .commit = radeon_legacy_tv_dac_commit, @@ -1302,6 +1287,29 @@ static struct radeon_encoder_int_tmds *radeon_legacy_get_tmds_info(struct radeon return tmds; } +static struct radeon_encoder_ext_tmds *radeon_legacy_get_ext_tmds_info(struct radeon_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder_ext_tmds *tmds = NULL; + bool ret; + + if (rdev->is_atom_bios) + return NULL; + + tmds = kzalloc(sizeof(struct radeon_encoder_ext_tmds), GFP_KERNEL); + + if (!tmds) + return NULL; + + ret = radeon_legacy_get_ext_tmds_info_from_combios(encoder, tmds); + + if (ret == false) + radeon_legacy_get_ext_tmds_info_from_table(encoder, tmds); + + return tmds; +} + void radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device) { @@ -1329,7 +1337,6 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t encoder->possible_crtcs = 0x1; else encoder->possible_crtcs = 0x3; - encoder->possible_clones = 0; radeon_encoder->enc_priv = NULL; @@ -1373,7 +1380,7 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs, DRM_MODE_ENCODER_TMDS); drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs); if (!rdev->is_atom_bios) - radeon_combios_get_ext_tmds_info(radeon_encoder); + radeon_encoder->enc_priv = radeon_legacy_get_ext_tmds_info(radeon_encoder); break; } } diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index ace726aa0d76093ddd1f11e43c8a142d933caddb..44d4b652ea12ceebffa40e206e0f4c2a10f7f4fa 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -89,24 +90,45 @@ enum radeon_tv_std { TV_STD_PAL_CN, }; +/* radeon gpio-based i2c + * 1. "mask" reg and bits + * grabs the gpio pins for software use + * 0=not held 1=held + * 2. "a" reg and bits + * output pin value + * 0=low 1=high + * 3. "en" reg and bits + * sets the pin direction + * 0=input 1=output + * 4. "y" reg and bits + * input pin value + * 0=low 1=high + */ struct radeon_i2c_bus_rec { bool valid; + /* id used by atom */ + uint8_t i2c_id; + /* can be used with hw i2c engine */ + bool hw_capable; + /* uses multi-media i2c engine */ + bool mm_i2c; + /* regs and bits */ uint32_t mask_clk_reg; uint32_t mask_data_reg; uint32_t a_clk_reg; uint32_t a_data_reg; - uint32_t put_clk_reg; - uint32_t put_data_reg; - uint32_t get_clk_reg; - uint32_t get_data_reg; + uint32_t en_clk_reg; + uint32_t en_data_reg; + uint32_t y_clk_reg; + uint32_t y_data_reg; uint32_t mask_clk_mask; uint32_t mask_data_mask; - uint32_t put_clk_mask; - uint32_t put_data_mask; - uint32_t get_clk_mask; - uint32_t get_data_mask; uint32_t a_clk_mask; uint32_t a_data_mask; + uint32_t en_clk_mask; + uint32_t en_data_mask; + uint32_t y_clk_mask; + uint32_t y_data_mask; }; struct radeon_tmds_pll { @@ -150,9 +172,12 @@ struct radeon_pll { }; struct radeon_i2c_chan { - struct drm_device *dev; struct i2c_adapter adapter; - struct i2c_algo_bit_data algo; + struct drm_device *dev; + union { + struct i2c_algo_dp_aux_data dp; + struct i2c_algo_bit_data bit; + } algo; struct radeon_i2c_bus_rec rec; }; @@ -170,6 +195,11 @@ enum radeon_connector_table { CT_EMAC, }; +enum radeon_dvo_chip { + DVO_SIL164, + DVO_SIL1178, +}; + struct radeon_mode_info { struct atom_context *atom_context; struct card_info *atom_card_info; @@ -261,6 +291,13 @@ struct radeon_encoder_int_tmds { struct radeon_tmds_pll tmds_pll[4]; }; +struct radeon_encoder_ext_tmds { + /* tmds over dvo */ + struct radeon_i2c_chan *i2c_bus; + uint8_t slave_addr; + enum radeon_dvo_chip dvo_chip; +}; + /* spread spectrum */ struct radeon_atom_ss { uint16_t percentage; @@ -302,6 +339,35 @@ struct radeon_encoder { struct radeon_connector_atom_dig { uint32_t igp_lane_info; bool linkb; + /* displayport */ + struct radeon_i2c_chan *dp_i2c_bus; + u8 dpcd[8]; + u8 dp_sink_type; + int dp_clock; + int dp_lane_count; +}; + +struct radeon_gpio_rec { + bool valid; + u8 id; + u32 reg; + u32 mask; +}; + +enum radeon_hpd_id { + RADEON_HPD_NONE = 0, + RADEON_HPD_1, + RADEON_HPD_2, + RADEON_HPD_3, + RADEON_HPD_4, + RADEON_HPD_5, + RADEON_HPD_6, +}; + +struct radeon_hpd { + enum radeon_hpd_id hpd; + u8 plugged_state; + struct radeon_gpio_rec gpio; }; struct radeon_connector { @@ -318,6 +384,7 @@ struct radeon_connector { void *con_priv; bool dac_load_detect; uint16_t connector_object_id; + struct radeon_hpd hpd; }; struct radeon_framebuffer { @@ -325,10 +392,37 @@ struct radeon_framebuffer { struct drm_gem_object *obj; }; +extern void radeon_connector_hotplug(struct drm_connector *connector); +extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector); +extern int radeon_dp_mode_valid_helper(struct radeon_connector *radeon_connector, + struct drm_display_mode *mode); +extern void radeon_dp_set_link_config(struct drm_connector *connector, + struct drm_display_mode *mode); +extern void dp_link_train(struct drm_encoder *encoder, + struct drm_connector *connector); +extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector); +extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector); +extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, + int action, uint8_t lane_num, + uint8_t lane_set); +extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, + uint8_t write_byte, uint8_t *read_byte); + +extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, + struct radeon_i2c_bus_rec *rec, + const char *name); extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, struct radeon_i2c_bus_rec *rec, const char *name); extern void radeon_i2c_destroy(struct radeon_i2c_chan *i2c); +extern void radeon_i2c_sw_get_byte(struct radeon_i2c_chan *i2c_bus, + u8 slave_addr, + u8 addr, + u8 *val); +extern void radeon_i2c_sw_put_byte(struct radeon_i2c_chan *i2c, + u8 slave_addr, + u8 addr, + u8 val); extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); @@ -343,12 +437,24 @@ extern void radeon_compute_pll(struct radeon_pll *pll, uint32_t *post_div_p, int flags); +extern void radeon_compute_pll_avivo(struct radeon_pll *pll, + uint64_t freq, + uint32_t *dot_clock_p, + uint32_t *fb_div_p, + uint32_t *frac_fb_div_p, + uint32_t *ref_div_p, + uint32_t *post_div_p, + int flags); + +extern void radeon_setup_encoder_clones(struct drm_device *dev); + struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index); struct drm_encoder *radeon_encoder_legacy_primary_dac_add(struct drm_device *dev, int bios_index, int with_tv); struct drm_encoder *radeon_encoder_legacy_tv_dac_add(struct drm_device *dev, int bios_index, int with_tv); struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, int bios_index); struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, int bios_index); extern void atombios_external_tmds_setup(struct drm_encoder *encoder, int action); +extern void atombios_digital_setup(struct drm_encoder *encoder, int action); extern int atombios_get_encoder_mode(struct drm_encoder *encoder); extern void radeon_encoder_set_active_device(struct drm_encoder *encoder); @@ -378,12 +484,16 @@ extern bool radeon_atom_get_clock_info(struct drm_device *dev); extern bool radeon_combios_get_clock_info(struct drm_device *dev); extern struct radeon_encoder_atom_dig * radeon_atombios_get_lvds_info(struct radeon_encoder *encoder); -bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder, - struct radeon_encoder_int_tmds *tmds); -bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder, - struct radeon_encoder_int_tmds *tmds); -bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder, - struct radeon_encoder_int_tmds *tmds); +extern bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder, + struct radeon_encoder_int_tmds *tmds); +extern bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder, + struct radeon_encoder_int_tmds *tmds); +extern bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder, + struct radeon_encoder_int_tmds *tmds); +extern bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder, + struct radeon_encoder_ext_tmds *tmds); +extern bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder, + struct radeon_encoder_ext_tmds *tmds); extern struct radeon_encoder_primary_dac * radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder); extern struct radeon_encoder_tv_dac * @@ -395,6 +505,8 @@ extern struct radeon_encoder_tv_dac * radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder); extern struct radeon_encoder_primary_dac * radeon_combios_get_primary_dac_info(struct radeon_encoder *encoder); +extern bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder); +extern void radeon_external_tmds_setup(struct drm_encoder *encoder); extern void radeon_combios_output_lock(struct drm_encoder *encoder, bool lock); extern void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev); extern void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock); @@ -426,16 +538,13 @@ void radeon_atombios_init_crtc(struct drm_device *dev, struct radeon_crtc *radeon_crtc); void radeon_legacy_init_crtc(struct drm_device *dev, struct radeon_crtc *radeon_crtc); -void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state); +extern void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state); void radeon_get_clock_info(struct drm_device *dev); extern bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev); extern bool radeon_get_atom_connector_info_from_supported_devices_table(struct drm_device *dev); -void radeon_rmx_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); void radeon_enc_destroy(struct drm_encoder *encoder); void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj); void radeon_combios_asic_init(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 1f056dadc5c2243339c0562801669bf28a903b1b..544e18ffaf22e808b8f899874756aa3114d12040 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -34,100 +34,53 @@ #include "radeon_drm.h" #include "radeon.h" -struct radeon_object { - struct ttm_buffer_object tobj; - struct list_head list; - struct radeon_device *rdev; - struct drm_gem_object *gobj; - struct ttm_bo_kmap_obj kmap; - unsigned pin_count; - uint64_t gpu_addr; - void *kptr; - bool is_iomem; - uint32_t tiling_flags; - uint32_t pitch; - int surface_reg; -}; int radeon_ttm_init(struct radeon_device *rdev); void radeon_ttm_fini(struct radeon_device *rdev); +static void radeon_bo_clear_surface_reg(struct radeon_bo *bo); /* * To exclude mutual BO access we rely on bo_reserve exclusion, as all * function are calling it. */ -static int radeon_object_reserve(struct radeon_object *robj, bool interruptible) +static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo) { - return ttm_bo_reserve(&robj->tobj, interruptible, false, false, 0); -} + struct radeon_bo *bo; -static void radeon_object_unreserve(struct radeon_object *robj) -{ - ttm_bo_unreserve(&robj->tobj); + bo = container_of(tbo, struct radeon_bo, tbo); + mutex_lock(&bo->rdev->gem.mutex); + list_del_init(&bo->list); + mutex_unlock(&bo->rdev->gem.mutex); + radeon_bo_clear_surface_reg(bo); + kfree(bo); } -static void radeon_ttm_object_object_destroy(struct ttm_buffer_object *tobj) +void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) { - struct radeon_object *robj; + u32 c = 0; - robj = container_of(tobj, struct radeon_object, tobj); - list_del_init(&robj->list); - radeon_object_clear_surface_reg(robj); - kfree(robj); + rbo->placement.fpfn = 0; + rbo->placement.lpfn = 0; + rbo->placement.placement = rbo->placements; + rbo->placement.busy_placement = rbo->placements; + if (domain & RADEON_GEM_DOMAIN_VRAM) + rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | + TTM_PL_FLAG_VRAM; + if (domain & RADEON_GEM_DOMAIN_GTT) + rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; + if (domain & RADEON_GEM_DOMAIN_CPU) + rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; + rbo->placement.num_placement = c; + rbo->placement.num_busy_placement = c; } -static inline void radeon_object_gpu_addr(struct radeon_object *robj) +int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, + unsigned long size, bool kernel, u32 domain, + struct radeon_bo **bo_ptr) { - /* Default gpu address */ - robj->gpu_addr = 0xFFFFFFFFFFFFFFFFULL; - if (robj->tobj.mem.mm_node == NULL) { - return; - } - robj->gpu_addr = ((u64)robj->tobj.mem.mm_node->start) << PAGE_SHIFT; - switch (robj->tobj.mem.mem_type) { - case TTM_PL_VRAM: - robj->gpu_addr += (u64)robj->rdev->mc.vram_location; - break; - case TTM_PL_TT: - robj->gpu_addr += (u64)robj->rdev->mc.gtt_location; - break; - default: - DRM_ERROR("Unknown placement %d\n", robj->tobj.mem.mem_type); - robj->gpu_addr = 0xFFFFFFFFFFFFFFFFULL; - return; - } -} - -static inline uint32_t radeon_object_flags_from_domain(uint32_t domain) -{ - uint32_t flags = 0; - if (domain & RADEON_GEM_DOMAIN_VRAM) { - flags |= TTM_PL_FLAG_VRAM | TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED; - } - if (domain & RADEON_GEM_DOMAIN_GTT) { - flags |= TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; - } - if (domain & RADEON_GEM_DOMAIN_CPU) { - flags |= TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING; - } - if (!flags) { - flags |= TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING; - } - return flags; -} - -int radeon_object_create(struct radeon_device *rdev, - struct drm_gem_object *gobj, - unsigned long size, - bool kernel, - uint32_t domain, - bool interruptible, - struct radeon_object **robj_ptr) -{ - struct radeon_object *robj; + struct radeon_bo *bo; enum ttm_bo_type type; - uint32_t flags; int r; if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { @@ -138,206 +91,125 @@ int radeon_object_create(struct radeon_device *rdev, } else { type = ttm_bo_type_device; } - *robj_ptr = NULL; - robj = kzalloc(sizeof(struct radeon_object), GFP_KERNEL); - if (robj == NULL) { + *bo_ptr = NULL; + bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); + if (bo == NULL) return -ENOMEM; - } - robj->rdev = rdev; - robj->gobj = gobj; - robj->surface_reg = -1; - INIT_LIST_HEAD(&robj->list); - - flags = radeon_object_flags_from_domain(domain); - r = ttm_buffer_object_init(&rdev->mman.bdev, &robj->tobj, size, type, flags, - 0, 0, false, NULL, size, - &radeon_ttm_object_object_destroy); + bo->rdev = rdev; + bo->gobj = gobj; + bo->surface_reg = -1; + INIT_LIST_HEAD(&bo->list); + + radeon_ttm_placement_from_domain(bo, domain); + /* Kernel allocation are uninterruptible */ + r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type, + &bo->placement, 0, 0, !kernel, NULL, size, + &radeon_ttm_bo_destroy); if (unlikely(r != 0)) { - /* ttm call radeon_ttm_object_object_destroy if error happen */ - DRM_ERROR("Failed to allocate TTM object (%ld, 0x%08X, %u)\n", - size, flags, 0); + if (r != -ERESTARTSYS) + dev_err(rdev->dev, + "object_init failed for (%lu, 0x%08X)\n", + size, domain); return r; } - *robj_ptr = robj; + *bo_ptr = bo; if (gobj) { - list_add_tail(&robj->list, &rdev->gem.objects); + mutex_lock(&bo->rdev->gem.mutex); + list_add_tail(&bo->list, &rdev->gem.objects); + mutex_unlock(&bo->rdev->gem.mutex); } return 0; } -int radeon_object_kmap(struct radeon_object *robj, void **ptr) +int radeon_bo_kmap(struct radeon_bo *bo, void **ptr) { + bool is_iomem; int r; - spin_lock(&robj->tobj.lock); - if (robj->kptr) { + if (bo->kptr) { if (ptr) { - *ptr = robj->kptr; + *ptr = bo->kptr; } - spin_unlock(&robj->tobj.lock); return 0; } - spin_unlock(&robj->tobj.lock); - r = ttm_bo_kmap(&robj->tobj, 0, robj->tobj.num_pages, &robj->kmap); + r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, &bo->kmap); if (r) { return r; } - spin_lock(&robj->tobj.lock); - robj->kptr = ttm_kmap_obj_virtual(&robj->kmap, &robj->is_iomem); - spin_unlock(&robj->tobj.lock); + bo->kptr = ttm_kmap_obj_virtual(&bo->kmap, &is_iomem); if (ptr) { - *ptr = robj->kptr; + *ptr = bo->kptr; } - radeon_object_check_tiling(robj, 0, 0); + radeon_bo_check_tiling(bo, 0, 0); return 0; } -void radeon_object_kunmap(struct radeon_object *robj) +void radeon_bo_kunmap(struct radeon_bo *bo) { - spin_lock(&robj->tobj.lock); - if (robj->kptr == NULL) { - spin_unlock(&robj->tobj.lock); + if (bo->kptr == NULL) return; - } - robj->kptr = NULL; - spin_unlock(&robj->tobj.lock); - radeon_object_check_tiling(robj, 0, 0); - ttm_bo_kunmap(&robj->kmap); + bo->kptr = NULL; + radeon_bo_check_tiling(bo, 0, 0); + ttm_bo_kunmap(&bo->kmap); } -void radeon_object_unref(struct radeon_object **robj) +void radeon_bo_unref(struct radeon_bo **bo) { - struct ttm_buffer_object *tobj; + struct ttm_buffer_object *tbo; - if ((*robj) == NULL) { + if ((*bo) == NULL) return; - } - tobj = &((*robj)->tobj); - ttm_bo_unref(&tobj); - if (tobj == NULL) { - *robj = NULL; - } -} - -int radeon_object_mmap(struct radeon_object *robj, uint64_t *offset) -{ - *offset = robj->tobj.addr_space_offset; - return 0; + tbo = &((*bo)->tbo); + ttm_bo_unref(&tbo); + if (tbo == NULL) + *bo = NULL; } -int radeon_object_pin(struct radeon_object *robj, uint32_t domain, - uint64_t *gpu_addr) +int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) { - uint32_t flags; - uint32_t tmp; - int r; + int r, i; - flags = radeon_object_flags_from_domain(domain); - spin_lock(&robj->tobj.lock); - if (robj->pin_count) { - robj->pin_count++; - if (gpu_addr != NULL) { - *gpu_addr = robj->gpu_addr; - } - spin_unlock(&robj->tobj.lock); + radeon_ttm_placement_from_domain(bo, domain); + if (bo->pin_count) { + bo->pin_count++; + if (gpu_addr) + *gpu_addr = radeon_bo_gpu_offset(bo); return 0; } - spin_unlock(&robj->tobj.lock); - r = radeon_object_reserve(robj, false); - if (unlikely(r != 0)) { - DRM_ERROR("radeon: failed to reserve object for pinning it.\n"); - return r; - } - tmp = robj->tobj.mem.placement; - ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM); - robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING; - r = ttm_buffer_object_validate(&robj->tobj, - robj->tobj.proposed_placement, - false, false); - radeon_object_gpu_addr(robj); - if (gpu_addr != NULL) { - *gpu_addr = robj->gpu_addr; - } - robj->pin_count = 1; - if (unlikely(r != 0)) { - DRM_ERROR("radeon: failed to pin object.\n"); - } - radeon_object_unreserve(robj); + radeon_ttm_placement_from_domain(bo, domain); + for (i = 0; i < bo->placement.num_placement; i++) + bo->placements[i] |= TTM_PL_FLAG_NO_EVICT; + r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); + if (likely(r == 0)) { + bo->pin_count = 1; + if (gpu_addr != NULL) + *gpu_addr = radeon_bo_gpu_offset(bo); + } + if (unlikely(r != 0)) + dev_err(bo->rdev->dev, "%p pin failed\n", bo); return r; } -void radeon_object_unpin(struct radeon_object *robj) +int radeon_bo_unpin(struct radeon_bo *bo) { - uint32_t flags; - int r; + int r, i; - spin_lock(&robj->tobj.lock); - if (!robj->pin_count) { - spin_unlock(&robj->tobj.lock); - printk(KERN_WARNING "Unpin not necessary for %p !\n", robj); - return; - } - robj->pin_count--; - if (robj->pin_count) { - spin_unlock(&robj->tobj.lock); - return; - } - spin_unlock(&robj->tobj.lock); - r = radeon_object_reserve(robj, false); - if (unlikely(r != 0)) { - DRM_ERROR("radeon: failed to reserve object for unpinning it.\n"); - return; - } - flags = robj->tobj.mem.placement; - robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT; - r = ttm_buffer_object_validate(&robj->tobj, - robj->tobj.proposed_placement, - false, false); - if (unlikely(r != 0)) { - DRM_ERROR("radeon: failed to unpin buffer.\n"); - } - radeon_object_unreserve(robj); -} - -int radeon_object_wait(struct radeon_object *robj) -{ - int r = 0; - - /* FIXME: should use block reservation instead */ - r = radeon_object_reserve(robj, true); - if (unlikely(r != 0)) { - DRM_ERROR("radeon: failed to reserve object for waiting.\n"); - return r; - } - spin_lock(&robj->tobj.lock); - if (robj->tobj.sync_obj) { - r = ttm_bo_wait(&robj->tobj, true, true, false); - } - spin_unlock(&robj->tobj.lock); - radeon_object_unreserve(robj); - return r; -} - -int radeon_object_busy_domain(struct radeon_object *robj, uint32_t *cur_placement) -{ - int r = 0; - - r = radeon_object_reserve(robj, true); - if (unlikely(r != 0)) { - DRM_ERROR("radeon: failed to reserve object for waiting.\n"); - return r; - } - spin_lock(&robj->tobj.lock); - *cur_placement = robj->tobj.mem.mem_type; - if (robj->tobj.sync_obj) { - r = ttm_bo_wait(&robj->tobj, true, true, true); + if (!bo->pin_count) { + dev_warn(bo->rdev->dev, "%p unpin not necessary\n", bo); + return 0; } - spin_unlock(&robj->tobj.lock); - radeon_object_unreserve(robj); + bo->pin_count--; + if (bo->pin_count) + return 0; + for (i = 0; i < bo->placement.num_placement; i++) + bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT; + r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); + if (unlikely(r != 0)) + dev_err(bo->rdev->dev, "%p validate failed for unpin\n", bo); return r; } -int radeon_object_evict_vram(struct radeon_device *rdev) +int radeon_bo_evict_vram(struct radeon_device *rdev) { if (rdev->flags & RADEON_IS_IGP) { /* Useless to evict on IGP chips */ @@ -346,30 +218,32 @@ int radeon_object_evict_vram(struct radeon_device *rdev) return ttm_bo_evict_mm(&rdev->mman.bdev, TTM_PL_VRAM); } -void radeon_object_force_delete(struct radeon_device *rdev) +void radeon_bo_force_delete(struct radeon_device *rdev) { - struct radeon_object *robj, *n; + struct radeon_bo *bo, *n; struct drm_gem_object *gobj; if (list_empty(&rdev->gem.objects)) { return; } - DRM_ERROR("Userspace still has active objects !\n"); - list_for_each_entry_safe(robj, n, &rdev->gem.objects, list) { + dev_err(rdev->dev, "Userspace still has active objects !\n"); + list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) { mutex_lock(&rdev->ddev->struct_mutex); - gobj = robj->gobj; - DRM_ERROR("Force free for (%p,%p,%lu,%lu)\n", - gobj, robj, (unsigned long)gobj->size, - *((unsigned long *)&gobj->refcount)); - list_del_init(&robj->list); - radeon_object_unref(&robj); + gobj = bo->gobj; + dev_err(rdev->dev, "%p %p %lu %lu force free\n", + gobj, bo, (unsigned long)gobj->size, + *((unsigned long *)&gobj->refcount)); + mutex_lock(&bo->rdev->gem.mutex); + list_del_init(&bo->list); + mutex_unlock(&bo->rdev->gem.mutex); + radeon_bo_unref(&bo); gobj->driver_private = NULL; drm_gem_object_unreference(gobj); mutex_unlock(&rdev->ddev->struct_mutex); } } -int radeon_object_init(struct radeon_device *rdev) +int radeon_bo_init(struct radeon_device *rdev) { /* Add an MTRR for the VRAM */ rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size, @@ -382,13 +256,13 @@ int radeon_object_init(struct radeon_device *rdev) return radeon_ttm_init(rdev); } -void radeon_object_fini(struct radeon_device *rdev) +void radeon_bo_fini(struct radeon_device *rdev) { radeon_ttm_fini(rdev); } -void radeon_object_list_add_object(struct radeon_object_list *lobj, - struct list_head *head) +void radeon_bo_list_add_object(struct radeon_bo_list *lobj, + struct list_head *head) { if (lobj->wdomain) { list_add(&lobj->list, head); @@ -397,72 +271,62 @@ void radeon_object_list_add_object(struct radeon_object_list *lobj, } } -int radeon_object_list_reserve(struct list_head *head) +int radeon_bo_list_reserve(struct list_head *head) { - struct radeon_object_list *lobj; + struct radeon_bo_list *lobj; int r; list_for_each_entry(lobj, head, list){ - if (!lobj->robj->pin_count) { - r = radeon_object_reserve(lobj->robj, true); - if (unlikely(r != 0)) { - DRM_ERROR("radeon: failed to reserve object.\n"); - return r; - } - } else { - } + r = radeon_bo_reserve(lobj->bo, false); + if (unlikely(r != 0)) + return r; } return 0; } -void radeon_object_list_unreserve(struct list_head *head) +void radeon_bo_list_unreserve(struct list_head *head) { - struct radeon_object_list *lobj; + struct radeon_bo_list *lobj; list_for_each_entry(lobj, head, list) { - if (!lobj->robj->pin_count) { - radeon_object_unreserve(lobj->robj); - } + /* only unreserve object we successfully reserved */ + if (radeon_bo_is_reserved(lobj->bo)) + radeon_bo_unreserve(lobj->bo); } } -int radeon_object_list_validate(struct list_head *head, void *fence) +int radeon_bo_list_validate(struct list_head *head, void *fence) { - struct radeon_object_list *lobj; - struct radeon_object *robj; + struct radeon_bo_list *lobj; + struct radeon_bo *bo; struct radeon_fence *old_fence = NULL; int r; - r = radeon_object_list_reserve(head); + r = radeon_bo_list_reserve(head); if (unlikely(r != 0)) { - radeon_object_list_unreserve(head); return r; } list_for_each_entry(lobj, head, list) { - robj = lobj->robj; - if (!robj->pin_count) { + bo = lobj->bo; + if (!bo->pin_count) { if (lobj->wdomain) { - robj->tobj.proposed_placement = - radeon_object_flags_from_domain(lobj->wdomain); + radeon_ttm_placement_from_domain(bo, + lobj->wdomain); } else { - robj->tobj.proposed_placement = - radeon_object_flags_from_domain(lobj->rdomain); + radeon_ttm_placement_from_domain(bo, + lobj->rdomain); } - r = ttm_buffer_object_validate(&robj->tobj, - robj->tobj.proposed_placement, - true, false); - if (unlikely(r)) { - DRM_ERROR("radeon: failed to validate.\n"); + r = ttm_bo_validate(&bo->tbo, &bo->placement, + true, false); + if (unlikely(r)) return r; - } - radeon_object_gpu_addr(robj); } - lobj->gpu_offset = robj->gpu_addr; - lobj->tiling_flags = robj->tiling_flags; + lobj->gpu_offset = radeon_bo_gpu_offset(bo); + lobj->tiling_flags = bo->tiling_flags; if (fence) { - old_fence = (struct radeon_fence *)robj->tobj.sync_obj; - robj->tobj.sync_obj = radeon_fence_ref(fence); - robj->tobj.sync_obj_arg = NULL; + old_fence = (struct radeon_fence *)bo->tbo.sync_obj; + bo->tbo.sync_obj = radeon_fence_ref(fence); + bo->tbo.sync_obj_arg = NULL; } if (old_fence) { radeon_fence_unref(&old_fence); @@ -471,51 +335,44 @@ int radeon_object_list_validate(struct list_head *head, void *fence) return 0; } -void radeon_object_list_unvalidate(struct list_head *head) +void radeon_bo_list_unvalidate(struct list_head *head, void *fence) { - struct radeon_object_list *lobj; - struct radeon_fence *old_fence = NULL; + struct radeon_bo_list *lobj; + struct radeon_fence *old_fence; - list_for_each_entry(lobj, head, list) { - old_fence = (struct radeon_fence *)lobj->robj->tobj.sync_obj; - lobj->robj->tobj.sync_obj = NULL; - if (old_fence) { - radeon_fence_unref(&old_fence); + if (fence) + list_for_each_entry(lobj, head, list) { + old_fence = to_radeon_fence(lobj->bo->tbo.sync_obj); + if (old_fence == fence) { + lobj->bo->tbo.sync_obj = NULL; + radeon_fence_unref(&old_fence); + } } - } - radeon_object_list_unreserve(head); -} - -void radeon_object_list_clean(struct list_head *head) -{ - radeon_object_list_unreserve(head); + radeon_bo_list_unreserve(head); } -int radeon_object_fbdev_mmap(struct radeon_object *robj, +int radeon_bo_fbdev_mmap(struct radeon_bo *bo, struct vm_area_struct *vma) { - return ttm_fbdev_mmap(vma, &robj->tobj); + return ttm_fbdev_mmap(vma, &bo->tbo); } -unsigned long radeon_object_size(struct radeon_object *robj) +int radeon_bo_get_surface_reg(struct radeon_bo *bo) { - return robj->tobj.num_pages << PAGE_SHIFT; -} - -int radeon_object_get_surface_reg(struct radeon_object *robj) -{ - struct radeon_device *rdev = robj->rdev; + struct radeon_device *rdev = bo->rdev; struct radeon_surface_reg *reg; - struct radeon_object *old_object; + struct radeon_bo *old_object; int steal; int i; - if (!robj->tiling_flags) + BUG_ON(!atomic_read(&bo->tbo.reserved)); + + if (!bo->tiling_flags) return 0; - if (robj->surface_reg >= 0) { - reg = &rdev->surface_regs[robj->surface_reg]; - i = robj->surface_reg; + if (bo->surface_reg >= 0) { + reg = &rdev->surface_regs[bo->surface_reg]; + i = bo->surface_reg; goto out; } @@ -523,10 +380,10 @@ int radeon_object_get_surface_reg(struct radeon_object *robj) for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) { reg = &rdev->surface_regs[i]; - if (!reg->robj) + if (!reg->bo) break; - old_object = reg->robj; + old_object = reg->bo; if (old_object->pin_count == 0) steal = i; } @@ -537,91 +394,101 @@ int radeon_object_get_surface_reg(struct radeon_object *robj) return -ENOMEM; /* find someone with a surface reg and nuke their BO */ reg = &rdev->surface_regs[steal]; - old_object = reg->robj; + old_object = reg->bo; /* blow away the mapping */ DRM_DEBUG("stealing surface reg %d from %p\n", steal, old_object); - ttm_bo_unmap_virtual(&old_object->tobj); + ttm_bo_unmap_virtual(&old_object->tbo); old_object->surface_reg = -1; i = steal; } - robj->surface_reg = i; - reg->robj = robj; + bo->surface_reg = i; + reg->bo = bo; out: - radeon_set_surface_reg(rdev, i, robj->tiling_flags, robj->pitch, - robj->tobj.mem.mm_node->start << PAGE_SHIFT, - robj->tobj.num_pages << PAGE_SHIFT); + radeon_set_surface_reg(rdev, i, bo->tiling_flags, bo->pitch, + bo->tbo.mem.mm_node->start << PAGE_SHIFT, + bo->tbo.num_pages << PAGE_SHIFT); return 0; } -void radeon_object_clear_surface_reg(struct radeon_object *robj) +static void radeon_bo_clear_surface_reg(struct radeon_bo *bo) { - struct radeon_device *rdev = robj->rdev; + struct radeon_device *rdev = bo->rdev; struct radeon_surface_reg *reg; - if (robj->surface_reg == -1) + if (bo->surface_reg == -1) return; - reg = &rdev->surface_regs[robj->surface_reg]; - radeon_clear_surface_reg(rdev, robj->surface_reg); + reg = &rdev->surface_regs[bo->surface_reg]; + radeon_clear_surface_reg(rdev, bo->surface_reg); - reg->robj = NULL; - robj->surface_reg = -1; + reg->bo = NULL; + bo->surface_reg = -1; } -void radeon_object_set_tiling_flags(struct radeon_object *robj, - uint32_t tiling_flags, uint32_t pitch) +int radeon_bo_set_tiling_flags(struct radeon_bo *bo, + uint32_t tiling_flags, uint32_t pitch) { - robj->tiling_flags = tiling_flags; - robj->pitch = pitch; + int r; + + r = radeon_bo_reserve(bo, false); + if (unlikely(r != 0)) + return r; + bo->tiling_flags = tiling_flags; + bo->pitch = pitch; + radeon_bo_unreserve(bo); + return 0; } -void radeon_object_get_tiling_flags(struct radeon_object *robj, - uint32_t *tiling_flags, - uint32_t *pitch) +void radeon_bo_get_tiling_flags(struct radeon_bo *bo, + uint32_t *tiling_flags, + uint32_t *pitch) { + BUG_ON(!atomic_read(&bo->tbo.reserved)); if (tiling_flags) - *tiling_flags = robj->tiling_flags; + *tiling_flags = bo->tiling_flags; if (pitch) - *pitch = robj->pitch; + *pitch = bo->pitch; } -int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved, - bool force_drop) +int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, + bool force_drop) { - if (!(robj->tiling_flags & RADEON_TILING_SURFACE)) + BUG_ON(!atomic_read(&bo->tbo.reserved)); + + if (!(bo->tiling_flags & RADEON_TILING_SURFACE)) return 0; if (force_drop) { - radeon_object_clear_surface_reg(robj); + radeon_bo_clear_surface_reg(bo); return 0; } - if (robj->tobj.mem.mem_type != TTM_PL_VRAM) { + if (bo->tbo.mem.mem_type != TTM_PL_VRAM) { if (!has_moved) return 0; - if (robj->surface_reg >= 0) - radeon_object_clear_surface_reg(robj); + if (bo->surface_reg >= 0) + radeon_bo_clear_surface_reg(bo); return 0; } - if ((robj->surface_reg >= 0) && !has_moved) + if ((bo->surface_reg >= 0) && !has_moved) return 0; - return radeon_object_get_surface_reg(robj); + return radeon_bo_get_surface_reg(bo); } void radeon_bo_move_notify(struct ttm_buffer_object *bo, - struct ttm_mem_reg *mem) + struct ttm_mem_reg *mem) { - struct radeon_object *robj = container_of(bo, struct radeon_object, tobj); - radeon_object_check_tiling(robj, 0, 1); + struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo); + radeon_bo_check_tiling(rbo, 0, 1); } void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) { - struct radeon_object *robj = container_of(bo, struct radeon_object, tobj); - radeon_object_check_tiling(robj, 0, 0); + struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo); + radeon_bo_check_tiling(rbo, 0, 0); } diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index 10e8af6bb456b9dd7e32f960edb1ad1f4b0d2b34..f6b69c2c0d00cdec665946070405fe31b6005df4 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -28,19 +28,152 @@ #ifndef __RADEON_OBJECT_H__ #define __RADEON_OBJECT_H__ -#include -#include -#include -#include +#include +#include "radeon.h" -/* - * TTM. +/** + * radeon_mem_type_to_domain - return domain corresponding to mem_type + * @mem_type: ttm memory type + * + * Returns corresponding domain of the ttm mem_type + */ +static inline unsigned radeon_mem_type_to_domain(u32 mem_type) +{ + switch (mem_type) { + case TTM_PL_VRAM: + return RADEON_GEM_DOMAIN_VRAM; + case TTM_PL_TT: + return RADEON_GEM_DOMAIN_GTT; + case TTM_PL_SYSTEM: + return RADEON_GEM_DOMAIN_CPU; + default: + break; + } + return 0; +} + +/** + * radeon_bo_reserve - reserve bo + * @bo: bo structure + * @no_wait: don't sleep while trying to reserve (return -EBUSY) + * + * Returns: + * -EBUSY: buffer is busy and @no_wait is true + * -ERESTART: A wait for the buffer to become unreserved was interrupted by + * a signal. Release all buffer reservations and return to user-space. */ -struct radeon_mman { - struct ttm_bo_global_ref bo_global_ref; - struct ttm_global_reference mem_global_ref; - bool mem_global_referenced; - struct ttm_bo_device bdev; -}; +static inline int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait) +{ + int r; + +retry: + r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0); + if (unlikely(r != 0)) { + if (r == -ERESTART) + goto retry; + dev_err(bo->rdev->dev, "%p reserve failed\n", bo); + return r; + } + return 0; +} + +static inline void radeon_bo_unreserve(struct radeon_bo *bo) +{ + ttm_bo_unreserve(&bo->tbo); +} + +/** + * radeon_bo_gpu_offset - return GPU offset of bo + * @bo: radeon object for which we query the offset + * + * Returns current GPU offset of the object. + * + * Note: object should either be pinned or reserved when calling this + * function, it might be usefull to add check for this for debugging. + */ +static inline u64 radeon_bo_gpu_offset(struct radeon_bo *bo) +{ + return bo->tbo.offset; +} + +static inline unsigned long radeon_bo_size(struct radeon_bo *bo) +{ + return bo->tbo.num_pages << PAGE_SHIFT; +} + +static inline bool radeon_bo_is_reserved(struct radeon_bo *bo) +{ + return !!atomic_read(&bo->tbo.reserved); +} + +/** + * radeon_bo_mmap_offset - return mmap offset of bo + * @bo: radeon object for which we query the offset + * + * Returns mmap offset of the object. + * + * Note: addr_space_offset is constant after ttm bo init thus isn't protected + * by any lock. + */ +static inline u64 radeon_bo_mmap_offset(struct radeon_bo *bo) +{ + return bo->tbo.addr_space_offset; +} + +static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, + bool no_wait) +{ + int r; + +retry: + r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0); + if (unlikely(r != 0)) { + if (r == -ERESTART) + goto retry; + dev_err(bo->rdev->dev, "%p reserve failed for wait\n", bo); + return r; + } + spin_lock(&bo->tbo.lock); + if (mem_type) + *mem_type = bo->tbo.mem.mem_type; + if (bo->tbo.sync_obj) + r = ttm_bo_wait(&bo->tbo, true, true, no_wait); + spin_unlock(&bo->tbo.lock); + ttm_bo_unreserve(&bo->tbo); + if (unlikely(r == -ERESTART)) + goto retry; + return r; +} +extern int radeon_bo_create(struct radeon_device *rdev, + struct drm_gem_object *gobj, unsigned long size, + bool kernel, u32 domain, + struct radeon_bo **bo_ptr); +extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr); +extern void radeon_bo_kunmap(struct radeon_bo *bo); +extern void radeon_bo_unref(struct radeon_bo **bo); +extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr); +extern int radeon_bo_unpin(struct radeon_bo *bo); +extern int radeon_bo_evict_vram(struct radeon_device *rdev); +extern void radeon_bo_force_delete(struct radeon_device *rdev); +extern int radeon_bo_init(struct radeon_device *rdev); +extern void radeon_bo_fini(struct radeon_device *rdev); +extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj, + struct list_head *head); +extern int radeon_bo_list_reserve(struct list_head *head); +extern void radeon_bo_list_unreserve(struct list_head *head); +extern int radeon_bo_list_validate(struct list_head *head, void *fence); +extern void radeon_bo_list_unvalidate(struct list_head *head, void *fence); +extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo, + struct vm_area_struct *vma); +extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo, + u32 tiling_flags, u32 pitch); +extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo, + u32 *tiling_flags, u32 *pitch); +extern int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, + bool force_drop); +extern void radeon_bo_move_notify(struct ttm_buffer_object *bo, + struct ttm_mem_reg *mem); +extern void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo); +extern int radeon_bo_get_surface_reg(struct radeon_bo *bo); #endif diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 46146c6a2a065d0270aa6562f077b357a50347a5..34b08d307c814529251fb5e8d4694986f2ffbe86 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -27,7 +27,7 @@ int radeon_debugfs_pm_init(struct radeon_device *rdev); int radeon_pm_init(struct radeon_device *rdev) { if (radeon_debugfs_pm_init(rdev)) { - DRM_ERROR("Failed to register debugfs file for CP !\n"); + DRM_ERROR("Failed to register debugfs file for PM!\n"); } return 0; @@ -44,8 +44,8 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct radeon_device *rdev = dev->dev_private; - seq_printf(m, "engine clock: %u0 Hz\n", radeon_get_engine_clock(rdev)); - seq_printf(m, "memory clock: %u0 Hz\n", radeon_get_memory_clock(rdev)); + seq_printf(m, "engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev)); + seq_printf(m, "memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev)); return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h index 29ab75903ec143a42446adff7d75741521d0eb23..6d0a009dd4a11fff1bd62a85a0a24df4526c4d30 100644 --- a/drivers/gpu/drm/radeon/radeon_reg.h +++ b/drivers/gpu/drm/radeon/radeon_reg.h @@ -887,6 +887,7 @@ # define RADEON_FP_PANEL_FORMAT (1 << 3) # define RADEON_FP_EN_TMDS (1 << 7) # define RADEON_FP_DETECT_SENSE (1 << 8) +# define RADEON_FP_DETECT_INT_POL (1 << 9) # define R200_FP_SOURCE_SEL_MASK (3 << 10) # define R200_FP_SOURCE_SEL_CRTC1 (0 << 10) # define R200_FP_SOURCE_SEL_CRTC2 (1 << 10) @@ -894,6 +895,7 @@ # define R200_FP_SOURCE_SEL_TRANS (3 << 10) # define RADEON_FP_SEL_CRTC1 (0 << 13) # define RADEON_FP_SEL_CRTC2 (1 << 13) +# define R300_HPD_SEL(x) ((x) << 13) # define RADEON_FP_CRTC_DONT_SHADOW_HPAR (1 << 15) # define RADEON_FP_CRTC_DONT_SHADOW_VPAR (1 << 16) # define RADEON_FP_CRTC_DONT_SHADOW_HEND (1 << 17) @@ -909,6 +911,7 @@ # define RADEON_FP2_ON (1 << 2) # define RADEON_FP2_PANEL_FORMAT (1 << 3) # define RADEON_FP2_DETECT_SENSE (1 << 8) +# define RADEON_FP2_DETECT_INT_POL (1 << 9) # define R200_FP2_SOURCE_SEL_MASK (3 << 10) # define R200_FP2_SOURCE_SEL_CRTC1 (0 << 10) # define R200_FP2_SOURCE_SEL_CRTC2 (1 << 10) @@ -988,14 +991,20 @@ #define RADEON_GEN_INT_CNTL 0x0040 # define RADEON_CRTC_VBLANK_MASK (1 << 0) +# define RADEON_FP_DETECT_MASK (1 << 4) # define RADEON_CRTC2_VBLANK_MASK (1 << 9) +# define RADEON_FP2_DETECT_MASK (1 << 10) # define RADEON_SW_INT_ENABLE (1 << 25) #define RADEON_GEN_INT_STATUS 0x0044 # define AVIVO_DISPLAY_INT_STATUS (1 << 0) # define RADEON_CRTC_VBLANK_STAT (1 << 0) # define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0) +# define RADEON_FP_DETECT_STAT (1 << 4) +# define RADEON_FP_DETECT_STAT_ACK (1 << 4) # define RADEON_CRTC2_VBLANK_STAT (1 << 9) # define RADEON_CRTC2_VBLANK_STAT_ACK (1 << 9) +# define RADEON_FP2_DETECT_STAT (1 << 10) +# define RADEON_FP2_DETECT_STAT_ACK (1 << 10) # define RADEON_SW_INT_FIRE (1 << 26) # define RADEON_SW_INT_TEST (1 << 25) # define RADEON_SW_INT_TEST_ACK (1 << 25) @@ -1051,20 +1060,25 @@ /* Multimedia I2C bus */ #define RADEON_I2C_CNTL_0 0x0090 -#define RADEON_I2C_DONE (1<<0) -#define RADEON_I2C_NACK (1<<1) -#define RADEON_I2C_HALT (1<<2) -#define RADEON_I2C_SOFT_RST (1<<5) -#define RADEON_I2C_DRIVE_EN (1<<6) -#define RADEON_I2C_DRIVE_SEL (1<<7) -#define RADEON_I2C_START (1<<8) -#define RADEON_I2C_STOP (1<<9) -#define RADEON_I2C_RECEIVE (1<<10) -#define RADEON_I2C_ABORT (1<<11) -#define RADEON_I2C_GO (1<<12) +#define RADEON_I2C_DONE (1 << 0) +#define RADEON_I2C_NACK (1 << 1) +#define RADEON_I2C_HALT (1 << 2) +#define RADEON_I2C_SOFT_RST (1 << 5) +#define RADEON_I2C_DRIVE_EN (1 << 6) +#define RADEON_I2C_DRIVE_SEL (1 << 7) +#define RADEON_I2C_START (1 << 8) +#define RADEON_I2C_STOP (1 << 9) +#define RADEON_I2C_RECEIVE (1 << 10) +#define RADEON_I2C_ABORT (1 << 11) +#define RADEON_I2C_GO (1 << 12) +#define RADEON_I2C_PRESCALE_SHIFT 16 #define RADEON_I2C_CNTL_1 0x0094 -#define RADEON_I2C_SEL (1<<16) -#define RADEON_I2C_EN (1<<17) +#define RADEON_I2C_DATA_COUNT_SHIFT 0 +#define RADEON_I2C_ADDR_COUNT_SHIFT 4 +#define RADEON_I2C_INTRA_BYTE_DELAY_SHIFT 8 +#define RADEON_I2C_SEL (1 << 16) +#define RADEON_I2C_EN (1 << 17) +#define RADEON_I2C_TIME_LIMIT_SHIFT 24 #define RADEON_I2C_DATA 0x0098 #define RADEON_DVI_I2C_CNTL_0 0x02e0 @@ -1072,7 +1086,7 @@ # define R200_SEL_DDC1 0 /* 0x60 - VGA_DDC */ # define R200_SEL_DDC2 1 /* 0x64 - DVI_DDC */ # define R200_SEL_DDC3 2 /* 0x68 - MONID_DDC */ -#define RADEON_DVI_I2C_CNTL_1 0x02e4 /* ? */ +#define RADEON_DVI_I2C_CNTL_1 0x02e4 #define RADEON_DVI_I2C_DATA 0x02e8 #define RADEON_INTERRUPT_LINE 0x0f3c /* PCI */ @@ -1143,15 +1157,16 @@ # define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1 << 13) # define RADEON_MC_MCLK_DYN_ENABLE (1 << 14) # define RADEON_IO_MCLK_DYN_ENABLE (1 << 15) -#define RADEON_LCD_GPIO_MASK 0x01a0 -#define RADEON_GPIOPAD_EN 0x01a0 -#define RADEON_LCD_GPIO_Y_REG 0x01a4 -#define RADEON_MDGPIO_A_REG 0x01ac -#define RADEON_MDGPIO_EN_REG 0x01b0 -#define RADEON_MDGPIO_MASK 0x0198 + #define RADEON_GPIOPAD_MASK 0x0198 #define RADEON_GPIOPAD_A 0x019c -#define RADEON_MDGPIO_Y_REG 0x01b4 +#define RADEON_GPIOPAD_EN 0x01a0 +#define RADEON_GPIOPAD_Y 0x01a4 +#define RADEON_MDGPIO_MASK 0x01a8 +#define RADEON_MDGPIO_A 0x01ac +#define RADEON_MDGPIO_EN 0x01b0 +#define RADEON_MDGPIO_Y 0x01b4 + #define RADEON_MEM_ADDR_CONFIG 0x0148 #define RADEON_MEM_BASE 0x0f10 /* PCI */ #define RADEON_MEM_CNTL 0x0140 @@ -1360,6 +1375,9 @@ #define RADEON_OVR_CLR 0x0230 #define RADEON_OVR_WID_LEFT_RIGHT 0x0234 #define RADEON_OVR_WID_TOP_BOTTOM 0x0238 +#define RADEON_OVR2_CLR 0x0330 +#define RADEON_OVR2_WID_LEFT_RIGHT 0x0334 +#define RADEON_OVR2_WID_TOP_BOTTOM 0x0338 /* first capture unit */ diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 747b4bffb84bab74fd52261df67c409019b78a9b..4d12b2d17b4d8b6b3d8eeef811209c742e23ec2d 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -165,19 +165,24 @@ int radeon_ib_pool_init(struct radeon_device *rdev) return 0; /* Allocate 1M object buffer */ INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs); - r = radeon_object_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024, - true, RADEON_GEM_DOMAIN_GTT, - false, &rdev->ib_pool.robj); + r = radeon_bo_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024, + true, RADEON_GEM_DOMAIN_GTT, + &rdev->ib_pool.robj); if (r) { DRM_ERROR("radeon: failed to ib pool (%d).\n", r); return r; } - r = radeon_object_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_GTT, &gpu_addr); + r = radeon_bo_reserve(rdev->ib_pool.robj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_GTT, &gpu_addr); if (r) { + radeon_bo_unreserve(rdev->ib_pool.robj); DRM_ERROR("radeon: failed to pin ib pool (%d).\n", r); return r; } - r = radeon_object_kmap(rdev->ib_pool.robj, &ptr); + r = radeon_bo_kmap(rdev->ib_pool.robj, &ptr); + radeon_bo_unreserve(rdev->ib_pool.robj); if (r) { DRM_ERROR("radeon: failed to map ib poll (%d).\n", r); return r; @@ -203,14 +208,21 @@ int radeon_ib_pool_init(struct radeon_device *rdev) void radeon_ib_pool_fini(struct radeon_device *rdev) { + int r; + if (!rdev->ib_pool.ready) { return; } mutex_lock(&rdev->ib_pool.mutex); bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE); if (rdev->ib_pool.robj) { - radeon_object_kunmap(rdev->ib_pool.robj); - radeon_object_unref(&rdev->ib_pool.robj); + r = radeon_bo_reserve(rdev->ib_pool.robj, false); + if (likely(r == 0)) { + radeon_bo_kunmap(rdev->ib_pool.robj); + radeon_bo_unpin(rdev->ib_pool.robj); + radeon_bo_unreserve(rdev->ib_pool.robj); + } + radeon_bo_unref(&rdev->ib_pool.robj); rdev->ib_pool.robj = NULL; } mutex_unlock(&rdev->ib_pool.mutex); @@ -288,29 +300,28 @@ int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size) rdev->cp.ring_size = ring_size; /* Allocate ring buffer */ if (rdev->cp.ring_obj == NULL) { - r = radeon_object_create(rdev, NULL, rdev->cp.ring_size, - true, - RADEON_GEM_DOMAIN_GTT, - false, - &rdev->cp.ring_obj); + r = radeon_bo_create(rdev, NULL, rdev->cp.ring_size, true, + RADEON_GEM_DOMAIN_GTT, + &rdev->cp.ring_obj); if (r) { - DRM_ERROR("radeon: failed to create ring buffer (%d).\n", r); - mutex_unlock(&rdev->cp.mutex); + dev_err(rdev->dev, "(%d) ring create failed\n", r); return r; } - r = radeon_object_pin(rdev->cp.ring_obj, - RADEON_GEM_DOMAIN_GTT, - &rdev->cp.gpu_addr); + r = radeon_bo_reserve(rdev->cp.ring_obj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->cp.ring_obj, RADEON_GEM_DOMAIN_GTT, + &rdev->cp.gpu_addr); if (r) { - DRM_ERROR("radeon: failed to pin ring buffer (%d).\n", r); - mutex_unlock(&rdev->cp.mutex); + radeon_bo_unreserve(rdev->cp.ring_obj); + dev_err(rdev->dev, "(%d) ring pin failed\n", r); return r; } - r = radeon_object_kmap(rdev->cp.ring_obj, + r = radeon_bo_kmap(rdev->cp.ring_obj, (void **)&rdev->cp.ring); + radeon_bo_unreserve(rdev->cp.ring_obj); if (r) { - DRM_ERROR("radeon: failed to map ring buffer (%d).\n", r); - mutex_unlock(&rdev->cp.mutex); + dev_err(rdev->dev, "(%d) ring map failed\n", r); return r; } } @@ -321,11 +332,17 @@ int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size) void radeon_ring_fini(struct radeon_device *rdev) { + int r; + mutex_lock(&rdev->cp.mutex); if (rdev->cp.ring_obj) { - radeon_object_kunmap(rdev->cp.ring_obj); - radeon_object_unpin(rdev->cp.ring_obj); - radeon_object_unref(&rdev->cp.ring_obj); + r = radeon_bo_reserve(rdev->cp.ring_obj, false); + if (likely(r == 0)) { + radeon_bo_kunmap(rdev->cp.ring_obj); + radeon_bo_unpin(rdev->cp.ring_obj); + radeon_bo_unreserve(rdev->cp.ring_obj); + } + radeon_bo_unref(&rdev->cp.ring_obj); rdev->cp.ring = NULL; rdev->cp.ring_obj = NULL; } diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index f8a465d9a1cf0eec8878cc151c70ad16702d05b3..391c973ec4dbb7ef3c83bdfd3b757ff8b1ecb8b4 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c @@ -30,8 +30,8 @@ /* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */ void radeon_test_moves(struct radeon_device *rdev) { - struct radeon_object *vram_obj = NULL; - struct radeon_object **gtt_obj = NULL; + struct radeon_bo *vram_obj = NULL; + struct radeon_bo **gtt_obj = NULL; struct radeon_fence *fence = NULL; uint64_t gtt_addr, vram_addr; unsigned i, n, size; @@ -52,38 +52,42 @@ void radeon_test_moves(struct radeon_device *rdev) goto out_cleanup; } - r = radeon_object_create(rdev, NULL, size, true, RADEON_GEM_DOMAIN_VRAM, - false, &vram_obj); + r = radeon_bo_create(rdev, NULL, size, true, RADEON_GEM_DOMAIN_VRAM, + &vram_obj); if (r) { DRM_ERROR("Failed to create VRAM object\n"); goto out_cleanup; } - - r = radeon_object_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr); + r = radeon_bo_reserve(vram_obj, false); + if (unlikely(r != 0)) + goto out_cleanup; + r = radeon_bo_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr); if (r) { DRM_ERROR("Failed to pin VRAM object\n"); goto out_cleanup; } - for (i = 0; i < n; i++) { void *gtt_map, *vram_map; void **gtt_start, **gtt_end; void **vram_start, **vram_end; - r = radeon_object_create(rdev, NULL, size, true, - RADEON_GEM_DOMAIN_GTT, false, gtt_obj + i); + r = radeon_bo_create(rdev, NULL, size, true, + RADEON_GEM_DOMAIN_GTT, gtt_obj + i); if (r) { DRM_ERROR("Failed to create GTT object %d\n", i); goto out_cleanup; } - r = radeon_object_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, >t_addr); + r = radeon_bo_reserve(gtt_obj[i], false); + if (unlikely(r != 0)) + goto out_cleanup; + r = radeon_bo_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, >t_addr); if (r) { DRM_ERROR("Failed to pin GTT object %d\n", i); goto out_cleanup; } - r = radeon_object_kmap(gtt_obj[i], >t_map); + r = radeon_bo_kmap(gtt_obj[i], >t_map); if (r) { DRM_ERROR("Failed to map GTT object %d\n", i); goto out_cleanup; @@ -94,7 +98,7 @@ void radeon_test_moves(struct radeon_device *rdev) gtt_start++) *gtt_start = gtt_start; - radeon_object_kunmap(gtt_obj[i]); + radeon_bo_kunmap(gtt_obj[i]); r = radeon_fence_create(rdev, &fence); if (r) { @@ -116,7 +120,7 @@ void radeon_test_moves(struct radeon_device *rdev) radeon_fence_unref(&fence); - r = radeon_object_kmap(vram_obj, &vram_map); + r = radeon_bo_kmap(vram_obj, &vram_map); if (r) { DRM_ERROR("Failed to map VRAM object after copy %d\n", i); goto out_cleanup; @@ -131,13 +135,13 @@ void radeon_test_moves(struct radeon_device *rdev) "expected 0x%p (GTT map 0x%p-0x%p)\n", i, *vram_start, gtt_start, gtt_map, gtt_end); - radeon_object_kunmap(vram_obj); + radeon_bo_kunmap(vram_obj); goto out_cleanup; } *vram_start = vram_start; } - radeon_object_kunmap(vram_obj); + radeon_bo_kunmap(vram_obj); r = radeon_fence_create(rdev, &fence); if (r) { @@ -159,7 +163,7 @@ void radeon_test_moves(struct radeon_device *rdev) radeon_fence_unref(&fence); - r = radeon_object_kmap(gtt_obj[i], >t_map); + r = radeon_bo_kmap(gtt_obj[i], >t_map); if (r) { DRM_ERROR("Failed to map GTT object after copy %d\n", i); goto out_cleanup; @@ -174,12 +178,12 @@ void radeon_test_moves(struct radeon_device *rdev) "expected 0x%p (VRAM map 0x%p-0x%p)\n", i, *gtt_start, vram_start, vram_map, vram_end); - radeon_object_kunmap(gtt_obj[i]); + radeon_bo_kunmap(gtt_obj[i]); goto out_cleanup; } } - radeon_object_kunmap(gtt_obj[i]); + radeon_bo_kunmap(gtt_obj[i]); DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n", gtt_addr - rdev->mc.gtt_location); @@ -187,14 +191,20 @@ void radeon_test_moves(struct radeon_device *rdev) out_cleanup: if (vram_obj) { - radeon_object_unpin(vram_obj); - radeon_object_unref(&vram_obj); + if (radeon_bo_is_reserved(vram_obj)) { + radeon_bo_unpin(vram_obj); + radeon_bo_unreserve(vram_obj); + } + radeon_bo_unref(&vram_obj); } if (gtt_obj) { for (i = 0; i < n; i++) { if (gtt_obj[i]) { - radeon_object_unpin(gtt_obj[i]); - radeon_object_unref(>t_obj[i]); + if (radeon_bo_is_reserved(gtt_obj[i])) { + radeon_bo_unpin(gtt_obj[i]); + radeon_bo_unreserve(gtt_obj[i]); + } + radeon_bo_unref(>t_obj[i]); } } kfree(gtt_obj); @@ -206,4 +216,3 @@ out_cleanup: printk(KERN_WARNING "Error while testing BO move.\n"); } } - diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index eda4ade24c3ab640a0a72d486590e6432870450b..5a19d529d1c0df9a52571b1423bcbc66b8847aca 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -150,7 +150,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, man->default_caching = TTM_PL_FLAG_CACHED; break; case TTM_PL_TT: - man->gpu_offset = 0; + man->gpu_offset = rdev->mc.gtt_location; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA; @@ -180,7 +180,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, break; case TTM_PL_VRAM: /* "On-card" video ram */ - man->gpu_offset = 0; + man->gpu_offset = rdev->mc.vram_location; man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_NEEDS_IOREMAP | TTM_MEMTYPE_FLAG_MAPPABLE; @@ -197,16 +197,19 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, return 0; } -static uint32_t radeon_evict_flags(struct ttm_buffer_object *bo) +static void radeon_evict_flags(struct ttm_buffer_object *bo, + struct ttm_placement *placement) { - uint32_t cur_placement = bo->mem.placement & ~TTM_PL_MASK_MEMTYPE; - + struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo); switch (bo->mem.mem_type) { + case TTM_PL_VRAM: + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); + break; + case TTM_PL_TT: default: - return (cur_placement & ~TTM_PL_MASK_CACHING) | - TTM_PL_FLAG_SYSTEM | - TTM_PL_FLAG_CACHED; + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU); } + *placement = rbo->placement; } static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp) @@ -283,14 +286,21 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo, struct radeon_device *rdev; struct ttm_mem_reg *old_mem = &bo->mem; struct ttm_mem_reg tmp_mem; - uint32_t proposed_placement; + u32 placements; + struct ttm_placement placement; int r; rdev = radeon_get_rdev(bo->bdev); tmp_mem = *new_mem; tmp_mem.mm_node = NULL; - proposed_placement = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; - r = ttm_bo_mem_space(bo, proposed_placement, &tmp_mem, + placement.fpfn = 0; + placement.lpfn = 0; + placement.num_placement = 1; + placement.placement = &placements; + placement.num_busy_placement = 1; + placement.busy_placement = &placements; + placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; + r = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible, no_wait); if (unlikely(r)) { return r; @@ -329,15 +339,21 @@ static int radeon_move_ram_vram(struct ttm_buffer_object *bo, struct radeon_device *rdev; struct ttm_mem_reg *old_mem = &bo->mem; struct ttm_mem_reg tmp_mem; - uint32_t proposed_flags; + struct ttm_placement placement; + u32 placements; int r; rdev = radeon_get_rdev(bo->bdev); tmp_mem = *new_mem; tmp_mem.mm_node = NULL; - proposed_flags = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; - r = ttm_bo_mem_space(bo, proposed_flags, &tmp_mem, - interruptible, no_wait); + placement.fpfn = 0; + placement.lpfn = 0; + placement.num_placement = 1; + placement.placement = &placements; + placement.num_busy_placement = 1; + placement.busy_placement = &placements; + placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; + r = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible, no_wait); if (unlikely(r)) { return r; } @@ -407,18 +423,6 @@ memcpy: return r; } -const uint32_t radeon_mem_prios[] = { - TTM_PL_VRAM, - TTM_PL_TT, - TTM_PL_SYSTEM, -}; - -const uint32_t radeon_busy_prios[] = { - TTM_PL_TT, - TTM_PL_VRAM, - TTM_PL_SYSTEM, -}; - static int radeon_sync_obj_wait(void *sync_obj, void *sync_arg, bool lazy, bool interruptible) { @@ -446,10 +450,6 @@ static bool radeon_sync_obj_signaled(void *sync_obj, void *sync_arg) } static struct ttm_bo_driver radeon_bo_driver = { - .mem_type_prio = radeon_mem_prios, - .mem_busy_prio = radeon_busy_prios, - .num_mem_type_prio = ARRAY_SIZE(radeon_mem_prios), - .num_mem_busy_prio = ARRAY_SIZE(radeon_busy_prios), .create_ttm_backend_entry = &radeon_create_ttm_backend_entry, .invalidate_caches = &radeon_invalidate_caches, .init_mem_type = &radeon_init_mem_type, @@ -482,27 +482,31 @@ int radeon_ttm_init(struct radeon_device *rdev) DRM_ERROR("failed initializing buffer object driver(%d).\n", r); return r; } - r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, 0, - ((rdev->mc.real_vram_size) >> PAGE_SHIFT)); + r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, + rdev->mc.real_vram_size >> PAGE_SHIFT); if (r) { DRM_ERROR("Failed initializing VRAM heap.\n"); return r; } - r = radeon_object_create(rdev, NULL, 256 * 1024, true, - RADEON_GEM_DOMAIN_VRAM, false, - &rdev->stollen_vga_memory); + r = radeon_bo_create(rdev, NULL, 256 * 1024, true, + RADEON_GEM_DOMAIN_VRAM, + &rdev->stollen_vga_memory); if (r) { return r; } - r = radeon_object_pin(rdev->stollen_vga_memory, RADEON_GEM_DOMAIN_VRAM, NULL); + r = radeon_bo_reserve(rdev->stollen_vga_memory, false); + if (r) + return r; + r = radeon_bo_pin(rdev->stollen_vga_memory, RADEON_GEM_DOMAIN_VRAM, NULL); + radeon_bo_unreserve(rdev->stollen_vga_memory); if (r) { - radeon_object_unref(&rdev->stollen_vga_memory); + radeon_bo_unref(&rdev->stollen_vga_memory); return r; } DRM_INFO("radeon: %uM of VRAM memory ready\n", (unsigned)rdev->mc.real_vram_size / (1024 * 1024)); - r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, 0, - ((rdev->mc.gtt_size) >> PAGE_SHIFT)); + r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, + rdev->mc.gtt_size >> PAGE_SHIFT); if (r) { DRM_ERROR("Failed initializing GTT heap.\n"); return r; @@ -523,9 +527,15 @@ int radeon_ttm_init(struct radeon_device *rdev) void radeon_ttm_fini(struct radeon_device *rdev) { + int r; + if (rdev->stollen_vga_memory) { - radeon_object_unpin(rdev->stollen_vga_memory); - radeon_object_unref(&rdev->stollen_vga_memory); + r = radeon_bo_reserve(rdev->stollen_vga_memory, false); + if (r == 0) { + radeon_bo_unpin(rdev->stollen_vga_memory); + radeon_bo_unreserve(rdev->stollen_vga_memory); + } + radeon_bo_unref(&rdev->stollen_vga_memory); } ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_VRAM); ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_TT); diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index ca037160a58267d78e5108f0dba58cad5e51045f..c1fcdddb6be68e7b4aa0ad56b5050679efb41bff 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -352,7 +352,7 @@ static int rs400_mc_init(struct radeon_device *rdev) u32 tmp; /* Setup GPU memory space */ - tmp = G_00015C_MC_FB_START(RREG32(R_00015C_NB_TOM)); + tmp = RREG32(R_00015C_NB_TOM); rdev->mc.vram_location = G_00015C_MC_FB_START(tmp) << 16; rdev->mc.gtt_location = 0xFFFFFFFFUL; r = radeon_mc_setup(rdev); @@ -387,13 +387,13 @@ static int rs400_startup(struct radeon_device *rdev) r300_clock_startup(rdev); /* Initialize GPU configuration (# pipes, ...) */ rs400_gpu_init(rdev); + r100_enable_bm(rdev); /* Initialize GART (initialize after TTM so we can allocate * memory through TTM but finalize after TTM) */ r = rs400_gart_enable(rdev); if (r) return r; /* Enable IRQ */ - rdev->irq.sw_int = true; r100_irq_set(rdev); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); @@ -430,6 +430,8 @@ int rs400_resume(struct radeon_device *rdev) radeon_combios_asic_init(rdev->ddev); /* Resume clock after posting */ r300_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); return rs400_startup(rdev); } @@ -452,7 +454,7 @@ void rs400_fini(struct radeon_device *rdev) rs400_gart_fini(rdev); radeon_irq_kms_fini(rdev); radeon_fence_driver_fini(rdev); - radeon_object_fini(rdev); + radeon_bo_fini(rdev); radeon_atombios_fini(rdev); kfree(rdev->bios); rdev->bios = NULL; @@ -490,10 +492,9 @@ int rs400_init(struct radeon_device *rdev) RREG32(R_0007C0_CP_STAT)); } /* check if cards are posted or not */ - if (!radeon_card_posted(rdev) && rdev->bios) { - DRM_INFO("GPU not posted. posting now...\n"); - radeon_combios_asic_init(rdev->ddev); - } + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; + /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); /* Get vram informations */ @@ -510,7 +511,7 @@ int rs400_init(struct radeon_device *rdev) if (r) return r; /* Memory manager */ - r = radeon_object_init(rdev); + r = radeon_bo_init(rdev); if (r) return r; r = rs400_gart_init(rdev); diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 5f117cd8736a6e6b4a0f9606fcc1e02612c43286..4f8ea4260572d83ad562b034d4550b8214c4cd01 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -45,6 +45,122 @@ void rs600_gpu_init(struct radeon_device *rdev); int rs600_mc_wait_for_idle(struct radeon_device *rdev); +int rs600_mc_init(struct radeon_device *rdev) +{ + /* read back the MC value from the hw */ + int r; + u32 tmp; + + /* Setup GPU memory space */ + tmp = RREG32_MC(R_000004_MC_FB_LOCATION); + rdev->mc.vram_location = G_000004_MC_FB_START(tmp) << 16; + rdev->mc.gtt_location = 0xffffffffUL; + r = radeon_mc_setup(rdev); + if (r) + return r; + return 0; +} + +/* hpd for digital panel detect/disconnect */ +bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) +{ + u32 tmp; + bool connected = false; + + switch (hpd) { + case RADEON_HPD_1: + tmp = RREG32(R_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS); + if (G_007D04_DC_HOT_PLUG_DETECT1_SENSE(tmp)) + connected = true; + break; + case RADEON_HPD_2: + tmp = RREG32(R_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS); + if (G_007D14_DC_HOT_PLUG_DETECT2_SENSE(tmp)) + connected = true; + break; + default: + break; + } + return connected; +} + +void rs600_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd) +{ + u32 tmp; + bool connected = rs600_hpd_sense(rdev, hpd); + + switch (hpd) { + case RADEON_HPD_1: + tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL); + if (connected) + tmp &= ~S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(1); + else + tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(1); + WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); + break; + case RADEON_HPD_2: + tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL); + if (connected) + tmp &= ~S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(1); + else + tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(1); + WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); + break; + default: + break; + } +} + +void rs600_hpd_init(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, + S_007D00_DC_HOT_PLUG_DETECT1_EN(1)); + rdev->irq.hpd[0] = true; + break; + case RADEON_HPD_2: + WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, + S_007D10_DC_HOT_PLUG_DETECT2_EN(1)); + rdev->irq.hpd[1] = true; + break; + default: + break; + } + } + rs600_irq_set(rdev); +} + +void rs600_hpd_fini(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, + S_007D00_DC_HOT_PLUG_DETECT1_EN(0)); + rdev->irq.hpd[0] = false; + break; + case RADEON_HPD_2: + WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, + S_007D10_DC_HOT_PLUG_DETECT2_EN(0)); + rdev->irq.hpd[1] = false; + break; + default: + break; + } + } +} + /* * GART. */ @@ -100,40 +216,40 @@ int rs600_gart_enable(struct radeon_device *rdev) WREG32(R_00004C_BUS_CNTL, tmp); /* FIXME: setup default page */ WREG32_MC(R_000100_MC_PT0_CNTL, - (S_000100_EFFECTIVE_L2_CACHE_SIZE(6) | - S_000100_EFFECTIVE_L2_QUEUE_SIZE(6))); + (S_000100_EFFECTIVE_L2_CACHE_SIZE(6) | + S_000100_EFFECTIVE_L2_QUEUE_SIZE(6))); + for (i = 0; i < 19; i++) { WREG32_MC(R_00016C_MC_PT0_CLIENT0_CNTL + i, - S_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE(1) | - S_00016C_SYSTEM_ACCESS_MODE_MASK( - V_00016C_SYSTEM_ACCESS_MODE_IN_SYS) | - S_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS( - V_00016C_SYSTEM_APERTURE_UNMAPPED_DEFAULT_PAGE) | - S_00016C_EFFECTIVE_L1_CACHE_SIZE(1) | - S_00016C_ENABLE_FRAGMENT_PROCESSING(1) | - S_00016C_EFFECTIVE_L1_QUEUE_SIZE(1)); + S_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE(1) | + S_00016C_SYSTEM_ACCESS_MODE_MASK( + V_00016C_SYSTEM_ACCESS_MODE_NOT_IN_SYS) | + S_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS( + V_00016C_SYSTEM_APERTURE_UNMAPPED_PASSTHROUGH) | + S_00016C_EFFECTIVE_L1_CACHE_SIZE(3) | + S_00016C_ENABLE_FRAGMENT_PROCESSING(1) | + S_00016C_EFFECTIVE_L1_QUEUE_SIZE(3)); } - - /* System context map to GART space */ - WREG32_MC(R_000112_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.gtt_start); - WREG32_MC(R_000114_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.gtt_end); - /* enable first context */ - WREG32_MC(R_00013C_MC_PT0_CONTEXT0_FLAT_START_ADDR, rdev->mc.gtt_start); - WREG32_MC(R_00014C_MC_PT0_CONTEXT0_FLAT_END_ADDR, rdev->mc.gtt_end); WREG32_MC(R_000102_MC_PT0_CONTEXT0_CNTL, - S_000102_ENABLE_PAGE_TABLE(1) | - S_000102_PAGE_TABLE_DEPTH(V_000102_PAGE_TABLE_FLAT)); + S_000102_ENABLE_PAGE_TABLE(1) | + S_000102_PAGE_TABLE_DEPTH(V_000102_PAGE_TABLE_FLAT)); + /* disable all other contexts */ - for (i = 1; i < 8; i++) { + for (i = 1; i < 8; i++) WREG32_MC(R_000102_MC_PT0_CONTEXT0_CNTL + i, 0); - } /* setup the page table */ WREG32_MC(R_00012C_MC_PT0_CONTEXT0_FLAT_BASE_ADDR, - rdev->gart.table_addr); + rdev->gart.table_addr); + WREG32_MC(R_00013C_MC_PT0_CONTEXT0_FLAT_START_ADDR, rdev->mc.gtt_start); + WREG32_MC(R_00014C_MC_PT0_CONTEXT0_FLAT_END_ADDR, rdev->mc.gtt_end); WREG32_MC(R_00011C_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0); + /* System context maps to VRAM space */ + WREG32_MC(R_000112_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start); + WREG32_MC(R_000114_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end); + /* enable page tables */ tmp = RREG32_MC(R_000100_MC_PT0_CNTL); WREG32_MC(R_000100_MC_PT0_CNTL, (tmp | S_000100_ENABLE_PT(1))); @@ -146,15 +262,20 @@ int rs600_gart_enable(struct radeon_device *rdev) void rs600_gart_disable(struct radeon_device *rdev) { - uint32_t tmp; + u32 tmp; + int r; /* FIXME: disable out of gart access */ WREG32_MC(R_000100_MC_PT0_CNTL, 0); tmp = RREG32_MC(R_000009_MC_CNTL1); WREG32_MC(R_000009_MC_CNTL1, tmp & C_000009_ENABLE_PAGE_TABLES); if (rdev->gart.table.vram.robj) { - radeon_object_kunmap(rdev->gart.table.vram.robj); - radeon_object_unpin(rdev->gart.table.vram.robj); + r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); + if (r == 0) { + radeon_bo_kunmap(rdev->gart.table.vram.robj); + radeon_bo_unpin(rdev->gart.table.vram.robj); + radeon_bo_unreserve(rdev->gart.table.vram.robj); + } } } @@ -189,6 +310,10 @@ int rs600_irq_set(struct radeon_device *rdev) { uint32_t tmp = 0; uint32_t mode_int = 0; + u32 hpd1 = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL) & + ~S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1); + u32 hpd2 = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL) & + ~S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1); if (rdev->irq.sw_int) { tmp |= S_000040_SW_INT_EN(1); @@ -199,8 +324,16 @@ int rs600_irq_set(struct radeon_device *rdev) if (rdev->irq.crtc_vblank_int[1]) { mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1); } + if (rdev->irq.hpd[0]) { + hpd1 |= S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1); + } + if (rdev->irq.hpd[1]) { + hpd2 |= S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1); + } WREG32(R_000040_GEN_INT_CNTL, tmp); WREG32(R_006540_DxMODE_INT_MASK, mode_int); + WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); + WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); return 0; } @@ -208,6 +341,7 @@ static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_ { uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS); uint32_t irq_mask = ~C_000044_SW_INT; + u32 tmp; if (G_000044_DISPLAY_INT_STAT(irqs)) { *r500_disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS); @@ -219,6 +353,16 @@ static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_ WREG32(R_006D34_D2MODE_VBLANK_STATUS, S_006D34_D2MODE_VBLANK_ACK(1)); } + if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(*r500_disp_int)) { + tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL); + tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(1); + WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); + } + if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(*r500_disp_int)) { + tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL); + tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(1); + WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); + } } else { *r500_disp_int = 0; } @@ -244,6 +388,7 @@ int rs600_irq_process(struct radeon_device *rdev) { uint32_t status, msi_rearm; uint32_t r500_disp_int; + bool queue_hotplug = false; status = rs600_irq_ack(rdev, &r500_disp_int); if (!status && !r500_disp_int) { @@ -258,8 +403,18 @@ int rs600_irq_process(struct radeon_device *rdev) drm_handle_vblank(rdev->ddev, 0); if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int)) drm_handle_vblank(rdev->ddev, 1); + if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(r500_disp_int)) { + queue_hotplug = true; + DRM_DEBUG("HPD1\n"); + } + if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(r500_disp_int)) { + queue_hotplug = true; + DRM_DEBUG("HPD2\n"); + } status = rs600_irq_ack(rdev, &r500_disp_int); } + if (queue_hotplug) + queue_work(rdev->wq, &rdev->hotplug_work); if (rdev->msi_enabled) { switch (rdev->family) { case CHIP_RS600: @@ -301,9 +456,7 @@ int rs600_mc_wait_for_idle(struct radeon_device *rdev) void rs600_gpu_init(struct radeon_device *rdev) { - /* FIXME: HDP same place on rs600 ? */ r100_hdp_reset(rdev); - /* FIXME: is this correct ? */ r420_pipes_init(rdev); /* Wait for mc idle */ if (rs600_mc_wait_for_idle(rdev)) @@ -312,9 +465,20 @@ void rs600_gpu_init(struct radeon_device *rdev) void rs600_vram_info(struct radeon_device *rdev) { - /* FIXME: to do or is these values sane ? */ rdev->mc.vram_is_ddr = true; rdev->mc.vram_width = 128; + + rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); + rdev->mc.mc_vram_size = rdev->mc.real_vram_size; + + rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); + rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + + if (rdev->mc.mc_vram_size > rdev->mc.aper_size) + rdev->mc.mc_vram_size = rdev->mc.aper_size; + + if (rdev->mc.real_vram_size > rdev->mc.aper_size) + rdev->mc.real_vram_size = rdev->mc.aper_size; } void rs600_bandwidth_update(struct radeon_device *rdev) @@ -388,7 +552,6 @@ static int rs600_startup(struct radeon_device *rdev) if (r) return r; /* Enable IRQ */ - rdev->irq.sw_int = true; rs600_irq_set(rdev); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); @@ -423,6 +586,8 @@ int rs600_resume(struct radeon_device *rdev) atom_asic_init(rdev->mode_info.atom_context); /* Resume clock after posting */ rv515_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); return rs600_startup(rdev); } @@ -445,7 +610,7 @@ void rs600_fini(struct radeon_device *rdev) rs600_gart_fini(rdev); radeon_irq_kms_fini(rdev); radeon_fence_driver_fini(rdev); - radeon_object_fini(rdev); + radeon_bo_fini(rdev); radeon_atombios_fini(rdev); kfree(rdev->bios); rdev->bios = NULL; @@ -482,10 +647,9 @@ int rs600_init(struct radeon_device *rdev) RREG32(R_0007C0_CP_STAT)); } /* check if cards are posted or not */ - if (!radeon_card_posted(rdev) && rdev->bios) { - DRM_INFO("GPU not posted. posting now...\n"); - atom_asic_init(rdev->mode_info.atom_context); - } + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; + /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); /* Initialize power management */ @@ -493,7 +657,7 @@ int rs600_init(struct radeon_device *rdev) /* Get vram informations */ rs600_vram_info(rdev); /* Initialize memory controller (also test AGP) */ - r = r420_mc_init(rdev); + r = rs600_mc_init(rdev); if (r) return r; rs600_debugfs(rdev); @@ -505,7 +669,7 @@ int rs600_init(struct radeon_device *rdev) if (r) return r; /* Memory manager */ - r = radeon_object_init(rdev); + r = radeon_bo_init(rdev); if (r) return r; r = rs600_gart_init(rdev); diff --git a/drivers/gpu/drm/radeon/rs600d.h b/drivers/gpu/drm/radeon/rs600d.h index 81308924859a2ebca4e5e45e889fe43e6f229bb8..c1c8f5885cbbc0727e484c49972e21790b5d3d74 100644 --- a/drivers/gpu/drm/radeon/rs600d.h +++ b/drivers/gpu/drm/radeon/rs600d.h @@ -30,27 +30,12 @@ /* Registers */ #define R_000040_GEN_INT_CNTL 0x000040 -#define S_000040_DISPLAY_INT_STATUS(x) (((x) & 0x1) << 0) -#define G_000040_DISPLAY_INT_STATUS(x) (((x) >> 0) & 0x1) -#define C_000040_DISPLAY_INT_STATUS 0xFFFFFFFE -#define S_000040_DMA_VIPH0_INT_EN(x) (((x) & 0x1) << 12) -#define G_000040_DMA_VIPH0_INT_EN(x) (((x) >> 12) & 0x1) -#define C_000040_DMA_VIPH0_INT_EN 0xFFFFEFFF -#define S_000040_CRTC2_VSYNC(x) (((x) & 0x1) << 6) -#define G_000040_CRTC2_VSYNC(x) (((x) >> 6) & 0x1) -#define C_000040_CRTC2_VSYNC 0xFFFFFFBF -#define S_000040_SNAPSHOT2(x) (((x) & 0x1) << 7) -#define G_000040_SNAPSHOT2(x) (((x) >> 7) & 0x1) -#define C_000040_SNAPSHOT2 0xFFFFFF7F -#define S_000040_CRTC2_VBLANK(x) (((x) & 0x1) << 9) -#define G_000040_CRTC2_VBLANK(x) (((x) >> 9) & 0x1) -#define C_000040_CRTC2_VBLANK 0xFFFFFDFF -#define S_000040_FP2_DETECT(x) (((x) & 0x1) << 10) -#define G_000040_FP2_DETECT(x) (((x) >> 10) & 0x1) -#define C_000040_FP2_DETECT 0xFFFFFBFF -#define S_000040_VSYNC_DIFF_OVER_LIMIT(x) (((x) & 0x1) << 11) -#define G_000040_VSYNC_DIFF_OVER_LIMIT(x) (((x) >> 11) & 0x1) -#define C_000040_VSYNC_DIFF_OVER_LIMIT 0xFFFFF7FF +#define S_000040_SCRATCH_INT_MASK(x) (((x) & 0x1) << 18) +#define G_000040_SCRATCH_INT_MASK(x) (((x) >> 18) & 0x1) +#define C_000040_SCRATCH_INT_MASK 0xFFFBFFFF +#define S_000040_GUI_IDLE_MASK(x) (((x) & 0x1) << 19) +#define G_000040_GUI_IDLE_MASK(x) (((x) >> 19) & 0x1) +#define C_000040_GUI_IDLE_MASK 0xFFF7FFFF #define S_000040_DMA_VIPH1_INT_EN(x) (((x) & 0x1) << 13) #define G_000040_DMA_VIPH1_INT_EN(x) (((x) >> 13) & 0x1) #define C_000040_DMA_VIPH1_INT_EN 0xFFFFDFFF @@ -370,7 +355,90 @@ #define S_007EDC_LB_D2_VBLANK_INTERRUPT(x) (((x) & 0x1) << 5) #define G_007EDC_LB_D2_VBLANK_INTERRUPT(x) (((x) >> 5) & 0x1) #define C_007EDC_LB_D2_VBLANK_INTERRUPT 0xFFFFFFDF - +#define S_007EDC_DACA_AUTODETECT_INTERRUPT(x) (((x) & 0x1) << 16) +#define G_007EDC_DACA_AUTODETECT_INTERRUPT(x) (((x) >> 16) & 0x1) +#define C_007EDC_DACA_AUTODETECT_INTERRUPT 0xFFFEFFFF +#define S_007EDC_DACB_AUTODETECT_INTERRUPT(x) (((x) & 0x1) << 17) +#define G_007EDC_DACB_AUTODETECT_INTERRUPT(x) (((x) >> 17) & 0x1) +#define C_007EDC_DACB_AUTODETECT_INTERRUPT 0xFFFDFFFF +#define S_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(x) (((x) & 0x1) << 18) +#define G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(x) (((x) >> 18) & 0x1) +#define C_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT 0xFFFBFFFF +#define S_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(x) (((x) & 0x1) << 19) +#define G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(x) (((x) >> 19) & 0x1) +#define C_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT 0xFFF7FFFF +#define R_007828_DACA_AUTODETECT_CONTROL 0x007828 +#define S_007828_DACA_AUTODETECT_MODE(x) (((x) & 0x3) << 0) +#define G_007828_DACA_AUTODETECT_MODE(x) (((x) >> 0) & 0x3) +#define C_007828_DACA_AUTODETECT_MODE 0xFFFFFFFC +#define S_007828_DACA_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) & 0xff) << 8) +#define G_007828_DACA_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) >> 8) & 0xff) +#define C_007828_DACA_AUTODETECT_FRAME_TIME_COUNTER 0xFFFF00FF +#define S_007828_DACA_AUTODETECT_CHECK_MASK(x) (((x) & 0x3) << 16) +#define G_007828_DACA_AUTODETECT_CHECK_MASK(x) (((x) >> 16) & 0x3) +#define C_007828_DACA_AUTODETECT_CHECK_MASK 0xFFFCFFFF +#define R_007838_DACA_AUTODETECT_INT_CONTROL 0x007838 +#define S_007838_DACA_AUTODETECT_ACK(x) (((x) & 0x1) << 0) +#define C_007838_DACA_DACA_AUTODETECT_ACK 0xFFFFFFFE +#define S_007838_DACA_AUTODETECT_INT_ENABLE(x) (((x) & 0x1) << 16) +#define G_007838_DACA_AUTODETECT_INT_ENABLE(x) (((x) >> 16) & 0x1) +#define C_007838_DACA_AUTODETECT_INT_ENABLE 0xFFFCFFFF +#define R_007A28_DACB_AUTODETECT_CONTROL 0x007A28 +#define S_007A28_DACB_AUTODETECT_MODE(x) (((x) & 0x3) << 0) +#define G_007A28_DACB_AUTODETECT_MODE(x) (((x) >> 0) & 0x3) +#define C_007A28_DACB_AUTODETECT_MODE 0xFFFFFFFC +#define S_007A28_DACB_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) & 0xff) << 8) +#define G_007A28_DACB_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) >> 8) & 0xff) +#define C_007A28_DACB_AUTODETECT_FRAME_TIME_COUNTER 0xFFFF00FF +#define S_007A28_DACB_AUTODETECT_CHECK_MASK(x) (((x) & 0x3) << 16) +#define G_007A28_DACB_AUTODETECT_CHECK_MASK(x) (((x) >> 16) & 0x3) +#define C_007A28_DACB_AUTODETECT_CHECK_MASK 0xFFFCFFFF +#define R_007A38_DACB_AUTODETECT_INT_CONTROL 0x007A38 +#define S_007A38_DACB_AUTODETECT_ACK(x) (((x) & 0x1) << 0) +#define C_007A38_DACB_DACA_AUTODETECT_ACK 0xFFFFFFFE +#define S_007A38_DACB_AUTODETECT_INT_ENABLE(x) (((x) & 0x1) << 16) +#define G_007A38_DACB_AUTODETECT_INT_ENABLE(x) (((x) >> 16) & 0x1) +#define C_007A38_DACB_AUTODETECT_INT_ENABLE 0xFFFCFFFF +#define R_007D00_DC_HOT_PLUG_DETECT1_CONTROL 0x007D00 +#define S_007D00_DC_HOT_PLUG_DETECT1_EN(x) (((x) & 0x1) << 0) +#define G_007D00_DC_HOT_PLUG_DETECT1_EN(x) (((x) >> 0) & 0x1) +#define C_007D00_DC_HOT_PLUG_DETECT1_EN 0xFFFFFFFE +#define R_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS 0x007D04 +#define S_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS(x) (((x) & 0x1) << 0) +#define G_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS(x) (((x) >> 0) & 0x1) +#define C_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS 0xFFFFFFFE +#define S_007D04_DC_HOT_PLUG_DETECT1_SENSE(x) (((x) & 0x1) << 1) +#define G_007D04_DC_HOT_PLUG_DETECT1_SENSE(x) (((x) >> 1) & 0x1) +#define C_007D04_DC_HOT_PLUG_DETECT1_SENSE 0xFFFFFFFD +#define R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL 0x007D08 +#define S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(x) (((x) & 0x1) << 0) +#define C_007D08_DC_HOT_PLUG_DETECT1_INT_ACK 0xFFFFFFFE +#define S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(x) (((x) & 0x1) << 8) +#define G_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(x) (((x) >> 8) & 0x1) +#define C_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY 0xFFFFFEFF +#define S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(x) (((x) & 0x1) << 16) +#define G_007D08_DC_HOT_PLUG_DETECT1_INT_EN(x) (((x) >> 16) & 0x1) +#define C_007D08_DC_HOT_PLUG_DETECT1_INT_EN 0xFFFEFFFF +#define R_007D10_DC_HOT_PLUG_DETECT2_CONTROL 0x007D10 +#define S_007D10_DC_HOT_PLUG_DETECT2_EN(x) (((x) & 0x1) << 0) +#define G_007D10_DC_HOT_PLUG_DETECT2_EN(x) (((x) >> 0) & 0x1) +#define C_007D10_DC_HOT_PLUG_DETECT2_EN 0xFFFFFFFE +#define R_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS 0x007D14 +#define S_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS(x) (((x) & 0x1) << 0) +#define G_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS(x) (((x) >> 0) & 0x1) +#define C_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS 0xFFFFFFFE +#define S_007D14_DC_HOT_PLUG_DETECT2_SENSE(x) (((x) & 0x1) << 1) +#define G_007D14_DC_HOT_PLUG_DETECT2_SENSE(x) (((x) >> 1) & 0x1) +#define C_007D14_DC_HOT_PLUG_DETECT2_SENSE 0xFFFFFFFD +#define R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL 0x007D18 +#define S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(x) (((x) & 0x1) << 0) +#define C_007D18_DC_HOT_PLUG_DETECT2_INT_ACK 0xFFFFFFFE +#define S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(x) (((x) & 0x1) << 8) +#define G_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(x) (((x) >> 8) & 0x1) +#define C_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY 0xFFFFFEFF +#define S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(x) (((x) & 0x1) << 16) +#define G_007D18_DC_HOT_PLUG_DETECT2_INT_EN(x) (((x) >> 16) & 0x1) +#define C_007D18_DC_HOT_PLUG_DETECT2_INT_EN 0xFFFEFFFF /* MC registers */ #define R_000000_MC_STATUS 0x000000 diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 27547175cf93cbcf79df7f5ab499c87f0b6da208..1e22f52d6039ff67c369b3317a997d0881ac094d 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -131,24 +131,25 @@ void rs690_pm_info(struct radeon_device *rdev) void rs690_vram_info(struct radeon_device *rdev) { - uint32_t tmp; fixed20_12 a; rs400_gart_adjust_size(rdev); - /* DDR for all card after R300 & IGP */ + rdev->mc.vram_is_ddr = true; - /* FIXME: is this correct for RS690/RS740 ? */ - tmp = RREG32(RADEON_MEM_CNTL); - if (tmp & R300_MEM_NUM_CHANNELS_MASK) { - rdev->mc.vram_width = 128; - } else { - rdev->mc.vram_width = 64; - } + rdev->mc.vram_width = 128; + rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); rdev->mc.mc_vram_size = rdev->mc.real_vram_size; rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + + if (rdev->mc.mc_vram_size > rdev->mc.aper_size) + rdev->mc.mc_vram_size = rdev->mc.aper_size; + + if (rdev->mc.real_vram_size > rdev->mc.aper_size) + rdev->mc.real_vram_size = rdev->mc.aper_size; + rs690_pm_info(rdev); /* FIXME: we should enforce default clock in case GPU is not in * default setup @@ -161,6 +162,21 @@ void rs690_vram_info(struct radeon_device *rdev) rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a); } +static int rs690_mc_init(struct radeon_device *rdev) +{ + int r; + u32 tmp; + + /* Setup GPU memory space */ + tmp = RREG32_MC(R_000100_MCCFG_FB_LOCATION); + rdev->mc.vram_location = G_000100_MC_FB_START(tmp) << 16; + rdev->mc.gtt_location = 0xFFFFFFFFUL; + r = radeon_mc_setup(rdev); + if (r) + return r; + return 0; +} + void rs690_line_buffer_adjust(struct radeon_device *rdev, struct drm_display_mode *mode1, struct drm_display_mode *mode2) @@ -244,8 +260,9 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, b.full = rfixed_const(mode->crtc_hdisplay); c.full = rfixed_const(256); - a.full = rfixed_mul(wm->num_line_pair, b); - request_fifo_depth.full = rfixed_div(a, c); + a.full = rfixed_div(b, c); + request_fifo_depth.full = rfixed_mul(a, wm->num_line_pair); + request_fifo_depth.full = rfixed_ceil(request_fifo_depth); if (a.full < rfixed_const(4)) { wm->lb_request_fifo_depth = 4; } else { @@ -374,6 +391,7 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, a.full = rfixed_const(16); wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay); wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a); + wm->priority_mark_max.full = rfixed_ceil(wm->priority_mark_max); /* Determine estimated width */ estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; @@ -383,6 +401,7 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, } else { a.full = rfixed_const(16); wm->priority_mark.full = rfixed_div(estimated_width, a); + wm->priority_mark.full = rfixed_ceil(wm->priority_mark); wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full; } } @@ -605,7 +624,6 @@ static int rs690_startup(struct radeon_device *rdev) if (r) return r; /* Enable IRQ */ - rdev->irq.sw_int = true; rs600_irq_set(rdev); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); @@ -640,6 +658,8 @@ int rs690_resume(struct radeon_device *rdev) atom_asic_init(rdev->mode_info.atom_context); /* Resume clock after posting */ rv515_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); return rs690_startup(rdev); } @@ -662,7 +682,7 @@ void rs690_fini(struct radeon_device *rdev) rs400_gart_fini(rdev); radeon_irq_kms_fini(rdev); radeon_fence_driver_fini(rdev); - radeon_object_fini(rdev); + radeon_bo_fini(rdev); radeon_atombios_fini(rdev); kfree(rdev->bios); rdev->bios = NULL; @@ -700,10 +720,9 @@ int rs690_init(struct radeon_device *rdev) RREG32(R_0007C0_CP_STAT)); } /* check if cards are posted or not */ - if (!radeon_card_posted(rdev) && rdev->bios) { - DRM_INFO("GPU not posted. posting now...\n"); - atom_asic_init(rdev->mode_info.atom_context); - } + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; + /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); /* Initialize power management */ @@ -711,7 +730,7 @@ int rs690_init(struct radeon_device *rdev) /* Get vram informations */ rs690_vram_info(rdev); /* Initialize memory controller (also test AGP) */ - r = r420_mc_init(rdev); + r = rs690_mc_init(rdev); if (r) return r; rv515_debugfs(rdev); @@ -723,7 +742,7 @@ int rs690_init(struct radeon_device *rdev) if (r) return r; /* Memory manager */ - r = radeon_object_init(rdev); + r = radeon_bo_init(rdev); if (r) return r; r = rs400_gart_init(rdev); diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index ba68c9fe90a1b7db910e8f6d551a192e42ef264e..59632a506b46cc53ad6f74e8ca8f527662f6758c 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -478,7 +478,6 @@ static int rv515_startup(struct radeon_device *rdev) return r; } /* Enable IRQ */ - rdev->irq.sw_int = true; rs600_irq_set(rdev); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); @@ -514,6 +513,8 @@ int rv515_resume(struct radeon_device *rdev) atom_asic_init(rdev->mode_info.atom_context); /* Resume clock after posting */ rv515_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); return rv515_startup(rdev); } @@ -540,11 +541,11 @@ void rv515_fini(struct radeon_device *rdev) r100_wb_fini(rdev); r100_ib_fini(rdev); radeon_gem_fini(rdev); - rv370_pcie_gart_fini(rdev); + rv370_pcie_gart_fini(rdev); radeon_agp_fini(rdev); radeon_irq_kms_fini(rdev); radeon_fence_driver_fini(rdev); - radeon_object_fini(rdev); + radeon_bo_fini(rdev); radeon_atombios_fini(rdev); kfree(rdev->bios); rdev->bios = NULL; @@ -580,10 +581,8 @@ int rv515_init(struct radeon_device *rdev) RREG32(R_0007C0_CP_STAT)); } /* check if cards are posted or not */ - if (!radeon_card_posted(rdev) && rdev->bios) { - DRM_INFO("GPU not posted. posting now...\n"); - atom_asic_init(rdev->mode_info.atom_context); - } + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); /* Initialize power management */ @@ -603,7 +602,7 @@ int rv515_init(struct radeon_device *rdev) if (r) return r; /* Memory manager */ - r = radeon_object_init(rdev); + r = radeon_bo_init(rdev); if (r) return r; r = rv370_pcie_gart_init(rdev); @@ -892,8 +891,9 @@ void rv515_crtc_bandwidth_compute(struct radeon_device *rdev, b.full = rfixed_const(mode->crtc_hdisplay); c.full = rfixed_const(256); - a.full = rfixed_mul(wm->num_line_pair, b); - request_fifo_depth.full = rfixed_div(a, c); + a.full = rfixed_div(b, c); + request_fifo_depth.full = rfixed_mul(a, wm->num_line_pair); + request_fifo_depth.full = rfixed_ceil(request_fifo_depth); if (a.full < rfixed_const(4)) { wm->lb_request_fifo_depth = 4; } else { @@ -995,15 +995,17 @@ void rv515_crtc_bandwidth_compute(struct radeon_device *rdev, a.full = rfixed_const(16); wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay); wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a); + wm->priority_mark_max.full = rfixed_ceil(wm->priority_mark_max); /* Determine estimated width */ estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; estimated_width.full = rfixed_div(estimated_width, consumption_time); if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) { - wm->priority_mark.full = rfixed_const(10); + wm->priority_mark.full = wm->priority_mark_max.full; } else { a.full = rfixed_const(16); wm->priority_mark.full = rfixed_div(estimated_width, a); + wm->priority_mark.full = rfixed_ceil(wm->priority_mark); wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full; } } diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 5e06ee7076f525ec98c35789ea6855a89beabe58..fbb0357f1ec32e21da862b2e17fee781599da337 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -92,7 +92,7 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev) void rv770_pcie_gart_disable(struct radeon_device *rdev) { u32 tmp; - int i; + int i, r; /* Disable all tables */ for (i = 0; i < 7; i++) @@ -113,8 +113,12 @@ void rv770_pcie_gart_disable(struct radeon_device *rdev) WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); if (rdev->gart.table.vram.robj) { - radeon_object_kunmap(rdev->gart.table.vram.robj); - radeon_object_unpin(rdev->gart.table.vram.robj); + r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); + if (likely(r == 0)) { + radeon_bo_kunmap(rdev->gart.table.vram.robj); + radeon_bo_unpin(rdev->gart.table.vram.robj); + radeon_bo_unreserve(rdev->gart.table.vram.robj); + } } } @@ -870,6 +874,14 @@ static int rv770_startup(struct radeon_device *rdev) { int r; + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { + r = r600_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + rv770_mc_program(rdev); if (rdev->flags & RADEON_IS_AGP) { rv770_agp_enable(rdev); @@ -880,13 +892,26 @@ static int rv770_startup(struct radeon_device *rdev) } rv770_gpu_init(rdev); - r = radeon_object_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, - &rdev->r600_blit.shader_gpu_addr); + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, + &rdev->r600_blit.shader_gpu_addr); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); if (r) { DRM_ERROR("failed to pin blit object %d\n", r); return r; } + /* Enable IRQ */ + r = r600_irq_init(rdev); + if (r) { + DRM_ERROR("radeon: IH init failed (%d).\n", r); + radeon_irq_kms_fini(rdev); + return r; + } + r600_irq_set(rdev); + r = radeon_ring_init(rdev, rdev->cp.ring_size); if (r) return r; @@ -934,13 +959,19 @@ int rv770_resume(struct radeon_device *rdev) int rv770_suspend(struct radeon_device *rdev) { + int r; + /* FIXME: we should wait for ring to be empty */ r700_cp_stop(rdev); rdev->cp.ready = false; r600_wb_disable(rdev); rv770_pcie_gart_disable(rdev); /* unpin shaders bo */ - radeon_object_unpin(rdev->r600_blit.shader_obj); + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (likely(r == 0)) { + radeon_bo_unpin(rdev->r600_blit.shader_obj); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); + } return 0; } @@ -975,7 +1006,11 @@ int rv770_init(struct radeon_device *rdev) if (r) return r; /* Post card if necessary */ - if (!r600_card_posted(rdev) && rdev->bios) { + if (!r600_card_posted(rdev)) { + if (!rdev->bios) { + dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); + return -EINVAL; + } DRM_INFO("GPU not posted. posting now...\n"); atom_asic_init(rdev->mode_info.atom_context); } @@ -998,31 +1033,31 @@ int rv770_init(struct radeon_device *rdev) if (r) return r; /* Memory manager */ - r = radeon_object_init(rdev); + r = radeon_bo_init(rdev); + if (r) + return r; + + r = radeon_irq_kms_init(rdev); if (r) return r; + rdev->cp.ring_obj = NULL; r600_ring_init(rdev, 1024 * 1024); - if (!rdev->me_fw || !rdev->pfp_fw) { - r = r600_cp_init_microcode(rdev); - if (r) { - DRM_ERROR("Failed to load firmware!\n"); - return r; - } - } + rdev->ih.ring_obj = NULL; + r600_ih_ring_init(rdev, 64 * 1024); r = r600_pcie_gart_init(rdev); if (r) return r; - rdev->accel_working = true; r = r600_blit_init(rdev); if (r) { - DRM_ERROR("radeon: failled blitter (%d).\n", r); - rdev->accel_working = false; + DRM_ERROR("radeon: failed blitter (%d).\n", r); + return r; } + rdev->accel_working = true; r = rv770_startup(rdev); if (r) { rv770_suspend(rdev); @@ -1034,12 +1069,12 @@ int rv770_init(struct radeon_device *rdev) if (rdev->accel_working) { r = radeon_ib_pool_init(rdev); if (r) { - DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r); + DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); rdev->accel_working = false; } r = r600_ib_test(rdev); if (r) { - DRM_ERROR("radeon: failled testing IB (%d).\n", r); + DRM_ERROR("radeon: failed testing IB (%d).\n", r); rdev->accel_working = false; } } @@ -1051,6 +1086,8 @@ void rv770_fini(struct radeon_device *rdev) rv770_suspend(rdev); r600_blit_fini(rdev); + r600_irq_fini(rdev); + radeon_irq_kms_fini(rdev); radeon_ring_fini(rdev); r600_wb_fini(rdev); rv770_pcie_gart_fini(rdev); @@ -1059,7 +1096,7 @@ void rv770_fini(struct radeon_device *rdev) radeon_clocks_fini(rdev); if (rdev->flags & RADEON_IS_AGP) radeon_agp_fini(rdev); - radeon_object_fini(rdev); + radeon_bo_fini(rdev); radeon_atombios_fini(rdev); kfree(rdev->bios); rdev->bios = NULL; diff --git a/drivers/gpu/drm/ttm/Makefile b/drivers/gpu/drm/ttm/Makefile index b0a9de7a57c22b65d043d895f049a4afb775fe76..1e138f5bae09acfa8b820b1cb17cad3ed0fbab4e 100644 --- a/drivers/gpu/drm/ttm/Makefile +++ b/drivers/gpu/drm/ttm/Makefile @@ -3,6 +3,7 @@ ccflags-y := -Iinclude/drm ttm-y := ttm_agp_backend.o ttm_memory.o ttm_tt.o ttm_bo.o \ - ttm_bo_util.o ttm_bo_vm.o ttm_module.o ttm_global.o + ttm_bo_util.o ttm_bo_vm.o ttm_module.o ttm_global.o \ + ttm_object.o ttm_lock.o ttm_execbuf_util.o obj-$(CONFIG_DRM_TTM) += ttm.o diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 87c06252d4643e35f0fc5234438efba8311c7ed6..1fbb2eea5e88d5d17b59ddffa40a29b0424f8069 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -27,6 +27,14 @@ /* * Authors: Thomas Hellstrom */ +/* Notes: + * + * We store bo pointer in drm_mm_node struct so we know which bo own a + * specific node. There is no protection on the pointer, thus to make + * sure things don't go berserk you have to access this pointer while + * holding the global lru lock and make sure anytime you free a node you + * reset the pointer to NULL. + */ #include "ttm/ttm_module.h" #include "ttm/ttm_bo_driver.h" @@ -51,6 +59,60 @@ static struct attribute ttm_bo_count = { .mode = S_IRUGO }; +static inline int ttm_mem_type_from_flags(uint32_t flags, uint32_t *mem_type) +{ + int i; + + for (i = 0; i <= TTM_PL_PRIV5; i++) + if (flags & (1 << i)) { + *mem_type = i; + return 0; + } + return -EINVAL; +} + +static void ttm_mem_type_manager_debug(struct ttm_bo_global *glob, + struct ttm_mem_type_manager *man) +{ + printk(KERN_ERR TTM_PFX " has_type: %d\n", man->has_type); + printk(KERN_ERR TTM_PFX " use_type: %d\n", man->use_type); + printk(KERN_ERR TTM_PFX " flags: 0x%08X\n", man->flags); + printk(KERN_ERR TTM_PFX " gpu_offset: 0x%08lX\n", man->gpu_offset); + printk(KERN_ERR TTM_PFX " io_offset: 0x%08lX\n", man->io_offset); + printk(KERN_ERR TTM_PFX " io_size: %ld\n", man->io_size); + printk(KERN_ERR TTM_PFX " size: %ld\n", (unsigned long)man->size); + printk(KERN_ERR TTM_PFX " available_caching: 0x%08X\n", + man->available_caching); + printk(KERN_ERR TTM_PFX " default_caching: 0x%08X\n", + man->default_caching); + spin_lock(&glob->lru_lock); + drm_mm_debug_table(&man->manager, TTM_PFX); + spin_unlock(&glob->lru_lock); +} + +static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, + struct ttm_placement *placement) +{ + struct ttm_bo_device *bdev = bo->bdev; + struct ttm_bo_global *glob = bo->glob; + struct ttm_mem_type_manager *man; + int i, ret, mem_type; + + printk(KERN_ERR TTM_PFX "No space for %p (%ld pages, %ldK, %ldM)\n", + bo, bo->mem.num_pages, bo->mem.size >> 10, + bo->mem.size >> 20); + for (i = 0; i < placement->num_placement; i++) { + ret = ttm_mem_type_from_flags(placement->placement[i], + &mem_type); + if (ret) + return; + man = &bdev->man[mem_type]; + printk(KERN_ERR TTM_PFX " placement[%d]=0x%08X (%d)\n", + i, placement->placement[i], mem_type); + ttm_mem_type_manager_debug(glob, man); + } +} + static ssize_t ttm_bo_global_show(struct kobject *kobj, struct attribute *attr, char *buffer) @@ -117,12 +179,13 @@ int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo, bool interruptible) ret = wait_event_interruptible(bo->event_queue, atomic_read(&bo->reserved) == 0); if (unlikely(ret != 0)) - return -ERESTART; + return ret; } else { wait_event(bo->event_queue, atomic_read(&bo->reserved) == 0); } return 0; } +EXPORT_SYMBOL(ttm_bo_wait_unreserved); static void ttm_bo_add_to_lru(struct ttm_buffer_object *bo) { @@ -247,7 +310,6 @@ EXPORT_SYMBOL(ttm_bo_unreserve); /* * Call bo->mutex locked. */ - static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc) { struct ttm_bo_device *bdev = bo->bdev; @@ -275,9 +337,10 @@ static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc) bo->ttm = ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT, page_flags | TTM_PAGE_FLAG_USER, glob->dummy_read_page); - if (unlikely(bo->ttm == NULL)) + if (unlikely(bo->ttm == NULL)) { ret = -ENOMEM; - break; + break; + } ret = ttm_tt_set_user(bo->ttm, current, bo->buffer_start, bo->num_pages); @@ -328,14 +391,8 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, } if (bo->mem.mem_type == TTM_PL_SYSTEM) { - - struct ttm_mem_reg *old_mem = &bo->mem; - uint32_t save_flags = old_mem->placement; - - *old_mem = *mem; + bo->mem = *mem; mem->mm_node = NULL; - ttm_flag_masked(&save_flags, mem->placement, - TTM_PL_MASK_MEMTYPE); goto moved; } @@ -418,6 +475,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all) kref_put(&bo->list_kref, ttm_bo_ref_bug); } if (bo->mem.mm_node) { + bo->mem.mm_node->private = NULL; drm_mm_put_block(bo->mem.mm_node); bo->mem.mm_node = NULL; } @@ -554,24 +612,21 @@ void ttm_bo_unref(struct ttm_buffer_object **p_bo) } EXPORT_SYMBOL(ttm_bo_unref); -static int ttm_bo_evict(struct ttm_buffer_object *bo, unsigned mem_type, - bool interruptible, bool no_wait) +static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible, + bool no_wait) { - int ret = 0; struct ttm_bo_device *bdev = bo->bdev; struct ttm_bo_global *glob = bo->glob; struct ttm_mem_reg evict_mem; - uint32_t proposed_placement; - - if (bo->mem.mem_type != mem_type) - goto out; + struct ttm_placement placement; + int ret = 0; spin_lock(&bo->lock); ret = ttm_bo_wait(bo, false, interruptible, no_wait); spin_unlock(&bo->lock); if (unlikely(ret != 0)) { - if (ret != -ERESTART) { + if (ret != -ERESTARTSYS) { printk(KERN_ERR TTM_PFX "Failed to expire sync object before " "buffer eviction.\n"); @@ -584,116 +639,139 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, unsigned mem_type, evict_mem = bo->mem; evict_mem.mm_node = NULL; - proposed_placement = bdev->driver->evict_flags(bo); - - ret = ttm_bo_mem_space(bo, proposed_placement, - &evict_mem, interruptible, no_wait); - if (unlikely(ret != 0 && ret != -ERESTART)) - ret = ttm_bo_mem_space(bo, TTM_PL_FLAG_SYSTEM, - &evict_mem, interruptible, no_wait); - + placement.fpfn = 0; + placement.lpfn = 0; + placement.num_placement = 0; + placement.num_busy_placement = 0; + bdev->driver->evict_flags(bo, &placement); + ret = ttm_bo_mem_space(bo, &placement, &evict_mem, interruptible, + no_wait); if (ret) { - if (ret != -ERESTART) + if (ret != -ERESTARTSYS) { printk(KERN_ERR TTM_PFX "Failed to find memory space for " "buffer 0x%p eviction.\n", bo); + ttm_bo_mem_space_debug(bo, &placement); + } goto out; } ret = ttm_bo_handle_move_mem(bo, &evict_mem, true, interruptible, no_wait); if (ret) { - if (ret != -ERESTART) + if (ret != -ERESTARTSYS) printk(KERN_ERR TTM_PFX "Buffer eviction failed\n"); + spin_lock(&glob->lru_lock); + if (evict_mem.mm_node) { + evict_mem.mm_node->private = NULL; + drm_mm_put_block(evict_mem.mm_node); + evict_mem.mm_node = NULL; + } + spin_unlock(&glob->lru_lock); goto out; } + bo->evicted = true; +out: + return ret; +} + +static int ttm_mem_evict_first(struct ttm_bo_device *bdev, + uint32_t mem_type, + bool interruptible, bool no_wait) +{ + struct ttm_bo_global *glob = bdev->glob; + struct ttm_mem_type_manager *man = &bdev->man[mem_type]; + struct ttm_buffer_object *bo; + int ret, put_count = 0; spin_lock(&glob->lru_lock); - if (evict_mem.mm_node) { - drm_mm_put_block(evict_mem.mm_node); - evict_mem.mm_node = NULL; - } + bo = list_first_entry(&man->lru, struct ttm_buffer_object, lru); + kref_get(&bo->list_kref); + ret = ttm_bo_reserve_locked(bo, interruptible, no_wait, false, 0); + if (likely(ret == 0)) + put_count = ttm_bo_del_from_lru(bo); spin_unlock(&glob->lru_lock); - bo->evicted = true; -out: + if (unlikely(ret != 0)) + return ret; + while (put_count--) + kref_put(&bo->list_kref, ttm_bo_ref_bug); + ret = ttm_bo_evict(bo, interruptible, no_wait); + ttm_bo_unreserve(bo); + kref_put(&bo->list_kref, ttm_bo_release_list); return ret; } +static int ttm_bo_man_get_node(struct ttm_buffer_object *bo, + struct ttm_mem_type_manager *man, + struct ttm_placement *placement, + struct ttm_mem_reg *mem, + struct drm_mm_node **node) +{ + struct ttm_bo_global *glob = bo->glob; + unsigned long lpfn; + int ret; + + lpfn = placement->lpfn; + if (!lpfn) + lpfn = man->size; + *node = NULL; + do { + ret = drm_mm_pre_get(&man->manager); + if (unlikely(ret)) + return ret; + + spin_lock(&glob->lru_lock); + *node = drm_mm_search_free_in_range(&man->manager, + mem->num_pages, mem->page_alignment, + placement->fpfn, lpfn, 1); + if (unlikely(*node == NULL)) { + spin_unlock(&glob->lru_lock); + return 0; + } + *node = drm_mm_get_block_atomic_range(*node, mem->num_pages, + mem->page_alignment, + placement->fpfn, + lpfn); + spin_unlock(&glob->lru_lock); + } while (*node == NULL); + return 0; +} + /** * Repeatedly evict memory from the LRU for @mem_type until we create enough * space, or we've evicted everything and there isn't enough space. */ -static int ttm_bo_mem_force_space(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem, - uint32_t mem_type, - bool interruptible, bool no_wait) +static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, + uint32_t mem_type, + struct ttm_placement *placement, + struct ttm_mem_reg *mem, + bool interruptible, bool no_wait) { + struct ttm_bo_device *bdev = bo->bdev; struct ttm_bo_global *glob = bdev->glob; - struct drm_mm_node *node; - struct ttm_buffer_object *entry; struct ttm_mem_type_manager *man = &bdev->man[mem_type]; - struct list_head *lru; - unsigned long num_pages = mem->num_pages; - int put_count = 0; + struct drm_mm_node *node; int ret; -retry_pre_get: - ret = drm_mm_pre_get(&man->manager); - if (unlikely(ret != 0)) - return ret; - - spin_lock(&glob->lru_lock); do { - node = drm_mm_search_free(&man->manager, num_pages, - mem->page_alignment, 1); + ret = ttm_bo_man_get_node(bo, man, placement, mem, &node); + if (unlikely(ret != 0)) + return ret; if (node) break; - - lru = &man->lru; - if (list_empty(lru)) + spin_lock(&glob->lru_lock); + if (list_empty(&man->lru)) { + spin_unlock(&glob->lru_lock); break; - - entry = list_first_entry(lru, struct ttm_buffer_object, lru); - kref_get(&entry->list_kref); - - ret = - ttm_bo_reserve_locked(entry, interruptible, no_wait, - false, 0); - - if (likely(ret == 0)) - put_count = ttm_bo_del_from_lru(entry); - + } spin_unlock(&glob->lru_lock); - + ret = ttm_mem_evict_first(bdev, mem_type, interruptible, + no_wait); if (unlikely(ret != 0)) return ret; - - while (put_count--) - kref_put(&entry->list_kref, ttm_bo_ref_bug); - - ret = ttm_bo_evict(entry, mem_type, interruptible, no_wait); - - ttm_bo_unreserve(entry); - - kref_put(&entry->list_kref, ttm_bo_release_list); - if (ret) - return ret; - - spin_lock(&glob->lru_lock); } while (1); - - if (!node) { - spin_unlock(&glob->lru_lock); + if (node == NULL) return -ENOMEM; - } - - node = drm_mm_get_block_atomic(node, num_pages, mem->page_alignment); - if (unlikely(!node)) { - spin_unlock(&glob->lru_lock); - goto retry_pre_get; - } - - spin_unlock(&glob->lru_lock); mem->mm_node = node; mem->mem_type = mem_type; return 0; @@ -724,7 +802,6 @@ static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man, return result; } - static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man, bool disallow_fixed, uint32_t mem_type, @@ -757,66 +834,55 @@ static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man, * space. */ int ttm_bo_mem_space(struct ttm_buffer_object *bo, - uint32_t proposed_placement, - struct ttm_mem_reg *mem, - bool interruptible, bool no_wait) + struct ttm_placement *placement, + struct ttm_mem_reg *mem, + bool interruptible, bool no_wait) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_bo_global *glob = bo->glob; struct ttm_mem_type_manager *man; - - uint32_t num_prios = bdev->driver->num_mem_type_prio; - const uint32_t *prios = bdev->driver->mem_type_prio; - uint32_t i; uint32_t mem_type = TTM_PL_SYSTEM; uint32_t cur_flags = 0; bool type_found = false; bool type_ok = false; - bool has_eagain = false; + bool has_erestartsys = false; struct drm_mm_node *node = NULL; - int ret; + int i, ret; mem->mm_node = NULL; - for (i = 0; i < num_prios; ++i) { - mem_type = prios[i]; + for (i = 0; i <= placement->num_placement; ++i) { + ret = ttm_mem_type_from_flags(placement->placement[i], + &mem_type); + if (ret) + return ret; man = &bdev->man[mem_type]; type_ok = ttm_bo_mt_compatible(man, - bo->type == ttm_bo_type_user, - mem_type, proposed_placement, - &cur_flags); + bo->type == ttm_bo_type_user, + mem_type, + placement->placement[i], + &cur_flags); if (!type_ok) continue; cur_flags = ttm_bo_select_caching(man, bo->mem.placement, cur_flags); + /* + * Use the access and other non-mapping-related flag bits from + * the memory placement flags to the current flags + */ + ttm_flag_masked(&cur_flags, placement->placement[i], + ~TTM_PL_MASK_MEMTYPE); if (mem_type == TTM_PL_SYSTEM) break; if (man->has_type && man->use_type) { type_found = true; - do { - ret = drm_mm_pre_get(&man->manager); - if (unlikely(ret)) - return ret; - - spin_lock(&glob->lru_lock); - node = drm_mm_search_free(&man->manager, - mem->num_pages, - mem->page_alignment, - 1); - if (unlikely(!node)) { - spin_unlock(&glob->lru_lock); - break; - } - node = drm_mm_get_block_atomic(node, - mem->num_pages, - mem-> - page_alignment); - spin_unlock(&glob->lru_lock); - } while (!node); + ret = ttm_bo_man_get_node(bo, man, placement, mem, + &node); + if (unlikely(ret)) + return ret; } if (node) break; @@ -826,67 +892,66 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, mem->mm_node = node; mem->mem_type = mem_type; mem->placement = cur_flags; + if (node) + node->private = bo; return 0; } if (!type_found) return -EINVAL; - num_prios = bdev->driver->num_mem_busy_prio; - prios = bdev->driver->mem_busy_prio; - - for (i = 0; i < num_prios; ++i) { - mem_type = prios[i]; + for (i = 0; i <= placement->num_busy_placement; ++i) { + ret = ttm_mem_type_from_flags(placement->placement[i], + &mem_type); + if (ret) + return ret; man = &bdev->man[mem_type]; - if (!man->has_type) continue; - if (!ttm_bo_mt_compatible(man, - bo->type == ttm_bo_type_user, - mem_type, - proposed_placement, &cur_flags)) + bo->type == ttm_bo_type_user, + mem_type, + placement->placement[i], + &cur_flags)) continue; cur_flags = ttm_bo_select_caching(man, bo->mem.placement, cur_flags); + /* + * Use the access and other non-mapping-related flag bits from + * the memory placement flags to the current flags + */ + ttm_flag_masked(&cur_flags, placement->placement[i], + ~TTM_PL_MASK_MEMTYPE); - ret = ttm_bo_mem_force_space(bdev, mem, mem_type, - interruptible, no_wait); - + ret = ttm_bo_mem_force_space(bo, mem_type, placement, mem, + interruptible, no_wait); if (ret == 0 && mem->mm_node) { mem->placement = cur_flags; + mem->mm_node->private = bo; return 0; } - - if (ret == -ERESTART) - has_eagain = true; + if (ret == -ERESTARTSYS) + has_erestartsys = true; } - - ret = (has_eagain) ? -ERESTART : -ENOMEM; + ret = (has_erestartsys) ? -ERESTARTSYS : -ENOMEM; return ret; } EXPORT_SYMBOL(ttm_bo_mem_space); int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait) { - int ret = 0; - if ((atomic_read(&bo->cpu_writers) > 0) && no_wait) return -EBUSY; - ret = wait_event_interruptible(bo->event_queue, - atomic_read(&bo->cpu_writers) == 0); - - if (ret == -ERESTARTSYS) - ret = -ERESTART; - - return ret; + return wait_event_interruptible(bo->event_queue, + atomic_read(&bo->cpu_writers) == 0); } +EXPORT_SYMBOL(ttm_bo_wait_cpu); int ttm_bo_move_buffer(struct ttm_buffer_object *bo, - uint32_t proposed_placement, - bool interruptible, bool no_wait) + struct ttm_placement *placement, + bool interruptible, bool no_wait) { struct ttm_bo_global *glob = bo->glob; int ret = 0; @@ -899,147 +964,132 @@ int ttm_bo_move_buffer(struct ttm_buffer_object *bo, * Have the driver move function wait for idle when necessary, * instead of doing it here. */ - spin_lock(&bo->lock); ret = ttm_bo_wait(bo, false, interruptible, no_wait); spin_unlock(&bo->lock); - if (ret) return ret; - mem.num_pages = bo->num_pages; mem.size = mem.num_pages << PAGE_SHIFT; mem.page_alignment = bo->mem.page_alignment; - /* * Determine where to move the buffer. */ - - ret = ttm_bo_mem_space(bo, proposed_placement, &mem, - interruptible, no_wait); + ret = ttm_bo_mem_space(bo, placement, &mem, interruptible, no_wait); if (ret) goto out_unlock; - ret = ttm_bo_handle_move_mem(bo, &mem, false, interruptible, no_wait); - out_unlock: if (ret && mem.mm_node) { spin_lock(&glob->lru_lock); + mem.mm_node->private = NULL; drm_mm_put_block(mem.mm_node); spin_unlock(&glob->lru_lock); } return ret; } -static int ttm_bo_mem_compat(uint32_t proposed_placement, +static int ttm_bo_mem_compat(struct ttm_placement *placement, struct ttm_mem_reg *mem) { - if ((proposed_placement & mem->placement & TTM_PL_MASK_MEM) == 0) - return 0; - if ((proposed_placement & mem->placement & TTM_PL_MASK_CACHING) == 0) - return 0; - - return 1; + int i; + + for (i = 0; i < placement->num_placement; i++) { + if ((placement->placement[i] & mem->placement & + TTM_PL_MASK_CACHING) && + (placement->placement[i] & mem->placement & + TTM_PL_MASK_MEM)) + return i; + } + return -1; } -int ttm_buffer_object_validate(struct ttm_buffer_object *bo, - uint32_t proposed_placement, - bool interruptible, bool no_wait) +int ttm_bo_validate(struct ttm_buffer_object *bo, + struct ttm_placement *placement, + bool interruptible, bool no_wait) { int ret; BUG_ON(!atomic_read(&bo->reserved)); - bo->proposed_placement = proposed_placement; - - TTM_DEBUG("Proposed placement 0x%08lx, Old flags 0x%08lx\n", - (unsigned long)proposed_placement, - (unsigned long)bo->mem.placement); - + /* Check that range is valid */ + if (placement->lpfn || placement->fpfn) + if (placement->fpfn > placement->lpfn || + (placement->lpfn - placement->fpfn) < bo->num_pages) + return -EINVAL; /* * Check whether we need to move buffer. */ - - if (!ttm_bo_mem_compat(bo->proposed_placement, &bo->mem)) { - ret = ttm_bo_move_buffer(bo, bo->proposed_placement, - interruptible, no_wait); - if (ret) { - if (ret != -ERESTART) - printk(KERN_ERR TTM_PFX - "Failed moving buffer. " - "Proposed placement 0x%08x\n", - bo->proposed_placement); - if (ret == -ENOMEM) - printk(KERN_ERR TTM_PFX - "Out of aperture space or " - "DRM memory quota.\n"); + ret = ttm_bo_mem_compat(placement, &bo->mem); + if (ret < 0) { + ret = ttm_bo_move_buffer(bo, placement, interruptible, no_wait); + if (ret) return ret; - } + } else { + /* + * Use the access and other non-mapping-related flag bits from + * the compatible memory placement flags to the active flags + */ + ttm_flag_masked(&bo->mem.placement, placement->placement[ret], + ~TTM_PL_MASK_MEMTYPE); } - /* * We might need to add a TTM. */ - if (bo->mem.mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { ret = ttm_bo_add_ttm(bo, true); if (ret) return ret; } - /* - * Validation has succeeded, move the access and other - * non-mapping-related flag bits from the proposed flags to - * the active flags - */ - - ttm_flag_masked(&bo->mem.placement, bo->proposed_placement, - ~TTM_PL_MASK_MEMTYPE); - return 0; } -EXPORT_SYMBOL(ttm_buffer_object_validate); +EXPORT_SYMBOL(ttm_bo_validate); -int -ttm_bo_check_placement(struct ttm_buffer_object *bo, - uint32_t set_flags, uint32_t clr_flags) +int ttm_bo_check_placement(struct ttm_buffer_object *bo, + struct ttm_placement *placement) { - uint32_t new_mask = set_flags | clr_flags; - - if ((bo->type == ttm_bo_type_user) && - (clr_flags & TTM_PL_FLAG_CACHED)) { - printk(KERN_ERR TTM_PFX - "User buffers require cache-coherent memory.\n"); - return -EINVAL; - } - - if (!capable(CAP_SYS_ADMIN)) { - if (new_mask & TTM_PL_FLAG_NO_EVICT) { - printk(KERN_ERR TTM_PFX "Need to be root to modify" - " NO_EVICT status.\n"); + int i; + + if (placement->fpfn || placement->lpfn) { + if (bo->mem.num_pages > (placement->lpfn - placement->fpfn)) { + printk(KERN_ERR TTM_PFX "Page number range to small " + "Need %lu pages, range is [%u, %u]\n", + bo->mem.num_pages, placement->fpfn, + placement->lpfn); return -EINVAL; } - - if ((clr_flags & bo->mem.placement & TTM_PL_MASK_MEMTYPE) && - (bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) { - printk(KERN_ERR TTM_PFX - "Incompatible memory specification" - " for NO_EVICT buffer.\n"); - return -EINVAL; + } + for (i = 0; i < placement->num_placement; i++) { + if (!capable(CAP_SYS_ADMIN)) { + if (placement->placement[i] & TTM_PL_FLAG_NO_EVICT) { + printk(KERN_ERR TTM_PFX "Need to be root to " + "modify NO_EVICT status.\n"); + return -EINVAL; + } + } + } + for (i = 0; i < placement->num_busy_placement; i++) { + if (!capable(CAP_SYS_ADMIN)) { + if (placement->busy_placement[i] & TTM_PL_FLAG_NO_EVICT) { + printk(KERN_ERR TTM_PFX "Need to be root to " + "modify NO_EVICT status.\n"); + return -EINVAL; + } } } return 0; } -int ttm_buffer_object_init(struct ttm_bo_device *bdev, - struct ttm_buffer_object *bo, - unsigned long size, - enum ttm_bo_type type, - uint32_t flags, - uint32_t page_alignment, - unsigned long buffer_start, - bool interruptible, - struct file *persistant_swap_storage, - size_t acc_size, - void (*destroy) (struct ttm_buffer_object *)) +int ttm_bo_init(struct ttm_bo_device *bdev, + struct ttm_buffer_object *bo, + unsigned long size, + enum ttm_bo_type type, + struct ttm_placement *placement, + uint32_t page_alignment, + unsigned long buffer_start, + bool interruptible, + struct file *persistant_swap_storage, + size_t acc_size, + void (*destroy) (struct ttm_buffer_object *)) { int ret = 0; unsigned long num_pages; @@ -1077,29 +1127,21 @@ int ttm_buffer_object_init(struct ttm_bo_device *bdev, bo->acc_size = acc_size; atomic_inc(&bo->glob->bo_count); - ret = ttm_bo_check_placement(bo, flags, 0ULL); + ret = ttm_bo_check_placement(bo, placement); if (unlikely(ret != 0)) goto out_err; - /* - * If no caching attributes are set, accept any form of caching. - */ - - if ((flags & TTM_PL_MASK_CACHING) == 0) - flags |= TTM_PL_MASK_CACHING; - /* * For ttm_bo_type_device buffers, allocate * address space from the device. */ - if (bo->type == ttm_bo_type_device) { ret = ttm_bo_setup_vm(bo); if (ret) goto out_err; } - ret = ttm_buffer_object_validate(bo, flags, interruptible, false); + ret = ttm_bo_validate(bo, placement, interruptible, false); if (ret) goto out_err; @@ -1112,7 +1154,7 @@ out_err: return ret; } -EXPORT_SYMBOL(ttm_buffer_object_init); +EXPORT_SYMBOL(ttm_bo_init); static inline size_t ttm_bo_size(struct ttm_bo_global *glob, unsigned long num_pages) @@ -1123,19 +1165,19 @@ static inline size_t ttm_bo_size(struct ttm_bo_global *glob, return glob->ttm_bo_size + 2 * page_array_size; } -int ttm_buffer_object_create(struct ttm_bo_device *bdev, - unsigned long size, - enum ttm_bo_type type, - uint32_t flags, - uint32_t page_alignment, - unsigned long buffer_start, - bool interruptible, - struct file *persistant_swap_storage, - struct ttm_buffer_object **p_bo) +int ttm_bo_create(struct ttm_bo_device *bdev, + unsigned long size, + enum ttm_bo_type type, + struct ttm_placement *placement, + uint32_t page_alignment, + unsigned long buffer_start, + bool interruptible, + struct file *persistant_swap_storage, + struct ttm_buffer_object **p_bo) { struct ttm_buffer_object *bo; - int ret; struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; + int ret; size_t acc_size = ttm_bo_size(bdev->glob, (size + PAGE_SIZE - 1) >> PAGE_SHIFT); @@ -1150,76 +1192,41 @@ int ttm_buffer_object_create(struct ttm_bo_device *bdev, return -ENOMEM; } - ret = ttm_buffer_object_init(bdev, bo, size, type, flags, - page_alignment, buffer_start, - interruptible, - persistant_swap_storage, acc_size, NULL); + ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment, + buffer_start, interruptible, + persistant_swap_storage, acc_size, NULL); if (likely(ret == 0)) *p_bo = bo; return ret; } -static int ttm_bo_leave_list(struct ttm_buffer_object *bo, - uint32_t mem_type, bool allow_errors) -{ - int ret; - - spin_lock(&bo->lock); - ret = ttm_bo_wait(bo, false, false, false); - spin_unlock(&bo->lock); - - if (ret && allow_errors) - goto out; - - if (bo->mem.mem_type == mem_type) - ret = ttm_bo_evict(bo, mem_type, false, false); - - if (ret) { - if (allow_errors) { - goto out; - } else { - ret = 0; - printk(KERN_ERR TTM_PFX "Cleanup eviction failed\n"); - } - } - -out: - return ret; -} - static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, - struct list_head *head, - unsigned mem_type, bool allow_errors) + unsigned mem_type, bool allow_errors) { + struct ttm_mem_type_manager *man = &bdev->man[mem_type]; struct ttm_bo_global *glob = bdev->glob; - struct ttm_buffer_object *entry; int ret; - int put_count; /* * Can't use standard list traversal since we're unlocking. */ spin_lock(&glob->lru_lock); - - while (!list_empty(head)) { - entry = list_first_entry(head, struct ttm_buffer_object, lru); - kref_get(&entry->list_kref); - ret = ttm_bo_reserve_locked(entry, false, false, false, 0); - put_count = ttm_bo_del_from_lru(entry); + while (!list_empty(&man->lru)) { spin_unlock(&glob->lru_lock); - while (put_count--) - kref_put(&entry->list_kref, ttm_bo_ref_bug); - BUG_ON(ret); - ret = ttm_bo_leave_list(entry, mem_type, allow_errors); - ttm_bo_unreserve(entry); - kref_put(&entry->list_kref, ttm_bo_release_list); + ret = ttm_mem_evict_first(bdev, mem_type, false, false); + if (ret) { + if (allow_errors) { + return ret; + } else { + printk(KERN_ERR TTM_PFX + "Cleanup eviction failed\n"); + } + } spin_lock(&glob->lru_lock); } - spin_unlock(&glob->lru_lock); - return 0; } @@ -1246,7 +1253,7 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) ret = 0; if (mem_type > 0) { - ttm_bo_force_list_clean(bdev, &man->lru, mem_type, false); + ttm_bo_force_list_clean(bdev, mem_type, false); spin_lock(&glob->lru_lock); if (drm_mm_clean(&man->manager)) @@ -1279,12 +1286,12 @@ int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) return 0; } - return ttm_bo_force_list_clean(bdev, &man->lru, mem_type, true); + return ttm_bo_force_list_clean(bdev, mem_type, true); } EXPORT_SYMBOL(ttm_bo_evict_mm); int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, - unsigned long p_offset, unsigned long p_size) + unsigned long p_size) { int ret = -EINVAL; struct ttm_mem_type_manager *man; @@ -1314,7 +1321,7 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, type); return ret; } - ret = drm_mm_init(&man->manager, p_offset, p_size); + ret = drm_mm_init(&man->manager, 0, p_size); if (ret) return ret; } @@ -1463,7 +1470,7 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev, * Initialize the system memory buffer type. * Other types need to be driver / IOCTL initialized. */ - ret = ttm_bo_init_mm(bdev, TTM_PL_SYSTEM, 0, 0); + ret = ttm_bo_init_mm(bdev, TTM_PL_SYSTEM, 0); if (unlikely(ret != 0)) goto out_no_sys; @@ -1693,7 +1700,7 @@ int ttm_bo_block_reservation(struct ttm_buffer_object *bo, bool interruptible, ret = wait_event_interruptible (bo->event_queue, atomic_read(&bo->reserved) == 0); if (unlikely(ret != 0)) - return -ERESTART; + return ret; } else { wait_event(bo->event_queue, atomic_read(&bo->reserved) == 0); @@ -1722,12 +1729,14 @@ int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait) ttm_bo_unreserve(bo); return ret; } +EXPORT_SYMBOL(ttm_bo_synccpu_write_grab); void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo) { if (atomic_dec_and_test(&bo->cpu_writers)) wake_up_all(&bo->event_queue); } +EXPORT_SYMBOL(ttm_bo_synccpu_write_release); /** * A buffer object shrink method that tries to swap out the first diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 61c5572d2b91792a19d41dc633d58dc5b0fcfce8..2ecf7d0c64f63102bc512a80b2a340011bff8eec 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -369,6 +369,7 @@ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp) #endif return tmp; } +EXPORT_SYMBOL(ttm_io_prot); static int ttm_bo_ioremap(struct ttm_buffer_object *bo, unsigned long bus_base, diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 1c040d0403389c6b9285bc2cfa55c110134a3bb9..609a85a4d855127288cc30e234333d516a58e7d2 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -114,7 +114,7 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ret = ttm_bo_wait(bo, false, true, false); spin_unlock(&bo->lock); if (unlikely(ret != 0)) { - retval = (ret != -ERESTART) ? + retval = (ret != -ERESTARTSYS) ? VM_FAULT_SIGBUS : VM_FAULT_NOPAGE; goto out_unlock; } @@ -349,9 +349,6 @@ ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp, switch (ret) { case 0: break; - case -ERESTART: - ret = -EINTR; - goto out_unref; case -EBUSY: ret = -EAGAIN; goto out_unref; @@ -421,8 +418,6 @@ ssize_t ttm_bo_fbdev_io(struct ttm_buffer_object *bo, const char __user *wbuf, switch (ret) { case 0: break; - case -ERESTART: - return -EINTR; case -EBUSY: return -EAGAIN; default: diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c new file mode 100644 index 0000000000000000000000000000000000000000..c285c2902d15f23780b726bd29b0e351147cfdca --- /dev/null +++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c @@ -0,0 +1,117 @@ +/************************************************************************** + * + * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "ttm/ttm_execbuf_util.h" +#include "ttm/ttm_bo_driver.h" +#include "ttm/ttm_placement.h" +#include +#include +#include + +void ttm_eu_backoff_reservation(struct list_head *list) +{ + struct ttm_validate_buffer *entry; + + list_for_each_entry(entry, list, head) { + struct ttm_buffer_object *bo = entry->bo; + if (!entry->reserved) + continue; + + entry->reserved = false; + ttm_bo_unreserve(bo); + } +} +EXPORT_SYMBOL(ttm_eu_backoff_reservation); + +/* + * Reserve buffers for validation. + * + * If a buffer in the list is marked for CPU access, we back off and + * wait for that buffer to become free for GPU access. + * + * If a buffer is reserved for another validation, the validator with + * the highest validation sequence backs off and waits for that buffer + * to become unreserved. This prevents deadlocks when validating multiple + * buffers in different orders. + */ + +int ttm_eu_reserve_buffers(struct list_head *list, uint32_t val_seq) +{ + struct ttm_validate_buffer *entry; + int ret; + +retry: + list_for_each_entry(entry, list, head) { + struct ttm_buffer_object *bo = entry->bo; + + entry->reserved = false; + ret = ttm_bo_reserve(bo, true, false, true, val_seq); + if (ret != 0) { + ttm_eu_backoff_reservation(list); + if (ret == -EAGAIN) { + ret = ttm_bo_wait_unreserved(bo, true); + if (unlikely(ret != 0)) + return ret; + goto retry; + } else + return ret; + } + + entry->reserved = true; + if (unlikely(atomic_read(&bo->cpu_writers) > 0)) { + ttm_eu_backoff_reservation(list); + ret = ttm_bo_wait_cpu(bo, false); + if (ret) + return ret; + goto retry; + } + } + return 0; +} +EXPORT_SYMBOL(ttm_eu_reserve_buffers); + +void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj) +{ + struct ttm_validate_buffer *entry; + + list_for_each_entry(entry, list, head) { + struct ttm_buffer_object *bo = entry->bo; + struct ttm_bo_driver *driver = bo->bdev->driver; + void *old_sync_obj; + + spin_lock(&bo->lock); + old_sync_obj = bo->sync_obj; + bo->sync_obj = driver->sync_obj_ref(sync_obj); + bo->sync_obj_arg = entry->new_sync_obj_arg; + spin_unlock(&bo->lock); + ttm_bo_unreserve(bo); + entry->reserved = false; + if (old_sync_obj) + driver->sync_obj_unref(&old_sync_obj); + } +} +EXPORT_SYMBOL(ttm_eu_fence_buffer_objects); diff --git a/drivers/gpu/drm/ttm/ttm_lock.c b/drivers/gpu/drm/ttm/ttm_lock.c new file mode 100644 index 0000000000000000000000000000000000000000..f619ebcaa4ecf8a14198eab87b907c5b9162ccb8 --- /dev/null +++ b/drivers/gpu/drm/ttm/ttm_lock.c @@ -0,0 +1,311 @@ +/************************************************************************** + * + * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ +/* + * Authors: Thomas Hellstrom + */ + +#include "ttm/ttm_lock.h" +#include "ttm/ttm_module.h" +#include +#include +#include +#include +#include + +#define TTM_WRITE_LOCK_PENDING (1 << 0) +#define TTM_VT_LOCK_PENDING (1 << 1) +#define TTM_SUSPEND_LOCK_PENDING (1 << 2) +#define TTM_VT_LOCK (1 << 3) +#define TTM_SUSPEND_LOCK (1 << 4) + +void ttm_lock_init(struct ttm_lock *lock) +{ + spin_lock_init(&lock->lock); + init_waitqueue_head(&lock->queue); + lock->rw = 0; + lock->flags = 0; + lock->kill_takers = false; + lock->signal = SIGKILL; +} +EXPORT_SYMBOL(ttm_lock_init); + +void ttm_read_unlock(struct ttm_lock *lock) +{ + spin_lock(&lock->lock); + if (--lock->rw == 0) + wake_up_all(&lock->queue); + spin_unlock(&lock->lock); +} +EXPORT_SYMBOL(ttm_read_unlock); + +static bool __ttm_read_lock(struct ttm_lock *lock) +{ + bool locked = false; + + spin_lock(&lock->lock); + if (unlikely(lock->kill_takers)) { + send_sig(lock->signal, current, 0); + spin_unlock(&lock->lock); + return false; + } + if (lock->rw >= 0 && lock->flags == 0) { + ++lock->rw; + locked = true; + } + spin_unlock(&lock->lock); + return locked; +} + +int ttm_read_lock(struct ttm_lock *lock, bool interruptible) +{ + int ret = 0; + + if (interruptible) + ret = wait_event_interruptible(lock->queue, + __ttm_read_lock(lock)); + else + wait_event(lock->queue, __ttm_read_lock(lock)); + return ret; +} +EXPORT_SYMBOL(ttm_read_lock); + +static bool __ttm_read_trylock(struct ttm_lock *lock, bool *locked) +{ + bool block = true; + + *locked = false; + + spin_lock(&lock->lock); + if (unlikely(lock->kill_takers)) { + send_sig(lock->signal, current, 0); + spin_unlock(&lock->lock); + return false; + } + if (lock->rw >= 0 && lock->flags == 0) { + ++lock->rw; + block = false; + *locked = true; + } else if (lock->flags == 0) { + block = false; + } + spin_unlock(&lock->lock); + + return !block; +} + +int ttm_read_trylock(struct ttm_lock *lock, bool interruptible) +{ + int ret = 0; + bool locked; + + if (interruptible) + ret = wait_event_interruptible + (lock->queue, __ttm_read_trylock(lock, &locked)); + else + wait_event(lock->queue, __ttm_read_trylock(lock, &locked)); + + if (unlikely(ret != 0)) { + BUG_ON(locked); + return ret; + } + + return (locked) ? 0 : -EBUSY; +} + +void ttm_write_unlock(struct ttm_lock *lock) +{ + spin_lock(&lock->lock); + lock->rw = 0; + wake_up_all(&lock->queue); + spin_unlock(&lock->lock); +} +EXPORT_SYMBOL(ttm_write_unlock); + +static bool __ttm_write_lock(struct ttm_lock *lock) +{ + bool locked = false; + + spin_lock(&lock->lock); + if (unlikely(lock->kill_takers)) { + send_sig(lock->signal, current, 0); + spin_unlock(&lock->lock); + return false; + } + if (lock->rw == 0 && ((lock->flags & ~TTM_WRITE_LOCK_PENDING) == 0)) { + lock->rw = -1; + lock->flags &= ~TTM_WRITE_LOCK_PENDING; + locked = true; + } else { + lock->flags |= TTM_WRITE_LOCK_PENDING; + } + spin_unlock(&lock->lock); + return locked; +} + +int ttm_write_lock(struct ttm_lock *lock, bool interruptible) +{ + int ret = 0; + + if (interruptible) { + ret = wait_event_interruptible(lock->queue, + __ttm_write_lock(lock)); + if (unlikely(ret != 0)) { + spin_lock(&lock->lock); + lock->flags &= ~TTM_WRITE_LOCK_PENDING; + wake_up_all(&lock->queue); + spin_unlock(&lock->lock); + } + } else + wait_event(lock->queue, __ttm_read_lock(lock)); + + return ret; +} +EXPORT_SYMBOL(ttm_write_lock); + +void ttm_write_lock_downgrade(struct ttm_lock *lock) +{ + spin_lock(&lock->lock); + lock->rw = 1; + wake_up_all(&lock->queue); + spin_unlock(&lock->lock); +} + +static int __ttm_vt_unlock(struct ttm_lock *lock) +{ + int ret = 0; + + spin_lock(&lock->lock); + if (unlikely(!(lock->flags & TTM_VT_LOCK))) + ret = -EINVAL; + lock->flags &= ~TTM_VT_LOCK; + wake_up_all(&lock->queue); + spin_unlock(&lock->lock); + printk(KERN_INFO TTM_PFX "vt unlock.\n"); + + return ret; +} + +static void ttm_vt_lock_remove(struct ttm_base_object **p_base) +{ + struct ttm_base_object *base = *p_base; + struct ttm_lock *lock = container_of(base, struct ttm_lock, base); + int ret; + + *p_base = NULL; + ret = __ttm_vt_unlock(lock); + BUG_ON(ret != 0); +} + +static bool __ttm_vt_lock(struct ttm_lock *lock) +{ + bool locked = false; + + spin_lock(&lock->lock); + if (lock->rw == 0) { + lock->flags &= ~TTM_VT_LOCK_PENDING; + lock->flags |= TTM_VT_LOCK; + locked = true; + } else { + lock->flags |= TTM_VT_LOCK_PENDING; + } + spin_unlock(&lock->lock); + return locked; +} + +int ttm_vt_lock(struct ttm_lock *lock, + bool interruptible, + struct ttm_object_file *tfile) +{ + int ret = 0; + + if (interruptible) { + ret = wait_event_interruptible(lock->queue, + __ttm_vt_lock(lock)); + if (unlikely(ret != 0)) { + spin_lock(&lock->lock); + lock->flags &= ~TTM_VT_LOCK_PENDING; + wake_up_all(&lock->queue); + spin_unlock(&lock->lock); + return ret; + } + } else + wait_event(lock->queue, __ttm_vt_lock(lock)); + + /* + * Add a base-object, the destructor of which will + * make sure the lock is released if the client dies + * while holding it. + */ + + ret = ttm_base_object_init(tfile, &lock->base, false, + ttm_lock_type, &ttm_vt_lock_remove, NULL); + if (ret) + (void)__ttm_vt_unlock(lock); + else { + lock->vt_holder = tfile; + printk(KERN_INFO TTM_PFX "vt lock.\n"); + } + + return ret; +} +EXPORT_SYMBOL(ttm_vt_lock); + +int ttm_vt_unlock(struct ttm_lock *lock) +{ + return ttm_ref_object_base_unref(lock->vt_holder, + lock->base.hash.key, TTM_REF_USAGE); +} +EXPORT_SYMBOL(ttm_vt_unlock); + +void ttm_suspend_unlock(struct ttm_lock *lock) +{ + spin_lock(&lock->lock); + lock->flags &= ~TTM_SUSPEND_LOCK; + wake_up_all(&lock->queue); + spin_unlock(&lock->lock); +} + +static bool __ttm_suspend_lock(struct ttm_lock *lock) +{ + bool locked = false; + + spin_lock(&lock->lock); + if (lock->rw == 0) { + lock->flags &= ~TTM_SUSPEND_LOCK_PENDING; + lock->flags |= TTM_SUSPEND_LOCK; + locked = true; + } else { + lock->flags |= TTM_SUSPEND_LOCK_PENDING; + } + spin_unlock(&lock->lock); + return locked; +} + +void ttm_suspend_lock(struct ttm_lock *lock) +{ + wait_event(lock->queue, __ttm_suspend_lock(lock)); +} diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c index 072c281a6bb5bd07ed491ad67b6265684eb0c7fb..f5245c02b8fd0b927f6d38db3bd997e57e1e3e98 100644 --- a/drivers/gpu/drm/ttm/ttm_memory.c +++ b/drivers/gpu/drm/ttm/ttm_memory.c @@ -274,16 +274,17 @@ static int ttm_mem_init_kernel_zone(struct ttm_mem_global *glob, static int ttm_mem_init_highmem_zone(struct ttm_mem_global *glob, const struct sysinfo *si) { - struct ttm_mem_zone *zone = kzalloc(sizeof(*zone), GFP_KERNEL); + struct ttm_mem_zone *zone; uint64_t mem; int ret; - if (unlikely(!zone)) - return -ENOMEM; - if (si->totalhigh == 0) return 0; + zone = kzalloc(sizeof(*zone), GFP_KERNEL); + if (unlikely(!zone)) + return -ENOMEM; + mem = si->totalram; mem *= si->mem_unit; @@ -322,8 +323,10 @@ static int ttm_mem_init_dma32_zone(struct ttm_mem_global *glob, * No special dma32 zone needed. */ - if (mem <= ((uint64_t) 1ULL << 32)) + if (mem <= ((uint64_t) 1ULL << 32)) { + kfree(zone); return 0; + } /* * Limit max dma32 memory to 4GB for now @@ -460,6 +463,7 @@ void ttm_mem_global_free(struct ttm_mem_global *glob, { return ttm_mem_global_free_zone(glob, NULL, amount); } +EXPORT_SYMBOL(ttm_mem_global_free); static int ttm_mem_global_reserve(struct ttm_mem_global *glob, struct ttm_mem_zone *single_zone, @@ -533,6 +537,7 @@ int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory, return ttm_mem_global_alloc_zone(glob, NULL, memory, no_wait, interruptible); } +EXPORT_SYMBOL(ttm_mem_global_alloc); int ttm_mem_global_alloc_page(struct ttm_mem_global *glob, struct page *page, @@ -588,3 +593,4 @@ size_t ttm_round_pot(size_t size) } return 0; } +EXPORT_SYMBOL(ttm_round_pot); diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/ttm/ttm_object.c new file mode 100644 index 0000000000000000000000000000000000000000..1099abac824b16ee35931f8631e375bffb1edb35 --- /dev/null +++ b/drivers/gpu/drm/ttm/ttm_object.c @@ -0,0 +1,452 @@ +/************************************************************************** + * + * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ +/* + * Authors: Thomas Hellstrom + */ +/** @file ttm_ref_object.c + * + * Base- and reference object implementation for the various + * ttm objects. Implements reference counting, minimal security checks + * and release on file close. + */ + +/** + * struct ttm_object_file + * + * @tdev: Pointer to the ttm_object_device. + * + * @lock: Lock that protects the ref_list list and the + * ref_hash hash tables. + * + * @ref_list: List of ttm_ref_objects to be destroyed at + * file release. + * + * @ref_hash: Hash tables of ref objects, one per ttm_ref_type, + * for fast lookup of ref objects given a base object. + */ + +#include "ttm/ttm_object.h" +#include "ttm/ttm_module.h" +#include +#include +#include +#include +#include + +struct ttm_object_file { + struct ttm_object_device *tdev; + rwlock_t lock; + struct list_head ref_list; + struct drm_open_hash ref_hash[TTM_REF_NUM]; + struct kref refcount; +}; + +/** + * struct ttm_object_device + * + * @object_lock: lock that protects the object_hash hash table. + * + * @object_hash: hash table for fast lookup of object global names. + * + * @object_count: Per device object count. + * + * This is the per-device data structure needed for ttm object management. + */ + +struct ttm_object_device { + rwlock_t object_lock; + struct drm_open_hash object_hash; + atomic_t object_count; + struct ttm_mem_global *mem_glob; +}; + +/** + * struct ttm_ref_object + * + * @hash: Hash entry for the per-file object reference hash. + * + * @head: List entry for the per-file list of ref-objects. + * + * @kref: Ref count. + * + * @obj: Base object this ref object is referencing. + * + * @ref_type: Type of ref object. + * + * This is similar to an idr object, but it also has a hash table entry + * that allows lookup with a pointer to the referenced object as a key. In + * that way, one can easily detect whether a base object is referenced by + * a particular ttm_object_file. It also carries a ref count to avoid creating + * multiple ref objects if a ttm_object_file references the same base + * object more than once. + */ + +struct ttm_ref_object { + struct drm_hash_item hash; + struct list_head head; + struct kref kref; + struct ttm_base_object *obj; + enum ttm_ref_type ref_type; + struct ttm_object_file *tfile; +}; + +static inline struct ttm_object_file * +ttm_object_file_ref(struct ttm_object_file *tfile) +{ + kref_get(&tfile->refcount); + return tfile; +} + +static void ttm_object_file_destroy(struct kref *kref) +{ + struct ttm_object_file *tfile = + container_of(kref, struct ttm_object_file, refcount); + + kfree(tfile); +} + + +static inline void ttm_object_file_unref(struct ttm_object_file **p_tfile) +{ + struct ttm_object_file *tfile = *p_tfile; + + *p_tfile = NULL; + kref_put(&tfile->refcount, ttm_object_file_destroy); +} + + +int ttm_base_object_init(struct ttm_object_file *tfile, + struct ttm_base_object *base, + bool shareable, + enum ttm_object_type object_type, + void (*refcount_release) (struct ttm_base_object **), + void (*ref_obj_release) (struct ttm_base_object *, + enum ttm_ref_type ref_type)) +{ + struct ttm_object_device *tdev = tfile->tdev; + int ret; + + base->shareable = shareable; + base->tfile = ttm_object_file_ref(tfile); + base->refcount_release = refcount_release; + base->ref_obj_release = ref_obj_release; + base->object_type = object_type; + write_lock(&tdev->object_lock); + kref_init(&base->refcount); + ret = drm_ht_just_insert_please(&tdev->object_hash, + &base->hash, + (unsigned long)base, 31, 0, 0); + write_unlock(&tdev->object_lock); + if (unlikely(ret != 0)) + goto out_err0; + + ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL); + if (unlikely(ret != 0)) + goto out_err1; + + ttm_base_object_unref(&base); + + return 0; +out_err1: + (void)drm_ht_remove_item(&tdev->object_hash, &base->hash); +out_err0: + return ret; +} +EXPORT_SYMBOL(ttm_base_object_init); + +static void ttm_release_base(struct kref *kref) +{ + struct ttm_base_object *base = + container_of(kref, struct ttm_base_object, refcount); + struct ttm_object_device *tdev = base->tfile->tdev; + + (void)drm_ht_remove_item(&tdev->object_hash, &base->hash); + write_unlock(&tdev->object_lock); + if (base->refcount_release) { + ttm_object_file_unref(&base->tfile); + base->refcount_release(&base); + } + write_lock(&tdev->object_lock); +} + +void ttm_base_object_unref(struct ttm_base_object **p_base) +{ + struct ttm_base_object *base = *p_base; + struct ttm_object_device *tdev = base->tfile->tdev; + + *p_base = NULL; + + /* + * Need to take the lock here to avoid racing with + * users trying to look up the object. + */ + + write_lock(&tdev->object_lock); + (void)kref_put(&base->refcount, &ttm_release_base); + write_unlock(&tdev->object_lock); +} +EXPORT_SYMBOL(ttm_base_object_unref); + +struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile, + uint32_t key) +{ + struct ttm_object_device *tdev = tfile->tdev; + struct ttm_base_object *base; + struct drm_hash_item *hash; + int ret; + + read_lock(&tdev->object_lock); + ret = drm_ht_find_item(&tdev->object_hash, key, &hash); + + if (likely(ret == 0)) { + base = drm_hash_entry(hash, struct ttm_base_object, hash); + kref_get(&base->refcount); + } + read_unlock(&tdev->object_lock); + + if (unlikely(ret != 0)) + return NULL; + + if (tfile != base->tfile && !base->shareable) { + printk(KERN_ERR TTM_PFX + "Attempted access of non-shareable object.\n"); + ttm_base_object_unref(&base); + return NULL; + } + + return base; +} +EXPORT_SYMBOL(ttm_base_object_lookup); + +int ttm_ref_object_add(struct ttm_object_file *tfile, + struct ttm_base_object *base, + enum ttm_ref_type ref_type, bool *existed) +{ + struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; + struct ttm_ref_object *ref; + struct drm_hash_item *hash; + struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob; + int ret = -EINVAL; + + if (existed != NULL) + *existed = true; + + while (ret == -EINVAL) { + read_lock(&tfile->lock); + ret = drm_ht_find_item(ht, base->hash.key, &hash); + + if (ret == 0) { + ref = drm_hash_entry(hash, struct ttm_ref_object, hash); + kref_get(&ref->kref); + read_unlock(&tfile->lock); + break; + } + + read_unlock(&tfile->lock); + ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref), + false, false); + if (unlikely(ret != 0)) + return ret; + ref = kmalloc(sizeof(*ref), GFP_KERNEL); + if (unlikely(ref == NULL)) { + ttm_mem_global_free(mem_glob, sizeof(*ref)); + return -ENOMEM; + } + + ref->hash.key = base->hash.key; + ref->obj = base; + ref->tfile = tfile; + ref->ref_type = ref_type; + kref_init(&ref->kref); + + write_lock(&tfile->lock); + ret = drm_ht_insert_item(ht, &ref->hash); + + if (likely(ret == 0)) { + list_add_tail(&ref->head, &tfile->ref_list); + kref_get(&base->refcount); + write_unlock(&tfile->lock); + if (existed != NULL) + *existed = false; + break; + } + + write_unlock(&tfile->lock); + BUG_ON(ret != -EINVAL); + + ttm_mem_global_free(mem_glob, sizeof(*ref)); + kfree(ref); + } + + return ret; +} +EXPORT_SYMBOL(ttm_ref_object_add); + +static void ttm_ref_object_release(struct kref *kref) +{ + struct ttm_ref_object *ref = + container_of(kref, struct ttm_ref_object, kref); + struct ttm_base_object *base = ref->obj; + struct ttm_object_file *tfile = ref->tfile; + struct drm_open_hash *ht; + struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob; + + ht = &tfile->ref_hash[ref->ref_type]; + (void)drm_ht_remove_item(ht, &ref->hash); + list_del(&ref->head); + write_unlock(&tfile->lock); + + if (ref->ref_type != TTM_REF_USAGE && base->ref_obj_release) + base->ref_obj_release(base, ref->ref_type); + + ttm_base_object_unref(&ref->obj); + ttm_mem_global_free(mem_glob, sizeof(*ref)); + kfree(ref); + write_lock(&tfile->lock); +} + +int ttm_ref_object_base_unref(struct ttm_object_file *tfile, + unsigned long key, enum ttm_ref_type ref_type) +{ + struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; + struct ttm_ref_object *ref; + struct drm_hash_item *hash; + int ret; + + write_lock(&tfile->lock); + ret = drm_ht_find_item(ht, key, &hash); + if (unlikely(ret != 0)) { + write_unlock(&tfile->lock); + return -EINVAL; + } + ref = drm_hash_entry(hash, struct ttm_ref_object, hash); + kref_put(&ref->kref, ttm_ref_object_release); + write_unlock(&tfile->lock); + return 0; +} +EXPORT_SYMBOL(ttm_ref_object_base_unref); + +void ttm_object_file_release(struct ttm_object_file **p_tfile) +{ + struct ttm_ref_object *ref; + struct list_head *list; + unsigned int i; + struct ttm_object_file *tfile = *p_tfile; + + *p_tfile = NULL; + write_lock(&tfile->lock); + + /* + * Since we release the lock within the loop, we have to + * restart it from the beginning each time. + */ + + while (!list_empty(&tfile->ref_list)) { + list = tfile->ref_list.next; + ref = list_entry(list, struct ttm_ref_object, head); + ttm_ref_object_release(&ref->kref); + } + + for (i = 0; i < TTM_REF_NUM; ++i) + drm_ht_remove(&tfile->ref_hash[i]); + + write_unlock(&tfile->lock); + ttm_object_file_unref(&tfile); +} +EXPORT_SYMBOL(ttm_object_file_release); + +struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev, + unsigned int hash_order) +{ + struct ttm_object_file *tfile = kmalloc(sizeof(*tfile), GFP_KERNEL); + unsigned int i; + unsigned int j = 0; + int ret; + + if (unlikely(tfile == NULL)) + return NULL; + + rwlock_init(&tfile->lock); + tfile->tdev = tdev; + kref_init(&tfile->refcount); + INIT_LIST_HEAD(&tfile->ref_list); + + for (i = 0; i < TTM_REF_NUM; ++i) { + ret = drm_ht_create(&tfile->ref_hash[i], hash_order); + if (ret) { + j = i; + goto out_err; + } + } + + return tfile; +out_err: + for (i = 0; i < j; ++i) + drm_ht_remove(&tfile->ref_hash[i]); + + kfree(tfile); + + return NULL; +} +EXPORT_SYMBOL(ttm_object_file_init); + +struct ttm_object_device *ttm_object_device_init(struct ttm_mem_global + *mem_glob, + unsigned int hash_order) +{ + struct ttm_object_device *tdev = kmalloc(sizeof(*tdev), GFP_KERNEL); + int ret; + + if (unlikely(tdev == NULL)) + return NULL; + + tdev->mem_glob = mem_glob; + rwlock_init(&tdev->object_lock); + atomic_set(&tdev->object_count, 0); + ret = drm_ht_create(&tdev->object_hash, hash_order); + + if (likely(ret == 0)) + return tdev; + + kfree(tdev); + return NULL; +} +EXPORT_SYMBOL(ttm_object_device_init); + +void ttm_object_device_release(struct ttm_object_device **p_tdev) +{ + struct ttm_object_device *tdev = *p_tdev; + + *p_tdev = NULL; + + write_lock(&tdev->object_lock); + drm_ht_remove(&tdev->object_hash); + write_unlock(&tdev->object_lock); + + kfree(tdev); +} +EXPORT_SYMBOL(ttm_object_device_release); diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 7bcb89f39ce8912b79d565e8b60228e542a08301..9c2b1cc5dba5a10b586d4c8b9a6dc6ffeb02a376 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -192,6 +192,7 @@ int ttm_tt_populate(struct ttm_tt *ttm) ttm->state = tt_unbound; return 0; } +EXPORT_SYMBOL(ttm_tt_populate); #ifdef CONFIG_X86 static inline int ttm_tt_set_page_caching(struct page *p, diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 0258289f3b3e649f04e5447f0d53221d1df07222..e2997a8d5e1b4b726ac9b62f0d60e2647ae37ce4 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1253,10 +1253,9 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) { struct hid_device *hid = usb_get_intfdata(intf); struct usbhid_device *usbhid = hid->driver_data; - struct usb_device *udev = interface_to_usbdev(intf); int status; - if (udev->auto_pm) { + if (message.event & PM_EVENT_AUTO) { spin_lock_irq(&usbhid->lock); /* Sync with error handler */ if (!test_bit(HID_RESET_PENDING, &usbhid->iofl) && !test_bit(HID_CLEAR_HALT, &usbhid->iofl) @@ -1281,7 +1280,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) return -EIO; } - if (!ignoreled && udev->auto_pm) { + if (!ignoreled && (message.event & PM_EVENT_AUTO)) { spin_lock_irq(&usbhid->lock); if (test_bit(HID_LED_ON, &usbhid->iofl)) { spin_unlock_irq(&usbhid->lock); @@ -1294,7 +1293,8 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) hid_cancel_delayed_stuff(usbhid); hid_cease_io(usbhid); - if (udev->auto_pm && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) { + if ((message.event & PM_EVENT_AUTO) && + test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) { /* lost race against keypresses */ status = hid_start_in(hid); if (status < 0) diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c index 97642a7a79c4143afc17e04db691cf555ddc8b40..7a4e788cab2f54d5c031cb814e2d42db7ca0e855 100644 --- a/drivers/ide/pmac.c +++ b/drivers/ide/pmac.c @@ -43,10 +43,7 @@ #include #include #include - -#ifndef CONFIG_PPC64 #include -#endif #define DRV_NAME "ide-pmac" @@ -59,13 +56,14 @@ typedef struct pmac_ide_hwif { int irq; int kind; int aapl_bus_id; - unsigned mediabay : 1; unsigned broken_dma : 1; unsigned broken_dma_warn : 1; struct device_node* node; struct macio_dev *mdev; u32 timings[4]; volatile u32 __iomem * *kauai_fcr; + ide_hwif_t *hwif; + /* Those fields are duplicating what is in hwif. We currently * can't use the hwif ones because of some assumptions that are * beeing done by the generic code about the kind of dma controller @@ -854,6 +852,11 @@ sanitize_timings(pmac_ide_hwif_t *pmif) pmif->timings[2] = pmif->timings[3] = value2; } +static int on_media_bay(pmac_ide_hwif_t *pmif) +{ + return pmif->mdev && pmif->mdev->media_bay != NULL; +} + /* Suspend call back, should be called after the child devices * have actually been suspended */ @@ -866,7 +869,7 @@ static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif) disable_irq(pmif->irq); /* The media bay will handle itself just fine */ - if (pmif->mediabay) + if (on_media_bay(pmif)) return 0; /* Kauai has bus control FCRs directly here */ @@ -889,7 +892,7 @@ static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif) static int pmac_ide_do_resume(pmac_ide_hwif_t *pmif) { /* Hard reset & re-enable controller (do we really need to reset ? -BenH) */ - if (!pmif->mediabay) { + if (!on_media_bay(pmif)) { ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1); ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1); msleep(10); @@ -950,13 +953,11 @@ static void pmac_ide_init_dev(ide_drive_t *drive) pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - if (pmif->mediabay) { -#ifdef CONFIG_PMAC_MEDIABAY - if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) { + if (on_media_bay(pmif)) { + if (check_media_bay(pmif->mdev->media_bay) == MB_CD) { drive->dev_flags &= ~IDE_DFLAG_NOPROBE; return; } -#endif drive->dev_flags |= IDE_DFLAG_NOPROBE; } } @@ -1072,26 +1073,23 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, writel(KAUAI_FCR_UATA_MAGIC | KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr); - - pmif->mediabay = 0; /* Make sure we have sane timings */ sanitize_timings(pmif); + /* If we are on a media bay, wait for it to settle and lock it */ + if (pmif->mdev) + lock_media_bay(pmif->mdev->media_bay); + host = ide_host_alloc(&d, hws, 1); - if (host == NULL) - return -ENOMEM; - hwif = host->ports[0]; + if (host == NULL) { + rc = -ENOMEM; + goto bail; + } + hwif = pmif->hwif = host->ports[0]; -#ifndef CONFIG_PPC64 - /* XXX FIXME: Media bay stuff need re-organizing */ - if (np->parent && np->parent->name - && strcasecmp(np->parent->name, "media-bay") == 0) { -#ifdef CONFIG_PMAC_MEDIABAY - media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, - hwif); -#endif /* CONFIG_PMAC_MEDIABAY */ - pmif->mediabay = 1; + if (on_media_bay(pmif)) { + /* Fixup bus ID for media bay */ if (!bidp) pmif->aapl_bus_id = 1; } else if (pmif->kind == controller_ohare) { @@ -1100,9 +1098,7 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, * units, I keep the old way */ ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1); - } else -#endif - { + } else { /* This is necessary to enable IDE when net-booting */ ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1); ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1); @@ -1112,17 +1108,21 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, } printk(KERN_INFO DRV_NAME ": Found Apple %s controller (%s), " - "bus ID %d%s, irq %d\n", model_name[pmif->kind], - pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id, - pmif->mediabay ? " (mediabay)" : "", hw->irq); + "bus ID %d%s, irq %d\n", model_name[pmif->kind], + pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id, + on_media_bay(pmif) ? " (mediabay)" : "", hw->irq); rc = ide_host_register(host, &d, hws); - if (rc) { - ide_host_free(host); - return rc; - } + if (rc) + pmif->hwif = NULL; - return 0; + if (pmif->mdev) + unlock_media_bay(pmif->mdev->media_bay); + + bail: + if (rc && host) + ide_host_free(host); + return rc; } static void __devinit pmac_ide_init_ports(struct ide_hw *hw, unsigned long base) @@ -1362,6 +1362,25 @@ pmac_ide_pci_resume(struct pci_dev *pdev) return rc; } +#ifdef CONFIG_PMAC_MEDIABAY +static void pmac_ide_macio_mb_event(struct macio_dev* mdev, int mb_state) +{ + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); + + switch(mb_state) { + case MB_CD: + if (!pmif->hwif->present) + ide_port_scan(pmif->hwif); + break; + default: + if (pmif->hwif->present) + ide_port_unregister_devices(pmif->hwif); + } +} +#endif /* CONFIG_PMAC_MEDIABAY */ + + static struct of_device_id pmac_ide_macio_match[] = { { @@ -1386,6 +1405,9 @@ static struct macio_driver pmac_ide_macio_driver = .probe = pmac_ide_macio_attach, .suspend = pmac_ide_macio_suspend, .resume = pmac_ide_macio_resume, +#ifdef CONFIG_PMAC_MEDIABAY + .mediabay_event = pmac_ide_macio_mb_event, +#endif }; static const struct pci_device_id pmac_ide_pci_match[] = { diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index 4b89b791be6a3cf5fdb7947638778ddd4451f8ab..42be0b15084bb2445e6024eea21033d765bf7438 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c @@ -826,8 +826,7 @@ static void __cpuinit take_over_work(struct ehca_comp_pool *pool, int cpu) cq = list_entry(cct->cq_list.next, struct ehca_cq, entry); list_del(&cq->entry); - __queue_comp_task(cq, per_cpu_ptr(pool->cpu_comp_tasks, - smp_processor_id())); + __queue_comp_task(cq, this_cpu_ptr(pool->cpu_comp_tasks)); } spin_unlock_irqrestore(&cct->task_lock, flags_cct); diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 50af91ebd07522e84461f3eecbb5c84f431da61e..07c2cd43109c1ea0332cfaefa0bdb30ceb801db3 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -165,6 +165,7 @@ config XEN_KBDDEV_FRONTEND tristate "Xen virtual keyboard and mouse support" depends on XEN_FBDEV_FRONTEND default y + select XEN_XENBUS_FRONTEND help This driver implements the front-end of the Xen virtual keyboard and mouse device driver. It communicates with a back-end diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 203b88a82b5658ae28c66d915db48323bb48bf6d..02c836e11813601471de72653381584bdca9684a 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -24,6 +24,16 @@ config KEYBOARD_AAED2000 To compile this driver as a module, choose M here: the module will be called aaed2000_kbd. +config KEYBOARD_ADP5520 + tristate "Keypad Support for ADP5520 PMIC" + depends on PMIC_ADP5520 + help + This option enables support for the keypad scan matrix + on Analog Devices ADP5520 PMICs. + + To compile this driver as a module, choose M here: the module will + be called adp5520-keys. + config KEYBOARD_ADP5588 tristate "ADP5588 I2C QWERTY Keypad and IO Expander" depends on I2C diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 68c017235ce9c2db3633456b2ac78bf38cf92cb0..78654ef6520644c98710b6ff640acd37bc8c224d 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -5,6 +5,7 @@ # Each configuration option enables a list of files. obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o +obj-$(CONFIG_KEYBOARD_ADP5520) += adp5520-keys.o obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c new file mode 100644 index 0000000000000000000000000000000000000000..a7ba27fb4109e32b7fff3bb8b22e67b93eb2967e --- /dev/null +++ b/drivers/input/keyboard/adp5520-keys.c @@ -0,0 +1,220 @@ +/* + * Keypad driver for Analog Devices ADP5520 MFD PMICs + * + * Copyright 2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include + +struct adp5520_keys { + struct input_dev *input; + struct notifier_block notifier; + struct device *master; + unsigned short keycode[ADP5520_KEYMAPSIZE]; +}; + +static void adp5520_keys_report_event(struct adp5520_keys *dev, + unsigned short keymask, int value) +{ + int i; + + for (i = 0; i < ADP5520_MAXKEYS; i++) + if (keymask & (1 << i)) + input_report_key(dev->input, dev->keycode[i], value); + + input_sync(dev->input); +} + +static int adp5520_keys_notifier(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct adp5520_keys *dev; + uint8_t reg_val_lo, reg_val_hi; + unsigned short keymask; + + dev = container_of(nb, struct adp5520_keys, notifier); + + if (event & ADP5520_KP_INT) { + adp5520_read(dev->master, ADP5520_KP_INT_STAT_1, ®_val_lo); + adp5520_read(dev->master, ADP5520_KP_INT_STAT_2, ®_val_hi); + + keymask = (reg_val_hi << 8) | reg_val_lo; + /* Read twice to clear */ + adp5520_read(dev->master, ADP5520_KP_INT_STAT_1, ®_val_lo); + adp5520_read(dev->master, ADP5520_KP_INT_STAT_2, ®_val_hi); + keymask |= (reg_val_hi << 8) | reg_val_lo; + adp5520_keys_report_event(dev, keymask, 1); + } + + if (event & ADP5520_KR_INT) { + adp5520_read(dev->master, ADP5520_KR_INT_STAT_1, ®_val_lo); + adp5520_read(dev->master, ADP5520_KR_INT_STAT_2, ®_val_hi); + + keymask = (reg_val_hi << 8) | reg_val_lo; + /* Read twice to clear */ + adp5520_read(dev->master, ADP5520_KR_INT_STAT_1, ®_val_lo); + adp5520_read(dev->master, ADP5520_KR_INT_STAT_2, ®_val_hi); + keymask |= (reg_val_hi << 8) | reg_val_lo; + adp5520_keys_report_event(dev, keymask, 0); + } + + return 0; +} + +static int __devinit adp5520_keys_probe(struct platform_device *pdev) +{ + struct adp5520_keys_platform_data *pdata = pdev->dev.platform_data; + struct input_dev *input; + struct adp5520_keys *dev; + int ret, i; + unsigned char en_mask, ctl_mask = 0; + + if (pdev->id != ID_ADP5520) { + dev_err(&pdev->dev, "only ADP5520 supports Keypad\n"); + return -EINVAL; + } + + if (pdata == NULL) { + dev_err(&pdev->dev, "missing platform data\n"); + return -EINVAL; + } + + if (!(pdata->rows_en_mask && pdata->cols_en_mask)) + return -EINVAL; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + dev_err(&pdev->dev, "failed to alloc memory\n"); + return -ENOMEM; + } + + input = input_allocate_device(); + if (!input) { + ret = -ENOMEM; + goto err; + } + + dev->master = pdev->dev.parent; + dev->input = input; + + input->name = pdev->name; + input->phys = "adp5520-keys/input0"; + input->dev.parent = &pdev->dev; + + input_set_drvdata(input, dev); + + input->id.bustype = BUS_I2C; + input->id.vendor = 0x0001; + input->id.product = 0x5520; + input->id.version = 0x0001; + + input->keycodesize = sizeof(dev->keycode[0]); + input->keycodemax = pdata->keymapsize; + input->keycode = dev->keycode; + + memcpy(dev->keycode, pdata->keymap, + pdata->keymapsize * input->keycodesize); + + /* setup input device */ + __set_bit(EV_KEY, input->evbit); + + if (pdata->repeat) + __set_bit(EV_REP, input->evbit); + + for (i = 0; i < input->keycodemax; i++) + __set_bit(dev->keycode[i], input->keybit); + __clear_bit(KEY_RESERVED, input->keybit); + + ret = input_register_device(input); + if (ret) { + dev_err(&pdev->dev, "unable to register input device\n"); + goto err; + } + + en_mask = pdata->rows_en_mask | pdata->cols_en_mask; + + ret = adp5520_set_bits(dev->master, ADP5520_GPIO_CFG_1, en_mask); + + if (en_mask & ADP5520_COL_C3) + ctl_mask |= ADP5520_C3_MODE; + + if (en_mask & ADP5520_ROW_R3) + ctl_mask |= ADP5520_R3_MODE; + + if (ctl_mask) + ret |= adp5520_set_bits(dev->master, ADP5520_LED_CONTROL, + ctl_mask); + + ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_PULLUP, + pdata->rows_en_mask); + + if (ret) { + dev_err(&pdev->dev, "failed to write\n"); + ret = -EIO; + goto err1; + } + + dev->notifier.notifier_call = adp5520_keys_notifier; + ret = adp5520_register_notifier(dev->master, &dev->notifier, + ADP5520_KP_IEN | ADP5520_KR_IEN); + if (ret) { + dev_err(&pdev->dev, "failed to register notifier\n"); + goto err1; + } + + platform_set_drvdata(pdev, dev); + return 0; + +err1: + input_unregister_device(input); + input = NULL; +err: + input_free_device(input); + kfree(dev); + return ret; +} + +static int __devexit adp5520_keys_remove(struct platform_device *pdev) +{ + struct adp5520_keys *dev = platform_get_drvdata(pdev); + + adp5520_unregister_notifier(dev->master, &dev->notifier, + ADP5520_KP_IEN | ADP5520_KR_IEN); + + input_unregister_device(dev->input); + kfree(dev); + return 0; +} + +static struct platform_driver adp5520_keys_driver = { + .driver = { + .name = "adp5520-keys", + .owner = THIS_MODULE, + }, + .probe = adp5520_keys_probe, + .remove = __devexit_p(adp5520_keys_remove), +}; + +static int __init adp5520_keys_init(void) +{ + return platform_driver_register(&adp5520_keys_driver); +} +module_init(adp5520_keys_init); + +static void __exit adp5520_keys_exit(void) +{ + platform_driver_unregister(&adp5520_keys_driver); +} +module_exit(adp5520_keys_exit); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Keys ADP5520 Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:adp5520-keys"); diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index 9a2977c216967d3c7a23daca744e8f136663c213..eeaa7acb9cfcfcc4ebf847a7035874a60c169d72 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include /* @@ -133,7 +133,7 @@ struct twl4030_keypad { static int twl4030_kpread(struct twl4030_keypad *kp, u8 *data, u32 reg, u8 num_bytes) { - int ret = twl4030_i2c_read(TWL4030_MODULE_KEYPAD, data, reg, num_bytes); + int ret = twl_i2c_read(TWL4030_MODULE_KEYPAD, data, reg, num_bytes); if (ret < 0) dev_warn(kp->dbg_dev, @@ -145,7 +145,7 @@ static int twl4030_kpread(struct twl4030_keypad *kp, static int twl4030_kpwrite_u8(struct twl4030_keypad *kp, u8 data, u32 reg) { - int ret = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, data, reg); + int ret = twl_i2c_write_u8(TWL4030_MODULE_KEYPAD, data, reg); if (ret < 0) dev_warn(kp->dbg_dev, diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c index 039dcb00ebd96250efea2a7b5903cb4521dee60f..008de0c5834b711d5efbf2de439f0104a3019916 100644 --- a/drivers/input/misc/pcf50633-input.c +++ b/drivers/input/misc/pcf50633-input.c @@ -55,7 +55,6 @@ pcf50633_input_irq(int irq, void *data) static int __devinit pcf50633_input_probe(struct platform_device *pdev) { struct pcf50633_input *input; - struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data; struct input_dev *input_dev; int ret; @@ -71,7 +70,7 @@ static int __devinit pcf50633_input_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, input); - input->pcf = pdata->pcf; + input->pcf = dev_to_pcf50633(pdev->dev.parent); input->input_dev = input_dev; input_dev->name = "PCF50633 PMU events"; @@ -85,9 +84,9 @@ static int __devinit pcf50633_input_probe(struct platform_device *pdev) kfree(input); return ret; } - pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ONKEYR, + pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYR, pcf50633_input_irq, input); - pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ONKEYF, + pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYF, pcf50633_input_irq, input); return 0; diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index f5fc9974a111842cd18af2bfd21ef9f762cd3c05..bdde5c8890358aa9ea7025008c93501f098b370d 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #define PWR_PWRON_IRQ (1 << 0) @@ -49,7 +49,7 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr) local_irq_enable(); #endif - err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value, + err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value, STS_HW_CONDITIONS); if (!err) { input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ); diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c index b115726dc088b169003a725ba29de8a4171e58a9..c721c0a23eb831d20672e16120b3278e8901f428 100644 --- a/drivers/input/xen-kbdfront.c +++ b/drivers/input/xen-kbdfront.c @@ -21,7 +21,10 @@ #include #include #include + #include + +#include #include #include #include diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 82ed1cd14ff50c7d8279e2cf4f7d62ca65a14a5e..664b0c519c3e63db2a096908ee0015cba0e14e27 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -29,7 +29,7 @@ #endif /* Module parameters */ -int gigaset_debuglevel = DEBUG_DEFAULT; +int gigaset_debuglevel; EXPORT_SYMBOL_GPL(gigaset_debuglevel); module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(debug, "debug level"); diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index 5a6ae646a6363efe0e28ee0639fca7ef8263b35c..94b796d84053986aa17f58afd7a4f64cd74ab161 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -108,8 +108,7 @@ static int avmcs_probe(struct pcmcia_device *p_dev) p_dev->io.NumPorts2 = 0; /* Interrupt setup */ - p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; /* General socket configuration */ p_dev->conf.Attributes = CONF_ENABLE_IRQ; diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index f9bdff39cf4aff3dd32e33ac2b417eb145e4fbf3..e5deb15cf40c9ec2a2354375ef174afe83e8e05f 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -120,8 +120,7 @@ static int avma1cs_probe(struct pcmcia_device *p_dev) p_dev->io.IOAddrLines = 5; /* Interrupt setup */ - p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; /* General socket configuration */ p_dev->conf.Attributes = CONF_ENABLE_IRQ; diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index a2f709f5397413f8352e66391207875bdbd93c1d..c9a30b1c92372373a652f877dad6d62d65dbf19f 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -137,7 +137,7 @@ static int elsa_cs_probe(struct pcmcia_device *link) local->cardnr = -1; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->irq.Handler = NULL; /* diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index af5d393cc2d0afe2f099ad72ef489c411117391b..7836ec3c7f86fb723131c10185a1ef432ec12d13 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -144,7 +144,7 @@ static int sedlbauer_probe(struct pcmcia_device *link) link->priv = local; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->irq.Handler = NULL; /* diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index ea705394ce2bf4c06d7d6c49b87dd5d0c16063e4..b0c5976cbdb356c8941d77a0dfc54a166379e4d0 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -127,7 +127,7 @@ static int teles_probe(struct pcmcia_device *link) link->priv = local; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->irq.Handler = NULL; /* diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c index 5f7c9c5c09b1306c35211ed024aed989c1592b61..d11d05be0dee3712132a70b50b0a77211aff23b6 100644 --- a/drivers/leds/leds-fsg.c +++ b/drivers/leds/leds-fsg.c @@ -22,6 +22,13 @@ #include #include +#define FSG_LED_WLAN_BIT 0 +#define FSG_LED_WAN_BIT 1 +#define FSG_LED_SATA_BIT 2 +#define FSG_LED_USB_BIT 4 +#define FSG_LED_RING_BIT 5 +#define FSG_LED_SYNC_BIT 7 + static short __iomem *latch_address; static unsigned short latch_value; diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 6ae388849a3b1c60c7b7263041c6f46552c1a7fc..fb2b7ef7868ef6e0126c932049122f729fab7cb1 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -69,7 +69,7 @@ static struct lguest_pages *lguest_pages(unsigned int cpu) (SWITCHER_ADDR + SHARED_SWITCHER_PAGES*PAGE_SIZE))[cpu]); } -static DEFINE_PER_CPU(struct lg_cpu *, last_cpu); +static DEFINE_PER_CPU(struct lg_cpu *, lg_last_cpu); /*S:010 * We approach the Switcher. @@ -90,8 +90,8 @@ static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages) * meanwhile). If that's not the case, we pretend everything in the * Guest has changed. */ - if (__get_cpu_var(last_cpu) != cpu || cpu->last_pages != pages) { - __get_cpu_var(last_cpu) = cpu; + if (__get_cpu_var(lg_last_cpu) != cpu || cpu->last_pages != pages) { + __get_cpu_var(lg_last_cpu) = cpu; cpu->last_pages = pages; cpu->changed = CHANGED_ALL; } diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 588a5b0bc4b59150101b3f214c385a8348693134..26a303a1d1abd4bc885de4be79d46798f98a0afc 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -379,6 +379,11 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, dev->ofdev.dev.parent = parent; dev->ofdev.dev.bus = &macio_bus_type; dev->ofdev.dev.release = macio_release_dev; + dev->ofdev.dev.dma_parms = &dev->dma_parms; + + /* Standard DMA paremeters */ + dma_set_max_seg_size(&dev->ofdev.dev, 65536); + dma_set_seg_boundary(&dev->ofdev.dev, 0xffffffff); #ifdef CONFIG_PCI /* Set the DMA ops to the ones from the PCI device, this could be @@ -538,6 +543,42 @@ void macio_unregister_driver(struct macio_driver *drv) driver_unregister(&drv->driver); } +/* Managed MacIO resources */ +struct macio_devres { + u32 res_mask; +}; + +static void maciom_release(struct device *gendev, void *res) +{ + struct macio_dev *dev = to_macio_device(gendev); + struct macio_devres *dr = res; + int i, max; + + max = min(dev->n_resources, 32); + for (i = 0; i < max; i++) { + if (dr->res_mask & (1 << i)) + macio_release_resource(dev, i); + } +} + +int macio_enable_devres(struct macio_dev *dev) +{ + struct macio_devres *dr; + + dr = devres_find(&dev->ofdev.dev, maciom_release, NULL, NULL); + if (!dr) { + dr = devres_alloc(maciom_release, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + } + return devres_get(&dev->ofdev.dev, dr, NULL, NULL) != NULL; +} + +static struct macio_devres * find_macio_dr(struct macio_dev *dev) +{ + return devres_find(&dev->ofdev.dev, maciom_release, NULL, NULL); +} + /** * macio_request_resource - Request an MMIO resource * @dev: pointer to the device holding the resource @@ -555,6 +596,8 @@ void macio_unregister_driver(struct macio_driver *drv) int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name) { + struct macio_devres *dr = find_macio_dr(dev); + if (macio_resource_len(dev, resource_no) == 0) return 0; @@ -562,6 +605,9 @@ int macio_request_resource(struct macio_dev *dev, int resource_no, macio_resource_len(dev, resource_no), name)) goto err_out; + + if (dr && resource_no < 32) + dr->res_mask |= 1 << resource_no; return 0; @@ -582,10 +628,14 @@ err_out: */ void macio_release_resource(struct macio_dev *dev, int resource_no) { + struct macio_devres *dr = find_macio_dr(dev); + if (macio_resource_len(dev, resource_no) == 0) return; release_mem_region(macio_resource_start(dev, resource_no), macio_resource_len(dev, resource_no)); + if (dr && resource_no < 32) + dr->res_mask &= ~(1 << resource_no); } /** @@ -744,3 +794,5 @@ EXPORT_SYMBOL(macio_request_resource); EXPORT_SYMBOL(macio_release_resource); EXPORT_SYMBOL(macio_request_resources); EXPORT_SYMBOL(macio_release_resources); +EXPORT_SYMBOL(macio_enable_devres); + diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index 029ad8ce8a7ef9e08fc1341a322cf4389df52d45..08002b88f342deb961d18b20994a838bbf76bac9 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -33,15 +33,6 @@ #include #include - -#define MB_DEBUG - -#ifdef MB_DEBUG -#define MBDBG(fmt, arg...) printk(KERN_INFO fmt , ## arg) -#else -#define MBDBG(fmt, arg...) do { } while (0) -#endif - #define MB_FCR32(bay, r) ((bay)->base + ((r) >> 2)) #define MB_FCR8(bay, r) (((volatile u8 __iomem *)((bay)->base)) + (r)) @@ -76,28 +67,14 @@ struct media_bay_info { int index; int cached_gpio; int sleeping; + int user_lock; struct mutex lock; -#ifdef CONFIG_BLK_DEV_IDE_PMAC - ide_hwif_t *cd_port; - void __iomem *cd_base; - int cd_irq; - int cd_retry; -#endif -#if defined(CONFIG_BLK_DEV_IDE_PMAC) - int cd_index; -#endif }; #define MAX_BAYS 2 static struct media_bay_info media_bays[MAX_BAYS]; -int media_bay_count = 0; - -#ifdef CONFIG_BLK_DEV_IDE_PMAC -/* check the busy bit in the media-bay ide interface - (assumes the media-bay contains an ide device) */ -#define MB_IDE_READY(i) ((readb(media_bays[i].cd_base + 0x70) & 0x80) == 0) -#endif +static int media_bay_count = 0; /* * Wait that number of ms between each step in normal polling mode @@ -130,20 +107,10 @@ int media_bay_count = 0; /* * Wait this many ticks after an IDE device (e.g. CD-ROM) is inserted - * (or until the device is ready) before waiting for busy bit to disappear + * (or until the device is ready) before calling into the driver */ #define MB_IDE_WAIT 1000 -/* - * Timeout waiting for busy bit of an IDE device to go down - */ -#define MB_IDE_TIMEOUT 5000 - -/* - * Max retries of the full power up/down sequence for an IDE device - */ -#define MAX_CD_RETRIES 3 - /* * States of a media bay */ @@ -153,7 +120,6 @@ enum { mb_enabling_bay, /* enable bits set, waiting MB_RESET_DELAY */ mb_resetting, /* reset bit unset, waiting MB_SETUP_DELAY */ mb_ide_resetting, /* IDE reset bit unser, waiting MB_IDE_WAIT */ - mb_ide_waiting, /* Waiting for BUSY bit to go away until MB_IDE_TIMEOUT */ mb_up, /* Media bay full */ mb_powering_down /* Powering down (avoid too fast down/up) */ }; @@ -373,12 +339,12 @@ static inline void set_mb_power(struct media_bay_info* bay, int onoff) if (onoff) { bay->ops->power(bay, 1); bay->state = mb_powering_up; - MBDBG("mediabay%d: powering up\n", bay->index); + pr_debug("mediabay%d: powering up\n", bay->index); } else { /* Make sure everything is powered down & disabled */ bay->ops->power(bay, 0); bay->state = mb_powering_down; - MBDBG("mediabay%d: powering down\n", bay->index); + pr_debug("mediabay%d: powering down\n", bay->index); } bay->timer = msecs_to_jiffies(MB_POWER_DELAY); } @@ -387,107 +353,118 @@ static void poll_media_bay(struct media_bay_info* bay) { int id = bay->ops->content(bay); - if (id == bay->last_value) { - if (id != bay->content_id) { - bay->value_count += msecs_to_jiffies(MB_POLL_DELAY); - if (bay->value_count >= msecs_to_jiffies(MB_STABLE_DELAY)) { - /* If the device type changes without going thru - * "MB_NO", we force a pass by "MB_NO" to make sure - * things are properly reset - */ - if ((id != MB_NO) && (bay->content_id != MB_NO)) { - id = MB_NO; - MBDBG("mediabay%d: forcing MB_NO\n", bay->index); - } - MBDBG("mediabay%d: switching to %d\n", bay->index, id); - set_mb_power(bay, id != MB_NO); - bay->content_id = id; - if (id == MB_NO) { -#ifdef CONFIG_BLK_DEV_IDE_PMAC - bay->cd_retry = 0; -#endif - printk(KERN_INFO "media bay %d is empty\n", bay->index); - } - } - } - } else { + static char *mb_content_types[] = { + "a floppy drive", + "a floppy drive", + "an unsuported audio device", + "an ATA device", + "an unsupported PCI device", + "an unknown device", + }; + + if (id != bay->last_value) { bay->last_value = id; bay->value_count = 0; + return; + } + if (id == bay->content_id) + return; + + bay->value_count += msecs_to_jiffies(MB_POLL_DELAY); + if (bay->value_count >= msecs_to_jiffies(MB_STABLE_DELAY)) { + /* If the device type changes without going thru + * "MB_NO", we force a pass by "MB_NO" to make sure + * things are properly reset + */ + if ((id != MB_NO) && (bay->content_id != MB_NO)) { + id = MB_NO; + pr_debug("mediabay%d: forcing MB_NO\n", bay->index); + } + pr_debug("mediabay%d: switching to %d\n", bay->index, id); + set_mb_power(bay, id != MB_NO); + bay->content_id = id; + if (id >= MB_NO || id < 0) + printk(KERN_INFO "mediabay%d: Bay is now empty\n", bay->index); + else + printk(KERN_INFO "mediabay%d: Bay contains %s\n", + bay->index, mb_content_types[id]); } } -#ifdef CONFIG_BLK_DEV_IDE_PMAC -int check_media_bay(struct device_node *which_bay, int what) +int check_media_bay(struct macio_dev *baydev) { - int i; + struct media_bay_info* bay; + int id; - for (i=0; iofdev.node) { - if ((what == media_bays[i].content_id) && media_bays[i].state == mb_up) - return 0; - media_bays[i].cd_index = -1; - return -EINVAL; - } - return -ENODEV; + if (baydev == NULL) + return MB_NO; + + /* This returns an instant snapshot, not locking, sine + * we may be called with the bay lock held. The resulting + * fuzzyness of the result if called at the wrong time is + * not actually a huge deal + */ + bay = macio_get_drvdata(baydev); + if (bay == NULL) + return MB_NO; + id = bay->content_id; + if (bay->state != mb_up) + return MB_NO; + if (id == MB_FD1) + return MB_FD; + return id; } -EXPORT_SYMBOL(check_media_bay); +EXPORT_SYMBOL_GPL(check_media_bay); -int check_media_bay_by_base(unsigned long base, int what) +void lock_media_bay(struct macio_dev *baydev) { - int i; - - for (i=0; ilock); + bay->user_lock = 1; } -EXPORT_SYMBOL_GPL(check_media_bay_by_base); +EXPORT_SYMBOL_GPL(lock_media_bay); -int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base, - int irq, ide_hwif_t *hwif) +void unlock_media_bay(struct macio_dev *baydev) { - int i; + struct media_bay_info* bay; - for (i=0; imdev && which_bay == bay->mdev->ofdev.node) { - int timeout = 5000, index = hwif->index; - - mutex_lock(&bay->lock); - - bay->cd_port = hwif; - bay->cd_base = (void __iomem *) base; - bay->cd_irq = irq; - - if ((MB_CD != bay->content_id) || bay->state != mb_up) { - mutex_unlock(&bay->lock); - return 0; - } - printk(KERN_DEBUG "Registered ide%d for media bay %d\n", index, i); - do { - if (MB_IDE_READY(i)) { - bay->cd_index = index; - mutex_unlock(&bay->lock); - return 0; - } - mdelay(1); - } while(--timeout); - printk(KERN_DEBUG "Timeount waiting IDE in bay %d\n", i); - mutex_unlock(&bay->lock); - return -ENODEV; - } + if (baydev == NULL) + return; + bay = macio_get_drvdata(baydev); + if (bay == NULL) + return; + if (bay->user_lock) { + bay->user_lock = 0; + mutex_unlock(&bay->lock); } +} +EXPORT_SYMBOL_GPL(unlock_media_bay); - return -ENODEV; +static int mb_broadcast_hotplug(struct device *dev, void *data) +{ + struct media_bay_info* bay = data; + struct macio_dev *mdev; + struct macio_driver *drv; + int state; + + if (dev->bus != &macio_bus_type) + return 0; + + state = bay->state == mb_up ? bay->content_id : MB_NO; + if (state == MB_FD1) + state = MB_FD; + mdev = to_macio_device(dev); + drv = to_macio_driver(dev->driver); + if (dev->driver && drv->mediabay_event) + drv->mediabay_event(mdev, state); + return 0; } -EXPORT_SYMBOL_GPL(media_bay_set_ide_infos); -#endif /* CONFIG_BLK_DEV_IDE_PMAC */ static void media_bay_step(int i) { @@ -497,8 +474,8 @@ static void media_bay_step(int i) if (bay->state != mb_powering_down) poll_media_bay(bay); - /* If timer expired or polling IDE busy, run state machine */ - if ((bay->state != mb_ide_waiting) && (bay->timer != 0)) { + /* If timer expired run state machine */ + if (bay->timer != 0) { bay->timer -= msecs_to_jiffies(MB_POLL_DELAY); if (bay->timer > 0) return; @@ -508,100 +485,50 @@ static void media_bay_step(int i) switch(bay->state) { case mb_powering_up: if (bay->ops->setup_bus(bay, bay->last_value) < 0) { - MBDBG("mediabay%d: device not supported (kind:%d)\n", i, bay->content_id); + pr_debug("mediabay%d: device not supported (kind:%d)\n", + i, bay->content_id); set_mb_power(bay, 0); break; } bay->timer = msecs_to_jiffies(MB_RESET_DELAY); bay->state = mb_enabling_bay; - MBDBG("mediabay%d: enabling (kind:%d)\n", i, bay->content_id); + pr_debug("mediabay%d: enabling (kind:%d)\n", i, bay->content_id); break; case mb_enabling_bay: bay->ops->un_reset(bay); bay->timer = msecs_to_jiffies(MB_SETUP_DELAY); bay->state = mb_resetting; - MBDBG("mediabay%d: waiting reset (kind:%d)\n", i, bay->content_id); + pr_debug("mediabay%d: releasing bay reset (kind:%d)\n", + i, bay->content_id); break; case mb_resetting: if (bay->content_id != MB_CD) { - MBDBG("mediabay%d: bay is up (kind:%d)\n", i, bay->content_id); + pr_debug("mediabay%d: bay is up (kind:%d)\n", i, + bay->content_id); bay->state = mb_up; + device_for_each_child(&bay->mdev->ofdev.dev, + bay, mb_broadcast_hotplug); break; } -#ifdef CONFIG_BLK_DEV_IDE_PMAC - MBDBG("mediabay%d: waiting IDE reset (kind:%d)\n", i, bay->content_id); + pr_debug("mediabay%d: releasing ATA reset (kind:%d)\n", + i, bay->content_id); bay->ops->un_reset_ide(bay); bay->timer = msecs_to_jiffies(MB_IDE_WAIT); bay->state = mb_ide_resetting; -#else - printk(KERN_DEBUG "media-bay %d is ide (not compiled in kernel)\n", i); - set_mb_power(bay, 0); -#endif /* CONFIG_BLK_DEV_IDE_PMAC */ break; -#ifdef CONFIG_BLK_DEV_IDE_PMAC + case mb_ide_resetting: - bay->timer = msecs_to_jiffies(MB_IDE_TIMEOUT); - bay->state = mb_ide_waiting; - MBDBG("mediabay%d: waiting IDE ready (kind:%d)\n", i, bay->content_id); + pr_debug("mediabay%d: bay is up (kind:%d)\n", i, bay->content_id); + bay->state = mb_up; + device_for_each_child(&bay->mdev->ofdev.dev, + bay, mb_broadcast_hotplug); break; - case mb_ide_waiting: - if (bay->cd_base == NULL) { - bay->timer = 0; - bay->state = mb_up; - MBDBG("mediabay%d: up before IDE init\n", i); - break; - } else if (MB_IDE_READY(i)) { - bay->timer = 0; - bay->state = mb_up; - if (bay->cd_index < 0) { - printk("mediabay %d, registering IDE...\n", i); - pmu_suspend(); - ide_port_scan(bay->cd_port); - if (bay->cd_port->present) - bay->cd_index = bay->cd_port->index; - pmu_resume(); - } - if (bay->cd_index == -1) { - /* We eventually do a retry */ - bay->cd_retry++; - printk("IDE register error\n"); - set_mb_power(bay, 0); - } else { - printk(KERN_DEBUG "media-bay %d is ide%d\n", i, bay->cd_index); - MBDBG("mediabay %d IDE ready\n", i); - } - break; - } else if (bay->timer > 0) - bay->timer -= msecs_to_jiffies(MB_POLL_DELAY); - if (bay->timer <= 0) { - printk("\nIDE Timeout in bay %d !, IDE state is: 0x%02x\n", - i, readb(bay->cd_base + 0x70)); - MBDBG("mediabay%d: nIDE Timeout !\n", i); - set_mb_power(bay, 0); - bay->timer = 0; - } - break; -#endif /* CONFIG_BLK_DEV_IDE_PMAC */ + case mb_powering_down: bay->state = mb_empty; -#ifdef CONFIG_BLK_DEV_IDE_PMAC - if (bay->cd_index >= 0) { - printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i, - bay->cd_index); - ide_port_unregister_devices(bay->cd_port); - bay->cd_index = -1; - } - if (bay->cd_retry) { - if (bay->cd_retry > MAX_CD_RETRIES) { - /* Should add an error sound (sort of beep in dmasound) */ - printk("\nmedia-bay %d, IDE device badly inserted or unrecognised\n", i); - } else { - /* Force a new power down/up sequence */ - bay->content_id = MB_NO; - } - } -#endif /* CONFIG_BLK_DEV_IDE_PMAC */ - MBDBG("mediabay%d: end of power down\n", i); + device_for_each_child(&bay->mdev->ofdev.dev, + bay, mb_broadcast_hotplug); + pr_debug("mediabay%d: end of power down\n", i); break; } } @@ -676,11 +603,6 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de bay->last_value = bay->ops->content(bay); bay->value_count = msecs_to_jiffies(MB_STABLE_DELAY); bay->state = mb_empty; - do { - msleep(MB_POLL_DELAY); - media_bay_step(i); - } while((bay->state != mb_empty) && - (bay->state != mb_up)); /* Mark us ready by filling our mdev data */ macio_set_drvdata(mdev, bay); @@ -725,7 +647,7 @@ static int media_bay_resume(struct macio_dev *mdev) set_mb_power(bay, 0); msleep(MB_POWER_DELAY); if (bay->ops->content(bay) != bay->content_id) { - printk("mediabay%d: content changed during sleep...\n", bay->index); + printk("mediabay%d: Content changed during sleep...\n", bay->index); mutex_unlock(&bay->lock); return 0; } @@ -733,9 +655,6 @@ static int media_bay_resume(struct macio_dev *mdev) bay->last_value = bay->content_id; bay->value_count = msecs_to_jiffies(MB_STABLE_DELAY); bay->timer = msecs_to_jiffies(MB_POWER_DELAY); -#ifdef CONFIG_BLK_DEV_IDE_PMAC - bay->cd_retry = 0; -#endif do { msleep(MB_POLL_DELAY); media_bay_step(bay->index); @@ -823,9 +742,6 @@ static int __init media_bay_init(void) for (i=0; i #include #include -#include #include #include @@ -21,7 +20,6 @@ static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) { - lock_kernel(); switch (origin) { case 1: offset += file->f_pos; @@ -30,12 +28,10 @@ static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) offset += NVRAM_SIZE; break; } - if (offset < 0) { - unlock_kernel(); + if (offset < 0) return -EINVAL; - } + file->f_pos = offset; - unlock_kernel(); return file->f_pos; } @@ -76,8 +72,7 @@ static ssize_t write_nvram(struct file *file, const char __user *buf, return p - buf; } -static int nvram_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long nvram_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch(cmd) { case PMAC_NVRAM_GET_OFFSET: diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 556f0feaa4df33fe3733e0ccf3638bb6bfe1aa44..5ff47ba7f2d052e639f733c6f8cddea3e18b9175 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -79,6 +79,7 @@ struct thermostat { u8 limits[3]; int last_speed[2]; int last_var[2]; + int pwm_inv[2]; }; static enum {ADT7460, ADT7467} therm_type; @@ -229,19 +230,23 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan) if (speed >= 0) { manual = read_reg(th, MANUAL_MODE[fan]); + manual &= ~INVERT_MASK; write_reg(th, MANUAL_MODE[fan], - (manual|MANUAL_MASK) & (~INVERT_MASK)); + manual | MANUAL_MASK | th->pwm_inv[fan]); write_reg(th, FAN_SPD_SET[fan], speed); } else { /* back to automatic */ if(therm_type == ADT7460) { manual = read_reg(th, MANUAL_MODE[fan]) & (~MANUAL_MASK); - + manual &= ~INVERT_MASK; + manual |= th->pwm_inv[fan]; write_reg(th, MANUAL_MODE[fan], manual|REM_CONTROL[fan]); } else { manual = read_reg(th, MANUAL_MODE[fan]); + manual &= ~INVERT_MASK; + manual |= th->pwm_inv[fan]; write_reg(th, MANUAL_MODE[fan], manual&(~AUTO_MASK)); } } @@ -387,7 +392,7 @@ static int probe_thermostat(struct i2c_client *client, i2c_set_clientdata(client, th); th->clt = client; - rc = read_reg(th, 0); + rc = read_reg(th, CONFIG_REG); if (rc < 0) { dev_err(&client->dev, "Thermostat failed to read config!\n"); kfree(th); @@ -418,6 +423,10 @@ static int probe_thermostat(struct i2c_client *client, thermostat = th; + /* record invert bit status because fw can corrupt it after suspend */ + th->pwm_inv[0] = read_reg(th, MANUAL_MODE[0]) & INVERT_MASK; + th->pwm_inv[1] = read_reg(th, MANUAL_MODE[1]) & INVERT_MASK; + /* be sure to really write fan speed the first time */ th->last_speed[0] = -2; th->last_speed[1] = -2; diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 6f308a4757ee60dd6aa8acd4881745efc4eb4521..db379c3814326db904a17a76b7182ec4266a3a4a 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -186,17 +187,11 @@ static int init_pmu(void); static void pmu_start(void); static irqreturn_t via_pmu_interrupt(int irq, void *arg); static irqreturn_t gpio1_interrupt(int irq, void *arg); -static int proc_get_info(char *page, char **start, off_t off, - int count, int *eof, void *data); -static int proc_get_irqstats(char *page, char **start, off_t off, - int count, int *eof, void *data); +static const struct file_operations pmu_info_proc_fops; +static const struct file_operations pmu_irqstats_proc_fops; 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); -static int proc_read_options(char *page, char **start, off_t off, - int count, int *eof, void *data); -static int proc_write_options(struct file *file, const char __user *buffer, - unsigned long count, void *data); +static const struct file_operations pmu_battery_proc_fops; +static const struct file_operations pmu_options_proc_fops; #ifdef CONFIG_ADB struct adb_driver via_pmu_driver = { @@ -507,19 +502,15 @@ static int __init via_pmu_dev_init(void) for (i=0; iread_proc = proc_read_options; - proc_pmu_options->write_proc = proc_write_options; - } + proc_pmu_info = proc_create("info", 0, proc_pmu_root, &pmu_info_proc_fops); + proc_pmu_irqstats = proc_create("interrupts", 0, proc_pmu_root, + &pmu_irqstats_proc_fops); + proc_pmu_options = proc_create("options", 0600, proc_pmu_root, + &pmu_options_proc_fops); } return 0; } @@ -799,27 +790,33 @@ query_battery_state(void) 2, PMU_SMART_BATTERY_STATE, pmu_cur_battery+1); } -static int -proc_get_info(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int pmu_info_proc_show(struct seq_file *m, void *v) { - char* p = page; - - p += sprintf(p, "PMU driver version : %d\n", PMU_DRIVER_VERSION); - p += sprintf(p, "PMU firmware version : %02x\n", pmu_version); - p += sprintf(p, "AC Power : %d\n", + seq_printf(m, "PMU driver version : %d\n", PMU_DRIVER_VERSION); + seq_printf(m, "PMU firmware version : %02x\n", pmu_version); + seq_printf(m, "AC Power : %d\n", ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0) || pmu_battery_count == 0); - p += sprintf(p, "Battery count : %d\n", pmu_battery_count); + seq_printf(m, "Battery count : %d\n", pmu_battery_count); + + return 0; +} - return p - page; +static int pmu_info_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, pmu_info_proc_show, NULL); } -static int -proc_get_irqstats(char *page, char **start, off_t off, - int count, int *eof, void *data) +static const struct file_operations pmu_info_proc_fops = { + .owner = THIS_MODULE, + .open = pmu_info_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int pmu_irqstats_proc_show(struct seq_file *m, void *v) { int i; - char* p = page; static const char *irq_names[] = { "Total CB1 triggered events", "Total GPIO1 triggered events", @@ -835,60 +832,76 @@ proc_get_irqstats(char *page, char **start, off_t off, }; for (i=0; i<11; i++) { - p += sprintf(p, " %2u: %10u (%s)\n", + seq_printf(m, " %2u: %10u (%s)\n", i, pmu_irq_stats[i], irq_names[i]); } - return p - page; + return 0; } -static int -proc_get_batt(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int pmu_irqstats_proc_open(struct inode *inode, struct file *file) { - long batnum = (long)data; - char *p = page; + return single_open(file, pmu_irqstats_proc_show, NULL); +} + +static const struct file_operations pmu_irqstats_proc_fops = { + .owner = THIS_MODULE, + .open = pmu_irqstats_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int pmu_battery_proc_show(struct seq_file *m, void *v) +{ + long batnum = (long)m->private; - p += sprintf(p, "\n"); - p += sprintf(p, "flags : %08x\n", - pmu_batteries[batnum].flags); - p += sprintf(p, "charge : %d\n", - pmu_batteries[batnum].charge); - p += sprintf(p, "max_charge : %d\n", - pmu_batteries[batnum].max_charge); - p += sprintf(p, "current : %d\n", - pmu_batteries[batnum].amperage); - p += sprintf(p, "voltage : %d\n", - pmu_batteries[batnum].voltage); - p += sprintf(p, "time rem. : %d\n", - pmu_batteries[batnum].time_remaining); - - return p - page; + seq_putc(m, '\n'); + seq_printf(m, "flags : %08x\n", pmu_batteries[batnum].flags); + seq_printf(m, "charge : %d\n", pmu_batteries[batnum].charge); + seq_printf(m, "max_charge : %d\n", pmu_batteries[batnum].max_charge); + seq_printf(m, "current : %d\n", pmu_batteries[batnum].amperage); + seq_printf(m, "voltage : %d\n", pmu_batteries[batnum].voltage); + seq_printf(m, "time rem. : %d\n", pmu_batteries[batnum].time_remaining); + return 0; } -static int -proc_read_options(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int pmu_battery_proc_open(struct inode *inode, struct file *file) { - char *p = page; + return single_open(file, pmu_battery_proc_show, PDE(inode)->data); +} +static const struct file_operations pmu_battery_proc_fops = { + .owner = THIS_MODULE, + .open = pmu_battery_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int pmu_options_proc_show(struct seq_file *m, void *v) +{ #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) if (pmu_kind == PMU_KEYLARGO_BASED && pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) - p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup); + seq_printf(m, "lid_wakeup=%d\n", option_lid_wakeup); #endif if (pmu_kind == PMU_KEYLARGO_BASED) - p += sprintf(p, "server_mode=%d\n", option_server_mode); + seq_printf(m, "server_mode=%d\n", option_server_mode); - return p - page; + return 0; } - -static int -proc_write_options(struct file *file, const char __user *buffer, - unsigned long count, void *data) + +static int pmu_options_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, pmu_options_proc_show, NULL); +} + +static ssize_t pmu_options_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) { char tmp[33]; char *label, *val; - unsigned long fcount = count; + size_t fcount = count; if (!count) return -EINVAL; @@ -927,6 +940,15 @@ proc_write_options(struct file *file, const char __user *buffer, return fcount; } +static const struct file_operations pmu_options_proc_fops = { + .owner = THIS_MODULE, + .open = pmu_options_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = pmu_options_proc_write, +}; + #ifdef CONFIG_ADB /* Send an ADB command */ static int pmu_send_request(struct adb_request *req, int sync) diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c index 961fa0e7c2cf76b3607fe02707d64275192d6f4d..6c68b9e5f5c467976c013cb6b18c5f39c3b7d98a 100644 --- a/drivers/macintosh/windfarm_smu_controls.c +++ b/drivers/macintosh/windfarm_smu_controls.c @@ -202,6 +202,8 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, fct->ctrl.name = "cpu-front-fan-1"; else if (!strcmp(l, "CPU A PUMP")) fct->ctrl.name = "cpu-pump-0"; + else if (!strcmp(l, "CPU B PUMP")) + fct->ctrl.name = "cpu-pump-1"; else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan") || !strcmp(l, "EXPANSION SLOTS INTAKE")) fct->ctrl.name = "slots-fan"; diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 2158377a13593a45938278ac860d5de3db8a06fa..acb3a4e404ff22b53a6c3017ee3affe2439306fc 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -185,11 +185,10 @@ config MD_MULTIPATH tristate "Multipath I/O support" depends on BLK_DEV_MD help - Multipath-IO is the ability of certain devices to address the same - physical disk over multiple 'IO paths'. The code ensures that such - paths can be defined and handled at runtime, and ensures that a - transparent failover to the backup path(s) happens if a IO errors - arrives on the primary path. + MD_MULTIPATH provides a simple multi-path personality for use + the MD framework. It is not under active development. New + projects should consider using DM_MULTIPATH which has more + features and more testing. If unsure, say N. diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 60e2b322db110b96d52f66e4f502610b29d822fe..26ac8aad0b1993dab39cf91fc692f5dca534cdb5 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -212,7 +212,7 @@ static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page) */ /* IO operations when bitmap is stored near all superblocks */ -static struct page *read_sb_page(mddev_t *mddev, long offset, +static struct page *read_sb_page(mddev_t *mddev, loff_t offset, struct page *page, unsigned long index, int size) { @@ -287,27 +287,36 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) while ((rdev = next_active_rdev(rdev, mddev)) != NULL) { int size = PAGE_SIZE; + loff_t offset = mddev->bitmap_info.offset; if (page->index == bitmap->file_pages-1) size = roundup(bitmap->last_page_size, bdev_logical_block_size(rdev->bdev)); /* Just make sure we aren't corrupting data or * metadata */ - if (bitmap->offset < 0) { + if (mddev->external) { + /* Bitmap could be anywhere. */ + if (rdev->sb_start + offset + (page->index *(PAGE_SIZE/512)) > + rdev->data_offset && + rdev->sb_start + offset < + rdev->data_offset + mddev->dev_sectors + + (PAGE_SIZE/512)) + goto bad_alignment; + } else if (offset < 0) { /* DATA BITMAP METADATA */ - if (bitmap->offset + if (offset + (long)(page->index * (PAGE_SIZE/512)) + size/512 > 0) /* bitmap runs in to metadata */ goto bad_alignment; if (rdev->data_offset + mddev->dev_sectors - > rdev->sb_start + bitmap->offset) + > rdev->sb_start + offset) /* data runs in to bitmap */ goto bad_alignment; } else if (rdev->sb_start < rdev->data_offset) { /* METADATA BITMAP DATA */ if (rdev->sb_start - + bitmap->offset + + offset + page->index*(PAGE_SIZE/512) + size/512 > rdev->data_offset) /* bitmap runs in to data */ @@ -316,7 +325,7 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) /* DATA METADATA BITMAP - no problems */ } md_super_write(mddev, rdev, - rdev->sb_start + bitmap->offset + rdev->sb_start + offset + page->index * (PAGE_SIZE/512), size, page); @@ -488,6 +497,8 @@ void bitmap_update_sb(struct bitmap *bitmap) if (!bitmap || !bitmap->mddev) /* no bitmap for this array */ return; + if (bitmap->mddev->bitmap_info.external) + return; spin_lock_irqsave(&bitmap->lock, flags); if (!bitmap->sb_page) { /* no superblock */ spin_unlock_irqrestore(&bitmap->lock, flags); @@ -501,6 +512,9 @@ void bitmap_update_sb(struct bitmap *bitmap) bitmap->events_cleared = bitmap->mddev->events; sb->events_cleared = cpu_to_le64(bitmap->events_cleared); } + /* Just in case these have been changed via sysfs: */ + sb->daemon_sleep = cpu_to_le32(bitmap->mddev->bitmap_info.daemon_sleep/HZ); + sb->write_behind = cpu_to_le32(bitmap->mddev->bitmap_info.max_write_behind); kunmap_atomic(sb, KM_USER0); write_page(bitmap, bitmap->sb_page, 1); } @@ -550,7 +564,8 @@ static int bitmap_read_sb(struct bitmap *bitmap) bitmap->sb_page = read_page(bitmap->file, 0, bitmap, bytes); } else { - bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, + bitmap->sb_page = read_sb_page(bitmap->mddev, + bitmap->mddev->bitmap_info.offset, NULL, 0, sizeof(bitmap_super_t)); } @@ -563,7 +578,7 @@ static int bitmap_read_sb(struct bitmap *bitmap) sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0); chunksize = le32_to_cpu(sb->chunksize); - daemon_sleep = le32_to_cpu(sb->daemon_sleep); + daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ; write_behind = le32_to_cpu(sb->write_behind); /* verify that the bitmap-specific fields are valid */ @@ -576,7 +591,7 @@ static int bitmap_read_sb(struct bitmap *bitmap) reason = "bitmap chunksize too small"; else if ((1 << ffz(~chunksize)) != chunksize) reason = "bitmap chunksize not a power of 2"; - else if (daemon_sleep < 1 || daemon_sleep > MAX_SCHEDULE_TIMEOUT / HZ) + else if (daemon_sleep < 1 || daemon_sleep > MAX_SCHEDULE_TIMEOUT) reason = "daemon sleep period out of range"; else if (write_behind > COUNTER_MAX) reason = "write-behind limit out of range (0 - 16383)"; @@ -610,10 +625,9 @@ static int bitmap_read_sb(struct bitmap *bitmap) } success: /* assign fields using values from superblock */ - bitmap->chunksize = chunksize; - bitmap->daemon_sleep = daemon_sleep; - bitmap->daemon_lastrun = jiffies; - bitmap->max_write_behind = write_behind; + bitmap->mddev->bitmap_info.chunksize = chunksize; + bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep; + bitmap->mddev->bitmap_info.max_write_behind = write_behind; bitmap->flags |= le32_to_cpu(sb->state); if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN) bitmap->flags |= BITMAP_HOSTENDIAN; @@ -664,16 +678,26 @@ static int bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits, * general bitmap file operations */ +/* + * on-disk bitmap: + * + * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap + * file a page at a time. There's a superblock at the start of the file. + */ /* calculate the index of the page that contains this bit */ -static inline unsigned long file_page_index(unsigned long chunk) +static inline unsigned long file_page_index(struct bitmap *bitmap, unsigned long chunk) { - return CHUNK_BIT_OFFSET(chunk) >> PAGE_BIT_SHIFT; + if (!bitmap->mddev->bitmap_info.external) + chunk += sizeof(bitmap_super_t) << 3; + return chunk >> PAGE_BIT_SHIFT; } /* calculate the (bit) offset of this bit within a page */ -static inline unsigned long file_page_offset(unsigned long chunk) +static inline unsigned long file_page_offset(struct bitmap *bitmap, unsigned long chunk) { - return CHUNK_BIT_OFFSET(chunk) & (PAGE_BITS - 1); + if (!bitmap->mddev->bitmap_info.external) + chunk += sizeof(bitmap_super_t) << 3; + return chunk & (PAGE_BITS - 1); } /* @@ -686,8 +710,9 @@ static inline unsigned long file_page_offset(unsigned long chunk) static inline struct page *filemap_get_page(struct bitmap *bitmap, unsigned long chunk) { - if (file_page_index(chunk) >= bitmap->file_pages) return NULL; - return bitmap->filemap[file_page_index(chunk) - file_page_index(0)]; + if (file_page_index(bitmap, chunk) >= bitmap->file_pages) return NULL; + return bitmap->filemap[file_page_index(bitmap, chunk) + - file_page_index(bitmap, 0)]; } @@ -710,7 +735,7 @@ static void bitmap_file_unmap(struct bitmap *bitmap) spin_unlock_irqrestore(&bitmap->lock, flags); while (pages--) - if (map[pages]->index != 0) /* 0 is sb_page, release it below */ + if (map[pages] != sb_page) /* 0 is sb_page, release it below */ free_buffers(map[pages]); kfree(map); kfree(attr); @@ -821,7 +846,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block) page = filemap_get_page(bitmap, chunk); if (!page) return; - bit = file_page_offset(chunk); + bit = file_page_offset(bitmap, chunk); /* set the bit */ kaddr = kmap_atomic(page, KM_USER0); @@ -907,7 +932,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) chunks = bitmap->chunks; file = bitmap->file; - BUG_ON(!file && !bitmap->offset); + BUG_ON(!file && !bitmap->mddev->bitmap_info.offset); #ifdef INJECT_FAULTS_3 outofdate = 1; @@ -919,14 +944,17 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) "recovery\n", bmname(bitmap)); bytes = (chunks + 7) / 8; + if (!bitmap->mddev->bitmap_info.external) + bytes += sizeof(bitmap_super_t); - num_pages = (bytes + sizeof(bitmap_super_t) + PAGE_SIZE - 1) / PAGE_SIZE; + + num_pages = (bytes + PAGE_SIZE - 1) / PAGE_SIZE; - if (file && i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) { + if (file && i_size_read(file->f_mapping->host) < bytes) { printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n", bmname(bitmap), (unsigned long) i_size_read(file->f_mapping->host), - bytes + sizeof(bitmap_super_t)); + bytes); goto err; } @@ -947,17 +975,16 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) for (i = 0; i < chunks; i++) { int b; - index = file_page_index(i); - bit = file_page_offset(i); + index = file_page_index(bitmap, i); + bit = file_page_offset(bitmap, 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 + sizeof(bitmap_super_t) - - index * PAGE_SIZE; + count = bytes - index * PAGE_SIZE; else count = PAGE_SIZE; - if (index == 0) { + if (index == 0 && bitmap->sb_page) { /* * if we're here then the superblock page * contains some bits (PAGE_SIZE != sizeof sb) @@ -967,14 +994,15 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) offset = sizeof(bitmap_super_t); if (!file) read_sb_page(bitmap->mddev, - bitmap->offset, + bitmap->mddev->bitmap_info.offset, page, index, count); } else if (file) { page = read_page(file, index, bitmap, count); offset = 0; } else { - page = read_sb_page(bitmap->mddev, bitmap->offset, + page = read_sb_page(bitmap->mddev, + bitmap->mddev->bitmap_info.offset, NULL, index, count); offset = 0; @@ -1078,23 +1106,32 @@ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap, * out to disk */ -void bitmap_daemon_work(struct bitmap *bitmap) +void bitmap_daemon_work(mddev_t *mddev) { + struct bitmap *bitmap; unsigned long j; unsigned long flags; struct page *page = NULL, *lastpage = NULL; int blocks; void *paddr; - if (bitmap == NULL) + /* Use a mutex to guard daemon_work against + * bitmap_destroy. + */ + mutex_lock(&mddev->bitmap_info.mutex); + bitmap = mddev->bitmap; + if (bitmap == NULL) { + mutex_unlock(&mddev->bitmap_info.mutex); return; - if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ)) + } + if (time_before(jiffies, bitmap->daemon_lastrun + + bitmap->mddev->bitmap_info.daemon_sleep)) goto done; bitmap->daemon_lastrun = jiffies; if (bitmap->allclean) { bitmap->mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; - return; + goto done; } bitmap->allclean = 1; @@ -1142,7 +1179,8 @@ void bitmap_daemon_work(struct bitmap *bitmap) /* We are possibly going to clear some bits, so make * sure that events_cleared is up-to-date. */ - if (bitmap->need_sync) { + if (bitmap->need_sync && + bitmap->mddev->bitmap_info.external == 0) { bitmap_super_t *sb; bitmap->need_sync = 0; sb = kmap_atomic(bitmap->sb_page, KM_USER0); @@ -1152,7 +1190,8 @@ void bitmap_daemon_work(struct bitmap *bitmap) write_page(bitmap, bitmap->sb_page, 1); } spin_lock_irqsave(&bitmap->lock, flags); - clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); + if (!bitmap->need_sync) + clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); } bmc = bitmap_get_counter(bitmap, (sector_t)j << CHUNK_BLOCK_SHIFT(bitmap), @@ -1167,7 +1206,7 @@ void bitmap_daemon_work(struct bitmap *bitmap) if (*bmc == 2) { *bmc=1; /* maybe clear the bit next time */ set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); - } else if (*bmc == 1) { + } else if (*bmc == 1 && !bitmap->need_sync) { /* we can clear the bit */ *bmc = 0; bitmap_count_page(bitmap, @@ -1177,9 +1216,11 @@ void bitmap_daemon_work(struct bitmap *bitmap) /* clear the bit */ paddr = kmap_atomic(page, KM_USER0); if (bitmap->flags & BITMAP_HOSTENDIAN) - clear_bit(file_page_offset(j), paddr); + clear_bit(file_page_offset(bitmap, j), + paddr); else - ext2_clear_bit(file_page_offset(j), paddr); + ext2_clear_bit(file_page_offset(bitmap, j), + paddr); kunmap_atomic(paddr, KM_USER0); } } else @@ -1202,7 +1243,9 @@ void bitmap_daemon_work(struct bitmap *bitmap) done: if (bitmap->allclean == 0) - bitmap->mddev->thread->timeout = bitmap->daemon_sleep * HZ; + bitmap->mddev->thread->timeout = + bitmap->mddev->bitmap_info.daemon_sleep; + mutex_unlock(&mddev->bitmap_info.mutex); } static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap, @@ -1332,6 +1375,7 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto bitmap->events_cleared < bitmap->mddev->events) { bitmap->events_cleared = bitmap->mddev->events; bitmap->need_sync = 1; + sysfs_notify_dirent(bitmap->sysfs_can_clear); } if (!success && ! (*bmc & NEEDED_MASK)) @@ -1470,7 +1514,7 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector) return; } if (time_before(jiffies, (bitmap->last_end_sync - + bitmap->daemon_sleep * HZ))) + + bitmap->mddev->bitmap_info.daemon_sleep))) return; wait_event(bitmap->mddev->recovery_wait, atomic_read(&bitmap->mddev->recovery_active) == 0); @@ -1522,6 +1566,12 @@ void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e) sector_t sec = (sector_t)chunk << CHUNK_BLOCK_SHIFT(bitmap); bitmap_set_memory_bits(bitmap, sec, 1); bitmap_file_set_bit(bitmap, sec); + if (sec < bitmap->mddev->recovery_cp) + /* We are asserting that the array is dirty, + * so move the recovery_cp address back so + * that it is obvious that it is dirty + */ + bitmap->mddev->recovery_cp = sec; } } @@ -1531,7 +1581,7 @@ void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e) void bitmap_flush(mddev_t *mddev) { struct bitmap *bitmap = mddev->bitmap; - int sleep; + long sleep; if (!bitmap) /* there was no bitmap */ return; @@ -1539,12 +1589,13 @@ void bitmap_flush(mddev_t *mddev) /* run the daemon_work three time to ensure everything is flushed * that can be */ - sleep = bitmap->daemon_sleep; - bitmap->daemon_sleep = 0; - bitmap_daemon_work(bitmap); - bitmap_daemon_work(bitmap); - bitmap_daemon_work(bitmap); - bitmap->daemon_sleep = sleep; + sleep = mddev->bitmap_info.daemon_sleep * 2; + bitmap->daemon_lastrun -= sleep; + bitmap_daemon_work(mddev); + bitmap->daemon_lastrun -= sleep; + bitmap_daemon_work(mddev); + bitmap->daemon_lastrun -= sleep; + bitmap_daemon_work(mddev); bitmap_update_sb(bitmap); } @@ -1574,6 +1625,7 @@ static void bitmap_free(struct bitmap *bitmap) kfree(bp); kfree(bitmap); } + void bitmap_destroy(mddev_t *mddev) { struct bitmap *bitmap = mddev->bitmap; @@ -1581,10 +1633,15 @@ void bitmap_destroy(mddev_t *mddev) if (!bitmap) /* there was no bitmap */ return; + mutex_lock(&mddev->bitmap_info.mutex); mddev->bitmap = NULL; /* disconnect from the md device */ + mutex_unlock(&mddev->bitmap_info.mutex); if (mddev->thread) mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; + if (bitmap->sysfs_can_clear) + sysfs_put(bitmap->sysfs_can_clear); + bitmap_free(bitmap); } @@ -1598,16 +1655,17 @@ int bitmap_create(mddev_t *mddev) sector_t blocks = mddev->resync_max_sectors; unsigned long chunks; unsigned long pages; - struct file *file = mddev->bitmap_file; + struct file *file = mddev->bitmap_info.file; int err; sector_t start; + struct sysfs_dirent *bm; BUILD_BUG_ON(sizeof(bitmap_super_t) != 256); - if (!file && !mddev->bitmap_offset) /* bitmap disabled, nothing to do */ + if (!file && !mddev->bitmap_info.offset) /* bitmap disabled, nothing to do */ return 0; - BUG_ON(file && mddev->bitmap_offset); + BUG_ON(file && mddev->bitmap_info.offset); bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL); if (!bitmap) @@ -1620,8 +1678,14 @@ int bitmap_create(mddev_t *mddev) bitmap->mddev = mddev; + bm = sysfs_get_dirent(mddev->kobj.sd, "bitmap"); + if (bm) { + bitmap->sysfs_can_clear = sysfs_get_dirent(bm, "can_clear"); + sysfs_put(bm); + } else + bitmap->sysfs_can_clear = NULL; + bitmap->file = file; - bitmap->offset = mddev->bitmap_offset; if (file) { get_file(file); /* As future accesses to this file will use bmap, @@ -1630,12 +1694,22 @@ int bitmap_create(mddev_t *mddev) */ vfs_fsync(file, file->f_dentry, 1); } - /* read superblock from bitmap file (this sets bitmap->chunksize) */ - err = bitmap_read_sb(bitmap); + /* read superblock from bitmap file (this sets mddev->bitmap_info.chunksize) */ + if (!mddev->bitmap_info.external) + err = bitmap_read_sb(bitmap); + else { + err = 0; + if (mddev->bitmap_info.chunksize == 0 || + mddev->bitmap_info.daemon_sleep == 0) + /* chunksize and time_base need to be + * set first. */ + err = -EINVAL; + } if (err) goto error; - bitmap->chunkshift = ffz(~bitmap->chunksize); + bitmap->daemon_lastrun = jiffies; + bitmap->chunkshift = ffz(~mddev->bitmap_info.chunksize); /* now that chunksize and chunkshift are set, we can use these macros */ chunks = (blocks + CHUNK_BLOCK_RATIO(bitmap) - 1) >> @@ -1677,7 +1751,8 @@ int bitmap_create(mddev_t *mddev) mddev->bitmap = bitmap; - mddev->thread->timeout = bitmap->daemon_sleep * HZ; + mddev->thread->timeout = mddev->bitmap_info.daemon_sleep; + md_wakeup_thread(mddev->thread); bitmap_update_sb(bitmap); @@ -1688,6 +1763,264 @@ int bitmap_create(mddev_t *mddev) return err; } +static ssize_t +location_show(mddev_t *mddev, char *page) +{ + ssize_t len; + if (mddev->bitmap_info.file) { + len = sprintf(page, "file"); + } else if (mddev->bitmap_info.offset) { + len = sprintf(page, "%+lld", (long long)mddev->bitmap_info.offset); + } else + len = sprintf(page, "none"); + len += sprintf(page+len, "\n"); + return len; +} + +static ssize_t +location_store(mddev_t *mddev, const char *buf, size_t len) +{ + + if (mddev->pers) { + if (!mddev->pers->quiesce) + return -EBUSY; + if (mddev->recovery || mddev->sync_thread) + return -EBUSY; + } + + if (mddev->bitmap || mddev->bitmap_info.file || + mddev->bitmap_info.offset) { + /* bitmap already configured. Only option is to clear it */ + if (strncmp(buf, "none", 4) != 0) + return -EBUSY; + if (mddev->pers) { + mddev->pers->quiesce(mddev, 1); + bitmap_destroy(mddev); + mddev->pers->quiesce(mddev, 0); + } + mddev->bitmap_info.offset = 0; + if (mddev->bitmap_info.file) { + struct file *f = mddev->bitmap_info.file; + mddev->bitmap_info.file = NULL; + restore_bitmap_write_access(f); + fput(f); + } + } else { + /* No bitmap, OK to set a location */ + long long offset; + if (strncmp(buf, "none", 4) == 0) + /* nothing to be done */; + else if (strncmp(buf, "file:", 5) == 0) { + /* Not supported yet */ + return -EINVAL; + } else { + int rv; + if (buf[0] == '+') + rv = strict_strtoll(buf+1, 10, &offset); + else + rv = strict_strtoll(buf, 10, &offset); + if (rv) + return rv; + if (offset == 0) + return -EINVAL; + if (mddev->bitmap_info.external == 0 && + mddev->major_version == 0 && + offset != mddev->bitmap_info.default_offset) + return -EINVAL; + mddev->bitmap_info.offset = offset; + if (mddev->pers) { + mddev->pers->quiesce(mddev, 1); + rv = bitmap_create(mddev); + if (rv) { + bitmap_destroy(mddev); + mddev->bitmap_info.offset = 0; + } + mddev->pers->quiesce(mddev, 0); + if (rv) + return rv; + } + } + } + if (!mddev->external) { + /* Ensure new bitmap info is stored in + * metadata promptly. + */ + set_bit(MD_CHANGE_DEVS, &mddev->flags); + md_wakeup_thread(mddev->thread); + } + return len; +} + +static struct md_sysfs_entry bitmap_location = +__ATTR(location, S_IRUGO|S_IWUSR, location_show, location_store); + +static ssize_t +timeout_show(mddev_t *mddev, char *page) +{ + ssize_t len; + unsigned long secs = mddev->bitmap_info.daemon_sleep / HZ; + unsigned long jifs = mddev->bitmap_info.daemon_sleep % HZ; + + len = sprintf(page, "%lu", secs); + if (jifs) + len += sprintf(page+len, ".%03u", jiffies_to_msecs(jifs)); + len += sprintf(page+len, "\n"); + return len; +} + +static ssize_t +timeout_store(mddev_t *mddev, const char *buf, size_t len) +{ + /* timeout can be set at any time */ + unsigned long timeout; + int rv = strict_strtoul_scaled(buf, &timeout, 4); + if (rv) + return rv; + + /* just to make sure we don't overflow... */ + if (timeout >= LONG_MAX / HZ) + return -EINVAL; + + timeout = timeout * HZ / 10000; + + if (timeout >= MAX_SCHEDULE_TIMEOUT) + timeout = MAX_SCHEDULE_TIMEOUT-1; + if (timeout < 1) + timeout = 1; + mddev->bitmap_info.daemon_sleep = timeout; + if (mddev->thread) { + /* if thread->timeout is MAX_SCHEDULE_TIMEOUT, then + * the bitmap is all clean and we don't need to + * adjust the timeout right now + */ + if (mddev->thread->timeout < MAX_SCHEDULE_TIMEOUT) { + mddev->thread->timeout = timeout; + md_wakeup_thread(mddev->thread); + } + } + return len; +} + +static struct md_sysfs_entry bitmap_timeout = +__ATTR(time_base, S_IRUGO|S_IWUSR, timeout_show, timeout_store); + +static ssize_t +backlog_show(mddev_t *mddev, char *page) +{ + return sprintf(page, "%lu\n", mddev->bitmap_info.max_write_behind); +} + +static ssize_t +backlog_store(mddev_t *mddev, const char *buf, size_t len) +{ + unsigned long backlog; + int rv = strict_strtoul(buf, 10, &backlog); + if (rv) + return rv; + if (backlog > COUNTER_MAX) + return -EINVAL; + mddev->bitmap_info.max_write_behind = backlog; + return len; +} + +static struct md_sysfs_entry bitmap_backlog = +__ATTR(backlog, S_IRUGO|S_IWUSR, backlog_show, backlog_store); + +static ssize_t +chunksize_show(mddev_t *mddev, char *page) +{ + return sprintf(page, "%lu\n", mddev->bitmap_info.chunksize); +} + +static ssize_t +chunksize_store(mddev_t *mddev, const char *buf, size_t len) +{ + /* Can only be changed when no bitmap is active */ + int rv; + unsigned long csize; + if (mddev->bitmap) + return -EBUSY; + rv = strict_strtoul(buf, 10, &csize); + if (rv) + return rv; + if (csize < 512 || + !is_power_of_2(csize)) + return -EINVAL; + mddev->bitmap_info.chunksize = csize; + return len; +} + +static struct md_sysfs_entry bitmap_chunksize = +__ATTR(chunksize, S_IRUGO|S_IWUSR, chunksize_show, chunksize_store); + +static ssize_t metadata_show(mddev_t *mddev, char *page) +{ + return sprintf(page, "%s\n", (mddev->bitmap_info.external + ? "external" : "internal")); +} + +static ssize_t metadata_store(mddev_t *mddev, const char *buf, size_t len) +{ + if (mddev->bitmap || + mddev->bitmap_info.file || + mddev->bitmap_info.offset) + return -EBUSY; + if (strncmp(buf, "external", 8) == 0) + mddev->bitmap_info.external = 1; + else if (strncmp(buf, "internal", 8) == 0) + mddev->bitmap_info.external = 0; + else + return -EINVAL; + return len; +} + +static struct md_sysfs_entry bitmap_metadata = +__ATTR(metadata, S_IRUGO|S_IWUSR, metadata_show, metadata_store); + +static ssize_t can_clear_show(mddev_t *mddev, char *page) +{ + int len; + if (mddev->bitmap) + len = sprintf(page, "%s\n", (mddev->bitmap->need_sync ? + "false" : "true")); + else + len = sprintf(page, "\n"); + return len; +} + +static ssize_t can_clear_store(mddev_t *mddev, const char *buf, size_t len) +{ + if (mddev->bitmap == NULL) + return -ENOENT; + if (strncmp(buf, "false", 5) == 0) + mddev->bitmap->need_sync = 1; + else if (strncmp(buf, "true", 4) == 0) { + if (mddev->degraded) + return -EBUSY; + mddev->bitmap->need_sync = 0; + } else + return -EINVAL; + return len; +} + +static struct md_sysfs_entry bitmap_can_clear = +__ATTR(can_clear, S_IRUGO|S_IWUSR, can_clear_show, can_clear_store); + +static struct attribute *md_bitmap_attrs[] = { + &bitmap_location.attr, + &bitmap_timeout.attr, + &bitmap_backlog.attr, + &bitmap_chunksize.attr, + &bitmap_metadata.attr, + &bitmap_can_clear.attr, + NULL +}; +struct attribute_group md_bitmap_group = { + .name = "bitmap", + .attrs = md_bitmap_attrs, +}; + + /* the bitmap API -- for raid personalities */ EXPORT_SYMBOL(bitmap_startwrite); EXPORT_SYMBOL(bitmap_endwrite); diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h index e98900671ca91d7a4f76ae91ac7393f6613bd5ee..cb821d76d1b4ebe7c8ad8aa2e44ab4c10b20f6f2 100644 --- a/drivers/md/bitmap.h +++ b/drivers/md/bitmap.h @@ -106,7 +106,7 @@ typedef __u16 bitmap_counter_t; #define BITMAP_BLOCK_SHIFT 9 /* how many blocks per chunk? (this is variable) */ -#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->chunksize >> BITMAP_BLOCK_SHIFT) +#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->mddev->bitmap_info.chunksize >> BITMAP_BLOCK_SHIFT) #define CHUNK_BLOCK_SHIFT(bitmap) ((bitmap)->chunkshift - BITMAP_BLOCK_SHIFT) #define CHUNK_BLOCK_MASK(bitmap) (CHUNK_BLOCK_RATIO(bitmap) - 1) @@ -118,16 +118,6 @@ typedef __u16 bitmap_counter_t; (CHUNK_BLOCK_SHIFT(bitmap) + PAGE_COUNTER_SHIFT - 1) #define PAGEPTR_BLOCK_MASK(bitmap) (PAGEPTR_BLOCK_RATIO(bitmap) - 1) -/* - * on-disk bitmap: - * - * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap - * file a page at a time. There's a superblock at the start of the file. - */ - -/* map chunks (bits) to file pages - offset by the size of the superblock */ -#define CHUNK_BIT_OFFSET(chunk) ((chunk) + (sizeof(bitmap_super_t) << 3)) - #endif /* @@ -209,7 +199,6 @@ struct bitmap { int counter_bits; /* how many bits per block counter */ /* bitmap chunksize -- how much data does each bit represent? */ - unsigned long chunksize; unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */ unsigned long chunks; /* total number of data chunks for the array */ @@ -226,7 +215,6 @@ struct bitmap { /* bitmap spinlock */ spinlock_t lock; - long offset; /* offset from superblock if file is NULL */ struct file *file; /* backing disk file */ struct page *sb_page; /* cached copy of the bitmap file superblock */ struct page **filemap; /* list of cache pages for the file */ @@ -238,7 +226,6 @@ struct bitmap { int allclean; - unsigned long max_write_behind; /* write-behind mode */ atomic_t behind_writes; /* @@ -246,7 +233,6 @@ struct bitmap { * file, cleaning up bits and flushing out pages to disk as necessary */ unsigned long daemon_lastrun; /* jiffies of last run */ - unsigned long daemon_sleep; /* how many seconds between updates? */ unsigned long last_end_sync; /* when we lasted called end_sync to * update bitmap with resync progress */ @@ -254,6 +240,7 @@ struct bitmap { wait_queue_head_t write_wait; wait_queue_head_t overflow_wait; + struct sysfs_dirent *sysfs_can_clear; }; /* the bitmap API */ @@ -282,7 +269,7 @@ void bitmap_close_sync(struct bitmap *bitmap); void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector); void bitmap_unplug(struct bitmap *bitmap); -void bitmap_daemon_work(struct bitmap *bitmap); +void bitmap_daemon_work(mddev_t *mddev); #endif #endif diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index 87d88dbb667f2abdb83190b5d1fc1ac3d19cb1ba..713acd02ab39f1cd9662b5238c6e770fcc73c00c 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c @@ -360,6 +360,7 @@ static void raid_exit(void) module_init(raid_init); module_exit(raid_exit); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Fault injection personality for MD"); MODULE_ALIAS("md-personality-10"); /* faulty */ MODULE_ALIAS("md-faulty"); MODULE_ALIAS("md-level--5"); diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 1ceceb334d5ebe8f5ce637d29898fc984bfcc797..00435bd206990416c21cad98b549483b123a99c8 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -292,7 +292,7 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) int cpu; if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { - bio_endio(bio, -EOPNOTSUPP); + md_barrier_request(mddev, bio); return 0; } @@ -383,6 +383,7 @@ static void linear_exit (void) module_init(linear_init); module_exit(linear_exit); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Linear device concatenation personality for MD"); MODULE_ALIAS("md-personality-1"); /* LINEAR - deprecated*/ MODULE_ALIAS("md-linear"); MODULE_ALIAS("md-level--1"); diff --git a/drivers/md/md.c b/drivers/md/md.c index 5f154ef1e4befeeef26358d9ae37e424c62cee47..e1f3c1715cca2ae459f0a70d7229128685ee2d70 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,12 @@ static DECLARE_WAIT_QUEUE_HEAD(resync_wait); #define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); } +/* + * Default number of read corrections we'll attempt on an rdev + * before ejecting it from the array. We divide the read error + * count by 2 for every hour elapsed between read errors. + */ +#define MD_DEFAULT_MAX_CORRECTED_READ_ERRORS 20 /* * 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. @@ -213,12 +220,12 @@ static int md_make_request(struct request_queue *q, struct bio *bio) return 0; } rcu_read_lock(); - if (mddev->suspended) { + if (mddev->suspended || mddev->barrier) { DEFINE_WAIT(__wait); for (;;) { prepare_to_wait(&mddev->sb_wait, &__wait, TASK_UNINTERRUPTIBLE); - if (!mddev->suspended) + if (!mddev->suspended && !mddev->barrier) break; rcu_read_unlock(); schedule(); @@ -260,10 +267,110 @@ static void mddev_resume(mddev_t *mddev) int mddev_congested(mddev_t *mddev, int bits) { + if (mddev->barrier) + return 1; return mddev->suspended; } EXPORT_SYMBOL(mddev_congested); +/* + * Generic barrier handling for md + */ + +#define POST_REQUEST_BARRIER ((void*)1) + +static void md_end_barrier(struct bio *bio, int err) +{ + mdk_rdev_t *rdev = bio->bi_private; + mddev_t *mddev = rdev->mddev; + if (err == -EOPNOTSUPP && mddev->barrier != POST_REQUEST_BARRIER) + set_bit(BIO_EOPNOTSUPP, &mddev->barrier->bi_flags); + + rdev_dec_pending(rdev, mddev); + + if (atomic_dec_and_test(&mddev->flush_pending)) { + if (mddev->barrier == POST_REQUEST_BARRIER) { + /* This was a post-request barrier */ + mddev->barrier = NULL; + wake_up(&mddev->sb_wait); + } else + /* The pre-request barrier has finished */ + schedule_work(&mddev->barrier_work); + } + bio_put(bio); +} + +static void submit_barriers(mddev_t *mddev) +{ + mdk_rdev_t *rdev; + + rcu_read_lock(); + list_for_each_entry_rcu(rdev, &mddev->disks, same_set) + if (rdev->raid_disk >= 0 && + !test_bit(Faulty, &rdev->flags)) { + /* Take two references, one is dropped + * when request finishes, one after + * we reclaim rcu_read_lock + */ + struct bio *bi; + atomic_inc(&rdev->nr_pending); + atomic_inc(&rdev->nr_pending); + rcu_read_unlock(); + bi = bio_alloc(GFP_KERNEL, 0); + bi->bi_end_io = md_end_barrier; + bi->bi_private = rdev; + bi->bi_bdev = rdev->bdev; + atomic_inc(&mddev->flush_pending); + submit_bio(WRITE_BARRIER, bi); + rcu_read_lock(); + rdev_dec_pending(rdev, mddev); + } + rcu_read_unlock(); +} + +static void md_submit_barrier(struct work_struct *ws) +{ + mddev_t *mddev = container_of(ws, mddev_t, barrier_work); + struct bio *bio = mddev->barrier; + + atomic_set(&mddev->flush_pending, 1); + + if (test_bit(BIO_EOPNOTSUPP, &bio->bi_flags)) + bio_endio(bio, -EOPNOTSUPP); + else if (bio->bi_size == 0) + /* an empty barrier - all done */ + bio_endio(bio, 0); + else { + bio->bi_rw &= ~(1<pers->make_request(mddev->queue, bio)) + generic_make_request(bio); + mddev->barrier = POST_REQUEST_BARRIER; + submit_barriers(mddev); + } + if (atomic_dec_and_test(&mddev->flush_pending)) { + mddev->barrier = NULL; + wake_up(&mddev->sb_wait); + } +} + +void md_barrier_request(mddev_t *mddev, struct bio *bio) +{ + spin_lock_irq(&mddev->write_lock); + wait_event_lock_irq(mddev->sb_wait, + !mddev->barrier, + mddev->write_lock, /*nothing*/); + mddev->barrier = bio; + spin_unlock_irq(&mddev->write_lock); + + atomic_set(&mddev->flush_pending, 1); + INIT_WORK(&mddev->barrier_work, md_submit_barrier); + + submit_barriers(mddev); + + if (atomic_dec_and_test(&mddev->flush_pending)) + schedule_work(&mddev->barrier_work); +} +EXPORT_SYMBOL(md_barrier_request); static inline mddev_t *mddev_get(mddev_t *mddev) { @@ -363,6 +470,7 @@ static mddev_t * mddev_find(dev_t unit) mutex_init(&new->open_mutex); mutex_init(&new->reconfig_mutex); + mutex_init(&new->bitmap_info.mutex); INIT_LIST_HEAD(&new->disks); INIT_LIST_HEAD(&new->all_mddevs); init_timer(&new->safemode_timer); @@ -370,6 +478,7 @@ static mddev_t * mddev_find(dev_t unit) atomic_set(&new->openers, 0); atomic_set(&new->active_io, 0); spin_lock_init(&new->write_lock); + atomic_set(&new->flush_pending, 0); init_waitqueue_head(&new->sb_wait); init_waitqueue_head(&new->recovery_wait); new->reshape_position = MaxSector; @@ -748,7 +857,7 @@ struct super_type { */ int md_check_no_bitmap(mddev_t *mddev) { - if (!mddev->bitmap_file && !mddev->bitmap_offset) + if (!mddev->bitmap_info.file && !mddev->bitmap_info.offset) return 0; printk(KERN_ERR "%s: bitmaps are not supported for %s\n", mdname(mddev), mddev->pers->name); @@ -876,8 +985,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->raid_disks = sb->raid_disks; mddev->dev_sectors = sb->size * 2; mddev->events = ev1; - mddev->bitmap_offset = 0; - mddev->default_bitmap_offset = MD_SB_BYTES >> 9; + mddev->bitmap_info.offset = 0; + mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9; if (mddev->minor_version >= 91) { mddev->reshape_position = sb->reshape_position; @@ -911,8 +1020,9 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->max_disks = MD_SB_DISKS; if (sb->state & (1<bitmap_file == NULL) - mddev->bitmap_offset = mddev->default_bitmap_offset; + mddev->bitmap_info.file == NULL) + mddev->bitmap_info.offset = + mddev->bitmap_info.default_offset; } else if (mddev->pers == NULL) { /* Insist on good event counter while assembling */ @@ -1029,7 +1139,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) sb->layout = mddev->layout; sb->chunk_size = mddev->chunk_sectors << 9; - if (mddev->bitmap && mddev->bitmap_file == NULL) + if (mddev->bitmap && mddev->bitmap_info.file == NULL) sb->state |= (1<disks[0].state = (1<mddev->dev_sectors) return 0; /* component must fit device */ - if (rdev->mddev->bitmap_offset) + if (rdev->mddev->bitmap_info.offset) return 0; /* can't move bitmap */ rdev->sb_start = calc_dev_sboffset(rdev->bdev); if (!num_sectors || num_sectors > rdev->sb_start) @@ -1286,8 +1396,8 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->raid_disks = le32_to_cpu(sb->raid_disks); mddev->dev_sectors = le64_to_cpu(sb->size); mddev->events = ev1; - mddev->bitmap_offset = 0; - mddev->default_bitmap_offset = 1024 >> 9; + mddev->bitmap_info.offset = 0; + mddev->bitmap_info.default_offset = 1024 >> 9; mddev->recovery_cp = le64_to_cpu(sb->resync_offset); memcpy(mddev->uuid, sb->set_uuid, 16); @@ -1295,8 +1405,9 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->max_disks = (4096-256)/2; if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) && - mddev->bitmap_file == NULL ) - mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset); + mddev->bitmap_info.file == NULL ) + mddev->bitmap_info.offset = + (__s32)le32_to_cpu(sb->bitmap_offset); if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) { mddev->reshape_position = le64_to_cpu(sb->reshape_position); @@ -1390,19 +1501,17 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) sb->level = cpu_to_le32(mddev->level); sb->layout = cpu_to_le32(mddev->layout); - if (mddev->bitmap && mddev->bitmap_file == NULL) { - sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset); + if (mddev->bitmap && mddev->bitmap_info.file == NULL) { + sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_info.offset); sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); } if (rdev->raid_disk >= 0 && !test_bit(In_sync, &rdev->flags)) { - if (rdev->recovery_offset > 0) { - sb->feature_map |= - cpu_to_le32(MD_FEATURE_RECOVERY_OFFSET); - sb->recovery_offset = - cpu_to_le64(rdev->recovery_offset); - } + sb->feature_map |= + cpu_to_le32(MD_FEATURE_RECOVERY_OFFSET); + sb->recovery_offset = + cpu_to_le64(rdev->recovery_offset); } if (mddev->reshape_position != MaxSector) { @@ -1436,7 +1545,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) 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) + else if (rdev2->raid_disk >= 0) sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk); else sb->dev_roles[i] = cpu_to_le16(0xffff); @@ -1458,7 +1567,7 @@ super_1_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors) max_sectors -= rdev->data_offset; if (!num_sectors || num_sectors > max_sectors) num_sectors = max_sectors; - } else if (rdev->mddev->bitmap_offset) { + } else if (rdev->mddev->bitmap_info.offset) { /* minor version 0 with bitmap we can't move */ return 0; } else { @@ -2442,12 +2551,49 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len) static struct rdev_sysfs_entry rdev_size = __ATTR(size, S_IRUGO|S_IWUSR, rdev_size_show, rdev_size_store); + +static ssize_t recovery_start_show(mdk_rdev_t *rdev, char *page) +{ + unsigned long long recovery_start = rdev->recovery_offset; + + if (test_bit(In_sync, &rdev->flags) || + recovery_start == MaxSector) + return sprintf(page, "none\n"); + + return sprintf(page, "%llu\n", recovery_start); +} + +static ssize_t recovery_start_store(mdk_rdev_t *rdev, const char *buf, size_t len) +{ + unsigned long long recovery_start; + + if (cmd_match(buf, "none")) + recovery_start = MaxSector; + else if (strict_strtoull(buf, 10, &recovery_start)) + return -EINVAL; + + if (rdev->mddev->pers && + rdev->raid_disk >= 0) + return -EBUSY; + + rdev->recovery_offset = recovery_start; + if (recovery_start == MaxSector) + set_bit(In_sync, &rdev->flags); + else + clear_bit(In_sync, &rdev->flags); + return len; +} + +static struct rdev_sysfs_entry rdev_recovery_start = +__ATTR(recovery_start, S_IRUGO|S_IWUSR, recovery_start_show, recovery_start_store); + static struct attribute *rdev_default_attrs[] = { &rdev_state.attr, &rdev_errors.attr, &rdev_slot.attr, &rdev_offset.attr, &rdev_size.attr, + &rdev_recovery_start.attr, NULL, }; static ssize_t @@ -2549,6 +2695,8 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi rdev->flags = 0; rdev->data_offset = 0; rdev->sb_events = 0; + rdev->last_read_error.tv_sec = 0; + rdev->last_read_error.tv_nsec = 0; atomic_set(&rdev->nr_pending, 0); atomic_set(&rdev->read_errors, 0); atomic_set(&rdev->corrected_errors, 0); @@ -2659,6 +2807,47 @@ static void analyze_sbs(mddev_t * mddev) } } +/* Read a fixed-point number. + * Numbers in sysfs attributes should be in "standard" units where + * possible, so time should be in seconds. + * However we internally use a a much smaller unit such as + * milliseconds or jiffies. + * This function takes a decimal number with a possible fractional + * component, and produces an integer which is the result of + * multiplying that number by 10^'scale'. + * all without any floating-point arithmetic. + */ +int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale) +{ + unsigned long result = 0; + long decimals = -1; + while (isdigit(*cp) || (*cp == '.' && decimals < 0)) { + if (*cp == '.') + decimals = 0; + else if (decimals < scale) { + unsigned int value; + value = *cp - '0'; + result = result * 10 + value; + if (decimals >= 0) + decimals++; + } + cp++; + } + if (*cp == '\n') + cp++; + if (*cp) + return -EINVAL; + if (decimals < 0) + decimals = 0; + while (decimals < scale) { + result *= 10; + decimals ++; + } + *res = result; + return 0; +} + + static void md_safemode_timeout(unsigned long data); static ssize_t @@ -2670,31 +2859,10 @@ safe_delay_show(mddev_t *mddev, char *page) 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]; - /* remove a period, and count digits after it */ - if (len >= sizeof(buf)) - return -EINVAL; - strlcpy(buf, cbuf, sizeof(buf)); - for (i=0; isafemode_delay = 0; else { @@ -2970,7 +3138,9 @@ resync_start_store(mddev_t *mddev, const char *buf, size_t len) if (mddev->pers) return -EBUSY; - if (!*buf || (*e && *e != '\n')) + if (cmd_match(buf, "none")) + n = MaxSector; + else if (!*buf || (*e && *e != '\n')) return -EINVAL; mddev->recovery_cp = n; @@ -3165,6 +3335,29 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) static struct md_sysfs_entry md_array_state = __ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store); +static ssize_t +max_corrected_read_errors_show(mddev_t *mddev, char *page) { + return sprintf(page, "%d\n", + atomic_read(&mddev->max_corr_read_errors)); +} + +static ssize_t +max_corrected_read_errors_store(mddev_t *mddev, const char *buf, size_t len) +{ + char *e; + unsigned long n = simple_strtoul(buf, &e, 10); + + if (*buf && (*e == 0 || *e == '\n')) { + atomic_set(&mddev->max_corr_read_errors, n); + return len; + } + return -EINVAL; +} + +static struct md_sysfs_entry max_corr_read_errors = +__ATTR(max_read_errors, S_IRUGO|S_IWUSR, max_corrected_read_errors_show, + max_corrected_read_errors_store); + static ssize_t null_show(mddev_t *mddev, char *page) { @@ -3790,6 +3983,7 @@ static struct attribute *md_default_attrs[] = { &md_array_state.attr, &md_reshape_position.attr, &md_array_size.attr, + &max_corr_read_errors.attr, NULL, }; @@ -3894,6 +4088,7 @@ static void mddev_delayed_delete(struct work_struct *ws) mddev->sysfs_action = NULL; mddev->private = NULL; } + sysfs_remove_group(&mddev->kobj, &md_bitmap_group); kobject_del(&mddev->kobj); kobject_put(&mddev->kobj); } @@ -3985,6 +4180,8 @@ static int md_alloc(dev_t dev, char *name) disk->disk_name); error = 0; } + if (sysfs_create_group(&mddev->kobj, &md_bitmap_group)) + printk(KERN_DEBUG "pointless warning\n"); abort: mutex_unlock(&disks_mutex); if (!error) { @@ -4206,6 +4403,8 @@ static int do_md_run(mddev_t * mddev) mddev->ro = 0; atomic_set(&mddev->writes_pending,0); + atomic_set(&mddev->max_corr_read_errors, + MD_DEFAULT_MAX_CORRECTED_READ_ERRORS); mddev->safemode = 0; mddev->safemode_timer.function = md_safemode_timeout; mddev->safemode_timer.data = (unsigned long) mddev; @@ -4310,7 +4509,7 @@ static int deny_bitmap_write_access(struct file * file) return 0; } -static void restore_bitmap_write_access(struct file *file) +void restore_bitmap_write_access(struct file *file) { struct inode *inode = file->f_mapping->host; @@ -4405,12 +4604,12 @@ out: printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); bitmap_destroy(mddev); - if (mddev->bitmap_file) { - restore_bitmap_write_access(mddev->bitmap_file); - fput(mddev->bitmap_file); - mddev->bitmap_file = NULL; + if (mddev->bitmap_info.file) { + restore_bitmap_write_access(mddev->bitmap_info.file); + fput(mddev->bitmap_info.file); + mddev->bitmap_info.file = NULL; } - mddev->bitmap_offset = 0; + mddev->bitmap_info.offset = 0; /* make sure all md_delayed_delete calls have finished */ flush_scheduled_work(); @@ -4451,6 +4650,11 @@ out: mddev->degraded = 0; mddev->barriers_work = 0; mddev->safemode = 0; + mddev->bitmap_info.offset = 0; + mddev->bitmap_info.default_offset = 0; + mddev->bitmap_info.chunksize = 0; + mddev->bitmap_info.daemon_sleep = 0; + mddev->bitmap_info.max_write_behind = 0; kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); if (mddev->hold_active == UNTIL_STOP) mddev->hold_active = 0; @@ -4636,7 +4840,7 @@ static int get_array_info(mddev_t * mddev, void __user * arg) info.state = 0; if (mddev->in_sync) info.state = (1<bitmap && mddev->bitmap_offset) + if (mddev->bitmap && mddev->bitmap_info.offset) info.state = (1<= 0) { if (mddev->bitmap) return -EEXIST; /* cannot add when bitmap is present */ - mddev->bitmap_file = fget(fd); + mddev->bitmap_info.file = fget(fd); - if (mddev->bitmap_file == NULL) { + if (mddev->bitmap_info.file == NULL) { printk(KERN_ERR "%s: error: failed to get bitmap file\n", mdname(mddev)); return -EBADF; } - err = deny_bitmap_write_access(mddev->bitmap_file); + err = deny_bitmap_write_access(mddev->bitmap_info.file); if (err) { printk(KERN_ERR "%s: error: bitmap file is already in use\n", mdname(mddev)); - fput(mddev->bitmap_file); - mddev->bitmap_file = NULL; + fput(mddev->bitmap_info.file); + mddev->bitmap_info.file = NULL; return err; } - mddev->bitmap_offset = 0; /* file overrides offset */ + mddev->bitmap_info.offset = 0; /* file overrides offset */ } else if (mddev->bitmap == NULL) return -ENOENT; /* cannot remove what isn't there */ err = 0; @@ -5025,11 +5229,11 @@ static int set_bitmap_file(mddev_t *mddev, int fd) mddev->pers->quiesce(mddev, 0); } if (fd < 0) { - if (mddev->bitmap_file) { - restore_bitmap_write_access(mddev->bitmap_file); - fput(mddev->bitmap_file); + if (mddev->bitmap_info.file) { + restore_bitmap_write_access(mddev->bitmap_info.file); + fput(mddev->bitmap_info.file); } - mddev->bitmap_file = NULL; + mddev->bitmap_info.file = NULL; } return err; @@ -5096,8 +5300,8 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) mddev->flags = 0; set_bit(MD_CHANGE_DEVS, &mddev->flags); - mddev->default_bitmap_offset = MD_SB_BYTES >> 9; - mddev->bitmap_offset = 0; + mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9; + mddev->bitmap_info.offset = 0; mddev->reshape_position = MaxSector; @@ -5197,7 +5401,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info) int state = 0; /* calculate expected state,ignoring low bits */ - if (mddev->bitmap && mddev->bitmap_offset) + if (mddev->bitmap && mddev->bitmap_info.offset) state |= (1 << MD_SB_BITMAP_PRESENT); if (mddev->major_version != info->major_version || @@ -5256,9 +5460,10 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info) /* add the bitmap */ if (mddev->bitmap) return -EEXIST; - if (mddev->default_bitmap_offset == 0) + if (mddev->bitmap_info.default_offset == 0) return -EINVAL; - mddev->bitmap_offset = mddev->default_bitmap_offset; + mddev->bitmap_info.offset = + mddev->bitmap_info.default_offset; mddev->pers->quiesce(mddev, 1); rv = bitmap_create(mddev); if (rv) @@ -5273,7 +5478,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info) mddev->pers->quiesce(mddev, 1); bitmap_destroy(mddev); mddev->pers->quiesce(mddev, 0); - mddev->bitmap_offset = 0; + mddev->bitmap_info.offset = 0; } } md_update_sb(mddev, 1); @@ -5524,6 +5729,25 @@ done: abort: return err; } +#ifdef CONFIG_COMPAT +static int md_compat_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case HOT_REMOVE_DISK: + case HOT_ADD_DISK: + case SET_DISK_FAULTY: + case SET_BITMAP_FILE: + /* These take in integer arg, do not convert */ + break; + default: + arg = (unsigned long)compat_ptr(arg); + break; + } + + return md_ioctl(bdev, mode, cmd, arg); +} +#endif /* CONFIG_COMPAT */ static int md_open(struct block_device *bdev, fmode_t mode) { @@ -5589,6 +5813,9 @@ static const struct block_device_operations md_fops = .open = md_open, .release = md_release, .ioctl = md_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = md_compat_ioctl, +#endif .getgeo = md_getgeo, .media_changed = md_media_changed, .revalidate_disk= md_revalidate, @@ -5982,14 +6209,14 @@ static int md_seq_show(struct seq_file *seq, void *v) unsigned long chunk_kb; unsigned long flags; spin_lock_irqsave(&bitmap->lock, flags); - chunk_kb = bitmap->chunksize >> 10; + chunk_kb = mddev->bitmap_info.chunksize >> 10; seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], " "%lu%s chunk", bitmap->pages - bitmap->missing_pages, bitmap->pages, (bitmap->pages - bitmap->missing_pages) << (PAGE_SHIFT - 10), - chunk_kb ? chunk_kb : bitmap->chunksize, + chunk_kb ? chunk_kb : mddev->bitmap_info.chunksize, chunk_kb ? "KB" : "B"); if (bitmap->file) { seq_printf(seq, ", file: "); @@ -6338,12 +6565,14 @@ void md_do_sync(mddev_t *mddev) /* recovery follows the physical size of devices */ max_sectors = mddev->dev_sectors; j = MaxSector; - list_for_each_entry(rdev, &mddev->disks, same_set) + rcu_read_lock(); + list_for_each_entry_rcu(rdev, &mddev->disks, same_set) if (rdev->raid_disk >= 0 && !test_bit(Faulty, &rdev->flags) && !test_bit(In_sync, &rdev->flags) && rdev->recovery_offset < j) j = rdev->recovery_offset; + rcu_read_unlock(); } printk(KERN_INFO "md: %s of RAID array %s\n", desc, mdname(mddev)); @@ -6380,6 +6609,7 @@ void md_do_sync(mddev_t *mddev) desc, mdname(mddev)); mddev->curr_resync = j; } + mddev->curr_resync_completed = mddev->curr_resync; while (j < max_sectors) { sector_t sectors; @@ -6512,22 +6742,29 @@ void md_do_sync(mddev_t *mddev) } else { if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) mddev->curr_resync = MaxSector; - list_for_each_entry(rdev, &mddev->disks, same_set) + rcu_read_lock(); + list_for_each_entry_rcu(rdev, &mddev->disks, same_set) 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; + rcu_read_unlock(); } } set_bit(MD_CHANGE_DEVS, &mddev->flags); skip: + if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { + /* We completed so min/max setting can be forgotten if used. */ + if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) + mddev->resync_min = 0; + mddev->resync_max = MaxSector; + } else if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) + mddev->resync_min = mddev->curr_resync_completed; mddev->curr_resync = 0; - mddev->curr_resync_completed = 0; if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) - /* We completed so max setting can be forgotten. */ - mddev->resync_max = MaxSector; + mddev->curr_resync_completed = 0; sysfs_notify(&mddev->kobj, NULL, "sync_completed"); wake_up(&resync_wait); set_bit(MD_RECOVERY_DONE, &mddev->recovery); @@ -6590,6 +6827,7 @@ static int remove_and_add_spares(mddev_t *mddev) nm, mdname(mddev)); spares++; md_new_event(mddev); + set_bit(MD_CHANGE_DEVS, &mddev->flags); } else break; } @@ -6625,7 +6863,7 @@ void md_check_recovery(mddev_t *mddev) if (mddev->bitmap) - bitmap_daemon_work(mddev->bitmap); + bitmap_daemon_work(mddev); if (mddev->ro) return; @@ -6995,5 +7233,6 @@ EXPORT_SYMBOL(md_unregister_thread); EXPORT_SYMBOL(md_wakeup_thread); EXPORT_SYMBOL(md_check_recovery); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MD RAID framework"); MODULE_ALIAS("md"); MODULE_ALIAS_BLOCKDEV_MAJOR(MD_MAJOR); diff --git a/drivers/md/md.h b/drivers/md/md.h index f184b69ef337514d460d669ffc4309a7d5dcc515..8e4c75c00d4628f76ca32e0aaab243e3aea70d4c 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -97,6 +97,9 @@ struct mdk_rdev_s atomic_t read_errors; /* number of consecutive read errors that * we have tried to ignore. */ + struct timespec last_read_error; /* monotonic time since our + * last read error + */ atomic_t corrected_errors; /* number of corrected read errors, * for reporting to userspace and storing * in superblock. @@ -280,17 +283,38 @@ struct mddev_s unsigned int max_write_behind; /* 0 = sync */ struct bitmap *bitmap; /* the bitmap for the device */ - struct file *bitmap_file; /* the bitmap file */ - long bitmap_offset; /* offset from superblock of - * start of bitmap. May be - * negative, but not '0' - */ - long default_bitmap_offset; /* this is the offset to use when - * hot-adding a bitmap. It should - * eventually be settable by sysfs. - */ - + struct { + struct file *file; /* the bitmap file */ + loff_t offset; /* offset from superblock of + * start of bitmap. May be + * negative, but not '0' + * For external metadata, offset + * from start of device. + */ + loff_t default_offset; /* this is the offset to use when + * hot-adding a bitmap. It should + * eventually be settable by sysfs. + */ + struct mutex mutex; + unsigned long chunksize; + unsigned long daemon_sleep; /* how many seconds between updates? */ + unsigned long max_write_behind; /* write-behind mode */ + int external; + } bitmap_info; + + atomic_t max_corr_read_errors; /* max read retries */ struct list_head all_mddevs; + + /* Generic barrier handling. + * If there is a pending barrier request, all other + * writes are blocked while the devices are flushed. + * The last to finish a flush schedules a worker to + * submit the barrier request (without the barrier flag), + * then submit more flush requests. + */ + struct bio *barrier; + atomic_t flush_pending; + struct work_struct barrier_work; }; @@ -353,7 +377,7 @@ struct md_sysfs_entry { ssize_t (*show)(mddev_t *, char *); ssize_t (*store)(mddev_t *, const char *, size_t); }; - +extern struct attribute_group md_bitmap_group; static inline char * mdname (mddev_t * mddev) { @@ -431,6 +455,7 @@ extern void md_done_sync(mddev_t *mddev, int blocks, int ok); extern void md_error(mddev_t *mddev, mdk_rdev_t *rdev); extern int mddev_congested(mddev_t *mddev, int bits); +extern void md_barrier_request(mddev_t *mddev, struct bio *bio); extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, sector_t sector, int size, struct page *page); extern void md_super_wait(mddev_t *mddev); @@ -443,6 +468,8 @@ extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev); extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors); extern int md_check_no_bitmap(mddev_t *mddev); extern int md_integrity_register(mddev_t *mddev); -void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev); +extern void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev); +extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale); +extern void restore_bitmap_write_access(struct file *file); #endif /* _MD_MD_H */ diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index ee7646f974a07165bd368deb3a18f6390e5553dc..32a662fc55c95d5f08de09362f85d0d6ab0917e3 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -145,7 +145,7 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) int cpu; if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { - bio_endio(bio, -EOPNOTSUPP); + md_barrier_request(mddev, bio); return 0; } @@ -581,6 +581,7 @@ static void __exit multipath_exit (void) module_init(multipath_init); module_exit(multipath_exit); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("simple multi-path personality for MD"); MODULE_ALIAS("md-personality-7"); /* MULTIPATH */ MODULE_ALIAS("md-multipath"); MODULE_ALIAS("md-level--4"); diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index d3a4ce06015a300e9d4df5e95ee63669613db17e..77605cdceaf179ce1a5ce15d9bf50d4239efb91e 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -453,7 +453,7 @@ static int raid0_make_request(struct request_queue *q, struct bio *bio) int cpu; if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { - bio_endio(bio, -EOPNOTSUPP); + md_barrier_request(mddev, bio); return 0; } @@ -567,6 +567,7 @@ static void raid0_exit (void) module_init(raid0_init); module_exit(raid0_exit); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("RAID0 (striping) personality for MD"); MODULE_ALIAS("md-personality-2"); /* RAID0 */ MODULE_ALIAS("md-raid0"); MODULE_ALIAS("md-level-0"); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index e07ce2e033a95c48ba2c9a78c519640743220e2d..859bd3ffe4351bad9204aa04e906e751a788c64a 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -677,6 +677,7 @@ static void raise_barrier(conf_t *conf) static void lower_barrier(conf_t *conf) { unsigned long flags; + BUG_ON(conf->barrier <= 0); spin_lock_irqsave(&conf->resync_lock, flags); conf->barrier--; spin_unlock_irqrestore(&conf->resync_lock, flags); @@ -801,6 +802,25 @@ static int make_request(struct request_queue *q, struct bio * bio) md_write_start(mddev, bio); /* wait on superblock update early */ + if (bio_data_dir(bio) == WRITE && + bio->bi_sector + bio->bi_size/512 > mddev->suspend_lo && + bio->bi_sector < mddev->suspend_hi) { + /* As the suspend_* range is controlled by + * userspace, we want an interruptible + * wait. + */ + DEFINE_WAIT(w); + for (;;) { + flush_signals(current); + prepare_to_wait(&conf->wait_barrier, + &w, TASK_INTERRUPTIBLE); + if (bio->bi_sector + bio->bi_size/512 <= mddev->suspend_lo || + bio->bi_sector >= mddev->suspend_hi) + break; + schedule(); + } + finish_wait(&conf->wait_barrier, &w); + } if (unlikely(!mddev->barriers_work && bio_rw_flagged(bio, BIO_RW_BARRIER))) { if (rw == WRITE) @@ -923,7 +943,8 @@ static int make_request(struct request_queue *q, struct bio * bio) /* do behind I/O ? */ if (bitmap && - atomic_read(&bitmap->behind_writes) < bitmap->max_write_behind && + (atomic_read(&bitmap->behind_writes) + < mddev->bitmap_info.max_write_behind) && (behind_pages = alloc_behind_pages(bio)) != NULL) set_bit(R1BIO_BehindIO, &r1_bio->state); @@ -1941,74 +1962,48 @@ static sector_t raid1_size(mddev_t *mddev, sector_t sectors, int raid_disks) return mddev->dev_sectors; } -static int run(mddev_t *mddev) +static conf_t *setup_conf(mddev_t *mddev) { conf_t *conf; - int i, j, disk_idx; + int i; mirror_info_t *disk; mdk_rdev_t *rdev; + int err = -ENOMEM; - if (mddev->level != 1) { - printk("raid1: %s: raid level not set to mirroring (%d)\n", - mdname(mddev), mddev->level); - goto out; - } - if (mddev->reshape_position != MaxSector) { - printk("raid1: %s: reshape_position set but not supported\n", - mdname(mddev)); - goto out; - } - /* - * copy the already verified devices into our private RAID1 - * bookkeeping area. [whatever we allocate in run(), - * should be freed in stop()] - */ conf = kzalloc(sizeof(conf_t), GFP_KERNEL); - mddev->private = conf; if (!conf) - goto out_no_mem; + goto abort; conf->mirrors = kzalloc(sizeof(struct mirror_info)*mddev->raid_disks, GFP_KERNEL); if (!conf->mirrors) - goto out_no_mem; + goto abort; conf->tmppage = alloc_page(GFP_KERNEL); if (!conf->tmppage) - goto out_no_mem; + goto abort; - conf->poolinfo = kmalloc(sizeof(*conf->poolinfo), GFP_KERNEL); + conf->poolinfo = kzalloc(sizeof(*conf->poolinfo), GFP_KERNEL); if (!conf->poolinfo) - goto out_no_mem; - conf->poolinfo->mddev = NULL; + goto abort; conf->poolinfo->raid_disks = mddev->raid_disks; conf->r1bio_pool = mempool_create(NR_RAID1_BIOS, r1bio_pool_alloc, r1bio_pool_free, conf->poolinfo); if (!conf->r1bio_pool) - goto out_no_mem; + goto abort; + conf->poolinfo->mddev = mddev; spin_lock_init(&conf->device_lock); - mddev->queue->queue_lock = &conf->device_lock; - list_for_each_entry(rdev, &mddev->disks, same_set) { - disk_idx = rdev->raid_disk; + int disk_idx = rdev->raid_disk; if (disk_idx >= mddev->raid_disks || disk_idx < 0) continue; disk = conf->mirrors + disk_idx; disk->rdev = rdev; - disk_stack_limits(mddev->gendisk, rdev->bdev, - rdev->data_offset << 9); - /* as we don't honour merge_bvec_fn, we must never risk - * violating it, so limit ->max_sector to one PAGE, as - * a one page request is never in violation. - */ - if (rdev->bdev->bd_disk->queue->merge_bvec_fn && - queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9)) - blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); disk->head_position = 0; } @@ -2022,8 +2017,7 @@ static int run(mddev_t *mddev) bio_list_init(&conf->pending_bio_list); bio_list_init(&conf->flushing_bio_list); - - mddev->degraded = 0; + conf->last_used = -1; for (i = 0; i < conf->raid_disks; i++) { disk = conf->mirrors + i; @@ -2031,38 +2025,97 @@ static int run(mddev_t *mddev) if (!disk->rdev || !test_bit(In_sync, &disk->rdev->flags)) { disk->head_position = 0; - mddev->degraded++; if (disk->rdev) conf->fullsync = 1; - } + } else if (conf->last_used < 0) + /* + * The first working device is used as a + * starting point to read balancing. + */ + conf->last_used = i; } - if (mddev->degraded == conf->raid_disks) { + + err = -EIO; + if (conf->last_used < 0) { printk(KERN_ERR "raid1: no operational mirrors for %s\n", - mdname(mddev)); - goto out_free_conf; + mdname(mddev)); + goto abort; } - if (conf->raid_disks - mddev->degraded == 1) - mddev->recovery_cp = MaxSector; + err = -ENOMEM; + conf->thread = md_register_thread(raid1d, mddev, NULL); + if (!conf->thread) { + printk(KERN_ERR + "raid1: couldn't allocate thread for %s\n", + mdname(mddev)); + goto abort; + } + + return conf; + + abort: + if (conf) { + if (conf->r1bio_pool) + mempool_destroy(conf->r1bio_pool); + kfree(conf->mirrors); + safe_put_page(conf->tmppage); + kfree(conf->poolinfo); + kfree(conf); + } + return ERR_PTR(err); +} +static int run(mddev_t *mddev) +{ + conf_t *conf; + int i; + mdk_rdev_t *rdev; + + if (mddev->level != 1) { + printk("raid1: %s: raid level not set to mirroring (%d)\n", + mdname(mddev), mddev->level); + return -EIO; + } + if (mddev->reshape_position != MaxSector) { + printk("raid1: %s: reshape_position set but not supported\n", + mdname(mddev)); + return -EIO; + } /* - * find the first working one and use it as a starting point - * to read balancing. + * copy the already verified devices into our private RAID1 + * bookkeeping area. [whatever we allocate in run(), + * should be freed in stop()] */ - for (j = 0; j < conf->raid_disks && - (!conf->mirrors[j].rdev || - !test_bit(In_sync, &conf->mirrors[j].rdev->flags)) ; j++) - /* nothing */; - conf->last_used = j; + if (mddev->private == NULL) + conf = setup_conf(mddev); + else + conf = mddev->private; + if (IS_ERR(conf)) + return PTR_ERR(conf); - mddev->thread = md_register_thread(raid1d, mddev, NULL); - if (!mddev->thread) { - printk(KERN_ERR - "raid1: couldn't allocate thread for %s\n", - mdname(mddev)); - goto out_free_conf; + mddev->queue->queue_lock = &conf->device_lock; + list_for_each_entry(rdev, &mddev->disks, same_set) { + disk_stack_limits(mddev->gendisk, rdev->bdev, + rdev->data_offset << 9); + /* as we don't honour merge_bvec_fn, we must never risk + * violating it, so limit ->max_sector to one PAGE, as + * a one page request is never in violation. + */ + if (rdev->bdev->bd_disk->queue->merge_bvec_fn && + queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9)) + blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); } + mddev->degraded = 0; + for (i=0; i < conf->raid_disks; i++) + if (conf->mirrors[i].rdev == NULL || + !test_bit(In_sync, &conf->mirrors[i].rdev->flags) || + test_bit(Faulty, &conf->mirrors[i].rdev->flags)) + mddev->degraded++; + + if (conf->raid_disks - mddev->degraded == 1) + mddev->recovery_cp = MaxSector; + if (mddev->recovery_cp != MaxSector) printk(KERN_NOTICE "raid1: %s is not clean" " -- starting background reconstruction\n", @@ -2071,9 +2124,14 @@ static int run(mddev_t *mddev) "raid1: raid set %s active with %d out of %d mirrors\n", mdname(mddev), mddev->raid_disks - mddev->degraded, mddev->raid_disks); + /* * Ok, everything is just fine now */ + mddev->thread = conf->thread; + conf->thread = NULL; + mddev->private = conf; + md_set_array_sectors(mddev, raid1_size(mddev, 0, 0)); mddev->queue->unplug_fn = raid1_unplug; @@ -2081,23 +2139,6 @@ static int run(mddev_t *mddev) mddev->queue->backing_dev_info.congested_data = mddev; md_integrity_register(mddev); return 0; - -out_no_mem: - printk(KERN_ERR "raid1: couldn't allocate memory for %s\n", - mdname(mddev)); - -out_free_conf: - if (conf) { - if (conf->r1bio_pool) - mempool_destroy(conf->r1bio_pool); - kfree(conf->mirrors); - safe_put_page(conf->tmppage); - kfree(conf->poolinfo); - kfree(conf); - mddev->private = NULL; - } -out: - return -EIO; } static int stop(mddev_t *mddev) @@ -2271,6 +2312,9 @@ static void raid1_quiesce(mddev_t *mddev, int state) conf_t *conf = mddev->private; switch(state) { + case 2: /* wake for suspend */ + wake_up(&conf->wait_barrier); + break; case 1: raise_barrier(conf); break; @@ -2280,6 +2324,23 @@ static void raid1_quiesce(mddev_t *mddev, int state) } } +static void *raid1_takeover(mddev_t *mddev) +{ + /* raid1 can take over: + * raid5 with 2 devices, any layout or chunk size + */ + if (mddev->level == 5 && mddev->raid_disks == 2) { + conf_t *conf; + mddev->new_level = 1; + mddev->new_layout = 0; + mddev->new_chunk_sectors = 0; + conf = setup_conf(mddev); + if (!IS_ERR(conf)) + conf->barrier = 1; + return conf; + } + return ERR_PTR(-EINVAL); +} static struct mdk_personality raid1_personality = { @@ -2299,6 +2360,7 @@ static struct mdk_personality raid1_personality = .size = raid1_size, .check_reshape = raid1_reshape, .quiesce = raid1_quiesce, + .takeover = raid1_takeover, }; static int __init raid_init(void) @@ -2314,6 +2376,7 @@ static void raid_exit(void) module_init(raid_init); module_exit(raid_exit); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("RAID1 (mirroring) personality for MD"); MODULE_ALIAS("md-personality-3"); /* RAID1 */ MODULE_ALIAS("md-raid1"); MODULE_ALIAS("md-level-1"); diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h index e87b84deff6831b4320bf2d496c4570ca14339f7..5f2d443ae28af03cb31d6b16d30495abc73b45ff 100644 --- a/drivers/md/raid1.h +++ b/drivers/md/raid1.h @@ -59,6 +59,11 @@ struct r1_private_data_s { mempool_t *r1bio_pool; mempool_t *r1buf_pool; + + /* When taking over an array from a different personality, we store + * the new thread here until we fully activate the array. + */ + struct mdk_thread_s *thread; }; typedef struct r1_private_data_s conf_t; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index c2cb7b87b440dce777d92bb6c215d1c82efddbe1..d119b7b75e71ffabe5863b0b3463b7a66304f831 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -804,7 +804,7 @@ static int make_request(struct request_queue *q, struct bio * bio) mdk_rdev_t *blocked_rdev; if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { - bio_endio(bio, -EOPNOTSUPP); + md_barrier_request(mddev, bio); return 0; } @@ -1431,6 +1431,43 @@ static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio) } +/* + * Used by fix_read_error() to decay the per rdev read_errors. + * We halve the read error count for every hour that has elapsed + * since the last recorded read error. + * + */ +static void check_decay_read_errors(mddev_t *mddev, mdk_rdev_t *rdev) +{ + struct timespec cur_time_mon; + unsigned long hours_since_last; + unsigned int read_errors = atomic_read(&rdev->read_errors); + + ktime_get_ts(&cur_time_mon); + + if (rdev->last_read_error.tv_sec == 0 && + rdev->last_read_error.tv_nsec == 0) { + /* first time we've seen a read error */ + rdev->last_read_error = cur_time_mon; + return; + } + + hours_since_last = (cur_time_mon.tv_sec - + rdev->last_read_error.tv_sec) / 3600; + + rdev->last_read_error = cur_time_mon; + + /* + * if hours_since_last is > the number of bits in read_errors + * just set read errors to 0. We do this to avoid + * overflowing the shift of read_errors by hours_since_last. + */ + if (hours_since_last >= 8 * sizeof(read_errors)) + atomic_set(&rdev->read_errors, 0); + else + atomic_set(&rdev->read_errors, read_errors >> hours_since_last); +} + /* * This is a kernel thread which: * @@ -1444,6 +1481,43 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) int sect = 0; /* Offset from r10_bio->sector */ int sectors = r10_bio->sectors; mdk_rdev_t*rdev; + int max_read_errors = atomic_read(&mddev->max_corr_read_errors); + + rcu_read_lock(); + { + int d = r10_bio->devs[r10_bio->read_slot].devnum; + char b[BDEVNAME_SIZE]; + int cur_read_error_count = 0; + + rdev = rcu_dereference(conf->mirrors[d].rdev); + bdevname(rdev->bdev, b); + + if (test_bit(Faulty, &rdev->flags)) { + rcu_read_unlock(); + /* drive has already been failed, just ignore any + more fix_read_error() attempts */ + return; + } + + check_decay_read_errors(mddev, rdev); + atomic_inc(&rdev->read_errors); + cur_read_error_count = atomic_read(&rdev->read_errors); + if (cur_read_error_count > max_read_errors) { + rcu_read_unlock(); + printk(KERN_NOTICE + "raid10: %s: Raid device exceeded " + "read_error threshold " + "[cur %d:max %d]\n", + b, cur_read_error_count, max_read_errors); + printk(KERN_NOTICE + "raid10: %s: Failing raid " + "device\n", b); + md_error(mddev, conf->mirrors[d].rdev); + return; + } + } + rcu_read_unlock(); + while(sectors) { int s = sectors; int sl = r10_bio->read_slot; @@ -1488,6 +1562,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) /* write it back and re-read */ rcu_read_lock(); while (sl != r10_bio->read_slot) { + char b[BDEVNAME_SIZE]; int d; if (sl==0) sl = conf->copies; @@ -1503,9 +1578,21 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) r10_bio->devs[sl].addr + sect + rdev->data_offset, s<<9, conf->tmppage, WRITE) - == 0) + == 0) { /* Well, this device is dead */ + printk(KERN_NOTICE + "raid10:%s: read correction " + "write failed" + " (%d sectors at %llu on %s)\n", + mdname(mddev), s, + (unsigned long long)(sect+ + rdev->data_offset), + bdevname(rdev->bdev, b)); + printk(KERN_NOTICE "raid10:%s: failing " + "drive\n", + bdevname(rdev->bdev, b)); md_error(mddev, rdev); + } rdev_dec_pending(rdev, mddev); rcu_read_lock(); } @@ -1526,10 +1613,22 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) if (sync_page_io(rdev->bdev, r10_bio->devs[sl].addr + sect + rdev->data_offset, - s<<9, conf->tmppage, READ) == 0) + s<<9, conf->tmppage, + READ) == 0) { /* Well, this device is dead */ + printk(KERN_NOTICE + "raid10:%s: unable to read back " + "corrected sectors" + " (%d sectors at %llu on %s)\n", + mdname(mddev), s, + (unsigned long long)(sect+ + rdev->data_offset), + bdevname(rdev->bdev, b)); + printk(KERN_NOTICE "raid10:%s: failing drive\n", + bdevname(rdev->bdev, b)); + md_error(mddev, rdev); - else + } else { printk(KERN_INFO "raid10:%s: read error corrected" " (%d sectors at %llu on %s)\n", @@ -1537,6 +1636,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) (unsigned long long)(sect+ rdev->data_offset), bdevname(rdev->bdev, b)); + } rdev_dec_pending(rdev, mddev); rcu_read_lock(); @@ -2275,13 +2375,6 @@ static void raid10_quiesce(mddev_t *mddev, int state) lower_barrier(conf); break; } - if (mddev->thread) { - if (mddev->bitmap) - mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ; - else - mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; - md_wakeup_thread(mddev->thread); - } } static struct mdk_personality raid10_personality = @@ -2315,6 +2408,7 @@ static void raid_exit(void) module_init(raid_init); module_exit(raid_exit); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("RAID10 (striped mirror) personality for MD"); MODULE_ALIAS("md-personality-9"); /* RAID10 */ MODULE_ALIAS("md-raid10"); MODULE_ALIAS("md-level-10"); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index d29215d966dadc23f4c1a6844a725dc89d6a8304..e84204eb12dff9c87daaf8ecbdba4462eda8971f 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2947,6 +2947,7 @@ static void handle_stripe5(struct stripe_head *sh) struct r5dev *dev; mdk_rdev_t *blocked_rdev = NULL; int prexor; + int dec_preread_active = 0; memset(&s, 0, sizeof(s)); pr_debug("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d check:%d " @@ -3096,12 +3097,8 @@ static void handle_stripe5(struct stripe_head *sh) 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); - } + if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) + dec_preread_active = 1; } /* Now to consider new write requests and what else, if anything @@ -3208,6 +3205,16 @@ static void handle_stripe5(struct stripe_head *sh) ops_run_io(sh, &s); + if (dec_preread_active) { + /* We delay this until after ops_run_io so that if make_request + * is waiting on a barrier, it won't continue until the writes + * have actually been submitted. + */ + atomic_dec(&conf->preread_active_stripes); + if (atomic_read(&conf->preread_active_stripes) < + IO_THRESHOLD) + md_wakeup_thread(conf->mddev->thread); + } return_io(return_bi); } @@ -3221,6 +3228,7 @@ static void handle_stripe6(struct stripe_head *sh) struct r6_state r6s; struct r5dev *dev, *pdev, *qdev; mdk_rdev_t *blocked_rdev = NULL; + int dec_preread_active = 0; pr_debug("handling stripe %llu, state=%#lx cnt=%d, " "pd_idx=%d, qd_idx=%d\n, check:%d, reconstruct:%d\n", @@ -3358,7 +3366,6 @@ static void handle_stripe6(struct stripe_head *sh) * completed */ if (sh->reconstruct_state == reconstruct_state_drain_result) { - int qd_idx = sh->qd_idx; sh->reconstruct_state = reconstruct_state_idle; /* All the 'written' buffers and the parity blocks are ready to @@ -3380,12 +3387,8 @@ static void handle_stripe6(struct stripe_head *sh) 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); - } + if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) + dec_preread_active = 1; } /* Now to consider new write requests and what else, if anything @@ -3494,6 +3497,18 @@ static void handle_stripe6(struct stripe_head *sh) ops_run_io(sh, &s); + + if (dec_preread_active) { + /* We delay this until after ops_run_io so that if make_request + * is waiting on a barrier, it won't continue until the writes + * have actually been submitted. + */ + atomic_dec(&conf->preread_active_stripes); + if (atomic_read(&conf->preread_active_stripes) < + IO_THRESHOLD) + md_wakeup_thread(conf->mddev->thread); + } + return_io(return_bi); } @@ -3741,7 +3756,7 @@ static int chunk_aligned_read(struct request_queue *q, struct bio * raid_bio) { mddev_t *mddev = q->queuedata; raid5_conf_t *conf = mddev->private; - unsigned int dd_idx; + int dd_idx; struct bio* align_bi; mdk_rdev_t *rdev; @@ -3866,7 +3881,13 @@ static int make_request(struct request_queue *q, struct bio * bi) int cpu, remaining; if (unlikely(bio_rw_flagged(bi, BIO_RW_BARRIER))) { - bio_endio(bi, -EOPNOTSUPP); + /* Drain all pending writes. We only really need + * to ensure they have been submitted, but this is + * easier. + */ + mddev->pers->quiesce(mddev, 1); + mddev->pers->quiesce(mddev, 0); + md_barrier_request(mddev, bi); return 0; } @@ -3990,6 +4011,9 @@ static int make_request(struct request_queue *q, struct bio * bi) finish_wait(&conf->wait_for_overlap, &w); set_bit(STRIPE_HANDLE, &sh->state); clear_bit(STRIPE_DELAYED, &sh->state); + if (mddev->barrier && + !test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) + atomic_inc(&conf->preread_active_stripes); release_stripe(sh); } else { /* cannot get stripe for read-ahead, just give-up */ @@ -4009,6 +4033,14 @@ static int make_request(struct request_queue *q, struct bio * bi) bio_endio(bi, 0); } + + if (mddev->barrier) { + /* We need to wait for the stripes to all be handled. + * So: wait for preread_active_stripes to drop to 0. + */ + wait_event(mddev->thread->wqueue, + atomic_read(&conf->preread_active_stripes) == 0); + } return 0; } @@ -5860,6 +5892,7 @@ static void raid5_exit(void) module_init(raid5_init); module_exit(raid5_exit); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("RAID4/5/6 (striping with parity) personality for MD"); MODULE_ALIAS("md-personality-4"); /* RAID5 */ MODULE_ALIAS("md-raid5"); MODULE_ALIAS("md-raid4"); diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c index 866215ac7f2554f86733cc900f4b902b3f60bc76..bffc61bff5ab7c743d4ce0da3d716cd8642112f0 100644 --- a/drivers/md/raid6algos.c +++ b/drivers/md/raid6algos.c @@ -31,25 +31,6 @@ EXPORT_SYMBOL(raid6_empty_zero_page); struct raid6_calls raid6_call; EXPORT_SYMBOL_GPL(raid6_call); -/* Various routine sets */ -extern const struct raid6_calls raid6_intx1; -extern const struct raid6_calls raid6_intx2; -extern const struct raid6_calls raid6_intx4; -extern const struct raid6_calls raid6_intx8; -extern const struct raid6_calls raid6_intx16; -extern const struct raid6_calls raid6_intx32; -extern const struct raid6_calls raid6_mmxx1; -extern const struct raid6_calls raid6_mmxx2; -extern const struct raid6_calls raid6_sse1x1; -extern const struct raid6_calls raid6_sse1x2; -extern const struct raid6_calls raid6_sse2x1; -extern const struct raid6_calls raid6_sse2x2; -extern const struct raid6_calls raid6_sse2x4; -extern const struct raid6_calls raid6_altivec1; -extern const struct raid6_calls raid6_altivec2; -extern const struct raid6_calls raid6_altivec4; -extern const struct raid6_calls raid6_altivec8; - const struct raid6_calls * const raid6_algos[] = { &raid6_intx1, &raid6_intx2, @@ -169,3 +150,4 @@ static void raid6_exit(void) subsys_initcall(raid6_select_algo); module_exit(raid6_exit); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("RAID6 Q-syndrome calculations"); diff --git a/drivers/media/common/tuners/max2165.c b/drivers/media/common/tuners/max2165.c index 1b486cfb8ed9876bffa0ac1b9a5f782e39503d00..3d03640cf1fe42aab8475419755f9294467e4968 100644 --- a/drivers/media/common/tuners/max2165.c +++ b/drivers/media/common/tuners/max2165.c @@ -193,7 +193,7 @@ static int max2165_set_rf(struct max2165_priv *priv, u32 freq) { u8 tf; u8 tf_ntch; - double t; + u32 t; u32 quotient, fraction; /* Set PLL divider according to RF frequency */ diff --git a/drivers/mfd/88pm8607.c b/drivers/mfd/88pm8607.c new file mode 100644 index 0000000000000000000000000000000000000000..7e3f65907993e111410b816d1bca5a2b1911750f --- /dev/null +++ b/drivers/mfd/88pm8607.c @@ -0,0 +1,302 @@ +/* + * Base driver for Marvell 88PM8607 + * + * Copyright (C) 2009 Marvell International Ltd. + * Haojian Zhuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + + +#define PM8607_REG_RESOURCE(_start, _end) \ +{ \ + .start = PM8607_##_start, \ + .end = PM8607_##_end, \ + .flags = IORESOURCE_IO, \ +} + +static struct resource pm8607_regulator_resources[] = { + PM8607_REG_RESOURCE(BUCK1, BUCK1), + PM8607_REG_RESOURCE(BUCK2, BUCK2), + PM8607_REG_RESOURCE(BUCK3, BUCK3), + PM8607_REG_RESOURCE(LDO1, LDO1), + PM8607_REG_RESOURCE(LDO2, LDO2), + PM8607_REG_RESOURCE(LDO3, LDO3), + PM8607_REG_RESOURCE(LDO4, LDO4), + PM8607_REG_RESOURCE(LDO5, LDO5), + PM8607_REG_RESOURCE(LDO6, LDO6), + PM8607_REG_RESOURCE(LDO7, LDO7), + PM8607_REG_RESOURCE(LDO8, LDO8), + PM8607_REG_RESOURCE(LDO9, LDO9), + PM8607_REG_RESOURCE(LDO10, LDO10), + PM8607_REG_RESOURCE(LDO12, LDO12), + PM8607_REG_RESOURCE(LDO14, LDO14), +}; + +#define PM8607_REG_DEVS(_name, _id) \ +{ \ + .name = "88pm8607-" #_name, \ + .num_resources = 1, \ + .resources = &pm8607_regulator_resources[PM8607_ID_##_id], \ +} + +static struct mfd_cell pm8607_devs[] = { + PM8607_REG_DEVS(buck1, BUCK1), + PM8607_REG_DEVS(buck2, BUCK2), + PM8607_REG_DEVS(buck3, BUCK3), + PM8607_REG_DEVS(ldo1, LDO1), + PM8607_REG_DEVS(ldo2, LDO2), + PM8607_REG_DEVS(ldo3, LDO3), + PM8607_REG_DEVS(ldo4, LDO4), + PM8607_REG_DEVS(ldo5, LDO5), + PM8607_REG_DEVS(ldo6, LDO6), + PM8607_REG_DEVS(ldo7, LDO7), + PM8607_REG_DEVS(ldo8, LDO8), + PM8607_REG_DEVS(ldo9, LDO9), + PM8607_REG_DEVS(ldo10, LDO10), + PM8607_REG_DEVS(ldo12, LDO12), + PM8607_REG_DEVS(ldo14, LDO14), +}; + +static inline int pm8607_read_device(struct pm8607_chip *chip, + int reg, int bytes, void *dest) +{ + struct i2c_client *i2c = chip->client; + unsigned char data; + int ret; + + data = (unsigned char)reg; + ret = i2c_master_send(i2c, &data, 1); + if (ret < 0) + return ret; + + ret = i2c_master_recv(i2c, dest, bytes); + if (ret < 0) + return ret; + return 0; +} + +static inline int pm8607_write_device(struct pm8607_chip *chip, + int reg, int bytes, void *src) +{ + struct i2c_client *i2c = chip->client; + unsigned char buf[bytes + 1]; + int ret; + + buf[0] = (unsigned char)reg; + memcpy(&buf[1], src, bytes); + + ret = i2c_master_send(i2c, buf, bytes + 1); + if (ret < 0) + return ret; + return 0; +} + +int pm8607_reg_read(struct pm8607_chip *chip, int reg) +{ + unsigned char data; + int ret; + + mutex_lock(&chip->io_lock); + ret = chip->read(chip, reg, 1, &data); + mutex_unlock(&chip->io_lock); + + if (ret < 0) + return ret; + else + return (int)data; +} +EXPORT_SYMBOL(pm8607_reg_read); + +int pm8607_reg_write(struct pm8607_chip *chip, int reg, + unsigned char data) +{ + int ret; + + mutex_lock(&chip->io_lock); + ret = chip->write(chip, reg, 1, &data); + mutex_unlock(&chip->io_lock); + + return ret; +} +EXPORT_SYMBOL(pm8607_reg_write); + +int pm8607_bulk_read(struct pm8607_chip *chip, int reg, + int count, unsigned char *buf) +{ + int ret; + + mutex_lock(&chip->io_lock); + ret = chip->read(chip, reg, count, buf); + mutex_unlock(&chip->io_lock); + + return ret; +} +EXPORT_SYMBOL(pm8607_bulk_read); + +int pm8607_bulk_write(struct pm8607_chip *chip, int reg, + int count, unsigned char *buf) +{ + int ret; + + mutex_lock(&chip->io_lock); + ret = chip->write(chip, reg, count, buf); + mutex_unlock(&chip->io_lock); + + return ret; +} +EXPORT_SYMBOL(pm8607_bulk_write); + +int pm8607_set_bits(struct pm8607_chip *chip, int reg, + unsigned char mask, unsigned char data) +{ + unsigned char value; + int ret; + + mutex_lock(&chip->io_lock); + ret = chip->read(chip, reg, 1, &value); + if (ret < 0) + goto out; + value &= ~mask; + value |= data; + ret = chip->write(chip, reg, 1, &value); +out: + mutex_unlock(&chip->io_lock); + return ret; +} +EXPORT_SYMBOL(pm8607_set_bits); + + +static const struct i2c_device_id pm8607_id_table[] = { + { "88PM8607", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, pm8607_id_table); + + +static int __devinit pm8607_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pm8607_platform_data *pdata = client->dev.platform_data; + struct pm8607_chip *chip; + int i, count; + int ret; + + chip = kzalloc(sizeof(struct pm8607_chip), GFP_KERNEL); + if (chip == NULL) + return -ENOMEM; + + chip->client = client; + chip->dev = &client->dev; + chip->read = pm8607_read_device; + chip->write = pm8607_write_device; + i2c_set_clientdata(client, chip); + + mutex_init(&chip->io_lock); + dev_set_drvdata(chip->dev, chip); + + ret = pm8607_reg_read(chip, PM8607_CHIP_ID); + if (ret < 0) { + dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); + goto out; + } + if ((ret & CHIP_ID_MASK) == CHIP_ID) + dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n", + ret); + else { + dev_err(chip->dev, "Failed to detect Marvell 88PM8607. " + "Chip ID: %02x\n", ret); + goto out; + } + chip->chip_id = ret; + + ret = pm8607_reg_read(chip, PM8607_BUCK3); + if (ret < 0) { + dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret); + goto out; + } + if (ret & PM8607_BUCK3_DOUBLE) + chip->buck3_double = 1; + + ret = pm8607_reg_read(chip, PM8607_MISC1); + if (ret < 0) { + dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret); + goto out; + } + if (pdata->i2c_port == PI2C_PORT) + ret |= PM8607_MISC1_PI2C; + else + ret &= ~PM8607_MISC1_PI2C; + ret = pm8607_reg_write(chip, PM8607_MISC1, ret); + if (ret < 0) { + dev_err(chip->dev, "Failed to write MISC1 register: %d\n", ret); + goto out; + } + + + count = ARRAY_SIZE(pm8607_devs); + for (i = 0; i < count; i++) { + ret = mfd_add_devices(chip->dev, i, &pm8607_devs[i], + 1, NULL, 0); + if (ret != 0) { + dev_err(chip->dev, "Failed to add subdevs\n"); + goto out; + } + } + + return 0; + +out: + i2c_set_clientdata(client, NULL); + kfree(chip); + return ret; +} + +static int __devexit pm8607_remove(struct i2c_client *client) +{ + struct pm8607_chip *chip = i2c_get_clientdata(client); + + mfd_remove_devices(chip->dev); + kfree(chip); + return 0; +} + +static struct i2c_driver pm8607_driver = { + .driver = { + .name = "88PM8607", + .owner = THIS_MODULE, + }, + .probe = pm8607_probe, + .remove = __devexit_p(pm8607_remove), + .id_table = pm8607_id_table, +}; + +static int __init pm8607_init(void) +{ + int ret; + ret = i2c_add_driver(&pm8607_driver); + if (ret != 0) + pr_err("Failed to register 88PM8607 I2C driver: %d\n", ret); + return ret; +} +subsys_initcall(pm8607_init); + +static void __exit pm8607_exit(void) +{ + i2c_del_driver(&pm8607_driver); +} +module_exit(pm8607_exit); + +MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM8607"); +MODULE_AUTHOR("Haojian Zhuang "); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index a296e717e86edbad24c9c34460ae65376c531af4..87829789243e87ded4653aa8b41da634060a670d 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -103,10 +103,10 @@ config MENELAUS cell phones and PDAs. config TWL4030_CORE - bool "Texas Instruments TWL4030/TPS659x0 Support" + bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support" depends on I2C=y && GENERIC_HARDIRQS help - Say yes here if you have TWL4030 family chip on your board. + Say yes here if you have TWL4030 / TWL6030 family chip on your board. This core driver provides register access and IRQ handling facilities, and registers devices for the various functions so that function-specific drivers can bind to them. @@ -174,6 +174,16 @@ config PMIC_DA903X individual components like LCD backlight, voltage regulators, LEDs and battery-charger under the corresponding menus. +config PMIC_ADP5520 + bool "Analog Devices ADP5520/01 MFD PMIC Core Support" + depends on I2C=y + help + Say yes here to add support for Analog Devices AD5520 and ADP5501, + Multifunction Power Management IC. This includes + the I2C driver and the core APIs _only_, you have to select + individual components like LCD backlight, LEDs, GPIOs and Kepad + under the corresponding menus. + config MFD_WM8400 tristate "Support Wolfson Microelectronics WM8400" select MFD_CORE @@ -185,12 +195,12 @@ config MFD_WM8400 the functionality of the device. config MFD_WM831X - tristate "Support Wolfson Microelectronics WM831x PMICs" + bool "Support Wolfson Microelectronics WM831x/2x PMICs" select MFD_CORE - depends on I2C + depends on I2C=y help - Support for the Wolfson Microelecronics WM831x PMICs. This - driver provides common support for accessing the device, + Support for the Wolfson Microelecronics WM831x and WM832x PMICs. + This driver provides common support for accessing the device, additional drivers must be enabled in order to use the functionality of the device. @@ -319,6 +329,25 @@ config EZX_PCAP This enables the PCAP ASIC present on EZX Phones. This is needed for MMC, TouchScreen, Sound, USB, etc.. +config MFD_88PM8607 + bool "Support Marvell 88PM8607" + depends on I2C=y + select MFD_CORE + help + This supports for Marvell 88PM8607 Power Management IC. This includes + the I2C driver and the core APIs _only_, you have to select + individual components like voltage regulators, RTC and + battery-charger under the corresponding menus. + +config AB4500_CORE + tristate "ST-Ericsson's AB4500 Mixed Signal Power management chip" + depends on SPI + help + Select this option to enable access to AB4500 power management + chip. This connects to U8500 on the SSP/SPI bus and exports + read/write functions for the devices to get access to this chip. + This chip embeds various other multimedia funtionalities as well. + endmenu menu "Multimedia Capabilities Port drivers" diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 11350c1d9301a72296a563daad3fc94e1f52b182..ca2f2c4ff05e70e2ac207516f4a215df3401136a 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -19,13 +19,14 @@ obj-$(CONFIG_MFD_WM8400) += wm8400-core.o wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o obj-$(CONFIG_MFD_WM831X) += wm831x.o wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o +wm8350-objs += wm8350-irq.o obj-$(CONFIG_MFD_WM8350) += wm8350.o obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o obj-$(CONFIG_TPS65010) += tps65010.o obj-$(CONFIG_MENELAUS) += menelaus.o -obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o +obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o @@ -52,3 +53,6 @@ obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o obj-$(CONFIG_AB3100_CORE) += ab3100-core.o obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o +obj-$(CONFIG_AB4500_CORE) += ab4500-core.o +obj-$(CONFIG_MFD_88PM8607) += 88pm8607.o +obj-$(CONFIG_PMIC_ADP5520) += adp5520.o \ No newline at end of file diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 613481028272f114c754a4a652987fce90452cae..fd42a80e7bf95df87cfa6d88301b418fae596a96 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -900,9 +900,6 @@ static int __init ab3100_probe(struct i2c_client *client, goto exit_no_testreg_client; } - strlcpy(ab3100->testreg_client->name, id->name, - sizeof(ab3100->testreg_client->name)); - err = ab3100_setup(ab3100); if (err) goto exit_no_setup; diff --git a/drivers/mfd/ab4500-core.c b/drivers/mfd/ab4500-core.c new file mode 100644 index 0000000000000000000000000000000000000000..1c44c19e073a10455e971143df832a9e3dd6a0dc --- /dev/null +++ b/drivers/mfd/ab4500-core.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2009 ST-Ericsson + * + * Author: Srinidhi KASAGAR + * + * 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. + * + * AB4500 is a companion power management chip used with U8500. + * On this platform, this is interfaced with SSP0 controller + * which is a ARM primecell pl022. + * + * At the moment the module just exports read/write features. + * Interrupt management to be added - TODO. + */ +#include +#include +#include +#include +#include +#include + +/* just required if probe fails, we need to + * unregister the device + */ +static struct spi_driver ab4500_driver; + +/* + * This funtion writes to any AB4500 registers using + * SPI protocol & before it writes it packs the data + * in the below 24 bit frame format + * + * *|------------------------------------| + * *| 23|22...18|17.......10|9|8|7......0| + * *| r/w bank adr data | + * * ------------------------------------ + * + * This function shouldn't be called from interrupt + * context + */ +int ab4500_write(struct ab4500 *ab4500, unsigned char block, + unsigned long addr, unsigned char data) +{ + struct spi_transfer xfer; + struct spi_message msg; + int err; + unsigned long spi_data = + block << 18 | addr << 10 | data; + + mutex_lock(&ab4500->lock); + ab4500->tx_buf[0] = spi_data; + ab4500->rx_buf[0] = 0; + + xfer.tx_buf = ab4500->tx_buf; + xfer.rx_buf = NULL; + xfer.len = sizeof(unsigned long); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + + err = spi_sync(ab4500->spi, &msg); + mutex_unlock(&ab4500->lock); + + return err; +} +EXPORT_SYMBOL(ab4500_write); + +int ab4500_read(struct ab4500 *ab4500, unsigned char block, + unsigned long addr) +{ + struct spi_transfer xfer; + struct spi_message msg; + unsigned long spi_data = + 1 << 23 | block << 18 | addr << 10; + + mutex_lock(&ab4500->lock); + ab4500->tx_buf[0] = spi_data; + ab4500->rx_buf[0] = 0; + + xfer.tx_buf = ab4500->tx_buf; + xfer.rx_buf = ab4500->rx_buf; + xfer.len = sizeof(unsigned long); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + + spi_sync(ab4500->spi, &msg); + mutex_unlock(&ab4500->lock); + + return ab4500->rx_buf[0]; +} +EXPORT_SYMBOL(ab4500_read); + +/* ref: ab3100 core */ +#define AB4500_DEVICE(devname, devid) \ +static struct platform_device ab4500_##devname##_device = { \ + .name = devid, \ + .id = -1, \ +} + +/* list of childern devices of ab4500 - all are + * not populated here - TODO + */ +AB4500_DEVICE(charger, "ab4500-charger"); +AB4500_DEVICE(audio, "ab4500-audio"); +AB4500_DEVICE(usb, "ab4500-usb"); +AB4500_DEVICE(tvout, "ab4500-tvout"); +AB4500_DEVICE(sim, "ab4500-sim"); +AB4500_DEVICE(gpadc, "ab4500-gpadc"); +AB4500_DEVICE(clkmgt, "ab4500-clkmgt"); +AB4500_DEVICE(misc, "ab4500-misc"); + +static struct platform_device *ab4500_platform_devs[] = { + &ab4500_charger_device, + &ab4500_audio_device, + &ab4500_usb_device, + &ab4500_tvout_device, + &ab4500_sim_device, + &ab4500_gpadc_device, + &ab4500_clkmgt_device, + &ab4500_misc_device, +}; + +static int __init ab4500_probe(struct spi_device *spi) +{ + struct ab4500 *ab4500; + unsigned char revision; + int err = 0; + int i; + + ab4500 = kzalloc(sizeof *ab4500, GFP_KERNEL); + if (!ab4500) { + dev_err(&spi->dev, "could not allocate AB4500\n"); + err = -ENOMEM; + goto not_detect; + } + + ab4500->spi = spi; + spi_set_drvdata(spi, ab4500); + + mutex_init(&ab4500->lock); + + /* read the revision register */ + revision = ab4500_read(ab4500, AB4500_MISC, AB4500_REV_REG); + + /* revision id 0x0 is for early drop, 0x10 is for cut1.0 */ + if (revision == 0x0 || revision == 0x10) + dev_info(&spi->dev, "Detected chip: %s, revision = %x\n", + ab4500_driver.driver.name, revision); + else { + dev_err(&spi->dev, "unknown chip: 0x%x\n", revision); + goto not_detect; + } + + for (i = 0; i < ARRAY_SIZE(ab4500_platform_devs); i++) { + ab4500_platform_devs[i]->dev.parent = + &spi->dev; + platform_set_drvdata(ab4500_platform_devs[i], ab4500); + } + + /* register the ab4500 platform devices */ + platform_add_devices(ab4500_platform_devs, + ARRAY_SIZE(ab4500_platform_devs)); + + return err; + + not_detect: + spi_unregister_driver(&ab4500_driver); + kfree(ab4500); + return err; +} + +static int __devexit ab4500_remove(struct spi_device *spi) +{ + struct ab4500 *ab4500 = + spi_get_drvdata(spi); + + kfree(ab4500); + + return 0; +} + +static struct spi_driver ab4500_driver = { + .driver = { + .name = "ab4500", + .owner = THIS_MODULE, + }, + .probe = ab4500_probe, + .remove = __devexit_p(ab4500_remove) +}; + +static int __devinit ab4500_init(void) +{ + return spi_register_driver(&ab4500_driver); +} + +static void __exit ab4500_exit(void) +{ + spi_unregister_driver(&ab4500_driver); +} + +subsys_initcall(ab4500_init); +module_exit(ab4500_exit); + +MODULE_AUTHOR("Srinidhi KASAGAR + * + * Copyright (C) 2006-2008 Marvell International Ltd. + * Eric Miao + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct adp5520_chip { + struct i2c_client *client; + struct device *dev; + struct mutex lock; + struct blocking_notifier_head notifier_list; + int irq; + unsigned long id; +}; + +static int __adp5520_read(struct i2c_client *client, + int reg, uint8_t *val) +{ + int ret; + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret < 0) { + dev_err(&client->dev, "failed reading at 0x%02x\n", reg); + return ret; + } + + *val = (uint8_t)ret; + return 0; +} + +static int __adp5520_write(struct i2c_client *client, + int reg, uint8_t val) +{ + int ret; + + ret = i2c_smbus_write_byte_data(client, reg, val); + if (ret < 0) { + dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n", + val, reg); + return ret; + } + return 0; +} + +static int __adp5520_ack_bits(struct i2c_client *client, int reg, + uint8_t bit_mask) +{ + struct adp5520_chip *chip = i2c_get_clientdata(client); + uint8_t reg_val; + int ret; + + mutex_lock(&chip->lock); + + ret = __adp5520_read(client, reg, ®_val); + + if (!ret) { + reg_val |= bit_mask; + ret = __adp5520_write(client, reg, reg_val); + } + + mutex_unlock(&chip->lock); + return ret; +} + +int adp5520_write(struct device *dev, int reg, uint8_t val) +{ + return __adp5520_write(to_i2c_client(dev), reg, val); +} +EXPORT_SYMBOL_GPL(adp5520_write); + +int adp5520_read(struct device *dev, int reg, uint8_t *val) +{ + return __adp5520_read(to_i2c_client(dev), reg, val); +} +EXPORT_SYMBOL_GPL(adp5520_read); + +int adp5520_set_bits(struct device *dev, int reg, uint8_t bit_mask) +{ + struct adp5520_chip *chip = dev_get_drvdata(dev); + uint8_t reg_val; + int ret; + + mutex_lock(&chip->lock); + + ret = __adp5520_read(chip->client, reg, ®_val); + + if (!ret && ((reg_val & bit_mask) == 0)) { + reg_val |= bit_mask; + ret = __adp5520_write(chip->client, reg, reg_val); + } + + mutex_unlock(&chip->lock); + return ret; +} +EXPORT_SYMBOL_GPL(adp5520_set_bits); + +int adp5520_clr_bits(struct device *dev, int reg, uint8_t bit_mask) +{ + struct adp5520_chip *chip = dev_get_drvdata(dev); + uint8_t reg_val; + int ret; + + mutex_lock(&chip->lock); + + ret = __adp5520_read(chip->client, reg, ®_val); + + if (!ret && (reg_val & bit_mask)) { + reg_val &= ~bit_mask; + ret = __adp5520_write(chip->client, reg, reg_val); + } + + mutex_unlock(&chip->lock); + return ret; +} +EXPORT_SYMBOL_GPL(adp5520_clr_bits); + +int adp5520_register_notifier(struct device *dev, struct notifier_block *nb, + unsigned int events) +{ + struct adp5520_chip *chip = dev_get_drvdata(dev); + + if (chip->irq) { + adp5520_set_bits(chip->dev, ADP5520_INTERRUPT_ENABLE, + events & (ADP5520_KP_IEN | ADP5520_KR_IEN | + ADP5520_OVP_IEN | ADP5520_CMPR_IEN)); + + return blocking_notifier_chain_register(&chip->notifier_list, + nb); + } + + return -ENODEV; +} +EXPORT_SYMBOL_GPL(adp5520_register_notifier); + +int adp5520_unregister_notifier(struct device *dev, struct notifier_block *nb, + unsigned int events) +{ + struct adp5520_chip *chip = dev_get_drvdata(dev); + + adp5520_clr_bits(chip->dev, ADP5520_INTERRUPT_ENABLE, + events & (ADP5520_KP_IEN | ADP5520_KR_IEN | + ADP5520_OVP_IEN | ADP5520_CMPR_IEN)); + + return blocking_notifier_chain_unregister(&chip->notifier_list, nb); +} +EXPORT_SYMBOL_GPL(adp5520_unregister_notifier); + +static irqreturn_t adp5520_irq_thread(int irq, void *data) +{ + struct adp5520_chip *chip = data; + unsigned int events; + uint8_t reg_val; + int ret; + + ret = __adp5520_read(chip->client, ADP5520_MODE_STATUS, ®_val); + if (ret) + goto out; + + events = reg_val & (ADP5520_OVP_INT | ADP5520_CMPR_INT | + ADP5520_GPI_INT | ADP5520_KR_INT | ADP5520_KP_INT); + + blocking_notifier_call_chain(&chip->notifier_list, events, NULL); + /* ACK, Sticky bits are W1C */ + __adp5520_ack_bits(chip->client, ADP5520_MODE_STATUS, events); + +out: + return IRQ_HANDLED; +} + +static int __remove_subdev(struct device *dev, void *unused) +{ + platform_device_unregister(to_platform_device(dev)); + return 0; +} + +static int adp5520_remove_subdevs(struct adp5520_chip *chip) +{ + return device_for_each_child(chip->dev, NULL, __remove_subdev); +} + +static int __devinit adp5520_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adp5520_platform_data *pdata = client->dev.platform_data; + struct platform_device *pdev; + struct adp5520_chip *chip; + int ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, "SMBUS Word Data not Supported\n"); + return -EIO; + } + + if (pdata == NULL) { + dev_err(&client->dev, "missing platform data\n"); + return -ENODEV; + } + + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + i2c_set_clientdata(client, chip); + chip->client = client; + + chip->dev = &client->dev; + chip->irq = client->irq; + chip->id = id->driver_data; + mutex_init(&chip->lock); + + if (chip->irq) { + BLOCKING_INIT_NOTIFIER_HEAD(&chip->notifier_list); + + ret = request_threaded_irq(chip->irq, NULL, adp5520_irq_thread, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "adp5520", chip); + if (ret) { + dev_err(&client->dev, "failed to request irq %d\n", + chip->irq); + goto out_free_chip; + } + } + + ret = adp5520_write(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); + if (ret) { + dev_err(&client->dev, "failed to write\n"); + goto out_free_irq; + } + + if (pdata->keys) { + pdev = platform_device_register_data(chip->dev, "adp5520-keys", + chip->id, pdata->keys, sizeof(*pdata->keys)); + if (IS_ERR(pdev)) { + ret = PTR_ERR(pdev); + goto out_remove_subdevs; + } + } + + if (pdata->gpio) { + pdev = platform_device_register_data(chip->dev, "adp5520-gpio", + chip->id, pdata->gpio, sizeof(*pdata->gpio)); + if (IS_ERR(pdev)) { + ret = PTR_ERR(pdev); + goto out_remove_subdevs; + } + } + + if (pdata->leds) { + pdev = platform_device_register_data(chip->dev, "adp5520-led", + chip->id, pdata->leds, sizeof(*pdata->leds)); + if (IS_ERR(pdev)) { + ret = PTR_ERR(pdev); + goto out_remove_subdevs; + } + } + + if (pdata->backlight) { + pdev = platform_device_register_data(chip->dev, + "adp5520-backlight", + chip->id, + pdata->backlight, + sizeof(*pdata->backlight)); + if (IS_ERR(pdev)) { + ret = PTR_ERR(pdev); + goto out_remove_subdevs; + } + } + + return 0; + +out_remove_subdevs: + adp5520_remove_subdevs(chip); + +out_free_irq: + if (chip->irq) + free_irq(chip->irq, chip); + +out_free_chip: + i2c_set_clientdata(client, NULL); + kfree(chip); + + return ret; +} + +static int __devexit adp5520_remove(struct i2c_client *client) +{ + struct adp5520_chip *chip = dev_get_drvdata(&client->dev); + + if (chip->irq) + free_irq(chip->irq, chip); + + adp5520_remove_subdevs(chip); + adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0); + i2c_set_clientdata(client, NULL); + kfree(chip); + return 0; +} + +#ifdef CONFIG_PM +static int adp5520_suspend(struct i2c_client *client, + pm_message_t state) +{ + struct adp5520_chip *chip = dev_get_drvdata(&client->dev); + + adp5520_clr_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); + return 0; +} + +static int adp5520_resume(struct i2c_client *client) +{ + struct adp5520_chip *chip = dev_get_drvdata(&client->dev); + + adp5520_set_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); + return 0; +} +#else +#define adp5520_suspend NULL +#define adp5520_resume NULL +#endif + +static const struct i2c_device_id adp5520_id[] = { + { "pmic-adp5520", ID_ADP5520 }, + { "pmic-adp5501", ID_ADP5501 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adp5520_id); + +static struct i2c_driver adp5520_driver = { + .driver = { + .name = "adp5520", + .owner = THIS_MODULE, + }, + .probe = adp5520_probe, + .remove = __devexit_p(adp5520_remove), + .suspend = adp5520_suspend, + .resume = adp5520_resume, + .id_table = adp5520_id, +}; + +static int __init adp5520_init(void) +{ + return i2c_add_driver(&adp5520_driver); +} +module_init(adp5520_init); + +static void __exit adp5520_exit(void) +{ + i2c_del_driver(&adp5520_driver); +} +module_exit(adp5520_exit); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("ADP5520(01) PMIC-MFD Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 63a2a6632106c3ad50a6ecbbb58e6ba80b11ba35..e22128c3e9a8a426825337eb5f2aadb5945f6ad2 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -908,7 +908,7 @@ static int __init asic3_probe(struct platform_device *pdev) return ret; } -static int asic3_remove(struct platform_device *pdev) +static int __devexit asic3_remove(struct platform_device *pdev) { int ret; struct asic3 *asic = platform_get_drvdata(pdev); diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index 8762889179763eb2a019c7867a72b1cbecd9dbad..df405af968fa2f1f1237b1b45a828249ecde65a1 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c @@ -387,7 +387,6 @@ static int __devinit pcap_add_subdev(struct pcap_chip *pcap, pdev = platform_device_alloc(subdev->name, subdev->id); pdev->dev.parent = &pcap->spi->dev; pdev->dev.platform_data = subdev->platform_data; - platform_set_drvdata(pdev, pcap); return platform_device_add(pdev); } diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c index e354d2912ef13dc11eb059959faec1ebfd5a3430..a1ade2324ea903bccfab8a35f75fecaa9428f59e 100644 --- a/drivers/mfd/mc13783-core.c +++ b/drivers/mfd/mc13783-core.c @@ -1,286 +1,549 @@ /* - * Copyright 2009 Pengutronix, Sascha Hauer - * - * This code is in parts based on wm8350-core.c and pcf50633-core.c - * - * Initial development of this code was funded by - * Phytec Messtechnik GmbH, http://www.phytec.de + * Copyright 2009 Pengutronix + * Uwe Kleine-Koenig * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * loosely based on an earlier driver that has + * Copyright 2009 Pengutronix, Sascha Hauer * - * You 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 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 MC13783_IRQSTAT0 0 +#define MC13783_IRQSTAT0_ADCDONEI (1 << 0) +#define MC13783_IRQSTAT0_ADCBISDONEI (1 << 1) +#define MC13783_IRQSTAT0_TSI (1 << 2) +#define MC13783_IRQSTAT0_WHIGHI (1 << 3) +#define MC13783_IRQSTAT0_WLOWI (1 << 4) +#define MC13783_IRQSTAT0_CHGDETI (1 << 6) +#define MC13783_IRQSTAT0_CHGOVI (1 << 7) +#define MC13783_IRQSTAT0_CHGREVI (1 << 8) +#define MC13783_IRQSTAT0_CHGSHORTI (1 << 9) +#define MC13783_IRQSTAT0_CCCVI (1 << 10) +#define MC13783_IRQSTAT0_CHGCURRI (1 << 11) +#define MC13783_IRQSTAT0_BPONI (1 << 12) +#define MC13783_IRQSTAT0_LOBATLI (1 << 13) +#define MC13783_IRQSTAT0_LOBATHI (1 << 14) +#define MC13783_IRQSTAT0_UDPI (1 << 15) +#define MC13783_IRQSTAT0_USBI (1 << 16) +#define MC13783_IRQSTAT0_IDI (1 << 19) +#define MC13783_IRQSTAT0_SE1I (1 << 21) +#define MC13783_IRQSTAT0_CKDETI (1 << 22) +#define MC13783_IRQSTAT0_UDMI (1 << 23) + +#define MC13783_IRQMASK0 1 +#define MC13783_IRQMASK0_ADCDONEM MC13783_IRQSTAT0_ADCDONEI +#define MC13783_IRQMASK0_ADCBISDONEM MC13783_IRQSTAT0_ADCBISDONEI +#define MC13783_IRQMASK0_TSM MC13783_IRQSTAT0_TSI +#define MC13783_IRQMASK0_WHIGHM MC13783_IRQSTAT0_WHIGHI +#define MC13783_IRQMASK0_WLOWM MC13783_IRQSTAT0_WLOWI +#define MC13783_IRQMASK0_CHGDETM MC13783_IRQSTAT0_CHGDETI +#define MC13783_IRQMASK0_CHGOVM MC13783_IRQSTAT0_CHGOVI +#define MC13783_IRQMASK0_CHGREVM MC13783_IRQSTAT0_CHGREVI +#define MC13783_IRQMASK0_CHGSHORTM MC13783_IRQSTAT0_CHGSHORTI +#define MC13783_IRQMASK0_CCCVM MC13783_IRQSTAT0_CCCVI +#define MC13783_IRQMASK0_CHGCURRM MC13783_IRQSTAT0_CHGCURRI +#define MC13783_IRQMASK0_BPONM MC13783_IRQSTAT0_BPONI +#define MC13783_IRQMASK0_LOBATLM MC13783_IRQSTAT0_LOBATLI +#define MC13783_IRQMASK0_LOBATHM MC13783_IRQSTAT0_LOBATHI +#define MC13783_IRQMASK0_UDPM MC13783_IRQSTAT0_UDPI +#define MC13783_IRQMASK0_USBM MC13783_IRQSTAT0_USBI +#define MC13783_IRQMASK0_IDM MC13783_IRQSTAT0_IDI +#define MC13783_IRQMASK0_SE1M MC13783_IRQSTAT0_SE1I +#define MC13783_IRQMASK0_CKDETM MC13783_IRQSTAT0_CKDETI +#define MC13783_IRQMASK0_UDMM MC13783_IRQSTAT0_UDMI + +#define MC13783_IRQSTAT1 3 +#define MC13783_IRQSTAT1_1HZI (1 << 0) +#define MC13783_IRQSTAT1_TODAI (1 << 1) +#define MC13783_IRQSTAT1_ONOFD1I (1 << 3) +#define MC13783_IRQSTAT1_ONOFD2I (1 << 4) +#define MC13783_IRQSTAT1_ONOFD3I (1 << 5) +#define MC13783_IRQSTAT1_SYSRSTI (1 << 6) +#define MC13783_IRQSTAT1_RTCRSTI (1 << 7) +#define MC13783_IRQSTAT1_PCI (1 << 8) +#define MC13783_IRQSTAT1_WARMI (1 << 9) +#define MC13783_IRQSTAT1_MEMHLDI (1 << 10) +#define MC13783_IRQSTAT1_PWRRDYI (1 << 11) +#define MC13783_IRQSTAT1_THWARNLI (1 << 12) +#define MC13783_IRQSTAT1_THWARNHI (1 << 13) +#define MC13783_IRQSTAT1_CLKI (1 << 14) +#define MC13783_IRQSTAT1_SEMAFI (1 << 15) +#define MC13783_IRQSTAT1_MC2BI (1 << 17) +#define MC13783_IRQSTAT1_HSDETI (1 << 18) +#define MC13783_IRQSTAT1_HSLI (1 << 19) +#define MC13783_IRQSTAT1_ALSPTHI (1 << 20) +#define MC13783_IRQSTAT1_AHSSHORTI (1 << 21) + +#define MC13783_IRQMASK1 4 +#define MC13783_IRQMASK1_1HZM MC13783_IRQSTAT1_1HZI +#define MC13783_IRQMASK1_TODAM MC13783_IRQSTAT1_TODAI +#define MC13783_IRQMASK1_ONOFD1M MC13783_IRQSTAT1_ONOFD1I +#define MC13783_IRQMASK1_ONOFD2M MC13783_IRQSTAT1_ONOFD2I +#define MC13783_IRQMASK1_ONOFD3M MC13783_IRQSTAT1_ONOFD3I +#define MC13783_IRQMASK1_SYSRSTM MC13783_IRQSTAT1_SYSRSTI +#define MC13783_IRQMASK1_RTCRSTM MC13783_IRQSTAT1_RTCRSTI +#define MC13783_IRQMASK1_PCM MC13783_IRQSTAT1_PCI +#define MC13783_IRQMASK1_WARMM MC13783_IRQSTAT1_WARMI +#define MC13783_IRQMASK1_MEMHLDM MC13783_IRQSTAT1_MEMHLDI +#define MC13783_IRQMASK1_PWRRDYM MC13783_IRQSTAT1_PWRRDYI +#define MC13783_IRQMASK1_THWARNLM MC13783_IRQSTAT1_THWARNLI +#define MC13783_IRQMASK1_THWARNHM MC13783_IRQSTAT1_THWARNHI +#define MC13783_IRQMASK1_CLKM MC13783_IRQSTAT1_CLKI +#define MC13783_IRQMASK1_SEMAFM MC13783_IRQSTAT1_SEMAFI +#define MC13783_IRQMASK1_MC2BM MC13783_IRQSTAT1_MC2BI +#define MC13783_IRQMASK1_HSDETM MC13783_IRQSTAT1_HSDETI +#define MC13783_IRQMASK1_HSLM MC13783_IRQSTAT1_HSLI +#define MC13783_IRQMASK1_ALSPTHM MC13783_IRQSTAT1_ALSPTHI +#define MC13783_IRQMASK1_AHSSHORTM MC13783_IRQSTAT1_AHSSHORTI + +#define MC13783_ADC1 44 +#define MC13783_ADC1_ADEN (1 << 0) +#define MC13783_ADC1_RAND (1 << 1) +#define MC13783_ADC1_ADSEL (1 << 3) +#define MC13783_ADC1_ASC (1 << 20) +#define MC13783_ADC1_ADTRIGIGN (1 << 21) + +#define MC13783_NUMREGS 0x3f + +void mc13783_lock(struct mc13783 *mc13783) +{ + if (!mutex_trylock(&mc13783->lock)) { + dev_dbg(&mc13783->spidev->dev, "wait for %s from %pf\n", + __func__, __builtin_return_address(0)); + + mutex_lock(&mc13783->lock); + } + dev_dbg(&mc13783->spidev->dev, "%s from %pf\n", + __func__, __builtin_return_address(0)); +} +EXPORT_SYMBOL(mc13783_lock); -#define MC13783_MAX_REG_NUM 0x3f -#define MC13783_FRAME_MASK 0x00ffffff -#define MC13783_MAX_REG_NUM 0x3f -#define MC13783_REG_NUM_SHIFT 0x19 -#define MC13783_WRITE_BIT_SHIFT 31 +void mc13783_unlock(struct mc13783 *mc13783) +{ + dev_dbg(&mc13783->spidev->dev, "%s from %pf\n", + __func__, __builtin_return_address(0)); + mutex_unlock(&mc13783->lock); +} +EXPORT_SYMBOL(mc13783_unlock); -static inline int spi_rw(struct spi_device *spi, u8 * buf, size_t len) +#define MC13783_REGOFFSET_SHIFT 25 +int mc13783_reg_read(struct mc13783 *mc13783, unsigned int offset, u32 *val) { - struct spi_transfer t = { - .tx_buf = (const void *)buf, - .rx_buf = buf, - .len = len, - .cs_change = 0, - .delay_usecs = 0, - }; + struct spi_transfer t; struct spi_message m; + int ret; + + BUG_ON(!mutex_is_locked(&mc13783->lock)); + + if (offset > MC13783_NUMREGS) + return -EINVAL; + + *val = offset << MC13783_REGOFFSET_SHIFT; + + memset(&t, 0, sizeof(t)); + + t.tx_buf = val; + t.rx_buf = val; + t.len = sizeof(u32); spi_message_init(&m); spi_message_add_tail(&t, &m); - if (spi_sync(spi, &m) != 0 || m.status != 0) - return -EINVAL; - return len - m.actual_length; -} -static int mc13783_read(struct mc13783 *mc13783, int reg_num, u32 *reg_val) -{ - unsigned int frame = 0; - int ret = 0; + ret = spi_sync(mc13783->spidev, &m); - if (reg_num > MC13783_MAX_REG_NUM) - return -EINVAL; + /* error in message.status implies error return from spi_sync */ + BUG_ON(!ret && m.status); - frame |= reg_num << MC13783_REG_NUM_SHIFT; + if (ret) + return ret; - ret = spi_rw(mc13783->spi_device, (u8 *)&frame, 4); + *val &= 0xffffff; - *reg_val = frame & MC13783_FRAME_MASK; + dev_vdbg(&mc13783->spidev->dev, "[0x%02x] -> 0x%06x\n", offset, *val); - return ret; + return 0; } +EXPORT_SYMBOL(mc13783_reg_read); -static int mc13783_write(struct mc13783 *mc13783, int reg_num, u32 reg_val) +int mc13783_reg_write(struct mc13783 *mc13783, unsigned int offset, u32 val) { - unsigned int frame = 0; + u32 buf; + struct spi_transfer t; + struct spi_message m; + int ret; + + BUG_ON(!mutex_is_locked(&mc13783->lock)); - if (reg_num > MC13783_MAX_REG_NUM) + dev_vdbg(&mc13783->spidev->dev, "[0x%02x] <- 0x%06x\n", offset, val); + + if (offset > MC13783_NUMREGS || val > 0xffffff) return -EINVAL; - frame |= (1 << MC13783_WRITE_BIT_SHIFT); - frame |= reg_num << MC13783_REG_NUM_SHIFT; - frame |= reg_val & MC13783_FRAME_MASK; + buf = 1 << 31 | offset << MC13783_REGOFFSET_SHIFT | val; + + memset(&t, 0, sizeof(t)); - return spi_rw(mc13783->spi_device, (u8 *)&frame, 4); + t.tx_buf = &buf; + t.rx_buf = &buf; + t.len = sizeof(u32); + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + + ret = spi_sync(mc13783->spidev, &m); + + BUG_ON(!ret && m.status); + + if (ret) + return ret; + + return 0; } +EXPORT_SYMBOL(mc13783_reg_write); -int mc13783_reg_read(struct mc13783 *mc13783, int reg_num, u32 *reg_val) +int mc13783_reg_rmw(struct mc13783 *mc13783, unsigned int offset, + u32 mask, u32 val) { int ret; + u32 valread; - mutex_lock(&mc13783->io_lock); - ret = mc13783_read(mc13783, reg_num, reg_val); - mutex_unlock(&mc13783->io_lock); + BUG_ON(val & ~mask); - return ret; + ret = mc13783_reg_read(mc13783, offset, &valread); + if (ret) + return ret; + + valread = (valread & ~mask) | val; + + return mc13783_reg_write(mc13783, offset, valread); } -EXPORT_SYMBOL_GPL(mc13783_reg_read); +EXPORT_SYMBOL(mc13783_reg_rmw); -int mc13783_reg_write(struct mc13783 *mc13783, int reg_num, u32 reg_val) +int mc13783_mask(struct mc13783 *mc13783, int irq) { int ret; + unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1; + u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); + u32 mask; - mutex_lock(&mc13783->io_lock); - ret = mc13783_write(mc13783, reg_num, reg_val); - mutex_unlock(&mc13783->io_lock); + if (irq < 0 || irq >= MC13783_NUM_IRQ) + return -EINVAL; - return ret; + ret = mc13783_reg_read(mc13783, offmask, &mask); + if (ret) + return ret; + + if (mask & irqbit) + /* already masked */ + return 0; + + return mc13783_reg_write(mc13783, offmask, mask | irqbit); } -EXPORT_SYMBOL_GPL(mc13783_reg_write); +EXPORT_SYMBOL(mc13783_mask); -/** - * mc13783_set_bits - Bitmask write - * - * @mc13783: Pointer to mc13783 control structure - * @reg: Register to access - * @mask: Mask of bits to change - * @val: Value to set for masked bits - */ -int mc13783_set_bits(struct mc13783 *mc13783, int reg, u32 mask, u32 val) +int mc13783_unmask(struct mc13783 *mc13783, int irq) { - u32 tmp; int ret; + unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1; + u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); + u32 mask; - mutex_lock(&mc13783->io_lock); + if (irq < 0 || irq >= MC13783_NUM_IRQ) + return -EINVAL; - ret = mc13783_read(mc13783, reg, &tmp); - tmp = (tmp & ~mask) | val; - if (ret == 0) - ret = mc13783_write(mc13783, reg, tmp); + ret = mc13783_reg_read(mc13783, offmask, &mask); + if (ret) + return ret; - mutex_unlock(&mc13783->io_lock); + if (!(mask & irqbit)) + /* already unmasked */ + return 0; - return ret; + return mc13783_reg_write(mc13783, offmask, mask & ~irqbit); } -EXPORT_SYMBOL_GPL(mc13783_set_bits); +EXPORT_SYMBOL(mc13783_unmask); -int mc13783_register_irq(struct mc13783 *mc13783, int irq, - void (*handler) (int, void *), void *data) +int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq, + irq_handler_t handler, const char *name, void *dev) { - if (irq < 0 || irq > MC13783_NUM_IRQ || !handler) + BUG_ON(!mutex_is_locked(&mc13783->lock)); + BUG_ON(!handler); + + if (irq < 0 || irq >= MC13783_NUM_IRQ) return -EINVAL; - if (WARN_ON(mc13783->irq_handler[irq].handler)) + if (mc13783->irqhandler[irq]) return -EBUSY; - mutex_lock(&mc13783->io_lock); - mc13783->irq_handler[irq].handler = handler; - mc13783->irq_handler[irq].data = data; - mutex_unlock(&mc13783->io_lock); + mc13783->irqhandler[irq] = handler; + mc13783->irqdata[irq] = dev; return 0; } -EXPORT_SYMBOL_GPL(mc13783_register_irq); +EXPORT_SYMBOL(mc13783_irq_request_nounmask); -int mc13783_free_irq(struct mc13783 *mc13783, int irq) +int mc13783_irq_request(struct mc13783 *mc13783, int irq, + irq_handler_t handler, const char *name, void *dev) { - if (irq < 0 || irq > MC13783_NUM_IRQ) + int ret; + + ret = mc13783_irq_request_nounmask(mc13783, irq, handler, name, dev); + if (ret) + return ret; + + ret = mc13783_unmask(mc13783, irq); + if (ret) { + mc13783->irqhandler[irq] = NULL; + mc13783->irqdata[irq] = NULL; + return ret; + } + + return 0; +} +EXPORT_SYMBOL(mc13783_irq_request); + +int mc13783_irq_free(struct mc13783 *mc13783, int irq, void *dev) +{ + int ret; + BUG_ON(!mutex_is_locked(&mc13783->lock)); + + if (irq < 0 || irq >= MC13783_NUM_IRQ || !mc13783->irqhandler[irq] || + mc13783->irqdata[irq] != dev) return -EINVAL; - mutex_lock(&mc13783->io_lock); - mc13783->irq_handler[irq].handler = NULL; - mutex_unlock(&mc13783->io_lock); + ret = mc13783_mask(mc13783, irq); + if (ret) + return ret; + + mc13783->irqhandler[irq] = NULL; + mc13783->irqdata[irq] = NULL; return 0; } -EXPORT_SYMBOL_GPL(mc13783_free_irq); +EXPORT_SYMBOL(mc13783_irq_free); -static void mc13783_irq_work(struct work_struct *work) +static inline irqreturn_t mc13783_irqhandler(struct mc13783 *mc13783, int irq) { - struct mc13783 *mc13783 = container_of(work, struct mc13783, work); - int i; - unsigned int adc_sts; - - /* check if the adc has finished any completion */ - mc13783_reg_read(mc13783, MC13783_REG_INTERRUPT_STATUS_0, &adc_sts); - mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_STATUS_0, - adc_sts & MC13783_INT_STAT_ADCDONEI); - - if (adc_sts & MC13783_INT_STAT_ADCDONEI) - complete_all(&mc13783->adc_done); - - for (i = 0; i < MC13783_NUM_IRQ; i++) - if (mc13783->irq_handler[i].handler) - mc13783->irq_handler[i].handler(i, - mc13783->irq_handler[i].data); - enable_irq(mc13783->irq); + return mc13783->irqhandler[irq](irq, mc13783->irqdata[irq]); } -static irqreturn_t mc13783_interrupt(int irq, void *dev_id) +int mc13783_ackirq(struct mc13783 *mc13783, int irq) { - struct mc13783 *mc13783 = dev_id; + unsigned int offstat = irq < 24 ? MC13783_IRQSTAT0 : MC13783_IRQSTAT1; + unsigned int val = 1 << (irq < 24 ? irq : irq - 24); - disable_irq_nosync(irq); + BUG_ON(irq < 0 || irq >= MC13783_NUM_IRQ); - schedule_work(&mc13783->work); - return IRQ_HANDLED; + return mc13783_reg_write(mc13783, offstat, val); } +EXPORT_SYMBOL(mc13783_ackirq); -/* set adc to ts interrupt mode, which generates touchscreen wakeup interrupt */ -static inline void mc13783_adc_set_ts_irq_mode(struct mc13783 *mc13783) +/* + * returns: number of handled irqs or negative error + * locking: holds mc13783->lock + */ +static int mc13783_irq_handle(struct mc13783 *mc13783, + unsigned int offstat, unsigned int offmask, int baseirq) { - unsigned int reg_adc0, reg_adc1; + u32 stat, mask; + int ret = mc13783_reg_read(mc13783, offstat, &stat); + int num_handled = 0; + + if (ret) + return ret; + + ret = mc13783_reg_read(mc13783, offmask, &mask); + if (ret) + return ret; + + while (stat & ~mask) { + int irq = __ffs(stat & ~mask); + + stat &= ~(1 << irq); + + if (likely(mc13783->irqhandler[baseirq + irq])) { + irqreturn_t handled; - reg_adc0 = MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE - | MC13783_ADC0_TSMOD0; - reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN; + handled = mc13783_irqhandler(mc13783, baseirq + irq); + if (handled == IRQ_HANDLED) + num_handled++; + } else { + dev_err(&mc13783->spidev->dev, + "BUG: irq %u but no handler\n", + baseirq + irq); - mc13783_reg_write(mc13783, MC13783_REG_ADC_0, reg_adc0); - mc13783_reg_write(mc13783, MC13783_REG_ADC_1, reg_adc1); + mask |= 1 << irq; + + ret = mc13783_reg_write(mc13783, offmask, mask); + } + } + + return num_handled; } +static irqreturn_t mc13783_irq_thread(int irq, void *data) +{ + struct mc13783 *mc13783 = data; + irqreturn_t ret; + int handled = 0; + + mc13783_lock(mc13783); + + ret = mc13783_irq_handle(mc13783, MC13783_IRQSTAT0, + MC13783_IRQMASK0, MC13783_IRQ_ADCDONE); + if (ret > 0) + handled = 1; + + ret = mc13783_irq_handle(mc13783, MC13783_IRQSTAT1, + MC13783_IRQMASK1, MC13783_IRQ_1HZ); + if (ret > 0) + handled = 1; + + mc13783_unlock(mc13783); + + return IRQ_RETVAL(handled); +} + +#define MC13783_ADC1_CHAN0_SHIFT 5 +#define MC13783_ADC1_CHAN1_SHIFT 8 + +struct mc13783_adcdone_data { + struct mc13783 *mc13783; + struct completion done; +}; + +static irqreturn_t mc13783_handler_adcdone(int irq, void *data) +{ + struct mc13783_adcdone_data *adcdone_data = data; + + mc13783_ackirq(adcdone_data->mc13783, irq); + + complete_all(&adcdone_data->done); + + return IRQ_HANDLED; +} + +#define MC13783_ADC_WORKING (1 << 16) + int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, unsigned int channel, unsigned int *sample) { - unsigned int reg_adc0, reg_adc1; - int i; + u32 adc0, adc1, old_adc0; + int i, ret; + struct mc13783_adcdone_data adcdone_data = { + .mc13783 = mc13783, + }; + init_completion(&adcdone_data.done); + + dev_dbg(&mc13783->spidev->dev, "%s\n", __func__); + + mc13783_lock(mc13783); + + if (mc13783->flags & MC13783_ADC_WORKING) { + ret = -EBUSY; + goto out; + } + + mc13783->flags |= MC13783_ADC_WORKING; - mutex_lock(&mc13783->adc_conv_lock); + mc13783_reg_read(mc13783, MC13783_ADC0, &old_adc0); - /* set up auto incrementing anyway to make quick read */ - reg_adc0 = MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2; - /* enable the adc, ignore external triggering and set ASC to trigger - * conversion */ - reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN - | MC13783_ADC1_ASC; + adc0 = MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2; + adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN | MC13783_ADC1_ASC; - /* setup channel number */ if (channel > 7) - reg_adc1 |= MC13783_ADC1_ADSEL; + adc1 |= MC13783_ADC1_ADSEL; switch (mode) { case MC13783_ADC_MODE_TS: - /* enables touch screen reference mode and set touchscreen mode - * to position mode */ - reg_adc0 |= MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE - | MC13783_ADC0_TSMOD0 | MC13783_ADC0_TSMOD1; - reg_adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; + adc0 |= MC13783_ADC0_ADREFEN | MC13783_ADC0_TSMOD0 | + MC13783_ADC0_TSMOD1; + adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; break; + case MC13783_ADC_MODE_SINGLE_CHAN: - reg_adc1 |= (channel & 0x7) << MC13783_ADC1_CHAN0_SHIFT; - reg_adc1 |= MC13783_ADC1_RAND; + adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK; + adc1 |= (channel & 0x7) << MC13783_ADC1_CHAN0_SHIFT; + adc1 |= MC13783_ADC1_RAND; break; + case MC13783_ADC_MODE_MULT_CHAN: - reg_adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; + adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK; + adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; break; + default: + mc13783_unlock(mc13783); return -EINVAL; } - mc13783_reg_write(mc13783, MC13783_REG_ADC_0, reg_adc0); - mc13783_reg_write(mc13783, MC13783_REG_ADC_1, reg_adc1); + dev_dbg(&mc13783->spidev->dev, "%s: request irq\n", __func__); + mc13783_irq_request(mc13783, MC13783_IRQ_ADCDONE, + mc13783_handler_adcdone, __func__, &adcdone_data); + mc13783_ackirq(mc13783, MC13783_IRQ_ADCDONE); - wait_for_completion_interruptible(&mc13783->adc_done); + mc13783_reg_write(mc13783, MC13783_REG_ADC_0, adc0); + mc13783_reg_write(mc13783, MC13783_REG_ADC_1, adc1); - for (i = 0; i < 4; i++) - mc13783_reg_read(mc13783, MC13783_REG_ADC_2, &sample[i]); + mc13783_unlock(mc13783); - if (mc13783->ts_active) - mc13783_adc_set_ts_irq_mode(mc13783); + ret = wait_for_completion_interruptible_timeout(&adcdone_data.done, HZ); - mutex_unlock(&mc13783->adc_conv_lock); + if (!ret) + ret = -ETIMEDOUT; - return 0; + mc13783_lock(mc13783); + + mc13783_irq_free(mc13783, MC13783_IRQ_ADCDONE, &adcdone_data); + + if (ret > 0) + for (i = 0; i < 4; ++i) { + ret = mc13783_reg_read(mc13783, + MC13783_REG_ADC_2, &sample[i]); + if (ret) + break; + } + + if (mode == MC13783_ADC_MODE_TS) + /* restore TSMOD */ + mc13783_reg_write(mc13783, MC13783_REG_ADC_0, old_adc0); + + mc13783->flags &= ~MC13783_ADC_WORKING; +out: + mc13783_unlock(mc13783); + + return ret; } EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion); -void mc13783_adc_set_ts_status(struct mc13783 *mc13783, unsigned int status) +static int mc13783_add_subdevice_pdata(struct mc13783 *mc13783, + const char *name, void *pdata, size_t pdata_size) { - mc13783->ts_active = status; + struct mfd_cell cell = { + .name = name, + .platform_data = pdata, + .data_size = pdata_size, + }; + + return mfd_add_devices(&mc13783->spidev->dev, -1, &cell, 1, NULL, 0); +} + +static int mc13783_add_subdevice(struct mc13783 *mc13783, const char *name) +{ + return mc13783_add_subdevice_pdata(mc13783, name, NULL, 0); } -EXPORT_SYMBOL_GPL(mc13783_adc_set_ts_status); static int mc13783_check_revision(struct mc13783 *mc13783) { u32 rev_id, rev1, rev2, finid, icid; - mc13783_read(mc13783, MC13783_REG_REVISION, &rev_id); + mc13783_reg_read(mc13783, MC13783_REG_REVISION, &rev_id); rev1 = (rev_id & 0x018) >> 3; rev2 = (rev_id & 0x007); @@ -292,38 +555,24 @@ static int mc13783_check_revision(struct mc13783 *mc13783) rev1 = 3; if (rev1 == 0 || icid != 2) { - dev_err(mc13783->dev, "No MC13783 detected.\n"); + dev_err(&mc13783->spidev->dev, "No MC13783 detected.\n"); return -ENODEV; } - mc13783->revision = ((rev1 * 10) + rev2); - dev_info(mc13783->dev, "MC13783 Rev %d.%d FinVer %x detected\n", rev1, - rev2, finid); + dev_info(&mc13783->spidev->dev, + "MC13783 Rev %d.%d FinVer %x detected\n", + rev1, rev2, finid); return 0; } -/* - * Register a client device. This is non-fatal since there is no need to - * fail the entire device init due to a single platform device failing. - */ -static void mc13783_client_dev_register(struct mc13783 *mc13783, - const char *name) -{ - struct mfd_cell cell = {}; - - cell.name = name; - - mfd_add_devices(mc13783->dev, -1, &cell, 1, NULL, 0); -} - -static int __devinit mc13783_probe(struct spi_device *spi) +static int mc13783_probe(struct spi_device *spi) { struct mc13783 *mc13783; - struct mc13783_platform_data *pdata = spi->dev.platform_data; + struct mc13783_platform_data *pdata = dev_get_platdata(&spi->dev); int ret; - mc13783 = kzalloc(sizeof(struct mc13783), GFP_KERNEL); + mc13783 = kzalloc(sizeof(*mc13783), GFP_KERNEL); if (!mc13783) return -ENOMEM; @@ -332,96 +581,104 @@ static int __devinit mc13783_probe(struct spi_device *spi) spi->bits_per_word = 32; spi_setup(spi); - mc13783->spi_device = spi; - mc13783->dev = &spi->dev; - mc13783->irq = spi->irq; + mc13783->spidev = spi; + + mutex_init(&mc13783->lock); + mc13783_lock(mc13783); + + ret = mc13783_check_revision(mc13783); + if (ret) + goto err_revision; + + /* mask all irqs */ + ret = mc13783_reg_write(mc13783, MC13783_IRQMASK0, 0x00ffffff); + if (ret) + goto err_mask; - INIT_WORK(&mc13783->work, mc13783_irq_work); - mutex_init(&mc13783->io_lock); - mutex_init(&mc13783->adc_conv_lock); - init_completion(&mc13783->adc_done); + ret = mc13783_reg_write(mc13783, MC13783_IRQMASK1, 0x00ffffff); + if (ret) + goto err_mask; + + ret = request_threaded_irq(spi->irq, NULL, mc13783_irq_thread, + IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mc13783", mc13783); + + if (ret) { +err_mask: +err_revision: + mutex_unlock(&mc13783->lock); + dev_set_drvdata(&spi->dev, NULL); + kfree(mc13783); + return ret; + } + /* This should go away (BEGIN) */ if (pdata) { mc13783->flags = pdata->flags; mc13783->regulators = pdata->regulators; mc13783->num_regulators = pdata->num_regulators; } + /* This should go away (END) */ - if (mc13783_check_revision(mc13783)) { - ret = -ENODEV; - goto err_out; + if (pdata->flags & MC13783_USE_ADC) + mc13783_add_subdevice(mc13783, "mc13783-adc"); + + if (pdata->flags & MC13783_USE_CODEC) + mc13783_add_subdevice(mc13783, "mc13783-codec"); + + if (pdata->flags & MC13783_USE_REGULATOR) { + struct mc13783_regulator_platform_data regulator_pdata = { + .num_regulators = pdata->num_regulators, + .regulators = pdata->regulators, + }; + + mc13783_add_subdevice_pdata(mc13783, "mc13783-regulator", + ®ulator_pdata, sizeof(regulator_pdata)); } - /* clear and mask all interrupts */ - mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_STATUS_0, 0x00ffffff); - mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_MASK_0, 0x00ffffff); - mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_STATUS_1, 0x00ffffff); - mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_MASK_1, 0x00ffffff); + if (pdata->flags & MC13783_USE_RTC) + mc13783_add_subdevice(mc13783, "mc13783-rtc"); - /* unmask adcdone interrupts */ - mc13783_set_bits(mc13783, MC13783_REG_INTERRUPT_MASK_0, - MC13783_INT_MASK_ADCDONEM, 0); + if (pdata->flags & MC13783_USE_TOUCHSCREEN) + mc13783_add_subdevice(mc13783, "mc13783-ts"); - ret = request_irq(mc13783->irq, mc13783_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_HIGH, "mc13783", - mc13783); - if (ret) - goto err_out; - - if (mc13783->flags & MC13783_USE_CODEC) - mc13783_client_dev_register(mc13783, "mc13783-codec"); - if (mc13783->flags & MC13783_USE_ADC) - mc13783_client_dev_register(mc13783, "mc13783-adc"); - if (mc13783->flags & MC13783_USE_RTC) - mc13783_client_dev_register(mc13783, "mc13783-rtc"); - if (mc13783->flags & MC13783_USE_REGULATOR) - mc13783_client_dev_register(mc13783, "mc13783-regulator"); - if (mc13783->flags & MC13783_USE_TOUCHSCREEN) - mc13783_client_dev_register(mc13783, "mc13783-ts"); + mc13783_unlock(mc13783); return 0; - -err_out: - kfree(mc13783); - return ret; } static int __devexit mc13783_remove(struct spi_device *spi) { - struct mc13783 *mc13783; + struct mc13783 *mc13783 = dev_get_drvdata(&spi->dev); - mc13783 = dev_get_drvdata(&spi->dev); - - free_irq(mc13783->irq, mc13783); + free_irq(mc13783->spidev->irq, mc13783); mfd_remove_devices(&spi->dev); return 0; } -static struct spi_driver pmic_driver = { +static struct spi_driver mc13783_driver = { .driver = { - .name = "mc13783", - .bus = &spi_bus_type, - .owner = THIS_MODULE, + .name = "mc13783", + .bus = &spi_bus_type, + .owner = THIS_MODULE, }, .probe = mc13783_probe, .remove = __devexit_p(mc13783_remove), }; -static int __init pmic_init(void) +static int __init mc13783_init(void) { - return spi_register_driver(&pmic_driver); + return spi_register_driver(&mc13783_driver); } -subsys_initcall(pmic_init); +subsys_initcall(mc13783_init); -static void __exit pmic_exit(void) +static void __exit mc13783_exit(void) { - spi_unregister_driver(&pmic_driver); + spi_unregister_driver(&mc13783_driver); } -module_exit(pmic_exit); - -MODULE_DESCRIPTION("Core/Protocol driver for Freescale MC13783 PMIC"); -MODULE_AUTHOR("Sascha Hauer "); -MODULE_LICENSE("GPL"); +module_exit(mc13783_exit); +MODULE_DESCRIPTION("Core driver for Freescale MC13783 PMIC"); +MODULE_AUTHOR("Uwe Kleine-Koenig "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c index 3d31e97d6a4553ab18f1752deec8ef5a76ce12de..6d2e8466df1dd804d2943144f9a8564309f76f96 100644 --- a/drivers/mfd/pcf50633-adc.c +++ b/drivers/mfd/pcf50633-adc.c @@ -209,17 +209,16 @@ static void pcf50633_adc_irq(int irq, void *data) static int __devinit pcf50633_adc_probe(struct platform_device *pdev) { - struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data; struct pcf50633_adc *adc; adc = kzalloc(sizeof(*adc), GFP_KERNEL); if (!adc) return -ENOMEM; - adc->pcf = pdata->pcf; + adc->pcf = dev_to_pcf50633(pdev->dev.parent); platform_set_drvdata(pdev, adc); - pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ADCRDY, + pcf50633_register_irq(adc->pcf, PCF50633_IRQ_ADCRDY, pcf50633_adc_irq, adc); mutex_init(&adc->queue_mutex); diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index d26d7747175ef107c9a34d08f44fab4d692114a7..03dcc92007070605b2ec0e7f7a8164eeca00183a 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -290,7 +290,7 @@ out: int pcf50633_irq_mask(struct pcf50633 *pcf, int irq) { - dev_info(pcf->dev, "Masking IRQ %d\n", irq); + dev_dbg(pcf->dev, "Masking IRQ %d\n", irq); return __pcf50633_irq_mask_set(pcf, irq, 1); } @@ -298,7 +298,7 @@ EXPORT_SYMBOL_GPL(pcf50633_irq_mask); int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq) { - dev_info(pcf->dev, "Unmasking IRQ %d\n", irq); + dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq); return __pcf50633_irq_mask_set(pcf, irq, 0); } @@ -345,6 +345,9 @@ static void pcf50633_irq_worker(struct work_struct *work) goto out; } + /* defeat 8s death from lowsys on A5 */ + pcf50633_reg_write(pcf, PCF50633_REG_OOCSHDWN, 0x04); + /* We immediately read the usb and adapter status. We thus make sure * only of USBINS/USBREM IRQ handlers are called */ if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) { @@ -453,7 +456,6 @@ static void pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name, struct platform_device **pdev) { - struct pcf50633_subdev_pdata *subdev_pdata; int ret; *pdev = platform_device_alloc(name, -1); @@ -462,15 +464,6 @@ pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name, return; } - subdev_pdata = kmalloc(sizeof(*subdev_pdata), GFP_KERNEL); - if (!subdev_pdata) { - dev_err(pcf->dev, "Error allocating subdev pdata\n"); - platform_device_put(*pdev); - } - - subdev_pdata->pcf = pcf; - platform_device_add_data(*pdev, subdev_pdata, sizeof(*subdev_pdata)); - (*pdev)->dev.parent = pcf->dev; ret = platform_device_add(*pdev); @@ -482,13 +475,13 @@ pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name, } #ifdef CONFIG_PM -static int pcf50633_suspend(struct device *dev, pm_message_t state) +static int pcf50633_suspend(struct i2c_client *client, pm_message_t state) { struct pcf50633 *pcf; int ret = 0, i; u8 res[5]; - pcf = dev_get_drvdata(dev); + pcf = i2c_get_clientdata(client); /* Make sure our interrupt handlers are not called * henceforth */ @@ -523,12 +516,12 @@ out: return ret; } -static int pcf50633_resume(struct device *dev) +static int pcf50633_resume(struct i2c_client *client) { struct pcf50633 *pcf; int ret; - pcf = dev_get_drvdata(dev); + pcf = i2c_get_clientdata(client); /* Write the saved mask registers */ ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M, @@ -560,9 +553,14 @@ static int __devinit pcf50633_probe(struct i2c_client *client, { struct pcf50633 *pcf; struct pcf50633_platform_data *pdata = client->dev.platform_data; - int i, ret = 0; + int i, ret; int version, variant; + if (!client->irq) { + dev_err(&client->dev, "Missing IRQ\n"); + return -ENOENT; + } + pcf = kzalloc(sizeof(*pcf), GFP_KERNEL); if (!pcf) return -ENOMEM; @@ -577,6 +575,12 @@ static int __devinit pcf50633_probe(struct i2c_client *client, pcf->irq = client->irq; pcf->work_queue = create_singlethread_workqueue("pcf50633"); + if (!pcf->work_queue) { + dev_err(&client->dev, "Failed to alloc workqueue\n"); + ret = -ENOMEM; + goto err_free; + } + INIT_WORK(&pcf->irq_work, pcf50633_irq_worker); version = pcf50633_reg_read(pcf, 0); @@ -584,7 +588,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client, if (version < 0 || variant < 0) { dev_err(pcf->dev, "Unable to probe pcf50633\n"); ret = -ENODEV; - goto err; + goto err_destroy_workqueue; } dev_info(pcf->dev, "Probed device version %d variant %d\n", @@ -598,6 +602,14 @@ static int __devinit pcf50633_probe(struct i2c_client *client, pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00); pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00); + ret = request_irq(client->irq, pcf50633_irq, + IRQF_TRIGGER_LOW, "pcf50633", pcf); + + if (ret) { + dev_err(pcf->dev, "Failed to request IRQ %d\n", ret); + goto err_destroy_workqueue; + } + /* Create sub devices */ pcf50633_client_dev_register(pcf, "pcf50633-input", &pcf->input_pdev); @@ -613,31 +625,18 @@ static int __devinit pcf50633_probe(struct i2c_client *client, pdev = platform_device_alloc("pcf50633-regltr", i); if (!pdev) { - dev_err(pcf->dev, "Cannot create regulator\n"); + dev_err(pcf->dev, "Cannot create regulator %d\n", i); continue; } pdev->dev.parent = pcf->dev; - pdev->dev.platform_data = &pdata->reg_init_data[i]; - dev_set_drvdata(&pdev->dev, pcf); + platform_device_add_data(pdev, &pdata->reg_init_data[i], + sizeof(pdata->reg_init_data[i])); pcf->regulator_pdev[i] = pdev; platform_device_add(pdev); } - if (client->irq) { - ret = request_irq(client->irq, pcf50633_irq, - IRQF_TRIGGER_LOW, "pcf50633", pcf); - - if (ret) { - dev_err(pcf->dev, "Failed to request IRQ %d\n", ret); - goto err; - } - } else { - dev_err(pcf->dev, "No IRQ configured\n"); - goto err; - } - if (enable_irq_wake(client->irq) < 0) dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source" "in this hardware revision", client->irq); @@ -651,9 +650,12 @@ static int __devinit pcf50633_probe(struct i2c_client *client, return 0; -err: +err_destroy_workqueue: destroy_workqueue(pcf->work_queue); +err_free: + i2c_set_clientdata(client, NULL); kfree(pcf); + return ret; } @@ -686,12 +688,12 @@ static struct i2c_device_id pcf50633_id_table[] = { static struct i2c_driver pcf50633_driver = { .driver = { .name = "pcf50633", - .suspend = pcf50633_suspend, - .resume = pcf50633_resume, }, .id_table = pcf50633_id_table, .probe = pcf50633_probe, .remove = __devexit_p(pcf50633_remove), + .suspend = pcf50633_suspend, + .resume = pcf50633_resume, }; static int __init pcf50633_init(void) diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c index acf8b9d5f575fec8cfe3d2578ab909c0956ce178..e5955306c2fa3397d97c5dba149adf1c67213159 100644 --- a/drivers/mfd/tps65010.c +++ b/drivers/mfd/tps65010.c @@ -637,7 +637,7 @@ static int tps65010_probe(struct i2c_client *client, tps, DEBUG_FOPS); /* optionally register GPIOs */ - if (board && board->base > 0) { + if (board && board->base != 0) { tps->outmask = board->outmask; tps->chip.label = client->name; @@ -964,6 +964,34 @@ int tps65010_config_vregs1(unsigned value) } EXPORT_SYMBOL(tps65010_config_vregs1); +int tps65010_config_vdcdc2(unsigned value) +{ + struct i2c_client *c; + int status; + + if (!the_tps) + return -ENODEV; + + c = the_tps->client; + mutex_lock(&the_tps->lock); + + pr_debug("%s: vdcdc2 0x%02x\n", DRIVER_NAME, + i2c_smbus_read_byte_data(c, TPS_VDCDC2)); + + status = i2c_smbus_write_byte_data(c, TPS_VDCDC2, value); + + if (status != 0) + printk(KERN_ERR "%s: Failed to write vdcdc2 register\n", + DRIVER_NAME); + else + pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, + i2c_smbus_read_byte_data(c, TPS_VDCDC2)); + + mutex_unlock(&the_tps->lock); + return status; +} +EXPORT_SYMBOL(tps65010_config_vdcdc2); + /*-------------------------------------------------------------------------*/ /* tps65013_set_low_pwr parameter: * mode: ON or OFF diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl-core.c similarity index 66% rename from drivers/mfd/twl4030-core.c rename to drivers/mfd/twl-core.c index 40449cdf09db15acb93a3a6c11cfe468da4db12c..2a7606534196e7849f8cac4b07bbb9751a21484e 100644 --- a/drivers/mfd/twl4030-core.c +++ b/drivers/mfd/twl-core.c @@ -1,5 +1,6 @@ /* - * twl4030_core.c - driver for TWL4030/TPS659x0 PM and audio CODEC devices + * twl_core.c - driver for TWL4030/TWL5030/TWL60X0/TPS659x0 PM + * and audio CODEC devices * * Copyright (C) 2005-2006 Texas Instruments, Inc. * @@ -36,7 +37,7 @@ #include #include -#include +#include #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) #include @@ -55,7 +56,7 @@ * (and associated registers). */ -#define DRIVER_NAME "twl4030" +#define DRIVER_NAME "twl" #if defined(CONFIG_TWL4030_BCI_BATTERY) || \ defined(CONFIG_TWL4030_BCI_BATTERY_MODULE) @@ -125,7 +126,7 @@ /* Last - for index max*/ #define TWL4030_MODULE_LAST TWL4030_MODULE_SECURED_REG -#define TWL4030_NUM_SLAVES 4 +#define TWL_NUM_SLAVES 4 #if defined(CONFIG_INPUT_TWL4030_PWRBUTTON) \ || defined(CONFIG_INPUT_TWL4030_PWBUTTON_MODULE) @@ -134,6 +135,13 @@ #define twl_has_pwrbutton() false #endif +#define SUB_CHIP_ID0 0 +#define SUB_CHIP_ID1 1 +#define SUB_CHIP_ID2 2 +#define SUB_CHIP_ID3 3 + +#define TWL_MODULE_LAST TWL4030_MODULE_LAST + /* Base Address defns for twl4030_map[] */ /* subchip/slave 0 - USB ID */ @@ -158,6 +166,10 @@ #define TWL4030_BASEADD_PWMB 0x00F1 #define TWL4030_BASEADD_KEYPAD 0x00D2 +#define TWL5031_BASEADD_ACCESSORY 0x0074 /* Replaces Main Charge */ +#define TWL5031_BASEADD_INTERRUPTS 0x00B9 /* Different than TWL4030's + one */ + /* subchip/slave 3 - POWER ID */ #define TWL4030_BASEADD_BACKUP 0x0014 #define TWL4030_BASEADD_INT 0x002E @@ -169,6 +181,30 @@ /* Triton Core internal information (END) */ +/* subchip/slave 0 0x48 - POWER */ +#define TWL6030_BASEADD_RTC 0x0000 +#define TWL6030_BASEADD_MEM 0x0017 +#define TWL6030_BASEADD_PM_MASTER 0x001F +#define TWL6030_BASEADD_PM_SLAVE_MISC 0x0030 /* PM_RECEIVER */ +#define TWL6030_BASEADD_PM_MISC 0x00E2 +#define TWL6030_BASEADD_PM_PUPD 0x00F0 + +/* subchip/slave 1 0x49 - FEATURE */ +#define TWL6030_BASEADD_USB 0x0000 +#define TWL6030_BASEADD_GPADC_CTRL 0x002E +#define TWL6030_BASEADD_AUX 0x0090 +#define TWL6030_BASEADD_PWM 0x00BA +#define TWL6030_BASEADD_GASGAUGE 0x00C0 +#define TWL6030_BASEADD_PIH 0x00D0 +#define TWL6030_BASEADD_CHARGER 0x00E0 + +/* subchip/slave 2 0x4A - DFT */ +#define TWL6030_BASEADD_DIEID 0x00C0 + +/* subchip/slave 3 0x4B - AUDIO */ +#define TWL6030_BASEADD_AUDIO 0x0000 +#define TWL6030_BASEADD_RSV 0x0000 + /* Few power values */ #define R_CFG_BOOT 0x05 #define R_PROTECT_KEY 0x0E @@ -183,19 +219,29 @@ #define HFCLK_FREQ_26_MHZ (2 << 0) #define HFCLK_FREQ_38p4_MHZ (3 << 0) #define HIGH_PERF_SQ (1 << 3) +#define CK32K_LOWPWR_EN (1 << 7) /* chip-specific feature flags, for i2c_device_id.driver_data */ #define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */ #define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */ +#define TWL5031 BIT(2) /* twl5031 has different registers */ +#define TWL6030_CLASS BIT(3) /* TWL6030 class */ /*----------------------------------------------------------------------*/ /* is driver active, bound to a chip? */ static bool inuse; -/* Structure for each TWL4030 Slave */ -struct twl4030_client { +static unsigned int twl_id; +unsigned int twl_rev(void) +{ + return twl_id; +} +EXPORT_SYMBOL(twl_rev); + +/* Structure for each TWL4030/TWL6030 Slave */ +struct twl_client { struct i2c_client *client; u8 address; @@ -206,19 +252,20 @@ struct twl4030_client { struct mutex xfer_lock; }; -static struct twl4030_client twl4030_modules[TWL4030_NUM_SLAVES]; +static struct twl_client twl_modules[TWL_NUM_SLAVES]; /* mapping the module id to slave id and base address */ -struct twl4030mapping { +struct twl_mapping { unsigned char sid; /* Slave ID */ unsigned char base; /* base address */ }; +struct twl_mapping *twl_map; -static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { +static struct twl_mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { /* * NOTE: don't change this table without updating the - * defines for TWL4030_MODULE_* + * defines for TWL4030_MODULE_* * so they continue to match the order in this table. */ @@ -240,6 +287,8 @@ static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { { 2, TWL4030_BASEADD_PWM1 }, { 2, TWL4030_BASEADD_PWMA }, { 2, TWL4030_BASEADD_PWMB }, + { 2, TWL5031_BASEADD_ACCESSORY }, + { 2, TWL5031_BASEADD_INTERRUPTS }, { 3, TWL4030_BASEADD_BACKUP }, { 3, TWL4030_BASEADD_INT }, @@ -249,12 +298,46 @@ static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { { 3, TWL4030_BASEADD_SECURED_REG }, }; +static struct twl_mapping twl6030_map[] = { + /* + * NOTE: don't change this table without updating the + * defines for TWL4030_MODULE_* + * so they continue to match the order in this table. + */ + { SUB_CHIP_ID1, TWL6030_BASEADD_USB }, + { SUB_CHIP_ID3, TWL6030_BASEADD_AUDIO }, + { SUB_CHIP_ID2, TWL6030_BASEADD_DIEID }, + { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, + { SUB_CHIP_ID1, TWL6030_BASEADD_PIH }, + + { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, + { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, + { SUB_CHIP_ID1, TWL6030_BASEADD_GPADC_CTRL }, + { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, + { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, + + { SUB_CHIP_ID1, TWL6030_BASEADD_CHARGER }, + { SUB_CHIP_ID1, TWL6030_BASEADD_GASGAUGE }, + { SUB_CHIP_ID1, TWL6030_BASEADD_PWM }, + { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, + { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, + + { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, + { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, + { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, + { SUB_CHIP_ID0, TWL6030_BASEADD_PM_MASTER }, + { SUB_CHIP_ID0, TWL6030_BASEADD_PM_SLAVE_MISC }, + + { SUB_CHIP_ID0, TWL6030_BASEADD_RTC }, + { SUB_CHIP_ID0, TWL6030_BASEADD_MEM }, +}; + /*----------------------------------------------------------------------*/ /* Exported Functions */ /** - * twl4030_i2c_write - Writes a n bit register in TWL4030 + * twl_i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0 * @mod_no: module number * @value: an array of num_bytes+1 containing data to write * @reg: register address (just offset will do) @@ -265,19 +348,19 @@ static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { * * Returns the result of operation - 0 is success */ -int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) +int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) { int ret; int sid; - struct twl4030_client *twl; + struct twl_client *twl; struct i2c_msg *msg; - if (unlikely(mod_no > TWL4030_MODULE_LAST)) { + if (unlikely(mod_no > TWL_MODULE_LAST)) { pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); return -EPERM; } - sid = twl4030_map[mod_no].sid; - twl = &twl4030_modules[sid]; + sid = twl_map[mod_no].sid; + twl = &twl_modules[sid]; if (unlikely(!inuse)) { pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid); @@ -294,19 +377,26 @@ int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) msg->flags = 0; msg->buf = value; /* over write the first byte of buffer with the register address */ - *value = twl4030_map[mod_no].base + reg; + *value = twl_map[mod_no].base + reg; ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1); mutex_unlock(&twl->xfer_lock); - /* i2cTransfer returns num messages.translate it pls.. */ - if (ret >= 0) - ret = 0; - return ret; + /* i2c_transfer returns number of messages transferred */ + if (ret != 1) { + pr_err("%s: i2c_write failed to transfer all messages\n", + DRIVER_NAME); + if (ret < 0) + return ret; + else + return -EIO; + } else { + return 0; + } } -EXPORT_SYMBOL(twl4030_i2c_write); +EXPORT_SYMBOL(twl_i2c_write); /** - * twl4030_i2c_read - Reads a n bit register in TWL4030 + * twl_i2c_read - Reads a n bit register in TWL4030/TWL5030/TWL60X0 * @mod_no: module number * @value: an array of num_bytes containing data to be read * @reg: register address (just offset will do) @@ -314,20 +404,20 @@ EXPORT_SYMBOL(twl4030_i2c_write); * * Returns result of operation - num_bytes is success else failure. */ -int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) +int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) { int ret; u8 val; int sid; - struct twl4030_client *twl; + struct twl_client *twl; struct i2c_msg *msg; - if (unlikely(mod_no > TWL4030_MODULE_LAST)) { + if (unlikely(mod_no > TWL_MODULE_LAST)) { pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); return -EPERM; } - sid = twl4030_map[mod_no].sid; - twl = &twl4030_modules[sid]; + sid = twl_map[mod_no].sid; + twl = &twl_modules[sid]; if (unlikely(!inuse)) { pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid); @@ -339,7 +429,7 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) msg->addr = twl->address; msg->len = 1; msg->flags = 0; /* Read the register value */ - val = twl4030_map[mod_no].base + reg; + val = twl_map[mod_no].base + reg; msg->buf = &val; /* [MSG2] fill the data rx buffer */ msg = &twl->xfer_msg[1]; @@ -350,45 +440,52 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 2); mutex_unlock(&twl->xfer_lock); - /* i2cTransfer returns num messages.translate it pls.. */ - if (ret >= 0) - ret = 0; - return ret; + /* i2c_transfer returns number of messages transferred */ + if (ret != 2) { + pr_err("%s: i2c_read failed to transfer all messages\n", + DRIVER_NAME); + if (ret < 0) + return ret; + else + return -EIO; + } else { + return 0; + } } -EXPORT_SYMBOL(twl4030_i2c_read); +EXPORT_SYMBOL(twl_i2c_read); /** - * twl4030_i2c_write_u8 - Writes a 8 bit register in TWL4030 + * twl_i2c_write_u8 - Writes a 8 bit register in TWL4030/TWL5030/TWL60X0 * @mod_no: module number * @value: the value to be written 8 bit * @reg: register address (just offset will do) * * Returns result of operation - 0 is success */ -int twl4030_i2c_write_u8(u8 mod_no, u8 value, u8 reg) +int twl_i2c_write_u8(u8 mod_no, u8 value, u8 reg) { /* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */ u8 temp_buffer[2] = { 0 }; /* offset 1 contains the data */ temp_buffer[1] = value; - return twl4030_i2c_write(mod_no, temp_buffer, reg, 1); + return twl_i2c_write(mod_no, temp_buffer, reg, 1); } -EXPORT_SYMBOL(twl4030_i2c_write_u8); +EXPORT_SYMBOL(twl_i2c_write_u8); /** - * twl4030_i2c_read_u8 - Reads a 8 bit register from TWL4030 + * twl_i2c_read_u8 - Reads a 8 bit register from TWL4030/TWL5030/TWL60X0 * @mod_no: module number * @value: the value read 8 bit * @reg: register address (just offset will do) * * Returns result of operation - 0 is success */ -int twl4030_i2c_read_u8(u8 mod_no, u8 *value, u8 reg) +int twl_i2c_read_u8(u8 mod_no, u8 *value, u8 reg) { - return twl4030_i2c_read(mod_no, value, reg, 1); + return twl_i2c_read(mod_no, value, reg, 1); } -EXPORT_SYMBOL(twl4030_i2c_read_u8); +EXPORT_SYMBOL(twl_i2c_read_u8); /*----------------------------------------------------------------------*/ @@ -398,7 +495,7 @@ add_numbered_child(unsigned chip, const char *name, int num, bool can_wakeup, int irq0, int irq1) { struct platform_device *pdev; - struct twl4030_client *twl = &twl4030_modules[chip]; + struct twl_client *twl = &twl_modules[chip]; int status; pdev = platform_device_alloc(name, num); @@ -456,6 +553,7 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, struct regulator_consumer_supply *consumers, unsigned num_consumers) { + unsigned sub_chip_id; /* regulator framework demands init_data ... */ if (!pdata) return NULL; @@ -466,7 +564,8 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, } /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ - return add_numbered_child(3, "twl4030_reg", num, + sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid; + return add_numbered_child(sub_chip_id, "twl_reg", num, pdata, sizeof(*pdata), false, 0, 0); } @@ -486,29 +585,32 @@ static int add_children(struct twl4030_platform_data *pdata, unsigned long features) { struct device *child; + unsigned sub_chip_id; - if (twl_has_bci() && pdata->bci && !(features & TPS_SUBSET)) { + if (twl_has_bci() && pdata->bci && + !(features & (TPS_SUBSET | TWL5031))) { child = add_child(3, "twl4030_bci", pdata->bci, sizeof(*pdata->bci), false, /* irq0 = CHG_PRES, irq1 = BCI */ - pdata->irq_base + 8 + 1, pdata->irq_base + 2); + pdata->irq_base + BCI_PRES_INTR_OFFSET, + pdata->irq_base + BCI_INTR_OFFSET); if (IS_ERR(child)) return PTR_ERR(child); } if (twl_has_gpio() && pdata->gpio) { - child = add_child(1, "twl4030_gpio", + child = add_child(SUB_CHIP_ID1, "twl4030_gpio", pdata->gpio, sizeof(*pdata->gpio), - false, pdata->irq_base + 0, 0); + false, pdata->irq_base + GPIO_INTR_OFFSET, 0); if (IS_ERR(child)) return PTR_ERR(child); } if (twl_has_keypad() && pdata->keypad) { - child = add_child(2, "twl4030_keypad", + child = add_child(SUB_CHIP_ID2, "twl4030_keypad", pdata->keypad, sizeof(*pdata->keypad), - true, pdata->irq_base + 1, 0); + true, pdata->irq_base + KEYPAD_INTR_OFFSET, 0); if (IS_ERR(child)) return PTR_ERR(child); } @@ -516,7 +618,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) if (twl_has_madc() && pdata->madc) { child = add_child(2, "twl4030_madc", pdata->madc, sizeof(*pdata->madc), - true, pdata->irq_base + 3, 0); + true, pdata->irq_base + MADC_INTR_OFFSET, 0); if (IS_ERR(child)) return PTR_ERR(child); } @@ -529,14 +631,15 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) * Eventually, Linux might become more aware of such * HW security concerns, and "least privilege". */ - child = add_child(3, "twl4030_rtc", + sub_chip_id = twl_map[TWL_MODULE_RTC].sid; + child = add_child(sub_chip_id, "twl_rtc", NULL, 0, - true, pdata->irq_base + 8 + 3, 0); + true, pdata->irq_base + RTC_INTR_OFFSET, 0); if (IS_ERR(child)) return PTR_ERR(child); } - if (twl_has_usb() && pdata->usb) { + if (twl_has_usb() && pdata->usb && twl_class_is_4030()) { static struct regulator_consumer_supply usb1v5 = { .supply = "usb1v5", @@ -581,7 +684,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) pdata->usb, sizeof(*pdata->usb), true, /* irq0 = USB_PRES, irq1 = USB */ - pdata->irq_base + 8 + 2, pdata->irq_base + 4); + pdata->irq_base + USB_PRES_INTR_OFFSET, + pdata->irq_base + USB_INTR_OFFSET); if (IS_ERR(child)) return PTR_ERR(child); @@ -615,12 +719,23 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) return PTR_ERR(child); } - if (twl_has_regulator()) { - /* + /* twl4030 regulators */ + if (twl_has_regulator() && twl_class_is_4030()) { child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1); if (IS_ERR(child)) return PTR_ERR(child); - */ + + child = add_regulator(TWL4030_REG_VIO, pdata->vio); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2); + if (IS_ERR(child)) + return PTR_ERR(child); child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1); if (IS_ERR(child)) @@ -636,10 +751,23 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) pdata->vaux2); if (IS_ERR(child)) return PTR_ERR(child); + + child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig); + if (IS_ERR(child)) + return PTR_ERR(child); } /* maybe add LDOs that are omitted on cost-reduced parts */ - if (twl_has_regulator() && !(features & TPS_SUBSET)) { + if (twl_has_regulator() && !(features & TPS_SUBSET) + && twl_class_is_4030()) { child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2); if (IS_ERR(child)) return PTR_ERR(child); @@ -665,6 +793,49 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) return PTR_ERR(child); } + /* twl6030 regulators */ + if (twl_has_regulator() && twl_class_is_6030()) { + child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VPP, pdata->vpp); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VANA, pdata->vana); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VDAC, pdata->vdac); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VUSB, pdata->vusb); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3); + if (IS_ERR(child)) + return PTR_ERR(child); + } + return 0; } @@ -679,7 +850,7 @@ static inline int __init protect_pm_master(void) { int e = 0; - e = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_LOCK, + e = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, KEY_LOCK, R_PROTECT_KEY); return e; } @@ -688,14 +859,15 @@ static inline int __init unprotect_pm_master(void) { int e = 0; - e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK1, + e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, KEY_UNLOCK1, R_PROTECT_KEY); - e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK2, + e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, KEY_UNLOCK2, R_PROTECT_KEY); return e; } -static void clocks_init(struct device *dev) +static void clocks_init(struct device *dev, + struct twl4030_clock_init_data *clock) { int e = 0; struct clk *osc; @@ -709,7 +881,7 @@ static void clocks_init(struct device *dev) osc = clk_get(dev, "osc_sys_ck"); if (IS_ERR(osc)) { - printk(KERN_WARNING "Skipping twl4030 internal clock init and " + printk(KERN_WARNING "Skipping twl internal clock init and " "using bootloader value (unknown osc rate)\n"); return; } @@ -723,7 +895,7 @@ static void clocks_init(struct device *dev) */ osc = ERR_PTR(-EIO); - printk(KERN_WARNING "Skipping twl4030 internal clock init and " + printk(KERN_WARNING "Skipping twl internal clock init and " "using bootloader value (unknown osc rate)\n"); return; @@ -742,9 +914,12 @@ static void clocks_init(struct device *dev) } ctrl |= HIGH_PERF_SQ; + if (clock && clock->ck32k_lowpwr_enable) + ctrl |= CK32K_LOWPWR_EN; + e |= unprotect_pm_master(); /* effect->MADC+USB ck en */ - e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT); + e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, ctrl, R_CFG_BOOT); e |= protect_pm_master(); if (e < 0) @@ -753,24 +928,31 @@ static void clocks_init(struct device *dev) /*----------------------------------------------------------------------*/ -int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); -int twl_exit_irq(void); +int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); +int twl4030_exit_irq(void); +int twl4030_init_chip_irq(const char *chip); +int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); +int twl6030_exit_irq(void); -static int twl4030_remove(struct i2c_client *client) +static int twl_remove(struct i2c_client *client) { unsigned i; int status; - status = twl_exit_irq(); + if (twl_class_is_4030()) + status = twl4030_exit_irq(); + else + status = twl6030_exit_irq(); + if (status < 0) return status; - for (i = 0; i < TWL4030_NUM_SLAVES; i++) { - struct twl4030_client *twl = &twl4030_modules[i]; + for (i = 0; i < TWL_NUM_SLAVES; i++) { + struct twl_client *twl = &twl_modules[i]; if (twl->client && twl->client != client) i2c_unregister_device(twl->client); - twl4030_modules[i].client = NULL; + twl_modules[i].client = NULL; } inuse = false; return 0; @@ -778,7 +960,7 @@ static int twl4030_remove(struct i2c_client *client) /* NOTE: this driver only handles a single twl4030/tps659x0 chip */ static int __init -twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) +twl_probe(struct i2c_client *client, const struct i2c_device_id *id) { int status; unsigned i; @@ -799,8 +981,8 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) return -EBUSY; } - for (i = 0; i < TWL4030_NUM_SLAVES; i++) { - struct twl4030_client *twl = &twl4030_modules[i]; + for (i = 0; i < TWL_NUM_SLAVES; i++) { + struct twl_client *twl = &twl_modules[i]; twl->address = client->addr + i; if (i == 0) @@ -814,15 +996,20 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) status = -ENOMEM; goto fail; } - strlcpy(twl->client->name, id->name, - sizeof(twl->client->name)); } mutex_init(&twl->xfer_lock); } inuse = true; + if ((id->driver_data) & TWL6030_CLASS) { + twl_id = TWL6030_CLASS_ID; + twl_map = &twl6030_map[0]; + } else { + twl_id = TWL4030_CLASS_ID; + twl_map = &twl4030_map[0]; + } /* setup clock framework */ - clocks_init(&client->dev); + clocks_init(&client->dev, pdata->clock); /* load power event scripts */ if (twl_has_power() && pdata->power) @@ -832,7 +1019,15 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) if (client->irq && pdata->irq_base && pdata->irq_end > pdata->irq_base) { - status = twl_init_irq(client->irq, pdata->irq_base, pdata->irq_end); + if (twl_class_is_4030()) { + twl4030_init_chip_irq(id->name); + status = twl4030_init_irq(client->irq, pdata->irq_base, + pdata->irq_end); + } else { + status = twl6030_init_irq(client->irq, pdata->irq_base, + pdata->irq_end); + } + if (status < 0) goto fail; } @@ -840,40 +1035,42 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) status = add_children(pdata, id->driver_data); fail: if (status < 0) - twl4030_remove(client); + twl_remove(client); return status; } -static const struct i2c_device_id twl4030_ids[] = { +static const struct i2c_device_id twl_ids[] = { { "twl4030", TWL4030_VAUX2 }, /* "Triton 2" */ { "twl5030", 0 }, /* T2 updated */ + { "twl5031", TWL5031 }, /* TWL5030 updated */ { "tps65950", 0 }, /* catalog version of twl5030 */ { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */ { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */ + { "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */ { /* end of list */ }, }; -MODULE_DEVICE_TABLE(i2c, twl4030_ids); +MODULE_DEVICE_TABLE(i2c, twl_ids); /* One Client Driver , 4 Clients */ -static struct i2c_driver twl4030_driver = { +static struct i2c_driver twl_driver = { .driver.name = DRIVER_NAME, - .id_table = twl4030_ids, - .probe = twl4030_probe, - .remove = twl4030_remove, + .id_table = twl_ids, + .probe = twl_probe, + .remove = twl_remove, }; -static int __init twl4030_init(void) +static int __init twl_init(void) { - return i2c_add_driver(&twl4030_driver); + return i2c_add_driver(&twl_driver); } -subsys_initcall(twl4030_init); +subsys_initcall(twl_init); -static void __exit twl4030_exit(void) +static void __exit twl_exit(void) { - i2c_del_driver(&twl4030_driver); + i2c_del_driver(&twl_driver); } -module_exit(twl4030_exit); +module_exit(twl_exit); MODULE_AUTHOR("Texas Instruments, Inc."); -MODULE_DESCRIPTION("I2C Core interface for TWL4030"); +MODULE_DESCRIPTION("I2C Core interface for TWL"); MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index fb194fe244c1b1ce2a0c487e6463af19d87a7693..20d29bafc9f5bc79477fcca4da0e567f17a58563 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -32,7 +32,7 @@ #include #include -#include +#include /* @@ -74,6 +74,8 @@ struct sih { u8 edr_offset; u8 bytes_edr; /* bytelen of EDR */ + u8 irq_lines; /* number of supported irq lines */ + /* SIR ignored -- set interrupt, for testing only */ struct irq_data { u8 isr_offset; @@ -82,6 +84,9 @@ struct sih { /* + 2 bytes padding */ }; +static const struct sih *sih_modules; +static int nr_sih_modules; + #define SIH_INITIALIZER(modname, nbits) \ .module = TWL4030_MODULE_ ## modname, \ .control_offset = TWL4030_ ## modname ## _SIH_CTRL, \ @@ -89,6 +94,7 @@ struct sih { .bytes_ixr = DIV_ROUND_UP(nbits, 8), \ .edr_offset = TWL4030_ ## modname ## _EDR, \ .bytes_edr = DIV_ROUND_UP((2*(nbits)), 8), \ + .irq_lines = 2, \ .mask = { { \ .isr_offset = TWL4030_ ## modname ## _ISR1, \ .imr_offset = TWL4030_ ## modname ## _IMR1, \ @@ -107,7 +113,8 @@ struct sih { /* Order in this table matches order in PIH_ISR. That is, * BIT(n) in PIH_ISR is sih_modules[n]. */ -static const struct sih sih_modules[6] = { +/* sih_modules_twl4030 is used both in twl4030 and twl5030 */ +static const struct sih sih_modules_twl4030[6] = { [0] = { .name = "gpio", .module = TWL4030_MODULE_GPIO, @@ -118,6 +125,7 @@ static const struct sih sih_modules[6] = { /* Note: *all* of these IRQs default to no-trigger */ .edr_offset = REG_GPIO_EDR1, .bytes_edr = 5, + .irq_lines = 2, .mask = { { .isr_offset = REG_GPIO_ISR1A, .imr_offset = REG_GPIO_IMR1A, @@ -140,6 +148,7 @@ static const struct sih sih_modules[6] = { .edr_offset = TWL4030_INTERRUPTS_BCIEDR1, /* Note: most of these IRQs default to no-trigger */ .bytes_edr = 3, + .irq_lines = 2, .mask = { { .isr_offset = TWL4030_INTERRUPTS_BCIISR1A, .imr_offset = TWL4030_INTERRUPTS_BCIIMR1A, @@ -164,6 +173,99 @@ static const struct sih sih_modules[6] = { /* there are no SIH modules #6 or #7 ... */ }; +static const struct sih sih_modules_twl5031[8] = { + [0] = { + .name = "gpio", + .module = TWL4030_MODULE_GPIO, + .control_offset = REG_GPIO_SIH_CTRL, + .set_cor = true, + .bits = TWL4030_GPIO_MAX, + .bytes_ixr = 3, + /* Note: *all* of these IRQs default to no-trigger */ + .edr_offset = REG_GPIO_EDR1, + .bytes_edr = 5, + .irq_lines = 2, + .mask = { { + .isr_offset = REG_GPIO_ISR1A, + .imr_offset = REG_GPIO_IMR1A, + }, { + .isr_offset = REG_GPIO_ISR1B, + .imr_offset = REG_GPIO_IMR1B, + }, }, + }, + [1] = { + .name = "keypad", + .set_cor = true, + SIH_INITIALIZER(KEYPAD_KEYP, 4) + }, + [2] = { + .name = "bci", + .module = TWL5031_MODULE_INTERRUPTS, + .control_offset = TWL5031_INTERRUPTS_BCISIHCTRL, + .bits = 7, + .bytes_ixr = 1, + .edr_offset = TWL5031_INTERRUPTS_BCIEDR1, + /* Note: most of these IRQs default to no-trigger */ + .bytes_edr = 2, + .irq_lines = 2, + .mask = { { + .isr_offset = TWL5031_INTERRUPTS_BCIISR1, + .imr_offset = TWL5031_INTERRUPTS_BCIIMR1, + }, { + .isr_offset = TWL5031_INTERRUPTS_BCIISR2, + .imr_offset = TWL5031_INTERRUPTS_BCIIMR2, + }, }, + }, + [3] = { + .name = "madc", + SIH_INITIALIZER(MADC, 4) + }, + [4] = { + /* USB doesn't use the same SIH organization */ + .name = "usb", + }, + [5] = { + .name = "power", + .set_cor = true, + SIH_INITIALIZER(INT_PWR, 8) + }, + [6] = { + /* + * ACI doesn't use the same SIH organization. + * For example, it supports only one interrupt line + */ + .name = "aci", + .module = TWL5031_MODULE_ACCESSORY, + .bits = 9, + .bytes_ixr = 2, + .irq_lines = 1, + .mask = { { + .isr_offset = TWL5031_ACIIDR_LSB, + .imr_offset = TWL5031_ACIIMR_LSB, + }, }, + + }, + [7] = { + /* Accessory */ + .name = "acc", + .module = TWL5031_MODULE_ACCESSORY, + .control_offset = TWL5031_ACCSIHCTRL, + .bits = 2, + .bytes_ixr = 1, + .edr_offset = TWL5031_ACCEDR1, + /* Note: most of these IRQs default to no-trigger */ + .bytes_edr = 1, + .irq_lines = 2, + .mask = { { + .isr_offset = TWL5031_ACCISR1, + .imr_offset = TWL5031_ACCIMR1, + }, { + .isr_offset = TWL5031_ACCISR2, + .imr_offset = TWL5031_ACCIMR2, + }, }, + }, +}; + #undef TWL4030_MODULE_KEYPAD_KEYP #undef TWL4030_MODULE_INT_PWR #undef TWL4030_INT_PWR_EDR @@ -194,7 +296,7 @@ static int twl4030_irq_thread(void *data) /* Wait for IRQ, then read PIH irq status (also blocking) */ wait_for_completion_interruptible(&irq_event); - ret = twl4030_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr, + ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr, REG_PIH_ISR_P1); if (ret) { pr_warning("twl4030: I2C error %d reading PIH ISR\n", @@ -284,13 +386,17 @@ static int twl4030_init_sih_modules(unsigned line) /* disable all interrupts on our line */ memset(buf, 0xff, sizeof buf); sih = sih_modules; - for (i = 0; i < ARRAY_SIZE(sih_modules); i++, sih++) { + for (i = 0; i < nr_sih_modules; i++, sih++) { /* skip USB -- it's funky */ if (!sih->bytes_ixr) continue; - status = twl4030_i2c_write(sih->module, buf, + /* Not all the SIH modules support multiple interrupt lines */ + if (sih->irq_lines <= line) + continue; + + status = twl_i2c_write(sih->module, buf, sih->mask[line].imr_offset, sih->bytes_ixr); if (status < 0) pr_err("twl4030: err %d initializing %s %s\n", @@ -304,7 +410,7 @@ static int twl4030_init_sih_modules(unsigned line) * And for PWR_INT it's not documented... */ if (sih->set_cor) { - status = twl4030_i2c_write_u8(sih->module, + status = twl_i2c_write_u8(sih->module, TWL4030_SIH_CTRL_COR_MASK, sih->control_offset); if (status < 0) @@ -314,7 +420,7 @@ static int twl4030_init_sih_modules(unsigned line) } sih = sih_modules; - for (i = 0; i < ARRAY_SIZE(sih_modules); i++, sih++) { + for (i = 0; i < nr_sih_modules; i++, sih++) { u8 rxbuf[4]; int j; @@ -322,20 +428,24 @@ static int twl4030_init_sih_modules(unsigned line) if (!sih->bytes_ixr) continue; + /* Not all the SIH modules support multiple interrupt lines */ + if (sih->irq_lines <= line) + continue; + /* Clear pending interrupt status. Either the read was * enough, or we need to write those bits. Repeat, in * case an IRQ is pending (PENDDIS=0) ... that's not * uncommon with PWR_INT.PWRON. */ for (j = 0; j < 2; j++) { - status = twl4030_i2c_read(sih->module, rxbuf, + status = twl_i2c_read(sih->module, rxbuf, sih->mask[line].isr_offset, sih->bytes_ixr); if (status < 0) pr_err("twl4030: err %d initializing %s %s\n", status, sih->name, "ISR"); if (!sih->set_cor) - status = twl4030_i2c_write(sih->module, buf, + status = twl_i2c_write(sih->module, buf, sih->mask[line].isr_offset, sih->bytes_ixr); /* else COR=1 means read sufficed. @@ -404,7 +514,7 @@ static void twl4030_sih_do_mask(struct work_struct *work) return; /* write the whole mask ... simpler than subsetting it */ - status = twl4030_i2c_write(sih->module, imr.bytes, + status = twl_i2c_write(sih->module, imr.bytes, sih->mask[irq_line].imr_offset, sih->bytes_ixr); if (status) pr_err("twl4030: %s, %s --> %d\n", __func__, @@ -435,7 +545,7 @@ static void twl4030_sih_do_edge(struct work_struct *work) * any processor on the other IRQ line, EDR registers are * shared. */ - status = twl4030_i2c_read(sih->module, bytes + 1, + status = twl_i2c_read(sih->module, bytes + 1, sih->edr_offset, sih->bytes_edr); if (status) { pr_err("twl4030: %s, %s --> %d\n", __func__, @@ -469,7 +579,7 @@ static void twl4030_sih_do_edge(struct work_struct *work) } /* Write */ - status = twl4030_i2c_write(sih->module, bytes, + status = twl_i2c_write(sih->module, bytes, sih->edr_offset, sih->bytes_edr); if (status) pr_err("twl4030: %s, %s --> %d\n", __func__, @@ -554,7 +664,7 @@ static inline int sih_read_isr(const struct sih *sih) /* FIXME need retry-on-error ... */ isr.word = 0; - status = twl4030_i2c_read(sih->module, isr.bytes, + status = twl_i2c_read(sih->module, isr.bytes, sih->mask[irq_line].isr_offset, sih->bytes_ixr); return (status < 0) ? status : le32_to_cpu(isr.word); @@ -611,7 +721,7 @@ int twl4030_sih_setup(int module) /* only support modules with standard clear-on-read for now */ for (sih_mod = 0, sih = sih_modules; - sih_mod < ARRAY_SIZE(sih_modules); + sih_mod < nr_sih_modules; sih_mod++, sih++) { if (sih->module == module && sih->set_cor) { if (!WARN((irq_base + sih->bits) > NR_IRQS, @@ -668,7 +778,7 @@ int twl4030_sih_setup(int module) /* FIXME pass in which interrupt line we'll use ... */ #define twl_irq_line 0 -int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) +int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) { static struct irq_chip twl4030_irq_chip; @@ -728,7 +838,8 @@ int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) goto fail_rqirq; } - task = kthread_run(twl4030_irq_thread, (void *)irq_num, "twl4030-irq"); + task = kthread_run(twl4030_irq_thread, (void *)(long)irq_num, + "twl4030-irq"); if (IS_ERR(task)) { pr_err("twl4030: could not create irq %d thread!\n", irq_num); status = PTR_ERR(task); @@ -747,7 +858,7 @@ fail: return status; } -int twl_exit_irq(void) +int twl4030_exit_irq(void) { /* FIXME undo twl_init_irq() */ if (twl4030_irq_base) { @@ -756,3 +867,16 @@ int twl_exit_irq(void) } return 0; } + +int twl4030_init_chip_irq(const char *chip) +{ + if (!strcmp(chip, "twl5031")) { + sih_modules = sih_modules_twl5031; + nr_sih_modules = ARRAY_SIZE(sih_modules_twl5031); + } else { + sih_modules = sih_modules_twl4030; + nr_sih_modules = ARRAY_SIZE(sih_modules_twl4030); + } + + return 0; +} diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index d423e0c4176b600db5a5dfe511a6d9f05da7e143..0815292fdafc6c98147b6f0328ed1f98f3861b2d 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include @@ -67,19 +67,35 @@ static u8 twl4030_start_script_address = 0x2b; #define R_KEY_1 0xC0 #define R_KEY_2 0x0C -/* resource configuration registers */ - -#define DEVGROUP_OFFSET 0 +/* resource configuration registers + _DEV_GRP at address 'n+0' + _TYPE at address 'n+1' + _REMAP at address 'n+2' + _DEDICATED at address 'n+3' +*/ +#define DEV_GRP_OFFSET 0 #define TYPE_OFFSET 1 +#define REMAP_OFFSET 2 +#define DEDICATED_OFFSET 3 + +/* Bit positions in the registers */ + +/* _DEV_GRP */ +#define DEV_GRP_SHIFT 5 +#define DEV_GRP_MASK (7 << DEV_GRP_SHIFT) -/* Bit positions */ -#define DEVGROUP_SHIFT 5 -#define DEVGROUP_MASK (7 << DEVGROUP_SHIFT) +/* _TYPE */ #define TYPE_SHIFT 0 #define TYPE_MASK (7 << TYPE_SHIFT) #define TYPE2_SHIFT 3 #define TYPE2_MASK (3 << TYPE2_SHIFT) +/* _REMAP */ +#define SLEEP_STATE_SHIFT 0 +#define SLEEP_STATE_MASK (0xf << SLEEP_STATE_SHIFT) +#define OFF_STATE_SHIFT 4 +#define OFF_STATE_MASK (0xf << OFF_STATE_SHIFT) + static u8 res_config_addrs[] = { [RES_VAUX1] = 0x17, [RES_VAUX2] = 0x1b, @@ -115,11 +131,11 @@ static int __init twl4030_write_script_byte(u8 address, u8 byte) { int err; - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, R_MEMORY_ADDRESS); if (err) goto out; - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, byte, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, byte, R_MEMORY_DATA); out: return err; @@ -176,18 +192,18 @@ static int __init twl4030_config_wakeup3_sequence(u8 address) u8 data; /* Set SLEEP to ACTIVE SEQ address for P3 */ - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A3); if (err) goto out; /* P3 LVL_WAKEUP should be on LEVEL */ - err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, + err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, R_P3_SW_EVENTS); if (err) goto out; data |= LVL_WAKEUP; - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, R_P3_SW_EVENTS); out: if (err) @@ -201,42 +217,42 @@ static int __init twl4030_config_wakeup12_sequence(u8 address) u8 data; /* Set SLEEP to ACTIVE SEQ address for P1 and P2 */ - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A12); if (err) goto out; /* P1/P2 LVL_WAKEUP should be on LEVEL */ - err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, + err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, R_P1_SW_EVENTS); if (err) goto out; data |= LVL_WAKEUP; - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, R_P1_SW_EVENTS); if (err) goto out; - err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, + err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, R_P2_SW_EVENTS); if (err) goto out; data |= LVL_WAKEUP; - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, R_P2_SW_EVENTS); if (err) goto out; if (machine_is_omap_3430sdp() || machine_is_omap_ldp()) { /* Disabling AC charger effect on sleep-active transitions */ - err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, + err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, R_CFG_P1_TRANSITION); if (err) goto out; data &= ~(1<<1); - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data , + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data , R_CFG_P1_TRANSITION); if (err) goto out; @@ -254,7 +270,7 @@ static int __init twl4030_config_sleep_sequence(u8 address) int err; /* Set ACTIVE to SLEEP SEQ address in T2 memory*/ - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, R_SEQ_ADD_A2S); if (err) @@ -269,41 +285,41 @@ static int __init twl4030_config_warmreset_sequence(u8 address) u8 rd_data; /* Set WARM RESET SEQ address for P1 */ - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, R_SEQ_ADD_WARM); if (err) goto out; /* P1/P2/P3 enable WARMRESET */ - err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, + err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, R_P1_SW_EVENTS); if (err) goto out; rd_data |= ENABLE_WARMRESET; - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, R_P1_SW_EVENTS); if (err) goto out; - err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, + err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, R_P2_SW_EVENTS); if (err) goto out; rd_data |= ENABLE_WARMRESET; - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, R_P2_SW_EVENTS); if (err) goto out; - err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, + err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, R_P3_SW_EVENTS); if (err) goto out; rd_data |= ENABLE_WARMRESET; - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, R_P3_SW_EVENTS); out: if (err) @@ -317,6 +333,7 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) int err; u8 type; u8 grp; + u8 remap; if (rconfig->resource > TOTAL_RESOURCES) { pr_err("TWL4030 Resource %d does not exist\n", @@ -327,19 +344,19 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) rconfig_addr = res_config_addrs[rconfig->resource]; /* Set resource group */ - err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp, - rconfig_addr + DEVGROUP_OFFSET); + err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp, + rconfig_addr + DEV_GRP_OFFSET); if (err) { pr_err("TWL4030 Resource %d group could not be read\n", rconfig->resource); return err; } - if (rconfig->devgroup >= 0) { - grp &= ~DEVGROUP_MASK; - grp |= rconfig->devgroup << DEVGROUP_SHIFT; - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, - grp, rconfig_addr + DEVGROUP_OFFSET); + if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) { + grp &= ~DEV_GRP_MASK; + grp |= rconfig->devgroup << DEV_GRP_SHIFT; + err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + grp, rconfig_addr + DEV_GRP_OFFSET); if (err < 0) { pr_err("TWL4030 failed to program devgroup\n"); return err; @@ -347,7 +364,7 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) } /* Set resource types */ - err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type, + err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type, rconfig_addr + TYPE_OFFSET); if (err < 0) { pr_err("TWL4030 Resource %d type could not be read\n", @@ -355,23 +372,50 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) return err; } - if (rconfig->type >= 0) { + if (rconfig->type != TWL4030_RESCONFIG_UNDEF) { type &= ~TYPE_MASK; type |= rconfig->type << TYPE_SHIFT; } - if (rconfig->type2 >= 0) { + if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) { type &= ~TYPE2_MASK; type |= rconfig->type2 << TYPE2_SHIFT; } - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, type, rconfig_addr + TYPE_OFFSET); if (err < 0) { pr_err("TWL4030 failed to program resource type\n"); return err; } + /* Set remap states */ + err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap, + rconfig_addr + REMAP_OFFSET); + if (err < 0) { + pr_err("TWL4030 Resource %d remap could not be read\n", + rconfig->resource); + return err; + } + + if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) { + remap &= ~OFF_STATE_MASK; + remap |= rconfig->remap_off << OFF_STATE_SHIFT; + } + + if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) { + remap &= ~SLEEP_STATE_MASK; + remap |= rconfig->remap_off << SLEEP_STATE_SHIFT; + } + + err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + remap, + rconfig_addr + REMAP_OFFSET); + if (err < 0) { + pr_err("TWL4030 failed to program remap\n"); + return err; + } + return 0; } @@ -424,12 +468,12 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) struct twl4030_resconfig *resconfig; u8 address = twl4030_start_script_address; - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_1, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_1, R_PROTECT_KEY); if (err) goto unlock; - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_2, + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_2, R_PROTECT_KEY); if (err) goto unlock; @@ -452,7 +496,7 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) } } - err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, R_PROTECT_KEY); + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, R_PROTECT_KEY); if (err) pr_err("TWL4030 Unable to relock registers\n"); return; diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c new file mode 100644 index 0000000000000000000000000000000000000000..10bf228ad626b6caedec0b8a50d2cff03008aa53 --- /dev/null +++ b/drivers/mfd/twl6030-irq.c @@ -0,0 +1,299 @@ +/* + * twl6030-irq.c - TWL6030 irq support + * + * Copyright (C) 2005-2009 Texas Instruments, Inc. + * + * Modifications to defer interrupt handling to a kernel thread: + * Copyright (C) 2006 MontaVista Software, Inc. + * + * Based on tlv320aic23.c: + * Copyright (c) by Kai Svahn + * + * Code cleanup and modifications to IRQ handler. + * by syed khasim + * + * TWL6030 specific code and IRQ handling changes by + * Jagadeesh Bhaskar Pakaravoor + * Balaji T K + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * 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 + +/* + * TWL6030 (unlike its predecessors, which had two level interrupt handling) + * three interrupt registers INT_STS_A, INT_STS_B and INT_STS_C. + * It exposes status bits saying who has raised an interrupt. There are + * three mask registers that corresponds to these status registers, that + * enables/disables these interrupts. + * + * We set up IRQs starting at a platform-specified base. An interrupt map table, + * specifies mapping between interrupt number and the associated module. + * + */ + +static int twl6030_interrupt_mapping[24] = { + PWR_INTR_OFFSET, /* Bit 0 PWRON */ + PWR_INTR_OFFSET, /* Bit 1 RPWRON */ + PWR_INTR_OFFSET, /* Bit 2 BAT_VLOW */ + RTC_INTR_OFFSET, /* Bit 3 RTC_ALARM */ + RTC_INTR_OFFSET, /* Bit 4 RTC_PERIOD */ + HOTDIE_INTR_OFFSET, /* Bit 5 HOT_DIE */ + SMPSLDO_INTR_OFFSET, /* Bit 6 VXXX_SHORT */ + SMPSLDO_INTR_OFFSET, /* Bit 7 VMMC_SHORT */ + + SMPSLDO_INTR_OFFSET, /* Bit 8 VUSIM_SHORT */ + BATDETECT_INTR_OFFSET, /* Bit 9 BAT */ + SIMDETECT_INTR_OFFSET, /* Bit 10 SIM */ + MMCDETECT_INTR_OFFSET, /* Bit 11 MMC */ + RSV_INTR_OFFSET, /* Bit 12 Reserved */ + MADC_INTR_OFFSET, /* Bit 13 GPADC_RT_EOC */ + MADC_INTR_OFFSET, /* Bit 14 GPADC_SW_EOC */ + GASGAUGE_INTR_OFFSET, /* Bit 15 CC_AUTOCAL */ + + USBOTG_INTR_OFFSET, /* Bit 16 ID_WKUP */ + USBOTG_INTR_OFFSET, /* Bit 17 VBUS_WKUP */ + USBOTG_INTR_OFFSET, /* Bit 18 ID */ + USBOTG_INTR_OFFSET, /* Bit 19 VBUS */ + CHARGER_INTR_OFFSET, /* Bit 20 CHRG_CTRL */ + CHARGER_INTR_OFFSET, /* Bit 21 EXT_CHRG */ + CHARGER_INTR_OFFSET, /* Bit 22 INT_CHRG */ + RSV_INTR_OFFSET, /* Bit 23 Reserved */ +}; +/*----------------------------------------------------------------------*/ + +static unsigned twl6030_irq_base; + +static struct completion irq_event; + +/* + * This thread processes interrupts reported by the Primary Interrupt Handler. + */ +static int twl6030_irq_thread(void *data) +{ + long irq = (long)data; + static unsigned i2c_errors; + static const unsigned max_i2c_errors = 100; + int ret; + + current->flags |= PF_NOFREEZE; + + while (!kthread_should_stop()) { + int i; + union { + u8 bytes[4]; + u32 int_sts; + } sts; + + /* Wait for IRQ, then read PIH irq status (also blocking) */ + wait_for_completion_interruptible(&irq_event); + + /* read INT_STS_A, B and C in one shot using a burst read */ + ret = twl_i2c_read(TWL_MODULE_PIH, sts.bytes, + REG_INT_STS_A, 3); + if (ret) { + pr_warning("twl6030: I2C error %d reading PIH ISR\n", + ret); + if (++i2c_errors >= max_i2c_errors) { + printk(KERN_ERR "Maximum I2C error count" + " exceeded. Terminating %s.\n", + __func__); + break; + } + complete(&irq_event); + continue; + } + + + + sts.bytes[3] = 0; /* Only 24 bits are valid*/ + + for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++) { + local_irq_disable(); + if (sts.int_sts & 0x1) { + int module_irq = twl6030_irq_base + + twl6030_interrupt_mapping[i]; + struct irq_desc *d = irq_to_desc(module_irq); + + if (!d) { + pr_err("twl6030: Invalid SIH IRQ: %d\n", + module_irq); + return -EINVAL; + } + + /* These can't be masked ... always warn + * if we get any surprises. + */ + if (d->status & IRQ_DISABLED) + note_interrupt(module_irq, d, + IRQ_NONE); + else + d->handle_irq(module_irq, d); + + } + local_irq_enable(); + } + ret = twl_i2c_write(TWL_MODULE_PIH, sts.bytes, + REG_INT_STS_A, 3); /* clear INT_STS_A */ + if (ret) + pr_warning("twl6030: I2C error in clearing PIH ISR\n"); + + enable_irq(irq); + } + + return 0; +} + +/* + * handle_twl6030_int() is the desc->handle method for the twl6030 interrupt. + * This is a chained interrupt, so there is no desc->action method for it. + * Now we need to query the interrupt controller in the twl6030 to determine + * which module is generating the interrupt request. However, we can't do i2c + * transactions in interrupt context, so we must defer that work to a kernel + * thread. All we do here is acknowledge and mask the interrupt and wakeup + * the kernel thread. + */ +static irqreturn_t handle_twl6030_pih(int irq, void *devid) +{ + disable_irq_nosync(irq); + complete(devid); + return IRQ_HANDLED; +} + +/*----------------------------------------------------------------------*/ + +static inline void activate_irq(int irq) +{ +#ifdef CONFIG_ARM + /* ARM requires an extra step to clear IRQ_NOREQUEST, which it + * sets on behalf of every irq_chip. Also sets IRQ_NOPROBE. + */ + set_irq_flags(irq, IRQF_VALID); +#else + /* same effect on other architectures */ + set_irq_noprobe(irq); +#endif +} + +/*----------------------------------------------------------------------*/ + +static unsigned twl6030_irq_next; + +/*----------------------------------------------------------------------*/ +int twl6030_interrupt_unmask(u8 bit_mask, u8 offset) +{ + int ret; + u8 unmask_value; + ret = twl_i2c_read_u8(TWL_MODULE_PIH, &unmask_value, + REG_INT_STS_A + offset); + unmask_value &= (~(bit_mask)); + ret |= twl_i2c_write_u8(TWL_MODULE_PIH, unmask_value, + REG_INT_STS_A + offset); /* unmask INT_MSK_A/B/C */ + return ret; +} +EXPORT_SYMBOL(twl6030_interrupt_unmask); + +int twl6030_interrupt_mask(u8 bit_mask, u8 offset) +{ + int ret; + u8 mask_value; + ret = twl_i2c_read_u8(TWL_MODULE_PIH, &mask_value, + REG_INT_STS_A + offset); + mask_value |= (bit_mask); + ret |= twl_i2c_write_u8(TWL_MODULE_PIH, mask_value, + REG_INT_STS_A + offset); /* mask INT_MSK_A/B/C */ + return ret; +} +EXPORT_SYMBOL(twl6030_interrupt_mask); + +int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) +{ + + int status = 0; + int i; + struct task_struct *task; + int ret; + u8 mask[4]; + + static struct irq_chip twl6030_irq_chip; + mask[1] = 0xFF; + mask[2] = 0xFF; + mask[3] = 0xFF; + ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], + REG_INT_MSK_LINE_A, 3); /* MASK ALL INT LINES */ + ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], + REG_INT_MSK_STS_A, 3); /* MASK ALL INT STS */ + ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], + REG_INT_STS_A, 3); /* clear INT_STS_A,B,C */ + + twl6030_irq_base = irq_base; + + /* install an irq handler for each of the modules; + * clone dummy irq_chip since PIH can't *do* anything + */ + twl6030_irq_chip = dummy_irq_chip; + twl6030_irq_chip.name = "twl6030"; + twl6030_irq_chip.set_type = NULL; + + for (i = irq_base; i < irq_end; i++) { + set_irq_chip_and_handler(i, &twl6030_irq_chip, + handle_simple_irq); + activate_irq(i); + } + + twl6030_irq_next = i; + pr_info("twl6030: %s (irq %d) chaining IRQs %d..%d\n", "PIH", + irq_num, irq_base, twl6030_irq_next - 1); + + /* install an irq handler to demultiplex the TWL6030 interrupt */ + init_completion(&irq_event); + task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq"); + if (IS_ERR(task)) { + pr_err("twl6030: could not create irq %d thread!\n", irq_num); + status = PTR_ERR(task); + goto fail_kthread; + } + + status = request_irq(irq_num, handle_twl6030_pih, IRQF_DISABLED, + "TWL6030-PIH", &irq_event); + if (status < 0) { + pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status); + goto fail_irq; + } + return status; +fail_irq: + free_irq(irq_num, &irq_event); + +fail_kthread: + for (i = irq_base; i < irq_end; i++) + set_irq_chip_and_handler(i, NULL, NULL); + return status; +} + +int twl6030_exit_irq(void) +{ + + if (twl6030_irq_base) { + pr_err("twl6030: can't yet clean up IRQs?\n"); + return -ENOSYS; + } + return 0; +} + diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 7f27576ca0464bede0c3bb6e1a1f86d04630f5eb..223a90c7492fbe71710dd4e1538608db90b75605 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -90,9 +90,10 @@ int wm831x_isinkv_values[WM831X_ISINK_MAX_ISEL + 1] = { EXPORT_SYMBOL_GPL(wm831x_isinkv_values); enum wm831x_parent { - WM8310 = 0, - WM8311 = 1, - WM8312 = 2, + WM8310 = 0x8310, + WM8311 = 0x8311, + WM8312 = 0x8312, + WM8320 = 0x8320, }; static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) @@ -478,6 +479,20 @@ static struct resource wm831x_dcdc4_resources[] = { }, }; +static struct resource wm8320_dcdc4_buck_resources[] = { + { + .start = WM831X_DC4_CONTROL, + .end = WM832X_DC4_SLEEP_CONTROL, + .flags = IORESOURCE_IO, + }, + { + .name = "UV", + .start = WM831X_IRQ_UV_DC4, + .end = WM831X_IRQ_UV_DC4, + .flags = IORESOURCE_IRQ, + }, +}; + static struct resource wm831x_gpio_resources[] = { { .start = WM831X_IRQ_GPIO_1, @@ -1237,6 +1252,137 @@ static struct mfd_cell wm8312_devs[] = { }, }; +static struct mfd_cell wm8320_devs[] = { + { + .name = "wm831x-backup", + }, + { + .name = "wm831x-buckv", + .id = 1, + .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources), + .resources = wm831x_dcdc1_resources, + }, + { + .name = "wm831x-buckv", + .id = 2, + .num_resources = ARRAY_SIZE(wm831x_dcdc2_resources), + .resources = wm831x_dcdc2_resources, + }, + { + .name = "wm831x-buckp", + .id = 3, + .num_resources = ARRAY_SIZE(wm831x_dcdc3_resources), + .resources = wm831x_dcdc3_resources, + }, + { + .name = "wm831x-buckp", + .id = 4, + .num_resources = ARRAY_SIZE(wm8320_dcdc4_buck_resources), + .resources = wm8320_dcdc4_buck_resources, + }, + { + .name = "wm831x-gpio", + .num_resources = ARRAY_SIZE(wm831x_gpio_resources), + .resources = wm831x_gpio_resources, + }, + { + .name = "wm831x-hwmon", + }, + { + .name = "wm831x-ldo", + .id = 1, + .num_resources = ARRAY_SIZE(wm831x_ldo1_resources), + .resources = wm831x_ldo1_resources, + }, + { + .name = "wm831x-ldo", + .id = 2, + .num_resources = ARRAY_SIZE(wm831x_ldo2_resources), + .resources = wm831x_ldo2_resources, + }, + { + .name = "wm831x-ldo", + .id = 3, + .num_resources = ARRAY_SIZE(wm831x_ldo3_resources), + .resources = wm831x_ldo3_resources, + }, + { + .name = "wm831x-ldo", + .id = 4, + .num_resources = ARRAY_SIZE(wm831x_ldo4_resources), + .resources = wm831x_ldo4_resources, + }, + { + .name = "wm831x-ldo", + .id = 5, + .num_resources = ARRAY_SIZE(wm831x_ldo5_resources), + .resources = wm831x_ldo5_resources, + }, + { + .name = "wm831x-ldo", + .id = 6, + .num_resources = ARRAY_SIZE(wm831x_ldo6_resources), + .resources = wm831x_ldo6_resources, + }, + { + .name = "wm831x-aldo", + .id = 7, + .num_resources = ARRAY_SIZE(wm831x_ldo7_resources), + .resources = wm831x_ldo7_resources, + }, + { + .name = "wm831x-aldo", + .id = 8, + .num_resources = ARRAY_SIZE(wm831x_ldo8_resources), + .resources = wm831x_ldo8_resources, + }, + { + .name = "wm831x-aldo", + .id = 9, + .num_resources = ARRAY_SIZE(wm831x_ldo9_resources), + .resources = wm831x_ldo9_resources, + }, + { + .name = "wm831x-aldo", + .id = 10, + .num_resources = ARRAY_SIZE(wm831x_ldo10_resources), + .resources = wm831x_ldo10_resources, + }, + { + .name = "wm831x-alive-ldo", + .id = 11, + .num_resources = ARRAY_SIZE(wm831x_ldo11_resources), + .resources = wm831x_ldo11_resources, + }, + { + .name = "wm831x-on", + .num_resources = ARRAY_SIZE(wm831x_on_resources), + .resources = wm831x_on_resources, + }, + { + .name = "wm831x-rtc", + .num_resources = ARRAY_SIZE(wm831x_rtc_resources), + .resources = wm831x_rtc_resources, + }, + { + .name = "wm831x-status", + .id = 1, + .num_resources = ARRAY_SIZE(wm831x_status1_resources), + .resources = wm831x_status1_resources, + }, + { + .name = "wm831x-status", + .id = 2, + .num_resources = ARRAY_SIZE(wm831x_status2_resources), + .resources = wm831x_status2_resources, + }, + { + .name = "wm831x-watchdog", + .num_resources = ARRAY_SIZE(wm831x_wdt_resources), + .resources = wm831x_wdt_resources, + }, +}; + static struct mfd_cell backlight_devs[] = { { .name = "wm831x-backlight", @@ -1282,50 +1428,37 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) goto err; } + /* Some engineering samples do not have the ID set, rely on + * the device being registered correctly. + */ + if (ret == 0) { + dev_info(wm831x->dev, "Device is an engineering sample\n"); + ret = id; + } + switch (ret) { - case 0x8310: + case WM8310: parent = WM8310; - switch (rev) { - case 0: - dev_info(wm831x->dev, "WM8310 revision %c\n", - 'A' + rev); - break; - } + wm831x->num_gpio = 16; + dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev); break; - case 0x8311: + case WM8311: parent = WM8311; - switch (rev) { - case 0: - dev_info(wm831x->dev, "WM8311 revision %c\n", - 'A' + rev); - break; - } + wm831x->num_gpio = 16; + dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev); break; - case 0x8312: + case WM8312: parent = WM8312; - switch (rev) { - case 0: - dev_info(wm831x->dev, "WM8312 revision %c\n", - 'A' + rev); - break; - } + wm831x->num_gpio = 16; + dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev); break; - case 0: - /* Some engineering samples do not have the ID set, - * rely on the device being registered correctly. - * This will need revisiting for future devices with - * multiple dies. - */ - parent = id; - switch (rev) { - case 0: - dev_info(wm831x->dev, "WM831%d ES revision %c\n", - parent, 'A' + rev); - break; - } + case WM8320: + parent = WM8320; + wm831x->num_gpio = 12; + dev_info(wm831x->dev, "WM8320 revision %c\n", 'A' + rev); break; default: @@ -1338,7 +1471,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) * current parts. */ if (parent != id) - dev_warn(wm831x->dev, "Device was registered as a WM831%lu\n", + dev_warn(wm831x->dev, "Device was registered as a WM%lx\n", id); /* Bootstrap the user key */ @@ -1371,18 +1504,24 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) case WM8310: ret = mfd_add_devices(wm831x->dev, -1, wm8310_devs, ARRAY_SIZE(wm8310_devs), - NULL, 0); + NULL, wm831x->irq_base); break; case WM8311: ret = mfd_add_devices(wm831x->dev, -1, wm8311_devs, ARRAY_SIZE(wm8311_devs), - NULL, 0); + NULL, wm831x->irq_base); break; case WM8312: ret = mfd_add_devices(wm831x->dev, -1, wm8312_devs, ARRAY_SIZE(wm8312_devs), + NULL, wm831x->irq_base); + break; + + case WM8320: + ret = mfd_add_devices(wm831x->dev, -1, + wm8320_devs, ARRAY_SIZE(wm8320_devs), NULL, 0); break; @@ -1399,7 +1538,8 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) if (pdata && pdata->backlight) { /* Treat errors as non-critical */ ret = mfd_add_devices(wm831x->dev, -1, backlight_devs, - ARRAY_SIZE(backlight_devs), NULL, 0); + ARRAY_SIZE(backlight_devs), NULL, + wm831x->irq_base); if (ret < 0) dev_err(wm831x->dev, "Failed to add backlight: %d\n", ret); @@ -1511,6 +1651,7 @@ static const struct i2c_device_id wm831x_i2c_id[] = { { "wm8310", WM8310 }, { "wm8311", WM8311 }, { "wm8312", WM8312 }, + { "wm8320", WM8320 }, { } }; MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index ac056ea6b66ed6c432e47683e0a9fe78ac0e464e..301327697117da5c7ac1fcb8c759bbad7bdf2b37 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -339,110 +340,71 @@ static inline int irq_data_to_mask_reg(struct wm831x_irq_data *irq_data) return WM831X_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg; } -static void __wm831x_enable_irq(struct wm831x *wm831x, int irq) +static inline struct wm831x_irq_data *irq_to_wm831x_irq(struct wm831x *wm831x, + int irq) { - struct wm831x_irq_data *irq_data = &wm831x_irqs[irq]; - - wm831x->irq_masks[irq_data->reg - 1] &= ~irq_data->mask; - wm831x_reg_write(wm831x, irq_data_to_mask_reg(irq_data), - wm831x->irq_masks[irq_data->reg - 1]); + return &wm831x_irqs[irq - wm831x->irq_base]; } -void wm831x_enable_irq(struct wm831x *wm831x, int irq) +static void wm831x_irq_lock(unsigned int irq) { - mutex_lock(&wm831x->irq_lock); - __wm831x_enable_irq(wm831x, irq); - mutex_unlock(&wm831x->irq_lock); -} -EXPORT_SYMBOL_GPL(wm831x_enable_irq); + struct wm831x *wm831x = get_irq_chip_data(irq); -static void __wm831x_disable_irq(struct wm831x *wm831x, int irq) -{ - struct wm831x_irq_data *irq_data = &wm831x_irqs[irq]; - - wm831x->irq_masks[irq_data->reg - 1] |= irq_data->mask; - wm831x_reg_write(wm831x, irq_data_to_mask_reg(irq_data), - wm831x->irq_masks[irq_data->reg - 1]); -} - -void wm831x_disable_irq(struct wm831x *wm831x, int irq) -{ mutex_lock(&wm831x->irq_lock); - __wm831x_disable_irq(wm831x, irq); - mutex_unlock(&wm831x->irq_lock); } -EXPORT_SYMBOL_GPL(wm831x_disable_irq); -int wm831x_request_irq(struct wm831x *wm831x, - unsigned int irq, irq_handler_t handler, - unsigned long flags, const char *name, - void *dev) +static void wm831x_irq_sync_unlock(unsigned int irq) { - int ret = 0; - - if (irq < 0 || irq >= WM831X_NUM_IRQS) - return -EINVAL; - - mutex_lock(&wm831x->irq_lock); - - if (wm831x_irqs[irq].handler) { - dev_err(wm831x->dev, "Already have handler for IRQ %d\n", irq); - ret = -EINVAL; - goto out; + struct wm831x *wm831x = get_irq_chip_data(irq); + int i; + + for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) { + /* If there's been a change in the mask write it back + * to the hardware. */ + if (wm831x->irq_masks_cur[i] != wm831x->irq_masks_cache[i]) { + wm831x->irq_masks_cache[i] = wm831x->irq_masks_cur[i]; + wm831x_reg_write(wm831x, + WM831X_INTERRUPT_STATUS_1_MASK + i, + wm831x->irq_masks_cur[i]); + } } - wm831x_irqs[irq].handler = handler; - wm831x_irqs[irq].handler_data = dev; - - __wm831x_enable_irq(wm831x, irq); - -out: mutex_unlock(&wm831x->irq_lock); - - return ret; } -EXPORT_SYMBOL_GPL(wm831x_request_irq); -void wm831x_free_irq(struct wm831x *wm831x, unsigned int irq, void *data) +static void wm831x_irq_unmask(unsigned int irq) { - if (irq < 0 || irq >= WM831X_NUM_IRQS) - return; - - mutex_lock(&wm831x->irq_lock); + struct wm831x *wm831x = get_irq_chip_data(irq); + struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq); - wm831x_irqs[irq].handler = NULL; - wm831x_irqs[irq].handler_data = NULL; - - __wm831x_disable_irq(wm831x, irq); - - mutex_unlock(&wm831x->irq_lock); + wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; } -EXPORT_SYMBOL_GPL(wm831x_free_irq); - -static void wm831x_handle_irq(struct wm831x *wm831x, int irq, int status) +static void wm831x_irq_mask(unsigned int irq) { - struct wm831x_irq_data *irq_data = &wm831x_irqs[irq]; - - if (irq_data->handler) { - irq_data->handler(irq, irq_data->handler_data); - wm831x_reg_write(wm831x, irq_data_to_status_reg(irq_data), - irq_data->mask); - } else { - dev_err(wm831x->dev, "Unhandled IRQ %d, masking\n", irq); - __wm831x_disable_irq(wm831x, irq); - } + struct wm831x *wm831x = get_irq_chip_data(irq); + struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq); + + wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; } -/* Main interrupt handling occurs in a workqueue since we need - * interrupts enabled to interact with the chip. */ -static void wm831x_irq_worker(struct work_struct *work) +static struct irq_chip wm831x_irq_chip = { + .name = "wm831x", + .bus_lock = wm831x_irq_lock, + .bus_sync_unlock = wm831x_irq_sync_unlock, + .mask = wm831x_irq_mask, + .unmask = wm831x_irq_unmask, +}; + +/* The processing of the primary interrupt occurs in a thread so that + * we can interact with the device over I2C or SPI. */ +static irqreturn_t wm831x_irq_thread(int irq, void *data) { - struct wm831x *wm831x = container_of(work, struct wm831x, irq_work); + struct wm831x *wm831x = data; unsigned int i; int primary; - int status_regs[5]; - int read[5] = { 0 }; + int status_regs[WM831X_NUM_IRQ_REGS] = { 0 }; + int read[WM831X_NUM_IRQ_REGS] = { 0 }; int *status; primary = wm831x_reg_read(wm831x, WM831X_SYSTEM_INTERRUPTS); @@ -452,8 +414,6 @@ static void wm831x_irq_worker(struct work_struct *work) goto out; } - mutex_lock(&wm831x->irq_lock); - for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) { int offset = wm831x_irqs[i].reg - 1; @@ -471,41 +431,34 @@ static void wm831x_irq_worker(struct work_struct *work) dev_err(wm831x->dev, "Failed to read IRQ status: %d\n", *status); - goto out_lock; + goto out; } - /* Mask out the disabled IRQs */ - *status &= ~wm831x->irq_masks[offset]; read[offset] = 1; } - if (*status & wm831x_irqs[i].mask) - wm831x_handle_irq(wm831x, i, *status); + /* Report it if it isn't masked, or forget the status. */ + if ((*status & ~wm831x->irq_masks_cur[offset]) + & wm831x_irqs[i].mask) + handle_nested_irq(wm831x->irq_base + i); + else + *status &= ~wm831x_irqs[i].mask; } -out_lock: - mutex_unlock(&wm831x->irq_lock); out: - enable_irq(wm831x->irq); -} - - -static irqreturn_t wm831x_cpu_irq(int irq, void *data) -{ - struct wm831x *wm831x = data; - - /* Shut the interrupt to the CPU up and schedule the actual - * handler; we can't check that the IRQ is asserted. */ - disable_irq_nosync(irq); - - queue_work(wm831x->irq_wq, &wm831x->irq_work); + for (i = 0; i < ARRAY_SIZE(status_regs); i++) { + if (status_regs[i]) + wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i, + status_regs[i]); + } return IRQ_HANDLED; } int wm831x_irq_init(struct wm831x *wm831x, int irq) { - int i, ret; + struct wm831x_pdata *pdata = wm831x->dev->platform_data; + int i, cur_irq, ret; mutex_init(&wm831x->irq_lock); @@ -515,41 +468,53 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) return 0; } - - wm831x->irq_wq = create_singlethread_workqueue("wm831x-irq"); - if (!wm831x->irq_wq) { - dev_err(wm831x->dev, "Failed to allocate IRQ worker\n"); - return -ESRCH; + if (!pdata || !pdata->irq_base) { + dev_err(wm831x->dev, + "No interrupt base specified, no interrupts\n"); + return 0; } wm831x->irq = irq; - INIT_WORK(&wm831x->irq_work, wm831x_irq_worker); + wm831x->irq_base = pdata->irq_base; /* Mask the individual interrupt sources */ - for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks); i++) { - wm831x->irq_masks[i] = 0xffff; + for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) { + wm831x->irq_masks_cur[i] = 0xffff; + wm831x->irq_masks_cache[i] = 0xffff; wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1_MASK + i, 0xffff); } - /* Enable top level interrupts, we mask at secondary level */ - wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0); + /* Register them with genirq */ + for (cur_irq = wm831x->irq_base; + cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base; + cur_irq++) { + set_irq_chip_data(cur_irq, wm831x); + set_irq_chip_and_handler(cur_irq, &wm831x_irq_chip, + handle_edge_irq); + set_irq_nested_thread(cur_irq, 1); + + /* ARM needs us to explicitly flag the IRQ as valid + * and will set them noprobe when we do so. */ +#ifdef CONFIG_ARM + set_irq_flags(cur_irq, IRQF_VALID); +#else + set_irq_noprobe(cur_irq); +#endif + } - /* We're good to go. We set IRQF_SHARED since there's a - * chance the driver will interoperate with another driver but - * the need to disable the IRQ while handing via I2C/SPI means - * that this may break and performance will be impacted. If - * this does happen it's a hardware design issue and the only - * other alternative would be polling. - */ - ret = request_irq(irq, wm831x_cpu_irq, IRQF_TRIGGER_LOW | IRQF_SHARED, - "wm831x", wm831x); + ret = request_threaded_irq(irq, NULL, wm831x_irq_thread, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "wm831x", wm831x); if (ret != 0) { dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n", irq, ret); return ret; } + /* Enable top level interrupts, we mask at secondary level */ + wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0); + return 0; } diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index ba27c9dc1ad39284a04ebcb8e11c8b7fd3d8c67e..8485a70180605d0eea68cb1b1d98872541846c5c 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c @@ -337,733 +337,6 @@ int wm8350_reg_unlock(struct wm8350 *wm8350) } EXPORT_SYMBOL_GPL(wm8350_reg_unlock); -static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq) -{ - mutex_lock(&wm8350->irq_mutex); - - if (wm8350->irq[irq].handler) - wm8350->irq[irq].handler(wm8350, irq, wm8350->irq[irq].data); - else { - dev_err(wm8350->dev, "irq %d nobody cared. now masked.\n", - irq); - wm8350_mask_irq(wm8350, irq); - } - - mutex_unlock(&wm8350->irq_mutex); -} - -/* - * This is a threaded IRQ handler so can access I2C/SPI. Since all - * interrupts are clear on read the IRQ line will be reasserted and - * the physical IRQ will be handled again if another interrupt is - * asserted while we run - in the normal course of events this is a - * rare occurrence so we save I2C/SPI reads. - */ -static irqreturn_t wm8350_irq(int irq, void *data) -{ - struct wm8350 *wm8350 = data; - u16 level_one, status1, status2, comp; - - /* TODO: Use block reads to improve performance? */ - level_one = wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS) - & ~wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK); - status1 = wm8350_reg_read(wm8350, WM8350_INT_STATUS_1) - & ~wm8350_reg_read(wm8350, WM8350_INT_STATUS_1_MASK); - status2 = wm8350_reg_read(wm8350, WM8350_INT_STATUS_2) - & ~wm8350_reg_read(wm8350, WM8350_INT_STATUS_2_MASK); - comp = wm8350_reg_read(wm8350, WM8350_COMPARATOR_INT_STATUS) - & ~wm8350_reg_read(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK); - - /* over current */ - if (level_one & WM8350_OC_INT) { - u16 oc; - - oc = wm8350_reg_read(wm8350, WM8350_OVER_CURRENT_INT_STATUS); - oc &= ~wm8350_reg_read(wm8350, - WM8350_OVER_CURRENT_INT_STATUS_MASK); - - if (oc & WM8350_OC_LS_EINT) /* limit switch */ - wm8350_irq_call_handler(wm8350, WM8350_IRQ_OC_LS); - } - - /* under voltage */ - if (level_one & WM8350_UV_INT) { - u16 uv; - - uv = wm8350_reg_read(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS); - uv &= ~wm8350_reg_read(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK); - - if (uv & WM8350_UV_DC1_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC1); - if (uv & WM8350_UV_DC2_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC2); - if (uv & WM8350_UV_DC3_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC3); - if (uv & WM8350_UV_DC4_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC4); - if (uv & WM8350_UV_DC5_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC5); - if (uv & WM8350_UV_DC6_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC6); - if (uv & WM8350_UV_LDO1_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO1); - if (uv & WM8350_UV_LDO2_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO2); - if (uv & WM8350_UV_LDO3_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO3); - if (uv & WM8350_UV_LDO4_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO4); - } - - /* charger, RTC */ - if (status1) { - if (status1 & WM8350_CHG_BAT_HOT_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_CHG_BAT_HOT); - if (status1 & WM8350_CHG_BAT_COLD_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_CHG_BAT_COLD); - if (status1 & WM8350_CHG_BAT_FAIL_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_CHG_BAT_FAIL); - if (status1 & WM8350_CHG_TO_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_TO); - if (status1 & WM8350_CHG_END_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_END); - if (status1 & WM8350_CHG_START_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_START); - if (status1 & WM8350_CHG_FAST_RDY_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_CHG_FAST_RDY); - if (status1 & WM8350_CHG_VBATT_LT_3P9_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_CHG_VBATT_LT_3P9); - if (status1 & WM8350_CHG_VBATT_LT_3P1_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_CHG_VBATT_LT_3P1); - if (status1 & WM8350_CHG_VBATT_LT_2P85_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_CHG_VBATT_LT_2P85); - if (status1 & WM8350_RTC_ALM_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_ALM); - if (status1 & WM8350_RTC_SEC_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_SEC); - if (status1 & WM8350_RTC_PER_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_PER); - } - - /* current sink, system, aux adc */ - if (status2) { - if (status2 & WM8350_CS1_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_CS1); - if (status2 & WM8350_CS2_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_CS2); - - if (status2 & WM8350_SYS_HYST_COMP_FAIL_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_SYS_HYST_COMP_FAIL); - if (status2 & WM8350_SYS_CHIP_GT115_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_SYS_CHIP_GT115); - if (status2 & WM8350_SYS_CHIP_GT140_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_SYS_CHIP_GT140); - if (status2 & WM8350_SYS_WDOG_TO_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_SYS_WDOG_TO); - - if (status2 & WM8350_AUXADC_DATARDY_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_AUXADC_DATARDY); - if (status2 & WM8350_AUXADC_DCOMP4_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_AUXADC_DCOMP4); - if (status2 & WM8350_AUXADC_DCOMP3_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_AUXADC_DCOMP3); - if (status2 & WM8350_AUXADC_DCOMP2_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_AUXADC_DCOMP2); - if (status2 & WM8350_AUXADC_DCOMP1_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_AUXADC_DCOMP1); - - if (status2 & WM8350_USB_LIMIT_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_USB_LIMIT); - } - - /* wake, codec, ext */ - if (comp) { - if (comp & WM8350_WKUP_OFF_STATE_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_WKUP_OFF_STATE); - if (comp & WM8350_WKUP_HIB_STATE_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_WKUP_HIB_STATE); - if (comp & WM8350_WKUP_CONV_FAULT_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_WKUP_CONV_FAULT); - if (comp & WM8350_WKUP_WDOG_RST_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_WKUP_WDOG_RST); - if (comp & WM8350_WKUP_GP_PWR_ON_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_WKUP_GP_PWR_ON); - if (comp & WM8350_WKUP_ONKEY_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_WKUP_ONKEY); - if (comp & WM8350_WKUP_GP_WAKEUP_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_WKUP_GP_WAKEUP); - - if (comp & WM8350_CODEC_JCK_DET_L_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_CODEC_JCK_DET_L); - if (comp & WM8350_CODEC_JCK_DET_R_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_CODEC_JCK_DET_R); - if (comp & WM8350_CODEC_MICSCD_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_CODEC_MICSCD); - if (comp & WM8350_CODEC_MICD_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_CODEC_MICD); - - if (comp & WM8350_EXT_USB_FB_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_EXT_USB_FB); - if (comp & WM8350_EXT_WALL_FB_EINT) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_EXT_WALL_FB); - if (comp & WM8350_EXT_BAT_FB_EINT) - wm8350_irq_call_handler(wm8350, WM8350_IRQ_EXT_BAT_FB); - } - - if (level_one & WM8350_GP_INT) { - int i; - u16 gpio; - - gpio = wm8350_reg_read(wm8350, WM8350_GPIO_INT_STATUS); - gpio &= ~wm8350_reg_read(wm8350, - WM8350_GPIO_INT_STATUS_MASK); - - for (i = 0; i < 12; i++) { - if (gpio & (1 << i)) - wm8350_irq_call_handler(wm8350, - WM8350_IRQ_GPIO(i)); - } - } - - return IRQ_HANDLED; -} - -int wm8350_register_irq(struct wm8350 *wm8350, int irq, - void (*handler) (struct wm8350 *, int, void *), - void *data) -{ - if (irq < 0 || irq > WM8350_NUM_IRQ || !handler) - return -EINVAL; - - if (wm8350->irq[irq].handler) - return -EBUSY; - - mutex_lock(&wm8350->irq_mutex); - wm8350->irq[irq].handler = handler; - wm8350->irq[irq].data = data; - mutex_unlock(&wm8350->irq_mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(wm8350_register_irq); - -int wm8350_free_irq(struct wm8350 *wm8350, int irq) -{ - if (irq < 0 || irq > WM8350_NUM_IRQ) - return -EINVAL; - - mutex_lock(&wm8350->irq_mutex); - wm8350->irq[irq].handler = NULL; - mutex_unlock(&wm8350->irq_mutex); - return 0; -} -EXPORT_SYMBOL_GPL(wm8350_free_irq); - -int wm8350_mask_irq(struct wm8350 *wm8350, int irq) -{ - switch (irq) { - case WM8350_IRQ_CHG_BAT_HOT: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_BAT_HOT_EINT); - case WM8350_IRQ_CHG_BAT_COLD: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_BAT_COLD_EINT); - case WM8350_IRQ_CHG_BAT_FAIL: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_BAT_FAIL_EINT); - case WM8350_IRQ_CHG_TO: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_TO_EINT); - case WM8350_IRQ_CHG_END: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_END_EINT); - case WM8350_IRQ_CHG_START: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_START_EINT); - case WM8350_IRQ_CHG_FAST_RDY: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_FAST_RDY_EINT); - case WM8350_IRQ_RTC_PER: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_RTC_PER_EINT); - case WM8350_IRQ_RTC_SEC: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_RTC_SEC_EINT); - case WM8350_IRQ_RTC_ALM: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_RTC_ALM_EINT); - case WM8350_IRQ_CHG_VBATT_LT_3P9: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_VBATT_LT_3P9_EINT); - case WM8350_IRQ_CHG_VBATT_LT_3P1: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_VBATT_LT_3P1_EINT); - case WM8350_IRQ_CHG_VBATT_LT_2P85: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_VBATT_LT_2P85_EINT); - case WM8350_IRQ_CS1: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_CS1_EINT); - case WM8350_IRQ_CS2: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_CS2_EINT); - case WM8350_IRQ_USB_LIMIT: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_USB_LIMIT_EINT); - case WM8350_IRQ_AUXADC_DATARDY: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_AUXADC_DATARDY_EINT); - case WM8350_IRQ_AUXADC_DCOMP4: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_AUXADC_DCOMP4_EINT); - case WM8350_IRQ_AUXADC_DCOMP3: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_AUXADC_DCOMP3_EINT); - case WM8350_IRQ_AUXADC_DCOMP2: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_AUXADC_DCOMP2_EINT); - case WM8350_IRQ_AUXADC_DCOMP1: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_AUXADC_DCOMP1_EINT); - case WM8350_IRQ_SYS_HYST_COMP_FAIL: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_SYS_HYST_COMP_FAIL_EINT); - case WM8350_IRQ_SYS_CHIP_GT115: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_SYS_CHIP_GT115_EINT); - case WM8350_IRQ_SYS_CHIP_GT140: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_SYS_CHIP_GT140_EINT); - case WM8350_IRQ_SYS_WDOG_TO: - return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_SYS_WDOG_TO_EINT); - case WM8350_IRQ_UV_LDO4: - return wm8350_set_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_LDO4_EINT); - case WM8350_IRQ_UV_LDO3: - return wm8350_set_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_LDO3_EINT); - case WM8350_IRQ_UV_LDO2: - return wm8350_set_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_LDO2_EINT); - case WM8350_IRQ_UV_LDO1: - return wm8350_set_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_LDO1_EINT); - case WM8350_IRQ_UV_DC6: - return wm8350_set_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_DC6_EINT); - case WM8350_IRQ_UV_DC5: - return wm8350_set_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_DC5_EINT); - case WM8350_IRQ_UV_DC4: - return wm8350_set_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_DC4_EINT); - case WM8350_IRQ_UV_DC3: - return wm8350_set_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_DC3_EINT); - case WM8350_IRQ_UV_DC2: - return wm8350_set_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_DC2_EINT); - case WM8350_IRQ_UV_DC1: - return wm8350_set_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_DC1_EINT); - case WM8350_IRQ_OC_LS: - return wm8350_set_bits(wm8350, - WM8350_OVER_CURRENT_INT_STATUS_MASK, - WM8350_IM_OC_LS_EINT); - case WM8350_IRQ_EXT_USB_FB: - return wm8350_set_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_EXT_USB_FB_EINT); - case WM8350_IRQ_EXT_WALL_FB: - return wm8350_set_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_EXT_WALL_FB_EINT); - case WM8350_IRQ_EXT_BAT_FB: - return wm8350_set_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_EXT_BAT_FB_EINT); - case WM8350_IRQ_CODEC_JCK_DET_L: - return wm8350_set_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_CODEC_JCK_DET_L_EINT); - case WM8350_IRQ_CODEC_JCK_DET_R: - return wm8350_set_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_CODEC_JCK_DET_R_EINT); - case WM8350_IRQ_CODEC_MICSCD: - return wm8350_set_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_CODEC_MICSCD_EINT); - case WM8350_IRQ_CODEC_MICD: - return wm8350_set_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_CODEC_MICD_EINT); - case WM8350_IRQ_WKUP_OFF_STATE: - return wm8350_set_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_WKUP_OFF_STATE_EINT); - case WM8350_IRQ_WKUP_HIB_STATE: - return wm8350_set_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_WKUP_HIB_STATE_EINT); - case WM8350_IRQ_WKUP_CONV_FAULT: - return wm8350_set_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_WKUP_CONV_FAULT_EINT); - case WM8350_IRQ_WKUP_WDOG_RST: - return wm8350_set_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_WKUP_OFF_STATE_EINT); - case WM8350_IRQ_WKUP_GP_PWR_ON: - return wm8350_set_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_WKUP_GP_PWR_ON_EINT); - case WM8350_IRQ_WKUP_ONKEY: - return wm8350_set_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_WKUP_ONKEY_EINT); - case WM8350_IRQ_WKUP_GP_WAKEUP: - return wm8350_set_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_WKUP_GP_WAKEUP_EINT); - case WM8350_IRQ_GPIO(0): - return wm8350_set_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP0_EINT); - case WM8350_IRQ_GPIO(1): - return wm8350_set_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP1_EINT); - case WM8350_IRQ_GPIO(2): - return wm8350_set_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP2_EINT); - case WM8350_IRQ_GPIO(3): - return wm8350_set_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP3_EINT); - case WM8350_IRQ_GPIO(4): - return wm8350_set_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP4_EINT); - case WM8350_IRQ_GPIO(5): - return wm8350_set_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP5_EINT); - case WM8350_IRQ_GPIO(6): - return wm8350_set_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP6_EINT); - case WM8350_IRQ_GPIO(7): - return wm8350_set_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP7_EINT); - case WM8350_IRQ_GPIO(8): - return wm8350_set_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP8_EINT); - case WM8350_IRQ_GPIO(9): - return wm8350_set_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP9_EINT); - case WM8350_IRQ_GPIO(10): - return wm8350_set_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP10_EINT); - case WM8350_IRQ_GPIO(11): - return wm8350_set_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP11_EINT); - case WM8350_IRQ_GPIO(12): - return wm8350_set_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP12_EINT); - default: - dev_warn(wm8350->dev, "Attempting to mask unknown IRQ %d\n", - irq); - return -EINVAL; - } - return 0; -} -EXPORT_SYMBOL_GPL(wm8350_mask_irq); - -int wm8350_unmask_irq(struct wm8350 *wm8350, int irq) -{ - switch (irq) { - case WM8350_IRQ_CHG_BAT_HOT: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_BAT_HOT_EINT); - case WM8350_IRQ_CHG_BAT_COLD: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_BAT_COLD_EINT); - case WM8350_IRQ_CHG_BAT_FAIL: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_BAT_FAIL_EINT); - case WM8350_IRQ_CHG_TO: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_TO_EINT); - case WM8350_IRQ_CHG_END: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_END_EINT); - case WM8350_IRQ_CHG_START: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_START_EINT); - case WM8350_IRQ_CHG_FAST_RDY: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_FAST_RDY_EINT); - case WM8350_IRQ_RTC_PER: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_RTC_PER_EINT); - case WM8350_IRQ_RTC_SEC: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_RTC_SEC_EINT); - case WM8350_IRQ_RTC_ALM: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_RTC_ALM_EINT); - case WM8350_IRQ_CHG_VBATT_LT_3P9: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_VBATT_LT_3P9_EINT); - case WM8350_IRQ_CHG_VBATT_LT_3P1: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_VBATT_LT_3P1_EINT); - case WM8350_IRQ_CHG_VBATT_LT_2P85: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, - WM8350_IM_CHG_VBATT_LT_2P85_EINT); - case WM8350_IRQ_CS1: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_CS1_EINT); - case WM8350_IRQ_CS2: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_CS2_EINT); - case WM8350_IRQ_USB_LIMIT: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_USB_LIMIT_EINT); - case WM8350_IRQ_AUXADC_DATARDY: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_AUXADC_DATARDY_EINT); - case WM8350_IRQ_AUXADC_DCOMP4: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_AUXADC_DCOMP4_EINT); - case WM8350_IRQ_AUXADC_DCOMP3: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_AUXADC_DCOMP3_EINT); - case WM8350_IRQ_AUXADC_DCOMP2: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_AUXADC_DCOMP2_EINT); - case WM8350_IRQ_AUXADC_DCOMP1: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_AUXADC_DCOMP1_EINT); - case WM8350_IRQ_SYS_HYST_COMP_FAIL: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_SYS_HYST_COMP_FAIL_EINT); - case WM8350_IRQ_SYS_CHIP_GT115: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_SYS_CHIP_GT115_EINT); - case WM8350_IRQ_SYS_CHIP_GT140: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_SYS_CHIP_GT140_EINT); - case WM8350_IRQ_SYS_WDOG_TO: - return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, - WM8350_IM_SYS_WDOG_TO_EINT); - case WM8350_IRQ_UV_LDO4: - return wm8350_clear_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_LDO4_EINT); - case WM8350_IRQ_UV_LDO3: - return wm8350_clear_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_LDO3_EINT); - case WM8350_IRQ_UV_LDO2: - return wm8350_clear_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_LDO2_EINT); - case WM8350_IRQ_UV_LDO1: - return wm8350_clear_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_LDO1_EINT); - case WM8350_IRQ_UV_DC6: - return wm8350_clear_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_DC6_EINT); - case WM8350_IRQ_UV_DC5: - return wm8350_clear_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_DC5_EINT); - case WM8350_IRQ_UV_DC4: - return wm8350_clear_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_DC4_EINT); - case WM8350_IRQ_UV_DC3: - return wm8350_clear_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_DC3_EINT); - case WM8350_IRQ_UV_DC2: - return wm8350_clear_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_DC2_EINT); - case WM8350_IRQ_UV_DC1: - return wm8350_clear_bits(wm8350, - WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, - WM8350_IM_UV_DC1_EINT); - case WM8350_IRQ_OC_LS: - return wm8350_clear_bits(wm8350, - WM8350_OVER_CURRENT_INT_STATUS_MASK, - WM8350_IM_OC_LS_EINT); - case WM8350_IRQ_EXT_USB_FB: - return wm8350_clear_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_EXT_USB_FB_EINT); - case WM8350_IRQ_EXT_WALL_FB: - return wm8350_clear_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_EXT_WALL_FB_EINT); - case WM8350_IRQ_EXT_BAT_FB: - return wm8350_clear_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_EXT_BAT_FB_EINT); - case WM8350_IRQ_CODEC_JCK_DET_L: - return wm8350_clear_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_CODEC_JCK_DET_L_EINT); - case WM8350_IRQ_CODEC_JCK_DET_R: - return wm8350_clear_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_CODEC_JCK_DET_R_EINT); - case WM8350_IRQ_CODEC_MICSCD: - return wm8350_clear_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_CODEC_MICSCD_EINT); - case WM8350_IRQ_CODEC_MICD: - return wm8350_clear_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_CODEC_MICD_EINT); - case WM8350_IRQ_WKUP_OFF_STATE: - return wm8350_clear_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_WKUP_OFF_STATE_EINT); - case WM8350_IRQ_WKUP_HIB_STATE: - return wm8350_clear_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_WKUP_HIB_STATE_EINT); - case WM8350_IRQ_WKUP_CONV_FAULT: - return wm8350_clear_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_WKUP_CONV_FAULT_EINT); - case WM8350_IRQ_WKUP_WDOG_RST: - return wm8350_clear_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_WKUP_OFF_STATE_EINT); - case WM8350_IRQ_WKUP_GP_PWR_ON: - return wm8350_clear_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_WKUP_GP_PWR_ON_EINT); - case WM8350_IRQ_WKUP_ONKEY: - return wm8350_clear_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_WKUP_ONKEY_EINT); - case WM8350_IRQ_WKUP_GP_WAKEUP: - return wm8350_clear_bits(wm8350, - WM8350_COMPARATOR_INT_STATUS_MASK, - WM8350_IM_WKUP_GP_WAKEUP_EINT); - case WM8350_IRQ_GPIO(0): - return wm8350_clear_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP0_EINT); - case WM8350_IRQ_GPIO(1): - return wm8350_clear_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP1_EINT); - case WM8350_IRQ_GPIO(2): - return wm8350_clear_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP2_EINT); - case WM8350_IRQ_GPIO(3): - return wm8350_clear_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP3_EINT); - case WM8350_IRQ_GPIO(4): - return wm8350_clear_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP4_EINT); - case WM8350_IRQ_GPIO(5): - return wm8350_clear_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP5_EINT); - case WM8350_IRQ_GPIO(6): - return wm8350_clear_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP6_EINT); - case WM8350_IRQ_GPIO(7): - return wm8350_clear_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP7_EINT); - case WM8350_IRQ_GPIO(8): - return wm8350_clear_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP8_EINT); - case WM8350_IRQ_GPIO(9): - return wm8350_clear_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP9_EINT); - case WM8350_IRQ_GPIO(10): - return wm8350_clear_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP10_EINT); - case WM8350_IRQ_GPIO(11): - return wm8350_clear_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP11_EINT); - case WM8350_IRQ_GPIO(12): - return wm8350_clear_bits(wm8350, - WM8350_GPIO_INT_STATUS_MASK, - WM8350_IM_GP12_EINT); - default: - dev_warn(wm8350->dev, "Attempting to unmask unknown IRQ %d\n", - irq); - return -EINVAL; - } - return 0; -} -EXPORT_SYMBOL_GPL(wm8350_unmask_irq); - int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) { u16 reg, result = 0; @@ -1264,7 +537,7 @@ static void wm8350_client_dev_register(struct wm8350 *wm8350, int ret; *pdev = platform_device_alloc(name, -1); - if (pdev == NULL) { + if (*pdev == NULL) { dev_err(wm8350->dev, "Failed to allocate %s\n", name); return; } @@ -1409,49 +682,18 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, return ret; } - wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF); - wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK, 0xFFFF); - wm8350_reg_write(wm8350, WM8350_INT_STATUS_2_MASK, 0xFFFF); - wm8350_reg_write(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, 0xFFFF); - wm8350_reg_write(wm8350, WM8350_GPIO_INT_STATUS_MASK, 0xFFFF); - wm8350_reg_write(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK, 0xFFFF); - mutex_init(&wm8350->auxadc_mutex); - mutex_init(&wm8350->irq_mutex); - if (irq) { - int flags = IRQF_ONESHOT; - - if (pdata && pdata->irq_high) { - flags |= IRQF_TRIGGER_HIGH; - - wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1, - WM8350_IRQ_POL); - } else { - flags |= IRQF_TRIGGER_LOW; - - wm8350_clear_bits(wm8350, WM8350_SYSTEM_CONTROL_1, - WM8350_IRQ_POL); - } - ret = request_threaded_irq(irq, NULL, wm8350_irq, flags, - "wm8350", wm8350); - if (ret != 0) { - dev_err(wm8350->dev, "Failed to request IRQ: %d\n", - ret); - goto err; - } - } else { - dev_err(wm8350->dev, "No IRQ configured\n"); + ret = wm8350_irq_init(wm8350, irq, pdata); + if (ret < 0) goto err; - } - wm8350->chip_irq = irq; if (pdata && pdata->init) { ret = pdata->init(wm8350); if (ret != 0) { dev_err(wm8350->dev, "Platform init() failed: %d\n", ret); - goto err; + goto err_irq; } } @@ -1470,6 +712,8 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, return 0; +err_irq: + wm8350_irq_exit(wm8350); err: kfree(wm8350->reg_cache); return ret; @@ -1493,7 +737,8 @@ void wm8350_device_exit(struct wm8350 *wm8350) platform_device_unregister(wm8350->gpio.pdev); platform_device_unregister(wm8350->codec.pdev); - free_irq(wm8350->chip_irq, wm8350); + wm8350_irq_exit(wm8350); + kfree(wm8350->reg_cache); } EXPORT_SYMBOL_GPL(wm8350_device_exit); diff --git a/drivers/mfd/wm8350-irq.c b/drivers/mfd/wm8350-irq.c new file mode 100644 index 0000000000000000000000000000000000000000..c8df547c474703b45d4285cd063bd68ab4c5e636 --- /dev/null +++ b/drivers/mfd/wm8350-irq.c @@ -0,0 +1,529 @@ +/* + * wm8350-irq.c -- IRQ support for Wolfson WM8350 + * + * Copyright 2007, 2008, 2009 Wolfson Microelectronics PLC. + * + * Author: Liam Girdwood, Mark Brown + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 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 + +#define WM8350_NUM_IRQ_REGS 7 + +#define WM8350_INT_OFFSET_1 0 +#define WM8350_INT_OFFSET_2 1 +#define WM8350_POWER_UP_INT_OFFSET 2 +#define WM8350_UNDER_VOLTAGE_INT_OFFSET 3 +#define WM8350_OVER_CURRENT_INT_OFFSET 4 +#define WM8350_GPIO_INT_OFFSET 5 +#define WM8350_COMPARATOR_INT_OFFSET 6 + +struct wm8350_irq_data { + int primary; + int reg; + int mask; + int primary_only; +}; + +static struct wm8350_irq_data wm8350_irqs[] = { + [WM8350_IRQ_OC_LS] = { + .primary = WM8350_OC_INT, + .reg = WM8350_OVER_CURRENT_INT_OFFSET, + .mask = WM8350_OC_LS_EINT, + .primary_only = 1, + }, + [WM8350_IRQ_UV_DC1] = { + .primary = WM8350_UV_INT, + .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, + .mask = WM8350_UV_DC1_EINT, + }, + [WM8350_IRQ_UV_DC2] = { + .primary = WM8350_UV_INT, + .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, + .mask = WM8350_UV_DC2_EINT, + }, + [WM8350_IRQ_UV_DC3] = { + .primary = WM8350_UV_INT, + .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, + .mask = WM8350_UV_DC3_EINT, + }, + [WM8350_IRQ_UV_DC4] = { + .primary = WM8350_UV_INT, + .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, + .mask = WM8350_UV_DC4_EINT, + }, + [WM8350_IRQ_UV_DC5] = { + .primary = WM8350_UV_INT, + .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, + .mask = WM8350_UV_DC5_EINT, + }, + [WM8350_IRQ_UV_DC6] = { + .primary = WM8350_UV_INT, + .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, + .mask = WM8350_UV_DC6_EINT, + }, + [WM8350_IRQ_UV_LDO1] = { + .primary = WM8350_UV_INT, + .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, + .mask = WM8350_UV_LDO1_EINT, + }, + [WM8350_IRQ_UV_LDO2] = { + .primary = WM8350_UV_INT, + .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, + .mask = WM8350_UV_LDO2_EINT, + }, + [WM8350_IRQ_UV_LDO3] = { + .primary = WM8350_UV_INT, + .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, + .mask = WM8350_UV_LDO3_EINT, + }, + [WM8350_IRQ_UV_LDO4] = { + .primary = WM8350_UV_INT, + .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, + .mask = WM8350_UV_LDO4_EINT, + }, + [WM8350_IRQ_CHG_BAT_HOT] = { + .primary = WM8350_CHG_INT, + .reg = WM8350_INT_OFFSET_1, + .mask = WM8350_CHG_BAT_HOT_EINT, + }, + [WM8350_IRQ_CHG_BAT_COLD] = { + .primary = WM8350_CHG_INT, + .reg = WM8350_INT_OFFSET_1, + .mask = WM8350_CHG_BAT_COLD_EINT, + }, + [WM8350_IRQ_CHG_BAT_FAIL] = { + .primary = WM8350_CHG_INT, + .reg = WM8350_INT_OFFSET_1, + .mask = WM8350_CHG_BAT_FAIL_EINT, + }, + [WM8350_IRQ_CHG_TO] = { + .primary = WM8350_CHG_INT, + .reg = WM8350_INT_OFFSET_1, + .mask = WM8350_CHG_TO_EINT, + }, + [WM8350_IRQ_CHG_END] = { + .primary = WM8350_CHG_INT, + .reg = WM8350_INT_OFFSET_1, + .mask = WM8350_CHG_END_EINT, + }, + [WM8350_IRQ_CHG_START] = { + .primary = WM8350_CHG_INT, + .reg = WM8350_INT_OFFSET_1, + .mask = WM8350_CHG_START_EINT, + }, + [WM8350_IRQ_CHG_FAST_RDY] = { + .primary = WM8350_CHG_INT, + .reg = WM8350_INT_OFFSET_1, + .mask = WM8350_CHG_FAST_RDY_EINT, + }, + [WM8350_IRQ_CHG_VBATT_LT_3P9] = { + .primary = WM8350_CHG_INT, + .reg = WM8350_INT_OFFSET_1, + .mask = WM8350_CHG_VBATT_LT_3P9_EINT, + }, + [WM8350_IRQ_CHG_VBATT_LT_3P1] = { + .primary = WM8350_CHG_INT, + .reg = WM8350_INT_OFFSET_1, + .mask = WM8350_CHG_VBATT_LT_3P1_EINT, + }, + [WM8350_IRQ_CHG_VBATT_LT_2P85] = { + .primary = WM8350_CHG_INT, + .reg = WM8350_INT_OFFSET_1, + .mask = WM8350_CHG_VBATT_LT_2P85_EINT, + }, + [WM8350_IRQ_RTC_ALM] = { + .primary = WM8350_RTC_INT, + .reg = WM8350_INT_OFFSET_1, + .mask = WM8350_RTC_ALM_EINT, + }, + [WM8350_IRQ_RTC_SEC] = { + .primary = WM8350_RTC_INT, + .reg = WM8350_INT_OFFSET_1, + .mask = WM8350_RTC_SEC_EINT, + }, + [WM8350_IRQ_RTC_PER] = { + .primary = WM8350_RTC_INT, + .reg = WM8350_INT_OFFSET_1, + .mask = WM8350_RTC_PER_EINT, + }, + [WM8350_IRQ_CS1] = { + .primary = WM8350_CS_INT, + .reg = WM8350_INT_OFFSET_2, + .mask = WM8350_CS1_EINT, + }, + [WM8350_IRQ_CS2] = { + .primary = WM8350_CS_INT, + .reg = WM8350_INT_OFFSET_2, + .mask = WM8350_CS2_EINT, + }, + [WM8350_IRQ_SYS_HYST_COMP_FAIL] = { + .primary = WM8350_SYS_INT, + .reg = WM8350_INT_OFFSET_2, + .mask = WM8350_SYS_HYST_COMP_FAIL_EINT, + }, + [WM8350_IRQ_SYS_CHIP_GT115] = { + .primary = WM8350_SYS_INT, + .reg = WM8350_INT_OFFSET_2, + .mask = WM8350_SYS_CHIP_GT115_EINT, + }, + [WM8350_IRQ_SYS_CHIP_GT140] = { + .primary = WM8350_SYS_INT, + .reg = WM8350_INT_OFFSET_2, + .mask = WM8350_SYS_CHIP_GT140_EINT, + }, + [WM8350_IRQ_SYS_WDOG_TO] = { + .primary = WM8350_SYS_INT, + .reg = WM8350_INT_OFFSET_2, + .mask = WM8350_SYS_WDOG_TO_EINT, + }, + [WM8350_IRQ_AUXADC_DATARDY] = { + .primary = WM8350_AUXADC_INT, + .reg = WM8350_INT_OFFSET_2, + .mask = WM8350_AUXADC_DATARDY_EINT, + }, + [WM8350_IRQ_AUXADC_DCOMP4] = { + .primary = WM8350_AUXADC_INT, + .reg = WM8350_INT_OFFSET_2, + .mask = WM8350_AUXADC_DCOMP4_EINT, + }, + [WM8350_IRQ_AUXADC_DCOMP3] = { + .primary = WM8350_AUXADC_INT, + .reg = WM8350_INT_OFFSET_2, + .mask = WM8350_AUXADC_DCOMP3_EINT, + }, + [WM8350_IRQ_AUXADC_DCOMP2] = { + .primary = WM8350_AUXADC_INT, + .reg = WM8350_INT_OFFSET_2, + .mask = WM8350_AUXADC_DCOMP2_EINT, + }, + [WM8350_IRQ_AUXADC_DCOMP1] = { + .primary = WM8350_AUXADC_INT, + .reg = WM8350_INT_OFFSET_2, + .mask = WM8350_AUXADC_DCOMP1_EINT, + }, + [WM8350_IRQ_USB_LIMIT] = { + .primary = WM8350_USB_INT, + .reg = WM8350_INT_OFFSET_2, + .mask = WM8350_USB_LIMIT_EINT, + .primary_only = 1, + }, + [WM8350_IRQ_WKUP_OFF_STATE] = { + .primary = WM8350_WKUP_INT, + .reg = WM8350_COMPARATOR_INT_OFFSET, + .mask = WM8350_WKUP_OFF_STATE_EINT, + }, + [WM8350_IRQ_WKUP_HIB_STATE] = { + .primary = WM8350_WKUP_INT, + .reg = WM8350_COMPARATOR_INT_OFFSET, + .mask = WM8350_WKUP_HIB_STATE_EINT, + }, + [WM8350_IRQ_WKUP_CONV_FAULT] = { + .primary = WM8350_WKUP_INT, + .reg = WM8350_COMPARATOR_INT_OFFSET, + .mask = WM8350_WKUP_CONV_FAULT_EINT, + }, + [WM8350_IRQ_WKUP_WDOG_RST] = { + .primary = WM8350_WKUP_INT, + .reg = WM8350_COMPARATOR_INT_OFFSET, + .mask = WM8350_WKUP_WDOG_RST_EINT, + }, + [WM8350_IRQ_WKUP_GP_PWR_ON] = { + .primary = WM8350_WKUP_INT, + .reg = WM8350_COMPARATOR_INT_OFFSET, + .mask = WM8350_WKUP_GP_PWR_ON_EINT, + }, + [WM8350_IRQ_WKUP_ONKEY] = { + .primary = WM8350_WKUP_INT, + .reg = WM8350_COMPARATOR_INT_OFFSET, + .mask = WM8350_WKUP_ONKEY_EINT, + }, + [WM8350_IRQ_WKUP_GP_WAKEUP] = { + .primary = WM8350_WKUP_INT, + .reg = WM8350_COMPARATOR_INT_OFFSET, + .mask = WM8350_WKUP_GP_WAKEUP_EINT, + }, + [WM8350_IRQ_CODEC_JCK_DET_L] = { + .primary = WM8350_CODEC_INT, + .reg = WM8350_COMPARATOR_INT_OFFSET, + .mask = WM8350_CODEC_JCK_DET_L_EINT, + }, + [WM8350_IRQ_CODEC_JCK_DET_R] = { + .primary = WM8350_CODEC_INT, + .reg = WM8350_COMPARATOR_INT_OFFSET, + .mask = WM8350_CODEC_JCK_DET_R_EINT, + }, + [WM8350_IRQ_CODEC_MICSCD] = { + .primary = WM8350_CODEC_INT, + .reg = WM8350_COMPARATOR_INT_OFFSET, + .mask = WM8350_CODEC_MICSCD_EINT, + }, + [WM8350_IRQ_CODEC_MICD] = { + .primary = WM8350_CODEC_INT, + .reg = WM8350_COMPARATOR_INT_OFFSET, + .mask = WM8350_CODEC_MICD_EINT, + }, + [WM8350_IRQ_EXT_USB_FB] = { + .primary = WM8350_EXT_INT, + .reg = WM8350_COMPARATOR_INT_OFFSET, + .mask = WM8350_EXT_USB_FB_EINT, + }, + [WM8350_IRQ_EXT_WALL_FB] = { + .primary = WM8350_EXT_INT, + .reg = WM8350_COMPARATOR_INT_OFFSET, + .mask = WM8350_EXT_WALL_FB_EINT, + }, + [WM8350_IRQ_EXT_BAT_FB] = { + .primary = WM8350_EXT_INT, + .reg = WM8350_COMPARATOR_INT_OFFSET, + .mask = WM8350_EXT_BAT_FB_EINT, + }, + [WM8350_IRQ_GPIO(0)] = { + .primary = WM8350_GP_INT, + .reg = WM8350_GPIO_INT_OFFSET, + .mask = WM8350_GP0_EINT, + }, + [WM8350_IRQ_GPIO(1)] = { + .primary = WM8350_GP_INT, + .reg = WM8350_GPIO_INT_OFFSET, + .mask = WM8350_GP1_EINT, + }, + [WM8350_IRQ_GPIO(2)] = { + .primary = WM8350_GP_INT, + .reg = WM8350_GPIO_INT_OFFSET, + .mask = WM8350_GP2_EINT, + }, + [WM8350_IRQ_GPIO(3)] = { + .primary = WM8350_GP_INT, + .reg = WM8350_GPIO_INT_OFFSET, + .mask = WM8350_GP3_EINT, + }, + [WM8350_IRQ_GPIO(4)] = { + .primary = WM8350_GP_INT, + .reg = WM8350_GPIO_INT_OFFSET, + .mask = WM8350_GP4_EINT, + }, + [WM8350_IRQ_GPIO(5)] = { + .primary = WM8350_GP_INT, + .reg = WM8350_GPIO_INT_OFFSET, + .mask = WM8350_GP5_EINT, + }, + [WM8350_IRQ_GPIO(6)] = { + .primary = WM8350_GP_INT, + .reg = WM8350_GPIO_INT_OFFSET, + .mask = WM8350_GP6_EINT, + }, + [WM8350_IRQ_GPIO(7)] = { + .primary = WM8350_GP_INT, + .reg = WM8350_GPIO_INT_OFFSET, + .mask = WM8350_GP7_EINT, + }, + [WM8350_IRQ_GPIO(8)] = { + .primary = WM8350_GP_INT, + .reg = WM8350_GPIO_INT_OFFSET, + .mask = WM8350_GP8_EINT, + }, + [WM8350_IRQ_GPIO(9)] = { + .primary = WM8350_GP_INT, + .reg = WM8350_GPIO_INT_OFFSET, + .mask = WM8350_GP9_EINT, + }, + [WM8350_IRQ_GPIO(10)] = { + .primary = WM8350_GP_INT, + .reg = WM8350_GPIO_INT_OFFSET, + .mask = WM8350_GP10_EINT, + }, + [WM8350_IRQ_GPIO(11)] = { + .primary = WM8350_GP_INT, + .reg = WM8350_GPIO_INT_OFFSET, + .mask = WM8350_GP11_EINT, + }, + [WM8350_IRQ_GPIO(12)] = { + .primary = WM8350_GP_INT, + .reg = WM8350_GPIO_INT_OFFSET, + .mask = WM8350_GP12_EINT, + }, +}; + +static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq) +{ + mutex_lock(&wm8350->irq_mutex); + + if (wm8350->irq[irq].handler) + wm8350->irq[irq].handler(irq, wm8350->irq[irq].data); + else { + dev_err(wm8350->dev, "irq %d nobody cared. now masked.\n", + irq); + wm8350_mask_irq(wm8350, irq); + } + + mutex_unlock(&wm8350->irq_mutex); +} + +/* + * This is a threaded IRQ handler so can access I2C/SPI. Since all + * interrupts are clear on read the IRQ line will be reasserted and + * the physical IRQ will be handled again if another interrupt is + * asserted while we run - in the normal course of events this is a + * rare occurrence so we save I2C/SPI reads. + */ +static irqreturn_t wm8350_irq(int irq, void *irq_data) +{ + struct wm8350 *wm8350 = irq_data; + u16 level_one; + u16 sub_reg[WM8350_NUM_IRQ_REGS]; + int read_done[WM8350_NUM_IRQ_REGS]; + struct wm8350_irq_data *data; + int i; + + /* TODO: Use block reads to improve performance? */ + level_one = wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS) + & ~wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK); + + if (!level_one) + return IRQ_NONE; + + memset(&read_done, 0, sizeof(read_done)); + + for (i = 0; i < ARRAY_SIZE(wm8350_irqs); i++) { + data = &wm8350_irqs[i]; + + if (!(level_one & data->primary)) + continue; + + if (!read_done[data->reg]) { + sub_reg[data->reg] = + wm8350_reg_read(wm8350, WM8350_INT_STATUS_1 + + data->reg); + sub_reg[data->reg] &= + ~wm8350_reg_read(wm8350, + WM8350_INT_STATUS_1_MASK + + data->reg); + read_done[data->reg] = 1; + } + + if (sub_reg[data->reg] & data->mask) + wm8350_irq_call_handler(wm8350, i); + } + + return IRQ_HANDLED; +} + +int wm8350_register_irq(struct wm8350 *wm8350, int irq, + irq_handler_t handler, unsigned long flags, + const char *name, void *data) +{ + if (irq < 0 || irq > WM8350_NUM_IRQ || !handler) + return -EINVAL; + + if (wm8350->irq[irq].handler) + return -EBUSY; + + mutex_lock(&wm8350->irq_mutex); + wm8350->irq[irq].handler = handler; + wm8350->irq[irq].data = data; + mutex_unlock(&wm8350->irq_mutex); + + wm8350_unmask_irq(wm8350, irq); + + return 0; +} +EXPORT_SYMBOL_GPL(wm8350_register_irq); + +int wm8350_free_irq(struct wm8350 *wm8350, int irq) +{ + if (irq < 0 || irq > WM8350_NUM_IRQ) + return -EINVAL; + + wm8350_mask_irq(wm8350, irq); + + mutex_lock(&wm8350->irq_mutex); + wm8350->irq[irq].handler = NULL; + mutex_unlock(&wm8350->irq_mutex); + return 0; +} +EXPORT_SYMBOL_GPL(wm8350_free_irq); + +int wm8350_mask_irq(struct wm8350 *wm8350, int irq) +{ + return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK + + wm8350_irqs[irq].reg, + wm8350_irqs[irq].mask); +} +EXPORT_SYMBOL_GPL(wm8350_mask_irq); + +int wm8350_unmask_irq(struct wm8350 *wm8350, int irq) +{ + return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK + + wm8350_irqs[irq].reg, + wm8350_irqs[irq].mask); +} +EXPORT_SYMBOL_GPL(wm8350_unmask_irq); + +int wm8350_irq_init(struct wm8350 *wm8350, int irq, + struct wm8350_platform_data *pdata) +{ + int ret; + int flags = IRQF_ONESHOT; + + if (!irq) { + dev_err(wm8350->dev, "No IRQ configured\n"); + return -EINVAL; + } + + wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF); + wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK, 0xFFFF); + wm8350_reg_write(wm8350, WM8350_INT_STATUS_2_MASK, 0xFFFF); + wm8350_reg_write(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, 0xFFFF); + wm8350_reg_write(wm8350, WM8350_GPIO_INT_STATUS_MASK, 0xFFFF); + wm8350_reg_write(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK, 0xFFFF); + + mutex_init(&wm8350->irq_mutex); + wm8350->chip_irq = irq; + + if (pdata && pdata->irq_high) { + flags |= IRQF_TRIGGER_HIGH; + + wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1, + WM8350_IRQ_POL); + } else { + flags |= IRQF_TRIGGER_LOW; + + wm8350_clear_bits(wm8350, WM8350_SYSTEM_CONTROL_1, + WM8350_IRQ_POL); + } + + ret = request_threaded_irq(irq, NULL, wm8350_irq, flags, + "wm8350", wm8350); + if (ret != 0) + dev_err(wm8350->dev, "Failed to request IRQ: %d\n", ret); + + return ret; +} + +int wm8350_irq_exit(struct wm8350 *wm8350) +{ + free_irq(wm8350->chip_irq, wm8350); + return 0; +} diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c index 7ccc1eab98ab51f01c750d8493fb01859836c17b..e965139e5cd5ba116369eedd05b72435621b6796 100644 --- a/drivers/mfd/wm8350-regmap.c +++ b/drivers/mfd/wm8350-regmap.c @@ -3170,14 +3170,6 @@ const u16 wm8352_mode3_defaults[] = { }; #endif -/* The register defaults for the config mode used must be compiled in but - * due to the impact on kernel size it is possible to disable - */ -#ifndef WM8350_HAVE_CONFIG_MODE -#warning No WM8350 config modes supported - select at least one of the -#warning MFD_WM8350_CONFIG_MODE_n options from the board driver. -#endif - /* * Access masks. */ diff --git a/drivers/misc/hpilo.h b/drivers/misc/hpilo.h index 38576050776ad459f84800bf11453be5731f5c13..247eb386a9732d4fef9af461976958ef7866ee37 100644 --- a/drivers/misc/hpilo.h +++ b/drivers/misc/hpilo.h @@ -44,9 +44,20 @@ struct ilo_hwinfo { struct pci_dev *ilo_dev; + /* + * open_lock serializes ccb_cnt during open and close + * [ irq disabled ] + * -> alloc_lock used when adding/removing/searching ccb_alloc, + * which represents all ccbs open on the device + * --> fifo_lock controls access to fifo queues shared with hw + * + * Locks must be taken in this order, but open_lock and alloc_lock + * are optional, they do not need to be held in order to take a + * lower level lock. + */ + spinlock_t open_lock; spinlock_t alloc_lock; spinlock_t fifo_lock; - spinlock_t open_lock; struct cdev cdev; }; diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index e4ff50b95a5ee8c5f834ab17f4834795108eaa8f..fcb6ec1af173dfe22e3130ef6016f348c3f24858 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c @@ -712,6 +712,12 @@ static int run_simple_test(int is_get_char, int chr) /* End of packet == #XX so look for the '#' */ if (put_buf_cnt > 3 && put_buf[put_buf_cnt - 3] == '#') { + if (put_buf_cnt >= BUFMAX) { + eprintk("kgdbts: ERROR: put buffer overflow on" + " '%s' line %i\n", ts.name, ts.idx); + put_buf_cnt = 0; + return 0; + } put_buf[put_buf_cnt] = '\0'; v2printk("put%i: %s\n", ts.idx, put_buf); /* Trigger check here */ @@ -885,16 +891,16 @@ static void kgdbts_run_tests(void) int nmi_sleep = 0; int i; - ptr = strstr(config, "F"); + ptr = strchr(config, 'F'); if (ptr) fork_test = simple_strtol(ptr + 1, NULL, 10); - ptr = strstr(config, "S"); + ptr = strchr(config, 'S'); if (ptr) do_sys_open_test = simple_strtol(ptr + 1, NULL, 10); - ptr = strstr(config, "N"); + ptr = strchr(config, 'N'); if (ptr) nmi_sleep = simple_strtol(ptr+1, NULL, 10); - ptr = strstr(config, "I"); + ptr = strchr(config, 'I'); if (ptr) sstep_test = simple_strtol(ptr+1, NULL, 10); diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index b8e7c5ae981e5e1e7414444452120705140b6943..f53755533e7e2e05b4343850ed544b10c0429df6 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -73,11 +74,10 @@ struct uart_icount { }; struct sdio_uart_port { + struct tty_port port; struct kref kref; struct tty_struct *tty; unsigned int index; - unsigned int opened; - struct mutex open_lock; struct sdio_func *func; struct mutex func_lock; struct task_struct *in_sdio_uart_irq; @@ -87,6 +87,7 @@ struct sdio_uart_port { struct uart_icount icount; unsigned int uartclk; unsigned int mctrl; + unsigned int rx_mctrl; unsigned int read_status_mask; unsigned int ignore_status_mask; unsigned char x_char; @@ -102,7 +103,6 @@ static int sdio_uart_add_port(struct sdio_uart_port *port) int index, ret = -EBUSY; kref_init(&port->kref); - mutex_init(&port->open_lock); mutex_init(&port->func_lock); spin_lock_init(&port->write_lock); @@ -151,6 +151,7 @@ static void sdio_uart_port_put(struct sdio_uart_port *port) static void sdio_uart_port_remove(struct sdio_uart_port *port) { struct sdio_func *func; + struct tty_struct *tty; BUG_ON(sdio_uart_table[port->index] != port); @@ -165,15 +166,19 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port) * give up on that port ASAP. * Beware: the lock ordering is critical. */ - mutex_lock(&port->open_lock); + mutex_lock(&port->port.mutex); mutex_lock(&port->func_lock); func = port->func; sdio_claim_host(func); port->func = NULL; mutex_unlock(&port->func_lock); - if (port->opened) - tty_hangup(port->tty); - mutex_unlock(&port->open_lock); + tty = tty_port_tty_get(&port->port); + /* tty_hangup is async so is this safe as is ?? */ + if (tty) { + tty_hangup(tty); + tty_kref_put(tty); + } + mutex_unlock(&port->port.mutex); sdio_release_irq(func); sdio_disable_func(func); sdio_release_host(func); @@ -217,6 +222,8 @@ static unsigned int sdio_uart_get_mctrl(struct sdio_uart_port *port) unsigned char status; unsigned int ret; + /* FIXME: What stops this losing the delta bits and breaking + sdio_uart_check_modem_status ? */ status = sdio_in(port, UART_MSR); ret = 0; @@ -391,7 +398,7 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port) static void sdio_uart_receive_chars(struct sdio_uart_port *port, unsigned int *status) { - struct tty_struct *tty = port->tty; + struct tty_struct *tty = tty_port_tty_get(&port->port); unsigned int ch, flag; int max_count = 256; @@ -428,24 +435,30 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port, } if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0) - tty_insert_flip_char(tty, ch, flag); + if (tty) + tty_insert_flip_char(tty, ch, flag); /* * Overrun is special. Since it's reported immediately, * it doesn't affect the current character. */ if (*status & ~port->ignore_status_mask & UART_LSR_OE) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + if (tty) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); *status = sdio_in(port, UART_LSR); } while ((*status & UART_LSR_DR) && (max_count-- > 0)); - tty_flip_buffer_push(tty); + if (tty) { + tty_flip_buffer_push(tty); + tty_kref_put(tty); + } } static void sdio_uart_transmit_chars(struct sdio_uart_port *port) { struct circ_buf *xmit = &port->xmit; int count; + struct tty_struct *tty; if (port->x_char) { sdio_out(port, UART_TX, port->x_char); @@ -453,8 +466,13 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port) port->x_char = 0; return; } - if (circ_empty(xmit) || port->tty->stopped || port->tty->hw_stopped) { + + tty = tty_port_tty_get(&port->port); + + if (tty == NULL || circ_empty(xmit) || + tty->stopped || tty->hw_stopped) { sdio_uart_stop_tx(port); + tty_kref_put(tty); return; } @@ -468,15 +486,17 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port) } while (--count > 0); if (circ_chars_pending(xmit) < WAKEUP_CHARS) - tty_wakeup(port->tty); + tty_wakeup(tty); if (circ_empty(xmit)) sdio_uart_stop_tx(port); + tty_kref_put(tty); } static void sdio_uart_check_modem_status(struct sdio_uart_port *port) { int status; + struct tty_struct *tty; status = sdio_in(port, UART_MSR); @@ -487,25 +507,39 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port) port->icount.rng++; if (status & UART_MSR_DDSR) port->icount.dsr++; - if (status & UART_MSR_DDCD) + if (status & UART_MSR_DDCD) { port->icount.dcd++; + /* DCD raise - wake for open */ + if (status & UART_MSR_DCD) + wake_up_interruptible(&port->port.open_wait); + else { + /* DCD drop - hang up if tty attached */ + tty = tty_port_tty_get(&port->port); + if (tty) { + tty_hangup(tty); + tty_kref_put(tty); + } + } + } if (status & UART_MSR_DCTS) { port->icount.cts++; - if (port->tty->termios->c_cflag & CRTSCTS) { + tty = tty_port_tty_get(&port->port); + if (tty && (tty->termios->c_cflag & CRTSCTS)) { int cts = (status & UART_MSR_CTS); - if (port->tty->hw_stopped) { + if (tty->hw_stopped) { if (cts) { - port->tty->hw_stopped = 0; + tty->hw_stopped = 0; sdio_uart_start_tx(port); - tty_wakeup(port->tty); + tty_wakeup(tty); } } else { if (!cts) { - port->tty->hw_stopped = 1; + tty->hw_stopped = 1; sdio_uart_stop_tx(port); } } } + tty_kref_put(tty); } } @@ -542,8 +576,62 @@ static void sdio_uart_irq(struct sdio_func *func) port->in_sdio_uart_irq = NULL; } -static int sdio_uart_startup(struct sdio_uart_port *port) +static int uart_carrier_raised(struct tty_port *tport) +{ + struct sdio_uart_port *port = + container_of(tport, struct sdio_uart_port, port); + unsigned int ret = sdio_uart_claim_func(port); + if (ret) /* Missing hardware shoudn't block for carrier */ + return 1; + ret = sdio_uart_get_mctrl(port); + sdio_uart_release_func(port); + if (ret & TIOCM_CAR) + return 1; + return 0; +} + +/** + * uart_dtr_rts - port helper to set uart signals + * @tport: tty port to be updated + * @onoff: set to turn on DTR/RTS + * + * Called by the tty port helpers when the modem signals need to be + * adjusted during an open, close and hangup. + */ + +static void uart_dtr_rts(struct tty_port *tport, int onoff) +{ + struct sdio_uart_port *port = + container_of(tport, struct sdio_uart_port, port); + int ret = sdio_uart_claim_func(port); + if (ret) + return; + if (onoff == 0) + sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); + else + sdio_uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS); + sdio_uart_release_func(port); +} + +/** + * sdio_uart_activate - start up hardware + * @tport: tty port to activate + * @tty: tty bound to this port + * + * Activate a tty port. The port locking guarantees us this will be + * run exactly once per set of opens, and if successful will see the + * shutdown method run exactly once to match. Start up and shutdown are + * protected from each other by the internal locking and will not run + * at the same time even during a hangup event. + * + * If we successfully start up the port we take an extra kref as we + * will keep it around until shutdown when the kref is dropped. + */ + +static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) { + struct sdio_uart_port *port = + container_of(tport, struct sdio_uart_port, port); unsigned long page; int ret; @@ -551,7 +639,7 @@ static int sdio_uart_startup(struct sdio_uart_port *port) * Set the TTY IO error marker - we will only clear this * once we have successfully opened the port. */ - set_bit(TTY_IO_ERROR, &port->tty->flags); + set_bit(TTY_IO_ERROR, &tty->flags); /* Initialise and allocate the transmit buffer. */ page = __get_free_page(GFP_KERNEL); @@ -592,19 +680,19 @@ static int sdio_uart_startup(struct sdio_uart_port *port) */ sdio_out(port, UART_LCR, UART_LCR_WLEN8); - port->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE; + port->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE; port->mctrl = TIOCM_OUT2; - sdio_uart_change_speed(port, port->tty->termios, NULL); + sdio_uart_change_speed(port, tty->termios, NULL); - if (port->tty->termios->c_cflag & CBAUD) + if (tty->termios->c_cflag & CBAUD) sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); - if (port->tty->termios->c_cflag & CRTSCTS) + if (tty->termios->c_cflag & CRTSCTS) if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) - port->tty->hw_stopped = 1; + tty->hw_stopped = 1; - clear_bit(TTY_IO_ERROR, &port->tty->flags); + clear_bit(TTY_IO_ERROR, &tty->flags); /* Kick the IRQ handler once while we're still holding the host lock */ sdio_uart_irq(port->func); @@ -621,8 +709,20 @@ err1: return ret; } -static void sdio_uart_shutdown(struct sdio_uart_port *port) +/** + * sdio_uart_shutdown - stop hardware + * @tport: tty port to shut down + * + * Deactivate a tty port. The port locking guarantees us this will be + * run only if a successful matching activate already ran. The two are + * protected from each other by the internal locking and will not run + * at the same time even during a hangup event. + */ + +static void sdio_uart_shutdown(struct tty_port *tport) { + struct sdio_uart_port *port = + container_of(tport, struct sdio_uart_port, port); int ret; ret = sdio_uart_claim_func(port); @@ -631,12 +731,6 @@ static void sdio_uart_shutdown(struct sdio_uart_port *port) sdio_uart_stop_rx(port); - /* TODO: wait here for TX FIFO to drain */ - - /* Turn off DTR and RTS early. */ - if (port->tty->termios->c_cflag & HUPCL) - sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); - /* Disable interrupts from this port */ sdio_release_irq(port->func); port->ier = 0; @@ -661,77 +755,70 @@ skip: free_page((unsigned long)port->xmit.buf); } -static int sdio_uart_open(struct tty_struct *tty, struct file *filp) +/** + * sdio_uart_install - install method + * @driver: the driver in use (sdio_uart in our case) + * @tty: the tty being bound + * + * Look up and bind the tty and the driver together. Initialize + * any needed private data (in our case the termios) + */ + +static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty) { - struct sdio_uart_port *port; - int ret; + int idx = tty->index; + struct sdio_uart_port *port = sdio_uart_port_get(idx); + int ret = tty_init_termios(tty); + + if (ret == 0) { + tty_driver_kref_get(driver); + tty->count++; + /* This is the ref sdio_uart_port get provided */ + tty->driver_data = port; + driver->ttys[idx] = tty; + } else + sdio_uart_port_put(port); + return ret; +} - port = sdio_uart_port_get(tty->index); - if (!port) - return -ENODEV; +/** + * sdio_uart_cleanup - called on the last tty kref drop + * @tty: the tty being destroyed + * + * Called asynchronously when the last reference to the tty is dropped. + * We cannot destroy the tty->driver_data port kref until this point + */ - mutex_lock(&port->open_lock); +static void sdio_uart_cleanup(struct tty_struct *tty) +{ + struct sdio_uart_port *port = tty->driver_data; + tty->driver_data = NULL; /* Bug trap */ + sdio_uart_port_put(port); +} - /* - * Make sure not to mess up with a dead port - * which has not been closed yet. - */ - if (tty->driver_data && tty->driver_data != port) { - mutex_unlock(&port->open_lock); - sdio_uart_port_put(port); - return -EBUSY; - } +/* + * Open/close/hangup is now entirely boilerplate + */ - if (!port->opened) { - tty->driver_data = port; - port->tty = tty; - ret = sdio_uart_startup(port); - if (ret) { - tty->driver_data = NULL; - port->tty = NULL; - mutex_unlock(&port->open_lock); - sdio_uart_port_put(port); - return ret; - } - } - port->opened++; - mutex_unlock(&port->open_lock); - return 0; +static int sdio_uart_open(struct tty_struct *tty, struct file *filp) +{ + struct sdio_uart_port *port = tty->driver_data; + return tty_port_open(&port->port, tty, filp); } static void sdio_uart_close(struct tty_struct *tty, struct file * filp) { struct sdio_uart_port *port = tty->driver_data; + tty_port_close(&port->port, tty, filp); +} - if (!port) - return; - - mutex_lock(&port->open_lock); - BUG_ON(!port->opened); - - /* - * This is messy. The tty layer calls us even when open() - * returned an error. Ignore this close request if tty->count - * is larger than port->count. - */ - if (tty->count > port->opened) { - mutex_unlock(&port->open_lock); - return; - } - - if (--port->opened == 0) { - tty->closing = 1; - sdio_uart_shutdown(port); - tty_ldisc_flush(tty); - port->tty = NULL; - tty->driver_data = NULL; - tty->closing = 0; - } - mutex_unlock(&port->open_lock); - sdio_uart_port_put(port); +static void sdio_uart_hangup(struct tty_struct *tty) +{ + struct sdio_uart_port *port = tty->driver_data; + tty_port_hangup(&port->port); } -static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf, +static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct sdio_uart_port *port = tty->driver_data; @@ -756,7 +843,7 @@ static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf, } spin_unlock(&port->write_lock); - if ( !(port->ier & UART_IER_THRI)) { + if (!(port->ier & UART_IER_THRI)) { int err = sdio_uart_claim_func(port); if (!err) { sdio_uart_start_tx(port); @@ -843,17 +930,12 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) sdio_uart_release_func(port); } -static void sdio_uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios) +static void sdio_uart_set_termios(struct tty_struct *tty, + struct ktermios *old_termios) { struct sdio_uart_port *port = tty->driver_data; unsigned int cflag = tty->termios->c_cflag; -#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - - if ((cflag ^ old_termios->c_cflag) == 0 && - RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) - return; - if (sdio_uart_claim_func(port) != 0) return; @@ -928,7 +1010,7 @@ static int sdio_uart_tiocmset(struct tty_struct *tty, struct file *file, int result; result = sdio_uart_claim_func(port); - if(!result) { + if (!result) { sdio_uart_update_mctrl(port, set, clear); sdio_uart_release_func(port); } @@ -946,7 +1028,7 @@ static int sdio_uart_proc_show(struct seq_file *m, void *v) struct sdio_uart_port *port = sdio_uart_port_get(i); if (port) { seq_printf(m, "%d: uart:SDIO", i); - if(capable(CAP_SYS_ADMIN)) { + if (capable(CAP_SYS_ADMIN)) { seq_printf(m, " tx:%d rx:%d", port->icount.tx, port->icount.rx); if (port->icount.frame) @@ -994,6 +1076,13 @@ static const struct file_operations sdio_uart_proc_fops = { .release = single_release, }; +static const struct tty_port_operations sdio_uart_port_ops = { + .dtr_rts = uart_dtr_rts, + .carrier_raised = uart_carrier_raised, + .shutdown = sdio_uart_shutdown, + .activate = sdio_uart_activate, +}; + static const struct tty_operations sdio_uart_ops = { .open = sdio_uart_open, .close = sdio_uart_close, @@ -1004,9 +1093,12 @@ static const struct tty_operations sdio_uart_ops = { .throttle = sdio_uart_throttle, .unthrottle = sdio_uart_unthrottle, .set_termios = sdio_uart_set_termios, + .hangup = sdio_uart_hangup, .break_ctl = sdio_uart_break_ctl, .tiocmget = sdio_uart_tiocmget, .tiocmset = sdio_uart_tiocmset, + .install = sdio_uart_install, + .cleanup = sdio_uart_cleanup, .proc_fops = &sdio_uart_proc_fops, }; @@ -1043,7 +1135,7 @@ static int sdio_uart_probe(struct sdio_func *func, } if (!tpl) { printk(KERN_WARNING - "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n", + "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n", sdio_func_id(func)); kfree(port); return -EINVAL; @@ -1068,13 +1160,16 @@ static int sdio_uart_probe(struct sdio_func *func, port->func = func; sdio_set_drvdata(func, port); + tty_port_init(&port->port); + port->port.ops = &sdio_uart_port_ops; ret = sdio_uart_add_port(port); if (ret) { kfree(port); } else { struct device *dev; - dev = tty_register_device(sdio_uart_tty_driver, port->index, &func->dev); + dev = tty_register_device(sdio_uart_tty_driver, + port->index, &func->dev); if (IS_ERR(dev)) { sdio_uart_port_remove(port); ret = PTR_ERR(dev); diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index dba4600bcdb458e6bd115ef0b1bc30a03a8e6ac7..b31946e0b4ca7ee72224f7e1f880384279d83914 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c @@ -38,10 +38,9 @@ #include #include -#include +#include #include #include -#include #include "msm_sdcc.h" @@ -775,13 +774,11 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) switch (ios->power_mode) { case MMC_POWER_OFF: - htc_pwrsink_set(PWRSINK_SDCARD, 0); break; case MMC_POWER_UP: pwr |= MCI_PWR_UP; break; case MMC_POWER_ON: - htc_pwrsink_set(PWRSINK_SDCARD, 100); pwr |= MCI_PWR_ON; break; } diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index 0c44d560bf1ab7755eda9f16e86875b545e875fd..0c7a63c1f12f4c9aeed7679b28da66e1a5f9a9b8 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c @@ -22,6 +22,8 @@ #include #include +MODULE_LICENSE("GPL"); + enum { CD_GPIO = 0, WP_GPIO, diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 88a72e9c8beb1085b6d4a811b5b2fa965a954653..277786ebaa2cc39ff7b1e669cbc4b2927014803c 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -22,6 +22,8 @@ #include #include +#include +#include #include #include "ubi.h" @@ -279,6 +281,44 @@ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name, } EXPORT_SYMBOL_GPL(ubi_open_volume_nm); +/** + * ubi_open_volume_path - open UBI volume by its character device node path. + * @pathname: volume character device node path + * @mode: open mode + * + * This function is similar to 'ubi_open_volume()', but opens a volume the path + * to its character device node. + */ +struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) +{ + int error, ubi_num, vol_id; + struct ubi_volume_desc *ret; + struct inode *inode; + struct path path; + + dbg_gen("open volume %s, mode %d", pathname, mode); + + if (!pathname || !*pathname) + return ERR_PTR(-EINVAL); + + error = kern_path(pathname, LOOKUP_FOLLOW, &path); + if (error) + return ERR_PTR(error); + + inode = path.dentry->d_inode; + ubi_num = ubi_major2num(imajor(inode)); + vol_id = iminor(inode) - 1; + + if (vol_id >= 0 && ubi_num >= 0) + ret = ubi_open_volume(ubi_num, vol_id, mode); + else + ret = ERR_PTR(-ENODEV); + + path_put(&path); + return ret; +} +EXPORT_SYMBOL_GPL(ubi_open_volume_path); + /** * ubi_close_volume - close UBI volume. * @desc: volume descriptor diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index 74fdc40c8627b84b4bf8ab89704176b3bcc22b72..c1d7b880c7953969a282969637b69f052a8454ed 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -147,12 +147,14 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, } if (bytes == 0) { + err = ubi_wl_flush(ubi); + if (err) + return err; + err = clear_update_marker(ubi, vol, 0); if (err) return err; - err = ubi_wl_flush(ubi); - if (!err) - vol->updating = 0; + vol->updating = 0; } vol->upd_buf = vmalloc(ubi->leb_size); @@ -362,16 +364,16 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, ubi_assert(vol->upd_received <= vol->upd_bytes); if (vol->upd_received == vol->upd_bytes) { + err = ubi_wl_flush(ubi); + if (err) + return err; /* The update is finished, clear the update marker */ err = clear_update_marker(ubi, vol, vol->upd_bytes); if (err) return err; - err = ubi_wl_flush(ubi); - if (err == 0) { - vol->updating = 0; - err = to_write; - vfree(vol->upd_buf); - } + vol->updating = 0; + err = to_write; + vfree(vol->upd_buf); } return err; diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 0bbd5ae498628e6278f33013091b279552450562..a5be9ac6405cfa27fcc918ae888fadd487902f40 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2696,6 +2696,7 @@ config NETXEN_NIC config NIU tristate "Sun Neptune 10Gbit Ethernet support" depends on PCI + select CRC32 help This enables support for cards based upon Sun's Neptune chipset. diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 691b81eb0f467d0aa39788aa4efb97206b776eb0..c3dfbdd2cdcfac499c44b46e85c015b4b9b0b9c2 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -322,7 +322,7 @@ static int ixp4xx_mdio_write(struct mii_bus *bus, int phy_id, int location, ret = ixp4xx_mdio_cmd(bus, phy_id, location, 1, val); spin_unlock_irqrestore(&mdio_lock, flags); #if DEBUG_MDIO - printk(KERN_DEBUG "%s #%i: MII read [%i] <- 0x%X, err = %i\n", + printk(KERN_DEBUG "%s #%i: MII write [%i] <- 0x%X, err = %i\n", bus->name, phy_id, location, val, ret); #endif return ret; diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h index a348a22551d9744d30e606bbeed3f65a5cba542e..efe5435bc3d3f9df920e3e20ea45985bac040a76 100644 --- a/drivers/net/atl1c/atl1c.h +++ b/drivers/net/atl1c/atl1c.h @@ -479,6 +479,9 @@ struct atl1c_buffer { #define ATL1C_PCIMAP_PAGE 0x0008 #define ATL1C_PCIMAP_TYPE_MASK 0x000C +#define ATL1C_PCIMAP_TODEVICE 0x0010 +#define ATL1C_PCIMAP_FROMDEVICE 0x0020 +#define ATL1C_PCIMAP_DIRECTION_MASK 0x0030 dma_addr_t dma; }; @@ -487,9 +490,11 @@ struct atl1c_buffer { ((buff)->flags) |= (state); \ } while (0) -#define ATL1C_SET_PCIMAP_TYPE(buff, type) do { \ - ((buff)->flags) &= ~ATL1C_PCIMAP_TYPE_MASK; \ - ((buff)->flags) |= (type); \ +#define ATL1C_SET_PCIMAP_TYPE(buff, type, direction) do { \ + ((buff)->flags) &= ~ATL1C_PCIMAP_TYPE_MASK; \ + ((buff)->flags) |= (type); \ + ((buff)->flags) &= ~ATL1C_PCIMAP_DIRECTION_MASK; \ + ((buff)->flags) |= (direction); \ } while (0) /* transimit packet descriptor (tpd) ring */ @@ -550,6 +555,9 @@ struct atl1c_adapter { #define __AT_TESTING 0x0001 #define __AT_RESETTING 0x0002 #define __AT_DOWN 0x0003 + u8 work_event; +#define ATL1C_WORK_EVENT_RESET 0x01 +#define ATL1C_WORK_EVENT_LINK_CHANGE 0x02 u32 msg_enable; bool have_msi; @@ -561,8 +569,7 @@ struct atl1c_adapter { spinlock_t tx_lock; atomic_t irq_sem; - struct work_struct reset_task; - struct work_struct link_chg_task; + struct work_struct common_task; struct timer_list watchdog_timer; struct timer_list phy_config_timer; diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 6eb9241cee0ae08c361b0533775239c9f1523eb1..2f4be59b9c0bfd29c8efd838f8b6da1ec03f5eb0 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -198,27 +198,12 @@ static void atl1c_phy_config(unsigned long data) void atl1c_reinit_locked(struct atl1c_adapter *adapter) { - WARN_ON(in_interrupt()); atl1c_down(adapter); atl1c_up(adapter); clear_bit(__AT_RESETTING, &adapter->flags); } -static void atl1c_reset_task(struct work_struct *work) -{ - struct atl1c_adapter *adapter; - struct net_device *netdev; - - adapter = container_of(work, struct atl1c_adapter, reset_task); - netdev = adapter->netdev; - - netif_device_detach(netdev); - atl1c_down(adapter); - atl1c_up(adapter); - netif_device_attach(netdev); -} - static void atl1c_check_link_status(struct atl1c_adapter *adapter) { struct atl1c_hw *hw = &adapter->hw; @@ -275,18 +260,6 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) } } -/* - * atl1c_link_chg_task - deal with link change event Out of interrupt context - * @netdev: network interface device structure - */ -static void atl1c_link_chg_task(struct work_struct *work) -{ - struct atl1c_adapter *adapter; - - adapter = container_of(work, struct atl1c_adapter, link_chg_task); - atl1c_check_link_status(adapter); -} - static void atl1c_link_chg_event(struct atl1c_adapter *adapter) { struct net_device *netdev = adapter->netdev; @@ -311,20 +284,40 @@ static void atl1c_link_chg_event(struct atl1c_adapter *adapter) adapter->link_speed = SPEED_0; } } - schedule_work(&adapter->link_chg_task); + + adapter->work_event |= ATL1C_WORK_EVENT_LINK_CHANGE; + schedule_work(&adapter->common_task); } -static void atl1c_del_timer(struct atl1c_adapter *adapter) +static void atl1c_common_task(struct work_struct *work) { - del_timer_sync(&adapter->phy_config_timer); + struct atl1c_adapter *adapter; + struct net_device *netdev; + + adapter = container_of(work, struct atl1c_adapter, common_task); + netdev = adapter->netdev; + + if (adapter->work_event & ATL1C_WORK_EVENT_RESET) { + netif_device_detach(netdev); + atl1c_down(adapter); + atl1c_up(adapter); + netif_device_attach(netdev); + return; + } + + if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE) + atl1c_check_link_status(adapter); + + return; } -static void atl1c_cancel_work(struct atl1c_adapter *adapter) + +static void atl1c_del_timer(struct atl1c_adapter *adapter) { - cancel_work_sync(&adapter->reset_task); - cancel_work_sync(&adapter->link_chg_task); + del_timer_sync(&adapter->phy_config_timer); } + /* * atl1c_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure @@ -334,7 +327,8 @@ static void atl1c_tx_timeout(struct net_device *netdev) struct atl1c_adapter *adapter = netdev_priv(netdev); /* Do the reset outside of interrupt context */ - schedule_work(&adapter->reset_task); + adapter->work_event |= ATL1C_WORK_EVENT_RESET; + schedule_work(&adapter->common_task); } /* @@ -713,15 +707,21 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) static inline void atl1c_clean_buffer(struct pci_dev *pdev, struct atl1c_buffer *buffer_info, int in_irq) { + u16 pci_driection; if (buffer_info->flags & ATL1C_BUFFER_FREE) return; if (buffer_info->dma) { + if (buffer_info->flags & ATL1C_PCIMAP_FROMDEVICE) + pci_driection = PCI_DMA_FROMDEVICE; + else + pci_driection = PCI_DMA_TODEVICE; + if (buffer_info->flags & ATL1C_PCIMAP_SINGLE) pci_unmap_single(pdev, buffer_info->dma, - buffer_info->length, PCI_DMA_TODEVICE); + buffer_info->length, pci_driection); else if (buffer_info->flags & ATL1C_PCIMAP_PAGE) pci_unmap_page(pdev, buffer_info->dma, - buffer_info->length, PCI_DMA_TODEVICE); + buffer_info->length, pci_driection); } if (buffer_info->skb) { if (in_irq) @@ -1533,7 +1533,8 @@ static irqreturn_t atl1c_intr(int irq, void *data) /* reset MAC */ hw->intr_mask &= ~ISR_ERROR; AT_WRITE_REG(hw, REG_IMR, hw->intr_mask); - schedule_work(&adapter->reset_task); + adapter->work_event |= ATL1C_WORK_EVENT_RESET; + schedule_work(&adapter->common_task); break; } @@ -1606,7 +1607,8 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid buffer_info->dma = pci_map_single(pdev, vir_addr, buffer_info->length, PCI_DMA_FROMDEVICE); - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE); + ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, + ATL1C_PCIMAP_FROMDEVICE); rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); rfd_next_to_use = next_next; if (++next_next == rfd_ring->count) @@ -1967,7 +1969,8 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter, buffer_info->dma = pci_map_single(adapter->pdev, skb->data, hdr_len, PCI_DMA_TODEVICE); ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE); + ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, + ATL1C_PCIMAP_TODEVICE); mapped_len += map_len; use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); use_tpd->buffer_len = cpu_to_le16(buffer_info->length); @@ -1988,7 +1991,8 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter, pci_map_single(adapter->pdev, skb->data + mapped_len, buffer_info->length, PCI_DMA_TODEVICE); ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE); + ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, + ATL1C_PCIMAP_TODEVICE); use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); use_tpd->buffer_len = cpu_to_le16(buffer_info->length); } @@ -2009,7 +2013,8 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter, buffer_info->length, PCI_DMA_TODEVICE); ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE); + ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE, + ATL1C_PCIMAP_TODEVICE); use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); use_tpd->buffer_len = cpu_to_le16(buffer_info->length); } @@ -2198,8 +2203,7 @@ void atl1c_down(struct atl1c_adapter *adapter) struct net_device *netdev = adapter->netdev; atl1c_del_timer(adapter); - atl1c_cancel_work(adapter); - + adapter->work_event = 0; /* clear all event */ /* signal that we're down so the interrupt handler does not * reschedule our watchdog timer */ set_bit(__AT_DOWN, &adapter->flags); @@ -2599,8 +2603,8 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]); atl1c_hw_set_mac_addr(&adapter->hw); - INIT_WORK(&adapter->reset_task, atl1c_reset_task); - INIT_WORK(&adapter->link_chg_task, atl1c_link_chg_task); + INIT_WORK(&adapter->common_task, atl1c_common_task); + adapter->work_event = 0; err = register_netdev(netdev); if (err) { dev_err(&pdev->dev, "register netdevice failed\n"); diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 2a9132343b66135fb2487c30a20ba6ce0db786ec..4869adb695865a3f7dc4ff3bacd1ee5a260b296d 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1505,8 +1505,7 @@ static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset) for (k = 0; k< ethaddr_bytes; k++) { ppattern[offset + magicsync + (j * ETH_ALEN) + k] = macaddr[k]; - len++; - set_bit(len, (unsigned long *) pmask); + set_bit(len++, (unsigned long *) pmask); } } return len - 1; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 24c7d9900baab5c053ac274255af4d5ae1fe166b..3a1f7902c16df0b51ad3be1803e92b3d2b23bb6c 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -759,7 +759,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, /* vlanf could be wrongly set in some cards. * ignore if vtm is not set */ - if ((adapter->cap == 0x400) && !vtm) + if ((adapter->cap & 0x400) && !vtm) vlanf = 0; skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN); @@ -816,7 +816,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, /* vlanf could be wrongly set in some cards. * ignore if vtm is not set */ - if ((adapter->cap == 0x400) && !vtm) + if ((adapter->cap & 0x400) && !vtm) vlanf = 0; skb = napi_get_frags(&eq_obj->napi); diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index bb803fa1e6a7ccc00d841dbf1d536bf19bd35f58..8c485aad1b94007ca98ff8cc6db39ba2f19f44f8 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -54,6 +54,15 @@ config CAN_MCP251X ---help--- Driver for the Microchip MCP251x SPI CAN controllers. +config CAN_BFIN + depends on CAN_DEV && (BF534 || BF536 || BF537 || BF538 || BF539 || BF54x) + tristate "Analog Devices Blackfin on-chip CAN" + ---help--- + Driver for the Analog Devices Blackfin on-chip CAN controllers + + To compile this driver as a module, choose M here: the + module will be called bfin_can. + source "drivers/net/can/mscan/Kconfig" source "drivers/net/can/sja1000/Kconfig" diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile index 56899fef1c6a2f219f30856bef8735638cde5621..7a702f28d01c8e1990b67f8ab9f63e920a02b10c 100644 --- a/drivers/net/can/Makefile +++ b/drivers/net/can/Makefile @@ -14,5 +14,6 @@ obj-$(CONFIG_CAN_MSCAN) += mscan/ obj-$(CONFIG_CAN_AT91) += at91_can.o obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o obj-$(CONFIG_CAN_MCP251X) += mcp251x.o +obj-$(CONFIG_CAN_BFIN) += bfin_can.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c new file mode 100644 index 0000000000000000000000000000000000000000..c7fc1de28173527157711881666067fc20cb996b --- /dev/null +++ b/drivers/net/can/bfin_can.c @@ -0,0 +1,783 @@ +/* + * Blackfin On-Chip CAN Driver + * + * Copyright 2004-2009 Analog Devices Inc. + * + * Enter bugs at http://blackfin.uclinux.org/ + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define DRV_NAME "bfin_can" +#define BFIN_CAN_TIMEOUT 100 + +/* + * transmit and receive channels + */ +#define TRANSMIT_CHL 24 +#define RECEIVE_STD_CHL 0 +#define RECEIVE_EXT_CHL 4 +#define RECEIVE_RTR_CHL 8 +#define RECEIVE_EXT_RTR_CHL 12 +#define MAX_CHL_NUMBER 32 + +/* + * bfin can registers layout + */ +struct bfin_can_mask_regs { + u16 aml; + u16 dummy1; + u16 amh; + u16 dummy2; +}; + +struct bfin_can_channel_regs { + u16 data[8]; + u16 dlc; + u16 dummy1; + u16 tsv; + u16 dummy2; + u16 id0; + u16 dummy3; + u16 id1; + u16 dummy4; +}; + +struct bfin_can_regs { + /* + * global control and status registers + */ + u16 mc1; /* offset 0 */ + u16 dummy1; + u16 md1; /* offset 4 */ + u16 rsv1[13]; + u16 mbtif1; /* offset 0x20 */ + u16 dummy2; + u16 mbrif1; /* offset 0x24 */ + u16 dummy3; + u16 mbim1; /* offset 0x28 */ + u16 rsv2[11]; + u16 mc2; /* offset 0x40 */ + u16 dummy4; + u16 md2; /* offset 0x44 */ + u16 dummy5; + u16 trs2; /* offset 0x48 */ + u16 rsv3[11]; + u16 mbtif2; /* offset 0x60 */ + u16 dummy6; + u16 mbrif2; /* offset 0x64 */ + u16 dummy7; + u16 mbim2; /* offset 0x68 */ + u16 rsv4[11]; + u16 clk; /* offset 0x80 */ + u16 dummy8; + u16 timing; /* offset 0x84 */ + u16 rsv5[3]; + u16 status; /* offset 0x8c */ + u16 dummy9; + u16 cec; /* offset 0x90 */ + u16 dummy10; + u16 gis; /* offset 0x94 */ + u16 dummy11; + u16 gim; /* offset 0x98 */ + u16 rsv6[3]; + u16 ctrl; /* offset 0xa0 */ + u16 dummy12; + u16 intr; /* offset 0xa4 */ + u16 rsv7[7]; + u16 esr; /* offset 0xb4 */ + u16 rsv8[37]; + + /* + * channel(mailbox) mask and message registers + */ + struct bfin_can_mask_regs msk[MAX_CHL_NUMBER]; /* offset 0x100 */ + struct bfin_can_channel_regs chl[MAX_CHL_NUMBER]; /* offset 0x200 */ +}; + +/* + * bfin can private data + */ +struct bfin_can_priv { + struct can_priv can; /* must be the first member */ + struct net_device *dev; + void __iomem *membase; + int rx_irq; + int tx_irq; + int err_irq; + unsigned short *pin_list; +}; + +/* + * bfin can timing parameters + */ +static struct can_bittiming_const bfin_can_bittiming_const = { + .name = DRV_NAME, + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + /* + * Although the BRP field can be set to any value, it is recommended + * that the value be greater than or equal to 4, as restrictions + * apply to the bit timing configuration when BRP is less than 4. + */ + .brp_min = 4, + .brp_max = 1024, + .brp_inc = 1, +}; + +static int bfin_can_set_bittiming(struct net_device *dev) +{ + struct bfin_can_priv *priv = netdev_priv(dev); + struct bfin_can_regs __iomem *reg = priv->membase; + struct can_bittiming *bt = &priv->can.bittiming; + u16 clk, timing; + + clk = bt->brp - 1; + timing = ((bt->sjw - 1) << 8) | (bt->prop_seg + bt->phase_seg1 - 1) | + ((bt->phase_seg2 - 1) << 4); + + /* + * If the SAM bit is set, the input signal is oversampled three times + * at the SCLK rate. + */ + if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) + timing |= SAM; + + bfin_write16(®->clk, clk); + bfin_write16(®->timing, timing); + + dev_info(dev->dev.parent, "setting CLOCK=0x%04x TIMING=0x%04x\n", + clk, timing); + + return 0; +} + +static void bfin_can_set_reset_mode(struct net_device *dev) +{ + struct bfin_can_priv *priv = netdev_priv(dev); + struct bfin_can_regs __iomem *reg = priv->membase; + int timeout = BFIN_CAN_TIMEOUT; + int i; + + /* disable interrupts */ + bfin_write16(®->mbim1, 0); + bfin_write16(®->mbim2, 0); + bfin_write16(®->gim, 0); + + /* reset can and enter configuration mode */ + bfin_write16(®->ctrl, SRS | CCR); + SSYNC(); + bfin_write16(®->ctrl, CCR); + SSYNC(); + while (!(bfin_read16(®->ctrl) & CCA)) { + udelay(10); + if (--timeout == 0) { + dev_err(dev->dev.parent, + "fail to enter configuration mode\n"); + BUG(); + } + } + + /* + * All mailbox configurations are marked as inactive + * by writing to CAN Mailbox Configuration Registers 1 and 2 + * For all bits: 0 - Mailbox disabled, 1 - Mailbox enabled + */ + bfin_write16(®->mc1, 0); + bfin_write16(®->mc2, 0); + + /* Set Mailbox Direction */ + bfin_write16(®->md1, 0xFFFF); /* mailbox 1-16 are RX */ + bfin_write16(®->md2, 0); /* mailbox 17-32 are TX */ + + /* RECEIVE_STD_CHL */ + for (i = 0; i < 2; i++) { + bfin_write16(®->chl[RECEIVE_STD_CHL + i].id0, 0); + bfin_write16(®->chl[RECEIVE_STD_CHL + i].id1, AME); + bfin_write16(®->chl[RECEIVE_STD_CHL + i].dlc, 0); + bfin_write16(®->msk[RECEIVE_STD_CHL + i].amh, 0x1FFF); + bfin_write16(®->msk[RECEIVE_STD_CHL + i].aml, 0xFFFF); + } + + /* RECEIVE_EXT_CHL */ + for (i = 0; i < 2; i++) { + bfin_write16(®->chl[RECEIVE_EXT_CHL + i].id0, 0); + bfin_write16(®->chl[RECEIVE_EXT_CHL + i].id1, AME | IDE); + bfin_write16(®->chl[RECEIVE_EXT_CHL + i].dlc, 0); + bfin_write16(®->msk[RECEIVE_EXT_CHL + i].amh, 0x1FFF); + bfin_write16(®->msk[RECEIVE_EXT_CHL + i].aml, 0xFFFF); + } + + bfin_write16(®->mc2, BIT(TRANSMIT_CHL - 16)); + bfin_write16(®->mc1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL)); + SSYNC(); + + priv->can.state = CAN_STATE_STOPPED; +} + +static void bfin_can_set_normal_mode(struct net_device *dev) +{ + struct bfin_can_priv *priv = netdev_priv(dev); + struct bfin_can_regs __iomem *reg = priv->membase; + int timeout = BFIN_CAN_TIMEOUT; + + /* + * leave configuration mode + */ + bfin_write16(®->ctrl, bfin_read16(®->ctrl) & ~CCR); + + while (bfin_read16(®->status) & CCA) { + udelay(10); + if (--timeout == 0) { + dev_err(dev->dev.parent, + "fail to leave configuration mode\n"); + BUG(); + } + } + + /* + * clear _All_ tx and rx interrupts + */ + bfin_write16(®->mbtif1, 0xFFFF); + bfin_write16(®->mbtif2, 0xFFFF); + bfin_write16(®->mbrif1, 0xFFFF); + bfin_write16(®->mbrif2, 0xFFFF); + + /* + * clear global interrupt status register + */ + bfin_write16(®->gis, 0x7FF); /* overwrites with '1' */ + + /* + * Initialize Interrupts + * - set bits in the mailbox interrupt mask register + * - global interrupt mask + */ + bfin_write16(®->mbim1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL)); + bfin_write16(®->mbim2, BIT(TRANSMIT_CHL - 16)); + + bfin_write16(®->gim, EPIM | BOIM | RMLIM); + SSYNC(); +} + +static void bfin_can_start(struct net_device *dev) +{ + struct bfin_can_priv *priv = netdev_priv(dev); + + /* enter reset mode */ + if (priv->can.state != CAN_STATE_STOPPED) + bfin_can_set_reset_mode(dev); + + /* leave reset mode */ + bfin_can_set_normal_mode(dev); +} + +static int bfin_can_set_mode(struct net_device *dev, enum can_mode mode) +{ + switch (mode) { + case CAN_MODE_START: + bfin_can_start(dev); + if (netif_queue_stopped(dev)) + netif_wake_queue(dev); + break; + + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int bfin_can_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct bfin_can_priv *priv = netdev_priv(dev); + struct bfin_can_regs __iomem *reg = priv->membase; + struct can_frame *cf = (struct can_frame *)skb->data; + u8 dlc = cf->can_dlc; + canid_t id = cf->can_id; + u8 *data = cf->data; + u16 val; + int i; + + netif_stop_queue(dev); + + /* fill id */ + if (id & CAN_EFF_FLAG) { + bfin_write16(®->chl[TRANSMIT_CHL].id0, id); + if (id & CAN_RTR_FLAG) + writew(((id & 0x1FFF0000) >> 16) | IDE | AME | RTR, + ®->chl[TRANSMIT_CHL].id1); + else + writew(((id & 0x1FFF0000) >> 16) | IDE | AME, + ®->chl[TRANSMIT_CHL].id1); + + } else { + if (id & CAN_RTR_FLAG) + writew((id << 2) | AME | RTR, + ®->chl[TRANSMIT_CHL].id1); + else + bfin_write16(®->chl[TRANSMIT_CHL].id1, + (id << 2) | AME); + } + + /* fill payload */ + for (i = 0; i < 8; i += 2) { + val = ((7 - i) < dlc ? (data[7 - i]) : 0) + + ((6 - i) < dlc ? (data[6 - i] << 8) : 0); + bfin_write16(®->chl[TRANSMIT_CHL].data[i], val); + } + + /* fill data length code */ + bfin_write16(®->chl[TRANSMIT_CHL].dlc, dlc); + + dev->trans_start = jiffies; + + can_put_echo_skb(skb, dev, 0); + + /* set transmit request */ + bfin_write16(®->trs2, BIT(TRANSMIT_CHL - 16)); + + return 0; +} + +static void bfin_can_rx(struct net_device *dev, u16 isrc) +{ + struct bfin_can_priv *priv = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + struct bfin_can_regs __iomem *reg = priv->membase; + struct can_frame *cf; + struct sk_buff *skb; + int obj; + int i; + u16 val; + + skb = alloc_can_skb(dev, &cf); + if (skb == NULL) + return; + + /* get id */ + if (isrc & BIT(RECEIVE_EXT_CHL)) { + /* extended frame format (EFF) */ + cf->can_id = ((bfin_read16(®->chl[RECEIVE_EXT_CHL].id1) + & 0x1FFF) << 16) + + bfin_read16(®->chl[RECEIVE_EXT_CHL].id0); + cf->can_id |= CAN_EFF_FLAG; + obj = RECEIVE_EXT_CHL; + } else { + /* standard frame format (SFF) */ + cf->can_id = (bfin_read16(®->chl[RECEIVE_STD_CHL].id1) + & 0x1ffc) >> 2; + obj = RECEIVE_STD_CHL; + } + if (bfin_read16(®->chl[obj].id1) & RTR) + cf->can_id |= CAN_RTR_FLAG; + + /* get data length code */ + cf->can_dlc = bfin_read16(®->chl[obj].dlc); + + /* get payload */ + for (i = 0; i < 8; i += 2) { + val = bfin_read16(®->chl[obj].data[i]); + cf->data[7 - i] = (7 - i) < cf->can_dlc ? val : 0; + cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0; + } + + netif_rx(skb); + + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; +} + +static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status) +{ + struct bfin_can_priv *priv = netdev_priv(dev); + struct bfin_can_regs __iomem *reg = priv->membase; + struct net_device_stats *stats = &dev->stats; + struct can_frame *cf; + struct sk_buff *skb; + enum can_state state = priv->can.state; + + skb = alloc_can_err_skb(dev, &cf); + if (skb == NULL) + return -ENOMEM; + + if (isrc & RMLIS) { + /* data overrun interrupt */ + dev_dbg(dev->dev.parent, "data overrun interrupt\n"); + cf->can_id |= CAN_ERR_CRTL; + cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; + stats->rx_over_errors++; + stats->rx_errors++; + } + + if (isrc & BOIS) { + dev_dbg(dev->dev.parent, "bus-off mode interrupt\n"); + state = CAN_STATE_BUS_OFF; + cf->can_id |= CAN_ERR_BUSOFF; + can_bus_off(dev); + } + + if (isrc & EPIS) { + /* error passive interrupt */ + dev_dbg(dev->dev.parent, "error passive interrupt\n"); + state = CAN_STATE_ERROR_PASSIVE; + } + + if ((isrc & EWTIS) || (isrc & EWRIS)) { + dev_dbg(dev->dev.parent, + "Error Warning Transmit/Receive Interrupt\n"); + state = CAN_STATE_ERROR_WARNING; + } + + if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING || + state == CAN_STATE_ERROR_PASSIVE)) { + u16 cec = bfin_read16(®->cec); + u8 rxerr = cec; + u8 txerr = cec >> 8; + + cf->can_id |= CAN_ERR_CRTL; + if (state == CAN_STATE_ERROR_WARNING) { + priv->can.can_stats.error_warning++; + cf->data[1] = (txerr > rxerr) ? + CAN_ERR_CRTL_TX_WARNING : + CAN_ERR_CRTL_RX_WARNING; + } else { + priv->can.can_stats.error_passive++; + cf->data[1] = (txerr > rxerr) ? + CAN_ERR_CRTL_TX_PASSIVE : + CAN_ERR_CRTL_RX_PASSIVE; + } + } + + if (status) { + priv->can.can_stats.bus_error++; + + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + + if (status & BEF) + cf->data[2] |= CAN_ERR_PROT_BIT; + else if (status & FER) + cf->data[2] |= CAN_ERR_PROT_FORM; + else if (status & SER) + cf->data[2] |= CAN_ERR_PROT_STUFF; + else + cf->data[2] |= CAN_ERR_PROT_UNSPEC; + } + + priv->can.state = state; + + netif_rx(skb); + + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; + + return 0; +} + +irqreturn_t bfin_can_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct bfin_can_priv *priv = netdev_priv(dev); + struct bfin_can_regs __iomem *reg = priv->membase; + struct net_device_stats *stats = &dev->stats; + u16 status, isrc; + + if ((irq == priv->tx_irq) && bfin_read16(®->mbtif2)) { + /* transmission complete interrupt */ + bfin_write16(®->mbtif2, 0xFFFF); + stats->tx_packets++; + stats->tx_bytes += bfin_read16(®->chl[TRANSMIT_CHL].dlc); + can_get_echo_skb(dev, 0); + netif_wake_queue(dev); + } else if ((irq == priv->rx_irq) && bfin_read16(®->mbrif1)) { + /* receive interrupt */ + isrc = bfin_read16(®->mbrif1); + bfin_write16(®->mbrif1, 0xFFFF); + bfin_can_rx(dev, isrc); + } else if ((irq == priv->err_irq) && bfin_read16(®->gis)) { + /* error interrupt */ + isrc = bfin_read16(®->gis); + status = bfin_read16(®->esr); + bfin_write16(®->gis, 0x7FF); + bfin_can_err(dev, isrc, status); + } else { + return IRQ_NONE; + } + + return IRQ_HANDLED; +} + +static int bfin_can_open(struct net_device *dev) +{ + struct bfin_can_priv *priv = netdev_priv(dev); + int err; + + /* set chip into reset mode */ + bfin_can_set_reset_mode(dev); + + /* common open */ + err = open_candev(dev); + if (err) + goto exit_open; + + /* register interrupt handler */ + err = request_irq(priv->rx_irq, &bfin_can_interrupt, 0, + "bfin-can-rx", dev); + if (err) + goto exit_rx_irq; + err = request_irq(priv->tx_irq, &bfin_can_interrupt, 0, + "bfin-can-tx", dev); + if (err) + goto exit_tx_irq; + err = request_irq(priv->err_irq, &bfin_can_interrupt, 0, + "bfin-can-err", dev); + if (err) + goto exit_err_irq; + + bfin_can_start(dev); + + netif_start_queue(dev); + + return 0; + +exit_err_irq: + free_irq(priv->tx_irq, dev); +exit_tx_irq: + free_irq(priv->rx_irq, dev); +exit_rx_irq: + close_candev(dev); +exit_open: + return err; +} + +static int bfin_can_close(struct net_device *dev) +{ + struct bfin_can_priv *priv = netdev_priv(dev); + + netif_stop_queue(dev); + bfin_can_set_reset_mode(dev); + + close_candev(dev); + + free_irq(priv->rx_irq, dev); + free_irq(priv->tx_irq, dev); + free_irq(priv->err_irq, dev); + + return 0; +} + +struct net_device *alloc_bfin_candev(void) +{ + struct net_device *dev; + struct bfin_can_priv *priv; + + dev = alloc_candev(sizeof(*priv)); + if (!dev) + return NULL; + + priv = netdev_priv(dev); + + priv->dev = dev; + priv->can.bittiming_const = &bfin_can_bittiming_const; + priv->can.do_set_bittiming = bfin_can_set_bittiming; + priv->can.do_set_mode = bfin_can_set_mode; + + return dev; +} + +static const struct net_device_ops bfin_can_netdev_ops = { + .ndo_open = bfin_can_open, + .ndo_stop = bfin_can_close, + .ndo_start_xmit = bfin_can_start_xmit, +}; + +static int __devinit bfin_can_probe(struct platform_device *pdev) +{ + int err; + struct net_device *dev; + struct bfin_can_priv *priv; + struct resource *res_mem, *rx_irq, *tx_irq, *err_irq; + unsigned short *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "No platform data provided!\n"); + err = -EINVAL; + goto exit; + } + + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rx_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + tx_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 1); + err_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 2); + if (!res_mem || !rx_irq || !tx_irq || !err_irq) { + err = -EINVAL; + goto exit; + } + + if (!request_mem_region(res_mem->start, resource_size(res_mem), + dev_name(&pdev->dev))) { + err = -EBUSY; + goto exit; + } + + /* request peripheral pins */ + err = peripheral_request_list(pdata, dev_name(&pdev->dev)); + if (err) + goto exit_mem_release; + + dev = alloc_bfin_candev(); + if (!dev) { + err = -ENOMEM; + goto exit_peri_pin_free; + } + + priv = netdev_priv(dev); + priv->membase = (void __iomem *)res_mem->start; + priv->rx_irq = rx_irq->start; + priv->tx_irq = tx_irq->start; + priv->err_irq = err_irq->start; + priv->pin_list = pdata; + priv->can.clock.freq = get_sclk(); + + dev_set_drvdata(&pdev->dev, dev); + SET_NETDEV_DEV(dev, &pdev->dev); + + dev->flags |= IFF_ECHO; /* we support local echo */ + dev->netdev_ops = &bfin_can_netdev_ops; + + bfin_can_set_reset_mode(dev); + + err = register_candev(dev); + if (err) { + dev_err(&pdev->dev, "registering failed (err=%d)\n", err); + goto exit_candev_free; + } + + dev_info(&pdev->dev, + "%s device registered" + "(®_base=%p, rx_irq=%d, tx_irq=%d, err_irq=%d, sclk=%d)\n", + DRV_NAME, (void *)priv->membase, priv->rx_irq, + priv->tx_irq, priv->err_irq, priv->can.clock.freq); + return 0; + +exit_candev_free: + free_candev(dev); +exit_peri_pin_free: + peripheral_free_list(pdata); +exit_mem_release: + release_mem_region(res_mem->start, resource_size(res_mem)); +exit: + return err; +} + +static int __devexit bfin_can_remove(struct platform_device *pdev) +{ + struct net_device *dev = dev_get_drvdata(&pdev->dev); + struct bfin_can_priv *priv = netdev_priv(dev); + struct resource *res; + + bfin_can_set_reset_mode(dev); + + unregister_candev(dev); + + dev_set_drvdata(&pdev->dev, NULL); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, resource_size(res)); + + peripheral_free_list(priv->pin_list); + + free_candev(dev); + return 0; +} + +#ifdef CONFIG_PM +static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + struct net_device *dev = dev_get_drvdata(&pdev->dev); + struct bfin_can_priv *priv = netdev_priv(dev); + struct bfin_can_regs __iomem *reg = priv->membase; + int timeout = BFIN_CAN_TIMEOUT; + + if (netif_running(dev)) { + /* enter sleep mode */ + bfin_write16(®->ctrl, bfin_read16(®->ctrl) | SMR); + SSYNC(); + while (!(bfin_read16(®->intr) & SMACK)) { + udelay(10); + if (--timeout == 0) { + dev_err(dev->dev.parent, + "fail to enter sleep mode\n"); + BUG(); + } + } + } + + return 0; +} + +static int bfin_can_resume(struct platform_device *pdev) +{ + struct net_device *dev = dev_get_drvdata(&pdev->dev); + struct bfin_can_priv *priv = netdev_priv(dev); + struct bfin_can_regs __iomem *reg = priv->membase; + + if (netif_running(dev)) { + /* leave sleep mode */ + bfin_write16(®->intr, 0); + SSYNC(); + } + + return 0; +} +#else +#define bfin_can_suspend NULL +#define bfin_can_resume NULL +#endif /* CONFIG_PM */ + +static struct platform_driver bfin_can_driver = { + .probe = bfin_can_probe, + .remove = __devexit_p(bfin_can_remove), + .suspend = bfin_can_suspend, + .resume = bfin_can_resume, + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init bfin_can_init(void) +{ + return platform_driver_register(&bfin_can_driver); +} +module_init(bfin_can_init); + +static void __exit bfin_can_exit(void) +{ + platform_driver_unregister(&bfin_can_driver); +} +module_exit(bfin_can_exit); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Blackfin on-chip CAN netdevice driver"); diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 8c658cf6f62f3066d84c3b7e45ce79d6d0979dd4..109d2783e4d88fc6823b57d36dd8138a30e5d68b 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -1378,7 +1378,7 @@ static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len) } __skb_pull(skb, sizeof(*p)); - st = per_cpu_ptr(sge->port_stats[p->iff], smp_processor_id()); + st = this_cpu_ptr(sge->port_stats[p->iff]); skb->protocol = eth_type_trans(skb, adapter->port[p->iff].dev); if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff && @@ -1780,8 +1780,7 @@ netdev_tx_t t1_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct adapter *adapter = dev->ml_priv; struct sge *sge = adapter->sge; - struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port], - smp_processor_id()); + struct sge_port_stats *st = this_cpu_ptr(sge->port_stats[dev->if_port]); struct cpl_tx_pkt *cpl; struct sk_buff *orig_skb = skb; int ret; diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index d4c6e7fcff53a1c1901a81263da4404c286ba9ce..4332b3a2fafbacec6705b650da28cea157032fc5 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -1104,6 +1104,8 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev) cp->bnx2x_status_blk = cp->status_blk; cp->bnx2x_def_status_blk = cp->ethdev->irq_arr[1].status_blk; + memset(cp->bnx2x_status_blk, 0, sizeof(struct host_status_block)); + cp->l2_rx_ring_size = 15; ret = cnic_alloc_l2_rings(dev, 4); @@ -4183,6 +4185,12 @@ static void cnic_shutdown_rings(struct cnic_dev *dev) cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_HALT, BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE, &l5_data); msleep(10); + + memset(&l5_data, 0, sizeof(l5_data)); + cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CFC_DEL, + BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE | + (1 << SPE_HDR_COMMON_RAMROD_SHIFT), &l5_data); + msleep(10); } } @@ -4289,6 +4297,9 @@ static void cnic_stop_bnx2x_hw(struct cnic_dev *dev) offsetof(struct cstorm_status_block_c, index_values[HC_INDEX_C_ISCSI_EQ_CONS]), 0); + CNIC_WR(dev, BAR_CSTRORM_INTMEM + + CSTORM_ISCSI_EQ_CONS_OFFSET(cp->func, 0), 0); + CNIC_WR16(dev, cp->kcq_io_addr, 0); cnic_free_resc(dev); } diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index cef3f882e2b66fd8340c7431291a60db3c61053b..89bec9c3c141a86517f7113d223bcf541a81c3db 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -2860,6 +2860,7 @@ static int t3_reenable_adapter(struct adapter *adapter) } pci_set_master(adapter->pdev); pci_restore_state(adapter->pdev); + pci_save_state(adapter->pdev); /* Free sge resources */ t3_free_sge_resources(adapter); diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index 86d2809763c3600dd808ab12b79b860b61adf9d0..e02e38221ed47c9ab428a7aec033c16ac97e2584 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -74,7 +74,7 @@ #define E1000_WUS_BC E1000_WUFC_BC /* Extended Device Control */ -#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */ +#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Definable Pin 3 */ #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ #define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ #define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c index d2a10479460944789ce7803c7098c6bcdf40baa3..3028f23da8918c306f1261a86221cab996380278 100644 --- a/drivers/net/e1000e/es2lan.c +++ b/drivers/net/e1000e/es2lan.c @@ -46,6 +46,9 @@ #define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000 #define E1000_KMRNCTRLSTA_OPMODE_E_IDLE 0x2000 +#define E1000_KMRNCTRLSTA_OPMODE_MASK 0x000C +#define E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO 0x0004 + #define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */ #define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000 @@ -462,28 +465,36 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, return ret_val; } - /* - * The "ready" bit in the MDIC register may be incorrectly set - * before the device has completed the "Page Select" MDI - * transaction. So we wait 200us after each MDI command... - */ - udelay(200); + if (hw->dev_spec.e80003es2lan.mdic_wa_enable == true) { + /* + * The "ready" bit in the MDIC register may be incorrectly set + * before the device has completed the "Page Select" MDI + * transaction. So we wait 200us after each MDI command... + */ + udelay(200); - /* ...and verify the command was successful. */ - ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); + /* ...and verify the command was successful. */ + ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); - if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { - ret_val = -E1000_ERR_PHY; - e1000_release_phy_80003es2lan(hw); - return ret_val; - } + if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { + ret_val = -E1000_ERR_PHY; + e1000_release_phy_80003es2lan(hw); + return ret_val; + } - udelay(200); + udelay(200); - ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); + ret_val = e1000e_read_phy_reg_mdic(hw, + MAX_PHY_REG_ADDRESS & offset, + data); + + udelay(200); + } else { + ret_val = e1000e_read_phy_reg_mdic(hw, + MAX_PHY_REG_ADDRESS & offset, + data); + } - udelay(200); e1000_release_phy_80003es2lan(hw); return ret_val; @@ -526,28 +537,35 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, return ret_val; } + if (hw->dev_spec.e80003es2lan.mdic_wa_enable == true) { + /* + * The "ready" bit in the MDIC register may be incorrectly set + * before the device has completed the "Page Select" MDI + * transaction. So we wait 200us after each MDI command... + */ + udelay(200); - /* - * The "ready" bit in the MDIC register may be incorrectly set - * before the device has completed the "Page Select" MDI - * transaction. So we wait 200us after each MDI command... - */ - udelay(200); + /* ...and verify the command was successful. */ + ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); - /* ...and verify the command was successful. */ - ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); + if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { + e1000_release_phy_80003es2lan(hw); + return -E1000_ERR_PHY; + } - if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { - e1000_release_phy_80003es2lan(hw); - return -E1000_ERR_PHY; - } + udelay(200); - udelay(200); + ret_val = e1000e_write_phy_reg_mdic(hw, + MAX_PHY_REG_ADDRESS & offset, + data); - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); + udelay(200); + } else { + ret_val = e1000e_write_phy_reg_mdic(hw, + MAX_PHY_REG_ADDRESS & offset, + data); + } - udelay(200); e1000_release_phy_80003es2lan(hw); return ret_val; @@ -866,6 +884,19 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) reg_data &= ~0x00100000; E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data); + /* default to true to enable the MDIC W/A */ + hw->dev_spec.e80003es2lan.mdic_wa_enable = true; + + ret_val = e1000_read_kmrn_reg_80003es2lan(hw, + E1000_KMRNCTRLSTA_OFFSET >> + E1000_KMRNCTRLSTA_OFFSET_SHIFT, + &i); + if (!ret_val) { + if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) == + E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO) + hw->dev_spec.e80003es2lan.mdic_wa_enable = false; + } + /* * Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index a7d08dae79c482e7ccf8e37f984bad5377c74820..2784cf44a6f3304e943068d8cb1b1e99e3e32c33 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -302,6 +302,8 @@ enum e1e_registers { #define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 #define E1000_KMRNCTRLSTA_REN 0x00200000 #define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ +#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */ +#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ #define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 #define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E @@ -898,6 +900,10 @@ struct e1000_dev_spec_82571 { u32 smb_counter; }; +struct e1000_dev_spec_80003es2lan { + bool mdic_wa_enable; +}; + struct e1000_shadow_ram { u16 value; bool modified; @@ -926,6 +932,7 @@ struct e1000_hw { union { struct e1000_dev_spec_82571 e82571; + struct e1000_dev_spec_80003es2lan e80003es2lan; struct e1000_dev_spec_ich8lan ich8lan; } dev_spec; }; diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 7b33be98a2cadc7a6a51efc8491232d3e7bb8500..9b09246af064675fa5c973db55ca76e5b63823b8 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -2755,14 +2755,16 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) * and increase the max iterations when polling the phy; * this fixes erroneous timeouts at 10Mbps. */ - ret_val = e1000e_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF); + ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_TIMEOUTS, 0xFFFF); if (ret_val) return ret_val; - ret_val = e1000e_read_kmrn_reg(hw, GG82563_REG(0x34, 9), ®_data); + ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, + ®_data); if (ret_val) return ret_val; reg_data |= 0x3F; - ret_val = e1000e_write_kmrn_reg(hw, GG82563_REG(0x34, 9), reg_data); + ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, + reg_data); if (ret_val) return ret_val; diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index c3105c5087e05d5ed81e991b026ac0cc128f6b5c..762b697ce7310d37d497cd2c169bd52497faf5fb 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -4541,7 +4541,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake) e1000_media_type_internal_serdes) { /* keep the laser running in D3 */ ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; + ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA; ew32(CTRL_EXT, ctrl_ext); } diff --git a/drivers/net/ehea/ehea_hcall.h b/drivers/net/ehea/ehea_hcall.h deleted file mode 100644 index 8e7d1c3edc6080f130b7ab1f4827b1571354dee8..0000000000000000000000000000000000000000 --- a/drivers/net/ehea/ehea_hcall.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * linux/drivers/net/ehea/ehea_hcall.h - * - * eHEA ethernet device driver for IBM eServer System p - * - * (C) Copyright IBM Corp. 2006 - * - * Authors: - * Christoph Raisch - * Jan-Bernd Themann - * Thomas Klein - * - * - * This program is free software; you can redistribute 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 __EHEA_HCALL_H__ -#define __EHEA_HCALL_H__ - -/** - * This file contains HCALL defines that are to be included in the appropriate - * kernel files later - */ - -#define H_ALLOC_HEA_RESOURCE 0x278 -#define H_MODIFY_HEA_QP 0x250 -#define H_QUERY_HEA_QP 0x254 -#define H_QUERY_HEA 0x258 -#define H_QUERY_HEA_PORT 0x25C -#define H_MODIFY_HEA_PORT 0x260 -#define H_REG_BCMC 0x264 -#define H_DEREG_BCMC 0x268 -#define H_REGISTER_HEA_RPAGES 0x26C -#define H_DISABLE_AND_GET_HEA 0x270 -#define H_GET_HEA_INFO 0x274 -#define H_ADD_CONN 0x284 -#define H_DEL_CONN 0x288 - -#endif /* __EHEA_HCALL_H__ */ diff --git a/drivers/net/ehea/ehea_phyp.h b/drivers/net/ehea/ehea_phyp.h index f3628c803567674c4b5650a9d71389b5aea0290e..2f8174c248bcdd64f9c59694926034e93d7b2131 100644 --- a/drivers/net/ehea/ehea_phyp.h +++ b/drivers/net/ehea/ehea_phyp.h @@ -33,7 +33,6 @@ #include #include "ehea.h" #include "ehea_hw.h" -#include "ehea_hcall.h" /* Some abbreviations used here: * diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index 6407672b28e96aac3491835c85eaa88684773474..848e8407ea8f5407a53eb5464a2f487e131e2ee9 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -85,11 +85,15 @@ MODULE_PARM_DESC(debug, "debugging messages level"); static void mpc52xx_fec_tx_timeout(struct net_device *dev) { + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + unsigned long flags; + dev_warn(&dev->dev, "transmit timed out\n"); + spin_lock_irqsave(&priv->lock, flags); mpc52xx_fec_reset(dev); - dev->stats.tx_errors++; + spin_unlock_irqrestore(&priv->lock, flags); netif_wake_queue(dev); } @@ -135,28 +139,32 @@ static void mpc52xx_fec_free_rx_buffers(struct net_device *dev, struct bcom_task } } +static void +mpc52xx_fec_rx_submit(struct net_device *dev, struct sk_buff *rskb) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct bcom_fec_bd *bd; + + bd = (struct bcom_fec_bd *) bcom_prepare_next_buffer(priv->rx_dmatsk); + bd->status = FEC_RX_BUFFER_SIZE; + bd->skb_pa = dma_map_single(dev->dev.parent, rskb->data, + FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); + bcom_submit_next_buffer(priv->rx_dmatsk, rskb); +} + static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task *rxtsk) { - while (!bcom_queue_full(rxtsk)) { - struct sk_buff *skb; - struct bcom_fec_bd *bd; + struct sk_buff *skb; + while (!bcom_queue_full(rxtsk)) { skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE); - if (skb == NULL) + if (!skb) return -EAGAIN; /* zero out the initial receive buffers to aid debugging */ memset(skb->data, 0, FEC_RX_BUFFER_SIZE); - - bd = (struct bcom_fec_bd *)bcom_prepare_next_buffer(rxtsk); - - bd->status = FEC_RX_BUFFER_SIZE; - bd->skb_pa = dma_map_single(dev->dev.parent, skb->data, - FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); - - bcom_submit_next_buffer(rxtsk, skb); + mpc52xx_fec_rx_submit(dev, skb); } - return 0; } @@ -328,13 +336,12 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev) DMA_TO_DEVICE); bcom_submit_next_buffer(priv->tx_dmatsk, skb); + spin_unlock_irqrestore(&priv->lock, flags); if (bcom_queue_full(priv->tx_dmatsk)) { netif_stop_queue(dev); } - spin_unlock_irqrestore(&priv->lock, flags); - return NETDEV_TX_OK; } @@ -359,9 +366,9 @@ static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; struct mpc52xx_fec_priv *priv = netdev_priv(dev); + unsigned long flags; - spin_lock(&priv->lock); - + spin_lock_irqsave(&priv->lock, flags); while (bcom_buffer_done(priv->tx_dmatsk)) { struct sk_buff *skb; struct bcom_fec_bd *bd; @@ -372,11 +379,10 @@ static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id) dev_kfree_skb_irq(skb); } + spin_unlock_irqrestore(&priv->lock, flags); netif_wake_queue(dev); - spin_unlock(&priv->lock); - return IRQ_HANDLED; } @@ -384,67 +390,60 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct sk_buff *rskb; /* received sk_buff */ + struct sk_buff *skb; /* new sk_buff to enqueue in its place */ + struct bcom_fec_bd *bd; + u32 status, physaddr; + int length; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); while (bcom_buffer_done(priv->rx_dmatsk)) { - struct sk_buff *skb; - struct sk_buff *rskb; - struct bcom_fec_bd *bd; - u32 status; rskb = bcom_retrieve_buffer(priv->rx_dmatsk, &status, - (struct bcom_bd **)&bd); - dma_unmap_single(dev->dev.parent, bd->skb_pa, rskb->len, - DMA_FROM_DEVICE); + (struct bcom_bd **)&bd); + physaddr = bd->skb_pa; /* Test for errors in received frame */ if (status & BCOM_FEC_RX_BD_ERRORS) { /* Drop packet and reuse the buffer */ - bd = (struct bcom_fec_bd *) - bcom_prepare_next_buffer(priv->rx_dmatsk); - - bd->status = FEC_RX_BUFFER_SIZE; - bd->skb_pa = dma_map_single(dev->dev.parent, - rskb->data, - FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); - - bcom_submit_next_buffer(priv->rx_dmatsk, rskb); - + mpc52xx_fec_rx_submit(dev, rskb); dev->stats.rx_dropped++; - continue; } /* skbs are allocated on open, so now we allocate a new one, * and remove the old (with the packet) */ skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE); - if (skb) { - /* Process the received skb */ - int length = status & BCOM_FEC_RX_BD_LEN_MASK; - - skb_put(rskb, length - 4); /* length without CRC32 */ - - rskb->dev = dev; - rskb->protocol = eth_type_trans(rskb, dev); - - netif_rx(rskb); - } else { + if (!skb) { /* Can't get a new one : reuse the same & drop pkt */ - dev_notice(&dev->dev, "Memory squeeze, dropping packet.\n"); + dev_notice(&dev->dev, "Low memory - dropped packet.\n"); + mpc52xx_fec_rx_submit(dev, rskb); dev->stats.rx_dropped++; - - skb = rskb; + continue; } - bd = (struct bcom_fec_bd *) - bcom_prepare_next_buffer(priv->rx_dmatsk); + /* Enqueue the new sk_buff back on the hardware */ + mpc52xx_fec_rx_submit(dev, skb); - bd->status = FEC_RX_BUFFER_SIZE; - bd->skb_pa = dma_map_single(dev->dev.parent, skb->data, - FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); + /* Process the received skb - Drop the spin lock while + * calling into the network stack */ + spin_unlock_irqrestore(&priv->lock, flags); - bcom_submit_next_buffer(priv->rx_dmatsk, skb); + dma_unmap_single(dev->dev.parent, physaddr, rskb->len, + DMA_FROM_DEVICE); + length = status & BCOM_FEC_RX_BD_LEN_MASK; + skb_put(rskb, length - 4); /* length without CRC32 */ + rskb->dev = dev; + rskb->protocol = eth_type_trans(rskb, dev); + netif_rx(rskb); + + spin_lock_irqsave(&priv->lock, flags); } + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_HANDLED; } @@ -454,6 +453,7 @@ static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id) struct mpc52xx_fec_priv *priv = netdev_priv(dev); struct mpc52xx_fec __iomem *fec = priv->fec; u32 ievent; + unsigned long flags; ievent = in_be32(&fec->ievent); @@ -471,9 +471,10 @@ static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id) if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR)) dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n"); + spin_lock_irqsave(&priv->lock, flags); mpc52xx_fec_reset(dev); + spin_unlock_irqrestore(&priv->lock, flags); - netif_wake_queue(dev); return IRQ_HANDLED; } @@ -768,6 +769,8 @@ static void mpc52xx_fec_reset(struct net_device *dev) bcom_enable(priv->tx_dmatsk); mpc52xx_fec_start(dev); + + netif_wake_queue(dev); } diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 16def131c390852e4dd5c30c30a936fc682513a2..6850dc0a7b9194c34807762eccb2d7d04a4a007c 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -2644,6 +2644,7 @@ static void gfar_netpoll(struct net_device *dev) gfar_interrupt(priv->gfargrp[i].interruptTransmit, &priv->gfargrp[i]); enable_irq(priv->gfargrp[i].interruptTransmit); + } } } #endif diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 16349ba687367755abe33c5d439e48704e3fcdbb..78963a0e128dcf4171c9d8a8d1ac579c0b529d15 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -4608,8 +4608,14 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) retval = igb_read_mbx(hw, msgbuf, E1000_VFMAILBOX_SIZE, vf); - if (retval) + if (retval) { + /* if receive failed revoke VF CTS stats and restart init */ dev_err(&pdev->dev, "Error receiving message from VF\n"); + vf_data->flags &= ~IGB_VF_FLAG_CTS; + if (!time_after(jiffies, vf_data->last_nack + (2 * HZ))) + return; + goto out; + } /* this is a message we already processed, do nothing */ if (msgbuf[0] & (E1000_VT_MSGTYPE_ACK | E1000_VT_MSGTYPE_NACK)) @@ -4626,12 +4632,10 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) } if (!(vf_data->flags & IGB_VF_FLAG_CTS)) { - msgbuf[0] = E1000_VT_MSGTYPE_NACK; - if (time_after(jiffies, vf_data->last_nack + (2 * HZ))) { - igb_write_mbx(hw, msgbuf, 1, vf); - vf_data->last_nack = jiffies; - } - return; + if (!time_after(jiffies, vf_data->last_nack + (2 * HZ))) + return; + retval = -1; + goto out; } switch ((msgbuf[0] & 0xFFFF)) { @@ -4656,14 +4660,14 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) break; } + msgbuf[0] |= E1000_VT_MSGTYPE_CTS; +out: /* notify the VF of the results of what it sent us */ if (retval) msgbuf[0] |= E1000_VT_MSGTYPE_NACK; else msgbuf[0] |= E1000_VT_MSGTYPE_ACK; - msgbuf[0] |= E1000_VT_MSGTYPE_CTS; - igb_write_mbx(hw, msgbuf, 1, vf); } diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/igbvf/igbvf.h index 3d1ee7a8478e77a0723dc3f1b25ff169fe020067..a1774b29d222093851ce46e29d5871d9cc69e286 100644 --- a/drivers/net/igbvf/igbvf.h +++ b/drivers/net/igbvf/igbvf.h @@ -276,6 +276,7 @@ struct igbvf_adapter { unsigned long led_status; unsigned int flags; + unsigned long last_reset; }; struct igbvf_info { diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index a127620dc6531689d11d479d8eddf3701307da30..e9dd95f136aa8432d1542fc344a19cd0acdf3abb 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -1469,6 +1469,8 @@ static void igbvf_reset(struct igbvf_adapter *adapter) memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len); } + + adapter->last_reset = jiffies; } int igbvf_up(struct igbvf_adapter *adapter) @@ -1812,11 +1814,15 @@ static bool igbvf_has_link(struct igbvf_adapter *adapter) s32 ret_val = E1000_SUCCESS; bool link_active; + /* If interface is down, stay link down */ + if (test_bit(__IGBVF_DOWN, &adapter->state)) + return false; + ret_val = hw->mac.ops.check_for_link(hw); link_active = !hw->mac.get_link_status; /* if check for link returns error we will need to reset */ - if (ret_val) + if (ret_val && time_after(jiffies, adapter->last_reset + (10 * HZ))) schedule_work(&adapter->reset_task); return link_active; diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 72106898a5cb9eced9f626c8f40b8ae86ab90c24..538340527aa6cb6514f8813d2e81cc1a07c7ac36 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -342,6 +342,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82599_KX4: case IXGBE_DEV_ID_82599_KX4_MEZZ: case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: + case IXGBE_DEV_ID_82599_KR: case IXGBE_DEV_ID_82599_XAUI_LOM: /* Default device ID is mezzanine card KX/KX4 */ media_type = ixgbe_media_type_backplane; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 06a9d18bbdbc13f22b3a824567e6adbf0ea5e115..0bd49d3b9f6566285dcd83c00193a0eba5fa9819 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -990,6 +990,7 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, char *p = NULL; ixgbe_update_stats(adapter); + dev_get_stats(netdev); for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { switch (ixgbe_gstrings_stats[i].type) { case NETDEV_STATS: diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 247ed2a24769a6e5929fba2332220f48632a1178..35ea8c93fd809b082c78e035aaa2b7c31966bd0c 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -96,6 +96,8 @@ static struct pci_device_id ixgbe_pci_tbl[] = { board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_XAUI_LOM), board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KR), + board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP), board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_EM), @@ -435,8 +437,6 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, tx_ring->total_packets += total_packets; tx_ring->stats.packets += total_packets; tx_ring->stats.bytes += total_bytes; - netdev->stats.tx_bytes += total_bytes; - netdev->stats.tx_packets += total_packets; return (count < tx_ring->work_limit); } @@ -5327,6 +5327,7 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_ring *tx_ring; + struct netdev_queue *txq; unsigned int first; unsigned int tx_flags = 0; u8 hdr_len = 0; @@ -5424,6 +5425,9 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, tx_ring->atr_count = 0; } } + txq = netdev_get_tx_queue(netdev, tx_ring->queue_index); + txq->tx_bytes += skb->len; + txq->tx_packets++; ixgbe_tx_queue(adapter, tx_ring, tx_flags, count, skb->len, hdr_len); ixgbe_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED); @@ -5437,19 +5441,6 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, return NETDEV_TX_OK; } -/** - * ixgbe_get_stats - Get System Network Statistics - * @netdev: network interface device structure - * - * Returns the address of the device statistics structure. - * The statistics are actually updated from the timer callback. - **/ -static struct net_device_stats *ixgbe_get_stats(struct net_device *netdev) -{ - /* only return the current stats */ - return &netdev->stats; -} - /** * ixgbe_set_mac - Change the Ethernet Address of the NIC * @netdev: network interface device structure @@ -5580,7 +5571,6 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_stop = ixgbe_close, .ndo_start_xmit = ixgbe_xmit_frame, .ndo_select_queue = ixgbe_select_queue, - .ndo_get_stats = ixgbe_get_stats, .ndo_set_rx_mode = ixgbe_set_rx_mode, .ndo_set_multicast_list = ixgbe_set_rx_mode, .ndo_validate_addr = eth_validate_addr, diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 21b6633da578f0f1fe04e4aef6af13c0a4e36287..f3e8d52610b7d57960dbbe835cdb7845ed05dc2f 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -50,6 +50,7 @@ #define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4 #define IXGBE_DEV_ID_82599_KX4 0x10F7 #define IXGBE_DEV_ID_82599_KX4_MEZZ 0x1514 +#define IXGBE_DEV_ID_82599_KR 0x1517 #define IXGBE_DEV_ID_82599_CX4 0x10F9 #define IXGBE_DEV_ID_82599_SFP 0x10FB #define IXGBE_DEV_ID_82599_SFP_EM 0x1507 diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index eae4ad749e9d87956facbfadd53036d5d882ce03..b9fcc9819837e7f79530ad11782272ea0f81a344 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -81,7 +81,7 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, /* it's OK to use per_cpu_ptr() because BHs are off */ pcpu_lstats = dev->ml_priv; - lb_stats = per_cpu_ptr(pcpu_lstats, smp_processor_id()); + lb_stats = this_cpu_ptr(pcpu_lstats); len = skb->len; if (likely(netif_rx(skb) == NET_RX_SUCCESS)) { diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 796a493f95aba719fd0e67bc9b4c6ab7dd6063e8..1405a170bb43483046b1d6f6be4542c2a7021e23 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1827,6 +1827,9 @@ static int mv643xx_eth_set_mac_address(struct net_device *dev, void *addr) { struct sockaddr *sa = addr; + if (!is_valid_ether_addr(sa->sa_data)) + return -EINVAL; + memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN); netif_addr_lock_bh(dev); diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index d38921906bb7217e65d0b1bcbe2926295841df5b..3fcb1c356e0d157de807fc1a729bf9b1af19b48e 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -75,7 +75,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.5.1-1.451" +#define MYRI10GE_VERSION_STR "1.5.1-1.453" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -347,7 +347,7 @@ static int myri10ge_max_slices = 1; module_param(myri10ge_max_slices, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_max_slices, "Max tx/rx queues"); -static int myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_PORT; +static int myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT; module_param(myri10ge_rss_hash, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_rss_hash, "Type of RSS hashing to do"); diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 80a66746051485016180ccfcd49a56002297f8cd..02f8d4b4db63d2bffe94407dc303bdcff186c844 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -619,17 +619,20 @@ nx_set_product_offs(struct netxen_adapter *adapter) uint32_t i; __le32 entries; + int mn_present = (NX_IS_REVISION_P2(adapter->ahw.revision_id)) ? + 1 : netxen_p3_has_mn(adapter); + ptab_descr = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_PRODUCT_TBL); if (ptab_descr == NULL) return -1; entries = cpu_to_le32(ptab_descr->num_entries); +nomn: for (i = 0; i < entries; i++) { __le32 flags, file_chiprev, offs; u8 chiprev = adapter->ahw.revision_id; - int mn_present = netxen_p3_has_mn(adapter); uint32_t flagbit; offs = cpu_to_le32(ptab_descr->findex) + @@ -647,6 +650,11 @@ nx_set_product_offs(struct netxen_adapter *adapter) } } + if (mn_present && NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + mn_present = 0; + goto nomn; + } + return -1; } @@ -1021,6 +1029,10 @@ netxen_p3_has_mn(struct netxen_adapter *adapter) u32 capability, flashed_ver; capability = 0; + /* NX2031 always had MN */ + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return 1; + netxen_rom_fast_read(adapter, NX_FW_VERSION_OFFSET, (int *)&flashed_ver); flashed_ver = NETXEN_DECODE_VERSION(flashed_ver); diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index e5d187fce51b537dd1f7fe066eb4b6cd642e4caa..f4996846a234b0edd6bbc7bb8d49bb19e28ca4b2 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -946,8 +946,9 @@ netxen_nic_init_coalesce_defaults(struct netxen_adapter *adapter) NETXEN_DEFAULT_INTR_COALESCE_TX_PACKETS; } +/* with rtnl_lock */ static int -netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) +__netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) { int err; @@ -988,14 +989,32 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) return 0; } +/* Usage: During resume and firmware recovery module.*/ + +static inline int +netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) +{ + int err = 0; + + rtnl_lock(); + if (netif_running(netdev)) + err = __netxen_nic_up(adapter, netdev); + rtnl_unlock(); + + return err; +} + +/* with rtnl_lock */ static void -netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) +__netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) { if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) return; - clear_bit(__NX_DEV_UP, &adapter->state); + if (!test_and_clear_bit(__NX_DEV_UP, &adapter->state)) + return; + smp_mb(); spin_lock(&adapter->tx_clean_lock); netif_carrier_off(netdev); netif_tx_disable(netdev); @@ -1014,6 +1033,17 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) spin_unlock(&adapter->tx_clean_lock); } +/* Usage: During suspend and firmware recovery module */ + +static inline void +netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) +{ + rtnl_lock(); + if (netif_running(netdev)) + __netxen_nic_down(adapter, netdev); + rtnl_unlock(); + +} static int netxen_nic_attach(struct netxen_adapter *adapter) @@ -1122,14 +1152,14 @@ netxen_nic_reset_context(struct netxen_adapter *adapter) netif_device_detach(netdev); if (netif_running(netdev)) - netxen_nic_down(adapter, netdev); + __netxen_nic_down(adapter, netdev); netxen_nic_detach(adapter); if (netif_running(netdev)) { err = netxen_nic_attach(adapter); if (!err) - err = netxen_nic_up(adapter, netdev); + err = __netxen_nic_up(adapter, netdev); if (err) goto done; @@ -1499,7 +1529,7 @@ static int netxen_nic_open(struct net_device *netdev) if (err) return err; - err = netxen_nic_up(adapter, netdev); + err = __netxen_nic_up(adapter, netdev); if (err) goto err_out; @@ -1519,7 +1549,7 @@ static int netxen_nic_close(struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); - netxen_nic_down(adapter, netdev); + __netxen_nic_down(adapter, netdev); return 0; } @@ -2025,7 +2055,7 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget) if ((work_done < budget) && tx_complete) { napi_complete(&sds_ring->napi); - if (netif_running(adapter->netdev)) + if (test_bit(__NX_DEV_UP, &adapter->state)) netxen_nic_enable_int(sds_ring); } @@ -2210,8 +2240,7 @@ netxen_detach_work(struct work_struct *work) netif_device_detach(netdev); - if (netif_running(netdev)) - netxen_nic_down(adapter, netdev); + netxen_nic_down(adapter, netdev); netxen_nic_detach(adapter); diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 81bafd57847814ef6875ff1447c092a5e24e1a03..d431b59e7d11bda7b203a96cec3217570344eade 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -270,7 +270,7 @@ static int try_io_port(struct pcmcia_device *link) /* for master/slave multifunction cards */ link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; link->irq.Attributes = - IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + IRQ_TYPE_DYNAMIC_SHARING; } } else { /* This should be two 16-port windows */ diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 8ad8384fc1c04ebde288ca9e8846d6b0ddb12eb7..813aca3fc433eed9d3411091e182e9f95c2602ca 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -426,7 +426,7 @@ static int fmvj18x_config(struct pcmcia_device *link) if (link->io.NumPorts2 != 0) { link->irq.Attributes = - IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + IRQ_TYPE_DYNAMIC_SHARING; ret = mfc_try_io_port(link); if (ret != 0) goto failed; } else if (cardtype == UNGERMANN) { diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 2d26b6ca28b92949fd543b484d916a187c6bcaed..92ed3fbf89a570c8c063521d3613828976e71461 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -490,7 +490,7 @@ static int try_io_port(struct pcmcia_device *link) /* for master/slave multifunction cards */ link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; link->irq.Attributes = - IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + IRQ_TYPE_DYNAMIC_SHARING; } } else { /* This should be two 16-port windows */ diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index cc4853bc025354ff62066ea9919598da1463b82d..6dd486d2977ba47c5ea72d98c2ea2d3378ebd435 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -454,7 +454,7 @@ static int mhz_mfc_config(struct pcmcia_device *link) link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; link->irq.Attributes = - IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + IRQ_TYPE_DYNAMIC_SHARING; link->io.IOAddrLines = 16; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts2 = 8; diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index a2eda28f903ea6e6ccd2b4104280e28d3314c07d..466fc72698c03c4599e78f961e257c2d1013cf92 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -841,7 +841,7 @@ xirc2ps_config(struct pcmcia_device * link) link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status |= CCSR_AUDIO_ENA; } - link->irq.Attributes |= IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED ; + link->irq.Attributes |= IRQ_TYPE_DYNAMIC_SHARING; link->io.NumPorts2 = 8; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; if (local->dingo) { diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 044e6817986f8abb9046e4515168e971bf2094b6..89a05d674ddca5c1acc6748fe2774299f5cc2b95 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2152,7 +2152,9 @@ static void sky2_qlink_intr(struct sky2_hw *hw) /* reset PHY Link Detect */ phy = sky2_pci_read16(hw, PSM_CONFIG_REG4); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); sky2_pci_write16(hw, PSM_CONFIG_REG4, phy | 1); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); sky2_link_up(sky2); } @@ -2968,8 +2970,13 @@ static int __devinit sky2_init(struct sky2_hw *hw) break; case CHIP_ID_YUKON_UL_2: + hw->flags = SKY2_HW_GIGABIT + | SKY2_HW_ADV_POWER_CTL; + break; + case CHIP_ID_YUKON_OPT: hw->flags = SKY2_HW_GIGABIT + | SKY2_HW_NEW_LE | SKY2_HW_ADV_POWER_CTL; break; @@ -3077,6 +3084,7 @@ static void sky2_reset(struct sky2_hw *hw) reg <<= PSM_CONFIG_REG4_TIMER_PHY_LINK_DETECT_BASE; /* reset PHY Link Detect */ + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); sky2_pci_write16(hw, PSM_CONFIG_REG4, reg | PSM_CONFIG_REG4_RST_PHY_LINK_DETECT); sky2_pci_write16(hw, PSM_CONFIG_REG4, reg); @@ -3094,6 +3102,7 @@ static void sky2_reset(struct sky2_hw *hw) /* restore the PCIe Link Control register */ sky2_pci_write16(hw, cap + PCI_EXP_LNKCTL, reg); } + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); /* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */ sky2_write32(hw, Y2_PEX_PHY_DATA, PEX_DB_ACCESS | (0x08UL << 16)); diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index ae4983a5127dba33093a5e4d84670202ec3f2bf0..ea4fae79d6ecc38171422c3128d2b6c4657d515c 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -534,9 +534,9 @@ static inline void smc_rcv(struct net_device *dev) #define smc_special_lock(lock, flags) spin_lock_irqsave(lock, flags) #define smc_special_unlock(lock, flags) spin_unlock_irqrestore(lock, flags) #else -#define smc_special_trylock(lock, flags) (1) -#define smc_special_lock(lock, flags) do { } while (0) -#define smc_special_unlock(lock, flags) do { } while (0) +#define smc_special_trylock(lock, flags) (flags == flags) +#define smc_special_lock(lock, flags) do { flags = 0; } while (0) +#define smc_special_unlock(lock, flags) do { flags = 0; } while (0) #endif /* @@ -2387,7 +2387,7 @@ static int smc_drv_resume(struct device *dev) if (ndev) { struct smc_local *lp = netdev_priv(ndev); - smc_enable_device(dev); + smc_enable_device(pdev); if (netif_running(ndev)) { smc_reset(ndev); smc_enable(ndev); diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 7815bfc300f5705bec3691c5e42ea0067bc5dd81..54799544bda3d1623ac77e84beb253cedd090fef 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -206,21 +206,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) } } -#elif defined(CONFIG_ARCH_OMAP) - -/* We can only do 16-bit reads and writes in the static memory space. */ -#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_inw(a, r) readw((a) + (r)) -#define SMC_outw(v, a, r) writew(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) -#define SMC_IRQ_FLAGS (-1) /* from resource */ - #elif defined(CONFIG_SH_SH4202_MICRODEV) #define SMC_CAN_USE_8BIT 0 diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 3b80e8d2d621fd235408d91bd0cd236eb45eb23f..f1d64ef67efad9174122f6832b7e5b11fa892c3f 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -716,7 +716,7 @@ static int kaweth_open(struct net_device *net) return 0; err_out: - usb_autopm_enable(kaweth->intf); + usb_autopm_put_interface(kaweth->intf); return -EIO; } @@ -753,7 +753,7 @@ static int kaweth_close(struct net_device *net) kaweth->status &= ~KAWETH_STATUS_CLOSING; - usb_autopm_enable(kaweth->intf); + usb_autopm_put_interface(kaweth->intf); return 0; } diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 63099c58a6ddd7a92f616ca196141becbd7ad463..3a15de56df9caa31b818139dbcd75e2dc99e5cc8 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -153,15 +153,14 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev) struct net_device *rcv = NULL; struct veth_priv *priv, *rcv_priv; struct veth_net_stats *stats, *rcv_stats; - int length, cpu; + int length; priv = netdev_priv(dev); rcv = priv->peer; rcv_priv = netdev_priv(rcv); - cpu = smp_processor_id(); - stats = per_cpu_ptr(priv->stats, cpu); - rcv_stats = per_cpu_ptr(rcv_priv->stats, cpu); + stats = this_cpu_ptr(priv->stats); + rcv_stats = this_cpu_ptr(rcv_priv->stats); if (!(rcv->flags & IFF_UP)) goto tx_drop; diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 47e84ef355c58862ba7632345ca964da57f5e692..3b48681f8a0d50c8db077e8fccd93021a4239f1c 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -579,7 +579,7 @@ void i2400mu_disconnect(struct usb_interface *iface) * * As well, the device might refuse going to sleep for whichever * reason. In this case we just fail. For system suspend/hibernate, - * we *can't* fail. We look at usb_dev->auto_pm to see if the + * we *can't* fail. We check PM_EVENT_AUTO to see if the * suspend call comes from the USB stack or from the system and act * in consequence. * @@ -591,14 +591,11 @@ int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg) int result = 0; struct device *dev = &iface->dev; struct i2400mu *i2400mu = usb_get_intfdata(iface); -#ifdef CONFIG_PM - struct usb_device *usb_dev = i2400mu->usb_dev; -#endif unsigned is_autosuspend = 0; struct i2400m *i2400m = &i2400mu->i2400m; #ifdef CONFIG_PM - if (usb_dev->auto_pm > 0) + if (pm_msg.event & PM_EVENT_AUTO) is_autosuspend = 1; #endif diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 81ea52c4faff10eb5c7d79103ded1c98a32949f2..5d1c8677f180f2723aa0e986ce6774a353a80477 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -97,6 +97,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; int ret; u16 val; + u32 cksum, offset; /* * Read values from EEPROM and store them in the capability structure @@ -111,7 +112,6 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0) return 0; -#ifdef notyet /* * Validate the checksum of the EEPROM date. There are some * devices with invalid EEPROMs. @@ -124,7 +124,6 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); return -EIO; } -#endif AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version), ee_ant_gain); diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index d495890355d95f24b226114bf264370626e53d05..60f547503d75a2eb7edc3bf4f42495f4a74b10a4 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -79,6 +79,8 @@ static const struct pci_device_id ath5k_led_devices[] = { { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) }, /* IBM-specific AR5212 (all others) */ { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, + /* Dell Vostro A860 (shahar@shahar-or.co.il) */ + { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0112), ATH_LED(3, 0) }, { } }; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 564c6cb1c2b4b0530a90415c7a4bb2c71ff49e71..2a11cc57ceeae891b2ef7a0f8c1bbf105e9a7f17 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2078,7 +2078,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) &txq->axq_q, lastbf->list.prev); txq->axq_depth--; - txok = (ds->ds_txstat.ts_status == 0); + txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_FILT); txq->axq_tx_inprogress = false; spin_unlock_bh(&txq->axq_lock); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 71e5c996bd0946749aa8ae1dae639a7ea1818f7f..4c41cfe44f261494eceaa4080d85d7889344b42c 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1784,7 +1784,10 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) dma_reason[0], dma_reason[1], dma_reason[2], dma_reason[3], dma_reason[4], dma_reason[5]); - b43_controller_restart(dev, "DMA error"); + b43err(dev->wl, "This device does not support DMA " + "on your system. Please use PIO instead.\n"); + b43err(dev->wl, "CONFIG_B43_FORCE_PIO must be set in " + "your kernel configuration.\n"); return; } if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 58b132f9cf2821c0c03015f104147d8a5768b311..00da5e152d46330de2bc701f6969434c8853f092 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1353,7 +1353,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) if (priv->stations[sta_id].tid[tid].agg.state == IWL_EMPTYING_HW_QUEUE_ADDBA) { IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); - ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid); + ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; return 0; } diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 0cb5ecc822a8e34544fc3ff861d629e4a8d7a745..59d49159cf2acc1b7c0497d20a642cf762290393 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -84,7 +84,8 @@ struct rxd_ops { int rxd_size; void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr); void (*rxd_refill)(void *rxd, dma_addr_t addr, int len); - int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status); + int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status, + __le16 *qos); }; struct mwl8k_device_info { @@ -184,7 +185,7 @@ struct mwl8k_priv { /* PHY parameters */ struct ieee80211_supported_band band; struct ieee80211_channel channels[14]; - struct ieee80211_rate rates[13]; + struct ieee80211_rate rates[14]; bool radio_on; bool radio_short_preamble; @@ -220,15 +221,6 @@ struct mwl8k_vif { u8 bssid[ETH_ALEN]; u8 mac_addr[ETH_ALEN]; - /* - * Subset of supported legacy rates. - * Intersection of AP and STA supported rates. - */ - struct ieee80211_rate legacy_rates[13]; - - /* number of supported legacy rates */ - u8 legacy_nrates; - /* Index into station database.Returned by update_sta_db call */ u8 peer_id; @@ -266,6 +258,11 @@ static const struct ieee80211_rate mwl8k_rates[] = { { .bitrate = 360, .hw_value = 72, }, { .bitrate = 480, .hw_value = 96, }, { .bitrate = 540, .hw_value = 108, }, + { .bitrate = 720, .hw_value = 144, }, +}; + +static const u8 mwl8k_rateids[12] = { + 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, }; /* Set or get info from Firmware */ @@ -574,7 +571,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) "helper image\n", pci_name(priv->pdev)); return rc; } - msleep(1); + msleep(5); rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); } else { @@ -591,9 +588,8 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) iowrite32(MWL8K_MODE_AP, priv->regs + MWL8K_HIU_GEN_PTR); else iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); - msleep(1); - loops = 200000; + loops = 500000; do { u32 ready_code; @@ -633,9 +629,6 @@ struct ewc_ht_info { /* Peer Entry flags - used to define the type of the peer node */ #define MWL8K_PEER_TYPE_ACCESSPOINT 2 -#define MWL8K_IEEE_LEGACY_DATA_RATES 13 -#define MWL8K_MCS_BITMAP_SIZE 16 - struct peer_capability_info { /* Peer type - AP vs. STA. */ __u8 peer_type; @@ -652,10 +645,10 @@ struct peer_capability_info { struct ewc_ht_info ewc_info; /* Legacy rate table. Intersection of our rates and peer rates. */ - __u8 legacy_rates[MWL8K_IEEE_LEGACY_DATA_RATES]; + __u8 legacy_rates[12]; /* HT rate table. Intersection of our rates and peer rates. */ - __u8 ht_rates[MWL8K_MCS_BITMAP_SIZE]; + __u8 ht_rates[16]; __u8 pad[16]; /* If set, interoperability mode, no proprietary extensions. */ @@ -706,55 +699,64 @@ static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len) struct mwl8k_dma_data { __le16 fwlen; struct ieee80211_hdr wh; + char data[0]; } __attribute__((packed)); /* Routines to add/remove DMA header from skb. */ -static inline void mwl8k_remove_dma_header(struct sk_buff *skb) +static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos) { - struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)skb->data; - void *dst, *src = &tr->wh; - int hdrlen = ieee80211_hdrlen(tr->wh.frame_control); - u16 space = sizeof(struct mwl8k_dma_data) - hdrlen; + struct mwl8k_dma_data *tr; + int hdrlen; - dst = (void *)tr + space; - if (dst != src) { - memmove(dst, src, hdrlen); - skb_pull(skb, space); + tr = (struct mwl8k_dma_data *)skb->data; + hdrlen = ieee80211_hdrlen(tr->wh.frame_control); + + if (hdrlen != sizeof(tr->wh)) { + if (ieee80211_is_data_qos(tr->wh.frame_control)) { + memmove(tr->data - hdrlen, &tr->wh, hdrlen - 2); + *((__le16 *)(tr->data - 2)) = qos; + } else { + memmove(tr->data - hdrlen, &tr->wh, hdrlen); + } } + + if (hdrlen != sizeof(*tr)) + skb_pull(skb, sizeof(*tr) - hdrlen); } static inline void mwl8k_add_dma_header(struct sk_buff *skb) { struct ieee80211_hdr *wh; - u32 hdrlen, pktlen; + int hdrlen; struct mwl8k_dma_data *tr; + /* + * Add a firmware DMA header; the firmware requires that we + * present a 2-byte payload length followed by a 4-address + * header (without QoS field), followed (optionally) by any + * WEP/ExtIV header (but only filled in for CCMP). + */ wh = (struct ieee80211_hdr *)skb->data; + hdrlen = ieee80211_hdrlen(wh->frame_control); - pktlen = skb->len; + if (hdrlen != sizeof(*tr)) + skb_push(skb, sizeof(*tr) - hdrlen); - /* - * Copy up/down the 802.11 header; the firmware requires - * we present a 2-byte payload length followed by a - * 4-address header (w/o QoS), followed (optionally) by - * any WEP/ExtIV header (but only filled in for CCMP). - */ - if (hdrlen != sizeof(struct mwl8k_dma_data)) - skb_push(skb, sizeof(struct mwl8k_dma_data) - hdrlen); + if (ieee80211_is_data_qos(wh->frame_control)) + hdrlen -= 2; tr = (struct mwl8k_dma_data *)skb->data; if (wh != &tr->wh) memmove(&tr->wh, wh, hdrlen); - - /* Clear addr4 */ - memset(tr->wh.addr4, 0, ETH_ALEN); + if (hdrlen != sizeof(tr->wh)) + memset(((void *)&tr->wh) + hdrlen, 0, sizeof(tr->wh) - hdrlen); /* * Firmware length is the length of the fully formed "802.11 * payload". That is, everything except for the 802.11 header. * This includes all crypto material including the MIC. */ - tr->fwlen = cpu_to_le16(pktlen - hdrlen); + tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr)); } @@ -779,6 +781,10 @@ struct mwl8k_rxd_8366 { __u8 rx_ctrl; } __attribute__((packed)); +#define MWL8K_8366_RATE_INFO_MCS_FORMAT 0x80 +#define MWL8K_8366_RATE_INFO_40MHZ 0x40 +#define MWL8K_8366_RATE_INFO_RATEID(x) ((x) & 0x3f) + #define MWL8K_8366_RX_CTRL_OWNED_BY_HOST 0x80 static void mwl8k_rxd_8366_init(void *_rxd, dma_addr_t next_dma_addr) @@ -800,7 +806,8 @@ static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len) } static int -mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status) +mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status, + __le16 *qos) { struct mwl8k_rxd_8366 *rxd = _rxd; @@ -813,9 +820,11 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status) status->signal = -rxd->rssi; status->noise = -rxd->noise_floor; - if (rxd->rate & 0x80) { + if (rxd->rate & MWL8K_8366_RATE_INFO_MCS_FORMAT) { status->flag |= RX_FLAG_HT; - status->rate_idx = rxd->rate & 0x7f; + if (rxd->rate & MWL8K_8366_RATE_INFO_40MHZ) + status->flag |= RX_FLAG_40MHZ; + status->rate_idx = MWL8K_8366_RATE_INFO_RATEID(rxd->rate); } else { int i; @@ -830,6 +839,8 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status) status->band = IEEE80211_BAND_2GHZ; status->freq = ieee80211_channel_to_frequency(rxd->channel); + *qos = rxd->qos_control; + return le16_to_cpu(rxd->pkt_len); } @@ -888,7 +899,8 @@ static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len) } static int -mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status) +mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status, + __le16 *qos) { struct mwl8k_rxd_8687 *rxd = _rxd; u16 rate_info; @@ -903,7 +915,6 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status) status->signal = -rxd->rssi; status->noise = -rxd->noise_level; - status->qual = rxd->link_quality; status->antenna = MWL8K_8687_RATE_INFO_ANTSELECT(rate_info); status->rate_idx = MWL8K_8687_RATE_INFO_RATEID(rate_info); @@ -919,6 +930,8 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status) status->band = IEEE80211_BAND_2GHZ; status->freq = ieee80211_channel_to_frequency(rxd->channel); + *qos = rxd->qos_control; + return le16_to_cpu(rxd->pkt_len); } @@ -1090,6 +1103,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) void *rxd; int pkt_len; struct ieee80211_rx_status status; + __le16 qos; skb = rxq->buf[rxq->head].skb; if (skb == NULL) @@ -1097,7 +1111,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size); - pkt_len = priv->rxd_ops->rxd_process(rxd, &status); + pkt_len = priv->rxd_ops->rxd_process(rxd, &status, &qos); if (pkt_len < 0) break; @@ -1115,7 +1129,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) rxq->rxd_count--; skb_put(skb, pkt_len); - mwl8k_remove_dma_header(skb); + mwl8k_remove_dma_header(skb, qos); /* * Check for a pending join operation. Save a @@ -1221,99 +1235,106 @@ static inline void mwl8k_tx_start(struct mwl8k_priv *priv) ioread32(priv->regs + MWL8K_HIU_INT_CODE); } -struct mwl8k_txq_info { - u32 fw_owned; - u32 drv_owned; - u32 unused; - u32 len; - u32 head; - u32 tail; -}; - -static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv, - struct mwl8k_txq_info *txinfo) +static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw) { - int count, desc, status; - struct mwl8k_tx_queue *txq; - struct mwl8k_tx_desc *tx_desc; - int ndescs = 0; + struct mwl8k_priv *priv = hw->priv; + int i; - memset(txinfo, 0, MWL8K_TX_QUEUES * sizeof(struct mwl8k_txq_info)); + for (i = 0; i < MWL8K_TX_QUEUES; i++) { + struct mwl8k_tx_queue *txq = priv->txq + i; + int fw_owned = 0; + int drv_owned = 0; + int unused = 0; + int desc; - for (count = 0; count < MWL8K_TX_QUEUES; count++) { - txq = priv->txq + count; - txinfo[count].len = txq->stats.len; - txinfo[count].head = txq->head; - txinfo[count].tail = txq->tail; for (desc = 0; desc < MWL8K_TX_DESCS; desc++) { - tx_desc = txq->txd + desc; - status = le32_to_cpu(tx_desc->status); + struct mwl8k_tx_desc *tx_desc = txq->txd + desc; + u32 status; + status = le32_to_cpu(tx_desc->status); if (status & MWL8K_TXD_STATUS_FW_OWNED) - txinfo[count].fw_owned++; + fw_owned++; else - txinfo[count].drv_owned++; + drv_owned++; if (tx_desc->pkt_len == 0) - txinfo[count].unused++; + unused++; } - } - return ndescs; + printk(KERN_ERR "%s: txq[%d] len=%d head=%d tail=%d " + "fw_owned=%d drv_owned=%d unused=%d\n", + wiphy_name(hw->wiphy), i, + txq->stats.len, txq->head, txq->tail, + fw_owned, drv_owned, unused); + } } /* * Must be called with priv->fw_mutex held and tx queues stopped. */ +#define MWL8K_TX_WAIT_TIMEOUT_MS 1000 + static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) { struct mwl8k_priv *priv = hw->priv; DECLARE_COMPLETION_ONSTACK(tx_wait); - u32 count; - unsigned long timeout; + int retry; + int rc; might_sleep(); + /* + * The TX queues are stopped at this point, so this test + * doesn't need to take ->tx_lock. + */ + if (!priv->pending_tx_pkts) + return 0; + + retry = 0; + rc = 0; + spin_lock_bh(&priv->tx_lock); - count = priv->pending_tx_pkts; - if (count) - priv->tx_wait = &tx_wait; - spin_unlock_bh(&priv->tx_lock); + priv->tx_wait = &tx_wait; + while (!rc) { + int oldcount; + unsigned long timeout; - if (count) { - struct mwl8k_txq_info txinfo[MWL8K_TX_QUEUES]; - int index; - int newcount; + oldcount = priv->pending_tx_pkts; + spin_unlock_bh(&priv->tx_lock); timeout = wait_for_completion_timeout(&tx_wait, - msecs_to_jiffies(5000)); - if (timeout) - return 0; - + msecs_to_jiffies(MWL8K_TX_WAIT_TIMEOUT_MS)); spin_lock_bh(&priv->tx_lock); - priv->tx_wait = NULL; - newcount = priv->pending_tx_pkts; - mwl8k_scan_tx_ring(priv, txinfo); - spin_unlock_bh(&priv->tx_lock); - printk(KERN_ERR "%s(%u) TIMEDOUT:5000ms Pend:%u-->%u\n", - __func__, __LINE__, count, newcount); + if (timeout) { + WARN_ON(priv->pending_tx_pkts); + if (retry) { + printk(KERN_NOTICE "%s: tx rings drained\n", + wiphy_name(hw->wiphy)); + } + break; + } - for (index = 0; index < MWL8K_TX_QUEUES; index++) - printk(KERN_ERR "TXQ:%u L:%u H:%u T:%u FW:%u " - "DRV:%u U:%u\n", - index, - txinfo[index].len, - txinfo[index].head, - txinfo[index].tail, - txinfo[index].fw_owned, - txinfo[index].drv_owned, - txinfo[index].unused); + if (priv->pending_tx_pkts < oldcount) { + printk(KERN_NOTICE "%s: timeout waiting for tx " + "rings to drain (%d -> %d pkts), retrying\n", + wiphy_name(hw->wiphy), oldcount, + priv->pending_tx_pkts); + retry = 1; + continue; + } - return -ETIMEDOUT; + priv->tx_wait = NULL; + + printk(KERN_ERR "%s: tx rings stuck for %d ms\n", + wiphy_name(hw->wiphy), MWL8K_TX_WAIT_TIMEOUT_MS); + mwl8k_dump_tx_rings(hw); + + rc = -ETIMEDOUT; } + spin_unlock_bh(&priv->tx_lock); - return 0; + return rc; } #define MWL8K_TXD_SUCCESS(status) \ @@ -1361,7 +1382,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) BUG_ON(skb == NULL); pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE); - mwl8k_remove_dma_header(skb); + mwl8k_remove_dma_header(skb, tx_desc->qos_control); /* Mark descriptor as unused */ tx_desc->pkt_phys_addr = 0; @@ -1563,8 +1584,8 @@ static void mwl8k_fw_unlock(struct ieee80211_hw *hw) * Command processing. */ -/* Timeout firmware commands after 2000ms */ -#define MWL8K_CMD_TIMEOUT_MS 2000 +/* Timeout firmware commands after 10s */ +#define MWL8K_CMD_TIMEOUT_MS 10000 static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) { @@ -1615,12 +1636,21 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) MWL8K_CMD_TIMEOUT_MS); rc = -ETIMEDOUT; } else { + int ms; + + ms = MWL8K_CMD_TIMEOUT_MS - jiffies_to_msecs(timeout); + rc = cmd->result ? -EINVAL : 0; if (rc) printk(KERN_ERR "%s: Command %s error 0x%x\n", wiphy_name(hw->wiphy), mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), le16_to_cpu(cmd->result)); + else if (ms > 2000) + printk(KERN_NOTICE "%s: Command %s took %d ms\n", + wiphy_name(hw->wiphy), + mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), + ms); } return rc; @@ -2439,8 +2469,6 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, /* * CMD_FINALIZE_JOIN. */ - -/* FJ beacon buffer size is compiled into the firmware. */ #define MWL8K_FJ_BEACON_MAXLEN 128 struct mwl8k_cmd_finalize_join { @@ -2450,17 +2478,13 @@ struct mwl8k_cmd_finalize_join { } __attribute__((packed)); static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, - __u16 framelen, __u16 dtim) + int framelen, int dtim) { struct mwl8k_cmd_finalize_join *cmd; struct ieee80211_mgmt *payload = frame; - u16 hdrlen; - u32 payload_len; + int payload_len; int rc; - if (frame == NULL) - return -EINVAL; - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) return -ENOMEM; @@ -2469,24 +2493,17 @@ static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, cmd->header.length = cpu_to_le16(sizeof(*cmd)); cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1); - hdrlen = ieee80211_hdrlen(payload->frame_control); - - payload_len = framelen > hdrlen ? framelen - hdrlen : 0; - - /* XXX TBD Might just have to abort and return an error */ - if (payload_len > MWL8K_FJ_BEACON_MAXLEN) - printk(KERN_ERR "%s(): WARNING: Incomplete beacon " - "sent to firmware. Sz=%u MAX=%u\n", __func__, - payload_len, MWL8K_FJ_BEACON_MAXLEN); - - if (payload_len > MWL8K_FJ_BEACON_MAXLEN) + payload_len = framelen - ieee80211_hdrlen(payload->frame_control); + if (payload_len < 0) + payload_len = 0; + else if (payload_len > MWL8K_FJ_BEACON_MAXLEN) payload_len = MWL8K_FJ_BEACON_MAXLEN; - if (payload && payload_len) - memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); + memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); + return rc; } @@ -2515,9 +2532,7 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, struct ieee80211_bss_conf *info = &mv_vif->bss_info; struct mwl8k_cmd_update_sta_db *cmd; struct peer_capability_info *peer_info; - struct ieee80211_rate *bitrates = mv_vif->legacy_rates; int rc; - __u8 count, *rates; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) @@ -2536,13 +2551,11 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, /* Build peer_info block */ peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; peer_info->basic_caps = cpu_to_le16(info->assoc_capability); + memcpy(peer_info->legacy_rates, mwl8k_rateids, + sizeof(mwl8k_rateids)); peer_info->interop = 1; peer_info->amsdu_enabled = 0; - rates = peer_info->legacy_rates; - for (count = 0; count < mv_vif->legacy_nrates; count++) - rates[count] = bitrates[count].hw_value; - rc = mwl8k_post_cmd(hw, &cmd->header); if (rc == 0) mv_vif->peer_id = peer_info->station_id; @@ -2565,8 +2578,6 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, /* * CMD_SET_AID. */ -#define MWL8K_RATE_INDEX_MAX_ARRAY 14 - #define MWL8K_FRAME_PROT_DISABLED 0x00 #define MWL8K_FRAME_PROT_11G 0x07 #define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 @@ -2579,7 +2590,7 @@ struct mwl8k_cmd_update_set_aid { /* AP's MAC address (BSSID) */ __u8 bssid[ETH_ALEN]; __le16 protection_mode; - __u8 supp_rates[MWL8K_RATE_INDEX_MAX_ARRAY]; + __u8 supp_rates[14]; } __attribute__((packed)); static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, @@ -2588,8 +2599,6 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); struct ieee80211_bss_conf *info = &mv_vif->bss_info; struct mwl8k_cmd_update_set_aid *cmd; - struct ieee80211_rate *bitrates = mv_vif->legacy_rates; - int count; u16 prot_mode; int rc; @@ -2621,8 +2630,7 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, } cmd->protection_mode = cpu_to_le16(prot_mode); - for (count = 0; count < mv_vif->legacy_nrates; count++) - cmd->supp_rates[count] = bitrates[count].hw_value; + memcpy(cmd->supp_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2635,20 +2643,17 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, */ struct mwl8k_cmd_update_rateset { struct mwl8k_cmd_pkt header; - __u8 legacy_rates[MWL8K_RATE_INDEX_MAX_ARRAY]; + __u8 legacy_rates[14]; /* Bitmap for supported MCS codes. */ - __u8 mcs_set[MWL8K_IEEE_LEGACY_DATA_RATES]; - __u8 reserved[MWL8K_IEEE_LEGACY_DATA_RATES]; + __u8 mcs_set[16]; + __u8 reserved[16]; } __attribute__((packed)); static int mwl8k_update_rateset(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); struct mwl8k_cmd_update_rateset *cmd; - struct ieee80211_rate *bitrates = mv_vif->legacy_rates; - int count; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -2657,9 +2662,7 @@ static int mwl8k_update_rateset(struct ieee80211_hw *hw, cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - - for (count = 0; count < mv_vif->legacy_nrates; count++) - cmd->legacy_rates[count] = bitrates[count].hw_value; + memcpy(cmd->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2932,11 +2935,6 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, /* Back pointer to parent config block */ mwl8k_vif->priv = priv; - /* Setup initial PHY parameters */ - memcpy(mwl8k_vif->legacy_rates, - priv->rates, sizeof(mwl8k_vif->legacy_rates)); - mwl8k_vif->legacy_nrates = ARRAY_SIZE(priv->rates); - /* Set Initial sequence number to zero */ mwl8k_vif->seqno = 0; @@ -3014,9 +3012,6 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); int rc; - if (changed & BSS_CHANGED_BSSID) - memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN); - if ((changed & BSS_CHANGED_ASSOC) == 0) return; @@ -3030,6 +3025,8 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, memcpy(&mwl8k_vif->bss_info, info, sizeof(struct ieee80211_bss_conf)); + memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN); + /* Install rates */ rc = mwl8k_update_rateset(hw, vif); if (rc) @@ -3366,7 +3363,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, if (rc) { printk(KERN_ERR "%s: Cannot obtain PCI resources\n", MWL8K_NAME); - return rc; + goto err_disable_device; } pci_set_master(pdev); @@ -3597,6 +3594,8 @@ err_iounmap: err_free_reg: pci_release_regions(pdev); + +err_disable_device: pci_disable_device(pdev); return rc; diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c index 84200da900b62e40a2894037c862a349e91d7131..fb157eb889ca19f20d507e7933b471ba8c564385 100644 --- a/drivers/net/wireless/orinoco/hermes_dld.c +++ b/drivers/net/wireless/orinoco/hermes_dld.c @@ -427,7 +427,7 @@ int hermesi_program_init(hermes_t *hw, u32 offset) if (err) return err; - pr_debug(KERN_DEBUG PFX "Enabling volatile, EP 0x%08x\n", offset); + pr_debug(PFX "Enabling volatile, EP 0x%08x\n", offset); err = hermes_doicmd_wait(hw, HERMES_PROGRAM_ENABLE_VOLATILE, offset & 0xFFFFu, diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h index abb4907cf2960925feeaec25a146b13e7d28e5e2..6af0f3f71f3a4b6f01789da274a31fdbcba00897 100644 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187.h @@ -23,6 +23,7 @@ #define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */ #define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */ #define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */ +#define RTL8187_EEPROM_SELECT_GPIO 0x3B #define RTL8187_REQT_READ 0xC0 #define RTL8187_REQT_WRITE 0x40 @@ -31,6 +32,9 @@ #define RTL8187_MAX_RX 0x9C4 +#define RFKILL_MASK_8187_89_97 0x2 +#define RFKILL_MASK_8198 0x4 + struct rtl8187_rx_info { struct urb *urb; struct ieee80211_hw *dev; @@ -104,6 +108,7 @@ struct rtl8187_priv { struct delayed_work work; struct ieee80211_hw *dev; #ifdef CONFIG_RTL8187_LEDS + struct rtl8187_led led_radio; struct rtl8187_led led_tx; struct rtl8187_led led_rx; struct delayed_work led_on; @@ -122,6 +127,7 @@ struct rtl8187_priv { u8 noise; u8 slot_time; u8 aifsn[4]; + u8 rfkill_mask; struct { __le64 buf; struct sk_buff_head queue; diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 76973b8c7099554f9a0e0bbef6fd3d6032d3321c..bc5726dd5fe49f5fc7582f4a94d6bce4402de7af 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -1322,6 +1322,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, struct ieee80211_channel *channel; const char *chip_name; u16 txpwr, reg; + u16 product_id = le16_to_cpu(udev->descriptor.idProduct); int err, i; dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops); @@ -1481,6 +1482,13 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, (*channel++).hw_value = txpwr & 0xFF; (*channel++).hw_value = txpwr >> 8; } + /* Handle the differing rfkill GPIO bit in different models */ + priv->rfkill_mask = RFKILL_MASK_8187_89_97; + if (product_id == 0x8197 || product_id == 0x8198) { + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_SELECT_GPIO, ®); + if (reg & 0xFF00) + priv->rfkill_mask = RFKILL_MASK_8198; + } /* * XXX: Once this driver supports anything that requires @@ -1509,9 +1517,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, mutex_init(&priv->conf_mutex); skb_queue_head_init(&priv->b_tx_status.queue); - printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n", + printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s, rfkill mask %d\n", wiphy_name(dev->wiphy), dev->wiphy->perm_addr, - chip_name, priv->asic_rev, priv->rf->name); + chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask); #ifdef CONFIG_RTL8187_LEDS eeprom_93cx6_read(&eeprom, 0x3F, ®); diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c index cf8a4a40fdf677ebb06f99a9311c25ddd96981a2..ded44c045eb24307a6377e18eec161a27247d922 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c @@ -105,19 +105,36 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev, struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led, led_dev); struct ieee80211_hw *hw = led->dev; - struct rtl8187_priv *priv = hw->priv; + struct rtl8187_priv *priv; + static bool radio_on; - if (brightness == LED_OFF) { - ieee80211_queue_delayed_work(hw, &priv->led_off, 0); - /* The LED is off for 1/20 sec so that it just blinks. */ - ieee80211_queue_delayed_work(hw, &priv->led_on, HZ / 20); - } else - ieee80211_queue_delayed_work(hw, &priv->led_on, 0); + if (!hw) + return; + priv = hw->priv; + if (led->is_radio) { + if (brightness == LED_FULL) { + ieee80211_queue_delayed_work(hw, &priv->led_on, 0); + radio_on = true; + } else if (radio_on) { + radio_on = false; + cancel_delayed_work_sync(&priv->led_on); + ieee80211_queue_delayed_work(hw, &priv->led_off, 0); + } + } else if (radio_on) { + if (brightness == LED_OFF) { + ieee80211_queue_delayed_work(hw, &priv->led_off, 0); + /* The LED is off for 1/20 sec - it just blinks. */ + ieee80211_queue_delayed_work(hw, &priv->led_on, + HZ / 20); + } else + ieee80211_queue_delayed_work(hw, &priv->led_on, 0); + } } static int rtl8187_register_led(struct ieee80211_hw *dev, struct rtl8187_led *led, const char *name, - const char *default_trigger, u8 ledpin) + const char *default_trigger, u8 ledpin, + bool is_radio) { int err; struct rtl8187_priv *priv = dev->priv; @@ -128,6 +145,7 @@ static int rtl8187_register_led(struct ieee80211_hw *dev, return -EINVAL; led->dev = dev; led->ledpin = ledpin; + led->is_radio = is_radio; strncpy(led->name, name, sizeof(led->name)); led->led_dev.name = led->name; @@ -145,7 +163,11 @@ static int rtl8187_register_led(struct ieee80211_hw *dev, static void rtl8187_unregister_led(struct rtl8187_led *led) { + struct ieee80211_hw *hw = led->dev; + struct rtl8187_priv *priv = hw->priv; + led_classdev_unregister(&led->led_dev); + flush_delayed_work(&priv->led_off); led->dev = NULL; } @@ -182,34 +204,38 @@ void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid) INIT_DELAYED_WORK(&priv->led_on, led_turn_on); INIT_DELAYED_WORK(&priv->led_off, led_turn_off); + snprintf(name, sizeof(name), + "rtl8187-%s::radio", wiphy_name(dev->wiphy)); + err = rtl8187_register_led(dev, &priv->led_radio, name, + ieee80211_get_radio_led_name(dev), ledpin, true); + if (err) + return; + snprintf(name, sizeof(name), "rtl8187-%s::tx", wiphy_name(dev->wiphy)); err = rtl8187_register_led(dev, &priv->led_tx, name, - ieee80211_get_tx_led_name(dev), ledpin); + ieee80211_get_tx_led_name(dev), ledpin, false); if (err) - goto error; + goto err_tx; + snprintf(name, sizeof(name), "rtl8187-%s::rx", wiphy_name(dev->wiphy)); err = rtl8187_register_led(dev, &priv->led_rx, name, - ieee80211_get_rx_led_name(dev), ledpin); - if (!err) { - ieee80211_queue_delayed_work(dev, &priv->led_on, 0); + ieee80211_get_rx_led_name(dev), ledpin, false); + if (!err) return; - } - /* registration of RX LED failed - unregister TX */ + + /* registration of RX LED failed - unregister */ rtl8187_unregister_led(&priv->led_tx); -error: - /* If registration of either failed, cancel delayed work */ - cancel_delayed_work_sync(&priv->led_off); - cancel_delayed_work_sync(&priv->led_on); +err_tx: + rtl8187_unregister_led(&priv->led_radio); } void rtl8187_leds_exit(struct ieee80211_hw *dev) { struct rtl8187_priv *priv = dev->priv; - /* turn the LED off before exiting */ - ieee80211_queue_delayed_work(dev, &priv->led_off, 0); + rtl8187_unregister_led(&priv->led_radio); rtl8187_unregister_led(&priv->led_rx); rtl8187_unregister_led(&priv->led_tx); cancel_delayed_work_sync(&priv->led_off); diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.h b/drivers/net/wireless/rtl818x/rtl8187_leds.h index a0332027aeadf1c42fbfc52e590a1531cb03cad2..efe8041bdda42af9ea74e240171b83580f140aaf 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.h +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.h @@ -47,6 +47,8 @@ struct rtl8187_led { u8 ledpin; /* The unique name string for this LED device. */ char name[RTL8187_LED_MAX_NAME_LEN + 1]; + /* If the LED is radio or tx/rx */ + bool is_radio; }; void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code); diff --git a/drivers/net/wireless/rtl818x/rtl8187_rfkill.c b/drivers/net/wireless/rtl818x/rtl8187_rfkill.c index cad8037ab2af3a4d136194dcdf3e322d65495ad6..03555e1e0cab29cb0d8b4698b71d994d3ec11296 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_rfkill.c +++ b/drivers/net/wireless/rtl818x/rtl8187_rfkill.c @@ -25,10 +25,10 @@ static bool rtl8187_is_radio_enabled(struct rtl8187_priv *priv) u8 gpio; gpio = rtl818x_ioread8(priv, &priv->map->GPIO0); - rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~0x02); + rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~priv->rfkill_mask); gpio = rtl818x_ioread8(priv, &priv->map->GPIO1); - return gpio & 0x02; + return gpio & priv->rfkill_mask; } void rtl8187_rfkill_init(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index ff4be7bf5d360f8223a7cc3fad7b383fdb75d191..2f50a256efa5a00fa18b45e94ce9be3130f7628c 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -629,10 +629,6 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) goto out_sleep; } - ret = wl1251_build_null_data(wl); - if (ret < 0) - goto out_sleep; - if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { wl1251_debug(DEBUG_PSM, "psm enabled"); @@ -1110,6 +1106,21 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, if (ret < 0) goto out; + if (changed & BSS_CHANGED_BSSID) { + memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); + + ret = wl1251_build_null_data(wl); + if (ret < 0) + goto out; + + if (wl->bss_type != BSS_TYPE_IBSS) { + ret = wl1251_join(wl, wl->bss_type, wl->channel, + wl->beacon_int, wl->dtim_period); + if (ret < 0) + goto out_sleep; + } + } + if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { wl->beacon_int = bss_conf->beacon_int; @@ -1169,23 +1180,6 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, } } - if (changed & BSS_CHANGED_BSSID) { - memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); - - ret = wl1251_build_null_data(wl); - if (ret < 0) - goto out; - - if (wl->bss_type != BSS_TYPE_IBSS) { - ret = wl1251_join(wl, wl->bss_type, wl->channel, - wl->beacon_int, wl->dtim_period); - if (ret < 0) - goto out_sleep; - wl1251_warning("Set ctsprotect failed %d", ret); - goto out_sleep; - } - } - if (changed & BSS_CHANGED_BEACON) { beacon = ieee80211_beacon_get(hw, vif); ret = wl1251_cmd_template_set(wl, CMD_BEACON, beacon->data, diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index baa051d5bfbe0bcd84bd9f28530ac73f6d4863d8..a869b45d3d37b2f38a986c4dfb0146d10be4416d 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -42,6 +42,7 @@ #include #include +#include #include #include #include diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 298de0f95d70d24d15727ab7b54a28d438854ec2..d58ade170c4b27fd50bf5abc471eac618c4eea3e 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -65,47 +65,322 @@ static int of_platform_device_remove(struct device *dev) return 0; } -static int of_platform_device_suspend(struct device *dev, pm_message_t state) +static void of_platform_device_shutdown(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->suspend) - error = drv->suspend(of_dev, state); - return error; + if (dev->driver && drv->shutdown) + drv->shutdown(of_dev); } -static int of_platform_device_resume(struct device * dev) +#ifdef CONFIG_PM_SLEEP + +static int of_platform_legacy_suspend(struct device *dev, pm_message_t mesg) { struct of_device *of_dev = to_of_device(dev); struct of_platform_driver *drv = to_of_platform_driver(dev->driver); - int error = 0; + int ret = 0; - if (dev->driver && drv->resume) - error = drv->resume(of_dev); - return error; + if (dev->driver && drv->suspend) + ret = drv->suspend(of_dev, mesg); + return ret; } -static void of_platform_device_shutdown(struct device *dev) +static int of_platform_legacy_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 ret = 0; - if (dev->driver && drv->shutdown) - drv->shutdown(of_dev); + if (dev->driver && drv->resume) + ret = drv->resume(of_dev); + return ret; +} + +static int of_platform_pm_prepare(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (drv && drv->pm && drv->pm->prepare) + ret = drv->pm->prepare(dev); + + return ret; +} + +static void of_platform_pm_complete(struct device *dev) +{ + struct device_driver *drv = dev->driver; + + if (drv && drv->pm && drv->pm->complete) + drv->pm->complete(dev); +} + +#ifdef CONFIG_SUSPEND + +static int of_platform_pm_suspend(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->suspend) + ret = drv->pm->suspend(dev); + } else { + ret = of_platform_legacy_suspend(dev, PMSG_SUSPEND); + } + + return ret; } +static int of_platform_pm_suspend_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->suspend_noirq) + ret = drv->pm->suspend_noirq(dev); + } + + return ret; +} + +static int of_platform_pm_resume(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->resume) + ret = drv->pm->resume(dev); + } else { + ret = of_platform_legacy_resume(dev); + } + + return ret; +} + +static int of_platform_pm_resume_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->resume_noirq) + ret = drv->pm->resume_noirq(dev); + } + + return ret; +} + +#else /* !CONFIG_SUSPEND */ + +#define of_platform_pm_suspend NULL +#define of_platform_pm_resume NULL +#define of_platform_pm_suspend_noirq NULL +#define of_platform_pm_resume_noirq NULL + +#endif /* !CONFIG_SUSPEND */ + +#ifdef CONFIG_HIBERNATION + +static int of_platform_pm_freeze(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->freeze) + ret = drv->pm->freeze(dev); + } else { + ret = of_platform_legacy_suspend(dev, PMSG_FREEZE); + } + + return ret; +} + +static int of_platform_pm_freeze_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->freeze_noirq) + ret = drv->pm->freeze_noirq(dev); + } + + return ret; +} + +static int of_platform_pm_thaw(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->thaw) + ret = drv->pm->thaw(dev); + } else { + ret = of_platform_legacy_resume(dev); + } + + return ret; +} + +static int of_platform_pm_thaw_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->thaw_noirq) + ret = drv->pm->thaw_noirq(dev); + } + + return ret; +} + +static int of_platform_pm_poweroff(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->poweroff) + ret = drv->pm->poweroff(dev); + } else { + ret = of_platform_legacy_suspend(dev, PMSG_HIBERNATE); + } + + return ret; +} + +static int of_platform_pm_poweroff_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->poweroff_noirq) + ret = drv->pm->poweroff_noirq(dev); + } + + return ret; +} + +static int of_platform_pm_restore(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->restore) + ret = drv->pm->restore(dev); + } else { + ret = of_platform_legacy_resume(dev); + } + + return ret; +} + +static int of_platform_pm_restore_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->restore_noirq) + ret = drv->pm->restore_noirq(dev); + } + + return ret; +} + +#else /* !CONFIG_HIBERNATION */ + +#define of_platform_pm_freeze NULL +#define of_platform_pm_thaw NULL +#define of_platform_pm_poweroff NULL +#define of_platform_pm_restore NULL +#define of_platform_pm_freeze_noirq NULL +#define of_platform_pm_thaw_noirq NULL +#define of_platform_pm_poweroff_noirq NULL +#define of_platform_pm_restore_noirq NULL + +#endif /* !CONFIG_HIBERNATION */ + +static struct dev_pm_ops of_platform_dev_pm_ops = { + .prepare = of_platform_pm_prepare, + .complete = of_platform_pm_complete, + .suspend = of_platform_pm_suspend, + .resume = of_platform_pm_resume, + .freeze = of_platform_pm_freeze, + .thaw = of_platform_pm_thaw, + .poweroff = of_platform_pm_poweroff, + .restore = of_platform_pm_restore, + .suspend_noirq = of_platform_pm_suspend_noirq, + .resume_noirq = of_platform_pm_resume_noirq, + .freeze_noirq = of_platform_pm_freeze_noirq, + .thaw_noirq = of_platform_pm_thaw_noirq, + .poweroff_noirq = of_platform_pm_poweroff_noirq, + .restore_noirq = of_platform_pm_restore_noirq, +}; + +#define OF_PLATFORM_PM_OPS_PTR (&of_platform_dev_pm_ops) + +#else /* !CONFIG_PM_SLEEP */ + +#define OF_PLATFORM_PM_OPS_PTR NULL + +#endif /* !CONFIG_PM_SLEEP */ + int of_bus_type_init(struct bus_type *bus, const char *name) { bus->name = name; bus->match = of_platform_bus_match; bus->probe = of_platform_device_probe; bus->remove = of_platform_device_remove; - bus->suspend = of_platform_device_suspend; - bus->resume = of_platform_device_resume; bus->shutdown = of_platform_device_shutdown; bus->dev_attrs = of_platform_device_attrs; + bus->pm = OF_PLATFORM_PM_OPS_PTR; return bus_register(bus); } diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index a7aae24f2889a4578ebd90dad52ae72aab916116..166b67ea622f11563a33c539b78c5dafc7c2503f 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -47,7 +47,7 @@ */ static struct ring_buffer *op_ring_buffer_read; static struct ring_buffer *op_ring_buffer_write; -DEFINE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer); +DEFINE_PER_CPU(struct oprofile_cpu_buffer, op_cpu_buffer); static void wq_sync_buffer(struct work_struct *work); @@ -61,8 +61,7 @@ unsigned long oprofile_get_cpu_buffer_size(void) void oprofile_cpu_buffer_inc_smpl_lost(void) { - struct oprofile_cpu_buffer *cpu_buf - = &__get_cpu_var(cpu_buffer); + struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer); cpu_buf->sample_lost_overflow++; } @@ -95,7 +94,7 @@ int alloc_cpu_buffers(void) goto fail; for_each_possible_cpu(i) { - struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i); + struct oprofile_cpu_buffer *b = &per_cpu(op_cpu_buffer, i); b->last_task = NULL; b->last_is_kernel = -1; @@ -122,7 +121,7 @@ void start_cpu_work(void) work_enabled = 1; for_each_online_cpu(i) { - struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i); + struct oprofile_cpu_buffer *b = &per_cpu(op_cpu_buffer, i); /* * Spread the work by 1 jiffy per cpu so they dont all @@ -139,7 +138,7 @@ void end_cpu_work(void) work_enabled = 0; for_each_online_cpu(i) { - struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i); + struct oprofile_cpu_buffer *b = &per_cpu(op_cpu_buffer, i); cancel_delayed_work(&b->work); } @@ -330,7 +329,7 @@ static inline void __oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, unsigned long event, int is_kernel) { - struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); + struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer); unsigned long backtrace = oprofile_backtrace_depth; /* @@ -375,7 +374,7 @@ oprofile_write_reserve(struct op_entry *entry, struct pt_regs * const regs, { struct op_sample *sample; int is_kernel = !user_mode(regs); - struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); + struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer); cpu_buf->sample_received++; @@ -430,13 +429,13 @@ int oprofile_write_commit(struct op_entry *entry) void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event) { - struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); + struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer); log_sample(cpu_buf, pc, 0, is_kernel, event); } void oprofile_add_trace(unsigned long pc) { - struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); + struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer); if (!cpu_buf->tracing) return; diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index 272995d20293ab10aa4d77fb44d7f4bd79d76afb..68ea16ab645f3e3e134b56db9269df2044234b92 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -50,7 +50,7 @@ struct oprofile_cpu_buffer { struct delayed_work work; }; -DECLARE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer); +DECLARE_PER_CPU(struct oprofile_cpu_buffer, op_cpu_buffer); /* * Resets the cpu buffer to a sane state. @@ -60,7 +60,7 @@ DECLARE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer); */ static inline void op_cpu_buffer_reset(int cpu) { - struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu); + struct oprofile_cpu_buffer *cpu_buf = &per_cpu(op_cpu_buffer, cpu); cpu_buf->last_is_kernel = -1; cpu_buf->last_task = NULL; diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c index 61689e814d465fc90bb0652d0c5cec9380e185f5..917d28ebeacd24ab2a6f0f3772be1846b4011bb5 100644 --- a/drivers/oprofile/oprofile_stats.c +++ b/drivers/oprofile/oprofile_stats.c @@ -23,7 +23,7 @@ void oprofile_reset_stats(void) int i; for_each_possible_cpu(i) { - cpu_buf = &per_cpu(cpu_buffer, i); + cpu_buf = &per_cpu(op_cpu_buffer, i); cpu_buf->sample_received = 0; cpu_buf->sample_lost_overflow = 0; cpu_buf->backtrace_aborted = 0; @@ -51,7 +51,7 @@ void oprofile_create_stats_files(struct super_block *sb, struct dentry *root) return; for_each_possible_cpu(i) { - cpu_buf = &per_cpu(cpu_buffer, i); + cpu_buf = &per_cpu(op_cpu_buffer, i); snprintf(buf, 10, "cpu%d", i); cpudir = oprofilefs_mkdir(sb, dir, buf); diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index fdc864f9cf233d5134803593640f49c3ed0b1ccf..b1ecefa2a23dac481b77c06e1090a4ef40daa171 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -27,10 +27,10 @@ config PCI_LEGACY default y help Say Y here if you want to include support for the deprecated - pci_find_slot() and pci_find_device() APIs. Most drivers have - been converted over to using the proper hotplug APIs, so this - option serves to include/exclude only a few drivers that are - still using this API. + pci_find_device() API. Most drivers have been converted over + to using the proper hotplug APIs, so this option serves to + include/exclude only a few drivers that are still using this + API. config PCI_DEBUG bool "PCI Debugging" @@ -69,3 +69,10 @@ config PCI_IOV physical resources. If unsure, say N. + +config PCI_IOAPIC + bool + depends on PCI + depends on ACPI + depends on HOTPLUG + default y diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 4a7f11d8f43215af8c10f87f8d08642eac28a339..4df48d58eaa6372109bbcd2ca4c7cd04aaa25a6e 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -14,6 +14,8 @@ CFLAGS_legacy.o += -Wno-deprecated-declarations # Build PCI Express stuff if needed obj-$(CONFIG_PCIEPORTBUS) += pcie/ +obj-$(CONFIG_PCI_IOAPIC) += ioapic.o + obj-$(CONFIG_HOTPLUG) += hotplug.o # Build the PCI Hotplug drivers if we were asked to diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 416f6ac65b761080a2e81a8ace5c5d442a8ea2d1..6cdc931f7c1773e6fb59b2c8bbac85df950a9f86 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -320,7 +320,7 @@ found: for (bus = dev->bus; bus; bus = bus->parent) { struct pci_dev *bridge = bus->self; - if (!bridge || !bridge->is_pcie || + if (!bridge || !pci_is_pcie(bridge) || bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) return 0; @@ -645,8 +645,11 @@ void __init detect_intel_iommu(void) "x2apic and Intr-remapping.\n"); #endif #ifdef CONFIG_DMAR - if (ret && !no_iommu && !iommu_detected && !dmar_disabled) + if (ret && !no_iommu && !iommu_detected && !dmar_disabled) { iommu_detected = 1; + /* Make sure ACS will be enabled */ + pci_request_acs(); + } #endif #ifdef CONFIG_X86 if (ret) diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index 3625b094bf7eeb2a80bde2a3e59fcbf631b5758a..6cd9f3c9887d2ac9841b542d92475a91f1d845b6 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile @@ -6,18 +6,22 @@ obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o -# pciehp should be linked before acpiphp in order to allow the native driver -# to attempt to bind first. We can then fall back to generic support. +# native drivers should be linked before acpiphp in order to allow the +# native driver to attempt to bind first. We can then fall back to +# generic support. obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o -obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o -obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o +obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o + +# acpiphp_ibm extends acpiphp, so should be linked afterwards. + +obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o # Link this last so it doesn't claim devices that have a real hotplug driver obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 0f32571b94df406d09c9cbf024d2c11dd41bc89e..3c76fc67cf0e62f8598877881ce40efb0c7a12ae 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -362,6 +362,8 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) status = acpi_pci_osc_control_set(handle, flags); if (ACPI_SUCCESS(status)) goto got_one; + if (status == AE_SUPPORT) + goto no_control; kfree(string.pointer); string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL }; } @@ -394,10 +396,9 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) if (ACPI_FAILURE(status)) break; } - +no_control: dbg("Cannot get control of hotplug hardware for pci %s\n", pci_name(pdev)); - kfree(string.pointer); return -ENODEV; got_one: diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 7d938df792065f86b26eca672dde731dfcf344d2..bab52047baa84101d2448a06b617381b21918444 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -146,12 +146,6 @@ struct acpiphp_attention_info struct module *owner; }; -struct acpiphp_ioapic { - struct pci_dev *dev; - u32 gsi_base; - struct list_head list; -}; - /* PCI bus bridge HID */ #define ACPI_PCI_HOST_HID "PNP0A03" diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index df1b0ea089d12218c1b7d55342211688aef32c70..8e952fdab7642a83aaedfefeba108826127e8807 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -52,8 +52,6 @@ #include "acpiphp.h" static LIST_HEAD(bridge_list); -static LIST_HEAD(ioapic_list); -static DEFINE_SPINLOCK(ioapic_list_lock); #define MY_NAME "acpiphp_glue" @@ -311,17 +309,13 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) /* 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); + list_for_each_entry(bridge, &bridge_list, list) { for (slot = bridge->slots; slot; slot = slot->next) { - list_for_each(l, &slot->funcs) { - func = list_entry(l, struct acpiphp_func, - sibling); + list_for_each_entry(func, &slot->funcs, sibling) { if (func->handle == handle) return func; } @@ -495,21 +489,19 @@ static int add_bridge(acpi_handle handle) static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) { - struct list_head *head; - list_for_each(head, &bridge_list) { - struct acpiphp_bridge *bridge = list_entry(head, - struct acpiphp_bridge, list); + struct acpiphp_bridge *bridge; + + list_for_each_entry(bridge, &bridge_list, list) if (bridge->handle == handle) return bridge; - } return NULL; } static void cleanup_bridge(struct acpiphp_bridge *bridge) { - struct list_head *list, *tmp; - struct acpiphp_slot *slot; + struct acpiphp_slot *slot, *next; + struct acpiphp_func *func, *tmp; acpi_status status; acpi_handle handle = bridge->handle; @@ -530,10 +522,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) slot = bridge->slots; while (slot) { - struct acpiphp_slot *next = slot->next; - list_for_each_safe (list, tmp, &slot->funcs) { - struct acpiphp_func *func; - func = list_entry(list, struct acpiphp_func, sibling); + next = slot->next; + list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) { if (is_dock_device(func->handle)) { unregister_hotplug_dock_device(func->handle); unregister_dock_notifier(&func->nb); @@ -545,7 +535,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) if (ACPI_FAILURE(status)) err("failed to remove notify handler\n"); } - list_del(list); + list_del(&func->sibling); kfree(func); } acpiphp_unregister_hotplug_slot(slot); @@ -606,204 +596,17 @@ static void remove_bridge(acpi_handle handle) handle_hotplug_event_bridge); } -static struct pci_dev * get_apic_pci_info(acpi_handle handle) -{ - struct pci_dev *dev; - - dev = acpi_get_pci_dev(handle); - if (!dev) - return NULL; - - if ((dev->class != PCI_CLASS_SYSTEM_PIC_IOAPIC) && - (dev->class != PCI_CLASS_SYSTEM_PIC_IOXAPIC)) - { - pci_dev_put(dev); - return NULL; - } - - return dev; -} - -static int get_gsi_base(acpi_handle handle, u32 *gsi_base) -{ - acpi_status status; - int result = -1; - unsigned long long gsb; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - union acpi_object *obj; - void *table; - - status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb); - if (ACPI_SUCCESS(status)) { - *gsi_base = (u32)gsb; - return 0; - } - - status = acpi_evaluate_object(handle, "_MAT", NULL, &buffer); - if (ACPI_FAILURE(status) || !buffer.length || !buffer.pointer) - return -1; - - obj = buffer.pointer; - if (obj->type != ACPI_TYPE_BUFFER) - goto out; - - table = obj->buffer.pointer; - switch (((struct acpi_subtable_header *)table)->type) { - case ACPI_MADT_TYPE_IO_SAPIC: - *gsi_base = ((struct acpi_madt_io_sapic *)table)->global_irq_base; - result = 0; - break; - case ACPI_MADT_TYPE_IO_APIC: - *gsi_base = ((struct acpi_madt_io_apic *)table)->global_irq_base; - result = 0; - break; - default: - break; - } - out: - kfree(buffer.pointer); - return result; -} - -static acpi_status -ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - acpi_status status; - unsigned long long sta; - acpi_handle tmp; - struct pci_dev *pdev; - u32 gsi_base; - u64 phys_addr; - struct acpiphp_ioapic *ioapic; - - /* Evaluate _STA if present */ - status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); - if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL) - return AE_CTRL_DEPTH; - - /* Scan only PCI bus scope */ - status = acpi_get_handle(handle, "_HID", &tmp); - if (ACPI_SUCCESS(status)) - return AE_CTRL_DEPTH; - - if (get_gsi_base(handle, &gsi_base)) - return AE_OK; - - ioapic = kmalloc(sizeof(*ioapic), GFP_KERNEL); - if (!ioapic) - return AE_NO_MEMORY; - - pdev = get_apic_pci_info(handle); - if (!pdev) - goto exit_kfree; - - if (pci_enable_device(pdev)) - goto exit_pci_dev_put; - - pci_set_master(pdev); - - if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)")) - goto exit_pci_disable_device; - - phys_addr = pci_resource_start(pdev, 0); - if (acpi_register_ioapic(handle, phys_addr, gsi_base)) - goto exit_pci_release_region; - - ioapic->gsi_base = gsi_base; - ioapic->dev = pdev; - spin_lock(&ioapic_list_lock); - list_add_tail(&ioapic->list, &ioapic_list); - spin_unlock(&ioapic_list_lock); - - return AE_OK; - - exit_pci_release_region: - pci_release_region(pdev, 0); - exit_pci_disable_device: - pci_disable_device(pdev); - exit_pci_dev_put: - pci_dev_put(pdev); - exit_kfree: - kfree(ioapic); - - return AE_OK; -} - -static acpi_status -ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - acpi_status status; - unsigned long long sta; - acpi_handle tmp; - u32 gsi_base; - struct acpiphp_ioapic *pos, *n, *ioapic = NULL; - - /* Evaluate _STA if present */ - status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); - if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL) - return AE_CTRL_DEPTH; - - /* Scan only PCI bus scope */ - status = acpi_get_handle(handle, "_HID", &tmp); - if (ACPI_SUCCESS(status)) - return AE_CTRL_DEPTH; - - if (get_gsi_base(handle, &gsi_base)) - return AE_OK; - - acpi_unregister_ioapic(handle, gsi_base); - - spin_lock(&ioapic_list_lock); - list_for_each_entry_safe(pos, n, &ioapic_list, list) { - if (pos->gsi_base != gsi_base) - continue; - ioapic = pos; - list_del(&ioapic->list); - break; - } - spin_unlock(&ioapic_list_lock); - - if (!ioapic) - return AE_OK; - - pci_release_region(ioapic->dev, 0); - pci_disable_device(ioapic->dev); - pci_dev_put(ioapic->dev); - kfree(ioapic); - - return AE_OK; -} - -static int acpiphp_configure_ioapics(acpi_handle handle) -{ - ioapic_add(handle, 0, NULL, NULL); - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, - ACPI_UINT32_MAX, ioapic_add, NULL, NULL, NULL); - return 0; -} - -static int acpiphp_unconfigure_ioapics(acpi_handle handle) -{ - ioapic_remove(handle, 0, NULL, NULL); - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, - ACPI_UINT32_MAX, ioapic_remove, NULL, NULL, NULL); - return 0; -} - static int power_on_slot(struct acpiphp_slot *slot) { acpi_status status; struct acpiphp_func *func; - struct list_head *l; int retval = 0; /* if already enabled, just skip */ if (slot->flags & SLOT_POWEREDON) goto err_exit; - list_for_each (l, &slot->funcs) { - func = list_entry(l, struct acpiphp_func, sibling); - + list_for_each_entry(func, &slot->funcs, sibling) { if (func->flags & FUNC_HAS_PS0) { dbg("%s: executing _PS0\n", __func__); status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL); @@ -829,7 +632,6 @@ static int power_off_slot(struct acpiphp_slot *slot) { acpi_status status; struct acpiphp_func *func; - struct list_head *l; int retval = 0; @@ -837,9 +639,7 @@ static int power_off_slot(struct acpiphp_slot *slot) if ((slot->flags & SLOT_POWEREDON) == 0) goto err_exit; - list_for_each (l, &slot->funcs) { - func = list_entry(l, struct acpiphp_func, sibling); - + list_for_each_entry(func, &slot->funcs, sibling) { if (func->flags & FUNC_HAS_PS3) { status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL); if (ACPI_FAILURE(status)) { @@ -966,7 +766,6 @@ static int __ref enable_device(struct acpiphp_slot *slot) { struct pci_dev *dev; struct pci_bus *bus = slot->bridge->pci_bus; - struct list_head *l; struct acpiphp_func *func; int retval = 0; int num, max, pass; @@ -1006,21 +805,16 @@ static int __ref enable_device(struct acpiphp_slot *slot) } } - list_for_each (l, &slot->funcs) { - func = list_entry(l, struct acpiphp_func, sibling); + list_for_each_entry(func, &slot->funcs, sibling) acpiphp_bus_add(func); - } pci_bus_assign_resources(bus); acpiphp_sanitize_bus(bus); acpiphp_set_hpp_values(bus); - list_for_each_entry(func, &slot->funcs, sibling) - acpiphp_configure_ioapics(func->handle); pci_enable_bridges(bus); pci_bus_add_devices(bus); - list_for_each (l, &slot->funcs) { - func = list_entry(l, struct acpiphp_func, sibling); + list_for_each_entry(func, &slot->funcs, sibling) { dev = pci_get_slot(bus, PCI_DEVFN(slot->device, func->function)); if (!dev) @@ -1091,7 +885,6 @@ static int disable_device(struct acpiphp_slot *slot) } list_for_each_entry(func, &slot->funcs, sibling) { - acpiphp_unconfigure_ioapics(func->handle); acpiphp_bus_trim(func->handle); } @@ -1119,12 +912,9 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) acpi_status status; unsigned long long sta = 0; u32 dvid; - struct list_head *l; struct acpiphp_func *func; - list_for_each (l, &slot->funcs) { - func = list_entry(l, struct acpiphp_func, sibling); - + list_for_each_entry(func, &slot->funcs, sibling) { if (func->flags & FUNC_HAS_STA) { status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta); if (ACPI_SUCCESS(status) && sta) @@ -1152,13 +942,10 @@ int acpiphp_eject_slot(struct acpiphp_slot *slot) { acpi_status status; struct acpiphp_func *func; - struct list_head *l; struct acpi_object_list arg_list; union acpi_object arg; - list_for_each (l, &slot->funcs) { - func = list_entry(l, struct acpiphp_func, sibling); - + list_for_each_entry(func, &slot->funcs, sibling) { /* We don't want to call _EJ0 on non-existing functions. */ if ((func->flags & FUNC_HAS_EJ0)) { /* _EJ0 method take one argument */ @@ -1275,7 +1062,6 @@ static int acpiphp_configure_bridge (acpi_handle handle) acpiphp_sanitize_bus(bus); acpiphp_set_hpp_values(bus); pci_enable_bridges(bus); - acpiphp_configure_ioapics(handle); return 0; } @@ -1542,7 +1328,7 @@ int __init acpiphp_get_num_slots(void) struct acpiphp_bridge *bridge; int num_slots = 0; - list_for_each_entry (bridge, &bridge_list, list) { + list_for_each_entry(bridge, &bridge_list, list) { dbg("Bus %04x:%02x has %d slot%s\n", pci_domain_nr(bridge->pci_bus), bridge->pci_bus->number, bridge->nr_slots, diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c index 83f337c891a9ca2ad78c82c3352c11da181c4cea..c7084f0eca5aaf29678933e7a16cb286ff6b0a3a 100644 --- a/drivers/pci/hotplug/ibmphp_hpc.c +++ b/drivers/pci/hotplug/ibmphp_hpc.c @@ -890,7 +890,7 @@ static int poll_hpc(void *data) msleep(POLL_INTERVAL_SEC * 1000); if (kthread_should_stop()) - break; + goto out_sleep; down (&semOperations); @@ -904,6 +904,7 @@ static int poll_hpc(void *data) /* give up the hardware semaphore */ up (&semOperations); /* sleep for a short time just for good measure */ +out_sleep: msleep(100); } up (&sem_exit); diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 0325d989bb46f138d7ff1923e8e28bb03efa4d55..38183a534b653c6965ffa875c5b699b02f1d58ab 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -68,26 +68,26 @@ static DEFINE_MUTEX(pci_hp_mutex); static char *pci_bus_speed_strings[] = { "33 MHz PCI", /* 0x00 */ "66 MHz PCI", /* 0x01 */ - "66 MHz PCIX", /* 0x02 */ - "100 MHz PCIX", /* 0x03 */ - "133 MHz PCIX", /* 0x04 */ + "66 MHz PCI-X", /* 0x02 */ + "100 MHz PCI-X", /* 0x03 */ + "133 MHz PCI-X", /* 0x04 */ NULL, /* 0x05 */ NULL, /* 0x06 */ NULL, /* 0x07 */ NULL, /* 0x08 */ - "66 MHz PCIX 266", /* 0x09 */ - "100 MHz PCIX 266", /* 0x0a */ - "133 MHz PCIX 266", /* 0x0b */ + "66 MHz PCI-X 266", /* 0x09 */ + "100 MHz PCI-X 266", /* 0x0a */ + "133 MHz PCI-X 266", /* 0x0b */ NULL, /* 0x0c */ NULL, /* 0x0d */ NULL, /* 0x0e */ NULL, /* 0x0f */ NULL, /* 0x10 */ - "66 MHz PCIX 533", /* 0x11 */ - "100 MHz PCIX 533", /* 0x12 */ - "133 MHz PCIX 533", /* 0x13 */ - "2.5 GT/s PCI-E", /* 0x14 */ - "5.0 GT/s PCI-E", /* 0x15 */ + "66 MHz PCI-X 533", /* 0x11 */ + "100 MHz PCI-X 533", /* 0x12 */ + "133 MHz PCI-X 533", /* 0x13 */ + "2.5 GT/s PCIe", /* 0x14 */ + "5.0 GT/s PCIe", /* 0x15 */ }; #ifdef CONFIG_HOTPLUG_PCI_CPCI diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 3070f77eb56ad3c4e53bf4369fcad7e40993ed3b..4ed76b47b6dcbd6358e083b11d5f8e823daa9cdb 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -91,7 +91,6 @@ struct controller { struct slot *slot; wait_queue_head_t queue; /* sleep & wake process */ u32 slot_cap; - u8 cap_base; struct timer_list poll_timer; unsigned int cmd_busy:1; unsigned int no_cmd_complete:1; diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c index 37c8d3d0323e60602d6a6b4296e5e6668139c696..b09b083011d69ad43e743490bad963266f6af36b 100644 --- a/drivers/pci/hotplug/pciehp_acpi.c +++ b/drivers/pci/hotplug/pciehp_acpi.c @@ -87,7 +87,8 @@ static int __init dummy_probe(struct pcie_device *dev) /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */ if (pciehp_get_hp_hw_control_from_firmware(pdev)) return -ENODEV; - if (!(pos = pci_find_capability(pdev, PCI_CAP_ID_EXP))) + pos = pci_pcie_cap(pdev); + if (!pos) return -ENODEV; pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap); slot = kzalloc(sizeof(*slot), GFP_KERNEL); diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index bc234719b1df7208f8f12003fe3f99b8997cb0ee..5674b2075bdc305699388f4e1528f6f951d4fe7b 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -72,18 +72,6 @@ static int get_adapter_status (struct hotplug_slot *slot, u8 *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); -static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { - .set_attention_status = set_attention_status, - .enable_slot = enable_slot, - .disable_slot = disable_slot, - .get_power_status = get_power_status, - .get_attention_status = get_attention_status, - .get_latch_status = get_latch_status, - .get_adapter_status = get_adapter_status, - .get_max_bus_speed = get_max_bus_speed, - .get_cur_bus_speed = get_cur_bus_speed, -}; - /** * release_slot - free up the memory used by a slot * @hotplug_slot: slot to free @@ -95,6 +83,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot) ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", __func__, hotplug_slot_name(hotplug_slot)); + kfree(hotplug_slot->ops); kfree(hotplug_slot->info); kfree(hotplug_slot); } @@ -104,6 +93,7 @@ static int init_slot(struct controller *ctrl) struct slot *slot = ctrl->slot; struct hotplug_slot *hotplug = NULL; struct hotplug_slot_info *info = NULL; + struct hotplug_slot_ops *ops = NULL; char name[SLOT_NAME_SIZE]; int retval = -ENOMEM; @@ -115,11 +105,28 @@ static int init_slot(struct controller *ctrl) if (!info) goto out; + /* Setup hotplug slot ops */ + ops = kzalloc(sizeof(*ops), GFP_KERNEL); + if (!ops) + goto out; + ops->enable_slot = enable_slot; + ops->disable_slot = disable_slot; + ops->get_power_status = get_power_status; + ops->get_adapter_status = get_adapter_status; + ops->get_max_bus_speed = get_max_bus_speed; + ops->get_cur_bus_speed = get_cur_bus_speed; + if (MRL_SENS(ctrl)) + ops->get_latch_status = get_latch_status; + if (ATTN_LED(ctrl)) { + ops->get_attention_status = get_attention_status; + ops->set_attention_status = set_attention_status; + } + /* register this slot with the hotplug pci core */ hotplug->info = info; hotplug->private = slot; hotplug->release = &release_slot; - hotplug->ops = &pciehp_hotplug_slot_ops; + hotplug->ops = ops; slot->hotplug_slot = hotplug; snprintf(name, SLOT_NAME_SIZE, "%u", PSN(ctrl)); @@ -128,17 +135,12 @@ static int init_slot(struct controller *ctrl) ctrl->pcie->port->subordinate->number, PSN(ctrl)); retval = pci_hp_register(hotplug, ctrl->pcie->port->subordinate, 0, name); - if (retval) { + if (retval) ctrl_err(ctrl, "pci_hp_register failed with error %d\n", retval); - goto out; - } - get_power_status(hotplug, &info->power_status); - get_attention_status(hotplug, &info->attention_status); - get_latch_status(hotplug, &info->latch_status); - get_adapter_status(hotplug, &info->adapter_status); out: if (retval) { + kfree(ops); kfree(info); kfree(hotplug); } @@ -160,12 +162,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", __func__, slot_name(slot)); - hotplug_slot->info->attention_status = status; - - if (ATTN_LED(slot->ctrl)) - pciehp_set_attention_status(slot, status); - - return 0; + return pciehp_set_attention_status(slot, status); } @@ -193,92 +190,62 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) { struct slot *slot = hotplug_slot->private; - int retval; ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", __func__, slot_name(slot)); - retval = pciehp_get_power_status(slot, value); - if (retval < 0) - *value = hotplug_slot->info->power_status; - - return 0; + return pciehp_get_power_status(slot, value); } static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) { struct slot *slot = hotplug_slot->private; - int retval; ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", __func__, slot_name(slot)); - retval = pciehp_get_attention_status(slot, value); - if (retval < 0) - *value = hotplug_slot->info->attention_status; - - return 0; + return pciehp_get_attention_status(slot, value); } static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) { struct slot *slot = hotplug_slot->private; - int retval; ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", __func__, slot_name(slot)); - retval = pciehp_get_latch_status(slot, value); - if (retval < 0) - *value = hotplug_slot->info->latch_status; - - return 0; + return pciehp_get_latch_status(slot, value); } static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) { struct slot *slot = hotplug_slot->private; - int retval; ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", __func__, slot_name(slot)); - retval = pciehp_get_adapter_status(slot, value); - if (retval < 0) - *value = hotplug_slot->info->adapter_status; - - return 0; + return pciehp_get_adapter_status(slot, value); } static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { struct slot *slot = hotplug_slot->private; - int retval; ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", __func__, slot_name(slot)); - retval = pciehp_get_max_link_speed(slot, value); - if (retval < 0) - *value = PCI_SPEED_UNKNOWN; - - return 0; + return pciehp_get_max_link_speed(slot, value); } static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { struct slot *slot = hotplug_slot->private; - int retval; ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", __func__, slot_name(slot)); - retval = pciehp_get_cur_link_speed(slot, value); - if (retval < 0) - *value = PCI_SPEED_UNKNOWN; - - return 0; + return pciehp_get_cur_link_speed(slot, value); } static int pciehp_probe(struct pcie_device *dev) @@ -286,14 +253,13 @@ static int pciehp_probe(struct pcie_device *dev) int rc; struct controller *ctrl; struct slot *slot; - u8 value; - struct pci_dev *pdev = dev->port; + u8 occupied, poweron; if (pciehp_force) dev_info(&dev->device, "Bypassing BIOS check for pciehp use on %s\n", - pci_name(pdev)); - else if (pciehp_get_hp_hw_control_from_firmware(pdev)) + pci_name(dev->port)); + else if (pciehp_get_hp_hw_control_from_firmware(dev->port)) goto err_out_none; ctrl = pcie_init(dev); @@ -318,23 +284,18 @@ static int pciehp_probe(struct pcie_device *dev) rc = pcie_init_notification(ctrl); if (rc) { ctrl_err(ctrl, "Notification initialization failed\n"); - goto err_out_release_ctlr; + goto err_out_free_ctrl_slot; } /* Check if slot is occupied */ slot = ctrl->slot; - pciehp_get_adapter_status(slot, &value); - if (value) { - if (pciehp_force) - pciehp_enable_slot(slot); - } else { - /* Power off slot if not occupied */ - if (POWER_CTRL(ctrl)) { - rc = pciehp_power_off_slot(slot); - if (rc) - goto err_out_free_ctrl_slot; - } - } + pciehp_get_adapter_status(slot, &occupied); + pciehp_get_power_status(slot, &poweron); + if (occupied && pciehp_force) + pciehp_enable_slot(slot); + /* If empty slot's power status is on, turn power off */ + if (!occupied && poweron && POWER_CTRL(ctrl)) + pciehp_power_off_slot(slot); return 0; diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 84487d126e4d7098c4010425b3dcfebe6a6122cf..d6ac1b261dd9d8b9a94185c93006b9739ea04305 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -142,23 +142,9 @@ u8 pciehp_handle_power_fault(struct slot *p_slot) /* power fault */ ctrl_dbg(ctrl, "Power fault interrupt received\n"); - - if (!pciehp_query_power_fault(p_slot)) { - /* - * power fault Cleared - */ - ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n", - slot_name(p_slot)); - event_type = INT_POWER_FAULT_CLEAR; - } else { - /* - * power fault - */ - ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot)); - event_type = INT_POWER_FAULT; - ctrl_info(ctrl, "Power fault bit %x set\n", 0); - } - + ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot)); + event_type = INT_POWER_FAULT; + ctrl_info(ctrl, "Power fault bit %x set\n", 0); queue_interrupt_event(p_slot, event_type); return 1; @@ -224,13 +210,12 @@ static int board_added(struct slot *p_slot) retval = pciehp_check_link_status(ctrl); if (retval) { ctrl_err(ctrl, "Failed to check link status\n"); - set_slot_off(ctrl, p_slot); - return retval; + goto err_exit; } /* Check for a power fault */ - if (pciehp_query_power_fault(p_slot)) { - ctrl_dbg(ctrl, "Power fault detected\n"); + if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) { + ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot)); retval = -EIO; goto err_exit; } @@ -363,25 +348,6 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) mutex_unlock(&p_slot->lock); } -static int update_slot_info(struct slot *slot) -{ - struct hotplug_slot_info *info; - int result; - - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - pciehp_get_power_status(slot, &info->power_status); - pciehp_get_attention_status(slot, &info->attention_status); - pciehp_get_latch_status(slot, &info->latch_status); - pciehp_get_adapter_status(slot, &info->adapter_status); - - result = pci_hp_change_slot_info(slot->hotplug_slot, info); - kfree (info); - return result; -} - /* * Note: This function must be called with slot->lock held */ @@ -442,7 +408,6 @@ static void handle_button_press_event(struct slot *p_slot) * to hot-add or hot-remove is undergoing */ ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot)); - update_slot_info(p_slot); break; default: ctrl_warn(ctrl, "Not a valid state\n"); @@ -500,11 +465,9 @@ static void interrupt_event_handler(struct work_struct *work) if (!HP_SUPR_RM(ctrl)) break; ctrl_dbg(ctrl, "Surprise Removal\n"); - update_slot_info(p_slot); handle_surprise_event(p_slot); break; default: - update_slot_info(p_slot); break; } mutex_unlock(&p_slot->lock); @@ -547,9 +510,6 @@ int pciehp_enable_slot(struct slot *p_slot) if (rc) { pciehp_get_latch_status(p_slot, &getstatus); } - - update_slot_info(p_slot); - return rc; } @@ -590,10 +550,7 @@ int pciehp_disable_slot(struct slot *p_slot) } } - ret = remove_board(p_slot); - update_slot_info(p_slot); - - return ret; + return remove_board(p_slot); } int pciehp_sysfs_enable_slot(struct slot *p_slot) diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 9ef4605c1ef6471fa6beddd55ccdb4465a2d7952..10040d58c8efaa6ec17b71bb52f419f40d2ccb90 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -45,25 +45,25 @@ static atomic_t pciehp_num_controllers = ATOMIC_INIT(0); static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) { struct pci_dev *dev = ctrl->pcie->port; - return pci_read_config_word(dev, ctrl->cap_base + reg, value); + return pci_read_config_word(dev, pci_pcie_cap(dev) + reg, value); } static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value) { struct pci_dev *dev = ctrl->pcie->port; - return pci_read_config_dword(dev, ctrl->cap_base + reg, value); + return pci_read_config_dword(dev, pci_pcie_cap(dev) + reg, value); } static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value) { struct pci_dev *dev = ctrl->pcie->port; - return pci_write_config_word(dev, ctrl->cap_base + reg, value); + return pci_write_config_word(dev, pci_pcie_cap(dev) + reg, value); } static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) { struct pci_dev *dev = ctrl->pcie->port; - return pci_write_config_dword(dev, ctrl->cap_base + reg, value); + return pci_write_config_dword(dev, pci_pcie_cap(dev) + reg, value); } /* Power Control Command */ @@ -318,8 +318,8 @@ int pciehp_get_attention_status(struct slot *slot, u8 *status) return retval; } - ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", - __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_ctrl); + ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__, + pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); atten_led_state = (slot_ctrl & PCI_EXP_SLTCTL_AIC) >> 6; @@ -356,8 +356,8 @@ int pciehp_get_power_status(struct slot *slot, u8 *status) ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); return retval; } - ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", - __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_ctrl); + ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", __func__, + pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); pwr_state = (slot_ctrl & PCI_EXP_SLTCTL_PCC) >> 10; @@ -427,27 +427,24 @@ int pciehp_set_attention_status(struct slot *slot, u8 value) struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; - int rc; cmd_mask = PCI_EXP_SLTCTL_AIC; switch (value) { - case 0 : /* turn off */ - slot_cmd = 0x00C0; - break; - case 1: /* turn on */ - slot_cmd = 0x0040; - break; - case 2: /* turn blink */ - slot_cmd = 0x0080; - break; - default: - return -1; + case 0 : /* turn off */ + slot_cmd = 0x00C0; + break; + case 1: /* turn on */ + slot_cmd = 0x0040; + break; + case 2: /* turn blink */ + slot_cmd = 0x0080; + break; + default: + return -EINVAL; } - rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); - ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", - __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); - - return rc; + ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, + pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); + return pcie_write_cmd(ctrl, slot_cmd, cmd_mask); } void pciehp_green_led_on(struct slot *slot) @@ -459,8 +456,8 @@ void pciehp_green_led_on(struct slot *slot) slot_cmd = 0x0100; cmd_mask = PCI_EXP_SLTCTL_PIC; pcie_write_cmd(ctrl, slot_cmd, cmd_mask); - ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", - __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); + ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, + pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); } void pciehp_green_led_off(struct slot *slot) @@ -472,8 +469,8 @@ void pciehp_green_led_off(struct slot *slot) slot_cmd = 0x0300; cmd_mask = PCI_EXP_SLTCTL_PIC; pcie_write_cmd(ctrl, slot_cmd, cmd_mask); - ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", - __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); + ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, + pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); } void pciehp_green_led_blink(struct slot *slot) @@ -485,8 +482,8 @@ void pciehp_green_led_blink(struct slot *slot) slot_cmd = 0x0200; cmd_mask = PCI_EXP_SLTCTL_PIC; pcie_write_cmd(ctrl, slot_cmd, cmd_mask); - ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", - __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); + ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, + pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); } int pciehp_power_on_slot(struct slot * slot) @@ -514,97 +511,38 @@ int pciehp_power_on_slot(struct slot * slot) return retval; } } + ctrl->power_fault_detected = 0; slot_cmd = POWER_ON; cmd_mask = PCI_EXP_SLTCTL_PCC; - if (!pciehp_poll_mode) { - /* Enable power fault detection turned off at power off time */ - slot_cmd |= PCI_EXP_SLTCTL_PFDE; - cmd_mask |= PCI_EXP_SLTCTL_PFDE; - } - retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); if (retval) { ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); return retval; } - ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", - __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); + ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, + pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); - ctrl->power_fault_detected = 0; return retval; } -static inline int pcie_mask_bad_dllp(struct controller *ctrl) -{ - struct pci_dev *dev = ctrl->pcie->port; - int pos; - u32 reg; - - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); - if (!pos) - return 0; - pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, ®); - if (reg & PCI_ERR_COR_BAD_DLLP) - return 0; - reg |= PCI_ERR_COR_BAD_DLLP; - pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg); - return 1; -} - -static inline void pcie_unmask_bad_dllp(struct controller *ctrl) -{ - struct pci_dev *dev = ctrl->pcie->port; - u32 reg; - int pos; - - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); - if (!pos) - return; - pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, ®); - if (!(reg & PCI_ERR_COR_BAD_DLLP)) - return; - reg &= ~PCI_ERR_COR_BAD_DLLP; - pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg); -} - int pciehp_power_off_slot(struct slot * slot) { struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; - int retval = 0; - int changed; - - /* - * Set Bad DLLP Mask bit in Correctable Error Mask - * Register. This is the workaround against Bad DLLP error - * that sometimes happens during turning power off the slot - * which conforms to PCI Express 1.0a spec. - */ - changed = pcie_mask_bad_dllp(ctrl); + int retval; slot_cmd = POWER_OFF; cmd_mask = PCI_EXP_SLTCTL_PCC; - if (!pciehp_poll_mode) { - /* Disable power fault detection */ - slot_cmd &= ~PCI_EXP_SLTCTL_PFDE; - cmd_mask |= PCI_EXP_SLTCTL_PFDE; - } - retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); if (retval) { ctrl_err(ctrl, "Write command failed!\n"); - retval = -1; - goto out; + return retval; } - ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", - __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); - out: - if (changed) - pcie_unmask_bad_dllp(ctrl); - - return retval; + ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, + pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); + return 0; } static irqreturn_t pcie_isr(int irq, void *dev_id) @@ -840,11 +778,19 @@ int pcie_enable_notification(struct controller *ctrl) { u16 cmd, mask; + /* + * TBD: Power fault detected software notification support. + * + * Power fault detected software notification is not enabled + * now, because it caused power fault detected interrupt storm + * on some machines. On those machines, power fault detected + * bit in the slot status register was set again immediately + * when it is cleared in the interrupt service routine, and + * next power fault detected interrupt was notified again. + */ cmd = PCI_EXP_SLTCTL_PDCE; if (ATTN_BUTTN(ctrl)) cmd |= PCI_EXP_SLTCTL_ABPE; - if (POWER_CTRL(ctrl)) - cmd |= PCI_EXP_SLTCTL_PFDE; if (MRL_SENS(ctrl)) cmd |= PCI_EXP_SLTCTL_MRLSCE; if (!pciehp_poll_mode) @@ -866,7 +812,8 @@ static void pcie_disable_notification(struct controller *ctrl) u16 mask; mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | - PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE); + PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE | + PCI_EXP_SLTCTL_DLLSCE); if (pcie_write_cmd(ctrl, 0, mask)) ctrl_warn(ctrl, "Cannot disable software notification\n"); } @@ -934,7 +881,8 @@ static inline void dbg_ctrl(struct controller *ctrl) pdev->subsystem_device); ctrl_info(ctrl, " Subsystem Vendor ID : 0x%04x\n", pdev->subsystem_vendor); - ctrl_info(ctrl, " PCIe Cap offset : 0x%02x\n", ctrl->cap_base); + ctrl_info(ctrl, " PCIe Cap offset : 0x%02x\n", + pci_pcie_cap(pdev)); for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { if (!pci_resource_len(pdev, i)) continue; @@ -978,8 +926,7 @@ struct controller *pcie_init(struct pcie_device *dev) goto abort; } ctrl->pcie = dev; - ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!ctrl->cap_base) { + if (!pci_pcie_cap(pdev)) { ctrl_err(ctrl, "Cannot find PCI Express capability\n"); goto abort_ctrl; } diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c index cc8ec3aa41a7f494f7338b0c30a4c2efcefe7a81..80b461c985579da3905744c36aabfd215c9cac06 100644 --- a/drivers/pci/hotplug/pcihp_slot.c +++ b/drivers/pci/hotplug/pcihp_slot.c @@ -43,7 +43,7 @@ static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp) * Perhaps we *should* use default settings for PCIe, but * pciehp didn't, so we won't either. */ - if (dev->is_pcie) + if (pci_is_pcie(dev)) return; dev_info(&dev->dev, "using default PCI settings\n"); hpp = &pci_default_type0; @@ -102,7 +102,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) return; /* Find PCI Express capability */ - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + pos = pci_pcie_cap(dev); if (!pos) return; diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 9261327b49f308941c07af292a31bc379b7cb6b9..8d6159426311bda6a5bcab491b282e5427d6eff2 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1611,7 +1611,7 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev, return ret; parent = parent->bus->self; } - if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */ + if (pci_is_pcie(tmp)) /* this is a PCIE-to-PCI bridge */ return domain_context_mapping_one(domain, pci_domain_nr(tmp->subordinate), tmp->subordinate->number, 0, @@ -1651,7 +1651,7 @@ static int domain_context_mapped(struct pci_dev *pdev) return ret; parent = parent->bus->self; } - if (tmp->is_pcie) + if (pci_is_pcie(tmp)) return device_context_mapped(iommu, tmp->subordinate->number, 0); else @@ -1821,7 +1821,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) dev_tmp = pci_find_upstream_pcie_bridge(pdev); if (dev_tmp) { - if (dev_tmp->is_pcie) { + if (pci_is_pcie(dev_tmp)) { bus = dev_tmp->subordinate->number; devfn = 0; } else { @@ -2182,7 +2182,7 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup) * the 1:1 domain, just in _case_ one of their siblings turns out * not to be able to map all of memory. */ - if (!pdev->is_pcie) { + if (!pci_is_pcie(pdev)) { if (!pci_is_root_bus(pdev->bus)) return 0; if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI) @@ -3319,7 +3319,7 @@ static void iommu_detach_dependent_devices(struct intel_iommu *iommu, parent->devfn); parent = parent->bus->self; } - if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */ + if (pci_is_pcie(tmp)) /* this is a PCIE-to-PCI bridge */ iommu_detach_dev(iommu, tmp->subordinate->number, 0); else /* this is a legacy PCI bridge */ diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index 3b3658669bee0c0002d1e108f9b99a3afa84a9bf..1487bf2be863115a9f858b9ed0886945d012dae1 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c @@ -520,7 +520,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev) return -1; /* PCIe device or Root Complex integrated PCI device */ - if (dev->is_pcie || !dev->bus->parent) { + if (pci_is_pcie(dev) || !dev->bus->parent) { set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, (dev->bus->number << 8) | dev->devfn); return 0; @@ -528,7 +528,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev) bridge = pci_find_upstream_pcie_bridge(dev); if (bridge) { - if (bridge->is_pcie) /* this is a PCIE-to-PCI/PCIX bridge */ + if (pci_is_pcie(bridge))/* this is a PCIE-to-PCI/PCIX bridge */ set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16, (bridge->bus->number << 8) | dev->bus->number); else /* this is a legacy PCI bridge */ diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c new file mode 100644 index 0000000000000000000000000000000000000000..3e0d7b5dd1b904e0e02425f1ea005915cafb2610 --- /dev/null +++ b/drivers/pci/ioapic.c @@ -0,0 +1,127 @@ +/* + * IOAPIC/IOxAPIC/IOSAPIC driver + * + * Copyright (C) 2009 Fujitsu Limited. + * (c) Copyright 2009 Hewlett-Packard Development Company, L.P. + * + * 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 driver manages PCI I/O APICs added by hotplug after boot. We try to + * claim all I/O APIC PCI devices, but those present at boot were registered + * when we parsed the ACPI MADT, so we'll fail when we try to re-register + * them. + */ + +#include +#include +#include + +struct ioapic { + acpi_handle handle; + u32 gsi_base; +}; + +static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent) +{ + acpi_handle handle; + acpi_status status; + unsigned long long gsb; + struct ioapic *ioapic; + u64 addr; + int ret; + char *type; + + handle = DEVICE_ACPI_HANDLE(&dev->dev); + if (!handle) + return -EINVAL; + + status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb); + if (ACPI_FAILURE(status)) + return -EINVAL; + + /* + * The previous code in acpiphp evaluated _MAT if _GSB failed, but + * ACPI spec 4.0 sec 6.2.2 requires _GSB for hot-pluggable I/O APICs. + */ + + ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL); + if (!ioapic) + return -ENOMEM; + + ioapic->handle = handle; + ioapic->gsi_base = (u32) gsb; + + if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC) + type = "IOAPIC"; + else + type = "IOxAPIC"; + + ret = pci_enable_device(dev); + if (ret < 0) + goto exit_free; + + pci_set_master(dev); + + if (pci_request_region(dev, 0, type)) + goto exit_disable; + + addr = pci_resource_start(dev, 0); + if (acpi_register_ioapic(ioapic->handle, addr, ioapic->gsi_base)) + goto exit_release; + + pci_set_drvdata(dev, ioapic); + dev_info(&dev->dev, "%s at %#llx, GSI %u\n", type, addr, + ioapic->gsi_base); + return 0; + +exit_release: + pci_release_region(dev, 0); +exit_disable: + pci_disable_device(dev); +exit_free: + kfree(ioapic); + return -ENODEV; +} + +static void ioapic_remove(struct pci_dev *dev) +{ + struct ioapic *ioapic = pci_get_drvdata(dev); + + acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base); + pci_release_region(dev, 0); + pci_disable_device(dev); + kfree(ioapic); +} + + +static struct pci_device_id ioapic_devices[] = { + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_SYSTEM_PIC_IOAPIC << 8, 0xffff00, }, + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_SYSTEM_PIC_IOXAPIC << 8, 0xffff00, }, + { } +}; + +static struct pci_driver ioapic_driver = { + .name = "ioapic", + .id_table = ioapic_devices, + .probe = ioapic_probe, + .remove = __devexit_p(ioapic_remove), +}; + +static int __init ioapic_init(void) +{ + return pci_register_driver(&ioapic_driver); +} + +static void __exit ioapic_exit(void) +{ + pci_unregister_driver(&ioapic_driver); +} + +module_init(ioapic_init); +module_exit(ioapic_exit); diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index e03fe98f06193c1c6a1fa22cbf6db92a0dbd2c6a..b2a448e19fe66e0dc6c90693b6fbd8a7c85a6e4b 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -555,7 +555,7 @@ int pci_iov_init(struct pci_dev *dev) { int pos; - if (!dev->is_pcie) + if (!pci_is_pcie(dev)) return -ENODEV; pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 33317df47699d0a69f18b6970583fb23b246f7f9..cc617ddd33d03ce8c16717249ad7413fdd0a0e3e 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -116,7 +116,7 @@ static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable) int ret; ret = acpi_pm_device_sleep_wake(&bridge->dev, enable); - if (!ret || bridge->is_pcie) + if (!ret || pci_is_pcie(bridge)) return; bus = bus->parent; } @@ -131,7 +131,7 @@ static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable) if (acpi_pci_can_wakeup(dev)) return acpi_pm_device_sleep_wake(&dev->dev, enable); - if (!dev->is_pcie) + if (!pci_is_pcie(dev)) acpi_pci_propagate_wakeup_enable(dev->bus, enable); return 0; diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 0f6382f090ee575f04add353066be31abbb05336..c5df94e866787bb63bf344197edd14a08d7a1398 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -74,7 +74,11 @@ static ssize_t local_cpus_show(struct device *dev, const struct cpumask *mask; int len; +#ifdef CONFIG_NUMA + mask = cpumask_of_node(dev_to_node(dev)); +#else mask = cpumask_of_pcibus(to_pci_dev(dev)->bus); +#endif len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask); buf[len++] = '\n'; buf[len] = '\0'; @@ -88,7 +92,11 @@ static ssize_t local_cpulist_show(struct device *dev, const struct cpumask *mask; int len; +#ifdef CONFIG_NUMA + mask = cpumask_of_node(dev_to_node(dev)); +#else mask = cpumask_of_pcibus(to_pci_dev(dev)->bus); +#endif len = cpulist_scnprintf(buf, PAGE_SIZE-2, mask); buf[len++] = '\n'; buf[len] = '\0'; @@ -175,6 +183,21 @@ numa_node_show(struct device *dev, struct device_attribute *attr, char *buf) } #endif +static ssize_t +dma_mask_bits_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct pci_dev *pdev = to_pci_dev(dev); + + return sprintf (buf, "%d\n", fls64(pdev->dma_mask)); +} + +static ssize_t +consistent_dma_mask_bits_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf (buf, "%d\n", fls64(dev->coherent_dma_mask)); +} + static ssize_t msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -306,6 +329,8 @@ struct device_attribute pci_dev_attrs[] = { #ifdef CONFIG_NUMA __ATTR_RO(numa_node), #endif + __ATTR_RO(dma_mask_bits), + __ATTR_RO(consistent_dma_mask_bits), __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), diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 4e4c295a049f7bfba524f24efe8379530e3dc906..0bc27e0590196484b7733c1e0dbb049e4571cda5 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -47,6 +47,15 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE; unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE; unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE; +/* + * The default CLS is used if arch didn't set CLS explicitly and not + * all pci devices agree on the same value. Arch can override either + * the dfl or actual value as it sees fit. Don't forget this is + * measured in 32-bit words, not bytes. + */ +u8 pci_dfl_cache_line_size __devinitdata = L1_CACHE_BYTES >> 2; +u8 pci_cache_line_size; + /** * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children * @bus: pointer to PCI bus structure to search @@ -373,8 +382,12 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res) continue; /* Wrong type */ if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) return r; /* Exact match */ - if ((res->flags & IORESOURCE_PREFETCH) && !(r->flags & IORESOURCE_PREFETCH)) - best = r; /* Approximating prefetchable by non-prefetchable */ + /* We can't insert a non-prefetch resource inside a prefetchable parent .. */ + if (r->flags & IORESOURCE_PREFETCH) + continue; + /* .. but we can put a prefetchable resource inside a non-prefetchable one */ + if (!best) + best = r; } return best; } @@ -728,8 +741,8 @@ static int pci_save_pcie_state(struct pci_dev *dev) u16 *cap; u16 flags; - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); - if (pos <= 0) + pos = pci_pcie_cap(dev); + if (!pos) return 0; save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); @@ -837,7 +850,7 @@ pci_save_state(struct pci_dev *dev) int i; /* XXX: 100% dword access ok here? */ for (i = 0; i < 16; i++) - pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); + pci_read_config_dword(dev, i * 4, &dev->saved_config_space[i]); dev->state_saved = true; if ((i = pci_save_pcie_state(dev)) != 0) return i; @@ -1202,7 +1215,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable) pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); - dev_printk(KERN_INFO, &dev->dev, "PME# %s\n", + dev_printk(KERN_DEBUG, &dev->dev, "PME# %s\n", enable ? "enabled" : "disabled"); } @@ -1413,7 +1426,8 @@ void pci_pm_init(struct pci_dev *dev) pmc &= PCI_PM_CAP_PME_MASK; if (pmc) { - dev_info(&dev->dev, "PME# supported from%s%s%s%s%s\n", + dev_printk(KERN_DEBUG, &dev->dev, + "PME# supported from%s%s%s%s%s\n", (pmc & PCI_PM_CAP_PME_D0) ? " D0" : "", (pmc & PCI_PM_CAP_PME_D1) ? " D1" : "", (pmc & PCI_PM_CAP_PME_D2) ? " D2" : "", @@ -1510,7 +1524,7 @@ void pci_enable_ari(struct pci_dev *dev) u16 ctrl; struct pci_dev *bridge; - if (!dev->is_pcie || dev->devfn) + if (!pci_is_pcie(dev) || dev->devfn) return; pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); @@ -1518,10 +1532,10 @@ void pci_enable_ari(struct pci_dev *dev) return; bridge = dev->bus->self; - if (!bridge || !bridge->is_pcie) + if (!bridge || !pci_is_pcie(bridge)) return; - pos = pci_find_capability(bridge, PCI_CAP_ID_EXP); + pos = pci_pcie_cap(bridge); if (!pos) return; @@ -1536,6 +1550,54 @@ void pci_enable_ari(struct pci_dev *dev) bridge->ari_enabled = 1; } +static int pci_acs_enable; + +/** + * pci_request_acs - ask for ACS to be enabled if supported + */ +void pci_request_acs(void) +{ + pci_acs_enable = 1; +} + +/** + * pci_enable_acs - enable ACS if hardware support it + * @dev: the PCI device + */ +void pci_enable_acs(struct pci_dev *dev) +{ + int pos; + u16 cap; + u16 ctrl; + + if (!pci_acs_enable) + return; + + if (!pci_is_pcie(dev)) + return; + + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); + if (!pos) + return; + + pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap); + pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl); + + /* Source Validation */ + ctrl |= (cap & PCI_ACS_SV); + + /* P2P Request Redirect */ + ctrl |= (cap & PCI_ACS_RR); + + /* P2P Completion Redirect */ + ctrl |= (cap & PCI_ACS_CR); + + /* Upstream Forwarding */ + ctrl |= (cap & PCI_ACS_UF); + + pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl); +} + /** * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge * @dev: the PCI device @@ -1669,9 +1731,7 @@ static int __pci_request_region(struct pci_dev *pdev, int bar, const char *res_n return 0; err_out: - dev_warn(&pdev->dev, "BAR %d: can't reserve %s region %pR\n", - bar, - pci_resource_flags(pdev, bar) & IORESOURCE_IO ? "I/O" : "mem", + dev_warn(&pdev->dev, "BAR %d: can't reserve %pR\n", bar, &pdev->resource[bar]); return -EBUSY; } @@ -1866,31 +1926,6 @@ void pci_clear_master(struct pci_dev *dev) __pci_set_master(dev, false); } -#ifdef PCI_DISABLE_MWI -int pci_set_mwi(struct pci_dev *dev) -{ - return 0; -} - -int pci_try_set_mwi(struct pci_dev *dev) -{ - return 0; -} - -void pci_clear_mwi(struct pci_dev *dev) -{ -} - -#else - -#ifndef PCI_CACHE_LINE_BYTES -#define PCI_CACHE_LINE_BYTES L1_CACHE_BYTES -#endif - -/* This can be overridden by arch code. */ -/* Don't forget this is measured in 32-bit words, not bytes */ -u8 pci_cache_line_size = PCI_CACHE_LINE_BYTES / 4; - /** * pci_set_cacheline_size - ensure the CACHE_LINE_SIZE register is programmed * @dev: the PCI device for which MWI is to be enabled @@ -1901,13 +1936,12 @@ u8 pci_cache_line_size = PCI_CACHE_LINE_BYTES / 4; * * RETURNS: An appropriate -ERRNO error value on error, or zero for success. */ -static int -pci_set_cacheline_size(struct pci_dev *dev) +int pci_set_cacheline_size(struct pci_dev *dev) { u8 cacheline_size; if (!pci_cache_line_size) - return -EINVAL; /* The system doesn't support MWI. */ + return -EINVAL; /* Validate current setting: the PCI_CACHE_LINE_SIZE must be equal to or multiple of the right value. */ @@ -1928,6 +1962,24 @@ pci_set_cacheline_size(struct pci_dev *dev) return -EINVAL; } +EXPORT_SYMBOL_GPL(pci_set_cacheline_size); + +#ifdef PCI_DISABLE_MWI +int pci_set_mwi(struct pci_dev *dev) +{ + return 0; +} + +int pci_try_set_mwi(struct pci_dev *dev) +{ + return 0; +} + +void pci_clear_mwi(struct pci_dev *dev) +{ +} + +#else /** * pci_set_mwi - enables memory-write-invalidate PCI transaction @@ -2062,6 +2114,7 @@ pci_set_dma_mask(struct pci_dev *dev, u64 mask) return -EIO; dev->dma_mask = mask; + dev_dbg(&dev->dev, "using %dbit DMA mask\n", fls64(mask)); return 0; } @@ -2073,6 +2126,7 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) return -EIO; dev->dev.coherent_dma_mask = mask; + dev_dbg(&dev->dev, "using %dbit consistent DMA mask\n", fls64(mask)); return 0; } @@ -2099,9 +2153,9 @@ static int pcie_flr(struct pci_dev *dev, int probe) int i; int pos; u32 cap; - u16 status; + u16 status, control; - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + pos = pci_pcie_cap(dev); if (!pos) return -ENOTTY; @@ -2126,8 +2180,10 @@ static int pcie_flr(struct pci_dev *dev, int probe) "proceeding with reset anyway\n"); clear: - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_BCR_FLR); + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &control); + control |= PCI_EXP_DEVCTL_BCR_FLR; + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, control); + msleep(100); return 0; @@ -2450,7 +2506,7 @@ int pcie_get_readrq(struct pci_dev *dev) int ret, cap; u16 ctl; - cap = pci_find_capability(dev, PCI_CAP_ID_EXP); + cap = pci_pcie_cap(dev); if (!cap) return -EINVAL; @@ -2480,7 +2536,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq) v = (ffs(rq) - 8) << 12; - cap = pci_find_capability(dev, PCI_CAP_ID_EXP); + cap = pci_pcie_cap(dev); if (!cap) goto out; @@ -2540,7 +2596,7 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type) return reg; } - dev_err(&dev->dev, "BAR: invalid resource #%d\n", resno); + dev_err(&dev->dev, "BAR %d: invalid resource\n", resno); return 0; } @@ -2590,7 +2646,7 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode, #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0}; -spinlock_t resource_alignment_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(resource_alignment_lock); /** * pci_specified_resource_alignment - get resource alignment specified by user. diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index d92d1954a2fb17ea0415772531ee27563ec02da3..33ed8e0aba1ea25b54c928691e1a03c78b1391f8 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -311,4 +311,6 @@ static inline int pci_resource_alignment(struct pci_dev *dev, return resource_alignment(res); } +extern void pci_enable_acs(struct pci_dev *dev); + #endif /* DRIVERS_PCI_H */ diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 62d15f652bb6530f72605eea0cd3b964fd02a3f8..7fcd5331b14c37fdbbe4662e80afdf393191dcb8 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "aerdrv.h" struct aer_error_inj { @@ -35,10 +36,12 @@ struct aer_error_inj { u32 header_log1; u32 header_log2; u32 header_log3; + u16 domain; }; struct aer_error { struct list_head list; + u16 domain; unsigned int bus; unsigned int devfn; int pos_cap_err; @@ -66,22 +69,27 @@ static LIST_HEAD(pci_bus_ops_list); /* Protect einjected and pci_bus_ops_list */ static DEFINE_SPINLOCK(inject_lock); -static void aer_error_init(struct aer_error *err, unsigned int bus, - unsigned int devfn, int pos_cap_err) +static void aer_error_init(struct aer_error *err, u16 domain, + unsigned int bus, unsigned int devfn, + int pos_cap_err) { INIT_LIST_HEAD(&err->list); + err->domain = domain; err->bus = bus; err->devfn = devfn; err->pos_cap_err = pos_cap_err; } /* inject_lock must be held before calling */ -static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn) +static struct aer_error *__find_aer_error(u16 domain, unsigned int bus, + unsigned int devfn) { struct aer_error *err; list_for_each_entry(err, &einjected, list) { - if (bus == err->bus && devfn == err->devfn) + if (domain == err->domain && + bus == err->bus && + devfn == err->devfn) return err; } return NULL; @@ -90,7 +98,10 @@ static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn) /* inject_lock must be held before calling */ static struct aer_error *__find_aer_error_by_dev(struct pci_dev *dev) { - return __find_aer_error(dev->bus->number, dev->devfn); + int domain = pci_domain_nr(dev->bus); + if (domain < 0) + return NULL; + return __find_aer_error((u16)domain, dev->bus->number, dev->devfn); } /* inject_lock must be held before calling */ @@ -172,11 +183,15 @@ static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where, struct aer_error *err; unsigned long flags; struct pci_ops *ops; + int domain; spin_lock_irqsave(&inject_lock, flags); if (size != sizeof(u32)) goto out; - err = __find_aer_error(bus->number, devfn); + domain = pci_domain_nr(bus); + if (domain < 0) + goto out; + err = __find_aer_error((u16)domain, bus->number, devfn); if (!err) goto out; @@ -200,11 +215,15 @@ int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size, unsigned long flags; int rw1cs; struct pci_ops *ops; + int domain; spin_lock_irqsave(&inject_lock, flags); if (size != sizeof(u32)) goto out; - err = __find_aer_error(bus->number, devfn); + domain = pci_domain_nr(bus); + if (domain < 0) + goto out; + err = __find_aer_error((u16)domain, bus->number, devfn); if (!err) goto out; @@ -262,7 +281,7 @@ out: static struct pci_dev *pcie_find_root_port(struct pci_dev *dev) { while (1) { - if (!dev->is_pcie) + if (!pci_is_pcie(dev)) break; if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) return dev; @@ -305,25 +324,25 @@ static int aer_inject(struct aer_error_inj *einj) u32 sever; int ret = 0; - dev = pci_get_bus_and_slot(einj->bus, devfn); + dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn); if (!dev) - return -EINVAL; + return -ENODEV; rpdev = pcie_find_root_port(dev); if (!rpdev) { - ret = -EINVAL; + ret = -ENOTTY; goto out_put; } pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); if (!pos_cap_err) { - ret = -EIO; + ret = -ENOTTY; goto out_put; } pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever); rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR); if (!rp_pos_cap_err) { - ret = -EIO; + ret = -ENOTTY; goto out_put; } @@ -344,7 +363,8 @@ static int aer_inject(struct aer_error_inj *einj) if (!err) { err = err_alloc; err_alloc = NULL; - aer_error_init(err, einj->bus, devfn, pos_cap_err); + aer_error_init(err, einj->domain, einj->bus, devfn, + pos_cap_err); list_add(&err->list, &einjected); } err->uncor_status |= einj->uncor_status; @@ -358,7 +378,8 @@ static int aer_inject(struct aer_error_inj *einj) if (!rperr) { rperr = rperr_alloc; rperr_alloc = NULL; - aer_error_init(rperr, rpdev->bus->number, rpdev->devfn, + aer_error_init(rperr, pci_domain_nr(rpdev->bus), + rpdev->bus->number, rpdev->devfn, rp_pos_cap_err); list_add(&rperr->list, &einjected); } @@ -411,10 +432,11 @@ static ssize_t aer_inject_write(struct file *filp, const char __user *ubuf, if (!capable(CAP_SYS_ADMIN)) return -EPERM; - - if (usize != sizeof(struct aer_error_inj)) + if (usize < offsetof(struct aer_error_inj, domain) || + usize > sizeof(einj)) return -EINVAL; + memset(&einj, 0, sizeof(einj)); if (copy_from_user(&einj, ubuf, usize)) return -EFAULT; @@ -452,7 +474,7 @@ static void __exit aer_inject_exit(void) } spin_lock_irqsave(&inject_lock, flags); - list_for_each_entry_safe(err, err_next, &pci_bus_ops_list, list) { + list_for_each_entry_safe(err, err_next, &einjected, list) { list_del(&err->list); kfree(err); } diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 40c3cc5d1caf1f1c74eb0a64cb3096aa700c4ca2..97a345927b55644e1798095d385ff6104abb3499 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -53,7 +53,7 @@ static struct pci_error_handlers aer_error_handlers = { static struct pcie_port_service_driver aerdriver = { .name = "aer", - .port_type = PCIE_RC_PORT, + .port_type = PCI_EXP_TYPE_ROOT_PORT, .service = PCIE_PORT_SERVICE_AER, .probe = aer_probe, @@ -295,7 +295,7 @@ static void aer_error_resume(struct pci_dev *dev) u16 reg16; /* Clean up Root device status */ - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + pos = pci_pcie_cap(dev); pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, ®16); pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16); diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 9f5ccbeb4fa5fcef281eb2ed3d3a079ae885909e..ae672ca803331f6c70ad12422110b5079a2090c2 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -35,11 +35,14 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev) u16 reg16 = 0; int pos; + if (dev->aer_firmware_first) + return -EIO; + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); if (!pos) return -EIO; - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + pos = pci_pcie_cap(dev); if (!pos) return -EIO; @@ -60,7 +63,10 @@ int pci_disable_pcie_error_reporting(struct pci_dev *dev) u16 reg16 = 0; int pos; - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (dev->aer_firmware_first) + return -EIO; + + pos = pci_pcie_cap(dev); if (!pos) return -EIO; @@ -78,48 +84,27 @@ EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting); int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) { int pos; - u32 status, mask; + u32 status; pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); if (!pos) return -EIO; pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); - pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask); - if (dev->error_state == pci_channel_io_normal) - status &= ~mask; /* Clear corresponding nonfatal bits */ - else - status &= mask; /* Clear corresponding fatal bits */ - pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status); + if (status) + pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status); return 0; } EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status); -#if 0 -int pci_cleanup_aer_correct_error_status(struct pci_dev *dev) -{ - int pos; - u32 status; - - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); - if (!pos) - return -EIO; - - pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status); - pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status); - - return 0; -} -#endif /* 0 */ - static int set_device_error_reporting(struct pci_dev *dev, void *data) { bool enable = *((bool *)data); - if (dev->pcie_type == PCIE_RC_PORT || - dev->pcie_type == PCIE_SW_UPSTREAM_PORT || - dev->pcie_type == PCIE_SW_DOWNSTREAM_PORT) { + if ((dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) || + (dev->pcie_type == PCI_EXP_TYPE_UPSTREAM) || + (dev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)) { if (enable) pci_enable_pcie_error_reporting(dev); else @@ -218,7 +203,7 @@ static int find_device_iter(struct pci_dev *dev, void *data) */ if (atomic_read(&dev->enable_cnt) == 0) return 0; - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + pos = pci_pcie_cap(dev); if (!pos) return 0; /* Check if AER is enabled */ @@ -431,10 +416,9 @@ static int find_aer_service_iter(struct device *device, void *data) result = (struct find_aer_service_data *) data; if (device->bus == &pcie_port_bus_type) { - struct pcie_port_data *port_data; + struct pcie_device *pcie = to_pcie_device(device); - port_data = pci_get_drvdata(to_pcie_device(device)->port); - if (port_data->port_type == PCIE_SW_DOWNSTREAM_PORT) + if (pcie->port->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) result->is_downstream = 1; driver = device->driver; @@ -612,7 +596,7 @@ void aer_enable_rootport(struct aer_rpc *rpc) u16 reg16; u32 reg32; - pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); + pos = pci_pcie_cap(pdev); /* Clear PCIE Capability's Device Status */ pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, ®16); pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16); @@ -874,8 +858,22 @@ void aer_delete_rootport(struct aer_rpc *rpc) */ int aer_init(struct pcie_device *dev) { - if (aer_osc_setup(dev) && !forceload) - return -ENXIO; + if (dev->port->aer_firmware_first) { + dev_printk(KERN_DEBUG, &dev->device, + "PCIe errors handled by platform firmware.\n"); + goto out; + } + + if (aer_osc_setup(dev)) + goto out; return 0; +out: + if (forceload) { + dev_printk(KERN_DEBUG, &dev->device, + "aerdrv forceload requested.\n"); + dev->port->aer_firmware_first = 0; + return 0; + } + return -ENXIO; } diff --git a/drivers/pci/pcie/aer/ecrc.c b/drivers/pci/pcie/aer/ecrc.c index a928d8ab6bda2a95f3fce746617778c53163585d..a2747a663bc9bf9dc8dfa34ca1efc1f922701ef5 100644 --- a/drivers/pci/pcie/aer/ecrc.c +++ b/drivers/pci/pcie/aer/ecrc.c @@ -51,7 +51,7 @@ static int enable_ecrc_checking(struct pci_dev *dev) int pos; u32 reg32; - if (!dev->is_pcie) + if (!pci_is_pcie(dev)) return -ENODEV; pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); @@ -79,7 +79,7 @@ static int disable_ecrc_checking(struct pci_dev *dev) int pos; u32 reg32; - if (!dev->is_pcie) + if (!pci_is_pcie(dev)) return -ENODEV; pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 5b7056cec00c4ebcc74e0de01de421477dc27fad..5a01fc7fbf056371e6a1e90c874060cec486c221 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -122,7 +122,7 @@ static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable) struct pci_bus *linkbus = link->pdev->subordinate; list_for_each_entry(child, &linkbus->devices, bus_list) { - pos = pci_find_capability(child, PCI_CAP_ID_EXP); + pos = pci_pcie_cap(child); if (!pos) return; pci_read_config_word(child, pos + PCI_EXP_LNKCTL, ®16); @@ -156,7 +156,7 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) /* All functions should have the same cap and state, take the worst */ list_for_each_entry(child, &linkbus->devices, bus_list) { - pos = pci_find_capability(child, PCI_CAP_ID_EXP); + pos = pci_pcie_cap(child); if (!pos) return; pci_read_config_dword(child, pos + PCI_EXP_LNKCAP, ®32); @@ -191,23 +191,23 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) * Configuration, so just check one function */ child = list_entry(linkbus->devices.next, struct pci_dev, bus_list); - BUG_ON(!child->is_pcie); + BUG_ON(!pci_is_pcie(child)); /* Check downstream component if bit Slot Clock Configuration is 1 */ - cpos = pci_find_capability(child, PCI_CAP_ID_EXP); + cpos = pci_pcie_cap(child); pci_read_config_word(child, cpos + PCI_EXP_LNKSTA, ®16); if (!(reg16 & PCI_EXP_LNKSTA_SLC)) same_clock = 0; /* Check upstream component if bit Slot Clock Configuration is 1 */ - ppos = pci_find_capability(parent, PCI_CAP_ID_EXP); + ppos = pci_pcie_cap(parent); pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, ®16); if (!(reg16 & PCI_EXP_LNKSTA_SLC)) same_clock = 0; /* Configure downstream component, all functions */ list_for_each_entry(child, &linkbus->devices, bus_list) { - cpos = pci_find_capability(child, PCI_CAP_ID_EXP); + cpos = pci_pcie_cap(child); pci_read_config_word(child, cpos + PCI_EXP_LNKCTL, ®16); child_reg[PCI_FUNC(child->devfn)] = reg16; if (same_clock) @@ -247,7 +247,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) dev_printk(KERN_ERR, &parent->dev, "ASPM: Could not configure common clock\n"); list_for_each_entry(child, &linkbus->devices, bus_list) { - cpos = pci_find_capability(child, PCI_CAP_ID_EXP); + cpos = pci_pcie_cap(child); pci_write_config_word(child, cpos + PCI_EXP_LNKCTL, child_reg[PCI_FUNC(child->devfn)]); } @@ -300,7 +300,7 @@ static void pcie_get_aspm_reg(struct pci_dev *pdev, u16 reg16; u32 reg32; - pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); + pos = pci_pcie_cap(pdev); pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, ®32); info->support = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10; info->latency_encoding_l0s = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12; @@ -420,7 +420,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) child->pcie_type != PCI_EXP_TYPE_LEG_END) continue; - pos = pci_find_capability(child, PCI_CAP_ID_EXP); + pos = pci_pcie_cap(child); pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, ®32); /* Calculate endpoint L0s acceptable latency */ encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6; @@ -436,7 +436,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) { u16 reg16; - int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); + int pos = pci_pcie_cap(pdev); pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); reg16 &= ~0x3; @@ -503,7 +503,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) * very strange. Disable ASPM for the whole slot */ list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { - pos = pci_find_capability(child, PCI_CAP_ID_EXP); + pos = pci_pcie_cap(child); if (!pos) return -EINVAL; /* @@ -563,7 +563,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) struct pcie_link_state *link; int blacklist = !!pcie_aspm_sanity_check(pdev); - if (aspm_disabled || !pdev->is_pcie || pdev->link_state) + if (aspm_disabled || !pci_is_pcie(pdev) || pdev->link_state) return; if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) @@ -629,7 +629,8 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) struct pci_dev *parent = pdev->bus->self; struct pcie_link_state *link, *root, *parent_link; - if (aspm_disabled || !pdev->is_pcie || !parent || !parent->link_state) + if (aspm_disabled || !pci_is_pcie(pdev) || + !parent || !parent->link_state) return; if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) @@ -670,7 +671,7 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev) { struct pcie_link_state *link = pdev->link_state; - if (aspm_disabled || !pdev->is_pcie || !link) + if (aspm_disabled || !pci_is_pcie(pdev) || !link) return; if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) @@ -696,7 +697,7 @@ void pci_disable_link_state(struct pci_dev *pdev, int state) struct pci_dev *parent = pdev->bus->self; struct pcie_link_state *link; - if (aspm_disabled || !pdev->is_pcie) + if (aspm_disabled || !pci_is_pcie(pdev)) return; if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) @@ -841,8 +842,9 @@ void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev) { struct pcie_link_state *link_state = pdev->link_state; - if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && - pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) + if (!pci_is_pcie(pdev) || + (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && + pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) return; if (link_state->aspm_support) @@ -857,8 +859,9 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) { struct pcie_link_state *link_state = pdev->link_state; - if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && - pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) + if (!pci_is_pcie(pdev) || + (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && + pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) return; if (link_state->aspm_support) diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index 17ad53868f9f1566b0628061a4359cb15d1ae472..aaeb9d21cba5eab65b02aa1696a177e29def6d63 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -11,31 +11,16 @@ #include -#if !defined(PCI_CAP_ID_PME) -#define PCI_CAP_ID_PME 1 -#endif - -#if !defined(PCI_CAP_ID_EXP) -#define PCI_CAP_ID_EXP 0x10 -#endif - -#define PORT_TYPE_MASK 0xf -#define PORT_TO_SLOT_MASK 0x100 -#define SLOT_HP_CAPABLE_MASK 0x40 -#define PCIE_CAPABILITIES_REG 0x2 -#define PCIE_SLOT_CAPABILITIES_REG 0x14 -#define PCIE_PORT_DEVICE_MAXSERVICES 4 -#define PCIE_PORT_MSI_VECTOR_MASK 0x1f +#define PCIE_PORT_DEVICE_MAXSERVICES 4 /* - * According to the PCI Express Base Specification 2.0, the indices of the MSI-X - * table entires used by port services must not exceed 31 + * According to the PCI Express Base Specification 2.0, the indices of + * the MSI-X table entires used by port services must not exceed 31 */ #define PCIE_PORT_MAX_MSIX_ENTRIES 32 #define get_descriptor_id(type, service) (((type - 4) << 4) | service) extern struct bus_type pcie_port_bus_type; -extern int pcie_port_device_probe(struct pci_dev *dev); extern int pcie_port_device_register(struct pci_dev *dev); #ifdef CONFIG_PM extern int pcie_port_device_suspend(struct device *dev); diff --git a/drivers/pci/pcie/portdrv_bus.c b/drivers/pci/pcie/portdrv_bus.c index ef3a4eeaebb45077005f4948b458e3b241ba1f38..18bf90f748f6346753e92a8e47dca991966f02b4 100644 --- a/drivers/pci/pcie/portdrv_bus.c +++ b/drivers/pci/pcie/portdrv_bus.c @@ -26,7 +26,6 @@ EXPORT_SYMBOL_GPL(pcie_port_bus_type); static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) { struct pcie_device *pciedev; - struct pcie_port_data *port_data; struct pcie_port_service_driver *driver; if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type) @@ -38,10 +37,8 @@ static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) if (driver->service != pciedev->service) return 0; - port_data = pci_get_drvdata(pciedev->port); - - if (driver->port_type != PCIE_ANY_PORT - && driver->port_type != port_data->port_type) + if ((driver->port_type != PCIE_ANY_PORT) && + (driver->port_type != pciedev->port->pcie_type)) return 0; return 1; diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 52f84fca9f7d4ded61c797b58323b23f6cc6bb90..413262eb95b7607be682ac374bbcd7f9e00fc682 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -108,9 +108,9 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask) * the value in this field indicates which MSI-X Table entry is * used to generate the interrupt message." */ - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); - pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, ®16); - entry = (reg16 >> 9) & PCIE_PORT_MSI_VECTOR_MASK; + pos = pci_pcie_cap(dev); + pci_read_config_word(dev, pos + PCI_EXP_FLAGS, ®16); + entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9; if (entry >= nr_entries) goto Error; @@ -177,37 +177,40 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask) } /** - * assign_interrupt_mode - choose interrupt mode for PCI Express port services - * (INTx, MSI-X, MSI) and set up vectors + * init_service_irqs - initialize irqs for PCI Express port services * @dev: PCI Express port to handle - * @vectors: Array of interrupt vectors to populate + * @irqs: Array of irqs to populate * @mask: Bitmask of port capabilities returned by get_port_device_capability() * * Return value: Interrupt mode associated with the port */ -static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask) +static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask) { - int irq, interrupt_mode = PCIE_PORT_NO_IRQ; - int i; + int i, irq; /* Try to use MSI-X if supported */ - if (!pcie_port_enable_msix(dev, vectors, mask)) - return PCIE_PORT_MSIX_MODE; - + if (!pcie_port_enable_msix(dev, irqs, mask)) + return 0; /* We're not going to use MSI-X, so try MSI and fall back to INTx */ - if (!pci_enable_msi(dev)) - interrupt_mode = PCIE_PORT_MSI_MODE; - - if (interrupt_mode == PCIE_PORT_NO_IRQ && dev->pin) - interrupt_mode = PCIE_PORT_INTx_MODE; + irq = -1; + if (!pci_enable_msi(dev) || dev->pin) + irq = dev->irq; - irq = interrupt_mode != PCIE_PORT_NO_IRQ ? dev->irq : -1; for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) - vectors[i] = irq; + irqs[i] = irq; + irqs[PCIE_PORT_SERVICE_VC_SHIFT] = -1; - vectors[PCIE_PORT_SERVICE_VC_SHIFT] = -1; + if (irq < 0) + return -ENODEV; + return 0; +} - return interrupt_mode; +static void cleanup_service_irqs(struct pci_dev *dev) +{ + if (dev->msix_enabled) + pci_disable_msix(dev); + else if (dev->msi_enabled) + pci_disable_msi(dev); } /** @@ -226,13 +229,12 @@ static int get_port_device_capability(struct pci_dev *dev) u16 reg16; u32 reg32; - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); - pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, ®16); + pos = pci_pcie_cap(dev); + pci_read_config_word(dev, pos + PCI_EXP_FLAGS, ®16); /* Hot-Plug Capable */ - if (reg16 & PORT_TO_SLOT_MASK) { - pci_read_config_dword(dev, - pos + PCIE_SLOT_CAPABILITIES_REG, ®32); - if (reg32 & SLOT_HP_CAPABLE_MASK) + if (reg16 & PCI_EXP_FLAGS_SLOT) { + pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, ®32); + if (reg32 & PCI_EXP_SLTCAP_HPC) services |= PCIE_PORT_SERVICE_HP; } /* AER capable */ @@ -241,80 +243,47 @@ static int get_port_device_capability(struct pci_dev *dev) /* VC support */ if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC)) services |= PCIE_PORT_SERVICE_VC; + /* Root ports are capable of generating PME too */ + if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) + services |= PCIE_PORT_SERVICE_PME; return services; } /** - * pcie_device_init - initialize PCI Express port service device - * @dev: Port service device to initialize - * @parent: PCI Express port to associate the service device with - * @port_type: Type of the port - * @service_type: Type of service to associate with the service device + * pcie_device_init - allocate and initialize PCI Express port service device + * @pdev: PCI Express port to associate the service device with + * @service: Type of service to associate with the service device * @irq: Interrupt vector to associate with the service device */ -static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev, - int service_type, int irq) +static int pcie_device_init(struct pci_dev *pdev, int service, int irq) { - struct pcie_port_data *port_data = pci_get_drvdata(parent); + int retval; + struct pcie_device *pcie; struct device *device; - int port_type = port_data->port_type; - dev->port = parent; - dev->irq = irq; - dev->service = service_type; + pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); + if (!pcie) + return -ENOMEM; + pcie->port = pdev; + pcie->irq = irq; + pcie->service = service; /* Initialize generic device interface */ - device = &dev->device; - memset(device, 0, sizeof(struct device)); + device = &pcie->device; device->bus = &pcie_port_bus_type; - device->driver = NULL; - dev_set_drvdata(device, NULL); device->release = release_pcie_device; /* callback to free pcie dev */ dev_set_name(device, "%s:pcie%02x", - pci_name(parent), get_descriptor_id(port_type, service_type)); - device->parent = &parent->dev; -} - -/** - * alloc_pcie_device - allocate PCI Express port service device structure - * @parent: PCI Express port to associate the service device with - * @port_type: Type of the port - * @service_type: Type of service to associate with the service device - * @irq: Interrupt vector to associate with the service device - */ -static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, - int service_type, int irq) -{ - struct pcie_device *device; - - device = kzalloc(sizeof(struct pcie_device), GFP_KERNEL); - if (!device) - return NULL; - - pcie_device_init(parent, device, service_type, irq); - return device; -} - -/** - * pcie_port_device_probe - check if device is a PCI Express port - * @dev: Device to check - */ -int pcie_port_device_probe(struct pci_dev *dev) -{ - int pos, type; - u16 reg; - - if (!(pos = pci_find_capability(dev, PCI_CAP_ID_EXP))) - return -ENODEV; - - pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, ®); - type = (reg >> 4) & PORT_TYPE_MASK; - if ( type == PCIE_RC_PORT || type == PCIE_SW_UPSTREAM_PORT || - type == PCIE_SW_DOWNSTREAM_PORT ) - return 0; - - return -ENODEV; + pci_name(pdev), + get_descriptor_id(pdev->pcie_type, service)); + device->parent = &pdev->dev; + + retval = device_register(device); + if (retval) + kfree(pcie); + else + get_device(device); + return retval; } /** @@ -326,77 +295,49 @@ int pcie_port_device_probe(struct pci_dev *dev) */ int pcie_port_device_register(struct pci_dev *dev) { - struct pcie_port_data *port_data; - int status, capabilities, irq_mode, i, nr_serv; - int vectors[PCIE_PORT_DEVICE_MAXSERVICES]; - u16 reg16; - - port_data = kzalloc(sizeof(*port_data), GFP_KERNEL); - if (!port_data) - return -ENOMEM; - pci_set_drvdata(dev, port_data); - - /* Get port type */ - pci_read_config_word(dev, - pci_find_capability(dev, PCI_CAP_ID_EXP) + - PCIE_CAPABILITIES_REG, ®16); - port_data->port_type = (reg16 >> 4) & PORT_TYPE_MASK; + int status, capabilities, i, nr_service; + int irqs[PCIE_PORT_DEVICE_MAXSERVICES]; + /* Get and check PCI Express port services */ capabilities = get_port_device_capability(dev); - /* Root ports are capable of generating PME too */ - if (port_data->port_type == PCIE_RC_PORT) - capabilities |= PCIE_PORT_SERVICE_PME; - - irq_mode = assign_interrupt_mode(dev, vectors, capabilities); - if (irq_mode == PCIE_PORT_NO_IRQ) { - /* - * Don't use service devices that require interrupts if there is - * no way to generate them. - */ - if (!(capabilities & PCIE_PORT_SERVICE_VC)) { - status = -ENODEV; - goto Error; - } - capabilities = PCIE_PORT_SERVICE_VC; - } - port_data->port_irq_mode = irq_mode; + if (!capabilities) + return -ENODEV; + /* Enable PCI Express port device */ status = pci_enable_device(dev); if (status) - goto Error; + return status; pci_set_master(dev); + /* + * Initialize service irqs. Don't use service devices that + * require interrupts if there is no way to generate them. + */ + status = init_service_irqs(dev, irqs, capabilities); + if (status) { + capabilities &= PCIE_PORT_SERVICE_VC; + if (!capabilities) + goto error_disable; + } /* Allocate child services if any */ - for (i = 0, nr_serv = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) { - struct pcie_device *child; + status = -ENODEV; + nr_service = 0; + for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) { int service = 1 << i; - if (!(capabilities & service)) continue; - - child = alloc_pcie_device(dev, service, vectors[i]); - if (!child) - continue; - - status = device_register(&child->device); - if (status) { - kfree(child); - continue; - } - - get_device(&child->device); - nr_serv++; - } - if (!nr_serv) { - pci_disable_device(dev); - status = -ENODEV; - goto Error; + if (!pcie_device_init(dev, service, irqs[i])) + nr_service++; } + if (!nr_service) + goto error_cleanup_irqs; return 0; - Error: - kfree(port_data); +error_cleanup_irqs: + cleanup_service_irqs(dev); +error_disable: + pci_disable_device(dev); return status; } @@ -464,21 +405,9 @@ static int remove_iter(struct device *dev, void *data) */ void pcie_port_device_remove(struct pci_dev *dev) { - struct pcie_port_data *port_data = pci_get_drvdata(dev); - device_for_each_child(&dev->dev, NULL, remove_iter); + cleanup_service_irqs(dev); pci_disable_device(dev); - - switch (port_data->port_irq_mode) { - case PCIE_PORT_MSIX_MODE: - pci_disable_msix(dev); - break; - case PCIE_PORT_MSI_MODE: - pci_disable_msi(dev); - break; - } - - kfree(port_data); } /** diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index f635e476d6322d5032082e5697c208c18f3174b7..ce52ea34fee5513822ef903a8b27ab8d38dfb359 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -67,14 +67,16 @@ static struct dev_pm_ops pcie_portdrv_pm_ops = { * this port device. * */ -static int __devinit pcie_portdrv_probe (struct pci_dev *dev, - const struct pci_device_id *id ) +static int __devinit pcie_portdrv_probe(struct pci_dev *dev, + const struct pci_device_id *id) { - int status; + int status; - status = pcie_port_device_probe(dev); - if (status) - return status; + if (!pci_is_pcie(dev) || + ((dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && + (dev->pcie_type != PCI_EXP_TYPE_UPSTREAM) && + (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))) + return -ENODEV; if (!dev->irq && dev->pin) { dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; " diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 8105e32117f67d8ce60317fb9a4151b305773434..98ffb2de22e90a3a17984bc75480237178d882b8 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "pci.h" #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ @@ -163,12 +164,12 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, { u32 l, sz, mask; - mask = type ? ~PCI_ROM_ADDRESS_ENABLE : ~0; + mask = type ? PCI_ROM_ADDRESS_MASK : ~0; res->name = pci_name(dev); pci_read_config_dword(dev, pos, &l); - pci_write_config_dword(dev, pos, mask); + pci_write_config_dword(dev, pos, l | mask); pci_read_config_dword(dev, pos, &sz); pci_write_config_dword(dev, pos, l); @@ -223,9 +224,13 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, goto fail; if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) { - dev_err(&dev->dev, "can't handle 64-bit BAR\n"); + dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", + pos); goto fail; - } else if ((sizeof(resource_size_t) < 8) && l) { + } + + res->flags |= IORESOURCE_MEM_64; + if ((sizeof(resource_size_t) < 8) && l) { /* Address above 32-bit boundary; disable the BAR */ pci_write_config_dword(dev, pos, 0); pci_write_config_dword(dev, pos + 4, 0); @@ -234,14 +239,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, } else { res->start = l64; res->end = l64 + sz64; - dev_printk(KERN_DEBUG, &dev->dev, - "reg %x %s: %pR\n", pos, - (res->flags & IORESOURCE_PREFETCH) ? - "64bit mmio pref" : "64bit mmio", - res); + dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", + pos, res); } - - res->flags |= IORESOURCE_MEM_64; } else { sz = pci_size(l, sz, mask); @@ -251,11 +251,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, res->start = l; res->end = l + sz; - dev_printk(KERN_DEBUG, &dev->dev, "reg %x %s: %pR\n", pos, - (res->flags & IORESOURCE_IO) ? "io port" : - ((res->flags & IORESOURCE_PREFETCH) ? - "32bit mmio pref" : "32bit mmio"), - res); + dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res); } out: @@ -297,8 +293,11 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */ return; + dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n", + child->secondary, child->subordinate, + dev->transparent ? " (subtractive decode)": ""); + if (dev->transparent) { - dev_info(&dev->dev, "transparent bridge\n"); for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++) child->resource[i] = child->parent->resource[i - 3]; } @@ -323,7 +322,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->start = base; if (!res->end) res->end = limit + 0xfff; - dev_printk(KERN_DEBUG, &dev->dev, "bridge io port: %pR\n", res); + dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); } res = child->resource[1]; @@ -335,8 +334,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; res->start = base; res->end = limit + 0xfffff; - dev_printk(KERN_DEBUG, &dev->dev, "bridge 32bit mmio: %pR\n", - res); + dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); } res = child->resource[2]; @@ -375,9 +373,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->flags |= IORESOURCE_MEM_64; res->start = base; res->end = limit + 0xfffff; - dev_printk(KERN_DEBUG, &dev->dev, "bridge %sbit mmio pref: %pR\n", - (res->flags & PCI_PREF_RANGE_TYPE_64) ? "64" : "32", - res); + dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); } } @@ -651,13 +647,14 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, (child->number > bus->subordinate) || (child->number < bus->number) || (child->subordinate < bus->number)) { - pr_debug("PCI: Bus #%02x (-#%02x) is %s " - "hidden behind%s bridge #%02x (-#%02x)\n", + dev_info(&child->dev, "[bus %02x-%02x] %s " + "hidden behind%s bridge %s [bus %02x-%02x]\n", child->number, child->subordinate, (bus->number > child->subordinate && bus->subordinate < child->number) ? "wholly" : "partially", bus->self->transparent ? " transparent" : "", + dev_name(&bus->dev), bus->number, bus->subordinate); } bus = bus->parent; @@ -693,6 +690,7 @@ static void set_pcie_port_type(struct pci_dev *pdev) if (!pos) return; pdev->is_pcie = 1; + pdev->pcie_cap = pos; pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; } @@ -703,7 +701,7 @@ static void set_pcie_hotplug_bridge(struct pci_dev *pdev) u16 reg16; u32 reg32; - pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); + pos = pci_pcie_cap(pdev); if (!pos) return; pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); @@ -714,6 +712,12 @@ static void set_pcie_hotplug_bridge(struct pci_dev *pdev) pdev->is_hotplug_bridge = 1; } +static void set_pci_aer_firmware_first(struct pci_dev *pdev) +{ + if (acpi_hest_firmware_first_pci(pdev)) + pdev->aer_firmware_first = 1; +} + #define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) /** @@ -731,6 +735,7 @@ int pci_setup_device(struct pci_dev *dev) u32 class; u8 hdr_type; struct pci_slot *slot; + int pos = 0; if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type)) return -EIO; @@ -742,6 +747,7 @@ int pci_setup_device(struct pci_dev *dev) dev->multifunction = !!(hdr_type & 0x80); dev->error_state = pci_channel_io_normal; set_pcie_port_type(dev); + set_pci_aer_firmware_first(dev); list_for_each_entry(slot, &dev->bus->slots, list) if (PCI_SLOT(dev->devfn) == slot->number) @@ -822,6 +828,11 @@ int pci_setup_device(struct pci_dev *dev) dev->transparent = ((dev->class & 0xff) == 1); pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); set_pcie_hotplug_bridge(dev); + pos = pci_find_capability(dev, PCI_CAP_ID_SSVID); + if (pos) { + pci_read_config_word(dev, pos + PCI_SSVID_VENDOR_ID, &dev->subsystem_vendor); + pci_read_config_word(dev, pos + PCI_SSVID_DEVICE_ID, &dev->subsystem_device); + } break; case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ @@ -907,7 +918,7 @@ int pci_cfg_space_size(struct pci_dev *dev) if (class == PCI_CLASS_BRIDGE_HOST) return pci_cfg_space_size_ext(dev); - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + pos = pci_pcie_cap(dev); if (!pos) { pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); if (!pos) @@ -1014,6 +1025,9 @@ static void pci_init_capabilities(struct pci_dev *dev) /* Single Root I/O Virtualization */ pci_iov_init(dev); + + /* Enable ACS P2P upstream forwarding */ + pci_enable_acs(dev); } void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) @@ -1110,7 +1124,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) unsigned int devfn, pass, max = bus->secondary; struct pci_dev *dev; - pr_debug("PCI: Scanning bus %04x:%02x\n", pci_domain_nr(bus), bus->number); + dev_dbg(&bus->dev, "scanning bus\n"); /* Go find them, Rover! */ for (devfn = 0; devfn < 0x100; devfn += 8) @@ -1124,8 +1138,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) * all PCI-to-PCI bridges on this bus. */ if (!bus->is_added) { - pr_debug("PCI: Fixups for bus %04x:%02x\n", - pci_domain_nr(bus), bus->number); + dev_dbg(&bus->dev, "fixups for bus\n"); pcibios_fixup_bus(bus); if (pci_is_root_bus(bus)) bus->is_added = 1; @@ -1145,8 +1158,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) * * Return how far we've got finding sub-buses. */ - pr_debug("PCI: Bus scan for %04x:%02x returning with max=%02x\n", - pci_domain_nr(bus), bus->number, max); + dev_dbg(&bus->dev, "bus scan returning with max=%02x\n", max); return max; } @@ -1154,7 +1166,7 @@ struct pci_bus * pci_create_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata) { int error; - struct pci_bus *b; + struct pci_bus *b, *b2; struct device *dev; b = pci_alloc_bus(); @@ -1170,9 +1182,10 @@ struct pci_bus * pci_create_bus(struct device *parent, b->sysdata = sysdata; b->ops = ops; - if (pci_find_bus(pci_domain_nr(b), bus)) { + b2 = pci_find_bus(pci_domain_nr(b), bus); + if (b2) { /* If we already got to this bus through a different bridge, ignore it */ - pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus); + dev_dbg(&b2->dev, "bus already known\n"); goto err_out; } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 245d2cdb47651d4d095edd847417b5251565fc69..7cfa7c38d31869bd482138fa2fc3fcba06d561e7 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -357,7 +357,7 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, pcibios_bus_to_resource(dev, res, &bus_region); pci_claim_resource(dev, nr); - dev_info(&dev->dev, "quirk: region %04x-%04x claimed by %s\n", region, region + size - 1, name); + dev_info(&dev->dev, "quirk: %pR claimed by %s\n", res, name); } } @@ -1680,6 +1680,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_ */ #define AMD_813X_MISC 0x40 #define AMD_813X_NOIOAMODE (1<<0) +#define AMD_813X_REV_B1 0x12 #define AMD_813X_REV_B2 0x13 static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) @@ -1688,7 +1689,8 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) if (noioapicquirk) return; - if (dev->revision == AMD_813X_REV_B2) + if ((dev->revision == AMD_813X_REV_B1) || + (dev->revision == AMD_813X_REV_B2)) return; pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword); @@ -1698,8 +1700,10 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) dev_info(&dev->dev, "disabled boot interrupts on device [%04x:%04x]\n", dev->vendor, dev->device); } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_amd_813x_boot_interrupt); -DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, quirk_disable_amd_813x_boot_interrupt); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_amd_813x_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_amd_813x_boot_interrupt); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, quirk_disable_amd_813x_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, quirk_disable_amd_813x_boot_interrupt); #define AMD_8111_PCI_IRQ_ROUTING 0x56 @@ -2595,9 +2599,37 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) static int __init pci_apply_final_quirks(void) { struct pci_dev *dev = NULL; + u8 cls = 0; + u8 tmp; + + if (pci_cache_line_size) + printk(KERN_DEBUG "PCI: CLS %u bytes\n", + pci_cache_line_size << 2); while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { pci_fixup_device(pci_fixup_final, dev); + /* + * If arch hasn't set it explicitly yet, use the CLS + * value shared by all PCI devices. If there's a + * mismatch, fall back to the default value. + */ + if (!pci_cache_line_size) { + pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp); + if (!cls) + cls = tmp; + if (!tmp || cls == tmp) + continue; + + printk(KERN_DEBUG "PCI: CLS mismatch (%u != %u), " + "using %u bytes\n", cls << 2, tmp << 2, + pci_dfl_cache_line_size << 2); + pci_cache_line_size = pci_dfl_cache_line_size; + } + } + if (!pci_cache_line_size) { + printk(KERN_DEBUG "PCI: CLS %u bytes, default %u\n", + cls << 2, pci_dfl_cache_line_size << 2); + pci_cache_line_size = cls; } return 0; diff --git a/drivers/pci/search.c b/drivers/pci/search.c index ec415352d9ba5cbf0d5572adfad37618ea88d773..6dae871432588e29f93b86e7a2565856cc36ab99 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -26,14 +26,14 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev) { struct pci_dev *tmp = NULL; - if (pdev->is_pcie) + if (pci_is_pcie(pdev)) return NULL; while (1) { if (pci_is_root_bus(pdev->bus)) break; pdev = pdev->bus->self; /* a p2p bridge */ - if (!pdev->is_pcie) { + if (!pci_is_pcie(pdev)) { tmp = pdev; continue; } @@ -149,32 +149,33 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) } /** - * pci_get_bus_and_slot - locate PCI device from a given PCI bus & slot - * @bus: number of PCI bus on which desired PCI device resides - * @devfn: encodes number of PCI slot in which the desired PCI - * device resides and the logical device number within that slot - * in case of multi-function devices. - * - * Note: the bus/slot search is limited to PCI domain (segment) 0. + * pci_get_domain_bus_and_slot - locate PCI device for a given PCI domain (segment), bus, and slot + * @domain: PCI domain/segment on which the PCI device resides. + * @bus: PCI bus on which desired PCI device resides + * @devfn: encodes number of PCI slot in which the desired PCI device + * resides and the logical device number within that slot in case of + * multi-function devices. * - * Given a PCI bus and slot/function number, the desired PCI device - * is located in system global list of PCI devices. If the device - * is found, a pointer to its data structure is returned. If no - * device is found, %NULL is returned. The returned device has its - * reference count bumped by one. + * Given a PCI domain, bus, and slot/function number, the desired PCI + * device is located in the list of PCI devices. If the device is + * found, its reference count is increased and this function returns a + * pointer to its data structure. The caller must decrement the + * reference count by calling pci_dev_put(). If no device is found, + * %NULL is returned. */ - -struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn) +struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus, + unsigned int devfn) { struct pci_dev *dev = NULL; while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (pci_domain_nr(dev->bus) == 0 && - (dev->bus->number == bus && dev->devfn == devfn)) + if (pci_domain_nr(dev->bus) == domain && + (dev->bus->number == bus && dev->devfn == devfn)) return dev; } return NULL; } +EXPORT_SYMBOL(pci_get_domain_bus_and_slot); static int match_pci_dev_by_id(struct device *dev, void *data) { @@ -354,5 +355,4 @@ EXPORT_SYMBOL(pci_find_next_bus); EXPORT_SYMBOL(pci_get_device); EXPORT_SYMBOL(pci_get_subsys); EXPORT_SYMBOL(pci_get_slot); -EXPORT_SYMBOL(pci_get_bus_and_slot); EXPORT_SYMBOL(pci_get_class); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index cb1a027eb552228a08bc53cef27af8e7db34e70e..c48cd377b3f56451731ed72d6953caaea349f8bd 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -71,53 +71,50 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus) void pci_setup_cardbus(struct pci_bus *bus) { struct pci_dev *bridge = bus->self; + struct resource *res; struct pci_bus_region region; - dev_info(&bridge->dev, "CardBus bridge, secondary bus %04x:%02x\n", - pci_domain_nr(bus), bus->number); + dev_info(&bridge->dev, "CardBus bridge to [bus %02x-%02x]\n", + bus->secondary, bus->subordinate); - pcibios_resource_to_bus(bridge, ®ion, bus->resource[0]); - if (bus->resource[0]->flags & IORESOURCE_IO) { + res = bus->resource[0]; + pcibios_resource_to_bus(bridge, ®ion, res); + if (res->flags & IORESOURCE_IO) { /* * The IO resource is allocated a range twice as large as it * would normally need. This allows us to set both IO regs. */ - dev_info(&bridge->dev, " IO window: %#08lx-%#08lx\n", - (unsigned long)region.start, - (unsigned long)region.end); + dev_info(&bridge->dev, " bridge window %pR\n", res); pci_write_config_dword(bridge, PCI_CB_IO_BASE_0, region.start); pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0, region.end); } - pcibios_resource_to_bus(bridge, ®ion, bus->resource[1]); - if (bus->resource[1]->flags & IORESOURCE_IO) { - dev_info(&bridge->dev, " IO window: %#08lx-%#08lx\n", - (unsigned long)region.start, - (unsigned long)region.end); + res = bus->resource[1]; + pcibios_resource_to_bus(bridge, ®ion, res); + if (res->flags & IORESOURCE_IO) { + dev_info(&bridge->dev, " bridge window %pR\n", res); pci_write_config_dword(bridge, PCI_CB_IO_BASE_1, region.start); pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1, region.end); } - pcibios_resource_to_bus(bridge, ®ion, bus->resource[2]); - if (bus->resource[2]->flags & IORESOURCE_MEM) { - dev_info(&bridge->dev, " PREFETCH window: %#08lx-%#08lx\n", - (unsigned long)region.start, - (unsigned long)region.end); + res = bus->resource[2]; + pcibios_resource_to_bus(bridge, ®ion, res); + if (res->flags & IORESOURCE_MEM) { + dev_info(&bridge->dev, " bridge window %pR\n", res); pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0, region.start); pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0, region.end); } - pcibios_resource_to_bus(bridge, ®ion, bus->resource[3]); - if (bus->resource[3]->flags & IORESOURCE_MEM) { - dev_info(&bridge->dev, " MEM window: %#08lx-%#08lx\n", - (unsigned long)region.start, - (unsigned long)region.end); + res = bus->resource[3]; + pcibios_resource_to_bus(bridge, ®ion, res); + if (res->flags & IORESOURCE_MEM) { + dev_info(&bridge->dev, " bridge window %pR\n", res); pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1, region.start); pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1, @@ -140,34 +137,33 @@ EXPORT_SYMBOL(pci_setup_cardbus); static void pci_setup_bridge(struct pci_bus *bus) { struct pci_dev *bridge = bus->self; + struct resource *res; struct pci_bus_region region; u32 l, bu, lu, io_upper16; - int pref_mem64; if (pci_is_enabled(bridge)) return; - dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n", - pci_domain_nr(bus), bus->number); + dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n", + bus->secondary, bus->subordinate); /* Set up the top and bottom of the PCI I/O segment for this bus. */ - pcibios_resource_to_bus(bridge, ®ion, bus->resource[0]); - if (bus->resource[0]->flags & IORESOURCE_IO) { + res = bus->resource[0]; + pcibios_resource_to_bus(bridge, ®ion, res); + if (res->flags & IORESOURCE_IO) { pci_read_config_dword(bridge, PCI_IO_BASE, &l); l &= 0xffff0000; l |= (region.start >> 8) & 0x00f0; l |= region.end & 0xf000; /* Set up upper 16 bits of I/O base/limit. */ io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); - dev_info(&bridge->dev, " IO window: %#04lx-%#04lx\n", - (unsigned long)region.start, - (unsigned long)region.end); + dev_info(&bridge->dev, " bridge window %pR\n", res); } else { /* Clear upper 16 bits of I/O base/limit. */ io_upper16 = 0; l = 0x00f0; - dev_info(&bridge->dev, " IO window: disabled\n"); + dev_info(&bridge->dev, " bridge window [io disabled]\n"); } /* Temporarily disable the I/O range before updating PCI_IO_BASE. */ pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff); @@ -178,17 +174,16 @@ static void pci_setup_bridge(struct pci_bus *bus) /* Set up the top and bottom of the PCI Memory segment for this bus. */ - pcibios_resource_to_bus(bridge, ®ion, bus->resource[1]); - if (bus->resource[1]->flags & IORESOURCE_MEM) { + res = bus->resource[1]; + pcibios_resource_to_bus(bridge, ®ion, res); + if (res->flags & IORESOURCE_MEM) { l = (region.start >> 16) & 0xfff0; l |= region.end & 0xfff00000; - dev_info(&bridge->dev, " MEM window: %#08lx-%#08lx\n", - (unsigned long)region.start, - (unsigned long)region.end); + dev_info(&bridge->dev, " bridge window %pR\n", res); } else { l = 0x0000fff0; - dev_info(&bridge->dev, " MEM window: disabled\n"); + dev_info(&bridge->dev, " bridge window [mem disabled]\n"); } pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); @@ -198,34 +193,27 @@ static void pci_setup_bridge(struct pci_bus *bus) pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0); /* Set up PREF base/limit. */ - pref_mem64 = 0; bu = lu = 0; - pcibios_resource_to_bus(bridge, ®ion, bus->resource[2]); - if (bus->resource[2]->flags & IORESOURCE_PREFETCH) { - int width = 8; + res = bus->resource[2]; + pcibios_resource_to_bus(bridge, ®ion, res); + if (res->flags & IORESOURCE_PREFETCH) { l = (region.start >> 16) & 0xfff0; l |= region.end & 0xfff00000; - if (bus->resource[2]->flags & IORESOURCE_MEM_64) { - pref_mem64 = 1; + if (res->flags & IORESOURCE_MEM_64) { bu = upper_32_bits(region.start); lu = upper_32_bits(region.end); - width = 16; } - dev_info(&bridge->dev, " PREFETCH window: %#0*llx-%#0*llx\n", - width, (unsigned long long)region.start, - width, (unsigned long long)region.end); + dev_info(&bridge->dev, " bridge window %pR\n", res); } else { l = 0x0000fff0; - dev_info(&bridge->dev, " PREFETCH window: disabled\n"); + dev_info(&bridge->dev, " bridge window [mem pref disabled]\n"); } pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l); - if (pref_mem64) { - /* Set the upper 32 bits of PREF base & limit. */ - pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); - pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); - } + /* Set the upper 32 bits of PREF base & limit. */ + pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); + pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); } @@ -345,6 +333,10 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) #endif size = ALIGN(size + size1, 4096); if (!size) { + if (b_res->start || b_res->end) + dev_info(&bus->self->dev, "disabling bridge window " + "%pR to [bus %02x-%02x] (unused)\n", b_res, + bus->secondary, bus->subordinate); b_res->flags = 0; return; } @@ -390,8 +382,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, align = pci_resource_alignment(dev, r); order = __ffs(align) - 20; if (order > 11) { - dev_warn(&dev->dev, "BAR %d bad alignment %llx: " - "%pR\n", i, (unsigned long long)align, r); + dev_warn(&dev->dev, "disabling BAR %d: %pR " + "(bad alignment %#llx)\n", i, r, + (unsigned long long) align); r->flags = 0; continue; } @@ -425,6 +418,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, } size = ALIGN(size, min_align); if (!size) { + if (b_res->start || b_res->end) + dev_info(&bus->self->dev, "disabling bridge window " + "%pR to [bus %02x-%02x] (unused)\n", b_res, + bus->secondary, bus->subordinate); b_res->flags = 0; return 1; } @@ -582,10 +579,7 @@ static void pci_bus_dump_res(struct pci_bus *bus) if (!res || !res->end) continue; - dev_printk(KERN_DEBUG, &bus->dev, "resource %d %s %pR\n", i, - (res->flags & IORESOURCE_IO) ? "io: " : - ((res->flags & IORESOURCE_PREFETCH)? "pref mem":"mem:"), - res); + dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res); } } diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index c54526b206b5da957d78170a6e430ce5c3b9f95b..7d678bb15ffb30daed8bebf18d1ef5642a30a13b 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -51,12 +51,6 @@ void pci_update_resource(struct pci_dev *dev, int resno) pcibios_resource_to_bus(dev, ®ion, res); - dev_dbg(&dev->dev, "BAR %d: got res %pR bus [%#llx-%#llx] " - "flags %#lx\n", resno, res, - (unsigned long long)region.start, - (unsigned long long)region.end, - (unsigned long)res->flags); - new = region.start | (res->flags & PCI_REGION_FLAG_MASK); if (res->flags & IORESOURCE_IO) mask = (u32)PCI_BASE_ADDRESS_IO_MASK; @@ -91,9 +85,9 @@ void pci_update_resource(struct pci_dev *dev, int resno) } } res->flags &= ~IORESOURCE_UNSET; - dev_dbg(&dev->dev, "BAR %d: moved to bus [%#llx-%#llx] flags %#lx\n", - resno, (unsigned long long)region.start, - (unsigned long long)region.end, res->flags); + dev_info(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx]\n", + resno, res, (unsigned long long)region.start, + (unsigned long long)region.end); } int pci_claim_resource(struct pci_dev *dev, int resource) @@ -103,20 +97,17 @@ int pci_claim_resource(struct pci_dev *dev, int resource) int err; root = pci_find_parent_resource(dev, res); - - err = -EINVAL; - if (root != NULL) - err = request_resource(root, res); - - if (err) { - const char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge"; - dev_err(&dev->dev, "BAR %d: %s of %s %pR\n", - resource, - root ? "address space collision on" : - "no parent found for", - dtype, res); + if (!root) { + dev_err(&dev->dev, "no compatible bridge window for %pR\n", + res); + return -EINVAL; } + err = request_resource(root, res); + if (err) + dev_err(&dev->dev, + "address space collision: %pR already in use\n", res); + return err; } EXPORT_SYMBOL(pci_claim_resource); @@ -124,7 +115,7 @@ EXPORT_SYMBOL(pci_claim_resource); #ifdef CONFIG_PCI_QUIRKS void pci_disable_bridge_window(struct pci_dev *dev) { - dev_dbg(&dev->dev, "Disabling bridge window.\n"); + dev_info(&dev->dev, "disabling bridge mem windows\n"); /* MMIO Base/Limit */ pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0); @@ -165,6 +156,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, if (!ret) { res->flags &= ~IORESOURCE_STARTALIGN; + dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res); if (resno < PCI_BRIDGE_RESOURCES) pci_update_resource(dev, resno); } @@ -178,12 +170,12 @@ int pci_assign_resource(struct pci_dev *dev, int resno) resource_size_t align; struct pci_bus *bus; int ret; + char *type; align = pci_resource_alignment(dev, res); if (!align) { - dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus " - "alignment) %pR flags %#lx\n", - resno, res, res->flags); + dev_info(&dev->dev, "BAR %d: can't assign %pR " + "(bogus alignment)\n", resno, res); return -EINVAL; } @@ -198,9 +190,20 @@ int pci_assign_resource(struct pci_dev *dev, int resno) break; } - if (ret) - dev_info(&dev->dev, "BAR %d: can't allocate %s resource %pR\n", - resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res); + if (ret) { + if (res->flags & IORESOURCE_MEM) + if (res->flags & IORESOURCE_PREFETCH) + type = "mem pref"; + else + type = "mem"; + else if (res->flags & IORESOURCE_IO) + type = "io"; + else + type = "unknown"; + dev_info(&dev->dev, + "BAR %d: can't assign %s (size %#llx)\n", + resno, type, (unsigned long long) resource_size(res)); + } return ret; } @@ -225,9 +228,8 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) r_align = pci_resource_alignment(dev, r); if (!r_align) { - dev_warn(&dev->dev, "BAR %d: bogus alignment " - "%pR flags %#lx\n", - i, r, r->flags); + dev_warn(&dev->dev, "BAR %d: %pR has bogus alignment\n", + i, r); continue; } for (list = head; ; list = list->next) { @@ -274,8 +276,8 @@ int pci_enable_resources(struct pci_dev *dev, int mask) continue; if (!r->parent) { - dev_err(&dev->dev, "device not available because of " - "BAR %d %pR collisions\n", i, r); + dev_err(&dev->dev, "device not available " + "(can't reserve %pR)\n", r); return -EINVAL; } diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index cd5082d3ca19272294410fa8b45f82b9aa6b9494..9f3adbd9f7005e02b6886f5915f42faaee89994f 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -64,7 +64,7 @@ config PCMCIA_IOCTL If unsure, say Y. config CARDBUS - bool "32-bit CardBus support" + bool "32-bit CardBus support" depends on PCI default y ---help--- @@ -87,8 +87,8 @@ config YENTA select PCCARD_NONSTATIC ---help--- This option enables support for CardBus host bridges. Virtually - all modern PCMCIA bridges are CardBus compatible. A "bridge" is - the hardware inside your computer that PCMCIA cards are plugged + all modern PCMCIA bridges are CardBus compatible. A "bridge" is + the hardware inside your computer that PCMCIA cards are plugged into. To compile this driver as modules, choose M here: the @@ -208,7 +208,7 @@ config PCMCIA_PXA2XX depends on ARM && ARCH_PXA && PCMCIA depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ - || ARCH_VIPER || ARCH_PXA_ESERIES || MACH_STARGATE2) + || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2) select PCMCIA_SOC_COMMON help Say Y here to include support for the PXA2xx PCMCIA controller diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 382938313991a263d77a43c5a03d28516f9939cb..83ff802de5446944d895f9c796d0544275c97533 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -67,7 +67,7 @@ pxa2xx-obj-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock_cs.o pxa2xx-obj-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o pxa2xx-obj-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o pxa2xx-obj-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x2xx_cs.o -pxa2xx-obj-$(CONFIG_ARCH_VIPER) += pxa2xx_viper.o +pxa2xx-obj-$(CONFIG_ARCOM_PCMCIA) += pxa2xx_viper.o pxa2xx-obj-$(CONFIG_TRIZEPS_PCMCIA) += pxa2xx_trizeps4.o pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o pxa2xx-obj-$(CONFIG_MACH_PALMTC) += pxa2xx_palmtc.o diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 4cd70d0568109d061d6b716140adc52494cfd062..cdf50f3bc2df389af234ed8976017ba5c717e218 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -27,8 +27,8 @@ #include #include #include +#include #include -#include #include #include @@ -58,7 +58,7 @@ image number and an offset within that image. xlate_rom_addr() converts an image/offset address to an absolute offset from the ROM's base address. - + =====================================================================*/ static u_int xlate_rom_addr(void __iomem *b, u_int addr) @@ -85,10 +85,10 @@ static u_int xlate_rom_addr(void __iomem *b, u_int addr) These are similar to setup_cis_mem and release_cis_mem for 16-bit cards. The "result" that is used externally is the cb_cis_virt pointer in the struct pcmcia_socket structure. - + =====================================================================*/ -static void cb_release_cis_mem(struct pcmcia_socket * s) +static void cb_release_cis_mem(struct pcmcia_socket *s) { if (s->cb_cis_virt) { dev_dbg(&s->dev, "cb_release_cis_mem()\n"); @@ -98,7 +98,7 @@ static void cb_release_cis_mem(struct pcmcia_socket * s) } } -static int cb_setup_cis_mem(struct pcmcia_socket * s, struct resource *res) +static int cb_setup_cis_mem(struct pcmcia_socket *s, struct resource *res) { unsigned int start, size; @@ -124,10 +124,11 @@ static int cb_setup_cis_mem(struct pcmcia_socket * s, struct resource *res) This is used by the CIS processing code to read CIS information from a CardBus device. - + =====================================================================*/ -int read_cb_mem(struct pcmcia_socket * s, int space, u_int addr, u_int len, void *ptr) +int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len, + void *ptr) { struct pci_dev *dev; struct resource *res; @@ -181,40 +182,47 @@ fail: cb_alloc() and cb_free() allocate and free the kernel data structures for a Cardbus device, and handle the lowest level PCI device setup issues. - + =====================================================================*/ -/* - * Since there is only one interrupt available to CardBus - * devices, all devices downstream of this device must - * be using this IRQ. - */ -static void cardbus_assign_irqs(struct pci_bus *bus, int irq) +static void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq) { struct pci_dev *dev; list_for_each_entry(dev, &bus->devices, bus_list) { u8 irq_pin; + /* + * Since there is only one interrupt available to + * CardBus devices, all devices downstream of this + * device must be using this IRQ. + */ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin); if (irq_pin) { dev->irq = irq; pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } + /* + * Some controllers transfer very slowly with 0 CLS. + * Configure it. This may fail as CLS configuration + * is mandatory only for MWI. + */ + pci_set_cacheline_size(dev); + if (dev->subordinate) - cardbus_assign_irqs(dev->subordinate, irq); + cardbus_config_irq_and_cls(dev->subordinate, irq); } } -int __ref cb_alloc(struct pcmcia_socket * s) +int __ref cb_alloc(struct pcmcia_socket *s) { struct pci_bus *bus = s->cb_dev->subordinate; struct pci_dev *dev; unsigned int max, pass; s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0)); -// pcibios_fixup_bus(bus); +/* pcibios_fixup_bus(bus); */ max = bus->secondary; for (pass = 0; pass < 2; pass++) @@ -228,7 +236,7 @@ int __ref cb_alloc(struct pcmcia_socket * s) */ pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); - cardbus_assign_irqs(bus, s->pci_irq); + cardbus_config_irq_and_cls(bus, s->pci_irq); /* socket specific tune function */ if (s->tune_bridge) @@ -241,7 +249,7 @@ int __ref cb_alloc(struct pcmcia_socket * s) return 0; } -void cb_free(struct pcmcia_socket * s) +void cb_free(struct pcmcia_socket *s) { struct pci_dev *bridge = s->cb_dev; diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 8c1b73cf021b2fee37c17f792748f27b0ec5f794..25b1cd219e374202b6d4f8f3fd84e849204daaa3 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include @@ -125,7 +125,7 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag Low-level functions to read and write CIS memory. I think the write routine is only useful for writing one-byte registers. - + ======================================================================*/ /* Bits in attr field */ @@ -137,7 +137,7 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, { void __iomem *sys, *end; unsigned char *buf = ptr; - + dev_dbg(&s->dev, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len); if (attr & IS_INDIRECT) { @@ -203,7 +203,7 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, { void __iomem *sys, *end; unsigned char *buf = ptr; - + dev_dbg(&s->dev, "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len); if (attr & IS_INDIRECT) { @@ -262,7 +262,7 @@ EXPORT_SYMBOL(pcmcia_write_cis_mem); This is a wrapper around read_cis_mem, with the same interface, but which caches information, for cards whose CIS may not be readable all the time. - + ======================================================================*/ static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, @@ -342,7 +342,7 @@ EXPORT_SYMBOL(destroy_cis_cache); This verifies if the CIS of a card matches what is in the CIS cache. - + ======================================================================*/ int verify_cis_cache(struct pcmcia_socket *s) @@ -381,7 +381,7 @@ int verify_cis_cache(struct pcmcia_socket *s) For really bad cards, we provide a facility for uploading a replacement CIS. - + ======================================================================*/ int pcmcia_replace_cis(struct pcmcia_socket *s, @@ -406,7 +406,7 @@ EXPORT_SYMBOL(pcmcia_replace_cis); /*====================================================================== The high-level CIS tuple services - + ======================================================================*/ typedef struct tuple_flags { @@ -421,8 +421,6 @@ typedef struct tuple_flags { #define MFC_FN(f) (((tuple_flags *)(&(f)))->mfc_fn) #define SPACE(f) (((tuple_flags *)(&(f)))->space) -int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *tuple); - int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple_t *tuple) { if (!s) @@ -523,10 +521,11 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_ ofs++; continue; } } - + /* End of chain? Follow long link if possible */ if (link[0] == CISTPL_END) { - if ((ofs = follow_link(s, tuple)) < 0) + ofs = follow_link(s, tuple); + if (ofs < 0) return -ENOSPC; attr = SPACE(tuple->Flags); read_cis_cache(s, attr, ofs, 2, link); @@ -578,7 +577,7 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_ } else if (tuple->DesiredTuple == RETURN_FIRST_TUPLE) break; - + if (link[0] == tuple->DesiredTuple) break; ofs += link[1] + 2; @@ -587,7 +586,7 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_ dev_dbg(&s->dev, "cs: overrun in pcmcia_get_next_tuple\n"); return -ENOSPC; } - + tuple->TupleCode = link[0]; tuple->TupleLink = link[1]; tuple->CISOffset = ofs + 2; @@ -623,7 +622,7 @@ EXPORT_SYMBOL(pccard_get_tuple_data); /*====================================================================== Parsing routines for individual tuples - + ======================================================================*/ static int parse_device(tuple_t *tuple, cistpl_device_t *device) @@ -637,26 +636,37 @@ static int parse_device(tuple_t *tuple, cistpl_device_t *device) device->ndev = 0; for (i = 0; i < CISTPL_MAX_DEVICES; i++) { - - if (*p == 0xff) break; + + if (*p == 0xff) + break; device->dev[i].type = (*p >> 4); device->dev[i].wp = (*p & 0x08) ? 1 : 0; switch (*p & 0x07) { - case 0: device->dev[i].speed = 0; break; - case 1: device->dev[i].speed = 250; break; - case 2: device->dev[i].speed = 200; break; - case 3: device->dev[i].speed = 150; break; - case 4: device->dev[i].speed = 100; break; + case 0: + device->dev[i].speed = 0; + break; + case 1: + device->dev[i].speed = 250; + break; + case 2: + device->dev[i].speed = 200; + break; + case 3: + device->dev[i].speed = 150; + break; + case 4: + device->dev[i].speed = 100; + break; case 7: - if (++p == q) - return -EINVAL; - device->dev[i].speed = SPEED_CVT(*p); - while (*p & 0x80) if (++p == q) return -EINVAL; - break; + device->dev[i].speed = SPEED_CVT(*p); + while (*p & 0x80) + if (++p == q) + return -EINVAL; + break; default: - return -EINVAL; + return -EINVAL; } if (++p == q) @@ -671,7 +681,7 @@ static int parse_device(tuple_t *tuple, cistpl_device_t *device) if (++p == q) break; } - + return 0; } @@ -706,9 +716,9 @@ static int parse_longlink_mfc(tuple_t *tuple, { u_char *p; int i; - + p = (u_char *)tuple->TupleData; - + link->nfn = *p; p++; if (tuple->TupleDataLen <= link->nfn*5) return -EINVAL; @@ -737,11 +747,13 @@ static int parse_strings(u_char *p, u_char *q, int max, ns++; for (;;) { s[j++] = (*p == 0xff) ? '\0' : *p; - if ((*p == '\0') || (*p == 0xff)) break; + if ((*p == '\0') || (*p == 0xff)) + break; if (++p == q) return -EINVAL; } - if ((*p == 0xff) || (++p == q)) break; + if ((*p == 0xff) || (++p == q)) + break; } if (found) { *found = ns; @@ -756,10 +768,10 @@ static int parse_strings(u_char *p, u_char *q, int max, static int parse_vers_1(tuple_t *tuple, cistpl_vers_1_t *vers_1) { u_char *p, *q; - + p = (u_char *)tuple->TupleData; q = p + tuple->TupleDataLen; - + vers_1->major = *p; p++; vers_1->minor = *p; p++; if (p >= q) @@ -774,10 +786,10 @@ static int parse_vers_1(tuple_t *tuple, cistpl_vers_1_t *vers_1) static int parse_altstr(tuple_t *tuple, cistpl_altstr_t *altstr) { u_char *p, *q; - + p = (u_char *)tuple->TupleData; q = p + tuple->TupleDataLen; - + return parse_strings(p, q, CISTPL_MAX_ALTSTR_STRINGS, altstr->str, altstr->ofs, &altstr->ns); } @@ -793,7 +805,8 @@ static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec) q = p + tuple->TupleDataLen; for (nid = 0; nid < CISTPL_MAX_DEVICES; nid++) { - if (p > q-2) break; + if (p > q-2) + break; jedec->id[nid].mfr = p[0]; jedec->id[nid].info = p[1]; p += 2; @@ -871,7 +884,7 @@ static int parse_config(tuple_t *tuple, cistpl_config_t *config) The following routines are all used to parse the nightmarish config table entries. - + ======================================================================*/ static u_char *parse_power(u_char *p, u_char *q, @@ -880,17 +893,20 @@ static u_char *parse_power(u_char *p, u_char *q, int i; u_int scale; - if (p == q) return NULL; + if (p == q) + return NULL; pwr->present = *p; pwr->flags = 0; p++; for (i = 0; i < 7; i++) if (pwr->present & (1<param[i] = POWER_CVT(*p); scale = POWER_SCALE(*p); while (*p & 0x80) { - if (++p == q) return NULL; + if (++p == q) + return NULL; if ((*p & 0x7f) < 100) pwr->param[i] += (*p & 0x7f) * scale / 100; else if (*p == 0x7d) @@ -914,24 +930,28 @@ static u_char *parse_timing(u_char *p, u_char *q, { u_char scale; - if (p == q) return NULL; + if (p == q) + return NULL; scale = *p; if ((scale & 3) != 3) { - if (++p == q) return NULL; + if (++p == q) + return NULL; timing->wait = SPEED_CVT(*p); timing->waitscale = exponent[scale & 3]; } else timing->wait = 0; scale >>= 2; if ((scale & 7) != 7) { - if (++p == q) return NULL; + if (++p == q) + return NULL; timing->ready = SPEED_CVT(*p); timing->rdyscale = exponent[scale & 7]; } else timing->ready = 0; scale >>= 3; if (scale != 7) { - if (++p == q) return NULL; + if (++p == q) + return NULL; timing->reserved = SPEED_CVT(*p); timing->rsvscale = exponent[scale]; } else @@ -946,7 +966,8 @@ static u_char *parse_io(u_char *p, u_char *q, cistpl_io_t *io) { int i, j, bsz, lsz; - if (p == q) return NULL; + if (p == q) + return NULL; io->flags = *p; if (!(*p & 0x80)) { @@ -955,24 +976,29 @@ static u_char *parse_io(u_char *p, u_char *q, cistpl_io_t *io) io->win[0].len = (1 << (io->flags & CISTPL_IO_LINES_MASK)); return p+1; } - - if (++p == q) return NULL; + + if (++p == q) + return NULL; io->nwin = (*p & 0x0f) + 1; bsz = (*p & 0x30) >> 4; - if (bsz == 3) bsz++; + if (bsz == 3) + bsz++; lsz = (*p & 0xc0) >> 6; - if (lsz == 3) lsz++; + if (lsz == 3) + lsz++; p++; - + for (i = 0; i < io->nwin; i++) { io->win[i].base = 0; io->win[i].len = 1; for (j = 0; j < bsz; j++, p++) { - if (p == q) return NULL; + if (p == q) + return NULL; io->win[i].base += *p << (j*8); } for (j = 0; j < lsz; j++, p++) { - if (p == q) return NULL; + if (p == q) + return NULL; io->win[i].len += *p << (j*8); } } @@ -986,27 +1012,32 @@ static u_char *parse_mem(u_char *p, u_char *q, cistpl_mem_t *mem) int i, j, asz, lsz, has_ha; u_int len, ca, ha; - if (p == q) return NULL; + if (p == q) + return NULL; mem->nwin = (*p & 0x07) + 1; lsz = (*p & 0x18) >> 3; asz = (*p & 0x60) >> 5; has_ha = (*p & 0x80); - if (++p == q) return NULL; - + if (++p == q) + return NULL; + for (i = 0; i < mem->nwin; i++) { len = ca = ha = 0; for (j = 0; j < lsz; j++, p++) { - if (p == q) return NULL; + if (p == q) + return NULL; len += *p << (j*8); } for (j = 0; j < asz; j++, p++) { - if (p == q) return NULL; + if (p == q) + return NULL; ca += *p << (j*8); } if (has_ha) for (j = 0; j < asz; j++, p++) { - if (p == q) return NULL; + if (p == q) + return NULL; ha += *p << (j*8); } mem->win[i].len = len << 8; @@ -1095,7 +1126,7 @@ static int parse_cftable_entry(tuple_t *tuple, entry->timing.ready = 0; entry->timing.reserved = 0; } - + /* I/O window options */ if (features & 0x08) { p = parse_io(p, q, &entry->io); @@ -1103,7 +1134,7 @@ static int parse_cftable_entry(tuple_t *tuple, return -EINVAL; } else entry->io.nwin = 0; - + /* Interrupt options */ if (features & 0x10) { p = parse_irq(p, q, &entry->irq); @@ -1153,7 +1184,7 @@ static int parse_cftable_entry(tuple_t *tuple, } entry->subtuples = q-p; - + return 0; } @@ -1176,7 +1207,7 @@ static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar) static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config) { u_char *p; - + p = (u_char *)tuple->TupleData; if ((*p != 3) || (tuple->TupleDataLen < 6)) return -EINVAL; @@ -1231,7 +1262,7 @@ static int parse_cftable_entry_cb(tuple_t *tuple, entry->io = *p; p++; } else entry->io = 0; - + /* Interrupt options */ if (features & 0x10) { p = parse_irq(p, q, &entry->irq); @@ -1264,7 +1295,7 @@ static int parse_cftable_entry_cb(tuple_t *tuple, } entry->subtuples = q-p; - + return 0; } @@ -1281,7 +1312,8 @@ static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo) q = p + tuple->TupleDataLen; for (n = 0; n < CISTPL_MAX_DEVICES; n++) { - if (p > q-6) break; + if (p > q-6) + break; geo->geo[n].buswidth = p[0]; geo->geo[n].erase_block = 1 << (p[1]-1); geo->geo[n].read_block = 1 << (p[2]-1); @@ -1302,13 +1334,13 @@ static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2) if (tuple->TupleDataLen < 10) return -EINVAL; - + p = tuple->TupleData; q = p + tuple->TupleDataLen; v2->vers = p[0]; v2->comply = p[1]; - v2->dindex = get_unaligned_le16(p +2 ); + v2->dindex = get_unaligned_le16(p + 2); v2->vspec8 = p[6]; v2->vspec9 = p[7]; v2->nhdr = p[8]; @@ -1322,7 +1354,7 @@ static int parse_org(tuple_t *tuple, cistpl_org_t *org) { u_char *p, *q; int i; - + p = tuple->TupleData; q = p + tuple->TupleDataLen; if (p == q) @@ -1332,7 +1364,8 @@ static int parse_org(tuple_t *tuple, cistpl_org_t *org) return -EINVAL; for (i = 0; i < 30; i++) { org->desc[i] = *p; - if (*p == '\0') break; + if (*p == '\0') + break; if (++p == q) return -EINVAL; } @@ -1363,7 +1396,7 @@ static int parse_format(tuple_t *tuple, cistpl_format_t *fmt) int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse) { int ret = 0; - + if (tuple->TupleDataLen > tuple->TupleDataMax) return -EINVAL; switch (tuple->TupleCode) { @@ -1448,7 +1481,7 @@ EXPORT_SYMBOL(pcmcia_parse_tuple); /*====================================================================== This is used internally by Card Services to look up CIS stuff. - + ======================================================================*/ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse) @@ -1550,7 +1583,7 @@ EXPORT_SYMBOL(pccard_loop_tuple); checks include making sure several critical tuples are present and valid; seeing if the total number of tuples is reasonable; and looking for tuples that use reserved codes. - + ======================================================================*/ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info) diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 790af87a922fc6e541f5ab2bb02d2b2f315388d9..6d6f82b38a68c9ffaf341504a3dbdbac882a5496 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -135,7 +135,7 @@ int pcmcia_socket_dev_resume(struct device *dev) EXPORT_SYMBOL(pcmcia_socket_dev_resume); -struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt) +struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt) { struct device *dev = get_device(&skt->dev); if (!dev) @@ -145,7 +145,7 @@ struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt) put_device(&skt->dev); return NULL; } - return (skt); + return skt; } EXPORT_SYMBOL(pcmcia_get_socket); @@ -297,7 +297,7 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket) EXPORT_SYMBOL(pcmcia_unregister_socket); -struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr) +struct pcmcia_socket *pcmcia_get_socket_by_nr(unsigned int nr) { struct pcmcia_socket *s; @@ -736,7 +736,7 @@ EXPORT_SYMBOL(pcmcia_parse_events); /* register pcmcia_callback */ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) { - int ret = 0; + int ret = 0; /* s->skt_mutex also protects s->callback */ mutex_lock(&s->skt_mutex); @@ -848,7 +848,7 @@ EXPORT_SYMBOL(pcmcia_suspend_card); int pcmcia_resume_card(struct pcmcia_socket *skt) { int ret; - + dev_dbg(&skt->dev, "waking up socket\n"); mutex_lock(&skt->skt_mutex); @@ -876,7 +876,7 @@ EXPORT_SYMBOL(pcmcia_resume_card); int pcmcia_eject_card(struct pcmcia_socket *skt) { int ret; - + dev_dbg(&skt->dev, "user eject request\n"); mutex_lock(&skt->skt_mutex); diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 05893d41dd418d19dde7847da6f33c7926b2b966..1a4a3c49cc15c71fe9db9ab07f61fd4cdff194ad 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -57,7 +57,7 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv) "function\n", p_drv->drv.name); while (did && did->match_flags) { - for (i=0; i<4; i++) { + for (i = 0; i < 4; i++) { if (!did->prod_id[i]) continue; @@ -105,7 +105,7 @@ pcmcia_store_new_id(struct device_driver *driver, const char *buf, size_t count) __u16 match_flags, manf_id, card_id; __u8 func_id, function, device_no; __u32 prod_id_hash[4] = {0, 0, 0, 0}; - int fields=0; + int fields = 0; int retval = 0; fields = sscanf(buf, "%hx %hx %hx %hhx %hhx %hhx %x %x %x %x", @@ -214,7 +214,7 @@ EXPORT_SYMBOL(pcmcia_unregister_driver); /* pcmcia_device handling */ -struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev) +struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev) { struct device *tmp_dev; tmp_dev = get_device(&p_dev->dev); @@ -258,7 +258,7 @@ static void pcmcia_add_device_later(struct pcmcia_socket *s, int mfc) return; } -static int pcmcia_device_probe(struct device * dev) +static int pcmcia_device_probe(struct device *dev) { struct pcmcia_device *p_dev; struct pcmcia_driver *p_drv; @@ -325,7 +325,7 @@ put_module: put_dev: if (ret) put_device(dev); - return (ret); + return ret; } @@ -354,7 +354,7 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le spin_lock_irqsave(&pcmcia_dev_list_lock, flags); list_del(&p_dev->socket_device_list); - p_dev->_removed=1; + p_dev->_removed = 1; spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); dev_dbg(&p_dev->dev, "unregistering device\n"); @@ -364,7 +364,7 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le return; } -static int pcmcia_device_remove(struct device * dev) +static int pcmcia_device_remove(struct device *dev) { struct pcmcia_device *p_dev; struct pcmcia_driver *p_drv; @@ -391,7 +391,7 @@ static int pcmcia_device_remove(struct device * dev) return 0; if (p_drv->remove) - p_drv->remove(p_dev); + p_drv->remove(p_dev); p_dev->dev_node = NULL; @@ -499,7 +499,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) */ static DEFINE_MUTEX(device_add_lock); -struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) +struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) { struct pcmcia_device *p_dev, *tmp_dev; unsigned long flags; @@ -545,8 +545,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f * Note that this is serialized by the device_add_lock, so that * only one such struct will be created. */ - list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) - if (p_dev->func == tmp_dev->func) { + list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) + if (p_dev->func == tmp_dev->func) { p_dev->function_config = tmp_dev->function_config; p_dev->io = tmp_dev->io; p_dev->irq = tmp_dev->irq; @@ -627,10 +627,10 @@ static int pcmcia_card_add(struct pcmcia_socket *s) no_funcs = 1; s->functions = no_funcs; - for (i=0; i < no_funcs; i++) + for (i = 0; i < no_funcs; i++) pcmcia_device_add(s, i); - return (ret); + return ret; } @@ -756,7 +756,7 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) release: release_firmware(fw); - return (ret); + return ret; } #else /* !CONFIG_PCMCIA_LOAD_CIS */ @@ -852,7 +852,7 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, if (did->match_flags & PCMCIA_DEV_ID_MATCH_ANONYMOUS) { int i; - for (i=0; i<4; i++) + for (i = 0; i < 4; i++) if (dev->prod_id[i]) return 0; if (dev->has_manf_id || dev->has_card_id || dev->has_func_id) @@ -865,9 +865,10 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, } -static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { - struct pcmcia_device * p_dev = to_pcmcia_dev(dev); - struct pcmcia_driver * p_drv = to_pcmcia_drv(drv); +static int pcmcia_bus_match(struct device *dev, struct device_driver *drv) +{ + struct pcmcia_device *p_dev = to_pcmcia_dev(dev); + struct pcmcia_driver *p_drv = to_pcmcia_drv(drv); struct pcmcia_device_id *did = p_drv->id_table; struct pcmcia_dynid *dynid; @@ -917,7 +918,7 @@ static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env) p_dev = to_pcmcia_dev(dev); /* calculate hashes */ - for (i=0; i<4; i++) { + for (i = 0; i < 4; i++) { if (!p_dev->prod_id[i]) continue; hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i])); @@ -984,14 +985,14 @@ static void runtime_resume(struct device *dev) static ssize_t field##_show (struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct pcmcia_device *p_dev = to_pcmcia_dev(dev); \ - return p_dev->test ? sprintf (buf, format, p_dev->field) : -ENODEV; \ + return p_dev->test ? sprintf(buf, format, p_dev->field) : -ENODEV; \ } #define pcmcia_device_stringattr(name, field) \ static ssize_t name##_show (struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct pcmcia_device *p_dev = to_pcmcia_dev(dev); \ - return p_dev->field ? sprintf (buf, "%s\n", p_dev->field) : -ENODEV; \ + return p_dev->field ? sprintf(buf, "%s\n", p_dev->field) : -ENODEV; \ } pcmcia_device_attr(func, socket, "0x%02x\n"); @@ -1020,8 +1021,8 @@ static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute struct pcmcia_device *p_dev = to_pcmcia_dev(dev); int ret = 0; - if (!count) - return -EINVAL; + if (!count) + return -EINVAL; if ((!p_dev->suspended) && !strncmp(buf, "off", 3)) ret = runtime_suspend(dev); @@ -1039,10 +1040,11 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, u32 hash[4] = { 0, 0, 0, 0}; /* calculate hashes */ - for (i=0; i<4; i++) { + for (i = 0; i < 4; i++) { if (!p_dev->prod_id[i]) continue; - hash[i] = crc32(0,p_dev->prod_id[i],strlen(p_dev->prod_id[i])); + hash[i] = crc32(0, p_dev->prod_id[i], + strlen(p_dev->prod_id[i])); } return sprintf(buf, "pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X" "pa%08Xpb%08Xpc%08Xpd%08X\n", @@ -1091,7 +1093,7 @@ static struct device_attribute pcmcia_dev_attrs[] = { /* PM support, also needed for reset */ -static int pcmcia_dev_suspend(struct device * dev, pm_message_t state) +static int pcmcia_dev_suspend(struct device *dev, pm_message_t state) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); struct pcmcia_driver *p_drv = NULL; @@ -1131,10 +1133,10 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state) } -static int pcmcia_dev_resume(struct device * dev) +static int pcmcia_dev_resume(struct device *dev) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); - struct pcmcia_driver *p_drv = NULL; + struct pcmcia_driver *p_drv = NULL; int ret = 0; if (!p_dev->suspended) @@ -1211,7 +1213,7 @@ static int pcmcia_bus_suspend(struct pcmcia_socket *skt) /*====================================================================== The card status event handler. - + ======================================================================*/ /* Normally, the event is passed to individual drivers after @@ -1264,7 +1266,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) } /* ds_event */ -struct pcmcia_device * pcmcia_dev_present(struct pcmcia_device *_p_dev) +struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev) { struct pcmcia_device *p_dev; struct pcmcia_device *ret = NULL; @@ -1329,7 +1331,7 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev, if (ret) { dev_printk(KERN_ERR, dev, "PCMCIA registration failed\n"); pcmcia_put_socket(socket); - return (ret); + return ret; } return 0; @@ -1400,7 +1402,7 @@ static int __init init_pcmcia_bus(void) return 0; } -fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that +fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that * pcmcia_socket_class is already registered */ diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index c4d7908fa37f1974f413627cd3b274512ec872ae..f73fd5beaa372f05ddd64a8621b6c1786e64c366 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -88,12 +88,12 @@ static struct pcmcia_driver *get_pcmcia_driver(dev_info_t *dev_info) p_drv = container_of(drv, struct pcmcia_driver, drv); - return (p_drv); + return p_drv; } #ifdef CONFIG_PROC_FS -static struct proc_dir_entry *proc_pccard = NULL; +static struct proc_dir_entry *proc_pccard; static int proc_read_drivers_callback(struct device_driver *driver, void *_m) { @@ -158,7 +158,8 @@ static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) #else -static inline int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) { +static inline int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) +{ return 0; } @@ -195,7 +196,7 @@ static int pcmcia_adjust_resource_info(adjust_t *adj) begin = adj->resource.memory.Base; end = adj->resource.memory.Base + adj->resource.memory.Size - 1; if (s->resource_ops->add_mem) - ret =s->resource_ops->add_mem(s, adj->Action, begin, end); + ret = s->resource_ops->add_mem(s, adj->Action, begin, end); case RES_IO_RANGE: begin = adj->resource.io.BasePort; end = adj->resource.io.BasePort + adj->resource.io.NumPorts - 1; @@ -215,7 +216,7 @@ static int pcmcia_adjust_resource_info(adjust_t *adj) } up_read(&pcmcia_socket_list_rwsem); - return (ret); + return ret; } @@ -490,7 +491,7 @@ static int bind_request(struct pcmcia_socket *s, bind_info_t *bind_info) } spin_lock_irqsave(&pcmcia_dev_list_lock, flags); - list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { + list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { if (p_dev->func == bind_info->function) { if ((p_dev->dev.driver == &p_drv->drv)) { if (p_dev->cardmgr) { @@ -558,7 +559,7 @@ rescan: err_put: pcmcia_put_socket(s); - return (ret); + return ret; } /* bind_request */ #ifdef CONFIG_CARDBUS @@ -655,7 +656,7 @@ static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int err_put: pcmcia_put_dev(p_dev); - return (ret); + return ret; } /* get_device_info */ @@ -664,7 +665,7 @@ static int ds_open(struct inode *inode, struct file *file) socket_t i = iminor(inode); struct pcmcia_socket *s; user_info_t *user; - static int warning_printed = 0; + static int warning_printed; int ret = 0; pr_debug("ds_open(socket %d)\n", i); @@ -738,12 +739,13 @@ static int ds_release(struct inode *inode, struct file *file) s = user->socket; /* Unlink user data structure */ - if ((file->f_flags & O_ACCMODE) != O_RDONLY) { + if ((file->f_flags & O_ACCMODE) != O_RDONLY) s->pcmcia_state.busy = 0; - } + file->private_data = NULL; for (link = &s->user; *link; link = &(*link)->next) - if (*link == user) break; + if (*link == user) + break; if (link == NULL) goto out; *link = user->next; @@ -774,7 +776,7 @@ static ssize_t ds_read(struct file *file, char __user *buf, s = user->socket; if (s->pcmcia_state.dead) - return -EIO; + return -EIO; ret = wait_event_interruptible(s->queue, !queue_empty(user)); if (ret == 0) @@ -824,7 +826,7 @@ static u_int ds_poll(struct file *file, poll_table *wait) /*====================================================================*/ -static int ds_ioctl(struct inode * inode, struct file * file, +static int ds_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg) { struct pcmcia_socket *s; @@ -842,10 +844,11 @@ static int ds_ioctl(struct inode * inode, struct file * file, s = user->socket; if (s->pcmcia_state.dead) - return -EIO; + return -EIO; size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; - if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL; + if (size > sizeof(ds_ioctl_arg_t)) + return -EINVAL; /* Permission check */ if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN)) @@ -1024,8 +1027,8 @@ static int ds_ioctl(struct inode * inode, struct file * file, } if (cmd & IOC_OUT) { - if (__copy_to_user(uarg, (char *)buf, size)) - err = -EFAULT; + if (__copy_to_user(uarg, (char *)buf, size)) + err = -EFAULT; } free_out: @@ -1045,7 +1048,8 @@ static const struct file_operations ds_fops = { .poll = ds_poll, }; -void __init pcmcia_setup_ioctl(void) { +void __init pcmcia_setup_ioctl(void) +{ int i; /* Set up character device for user mode clients */ @@ -1064,7 +1068,8 @@ void __init pcmcia_setup_ioctl(void) { } -void __exit pcmcia_cleanup_ioctl(void) { +void __exit pcmcia_cleanup_ioctl(void) +{ #ifdef CONFIG_PROC_FS if (proc_pccard) { remove_proc_entry("drivers", proc_pccard); diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index a8bf8c1b45ede688ab3613eeaf570356d0baa795..d5db95644b64f69cc5dc61fc47f11a7abc21bc71 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -33,7 +33,7 @@ /* Access speed for IO windows */ -static int io_speed = 0; +static int io_speed; module_param(io_speed, int, 0444); @@ -62,7 +62,8 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, num, align); align = 0; } else - while (align && (align < num)) align <<= 1; + while (align && (align < num)) + align <<= 1; } if (*base & ~(align-1)) { dev_dbg(&s->dev, "odd IO request: base %#x align %#x\n", @@ -338,7 +339,7 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) struct pcmcia_socket *s = p_dev->socket; config_t *c = p_dev->function_config; - if (!p_dev->_io ) + if (!p_dev->_io) return -EINVAL; p_dev->_io = 0; @@ -362,7 +363,7 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) { struct pcmcia_socket *s = p_dev->socket; - config_t *c= p_dev->function_config; + config_t *c = p_dev->function_config; if (!p_dev->_irq) return -EINVAL; @@ -383,9 +384,8 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) s->irq.AssignedIRQ = 0; } - if (req->Handler) { + if (req->Handler) free_irq(req->AssignedIRQ, p_dev->priv); - } #ifdef CONFIG_PCMCIA_PROBE pcmcia_used_irq[req->AssignedIRQ]--; @@ -656,7 +656,8 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) type = IRQF_SHARED; else if (req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) type = IRQF_SHARED; - else printk(KERN_WARNING "pcmcia: Driver needs updating to support IRQ sharing.\n"); + else + printk(KERN_WARNING "pcmcia: Driver needs updating to support IRQ sharing.\n"); #ifdef CONFIG_PCMCIA_PROBE @@ -788,7 +789,8 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha /* Allocate system memory window */ for (w = 0; w < MAX_WIN; w++) - if (!(s->state & SOCKET_WIN_REQ(w))) break; + if (!(s->state & SOCKET_WIN_REQ(w))) + break; if (w == MAX_WIN) { dev_dbg(&s->dev, "all windows are used already\n"); return -EINVAL; @@ -826,18 +828,19 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha s->state |= SOCKET_WIN_REQ(w); /* Return window handle */ - if (s->features & SS_CAP_STATIC_MAP) { + if (s->features & SS_CAP_STATIC_MAP) req->Base = win->static_start; - } else { + else req->Base = win->res->start; - } + *wh = w + 1; return 0; } /* pcmcia_request_window */ EXPORT_SYMBOL(pcmcia_request_window); -void pcmcia_disable_device(struct pcmcia_device *p_dev) { +void pcmcia_disable_device(struct pcmcia_device *p_dev) +{ pcmcia_release_configuration(p_dev); pcmcia_release_io(p_dev, &p_dev->io); pcmcia_release_irq(p_dev, &p_dev->irq); @@ -970,7 +973,7 @@ int pcmcia_loop_tuple(struct pcmcia_device *p_dev, cisdata_t code, return pccard_loop_tuple(p_dev->socket, p_dev->func, code, NULL, &loop, pcmcia_do_loop_tuple); -}; +} EXPORT_SYMBOL(pcmcia_loop_tuple); @@ -1000,7 +1003,7 @@ static int pcmcia_do_get_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, } else dev_dbg(&p_dev->dev, "do_get_tuple: out of memory\n"); return 0; -}; +} /** * pcmcia_get_tuple() - get first tuple from CIS @@ -1024,7 +1027,7 @@ size_t pcmcia_get_tuple(struct pcmcia_device *p_dev, cisdata_t code, pcmcia_loop_tuple(p_dev, code, pcmcia_do_get_tuple, &get); return get.len; -}; +} EXPORT_SYMBOL(pcmcia_get_tuple); @@ -1057,7 +1060,7 @@ static int pcmcia_do_get_mac(struct pcmcia_device *p_dev, tuple_t *tuple, for (i = 0; i < 6; i++) dev->dev_addr[i] = tuple->TupleData[i+2]; return 0; -}; +} /** * pcmcia_get_mac_from_cis() - read out MAC address from CISTPL_FUNCE @@ -1071,6 +1074,6 @@ static int pcmcia_do_get_mac(struct pcmcia_device *p_dev, tuple_t *tuple, int pcmcia_get_mac_from_cis(struct pcmcia_device *p_dev, struct net_device *dev) { return pcmcia_loop_tuple(p_dev, CISTPL_FUNCE, pcmcia_do_get_mac, dev); -}; +} EXPORT_SYMBOL(pcmcia_get_mac_from_cis); diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index 84dde7768ad54cd6c8d1fbd0899afd2c38700a95..da346eb7e77eba91474027329794c94ceb8cd2b7 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c @@ -214,7 +214,8 @@ static void pxa2xx_configure_sockets(struct device *dev) MECR |= MECR_CIT; /* Set MECR:NOS (Number Of Sockets) */ - if ((ops->first + ops->nr) > 1 || machine_is_viper()) + if ((ops->first + ops->nr) > 1 || + machine_is_viper() || machine_is_arcom_zeus()) MECR |= MECR_NOS; else MECR &= ~MECR_NOS; @@ -252,6 +253,7 @@ int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt) return soc_pcmcia_add_one(skt); } +EXPORT_SYMBOL(pxa2xx_drv_pcmcia_add_one); void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops) { @@ -261,19 +263,19 @@ void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops) ops->frequency_change = pxa2xx_pcmcia_frequency_change; #endif } +EXPORT_SYMBOL(pxa2xx_drv_pcmcia_ops); -int __pxa2xx_drv_pcmcia_probe(struct device *dev) +static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev) { int i, ret = 0; struct pcmcia_low_level *ops; struct skt_dev_info *sinfo; struct soc_pcmcia_socket *skt; - if (!dev || !dev->platform_data) + ops = (struct pcmcia_low_level *)dev->dev.platform_data; + if (!ops) return -ENODEV; - ops = (struct pcmcia_low_level *)dev->platform_data; - pxa2xx_drv_pcmcia_ops(ops); sinfo = kzalloc(SKT_DEV_INFO_SIZE(ops->nr), GFP_KERNEL); @@ -308,13 +310,6 @@ int __pxa2xx_drv_pcmcia_probe(struct device *dev) return ret; } -EXPORT_SYMBOL(__pxa2xx_drv_pcmcia_probe); - - -static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev) -{ - return __pxa2xx_drv_pcmcia_probe(&dev->dev); -} static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev) { diff --git a/drivers/pcmcia/pxa2xx_base.h b/drivers/pcmcia/pxa2xx_base.h index cb5efaec886f2c807849d2dc467aa71b631c6b1a..bb62ea87b8f9c55158027c1716442d5593ab0772 100644 --- a/drivers/pcmcia/pxa2xx_base.h +++ b/drivers/pcmcia/pxa2xx_base.h @@ -1,6 +1,3 @@ -/* temporary measure */ -extern int __pxa2xx_drv_pcmcia_probe(struct device *); - int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt); void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops); diff --git a/drivers/pcmcia/pxa2xx_palmtc.c b/drivers/pcmcia/pxa2xx_palmtc.c index 3a8993ed562120f7da811620c770d98f23430831..459a232d66be2caad82155d712cb97c62a7b01a6 100644 --- a/drivers/pcmcia/pxa2xx_palmtc.c +++ b/drivers/pcmcia/pxa2xx_palmtc.c @@ -67,7 +67,7 @@ static int palmtc_pcmcia_hw_init(struct soc_pcmcia_socket *skt) if (ret) goto err7; - skt->irq = IRQ_GPIO(GPIO_NR_PALMTC_PCMCIA_READY); + skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMTC_PCMCIA_READY); return 0; err7: diff --git a/drivers/pcmcia/pxa2xx_stargate2.c b/drivers/pcmcia/pxa2xx_stargate2.c index 490749ea677faed056b3db7e8fc2115c8967bba4..d08802fe35f9a993cdd50cec2410543d83aa29ad 100644 --- a/drivers/pcmcia/pxa2xx_stargate2.c +++ b/drivers/pcmcia/pxa2xx_stargate2.c @@ -40,7 +40,7 @@ static struct pcmcia_irqs irqs[] = { static int sg2_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { - skt->irq = IRQ_GPIO(SG2_S0_GPIO_READY); + skt->socket.pci_irq = IRQ_GPIO(SG2_S0_GPIO_READY); return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); } diff --git a/drivers/pcmcia/pxa2xx_viper.c b/drivers/pcmcia/pxa2xx_viper.c index 27be2e154df2a92782dbfafa48598c00dc3cd72f..a51f2077644a5f80cdb4e9688947e046ce42a0e7 100644 --- a/drivers/pcmcia/pxa2xx_viper.c +++ b/drivers/pcmcia/pxa2xx_viper.c @@ -1,9 +1,8 @@ /* - * VIPER PCMCIA support + * Viper/Zeus PCMCIA support * Copyright 2004 Arcom Control Systems * * Maintained by Marc Zyngier - * * * Based on: * iPAQ h2200 PCMCIA support @@ -26,37 +25,47 @@ #include -#include -#include +#include #include "soc_common.h" #include "pxa2xx_base.h" +static struct platform_device *arcom_pcmcia_dev; + static struct pcmcia_irqs irqs[] = { - { 0, gpio_to_irq(VIPER_CF_CD_GPIO), "PCMCIA_CD" } + { + .sock = 0, + .str = "PCMCIA_CD", + }, }; +static inline struct arcom_pcmcia_pdata *viper_get_pdata(void) +{ + return arcom_pcmcia_dev->dev.platform_data; +} + static int viper_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { + struct arcom_pcmcia_pdata *pdata = viper_get_pdata(); unsigned long flags; - skt->socket.pci_irq = gpio_to_irq(VIPER_CF_RDY_GPIO); + skt->socket.pci_irq = gpio_to_irq(pdata->rdy_gpio); + irqs[0].irq = gpio_to_irq(pdata->cd_gpio); - if (gpio_request(VIPER_CF_CD_GPIO, "CF detect")) + if (gpio_request(pdata->cd_gpio, "CF detect")) goto err_request_cd; - if (gpio_request(VIPER_CF_RDY_GPIO, "CF ready")) + if (gpio_request(pdata->rdy_gpio, "CF ready")) goto err_request_rdy; - if (gpio_request(VIPER_CF_POWER_GPIO, "CF power")) + if (gpio_request(pdata->pwr_gpio, "CF power")) goto err_request_pwr; local_irq_save(flags); - /* GPIO 82 is the CF power enable line. initially off */ - if (gpio_direction_output(VIPER_CF_POWER_GPIO, 0) || - gpio_direction_input(VIPER_CF_CD_GPIO) || - gpio_direction_input(VIPER_CF_RDY_GPIO)) { + if (gpio_direction_output(pdata->pwr_gpio, 0) || + gpio_direction_input(pdata->cd_gpio) || + gpio_direction_input(pdata->rdy_gpio)) { local_irq_restore(flags); goto err_dir; } @@ -66,13 +75,13 @@ static int viper_pcmcia_hw_init(struct soc_pcmcia_socket *skt) return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); err_dir: - gpio_free(VIPER_CF_POWER_GPIO); + gpio_free(pdata->pwr_gpio); err_request_pwr: - gpio_free(VIPER_CF_RDY_GPIO); + gpio_free(pdata->rdy_gpio); err_request_rdy: - gpio_free(VIPER_CF_CD_GPIO); + gpio_free(pdata->cd_gpio); err_request_cd: - printk(KERN_ERR "viper: Failed to setup PCMCIA GPIOs\n"); + dev_err(&arcom_pcmcia_dev->dev, "Failed to setup PCMCIA GPIOs\n"); return -1; } @@ -81,17 +90,21 @@ err_request_cd: */ static void viper_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) { + struct arcom_pcmcia_pdata *pdata = viper_get_pdata(); + soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); - gpio_free(VIPER_CF_POWER_GPIO); - gpio_free(VIPER_CF_RDY_GPIO); - gpio_free(VIPER_CF_CD_GPIO); + gpio_free(pdata->pwr_gpio); + gpio_free(pdata->rdy_gpio); + gpio_free(pdata->cd_gpio); } static void viper_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - state->detect = gpio_get_value(VIPER_CF_CD_GPIO) ? 0 : 1; - state->ready = gpio_get_value(VIPER_CF_RDY_GPIO) ? 1 : 0; + struct arcom_pcmcia_pdata *pdata = viper_get_pdata(); + + state->detect = !gpio_get_value(pdata->cd_gpio); + state->ready = !!gpio_get_value(pdata->rdy_gpio); state->bvd1 = 1; state->bvd2 = 1; state->wrprot = 0; @@ -102,20 +115,21 @@ static void viper_pcmcia_socket_state(struct soc_pcmcia_socket *skt, static int viper_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) { + struct arcom_pcmcia_pdata *pdata = viper_get_pdata(); + /* Silently ignore Vpp, output enable, speaker enable. */ - viper_cf_rst(state->flags & SS_RESET); + pdata->reset(state->flags & SS_RESET); /* Apply socket voltage */ switch (state->Vcc) { case 0: - gpio_set_value(VIPER_CF_POWER_GPIO, 0); + gpio_set_value(pdata->pwr_gpio, 0); break; case 33: - gpio_set_value(VIPER_CF_POWER_GPIO, 1); + gpio_set_value(pdata->pwr_gpio, 1); break; default: - printk(KERN_ERR "%s: Unsupported Vcc:%d\n", - __func__, state->Vcc); + dev_err(&arcom_pcmcia_dev->dev, "Unsupported Vcc:%d\n", state->Vcc); return -1; } @@ -130,7 +144,7 @@ static void viper_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) { } -static struct pcmcia_low_level viper_pcmcia_ops __initdata = { +static struct pcmcia_low_level viper_pcmcia_ops = { .owner = THIS_MODULE, .hw_init = viper_pcmcia_hw_init, .hw_shutdown = viper_pcmcia_hw_shutdown, @@ -143,17 +157,25 @@ static struct pcmcia_low_level viper_pcmcia_ops __initdata = { static struct platform_device *viper_pcmcia_device; -static int __init viper_pcmcia_init(void) +static int viper_pcmcia_probe(struct platform_device *pdev) { int ret; - if (!machine_is_viper()) - return -ENODEV; + /* I can't imagine more than one device, but you never know... */ + if (arcom_pcmcia_dev) + return -EEXIST; + + if (!pdev->dev.platform_data) + return -EINVAL; viper_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); if (!viper_pcmcia_device) return -ENOMEM; + arcom_pcmcia_dev = pdev; + + viper_pcmcia_device->dev.parent = &pdev->dev; + ret = platform_device_add_data(viper_pcmcia_device, &viper_pcmcia_ops, sizeof(viper_pcmcia_ops)); @@ -161,18 +183,49 @@ static int __init viper_pcmcia_init(void) if (!ret) ret = platform_device_add(viper_pcmcia_device); - if (ret) + if (ret) { platform_device_put(viper_pcmcia_device); + arcom_pcmcia_dev = NULL; + } return ret; } -static void __exit viper_pcmcia_exit(void) +static int viper_pcmcia_remove(struct platform_device *pdev) { platform_device_unregister(viper_pcmcia_device); + arcom_pcmcia_dev = NULL; + return 0; +} + +static struct platform_device_id viper_pcmcia_id_table[] = { + { .name = "viper-pcmcia", }, + { .name = "zeus-pcmcia", }, + { }, +}; + +static struct platform_driver viper_pcmcia_driver = { + .probe = viper_pcmcia_probe, + .remove = viper_pcmcia_remove, + .driver = { + .name = "arcom-pcmcia", + .owner = THIS_MODULE, + }, + .id_table = viper_pcmcia_id_table, +}; + +static int __init viper_pcmcia_init(void) +{ + return platform_driver_register(&viper_pcmcia_driver); +} + +static void __exit viper_pcmcia_exit(void) +{ + return platform_driver_unregister(&viper_pcmcia_driver); } module_init(viper_pcmcia_init); module_exit(viper_pcmcia_exit); +MODULE_DEVICE_TABLE(platform, viper_pcmcia_id_table); MODULE_LICENSE("GPL"); diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index de0e770ce6a30ec404fb9fb1833ce793ab5d55b5..52db17263d8bd9b0b7265040c0a3747ccc7be601 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -126,16 +126,16 @@ static void pcmcia_align(void *align_data, struct resource *res, res->start = start; #ifdef CONFIG_X86 - if (res->flags & IORESOURCE_IO) { - if (start & 0x300) { - start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } - } + if (res->flags & IORESOURCE_IO) { + if (start & 0x300) { + start = (start + 0x3ff) & ~0x3ff; + res->start = start; + } + } #endif #ifdef CONFIG_M68K - if (res->flags & IORESOURCE_IO) { + if (res->flags & IORESOURCE_IO) { if ((res->start + size - 1) >= 1024) res->start = res->end; } diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 7039f3cf5b77e5650a99d090d5eabd239ff70ad8..9b0dc433a8c3a6953f223dd6160adbdc22db5b20 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -24,9 +24,9 @@ #include #include #include +#include #include -#include #include #include @@ -144,43 +144,44 @@ static int add_interval(struct resource_map *map, u_long base, u_long num) static int sub_interval(struct resource_map *map, u_long base, u_long num) { - struct resource_map *p, *q; - - for (p = map; ; p = q) { - q = p->next; - if (q == map) - break; - if ((q->base+q->num > base) && (base+num > q->base)) { - if (q->base >= base) { - if (q->base+q->num <= base+num) { - /* Delete whole block */ - p->next = q->next; - kfree(q); - /* don't advance the pointer yet */ - q = p; - } else { - /* Cut off bit from the front */ - q->num = q->base + q->num - base - num; - q->base = base + num; - } - } else if (q->base+q->num <= base+num) { - /* Cut off bit from the end */ - q->num = base - q->base; - } else { - /* Split the block into two pieces */ - p = kmalloc(sizeof(struct resource_map), GFP_KERNEL); - if (!p) { - printk(KERN_WARNING "out of memory to update resources\n"); - return -ENOMEM; + struct resource_map *p, *q; + + for (p = map; ; p = q) { + q = p->next; + if (q == map) + break; + if ((q->base+q->num > base) && (base+num > q->base)) { + if (q->base >= base) { + if (q->base+q->num <= base+num) { + /* Delete whole block */ + p->next = q->next; + kfree(q); + /* don't advance the pointer yet */ + q = p; + } else { + /* Cut off bit from the front */ + q->num = q->base + q->num - base - num; + q->base = base + num; + } + } else if (q->base+q->num <= base+num) { + /* Cut off bit from the end */ + q->num = base - q->base; + } else { + /* Split the block into two pieces */ + p = kmalloc(sizeof(struct resource_map), + GFP_KERNEL); + if (!p) { + printk(KERN_WARNING "out of memory to update resources\n"); + return -ENOMEM; + } + p->base = base+num; + p->num = q->base+q->num - p->base; + q->num = base - q->base; + p->next = q->next ; q->next = p; + } } - p->base = base+num; - p->num = q->base+q->num - p->base; - q->num = base - q->base; - p->next = q->next ; q->next = p; - } } - } - return 0; + return 0; } /*====================================================================== @@ -194,69 +195,72 @@ static int sub_interval(struct resource_map *map, u_long base, u_long num) static void do_io_probe(struct pcmcia_socket *s, unsigned int base, unsigned int num) { - struct resource *res; - struct socket_data *s_data = s->resource_data; - unsigned int i, j, bad; - int any; - u_char *b, hole, most; - - dev_printk(KERN_INFO, &s->dev, "cs: IO port probe %#x-%#x:", - base, base+num-1); - - /* First, what does a floating port look like? */ - b = kzalloc(256, GFP_KERNEL); - if (!b) { - printk("\n"); - dev_printk(KERN_ERR, &s->dev, - "do_io_probe: unable to kmalloc 256 bytes"); - return; - } - for (i = base, most = 0; i < base+num; i += 8) { - res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe"); - if (!res) - continue; - hole = inb(i); - for (j = 1; j < 8; j++) - if (inb(i+j) != hole) break; - free_region(res); - if ((j == 8) && (++b[hole] > b[most])) - most = hole; - if (b[most] == 127) break; - } - kfree(b); - - bad = any = 0; - for (i = base; i < base+num; i += 8) { - res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe"); - if (!res) - continue; - for (j = 0; j < 8; j++) - if (inb(i+j) != most) break; - free_region(res); - if (j < 8) { - if (!any) - printk(" excluding"); - if (!bad) - bad = any = i; - } else { - if (bad) { - sub_interval(&s_data->io_db, bad, i-bad); - printk(" %#x-%#x", bad, i-1); - bad = 0; - } + struct resource *res; + struct socket_data *s_data = s->resource_data; + unsigned int i, j, bad; + int any; + u_char *b, hole, most; + + dev_printk(KERN_INFO, &s->dev, "cs: IO port probe %#x-%#x:", + base, base+num-1); + + /* First, what does a floating port look like? */ + b = kzalloc(256, GFP_KERNEL); + if (!b) { + printk("\n"); + dev_printk(KERN_ERR, &s->dev, + "do_io_probe: unable to kmalloc 256 bytes"); + return; } - } - if (bad) { - if ((num > 16) && (bad == base) && (i == base+num)) { - printk(" nothing: probe failed.\n"); - return; - } else { - sub_interval(&s_data->io_db, bad, i-bad); - printk(" %#x-%#x", bad, i-1); + for (i = base, most = 0; i < base+num; i += 8) { + res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA ioprobe"); + if (!res) + continue; + hole = inb(i); + for (j = 1; j < 8; j++) + if (inb(i+j) != hole) + break; + free_region(res); + if ((j == 8) && (++b[hole] > b[most])) + most = hole; + if (b[most] == 127) + break; } - } + kfree(b); - printk(any ? "\n" : " clean.\n"); + bad = any = 0; + for (i = base; i < base+num; i += 8) { + res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA ioprobe"); + if (!res) + continue; + for (j = 0; j < 8; j++) + if (inb(i+j) != most) + break; + free_region(res); + if (j < 8) { + if (!any) + printk(" excluding"); + if (!bad) + bad = any = i; + } else { + if (bad) { + sub_interval(&s_data->io_db, bad, i-bad); + printk(" %#x-%#x", bad, i-1); + bad = 0; + } + } + } + if (bad) { + if ((num > 16) && (bad == base) && (i == base+num)) { + printk(" nothing: probe failed.\n"); + return; + } else { + sub_interval(&s_data->io_db, bad, i-bad); + printk(" %#x-%#x", bad, i-1); + } + } + + printk(any ? "\n" : " clean.\n"); } #endif @@ -327,8 +331,9 @@ cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size) unsigned int info1, info2; int ret = 0; - res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe"); - res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe"); + res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "PCMCIA memprobe"); + res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, + "PCMCIA memprobe"); if (res1 && res2) { ret = readable(s, res1, &info1); @@ -347,8 +352,9 @@ checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size) struct resource *res1, *res2; int a = -1, b = -1; - res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe"); - res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe"); + res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "PCMCIA memprobe"); + res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, + "PCMCIA memprobe"); if (res1 && res2) { a = checksum(s, res1); @@ -371,42 +377,43 @@ checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size) static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s) { - struct socket_data *s_data = s->resource_data; - u_long i, j, bad, fail, step; - - dev_printk(KERN_INFO, &s->dev, "cs: memory probe 0x%06lx-0x%06lx:", - base, base+num-1); - bad = fail = 0; - step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff); - /* don't allow too large steps */ - if (step > 0x800000) - step = 0x800000; - /* cis_readable wants to map 2x map_size */ - if (step < 2 * s->map_size) - step = 2 * s->map_size; - for (i = j = base; i < base+num; i = j + step) { - if (!fail) { - for (j = i; j < base+num; j += step) { - if (cis_readable(s, j, step)) - break; - } - fail = ((i == base) && (j == base+num)); - } - if (fail) { - for (j = i; j < base+num; j += 2*step) - if (checksum_match(s, j, step) && - checksum_match(s, j + step, step)) - break; - } - if (i != j) { - if (!bad) printk(" excluding"); - printk(" %#05lx-%#05lx", i, j-1); - sub_interval(&s_data->mem_db, i, j-i); - bad += j-i; + struct socket_data *s_data = s->resource_data; + u_long i, j, bad, fail, step; + + dev_printk(KERN_INFO, &s->dev, "cs: memory probe 0x%06lx-0x%06lx:", + base, base+num-1); + bad = fail = 0; + step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff); + /* don't allow too large steps */ + if (step > 0x800000) + step = 0x800000; + /* cis_readable wants to map 2x map_size */ + if (step < 2 * s->map_size) + step = 2 * s->map_size; + for (i = j = base; i < base+num; i = j + step) { + if (!fail) { + for (j = i; j < base+num; j += step) { + if (cis_readable(s, j, step)) + break; + } + fail = ((i == base) && (j == base+num)); + } + if (fail) { + for (j = i; j < base+num; j += 2*step) + if (checksum_match(s, j, step) && + checksum_match(s, j + step, step)) + break; + } + if (i != j) { + if (!bad) + printk(" excluding"); + printk(" %#05lx-%#05lx", i, j-1); + sub_interval(&s_data->mem_db, i, j-i); + bad += j-i; + } } - } - printk(bad ? "\n" : " clean.\n"); - return (num - bad); + printk(bad ? "\n" : " clean.\n"); + return num - bad; } #ifdef CONFIG_PCMCIA_PROBE @@ -656,7 +663,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num, return res; } -static struct resource * nonstatic_find_mem_region(u_long base, u_long num, +static struct resource *nonstatic_find_mem_region(u_long base, u_long num, u_long align, int low, struct pcmcia_socket *s) { struct resource *res = make_resource(0, num, IORESOURCE_MEM, dev_name(&s->dev)); @@ -794,7 +801,7 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s) return -EINVAL; #endif - for (i=0; i < PCI_BUS_NUM_RESOURCES; i++) { + for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { res = s->cb_dev->bus->resource[i]; if (!res) continue; @@ -908,14 +915,14 @@ static ssize_t show_io_db(struct device *dev, for (p = data->io_db.next; p != &data->io_db; p = p->next) { if (ret > (PAGE_SIZE - 10)) continue; - ret += snprintf (&buf[ret], (PAGE_SIZE - ret - 1), - "0x%08lx - 0x%08lx\n", - ((unsigned long) p->base), - ((unsigned long) p->base + p->num - 1)); + ret += snprintf(&buf[ret], (PAGE_SIZE - ret - 1), + "0x%08lx - 0x%08lx\n", + ((unsigned long) p->base), + ((unsigned long) p->base + p->num - 1)); } mutex_unlock(&rsrc_mutex); - return (ret); + return ret; } static ssize_t store_io_db(struct device *dev, @@ -927,12 +934,13 @@ static ssize_t store_io_db(struct device *dev, unsigned int add = ADD_MANAGED_RESOURCE; ssize_t ret = 0; - ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr); + ret = sscanf(buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr); if (ret != 2) { - ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr); + ret = sscanf(buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr); add = REMOVE_MANAGED_RESOURCE; if (ret != 2) { - ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr); + ret = sscanf(buf, "0x%lx - 0x%lx", &start_addr, + &end_addr); add = ADD_MANAGED_RESOURCE; if (ret != 2) return -EINVAL; @@ -963,14 +971,14 @@ static ssize_t show_mem_db(struct device *dev, for (p = data->mem_db.next; p != &data->mem_db; p = p->next) { if (ret > (PAGE_SIZE - 10)) continue; - ret += snprintf (&buf[ret], (PAGE_SIZE - ret - 1), - "0x%08lx - 0x%08lx\n", - ((unsigned long) p->base), - ((unsigned long) p->base + p->num - 1)); + ret += snprintf(&buf[ret], (PAGE_SIZE - ret - 1), + "0x%08lx - 0x%08lx\n", + ((unsigned long) p->base), + ((unsigned long) p->base + p->num - 1)); } mutex_unlock(&rsrc_mutex); - return (ret); + return ret; } static ssize_t store_mem_db(struct device *dev, @@ -982,12 +990,13 @@ static ssize_t store_mem_db(struct device *dev, unsigned int add = ADD_MANAGED_RESOURCE; ssize_t ret = 0; - ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr); + ret = sscanf(buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr); if (ret != 2) { - ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr); + ret = sscanf(buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr); add = REMOVE_MANAGED_RESOURCE; if (ret != 2) { - ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr); + ret = sscanf(buf, "0x%lx - 0x%lx", &start_addr, + &end_addr); add = ADD_MANAGED_RESOURCE; if (ret != 2) return -EINVAL; diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index 78d5aab542f7fdfc8fcf29361cb4b053b9b2bdec..7a456000332a77ada559a04c4c238cdabbc69e6f 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c @@ -164,7 +164,7 @@ static ssize_t pccard_store_irq_mask(struct device *dev, if (!count) return -EINVAL; - ret = sscanf (buf, "0x%x\n", &mask); + ret = sscanf(buf, "0x%x\n", &mask); if (ret == 1) { s->irq_mask &= mask; @@ -278,7 +278,7 @@ static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, loff_t off free_tuple: kfree(tuplebuffer); - return (ret); + return ret; } static ssize_t pccard_show_cis(struct kobject *kobj, @@ -308,7 +308,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, count = pccard_extract_cis(s, buf, off, count); } - return (count); + return count; } static ssize_t pccard_store_cis(struct kobject *kobj, diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 8be4cc447a176a9d1bea0f33b355791dd460b6b1..fe02cfd4b5e905673fddb4f0d9e98391d7379ce2 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -6,7 +6,7 @@ * Changelog: * Aug 2002: Manfred Spraul * Dynamically adjust the size of the bridge resource - * + * * May 2003: Dominik Brodowski * Merge pci_socket.c and yenta.c into one file */ @@ -16,13 +16,12 @@ #include #include #include +#include #include #include #include -#include - #include "yenta_socket.h" #include "i82365.h" @@ -55,7 +54,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket); static unsigned int override_bios; module_param(override_bios, uint, 0000); -MODULE_PARM_DESC (override_bios, "yenta ignore bios resource allocation"); +MODULE_PARM_DESC(override_bios, "yenta ignore bios resource allocation"); /* * Generate easy-to-use ways of reading a cardbus sockets @@ -237,24 +236,42 @@ static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state) /* i82365SL-DF style */ if (socket->flags & YENTA_16BIT_POWER_DF) { switch (state->Vcc) { - case 33: reg |= I365_VCC_3V; break; - case 50: reg |= I365_VCC_5V; break; - default: reg = 0; break; + case 33: + reg |= I365_VCC_3V; + break; + case 50: + reg |= I365_VCC_5V; + break; + default: + reg = 0; + break; } switch (state->Vpp) { case 33: - case 50: reg |= I365_VPP1_5V; break; - case 120: reg |= I365_VPP1_12V; break; + case 50: + reg |= I365_VPP1_5V; + break; + case 120: + reg |= I365_VPP1_12V; + break; } } else { /* i82365SL-B style */ switch (state->Vcc) { - case 50: reg |= I365_VCC_5V; break; - default: reg = 0; break; + case 50: + reg |= I365_VCC_5V; + break; + default: + reg = 0; + break; } switch (state->Vpp) { - case 50: reg |= I365_VPP1_5V | I365_VPP2_5V; break; - case 120: reg |= I365_VPP1_12V | I365_VPP2_12V; break; + case 50: + reg |= I365_VPP1_5V | I365_VPP2_5V; + break; + case 120: + reg |= I365_VPP1_12V | I365_VPP2_12V; + break; } } @@ -263,14 +280,26 @@ static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state) } else { u32 reg = 0; /* CB_SC_STPCLK? */ switch (state->Vcc) { - case 33: reg = CB_SC_VCC_3V; break; - case 50: reg = CB_SC_VCC_5V; break; - default: reg = 0; break; + case 33: + reg = CB_SC_VCC_3V; + break; + case 50: + reg = CB_SC_VCC_5V; + break; + default: + reg = 0; + break; } switch (state->Vpp) { - case 33: reg |= CB_SC_VPP_3V; break; - case 50: reg |= CB_SC_VPP_5V; break; - case 120: reg |= CB_SC_VPP_12V; break; + case 33: + reg |= CB_SC_VPP_3V; + break; + case 50: + reg |= CB_SC_VPP_5V; + break; + case 120: + reg |= CB_SC_VPP_12V; + break; } if (reg != cb_readl(socket, CB_SOCKET_CONTROL)) cb_writel(socket, CB_SOCKET_CONTROL, reg); @@ -314,23 +343,29 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) reg = exca_readb(socket, I365_POWER) & (I365_VCC_MASK|I365_VPP1_MASK); reg |= I365_PWR_NORESET; - if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO; - if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT; + if (state->flags & SS_PWR_AUTO) + reg |= I365_PWR_AUTO; + if (state->flags & SS_OUTPUT_ENA) + reg |= I365_PWR_OUT; if (exca_readb(socket, I365_POWER) != reg) exca_writeb(socket, I365_POWER, reg); /* CSC interrupt: no ISA irq for CSC */ reg = I365_CSC_DETECT; if (state->flags & SS_IOCARD) { - if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG; + if (state->csc_mask & SS_STSCHG) + reg |= I365_CSC_STSCHG; } else { - if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1; - if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2; - if (state->csc_mask & SS_READY) reg |= I365_CSC_READY; + if (state->csc_mask & SS_BATDEAD) + reg |= I365_CSC_BVD1; + if (state->csc_mask & SS_BATWARN) + reg |= I365_CSC_BVD2; + if (state->csc_mask & SS_READY) + reg |= I365_CSC_READY; } exca_writeb(socket, I365_CSCINT, reg); exca_readb(socket, I365_CSC); - if(sock->zoom_video) + if (sock->zoom_video) sock->zoom_video(sock, state->flags & SS_ZVCARD); } config_writew(socket, CB_BRIDGE_CONTROL, bridge); @@ -368,9 +403,12 @@ static int yenta_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io exca_writew(socket, I365_IO(map)+I365_W_STOP, io->stop); ioctl = exca_readb(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map); - if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map); - if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map); - if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map); + if (io->flags & MAP_0WS) + ioctl |= I365_IOCTL_0WS(map); + if (io->flags & MAP_16BIT) + ioctl |= I365_IOCTL_16BIT(map); + if (io->flags & MAP_AUTOSZ) + ioctl |= I365_IOCTL_IOCS16(map); exca_writeb(socket, I365_IOCTL, ioctl); if (io->flags & MAP_ACTIVE) @@ -416,10 +454,17 @@ static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map * word = (stop >> 12) & 0x0fff; switch (to_cycles(mem->speed)) { - case 0: break; - case 1: word |= I365_MEM_WS0; break; - case 2: word |= I365_MEM_WS1; break; - default: word |= I365_MEM_WS1 | I365_MEM_WS0; break; + case 0: + break; + case 1: + word |= I365_MEM_WS0; + break; + case 2: + word |= I365_MEM_WS1; + break; + default: + word |= I365_MEM_WS1 | I365_MEM_WS0; + break; } exca_writew(socket, I365_MEM(map) + I365_W_STOP, word); @@ -547,9 +592,9 @@ static int yenta_sock_suspend(struct pcmcia_socket *sock) * max 4 MB, min 16 kB. We try very hard to not get below * the "ACC" values, though. */ -#define BRIDGE_MEM_MAX 4*1024*1024 -#define BRIDGE_MEM_ACC 128*1024 -#define BRIDGE_MEM_MIN 16*1024 +#define BRIDGE_MEM_MAX (4*1024*1024) +#define BRIDGE_MEM_ACC (128*1024) +#define BRIDGE_MEM_MIN (16*1024) #define BRIDGE_IO_MAX 512 #define BRIDGE_IO_ACC 256 @@ -574,7 +619,7 @@ static int yenta_search_one_res(struct resource *root, struct resource *res, int i; size = BRIDGE_MEM_MAX; if (size > avail/8) { - size=(avail+1)/8; + size = (avail+1)/8; /* round size down to next power of 2 */ i = 0; while ((size /= 2) != 0) @@ -590,7 +635,7 @@ static int yenta_search_one_res(struct resource *root, struct resource *res, do { if (allocate_resource(root, res, size, start, end, align, - NULL, NULL)==0) { + NULL, NULL) == 0) { return 1; } size = size/2; @@ -605,8 +650,8 @@ static int yenta_search_res(struct yenta_socket *socket, struct resource *res, u32 min) { int i; - for (i=0; idev->bus->resource[i]; + for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { + struct resource *root = socket->dev->bus->resource[i]; if (!root) continue; @@ -704,7 +749,7 @@ static void yenta_allocate_resources(struct yenta_socket *socket) static void yenta_free_resources(struct yenta_socket *socket) { int i; - for (i=0;i<4;i++) { + for (i = 0; i < 4; i++) { struct resource *res; res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i; if (res->start != 0 && res->end != 0) @@ -726,7 +771,7 @@ static void __devexit yenta_close(struct pci_dev *dev) /* we don't want a dying socket registered */ pcmcia_unregister_socket(&sock->socket); - + /* Disable all events so we don't die in an IRQ storm */ cb_writel(sock, CB_SOCKET_MASK, 0x0); exca_writeb(sock, I365_CSCINT, 0); @@ -898,7 +943,7 @@ static irqreturn_t yenta_probe_handler(int irq, void *dev_id) { struct yenta_socket *socket = (struct yenta_socket *) dev_id; u8 csc; - u32 cb_event; + u32 cb_event; /* Clear interrupt status for the event */ cb_event = cb_readl(socket, CB_SOCKET_EVENT); @@ -1019,7 +1064,7 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) { struct list_head *tmp; unsigned char upper_limit; - /* + /* * We only check and fix the parent bridge: All systems which need * this fixup that have been reviewed are laptops and the only bridge * which needed fixing was the parent bridge of the CardBus bridge: @@ -1038,7 +1083,7 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) /* check the bus ranges of all silbling bridges to prevent overlap */ list_for_each(tmp, &bridge_to_fix->parent->children) { - struct pci_bus * silbling = pci_bus_b(tmp); + struct pci_bus *silbling = pci_bus_b(tmp); /* * If the silbling has a higher secondary bus number * and it's secondary is equal or smaller than our @@ -1083,7 +1128,7 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) * interrupt, and that we can map the cardbus area. Fill in the * socket information structure.. */ -static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_id *id) +static int __devinit yenta_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct yenta_socket *socket; int ret; @@ -1302,7 +1347,7 @@ static struct dev_pm_ops yenta_pm_ops = { #define YENTA_PM_OPS NULL #endif -#define CB_ID(vend,dev,type) \ +#define CB_ID(vend, dev, type) \ { \ .vendor = vend, \ .device = dev, \ @@ -1313,7 +1358,7 @@ static struct dev_pm_ops yenta_pm_ops = { .driver_data = CARDBUS_TYPE_##type, \ } -static struct pci_device_id yenta_table [] = { +static struct pci_device_id yenta_table[] = { CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1031, TI), /* @@ -1403,13 +1448,13 @@ static struct pci_driver yenta_cardbus_driver = { static int __init yenta_socket_init(void) { - return pci_register_driver (¥ta_cardbus_driver); + return pci_register_driver(¥ta_cardbus_driver); } -static void __exit yenta_socket_exit (void) +static void __exit yenta_socket_exit(void) { - pci_unregister_driver (¥ta_cardbus_driver); + pci_unregister_driver(¥ta_cardbus_driver); } diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index 8473fe5ed7ffe79d190cffcc42b3b2b383e4cf58..dfbd5a6cc58becc8cca321e4c6c34a043aebe81f 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -285,15 +285,10 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) * the PCI region, and that might prevent a PCI * driver from requesting its resources. */ - dev_warn(&dev->dev, "%s resource " - "(0x%llx-0x%llx) overlaps %s BAR %d " - "(0x%llx-0x%llx), disabling\n", - pnp_resource_type_name(res), - (unsigned long long) pnp_start, - (unsigned long long) pnp_end, - pci_name(pdev), i, - (unsigned long long) pci_start, - (unsigned long long) pci_end); + dev_warn(&dev->dev, + "disabling %pR because it overlaps " + "%s BAR %d %pR\n", res, + pci_name(pdev), i, &pdev->resource[i]); res->flags |= IORESOURCE_DISABLED; } } diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index ba97654278862ea5824c9645bcaa740dfcfe3061..64d0596bafb5949aacc8e1ae9c6bffdd578f91fe 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -517,7 +517,7 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, res->start = irq; res->end = irq; - pnp_dbg(&dev->dev, " add irq %d flags %#x\n", irq, flags); + pnp_dbg(&dev->dev, " add %pr\n", res); return pnp_res; } @@ -538,7 +538,7 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, res->start = dma; res->end = dma; - pnp_dbg(&dev->dev, " add dma %d flags %#x\n", dma, flags); + pnp_dbg(&dev->dev, " add %pr\n", res); return pnp_res; } @@ -562,8 +562,7 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev, res->start = start; res->end = end; - pnp_dbg(&dev->dev, " add io %#llx-%#llx flags %#x\n", - (unsigned long long) start, (unsigned long long) end, flags); + pnp_dbg(&dev->dev, " add %pr\n", res); return pnp_res; } @@ -587,8 +586,7 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev, res->start = start; res->end = end; - pnp_dbg(&dev->dev, " add mem %#llx-%#llx flags %#x\n", - (unsigned long long) start, (unsigned long long) end, flags); + pnp_dbg(&dev->dev, " add %pr\n", res); return pnp_res; } diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c index 63087d5ce609a189ca0b564ffa546e15e7b0c176..9585c1c1cc3669783653deb6841d14fe0c10b292 100644 --- a/drivers/pnp/support.c +++ b/drivers/pnp/support.c @@ -75,47 +75,14 @@ char *pnp_resource_type_name(struct resource *res) void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc) { - char buf[128]; - int len; struct pnp_resource *pnp_res; - struct resource *res; - if (list_empty(&dev->resources)) { + if (list_empty(&dev->resources)) pnp_dbg(&dev->dev, "%s: no current resources\n", desc); - return; - } - - pnp_dbg(&dev->dev, "%s: current resources:\n", desc); - list_for_each_entry(pnp_res, &dev->resources, list) { - res = &pnp_res->res; - len = 0; - - len += scnprintf(buf + len, sizeof(buf) - len, " %-3s ", - pnp_resource_type_name(res)); - - if (res->flags & IORESOURCE_DISABLED) { - pnp_dbg(&dev->dev, "%sdisabled\n", buf); - continue; - } - - switch (pnp_resource_type(res)) { - case IORESOURCE_IO: - case IORESOURCE_MEM: - len += scnprintf(buf + len, sizeof(buf) - len, - "%#llx-%#llx flags %#lx", - (unsigned long long) res->start, - (unsigned long long) res->end, - res->flags); - break; - case IORESOURCE_IRQ: - case IORESOURCE_DMA: - len += scnprintf(buf + len, sizeof(buf) - len, - "%lld flags %#lx", - (unsigned long long) res->start, - res->flags); - break; - } - pnp_dbg(&dev->dev, "%s\n", buf); + else { + pnp_dbg(&dev->dev, "%s: current resources:\n", desc); + list_for_each_entry(pnp_res, &dev->resources, list) + pnp_dbg(&dev->dev, "%pr\n", &pnp_res->res); } } diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c index 59b90922da8c324529c4d198c23b54211168f23f..49c1720df59a8550cdca31735e6ef519f6b88266 100644 --- a/drivers/pnp/system.c +++ b/drivers/pnp/system.c @@ -22,11 +22,11 @@ static const struct pnp_device_id pnp_dev_table[] = { {"", 0} }; -static void reserve_range(struct pnp_dev *dev, resource_size_t start, - resource_size_t end, int port) +static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) { char *regionid; const char *pnpid = dev_name(&dev->dev); + resource_size_t start = r->start, end = r->end; struct resource *res; regionid = kmalloc(16, GFP_KERNEL); @@ -48,10 +48,8 @@ static void reserve_range(struct pnp_dev *dev, resource_size_t start, * example do reserve stuff they know about too, so we may well * have double reservations. */ - dev_info(&dev->dev, "%s range 0x%llx-0x%llx %s reserved\n", - port ? "ioport" : "iomem", - (unsigned long long) start, (unsigned long long) end, - res ? "has been" : "could not be"); + dev_info(&dev->dev, "%pR %s reserved\n", r, + res ? "has been" : "could not be"); } static void reserve_resources_of_dev(struct pnp_dev *dev) @@ -77,14 +75,14 @@ static void reserve_resources_of_dev(struct pnp_dev *dev) if (res->end < res->start) continue; /* invalid */ - reserve_range(dev, res->start, res->end, 1); + reserve_range(dev, res, 1); } for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { if (res->flags & IORESOURCE_DISABLED) continue; - reserve_range(dev, res->start, res->end, 0); + reserve_range(dev, res, 0); } } diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c index e8b278f71781a2c3590fd6029f6a1daa34ccfe0f..6a84a8eb8d7ac711ae0fa46b87ea8d63d7be80ff 100644 --- a/drivers/power/pcf50633-charger.c +++ b/drivers/power/pcf50633-charger.c @@ -303,7 +303,6 @@ static const u8 mbc_irq_handlers[] = { static int __devinit pcf50633_mbc_probe(struct platform_device *pdev) { struct pcf50633_mbc *mbc; - struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data; int ret; int i; u8 mbcs1; @@ -313,7 +312,7 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev) return -ENOMEM; platform_set_drvdata(pdev, mbc); - mbc->pcf = pdata->pcf; + mbc->pcf = dev_to_pcf50633(pdev->dev.parent); /* Set up IRQ handlers */ for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++) diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c index 28b0299c0043694cf19bed7d3bc97b8289db2873..ad4f071e12870a26cbf6d7fb9415590947ba1833 100644 --- a/drivers/power/wm8350_power.c +++ b/drivers/power/wm8350_power.c @@ -184,8 +184,9 @@ static ssize_t charger_state_show(struct device *dev, static DEVICE_ATTR(charger_state, 0444, charger_state_show, NULL); -static void wm8350_charger_handler(struct wm8350 *wm8350, int irq, void *data) +static irqreturn_t wm8350_charger_handler(int irq, void *data) { + struct wm8350 *wm8350 = data; struct wm8350_power *power = &wm8350->power; struct wm8350_charger_policy *policy = power->policy; @@ -238,6 +239,8 @@ static void wm8350_charger_handler(struct wm8350 *wm8350, int irq, void *data) default: dev_err(wm8350->dev, "Unknown interrupt %d\n", irq); } + + return IRQ_HANDLED; } /********************************************************************* @@ -387,73 +390,55 @@ static void wm8350_init_charger(struct wm8350 *wm8350) { /* register our interest in charger events */ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, - wm8350_charger_handler, NULL); - wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); + wm8350_charger_handler, 0, "Battery hot", wm8350); wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, - wm8350_charger_handler, NULL); - wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); + wm8350_charger_handler, 0, "Battery cold", wm8350); wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, - wm8350_charger_handler, NULL); - wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); + wm8350_charger_handler, 0, "Battery fail", wm8350); wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO, - wm8350_charger_handler, NULL); - wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_TO); + wm8350_charger_handler, 0, + "Charger timeout", wm8350); wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END, - wm8350_charger_handler, NULL); - wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_END); + wm8350_charger_handler, 0, + "Charge end", wm8350); wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START, - wm8350_charger_handler, NULL); - wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_START); + wm8350_charger_handler, 0, + "Charge start", wm8350); wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, - wm8350_charger_handler, NULL); - wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY); + wm8350_charger_handler, 0, + "Fast charge ready", wm8350); wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, - wm8350_charger_handler, NULL); - wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); + wm8350_charger_handler, 0, + "Battery <3.9V", wm8350); wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, - wm8350_charger_handler, NULL); - wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); + wm8350_charger_handler, 0, + "Battery <3.1V", wm8350); wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, - wm8350_charger_handler, NULL); - wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); + wm8350_charger_handler, 0, + "Battery <2.85V", wm8350); /* and supply change events */ wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB, - wm8350_charger_handler, NULL); - wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_USB_FB); + wm8350_charger_handler, 0, "USB", wm8350); wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, - wm8350_charger_handler, NULL); - wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB); + wm8350_charger_handler, 0, "Wall", wm8350); wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, - wm8350_charger_handler, NULL); - wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB); + wm8350_charger_handler, 0, "Battery", wm8350); } static void free_charger_irq(struct wm8350 *wm8350) { - wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); - wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); - wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); - wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_TO); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO); - wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_END); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END); - wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_START); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START); - wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); - wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); - wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); - wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_USB_FB); wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB); - wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB); wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB); - wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB); wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB); } diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index bcbb161bde0b706c6083f2bc6205180dc0fcea09..7cfdd65bebb4185efb9552d2be4afa9f3611385f 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -70,7 +70,7 @@ config REGULATOR_MAX1586 for PXA27x chips to control VCC_CORE and VCC_USIM voltages. config REGULATOR_TWL4030 - bool "TI TWL4030/TWL5030/TPS695x0 PMIC" + bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC" depends on TWL4030_CORE help This driver supports the voltage regulators provided by diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 4257a868377803b0359f49af864fb3b4ad014d57..9ae3cc44e668d97dacaecee4489322de94f8d56e 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o -obj-$(CONFIG_REGULATOR_TWL4030) += twl4030-regulator.o +obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 0803ffe6236d03526c66df8fbf6e9bdba0150b7f..c8f41dc05b76f772aa58d57d85c0ab231672a87f 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -314,13 +314,15 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev) struct pcf50633 *pcf; /* Already set by core driver */ - pcf = platform_get_drvdata(pdev); + pcf = dev_to_pcf50633(pdev->dev.parent); rdev = regulator_register(®ulators[pdev->id], &pdev->dev, pdev->dev.platform_data, pcf); if (IS_ERR(rdev)) return PTR_ERR(rdev); + platform_set_drvdata(pdev, rdev); + if (pcf->pdata->regulator_registered) pcf->pdata->regulator_registered(pcf, pdev->id); @@ -331,6 +333,7 @@ static int __devexit pcf50633_regulator_remove(struct platform_device *pdev) { struct regulator_dev *rdev = platform_get_drvdata(pdev); + platform_set_drvdata(pdev, NULL); regulator_unregister(rdev); return 0; diff --git a/drivers/regulator/twl4030-regulator.c b/drivers/regulator/twl-regulator.c similarity index 55% rename from drivers/regulator/twl4030-regulator.c rename to drivers/regulator/twl-regulator.c index e2032fb60b556cc0619eed628fb605b8ca62deeb..7ea1c3a31081cd656b85ee62a1694ae943d34993 100644 --- a/drivers/regulator/twl4030-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1,5 +1,5 @@ /* - * twl4030-regulator.c -- support regulators in twl4030 family chips + * twl-regulator.c -- support regulators in twl4030/twl6030 family chips * * Copyright (C) 2008 David Brownell * @@ -15,11 +15,11 @@ #include #include #include -#include +#include /* - * The TWL4030/TW5030/TPS659x0 family chips include power management, a + * The TWL4030/TW5030/TPS659x0/TWL6030 family chips include power management, a * USB OTG transceiver, an RTC, ADC, PWM, and lots more. Some versions * include an audio codec, battery charger, and more voltage regulators. * These chips are often used in OMAP-based systems. @@ -33,7 +33,7 @@ struct twlreg_info { /* start of regulator's PM_RECEIVER control register bank */ u8 base; - /* twl4030 resource ID, for resource control state machine */ + /* twl resource ID, for resource control state machine */ u8 id; /* voltage in mV = table[VSEL]; table_len must be a power-of-two */ @@ -52,27 +52,38 @@ struct twlreg_info { * The first three registers of all power resource banks help hardware to * manage the various resource groups. */ +/* Common offset in TWL4030/6030 */ #define VREG_GRP 0 +/* TWL4030 register offsets */ #define VREG_TYPE 1 #define VREG_REMAP 2 #define VREG_DEDICATED 3 /* LDO control */ - +/* TWL6030 register offsets */ +#define VREG_TRANS 1 +#define VREG_STATE 2 +#define VREG_VOLTAGE 3 +/* TWL6030 Misc register offsets */ +#define VREG_BC_ALL 1 +#define VREG_BC_REF 2 +#define VREG_BC_PROC 3 +#define VREG_BC_CLK_RST 4 static inline int -twl4030reg_read(struct twlreg_info *info, unsigned offset) +twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset) { u8 value; int status; - status = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, + status = twl_i2c_read_u8(slave_subgp, &value, info->base + offset); return (status < 0) ? status : value; } static inline int -twl4030reg_write(struct twlreg_info *info, unsigned offset, u8 value) +twlreg_write(struct twlreg_info *info, unsigned slave_subgp, unsigned offset, + u8 value) { - return twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + return twl_i2c_write_u8(slave_subgp, value, info->base + offset); } @@ -80,59 +91,79 @@ twl4030reg_write(struct twlreg_info *info, unsigned offset, u8 value) /* generic power resource operations, which work on all regulators */ -static int twl4030reg_grp(struct regulator_dev *rdev) +static int twlreg_grp(struct regulator_dev *rdev) { - return twl4030reg_read(rdev_get_drvdata(rdev), VREG_GRP); + return twlreg_read(rdev_get_drvdata(rdev), TWL_MODULE_PM_RECEIVER, + VREG_GRP); } /* * Enable/disable regulators by joining/leaving the P1 (processor) group. * We assume nobody else is updating the DEV_GRP registers. */ - -#define P3_GRP BIT(7) /* "peripherals" */ -#define P2_GRP BIT(6) /* secondary processor, modem, etc */ -#define P1_GRP BIT(5) /* CPU/Linux */ - -static int twl4030reg_is_enabled(struct regulator_dev *rdev) +/* definition for 4030 family */ +#define P3_GRP_4030 BIT(7) /* "peripherals" */ +#define P2_GRP_4030 BIT(6) /* secondary processor, modem, etc */ +#define P1_GRP_4030 BIT(5) /* CPU/Linux */ +/* definition for 6030 family */ +#define P3_GRP_6030 BIT(2) /* secondary processor, modem, etc */ +#define P2_GRP_6030 BIT(1) /* "peripherals" */ +#define P1_GRP_6030 BIT(0) /* CPU/Linux */ + +static int twlreg_is_enabled(struct regulator_dev *rdev) { - int state = twl4030reg_grp(rdev); + int state = twlreg_grp(rdev); if (state < 0) return state; - return (state & P1_GRP) != 0; + if (twl_class_is_4030()) + state &= P1_GRP_4030; + else + state &= P1_GRP_6030; + return state; } -static int twl4030reg_enable(struct regulator_dev *rdev) +static int twlreg_enable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; - grp = twl4030reg_read(info, VREG_GRP); + grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); if (grp < 0) return grp; - grp |= P1_GRP; - return twl4030reg_write(info, VREG_GRP, grp); + if (twl_class_is_4030()) + grp |= P1_GRP_4030; + else + grp |= P1_GRP_6030; + + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); } -static int twl4030reg_disable(struct regulator_dev *rdev) +static int twlreg_disable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; - grp = twl4030reg_read(info, VREG_GRP); + grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); if (grp < 0) return grp; - grp &= ~P1_GRP; - return twl4030reg_write(info, VREG_GRP, grp); + if (twl_class_is_4030()) + grp &= ~P1_GRP_4030; + else + grp &= ~P1_GRP_6030; + + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); } -static int twl4030reg_get_status(struct regulator_dev *rdev) +static int twlreg_get_status(struct regulator_dev *rdev) { - int state = twl4030reg_grp(rdev); + int state = twlreg_grp(rdev); + + if (twl_class_is_6030()) + return 0; /* FIXME return for 6030 regulator */ if (state < 0) return state; @@ -146,12 +177,15 @@ static int twl4030reg_get_status(struct regulator_dev *rdev) : REGULATOR_STATUS_STANDBY; } -static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode) +static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode) { struct twlreg_info *info = rdev_get_drvdata(rdev); unsigned message; int status; + if (twl_class_is_6030()) + return 0; /* FIXME return for 6030 regulator */ + /* We can only set the mode through state machine commands... */ switch (mode) { case REGULATOR_MODE_NORMAL: @@ -165,18 +199,18 @@ static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode) } /* Ensure the resource is associated with some group */ - status = twl4030reg_grp(rdev); + status = twlreg_grp(rdev); if (status < 0) return status; - if (!(status & (P3_GRP | P2_GRP | P1_GRP))) + if (!(status & (P3_GRP_4030 | P2_GRP_4030 | P1_GRP_4030))) return -EACCES; - status = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, + status = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, message >> 8, 0x15 /* PB_WORD_MSB */ ); if (status >= 0) return status; - return twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, + return twl_i2c_write_u8(TWL_MODULE_PM_MASTER, message, 0x16 /* PB_WORD_LSB */ ); } @@ -260,9 +294,31 @@ static const u16 VSIM_VSEL_table[] = { static const u16 VDAC_VSEL_table[] = { 1200, 1300, 1800, 1800, }; +static const u16 VAUX1_6030_VSEL_table[] = { + 1000, 1300, 1800, 2500, + 2800, 2900, 3000, 3000, +}; +static const u16 VAUX2_6030_VSEL_table[] = { + 1200, 1800, 2500, 2750, + 2800, 2800, 2800, 2800, +}; +static const u16 VAUX3_6030_VSEL_table[] = { + 1000, 1200, 1300, 1800, + 2500, 2800, 3000, 3000, +}; +static const u16 VMMC_VSEL_table[] = { + 1200, 1800, 2800, 2900, + 3000, 3000, 3000, 3000, +}; +static const u16 VPP_VSEL_table[] = { + 1800, 1900, 2000, 2100, + 2200, 2300, 2400, 2500, +}; +static const u16 VUSIM_VSEL_table[] = { + 1200, 1800, 2500, 2900, +}; - -static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) +static int twlldo_list_voltage(struct regulator_dev *rdev, unsigned index) { struct twlreg_info *info = rdev_get_drvdata(rdev); int mV = info->table[index]; @@ -271,7 +327,7 @@ static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) } static int -twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) +twlldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel; @@ -288,16 +344,18 @@ twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) /* use the first in-range value */ if (min_uV <= uV && uV <= max_uV) - return twl4030reg_write(info, VREG_DEDICATED, vsel); + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, + VREG_VOLTAGE, vsel); } return -EDOM; } -static int twl4030ldo_get_voltage(struct regulator_dev *rdev) +static int twlldo_get_voltage(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); - int vsel = twl4030reg_read(info, VREG_DEDICATED); + int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, + VREG_VOLTAGE); if (vsel < 0) return vsel; @@ -306,19 +364,19 @@ static int twl4030ldo_get_voltage(struct regulator_dev *rdev) return LDO_MV(info->table[vsel]) * 1000; } -static struct regulator_ops twl4030ldo_ops = { - .list_voltage = twl4030ldo_list_voltage, +static struct regulator_ops twlldo_ops = { + .list_voltage = twlldo_list_voltage, - .set_voltage = twl4030ldo_set_voltage, - .get_voltage = twl4030ldo_get_voltage, + .set_voltage = twlldo_set_voltage, + .get_voltage = twlldo_get_voltage, - .enable = twl4030reg_enable, - .disable = twl4030reg_disable, - .is_enabled = twl4030reg_is_enabled, + .enable = twlreg_enable, + .disable = twlreg_disable, + .is_enabled = twlreg_is_enabled, - .set_mode = twl4030reg_set_mode, + .set_mode = twlreg_set_mode, - .get_status = twl4030reg_get_status, + .get_status = twlreg_get_status, }; /*----------------------------------------------------------------------*/ @@ -326,60 +384,69 @@ static struct regulator_ops twl4030ldo_ops = { /* * Fixed voltage LDOs don't have a VSEL field to update. */ -static int twl4030fixed_list_voltage(struct regulator_dev *rdev, unsigned index) +static int twlfixed_list_voltage(struct regulator_dev *rdev, unsigned index) { struct twlreg_info *info = rdev_get_drvdata(rdev); return info->min_mV * 1000; } -static int twl4030fixed_get_voltage(struct regulator_dev *rdev) +static int twlfixed_get_voltage(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); return info->min_mV * 1000; } -static struct regulator_ops twl4030fixed_ops = { - .list_voltage = twl4030fixed_list_voltage, +static struct regulator_ops twlfixed_ops = { + .list_voltage = twlfixed_list_voltage, - .get_voltage = twl4030fixed_get_voltage, + .get_voltage = twlfixed_get_voltage, - .enable = twl4030reg_enable, - .disable = twl4030reg_disable, - .is_enabled = twl4030reg_is_enabled, + .enable = twlreg_enable, + .disable = twlreg_disable, + .is_enabled = twlreg_is_enabled, - .set_mode = twl4030reg_set_mode, + .set_mode = twlreg_set_mode, - .get_status = twl4030reg_get_status, + .get_status = twlreg_get_status, }; /*----------------------------------------------------------------------*/ -#define TWL_ADJUSTABLE_LDO(label, offset, num) { \ +#define TWL4030_ADJUSTABLE_LDO(label, offset, num) \ + TWL_ADJUSTABLE_LDO(label, offset, num, TWL4030) +#define TWL4030_FIXED_LDO(label, offset, mVolts, num) \ + TWL_FIXED_LDO(label, offset, mVolts, num, TWL4030) +#define TWL6030_ADJUSTABLE_LDO(label, offset, num) \ + TWL_ADJUSTABLE_LDO(label, offset, num, TWL6030) +#define TWL6030_FIXED_LDO(label, offset, mVolts, num) \ + TWL_FIXED_LDO(label, offset, mVolts, num, TWL6030) + +#define TWL_ADJUSTABLE_LDO(label, offset, num, family) { \ .base = offset, \ .id = num, \ .table_len = ARRAY_SIZE(label##_VSEL_table), \ .table = label##_VSEL_table, \ .desc = { \ .name = #label, \ - .id = TWL4030_REG_##label, \ + .id = family##_REG_##label, \ .n_voltages = ARRAY_SIZE(label##_VSEL_table), \ - .ops = &twl4030ldo_ops, \ + .ops = &twlldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ }, \ } -#define TWL_FIXED_LDO(label, offset, mVolts, num) { \ +#define TWL_FIXED_LDO(label, offset, mVolts, num, family) { \ .base = offset, \ .id = num, \ .min_mV = mVolts, \ .desc = { \ .name = #label, \ - .id = TWL4030_REG_##label, \ + .id = family##_REG_##label, \ .n_voltages = 1, \ - .ops = &twl4030fixed_ops, \ + .ops = &twlfixed_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ }, \ @@ -389,35 +456,47 @@ static struct regulator_ops twl4030fixed_ops = { * We list regulators here if systems need some level of * software control over them after boot. */ -static struct twlreg_info twl4030_regs[] = { - TWL_ADJUSTABLE_LDO(VAUX1, 0x17, 1), - TWL_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2), - TWL_ADJUSTABLE_LDO(VAUX2, 0x1b, 2), - TWL_ADJUSTABLE_LDO(VAUX3, 0x1f, 3), - TWL_ADJUSTABLE_LDO(VAUX4, 0x23, 4), - TWL_ADJUSTABLE_LDO(VMMC1, 0x27, 5), - TWL_ADJUSTABLE_LDO(VMMC2, 0x2b, 6), +static struct twlreg_info twl_regs[] = { + TWL4030_ADJUSTABLE_LDO(VAUX1, 0x17, 1), + TWL4030_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2), + TWL4030_ADJUSTABLE_LDO(VAUX2, 0x1b, 2), + TWL4030_ADJUSTABLE_LDO(VAUX3, 0x1f, 3), + TWL4030_ADJUSTABLE_LDO(VAUX4, 0x23, 4), + TWL4030_ADJUSTABLE_LDO(VMMC1, 0x27, 5), + TWL4030_ADJUSTABLE_LDO(VMMC2, 0x2b, 6), /* - TWL_ADJUSTABLE_LDO(VPLL1, 0x2f, 7), + TWL4030_ADJUSTABLE_LDO(VPLL1, 0x2f, 7), */ - TWL_ADJUSTABLE_LDO(VPLL2, 0x33, 8), - TWL_ADJUSTABLE_LDO(VSIM, 0x37, 9), - TWL_ADJUSTABLE_LDO(VDAC, 0x3b, 10), + TWL4030_ADJUSTABLE_LDO(VPLL2, 0x33, 8), + TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9), + TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10), /* - TWL_ADJUSTABLE_LDO(VINTANA1, 0x3f, 11), - TWL_ADJUSTABLE_LDO(VINTANA2, 0x43, 12), - TWL_ADJUSTABLE_LDO(VINTDIG, 0x47, 13), - TWL_SMPS(VIO, 0x4b, 14), - TWL_SMPS(VDD1, 0x55, 15), - TWL_SMPS(VDD2, 0x63, 16), + TWL4030_ADJUSTABLE_LDO(VINTANA1, 0x3f, 11), + TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12), + TWL4030_ADJUSTABLE_LDO(VINTDIG, 0x47, 13), + TWL4030_SMPS(VIO, 0x4b, 14), + TWL4030_SMPS(VDD1, 0x55, 15), + TWL4030_SMPS(VDD2, 0x63, 16), */ - TWL_FIXED_LDO(VUSB1V5, 0x71, 1500, 17), - TWL_FIXED_LDO(VUSB1V8, 0x74, 1800, 18), - TWL_FIXED_LDO(VUSB3V1, 0x77, 3100, 19), + TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17), + TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18), + TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19), /* VUSBCP is managed *only* by the USB subchip */ + + /* 6030 REG with base as PMC Slave Misc : 0x0030 */ + TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1), + TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2), + TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3), + TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4), + TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5), + TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7), + TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15), + TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16), + TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17), + TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18) }; -static int twl4030reg_probe(struct platform_device *pdev) +static int twlreg_probe(struct platform_device *pdev) { int i; struct twlreg_info *info; @@ -425,10 +504,10 @@ static int twl4030reg_probe(struct platform_device *pdev) struct regulation_constraints *c; struct regulator_dev *rdev; - for (i = 0, info = NULL; i < ARRAY_SIZE(twl4030_regs); i++) { - if (twl4030_regs[i].desc.id != pdev->id) + for (i = 0, info = NULL; i < ARRAY_SIZE(twl_regs); i++) { + if (twl_regs[i].desc.id != pdev->id) continue; - info = twl4030_regs + i; + info = twl_regs + i; break; } if (!info) @@ -466,35 +545,35 @@ static int twl4030reg_probe(struct platform_device *pdev) return 0; } -static int __devexit twl4030reg_remove(struct platform_device *pdev) +static int __devexit twlreg_remove(struct platform_device *pdev) { regulator_unregister(platform_get_drvdata(pdev)); return 0; } -MODULE_ALIAS("platform:twl4030_reg"); +MODULE_ALIAS("platform:twl_reg"); -static struct platform_driver twl4030reg_driver = { - .probe = twl4030reg_probe, - .remove = __devexit_p(twl4030reg_remove), +static struct platform_driver twlreg_driver = { + .probe = twlreg_probe, + .remove = __devexit_p(twlreg_remove), /* NOTE: short name, to work around driver model truncation of - * "twl4030_regulator.12" (and friends) to "twl4030_regulator.1". + * "twl_regulator.12" (and friends) to "twl_regulator.1". */ - .driver.name = "twl4030_reg", + .driver.name = "twl_reg", .driver.owner = THIS_MODULE, }; -static int __init twl4030reg_init(void) +static int __init twlreg_init(void) { - return platform_driver_register(&twl4030reg_driver); + return platform_driver_register(&twlreg_driver); } -subsys_initcall(twl4030reg_init); +subsys_initcall(twlreg_init); -static void __exit twl4030reg_exit(void) +static void __exit twlreg_exit(void) { - platform_driver_unregister(&twl4030reg_driver); + platform_driver_unregister(&twlreg_driver); } -module_exit(twl4030reg_exit) +module_exit(twlreg_exit) -MODULE_DESCRIPTION("TWL4030 regulator driver"); +MODULE_DESCRIPTION("TWL regulator driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 768bd0e5b48bdd00293796554807fb2523ecc01d..1bbff099a546af37a1e4e2179ca52f9ffa478962 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1330,9 +1330,10 @@ static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { }, }; -static void pmic_uv_handler(struct wm8350 *wm8350, int irq, void *data) +static irqreturn_t pmic_uv_handler(int irq, void *data) { struct regulator_dev *rdev = (struct regulator_dev *)data; + struct wm8350 *wm8350 = rdev_get_drvdata(rdev); mutex_lock(&rdev->mutex); if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2) @@ -1344,6 +1345,8 @@ static void pmic_uv_handler(struct wm8350 *wm8350, int irq, void *data) REGULATOR_EVENT_UNDER_VOLTAGE, wm8350); mutex_unlock(&rdev->mutex); + + return IRQ_HANDLED; } static int wm8350_regulator_probe(struct platform_device *pdev) @@ -1388,7 +1391,7 @@ static int wm8350_regulator_probe(struct platform_device *pdev) /* register regulator IRQ */ ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq, - pmic_uv_handler, rdev); + pmic_uv_handler, 0, "UV", rdev); if (ret < 0) { regulator_unregister(rdev); dev_err(&pdev->dev, "failed to register regulator %s IRQ\n", @@ -1396,8 +1399,6 @@ static int wm8350_regulator_probe(struct platform_device *pdev) return ret; } - wm8350_unmask_irq(wm8350, wm8350_reg[pdev->id].irq); - return 0; } @@ -1406,7 +1407,6 @@ static int wm8350_regulator_remove(struct platform_device *pdev) struct regulator_dev *rdev = platform_get_drvdata(pdev); struct wm8350 *wm8350 = rdev_get_drvdata(rdev); - wm8350_mask_irq(wm8350, wm8350_reg[pdev->id].irq); wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq); regulator_unregister(rdev); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index f2e1004d12c7807f56b129e221a36c23cdc1c3bf..71fbd6e8edf71b9fda76a3df084ba00d50e77681 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -258,14 +258,14 @@ config RTC_DRV_TWL92330 the Menelaus driver; it's not separate module. config RTC_DRV_TWL4030 - tristate "TI TWL4030/TWL5030/TPS659x0" + tristate "TI TWL4030/TWL5030/TWL6030/TPS659x0" depends on RTC_CLASS && TWL4030_CORE help If you say yes here you get support for the RTC on the - TWL4030 family chips, used mostly with OMAP3 platforms. + TWL4030/TWL5030/TWL6030 family chips, used mostly with OMAP3 platforms. This driver can also be built as a module. If so, the module - will be called rtc-twl4030. + will be called rtc-twl. config RTC_DRV_S35390A tristate "Seiko Instruments S-35390A" diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index af1ba7ae285716667172ed663df8b85ecda301e5..7da6efb3e953407d9be5723797dd7a9c4ece1e30 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -80,7 +80,7 @@ obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o -obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o +obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c index 4c5d5d0c4cfcf13a4cbf462c7d03a8ad8531f99c..9b74e9c9151c6276c42256b8545508521cafcbd3 100644 --- a/drivers/rtc/rtc-pcf50633.c +++ b/drivers/rtc/rtc-pcf50633.c @@ -277,16 +277,13 @@ static void pcf50633_rtc_irq(int irq, void *data) static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) { - struct pcf50633_subdev_pdata *pdata; struct pcf50633_rtc *rtc; - rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); if (!rtc) return -ENOMEM; - pdata = pdev->dev.platform_data; - rtc->pcf = pdata->pcf; + rtc->pcf = dev_to_pcf50633(pdev->dev.parent); platform_set_drvdata(pdev, rtc); rtc->rtc_dev = rtc_device_register("pcf50633-rtc", &pdev->dev, &pcf50633_rtc_ops, THIS_MODULE); diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl.c similarity index 59% rename from drivers/rtc/rtc-twl4030.c rename to drivers/rtc/rtc-twl.c index 9c8c70c497dcc6a515b44d71035bd313d3955116..c6a83a2a722cbf9657b9e4f9280b482f2e6e3cbb 100644 --- a/drivers/rtc/rtc-twl4030.c +++ b/drivers/rtc/rtc-twl.c @@ -1,5 +1,5 @@ /* - * rtc-twl4030.c -- TWL4030 Real Time Clock interface + * rtc-twl.c -- TWL Real Time Clock interface * * Copyright (C) 2007 MontaVista Software, Inc * Author: Alexandre Rusev @@ -28,33 +28,81 @@ #include #include -#include +#include /* * RTC block register offsets (use TWL_MODULE_RTC) */ -#define REG_SECONDS_REG 0x00 -#define REG_MINUTES_REG 0x01 -#define REG_HOURS_REG 0x02 -#define REG_DAYS_REG 0x03 -#define REG_MONTHS_REG 0x04 -#define REG_YEARS_REG 0x05 -#define REG_WEEKS_REG 0x06 - -#define REG_ALARM_SECONDS_REG 0x07 -#define REG_ALARM_MINUTES_REG 0x08 -#define REG_ALARM_HOURS_REG 0x09 -#define REG_ALARM_DAYS_REG 0x0A -#define REG_ALARM_MONTHS_REG 0x0B -#define REG_ALARM_YEARS_REG 0x0C - -#define REG_RTC_CTRL_REG 0x0D -#define REG_RTC_STATUS_REG 0x0E -#define REG_RTC_INTERRUPTS_REG 0x0F - -#define REG_RTC_COMP_LSB_REG 0x10 -#define REG_RTC_COMP_MSB_REG 0x11 +enum { + REG_SECONDS_REG = 0, + REG_MINUTES_REG, + REG_HOURS_REG, + REG_DAYS_REG, + REG_MONTHS_REG, + REG_YEARS_REG, + REG_WEEKS_REG, + + REG_ALARM_SECONDS_REG, + REG_ALARM_MINUTES_REG, + REG_ALARM_HOURS_REG, + REG_ALARM_DAYS_REG, + REG_ALARM_MONTHS_REG, + REG_ALARM_YEARS_REG, + + REG_RTC_CTRL_REG, + REG_RTC_STATUS_REG, + REG_RTC_INTERRUPTS_REG, + + REG_RTC_COMP_LSB_REG, + REG_RTC_COMP_MSB_REG, +}; +const static u8 twl4030_rtc_reg_map[] = { + [REG_SECONDS_REG] = 0x00, + [REG_MINUTES_REG] = 0x01, + [REG_HOURS_REG] = 0x02, + [REG_DAYS_REG] = 0x03, + [REG_MONTHS_REG] = 0x04, + [REG_YEARS_REG] = 0x05, + [REG_WEEKS_REG] = 0x06, + + [REG_ALARM_SECONDS_REG] = 0x07, + [REG_ALARM_MINUTES_REG] = 0x08, + [REG_ALARM_HOURS_REG] = 0x09, + [REG_ALARM_DAYS_REG] = 0x0A, + [REG_ALARM_MONTHS_REG] = 0x0B, + [REG_ALARM_YEARS_REG] = 0x0C, + + [REG_RTC_CTRL_REG] = 0x0D, + [REG_RTC_STATUS_REG] = 0x0E, + [REG_RTC_INTERRUPTS_REG] = 0x0F, + + [REG_RTC_COMP_LSB_REG] = 0x10, + [REG_RTC_COMP_MSB_REG] = 0x11, +}; +const static u8 twl6030_rtc_reg_map[] = { + [REG_SECONDS_REG] = 0x00, + [REG_MINUTES_REG] = 0x01, + [REG_HOURS_REG] = 0x02, + [REG_DAYS_REG] = 0x03, + [REG_MONTHS_REG] = 0x04, + [REG_YEARS_REG] = 0x05, + [REG_WEEKS_REG] = 0x06, + + [REG_ALARM_SECONDS_REG] = 0x08, + [REG_ALARM_MINUTES_REG] = 0x09, + [REG_ALARM_HOURS_REG] = 0x0A, + [REG_ALARM_DAYS_REG] = 0x0B, + [REG_ALARM_MONTHS_REG] = 0x0C, + [REG_ALARM_YEARS_REG] = 0x0D, + + [REG_RTC_CTRL_REG] = 0x10, + [REG_RTC_STATUS_REG] = 0x11, + [REG_RTC_INTERRUPTS_REG] = 0x12, + + [REG_RTC_COMP_LSB_REG] = 0x13, + [REG_RTC_COMP_MSB_REG] = 0x14, +}; /* RTC_CTRL_REG bitfields */ #define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 @@ -84,31 +132,32 @@ #define ALL_TIME_REGS 6 /*----------------------------------------------------------------------*/ +static u8 *rtc_reg_map; /* - * Supports 1 byte read from TWL4030 RTC register. + * Supports 1 byte read from TWL RTC register. */ -static int twl4030_rtc_read_u8(u8 *data, u8 reg) +static int twl_rtc_read_u8(u8 *data, u8 reg) { int ret; - ret = twl4030_i2c_read_u8(TWL4030_MODULE_RTC, data, reg); + ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg])); if (ret < 0) - pr_err("twl4030_rtc: Could not read TWL4030" + pr_err("twl_rtc: Could not read TWL" "register %X - error %d\n", reg, ret); return ret; } /* - * Supports 1 byte write to TWL4030 RTC registers. + * Supports 1 byte write to TWL RTC registers. */ -static int twl4030_rtc_write_u8(u8 data, u8 reg) +static int twl_rtc_write_u8(u8 data, u8 reg) { int ret; - ret = twl4030_i2c_write_u8(TWL4030_MODULE_RTC, data, reg); + ret = twl_i2c_write_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg])); if (ret < 0) - pr_err("twl4030_rtc: Could not write TWL4030" + pr_err("twl_rtc: Could not write TWL" "register %X - error %d\n", reg, ret); return ret; } @@ -129,7 +178,7 @@ static int set_rtc_irq_bit(unsigned char bit) val = rtc_irq_bits | bit; val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; - ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); + ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); if (ret == 0) rtc_irq_bits = val; @@ -145,14 +194,14 @@ static int mask_rtc_irq_bit(unsigned char bit) int ret; val = rtc_irq_bits & ~bit; - ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); + ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); if (ret == 0) rtc_irq_bits = val; return ret; } -static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) +static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) { int ret; @@ -164,7 +213,7 @@ static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) return ret; } -static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) +static int twl_rtc_update_irq_enable(struct device *dev, unsigned enabled) { int ret; @@ -177,7 +226,7 @@ static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) } /* - * Gets current TWL4030 RTC time and date parameters. + * Gets current TWL RTC time and date parameters. * * The RTC's time/alarm representation is not what gmtime(3) requires * Linux to use: @@ -185,24 +234,24 @@ static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) * - Months are 1..12 vs Linux 0-11 * - Years are 0..99 vs Linux 1900..N (we assume 21st century) */ -static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) +static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm) { unsigned char rtc_data[ALL_TIME_REGS + 1]; int ret; u8 save_control; - ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); + ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); if (ret < 0) return ret; save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; - ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); + ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); if (ret < 0) return ret; - ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, - REG_SECONDS_REG, ALL_TIME_REGS); + ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, + (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); if (ret < 0) { dev_err(dev, "rtc_read_time error %d\n", ret); @@ -219,7 +268,7 @@ static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) return ret; } -static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) +static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm) { unsigned char save_control; unsigned char rtc_data[ALL_TIME_REGS + 1]; @@ -233,18 +282,18 @@ static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) rtc_data[6] = bin2bcd(tm->tm_year - 100); /* Stop RTC while updating the TC registers */ - ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); + ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); if (ret < 0) goto out; save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; - twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); + twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); if (ret < 0) goto out; /* update all the time registers in one shot */ - ret = twl4030_i2c_write(TWL4030_MODULE_RTC, rtc_data, - REG_SECONDS_REG, ALL_TIME_REGS); + ret = twl_i2c_write(TWL_MODULE_RTC, rtc_data, + (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); if (ret < 0) { dev_err(dev, "rtc_set_time error %d\n", ret); goto out; @@ -252,22 +301,22 @@ static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) /* Start back RTC */ save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M; - ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); + ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); out: return ret; } /* - * Gets current TWL4030 RTC alarm time. + * Gets current TWL RTC alarm time. */ -static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) +static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) { unsigned char rtc_data[ALL_TIME_REGS + 1]; int ret; - ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, - REG_ALARM_SECONDS_REG, ALL_TIME_REGS); + ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, + (rtc_reg_map[REG_ALARM_SECONDS_REG]), ALL_TIME_REGS); if (ret < 0) { dev_err(dev, "rtc_read_alarm error %d\n", ret); return ret; @@ -288,12 +337,12 @@ static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) return ret; } -static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) +static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) { unsigned char alarm_data[ALL_TIME_REGS + 1]; int ret; - ret = twl4030_rtc_alarm_irq_enable(dev, 0); + ret = twl_rtc_alarm_irq_enable(dev, 0); if (ret) goto out; @@ -305,20 +354,20 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) alarm_data[6] = bin2bcd(alm->time.tm_year - 100); /* update all the alarm registers in one shot */ - ret = twl4030_i2c_write(TWL4030_MODULE_RTC, alarm_data, - REG_ALARM_SECONDS_REG, ALL_TIME_REGS); + ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data, + (rtc_reg_map[REG_ALARM_SECONDS_REG]), ALL_TIME_REGS); if (ret) { dev_err(dev, "rtc_set_alarm error %d\n", ret); goto out; } if (alm->enabled) - ret = twl4030_rtc_alarm_irq_enable(dev, 1); + ret = twl_rtc_alarm_irq_enable(dev, 1); out: return ret; } -static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) +static irqreturn_t twl_rtc_interrupt(int irq, void *rtc) { unsigned long events = 0; int ret = IRQ_NONE; @@ -333,7 +382,7 @@ static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) local_irq_enable(); #endif - res = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); + res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); if (res) goto out; /* @@ -347,26 +396,28 @@ static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) else events |= RTC_IRQF | RTC_UF; - res = twl4030_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, + res = twl_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, REG_RTC_STATUS_REG); if (res) goto out; - /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 - * needs 2 reads to clear the interrupt. One read is done in - * do_twl4030_pwrirq(). Doing the second read, to clear - * the bit. - * - * FIXME the reason PWR_ISR1 needs an extra read is that - * RTC_IF retriggered until we cleared REG_ALARM_M above. - * But re-reading like this is a bad hack; by doing so we - * risk wrongly clearing status for some other IRQ (losing - * the interrupt). Be smarter about handling RTC_UF ... - */ - res = twl4030_i2c_read_u8(TWL4030_MODULE_INT, + if (twl_class_is_4030()) { + /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 + * needs 2 reads to clear the interrupt. One read is done in + * do_twl_pwrirq(). Doing the second read, to clear + * the bit. + * + * FIXME the reason PWR_ISR1 needs an extra read is that + * RTC_IF retriggered until we cleared REG_ALARM_M above. + * But re-reading like this is a bad hack; by doing so we + * risk wrongly clearing status for some other IRQ (losing + * the interrupt). Be smarter about handling RTC_UF ... + */ + res = twl_i2c_read_u8(TWL4030_MODULE_INT, &rd_reg, TWL4030_INT_PWR_ISR1); - if (res) - goto out; + if (res) + goto out; + } /* Notify RTC core on event */ rtc_update_irq(rtc, 1, events); @@ -376,18 +427,18 @@ out: return ret; } -static struct rtc_class_ops twl4030_rtc_ops = { - .read_time = twl4030_rtc_read_time, - .set_time = twl4030_rtc_set_time, - .read_alarm = twl4030_rtc_read_alarm, - .set_alarm = twl4030_rtc_set_alarm, - .alarm_irq_enable = twl4030_rtc_alarm_irq_enable, - .update_irq_enable = twl4030_rtc_update_irq_enable, +static struct rtc_class_ops twl_rtc_ops = { + .read_time = twl_rtc_read_time, + .set_time = twl_rtc_set_time, + .read_alarm = twl_rtc_read_alarm, + .set_alarm = twl_rtc_set_alarm, + .alarm_irq_enable = twl_rtc_alarm_irq_enable, + .update_irq_enable = twl_rtc_update_irq_enable, }; /*----------------------------------------------------------------------*/ -static int __devinit twl4030_rtc_probe(struct platform_device *pdev) +static int __devinit twl_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; int ret = 0; @@ -398,7 +449,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) return -EINVAL; rtc = rtc_device_register(pdev->name, - &pdev->dev, &twl4030_rtc_ops, THIS_MODULE); + &pdev->dev, &twl_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { ret = PTR_ERR(rtc); dev_err(&pdev->dev, "can't register RTC device, err %ld\n", @@ -409,7 +460,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); - ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); + ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); if (ret < 0) goto out1; @@ -420,11 +471,11 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); /* Clear RTC Power up reset and pending alarm interrupts */ - ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); + ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); if (ret < 0) goto out1; - ret = request_irq(irq, twl4030_rtc_interrupt, + ret = request_irq(irq, twl_rtc_interrupt, IRQF_TRIGGER_RISING, dev_name(&rtc->dev), rtc); if (ret < 0) { @@ -432,21 +483,28 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) goto out1; } + if (twl_class_is_6030()) { + twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, + REG_INT_MSK_LINE_A); + twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, + REG_INT_MSK_STS_A); + } + /* Check RTC module status, Enable if it is off */ - ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); + ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); if (ret < 0) goto out2; if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { - dev_info(&pdev->dev, "Enabling TWL4030-RTC.\n"); + dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; - ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); + ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); if (ret < 0) goto out2; } /* init cached IRQ enable bits */ - ret = twl4030_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); + ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); if (ret < 0) goto out2; @@ -461,10 +519,10 @@ out0: } /* - * Disable all TWL4030 RTC module interrupts. + * Disable all TWL RTC module interrupts. * Sets status flag to free. */ -static int __devexit twl4030_rtc_remove(struct platform_device *pdev) +static int __devexit twl_rtc_remove(struct platform_device *pdev) { /* leave rtc running, but disable irqs */ struct rtc_device *rtc = platform_get_drvdata(pdev); @@ -472,6 +530,13 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev) mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); + if (twl_class_is_6030()) { + twl6030_interrupt_mask(TWL6030_RTC_INT_MASK, + REG_INT_MSK_LINE_A); + twl6030_interrupt_mask(TWL6030_RTC_INT_MASK, + REG_INT_MSK_STS_A); + } + free_irq(irq, rtc); @@ -480,7 +545,7 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev) return 0; } -static void twl4030_rtc_shutdown(struct platform_device *pdev) +static void twl_rtc_shutdown(struct platform_device *pdev) { /* mask timer interrupts, but leave alarm interrupts on to enable power-on when alarm is triggered */ @@ -491,7 +556,7 @@ static void twl4030_rtc_shutdown(struct platform_device *pdev) static unsigned char irqstat; -static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) +static int twl_rtc_suspend(struct platform_device *pdev, pm_message_t state) { irqstat = rtc_irq_bits; @@ -499,42 +564,47 @@ static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int twl4030_rtc_resume(struct platform_device *pdev) +static int twl_rtc_resume(struct platform_device *pdev) { set_rtc_irq_bit(irqstat); return 0; } #else -#define twl4030_rtc_suspend NULL -#define twl4030_rtc_resume NULL +#define twl_rtc_suspend NULL +#define twl_rtc_resume NULL #endif -MODULE_ALIAS("platform:twl4030_rtc"); +MODULE_ALIAS("platform:twl_rtc"); static struct platform_driver twl4030rtc_driver = { - .probe = twl4030_rtc_probe, - .remove = __devexit_p(twl4030_rtc_remove), - .shutdown = twl4030_rtc_shutdown, - .suspend = twl4030_rtc_suspend, - .resume = twl4030_rtc_resume, + .probe = twl_rtc_probe, + .remove = __devexit_p(twl_rtc_remove), + .shutdown = twl_rtc_shutdown, + .suspend = twl_rtc_suspend, + .resume = twl_rtc_resume, .driver = { .owner = THIS_MODULE, - .name = "twl4030_rtc", + .name = "twl_rtc", }, }; -static int __init twl4030_rtc_init(void) +static int __init twl_rtc_init(void) { + if (twl_class_is_4030()) + rtc_reg_map = (u8 *) twl4030_rtc_reg_map; + else + rtc_reg_map = (u8 *) twl6030_rtc_reg_map; + return platform_driver_register(&twl4030rtc_driver); } -module_init(twl4030_rtc_init); +module_init(twl_rtc_init); -static void __exit twl4030_rtc_exit(void) +static void __exit twl_rtc_exit(void) { platform_driver_unregister(&twl4030rtc_driver); } -module_exit(twl4030_rtc_exit); +module_exit(twl_rtc_exit); MODULE_AUTHOR("Texas Instruments, MontaVista Software"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index c91edc572eb609f3c78449099fabf04d0e76af8d..f16486635a8efab098e21e22c1ada0c42f91b2da 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c @@ -315,9 +315,9 @@ static int wm8350_rtc_update_irq_enable(struct device *dev, return 0; } -static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq, - void *data) +static irqreturn_t wm8350_rtc_alarm_handler(int irq, void *data) { + struct wm8350 *wm8350 = data; struct rtc_device *rtc = wm8350->rtc.rtc; int ret; @@ -330,14 +330,18 @@ static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq, dev_err(&(wm8350->rtc.pdev->dev), "Failed to disable alarm: %d\n", ret); } + + return IRQ_HANDLED; } -static void wm8350_rtc_update_handler(struct wm8350 *wm8350, int irq, - void *data) +static irqreturn_t wm8350_rtc_update_handler(int irq, void *data) { + struct wm8350 *wm8350 = data; struct rtc_device *rtc = wm8350->rtc.rtc; rtc_update_irq(rtc, 1, RTC_IRQF | RTC_UF); + + return IRQ_HANDLED; } static const struct rtc_class_ops wm8350_rtc_ops = { @@ -455,15 +459,14 @@ static int wm8350_rtc_probe(struct platform_device *pdev) return ret; } - wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); - wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_PER); - wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC, - wm8350_rtc_update_handler, NULL); + wm8350_rtc_update_handler, 0, + "RTC Seconds", wm8350); + wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM, - wm8350_rtc_alarm_handler, NULL); - wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_ALM); + wm8350_rtc_alarm_handler, 0, + "RTC Alarm", wm8350); return 0; } @@ -473,8 +476,6 @@ static int __devexit wm8350_rtc_remove(struct platform_device *pdev) struct wm8350 *wm8350 = platform_get_drvdata(pdev); struct wm8350_rtc *wm_rtc = &wm8350->rtc; - wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); - wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 395c04c2b00fcd5cca85a696bccddf6f540b7064..98c04cac43c1d87467ee60f43807c0dbc654409b 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -113,11 +113,9 @@ static inline int iucv_dbf_passes(debug_info_t *dbf_grp, int level) #define IUCV_DBF_TEXT_(name, level, text...) \ do { \ if (iucv_dbf_passes(iucv_dbf_##name, level)) { \ - char* iucv_dbf_txt_buf = \ - get_cpu_var(iucv_dbf_txt_buf); \ - sprintf(iucv_dbf_txt_buf, text); \ - debug_text_event(iucv_dbf_##name, level, \ - iucv_dbf_txt_buf); \ + char* __buf = get_cpu_var(iucv_dbf_txt_buf); \ + sprintf(__buf, text); \ + debug_text_event(iucv_dbf_##name, level, __buf); \ put_cpu_var(iucv_dbf_txt_buf); \ } \ } while (0) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 737b4c9609712532e96c4d277b093014f7b0d249..c3e37c8e7e26a8b8ecc4a767561aea15b2378909 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1339,14 +1339,12 @@ static void serial8250_start_tx(struct uart_port *port) serial_out(up, UART_IER, up->ier); if (up->bugs & UART_BUG_TXEN) { - unsigned char lsr, iir; + unsigned char lsr; lsr = serial_in(up, UART_LSR); up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; - iir = serial_in(up, UART_IIR) & 0x0f; if ((up->port.type == PORT_RM9000) ? - (lsr & UART_LSR_THRE && - (iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) : - (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)) + (lsr & UART_LSR_THRE) : + (lsr & UART_LSR_TEMT)) transmit_chars(up); } } @@ -2646,7 +2644,7 @@ static void __init serial8250_isa_init_ports(void) { struct uart_8250_port *up; static int first = 1; - int i; + int i, irqflag = 0; if (!first) return; @@ -2670,6 +2668,9 @@ static void __init serial8250_isa_init_ports(void) up->port.ops = &serial8250_pops; } + if (share_irqs) + irqflag = IRQF_SHARED; + for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; i++, up++) { @@ -2683,8 +2684,7 @@ static void __init serial8250_isa_init_ports(void) up->port.iotype = old_serial_port[i].io_type; up->port.regshift = old_serial_port[i].iomem_reg_shift; set_io_from_upio(&up->port); - if (share_irqs) - up->port.irqflags |= IRQF_SHARED; + up->port.irqflags |= irqflag; } } @@ -2940,10 +2940,13 @@ static int __devinit serial8250_probe(struct platform_device *dev) { struct plat_serial8250_port *p = dev->dev.platform_data; struct uart_port port; - int ret, i; + int ret, i, irqflag = 0; memset(&port, 0, sizeof(struct uart_port)); + if (share_irqs) + irqflag = IRQF_SHARED; + for (i = 0; p && p->flags != 0; p++, i++) { port.iobase = p->iobase; port.membase = p->membase; @@ -2960,8 +2963,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) port.serial_in = p->serial_in; port.serial_out = p->serial_out; port.dev = &dev->dev; - if (share_irqs) - port.irqflags |= IRQF_SHARED; + port.irqflags |= irqflag; ret = serial8250_register_port(&port); if (ret < 0) { dev_err(&dev->dev, "unable to register port at index %d " diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index 4e5f3bde0461ca4c8eb4638bcc11643466c697ab..38a509c684cd297f0dfaa18bf67279bdfcd9d9b8 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h @@ -138,7 +138,6 @@ struct jsm_board u32 nasync; /* Number of ports on card */ u32 irq; /* Interrupt request number */ - u64 intr_count; /* Count of interrupts */ u64 membase; /* Start of base memory of the card */ u64 membase_end; /* End of base memory of the card */ @@ -206,8 +205,6 @@ struct jsm_channel { u64 ch_close_delay; /* How long we should drop RTS/DTR for */ - u64 ch_cpstime; /* Time for CPS calculations */ - tcflag_t ch_c_iflag; /* channel iflags */ tcflag_t ch_c_cflag; /* channel cflags */ tcflag_t ch_c_oflag; /* channel oflags */ @@ -215,11 +212,6 @@ struct jsm_channel { u8 ch_stopc; /* Stop character */ u8 ch_startc; /* Start character */ - u32 ch_old_baud; /* Cache of the current baud */ - u32 ch_custom_speed;/* Custom baud, if set */ - - u32 ch_wopen; /* Waiting for open process cnt */ - u8 ch_mostat; /* FEP output modem status */ u8 ch_mistat; /* FEP input modem status */ diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index b3604aa322a46ed5f7801f728c209cd67ce6c7ab..108c3e0471fd523ab849d7ebc58d702c0b3ac1d4 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c @@ -48,6 +48,17 @@ struct uart_driver jsm_uart_driver = { .nr = NR_PORTS, }; +static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state); +static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev); +static void jsm_io_resume(struct pci_dev *pdev); + +static struct pci_error_handlers jsm_err_handler = { + .error_detected = jsm_io_error_detected, + .slot_reset = jsm_io_slot_reset, + .resume = jsm_io_resume, +}; + int jsm_debug; module_param(jsm_debug, int, 0); MODULE_PARM_DESC(jsm_debug, "Driver debugging level"); @@ -123,7 +134,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device } rc = request_irq(brd->irq, brd->bd_ops->intr, - IRQF_DISABLED|IRQF_SHARED, "JSM", brd); + IRQF_SHARED, "JSM", brd); if (rc) { printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq); goto out_iounmap; @@ -164,6 +175,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device } pci_set_drvdata(pdev, brd); + pci_save_state(pdev); return 0; out_free_irq: @@ -222,8 +234,42 @@ static struct pci_driver jsm_driver = { .id_table = jsm_pci_tbl, .probe = jsm_probe_one, .remove = __devexit_p(jsm_remove_one), + .err_handler = &jsm_err_handler, }; +static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct jsm_board *brd = pci_get_drvdata(pdev); + + jsm_remove_uart_port(brd); + + return PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev) +{ + int rc; + + rc = pci_enable_device(pdev); + + if (rc) + return PCI_ERS_RESULT_DISCONNECT; + + pci_set_master(pdev); + + return PCI_ERS_RESULT_RECOVERED; +} + +static void jsm_io_resume(struct pci_dev *pdev) +{ + struct jsm_board *brd = pci_get_drvdata(pdev); + + pci_restore_state(pdev); + + jsm_uart_port_init(brd); +} + static int __init jsm_init_module(void) { int rc; diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c index b4b124e4828fc31f85de069a554c980f60ccad65..7960d9633c15a2a18ad53b57540b6d316ca010bf 100644 --- a/drivers/serial/jsm/jsm_neo.c +++ b/drivers/serial/jsm/jsm_neo.c @@ -954,13 +954,8 @@ static void neo_param(struct jsm_channel *ch) ch->ch_flags |= (CH_BAUD0); ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR); neo_assert_modem_signals(ch); - ch->ch_old_baud = 0; return; - } else if (ch->ch_custom_speed) { - baud = ch->ch_custom_speed; - if (ch->ch_flags & CH_BAUD0) - ch->ch_flags &= ~(CH_BAUD0); } else { int i; unsigned int cflag; @@ -1045,7 +1040,6 @@ static void neo_param(struct jsm_channel *ch) quot = ch->ch_bd->bd_dividend / baud; if (quot != 0) { - ch->ch_old_baud = baud; writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr); writeb((quot & 0xff), &ch->ch_neo_uart->txrx); writeb((quot >> 8), &ch->ch_neo_uart->ier); @@ -1123,8 +1117,6 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) unsigned long lock_flags2; int outofloop_count = 0; - brd->intr_count++; - /* Lock out the slow poller from running on this board. */ spin_lock_irqsave(&brd->bd_intr_lock, lock_flags); diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 7439c0373620b60f0351b2cccda143d1b023a642..cd95e215550d70fdeac7c1280264c94a327bc880 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c @@ -296,8 +296,6 @@ static void jsm_tty_close(struct uart_port *port) bd->bd_ops->assert_modem_signals(channel); } - channel->ch_old_baud = 0; - /* Turn off UART interrupts for this port */ channel->ch_bd->bd_ops->uart_off(channel); @@ -432,7 +430,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd) return 0; } -int __devinit jsm_uart_port_init(struct jsm_board *brd) +int jsm_uart_port_init(struct jsm_board *brd) { int i; unsigned int line; @@ -472,7 +470,7 @@ int __devinit jsm_uart_port_init(struct jsm_board *brd) if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port)) printk(KERN_INFO "jsm: add device failed\n"); else - printk(KERN_INFO "Added device \n"); + printk(KERN_INFO "jsm: Port %d added\n", i); } jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n"); diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index b8629d74f6a2818fb30a9ba7a0d9f5b82e9eae05..4a821046baae0124e6bb9a36824979d49e69952e 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -438,6 +438,7 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, unsigned char cval, fcr = 0; unsigned long flags; unsigned int baud, quot; + unsigned int dll; switch (termios->c_cflag & CSIZE) { case CS5: @@ -534,10 +535,18 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, else up->mcr &= ~UART_MCR_AFE; - serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ + serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ + + /* + * work around Errata #75 according to Intel(R) PXA27x Processor Family + * Specification Update (Nov 2005) + */ + dll = serial_in(up, UART_DLL); + WARN_ON(dll != (quot & 0xff)); + serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ - serial_out(up, UART_LCR, cval); /* reset DLAB */ + serial_out(up, UART_LCR, cval); /* reset DLAB */ up->lcr = cval; /* Save LCR */ serial_pxa_set_mctrl(&up->port, up->port.mctrl); serial_out(up, UART_FCR, fcr); diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index dcc72444e8e7015e904c70d726a83873dbeff21e..047530b285bb3a50ddf15d8804080980d9539978 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -342,11 +342,11 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, if (flags == UPF_SPD_HI) altbaud = 57600; - if (flags == UPF_SPD_VHI) + else if (flags == UPF_SPD_VHI) altbaud = 115200; - if (flags == UPF_SPD_SHI) + else if (flags == UPF_SPD_SHI) altbaud = 230400; - if (flags == UPF_SPD_WARP) + else if (flags == UPF_SPD_WARP) altbaud = 460800; for (try = 0; try < 2; try++) { @@ -1217,9 +1217,8 @@ static void uart_set_termios(struct tty_struct *tty, /* Handle transition to B0 status */ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR); - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { + else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { unsigned int mask = TIOCM_DTR; if (!(cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags)) @@ -1234,9 +1233,8 @@ static void uart_set_termios(struct tty_struct *tty, __uart_start(tty); spin_unlock_irqrestore(&state->uart_port->lock, flags); } - /* Handle turning on CRTSCTS */ - if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { + else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { spin_lock_irqsave(&state->uart_port->lock, flags); if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) { tty->hw_stopped = 1; @@ -2344,7 +2342,7 @@ static const struct tty_operations uart_ops = { */ int uart_register_driver(struct uart_driver *drv) { - struct tty_driver *normal = NULL; + struct tty_driver *normal; int i, retval; BUG_ON(drv->state); @@ -2354,13 +2352,12 @@ int uart_register_driver(struct uart_driver *drv) * we have a large number of ports to handle. */ drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); - retval = -ENOMEM; if (!drv->state) goto out; - normal = alloc_tty_driver(drv->nr); + normal = alloc_tty_driver(drv->nr); if (!normal) - goto out; + goto out_kfree; drv->tty_driver = normal; @@ -2393,12 +2390,14 @@ int uart_register_driver(struct uart_driver *drv) } retval = tty_register_driver(normal); - out: - if (retval < 0) { - put_tty_driver(normal); - kfree(drv->state); - } - return retval; + if (retval >= 0) + return retval; + + put_tty_driver(normal); +out_kfree: + kfree(drv->state); +out: + return -ENOMEM; } /** diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c index 46de564aaea0c15d61211dd3e7048f8117cf6fca..465f2fae1025ebeef99a7c7a657a14de23858341 100644 --- a/drivers/serial/ucc_uart.c +++ b/drivers/serial/ucc_uart.c @@ -1179,16 +1179,18 @@ static void uart_firmware_cont(const struct firmware *fw, void *context) if (firmware->header.length != fw->size) { dev_err(dev, "invalid firmware\n"); - return; + goto out; } ret = qe_upload_firmware(firmware); if (ret) { dev_err(dev, "could not load firmware\n"); - return; + goto out; } firmware_loaded = 1; + out: + release_firmware(fw); } static int ucc_uart_probe(struct of_device *ofdev, @@ -1247,7 +1249,7 @@ static int ucc_uart_probe(struct of_device *ofdev, */ ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, filename, &ofdev->dev, - &ofdev->dev, uart_firmware_cont); + GFP_KERNEL, &ofdev->dev, uart_firmware_cont); if (ret) { dev_err(&ofdev->dev, "could not load firmware %s\n", diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 4b6f7cba3b3dc536d6e8480d5c2b1e14523bb329..2d9d70359360719ea3851ee8ad33fba70f884635 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -133,6 +133,14 @@ config SPI_LM70_LLP which interfaces to an LM70 temperature sensor using a parallel port. +config SPI_MPC52xx + tristate "Freescale MPC52xx SPI (non-PSC) controller support" + depends on PPC_MPC52xx && SPI + select SPI_MASTER_OF + help + This drivers supports the MPC52xx SPI controller in master SPI + mode. + config SPI_MPC52xx_PSC tristate "Freescale MPC52xx PSC SPI controller" depends on PPC_MPC52xx && EXPERIMENTAL @@ -147,9 +155,6 @@ config SPI_MPC8xxx This enables using the Freescale MPC8xxx SPI controllers in master mode. - This driver uses a simple set of shift registers for data (opposed - to the CPM based descriptor model). - config SPI_OMAP_UWIRE tristate "OMAP1 MicroWire" depends on ARCH_OMAP1 @@ -164,6 +169,12 @@ config SPI_OMAP24XX SPI master controller for OMAP24xx/OMAP34xx Multichannel SPI (McSPI) modules. +config SPI_OMAP_100K + tristate "OMAP SPI 100K" + depends on SPI_MASTER && (ARCH_OMAP850 || ARCH_OMAP730) + help + OMAP SPI 100K master controller for omap7xx boards. + config SPI_ORION tristate "Orion SPI master (EXPERIMENTAL)" depends on PLAT_ORION && EXPERIMENTAL @@ -215,6 +226,13 @@ config SPI_S3C24XX_GPIO the inbuilt hardware cannot provide the transfer mode, or where the board is using non hardware connected pins. +config SPI_SH_MSIOF + tristate "SuperH MSIOF SPI controller" + depends on SUPERH && HAVE_CLK + select SPI_BITBANG + help + SPI driver for SuperH MSIOF blocks. + config SPI_SH_SCI tristate "SuperH SCI SPI controller" depends on SUPERH @@ -235,15 +253,38 @@ config SPI_TXX9 SPI driver for Toshiba TXx9 MIPS SoCs config SPI_XILINX - tristate "Xilinx SPI controller" - depends on (XILINX_VIRTEX || MICROBLAZE) && EXPERIMENTAL + tristate "Xilinx SPI controller common module" + depends on HAS_IOMEM && EXPERIMENTAL select SPI_BITBANG + select SPI_XILINX_OF if (XILINX_VIRTEX || MICROBLAZE) help This exposes the SPI controller IP from the Xilinx EDK. See the "OPB Serial Peripheral Interface (SPI) (v1.00e)" Product Specification document (DS464) for hardware details. + Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)" + +config SPI_XILINX_OF + tristate "Xilinx SPI controller OF device" + depends on SPI_XILINX && (XILINX_VIRTEX || MICROBLAZE) + help + This is the OF driver for the SPI controller IP from the Xilinx EDK. + +config SPI_XILINX_PLTFM + tristate "Xilinx SPI controller platform device" + depends on SPI_XILINX + help + This is the platform driver for the SPI controller IP + from the Xilinx EDK. + +config SPI_NUC900 + tristate "Nuvoton NUC900 series SPI" + depends on ARCH_W90X900 && EXPERIMENTAL + select SPI_BITBANG + help + SPI driver for Nuvoton NUC900 series ARM SoCs + # # Add new SPI master controllers in alphabetical order above this line # diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 21a118269cac1feb030b23977eb6dd454740345b..ed8c1675b52f8c1af6918eb016fe871b85ccf973 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -22,17 +22,23 @@ obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o +obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o obj-$(CONFIG_SPI_ORION) += orion_spi.o obj-$(CONFIG_SPI_PL022) += amba-pl022.o obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o +obj-$(CONFIG_SPI_MPC52xx) += mpc52xx_spi.o obj-$(CONFIG_SPI_MPC8xxx) += spi_mpc8xxx.o obj-$(CONFIG_SPI_PPC4xx) += spi_ppc4xx.o obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o obj-$(CONFIG_SPI_TXX9) += spi_txx9.o obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o +obj-$(CONFIG_SPI_XILINX_OF) += xilinx_spi_of.o +obj-$(CONFIG_SPI_XILINX_PLTFM) += xilinx_spi_pltfm.o obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o +obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o +obj-$(CONFIG_SPI_NUC900) += spi_nuc900.o # ... add above this line ... # SPI protocol drivers (device/link on bus) diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c index 76cbc1a66598a87ad32fcfbcd3207c59f296a175..cfd5ff9508fadd2f607d33495b5066cc34b1bbd1 100644 --- a/drivers/spi/au1550_spi.c +++ b/drivers/spi/au1550_spi.c @@ -237,8 +237,14 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t) unsigned bpw, hz; u32 cfg, stat; - bpw = t ? t->bits_per_word : spi->bits_per_word; - hz = t ? t->speed_hz : spi->max_speed_hz; + bpw = spi->bits_per_word; + hz = spi->max_speed_hz; + if (t) { + if (t->bits_per_word) + bpw = t->bits_per_word; + if (t->speed_hz) + hz = t->speed_hz; + } if (bpw < 4 || bpw > 24) { dev_err(&spi->dev, "setupxfer: invalid bits_per_word=%d\n", diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c index 1b74d5ca03f30dd849a7b394057ef694317d2cb2..f50c81df336a7831a76cdc85f92a1f3c2a7b7527 100644 --- a/drivers/spi/mpc52xx_psc_spi.c +++ b/drivers/spi/mpc52xx_psc_spi.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -313,11 +314,13 @@ static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps) struct mpc52xx_psc __iomem *psc = mps->psc; struct mpc52xx_psc_fifo __iomem *fifo = mps->fifo; u32 mclken_div; - int ret = 0; + int ret; /* default sysclk is 512MHz */ mclken_div = (mps->sysclk ? mps->sysclk : 512000000) / MCLK; - mpc52xx_set_psc_clkdiv(psc_id, mclken_div); + ret = mpc52xx_set_psc_clkdiv(psc_id, mclken_div); + if (ret) + return ret; /* Reset the PSC into a known state */ out_8(&psc->command, MPC52xx_PSC_RST_RX); @@ -341,7 +344,7 @@ static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps) mps->bits_per_word = 8; - return ret; + return 0; } static irqreturn_t mpc52xx_psc_spi_isr(int irq, void *dev_id) @@ -410,8 +413,10 @@ static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr, goto free_master; ret = mpc52xx_psc_spi_port_config(master->bus_num, mps); - if (ret < 0) + if (ret < 0) { + dev_err(dev, "can't configure PSC! Is it capable of SPI?\n"); goto free_irq; + } spin_lock_init(&mps->lock); init_completion(&mps->done); @@ -464,10 +469,11 @@ static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, const u32 *regaddr_p; u64 regaddr64, size64; s16 id = -1; + int rc; regaddr_p = of_get_address(op->node, 0, &size64, NULL); if (!regaddr_p) { - printk(KERN_ERR "Invalid PSC address\n"); + dev_err(&op->dev, "Invalid PSC address\n"); return -EINVAL; } regaddr64 = of_translate_address(op->node, regaddr_p); @@ -478,15 +484,18 @@ static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, psc_nump = of_get_property(op->node, "cell-index", NULL); if (!psc_nump || *psc_nump > 5) { - printk(KERN_ERR "mpc52xx_psc_spi: Device node %s has invalid " - "cell-index property\n", op->node->full_name); + dev_err(&op->dev, "Invalid cell-index property\n"); return -EINVAL; } id = *psc_nump + 1; } - return mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64, + rc = mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64, irq_of_parse_and_map(op->node, 0), id); + if (rc == 0) + of_register_spi_devices(dev_get_drvdata(&op->dev), op->node); + + return rc; } static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op) diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c new file mode 100644 index 0000000000000000000000000000000000000000..45bfe645817332f7a3754237815c263e909582ea --- /dev/null +++ b/drivers/spi/mpc52xx_spi.c @@ -0,0 +1,578 @@ +/* + * MPC52xx SPI bus driver. + * + * Copyright (C) 2008 Secret Lab Technologies Ltd. + * + * This file is released under the GPLv2 + * + * This is the driver for the MPC5200's dedicated SPI controller. + * + * Note: this driver does not support the MPC5200 PSC in SPI mode. For + * that driver see drivers/spi/mpc52xx_psc_spi.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Grant Likely "); +MODULE_DESCRIPTION("MPC52xx SPI (non-PSC) Driver"); +MODULE_LICENSE("GPL"); + +/* Register offsets */ +#define SPI_CTRL1 0x00 +#define SPI_CTRL1_SPIE (1 << 7) +#define SPI_CTRL1_SPE (1 << 6) +#define SPI_CTRL1_MSTR (1 << 4) +#define SPI_CTRL1_CPOL (1 << 3) +#define SPI_CTRL1_CPHA (1 << 2) +#define SPI_CTRL1_SSOE (1 << 1) +#define SPI_CTRL1_LSBFE (1 << 0) + +#define SPI_CTRL2 0x01 +#define SPI_BRR 0x04 + +#define SPI_STATUS 0x05 +#define SPI_STATUS_SPIF (1 << 7) +#define SPI_STATUS_WCOL (1 << 6) +#define SPI_STATUS_MODF (1 << 4) + +#define SPI_DATA 0x09 +#define SPI_PORTDATA 0x0d +#define SPI_DATADIR 0x10 + +/* FSM state return values */ +#define FSM_STOP 0 /* Nothing more for the state machine to */ + /* do. If something interesting happens */ + /* then an IRQ will be received */ +#define FSM_POLL 1 /* need to poll for completion, an IRQ is */ + /* not expected */ +#define FSM_CONTINUE 2 /* Keep iterating the state machine */ + +/* Driver internal data */ +struct mpc52xx_spi { + struct spi_master *master; + void __iomem *regs; + int irq0; /* MODF irq */ + int irq1; /* SPIF irq */ + unsigned int ipb_freq; + + /* Statistics; not used now, but will be reintroduced for debugfs */ + int msg_count; + int wcol_count; + int wcol_ticks; + u32 wcol_tx_timestamp; + int modf_count; + int byte_count; + + struct list_head queue; /* queue of pending messages */ + spinlock_t lock; + struct work_struct work; + + /* Details of current transfer (length, and buffer pointers) */ + struct spi_message *message; /* current message */ + struct spi_transfer *transfer; /* current transfer */ + int (*state)(int irq, struct mpc52xx_spi *ms, u8 status, u8 data); + int len; + int timestamp; + u8 *rx_buf; + const u8 *tx_buf; + int cs_change; + int gpio_cs_count; + unsigned int *gpio_cs; +}; + +/* + * CS control function + */ +static void mpc52xx_spi_chipsel(struct mpc52xx_spi *ms, int value) +{ + int cs; + + if (ms->gpio_cs_count > 0) { + cs = ms->message->spi->chip_select; + gpio_set_value(ms->gpio_cs[cs], value ? 0 : 1); + } else + out_8(ms->regs + SPI_PORTDATA, value ? 0 : 0x08); +} + +/* + * Start a new transfer. This is called both by the idle state + * for the first transfer in a message, and by the wait state when the + * previous transfer in a message is complete. + */ +static void mpc52xx_spi_start_transfer(struct mpc52xx_spi *ms) +{ + ms->rx_buf = ms->transfer->rx_buf; + ms->tx_buf = ms->transfer->tx_buf; + ms->len = ms->transfer->len; + + /* Activate the chip select */ + if (ms->cs_change) + mpc52xx_spi_chipsel(ms, 1); + ms->cs_change = ms->transfer->cs_change; + + /* Write out the first byte */ + ms->wcol_tx_timestamp = get_tbl(); + if (ms->tx_buf) + out_8(ms->regs + SPI_DATA, *ms->tx_buf++); + else + out_8(ms->regs + SPI_DATA, 0); +} + +/* Forward declaration of state handlers */ +static int mpc52xx_spi_fsmstate_transfer(int irq, struct mpc52xx_spi *ms, + u8 status, u8 data); +static int mpc52xx_spi_fsmstate_wait(int irq, struct mpc52xx_spi *ms, + u8 status, u8 data); + +/* + * IDLE state + * + * No transfers are in progress; if another transfer is pending then retrieve + * it and kick it off. Otherwise, stop processing the state machine + */ +static int +mpc52xx_spi_fsmstate_idle(int irq, struct mpc52xx_spi *ms, u8 status, u8 data) +{ + struct spi_device *spi; + int spr, sppr; + u8 ctrl1; + + if (status && (irq != NO_IRQ)) + dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n", + status); + + /* Check if there is another transfer waiting. */ + if (list_empty(&ms->queue)) + return FSM_STOP; + + /* get the head of the queue */ + ms->message = list_first_entry(&ms->queue, struct spi_message, queue); + list_del_init(&ms->message->queue); + + /* Setup the controller parameters */ + ctrl1 = SPI_CTRL1_SPIE | SPI_CTRL1_SPE | SPI_CTRL1_MSTR; + spi = ms->message->spi; + if (spi->mode & SPI_CPHA) + ctrl1 |= SPI_CTRL1_CPHA; + if (spi->mode & SPI_CPOL) + ctrl1 |= SPI_CTRL1_CPOL; + if (spi->mode & SPI_LSB_FIRST) + ctrl1 |= SPI_CTRL1_LSBFE; + out_8(ms->regs + SPI_CTRL1, ctrl1); + + /* Setup the controller speed */ + /* minimum divider is '2'. Also, add '1' to force rounding the + * divider up. */ + sppr = ((ms->ipb_freq / ms->message->spi->max_speed_hz) + 1) >> 1; + spr = 0; + if (sppr < 1) + sppr = 1; + while (((sppr - 1) & ~0x7) != 0) { + sppr = (sppr + 1) >> 1; /* add '1' to force rounding up */ + spr++; + } + sppr--; /* sppr quantity in register is offset by 1 */ + if (spr > 7) { + /* Don't overrun limits of SPI baudrate register */ + spr = 7; + sppr = 7; + } + out_8(ms->regs + SPI_BRR, sppr << 4 | spr); /* Set speed */ + + ms->cs_change = 1; + ms->transfer = container_of(ms->message->transfers.next, + struct spi_transfer, transfer_list); + + mpc52xx_spi_start_transfer(ms); + ms->state = mpc52xx_spi_fsmstate_transfer; + + return FSM_CONTINUE; +} + +/* + * TRANSFER state + * + * In the middle of a transfer. If the SPI core has completed processing + * a byte, then read out the received data and write out the next byte + * (unless this transfer is finished; in which case go on to the wait + * state) + */ +static int mpc52xx_spi_fsmstate_transfer(int irq, struct mpc52xx_spi *ms, + u8 status, u8 data) +{ + if (!status) + return ms->irq0 ? FSM_STOP : FSM_POLL; + + if (status & SPI_STATUS_WCOL) { + /* The SPI controller is stoopid. At slower speeds, it may + * raise the SPIF flag before the state machine is actually + * finished, which causes a collision (internal to the state + * machine only). The manual recommends inserting a delay + * between receiving the interrupt and sending the next byte, + * but it can also be worked around simply by retrying the + * transfer which is what we do here. */ + ms->wcol_count++; + ms->wcol_ticks += get_tbl() - ms->wcol_tx_timestamp; + ms->wcol_tx_timestamp = get_tbl(); + data = 0; + if (ms->tx_buf) + data = *(ms->tx_buf - 1); + out_8(ms->regs + SPI_DATA, data); /* try again */ + return FSM_CONTINUE; + } else if (status & SPI_STATUS_MODF) { + ms->modf_count++; + dev_err(&ms->master->dev, "mode fault\n"); + mpc52xx_spi_chipsel(ms, 0); + ms->message->status = -EIO; + ms->message->complete(ms->message->context); + ms->state = mpc52xx_spi_fsmstate_idle; + return FSM_CONTINUE; + } + + /* Read data out of the spi device */ + ms->byte_count++; + if (ms->rx_buf) + *ms->rx_buf++ = data; + + /* Is the transfer complete? */ + ms->len--; + if (ms->len == 0) { + ms->timestamp = get_tbl(); + ms->timestamp += ms->transfer->delay_usecs * tb_ticks_per_usec; + ms->state = mpc52xx_spi_fsmstate_wait; + return FSM_CONTINUE; + } + + /* Write out the next byte */ + ms->wcol_tx_timestamp = get_tbl(); + if (ms->tx_buf) + out_8(ms->regs + SPI_DATA, *ms->tx_buf++); + else + out_8(ms->regs + SPI_DATA, 0); + + return FSM_CONTINUE; +} + +/* + * WAIT state + * + * A transfer has completed; need to wait for the delay period to complete + * before starting the next transfer + */ +static int +mpc52xx_spi_fsmstate_wait(int irq, struct mpc52xx_spi *ms, u8 status, u8 data) +{ + if (status && irq) + dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n", + status); + + if (((int)get_tbl()) - ms->timestamp < 0) + return FSM_POLL; + + ms->message->actual_length += ms->transfer->len; + + /* Check if there is another transfer in this message. If there + * aren't then deactivate CS, notify sender, and drop back to idle + * to start the next message. */ + if (ms->transfer->transfer_list.next == &ms->message->transfers) { + ms->msg_count++; + mpc52xx_spi_chipsel(ms, 0); + ms->message->status = 0; + ms->message->complete(ms->message->context); + ms->state = mpc52xx_spi_fsmstate_idle; + return FSM_CONTINUE; + } + + /* There is another transfer; kick it off */ + + if (ms->cs_change) + mpc52xx_spi_chipsel(ms, 0); + + ms->transfer = container_of(ms->transfer->transfer_list.next, + struct spi_transfer, transfer_list); + mpc52xx_spi_start_transfer(ms); + ms->state = mpc52xx_spi_fsmstate_transfer; + return FSM_CONTINUE; +} + +/** + * mpc52xx_spi_fsm_process - Finite State Machine iteration function + * @irq: irq number that triggered the FSM or 0 for polling + * @ms: pointer to mpc52xx_spi driver data + */ +static void mpc52xx_spi_fsm_process(int irq, struct mpc52xx_spi *ms) +{ + int rc = FSM_CONTINUE; + u8 status, data; + + while (rc == FSM_CONTINUE) { + /* Interrupt cleared by read of STATUS followed by + * read of DATA registers */ + status = in_8(ms->regs + SPI_STATUS); + data = in_8(ms->regs + SPI_DATA); + rc = ms->state(irq, ms, status, data); + } + + if (rc == FSM_POLL) + schedule_work(&ms->work); +} + +/** + * mpc52xx_spi_irq - IRQ handler + */ +static irqreturn_t mpc52xx_spi_irq(int irq, void *_ms) +{ + struct mpc52xx_spi *ms = _ms; + spin_lock(&ms->lock); + mpc52xx_spi_fsm_process(irq, ms); + spin_unlock(&ms->lock); + return IRQ_HANDLED; +} + +/** + * mpc52xx_spi_wq - Workqueue function for polling the state machine + */ +static void mpc52xx_spi_wq(struct work_struct *work) +{ + struct mpc52xx_spi *ms = container_of(work, struct mpc52xx_spi, work); + unsigned long flags; + + spin_lock_irqsave(&ms->lock, flags); + mpc52xx_spi_fsm_process(0, ms); + spin_unlock_irqrestore(&ms->lock, flags); +} + +/* + * spi_master ops + */ + +static int mpc52xx_spi_setup(struct spi_device *spi) +{ + if (spi->bits_per_word % 8) + return -EINVAL; + + if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) + return -EINVAL; + + if (spi->chip_select >= spi->master->num_chipselect) + return -EINVAL; + + return 0; +} + +static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m) +{ + struct mpc52xx_spi *ms = spi_master_get_devdata(spi->master); + unsigned long flags; + + m->actual_length = 0; + m->status = -EINPROGRESS; + + spin_lock_irqsave(&ms->lock, flags); + list_add_tail(&m->queue, &ms->queue); + spin_unlock_irqrestore(&ms->lock, flags); + schedule_work(&ms->work); + + return 0; +} + +/* + * OF Platform Bus Binding + */ +static int __devinit mpc52xx_spi_probe(struct of_device *op, + const struct of_device_id *match) +{ + struct spi_master *master; + struct mpc52xx_spi *ms; + void __iomem *regs; + u8 ctrl1; + int rc, i = 0; + int gpio_cs; + + /* MMIO registers */ + dev_dbg(&op->dev, "probing mpc5200 SPI device\n"); + regs = of_iomap(op->node, 0); + if (!regs) + return -ENODEV; + + /* initialize the device */ + ctrl1 = SPI_CTRL1_SPIE | SPI_CTRL1_SPE | SPI_CTRL1_MSTR; + out_8(regs + SPI_CTRL1, ctrl1); + out_8(regs + SPI_CTRL2, 0x0); + out_8(regs + SPI_DATADIR, 0xe); /* Set output pins */ + out_8(regs + SPI_PORTDATA, 0x8); /* Deassert /SS signal */ + + /* Clear the status register and re-read it to check for a MODF + * failure. This driver cannot currently handle multiple masters + * on the SPI bus. This fault will also occur if the SPI signals + * are not connected to any pins (port_config setting) */ + in_8(regs + SPI_STATUS); + out_8(regs + SPI_CTRL1, ctrl1); + + in_8(regs + SPI_DATA); + if (in_8(regs + SPI_STATUS) & SPI_STATUS_MODF) { + dev_err(&op->dev, "mode fault; is port_config correct?\n"); + rc = -EIO; + goto err_init; + } + + dev_dbg(&op->dev, "allocating spi_master struct\n"); + master = spi_alloc_master(&op->dev, sizeof *ms); + if (!master) { + rc = -ENOMEM; + goto err_alloc; + } + + master->bus_num = -1; + master->setup = mpc52xx_spi_setup; + master->transfer = mpc52xx_spi_transfer; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; + + dev_set_drvdata(&op->dev, master); + + ms = spi_master_get_devdata(master); + ms->master = master; + ms->regs = regs; + ms->irq0 = irq_of_parse_and_map(op->node, 0); + ms->irq1 = irq_of_parse_and_map(op->node, 1); + ms->state = mpc52xx_spi_fsmstate_idle; + ms->ipb_freq = mpc5xxx_get_bus_frequency(op->node); + ms->gpio_cs_count = of_gpio_count(op->node); + if (ms->gpio_cs_count > 0) { + master->num_chipselect = ms->gpio_cs_count; + ms->gpio_cs = kmalloc(ms->gpio_cs_count * sizeof(unsigned int), + GFP_KERNEL); + if (!ms->gpio_cs) { + rc = -ENOMEM; + goto err_alloc; + } + + for (i = 0; i < ms->gpio_cs_count; i++) { + gpio_cs = of_get_gpio(op->node, i); + if (gpio_cs < 0) { + dev_err(&op->dev, + "could not parse the gpio field " + "in oftree\n"); + rc = -ENODEV; + goto err_gpio; + } + + rc = gpio_request(gpio_cs, dev_name(&op->dev)); + if (rc) { + dev_err(&op->dev, + "can't request spi cs gpio #%d " + "on gpio line %d\n", i, gpio_cs); + goto err_gpio; + } + + gpio_direction_output(gpio_cs, 1); + ms->gpio_cs[i] = gpio_cs; + } + } else { + master->num_chipselect = 1; + } + + spin_lock_init(&ms->lock); + INIT_LIST_HEAD(&ms->queue); + INIT_WORK(&ms->work, mpc52xx_spi_wq); + + /* Decide if interrupts can be used */ + if (ms->irq0 && ms->irq1) { + rc = request_irq(ms->irq0, mpc52xx_spi_irq, 0, + "mpc5200-spi-modf", ms); + rc |= request_irq(ms->irq1, mpc52xx_spi_irq, 0, + "mpc5200-spi-spif", ms); + if (rc) { + free_irq(ms->irq0, ms); + free_irq(ms->irq1, ms); + ms->irq0 = ms->irq1 = 0; + } + } else { + /* operate in polled mode */ + ms->irq0 = ms->irq1 = 0; + } + + if (!ms->irq0) + dev_info(&op->dev, "using polled mode\n"); + + dev_dbg(&op->dev, "registering spi_master struct\n"); + rc = spi_register_master(master); + if (rc) + goto err_register; + + of_register_spi_devices(master, op->node); + dev_info(&ms->master->dev, "registered MPC5200 SPI bus\n"); + + return rc; + + err_register: + dev_err(&ms->master->dev, "initialization failed\n"); + spi_master_put(master); + err_gpio: + while (i-- > 0) + gpio_free(ms->gpio_cs[i]); + + kfree(ms->gpio_cs); + err_alloc: + err_init: + iounmap(regs); + return rc; +} + +static int __devexit mpc52xx_spi_remove(struct of_device *op) +{ + struct spi_master *master = dev_get_drvdata(&op->dev); + struct mpc52xx_spi *ms = spi_master_get_devdata(master); + int i; + + free_irq(ms->irq0, ms); + free_irq(ms->irq1, ms); + + for (i = 0; i < ms->gpio_cs_count; i++) + gpio_free(ms->gpio_cs[i]); + + kfree(ms->gpio_cs); + spi_unregister_master(master); + spi_master_put(master); + iounmap(ms->regs); + + return 0; +} + +static struct of_device_id mpc52xx_spi_match[] __devinitdata = { + { .compatible = "fsl,mpc5200-spi", }, + {} +}; +MODULE_DEVICE_TABLE(of, mpc52xx_spi_match); + +static struct of_platform_driver mpc52xx_spi_of_driver = { + .owner = THIS_MODULE, + .name = "mpc52xx-spi", + .match_table = mpc52xx_spi_match, + .probe = mpc52xx_spi_probe, + .remove = __exit_p(mpc52xx_spi_remove), +}; + +static int __init mpc52xx_spi_init(void) +{ + return of_register_platform_driver(&mpc52xx_spi_of_driver); +} +module_init(mpc52xx_spi_init); + +static void __exit mpc52xx_spi_exit(void) +{ + of_unregister_platform_driver(&mpc52xx_spi_of_driver); +} +module_exit(mpc52xx_spi_exit); + diff --git a/drivers/spi/omap_spi_100k.c b/drivers/spi/omap_spi_100k.c new file mode 100644 index 0000000000000000000000000000000000000000..5355d90d1bee10fc08a2a3728d1836f6d1a82696 --- /dev/null +++ b/drivers/spi/omap_spi_100k.c @@ -0,0 +1,635 @@ +/* + * OMAP7xx SPI 100k controller driver + * Author: Fabrice Crohas + * from original omap1_mcspi driver + * + * Copyright (C) 2005, 2006 Nokia Corporation + * Author: Samuel Ortiz and + * Juha Yrj�l� + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * 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 + +#define OMAP1_SPI100K_MAX_FREQ 48000000 + +#define ICR_SPITAS (OMAP7XX_ICR_BASE + 0x12) + +#define SPI_SETUP1 0x00 +#define SPI_SETUP2 0x02 +#define SPI_CTRL 0x04 +#define SPI_STATUS 0x06 +#define SPI_TX_LSB 0x08 +#define SPI_TX_MSB 0x0a +#define SPI_RX_LSB 0x0c +#define SPI_RX_MSB 0x0e + +#define SPI_SETUP1_INT_READ_ENABLE (1UL << 5) +#define SPI_SETUP1_INT_WRITE_ENABLE (1UL << 4) +#define SPI_SETUP1_CLOCK_DIVISOR(x) ((x) << 1) +#define SPI_SETUP1_CLOCK_ENABLE (1UL << 0) + +#define SPI_SETUP2_ACTIVE_EDGE_FALLING (0UL << 0) +#define SPI_SETUP2_ACTIVE_EDGE_RISING (1UL << 0) +#define SPI_SETUP2_NEGATIVE_LEVEL (0UL << 5) +#define SPI_SETUP2_POSITIVE_LEVEL (1UL << 5) +#define SPI_SETUP2_LEVEL_TRIGGER (0UL << 10) +#define SPI_SETUP2_EDGE_TRIGGER (1UL << 10) + +#define SPI_CTRL_SEN(x) ((x) << 7) +#define SPI_CTRL_WORD_SIZE(x) (((x) - 1) << 2) +#define SPI_CTRL_WR (1UL << 1) +#define SPI_CTRL_RD (1UL << 0) + +#define SPI_STATUS_WE (1UL << 1) +#define SPI_STATUS_RD (1UL << 0) + +#define WRITE 0 +#define READ 1 + + +/* use PIO for small transfers, avoiding DMA setup/teardown overhead and + * cache operations; better heuristics consider wordsize and bitrate. + */ +#define DMA_MIN_BYTES 8 + +#define SPI_RUNNING 0 +#define SPI_SHUTDOWN 1 + +struct omap1_spi100k { + struct work_struct work; + + /* lock protects queue and registers */ + spinlock_t lock; + struct list_head msg_queue; + struct spi_master *master; + struct clk *ick; + struct clk *fck; + + /* Virtual base address of the controller */ + void __iomem *base; + + /* State of the SPI */ + unsigned int state; +}; + +struct omap1_spi100k_cs { + void __iomem *base; + int word_len; +}; + +static struct workqueue_struct *omap1_spi100k_wq; + +#define MOD_REG_BIT(val, mask, set) do { \ + if (set) \ + val |= mask; \ + else \ + val &= ~mask; \ +} while (0) + +static void spi100k_enable_clock(struct spi_master *master) +{ + unsigned int val; + struct omap1_spi100k *spi100k = spi_master_get_devdata(master); + + /* enable SPI */ + val = readw(spi100k->base + SPI_SETUP1); + val |= SPI_SETUP1_CLOCK_ENABLE; + writew(val, spi100k->base + SPI_SETUP1); +} + +static void spi100k_disable_clock(struct spi_master *master) +{ + unsigned int val; + struct omap1_spi100k *spi100k = spi_master_get_devdata(master); + + /* disable SPI */ + val = readw(spi100k->base + SPI_SETUP1); + val &= ~SPI_SETUP1_CLOCK_ENABLE; + writew(val, spi100k->base + SPI_SETUP1); +} + +static void spi100k_write_data(struct spi_master *master, int len, int data) +{ + struct omap1_spi100k *spi100k = spi_master_get_devdata(master); + + /* write 16-bit word */ + spi100k_enable_clock(master); + writew( data , spi100k->base + SPI_TX_MSB); + + writew(SPI_CTRL_SEN(0) | + SPI_CTRL_WORD_SIZE(len) | + SPI_CTRL_WR, + spi100k->base + SPI_CTRL); + + /* Wait for bit ack send change */ + while((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_WE) != SPI_STATUS_WE); + udelay(1000); + + spi100k_disable_clock(master); +} + +static int spi100k_read_data(struct spi_master *master, int len) +{ + int dataH,dataL; + struct omap1_spi100k *spi100k = spi_master_get_devdata(master); + + spi100k_enable_clock(master); + writew(SPI_CTRL_SEN(0) | + SPI_CTRL_WORD_SIZE(len) | + SPI_CTRL_RD, + spi100k->base + SPI_CTRL); + + while((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_RD) != SPI_STATUS_RD); + udelay(1000); + + dataL = readw(spi100k->base + SPI_RX_LSB); + dataH = readw(spi100k->base + SPI_RX_MSB); + spi100k_disable_clock(master); + + return dataL; +} + +static void spi100k_open(struct spi_master *master) +{ + /* get control of SPI */ + struct omap1_spi100k *spi100k = spi_master_get_devdata(master); + + writew(SPI_SETUP1_INT_READ_ENABLE | + SPI_SETUP1_INT_WRITE_ENABLE | + SPI_SETUP1_CLOCK_DIVISOR(0), spi100k->base + SPI_SETUP1); + + /* configure clock and interrupts */ + writew(SPI_SETUP2_ACTIVE_EDGE_FALLING | + SPI_SETUP2_NEGATIVE_LEVEL | + SPI_SETUP2_LEVEL_TRIGGER, spi100k->base + SPI_SETUP2); +} + +static void omap1_spi100k_force_cs(struct omap1_spi100k *spi100k, int enable) +{ + if (enable) + writew(0x05fc, spi100k->base + SPI_CTRL); + else + writew(0x05fd, spi100k->base + SPI_CTRL); +} + +static unsigned +omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) +{ + struct omap1_spi100k *spi100k; + struct omap1_spi100k_cs *cs = spi->controller_state; + unsigned int count, c; + int word_len; + + spi100k = spi_master_get_devdata(spi->master); + count = xfer->len; + c = count; + word_len = cs->word_len; + + /* RX_ONLY mode needs dummy data in TX reg */ + if (xfer->tx_buf == NULL) + spi100k_write_data(spi->master,word_len, 0); + + if (word_len <= 8) { + u8 *rx; + const u8 *tx; + + rx = xfer->rx_buf; + tx = xfer->tx_buf; + do { + c-=1; + if (xfer->tx_buf != NULL) + spi100k_write_data(spi->master,word_len, *tx); + if (xfer->rx_buf != NULL) + *rx = spi100k_read_data(spi->master,word_len); + } while(c); + } else if (word_len <= 16) { + u16 *rx; + const u16 *tx; + + rx = xfer->rx_buf; + tx = xfer->tx_buf; + do { + c-=2; + if (xfer->tx_buf != NULL) + spi100k_write_data(spi->master,word_len, *tx++); + if (xfer->rx_buf != NULL) + *rx++ = spi100k_read_data(spi->master,word_len); + } while(c); + } else if (word_len <= 32) { + u32 *rx; + const u32 *tx; + + rx = xfer->rx_buf; + tx = xfer->tx_buf; + do { + c-=4; + if (xfer->tx_buf != NULL) + spi100k_write_data(spi->master,word_len, *tx); + if (xfer->rx_buf != NULL) + *rx = spi100k_read_data(spi->master,word_len); + } while(c); + } + return count - c; +} + +/* called only when no transfer is active to this device */ +static int omap1_spi100k_setup_transfer(struct spi_device *spi, + struct spi_transfer *t) +{ + struct omap1_spi100k *spi100k = spi_master_get_devdata(spi->master); + struct omap1_spi100k_cs *cs = spi->controller_state; + u8 word_len = spi->bits_per_word; + + if (t != NULL && t->bits_per_word) + word_len = t->bits_per_word; + if (!word_len) + word_len = 8; + + if (spi->bits_per_word > 32) + return -EINVAL; + cs->word_len = word_len; + + /* SPI init before transfer */ + writew(0x3e , spi100k->base + SPI_SETUP1); + writew(0x00 , spi100k->base + SPI_STATUS); + writew(0x3e , spi100k->base + SPI_CTRL); + + return 0; +} + +/* the spi->mode bits understood by this driver: */ +#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) + +static int omap1_spi100k_setup(struct spi_device *spi) +{ + int ret; + struct omap1_spi100k *spi100k; + struct omap1_spi100k_cs *cs = spi->controller_state; + + if (spi->bits_per_word < 4 || spi->bits_per_word > 32) { + dev_dbg(&spi->dev, "setup: unsupported %d bit words\n", + spi->bits_per_word); + return -EINVAL; + } + + spi100k = spi_master_get_devdata(spi->master); + + if (!cs) { + cs = kzalloc(sizeof *cs, GFP_KERNEL); + if (!cs) + return -ENOMEM; + cs->base = spi100k->base + spi->chip_select * 0x14; + spi->controller_state = cs; + } + + spi100k_open(spi->master); + + clk_enable(spi100k->ick); + clk_enable(spi100k->fck); + + ret = omap1_spi100k_setup_transfer(spi, NULL); + + clk_disable(spi100k->ick); + clk_disable(spi100k->fck); + + return ret; +} + +static void omap1_spi100k_work(struct work_struct *work) +{ + struct omap1_spi100k *spi100k; + int status = 0; + + spi100k = container_of(work, struct omap1_spi100k, work); + spin_lock_irq(&spi100k->lock); + + clk_enable(spi100k->ick); + clk_enable(spi100k->fck); + + /* We only enable one channel at a time -- the one whose message is + * at the head of the queue -- although this controller would gladly + * arbitrate among multiple channels. This corresponds to "single + * channel" master mode. As a side effect, we need to manage the + * chipselect with the FORCE bit ... CS != channel enable. + */ + while (!list_empty(&spi100k->msg_queue)) { + struct spi_message *m; + struct spi_device *spi; + struct spi_transfer *t = NULL; + int cs_active = 0; + struct omap1_spi100k_cs *cs; + int par_override = 0; + + m = container_of(spi100k->msg_queue.next, struct spi_message, + queue); + + list_del_init(&m->queue); + spin_unlock_irq(&spi100k->lock); + + spi = m->spi; + cs = spi->controller_state; + + list_for_each_entry(t, &m->transfers, transfer_list) { + if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { + status = -EINVAL; + break; + } + if (par_override || t->speed_hz || t->bits_per_word) { + par_override = 1; + status = omap1_spi100k_setup_transfer(spi, t); + if (status < 0) + break; + if (!t->speed_hz && !t->bits_per_word) + par_override = 0; + } + + if (!cs_active) { + omap1_spi100k_force_cs(spi100k, 1); + cs_active = 1; + } + + if (t->len) { + unsigned count; + + /* RX_ONLY mode needs dummy data in TX reg */ + if (t->tx_buf == NULL) + spi100k_write_data(spi->master, 8, 0); + + count = omap1_spi100k_txrx_pio(spi, t); + m->actual_length += count; + + if (count != t->len) { + status = -EIO; + break; + } + } + + if (t->delay_usecs) + udelay(t->delay_usecs); + + /* ignore the "leave it on after last xfer" hint */ + + if (t->cs_change) { + omap1_spi100k_force_cs(spi100k, 0); + cs_active = 0; + } + } + + /* Restore defaults if they were overriden */ + if (par_override) { + par_override = 0; + status = omap1_spi100k_setup_transfer(spi, NULL); + } + + if (cs_active) + omap1_spi100k_force_cs(spi100k, 0); + + m->status = status; + m->complete(m->context); + + spin_lock_irq(&spi100k->lock); + } + + clk_disable(spi100k->ick); + clk_disable(spi100k->fck); + spin_unlock_irq(&spi100k->lock); + + if (status < 0) + printk(KERN_WARNING "spi transfer failed with %d\n", status); +} + +static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m) +{ + struct omap1_spi100k *spi100k; + unsigned long flags; + struct spi_transfer *t; + + m->actual_length = 0; + m->status = -EINPROGRESS; + + spi100k = spi_master_get_devdata(spi->master); + + /* Don't accept new work if we're shutting down */ + if (spi100k->state == SPI_SHUTDOWN) + return -ESHUTDOWN; + + /* reject invalid messages and transfers */ + if (list_empty(&m->transfers) || !m->complete) + return -EINVAL; + + list_for_each_entry(t, &m->transfers, transfer_list) { + const void *tx_buf = t->tx_buf; + void *rx_buf = t->rx_buf; + unsigned len = t->len; + + if (t->speed_hz > OMAP1_SPI100K_MAX_FREQ + || (len && !(rx_buf || tx_buf)) + || (t->bits_per_word && + ( t->bits_per_word < 4 + || t->bits_per_word > 32))) { + dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", + t->speed_hz, + len, + tx_buf ? "tx" : "", + rx_buf ? "rx" : "", + t->bits_per_word); + return -EINVAL; + } + + if (t->speed_hz && t->speed_hz < OMAP1_SPI100K_MAX_FREQ/(1<<16)) { + dev_dbg(&spi->dev, "%d Hz max exceeds %d\n", + t->speed_hz, + OMAP1_SPI100K_MAX_FREQ/(1<<16)); + return -EINVAL; + } + + } + + spin_lock_irqsave(&spi100k->lock, flags); + list_add_tail(&m->queue, &spi100k->msg_queue); + queue_work(omap1_spi100k_wq, &spi100k->work); + spin_unlock_irqrestore(&spi100k->lock, flags); + + return 0; +} + +static int __init omap1_spi100k_reset(struct omap1_spi100k *spi100k) +{ + return 0; +} + +static int __devinit omap1_spi100k_probe(struct platform_device *pdev) +{ + struct spi_master *master; + struct omap1_spi100k *spi100k; + int status = 0; + + if (!pdev->id) + return -EINVAL; + + master = spi_alloc_master(&pdev->dev, sizeof *spi100k); + if (master == NULL) { + dev_dbg(&pdev->dev, "master allocation failed\n"); + return -ENOMEM; + } + + if (pdev->id != -1) + master->bus_num = pdev->id; + + master->setup = omap1_spi100k_setup; + master->transfer = omap1_spi100k_transfer; + master->cleanup = NULL; + master->num_chipselect = 2; + master->mode_bits = MODEBITS; + + dev_set_drvdata(&pdev->dev, master); + + spi100k = spi_master_get_devdata(master); + spi100k->master = master; + + /* + * The memory region base address is taken as the platform_data. + * You should allocate this with ioremap() before initializing + * the SPI. + */ + spi100k->base = (void __iomem *) pdev->dev.platform_data; + + INIT_WORK(&spi100k->work, omap1_spi100k_work); + + spin_lock_init(&spi100k->lock); + INIT_LIST_HEAD(&spi100k->msg_queue); + spi100k->ick = clk_get(&pdev->dev, "ick"); + if (IS_ERR(spi100k->ick)) { + dev_dbg(&pdev->dev, "can't get spi100k_ick\n"); + status = PTR_ERR(spi100k->ick); + goto err1; + } + + spi100k->fck = clk_get(&pdev->dev, "fck"); + if (IS_ERR(spi100k->fck)) { + dev_dbg(&pdev->dev, "can't get spi100k_fck\n"); + status = PTR_ERR(spi100k->fck); + goto err2; + } + + if (omap1_spi100k_reset(spi100k) < 0) + goto err3; + + status = spi_register_master(master); + if (status < 0) + goto err3; + + spi100k->state = SPI_RUNNING; + + return status; + +err3: + clk_put(spi100k->fck); +err2: + clk_put(spi100k->ick); +err1: + spi_master_put(master); + return status; +} + +static int __exit omap1_spi100k_remove(struct platform_device *pdev) +{ + struct spi_master *master; + struct omap1_spi100k *spi100k; + struct resource *r; + unsigned limit = 500; + unsigned long flags; + int status = 0; + + master = dev_get_drvdata(&pdev->dev); + spi100k = spi_master_get_devdata(master); + + spin_lock_irqsave(&spi100k->lock, flags); + + spi100k->state = SPI_SHUTDOWN; + while (!list_empty(&spi100k->msg_queue) && limit--) { + spin_unlock_irqrestore(&spi100k->lock, flags); + msleep(10); + spin_lock_irqsave(&spi100k->lock, flags); + } + + if (!list_empty(&spi100k->msg_queue)) + status = -EBUSY; + + spin_unlock_irqrestore(&spi100k->lock, flags); + + if (status != 0) + return status; + + clk_put(spi100k->fck); + clk_put(spi100k->ick); + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + spi_unregister_master(master); + + return 0; +} + +static struct platform_driver omap1_spi100k_driver = { + .driver = { + .name = "omap1_spi100k", + .owner = THIS_MODULE, + }, + .remove = __exit_p(omap1_spi100k_remove), +}; + + +static int __init omap1_spi100k_init(void) +{ + omap1_spi100k_wq = create_singlethread_workqueue( + omap1_spi100k_driver.driver.name); + + if (omap1_spi100k_wq == NULL) + return -1; + + return platform_driver_probe(&omap1_spi100k_driver, omap1_spi100k_probe); +} + +static void __exit omap1_spi100k_exit(void) +{ + platform_driver_unregister(&omap1_spi100k_driver); + + destroy_workqueue(omap1_spi100k_wq); +} + +module_init(omap1_spi100k_init); +module_exit(omap1_spi100k_exit); + +MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver"); +MODULE_AUTHOR("Fabrice Crohas "); +MODULE_LICENSE("GPL"); + diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index 89c22efedfb0db8102339a06a35847205424771a..1893f1e96dc4906da0a92d1d4de38492781faa53 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c @@ -44,6 +44,9 @@ #define MXC_CSPIINT 0x0c #define MXC_RESET 0x1c +#define MX3_CSPISTAT 0x14 +#define MX3_CSPISTAT_RR (1 << 3) + /* generic defines to abstract from the different register layouts */ #define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */ #define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */ @@ -205,7 +208,7 @@ static int mx31_config(struct spi_imx_data *spi_imx, if (cpu_is_mx31()) reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT; - else if (cpu_is_mx35()) { + else if (cpu_is_mx25() || cpu_is_mx35()) { reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT; reg |= MX31_CSPICTRL_SSCTL; } @@ -219,7 +222,7 @@ static int mx31_config(struct spi_imx_data *spi_imx, if (config->cs < 0) { if (cpu_is_mx31()) reg |= (config->cs + 32) << MX31_CSPICTRL_CS_SHIFT; - else if (cpu_is_mx35()) + else if (cpu_is_mx25() || cpu_is_mx35()) reg |= (config->cs + 32) << MX35_CSPICTRL_CS_SHIFT; } @@ -481,7 +484,7 @@ static void spi_imx_cleanup(struct spi_device *spi) { } -static int __init spi_imx_probe(struct platform_device *pdev) +static int __devinit spi_imx_probe(struct platform_device *pdev) { struct spi_imx_master *mxc_platform_info; struct spi_master *master; @@ -489,7 +492,7 @@ static int __init spi_imx_probe(struct platform_device *pdev) struct resource *res; int i, ret; - mxc_platform_info = (struct spi_imx_master *)pdev->dev.platform_data; + mxc_platform_info = dev_get_platdata(&pdev->dev); if (!mxc_platform_info) { dev_err(&pdev->dev, "can't get the platform data\n"); return -EINVAL; @@ -513,11 +516,12 @@ static int __init spi_imx_probe(struct platform_device *pdev) continue; ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME); if (ret) { - i--; - while (i > 0) + while (i > 0) { + i--; if (spi_imx->chipselect[i] >= 0) - gpio_free(spi_imx->chipselect[i--]); - dev_err(&pdev->dev, "can't get cs gpios"); + gpio_free(spi_imx->chipselect[i]); + } + dev_err(&pdev->dev, "can't get cs gpios\n"); goto out_master_put; } } @@ -551,7 +555,7 @@ static int __init spi_imx_probe(struct platform_device *pdev) } spi_imx->irq = platform_get_irq(pdev, 0); - if (!spi_imx->irq) { + if (spi_imx->irq <= 0) { ret = -EINVAL; goto out_iounmap; } @@ -562,7 +566,7 @@ static int __init spi_imx_probe(struct platform_device *pdev) goto out_iounmap; } - if (cpu_is_mx31() || cpu_is_mx35()) { + if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35()) { spi_imx->intctrl = mx31_intctrl; spi_imx->config = mx31_config; spi_imx->trigger = mx31_trigger; @@ -590,9 +594,14 @@ static int __init spi_imx_probe(struct platform_device *pdev) clk_enable(spi_imx->clk); spi_imx->spi_clk = clk_get_rate(spi_imx->clk); - if (!cpu_is_mx31() || !cpu_is_mx35()) + if (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27()) writel(1, spi_imx->base + MXC_RESET); + /* drain receive buffer */ + if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35()) + while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR) + readl(spi_imx->base + MXC_CSPIRXDATA); + spi_imx->intctrl(spi_imx, 0); ret = spi_bitbang_start(&spi_imx->bitbang); @@ -625,7 +634,7 @@ out_master_put: return ret; } -static int __exit spi_imx_remove(struct platform_device *pdev) +static int __devexit spi_imx_remove(struct platform_device *pdev) { struct spi_master *master = platform_get_drvdata(pdev); struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -659,7 +668,7 @@ static struct platform_driver spi_imx_driver = { .owner = THIS_MODULE, }, .probe = spi_imx_probe, - .remove = __exit_p(spi_imx_remove), + .remove = __devexit_p(spi_imx_remove), }; static int __init spi_imx_init(void) diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c index 0fd0ec4d3a7d1899e742a5d7005f4f986eab7293..e9390d747bfcf35e018747fcfc6a1b2e529ef486 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_mpc8xxx.c @@ -5,6 +5,10 @@ * * Copyright (C) 2006 Polycom, Inc. * + * CPM SPI and QE buffer descriptors mode support: + * Copyright (c) 2009 MontaVista Software, Inc. + * Author: Anton Vorontsov + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -27,6 +31,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -34,8 +41,19 @@ #include #include +#include +#include #include +/* CPM1 and CPM2 are mutually exclusive. */ +#ifdef CONFIG_CPM1 +#include +#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0) +#else +#include +#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0) +#endif + /* SPI Controller registers */ struct mpc8xxx_spi_reg { u8 res1[0x20]; @@ -47,6 +65,28 @@ struct mpc8xxx_spi_reg { __be32 receive; }; +/* SPI Parameter RAM */ +struct spi_pram { + __be16 rbase; /* Rx Buffer descriptor base address */ + __be16 tbase; /* Tx Buffer descriptor base address */ + u8 rfcr; /* Rx function code */ + u8 tfcr; /* Tx function code */ + __be16 mrblr; /* Max receive buffer length */ + __be32 rstate; /* Internal */ + __be32 rdp; /* Internal */ + __be16 rbptr; /* Internal */ + __be16 rbc; /* Internal */ + __be32 rxtmp; /* Internal */ + __be32 tstate; /* Internal */ + __be32 tdp; /* Internal */ + __be16 tbptr; /* Internal */ + __be16 tbc; /* Internal */ + __be32 txtmp; /* Internal */ + __be32 res; /* Tx temp. */ + __be16 rpbase; /* Relocation pointer (CPM1 only) */ + __be16 res1; /* Reserved */ +}; + /* SPI Controller mode register definitions */ #define SPMODE_LOOP (1 << 30) #define SPMODE_CI_INACTIVEHIGH (1 << 29) @@ -75,14 +115,40 @@ struct mpc8xxx_spi_reg { #define SPIM_NE 0x00000200 /* Not empty */ #define SPIM_NF 0x00000100 /* Not full */ +#define SPIE_TXB 0x00000200 /* Last char is written to tx fifo */ +#define SPIE_RXB 0x00000100 /* Last char is written to rx buf */ + +/* SPCOM register values */ +#define SPCOM_STR (1 << 23) /* Start transmit */ + +#define SPI_PRAM_SIZE 0x100 +#define SPI_MRBLR ((unsigned int)PAGE_SIZE) + /* SPI Controller driver's private data. */ struct mpc8xxx_spi { + struct device *dev; struct mpc8xxx_spi_reg __iomem *base; /* rx & tx bufs from the spi_transfer */ const void *tx; void *rx; + int subblock; + struct spi_pram __iomem *pram; + struct cpm_buf_desc __iomem *tx_bd; + struct cpm_buf_desc __iomem *rx_bd; + + struct spi_transfer *xfer_in_progress; + + /* dma addresses for CPM transfers */ + dma_addr_t tx_dma; + dma_addr_t rx_dma; + bool map_tx_dma; + bool map_rx_dma; + + dma_addr_t dma_dummy_tx; + dma_addr_t dma_dummy_rx; + /* functions to deal with different sized buffers */ void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *); u32(*get_tx) (struct mpc8xxx_spi *); @@ -96,7 +162,7 @@ struct mpc8xxx_spi { u32 rx_shift; /* RX data reg shift when in qe mode */ u32 tx_shift; /* TX data reg shift when in qe mode */ - bool qe_mode; + unsigned int flags; struct workqueue_struct *workqueue; struct work_struct work; @@ -107,6 +173,10 @@ struct mpc8xxx_spi { struct completion done; }; +static void *mpc8xxx_dummy_rx; +static DEFINE_MUTEX(mpc8xxx_dummy_rx_lock); +static int mpc8xxx_dummy_rx_refcnt; + struct spi_mpc8xxx_cs { /* functions to deal with different sized buffers */ void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *); @@ -155,6 +225,42 @@ MPC83XX_SPI_TX_BUF(u8) MPC83XX_SPI_TX_BUF(u16) MPC83XX_SPI_TX_BUF(u32) +static void mpc8xxx_spi_change_mode(struct spi_device *spi) +{ + struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); + struct spi_mpc8xxx_cs *cs = spi->controller_state; + __be32 __iomem *mode = &mspi->base->mode; + unsigned long flags; + + if (cs->hw_mode == mpc8xxx_spi_read_reg(mode)) + return; + + /* Turn off IRQs locally to minimize time that SPI is disabled. */ + local_irq_save(flags); + + /* Turn off SPI unit prior changing mode */ + mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE); + mpc8xxx_spi_write_reg(mode, cs->hw_mode); + + /* When in CPM mode, we need to reinit tx and rx. */ + if (mspi->flags & SPI_CPM_MODE) { + if (mspi->flags & SPI_QE) { + qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock, + QE_CR_PROTOCOL_UNSPECIFIED, 0); + } else { + cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX); + if (mspi->flags & SPI_CPM1) { + out_be16(&mspi->pram->rbptr, + in_be16(&mspi->pram->rbase)); + out_be16(&mspi->pram->tbptr, + in_be16(&mspi->pram->tbase)); + } + } + } + + local_irq_restore(flags); +} + static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value) { struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); @@ -168,27 +274,13 @@ static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value) } if (value == BITBANG_CS_ACTIVE) { - u32 regval = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode); - mpc8xxx_spi->rx_shift = cs->rx_shift; mpc8xxx_spi->tx_shift = cs->tx_shift; mpc8xxx_spi->get_rx = cs->get_rx; mpc8xxx_spi->get_tx = cs->get_tx; - if (cs->hw_mode != regval) { - unsigned long flags; - __be32 __iomem *mode = &mpc8xxx_spi->base->mode; - - regval = cs->hw_mode; - /* Turn off IRQs locally to minimize time that - * SPI is disabled - */ - local_irq_save(flags); - /* Turn off SPI unit prior changing mode */ - mpc8xxx_spi_write_reg(mode, regval & ~SPMODE_ENABLE); - mpc8xxx_spi_write_reg(mode, regval); - local_irq_restore(flags); - } + mpc8xxx_spi_change_mode(spi); + if (pdata->cs_control) pdata->cs_control(spi, pol); } @@ -198,7 +290,6 @@ static int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { struct mpc8xxx_spi *mpc8xxx_spi; - u32 regval; u8 bits_per_word, pm; u32 hz; struct spi_mpc8xxx_cs *cs = spi->controller_state; @@ -230,14 +321,14 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) if (bits_per_word <= 8) { cs->get_rx = mpc8xxx_spi_rx_buf_u8; cs->get_tx = mpc8xxx_spi_tx_buf_u8; - if (mpc8xxx_spi->qe_mode) { + if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { cs->rx_shift = 16; cs->tx_shift = 24; } } else if (bits_per_word <= 16) { cs->get_rx = mpc8xxx_spi_rx_buf_u16; cs->get_tx = mpc8xxx_spi_tx_buf_u16; - if (mpc8xxx_spi->qe_mode) { + if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { cs->rx_shift = 16; cs->tx_shift = 16; } @@ -247,7 +338,8 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) } else return -EINVAL; - if (mpc8xxx_spi->qe_mode && spi->mode & SPI_LSB_FIRST) { + if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE && + spi->mode & SPI_LSB_FIRST) { cs->tx_shift = 0; if (bits_per_word <= 8) cs->rx_shift = 8; @@ -286,37 +378,138 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) pm--; cs->hw_mode |= SPMODE_PM(pm); - regval = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode); - if (cs->hw_mode != regval) { - unsigned long flags; - __be32 __iomem *mode = &mpc8xxx_spi->base->mode; - - regval = cs->hw_mode; - /* Turn off IRQs locally to minimize time - * that SPI is disabled - */ - local_irq_save(flags); - /* Turn off SPI unit prior changing mode */ - mpc8xxx_spi_write_reg(mode, regval & ~SPMODE_ENABLE); - mpc8xxx_spi_write_reg(mode, regval); - local_irq_restore(flags); + + mpc8xxx_spi_change_mode(spi); + return 0; +} + +static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi) +{ + struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd; + struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd; + unsigned int xfer_len = min(mspi->count, SPI_MRBLR); + unsigned int xfer_ofs; + + xfer_ofs = mspi->xfer_in_progress->len - mspi->count; + + out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs); + out_be16(&rx_bd->cbd_datlen, 0); + out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP); + + out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs); + out_be16(&tx_bd->cbd_datlen, xfer_len); + out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP | + BD_SC_LAST); + + /* start transfer */ + mpc8xxx_spi_write_reg(&mspi->base->command, SPCOM_STR); +} + +static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi, + struct spi_transfer *t, bool is_dma_mapped) +{ + struct device *dev = mspi->dev; + + if (is_dma_mapped) { + mspi->map_tx_dma = 0; + mspi->map_rx_dma = 0; + } else { + mspi->map_tx_dma = 1; + mspi->map_rx_dma = 1; + } + + if (!t->tx_buf) { + mspi->tx_dma = mspi->dma_dummy_tx; + mspi->map_tx_dma = 0; + } + + if (!t->rx_buf) { + mspi->rx_dma = mspi->dma_dummy_rx; + mspi->map_rx_dma = 0; } + + if (mspi->map_tx_dma) { + void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */ + + mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, mspi->tx_dma)) { + dev_err(dev, "unable to map tx dma\n"); + return -ENOMEM; + } + } else { + mspi->tx_dma = t->tx_dma; + } + + if (mspi->map_rx_dma) { + mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len, + DMA_FROM_DEVICE); + if (dma_mapping_error(dev, mspi->rx_dma)) { + dev_err(dev, "unable to map rx dma\n"); + goto err_rx_dma; + } + } else { + mspi->rx_dma = t->rx_dma; + } + + /* enable rx ints */ + mpc8xxx_spi_write_reg(&mspi->base->mask, SPIE_RXB); + + mspi->xfer_in_progress = t; + mspi->count = t->len; + + /* start CPM transfers */ + mpc8xxx_spi_cpm_bufs_start(mspi); + return 0; + +err_rx_dma: + if (mspi->map_tx_dma) + dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE); + return -ENOMEM; } -static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t) +static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi) { - struct mpc8xxx_spi *mpc8xxx_spi; - u32 word, len, bits_per_word; + struct device *dev = mspi->dev; + struct spi_transfer *t = mspi->xfer_in_progress; + + if (mspi->map_tx_dma) + dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE); + if (mspi->map_tx_dma) + dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE); + mspi->xfer_in_progress = NULL; +} - mpc8xxx_spi = spi_master_get_devdata(spi->master); +static int mpc8xxx_spi_cpu_bufs(struct mpc8xxx_spi *mspi, + struct spi_transfer *t, unsigned int len) +{ + u32 word; + + mspi->count = len; + + /* enable rx ints */ + mpc8xxx_spi_write_reg(&mspi->base->mask, SPIM_NE); + + /* transmit word */ + word = mspi->get_tx(mspi); + mpc8xxx_spi_write_reg(&mspi->base->transmit, word); + + return 0; +} + +static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t, + bool is_dma_mapped) +{ + struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); + unsigned int len = t->len; + u8 bits_per_word; + int ret; - mpc8xxx_spi->tx = t->tx_buf; - mpc8xxx_spi->rx = t->rx_buf; bits_per_word = spi->bits_per_word; if (t->bits_per_word) bits_per_word = t->bits_per_word; - len = t->len; + if (bits_per_word > 8) { /* invalid length? */ if (len & 1) @@ -329,22 +522,27 @@ static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t) return -EINVAL; len /= 2; } - mpc8xxx_spi->count = len; - INIT_COMPLETION(mpc8xxx_spi->done); + mpc8xxx_spi->tx = t->tx_buf; + mpc8xxx_spi->rx = t->rx_buf; - /* enable rx ints */ - mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, SPIM_NE); + INIT_COMPLETION(mpc8xxx_spi->done); - /* transmit word */ - word = mpc8xxx_spi->get_tx(mpc8xxx_spi); - mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->transmit, word); + if (mpc8xxx_spi->flags & SPI_CPM_MODE) + ret = mpc8xxx_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped); + else + ret = mpc8xxx_spi_cpu_bufs(mpc8xxx_spi, t, len); + if (ret) + return ret; wait_for_completion(&mpc8xxx_spi->done); /* disable rx ints */ mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0); + if (mpc8xxx_spi->flags & SPI_CPM_MODE) + mpc8xxx_spi_cpm_bufs_complete(mpc8xxx_spi); + return mpc8xxx_spi->count; } @@ -375,7 +573,7 @@ static void mpc8xxx_spi_do_one_msg(struct spi_message *m) } cs_change = t->cs_change; if (t->len) - status = mpc8xxx_spi_bufs(spi, t); + status = mpc8xxx_spi_bufs(spi, t, m->is_dma_mapped); if (status) { status = -EMSGSIZE; break; @@ -464,45 +662,80 @@ static int mpc8xxx_spi_setup(struct spi_device *spi) return 0; } -static irqreturn_t mpc8xxx_spi_irq(s32 irq, void *context_data) +static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events) { - struct mpc8xxx_spi *mpc8xxx_spi = context_data; - u32 event; - irqreturn_t ret = IRQ_NONE; + u16 len; - /* Get interrupt events(tx/rx) */ - event = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->event); + dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__, + in_be16(&mspi->rx_bd->cbd_datlen), mspi->count); - /* We need handle RX first */ - if (event & SPIE_NE) { - u32 rx_data = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->receive); + len = in_be16(&mspi->rx_bd->cbd_datlen); + if (len > mspi->count) { + WARN_ON(1); + len = mspi->count; + } - if (mpc8xxx_spi->rx) - mpc8xxx_spi->get_rx(rx_data, mpc8xxx_spi); + /* Clear the events */ + mpc8xxx_spi_write_reg(&mspi->base->event, events); - ret = IRQ_HANDLED; + mspi->count -= len; + if (mspi->count) + mpc8xxx_spi_cpm_bufs_start(mspi); + else + complete(&mspi->done); +} + +static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) +{ + /* We need handle RX first */ + if (events & SPIE_NE) { + u32 rx_data = mpc8xxx_spi_read_reg(&mspi->base->receive); + + if (mspi->rx) + mspi->get_rx(rx_data, mspi); } - if ((event & SPIE_NF) == 0) + if ((events & SPIE_NF) == 0) /* spin until TX is done */ - while (((event = - mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->event)) & + while (((events = + mpc8xxx_spi_read_reg(&mspi->base->event)) & SPIE_NF) == 0) cpu_relax(); - mpc8xxx_spi->count -= 1; - if (mpc8xxx_spi->count) { - u32 word = mpc8xxx_spi->get_tx(mpc8xxx_spi); - mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->transmit, word); + /* Clear the events */ + mpc8xxx_spi_write_reg(&mspi->base->event, events); + + mspi->count -= 1; + if (mspi->count) { + u32 word = mspi->get_tx(mspi); + + mpc8xxx_spi_write_reg(&mspi->base->transmit, word); } else { - complete(&mpc8xxx_spi->done); + complete(&mspi->done); } +} - /* Clear the events */ - mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->event, event); +static irqreturn_t mpc8xxx_spi_irq(s32 irq, void *context_data) +{ + struct mpc8xxx_spi *mspi = context_data; + irqreturn_t ret = IRQ_NONE; + u32 events; + + /* Get interrupt events(tx/rx) */ + events = mpc8xxx_spi_read_reg(&mspi->base->event); + if (events) + ret = IRQ_HANDLED; + + dev_dbg(mspi->dev, "%s: events %x\n", __func__, events); + + if (mspi->flags & SPI_CPM_MODE) + mpc8xxx_spi_cpm_irq(mspi, events); + else + mpc8xxx_spi_cpu_irq(mspi, events); return ret; } + static int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m) { @@ -526,6 +759,215 @@ static void mpc8xxx_spi_cleanup(struct spi_device *spi) kfree(spi->controller_state); } +static void *mpc8xxx_spi_alloc_dummy_rx(void) +{ + mutex_lock(&mpc8xxx_dummy_rx_lock); + + if (!mpc8xxx_dummy_rx) + mpc8xxx_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL); + if (mpc8xxx_dummy_rx) + mpc8xxx_dummy_rx_refcnt++; + + mutex_unlock(&mpc8xxx_dummy_rx_lock); + + return mpc8xxx_dummy_rx; +} + +static void mpc8xxx_spi_free_dummy_rx(void) +{ + mutex_lock(&mpc8xxx_dummy_rx_lock); + + switch (mpc8xxx_dummy_rx_refcnt) { + case 0: + WARN_ON(1); + break; + case 1: + kfree(mpc8xxx_dummy_rx); + mpc8xxx_dummy_rx = NULL; + /* fall through */ + default: + mpc8xxx_dummy_rx_refcnt--; + break; + } + + mutex_unlock(&mpc8xxx_dummy_rx_lock); +} + +static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi) +{ + struct device *dev = mspi->dev; + struct device_node *np = dev_archdata_get_node(&dev->archdata); + const u32 *iprop; + int size; + unsigned long spi_base_ofs; + unsigned long pram_ofs = -ENOMEM; + + /* Can't use of_address_to_resource(), QE muram isn't at 0. */ + iprop = of_get_property(np, "reg", &size); + + /* QE with a fixed pram location? */ + if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4) + return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE); + + /* QE but with a dynamic pram location? */ + if (mspi->flags & SPI_QE) { + pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64); + qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock, + QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs); + return pram_ofs; + } + + /* CPM1 and CPM2 pram must be at a fixed addr. */ + if (!iprop || size != sizeof(*iprop) * 4) + return -ENOMEM; + + spi_base_ofs = cpm_muram_alloc_fixed(iprop[2], 2); + if (IS_ERR_VALUE(spi_base_ofs)) + return -ENOMEM; + + if (mspi->flags & SPI_CPM2) { + pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64); + if (!IS_ERR_VALUE(pram_ofs)) { + u16 __iomem *spi_base = cpm_muram_addr(spi_base_ofs); + + out_be16(spi_base, pram_ofs); + } + } else { + struct spi_pram __iomem *pram = cpm_muram_addr(spi_base_ofs); + u16 rpbase = in_be16(&pram->rpbase); + + /* Microcode relocation patch applied? */ + if (rpbase) + pram_ofs = rpbase; + else + return spi_base_ofs; + } + + cpm_muram_free(spi_base_ofs); + return pram_ofs; +} + +static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi) +{ + struct device *dev = mspi->dev; + struct device_node *np = dev_archdata_get_node(&dev->archdata); + const u32 *iprop; + int size; + unsigned long pram_ofs; + unsigned long bds_ofs; + + if (!(mspi->flags & SPI_CPM_MODE)) + return 0; + + if (!mpc8xxx_spi_alloc_dummy_rx()) + return -ENOMEM; + + if (mspi->flags & SPI_QE) { + iprop = of_get_property(np, "cell-index", &size); + if (iprop && size == sizeof(*iprop)) + mspi->subblock = *iprop; + + switch (mspi->subblock) { + default: + dev_warn(dev, "cell-index unspecified, assuming SPI1"); + /* fall through */ + case 0: + mspi->subblock = QE_CR_SUBBLOCK_SPI1; + break; + case 1: + mspi->subblock = QE_CR_SUBBLOCK_SPI2; + break; + } + } + + pram_ofs = mpc8xxx_spi_cpm_get_pram(mspi); + if (IS_ERR_VALUE(pram_ofs)) { + dev_err(dev, "can't allocate spi parameter ram\n"); + goto err_pram; + } + + bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) + + sizeof(*mspi->rx_bd), 8); + if (IS_ERR_VALUE(bds_ofs)) { + dev_err(dev, "can't allocate bds\n"); + goto err_bds; + } + + mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, mspi->dma_dummy_tx)) { + dev_err(dev, "unable to map dummy tx buffer\n"); + goto err_dummy_tx; + } + + mspi->dma_dummy_rx = dma_map_single(dev, mpc8xxx_dummy_rx, SPI_MRBLR, + DMA_FROM_DEVICE); + if (dma_mapping_error(dev, mspi->dma_dummy_rx)) { + dev_err(dev, "unable to map dummy rx buffer\n"); + goto err_dummy_rx; + } + + mspi->pram = cpm_muram_addr(pram_ofs); + + mspi->tx_bd = cpm_muram_addr(bds_ofs); + mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd)); + + /* Initialize parameter ram. */ + out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd)); + out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd)); + out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL); + out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL); + out_be16(&mspi->pram->mrblr, SPI_MRBLR); + out_be32(&mspi->pram->rstate, 0); + out_be32(&mspi->pram->rdp, 0); + out_be16(&mspi->pram->rbptr, 0); + out_be16(&mspi->pram->rbc, 0); + out_be32(&mspi->pram->rxtmp, 0); + out_be32(&mspi->pram->tstate, 0); + out_be32(&mspi->pram->tdp, 0); + out_be16(&mspi->pram->tbptr, 0); + out_be16(&mspi->pram->tbc, 0); + out_be32(&mspi->pram->txtmp, 0); + + return 0; + +err_dummy_rx: + dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE); +err_dummy_tx: + cpm_muram_free(bds_ofs); +err_bds: + cpm_muram_free(pram_ofs); +err_pram: + mpc8xxx_spi_free_dummy_rx(); + return -ENOMEM; +} + +static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi) +{ + struct device *dev = mspi->dev; + + dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE); + dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE); + cpm_muram_free(cpm_muram_offset(mspi->tx_bd)); + cpm_muram_free(cpm_muram_offset(mspi->pram)); + mpc8xxx_spi_free_dummy_rx(); +} + +static const char *mpc8xxx_spi_strmode(unsigned int flags) +{ + if (flags & SPI_QE_CPU_MODE) { + return "QE CPU"; + } else if (flags & SPI_CPM_MODE) { + if (flags & SPI_QE) + return "QE"; + else if (flags & SPI_CPM2) + return "CPM2"; + else + return "CPM1"; + } + return "CPU"; +} + static struct spi_master * __devinit mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) { @@ -552,14 +994,19 @@ mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) master->cleanup = mpc8xxx_spi_cleanup; mpc8xxx_spi = spi_master_get_devdata(master); - mpc8xxx_spi->qe_mode = pdata->qe_mode; + mpc8xxx_spi->dev = dev; mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8; mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8; + mpc8xxx_spi->flags = pdata->flags; mpc8xxx_spi->spibrg = pdata->sysclk; + ret = mpc8xxx_spi_cpm_init(mpc8xxx_spi); + if (ret) + goto err_cpm_init; + mpc8xxx_spi->rx_shift = 0; mpc8xxx_spi->tx_shift = 0; - if (mpc8xxx_spi->qe_mode) { + if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { mpc8xxx_spi->rx_shift = 16; mpc8xxx_spi->tx_shift = 24; } @@ -569,7 +1016,7 @@ mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) mpc8xxx_spi->base = ioremap(mem->start, mem->end - mem->start + 1); if (mpc8xxx_spi->base == NULL) { ret = -ENOMEM; - goto put_master; + goto err_ioremap; } mpc8xxx_spi->irq = irq; @@ -592,7 +1039,7 @@ mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) /* Enable SPI interface */ regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; - if (pdata->qe_mode) + if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) regval |= SPMODE_OP; mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, regval); @@ -612,9 +1059,8 @@ mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) if (ret < 0) goto unreg_master; - printk(KERN_INFO - "%s: MPC8xxx SPI Controller driver at 0x%p (irq = %d)\n", - dev_name(dev), mpc8xxx_spi->base, mpc8xxx_spi->irq); + dev_info(dev, "at 0x%p (irq = %d), %s mode\n", mpc8xxx_spi->base, + mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags)); return master; @@ -624,7 +1070,9 @@ free_irq: free_irq(mpc8xxx_spi->irq, mpc8xxx_spi); unmap_io: iounmap(mpc8xxx_spi->base); -put_master: +err_ioremap: + mpc8xxx_spi_cpm_free(mpc8xxx_spi); +err_cpm_init: spi_master_put(master); err: return ERR_PTR(ret); @@ -644,6 +1092,7 @@ static int __devexit mpc8xxx_spi_remove(struct device *dev) free_irq(mpc8xxx_spi->irq, mpc8xxx_spi); iounmap(mpc8xxx_spi->base); + mpc8xxx_spi_cpm_free(mpc8xxx_spi); return 0; } @@ -709,6 +1158,7 @@ static int of_mpc8xxx_spi_get_chipselects(struct device *dev) gpio = of_get_gpio_flags(np, i, &flags); if (!gpio_is_valid(gpio)) { dev_err(dev, "invalid gpio #%d: %d\n", i, gpio); + ret = gpio; goto err_loop; } @@ -804,7 +1254,13 @@ static int __devinit of_mpc8xxx_spi_probe(struct of_device *ofdev, prop = of_get_property(np, "mode", NULL); if (prop && !strcmp(prop, "cpu-qe")) - pdata->qe_mode = 1; + pdata->flags = SPI_QE_CPU_MODE; + else if (prop && !strcmp(prop, "qe")) + pdata->flags = SPI_CPM_MODE | SPI_QE; + else if (of_device_is_compatible(np, "fsl,cpm2-spi")) + pdata->flags = SPI_CPM_MODE | SPI_CPM2; + else if (of_device_is_compatible(np, "fsl,cpm1-spi")) + pdata->flags = SPI_CPM_MODE | SPI_CPM1; ret = of_mpc8xxx_spi_get_chipselects(dev); if (ret) @@ -900,7 +1356,7 @@ static int __devexit plat_mpc8xxx_spi_remove(struct platform_device *pdev) MODULE_ALIAS("platform:mpc8xxx_spi"); static struct platform_driver mpc8xxx_spi_driver = { .probe = plat_mpc8xxx_spi_probe, - .remove = __exit_p(plat_mpc8xxx_spi_remove), + .remove = __devexit_p(plat_mpc8xxx_spi_remove), .driver = { .name = "mpc8xxx_spi", .owner = THIS_MODULE, diff --git a/drivers/spi/spi_nuc900.c b/drivers/spi/spi_nuc900.c new file mode 100644 index 0000000000000000000000000000000000000000..b319f9bf9b9b902012ef33998d6e14f95d196ec7 --- /dev/null +++ b/drivers/spi/spi_nuc900.c @@ -0,0 +1,504 @@ +/* linux/drivers/spi/spi_nuc900.c + * + * Copyright (c) 2009 Nuvoton technology. + * Wan ZongShun + * + * 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 + +/* usi registers offset */ +#define USI_CNT 0x00 +#define USI_DIV 0x04 +#define USI_SSR 0x08 +#define USI_RX0 0x10 +#define USI_TX0 0x10 + +/* usi register bit */ +#define ENINT (0x01 << 17) +#define ENFLG (0x01 << 16) +#define TXNUM (0x03 << 8) +#define TXNEG (0x01 << 2) +#define RXNEG (0x01 << 1) +#define LSB (0x01 << 10) +#define SELECTLEV (0x01 << 2) +#define SELECTPOL (0x01 << 31) +#define SELECTSLAVE 0x01 +#define GOBUSY 0x01 + +struct nuc900_spi { + struct spi_bitbang bitbang; + struct completion done; + void __iomem *regs; + int irq; + int len; + int count; + const unsigned char *tx; + unsigned char *rx; + struct clk *clk; + struct resource *ioarea; + struct spi_master *master; + struct spi_device *curdev; + struct device *dev; + struct nuc900_spi_info *pdata; + spinlock_t lock; + struct resource *res; +}; + +static inline struct nuc900_spi *to_hw(struct spi_device *sdev) +{ + return spi_master_get_devdata(sdev->master); +} + +static void nuc900_slave_select(struct spi_device *spi, unsigned int ssr) +{ + struct nuc900_spi *hw = to_hw(spi); + unsigned int val; + unsigned int cs = spi->mode & SPI_CS_HIGH ? 1 : 0; + unsigned int cpol = spi->mode & SPI_CPOL ? 1 : 0; + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + + val = __raw_readl(hw->regs + USI_SSR); + + if (!cs) + val &= ~SELECTLEV; + else + val |= SELECTLEV; + + if (!ssr) + val &= ~SELECTSLAVE; + else + val |= SELECTSLAVE; + + __raw_writel(val, hw->regs + USI_SSR); + + val = __raw_readl(hw->regs + USI_CNT); + + if (!cpol) + val &= ~SELECTPOL; + else + val |= SELECTPOL; + + __raw_writel(val, hw->regs + USI_CNT); + + spin_unlock_irqrestore(&hw->lock, flags); +} + +static void nuc900_spi_chipsel(struct spi_device *spi, int value) +{ + switch (value) { + case BITBANG_CS_INACTIVE: + nuc900_slave_select(spi, 0); + break; + + case BITBANG_CS_ACTIVE: + nuc900_slave_select(spi, 1); + break; + } +} + +static void nuc900_spi_setup_txnum(struct nuc900_spi *hw, + unsigned int txnum) +{ + unsigned int val; + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + + val = __raw_readl(hw->regs + USI_CNT); + + if (!txnum) + val &= ~TXNUM; + else + val |= txnum << 0x08; + + __raw_writel(val, hw->regs + USI_CNT); + + spin_unlock_irqrestore(&hw->lock, flags); + +} + +static void nuc900_spi_setup_txbitlen(struct nuc900_spi *hw, + unsigned int txbitlen) +{ + unsigned int val; + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + + val = __raw_readl(hw->regs + USI_CNT); + + val |= (txbitlen << 0x03); + + __raw_writel(val, hw->regs + USI_CNT); + + spin_unlock_irqrestore(&hw->lock, flags); +} + +static void nuc900_spi_gobusy(struct nuc900_spi *hw) +{ + unsigned int val; + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + + val = __raw_readl(hw->regs + USI_CNT); + + val |= GOBUSY; + + __raw_writel(val, hw->regs + USI_CNT); + + spin_unlock_irqrestore(&hw->lock, flags); +} + +static int nuc900_spi_setupxfer(struct spi_device *spi, + struct spi_transfer *t) +{ + return 0; +} + +static int nuc900_spi_setup(struct spi_device *spi) +{ + return 0; +} + +static inline unsigned int hw_txbyte(struct nuc900_spi *hw, int count) +{ + return hw->tx ? hw->tx[count] : 0; +} + +static int nuc900_spi_txrx(struct spi_device *spi, struct spi_transfer *t) +{ + struct nuc900_spi *hw = to_hw(spi); + + hw->tx = t->tx_buf; + hw->rx = t->rx_buf; + hw->len = t->len; + hw->count = 0; + + __raw_writel(hw_txbyte(hw, 0x0), hw->regs + USI_TX0); + + nuc900_spi_gobusy(hw); + + wait_for_completion(&hw->done); + + return hw->count; +} + +static irqreturn_t nuc900_spi_irq(int irq, void *dev) +{ + struct nuc900_spi *hw = dev; + unsigned int status; + unsigned int count = hw->count; + + status = __raw_readl(hw->regs + USI_CNT); + __raw_writel(status, hw->regs + USI_CNT); + + if (status & ENFLG) { + hw->count++; + + if (hw->rx) + hw->rx[count] = __raw_readl(hw->regs + USI_RX0); + count++; + + if (count < hw->len) { + __raw_writel(hw_txbyte(hw, count), hw->regs + USI_TX0); + nuc900_spi_gobusy(hw); + } else { + complete(&hw->done); + } + + return IRQ_HANDLED; + } + + complete(&hw->done); + return IRQ_HANDLED; +} + +static void nuc900_tx_edge(struct nuc900_spi *hw, unsigned int edge) +{ + unsigned int val; + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + + val = __raw_readl(hw->regs + USI_CNT); + + if (edge) + val |= TXNEG; + else + val &= ~TXNEG; + __raw_writel(val, hw->regs + USI_CNT); + + spin_unlock_irqrestore(&hw->lock, flags); +} + +static void nuc900_rx_edge(struct nuc900_spi *hw, unsigned int edge) +{ + unsigned int val; + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + + val = __raw_readl(hw->regs + USI_CNT); + + if (edge) + val |= RXNEG; + else + val &= ~RXNEG; + __raw_writel(val, hw->regs + USI_CNT); + + spin_unlock_irqrestore(&hw->lock, flags); +} + +static void nuc900_send_first(struct nuc900_spi *hw, unsigned int lsb) +{ + unsigned int val; + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + + val = __raw_readl(hw->regs + USI_CNT); + + if (lsb) + val |= LSB; + else + val &= ~LSB; + __raw_writel(val, hw->regs + USI_CNT); + + spin_unlock_irqrestore(&hw->lock, flags); +} + +static void nuc900_set_sleep(struct nuc900_spi *hw, unsigned int sleep) +{ + unsigned int val; + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + + val = __raw_readl(hw->regs + USI_CNT); + + if (sleep) + val |= (sleep << 12); + else + val &= ~(0x0f << 12); + __raw_writel(val, hw->regs + USI_CNT); + + spin_unlock_irqrestore(&hw->lock, flags); +} + +static void nuc900_enable_int(struct nuc900_spi *hw) +{ + unsigned int val; + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + + val = __raw_readl(hw->regs + USI_CNT); + + val |= ENINT; + + __raw_writel(val, hw->regs + USI_CNT); + + spin_unlock_irqrestore(&hw->lock, flags); +} + +static void nuc900_set_divider(struct nuc900_spi *hw) +{ + __raw_writel(hw->pdata->divider, hw->regs + USI_DIV); +} + +static void nuc900_init_spi(struct nuc900_spi *hw) +{ + clk_enable(hw->clk); + spin_lock_init(&hw->lock); + + nuc900_tx_edge(hw, hw->pdata->txneg); + nuc900_rx_edge(hw, hw->pdata->rxneg); + nuc900_send_first(hw, hw->pdata->lsb); + nuc900_set_sleep(hw, hw->pdata->sleep); + nuc900_spi_setup_txbitlen(hw, hw->pdata->txbitlen); + nuc900_spi_setup_txnum(hw, hw->pdata->txnum); + nuc900_set_divider(hw); + nuc900_enable_int(hw); +} + +static int __devinit nuc900_spi_probe(struct platform_device *pdev) +{ + struct nuc900_spi *hw; + struct spi_master *master; + int err = 0; + + master = spi_alloc_master(&pdev->dev, sizeof(struct nuc900_spi)); + if (master == NULL) { + dev_err(&pdev->dev, "No memory for spi_master\n"); + err = -ENOMEM; + goto err_nomem; + } + + hw = spi_master_get_devdata(master); + memset(hw, 0, sizeof(struct nuc900_spi)); + + hw->master = spi_master_get(master); + hw->pdata = pdev->dev.platform_data; + hw->dev = &pdev->dev; + + if (hw->pdata == NULL) { + dev_err(&pdev->dev, "No platform data supplied\n"); + err = -ENOENT; + goto err_pdata; + } + + platform_set_drvdata(pdev, hw); + init_completion(&hw->done); + + master->mode_bits = SPI_MODE_0; + master->num_chipselect = hw->pdata->num_cs; + master->bus_num = hw->pdata->bus_num; + hw->bitbang.master = hw->master; + hw->bitbang.setup_transfer = nuc900_spi_setupxfer; + hw->bitbang.chipselect = nuc900_spi_chipsel; + hw->bitbang.txrx_bufs = nuc900_spi_txrx; + hw->bitbang.master->setup = nuc900_spi_setup; + + hw->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (hw->res == NULL) { + dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); + err = -ENOENT; + goto err_pdata; + } + + hw->ioarea = request_mem_region(hw->res->start, + resource_size(hw->res), pdev->name); + + if (hw->ioarea == NULL) { + dev_err(&pdev->dev, "Cannot reserve region\n"); + err = -ENXIO; + goto err_pdata; + } + + hw->regs = ioremap(hw->res->start, resource_size(hw->res)); + if (hw->regs == NULL) { + dev_err(&pdev->dev, "Cannot map IO\n"); + err = -ENXIO; + goto err_iomap; + } + + hw->irq = platform_get_irq(pdev, 0); + if (hw->irq < 0) { + dev_err(&pdev->dev, "No IRQ specified\n"); + err = -ENOENT; + goto err_irq; + } + + err = request_irq(hw->irq, nuc900_spi_irq, 0, pdev->name, hw); + if (err) { + dev_err(&pdev->dev, "Cannot claim IRQ\n"); + goto err_irq; + } + + hw->clk = clk_get(&pdev->dev, "spi"); + if (IS_ERR(hw->clk)) { + dev_err(&pdev->dev, "No clock for device\n"); + err = PTR_ERR(hw->clk); + goto err_clk; + } + + mfp_set_groupg(&pdev->dev); + nuc900_init_spi(hw); + + err = spi_bitbang_start(&hw->bitbang); + if (err) { + dev_err(&pdev->dev, "Failed to register SPI master\n"); + goto err_register; + } + + return 0; + +err_register: + clk_disable(hw->clk); + clk_put(hw->clk); +err_clk: + free_irq(hw->irq, hw); +err_irq: + iounmap(hw->regs); +err_iomap: + release_mem_region(hw->res->start, resource_size(hw->res)); + kfree(hw->ioarea); +err_pdata: + spi_master_put(hw->master);; + +err_nomem: + return err; +} + +static int __devexit nuc900_spi_remove(struct platform_device *dev) +{ + struct nuc900_spi *hw = platform_get_drvdata(dev); + + free_irq(hw->irq, hw); + + platform_set_drvdata(dev, NULL); + + spi_unregister_master(hw->master); + + clk_disable(hw->clk); + clk_put(hw->clk); + + iounmap(hw->regs); + + release_mem_region(hw->res->start, resource_size(hw->res)); + kfree(hw->ioarea); + + spi_master_put(hw->master); + return 0; +} + +static struct platform_driver nuc900_spi_driver = { + .probe = nuc900_spi_probe, + .remove = __devexit_p(nuc900_spi_remove), + .driver = { + .name = "nuc900-spi", + .owner = THIS_MODULE, + }, +}; + +static int __init nuc900_spi_init(void) +{ + return platform_driver_register(&nuc900_spi_driver); +} + +static void __exit nuc900_spi_exit(void) +{ + platform_driver_unregister(&nuc900_spi_driver); +} + +module_init(nuc900_spi_init); +module_exit(nuc900_spi_exit); + +MODULE_AUTHOR("Wan ZongShun "); +MODULE_DESCRIPTION("nuc900 spi driver!"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:nuc900-spi"); diff --git a/drivers/spi/spi_sh_msiof.c b/drivers/spi/spi_sh_msiof.c new file mode 100644 index 0000000000000000000000000000000000000000..51e5e1dfa6e5229151e8217f139b613ed73b8794 --- /dev/null +++ b/drivers/spi/spi_sh_msiof.c @@ -0,0 +1,691 @@ +/* + * SuperH MSIOF SPI Master Interface + * + * Copyright (c) 2009 Magnus Damm + * + * 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 + +struct sh_msiof_spi_priv { + struct spi_bitbang bitbang; /* must be first for spi_bitbang.c */ + void __iomem *mapbase; + struct clk *clk; + struct platform_device *pdev; + struct sh_msiof_spi_info *info; + struct completion done; + unsigned long flags; + int tx_fifo_size; + int rx_fifo_size; +}; + +#define TMDR1 0x00 +#define TMDR2 0x04 +#define TMDR3 0x08 +#define RMDR1 0x10 +#define RMDR2 0x14 +#define RMDR3 0x18 +#define TSCR 0x20 +#define RSCR 0x22 +#define CTR 0x28 +#define FCTR 0x30 +#define STR 0x40 +#define IER 0x44 +#define TDR1 0x48 +#define TDR2 0x4c +#define TFDR 0x50 +#define RDR1 0x58 +#define RDR2 0x5c +#define RFDR 0x60 + +#define CTR_TSCKE (1 << 15) +#define CTR_TFSE (1 << 14) +#define CTR_TXE (1 << 9) +#define CTR_RXE (1 << 8) + +#define STR_TEOF (1 << 23) +#define STR_REOF (1 << 7) + +static unsigned long sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs) +{ + switch (reg_offs) { + case TSCR: + case RSCR: + return ioread16(p->mapbase + reg_offs); + default: + return ioread32(p->mapbase + reg_offs); + } +} + +static void sh_msiof_write(struct sh_msiof_spi_priv *p, int reg_offs, + unsigned long value) +{ + switch (reg_offs) { + case TSCR: + case RSCR: + iowrite16(value, p->mapbase + reg_offs); + break; + default: + iowrite32(value, p->mapbase + reg_offs); + break; + } +} + +static int sh_msiof_modify_ctr_wait(struct sh_msiof_spi_priv *p, + unsigned long clr, unsigned long set) +{ + unsigned long mask = clr | set; + unsigned long data; + int k; + + data = sh_msiof_read(p, CTR); + data &= ~clr; + data |= set; + sh_msiof_write(p, CTR, data); + + for (k = 100; k > 0; k--) { + if ((sh_msiof_read(p, CTR) & mask) == set) + break; + + udelay(10); + } + + return k > 0 ? 0 : -ETIMEDOUT; +} + +static irqreturn_t sh_msiof_spi_irq(int irq, void *data) +{ + struct sh_msiof_spi_priv *p = data; + + /* just disable the interrupt and wake up */ + sh_msiof_write(p, IER, 0); + complete(&p->done); + + return IRQ_HANDLED; +} + +static struct { + unsigned short div; + unsigned short scr; +} const sh_msiof_spi_clk_table[] = { + { 1, 0x0007 }, + { 2, 0x0000 }, + { 4, 0x0001 }, + { 8, 0x0002 }, + { 16, 0x0003 }, + { 32, 0x0004 }, + { 64, 0x1f00 }, + { 128, 0x1f01 }, + { 256, 0x1f02 }, + { 512, 0x1f03 }, + { 1024, 0x1f04 }, +}; + +static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, + unsigned long parent_rate, + unsigned long spi_hz) +{ + unsigned long div = 1024; + size_t k; + + if (!WARN_ON(!spi_hz || !parent_rate)) + div = parent_rate / spi_hz; + + /* TODO: make more fine grained */ + + for (k = 0; k < ARRAY_SIZE(sh_msiof_spi_clk_table); k++) { + if (sh_msiof_spi_clk_table[k].div >= div) + break; + } + + k = min_t(int, k, ARRAY_SIZE(sh_msiof_spi_clk_table) - 1); + + sh_msiof_write(p, TSCR, sh_msiof_spi_clk_table[k].scr); + sh_msiof_write(p, RSCR, sh_msiof_spi_clk_table[k].scr); +} + +static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, + int cpol, int cpha, + int tx_hi_z, int lsb_first) +{ + unsigned long tmp; + int edge; + + /* + * CPOL CPHA TSCKIZ RSCKIZ TEDG REDG(!) + * 0 0 10 10 1 0 + * 0 1 10 10 0 1 + * 1 0 11 11 0 1 + * 1 1 11 11 1 0 + * + * (!) Note: REDG is inverted recommended data sheet setting + */ + + sh_msiof_write(p, FCTR, 0); + sh_msiof_write(p, TMDR1, 0xe2000005 | (lsb_first << 24)); + sh_msiof_write(p, RMDR1, 0x22000005 | (lsb_first << 24)); + + tmp = 0xa0000000; + tmp |= cpol << 30; /* TSCKIZ */ + tmp |= cpol << 28; /* RSCKIZ */ + + edge = cpol ? cpha : !cpha; + + tmp |= edge << 27; /* TEDG */ + tmp |= !edge << 26; /* REDG */ + tmp |= (tx_hi_z ? 2 : 0) << 22; /* TXDIZ */ + sh_msiof_write(p, CTR, tmp); +} + +static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p, + const void *tx_buf, void *rx_buf, + int bits, int words) +{ + unsigned long dr2; + + dr2 = ((bits - 1) << 24) | ((words - 1) << 16); + + if (tx_buf) + sh_msiof_write(p, TMDR2, dr2); + else + sh_msiof_write(p, TMDR2, dr2 | 1); + + if (rx_buf) + sh_msiof_write(p, RMDR2, dr2); + + sh_msiof_write(p, IER, STR_TEOF | STR_REOF); +} + +static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p) +{ + sh_msiof_write(p, STR, sh_msiof_read(p, STR)); +} + +static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p, + const void *tx_buf, int words, int fs) +{ + const unsigned char *buf_8 = tx_buf; + int k; + + for (k = 0; k < words; k++) + sh_msiof_write(p, TFDR, buf_8[k] << fs); +} + +static void sh_msiof_spi_write_fifo_16(struct sh_msiof_spi_priv *p, + const void *tx_buf, int words, int fs) +{ + const unsigned short *buf_16 = tx_buf; + int k; + + for (k = 0; k < words; k++) + sh_msiof_write(p, TFDR, buf_16[k] << fs); +} + +static void sh_msiof_spi_write_fifo_16u(struct sh_msiof_spi_priv *p, + const void *tx_buf, int words, int fs) +{ + const unsigned short *buf_16 = tx_buf; + int k; + + for (k = 0; k < words; k++) + sh_msiof_write(p, TFDR, get_unaligned(&buf_16[k]) << fs); +} + +static void sh_msiof_spi_write_fifo_32(struct sh_msiof_spi_priv *p, + const void *tx_buf, int words, int fs) +{ + const unsigned int *buf_32 = tx_buf; + int k; + + for (k = 0; k < words; k++) + sh_msiof_write(p, TFDR, buf_32[k] << fs); +} + +static void sh_msiof_spi_write_fifo_32u(struct sh_msiof_spi_priv *p, + const void *tx_buf, int words, int fs) +{ + const unsigned int *buf_32 = tx_buf; + int k; + + for (k = 0; k < words; k++) + sh_msiof_write(p, TFDR, get_unaligned(&buf_32[k]) << fs); +} + +static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p, + void *rx_buf, int words, int fs) +{ + unsigned char *buf_8 = rx_buf; + int k; + + for (k = 0; k < words; k++) + buf_8[k] = sh_msiof_read(p, RFDR) >> fs; +} + +static void sh_msiof_spi_read_fifo_16(struct sh_msiof_spi_priv *p, + void *rx_buf, int words, int fs) +{ + unsigned short *buf_16 = rx_buf; + int k; + + for (k = 0; k < words; k++) + buf_16[k] = sh_msiof_read(p, RFDR) >> fs; +} + +static void sh_msiof_spi_read_fifo_16u(struct sh_msiof_spi_priv *p, + void *rx_buf, int words, int fs) +{ + unsigned short *buf_16 = rx_buf; + int k; + + for (k = 0; k < words; k++) + put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_16[k]); +} + +static void sh_msiof_spi_read_fifo_32(struct sh_msiof_spi_priv *p, + void *rx_buf, int words, int fs) +{ + unsigned int *buf_32 = rx_buf; + int k; + + for (k = 0; k < words; k++) + buf_32[k] = sh_msiof_read(p, RFDR) >> fs; +} + +static void sh_msiof_spi_read_fifo_32u(struct sh_msiof_spi_priv *p, + void *rx_buf, int words, int fs) +{ + unsigned int *buf_32 = rx_buf; + int k; + + for (k = 0; k < words; k++) + put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_32[k]); +} + +static int sh_msiof_spi_bits(struct spi_device *spi, struct spi_transfer *t) +{ + int bits; + + bits = t ? t->bits_per_word : 0; + bits = bits ? bits : spi->bits_per_word; + return bits; +} + +static unsigned long sh_msiof_spi_hz(struct spi_device *spi, + struct spi_transfer *t) +{ + unsigned long hz; + + hz = t ? t->speed_hz : 0; + hz = hz ? hz : spi->max_speed_hz; + return hz; +} + +static int sh_msiof_spi_setup_transfer(struct spi_device *spi, + struct spi_transfer *t) +{ + int bits; + + /* noting to check hz values against since parent clock is disabled */ + + bits = sh_msiof_spi_bits(spi, t); + if (bits < 8) + return -EINVAL; + if (bits > 32) + return -EINVAL; + + return spi_bitbang_setup_transfer(spi, t); +} + +static void sh_msiof_spi_chipselect(struct spi_device *spi, int is_on) +{ + struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master); + int value; + + /* chip select is active low unless SPI_CS_HIGH is set */ + if (spi->mode & SPI_CS_HIGH) + value = (is_on == BITBANG_CS_ACTIVE) ? 1 : 0; + else + value = (is_on == BITBANG_CS_ACTIVE) ? 0 : 1; + + if (is_on == BITBANG_CS_ACTIVE) { + if (!test_and_set_bit(0, &p->flags)) { + pm_runtime_get_sync(&p->pdev->dev); + clk_enable(p->clk); + } + + /* Configure pins before asserting CS */ + sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL), + !!(spi->mode & SPI_CPHA), + !!(spi->mode & SPI_3WIRE), + !!(spi->mode & SPI_LSB_FIRST)); + } + + /* use spi->controller data for CS (same strategy as spi_gpio) */ + gpio_set_value((unsigned)spi->controller_data, value); + + if (is_on == BITBANG_CS_INACTIVE) { + if (test_and_clear_bit(0, &p->flags)) { + clk_disable(p->clk); + pm_runtime_put(&p->pdev->dev); + } + } +} + +static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, + void (*tx_fifo)(struct sh_msiof_spi_priv *, + const void *, int, int), + void (*rx_fifo)(struct sh_msiof_spi_priv *, + void *, int, int), + const void *tx_buf, void *rx_buf, + int words, int bits) +{ + int fifo_shift; + int ret; + + /* limit maximum word transfer to rx/tx fifo size */ + if (tx_buf) + words = min_t(int, words, p->tx_fifo_size); + if (rx_buf) + words = min_t(int, words, p->rx_fifo_size); + + /* the fifo contents need shifting */ + fifo_shift = 32 - bits; + + /* setup msiof transfer mode registers */ + sh_msiof_spi_set_mode_regs(p, tx_buf, rx_buf, bits, words); + + /* write tx fifo */ + if (tx_buf) + tx_fifo(p, tx_buf, words, fifo_shift); + + /* setup clock and rx/tx signals */ + ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE); + if (rx_buf) + ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_RXE); + ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_TXE); + + /* start by setting frame bit */ + INIT_COMPLETION(p->done); + ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_TFSE); + if (ret) { + dev_err(&p->pdev->dev, "failed to start hardware\n"); + goto err; + } + + /* wait for tx fifo to be emptied / rx fifo to be filled */ + wait_for_completion(&p->done); + + /* read rx fifo */ + if (rx_buf) + rx_fifo(p, rx_buf, words, fifo_shift); + + /* clear status bits */ + sh_msiof_reset_str(p); + + /* shut down frame, tx/tx and clock signals */ + ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0); + ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TXE, 0); + if (rx_buf) + ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_RXE, 0); + ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TSCKE, 0); + if (ret) { + dev_err(&p->pdev->dev, "failed to shut down hardware\n"); + goto err; + } + + return words; + + err: + sh_msiof_write(p, IER, 0); + return ret; +} + +static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t) +{ + struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master); + void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int); + void (*rx_fifo)(struct sh_msiof_spi_priv *, void *, int, int); + int bits; + int bytes_per_word; + int bytes_done; + int words; + int n; + + bits = sh_msiof_spi_bits(spi, t); + + /* setup bytes per word and fifo read/write functions */ + if (bits <= 8) { + bytes_per_word = 1; + tx_fifo = sh_msiof_spi_write_fifo_8; + rx_fifo = sh_msiof_spi_read_fifo_8; + } else if (bits <= 16) { + bytes_per_word = 2; + if ((unsigned long)t->tx_buf & 0x01) + tx_fifo = sh_msiof_spi_write_fifo_16u; + else + tx_fifo = sh_msiof_spi_write_fifo_16; + + if ((unsigned long)t->rx_buf & 0x01) + rx_fifo = sh_msiof_spi_read_fifo_16u; + else + rx_fifo = sh_msiof_spi_read_fifo_16; + } else { + bytes_per_word = 4; + if ((unsigned long)t->tx_buf & 0x03) + tx_fifo = sh_msiof_spi_write_fifo_32u; + else + tx_fifo = sh_msiof_spi_write_fifo_32; + + if ((unsigned long)t->rx_buf & 0x03) + rx_fifo = sh_msiof_spi_read_fifo_32u; + else + rx_fifo = sh_msiof_spi_read_fifo_32; + } + + /* setup clocks (clock already enabled in chipselect()) */ + sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), + sh_msiof_spi_hz(spi, t)); + + /* transfer in fifo sized chunks */ + words = t->len / bytes_per_word; + bytes_done = 0; + + while (bytes_done < t->len) { + n = sh_msiof_spi_txrx_once(p, tx_fifo, rx_fifo, + t->tx_buf + bytes_done, + t->rx_buf + bytes_done, + words, bits); + if (n < 0) + break; + + bytes_done += n * bytes_per_word; + words -= n; + } + + return bytes_done; +} + +static u32 sh_msiof_spi_txrx_word(struct spi_device *spi, unsigned nsecs, + u32 word, u8 bits) +{ + BUG(); /* unused but needed by bitbang code */ + return 0; +} + +static int sh_msiof_spi_probe(struct platform_device *pdev) +{ + struct resource *r; + struct spi_master *master; + struct sh_msiof_spi_priv *p; + char clk_name[16]; + int i; + int ret; + + master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv)); + if (master == NULL) { + dev_err(&pdev->dev, "failed to allocate spi master\n"); + ret = -ENOMEM; + goto err0; + } + + p = spi_master_get_devdata(master); + + platform_set_drvdata(pdev, p); + p->info = pdev->dev.platform_data; + init_completion(&p->done); + + snprintf(clk_name, sizeof(clk_name), "msiof%d", pdev->id); + p->clk = clk_get(&pdev->dev, clk_name); + if (IS_ERR(p->clk)) { + dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); + ret = PTR_ERR(p->clk); + goto err1; + } + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + i = platform_get_irq(pdev, 0); + if (!r || i < 0) { + dev_err(&pdev->dev, "cannot get platform resources\n"); + ret = -ENOENT; + goto err2; + } + p->mapbase = ioremap_nocache(r->start, resource_size(r)); + if (!p->mapbase) { + dev_err(&pdev->dev, "unable to ioremap\n"); + ret = -ENXIO; + goto err2; + } + + ret = request_irq(i, sh_msiof_spi_irq, IRQF_DISABLED, + dev_name(&pdev->dev), p); + if (ret) { + dev_err(&pdev->dev, "unable to request irq\n"); + goto err3; + } + + p->pdev = pdev; + pm_runtime_enable(&pdev->dev); + + /* The standard version of MSIOF use 64 word FIFOs */ + p->tx_fifo_size = 64; + p->rx_fifo_size = 64; + + /* Platform data may override FIFO sizes */ + if (p->info->tx_fifo_override) + p->tx_fifo_size = p->info->tx_fifo_override; + if (p->info->rx_fifo_override) + p->rx_fifo_size = p->info->rx_fifo_override; + + /* init master and bitbang code */ + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + master->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE; + master->flags = 0; + master->bus_num = pdev->id; + master->num_chipselect = p->info->num_chipselect; + master->setup = spi_bitbang_setup; + master->cleanup = spi_bitbang_cleanup; + + p->bitbang.master = master; + p->bitbang.chipselect = sh_msiof_spi_chipselect; + p->bitbang.setup_transfer = sh_msiof_spi_setup_transfer; + p->bitbang.txrx_bufs = sh_msiof_spi_txrx; + p->bitbang.txrx_word[SPI_MODE_0] = sh_msiof_spi_txrx_word; + p->bitbang.txrx_word[SPI_MODE_1] = sh_msiof_spi_txrx_word; + p->bitbang.txrx_word[SPI_MODE_2] = sh_msiof_spi_txrx_word; + p->bitbang.txrx_word[SPI_MODE_3] = sh_msiof_spi_txrx_word; + + ret = spi_bitbang_start(&p->bitbang); + if (ret == 0) + return 0; + + pm_runtime_disable(&pdev->dev); + err3: + iounmap(p->mapbase); + err2: + clk_put(p->clk); + err1: + spi_master_put(master); + err0: + return ret; +} + +static int sh_msiof_spi_remove(struct platform_device *pdev) +{ + struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev); + int ret; + + ret = spi_bitbang_stop(&p->bitbang); + if (!ret) { + pm_runtime_disable(&pdev->dev); + free_irq(platform_get_irq(pdev, 0), sh_msiof_spi_irq); + iounmap(p->mapbase); + clk_put(p->clk); + spi_master_put(p->bitbang.master); + } + return ret; +} + +static int sh_msiof_spi_runtime_nop(struct device *dev) +{ + /* Runtime PM callback shared between ->runtime_suspend() + * and ->runtime_resume(). Simply returns success. + * + * This driver re-initializes all registers after + * pm_runtime_get_sync() anyway so there is no need + * to save and restore registers here. + */ + return 0; +} + +static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = { + .runtime_suspend = sh_msiof_spi_runtime_nop, + .runtime_resume = sh_msiof_spi_runtime_nop, +}; + +static struct platform_driver sh_msiof_spi_drv = { + .probe = sh_msiof_spi_probe, + .remove = sh_msiof_spi_remove, + .driver = { + .name = "spi_sh_msiof", + .owner = THIS_MODULE, + .pm = &sh_msiof_spi_dev_pm_ops, + }, +}; + +static int __init sh_msiof_spi_init(void) +{ + return platform_driver_register(&sh_msiof_spi_drv); +} +module_init(sh_msiof_spi_init); + +static void __exit sh_msiof_spi_exit(void) +{ + platform_driver_unregister(&sh_msiof_spi_drv); +} +module_exit(sh_msiof_spi_exit); + +MODULE_DESCRIPTION("SuperH MSIOF SPI Master Interface Driver"); +MODULE_AUTHOR("Magnus Damm"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:spi_sh_msiof"); diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 20d7322e2f7163713a086e8dadd4c6e6213567bb..9c446e6003d5c16bae4b9b7c5cb589411bc79770 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -266,15 +266,15 @@ static int spidev_message(struct spidev_data *spidev, k_tmp->delay_usecs = u_tmp->delay_usecs; k_tmp->speed_hz = u_tmp->speed_hz; #ifdef VERBOSE - dev_dbg(&spi->dev, + dev_dbg(&spidev->spi->dev, " xfer len %zd %s%s%s%dbits %u usec %uHz\n", u_tmp->len, u_tmp->rx_buf ? "rx " : "", u_tmp->tx_buf ? "tx " : "", u_tmp->cs_change ? "cs " : "", - u_tmp->bits_per_word ? : spi->bits_per_word, + u_tmp->bits_per_word ? : spidev->spi->bits_per_word, u_tmp->delay_usecs, - u_tmp->speed_hz ? : spi->max_speed_hz); + u_tmp->speed_hz ? : spidev->spi->max_speed_hz); #endif spi_message_add_tail(k_tmp, &msg); } diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 46b8c5c2f45e3c08a1ce4600005a3397852a2cba..9f386379c16974285c48c48932075d4025471b90 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -14,22 +14,20 @@ #include #include #include -#include - -#include -#include -#include #include #include #include +#include "xilinx_spi.h" +#include + #define XILINX_SPI_NAME "xilinx_spi" /* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e) * Product Specification", DS464 */ -#define XSPI_CR_OFFSET 0x62 /* 16-bit Control Register */ +#define XSPI_CR_OFFSET 0x60 /* Control Register */ #define XSPI_CR_ENABLE 0x02 #define XSPI_CR_MASTER_MODE 0x04 @@ -40,8 +38,9 @@ #define XSPI_CR_RXFIFO_RESET 0x40 #define XSPI_CR_MANUAL_SSELECT 0x80 #define XSPI_CR_TRANS_INHIBIT 0x100 +#define XSPI_CR_LSB_FIRST 0x200 -#define XSPI_SR_OFFSET 0x67 /* 8-bit Status Register */ +#define XSPI_SR_OFFSET 0x64 /* Status Register */ #define XSPI_SR_RX_EMPTY_MASK 0x01 /* Receive FIFO is empty */ #define XSPI_SR_RX_FULL_MASK 0x02 /* Receive FIFO is full */ @@ -49,8 +48,8 @@ #define XSPI_SR_TX_FULL_MASK 0x08 /* Transmit FIFO is full */ #define XSPI_SR_MODE_FAULT_MASK 0x10 /* Mode fault error */ -#define XSPI_TXD_OFFSET 0x6b /* 8-bit Data Transmit Register */ -#define XSPI_RXD_OFFSET 0x6f /* 8-bit Data Receive Register */ +#define XSPI_TXD_OFFSET 0x68 /* Data Transmit Register */ +#define XSPI_RXD_OFFSET 0x6c /* Data Receive Register */ #define XSPI_SSR_OFFSET 0x70 /* 32-bit Slave Select Register */ @@ -70,6 +69,7 @@ #define XSPI_INTR_TX_UNDERRUN 0x08 /* TxFIFO was underrun */ #define XSPI_INTR_RX_FULL 0x10 /* RxFIFO is full */ #define XSPI_INTR_RX_OVERRUN 0x20 /* RxFIFO was overrun */ +#define XSPI_INTR_TX_HALF_EMPTY 0x40 /* TxFIFO is half empty */ #define XIPIF_V123B_RESETR_OFFSET 0x40 /* IPIF reset register */ #define XIPIF_V123B_RESET_MASK 0x0a /* the value to write */ @@ -78,35 +78,85 @@ struct xilinx_spi { /* bitbang has to be first */ struct spi_bitbang bitbang; struct completion done; - + struct resource mem; /* phys mem */ void __iomem *regs; /* virt. address of the control registers */ u32 irq; - u32 speed_hz; /* SCK has a fixed frequency of speed_hz Hz */ - u8 *rx_ptr; /* pointer in the Tx buffer */ const u8 *tx_ptr; /* pointer in the Rx buffer */ int remaining_bytes; /* the number of bytes left to transfer */ + u8 bits_per_word; + unsigned int (*read_fn) (void __iomem *); + void (*write_fn) (u32, void __iomem *); + void (*tx_fn) (struct xilinx_spi *); + void (*rx_fn) (struct xilinx_spi *); }; -static void xspi_init_hw(void __iomem *regs_base) +static void xspi_tx8(struct xilinx_spi *xspi) +{ + xspi->write_fn(*xspi->tx_ptr, xspi->regs + XSPI_TXD_OFFSET); + xspi->tx_ptr++; +} + +static void xspi_tx16(struct xilinx_spi *xspi) +{ + xspi->write_fn(*(u16 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET); + xspi->tx_ptr += 2; +} + +static void xspi_tx32(struct xilinx_spi *xspi) +{ + xspi->write_fn(*(u32 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET); + xspi->tx_ptr += 4; +} + +static void xspi_rx8(struct xilinx_spi *xspi) +{ + u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET); + if (xspi->rx_ptr) { + *xspi->rx_ptr = data & 0xff; + xspi->rx_ptr++; + } +} + +static void xspi_rx16(struct xilinx_spi *xspi) { + u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET); + if (xspi->rx_ptr) { + *(u16 *)(xspi->rx_ptr) = data & 0xffff; + xspi->rx_ptr += 2; + } +} + +static void xspi_rx32(struct xilinx_spi *xspi) +{ + u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET); + if (xspi->rx_ptr) { + *(u32 *)(xspi->rx_ptr) = data; + xspi->rx_ptr += 4; + } +} + +static void xspi_init_hw(struct xilinx_spi *xspi) +{ + void __iomem *regs_base = xspi->regs; + /* Reset the SPI device */ - out_be32(regs_base + XIPIF_V123B_RESETR_OFFSET, - XIPIF_V123B_RESET_MASK); + xspi->write_fn(XIPIF_V123B_RESET_MASK, + regs_base + XIPIF_V123B_RESETR_OFFSET); /* Disable all the interrupts just in case */ - out_be32(regs_base + XIPIF_V123B_IIER_OFFSET, 0); + xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET); /* Enable the global IPIF interrupt */ - out_be32(regs_base + XIPIF_V123B_DGIER_OFFSET, - XIPIF_V123B_GINTR_ENABLE); + xspi->write_fn(XIPIF_V123B_GINTR_ENABLE, + regs_base + XIPIF_V123B_DGIER_OFFSET); /* Deselect the slave on the SPI bus */ - out_be32(regs_base + XSPI_SSR_OFFSET, 0xffff); + xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET); /* Disable the transmitter, enable Manual Slave Select Assertion, * put SPI controller into master mode, and enable it */ - out_be16(regs_base + XSPI_CR_OFFSET, - XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT - | XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE); + xspi->write_fn(XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT | + XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET | + XSPI_CR_RXFIFO_RESET, regs_base + XSPI_CR_OFFSET); } static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) @@ -115,16 +165,16 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) if (is_on == BITBANG_CS_INACTIVE) { /* Deselect the slave on the SPI bus */ - out_be32(xspi->regs + XSPI_SSR_OFFSET, 0xffff); + xspi->write_fn(0xffff, xspi->regs + XSPI_SSR_OFFSET); } else if (is_on == BITBANG_CS_ACTIVE) { /* Set the SPI clock phase and polarity */ - u16 cr = in_be16(xspi->regs + XSPI_CR_OFFSET) + u16 cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_MODE_MASK; if (spi->mode & SPI_CPHA) cr |= XSPI_CR_CPHA; if (spi->mode & SPI_CPOL) cr |= XSPI_CR_CPOL; - out_be16(xspi->regs + XSPI_CR_OFFSET, cr); + xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); /* We do not check spi->max_speed_hz here as the SPI clock * frequency is not software programmable (the IP block design @@ -132,24 +182,27 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) */ /* Activate the chip select */ - out_be32(xspi->regs + XSPI_SSR_OFFSET, - ~(0x0001 << spi->chip_select)); + xspi->write_fn(~(0x0001 << spi->chip_select), + xspi->regs + XSPI_SSR_OFFSET); } } /* spi_bitbang requires custom setup_transfer() to be defined if there is a * custom txrx_bufs(). We have nothing to setup here as the SPI IP block - * supports just 8 bits per word, and SPI clock can't be changed in software. - * Check for 8 bits per word. Chip select delay calculations could be + * supports 8 or 16 bits per word which cannot be changed in software. + * SPI clock can't be changed in software either. + * Check for correct bits per word. Chip select delay calculations could be * added here as soon as bitbang_work() can be made aware of the delay value. */ static int xilinx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { + struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); u8 bits_per_word; - bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word; - if (bits_per_word != 8) { + bits_per_word = (t && t->bits_per_word) + ? t->bits_per_word : spi->bits_per_word; + if (bits_per_word != xspi->bits_per_word) { dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", __func__, bits_per_word); return -EINVAL; @@ -160,17 +213,16 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi, static int xilinx_spi_setup(struct spi_device *spi) { - struct spi_bitbang *bitbang; - struct xilinx_spi *xspi; - int retval; - - xspi = spi_master_get_devdata(spi->master); - bitbang = &xspi->bitbang; - - retval = xilinx_spi_setup_transfer(spi, NULL); - if (retval < 0) - return retval; - + /* always return 0, we can not check the number of bits. + * There are cases when SPI setup is called before any driver is + * there, in that case the SPI core defaults to 8 bits, which we + * do not support in some cases. But if we return an error, the + * SPI device would not be registered and no driver can get hold of it + * When the driver is there, it will call SPI setup again with the + * correct number of bits per transfer. + * If a driver setups with the wrong bit number, it will fail when + * it tries to do a transfer + */ return 0; } @@ -179,15 +231,14 @@ static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi) u8 sr; /* Fill the Tx FIFO with as many bytes as possible */ - sr = in_8(xspi->regs + XSPI_SR_OFFSET); + sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) { - if (xspi->tx_ptr) { - out_8(xspi->regs + XSPI_TXD_OFFSET, *xspi->tx_ptr++); - } else { - out_8(xspi->regs + XSPI_TXD_OFFSET, 0); - } - xspi->remaining_bytes--; - sr = in_8(xspi->regs + XSPI_SR_OFFSET); + if (xspi->tx_ptr) + xspi->tx_fn(xspi); + else + xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET); + xspi->remaining_bytes -= xspi->bits_per_word / 8; + sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); } } @@ -209,18 +260,19 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) /* Enable the transmit empty interrupt, which we use to determine * progress on the transmission. */ - ipif_ier = in_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET); - out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET, - ipif_ier | XSPI_INTR_TX_EMPTY); + ipif_ier = xspi->read_fn(xspi->regs + XIPIF_V123B_IIER_OFFSET); + xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY, + xspi->regs + XIPIF_V123B_IIER_OFFSET); /* Start the transfer by not inhibiting the transmitter any longer */ - cr = in_be16(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_TRANS_INHIBIT; - out_be16(xspi->regs + XSPI_CR_OFFSET, cr); + cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) & + ~XSPI_CR_TRANS_INHIBIT; + xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); wait_for_completion(&xspi->done); /* Disable the transmit empty interrupt */ - out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET, ipif_ier); + xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET); return t->len - xspi->remaining_bytes; } @@ -237,8 +289,8 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) u32 ipif_isr; /* Get the IPIF interrupts, and clear them immediately */ - ipif_isr = in_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET); - out_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET, ipif_isr); + ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET); + xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET); if (ipif_isr & XSPI_INTR_TX_EMPTY) { /* Transmission completed */ u16 cr; @@ -249,20 +301,15 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) * transmitter while the Isr refills the transmit register/FIFO, * or make sure it is stopped if we're done. */ - cr = in_be16(xspi->regs + XSPI_CR_OFFSET); - out_be16(xspi->regs + XSPI_CR_OFFSET, - cr | XSPI_CR_TRANS_INHIBIT); + cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); + xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, + xspi->regs + XSPI_CR_OFFSET); /* Read out all the data from the Rx FIFO */ - sr = in_8(xspi->regs + XSPI_SR_OFFSET); + sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) { - u8 data; - - data = in_8(xspi->regs + XSPI_RXD_OFFSET); - if (xspi->rx_ptr) { - *xspi->rx_ptr++ = data; - } - sr = in_8(xspi->regs + XSPI_SR_OFFSET); + xspi->rx_fn(xspi); + sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); } /* See if there is more data to send */ @@ -271,7 +318,7 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) /* Start the transfer by not inhibiting the * transmitter any longer */ - out_be16(xspi->regs + XSPI_CR_OFFSET, cr); + xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); } else { /* No more data to send. * Indicate the transfer is completed. @@ -283,40 +330,22 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) return IRQ_HANDLED; } -static int __init xilinx_spi_of_probe(struct of_device *ofdev, - const struct of_device_id *match) +struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, + u32 irq, s16 bus_num) { struct spi_master *master; struct xilinx_spi *xspi; - struct resource r_irq_struct; - struct resource r_mem_struct; - - struct resource *r_irq = &r_irq_struct; - struct resource *r_mem = &r_mem_struct; - int rc = 0; - const u32 *prop; - int len; - - /* Get resources(memory, IRQ) associated with the device */ - master = spi_alloc_master(&ofdev->dev, sizeof(struct xilinx_spi)); + struct xspi_platform_data *pdata = dev->platform_data; + int ret; - if (master == NULL) { - return -ENOMEM; + if (!pdata) { + dev_err(dev, "No platform data attached\n"); + return NULL; } - dev_set_drvdata(&ofdev->dev, master); - - rc = of_address_to_resource(ofdev->node, 0, r_mem); - if (rc) { - dev_warn(&ofdev->dev, "invalid address\n"); - goto put_master; - } - - rc = of_irq_to_resource(ofdev->node, 0, r_irq); - if (rc == NO_IRQ) { - dev_warn(&ofdev->dev, "no IRQ found\n"); - goto put_master; - } + master = spi_alloc_master(dev, sizeof(struct xilinx_spi)); + if (!master) + return NULL; /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA; @@ -329,128 +358,87 @@ static int __init xilinx_spi_of_probe(struct of_device *ofdev, xspi->bitbang.master->setup = xilinx_spi_setup; init_completion(&xspi->done); - xspi->irq = r_irq->start; - - if (!request_mem_region(r_mem->start, - r_mem->end - r_mem->start + 1, XILINX_SPI_NAME)) { - rc = -ENXIO; - dev_warn(&ofdev->dev, "memory request failure\n"); + if (!request_mem_region(mem->start, resource_size(mem), + XILINX_SPI_NAME)) goto put_master; - } - xspi->regs = ioremap(r_mem->start, r_mem->end - r_mem->start + 1); + xspi->regs = ioremap(mem->start, resource_size(mem)); if (xspi->regs == NULL) { - rc = -ENOMEM; - dev_warn(&ofdev->dev, "ioremap failure\n"); - goto release_mem; + dev_warn(dev, "ioremap failure\n"); + goto map_failed; } - xspi->irq = r_irq->start; - - /* dynamic bus assignment */ - master->bus_num = -1; - /* number of slave select bits is required */ - prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len); - if (!prop || len < sizeof(*prop)) { - dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n"); - goto unmap_io; + master->bus_num = bus_num; + master->num_chipselect = pdata->num_chipselect; + + xspi->mem = *mem; + xspi->irq = irq; + if (pdata->little_endian) { + xspi->read_fn = ioread32; + xspi->write_fn = iowrite32; + } else { + xspi->read_fn = ioread32be; + xspi->write_fn = iowrite32be; } - master->num_chipselect = *prop; + xspi->bits_per_word = pdata->bits_per_word; + if (xspi->bits_per_word == 8) { + xspi->tx_fn = xspi_tx8; + xspi->rx_fn = xspi_rx8; + } else if (xspi->bits_per_word == 16) { + xspi->tx_fn = xspi_tx16; + xspi->rx_fn = xspi_rx16; + } else if (xspi->bits_per_word == 32) { + xspi->tx_fn = xspi_tx32; + xspi->rx_fn = xspi_rx32; + } else + goto unmap_io; + /* SPI controller initializations */ - xspi_init_hw(xspi->regs); + xspi_init_hw(xspi); /* Register for SPI Interrupt */ - rc = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi); - if (rc != 0) { - dev_warn(&ofdev->dev, "irq request failure: %d\n", xspi->irq); + ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi); + if (ret) goto unmap_io; - } - rc = spi_bitbang_start(&xspi->bitbang); - if (rc != 0) { - dev_err(&ofdev->dev, "spi_bitbang_start FAILED\n"); + ret = spi_bitbang_start(&xspi->bitbang); + if (ret) { + dev_err(dev, "spi_bitbang_start FAILED\n"); goto free_irq; } - dev_info(&ofdev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n", - (unsigned int)r_mem->start, (u32)xspi->regs, xspi->irq); - - /* Add any subnodes on the SPI bus */ - of_register_spi_devices(master, ofdev->node); - - return rc; + dev_info(dev, "at 0x%08llX mapped to 0x%p, irq=%d\n", + (unsigned long long)mem->start, xspi->regs, xspi->irq); + return master; free_irq: free_irq(xspi->irq, xspi); unmap_io: iounmap(xspi->regs); -release_mem: - release_mem_region(r_mem->start, resource_size(r_mem)); +map_failed: + release_mem_region(mem->start, resource_size(mem)); put_master: spi_master_put(master); - return rc; + return NULL; } +EXPORT_SYMBOL(xilinx_spi_init); -static int __devexit xilinx_spi_remove(struct of_device *ofdev) +void xilinx_spi_deinit(struct spi_master *master) { struct xilinx_spi *xspi; - struct spi_master *master; - struct resource r_mem; - master = platform_get_drvdata(ofdev); xspi = spi_master_get_devdata(master); spi_bitbang_stop(&xspi->bitbang); free_irq(xspi->irq, xspi); iounmap(xspi->regs); - if (!of_address_to_resource(ofdev->node, 0, &r_mem)) - release_mem_region(r_mem.start, resource_size(&r_mem)); - dev_set_drvdata(&ofdev->dev, 0); - spi_master_put(xspi->bitbang.master); - - return 0; -} - -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:" XILINX_SPI_NAME); - -static int __exit xilinx_spi_of_remove(struct of_device *op) -{ - return xilinx_spi_remove(op); -} -static struct of_device_id xilinx_spi_of_match[] = { - { .compatible = "xlnx,xps-spi-2.00.a", }, - { .compatible = "xlnx,xps-spi-2.00.b", }, - {} -}; - -MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); - -static struct of_platform_driver xilinx_spi_of_driver = { - .owner = THIS_MODULE, - .name = "xilinx-xps-spi", - .match_table = xilinx_spi_of_match, - .probe = xilinx_spi_of_probe, - .remove = __exit_p(xilinx_spi_of_remove), - .driver = { - .name = "xilinx-xps-spi", - .owner = THIS_MODULE, - }, -}; - -static int __init xilinx_spi_init(void) -{ - return of_register_platform_driver(&xilinx_spi_of_driver); + release_mem_region(xspi->mem.start, resource_size(&xspi->mem)); + spi_master_put(xspi->bitbang.master); } -module_init(xilinx_spi_init); +EXPORT_SYMBOL(xilinx_spi_deinit); -static void __exit xilinx_spi_exit(void) -{ - of_unregister_platform_driver(&xilinx_spi_of_driver); -} -module_exit(xilinx_spi_exit); MODULE_AUTHOR("MontaVista Software, Inc. "); MODULE_DESCRIPTION("Xilinx SPI driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/spi/xilinx_spi.h b/drivers/spi/xilinx_spi.h new file mode 100644 index 0000000000000000000000000000000000000000..d211accf68d2062cf98bef8aad9b5adba3372617 --- /dev/null +++ b/drivers/spi/xilinx_spi.h @@ -0,0 +1,32 @@ +/* + * Xilinx SPI device driver API and platform data header file + * + * Copyright (c) 2009 Intel Corporation + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _XILINX_SPI_H_ +#define _XILINX_SPI_H_ + +#include +#include + +#define XILINX_SPI_NAME "xilinx_spi" + +struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, + u32 irq, s16 bus_num); + +void xilinx_spi_deinit(struct spi_master *master); +#endif diff --git a/drivers/spi/xilinx_spi_of.c b/drivers/spi/xilinx_spi_of.c new file mode 100644 index 0000000000000000000000000000000000000000..71dc3adc049577f0a5159fdca7864786218e1930 --- /dev/null +++ b/drivers/spi/xilinx_spi_of.c @@ -0,0 +1,134 @@ +/* + * Xilinx SPI OF device driver + * + * Copyright (c) 2009 Intel Corporation + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supports: + * Xilinx SPI devices as OF devices + * + * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "xilinx_spi.h" + + +static int __devinit xilinx_spi_of_probe(struct of_device *ofdev, + const struct of_device_id *match) +{ + struct spi_master *master; + struct xspi_platform_data *pdata; + struct resource r_mem; + struct resource r_irq; + int rc = 0; + const u32 *prop; + int len; + + rc = of_address_to_resource(ofdev->node, 0, &r_mem); + if (rc) { + dev_warn(&ofdev->dev, "invalid address\n"); + return rc; + } + + rc = of_irq_to_resource(ofdev->node, 0, &r_irq); + if (rc == NO_IRQ) { + dev_warn(&ofdev->dev, "no IRQ found\n"); + return -ENODEV; + } + + ofdev->dev.platform_data = + kzalloc(sizeof(struct xspi_platform_data), GFP_KERNEL); + pdata = ofdev->dev.platform_data; + if (!pdata) + return -ENOMEM; + + /* number of slave select bits is required */ + prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len); + if (!prop || len < sizeof(*prop)) { + dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n"); + return -EINVAL; + } + pdata->num_chipselect = *prop; + pdata->bits_per_word = 8; + master = xilinx_spi_init(&ofdev->dev, &r_mem, r_irq.start, -1); + if (!master) + return -ENODEV; + + dev_set_drvdata(&ofdev->dev, master); + + /* Add any subnodes on the SPI bus */ + of_register_spi_devices(master, ofdev->node); + + return 0; +} + +static int __devexit xilinx_spi_remove(struct of_device *ofdev) +{ + xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev)); + dev_set_drvdata(&ofdev->dev, 0); + kfree(ofdev->dev.platform_data); + ofdev->dev.platform_data = NULL; + return 0; +} + +static int __exit xilinx_spi_of_remove(struct of_device *op) +{ + return xilinx_spi_remove(op); +} + +static struct of_device_id xilinx_spi_of_match[] = { + { .compatible = "xlnx,xps-spi-2.00.a", }, + { .compatible = "xlnx,xps-spi-2.00.b", }, + {} +}; + +MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); + +static struct of_platform_driver xilinx_spi_of_driver = { + .match_table = xilinx_spi_of_match, + .probe = xilinx_spi_of_probe, + .remove = __exit_p(xilinx_spi_of_remove), + .driver = { + .name = "xilinx-xps-spi", + .owner = THIS_MODULE, + }, +}; + +static int __init xilinx_spi_of_init(void) +{ + return of_register_platform_driver(&xilinx_spi_of_driver); +} +module_init(xilinx_spi_of_init); + +static void __exit xilinx_spi_of_exit(void) +{ + of_unregister_platform_driver(&xilinx_spi_of_driver); +} +module_exit(xilinx_spi_of_exit); + +MODULE_AUTHOR("Mocean Laboratories "); +MODULE_DESCRIPTION("Xilinx SPI platform driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/spi/xilinx_spi_pltfm.c b/drivers/spi/xilinx_spi_pltfm.c new file mode 100644 index 0000000000000000000000000000000000000000..24debac646a9f671ee39827f1e13fd9ffcaa4060 --- /dev/null +++ b/drivers/spi/xilinx_spi_pltfm.c @@ -0,0 +1,102 @@ +/* + * Support for Xilinx SPI platform devices + * Copyright (c) 2009 Intel Corporation + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supports: + * Xilinx SPI devices as platform devices + * + * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "xilinx_spi.h" + +static int __devinit xilinx_spi_probe(struct platform_device *dev) +{ + struct xspi_platform_data *pdata; + struct resource *r; + int irq; + struct spi_master *master; + u8 i; + + pdata = dev->dev.platform_data; + if (!pdata) + return -ENODEV; + + r = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!r) + return -ENODEV; + + irq = platform_get_irq(dev, 0); + if (irq < 0) + return -ENXIO; + + master = xilinx_spi_init(&dev->dev, r, irq, dev->id); + if (!master) + return -ENODEV; + + for (i = 0; i < pdata->num_devices; i++) + spi_new_device(master, pdata->devices + i); + + platform_set_drvdata(dev, master); + return 0; +} + +static int __devexit xilinx_spi_remove(struct platform_device *dev) +{ + xilinx_spi_deinit(platform_get_drvdata(dev)); + platform_set_drvdata(dev, 0); + + return 0; +} + +/* work with hotplug and coldplug */ +MODULE_ALIAS("platform:" XILINX_SPI_NAME); + +static struct platform_driver xilinx_spi_driver = { + .probe = xilinx_spi_probe, + .remove = __devexit_p(xilinx_spi_remove), + .driver = { + .name = XILINX_SPI_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init xilinx_spi_pltfm_init(void) +{ + return platform_driver_register(&xilinx_spi_driver); +} +module_init(xilinx_spi_pltfm_init); + +static void __exit xilinx_spi_pltfm_exit(void) +{ + platform_driver_unregister(&xilinx_spi_driver); +} +module_exit(xilinx_spi_pltfm_exit); + +MODULE_AUTHOR("Mocean Laboratories "); +MODULE_DESCRIPTION("Xilinx SPI platform driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index dfcd75cf4907f5c992bc853f59850611848c128a..54e174d28234600c49f8845f94c6fcfb7162aa03 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -65,8 +65,6 @@ source "drivers/staging/rt2860/Kconfig" source "drivers/staging/rt2870/Kconfig" -source "drivers/staging/rt3090/Kconfig" - source "drivers/staging/comedi/Kconfig" source "drivers/staging/asus_oled/Kconfig" @@ -79,14 +77,14 @@ source "drivers/staging/rtl8187se/Kconfig" source "drivers/staging/rtl8192su/Kconfig" +source "drivers/staging/rtl8192u/Kconfig" + source "drivers/staging/rtl8192e/Kconfig" source "drivers/staging/mimio/Kconfig" source "drivers/staging/frontier/Kconfig" -source "drivers/staging/android/Kconfig" - source "drivers/staging/dream/Kconfig" source "drivers/staging/dst/Kconfig" @@ -103,6 +101,8 @@ source "drivers/staging/line6/Kconfig" source "drivers/gpu/drm/radeon/Kconfig" +source "drivers/gpu/drm/nouveau/Kconfig" + source "drivers/staging/octeon/Kconfig" source "drivers/staging/serqt_usb2/Kconfig" @@ -125,6 +125,16 @@ source "drivers/staging/sep/Kconfig" source "drivers/staging/iio/Kconfig" +source "drivers/staging/ramzswap/Kconfig" + +source "drivers/staging/wlags49_h2/Kconfig" + +source "drivers/staging/wlags49_h25/Kconfig" + +source "drivers/staging/batman-adv/Kconfig" + +source "drivers/staging/samsung-laptop/Kconfig" + source "drivers/staging/strip/Kconfig" source "drivers/staging/arlan/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 7719d04a4a860b2fee784759d73a1aa514d53348..069864f4391ecbc20c68e820a22c324669b4240f 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -15,18 +15,17 @@ obj-$(CONFIG_POCH) += poch/ obj-$(CONFIG_OTUS) += otus/ obj-$(CONFIG_RT2860) += rt2860/ obj-$(CONFIG_RT2870) += rt2870/ -obj-$(CONFIG_RT3090) += rt3090/ obj-$(CONFIG_COMEDI) += comedi/ obj-$(CONFIG_ASUS_OLED) += asus_oled/ obj-$(CONFIG_PANEL) += panel/ obj-$(CONFIG_ALTERA_PCIE_CHDMA) += altpciechdma/ -obj-$(CONFIG_RTL8187SE) += rtl8187se/ +obj-$(CONFIG_R8187SE) += rtl8187se/ obj-$(CONFIG_RTL8192SU) += rtl8192su/ +obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_INPUT_MIMIO) += mimio/ obj-$(CONFIG_TRANZPORT) += frontier/ -obj-$(CONFIG_ANDROID) += android/ -obj-$(CONFIG_ANDROID) += dream/ +obj-$(CONFIG_DREAM) += dream/ obj-$(CONFIG_DST) += dst/ obj-$(CONFIG_POHMELFS) += pohmelfs/ obj-$(CONFIG_B3DFG) += b3dfg/ @@ -44,6 +43,11 @@ obj-$(CONFIG_VME_BUS) += vme/ obj-$(CONFIG_RAR_REGISTER) += rar/ obj-$(CONFIG_DX_SEP) += sep/ obj-$(CONFIG_IIO) += iio/ +obj-$(CONFIG_RAMZSWAP) += ramzswap/ +obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ +obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/ +obj-$(CONFIG_BATMAN_ADV) += batman-adv/ +obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop/ obj-$(CONFIG_STRIP) += strip/ obj-$(CONFIG_ARLAN) += arlan/ obj-$(CONFIG_WAVELAN) += wavelan/ diff --git a/drivers/staging/altpciechdma/altpciechdma.c b/drivers/staging/altpciechdma/altpciechdma.c index e0c5ba4b4c2907abc0092795c35a4998bab04c41..2f07dd4563aca51b732f1141aef1a29f905b7537 100644 --- a/drivers/staging/altpciechdma/altpciechdma.c +++ b/drivers/staging/altpciechdma/altpciechdma.c @@ -212,7 +212,7 @@ struct ape_dev { int msi_enabled; /* whether this driver could obtain the regions */ int got_regions; - /* irq line succesfully requested by this driver, -1 otherwise */ + /* irq line successfully requested by this driver, -1 otherwise */ int irq_line; /* board revision */ u8 revision; @@ -336,7 +336,7 @@ static int __devinit map_bars(struct ape_dev *ape, struct pci_dev *dev) printk(KERN_DEBUG "BAR[%d] mapped at 0x%p with length %lu(/%lu).\n", i, ape->bar[i], bar_min_len[i], bar_length); } - /* succesfully mapped all required BAR regions */ + /* successfully mapped all required BAR regions */ rc = 0; goto success; fail: @@ -911,7 +911,7 @@ static int __devinit probe(struct pci_dev *dev, const struct pci_device_id *id) /* perform DMA engines loop back test */ rc = dma_test(ape, dev); (void)rc; - /* succesfully took the device */ + /* successfully took the device */ rc = 0; printk(KERN_DEBUG "probe() successful.\n"); goto end; diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig deleted file mode 100644 index eb675635ae60c532e800ae6a57c1c9c667b052b8..0000000000000000000000000000000000000000 --- a/drivers/staging/android/Kconfig +++ /dev/null @@ -1,96 +0,0 @@ -menu "Android" - -config ANDROID - bool "Android Drivers" - depends on BROKEN - default N - ---help--- - Enable support for various drivers needed on the Android platform - -if ANDROID - -config ANDROID_BINDER_IPC - bool "Android Binder IPC Driver" - default n - -config ANDROID_LOGGER - tristate "Android log driver" - default n - -config ANDROID_RAM_CONSOLE - bool "Android RAM buffer console" - default n - -config ANDROID_RAM_CONSOLE_ENABLE_VERBOSE - bool "Enable verbose console messages on Android RAM console" - default y - depends on ANDROID_RAM_CONSOLE - -menuconfig ANDROID_RAM_CONSOLE_ERROR_CORRECTION - bool "Android RAM Console Enable error correction" - default n - depends on ANDROID_RAM_CONSOLE - depends on !ANDROID_RAM_CONSOLE_EARLY_INIT - select REED_SOLOMON - select REED_SOLOMON_ENC8 - select REED_SOLOMON_DEC8 - -if ANDROID_RAM_CONSOLE_ERROR_CORRECTION - -config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE - int "Android RAM Console Data data size" - default 128 - help - Must be a power of 2. - -config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE - int "Android RAM Console ECC size" - default 16 - -config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE - int "Android RAM Console Symbol size" - default 8 - -config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL - hex "Android RAM Console Polynomial" - default 0x19 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 4) - default 0x29 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 5) - default 0x61 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 6) - default 0x89 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 7) - default 0x11d if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 8) - -endif # ANDROID_RAM_CONSOLE_ERROR_CORRECTION - -config ANDROID_RAM_CONSOLE_EARLY_INIT - bool "Start Android RAM console early" - default n - depends on ANDROID_RAM_CONSOLE - -config ANDROID_RAM_CONSOLE_EARLY_ADDR - hex "Android RAM console virtual address" - default 0 - depends on ANDROID_RAM_CONSOLE_EARLY_INIT - -config ANDROID_RAM_CONSOLE_EARLY_SIZE - hex "Android RAM console buffer size" - default 0 - depends on ANDROID_RAM_CONSOLE_EARLY_INIT - -config ANDROID_TIMED_OUTPUT - bool "Timed output class driver" - default y - -config ANDROID_TIMED_GPIO - tristate "Android timed gpio driver" - depends on GENERIC_GPIO && ANDROID_TIMED_OUTPUT - default n - -config ANDROID_LOW_MEMORY_KILLER - bool "Android Low Memory Killer" - default N - ---help--- - Register processes to be killed when memory is low - -endif # if ANDROID - -endmenu diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile deleted file mode 100644 index 8e057e626d11c85c0da8f972824ae8e95c316e4d..0000000000000000000000000000000000000000 --- a/drivers/staging/android/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o -obj-$(CONFIG_ANDROID_LOGGER) += logger.o -obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o -obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o -obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o -obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o diff --git a/drivers/staging/android/TODO b/drivers/staging/android/TODO deleted file mode 100644 index e59c5be4be2bfa4eb4e8e3878ac3b857bf6911f5..0000000000000000000000000000000000000000 --- a/drivers/staging/android/TODO +++ /dev/null @@ -1,10 +0,0 @@ -TODO: - - checkpatch.pl cleanups - - sparse fixes - - rename files to be not so "generic" - - make sure things build as modules properly - - add proper arch dependancies as needed - - audit userspace interfaces to make sure they are sane - -Please send patches to Greg Kroah-Hartman and Cc: -Brian Swetland diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c deleted file mode 100644 index 99010d4b3044b2c33c9d709e334b5be7871b9599..0000000000000000000000000000000000000000 --- a/drivers/staging/android/binder.c +++ /dev/null @@ -1,3767 +0,0 @@ -/* binder.c - * - * Android IPC Subsystem - * - * Copyright (C) 2007-2008 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "binder.h" - -static DEFINE_MUTEX(binder_lock); -static DEFINE_MUTEX(binder_deferred_lock); - -static HLIST_HEAD(binder_procs); -static HLIST_HEAD(binder_deferred_list); -static HLIST_HEAD(binder_dead_nodes); - -static struct proc_dir_entry *binder_proc_dir_entry_root; -static struct proc_dir_entry *binder_proc_dir_entry_proc; -static struct binder_node *binder_context_mgr_node; -static uid_t binder_context_mgr_uid = -1; -static int binder_last_id; - -static int binder_read_proc_proc(char *page, char **start, off_t off, - int count, int *eof, void *data); - -/* This is only defined in include/asm-arm/sizes.h */ -#ifndef SZ_1K -#define SZ_1K 0x400 -#endif - -#ifndef SZ_4M -#define SZ_4M 0x400000 -#endif - -#define FORBIDDEN_MMAP_FLAGS (VM_WRITE) - -#define BINDER_SMALL_BUF_SIZE (PAGE_SIZE * 64) - -enum { - BINDER_DEBUG_USER_ERROR = 1U << 0, - BINDER_DEBUG_FAILED_TRANSACTION = 1U << 1, - BINDER_DEBUG_DEAD_TRANSACTION = 1U << 2, - BINDER_DEBUG_OPEN_CLOSE = 1U << 3, - BINDER_DEBUG_DEAD_BINDER = 1U << 4, - BINDER_DEBUG_DEATH_NOTIFICATION = 1U << 5, - BINDER_DEBUG_READ_WRITE = 1U << 6, - BINDER_DEBUG_USER_REFS = 1U << 7, - BINDER_DEBUG_THREADS = 1U << 8, - BINDER_DEBUG_TRANSACTION = 1U << 9, - BINDER_DEBUG_TRANSACTION_COMPLETE = 1U << 10, - BINDER_DEBUG_FREE_BUFFER = 1U << 11, - BINDER_DEBUG_INTERNAL_REFS = 1U << 12, - BINDER_DEBUG_BUFFER_ALLOC = 1U << 13, - BINDER_DEBUG_PRIORITY_CAP = 1U << 14, - BINDER_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 15, -}; -static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR | - BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION; -module_param_named(debug_mask, binder_debug_mask, uint, S_IWUSR | S_IRUGO); - -static int binder_debug_no_lock; -module_param_named(proc_no_lock, binder_debug_no_lock, bool, S_IWUSR | S_IRUGO); - -static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait); -static int binder_stop_on_user_error; - -static int binder_set_stop_on_user_error(const char *val, - struct kernel_param *kp) -{ - int ret; - ret = param_set_int(val, kp); - if (binder_stop_on_user_error < 2) - wake_up(&binder_user_error_wait); - return ret; -} -module_param_call(stop_on_user_error, binder_set_stop_on_user_error, - param_get_int, &binder_stop_on_user_error, S_IWUSR | S_IRUGO); - -#define binder_debug(mask, x...) \ - do { \ - if (binder_debug_mask & mask) \ - printk(KERN_INFO x); \ - } while (0) - -#define binder_user_error(x...) \ - do { \ - if (binder_debug_mask & BINDER_DEBUG_USER_ERROR) \ - printk(KERN_INFO x); \ - if (binder_stop_on_user_error) \ - binder_stop_on_user_error = 2; \ - } while (0) - -enum binder_stat_types { - BINDER_STAT_PROC, - BINDER_STAT_THREAD, - BINDER_STAT_NODE, - BINDER_STAT_REF, - BINDER_STAT_DEATH, - BINDER_STAT_TRANSACTION, - BINDER_STAT_TRANSACTION_COMPLETE, - BINDER_STAT_COUNT -}; - -struct binder_stats { - int br[_IOC_NR(BR_FAILED_REPLY) + 1]; - int bc[_IOC_NR(BC_DEAD_BINDER_DONE) + 1]; - int obj_created[BINDER_STAT_COUNT]; - int obj_deleted[BINDER_STAT_COUNT]; -}; - -static struct binder_stats binder_stats; - -static inline void binder_stats_deleted(enum binder_stat_types type) -{ - binder_stats.obj_deleted[type]++; -} - -static inline void binder_stats_created(enum binder_stat_types type) -{ - binder_stats.obj_created[type]++; -} - -struct binder_transaction_log_entry { - int debug_id; - int call_type; - int from_proc; - int from_thread; - int target_handle; - int to_proc; - int to_thread; - int to_node; - int data_size; - int offsets_size; -}; -struct binder_transaction_log { - int next; - int full; - struct binder_transaction_log_entry entry[32]; -}; -static struct binder_transaction_log binder_transaction_log; -static struct binder_transaction_log binder_transaction_log_failed; - -static struct binder_transaction_log_entry *binder_transaction_log_add( - struct binder_transaction_log *log) -{ - struct binder_transaction_log_entry *e; - e = &log->entry[log->next]; - memset(e, 0, sizeof(*e)); - log->next++; - if (log->next == ARRAY_SIZE(log->entry)) { - log->next = 0; - log->full = 1; - } - return e; -} - -struct binder_work { - struct list_head entry; - enum { - BINDER_WORK_TRANSACTION = 1, - BINDER_WORK_TRANSACTION_COMPLETE, - BINDER_WORK_NODE, - BINDER_WORK_DEAD_BINDER, - BINDER_WORK_DEAD_BINDER_AND_CLEAR, - BINDER_WORK_CLEAR_DEATH_NOTIFICATION, - } type; -}; - -struct binder_node { - int debug_id; - struct binder_work work; - union { - struct rb_node rb_node; - struct hlist_node dead_node; - }; - struct binder_proc *proc; - struct hlist_head refs; - int internal_strong_refs; - int local_weak_refs; - int local_strong_refs; - void __user *ptr; - void __user *cookie; - unsigned has_strong_ref:1; - unsigned pending_strong_ref:1; - unsigned has_weak_ref:1; - unsigned pending_weak_ref:1; - unsigned has_async_transaction:1; - unsigned accept_fds:1; - unsigned min_priority:8; - struct list_head async_todo; -}; - -struct binder_ref_death { - struct binder_work work; - void __user *cookie; -}; - -struct binder_ref { - /* Lookups needed: */ - /* node + proc => ref (transaction) */ - /* desc + proc => ref (transaction, inc/dec ref) */ - /* node => refs + procs (proc exit) */ - int debug_id; - struct rb_node rb_node_desc; - struct rb_node rb_node_node; - struct hlist_node node_entry; - struct binder_proc *proc; - struct binder_node *node; - uint32_t desc; - int strong; - int weak; - struct binder_ref_death *death; -}; - -struct binder_buffer { - struct list_head entry; /* free and allocated entries by addesss */ - struct rb_node rb_node; /* free entry by size or allocated entry */ - /* by address */ - unsigned free:1; - unsigned allow_user_free:1; - unsigned async_transaction:1; - unsigned debug_id:29; - - struct binder_transaction *transaction; - - struct binder_node *target_node; - size_t data_size; - size_t offsets_size; - uint8_t data[0]; -}; - -enum binder_deferred_state { - BINDER_DEFERRED_PUT_FILES = 0x01, - BINDER_DEFERRED_FLUSH = 0x02, - BINDER_DEFERRED_RELEASE = 0x04, -}; - -struct binder_proc { - struct hlist_node proc_node; - struct rb_root threads; - struct rb_root nodes; - struct rb_root refs_by_desc; - struct rb_root refs_by_node; - int pid; - struct vm_area_struct *vma; - struct task_struct *tsk; - struct files_struct *files; - struct hlist_node deferred_work_node; - int deferred_work; - void *buffer; - ptrdiff_t user_buffer_offset; - - struct list_head buffers; - struct rb_root free_buffers; - struct rb_root allocated_buffers; - size_t free_async_space; - - struct page **pages; - size_t buffer_size; - uint32_t buffer_free; - struct list_head todo; - wait_queue_head_t wait; - struct binder_stats stats; - struct list_head delivered_death; - int max_threads; - int requested_threads; - int requested_threads_started; - int ready_threads; - long default_priority; -}; - -enum { - BINDER_LOOPER_STATE_REGISTERED = 0x01, - BINDER_LOOPER_STATE_ENTERED = 0x02, - BINDER_LOOPER_STATE_EXITED = 0x04, - BINDER_LOOPER_STATE_INVALID = 0x08, - BINDER_LOOPER_STATE_WAITING = 0x10, - BINDER_LOOPER_STATE_NEED_RETURN = 0x20 -}; - -struct binder_thread { - struct binder_proc *proc; - struct rb_node rb_node; - int pid; - int looper; - struct binder_transaction *transaction_stack; - struct list_head todo; - uint32_t return_error; /* Write failed, return error code in read buf */ - uint32_t return_error2; /* Write failed, return error code in read */ - /* buffer. Used when sending a reply to a dead process that */ - /* we are also waiting on */ - wait_queue_head_t wait; - struct binder_stats stats; -}; - -struct binder_transaction { - int debug_id; - struct binder_work work; - struct binder_thread *from; - struct binder_transaction *from_parent; - struct binder_proc *to_proc; - struct binder_thread *to_thread; - struct binder_transaction *to_parent; - unsigned need_reply:1; - /* unsigned is_dead:1; */ /* not used at the moment */ - - struct binder_buffer *buffer; - unsigned int code; - unsigned int flags; - long priority; - long saved_priority; - uid_t sender_euid; -}; - -static void -binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); - -/* - * copied from get_unused_fd_flags - */ -int task_get_unused_fd_flags(struct binder_proc *proc, int flags) -{ - struct files_struct *files = proc->files; - int fd, error; - struct fdtable *fdt; - unsigned long rlim_cur; - unsigned long irqs; - - if (files == NULL) - return -ESRCH; - - error = -EMFILE; - spin_lock(&files->file_lock); - -repeat: - fdt = files_fdtable(files); - fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds, - files->next_fd); - - /* - * N.B. For clone tasks sharing a files structure, this test - * will limit the total number of files that can be opened. - */ - rlim_cur = 0; - if (lock_task_sighand(proc->tsk, &irqs)) { - rlim_cur = proc->tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur; - unlock_task_sighand(proc->tsk, &irqs); - } - if (fd >= rlim_cur) - goto out; - - /* Do we need to expand the fd array or fd set? */ - error = expand_files(files, fd); - if (error < 0) - goto out; - - if (error) { - /* - * If we needed to expand the fs array we - * might have blocked - try again. - */ - error = -EMFILE; - goto repeat; - } - - FD_SET(fd, fdt->open_fds); - if (flags & O_CLOEXEC) - FD_SET(fd, fdt->close_on_exec); - else - FD_CLR(fd, fdt->close_on_exec); - files->next_fd = fd + 1; -#if 1 - /* Sanity check */ - if (fdt->fd[fd] != NULL) { - printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd); - fdt->fd[fd] = NULL; - } -#endif - error = fd; - -out: - spin_unlock(&files->file_lock); - return error; -} - -/* - * copied from fd_install - */ -static void task_fd_install( - struct binder_proc *proc, unsigned int fd, struct file *file) -{ - struct files_struct *files = proc->files; - struct fdtable *fdt; - - if (files == NULL) - return; - - spin_lock(&files->file_lock); - fdt = files_fdtable(files); - BUG_ON(fdt->fd[fd] != NULL); - rcu_assign_pointer(fdt->fd[fd], file); - spin_unlock(&files->file_lock); -} - -/* - * copied from __put_unused_fd in open.c - */ -static void __put_unused_fd(struct files_struct *files, unsigned int fd) -{ - struct fdtable *fdt = files_fdtable(files); - __FD_CLR(fd, fdt->open_fds); - if (fd < files->next_fd) - files->next_fd = fd; -} - -/* - * copied from sys_close - */ -static long task_close_fd(struct binder_proc *proc, unsigned int fd) -{ - struct file *filp; - struct files_struct *files = proc->files; - struct fdtable *fdt; - int retval; - - if (files == NULL) - return -ESRCH; - - spin_lock(&files->file_lock); - fdt = files_fdtable(files); - if (fd >= fdt->max_fds) - goto out_unlock; - filp = fdt->fd[fd]; - if (!filp) - goto out_unlock; - rcu_assign_pointer(fdt->fd[fd], NULL); - FD_CLR(fd, fdt->close_on_exec); - __put_unused_fd(files, fd); - spin_unlock(&files->file_lock); - retval = filp_close(filp, files); - - /* can't restart close syscall because file table entry was cleared */ - if (unlikely(retval == -ERESTARTSYS || - retval == -ERESTARTNOINTR || - retval == -ERESTARTNOHAND || - retval == -ERESTART_RESTARTBLOCK)) - retval = -EINTR; - - return retval; - -out_unlock: - spin_unlock(&files->file_lock); - return -EBADF; -} - -static void binder_set_nice(long nice) -{ - long min_nice; - if (can_nice(current, nice)) { - set_user_nice(current, nice); - return; - } - min_nice = 20 - current->signal->rlim[RLIMIT_NICE].rlim_cur; - binder_debug(BINDER_DEBUG_PRIORITY_CAP, - "binder: %d: nice value %ld not allowed use " - "%ld instead\n", current->pid, nice, min_nice); - set_user_nice(current, min_nice); - if (min_nice < 20) - return; - binder_user_error("binder: %d RLIMIT_NICE not set\n", current->pid); -} - -static size_t binder_buffer_size(struct binder_proc *proc, - struct binder_buffer *buffer) -{ - if (list_is_last(&buffer->entry, &proc->buffers)) - return proc->buffer + proc->buffer_size - (void *)buffer->data; - else - return (size_t)list_entry(buffer->entry.next, - struct binder_buffer, entry) - (size_t)buffer->data; -} - -static void binder_insert_free_buffer(struct binder_proc *proc, - struct binder_buffer *new_buffer) -{ - struct rb_node **p = &proc->free_buffers.rb_node; - struct rb_node *parent = NULL; - struct binder_buffer *buffer; - size_t buffer_size; - size_t new_buffer_size; - - BUG_ON(!new_buffer->free); - - new_buffer_size = binder_buffer_size(proc, new_buffer); - - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: add free buffer, size %zd, " - "at %p\n", proc->pid, new_buffer_size, new_buffer); - - while (*p) { - parent = *p; - buffer = rb_entry(parent, struct binder_buffer, rb_node); - BUG_ON(!buffer->free); - - buffer_size = binder_buffer_size(proc, buffer); - - if (new_buffer_size < buffer_size) - p = &parent->rb_left; - else - p = &parent->rb_right; - } - rb_link_node(&new_buffer->rb_node, parent, p); - rb_insert_color(&new_buffer->rb_node, &proc->free_buffers); -} - -static void binder_insert_allocated_buffer(struct binder_proc *proc, - struct binder_buffer *new_buffer) -{ - struct rb_node **p = &proc->allocated_buffers.rb_node; - struct rb_node *parent = NULL; - struct binder_buffer *buffer; - - BUG_ON(new_buffer->free); - - while (*p) { - parent = *p; - buffer = rb_entry(parent, struct binder_buffer, rb_node); - BUG_ON(buffer->free); - - if (new_buffer < buffer) - p = &parent->rb_left; - else if (new_buffer > buffer) - p = &parent->rb_right; - else - BUG(); - } - rb_link_node(&new_buffer->rb_node, parent, p); - rb_insert_color(&new_buffer->rb_node, &proc->allocated_buffers); -} - -static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc, - void __user *user_ptr) -{ - struct rb_node *n = proc->allocated_buffers.rb_node; - struct binder_buffer *buffer; - struct binder_buffer *kern_ptr; - - kern_ptr = user_ptr - proc->user_buffer_offset - - offsetof(struct binder_buffer, data); - - while (n) { - buffer = rb_entry(n, struct binder_buffer, rb_node); - BUG_ON(buffer->free); - - if (kern_ptr < buffer) - n = n->rb_left; - else if (kern_ptr > buffer) - n = n->rb_right; - else - return buffer; - } - return NULL; -} - -static int binder_update_page_range(struct binder_proc *proc, int allocate, - void *start, void *end, - struct vm_area_struct *vma) -{ - void *page_addr; - unsigned long user_page_addr; - struct vm_struct tmp_area; - struct page **page; - struct mm_struct *mm; - - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: %s pages %p-%p\n", proc->pid, - allocate ? "allocate" : "free", start, end); - - if (end <= start) - return 0; - - if (vma) - mm = NULL; - else - mm = get_task_mm(proc->tsk); - - if (mm) { - down_write(&mm->mmap_sem); - vma = proc->vma; - } - - if (allocate == 0) - goto free_range; - - if (vma == NULL) { - printk(KERN_ERR "binder: %d: binder_alloc_buf failed to " - "map pages in userspace, no vma\n", proc->pid); - goto err_no_vma; - } - - for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { - int ret; - struct page **page_array_ptr; - page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE]; - - BUG_ON(*page); - *page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (*page == NULL) { - printk(KERN_ERR "binder: %d: binder_alloc_buf failed " - "for page at %p\n", proc->pid, page_addr); - goto err_alloc_page_failed; - } - tmp_area.addr = page_addr; - tmp_area.size = PAGE_SIZE + PAGE_SIZE /* guard page? */; - page_array_ptr = page; - ret = map_vm_area(&tmp_area, PAGE_KERNEL, &page_array_ptr); - if (ret) { - printk(KERN_ERR "binder: %d: binder_alloc_buf failed " - "to map page at %p in kernel\n", - proc->pid, page_addr); - goto err_map_kernel_failed; - } - user_page_addr = - (uintptr_t)page_addr + proc->user_buffer_offset; - ret = vm_insert_page(vma, user_page_addr, page[0]); - if (ret) { - printk(KERN_ERR "binder: %d: binder_alloc_buf failed " - "to map page at %lx in userspace\n", - proc->pid, user_page_addr); - goto err_vm_insert_page_failed; - } - /* vm_insert_page does not seem to increment the refcount */ - } - if (mm) { - up_write(&mm->mmap_sem); - mmput(mm); - } - return 0; - -free_range: - for (page_addr = end - PAGE_SIZE; page_addr >= start; - page_addr -= PAGE_SIZE) { - page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE]; - if (vma) - zap_page_range(vma, (uintptr_t)page_addr + - proc->user_buffer_offset, PAGE_SIZE, NULL); -err_vm_insert_page_failed: - unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); -err_map_kernel_failed: - __free_page(*page); - *page = NULL; -err_alloc_page_failed: - ; - } -err_no_vma: - if (mm) { - up_write(&mm->mmap_sem); - mmput(mm); - } - return -ENOMEM; -} - -static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, - size_t data_size, - size_t offsets_size, int is_async) -{ - struct rb_node *n = proc->free_buffers.rb_node; - struct binder_buffer *buffer; - size_t buffer_size; - struct rb_node *best_fit = NULL; - void *has_page_addr; - void *end_page_addr; - size_t size; - - if (proc->vma == NULL) { - printk(KERN_ERR "binder: %d: binder_alloc_buf, no vma\n", - proc->pid); - return NULL; - } - - size = ALIGN(data_size, sizeof(void *)) + - ALIGN(offsets_size, sizeof(void *)); - - if (size < data_size || size < offsets_size) { - binder_user_error("binder: %d: got transaction with invalid " - "size %zd-%zd\n", proc->pid, data_size, offsets_size); - return NULL; - } - - if (is_async && - proc->free_async_space < size + sizeof(struct binder_buffer)) { - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: binder_alloc_buf size %zd" - "failed, no async space left\n", proc->pid, size); - return NULL; - } - - while (n) { - buffer = rb_entry(n, struct binder_buffer, rb_node); - BUG_ON(!buffer->free); - buffer_size = binder_buffer_size(proc, buffer); - - if (size < buffer_size) { - best_fit = n; - n = n->rb_left; - } else if (size > buffer_size) - n = n->rb_right; - else { - best_fit = n; - break; - } - } - if (best_fit == NULL) { - printk(KERN_ERR "binder: %d: binder_alloc_buf size %zd failed, " - "no address space\n", proc->pid, size); - return NULL; - } - if (n == NULL) { - buffer = rb_entry(best_fit, struct binder_buffer, rb_node); - buffer_size = binder_buffer_size(proc, buffer); - } - - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: binder_alloc_buf size %zd got buff" - "er %p size %zd\n", proc->pid, size, buffer, buffer_size); - - has_page_addr = - (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK); - if (n == NULL) { - if (size + sizeof(struct binder_buffer) + 4 >= buffer_size) - buffer_size = size; /* no room for other buffers */ - else - buffer_size = size + sizeof(struct binder_buffer); - } - end_page_addr = - (void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size); - if (end_page_addr > has_page_addr) - end_page_addr = has_page_addr; - if (binder_update_page_range(proc, 1, - (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL)) - return NULL; - - rb_erase(best_fit, &proc->free_buffers); - buffer->free = 0; - binder_insert_allocated_buffer(proc, buffer); - if (buffer_size != size) { - struct binder_buffer *new_buffer = (void *)buffer->data + size; - list_add(&new_buffer->entry, &buffer->entry); - new_buffer->free = 1; - binder_insert_free_buffer(proc, new_buffer); - } - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: binder_alloc_buf size %zd got " - "%p\n", proc->pid, size, buffer); - buffer->data_size = data_size; - buffer->offsets_size = offsets_size; - buffer->async_transaction = is_async; - if (is_async) { - proc->free_async_space -= size + sizeof(struct binder_buffer); - binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, - "binder: %d: binder_alloc_buf size %zd " - "async free %zd\n", proc->pid, size, - proc->free_async_space); - } - - return buffer; -} - -static void *buffer_start_page(struct binder_buffer *buffer) -{ - return (void *)((uintptr_t)buffer & PAGE_MASK); -} - -static void *buffer_end_page(struct binder_buffer *buffer) -{ - return (void *)(((uintptr_t)(buffer + 1) - 1) & PAGE_MASK); -} - -static void binder_delete_free_buffer(struct binder_proc *proc, - struct binder_buffer *buffer) -{ - struct binder_buffer *prev, *next = NULL; - int free_page_end = 1; - int free_page_start = 1; - - BUG_ON(proc->buffers.next == &buffer->entry); - prev = list_entry(buffer->entry.prev, struct binder_buffer, entry); - BUG_ON(!prev->free); - if (buffer_end_page(prev) == buffer_start_page(buffer)) { - free_page_start = 0; - if (buffer_end_page(prev) == buffer_end_page(buffer)) - free_page_end = 0; - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: merge free, buffer %p " - "share page with %p\n", proc->pid, buffer, prev); - } - - if (!list_is_last(&buffer->entry, &proc->buffers)) { - next = list_entry(buffer->entry.next, - struct binder_buffer, entry); - if (buffer_start_page(next) == buffer_end_page(buffer)) { - free_page_end = 0; - if (buffer_start_page(next) == - buffer_start_page(buffer)) - free_page_start = 0; - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: merge free, buffer" - " %p share page with %p\n", proc->pid, - buffer, prev); - } - } - list_del(&buffer->entry); - if (free_page_start || free_page_end) { - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: merge free, buffer %p do " - "not share page%s%s with with %p or %p\n", - proc->pid, buffer, free_page_start ? "" : " end", - free_page_end ? "" : " start", prev, next); - binder_update_page_range(proc, 0, free_page_start ? - buffer_start_page(buffer) : buffer_end_page(buffer), - (free_page_end ? buffer_end_page(buffer) : - buffer_start_page(buffer)) + PAGE_SIZE, NULL); - } -} - -static void binder_free_buf(struct binder_proc *proc, - struct binder_buffer *buffer) -{ - size_t size, buffer_size; - - buffer_size = binder_buffer_size(proc, buffer); - - size = ALIGN(buffer->data_size, sizeof(void *)) + - ALIGN(buffer->offsets_size, sizeof(void *)); - - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: binder_free_buf %p size %zd buffer" - "_size %zd\n", proc->pid, buffer, size, buffer_size); - - BUG_ON(buffer->free); - BUG_ON(size > buffer_size); - BUG_ON(buffer->transaction != NULL); - BUG_ON((void *)buffer < proc->buffer); - BUG_ON((void *)buffer > proc->buffer + proc->buffer_size); - - if (buffer->async_transaction) { - proc->free_async_space += size + sizeof(struct binder_buffer); - - binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, - "binder: %d: binder_free_buf size %zd " - "async free %zd\n", proc->pid, size, - proc->free_async_space); - } - - binder_update_page_range(proc, 0, - (void *)PAGE_ALIGN((uintptr_t)buffer->data), - (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK), - NULL); - rb_erase(&buffer->rb_node, &proc->allocated_buffers); - buffer->free = 1; - if (!list_is_last(&buffer->entry, &proc->buffers)) { - struct binder_buffer *next = list_entry(buffer->entry.next, - struct binder_buffer, entry); - if (next->free) { - rb_erase(&next->rb_node, &proc->free_buffers); - binder_delete_free_buffer(proc, next); - } - } - if (proc->buffers.next != &buffer->entry) { - struct binder_buffer *prev = list_entry(buffer->entry.prev, - struct binder_buffer, entry); - if (prev->free) { - binder_delete_free_buffer(proc, buffer); - rb_erase(&prev->rb_node, &proc->free_buffers); - buffer = prev; - } - } - binder_insert_free_buffer(proc, buffer); -} - -static struct binder_node *binder_get_node(struct binder_proc *proc, - void __user *ptr) -{ - struct rb_node *n = proc->nodes.rb_node; - struct binder_node *node; - - while (n) { - node = rb_entry(n, struct binder_node, rb_node); - - if (ptr < node->ptr) - n = n->rb_left; - else if (ptr > node->ptr) - n = n->rb_right; - else - return node; - } - return NULL; -} - -static struct binder_node *binder_new_node(struct binder_proc *proc, - void __user *ptr, - void __user *cookie) -{ - struct rb_node **p = &proc->nodes.rb_node; - struct rb_node *parent = NULL; - struct binder_node *node; - - while (*p) { - parent = *p; - node = rb_entry(parent, struct binder_node, rb_node); - - if (ptr < node->ptr) - p = &(*p)->rb_left; - else if (ptr > node->ptr) - p = &(*p)->rb_right; - else - return NULL; - } - - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (node == NULL) - return NULL; - binder_stats_created(BINDER_STAT_NODE); - rb_link_node(&node->rb_node, parent, p); - rb_insert_color(&node->rb_node, &proc->nodes); - node->debug_id = ++binder_last_id; - node->proc = proc; - node->ptr = ptr; - node->cookie = cookie; - node->work.type = BINDER_WORK_NODE; - INIT_LIST_HEAD(&node->work.entry); - INIT_LIST_HEAD(&node->async_todo); - binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: %d:%d node %d u%p c%p created\n", - proc->pid, current->pid, node->debug_id, - node->ptr, node->cookie); - return node; -} - -static int binder_inc_node(struct binder_node *node, int strong, int internal, - struct list_head *target_list) -{ - if (strong) { - if (internal) { - if (target_list == NULL && - node->internal_strong_refs == 0 && - !(node == binder_context_mgr_node && - node->has_strong_ref)) { - printk(KERN_ERR "binder: invalid inc strong " - "node for %d\n", node->debug_id); - return -EINVAL; - } - node->internal_strong_refs++; - } else - node->local_strong_refs++; - if (!node->has_strong_ref && target_list) { - list_del_init(&node->work.entry); - list_add_tail(&node->work.entry, target_list); - } - } else { - if (!internal) - node->local_weak_refs++; - if (!node->has_weak_ref && list_empty(&node->work.entry)) { - if (target_list == NULL) { - printk(KERN_ERR "binder: invalid inc weak node " - "for %d\n", node->debug_id); - return -EINVAL; - } - list_add_tail(&node->work.entry, target_list); - } - } - return 0; -} - -static int binder_dec_node(struct binder_node *node, int strong, int internal) -{ - if (strong) { - if (internal) - node->internal_strong_refs--; - else - node->local_strong_refs--; - if (node->local_strong_refs || node->internal_strong_refs) - return 0; - } else { - if (!internal) - node->local_weak_refs--; - if (node->local_weak_refs || !hlist_empty(&node->refs)) - return 0; - } - if (node->proc && (node->has_strong_ref || node->has_weak_ref)) { - if (list_empty(&node->work.entry)) { - list_add_tail(&node->work.entry, &node->proc->todo); - wake_up_interruptible(&node->proc->wait); - } - } else { - if (hlist_empty(&node->refs) && !node->local_strong_refs && - !node->local_weak_refs) { - list_del_init(&node->work.entry); - if (node->proc) { - rb_erase(&node->rb_node, &node->proc->nodes); - binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: refless node %d deleted\n", - node->debug_id); - } else { - hlist_del(&node->dead_node); - binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: dead node %d deleted\n", - node->debug_id); - } - kfree(node); - binder_stats_deleted(BINDER_STAT_NODE); - } - } - - return 0; -} - - -static struct binder_ref *binder_get_ref(struct binder_proc *proc, - uint32_t desc) -{ - struct rb_node *n = proc->refs_by_desc.rb_node; - struct binder_ref *ref; - - while (n) { - ref = rb_entry(n, struct binder_ref, rb_node_desc); - - if (desc < ref->desc) - n = n->rb_left; - else if (desc > ref->desc) - n = n->rb_right; - else - return ref; - } - return NULL; -} - -static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, - struct binder_node *node) -{ - struct rb_node *n; - struct rb_node **p = &proc->refs_by_node.rb_node; - struct rb_node *parent = NULL; - struct binder_ref *ref, *new_ref; - - while (*p) { - parent = *p; - ref = rb_entry(parent, struct binder_ref, rb_node_node); - - if (node < ref->node) - p = &(*p)->rb_left; - else if (node > ref->node) - p = &(*p)->rb_right; - else - return ref; - } - new_ref = kzalloc(sizeof(*ref), GFP_KERNEL); - if (new_ref == NULL) - return NULL; - binder_stats_created(BINDER_STAT_REF); - new_ref->debug_id = ++binder_last_id; - new_ref->proc = proc; - new_ref->node = node; - rb_link_node(&new_ref->rb_node_node, parent, p); - rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node); - - new_ref->desc = (node == binder_context_mgr_node) ? 0 : 1; - for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) { - ref = rb_entry(n, struct binder_ref, rb_node_desc); - if (ref->desc > new_ref->desc) - break; - new_ref->desc = ref->desc + 1; - } - - p = &proc->refs_by_desc.rb_node; - while (*p) { - parent = *p; - ref = rb_entry(parent, struct binder_ref, rb_node_desc); - - if (new_ref->desc < ref->desc) - p = &(*p)->rb_left; - else if (new_ref->desc > ref->desc) - p = &(*p)->rb_right; - else - BUG(); - } - rb_link_node(&new_ref->rb_node_desc, parent, p); - rb_insert_color(&new_ref->rb_node_desc, &proc->refs_by_desc); - if (node) { - hlist_add_head(&new_ref->node_entry, &node->refs); - - binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: %d new ref %d desc %d for " - "node %d\n", proc->pid, new_ref->debug_id, - new_ref->desc, node->debug_id); - } else { - binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: %d new ref %d desc %d for " - "dead node\n", proc->pid, new_ref->debug_id, - new_ref->desc); - } - return new_ref; -} - -static void binder_delete_ref(struct binder_ref *ref) -{ - binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: %d delete ref %d desc %d for " - "node %d\n", ref->proc->pid, ref->debug_id, - ref->desc, ref->node->debug_id); - - rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc); - rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node); - if (ref->strong) - binder_dec_node(ref->node, 1, 1); - hlist_del(&ref->node_entry); - binder_dec_node(ref->node, 0, 1); - if (ref->death) { - binder_debug(BINDER_DEBUG_DEAD_BINDER, - "binder: %d delete ref %d desc %d " - "has death notification\n", ref->proc->pid, - ref->debug_id, ref->desc); - list_del(&ref->death->work.entry); - kfree(ref->death); - binder_stats_deleted(BINDER_STAT_DEATH); - } - kfree(ref); - binder_stats_deleted(BINDER_STAT_REF); -} - -static int binder_inc_ref(struct binder_ref *ref, int strong, - struct list_head *target_list) -{ - int ret; - if (strong) { - if (ref->strong == 0) { - ret = binder_inc_node(ref->node, 1, 1, target_list); - if (ret) - return ret; - } - ref->strong++; - } else { - if (ref->weak == 0) { - ret = binder_inc_node(ref->node, 0, 1, target_list); - if (ret) - return ret; - } - ref->weak++; - } - return 0; -} - - -static int binder_dec_ref(struct binder_ref *ref, int strong) -{ - if (strong) { - if (ref->strong == 0) { - binder_user_error("binder: %d invalid dec strong, " - "ref %d desc %d s %d w %d\n", - ref->proc->pid, ref->debug_id, - ref->desc, ref->strong, ref->weak); - return -EINVAL; - } - ref->strong--; - if (ref->strong == 0) { - int ret; - ret = binder_dec_node(ref->node, strong, 1); - if (ret) - return ret; - } - } else { - if (ref->weak == 0) { - binder_user_error("binder: %d invalid dec weak, " - "ref %d desc %d s %d w %d\n", - ref->proc->pid, ref->debug_id, - ref->desc, ref->strong, ref->weak); - return -EINVAL; - } - ref->weak--; - } - if (ref->strong == 0 && ref->weak == 0) - binder_delete_ref(ref); - return 0; -} - -static void binder_pop_transaction(struct binder_thread *target_thread, - struct binder_transaction *t) -{ - if (target_thread) { - BUG_ON(target_thread->transaction_stack != t); - BUG_ON(target_thread->transaction_stack->from != target_thread); - target_thread->transaction_stack = - target_thread->transaction_stack->from_parent; - t->from = NULL; - } - t->need_reply = 0; - if (t->buffer) - t->buffer->transaction = NULL; - kfree(t); - binder_stats_deleted(BINDER_STAT_TRANSACTION); -} - -static void binder_send_failed_reply(struct binder_transaction *t, - uint32_t error_code) -{ - struct binder_thread *target_thread; - BUG_ON(t->flags & TF_ONE_WAY); - while (1) { - target_thread = t->from; - if (target_thread) { - if (target_thread->return_error != BR_OK && - target_thread->return_error2 == BR_OK) { - target_thread->return_error2 = - target_thread->return_error; - target_thread->return_error = BR_OK; - } - if (target_thread->return_error == BR_OK) { - binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "binder: send failed reply for " - "transaction %d to %d:%d\n", - t->debug_id, target_thread->proc->pid, - target_thread->pid); - - binder_pop_transaction(target_thread, t); - target_thread->return_error = error_code; - wake_up_interruptible(&target_thread->wait); - } else { - printk(KERN_ERR "binder: reply failed, target " - "thread, %d:%d, has error code %d " - "already\n", target_thread->proc->pid, - target_thread->pid, - target_thread->return_error); - } - return; - } else { - struct binder_transaction *next = t->from_parent; - - binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "binder: send failed reply " - "for transaction %d, target dead\n", - t->debug_id); - - binder_pop_transaction(target_thread, t); - if (next == NULL) { - binder_debug(BINDER_DEBUG_DEAD_BINDER, - "binder: reply failed," - " no target thread at root\n"); - return; - } - t = next; - binder_debug(BINDER_DEBUG_DEAD_BINDER, - "binder: reply failed, no target " - "thread -- retry %d\n", t->debug_id); - } - } -} - -static void binder_transaction_buffer_release(struct binder_proc *proc, - struct binder_buffer *buffer, - size_t *failed_at) -{ - size_t *offp, *off_end; - int debug_id = buffer->debug_id; - - binder_debug(BINDER_DEBUG_TRANSACTION, - "binder: %d buffer release %d, size %zd-%zd, failed at %p\n", - proc->pid, buffer->debug_id, - buffer->data_size, buffer->offsets_size, failed_at); - - if (buffer->target_node) - binder_dec_node(buffer->target_node, 1, 0); - - offp = (size_t *)(buffer->data + ALIGN(buffer->data_size, sizeof(void *))); - if (failed_at) - off_end = failed_at; - else - off_end = (void *)offp + buffer->offsets_size; - for (; offp < off_end; offp++) { - struct flat_binder_object *fp; - if (*offp > buffer->data_size - sizeof(*fp) || - buffer->data_size < sizeof(*fp) || - !IS_ALIGNED(*offp, sizeof(void *))) { - printk(KERN_ERR "binder: transaction release %d bad" - "offset %zd, size %zd\n", debug_id, - *offp, buffer->data_size); - continue; - } - fp = (struct flat_binder_object *)(buffer->data + *offp); - switch (fp->type) { - case BINDER_TYPE_BINDER: - case BINDER_TYPE_WEAK_BINDER: { - struct binder_node *node = binder_get_node(proc, fp->binder); - if (node == NULL) { - printk(KERN_ERR "binder: transaction release %d" - " bad node %p\n", debug_id, fp->binder); - break; - } - binder_debug(BINDER_DEBUG_TRANSACTION, - " node %d u%p\n", - node->debug_id, node->ptr); - binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0); - } break; - case BINDER_TYPE_HANDLE: - case BINDER_TYPE_WEAK_HANDLE: { - struct binder_ref *ref = binder_get_ref(proc, fp->handle); - if (ref == NULL) { - printk(KERN_ERR "binder: transaction release %d" - " bad handle %ld\n", debug_id, - fp->handle); - break; - } - binder_debug(BINDER_DEBUG_TRANSACTION, - " ref %d desc %d (node %d)\n", - ref->debug_id, ref->desc, ref->node->debug_id); - binder_dec_ref(ref, fp->type == BINDER_TYPE_HANDLE); - } break; - - case BINDER_TYPE_FD: - binder_debug(BINDER_DEBUG_TRANSACTION, - " fd %ld\n", fp->handle); - if (failed_at) - task_close_fd(proc, fp->handle); - break; - - default: - printk(KERN_ERR "binder: transaction release %d bad " - "object type %lx\n", debug_id, fp->type); - break; - } - } -} - -static void binder_transaction(struct binder_proc *proc, - struct binder_thread *thread, - struct binder_transaction_data *tr, int reply) -{ - struct binder_transaction *t; - struct binder_work *tcomplete; - size_t *offp, *off_end; - struct binder_proc *target_proc; - struct binder_thread *target_thread = NULL; - struct binder_node *target_node = NULL; - struct list_head *target_list; - wait_queue_head_t *target_wait; - struct binder_transaction *in_reply_to = NULL; - struct binder_transaction_log_entry *e; - uint32_t return_error; - - e = binder_transaction_log_add(&binder_transaction_log); - e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY); - e->from_proc = proc->pid; - e->from_thread = thread->pid; - e->target_handle = tr->target.handle; - e->data_size = tr->data_size; - e->offsets_size = tr->offsets_size; - - if (reply) { - in_reply_to = thread->transaction_stack; - if (in_reply_to == NULL) { - binder_user_error("binder: %d:%d got reply transaction " - "with no transaction stack\n", - proc->pid, thread->pid); - return_error = BR_FAILED_REPLY; - goto err_empty_call_stack; - } - binder_set_nice(in_reply_to->saved_priority); - if (in_reply_to->to_thread != thread) { - binder_user_error("binder: %d:%d got reply transaction " - "with bad transaction stack," - " transaction %d has target %d:%d\n", - proc->pid, thread->pid, in_reply_to->debug_id, - in_reply_to->to_proc ? - in_reply_to->to_proc->pid : 0, - in_reply_to->to_thread ? - in_reply_to->to_thread->pid : 0); - return_error = BR_FAILED_REPLY; - in_reply_to = NULL; - goto err_bad_call_stack; - } - thread->transaction_stack = in_reply_to->to_parent; - target_thread = in_reply_to->from; - if (target_thread == NULL) { - return_error = BR_DEAD_REPLY; - goto err_dead_binder; - } - if (target_thread->transaction_stack != in_reply_to) { - binder_user_error("binder: %d:%d got reply transaction " - "with bad target transaction stack %d, " - "expected %d\n", - proc->pid, thread->pid, - target_thread->transaction_stack ? - target_thread->transaction_stack->debug_id : 0, - in_reply_to->debug_id); - return_error = BR_FAILED_REPLY; - in_reply_to = NULL; - target_thread = NULL; - goto err_dead_binder; - } - target_proc = target_thread->proc; - } else { - if (tr->target.handle) { - struct binder_ref *ref; - ref = binder_get_ref(proc, tr->target.handle); - if (ref == NULL) { - binder_user_error("binder: %d:%d got " - "transaction to invalid handle\n", - proc->pid, thread->pid); - return_error = BR_FAILED_REPLY; - goto err_invalid_target_handle; - } - target_node = ref->node; - } else { - target_node = binder_context_mgr_node; - if (target_node == NULL) { - return_error = BR_DEAD_REPLY; - goto err_no_context_mgr_node; - } - } - e->to_node = target_node->debug_id; - target_proc = target_node->proc; - if (target_proc == NULL) { - return_error = BR_DEAD_REPLY; - goto err_dead_binder; - } - if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) { - struct binder_transaction *tmp; - tmp = thread->transaction_stack; - if (tmp->to_thread != thread) { - binder_user_error("binder: %d:%d got new " - "transaction with bad transaction stack" - ", transaction %d has target %d:%d\n", - proc->pid, thread->pid, tmp->debug_id, - tmp->to_proc ? tmp->to_proc->pid : 0, - tmp->to_thread ? - tmp->to_thread->pid : 0); - return_error = BR_FAILED_REPLY; - goto err_bad_call_stack; - } - while (tmp) { - if (tmp->from && tmp->from->proc == target_proc) - target_thread = tmp->from; - tmp = tmp->from_parent; - } - } - } - if (target_thread) { - e->to_thread = target_thread->pid; - target_list = &target_thread->todo; - target_wait = &target_thread->wait; - } else { - target_list = &target_proc->todo; - target_wait = &target_proc->wait; - } - e->to_proc = target_proc->pid; - - /* TODO: reuse incoming transaction for reply */ - t = kzalloc(sizeof(*t), GFP_KERNEL); - if (t == NULL) { - return_error = BR_FAILED_REPLY; - goto err_alloc_t_failed; - } - binder_stats_created(BINDER_STAT_TRANSACTION); - - tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL); - if (tcomplete == NULL) { - return_error = BR_FAILED_REPLY; - goto err_alloc_tcomplete_failed; - } - binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE); - - t->debug_id = ++binder_last_id; - e->debug_id = t->debug_id; - - if (reply) - binder_debug(BINDER_DEBUG_TRANSACTION, - "binder: %d:%d BC_REPLY %d -> %d:%d, " - "data %p-%p size %zd-%zd\n", - proc->pid, thread->pid, t->debug_id, - target_proc->pid, target_thread->pid, - tr->data.ptr.buffer, tr->data.ptr.offsets, - tr->data_size, tr->offsets_size); - else - binder_debug(BINDER_DEBUG_TRANSACTION, - "binder: %d:%d BC_TRANSACTION %d -> " - "%d - node %d, data %p-%p size %zd-%zd\n", - proc->pid, thread->pid, t->debug_id, - target_proc->pid, target_node->debug_id, - tr->data.ptr.buffer, tr->data.ptr.offsets, - tr->data_size, tr->offsets_size); - - if (!reply && !(tr->flags & TF_ONE_WAY)) - t->from = thread; - else - t->from = NULL; - t->sender_euid = proc->tsk->cred->euid; - t->to_proc = target_proc; - t->to_thread = target_thread; - t->code = tr->code; - t->flags = tr->flags; - t->priority = task_nice(current); - t->buffer = binder_alloc_buf(target_proc, tr->data_size, - tr->offsets_size, !reply && (t->flags & TF_ONE_WAY)); - if (t->buffer == NULL) { - return_error = BR_FAILED_REPLY; - goto err_binder_alloc_buf_failed; - } - t->buffer->allow_user_free = 0; - t->buffer->debug_id = t->debug_id; - t->buffer->transaction = t; - t->buffer->target_node = target_node; - if (target_node) - binder_inc_node(target_node, 1, 0, NULL); - - offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *))); - - if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) { - binder_user_error("binder: %d:%d got transaction with invalid " - "data ptr\n", proc->pid, thread->pid); - return_error = BR_FAILED_REPLY; - goto err_copy_data_failed; - } - if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) { - binder_user_error("binder: %d:%d got transaction with invalid " - "offsets ptr\n", proc->pid, thread->pid); - return_error = BR_FAILED_REPLY; - goto err_copy_data_failed; - } - if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) { - binder_user_error("binder: %d:%d got transaction with " - "invalid offsets size, %zd\n", - proc->pid, thread->pid, tr->offsets_size); - return_error = BR_FAILED_REPLY; - goto err_bad_offset; - } - off_end = (void *)offp + tr->offsets_size; - for (; offp < off_end; offp++) { - struct flat_binder_object *fp; - if (*offp > t->buffer->data_size - sizeof(*fp) || - t->buffer->data_size < sizeof(*fp) || - !IS_ALIGNED(*offp, sizeof(void *))) { - binder_user_error("binder: %d:%d got transaction with " - "invalid offset, %zd\n", - proc->pid, thread->pid, *offp); - return_error = BR_FAILED_REPLY; - goto err_bad_offset; - } - fp = (struct flat_binder_object *)(t->buffer->data + *offp); - switch (fp->type) { - case BINDER_TYPE_BINDER: - case BINDER_TYPE_WEAK_BINDER: { - struct binder_ref *ref; - struct binder_node *node = binder_get_node(proc, fp->binder); - if (node == NULL) { - node = binder_new_node(proc, fp->binder, fp->cookie); - if (node == NULL) { - return_error = BR_FAILED_REPLY; - goto err_binder_new_node_failed; - } - node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK; - node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS); - } - if (fp->cookie != node->cookie) { - binder_user_error("binder: %d:%d sending u%p " - "node %d, cookie mismatch %p != %p\n", - proc->pid, thread->pid, - fp->binder, node->debug_id, - fp->cookie, node->cookie); - goto err_binder_get_ref_for_node_failed; - } - ref = binder_get_ref_for_node(target_proc, node); - if (ref == NULL) { - return_error = BR_FAILED_REPLY; - goto err_binder_get_ref_for_node_failed; - } - if (fp->type == BINDER_TYPE_BINDER) - fp->type = BINDER_TYPE_HANDLE; - else - fp->type = BINDER_TYPE_WEAK_HANDLE; - fp->handle = ref->desc; - binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE, - &thread->todo); - - binder_debug(BINDER_DEBUG_TRANSACTION, - " node %d u%p -> ref %d desc %d\n", - node->debug_id, node->ptr, ref->debug_id, - ref->desc); - } break; - case BINDER_TYPE_HANDLE: - case BINDER_TYPE_WEAK_HANDLE: { - struct binder_ref *ref = binder_get_ref(proc, fp->handle); - if (ref == NULL) { - binder_user_error("binder: %d:%d got " - "transaction with invalid " - "handle, %ld\n", proc->pid, - thread->pid, fp->handle); - return_error = BR_FAILED_REPLY; - goto err_binder_get_ref_failed; - } - if (ref->node->proc == target_proc) { - if (fp->type == BINDER_TYPE_HANDLE) - fp->type = BINDER_TYPE_BINDER; - else - fp->type = BINDER_TYPE_WEAK_BINDER; - fp->binder = ref->node->ptr; - fp->cookie = ref->node->cookie; - binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL); - binder_debug(BINDER_DEBUG_TRANSACTION, - " ref %d desc %d -> node %d u%p\n", - ref->debug_id, ref->desc, ref->node->debug_id, - ref->node->ptr); - } else { - struct binder_ref *new_ref; - new_ref = binder_get_ref_for_node(target_proc, ref->node); - if (new_ref == NULL) { - return_error = BR_FAILED_REPLY; - goto err_binder_get_ref_for_node_failed; - } - fp->handle = new_ref->desc; - binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL); - binder_debug(BINDER_DEBUG_TRANSACTION, - " ref %d desc %d -> ref %d desc %d (node %d)\n", - ref->debug_id, ref->desc, new_ref->debug_id, - new_ref->desc, ref->node->debug_id); - } - } break; - - case BINDER_TYPE_FD: { - int target_fd; - struct file *file; - - if (reply) { - if (!(in_reply_to->flags & TF_ACCEPT_FDS)) { - binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n", - proc->pid, thread->pid, fp->handle); - return_error = BR_FAILED_REPLY; - goto err_fd_not_allowed; - } - } else if (!target_node->accept_fds) { - binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n", - proc->pid, thread->pid, fp->handle); - return_error = BR_FAILED_REPLY; - goto err_fd_not_allowed; - } - - file = fget(fp->handle); - if (file == NULL) { - binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n", - proc->pid, thread->pid, fp->handle); - return_error = BR_FAILED_REPLY; - goto err_fget_failed; - } - target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC); - if (target_fd < 0) { - fput(file); - return_error = BR_FAILED_REPLY; - goto err_get_unused_fd_failed; - } - task_fd_install(target_proc, target_fd, file); - binder_debug(BINDER_DEBUG_TRANSACTION, - " fd %ld -> %d\n", fp->handle, target_fd); - /* TODO: fput? */ - fp->handle = target_fd; - } break; - - default: - binder_user_error("binder: %d:%d got transactio" - "n with invalid object type, %lx\n", - proc->pid, thread->pid, fp->type); - return_error = BR_FAILED_REPLY; - goto err_bad_object_type; - } - } - if (reply) { - BUG_ON(t->buffer->async_transaction != 0); - binder_pop_transaction(target_thread, in_reply_to); - } else if (!(t->flags & TF_ONE_WAY)) { - BUG_ON(t->buffer->async_transaction != 0); - t->need_reply = 1; - t->from_parent = thread->transaction_stack; - thread->transaction_stack = t; - } else { - BUG_ON(target_node == NULL); - BUG_ON(t->buffer->async_transaction != 1); - if (target_node->has_async_transaction) { - target_list = &target_node->async_todo; - target_wait = NULL; - } else - target_node->has_async_transaction = 1; - } - t->work.type = BINDER_WORK_TRANSACTION; - list_add_tail(&t->work.entry, target_list); - tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE; - list_add_tail(&tcomplete->entry, &thread->todo); - if (target_wait) - wake_up_interruptible(target_wait); - return; - -err_get_unused_fd_failed: -err_fget_failed: -err_fd_not_allowed: -err_binder_get_ref_for_node_failed: -err_binder_get_ref_failed: -err_binder_new_node_failed: -err_bad_object_type: -err_bad_offset: -err_copy_data_failed: - binder_transaction_buffer_release(target_proc, t->buffer, offp); - t->buffer->transaction = NULL; - binder_free_buf(target_proc, t->buffer); -err_binder_alloc_buf_failed: - kfree(tcomplete); - binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); -err_alloc_tcomplete_failed: - kfree(t); - binder_stats_deleted(BINDER_STAT_TRANSACTION); -err_alloc_t_failed: -err_bad_call_stack: -err_empty_call_stack: -err_dead_binder: -err_invalid_target_handle: -err_no_context_mgr_node: - binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "binder: %d:%d transaction failed %d, size %zd-%zd\n", - proc->pid, thread->pid, return_error, - tr->data_size, tr->offsets_size); - - { - struct binder_transaction_log_entry *fe; - fe = binder_transaction_log_add(&binder_transaction_log_failed); - *fe = *e; - } - - BUG_ON(thread->return_error != BR_OK); - if (in_reply_to) { - thread->return_error = BR_TRANSACTION_COMPLETE; - binder_send_failed_reply(in_reply_to, return_error); - } else - thread->return_error = return_error; -} - -int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, - void __user *buffer, int size, signed long *consumed) -{ - uint32_t cmd; - void __user *ptr = buffer + *consumed; - void __user *end = buffer + size; - - while (ptr < end && thread->return_error == BR_OK) { - if (get_user(cmd, (uint32_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(uint32_t); - if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) { - binder_stats.bc[_IOC_NR(cmd)]++; - proc->stats.bc[_IOC_NR(cmd)]++; - thread->stats.bc[_IOC_NR(cmd)]++; - } - switch (cmd) { - case BC_INCREFS: - case BC_ACQUIRE: - case BC_RELEASE: - case BC_DECREFS: { - uint32_t target; - struct binder_ref *ref; - const char *debug_string; - - if (get_user(target, (uint32_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(uint32_t); - if (target == 0 && binder_context_mgr_node && - (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) { - ref = binder_get_ref_for_node(proc, - binder_context_mgr_node); - if (ref->desc != target) { - binder_user_error("binder: %d:" - "%d tried to acquire " - "reference to desc 0, " - "got %d instead\n", - proc->pid, thread->pid, - ref->desc); - } - } else - ref = binder_get_ref(proc, target); - if (ref == NULL) { - binder_user_error("binder: %d:%d refcou" - "nt change on invalid ref %d\n", - proc->pid, thread->pid, target); - break; - } - switch (cmd) { - case BC_INCREFS: - debug_string = "IncRefs"; - binder_inc_ref(ref, 0, NULL); - break; - case BC_ACQUIRE: - debug_string = "Acquire"; - binder_inc_ref(ref, 1, NULL); - break; - case BC_RELEASE: - debug_string = "Release"; - binder_dec_ref(ref, 1); - break; - case BC_DECREFS: - default: - debug_string = "DecRefs"; - binder_dec_ref(ref, 0); - break; - } - binder_debug(BINDER_DEBUG_USER_REFS, - "binder: %d:%d %s ref %d desc %d s %d w %d for node %d\n", - proc->pid, thread->pid, debug_string, ref->debug_id, - ref->desc, ref->strong, ref->weak, ref->node->debug_id); - break; - } - case BC_INCREFS_DONE: - case BC_ACQUIRE_DONE: { - void __user *node_ptr; - void *cookie; - struct binder_node *node; - - if (get_user(node_ptr, (void * __user *)ptr)) - return -EFAULT; - ptr += sizeof(void *); - if (get_user(cookie, (void * __user *)ptr)) - return -EFAULT; - ptr += sizeof(void *); - node = binder_get_node(proc, node_ptr); - if (node == NULL) { - binder_user_error("binder: %d:%d " - "%s u%p no match\n", - proc->pid, thread->pid, - cmd == BC_INCREFS_DONE ? - "BC_INCREFS_DONE" : - "BC_ACQUIRE_DONE", - node_ptr); - break; - } - if (cookie != node->cookie) { - binder_user_error("binder: %d:%d %s u%p node %d" - " cookie mismatch %p != %p\n", - proc->pid, thread->pid, - cmd == BC_INCREFS_DONE ? - "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", - node_ptr, node->debug_id, - cookie, node->cookie); - break; - } - if (cmd == BC_ACQUIRE_DONE) { - if (node->pending_strong_ref == 0) { - binder_user_error("binder: %d:%d " - "BC_ACQUIRE_DONE node %d has " - "no pending acquire request\n", - proc->pid, thread->pid, - node->debug_id); - break; - } - node->pending_strong_ref = 0; - } else { - if (node->pending_weak_ref == 0) { - binder_user_error("binder: %d:%d " - "BC_INCREFS_DONE node %d has " - "no pending increfs request\n", - proc->pid, thread->pid, - node->debug_id); - break; - } - node->pending_weak_ref = 0; - } - binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0); - binder_debug(BINDER_DEBUG_USER_REFS, - "binder: %d:%d %s node %d ls %d lw %d\n", - proc->pid, thread->pid, - cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", - node->debug_id, node->local_strong_refs, node->local_weak_refs); - break; - } - case BC_ATTEMPT_ACQUIRE: - printk(KERN_ERR "binder: BC_ATTEMPT_ACQUIRE not supported\n"); - return -EINVAL; - case BC_ACQUIRE_RESULT: - printk(KERN_ERR "binder: BC_ACQUIRE_RESULT not supported\n"); - return -EINVAL; - - case BC_FREE_BUFFER: { - void __user *data_ptr; - struct binder_buffer *buffer; - - if (get_user(data_ptr, (void * __user *)ptr)) - return -EFAULT; - ptr += sizeof(void *); - - buffer = binder_buffer_lookup(proc, data_ptr); - if (buffer == NULL) { - binder_user_error("binder: %d:%d " - "BC_FREE_BUFFER u%p no match\n", - proc->pid, thread->pid, data_ptr); - break; - } - if (!buffer->allow_user_free) { - binder_user_error("binder: %d:%d " - "BC_FREE_BUFFER u%p matched " - "unreturned buffer\n", - proc->pid, thread->pid, data_ptr); - break; - } - binder_debug(BINDER_DEBUG_FREE_BUFFER, - "binder: %d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n", - proc->pid, thread->pid, data_ptr, buffer->debug_id, - buffer->transaction ? "active" : "finished"); - - if (buffer->transaction) { - buffer->transaction->buffer = NULL; - buffer->transaction = NULL; - } - if (buffer->async_transaction && buffer->target_node) { - BUG_ON(!buffer->target_node->has_async_transaction); - if (list_empty(&buffer->target_node->async_todo)) - buffer->target_node->has_async_transaction = 0; - else - list_move_tail(buffer->target_node->async_todo.next, &thread->todo); - } - binder_transaction_buffer_release(proc, buffer, NULL); - binder_free_buf(proc, buffer); - break; - } - - case BC_TRANSACTION: - case BC_REPLY: { - struct binder_transaction_data tr; - - if (copy_from_user(&tr, ptr, sizeof(tr))) - return -EFAULT; - ptr += sizeof(tr); - binder_transaction(proc, thread, &tr, cmd == BC_REPLY); - break; - } - - case BC_REGISTER_LOOPER: - binder_debug(BINDER_DEBUG_THREADS, - "binder: %d:%d BC_REGISTER_LOOPER\n", - proc->pid, thread->pid); - if (thread->looper & BINDER_LOOPER_STATE_ENTERED) { - thread->looper |= BINDER_LOOPER_STATE_INVALID; - binder_user_error("binder: %d:%d ERROR:" - " BC_REGISTER_LOOPER called " - "after BC_ENTER_LOOPER\n", - proc->pid, thread->pid); - } else if (proc->requested_threads == 0) { - thread->looper |= BINDER_LOOPER_STATE_INVALID; - binder_user_error("binder: %d:%d ERROR:" - " BC_REGISTER_LOOPER called " - "without request\n", - proc->pid, thread->pid); - } else { - proc->requested_threads--; - proc->requested_threads_started++; - } - thread->looper |= BINDER_LOOPER_STATE_REGISTERED; - break; - case BC_ENTER_LOOPER: - binder_debug(BINDER_DEBUG_THREADS, - "binder: %d:%d BC_ENTER_LOOPER\n", - proc->pid, thread->pid); - if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) { - thread->looper |= BINDER_LOOPER_STATE_INVALID; - binder_user_error("binder: %d:%d ERROR:" - " BC_ENTER_LOOPER called after " - "BC_REGISTER_LOOPER\n", - proc->pid, thread->pid); - } - thread->looper |= BINDER_LOOPER_STATE_ENTERED; - break; - case BC_EXIT_LOOPER: - binder_debug(BINDER_DEBUG_THREADS, - "binder: %d:%d BC_EXIT_LOOPER\n", - proc->pid, thread->pid); - thread->looper |= BINDER_LOOPER_STATE_EXITED; - break; - - case BC_REQUEST_DEATH_NOTIFICATION: - case BC_CLEAR_DEATH_NOTIFICATION: { - uint32_t target; - void __user *cookie; - struct binder_ref *ref; - struct binder_ref_death *death; - - if (get_user(target, (uint32_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(uint32_t); - if (get_user(cookie, (void __user * __user *)ptr)) - return -EFAULT; - ptr += sizeof(void *); - ref = binder_get_ref(proc, target); - if (ref == NULL) { - binder_user_error("binder: %d:%d %s " - "invalid ref %d\n", - proc->pid, thread->pid, - cmd == BC_REQUEST_DEATH_NOTIFICATION ? - "BC_REQUEST_DEATH_NOTIFICATION" : - "BC_CLEAR_DEATH_NOTIFICATION", - target); - break; - } - - binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, - "binder: %d:%d %s %p ref %d desc %d s %d w %d for node %d\n", - proc->pid, thread->pid, - cmd == BC_REQUEST_DEATH_NOTIFICATION ? - "BC_REQUEST_DEATH_NOTIFICATION" : - "BC_CLEAR_DEATH_NOTIFICATION", - cookie, ref->debug_id, ref->desc, - ref->strong, ref->weak, ref->node->debug_id); - - if (cmd == BC_REQUEST_DEATH_NOTIFICATION) { - if (ref->death) { - binder_user_error("binder: %d:%" - "d BC_REQUEST_DEATH_NOTI" - "FICATION death notific" - "ation already set\n", - proc->pid, thread->pid); - break; - } - death = kzalloc(sizeof(*death), GFP_KERNEL); - if (death == NULL) { - thread->return_error = BR_ERROR; - binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "binder: %d:%d " - "BC_REQUEST_DEATH_NOTIFICATION failed\n", - proc->pid, thread->pid); - break; - } - binder_stats_created(BINDER_STAT_DEATH); - INIT_LIST_HEAD(&death->work.entry); - death->cookie = cookie; - ref->death = death; - if (ref->node->proc == NULL) { - ref->death->work.type = BINDER_WORK_DEAD_BINDER; - if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { - list_add_tail(&ref->death->work.entry, &thread->todo); - } else { - list_add_tail(&ref->death->work.entry, &proc->todo); - wake_up_interruptible(&proc->wait); - } - } - } else { - if (ref->death == NULL) { - binder_user_error("binder: %d:%" - "d BC_CLEAR_DEATH_NOTIFI" - "CATION death notificat" - "ion not active\n", - proc->pid, thread->pid); - break; - } - death = ref->death; - if (death->cookie != cookie) { - binder_user_error("binder: %d:%" - "d BC_CLEAR_DEATH_NOTIFI" - "CATION death notificat" - "ion cookie mismatch " - "%p != %p\n", - proc->pid, thread->pid, - death->cookie, cookie); - break; - } - ref->death = NULL; - if (list_empty(&death->work.entry)) { - death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION; - if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { - list_add_tail(&death->work.entry, &thread->todo); - } else { - list_add_tail(&death->work.entry, &proc->todo); - wake_up_interruptible(&proc->wait); - } - } else { - BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER); - death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR; - } - } - } break; - case BC_DEAD_BINDER_DONE: { - struct binder_work *w; - void __user *cookie; - struct binder_ref_death *death = NULL; - if (get_user(cookie, (void __user * __user *)ptr)) - return -EFAULT; - - ptr += sizeof(void *); - list_for_each_entry(w, &proc->delivered_death, entry) { - struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work); - if (tmp_death->cookie == cookie) { - death = tmp_death; - break; - } - } - binder_debug(BINDER_DEBUG_DEAD_BINDER, - "binder: %d:%d BC_DEAD_BINDER_DONE %p found %p\n", - proc->pid, thread->pid, cookie, death); - if (death == NULL) { - binder_user_error("binder: %d:%d BC_DEAD" - "_BINDER_DONE %p not found\n", - proc->pid, thread->pid, cookie); - break; - } - - list_del_init(&death->work.entry); - if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) { - death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION; - if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { - list_add_tail(&death->work.entry, &thread->todo); - } else { - list_add_tail(&death->work.entry, &proc->todo); - wake_up_interruptible(&proc->wait); - } - } - } break; - - default: - printk(KERN_ERR "binder: %d:%d unknown command %d\n", - proc->pid, thread->pid, cmd); - return -EINVAL; - } - *consumed = ptr - buffer; - } - return 0; -} - -void binder_stat_br(struct binder_proc *proc, struct binder_thread *thread, - uint32_t cmd) -{ - if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) { - binder_stats.br[_IOC_NR(cmd)]++; - proc->stats.br[_IOC_NR(cmd)]++; - thread->stats.br[_IOC_NR(cmd)]++; - } -} - -static int binder_has_proc_work(struct binder_proc *proc, - struct binder_thread *thread) -{ - return !list_empty(&proc->todo) || - (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN); -} - -static int binder_has_thread_work(struct binder_thread *thread) -{ - return !list_empty(&thread->todo) || thread->return_error != BR_OK || - (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN); -} - -static int binder_thread_read(struct binder_proc *proc, - struct binder_thread *thread, - void __user *buffer, int size, - signed long *consumed, int non_block) -{ - void __user *ptr = buffer + *consumed; - void __user *end = buffer + size; - - int ret = 0; - int wait_for_proc_work; - - if (*consumed == 0) { - if (put_user(BR_NOOP, (uint32_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(uint32_t); - } - -retry: - wait_for_proc_work = thread->transaction_stack == NULL && - list_empty(&thread->todo); - - if (thread->return_error != BR_OK && ptr < end) { - if (thread->return_error2 != BR_OK) { - if (put_user(thread->return_error2, (uint32_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(uint32_t); - if (ptr == end) - goto done; - thread->return_error2 = BR_OK; - } - if (put_user(thread->return_error, (uint32_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(uint32_t); - thread->return_error = BR_OK; - goto done; - } - - - thread->looper |= BINDER_LOOPER_STATE_WAITING; - if (wait_for_proc_work) - proc->ready_threads++; - mutex_unlock(&binder_lock); - if (wait_for_proc_work) { - if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED | - BINDER_LOOPER_STATE_ENTERED))) { - binder_user_error("binder: %d:%d ERROR: Thread waiting " - "for process work before calling BC_REGISTER_" - "LOOPER or BC_ENTER_LOOPER (state %x)\n", - proc->pid, thread->pid, thread->looper); - wait_event_interruptible(binder_user_error_wait, - binder_stop_on_user_error < 2); - } - binder_set_nice(proc->default_priority); - if (non_block) { - if (!binder_has_proc_work(proc, thread)) - ret = -EAGAIN; - } else - ret = wait_event_interruptible_exclusive(proc->wait, binder_has_proc_work(proc, thread)); - } else { - if (non_block) { - if (!binder_has_thread_work(thread)) - ret = -EAGAIN; - } else - ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread)); - } - mutex_lock(&binder_lock); - if (wait_for_proc_work) - proc->ready_threads--; - thread->looper &= ~BINDER_LOOPER_STATE_WAITING; - - if (ret) - return ret; - - while (1) { - uint32_t cmd; - struct binder_transaction_data tr; - struct binder_work *w; - struct binder_transaction *t = NULL; - - if (!list_empty(&thread->todo)) - w = list_first_entry(&thread->todo, struct binder_work, entry); - else if (!list_empty(&proc->todo) && wait_for_proc_work) - w = list_first_entry(&proc->todo, struct binder_work, entry); - else { - if (ptr - buffer == 4 && !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN)) /* no data added */ - goto retry; - break; - } - - if (end - ptr < sizeof(tr) + 4) - break; - - switch (w->type) { - case BINDER_WORK_TRANSACTION: { - t = container_of(w, struct binder_transaction, work); - } break; - case BINDER_WORK_TRANSACTION_COMPLETE: { - cmd = BR_TRANSACTION_COMPLETE; - if (put_user(cmd, (uint32_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(uint32_t); - - binder_stat_br(proc, thread, cmd); - binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE, - "binder: %d:%d BR_TRANSACTION_COMPLETE\n", - proc->pid, thread->pid); - - list_del(&w->entry); - kfree(w); - binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); - } break; - case BINDER_WORK_NODE: { - struct binder_node *node = container_of(w, struct binder_node, work); - uint32_t cmd = BR_NOOP; - const char *cmd_name; - int strong = node->internal_strong_refs || node->local_strong_refs; - int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong; - if (weak && !node->has_weak_ref) { - cmd = BR_INCREFS; - cmd_name = "BR_INCREFS"; - node->has_weak_ref = 1; - node->pending_weak_ref = 1; - node->local_weak_refs++; - } else if (strong && !node->has_strong_ref) { - cmd = BR_ACQUIRE; - cmd_name = "BR_ACQUIRE"; - node->has_strong_ref = 1; - node->pending_strong_ref = 1; - node->local_strong_refs++; - } else if (!strong && node->has_strong_ref) { - cmd = BR_RELEASE; - cmd_name = "BR_RELEASE"; - node->has_strong_ref = 0; - } else if (!weak && node->has_weak_ref) { - cmd = BR_DECREFS; - cmd_name = "BR_DECREFS"; - node->has_weak_ref = 0; - } - if (cmd != BR_NOOP) { - if (put_user(cmd, (uint32_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(uint32_t); - if (put_user(node->ptr, (void * __user *)ptr)) - return -EFAULT; - ptr += sizeof(void *); - if (put_user(node->cookie, (void * __user *)ptr)) - return -EFAULT; - ptr += sizeof(void *); - - binder_stat_br(proc, thread, cmd); - binder_debug(BINDER_DEBUG_USER_REFS, - "binder: %d:%d %s %d u%p c%p\n", - proc->pid, thread->pid, cmd_name, node->debug_id, node->ptr, node->cookie); - } else { - list_del_init(&w->entry); - if (!weak && !strong) { - binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: %d:%d node %d u%p c%p deleted\n", - proc->pid, thread->pid, node->debug_id, - node->ptr, node->cookie); - rb_erase(&node->rb_node, &proc->nodes); - kfree(node); - binder_stats_deleted(BINDER_STAT_NODE); - } else { - binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: %d:%d node %d u%p c%p state unchanged\n", - proc->pid, thread->pid, node->debug_id, node->ptr, - node->cookie); - } - } - } break; - case BINDER_WORK_DEAD_BINDER: - case BINDER_WORK_DEAD_BINDER_AND_CLEAR: - case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: { - struct binder_ref_death *death; - uint32_t cmd; - - death = container_of(w, struct binder_ref_death, work); - if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) - cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE; - else - cmd = BR_DEAD_BINDER; - if (put_user(cmd, (uint32_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(uint32_t); - if (put_user(death->cookie, (void * __user *)ptr)) - return -EFAULT; - ptr += sizeof(void *); - binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, - "binder: %d:%d %s %p\n", - proc->pid, thread->pid, - cmd == BR_DEAD_BINDER ? - "BR_DEAD_BINDER" : - "BR_CLEAR_DEATH_NOTIFICATION_DONE", - death->cookie); - - if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) { - list_del(&w->entry); - kfree(death); - binder_stats_deleted(BINDER_STAT_DEATH); - } else - list_move(&w->entry, &proc->delivered_death); - if (cmd == BR_DEAD_BINDER) - goto done; /* DEAD_BINDER notifications can cause transactions */ - } break; - } - - if (!t) - continue; - - BUG_ON(t->buffer == NULL); - if (t->buffer->target_node) { - struct binder_node *target_node = t->buffer->target_node; - tr.target.ptr = target_node->ptr; - tr.cookie = target_node->cookie; - t->saved_priority = task_nice(current); - if (t->priority < target_node->min_priority && - !(t->flags & TF_ONE_WAY)) - binder_set_nice(t->priority); - else if (!(t->flags & TF_ONE_WAY) || - t->saved_priority > target_node->min_priority) - binder_set_nice(target_node->min_priority); - cmd = BR_TRANSACTION; - } else { - tr.target.ptr = NULL; - tr.cookie = NULL; - cmd = BR_REPLY; - } - tr.code = t->code; - tr.flags = t->flags; - tr.sender_euid = t->sender_euid; - - if (t->from) { - struct task_struct *sender = t->from->proc->tsk; - tr.sender_pid = task_tgid_nr_ns(sender, - current->nsproxy->pid_ns); - } else { - tr.sender_pid = 0; - } - - tr.data_size = t->buffer->data_size; - tr.offsets_size = t->buffer->offsets_size; - tr.data.ptr.buffer = (void *)t->buffer->data + - proc->user_buffer_offset; - tr.data.ptr.offsets = tr.data.ptr.buffer + - ALIGN(t->buffer->data_size, - sizeof(void *)); - - if (put_user(cmd, (uint32_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(uint32_t); - if (copy_to_user(ptr, &tr, sizeof(tr))) - return -EFAULT; - ptr += sizeof(tr); - - binder_stat_br(proc, thread, cmd); - binder_debug(BINDER_DEBUG_TRANSACTION, - "binder: %d:%d %s %d %d:%d, cmd %d" - "size %zd-%zd ptr %p-%p\n", - proc->pid, thread->pid, - (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" : - "BR_REPLY", - t->debug_id, t->from ? t->from->proc->pid : 0, - t->from ? t->from->pid : 0, cmd, - t->buffer->data_size, t->buffer->offsets_size, - tr.data.ptr.buffer, tr.data.ptr.offsets); - - list_del(&t->work.entry); - t->buffer->allow_user_free = 1; - if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) { - t->to_parent = thread->transaction_stack; - t->to_thread = thread; - thread->transaction_stack = t; - } else { - t->buffer->transaction = NULL; - kfree(t); - binder_stats_deleted(BINDER_STAT_TRANSACTION); - } - break; - } - -done: - - *consumed = ptr - buffer; - if (proc->requested_threads + proc->ready_threads == 0 && - proc->requested_threads_started < proc->max_threads && - (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | - BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */ - /*spawn a new thread if we leave this out */) { - proc->requested_threads++; - binder_debug(BINDER_DEBUG_THREADS, - "binder: %d:%d BR_SPAWN_LOOPER\n", - proc->pid, thread->pid); - if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer)) - return -EFAULT; - } - return 0; -} - -static void binder_release_work(struct list_head *list) -{ - struct binder_work *w; - while (!list_empty(list)) { - w = list_first_entry(list, struct binder_work, entry); - list_del_init(&w->entry); - switch (w->type) { - case BINDER_WORK_TRANSACTION: { - struct binder_transaction *t; - - t = container_of(w, struct binder_transaction, work); - if (t->buffer->target_node && !(t->flags & TF_ONE_WAY)) - binder_send_failed_reply(t, BR_DEAD_REPLY); - } break; - case BINDER_WORK_TRANSACTION_COMPLETE: { - kfree(w); - binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); - } break; - default: - break; - } - } - -} - -static struct binder_thread *binder_get_thread(struct binder_proc *proc) -{ - struct binder_thread *thread = NULL; - struct rb_node *parent = NULL; - struct rb_node **p = &proc->threads.rb_node; - - while (*p) { - parent = *p; - thread = rb_entry(parent, struct binder_thread, rb_node); - - if (current->pid < thread->pid) - p = &(*p)->rb_left; - else if (current->pid > thread->pid) - p = &(*p)->rb_right; - else - break; - } - if (*p == NULL) { - thread = kzalloc(sizeof(*thread), GFP_KERNEL); - if (thread == NULL) - return NULL; - binder_stats_created(BINDER_STAT_THREAD); - thread->proc = proc; - thread->pid = current->pid; - init_waitqueue_head(&thread->wait); - INIT_LIST_HEAD(&thread->todo); - rb_link_node(&thread->rb_node, parent, p); - rb_insert_color(&thread->rb_node, &proc->threads); - thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN; - thread->return_error = BR_OK; - thread->return_error2 = BR_OK; - } - return thread; -} - -static int binder_free_thread(struct binder_proc *proc, - struct binder_thread *thread) -{ - struct binder_transaction *t; - struct binder_transaction *send_reply = NULL; - int active_transactions = 0; - - rb_erase(&thread->rb_node, &proc->threads); - t = thread->transaction_stack; - if (t && t->to_thread == thread) - send_reply = t; - while (t) { - active_transactions++; - binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, - "binder: release %d:%d transaction %d " - "%s, still active\n", proc->pid, thread->pid, - t->debug_id, - (t->to_thread == thread) ? "in" : "out"); - - if (t->to_thread == thread) { - t->to_proc = NULL; - t->to_thread = NULL; - if (t->buffer) { - t->buffer->transaction = NULL; - t->buffer = NULL; - } - t = t->to_parent; - } else if (t->from == thread) { - t->from = NULL; - t = t->from_parent; - } else - BUG(); - } - if (send_reply) - binder_send_failed_reply(send_reply, BR_DEAD_REPLY); - binder_release_work(&thread->todo); - kfree(thread); - binder_stats_deleted(BINDER_STAT_THREAD); - return active_transactions; -} - -static unsigned int binder_poll(struct file *filp, - struct poll_table_struct *wait) -{ - struct binder_proc *proc = filp->private_data; - struct binder_thread *thread = NULL; - int wait_for_proc_work; - - mutex_lock(&binder_lock); - thread = binder_get_thread(proc); - - wait_for_proc_work = thread->transaction_stack == NULL && - list_empty(&thread->todo) && thread->return_error == BR_OK; - mutex_unlock(&binder_lock); - - if (wait_for_proc_work) { - if (binder_has_proc_work(proc, thread)) - return POLLIN; - poll_wait(filp, &proc->wait, wait); - if (binder_has_proc_work(proc, thread)) - return POLLIN; - } else { - if (binder_has_thread_work(thread)) - return POLLIN; - poll_wait(filp, &thread->wait, wait); - if (binder_has_thread_work(thread)) - return POLLIN; - } - return 0; -} - -static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - int ret; - struct binder_proc *proc = filp->private_data; - struct binder_thread *thread; - unsigned int size = _IOC_SIZE(cmd); - void __user *ubuf = (void __user *)arg; - - /*printk(KERN_INFO "binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/ - - ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); - if (ret) - return ret; - - mutex_lock(&binder_lock); - thread = binder_get_thread(proc); - if (thread == NULL) { - ret = -ENOMEM; - goto err; - } - - switch (cmd) { - case BINDER_WRITE_READ: { - struct binder_write_read bwr; - if (size != sizeof(struct binder_write_read)) { - ret = -EINVAL; - goto err; - } - if (copy_from_user(&bwr, ubuf, sizeof(bwr))) { - ret = -EFAULT; - goto err; - } - binder_debug(BINDER_DEBUG_READ_WRITE, - "binder: %d:%d write %ld at %08lx, read %ld at %08lx\n", - proc->pid, thread->pid, bwr.write_size, bwr.write_buffer, - bwr.read_size, bwr.read_buffer); - - if (bwr.write_size > 0) { - ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed); - if (ret < 0) { - bwr.read_consumed = 0; - if (copy_to_user(ubuf, &bwr, sizeof(bwr))) - ret = -EFAULT; - goto err; - } - } - if (bwr.read_size > 0) { - ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK); - if (!list_empty(&proc->todo)) - wake_up_interruptible(&proc->wait); - if (ret < 0) { - if (copy_to_user(ubuf, &bwr, sizeof(bwr))) - ret = -EFAULT; - goto err; - } - } - binder_debug(BINDER_DEBUG_READ_WRITE, - "binder: %d:%d wrote %ld of %ld, read return %ld of %ld\n", - proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, - bwr.read_consumed, bwr.read_size); - if (copy_to_user(ubuf, &bwr, sizeof(bwr))) { - ret = -EFAULT; - goto err; - } - break; - } - case BINDER_SET_MAX_THREADS: - if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) { - ret = -EINVAL; - goto err; - } - break; - case BINDER_SET_CONTEXT_MGR: - if (binder_context_mgr_node != NULL) { - printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already set\n"); - ret = -EBUSY; - goto err; - } - if (binder_context_mgr_uid != -1) { - if (binder_context_mgr_uid != current->cred->euid) { - printk(KERN_ERR "binder: BINDER_SET_" - "CONTEXT_MGR bad uid %d != %d\n", - current->cred->euid, - binder_context_mgr_uid); - ret = -EPERM; - goto err; - } - } else - binder_context_mgr_uid = current->cred->euid; - binder_context_mgr_node = binder_new_node(proc, NULL, NULL); - if (binder_context_mgr_node == NULL) { - ret = -ENOMEM; - goto err; - } - binder_context_mgr_node->local_weak_refs++; - binder_context_mgr_node->local_strong_refs++; - binder_context_mgr_node->has_strong_ref = 1; - binder_context_mgr_node->has_weak_ref = 1; - break; - case BINDER_THREAD_EXIT: - binder_debug(BINDER_DEBUG_THREADS, "binder: %d:%d exit\n", - proc->pid, thread->pid); - binder_free_thread(proc, thread); - thread = NULL; - break; - case BINDER_VERSION: - if (size != sizeof(struct binder_version)) { - ret = -EINVAL; - goto err; - } - if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, &((struct binder_version *)ubuf)->protocol_version)) { - ret = -EINVAL; - goto err; - } - break; - default: - ret = -EINVAL; - goto err; - } - ret = 0; -err: - if (thread) - thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN; - mutex_unlock(&binder_lock); - wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); - if (ret && ret != -ERESTARTSYS) - printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret); - return ret; -} - -static void binder_vma_open(struct vm_area_struct *vma) -{ - struct binder_proc *proc = vma->vm_private_data; - binder_debug(BINDER_DEBUG_OPEN_CLOSE, - "binder: %d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", - proc->pid, vma->vm_start, vma->vm_end, - (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, - (unsigned long)pgprot_val(vma->vm_page_prot)); - dump_stack(); -} - -static void binder_vma_close(struct vm_area_struct *vma) -{ - struct binder_proc *proc = vma->vm_private_data; - binder_debug(BINDER_DEBUG_OPEN_CLOSE, - "binder: %d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", - proc->pid, vma->vm_start, vma->vm_end, - (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, - (unsigned long)pgprot_val(vma->vm_page_prot)); - proc->vma = NULL; - binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES); -} - -static struct vm_operations_struct binder_vm_ops = { - .open = binder_vma_open, - .close = binder_vma_close, -}; - -static int binder_mmap(struct file *filp, struct vm_area_struct *vma) -{ - int ret; - struct vm_struct *area; - struct binder_proc *proc = filp->private_data; - const char *failure_string; - struct binder_buffer *buffer; - - if ((vma->vm_end - vma->vm_start) > SZ_4M) - vma->vm_end = vma->vm_start + SZ_4M; - - binder_debug(BINDER_DEBUG_OPEN_CLOSE, - "binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n", - proc->pid, vma->vm_start, vma->vm_end, - (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, - (unsigned long)pgprot_val(vma->vm_page_prot)); - - if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) { - ret = -EPERM; - failure_string = "bad vm_flags"; - goto err_bad_arg; - } - vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE; - - if (proc->buffer) { - ret = -EBUSY; - failure_string = "already mapped"; - goto err_already_mapped; - } - - area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP); - if (area == NULL) { - ret = -ENOMEM; - failure_string = "get_vm_area"; - goto err_get_vm_area_failed; - } - proc->buffer = area->addr; - proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer; - -#ifdef CONFIG_CPU_CACHE_VIPT - if (cache_is_vipt_aliasing()) { - while (CACHE_COLOUR((vma->vm_start ^ (uint32_t)proc->buffer))) { - printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer); - vma->vm_start += PAGE_SIZE; - } - } -#endif - proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL); - if (proc->pages == NULL) { - ret = -ENOMEM; - failure_string = "alloc page array"; - goto err_alloc_pages_failed; - } - proc->buffer_size = vma->vm_end - vma->vm_start; - - vma->vm_ops = &binder_vm_ops; - vma->vm_private_data = proc; - - if (binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma)) { - ret = -ENOMEM; - failure_string = "alloc small buf"; - goto err_alloc_small_buf_failed; - } - buffer = proc->buffer; - INIT_LIST_HEAD(&proc->buffers); - list_add(&buffer->entry, &proc->buffers); - buffer->free = 1; - binder_insert_free_buffer(proc, buffer); - proc->free_async_space = proc->buffer_size / 2; - barrier(); - proc->files = get_files_struct(current); - proc->vma = vma; - - /*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n", - proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/ - return 0; - -err_alloc_small_buf_failed: - kfree(proc->pages); - proc->pages = NULL; -err_alloc_pages_failed: - vfree(proc->buffer); - proc->buffer = NULL; -err_get_vm_area_failed: -err_already_mapped: -err_bad_arg: - printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n", - proc->pid, vma->vm_start, vma->vm_end, failure_string, ret); - return ret; -} - -static int binder_open(struct inode *nodp, struct file *filp) -{ - struct binder_proc *proc; - - binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n", - current->group_leader->pid, current->pid); - - proc = kzalloc(sizeof(*proc), GFP_KERNEL); - if (proc == NULL) - return -ENOMEM; - get_task_struct(current); - proc->tsk = current; - INIT_LIST_HEAD(&proc->todo); - init_waitqueue_head(&proc->wait); - proc->default_priority = task_nice(current); - mutex_lock(&binder_lock); - binder_stats_created(BINDER_STAT_PROC); - hlist_add_head(&proc->proc_node, &binder_procs); - proc->pid = current->group_leader->pid; - INIT_LIST_HEAD(&proc->delivered_death); - filp->private_data = proc; - mutex_unlock(&binder_lock); - - if (binder_proc_dir_entry_proc) { - char strbuf[11]; - snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); - remove_proc_entry(strbuf, binder_proc_dir_entry_proc); - create_proc_read_entry(strbuf, S_IRUGO, - binder_proc_dir_entry_proc, - binder_read_proc_proc, proc); - } - - return 0; -} - -static int binder_flush(struct file *filp, fl_owner_t id) -{ - struct binder_proc *proc = filp->private_data; - - binder_defer_work(proc, BINDER_DEFERRED_FLUSH); - - return 0; -} - -static void binder_deferred_flush(struct binder_proc *proc) -{ - struct rb_node *n; - int wake_count = 0; - for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) { - struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node); - thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN; - if (thread->looper & BINDER_LOOPER_STATE_WAITING) { - wake_up_interruptible(&thread->wait); - wake_count++; - } - } - wake_up_interruptible_all(&proc->wait); - - binder_debug(BINDER_DEBUG_OPEN_CLOSE, - "binder_flush: %d woke %d threads\n", proc->pid, - wake_count); -} - -static int binder_release(struct inode *nodp, struct file *filp) -{ - struct binder_proc *proc = filp->private_data; - if (binder_proc_dir_entry_proc) { - char strbuf[11]; - snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); - remove_proc_entry(strbuf, binder_proc_dir_entry_proc); - } - - binder_defer_work(proc, BINDER_DEFERRED_RELEASE); - - return 0; -} - -static void binder_deferred_release(struct binder_proc *proc) -{ - struct hlist_node *pos; - struct binder_transaction *t; - struct rb_node *n; - int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count; - - BUG_ON(proc->vma); - BUG_ON(proc->files); - - hlist_del(&proc->proc_node); - if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) { - binder_debug(BINDER_DEBUG_DEAD_BINDER, - "binder_release: %d context_mgr_node gone\n", - proc->pid); - binder_context_mgr_node = NULL; - } - - threads = 0; - active_transactions = 0; - while ((n = rb_first(&proc->threads))) { - struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node); - threads++; - active_transactions += binder_free_thread(proc, thread); - } - nodes = 0; - incoming_refs = 0; - while ((n = rb_first(&proc->nodes))) { - struct binder_node *node = rb_entry(n, struct binder_node, rb_node); - - nodes++; - rb_erase(&node->rb_node, &proc->nodes); - list_del_init(&node->work.entry); - if (hlist_empty(&node->refs)) { - kfree(node); - binder_stats_deleted(BINDER_STAT_NODE); - } else { - struct binder_ref *ref; - int death = 0; - - node->proc = NULL; - node->local_strong_refs = 0; - node->local_weak_refs = 0; - hlist_add_head(&node->dead_node, &binder_dead_nodes); - - hlist_for_each_entry(ref, pos, &node->refs, node_entry) { - incoming_refs++; - if (ref->death) { - death++; - if (list_empty(&ref->death->work.entry)) { - ref->death->work.type = BINDER_WORK_DEAD_BINDER; - list_add_tail(&ref->death->work.entry, &ref->proc->todo); - wake_up_interruptible(&ref->proc->wait); - } else - BUG(); - } - } - binder_debug(BINDER_DEBUG_DEAD_BINDER, - "binder: node %d now dead, " - "refs %d, death %d\n", node->debug_id, - incoming_refs, death); - } - } - outgoing_refs = 0; - while ((n = rb_first(&proc->refs_by_desc))) { - struct binder_ref *ref = rb_entry(n, struct binder_ref, - rb_node_desc); - outgoing_refs++; - binder_delete_ref(ref); - } - binder_release_work(&proc->todo); - buffers = 0; - - while ((n = rb_first(&proc->allocated_buffers))) { - struct binder_buffer *buffer = rb_entry(n, struct binder_buffer, - rb_node); - t = buffer->transaction; - if (t) { - t->buffer = NULL; - buffer->transaction = NULL; - printk(KERN_ERR "binder: release proc %d, " - "transaction %d, not freed\n", - proc->pid, t->debug_id); - /*BUG();*/ - } - binder_free_buf(proc, buffer); - buffers++; - } - - binder_stats_deleted(BINDER_STAT_PROC); - - page_count = 0; - if (proc->pages) { - int i; - for (i = 0; i < proc->buffer_size / PAGE_SIZE; i++) { - if (proc->pages[i]) { - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder_release: %d: " - "page %d at %p not freed\n", - proc->pid, i, - proc->buffer + i * PAGE_SIZE); - __free_page(proc->pages[i]); - page_count++; - } - } - kfree(proc->pages); - vfree(proc->buffer); - } - - put_task_struct(proc->tsk); - - binder_debug(BINDER_DEBUG_OPEN_CLOSE, - "binder_release: %d threads %d, nodes %d (ref %d), " - "refs %d, active transactions %d, buffers %d, " - "pages %d\n", - proc->pid, threads, nodes, incoming_refs, outgoing_refs, - active_transactions, buffers, page_count); - - kfree(proc); -} - -static void binder_deferred_func(struct work_struct *work) -{ - struct binder_proc *proc; - struct files_struct *files; - - int defer; - do { - mutex_lock(&binder_lock); - mutex_lock(&binder_deferred_lock); - if (!hlist_empty(&binder_deferred_list)) { - proc = hlist_entry(binder_deferred_list.first, - struct binder_proc, deferred_work_node); - hlist_del_init(&proc->deferred_work_node); - defer = proc->deferred_work; - proc->deferred_work = 0; - } else { - proc = NULL; - defer = 0; - } - mutex_unlock(&binder_deferred_lock); - - files = NULL; - if (defer & BINDER_DEFERRED_PUT_FILES) { - files = proc->files; - if (files) - proc->files = NULL; - } - - if (defer & BINDER_DEFERRED_FLUSH) - binder_deferred_flush(proc); - - if (defer & BINDER_DEFERRED_RELEASE) - binder_deferred_release(proc); /* frees proc */ - - mutex_unlock(&binder_lock); - if (files) - put_files_struct(files); - } while (proc); -} -static DECLARE_WORK(binder_deferred_work, binder_deferred_func); - -static void -binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer) -{ - mutex_lock(&binder_deferred_lock); - proc->deferred_work |= defer; - if (hlist_unhashed(&proc->deferred_work_node)) { - hlist_add_head(&proc->deferred_work_node, - &binder_deferred_list); - schedule_work(&binder_deferred_work); - } - mutex_unlock(&binder_deferred_lock); -} - -static char *print_binder_transaction(char *buf, char *end, const char *prefix, - struct binder_transaction *t) -{ - buf += snprintf(buf, end - buf, - "%s %d: %p from %d:%d to %d:%d code %x " - "flags %x pri %ld r%d", - prefix, t->debug_id, t, - t->from ? t->from->proc->pid : 0, - t->from ? t->from->pid : 0, - t->to_proc ? t->to_proc->pid : 0, - t->to_thread ? t->to_thread->pid : 0, - t->code, t->flags, t->priority, t->need_reply); - if (buf >= end) - return buf; - if (t->buffer == NULL) { - buf += snprintf(buf, end - buf, " buffer free\n"); - return buf; - } - if (t->buffer->target_node) { - buf += snprintf(buf, end - buf, " node %d", - t->buffer->target_node->debug_id); - if (buf >= end) - return buf; - } - buf += snprintf(buf, end - buf, " size %zd:%zd data %p\n", - t->buffer->data_size, t->buffer->offsets_size, - t->buffer->data); - return buf; -} - -static char *print_binder_buffer(char *buf, char *end, const char *prefix, - struct binder_buffer *buffer) -{ - buf += snprintf(buf, end - buf, "%s %d: %p size %zd:%zd %s\n", - prefix, buffer->debug_id, buffer->data, - buffer->data_size, buffer->offsets_size, - buffer->transaction ? "active" : "delivered"); - return buf; -} - -static char *print_binder_work(char *buf, char *end, const char *prefix, - const char *transaction_prefix, - struct binder_work *w) -{ - struct binder_node *node; - struct binder_transaction *t; - - switch (w->type) { - case BINDER_WORK_TRANSACTION: - t = container_of(w, struct binder_transaction, work); - buf = print_binder_transaction(buf, end, transaction_prefix, t); - break; - case BINDER_WORK_TRANSACTION_COMPLETE: - buf += snprintf(buf, end - buf, - "%stransaction complete\n", prefix); - break; - case BINDER_WORK_NODE: - node = container_of(w, struct binder_node, work); - buf += snprintf(buf, end - buf, "%snode work %d: u%p c%p\n", - prefix, node->debug_id, node->ptr, - node->cookie); - break; - case BINDER_WORK_DEAD_BINDER: - buf += snprintf(buf, end - buf, "%shas dead binder\n", prefix); - break; - case BINDER_WORK_DEAD_BINDER_AND_CLEAR: - buf += snprintf(buf, end - buf, - "%shas cleared dead binder\n", prefix); - break; - case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: - buf += snprintf(buf, end - buf, - "%shas cleared death notification\n", prefix); - break; - default: - buf += snprintf(buf, end - buf, "%sunknown work: type %d\n", - prefix, w->type); - break; - } - return buf; -} - -static char *print_binder_thread(char *buf, char *end, - struct binder_thread *thread, - int print_always) -{ - struct binder_transaction *t; - struct binder_work *w; - char *start_buf = buf; - char *header_buf; - - buf += snprintf(buf, end - buf, " thread %d: l %02x\n", - thread->pid, thread->looper); - header_buf = buf; - t = thread->transaction_stack; - while (t) { - if (buf >= end) - break; - if (t->from == thread) { - buf = print_binder_transaction(buf, end, - " outgoing transaction", t); - t = t->from_parent; - } else if (t->to_thread == thread) { - buf = print_binder_transaction(buf, end, - " incoming transaction", t); - t = t->to_parent; - } else { - buf = print_binder_transaction(buf, end, - " bad transaction", t); - t = NULL; - } - } - list_for_each_entry(w, &thread->todo, entry) { - if (buf >= end) - break; - buf = print_binder_work(buf, end, " ", - " pending transaction", w); - } - if (!print_always && buf == header_buf) - buf = start_buf; - return buf; -} - -static char *print_binder_node(char *buf, char *end, struct binder_node *node) -{ - struct binder_ref *ref; - struct hlist_node *pos; - struct binder_work *w; - int count; - - count = 0; - hlist_for_each_entry(ref, pos, &node->refs, node_entry) - count++; - - buf += snprintf(buf, end - buf, - " node %d: u%p c%p hs %d hw %d ls %d lw %d " - "is %d iw %d", - node->debug_id, node->ptr, node->cookie, - node->has_strong_ref, node->has_weak_ref, - node->local_strong_refs, node->local_weak_refs, - node->internal_strong_refs, count); - if (buf >= end) - return buf; - if (count) { - buf += snprintf(buf, end - buf, " proc"); - if (buf >= end) - return buf; - hlist_for_each_entry(ref, pos, &node->refs, node_entry) { - buf += snprintf(buf, end - buf, " %d", ref->proc->pid); - if (buf >= end) - return buf; - } - } - buf += snprintf(buf, end - buf, "\n"); - list_for_each_entry(w, &node->async_todo, entry) { - if (buf >= end) - break; - buf = print_binder_work(buf, end, " ", - " pending async transaction", w); - } - return buf; -} - -static char *print_binder_ref(char *buf, char *end, struct binder_ref *ref) -{ - buf += snprintf(buf, end - buf, - " ref %d: desc %d %snode %d s %d w %d d %p\n", - ref->debug_id, ref->desc, - ref->node->proc ? "" : "dead ", ref->node->debug_id, - ref->strong, ref->weak, ref->death); - return buf; -} - -static char *print_binder_proc(char *buf, char *end, - struct binder_proc *proc, int print_all) -{ - struct binder_work *w; - struct rb_node *n; - char *start_buf = buf; - char *header_buf; - - buf += snprintf(buf, end - buf, "proc %d\n", proc->pid); - header_buf = buf; - - for (n = rb_first(&proc->threads); - n != NULL && buf < end; - n = rb_next(n)) - buf = print_binder_thread(buf, end, - rb_entry(n, struct binder_thread, - rb_node), print_all); - for (n = rb_first(&proc->nodes); - n != NULL && buf < end; - n = rb_next(n)) { - struct binder_node *node = rb_entry(n, struct binder_node, - rb_node); - if (print_all || node->has_async_transaction) - buf = print_binder_node(buf, end, node); - } - if (print_all) { - for (n = rb_first(&proc->refs_by_desc); - n != NULL && buf < end; - n = rb_next(n)) - buf = print_binder_ref(buf, end, - rb_entry(n, struct binder_ref, - rb_node_desc)); - } - for (n = rb_first(&proc->allocated_buffers); - n != NULL && buf < end; - n = rb_next(n)) - buf = print_binder_buffer(buf, end, " buffer", - rb_entry(n, struct binder_buffer, - rb_node)); - list_for_each_entry(w, &proc->todo, entry) { - if (buf >= end) - break; - buf = print_binder_work(buf, end, " ", - " pending transaction", w); - } - list_for_each_entry(w, &proc->delivered_death, entry) { - if (buf >= end) - break; - buf += snprintf(buf, end - buf, - " has delivered dead binder\n"); - break; - } - if (!print_all && buf == header_buf) - buf = start_buf; - return buf; -} - -static const char *binder_return_strings[] = { - "BR_ERROR", - "BR_OK", - "BR_TRANSACTION", - "BR_REPLY", - "BR_ACQUIRE_RESULT", - "BR_DEAD_REPLY", - "BR_TRANSACTION_COMPLETE", - "BR_INCREFS", - "BR_ACQUIRE", - "BR_RELEASE", - "BR_DECREFS", - "BR_ATTEMPT_ACQUIRE", - "BR_NOOP", - "BR_SPAWN_LOOPER", - "BR_FINISHED", - "BR_DEAD_BINDER", - "BR_CLEAR_DEATH_NOTIFICATION_DONE", - "BR_FAILED_REPLY" -}; - -static const char *binder_command_strings[] = { - "BC_TRANSACTION", - "BC_REPLY", - "BC_ACQUIRE_RESULT", - "BC_FREE_BUFFER", - "BC_INCREFS", - "BC_ACQUIRE", - "BC_RELEASE", - "BC_DECREFS", - "BC_INCREFS_DONE", - "BC_ACQUIRE_DONE", - "BC_ATTEMPT_ACQUIRE", - "BC_REGISTER_LOOPER", - "BC_ENTER_LOOPER", - "BC_EXIT_LOOPER", - "BC_REQUEST_DEATH_NOTIFICATION", - "BC_CLEAR_DEATH_NOTIFICATION", - "BC_DEAD_BINDER_DONE" -}; - -static const char *binder_objstat_strings[] = { - "proc", - "thread", - "node", - "ref", - "death", - "transaction", - "transaction_complete" -}; - -static char *print_binder_stats(char *buf, char *end, const char *prefix, - struct binder_stats *stats) -{ - int i; - - BUILD_BUG_ON(ARRAY_SIZE(stats->bc) != - ARRAY_SIZE(binder_command_strings)); - for (i = 0; i < ARRAY_SIZE(stats->bc); i++) { - if (stats->bc[i]) - buf += snprintf(buf, end - buf, "%s%s: %d\n", prefix, - binder_command_strings[i], - stats->bc[i]); - if (buf >= end) - return buf; - } - - BUILD_BUG_ON(ARRAY_SIZE(stats->br) != - ARRAY_SIZE(binder_return_strings)); - for (i = 0; i < ARRAY_SIZE(stats->br); i++) { - if (stats->br[i]) - buf += snprintf(buf, end - buf, "%s%s: %d\n", prefix, - binder_return_strings[i], stats->br[i]); - if (buf >= end) - return buf; - } - - BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) != - ARRAY_SIZE(binder_objstat_strings)); - BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) != - ARRAY_SIZE(stats->obj_deleted)); - for (i = 0; i < ARRAY_SIZE(stats->obj_created); i++) { - if (stats->obj_created[i] || stats->obj_deleted[i]) - buf += snprintf(buf, end - buf, - "%s%s: active %d total %d\n", prefix, - binder_objstat_strings[i], - stats->obj_created[i] - - stats->obj_deleted[i], - stats->obj_created[i]); - if (buf >= end) - return buf; - } - return buf; -} - -static char *print_binder_proc_stats(char *buf, char *end, - struct binder_proc *proc) -{ - struct binder_work *w; - struct rb_node *n; - int count, strong, weak; - - buf += snprintf(buf, end - buf, "proc %d\n", proc->pid); - if (buf >= end) - return buf; - count = 0; - for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) - count++; - buf += snprintf(buf, end - buf, " threads: %d\n", count); - if (buf >= end) - return buf; - buf += snprintf(buf, end - buf, " requested threads: %d+%d/%d\n" - " ready threads %d\n" - " free async space %zd\n", proc->requested_threads, - proc->requested_threads_started, proc->max_threads, - proc->ready_threads, proc->free_async_space); - if (buf >= end) - return buf; - count = 0; - for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) - count++; - buf += snprintf(buf, end - buf, " nodes: %d\n", count); - if (buf >= end) - return buf; - count = 0; - strong = 0; - weak = 0; - for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) { - struct binder_ref *ref = rb_entry(n, struct binder_ref, - rb_node_desc); - count++; - strong += ref->strong; - weak += ref->weak; - } - buf += snprintf(buf, end - buf, " refs: %d s %d w %d\n", - count, strong, weak); - if (buf >= end) - return buf; - - count = 0; - for (n = rb_first(&proc->allocated_buffers); n != NULL; n = rb_next(n)) - count++; - buf += snprintf(buf, end - buf, " buffers: %d\n", count); - if (buf >= end) - return buf; - - count = 0; - list_for_each_entry(w, &proc->todo, entry) { - switch (w->type) { - case BINDER_WORK_TRANSACTION: - count++; - break; - default: - break; - } - } - buf += snprintf(buf, end - buf, " pending transactions: %d\n", count); - if (buf >= end) - return buf; - - buf = print_binder_stats(buf, end, " ", &proc->stats); - - return buf; -} - - -static int binder_read_proc_state(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct binder_proc *proc; - struct hlist_node *pos; - struct binder_node *node; - int len = 0; - char *buf = page; - char *end = page + PAGE_SIZE; - int do_lock = !binder_debug_no_lock; - - if (off) - return 0; - - if (do_lock) - mutex_lock(&binder_lock); - - buf += snprintf(buf, end - buf, "binder state:\n"); - - if (!hlist_empty(&binder_dead_nodes)) - buf += snprintf(buf, end - buf, "dead nodes:\n"); - hlist_for_each_entry(node, pos, &binder_dead_nodes, dead_node) { - if (buf >= end) - break; - buf = print_binder_node(buf, end, node); - } - - hlist_for_each_entry(proc, pos, &binder_procs, proc_node) { - if (buf >= end) - break; - buf = print_binder_proc(buf, end, proc, 1); - } - if (do_lock) - mutex_unlock(&binder_lock); - if (buf > page + PAGE_SIZE) - buf = page + PAGE_SIZE; - - *start = page + off; - - len = buf - page; - if (len > off) - len -= off; - else - len = 0; - - return len < count ? len : count; -} - -static int binder_read_proc_stats(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct binder_proc *proc; - struct hlist_node *pos; - int len = 0; - char *p = page; - int do_lock = !binder_debug_no_lock; - - if (off) - return 0; - - if (do_lock) - mutex_lock(&binder_lock); - - p += snprintf(p, PAGE_SIZE, "binder stats:\n"); - - p = print_binder_stats(p, page + PAGE_SIZE, "", &binder_stats); - - hlist_for_each_entry(proc, pos, &binder_procs, proc_node) { - if (p >= page + PAGE_SIZE) - break; - p = print_binder_proc_stats(p, page + PAGE_SIZE, proc); - } - if (do_lock) - mutex_unlock(&binder_lock); - if (p > page + PAGE_SIZE) - p = page + PAGE_SIZE; - - *start = page + off; - - len = p - page; - if (len > off) - len -= off; - else - len = 0; - - return len < count ? len : count; -} - -static int binder_read_proc_transactions(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct binder_proc *proc; - struct hlist_node *pos; - int len = 0; - char *buf = page; - char *end = page + PAGE_SIZE; - int do_lock = !binder_debug_no_lock; - - if (off) - return 0; - - if (do_lock) - mutex_lock(&binder_lock); - - buf += snprintf(buf, end - buf, "binder transactions:\n"); - hlist_for_each_entry(proc, pos, &binder_procs, proc_node) { - if (buf >= end) - break; - buf = print_binder_proc(buf, end, proc, 0); - } - if (do_lock) - mutex_unlock(&binder_lock); - if (buf > page + PAGE_SIZE) - buf = page + PAGE_SIZE; - - *start = page + off; - - len = buf - page; - if (len > off) - len -= off; - else - len = 0; - - return len < count ? len : count; -} - -static int binder_read_proc_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct binder_proc *proc = data; - int len = 0; - char *p = page; - int do_lock = !binder_debug_no_lock; - - if (off) - return 0; - - if (do_lock) - mutex_lock(&binder_lock); - p += snprintf(p, PAGE_SIZE, "binder proc state:\n"); - p = print_binder_proc(p, page + PAGE_SIZE, proc, 1); - if (do_lock) - mutex_unlock(&binder_lock); - - if (p > page + PAGE_SIZE) - p = page + PAGE_SIZE; - *start = page + off; - - len = p - page; - if (len > off) - len -= off; - else - len = 0; - - return len < count ? len : count; -} - -static char *print_binder_transaction_log_entry(char *buf, char *end, - struct binder_transaction_log_entry *e) -{ - buf += snprintf(buf, end - buf, - "%d: %s from %d:%d to %d:%d node %d handle %d " - "size %d:%d\n", - e->debug_id, (e->call_type == 2) ? "reply" : - ((e->call_type == 1) ? "async" : "call "), e->from_proc, - e->from_thread, e->to_proc, e->to_thread, e->to_node, - e->target_handle, e->data_size, e->offsets_size); - return buf; -} - -static int binder_read_proc_transaction_log( - char *page, char **start, off_t off, int count, int *eof, void *data) -{ - struct binder_transaction_log *log = data; - int len = 0; - int i; - char *buf = page; - char *end = page + PAGE_SIZE; - - if (off) - return 0; - - if (log->full) { - for (i = log->next; i < ARRAY_SIZE(log->entry); i++) { - if (buf >= end) - break; - buf = print_binder_transaction_log_entry(buf, end, - &log->entry[i]); - } - } - for (i = 0; i < log->next; i++) { - if (buf >= end) - break; - buf = print_binder_transaction_log_entry(buf, end, - &log->entry[i]); - } - - *start = page + off; - - len = buf - page; - if (len > off) - len -= off; - else - len = 0; - - return len < count ? len : count; -} - -static const struct file_operations binder_fops = { - .owner = THIS_MODULE, - .poll = binder_poll, - .unlocked_ioctl = binder_ioctl, - .mmap = binder_mmap, - .open = binder_open, - .flush = binder_flush, - .release = binder_release, -}; - -static struct miscdevice binder_miscdev = { - .minor = MISC_DYNAMIC_MINOR, - .name = "binder", - .fops = &binder_fops -}; - -static int __init binder_init(void) -{ - int ret; - - binder_proc_dir_entry_root = proc_mkdir("binder", NULL); - if (binder_proc_dir_entry_root) - binder_proc_dir_entry_proc = proc_mkdir("proc", - binder_proc_dir_entry_root); - ret = misc_register(&binder_miscdev); - if (binder_proc_dir_entry_root) { - create_proc_read_entry("state", - S_IRUGO, - binder_proc_dir_entry_root, - binder_read_proc_state, - NULL); - create_proc_read_entry("stats", - S_IRUGO, - binder_proc_dir_entry_root, - binder_read_proc_stats, - NULL); - create_proc_read_entry("transactions", - S_IRUGO, - binder_proc_dir_entry_root, - binder_read_proc_transactions, - NULL); - create_proc_read_entry("transaction_log", - S_IRUGO, - binder_proc_dir_entry_root, - binder_read_proc_transaction_log, - &binder_transaction_log); - create_proc_read_entry("failed_transaction_log", - S_IRUGO, - binder_proc_dir_entry_root, - binder_read_proc_transaction_log, - &binder_transaction_log_failed); - } - return ret; -} - -device_initcall(binder_init); - -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h deleted file mode 100644 index 863ae1ad5d558075ef1a7b964f0a6d19ea8dbdab..0000000000000000000000000000000000000000 --- a/drivers/staging/android/binder.h +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (C) 2008 Google, Inc. - * - * Based on, but no longer compatible with, the original - * OpenBinder.org binder driver interface, which is: - * - * Copyright (c) 2005 Palmsource, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef _LINUX_BINDER_H -#define _LINUX_BINDER_H - -#include - -#define B_PACK_CHARS(c1, c2, c3, c4) \ - ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4)) -#define B_TYPE_LARGE 0x85 - -enum { - BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE), - BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE), - BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE), - BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE), - BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE), -}; - -enum { - FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff, - FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100, -}; - -/* - * This is the flattened representation of a Binder object for transfer - * between processes. The 'offsets' supplied as part of a binder transaction - * contains offsets into the data where these structures occur. The Binder - * driver takes care of re-writing the structure type and data as it moves - * between processes. - */ -struct flat_binder_object { - /* 8 bytes for large_flat_header. */ - unsigned long type; - unsigned long flags; - - /* 8 bytes of data. */ - union { - void *binder; /* local object */ - signed long handle; /* remote object */ - }; - - /* extra data associated with local object */ - void *cookie; -}; - -/* - * On 64-bit platforms where user code may run in 32-bits the driver must - * translate the buffer (and local binder) addresses apropriately. - */ - -struct binder_write_read { - signed long write_size; /* bytes to write */ - signed long write_consumed; /* bytes consumed by driver */ - unsigned long write_buffer; - signed long read_size; /* bytes to read */ - signed long read_consumed; /* bytes consumed by driver */ - unsigned long read_buffer; -}; - -/* Use with BINDER_VERSION, driver fills in fields. */ -struct binder_version { - /* driver protocol version -- increment with incompatible change */ - signed long protocol_version; -}; - -/* This is the current protocol version. */ -#define BINDER_CURRENT_PROTOCOL_VERSION 7 - -#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) -#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, int64_t) -#define BINDER_SET_MAX_THREADS _IOW('b', 5, size_t) -#define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, int) -#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, int) -#define BINDER_THREAD_EXIT _IOW('b', 8, int) -#define BINDER_VERSION _IOWR('b', 9, struct binder_version) - -/* - * NOTE: Two special error codes you should check for when calling - * in to the driver are: - * - * EINTR -- The operation has been interupted. This should be - * handled by retrying the ioctl() until a different error code - * is returned. - * - * ECONNREFUSED -- The driver is no longer accepting operations - * from your process. That is, the process is being destroyed. - * You should handle this by exiting from your process. Note - * that once this error code is returned, all further calls to - * the driver from any thread will return this same code. - */ - -enum transaction_flags { - TF_ONE_WAY = 0x01, /* this is a one-way call: async, no return */ - TF_ROOT_OBJECT = 0x04, /* contents are the component's root object */ - TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */ - TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */ -}; - -struct binder_transaction_data { - /* The first two are only used for bcTRANSACTION and brTRANSACTION, - * identifying the target and contents of the transaction. - */ - union { - size_t handle; /* target descriptor of command transaction */ - void *ptr; /* target descriptor of return transaction */ - } target; - void *cookie; /* target object cookie */ - unsigned int code; /* transaction command */ - - /* General information about the transaction. */ - unsigned int flags; - pid_t sender_pid; - uid_t sender_euid; - size_t data_size; /* number of bytes of data */ - size_t offsets_size; /* number of bytes of offsets */ - - /* If this transaction is inline, the data immediately - * follows here; otherwise, it ends with a pointer to - * the data buffer. - */ - union { - struct { - /* transaction data */ - const void *buffer; - /* offsets from buffer to flat_binder_object structs */ - const void *offsets; - } ptr; - uint8_t buf[8]; - } data; -}; - -struct binder_ptr_cookie { - void *ptr; - void *cookie; -}; - -struct binder_pri_desc { - int priority; - int desc; -}; - -struct binder_pri_ptr_cookie { - int priority; - void *ptr; - void *cookie; -}; - -enum BinderDriverReturnProtocol { - BR_ERROR = _IOR('r', 0, int), - /* - * int: error code - */ - - BR_OK = _IO('r', 1), - /* No parameters! */ - - BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data), - BR_REPLY = _IOR('r', 3, struct binder_transaction_data), - /* - * binder_transaction_data: the received command. - */ - - BR_ACQUIRE_RESULT = _IOR('r', 4, int), - /* - * not currently supported - * int: 0 if the last bcATTEMPT_ACQUIRE was not successful. - * Else the remote object has acquired a primary reference. - */ - - BR_DEAD_REPLY = _IO('r', 5), - /* - * The target of the last transaction (either a bcTRANSACTION or - * a bcATTEMPT_ACQUIRE) is no longer with us. No parameters. - */ - - BR_TRANSACTION_COMPLETE = _IO('r', 6), - /* - * No parameters... always refers to the last transaction requested - * (including replies). Note that this will be sent even for - * asynchronous transactions. - */ - - BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie), - BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie), - BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie), - BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie), - /* - * void *: ptr to binder - * void *: cookie for binder - */ - - BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie), - /* - * not currently supported - * int: priority - * void *: ptr to binder - * void *: cookie for binder - */ - - BR_NOOP = _IO('r', 12), - /* - * No parameters. Do nothing and examine the next command. It exists - * primarily so that we can replace it with a BR_SPAWN_LOOPER command. - */ - - BR_SPAWN_LOOPER = _IO('r', 13), - /* - * No parameters. The driver has determined that a process has no - * threads waiting to service incomming transactions. When a process - * receives this command, it must spawn a new service thread and - * register it via bcENTER_LOOPER. - */ - - BR_FINISHED = _IO('r', 14), - /* - * not currently supported - * stop threadpool thread - */ - - BR_DEAD_BINDER = _IOR('r', 15, void *), - /* - * void *: cookie - */ - BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *), - /* - * void *: cookie - */ - - BR_FAILED_REPLY = _IO('r', 17), - /* - * The the last transaction (either a bcTRANSACTION or - * a bcATTEMPT_ACQUIRE) failed (e.g. out of memory). No parameters. - */ -}; - -enum BinderDriverCommandProtocol { - BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data), - BC_REPLY = _IOW('c', 1, struct binder_transaction_data), - /* - * binder_transaction_data: the sent command. - */ - - BC_ACQUIRE_RESULT = _IOW('c', 2, int), - /* - * not currently supported - * int: 0 if the last BR_ATTEMPT_ACQUIRE was not successful. - * Else you have acquired a primary reference on the object. - */ - - BC_FREE_BUFFER = _IOW('c', 3, int), - /* - * void *: ptr to transaction data received on a read - */ - - BC_INCREFS = _IOW('c', 4, int), - BC_ACQUIRE = _IOW('c', 5, int), - BC_RELEASE = _IOW('c', 6, int), - BC_DECREFS = _IOW('c', 7, int), - /* - * int: descriptor - */ - - BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie), - BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie), - /* - * void *: ptr to binder - * void *: cookie for binder - */ - - BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc), - /* - * not currently supported - * int: priority - * int: descriptor - */ - - BC_REGISTER_LOOPER = _IO('c', 11), - /* - * No parameters. - * Register a spawned looper thread with the device. - */ - - BC_ENTER_LOOPER = _IO('c', 12), - BC_EXIT_LOOPER = _IO('c', 13), - /* - * No parameters. - * These two commands are sent as an application-level thread - * enters and exits the binder loop, respectively. They are - * used so the binder can have an accurate count of the number - * of looping threads it has available. - */ - - BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie), - /* - * void *: ptr to binder - * void *: cookie - */ - - BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie), - /* - * void *: ptr to binder - * void *: cookie - */ - - BC_DEAD_BINDER_DONE = _IOW('c', 16, void *), - /* - * void *: cookie - */ -}; - -#endif /* _LINUX_BINDER_H */ - diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c deleted file mode 100644 index 6c10b456c6cc5c082c6ceca278672c98538ff0aa..0000000000000000000000000000000000000000 --- a/drivers/staging/android/logger.c +++ /dev/null @@ -1,607 +0,0 @@ -/* - * drivers/misc/logger.c - * - * A Logging Subsystem - * - * Copyright (C) 2007-2008 Google, Inc. - * - * Robert Love - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include "logger.h" - -#include - -/* - * struct logger_log - represents a specific log, such as 'main' or 'radio' - * - * This structure lives from module insertion until module removal, so it does - * not need additional reference counting. The structure is protected by the - * mutex 'mutex'. - */ -struct logger_log { - unsigned char *buffer;/* the ring buffer itself */ - struct miscdevice misc; /* misc device representing the log */ - wait_queue_head_t wq; /* wait queue for readers */ - struct list_head readers; /* this log's readers */ - struct mutex mutex; /* mutex protecting buffer */ - size_t w_off; /* current write head offset */ - size_t head; /* new readers start here */ - size_t size; /* size of the log */ -}; - -/* - * struct logger_reader - a logging device open for reading - * - * This object lives from open to release, so we don't need additional - * reference counting. The structure is protected by log->mutex. - */ -struct logger_reader { - struct logger_log *log; /* associated log */ - struct list_head list; /* entry in logger_log's list */ - size_t r_off; /* current read head offset */ -}; - -/* logger_offset - returns index 'n' into the log via (optimized) modulus */ -#define logger_offset(n) ((n) & (log->size - 1)) - -/* - * file_get_log - Given a file structure, return the associated log - * - * This isn't aesthetic. We have several goals: - * - * 1) Need to quickly obtain the associated log during an I/O operation - * 2) Readers need to maintain state (logger_reader) - * 3) Writers need to be very fast (open() should be a near no-op) - * - * In the reader case, we can trivially go file->logger_reader->logger_log. - * For a writer, we don't want to maintain a logger_reader, so we just go - * file->logger_log. Thus what file->private_data points at depends on whether - * or not the file was opened for reading. This function hides that dirtiness. - */ -static inline struct logger_log *file_get_log(struct file *file) -{ - if (file->f_mode & FMODE_READ) { - struct logger_reader *reader = file->private_data; - return reader->log; - } else - return file->private_data; -} - -/* - * get_entry_len - Grabs the length of the payload of the next entry starting - * from 'off'. - * - * Caller needs to hold log->mutex. - */ -static __u32 get_entry_len(struct logger_log *log, size_t off) -{ - __u16 val; - - switch (log->size - off) { - case 1: - memcpy(&val, log->buffer + off, 1); - memcpy(((char *) &val) + 1, log->buffer, 1); - break; - default: - memcpy(&val, log->buffer + off, 2); - } - - return sizeof(struct logger_entry) + val; -} - -/* - * do_read_log_to_user - reads exactly 'count' bytes from 'log' into the - * user-space buffer 'buf'. Returns 'count' on success. - * - * Caller must hold log->mutex. - */ -static ssize_t do_read_log_to_user(struct logger_log *log, - struct logger_reader *reader, - char __user *buf, - size_t count) -{ - size_t len; - - /* - * We read from the log in two disjoint operations. First, we read from - * the current read head offset up to 'count' bytes or to the end of - * the log, whichever comes first. - */ - len = min(count, log->size - reader->r_off); - if (copy_to_user(buf, log->buffer + reader->r_off, len)) - return -EFAULT; - - /* - * Second, we read any remaining bytes, starting back at the head of - * the log. - */ - if (count != len) - if (copy_to_user(buf + len, log->buffer, count - len)) - return -EFAULT; - - reader->r_off = logger_offset(reader->r_off + count); - - return count; -} - -/* - * logger_read - our log's read() method - * - * Behavior: - * - * - O_NONBLOCK works - * - If there are no log entries to read, blocks until log is written to - * - Atomically reads exactly one log entry - * - * Optimal read size is LOGGER_ENTRY_MAX_LEN. Will set errno to EINVAL if read - * buffer is insufficient to hold next entry. - */ -static ssize_t logger_read(struct file *file, char __user *buf, - size_t count, loff_t *pos) -{ - struct logger_reader *reader = file->private_data; - struct logger_log *log = reader->log; - ssize_t ret; - DEFINE_WAIT(wait); - -start: - while (1) { - prepare_to_wait(&log->wq, &wait, TASK_INTERRUPTIBLE); - - mutex_lock(&log->mutex); - ret = (log->w_off == reader->r_off); - mutex_unlock(&log->mutex); - if (!ret) - break; - - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - - if (signal_pending(current)) { - ret = -EINTR; - break; - } - - schedule(); - } - - finish_wait(&log->wq, &wait); - if (ret) - return ret; - - mutex_lock(&log->mutex); - - /* is there still something to read or did we race? */ - if (unlikely(log->w_off == reader->r_off)) { - mutex_unlock(&log->mutex); - goto start; - } - - /* get the size of the next entry */ - ret = get_entry_len(log, reader->r_off); - if (count < ret) { - ret = -EINVAL; - goto out; - } - - /* get exactly one entry from the log */ - ret = do_read_log_to_user(log, reader, buf, ret); - -out: - mutex_unlock(&log->mutex); - - return ret; -} - -/* - * get_next_entry - return the offset of the first valid entry at least 'len' - * bytes after 'off'. - * - * Caller must hold log->mutex. - */ -static size_t get_next_entry(struct logger_log *log, size_t off, size_t len) -{ - size_t count = 0; - - do { - size_t nr = get_entry_len(log, off); - off = logger_offset(off + nr); - count += nr; - } while (count < len); - - return off; -} - -/* - * clock_interval - is a < c < b in mod-space? Put another way, does the line - * from a to b cross c? - */ -static inline int clock_interval(size_t a, size_t b, size_t c) -{ - if (b < a) { - if (a < c || b >= c) - return 1; - } else { - if (a < c && b >= c) - return 1; - } - - return 0; -} - -/* - * fix_up_readers - walk the list of all readers and "fix up" any who were - * lapped by the writer; also do the same for the default "start head". - * We do this by "pulling forward" the readers and start head to the first - * entry after the new write head. - * - * The caller needs to hold log->mutex. - */ -static void fix_up_readers(struct logger_log *log, size_t len) -{ - size_t old = log->w_off; - size_t new = logger_offset(old + len); - struct logger_reader *reader; - - if (clock_interval(old, new, log->head)) - log->head = get_next_entry(log, log->head, len); - - list_for_each_entry(reader, &log->readers, list) - if (clock_interval(old, new, reader->r_off)) - reader->r_off = get_next_entry(log, reader->r_off, len); -} - -/* - * do_write_log - writes 'len' bytes from 'buf' to 'log' - * - * The caller needs to hold log->mutex. - */ -static void do_write_log(struct logger_log *log, const void *buf, size_t count) -{ - size_t len; - - len = min(count, log->size - log->w_off); - memcpy(log->buffer + log->w_off, buf, len); - - if (count != len) - memcpy(log->buffer, buf + len, count - len); - - log->w_off = logger_offset(log->w_off + count); - -} - -/* - * do_write_log_user - writes 'len' bytes from the user-space buffer 'buf' to - * the log 'log' - * - * The caller needs to hold log->mutex. - * - * Returns 'count' on success, negative error code on failure. - */ -static ssize_t do_write_log_from_user(struct logger_log *log, - const void __user *buf, size_t count) -{ - size_t len; - - len = min(count, log->size - log->w_off); - if (len && copy_from_user(log->buffer + log->w_off, buf, len)) - return -EFAULT; - - if (count != len) - if (copy_from_user(log->buffer, buf + len, count - len)) - return -EFAULT; - - log->w_off = logger_offset(log->w_off + count); - - return count; -} - -/* - * logger_aio_write - our write method, implementing support for write(), - * writev(), and aio_write(). Writes are our fast path, and we try to optimize - * them above all else. - */ -ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t ppos) -{ - struct logger_log *log = file_get_log(iocb->ki_filp); - size_t orig = log->w_off; - struct logger_entry header; - struct timespec now; - ssize_t ret = 0; - - now = current_kernel_time(); - - header.pid = current->tgid; - header.tid = current->pid; - header.sec = now.tv_sec; - header.nsec = now.tv_nsec; - header.len = min_t(size_t, iocb->ki_left, LOGGER_ENTRY_MAX_PAYLOAD); - - /* null writes succeed, return zero */ - if (unlikely(!header.len)) - return 0; - - mutex_lock(&log->mutex); - - /* - * Fix up any readers, pulling them forward to the first readable - * entry after (what will be) the new write offset. We do this now - * because if we partially fail, we can end up with clobbered log - * entries that encroach on readable buffer. - */ - fix_up_readers(log, sizeof(struct logger_entry) + header.len); - - do_write_log(log, &header, sizeof(struct logger_entry)); - - while (nr_segs-- > 0) { - size_t len; - ssize_t nr; - - /* figure out how much of this vector we can keep */ - len = min_t(size_t, iov->iov_len, header.len - ret); - - /* write out this segment's payload */ - nr = do_write_log_from_user(log, iov->iov_base, len); - if (unlikely(nr < 0)) { - log->w_off = orig; - mutex_unlock(&log->mutex); - return nr; - } - - iov++; - ret += nr; - } - - mutex_unlock(&log->mutex); - - /* wake up any blocked readers */ - wake_up_interruptible(&log->wq); - - return ret; -} - -static struct logger_log *get_log_from_minor(int); - -/* - * logger_open - the log's open() file operation - * - * Note how near a no-op this is in the write-only case. Keep it that way! - */ -static int logger_open(struct inode *inode, struct file *file) -{ - struct logger_log *log; - int ret; - - ret = nonseekable_open(inode, file); - if (ret) - return ret; - - log = get_log_from_minor(MINOR(inode->i_rdev)); - if (!log) - return -ENODEV; - - if (file->f_mode & FMODE_READ) { - struct logger_reader *reader; - - reader = kmalloc(sizeof(struct logger_reader), GFP_KERNEL); - if (!reader) - return -ENOMEM; - - reader->log = log; - INIT_LIST_HEAD(&reader->list); - - mutex_lock(&log->mutex); - reader->r_off = log->head; - list_add_tail(&reader->list, &log->readers); - mutex_unlock(&log->mutex); - - file->private_data = reader; - } else - file->private_data = log; - - return 0; -} - -/* - * logger_release - the log's release file operation - * - * Note this is a total no-op in the write-only case. Keep it that way! - */ -static int logger_release(struct inode *ignored, struct file *file) -{ - if (file->f_mode & FMODE_READ) { - struct logger_reader *reader = file->private_data; - list_del(&reader->list); - kfree(reader); - } - - return 0; -} - -/* - * logger_poll - the log's poll file operation, for poll/select/epoll - * - * Note we always return POLLOUT, because you can always write() to the log. - * Note also that, strictly speaking, a return value of POLLIN does not - * guarantee that the log is readable without blocking, as there is a small - * chance that the writer can lap the reader in the interim between poll() - * returning and the read() request. - */ -static unsigned int logger_poll(struct file *file, poll_table *wait) -{ - struct logger_reader *reader; - struct logger_log *log; - unsigned int ret = POLLOUT | POLLWRNORM; - - if (!(file->f_mode & FMODE_READ)) - return ret; - - reader = file->private_data; - log = reader->log; - - poll_wait(file, &log->wq, wait); - - mutex_lock(&log->mutex); - if (log->w_off != reader->r_off) - ret |= POLLIN | POLLRDNORM; - mutex_unlock(&log->mutex); - - return ret; -} - -static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct logger_log *log = file_get_log(file); - struct logger_reader *reader; - long ret = -ENOTTY; - - mutex_lock(&log->mutex); - - switch (cmd) { - case LOGGER_GET_LOG_BUF_SIZE: - ret = log->size; - break; - case LOGGER_GET_LOG_LEN: - if (!(file->f_mode & FMODE_READ)) { - ret = -EBADF; - break; - } - reader = file->private_data; - if (log->w_off >= reader->r_off) - ret = log->w_off - reader->r_off; - else - ret = (log->size - reader->r_off) + log->w_off; - break; - case LOGGER_GET_NEXT_ENTRY_LEN: - if (!(file->f_mode & FMODE_READ)) { - ret = -EBADF; - break; - } - reader = file->private_data; - if (log->w_off != reader->r_off) - ret = get_entry_len(log, reader->r_off); - else - ret = 0; - break; - case LOGGER_FLUSH_LOG: - if (!(file->f_mode & FMODE_WRITE)) { - ret = -EBADF; - break; - } - list_for_each_entry(reader, &log->readers, list) - reader->r_off = log->w_off; - log->head = log->w_off; - ret = 0; - break; - } - - mutex_unlock(&log->mutex); - - return ret; -} - -static const struct file_operations logger_fops = { - .owner = THIS_MODULE, - .read = logger_read, - .aio_write = logger_aio_write, - .poll = logger_poll, - .unlocked_ioctl = logger_ioctl, - .compat_ioctl = logger_ioctl, - .open = logger_open, - .release = logger_release, -}; - -/* - * Defines a log structure with name 'NAME' and a size of 'SIZE' bytes, which - * must be a power of two, greater than LOGGER_ENTRY_MAX_LEN, and less than - * LONG_MAX minus LOGGER_ENTRY_MAX_LEN. - */ -#define DEFINE_LOGGER_DEVICE(VAR, NAME, SIZE) \ -static unsigned char _buf_ ## VAR[SIZE]; \ -static struct logger_log VAR = { \ - .buffer = _buf_ ## VAR, \ - .misc = { \ - .minor = MISC_DYNAMIC_MINOR, \ - .name = NAME, \ - .fops = &logger_fops, \ - .parent = NULL, \ - }, \ - .wq = __WAIT_QUEUE_HEAD_INITIALIZER(VAR .wq), \ - .readers = LIST_HEAD_INIT(VAR .readers), \ - .mutex = __MUTEX_INITIALIZER(VAR .mutex), \ - .w_off = 0, \ - .head = 0, \ - .size = SIZE, \ -}; - -DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 64*1024) -DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024) -DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 64*1024) - -static struct logger_log *get_log_from_minor(int minor) -{ - if (log_main.misc.minor == minor) - return &log_main; - if (log_events.misc.minor == minor) - return &log_events; - if (log_radio.misc.minor == minor) - return &log_radio; - return NULL; -} - -static int __init init_log(struct logger_log *log) -{ - int ret; - - ret = misc_register(&log->misc); - if (unlikely(ret)) { - printk(KERN_ERR "logger: failed to register misc " - "device for log '%s'!\n", log->misc.name); - return ret; - } - - printk(KERN_INFO "logger: created %luK log '%s'\n", - (unsigned long) log->size >> 10, log->misc.name); - - return 0; -} - -static int __init logger_init(void) -{ - int ret; - - ret = init_log(&log_main); - if (unlikely(ret)) - goto out; - - ret = init_log(&log_events); - if (unlikely(ret)) - goto out; - - ret = init_log(&log_radio); - if (unlikely(ret)) - goto out; - -out: - return ret; -} -device_initcall(logger_init); diff --git a/drivers/staging/android/logger.h b/drivers/staging/android/logger.h deleted file mode 100644 index a562434d74190f015317e2571ccedb80d5139304..0000000000000000000000000000000000000000 --- a/drivers/staging/android/logger.h +++ /dev/null @@ -1,48 +0,0 @@ -/* include/linux/logger.h - * - * Copyright (C) 2007-2008 Google, Inc. - * Author: Robert Love - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef _LINUX_LOGGER_H -#define _LINUX_LOGGER_H - -#include -#include - -struct logger_entry { - __u16 len; /* length of the payload */ - __u16 __pad; /* no matter what, we get 2 bytes of padding */ - __s32 pid; /* generating process's pid */ - __s32 tid; /* generating process's tid */ - __s32 sec; /* seconds since Epoch */ - __s32 nsec; /* nanoseconds */ - char msg[0]; /* the entry's payload */ -}; - -#define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */ -#define LOGGER_LOG_EVENTS "log_events" /* system/hardware events */ -#define LOGGER_LOG_MAIN "log_main" /* everything else */ - -#define LOGGER_ENTRY_MAX_LEN (4*1024) -#define LOGGER_ENTRY_MAX_PAYLOAD \ - (LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry)) - -#define __LOGGERIO 0xAE - -#define LOGGER_GET_LOG_BUF_SIZE _IO(__LOGGERIO, 1) /* size of log */ -#define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */ -#define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */ -#define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */ - -#endif /* _LINUX_LOGGER_H */ diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c deleted file mode 100644 index 935d281a201acdfcff732d1e74d1879942c9e183..0000000000000000000000000000000000000000 --- a/drivers/staging/android/lowmemorykiller.c +++ /dev/null @@ -1,173 +0,0 @@ -/* drivers/misc/lowmemorykiller.c - * - * The lowmemorykiller driver lets user-space specify a set of memory thresholds - * where processes with a range of oom_adj values will get killed. Specify the - * minimum oom_adj values in /sys/module/lowmemorykiller/parameters/adj and the - * number of free pages in /sys/module/lowmemorykiller/parameters/minfree. Both - * files take a comma separated list of numbers in ascending order. - * - * For example, write "0,8" to /sys/module/lowmemorykiller/parameters/adj and - * "1024,4096" to /sys/module/lowmemorykiller/parameters/minfree to kill processes - * with a oom_adj value of 8 or higher when the free memory drops below 4096 pages - * and kill processes with a oom_adj value of 0 or higher when the free memory - * drops below 1024 pages. - * - * The driver considers memory used for caches to be free, but if a large - * percentage of the cached memory is locked this can be very inaccurate - * and processes may not get killed until the normal oom killer is triggered. - * - * Copyright (C) 2007-2008 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include - -static uint32_t lowmem_debug_level = 2; -static int lowmem_adj[6] = { - 0, - 1, - 6, - 12, -}; -static int lowmem_adj_size = 4; -static size_t lowmem_minfree[6] = { - 3 * 512, /* 6MB */ - 2 * 1024, /* 8MB */ - 4 * 1024, /* 16MB */ - 16 * 1024, /* 64MB */ -}; -static int lowmem_minfree_size = 4; - -#define lowmem_print(level, x...) \ - do { \ - if (lowmem_debug_level >= (level)) \ - printk(x); \ - } while (0) - -static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask) -{ - struct task_struct *p; - struct task_struct *selected = NULL; - int rem = 0; - int tasksize; - int i; - int min_adj = OOM_ADJUST_MAX + 1; - int selected_tasksize = 0; - int selected_oom_adj; - int array_size = ARRAY_SIZE(lowmem_adj); - int other_free = global_page_state(NR_FREE_PAGES); - int other_file = global_page_state(NR_FILE_PAGES); - - if (lowmem_adj_size < array_size) - array_size = lowmem_adj_size; - if (lowmem_minfree_size < array_size) - array_size = lowmem_minfree_size; - for (i = 0; i < array_size; i++) { - if (other_free < lowmem_minfree[i] && - other_file < lowmem_minfree[i]) { - min_adj = lowmem_adj[i]; - break; - } - } - if (nr_to_scan > 0) - lowmem_print(3, "lowmem_shrink %d, %x, ofree %d %d, ma %d\n", - nr_to_scan, gfp_mask, other_free, other_file, - min_adj); - rem = global_page_state(NR_ACTIVE_ANON) + - global_page_state(NR_ACTIVE_FILE) + - global_page_state(NR_INACTIVE_ANON) + - global_page_state(NR_INACTIVE_FILE); - if (nr_to_scan <= 0 || min_adj == OOM_ADJUST_MAX + 1) { - lowmem_print(5, "lowmem_shrink %d, %x, return %d\n", - nr_to_scan, gfp_mask, rem); - return rem; - } - selected_oom_adj = min_adj; - - read_lock(&tasklist_lock); - for_each_process(p) { - struct mm_struct *mm; - int oom_adj; - - task_lock(p); - mm = p->mm; - if (!mm) { - task_unlock(p); - continue; - } - oom_adj = mm->oom_adj; - if (oom_adj < min_adj) { - task_unlock(p); - continue; - } - tasksize = get_mm_rss(mm); - task_unlock(p); - if (tasksize <= 0) - continue; - if (selected) { - if (oom_adj < selected_oom_adj) - continue; - if (oom_adj == selected_oom_adj && - tasksize <= selected_tasksize) - continue; - } - selected = p; - selected_tasksize = tasksize; - selected_oom_adj = oom_adj; - lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n", - p->pid, p->comm, oom_adj, tasksize); - } - if (selected) { - lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n", - selected->pid, selected->comm, - selected_oom_adj, selected_tasksize); - force_sig(SIGKILL, selected); - rem -= selected_tasksize; - } - lowmem_print(4, "lowmem_shrink %d, %x, return %d\n", - nr_to_scan, gfp_mask, rem); - read_unlock(&tasklist_lock); - return rem; -} - -static struct shrinker lowmem_shrinker = { - .shrink = lowmem_shrink, - .seeks = DEFAULT_SEEKS * 16 -}; - -static int __init lowmem_init(void) -{ - register_shrinker(&lowmem_shrinker); - return 0; -} - -static void __exit lowmem_exit(void) -{ - unregister_shrinker(&lowmem_shrinker); -} - -module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR); -module_param_array_named(adj, lowmem_adj, int, &lowmem_adj_size, - S_IRUGO | S_IWUSR); -module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size, - S_IRUGO | S_IWUSR); -module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR); - -module_init(lowmem_init); -module_exit(lowmem_exit); - -MODULE_LICENSE("GPL"); - diff --git a/drivers/staging/android/ram_console.c b/drivers/staging/android/ram_console.c deleted file mode 100644 index 8f18a59744cdd8911a1be78297421b245dccad2b..0000000000000000000000000000000000000000 --- a/drivers/staging/android/ram_console.c +++ /dev/null @@ -1,410 +0,0 @@ -/* drivers/android/ram_console.c - * - * Copyright (C) 2007-2008 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION -#include -#endif - -struct ram_console_buffer { - uint32_t sig; - uint32_t start; - uint32_t size; - uint8_t data[0]; -}; - -#define RAM_CONSOLE_SIG (0x43474244) /* DBGC */ - -#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT -static char __initdata - ram_console_old_log_init_buffer[CONFIG_ANDROID_RAM_CONSOLE_EARLY_SIZE]; -#endif -static char *ram_console_old_log; -static size_t ram_console_old_log_size; - -static struct ram_console_buffer *ram_console_buffer; -static size_t ram_console_buffer_size; -#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION -static char *ram_console_par_buffer; -static struct rs_control *ram_console_rs_decoder; -static int ram_console_corrected_bytes; -static int ram_console_bad_blocks; -#define ECC_BLOCK_SIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE -#define ECC_SIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE -#define ECC_SYMSIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE -#define ECC_POLY CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL -#endif - -#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION -static void ram_console_encode_rs8(uint8_t *data, size_t len, uint8_t *ecc) -{ - int i; - uint16_t par[ECC_SIZE]; - /* Initialize the parity buffer */ - memset(par, 0, sizeof(par)); - encode_rs8(ram_console_rs_decoder, data, len, par, 0); - for (i = 0; i < ECC_SIZE; i++) - ecc[i] = par[i]; -} - -static int ram_console_decode_rs8(void *data, size_t len, uint8_t *ecc) -{ - int i; - uint16_t par[ECC_SIZE]; - for (i = 0; i < ECC_SIZE; i++) - par[i] = ecc[i]; - return decode_rs8(ram_console_rs_decoder, data, par, len, - NULL, 0, NULL, 0, NULL); -} -#endif - -static void ram_console_update(const char *s, unsigned int count) -{ - struct ram_console_buffer *buffer = ram_console_buffer; -#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION - uint8_t *buffer_end = buffer->data + ram_console_buffer_size; - uint8_t *block; - uint8_t *par; - int size = ECC_BLOCK_SIZE; -#endif - memcpy(buffer->data + buffer->start, s, count); -#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION - block = buffer->data + (buffer->start & ~(ECC_BLOCK_SIZE - 1)); - par = ram_console_par_buffer + - (buffer->start / ECC_BLOCK_SIZE) * ECC_SIZE; - do { - if (block + ECC_BLOCK_SIZE > buffer_end) - size = buffer_end - block; - ram_console_encode_rs8(block, size, par); - block += ECC_BLOCK_SIZE; - par += ECC_SIZE; - } while (block < buffer->data + buffer->start + count); -#endif -} - -static void ram_console_update_header(void) -{ -#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION - struct ram_console_buffer *buffer = ram_console_buffer; - uint8_t *par; - par = ram_console_par_buffer + - DIV_ROUND_UP(ram_console_buffer_size, ECC_BLOCK_SIZE) * ECC_SIZE; - ram_console_encode_rs8((uint8_t *)buffer, sizeof(*buffer), par); -#endif -} - -static void -ram_console_write(struct console *console, const char *s, unsigned int count) -{ - int rem; - struct ram_console_buffer *buffer = ram_console_buffer; - - if (count > ram_console_buffer_size) { - s += count - ram_console_buffer_size; - count = ram_console_buffer_size; - } - rem = ram_console_buffer_size - buffer->start; - if (rem < count) { - ram_console_update(s, rem); - s += rem; - count -= rem; - buffer->start = 0; - buffer->size = ram_console_buffer_size; - } - ram_console_update(s, count); - - buffer->start += count; - if (buffer->size < ram_console_buffer_size) - buffer->size += count; - ram_console_update_header(); -} - -static struct console ram_console = { - .name = "ram", - .write = ram_console_write, - .flags = CON_PRINTBUFFER | CON_ENABLED, - .index = -1, -}; - -static void __init -ram_console_save_old(struct ram_console_buffer *buffer, char *dest) -{ - size_t old_log_size = buffer->size; -#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION - uint8_t *block; - uint8_t *par; - char strbuf[80]; - int strbuf_len; - - block = buffer->data; - par = ram_console_par_buffer; - while (block < buffer->data + buffer->size) { - int numerr; - int size = ECC_BLOCK_SIZE; - if (block + size > buffer->data + ram_console_buffer_size) - size = buffer->data + ram_console_buffer_size - block; - numerr = ram_console_decode_rs8(block, size, par); - if (numerr > 0) { -#if 0 - printk(KERN_INFO "ram_console: error in block %p, %d\n", - block, numerr); -#endif - ram_console_corrected_bytes += numerr; - } else if (numerr < 0) { -#if 0 - printk(KERN_INFO "ram_console: uncorrectable error in " - "block %p\n", block); -#endif - ram_console_bad_blocks++; - } - block += ECC_BLOCK_SIZE; - par += ECC_SIZE; - } - if (ram_console_corrected_bytes || ram_console_bad_blocks) - strbuf_len = snprintf(strbuf, sizeof(strbuf), - "\n%d Corrected bytes, %d unrecoverable blocks\n", - ram_console_corrected_bytes, ram_console_bad_blocks); - else - strbuf_len = snprintf(strbuf, sizeof(strbuf), - "\nNo errors detected\n"); - if (strbuf_len >= sizeof(strbuf)) - strbuf_len = sizeof(strbuf) - 1; - old_log_size += strbuf_len; -#endif - - if (dest == NULL) { - dest = kmalloc(old_log_size, GFP_KERNEL); - if (dest == NULL) { - printk(KERN_ERR - "ram_console: failed to allocate buffer\n"); - return; - } - } - - ram_console_old_log = dest; - ram_console_old_log_size = old_log_size; - memcpy(ram_console_old_log, - &buffer->data[buffer->start], buffer->size - buffer->start); - memcpy(ram_console_old_log + buffer->size - buffer->start, - &buffer->data[0], buffer->start); -#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION - memcpy(ram_console_old_log + old_log_size - strbuf_len, - strbuf, strbuf_len); -#endif -} - -static int __init ram_console_init(struct ram_console_buffer *buffer, - size_t buffer_size, char *old_buf) -{ -#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION - int numerr; - uint8_t *par; -#endif - ram_console_buffer = buffer; - ram_console_buffer_size = - buffer_size - sizeof(struct ram_console_buffer); - - if (ram_console_buffer_size > buffer_size) { - pr_err("ram_console: buffer %p, invalid size %zu, " - "datasize %zu\n", buffer, buffer_size, - ram_console_buffer_size); - return 0; - } - -#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION - ram_console_buffer_size -= (DIV_ROUND_UP(ram_console_buffer_size, - ECC_BLOCK_SIZE) + 1) * ECC_SIZE; - - if (ram_console_buffer_size > buffer_size) { - pr_err("ram_console: buffer %p, invalid size %zu, " - "non-ecc datasize %zu\n", - buffer, buffer_size, ram_console_buffer_size); - return 0; - } - - ram_console_par_buffer = buffer->data + ram_console_buffer_size; - - - /* first consecutive root is 0 - * primitive element to generate roots = 1 - */ - ram_console_rs_decoder = init_rs(ECC_SYMSIZE, ECC_POLY, 0, 1, ECC_SIZE); - if (ram_console_rs_decoder == NULL) { - printk(KERN_INFO "ram_console: init_rs failed\n"); - return 0; - } - - ram_console_corrected_bytes = 0; - ram_console_bad_blocks = 0; - - par = ram_console_par_buffer + - DIV_ROUND_UP(ram_console_buffer_size, ECC_BLOCK_SIZE) * ECC_SIZE; - - numerr = ram_console_decode_rs8(buffer, sizeof(*buffer), par); - if (numerr > 0) { - printk(KERN_INFO "ram_console: error in header, %d\n", numerr); - ram_console_corrected_bytes += numerr; - } else if (numerr < 0) { - printk(KERN_INFO - "ram_console: uncorrectable error in header\n"); - ram_console_bad_blocks++; - } -#endif - - if (buffer->sig == RAM_CONSOLE_SIG) { - if (buffer->size > ram_console_buffer_size - || buffer->start > buffer->size) - printk(KERN_INFO "ram_console: found existing invalid " - "buffer, size %d, start %d\n", - buffer->size, buffer->start); - else { - printk(KERN_INFO "ram_console: found existing buffer, " - "size %d, start %d\n", - buffer->size, buffer->start); - ram_console_save_old(buffer, old_buf); - } - } else { - printk(KERN_INFO "ram_console: no valid data in buffer " - "(sig = 0x%08x)\n", buffer->sig); - } - - buffer->sig = RAM_CONSOLE_SIG; - buffer->start = 0; - buffer->size = 0; - - register_console(&ram_console); -#ifdef CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE - console_verbose(); -#endif - return 0; -} - -#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT -static int __init ram_console_early_init(void) -{ - return ram_console_init((struct ram_console_buffer *) - CONFIG_ANDROID_RAM_CONSOLE_EARLY_ADDR, - CONFIG_ANDROID_RAM_CONSOLE_EARLY_SIZE, - ram_console_old_log_init_buffer); -} -#else -static int ram_console_driver_probe(struct platform_device *pdev) -{ - struct resource *res = pdev->resource; - size_t start; - size_t buffer_size; - void *buffer; - - if (res == NULL || pdev->num_resources != 1 || - !(res->flags & IORESOURCE_MEM)) { - printk(KERN_ERR "ram_console: invalid resource, %p %d flags " - "%lx\n", res, pdev->num_resources, res ? res->flags : 0); - return -ENXIO; - } - buffer_size = res->end - res->start + 1; - start = res->start; - printk(KERN_INFO "ram_console: got buffer at %zx, size %zx\n", - start, buffer_size); - buffer = ioremap(res->start, buffer_size); - if (buffer == NULL) { - printk(KERN_ERR "ram_console: failed to map memory\n"); - return -ENOMEM; - } - - return ram_console_init(buffer, buffer_size, NULL/* allocate */); -} - -static struct platform_driver ram_console_driver = { - .probe = ram_console_driver_probe, - .driver = { - .name = "ram_console", - }, -}; - -static int __init ram_console_module_init(void) -{ - int err; - err = platform_driver_register(&ram_console_driver); - return err; -} -#endif - -static ssize_t ram_console_read_old(struct file *file, char __user *buf, - size_t len, loff_t *offset) -{ - loff_t pos = *offset; - ssize_t count; - - if (pos >= ram_console_old_log_size) - return 0; - - count = min(len, (size_t)(ram_console_old_log_size - pos)); - if (copy_to_user(buf, ram_console_old_log + pos, count)) - return -EFAULT; - - *offset += count; - return count; -} - -static const struct file_operations ram_console_file_ops = { - .owner = THIS_MODULE, - .read = ram_console_read_old, -}; - -static int __init ram_console_late_init(void) -{ - struct proc_dir_entry *entry; - - if (ram_console_old_log == NULL) - return 0; -#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT - ram_console_old_log = kmalloc(ram_console_old_log_size, GFP_KERNEL); - if (ram_console_old_log == NULL) { - printk(KERN_ERR - "ram_console: failed to allocate buffer for old log\n"); - ram_console_old_log_size = 0; - return 0; - } - memcpy(ram_console_old_log, - ram_console_old_log_init_buffer, ram_console_old_log_size); -#endif - entry = create_proc_entry("last_kmsg", S_IFREG | S_IRUGO, NULL); - if (!entry) { - printk(KERN_ERR "ram_console: failed to create proc entry\n"); - kfree(ram_console_old_log); - ram_console_old_log = NULL; - return 0; - } - - entry->proc_fops = &ram_console_file_ops; - entry->size = ram_console_old_log_size; - return 0; -} - -#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT -console_initcall(ram_console_early_init); -#else -module_init(ram_console_module_init); -#endif -late_initcall(ram_console_late_init); - diff --git a/drivers/staging/android/timed_gpio.c b/drivers/staging/android/timed_gpio.c deleted file mode 100644 index be7cdaa783ae2fbdf79a444f370b35e352002646..0000000000000000000000000000000000000000 --- a/drivers/staging/android/timed_gpio.c +++ /dev/null @@ -1,166 +0,0 @@ -/* drivers/misc/timed_gpio.c - * - * Copyright (C) 2008 Google, Inc. - * Author: Mike Lockwood - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include - -#include "timed_output.h" -#include "timed_gpio.h" - - -struct timed_gpio_data { - struct timed_output_dev dev; - struct hrtimer timer; - spinlock_t lock; - unsigned gpio; - int max_timeout; - u8 active_low; -}; - -static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer) -{ - struct timed_gpio_data *data = - container_of(timer, struct timed_gpio_data, timer); - - gpio_direction_output(data->gpio, data->active_low ? 1 : 0); - return HRTIMER_NORESTART; -} - -static int gpio_get_time(struct timed_output_dev *dev) -{ - struct timed_gpio_data *data = - container_of(dev, struct timed_gpio_data, dev); - - if (hrtimer_active(&data->timer)) { - ktime_t r = hrtimer_get_remaining(&data->timer); - struct timeval t = ktime_to_timeval(r); - return t.tv_sec * 1000 + t.tv_usec / 1000; - } else - return 0; -} - -static void gpio_enable(struct timed_output_dev *dev, int value) -{ - struct timed_gpio_data *data = - container_of(dev, struct timed_gpio_data, dev); - unsigned long flags; - - spin_lock_irqsave(&data->lock, flags); - - /* cancel previous timer and set GPIO according to value */ - hrtimer_cancel(&data->timer); - gpio_direction_output(data->gpio, data->active_low ? !value : !!value); - - if (value > 0) { - if (value > data->max_timeout) - value = data->max_timeout; - - hrtimer_start(&data->timer, - ktime_set(value / 1000, (value % 1000) * 1000000), - HRTIMER_MODE_REL); - } - - spin_unlock_irqrestore(&data->lock, flags); -} - -static int timed_gpio_probe(struct platform_device *pdev) -{ - struct timed_gpio_platform_data *pdata = pdev->dev.platform_data; - struct timed_gpio *cur_gpio; - struct timed_gpio_data *gpio_data, *gpio_dat; - int i, j, ret = 0; - - if (!pdata) - return -EBUSY; - - gpio_data = kzalloc(sizeof(struct timed_gpio_data) * pdata->num_gpios, - GFP_KERNEL); - if (!gpio_data) - return -ENOMEM; - - for (i = 0; i < pdata->num_gpios; i++) { - cur_gpio = &pdata->gpios[i]; - gpio_dat = &gpio_data[i]; - - hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - gpio_dat->timer.function = gpio_timer_func; - spin_lock_init(&gpio_dat->lock); - - gpio_dat->dev.name = cur_gpio->name; - gpio_dat->dev.get_time = gpio_get_time; - gpio_dat->dev.enable = gpio_enable; - ret = timed_output_dev_register(&gpio_dat->dev); - if (ret < 0) { - for (j = 0; j < i; j++) - timed_output_dev_unregister(&gpio_data[i].dev); - kfree(gpio_data); - return ret; - } - - gpio_dat->gpio = cur_gpio->gpio; - gpio_dat->max_timeout = cur_gpio->max_timeout; - gpio_dat->active_low = cur_gpio->active_low; - gpio_direction_output(gpio_dat->gpio, gpio_dat->active_low); - } - - platform_set_drvdata(pdev, gpio_data); - - return 0; -} - -static int timed_gpio_remove(struct platform_device *pdev) -{ - struct timed_gpio_platform_data *pdata = pdev->dev.platform_data; - struct timed_gpio_data *gpio_data = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < pdata->num_gpios; i++) - timed_output_dev_unregister(&gpio_data[i].dev); - - kfree(gpio_data); - - return 0; -} - -static struct platform_driver timed_gpio_driver = { - .probe = timed_gpio_probe, - .remove = timed_gpio_remove, - .driver = { - .name = TIMED_GPIO_NAME, - .owner = THIS_MODULE, - }, -}; - -static int __init timed_gpio_init(void) -{ - return platform_driver_register(&timed_gpio_driver); -} - -static void __exit timed_gpio_exit(void) -{ - platform_driver_unregister(&timed_gpio_driver); -} - -module_init(timed_gpio_init); -module_exit(timed_gpio_exit); - -MODULE_AUTHOR("Mike Lockwood "); -MODULE_DESCRIPTION("timed gpio driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/android/timed_gpio.h b/drivers/staging/android/timed_gpio.h deleted file mode 100644 index a0e15f8be3f717e5aa8c6bb462ef3710b75bbba3..0000000000000000000000000000000000000000 --- a/drivers/staging/android/timed_gpio.h +++ /dev/null @@ -1,33 +0,0 @@ -/* include/linux/timed_gpio.h - * - * Copyright (C) 2008 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * -*/ - -#ifndef _LINUX_TIMED_GPIO_H -#define _LINUX_TIMED_GPIO_H - -#define TIMED_GPIO_NAME "timed-gpio" - -struct timed_gpio { - const char *name; - unsigned gpio; - int max_timeout; - u8 active_low; -}; - -struct timed_gpio_platform_data { - int num_gpios; - struct timed_gpio *gpios; -}; - -#endif diff --git a/drivers/staging/android/timed_output.c b/drivers/staging/android/timed_output.c deleted file mode 100644 index 62e79180421b3d7eb5ef837eee0442cb9722ad3d..0000000000000000000000000000000000000000 --- a/drivers/staging/android/timed_output.c +++ /dev/null @@ -1,121 +0,0 @@ -/* drivers/misc/timed_output.c - * - * Copyright (C) 2009 Google, Inc. - * Author: Mike Lockwood - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include - -#include "timed_output.h" - -static struct class *timed_output_class; -static atomic_t device_count; - -static ssize_t enable_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct timed_output_dev *tdev = dev_get_drvdata(dev); - int remaining = tdev->get_time(tdev); - - return sprintf(buf, "%d\n", remaining); -} - -static ssize_t enable_store( - struct device *dev, struct device_attribute *attr, - const char *buf, size_t size) -{ - struct timed_output_dev *tdev = dev_get_drvdata(dev); - int value; - - sscanf(buf, "%d", &value); - tdev->enable(tdev, value); - - return size; -} - -static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store); - -static int create_timed_output_class(void) -{ - if (!timed_output_class) { - timed_output_class = class_create(THIS_MODULE, "timed_output"); - if (IS_ERR(timed_output_class)) - return PTR_ERR(timed_output_class); - atomic_set(&device_count, 0); - } - - return 0; -} - -int timed_output_dev_register(struct timed_output_dev *tdev) -{ - int ret; - - if (!tdev || !tdev->name || !tdev->enable || !tdev->get_time) - return -EINVAL; - - ret = create_timed_output_class(); - if (ret < 0) - return ret; - - tdev->index = atomic_inc_return(&device_count); - tdev->dev = device_create(timed_output_class, NULL, - MKDEV(0, tdev->index), NULL, tdev->name); - if (IS_ERR(tdev->dev)) - return PTR_ERR(tdev->dev); - - ret = device_create_file(tdev->dev, &dev_attr_enable); - if (ret < 0) - goto err_create_file; - - dev_set_drvdata(tdev->dev, tdev); - tdev->state = 0; - return 0; - -err_create_file: - device_destroy(timed_output_class, MKDEV(0, tdev->index)); - printk(KERN_ERR "timed_output: Failed to register driver %s\n", - tdev->name); - - return ret; -} -EXPORT_SYMBOL_GPL(timed_output_dev_register); - -void timed_output_dev_unregister(struct timed_output_dev *tdev) -{ - device_remove_file(tdev->dev, &dev_attr_enable); - device_destroy(timed_output_class, MKDEV(0, tdev->index)); - dev_set_drvdata(tdev->dev, NULL); -} -EXPORT_SYMBOL_GPL(timed_output_dev_unregister); - -static int __init timed_output_init(void) -{ - return create_timed_output_class(); -} - -static void __exit timed_output_exit(void) -{ - class_destroy(timed_output_class); -} - -module_init(timed_output_init); -module_exit(timed_output_exit); - -MODULE_AUTHOR("Mike Lockwood "); -MODULE_DESCRIPTION("timed output class driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/android/timed_output.h b/drivers/staging/android/timed_output.h deleted file mode 100644 index ec907ab2ff5484fdfb87168b9f87ae9937582d3c..0000000000000000000000000000000000000000 --- a/drivers/staging/android/timed_output.h +++ /dev/null @@ -1,37 +0,0 @@ -/* include/linux/timed_output.h - * - * Copyright (C) 2008 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * -*/ - -#ifndef _LINUX_TIMED_OUTPUT_H -#define _LINUX_TIMED_OUTPUT_H - -struct timed_output_dev { - const char *name; - - /* enable the output and set the timer */ - void (*enable)(struct timed_output_dev *sdev, int timeout); - - /* returns the current number of milliseconds remaining on the timer */ - int (*get_time)(struct timed_output_dev *sdev); - - /* private data */ - struct device *dev; - int index; - int state; -}; - -extern int timed_output_dev_register(struct timed_output_dev *dev); -extern void timed_output_dev_unregister(struct timed_output_dev *dev); - -#endif diff --git a/drivers/staging/b3dfg/b3dfg.c b/drivers/staging/b3dfg/b3dfg.c index cda26bb493b3d3185177e8d3041f4ebf106e0f79..4a43c51c172abdb454e857e42dac52432b37cd35 100644 --- a/drivers/staging/b3dfg/b3dfg.c +++ b/drivers/staging/b3dfg/b3dfg.c @@ -468,7 +468,6 @@ static int get_wand_status(struct b3dfg_dev *fgdev, int __user *arg) static int enable_transmission(struct b3dfg_dev *fgdev) { - u16 command; unsigned long flags; struct device *dev = &fgdev->pdev->dev; @@ -480,17 +479,6 @@ static int enable_transmission(struct b3dfg_dev *fgdev) return -EINVAL; } - /* - * Check we're a bus master. - * TODO: I think we can remove this having added the pci_set_master call - */ - pci_read_config_word(fgdev->pdev, PCI_COMMAND, &command); - if (!(command & PCI_COMMAND_MASTER)) { - dev_err(dev, "not a bus master, force-enabling\n"); - pci_write_config_word(fgdev->pdev, PCI_COMMAND, - command | PCI_COMMAND_MASTER); - } - spin_lock_irqsave(&fgdev->buffer_lock, flags); /* Handle racing enable_transmission calls. */ diff --git a/drivers/staging/batman-adv/CHANGELOG b/drivers/staging/batman-adv/CHANGELOG new file mode 100644 index 0000000000000000000000000000000000000000..8a181639ceaae4adbdd42fd603dc33bf21ccb522 --- /dev/null +++ b/drivers/staging/batman-adv/CHANGELOG @@ -0,0 +1,37 @@ +batman-adv 0.2: + +* support latest kernels (2.6.20 - 2.6.31) +* temporary routing loops / TTL code bug / ghost entries in originator table fixed +* internal packet queue for packet aggregation & transmission retry (ARQ) + for payload broadcasts added +* interface detection converted to event based handling to avoid timers +* major linux coding style adjustments applied +* all kernel version compatibility functions has been moved to compat.h +* use random ethernet address generator from the kernel +* /sys/module/batman_adv/version to export kernel module version +* vis: secondary interface export for dot draw format + JSON output format added +* many bugs (alignment issues, race conditions, deadlocks, etc) squashed + + -- Sat, 07 Nov 2009 15:44:31 +0100 + +batman-adv 0.1: + +* support latest kernels (2.6.20 - 2.6.28) +* LOTS of cleanup: locking, stack usage, memory leaks +* Change Ethertype from 0x0842 to 0x4305 + unregistered at IEEE, if you want to sponsor an official Ethertype ($2500) + please contact us + + -- Sun, 28 Dec 2008 00:44:31 +0100 + +batman-adv 0.1-beta: + +* layer 2 meshing based on BATMAN TQ algorithm in kernelland +* operates on any ethernet like interface +* supports IPv4, IPv6, DHCP, etc +* is controlled via /proc/net/batman-adv/ +* bridging via brctl is supported +* interface watchdog (interfaces can be (de)activated dynamically) +* offers integrated vis server which meshes/syncs with other vis servers in range + + -- Mon, 05 May 2008 14:10:04 +0200 diff --git a/drivers/staging/batman-adv/Kconfig b/drivers/staging/batman-adv/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..7632f57600609ddbca11b67ba645f570e89c0c53 --- /dev/null +++ b/drivers/staging/batman-adv/Kconfig @@ -0,0 +1,25 @@ +# +# B.A.T.M.A.N meshing protocol +# + +config BATMAN_ADV + tristate "B.A.T.M.A.N. Advanced Meshing Protocol" + default n + ---help--- + + B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is + a routing protocol for multi-hop ad-hoc mesh networks. The + networks may be wired or wireless. See + http://www.open-mesh.org/ for more information and user space + tools. + +config BATMAN_DEBUG + bool "B.A.T.M.A.N. debugging" + depends on BATMAN_ADV != n + help + + This is an option for use by developers; most people should + say N here. This enables compilation of support for + outputting debugging information to the kernel log. The + output is controlled via the module parameter debug. + diff --git a/drivers/staging/batman-adv/Makefile b/drivers/staging/batman-adv/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..02da87134fce6b9286fc2350c37d199032045d58 --- /dev/null +++ b/drivers/staging/batman-adv/Makefile @@ -0,0 +1,22 @@ +# +# Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: +# +# Marek Lindner, Simon Wunderlich +# +# 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 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., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA +# + +obj-m += batman-adv.o +batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o log.o diff --git a/drivers/staging/batman-adv/README b/drivers/staging/batman-adv/README new file mode 100644 index 0000000000000000000000000000000000000000..3aaf393ebaa7a242ed27627299bb4fd8001bf3af --- /dev/null +++ b/drivers/staging/batman-adv/README @@ -0,0 +1,125 @@ +[state: 07-11-2009] + +BATMAN-ADV +---------- + +Batman-advanced is a new approach to wireless networking which does no longer +operate on the IP basis. Unlike B.A.T.M.A.N, which exchanges information +using UDP packets and sets routing tables, batman-advanced operates on ISO/OSI +Layer 2 only and uses and routes (or better: bridges) Ethernet Frames. It +emulates a virtual network switch of all nodes participating. Therefore all +nodes appear to be link local, thus all higher operating protocols won't be +affected by any changes within the network. You can run almost any protocol +above B.A.T.M.A.N. Advanced, prominent examples are: IPv4, IPv6, DHCP, IPX. + +This is batman-advanced implemented as Linux kernel driver. It does not depend +on any network (other) driver, and can be used on wifi as well as ethernet, +vpn, etc ... (anything with ethernet-style layer 2). +It compiles against and should work with Linux 2.6.20 - 2.6.31. Supporting older +versions is not planned, but it's probably easy to backport it. If you work on a +backport, feel free to contact us. :-) + +COMPILE +------- +To compile against your currently installed kernel, just type: + +# make + +if you want to compile against some other kernel, use: + +# make KERNELPATH=/path/to/kernel + +USAGE +----- + +insmod the batman-adv.ko in your kernel: + +# insmod batman-adv.ko + +the module is now waiting for activation. You must add some interfaces +on which batman can operate. Each interface must be added separately: + +# echo wlan0 > /proc/net/batman-adv/interfaces + +( # echo wlan1 > /proc/net/batman-adv/interfaces ) +( # echo eth0 > /proc/net/batman-adv/interfaces ) +( ... ) + +Now batman starts broadcasting on this interface. +You can now view the table of originators (mesh participants) with: + +# cat /proc/net/batman-adv/originators + +The module will create a new interface "bat0", which can be used as a +regular interface: + +# ifconfig bat0 inet 192.168.0.1 up +# ping 192.168.0.2 +... + +If you want topology visualization, your meshnode must be configured +as VIS-server: + +# echo "server" > /proc/net/batman-adv/vis + +Each node is either configured as "server" or as "client" (default: +"client"). Clients send their topology data to the server next to them, +and server synchronize with other servers. If there is no server +configured (default) within the mesh, no topology information will be +transmitted. With these "synchronizing servers", there can be 1 or +more vis servers sharing the same (or at least very similar) data. + +When configured as server, you can get a topology snapshot of your mesh: + +# cat /proc/net/batman-adv/vis + +This output format is a graphviz formatted text file which can be +processed with graphviz-tools like dot. +The labels are similar/compatible to the ETX metric, 1.0 means perfect +connection (100%), 2.0 means 50%, 3.0 means 33% and so on. + +Alternatively, a JSON output format is available. The format can be set +using by writing either "dot_draw" or "json" into the vis_format file. +"dot_draw" is selected by default. + +echo "json" > /proc/net/batman-adv/vis_format + +In very mobile scenarios, you might want to adjust the originator +interval to a lower value. This will make the mesh more responsive to +topology changes, but will also increase the overhead. Please make sure +that all nodes in your mesh use the same interval. The default value +is 1000 ms (1 second). + +# echo 1000 > /proc/net/batman-adv/orig_interval + +To deactivate batman, do: + +# echo "" > /proc/net/batman-adv/interfaces + +BATCTL +------ + +B.A.T.M.A.N. advanced operates on layer 2 and thus all hosts partici- +pating in the virtual switch are completely transparent for all proto- +cols above layer 2. Therefore the common diagnosis tools do not work as +expected. To overcome these problems batctl was created. At the moment +the batctl contains ping, traceroute, tcpdump and interfaces to the +kernel module settings. + +For more information, please see the manpage (man batctl). + +batctl is available on http://www.open-mesh.net/ + +CONTACT +------- + +Please send us comments, experiences, questions, anything :) + +IRC: #batman on irc.freenode.org +Mailing-list: b.a.t.m.a.n@open-mesh.net +(subscription at https://list.open-mesh.net/mm/listinfo/b.a.t.m.a.n ) + +You can also contact the Authors: + +Marek Lindner +Simon Wunderlich diff --git a/drivers/staging/batman-adv/TODO b/drivers/staging/batman-adv/TODO new file mode 100644 index 0000000000000000000000000000000000000000..ea6dcf94d661106138a76e184680097aecb7cabc --- /dev/null +++ b/drivers/staging/batman-adv/TODO @@ -0,0 +1,51 @@ +=> proc interface +* implement new interface to add/delete interfaces and setting options +* /proc/sys/net/batman-adv/ as main folder +* in interfaces/ list every available interface of the host +* each interfaces/$iface/ contains the following files: +-> enable (def: 0) [add/remove this interface to batman-adv] +-> ogm_interval (def: 1000) [ogm interval of that interface] +-> context (def: bat0) [later we want to support multiple mesh instances via +-> bat0/bat1/bat2/..] +-> status (read-only) [outputs the interface status from batman's +-> perspective] +* in mesh/batX/ list every available mesh subnet +-> vis_server (def: 0) [enable/disable vis server for that mesh] +-> vis_data (read-only) [outputs the vis data in a raw format] +-> aggregate_ogm (def: 1) [enable/disable ogm aggregation for that mesh] +-> originators (read-only) [outputs the originator table] +-> transtable_global (read-only) [outputs the global translation table] +-> transtable_local (read-only) [outputs the local translation table] + +=> vis "raw" data output +* the raw format shall replace dot draw / json to offer a neutral that can +* be converted +* the format (comma seperated entries): +-> "mac" -> mac address of an originator (each line begins with it) +-> "TQ mac value" -> src mac's link quality towards mac address +-> "HNA mac" -> HNA announced by source mac +-> "PRIMARY" -> this is a primary interface +-> "SEC mac" -> secondary mac address of source (requires preceeding +-> PRIMARY) + +=> logging +* the log level LOG_TYPE_CRIT, LOG_TYPE_WARN & LOG_TYPE_NOTICE will be +* unified to use printk +* LOG_TYPE_BATMAN & LOG_TYPE_ROUTES will also use printk but only after the +* internal debug level has been raised +* the internal debug level can be modified using a module parameter (debug) +* or at run time via /sys/module/batman-adv/parameters/debug +* make use of printk %pM support instead of converting mac addresses +* manually + +=> strip out all backward compatibility support to older kernels + (only found in compat.h) + +=> fix checkpatch.pl errors + +Please send all patches to: + Marek Lindner + Simon Wunderlich + Andrew Lunn + b.a.t.m.a.n@lists.open-mesh.net + Greg Kroah-Hartman diff --git a/drivers/staging/batman-adv/aggregation.c b/drivers/staging/batman-adv/aggregation.c new file mode 100644 index 0000000000000000000000000000000000000000..9c6e681f6fb65bc319944dcd3ea5d467bf0f9786 --- /dev/null +++ b/drivers/staging/batman-adv/aggregation.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "aggregation.h" +#include "send.h" +#include "routing.h" + +/* calculate the size of the hna information for a given packet */ +static int hna_len(struct batman_packet *batman_packet) +{ + return batman_packet->num_hna * ETH_ALEN; +} + +/* return true if new_packet can be aggregated with forw_packet */ +static bool can_aggregate_with(struct batman_packet *new_batman_packet, + int packet_len, + unsigned long send_time, + bool directlink, + struct batman_if *if_incoming, + struct forw_packet *forw_packet) +{ + struct batman_packet *batman_packet = + (struct batman_packet *)forw_packet->packet_buff; + int aggregated_bytes = forw_packet->packet_len + packet_len; + + /** + * we can aggregate the current packet to this aggregated packet + * if: + * + * - the send time is within our MAX_AGGREGATION_MS time + * - the resulting packet wont be bigger than + * MAX_AGGREGATION_BYTES + */ + + if (time_before(send_time, forw_packet->send_time) && + (aggregated_bytes <= MAX_AGGREGATION_BYTES)) { + + /** + * check aggregation compatibility + * -> direct link packets are broadcasted on + * their interface only + * -> aggregate packet if the current packet is + * a "global" packet as well as the base + * packet + */ + + /* packets without direct link flag and high TTL + * are flooded through the net */ + if ((!directlink) && + (!(batman_packet->flags & DIRECTLINK)) && + (batman_packet->ttl != 1) && + + /* own packets originating non-primary + * interfaces leave only that interface */ + ((!forw_packet->own) || + (forw_packet->if_incoming->if_num == 0))) + return true; + + /* if the incoming packet is sent via this one + * interface only - we still can aggregate */ + if ((directlink) && + (new_batman_packet->ttl == 1) && + (forw_packet->if_incoming == if_incoming)) + return true; + + } + + return false; +} + +/* create a new aggregated packet and add this packet to it */ +static void new_aggregated_packet(unsigned char *packet_buff, + int packet_len, + unsigned long send_time, + bool direct_link, + struct batman_if *if_incoming, + int own_packet) +{ + struct forw_packet *forw_packet_aggr; + + forw_packet_aggr = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC); + if (!forw_packet_aggr) + return; + + forw_packet_aggr->packet_buff = kmalloc(MAX_AGGREGATION_BYTES, + GFP_ATOMIC); + if (!forw_packet_aggr->packet_buff) { + kfree(forw_packet_aggr); + return; + } + + INIT_HLIST_NODE(&forw_packet_aggr->list); + + forw_packet_aggr->packet_len = packet_len; + memcpy(forw_packet_aggr->packet_buff, + packet_buff, + forw_packet_aggr->packet_len); + + forw_packet_aggr->own = own_packet; + forw_packet_aggr->if_incoming = if_incoming; + forw_packet_aggr->num_packets = 0; + forw_packet_aggr->direct_link_flags = 0; + forw_packet_aggr->send_time = send_time; + + /* save packet direct link flag status */ + if (direct_link) + forw_packet_aggr->direct_link_flags |= 1; + + /* add new packet to packet list */ + spin_lock(&forw_bat_list_lock); + hlist_add_head(&forw_packet_aggr->list, &forw_bat_list); + spin_unlock(&forw_bat_list_lock); + + /* start timer for this packet */ + INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work, + send_outstanding_bat_packet); + queue_delayed_work(bat_event_workqueue, + &forw_packet_aggr->delayed_work, + send_time - jiffies); +} + +/* aggregate a new packet into the existing aggregation */ +static void aggregate(struct forw_packet *forw_packet_aggr, + unsigned char *packet_buff, + int packet_len, + bool direct_link) +{ + memcpy((forw_packet_aggr->packet_buff + forw_packet_aggr->packet_len), + packet_buff, packet_len); + forw_packet_aggr->packet_len += packet_len; + forw_packet_aggr->num_packets++; + + /* save packet direct link flag status */ + if (direct_link) + forw_packet_aggr->direct_link_flags |= + (1 << forw_packet_aggr->num_packets); +} + +void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len, + struct batman_if *if_incoming, char own_packet, + unsigned long send_time) +{ + /** + * _aggr -> pointer to the packet we want to aggregate with + * _pos -> pointer to the position in the queue + */ + struct forw_packet *forw_packet_aggr = NULL, *forw_packet_pos = NULL; + struct hlist_node *tmp_node; + struct batman_packet *batman_packet = + (struct batman_packet *)packet_buff; + bool direct_link = batman_packet->flags & DIRECTLINK ? 1 : 0; + + /* find position for the packet in the forward queue */ + spin_lock(&forw_bat_list_lock); + /* own packets are not to be aggregated */ + if ((atomic_read(&aggregation_enabled)) && (!own_packet)) { + hlist_for_each_entry(forw_packet_pos, tmp_node, &forw_bat_list, + list) { + if (can_aggregate_with(batman_packet, + packet_len, + send_time, + direct_link, + if_incoming, + forw_packet_pos)) { + forw_packet_aggr = forw_packet_pos; + break; + } + } + } + + /* nothing to aggregate with - either aggregation disabled or no + * suitable aggregation packet found */ + if (forw_packet_aggr == NULL) { + /* the following section can run without the lock */ + spin_unlock(&forw_bat_list_lock); + new_aggregated_packet(packet_buff, packet_len, + send_time, direct_link, + if_incoming, own_packet); + } else { + aggregate(forw_packet_aggr, + packet_buff, packet_len, + direct_link); + spin_unlock(&forw_bat_list_lock); + } +} + +/* unpack the aggregated packets and process them one by one */ +void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff, + int packet_len, struct batman_if *if_incoming) +{ + struct batman_packet *batman_packet; + int buff_pos = 0; + unsigned char *hna_buff; + + batman_packet = (struct batman_packet *)packet_buff; + + while (aggregated_packet(buff_pos, packet_len, + batman_packet->num_hna)) { + + /* network to host order for our 16bit seqno, and the + orig_interval. */ + batman_packet->seqno = ntohs(batman_packet->seqno); + + hna_buff = packet_buff + buff_pos + BAT_PACKET_LEN; + receive_bat_packet(ethhdr, batman_packet, + hna_buff, hna_len(batman_packet), + if_incoming); + + buff_pos += BAT_PACKET_LEN + hna_len(batman_packet); + batman_packet = (struct batman_packet *) + (packet_buff + buff_pos); + } +} diff --git a/drivers/staging/batman-adv/aggregation.h b/drivers/staging/batman-adv/aggregation.h new file mode 100644 index 0000000000000000000000000000000000000000..6da8df9f99b72425cdc64acff233831e72b7f4c4 --- /dev/null +++ b/drivers/staging/batman-adv/aggregation.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" + +/* is there another aggregated packet here? */ +static inline int aggregated_packet(int buff_pos, int packet_len, int num_hna) +{ + int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_hna * ETH_ALEN); + + return (next_buff_pos <= packet_len) && + (next_buff_pos <= MAX_AGGREGATION_BYTES); +} + +void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len, + struct batman_if *if_outgoing, char own_packet, + unsigned long send_time); +void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff, + int packet_len, struct batman_if *if_incoming); diff --git a/drivers/staging/batman-adv/bitarray.c b/drivers/staging/batman-adv/bitarray.c new file mode 100644 index 0000000000000000000000000000000000000000..3c67f5f42b2b6eaf2536ecaca5148efb9b8ac95b --- /dev/null +++ b/drivers/staging/batman-adv/bitarray.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2006-2009 B.A.T.M.A.N. contributors: + * + * Simon Wunderlich, Marek Lindner + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "bitarray.h" +#include "log.h" + +/* returns true if the corresponding bit in the given seq_bits indicates true + * and curr_seqno is within range of last_seqno */ +uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint16_t last_seqno, + uint16_t curr_seqno) +{ + int16_t diff, word_offset, word_num; + + diff = last_seqno - curr_seqno; + if (diff < 0 || diff >= TQ_LOCAL_WINDOW_SIZE) { + return 0; + } else { + /* which word */ + word_num = (last_seqno - curr_seqno) / WORD_BIT_SIZE; + /* which position in the selected word */ + word_offset = (last_seqno - curr_seqno) % WORD_BIT_SIZE; + + if (seq_bits[word_num] & 1 << word_offset) + return 1; + else + return 0; + } +} + +/* turn corresponding bit on, so we can remember that we got the packet */ +void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n) +{ + int32_t word_offset, word_num; + + /* if too old, just drop it */ + if (n < 0 || n >= TQ_LOCAL_WINDOW_SIZE) + return; + + /* which word */ + word_num = n / WORD_BIT_SIZE; + /* which position in the selected word */ + word_offset = n % WORD_BIT_SIZE; + + seq_bits[word_num] |= 1 << word_offset; /* turn the position on */ +} + +/* shift the packet array by n places. */ +void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n) +{ + int32_t word_offset, word_num; + int32_t i; + + if (n <= 0) + return; + + word_offset = n % WORD_BIT_SIZE;/* shift how much inside each word */ + word_num = n / WORD_BIT_SIZE; /* shift over how much (full) words */ + + for (i = NUM_WORDS - 1; i > word_num; i--) { + /* going from old to new, so we don't overwrite the data we copy + * from. + * + * left is high, right is low: FEDC BA98 7654 3210 + * ^^ ^^ + * vvvv + * ^^^^ = from, vvvvv =to, we'd have word_num==1 and + * word_offset==WORD_BIT_SIZE/2 ????? in this example. + * (=24 bits) + * + * our desired output would be: 9876 5432 1000 0000 + * */ + + seq_bits[i] = + (seq_bits[i - word_num] << word_offset) + + /* take the lower port from the left half, shift it left + * to its final position */ + (seq_bits[i - word_num - 1] >> + (WORD_BIT_SIZE-word_offset)); + /* and the upper part of the right half and shift it left to + * it's position */ + /* for our example that would be: word[0] = 9800 + 0076 = + * 9876 */ + } + /* now for our last word, i==word_num, we only have the it's "left" + * half. that's the 1000 word in our example.*/ + + seq_bits[i] = (seq_bits[i - word_num] << word_offset); + + /* pad the rest with 0, if there is anything */ + i--; + + for (; i >= 0; i--) + seq_bits[i] = 0; +} + + +/* receive and process one packet, returns 1 if received seq_num is considered + * new, 0 if old */ +char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff, + int8_t set_mark) +{ + int i; + + /* we already got a sequence number higher than this one, so we just + * mark it. this should wrap around the integer just fine */ + if ((seq_num_diff < 0) && (seq_num_diff >= -TQ_LOCAL_WINDOW_SIZE)) { + if (set_mark) + bit_mark(seq_bits, -seq_num_diff); + return 0; + } + + /* it seems we missed a lot of packets or the other host restarted */ + if ((seq_num_diff > TQ_LOCAL_WINDOW_SIZE) || + (seq_num_diff < -TQ_LOCAL_WINDOW_SIZE)) { + + if (seq_num_diff > TQ_LOCAL_WINDOW_SIZE) + debug_log(LOG_TYPE_BATMAN, + "We missed a lot of packets (%i) !\n", + seq_num_diff-1); + + if (-seq_num_diff > TQ_LOCAL_WINDOW_SIZE) + debug_log(LOG_TYPE_BATMAN, + "Other host probably restarted !\n"); + + for (i = 0; i < NUM_WORDS; i++) + seq_bits[i] = 0; + + if (set_mark) + seq_bits[0] = 1; /* we only have the latest packet */ + } else { + bit_shift(seq_bits, seq_num_diff); + + if (set_mark) + bit_mark(seq_bits, 0); + } + + return 1; +} + +/* count the hamming weight, how many good packets did we receive? just count + * the 1's. The inner loop uses the Kernighan algorithm, see + * http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan + */ +int bit_packet_count(TYPE_OF_WORD *seq_bits) +{ + int i, hamming = 0; + TYPE_OF_WORD word; + + for (i = 0; i < NUM_WORDS; i++) { + word = seq_bits[i]; + + while (word) { + word &= word-1; + hamming++; + } + } + return hamming; +} diff --git a/drivers/staging/batman-adv/bitarray.h b/drivers/staging/batman-adv/bitarray.h new file mode 100644 index 0000000000000000000000000000000000000000..ec72dd7843621befd59597bfb0a282846576dd52 --- /dev/null +++ b/drivers/staging/batman-adv/bitarray.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2006-2009 B.A.T.M.A.N. contributors: + * + * Simon Wunderlich, Marek Lindner + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + + +/* you should choose something big, if you don't want to waste cpu */ +#define TYPE_OF_WORD unsigned long +#define WORD_BIT_SIZE (sizeof(TYPE_OF_WORD) * 8) + +/* returns true if the corresponding bit in the given seq_bits indicates true + * and curr_seqno is within range of last_seqno */ +uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint16_t last_seqno, + uint16_t curr_seqno); + +/* turn corresponding bit on, so we can remember that we got the packet */ +void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n); + +/* shift the packet array by n places. */ +void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n); + + +/* receive and process one packet, returns 1 if received seq_num is considered + * new, 0 if old */ +char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff, + int8_t set_mark); + +/* count the hamming weight, how many good packets did we receive? */ +int bit_packet_count(TYPE_OF_WORD *seq_bits); diff --git a/drivers/staging/batman-adv/compat.h b/drivers/staging/batman-adv/compat.h new file mode 100644 index 0000000000000000000000000000000000000000..f4e0a4564ba7bc5606d5f4ecb9e4d2fffb801c66 --- /dev/null +++ b/drivers/staging/batman-adv/compat.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + * + * This file contains macros for maintaining compatibility with older versions + * of the Linux kernel. + */ + +#include /* LINUX_VERSION_CODE */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) + +#define skb_set_network_header(_skb, _offset) \ + do { (_skb)->nh.raw = (_skb)->data + (_offset); } while (0) + +#define skb_reset_mac_header(_skb) \ + do { (_skb)->mac.raw = (_skb)->data; } while (0) + +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) */ + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + +#define device_create(_cls, _parent, _devt, _device, _fmt) \ + class_device_create(_cls, _parent, _devt, _device, _fmt) + +#define device_destroy(_cls, _device) \ + class_device_destroy(_cls, _device) + +#else + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) + +#define device_create(_cls, _parent, _devt, _device, _fmt) \ + device_create_drvdata(_cls, _parent, _devt, _device, _fmt) + +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) */ + +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) + +#define cancel_delayed_work_sync(wq) cancel_rearming_delayed_work(wq) + +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) +#define strict_strtoul(cp, base, res) \ + ({ \ + int ret = 0; \ + char *endp; \ + *res = simple_strtoul(cp, &endp, base); \ + if (cp == endp) \ + ret = -EINVAL; \ + ret; \ +}) +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */ diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c new file mode 100644 index 0000000000000000000000000000000000000000..1e7d1f88674ffd2361ccdb0830c7b5580baf9557 --- /dev/null +++ b/drivers/staging/batman-adv/device.c @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "device.h" +#include "log.h" +#include "send.h" +#include "types.h" +#include "hash.h" + +#include "compat.h" + +static struct class *batman_class; + +static int Major; /* Major number assigned to our device driver */ + +static const struct file_operations fops = { + .open = bat_device_open, + .release = bat_device_release, + .read = bat_device_read, + .write = bat_device_write, + .poll = bat_device_poll, +}; + +static struct device_client *device_client_hash[256]; + +void bat_device_init(void) +{ + int i; + + for (i = 0; i < 256; i++) + device_client_hash[i] = NULL; +} + +int bat_device_setup(void) +{ + int tmp_major; + + if (Major) + return 1; + + /* register our device - kernel assigns a free major number */ + tmp_major = register_chrdev(0, DRIVER_DEVICE, &fops); + if (tmp_major < 0) { + debug_log(LOG_TYPE_WARN, "Registering the character device failed with %d\n", + tmp_major); + return 0; + } + + batman_class = class_create(THIS_MODULE, "batman-adv"); + + if (IS_ERR(batman_class)) { + debug_log(LOG_TYPE_WARN, "Could not register class 'batman-adv' \n"); + return 0; + } + + device_create(batman_class, NULL, MKDEV(tmp_major, 0), NULL, + "batman-adv"); + + Major = tmp_major; + return 1; +} + +void bat_device_destroy(void) +{ + if (!Major) + return; + + device_destroy(batman_class, MKDEV(Major, 0)); + class_destroy(batman_class); + + /* Unregister the device */ + unregister_chrdev(Major, DRIVER_DEVICE); + + Major = 0; +} + +int bat_device_open(struct inode *inode, struct file *file) +{ + unsigned int i; + struct device_client *device_client; + + device_client = kmalloc(sizeof(struct device_client), GFP_KERNEL); + + if (!device_client) + return -ENOMEM; + + for (i = 0; i < 256; i++) { + if (!device_client_hash[i]) { + device_client_hash[i] = device_client; + break; + } + } + + if (device_client_hash[i] != device_client) { + debug_log(LOG_TYPE_WARN, "Error - can't add another packet client: maximum number of clients reached \n"); + kfree(device_client); + return -EXFULL; + } + + INIT_LIST_HEAD(&device_client->queue_list); + device_client->queue_len = 0; + device_client->index = i; + device_client->lock = __SPIN_LOCK_UNLOCKED(device_client->lock); + init_waitqueue_head(&device_client->queue_wait); + + file->private_data = device_client; + + inc_module_count(); + return 0; +} + +int bat_device_release(struct inode *inode, struct file *file) +{ + struct device_client *device_client = + (struct device_client *)file->private_data; + struct device_packet *device_packet; + struct list_head *list_pos, *list_pos_tmp; + + spin_lock(&device_client->lock); + + /* for all packets in the queue ... */ + list_for_each_safe(list_pos, list_pos_tmp, &device_client->queue_list) { + device_packet = list_entry(list_pos, + struct device_packet, list); + + list_del(list_pos); + kfree(device_packet); + } + + device_client_hash[device_client->index] = NULL; + spin_unlock(&device_client->lock); + + kfree(device_client); + dec_module_count(); + + return 0; +} + +ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + struct device_client *device_client = + (struct device_client *)file->private_data; + struct device_packet *device_packet; + int error; + + if ((file->f_flags & O_NONBLOCK) && (device_client->queue_len == 0)) + return -EAGAIN; + + if ((!buf) || (count < sizeof(struct icmp_packet))) + return -EINVAL; + + if (!access_ok(VERIFY_WRITE, buf, count)) + return -EFAULT; + + error = wait_event_interruptible(device_client->queue_wait, + device_client->queue_len); + + if (error) + return error; + + spin_lock(&device_client->lock); + + device_packet = list_first_entry(&device_client->queue_list, + struct device_packet, list); + list_del(&device_packet->list); + device_client->queue_len--; + + spin_unlock(&device_client->lock); + + error = __copy_to_user(buf, &device_packet->icmp_packet, + sizeof(struct icmp_packet)); + + kfree(device_packet); + + if (error) + return error; + + return sizeof(struct icmp_packet); +} + +ssize_t bat_device_write(struct file *file, const char __user *buff, + size_t len, loff_t *off) +{ + struct device_client *device_client = + (struct device_client *)file->private_data; + struct icmp_packet icmp_packet; + struct orig_node *orig_node; + struct batman_if *batman_if; + + if (len < sizeof(struct icmp_packet)) { + debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from char device: invalid packet size\n"); + return -EINVAL; + } + + if (!access_ok(VERIFY_READ, buff, sizeof(struct icmp_packet))) + return -EFAULT; + + if (__copy_from_user(&icmp_packet, buff, sizeof(icmp_packet))) + return -EFAULT; + + if (icmp_packet.packet_type != BAT_ICMP) { + debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n"); + return -EINVAL; + } + + if (icmp_packet.msg_type != ECHO_REQUEST) { + debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from char device: got bogus message type (expected: ECHO_REQUEST)\n"); + return -EINVAL; + } + + icmp_packet.uid = device_client->index; + + if (icmp_packet.version != COMPAT_VERSION) { + icmp_packet.msg_type = PARAMETER_PROBLEM; + icmp_packet.ttl = COMPAT_VERSION; + bat_device_add_packet(device_client, &icmp_packet); + goto out; + } + + if (atomic_read(&module_state) != MODULE_ACTIVE) + goto dst_unreach; + + spin_lock(&orig_hash_lock); + orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst)); + + if (!orig_node) + goto unlock; + + if (!orig_node->router) + goto unlock; + + batman_if = orig_node->batman_if; + + if (!batman_if) + goto unlock; + + memcpy(icmp_packet.orig, + batman_if->net_dev->dev_addr, + ETH_ALEN); + + send_raw_packet((unsigned char *)&icmp_packet, + sizeof(struct icmp_packet), + batman_if, orig_node->router->addr); + + spin_unlock(&orig_hash_lock); + goto out; + +unlock: + spin_unlock(&orig_hash_lock); +dst_unreach: + icmp_packet.msg_type = DESTINATION_UNREACHABLE; + bat_device_add_packet(device_client, &icmp_packet); +out: + return len; +} + +unsigned int bat_device_poll(struct file *file, poll_table *wait) +{ + struct device_client *device_client = + (struct device_client *)file->private_data; + + poll_wait(file, &device_client->queue_wait, wait); + + if (device_client->queue_len > 0) + return POLLIN | POLLRDNORM; + + return 0; +} + +void bat_device_add_packet(struct device_client *device_client, + struct icmp_packet *icmp_packet) +{ + struct device_packet *device_packet; + + device_packet = kmalloc(sizeof(struct device_packet), GFP_KERNEL); + + if (!device_packet) + return; + + INIT_LIST_HEAD(&device_packet->list); + memcpy(&device_packet->icmp_packet, icmp_packet, + sizeof(struct icmp_packet)); + + spin_lock(&device_client->lock); + + /* while waiting for the lock the device_client could have been + * deleted */ + if (!device_client_hash[icmp_packet->uid]) { + spin_unlock(&device_client->lock); + kfree(device_packet); + return; + } + + list_add_tail(&device_packet->list, &device_client->queue_list); + device_client->queue_len++; + + if (device_client->queue_len > 100) { + device_packet = list_first_entry(&device_client->queue_list, + struct device_packet, list); + + list_del(&device_packet->list); + kfree(device_packet); + device_client->queue_len--; + } + + spin_unlock(&device_client->lock); + + wake_up(&device_client->queue_wait); +} + +void bat_device_receive_packet(struct icmp_packet *icmp_packet) +{ + struct device_client *hash = device_client_hash[icmp_packet->uid]; + + if (hash) + bat_device_add_packet(hash, icmp_packet); +} diff --git a/drivers/staging/batman-adv/device.h b/drivers/staging/batman-adv/device.h new file mode 100644 index 0000000000000000000000000000000000000000..46c0f44965272401e55c100842828442d0486f13 --- /dev/null +++ b/drivers/staging/batman-adv/device.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "types.h" + +void bat_device_init(void); +int bat_device_setup(void); +void bat_device_destroy(void); +int bat_device_open(struct inode *inode, struct file *file); +int bat_device_release(struct inode *inode, struct file *file); +ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos); +ssize_t bat_device_write(struct file *file, const char __user *buff, + size_t len, loff_t *off); +unsigned int bat_device_poll(struct file *file, poll_table *wait); +void bat_device_add_packet(struct device_client *device_client, + struct icmp_packet *icmp_packet); +void bat_device_receive_packet(struct icmp_packet *icmp_packet); diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c new file mode 100644 index 0000000000000000000000000000000000000000..5ea35da5ee7a332db0589e0eee56655ddd125806 --- /dev/null +++ b/drivers/staging/batman-adv/hard-interface.c @@ -0,0 +1,451 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "hard-interface.h" +#include "log.h" +#include "soft-interface.h" +#include "send.h" +#include "translation-table.h" +#include "routing.h" +#include "hash.h" +#include "compat.h" + +#define MIN(x, y) ((x) < (y) ? (x) : (y)) + +static char avail_ifs; +static char active_ifs; + +static void hardif_free_interface(struct rcu_head *rcu); + +static struct batman_if *get_batman_if_by_name(char *name) +{ + struct batman_if *batman_if; + + rcu_read_lock(); + list_for_each_entry_rcu(batman_if, &if_list, list) { + if (strncmp(batman_if->dev, name, IFNAMSIZ) == 0) + goto out; + } + + batman_if = NULL; + +out: + rcu_read_unlock(); + return batman_if; +} + +int hardif_min_mtu(void) +{ + struct batman_if *batman_if; + /* allow big frames if all devices are capable to do so + * (have MTU > 1500 + BAT_HEADER_LEN) */ + int min_mtu = ETH_DATA_LEN; + + rcu_read_lock(); + list_for_each_entry_rcu(batman_if, &if_list, list) { + if ((batman_if->if_active == IF_ACTIVE) || + (batman_if->if_active == IF_TO_BE_ACTIVATED)) + min_mtu = MIN(batman_if->net_dev->mtu - BAT_HEADER_LEN, + min_mtu); + } + rcu_read_unlock(); + + return min_mtu; +} + +static void check_known_mac_addr(uint8_t *addr) +{ + struct batman_if *batman_if; + char mac_string[ETH_STR_LEN]; + + rcu_read_lock(); + list_for_each_entry_rcu(batman_if, &if_list, list) { + if ((batman_if->if_active != IF_ACTIVE) && + (batman_if->if_active != IF_TO_BE_ACTIVATED)) + continue; + + if (!compare_orig(batman_if->net_dev->dev_addr, addr)) + continue; + + addr_to_string(mac_string, addr); + debug_log(LOG_TYPE_WARN, "The newly added mac address (%s) already exists on: %s\n", + mac_string, batman_if->dev); + debug_log(LOG_TYPE_WARN, "It is strongly recommended to keep mac addresses unique to avoid problems!\n"); + } + rcu_read_unlock(); +} + +/* adjusts the MTU if a new interface with a smaller MTU appeared. */ +void update_min_mtu(void) +{ + int min_mtu; + + min_mtu = hardif_min_mtu(); + if (soft_device->mtu != min_mtu) + soft_device->mtu = min_mtu; +} + +/* checks if the interface is up. (returns 1 if it is) */ +static int hardif_is_interface_up(char *dev) +{ + struct net_device *net_dev; + + /** + * if we already have an interface in our interface list and + * the current interface is not the primary interface and + * the primary interface is not up and + * the primary interface has never been up - don't activate any + * secondary interface ! + */ + + rcu_read_lock(); + if ((!list_empty(&if_list)) && + strncmp(((struct batman_if *)if_list.next)->dev, dev, IFNAMSIZ) && + !(((struct batman_if *)if_list.next)->if_active == IF_ACTIVE) && + !(((struct batman_if *)if_list.next)->if_active == IF_TO_BE_ACTIVATED) && + (!main_if_was_up())) { + rcu_read_unlock(); + goto end; + } + rcu_read_unlock(); + +#ifdef __NET_NET_NAMESPACE_H + net_dev = dev_get_by_name(&init_net, dev); +#else + net_dev = dev_get_by_name(dev); +#endif + if (!net_dev) + goto end; + + if (!(net_dev->flags & IFF_UP)) + goto failure; + + dev_put(net_dev); + return 1; + +failure: + dev_put(net_dev); +end: + return 0; +} + +/* deactivates the interface. */ +void hardif_deactivate_interface(struct batman_if *batman_if) +{ + if (batman_if->if_active != IF_ACTIVE) + return; + + if (batman_if->raw_sock) + sock_release(batman_if->raw_sock); + + /** + * batman_if->net_dev has been acquired by dev_get_by_name() in + * proc_interfaces_write() and has to be unreferenced. + */ + + if (batman_if->net_dev) + dev_put(batman_if->net_dev); + + batman_if->raw_sock = NULL; + batman_if->net_dev = NULL; + + batman_if->if_active = IF_INACTIVE; + active_ifs--; + + debug_log(LOG_TYPE_NOTICE, "Interface deactivated: %s\n", + batman_if->dev); +} + +/* (re)activate given interface. */ +static void hardif_activate_interface(struct batman_if *batman_if) +{ + struct sockaddr_ll bind_addr; + int retval; + + if (batman_if->if_active != IF_INACTIVE) + return; + +#ifdef __NET_NET_NAMESPACE_H + batman_if->net_dev = dev_get_by_name(&init_net, batman_if->dev); +#else + batman_if->net_dev = dev_get_by_name(batman_if->dev); +#endif + if (!batman_if->net_dev) + goto dev_err; + + retval = sock_create_kern(PF_PACKET, SOCK_RAW, + __constant_htons(ETH_P_BATMAN), + &batman_if->raw_sock); + + if (retval < 0) { + debug_log(LOG_TYPE_WARN, "Can't create raw socket: %i\n", + retval); + goto sock_err; + } + + bind_addr.sll_family = AF_PACKET; + bind_addr.sll_ifindex = batman_if->net_dev->ifindex; + bind_addr.sll_protocol = 0; /* is set by the kernel */ + + retval = kernel_bind(batman_if->raw_sock, + (struct sockaddr *)&bind_addr, sizeof(bind_addr)); + + if (retval < 0) { + debug_log(LOG_TYPE_WARN, "Can't create bind raw socket: %i\n", + retval); + goto bind_err; + } + + check_known_mac_addr(batman_if->net_dev->dev_addr); + + batman_if->raw_sock->sk->sk_user_data = + batman_if->raw_sock->sk->sk_data_ready; + batman_if->raw_sock->sk->sk_data_ready = batman_data_ready; + + addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr); + + memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig, + batman_if->net_dev->dev_addr, ETH_ALEN); + memcpy(((struct batman_packet *)(batman_if->packet_buff))->prev_sender, + batman_if->net_dev->dev_addr, ETH_ALEN); + + batman_if->if_active = IF_TO_BE_ACTIVATED; + active_ifs++; + + /* save the mac address if it is our primary interface */ + if (batman_if->if_num == 0) + set_main_if_addr(batman_if->net_dev->dev_addr); + + debug_log(LOG_TYPE_NOTICE, "Interface activated: %s\n", + batman_if->dev); + + return; + +bind_err: + sock_release(batman_if->raw_sock); +sock_err: + dev_put(batman_if->net_dev); +dev_err: + batman_if->raw_sock = NULL; + batman_if->net_dev = NULL; +} + +static void hardif_free_interface(struct rcu_head *rcu) +{ + struct batman_if *batman_if = container_of(rcu, struct batman_if, rcu); + + kfree(batman_if->packet_buff); + kfree(batman_if->dev); + kfree(batman_if); +} + +/** + * called by + * - echo '' > /proc/.../interfaces + * - modprobe -r batman-adv-core + */ +/* removes and frees all interfaces */ +void hardif_remove_interfaces(void) +{ + struct batman_if *batman_if = NULL; + + avail_ifs = 0; + + /* no lock needed - we don't delete somewhere else */ + list_for_each_entry(batman_if, &if_list, list) { + + list_del_rcu(&batman_if->list); + + /* first deactivate interface */ + if (batman_if->if_active != IF_INACTIVE) + hardif_deactivate_interface(batman_if); + + call_rcu(&batman_if->rcu, hardif_free_interface); + } +} + +static int resize_orig(struct orig_node *orig_node, int if_num) +{ + void *data_ptr; + + data_ptr = kmalloc((if_num + 1) * sizeof(TYPE_OF_WORD) * NUM_WORDS, + GFP_ATOMIC); + if (!data_ptr) { + debug_log(LOG_TYPE_WARN, "Can't resize orig: out of memory\n"); + return -1; + } + + memcpy(data_ptr, orig_node->bcast_own, + if_num * sizeof(TYPE_OF_WORD) * NUM_WORDS); + kfree(orig_node->bcast_own); + orig_node->bcast_own = data_ptr; + + data_ptr = kmalloc((if_num + 1) * sizeof(uint8_t), GFP_ATOMIC); + if (!data_ptr) { + debug_log(LOG_TYPE_WARN, "Can't resize orig: out of memory\n"); + return -1; + } + + memcpy(data_ptr, orig_node->bcast_own_sum, if_num * sizeof(uint8_t)); + kfree(orig_node->bcast_own_sum); + orig_node->bcast_own_sum = data_ptr; + + return 0; +} + + +/* adds an interface the interface list and activate it, if possible */ +int hardif_add_interface(char *dev, int if_num) +{ + struct batman_if *batman_if; + struct batman_packet *batman_packet; + struct orig_node *orig_node; + struct hash_it_t *hashit = NULL; + + batman_if = kmalloc(sizeof(struct batman_if), GFP_KERNEL); + + if (!batman_if) { + debug_log(LOG_TYPE_WARN, "Can't add interface (%s): out of memory\n", dev); + return -1; + } + + batman_if->raw_sock = NULL; + batman_if->net_dev = NULL; + + if ((if_num == 0) && (num_hna > 0)) + batman_if->packet_len = BAT_PACKET_LEN + num_hna * ETH_ALEN; + else + batman_if->packet_len = BAT_PACKET_LEN; + + batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_KERNEL); + + if (!batman_if->packet_buff) { + debug_log(LOG_TYPE_WARN, "Can't add interface packet (%s): out of memory\n", dev); + goto out; + } + + batman_if->if_num = if_num; + batman_if->dev = dev; + batman_if->if_active = IF_INACTIVE; + INIT_RCU_HEAD(&batman_if->rcu); + + debug_log(LOG_TYPE_NOTICE, "Adding interface: %s\n", dev); + avail_ifs++; + + INIT_LIST_HEAD(&batman_if->list); + + batman_packet = (struct batman_packet *)(batman_if->packet_buff); + batman_packet->packet_type = BAT_PACKET; + batman_packet->version = COMPAT_VERSION; + batman_packet->flags = 0x00; + batman_packet->ttl = (batman_if->if_num > 0 ? 2 : TTL); + batman_packet->flags = 0; + batman_packet->tq = TQ_MAX_VALUE; + batman_packet->num_hna = 0; + + if (batman_if->packet_len != BAT_PACKET_LEN) { + unsigned char *hna_buff; + int hna_len; + + hna_buff = batman_if->packet_buff + BAT_PACKET_LEN; + hna_len = batman_if->packet_len - BAT_PACKET_LEN; + batman_packet->num_hna = hna_local_fill_buffer(hna_buff, + hna_len); + } + + atomic_set(&batman_if->seqno, 1); + + /* resize all orig nodes because orig_node->bcast_own(_sum) depend on + * if_num */ + spin_lock(&orig_hash_lock); + + while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { + orig_node = hashit->bucket->data; + if (resize_orig(orig_node, if_num) == -1) { + spin_unlock(&orig_hash_lock); + goto out; + } + } + + spin_unlock(&orig_hash_lock); + + if (!hardif_is_interface_up(batman_if->dev)) + debug_log(LOG_TYPE_WARN, "Not using interface %s (retrying later): interface not active\n", batman_if->dev); + else + hardif_activate_interface(batman_if); + + list_add_tail_rcu(&batman_if->list, &if_list); + + /* begin sending originator messages on that interface */ + schedule_own_packet(batman_if); + return 1; + +out: + if (batman_if->packet_buff) + kfree(batman_if->packet_buff); + kfree(batman_if); + kfree(dev); + return -1; +} + +char hardif_get_active_if_num(void) +{ + return active_ifs; +} + +static int hard_if_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct net_device *dev = (struct net_device *)ptr; + struct batman_if *batman_if = get_batman_if_by_name(dev->name); + + if (!batman_if) + goto out; + + switch (event) { + case NETDEV_GOING_DOWN: + case NETDEV_DOWN: + case NETDEV_UNREGISTER: + hardif_deactivate_interface(batman_if); + break; + case NETDEV_UP: + hardif_activate_interface(batman_if); + if ((atomic_read(&module_state) == MODULE_INACTIVE) && + (hardif_get_active_if_num() > 0)) { + activate_module(); + } + break; + /* NETDEV_CHANGEADDR - mac address change - what are we doing here ? */ + default: + /* debug_log(LOG_TYPE_CRIT, "hard_if_event: %s %i\n", dev->name, event); */ + break; + }; + + update_min_mtu(); + +out: + return NOTIFY_DONE; +} + +struct notifier_block hard_if_notifier = { + .notifier_call = hard_if_event, +}; diff --git a/drivers/staging/batman-adv/hard-interface.h b/drivers/staging/batman-adv/hard-interface.h new file mode 100644 index 0000000000000000000000000000000000000000..742358c00c0e1972fa14ffdc5319e1e47db94bc8 --- /dev/null +++ b/drivers/staging/batman-adv/hard-interface.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#define IF_INACTIVE 0 +#define IF_ACTIVE 1 +/* #define IF_TO_BE_DEACTIVATED 2 - not needed anymore */ +#define IF_TO_BE_ACTIVATED 3 + +extern struct notifier_block hard_if_notifier; + +void hardif_remove_interfaces(void); +int hardif_add_interface(char *dev, int if_num); +void hardif_deactivate_interface(struct batman_if *batman_if); +char hardif_get_active_if_num(void); +void hardif_check_interfaces_status(void); +void hardif_check_interfaces_status_wq(struct work_struct *work); +int hardif_min_mtu(void); +void update_min_mtu(void); diff --git a/drivers/staging/batman-adv/hash.c b/drivers/staging/batman-adv/hash.c new file mode 100644 index 0000000000000000000000000000000000000000..61cb4a20ebca73ecdfd32dd99bc7632a28f487d7 --- /dev/null +++ b/drivers/staging/batman-adv/hash.c @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2006-2009 B.A.T.M.A.N. contributors: + * + * Simon Wunderlich, Marek Lindner + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "hash.h" + +/* clears the hash */ +void hash_init(struct hashtable_t *hash) +{ + int i; + + hash->elements = 0; + + for (i = 0 ; i < hash->size; i++) + hash->table[i] = NULL; +} + +/* remove the hash structure. if hashdata_free_cb != NULL, this function will be + * called to remove the elements inside of the hash. if you don't remove the + * elements, memory might be leaked. */ +void hash_delete(struct hashtable_t *hash, hashdata_free_cb free_cb) +{ + struct element_t *bucket, *last_bucket; + int i; + + for (i = 0; i < hash->size; i++) { + bucket = hash->table[i]; + + while (bucket != NULL) { + if (free_cb != NULL) + free_cb(bucket->data); + + last_bucket = bucket; + bucket = bucket->next; + kfree(last_bucket); + } + } + + hash_destroy(hash); +} + +/* free only the hashtable and the hash itself. */ +void hash_destroy(struct hashtable_t *hash) +{ + kfree(hash->table); + kfree(hash); +} + +/* iterate though the hash. first element is selected with iter_in NULL. use + * the returned iterator to access the elements until hash_it_t returns NULL. */ +struct hash_it_t *hash_iterate(struct hashtable_t *hash, + struct hash_it_t *iter_in) +{ + struct hash_it_t *iter; + + if (!hash) + return NULL; + + if (iter_in == NULL) { + iter = kmalloc(sizeof(struct hash_it_t), GFP_ATOMIC); + iter->index = -1; + iter->bucket = NULL; + iter->prev_bucket = NULL; + } else { + iter = iter_in; + } + + /* sanity checks first (if our bucket got deleted in the last + * iteration): */ + if (iter->bucket != NULL) { + if (iter->first_bucket != NULL) { + /* we're on the first element and it got removed after + * the last iteration. */ + if ((*iter->first_bucket) != iter->bucket) { + /* there are still other elements in the list */ + if ((*iter->first_bucket) != NULL) { + iter->prev_bucket = NULL; + iter->bucket = (*iter->first_bucket); + iter->first_bucket = + &hash->table[iter->index]; + return iter; + } else { + iter->bucket = NULL; + } + } + } else if (iter->prev_bucket != NULL) { + /* + * we're not on the first element, and the bucket got + * removed after the last iteration. the last bucket's + * next pointer is not pointing to our actual bucket + * anymore. select the next. + */ + if (iter->prev_bucket->next != iter->bucket) + iter->bucket = iter->prev_bucket; + } + } + + /* now as we are sane, select the next one if there is some */ + if (iter->bucket != NULL) { + if (iter->bucket->next != NULL) { + iter->prev_bucket = iter->bucket; + iter->bucket = iter->bucket->next; + iter->first_bucket = NULL; + return iter; + } + } + + /* if not returned yet, we've reached the last one on the index and have + * to search forward */ + iter->index++; + /* go through the entries of the hash table */ + while (iter->index < hash->size) { + if ((hash->table[iter->index]) != NULL) { + iter->prev_bucket = NULL; + iter->bucket = hash->table[iter->index]; + iter->first_bucket = &hash->table[iter->index]; + return iter; + } else { + iter->index++; + } + } + + /* nothing to iterate over anymore */ + kfree(iter); + return NULL; +} + +/* allocates and clears the hash */ +struct hashtable_t *hash_new(int size, hashdata_compare_cb compare, + hashdata_choose_cb choose) +{ + struct hashtable_t *hash; + + hash = kmalloc(sizeof(struct hashtable_t) , GFP_ATOMIC); + + if (hash == NULL) + return NULL; + + hash->size = size; + hash->table = kmalloc(sizeof(struct element_t *) * size, GFP_ATOMIC); + + if (hash->table == NULL) { + kfree(hash); + return NULL; + } + + hash_init(hash); + + hash->compare = compare; + hash->choose = choose; + + return hash; +} + +/* adds data to the hashtable. returns 0 on success, -1 on error */ +int hash_add(struct hashtable_t *hash, void *data) +{ + int index; + struct element_t *bucket, *prev_bucket = NULL; + + if (!hash) + return -1; + + index = hash->choose(data, hash->size); + bucket = hash->table[index]; + + while (bucket != NULL) { + if (hash->compare(bucket->data, data)) + return -1; + + prev_bucket = bucket; + bucket = bucket->next; + } + + /* found the tail of the list, add new element */ + bucket = kmalloc(sizeof(struct element_t), GFP_ATOMIC); + + if (bucket == NULL) + return -1; + + bucket->data = data; + bucket->next = NULL; + + /* and link it */ + if (prev_bucket == NULL) + hash->table[index] = bucket; + else + prev_bucket->next = bucket; + + hash->elements++; + return 0; +} + +/* finds data, based on the key in keydata. returns the found data on success, + * or NULL on error */ +void *hash_find(struct hashtable_t *hash, void *keydata) +{ + int index; + struct element_t *bucket; + + if (!hash) + return NULL; + + index = hash->choose(keydata , hash->size); + bucket = hash->table[index]; + + while (bucket != NULL) { + if (hash->compare(bucket->data, keydata)) + return bucket->data; + + bucket = bucket->next; + } + + return NULL; +} + +/* remove bucket (this might be used in hash_iterate() if you already found the + * bucket you want to delete and don't need the overhead to find it again with + * hash_remove(). But usually, you don't want to use this function, as it + * fiddles with hash-internals. */ +void *hash_remove_bucket(struct hashtable_t *hash, struct hash_it_t *hash_it_t) +{ + void *data_save; + + data_save = hash_it_t->bucket->data; + + if (hash_it_t->prev_bucket != NULL) + hash_it_t->prev_bucket->next = hash_it_t->bucket->next; + else if (hash_it_t->first_bucket != NULL) + (*hash_it_t->first_bucket) = hash_it_t->bucket->next; + + kfree(hash_it_t->bucket); + hash->elements--; + + return data_save; +} + +/* removes data from hash, if found. returns pointer do data on success, so you + * can remove the used structure yourself, or NULL on error . data could be the + * structure you use with just the key filled, we just need the key for + * comparing. */ +void *hash_remove(struct hashtable_t *hash, void *data) +{ + struct hash_it_t hash_it_t; + + hash_it_t.index = hash->choose(data, hash->size); + hash_it_t.bucket = hash->table[hash_it_t.index]; + hash_it_t.prev_bucket = NULL; + + while (hash_it_t.bucket != NULL) { + if (hash->compare(hash_it_t.bucket->data, data)) { + hash_it_t.first_bucket = + (hash_it_t.bucket == + hash->table[hash_it_t.index] ? + &hash->table[hash_it_t.index] : NULL); + return hash_remove_bucket(hash, &hash_it_t); + } + + hash_it_t.prev_bucket = hash_it_t.bucket; + hash_it_t.bucket = hash_it_t.bucket->next; + } + + return NULL; +} + +/* resize the hash, returns the pointer to the new hash or NULL on + * error. removes the old hash on success. */ +struct hashtable_t *hash_resize(struct hashtable_t *hash, int size) +{ + struct hashtable_t *new_hash; + struct element_t *bucket; + int i; + + /* initialize a new hash with the new size */ + new_hash = hash_new(size, hash->compare, hash->choose); + + if (new_hash == NULL) + return NULL; + + /* copy the elements */ + for (i = 0; i < hash->size; i++) { + bucket = hash->table[i]; + + while (bucket != NULL) { + hash_add(new_hash, bucket->data); + bucket = bucket->next; + } + } + + /* remove hash and eventual overflow buckets but not the content + * itself. */ + hash_delete(hash, NULL); + + return new_hash; +} diff --git a/drivers/staging/batman-adv/hash.h b/drivers/staging/batman-adv/hash.h new file mode 100644 index 0000000000000000000000000000000000000000..bb60f082be6a7f9c9b7f5987ee7298842e49fada --- /dev/null +++ b/drivers/staging/batman-adv/hash.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2006-2009 B.A.T.M.A.N. contributors: + * + * Simon Wunderlich, Marek Lindner + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#ifndef _BATMAN_HASH_H +#define _BATMAN_HASH_H + +typedef int (*hashdata_compare_cb)(void *, void *); +typedef int (*hashdata_choose_cb)(void *, int); +typedef void (*hashdata_free_cb)(void *); + +struct element_t { + void *data; /* pointer to the data */ + struct element_t *next; /* overflow bucket pointer */ +}; + +struct hash_it_t { + int index; + struct element_t *bucket; + struct element_t *prev_bucket; + struct element_t **first_bucket; +}; + +struct hashtable_t { + struct element_t **table; /* the hashtable itself, with the buckets */ + int elements; /* number of elements registered */ + int size; /* size of hashtable */ + hashdata_compare_cb compare;/* callback to a compare function. should + * compare 2 element datas for their keys, + * return 0 if same and not 0 if not + * same */ + hashdata_choose_cb choose; /* the hashfunction, should return an index + * based on the key in the data of the first + * argument and the size the second */ +}; + +/* clears the hash */ +void hash_init(struct hashtable_t *hash); + +/* allocates and clears the hash */ +struct hashtable_t *hash_new(int size, hashdata_compare_cb compare, + hashdata_choose_cb choose); + +/* remove bucket (this might be used in hash_iterate() if you already found the + * bucket you want to delete and don't need the overhead to find it again with + * hash_remove(). But usually, you don't want to use this function, as it + * fiddles with hash-internals. */ +void *hash_remove_bucket(struct hashtable_t *hash, struct hash_it_t *hash_it_t); + +/* remove the hash structure. if hashdata_free_cb != NULL, this function will be + * called to remove the elements inside of the hash. if you don't remove the + * elements, memory might be leaked. */ +void hash_delete(struct hashtable_t *hash, hashdata_free_cb free_cb); + +/* free only the hashtable and the hash itself. */ +void hash_destroy(struct hashtable_t *hash); + +/* adds data to the hashtable. returns 0 on success, -1 on error */ +int hash_add(struct hashtable_t *hash, void *data); + +/* removes data from hash, if found. returns pointer do data on success, so you + * can remove the used structure yourself, or NULL on error . data could be the + * structure you use with just the key filled, we just need the key for + * comparing. */ +void *hash_remove(struct hashtable_t *hash, void *data); + +/* finds data, based on the key in keydata. returns the found data on success, + * or NULL on error */ +void *hash_find(struct hashtable_t *hash, void *keydata); + +/* resize the hash, returns the pointer to the new hash or NULL on + * error. removes the old hash on success */ +struct hashtable_t *hash_resize(struct hashtable_t *hash, int size); + +/* iterate though the hash. first element is selected with iter_in NULL. use + * the returned iterator to access the elements until hash_it_t returns NULL. */ +struct hash_it_t *hash_iterate(struct hashtable_t *hash, + struct hash_it_t *iter_in); + +/* print the hash table for debugging */ +void hash_debug(struct hashtable_t *hash); +#endif diff --git a/drivers/staging/batman-adv/log.c b/drivers/staging/batman-adv/log.c new file mode 100644 index 0000000000000000000000000000000000000000..f37c7f01a9f5a361c2d2bffafadb643fb6217bb7 --- /dev/null +++ b/drivers/staging/batman-adv/log.c @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "log.h" + +#define LOG_BUF_MASK (log_buf_len-1) +#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK]) + +static char log_buf[LOG_BUF_LEN]; +static int log_buf_len = LOG_BUF_LEN; +static unsigned long log_start; +static unsigned long log_end; +uint8_t log_level; + +static DEFINE_SPINLOCK(logbuf_lock); + +const struct file_operations proc_log_operations = { + .open = log_open, + .release = log_release, + .read = log_read, + .write = log_write, + .poll = log_poll, +}; + +static DECLARE_WAIT_QUEUE_HEAD(log_wait); + +static void emit_log_char(char c) +{ + LOG_BUF(log_end) = c; + log_end++; + + if (log_end - log_start > log_buf_len) + log_start = log_end - log_buf_len; +} + +static int fdebug_log(char *fmt, ...) +{ + int printed_len; + char *p; + va_list args; + static char debug_log_buf[256]; + unsigned long flags; + + spin_lock_irqsave(&logbuf_lock, flags); + va_start(args, fmt); + printed_len = vscnprintf(debug_log_buf, sizeof(debug_log_buf), fmt, + args); + va_end(args); + + for (p = debug_log_buf; *p != 0; p++) + emit_log_char(*p); + + spin_unlock_irqrestore(&logbuf_lock, flags); + + wake_up(&log_wait); + + return 0; +} + +int debug_log(int type, char *fmt, ...) +{ + va_list args; + int retval = 0; + char tmp_log_buf[256]; + + /* only critical information get into the official kernel log */ + if (type == LOG_TYPE_CRIT) { + va_start(args, fmt); + vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args); + printk(KERN_ERR "batman-adv: %s", tmp_log_buf); + va_end(args); + } + + if ((type == LOG_TYPE_CRIT) || (log_level & type)) { + va_start(args, fmt); + vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args); + fdebug_log("[%10u] %s", (jiffies / HZ), tmp_log_buf); + va_end(args); + } + + return retval; +} + +int log_open(struct inode *inode, struct file *file) +{ + inc_module_count(); + return 0; +} + +int log_release(struct inode *inode, struct file *file) +{ + dec_module_count(); + return 0; +} + +ssize_t log_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + int error, i = 0; + char c; + unsigned long flags; + + if ((file->f_flags & O_NONBLOCK) && !(log_end - log_start)) + return -EAGAIN; + + if ((!buf) || (count < 0)) + return -EINVAL; + + if (count == 0) + return 0; + + if (!access_ok(VERIFY_WRITE, buf, count)) + return -EFAULT; + + error = wait_event_interruptible(log_wait, (log_start - log_end)); + + if (error) + return error; + + spin_lock_irqsave(&logbuf_lock, flags); + + while ((!error) && (log_start != log_end) && (i < count)) { + c = LOG_BUF(log_start); + + log_start++; + + spin_unlock_irqrestore(&logbuf_lock, flags); + + error = __put_user(c, buf); + + spin_lock_irqsave(&logbuf_lock, flags); + + buf++; + i++; + + } + + spin_unlock_irqrestore(&logbuf_lock, flags); + + if (!error) + return i; + + return error; +} + +ssize_t log_write(struct file *file, const char __user *buf, size_t count, + loff_t *ppos) +{ + return count; +} + +unsigned int log_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &log_wait, wait); + + if (log_end - log_start) + return POLLIN | POLLRDNORM; + + return 0; +} diff --git a/drivers/staging/batman-adv/log.h b/drivers/staging/batman-adv/log.h new file mode 100644 index 0000000000000000000000000000000000000000..780e3abb48f9c3c3409fa8925c2794ad3692b132 --- /dev/null +++ b/drivers/staging/batman-adv/log.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +extern const struct file_operations proc_log_operations; +extern uint8_t log_level; + +int debug_log(int type, char *fmt, ...); +int log_open(struct inode *inode, struct file *file); +int log_release(struct inode *inode, struct file *file); +ssize_t log_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos); +ssize_t log_write(struct file *file, const char __user *buf, size_t count, + loff_t *ppos); +unsigned int log_poll(struct file *file, poll_table *wait); diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c new file mode 100644 index 0000000000000000000000000000000000000000..bb89bfc5dda618d766072639e2dd500940f797dc --- /dev/null +++ b/drivers/staging/batman-adv/main.c @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "proc.h" +#include "log.h" +#include "routing.h" +#include "send.h" +#include "soft-interface.h" +#include "device.h" +#include "translation-table.h" +#include "hard-interface.h" +#include "types.h" +#include "vis.h" +#include "hash.h" +#include "compat.h" + +struct list_head if_list; +struct hlist_head forw_bat_list; +struct hlist_head forw_bcast_list; +struct hashtable_t *orig_hash; + +DEFINE_SPINLOCK(orig_hash_lock); +DEFINE_SPINLOCK(forw_bat_list_lock); +DEFINE_SPINLOCK(forw_bcast_list_lock); + +atomic_t originator_interval; +atomic_t vis_interval; +atomic_t aggregation_enabled; +int16_t num_hna; +int16_t num_ifs; + +struct net_device *soft_device; + +static struct task_struct *kthread_task; + +unsigned char broadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +atomic_t module_state; + +struct workqueue_struct *bat_event_workqueue; + +int init_module(void) +{ + int retval; + + INIT_LIST_HEAD(&if_list); + INIT_HLIST_HEAD(&forw_bat_list); + INIT_HLIST_HEAD(&forw_bcast_list); + + atomic_set(&module_state, MODULE_INACTIVE); + + atomic_set(&originator_interval, 1000); + atomic_set(&vis_interval, 1000);/* TODO: raise this later, this is only + * for debugging now. */ + atomic_set(&aggregation_enabled, 1); + + /* the name should not be longer than 10 chars - see + * http://lwn.net/Articles/23634/ */ + bat_event_workqueue = create_singlethread_workqueue("bat_events"); + + if (!bat_event_workqueue) + return -ENOMEM; + + retval = setup_procfs(); + if (retval < 0) + return retval; + + bat_device_init(); + + /* initialize layer 2 interface */ + soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d", + interface_setup); + + if (!soft_device) { + debug_log(LOG_TYPE_CRIT, "Unable to allocate the batman interface\n"); + goto end; + } + + retval = register_netdev(soft_device); + + if (retval < 0) { + debug_log(LOG_TYPE_CRIT, "Unable to register the batman interface: %i\n", retval); + goto free_soft_device; + } + + register_netdevice_notifier(&hard_if_notifier); + + debug_log(LOG_TYPE_CRIT, "B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded \n", + SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION); + + return 0; + +free_soft_device: + free_netdev(soft_device); + soft_device = NULL; +end: + return -ENOMEM; +} + +void cleanup_module(void) +{ + shutdown_module(); + + if (soft_device) { + unregister_netdev(soft_device); + soft_device = NULL; + } + + unregister_netdevice_notifier(&hard_if_notifier); + cleanup_procfs(); + + destroy_workqueue(bat_event_workqueue); + bat_event_workqueue = NULL; +} + +/* activates the module, creates bat device, starts timer ... */ +void activate_module(void) +{ + if (originator_init() < 1) + goto err; + + if (hna_local_init() < 1) + goto err; + + if (hna_global_init() < 1) + goto err; + + hna_local_add(soft_device->dev_addr); + + if (bat_device_setup() < 1) + goto end; + + if (vis_init() < 1) + goto err; + + /* (re)start kernel thread for packet processing */ + if (!kthread_task) { + kthread_task = kthread_run(packet_recv_thread, NULL, "batman-adv"); + + if (IS_ERR(kthread_task)) { + debug_log(LOG_TYPE_CRIT, "Unable to start packet receive thread\n"); + kthread_task = NULL; + } + } + + update_min_mtu(); + atomic_set(&module_state, MODULE_ACTIVE); + goto end; + +err: + debug_log(LOG_TYPE_CRIT, "Unable to allocate memory for mesh information structures: out of mem ?\n"); + shutdown_module(); +end: + return; +} + +/* shuts down the whole module.*/ +void shutdown_module(void) +{ + atomic_set(&module_state, MODULE_DEACTIVATING); + + purge_outstanding_packets(); + flush_workqueue(bat_event_workqueue); + + vis_quit(); + + /* deactivate kernel thread for packet processing (if running) */ + if (kthread_task) { + atomic_set(&exit_cond, 1); + wake_up_interruptible(&thread_wait); + kthread_stop(kthread_task); + + kthread_task = NULL; + } + + originator_free(); + + hna_local_free(); + hna_global_free(); + + synchronize_net(); + bat_device_destroy(); + + hardif_remove_interfaces(); + synchronize_rcu(); + atomic_set(&module_state, MODULE_INACTIVE); +} + +void inc_module_count(void) +{ + try_module_get(THIS_MODULE); +} + +void dec_module_count(void) +{ + module_put(THIS_MODULE); +} + +int addr_to_string(char *buff, uint8_t *addr) +{ + return sprintf(buff, "%02x:%02x:%02x:%02x:%02x:%02x", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); +} + +/* returns 1 if they are the same originator */ + +int compare_orig(void *data1, void *data2) +{ + return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); +} + +/* hashfunction to choose an entry in a hash table of given size */ +/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */ +int choose_orig(void *data, int32_t size) +{ + unsigned char *key = data; + uint32_t hash = 0; + size_t i; + + for (i = 0; i < 6; i++) { + hash += key[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + + return hash % size; +} + +int is_my_mac(uint8_t *addr) +{ + struct batman_if *batman_if; + rcu_read_lock(); + list_for_each_entry_rcu(batman_if, &if_list, list) { + if ((batman_if->net_dev) && + (compare_orig(batman_if->net_dev->dev_addr, addr))) { + rcu_read_unlock(); + return 1; + } + } + rcu_read_unlock(); + return 0; + +} + +int is_bcast(uint8_t *addr) +{ + return (addr[0] == (uint8_t)0xff) && (addr[1] == (uint8_t)0xff); +} + +int is_mcast(uint8_t *addr) +{ + return *addr & 0x01; +} + +MODULE_LICENSE("GPL"); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_SUPPORTED_DEVICE(DRIVER_DEVICE); +#ifdef REVISION_VERSION +MODULE_VERSION(SOURCE_VERSION "-" REVISION_VERSION); +#else +MODULE_VERSION(SOURCE_VERSION); +#endif diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h new file mode 100644 index 0000000000000000000000000000000000000000..facb6b79ee5231f0982e9fa03f0766759fe6976f --- /dev/null +++ b/drivers/staging/batman-adv/main.h @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +/* Kernel Programming */ +#define LINUX + +#define DRIVER_AUTHOR "Marek Lindner , Simon Wunderlich " +#define DRIVER_DESC "B.A.T.M.A.N. advanced" +#define DRIVER_DEVICE "batman-adv" + +#define SOURCE_VERSION "0.2.1-beta" + + +/* B.A.T.M.A.N. parameters */ + +#define TQ_MAX_VALUE 255 +#define JITTER 20 +#define TTL 50 /* Time To Live of broadcast messages */ +#define MAX_ADDR 16 /* number of interfaces which can be added to + * batman. */ + +#define PURGE_TIMEOUT 200000 /* purge originators after time in ms if no + * valid packet comes in -> TODO: check + * influence on TQ_LOCAL_WINDOW_SIZE */ +#define LOCAL_HNA_TIMEOUT 3600000 + +#define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator + * messages in squence numbers (should be a + * multiple of our word size) */ +#define TQ_GLOBAL_WINDOW_SIZE 5 +#define TQ_LOCAL_BIDRECT_SEND_MINIMUM 1 +#define TQ_LOCAL_BIDRECT_RECV_MINIMUM 1 +#define TQ_TOTAL_BIDRECT_LIMIT 1 + +#define TQ_HOP_PENALTY 10 + +#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE) + +#define PACKBUFF_SIZE 2000 +#define LOG_BUF_LEN 8192 /* has to be a power of 2 */ +#define ETH_STR_LEN 20 + +#define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or + * change the size of + * forw_packet->direct_link_flags */ +#define MAX_AGGREGATION_MS 100 + +#define MODULE_INACTIVE 0 +#define MODULE_ACTIVE 1 +#define MODULE_DEACTIVATING 2 + + +/* + * Logging + */ + +#define LOG_TYPE_CRIT 0 /* highest priority for fatal errors such as + * blocked sockets / failed packet delivery / + * programming errors */ +#define LOG_TYPE_WARN 1 /* warnings for small errors like wrong user + * input / damaged packets / etc */ +#define LOG_TYPE_NOTICE 2 /* notice information for new interfaces / + * changed settings / new originators / etc */ +#define LOG_TYPE_BATMAN 4 /* all messages related to routing / flooding / + * broadcasting / etc */ +#define LOG_TYPE_ROUTES 8 /* route or hna added / changed / deleted */ +#define LOG_TYPE_CRIT_NAME "critical" +#define LOG_TYPE_WARN_NAME "warnings" +#define LOG_TYPE_NOTICE_NAME "notices" +#define LOG_TYPE_BATMAN_NAME "batman" +#define LOG_TYPE_ROUTES_NAME "routes" + +/* + * Vis + */ + +/* #define VIS_SUBCLUSTERS_DISABLED */ + +/* + * Kernel headers + */ + +#include /* mutex */ +#include /* needed by all modules */ +#include /* netdevice */ +#include /* ethernet header */ +#include /* poll_table */ +#include /* kernel threads */ +#include /* schedule types */ +#include /* workqueue */ +#include /* struct sock */ +#include +#include "types.h" + +#ifndef REVISION_VERSION +#define REVISION_VERSION_STR "" +#else +#define REVISION_VERSION_STR " "REVISION_VERSION +#endif + +extern struct list_head if_list; +extern struct hlist_head forw_bat_list; +extern struct hlist_head forw_bcast_list; +extern struct hashtable_t *orig_hash; + +extern spinlock_t orig_hash_lock; +extern spinlock_t forw_bat_list_lock; +extern spinlock_t forw_bcast_list_lock; + +extern atomic_t originator_interval; +extern atomic_t vis_interval; +extern atomic_t aggregation_enabled; +extern int16_t num_hna; +extern int16_t num_ifs; + +extern struct net_device *soft_device; + +extern unsigned char broadcastAddr[]; +extern atomic_t module_state; +extern struct workqueue_struct *bat_event_workqueue; + +void activate_module(void); +void shutdown_module(void); +void inc_module_count(void); +void dec_module_count(void); +int addr_to_string(char *buff, uint8_t *addr); +int compare_orig(void *data1, void *data2); +int choose_orig(void *data, int32_t size); +int is_my_mac(uint8_t *addr); +int is_bcast(uint8_t *addr); +int is_mcast(uint8_t *addr); + + diff --git a/drivers/staging/batman-adv/packet.h b/drivers/staging/batman-adv/packet.h new file mode 100644 index 0000000000000000000000000000000000000000..5627ca326018c7e8dda6b4f53004722d5c5d47e3 --- /dev/null +++ b/drivers/staging/batman-adv/packet.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */ + +#define BAT_PACKET 0x01 +#define BAT_ICMP 0x02 +#define BAT_UNICAST 0x03 +#define BAT_BCAST 0x04 +#define BAT_VIS 0x05 + +/* this file is included by batctl which needs these defines */ +#define COMPAT_VERSION 8 +#define DIRECTLINK 0x40 +#define VIS_SERVER 0x20 + +/* ICMP message types */ +#define ECHO_REPLY 0 +#define DESTINATION_UNREACHABLE 3 +#define ECHO_REQUEST 8 +#define TTL_EXCEEDED 11 +#define PARAMETER_PROBLEM 12 + +/* vis defines */ +#define VIS_TYPE_SERVER_SYNC 0 +#define VIS_TYPE_CLIENT_UPDATE 1 + +struct batman_packet { + uint8_t packet_type; + uint8_t version; /* batman version field */ + uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */ + uint8_t tq; + uint16_t seqno; + uint8_t orig[6]; + uint8_t prev_sender[6]; + uint8_t ttl; + uint8_t num_hna; +} __attribute__((packed)); + +#define BAT_PACKET_LEN sizeof(struct batman_packet) + +struct icmp_packet { + uint8_t packet_type; + uint8_t version; /* batman version field */ + uint8_t msg_type; /* see ICMP message types above */ + uint8_t ttl; + uint8_t dst[6]; + uint8_t orig[6]; + uint16_t seqno; + uint8_t uid; +} __attribute__((packed)); + +struct unicast_packet { + uint8_t packet_type; + uint8_t version; /* batman version field */ + uint8_t dest[6]; + uint8_t ttl; +} __attribute__((packed)); + +struct bcast_packet { + uint8_t packet_type; + uint8_t version; /* batman version field */ + uint8_t orig[6]; + uint16_t seqno; +} __attribute__((packed)); + +struct vis_packet { + uint8_t packet_type; + uint8_t version; /* batman version field */ + uint8_t vis_type; /* which type of vis-participant sent this? */ + uint8_t seqno; /* sequence number */ + uint8_t entries; /* number of entries behind this struct */ + uint8_t ttl; /* TTL */ + uint8_t vis_orig[6]; /* originator that informs about its + * neighbours */ + uint8_t target_orig[6]; /* who should receive this packet */ + uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */ +} __attribute__((packed)); diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c new file mode 100644 index 0000000000000000000000000000000000000000..aac3df7f13fba6bc0e78d356440d663eba23d5c1 --- /dev/null +++ b/drivers/staging/batman-adv/proc.c @@ -0,0 +1,950 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "proc.h" +#include "log.h" +#include "routing.h" +#include "translation-table.h" +#include "hard-interface.h" +#include "types.h" +#include "hash.h" +#include "vis.h" +#include "compat.h" + +static uint8_t vis_format = DOT_DRAW; + +static struct proc_dir_entry *proc_batman_dir, *proc_interface_file; +static struct proc_dir_entry *proc_orig_interval_file, *proc_originators_file; +static struct proc_dir_entry *proc_log_file, *proc_log_level_file; +static struct proc_dir_entry *proc_transt_local_file; +static struct proc_dir_entry *proc_transt_global_file; +static struct proc_dir_entry *proc_vis_file, *proc_vis_format_file; +static struct proc_dir_entry *proc_aggr_file; + +static int proc_interfaces_read(struct seq_file *seq, void *offset) +{ + struct batman_if *batman_if; + + rcu_read_lock(); + list_for_each_entry_rcu(batman_if, &if_list, list) { + seq_printf(seq, "[%8s] %s %s \n", + (batman_if->if_active == IF_ACTIVE ? + "active" : "inactive"), + batman_if->dev, + (batman_if->if_active == IF_ACTIVE ? + batman_if->addr_str : " ")); + } + rcu_read_unlock(); + + return 0; +} + +static int proc_interfaces_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_interfaces_read, NULL); +} + +static ssize_t proc_interfaces_write(struct file *instance, + const char __user *userbuffer, + size_t count, loff_t *data) +{ + char *if_string, *colon_ptr = NULL, *cr_ptr = NULL; + int not_copied = 0, if_num = 0; + struct batman_if *batman_if = NULL; + + if_string = kmalloc(count, GFP_KERNEL); + + if (!if_string) + return -ENOMEM; + + if (count > IFNAMSIZ - 1) { + debug_log(LOG_TYPE_WARN, + "Can't add interface: device name is too long\n"); + goto end; + } + + not_copied = copy_from_user(if_string, userbuffer, count); + if_string[count - not_copied - 1] = 0; + + colon_ptr = strchr(if_string, ':'); + if (colon_ptr) + *colon_ptr = 0; + + if (!colon_ptr) { + cr_ptr = strchr(if_string, '\n'); + if (cr_ptr) + *cr_ptr = 0; + } + + if (strlen(if_string) == 0) { + shutdown_module(); + num_ifs = 0; + goto end; + } + + /* add interface */ + rcu_read_lock(); + list_for_each_entry_rcu(batman_if, &if_list, list) { + if (strncmp(batman_if->dev, if_string, count) == 0) { + debug_log(LOG_TYPE_WARN, "Given interface is already active: %s\n", if_string); + rcu_read_unlock(); + goto end; + + } + + if_num++; + } + rcu_read_unlock(); + + hardif_add_interface(if_string, if_num); + + if ((atomic_read(&module_state) == MODULE_INACTIVE) && + (hardif_get_active_if_num() > 0)) + activate_module(); + + rcu_read_lock(); + if (list_empty(&if_list)) { + rcu_read_unlock(); + goto end; + } + rcu_read_unlock(); + + num_ifs = if_num + 1; + return count; + +end: + kfree(if_string); + return count; +} + +static int proc_orig_interval_read(struct seq_file *seq, void *offset) +{ + seq_printf(seq, "%i\n", atomic_read(&originator_interval)); + + return 0; +} + +static ssize_t proc_orig_interval_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *ppos) +{ + char *interval_string; + int not_copied = 0; + unsigned long originator_interval_tmp; + int retval; + + interval_string = kmalloc(count, GFP_KERNEL); + + if (!interval_string) + return -ENOMEM; + + not_copied = copy_from_user(interval_string, buffer, count); + interval_string[count - not_copied - 1] = 0; + + retval = strict_strtoul(interval_string, 10, &originator_interval_tmp); + if (retval) { + debug_log(LOG_TYPE_WARN, "New originator interval invalid\n"); + goto end; + } + + if (originator_interval_tmp <= JITTER * 2) { + debug_log(LOG_TYPE_WARN, + "New originator interval too small: %i (min: %i)\n", + originator_interval_tmp, JITTER * 2); + goto end; + } + + debug_log(LOG_TYPE_NOTICE, + "Changing originator interval from: %i to: %i\n", + atomic_read(&originator_interval), originator_interval_tmp); + + atomic_set(&originator_interval, originator_interval_tmp); + +end: + kfree(interval_string); + return count; +} + +static int proc_orig_interval_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_orig_interval_read, NULL); +} + +static int proc_originators_read(struct seq_file *seq, void *offset) +{ + struct hash_it_t *hashit = NULL; + struct orig_node *orig_node; + struct neigh_node *neigh_node; + int batman_count = 0; + char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN]; + + rcu_read_lock(); + if (list_empty(&if_list)) { + rcu_read_unlock(); + seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n"); + goto end; + } + + if (((struct batman_if *)if_list.next)->if_active != IF_ACTIVE) { + rcu_read_unlock(); + seq_printf(seq, "BATMAN disabled - primary interface not active \n"); + goto end; + } + + seq_printf(seq, + " %-14s (%s/%i) %17s [%10s]: %20s ... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s] \n", + "Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", + "Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR, + ((struct batman_if *)if_list.next)->dev, + ((struct batman_if *)if_list.next)->addr_str); + + rcu_read_unlock(); + spin_lock(&orig_hash_lock); + + while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { + + orig_node = hashit->bucket->data; + + if (!orig_node->router) + continue; + + if (orig_node->router->tq_avg == 0) + continue; + + batman_count++; + + addr_to_string(orig_str, orig_node->orig); + addr_to_string(router_str, orig_node->router->addr); + + seq_printf(seq, "%-17s (%3i) %17s [%10s]:", + orig_str, orig_node->router->tq_avg, + router_str, orig_node->router->if_incoming->dev); + + list_for_each_entry(neigh_node, &orig_node->neigh_list, list) { + addr_to_string(orig_str, neigh_node->addr); + seq_printf(seq, " %17s (%3i)", + orig_str, neigh_node->tq_avg); + } + + seq_printf(seq, "\n"); + + } + + spin_unlock(&orig_hash_lock); + + if (batman_count == 0) + seq_printf(seq, "No batman nodes in range ... \n"); + +end: + return 0; +} + +static int proc_originators_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_originators_read, NULL); +} + +static int proc_log_level_read(struct seq_file *seq, void *offset) +{ + + seq_printf(seq, "[x] %s (%d)\n", LOG_TYPE_CRIT_NAME, LOG_TYPE_CRIT); + seq_printf(seq, "[%c] %s (%d)\n", + (LOG_TYPE_WARN & log_level) ? 'x' : ' ', + LOG_TYPE_WARN_NAME, LOG_TYPE_WARN); + seq_printf(seq, "[%c] %s (%d)\n", + (LOG_TYPE_NOTICE & log_level) ? 'x' : ' ', + LOG_TYPE_NOTICE_NAME, LOG_TYPE_NOTICE); + seq_printf(seq, "[%c] %s (%d)\n", + (LOG_TYPE_BATMAN & log_level) ? 'x' : ' ', + LOG_TYPE_BATMAN_NAME, LOG_TYPE_BATMAN); + seq_printf(seq, "[%c] %s (%d)\n", + (LOG_TYPE_ROUTES & log_level) ? 'x' : ' ', + LOG_TYPE_ROUTES_NAME, LOG_TYPE_ROUTES); + return 0; +} + +static int proc_log_level_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_log_level_read, NULL); +} + +static ssize_t proc_log_level_write(struct file *instance, + const char __user *userbuffer, + size_t count, loff_t *data) +{ + char *log_level_string, *tokptr, *cp; + int finished, not_copied = 0; + unsigned long log_level_tmp = 0; + + log_level_string = kmalloc(count, GFP_KERNEL); + + if (!log_level_string) + return -ENOMEM; + + not_copied = copy_from_user(log_level_string, userbuffer, count); + log_level_string[count - not_copied - 1] = 0; + + if (strict_strtoul(log_level_string, 10, &log_level_tmp) < 0) { + /* was not a number, doing textual parsing */ + log_level_tmp = 0; + tokptr = log_level_string; + + for (cp = log_level_string, finished = 0; !finished; cp++) { + switch (*cp) { + case 0: + finished = 1; + case ' ': + case '\n': + case '\t': + *cp = 0; + /* compare */ + if (strcmp(tokptr, LOG_TYPE_WARN_NAME) == 0) + log_level_tmp |= LOG_TYPE_WARN; + if (strcmp(tokptr, LOG_TYPE_NOTICE_NAME) == 0) + log_level_tmp |= LOG_TYPE_NOTICE; + if (strcmp(tokptr, LOG_TYPE_BATMAN_NAME) == 0) + log_level_tmp |= LOG_TYPE_BATMAN; + if (strcmp(tokptr, LOG_TYPE_ROUTES_NAME) == 0) + log_level_tmp |= LOG_TYPE_ROUTES; + tokptr = cp + 1; + break; + default: + ; + } + } + } + + debug_log(LOG_TYPE_CRIT, "Changing log_level from: %i to: %i\n", + log_level, log_level_tmp); + log_level = log_level_tmp; + + kfree(log_level_string); + return count; +} + +static int proc_transt_local_read(struct seq_file *seq, void *offset) +{ + char *buf; + + buf = kmalloc(4096, GFP_KERNEL); + if (!buf) + return 0; + + rcu_read_lock(); + if (list_empty(&if_list)) { + rcu_read_unlock(); + seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n"); + goto end; + } + + rcu_read_unlock(); + + seq_printf(seq, "Locally retrieved addresses (from %s) announced via HNA:\n", soft_device->name); + + hna_local_fill_buffer_text(buf, 4096); + seq_printf(seq, "%s", buf); + +end: + kfree(buf); + return 0; +} + +static int proc_transt_local_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_transt_local_read, NULL); +} + +static int proc_transt_global_read(struct seq_file *seq, void *offset) +{ + char *buf; + + buf = kmalloc(4096, GFP_KERNEL); + if (!buf) + return 0; + + rcu_read_lock(); + if (list_empty(&if_list)) { + rcu_read_unlock(); + seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n"); + goto end; + } + rcu_read_unlock(); + + + seq_printf(seq, "Globally announced HNAs received via the mesh (translation table):\n"); + + hna_global_fill_buffer_text(buf, 4096); + seq_printf(seq, "%s", buf); + +end: + kfree(buf); + return 0; +} + +static int proc_transt_global_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_transt_global_read, NULL); +} + +/* insert interface to the list of interfaces of one originator */ + +static void proc_vis_insert_interface(const uint8_t *interface, + struct vis_if_list **if_entry, + bool primary) +{ + /* Did we get an empty list? (then insert imediately) */ + if(*if_entry == NULL) { + *if_entry = kmalloc(sizeof(struct vis_if_list), GFP_KERNEL); + if (*if_entry == NULL) + return; + + (*if_entry)->primary = primary; + (*if_entry)->next = NULL; + memcpy((*if_entry)->addr, interface, ETH_ALEN); + } else { + struct vis_if_list *head_if_entry = *if_entry; + /* Do we already have this interface in our list? */ + while (!compare_orig((*if_entry)->addr, (void *)interface)) { + + /* Or did we reach the end (then append the interface) */ + if ((*if_entry)->next == NULL) { + (*if_entry)->next = kmalloc(sizeof(struct vis_if_list), GFP_KERNEL); + if ((*if_entry)->next == NULL) + return; + + memcpy((*if_entry)->next->addr, interface, ETH_ALEN); + (*if_entry)->next->primary = primary; + (*if_entry)->next->next = NULL; + break; + } + *if_entry = (*if_entry)->next; + } + /* Rewind the list to its head */ + *if_entry = head_if_entry; + } +} +/* read an entry */ + +static void proc_vis_read_entry(struct seq_file *seq, + struct vis_info_entry *entry, + struct vis_if_list **if_entry, + uint8_t *vis_orig, + uint8_t current_format, + uint8_t first_line) +{ + char from[40]; + char to[40]; + int int_part, frac_part; + + addr_to_string(to, entry->dest); + if (entry->quality == 0) { +#ifndef VIS_SUBCLUSTERS_DISABLED + proc_vis_insert_interface(vis_orig, if_entry, true); +#endif /* VIS_SUBCLUSTERS_DISABLED */ + addr_to_string(from, vis_orig); + if (current_format == DOT_DRAW) { + seq_printf(seq, "\t\"%s\" -> \"%s\" [label=\"HNA\"]\n", + from, to); + } else { + seq_printf(seq, + "%s\t{ router : \"%s\", gateway : \"%s\", label : \"HNA\" }", + (first_line ? "" : ",\n"), from, to); + } + } else { +#ifndef VIS_SUBCLUSTERS_DISABLED + proc_vis_insert_interface(entry->src, if_entry, compare_orig(entry->src, vis_orig)); +#endif /* VIS_SUBCLUSTERS_DISABLED */ + addr_to_string(from, entry->src); + + /* kernel has no printf-support for %f? it'd be better to return + * this in float. */ + + int_part = TQ_MAX_VALUE / entry->quality; + frac_part = 1000 * TQ_MAX_VALUE / entry->quality - int_part * 1000; + + if (current_format == DOT_DRAW) { + seq_printf(seq, + "\t\"%s\" -> \"%s\" [label=\"%d.%d\"]\n", + from, to, int_part, frac_part); + } else { + seq_printf(seq, + "%s\t{ router : \"%s\", neighbour : \"%s\", label : %d.%d }", + (first_line ? "" : ",\n"), from, to, int_part, frac_part); + } + } +} + + +static int proc_vis_read(struct seq_file *seq, void *offset) +{ + struct hash_it_t *hashit = NULL; + struct vis_info *info; + struct vis_info_entry *entries; + struct vis_if_list *if_entries = NULL; + int i; + uint8_t current_format, first_line = 1; +#ifndef VIS_SUBCLUSTERS_DISABLED + char tmp_addr_str[ETH_STR_LEN]; + struct vis_if_list *tmp_if_next; +#endif /* VIS_SUBCLUSTERS_DISABLED */ + + current_format = vis_format; + + rcu_read_lock(); + if (list_empty(&if_list) || (!is_vis_server())) { + rcu_read_unlock(); + if (current_format == DOT_DRAW) + seq_printf(seq, "digraph {\n}\n"); + goto end; + } + + rcu_read_unlock(); + + if (current_format == DOT_DRAW) + seq_printf(seq, "digraph {\n"); + + spin_lock(&vis_hash_lock); + while (NULL != (hashit = hash_iterate(vis_hash, hashit))) { + info = hashit->bucket->data; + entries = (struct vis_info_entry *) + ((char *)info + sizeof(struct vis_info)); + + for (i = 0; i < info->packet.entries; i++) { + proc_vis_read_entry(seq, &entries[i], &if_entries, + info->packet.vis_orig, + current_format, first_line); + if (first_line) + first_line = 0; + } + +#ifndef VIS_SUBCLUSTERS_DISABLED + /* Generate subgraphs from the collected items */ + if (current_format == DOT_DRAW) { + + addr_to_string(tmp_addr_str, info->packet.vis_orig); + seq_printf(seq, "\tsubgraph \"cluster_%s\" {\n", tmp_addr_str); + while (if_entries != NULL) { + + addr_to_string(tmp_addr_str, if_entries->addr); + if (if_entries->primary) + seq_printf(seq, "\t\t\"%s\" [peripheries=2]\n", tmp_addr_str); + else + seq_printf(seq, "\t\t\"%s\"\n", tmp_addr_str); + + /* ... and empty the list while doing this */ + tmp_if_next = if_entries->next; + kfree(if_entries); + if_entries = tmp_if_next; + } + seq_printf(seq, "\t}\n"); + } +#endif /* VIS_SUBCLUSTERS_DISABLED */ + } + spin_unlock(&vis_hash_lock); + + if (current_format == DOT_DRAW) + seq_printf(seq, "}\n"); + else + seq_printf(seq, "\n"); +end: + return 0; +} + +/* setting the mode of the vis server by the user */ +static ssize_t proc_vis_write(struct file *file, const char __user * buffer, + size_t count, loff_t *ppos) +{ + char *vis_mode_string; + int not_copied = 0; + + vis_mode_string = kmalloc(count, GFP_KERNEL); + + if (!vis_mode_string) + return -ENOMEM; + + not_copied = copy_from_user(vis_mode_string, buffer, count); + vis_mode_string[count - not_copied - 1] = 0; + + if (strcmp(vis_mode_string, "client") == 0) { + debug_log(LOG_TYPE_NOTICE, "Setting VIS mode to client\n"); + vis_set_mode(VIS_TYPE_CLIENT_UPDATE); + } else if (strcmp(vis_mode_string, "server") == 0) { + debug_log(LOG_TYPE_NOTICE, "Setting VIS mode to server\n"); + vis_set_mode(VIS_TYPE_SERVER_SYNC); + } else + debug_log(LOG_TYPE_WARN, "Unknown VIS mode: %s\n", + vis_mode_string); + + kfree(vis_mode_string); + return count; +} + +static int proc_vis_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_vis_read, NULL); +} + +static int proc_vis_format_read(struct seq_file *seq, void *offset) +{ + uint8_t current_format = vis_format; + + seq_printf(seq, "[%c] %s\n", + (current_format == DOT_DRAW) ? 'x' : ' ', + VIS_FORMAT_DD_NAME); + seq_printf(seq, "[%c] %s\n", + (current_format == JSON) ? 'x' : ' ', + VIS_FORMAT_JSON_NAME); + return 0; +} + +static int proc_vis_format_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_vis_format_read, NULL); +} + +static ssize_t proc_vis_format_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *ppos) +{ + char *vis_format_string; + int not_copied = 0; + + vis_format_string = kmalloc(count, GFP_KERNEL); + + if (!vis_format_string) + return -ENOMEM; + + not_copied = copy_from_user(vis_format_string, buffer, count); + vis_format_string[count - not_copied - 1] = 0; + + if (strcmp(vis_format_string, VIS_FORMAT_DD_NAME) == 0) { + debug_log(LOG_TYPE_NOTICE, "Setting VIS output format to: %s\n", + VIS_FORMAT_DD_NAME); + vis_format = DOT_DRAW; + } else if (strcmp(vis_format_string, VIS_FORMAT_JSON_NAME) == 0) { + debug_log(LOG_TYPE_NOTICE, "Setting VIS output format to: %s\n", + VIS_FORMAT_JSON_NAME); + vis_format = JSON; + } else + debug_log(LOG_TYPE_WARN, "Unknown VIS output format: %s\n", + vis_format_string); + + kfree(vis_format_string); + return count; +} + +static int proc_aggr_read(struct seq_file *seq, void *offset) +{ + seq_printf(seq, "%i\n", atomic_read(&aggregation_enabled)); + + return 0; +} + +static ssize_t proc_aggr_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ + char *aggr_string; + int not_copied = 0; + unsigned long aggregation_enabled_tmp; + + aggr_string = kmalloc(count, GFP_KERNEL); + + if (!aggr_string) + return -ENOMEM; + + not_copied = copy_from_user(aggr_string, buffer, count); + aggr_string[count - not_copied - 1] = 0; + + strict_strtoul(aggr_string, 10, &aggregation_enabled_tmp); + + if ((aggregation_enabled_tmp != 0) && (aggregation_enabled_tmp != 1)) { + debug_log(LOG_TYPE_WARN, "Aggregation can only be enabled (1) or disabled (0), given value: %li\n", aggregation_enabled_tmp); + goto end; + } + + debug_log(LOG_TYPE_NOTICE, "Changing aggregation from: %s (%i) to: %s (%li)\n", + (atomic_read(&aggregation_enabled) == 1 ? + "enabled" : "disabled"), + atomic_read(&aggregation_enabled), + (aggregation_enabled_tmp == 1 ? "enabled" : "disabled"), + aggregation_enabled_tmp); + + atomic_set(&aggregation_enabled, (unsigned)aggregation_enabled_tmp); +end: + kfree(aggr_string); + return count; +} + +static int proc_aggr_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_aggr_read, NULL); +} + +/* satisfying different prototypes ... */ +static ssize_t proc_dummy_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ + return count; +} + +static const struct file_operations proc_aggr_fops = { + .owner = THIS_MODULE, + .open = proc_aggr_open, + .read = seq_read, + .write = proc_aggr_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_vis_format_fops = { + .owner = THIS_MODULE, + .open = proc_vis_format_open, + .read = seq_read, + .write = proc_vis_format_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_vis_fops = { + .owner = THIS_MODULE, + .open = proc_vis_open, + .read = seq_read, + .write = proc_vis_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_originators_fops = { + .owner = THIS_MODULE, + .open = proc_originators_open, + .read = seq_read, + .write = proc_dummy_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_transt_local_fops = { + .owner = THIS_MODULE, + .open = proc_transt_local_open, + .read = seq_read, + .write = proc_dummy_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_transt_global_fops = { + .owner = THIS_MODULE, + .open = proc_transt_global_open, + .read = seq_read, + .write = proc_dummy_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_log_level_fops = { + .owner = THIS_MODULE, + .open = proc_log_level_open, + .read = seq_read, + .write = proc_log_level_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_interfaces_fops = { + .owner = THIS_MODULE, + .open = proc_interfaces_open, + .read = seq_read, + .write = proc_interfaces_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_orig_interval_fops = { + .owner = THIS_MODULE, + .open = proc_orig_interval_open, + .read = seq_read, + .write = proc_orig_interval_write, + .llseek = seq_lseek, + .release = single_release, +}; + +void cleanup_procfs(void) +{ + if (proc_transt_global_file) + remove_proc_entry(PROC_FILE_TRANST_GLOBAL, proc_batman_dir); + + if (proc_transt_local_file) + remove_proc_entry(PROC_FILE_TRANST_LOCAL, proc_batman_dir); + + if (proc_log_file) + remove_proc_entry(PROC_FILE_LOG, proc_batman_dir); + + if (proc_log_level_file) + remove_proc_entry(PROC_FILE_LOG_LEVEL, proc_batman_dir); + + if (proc_originators_file) + remove_proc_entry(PROC_FILE_ORIGINATORS, proc_batman_dir); + + if (proc_orig_interval_file) + remove_proc_entry(PROC_FILE_ORIG_INTERVAL, proc_batman_dir); + + if (proc_interface_file) + remove_proc_entry(PROC_FILE_INTERFACES, proc_batman_dir); + + if (proc_vis_file) + remove_proc_entry(PROC_FILE_VIS, proc_batman_dir); + + if (proc_vis_format_file) + remove_proc_entry(PROC_FILE_VIS_FORMAT, proc_batman_dir); + + if (proc_aggr_file) + remove_proc_entry(PROC_FILE_AGGR, proc_batman_dir); + + if (proc_batman_dir) +#ifdef __NET_NET_NAMESPACE_H + remove_proc_entry(PROC_ROOT_DIR, init_net.proc_net); +#else + remove_proc_entry(PROC_ROOT_DIR, proc_net); +#endif +} + +int setup_procfs(void) +{ +#ifdef __NET_NET_NAMESPACE_H + proc_batman_dir = proc_mkdir(PROC_ROOT_DIR, init_net.proc_net); +#else + proc_batman_dir = proc_mkdir(PROC_ROOT_DIR, proc_net); +#endif + + if (!proc_batman_dir) { + printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s' folder failed\n", PROC_ROOT_DIR); + return -EFAULT; + } + + proc_interface_file = create_proc_entry(PROC_FILE_INTERFACES, + S_IWUSR | S_IRUGO, + proc_batman_dir); + if (proc_interface_file) { + proc_interface_file->proc_fops = &proc_interfaces_fops; + } else { + printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_INTERFACES); + cleanup_procfs(); + return -EFAULT; + } + + proc_orig_interval_file = create_proc_entry(PROC_FILE_ORIG_INTERVAL, + S_IWUSR | S_IRUGO, + proc_batman_dir); + if (proc_orig_interval_file) { + proc_orig_interval_file->proc_fops = &proc_orig_interval_fops; + } else { + printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_ORIG_INTERVAL); + cleanup_procfs(); + return -EFAULT; + } + + proc_log_level_file = create_proc_entry(PROC_FILE_LOG_LEVEL, + S_IWUSR | S_IRUGO, + proc_batman_dir); + if (proc_log_level_file) { + proc_log_level_file->proc_fops = &proc_log_level_fops; + } else { + printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_LOG_LEVEL); + cleanup_procfs(); + return -EFAULT; + } + + proc_originators_file = create_proc_entry(PROC_FILE_ORIGINATORS, + S_IRUGO, proc_batman_dir); + if (proc_originators_file) { + proc_originators_file->proc_fops = &proc_originators_fops; + } else { + printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_ORIGINATORS); + cleanup_procfs(); + return -EFAULT; + } + + proc_log_file = create_proc_entry(PROC_FILE_LOG, + S_IRUGO, proc_batman_dir); + if (proc_log_file) { + proc_log_file->proc_fops = &proc_log_operations; + } else { + printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_FILE_LOG, PROC_FILE_GATEWAYS); + cleanup_procfs(); + return -EFAULT; + } + + proc_transt_local_file = create_proc_entry(PROC_FILE_TRANST_LOCAL, + S_IRUGO, proc_batman_dir); + if (proc_transt_local_file) { + proc_transt_local_file->proc_fops = &proc_transt_local_fops; + } else { + printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_TRANST_LOCAL); + cleanup_procfs(); + return -EFAULT; + } + + proc_transt_global_file = create_proc_entry(PROC_FILE_TRANST_GLOBAL, + S_IRUGO, proc_batman_dir); + if (proc_transt_global_file) { + proc_transt_global_file->proc_fops = &proc_transt_global_fops; + } else { + printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_TRANST_GLOBAL); + cleanup_procfs(); + return -EFAULT; + } + + proc_vis_file = create_proc_entry(PROC_FILE_VIS, S_IWUSR | S_IRUGO, + proc_batman_dir); + if (proc_vis_file) { + proc_vis_file->proc_fops = &proc_vis_fops; + } else { + printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS); + cleanup_procfs(); + return -EFAULT; + } + + proc_vis_format_file = create_proc_entry(PROC_FILE_VIS_FORMAT, + S_IWUSR | S_IRUGO, + proc_batman_dir); + if (proc_vis_format_file) { + proc_vis_format_file->proc_fops = &proc_vis_format_fops; + } else { + printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_FORMAT); + cleanup_procfs(); + return -EFAULT; + } + + proc_aggr_file = create_proc_entry(PROC_FILE_AGGR, S_IWUSR | S_IRUGO, + proc_batman_dir); + if (proc_aggr_file) { + proc_aggr_file->proc_fops = &proc_aggr_fops; + } else { + printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_AGGR); + cleanup_procfs(); + return -EFAULT; + } + + return 0; +} + + diff --git a/drivers/staging/batman-adv/proc.h b/drivers/staging/batman-adv/proc.h new file mode 100644 index 0000000000000000000000000000000000000000..16d3efdebe52e34500475c4082bb7d2930b037c8 --- /dev/null +++ b/drivers/staging/batman-adv/proc.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include +#include + +#define PROC_ROOT_DIR "batman-adv" +#define PROC_FILE_INTERFACES "interfaces" +#define PROC_FILE_ORIG_INTERVAL "orig_interval" +#define PROC_FILE_ORIGINATORS "originators" +#define PROC_FILE_GATEWAYS "gateways" +#define PROC_FILE_LOG "log" +#define PROC_FILE_LOG_LEVEL "log_level" +#define PROC_FILE_TRANST_LOCAL "transtable_local" +#define PROC_FILE_TRANST_GLOBAL "transtable_global" +#define PROC_FILE_VIS "vis" +#define PROC_FILE_VIS_FORMAT "vis_format" +#define PROC_FILE_AGGR "aggregate_ogm" + +void cleanup_procfs(void); +int setup_procfs(void); + +/* While scanning for vis-entries of a particular vis-originator + * this list collects its interfaces to create a subgraph/cluster + * out of them later + */ +struct vis_if_list { + uint8_t addr[ETH_ALEN]; + bool primary; + struct vis_if_list *next; +}; diff --git a/drivers/staging/batman-adv/ring_buffer.c b/drivers/staging/batman-adv/ring_buffer.c new file mode 100644 index 0000000000000000000000000000000000000000..751c899f54c5e9365aafc1c886e7cee05c7668c4 --- /dev/null +++ b/drivers/staging/batman-adv/ring_buffer.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "ring_buffer.h" + +void ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, uint8_t value) +{ + lq_recv[*lq_index] = value; + *lq_index = (*lq_index + 1) % TQ_GLOBAL_WINDOW_SIZE; +} + +uint8_t ring_buffer_avg(uint8_t lq_recv[]) +{ + uint8_t *ptr; + uint16_t count = 0, i = 0, sum = 0; + + ptr = lq_recv; + + while (i < TQ_GLOBAL_WINDOW_SIZE) { + if (*ptr != 0) { + count++; + sum += *ptr; + } + + i++; + ptr++; + } + + if (count == 0) + return 0; + + return (uint8_t)(sum / count); +} diff --git a/drivers/staging/batman-adv/ring_buffer.h b/drivers/staging/batman-adv/ring_buffer.h new file mode 100644 index 0000000000000000000000000000000000000000..6839ba97eeb33175329f862296896599137c168c --- /dev/null +++ b/drivers/staging/batman-adv/ring_buffer.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +void ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, uint8_t value); +uint8_t ring_buffer_avg(uint8_t lq_recv[]); diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c new file mode 100644 index 0000000000000000000000000000000000000000..4a14c363ac2bfb3f7f9f9b4913f39c8593da50b5 --- /dev/null +++ b/drivers/staging/batman-adv/routing.c @@ -0,0 +1,1010 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + + + + + +#include "main.h" +#include "routing.h" +#include "log.h" +#include "send.h" +#include "soft-interface.h" +#include "hard-interface.h" +#include "device.h" +#include "translation-table.h" +#include "types.h" +#include "hash.h" +#include "ring_buffer.h" +#include "vis.h" +#include "aggregation.h" +#include "compat.h" + + + +DECLARE_WAIT_QUEUE_HEAD(thread_wait); +static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig); + +static atomic_t data_ready_cond; +atomic_t exit_cond; + +static void start_purge_timer(void) +{ + queue_delayed_work(bat_event_workqueue, &purge_orig_wq, 1 * HZ); +} + +int originator_init(void) +{ + if (orig_hash) + return 1; + + spin_lock(&orig_hash_lock); + orig_hash = hash_new(128, compare_orig, choose_orig); + + if (!orig_hash) + goto err; + + spin_unlock(&orig_hash_lock); + start_purge_timer(); + return 1; + +err: + spin_unlock(&orig_hash_lock); + return 0; +} + +void originator_free(void) +{ + if (!orig_hash) + return; + + cancel_delayed_work_sync(&purge_orig_wq); + + spin_lock(&orig_hash_lock); + hash_delete(orig_hash, free_orig_node); + orig_hash = NULL; + spin_unlock(&orig_hash_lock); +} + +static struct neigh_node *create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, uint8_t *neigh, struct batman_if *if_incoming) +{ + struct neigh_node *neigh_node; + + debug_log(LOG_TYPE_BATMAN, "Creating new last-hop neighbour of originator\n"); + + neigh_node = kmalloc(sizeof(struct neigh_node), GFP_ATOMIC); + memset(neigh_node, 0, sizeof(struct neigh_node)); + INIT_LIST_HEAD(&neigh_node->list); + + memcpy(neigh_node->addr, neigh, ETH_ALEN); + neigh_node->orig_node = orig_neigh_node; + neigh_node->if_incoming = if_incoming; + + list_add_tail(&neigh_node->list, &orig_node->neigh_list); + return neigh_node; +} + +void free_orig_node(void *data) +{ + struct list_head *list_pos, *list_pos_tmp; + struct neigh_node *neigh_node; + struct orig_node *orig_node = (struct orig_node *)data; + + /* for all neighbours towards this originator ... */ + list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) { + neigh_node = list_entry(list_pos, struct neigh_node, list); + + list_del(list_pos); + kfree(neigh_node); + } + + hna_global_del_orig(orig_node, "originator timed out"); + + kfree(orig_node->bcast_own); + kfree(orig_node->bcast_own_sum); + kfree(orig_node); +} + +/* this function finds or creates an originator entry for the given address if it does not exits */ +static struct orig_node *get_orig_node(uint8_t *addr) +{ + struct orig_node *orig_node; + struct hashtable_t *swaphash; + char orig_str[ETH_STR_LEN]; + + orig_node = ((struct orig_node *)hash_find(orig_hash, addr)); + + if (orig_node != NULL) + return orig_node; + + addr_to_string(orig_str, addr); + debug_log(LOG_TYPE_BATMAN, "Creating new originator: %s \n", orig_str); + + orig_node = kmalloc(sizeof(struct orig_node), GFP_ATOMIC); + memset(orig_node, 0, sizeof(struct orig_node)); + INIT_LIST_HEAD(&orig_node->neigh_list); + + memcpy(orig_node->orig, addr, ETH_ALEN); + orig_node->router = NULL; + orig_node->batman_if = NULL; + orig_node->hna_buff = NULL; + + orig_node->bcast_own = kmalloc(num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS, GFP_ATOMIC); + memset(orig_node->bcast_own, 0, num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS); + + orig_node->bcast_own_sum = kmalloc(num_ifs * sizeof(uint8_t), GFP_ATOMIC); + memset(orig_node->bcast_own_sum, 0, num_ifs * sizeof(uint8_t)); + + hash_add(orig_hash, orig_node); + + if (orig_hash->elements * 4 > orig_hash->size) { + swaphash = hash_resize(orig_hash, orig_hash->size * 2); + + if (swaphash == NULL) + debug_log(LOG_TYPE_CRIT, "Couldn't resize orig hash table \n"); + else + orig_hash = swaphash; + } + + return orig_node; +} + +void slide_own_bcast_window(struct batman_if *batman_if) +{ + struct hash_it_t *hashit = NULL; + struct orig_node *orig_node; + + spin_lock(&orig_hash_lock); + + while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { + orig_node = hashit->bucket->data; + + bit_get_packet((TYPE_OF_WORD *)&(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]), 1, 0); + orig_node->bcast_own_sum[batman_if->if_num] = bit_packet_count((TYPE_OF_WORD *)&(orig_node->bcast_own[batman_if->if_num * NUM_WORDS])); + } + + spin_unlock(&orig_hash_lock); +} + +static void update_routes(struct orig_node *orig_node, struct neigh_node *neigh_node, unsigned char *hna_buff, int hna_buff_len) +{ + char orig_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN], router_str[ETH_STR_LEN]; + + if (orig_node == NULL) + return; + + if (orig_node->router != neigh_node) { + addr_to_string(orig_str, orig_node->orig); + + /* route deleted */ + if ((orig_node->router != NULL) && (neigh_node == NULL)) { + + debug_log(LOG_TYPE_ROUTES, "Deleting route towards: %s\n", orig_str); + hna_global_del_orig(orig_node, "originator timed out"); + + /* route added */ + } else if ((orig_node->router == NULL) && (neigh_node != NULL)) { + + addr_to_string(neigh_str, neigh_node->addr); + debug_log(LOG_TYPE_ROUTES, "Adding route towards: %s (via %s)\n", orig_str, neigh_str); + hna_global_add_orig(orig_node, hna_buff, hna_buff_len); + + /* route changed */ + } else { + + addr_to_string(neigh_str, neigh_node->addr); + addr_to_string(router_str, orig_node->router->addr); + debug_log(LOG_TYPE_ROUTES, "Changing route towards: %s (now via %s - was via %s)\n", orig_str, neigh_str, router_str); + + } + + if (neigh_node != NULL) + orig_node->batman_if = neigh_node->if_incoming; + else + orig_node->batman_if = NULL; + + orig_node->router = neigh_node; + + /* may be just HNA changed */ + } else { + + if ((hna_buff_len != orig_node->hna_buff_len) || ((hna_buff_len > 0) && (orig_node->hna_buff_len > 0) && (memcmp(orig_node->hna_buff, hna_buff, hna_buff_len) != 0))) { + + if (orig_node->hna_buff_len > 0) + hna_global_del_orig(orig_node, "originator changed hna"); + + if ((hna_buff_len > 0) && (hna_buff != NULL)) + hna_global_add_orig(orig_node, hna_buff, hna_buff_len); + + } + + } +} + +static int isBidirectionalNeigh(struct orig_node *orig_node, struct orig_node *orig_neigh_node, struct batman_packet *batman_packet, struct batman_if *if_incoming) +{ + struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; + char orig_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN]; + unsigned char total_count; + + addr_to_string(orig_str, orig_node->orig); + addr_to_string(neigh_str, orig_neigh_node->orig); + + if (orig_node == orig_neigh_node) { + list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) { + + if (compare_orig(tmp_neigh_node->addr, orig_neigh_node->orig) && (tmp_neigh_node->if_incoming == if_incoming)) + neigh_node = tmp_neigh_node; + } + + if (neigh_node == NULL) + neigh_node = create_neighbor(orig_node, orig_neigh_node, orig_neigh_node->orig, if_incoming); + + neigh_node->last_valid = jiffies; + } else { + /* find packet count of corresponding one hop neighbor */ + list_for_each_entry(tmp_neigh_node, &orig_neigh_node->neigh_list, list) { + + if (compare_orig(tmp_neigh_node->addr, orig_neigh_node->orig) && (tmp_neigh_node->if_incoming == if_incoming)) + neigh_node = tmp_neigh_node; + } + + if (neigh_node == NULL) + neigh_node = create_neighbor(orig_neigh_node, orig_neigh_node, orig_neigh_node->orig, if_incoming); + } + + orig_node->last_valid = jiffies; + + /* pay attention to not get a value bigger than 100 % */ + total_count = (orig_neigh_node->bcast_own_sum[if_incoming->if_num] > neigh_node->real_packet_count ? neigh_node->real_packet_count : orig_neigh_node->bcast_own_sum[if_incoming->if_num]); + + /* if we have too few packets (too less data) we set tq_own to zero */ + /* if we receive too few packets it is not considered bidirectional */ + if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) || (neigh_node->real_packet_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM)) + orig_neigh_node->tq_own = 0; + else + /* neigh_node->real_packet_count is never zero as we only purge old information when getting new information */ + orig_neigh_node->tq_own = (TQ_MAX_VALUE * total_count) / neigh_node->real_packet_count; + + /* + * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE + * this does affect the nearly-symmetric links only a little, + * but punishes asymmetric links more. + * this will give a value between 0 and TQ_MAX_VALUE + */ + orig_neigh_node->tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE * + (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) * + (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) * + (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count)) / + (TQ_LOCAL_WINDOW_SIZE * TQ_LOCAL_WINDOW_SIZE * TQ_LOCAL_WINDOW_SIZE); + + batman_packet->tq = ((batman_packet->tq * orig_neigh_node->tq_own * orig_neigh_node->tq_asym_penalty) / (TQ_MAX_VALUE * TQ_MAX_VALUE)); + + debug_log(LOG_TYPE_BATMAN, "bidirectional: orig = %-15s neigh = %-15s => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, total tq: %3i \n", + orig_str, neigh_str, total_count, neigh_node->real_packet_count, orig_neigh_node->tq_own, orig_neigh_node->tq_asym_penalty, batman_packet->tq); + + /* if link has the minimum required transmission quality consider it bidirectional */ + if (batman_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT) + return 1; + + return 0; +} + +static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr, struct batman_packet *batman_packet, struct batman_if *if_incoming, unsigned char *hna_buff, int hna_buff_len, char is_duplicate) +{ + struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; + int tmp_hna_buff_len; + + debug_log(LOG_TYPE_BATMAN, "update_originator(): Searching and updating originator entry of received packet \n"); + + list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) { + if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) && (tmp_neigh_node->if_incoming == if_incoming)) { + neigh_node = tmp_neigh_node; + continue; + } + + if (is_duplicate) + continue; + + ring_buffer_set(tmp_neigh_node->tq_recv, &tmp_neigh_node->tq_index, 0); + tmp_neigh_node->tq_avg = ring_buffer_avg(tmp_neigh_node->tq_recv); + } + + if (neigh_node == NULL) + neigh_node = create_neighbor(orig_node, get_orig_node(ethhdr->h_source), ethhdr->h_source, if_incoming); + else + debug_log(LOG_TYPE_BATMAN, "Updating existing last-hop neighbour of originator\n"); + + orig_node->flags = batman_packet->flags; + neigh_node->last_valid = jiffies; + + ring_buffer_set(neigh_node->tq_recv, &neigh_node->tq_index, batman_packet->tq); + neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv); + + if (!is_duplicate) { + orig_node->last_ttl = batman_packet->ttl; + neigh_node->last_ttl = batman_packet->ttl; + } + + tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ? batman_packet->num_hna * ETH_ALEN : hna_buff_len); + + /* if this neighbor already is our next hop there is nothing to change */ + if (orig_node->router == neigh_node) + goto update_hna; + + /* if this neighbor does not offer a better TQ we won't consider it */ + if ((orig_node->router) && + (orig_node->router->tq_avg > neigh_node->tq_avg)) + goto update_hna; + + /* if the TQ is the same and the link not more symetric we won't consider it either */ + if ((orig_node->router) && + ((neigh_node->tq_avg == orig_node->router->tq_avg) && + (orig_node->router->orig_node->bcast_own_sum[if_incoming->if_num] >= + neigh_node->orig_node->bcast_own_sum[if_incoming->if_num]))) + goto update_hna; + + update_routes(orig_node, neigh_node, hna_buff, tmp_hna_buff_len); + return; + +update_hna: + update_routes(orig_node, orig_node->router, hna_buff, tmp_hna_buff_len); + return; +} + +static char count_real_packets(struct ethhdr *ethhdr, struct batman_packet *batman_packet, struct batman_if *if_incoming) +{ + struct orig_node *orig_node; + struct neigh_node *tmp_neigh_node; + char is_duplicate = 0; + + + orig_node = get_orig_node(batman_packet->orig); + if (orig_node == NULL) + return 0; + + + list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) { + + if (!is_duplicate) + is_duplicate = get_bit_status(tmp_neigh_node->real_bits, orig_node->last_real_seqno, batman_packet->seqno); + + if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) && (tmp_neigh_node->if_incoming == if_incoming)) + bit_get_packet(tmp_neigh_node->real_bits, batman_packet->seqno - orig_node->last_real_seqno, 1); + else + bit_get_packet(tmp_neigh_node->real_bits, batman_packet->seqno - orig_node->last_real_seqno, 0); + + tmp_neigh_node->real_packet_count = bit_packet_count(tmp_neigh_node->real_bits); + } + + if (!is_duplicate) { + debug_log(LOG_TYPE_BATMAN, "updating last_seqno: old %d, new %d \n", orig_node->last_real_seqno, batman_packet->seqno); + orig_node->last_real_seqno = batman_packet->seqno; + } + + return is_duplicate; +} + +void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, unsigned char *hna_buff, int hna_buff_len, struct batman_if *if_incoming) +{ + struct batman_if *batman_if; + struct orig_node *orig_neigh_node, *orig_node; + char orig_str[ETH_STR_LEN], prev_sender_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN]; + char has_directlink_flag; + char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0, is_broadcast = 0, is_bidirectional, is_single_hop_neigh, is_duplicate; + unsigned short if_incoming_seqno; + + /* Silently drop when the batman packet is actually not a correct packet. + * + * This might happen if a packet is padded (e.g. Ethernet has a + * minimum frame length of 64 byte) and the aggregation interprets + * it as an additional length. + * + * TODO: A more sane solution would be to have a bit in the batman_packet + * to detect whether the packet is the last packet in an aggregation. + * Here we expect that the padding is always zero (or not 0x01) + */ + if (batman_packet->packet_type != BAT_PACKET) + return; + + /* could be changed by schedule_own_packet() */ + if_incoming_seqno = atomic_read(&if_incoming->seqno); + + addr_to_string(orig_str, batman_packet->orig); + addr_to_string(prev_sender_str, batman_packet->prev_sender); + addr_to_string(neigh_str, ethhdr->h_source); + + has_directlink_flag = (batman_packet->flags & DIRECTLINK ? 1 : 0); + + is_single_hop_neigh = (compare_orig(ethhdr->h_source, batman_packet->orig) ? 1 : 0); + + debug_log(LOG_TYPE_BATMAN, "Received BATMAN packet via NB: %s, IF: %s [%s] (from OG: %s, via prev OG: %s, seqno %d, tq %d, TTL %d, V %d, IDF %d) \n", neigh_str, if_incoming->dev, if_incoming->addr_str, orig_str, prev_sender_str, batman_packet->seqno, batman_packet->tq, batman_packet->ttl, batman_packet->version, has_directlink_flag); + + list_for_each_entry_rcu(batman_if, &if_list, list) { + if (batman_if->if_active != IF_ACTIVE) + continue; + + if (compare_orig(ethhdr->h_source, batman_if->net_dev->dev_addr)) + is_my_addr = 1; + + if (compare_orig(batman_packet->orig, batman_if->net_dev->dev_addr)) + is_my_orig = 1; + + if (compare_orig(batman_packet->prev_sender, batman_if->net_dev->dev_addr)) + is_my_oldorig = 1; + + if (compare_orig(ethhdr->h_source, broadcastAddr)) + is_broadcast = 1; + } + + if (batman_packet->version != COMPAT_VERSION) { + debug_log(LOG_TYPE_BATMAN, "Drop packet: incompatible batman version (%i) \n", batman_packet->version); + return; + } + + if (is_my_addr) { + debug_log(LOG_TYPE_BATMAN, "Drop packet: received my own broadcast (sender: %s) \n", neigh_str); + return; + } + + if (is_broadcast) { + debug_log(LOG_TYPE_BATMAN, "Drop packet: ignoring all packets with broadcast source addr (sender: %s) \n", neigh_str); + return; + } + + if (is_my_orig) { + orig_neigh_node = get_orig_node(ethhdr->h_source); + + /* neighbour has to indicate direct link and it has to come via the corresponding interface */ + /* if received seqno equals last send seqno save new seqno for bidirectional check */ + if (has_directlink_flag && compare_orig(if_incoming->net_dev->dev_addr, batman_packet->orig) && + (batman_packet->seqno - if_incoming_seqno + 2 == 0)) { + bit_mark((TYPE_OF_WORD *)&(orig_neigh_node->bcast_own[if_incoming->if_num * NUM_WORDS]), 0); + orig_neigh_node->bcast_own_sum[if_incoming->if_num] = bit_packet_count((TYPE_OF_WORD *)&(orig_neigh_node->bcast_own[if_incoming->if_num * NUM_WORDS])); + } + + debug_log(LOG_TYPE_BATMAN, "Drop packet: originator packet from myself (via neighbour) \n"); + return; + } + + if (batman_packet->tq == 0) { + count_real_packets(ethhdr, batman_packet, if_incoming); + + debug_log(LOG_TYPE_BATMAN, "Drop packet: originator packet with tq equal 0 \n"); + return; + } + + if (is_my_oldorig) { + debug_log(LOG_TYPE_BATMAN, "Drop packet: ignoring all rebroadcast echos (sender: %s) \n", neigh_str); + return; + } + + is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming); + + orig_node = get_orig_node(batman_packet->orig); + if (orig_node == NULL) + return; + + /* avoid temporary routing loops */ + if ((orig_node->router) && (orig_node->router->orig_node->router) && + (compare_orig(orig_node->router->addr, batman_packet->prev_sender)) && + !(compare_orig(batman_packet->orig, batman_packet->prev_sender)) && + (compare_orig(orig_node->router->addr, orig_node->router->orig_node->router->addr))) { + debug_log(LOG_TYPE_BATMAN, "Drop packet: ignoring all rebroadcast packets that may make me loop (sender: %s) \n", neigh_str); + return; + } + + /* if sender is a direct neighbor the sender mac equals originator mac */ + orig_neigh_node = (is_single_hop_neigh ? orig_node : get_orig_node(ethhdr->h_source)); + if (orig_neigh_node == NULL) + return; + + /* drop packet if sender is not a direct neighbor and if we don't route towards it */ + if (!is_single_hop_neigh && (orig_neigh_node->router == NULL)) { + debug_log(LOG_TYPE_BATMAN, "Drop packet: OGM via unknown neighbor! \n"); + return; + } + + is_bidirectional = isBidirectionalNeigh(orig_node, orig_neigh_node, batman_packet, if_incoming); + + /* update ranking if it is not a duplicate or has the same seqno and similar ttl as the non-duplicate */ + if (is_bidirectional && (!is_duplicate || + ((orig_node->last_real_seqno == batman_packet->seqno) && + (orig_node->last_ttl - 3 <= batman_packet->ttl)))) + update_orig(orig_node, ethhdr, batman_packet, if_incoming, hna_buff, hna_buff_len, is_duplicate); + + /* is single hop (direct) neighbour */ + if (is_single_hop_neigh) { + + /* mark direct link on incoming interface */ + schedule_forward_packet(orig_node, ethhdr, batman_packet, 1, hna_buff_len, if_incoming); + + debug_log(LOG_TYPE_BATMAN, "Forwarding packet: rebroadcast neighbour packet with direct link flag \n"); + return; + } + + /* multihop originator */ + if (!is_bidirectional) { + debug_log(LOG_TYPE_BATMAN, "Drop packet: not received via bidirectional link\n"); + return; + } + + if (is_duplicate) { + debug_log(LOG_TYPE_BATMAN, "Drop packet: duplicate packet received\n"); + return; + } + + debug_log(LOG_TYPE_BATMAN, "Forwarding packet: rebroadcast originator packet \n"); + schedule_forward_packet(orig_node, ethhdr, batman_packet, 0, hna_buff_len, if_incoming); +} + +void purge_orig(struct work_struct *work) +{ + struct list_head *list_pos, *list_pos_tmp; + struct hash_it_t *hashit = NULL; + struct orig_node *orig_node; + struct neigh_node *neigh_node, *best_neigh_node; + char orig_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN], neigh_purged; + + spin_lock(&orig_hash_lock); + + /* for all origins... */ + while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { + + orig_node = hashit->bucket->data; + addr_to_string(orig_str, orig_node->orig); + + if (time_after(jiffies, orig_node->last_valid + ((2 * PURGE_TIMEOUT * HZ) / 1000))) { + + debug_log(LOG_TYPE_BATMAN, "Originator timeout: originator %s, last_valid %u \n", orig_str, (orig_node->last_valid / HZ)); + + hash_remove_bucket(orig_hash, hashit); + free_orig_node(orig_node); + + } else { + + best_neigh_node = NULL; + neigh_purged = 0; + + /* for all neighbours towards this originator ... */ + list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) { + neigh_node = list_entry(list_pos, struct neigh_node, list); + + if (time_after(jiffies, neigh_node->last_valid + ((PURGE_TIMEOUT * HZ) / 1000))) { + + addr_to_string(neigh_str, neigh_node->addr); + debug_log(LOG_TYPE_BATMAN, "Neighbour timeout: originator %s, neighbour: %s, last_valid %u \n", orig_str, neigh_str, (neigh_node->last_valid / HZ)); + + neigh_purged = 1; + list_del(list_pos); + kfree(neigh_node); + + } else { + + if ((best_neigh_node == NULL) || (neigh_node->tq_avg > best_neigh_node->tq_avg)) + best_neigh_node = neigh_node; + + } + + } + + if (neigh_purged) + update_routes(orig_node, best_neigh_node, orig_node->hna_buff, orig_node->hna_buff_len); + + } + + } + + spin_unlock(&orig_hash_lock); + + start_purge_timer(); +} + +static int receive_raw_packet(struct socket *raw_sock, unsigned char *packet_buff, int packet_buff_len) +{ + struct kvec iov; + struct msghdr msg; + + iov.iov_base = packet_buff; + iov.iov_len = packet_buff_len; + + msg.msg_flags = MSG_DONTWAIT; /* non-blocking */ + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = NULL; + + return kernel_recvmsg(raw_sock, &msg, &iov, 1, packet_buff_len, MSG_DONTWAIT); +} + +int packet_recv_thread(void *data) +{ + struct batman_if *batman_if; + struct ethhdr *ethhdr; + struct batman_packet *batman_packet; + struct unicast_packet *unicast_packet; + struct bcast_packet *bcast_packet; + struct icmp_packet *icmp_packet; + struct vis_packet *vis_packet; + struct orig_node *orig_node; + unsigned char *packet_buff, src_str[ETH_STR_LEN], dst_str[ETH_STR_LEN]; + int vis_info_len; + int result; + + atomic_set(&data_ready_cond, 0); + atomic_set(&exit_cond, 0); + packet_buff = kmalloc(PACKBUFF_SIZE, GFP_KERNEL); + if (!packet_buff) { + debug_log(LOG_TYPE_CRIT, "Could allocate memory for the packet buffer. :(\n"); + return -1; + } + + while ((!kthread_should_stop()) && (!atomic_read(&exit_cond))) { + + wait_event_interruptible(thread_wait, (atomic_read(&data_ready_cond) || atomic_read(&exit_cond))); + + atomic_set(&data_ready_cond, 0); + + if (kthread_should_stop() || atomic_read(&exit_cond)) + break; + + /* we only want to safely traverse the list, hard-interfaces + * won't be deleted anyway as long as this thread runs. */ + + rcu_read_lock(); + list_for_each_entry_rcu(batman_if, &if_list, list) { + rcu_read_unlock(); + + result = -1; + + while (1) { + if (batman_if->if_active != IF_ACTIVE) { + if (batman_if->if_active != IF_TO_BE_ACTIVATED) + debug_log(LOG_TYPE_NOTICE, + "Could not read from deactivated interface %s!\n", + batman_if->dev); + + if (batman_if->raw_sock) + receive_raw_packet(batman_if->raw_sock, packet_buff, PACKBUFF_SIZE); + result = 0; + break; + } + + result = receive_raw_packet(batman_if->raw_sock, packet_buff, PACKBUFF_SIZE); + if (result <= 0) + break; + + if (result < sizeof(struct ethhdr) + 2) + continue; + + ethhdr = (struct ethhdr *)packet_buff; + batman_packet = (struct batman_packet *)(packet_buff + sizeof(struct ethhdr)); + + if (batman_packet->version != COMPAT_VERSION) { + debug_log(LOG_TYPE_BATMAN, "Drop packet: incompatible batman version (%i) \n", batman_packet->version); + continue; + } + + switch (batman_packet->packet_type) { + /* batman originator packet */ + case BAT_PACKET: + /* packet with broadcast indication but unicast recipient */ + if (!is_bcast(ethhdr->h_dest)) + continue; + + /* packet with broadcast sender address */ + if (is_bcast(ethhdr->h_source)) + continue; + + /* drop packet if it has not at least one batman packet as payload */ + if (result < sizeof(struct ethhdr) + sizeof(struct batman_packet)) + continue; + + spin_lock(&orig_hash_lock); + receive_aggr_bat_packet(ethhdr, + packet_buff + sizeof(struct ethhdr), + result - sizeof(struct ethhdr), + batman_if); + spin_unlock(&orig_hash_lock); + + break; + + /* batman icmp packet */ + case BAT_ICMP: + /* packet with unicast indication but broadcast recipient */ + if (is_bcast(ethhdr->h_dest)) + continue; + + /* packet with broadcast sender address */ + if (is_bcast(ethhdr->h_source)) + continue; + + /* not for me */ + if (!is_my_mac(ethhdr->h_dest)) + continue; + + /* drop packet if it has not necessary minimum size */ + if (result < sizeof(struct ethhdr) + sizeof(struct icmp_packet)) + continue; + + icmp_packet = (struct icmp_packet *)(packet_buff + sizeof(struct ethhdr)); + + /* packet for me */ + if (is_my_mac(icmp_packet->dst)) { + + /* add data to device queue */ + if (icmp_packet->msg_type != ECHO_REQUEST) { + bat_device_receive_packet(icmp_packet); + continue; + } + + /* answer echo request (ping) */ + /* get routing information */ + spin_lock(&orig_hash_lock); + orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet->orig)); + + if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) { + + memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); + memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN); + icmp_packet->msg_type = ECHO_REPLY; + icmp_packet->ttl = TTL; + + send_raw_packet(packet_buff + sizeof(struct ethhdr), + result - sizeof(struct ethhdr), + orig_node->batman_if, + orig_node->router->addr); + + } + + spin_unlock(&orig_hash_lock); + continue; + + } + + /* TTL exceeded */ + if (icmp_packet->ttl < 2) { + + addr_to_string(src_str, icmp_packet->orig); + addr_to_string(dst_str, icmp_packet->dst); + + debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str); + + /* send TTL exceeded if packet is an echo request (traceroute) */ + if (icmp_packet->msg_type != ECHO_REQUEST) + continue; + + /* get routing information */ + spin_lock(&orig_hash_lock); + orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet->orig)); + + if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) { + + memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); + memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN); + icmp_packet->msg_type = TTL_EXCEEDED; + icmp_packet->ttl = TTL; + + send_raw_packet(packet_buff + sizeof(struct ethhdr), + result - sizeof(struct ethhdr), + orig_node->batman_if, + orig_node->router->addr); + + } + + spin_unlock(&orig_hash_lock); + continue; + + } + + /* get routing information */ + spin_lock(&orig_hash_lock); + orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet->dst)); + + if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) { + + /* decrement ttl */ + icmp_packet->ttl--; + + /* route it */ + send_raw_packet(packet_buff + sizeof(struct ethhdr), + result - sizeof(struct ethhdr), + orig_node->batman_if, + orig_node->router->addr); + } + + spin_unlock(&orig_hash_lock); + break; + + /* unicast packet */ + case BAT_UNICAST: + /* packet with unicast indication but broadcast recipient */ + if (is_bcast(ethhdr->h_dest)) + continue; + + /* packet with broadcast sender address */ + if (is_bcast(ethhdr->h_source)) + continue; + + /* not for me */ + if (!is_my_mac(ethhdr->h_dest)) + continue; + + /* drop packet if it has not necessary minimum size */ + if (result < sizeof(struct ethhdr) + sizeof(struct unicast_packet)) + continue; + + unicast_packet = (struct unicast_packet *)(packet_buff + sizeof(struct ethhdr)); + + /* packet for me */ + if (is_my_mac(unicast_packet->dest)) { + + interface_rx(soft_device, packet_buff + sizeof(struct ethhdr) + sizeof(struct unicast_packet), result - sizeof(struct ethhdr) - sizeof(struct unicast_packet)); + continue; + + } + + /* TTL exceeded */ + if (unicast_packet->ttl < 2) { + addr_to_string(src_str, ((struct ethhdr *)(unicast_packet + 1))->h_source); + addr_to_string(dst_str, unicast_packet->dest); + + debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str); + continue; + } + + /* get routing information */ + spin_lock(&orig_hash_lock); + orig_node = ((struct orig_node *)hash_find(orig_hash, unicast_packet->dest)); + + if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) { + /* decrement ttl */ + unicast_packet->ttl--; + + /* route it */ + send_raw_packet(packet_buff + sizeof(struct ethhdr), + result - sizeof(struct ethhdr), + orig_node->batman_if, + orig_node->router->addr); + } + + spin_unlock(&orig_hash_lock); + break; + + /* broadcast packet */ + case BAT_BCAST: + /* packet with broadcast indication but unicast recipient */ + if (!is_bcast(ethhdr->h_dest)) + continue; + + /* packet with broadcast sender address */ + if (is_bcast(ethhdr->h_source)) + continue; + + /* drop packet if it has not necessary minimum size */ + if (result < sizeof(struct ethhdr) + sizeof(struct bcast_packet)) + continue; + + /* ignore broadcasts sent by myself */ + if (is_my_mac(ethhdr->h_source)) + continue; + + bcast_packet = (struct bcast_packet *)(packet_buff + sizeof(struct ethhdr)); + + /* ignore broadcasts originated by myself */ + if (is_my_mac(bcast_packet->orig)) + continue; + + spin_lock(&orig_hash_lock); + orig_node = ((struct orig_node *)hash_find(orig_hash, bcast_packet->orig)); + + if (orig_node == NULL) { + spin_unlock(&orig_hash_lock); + continue; + } + + /* check flood history */ + if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno, ntohs(bcast_packet->seqno))) { + spin_unlock(&orig_hash_lock); + continue; + } + + /* mark broadcast in flood history */ + if (bit_get_packet(orig_node->bcast_bits, ntohs(bcast_packet->seqno) - orig_node->last_bcast_seqno, 1)) + orig_node->last_bcast_seqno = ntohs(bcast_packet->seqno); + + spin_unlock(&orig_hash_lock); + + /* broadcast for me */ + interface_rx(soft_device, packet_buff + sizeof(struct ethhdr) + sizeof(struct bcast_packet), result - sizeof(struct ethhdr) - sizeof(struct bcast_packet)); + + /* rebroadcast packet */ + add_bcast_packet_to_list(packet_buff + sizeof(struct ethhdr), + result - sizeof(struct ethhdr)); + + break; + + /* vis packet */ + case BAT_VIS: + /* drop if too short. */ + if (result < sizeof(struct ethhdr) + sizeof(struct vis_packet)) + continue; + + /* not for me */ + if (!is_my_mac(ethhdr->h_dest)) + continue; + + vis_packet = (struct vis_packet *)(packet_buff + sizeof(struct ethhdr)); + vis_info_len = result - sizeof(struct ethhdr) - sizeof(struct vis_packet); + + /* ignore own packets */ + if (is_my_mac(vis_packet->vis_orig)) + continue; + + if (is_my_mac(vis_packet->sender_orig)) + continue; + + switch (vis_packet->vis_type) { + case VIS_TYPE_SERVER_SYNC: + receive_server_sync_packet(vis_packet, vis_info_len); + break; + + case VIS_TYPE_CLIENT_UPDATE: + receive_client_update_packet(vis_packet, vis_info_len); + break; + + default: /* ignore unknown packet */ + break; + } + + break; + } + + } + + if ((result < 0) && (result != -EAGAIN)) + debug_log(LOG_TYPE_CRIT, "Could not receive packet from interface %s: %i\n", batman_if->dev, result); + + /* lock for the next iteration */ + rcu_read_lock(); + } + rcu_read_unlock(); + + } + kfree(packet_buff); + + /* do not exit until kthread_stop() is actually called, otherwise it will wait for us + * forever. */ + while (!kthread_should_stop()) + schedule(); + + return 0; +} + +void batman_data_ready(struct sock *sk, int len) +{ + void (*data_ready)(struct sock *, int) = sk->sk_user_data; + + data_ready(sk, len); + + atomic_set(&data_ready_cond, 1); + wake_up_interruptible(&thread_wait); +} + diff --git a/drivers/staging/batman-adv/routing.h b/drivers/staging/batman-adv/routing.h new file mode 100644 index 0000000000000000000000000000000000000000..0123ea86debb8a2c61b260b59b02baa037f07bc1 --- /dev/null +++ b/drivers/staging/batman-adv/routing.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "types.h" + +extern wait_queue_head_t thread_wait; +extern atomic_t exit_cond; + +int originator_init(void); +void free_orig_node(void *data); +void originator_free(void); +void slide_own_bcast_window(struct batman_if *batman_if); +void batman_data_ready(struct sock *sk, int len); +void purge_orig(struct work_struct *work); +int packet_recv_thread(void *data); +void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, unsigned char *hna_buff, int hna_buff_len, struct batman_if *if_incoming); diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c new file mode 100644 index 0000000000000000000000000000000000000000..d724798278d6c813f9fafa88b4fb18bd394c1edf --- /dev/null +++ b/drivers/staging/batman-adv/send.c @@ -0,0 +1,473 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "send.h" +#include "log.h" +#include "routing.h" +#include "translation-table.h" +#include "hard-interface.h" +#include "types.h" +#include "vis.h" +#include "aggregation.h" + +#include "compat.h" + +/* apply hop penalty for a normal link */ +static uint8_t hop_penalty(const uint8_t tq) +{ + return (tq * (TQ_MAX_VALUE - TQ_HOP_PENALTY)) / (TQ_MAX_VALUE); +} + +/* when do we schedule our own packet to be sent */ +static unsigned long own_send_time(void) +{ + return jiffies + + (((atomic_read(&originator_interval) - JITTER + + (random32() % 2*JITTER)) * HZ) / 1000); +} + +/* when do we schedule a forwarded packet to be sent */ +static unsigned long forward_send_time(void) +{ + unsigned long send_time = jiffies; /* Starting now plus... */ + + if (atomic_read(&aggregation_enabled)) + send_time += (((MAX_AGGREGATION_MS - (JITTER/2) + + (random32() % JITTER)) * HZ) / 1000); + else + send_time += (((random32() % (JITTER/2)) * HZ) / 1000); + + return send_time; +} + +/* sends a raw packet. */ +void send_raw_packet(unsigned char *pack_buff, int pack_buff_len, + struct batman_if *batman_if, uint8_t *dst_addr) +{ + struct ethhdr *ethhdr; + struct sk_buff *skb; + int retval; + char *data; + + if (batman_if->if_active != IF_ACTIVE) + return; + + if (!(batman_if->net_dev->flags & IFF_UP)) { + debug_log(LOG_TYPE_WARN, + "Interface %s is not up - can't send packet via that interface (IF_TO_BE_DEACTIVATED was here) !\n", + batman_if->dev); + return; + } + + skb = dev_alloc_skb(pack_buff_len + sizeof(struct ethhdr)); + if (!skb) + return; + data = skb_put(skb, pack_buff_len + sizeof(struct ethhdr)); + + memcpy(data + sizeof(struct ethhdr), pack_buff, pack_buff_len); + + ethhdr = (struct ethhdr *) data; + memcpy(ethhdr->h_source, batman_if->net_dev->dev_addr, ETH_ALEN); + memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN); + ethhdr->h_proto = __constant_htons(ETH_P_BATMAN); + + skb_reset_mac_header(skb); + skb_set_network_header(skb, ETH_HLEN); + skb->priority = TC_PRIO_CONTROL; + skb->protocol = __constant_htons(ETH_P_BATMAN); + skb->dev = batman_if->net_dev; + + /* dev_queue_xmit() returns a negative result on error. However on + * congestion and traffic shaping, it drops and returns NET_XMIT_DROP + * (which is > 0). This will not be treated as an error. */ + retval = dev_queue_xmit(skb); + if (retval < 0) + debug_log(LOG_TYPE_CRIT, + "Can't write to raw socket (IF_TO_BE_DEACTIVATED was here): %i\n", + retval); +} + +/* Send a packet to a given interface */ +static void send_packet_to_if(struct forw_packet *forw_packet, + struct batman_if *batman_if) +{ + char *fwd_str; + uint8_t packet_num; + int16_t buff_pos; + struct batman_packet *batman_packet; + char orig_str[ETH_STR_LEN]; + + if (batman_if->if_active != IF_ACTIVE) + return; + + packet_num = buff_pos = 0; + batman_packet = (struct batman_packet *) + (forw_packet->packet_buff); + + /* adjust all flags and log packets */ + while (aggregated_packet(buff_pos, + forw_packet->packet_len, + batman_packet->num_hna)) { + + /* we might have aggregated direct link packets with an + * ordinary base packet */ + if ((forw_packet->direct_link_flags & (1 << packet_num)) && + (forw_packet->if_incoming == batman_if)) + batman_packet->flags |= DIRECTLINK; + else + batman_packet->flags &= ~DIRECTLINK; + + addr_to_string(orig_str, batman_packet->orig); + fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ? + "Sending own" : + "Forwarding")); + debug_log(LOG_TYPE_BATMAN, + "%s %spacket (originator %s, seqno %d, TQ %d, TTL %d, IDF %s) on interface %s [%s]\n", + fwd_str, + (packet_num > 0 ? "aggregated " : ""), + orig_str, ntohs(batman_packet->seqno), + batman_packet->tq, batman_packet->ttl, + (batman_packet->flags & DIRECTLINK ? + "on" : "off"), + batman_if->dev, batman_if->addr_str); + + buff_pos += sizeof(struct batman_packet) + + (batman_packet->num_hna * ETH_ALEN); + packet_num++; + batman_packet = (struct batman_packet *) + (forw_packet->packet_buff + buff_pos); + } + + send_raw_packet(forw_packet->packet_buff, + forw_packet->packet_len, + batman_if, broadcastAddr); +} + +/* send a batman packet */ +static void send_packet(struct forw_packet *forw_packet) +{ + struct batman_if *batman_if; + struct batman_packet *batman_packet = + (struct batman_packet *)(forw_packet->packet_buff); + char orig_str[ETH_STR_LEN]; + unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0); + + if (!forw_packet->if_incoming) { + debug_log(LOG_TYPE_CRIT, + "Error - can't forward packet: incoming iface not specified\n"); + return; + } + + if (forw_packet->if_incoming->if_active != IF_ACTIVE) + return; + + addr_to_string(orig_str, batman_packet->orig); + + /* multihomed peer assumed */ + /* non-primary OGMs are only broadcasted on their interface */ + if ((directlink && (batman_packet->ttl == 1)) || + (forw_packet->own && (forw_packet->if_incoming->if_num > 0))) { + + /* FIXME: what about aggregated packets ? */ + debug_log(LOG_TYPE_BATMAN, + "%s packet (originator %s, seqno %d, TTL %d) on interface %s [%s]\n", + (forw_packet->own ? "Sending own" : "Forwarding"), + orig_str, ntohs(batman_packet->seqno), + batman_packet->ttl, forw_packet->if_incoming->dev, + forw_packet->if_incoming->addr_str); + + send_raw_packet(forw_packet->packet_buff, + forw_packet->packet_len, + forw_packet->if_incoming, + broadcastAddr); + return; + } + + /* broadcast on every interface */ + rcu_read_lock(); + list_for_each_entry_rcu(batman_if, &if_list, list) + send_packet_to_if(forw_packet, batman_if); + rcu_read_unlock(); +} + +static void rebuild_batman_packet(struct batman_if *batman_if) +{ + int new_len; + unsigned char *new_buff; + struct batman_packet *batman_packet; + + new_len = sizeof(struct batman_packet) + (num_hna * ETH_ALEN); + new_buff = kmalloc(new_len, GFP_ATOMIC); + + /* keep old buffer if kmalloc should fail */ + if (new_buff) { + memcpy(new_buff, batman_if->packet_buff, + sizeof(struct batman_packet)); + batman_packet = (struct batman_packet *)new_buff; + + batman_packet->num_hna = hna_local_fill_buffer( + new_buff + sizeof(struct batman_packet), + new_len - sizeof(struct batman_packet)); + + kfree(batman_if->packet_buff); + batman_if->packet_buff = new_buff; + batman_if->packet_len = new_len; + } +} + +void schedule_own_packet(struct batman_if *batman_if) +{ + unsigned long send_time; + struct batman_packet *batman_packet; + + /** + * the interface gets activated here to avoid race conditions between + * the moment of activating the interface in + * hardif_activate_interface() where the originator mac is set and + * outdated packets (especially uninitialized mac addresses) in the + * packet queue + */ + if (batman_if->if_active == IF_TO_BE_ACTIVATED) + batman_if->if_active = IF_ACTIVE; + + /* if local hna has changed and interface is a primary interface */ + if ((atomic_read(&hna_local_changed)) && (batman_if->if_num == 0)) + rebuild_batman_packet(batman_if); + + /** + * NOTE: packet_buff might just have been re-allocated in + * rebuild_batman_packet() + */ + batman_packet = (struct batman_packet *)batman_if->packet_buff; + + /* change sequence number to network order */ + batman_packet->seqno = htons((uint16_t)atomic_read(&batman_if->seqno)); + + if (is_vis_server()) + batman_packet->flags = VIS_SERVER; + else + batman_packet->flags = 0; + + /* could be read by receive_bat_packet() */ + atomic_inc(&batman_if->seqno); + + slide_own_bcast_window(batman_if); + send_time = own_send_time(); + add_bat_packet_to_list(batman_if->packet_buff, + batman_if->packet_len, batman_if, 1, send_time); +} + +void schedule_forward_packet(struct orig_node *orig_node, + struct ethhdr *ethhdr, + struct batman_packet *batman_packet, + uint8_t directlink, int hna_buff_len, + struct batman_if *if_incoming) +{ + unsigned char in_tq, in_ttl, tq_avg = 0; + unsigned long send_time; + + if (batman_packet->ttl <= 1) { + debug_log(LOG_TYPE_BATMAN, "ttl exceeded \n"); + return; + } + + in_tq = batman_packet->tq; + in_ttl = batman_packet->ttl; + + batman_packet->ttl--; + memcpy(batman_packet->prev_sender, ethhdr->h_source, ETH_ALEN); + + /* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast + * of our best tq value */ + if ((orig_node->router) && (orig_node->router->tq_avg != 0)) { + + /* rebroadcast ogm of best ranking neighbor as is */ + if (!compare_orig(orig_node->router->addr, ethhdr->h_source)) { + batman_packet->tq = orig_node->router->tq_avg; + + if (orig_node->router->last_ttl) + batman_packet->ttl = orig_node->router->last_ttl - 1; + } + + tq_avg = orig_node->router->tq_avg; + } + + /* apply hop penalty */ + batman_packet->tq = hop_penalty(batman_packet->tq); + + debug_log(LOG_TYPE_BATMAN, "Forwarding packet: tq_orig: %i, tq_avg: %i, tq_forw: %i, ttl_orig: %i, ttl_forw: %i \n", + in_tq, tq_avg, batman_packet->tq, in_ttl - 1, + batman_packet->ttl); + + batman_packet->seqno = htons(batman_packet->seqno); + + if (directlink) + batman_packet->flags |= DIRECTLINK; + else + batman_packet->flags &= ~DIRECTLINK; + + send_time = forward_send_time(); + add_bat_packet_to_list((unsigned char *)batman_packet, + sizeof(struct batman_packet) + hna_buff_len, + if_incoming, 0, send_time); +} + +static void forw_packet_free(struct forw_packet *forw_packet) +{ + kfree(forw_packet->packet_buff); + kfree(forw_packet); +} + +static void _add_bcast_packet_to_list(struct forw_packet *forw_packet, + unsigned long send_time) +{ + INIT_HLIST_NODE(&forw_packet->list); + + /* add new packet to packet list */ + spin_lock(&forw_bcast_list_lock); + hlist_add_head(&forw_packet->list, &forw_bcast_list); + spin_unlock(&forw_bcast_list_lock); + + /* start timer for this packet */ + INIT_DELAYED_WORK(&forw_packet->delayed_work, + send_outstanding_bcast_packet); + queue_delayed_work(bat_event_workqueue, &forw_packet->delayed_work, + send_time); +} + +void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len) +{ + struct forw_packet *forw_packet; + + forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC); + if (!forw_packet) + return; + + forw_packet->packet_buff = kmalloc(packet_len, GFP_ATOMIC); + if (!forw_packet->packet_buff) + return; + + forw_packet->packet_len = packet_len; + memcpy(forw_packet->packet_buff, packet_buff, forw_packet->packet_len); + + /* how often did we send the bcast packet ? */ + forw_packet->num_packets = 0; + + _add_bcast_packet_to_list(forw_packet, 1); +} + +void send_outstanding_bcast_packet(struct work_struct *work) +{ + struct batman_if *batman_if; + struct delayed_work *delayed_work = + container_of(work, struct delayed_work, work); + struct forw_packet *forw_packet = + container_of(delayed_work, struct forw_packet, delayed_work); + + spin_lock(&forw_bcast_list_lock); + hlist_del(&forw_packet->list); + spin_unlock(&forw_bcast_list_lock); + + /* rebroadcast packet */ + rcu_read_lock(); + list_for_each_entry_rcu(batman_if, &if_list, list) { + send_raw_packet(forw_packet->packet_buff, + forw_packet->packet_len, + batman_if, broadcastAddr); + } + rcu_read_unlock(); + + forw_packet->num_packets++; + + /* if we still have some more bcasts to send and we are not shutting + * down */ + if ((forw_packet->num_packets < 3) && + (atomic_read(&module_state) != MODULE_DEACTIVATING)) + _add_bcast_packet_to_list(forw_packet, ((5 * HZ) / 1000)); + else + forw_packet_free(forw_packet); +} + +void send_outstanding_bat_packet(struct work_struct *work) +{ + struct delayed_work *delayed_work = + container_of(work, struct delayed_work, work); + struct forw_packet *forw_packet = + container_of(delayed_work, struct forw_packet, delayed_work); + + spin_lock(&forw_bat_list_lock); + hlist_del(&forw_packet->list); + spin_unlock(&forw_bat_list_lock); + + send_packet(forw_packet); + + /** + * we have to have at least one packet in the queue + * to determine the queues wake up time unless we are + * shutting down + */ + if ((forw_packet->own) && + (atomic_read(&module_state) != MODULE_DEACTIVATING)) + schedule_own_packet(forw_packet->if_incoming); + + forw_packet_free(forw_packet); +} + +void purge_outstanding_packets(void) +{ + struct forw_packet *forw_packet; + struct hlist_node *tmp_node, *safe_tmp_node; + + debug_log(LOG_TYPE_BATMAN, "purge_outstanding_packets()\n"); + + /* free bcast list */ + spin_lock(&forw_bcast_list_lock); + hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node, + &forw_bcast_list, list) { + + spin_unlock(&forw_bcast_list_lock); + + /** + * send_outstanding_bcast_packet() will lock the list to + * delete the item from the list + */ + cancel_delayed_work_sync(&forw_packet->delayed_work); + spin_lock(&forw_bcast_list_lock); + } + spin_unlock(&forw_bcast_list_lock); + + /* free batman packet list */ + spin_lock(&forw_bat_list_lock); + hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node, + &forw_bat_list, list) { + + spin_unlock(&forw_bat_list_lock); + + /** + * send_outstanding_bat_packet() will lock the list to + * delete the item from the list + */ + cancel_delayed_work_sync(&forw_packet->delayed_work); + spin_lock(&forw_bat_list_lock); + } + spin_unlock(&forw_bat_list_lock); +} diff --git a/drivers/staging/batman-adv/send.h b/drivers/staging/batman-adv/send.h new file mode 100644 index 0000000000000000000000000000000000000000..59d500917a35cb1e3d613e2da6b07eead9e54a30 --- /dev/null +++ b/drivers/staging/batman-adv/send.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "types.h" + +void send_own_packet_work(struct work_struct *work); +void send_raw_packet(unsigned char *pack_buff, int pack_buff_len, + struct batman_if *batman_if, uint8_t *dst_addr); +void schedule_own_packet(struct batman_if *batman_if); +void schedule_forward_packet(struct orig_node *orig_node, + struct ethhdr *ethhdr, + struct batman_packet *batman_packet, + uint8_t directlink, int hna_buff_len, + struct batman_if *if_outgoing); +void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len); +void send_outstanding_bcast_packet(struct work_struct *work); +void send_outstanding_bat_packet(struct work_struct *work); +void purge_outstanding_packets(void); diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c new file mode 100644 index 0000000000000000000000000000000000000000..d543f50b647f888a28ce47159c3eea2bf47dd7b3 --- /dev/null +++ b/drivers/staging/batman-adv/soft-interface.c @@ -0,0 +1,349 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "soft-interface.h" +#include "hard-interface.h" +#include "send.h" +#include "translation-table.h" +#include "log.h" +#include "types.h" +#include "hash.h" +#include +#include +#include "compat.h" + +static uint16_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid + * broadcast storms */ +static int32_t skb_packets; +static int32_t skb_bad_packets; +static int32_t lock_dropped; + +unsigned char mainIfAddr[ETH_ALEN]; +static unsigned char mainIfAddr_default[ETH_ALEN]; +static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); +static void bat_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info); +static u32 bat_get_msglevel(struct net_device *dev); +static void bat_set_msglevel(struct net_device *dev, u32 value); +static u32 bat_get_link(struct net_device *dev); +static u32 bat_get_rx_csum(struct net_device *dev); +static int bat_set_rx_csum(struct net_device *dev, u32 data); + +static const struct ethtool_ops bat_ethtool_ops = { + .get_settings = bat_get_settings, + .get_drvinfo = bat_get_drvinfo, + .get_msglevel = bat_get_msglevel, + .set_msglevel = bat_set_msglevel, + .get_link = bat_get_link, + .get_rx_csum = bat_get_rx_csum, + .set_rx_csum = bat_set_rx_csum +}; + +void set_main_if_addr(uint8_t *addr) +{ + memcpy(mainIfAddr, addr, ETH_ALEN); +} + +int main_if_was_up(void) +{ + return (memcmp(mainIfAddr, mainIfAddr_default, ETH_ALEN) != 0 ? 1 : 0); +} + +static int my_skb_push(struct sk_buff *skb, unsigned int len) +{ + int result = 0; + + skb_packets++; + if (skb->data - len < skb->head) { + skb_bad_packets++; + result = pskb_expand_head(skb, len, 0, GFP_ATOMIC); + + if (result < 0) + return result; + } + + skb_push(skb, len); + return 0; +} + +#ifdef HAVE_NET_DEVICE_OPS +static const struct net_device_ops bat_netdev_ops = { + .ndo_open = interface_open, + .ndo_stop = interface_release, + .ndo_get_stats = interface_stats, + .ndo_set_mac_address = interface_set_mac_addr, + .ndo_change_mtu = interface_change_mtu, + .ndo_start_xmit = interface_tx, + .ndo_validate_addr = eth_validate_addr +}; +#endif + +void interface_setup(struct net_device *dev) +{ + struct bat_priv *priv = netdev_priv(dev); + char dev_addr[ETH_ALEN]; + + ether_setup(dev); + +#ifdef HAVE_NET_DEVICE_OPS + dev->netdev_ops = &bat_netdev_ops; +#else + dev->open = interface_open; + dev->stop = interface_release; + dev->get_stats = interface_stats; + dev->set_mac_address = interface_set_mac_addr; + dev->change_mtu = interface_change_mtu; + dev->hard_start_xmit = interface_tx; +#endif + dev->destructor = free_netdev; + + dev->mtu = hardif_min_mtu(); + dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the + * skbuff for our header */ + + /* generate random address */ + random_ether_addr(dev_addr); + memcpy(dev->dev_addr, dev_addr, sizeof(dev->dev_addr)); + + SET_ETHTOOL_OPS(dev, &bat_ethtool_ops); + + memset(priv, 0, sizeof(struct bat_priv)); +} + +int interface_open(struct net_device *dev) +{ + netif_start_queue(dev); + return 0; +} + +int interface_release(struct net_device *dev) +{ + netif_stop_queue(dev); + return 0; +} + +struct net_device_stats *interface_stats(struct net_device *dev) +{ + struct bat_priv *priv = netdev_priv(dev); + return &priv->stats; +} + +int interface_set_mac_addr(struct net_device *dev, void *addr) +{ + return -EBUSY; +} + +int interface_change_mtu(struct net_device *dev, int new_mtu) +{ + /* check ranges */ + if ((new_mtu < 68) || (new_mtu > hardif_min_mtu())) + return -EINVAL; + + dev->mtu = new_mtu; + + return 0; +} + +int interface_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct unicast_packet *unicast_packet; + struct bcast_packet *bcast_packet; + struct orig_node *orig_node; + struct ethhdr *ethhdr = (struct ethhdr *)skb->data; + struct bat_priv *priv = netdev_priv(dev); + int data_len = skb->len; + + if (atomic_read(&module_state) != MODULE_ACTIVE) + goto dropped; + + dev->trans_start = jiffies; + /* TODO: check this for locks */ + hna_local_add(ethhdr->h_source); + + /* ethernet packet should be broadcasted */ + if (is_bcast(ethhdr->h_dest) || is_mcast(ethhdr->h_dest)) { + + if (my_skb_push(skb, sizeof(struct bcast_packet)) < 0) + goto dropped; + + bcast_packet = (struct bcast_packet *)skb->data; + + bcast_packet->version = COMPAT_VERSION; + + /* batman packet type: broadcast */ + bcast_packet->packet_type = BAT_BCAST; + + /* hw address of first interface is the orig mac because only + * this mac is known throughout the mesh */ + memcpy(bcast_packet->orig, mainIfAddr, ETH_ALEN); + /* set broadcast sequence number */ + bcast_packet->seqno = htons(bcast_seqno); + + bcast_seqno++; + + /* broadcast packet */ + add_bcast_packet_to_list(skb->data, skb->len); + + /* unicast packet */ + } else { + + /* simply spin_lock()ing can deadlock when the lock is already + * hold. */ + /* TODO: defer the work in a working queue instead of + * dropping */ + if (!spin_trylock(&orig_hash_lock)) { + lock_dropped++; + debug_log(LOG_TYPE_NOTICE, "%d packets dropped because lock was hold\n", lock_dropped); + goto dropped; + } + + /* get routing information */ + orig_node = ((struct orig_node *)hash_find(orig_hash, + ethhdr->h_dest)); + + /* check for hna host */ + if (!orig_node) + orig_node = transtable_search(ethhdr->h_dest); + + if ((orig_node) && + (orig_node->batman_if) && + (orig_node->router)) { + if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0) + goto unlock; + + unicast_packet = (struct unicast_packet *)skb->data; + + unicast_packet->version = COMPAT_VERSION; + /* batman packet type: unicast */ + unicast_packet->packet_type = BAT_UNICAST; + /* set unicast ttl */ + unicast_packet->ttl = TTL; + /* copy the destination for faster routing */ + memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); + + /* net_dev won't be available when not active */ + if (orig_node->batman_if->if_active != IF_ACTIVE) + goto unlock; + + send_raw_packet(skb->data, skb->len, + orig_node->batman_if, + orig_node->router->addr); + } else { + goto unlock; + } + + spin_unlock(&orig_hash_lock); + } + + priv->stats.tx_packets++; + priv->stats.tx_bytes += data_len; + goto end; + +unlock: + spin_unlock(&orig_hash_lock); +dropped: + priv->stats.tx_dropped++; +end: + kfree_skb(skb); + return 0; +} + +void interface_rx(struct net_device *dev, void *packet, int packet_len) +{ + struct sk_buff *skb; + struct bat_priv *priv = netdev_priv(dev); + + skb = dev_alloc_skb(packet_len); + + if (!skb) { + priv->stats.rx_dropped++; + goto out; + } + + memcpy(skb_put(skb, packet_len), packet, packet_len); + + /* Write metadata, and then pass to the receive level */ + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + skb->ip_summed = CHECKSUM_UNNECESSARY; + + priv->stats.rx_packets++; + priv->stats.rx_bytes += packet_len; + + dev->last_rx = jiffies; + + netif_rx(skb); + +out: + return; +} + +/* ethtool */ +static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + cmd->supported = 0; + cmd->advertising = 0; + cmd->speed = SPEED_10; + cmd->duplex = DUPLEX_FULL; + cmd->port = PORT_TP; + cmd->phy_address = 0; + cmd->transceiver = XCVR_INTERNAL; + cmd->autoneg = AUTONEG_DISABLE; + cmd->maxtxpkt = 0; + cmd->maxrxpkt = 0; + + return 0; +} + +static void bat_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strcpy(info->driver, "B.A.T.M.A.N. advanced"); + strcpy(info->version, SOURCE_VERSION); + strcpy(info->fw_version, "N/A"); + strcpy(info->bus_info, "batman"); +} + +static u32 bat_get_msglevel(struct net_device *dev) +{ + return -EOPNOTSUPP; +} + +static void bat_set_msglevel(struct net_device *dev, u32 value) +{ + return; +} + +static u32 bat_get_link(struct net_device *dev) +{ + return 1; +} + +static u32 bat_get_rx_csum(struct net_device *dev) +{ + return 0; +} + +static int bat_set_rx_csum(struct net_device *dev, u32 data) +{ + return -EOPNOTSUPP; +} diff --git a/drivers/staging/batman-adv/soft-interface.h b/drivers/staging/batman-adv/soft-interface.h new file mode 100644 index 0000000000000000000000000000000000000000..515e276ef53d38a77bade9a2d9272ec8221d1dc5 --- /dev/null +++ b/drivers/staging/batman-adv/soft-interface.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +void set_main_if_addr(uint8_t *addr); +int main_if_was_up(void); +void interface_setup(struct net_device *dev); +int interface_open(struct net_device *dev); +int interface_release(struct net_device *dev); +struct net_device_stats *interface_stats(struct net_device *dev); +int interface_set_mac_addr(struct net_device *dev, void *addr); +int interface_change_mtu(struct net_device *dev, int new_mtu); +int interface_tx(struct sk_buff *skb, struct net_device *dev); +void interface_rx(struct net_device *dev, void *packet, int packet_len); + +extern unsigned char mainIfAddr[]; diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c new file mode 100644 index 0000000000000000000000000000000000000000..c2190e177c56d73324ebcc8e72c4f08fc1967b6f --- /dev/null +++ b/drivers/staging/batman-adv/translation-table.c @@ -0,0 +1,454 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "translation-table.h" +#include "log.h" +#include "soft-interface.h" +#include "types.h" +#include "hash.h" +#include "compat.h" + +struct hashtable_t *hna_local_hash; +static struct hashtable_t *hna_global_hash; +atomic_t hna_local_changed; + +DEFINE_SPINLOCK(hna_local_hash_lock); +static DEFINE_SPINLOCK(hna_global_hash_lock); + +static DECLARE_DELAYED_WORK(hna_local_purge_wq, hna_local_purge); + +static void hna_local_start_timer(void) +{ + queue_delayed_work(bat_event_workqueue, &hna_local_purge_wq, 10 * HZ); +} + +int hna_local_init(void) +{ + if (hna_local_hash) + return 1; + + hna_local_hash = hash_new(128, compare_orig, choose_orig); + + if (!hna_local_hash) + return 0; + + atomic_set(&hna_local_changed, 0); + hna_local_start_timer(); + + return 1; +} + +void hna_local_add(uint8_t *addr) +{ + struct hna_local_entry *hna_local_entry; + struct hna_global_entry *hna_global_entry; + struct hashtable_t *swaphash; + char hna_str[ETH_STR_LEN]; + unsigned long flags; + + spin_lock_irqsave(&hna_local_hash_lock, flags); + hna_local_entry = + ((struct hna_local_entry *)hash_find(hna_local_hash, addr)); + spin_unlock_irqrestore(&hna_local_hash_lock, flags); + + if (hna_local_entry != NULL) { + hna_local_entry->last_seen = jiffies; + return; + } + + addr_to_string(hna_str, addr); + + /* only announce as many hosts as possible in the batman-packet and + space in batman_packet->num_hna That also should give a limit to + MAC-flooding. */ + if ((num_hna + 1 > (ETH_DATA_LEN - BAT_PACKET_LEN) / ETH_ALEN) || + (num_hna + 1 > 255)) { + debug_log(LOG_TYPE_ROUTES, "Can't add new local hna entry (%s): number of local hna entries exceeds packet size \n", hna_str); + return; + } + + debug_log(LOG_TYPE_ROUTES, "Creating new local hna entry: %s \n", + hna_str); + + hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC); + if (!hna_local_entry) + return; + + memcpy(hna_local_entry->addr, addr, ETH_ALEN); + hna_local_entry->last_seen = jiffies; + + /* the batman interface mac address should never be purged */ + if (compare_orig(addr, soft_device->dev_addr)) + hna_local_entry->never_purge = 1; + else + hna_local_entry->never_purge = 0; + + spin_lock_irqsave(&hna_local_hash_lock, flags); + + hash_add(hna_local_hash, hna_local_entry); + num_hna++; + atomic_set(&hna_local_changed, 1); + + if (hna_local_hash->elements * 4 > hna_local_hash->size) { + swaphash = hash_resize(hna_local_hash, + hna_local_hash->size * 2); + + if (swaphash == NULL) + debug_log(LOG_TYPE_CRIT, "Couldn't resize local hna hash table \n"); + else + hna_local_hash = swaphash; + } + + spin_unlock_irqrestore(&hna_local_hash_lock, flags); + + /* remove address from global hash if present */ + spin_lock_irqsave(&hna_global_hash_lock, flags); + + hna_global_entry = + ((struct hna_global_entry *)hash_find(hna_global_hash, addr)); + + if (hna_global_entry != NULL) + _hna_global_del_orig(hna_global_entry, "local hna received"); + + spin_unlock_irqrestore(&hna_global_hash_lock, flags); +} + +int hna_local_fill_buffer(unsigned char *buff, int buff_len) +{ + struct hna_local_entry *hna_local_entry; + struct hash_it_t *hashit = NULL; + int i = 0; + unsigned long flags; + + spin_lock_irqsave(&hna_local_hash_lock, flags); + + while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) { + + if (buff_len < (i + 1) * ETH_ALEN) + break; + + hna_local_entry = hashit->bucket->data; + memcpy(buff + (i * ETH_ALEN), hna_local_entry->addr, ETH_ALEN); + + i++; + } + + /* if we did not get all new local hnas see you next time ;-) */ + if (i == num_hna) + atomic_set(&hna_local_changed, 0); + + spin_unlock_irqrestore(&hna_local_hash_lock, flags); + + return i; +} + +int hna_local_fill_buffer_text(unsigned char *buff, int buff_len) +{ + struct hna_local_entry *hna_local_entry; + struct hash_it_t *hashit = NULL; + int bytes_written = 0; + unsigned long flags; + + spin_lock_irqsave(&hna_local_hash_lock, flags); + + while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) { + + if (buff_len < bytes_written + ETH_STR_LEN + 4) + break; + + hna_local_entry = hashit->bucket->data; + + bytes_written += snprintf(buff + bytes_written, ETH_STR_LEN + 4, + " * %02x:%02x:%02x:%02x:%02x:%02x\n", + hna_local_entry->addr[0], + hna_local_entry->addr[1], + hna_local_entry->addr[2], + hna_local_entry->addr[3], + hna_local_entry->addr[4], + hna_local_entry->addr[5]); + } + + spin_unlock_irqrestore(&hna_local_hash_lock, flags); + + return bytes_written; +} + +static void _hna_local_del(void *data) +{ + kfree(data); + num_hna--; + atomic_set(&hna_local_changed, 1); +} + +static void hna_local_del(struct hna_local_entry *hna_local_entry, + char *message) +{ + char hna_str[ETH_STR_LEN]; + + addr_to_string(hna_str, hna_local_entry->addr); + debug_log(LOG_TYPE_ROUTES, "Deleting local hna entry (%s): %s \n", + hna_str, message); + + hash_remove(hna_local_hash, hna_local_entry->addr); + _hna_local_del(hna_local_entry); +} + +void hna_local_purge(struct work_struct *work) +{ + struct hna_local_entry *hna_local_entry; + struct hash_it_t *hashit = NULL; + unsigned long flags; + unsigned long timeout; + + spin_lock_irqsave(&hna_local_hash_lock, flags); + + while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) { + hna_local_entry = hashit->bucket->data; + + timeout = hna_local_entry->last_seen + + ((LOCAL_HNA_TIMEOUT / 1000) * HZ); + if ((!hna_local_entry->never_purge) && + time_after(jiffies, timeout)) + hna_local_del(hna_local_entry, "address timed out"); + } + + spin_unlock_irqrestore(&hna_local_hash_lock, flags); + hna_local_start_timer(); +} + +void hna_local_free(void) +{ + if (!hna_local_hash) + return; + + cancel_delayed_work_sync(&hna_local_purge_wq); + hash_delete(hna_local_hash, _hna_local_del); + hna_local_hash = NULL; +} + +int hna_global_init(void) +{ + if (hna_global_hash) + return 1; + + hna_global_hash = hash_new(128, compare_orig, choose_orig); + + if (!hna_global_hash) + return 0; + + return 1; +} + +void hna_global_add_orig(struct orig_node *orig_node, + unsigned char *hna_buff, int hna_buff_len) +{ + struct hna_global_entry *hna_global_entry; + struct hna_local_entry *hna_local_entry; + struct hashtable_t *swaphash; + char hna_str[ETH_STR_LEN], orig_str[ETH_STR_LEN]; + int hna_buff_count = 0; + unsigned long flags; + unsigned char *hna_ptr; + + addr_to_string(orig_str, orig_node->orig); + + while ((hna_buff_count + 1) * ETH_ALEN <= hna_buff_len) { + spin_lock_irqsave(&hna_global_hash_lock, flags); + + hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN); + hna_global_entry = (struct hna_global_entry *) + hash_find(hna_global_hash, hna_ptr); + + if (hna_global_entry == NULL) { + spin_unlock_irqrestore(&hna_global_hash_lock, flags); + + hna_global_entry = + kmalloc(sizeof(struct hna_global_entry), + GFP_ATOMIC); + + if (!hna_global_entry) + break; + + memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN); + + addr_to_string(hna_str, hna_global_entry->addr); + debug_log(LOG_TYPE_ROUTES, "Creating new global hna entry: %s (via %s)\n", hna_str, orig_str); + + spin_lock_irqsave(&hna_global_hash_lock, flags); + hash_add(hna_global_hash, hna_global_entry); + + } + + hna_global_entry->orig_node = orig_node; + spin_unlock_irqrestore(&hna_global_hash_lock, flags); + + /* remove address from local hash if present */ + spin_lock_irqsave(&hna_local_hash_lock, flags); + + hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN); + hna_local_entry = (struct hna_local_entry *) + hash_find(hna_local_hash, hna_ptr); + + if (hna_local_entry != NULL) + hna_local_del(hna_local_entry, "global hna received"); + + spin_unlock_irqrestore(&hna_local_hash_lock, flags); + + hna_buff_count++; + } + + orig_node->hna_buff_len = hna_buff_len; + + if (orig_node->hna_buff_len > 0) { + orig_node->hna_buff = kmalloc(orig_node->hna_buff_len, + GFP_ATOMIC); + memcpy(orig_node->hna_buff, hna_buff, orig_node->hna_buff_len); + } else { + orig_node->hna_buff = NULL; + } + + spin_lock_irqsave(&hna_global_hash_lock, flags); + + if (hna_global_hash->elements * 4 > hna_global_hash->size) { + swaphash = hash_resize(hna_global_hash, + hna_global_hash->size * 2); + + if (swaphash == NULL) + debug_log(LOG_TYPE_CRIT, "Couldn't resize global hna hash table \n"); + else + hna_global_hash = swaphash; + } + + spin_unlock_irqrestore(&hna_global_hash_lock, flags); +} + +int hna_global_fill_buffer_text(unsigned char *buff, int buff_len) +{ + struct hna_global_entry *hna_global_entry; + struct hash_it_t *hashit = NULL; + int bytes_written = 0; + unsigned long flags; + + spin_lock_irqsave(&hna_global_hash_lock, flags); + + while (NULL != (hashit = hash_iterate(hna_global_hash, hashit))) { + if (buff_len < bytes_written + (2 * ETH_STR_LEN) + 10) + break; + + hna_global_entry = hashit->bucket->data; + + bytes_written += snprintf(buff + bytes_written, + (2 * ETH_STR_LEN) + 10, + " * %02x:%02x:%02x:%02x:%02x:%02x via %02x:%02x:%02x:%02x:%02x:%02x \n", + hna_global_entry->addr[0], + hna_global_entry->addr[1], + hna_global_entry->addr[2], + hna_global_entry->addr[3], + hna_global_entry->addr[4], + hna_global_entry->addr[5], + hna_global_entry->orig_node->orig[0], + hna_global_entry->orig_node->orig[1], + hna_global_entry->orig_node->orig[2], + hna_global_entry->orig_node->orig[3], + hna_global_entry->orig_node->orig[4], + hna_global_entry->orig_node->orig[5]); + } + + spin_unlock_irqrestore(&hna_global_hash_lock, flags); + + return bytes_written; +} + +void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, + char *message) +{ + char hna_str[ETH_STR_LEN], orig_str[ETH_STR_LEN]; + + addr_to_string(orig_str, hna_global_entry->orig_node->orig); + addr_to_string(hna_str, hna_global_entry->addr); + + debug_log(LOG_TYPE_ROUTES, "Deleting global hna entry %s (via %s): %s \n", hna_str, orig_str, message); + + hash_remove(hna_global_hash, hna_global_entry->addr); + kfree(hna_global_entry); +} + +void hna_global_del_orig(struct orig_node *orig_node, char *message) +{ + struct hna_global_entry *hna_global_entry; + int hna_buff_count = 0; + unsigned long flags; + unsigned char *hna_ptr; + + if (orig_node->hna_buff_len == 0) + return; + + spin_lock_irqsave(&hna_global_hash_lock, flags); + + while ((hna_buff_count + 1) * ETH_ALEN <= orig_node->hna_buff_len) { + hna_ptr = orig_node->hna_buff + (hna_buff_count * ETH_ALEN); + hna_global_entry = (struct hna_global_entry *) + hash_find(hna_global_hash, hna_ptr); + + if ((hna_global_entry != NULL) && + (hna_global_entry->orig_node == orig_node)) + _hna_global_del_orig(hna_global_entry, message); + + hna_buff_count++; + } + + spin_unlock_irqrestore(&hna_global_hash_lock, flags); + + orig_node->hna_buff_len = 0; + kfree(orig_node->hna_buff); + orig_node->hna_buff = NULL; +} + +static void hna_global_del(void *data) +{ + kfree(data); +} + +void hna_global_free(void) +{ + if (!hna_global_hash) + return; + + hash_delete(hna_global_hash, hna_global_del); + hna_global_hash = NULL; +} + +struct orig_node *transtable_search(uint8_t *addr) +{ + struct hna_global_entry *hna_global_entry; + unsigned long flags; + + spin_lock_irqsave(&hna_global_hash_lock, flags); + hna_global_entry = (struct hna_global_entry *) + hash_find(hna_global_hash, addr); + spin_unlock_irqrestore(&hna_global_hash_lock, flags); + + if (hna_global_entry == NULL) + return NULL; + + return hna_global_entry->orig_node; +} diff --git a/drivers/staging/batman-adv/translation-table.h b/drivers/staging/batman-adv/translation-table.h new file mode 100644 index 0000000000000000000000000000000000000000..f7da81129318d10c60b384ab3a54d0dc70c1fa6f --- /dev/null +++ b/drivers/staging/batman-adv/translation-table.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "types.h" + +int hna_local_init(void); +void hna_local_add(uint8_t *addr); +int hna_local_fill_buffer(unsigned char *buff, int buff_len); +int hna_local_fill_buffer_text(unsigned char *buff, int buff_len); +void hna_local_purge(struct work_struct *work); +void hna_local_free(void); +int hna_global_init(void); +void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff, + int hna_buff_len); +int hna_global_fill_buffer_text(unsigned char *buff, int buff_len); +void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, + char *orig_str); +void hna_global_del_orig(struct orig_node *orig_node, char *message); +void hna_global_free(void); +struct orig_node *transtable_search(uint8_t *addr); + +extern spinlock_t hna_local_hash_lock; +extern struct hashtable_t *hna_local_hash; +extern atomic_t hna_local_changed; diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h new file mode 100644 index 0000000000000000000000000000000000000000..3a0ef0c38c93ae86994358d413f6fad4cf5e07b6 --- /dev/null +++ b/drivers/staging/batman-adv/types.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + + + + + +#ifndef TYPES_H +#define TYPES_H + +#include "packet.h" +#include "bitarray.h" + +#define BAT_HEADER_LEN (sizeof(struct ethhdr) + ((sizeof(struct unicast_packet) > sizeof(struct bcast_packet) ? sizeof(struct unicast_packet) : sizeof(struct bcast_packet)))) + + +struct batman_if { + struct list_head list; + int16_t if_num; + char *dev; + char if_active; + char addr_str[ETH_STR_LEN]; + struct net_device *net_dev; + struct socket *raw_sock; + atomic_t seqno; + unsigned char *packet_buff; + int packet_len; + struct rcu_head rcu; + +}; + +struct orig_node { /* structure for orig_list maintaining nodes of mesh */ + uint8_t orig[ETH_ALEN]; + struct neigh_node *router; + struct batman_if *batman_if; + TYPE_OF_WORD *bcast_own; + uint8_t *bcast_own_sum; + uint8_t tq_own; + int tq_asym_penalty; + unsigned long last_valid; /* when last packet from this node was received */ +/* uint8_t gwflags; * flags related to gateway functions: gateway class */ + uint8_t flags; /* for now only VIS_SERVER flag. */ + unsigned char *hna_buff; + int16_t hna_buff_len; + uint16_t last_real_seqno; /* last and best known squence number */ + uint8_t last_ttl; /* ttl of last received packet */ + TYPE_OF_WORD bcast_bits[NUM_WORDS]; + uint16_t last_bcast_seqno; /* last broadcast sequence number received by this host */ + struct list_head neigh_list; +}; + +struct neigh_node { + struct list_head list; + uint8_t addr[ETH_ALEN]; + uint8_t real_packet_count; + uint8_t tq_recv[TQ_GLOBAL_WINDOW_SIZE]; + uint8_t tq_index; + uint8_t tq_avg; + uint8_t last_ttl; + unsigned long last_valid; /* when last packet via this neighbour was received */ + TYPE_OF_WORD real_bits[NUM_WORDS]; + struct orig_node *orig_node; + struct batman_if *if_incoming; +}; + +struct bat_priv { + struct net_device_stats stats; +}; + +struct device_client { + struct list_head queue_list; + unsigned int queue_len; + unsigned char index; + spinlock_t lock; + wait_queue_head_t queue_wait; +}; + +struct device_packet { + struct list_head list; + struct icmp_packet icmp_packet; +}; + +struct hna_local_entry { + uint8_t addr[ETH_ALEN]; + unsigned long last_seen; + char never_purge; +}; + +struct hna_global_entry { + uint8_t addr[ETH_ALEN]; + struct orig_node *orig_node; +}; + +struct forw_packet { /* structure for forw_list maintaining packets to be send/forwarded */ + struct hlist_node list; + unsigned long send_time; + uint8_t own; + unsigned char *packet_buff; + uint16_t packet_len; + uint32_t direct_link_flags; + uint8_t num_packets; + struct delayed_work delayed_work; + struct batman_if *if_incoming; +}; + +#endif diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c new file mode 100644 index 0000000000000000000000000000000000000000..f6c9acb289ed9cdc5e30bca3d51c8dccd8012c47 --- /dev/null +++ b/drivers/staging/batman-adv/vis.c @@ -0,0 +1,564 @@ +/* + * Copyright (C) 2008-2009 B.A.T.M.A.N. contributors: + * + * Simon Wunderlich + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "send.h" +#include "translation-table.h" +#include "vis.h" +#include "log.h" +#include "soft-interface.h" +#include "hard-interface.h" +#include "hash.h" +#include "compat.h" + +struct hashtable_t *vis_hash; +DEFINE_SPINLOCK(vis_hash_lock); +static struct vis_info *my_vis_info; +static struct list_head send_list; /* always locked with vis_hash_lock */ + +static void start_vis_timer(void); + +/* free the info */ +static void free_info(void *data) +{ + struct vis_info *info = data; + struct recvlist_node *entry, *tmp; + + list_del_init(&info->send_list); + list_for_each_entry_safe(entry, tmp, &info->recv_list, list) { + list_del(&entry->list); + kfree(entry); + } + kfree(info); +} + +/* set the mode of the visualization to client or server */ +void vis_set_mode(int mode) +{ + spin_lock(&vis_hash_lock); + + if (my_vis_info != NULL) + my_vis_info->packet.vis_type = mode; + + spin_unlock(&vis_hash_lock); +} + +/* is_vis_server(), locked outside */ +static int is_vis_server_locked(void) +{ + if (my_vis_info != NULL) + if (my_vis_info->packet.vis_type == VIS_TYPE_SERVER_SYNC) + return 1; + + return 0; +} + +/* get the current set mode */ +int is_vis_server(void) +{ + int ret = 0; + + spin_lock(&vis_hash_lock); + ret = is_vis_server_locked(); + spin_unlock(&vis_hash_lock); + + return ret; +} + +/* Compare two vis packets, used by the hashing algorithm */ +static int vis_info_cmp(void *data1, void *data2) +{ + struct vis_info *d1, *d2; + d1 = data1; + d2 = data2; + return compare_orig(d1->packet.vis_orig, d2->packet.vis_orig); +} + +/* hash function to choose an entry in a hash table of given size */ +/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */ +static int vis_info_choose(void *data, int size) +{ + struct vis_info *vis_info = data; + unsigned char *key; + uint32_t hash = 0; + size_t i; + + key = vis_info->packet.vis_orig; + for (i = 0; i < ETH_ALEN; i++) { + hash += key[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + + return hash % size; +} + +/* tries to add one entry to the receive list. */ +static void recv_list_add(struct list_head *recv_list, char *mac) +{ + struct recvlist_node *entry; + entry = kmalloc(sizeof(struct recvlist_node), GFP_ATOMIC); + if (!entry) + return; + + memcpy(entry->mac, mac, ETH_ALEN); + list_add_tail(&entry->list, recv_list); +} + +/* returns 1 if this mac is in the recv_list */ +static int recv_list_is_in(struct list_head *recv_list, char *mac) +{ + struct recvlist_node *entry; + + list_for_each_entry(entry, recv_list, list) { + if (memcmp(entry->mac, mac, ETH_ALEN) == 0) + return 1; + } + + return 0; +} + +/* try to add the packet to the vis_hash. return NULL if invalid (e.g. too old, + * broken.. ). vis hash must be locked outside. is_new is set when the packet + * is newer than old entries in the hash. */ +static struct vis_info *add_packet(struct vis_packet *vis_packet, + int vis_info_len, int *is_new) +{ + struct vis_info *info, *old_info; + struct vis_info search_elem; + + *is_new = 0; + /* sanity check */ + if (vis_hash == NULL) + return NULL; + + /* see if the packet is already in vis_hash */ + memcpy(search_elem.packet.vis_orig, vis_packet->vis_orig, ETH_ALEN); + old_info = hash_find(vis_hash, &search_elem); + + if (old_info != NULL) { + if (vis_packet->seqno - old_info->packet.seqno <= 0) { + if (old_info->packet.seqno == vis_packet->seqno) { + recv_list_add(&old_info->recv_list, + vis_packet->sender_orig); + return old_info; + } else { + /* newer packet is already in hash. */ + return NULL; + } + } + /* remove old entry */ + hash_remove(vis_hash, old_info); + free_info(old_info); + } + + info = kmalloc(sizeof(struct vis_info) + vis_info_len, GFP_ATOMIC); + if (info == NULL) + return NULL; + + INIT_LIST_HEAD(&info->send_list); + INIT_LIST_HEAD(&info->recv_list); + info->first_seen = jiffies; + memcpy(&info->packet, vis_packet, + sizeof(struct vis_packet) + vis_info_len); + + /* initialize and add new packet. */ + *is_new = 1; + + /* repair if entries is longer than packet. */ + if (info->packet.entries * sizeof(struct vis_info_entry) > vis_info_len) + info->packet.entries = vis_info_len / sizeof(struct vis_info_entry); + + recv_list_add(&info->recv_list, info->packet.sender_orig); + + /* try to add it */ + if (hash_add(vis_hash, info) < 0) { + /* did not work (for some reason) */ + free_info(info); + info = NULL; + } + + return info; +} + +/* handle the server sync packet, forward if needed. */ +void receive_server_sync_packet(struct vis_packet *vis_packet, int vis_info_len) +{ + struct vis_info *info; + int is_new; + + spin_lock(&vis_hash_lock); + info = add_packet(vis_packet, vis_info_len, &is_new); + if (info == NULL) + goto end; + + /* only if we are server ourselves and packet is newer than the one in + * hash.*/ + if (is_vis_server_locked() && is_new) { + memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); + if (list_empty(&info->send_list)) + list_add_tail(&info->send_list, &send_list); + } +end: + spin_unlock(&vis_hash_lock); +} + +/* handle an incoming client update packet and schedule forward if needed. */ +void receive_client_update_packet(struct vis_packet *vis_packet, + int vis_info_len) +{ + struct vis_info *info; + int is_new; + + /* clients shall not broadcast. */ + if (is_bcast(vis_packet->target_orig)) + return; + + spin_lock(&vis_hash_lock); + info = add_packet(vis_packet, vis_info_len, &is_new); + if (info == NULL) + goto end; + /* note that outdated packets will be dropped at this point. */ + + + /* send only if we're the target server or ... */ + if (is_vis_server_locked() && + is_my_mac(info->packet.target_orig) && + is_new) { + info->packet.vis_type = VIS_TYPE_SERVER_SYNC; /* upgrade! */ + memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); + if (list_empty(&info->send_list)) + list_add_tail(&info->send_list, &send_list); + + /* ... we're not the recipient (and thus need to forward). */ + } else if (!is_my_mac(info->packet.target_orig)) { + if (list_empty(&info->send_list)) + list_add_tail(&info->send_list, &send_list); + } +end: + spin_unlock(&vis_hash_lock); +} + +/* Walk the originators and find the VIS server with the best tq. Set the packet + * address to its address and return the best_tq. + * + * Must be called with the originator hash locked */ +static int find_best_vis_server(struct vis_info *info) +{ + struct hash_it_t *hashit = NULL; + struct orig_node *orig_node; + int best_tq = -1; + + while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { + orig_node = hashit->bucket->data; + if ((orig_node != NULL) && + (orig_node->router != NULL) && + (orig_node->flags & VIS_SERVER) && + (orig_node->router->tq_avg > best_tq)) { + best_tq = orig_node->router->tq_avg; + memcpy(info->packet.target_orig, orig_node->orig, + ETH_ALEN); + } + } + return best_tq; +} + +/* Return true if the vis packet is full. */ +static bool vis_packet_full(struct vis_info *info) +{ + if (info->packet.entries + 1 > + (1000 - sizeof(struct vis_info)) / sizeof(struct vis_info_entry)) + return true; + return false; +} + +/* generates a packet of own vis data, + * returns 0 on success, -1 if no packet could be generated */ +static int generate_vis_packet(void) +{ + struct hash_it_t *hashit = NULL; + struct orig_node *orig_node; + struct vis_info *info = (struct vis_info *)my_vis_info; + struct vis_info_entry *entry, *entry_array; + struct hna_local_entry *hna_local_entry; + int best_tq = -1; + unsigned long flags; + + info->first_seen = jiffies; + + spin_lock(&orig_hash_lock); + memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); + info->packet.ttl = TTL; + info->packet.seqno++; + info->packet.entries = 0; + + if (!is_vis_server_locked()) { + best_tq = find_best_vis_server(info); + if (best_tq < 0) { + spin_unlock(&orig_hash_lock); + return -1; + } + } + hashit = NULL; + + entry_array = (struct vis_info_entry *) + ((char *)info + sizeof(struct vis_info)); + + while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { + orig_node = hashit->bucket->data; + if (orig_node->router != NULL + && compare_orig(orig_node->router->addr, orig_node->orig) + && orig_node->batman_if + && (orig_node->batman_if->if_active == IF_ACTIVE) + && orig_node->router->tq_avg > 0) { + + /* fill one entry into buffer. */ + entry = &entry_array[info->packet.entries]; + memcpy(entry->src, orig_node->batman_if->net_dev->dev_addr, ETH_ALEN); + memcpy(entry->dest, orig_node->orig, ETH_ALEN); + entry->quality = orig_node->router->tq_avg; + info->packet.entries++; + + if (vis_packet_full(info)) { + spin_unlock(&orig_hash_lock); + return 0; + } + } + } + + spin_unlock(&orig_hash_lock); + + hashit = NULL; + spin_lock_irqsave(&hna_local_hash_lock, flags); + while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) { + hna_local_entry = hashit->bucket->data; + entry = &entry_array[info->packet.entries]; + memset(entry->src, 0, ETH_ALEN); + memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN); + entry->quality = 0; /* 0 means HNA */ + info->packet.entries++; + + if (vis_packet_full(info)) { + spin_unlock_irqrestore(&hna_local_hash_lock, flags); + return 0; + } + } + spin_unlock_irqrestore(&hna_local_hash_lock, flags); + return 0; +} + +static void purge_vis_packets(void) +{ + struct hash_it_t *hashit = NULL; + struct vis_info *info; + + while (NULL != (hashit = hash_iterate(vis_hash, hashit))) { + info = hashit->bucket->data; + if (info == my_vis_info) /* never purge own data. */ + continue; + if (time_after(jiffies, + info->first_seen + (VIS_TIMEOUT/1000)*HZ)) { + hash_remove_bucket(vis_hash, hashit); + free_info(info); + } + } +} + +static void broadcast_vis_packet(struct vis_info *info, int packet_length) +{ + struct hash_it_t *hashit = NULL; + struct orig_node *orig_node; + + spin_lock(&orig_hash_lock); + + /* send to all routers in range. */ + while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { + orig_node = hashit->bucket->data; + + /* if it's a vis server and reachable, send it. */ + if (orig_node && + (orig_node->flags & VIS_SERVER) && + orig_node->batman_if && + orig_node->router) { + + /* don't send it if we already received the packet from + * this node. */ + if (recv_list_is_in(&info->recv_list, orig_node->orig)) + continue; + + memcpy(info->packet.target_orig, + orig_node->orig, ETH_ALEN); + + send_raw_packet((unsigned char *) &info->packet, + packet_length, + orig_node->batman_if, + orig_node->router->addr); + } + } + memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); + spin_unlock(&orig_hash_lock); +} + +static void unicast_vis_packet(struct vis_info *info, int packet_length) +{ + struct orig_node *orig_node; + + spin_lock(&orig_hash_lock); + orig_node = ((struct orig_node *) + hash_find(orig_hash, info->packet.target_orig)); + + if ((orig_node != NULL) && + (orig_node->batman_if != NULL) && + (orig_node->router != NULL)) { + send_raw_packet((unsigned char *) &info->packet, packet_length, + orig_node->batman_if, + orig_node->router->addr); + } + spin_unlock(&orig_hash_lock); +} + +/* only send one vis packet. called from send_vis_packets() */ +static void send_vis_packet(struct vis_info *info) +{ + int packet_length; + + if (info->packet.ttl < 2) { + debug_log(LOG_TYPE_NOTICE, + "Error - can't send vis packet: ttl exceeded\n"); + return; + } + + memcpy(info->packet.sender_orig, mainIfAddr, ETH_ALEN); + info->packet.ttl--; + + packet_length = sizeof(struct vis_packet) + + info->packet.entries * sizeof(struct vis_info_entry); + + if (is_bcast(info->packet.target_orig)) + broadcast_vis_packet(info, packet_length); + else + unicast_vis_packet(info, packet_length); + info->packet.ttl++; /* restore TTL */ +} + +/* called from timer; send (and maybe generate) vis packet. */ +static void send_vis_packets(struct work_struct *work) +{ + struct vis_info *info, *temp; + + spin_lock(&vis_hash_lock); + purge_vis_packets(); + + if (generate_vis_packet() == 0) + /* schedule if generation was successful */ + list_add_tail(&my_vis_info->send_list, &send_list); + + list_for_each_entry_safe(info, temp, &send_list, send_list) { + list_del_init(&info->send_list); + send_vis_packet(info); + } + spin_unlock(&vis_hash_lock); + start_vis_timer(); +} +static DECLARE_DELAYED_WORK(vis_timer_wq, send_vis_packets); + +/* init the vis server. this may only be called when if_list is already + * initialized (e.g. bat0 is initialized, interfaces have been added) */ +int vis_init(void) +{ + if (vis_hash) + return 1; + + spin_lock(&vis_hash_lock); + + vis_hash = hash_new(256, vis_info_cmp, vis_info_choose); + if (!vis_hash) { + debug_log(LOG_TYPE_CRIT, "Can't initialize vis_hash\n"); + goto err; + } + + my_vis_info = kmalloc(1000, GFP_ATOMIC); + if (!my_vis_info) { + debug_log(LOG_TYPE_CRIT, "Can't initialize vis packet\n"); + goto err; + } + + /* prefill the vis info */ + my_vis_info->first_seen = jiffies - atomic_read(&vis_interval); + INIT_LIST_HEAD(&my_vis_info->recv_list); + INIT_LIST_HEAD(&my_vis_info->send_list); + my_vis_info->packet.version = COMPAT_VERSION; + my_vis_info->packet.packet_type = BAT_VIS; + my_vis_info->packet.vis_type = VIS_TYPE_CLIENT_UPDATE; + my_vis_info->packet.ttl = TTL; + my_vis_info->packet.seqno = 0; + my_vis_info->packet.entries = 0; + + INIT_LIST_HEAD(&send_list); + + memcpy(my_vis_info->packet.vis_orig, mainIfAddr, ETH_ALEN); + memcpy(my_vis_info->packet.sender_orig, mainIfAddr, ETH_ALEN); + + if (hash_add(vis_hash, my_vis_info) < 0) { + debug_log(LOG_TYPE_CRIT, + "Can't add own vis packet into hash\n"); + free_info(my_vis_info); /* not in hash, need to remove it + * manually. */ + goto err; + } + + spin_unlock(&vis_hash_lock); + start_vis_timer(); + return 1; + +err: + spin_unlock(&vis_hash_lock); + vis_quit(); + return 0; +} + +/* shutdown vis-server */ +void vis_quit(void) +{ + if (!vis_hash) + return; + + cancel_delayed_work_sync(&vis_timer_wq); + + spin_lock(&vis_hash_lock); + /* properly remove, kill timers ... */ + hash_delete(vis_hash, free_info); + vis_hash = NULL; + my_vis_info = NULL; + spin_unlock(&vis_hash_lock); +} + +/* schedule packets for (re)transmission */ +static void start_vis_timer(void) +{ + queue_delayed_work(bat_event_workqueue, &vis_timer_wq, + (atomic_read(&vis_interval)/1000) * HZ); +} + diff --git a/drivers/staging/batman-adv/vis.h b/drivers/staging/batman-adv/vis.h new file mode 100644 index 0000000000000000000000000000000000000000..276fabab4e8803386ff42eaf7e6667c1d699e59f --- /dev/null +++ b/drivers/staging/batman-adv/vis.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008-2009 B.A.T.M.A.N. contributors: + * + * Simon Wunderlich, Marek Lindner + * + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#define VIS_TIMEOUT 200000 +#define VIS_FORMAT_DD_NAME "dot_draw" +#define VIS_FORMAT_JSON_NAME "json" + +struct vis_info { + unsigned long first_seen; + struct list_head recv_list; + /* list of server-neighbors we received a vis-packet + * from. we should not reply to them. */ + struct list_head send_list; + /* this packet might be part of the vis send queue. */ + struct vis_packet packet; + /* vis_info may follow here*/ +} __attribute__((packed)); + +struct vis_info_entry { + uint8_t src[ETH_ALEN]; + uint8_t dest[ETH_ALEN]; + uint8_t quality; /* quality = 0 means HNA */ +} __attribute__((packed)); + +struct recvlist_node { + struct list_head list; + uint8_t mac[ETH_ALEN]; +}; + +enum vis_formats { + DOT_DRAW, + JSON, +}; + +extern struct hashtable_t *vis_hash; +extern spinlock_t vis_hash_lock; + +void vis_set_mode(int mode); +int is_vis_server(void); +void receive_server_sync_packet(struct vis_packet *vis_packet, + int vis_info_len); +void receive_client_update_packet(struct vis_packet *vis_packet, + int vis_info_len); +int vis_init(void); +void vis_quit(void); diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index 957b6405dfa744bfd50a403c831bae58d478e17e..ccc5cdc008c6eaf3e7323afd677f5b9775a0ad7f 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -24,10 +24,6 @@ #ifndef _COMEDI_H #define _COMEDI_H -#ifdef __cplusplus -extern "C" { -#endif - #define COMEDI_MAJORVERSION 0 #define COMEDI_MINORVERSION 7 #define COMEDI_MICROVERSION 76 @@ -871,8 +867,4 @@ INSN_CONFIG_ARM */ AMPLC_DIO_GAT_RESERVED7 }; -#ifdef __cplusplus -} -#endif - #endif /* _COMEDI_H */ diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index 9810e37845c7ab48e4d3cef8f215dd4bfab6fac5..a9fdcda5db7af4f9ccd4613c88a83232c7083243 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -27,16 +27,12 @@ #define __NO_VERSION__ #include "comedi.h" #include -#include +#include #include "comedi_compat32.h" #ifdef CONFIG_COMPAT -#ifndef HAVE_COMPAT_IOCTL -#include /* for (un)register_ioctl32_conversion */ -#endif - #define COMEDI32_CHANINFO _IOR(CIO, 3, struct comedi32_chaninfo_struct) #define COMEDI32_RANGEINFO _IOR(CIO, 8, struct comedi32_rangeinfo_struct) /* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR. @@ -101,22 +97,9 @@ static int translated_ioctl(struct file *file, unsigned int cmd, if (!file->f_op) return -ENOTTY; -#ifdef HAVE_UNLOCKED_IOCTL - if (file->f_op->unlocked_ioctl) { - int rc = (int)(*file->f_op->unlocked_ioctl) (file, cmd, arg); - if (rc == -ENOIOCTLCMD) - rc = -ENOTTY; - return rc; - } -#endif - if (file->f_op->ioctl) { - int rc; - lock_kernel(); - rc = (*file->f_op->ioctl) (file->f_dentry->d_inode, - file, cmd, arg); - unlock_kernel(); - return rc; - } + if (file->f_op->unlocked_ioctl) + return file->f_op->unlocked_ioctl(file, cmd, arg); + return -ENOTTY; } @@ -186,8 +169,8 @@ static int compat_rangeinfo(struct file *file, unsigned long arg) } /* Copy 32-bit cmd structure to native cmd structure. */ -static int get_compat_cmd(struct comedi_cmd __user * cmd, - struct comedi32_cmd_struct __user * cmd32) +static int get_compat_cmd(struct comedi_cmd __user *cmd, + struct comedi32_cmd_struct __user *cmd32) { int err; union { @@ -237,8 +220,8 @@ static int get_compat_cmd(struct comedi_cmd __user * cmd, } /* Copy native cmd structure to 32-bit cmd structure. */ -static int put_compat_cmd(struct comedi32_cmd_struct __user * cmd32, - struct comedi_cmd __user * cmd) +static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, + struct comedi_cmd __user *cmd) { int err; unsigned int temp; @@ -328,8 +311,8 @@ static int compat_cmdtest(struct file *file, unsigned long arg) } /* Copy 32-bit insn structure to native insn structure. */ -static int get_compat_insn(struct comedi_insn __user * insn, - struct comedi32_insn_struct __user * insn32) +static int get_compat_insn(struct comedi_insn __user *insn, + struct comedi32_insn_struct __user *insn32) { int err; union { @@ -372,9 +355,9 @@ static int compat_insnlist(struct file *file, unsigned long arg) insnlist32 = compat_ptr(arg); /* Get 32-bit insnlist structure. */ - if (!access_ok(VERIFY_READ, insnlist32, sizeof(*insnlist32))) { + if (!access_ok(VERIFY_READ, insnlist32, sizeof(*insnlist32))) return -EFAULT; - } + err = 0; err |= __get_user(n_insns, &insnlist32->n_insns); err |= __get_user(uptr, &insnlist32->insns); @@ -387,9 +370,9 @@ static int compat_insnlist(struct file *file, unsigned long arg) insn[n_insns])); /* Set native insnlist structure. */ - if (!access_ok(VERIFY_WRITE, &s->insnlist, sizeof(s->insnlist))) { + if (!access_ok(VERIFY_WRITE, &s->insnlist, sizeof(s->insnlist))) return -EFAULT; - } + err |= __put_user(n_insns, &s->insnlist.n_insns); err |= __put_user(&s->insn[0], &s->insnlist.insns); if (err) @@ -472,8 +455,6 @@ static inline int raw_ioctl(struct file *file, unsigned int cmd, return rc; } -#ifdef HAVE_COMPAT_IOCTL /* defined in 2.6.11 onwards */ - /* compat_ioctl file operation. */ /* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */ long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) @@ -481,106 +462,4 @@ long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return raw_ioctl(file, cmd, arg); } -#else /* HAVE_COMPAT_IOCTL */ - -/* - * Brain-dead ioctl compatibility for 2.6.10 and earlier. - * - * It's brain-dead because cmd numbers need to be unique system-wide! - * The comedi driver could end up attempting to execute ioctls for non-Comedi - * devices because it registered the system-wide cmd code first. Similarly, - * another driver could end up attempting to execute ioctls for a Comedi - * device because it registered the cmd code first. Chaos ensues. - */ - -/* Handler for all 32-bit ioctl codes registered by this driver. */ -static int mapped_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, - struct file *file) -{ - int rc; - - /* Make sure we are dealing with a Comedi device. */ - if (imajor(file->f_dentry->d_inode) != COMEDI_MAJOR) - return -ENOTTY; - - rc = raw_ioctl(file, cmd, arg); - /* Do not return -ENOIOCTLCMD. */ - if (rc == -ENOIOCTLCMD) - rc = -ENOTTY; - - return rc; -} - -struct ioctl32_map { - unsigned int cmd; - int (*handler) (unsigned int, unsigned int, unsigned long, - struct file *); - int registered; -}; - -static struct ioctl32_map comedi_ioctl32_map[] = { - {COMEDI_DEVCONFIG, mapped_ioctl, 0}, - {COMEDI_DEVINFO, mapped_ioctl, 0}, - {COMEDI_SUBDINFO, mapped_ioctl, 0}, - {COMEDI_BUFCONFIG, mapped_ioctl, 0}, - {COMEDI_BUFINFO, mapped_ioctl, 0}, - {COMEDI_LOCK, mapped_ioctl, 0}, - {COMEDI_UNLOCK, mapped_ioctl, 0}, - {COMEDI_CANCEL, mapped_ioctl, 0}, - {COMEDI_POLL, mapped_ioctl, 0}, - {COMEDI32_CHANINFO, mapped_ioctl, 0}, - {COMEDI32_RANGEINFO, mapped_ioctl, 0}, - {COMEDI32_CMD, mapped_ioctl, 0}, - {COMEDI32_CMDTEST, mapped_ioctl, 0}, - {COMEDI32_INSNLIST, mapped_ioctl, 0}, - {COMEDI32_INSN, mapped_ioctl, 0}, -}; - -#define NUM_IOCTL32_MAPS ARRAY_SIZE(comedi_ioctl32_map) - -/* Register system-wide 32-bit ioctl handlers. */ -void comedi_register_ioctl32(void) -{ - int n, rc; - - for (n = 0; n < NUM_IOCTL32_MAPS; n++) { - rc = register_ioctl32_conversion(comedi_ioctl32_map[n].cmd, - comedi_ioctl32_map[n].handler); - if (rc) { - printk(KERN_WARNING - "comedi: failed to register 32-bit " - "compatible ioctl handler for 0x%X - " - "expect bad things to happen!\n", - comedi_ioctl32_map[n].cmd); - } - comedi_ioctl32_map[n].registered = !rc; - } -} - -/* Unregister system-wide 32-bit ioctl translations. */ -void comedi_unregister_ioctl32(void) -{ - int n, rc; - - for (n = 0; n < NUM_IOCTL32_MAPS; n++) { - if (comedi_ioctl32_map[n].registered) { - rc = unregister_ioctl32_conversion(comedi_ioctl32_map - [n].cmd, - comedi_ioctl32_map - [n].handler); - if (rc) { - printk(KERN_ERR - "comedi: failed to unregister 32-bit " - "compatible ioctl handler for 0x%X - " - "expect kernel Oops!\n", - comedi_ioctl32_map[n].cmd); - } else { - comedi_ioctl32_map[n].registered = 0; - } - } - } -} - -#endif /* HAVE_COMPAT_IOCTL */ - #endif /* CONFIG_COMPAT */ diff --git a/drivers/staging/comedi/comedi_compat32.h b/drivers/staging/comedi/comedi_compat32.h index fd0f8a3125a14681a1b3ebebbf3e9c4a410e53fe..0340a8949c6bad183269d8bb83e0160b9acce133 100644 --- a/drivers/staging/comedi/comedi_compat32.h +++ b/drivers/staging/comedi/comedi_compat32.h @@ -28,30 +28,16 @@ #define _COMEDI_COMPAT32_H #include -#include /* For HAVE_COMPAT_IOCTL and HAVE_UNLOCKED_IOCTL */ +#include #ifdef CONFIG_COMPAT -#ifdef HAVE_COMPAT_IOCTL - extern long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -#define comedi_register_ioctl32() do {} while (0) -#define comedi_unregister_ioctl32() do {} while (0) - -#else /* HAVE_COMPAT_IOCTL */ - -#define comedi_compat_ioctl 0 /* NULL */ -extern void comedi_register_ioctl32(void); -extern void comedi_unregister_ioctl32(void); - -#endif /* HAVE_COMPAT_IOCTL */ #else /* CONFIG_COMPAT */ #define comedi_compat_ioctl 0 /* NULL */ -#define comedi_register_ioctl32() do {} while (0) -#define comedi_unregister_ioctl32() do {} while (0) #endif /* CONFIG_COMPAT */ diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index aaad76e0a76a351f6b26a508982dbbfa9787c7a9..8117748ad5a5ec50fd1ea2963adc3078b1ab8632 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -110,13 +110,8 @@ static struct device_attribute dev_attr_read_buffer_kb; static struct device_attribute dev_attr_max_write_buffer_kb; static struct device_attribute dev_attr_write_buffer_kb; -#ifdef HAVE_UNLOCKED_IOCTL static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -#else -static int comedi_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -#endif { const unsigned minor = iminor(file->f_dentry->d_inode); struct comedi_device_file_info *dev_file_info = @@ -1867,14 +1862,8 @@ static int comedi_fasync(int fd, struct file *file, int on) const struct file_operations comedi_fops = { .owner = THIS_MODULE, -#ifdef HAVE_UNLOCKED_IOCTL .unlocked_ioctl = comedi_unlocked_ioctl, -#else - .ioctl = comedi_ioctl, -#endif -#ifdef HAVE_COMPAT_IOCTL .compat_ioctl = comedi_compat_ioctl, -#endif .open = comedi_open, .release = comedi_close, .read = comedi_read, @@ -1959,8 +1948,6 @@ static int __init comedi_init(void) } } - comedi_register_ioctl32(); - return 0; } @@ -1977,8 +1964,6 @@ static void __exit comedi_cleanup(void) unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS); comedi_proc_cleanup(); - - comedi_unregister_ioctl32(); } module_init(comedi_init); diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index e8a5f7d33e7a475b96ea5942d49bbcb8acc49375..ebdccfdf220ea64f5671470cca30c0b3a806b793 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -49,7 +49,8 @@ } while (0) #define COMEDI_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) -#define COMEDI_VERSION_CODE COMEDI_VERSION(COMEDI_MAJORVERSION, COMEDI_MINORVERSION, COMEDI_MICROVERSION) +#define COMEDI_VERSION_CODE COMEDI_VERSION(COMEDI_MAJORVERSION, \ + COMEDI_MINORVERSION, COMEDI_MICROVERSION) #define COMEDI_RELEASE VERSION #define COMEDI_INITCLEANUP_NOMODULE(x) \ @@ -58,12 +59,12 @@ static void __exit x ## _cleanup_module(void) \ {comedi_driver_unregister(&(x)); } \ module_init(x ## _init_module); \ - module_exit(x ## _cleanup_module); \ + module_exit(x ## _cleanup_module); #define COMEDI_MODULE_MACROS \ MODULE_AUTHOR("Comedi http://www.comedi.org"); \ MODULE_DESCRIPTION("Comedi low-level driver"); \ - MODULE_LICENSE("GPL"); \ + MODULE_LICENSE("GPL"); #define COMEDI_INITCLEANUP(x) \ COMEDI_MODULE_MACROS \ @@ -75,7 +76,8 @@ { \ return comedi_pci_auto_config(dev, comedi_driver.driver_name); \ } \ - static void __devexit comedi_driver ## _pci_remove(struct pci_dev *dev) \ + static void __devexit comedi_driver ## _pci_remove(\ + struct pci_dev *dev) \ { \ comedi_pci_auto_unconfig(dev); \ } \ @@ -91,7 +93,8 @@ retval = comedi_driver_register(&comedi_driver); \ if (retval < 0) \ return retval; \ - comedi_driver ## _pci_driver.name = (char *)comedi_driver.driver_name; \ + comedi_driver ## _pci_driver.name = \ + (char *)comedi_driver.driver_name; \ return pci_register_driver(&comedi_driver ## _pci_driver); \ } \ static void __exit comedi_driver ## _cleanup_module(void) \ @@ -170,14 +173,15 @@ struct comedi_subdevice { struct comedi_cmd *); int (*poll) (struct comedi_device *, struct comedi_subdevice *); int (*cancel) (struct comedi_device *, struct comedi_subdevice *); - /* int (*do_lock)(struct comedi_device *,struct comedi_subdevice *); */ - /* int (*do_unlock)(struct comedi_device *,struct comedi_subdevice *); */ + /* int (*do_lock)(struct comedi_device *, struct comedi_subdevice *); */ + /* int (*do_unlock)(struct comedi_device *, \ + struct comedi_subdevice *); */ /* called when the buffer changes */ - int (*buf_change) (struct comedi_device * dev, - struct comedi_subdevice * s, unsigned long new_size); + int (*buf_change) (struct comedi_device *dev, + struct comedi_subdevice *s, unsigned long new_size); - void (*munge) (struct comedi_device * dev, struct comedi_subdevice * s, + void (*munge) (struct comedi_device *dev, struct comedi_subdevice *s, void *data, unsigned int num_bytes, unsigned int start_chan_index); enum dma_data_direction async_dma_dir; @@ -198,16 +202,22 @@ struct comedi_async { void *prealloc_buf; /* pre-allocated buffer */ unsigned int prealloc_bufsz; /* buffer size, in bytes */ - struct comedi_buf_page *buf_page_list; /* virtual and dma address of each page */ + /* virtual and dma address of each page */ + struct comedi_buf_page *buf_page_list; unsigned n_buf_pages; /* num elements in buf_page_list */ unsigned int max_bufsize; /* maximum buffer size, bytes */ - unsigned int mmap_count; /* current number of mmaps of prealloc_buf */ - - unsigned int buf_write_count; /* byte count for writer (write completed) */ - unsigned int buf_write_alloc_count; /* byte count for writer (allocated for writing) */ - unsigned int buf_read_count; /* byte count for reader (read completed) */ - unsigned int buf_read_alloc_count; /* byte count for reader (allocated for reading) */ + /* current number of mmaps of prealloc_buf */ + unsigned int mmap_count; + + /* byte count for writer (write completed) */ + unsigned int buf_write_count; + /* byte count for writer (allocated for writing) */ + unsigned int buf_write_alloc_count; + /* byte count for reader (read completed) */ + unsigned int buf_read_count; + /* byte count for reader (allocated for reading) */ + unsigned int buf_read_alloc_count; unsigned int buf_write_ptr; /* buffer marker for writer */ unsigned int buf_read_ptr; /* buffer marker for reader */ @@ -233,7 +243,7 @@ struct comedi_async { int (*cb_func) (unsigned int flags, void *); void *cb_arg; - int (*inttrig) (struct comedi_device * dev, struct comedi_subdevice * s, + int (*inttrig) (struct comedi_device *dev, struct comedi_subdevice *s, unsigned int x); }; @@ -283,8 +293,8 @@ struct comedi_device { struct fasync_struct *async_queue; - void (*open) (struct comedi_device * dev); - void (*close) (struct comedi_device * dev); + void (*open) (struct comedi_device *dev); + void (*close) (struct comedi_device *dev); }; struct comedi_device_file_info { @@ -318,9 +328,8 @@ static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1; struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor); -static inline struct comedi_subdevice *comedi_get_read_subdevice(const struct - comedi_device_file_info - *info) +static inline struct comedi_subdevice *comedi_get_read_subdevice( + const struct comedi_device_file_info *info) { if (info->read_subdevice) return info->read_subdevice; @@ -329,9 +338,8 @@ static inline struct comedi_subdevice *comedi_get_read_subdevice(const struct return info->device->read_subdev; } -static inline struct comedi_subdevice *comedi_get_write_subdevice(const struct - comedi_device_file_info - *info) +static inline struct comedi_subdevice *comedi_get_write_subdevice( + const struct comedi_device_file_info *info) { if (info->write_subdevice) return info->write_subdevice; diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index dc53aeeac68f4cc0a66b3024f2e3971337f68d52..c2a632d31c61784f120f9eeb02acf2d642532146 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -387,7 +387,7 @@ static int insn_rw_emulate_bits(struct comedi_device *dev, return 1; } -static inline unsigned long uvirt_to_kva(pgd_t * pgd, unsigned long adr) +static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) { unsigned long ret = 0UL; pmd_t *pmd; diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h index c2ea2d96f1cc7f59cf85426f3980872bc8e362d1..0bb35db4ea3bb5cd7738717ec1be79766532ad94 100644 --- a/drivers/staging/comedi/drivers/8253.h +++ b/drivers/staging/comedi/drivers/8253.h @@ -206,7 +206,8 @@ static inline void i8253_cascade_ns_to_timer_2div(int i8253_osc_base, } *nanosec = div1 * div2 * i8253_osc_base; - *d1 = div1 & 0xffff; /* masking is done since counter maps zero to 0x10000 */ + /* masking is done since counter maps zero to 0x10000 */ + *d1 = div1 & 0xffff; *d2 = div2 & 0xffff; return; } diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 0a50864767e4634368ac47f84c9bf38eaa209b27..10f488f0e5ee732f49f6ad319ad046aa5e637a4a 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -132,6 +132,7 @@ void subdev_8255_interrupt(struct comedi_device *dev, comedi_event(dev, s); } +EXPORT_SYMBOL(subdev_8255_interrupt); static int subdev_8255_cb(int dir, int port, int data, unsigned long arg) { @@ -179,15 +180,14 @@ static int subdev_8255_insn_config(struct comedi_device *dev, unsigned int bits; mask = 1 << CR_CHAN(insn->chanspec); - if (mask & 0x0000ff) { + if (mask & 0x0000ff) bits = 0x0000ff; - } else if (mask & 0x00ff00) { + else if (mask & 0x00ff00) bits = 0x00ff00; - } else if (mask & 0x0f0000) { + else if (mask & 0x0f0000) bits = 0x0f0000; - } else { + else bits = 0xf00000; - } switch (data[0]) { case INSN_CONFIG_DIO_INPUT: @@ -333,11 +333,10 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, return -ENOMEM; CALLBACK_ARG = arg; - if (cb == NULL) { + if (cb == NULL) CALLBACK_FUNC = subdev_8255_cb; - } else { + else CALLBACK_FUNC = cb; - } s->insn_bits = subdev_8255_insn; s->insn_config = subdev_8255_insn_config; @@ -347,6 +346,7 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, return 0; } +EXPORT_SYMBOL(subdev_8255_init); int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s, int (*cb) (int, int, int, unsigned long), @@ -366,6 +366,7 @@ int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s, return 0; } +EXPORT_SYMBOL(subdev_8255_init_irq); void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -378,6 +379,7 @@ void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice *s) kfree(s->private); } } +EXPORT_SYMBOL(subdev_8255_cleanup); /* @@ -448,8 +450,3 @@ static int dev_8255_detach(struct comedi_device *dev) return 0; } - -EXPORT_SYMBOL(subdev_8255_init); -EXPORT_SYMBOL(subdev_8255_init_irq); -EXPORT_SYMBOL(subdev_8255_cleanup); -EXPORT_SYMBOL(subdev_8255_interrupt); diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c index c3652ef19a5fecff1d7bd89f60bfc2c991d58383..e20c3542c069d2a9333af9dcf7e58d23c46ccc43 100644 --- a/drivers/staging/comedi/drivers/acl7225b.c +++ b/drivers/staging/comedi/drivers/acl7225b.c @@ -94,10 +94,11 @@ static int acl7225b_attach(struct comedi_device *dev, iobase = it->options[0]; iorange = this_board->io_range; - printk("comedi%d: acl7225b: board=%s 0x%04x ", dev->minor, + printk(KERN_INFO "comedi%d: acl7225b: board=%s 0x%04x\n", dev->minor, this_board->name, iobase); if (!request_region(iobase, iorange, "acl7225b")) { - printk("I/O port conflict\n"); + printk(KERN_ERR "comedi%d: request_region failed - I/O port conflict\n", + dev->minor); return -EIO; } dev->board_name = this_board->name; @@ -137,14 +138,12 @@ static int acl7225b_attach(struct comedi_device *dev, s->range_table = &range_digital; s->private = (void *)ACL7225_DI_LO; - printk("\n"); - return 0; } static int acl7225b_detach(struct comedi_device *dev) { - printk("comedi%d: acl7225b: remove\n", dev->minor); + printk(KERN_INFO "comedi%d: acl7225b: remove\n", dev->minor); if (dev->iobase) release_region(dev->iobase, this_board->io_range); diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c index ccb109a851f2d67f2b8462bebef2fb34b883164b..0af12fd2a40a79564108914c5a346a25f8cdff30 100644 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c @@ -1386,8 +1386,7 @@ int i_APCI1710_ReadChronoValue(struct comedi_device *dev, /* Test the timout parameter */ /*****************************/ - if ((ui_TimeOut >= 0) - && (ui_TimeOut <= 65535UL)) { + if (ui_TimeOut <= 65535UL) { for (;;) { /*******************/ diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c index 6c092efee7bddc041b2410e9a47ede2efb3c1ab6..a15c952c0fabd3360414d65794d2c4a6d4413804 100644 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c @@ -3807,7 +3807,7 @@ int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev, s_ModuleInfo[b_ModulNbr]. s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { /********************************************/ - /* Test if frequency mesurement initialised */ + /* Test if frequency measurement initialised */ /********************************************/ if (devpriv-> @@ -3953,7 +3953,7 @@ int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev, unsigned c s_ModuleInfo[b_ModulNbr]. s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { /********************************************/ - /* Test if frequency mesurement initialised */ + /* Test if frequency measurement initialised */ /********************************************/ if (devpriv-> @@ -5166,7 +5166,7 @@ int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev, s_ModuleInfo[b_ModulNbr]. s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { /********************************************/ - /* Test if frequency mesurement initialised */ + /* Test if frequency measurement initialised */ /********************************************/ if (devpriv-> diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c index 43198aafb2dcba5d126998f89836b7ec09ae2eae..7e12544757922c7459ca42ed25d78f70b7e0224c 100644 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c @@ -1808,7 +1808,7 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device 2) { if (dw_Status & 4) { /************************/ - /* Tor counter owerflow */ + /* Tor counter overflow */ /************************/ *pb_TorCounterStatus diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h index edd657b902aa70db2dc8dcc1d5d952bba917f3cf..3ab27cf0facc2eee408b9e9d6ef51340434a8766 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.h +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h @@ -82,7 +82,7 @@ struct addi_board { int i_NbrDiChannel; /* Number of DI channels */ int i_NbrDoChannel; /* Number of DO channels */ - int i_DoMaxdata; /* data to set all chanels high */ + int i_DoMaxdata; /* data to set all channels high */ int i_NbrTTLChannel; /* Number of TTL channels */ const struct comedi_lrange *pr_TTLRangelist; /* rangelist for TTL */ diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c index e9021cd4d34161319981f098f3b8b7d59a52c00f..723a97bab44c4605f511d7dfa61763bb06cbe7d4 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c @@ -150,7 +150,7 @@ int i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev unsigned int ui_TmpValue = 0; unsigned int ui_Channel; ui_Channel = CR_CHAN(insn->chanspec); - if (ui_Channel >= 0 && ui_Channel <= 31) { + if (ui_Channel <= 31) { ui_TmpValue = (unsigned int) inl(devpriv->iobase + APCI1032_DIGITAL_IP); /* * since only 1 channel reqd to bring it to last bit it is rotated 8 diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index 236b8a31c82421ef23437d87ed1dec901668171a..36b929ffecbd8ac33a0ed0e56b49c31bb0749c89 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -968,7 +968,7 @@ int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub switch (data[0]) { case 0: - if (ui_Channel >= 0 && ui_Channel <= 15) { + if (ui_Channel <= 15) { ui_TmpValue = (unsigned int) inw(devpriv->i_IobaseAddon + APCI1500_DIGITAL_IP); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c index 38416356628d47e57ac1e0c67ca04812f4fd08ef..866eb8d758203804a3efe03cda1e4cf8b4c68eb0 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c @@ -79,7 +79,7 @@ int i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev unsigned int ui_TmpValue = 0; unsigned int ui_Channel; ui_Channel = CR_CHAN(insn->chanspec); - if (ui_Channel >= 0 && ui_Channel <= 7) { + if (ui_Channel <= 7) { ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI1516_DIGITAL_IP); /* since only 1 channel reqd to bring it to last bit it is rotated */ /* 8 +(chan - 1) times then ANDed with 1 for last bit. */ diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c index 3a47c303422903cffbfd318b768ad833b49d373d..3ae663bc754e8ede587d75c0b012ca995ee1942d 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c @@ -154,7 +154,7 @@ int i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev unsigned int ui_Channel; ui_Channel = CR_CHAN(insn->chanspec); - if (ui_Channel >= 0 && ui_Channel <= 31) { + if (ui_Channel <= 31) { ui_TmpValue = (unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP); /* diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c index 457917f292b76b7a0ee7b5faf814736c45041c54..d348cd5687aa8d62b87686a54d0d757fc1630a2e 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c @@ -117,7 +117,7 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde unsigned int ui_NoOfChannel; unsigned int ui_Temp, ui_Temp1; ui_NoOfChannel = CR_CHAN(insn->chanspec); - if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) { + if (ui_NoOfChannel > 15) { comedi_error(dev, "Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n"); return -EINVAL; @@ -272,7 +272,7 @@ int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdev unsigned int ui_Temp; unsigned int ui_NoOfChannel; ui_NoOfChannel = CR_CHAN(insn->chanspec); - if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) { + if (ui_NoOfChannel > 15) { comedi_error(dev, "Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n"); return -EINVAL; diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c index a853c62a4fd9c52d9988c5655b71bdaacd56e75b..aa159dccc36a858e1c04a303c8831c768406aae4 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c @@ -79,7 +79,7 @@ int i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev unsigned int ui_TmpValue = 0; unsigned int ui_Channel; ui_Channel = CR_CHAN(insn->chanspec); - if (ui_Channel >= 0 && ui_Channel <= 7) { + if (ui_Channel <= 7) { ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI2200_DIGITAL_IP); *data = (ui_TmpValue >> ui_Channel) & 0x1; } /* if(ui_Channel >= 0 && ui_Channel <=7) */ diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c index 169cee41b871b804ad93433428e917abf4cab175..172fba8dbfe59cf8cbcfccb09ef98f9f9e159eeb 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c @@ -1468,7 +1468,7 @@ void v_APCI3120_Interrupt(int irq, void *d) int_amcc = inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); /* get AMCC int register */ if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) { - comedi_error(dev, "IRQ from unknow source"); + comedi_error(dev, "IRQ from unknown source"); return; } @@ -2350,7 +2350,7 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev, ui_Chan = CR_CHAN(insn->chanspec); /* channel specified */ /* this_board->i_hwdrv_InsnReadDigitalInput(dev,ui_Chan,data); */ - if (ui_Chan >= 0 && ui_Chan <= 3) { + if (ui_Chan <= 3) { ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS); /* @@ -2539,8 +2539,7 @@ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev, "Not a valid Data !!! ,Data should be 1 or 0\n"); return -EINVAL; } - if ((ui_NoOfChannel > (this_board->i_NbrDoChannel - 1)) - || (ui_NoOfChannel < 0)) { + if (ui_NoOfChannel > this_board->i_NbrDoChannel - 1) { comedi_error(dev, "This board doesn't have specified channel !!! \n"); return -EINVAL; diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c index 010697fa293690ed5857fc0f599f21a675274a54..98c23872e374ce9a4bff8cbd83569f579d365bb6 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c @@ -461,7 +461,7 @@ int i_APCI3200_GetChannelCalibrationValue(struct comedi_device *dev, if (s_BoardInfos[dev->minor].i_ConnectionType == 1) { /* if diff */ - if ((ui_Channel_num >= 0) && (ui_Channel_num <= 1)) + if (ui_Channel_num <= 1) i_DiffChannel = ui_Channel_num, i_Module = 0; else if ((ui_Channel_num >= 2) && (ui_Channel_num <= 3)) i_DiffChannel = ui_Channel_num - 2, i_Module = 1; diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c index ef21f03fc961f5e8e78bf1c133d671c595d2afdf..7b38d177394b36e9fad9fb1e0e9191abebf26a96 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c @@ -724,7 +724,7 @@ void v_APCI3501_Interrupt(int irq, void *d) APCI3501_TCW_IRQ) & 0x1; if ((!ui_Timer_AOWatchdog)) { - comedi_error(dev, "IRQ from unknow source"); + comedi_error(dev, "IRQ from unknown source"); return; } diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c index 338727879827611a05ecc81ef97cbab79090af7d..1d1e5fc2ea9a44feb3666597211f9939c77bdd78 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c @@ -148,7 +148,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev, /* Test the convert time value */ /*******************************/ - if ((dw_ReloadValue >= 0) && (dw_ReloadValue <= 65535)) { + if (dw_ReloadValue <= 65535) { dw_TestReloadValue = dw_ReloadValue; if (b_TimeBase == 1) { diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 8e1befc448a3566b69bc474def8782fb31807067..6925faaf52931aaa2880ed81821a0ac2fb1f0c80 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -133,9 +133,11 @@ static int pci6208_ao_winsn(struct comedi_device *dev, static int pci6208_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); -/* static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, */ +/* static int pci6208_dio_insn_bits (struct comedi_device *dev, + * struct comedi_subdevice *s, */ /* struct comedi_insn *insn,unsigned int *data); */ -/* static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s, */ +/* static int pci6208_dio_insn_config(struct comedi_device *dev, + * struct comedi_subdevice *s, */ /* struct comedi_insn *insn,unsigned int *data); */ /* @@ -151,7 +153,7 @@ static int pci6208_attach(struct comedi_device *dev, int retval; unsigned long io_base; - printk("comedi%d: pci6208: ", dev->minor); + printk(KERN_INFO "comedi%d: pci6208: ", dev->minor); retval = alloc_private(dev, sizeof(struct pci6208_private)); if (retval < 0) @@ -195,7 +197,7 @@ static int pci6208_attach(struct comedi_device *dev, /* s->insn_bits = pci6208_dio_insn_bits; */ /* s->insn_config = pci6208_dio_insn_config; */ - printk("attached\n"); + printk(KERN_INFO "attached\n"); return 1; } @@ -210,12 +212,11 @@ static int pci6208_attach(struct comedi_device *dev, */ static int pci6208_detach(struct comedi_device *dev) { - printk("comedi%d: pci6208: remove\n", dev->minor); + printk(KERN_INFO "comedi%d: pci6208: remove\n", dev->minor); if (devpriv && devpriv->pci_dev) { - if (dev->iobase) { + if (dev->iobase) comedi_pci_disable(devpriv->pci_dev); - } pci_dev_put(devpriv->pci_dev); } @@ -266,7 +267,8 @@ static int pci6208_ao_rinsn(struct comedi_device *dev, * useful to applications if you implement the insn_bits interface. * This allows packed reading/writing of the DIO channels. The * comedi core can convert between insn_bits and insn_read/write */ -/* static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, */ +/* static int pci6208_dio_insn_bits(struct comedi_device *dev, + * struct comedi_subdevice *s, */ /* struct comedi_insn *insn,unsigned int *data) */ /* { */ /* if(insn->n!=2)return -EINVAL; */ @@ -290,7 +292,8 @@ static int pci6208_ao_rinsn(struct comedi_device *dev, /* return 2; */ /* } */ -/* static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s, */ +/* static int pci6208_dio_insn_config(struct comedi_device *dev, + * struct comedi_subdevice *s, */ /* struct comedi_insn *insn,unsigned int *data) */ /* { */ /* int chan=CR_CHAN(insn->chanspec); */ @@ -320,10 +323,16 @@ static int pci6208_find_device(struct comedi_device *dev, int bus, int slot) pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) { if (pci_dev->vendor == PCI_VENDOR_ID_ADLINK) { for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) { - if (pci6208_boards[i].dev_id == pci_dev->device) { - /* was a particular bus/slot requested? */ + if (pci6208_boards[i].dev_id == + pci_dev->device) { + /* + * was a particular bus/slot requested? + */ if ((bus != 0) || (slot != 0)) { - /* are we on the wrong bus/slot? */ + /* + * are we on the + * wrong bus/slot? + */ if (pci_dev->bus->number != bus || PCI_SLOT(pci_dev->devfn) @@ -338,8 +347,9 @@ static int pci6208_find_device(struct comedi_device *dev, int bus, int slot) } } - printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", - dev->minor, bus, slot); + printk(KERN_ERR "comedi%d: no supported board found! " + "(req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); return -EIO; found: @@ -368,17 +378,20 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr, /* Enable PCI device and request regions */ if (comedi_pci_enable(pci_dev, PCI6208_DRIVER_NAME) < 0) { - printk - ("comedi%d: Failed to enable PCI device and request regions\n", - dev_minor); + printk(KERN_ERR "comedi%d: Failed to enable PCI device " + "and request regions\n", + dev_minor); return -EIO; } - /* Read local configuration register base address [PCI_BASE_ADDRESS #1]. */ + /* Read local configuration register + * base address [PCI_BASE_ADDRESS #1]. + */ lcr_io_base = pci_resource_start(pci_dev, 1); lcr_io_range = pci_resource_len(pci_dev, 1); - printk("comedi%d: local config registers at address 0x%4lx [0x%4lx]\n", - dev_minor, lcr_io_base, lcr_io_range); + printk(KERN_INFO "comedi%d: local config registers at address" + " 0x%4lx [0x%4lx]\n", + dev_minor, lcr_io_base, lcr_io_range); /* Read PCI6208 register base address [PCI_BASE_ADDRESS #2]. */ io_base = pci_resource_start(pci_dev, 2); diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c index 4de6fadec78b9b5da6d268b2d2b88749a2279865..8602865ae6b7a7885cd3cf2efab4f6aa063b6700 100644 --- a/drivers/staging/comedi/drivers/adl_pci7296.c +++ b/drivers/staging/comedi/drivers/adl_pci7296.c @@ -82,8 +82,7 @@ static int adl_pci7296_attach(struct comedi_device *dev, int bus, slot; int ret; - printk("comedi: attempt to attach...\n"); - printk("comedi%d: adl_pci7432\n", dev->minor); + printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor); dev->board_name = "pci7432"; bus = it->options[0]; @@ -110,14 +109,14 @@ static int adl_pci7296_attach(struct comedi_device *dev, } devpriv->pci_dev = pcidev; if (comedi_pci_enable(pcidev, "adl_pci7296") < 0) { - printk - ("comedi%d: Failed to enable PCI device and request regions\n", + printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n", dev->minor); return -EIO; } dev->iobase = pci_resource_start(pcidev, 2); - printk("comedi: base addr %4lx\n", dev->iobase); + printk(KERN_INFO "comedi: base addr %4lx\n", + dev->iobase); /* four 8255 digital io subdevices */ s = dev->subdevices + 0; @@ -145,25 +144,25 @@ static int adl_pci7296_attach(struct comedi_device *dev, if (ret < 0) return ret; - printk("attached\n"); + printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n", + dev->minor); return 1; } } - printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + printk(KERN_ERR "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", dev->minor, bus, slot); return -EIO; } static int adl_pci7296_detach(struct comedi_device *dev) { - printk("comedi%d: pci7432: remove\n", dev->minor); + printk(KERN_INFO "comedi%d: pci7432: remove\n", dev->minor); if (devpriv && devpriv->pci_dev) { - if (dev->iobase) { + if (dev->iobase) comedi_pci_disable(devpriv->pci_dev); - } pci_dev_put(devpriv->pci_dev); } /* detach four 8255 digital io subdevices */ diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c index e0844c69be77f0b7dc68215b6cd28b786ddb9279..b5a9499e438c0e09ce99a46f8ef049d631b2a193 100644 --- a/drivers/staging/comedi/drivers/adl_pci7432.c +++ b/drivers/staging/comedi/drivers/adl_pci7432.c @@ -90,8 +90,7 @@ static int adl_pci7432_attach(struct comedi_device *dev, struct comedi_subdevice *s; int bus, slot; - printk("comedi: attempt to attach...\n"); - printk("comedi%d: adl_pci7432\n", dev->minor); + printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor); dev->board_name = "pci7432"; bus = it->options[0]; @@ -118,13 +117,13 @@ static int adl_pci7432_attach(struct comedi_device *dev, } devpriv->pci_dev = pcidev; if (comedi_pci_enable(pcidev, "adl_pci7432") < 0) { - printk - ("comedi%d: Failed to enable PCI device and request regions\n", + printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n", dev->minor); return -EIO; } dev->iobase = pci_resource_start(pcidev, 2); - printk("comedi: base addr %4lx\n", dev->iobase); + printk(KERN_INFO "comedi: base addr %4lx\n", + dev->iobase); s = dev->subdevices + 0; s->type = COMEDI_SUBD_DI; @@ -148,25 +147,24 @@ static int adl_pci7432_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_bits = adl_pci7432_do_insn_bits; - printk("comedi: attached\n"); - + printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n", + dev->minor); return 1; } } - printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + printk(KERN_ERR "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", dev->minor, bus, slot); return -EIO; } static int adl_pci7432_detach(struct comedi_device *dev) { - printk("comedi%d: pci7432: remove\n", dev->minor); + printk(KERN_INFO "comedi%d: pci7432: remove\n", dev->minor); if (devpriv && devpriv->pci_dev) { - if (dev->iobase) { + if (dev->iobase) comedi_pci_disable(devpriv->pci_dev); - } pci_dev_put(devpriv->pci_dev); } @@ -178,8 +176,8 @@ static int adl_pci7432_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - printk("comedi: pci7432_do_insn_bits called\n"); - printk("comedi: data0: %8x data1: %8x\n", data[0], data[1]); + printk(KERN_DEBUG "comedi: pci7432_do_insn_bits called\n"); + printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]); if (insn->n != 2) return -EINVAL; @@ -188,7 +186,7 @@ static int adl_pci7432_do_insn_bits(struct comedi_device *dev, s->state &= ~data[0]; s->state |= (data[0] & data[1]); - printk("comedi: out: %8x on iobase %4lx\n", s->state, + printk(KERN_DEBUG "comedi: out: %8x on iobase %4lx\n", s->state, dev->iobase + PCI7432_DO); outl(s->state & 0xffffffff, dev->iobase + PCI7432_DO); } @@ -200,14 +198,14 @@ static int adl_pci7432_di_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - printk("comedi: pci7432_di_insn_bits called\n"); - printk("comedi: data0: %8x data1: %8x\n", data[0], data[1]); + printk(KERN_DEBUG "comedi: pci7432_di_insn_bits called\n"); + printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]); if (insn->n != 2) return -EINVAL; data[1] = inl(dev->iobase + PCI7432_DI) & 0xffffffff; - printk("comedi: data1 %8x\n", data[1]); + printk(KERN_DEBUG "comedi: data1 %8x\n", data[1]); return 2; } diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index 43745ec94ab50b9c5ea55f66e53915daf90b2917..da256a1e0b4dae23fe771f15046512b4e54212b4 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -35,6 +35,7 @@ Configuration Options: */ #include "../comedidev.h" +#include #include #include "comedi_fc.h" #include "comedi_pci.h" @@ -128,8 +129,8 @@ static int adl_pci8164_attach(struct comedi_device *dev, struct comedi_subdevice *s; int bus, slot; - printk("comedi: attempt to attach...\n"); - printk("comedi%d: adl_pci8164\n", dev->minor); + printk(KERN_INFO "comedi: attempt to attach...\n"); + printk(KERN_INFO "comedi%d: adl_pci8164\n", dev->minor); dev->board_name = "pci8164"; bus = it->options[0]; @@ -150,19 +151,18 @@ static int adl_pci8164_attach(struct comedi_device *dev, if (bus || slot) { /* requested particular bus/slot */ if (pcidev->bus->number != bus - || PCI_SLOT(pcidev->devfn) != slot) { + || PCI_SLOT(pcidev->devfn) != slot) continue; - } } devpriv->pci_dev = pcidev; if (comedi_pci_enable(pcidev, "adl_pci8164") < 0) { - printk - ("comedi%d: Failed to enable PCI device and request regions\n", - dev->minor); + printk(KERN_ERR "comedi%d: Failed to enable " + "PCI device and request regions\n", dev->minor); return -EIO; } dev->iobase = pci_resource_start(pcidev, 2); - printk("comedi: base addr %4lx\n", dev->iobase); + printk(KERN_DEBUG "comedi: base addr %4lx\n", + dev->iobase); s = dev->subdevices + 0; s->type = COMEDI_SUBD_PROC; @@ -204,25 +204,24 @@ static int adl_pci8164_attach(struct comedi_device *dev, s->insn_read = adl_pci8164_insn_read_buf1; s->insn_write = adl_pci8164_insn_write_buf1; - printk("comedi: attached\n"); + printk(KERN_INFO "comedi: attached\n"); return 1; } } - printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", - dev->minor, bus, slot); + printk(KERN_ERR "comedi%d: no supported board found!" + "(req. bus/slot : %d/%d)\n", dev->minor, bus, slot); return -EIO; } static int adl_pci8164_detach(struct comedi_device *dev) { - printk("comedi%d: pci8164: remove\n", dev->minor); + printk(KERN_INFO "comedi%d: pci8164: remove\n", dev->minor); if (devpriv && devpriv->pci_dev) { - if (dev->iobase) { + if (dev->iobase) comedi_pci_disable(devpriv->pci_dev); - } pci_dev_put(devpriv->pci_dev); } @@ -267,8 +266,9 @@ static void adl_pci8164_insn_read(struct comedi_device *dev, } data[0] = inw(dev->iobase + axis_reg + offset); - printk("comedi: pci8164 %s read -> %04X:%04X on axis %s\n", action, - data[0], data[1], axisname); + printk(KERN_DEBUG "comedi: pci8164 %s read -> " + "%04X:%04X on axis %s\n", + action, data[0], data[1], axisname); } static int adl_pci8164_insn_read_msts(struct comedi_device *dev, @@ -347,8 +347,9 @@ static void adl_pci8164_insn_out(struct comedi_device *dev, outw(data[0], dev->iobase + axis_reg + offset); - printk("comedi: pci8164 %s write -> %04X:%04X on axis %s\n", action, - data[0], data[1], axisname); + printk(KERN_DEBUG "comedi: pci8164 %s write -> " + "%04X:%04X on axis %s\n", + action, data[0], data[1], axisname); } diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 1ee4b6a91c1fbab1807603f2d9bd248327b79cdd..791ea8334e1e0f2ab50f9c1055f3fdc179e8f4eb 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -780,7 +780,7 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd) { int err = 0; - int tmp, divisor1, divisor2; + int tmp, divisor1 = 0, divisor2 = 0; /* step 1: make sure trigger sources are trivially valid */ diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index f0ae4c06fe9554c1803bac6e90217d94e0633d47..951e57949f7fdfde4cba3a50aa21b8d428343b62 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -830,7 +830,7 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev, struct comedi_subdevice *s) { - unsigned int divisor1, divisor2; + unsigned int divisor1 = 0, divisor2 = 0; unsigned int seglen; DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_docmd_and_mode(%d,...)\n", @@ -934,7 +934,7 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd) { int err = 0; - int tmp, divisor1, divisor2; + int tmp, divisor1 = 0, divisor2 = 0; DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...)\n"); #ifdef PCI171X_EXTDEBUG diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index c62a7e1f81bd26e3ba5ae33890e8ad59330cff84..15808e95ceabc0714dd5e0576950950e4170d23c 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -117,7 +117,8 @@ MODULE_DEVICE_TABLE(pci, pc263_pci_table); /* this structure is for data unique to this hardware driver. If several hardware drivers keep similar information in this structure, - feel free to suggest moving the variable to the struct comedi_device struct. */ + feel free to suggest moving the variable to the struct comedi_device struct. +*/ #ifdef CONFIG_COMEDI_PCI struct pc263_private { /* PCI device. */ @@ -281,7 +282,8 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME); if (ret < 0) { printk(KERN_ERR - "comedi%d: error! cannot enable PCI device and request regions!\n", + "comedi%d: error! cannot enable PCI device and " + "request regions!\n", dev->minor); return ret; } @@ -290,9 +292,8 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) #endif { ret = pc263_request_region(dev->minor, iobase, PC263_IO_SIZE); - if (ret < 0) { + if (ret < 0) return ret; - } } dev->iobase = iobase; @@ -350,21 +351,18 @@ static int pc263_detach(struct comedi_device *dev) PC263_DRIVER_NAME); #ifdef CONFIG_COMEDI_PCI - if (devpriv) + if (devpriv) { #endif - { #ifdef CONFIG_COMEDI_PCI if (devpriv->pci_dev) { - if (dev->iobase) { + if (dev->iobase) comedi_pci_disable(devpriv->pci_dev); - } pci_dev_put(devpriv->pci_dev); } else #endif { - if (dev->iobase) { + if (dev->iobase) release_region(dev->iobase, PC263_IO_SIZE); - } } } if (dev->board_name) { diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 39923cb388be5053c09a3e3b4e3ce28ffa72b51f..bc375e73abc105cdc6a3523d2c7e1c7583f13046 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -372,7 +372,7 @@ static int das16cs_ai_cmdtest(struct comedi_device *dev, /* step 2: make sure trigger sources are unique and mutually compatible */ - /* note that mutual compatiblity is not an issue here */ + /* note that mutual compatibility is not an issue here */ if (cmd->scan_begin_src != TRIG_TIMER && cmd->scan_begin_src != TRIG_EXT) err++; @@ -452,7 +452,7 @@ static int das16cs_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { - unsigned int div1, div2; + unsigned int div1 = 0, div2 = 0; tmp = cmd->scan_begin_arg; i8253_cascade_ns_to_timer(100, &div1, &div2, @@ -462,7 +462,7 @@ static int das16cs_ai_cmdtest(struct comedi_device *dev, err++; } if (cmd->convert_src == TRIG_TIMER) { - unsigned int div1, div2; + unsigned int div1 = 0, div2 = 0; tmp = cmd->convert_arg; i8253_cascade_ns_to_timer(100, &div1, &div2, diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 7a5d46ef1b77bb8ffc6aaa9bea5c3fddc06aba29..782357732eed8a85a3a93a8824d923c80e38f7a3 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -497,7 +497,7 @@ static int cb_pcidda_ai_cmdtest(struct comedi_device *dev, /* step 2: make sure trigger sources are unique and mutually compatible */ - /* note that mutual compatiblity is not an issue here */ + /* note that mutual compatibility is not an issue here */ if (cmd->scan_begin_src != TRIG_TIMER && cmd->scan_begin_src != TRIG_EXT) err++; diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c index 09e6e3bdfb3e6d9b9d0021ca3faf9f8d99d59091..7daad0a17fb1f978b96175a82c1170641687645a 100644 --- a/drivers/staging/comedi/drivers/cb_pcidio.c +++ b/drivers/staging/comedi/drivers/cb_pcidio.c @@ -109,12 +109,12 @@ MODULE_DEVICE_TABLE(pci, pcidio_pci_table); several hardware drivers keep similar information in this structure, feel free to suggest moving the variable to the struct comedi_device struct. */ struct pcidio_private { - int data; /* curently unused */ + int data; /* currently unused */ /* would be useful for a PCI device */ struct pci_dev *pci_dev; - /* used for DO readback, curently unused */ + /* used for DO readback, currently unused */ unsigned int do_readback[4]; /* up to 4 unsigned int suffice to hold 96 bits for PCI-DIO96 */ unsigned long dio_reg_base; /* address of port A of the first 8255 chip on board */ diff --git a/drivers/staging/comedi/drivers/comedi_fc.c b/drivers/staging/comedi/drivers/comedi_fc.c index f781154734ade5e0d78287196c36269124852b71..63be619dd606792e5e708ecd720a849ebcbb1427 100644 --- a/drivers/staging/comedi/drivers/comedi_fc.c +++ b/drivers/staging/comedi/drivers/comedi_fc.c @@ -53,7 +53,7 @@ unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *subd, retval = comedi_buf_write_alloc(async, num_bytes); if (retval != num_bytes) { - printk("comedi: buffer overrun\n"); + printk(KERN_WARNING "comedi: buffer overrun\n"); async->events |= COMEDI_CB_OVERFLOW; return 0; } @@ -65,7 +65,6 @@ unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *subd, return num_bytes; } - EXPORT_SYMBOL(cfc_write_array_to_buffer); unsigned int cfc_read_array_from_buffer(struct comedi_subdevice *subd, @@ -84,7 +83,6 @@ unsigned int cfc_read_array_from_buffer(struct comedi_subdevice *subd, return num_bytes; } - EXPORT_SYMBOL(cfc_read_array_from_buffer); unsigned int cfc_handle_events(struct comedi_device *dev, @@ -102,7 +100,6 @@ unsigned int cfc_handle_events(struct comedi_device *dev, return events; } - EXPORT_SYMBOL(cfc_handle_events); MODULE_AUTHOR("Frank Mori Hess "); diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index aeec1ee9ad6bf7185fdda13f525e832ed90779ee..9db9a467c8f875e5678d64fa9d95e5fd7b63c90e 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -629,7 +629,7 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev, /* step 2: make sure trigger sources are unique and mutually compatible */ - /* note that mutual compatiblity is not an issue here */ + /* note that mutual compatibility is not an issue here */ if (cmd->scan_begin_src != TRIG_TIMER && cmd->scan_begin_src != TRIG_EXT) err++; diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index 0364bbf178e1a4d75ea575c6824beb779325c0e4..e1b73752f607be3fa296991db42be0ec8197c614 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -175,7 +175,7 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev, /* step 2: make sure trigger sources are unique and mutually compatible */ - /* note that mutual compatiblity is not an issue here */ + /* note that mutual compatibility is not an issue here */ if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT) err++; diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index a4c96c02fa2bea82ff8f6c8198ff91dfaf5ee05c..99ca294b1ec560539961eae28d759d4ccab7f60a 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -777,7 +777,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, /* step 2: make sure trigger sources are unique and mutually compatible */ - /* note that mutual compatiblity is not an issue here */ + /* note that mutual compatibility is not an issue here */ if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->scan_begin_src != TRIG_EXT) err++; @@ -1050,7 +1050,7 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev, /* step 2: make sure trigger sources are unique and mutually compatible */ - /* note that mutual compatiblity is not an issue here */ + /* note that mutual compatibility is not an issue here */ if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) err++; diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index 0bb30162e92cae70f6355b9953275a4308563a78..51f12bf45cf1514fe7c0f838a319e36e48d8fbd2 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -55,7 +55,7 @@ support could be added to this driver. static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it); static int hpdi_detach(struct comedi_device *dev); -void abort_dma(struct comedi_device *dev, unsigned int channel); +static void abort_dma(struct comedi_device *dev, unsigned int channel); static int hpdi_cmd(struct comedi_device *dev, struct comedi_subdevice *s); static int hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd); @@ -110,7 +110,8 @@ enum hpdi_registers { int command_channel_valid(unsigned int channel) { if (channel == 0 || channel > 6) { - printk("gsc_hpdi: bug! invalid cable command channel\n"); + printk(KERN_WARNING + "gsc_hpdi: bug! invalid cable command channel\n"); return 0; } return 1; @@ -142,7 +143,8 @@ enum board_control_bits { RX_FIFO_RESET_BIT = 0x4, TX_ENABLE_BIT = 0x10, RX_ENABLE_BIT = 0x20, - DEMAND_DMA_DIRECTION_TX_BIT = 0x40, /* for channel 0, channel 1 can only transmit (when present) */ + DEMAND_DMA_DIRECTION_TX_BIT = 0x40, + /* for ch 0, ch 1 can only transmit (when present) */ LINE_VALID_ON_STATUS_VALID_BIT = 0x80, START_TX_BIT = 0x10, CABLE_THROTTLE_ENABLE_BIT = 0x20, @@ -420,9 +422,11 @@ static void init_plx9080(struct comedi_device *dev) bits |= PLX_DMA_EN_READYIN_BIT; /* enable dma chaining */ bits |= PLX_EN_CHAIN_BIT; - /* enable interrupt on dma done (probably don't need this, since chain never finishes) */ + /* enable interrupt on dma done + * (probably don't need this, since chain never finishes) */ bits |= PLX_EN_DMA_DONE_INTR_BIT; - /* don't increment local address during transfers (we are transferring from a fixed fifo register) */ + /* don't increment local address during transfers + * (we are transferring from a fixed fifo register) */ bits |= PLX_LOCAL_ADDR_CONST_BIT; /* route dma interrupt to pci bus */ bits |= PLX_DMA_INTR_PCI_BIT; @@ -560,7 +564,7 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it) int i; int retval; - printk("comedi%d: gsc_hpdi\n", dev->minor); + printk(KERN_WARNING "comedi%d: gsc_hpdi\n", dev->minor); if (alloc_private(dev, sizeof(struct hpdi_private)) < 0) return -ENOMEM; @@ -588,11 +592,12 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it) } while (pcidev != NULL); } if (dev->board_ptr == NULL) { - printk("gsc_hpdi: no hpdi card found\n"); + printk(KERN_WARNING "gsc_hpdi: no hpdi card found\n"); return -EIO; } - printk("gsc_hpdi: found %s on bus %i, slot %i\n", board(dev)->name, + printk(KERN_WARNING + "gsc_hpdi: found %s on bus %i, slot %i\n", board(dev)->name, pcidev->bus->number, PCI_SLOT(pcidev->devfn)); if (comedi_pci_enable(pcidev, driver_hpdi.driver_name)) { @@ -618,7 +623,7 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it) ioremap(priv(dev)->hpdi_phys_iobase, pci_resource_len(pcidev, HPDI_BADDRINDEX)); if (!priv(dev)->plx9080_iobase || !priv(dev)->hpdi_iobase) { - printk(" failed to remap io memory\n"); + printk(KERN_WARNING " failed to remap io memory\n"); return -ENOMEM; } @@ -630,12 +635,13 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* get irq */ if (request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED, driver_hpdi.driver_name, dev)) { - printk(" unable to allocate irq %u\n", pcidev->irq); + printk(KERN_WARNING + " unable to allocate irq %u\n", pcidev->irq); return -EINVAL; } dev->irq = pcidev->irq; - printk(" irq %u\n", dev->irq); + printk(KERN_WARNING " irq %u\n", dev->irq); /* alocate pci dma buffers */ for (i = 0; i < NUM_DMA_BUFFERS; i++) { @@ -653,7 +659,8 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it) &priv(dev)-> dma_desc_phys_addr); if (priv(dev)->dma_desc_phys_addr & 0xf) { - printk(" dma descriptors not quad-word aligned (bug)\n"); + printk(KERN_WARNING + " dma descriptors not quad-word aligned (bug)\n"); return -EIO; } @@ -672,42 +679,39 @@ static int hpdi_detach(struct comedi_device *dev) { unsigned int i; - printk("comedi%d: gsc_hpdi: remove\n", dev->minor); + printk(KERN_WARNING "comedi%d: gsc_hpdi: remove\n", dev->minor); if (dev->irq) free_irq(dev->irq, dev); - if (priv(dev)) { - if (priv(dev)->hw_dev) { - if (priv(dev)->plx9080_iobase) { - disable_plx_interrupts(dev); - iounmap((void *)priv(dev)->plx9080_iobase); - } - if (priv(dev)->hpdi_iobase) - iounmap((void *)priv(dev)->hpdi_iobase); - /* free pci dma buffers */ - for (i = 0; i < NUM_DMA_BUFFERS; i++) { - if (priv(dev)->dio_buffer[i]) - pci_free_consistent(priv(dev)->hw_dev, - DMA_BUFFER_SIZE, - priv(dev)-> - dio_buffer[i], - priv - (dev)->dio_buffer_phys_addr - [i]); - } - /* free dma descriptors */ - if (priv(dev)->dma_desc) + if ((priv(dev)) && (priv(dev)->hw_dev)) { + if (priv(dev)->plx9080_iobase) { + disable_plx_interrupts(dev); + iounmap((void *)priv(dev)->plx9080_iobase); + } + if (priv(dev)->hpdi_iobase) + iounmap((void *)priv(dev)->hpdi_iobase); + /* free pci dma buffers */ + for (i = 0; i < NUM_DMA_BUFFERS; i++) { + if (priv(dev)->dio_buffer[i]) pci_free_consistent(priv(dev)->hw_dev, - sizeof(struct plx_dma_desc) - * NUM_DMA_DESCRIPTORS, - priv(dev)->dma_desc, + DMA_BUFFER_SIZE, priv(dev)-> - dma_desc_phys_addr); - if (priv(dev)->hpdi_phys_iobase) { - comedi_pci_disable(priv(dev)->hw_dev); - } - pci_dev_put(priv(dev)->hw_dev); + dio_buffer[i], + priv + (dev)->dio_buffer_phys_addr + [i]); } + /* free dma descriptors */ + if (priv(dev)->dma_desc) + pci_free_consistent(priv(dev)->hw_dev, + sizeof(struct plx_dma_desc) + * NUM_DMA_DESCRIPTORS, + priv(dev)->dma_desc, + priv(dev)-> + dma_desc_phys_addr); + if (priv(dev)->hpdi_phys_iobase) + comedi_pci_disable(priv(dev)->hw_dev); + pci_dev_put(priv(dev)->hw_dev); } return 0; } @@ -810,15 +814,16 @@ static int di_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, if (err) return 4; - if (cmd->chanlist) { - for (i = 1; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) != i) { - /* XXX could support 8 channels or 16 channels */ - comedi_error(dev, - "chanlist must be channels 0 to 31 in order"); - err++; - break; - } + if (!cmd->chanlist) + return 0; + + for (i = 1; i < cmd->chanlist_len; i++) { + if (CR_CHAN(cmd->chanlist[i]) != i) { + /* XXX could support 8 or 16 channels */ + comedi_error(dev, + "chanlist must be ch 0 to 31 in order"); + err++; + break; } } @@ -831,9 +836,9 @@ static int di_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, static int hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - if (priv(dev)->dio_config_output) { + if (priv(dev)->dio_config_output) return -EINVAL; - } else + else return di_cmd_test(dev, s, cmd); } @@ -899,9 +904,9 @@ static int di_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int hpdi_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - if (priv(dev)->dio_config_output) { + if (priv(dev)->dio_config_output) return -EINVAL; - } else + else return di_cmd(dev, s); } @@ -963,14 +968,12 @@ static irqreturn_t handle_interrupt(int irq, void *d) uint8_t dma0_status, dma1_status; unsigned long flags; - if (!dev->attached) { + if (!dev->attached) return IRQ_NONE; - } plx_status = readl(priv(dev)->plx9080_iobase + PLX_INTRCS_REG); - if ((plx_status & (ICS_DMA0_A | ICS_DMA1_A | ICS_LIA)) == 0) { + if ((plx_status & (ICS_DMA0_A | ICS_DMA1_A | ICS_LIA)) == 0) return IRQ_NONE; - } hpdi_intr_status = readl(priv(dev)->hpdi_iobase + INTERRUPT_STATUS_REG); hpdi_board_status = readl(priv(dev)->hpdi_iobase + BOARD_STATUS_REG); @@ -990,9 +993,8 @@ static irqreturn_t handle_interrupt(int irq, void *d) priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG); DEBUG_PRINT("dma0 status 0x%x\n", dma0_status); - if (dma0_status & PLX_DMA_EN_BIT) { + if (dma0_status & PLX_DMA_EN_BIT) drain_dma_buffers(dev, 0); - } DEBUG_PRINT(" cleared dma ch0 interrupt\n"); } spin_unlock_irqrestore(&dev->spinlock, flags); @@ -1042,7 +1044,7 @@ static irqreturn_t handle_interrupt(int irq, void *d) return IRQ_HANDLED; } -void abort_dma(struct comedi_device *dev, unsigned int channel) +static void abort_dma(struct comedi_device *dev, unsigned int channel) { unsigned long flags; diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index 7a67fff42358472ee2d4de14f81d3be2e6ae9dda..fa0e48173bd4479968f3eb027ef6ee60583954c2 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -46,7 +46,7 @@ There are 4 x 12-bit Analogue Outputs. Ranges : 5V, 10V, +/-5V, +/-10V Options: [0] - PCI bus number - if bus number and slot number are 0, - then driver search for first unused card + then driver search for first unused card [1] - PCI slot number */ @@ -133,7 +133,7 @@ static int icp_multi_detach(struct comedi_device *dev); Data & Structure declarations ============================================================================== */ -static unsigned short pci_list_builded = 0; /*>0 list of card is known */ +static unsigned short pci_list_builded; /*>0 list of card is known */ struct boardtype { const char *name; /* driver name */ @@ -176,13 +176,13 @@ static const struct boardtype boardtypes[] = { #define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype)) static struct comedi_driver driver_icp_multi = { -driver_name:"icp_multi", -module:THIS_MODULE, -attach:icp_multi_attach, -detach:icp_multi_detach, -num_names:n_boardtypes, -board_name:&boardtypes[0].name, -offset:sizeof(struct boardtype), +driver_name: "icp_multi", +module : THIS_MODULE, +attach : icp_multi_attach, +detach : icp_multi_detach, +num_names : n_boardtypes, +board_name : &boardtypes[0].name, +offset : sizeof(struct boardtype), }; COMEDI_INITCLEANUP(driver_icp_multi); @@ -234,18 +234,18 @@ static int icp_multi_reset(struct comedi_device *dev); /* ============================================================================== - Name: icp_multi_insn_read_ai +Name: icp_multi_insn_read_ai - Description: - This function reads a single analogue input. +Description: + This function reads a single analogue input. - Parameters: - struct comedi_device *dev Pointer to current device structure - struct comedi_subdevice *s Pointer to current subdevice structure - struct comedi_insn *insn Pointer to current comedi instruction - unsigned int *data Pointer to analogue input data +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue input data - Returns:int Nmuber of instructions executed +Returns:int Nmuber of instructions executed ============================================================================== */ @@ -256,7 +256,7 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, int n, timeout; #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi EDBG: BGN: icp_multi_insn_read_ai(...)\n"); + printk(KERN_DEBUG "icp multi EDBG: BGN: icp_multi_insn_read_ai(...)\n"); #endif /* Disable A/D conversion ready interrupt */ devpriv->IntEnable &= ~ADC_READY; @@ -266,11 +266,11 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, devpriv->IntStatus |= ADC_READY; writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT); - /* Set up appropriate channel, mode and range data, for specified channel */ + /* Set up appropriate channel, mode and range data, for specified ch */ setup_channel_list(dev, s, &insn->chanspec, 1); #ifdef ICP_MULTI_EXTDEBUG - printk("icp_multi A ST=%4x IO=%p\n", + printk(KERN_DEBUG "icp_multi A ST=%4x IO=%p\n", readw(devpriv->io_addr + ICP_MULTI_ADC_CSR), devpriv->io_addr + ICP_MULTI_ADC_CSR); #endif @@ -283,14 +283,14 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, devpriv->AdcCmdStatus &= ~ADC_ST; #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi B n=%d ST=%4x\n", n, + printk(KERN_DEBUG "icp multi B n=%d ST=%4x\n", n, readw(devpriv->io_addr + ICP_MULTI_ADC_CSR)); #endif udelay(1); #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi C n=%d ST=%4x\n", n, + printk(KERN_DEBUG "icp multi C n=%d ST=%4x\n", n, readw(devpriv->io_addr + ICP_MULTI_ADC_CSR)); #endif @@ -303,7 +303,8 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, #ifdef ICP_MULTI_EXTDEBUG if (!(timeout % 10)) - printk("icp multi D n=%d tm=%d ST=%4x\n", n, + printk(KERN_DEBUG + "icp multi D n=%d tm=%d ST=%4x\n", n, timeout, readw(devpriv->io_addr + ICP_MULTI_ADC_CSR)); @@ -328,9 +329,9 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, data[n] = 0; #ifdef ICP_MULTI_EXTDEBUG - printk - ("icp multi EDBG: END: icp_multi_insn_read_ai(...) n=%d\n", - n); + printk(KERN_DEBUG + "icp multi EDBG: END: icp_multi_insn_read_ai(...) n=%d\n", + n); #endif return -ETIME; @@ -348,7 +349,8 @@ conv_finish: writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT); #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi EDBG: END: icp_multi_insn_read_ai(...) n=%d\n", n); + printk(KERN_DEBUG + "icp multi EDBG: END: icp_multi_insn_read_ai(...) n=%d\n", n); #endif return n; } @@ -356,18 +358,18 @@ conv_finish: /* ============================================================================== - Name: icp_multi_insn_write_ao +Name: icp_multi_insn_write_ao - Description: - This function writes a single analogue output. +Description: + This function writes a single analogue output. - Parameters: - struct comedi_device *dev Pointer to current device structure - struct comedi_subdevice *s Pointer to current subdevice structure - struct comedi_insn *insn Pointer to current comedi instruction - unsigned int *data Pointer to analogue output data +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue output data - Returns:int Nmuber of instructions executed +Returns:int Nmuber of instructions executed ============================================================================== */ @@ -378,7 +380,8 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, int n, chan, range, timeout; #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi EDBG: BGN: icp_multi_insn_write_ao(...)\n"); + printk(KERN_DEBUG + "icp multi EDBG: BGN: icp_multi_insn_write_ao(...)\n"); #endif /* Disable D/A conversion ready interrupt */ devpriv->IntEnable &= ~DAC_READY; @@ -404,7 +407,8 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, writew(devpriv->DacCmdStatus, devpriv->io_addr + ICP_MULTI_DAC_CSR); for (n = 0; n < insn->n; n++) { - /* Wait for analogue output data register to be ready for new data, or get fed up waiting */ + /* Wait for analogue output data register to be + * ready for new data, or get fed up waiting */ timeout = 100; while (timeout--) { if (!(readw(devpriv->io_addr + @@ -413,7 +417,8 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, #ifdef ICP_MULTI_EXTDEBUG if (!(timeout % 10)) - printk("icp multi A n=%d tm=%d ST=%4x\n", n, + printk(KERN_DEBUG + "icp multi A n=%d tm=%d ST=%4x\n", n, timeout, readw(devpriv->io_addr + ICP_MULTI_DAC_CSR)); @@ -438,8 +443,8 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, devpriv->ao_data[chan] = 0; #ifdef ICP_MULTI_EXTDEBUG - printk - ("icp multi EDBG: END: icp_multi_insn_write_ao(...) n=%d\n", + printk(KERN_DEBUG + "icp multi EDBG: END: icp_multi_insn_write_ao(...) n=%d\n", n); #endif return -ETIME; @@ -459,7 +464,8 @@ dac_ready: } #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi EDBG: END: icp_multi_insn_write_ao(...) n=%d\n", n); + printk(KERN_DEBUG + "icp multi EDBG: END: icp_multi_insn_write_ao(...) n=%d\n", n); #endif return n; } @@ -467,18 +473,18 @@ dac_ready: /* ============================================================================== - Name: icp_multi_insn_read_ao +Name: icp_multi_insn_read_ao - Description: - This function reads a single analogue output. +Description: + This function reads a single analogue output. - Parameters: - struct comedi_device *dev Pointer to current device structure - struct comedi_subdevice *s Pointer to current subdevice structure - struct comedi_insn *insn Pointer to current comedi instruction - unsigned int *data Pointer to analogue output data +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue output data - Returns:int Nmuber of instructions executed +Returns:int Nmuber of instructions executed ============================================================================== */ @@ -501,18 +507,18 @@ static int icp_multi_insn_read_ao(struct comedi_device *dev, /* ============================================================================== - Name: icp_multi_insn_bits_di +Name: icp_multi_insn_bits_di - Description: - This function reads the digital inputs. +Description: + This function reads the digital inputs. - Parameters: - struct comedi_device *dev Pointer to current device structure - struct comedi_subdevice *s Pointer to current subdevice structure - struct comedi_insn *insn Pointer to current comedi instruction - unsigned int *data Pointer to analogue output data +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue output data - Returns:int Nmuber of instructions executed +Returns:int Nmuber of instructions executed ============================================================================== */ @@ -528,18 +534,18 @@ static int icp_multi_insn_bits_di(struct comedi_device *dev, /* ============================================================================== - Name: icp_multi_insn_bits_do +Name: icp_multi_insn_bits_do - Description: - This function writes the appropriate digital outputs. +Description: + This function writes the appropriate digital outputs. - Parameters: - struct comedi_device *dev Pointer to current device structure - struct comedi_subdevice *s Pointer to current subdevice structure - struct comedi_insn *insn Pointer to current comedi instruction - unsigned int *data Pointer to analogue output data +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue output data - Returns:int Nmuber of instructions executed +Returns:int Nmuber of instructions executed ============================================================================== */ @@ -548,14 +554,14 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi EDBG: BGN: icp_multi_insn_bits_do(...)\n"); + printk(KERN_DEBUG "icp multi EDBG: BGN: icp_multi_insn_bits_do(...)\n"); #endif if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); - printk("Digital outputs = %4x \n", s->state); + printk(KERN_DEBUG "Digital outputs = %4x \n", s->state); writew(s->state, devpriv->io_addr + ICP_MULTI_DO); } @@ -563,7 +569,7 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev, data[1] = readw(devpriv->io_addr + ICP_MULTI_DI); #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi EDBG: END: icp_multi_insn_bits_do(...)\n"); + printk(KERN_DEBUG "icp multi EDBG: END: icp_multi_insn_bits_do(...)\n"); #endif return 2; } @@ -571,18 +577,18 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev, /* ============================================================================== - Name: icp_multi_insn_read_ctr +Name: icp_multi_insn_read_ctr - Description: - This function reads the specified counter. +Description: + This function reads the specified counter. - Parameters: - struct comedi_device *dev Pointer to current device structure - struct comedi_subdevice *s Pointer to current subdevice structure - struct comedi_insn *insn Pointer to current comedi instruction - unsigned int *data Pointer to counter data +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to counter data - Returns:int Nmuber of instructions executed +Returns:int Nmuber of instructions executed ============================================================================== */ @@ -596,18 +602,18 @@ static int icp_multi_insn_read_ctr(struct comedi_device *dev, /* ============================================================================== - Name: icp_multi_insn_write_ctr +Name: icp_multi_insn_write_ctr - Description: - This function write to the specified counter. +Description: + This function write to the specified counter. - Parameters: - struct comedi_device *dev Pointer to current device structure - struct comedi_subdevice *s Pointer to current subdevice structure - struct comedi_insn *insn Pointer to current comedi instruction - unsigned int *data Pointer to counter data +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to counter data - Returns:int Nmuber of instructions executed +Returns:int Nmuber of instructions executed ============================================================================== */ @@ -622,15 +628,15 @@ static int icp_multi_insn_write_ctr(struct comedi_device *dev, /* ============================================================================== - Name: interrupt_service_icp_multi +Name: interrupt_service_icp_multi - Description: - This function is the interrupt service routine for all - interrupts generated by the icp multi board. +Description: + This function is the interrupt service routine for all + interrupts generated by the icp multi board. - Parameters: - int irq - void *d Pointer to current device +Parameters: + int irq + void *d Pointer to current device ============================================================================== */ @@ -640,7 +646,8 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d) int int_no; #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi EDBG: BGN: interrupt_service_icp_multi(%d,...)\n", + printk(KERN_DEBUG + "icp multi EDBG: BGN: interrupt_service_icp_multi(%d,...)\n", irq); #endif @@ -651,7 +658,8 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d) return IRQ_NONE; #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi EDBG: interrupt_service_icp_multi() ST: %4x\n", + printk(KERN_DEBUG + "icp multi EDBG: interrupt_service_icp_multi() ST: %4x\n", readw(devpriv->io_addr + ICP_MULTI_INT_STAT)); #endif @@ -679,7 +687,8 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d) } #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi EDBG: END: interrupt_service_icp_multi(...)\n"); + printk(KERN_DEBUG + "icp multi EDBG: END: interrupt_service_icp_multi(...)\n"); #endif return IRQ_HANDLED; } @@ -688,20 +697,20 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d) /* ============================================================================== - Name: check_channel_list +Name: check_channel_list - Description: - This function checks if the channel list, provided by user - is built correctly +Description: + This function checks if the channel list, provided by user + is built correctly - Parameters: - struct comedi_device *dev Pointer to current sevice structure - struct comedi_subdevice *s Pointer to current subdevice structure - unsigned int *chanlist Pointer to packed channel list - unsigned int n_chan Number of channels to scan +Parameters: + struct comedi_device *dev Pointer to current sevice structure + struct comedi_subdevice *s Pointer to current subdevice structure + unsigned int *chanlist Pointer to packed channel list + unsigned int n_chan Number of channels to scan - Returns:int 0 = failure - 1 = success +Returns:int 0 = failure + 1 = success ============================================================================== */ @@ -712,7 +721,8 @@ static int check_channel_list(struct comedi_device *dev, unsigned int i; #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi EDBG: check_channel_list(...,%d)\n", n_chan); + printk(KERN_DEBUG + "icp multi EDBG: check_channel_list(...,%d)\n", n_chan); #endif /* Check that we at least have one channel to check */ if (n_chan < 1) { @@ -725,7 +735,7 @@ static int check_channel_list(struct comedi_device *dev, if (CR_AREF(chanlist[i]) == AREF_DIFF) { if (CR_CHAN(chanlist[i]) > this_board->n_aichand) { comedi_error(dev, - "Incorrect differential ai channel number"); + "Incorrect differential ai ch-nr"); return 0; } } else { @@ -743,20 +753,20 @@ static int check_channel_list(struct comedi_device *dev, /* ============================================================================== - Name: setup_channel_list +Name: setup_channel_list - Description: - This function sets the appropriate channel selection, - differential input mode and range bits in the ADC Command/ - Status register. +Description: + This function sets the appropriate channel selection, + differential input mode and range bits in the ADC Command/ + Status register. - Parameters: - struct comedi_device *dev Pointer to current sevice structure - struct comedi_subdevice *s Pointer to current subdevice structure - unsigned int *chanlist Pointer to packed channel list - unsigned int n_chan Number of channels to scan +Parameters: + struct comedi_device *dev Pointer to current sevice structure + struct comedi_subdevice *s Pointer to current subdevice structure + unsigned int *chanlist Pointer to packed channel list + unsigned int n_chan Number of channels to scan - Returns:Void +Returns:Void ============================================================================== */ @@ -768,7 +778,8 @@ static void setup_channel_list(struct comedi_device *dev, unsigned int diff; #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi EDBG: setup_channel_list(...,%d)\n", n_chan); + printk(KERN_DEBUG + "icp multi EDBG: setup_channel_list(...,%d)\n", n_chan); #endif devpriv->act_chanlist_len = n_chan; devpriv->act_chanlist_pos = 0; @@ -786,7 +797,8 @@ static void setup_channel_list(struct comedi_device *dev, chanprog &= 0x000f; } - /* Clear channel, range and input mode bits in A/D command/status register */ + /* Clear channel, range and input mode bits + * in A/D command/status register */ devpriv->AdcCmdStatus &= 0xf00f; /* Set channel number and differential mode status bit */ @@ -808,7 +820,8 @@ static void setup_channel_list(struct comedi_device *dev, devpriv->io_addr + ICP_MULTI_ADC_CSR); #ifdef ICP_MULTI_EXTDEBUG - printk("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range, + printk(KERN_DEBUG + "GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range, devpriv->act_chanlist[i]); #endif } @@ -818,15 +831,15 @@ static void setup_channel_list(struct comedi_device *dev, /* ============================================================================== - Name: icp_multi_reset +Name: icp_multi_reset - Description: - This function resets the icp multi device to a 'safe' state +Description: + This function resets the icp multi device to a 'safe' state - Parameters: - struct comedi_device *dev Pointer to current sevice structure +Parameters: + struct comedi_device *dev Pointer to current sevice structure - Returns:int 0 = success +Returns:int 0 = success ============================================================================== */ @@ -835,7 +848,8 @@ static int icp_multi_reset(struct comedi_device *dev) unsigned int i; #ifdef ICP_MULTI_EXTDEBUG - printk("icp_multi EDBG: BGN: icp_multi_reset(...)\n"); + printk(KERN_DEBUG + "icp_multi EDBG: BGN: icp_multi_reset(...)\n"); #endif /* Clear INT enables and requests */ writew(0, devpriv->io_addr + ICP_MULTI_INT_EN); @@ -866,7 +880,8 @@ static int icp_multi_reset(struct comedi_device *dev) writew(0, devpriv->io_addr + ICP_MULTI_DO); #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi EDBG: END: icp_multi_reset(...)\n"); + printk(KERN_DEBUG + "icp multi EDBG: END: icp_multi_reset(...)\n"); #endif return 0; } @@ -874,17 +889,17 @@ static int icp_multi_reset(struct comedi_device *dev) /* ============================================================================== - Name: icp_multi_attach +Name: icp_multi_attach - Description: - This function sets up all the appropriate data for the current - device. +Description: + This function sets up all the appropriate data for the current + device. - Parameters: - struct comedi_device *dev Pointer to current device structure - struct comedi_devconfig *it Pointer to current device configuration +Parameters: + struct comedi_device *dev Pointer to current device structure + struct comedi_devconfig *it Pointer to current device configuration - Returns:int 0 = success +Returns:int 0 = success ============================================================================== */ @@ -898,7 +913,8 @@ static int icp_multi_attach(struct comedi_device *dev, resource_size_t io_addr[5], iobase; unsigned char pci_bus, pci_slot, pci_func; - printk("icp_multi EDBG: BGN: icp_multi_attach(...)\n"); + printk(KERN_WARNING + "icp_multi EDBG: BGN: icp_multi_attach(...)\n"); /* Alocate private data storage space */ ret = alloc_private(dev, sizeof(struct icp_multi_private)); @@ -916,7 +932,8 @@ static int icp_multi_attach(struct comedi_device *dev, ); } - printk("Anne's comedi%d: icp_multi: board=%s", dev->minor, + printk(KERN_WARNING + "Anne's comedi%d: icp_multi: board=%s", dev->minor, this_board->name); card = select_and_alloc_pci_card(PCI_VENDOR_ID_ICP, @@ -930,24 +947,26 @@ static int icp_multi_attach(struct comedi_device *dev, if ((pci_card_data(card, &pci_bus, &pci_slot, &pci_func, &io_addr[0], &irq)) < 0) { - printk(" - Can't get configuration data!\n"); + printk(KERN_WARNING " - Can't get configuration data!\n"); return -EIO; } iobase = io_addr[2]; devpriv->phys_iobase = iobase; - printk(", b:s:f=%d:%d:%d, io=0x%8llx \n", pci_bus, pci_slot, pci_func, + printk(KERN_WARNING + ", b:s:f=%d:%d:%d, io=0x%8llx \n", pci_bus, pci_slot, pci_func, (unsigned long long)iobase); devpriv->io_addr = ioremap(iobase, ICP_MULTI_SIZE); if (devpriv->io_addr == NULL) { - printk("ioremap failed.\n"); + printk(KERN_WARNING "ioremap failed.\n"); return -ENOMEM; } #ifdef ICP_MULTI_EXTDEBUG - printk("0x%08llx mapped to %p, ", (unsigned long long)iobase, + printk(KERN_DEBUG + "0x%08llx mapped to %p, ", (unsigned long long)iobase, devpriv->io_addr); #endif @@ -975,20 +994,20 @@ static int icp_multi_attach(struct comedi_device *dev, if (irq) { if (request_irq(irq, interrupt_service_icp_multi, IRQF_SHARED, "Inova Icp Multi", dev)) { - printk - (", unable to allocate IRQ %u, DISABLING IT", + printk(KERN_WARNING + "unable to allocate IRQ %u, DISABLING IT", irq); irq = 0; /* Can't use IRQ */ } else - printk(", irq=%u", irq); + printk(KERN_WARNING ", irq=%u", irq); } else - printk(", IRQ disabled"); + printk(KERN_WARNING ", IRQ disabled"); } else irq = 0; dev->irq = irq; - printk(".\n"); + printk(KERN_WARNING ".\n"); subdev = 0; @@ -1063,7 +1082,7 @@ static int icp_multi_attach(struct comedi_device *dev, devpriv->valid = 1; #ifdef ICP_MULTI_EXTDEBUG - printk("icp multi EDBG: END: icp_multi_attach(...)\n"); + printk(KERN_DEBUG "icp multi EDBG: END: icp_multi_attach(...)\n"); #endif return 0; @@ -1072,16 +1091,16 @@ static int icp_multi_attach(struct comedi_device *dev, /* ============================================================================== - Name: icp_multi_detach +Name: icp_multi_detach - Description: - This function releases all the resources used by the current - device. +Description: + This function releases all the resources used by the current + device. - Parameters: - struct comedi_device *dev Pointer to current device structure +Parameters: + struct comedi_device *dev Pointer to current device structure - Returns:int 0 = success +Returns:int 0 = success ============================================================================== */ diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 24df2453e683cf4422832e37c9cd7766c35ee3a6..e26c1b88ebeb0908b5cf4f0248c32f2788d5cdd4 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -23,7 +23,8 @@ * no extern trigger implemented * * NOT WORKING (but soon) only 4 on-board differential channels supported - * NOT WORKING (but soon) only ONE di-port and ONE do-port supported instead of 4 digital ports + * NOT WORKING (but soon) only ONE di-port and ONE do-port supported + * instead of 4 digital ports * di-port == Port 0 * do-port == Port 1 * @@ -63,17 +64,17 @@ Options: options for PCI-20006M: first: Analog output channel 0 range configuration - 0 bipolar 10 (-10V -- +10V) - 1 unipolar 10 (0V -- +10V) - 2 bipolar 5 (-5V -- 5V) + 0 bipolar 10 (-10V -- +10V) + 1 unipolar 10 (0V -- +10V) + 2 bipolar 5 (-5V -- 5V) second: Analog output channel 1 range configuration options for PCI-20341M: first: Analog input gain configuration - 0 1 - 1 10 - 2 100 - 3 200 + 0 1 + 1 10 + 2 100 + 3 200 */ /* XXX needs to use ioremap() for compatibility with 2.4 kernels. Should also @@ -95,12 +96,12 @@ options for PCI-20341M: #define PCI20000_DIO_3 0xc1 #define PCI20000_DIO_CONTROL_01 0x83 /* port 0, 1 control */ #define PCI20000_DIO_CONTROL_23 0xc3 /* port 2, 3 control */ -#define PCI20000_DIO_BUFFER 0x82 /* buffer direction and enable */ +#define PCI20000_DIO_BUFFER 0x82 /* buffer direction & enable */ #define PCI20000_DIO_EOC 0xef /* even port, control output */ #define PCI20000_DIO_OOC 0xfd /* odd port, control output */ #define PCI20000_DIO_EIC 0x90 /* even port, control input */ #define PCI20000_DIO_OIC 0x82 /* odd port, control input */ -#define DIO_CAND 0x12 /* and bit 1, bit 4 of control */ +#define DIO_CAND 0x12 /* and bit 1 & 4 of control */ #define DIO_BE 0x01 /* buffer: port enable */ #define DIO_BO 0x04 /* buffer: output */ #define DIO_BI 0x05 /* buffer: input */ @@ -137,7 +138,8 @@ union pci20xxx_subdev_private { void *iobase; struct { void *iobase; - const struct comedi_lrange *ao_range_list[2]; /* range of channels of ao module */ + const struct comedi_lrange *ao_range_list[2]; + /* range of channels of ao module */ unsigned int last_data[2]; } pci20006; struct { @@ -224,14 +226,13 @@ static int pci20xxx_attach(struct comedi_device *dev, /* Check PCI-20001 C-2A Carrier Board ID */ if ((readb(devpriv->ioaddr) & PCI20000_ID) != PCI20000_ID) { - printk("comedi%d: ii_pci20kc", dev->minor); - printk - (" PCI-20001 C-2A Carrier Board at base=0x%p not found !\n", - devpriv->ioaddr); + printk(KERN_WARNING "comedi%d: ii_pci20kc PCI-20001" + " C-2A Carrier Board at base=0x%p not found !\n", + dev->minor, devpriv->ioaddr); return -EINVAL; } - printk("comedi%d:\n", dev->minor); - printk("ii_pci20kc: PCI-20001 C-2A at base=0x%p\n", devpriv->ioaddr); + printk(KERN_INFO "comedi%d: ii_pci20kc: PCI-20001 C-2A at base=0x%p\n", + dev->minor, devpriv->ioaddr); for (i = 0; i < PCI20000_MODULES; i++) { s = dev->subdevices + i; @@ -244,21 +245,23 @@ static int pci20xxx_attach(struct comedi_device *dev, devpriv->ioaddr + (i + 1) * PCI20000_OFFSET; pci20006_init(dev, s, it->options[2 * i + 2], it->options[2 * i + 3]); - printk("comedi%d: ii_pci20kc", dev->minor); - printk(" PCI-20006 module in slot %d \n", i + 1); + printk(KERN_INFO "comedi%d: " + "ii_pci20kc PCI-20006 module in slot %d \n", + dev->minor, i + 1); break; case PCI20341_ID: sdp->pci20341.iobase = devpriv->ioaddr + (i + 1) * PCI20000_OFFSET; pci20341_init(dev, s, it->options[2 * i + 2], it->options[2 * i + 3]); - printk("comedi%d: ii_pci20kc", dev->minor); - printk(" PCI-20341 module in slot %d \n", i + 1); + printk(KERN_INFO "comedi%d: " + "ii_pci20kc PCI-20341 module in slot %d \n", + dev->minor, i + 1); break; default: - printk - ("ii_pci20kc: unknown module code 0x%02x in slot %d: module disabled\n", - id, i); + printk(KERN_WARNING "ii_pci20kc: unknown module " + "code 0x%02x in slot %d: module disabled\n", + id, i); /* XXX this looks like a bug! i + 1 ?? */ /* fall through */ case PCI20xxx_EMPTY_ID: s->type = COMEDI_SUBD_UNUSED; @@ -274,7 +277,7 @@ static int pci20xxx_attach(struct comedi_device *dev, static int pci20xxx_detach(struct comedi_device *dev) { - printk("comedi%d: pci20xxx: remove\n", dev->minor); + printk(KERN_INFO "comedi%d: pci20xxx: remove\n", dev->minor); return 0; } @@ -339,7 +342,8 @@ static int pci20006_insn_write(struct comedi_device *dev, unsigned int boarddata; sdp->pci20006.last_data[CR_CHAN(insn->chanspec)] = data[0]; - boarddata = (((unsigned int)data[0] + 0x8000) & 0xffff); /* comedi-data -> board-data */ + boarddata = (((unsigned int)data[0] + 0x8000) & 0xffff); + /* comedi-data -> board-data */ lo = (boarddata & 0xff); hi = ((boarddata >> 8) & 0xff); @@ -355,7 +359,8 @@ static int pci20006_insn_write(struct comedi_device *dev, writeb(0x00, sdp->iobase + PCI20006_STROBE1); break; default: - printk(" comedi%d: pci20xxx: ao channel Error!\n", dev->minor); + printk(KERN_WARNING + " comedi%d: pci20xxx: ao channel Error!\n", dev->minor); return -EINVAL; } @@ -373,8 +378,7 @@ static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 }; static const struct comedi_lrange range_bipolar0_5 = { 1, {BIP_RANGE(0.5)} }; static const struct comedi_lrange range_bipolar0_05 = { 1, {BIP_RANGE(0.05)} }; -static const struct comedi_lrange range_bipolar0_025 = - { 1, {BIP_RANGE(0.025)} }; +static const struct comedi_lrange range_bipolar0_025 = { 1, {BIP_RANGE(0.025)} }; static const struct comedi_lrange *const pci20341_ranges[] = { &range_bipolar5, @@ -447,9 +451,10 @@ static int pci20341_insn_read(struct comedi_device *dev, eoc = readb(sdp->iobase + PCI20341_STATUS_REG); } if (j >= 100) { - printk - ("comedi%d: pci20xxx: AI interrupt channel %i polling exit !\n", - dev->minor, i); + printk(KERN_WARNING + "comedi%d: pci20xxx: " + "AI interrupt channel %i polling exit !\n", + dev->minor, i); return -EINVAL; } lo = readb(sdp->iobase + PCI20341_LDATA); @@ -502,20 +507,18 @@ static int pci20xxx_dio_insn_config(struct comedi_device *dev, int mask, bits; mask = 1 << CR_CHAN(insn->chanspec); - if (mask & 0x000000ff) { + if (mask & 0x000000ff) bits = 0x000000ff; - } else if (mask & 0x0000ff00) { + else if (mask & 0x0000ff00) bits = 0x0000ff00; - } else if (mask & 0x00ff0000) { + else if (mask & 0x00ff0000) bits = 0x00ff0000; - } else { + else bits = 0xff000000; - } - if (data[0]) { + if (data[0]) s->io_bits |= bits; - } else { + else s->io_bits &= ~bits; - } pci20xxx_dio_config(dev, s); return 1; diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index c145e829108f3fb848e0aee9ba05ce29f0c879e6..73b0445e310faf125d956c8b5c9b163bcc0a466b 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -192,12 +192,14 @@ static int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it) } } } - printk("comedi%d: no supported board found! (req. bus/slot: %d/%d)\n", + printk(KERN_WARNING + "comedi%d: no supported board found! (req. bus/slot: %d/%d)\n", dev->minor, it->options[0], it->options[1]); return -EIO; found: - printk("comedi%d: found %s at PCI bus %d, slot %d\n", dev->minor, + printk(KERN_INFO + "comedi%d: found %s at PCI bus %d, slot %d\n", dev->minor, board->name, pci_device->bus->number, PCI_SLOT(pci_device->devfn)); devpriv->pcidev = pci_device; @@ -206,9 +208,9 @@ found: /* enable PCI device and request regions */ error = comedi_pci_enable(pci_device, CNT_DRIVER_NAME); if (error < 0) { - printk - ("comedi%d: failed to enable PCI device and request regions!\n", - dev->minor); + printk(KERN_WARNING "comedi%d: " + "failed to enable PCI device and request regions!\n", + dev->minor); return error; } @@ -239,7 +241,8 @@ found: outb(0, dev->iobase + 0x20); outb(0, dev->iobase + 0x40); - printk("comedi%d: " CNT_DRIVER_NAME " attached.\n", dev->minor); + printk(KERN_INFO "comedi%d: " CNT_DRIVER_NAME " attached.\n", + dev->minor); return 0; } @@ -248,11 +251,11 @@ found: static int cnt_detach(struct comedi_device *dev) { if (devpriv && devpriv->pcidev) { - if (dev->iobase) { + if (dev->iobase) comedi_pci_disable(devpriv->pcidev); - } pci_dev_put(devpriv->pcidev); } - printk("comedi%d: " CNT_DRIVER_NAME " remove\n", dev->minor); + printk(KERN_INFO "comedi%d: " CNT_DRIVER_NAME " remove\n", + dev->minor); return 0; } diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 6079913d14b0890b39bf06c5ebcf3da93c0b69d5..8b9fa0f9f1f62606eb0d8e618ae0c0f5e0862ba0 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -840,7 +840,7 @@ static int xilinx_download(struct comedi_device *dev) "comedi%d: me4000: xilinx_download(): DONE flag is not set\n", dev->minor); printk(KERN_ERR - "comedi%d: me4000: xilinx_download(): Download not succesful\n", + "comedi%d: me4000: xilinx_download(): Download not successful\n", dev->minor); return -EIO; } diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index e652f3b270b11fe5bcfbe77e2c2bdc36486d03c9..188f58042746ee654dea7fed25aa613b588ef640 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -64,6 +64,7 @@ MODULE_LICENSE("GPL"); struct mite_struct *mite_devices; +EXPORT_SYMBOL(mite_devices); #define TOP_OF_PAGE(x) ((x)|(~(PAGE_MASK))) @@ -80,7 +81,7 @@ void mite_init(void) mite = kzalloc(sizeof(*mite), GFP_KERNEL); if (!mite) { - printk("mite: allocation failed\n"); + printk(KERN_ERR "mite: allocation failed\n"); pci_dev_put(pcidev); return; } @@ -99,14 +100,14 @@ void mite_init(void) static void dump_chip_signature(u32 csigr_bits) { - printk - ("mite: version = %i, type = %i, mite mode = %i, interface mode = %i\n", - mite_csigr_version(csigr_bits), mite_csigr_type(csigr_bits), - mite_csigr_mmode(csigr_bits), mite_csigr_imode(csigr_bits)); - printk - ("mite: num channels = %i, write post fifo depth = %i, wins = %i, iowins = %i\n", - mite_csigr_dmac(csigr_bits), mite_csigr_wpdep(csigr_bits), - mite_csigr_wins(csigr_bits), mite_csigr_iowins(csigr_bits)); + printk(KERN_INFO "mite: version = %i, type = %i, mite mode = %i," + "interface mode = %i\n", + mite_csigr_version(csigr_bits), mite_csigr_type(csigr_bits), + mite_csigr_mmode(csigr_bits), mite_csigr_imode(csigr_bits)); + printk(KERN_INFO "mite: num channels = %i, write post fifo depth = %i," + "wins = %i, iowins = %i\n", + mite_csigr_dmac(csigr_bits), mite_csigr_wpdep(csigr_bits), + mite_csigr_wins(csigr_bits), mite_csigr_iowins(csigr_bits)); } unsigned mite_fifo_size(struct mite_struct *mite, unsigned channel) @@ -126,7 +127,7 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) unsigned unknown_dma_burst_bits; if (comedi_pci_enable(mite->pcidev, "mite")) { - printk("error enabling mite and requesting io regions\n"); + printk(KERN_ERR "error enabling mite and requesting io regions\n"); return -EIO; } pci_set_master(mite->pcidev); @@ -135,27 +136,30 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) mite->mite_phys_addr = addr; mite->mite_io_addr = ioremap(addr, PCI_MITE_SIZE); if (!mite->mite_io_addr) { - printk("failed to remap mite io memory address\n"); + printk(KERN_ERR "Failed to remap mite io memory address\n"); return -ENOMEM; } - printk("MITE:0x%08llx mapped to %p ", + printk(KERN_INFO "MITE:0x%08llx mapped to %p ", (unsigned long long)mite->mite_phys_addr, mite->mite_io_addr); addr = pci_resource_start(mite->pcidev, 1); mite->daq_phys_addr = addr; length = pci_resource_len(mite->pcidev, 1); - /* In case of a 660x board, DAQ size is 8k instead of 4k (see as shown by lspci output) */ + /* + * In case of a 660x board, DAQ size is 8k instead of 4k + * (see as shown by lspci output) + */ mite->daq_io_addr = ioremap(mite->daq_phys_addr, length); if (!mite->daq_io_addr) { - printk("failed to remap daq io memory address\n"); + printk(KERN_ERR "Failed to remap daq io memory address\n"); return -ENOMEM; } - printk("DAQ:0x%08llx mapped to %p\n", + printk(KERN_INFO "DAQ:0x%08llx mapped to %p\n", (unsigned long long)mite->daq_phys_addr, mite->daq_io_addr); if (use_iodwbsr_1) { writel(0, mite->mite_io_addr + MITE_IODWBSR); - printk("mite: using I/O Window Base Size register 1\n"); + printk(KERN_INFO "mite: using I/O Window Base Size register 1\n"); writel(mite->daq_phys_addr | WENAB | MITE_IODWBSR_1_WSIZE_bits(length), mite->mite_io_addr + MITE_IODWBSR_1); @@ -164,11 +168,12 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) writel(mite->daq_phys_addr | WENAB, mite->mite_io_addr + MITE_IODWBSR); } - /* make sure dma bursts work. I got this from running a bus analyzer - on a pxi-6281 and a pxi-6713. 6713 powered up with register value - of 0x61f and bursts worked. 6281 powered up with register value of - 0x1f and bursts didn't work. The NI windows driver reads the register, - then does a bitwise-or of 0x600 with it and writes it back. + /* + * make sure dma bursts work. I got this from running a bus analyzer + * on a pxi-6281 and a pxi-6713. 6713 powered up with register value + * of 0x61f and bursts worked. 6281 powered up with register value of + * 0x1f and bursts didn't work. The NI windows driver reads the + * register, then does a bitwise-or of 0x600 with it and writes it back. */ unknown_dma_burst_bits = readl(mite->mite_io_addr + MITE_UNKNOWN_DMA_BURST_REG); @@ -179,9 +184,9 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) csigr_bits = readl(mite->mite_io_addr + MITE_CSIGR); mite->num_channels = mite_csigr_dmac(csigr_bits); if (mite->num_channels > MAX_MITE_DMA_CHANNELS) { - printk - ("mite: bug? chip claims to have %i dma channels. Setting to %i.\n", - mite->num_channels, MAX_MITE_DMA_CHANNELS); + printk(KERN_WARNING "mite: bug? chip claims to have %i dma " + "channels. Setting to %i.\n", + mite->num_channels, MAX_MITE_DMA_CHANNELS); mite->num_channels = MAX_MITE_DMA_CHANNELS; } dump_chip_signature(csigr_bits); @@ -194,16 +199,18 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) mite->mite_io_addr + MITE_CHCR(i)); } mite->fifo_size = mite_fifo_size(mite, 0); - printk("mite: fifo size is %i.\n", mite->fifo_size); + printk(KERN_INFO "mite: fifo size is %i.\n", mite->fifo_size); mite->used = 1; return 0; } +EXPORT_SYMBOL(mite_setup2); int mite_setup(struct mite_struct *mite) { return mite_setup2(mite, 0); } +EXPORT_SYMBOL(mite_setup); void mite_cleanup(void) { @@ -238,22 +245,23 @@ void mite_unsetup(struct mite_struct *mite) mite->used = 0; } +EXPORT_SYMBOL(mite_unsetup); void mite_list_devices(void) { struct mite_struct *mite, *next; - printk("Available NI device IDs:"); + printk(KERN_INFO "Available NI device IDs:"); if (mite_devices) for (mite = mite_devices; mite; mite = next) { next = mite->next; - printk(" 0x%04x", mite_device_id(mite)); + printk(KERN_INFO " 0x%04x", mite_device_id(mite)); if (mite->used) - printk("(used)"); + printk(KERN_INFO "(used)"); } - printk("\n"); - + printk(KERN_INFO "\n"); } +EXPORT_SYMBOL(mite_list_devices); struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite, struct @@ -265,7 +273,9 @@ struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite, unsigned long flags; struct mite_channel *channel = NULL; - /* spin lock so mite_release_channel can be called safely from interrupts */ + /* spin lock so mite_release_channel can be called safely + * from interrupts + */ spin_lock_irqsave(&mite->lock, flags); for (i = min_channel; i <= max_channel; ++i) { if (mite->channel_allocated[i] == 0) { @@ -278,6 +288,7 @@ struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite, spin_unlock_irqrestore(&mite->lock, flags); return channel; } +EXPORT_SYMBOL(mite_request_channel_in_range); void mite_release_channel(struct mite_channel *mite_chan) { @@ -289,8 +300,10 @@ void mite_release_channel(struct mite_channel *mite_chan) if (mite->channel_allocated[mite_chan->channel]) { mite_dma_disarm(mite_chan); mite_dma_reset(mite_chan); -/* disable all channel's interrupts (do it after disarm/reset so -MITE_CHCR reg isn't changed while dma is still active!) */ + /* + * disable all channel's interrupts (do it after disarm/reset so + * MITE_CHCR reg isn't changed while dma is still active!) + */ writel(CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE | CHCR_CLR_SAR_IE | CHCR_CLR_DONE_IE | CHCR_CLR_MRDY_IE | CHCR_CLR_DRDY_IE | @@ -302,6 +315,7 @@ MITE_CHCR reg isn't changed while dma is still active!) */ } spin_unlock_irqrestore(&mite->lock, flags); } +EXPORT_SYMBOL(mite_release_channel); void mite_dma_arm(struct mite_channel *mite_chan) { @@ -310,8 +324,10 @@ void mite_dma_arm(struct mite_channel *mite_chan) unsigned long flags; MDPRINTK("mite_dma_arm ch%i\n", channel); - /* memory barrier is intended to insure any twiddling with the buffer - is done before writing to the mite to arm dma transfer */ + /* + * memory barrier is intended to insure any twiddling with the buffer + * is done before writing to the mite to arm dma transfer + */ smp_mb(); /* arm */ chor = CHOR_START; @@ -322,6 +338,7 @@ void mite_dma_arm(struct mite_channel *mite_chan) spin_unlock_irqrestore(&mite->lock, flags); /* mite_dma_tcr(mite, channel); */ } +EXPORT_SYMBOL(mite_dma_arm); /**************************************/ @@ -354,7 +371,7 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, n_links * sizeof(struct mite_dma_descriptor), &ring->descriptors_dma_addr, GFP_KERNEL); if (!ring->descriptors) { - printk("mite: ring buffer allocation failed\n"); + printk(KERN_ERR "mite: ring buffer allocation failed\n"); return -ENOMEM; } ring->n_links = n_links; @@ -370,11 +387,14 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, } ring->descriptors[n_links - 1].next = cpu_to_le32(ring->descriptors_dma_addr); - /* barrier is meant to insure that all the writes to the dma descriptors - have completed before the dma controller is commanded to read them */ + /* + * barrier is meant to insure that all the writes to the dma descriptors + * have completed before the dma controller is commanded to read them + */ smp_wmb(); return 0; } +EXPORT_SYMBOL(mite_buf_change); void mite_prep_dma(struct mite_channel *mite_chan, unsigned int num_device_bits, unsigned int num_memory_bits) @@ -395,16 +415,19 @@ void mite_prep_dma(struct mite_channel *mite_chan, * Link Complete Interrupt: interrupt every time a link * in MITE_RING is completed. This can generate a lot of * extra interrupts, but right now we update the values - * of buf_int_ptr and buf_int_count at each interrupt. A + * of buf_int_ptr and buf_int_count at each interrupt. A * better method is to poll the MITE before each user * "read()" to calculate the number of bytes available. */ chcr |= CHCR_SET_LC_IE; if (num_memory_bits == 32 && num_device_bits == 16) { - /* Doing a combined 32 and 16 bit byteswap gets the 16 bit samples into the fifo in the right order. - Tested doing 32 bit memory to 16 bit device transfers to the analog out of a pxi-6281, - which has mite version = 1, type = 4. This also works for dma reads from the counters - on e-series boards. */ + /* + * Doing a combined 32 and 16 bit byteswap gets the 16 bit + * samples into the fifo in the right order. Tested doing 32 bit + * memory to 16 bit device transfers to the analog out of a + * pxi-6281, which has mite version = 1, type = 4. This also + * works for dma reads from the counters on e-series boards. + */ chcr |= CHCR_BYTE_SWAP_DEVICE | CHCR_BYTE_SWAP_MEMORY; } if (mite_chan->dir == COMEDI_INPUT) @@ -425,7 +448,8 @@ void mite_prep_dma(struct mite_channel *mite_chan, mcr |= CR_PSIZE32; break; default: - printk("mite: bug! invalid mem bit width for dma transfer\n"); + printk(KERN_WARNING "mite: bug! invalid mem bit width for dma " + "transfer\n"); break; } writel(mcr, mite->mite_io_addr + MITE_MCR(mite_chan->channel)); @@ -444,7 +468,8 @@ void mite_prep_dma(struct mite_channel *mite_chan, dcr |= CR_PSIZE32; break; default: - printk("mite: bug! invalid dev bit width for dma transfer\n"); + printk(KERN_WARNING "mite: bug! invalid dev bit width for dma " + "transfer\n"); break; } writel(dcr, mite->mite_io_addr + MITE_DCR(mite_chan->channel)); @@ -462,6 +487,7 @@ void mite_prep_dma(struct mite_channel *mite_chan, MDPRINTK("exit mite_prep_dma\n"); } +EXPORT_SYMBOL(mite_prep_dma); u32 mite_device_bytes_transferred(struct mite_channel *mite_chan) { @@ -469,48 +495,53 @@ u32 mite_device_bytes_transferred(struct mite_channel *mite_chan) return readl(mite->mite_io_addr + MITE_DAR(mite_chan->channel)); } -u32 mite_bytes_in_transit(struct mite_channel * mite_chan) +u32 mite_bytes_in_transit(struct mite_channel *mite_chan) { struct mite_struct *mite = mite_chan->mite; return readl(mite->mite_io_addr + MITE_FCR(mite_chan->channel)) & 0x000000FF; } +EXPORT_SYMBOL(mite_bytes_in_transit); -/* returns lower bound for number of bytes transferred from device to memory */ -u32 mite_bytes_written_to_memory_lb(struct mite_channel * mite_chan) +/* returns lower bound for number of bytes transferred from device to memory */ +u32 mite_bytes_written_to_memory_lb(struct mite_channel *mite_chan) { u32 device_byte_count; device_byte_count = mite_device_bytes_transferred(mite_chan); return device_byte_count - mite_bytes_in_transit(mite_chan); } +EXPORT_SYMBOL(mite_bytes_written_to_memory_lb); -/* returns upper bound for number of bytes transferred from device to memory */ -u32 mite_bytes_written_to_memory_ub(struct mite_channel * mite_chan) +/* returns upper bound for number of bytes transferred from device to memory */ +u32 mite_bytes_written_to_memory_ub(struct mite_channel *mite_chan) { u32 in_transit_count; in_transit_count = mite_bytes_in_transit(mite_chan); return mite_device_bytes_transferred(mite_chan) - in_transit_count; } +EXPORT_SYMBOL(mite_bytes_written_to_memory_ub); -/* returns lower bound for number of bytes read from memory for transfer to device */ -u32 mite_bytes_read_from_memory_lb(struct mite_channel * mite_chan) +/* returns lower bound for number of bytes read from memory to device */ +u32 mite_bytes_read_from_memory_lb(struct mite_channel *mite_chan) { u32 device_byte_count; device_byte_count = mite_device_bytes_transferred(mite_chan); return device_byte_count + mite_bytes_in_transit(mite_chan); } +EXPORT_SYMBOL(mite_bytes_read_from_memory_lb); -/* returns upper bound for number of bytes read from memory for transfer to device */ -u32 mite_bytes_read_from_memory_ub(struct mite_channel * mite_chan) +/* returns upper bound for number of bytes read from memory to device */ +u32 mite_bytes_read_from_memory_ub(struct mite_channel *mite_chan) { u32 in_transit_count; in_transit_count = mite_bytes_in_transit(mite_chan); return mite_device_bytes_transferred(mite_chan) + in_transit_count; } +EXPORT_SYMBOL(mite_bytes_read_from_memory_ub); unsigned mite_dma_tcr(struct mite_channel *mite_chan) { @@ -525,6 +556,7 @@ unsigned mite_dma_tcr(struct mite_channel *mite_chan) return tcr; } +EXPORT_SYMBOL(mite_dma_tcr); void mite_dma_disarm(struct mite_channel *mite_chan) { @@ -535,6 +567,7 @@ void mite_dma_disarm(struct mite_channel *mite_chan) chor = CHOR_ABORT; writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel)); } +EXPORT_SYMBOL(mite_dma_disarm); int mite_sync_input_dma(struct mite_channel *mite_chan, struct comedi_async *async) @@ -544,7 +577,7 @@ int mite_sync_input_dma(struct mite_channel *mite_chan, const unsigned bytes_per_scan = cfc_bytes_per_scan(async->subdevice); old_alloc_count = async->buf_write_alloc_count; - /* write alloc as much as we can */ + /* write alloc as much as we can */ comedi_buf_write_alloc(async, async->prealloc_bufsz); nbytes = mite_bytes_written_to_memory_lb(mite_chan); @@ -571,6 +604,7 @@ int mite_sync_input_dma(struct mite_channel *mite_chan, async->events |= COMEDI_CB_BLOCK; return 0; } +EXPORT_SYMBOL(mite_sync_input_dma); int mite_sync_output_dma(struct mite_channel *mite_chan, struct comedi_async *async) @@ -593,7 +627,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, (int)(nbytes_ub - stop_count) > 0) nbytes_ub = stop_count; if ((int)(nbytes_ub - old_alloc_count) > 0) { - printk("mite: DMA underrun\n"); + printk(KERN_ERR "mite: DMA underrun\n"); async->events |= COMEDI_CB_OVERFLOW; return -1; } @@ -607,6 +641,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, } return 0; } +EXPORT_SYMBOL(mite_sync_output_dma); unsigned mite_get_status(struct mite_channel *mite_chan) { @@ -625,6 +660,7 @@ unsigned mite_get_status(struct mite_channel *mite_chan) spin_unlock_irqrestore(&mite->lock, flags); return status; } +EXPORT_SYMBOL(mite_get_status); int mite_done(struct mite_channel *mite_chan) { @@ -638,6 +674,7 @@ int mite_done(struct mite_channel *mite_chan) spin_unlock_irqrestore(&mite->lock, flags); return done; } +EXPORT_SYMBOL(mite_done); #ifdef DEBUG_MITE @@ -719,46 +756,51 @@ void mite_dump_regs(struct mite_channel *mite_chan) unsigned long addr = 0; unsigned long temp = 0; - printk("mite_dump_regs ch%i\n", mite_chan->channel); - printk("mite address is =0x%08lx\n", mite_io_addr); + printk(KERN_DEBUG "mite_dump_regs ch%i\n", mite_chan->channel); + printk(KERN_DEBUG "mite address is =0x%08lx\n", mite_io_addr); addr = mite_io_addr + MITE_CHOR(channel); - printk("mite status[CHOR]at 0x%08lx =0x%08lx\n", addr, temp = - readl(addr)); + printk(KERN_DEBUG "mite status[CHOR]at 0x%08lx =0x%08lx\n", addr, + temp = readl(addr)); mite_decode(mite_CHOR_strings, temp); addr = mite_io_addr + MITE_CHCR(channel); - printk("mite status[CHCR]at 0x%08lx =0x%08lx\n", addr, temp = - readl(addr)); + printk(KERN_DEBUG "mite status[CHCR]at 0x%08lx =0x%08lx\n", addr, + temp = readl(addr)); mite_decode(mite_CHCR_strings, temp); addr = mite_io_addr + MITE_TCR(channel); - printk("mite status[TCR] at 0x%08lx =0x%08x\n", addr, readl(addr)); - addr = mite_io_addr + MITE_MCR(channel); - printk("mite status[MCR] at 0x%08lx =0x%08lx\n", addr, temp = + printk(KERN_DEBUG "mite status[TCR] at 0x%08lx =0x%08x\n", addr, readl(addr)); + addr = mite_io_addr + MITE_MCR(channel); + printk(KERN_DEBUG "mite status[MCR] at 0x%08lx =0x%08lx\n", addr, + temp = readl(addr)); mite_decode(mite_MCR_strings, temp); addr = mite_io_addr + MITE_MAR(channel); - printk("mite status[MAR] at 0x%08lx =0x%08x\n", addr, readl(addr)); - addr = mite_io_addr + MITE_DCR(channel); - printk("mite status[DCR] at 0x%08lx =0x%08lx\n", addr, temp = + printk(KERN_DEBUG "mite status[MAR] at 0x%08lx =0x%08x\n", addr, readl(addr)); + addr = mite_io_addr + MITE_DCR(channel); + printk(KERN_DEBUG "mite status[DCR] at 0x%08lx =0x%08lx\n", addr, + temp = readl(addr)); mite_decode(mite_DCR_strings, temp); addr = mite_io_addr + MITE_DAR(channel); - printk("mite status[DAR] at 0x%08lx =0x%08x\n", addr, readl(addr)); - addr = mite_io_addr + MITE_LKCR(channel); - printk("mite status[LKCR]at 0x%08lx =0x%08lx\n", addr, temp = + printk(KERN_DEBUG "mite status[DAR] at 0x%08lx =0x%08x\n", addr, readl(addr)); + addr = mite_io_addr + MITE_LKCR(channel); + printk(KERN_DEBUG "mite status[LKCR]at 0x%08lx =0x%08lx\n", addr, + temp = readl(addr)); mite_decode(mite_LKCR_strings, temp); addr = mite_io_addr + MITE_LKAR(channel); - printk("mite status[LKAR]at 0x%08lx =0x%08x\n", addr, readl(addr)); - - addr = mite_io_addr + MITE_CHSR(channel); - printk("mite status[CHSR]at 0x%08lx =0x%08lx\n", addr, temp = + printk(KERN_DEBUG "mite status[LKAR]at 0x%08lx =0x%08x\n", addr, readl(addr)); + addr = mite_io_addr + MITE_CHSR(channel); + printk(KERN_DEBUG "mite status[CHSR]at 0x%08lx =0x%08lx\n", addr, + temp = readl(addr)); mite_decode(mite_CHSR_strings, temp); addr = mite_io_addr + MITE_FCR(channel); - printk("mite status[FCR] at 0x%08lx =0x%08x\n\n", addr, readl(addr)); + printk(KERN_DEBUG "mite status[FCR] at 0x%08lx =0x%08x\n\n", addr, + readl(addr)); } +EXPORT_SYMBOL(mite_dump_regs); static void mite_decode(char **bit_str, unsigned int bits) { @@ -766,10 +808,11 @@ static void mite_decode(char **bit_str, unsigned int bits) for (i = 31; i >= 0; i--) { if (bits & (1 << i)) - printk(" %s", bit_str[i]); + printk(KERN_DEBUG " %s", bit_str[i]); } - printk("\n"); + printk(KERN_DEBUG "\n"); } +EXPORT_SYMBOL(mite_decode); #endif #ifdef MODULE @@ -785,36 +828,4 @@ void __exit cleanup_module(void) { mite_cleanup(); } - -EXPORT_SYMBOL(mite_dma_tcr); -EXPORT_SYMBOL(mite_dma_arm); -EXPORT_SYMBOL(mite_dma_disarm); -EXPORT_SYMBOL(mite_sync_input_dma); -EXPORT_SYMBOL(mite_sync_output_dma); -EXPORT_SYMBOL(mite_setup); -EXPORT_SYMBOL(mite_setup2); -EXPORT_SYMBOL(mite_unsetup); -#if 0 -EXPORT_SYMBOL(mite_kvmem_segment_load); -EXPORT_SYMBOL(mite_ll_from_kvmem); -EXPORT_SYMBOL(mite_setregs); -#endif -EXPORT_SYMBOL(mite_devices); -EXPORT_SYMBOL(mite_list_devices); -EXPORT_SYMBOL(mite_request_channel_in_range); -EXPORT_SYMBOL(mite_release_channel); -EXPORT_SYMBOL(mite_prep_dma); -EXPORT_SYMBOL(mite_buf_change); -EXPORT_SYMBOL(mite_bytes_written_to_memory_lb); -EXPORT_SYMBOL(mite_bytes_written_to_memory_ub); -EXPORT_SYMBOL(mite_bytes_read_from_memory_lb); -EXPORT_SYMBOL(mite_bytes_read_from_memory_ub); -EXPORT_SYMBOL(mite_bytes_in_transit); -EXPORT_SYMBOL(mite_get_status); -EXPORT_SYMBOL(mite_done); -#ifdef DEBUG_MITE -EXPORT_SYMBOL(mite_decode); -EXPORT_SYMBOL(mite_dump_regs); -#endif - #endif diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h index 0518fadc4daa39119e3b0f32354f50639fb69f5f..9d5049f8fa858a89eb7dfdee555e342fc76560ef 100644 --- a/drivers/staging/comedi/drivers/mite.h +++ b/drivers/staging/comedi/drivers/mite.h @@ -163,13 +163,6 @@ u32 mite_bytes_in_transit(struct mite_channel *mite_chan); unsigned mite_get_status(struct mite_channel *mite_chan); int mite_done(struct mite_channel *mite_chan); -#if 0 -unsigned long mite_ll_from_kvmem(struct mite_struct *mite, - struct comedi_async *async, int len); -void mite_setregs(struct mite_struct *mite, unsigned long ll_start, int chan, - int dir); -#endif - void mite_prep_dma(struct mite_channel *mite_chan, unsigned int num_device_bits, unsigned int num_memory_bits); int mite_buf_change(struct mite_dma_descriptor_ring *ring, diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index 5d6af9c459db0d37cddc6e9fa0c12e38d92d71cb..6b22f0f8f06a3dce026937195c6503d927878bae 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -144,9 +144,8 @@ static int multiq3_ao_insn_read(struct comedi_device *dev, int i; int chan = CR_CHAN(insn->chanspec); - for (i = 0; i < insn->n; i++) { + for (i = 0; i < insn->n; i++) data[i] = devpriv->ao_readback[chan]; - } return i; } @@ -253,20 +252,20 @@ static int multiq3_attach(struct comedi_device *dev, struct comedi_subdevice *s; iobase = it->options[0]; - printk("comedi%d: multiq3: 0x%04lx ", dev->minor, iobase); + printk(KERN_INFO "comedi%d: multiq3: 0x%04lx ", dev->minor, iobase); if (!request_region(iobase, MULTIQ3_SIZE, "multiq3")) { - printk("comedi%d: I/O port conflict\n", dev->minor); + printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor); return -EIO; } dev->iobase = iobase; irq = it->options[1]; - if (irq) { - printk("comedi%d: irq = %u ignored\n", dev->minor, irq); - } else { - printk("comedi%d: no irq\n", dev->minor); - } + if (irq) + printk(KERN_WARNING "comedi%d: irq = %u ignored\n", + dev->minor, irq); + else + printk(KERN_WARNING "comedi%d: no irq\n", dev->minor); dev->board_name = "multiq3"; result = alloc_subdevices(dev, 5); if (result < 0) @@ -330,14 +329,12 @@ static int multiq3_attach(struct comedi_device *dev, static int multiq3_detach(struct comedi_device *dev) { - printk("comedi%d: multiq3: remove\n", dev->minor); + printk(KERN_INFO "comedi%d: multiq3: remove\n", dev->minor); - if (dev->iobase) { + if (dev->iobase) release_region(dev->iobase, MULTIQ3_SIZE); - } - if (dev->irq) { + if (dev->irq) free_irq(dev->irq, dev); - } return 0; } diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index b37ef37c2d2df454701b60c0662455ace55554bd..653b4c8700af6103deada261e2bbb1fcad1644af 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -273,7 +273,8 @@ static int ni6527_intr_cmdtest(struct comedi_device *dev, if (err) return 1; - /* step 2: make sure trigger sources are unique and mutually compatible */ + /* step 2: make sure trigger sources are unique and */ + /* are mutually compatible */ if (err) return 2; @@ -377,7 +378,7 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int ret; - printk("comedi%d: ni6527:", dev->minor); + printk(KERN_INFO "comedi%d: ni6527\n", dev->minor); ret = alloc_private(dev, sizeof(struct ni6527_private)); if (ret < 0) @@ -389,14 +390,13 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it) ret = mite_setup(devpriv->mite); if (ret < 0) { - printk("error setting up mite\n"); + printk(KERN_ERR "comedi: error setting up mite\n"); return ret; } dev->board_name = this_board->name; - printk(" %s", dev->board_name); - - printk(" ID=0x%02x", readb(devpriv->mite->daq_io_addr + ID_Register)); + printk(KERN_INFO "comedi board: %s, ID=0x%02x\n", dev->board_name, + readb(devpriv->mite->daq_io_addr + ID_Register)); ret = alloc_subdevices(dev, 3); if (ret < 0) @@ -415,7 +415,7 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 24; - s->range_table = &range_unknown; /* FIXME: actually conductance */ + s->range_table = &range_unknown; /* FIXME: actually conductance */ s->maxdata = 1; s->insn_bits = ni6527_do_insn_bits; @@ -442,30 +442,25 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it) ret = request_irq(mite_irq(devpriv->mite), ni6527_interrupt, IRQF_SHARED, "ni6527", dev); - if (ret < 0) { - printk(" irq not available"); - } else + if (ret < 0) + printk(KERN_WARNING "comedi i6527 irq not available\n"); + else dev->irq = mite_irq(devpriv->mite); - printk("\n"); - return 0; } static int ni6527_detach(struct comedi_device *dev) { - if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) { + if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control); - } - if (dev->irq) { + if (dev->irq) free_irq(dev->irq, dev); - } - if (devpriv && devpriv->mite) { + if (devpriv && devpriv->mite) mite_unsetup(devpriv->mite); - } return 0; } @@ -491,7 +486,7 @@ static int ni6527_find_device(struct comedi_device *dev, int bus, int slot) } } } - printk("no device found\n"); + printk(KERN_ERR "comedi 6527: no device found\n"); mite_list_devices(); return -EIO; } diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index 8adb2373984651e55a94915da3deea4a663d6f2e..3778565c1f6bbbc30cea1855d678a82ebe6f4d6f 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -32,7 +32,8 @@ Configuration options: [0] - I/O port base address [1] - IRQ (unused) [2] - DMA (unused) - [3] - analog output range, set by jumpers on hardware (0 for -10 to 10V bipolar, 1 for 0V to 10V unipolar) + [3] - analog output range, set by jumpers on hardware (0 for -10 to 10V + bipolar, 1 for 0V to 10V unipolar) */ /* @@ -431,9 +432,8 @@ static int atao_calib_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { int i; - for (i = 0; i < insn->n; i++) { + for (i = 0; i < insn->n; i++) data[i] = 0; /* XXX */ - } return insn->n; } diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 901833d9b772b4bd83bcbdf9a4463dda4c98d604..cf4f241f210a69109257cdd242563c36cf258d0b 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -200,8 +200,8 @@ struct atmio16d_private { enum { dac_2comp, dac_straight } dac0_coding, dac1_coding; const struct comedi_lrange *ao_range_type_list[2]; unsigned int ao_readback[2]; - unsigned int com_reg_1_state; /* current state of command register 1 */ - unsigned int com_reg_2_state; /* current state of command register 2 */ + unsigned int com_reg_1_state; /* current state of command register 1 */ + unsigned int com_reg_2_state; /* current state of command register 2 */ }; static void reset_counters(struct comedi_device *dev) @@ -279,7 +279,9 @@ static irqreturn_t atmio16d_interrupt(int irq, void *d) struct comedi_device *dev = d; struct comedi_subdevice *s = dev->subdevices + 0; -/* printk("atmio16d_interrupt!\n"); */ +#ifdef DEBUG1 + printk(KERN_DEBUG "atmio16d_interrupt!\n"); +#endif comedi_buf_put(s->async, inw(dev->iobase + AD_FIFO_REG)); @@ -293,7 +295,7 @@ static int atmio16d_ai_cmdtest(struct comedi_device *dev, { int err = 0, tmp; #ifdef DEBUG1 - printk("atmio16d_ai_cmdtest\n"); + printk(KERN_DEBUG "atmio16d_ai_cmdtest\n"); #endif /* make sure triggers are valid */ tmp = cmd->start_src; @@ -324,8 +326,8 @@ static int atmio16d_ai_cmdtest(struct comedi_device *dev, if (err) return 1; - /* step 2: make sure trigger sources are unique and mutually compatible */ - /* note that mutual compatiblity is not an issue here */ + /* step 2: make sure trigger sources are unique & mutually compatible */ + /* note that mutual compatibility is not an issue here */ if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->scan_begin_src != TRIG_EXT && cmd->scan_begin_src != TRIG_TIMER) @@ -397,7 +399,7 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, unsigned int sample_count, tmp, chan, gain; int i; #ifdef DEBUG1 - printk("atmio16d_ai_cmd\n"); + printk(KERN_DEBUG "atmio16d_ai_cmd\n"); #endif /* This is slowly becoming a working command interface. * * It is still uber-experimental */ @@ -436,10 +438,10 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, } else if (cmd->convert_arg < 655360000) { base_clock = CLOCK_100_KHZ; timer = cmd->convert_arg / 10000; - } else if (cmd->convert_arg <= 0xffffffff /* 6553600000 */ ) { + } else if (cmd->convert_arg <= 0xffffffff /* 6553600000 */) { base_clock = CLOCK_10_KHZ; timer = cmd->convert_arg / 100000; - } else if (cmd->convert_arg <= 0xffffffff /* 65536000000 */ ) { + } else if (cmd->convert_arg <= 0xffffffff /* 65536000000 */) { base_clock = CLOCK_1_KHZ; timer = cmd->convert_arg / 1000000; } @@ -504,10 +506,10 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, } else if (cmd->scan_begin_arg < 655360000) { base_clock = CLOCK_100_KHZ; timer = cmd->scan_begin_arg / 10000; - } else if (cmd->scan_begin_arg < 0xffffffff /* 6553600000 */ ) { + } else if (cmd->scan_begin_arg < 0xffffffff /* 6553600000 */) { base_clock = CLOCK_10_KHZ; timer = cmd->scan_begin_arg / 100000; - } else if (cmd->scan_begin_arg < 0xffffffff /* 65536000000 */ ) { + } else if (cmd->scan_begin_arg < 0xffffffff /* 65536000000 */) { base_clock = CLOCK_1_KHZ; timer = cmd->scan_begin_arg / 1000000; } @@ -559,7 +561,7 @@ static int atmio16d_ai_insn_read(struct comedi_device *dev, int status; #ifdef DEBUG1 - printk("atmio16d_ai_insn_read\n"); + printk(KERN_DEBUG "atmio16d_ai_insn_read\n"); #endif chan = CR_CHAN(insn->chanspec); gain = CR_RANGE(insn->chanspec); @@ -580,19 +582,18 @@ static int atmio16d_ai_insn_read(struct comedi_device *dev, /* check conversion status */ status = inw(dev->iobase + STAT_REG); #ifdef DEBUG1 - printk("status=%x\n", status); + printk(KERN_DEBUG "status=%x\n", status); #endif if (status & STAT_AD_CONVAVAIL) { /* read the data now */ data[i] = inw(dev->iobase + AD_FIFO_REG); /* change to two's complement if need be */ - if (devpriv->adc_coding == adc_2comp) { + if (devpriv->adc_coding == adc_2comp) data[i] ^= 0x800; - } break; } if (status & STAT_AD_OVERFLOW) { - printk("atmio16d: a/d FIFO overflow\n"); + printk(KERN_INFO "atmio16d: a/d FIFO overflow\n"); outw(0, dev->iobase + AD_CLEAR_REG); return -ETIME; @@ -600,7 +601,7 @@ static int atmio16d_ai_insn_read(struct comedi_device *dev, } /* end waiting, now check if it timed out */ if (t == ATMIO16D_TIMEOUT) { - printk("atmio16d: timeout\n"); + printk(KERN_INFO "atmio16d: timeout\n"); return -ETIME; } @@ -615,13 +616,11 @@ static int atmio16d_ao_insn_read(struct comedi_device *dev, { int i; #ifdef DEBUG1 - printk("atmio16d_ao_insn_read\n"); + printk(KERN_DEBUG "atmio16d_ao_insn_read\n"); #endif - for (i = 0; i < insn->n; i++) { + for (i = 0; i < insn->n; i++) data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)]; - } - return i; } @@ -633,7 +632,7 @@ static int atmio16d_ao_insn_write(struct comedi_device *dev, int chan; int d; #ifdef DEBUG1 - printk("atmio16d_ao_insn_write\n"); + printk(KERN_DEBUG "atmio16d_ao_insn_write\n"); #endif chan = CR_CHAN(insn->chanspec); @@ -642,15 +641,13 @@ static int atmio16d_ao_insn_write(struct comedi_device *dev, d = data[i]; switch (chan) { case 0: - if (devpriv->dac0_coding == dac_2comp) { + if (devpriv->dac0_coding == dac_2comp) d ^= 0x800; - } outw(d, dev->iobase + DAC0_REG); break; case 1: - if (devpriv->dac1_coding == dac_2comp) { + if (devpriv->dac1_coding == dac_2comp) d ^= 0x800; - } outw(d, dev->iobase + DAC1_REG); break; default: @@ -705,29 +702,29 @@ static int atmio16d_dio_insn_config(struct comedi_device *dev, /* options[0] - I/O port options[1] - MIO irq - 0 == no irq - N == irq N {3,4,5,6,7,9,10,11,12,14,15} + 0 == no irq + N == irq N {3,4,5,6,7,9,10,11,12,14,15} options[2] - DIO irq - 0 == no irq - N == irq N {3,4,5,6,7,9} + 0 == no irq + N == irq N {3,4,5,6,7,9} options[3] - DMA1 channel - 0 == no DMA - N == DMA N {5,6,7} + 0 == no DMA + N == DMA N {5,6,7} options[4] - DMA2 channel - 0 == no DMA - N == DMA N {5,6,7} + 0 == no DMA + N == DMA N {5,6,7} options[5] - a/d mux - 0=differential, 1=single + 0=differential, 1=single options[6] - a/d range - 0=bipolar10, 1=bipolar5, 2=unipolar10 + 0=bipolar10, 1=bipolar5, 2=unipolar10 options[7] - dac0 range - 0=bipolar, 1=unipolar + 0=bipolar, 1=unipolar options[8] - dac0 reference - 0=internal, 1=external + 0=internal, 1=external options[9] - dac0 coding - 0=2's comp, 1=straight binary + 0=2's comp, 1=straight binary options[10] - dac1 range options[11] - dac1 reference @@ -745,7 +742,7 @@ static int atmio16d_attach(struct comedi_device *dev, /* make sure the address range is free and allocate it */ iobase = it->options[0]; - printk("comedi%d: atmio16d: 0x%04lx ", dev->minor, iobase); + printk(KERN_INFO "comedi%d: atmio16d: 0x%04lx ", dev->minor, iobase); if (!request_region(iobase, ATMIO16D_SIZE, "ni_atmio16d")) { printk("I/O port conflict\n"); return -EIO; @@ -772,13 +769,13 @@ static int atmio16d_attach(struct comedi_device *dev, ret = request_irq(irq, atmio16d_interrupt, 0, "atmio16d", dev); if (ret < 0) { - printk("failed to allocate irq %u\n", irq); + printk(KERN_INFO "failed to allocate irq %u\n", irq); return ret; } dev->irq = irq; - printk("( irq = %u )\n", irq); + printk(KERN_INFO "( irq = %u )\n", irq); } else { - printk("( no irq )"); + printk(KERN_INFO "( no irq )"); } /* set device options */ @@ -855,11 +852,10 @@ static int atmio16d_attach(struct comedi_device *dev, /* 8255 subdevice */ s++; - if (boardtype->has_8255) { + if (boardtype->has_8255) subdev_8255_init(dev, s, NULL, dev->iobase); - } else { + else s->type = COMEDI_SUBD_UNUSED; - } /* don't yet know how to deal with counter/timers */ #if 0 @@ -876,7 +872,7 @@ static int atmio16d_attach(struct comedi_device *dev, static int atmio16d_detach(struct comedi_device *dev) { - printk("comedi%d: atmio16d: remove\n", dev->minor); + printk(KERN_INFO "comedi%d: atmio16d: remove\n", dev->minor); if (dev->subdevices && boardtype->has_8255) subdev_8255_cleanup(dev, dev->subdevices + 3); diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h index 82596345dcf4b651c8a9056fa98e72d5266155ac..422cee58a9676e2fd9a71f9d1eec4d2d8613a4f5 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.h +++ b/drivers/staging/comedi/drivers/ni_labpc.h @@ -38,19 +38,27 @@ struct labpc_board_struct { int device_id; /* device id for pci and pcmcia boards */ int ai_speed; /* maximum input speed in nanoseconds */ enum labpc_bustype bustype; /* ISA/PCI/etc. */ - enum labpc_register_layout register_layout; /* 1200 has extra registers compared to pc+ */ + + /* 1200 has extra registers compared to pc+ */ + enum labpc_register_layout register_layout; int has_ao; /* has analog output true/false */ const struct comedi_lrange *ai_range_table; const int *ai_range_code; const int *ai_range_is_unipolar; - unsigned ai_scan_up:1; /* board can auto scan up in ai channels, not just down */ - unsigned memory_mapped_io:1; /* uses memory mapped io instead of ioports */ + + /* board can auto scan up in ai channels, not just down */ + unsigned ai_scan_up:1; + + /* uses memory mapped io instead of ioports */ + unsigned memory_mapped_io:1; }; struct labpc_private { struct mite_struct *mite; /* for mite chip on pci-1200 */ - volatile unsigned long long count; /* number of data points left to be taken */ - unsigned int ao_value[NUM_AO_CHAN]; /* software copy of analog output values */ + /* number of data points left to be taken */ + volatile unsigned long long count; + /* software copy of analog output values */ + unsigned int ao_value[NUM_AO_CHAN]; /* software copys of bits written to command registers */ volatile unsigned int command1_bits; volatile unsigned int command2_bits; @@ -61,16 +69,34 @@ struct labpc_private { /* store last read of board status registers */ volatile unsigned int status1_bits; volatile unsigned int status2_bits; - unsigned int divisor_a0; /* value to load into board's counter a0 (conversion pacing) for timed conversions */ - unsigned int divisor_b0; /* value to load into board's counter b0 (master) for timed conversions */ - unsigned int divisor_b1; /* value to load into board's counter b1 (scan pacing) for timed conversions */ + /* + * value to load into board's counter a0 (conversion pacing) for timed + * conversions + */ + unsigned int divisor_a0; + /* + * value to load into board's counter b0 (master) for timed conversions + */ + unsigned int divisor_b0; + /* + * value to load into board's counter b1 (scan pacing) for timed + * conversions + */ + unsigned int divisor_b1; unsigned int dma_chan; /* dma channel to use */ u16 *dma_buffer; /* buffer ai will dma into */ - unsigned int dma_transfer_size; /* transfer size in bytes for current transfer */ - enum transfer_type current_transfer; /* we are using dma/fifo-half-full/etc. */ - unsigned int eeprom_data[EEPROM_SIZE]; /* stores contents of board's eeprom */ - unsigned int caldac[16]; /* stores settings of calibration dacs */ - /* function pointers so we can use inb/outb or readb/writeb as appropriate */ + /* transfer size in bytes for current transfer */ + unsigned int dma_transfer_size; + /* we are using dma/fifo-half-full/etc. */ + enum transfer_type current_transfer; + /* stores contents of board's eeprom */ + unsigned int eeprom_data[EEPROM_SIZE]; + /* stores settings of calibration dacs */ + unsigned int caldac[16]; + /* + * function pointers so we can use inb/outb or readb/writeb as + * appropriate + */ unsigned int (*read_byte) (unsigned long address); void (*write_byte) (unsigned int byte, unsigned long address); }; diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index 7d514b3ee75436c5f4c8e345cd8ffdf57b15f93e..0b963bb3328bdcaff6efdbc3fae2baf6ea15876d 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -59,8 +59,7 @@ NI manuals: */ -#undef LABPC_DEBUG - /* #define LABPC_DEBUG *//* enable debugging messages */ +#undef LABPC_DEBUG /* debugging messages */ #include "../comedidev.h" @@ -77,14 +76,15 @@ NI manuals: #include #include -static struct pcmcia_device *pcmcia_cur_dev = NULL; +static struct pcmcia_device *pcmcia_cur_dev; static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it); static const struct labpc_board_struct labpc_cs_boards[] = { { .name = "daqcard-1200", - .device_id = 0x103, /* 0x10b is manufacturer id, 0x103 is device id */ + .device_id = 0x103, /* 0x10b is manufacturer id, + 0x103 is device id */ .ai_speed = 10000, .bustype = pcmcia_bustype, .register_layout = labpc_1200_layout, @@ -273,9 +273,8 @@ static void labpc_cs_detach(struct pcmcia_device *link) labpc_release(link); } - /* This points to the parent local_info_t struct */ - if (link->priv) - kfree(link->priv); + /* This points to the parent local_info_t struct (may be null) */ + kfree(link->priv); } /* labpc_cs_detach */ diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 753ee05123425211c3c22d17ab15c9432ded7a2a..d6d49c3bbf1ce57ce12142a39e24d0d2929aedc8 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -2207,7 +2207,7 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, /* step 2: make sure trigger sources are unique and mutually compatible */ - /* note that mutual compatiblity is not an issue here */ + /* note that mutual compatibility is not an issue here */ if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) err++; diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index d692f4bb47eaed1bd9930d152e584e0a968ef42a..dc4849a40c97818ba5b20493c218e6586bebb116 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -250,9 +250,8 @@ static int mio_cs_detach(struct comedi_device *dev) /* PCMCIA layer frees the IO region */ - if (dev->irq) { + if (dev->irq) free_irq(dev->irq, dev); - } return 0; } @@ -293,9 +292,8 @@ static void cs_detach(struct pcmcia_device *link) { DPRINTK("cs_detach(link=%p)\n", link); - if (link->dev_node) { + if (link->dev_node) cs_release(link); - } } static int mio_cs_suspend(struct pcmcia_device *link) @@ -387,9 +385,8 @@ static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it) } printk("\n"); printk(" board fingerprint (windowed):"); - for (i = 0; i < 10; i++) { + for (i = 0; i < 10; i++) printk(" 0x%04x", win_in(i)); - } printk("\n"); } #endif diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index d544698f2414e2b5685fdd5ac7df950548582589..2d88a5be65ff773dbd4caf821d8bb21ccf6e93f3 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -795,7 +795,7 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev, /* step 2: make sure trigger sources are unique and mutually compatible */ - /* note that mutual compatiblity is not an issue here */ + /* note that mutual compatibility is not an issue here */ if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_INT) err++; if (cmd->scan_begin_src != TRIG_TIMER && diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index dd9db069a932469f85aae339b842b8faef4fdb1f..4914784f6995d121a76e028474ce6eb2ec9076e2 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -407,6 +407,7 @@ static int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * 0xb4 = Select Counter 2 | LSB/MSB | Mode=2 | Binary */ + timer1 = timer2 = 0; i8253_cascade_ns_to_timer(i8253_osc_base, &timer1, &timer2, &cmd->scan_begin_arg, TRIG_ROUND_NEAREST); diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index ccadd095f630c484f1699fbcb4a835d0b880af90..6a1a9790a9072109168b009a6e56ddf98ce21abe 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -39,27 +39,27 @@ Interrupts are not supported. Options for PCL-726: [0] - IO Base [2]...[7] - D/A output range for channel 1-6: - 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, - 4: 4-20mA, 5: unknown (external reference) + 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, + 4: 4-20mA, 5: unknown (external reference) Options for PCL-727: [0] - IO Base [2]...[13] - D/A output range for channel 1-12: - 0: 0-5V, 1: 0-10V, 2: +/-5V, - 3: 4-20mA + 0: 0-5V, 1: 0-10V, 2: +/-5V, + 3: 4-20mA Options for PCL-728 and ACL-6128: [0] - IO Base [2], [3] - D/A output range for channel 1 and 2: - 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, - 4: 4-20mA, 5: 0-20mA + 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, + 4: 4-20mA, 5: 0-20mA Options for ACL-6126: [0] - IO Base [1] - IRQ (0=disable, 3, 5, 6, 7, 9, 10, 11, 12, 15) (currently ignored) [2]...[7] - D/A output range for channel 1-6: - 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, - 4: 4-20mA + 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, + 4: 4-20mA */ /* @@ -127,7 +127,8 @@ struct pcl726_board { int di_lo; int do_hi; int do_lo; - const struct comedi_lrange *const *range_type_list; /* list of supported ranges */ + const struct comedi_lrange *const *range_type_list; + /* list of supported ranges */ }; static const struct pcl726_board boardtypes[] = { @@ -204,9 +205,8 @@ static int pcl726_ao_insn_read(struct comedi_device *dev, int chan = CR_CHAN(insn->chanspec); int n; - for (n = 0; n < insn->n; n++) { + for (n = 0; n < insn->n; n++) data[n] = devpriv->ao_readback[chan]; - } return n; } @@ -256,10 +256,10 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) iobase = it->options[0]; iorange = this_board->io_range; - printk("comedi%d: pcl726: board=%s, 0x%03lx ", dev->minor, + printk(KERN_WARNING "comedi%d: pcl726: board=%s, 0x%03lx ", dev->minor, this_board->name, iobase); if (!request_region(iobase, iorange, "pcl726")) { - printk("I/O port conflict\n"); + printk(KERN_WARNING "I/O port conflict\n"); return -EIO; } @@ -283,16 +283,16 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->first_chan = 2; if (irq) { /* we want to use IRQ */ if (((1 << irq) & boardtypes[board].IRQbits) == 0) { - printk - (", IRQ %d is out of allowed range, DISABLING IT", - irq); + printk(KERN_WARNING + ", IRQ %d is out of allowed range," + " DISABLING IT", irq); irq = 0; /* Bad IRQ */ } else { if (request_irq(irq, interrupt_pcl818, 0, "pcl726", dev)) { - printk - (", unable to allocate IRQ %d, DISABLING IT", - irq); + printk(KERN_WARNING + ", unable to allocate IRQ %d," + " DISABLING IT", irq); irq = 0; /* Can't use IRQ */ } else { printk(", irq=%d", irq); @@ -372,9 +372,8 @@ static int pcl726_detach(struct comedi_device *dev) /* printk("comedi%d: pcl726: remove\n",dev->minor); */ #ifdef ACL6126_IRQ - if (dev->irq) { + if (dev->irq) free_irq(dev->irq, dev); - } #endif if (dev->iobase) diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 0b51a48c3ad83fe2f54840427955afe76da961a1..0a5bc3d6da8c30549a8be2d6865574ee07be9686 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -51,7 +51,7 @@ Options for PCL-812: 5=A/D input range is +/-0.3125V [5] - 0=D/A outputs 0-5V (internal reference -5V) 1=D/A outputs 0-10V (internal reference -10V) - 2=D/A outputs unknow (external reference) + 2=D/A outputs unknown (external reference) Options for PCL-812PG, ACL-8112PG: [0] - IO Base @@ -63,7 +63,7 @@ Options for PCL-812PG, ACL-8112PG: 1=A/D have max +/-10V input [5] - 0=D/A outputs 0-5V (internal reference -5V) 1=D/A outputs 0-10V (internal reference -10V) - 2=D/A outputs unknow (external reference) + 2=D/A outputs unknown (external reference) Options for ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH, ACL-8216, A-826PG: [0] - IO Base @@ -75,7 +75,7 @@ Options for ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH, ACL-8216, A-826PG: 1=A/D channels are DIFF [5] - 0=D/A outputs 0-5V (internal reference -5V) 1=D/A outputs 0-10V (internal reference -10V) - 2=D/A outputs unknow (external reference) + 2=D/A outputs unknown (external reference) Options for A-821PGL/PGH: [0] - IO Base diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index fa2414500a07fe1b16879cf2ab98b78f4e5f4294..852fe2458fdc16682c1953de9efc974e5806654f 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -112,7 +112,7 @@ struct pcl816_board { int n_dichan; /* num of DI chans */ int n_dochan; /* num of DO chans */ const struct comedi_lrange *ai_range_type; /* default A/D rangelist */ - const struct comedi_lrange *ao_range_type; /* dafault D/A rangelist */ + const struct comedi_lrange *ao_range_type; /* default D/A rangelist */ unsigned int io_range; /* len of IO space */ unsigned int IRQbits; /* allowed interrupts */ unsigned int DMAbits; /* allowed DMA chans */ @@ -445,7 +445,7 @@ static irqreturn_t interrupt_pcl816(int irq, void *d) comedi_error(dev, "bad IRQ!"); return IRQ_NONE; } - comedi_error(dev, "IRQ from unknow source!"); + comedi_error(dev, "IRQ from unknown source!"); return IRQ_NONE; } @@ -472,7 +472,7 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; - int tmp, divisor1, divisor2; + int tmp, divisor1 = 0, divisor2 = 0; DEBUG(printk("pcl816 pcl812_ai_cmdtest\n"); pcl816_cmdtest_out(-1, cmd); ); @@ -488,7 +488,9 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) err++; - if (!(cmd->convert_src & (TRIG_EXT | TRIG_TIMER))) + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_EXT | TRIG_TIMER; + if (!cmd->convert_src || tmp != cmd->convert_src) err++; tmp = cmd->scan_end_src; diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index e95229b13118e154ae6b63a4657fec3c4c3ebd67..d0481013a837bb5fcc30da7a6cb8aedd70b85c80 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -50,7 +50,7 @@ A word or two about DMA. Driver support DMA operations at two ways: 1, 10=A/D input -10V..+10V [5] - 0, 5=D/A output 0-5V (internal reference -5V) 1, 10=D/A output 0-10V (internal reference -10V) - 2 =D/A output unknow (external reference) + 2 =D/A output unknown (external reference) Options for PCL-818, PCL-818H: [0] - IO Base @@ -60,7 +60,7 @@ A word or two about DMA. Driver support DMA operations at two ways: 1= 1MHz clock for 8254 [4] - 0, 5=D/A output 0-5V (internal reference -5V) 1, 10=D/A output 0-10V (internal reference -10V) - 2 =D/A output unknow (external reference) + 2 =D/A output unknown (external reference) Options for PCL-818HD, PCL-818HG: [0] - IO Base @@ -71,7 +71,7 @@ A word or two about DMA. Driver support DMA operations at two ways: 1= 1MHz clock for 8254 [4] - 0, 5=D/A output 0-5V (internal reference -5V) 1, 10=D/A output 0-10V (internal reference -10V) - 2 =D/A output unknow (external reference) + 2 =D/A output unknown (external reference) Options for PCL-718: [0] - IO Base @@ -92,7 +92,7 @@ A word or two about DMA. Driver support DMA operations at two ways: 10= user defined unipolar [5] - 0, 5=D/A outputs 0-5V (internal reference -5V) 1, 10=D/A outputs 0-10V (internal reference -10V) - 2=D/A outputs unknow (external reference) + 2=D/A outputs unknown (external reference) [6] - 0, 60=max 60kHz A/D sampling 1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed) @@ -876,7 +876,7 @@ static irqreturn_t interrupt_pcl818(int irq, void *d) return IRQ_NONE; } - comedi_error(dev, "IRQ from unknow source!"); + comedi_error(dev, "IRQ from unknown source!"); return IRQ_NONE; } @@ -970,7 +970,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev, struct comedi_subdevice *s) { struct comedi_cmd *cmd = &s->async->cmd; - int divisor1, divisor2; + int divisor1 = 0, divisor2 = 0; unsigned int seglen; printk("pcl818_ai_cmd_mode()\n"); @@ -1089,7 +1089,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev, static int pcl818_ao_mode13(int mode, struct comedi_device *dev, struct comedi_subdevice *s, comedi_trig * it) { - int divisor1, divisor2; + int divisor1 = 0, divisor2 = 0; if (!dev->irq) { comedi_error(dev, "IRQ not defined!"); @@ -1287,7 +1287,7 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; - int tmp, divisor1, divisor2; + int tmp, divisor1 = 0, divisor2 = 0; /* step 1: make sure trigger sources are trivially valid */ diff --git a/drivers/staging/comedi/drivers/pcm_common.c b/drivers/staging/comedi/drivers/pcm_common.c index ebd9838232af6e9e05f2f8020b2dc9d000b75c25..52c2a6698214277393d00490c412ffdc5a60591a 100644 --- a/drivers/staging/comedi/drivers/pcm_common.c +++ b/drivers/staging/comedi/drivers/pcm_common.c @@ -41,7 +41,8 @@ int comedi_pcm_cmdtest(struct comedi_device *dev, if (err) return 1; - /* step 2: make sure trigger sources are unique and mutually compatible */ + /* step 2: make sure trigger sources are unique and + * mutually compatible */ /* these tests are true if more than one _src bit is set */ if ((cmd->start_src & (cmd->start_src - 1)) != 0) @@ -107,5 +108,4 @@ int comedi_pcm_cmdtest(struct comedi_device *dev, return 0; } - EXPORT_SYMBOL(comedi_pcm_cmdtest); diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index d812c2c3af12f64a554fcecd562ab7fe8dca09c8..35ba93989a36e1c55854280214f668bfbddbdc62 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -32,8 +32,10 @@ Winsystems. This board is a PC-104 based I/O board. It contains four subdevices: subdevice 0 - 16 channels of 16-bit AI subdevice 1 - 8 channels of 16-bit AO - subdevice 2 - first 24 channels of the 48 channel of DIO (with edge-triggered interrupt support) - subdevice 3 - last 24 channels of the 48 channel DIO (no interrupt support for this bank of channels) + subdevice 2 - first 24 channels of the 48 channel of DIO + (with edge-triggered interrupt support) + subdevice 3 - last 24 channels of the 48 channel DIO + (no interrupt support for this bank of channels) Some notes: @@ -70,7 +72,8 @@ four subdevices: Configuration Options: [0] - I/O port base address - [1] - IRQ (optional -- for edge-detect interrupt support only, leave out if you don't need this feature) + [1] - IRQ (optional -- for edge-detect interrupt support only, + leave out if you don't need this feature) */ #include @@ -115,9 +118,11 @@ Configuration Options: #define REG_PORT4 0x4 #define REG_PORT5 0x5 #define REG_INT_PENDING 0x6 -#define REG_PAGELOCK 0x7 /* page selector register, upper 2 bits select a page - and bits 0-5 are used to 'lock down' a particular - port above to make it readonly. */ +#define REG_PAGELOCK 0x7 /* + * page selector register, upper 2 bits select + * a page and bits 0-5 are used to 'lock down' + * a particular port above to make it readonly. + */ #define REG_POL0 0x8 #define REG_POL1 0x9 #define REG_POL2 0xA @@ -134,7 +139,7 @@ Configuration Options: #define REG_PAGE_BITOFFSET 6 #define REG_LOCK_BITOFFSET 0 #define REG_PAGE_MASK (~((0x1<asics[asic].num = asic; devpriv->asics[asic].iobase = dev->iobase + 16 + asic * ASIC_IOSIZE; - devpriv->asics[asic].irq = 0; /* this gets actually set at the end of - this function when we - request_irqs */ + /* + * this gets actually set at the end of this function when we + * request_irqs + */ + devpriv->asics[asic].irq = 0; spin_lock_init(&devpriv->asics[asic].spinlock); } @@ -463,7 +492,10 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (thisasic_chanct < CHANS_PER_PORT * INTR_PORTS_PER_ASIC && subpriv->dio.intr.asic < 0) { - /* this is an interrupt subdevice, so setup the struct */ + /* + * this is an interrupt subdevice, + * so setup the struct + */ subpriv->dio.intr.asic = asic; subpriv->dio.intr.active = 0; subpriv->dio.intr.stop_count = 0; @@ -484,7 +516,11 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) chans_left -= s->n_chan; if (!chans_left) { - asic = 0; /* reset the asic to our first asic, to do intr subdevs */ + /* + * reset the asic to our first asic, + * to do intr subdevs + */ + asic = 0; port = 0; } @@ -507,8 +543,10 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->asics[asic].irq = irq[asic]; } - dev->irq = irq[0]; /* grr.. wish comedi dev struct supported multiple - irqs.. */ + dev->irq = irq[0]; /* + * grr.. wish comedi dev struct supported + * multiple irqs.. + */ if (irq[0]) { printk("irq: %u ", irq[0]); @@ -604,9 +642,14 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev, #endif if (write_mask_byte) { - /* this byte has some write_bits -- so set the output lines */ - byte &= ~write_mask_byte; /* clear bits for write mask */ - byte |= ~data_byte & write_mask_byte; /* set to inverted data_byte */ + /* + * this byte has some write_bits + * -- so set the output lines + */ + /* clear bits for write mask */ + byte &= ~write_mask_byte; + /* set to inverted data_byte */ + byte |= ~data_byte & write_mask_byte; /* Write out the new digital output state */ outb(byte, ioaddr); } @@ -670,9 +713,11 @@ static int pcmmio_dio_insn_config(struct comedi_device *dev, byte &= ~(1 << bit_no); /**< set input channel to '0' */ - /* write out byte -- this is the only time we actually affect the - hardware as all channels are implicitly output -- but input - channels are set to float-high */ + /* + * write out byte -- this is the only time we actually affect + * the hardware as all channels are implicitly output + * -- but input channels are set to float-high + */ outb(byte, ioaddr); /* save to io_bits */ @@ -726,8 +771,8 @@ static void init_asics(struct comedi_device *dev) outb(0xff, baseaddr + REG_ENAB0); */ /* END DEBUG */ - switch_page(dev, asic, 0); /* switch back to default page 0 */ - + /* switch back to default page 0 */ + switch_page(dev, asic, 0); } } @@ -806,7 +851,10 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) REG_INT_ID0 + port); if (io_lines_with_edges) - /* clear pending interrupt */ + /* + * clear pending + * interrupt + */ outb(0, iobase + REG_INT_ID0 + port); @@ -825,14 +873,21 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) if (triggered) { struct comedi_subdevice *s; - /* TODO here: dispatch io lines to subdevs with commands.. */ + /* + * TODO here: dispatch io lines to subdevs + * with commands.. + */ printk ("PCMMIO DEBUG: got edge detect interrupt %d asic %d which_chans: %06x\n", irq, asic, triggered); for (s = dev->subdevices + 2; s < dev->subdevices + dev->n_subdevices; ++s) { - if (subpriv->dio.intr.asic == asic) { /* this is an interrupt subdev, and it matches this asic! */ + /* + * this is an interrupt subdev, + * and it matches this asic! + */ + if (subpriv->dio.intr.asic == asic) { unsigned long flags; unsigned oldevents; @@ -867,9 +922,8 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) n < len; n++) { ch = CR_CHAN(s->async->cmd.chanlist[n]); - if (mytrig & (1U << ch)) { + if (mytrig & (1U << ch)) val |= (1U << n); - } } /* Write the scan to the buffer. */ if (comedi_buf_put(s->async, ((short *)&val)[0]) @@ -877,8 +931,7 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) comedi_buf_put (s->async, ((short *) - &val)[1])) - { + &val)[1])) { s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); } else { /* Overflow! Stop acquisition!! */ @@ -981,9 +1034,16 @@ static int pcmmio_start_intr(struct comedi_device *dev, 1) << subpriv->dio.intr.first_chan; subpriv->dio.intr.enabled_mask = bits; - { /* the below code configures the board to use a specific IRQ from 0-15. */ + { + /* + * the below code configures the board + * to use a specific IRQ from 0-15. + */ unsigned char b; - /* set resource enable register to enable IRQ operation */ + /* + * set resource enable register + * to enable IRQ operation + */ outb(1 << 4, dev->iobase + 3); /* set bits 0-3 of b to the irq number from 0-15 */ b = dev->irq & ((1 << 4) - 1); @@ -1037,14 +1097,12 @@ pcmmio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); s->async->inttrig = 0; - if (subpriv->dio.intr.active) { + if (subpriv->dio.intr.active) event = pcmmio_start_intr(dev, s); - } spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); - if (event) { + if (event) comedi_event(dev, s); - } return 1; } @@ -1086,9 +1144,8 @@ static int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); - if (event) { + if (event) comedi_event(dev, s); - } return 0; } @@ -1136,17 +1193,32 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, short sample, adc_adjust = 0; if (chan > 7) - chan -= 8, iooffset = 4; /* use the second dword for channels > 7 */ + chan -= 8, iooffset = 4; /* + * use the second dword + * for channels > 7 + */ if (aref != AREF_DIFF) { aref = AREF_GROUND; - command_byte |= 1 << 7; /* set bit 7 to indicate single-ended */ + command_byte |= 1 << 7; /* + * set bit 7 to indicate + * single-ended + */ } if (range < 2) - adc_adjust = 0x8000; /* bipolar ranges (-5,5 .. -10,10 need to be adjusted -- that is.. they need to wrap around by adding 0x8000 */ + adc_adjust = 0x8000; /* + * bipolar ranges + * (-5,5 .. -10,10 need to be + * adjusted -- that is.. they + * need to wrap around by + * adding 0x8000 + */ if (chan % 2) { - command_byte |= 1 << 6; /* odd-numbered channels have bit 6 set */ + command_byte |= 1 << 6; /* + * odd-numbered channels + * have bit 6 set + */ } /* select the channel, bits 4-5 == chan/2 */ @@ -1156,16 +1228,22 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, command_byte |= (range & 0x3) << 2; /* need to do this twice to make sure mux settled */ - outb(command_byte, iobase + iooffset + 2); /* chan/range/aref select */ + /* chan/range/aref select */ + outb(command_byte, iobase + iooffset + 2); - adc_wait_ready(iobase + iooffset); /* wait for the adc to say it finised the conversion */ + /* wait for the adc to say it finised the conversion */ + adc_wait_ready(iobase + iooffset); - outb(command_byte, iobase + iooffset + 2); /* select the chan/range/aref AGAIN */ + /* select the chan/range/aref AGAIN */ + outb(command_byte, iobase + iooffset + 2); adc_wait_ready(iobase + iooffset); - sample = inb(iobase + iooffset + 0); /* read data lo byte */ - sample |= inb(iobase + iooffset + 1) << 8; /* read data hi byte */ + /* read data lo byte */ + sample = inb(iobase + iooffset + 0); + + /* read data hi byte */ + sample |= inb(iobase + iooffset + 1) << 8; sample += adc_adjust; /* adjustment .. munge data */ data[n] = sample; } @@ -1227,15 +1305,24 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, wait_dac_ready(iobase + iooffset); - outb(data[n] & 0xff, iobase + iooffset + 0); /* low order byte */ - outb((data[n] >> 8) & 0xff, iobase + iooffset + 1); /* high order byte */ - command_byte = 0x70 | (chan << 1); /* set bit 4 of command byte to indicate data is loaded and trigger conversion */ + /* low order byte */ + outb(data[n] & 0xff, iobase + iooffset + 0); + + /* high order byte */ + outb((data[n] >> 8) & 0xff, iobase + iooffset + 1); + + /* + * set bit 4 of command byte to indicate + * data is loaded and trigger conversion + */ + command_byte = 0x70 | (chan << 1); /* trigger converion */ outb(command_byte, iobase + iooffset + 2); wait_dac_ready(iobase + iooffset); - subpriv->ao.shadow_samples[chan] = data[n]; /* save to shadow register for ao_rinsn */ + /* save to shadow register for ao_rinsn */ + subpriv->ao.shadow_samples[chan] = data[n]; } } return n; diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 5256fd9331629409b79aac5436c0cf25d32e1f81..3325f24448b599989d6bc258c0226fb088982145 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -489,7 +489,7 @@ static int daqp_ai_cmdtest(struct comedi_device *dev, /* step 2: make sure trigger sources are unique and mutually compatible */ - /* note that mutual compatiblity is not an issue here */ + /* note that mutual compatibility is not an issue here */ if (cmd->scan_begin_src != TRIG_TIMER && cmd->scan_begin_src != TRIG_FOLLOW) err++; diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index f35cce5971401fd13ee8ea4520325c93fb5adf2d..8626658e778c118ffa5b7d6589aba4be4ee7d02b 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1768,7 +1768,7 @@ static int rtd_ai_cmdtest(struct comedi_device *dev, /* step 2: make sure trigger sources are unique and mutually compatible */ - /* note that mutual compatiblity is not an issue here */ + /* note that mutual compatibility is not an issue here */ if (cmd->scan_begin_src != TRIG_TIMER && cmd->scan_begin_src != TRIG_EXT) { err++; diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 80d2787d10637d0ab2bf53600d615ba5ff3206dc..fdd7ab954d8c0dd9c440b94e8c281e1f95b8c81a 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -1926,7 +1926,7 @@ static int s626_ai_cmdtest(struct comedi_device *dev, /* step 2: make sure trigger sources are unique and mutually compatible */ - /* note that mutual compatiblity is not an issue here */ + /* note that mutual compatibility is not an issue here */ if (cmd->scan_begin_src != TRIG_TIMER && cmd->scan_begin_src != TRIG_EXT && cmd->scan_begin_src != TRIG_FOLLOW) diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h index 1d04922ea16c778eca8c71f8024015a46272e7af..d02742a95294a3fddf85bbede6fe505a451a65ff 100644 --- a/drivers/staging/comedi/drivers/s626.h +++ b/drivers/staging/comedi/drivers/s626.h @@ -76,14 +76,6 @@ #define FALSE (0) #endif -#if !defined(EXTERN) -#if defined(__cplusplus) -#define EXTERN extern "C" -#else -#define EXTERN extern -#endif -#endif - #if !defined(INLINE) #define INLINE static __inline #endif diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index 82aa86e718b2c819ff6e81e33282eda355ea8e08..db37dcdd98b6ebcd214fa2e0e660cf35aeb74bdc 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -125,14 +125,9 @@ struct serial_data { static long tty_ioctl(struct file *f, unsigned op, unsigned long param) { -#ifdef HAVE_UNLOCKED_IOCTL - if (f->f_op->unlocked_ioctl) { + if (f->f_op->unlocked_ioctl) return f->f_op->unlocked_ioctl(f, op, param); - } -#endif - if (f->f_op->ioctl) { - return f->f_op->ioctl(f->f_dentry->d_inode, f, op, param); - } + return -ENOSYS; } @@ -409,8 +404,8 @@ static void serial_2002_open(struct comedi_device *dev) } else { struct config_t { - int kind; - int bits; + short int kind; + short int bits; int min; int max; }; diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index 3dee62aa2d7bb044a879e766ee976871ccfdba98..aba57d93dd3d7cbdf2c2fc718bb8514abb904d3c 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -399,7 +399,7 @@ static int skel_ai_cmdtest(struct comedi_device *dev, /* step 2: make sure trigger sources are unique and mutually compatible */ - /* note that mutual compatiblity is not an issue here */ + /* note that mutual compatibility is not an issue here */ if (cmd->scan_begin_src != TRIG_TIMER && cmd->scan_begin_src != TRIG_EXT) err++; diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index cca4e869f0ecf10868a17d7d7cf060f6b94b87df..06c020466298a04cd82dae666133309be624a976 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1,4 +1,4 @@ -#define DRIVER_VERSION "v2.2" +#define DRIVER_VERSION "v2.3" #define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com" #define DRIVER_DESC "Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com" /* @@ -80,6 +80,7 @@ sampling rate. If you sample two channels you get 4kHz and so on. * 2.0: PWM seems to be stable and is not interfering with the other functions * 2.1: changed PWM API * 2.2: added firmware kernel request to fix an udev problem + * 2.3: corrected a bug in bulk timeouts which were far too short * */ @@ -101,8 +102,8 @@ sampling rate. If you sample two channels you get 4kHz and so on. #define BOARDNAME "usbdux" -/* timeout for the USB-transfer */ -#define EZTIMEOUT 30 +/* timeout for the USB-transfer in ms*/ +#define BULK_TIMEOUT 1000 /* constants for "firmware" upload and download */ #define USBDUXSUB_FIRMWARE 0xA0 @@ -750,7 +751,7 @@ static int usbduxsub_start(struct usbduxsub *usbduxsub) /* Length */ 1, /* Timeout */ - EZTIMEOUT); + BULK_TIMEOUT); if (errcode < 0) { dev_err(&usbduxsub->interface->dev, "comedi_: control msg failed (start)\n"); @@ -780,7 +781,7 @@ static int usbduxsub_stop(struct usbduxsub *usbduxsub) /* Length */ 1, /* Timeout */ - EZTIMEOUT); + BULK_TIMEOUT); if (errcode < 0) { dev_err(&usbduxsub->interface->dev, "comedi_: control msg failed (stop)\n"); @@ -810,7 +811,7 @@ static int usbduxsub_upload(struct usbduxsub *usbduxsub, /* length */ len, /* timeout */ - EZTIMEOUT); + BULK_TIMEOUT); dev_dbg(&usbduxsub->interface->dev, "comedi_: result=%d\n", errcode); if (errcode < 0) { dev_err(&usbduxsub->interface->dev, "comedi_: upload failed\n"); @@ -979,7 +980,7 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, /* * step 2: make sure trigger sources are unique and mutually compatible - * note that mutual compatiblity is not an issue here + * note that mutual compatibility is not an issue here */ if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->scan_begin_src != TRIG_EXT && @@ -1110,7 +1111,7 @@ static int send_dux_commands(struct usbduxsub *this_usbduxsub, int cmd_type) usb_sndbulkpipe(this_usbduxsub->usbdev, COMMAND_OUT_EP), this_usbduxsub->dux_commands, SIZEOFDUXBUFFER, - &nsent, 10); + &nsent, BULK_TIMEOUT); if (result < 0) dev_err(&this_usbduxsub->interface->dev, "comedi%d: " "could not transmit dux_command to the usb-device, " @@ -1130,7 +1131,7 @@ static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command) usb_rcvbulkpipe(this_usbduxsub->usbdev, COMMAND_IN_EP), this_usbduxsub->insnBuffer, SIZEINSNBUF, - &nrec, 1); + &nrec, BULK_TIMEOUT); if (result < 0) { dev_err(&this_usbduxsub->interface->dev, "comedi%d: " "insn: USB error %d while receiving DUX command" @@ -1557,7 +1558,7 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev, /* * step 2: make sure trigger sources are unique and mutually compatible - * note that mutual compatiblity is not an issue here + * note that mutual compatibility is not an issue here */ if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->scan_begin_src != TRIG_EXT && @@ -2327,9 +2328,11 @@ static void usbdux_firmware_request_complete_handler(const struct firmware *fw, if (ret) { dev_err(&usbdev->dev, "Could not upload firmware (err=%d)\n", ret); - return; + goto out; } comedi_usb_auto_config(usbdev, BOARDNAME); + out: + release_firmware(fw); } /* allocate memory for the urbs and initialise them */ @@ -2580,6 +2583,7 @@ static int usbduxsub_probe(struct usb_interface *uinterf, FW_ACTION_HOTPLUG, "usbdux_firmware.bin", &udev->dev, + GFP_KERNEL, usbduxsub + index, usbdux_firmware_request_complete_handler); diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index d143222579c2bfff829df86c879fce48763bdc94..2e675cce7dbf5157fc4613c5f84fc4e4143c2e59 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -1451,10 +1451,12 @@ static void usbduxfast_firmware_request_complete_handler(const struct firmware if (ret) { dev_err(&usbdev->dev, "Could not upload firmware (err=%d)\n", ret); - return; + goto out; } comedi_usb_auto_config(usbdev, BOARDNAME); + out: + release_firmware(fw); } /* @@ -1569,6 +1571,7 @@ static int usbduxfastsub_probe(struct usb_interface *uinterf, FW_ACTION_HOTPLUG, "usbduxfast_firmware.bin", &udev->dev, + GFP_KERNEL, usbduxfastsub + index, usbduxfast_firmware_request_complete_handler); diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index c335040778f0c55fd16e2ec449a508cf043711bb..c34a0b9141e2a51f012edbc6ed2b10154401dad4 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -76,18 +76,18 @@ enum { }; static struct usb_device_id vmk80xx_id_table[] = { - {USB_DEVICE(0x10cf, 0x5500),.driver_info = DEVICE_VMK8055}, - {USB_DEVICE(0x10cf, 0x5501),.driver_info = DEVICE_VMK8055}, - {USB_DEVICE(0x10cf, 0x5502),.driver_info = DEVICE_VMK8055}, - {USB_DEVICE(0x10cf, 0x5503),.driver_info = DEVICE_VMK8055}, - {USB_DEVICE(0x10cf, 0x8061),.driver_info = DEVICE_VMK8061}, - {USB_DEVICE(0x10cf, 0x8062),.driver_info = DEVICE_VMK8061}, - {USB_DEVICE(0x10cf, 0x8063),.driver_info = DEVICE_VMK8061}, - {USB_DEVICE(0x10cf, 0x8064),.driver_info = DEVICE_VMK8061}, - {USB_DEVICE(0x10cf, 0x8065),.driver_info = DEVICE_VMK8061}, - {USB_DEVICE(0x10cf, 0x8066),.driver_info = DEVICE_VMK8061}, - {USB_DEVICE(0x10cf, 0x8067),.driver_info = DEVICE_VMK8061}, - {USB_DEVICE(0x10cf, 0x8068),.driver_info = DEVICE_VMK8061}, + {USB_DEVICE(0x10cf, 0x5500), .driver_info = DEVICE_VMK8055}, + {USB_DEVICE(0x10cf, 0x5501), .driver_info = DEVICE_VMK8055}, + {USB_DEVICE(0x10cf, 0x5502), .driver_info = DEVICE_VMK8055}, + {USB_DEVICE(0x10cf, 0x5503), .driver_info = DEVICE_VMK8055}, + {USB_DEVICE(0x10cf, 0x8061), .driver_info = DEVICE_VMK8061}, + {USB_DEVICE(0x10cf, 0x8062), .driver_info = DEVICE_VMK8061}, + {USB_DEVICE(0x10cf, 0x8063), .driver_info = DEVICE_VMK8061}, + {USB_DEVICE(0x10cf, 0x8064), .driver_info = DEVICE_VMK8061}, + {USB_DEVICE(0x10cf, 0x8065), .driver_info = DEVICE_VMK8061}, + {USB_DEVICE(0x10cf, 0x8066), .driver_info = DEVICE_VMK8061}, + {USB_DEVICE(0x10cf, 0x8067), .driver_info = DEVICE_VMK8061}, + {USB_DEVICE(0x10cf, 0x8068), .driver_info = DEVICE_VMK8061}, {} /* terminating entry */ }; diff --git a/drivers/staging/cx25821/cx25821-core.c b/drivers/staging/cx25821/cx25821-core.c index 8aceae5a072e08fd4c6b2351b77ac9f445db59dd..67f689de4daada8a8d110c9377ce65e62f6efc60 100644 --- a/drivers/staging/cx25821/cx25821-core.c +++ b/drivers/staging/cx25821/cx25821-core.c @@ -1521,7 +1521,7 @@ static struct pci_driver cx25821_pci_driver = { .resume = NULL, }; -static int cx25821_init(void) +static int __init cx25821_init(void) { INIT_LIST_HEAD(&cx25821_devlist); printk(KERN_INFO "cx25821 driver version %d.%d.%d loaded\n", @@ -1530,7 +1530,7 @@ static int cx25821_init(void) return pci_register_driver(&cx25821_pci_driver); } -static void cx25821_fini(void) +static void __exit cx25821_fini(void) { pci_unregister_driver(&cx25821_pci_driver); } diff --git a/drivers/staging/dream/Kconfig b/drivers/staging/dream/Kconfig index 52bd187de5a7e763c5b9b181d060c79dcc6f1186..4afa081c870c97708bc597de5214b7c571e7ad97 100644 --- a/drivers/staging/dream/Kconfig +++ b/drivers/staging/dream/Kconfig @@ -1,3 +1,7 @@ +config DREAM + tristate "HTC Dream support" + depends on BROKEN + source "drivers/staging/dream/smd/Kconfig" source "drivers/staging/dream/camera/Kconfig" diff --git a/drivers/staging/dream/TODO b/drivers/staging/dream/TODO new file mode 100644 index 0000000000000000000000000000000000000000..c07c8803f07cfc2dd49a448637fff7947b93c849 --- /dev/null +++ b/drivers/staging/dream/TODO @@ -0,0 +1,14 @@ +* remove support for wakelocks since those are not in mainline + +* camera driver uses old V4L API + +* coding style in some places is lacking + +* gpio_input.c has some features matrix_keypad lacks. They should be +merged to gpio_input, with gpio_input.c removed + +* pmem provides interface for userspace. Needs to be reviewed at least. + +* it is probably possible to simplify touchscreen driver using threaded_irq's. + +* touchscreen driver should be switched to oficial multitouch API diff --git a/drivers/staging/dream/camera/msm_camera.c b/drivers/staging/dream/camera/msm_camera.c index 88165998698c66012be01dcdcd0d6d906112f51d..7d938772eacc826077e221323f3c373eadc8959c 100644 --- a/drivers/staging/dream/camera/msm_camera.c +++ b/drivers/staging/dream/camera/msm_camera.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -1597,7 +1598,6 @@ static int __msm_release(struct msm_sync *sync) MSM_DRAIN_QUEUE(sync, pict_frame_q); sync->sctrl.s_release(); - wake_unlock(&sync->wake_lock); sync->apps_id = NULL; CDBG("msm_release completed!\n"); @@ -1806,7 +1806,6 @@ static int __msm_open(struct msm_sync *sync, const char *const apps_id) sync->apps_id = apps_id; if (!sync->opencnt) { - wake_lock(&sync->wake_lock); msm_camvfe_fn_init(&sync->vfefn, sync); if (sync->vfefn.vfe_init) { @@ -2044,8 +2043,6 @@ static int msm_sync_init(struct msm_sync *sync, INIT_LIST_HEAD(&sync->pict_frame_q); init_waitqueue_head(&sync->pict_frame_wait); - wake_lock_init(&sync->wake_lock, WAKE_LOCK_IDLE, "msm_camera"); - rc = msm_camio_probe_on(pdev); if (rc < 0) return rc; @@ -2058,7 +2055,6 @@ static int msm_sync_init(struct msm_sync *sync, if (rc < 0) { pr_err("msm_camera: failed to initialize %s\n", sync->sdata->sensor_name); - wake_lock_destroy(&sync->wake_lock); return rc; } @@ -2070,7 +2066,6 @@ static int msm_sync_init(struct msm_sync *sync, static int msm_sync_destroy(struct msm_sync *sync) { - wake_lock_destroy(&sync->wake_lock); return 0; } diff --git a/drivers/staging/dream/camera/msm_vfe7x.c b/drivers/staging/dream/camera/msm_vfe7x.c index 5de96c5d635233035d1f6e08dc7a0d6a1f617af2..33ab3ac6ac57a61668f4d76e292ee9d0dfba1e98 100644 --- a/drivers/staging/dream/camera/msm_vfe7x.c +++ b/drivers/staging/dream/camera/msm_vfe7x.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/staging/dream/generic_gpio.c b/drivers/staging/dream/generic_gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..fe24d38345d0fafe3667d0e6dc8e5ab0282473aa --- /dev/null +++ b/drivers/staging/dream/generic_gpio.c @@ -0,0 +1,274 @@ +/* arch/arm/mach-msm/generic_gpio.c + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include "gpio_chip.h" + +#define GPIO_NUM_TO_CHIP_INDEX(gpio) ((gpio)>>5) + +struct gpio_state { + unsigned long flags; + int refcount; +}; + +static DEFINE_SPINLOCK(gpio_chips_lock); +static LIST_HEAD(gpio_chip_list); +static struct gpio_chip **gpio_chip_array; +static unsigned long gpio_chip_array_size; + +int register_gpio_chip(struct gpio_chip *new_gpio_chip) +{ + int err = 0; + struct gpio_chip *gpio_chip; + int i; + unsigned long irq_flags; + unsigned int chip_array_start_index, chip_array_end_index; + + new_gpio_chip->state = kzalloc((new_gpio_chip->end + 1 - new_gpio_chip->start) * sizeof(new_gpio_chip->state[0]), GFP_KERNEL); + if (new_gpio_chip->state == NULL) { + printk(KERN_ERR "register_gpio_chip: failed to allocate state\n"); + return -ENOMEM; + } + + spin_lock_irqsave(&gpio_chips_lock, irq_flags); + chip_array_start_index = GPIO_NUM_TO_CHIP_INDEX(new_gpio_chip->start); + chip_array_end_index = GPIO_NUM_TO_CHIP_INDEX(new_gpio_chip->end); + if (chip_array_end_index >= gpio_chip_array_size) { + struct gpio_chip **new_gpio_chip_array; + unsigned long new_gpio_chip_array_size = chip_array_end_index + 1; + + new_gpio_chip_array = kmalloc(new_gpio_chip_array_size * sizeof(new_gpio_chip_array[0]), GFP_ATOMIC); + if (new_gpio_chip_array == NULL) { + printk(KERN_ERR "register_gpio_chip: failed to allocate array\n"); + err = -ENOMEM; + goto failed; + } + for (i = 0; i < gpio_chip_array_size; i++) + new_gpio_chip_array[i] = gpio_chip_array[i]; + for (i = gpio_chip_array_size; i < new_gpio_chip_array_size; i++) + new_gpio_chip_array[i] = NULL; + gpio_chip_array = new_gpio_chip_array; + gpio_chip_array_size = new_gpio_chip_array_size; + } + list_for_each_entry(gpio_chip, &gpio_chip_list, list) { + if (gpio_chip->start > new_gpio_chip->end) { + list_add_tail(&new_gpio_chip->list, &gpio_chip->list); + goto added; + } + if (gpio_chip->end >= new_gpio_chip->start) { + printk(KERN_ERR "register_gpio_source %u-%u overlaps with %u-%u\n", + new_gpio_chip->start, new_gpio_chip->end, + gpio_chip->start, gpio_chip->end); + err = -EBUSY; + goto failed; + } + } + list_add_tail(&new_gpio_chip->list, &gpio_chip_list); +added: + for (i = chip_array_start_index; i <= chip_array_end_index; i++) { + if (gpio_chip_array[i] == NULL || gpio_chip_array[i]->start > new_gpio_chip->start) + gpio_chip_array[i] = new_gpio_chip; + } +failed: + spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); + if (err) + kfree(new_gpio_chip->state); + return err; +} + +static struct gpio_chip *get_gpio_chip_locked(unsigned int gpio) +{ + unsigned long i; + struct gpio_chip *chip; + + i = GPIO_NUM_TO_CHIP_INDEX(gpio); + if (i >= gpio_chip_array_size) + return NULL; + chip = gpio_chip_array[i]; + if (chip == NULL) + return NULL; + list_for_each_entry_from(chip, &gpio_chip_list, list) { + if (gpio < chip->start) + return NULL; + if (gpio <= chip->end) + return chip; + } + return NULL; +} + +static int request_gpio(unsigned int gpio, unsigned long flags) +{ + int err = 0; + struct gpio_chip *chip; + unsigned long irq_flags; + unsigned long chip_index; + + spin_lock_irqsave(&gpio_chips_lock, irq_flags); + chip = get_gpio_chip_locked(gpio); + if (chip == NULL) { + err = -EINVAL; + goto err; + } + chip_index = gpio - chip->start; + if (chip->state[chip_index].refcount == 0) { + chip->configure(chip, gpio, flags); + chip->state[chip_index].flags = flags; + chip->state[chip_index].refcount++; + } else if ((flags & IRQF_SHARED) && (chip->state[chip_index].flags & IRQF_SHARED)) + chip->state[chip_index].refcount++; + else + err = -EBUSY; +err: + spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); + return err; +} + +int gpio_request(unsigned gpio, const char *label) +{ + return request_gpio(gpio, 0); +} +EXPORT_SYMBOL(gpio_request); + +void gpio_free(unsigned gpio) +{ + struct gpio_chip *chip; + unsigned long irq_flags; + unsigned long chip_index; + + spin_lock_irqsave(&gpio_chips_lock, irq_flags); + chip = get_gpio_chip_locked(gpio); + if (chip) { + chip_index = gpio - chip->start; + chip->state[chip_index].refcount--; + } + spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); +} +EXPORT_SYMBOL(gpio_free); + +static int gpio_get_irq_num(unsigned int gpio, unsigned int *irqp, unsigned long *irqnumflagsp) +{ + int ret = -ENOTSUPP; + struct gpio_chip *chip; + unsigned long irq_flags; + + spin_lock_irqsave(&gpio_chips_lock, irq_flags); + chip = get_gpio_chip_locked(gpio); + if (chip && chip->get_irq_num) + ret = chip->get_irq_num(chip, gpio, irqp, irqnumflagsp); + spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); + return ret; +} + +int gpio_to_irq(unsigned gpio) +{ + int ret, irq; + ret = gpio_get_irq_num(gpio, &irq, NULL); + if (ret) + return ret; + return irq; +} +EXPORT_SYMBOL(gpio_to_irq); + +int gpio_configure(unsigned int gpio, unsigned long flags) +{ + int ret = -ENOTSUPP; + struct gpio_chip *chip; + unsigned long irq_flags; + + spin_lock_irqsave(&gpio_chips_lock, irq_flags); + chip = get_gpio_chip_locked(gpio); + if (chip) + ret = chip->configure(chip, gpio, flags); + spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); + return ret; +} +EXPORT_SYMBOL(gpio_configure); + +int gpio_direction_input(unsigned gpio) +{ + return gpio_configure(gpio, GPIOF_INPUT); +} +EXPORT_SYMBOL(gpio_direction_input); + +int gpio_direction_output(unsigned gpio, int value) +{ + gpio_set_value(gpio, value); + return gpio_configure(gpio, GPIOF_DRIVE_OUTPUT); +} +EXPORT_SYMBOL(gpio_direction_output); + +int gpio_get_value(unsigned gpio) +{ + int ret = -ENOTSUPP; + struct gpio_chip *chip; + unsigned long irq_flags; + + spin_lock_irqsave(&gpio_chips_lock, irq_flags); + chip = get_gpio_chip_locked(gpio); + if (chip && chip->read) + ret = chip->read(chip, gpio); + spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); + return ret; +} +EXPORT_SYMBOL(gpio_get_value); + +void gpio_set_value(unsigned gpio, int on) +{ + int ret = -ENOTSUPP; + struct gpio_chip *chip; + unsigned long irq_flags; + + spin_lock_irqsave(&gpio_chips_lock, irq_flags); + chip = get_gpio_chip_locked(gpio); + if (chip && chip->write) + ret = chip->write(chip, gpio, on); + spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); +} +EXPORT_SYMBOL(gpio_set_value); + +int gpio_read_detect_status(unsigned int gpio) +{ + int ret = -ENOTSUPP; + struct gpio_chip *chip; + unsigned long irq_flags; + + spin_lock_irqsave(&gpio_chips_lock, irq_flags); + chip = get_gpio_chip_locked(gpio); + if (chip && chip->read_detect_status) + ret = chip->read_detect_status(chip, gpio); + spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); + return ret; +} +EXPORT_SYMBOL(gpio_read_detect_status); + +int gpio_clear_detect_status(unsigned int gpio) +{ + int ret = -ENOTSUPP; + struct gpio_chip *chip; + unsigned long irq_flags; + + spin_lock_irqsave(&gpio_chips_lock, irq_flags); + chip = get_gpio_chip_locked(gpio); + if (chip && chip->clear_detect_status) + ret = chip->clear_detect_status(chip, gpio); + spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); + return ret; +} +EXPORT_SYMBOL(gpio_clear_detect_status); diff --git a/drivers/staging/dream/gpio_event.c b/drivers/staging/dream/gpio_event.c index 8b64c1e579ba10386ddb4c40ef763a9f722b1ddf..e60e2c0db9c04d349411376e074a0e3c29fb58e8 100644 --- a/drivers/staging/dream/gpio_event.c +++ b/drivers/staging/dream/gpio_event.c @@ -13,7 +13,7 @@ * */ -#include + #include #include #include @@ -23,7 +23,6 @@ struct gpio_event { struct input_dev *input_dev; const struct gpio_event_platform_data *info; - struct early_suspend early_suspend; void *state[0]; }; diff --git a/drivers/staging/dream/gpio_input.c b/drivers/staging/dream/gpio_input.c index 7e307f267a2a059b64a3fb9c8a379b149016b2f8..0638ec43601a9058b05ae7eb7b2f5de7fd7a261e 100644 --- a/drivers/staging/dream/gpio_input.c +++ b/drivers/staging/dream/gpio_input.c @@ -19,7 +19,6 @@ #include #include #include -#include enum { DEBOUNCE_UNSTABLE = BIT(0), /* Got irq, while debouncing */ @@ -44,7 +43,6 @@ struct gpio_input_state { int use_irq; int debounce_count; spinlock_t irq_lock; - struct wake_lock wake_lock; struct gpio_key_state key_state[0]; }; @@ -143,8 +141,6 @@ static enum hrtimer_restart gpio_event_input_timer_func(struct hrtimer *timer) hrtimer_start(timer, ds->info->debounce_time, HRTIMER_MODE_REL); else if (!ds->use_irq) hrtimer_start(timer, ds->info->poll_time, HRTIMER_MODE_REL); - else - wake_unlock(&ds->wake_lock); spin_unlock_irqrestore(&ds->irq_lock, irqflags); @@ -170,7 +166,6 @@ static irqreturn_t gpio_event_input_irq_handler(int irq, void *dev_id) if (ks->debounce & DEBOUNCE_WAIT_IRQ) { ks->debounce = DEBOUNCE_UNKNOWN; if (ds->debounce_count++ == 0) { - wake_lock(&ds->wake_lock); hrtimer_start( &ds->timer, ds->info->debounce_time, HRTIMER_MODE_REL); @@ -277,7 +272,6 @@ int gpio_event_input_func(struct input_dev *input_dev, ds->debounce_count = di->keymap_size; ds->input_dev = input_dev; ds->info = di; - wake_lock_init(&ds->wake_lock, WAKE_LOCK_SUSPEND, "gpio_input"); spin_lock_init(&ds->irq_lock); for (i = 0; i < di->keymap_size; i++) { @@ -336,7 +330,6 @@ err_gpio_configure_failed: err_gpio_request_failed: ; } - wake_lock_destroy(&ds->wake_lock); kfree(ds); err_ds_alloc_failed: return ret; diff --git a/drivers/staging/dream/gpio_matrix.c b/drivers/staging/dream/gpio_matrix.c index c1f47651a4937d5c976a9625ca5da389dd7e4a7c..796de4faf85929d2dcd43cc7b718463ee53c7a78 100644 --- a/drivers/staging/dream/gpio_matrix.c +++ b/drivers/staging/dream/gpio_matrix.c @@ -18,13 +18,11 @@ #include #include #include -#include struct gpio_kp { struct input_dev *input_dev; struct gpio_event_matrix_info *keypad_info; struct hrtimer timer; - struct wake_lock wake_lock; int current_output; unsigned int use_irq:1; unsigned int key_state_changed:1; @@ -199,7 +197,6 @@ static enum hrtimer_restart gpio_keypad_timer_func(struct hrtimer *timer) } for (in = 0; in < mi->ninputs; in++) enable_irq(gpio_to_irq(mi->input_gpios[in])); - wake_unlock(&kp->wake_lock); return HRTIMER_NORESTART; } @@ -222,7 +219,6 @@ static irqreturn_t gpio_keypad_irq_handler(int irq_in, void *dev_id) else gpio_direction_input(mi->output_gpios[i]); } - wake_lock(&kp->wake_lock); hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL); return IRQ_HANDLED; } @@ -363,7 +359,6 @@ int gpio_event_matrix_func(struct input_dev *input_dev, hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); kp->timer.function = gpio_keypad_timer_func; - wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp"); err = gpio_keypad_request_irqs(kp); kp->use_irq = err == 0; @@ -371,8 +366,6 @@ int gpio_event_matrix_func(struct input_dev *input_dev, "in %s mode\n", input_dev->name, kp->use_irq ? "interrupt" : "polling"); - if (kp->use_irq) - wake_lock(&kp->wake_lock); hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL); return 0; @@ -386,7 +379,6 @@ int gpio_event_matrix_func(struct input_dev *input_dev, free_irq(gpio_to_irq(mi->input_gpios[i]), kp); hrtimer_cancel(&kp->timer); - wake_lock_destroy(&kp->wake_lock); for (i = mi->noutputs - 1; i >= 0; i--) { err_gpio_direction_input_failed: gpio_free(mi->input_gpios[i]); diff --git a/drivers/staging/dream/pmem.c b/drivers/staging/dream/pmem.c new file mode 100644 index 0000000000000000000000000000000000000000..def64681234842b4b381457c3a396e903f620148 --- /dev/null +++ b/drivers/staging/dream/pmem.c @@ -0,0 +1,1335 @@ +/* drivers/android/pmem.c + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PMEM_MAX_DEVICES 10 +#define PMEM_MAX_ORDER 128 +#define PMEM_MIN_ALLOC PAGE_SIZE + +#define PMEM_DEBUG 1 + +/* indicates that a refernce to this file has been taken via get_pmem_file, + * the file should not be released until put_pmem_file is called */ +#define PMEM_FLAGS_BUSY 0x1 +/* indicates that this is a suballocation of a larger master range */ +#define PMEM_FLAGS_CONNECTED 0x1 << 1 +/* indicates this is a master and not a sub allocation and that it is mmaped */ +#define PMEM_FLAGS_MASTERMAP 0x1 << 2 +/* submap and unsubmap flags indicate: + * 00: subregion has never been mmaped + * 10: subregion has been mmaped, reference to the mm was taken + * 11: subretion has ben released, refernece to the mm still held + * 01: subretion has been released, reference to the mm has been released + */ +#define PMEM_FLAGS_SUBMAP 0x1 << 3 +#define PMEM_FLAGS_UNSUBMAP 0x1 << 4 + + +struct pmem_data { + /* in alloc mode: an index into the bitmap + * in no_alloc mode: the size of the allocation */ + int index; + /* see flags above for descriptions */ + unsigned int flags; + /* protects this data field, if the mm_mmap sem will be held at the + * same time as this sem, the mm sem must be taken first (as this is + * the order for vma_open and vma_close ops */ + struct rw_semaphore sem; + /* info about the mmaping process */ + struct vm_area_struct *vma; + /* task struct of the mapping process */ + struct task_struct *task; + /* process id of teh mapping process */ + pid_t pid; + /* file descriptor of the master */ + int master_fd; + /* file struct of the master */ + struct file *master_file; + /* a list of currently available regions if this is a suballocation */ + struct list_head region_list; + /* a linked list of data so we can access them for debugging */ + struct list_head list; +#if PMEM_DEBUG + int ref; +#endif +}; + +struct pmem_bits { + unsigned allocated:1; /* 1 if allocated, 0 if free */ + unsigned order:7; /* size of the region in pmem space */ +}; + +struct pmem_region_node { + struct pmem_region region; + struct list_head list; +}; + +#define PMEM_DEBUG_MSGS 0 +#if PMEM_DEBUG_MSGS +#define DLOG(fmt,args...) \ + do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \ + ##args); } \ + while (0) +#else +#define DLOG(x...) do {} while (0) +#endif + +struct pmem_info { + struct miscdevice dev; + /* physical start address of the remaped pmem space */ + unsigned long base; + /* vitual start address of the remaped pmem space */ + unsigned char __iomem *vbase; + /* total size of the pmem space */ + unsigned long size; + /* number of entries in the pmem space */ + unsigned long num_entries; + /* pfn of the garbage page in memory */ + unsigned long garbage_pfn; + /* index of the garbage page in the pmem space */ + int garbage_index; + /* the bitmap for the region indicating which entries are allocated + * and which are free */ + struct pmem_bits *bitmap; + /* indicates the region should not be managed with an allocator */ + unsigned no_allocator; + /* indicates maps of this region should be cached, if a mix of + * cached and uncached is desired, set this and open the device with + * O_SYNC to get an uncached region */ + unsigned cached; + unsigned buffered; + /* in no_allocator mode the first mapper gets the whole space and sets + * this flag */ + unsigned allocated; + /* for debugging, creates a list of pmem file structs, the + * data_list_sem should be taken before pmem_data->sem if both are + * needed */ + struct semaphore data_list_sem; + struct list_head data_list; + /* pmem_sem protects the bitmap array + * a write lock should be held when modifying entries in bitmap + * a read lock should be held when reading data from bits or + * dereferencing a pointer into bitmap + * + * pmem_data->sem protects the pmem data of a particular file + * Many of the function that require the pmem_data->sem have a non- + * locking version for when the caller is already holding that sem. + * + * IF YOU TAKE BOTH LOCKS TAKE THEM IN THIS ORDER: + * down(pmem_data->sem) => down(bitmap_sem) + */ + struct rw_semaphore bitmap_sem; + + long (*ioctl)(struct file *, unsigned int, unsigned long); + int (*release)(struct inode *, struct file *); +}; + +static struct pmem_info pmem[PMEM_MAX_DEVICES]; +static int id_count; + +#define PMEM_IS_FREE(id, index) !(pmem[id].bitmap[index].allocated) +#define PMEM_ORDER(id, index) pmem[id].bitmap[index].order +#define PMEM_BUDDY_INDEX(id, index) (index ^ (1 << PMEM_ORDER(id, index))) +#define PMEM_NEXT_INDEX(id, index) (index + (1 << PMEM_ORDER(id, index))) +#define PMEM_OFFSET(index) (index * PMEM_MIN_ALLOC) +#define PMEM_START_ADDR(id, index) (PMEM_OFFSET(index) + pmem[id].base) +#define PMEM_LEN(id, index) ((1 << PMEM_ORDER(id, index)) * PMEM_MIN_ALLOC) +#define PMEM_END_ADDR(id, index) (PMEM_START_ADDR(id, index) + \ + PMEM_LEN(id, index)) +#define PMEM_START_VADDR(id, index) (PMEM_OFFSET(id, index) + pmem[id].vbase) +#define PMEM_END_VADDR(id, index) (PMEM_START_VADDR(id, index) + \ + PMEM_LEN(id, index)) +#define PMEM_REVOKED(data) (data->flags & PMEM_FLAGS_REVOKED) +#define PMEM_IS_PAGE_ALIGNED(addr) (!((addr) & (~PAGE_MASK))) +#define PMEM_IS_SUBMAP(data) ((data->flags & PMEM_FLAGS_SUBMAP) && \ + (!(data->flags & PMEM_FLAGS_UNSUBMAP))) + +static int pmem_release(struct inode *, struct file *); +static int pmem_mmap(struct file *, struct vm_area_struct *); +static int pmem_open(struct inode *, struct file *); +static long pmem_ioctl(struct file *, unsigned int, unsigned long); + +struct file_operations pmem_fops = { + .release = pmem_release, + .mmap = pmem_mmap, + .open = pmem_open, + .unlocked_ioctl = pmem_ioctl, +}; + +static int get_id(struct file *file) +{ + return MINOR(file->f_dentry->d_inode->i_rdev); +} + +static int is_pmem_file(struct file *file) +{ + int id; + + if (unlikely(!file || !file->f_dentry || !file->f_dentry->d_inode)) + return 0; + id = get_id(file); + if (unlikely(id >= PMEM_MAX_DEVICES)) + return 0; + if (unlikely(file->f_dentry->d_inode->i_rdev != + MKDEV(MISC_MAJOR, pmem[id].dev.minor))) + return 0; + return 1; +} + +static int has_allocation(struct file *file) +{ + struct pmem_data *data; + /* check is_pmem_file first if not accessed via pmem_file_ops */ + + if (unlikely(!file->private_data)) + return 0; + data = (struct pmem_data *)file->private_data; + if (unlikely(data->index < 0)) + return 0; + return 1; +} + +static int is_master_owner(struct file *file) +{ + struct file *master_file; + struct pmem_data *data; + int put_needed, ret = 0; + + if (!is_pmem_file(file) || !has_allocation(file)) + return 0; + data = (struct pmem_data *)file->private_data; + if (PMEM_FLAGS_MASTERMAP & data->flags) + return 1; + master_file = fget_light(data->master_fd, &put_needed); + if (master_file && data->master_file == master_file) + ret = 1; + fput_light(master_file, put_needed); + return ret; +} + +static int pmem_free(int id, int index) +{ + /* caller should hold the write lock on pmem_sem! */ + int buddy, curr = index; + DLOG("index %d\n", index); + + if (pmem[id].no_allocator) { + pmem[id].allocated = 0; + return 0; + } + /* clean up the bitmap, merging any buddies */ + pmem[id].bitmap[curr].allocated = 0; + /* find a slots buddy Buddy# = Slot# ^ (1 << order) + * if the buddy is also free merge them + * repeat until the buddy is not free or end of the bitmap is reached + */ + do { + buddy = PMEM_BUDDY_INDEX(id, curr); + if (PMEM_IS_FREE(id, buddy) && + PMEM_ORDER(id, buddy) == PMEM_ORDER(id, curr)) { + PMEM_ORDER(id, buddy)++; + PMEM_ORDER(id, curr)++; + curr = min(buddy, curr); + } else { + break; + } + } while (curr < pmem[id].num_entries); + + return 0; +} + +static void pmem_revoke(struct file *file, struct pmem_data *data); + +static int pmem_release(struct inode *inode, struct file *file) +{ + struct pmem_data *data = (struct pmem_data *)file->private_data; + struct pmem_region_node *region_node; + struct list_head *elt, *elt2; + int id = get_id(file), ret = 0; + + + down(&pmem[id].data_list_sem); + /* if this file is a master, revoke all the memory in the connected + * files */ + if (PMEM_FLAGS_MASTERMAP & data->flags) { + struct pmem_data *sub_data; + list_for_each(elt, &pmem[id].data_list) { + sub_data = list_entry(elt, struct pmem_data, list); + down_read(&sub_data->sem); + if (PMEM_IS_SUBMAP(sub_data) && + file == sub_data->master_file) { + up_read(&sub_data->sem); + pmem_revoke(file, sub_data); + } else + up_read(&sub_data->sem); + } + } + list_del(&data->list); + up(&pmem[id].data_list_sem); + + + down_write(&data->sem); + + /* if its not a conencted file and it has an allocation, free it */ + if (!(PMEM_FLAGS_CONNECTED & data->flags) && has_allocation(file)) { + down_write(&pmem[id].bitmap_sem); + ret = pmem_free(id, data->index); + up_write(&pmem[id].bitmap_sem); + } + + /* if this file is a submap (mapped, connected file), downref the + * task struct */ + if (PMEM_FLAGS_SUBMAP & data->flags) + if (data->task) { + put_task_struct(data->task); + data->task = NULL; + } + + file->private_data = NULL; + + list_for_each_safe(elt, elt2, &data->region_list) { + region_node = list_entry(elt, struct pmem_region_node, list); + list_del(elt); + kfree(region_node); + } + BUG_ON(!list_empty(&data->region_list)); + + up_write(&data->sem); + kfree(data); + if (pmem[id].release) + ret = pmem[id].release(inode, file); + + return ret; +} + +static int pmem_open(struct inode *inode, struct file *file) +{ + struct pmem_data *data; + int id = get_id(file); + int ret = 0; + + DLOG("current %u file %p(%d)\n", current->pid, file, file_count(file)); + /* setup file->private_data to indicate its unmapped */ + /* you can only open a pmem device one time */ + if (file->private_data != NULL) + return -1; + data = kmalloc(sizeof(struct pmem_data), GFP_KERNEL); + if (!data) { + printk("pmem: unable to allocate memory for pmem metadata."); + return -1; + } + data->flags = 0; + data->index = -1; + data->task = NULL; + data->vma = NULL; + data->pid = 0; + data->master_file = NULL; +#if PMEM_DEBUG + data->ref = 0; +#endif + INIT_LIST_HEAD(&data->region_list); + init_rwsem(&data->sem); + + file->private_data = data; + INIT_LIST_HEAD(&data->list); + + down(&pmem[id].data_list_sem); + list_add(&data->list, &pmem[id].data_list); + up(&pmem[id].data_list_sem); + return ret; +} + +static unsigned long pmem_order(unsigned long len) +{ + int i; + + len = (len + PMEM_MIN_ALLOC - 1)/PMEM_MIN_ALLOC; + len--; + for (i = 0; i < sizeof(len)*8; i++) + if (len >> i == 0) + break; + return i; +} + +static int pmem_allocate(int id, unsigned long len) +{ + /* caller should hold the write lock on pmem_sem! */ + /* return the corresponding pdata[] entry */ + int curr = 0; + int end = pmem[id].num_entries; + int best_fit = -1; + unsigned long order = pmem_order(len); + + if (pmem[id].no_allocator) { + DLOG("no allocator"); + if ((len > pmem[id].size) || pmem[id].allocated) + return -1; + pmem[id].allocated = 1; + return len; + } + + if (order > PMEM_MAX_ORDER) + return -1; + DLOG("order %lx\n", order); + + /* look through the bitmap: + * if you find a free slot of the correct order use it + * otherwise, use the best fit (smallest with size > order) slot + */ + while (curr < end) { + if (PMEM_IS_FREE(id, curr)) { + if (PMEM_ORDER(id, curr) == (unsigned char)order) { + /* set the not free bit and clear others */ + best_fit = curr; + break; + } + if (PMEM_ORDER(id, curr) > (unsigned char)order && + (best_fit < 0 || + PMEM_ORDER(id, curr) < PMEM_ORDER(id, best_fit))) + best_fit = curr; + } + curr = PMEM_NEXT_INDEX(id, curr); + } + + /* if best_fit < 0, there are no suitable slots, + * return an error + */ + if (best_fit < 0) { + printk("pmem: no space left to allocate!\n"); + return -1; + } + + /* now partition the best fit: + * split the slot into 2 buddies of order - 1 + * repeat until the slot is of the correct order + */ + while (PMEM_ORDER(id, best_fit) > (unsigned char)order) { + int buddy; + PMEM_ORDER(id, best_fit) -= 1; + buddy = PMEM_BUDDY_INDEX(id, best_fit); + PMEM_ORDER(id, buddy) = PMEM_ORDER(id, best_fit); + } + pmem[id].bitmap[best_fit].allocated = 1; + return best_fit; +} + +static pgprot_t phys_mem_access_prot(struct file *file, pgprot_t vma_prot) +{ + int id = get_id(file); +#ifdef pgprot_noncached + if (pmem[id].cached == 0 || file->f_flags & O_SYNC) + return pgprot_noncached(vma_prot); +#endif +#ifdef pgprot_ext_buffered + else if (pmem[id].buffered) + return pgprot_ext_buffered(vma_prot); +#endif + return vma_prot; +} + +static unsigned long pmem_start_addr(int id, struct pmem_data *data) +{ + if (pmem[id].no_allocator) + return PMEM_START_ADDR(id, 0); + else + return PMEM_START_ADDR(id, data->index); + +} + +static void *pmem_start_vaddr(int id, struct pmem_data *data) +{ + return pmem_start_addr(id, data) - pmem[id].base + pmem[id].vbase; +} + +static unsigned long pmem_len(int id, struct pmem_data *data) +{ + if (pmem[id].no_allocator) + return data->index; + else + return PMEM_LEN(id, data->index); +} + +static int pmem_map_garbage(int id, struct vm_area_struct *vma, + struct pmem_data *data, unsigned long offset, + unsigned long len) +{ + int i, garbage_pages = len >> PAGE_SHIFT; + + vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP | VM_SHARED | VM_WRITE; + for (i = 0; i < garbage_pages; i++) { + if (vm_insert_pfn(vma, vma->vm_start + offset + (i * PAGE_SIZE), + pmem[id].garbage_pfn)) + return -EAGAIN; + } + return 0; +} + +static int pmem_unmap_pfn_range(int id, struct vm_area_struct *vma, + struct pmem_data *data, unsigned long offset, + unsigned long len) +{ + int garbage_pages; + DLOG("unmap offset %lx len %lx\n", offset, len); + + BUG_ON(!PMEM_IS_PAGE_ALIGNED(len)); + + garbage_pages = len >> PAGE_SHIFT; + zap_page_range(vma, vma->vm_start + offset, len, NULL); + pmem_map_garbage(id, vma, data, offset, len); + return 0; +} + +static int pmem_map_pfn_range(int id, struct vm_area_struct *vma, + struct pmem_data *data, unsigned long offset, + unsigned long len) +{ + DLOG("map offset %lx len %lx\n", offset, len); + BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_start)); + BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_end)); + BUG_ON(!PMEM_IS_PAGE_ALIGNED(len)); + BUG_ON(!PMEM_IS_PAGE_ALIGNED(offset)); + + if (io_remap_pfn_range(vma, vma->vm_start + offset, + (pmem_start_addr(id, data) + offset) >> PAGE_SHIFT, + len, vma->vm_page_prot)) { + return -EAGAIN; + } + return 0; +} + +static int pmem_remap_pfn_range(int id, struct vm_area_struct *vma, + struct pmem_data *data, unsigned long offset, + unsigned long len) +{ + /* hold the mm semp for the vma you are modifying when you call this */ + BUG_ON(!vma); + zap_page_range(vma, vma->vm_start + offset, len, NULL); + return pmem_map_pfn_range(id, vma, data, offset, len); +} + +static void pmem_vma_open(struct vm_area_struct *vma) +{ + struct file *file = vma->vm_file; + struct pmem_data *data = file->private_data; + int id = get_id(file); + /* this should never be called as we don't support copying pmem + * ranges via fork */ + BUG_ON(!has_allocation(file)); + down_write(&data->sem); + /* remap the garbage pages, forkers don't get access to the data */ + pmem_unmap_pfn_range(id, vma, data, 0, vma->vm_start - vma->vm_end); + up_write(&data->sem); +} + +static void pmem_vma_close(struct vm_area_struct *vma) +{ + struct file *file = vma->vm_file; + struct pmem_data *data = file->private_data; + + DLOG("current %u ppid %u file %p count %d\n", current->pid, + current->parent->pid, file, file_count(file)); + if (unlikely(!is_pmem_file(file) || !has_allocation(file))) { + printk(KERN_WARNING "pmem: something is very wrong, you are " + "closing a vm backing an allocation that doesn't " + "exist!\n"); + return; + } + down_write(&data->sem); + if (data->vma == vma) { + data->vma = NULL; + if ((data->flags & PMEM_FLAGS_CONNECTED) && + (data->flags & PMEM_FLAGS_SUBMAP)) + data->flags |= PMEM_FLAGS_UNSUBMAP; + } + /* the kernel is going to free this vma now anyway */ + up_write(&data->sem); +} + +static struct vm_operations_struct vm_ops = { + .open = pmem_vma_open, + .close = pmem_vma_close, +}; + +static int pmem_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct pmem_data *data; + int index; + unsigned long vma_size = vma->vm_end - vma->vm_start; + int ret = 0, id = get_id(file); + + if (vma->vm_pgoff || !PMEM_IS_PAGE_ALIGNED(vma_size)) { +#if PMEM_DEBUG + printk(KERN_ERR "pmem: mmaps must be at offset zero, aligned" + " and a multiple of pages_size.\n"); +#endif + return -EINVAL; + } + + data = (struct pmem_data *)file->private_data; + down_write(&data->sem); + /* check this file isn't already mmaped, for submaps check this file + * has never been mmaped */ + if ((data->flags & PMEM_FLAGS_MASTERMAP) || + (data->flags & PMEM_FLAGS_SUBMAP) || + (data->flags & PMEM_FLAGS_UNSUBMAP)) { +#if PMEM_DEBUG + printk(KERN_ERR "pmem: you can only mmap a pmem file once, " + "this file is already mmaped. %x\n", data->flags); +#endif + ret = -EINVAL; + goto error; + } + /* if file->private_data == unalloced, alloc*/ + if (data && data->index == -1) { + down_write(&pmem[id].bitmap_sem); + index = pmem_allocate(id, vma->vm_end - vma->vm_start); + up_write(&pmem[id].bitmap_sem); + data->index = index; + } + /* either no space was available or an error occured */ + if (!has_allocation(file)) { + ret = -EINVAL; + printk("pmem: could not find allocation for map.\n"); + goto error; + } + + if (pmem_len(id, data) < vma_size) { +#if PMEM_DEBUG + printk(KERN_WARNING "pmem: mmap size [%lu] does not match" + "size of backing region [%lu].\n", vma_size, + pmem_len(id, data)); +#endif + ret = -EINVAL; + goto error; + } + + vma->vm_pgoff = pmem_start_addr(id, data) >> PAGE_SHIFT; + vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_page_prot); + + if (data->flags & PMEM_FLAGS_CONNECTED) { + struct pmem_region_node *region_node; + struct list_head *elt; + if (pmem_map_garbage(id, vma, data, 0, vma_size)) { + printk("pmem: mmap failed in kernel!\n"); + ret = -EAGAIN; + goto error; + } + list_for_each(elt, &data->region_list) { + region_node = list_entry(elt, struct pmem_region_node, + list); + DLOG("remapping file: %p %lx %lx\n", file, + region_node->region.offset, + region_node->region.len); + if (pmem_remap_pfn_range(id, vma, data, + region_node->region.offset, + region_node->region.len)) { + ret = -EAGAIN; + goto error; + } + } + data->flags |= PMEM_FLAGS_SUBMAP; + get_task_struct(current->group_leader); + data->task = current->group_leader; + data->vma = vma; +#if PMEM_DEBUG + data->pid = current->pid; +#endif + DLOG("submmapped file %p vma %p pid %u\n", file, vma, + current->pid); + } else { + if (pmem_map_pfn_range(id, vma, data, 0, vma_size)) { + printk(KERN_INFO "pmem: mmap failed in kernel!\n"); + ret = -EAGAIN; + goto error; + } + data->flags |= PMEM_FLAGS_MASTERMAP; + data->pid = current->pid; + } + vma->vm_ops = &vm_ops; +error: + up_write(&data->sem); + return ret; +} + +/* the following are the api for accessing pmem regions by other drivers + * from inside the kernel */ +int get_pmem_user_addr(struct file *file, unsigned long *start, + unsigned long *len) +{ + struct pmem_data *data; + if (!is_pmem_file(file) || !has_allocation(file)) { +#if PMEM_DEBUG + printk(KERN_INFO "pmem: requested pmem data from invalid" + "file.\n"); +#endif + return -1; + } + data = (struct pmem_data *)file->private_data; + down_read(&data->sem); + if (data->vma) { + *start = data->vma->vm_start; + *len = data->vma->vm_end - data->vma->vm_start; + } else { + *start = 0; + *len = 0; + } + up_read(&data->sem); + return 0; +} + +int get_pmem_addr(struct file *file, unsigned long *start, + unsigned long *vstart, unsigned long *len) +{ + struct pmem_data *data; + int id; + + if (!is_pmem_file(file) || !has_allocation(file)) { + return -1; + } + + data = (struct pmem_data *)file->private_data; + if (data->index == -1) { +#if PMEM_DEBUG + printk(KERN_INFO "pmem: requested pmem data from file with no " + "allocation.\n"); + return -1; +#endif + } + id = get_id(file); + + down_read(&data->sem); + *start = pmem_start_addr(id, data); + *len = pmem_len(id, data); + *vstart = (unsigned long)pmem_start_vaddr(id, data); + up_read(&data->sem); +#if PMEM_DEBUG + down_write(&data->sem); + data->ref++; + up_write(&data->sem); +#endif + return 0; +} + +int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart, + unsigned long *len, struct file **filp) +{ + struct file *file; + + file = fget(fd); + if (unlikely(file == NULL)) { + printk(KERN_INFO "pmem: requested data from file descriptor " + "that doesn't exist."); + return -1; + } + + if (get_pmem_addr(file, start, vstart, len)) + goto end; + + if (filp) + *filp = file; + return 0; +end: + fput(file); + return -1; +} + +void put_pmem_file(struct file *file) +{ + struct pmem_data *data; + int id; + + if (!is_pmem_file(file)) + return; + id = get_id(file); + data = (struct pmem_data *)file->private_data; +#if PMEM_DEBUG + down_write(&data->sem); + if (data->ref == 0) { + printk("pmem: pmem_put > pmem_get %s (pid %d)\n", + pmem[id].dev.name, data->pid); + BUG(); + } + data->ref--; + up_write(&data->sem); +#endif + fput(file); +} + +void flush_pmem_file(struct file *file, unsigned long offset, unsigned long len) +{ + struct pmem_data *data; + int id; + void *vaddr; + struct pmem_region_node *region_node; + struct list_head *elt; + void *flush_start, *flush_end; + + if (!is_pmem_file(file) || !has_allocation(file)) { + return; + } + + id = get_id(file); + data = (struct pmem_data *)file->private_data; + if (!pmem[id].cached) + return; + + down_read(&data->sem); + vaddr = pmem_start_vaddr(id, data); + /* if this isn't a submmapped file, flush the whole thing */ + if (unlikely(!(data->flags & PMEM_FLAGS_CONNECTED))) { + dmac_flush_range(vaddr, vaddr + pmem_len(id, data)); + goto end; + } + /* otherwise, flush the region of the file we are drawing */ + list_for_each(elt, &data->region_list) { + region_node = list_entry(elt, struct pmem_region_node, list); + if ((offset >= region_node->region.offset) && + ((offset + len) <= (region_node->region.offset + + region_node->region.len))) { + flush_start = vaddr + region_node->region.offset; + flush_end = flush_start + region_node->region.len; + dmac_flush_range(flush_start, flush_end); + break; + } + } +end: + up_read(&data->sem); +} + +static int pmem_connect(unsigned long connect, struct file *file) +{ + struct pmem_data *data = (struct pmem_data *)file->private_data; + struct pmem_data *src_data; + struct file *src_file; + int ret = 0, put_needed; + + down_write(&data->sem); + /* retrieve the src file and check it is a pmem file with an alloc */ + src_file = fget_light(connect, &put_needed); + DLOG("connect %p to %p\n", file, src_file); + if (!src_file) { + printk("pmem: src file not found!\n"); + ret = -EINVAL; + goto err_no_file; + } + if (unlikely(!is_pmem_file(src_file) || !has_allocation(src_file))) { + printk(KERN_INFO "pmem: src file is not a pmem file or has no " + "alloc!\n"); + ret = -EINVAL; + goto err_bad_file; + } + src_data = (struct pmem_data *)src_file->private_data; + + if (has_allocation(file) && (data->index != src_data->index)) { + printk("pmem: file is already mapped but doesn't match this" + " src_file!\n"); + ret = -EINVAL; + goto err_bad_file; + } + data->index = src_data->index; + data->flags |= PMEM_FLAGS_CONNECTED; + data->master_fd = connect; + data->master_file = src_file; + +err_bad_file: + fput_light(src_file, put_needed); +err_no_file: + up_write(&data->sem); + return ret; +} + +static void pmem_unlock_data_and_mm(struct pmem_data *data, + struct mm_struct *mm) +{ + up_write(&data->sem); + if (mm != NULL) { + up_write(&mm->mmap_sem); + mmput(mm); + } +} + +static int pmem_lock_data_and_mm(struct file *file, struct pmem_data *data, + struct mm_struct **locked_mm) +{ + int ret = 0; + struct mm_struct *mm = NULL; + *locked_mm = NULL; +lock_mm: + down_read(&data->sem); + if (PMEM_IS_SUBMAP(data)) { + mm = get_task_mm(data->task); + if (!mm) { +#if PMEM_DEBUG + printk("pmem: can't remap task is gone!\n"); +#endif + up_read(&data->sem); + return -1; + } + } + up_read(&data->sem); + + if (mm) + down_write(&mm->mmap_sem); + + down_write(&data->sem); + /* check that the file didn't get mmaped before we could take the + * data sem, this should be safe b/c you can only submap each file + * once */ + if (PMEM_IS_SUBMAP(data) && !mm) { + pmem_unlock_data_and_mm(data, mm); + up_write(&data->sem); + goto lock_mm; + } + /* now check that vma.mm is still there, it could have been + * deleted by vma_close before we could get the data->sem */ + if ((data->flags & PMEM_FLAGS_UNSUBMAP) && (mm != NULL)) { + /* might as well release this */ + if (data->flags & PMEM_FLAGS_SUBMAP) { + put_task_struct(data->task); + data->task = NULL; + /* lower the submap flag to show the mm is gone */ + data->flags &= ~(PMEM_FLAGS_SUBMAP); + } + pmem_unlock_data_and_mm(data, mm); + return -1; + } + *locked_mm = mm; + return ret; +} + +int pmem_remap(struct pmem_region *region, struct file *file, + unsigned operation) +{ + int ret; + struct pmem_region_node *region_node; + struct mm_struct *mm = NULL; + struct list_head *elt, *elt2; + int id = get_id(file); + struct pmem_data *data = (struct pmem_data *)file->private_data; + + /* pmem region must be aligned on a page boundry */ + if (unlikely(!PMEM_IS_PAGE_ALIGNED(region->offset) || + !PMEM_IS_PAGE_ALIGNED(region->len))) { +#if PMEM_DEBUG + printk("pmem: request for unaligned pmem suballocation " + "%lx %lx\n", region->offset, region->len); +#endif + return -EINVAL; + } + + /* if userspace requests a region of len 0, there's nothing to do */ + if (region->len == 0) + return 0; + + /* lock the mm and data */ + ret = pmem_lock_data_and_mm(file, data, &mm); + if (ret) + return 0; + + /* only the owner of the master file can remap the client fds + * that back in it */ + if (!is_master_owner(file)) { +#if PMEM_DEBUG + printk("pmem: remap requested from non-master process\n"); +#endif + ret = -EINVAL; + goto err; + } + + /* check that the requested range is within the src allocation */ + if (unlikely((region->offset > pmem_len(id, data)) || + (region->len > pmem_len(id, data)) || + (region->offset + region->len > pmem_len(id, data)))) { +#if PMEM_DEBUG + printk(KERN_INFO "pmem: suballoc doesn't fit in src_file!\n"); +#endif + ret = -EINVAL; + goto err; + } + + if (operation == PMEM_MAP) { + region_node = kmalloc(sizeof(struct pmem_region_node), + GFP_KERNEL); + if (!region_node) { + ret = -ENOMEM; +#if PMEM_DEBUG + printk(KERN_INFO "No space to allocate metadata!"); +#endif + goto err; + } + region_node->region = *region; + list_add(®ion_node->list, &data->region_list); + } else if (operation == PMEM_UNMAP) { + int found = 0; + list_for_each_safe(elt, elt2, &data->region_list) { + region_node = list_entry(elt, struct pmem_region_node, + list); + if (region->len == 0 || + (region_node->region.offset == region->offset && + region_node->region.len == region->len)) { + list_del(elt); + kfree(region_node); + found = 1; + } + } + if (!found) { +#if PMEM_DEBUG + printk("pmem: Unmap region does not map any mapped " + "region!"); +#endif + ret = -EINVAL; + goto err; + } + } + + if (data->vma && PMEM_IS_SUBMAP(data)) { + if (operation == PMEM_MAP) + ret = pmem_remap_pfn_range(id, data->vma, data, + region->offset, region->len); + else if (operation == PMEM_UNMAP) + ret = pmem_unmap_pfn_range(id, data->vma, data, + region->offset, region->len); + } + +err: + pmem_unlock_data_and_mm(data, mm); + return ret; +} + +static void pmem_revoke(struct file *file, struct pmem_data *data) +{ + struct pmem_region_node *region_node; + struct list_head *elt, *elt2; + struct mm_struct *mm = NULL; + int id = get_id(file); + int ret = 0; + + data->master_file = NULL; + ret = pmem_lock_data_and_mm(file, data, &mm); + /* if lock_data_and_mm fails either the task that mapped the fd, or + * the vma that mapped it have already gone away, nothing more + * needs to be done */ + if (ret) + return; + /* unmap everything */ + /* delete the regions and region list nothing is mapped any more */ + if (data->vma) + list_for_each_safe(elt, elt2, &data->region_list) { + region_node = list_entry(elt, struct pmem_region_node, + list); + pmem_unmap_pfn_range(id, data->vma, data, + region_node->region.offset, + region_node->region.len); + list_del(elt); + kfree(region_node); + } + /* delete the master file */ + pmem_unlock_data_and_mm(data, mm); +} + +static void pmem_get_size(struct pmem_region *region, struct file *file) +{ + struct pmem_data *data = (struct pmem_data *)file->private_data; + int id = get_id(file); + + if (!has_allocation(file)) { + region->offset = 0; + region->len = 0; + return; + } else { + region->offset = pmem_start_addr(id, data); + region->len = pmem_len(id, data); + } + DLOG("offset %lx len %lx\n", region->offset, region->len); +} + + +static long pmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct pmem_data *data; + int id = get_id(file); + + switch (cmd) { + case PMEM_GET_PHYS: + { + struct pmem_region region; + DLOG("get_phys\n"); + if (!has_allocation(file)) { + region.offset = 0; + region.len = 0; + } else { + data = (struct pmem_data *)file->private_data; + region.offset = pmem_start_addr(id, data); + region.len = pmem_len(id, data); + } + printk(KERN_INFO "pmem: request for physical address of pmem region " + "from process %d.\n", current->pid); + if (copy_to_user((void __user *)arg, ®ion, + sizeof(struct pmem_region))) + return -EFAULT; + break; + } + case PMEM_MAP: + { + struct pmem_region region; + if (copy_from_user(®ion, (void __user *)arg, + sizeof(struct pmem_region))) + return -EFAULT; + data = (struct pmem_data *)file->private_data; + return pmem_remap(®ion, file, PMEM_MAP); + } + break; + case PMEM_UNMAP: + { + struct pmem_region region; + if (copy_from_user(®ion, (void __user *)arg, + sizeof(struct pmem_region))) + return -EFAULT; + data = (struct pmem_data *)file->private_data; + return pmem_remap(®ion, file, PMEM_UNMAP); + break; + } + case PMEM_GET_SIZE: + { + struct pmem_region region; + DLOG("get_size\n"); + pmem_get_size(®ion, file); + if (copy_to_user((void __user *)arg, ®ion, + sizeof(struct pmem_region))) + return -EFAULT; + break; + } + case PMEM_GET_TOTAL_SIZE: + { + struct pmem_region region; + DLOG("get total size\n"); + region.offset = 0; + get_id(file); + region.len = pmem[id].size; + if (copy_to_user((void __user *)arg, ®ion, + sizeof(struct pmem_region))) + return -EFAULT; + break; + } + case PMEM_ALLOCATE: + { + if (has_allocation(file)) + return -EINVAL; + data = (struct pmem_data *)file->private_data; + data->index = pmem_allocate(id, arg); + break; + } + case PMEM_CONNECT: + DLOG("connect\n"); + return pmem_connect(arg, file); + break; + default: + if (pmem[id].ioctl) + return pmem[id].ioctl(file, cmd, arg); + return -EINVAL; + } + return 0; +} + +#if PMEM_DEBUG +static ssize_t debug_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t debug_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + struct list_head *elt, *elt2; + struct pmem_data *data; + struct pmem_region_node *region_node; + int id = (int)file->private_data; + const int debug_bufmax = 4096; + static char buffer[4096]; + int n = 0; + + DLOG("debug open\n"); + n = scnprintf(buffer, debug_bufmax, + "pid #: mapped regions (offset, len) (offset,len)...\n"); + + down(&pmem[id].data_list_sem); + list_for_each(elt, &pmem[id].data_list) { + data = list_entry(elt, struct pmem_data, list); + down_read(&data->sem); + n += scnprintf(buffer + n, debug_bufmax - n, "pid %u:", + data->pid); + list_for_each(elt2, &data->region_list) { + region_node = list_entry(elt2, struct pmem_region_node, + list); + n += scnprintf(buffer + n, debug_bufmax - n, + "(%lx,%lx) ", + region_node->region.offset, + region_node->region.len); + } + n += scnprintf(buffer + n, debug_bufmax - n, "\n"); + up_read(&data->sem); + } + up(&pmem[id].data_list_sem); + + n++; + buffer[n] = 0; + return simple_read_from_buffer(buf, count, ppos, buffer, n); +} + +static struct file_operations debug_fops = { + .read = debug_read, + .open = debug_open, +}; +#endif + +#if 0 +static struct miscdevice pmem_dev = { + .name = "pmem", + .fops = &pmem_fops, +}; +#endif + +int pmem_setup(struct android_pmem_platform_data *pdata, + long (*ioctl)(struct file *, unsigned int, unsigned long), + int (*release)(struct inode *, struct file *)) +{ + int err = 0; + int i, index = 0; + int id = id_count; + id_count++; + + pmem[id].no_allocator = pdata->no_allocator; + pmem[id].cached = pdata->cached; + pmem[id].buffered = pdata->buffered; + pmem[id].base = pdata->start; + pmem[id].size = pdata->size; + pmem[id].ioctl = ioctl; + pmem[id].release = release; + init_rwsem(&pmem[id].bitmap_sem); + init_MUTEX(&pmem[id].data_list_sem); + INIT_LIST_HEAD(&pmem[id].data_list); + pmem[id].dev.name = pdata->name; + pmem[id].dev.minor = id; + pmem[id].dev.fops = &pmem_fops; + printk(KERN_INFO "%s: %d init\n", pdata->name, pdata->cached); + + err = misc_register(&pmem[id].dev); + if (err) { + printk(KERN_ALERT "Unable to register pmem driver!\n"); + goto err_cant_register_device; + } + pmem[id].num_entries = pmem[id].size / PMEM_MIN_ALLOC; + + pmem[id].bitmap = kmalloc(pmem[id].num_entries * + sizeof(struct pmem_bits), GFP_KERNEL); + if (!pmem[id].bitmap) + goto err_no_mem_for_metadata; + + memset(pmem[id].bitmap, 0, sizeof(struct pmem_bits) * + pmem[id].num_entries); + + for (i = sizeof(pmem[id].num_entries) * 8 - 1; i >= 0; i--) { + if ((pmem[id].num_entries) & 1<name, S_IFREG | S_IRUGO, NULL, (void *)id, + &debug_fops); +#endif + return 0; +error_cant_remap: + kfree(pmem[id].bitmap); +err_no_mem_for_metadata: + misc_deregister(&pmem[id].dev); +err_cant_register_device: + return -1; +} + +static int pmem_probe(struct platform_device *pdev) +{ + struct android_pmem_platform_data *pdata; + + if (!pdev || !pdev->dev.platform_data) { + printk(KERN_ALERT "Unable to probe pmem!\n"); + return -1; + } + pdata = pdev->dev.platform_data; + return pmem_setup(pdata, NULL, NULL); +} + + +static int pmem_remove(struct platform_device *pdev) +{ + int id = pdev->id; + __free_page(pfn_to_page(pmem[id].garbage_pfn)); + misc_deregister(&pmem[id].dev); + return 0; +} + +static struct platform_driver pmem_driver = { + .probe = pmem_probe, + .remove = pmem_remove, + .driver = { .name = "android_pmem" } +}; + + +static int __init pmem_init(void) +{ + return platform_driver_register(&pmem_driver); +} + +static void __exit pmem_exit(void) +{ + platform_driver_unregister(&pmem_driver); +} + +module_init(pmem_init); +module_exit(pmem_exit); + diff --git a/drivers/staging/dream/qdsp5/adsp.c b/drivers/staging/dream/qdsp5/adsp.c index d096456688dac18f3d4e9d51dc96f4f15d88c501..9069535fcaf18ba213086066dddf7dde9a46b764 100644 --- a/drivers/staging/dream/qdsp5/adsp.c +++ b/drivers/staging/dream/qdsp5/adsp.c @@ -32,16 +32,12 @@ #include #include #include -#include -static struct wake_lock adsp_wake_lock; static inline void prevent_suspend(void) { - wake_lock(&adsp_wake_lock); } static inline void allow_suspend(void) { - wake_unlock(&adsp_wake_lock); } #include @@ -1046,7 +1042,6 @@ static int msm_adsp_probe(struct platform_device *pdev) pr_info("adsp: probe\n"); - wake_lock_init(&adsp_wake_lock, WAKE_LOCK_SUSPEND, "adsp"); #if CONFIG_MSM_AMSS_VERSION >= 6350 adsp_info.init_info_ptr = kzalloc( (sizeof(struct adsp_rtos_mp_mtoa_init_info_type)), GFP_KERNEL); diff --git a/drivers/staging/dream/qdsp5/audio_out.c b/drivers/staging/dream/qdsp5/audio_out.c index d1adcf65f2bd243dfc8cd6a71b623089b70f61a4..df87ca337b9476e313bdaf358dad5c432983d615 100644 --- a/drivers/staging/dream/qdsp5/audio_out.c +++ b/drivers/staging/dream/qdsp5/audio_out.c @@ -38,8 +38,6 @@ #include #include -#include - #include "evlog.h" #define LOG_AUDIO_EVENTS 1 @@ -260,7 +258,6 @@ static int audio_enable(struct audio *audio) } audio->enabled = 1; - htc_pwrsink_set(PWRSINK_AUDIO, 100); return 0; } @@ -695,7 +692,6 @@ static int audio_release(struct inode *inode, struct file *file) audio_flush(audio); audio->opened = 0; mutex_unlock(&audio->lock); - htc_pwrsink_set(PWRSINK_AUDIO, 0); return 0; } diff --git a/drivers/staging/dream/smd/smd_qmi.c b/drivers/staging/dream/smd/smd_qmi.c index d4e7d880462685a17d38ca79bc3f7cead03012f8..687db142904c5c3be420406b377ad18da5b22037 100644 --- a/drivers/staging/dream/smd/smd_qmi.c +++ b/drivers/staging/dream/smd/smd_qmi.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -74,7 +73,6 @@ struct qmi_ctxt { smd_channel_t *ch; const char *ch_name; - struct wake_lock wake_lock; struct work_struct open_work; struct work_struct read_work; @@ -90,7 +88,6 @@ void qmi_ctxt_init(struct qmi_ctxt *ctxt, unsigned n) mutex_init(&ctxt->lock); INIT_WORK(&ctxt->read_work, qmi_read_work); INIT_WORK(&ctxt->open_work, qmi_open_work); - wake_lock_init(&ctxt->wake_lock, WAKE_LOCK_SUSPEND, ctxt->misc.name); ctxt->ctl_txn_id = 1; ctxt->wds_txn_id = 1; ctxt->wds_busy = 1; @@ -454,7 +451,6 @@ static void qmi_process_qmux(struct qmi_ctxt *ctxt, break; } mutex_unlock(&ctxt->lock); - wake_up(&qmi_wait_queue); } @@ -509,7 +505,6 @@ static void qmi_notify(void *priv, unsigned event) int sz; sz = smd_cur_packet_size(ctxt->ch); if ((sz > 0) && (sz <= smd_read_avail(ctxt->ch))) { - wake_lock_timeout(&ctxt->wake_lock, HZ / 2); queue_work(qmi_wq, &ctxt->read_work); } break; diff --git a/drivers/staging/dream/smd/smd_rpcrouter.c b/drivers/staging/dream/smd/smd_rpcrouter.c index d4a4a887e428554bab3cfaf30f3aae2b3db62e5e..5ac2cd4a59784eeb2b50887a833f09853101ebcd 100644 --- a/drivers/staging/dream/smd/smd_rpcrouter.c +++ b/drivers/staging/dream/smd/smd_rpcrouter.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -96,7 +95,6 @@ static DEFINE_SPINLOCK(server_list_lock); static DEFINE_SPINLOCK(smd_lock); static struct workqueue_struct *rpcrouter_workqueue; -static struct wake_lock rpcrouter_wake_lock; static int rpcrouter_need_len; static atomic_t next_xid = ATOMIC_INIT(1); @@ -290,7 +288,6 @@ struct msm_rpc_endpoint *msm_rpcrouter_create_local_endpoint(dev_t dev) init_waitqueue_head(&ept->wait_q); INIT_LIST_HEAD(&ept->read_q); spin_lock_init(&ept->read_q_lock); - wake_lock_init(&ept->read_q_wake_lock, WAKE_LOCK_SUSPEND, "rpc_read"); INIT_LIST_HEAD(&ept->incomplete); spin_lock_irqsave(&local_endpoints_lock, flags); @@ -313,7 +310,6 @@ int msm_rpcrouter_destroy_local_endpoint(struct msm_rpc_endpoint *ept) if (rc < 0) return rc; - wake_lock_destroy(&ept->read_q_wake_lock); list_del(&ept->list); kfree(ept); return 0; @@ -540,8 +536,6 @@ static void rpcrouter_smdnotify(void *_dev, unsigned event) if (event != SMD_EVENT_DATA) return; - if (smd_read_avail(smd_channel) >= rpcrouter_need_len) - wake_lock(&rpcrouter_wake_lock); wake_up(&smd_wait); } @@ -576,7 +570,6 @@ static int rr_read(void *data, int len) return -EIO; } rpcrouter_need_len = len; - wake_unlock(&rpcrouter_wake_lock); spin_unlock_irqrestore(&smd_lock, flags); // printk("rr_read: waiting (%d)\n", len); @@ -676,7 +669,6 @@ static void do_read_data(struct work_struct *work) packet_complete: spin_lock_irqsave(&ept->read_q_lock, flags); - wake_lock(&ept->read_q_wake_lock); list_add_tail(&pkt->list, &ept->read_q); wake_up(&ept->wait_q); spin_unlock_irqrestore(&ept->read_q_lock, flags); @@ -699,7 +691,6 @@ done: fail_io: fail_data: printk(KERN_ERR "rpc_router has died\n"); - wake_unlock(&rpcrouter_wake_lock); } void msm_rpc_setup_req(struct rpc_request_hdr *hdr, uint32_t prog, @@ -1061,8 +1052,6 @@ int __msm_rpc_read(struct msm_rpc_endpoint *ept, return -ETOOSMALL; } list_del(&pkt->list); - if (list_empty(&ept->read_q)) - wake_unlock(&ept->read_q_wake_lock); spin_unlock_irqrestore(&ept->read_q_lock, flags); rc = pkt->length; @@ -1229,7 +1218,6 @@ static int msm_rpcrouter_probe(struct platform_device *pdev) init_waitqueue_head(&newserver_wait); init_waitqueue_head(&smd_wait); - wake_lock_init(&rpcrouter_wake_lock, WAKE_LOCK_SUSPEND, "SMD_RPCCALL"); rpcrouter_workqueue = create_singlethread_workqueue("rpcrouter"); if (!rpcrouter_workqueue) diff --git a/drivers/staging/dream/smd/smd_rpcrouter.h b/drivers/staging/dream/smd/smd_rpcrouter.h index a7416a2ec58cfed80b6bbe66e5d262260e87f885..86ab997b1b79dec274970cdc7ba317a693b881d1 100644 --- a/drivers/staging/dream/smd/smd_rpcrouter.h +++ b/drivers/staging/dream/smd/smd_rpcrouter.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -144,7 +143,6 @@ struct msm_rpc_endpoint { /* complete packets waiting to be read */ struct list_head read_q; spinlock_t read_q_lock; - struct wake_lock read_q_wake_lock; wait_queue_head_t wait_q; unsigned flags; diff --git a/drivers/staging/dream/smd/smd_tty.c b/drivers/staging/dream/smd/smd_tty.c index 2edd9d1ec2dc96e6c97113ea1954c6084926f4d5..f40944958d44003ffe5e5774b6dcc04bcf84a4cd 100644 --- a/drivers/staging/dream/smd/smd_tty.c +++ b/drivers/staging/dream/smd/smd_tty.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -34,7 +33,6 @@ static DEFINE_MUTEX(smd_tty_lock); struct smd_tty_info { smd_channel_t *ch; struct tty_struct *tty; - struct wake_lock wake_lock; int open_count; }; @@ -69,7 +67,6 @@ static void smd_tty_notify(void *priv, unsigned event) printk(KERN_ERR "OOPS - smd_tty_buffer mismatch?!"); } - wake_lock_timeout(&info->wake_lock, HZ / 2); tty_flip_buffer_push(tty); } @@ -95,7 +92,6 @@ static int smd_tty_open(struct tty_struct *tty, struct file *f) info = smd_tty + n; mutex_lock(&smd_tty_lock); - wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND, name); tty->driver_data = info; if (info->open_count++ == 0) { @@ -122,7 +118,6 @@ static void smd_tty_close(struct tty_struct *tty, struct file *f) if (--info->open_count == 0) { info->tty = 0; tty->driver_data = 0; - wake_lock_destroy(&info->wake_lock); if (info->ch) { smd_close(info->ch); info->ch = 0; diff --git a/drivers/staging/dream/synaptics_i2c_rmi.c b/drivers/staging/dream/synaptics_i2c_rmi.c index ae696d3bc8e691207a516fb201d1833309d69739..4de6bc9175954899b314c2ec14fa4bed8805c257 100644 --- a/drivers/staging/dream/synaptics_i2c_rmi.c +++ b/drivers/staging/dream/synaptics_i2c_rmi.c @@ -379,6 +379,12 @@ static int __devinit synaptics_ts_probe( goto err_check_functionality_failed; } + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) { + pr_err("synaptics_ts_probe: need I2C_FUNC_SMBUS_WORD_DATA\n"); + ret = -ENODEV; + goto err_check_functionality_failed; + } + ts = kzalloc(sizeof(*ts), GFP_KERNEL); if (ts == NULL) { ret = -ENOMEM; diff --git a/drivers/staging/dst/crypto.c b/drivers/staging/dst/crypto.c index 7250f90f5924638ebecec64d2d1fde713c4f25b9..351295c97a4b89a50f65cbd841b3a50e5f91e665 100644 --- a/drivers/staging/dst/crypto.c +++ b/drivers/staging/dst/crypto.c @@ -64,7 +64,8 @@ err_out_exit: return ERR_PTR(err); } -static struct crypto_ablkcipher *dst_init_cipher(struct dst_crypto_ctl *ctl, u8 *key) +static struct crypto_ablkcipher *dst_init_cipher(struct dst_crypto_ctl *ctl, + u8 *key) { int err = -EINVAL; struct crypto_ablkcipher *cipher; @@ -105,7 +106,7 @@ static void dst_crypto_pages_free(struct dst_crypto_engine *e) { unsigned int i; - for (i=0; ipage_num; ++i) + for (i = 0; i < e->page_num; ++i) __free_page(e->pages[i]); kfree(e->pages); } @@ -118,7 +119,7 @@ static int dst_crypto_pages_alloc(struct dst_crypto_engine *e, int num) if (!e->pages) return -ENOMEM; - for (i=0; ipages[i] = alloc_page(GFP_KERNEL); if (!e->pages[i]) goto err_out_free_pages; @@ -139,7 +140,8 @@ err_out_free_pages: * Initialize crypto engine for given node. * Setup cipher/hash, keys, pool of threads and private data. */ -static int dst_crypto_engine_init(struct dst_crypto_engine *e, struct dst_node *n) +static int dst_crypto_engine_init(struct dst_crypto_engine *e, + struct dst_node *n) { int err; struct dst_crypto_ctl *ctl = &n->crypto; @@ -198,8 +200,7 @@ static void dst_crypto_engine_exit(struct dst_crypto_engine *e) /* * Waiting for cipher processing to be completed. */ -struct dst_crypto_completion -{ +struct dst_crypto_completion { struct completion complete; int error; }; @@ -237,17 +238,17 @@ static int dst_crypto_process(struct ablkcipher_request *req, err = crypto_ablkcipher_decrypt(req); switch (err) { - case -EINPROGRESS: - case -EBUSY: - err = wait_for_completion_interruptible_timeout(&c.complete, - timeout); - if (!err) - err = -ETIMEDOUT; - else - err = c.error; - break; - default: - break; + case -EINPROGRESS: + case -EBUSY: + err = wait_for_completion_interruptible_timeout(&c.complete, + timeout); + if (!err) + err = -ETIMEDOUT; + else + err = c.error; + break; + default: + break; } return err; @@ -263,7 +264,7 @@ static int dst_crypto_process(struct ablkcipher_request *req, * temporary storage, which is then being sent to the remote peer. */ static int dst_trans_iter_out(struct bio *bio, struct dst_crypto_engine *e, - int (* iterator) (struct dst_crypto_engine *e, + int (*iterator) (struct dst_crypto_engine *e, struct scatterlist *dst, struct scatterlist *src)) { @@ -286,7 +287,7 @@ static int dst_trans_iter_out(struct bio *bio, struct dst_crypto_engine *e, } static int dst_trans_iter_in(struct bio *bio, struct dst_crypto_engine *e, - int (* iterator) (struct dst_crypto_engine *e, + int (*iterator) (struct dst_crypto_engine *e, struct scatterlist *dst, struct scatterlist *src)) { @@ -411,9 +412,9 @@ static void dst_crypto_thread_cleanup(void *private) * Initialize crypto engine for given node: store keys, create pool * of threads, initialize each one. * - * Each thread has unique ID, but 0 and 1 are reserved for receiving and accepting - * threads (if export node), so IDs could start from 2, but starting them - * from 10 allows easily understand what this thread is for. + * Each thread has unique ID, but 0 and 1 are reserved for receiving and + * accepting threads (if export node), so IDs could start from 2, but starting + * them from 10 allows easily understand what this thread is for. */ int dst_node_crypto_init(struct dst_node *n, struct dst_crypto_ctl *ctl) { @@ -436,10 +437,10 @@ int dst_node_crypto_init(struct dst_node *n, struct dst_crypto_ctl *ctl) } memcpy(&n->crypto, ctl, sizeof(struct dst_crypto_ctl)); - for (i=0; ithread_num; ++i) { + for (i = 0; i < ctl->thread_num; ++i) { snprintf(name, sizeof(name), "%s-crypto-%d", n->name, i); /* Unique ids... */ - err = thread_pool_add_worker(n->pool, name, i+10, + err = thread_pool_add_worker(n->pool, name, i + 10, dst_crypto_thread_init, dst_crypto_thread_cleanup, n); if (err) goto err_out_free_threads; @@ -496,8 +497,8 @@ static void dst_dump_bio(struct bio *bio) bv->bv_len, bv->bv_offset); p = kmap(bv->bv_page) + bv->bv_offset; - for (i=0; ibv_len; ++i) - printk("%02x ", p[i]); + for (i = 0; i < bv->bv_len; ++i) + printk(KERN_DEBUG "%02x ", p[i]); kunmap(bv->bv_page); printk("\n"); } @@ -532,7 +533,7 @@ static int dst_crypto_process_sending(struct dst_crypto_engine *e, printk(KERN_DEBUG "%s: bio: %llu/%u, rw: %lu, hash: ", __func__, (u64)bio->bi_sector, bio->bi_size, bio_data_dir(bio)); - for (i=0; ihash); ++i) + for (i = 0; i < crypto_hash_digestsize(e->hash); ++i) printk("%02x ", hash[i]); printk("\n"); } @@ -572,9 +573,9 @@ static int dst_crypto_process_receiving(struct dst_crypto_engine *e, unsigned int i; printk(", recv/calc: "); - for (i=0; ihash); ++i) { + for (i = 0; i < crypto_hash_digestsize(e->hash); ++i) printk("%02x/%02x ", recv_hash[i], hash[i]); - } + } printk("\n"); #endif @@ -680,8 +681,9 @@ static int dst_export_crypto_action(void *crypto_engine, void *schedule_data) struct dst_export_priv *p = bio->bi_private; int err; - dprintk("%s: e: %p, data: %p, bio: %llu/%u, dir: %lu.\n", __func__, - e, e->data, (u64)bio->bi_sector, bio->bi_size, bio_data_dir(bio)); + dprintk("%s: e: %p, data: %p, bio: %llu/%u, dir: %lu.\n", + __func__, e, e->data, (u64)bio->bi_sector, + bio->bi_size, bio_data_dir(bio)); e->enc = (bio_data_dir(bio) == READ); e->iv = p->cmd.id; diff --git a/drivers/staging/dst/dcore.c b/drivers/staging/dst/dcore.c index c24e4e0367a276ce787140154156b25ac73707bb..fd5bd0ea1e0d578c454a4bb59938a8199eba49fe 100644 --- a/drivers/staging/dst/dcore.c +++ b/drivers/staging/dst/dcore.c @@ -116,7 +116,7 @@ static int dst_request(struct request_queue *q, struct bio *bio) * bio_rw_flagged(bio, BIO_RW_DISCARD) only, which does not * work in this case. */ - //err = -EOPNOTSUPP; + /* err = -EOPNOTSUPP; */ err = 0; goto end_io; } @@ -197,7 +197,8 @@ static int dst_node_create_disk(struct dst_node *n) n->disk->fops = &dst_blk_ops; n->disk->queue = n->queue; n->disk->private_data = n; - snprintf(n->disk->disk_name, sizeof(n->disk->disk_name), "dst-%s", n->name); + snprintf(n->disk->disk_name, sizeof(n->disk->disk_name), + "dst-%s", n->name); return 0; @@ -246,7 +247,8 @@ static ssize_t dst_show_type(struct device *dev, return sprintf(buf, "%u.%u.%u.%u:%d\n", NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); } else if (family == AF_INET6) { - struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&info->net.addr; + struct sockaddr_in6 *sin = (struct sockaddr_in6 *) + &info->net.addr; return sprintf(buf, "%pi6:%d\n", &sin->sin6_addr, ntohs(sin->sin6_port)); @@ -261,7 +263,7 @@ static ssize_t dst_show_type(struct device *dev, sz -= size; buf += size; - for (i=0; iinfo->device, &dst_node_attrs[i]); if (err) @@ -306,7 +308,7 @@ static void dst_remove_node_attributes(struct dst_node *n) { int i; - for (i=0; iinfo->device, &dst_node_attrs[i]); } @@ -358,7 +360,7 @@ err_out_exit: */ static inline unsigned int dst_hash(char *str, unsigned int size) { - return (jhash(str, size, 0) % dst_hashtable_size); + return jhash(str, size, 0) % dst_hashtable_size; } static void dst_node_remove(struct dst_node *n) @@ -641,7 +643,8 @@ static int dst_start_remote(struct dst_node *n) dst_node_set_size(n); add_disk(n->disk); - dprintk("DST: started remote node '%s', minor: %d.\n", n->name, n->disk->first_minor); + dprintk("DST: started remote node '%s', minor: %d.\n", + n->name, n->disk->first_minor); return 0; } @@ -740,7 +743,8 @@ static int dst_node_remove_unload(struct dst_node *n) * counter will be equal to 1), * and subsequent dst_node_put() calls will free the node. */ - dprintk("%s: going to sleep with %d refcnt.\n", __func__, atomic_read(&n->refcnt)); + dprintk("%s: going to sleep with %d refcnt.\n", + __func__, atomic_read(&n->refcnt)); wait_event(n->wait, atomic_read(&n->refcnt) <= 2); dst_node_put(n); @@ -921,7 +925,7 @@ static int __init dst_hashtable_init(void) if (!dst_hashtable) return -ENOMEM; - for (i=0; inode; struct dst_secure *sentry; @@ -73,9 +74,9 @@ static unsigned int dst_check_permissions(struct dst_state *main, struct dst_sta /* * This '2' below is a port field. This may be very wrong to do - * in atalk for example though. If there will be any need to extent - * protocol to something else, I can create per-family helpers and - * use them instead of this memcmp. + * in atalk for example though. If there will be any need + * to extent protocol to something else, I can create + * per-family helpers and use them instead of this memcmp. */ if (memcmp(s->addr.sa_data + 2, sa->sa_data + 2, sa->sa_data_len - 2)) @@ -125,8 +126,8 @@ static struct dst_state *dst_accept_client(struct dst_state *st) * Magic HZ? Polling check above is not safe in * all cases (like socket reset in BH context), * so it is simpler just to postpone it to the - * process context instead of implementing special - * locking there. + * process context instead of implementing + * special locking there. */ schedule_timeout(HZ); } @@ -202,7 +203,7 @@ err_out_exit: * so to play good with all cases we just queue BIO into the queue * and wake up processing thread, which gets completed request and * send (encrypting if needed) it back to the client (if it was a read - * request), or sends back reply that writing succesfully completed. + * request), or sends back reply that writing successfully completed. */ static int dst_export_process_request_queue(struct dst_state *st) { @@ -272,8 +273,8 @@ static void dst_state_cleanup_export(struct dst_state *st) if (p) bio_put(p->bio); - dprintk("%s: st: %p, refcnt: %d, list_empty: %d, p: %p.\n", - __func__, st, atomic_read(&st->refcnt), + dprintk("%s: st: %p, refcnt: %d, list_empty: %d, p: " + "%p.\n", __func__, st, atomic_read(&st->refcnt), list_empty(&st->request_list), p); } } @@ -303,9 +304,9 @@ static int dst_accept(void *init_data, void *schedule_data) if (!err) { while (n->trans_scan_timeout) { err = wait_event_interruptible_timeout(st->thread_wait, - !list_empty(&st->request_list) || - !n->trans_scan_timeout || - st->need_exit, + !list_empty(&st->request_list) || + !n->trans_scan_timeout || + st->need_exit, HZ); if (!n->trans_scan_timeout || st->need_exit) @@ -341,8 +342,9 @@ static int dst_accept(void *init_data, void *schedule_data) int dst_start_export(struct dst_node *n) { if (list_empty(&n->security_list)) { - printk(KERN_ERR "You are trying to export node '%s' without security attributes.\n" - "No clients will be allowed to connect. Exiting.\n", n->name); + printk(KERN_ERR "You are trying to export node '%s' " + "without security attributes.\nNo clients will " + "be allowed to connect. Exiting.\n", n->name); return -EINVAL; } return dst_node_trans_init(n, sizeof(struct dst_export_priv)); @@ -552,7 +554,8 @@ int dst_process_io(struct dst_state *st) if (!bio) goto err_out_exit; - priv = (struct dst_export_priv *)(((void *)bio) - sizeof (struct dst_export_priv)); + priv = (struct dst_export_priv *)(((void *)bio) - + sizeof (struct dst_export_priv)); priv->state = dst_state_get(st); priv->bio = bio; diff --git a/drivers/staging/dst/state.c b/drivers/staging/dst/state.c index d057e52f3b64921262d3a14610f060953126ee2c..02a05e6c48c356c4b6d13c9ba4ea8eda250e94c2 100644 --- a/drivers/staging/dst/state.c +++ b/drivers/staging/dst/state.c @@ -30,13 +30,13 @@ * Polling machinery. */ -struct dst_poll_helper -{ - poll_table pt; +struct dst_poll_helper { + poll_table pt; struct dst_state *st; }; -static int dst_queue_wake(wait_queue_t *wait, unsigned mode, int sync, void *key) +static int dst_queue_wake(wait_queue_t *wait, unsigned mode, + int sync, void *key) { struct dst_state *st = container_of(wait, struct dst_state, wait); @@ -92,7 +92,7 @@ static int dst_data_recv_header(struct socket *sock, msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; - msg.msg_flags = (block)?MSG_WAITALL:MSG_DONTWAIT; + msg.msg_flags = (block) ? MSG_WAITALL : MSG_DONTWAIT; err = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, msg.msg_flags); @@ -121,7 +121,7 @@ int dst_data_send_header(struct socket *sock, msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; - msg.msg_flags = MSG_WAITALL | (more)?MSG_MORE:0; + msg.msg_flags = MSG_WAITALL | (more ? MSG_MORE : 0); err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len); if (err != size) { @@ -217,8 +217,8 @@ void dst_dump_addr(struct socket *sk, struct sockaddr *sa, char *str) { if (sk->ops->family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in *)sa; - printk(KERN_INFO "%s %u.%u.%u.%u:%d.\n", - str, NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); + printk(KERN_INFO "%s %u.%u.%u.%u:%d.\n", str, + NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); } else if (sk->ops->family == AF_INET6) { struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa; printk(KERN_INFO "%s %pi6:%d", @@ -271,13 +271,13 @@ err_out_exit: * State reset is used to reconnect to the remote peer. * May fail, but who cares, we will try again later. */ -static void inline dst_state_reset_nolock(struct dst_state *st) +static inline void dst_state_reset_nolock(struct dst_state *st) { dst_state_exit_connected(st); dst_state_init_connected(st); } -static void inline dst_state_reset(struct dst_state *st) +static inline void dst_state_reset(struct dst_state *st) { dst_state_lock(st); dst_state_reset_nolock(st); @@ -335,9 +335,11 @@ static int dst_send_ping(struct dst_state *st) cmd->cmd = __cpu_to_be32(DST_PING); - err = dst_data_send_header(st->socket, cmd, sizeof(struct dst_cmd), 0); + err = dst_data_send_header(st->socket, cmd, + sizeof(struct dst_cmd), 0); } - dprintk("%s: st: %p, socket: %p, err: %d.\n", __func__, st, st->socket, err); + dprintk("%s: st: %p, socket: %p, err: %d.\n", __func__, + st, st->socket, err); dst_state_unlock(st); return err; @@ -390,8 +392,7 @@ int dst_data_recv(struct dst_state *st, void *data, unsigned int size) err = -ECONNRESET; dst_state_lock(st); - if ( st->socket && - (st->read_socket == st->socket) && + if (st->socket && (st->read_socket == st->socket) && (revents & POLLIN)) { err = dst_data_recv_raw(st, data, size); if (err > 0) { @@ -402,8 +403,9 @@ int dst_data_recv(struct dst_state *st, void *data, unsigned int size) } if (revents & err_mask || !st->socket) { - dprintk("%s: revents: %x, socket: %p, size: %u, err: %d.\n", - __func__, revents, st->socket, size, err); + dprintk("%s: revents: %x, socket: %p, size: %u, " + "err: %d.\n", __func__, revents, + st->socket, size, err); err = -ECONNRESET; } @@ -440,7 +442,8 @@ static int dst_process_cfg(struct dst_state *st) /* * Receive block IO from the network. */ -static int dst_recv_bio(struct dst_state *st, struct bio *bio, unsigned int total_size) +static int dst_recv_bio(struct dst_state *st, struct bio *bio, + unsigned int total_size) { struct bio_vec *bv; int i, err; @@ -450,9 +453,10 @@ static int dst_recv_bio(struct dst_state *st, struct bio *bio, unsigned int tota bio_for_each_segment(bv, bio, i) { sz = min(total_size, bv->bv_len); - dprintk("%s: bio: %llu/%u, total: %u, len: %u, sz: %u, off: %u.\n", - __func__, (u64)bio->bi_sector, bio->bi_size, total_size, - bv->bv_len, sz, bv->bv_offset); + dprintk("%s: bio: %llu/%u, total: %u, len: %u, sz: %u, " + "off: %u.\n", __func__, (u64)bio->bi_sector, + bio->bi_size, total_size, bv->bv_len, sz, + bv->bv_offset); data = kmap(bv->bv_page) + bv->bv_offset; err = dst_data_recv(st, data, sz); @@ -590,7 +594,8 @@ static int dst_recv_processing(struct dst_state *st) cmd->flags, cmd->rw); /* - * This should catch protocol breakage and random garbage instead of commands. + * This should catch protocol breakage and random garbage + * instead of commands. */ if (unlikely(cmd->csize > st->size - sizeof(struct dst_cmd))) { err = -EBADMSG; @@ -599,20 +604,20 @@ static int dst_recv_processing(struct dst_state *st) err = -EPROTO; switch (cmd->cmd) { - case DST_IO_RESPONSE: - err = dst_process_io_response(st); - break; - case DST_IO: - err = dst_process_io(st); - break; - case DST_CFG: - err = dst_process_cfg(st); - break; - case DST_PING: - err = 0; - break; - default: - break; + case DST_IO_RESPONSE: + err = dst_process_io_response(st); + break; + case DST_IO: + err = dst_process_io(st); + break; + case DST_CFG: + err = dst_process_cfg(st); + break; + case DST_PING: + err = 0; + break; + default: + break; } out_exit: diff --git a/drivers/staging/dst/thread_pool.c b/drivers/staging/dst/thread_pool.c index 7bed4e851029bff19c570a3d4a198d69f6490281..29a82b2602f3296b6b44fc4ca4626be629201350 100644 --- a/drivers/staging/dst/thread_pool.c +++ b/drivers/staging/dst/thread_pool.c @@ -30,8 +30,7 @@ * When action is being performed, thread can not be used by other users, * instead they will sleep until there is free thread to pick their work. */ -struct thread_pool_worker -{ +struct thread_pool_worker { struct list_head worker_entry; struct task_struct *thread; @@ -48,8 +47,8 @@ struct thread_pool_worker void *private; void *schedule_data; - int (* action)(void *private, void *schedule_data); - void (* cleanup)(void *private); + int (*action)(void *private, void *schedule_data); + void (*cleanup)(void *private); }; static void thread_pool_exit_worker(struct thread_pool_worker *w) @@ -116,10 +115,12 @@ void thread_pool_del_worker(struct thread_pool *p) struct thread_pool_worker *w = NULL; while (!w && p->thread_num) { - wait_event(p->wait, !list_empty(&p->ready_list) || !p->thread_num); + wait_event(p->wait, !list_empty(&p->ready_list) || + !p->thread_num); dprintk("%s: locking list_empty: %d, thread_num: %d.\n", - __func__, list_empty(&p->ready_list), p->thread_num); + __func__, list_empty(&p->ready_list), + p->thread_num); mutex_lock(&p->thread_lock); if (!list_empty(&p->ready_list)) { @@ -127,8 +128,9 @@ void thread_pool_del_worker(struct thread_pool *p) struct thread_pool_worker, worker_entry); - dprintk("%s: deleting w: %p, thread_num: %d, list: %p [%p.%p].\n", - __func__, w, p->thread_num, &p->ready_list, + dprintk("%s: deleting w: %p, thread_num: %d, " + "list: %p [%p.%p].\n", __func__, + w, p->thread_num, &p->ready_list, p->ready_list.prev, p->ready_list.next); p->thread_num--; @@ -182,8 +184,8 @@ void thread_pool_del_worker_id(struct thread_pool *p, unsigned int id) int thread_pool_add_worker(struct thread_pool *p, char *name, unsigned int id, - void *(* init)(void *private), - void (* cleanup)(void *private), + void *(*init)(void *private), + void (*cleanup)(void *private), void *private) { struct thread_pool_worker *w; @@ -243,8 +245,8 @@ void thread_pool_destroy(struct thread_pool *p) * They will have sequential IDs started from zero. */ struct thread_pool *thread_pool_create(int num, char *name, - void *(* init)(void *private), - void (* cleanup)(void *private), + void *(*init)(void *private), + void (*cleanup)(void *private), void *private) { struct thread_pool_worker *w, *tmp; @@ -262,7 +264,7 @@ struct thread_pool *thread_pool_create(int num, char *name, INIT_LIST_HEAD(&p->active_list); p->thread_num = 0; - for (i=0; ihas_data = 1; wake_up(&w->wait); } else { - list_move_tail(&w->worker_entry, &p->ready_list); + list_move_tail(&w->worker_entry, + &p->ready_list); } break; @@ -336,8 +339,8 @@ int thread_pool_schedule_private(struct thread_pool *p, * Schedule execution on arbitrary thread from the pool. */ int thread_pool_schedule(struct thread_pool *p, - int (* setup)(void *private, void *data), - int (* action)(void *private, void *data), + int (*setup)(void *private, void *data), + int (*action)(void *private, void *data), void *data, long timeout) { return thread_pool_schedule_private(p, setup, diff --git a/drivers/staging/dst/trans.c b/drivers/staging/dst/trans.c index 557d372a496ccbc65f818d201c9e27e13a422eab..1c36a6bc31d53d603d33b00157cf03ce67581b91 100644 --- a/drivers/staging/dst/trans.c +++ b/drivers/staging/dst/trans.c @@ -58,7 +58,7 @@ struct dst_trans *dst_trans_search(struct dst_node *node, dst_gen_t gen) } dprintk("%s: %s transaction: id: %llu.\n", __func__, - (ret)?"found":"not found", gen); + (ret) ? "found" : "not found", gen); return ret; } @@ -88,9 +88,9 @@ static int dst_trans_insert(struct dst_trans *new) new->send_time = jiffies; if (ret) { - printk("%s: exist: old: gen: %llu, bio: %llu/%u, send_time: %lu, " - "new: gen: %llu, bio: %llu/%u, send_time: %lu.\n", - __func__, + printk(KERN_DEBUG "%s: exist: old: gen: %llu, bio: %llu/%u, " + "send_time: %lu, new: gen: %llu, bio: %llu/%u, " + "send_time: %lu.\n", __func__, ret->gen, (u64)ret->bio->bi_sector, ret->bio->bi_size, ret->send_time, new->gen, (u64)new->bio->bi_sector, @@ -206,7 +206,8 @@ err_out_exit: */ static void dst_trans_scan(struct work_struct *work) { - struct dst_node *n = container_of(work, struct dst_node, trans_work.work); + struct dst_node *n = container_of(work, struct dst_node, + trans_work.work); struct rb_node *rb_node; struct dst_trans *t; unsigned long timeout = n->trans_scan_timeout; @@ -246,8 +247,8 @@ static void dst_trans_scan(struct work_struct *work) mutex_unlock(&n->trans_lock); /* - * If no timeout specified then system is in the middle of exiting process, - * so no need to reschedule scanning process again. + * If no timeout specified then system is in the middle of exiting + * process, so no need to reschedule scanning process again. */ if (timeout) { if (!num) @@ -313,7 +314,8 @@ int dst_node_trans_init(struct dst_node *n, unsigned int size) if (!n->trans_cache) goto err_out_exit; - n->trans_pool = mempool_create_slab_pool(dst_mempool_num, n->trans_cache); + n->trans_pool = mempool_create_slab_pool(dst_mempool_num, + n->trans_cache); if (!n->trans_pool) goto err_out_cache_destroy; diff --git a/drivers/staging/et131x/et1310_address_map.h b/drivers/staging/et131x/et1310_address_map.h index 2c3d65a622a7897caea27f11a34d3ce42202b78f..6da843cc343c4506c803d1e7d5e1b45d3e47ceb6 100644 --- a/drivers/staging/et131x/et1310_address_map.h +++ b/drivers/staging/et131x/et1310_address_map.h @@ -198,20 +198,10 @@ typedef struct _GLOBAL_t { /* Location: */ /* * structure for txdma packet ring number of descriptor reg in txdma address * map. Located at address 0x100C + * + * 31-10: unused + * 9-0: pr ndes */ -typedef union _TXDMA_PR_NUM_DES_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:22; /* bits 10-31 */ - u32 pr_ndes:10; /* bits 0-9 */ -#else - u32 pr_ndes:10; /* bits 0-9 */ - u32 unused:22; /* bits 10-31 */ -#endif - } bits; -} TXDMA_PR_NUM_DES_t, *PTXDMA_PR_NUM_DES_t; - #define ET_DMA10_MASK 0x3FF /* 10 bit mask for DMA10W types */ #define ET_DMA10_WRAP 0x400 @@ -261,7 +251,7 @@ typedef struct _TXDMA_t { /* Location: */ u32 csr; /* 0x1000 */ u32 pr_base_hi; /* 0x1004 */ u32 pr_base_lo; /* 0x1008 */ - TXDMA_PR_NUM_DES_t pr_num_des; /* 0x100C */ + u32 pr_num_des; /* 0x100C */ u32 txq_wr_addr; /* 0x1010 */ u32 txq_wr_addr_ext; /* 0x1014 */ u32 txq_rd_addr; /* 0x1018 */ @@ -349,36 +339,18 @@ typedef union _RXDMA_CSR_t { /* * structure for number of packets done reg in rxdma address map * located at address 0x200C + * + * 31-8: unused + * 7-0: num done */ -typedef union _RXDMA_NUM_PKT_DONE_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:24; /* bits 8-31 */ - u32 num_done:8; /* bits 0-7 */ -#else - u32 num_done:8; /* bits 0-7 */ - u32 unused:24; /* bits 8-31 */ -#endif - } bits; -} RXDMA_NUM_PKT_DONE_t, *PRXDMA_NUM_PKT_DONE_t; /* * structure for max packet time reg in rxdma address map * located at address 0x2010 + * + * 31-18: unused + * 17-0: time done */ -typedef union _RXDMA_MAX_PKT_TIME_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:14; /* bits 18-31 */ - u32 time_done:18; /* bits 0-17 */ -#else - u32 time_done:18; /* bits 0-17 */ - u32 unused:14; /* bits 18-31 */ -#endif - } bits; -} RXDMA_MAX_PKT_TIME_t, *PRXDMA_MAX_PKT_TIME_t; /* * structure for rx queue read address reg in rxdma address map @@ -413,91 +385,44 @@ typedef union _RXDMA_MAX_PKT_TIME_t { /* * structure for packet status ring number of descriptors reg in rxdma address * map. Located at address 0x2028 + * + * 31-12: unused + * 11-0: psr ndes */ -typedef union _RXDMA_PSR_NUM_DES_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:20; /* bits 12-31 */ - u32 psr_ndes:12; /* bit 0-11 */ -#else - u32 psr_ndes:12; /* bit 0-11 */ - u32 unused:20; /* bits 12-31 */ -#endif - } bits; -} RXDMA_PSR_NUM_DES_t, *PRXDMA_PSR_NUM_DES_t; /* * structure for packet status ring available offset reg in rxdma address map * located at address 0x202C + * + * 31-13: unused + * 12: psr avail wrap + * 11-0: psr avail */ -typedef union _RXDMA_PSR_AVAIL_OFFSET_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:19; /* bits 13-31 */ - u32 psr_avail_wrap:1; /* bit 12 */ - u32 psr_avail:12; /* bit 0-11 */ -#else - u32 psr_avail:12; /* bit 0-11 */ - u32 psr_avail_wrap:1; /* bit 12 */ - u32 unused:19; /* bits 13-31 */ -#endif - } bits; -} RXDMA_PSR_AVAIL_OFFSET_t, *PRXDMA_PSR_AVAIL_OFFSET_t; /* * structure for packet status ring full offset reg in rxdma address map * located at address 0x2030 + * + * 31-13: unused + * 12: psr full wrap + * 11-0: psr full */ -typedef union _RXDMA_PSR_FULL_OFFSET_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:19; /* bits 13-31 */ - u32 psr_full_wrap:1; /* bit 12 */ - u32 psr_full:12; /* bit 0-11 */ -#else - u32 psr_full:12; /* bit 0-11 */ - u32 psr_full_wrap:1; /* bit 12 */ - u32 unused:19; /* bits 13-31 */ -#endif - } bits; -} RXDMA_PSR_FULL_OFFSET_t, *PRXDMA_PSR_FULL_OFFSET_t; /* * structure for packet status ring access index reg in rxdma address map * located at address 0x2034 + * + * 31-5: unused + * 4-0: psr_ai */ -typedef union _RXDMA_PSR_ACCESS_INDEX_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:27; /* bits 5-31 */ - u32 psr_ai:5; /* bits 0-4 */ -#else - u32 psr_ai:5; /* bits 0-4 */ - u32 unused:27; /* bits 5-31 */ -#endif - } bits; -} RXDMA_PSR_ACCESS_INDEX_t, *PRXDMA_PSR_ACCESS_INDEX_t; /* * structure for packet status ring minimum descriptors reg in rxdma address * map. Located at address 0x2038 + * + * 31-12: unused + * 11-0: psr_min */ -typedef union _RXDMA_PSR_MIN_DES_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:20; /* bits 12-31 */ - u32 psr_min:12; /* bits 0-11 */ -#else - u32 psr_min:12; /* bits 0-11 */ - u32 unused:20; /* bits 12-31 */ -#endif - } bits; -} RXDMA_PSR_MIN_DES_t, *PRXDMA_PSR_MIN_DES_t; /* * structure for free buffer ring base lo address reg in rxdma address map @@ -514,6 +439,9 @@ typedef union _RXDMA_PSR_MIN_DES_t { /* * structure for free buffer ring number of descriptors reg in rxdma address * map. Located at address 0x2044 + * + * 31-10: unused + * 9-0: fbr ndesc */ typedef union _RXDMA_FBR_NUM_DES_t { u32 value; @@ -543,36 +471,18 @@ typedef union _RXDMA_FBR_NUM_DES_t { /* * structure for free buffer cache 0 full offset reg in rxdma address map * located at address 0x2050 + * + * 31-5: unused + * 4-0: fbc rdi */ -typedef union _RXDMA_FBC_RD_INDEX_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:27; /* bits 5-31 */ - u32 fbc_rdi:5; /* bit 0-4 */ -#else - u32 fbc_rdi:5; /* bit 0-4 */ - u32 unused:27; /* bits 5-31 */ -#endif - } bits; -} RXDMA_FBC_RD_INDEX_t, *PRXDMA_FBC_RD_INDEX_t; /* * structure for free buffer ring 0 minimum descriptor reg in rxdma address map * located at address 0x2054 + * + * 31-10: unused + * 9-0: fbr min */ -typedef union _RXDMA_FBR_MIN_DES_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:22; /* bits 10-31 */ - u32 fbr_min:10; /* bits 0-9 */ -#else - u32 fbr_min:10; /* bits 0-9 */ - u32 unused:22; /* bits 10-31 */ -#endif - } bits; -} RXDMA_FBR_MIN_DES_t, *PRXDMA_FBR_MIN_DES_t; /* * structure for free buffer ring 1 base address lo reg in rxdma address map @@ -618,32 +528,32 @@ typedef struct _RXDMA_t { /* Location: */ RXDMA_CSR_t csr; /* 0x2000 */ u32 dma_wb_base_lo; /* 0x2004 */ u32 dma_wb_base_hi; /* 0x2008 */ - RXDMA_NUM_PKT_DONE_t num_pkt_done; /* 0x200C */ - RXDMA_MAX_PKT_TIME_t max_pkt_time; /* 0x2010 */ + u32 num_pkt_done; /* 0x200C */ + u32 max_pkt_time; /* 0x2010 */ u32 rxq_rd_addr; /* 0x2014 */ - u32 rxq_rd_addr_ext; /* 0x2018 */ + u32 rxq_rd_addr_ext; /* 0x2018 */ u32 rxq_wr_addr; /* 0x201C */ u32 psr_base_lo; /* 0x2020 */ u32 psr_base_hi; /* 0x2024 */ - RXDMA_PSR_NUM_DES_t psr_num_des; /* 0x2028 */ - RXDMA_PSR_AVAIL_OFFSET_t psr_avail_offset; /* 0x202C */ - RXDMA_PSR_FULL_OFFSET_t psr_full_offset; /* 0x2030 */ - RXDMA_PSR_ACCESS_INDEX_t psr_access_index; /* 0x2034 */ - RXDMA_PSR_MIN_DES_t psr_min_des; /* 0x2038 */ + u32 psr_num_des; /* 0x2028 */ + u32 psr_avail_offset; /* 0x202C */ + u32 psr_full_offset; /* 0x2030 */ + u32 psr_access_index; /* 0x2034 */ + u32 psr_min_des; /* 0x2038 */ u32 fbr0_base_lo; /* 0x203C */ u32 fbr0_base_hi; /* 0x2040 */ - RXDMA_FBR_NUM_DES_t fbr0_num_des; /* 0x2044 */ - u32 fbr0_avail_offset; /* 0x2048 */ - u32 fbr0_full_offset; /* 0x204C */ - RXDMA_FBC_RD_INDEX_t fbr0_rd_index; /* 0x2050 */ - RXDMA_FBR_MIN_DES_t fbr0_min_des; /* 0x2054 */ + u32 fbr0_num_des; /* 0x2044 */ + u32 fbr0_avail_offset; /* 0x2048 */ + u32 fbr0_full_offset; /* 0x204C */ + u32 fbr0_rd_index; /* 0x2050 */ + u32 fbr0_min_des; /* 0x2054 */ u32 fbr1_base_lo; /* 0x2058 */ u32 fbr1_base_hi; /* 0x205C */ - RXDMA_FBR_NUM_DES_t fbr1_num_des; /* 0x2060 */ - u32 fbr1_avail_offset; /* 0x2064 */ - u32 fbr1_full_offset; /* 0x2068 */ - RXDMA_FBC_RD_INDEX_t fbr1_rd_index; /* 0x206C */ - RXDMA_FBR_MIN_DES_t fbr1_min_des; /* 0x2070 */ + u32 fbr1_num_des; /* 0x2060 */ + u32 fbr1_avail_offset; /* 0x2064 */ + u32 fbr1_full_offset; /* 0x2068 */ + u32 fbr1_rd_index; /* 0x206C */ + u32 fbr1_min_des; /* 0x2070 */ } RXDMA_t, *PRXDMA_t; /* END OF RXDMA REGISTER ADDRESS MAP */ @@ -685,23 +595,11 @@ typedef union _TXMAC_CTL_t { /* * structure for shadow pointer reg in txmac address map * located at address 0x3004 + * 31-27: reserved + * 26-16: txq rd ptr + * 15-11: reserved + * 10-0: txq wr ptr */ -typedef union _TXMAC_SHADOW_PTR_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 reserved2:5; /* bits 27-31 */ - u32 txq_rd_ptr:11; /* bits 16-26 */ - u32 reserved:5; /* bits 11-15 */ - u32 txq_wr_ptr:11; /* bits 0-10 */ -#else - u32 txq_wr_ptr:11; /* bits 0-10 */ - u32 reserved:5; /* bits 11-15 */ - u32 txq_rd_ptr:11; /* bits 16-26 */ - u32 reserved2:5; /* bits 27-31 */ -#endif - } bits; -} TXMAC_SHADOW_PTR_t, *PTXMAC_SHADOW_PTR_t; /* * structure for error count reg in txmac address map @@ -727,59 +625,26 @@ typedef union _TXMAC_ERR_CNT_t { /* * structure for max fill reg in txmac address map * located at address 0x300C + * 31-12: unused + * 11-0: max fill */ -typedef union _TXMAC_MAX_FILL_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:20; /* bits 12-31 */ - u32 max_fill:12; /* bits 0-11 */ -#else - u32 max_fill:12; /* bits 0-11 */ - u32 unused:20; /* bits 12-31 */ -#endif - } bits; -} TXMAC_MAX_FILL_t, *PTXMAC_MAX_FILL_t; /* * structure for cf parameter reg in txmac address map * located at address 0x3010 + * 31-16: cfep + * 15-0: cfpt */ -typedef union _TXMAC_CF_PARAM_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 cfep:16; /* bits 16-31 */ - u32 cfpt:16; /* bits 0-15 */ -#else - u32 cfpt:16; /* bits 0-15 */ - u32 cfep:16; /* bits 16-31 */ -#endif - } bits; -} TXMAC_CF_PARAM_t, *PTXMAC_CF_PARAM_t; /* * structure for tx test reg in txmac address map * located at address 0x3014 + * 31-17: unused + * 16: reserved1 + * 15: txtest_en + * 14-11: unused + * 10-0: txq test pointer */ -typedef union _TXMAC_TXTEST_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused2:15; /* bits 17-31 */ - u32 reserved1:1; /* bit 16 */ - u32 txtest_en:1; /* bit 15 */ - u32 unused1:4; /* bits 11-14 */ - u32 txqtest_ptr:11; /* bits 0-11 */ -#else - u32 txqtest_ptr:11; /* bits 0-10 */ - u32 unused1:4; /* bits 11-14 */ - u32 txtest_en:1; /* bit 15 */ - u32 reserved1:1; /* bit 16 */ - u32 unused2:15; /* bits 17-31 */ -#endif - } bits; -} TXMAC_TXTEST_t, *PTXMAC_TXTEST_t; /* * structure for error reg in txmac address map @@ -846,35 +711,25 @@ typedef union _TXMAC_ERR_INT_t { /* * structure for error interrupt reg in txmac address map * located at address 0x3020 + * + * 31-2: unused + * 1: bp_req + * 0: bp_xonxoff */ -typedef union _TXMAC_CP_CTRL_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:30; /* bits 2-31 */ - u32 bp_req:1; /* bit 1 */ - u32 bp_xonxoff:1; /* bit 0 */ -#else - u32 bp_xonxoff:1; /* bit 0 */ - u32 bp_req:1; /* bit 1 */ - u32 unused:30; /* bits 2-31 */ -#endif - } bits; -} TXMAC_BP_CTRL_t, *PTXMAC_BP_CTRL_t; /* * Tx MAC Module of JAGCore Address Mapping */ typedef struct _TXMAC_t { /* Location: */ TXMAC_CTL_t ctl; /* 0x3000 */ - TXMAC_SHADOW_PTR_t shadow_ptr; /* 0x3004 */ + u32 shadow_ptr; /* 0x3004 */ TXMAC_ERR_CNT_t err_cnt; /* 0x3008 */ - TXMAC_MAX_FILL_t max_fill; /* 0x300C */ - TXMAC_CF_PARAM_t cf_param; /* 0x3010 */ - TXMAC_TXTEST_t tx_test; /* 0x3014 */ + u32 max_fill; /* 0x300C */ + u32 cf_param; /* 0x3010 */ + u32 tx_test; /* 0x3014 */ TXMAC_ERR_t err; /* 0x3018 */ TXMAC_ERR_INT_t err_int; /* 0x301C */ - TXMAC_BP_CTRL_t bp_ctrl; /* 0x3020 */ + u32 bp_ctrl; /* 0x3020 */ } TXMAC_t, *PTXMAC_t; /* END OF TXMAC REGISTER ADDRESS MAP */ @@ -1308,157 +1163,77 @@ typedef struct _RXMAC_t { /* Location: */ /* * structure for configuration #1 reg in mac address map. * located at address 0x5000 - */ -typedef union _MAC_CFG1_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 soft_reset:1; /* bit 31 */ - u32 sim_reset:1; /* bit 30 */ - u32 reserved3:10; /* bits 20-29 */ - u32 reset_rx_mc:1; /* bit 19 */ - u32 reset_tx_mc:1; /* bit 18 */ - u32 reset_rx_fun:1; /* bit 17 */ - u32 reset_tx_fun:1; /* bit 16 */ - u32 reserved2:7; /* bits 9-15 */ - u32 loop_back:1; /* bit 8 */ - u32 reserved1:2; /* bits 6-7 */ - u32 rx_flow:1; /* bit 5 */ - u32 tx_flow:1; /* bit 4 */ - u32 syncd_rx_en:1; /* bit 3 */ - u32 rx_enable:1; /* bit 2 */ - u32 syncd_tx_en:1; /* bit 1 */ - u32 tx_enable:1; /* bit 0 */ -#else - u32 tx_enable:1; /* bit 0 */ - u32 syncd_tx_en:1; /* bit 1 */ - u32 rx_enable:1; /* bit 2 */ - u32 syncd_rx_en:1; /* bit 3 */ - u32 tx_flow:1; /* bit 4 */ - u32 rx_flow:1; /* bit 5 */ - u32 reserved1:2; /* bits 6-7 */ - u32 loop_back:1; /* bit 8 */ - u32 reserved2:7; /* bits 9-15 */ - u32 reset_tx_fun:1; /* bit 16 */ - u32 reset_rx_fun:1; /* bit 17 */ - u32 reset_tx_mc:1; /* bit 18 */ - u32 reset_rx_mc:1; /* bit 19 */ - u32 reserved3:10; /* bits 20-29 */ - u32 sim_reset:1; /* bit 30 */ - u32 soft_reset:1; /* bit 31 */ -#endif - } bits; -} MAC_CFG1_t, *PMAC_CFG1_t; + * + * 31: soft reset + * 30: sim reset + * 29-20: reserved + * 19: reset rx mc + * 18: reset tx mc + * 17: reset rx func + * 16: reset tx fnc + * 15-9: reserved + * 8: loopback + * 7-6: reserved + * 5: rx flow + * 4: tx flow + * 3: syncd rx en + * 2: rx enable + * 1: syncd tx en + * 0: tx enable + */ + +#define CFG1_LOOPBACK 0x00000100 +#define CFG1_RX_FLOW 0x00000020 +#define CFG1_TX_FLOW 0x00000010 +#define CFG1_RX_ENABLE 0x00000004 +#define CFG1_TX_ENABLE 0x00000001 +#define CFG1_WAIT 0x0000000A /* RX & TX syncd */ /* * structure for configuration #2 reg in mac address map. * located at address 0x5004 + * 31-16: reserved + * 15-12: preamble + * 11-10: reserved + * 9-8: if mode + * 7-6: reserved + * 5: huge frame + * 4: length check + * 3: undefined + * 2: pad crc + * 1: crc enable + * 0: full duplex */ -typedef union _MAC_CFG2_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 reserved3:16; /* bits 16-31 */ - u32 preamble_len:4; /* bits 12-15 */ - u32 reserved2:2; /* bits 10-11 */ - u32 if_mode:2; /* bits 8-9 */ - u32 reserved1:2; /* bits 6-7 */ - u32 huge_frame:1; /* bit 5 */ - u32 len_check:1; /* bit 4 */ - u32 undefined:1; /* bit 3 */ - u32 pad_crc:1; /* bit 2 */ - u32 crc_enable:1; /* bit 1 */ - u32 full_duplex:1; /* bit 0 */ -#else - u32 full_duplex:1; /* bit 0 */ - u32 crc_enable:1; /* bit 1 */ - u32 pad_crc:1; /* bit 2 */ - u32 undefined:1; /* bit 3 */ - u32 len_check:1; /* bit 4 */ - u32 huge_frame:1; /* bit 5 */ - u32 reserved1:2; /* bits 6-7 */ - u32 if_mode:2; /* bits 8-9 */ - u32 reserved2:2; /* bits 10-11 */ - u32 preamble_len:4; /* bits 12-15 */ - u32 reserved3:16; /* bits 16-31 */ -#endif - } bits; -} MAC_CFG2_t, *PMAC_CFG2_t; + /* * structure for Interpacket gap reg in mac address map. * located at address 0x5008 - */ -typedef union _MAC_IPG_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 reserved:1; /* bit 31 */ - u32 non_B2B_ipg_1:7; /* bits 24-30 */ - u32 undefined2:1; /* bit 23 */ - u32 non_B2B_ipg_2:7; /* bits 16-22 */ - u32 min_ifg_enforce:8; /* bits 8-15 */ - u32 undefined1:1; /* bit 7 */ - u32 B2B_ipg:7; /* bits 0-6 */ -#else - u32 B2B_ipg:7; /* bits 0-6 */ - u32 undefined1:1; /* bit 7 */ - u32 min_ifg_enforce:8; /* bits 8-15 */ - u32 non_B2B_ipg_2:7; /* bits 16-22 */ - u32 undefined2:1; /* bit 23 */ - u32 non_B2B_ipg_1:7; /* bits 24-30 */ - u32 reserved:1; /* bit 31 */ -#endif - } bits; -} MAC_IPG_t, *PMAC_IPG_t; - -/* + * + * 31: reserved + * 30-24: non B2B ipg 1 + * 23: undefined + * 22-16: non B2B ipg 2 + * 15-8: Min ifg enforce + * 7-0: B2B ipg + * * structure for half duplex reg in mac address map. * located at address 0x500C + * 31-24: reserved + * 23-20: Alt BEB trunc + * 19: Alt BEB enable + * 18: BP no backoff + * 17: no backoff + * 16: excess defer + * 15-12: re-xmit max + * 11-10: reserved + * 9-0: collision window */ -typedef union _MAC_HFDP_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 reserved2:8; /* bits 24-31 */ - u32 alt_beb_trunc:4; /* bits 23-20 */ - u32 alt_beb_enable:1; /* bit 19 */ - u32 bp_no_backoff:1; /* bit 18 */ - u32 no_backoff:1; /* bit 17 */ - u32 excess_defer:1; /* bit 16 */ - u32 rexmit_max:4; /* bits 12-15 */ - u32 reserved1:2; /* bits 10-11 */ - u32 coll_window:10; /* bits 0-9 */ -#else - u32 coll_window:10; /* bits 0-9 */ - u32 reserved1:2; /* bits 10-11 */ - u32 rexmit_max:4; /* bits 12-15 */ - u32 excess_defer:1; /* bit 16 */ - u32 no_backoff:1; /* bit 17 */ - u32 bp_no_backoff:1; /* bit 18 */ - u32 alt_beb_enable:1; /* bit 19 */ - u32 alt_beb_trunc:4; /* bits 23-20 */ - u32 reserved2:8; /* bits 24-31 */ -#endif - } bits; -} MAC_HFDP_t, *PMAC_HFDP_t; /* * structure for Maximum Frame Length reg in mac address map. - * located at address 0x5010 + * located at address 0x5010: bits 0-15 hold the length. */ -typedef union _MAC_MAX_FM_LEN_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 reserved:16; /* bits 16-31 */ - u32 max_len:16; /* bits 0-15 */ -#else - u32 max_len:16; /* bits 0-15 */ - u32 reserved:16; /* bits 16-31 */ -#endif - } bits; -} MAC_MAX_FM_LEN_t, *PMAC_MAX_FM_LEN_t; /* * structure for Reserve 1 reg in mac address map. @@ -1469,186 +1244,87 @@ typedef union _MAC_MAX_FM_LEN_t { /* * structure for Test reg in mac address map. * located at address 0x501C + * test: bits 0-2, rest unused */ -typedef union _MAC_TEST_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:29; /* bits 3-31 */ - u32 mac_test:3; /* bits 0-2 */ -#else - u32 mac_test:3; /* bits 0-2 */ - u32 unused:29; /* bits 3-31 */ -#endif - } bits; -} MAC_TEST_t, *PMAC_TEST_t; /* * structure for MII Management Configuration reg in mac address map. * located at address 0x5020 + * + * 31: reset MII mgmt + * 30-6: unused + * 5: scan auto increment + * 4: preamble supress + * 3: undefined + * 2-0: mgmt clock reset */ -typedef union _MII_MGMT_CFG_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 reset_mii_mgmt:1; /* bit 31 */ - u32 reserved:25; /* bits 6-30 */ - u32 scan_auto_incremt:1; /* bit 5 */ - u32 preamble_suppress:1; /* bit 4 */ - u32 undefined:1; /* bit 3 */ - u32 mgmt_clk_reset:3; /* bits 0-2 */ -#else - u32 mgmt_clk_reset:3; /* bits 0-2 */ - u32 undefined:1; /* bit 3 */ - u32 preamble_suppress:1; /* bit 4 */ - u32 scan_auto_incremt:1; /* bit 5 */ - u32 reserved:25; /* bits 6-30 */ - u32 reset_mii_mgmt:1; /* bit 31 */ -#endif - } bits; -} MII_MGMT_CFG_t, *PMII_MGMT_CFG_t; /* * structure for MII Management Command reg in mac address map. * located at address 0x5024 + * bit 1: scan cycle + * bit 0: read cycle */ -typedef union _MII_MGMT_CMD_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 reserved:30; /* bits 2-31 */ - u32 scan_cycle:1; /* bit 1 */ - u32 read_cycle:1; /* bit 0 */ -#else - u32 read_cycle:1; /* bit 0 */ - u32 scan_cycle:1; /* bit 1 */ - u32 reserved:30; /* bits 2-31 */ -#endif - } bits; -} MII_MGMT_CMD_t, *PMII_MGMT_CMD_t; /* * structure for MII Management Address reg in mac address map. * located at address 0x5028 + * 31-13: reserved + * 12-8: phy addr + * 7-5: reserved + * 4-0: register */ -typedef union _MII_MGMT_ADDR_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 reserved2:19; /* bit 13-31 */ - u32 phy_addr:5; /* bits 8-12 */ - u32 reserved1:3; /* bits 5-7 */ - u32 reg_addr:5; /* bits 0-4 */ -#else - u32 reg_addr:5; /* bits 0-4 */ - u32 reserved1:3; /* bits 5-7 */ - u32 phy_addr:5; /* bits 8-12 */ - u32 reserved2:19; /* bit 13-31 */ -#endif - } bits; -} MII_MGMT_ADDR_t, *PMII_MGMT_ADDR_t; + +#define MII_ADDR(phy,reg) ((phy) << 8 | (reg)) /* * structure for MII Management Control reg in mac address map. * located at address 0x502C + * 31-16: reserved + * 15-0: phy control */ -typedef union _MII_MGMT_CTRL_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 reserved:16; /* bits 16-31 */ - u32 phy_ctrl:16; /* bits 0-15 */ -#else - u32 phy_ctrl:16; /* bits 0-15 */ - u32 reserved:16; /* bits 16-31 */ -#endif - } bits; -} MII_MGMT_CTRL_t, *PMII_MGMT_CTRL_t; /* * structure for MII Management Status reg in mac address map. * located at address 0x5030 + * 31-16: reserved + * 15-0: phy control */ -typedef union _MII_MGMT_STAT_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 reserved:16; /* bits 16-31 */ - u32 phy_stat:16; /* bits 0-15 */ -#else - u32 phy_stat:16; /* bits 0-15 */ - u32 reserved:16; /* bits 16-31 */ -#endif - } bits; -} MII_MGMT_STAT_t, *PMII_MGMT_STAT_t; /* * structure for MII Management Indicators reg in mac address map. * located at address 0x5034 + * 31-3: reserved + * 2: not valid + * 1: scanning + * 0: busy */ -typedef union _MII_MGMT_INDICATOR_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 reserved:29; /* bits 3-31 */ - u32 not_valid:1; /* bit 2 */ - u32 scanning:1; /* bit 1 */ - u32 busy:1; /* bit 0 */ -#else - u32 busy:1; /* bit 0 */ - u32 scanning:1; /* bit 1 */ - u32 not_valid:1; /* bit 2 */ - u32 reserved:29; /* bits 3-31 */ -#endif - } bits; -} MII_MGMT_INDICATOR_t, *PMII_MGMT_INDICATOR_t; + +#define MGMT_BUSY 0x00000001 /* busy */ +#define MGMT_WAIT 0x00000005 /* busy | not valid */ /* * structure for Interface Control reg in mac address map. * located at address 0x5038 + * + * 31: reset if module + * 30-28: reserved + * 27: tbi mode + * 26: ghd mode + * 25: lhd mode + * 24: phy mode + * 23: reset per mii + * 22-17: reserved + * 16: speed + * 15: reset pe100x + * 14-11: reserved + * 10: force quiet + * 9: no cipher + * 8: disable link fail + * 7: reset gpsi + * 6-1: reserved + * 0: enable jabber protection */ -typedef union _MAC_IF_CTRL_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 reset_if_module:1; /* bit 31 */ - u32 reserved4:3; /* bit 28-30 */ - u32 tbi_mode:1; /* bit 27 */ - u32 ghd_mode:1; /* bit 26 */ - u32 lhd_mode:1; /* bit 25 */ - u32 phy_mode:1; /* bit 24 */ - u32 reset_per_mii:1; /* bit 23 */ - u32 reserved3:6; /* bits 17-22 */ - u32 speed:1; /* bit 16 */ - u32 reset_pe100x:1; /* bit 15 */ - u32 reserved2:4; /* bits 11-14 */ - u32 force_quiet:1; /* bit 10 */ - u32 no_cipher:1; /* bit 9 */ - u32 disable_link_fail:1; /* bit 8 */ - u32 reset_gpsi:1; /* bit 7 */ - u32 reserved1:6; /* bits 1-6 */ - u32 enab_jab_protect:1; /* bit 0 */ -#else - u32 enab_jab_protect:1; /* bit 0 */ - u32 reserved1:6; /* bits 1-6 */ - u32 reset_gpsi:1; /* bit 7 */ - u32 disable_link_fail:1; /* bit 8 */ - u32 no_cipher:1; /* bit 9 */ - u32 force_quiet:1; /* bit 10 */ - u32 reserved2:4; /* bits 11-14 */ - u32 reset_pe100x:1; /* bit 15 */ - u32 speed:1; /* bit 16 */ - u32 reserved3:6; /* bits 17-22 */ - u32 reset_per_mii:1; /* bit 23 */ - u32 phy_mode:1; /* bit 24 */ - u32 lhd_mode:1; /* bit 25 */ - u32 ghd_mode:1; /* bit 26 */ - u32 tbi_mode:1; /* bit 27 */ - u32 reserved4:3; /* bit 28-30 */ - u32 reset_if_module:1; /* bit 31 */ -#endif - } bits; -} MAC_IF_CTRL_t, *PMAC_IF_CTRL_t; /* * structure for Interface Status reg in mac address map. @@ -1729,21 +1405,21 @@ typedef union _MAC_STATION_ADDR2_t { * MAC Module of JAGCore Address Mapping */ typedef struct _MAC_t { /* Location: */ - MAC_CFG1_t cfg1; /* 0x5000 */ - MAC_CFG2_t cfg2; /* 0x5004 */ - MAC_IPG_t ipg; /* 0x5008 */ - MAC_HFDP_t hfdp; /* 0x500C */ - MAC_MAX_FM_LEN_t max_fm_len; /* 0x5010 */ + u32 cfg1; /* 0x5000 */ + u32 cfg2; /* 0x5004 */ + u32 ipg; /* 0x5008 */ + u32 hfdp; /* 0x500C */ + u32 max_fm_len; /* 0x5010 */ u32 rsv1; /* 0x5014 */ u32 rsv2; /* 0x5018 */ - MAC_TEST_t mac_test; /* 0x501C */ - MII_MGMT_CFG_t mii_mgmt_cfg; /* 0x5020 */ - MII_MGMT_CMD_t mii_mgmt_cmd; /* 0x5024 */ - MII_MGMT_ADDR_t mii_mgmt_addr; /* 0x5028 */ - MII_MGMT_CTRL_t mii_mgmt_ctrl; /* 0x502C */ - MII_MGMT_STAT_t mii_mgmt_stat; /* 0x5030 */ - MII_MGMT_INDICATOR_t mii_mgmt_indicator; /* 0x5034 */ - MAC_IF_CTRL_t if_ctrl; /* 0x5038 */ + u32 mac_test; /* 0x501C */ + u32 mii_mgmt_cfg; /* 0x5020 */ + u32 mii_mgmt_cmd; /* 0x5024 */ + u32 mii_mgmt_addr; /* 0x5028 */ + u32 mii_mgmt_ctrl; /* 0x502C */ + u32 mii_mgmt_stat; /* 0x5030 */ + u32 mii_mgmt_indicator; /* 0x5034 */ + u32 if_ctrl; /* 0x5038 */ MAC_IF_STAT_t if_stat; /* 0x503C */ MAC_STATION_ADDR1_t station_addr_1; /* 0x5040 */ MAC_STATION_ADDR2_t station_addr_2; /* 0x5044 */ @@ -1756,120 +1432,60 @@ typedef struct _MAC_t { /* Location: */ /* * structure for Carry Register One and it's Mask Register reg located in mac * stat address map address 0x6130 and 0x6138. + * + * 31: tr64 + * 30: tr127 + * 29: tr255 + * 28: tr511 + * 27: tr1k + * 26: trmax + * 25: trmgv + * 24-17: unused + * 16: rbyt + * 15: rpkt + * 14: rfcs + * 13: rmca + * 12: rbca + * 11: rxcf + * 10: rxpf + * 9: rxuo + * 8: raln + * 7: rflr + * 6: rcde + * 5: rcse + * 4: rund + * 3: rovr + * 2: rfrg + * 1: rjbr + * 0: rdrp */ -typedef union _MAC_STAT_REG_1_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 tr64:1; /* bit 31 */ - u32 tr127:1; /* bit 30 */ - u32 tr255:1; /* bit 29 */ - u32 tr511:1; /* bit 28 */ - u32 tr1k:1; /* bit 27 */ - u32 trmax:1; /* bit 26 */ - u32 trmgv:1; /* bit 25 */ - u32 unused:8; /* bits 17-24 */ - u32 rbyt:1; /* bit 16 */ - u32 rpkt:1; /* bit 15 */ - u32 rfcs:1; /* bit 14 */ - u32 rmca:1; /* bit 13 */ - u32 rbca:1; /* bit 12 */ - u32 rxcf:1; /* bit 11 */ - u32 rxpf:1; /* bit 10 */ - u32 rxuo:1; /* bit 9 */ - u32 raln:1; /* bit 8 */ - u32 rflr:1; /* bit 7 */ - u32 rcde:1; /* bit 6 */ - u32 rcse:1; /* bit 5 */ - u32 rund:1; /* bit 4 */ - u32 rovr:1; /* bit 3 */ - u32 rfrg:1; /* bit 2 */ - u32 rjbr:1; /* bit 1 */ - u32 rdrp:1; /* bit 0 */ -#else - u32 rdrp:1; /* bit 0 */ - u32 rjbr:1; /* bit 1 */ - u32 rfrg:1; /* bit 2 */ - u32 rovr:1; /* bit 3 */ - u32 rund:1; /* bit 4 */ - u32 rcse:1; /* bit 5 */ - u32 rcde:1; /* bit 6 */ - u32 rflr:1; /* bit 7 */ - u32 raln:1; /* bit 8 */ - u32 rxuo:1; /* bit 9 */ - u32 rxpf:1; /* bit 10 */ - u32 rxcf:1; /* bit 11 */ - u32 rbca:1; /* bit 12 */ - u32 rmca:1; /* bit 13 */ - u32 rfcs:1; /* bit 14 */ - u32 rpkt:1; /* bit 15 */ - u32 rbyt:1; /* bit 16 */ - u32 unused:8; /* bits 17-24 */ - u32 trmgv:1; /* bit 25 */ - u32 trmax:1; /* bit 26 */ - u32 tr1k:1; /* bit 27 */ - u32 tr511:1; /* bit 28 */ - u32 tr255:1; /* bit 29 */ - u32 tr127:1; /* bit 30 */ - u32 tr64:1; /* bit 31 */ -#endif - } bits; -} MAC_STAT_REG_1_t, *PMAC_STAT_REG_1_t; /* * structure for Carry Register Two Mask Register reg in mac stat address map. * located at address 0x613C + * + * 31-20: unused + * 19: tjbr + * 18: tfcs + * 17: txcf + * 16: tovr + * 15: tund + * 14: trfg + * 13: tbyt + * 12: tpkt + * 11: tmca + * 10: tbca + * 9: txpf + * 8: tdfr + * 7: tedf + * 6: tscl + * 5: tmcl + * 4: tlcl + * 3: txcl + * 2: tncl + * 1: tpfh + * 0: tdrp */ -typedef union _MAC_STAT_REG_2_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:12; /* bit 20-31 */ - u32 tjbr:1; /* bit 19 */ - u32 tfcs:1; /* bit 18 */ - u32 txcf:1; /* bit 17 */ - u32 tovr:1; /* bit 16 */ - u32 tund:1; /* bit 15 */ - u32 tfrg:1; /* bit 14 */ - u32 tbyt:1; /* bit 13 */ - u32 tpkt:1; /* bit 12 */ - u32 tmca:1; /* bit 11 */ - u32 tbca:1; /* bit 10 */ - u32 txpf:1; /* bit 9 */ - u32 tdfr:1; /* bit 8 */ - u32 tedf:1; /* bit 7 */ - u32 tscl:1; /* bit 6 */ - u32 tmcl:1; /* bit 5 */ - u32 tlcl:1; /* bit 4 */ - u32 txcl:1; /* bit 3 */ - u32 tncl:1; /* bit 2 */ - u32 tpfh:1; /* bit 1 */ - u32 tdrp:1; /* bit 0 */ -#else - u32 tdrp:1; /* bit 0 */ - u32 tpfh:1; /* bit 1 */ - u32 tncl:1; /* bit 2 */ - u32 txcl:1; /* bit 3 */ - u32 tlcl:1; /* bit 4 */ - u32 tmcl:1; /* bit 5 */ - u32 tscl:1; /* bit 6 */ - u32 tedf:1; /* bit 7 */ - u32 tdfr:1; /* bit 8 */ - u32 txpf:1; /* bit 9 */ - u32 tbca:1; /* bit 10 */ - u32 tmca:1; /* bit 11 */ - u32 tpkt:1; /* bit 12 */ - u32 tbyt:1; /* bit 13 */ - u32 tfrg:1; /* bit 14 */ - u32 tund:1; /* bit 15 */ - u32 tovr:1; /* bit 16 */ - u32 txcf:1; /* bit 17 */ - u32 tfcs:1; /* bit 18 */ - u32 tjbr:1; /* bit 19 */ - u32 unused:12; /* bit 20-31 */ -#endif - } bits; -} MAC_STAT_REG_2_t, *PMAC_STAT_REG_2_t; /* * MAC STATS Module of JAGCore Address Mapping @@ -2010,16 +1626,16 @@ typedef struct _MAC_STAT_t { /* Location: */ u32 TFrg; /* 0x612C */ /* Carry Register One Register */ - MAC_STAT_REG_1_t Carry1; /* 0x6130 */ + u32 Carry1; /* 0x6130 */ /* Carry Register Two Register */ - MAC_STAT_REG_2_t Carry2; /* 0x6134 */ + u32 Carry2; /* 0x6134 */ /* Carry Register One Mask Register */ - MAC_STAT_REG_1_t Carry1M; /* 0x6138 */ + u32 Carry1M; /* 0x6138 */ /* Carry Register Two Mask Register */ - MAC_STAT_REG_2_t Carry2M; /* 0x613C */ + u32 Carry2M; /* 0x613C */ } MAC_STAT_t, *PMAC_STAT_t; /* END OF MAC STAT REGISTER ADDRESS MAP */ diff --git a/drivers/staging/et131x/et1310_eeprom.c b/drivers/staging/et131x/et1310_eeprom.c index c853a2c243a87ea5b3723f73d3558fe633a0d702..bcca1f86f51629936f6b180256f1949b32dcf097 100644 --- a/drivers/staging/et131x/et1310_eeprom.c +++ b/drivers/staging/et131x/et1310_eeprom.c @@ -95,198 +95,120 @@ #include "et1310_tx.h" -/* - * EEPROM Defines - */ -/* LBCIF Register Groups (addressed via 32-bit offsets) */ -#define LBCIF_DWORD0_GROUP_OFFSET 0xAC -#define LBCIF_DWORD1_GROUP_OFFSET 0xB0 - -/* LBCIF Registers (addressed via 8-bit offsets) */ -#define LBCIF_ADDRESS_REGISTER_OFFSET 0xAC -#define LBCIF_DATA_REGISTER_OFFSET 0xB0 -#define LBCIF_CONTROL_REGISTER_OFFSET 0xB1 -#define LBCIF_STATUS_REGISTER_OFFSET 0xB2 - -/* LBCIF Control Register Bits */ -#define LBCIF_CONTROL_SEQUENTIAL_READ 0x01 -#define LBCIF_CONTROL_PAGE_WRITE 0x02 -#define LBCIF_CONTROL_UNUSED1 0x04 -#define LBCIF_CONTROL_EEPROM_RELOAD 0x08 -#define LBCIF_CONTROL_UNUSED2 0x10 -#define LBCIF_CONTROL_TWO_BYTE_ADDR 0x20 -#define LBCIF_CONTROL_I2C_WRITE 0x40 -#define LBCIF_CONTROL_LBCIF_ENABLE 0x80 - -/* LBCIF Status Register Bits */ -#define LBCIF_STATUS_PHY_QUEUE_AVAIL 0x01 -#define LBCIF_STATUS_I2C_IDLE 0x02 -#define LBCIF_STATUS_ACK_ERROR 0x04 -#define LBCIF_STATUS_GENERAL_ERROR 0x08 -#define LBCIF_STATUS_UNUSED 0x30 -#define LBCIF_STATUS_CHECKSUM_ERROR 0x40 -#define LBCIF_STATUS_EEPROM_PRESENT 0x80 - -/* Miscellaneous Constraints */ -#define MAX_NUM_REGISTER_POLLS 1000 -#define MAX_NUM_WRITE_RETRIES 2 +static int eeprom_wait_ready(struct pci_dev *pdev, u32 *status) +{ + u32 reg; + int i; + + /* + * 1. Check LBCIF Status Register for bits 6 & 3:2 all equal to 0 and + * bits 7,1:0 both equal to 1, at least once after reset. + * Subsequent operations need only to check that bits 1:0 are equal + * to 1 prior to starting a single byte read/write + */ + + for (i = 0; i < MAX_NUM_REGISTER_POLLS; i++) { + /* Read registers grouped in DWORD1 */ + if (pci_read_config_dword(pdev, LBCIF_DWORD1_GROUP, ®)) + return -EIO; + + /* I2C idle and Phy Queue Avail both true */ + if ((reg & 0x3000) == 0x3000) { + if (status) + *status = reg; + return reg & 0xFF; + } + } + return -ETIMEDOUT; +} -/* - * Define macros that allow individual register values to be extracted from a - * DWORD1 register grouping - */ -#define EXTRACT_DATA_REGISTER(x) (u8)(x & 0xFF) -#define EXTRACT_STATUS_REGISTER(x) (u8)((x >> 16) & 0xFF) -#define EXTRACT_CONTROL_REG(x) (u8)((x >> 8) & 0xFF) /** - * EepromWriteByte - Write a byte to the ET1310's EEPROM + * eeprom_write - Write a byte to the ET1310's EEPROM * @etdev: pointer to our private adapter structure * @addr: the address to write * @data: the value to write * - * Returns SUCCESS or FAILURE + * Returns 1 for a successful write. */ -int EepromWriteByte(struct et131x_adapter *etdev, u32 addr, u8 data) +static int eeprom_write(struct et131x_adapter *etdev, u32 addr, u8 data) { struct pci_dev *pdev = etdev->pdev; - int index; + int index = 0; int retries; int err = 0; int i2c_wack = 0; int writeok = 0; - u8 control; - u8 status = 0; - u32 dword1 = 0; + u32 status; u32 val = 0; /* - * The following excerpt is from "Serial EEPROM HW Design - * Specification" Version 0.92 (9/20/2004): - * - * Single Byte Writes - * * For an EEPROM, an I2C single byte write is defined as a START * condition followed by the device address, EEPROM address, one byte * of data and a STOP condition. The STOP condition will trigger the * EEPROM's internally timed write cycle to the nonvolatile memory. * All inputs are disabled during this write cycle and the EEPROM will * not respond to any access until the internal write is complete. - * The steps to execute a single byte write are as follows: - * - * 1. Check LBCIF Status Register for bits 6 & 3:2 all equal to 0 and - * bits 7,1:0 both equal to 1, at least once after reset. - * Subsequent operations need only to check that bits 1:0 are - * equal to 1 prior to starting a single byte write. - * + */ + + err = eeprom_wait_ready(pdev, NULL); + if (err) + return err; + + /* * 2. Write to the LBCIF Control Register: bit 7=1, bit 6=1, bit 3=0, * and bits 1:0 both =0. Bit 5 should be set according to the * type of EEPROM being accessed (1=two byte addressing, 0=one * byte addressing). - * - * 3. Write the address to the LBCIF Address Register. - * - * 4. Write the data to the LBCIF Data Register (the I2C write will - * begin). - * - * 5. Monitor bit 1:0 of the LBCIF Status Register. When bits 1:0 are - * both equal to 1, the I2C write has completed and the internal - * write cycle of the EEPROM is about to start. (bits 1:0 = 01 is - * a legal state while waiting from both equal to 1, but bits - * 1:0 = 10 is invalid and implies that something is broken). - * - * 6. Check bit 3 of the LBCIF Status Register. If equal to 1, an - * error has occurred. - * - * 7. Check bit 2 of the LBCIF Status Register. If equal to 1 an ACK - * error has occurred on the address phase of the write. This - * could be due to an actual hardware failure or the EEPROM may - * still be in its internal write cycle from a previous write. - * This write operation was ignored and must be repeated later. - * - * 8. Set bit 6 of the LBCIF Control Register = 0. If another write is - * required, go to step 1. */ - - /* Step 1: */ - for (index = 0; index < MAX_NUM_REGISTER_POLLS; index++) { - /* Read registers grouped in DWORD1 */ - if (pci_read_config_dword(pdev, LBCIF_DWORD1_GROUP_OFFSET, - &dword1)) { - err = 1; - break; - } - - status = EXTRACT_STATUS_REGISTER(dword1); - - if (status & LBCIF_STATUS_PHY_QUEUE_AVAIL && - status & LBCIF_STATUS_I2C_IDLE) - /* bits 1:0 are equal to 1 */ - break; - } - - if (err || (index >= MAX_NUM_REGISTER_POLLS)) - return FAILURE; - - /* Step 2: */ - control = 0; - control |= LBCIF_CONTROL_LBCIF_ENABLE | LBCIF_CONTROL_I2C_WRITE; - - if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER_OFFSET, - control)) { - return FAILURE; - } + if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER, + LBCIF_CONTROL_LBCIF_ENABLE | LBCIF_CONTROL_I2C_WRITE)) + return -EIO; i2c_wack = 1; /* Prepare EEPROM address for Step 3 */ for (retries = 0; retries < MAX_NUM_WRITE_RETRIES; retries++) { - /* Step 3:*/ - if (pci_write_config_dword(pdev, LBCIF_ADDRESS_REGISTER_OFFSET, - addr)) { - break; - } - - /* Step 4: */ - if (pci_write_config_byte(pdev, LBCIF_DATA_REGISTER_OFFSET, - data)) { + /* Write the address to the LBCIF Address Register */ + if (pci_write_config_dword(pdev, LBCIF_ADDRESS_REGISTER, addr)) break; - } - - /* Step 5: */ - for (index = 0; index < MAX_NUM_REGISTER_POLLS; index++) { - /* Read registers grouped in DWORD1 */ - if (pci_read_config_dword(pdev, - LBCIF_DWORD1_GROUP_OFFSET, - &dword1)) { - err = 1; - break; - } - - status = EXTRACT_STATUS_REGISTER(dword1); - - if (status & LBCIF_STATUS_PHY_QUEUE_AVAIL && - status & LBCIF_STATUS_I2C_IDLE) { - /* I2C write complete */ - break; - } - } - - if (err || (index >= MAX_NUM_REGISTER_POLLS)) + /* + * Write the data to the LBCIF Data Register (the I2C write + * will begin). + */ + if (pci_write_config_byte(pdev, LBCIF_DATA_REGISTER, data)) break; + /* + * Monitor bit 1:0 of the LBCIF Status Register. When bits + * 1:0 are both equal to 1, the I2C write has completed and the + * internal write cycle of the EEPROM is about to start. + * (bits 1:0 = 01 is a legal state while waiting from both + * equal to 1, but bits 1:0 = 10 is invalid and implies that + * something is broken). + */ + err = eeprom_wait_ready(pdev, &status); + if (err < 0) + return 0; /* - * Step 6: Don't break here if we are revision 1, this is - * so we do a blind write for load bug. + * Check bit 3 of the LBCIF Status Register. If equal to 1, + * an error has occurred.Don't break here if we are revision + * 1, this is so we do a blind write for load bug. */ - if (status & LBCIF_STATUS_GENERAL_ERROR - && etdev->pdev->revision == 0) { + if ((status & LBCIF_STATUS_GENERAL_ERROR) + && etdev->pdev->revision == 0) break; - } - /* Step 7 */ + /* + * Check bit 2 of the LBCIF Status Register. If equal to 1 an + * ACK error has occurred on the address phase of the write. + * This could be due to an actual hardware failure or the + * EEPROM may still be in its internal write cycle from a + * previous write. This write operation was ignored and must be + *repeated later. + */ if (status & LBCIF_STATUS_ACK_ERROR) { /* * This could be due to an actual hardware failure @@ -302,154 +224,160 @@ int EepromWriteByte(struct et131x_adapter *etdev, u32 addr, u8 data) break; } - /* Step 8: */ + /* + * Set bit 6 of the LBCIF Control Register = 0. + */ udelay(10); - index = 0; - while (i2c_wack) { - control &= ~LBCIF_CONTROL_I2C_WRITE; - if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER_OFFSET, - control)) { + while (i2c_wack) { + if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER, + LBCIF_CONTROL_LBCIF_ENABLE)) writeok = 0; - } /* Do read until internal ACK_ERROR goes away meaning write * completed */ do { pci_write_config_dword(pdev, - LBCIF_ADDRESS_REGISTER_OFFSET, + LBCIF_ADDRESS_REGISTER, addr); do { pci_read_config_dword(pdev, - LBCIF_DATA_REGISTER_OFFSET, &val); + LBCIF_DATA_REGISTER, &val); } while ((val & 0x00010000) == 0); } while (val & 0x00040000); - control = EXTRACT_CONTROL_REG(val); - - if (control != 0xC0 || index == 10000) + if ((val & 0xFF00) != 0xC000 || index == 10000) break; - index++; } - - return writeok ? SUCCESS : FAILURE; + return writeok ? 0 : -EIO; } /** - * EepromReadByte - Read a byte from the ET1310's EEPROM + * eeprom_read - Read a byte from the ET1310's EEPROM * @etdev: pointer to our private adapter structure * @addr: the address from which to read * @pdata: a pointer to a byte in which to store the value of the read * @eeprom_id: the ID of the EEPROM * @addrmode: how the EEPROM is to be accessed * - * Returns SUCCESS or FAILURE + * Returns 1 for a successful read */ -int EepromReadByte(struct et131x_adapter *etdev, u32 addr, u8 *pdata) +static int eeprom_read(struct et131x_adapter *etdev, u32 addr, u8 *pdata) { struct pci_dev *pdev = etdev->pdev; - int index; - int err = 0; - u8 control; - u8 status = 0; - u32 dword1 = 0; + int err; + u32 status; /* - * The following excerpt is from "Serial EEPROM HW Design - * Specification" Version 0.92 (9/20/2004): - * - * Single Byte Reads - * * A single byte read is similar to the single byte write, with the * exception of the data flow: - * - * 1. Check LBCIF Status Register for bits 6 & 3:2 all equal to 0 and - * bits 7,1:0 both equal to 1, at least once after reset. - * Subsequent operations need only to check that bits 1:0 are equal - * to 1 prior to starting a single byte read. - * - * 2. Write to the LBCIF Control Register: bit 7=1, bit 6=0, bit 3=0, - * and bits 1:0 both =0. Bit 5 should be set according to the type - * of EEPROM being accessed (1=two byte addressing, 0=one byte - * addressing). - * - * 3. Write the address to the LBCIF Address Register (I2C read will - * begin). - * - * 4. Monitor bit 0 of the LBCIF Status Register. When =1, I2C read - * is complete. (if bit 1 =1 and bit 0 stays =0, a hardware failure - * has occurred). - * - * 5. Check bit 2 of the LBCIF Status Register. If =1, then an error - * has occurred. The data that has been returned from the PHY may - * be invalid. - * - * 6. Regardless of error status, read data byte from LBCIF Data - * Register. If another byte is required, go to step 1. */ - /* Step 1: */ - for (index = 0; index < MAX_NUM_REGISTER_POLLS; index++) { - /* Read registers grouped in DWORD1 */ - if (pci_read_config_dword(pdev, LBCIF_DWORD1_GROUP_OFFSET, - &dword1)) { - err = 1; - break; - } - - status = EXTRACT_STATUS_REGISTER(dword1); - - if (status & LBCIF_STATUS_PHY_QUEUE_AVAIL && - status & LBCIF_STATUS_I2C_IDLE) { - /* bits 1:0 are equal to 1 */ - break; - } - } - - if (err || (index >= MAX_NUM_REGISTER_POLLS)) - return FAILURE; - - /* Step 2: */ - control = 0; - control |= LBCIF_CONTROL_LBCIF_ENABLE; - - if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER_OFFSET, - control)) { - return FAILURE; - } + err = eeprom_wait_ready(pdev, NULL); + if (err) + return err; + /* + * Write to the LBCIF Control Register: bit 7=1, bit 6=0, bit 3=0, + * and bits 1:0 both =0. Bit 5 should be set according to the type + * of EEPROM being accessed (1=two byte addressing, 0=one byte + * addressing). + */ + if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER, + LBCIF_CONTROL_LBCIF_ENABLE)) + return -EIO; + /* + * Write the address to the LBCIF Address Register (I2C read will + * begin). + */ + if (pci_write_config_dword(pdev, LBCIF_ADDRESS_REGISTER, addr)) + return -EIO; + /* + * Monitor bit 0 of the LBCIF Status Register. When = 1, I2C read + * is complete. (if bit 1 =1 and bit 0 stays = 0, a hardware failure + * has occurred). + */ + err = eeprom_wait_ready(pdev, &status); + if (err < 0) + return err; + /* + * Regardless of error status, read data byte from LBCIF Data + * Register. + */ + *pdata = err; + /* + * Check bit 2 of the LBCIF Status Register. If = 1, + * then an error has occurred. + */ + return (status & LBCIF_STATUS_ACK_ERROR) ? -EIO : 0; +} - /* Step 3: */ +int et131x_init_eeprom(struct et131x_adapter *etdev) +{ + struct pci_dev *pdev = etdev->pdev; + u8 eestatus; - if (pci_write_config_dword(pdev, LBCIF_ADDRESS_REGISTER_OFFSET, - addr)) { - return FAILURE; + /* We first need to check the EEPROM Status code located at offset + * 0xB2 of config space + */ + pci_read_config_byte(pdev, ET1310_PCI_EEPROM_STATUS, + &eestatus); + + /* THIS IS A WORKAROUND: + * I need to call this function twice to get my card in a + * LG M1 Express Dual running. I tried also a msleep before this + * function, because I thougth there could be some time condidions + * but it didn't work. Call the whole function twice also work. + */ + if (pci_read_config_byte(pdev, ET1310_PCI_EEPROM_STATUS, &eestatus)) { + dev_err(&pdev->dev, + "Could not read PCI config space for EEPROM Status\n"); + return -EIO; } - /* Step 4: */ - for (index = 0; index < MAX_NUM_REGISTER_POLLS; index++) { - /* Read registers grouped in DWORD1 */ - if (pci_read_config_dword(pdev, LBCIF_DWORD1_GROUP_OFFSET, - &dword1)) { - err = 1; - break; + /* Determine if the error(s) we care about are present. If they are + * present we need to fail. + */ + if (eestatus & 0x4C) { + int write_failed = 0; + if (pdev->revision == 0x01) { + int i; + static const u8 eedata[4] = { 0xFE, 0x13, 0x10, 0xFF }; + + /* Re-write the first 4 bytes if we have an eeprom + * present and the revision id is 1, this fixes the + * corruption seen with 1310 B Silicon + */ + for (i = 0; i < 3; i++) + if (eeprom_write(etdev, i, eedata[i]) < 0) + write_failed = 1; } - - status = EXTRACT_STATUS_REGISTER(dword1); - - if (status & LBCIF_STATUS_PHY_QUEUE_AVAIL - && status & LBCIF_STATUS_I2C_IDLE) { - /* I2C read complete */ - break; + if (pdev->revision != 0x01 || write_failed) { + dev_err(&pdev->dev, + "Fatal EEPROM Status Error - 0x%04x\n", eestatus); + + /* This error could mean that there was an error + * reading the eeprom or that the eeprom doesn't exist. + * We will treat each case the same and not try to gather + * additional information that normally would come from the + * eeprom, like MAC Address + */ + etdev->has_eeprom = 0; + return -EIO; } } + etdev->has_eeprom = 1; - if (err || (index >= MAX_NUM_REGISTER_POLLS)) - return FAILURE; + /* Read the EEPROM for information regarding LED behavior. Refer to + * ET1310_phy.c, et131x_xcvr_init(), for its use. + */ + eeprom_read(etdev, 0x70, &etdev->eepromData[0]); + eeprom_read(etdev, 0x71, &etdev->eepromData[1]); - /* Step 6: */ - *pdata = EXTRACT_DATA_REGISTER(dword1); + if (etdev->eepromData[0] != 0xcd) + /* Disable all optional features */ + etdev->eepromData[1] = 0x00; - return (status & LBCIF_STATUS_ACK_ERROR) ? FAILURE : SUCCESS; + return 0; } diff --git a/drivers/staging/et131x/et1310_eeprom.h b/drivers/staging/et131x/et1310_eeprom.h index d8ac9a0439e2ae7038d03e0cdd47ca395fba75e8..6a6c6a632a8f3d089642a4f184f099a27a65e29f 100644 --- a/drivers/staging/et131x/et1310_eeprom.h +++ b/drivers/staging/et131x/et1310_eeprom.h @@ -61,17 +61,43 @@ #include "et1310_address_map.h" -#ifndef SUCCESS -#define SUCCESS 0 -#define FAILURE 1 -#endif +/* + * EEPROM Defines + */ + +/* LBCIF Register Groups (addressed via 32-bit offsets) */ +#define LBCIF_DWORD0_GROUP 0xAC +#define LBCIF_DWORD1_GROUP 0xB0 + +/* LBCIF Registers (addressed via 8-bit offsets) */ +#define LBCIF_ADDRESS_REGISTER 0xAC +#define LBCIF_DATA_REGISTER 0xB0 +#define LBCIF_CONTROL_REGISTER 0xB1 +#define LBCIF_STATUS_REGISTER 0xB2 + +/* LBCIF Control Register Bits */ +#define LBCIF_CONTROL_SEQUENTIAL_READ 0x01 +#define LBCIF_CONTROL_PAGE_WRITE 0x02 +#define LBCIF_CONTROL_EEPROM_RELOAD 0x08 +#define LBCIF_CONTROL_TWO_BYTE_ADDR 0x20 +#define LBCIF_CONTROL_I2C_WRITE 0x40 +#define LBCIF_CONTROL_LBCIF_ENABLE 0x80 + +/* LBCIF Status Register Bits */ +#define LBCIF_STATUS_PHY_QUEUE_AVAIL 0x01 +#define LBCIF_STATUS_I2C_IDLE 0x02 +#define LBCIF_STATUS_ACK_ERROR 0x04 +#define LBCIF_STATUS_GENERAL_ERROR 0x08 +#define LBCIF_STATUS_CHECKSUM_ERROR 0x40 +#define LBCIF_STATUS_EEPROM_PRESENT 0x80 + +/* Miscellaneous Constraints */ +#define MAX_NUM_REGISTER_POLLS 1000 +#define MAX_NUM_WRITE_RETRIES 2 /* Forward declaration of the private adapter structure */ struct et131x_adapter; -int32_t EepromWriteByte(struct et131x_adapter *adapter, u32 unAddress, - u8 bData); -int32_t EepromReadByte(struct et131x_adapter *adapter, u32 unAddress, - u8 *pbData); +int et131x_init_eeprom(struct et131x_adapter *etdev); #endif /* _ET1310_EEPROM_H_ */ diff --git a/drivers/staging/et131x/et1310_mac.c b/drivers/staging/et131x/et1310_mac.c index f81e1cba8547e4a7abe590f5981af4eaecb1341f..b8a1f2037314241c005245023e17125634d21187 100644 --- a/drivers/staging/et131x/et1310_mac.c +++ b/drivers/staging/et131x/et1310_mac.c @@ -101,41 +101,27 @@ void ConfigMACRegs1(struct et131x_adapter *etdev) struct _MAC_t __iomem *pMac = &etdev->regs->mac; MAC_STATION_ADDR1_t station1; MAC_STATION_ADDR2_t station2; - MAC_IPG_t ipg; - MAC_HFDP_t hfdp; - MII_MGMT_CFG_t mii_mgmt_cfg; + u32 ipg; /* First we need to reset everything. Write to MAC configuration * register 1 to perform reset. */ - writel(0xC00F0000, &pMac->cfg1.value); + writel(0xC00F0000, &pMac->cfg1); /* Next lets configure the MAC Inter-packet gap register */ - ipg.bits.non_B2B_ipg_1 = 0x38; /* 58d */ - ipg.bits.non_B2B_ipg_2 = 0x58; /* 88d */ - ipg.bits.min_ifg_enforce = 0x50; /* 80d */ - ipg.bits.B2B_ipg = 0x60; /* 96d */ - writel(ipg.value, &pMac->ipg.value); + ipg = 0x38005860; /* IPG1 0x38 IPG2 0x58 B2B 0x60 */ + ipg |= 0x50 << 8; /* ifg enforce 0x50 */ + writel(ipg, &pMac->ipg); /* Next lets configure the MAC Half Duplex register */ - hfdp.bits.alt_beb_trunc = 0xA; - hfdp.bits.alt_beb_enable = 0x0; - hfdp.bits.bp_no_backoff = 0x0; - hfdp.bits.no_backoff = 0x0; - hfdp.bits.excess_defer = 0x1; - hfdp.bits.rexmit_max = 0xF; - hfdp.bits.coll_window = 0x37; /* 55d */ - writel(hfdp.value, &pMac->hfdp.value); + /* BEB trunc 0xA, Ex Defer, Rexmit 0xF Coll 0x37 */ + writel(0x00A1F037, &pMac->hfdp); /* Next lets configure the MAC Interface Control register */ - writel(0, &pMac->if_ctrl.value); + writel(0, &pMac->if_ctrl); /* Let's move on to setting up the mii management configuration */ - mii_mgmt_cfg.bits.reset_mii_mgmt = 0; - mii_mgmt_cfg.bits.scan_auto_incremt = 0; - mii_mgmt_cfg.bits.preamble_suppress = 0; - mii_mgmt_cfg.bits.mgmt_clk_reset = 0x7; - writel(mii_mgmt_cfg.value, &pMac->mii_mgmt_cfg.value); + writel(0x07, &pMac->mii_mgmt_cfg); /* Clock reset 0x7 */ /* Next lets configure the MAC Station Address register. These * values are read from the EEPROM during initialization and stored @@ -160,10 +146,10 @@ void ConfigMACRegs1(struct et131x_adapter *etdev) * Packets larger than (RegistryJumboPacket) that do not contain a * VLAN ID will be dropped by the Rx function. */ - writel(etdev->RegistryJumboPacket + 4, &pMac->max_fm_len.value); + writel(etdev->RegistryJumboPacket + 4, &pMac->max_fm_len); /* clear out MAC config reset */ - writel(0, &pMac->cfg1.value); + writel(0, &pMac->cfg1); } /** @@ -174,79 +160,62 @@ void ConfigMACRegs2(struct et131x_adapter *etdev) { int32_t delay = 0; struct _MAC_t __iomem *pMac = &etdev->regs->mac; - MAC_CFG1_t cfg1; - MAC_CFG2_t cfg2; - MAC_IF_CTRL_t ifctrl; + u32 cfg1; + u32 cfg2; + u32 ifctrl; TXMAC_CTL_t ctl; ctl.value = readl(&etdev->regs->txmac.ctl.value); - cfg1.value = readl(&pMac->cfg1.value); - cfg2.value = readl(&pMac->cfg2.value); - ifctrl.value = readl(&pMac->if_ctrl.value); + cfg1 = readl(&pMac->cfg1); + cfg2 = readl(&pMac->cfg2); + ifctrl = readl(&pMac->if_ctrl); + /* Set up the if mode bits */ + cfg2 &= ~0x300; if (etdev->linkspeed == TRUEPHY_SPEED_1000MBPS) { - cfg2.bits.if_mode = 0x2; - ifctrl.bits.phy_mode = 0x0; + cfg2 |= 0x200; + /* Phy mode bit */ + ifctrl &= ~(1 << 24); } else { - cfg2.bits.if_mode = 0x1; - ifctrl.bits.phy_mode = 0x1; + cfg2 |= 0x100; + ifctrl |= (1 << 24); } /* We need to enable Rx/Tx */ - cfg1.bits.rx_enable = 0x1; - cfg1.bits.tx_enable = 0x1; - - /* Set up flow control */ - cfg1.bits.tx_flow = 0x1; - - if ((etdev->FlowControl == RxOnly) || - (etdev->FlowControl == Both)) { - cfg1.bits.rx_flow = 0x1; - } else { - cfg1.bits.rx_flow = 0x0; - } - + cfg1 |= CFG1_RX_ENABLE|CFG1_TX_ENABLE|CFG1_TX_FLOW; /* Initialize loop back to off */ - cfg1.bits.loop_back = 0; - - writel(cfg1.value, &pMac->cfg1.value); + cfg1 &= ~(CFG1_LOOPBACK|CFG1_RX_FLOW); + if (etdev->FlowControl == RxOnly || etdev->FlowControl == Both) + cfg1 |= CFG1_RX_FLOW; + writel(cfg1, &pMac->cfg1); /* Now we need to initialize the MAC Configuration 2 register */ - cfg2.bits.preamble_len = 0x7; - cfg2.bits.huge_frame = 0x0; - /* LENGTH FIELD CHECKING bit4: Set this bit to cause the MAC to check - * the frame's length field to ensure it matches the actual data - * field length. Clear this bit if no length field checking is - * desired. Its default is 0. - */ - cfg2.bits.len_check = 0x1; + /* preamble 7, check length, huge frame off, pad crc, crc enable + full duplex off */ + cfg2 |= 0x7016; + cfg2 &= ~0x0021; - if (etdev->RegistryPhyLoopbk == false) { - cfg2.bits.pad_crc = 0x1; - cfg2.bits.crc_enable = 0x1; - } else { - cfg2.bits.pad_crc = 0; - cfg2.bits.crc_enable = 0; - } + /* Turn on duplex if needed */ + if (etdev->duplex_mode) + cfg2 |= 0x01; - /* 1 - full duplex, 0 - half-duplex */ - cfg2.bits.full_duplex = etdev->duplex_mode; - ifctrl.bits.ghd_mode = !etdev->duplex_mode; + ifctrl &= ~(1 << 26); + if (!etdev->duplex_mode) + ifctrl |= (1<<26); /* Enable ghd */ - writel(ifctrl.value, &pMac->if_ctrl.value); - writel(cfg2.value, &pMac->cfg2.value); + writel(ifctrl, &pMac->if_ctrl); + writel(cfg2, &pMac->cfg2); do { udelay(10); delay++; - cfg1.value = readl(&pMac->cfg1.value); - } while ((!cfg1.bits.syncd_rx_en || !cfg1.bits.syncd_tx_en) && - delay < 100); + cfg1 = readl(&pMac->cfg1); + } while ((cfg1 & CFG1_WAIT) != CFG1_WAIT && delay < 100); if (delay == 100) { dev_warn(&etdev->pdev->dev, "Syncd bits did not respond correctly cfg1 word 0x%08x\n", - cfg1.value); + cfg1); } /* Enable TXMAC */ @@ -402,106 +371,47 @@ void ConfigRxMacRegs(struct et131x_adapter *etdev) void ConfigTxMacRegs(struct et131x_adapter *etdev) { struct _TXMAC_t __iomem *pTxMac = &etdev->regs->txmac; - TXMAC_CF_PARAM_t Local; /* We need to update the Control Frame Parameters * cfpt - control frame pause timer set to 64 (0x40) * cfep - control frame extended pause timer set to 0x0 */ - if (etdev->FlowControl == None) { - writel(0, &pTxMac->cf_param.value); - } else { - Local.bits.cfpt = 0x40; - Local.bits.cfep = 0x0; - writel(Local.value, &pTxMac->cf_param.value); - } + if (etdev->FlowControl == None) + writel(0, &pTxMac->cf_param); + else + writel(0x40, &pTxMac->cf_param); } void ConfigMacStatRegs(struct et131x_adapter *etdev) { - struct _MAC_STAT_t __iomem *pDevMacStat = + struct _MAC_STAT_t __iomem *macstat = &etdev->regs->macStat; /* Next we need to initialize all the MAC_STAT registers to zero on * the device. */ - writel(0, &pDevMacStat->RFcs); - writel(0, &pDevMacStat->RAln); - writel(0, &pDevMacStat->RFlr); - writel(0, &pDevMacStat->RDrp); - writel(0, &pDevMacStat->RCde); - writel(0, &pDevMacStat->ROvr); - writel(0, &pDevMacStat->RFrg); - - writel(0, &pDevMacStat->TScl); - writel(0, &pDevMacStat->TDfr); - writel(0, &pDevMacStat->TMcl); - writel(0, &pDevMacStat->TLcl); - writel(0, &pDevMacStat->TNcl); - writel(0, &pDevMacStat->TOvr); - writel(0, &pDevMacStat->TUnd); + writel(0, &macstat->RFcs); + writel(0, &macstat->RAln); + writel(0, &macstat->RFlr); + writel(0, &macstat->RDrp); + writel(0, &macstat->RCde); + writel(0, &macstat->ROvr); + writel(0, &macstat->RFrg); + + writel(0, &macstat->TScl); + writel(0, &macstat->TDfr); + writel(0, &macstat->TMcl); + writel(0, &macstat->TLcl); + writel(0, &macstat->TNcl); + writel(0, &macstat->TOvr); + writel(0, &macstat->TUnd); /* Unmask any counters that we want to track the overflow of. * Initially this will be all counters. It may become clear later * that we do not need to track all counters. */ - { - MAC_STAT_REG_1_t Carry1M = { 0xffffffff }; - - Carry1M.bits.rdrp = 0; - Carry1M.bits.rjbr = 1; - Carry1M.bits.rfrg = 0; - Carry1M.bits.rovr = 0; - Carry1M.bits.rund = 1; - Carry1M.bits.rcse = 1; - Carry1M.bits.rcde = 0; - Carry1M.bits.rflr = 0; - Carry1M.bits.raln = 0; - Carry1M.bits.rxuo = 1; - Carry1M.bits.rxpf = 1; - Carry1M.bits.rxcf = 1; - Carry1M.bits.rbca = 1; - Carry1M.bits.rmca = 1; - Carry1M.bits.rfcs = 0; - Carry1M.bits.rpkt = 1; - Carry1M.bits.rbyt = 1; - Carry1M.bits.trmgv = 1; - Carry1M.bits.trmax = 1; - Carry1M.bits.tr1k = 1; - Carry1M.bits.tr511 = 1; - Carry1M.bits.tr255 = 1; - Carry1M.bits.tr127 = 1; - Carry1M.bits.tr64 = 1; - - writel(Carry1M.value, &pDevMacStat->Carry1M.value); - } - - { - MAC_STAT_REG_2_t Carry2M = { 0xffffffff }; - - Carry2M.bits.tdrp = 1; - Carry2M.bits.tpfh = 1; - Carry2M.bits.tncl = 0; - Carry2M.bits.txcl = 1; - Carry2M.bits.tlcl = 0; - Carry2M.bits.tmcl = 0; - Carry2M.bits.tscl = 0; - Carry2M.bits.tedf = 1; - Carry2M.bits.tdfr = 0; - Carry2M.bits.txpf = 1; - Carry2M.bits.tbca = 1; - Carry2M.bits.tmca = 1; - Carry2M.bits.tpkt = 1; - Carry2M.bits.tbyt = 1; - Carry2M.bits.tfrg = 1; - Carry2M.bits.tund = 0; - Carry2M.bits.tovr = 0; - Carry2M.bits.txcf = 1; - Carry2M.bits.tfcs = 1; - Carry2M.bits.tjbr = 1; - - writel(Carry2M.value, &pDevMacStat->Carry2M.value); - } + writel(0xFFFFBE32, &macstat->Carry1M); + writel(0xFFFE7E8B, &macstat->Carry2M); } void ConfigFlowControl(struct et131x_adapter *etdev) @@ -509,28 +419,28 @@ void ConfigFlowControl(struct et131x_adapter *etdev) if (etdev->duplex_mode == 0) { etdev->FlowControl = None; } else { - char RemotePause, RemoteAsyncPause; + char remote_pause, remote_async_pause; ET1310_PhyAccessMiBit(etdev, - TRUEPHY_BIT_READ, 5, 10, &RemotePause); + TRUEPHY_BIT_READ, 5, 10, &remote_pause); ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_READ, 5, 11, - &RemoteAsyncPause); + &remote_async_pause); - if ((RemotePause == TRUEPHY_BIT_SET) && - (RemoteAsyncPause == TRUEPHY_BIT_SET)) { + if ((remote_pause == TRUEPHY_BIT_SET) && + (remote_async_pause == TRUEPHY_BIT_SET)) { etdev->FlowControl = etdev->RegistryFlowControl; - } else if ((RemotePause == TRUEPHY_BIT_SET) && - (RemoteAsyncPause == TRUEPHY_BIT_CLEAR)) { + } else if ((remote_pause == TRUEPHY_BIT_SET) && + (remote_async_pause == TRUEPHY_BIT_CLEAR)) { if (etdev->RegistryFlowControl == Both) etdev->FlowControl = Both; else etdev->FlowControl = None; - } else if ((RemotePause == TRUEPHY_BIT_CLEAR) && - (RemoteAsyncPause == TRUEPHY_BIT_CLEAR)) { + } else if ((remote_pause == TRUEPHY_BIT_CLEAR) && + (remote_async_pause == TRUEPHY_BIT_CLEAR)) { etdev->FlowControl = None; - } else {/* if (RemotePause == TRUEPHY_CLEAR_BIT && - RemoteAsyncPause == TRUEPHY_SET_BIT) */ + } else {/* if (remote_pause == TRUEPHY_CLEAR_BIT && + remote_async_pause == TRUEPHY_SET_BIT) */ if (etdev->RegistryFlowControl == Both) etdev->FlowControl = RxOnly; else @@ -546,25 +456,25 @@ void ConfigFlowControl(struct et131x_adapter *etdev) void UpdateMacStatHostCounters(struct et131x_adapter *etdev) { struct _ce_stats_t *stats = &etdev->Stats; - struct _MAC_STAT_t __iomem *pDevMacStat = + struct _MAC_STAT_t __iomem *macstat = &etdev->regs->macStat; - stats->collisions += readl(&pDevMacStat->TNcl); - stats->first_collision += readl(&pDevMacStat->TScl); - stats->tx_deferred += readl(&pDevMacStat->TDfr); - stats->excessive_collisions += readl(&pDevMacStat->TMcl); - stats->late_collisions += readl(&pDevMacStat->TLcl); - stats->tx_uflo += readl(&pDevMacStat->TUnd); - stats->max_pkt_error += readl(&pDevMacStat->TOvr); - - stats->alignment_err += readl(&pDevMacStat->RAln); - stats->crc_err += readl(&pDevMacStat->RCde); - stats->norcvbuf += readl(&pDevMacStat->RDrp); - stats->rx_ov_flow += readl(&pDevMacStat->ROvr); - stats->code_violations += readl(&pDevMacStat->RFcs); - stats->length_err += readl(&pDevMacStat->RFlr); - - stats->other_errors += readl(&pDevMacStat->RFrg); + stats->collisions += readl(&macstat->TNcl); + stats->first_collision += readl(&macstat->TScl); + stats->tx_deferred += readl(&macstat->TDfr); + stats->excessive_collisions += readl(&macstat->TMcl); + stats->late_collisions += readl(&macstat->TLcl); + stats->tx_uflo += readl(&macstat->TUnd); + stats->max_pkt_error += readl(&macstat->TOvr); + + stats->alignment_err += readl(&macstat->RAln); + stats->crc_err += readl(&macstat->RCde); + stats->norcvbuf += readl(&macstat->RDrp); + stats->rx_ov_flow += readl(&macstat->ROvr); + stats->code_violations += readl(&macstat->RFcs); + stats->length_err += readl(&macstat->RFlr); + + stats->other_errors += readl(&macstat->RFrg); } /** @@ -577,17 +487,17 @@ void UpdateMacStatHostCounters(struct et131x_adapter *etdev) */ void HandleMacStatInterrupt(struct et131x_adapter *etdev) { - MAC_STAT_REG_1_t Carry1; - MAC_STAT_REG_2_t Carry2; + u32 Carry1; + u32 Carry2; /* Read the interrupt bits from the register(s). These are Clear On * Write. */ - Carry1.value = readl(&etdev->regs->macStat.Carry1.value); - Carry2.value = readl(&etdev->regs->macStat.Carry2.value); + Carry1 = readl(&etdev->regs->macStat.Carry1); + Carry2 = readl(&etdev->regs->macStat.Carry2); - writel(Carry1.value, &etdev->regs->macStat.Carry1.value); - writel(Carry2.value, &etdev->regs->macStat.Carry2.value); + writel(Carry1, &etdev->regs->macStat.Carry1); + writel(Carry2, &etdev->regs->macStat.Carry2); /* We need to do update the host copy of all the MAC_STAT counters. * For each counter, check it's overflow bit. If the overflow bit is @@ -595,33 +505,33 @@ void HandleMacStatInterrupt(struct et131x_adapter *etdev) * revolution of the counter. This routine is called when the counter * block indicates that one of the counters has wrapped. */ - if (Carry1.bits.rfcs) + if (Carry1 & (1 << 14)) etdev->Stats.code_violations += COUNTER_WRAP_16_BIT; - if (Carry1.bits.raln) + if (Carry1 & (1 << 8)) etdev->Stats.alignment_err += COUNTER_WRAP_12_BIT; - if (Carry1.bits.rflr) + if (Carry1 & (1 << 7)) etdev->Stats.length_err += COUNTER_WRAP_16_BIT; - if (Carry1.bits.rfrg) + if (Carry1 & (1 << 2)) etdev->Stats.other_errors += COUNTER_WRAP_16_BIT; - if (Carry1.bits.rcde) + if (Carry1 & (1 << 6)) etdev->Stats.crc_err += COUNTER_WRAP_16_BIT; - if (Carry1.bits.rovr) + if (Carry1 & (1 << 3)) etdev->Stats.rx_ov_flow += COUNTER_WRAP_16_BIT; - if (Carry1.bits.rdrp) + if (Carry1 & (1 << 0)) etdev->Stats.norcvbuf += COUNTER_WRAP_16_BIT; - if (Carry2.bits.tovr) + if (Carry2 & (1 << 16)) etdev->Stats.max_pkt_error += COUNTER_WRAP_12_BIT; - if (Carry2.bits.tund) + if (Carry2 & (1 << 15)) etdev->Stats.tx_uflo += COUNTER_WRAP_12_BIT; - if (Carry2.bits.tscl) + if (Carry2 & (1 << 6)) etdev->Stats.first_collision += COUNTER_WRAP_12_BIT; - if (Carry2.bits.tdfr) + if (Carry2 & (1 << 8)) etdev->Stats.tx_deferred += COUNTER_WRAP_12_BIT; - if (Carry2.bits.tmcl) + if (Carry2 & (1 << 5)) etdev->Stats.excessive_collisions += COUNTER_WRAP_12_BIT; - if (Carry2.bits.tlcl) + if (Carry2 & (1 << 4)) etdev->Stats.late_collisions += COUNTER_WRAP_12_BIT; - if (Carry2.bits.tncl) + if (Carry2 & (1 << 2)) etdev->Stats.collisions += COUNTER_WRAP_12_BIT; } diff --git a/drivers/staging/et131x/et1310_phy.c b/drivers/staging/et131x/et1310_phy.c index dd199bdb9efffc73b0e2ff08f04d4aee883697a0..6ecad619f77925bcc5c02dd89f6defcd7fcae6a4 100644 --- a/drivers/staging/et131x/et1310_phy.c +++ b/drivers/staging/et131x/et1310_phy.c @@ -98,238 +98,498 @@ #include "et1310_mac.h" /* Prototypes for functions with local scope */ -static int et131x_xcvr_init(struct et131x_adapter *adapter); +static void et131x_xcvr_init(struct et131x_adapter *etdev); /** * PhyMiRead - Read from the PHY through the MII Interface on the MAC - * @adapter: pointer to our private adapter structure + * @etdev: pointer to our private adapter structure * @xcvrAddr: the address of the transciever * @xcvrReg: the register to read * @value: pointer to a 16-bit value in which the value will be stored * * Returns 0 on success, errno on failure (as defined in errno.h) */ -int PhyMiRead(struct et131x_adapter *adapter, uint8_t xcvrAddr, - uint8_t xcvrReg, uint16_t *value) +int PhyMiRead(struct et131x_adapter *etdev, u8 xcvrAddr, + u8 xcvrReg, u16 *value) { - struct _MAC_t __iomem *mac = &adapter->regs->mac; + struct _MAC_t __iomem *mac = &etdev->regs->mac; int status = 0; - uint32_t delay; - MII_MGMT_ADDR_t miiAddr; - MII_MGMT_CMD_t miiCmd; - MII_MGMT_INDICATOR_t miiIndicator; + u32 delay; + u32 miiAddr; + u32 miiCmd; + u32 miiIndicator; /* Save a local copy of the registers we are dealing with so we can * set them back */ - miiAddr.value = readl(&mac->mii_mgmt_addr.value); - miiCmd.value = readl(&mac->mii_mgmt_cmd.value); + miiAddr = readl(&mac->mii_mgmt_addr); + miiCmd = readl(&mac->mii_mgmt_cmd); /* Stop the current operation */ - writel(0, &mac->mii_mgmt_cmd.value); + writel(0, &mac->mii_mgmt_cmd); /* Set up the register we need to read from on the correct PHY */ - { - MII_MGMT_ADDR_t mii_mgmt_addr = { 0 }; - - mii_mgmt_addr.bits.phy_addr = xcvrAddr; - mii_mgmt_addr.bits.reg_addr = xcvrReg; - writel(mii_mgmt_addr.value, &mac->mii_mgmt_addr.value); - } + writel(MII_ADDR(xcvrAddr, xcvrReg), &mac->mii_mgmt_addr); /* Kick the read cycle off */ delay = 0; - writel(0x1, &mac->mii_mgmt_cmd.value); + writel(0x1, &mac->mii_mgmt_cmd); do { udelay(50); delay++; - miiIndicator.value = readl(&mac->mii_mgmt_indicator.value); - } while ((miiIndicator.bits.not_valid || miiIndicator.bits.busy) && - delay < 50); + miiIndicator = readl(&mac->mii_mgmt_indicator); + } while ((miiIndicator & MGMT_WAIT) && delay < 50); /* If we hit the max delay, we could not read the register */ - if (delay >= 50) { - dev_warn(&adapter->pdev->dev, + if (delay == 50) { + dev_warn(&etdev->pdev->dev, "xcvrReg 0x%08x could not be read\n", xcvrReg); - dev_warn(&adapter->pdev->dev, "status is 0x%08x\n", - miiIndicator.value); + dev_warn(&etdev->pdev->dev, "status is 0x%08x\n", + miiIndicator); status = -EIO; } /* If we hit here we were able to read the register and we need to - * return the value to the caller - */ - /* TODO: make this stuff a simple readw()?! */ - { - MII_MGMT_STAT_t mii_mgmt_stat; - - mii_mgmt_stat.value = readl(&mac->mii_mgmt_stat.value); - *value = (uint16_t) mii_mgmt_stat.bits.phy_stat; - } + * return the value to the caller */ + *value = readl(&mac->mii_mgmt_stat) & 0xFFFF; /* Stop the read operation */ - writel(0, &mac->mii_mgmt_cmd.value); + writel(0, &mac->mii_mgmt_cmd); /* set the registers we touched back to the state at which we entered * this function */ - writel(miiAddr.value, &mac->mii_mgmt_addr.value); - writel(miiCmd.value, &mac->mii_mgmt_cmd.value); + writel(miiAddr, &mac->mii_mgmt_addr); + writel(miiCmd, &mac->mii_mgmt_cmd); return status; } /** * MiWrite - Write to a PHY register through the MII interface of the MAC - * @adapter: pointer to our private adapter structure + * @etdev: pointer to our private adapter structure * @xcvrReg: the register to read * @value: 16-bit value to write * + * FIXME: one caller in netdev still + * * Return 0 on success, errno on failure (as defined in errno.h) */ -int MiWrite(struct et131x_adapter *adapter, uint8_t xcvrReg, uint16_t value) +int MiWrite(struct et131x_adapter *etdev, u8 xcvrReg, u16 value) { - struct _MAC_t __iomem *mac = &adapter->regs->mac; + struct _MAC_t __iomem *mac = &etdev->regs->mac; int status = 0; - uint8_t xcvrAddr = adapter->Stats.xcvr_addr; - uint32_t delay; - MII_MGMT_ADDR_t miiAddr; - MII_MGMT_CMD_t miiCmd; - MII_MGMT_INDICATOR_t miiIndicator; + u8 xcvrAddr = etdev->Stats.xcvr_addr; + u32 delay; + u32 miiAddr; + u32 miiCmd; + u32 miiIndicator; /* Save a local copy of the registers we are dealing with so we can * set them back */ - miiAddr.value = readl(&mac->mii_mgmt_addr.value); - miiCmd.value = readl(&mac->mii_mgmt_cmd.value); + miiAddr = readl(&mac->mii_mgmt_addr); + miiCmd = readl(&mac->mii_mgmt_cmd); /* Stop the current operation */ - writel(0, &mac->mii_mgmt_cmd.value); + writel(0, &mac->mii_mgmt_cmd); /* Set up the register we need to write to on the correct PHY */ - { - MII_MGMT_ADDR_t mii_mgmt_addr; - - mii_mgmt_addr.bits.phy_addr = xcvrAddr; - mii_mgmt_addr.bits.reg_addr = xcvrReg; - writel(mii_mgmt_addr.value, &mac->mii_mgmt_addr.value); - } + writel(MII_ADDR(xcvrAddr, xcvrReg), &mac->mii_mgmt_addr); /* Add the value to write to the registers to the mac */ - writel(value, &mac->mii_mgmt_ctrl.value); + writel(value, &mac->mii_mgmt_ctrl); delay = 0; do { udelay(50); delay++; - miiIndicator.value = readl(&mac->mii_mgmt_indicator.value); - } while (miiIndicator.bits.busy && delay < 100); + miiIndicator = readl(&mac->mii_mgmt_indicator); + } while ((miiIndicator & MGMT_BUSY) && delay < 100); /* If we hit the max delay, we could not write the register */ if (delay == 100) { - uint16_t TempValue; + u16 TempValue; - dev_warn(&adapter->pdev->dev, + dev_warn(&etdev->pdev->dev, "xcvrReg 0x%08x could not be written", xcvrReg); - dev_warn(&adapter->pdev->dev, "status is 0x%08x\n", - miiIndicator.value); - dev_warn(&adapter->pdev->dev, "command is 0x%08x\n", - readl(&mac->mii_mgmt_cmd.value)); + dev_warn(&etdev->pdev->dev, "status is 0x%08x\n", + miiIndicator); + dev_warn(&etdev->pdev->dev, "command is 0x%08x\n", + readl(&mac->mii_mgmt_cmd)); - MiRead(adapter, xcvrReg, &TempValue); + MiRead(etdev, xcvrReg, &TempValue); status = -EIO; } - /* Stop the write operation */ - writel(0, &mac->mii_mgmt_cmd.value); + writel(0, &mac->mii_mgmt_cmd); /* set the registers we touched back to the state at which we entered * this function */ - writel(miiAddr.value, &mac->mii_mgmt_addr.value); - writel(miiCmd.value, &mac->mii_mgmt_cmd.value); + writel(miiAddr, &mac->mii_mgmt_addr); + writel(miiCmd, &mac->mii_mgmt_cmd); return status; } /** * et131x_xcvr_find - Find the PHY ID - * @adapter: pointer to our private adapter structure + * @etdev: pointer to our private adapter structure * * Returns 0 on success, errno on failure (as defined in errno.h) */ -int et131x_xcvr_find(struct et131x_adapter *adapter) +int et131x_xcvr_find(struct et131x_adapter *etdev) { - int status = -ENODEV; - uint8_t xcvr_addr; + u8 xcvr_addr; MI_IDR1_t idr1; MI_IDR2_t idr2; - uint32_t xcvr_id; + u32 xcvr_id; /* We need to get xcvr id and address we just get the first one */ for (xcvr_addr = 0; xcvr_addr < 32; xcvr_addr++) { /* Read the ID from the PHY */ - PhyMiRead(adapter, xcvr_addr, - (uint8_t) offsetof(MI_REGS_t, idr1), + PhyMiRead(etdev, xcvr_addr, + (u8) offsetof(MI_REGS_t, idr1), &idr1.value); - PhyMiRead(adapter, xcvr_addr, - (uint8_t) offsetof(MI_REGS_t, idr2), + PhyMiRead(etdev, xcvr_addr, + (u8) offsetof(MI_REGS_t, idr2), &idr2.value); - xcvr_id = (uint32_t) ((idr1.value << 16) | idr2.value); - - if ((idr1.value != 0) && (idr1.value != 0xffff)) { - adapter->Stats.xcvr_id = xcvr_id; - adapter->Stats.xcvr_addr = xcvr_addr; + xcvr_id = (u32) ((idr1.value << 16) | idr2.value); - status = 0; - break; + if (idr1.value != 0 && idr1.value != 0xffff) { + etdev->Stats.xcvr_id = xcvr_id; + etdev->Stats.xcvr_addr = xcvr_addr; + return 0; } } - return status; + return -ENODEV; +} + +void ET1310_PhyReset(struct et131x_adapter *etdev) +{ + MiWrite(etdev, PHY_CONTROL, 0x8000); +} + +/** + * ET1310_PhyPowerDown - PHY power control + * @etdev: device to control + * @down: true for off/false for back on + * + * one hundred, ten, one thousand megs + * How would you like to have your LAN accessed + * Can't you see that this code processed + * Phy power, phy power.. + */ + +void ET1310_PhyPowerDown(struct et131x_adapter *etdev, bool down) +{ + u16 data; + + MiRead(etdev, PHY_CONTROL, &data); + data &= ~0x0800; /* Power UP */ + if (down) /* Power DOWN */ + data |= 0x0800; + MiWrite(etdev, PHY_CONTROL, data); +} + +/** + * ET130_PhyAutoNEg - autonegotiate control + * @etdev: device to control + * @enabe: autoneg on/off + * + * Set up the autonegotiation state according to whether we will be + * negotiating the state or forcing a speed. + */ + +static void ET1310_PhyAutoNeg(struct et131x_adapter *etdev, bool enable) +{ + u16 data; + + MiRead(etdev, PHY_CONTROL, &data); + data &= ~0x1000; /* Autonegotiation OFF */ + if (enable) + data |= 0x1000; /* Autonegotiation ON */ + MiWrite(etdev, PHY_CONTROL, data); +} + +/** + * ET130_PhyDuplexMode - duplex control + * @etdev: device to control + * @duplex: duplex on/off + * + * Set up the duplex state on the PHY + */ + +static void ET1310_PhyDuplexMode(struct et131x_adapter *etdev, u16 duplex) +{ + u16 data; + + MiRead(etdev, PHY_CONTROL, &data); + data &= ~0x100; /* Set Half Duplex */ + if (duplex == TRUEPHY_DUPLEX_FULL) + data |= 0x100; /* Set Full Duplex */ + MiWrite(etdev, PHY_CONTROL, data); +} + +/** + * ET130_PhySpeedSelect - speed control + * @etdev: device to control + * @duplex: duplex on/off + * + * Set the speed of our PHY. + */ + +static void ET1310_PhySpeedSelect(struct et131x_adapter *etdev, u16 speed) +{ + u16 data; + static const u16 bits[3]={0x0000, 0x2000, 0x0040}; + + /* Read the PHY control register */ + MiRead(etdev, PHY_CONTROL, &data); + /* Clear all Speed settings (Bits 6, 13) */ + data &= ~0x2040; + /* Write back the new speed */ + MiWrite(etdev, PHY_CONTROL, data | bits[speed]); +} + +/** + * ET1310_PhyLinkStatus - read link state + * @etdev: device to read + * @link_status: reported link state + * @autoneg: reported autonegotiation state (complete/incomplete/disabled) + * @linkspeed: returnedlink speed in use + * @duplex_mode: reported half/full duplex state + * @mdi_mdix: not yet working + * @masterslave: report whether we are master or slave + * @polarity: link polarity + * + * I can read your lan like a magazine + * I see if your up + * I know your link speed + * I see all the setting that you'd rather keep + */ + +static void ET1310_PhyLinkStatus(struct et131x_adapter *etdev, + u8 *link_status, + u32 *autoneg, + u32 *linkspeed, + u32 *duplex_mode, + u32 *mdi_mdix, + u32 *masterslave, u32 *polarity) +{ + u16 mistatus = 0; + u16 is1000BaseT = 0; + u16 vmi_phystatus = 0; + u16 control = 0; + + MiRead(etdev, PHY_STATUS, &mistatus); + MiRead(etdev, PHY_1000_STATUS, &is1000BaseT); + MiRead(etdev, PHY_PHY_STATUS, &vmi_phystatus); + MiRead(etdev, PHY_CONTROL, &control); + + *link_status = (vmi_phystatus & 0x0040) ? 1 : 0; + *autoneg = (control & 0x1000) ? ((vmi_phystatus & 0x0020) ? + TRUEPHY_ANEG_COMPLETE : + TRUEPHY_ANEG_NOT_COMPLETE) : + TRUEPHY_ANEG_DISABLED; + *linkspeed = (vmi_phystatus & 0x0300) >> 8; + *duplex_mode = (vmi_phystatus & 0x0080) >> 7; + /* NOTE: Need to complete this */ + *mdi_mdix = 0; + + *masterslave = (is1000BaseT & 0x4000) ? + TRUEPHY_CFG_MASTER : TRUEPHY_CFG_SLAVE; + *polarity = (vmi_phystatus & 0x0400) ? + TRUEPHY_POLARITY_INVERTED : TRUEPHY_POLARITY_NORMAL; +} + +static void ET1310_PhyAndOrReg(struct et131x_adapter *etdev, + u16 regnum, u16 andMask, u16 orMask) +{ + u16 reg; + + MiRead(etdev, regnum, ®); + reg &= andMask; + reg |= orMask; + MiWrite(etdev, regnum, reg); +} + +/* Still used from _mac for BIT_READ */ +void ET1310_PhyAccessMiBit(struct et131x_adapter *etdev, u16 action, + u16 regnum, u16 bitnum, u8 *value) +{ + u16 reg; + u16 mask = 0x0001 << bitnum; + + /* Read the requested register */ + MiRead(etdev, regnum, ®); + + switch (action) { + case TRUEPHY_BIT_READ: + *value = (reg & mask) >> bitnum; + break; + + case TRUEPHY_BIT_SET: + MiWrite(etdev, regnum, reg | mask); + break; + + case TRUEPHY_BIT_CLEAR: + MiWrite(etdev, regnum, reg & ~mask); + break; + + default: + break; + } +} + +void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *etdev, + u16 duplex) +{ + u16 data; + + /* Read the PHY 1000 Base-T Control Register */ + MiRead(etdev, PHY_1000_CONTROL, &data); + + /* Clear Bits 8,9 */ + data &= ~0x0300; + + switch (duplex) { + case TRUEPHY_ADV_DUPLEX_NONE: + /* Duplex already cleared, do nothing */ + break; + + case TRUEPHY_ADV_DUPLEX_FULL: + /* Set Bit 9 */ + data |= 0x0200; + break; + + case TRUEPHY_ADV_DUPLEX_HALF: + /* Set Bit 8 */ + data |= 0x0100; + break; + + case TRUEPHY_ADV_DUPLEX_BOTH: + default: + data |= 0x0300; + break; + } + + /* Write back advertisement */ + MiWrite(etdev, PHY_1000_CONTROL, data); +} + +static void ET1310_PhyAdvertise100BaseT(struct et131x_adapter *etdev, + u16 duplex) +{ + u16 data; + + /* Read the Autonegotiation Register (10/100) */ + MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data); + + /* Clear bits 7,8 */ + data &= ~0x0180; + + switch (duplex) { + case TRUEPHY_ADV_DUPLEX_NONE: + /* Duplex already cleared, do nothing */ + break; + + case TRUEPHY_ADV_DUPLEX_FULL: + /* Set Bit 8 */ + data |= 0x0100; + break; + + case TRUEPHY_ADV_DUPLEX_HALF: + /* Set Bit 7 */ + data |= 0x0080; + break; + + case TRUEPHY_ADV_DUPLEX_BOTH: + default: + /* Set Bits 7,8 */ + data |= 0x0180; + break; + } + + /* Write back advertisement */ + MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data); +} + +static void ET1310_PhyAdvertise10BaseT(struct et131x_adapter *etdev, + u16 duplex) +{ + u16 data; + + /* Read the Autonegotiation Register (10/100) */ + MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data); + + /* Clear bits 5,6 */ + data &= ~0x0060; + + switch (duplex) { + case TRUEPHY_ADV_DUPLEX_NONE: + /* Duplex already cleared, do nothing */ + break; + + case TRUEPHY_ADV_DUPLEX_FULL: + /* Set Bit 6 */ + data |= 0x0040; + break; + + case TRUEPHY_ADV_DUPLEX_HALF: + /* Set Bit 5 */ + data |= 0x0020; + break; + + case TRUEPHY_ADV_DUPLEX_BOTH: + default: + /* Set Bits 5,6 */ + data |= 0x0060; + break; + } + + /* Write back advertisement */ + MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data); } /** * et131x_setphy_normal - Set PHY for normal operation. - * @adapter: pointer to our private adapter structure + * @etdev: pointer to our private adapter structure * * Used by Power Management to force the PHY into 10 Base T half-duplex mode, * when going to D3 in WOL mode. Also used during initialization to set the * PHY for normal operation. */ -int et131x_setphy_normal(struct et131x_adapter *adapter) +void et131x_setphy_normal(struct et131x_adapter *etdev) { - int status; - /* Make sure the PHY is powered up */ - ET1310_PhyPowerDown(adapter, 0); - status = et131x_xcvr_init(adapter); - return status; + ET1310_PhyPowerDown(etdev, 0); + et131x_xcvr_init(etdev); } + /** * et131x_xcvr_init - Init the phy if we are setting it into force mode - * @adapter: pointer to our private adapter structure + * @etdev: pointer to our private adapter structure * - * Returns 0 on success, errno on failure (as defined in errno.h) */ -static int et131x_xcvr_init(struct et131x_adapter *adapter) +static void et131x_xcvr_init(struct et131x_adapter *etdev) { - int status = 0; MI_IMR_t imr; MI_ISR_t isr; MI_LCR2_t lcr2; /* Zero out the adapter structure variable representing BMSR */ - adapter->Bmsr.value = 0; - - MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, isr), &isr.value); + etdev->Bmsr.value = 0; - MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, imr), &imr.value); + MiRead(etdev, (u8) offsetof(MI_REGS_t, isr), &isr.value); + MiRead(etdev, (u8) offsetof(MI_REGS_t, imr), &imr.value); /* Set the link status interrupt only. Bad behavior when link status * and auto neg are set, we run into a nested interrupt problem @@ -338,7 +598,7 @@ static int et131x_xcvr_init(struct et131x_adapter *adapter) imr.bits.link_status = 0x1; imr.bits.autoneg_status = 0x1; - MiWrite(adapter, (uint8_t) offsetof(MI_REGS_t, imr), imr.value); + MiWrite(etdev, (u8) offsetof(MI_REGS_t, imr), imr.value); /* Set the LED behavior such that LED 1 indicates speed (off = * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates @@ -348,111 +608,138 @@ static int et131x_xcvr_init(struct et131x_adapter *adapter) * vendors; The LED behavior is now determined by vendor data in the * EEPROM. However, the above description is the default. */ - if ((adapter->eepromData[1] & 0x4) == 0) { - MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, lcr2), + if ((etdev->eepromData[1] & 0x4) == 0) { + MiRead(etdev, (u8) offsetof(MI_REGS_t, lcr2), &lcr2.value); - if ((adapter->eepromData[1] & 0x8) == 0) + if ((etdev->eepromData[1] & 0x8) == 0) lcr2.bits.led_tx_rx = 0x3; else lcr2.bits.led_tx_rx = 0x4; lcr2.bits.led_link = 0xa; - MiWrite(adapter, (uint8_t) offsetof(MI_REGS_t, lcr2), + MiWrite(etdev, (u8) offsetof(MI_REGS_t, lcr2), lcr2.value); } /* Determine if we need to go into a force mode and set it */ - if (adapter->AiForceSpeed == 0 && adapter->AiForceDpx == 0) { - if ((adapter->RegistryFlowControl == TxOnly) || - (adapter->RegistryFlowControl == Both)) { - ET1310_PhyAccessMiBit(adapter, + if (etdev->AiForceSpeed == 0 && etdev->AiForceDpx == 0) { + if (etdev->RegistryFlowControl == TxOnly || + etdev->RegistryFlowControl == Both) + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_SET, 4, 11, NULL); - } else { - ET1310_PhyAccessMiBit(adapter, + else + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_CLEAR, 4, 11, NULL); - } - if (adapter->RegistryFlowControl == Both) { - ET1310_PhyAccessMiBit(adapter, + if (etdev->RegistryFlowControl == Both) + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_SET, 4, 10, NULL); - } else { - ET1310_PhyAccessMiBit(adapter, + else + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_CLEAR, 4, 10, NULL); - } /* Set the phy to autonegotiation */ - ET1310_PhyAutoNeg(adapter, true); + ET1310_PhyAutoNeg(etdev, true); /* NOTE - Do we need this? */ - ET1310_PhyAccessMiBit(adapter, TRUEPHY_BIT_SET, 0, 9, NULL); - return status; - } else { - ET1310_PhyAutoNeg(adapter, false); - - /* Set to the correct force mode. */ - if (adapter->AiForceDpx != 1) { - if ((adapter->RegistryFlowControl == TxOnly) || - (adapter->RegistryFlowControl == Both)) { - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_SET, 4, 11, - NULL); - } else { - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_CLEAR, 4, 11, - NULL); - } + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_SET, 0, 9, NULL); + return; + } - if (adapter->RegistryFlowControl == Both) { - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_SET, 4, 10, - NULL); - } else { - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_CLEAR, 4, 10, - NULL); - } - } else { - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_CLEAR, 4, 10, NULL); - ET1310_PhyAccessMiBit(adapter, + ET1310_PhyAutoNeg(etdev, false); + + /* Set to the correct force mode. */ + if (etdev->AiForceDpx != 1) { + if (etdev->RegistryFlowControl == TxOnly || + etdev->RegistryFlowControl == Both) + ET1310_PhyAccessMiBit(etdev, + TRUEPHY_BIT_SET, 4, 11, NULL); + else + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_CLEAR, 4, 11, NULL); - } - switch (adapter->AiForceSpeed) { - case 10: - if (adapter->AiForceDpx == 1) - TPAL_SetPhy10HalfDuplex(adapter); - else if (adapter->AiForceDpx == 2) - TPAL_SetPhy10FullDuplex(adapter); - else - TPAL_SetPhy10Force(adapter); - break; - case 100: - if (adapter->AiForceDpx == 1) - TPAL_SetPhy100HalfDuplex(adapter); - else if (adapter->AiForceDpx == 2) - TPAL_SetPhy100FullDuplex(adapter); - else - TPAL_SetPhy100Force(adapter); - break; - case 1000: - TPAL_SetPhy1000FullDuplex(adapter); - break; + if (etdev->RegistryFlowControl == Both) + ET1310_PhyAccessMiBit(etdev, + TRUEPHY_BIT_SET, 4, 10, NULL); + else + ET1310_PhyAccessMiBit(etdev, + TRUEPHY_BIT_CLEAR, 4, 10, NULL); + } else { + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_CLEAR, 4, 10, NULL); + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_CLEAR, 4, 11, NULL); + } + ET1310_PhyPowerDown(etdev, 1); + switch (etdev->AiForceSpeed) { + case 10: + /* First we need to turn off all other advertisement */ + ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); + ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); + if (etdev->AiForceDpx == 1) { + /* Set our advertise values accordingly */ + ET1310_PhyAdvertise10BaseT(etdev, + TRUEPHY_ADV_DUPLEX_HALF); + } else if (etdev->AiForceDpx == 2) { + /* Set our advertise values accordingly */ + ET1310_PhyAdvertise10BaseT(etdev, + TRUEPHY_ADV_DUPLEX_FULL); + } else { + /* Disable autoneg */ + ET1310_PhyAutoNeg(etdev, false); + /* Disable rest of the advertisements */ + ET1310_PhyAdvertise10BaseT(etdev, + TRUEPHY_ADV_DUPLEX_NONE); + /* Force 10 Mbps */ + ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_10MBPS); + /* Force Full duplex */ + ET1310_PhyDuplexMode(etdev, TRUEPHY_DUPLEX_FULL); } - - return status; + break; + case 100: + /* first we need to turn off all other advertisement */ + ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); + ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); + if (etdev->AiForceDpx == 1) { + /* Set our advertise values accordingly */ + ET1310_PhyAdvertise100BaseT(etdev, + TRUEPHY_ADV_DUPLEX_HALF); + /* Set speed */ + ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_100MBPS); + } else if (etdev->AiForceDpx == 2) { + /* Set our advertise values accordingly */ + ET1310_PhyAdvertise100BaseT(etdev, + TRUEPHY_ADV_DUPLEX_FULL); + } else { + /* Disable autoneg */ + ET1310_PhyAutoNeg(etdev, false); + /* Disable other advertisement */ + ET1310_PhyAdvertise100BaseT(etdev, + TRUEPHY_ADV_DUPLEX_NONE); + /* Force 100 Mbps */ + ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_100MBPS); + /* Force Full duplex */ + ET1310_PhyDuplexMode(etdev, TRUEPHY_DUPLEX_FULL); + } + break; + case 1000: + /* first we need to turn off all other advertisement */ + ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); + ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); + /* set our advertise values accordingly */ + ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL); + break; } + ET1310_PhyPowerDown(etdev, 0); } void et131x_Mii_check(struct et131x_adapter *etdev, MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints) { - uint8_t link_status; - uint32_t autoneg_status; - uint32_t speed; - uint32_t duplex; - uint32_t mdi_mdix; - uint32_t masterslave; - uint32_t polarity; + u8 link_status; + u32 autoneg_status; + u32 speed; + u32 duplex; + u32 mdi_mdix; + u32 masterslave; + u32 polarity; unsigned long flags; if (bmsr_ints.bits.link_status) { @@ -469,9 +756,7 @@ void et131x_Mii_check(struct et131x_adapter *etdev, spin_unlock_irqrestore(&etdev->Lock, flags); - /* Don't indicate state if we're in loopback mode */ - if (etdev->RegistryPhyLoopbk == false) - netif_carrier_on(etdev->netdev); + netif_carrier_on(etdev->netdev); } else { dev_warn(&etdev->pdev->dev, "Link down - cable problem ?\n"); @@ -481,7 +766,7 @@ void et131x_Mii_check(struct et131x_adapter *etdev, * TruePHY? * && TRU_QueryCoreType(etdev->hTruePhy, 0) == EMI_TRUEPHY_A13O) { */ - uint16_t Register18; + u16 Register18; MiRead(etdev, 0x12, &Register18); MiWrite(etdev, 0x12, Register18 | 0x4); @@ -504,11 +789,7 @@ void et131x_Mii_check(struct et131x_adapter *etdev, spin_unlock_irqrestore(&etdev->Lock, flags); - /* Only indicate state if we're in loopback - * mode - */ - if (etdev->RegistryPhyLoopbk == false) - netif_carrier_off(etdev->netdev); + netif_carrier_off(etdev->netdev); } etdev->linkspeed = 0; @@ -561,7 +842,7 @@ void et131x_Mii_check(struct et131x_adapter *etdev, * TruePHY? * && TRU_QueryCoreType(etdev->hTruePhy, 0)== EMI_TRUEPHY_A13O) { */ - uint16_t Register18; + u16 Register18; MiRead(etdev, 0x12, &Register18); MiWrite(etdev, 0x12, Register18 | 0x4); @@ -583,212 +864,13 @@ void et131x_Mii_check(struct et131x_adapter *etdev, } } -/** - * TPAL_SetPhy10HalfDuplex - Force the phy into 10 Base T Half Duplex mode. - * @etdev: pointer to the adapter structure - * - * Also sets the MAC so it is syncd up properly +/* + * The routines which follow provide low-level access to the PHY, and are used + * primarily by the routines above (although there are a few places elsewhere + * in the driver where this level of access is required). */ -void TPAL_SetPhy10HalfDuplex(struct et131x_adapter *etdev) -{ - /* Power down PHY */ - ET1310_PhyPowerDown(etdev, 1); - - /* First we need to turn off all other advertisement */ - ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - - ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - - /* Set our advertise values accordingly */ - ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_HALF); - - /* Power up PHY */ - ET1310_PhyPowerDown(etdev, 0); -} - -/** - * TPAL_SetPhy10FullDuplex - Force the phy into 10 Base T Full Duplex mode. - * @etdev: pointer to the adapter structure - * - * Also sets the MAC so it is syncd up properly - */ -void TPAL_SetPhy10FullDuplex(struct et131x_adapter *etdev) -{ - /* Power down PHY */ - ET1310_PhyPowerDown(etdev, 1); - - /* First we need to turn off all other advertisement */ - ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - - ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - - /* Set our advertise values accordingly */ - ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL); - - /* Power up PHY */ - ET1310_PhyPowerDown(etdev, 0); -} - -/** - * TPAL_SetPhy10Force - Force Base-T FD mode WITHOUT using autonegotiation - * @etdev: pointer to the adapter structure - */ -void TPAL_SetPhy10Force(struct et131x_adapter *etdev) -{ - /* Power down PHY */ - ET1310_PhyPowerDown(etdev, 1); - - /* Disable autoneg */ - ET1310_PhyAutoNeg(etdev, false); - - /* Disable all advertisement */ - ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - - /* Force 10 Mbps */ - ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_10MBPS); - - /* Force Full duplex */ - ET1310_PhyDuplexMode(etdev, TRUEPHY_DUPLEX_FULL); - - /* Power up PHY */ - ET1310_PhyPowerDown(etdev, 0); -} - -/** - * TPAL_SetPhy100HalfDuplex - Force 100 Base T Half Duplex mode. - * @etdev: pointer to the adapter structure - * - * Also sets the MAC so it is syncd up properly. - */ -void TPAL_SetPhy100HalfDuplex(struct et131x_adapter *etdev) -{ - /* Power down PHY */ - ET1310_PhyPowerDown(etdev, 1); - - /* first we need to turn off all other advertisement */ - ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - - ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - - /* Set our advertise values accordingly */ - ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_HALF); - - /* Set speed */ - ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_100MBPS); - - /* Power up PHY */ - ET1310_PhyPowerDown(etdev, 0); -} - -/** - * TPAL_SetPhy100FullDuplex - Force 100 Base T Full Duplex mode. - * @etdev: pointer to the adapter structure - * - * Also sets the MAC so it is syncd up properly - */ -void TPAL_SetPhy100FullDuplex(struct et131x_adapter *etdev) -{ - /* Power down PHY */ - ET1310_PhyPowerDown(etdev, 1); - - /* First we need to turn off all other advertisement */ - ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - - ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - - /* Set our advertise values accordingly */ - ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL); - - /* Power up PHY */ - ET1310_PhyPowerDown(etdev, 0); -} - -/** - * TPAL_SetPhy100Force - Force 100 BaseT FD mode WITHOUT using autonegotiation - * @etdev: pointer to the adapter structure - */ -void TPAL_SetPhy100Force(struct et131x_adapter *etdev) -{ - /* Power down PHY */ - ET1310_PhyPowerDown(etdev, 1); - - /* Disable autoneg */ - ET1310_PhyAutoNeg(etdev, false); - - /* Disable all advertisement */ - ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - - /* Force 100 Mbps */ - ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_100MBPS); - - /* Force Full duplex */ - ET1310_PhyDuplexMode(etdev, TRUEPHY_DUPLEX_FULL); - - /* Power up PHY */ - ET1310_PhyPowerDown(etdev, 0); -} - -/** - * TPAL_SetPhy1000FullDuplex - Force 1000 Base T Full Duplex mode - * @etdev: pointer to the adapter structure - * - * Also sets the MAC so it is syncd up properly. - */ -void TPAL_SetPhy1000FullDuplex(struct et131x_adapter *etdev) -{ - /* Power down PHY */ - ET1310_PhyPowerDown(etdev, 1); - - /* first we need to turn off all other advertisement */ - ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - - ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - /* set our advertise values accordingly */ - ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL); - - /* power up PHY */ - ET1310_PhyPowerDown(etdev, 0); -} - -/** - * TPAL_SetPhyAutoNeg - Set phy to autonegotiation mode. - * @etdev: pointer to the adapter structure - */ -void TPAL_SetPhyAutoNeg(struct et131x_adapter *etdev) -{ - /* Power down PHY */ - ET1310_PhyPowerDown(etdev, 1); - - /* Turn on advertisement of all capabilities */ - ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_BOTH); - - ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_BOTH); - - if (etdev->pdev->device != ET131X_PCI_DEVICE_ID_FAST) - ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL); - else - ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); - - /* Make sure auto-neg is ON (it is disabled in FORCE modes) */ - ET1310_PhyAutoNeg(etdev, true); - - /* Power up PHY */ - ET1310_PhyPowerDown(etdev, 0); -} - - -/* - * The routines which follow provide low-level access to the PHY, and are used - * primarily by the routines above (although there are a few places elsewhere - * in the driver where this level of access is required). - */ - -static const uint16_t ConfigPhy[25][2] = { +static const u16 ConfigPhy[25][2] = { /* Reg Value Register */ /* Addr */ {0x880B, 0x0926}, /* AfeIfCreg4B1000Msbs */ @@ -831,7 +913,7 @@ static const uint16_t ConfigPhy[25][2] = { /* condensed version of the phy initialization routine */ void ET1310_PhyInit(struct et131x_adapter *etdev) { - uint16_t data, index; + u16 data, index; if (etdev == NULL) return; @@ -896,304 +978,3 @@ void ET1310_PhyInit(struct et131x_adapter *etdev) MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0002); } -void ET1310_PhyReset(struct et131x_adapter *etdev) -{ - MiWrite(etdev, PHY_CONTROL, 0x8000); -} - -void ET1310_PhyPowerDown(struct et131x_adapter *etdev, bool down) -{ - uint16_t data; - - MiRead(etdev, PHY_CONTROL, &data); - - if (down == false) { - /* Power UP */ - data &= ~0x0800; - MiWrite(etdev, PHY_CONTROL, data); - } else { - /* Power DOWN */ - data |= 0x0800; - MiWrite(etdev, PHY_CONTROL, data); - } -} - -void ET1310_PhyAutoNeg(struct et131x_adapter *etdev, bool enable) -{ - uint16_t data; - - MiRead(etdev, PHY_CONTROL, &data); - - if (enable == true) { - /* Autonegotiation ON */ - data |= 0x1000; - MiWrite(etdev, PHY_CONTROL, data); - } else { - /* Autonegotiation OFF */ - data &= ~0x1000; - MiWrite(etdev, PHY_CONTROL, data); - } -} - -void ET1310_PhyDuplexMode(struct et131x_adapter *etdev, uint16_t duplex) -{ - uint16_t data; - - MiRead(etdev, PHY_CONTROL, &data); - - if (duplex == TRUEPHY_DUPLEX_FULL) { - /* Set Full Duplex */ - data |= 0x100; - MiWrite(etdev, PHY_CONTROL, data); - } else { - /* Set Half Duplex */ - data &= ~0x100; - MiWrite(etdev, PHY_CONTROL, data); - } -} - -void ET1310_PhySpeedSelect(struct et131x_adapter *etdev, uint16_t speed) -{ - uint16_t data; - - /* Read the PHY control register */ - MiRead(etdev, PHY_CONTROL, &data); - - /* Clear all Speed settings (Bits 6, 13) */ - data &= ~0x2040; - - /* Reset the speed bits based on user selection */ - switch (speed) { - case TRUEPHY_SPEED_10MBPS: - /* Bits already cleared above, do nothing */ - break; - - case TRUEPHY_SPEED_100MBPS: - /* 100M == Set bit 13 */ - data |= 0x2000; - break; - - case TRUEPHY_SPEED_1000MBPS: - default: - data |= 0x0040; - break; - } - - /* Write back the new speed */ - MiWrite(etdev, PHY_CONTROL, data); -} - -void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *etdev, - uint16_t duplex) -{ - uint16_t data; - - /* Read the PHY 1000 Base-T Control Register */ - MiRead(etdev, PHY_1000_CONTROL, &data); - - /* Clear Bits 8,9 */ - data &= ~0x0300; - - switch (duplex) { - case TRUEPHY_ADV_DUPLEX_NONE: - /* Duplex already cleared, do nothing */ - break; - - case TRUEPHY_ADV_DUPLEX_FULL: - /* Set Bit 9 */ - data |= 0x0200; - break; - - case TRUEPHY_ADV_DUPLEX_HALF: - /* Set Bit 8 */ - data |= 0x0100; - break; - - case TRUEPHY_ADV_DUPLEX_BOTH: - default: - data |= 0x0300; - break; - } - - /* Write back advertisement */ - MiWrite(etdev, PHY_1000_CONTROL, data); -} - -void ET1310_PhyAdvertise100BaseT(struct et131x_adapter *etdev, - uint16_t duplex) -{ - uint16_t data; - - /* Read the Autonegotiation Register (10/100) */ - MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data); - - /* Clear bits 7,8 */ - data &= ~0x0180; - - switch (duplex) { - case TRUEPHY_ADV_DUPLEX_NONE: - /* Duplex already cleared, do nothing */ - break; - - case TRUEPHY_ADV_DUPLEX_FULL: - /* Set Bit 8 */ - data |= 0x0100; - break; - - case TRUEPHY_ADV_DUPLEX_HALF: - /* Set Bit 7 */ - data |= 0x0080; - break; - - case TRUEPHY_ADV_DUPLEX_BOTH: - default: - /* Set Bits 7,8 */ - data |= 0x0180; - break; - } - - /* Write back advertisement */ - MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data); -} - -void ET1310_PhyAdvertise10BaseT(struct et131x_adapter *etdev, - uint16_t duplex) -{ - uint16_t data; - - /* Read the Autonegotiation Register (10/100) */ - MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data); - - /* Clear bits 5,6 */ - data &= ~0x0060; - - switch (duplex) { - case TRUEPHY_ADV_DUPLEX_NONE: - /* Duplex already cleared, do nothing */ - break; - - case TRUEPHY_ADV_DUPLEX_FULL: - /* Set Bit 6 */ - data |= 0x0040; - break; - - case TRUEPHY_ADV_DUPLEX_HALF: - /* Set Bit 5 */ - data |= 0x0020; - break; - - case TRUEPHY_ADV_DUPLEX_BOTH: - default: - /* Set Bits 5,6 */ - data |= 0x0060; - break; - } - - /* Write back advertisement */ - MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data); -} - -void ET1310_PhyLinkStatus(struct et131x_adapter *etdev, - uint8_t *link_status, - uint32_t *autoneg, - uint32_t *linkspeed, - uint32_t *duplex_mode, - uint32_t *mdi_mdix, - uint32_t *masterslave, uint32_t *polarity) -{ - uint16_t mistatus = 0; - uint16_t is1000BaseT = 0; - uint16_t vmi_phystatus = 0; - uint16_t control = 0; - - MiRead(etdev, PHY_STATUS, &mistatus); - MiRead(etdev, PHY_1000_STATUS, &is1000BaseT); - MiRead(etdev, PHY_PHY_STATUS, &vmi_phystatus); - MiRead(etdev, PHY_CONTROL, &control); - - if (link_status) { - *link_status = - (unsigned char)((vmi_phystatus & 0x0040) ? 1 : 0); - } - - if (autoneg) { - *autoneg = - (control & 0x1000) ? ((vmi_phystatus & 0x0020) ? - TRUEPHY_ANEG_COMPLETE : - TRUEPHY_ANEG_NOT_COMPLETE) : - TRUEPHY_ANEG_DISABLED; - } - - if (linkspeed) - *linkspeed = (vmi_phystatus & 0x0300) >> 8; - - if (duplex_mode) - *duplex_mode = (vmi_phystatus & 0x0080) >> 7; - - if (mdi_mdix) - /* NOTE: Need to complete this */ - *mdi_mdix = 0; - - if (masterslave) { - *masterslave = - (is1000BaseT & 0x4000) ? TRUEPHY_CFG_MASTER : - TRUEPHY_CFG_SLAVE; - } - - if (polarity) { - *polarity = - (vmi_phystatus & 0x0400) ? TRUEPHY_POLARITY_INVERTED : - TRUEPHY_POLARITY_NORMAL; - } -} - -void ET1310_PhyAndOrReg(struct et131x_adapter *etdev, - uint16_t regnum, uint16_t andMask, uint16_t orMask) -{ - uint16_t reg; - - /* Read the requested register */ - MiRead(etdev, regnum, ®); - - /* Apply the AND mask */ - reg &= andMask; - - /* Apply the OR mask */ - reg |= orMask; - - /* Write the value back to the register */ - MiWrite(etdev, regnum, reg); -} - -void ET1310_PhyAccessMiBit(struct et131x_adapter *etdev, uint16_t action, - uint16_t regnum, uint16_t bitnum, uint8_t *value) -{ - uint16_t reg; - uint16_t mask = 0; - - /* Create a mask to isolate the requested bit */ - mask = 0x0001 << bitnum; - - /* Read the requested register */ - MiRead(etdev, regnum, ®); - - switch (action) { - case TRUEPHY_BIT_READ: - if (value != NULL) - *value = (reg & mask) >> bitnum; - break; - - case TRUEPHY_BIT_SET: - reg |= mask; - MiWrite(etdev, regnum, reg); - break; - - case TRUEPHY_BIT_CLEAR: - reg &= ~mask; - MiWrite(etdev, regnum, reg); - break; - - default: - break; - } -} diff --git a/drivers/staging/et131x/et1310_phy.h b/drivers/staging/et131x/et1310_phy.h index 080656c6142c18135f08788c19a2196360607b06..758b9b251715004f5c2f770ef3f335620ed79216 100644 --- a/drivers/staging/et131x/et1310_phy.h +++ b/drivers/staging/et131x/et1310_phy.h @@ -61,9 +61,6 @@ #include "et1310_address_map.h" -#define TRUEPHY_SUCCESS 0 -#define TRUEPHY_FAILURE 1 - /* MI Register Addresses */ #define MI_CONTROL_REG 0 #define MI_STATUS_REG 1 @@ -742,25 +739,15 @@ typedef union _MI_LCR2_t { /* Forward declaration of the private adapter structure */ struct et131x_adapter; -/* OS Specific Functions*/ -void TPAL_SetPhy10HalfDuplex(struct et131x_adapter *adapter); -void TPAL_SetPhy10FullDuplex(struct et131x_adapter *adapter); -void TPAL_SetPhy10Force(struct et131x_adapter *pAdapter); -void TPAL_SetPhy100HalfDuplex(struct et131x_adapter *adapter); -void TPAL_SetPhy100FullDuplex(struct et131x_adapter *adapter); -void TPAL_SetPhy100Force(struct et131x_adapter *pAdapter); -void TPAL_SetPhy1000FullDuplex(struct et131x_adapter *adapter); -void TPAL_SetPhyAutoNeg(struct et131x_adapter *adapter); - /* Prototypes for ET1310_phy.c */ int et131x_xcvr_find(struct et131x_adapter *adapter); -int et131x_setphy_normal(struct et131x_adapter *adapter); -int32_t PhyMiRead(struct et131x_adapter *adapter, - u8 xcvrAddr, u8 xcvrReg, u16 *value); +void et131x_setphy_normal(struct et131x_adapter *adapter); /* static inline function does not work because et131x_adapter is not always * defined */ +int PhyMiRead(struct et131x_adapter *adapter, u8 xcvrAddr, + u8 xcvrReg, u16 *value); #define MiRead(adapter, xcvrReg, value) \ PhyMiRead((adapter), (adapter)->Stats.xcvr_addr, (xcvrReg), (value)) @@ -860,24 +847,8 @@ void SetPhy_10BaseTHalfDuplex(struct et131x_adapter *adapter); void ET1310_PhyInit(struct et131x_adapter *adapter); void ET1310_PhyReset(struct et131x_adapter *adapter); void ET1310_PhyPowerDown(struct et131x_adapter *adapter, bool down); -void ET1310_PhyAutoNeg(struct et131x_adapter *adapter, bool enable); -void ET1310_PhyDuplexMode(struct et131x_adapter *adapter, u16 duplex); -void ET1310_PhySpeedSelect(struct et131x_adapter *adapter, u16 speed); void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *adapter, u16 duplex); -void ET1310_PhyAdvertise100BaseT(struct et131x_adapter *adapter, - u16 duplex); -void ET1310_PhyAdvertise10BaseT(struct et131x_adapter *adapter, - u16 duplex); -void ET1310_PhyLinkStatus(struct et131x_adapter *adapter, - u8 *Link_status, - u32 *autoneg, - u32 *linkspeed, - u32 *duplex_mode, - u32 *mdi_mdix, - u32 *masterslave, u32 *polarity); -void ET1310_PhyAndOrReg(struct et131x_adapter *adapter, - u16 regnum, u16 andMask, u16 orMask); void ET1310_PhyAccessMiBit(struct et131x_adapter *adapter, u16 action, u16 regnum, u16 bitnum, u8 *value); diff --git a/drivers/staging/et131x/et1310_rx.c b/drivers/staging/et131x/et1310_rx.c index 10e21db57ac3d87143ad6dbb2f3a8ed16e8dcd15..3ddc9b12b8db70ef9f2171481fcc5a1a5b60697d 100644 --- a/drivers/staging/et131x/et1310_rx.c +++ b/drivers/staging/et131x/et1310_rx.c @@ -106,9 +106,9 @@ void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD pMpRfd); */ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) { - uint32_t OuterLoop, InnerLoop; - uint32_t bufsize; - uint32_t pktStatRingSize, FBRChunkSize; + u32 i, j; + u32 bufsize; + u32 pktStatRingSize, FBRChunkSize; RX_RING_t *rx_ring; /* Setup some convenience pointers */ @@ -227,11 +227,11 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) rx_ring->Fbr0offset); #endif - for (OuterLoop = 0; OuterLoop < (rx_ring->Fbr1NumEntries / FBR_CHUNKS); - OuterLoop++) { - uint64_t Fbr1Offset; - uint64_t Fbr1TempPa; - uint32_t Fbr1Align; + for (i = 0; i < (rx_ring->Fbr1NumEntries / FBR_CHUNKS); + i++) { + u64 Fbr1Offset; + u64 Fbr1TempPa; + u32 Fbr1Align; /* This code allocates an area of memory big enough for N * free buffers + (buffer_size - 1) so that the buffers can @@ -247,39 +247,39 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) FBRChunkSize = (FBR_CHUNKS * rx_ring->Fbr1BufferSize) + Fbr1Align - 1; - rx_ring->Fbr1MemVa[OuterLoop] = + rx_ring->Fbr1MemVa[i] = pci_alloc_consistent(adapter->pdev, FBRChunkSize, - &rx_ring->Fbr1MemPa[OuterLoop]); + &rx_ring->Fbr1MemPa[i]); - if (!rx_ring->Fbr1MemVa[OuterLoop]) { + if (!rx_ring->Fbr1MemVa[i]) { dev_err(&adapter->pdev->dev, "Could not alloc memory\n"); return -ENOMEM; } /* See NOTE in "Save Physical Address" comment above */ - Fbr1TempPa = rx_ring->Fbr1MemPa[OuterLoop]; + Fbr1TempPa = rx_ring->Fbr1MemPa[i]; et131x_align_allocated_memory(adapter, &Fbr1TempPa, &Fbr1Offset, (Fbr1Align - 1)); - for (InnerLoop = 0; InnerLoop < FBR_CHUNKS; InnerLoop++) { - uint32_t index = (OuterLoop * FBR_CHUNKS) + InnerLoop; + for (j = 0; j < FBR_CHUNKS; j++) { + u32 index = (i * FBR_CHUNKS) + j; /* Save the Virtual address of this index for quick * access later */ rx_ring->Fbr[1]->Va[index] = - (uint8_t *) rx_ring->Fbr1MemVa[OuterLoop] + - (InnerLoop * rx_ring->Fbr1BufferSize) + Fbr1Offset; + (uint8_t *) rx_ring->Fbr1MemVa[i] + + (j * rx_ring->Fbr1BufferSize) + Fbr1Offset; /* now store the physical address in the descriptor * so the device can access it */ rx_ring->Fbr[1]->PAHigh[index] = - (uint32_t) (Fbr1TempPa >> 32); - rx_ring->Fbr[1]->PALow[index] = (uint32_t) Fbr1TempPa; + (u32) (Fbr1TempPa >> 32); + rx_ring->Fbr[1]->PALow[index] = (u32) Fbr1TempPa; Fbr1TempPa += rx_ring->Fbr1BufferSize; @@ -292,40 +292,40 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) #ifdef USE_FBR0 /* Same for FBR0 (if in use) */ - for (OuterLoop = 0; OuterLoop < (rx_ring->Fbr0NumEntries / FBR_CHUNKS); - OuterLoop++) { - uint64_t Fbr0Offset; - uint64_t Fbr0TempPa; + for (i = 0; i < (rx_ring->Fbr0NumEntries / FBR_CHUNKS); + i++) { + u64 Fbr0Offset; + u64 Fbr0TempPa; FBRChunkSize = ((FBR_CHUNKS + 1) * rx_ring->Fbr0BufferSize) - 1; - rx_ring->Fbr0MemVa[OuterLoop] = + rx_ring->Fbr0MemVa[i] = pci_alloc_consistent(adapter->pdev, FBRChunkSize, - &rx_ring->Fbr0MemPa[OuterLoop]); + &rx_ring->Fbr0MemPa[i]); - if (!rx_ring->Fbr0MemVa[OuterLoop]) { + if (!rx_ring->Fbr0MemVa[i]) { dev_err(&adapter->pdev->dev, "Could not alloc memory\n"); return -ENOMEM; } /* See NOTE in "Save Physical Address" comment above */ - Fbr0TempPa = rx_ring->Fbr0MemPa[OuterLoop]; + Fbr0TempPa = rx_ring->Fbr0MemPa[i]; et131x_align_allocated_memory(adapter, &Fbr0TempPa, &Fbr0Offset, rx_ring->Fbr0BufferSize - 1); - for (InnerLoop = 0; InnerLoop < FBR_CHUNKS; InnerLoop++) { - uint32_t index = (OuterLoop * FBR_CHUNKS) + InnerLoop; + for (j = 0; j < FBR_CHUNKS; j++) { + u32 index = (i * FBR_CHUNKS) + j; rx_ring->Fbr[0]->Va[index] = - (uint8_t *) rx_ring->Fbr0MemVa[OuterLoop] + - (InnerLoop * rx_ring->Fbr0BufferSize) + Fbr0Offset; + (uint8_t *) rx_ring->Fbr0MemVa[i] + + (j * rx_ring->Fbr0BufferSize) + Fbr0Offset; rx_ring->Fbr[0]->PAHigh[index] = - (uint32_t) (Fbr0TempPa >> 32); - rx_ring->Fbr[0]->PALow[index] = (uint32_t) Fbr0TempPa; + (u32) (Fbr0TempPa >> 32); + rx_ring->Fbr[0]->PALow[index] = (u32) Fbr0TempPa; Fbr0TempPa += rx_ring->Fbr0BufferSize; @@ -342,7 +342,7 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) sizeof(PKT_STAT_DESC_t) * adapter->RxRing.PsrNumEntries; rx_ring->pPSRingVa = pci_alloc_consistent(adapter->pdev, - pktStatRingSize + 0x0fff, + pktStatRingSize, &rx_ring->pPSRingPa); if (!rx_ring->pPSRingVa) { @@ -350,45 +350,26 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) "Cannot alloc memory for Packet Status Ring\n"); return -ENOMEM; } + printk("PSR %lx\n", (unsigned long) rx_ring->pPSRingPa); - /* Save physical address - * + /* * NOTE : pci_alloc_consistent(), used above to alloc DMA regions, * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses * are ever returned, make sure the high part is retrieved here before * storing the adjusted address. */ - rx_ring->pPSRingRealPa = rx_ring->pPSRingPa; - - /* Align Packet Status Ring on a 4K boundary */ - et131x_align_allocated_memory(adapter, - &rx_ring->pPSRingRealPa, - &rx_ring->pPSRingOffset, 0x0FFF); - - rx_ring->pPSRingVa = (void *)((uint8_t *) rx_ring->pPSRingVa + - rx_ring->pPSRingOffset); /* Allocate an area of memory for writeback of status information */ rx_ring->pRxStatusVa = pci_alloc_consistent(adapter->pdev, - sizeof(RX_STATUS_BLOCK_t) + - 0x7, &rx_ring->pRxStatusPa); + sizeof(RX_STATUS_BLOCK_t), + &rx_ring->pRxStatusPa); if (!rx_ring->pRxStatusVa) { dev_err(&adapter->pdev->dev, "Cannot alloc memory for Status Block\n"); return -ENOMEM; } - - /* Save physical address */ - rx_ring->RxStatusRealPA = rx_ring->pRxStatusPa; - - /* Align write back on an 8 byte boundary */ - et131x_align_allocated_memory(adapter, - &rx_ring->RxStatusRealPA, - &rx_ring->RxStatusOffset, 0x07); - - rx_ring->pRxStatusVa = (void *)((uint8_t *) rx_ring->pRxStatusVa + - rx_ring->RxStatusOffset); rx_ring->NumRfd = NIC_DEFAULT_NUM_RFD; + printk("PRS %lx\n", (unsigned long)rx_ring->pRxStatusPa); /* Recv * pci_pool_create initializes a lookaside list. After successful @@ -409,7 +390,6 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) * lists now. */ INIT_LIST_HEAD(&rx_ring->RecvList); - INIT_LIST_HEAD(&rx_ring->RecvPendingList); return 0; } @@ -419,10 +399,10 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) */ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) { - uint32_t index; - uint32_t bufsize; - uint32_t pktStatRingSize; - PMP_RFD pMpRfd; + u32 index; + u32 bufsize; + u32 pktStatRingSize; + PMP_RFD rfd; RX_RING_t *rx_ring; /* Setup some convenience pointers */ @@ -432,18 +412,12 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) WARN_ON(rx_ring->nReadyRecv != rx_ring->NumRfd); while (!list_empty(&rx_ring->RecvList)) { - pMpRfd = (MP_RFD *) list_entry(rx_ring->RecvList.next, + rfd = (MP_RFD *) list_entry(rx_ring->RecvList.next, MP_RFD, list_node); - list_del(&pMpRfd->list_node); - et131x_rfd_resources_free(adapter, pMpRfd); - } - - while (!list_empty(&rx_ring->RecvPendingList)) { - pMpRfd = (MP_RFD *) list_entry(rx_ring->RecvPendingList.next, - MP_RFD, list_node); - list_del(&pMpRfd->list_node); - et131x_rfd_resources_free(adapter, pMpRfd); + list_del(&rfd->list_node); + rfd->Packet = NULL; + kmem_cache_free(adapter->RxRing.RecvLookaside, rfd); } /* Free Free Buffer Ring 1 */ @@ -452,7 +426,7 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) for (index = 0; index < (rx_ring->Fbr1NumEntries / FBR_CHUNKS); index++) { if (rx_ring->Fbr1MemVa[index]) { - uint32_t Fbr1Align; + u32 Fbr1Align; if (rx_ring->Fbr1BufferSize > 4096) Fbr1Align = 4096; @@ -523,14 +497,10 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) /* Free Packet Status Ring */ if (rx_ring->pPSRingVa) { - rx_ring->pPSRingVa = (void *)((uint8_t *) rx_ring->pPSRingVa - - rx_ring->pPSRingOffset); - pktStatRingSize = sizeof(PKT_STAT_DESC_t) * adapter->RxRing.PsrNumEntries; - pci_free_consistent(adapter->pdev, - pktStatRingSize + 0x0fff, + pci_free_consistent(adapter->pdev, pktStatRingSize, rx_ring->pPSRingVa, rx_ring->pPSRingPa); rx_ring->pPSRingVa = NULL; @@ -538,11 +508,8 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) /* Free area of memory for the writeback of status information */ if (rx_ring->pRxStatusVa) { - rx_ring->pRxStatusVa = (void *)((uint8_t *) - rx_ring->pRxStatusVa - rx_ring->RxStatusOffset); - pci_free_consistent(adapter->pdev, - sizeof(RX_STATUS_BLOCK_t) + 0x7, + sizeof(RX_STATUS_BLOCK_t), rx_ring->pRxStatusVa, rx_ring->pRxStatusPa); rx_ring->pRxStatusVa = NULL; @@ -578,80 +545,49 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) int et131x_init_recv(struct et131x_adapter *adapter) { int status = -ENOMEM; - PMP_RFD pMpRfd = NULL; - uint32_t RfdCount; - uint32_t TotalNumRfd = 0; + PMP_RFD rfd = NULL; + u32 rfdct; + u32 numrfd = 0; RX_RING_t *rx_ring = NULL; /* Setup some convenience pointers */ rx_ring = (RX_RING_t *) &adapter->RxRing; /* Setup each RFD */ - for (RfdCount = 0; RfdCount < rx_ring->NumRfd; RfdCount++) { - pMpRfd = (MP_RFD *) kmem_cache_alloc(rx_ring->RecvLookaside, + for (rfdct = 0; rfdct < rx_ring->NumRfd; rfdct++) { + rfd = (MP_RFD *) kmem_cache_alloc(rx_ring->RecvLookaside, GFP_ATOMIC | GFP_DMA); - if (!pMpRfd) { + if (!rfd) { dev_err(&adapter->pdev->dev, "Couldn't alloc RFD out of kmem_cache\n"); status = -ENOMEM; continue; } - status = et131x_rfd_resources_alloc(adapter, pMpRfd); - if (status != 0) { - dev_err(&adapter->pdev->dev, - "Couldn't alloc packet for RFD\n"); - kmem_cache_free(rx_ring->RecvLookaside, pMpRfd); - continue; - } + rfd->Packet = NULL; /* Add this RFD to the RecvList */ - list_add_tail(&pMpRfd->list_node, &rx_ring->RecvList); + list_add_tail(&rfd->list_node, &rx_ring->RecvList); /* Increment both the available RFD's, and the total RFD's. */ rx_ring->nReadyRecv++; - TotalNumRfd++; + numrfd++; } - if (TotalNumRfd > NIC_MIN_NUM_RFD) + if (numrfd > NIC_MIN_NUM_RFD) status = 0; - rx_ring->NumRfd = TotalNumRfd; + rx_ring->NumRfd = numrfd; if (status != 0) { - kmem_cache_free(rx_ring->RecvLookaside, pMpRfd); + kmem_cache_free(rx_ring->RecvLookaside, rfd); dev_err(&adapter->pdev->dev, "Allocation problems in et131x_init_recv\n"); } return status; } -/** - * et131x_rfd_resources_alloc - * @adapter: pointer to our private adapter structure - * @pMpRfd: pointer to a RFD - * - * Returns 0 on success and errno on failure (as defined in errno.h) - */ -int et131x_rfd_resources_alloc(struct et131x_adapter *adapter, MP_RFD *pMpRfd) -{ - pMpRfd->Packet = NULL; - - return 0; -} - -/** - * et131x_rfd_resources_free - Free the packet allocated for the given RFD - * @adapter: pointer to our private adapter structure - * @pMpRfd: pointer to a RFD - */ -void et131x_rfd_resources_free(struct et131x_adapter *adapter, MP_RFD *pMpRfd) -{ - pMpRfd->Packet = NULL; - kmem_cache_free(adapter->RxRing.RecvLookaside, pMpRfd); -} - /** * ConfigRxDmaRegs - Start of Rx_DMA init sequence * @etdev: pointer to our adapter structure @@ -659,10 +595,10 @@ void et131x_rfd_resources_free(struct et131x_adapter *adapter, MP_RFD *pMpRfd) void ConfigRxDmaRegs(struct et131x_adapter *etdev) { struct _RXDMA_t __iomem *rx_dma = &etdev->regs->rxdma; - struct _rx_ring_t *pRxLocal = &etdev->RxRing; + struct _rx_ring_t *rx_local = &etdev->RxRing; PFBR_DESC_t fbr_entry; - uint32_t entry; - RXDMA_PSR_NUM_DES_t psr_num_des; + u32 entry; + u32 psr_num_des; unsigned long flags; /* Halt RXDMA to perform the reconfigure. */ @@ -675,36 +611,35 @@ void ConfigRxDmaRegs(struct et131x_adapter *etdev) * are ever returned, make sure the high part is retrieved here * before storing the adjusted address. */ - writel((uint32_t) (pRxLocal->RxStatusRealPA >> 32), + writel((u32) ((u64)rx_local->pRxStatusPa >> 32), &rx_dma->dma_wb_base_hi); - writel((uint32_t) pRxLocal->RxStatusRealPA, &rx_dma->dma_wb_base_lo); + writel((u32) rx_local->pRxStatusPa, &rx_dma->dma_wb_base_lo); - memset(pRxLocal->pRxStatusVa, 0, sizeof(RX_STATUS_BLOCK_t)); + memset(rx_local->pRxStatusVa, 0, sizeof(RX_STATUS_BLOCK_t)); /* Set the address and parameters of the packet status ring into the * 1310's registers */ - writel((uint32_t) (pRxLocal->pPSRingRealPa >> 32), + writel((u32) ((u64)rx_local->pPSRingPa >> 32), &rx_dma->psr_base_hi); - writel((uint32_t) pRxLocal->pPSRingRealPa, &rx_dma->psr_base_lo); - writel(pRxLocal->PsrNumEntries - 1, &rx_dma->psr_num_des.value); - writel(0, &rx_dma->psr_full_offset.value); + writel((u32) rx_local->pPSRingPa, &rx_dma->psr_base_lo); + writel(rx_local->PsrNumEntries - 1, &rx_dma->psr_num_des); + writel(0, &rx_dma->psr_full_offset); - psr_num_des.value = readl(&rx_dma->psr_num_des.value); - writel((psr_num_des.bits.psr_ndes * LO_MARK_PERCENT_FOR_PSR) / 100, - &rx_dma->psr_min_des.value); + psr_num_des = readl(&rx_dma->psr_num_des) & 0xFFF; + writel((psr_num_des * LO_MARK_PERCENT_FOR_PSR) / 100, + &rx_dma->psr_min_des); spin_lock_irqsave(&etdev->RcvLock, flags); /* These local variables track the PSR in the adapter structure */ - pRxLocal->local_psr_full.bits.psr_full = 0; - pRxLocal->local_psr_full.bits.psr_full_wrap = 0; + rx_local->local_psr_full = 0; /* Now's the best time to initialize FBR1 contents */ - fbr_entry = (PFBR_DESC_t) pRxLocal->pFbr1RingVa; - for (entry = 0; entry < pRxLocal->Fbr1NumEntries; entry++) { - fbr_entry->addr_hi = pRxLocal->Fbr[1]->PAHigh[entry]; - fbr_entry->addr_lo = pRxLocal->Fbr[1]->PALow[entry]; + fbr_entry = (PFBR_DESC_t) rx_local->pFbr1RingVa; + for (entry = 0; entry < rx_local->Fbr1NumEntries; entry++) { + fbr_entry->addr_hi = rx_local->Fbr[1]->PAHigh[entry]; + fbr_entry->addr_lo = rx_local->Fbr[1]->PALow[entry]; fbr_entry->word2.bits.bi = entry; fbr_entry++; } @@ -712,39 +647,39 @@ void ConfigRxDmaRegs(struct et131x_adapter *etdev) /* Set the address and parameters of Free buffer ring 1 (and 0 if * required) into the 1310's registers */ - writel((uint32_t) (pRxLocal->Fbr1Realpa >> 32), &rx_dma->fbr1_base_hi); - writel((uint32_t) pRxLocal->Fbr1Realpa, &rx_dma->fbr1_base_lo); - writel(pRxLocal->Fbr1NumEntries - 1, &rx_dma->fbr1_num_des.value); + writel((u32) (rx_local->Fbr1Realpa >> 32), &rx_dma->fbr1_base_hi); + writel((u32) rx_local->Fbr1Realpa, &rx_dma->fbr1_base_lo); + writel(rx_local->Fbr1NumEntries - 1, &rx_dma->fbr1_num_des); writel(ET_DMA10_WRAP, &rx_dma->fbr1_full_offset); /* This variable tracks the free buffer ring 1 full position, so it * has to match the above. */ - pRxLocal->local_Fbr1_full = ET_DMA10_WRAP; - writel(((pRxLocal->Fbr1NumEntries * LO_MARK_PERCENT_FOR_RX) / 100) - 1, - &rx_dma->fbr1_min_des.value); + rx_local->local_Fbr1_full = ET_DMA10_WRAP; + writel(((rx_local->Fbr1NumEntries * LO_MARK_PERCENT_FOR_RX) / 100) - 1, + &rx_dma->fbr1_min_des); #ifdef USE_FBR0 /* Now's the best time to initialize FBR0 contents */ - fbr_entry = (PFBR_DESC_t) pRxLocal->pFbr0RingVa; - for (entry = 0; entry < pRxLocal->Fbr0NumEntries; entry++) { - fbr_entry->addr_hi = pRxLocal->Fbr[0]->PAHigh[entry]; - fbr_entry->addr_lo = pRxLocal->Fbr[0]->PALow[entry]; + fbr_entry = (PFBR_DESC_t) rx_local->pFbr0RingVa; + for (entry = 0; entry < rx_local->Fbr0NumEntries; entry++) { + fbr_entry->addr_hi = rx_local->Fbr[0]->PAHigh[entry]; + fbr_entry->addr_lo = rx_local->Fbr[0]->PALow[entry]; fbr_entry->word2.bits.bi = entry; fbr_entry++; } - writel((uint32_t) (pRxLocal->Fbr0Realpa >> 32), &rx_dma->fbr0_base_hi); - writel((uint32_t) pRxLocal->Fbr0Realpa, &rx_dma->fbr0_base_lo); - writel(pRxLocal->Fbr0NumEntries - 1, &rx_dma->fbr0_num_des.value); + writel((u32) (rx_local->Fbr0Realpa >> 32), &rx_dma->fbr0_base_hi); + writel((u32) rx_local->Fbr0Realpa, &rx_dma->fbr0_base_lo); + writel(rx_local->Fbr0NumEntries - 1, &rx_dma->fbr0_num_des); writel(ET_DMA10_WRAP, &rx_dma->fbr0_full_offset); /* This variable tracks the free buffer ring 0 full position, so it * has to match the above. */ - pRxLocal->local_Fbr0_full = ET_DMA10_WRAP; - writel(((pRxLocal->Fbr0NumEntries * LO_MARK_PERCENT_FOR_RX) / 100) - 1, - &rx_dma->fbr0_min_des.value); + rx_local->local_Fbr0_full = ET_DMA10_WRAP; + writel(((rx_local->Fbr0NumEntries * LO_MARK_PERCENT_FOR_RX) / 100) - 1, + &rx_dma->fbr0_min_des); #endif /* Program the number of packets we will receive before generating an @@ -752,14 +687,14 @@ void ConfigRxDmaRegs(struct et131x_adapter *etdev) * For version B silicon, this value gets updated once autoneg is *complete. */ - writel(PARM_RX_NUM_BUFS_DEF, &rx_dma->num_pkt_done.value); + writel(PARM_RX_NUM_BUFS_DEF, &rx_dma->num_pkt_done); /* The "time_done" is not working correctly to coalesce interrupts * after a given time period, but rather is giving us an interrupt * regardless of whether we have received packets. * This value gets updated once autoneg is complete. */ - writel(PARM_RX_TIME_INT_DEF, &rx_dma->max_pkt_time.value); + writel(PARM_RX_TIME_INT_DEF, &rx_dma->max_pkt_time); spin_unlock_irqrestore(&etdev->RcvLock, flags); } @@ -775,8 +710,8 @@ void SetRxDmaTimer(struct et131x_adapter *etdev) */ if ((etdev->linkspeed == TRUEPHY_SPEED_100MBPS) || (etdev->linkspeed == TRUEPHY_SPEED_10MBPS)) { - writel(0, &etdev->regs->rxdma.max_pkt_time.value); - writel(1, &etdev->regs->rxdma.num_pkt_done.value); + writel(0, &etdev->regs->rxdma.max_pkt_time); + writel(1, &etdev->regs->rxdma.num_pkt_done); } } @@ -807,40 +742,35 @@ void et131x_rx_dma_disable(struct et131x_adapter *etdev) */ void et131x_rx_dma_enable(struct et131x_adapter *etdev) { - if (etdev->RegistryPhyLoopbk) - /* RxDMA is disabled for loopback operation. */ - writel(0x1, &etdev->regs->rxdma.csr.value); - else { /* Setup the receive dma configuration register for normal operation */ - RXDMA_CSR_t csr = { 0 }; - - csr.bits.fbr1_enable = 1; - if (etdev->RxRing.Fbr1BufferSize == 4096) - csr.bits.fbr1_size = 1; - else if (etdev->RxRing.Fbr1BufferSize == 8192) - csr.bits.fbr1_size = 2; - else if (etdev->RxRing.Fbr1BufferSize == 16384) - csr.bits.fbr1_size = 3; + RXDMA_CSR_t csr = { 0 }; + + csr.bits.fbr1_enable = 1; + if (etdev->RxRing.Fbr1BufferSize == 4096) + csr.bits.fbr1_size = 1; + else if (etdev->RxRing.Fbr1BufferSize == 8192) + csr.bits.fbr1_size = 2; + else if (etdev->RxRing.Fbr1BufferSize == 16384) + csr.bits.fbr1_size = 3; #ifdef USE_FBR0 - csr.bits.fbr0_enable = 1; - if (etdev->RxRing.Fbr0BufferSize == 256) - csr.bits.fbr0_size = 1; - else if (etdev->RxRing.Fbr0BufferSize == 512) - csr.bits.fbr0_size = 2; - else if (etdev->RxRing.Fbr0BufferSize == 1024) - csr.bits.fbr0_size = 3; + csr.bits.fbr0_enable = 1; + if (etdev->RxRing.Fbr0BufferSize == 256) + csr.bits.fbr0_size = 1; + else if (etdev->RxRing.Fbr0BufferSize == 512) + csr.bits.fbr0_size = 2; + else if (etdev->RxRing.Fbr0BufferSize == 1024) + csr.bits.fbr0_size = 3; #endif - writel(csr.value, &etdev->regs->rxdma.csr.value); + writel(csr.value, &etdev->regs->rxdma.csr.value); + csr.value = readl(&etdev->regs->rxdma.csr.value); + if (csr.bits.halt_status != 0) { + udelay(5); csr.value = readl(&etdev->regs->rxdma.csr.value); if (csr.bits.halt_status != 0) { - udelay(5); - csr.value = readl(&etdev->regs->rxdma.csr.value); - if (csr.bits.halt_status != 0) { - dev_err(&etdev->pdev->dev, - "RX Dma failed to exit halt state. CSR 0x%08x\n", - csr.value); - } + dev_err(&etdev->pdev->dev, + "RX Dma failed to exit halt state. CSR 0x%08x\n", + csr.value); } } } @@ -849,7 +779,7 @@ void et131x_rx_dma_enable(struct et131x_adapter *etdev) * nic_rx_pkts - Checks the hardware for available packets * @etdev: pointer to our adapter * - * Returns pMpRfd, a pointer to our MPRFD. + * Returns rfd, a pointer to our MPRFD. * * Checks the hardware for available packets, using completion ring * If packets are available, it gets an RFD from the RecvList, attaches @@ -858,119 +788,122 @@ void et131x_rx_dma_enable(struct et131x_adapter *etdev) */ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev) { - struct _rx_ring_t *pRxLocal = &etdev->RxRing; - PRX_STATUS_BLOCK_t pRxStatusBlock; - PPKT_STAT_DESC_t pPSREntry; - PMP_RFD pMpRfd; - uint32_t nIndex; - uint8_t *pBufVa; + struct _rx_ring_t *rx_local = &etdev->RxRing; + PRX_STATUS_BLOCK_t status; + PPKT_STAT_DESC_t psr; + PMP_RFD rfd; + u32 i; + uint8_t *buf; unsigned long flags; struct list_head *element; - uint8_t ringIndex; - uint16_t bufferIndex; - uint32_t localLen; + uint8_t rindex; + uint16_t bindex; + u32 len; PKT_STAT_DESC_WORD0_t Word0; /* RX Status block is written by the DMA engine prior to every * interrupt. It contains the next to be used entry in the Packet * Status Ring, and also the two Free Buffer rings. */ - pRxStatusBlock = (PRX_STATUS_BLOCK_t) pRxLocal->pRxStatusVa; + status = (PRX_STATUS_BLOCK_t) rx_local->pRxStatusVa; - if (pRxStatusBlock->Word1.bits.PSRoffset == - pRxLocal->local_psr_full.bits.psr_full && - pRxStatusBlock->Word1.bits.PSRwrap == - pRxLocal->local_psr_full.bits.psr_full_wrap) { + /* FIXME: tidy later when conversions complete */ + if (status->Word1.bits.PSRoffset == + (rx_local->local_psr_full & 0xFFF) && + status->Word1.bits.PSRwrap == + ((rx_local->local_psr_full >> 12) & 1)) { /* Looks like this ring is not updated yet */ return NULL; } /* The packet status ring indicates that data is available. */ - pPSREntry = (PPKT_STAT_DESC_t) (pRxLocal->pPSRingVa) + - pRxLocal->local_psr_full.bits.psr_full; + psr = (PPKT_STAT_DESC_t) (rx_local->pPSRingVa) + + (rx_local->local_psr_full & 0xFFF); /* Grab any information that is required once the PSR is * advanced, since we can no longer rely on the memory being * accurate */ - localLen = pPSREntry->word1.bits.length; - ringIndex = (uint8_t) pPSREntry->word1.bits.ri; - bufferIndex = (uint16_t) pPSREntry->word1.bits.bi; - Word0 = pPSREntry->word0; + len = psr->word1.bits.length; + rindex = (uint8_t) psr->word1.bits.ri; + bindex = (uint16_t) psr->word1.bits.bi; + Word0 = psr->word0; /* Indicate that we have used this PSR entry. */ - if (++pRxLocal->local_psr_full.bits.psr_full > - pRxLocal->PsrNumEntries - 1) { - pRxLocal->local_psr_full.bits.psr_full = 0; - pRxLocal->local_psr_full.bits.psr_full_wrap ^= 1; + /* FIXME wrap 12 */ + rx_local->local_psr_full = (rx_local->local_psr_full + 1) & 0xFFF; + if (rx_local->local_psr_full > rx_local->PsrNumEntries - 1) { + /* Clear psr full and toggle the wrap bit */ + rx_local->local_psr_full &= 0xFFF; + rx_local->local_psr_full ^= 0x1000; } - writel(pRxLocal->local_psr_full.value, - &etdev->regs->rxdma.psr_full_offset.value); + writel(rx_local->local_psr_full, + &etdev->regs->rxdma.psr_full_offset); #ifndef USE_FBR0 - if (ringIndex != 1) { + if (rindex != 1) { return NULL; } #endif #ifdef USE_FBR0 - if (ringIndex > 1 || - (ringIndex == 0 && - bufferIndex > pRxLocal->Fbr0NumEntries - 1) || - (ringIndex == 1 && - bufferIndex > pRxLocal->Fbr1NumEntries - 1)) + if (rindex > 1 || + (rindex == 0 && + bindex > rx_local->Fbr0NumEntries - 1) || + (rindex == 1 && + bindex > rx_local->Fbr1NumEntries - 1)) #else - if (ringIndex != 1 || - bufferIndex > pRxLocal->Fbr1NumEntries - 1) + if (rindex != 1 || + bindex > rx_local->Fbr1NumEntries - 1) #endif { /* Illegal buffer or ring index cannot be used by S/W*/ dev_err(&etdev->pdev->dev, "NICRxPkts PSR Entry %d indicates " "length of %d and/or bad bi(%d)\n", - pRxLocal->local_psr_full.bits.psr_full, - localLen, bufferIndex); + rx_local->local_psr_full & 0xFFF, + len, bindex); return NULL; } /* Get and fill the RFD. */ spin_lock_irqsave(&etdev->RcvLock, flags); - pMpRfd = NULL; - element = pRxLocal->RecvList.next; - pMpRfd = (PMP_RFD) list_entry(element, MP_RFD, list_node); + rfd = NULL; + element = rx_local->RecvList.next; + rfd = (PMP_RFD) list_entry(element, MP_RFD, list_node); - if (pMpRfd == NULL) { + if (rfd == NULL) { spin_unlock_irqrestore(&etdev->RcvLock, flags); return NULL; } - list_del(&pMpRfd->list_node); - pRxLocal->nReadyRecv--; + list_del(&rfd->list_node); + rx_local->nReadyRecv--; spin_unlock_irqrestore(&etdev->RcvLock, flags); - pMpRfd->bufferindex = bufferIndex; - pMpRfd->ringindex = ringIndex; + rfd->bufferindex = bindex; + rfd->ringindex = rindex; /* In V1 silicon, there is a bug which screws up filtering of * runt packets. Therefore runt packet filtering is disabled * in the MAC and the packets are dropped here. They are * also counted here. */ - if (localLen < (NIC_MIN_PACKET_SIZE + 4)) { + if (len < (NIC_MIN_PACKET_SIZE + 4)) { etdev->Stats.other_errors++; - localLen = 0; + len = 0; } - if (localLen) { + if (len) { if (etdev->ReplicaPhyLoopbk == 1) { - pBufVa = pRxLocal->Fbr[ringIndex]->Va[bufferIndex]; + buf = rx_local->Fbr[rindex]->Va[bindex]; - if (memcmp(&pBufVa[6], &etdev->CurrentAddress[0], + if (memcmp(&buf[6], &etdev->CurrentAddress[0], ETH_ALEN) == 0) { - if (memcmp(&pBufVa[42], "Replica packet", + if (memcmp(&buf[42], "Replica packet", ETH_HLEN)) { etdev->ReplicaPhyLoopbkPF = 1; } @@ -990,28 +923,28 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev) if ((etdev->PacketFilter & ET131X_PACKET_TYPE_MULTICAST) && !(etdev->PacketFilter & ET131X_PACKET_TYPE_PROMISCUOUS) && !(etdev->PacketFilter & ET131X_PACKET_TYPE_ALL_MULTICAST)) { - pBufVa = pRxLocal->Fbr[ringIndex]-> - Va[bufferIndex]; + buf = rx_local->Fbr[rindex]-> + Va[bindex]; /* Loop through our list to see if the * destination address of this packet * matches one in our list. */ - for (nIndex = 0; - nIndex < etdev->MCAddressCount; - nIndex++) { - if (pBufVa[0] == - etdev->MCList[nIndex][0] - && pBufVa[1] == - etdev->MCList[nIndex][1] - && pBufVa[2] == - etdev->MCList[nIndex][2] - && pBufVa[3] == - etdev->MCList[nIndex][3] - && pBufVa[4] == - etdev->MCList[nIndex][4] - && pBufVa[5] == - etdev->MCList[nIndex][5]) { + for (i = 0; + i < etdev->MCAddressCount; + i++) { + if (buf[0] == + etdev->MCList[i][0] + && buf[1] == + etdev->MCList[i][1] + && buf[2] == + etdev->MCList[i][2] + && buf[3] == + etdev->MCList[i][3] + && buf[4] == + etdev->MCList[i][4] + && buf[5] == + etdev->MCList[i][5]) { break; } } @@ -1024,11 +957,11 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev) * so we free our RFD when we return * from this function. */ - if (nIndex == etdev->MCAddressCount) - localLen = 0; + if (i == etdev->MCAddressCount) + len = 0; } - if (localLen > 0) + if (len > 0) etdev->Stats.multircv++; } else if (Word0.value & ALCATEL_BROADCAST_PKT) etdev->Stats.brdcstrcv++; @@ -1041,24 +974,24 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev) etdev->Stats.unircv++; } - if (localLen > 0) { + if (len > 0) { struct sk_buff *skb = NULL; - /* pMpRfd->PacketSize = localLen - 4; */ - pMpRfd->PacketSize = localLen; + /* rfd->PacketSize = len - 4; */ + rfd->PacketSize = len; - skb = dev_alloc_skb(pMpRfd->PacketSize + 2); + skb = dev_alloc_skb(rfd->PacketSize + 2); if (!skb) { dev_err(&etdev->pdev->dev, "Couldn't alloc an SKB for Rx\n"); return NULL; } - etdev->net_stats.rx_bytes += pMpRfd->PacketSize; + etdev->net_stats.rx_bytes += rfd->PacketSize; - memcpy(skb_put(skb, pMpRfd->PacketSize), - pRxLocal->Fbr[ringIndex]->Va[bufferIndex], - pMpRfd->PacketSize); + memcpy(skb_put(skb, rfd->PacketSize), + rx_local->Fbr[rindex]->Va[bindex], + rfd->PacketSize); skb->dev = etdev->netdev; skb->protocol = eth_type_trans(skb, etdev->netdev); @@ -1066,11 +999,11 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev) netif_rx(skb); } else { - pMpRfd->PacketSize = 0; + rfd->PacketSize = 0; } - nic_return_rfd(etdev, pMpRfd); - return pMpRfd; + nic_return_rfd(etdev, rfd); + return rfd; } /** @@ -1081,21 +1014,8 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev) */ void et131x_reset_recv(struct et131x_adapter *etdev) { - PMP_RFD pMpRfd; - struct list_head *element; - WARN_ON(list_empty(&etdev->RxRing.RecvList)); - /* Take all the RFD's from the pending list, and stick them on the - * RecvList. - */ - while (!list_empty(&etdev->RxRing.RecvPendingList)) { - element = etdev->RxRing.RecvPendingList.next; - - pMpRfd = (PMP_RFD) list_entry(element, MP_RFD, list_node); - - list_move_tail(&pMpRfd->list_node, &etdev->RxRing.RecvList); - } } /** @@ -1106,27 +1026,21 @@ void et131x_reset_recv(struct et131x_adapter *etdev) */ void et131x_handle_recv_interrupt(struct et131x_adapter *etdev) { - PMP_RFD pMpRfd = NULL; - struct sk_buff *PacketArray[NUM_PACKETS_HANDLED]; - PMP_RFD RFDFreeArray[NUM_PACKETS_HANDLED]; - uint32_t PacketArrayCount = 0; - uint32_t PacketsToHandle; - uint32_t PacketFreeCount = 0; - bool TempUnfinishedRec = false; - - PacketsToHandle = NUM_PACKETS_HANDLED; + PMP_RFD rfd = NULL; + u32 count = 0; + bool done = true; /* Process up to available RFD's */ - while (PacketArrayCount < PacketsToHandle) { + while (count < NUM_PACKETS_HANDLED) { if (list_empty(&etdev->RxRing.RecvList)) { WARN_ON(etdev->RxRing.nReadyRecv != 0); - TempUnfinishedRec = true; + done = false; break; } - pMpRfd = nic_rx_pkts(etdev); + rfd = nic_rx_pkts(etdev); - if (pMpRfd == NULL) + if (rfd == NULL) break; /* Do not receive any packets until a filter has been set. @@ -1136,7 +1050,7 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *etdev) */ if (!etdev->PacketFilter || !(etdev->Flags & fMP_ADAPTER_LINK_DETECTION) || - pMpRfd->PacketSize == 0) { + rfd->PacketSize == 0) { continue; } @@ -1144,35 +1058,20 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *etdev) etdev->Stats.ipackets++; /* Set the status on the packet, either resources or success */ - if (etdev->RxRing.nReadyRecv >= RFD_LOW_WATER_MARK) { - /* Put this RFD on the pending list - * - * NOTE: nic_rx_pkts() above is already returning the - * RFD to the RecvList, so don't additionally do that - * here. - * Besides, we don't really need (at this point) the - * pending list anyway. - */ - } else { - RFDFreeArray[PacketFreeCount] = pMpRfd; - PacketFreeCount++; - + if (etdev->RxRing.nReadyRecv < RFD_LOW_WATER_MARK) { dev_warn(&etdev->pdev->dev, "RFD's are running out\n"); } - - PacketArray[PacketArrayCount] = pMpRfd->Packet; - PacketArrayCount++; + count++; } - if ((PacketArrayCount == NUM_PACKETS_HANDLED) || TempUnfinishedRec) { + if (count == NUM_PACKETS_HANDLED || !done) { etdev->RxRing.UnfinishedReceives = true; writel(PARM_TX_TIME_INT_DEF * NANO_IN_A_MICRO, &etdev->regs->global.watchdog_timer); - } else { + } else /* Watchdog timer will disable itself if appropriate. */ etdev->RxRing.UnfinishedReceives = false; - } } static inline u32 bump_fbr(u32 *fbr, u32 limit) @@ -1196,14 +1095,14 @@ static inline u32 bump_fbr(u32 *fbr, u32 limit) /** * NICReturnRFD - Recycle a RFD and put it back onto the receive list * @etdev: pointer to our adapter - * @pMpRfd: pointer to the RFD + * @rfd: pointer to the RFD */ -void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD pMpRfd) +void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD rfd) { struct _rx_ring_t *rx_local = &etdev->RxRing; struct _RXDMA_t __iomem *rx_dma = &etdev->regs->rxdma; - uint16_t bi = pMpRfd->bufferindex; - uint8_t ri = pMpRfd->ringindex; + uint16_t bi = rfd->bufferindex; + uint8_t ri = rfd->ringindex; unsigned long flags; /* We don't use any of the OOB data besides status. Otherwise, we @@ -1217,7 +1116,7 @@ void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD pMpRfd) spin_lock_irqsave(&etdev->FbrLock, flags); if (ri == 1) { - PFBR_DESC_t pNextDesc = + PFBR_DESC_t next = (PFBR_DESC_t) (rx_local->pFbr1RingVa) + INDEX10(rx_local->local_Fbr1_full); @@ -1225,9 +1124,9 @@ void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD pMpRfd) * the PA / Buffer Index for the returned buffer into * the oldest (next to be freed)FBR entry */ - pNextDesc->addr_hi = rx_local->Fbr[1]->PAHigh[bi]; - pNextDesc->addr_lo = rx_local->Fbr[1]->PALow[bi]; - pNextDesc->word2.value = bi; + next->addr_hi = rx_local->Fbr[1]->PAHigh[bi]; + next->addr_lo = rx_local->Fbr[1]->PALow[bi]; + next->word2.value = bi; writel(bump_fbr(&rx_local->local_Fbr1_full, rx_local->Fbr1NumEntries - 1), @@ -1235,7 +1134,7 @@ void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD pMpRfd) } #ifdef USE_FBR0 else { - PFBR_DESC_t pNextDesc = + PFBR_DESC_t next = (PFBR_DESC_t) rx_local->pFbr0RingVa + INDEX10(rx_local->local_Fbr0_full); @@ -1243,9 +1142,9 @@ void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD pMpRfd) * the PA / Buffer Index for the returned buffer into * the oldest (next to be freed) FBR entry */ - pNextDesc->addr_hi = rx_local->Fbr[0]->PAHigh[bi]; - pNextDesc->addr_lo = rx_local->Fbr[0]->PALow[bi]; - pNextDesc->word2.value = bi; + next->addr_hi = rx_local->Fbr[0]->PAHigh[bi]; + next->addr_lo = rx_local->Fbr[0]->PALow[bi]; + next->word2.value = bi; writel(bump_fbr(&rx_local->local_Fbr0_full, rx_local->Fbr0NumEntries - 1), @@ -1262,7 +1161,7 @@ void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD pMpRfd) * our list */ spin_lock_irqsave(&etdev->RcvLock, flags); - list_add_tail(&pMpRfd->list_node, &rx_local->RecvList); + list_add_tail(&rfd->list_node, &rx_local->RecvList); rx_local->nReadyRecv++; spin_unlock_irqrestore(&etdev->RcvLock, flags); diff --git a/drivers/staging/et131x/et1310_rx.h b/drivers/staging/et131x/et1310_rx.h index 72a522985270012f04fc938b34859fc7b66f6010..69514593612c006bcfed7cf5b3c07b4b13aa5e11 100644 --- a/drivers/staging/et131x/et1310_rx.h +++ b/drivers/staging/et131x/et1310_rx.h @@ -209,36 +209,26 @@ typedef struct _PKT_STAT_DESC_t { /* Typedefs for the RX DMA status word */ /* - * RXSTAT_WORD0_t structure holds part of the status bits of the Rx DMA engine + * rx status word 0 holds part of the status bits of the Rx DMA engine * that get copied out to memory by the ET-1310. Word 0 is a 32 bit word - * whichcontains Free Buffer ring 0 and 1 available offset. + * which contains the Free Buffer ring 0 and 1 available offset. + * + * bit 0-9 FBR1 offset + * bit 10 Wrap flag for FBR1 + * bit 16-25 FBR0 offset + * bit 26 Wrap flag for FBR0 */ -typedef union _rxstat_word0_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 FBR1unused:5; /* bits 27-31 */ - u32 FBR1wrap:1; /* bit 26 */ - u32 FBR1offset:10; /* bits 16-25 */ - u32 FBR0unused:5; /* bits 11-15 */ - u32 FBR0wrap:1; /* bit 10 */ - u32 FBR0offset:10; /* bits 0-9 */ -#else - u32 FBR0offset:10; /* bits 0-9 */ - u32 FBR0wrap:1; /* bit 10 */ - u32 FBR0unused:5; /* bits 11-15 */ - u32 FBR1offset:10; /* bits 16-25 */ - u32 FBR1wrap:1; /* bit 26 */ - u32 FBR1unused:5; /* bits 27-31 */ -#endif - } bits; -} RXSTAT_WORD0_t, *PRXSTAT_WORD0_t; /* * RXSTAT_WORD1_t structure holds part of the status bits of the Rx DMA engine * that get copied out to memory by the ET-1310. Word 3 is a 32 bit word * which contains the Packet Status Ring available offset. */ + +#define RXSTAT1_OFFSET 16 +#define RXSTAT1_MASK 0xFFF +#define RXSTAT1_WRAP 0x10000000 + typedef union _rxstat_word1_t { u32 value; struct { @@ -261,7 +251,7 @@ typedef union _rxstat_word1_t { * it sits in free memory, and is pointed to by 0x101c / 0x1020 */ typedef struct _rx_status_block_t { - RXSTAT_WORD0_t Word0; + u32 Word0; RXSTAT_WORD1_t Word1; } RX_STATUS_BLOCK_t, *PRX_STATUS_BLOCK_t; @@ -281,15 +271,6 @@ typedef enum { FOUR_PACKET_INTERRUPT } eRX_INTERRUPT_STATE_t, *PeRX_INTERRUPT_STATE_t; -/* - * Structure to hold the skb's in a list - */ -typedef struct rx_skb_list_elem { - struct list_head skb_list_elem; - dma_addr_t dma_addr; - struct sk_buff *skb; -} RX_SKB_LIST_ELEM, *PRX_SKB_LIST_ELEM; - /* * RX_RING_t is sructure representing the adaptor's local reference(s) to the * rings @@ -319,21 +300,16 @@ typedef struct _rx_ring_t { void *pPSRingVa; dma_addr_t pPSRingPa; - uint64_t pPSRingRealPa; - uint64_t pPSRingOffset; - RXDMA_PSR_FULL_OFFSET_t local_psr_full; + u32 local_psr_full; u32 PsrNumEntries; void *pRxStatusVa; dma_addr_t pRxStatusPa; - uint64_t RxStatusRealPA; - uint64_t RxStatusOffset; struct list_head RecvBufferPool; /* RECV */ struct list_head RecvList; - struct list_head RecvPendingList; u32 nReadyRecv; u32 NumRfd; diff --git a/drivers/staging/et131x/et1310_tx.c b/drivers/staging/et131x/et1310_tx.c index 94f7752e2cccd661f6b14ad00cae23e21fbdb129..977e8b34e7a66a2039bab7ba829f71019f39c8bd 100644 --- a/drivers/staging/et131x/et1310_tx.c +++ b/drivers/staging/et131x/et1310_tx.c @@ -94,13 +94,11 @@ #include "et1310_tx.h" -static void et131x_update_tcb_list(struct et131x_adapter *etdev); -static void et131x_check_send_wait_list(struct et131x_adapter *etdev); static inline void et131x_free_send_packet(struct et131x_adapter *etdev, - PMP_TCB pMpTcb); + struct tcb *tcb); static int et131x_send_packet(struct sk_buff *skb, struct et131x_adapter *etdev); -static int nic_send_packet(struct et131x_adapter *etdev, PMP_TCB pMpTcb); +static int nic_send_packet(struct et131x_adapter *etdev, struct tcb *tcb); /** * et131x_tx_dma_memory_alloc @@ -117,12 +115,12 @@ static int nic_send_packet(struct et131x_adapter *etdev, PMP_TCB pMpTcb); int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter) { int desc_size = 0; - TX_RING_t *tx_ring = &adapter->TxRing; + struct tx_ring *tx_ring = &adapter->tx_ring; /* Allocate memory for the TCB's (Transmit Control Block) */ - adapter->TxRing.MpTcbMem = (MP_TCB *)kcalloc(NUM_TCB, sizeof(MP_TCB), - GFP_ATOMIC | GFP_DMA); - if (!adapter->TxRing.MpTcbMem) { + adapter->tx_ring.tcb_ring = (struct tcb *) + kcalloc(NUM_TCB, sizeof(struct tcb), GFP_ATOMIC | GFP_DMA); + if (!adapter->tx_ring.tcb_ring) { dev_err(&adapter->pdev->dev, "Cannot alloc memory for TCBs\n"); return -ENOMEM; } @@ -130,12 +128,13 @@ int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter) /* Allocate enough memory for the Tx descriptor ring, and allocate * some extra so that the ring can be aligned on a 4k boundary. */ - desc_size = (sizeof(TX_DESC_ENTRY_t) * NUM_DESC_PER_RING_TX) + 4096 - 1; - tx_ring->pTxDescRingVa = - (PTX_DESC_ENTRY_t) pci_alloc_consistent(adapter->pdev, desc_size, - &tx_ring->pTxDescRingPa); - if (!adapter->TxRing.pTxDescRingVa) { - dev_err(&adapter->pdev->dev, "Cannot alloc memory for Tx Ring\n"); + desc_size = (sizeof(struct tx_desc) * NUM_DESC_PER_RING_TX) + 4096 - 1; + tx_ring->tx_desc_ring = + (struct tx_desc *) pci_alloc_consistent(adapter->pdev, desc_size, + &tx_ring->tx_desc_ring_pa); + if (!adapter->tx_ring.tx_desc_ring) { + dev_err(&adapter->pdev->dev, + "Cannot alloc memory for Tx Ring\n"); return -ENOMEM; } @@ -146,35 +145,15 @@ int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter) * are ever returned, make sure the high part is retrieved here before * storing the adjusted address. */ - tx_ring->pTxDescRingAdjustedPa = tx_ring->pTxDescRingPa; - - /* Align Tx Descriptor Ring on a 4k (0x1000) byte boundary */ - et131x_align_allocated_memory(adapter, - &tx_ring->pTxDescRingAdjustedPa, - &tx_ring->TxDescOffset, 0x0FFF); - - tx_ring->pTxDescRingVa += tx_ring->TxDescOffset; - /* Allocate memory for the Tx status block */ - tx_ring->pTxStatusVa = pci_alloc_consistent(adapter->pdev, - sizeof(TX_STATUS_BLOCK_t), - &tx_ring->pTxStatusPa); - if (!adapter->TxRing.pTxStatusPa) { + tx_ring->tx_status = pci_alloc_consistent(adapter->pdev, + sizeof(u32), + &tx_ring->tx_status_pa); + if (!adapter->tx_ring.tx_status_pa) { dev_err(&adapter->pdev->dev, "Cannot alloc memory for Tx status block\n"); return -ENOMEM; } - - /* Allocate memory for a dummy buffer */ - tx_ring->pTxDummyBlkVa = pci_alloc_consistent(adapter->pdev, - NIC_MIN_PACKET_SIZE, - &tx_ring->pTxDummyBlkPa); - if (!adapter->TxRing.pTxDummyBlkPa) { - dev_err(&adapter->pdev->dev, - "Cannot alloc memory for Tx dummy buffer\n"); - return -ENOMEM; - } - return 0; } @@ -188,76 +167,59 @@ void et131x_tx_dma_memory_free(struct et131x_adapter *adapter) { int desc_size = 0; - if (adapter->TxRing.pTxDescRingVa) { + if (adapter->tx_ring.tx_desc_ring) { /* Free memory relating to Tx rings here */ - adapter->TxRing.pTxDescRingVa -= adapter->TxRing.TxDescOffset; - - desc_size = - (sizeof(TX_DESC_ENTRY_t) * NUM_DESC_PER_RING_TX) + 4096 - 1; - + desc_size = (sizeof(struct tx_desc) * NUM_DESC_PER_RING_TX) + + 4096 - 1; pci_free_consistent(adapter->pdev, desc_size, - adapter->TxRing.pTxDescRingVa, - adapter->TxRing.pTxDescRingPa); - - adapter->TxRing.pTxDescRingVa = NULL; + adapter->tx_ring.tx_desc_ring, + adapter->tx_ring.tx_desc_ring_pa); + adapter->tx_ring.tx_desc_ring = NULL; } /* Free memory for the Tx status block */ - if (adapter->TxRing.pTxStatusVa) { - pci_free_consistent(adapter->pdev, - sizeof(TX_STATUS_BLOCK_t), - adapter->TxRing.pTxStatusVa, - adapter->TxRing.pTxStatusPa); - - adapter->TxRing.pTxStatusVa = NULL; - } - - /* Free memory for the dummy buffer */ - if (adapter->TxRing.pTxDummyBlkVa) { + if (adapter->tx_ring.tx_status) { pci_free_consistent(adapter->pdev, - NIC_MIN_PACKET_SIZE, - adapter->TxRing.pTxDummyBlkVa, - adapter->TxRing.pTxDummyBlkPa); + sizeof(u32), + adapter->tx_ring.tx_status, + adapter->tx_ring.tx_status_pa); - adapter->TxRing.pTxDummyBlkVa = NULL; + adapter->tx_ring.tx_status = NULL; } - - /* Free the memory for MP_TCB structures */ - kfree(adapter->TxRing.MpTcbMem); + /* Free the memory for the tcb structures */ + kfree(adapter->tx_ring.tcb_ring); } /** * ConfigTxDmaRegs - Set up the tx dma section of the JAGCore. * @etdev: pointer to our private adapter structure + * + * Configure the transmit engine with the ring buffers we have created + * and prepare it for use. */ void ConfigTxDmaRegs(struct et131x_adapter *etdev) { struct _TXDMA_t __iomem *txdma = &etdev->regs->txdma; /* Load the hardware with the start of the transmit descriptor ring. */ - writel((uint32_t) (etdev->TxRing.pTxDescRingAdjustedPa >> 32), + writel((u32) ((u64)etdev->tx_ring.tx_desc_ring_pa >> 32), &txdma->pr_base_hi); - writel((uint32_t) etdev->TxRing.pTxDescRingAdjustedPa, + writel((u32) etdev->tx_ring.tx_desc_ring_pa, &txdma->pr_base_lo); /* Initialise the transmit DMA engine */ - writel(NUM_DESC_PER_RING_TX - 1, &txdma->pr_num_des.value); + writel(NUM_DESC_PER_RING_TX - 1, &txdma->pr_num_des); - /* Load the completion writeback physical address - * - * NOTE: pci_alloc_consistent(), used above to alloc DMA regions, - * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses - * are ever returned, make sure the high part is retrieved here before - * storing the adjusted address. - */ - writel(0, &txdma->dma_wb_base_hi); - writel(etdev->TxRing.pTxStatusPa, &txdma->dma_wb_base_lo); + /* Load the completion writeback physical address */ + writel((u32)((u64)etdev->tx_ring.tx_status_pa >> 32), + &txdma->dma_wb_base_hi); + writel((u32)etdev->tx_ring.tx_status_pa, &txdma->dma_wb_base_lo); - memset(etdev->TxRing.pTxStatusVa, 0, sizeof(TX_STATUS_BLOCK_t)); + *etdev->tx_ring.tx_status = 0; writel(0, &txdma->service_request); - etdev->TxRing.txDmaReadyToSend = 0; + etdev->tx_ring.send_idx = 0; } /** @@ -279,16 +241,11 @@ void et131x_tx_dma_disable(struct et131x_adapter *etdev) */ void et131x_tx_dma_enable(struct et131x_adapter *etdev) { - u32 csr = ET_TXDMA_SNGL_EPKT; - if (etdev->RegistryPhyLoopbk) - /* TxDMA is disabled for loopback operation. */ - csr |= ET_TXDMA_CSR_HALT; - else - /* Setup the transmit dma configuration register for normal - * operation - */ - csr |= PARM_DMA_CACHE_DEF << ET_TXDMA_CACHE_SHIFT; - writel(csr, &etdev->regs->txdma.csr); + /* Setup the transmit dma configuration register for normal + * operation + */ + writel(ET_TXDMA_SNGL_EPKT|(PARM_DMA_CACHE_DEF << ET_TXDMA_CACHE_SHIFT), + &etdev->regs->txdma.csr); } /** @@ -297,39 +254,32 @@ void et131x_tx_dma_enable(struct et131x_adapter *etdev) */ void et131x_init_send(struct et131x_adapter *adapter) { - PMP_TCB pMpTcb; - uint32_t TcbCount; - TX_RING_t *tx_ring; + struct tcb *tcb; + u32 ct; + struct tx_ring *tx_ring; /* Setup some convenience pointers */ - tx_ring = &adapter->TxRing; - pMpTcb = adapter->TxRing.MpTcbMem; + tx_ring = &adapter->tx_ring; + tcb = adapter->tx_ring.tcb_ring; - tx_ring->TCBReadyQueueHead = pMpTcb; + tx_ring->tcb_qhead = tcb; - /* Go through and set up each TCB */ - for (TcbCount = 0; TcbCount < NUM_TCB; TcbCount++) { - memset(pMpTcb, 0, sizeof(MP_TCB)); + memset(tcb, 0, sizeof(struct tcb) * NUM_TCB); + /* Go through and set up each TCB */ + for (ct = 0; ct++ < NUM_TCB; tcb++) /* Set the link pointer in HW TCB to the next TCB in the - * chain. If this is the last TCB in the chain, also set the - * tail pointer. + * chain */ - if (TcbCount < NUM_TCB - 1) { - pMpTcb->Next = pMpTcb + 1; - } else { - tx_ring->TCBReadyQueueTail = pMpTcb; - pMpTcb->Next = (PMP_TCB) NULL; - } - - pMpTcb++; - } + tcb->next = tcb + 1; + /* Set the tail pointer */ + tcb--; + tx_ring->tcb_qtail = tcb; + tcb->next = NULL; /* Curr send queue should now be empty */ - tx_ring->CurrSendHead = (PMP_TCB) NULL; - tx_ring->CurrSendTail = (PMP_TCB) NULL; - - INIT_LIST_HEAD(&adapter->TxRing.SendWaitQueue); + tx_ring->send_head = NULL; + tx_ring->send_tail = NULL; } /** @@ -352,9 +302,8 @@ int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev) * to Tx, so the PacketCount and it's array used makes no sense here */ - /* Queue is not empty or TCB is not available */ - if (!list_empty(&etdev->TxRing.SendWaitQueue) || - MP_TCB_RESOURCES_NOT_AVAILABLE(etdev)) { + /* TCB is not available */ + if (etdev->tx_ring.used >= NUM_TCB) { /* NOTE: If there's an error on send, no need to queue the * packet under Linux; if we just send an error up to the * netif layer, it will resend the skb to us. @@ -364,27 +313,15 @@ int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev) /* We need to see if the link is up; if it's not, make the * netif layer think we're good and drop the packet */ - /* - * if( MP_SHOULD_FAIL_SEND( etdev ) || - * etdev->DriverNoPhyAccess ) - */ - if (MP_SHOULD_FAIL_SEND(etdev) || etdev->DriverNoPhyAccess - || !netif_carrier_ok(netdev)) { + if ((etdev->Flags & fMP_ADAPTER_FAIL_SEND_MASK) || + !netif_carrier_ok(netdev)) { dev_kfree_skb_any(skb); skb = NULL; etdev->net_stats.tx_dropped++; } else { status = et131x_send_packet(skb, etdev); - - if (status == -ENOMEM) { - - /* NOTE: If there's an error on send, no need - * to queue the packet under Linux; if we just - * send an error up to the netif layer, it - * will resend the skb to us. - */ - } else if (status != 0) { + if (status != 0 && status != -ENOMEM) { /* On any other error, make netif think we're * OK and drop the packet */ @@ -409,87 +346,83 @@ int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev) static int et131x_send_packet(struct sk_buff *skb, struct et131x_adapter *etdev) { - int status = 0; - PMP_TCB pMpTcb = NULL; - uint16_t *shbufva; + int status; + struct tcb *tcb = NULL; + u16 *shbufva; unsigned long flags; /* All packets must have at least a MAC address and a protocol type */ - if (skb->len < ETH_HLEN) { + if (skb->len < ETH_HLEN) return -EIO; - } /* Get a TCB for this packet */ spin_lock_irqsave(&etdev->TCBReadyQLock, flags); - pMpTcb = etdev->TxRing.TCBReadyQueueHead; + tcb = etdev->tx_ring.tcb_qhead; - if (pMpTcb == NULL) { + if (tcb == NULL) { spin_unlock_irqrestore(&etdev->TCBReadyQLock, flags); return -ENOMEM; } - etdev->TxRing.TCBReadyQueueHead = pMpTcb->Next; + etdev->tx_ring.tcb_qhead = tcb->next; - if (etdev->TxRing.TCBReadyQueueHead == NULL) - etdev->TxRing.TCBReadyQueueTail = NULL; + if (etdev->tx_ring.tcb_qhead == NULL) + etdev->tx_ring.tcb_qtail = NULL; spin_unlock_irqrestore(&etdev->TCBReadyQLock, flags); - pMpTcb->PacketLength = skb->len; - pMpTcb->Packet = skb; + tcb->skb = skb; - if ((skb->data != NULL) && ((skb->len - skb->data_len) >= 6)) { - shbufva = (uint16_t *) skb->data; + if (skb->data != NULL && skb->len - skb->data_len >= 6) { + shbufva = (u16 *) skb->data; if ((shbufva[0] == 0xffff) && (shbufva[1] == 0xffff) && (shbufva[2] == 0xffff)) { - pMpTcb->Flags |= fMP_DEST_BROAD; + tcb->flags |= fMP_DEST_BROAD; } else if ((shbufva[0] & 0x3) == 0x0001) { - pMpTcb->Flags |= fMP_DEST_MULTI; + tcb->flags |= fMP_DEST_MULTI; } } - pMpTcb->Next = NULL; + tcb->next = NULL; /* Call the NIC specific send handler. */ - if (status == 0) - status = nic_send_packet(etdev, pMpTcb); + status = nic_send_packet(etdev, tcb); if (status != 0) { spin_lock_irqsave(&etdev->TCBReadyQLock, flags); - if (etdev->TxRing.TCBReadyQueueTail) { - etdev->TxRing.TCBReadyQueueTail->Next = pMpTcb; - } else { + if (etdev->tx_ring.tcb_qtail) + etdev->tx_ring.tcb_qtail->next = tcb; + else /* Apparently ready Q is empty. */ - etdev->TxRing.TCBReadyQueueHead = pMpTcb; - } + etdev->tx_ring.tcb_qhead = tcb; - etdev->TxRing.TCBReadyQueueTail = pMpTcb; + etdev->tx_ring.tcb_qtail = tcb; spin_unlock_irqrestore(&etdev->TCBReadyQLock, flags); return status; } - WARN_ON(etdev->TxRing.nBusySend > NUM_TCB); + WARN_ON(etdev->tx_ring.used > NUM_TCB); return 0; } /** * nic_send_packet - NIC specific send handler for version B silicon. * @etdev: pointer to our adapter - * @pMpTcb: pointer to MP_TCB + * @tcb: pointer to struct tcb * * Returns 0 or errno. */ -static int nic_send_packet(struct et131x_adapter *etdev, PMP_TCB pMpTcb) +static int nic_send_packet(struct et131x_adapter *etdev, struct tcb *tcb) { - uint32_t loopIndex; - TX_DESC_ENTRY_t CurDesc[24]; - uint32_t FragmentNumber = 0; - uint32_t thiscopy, remainder; - struct sk_buff *pPacket = pMpTcb->Packet; - uint32_t FragListCount = skb_shinfo(pPacket)->nr_frags + 1; - struct skb_frag_struct *pFragList = &skb_shinfo(pPacket)->frags[0]; + u32 i; + struct tx_desc desc[24]; /* 24 x 16 byte */ + u32 frag = 0; + u32 thiscopy, remainder; + struct sk_buff *skb = tcb->skb; + u32 nr_frags = skb_shinfo(skb)->nr_frags + 1; + struct skb_frag_struct *frags = &skb_shinfo(skb)->frags[0]; unsigned long flags; /* Part of the optimizations of this send routine restrict us to @@ -500,17 +433,16 @@ static int nic_send_packet(struct et131x_adapter *etdev, PMP_TCB pMpTcb) * number of fragments. If needed, we can call this function, * although it is less efficient. */ - if (FragListCount > 23) { + if (nr_frags > 23) return -EIO; - } - memset(CurDesc, 0, sizeof(TX_DESC_ENTRY_t) * (FragListCount + 1)); + memset(desc, 0, sizeof(struct tx_desc) * (nr_frags + 1)); - for (loopIndex = 0; loopIndex < FragListCount; loopIndex++) { + for (i = 0; i < nr_frags; i++) { /* If there is something in this element, lets get a * descriptor from the ring and get the necessary data */ - if (loopIndex == 0) { + if (i == 0) { /* If the fragments are smaller than a standard MTU, * then map them to a single descriptor in the Tx * Desc ring. However, if they're larger, as is @@ -520,166 +452,164 @@ static int nic_send_packet(struct et131x_adapter *etdev, PMP_TCB pMpTcb) * This will work until we determine why the hardware * doesn't seem to like large fragments. */ - if ((pPacket->len - pPacket->data_len) <= 1514) { - CurDesc[FragmentNumber].DataBufferPtrHigh = 0; - CurDesc[FragmentNumber].word2.bits. - length_in_bytes = - pPacket->len - pPacket->data_len; + if ((skb->len - skb->data_len) <= 1514) { + desc[frag].addr_hi = 0; + /* Low 16bits are length, high is vlan and + unused currently so zero */ + desc[frag].len_vlan = + skb->len - skb->data_len; /* NOTE: Here, the dma_addr_t returned from * pci_map_single() is implicitly cast as a - * uint32_t. Although dma_addr_t can be + * u32. Although dma_addr_t can be * 64-bit, the address returned by * pci_map_single() is always 32-bit * addressable (as defined by the pci/dma * subsystem) */ - CurDesc[FragmentNumber++].DataBufferPtrLow = + desc[frag++].addr_lo = pci_map_single(etdev->pdev, - pPacket->data, - pPacket->len - - pPacket->data_len, + skb->data, + skb->len - + skb->data_len, PCI_DMA_TODEVICE); } else { - CurDesc[FragmentNumber].DataBufferPtrHigh = 0; - CurDesc[FragmentNumber].word2.bits. - length_in_bytes = - ((pPacket->len - pPacket->data_len) / 2); + desc[frag].addr_hi = 0; + desc[frag].len_vlan = + (skb->len - skb->data_len) / 2; /* NOTE: Here, the dma_addr_t returned from * pci_map_single() is implicitly cast as a - * uint32_t. Although dma_addr_t can be + * u32. Although dma_addr_t can be * 64-bit, the address returned by * pci_map_single() is always 32-bit * addressable (as defined by the pci/dma * subsystem) */ - CurDesc[FragmentNumber++].DataBufferPtrLow = + desc[frag++].addr_lo = pci_map_single(etdev->pdev, - pPacket->data, - ((pPacket->len - - pPacket->data_len) / 2), + skb->data, + ((skb->len - + skb->data_len) / 2), PCI_DMA_TODEVICE); - CurDesc[FragmentNumber].DataBufferPtrHigh = 0; + desc[frag].addr_hi = 0; - CurDesc[FragmentNumber].word2.bits. - length_in_bytes = - ((pPacket->len - pPacket->data_len) / 2); + desc[frag].len_vlan = + (skb->len - skb->data_len) / 2; /* NOTE: Here, the dma_addr_t returned from * pci_map_single() is implicitly cast as a - * uint32_t. Although dma_addr_t can be + * u32. Although dma_addr_t can be * 64-bit, the address returned by * pci_map_single() is always 32-bit * addressable (as defined by the pci/dma * subsystem) */ - CurDesc[FragmentNumber++].DataBufferPtrLow = + desc[frag++].addr_lo = pci_map_single(etdev->pdev, - pPacket->data + - ((pPacket->len - - pPacket->data_len) / 2), - ((pPacket->len - - pPacket->data_len) / 2), + skb->data + + ((skb->len - + skb->data_len) / 2), + ((skb->len - + skb->data_len) / 2), PCI_DMA_TODEVICE); } } else { - CurDesc[FragmentNumber].DataBufferPtrHigh = 0; - CurDesc[FragmentNumber].word2.bits.length_in_bytes = - pFragList[loopIndex - 1].size; + desc[frag].addr_hi = 0; + desc[frag].len_vlan = + frags[i - 1].size; /* NOTE: Here, the dma_addr_t returned from - * pci_map_page() is implicitly cast as a uint32_t. + * pci_map_page() is implicitly cast as a u32. * Although dma_addr_t can be 64-bit, the address * returned by pci_map_page() is always 32-bit * addressable (as defined by the pci/dma subsystem) */ - CurDesc[FragmentNumber++].DataBufferPtrLow = + desc[frag++].addr_lo = pci_map_page(etdev->pdev, - pFragList[loopIndex - 1].page, - pFragList[loopIndex - 1].page_offset, - pFragList[loopIndex - 1].size, + frags[i - 1].page, + frags[i - 1].page_offset, + frags[i - 1].size, PCI_DMA_TODEVICE); } } - if (FragmentNumber == 0) + if (frag == 0) return -EIO; if (etdev->linkspeed == TRUEPHY_SPEED_1000MBPS) { - if (++etdev->TxRing.TxPacketsSinceLastinterrupt == - PARM_TX_NUM_BUFS_DEF) { - CurDesc[FragmentNumber - 1].word3.value = 0x5; - etdev->TxRing.TxPacketsSinceLastinterrupt = 0; - } else { - CurDesc[FragmentNumber - 1].word3.value = 0x1; + if (++etdev->tx_ring.since_irq == PARM_TX_NUM_BUFS_DEF) { + /* Last element & Interrupt flag */ + desc[frag - 1].flags = 0x5; + etdev->tx_ring.since_irq = 0; + } else { /* Last element */ + desc[frag - 1].flags = 0x1; } - } else { - CurDesc[FragmentNumber - 1].word3.value = 0x5; - } + } else + desc[frag - 1].flags = 0x5; - CurDesc[0].word3.bits.f = 1; + desc[0].flags |= 2; /* First element flag */ - pMpTcb->WrIndexStart = etdev->TxRing.txDmaReadyToSend; - pMpTcb->PacketStaleCount = 0; + tcb->index_start = etdev->tx_ring.send_idx; + tcb->stale = 0; spin_lock_irqsave(&etdev->SendHWLock, flags); thiscopy = NUM_DESC_PER_RING_TX - - INDEX10(etdev->TxRing.txDmaReadyToSend); + INDEX10(etdev->tx_ring.send_idx); - if (thiscopy >= FragmentNumber) { + if (thiscopy >= frag) { remainder = 0; - thiscopy = FragmentNumber; + thiscopy = frag; } else { - remainder = FragmentNumber - thiscopy; + remainder = frag - thiscopy; } - memcpy(etdev->TxRing.pTxDescRingVa + - INDEX10(etdev->TxRing.txDmaReadyToSend), CurDesc, - sizeof(TX_DESC_ENTRY_t) * thiscopy); + memcpy(etdev->tx_ring.tx_desc_ring + + INDEX10(etdev->tx_ring.send_idx), desc, + sizeof(struct tx_desc) * thiscopy); - add_10bit(&etdev->TxRing.txDmaReadyToSend, thiscopy); + add_10bit(&etdev->tx_ring.send_idx, thiscopy); - if (INDEX10(etdev->TxRing.txDmaReadyToSend)== 0 || - INDEX10(etdev->TxRing.txDmaReadyToSend) == NUM_DESC_PER_RING_TX) { - etdev->TxRing.txDmaReadyToSend &= ~ET_DMA10_MASK; - etdev->TxRing.txDmaReadyToSend ^= ET_DMA10_WRAP; + if (INDEX10(etdev->tx_ring.send_idx) == 0 || + INDEX10(etdev->tx_ring.send_idx) == NUM_DESC_PER_RING_TX) { + etdev->tx_ring.send_idx &= ~ET_DMA10_MASK; + etdev->tx_ring.send_idx ^= ET_DMA10_WRAP; } if (remainder) { - memcpy(etdev->TxRing.pTxDescRingVa, - CurDesc + thiscopy, - sizeof(TX_DESC_ENTRY_t) * remainder); + memcpy(etdev->tx_ring.tx_desc_ring, + desc + thiscopy, + sizeof(struct tx_desc) * remainder); - add_10bit(&etdev->TxRing.txDmaReadyToSend, remainder); + add_10bit(&etdev->tx_ring.send_idx, remainder); } - if (INDEX10(etdev->TxRing.txDmaReadyToSend) == 0) { - if (etdev->TxRing.txDmaReadyToSend) - pMpTcb->WrIndex = NUM_DESC_PER_RING_TX - 1; + if (INDEX10(etdev->tx_ring.send_idx) == 0) { + if (etdev->tx_ring.send_idx) + tcb->index = NUM_DESC_PER_RING_TX - 1; else - pMpTcb->WrIndex= ET_DMA10_WRAP | (NUM_DESC_PER_RING_TX - 1); + tcb->index = ET_DMA10_WRAP|(NUM_DESC_PER_RING_TX - 1); } else - pMpTcb->WrIndex = etdev->TxRing.txDmaReadyToSend - 1; + tcb->index = etdev->tx_ring.send_idx - 1; spin_lock(&etdev->TCBSendQLock); - if (etdev->TxRing.CurrSendTail) - etdev->TxRing.CurrSendTail->Next = pMpTcb; + if (etdev->tx_ring.send_tail) + etdev->tx_ring.send_tail->next = tcb; else - etdev->TxRing.CurrSendHead = pMpTcb; + etdev->tx_ring.send_head = tcb; - etdev->TxRing.CurrSendTail = pMpTcb; + etdev->tx_ring.send_tail = tcb; - WARN_ON(pMpTcb->Next != NULL); + WARN_ON(tcb->next != NULL); - etdev->TxRing.nBusySend++; + etdev->tx_ring.used++; spin_unlock(&etdev->TCBSendQLock); /* Write the new write pointer back to the device. */ - writel(etdev->TxRing.txDmaReadyToSend, + writel(etdev->tx_ring.send_idx, &etdev->regs->txdma.service_request); /* For Gig only, we use Tx Interrupt coalescing. Enable the software @@ -696,72 +626,71 @@ static int nic_send_packet(struct et131x_adapter *etdev, PMP_TCB pMpTcb) /** - * et131x_free_send_packet - Recycle a MP_TCB, complete the packet if necessary + * et131x_free_send_packet - Recycle a struct tcb * @etdev: pointer to our adapter - * @pMpTcb: pointer to MP_TCB + * @tcb: pointer to struct tcb * + * Complete the packet if necessary * Assumption - Send spinlock has been acquired */ inline void et131x_free_send_packet(struct et131x_adapter *etdev, - PMP_TCB pMpTcb) + struct tcb *tcb) { unsigned long flags; - TX_DESC_ENTRY_t *desc = NULL; + struct tx_desc *desc = NULL; struct net_device_stats *stats = &etdev->net_stats; - if (pMpTcb->Flags & fMP_DEST_BROAD) + if (tcb->flags & fMP_DEST_BROAD) atomic_inc(&etdev->Stats.brdcstxmt); - else if (pMpTcb->Flags & fMP_DEST_MULTI) + else if (tcb->flags & fMP_DEST_MULTI) atomic_inc(&etdev->Stats.multixmt); else atomic_inc(&etdev->Stats.unixmt); - if (pMpTcb->Packet) { - stats->tx_bytes += pMpTcb->Packet->len; + if (tcb->skb) { + stats->tx_bytes += tcb->skb->len; /* Iterate through the TX descriptors on the ring * corresponding to this packet and umap the fragments * they point to */ do { - desc = - (TX_DESC_ENTRY_t *) (etdev->TxRing.pTxDescRingVa + - INDEX10(pMpTcb->WrIndexStart)); + desc = (struct tx_desc *)(etdev->tx_ring.tx_desc_ring + + INDEX10(tcb->index_start)); pci_unmap_single(etdev->pdev, - desc->DataBufferPtrLow, - desc->word2.value, PCI_DMA_TODEVICE); - - add_10bit(&pMpTcb->WrIndexStart, 1); - if (INDEX10(pMpTcb->WrIndexStart) >= - NUM_DESC_PER_RING_TX) { - pMpTcb->WrIndexStart &= ~ET_DMA10_MASK; - pMpTcb->WrIndexStart ^= ET_DMA10_WRAP; + desc->addr_lo, + desc->len_vlan, PCI_DMA_TODEVICE); + + add_10bit(&tcb->index_start, 1); + if (INDEX10(tcb->index_start) >= + NUM_DESC_PER_RING_TX) { + tcb->index_start &= ~ET_DMA10_MASK; + tcb->index_start ^= ET_DMA10_WRAP; } - } while (desc != (etdev->TxRing.pTxDescRingVa + - INDEX10(pMpTcb->WrIndex))); + } while (desc != (etdev->tx_ring.tx_desc_ring + + INDEX10(tcb->index))); - dev_kfree_skb_any(pMpTcb->Packet); + dev_kfree_skb_any(tcb->skb); } - memset(pMpTcb, 0, sizeof(MP_TCB)); + memset(tcb, 0, sizeof(struct tcb)); /* Add the TCB to the Ready Q */ spin_lock_irqsave(&etdev->TCBReadyQLock, flags); etdev->Stats.opackets++; - if (etdev->TxRing.TCBReadyQueueTail) { - etdev->TxRing.TCBReadyQueueTail->Next = pMpTcb; - } else { + if (etdev->tx_ring.tcb_qtail) + etdev->tx_ring.tcb_qtail->next = tcb; + else /* Apparently ready Q is empty. */ - etdev->TxRing.TCBReadyQueueHead = pMpTcb; - } + etdev->tx_ring.tcb_qhead = tcb; - etdev->TxRing.TCBReadyQueueTail = pMpTcb; + etdev->tx_ring.tcb_qtail = tcb; spin_unlock_irqrestore(&etdev->TCBReadyQLock, flags); - WARN_ON(etdev->TxRing.nBusySend < 0); + WARN_ON(etdev->tx_ring.used < 0); } /** @@ -772,52 +701,40 @@ inline void et131x_free_send_packet(struct et131x_adapter *etdev, */ void et131x_free_busy_send_packets(struct et131x_adapter *etdev) { - PMP_TCB pMpTcb; - struct list_head *entry; + struct tcb *tcb; unsigned long flags; - uint32_t FreeCounter = 0; - - while (!list_empty(&etdev->TxRing.SendWaitQueue)) { - spin_lock_irqsave(&etdev->SendWaitLock, flags); - - etdev->TxRing.nWaitSend--; - spin_unlock_irqrestore(&etdev->SendWaitLock, flags); - - entry = etdev->TxRing.SendWaitQueue.next; - } - - etdev->TxRing.nWaitSend = 0; + u32 freed = 0; /* Any packets being sent? Check the first TCB on the send list */ spin_lock_irqsave(&etdev->TCBSendQLock, flags); - pMpTcb = etdev->TxRing.CurrSendHead; + tcb = etdev->tx_ring.send_head; - while ((pMpTcb != NULL) && (FreeCounter < NUM_TCB)) { - PMP_TCB pNext = pMpTcb->Next; + while (tcb != NULL && freed < NUM_TCB) { + struct tcb *next = tcb->next; - etdev->TxRing.CurrSendHead = pNext; + etdev->tx_ring.send_head = next; - if (pNext == NULL) - etdev->TxRing.CurrSendTail = NULL; + if (next == NULL) + etdev->tx_ring.send_tail = NULL; - etdev->TxRing.nBusySend--; + etdev->tx_ring.used--; spin_unlock_irqrestore(&etdev->TCBSendQLock, flags); - FreeCounter++; - et131x_free_send_packet(etdev, pMpTcb); + freed++; + et131x_free_send_packet(etdev, tcb); spin_lock_irqsave(&etdev->TCBSendQLock, flags); - pMpTcb = etdev->TxRing.CurrSendHead; + tcb = etdev->tx_ring.send_head; } - WARN_ON(FreeCounter == NUM_TCB); + WARN_ON(freed == NUM_TCB); spin_unlock_irqrestore(&etdev->TCBSendQLock, flags); - etdev->TxRing.nBusySend = 0; + etdev->tx_ring.used = 0; } /** @@ -830,100 +747,57 @@ void et131x_free_busy_send_packets(struct et131x_adapter *etdev) * Assumption - Send spinlock has been acquired */ void et131x_handle_send_interrupt(struct et131x_adapter *etdev) -{ - /* Mark as completed any packets which have been sent by the device. */ - et131x_update_tcb_list(etdev); - - /* If we queued any transmits because we didn't have any TCBs earlier, - * dequeue and send those packets now, as long as we have free TCBs. - */ - et131x_check_send_wait_list(etdev); -} - -/** - * et131x_update_tcb_list - Helper routine for Send Interrupt handler - * @etdev: pointer to our adapter - * - * Re-claims the send resources and completes sends. Can also be called as - * part of the NIC send routine when the "ServiceComplete" indication has - * wrapped. - */ -static void et131x_update_tcb_list(struct et131x_adapter *etdev) { unsigned long flags; - u32 ServiceComplete; - PMP_TCB pMpTcb; + u32 serviced; + struct tcb *tcb; u32 index; - ServiceComplete = readl(&etdev->regs->txdma.NewServiceComplete); - index = INDEX10(ServiceComplete); + serviced = readl(&etdev->regs->txdma.NewServiceComplete); + index = INDEX10(serviced); /* Has the ring wrapped? Process any descriptors that do not have * the same "wrap" indicator as the current completion indicator */ spin_lock_irqsave(&etdev->TCBSendQLock, flags); - pMpTcb = etdev->TxRing.CurrSendHead; + tcb = etdev->tx_ring.send_head; - while (pMpTcb && - ((ServiceComplete ^ pMpTcb->WrIndex) & ET_DMA10_WRAP) && - index < INDEX10(pMpTcb->WrIndex)) { - etdev->TxRing.nBusySend--; - etdev->TxRing.CurrSendHead = pMpTcb->Next; - if (pMpTcb->Next == NULL) - etdev->TxRing.CurrSendTail = NULL; + while (tcb && + ((serviced ^ tcb->index) & ET_DMA10_WRAP) && + index < INDEX10(tcb->index)) { + etdev->tx_ring.used--; + etdev->tx_ring.send_head = tcb->next; + if (tcb->next == NULL) + etdev->tx_ring.send_tail = NULL; spin_unlock_irqrestore(&etdev->TCBSendQLock, flags); - et131x_free_send_packet(etdev, pMpTcb); + et131x_free_send_packet(etdev, tcb); spin_lock_irqsave(&etdev->TCBSendQLock, flags); /* Goto the next packet */ - pMpTcb = etdev->TxRing.CurrSendHead; + tcb = etdev->tx_ring.send_head; } - while (pMpTcb && - !((ServiceComplete ^ pMpTcb->WrIndex) & ET_DMA10_WRAP) - && index > (pMpTcb->WrIndex & ET_DMA10_MASK)) { - etdev->TxRing.nBusySend--; - etdev->TxRing.CurrSendHead = pMpTcb->Next; - if (pMpTcb->Next == NULL) - etdev->TxRing.CurrSendTail = NULL; + while (tcb && + !((serviced ^ tcb->index) & ET_DMA10_WRAP) + && index > (tcb->index & ET_DMA10_MASK)) { + etdev->tx_ring.used--; + etdev->tx_ring.send_head = tcb->next; + if (tcb->next == NULL) + etdev->tx_ring.send_tail = NULL; spin_unlock_irqrestore(&etdev->TCBSendQLock, flags); - et131x_free_send_packet(etdev, pMpTcb); + et131x_free_send_packet(etdev, tcb); spin_lock_irqsave(&etdev->TCBSendQLock, flags); /* Goto the next packet */ - pMpTcb = etdev->TxRing.CurrSendHead; + tcb = etdev->tx_ring.send_head; } /* Wake up the queue when we hit a low-water mark */ - if (etdev->TxRing.nBusySend <= (NUM_TCB / 3)) + if (etdev->tx_ring.used <= NUM_TCB / 3) netif_wake_queue(etdev->netdev); spin_unlock_irqrestore(&etdev->TCBSendQLock, flags); } -/** - * et131x_check_send_wait_list - Helper routine for the interrupt handler - * @etdev: pointer to our adapter - * - * Takes packets from the send wait queue and posts them to the device (if - * room available). - */ -static void et131x_check_send_wait_list(struct et131x_adapter *etdev) -{ - unsigned long flags; - - spin_lock_irqsave(&etdev->SendWaitLock, flags); - - while (!list_empty(&etdev->TxRing.SendWaitQueue) && - MP_TCB_RESOURCES_AVAILABLE(etdev)) { - struct list_head *entry; - - entry = etdev->TxRing.SendWaitQueue.next; - - etdev->TxRing.nWaitSend--; - } - - spin_unlock_irqrestore(&etdev->SendWaitLock, flags); -} diff --git a/drivers/staging/et131x/et1310_tx.h b/drivers/staging/et131x/et1310_tx.h index ad0372121de040164625d010d24002bbcc51262d..4f0ea81978f5aaca1fb2e42a57e984cb27417092 100644 --- a/drivers/staging/et131x/et1310_tx.h +++ b/drivers/staging/et131x/et1310_tx.h @@ -63,167 +63,89 @@ /* Typedefs for Tx Descriptor Ring */ /* - * TXDESC_WORD2_t structure holds part of the control bits in the Tx Descriptor - * ring for the ET-1310 + * word 2 of the control bits in the Tx Descriptor ring for the ET-1310 + * + * 0-15: length of packet + * 16-27: VLAN tag + * 28: VLAN CFI + * 29-31: VLAN priority + * + * word 3 of the control bits in the Tx Descriptor ring for the ET-1310 + * + * 0: last packet in the sequence + * 1: first packet in the sequence + * 2: interrupt the processor when this pkt sent + * 3: Control word - no packet data + * 4: Issue half-duplex backpressure : XON/XOFF + * 5: send pause frame + * 6: Tx frame has error + * 7: append CRC + * 8: MAC override + * 9: pad packet + * 10: Packet is a Huge packet + * 11: append VLAN tag + * 12: IP checksum assist + * 13: TCP checksum assist + * 14: UDP checksum assist */ -typedef union _txdesc_word2_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 vlan_prio:3; /* bits 29-31(VLAN priority) */ - u32 vlan_cfi:1; /* bit 28(cfi) */ - u32 vlan_tag:12; /* bits 16-27(VLAN tag) */ - u32 length_in_bytes:16; /* bits 0-15(packet length) */ -#else - u32 length_in_bytes:16; /* bits 0-15(packet length) */ - u32 vlan_tag:12; /* bits 16-27(VLAN tag) */ - u32 vlan_cfi:1; /* bit 28(cfi) */ - u32 vlan_prio:3; /* bits 29-31(VLAN priority) */ -#endif /* _BIT_FIELDS_HTOL */ - } bits; -} TXDESC_WORD2_t, *PTXDESC_WORD2_t; -/* - * TXDESC_WORD3_t structure holds part of the control bits in the Tx Descriptor - * ring for the ET-1310 - */ -typedef union _txdesc_word3_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:17; /* bits 15-31 */ - u32 udpa:1; /* bit 14(UDP checksum assist) */ - u32 tcpa:1; /* bit 13(TCP checksum assist) */ - u32 ipa:1; /* bit 12(IP checksum assist) */ - u32 vlan:1; /* bit 11(append VLAN tag) */ - u32 hp:1; /* bit 10(Packet is a Huge packet) */ - u32 pp:1; /* bit 9(pad packet) */ - u32 mac:1; /* bit 8(MAC override) */ - u32 crc:1; /* bit 7(append CRC) */ - u32 e:1; /* bit 6(Tx frame has error) */ - u32 pf:1; /* bit 5(send pause frame) */ - u32 bp:1; /* bit 4(Issue half-duplex backpressure (XON/XOFF) */ - u32 cw:1; /* bit 3(Control word - no packet data) */ - u32 ir:1; /* bit 2(interrupt the processor when this pkt sent) */ - u32 f:1; /* bit 1(first packet in the sequence) */ - u32 l:1; /* bit 0(last packet in the sequence) */ -#else - u32 l:1; /* bit 0(last packet in the sequence) */ - u32 f:1; /* bit 1(first packet in the sequence) */ - u32 ir:1; /* bit 2(interrupt the processor when this pkt sent) */ - u32 cw:1; /* bit 3(Control word - no packet data) */ - u32 bp:1; /* bit 4(Issue half-duplex backpressure (XON/XOFF) */ - u32 pf:1; /* bit 5(send pause frame) */ - u32 e:1; /* bit 6(Tx frame has error) */ - u32 crc:1; /* bit 7(append CRC) */ - u32 mac:1; /* bit 8(MAC override) */ - u32 pp:1; /* bit 9(pad packet) */ - u32 hp:1; /* bit 10(Packet is a Huge packet) */ - u32 vlan:1; /* bit 11(append VLAN tag) */ - u32 ipa:1; /* bit 12(IP checksum assist) */ - u32 tcpa:1; /* bit 13(TCP checksum assist) */ - u32 udpa:1; /* bit 14(UDP checksum assist) */ - u32 unused:17; /* bits 15-31 */ -#endif /* _BIT_FIELDS_HTOL */ - } bits; -} TXDESC_WORD3_t, *PTXDESC_WORD3_t; - -/* TX_DESC_ENTRY_t is sructure representing each descriptor on the ring */ -typedef struct _tx_desc_entry_t { - u32 DataBufferPtrHigh; - u32 DataBufferPtrLow; - TXDESC_WORD2_t word2; /* control words how to xmit the */ - TXDESC_WORD3_t word3; /* data (detailed above) */ -} TX_DESC_ENTRY_t, *PTX_DESC_ENTRY_t; - - -/* Typedefs for Tx DMA engine status writeback */ +/* struct tx_desc represents each descriptor on the ring */ +struct tx_desc { + u32 addr_hi; + u32 addr_lo; + u32 len_vlan; /* control words how to xmit the */ + u32 flags; /* data (detailed above) */ +}; /* - * TX_STATUS_BLOCK_t is sructure representing the status of the Tx DMA engine - * it sits in free memory, and is pointed to by 0x101c / 0x1020 + * The status of the Tx DMA engine it sits in free memory, and is pointed to + * by 0x101c / 0x1020. This is a DMA10 type */ -typedef union _tx_status_block_t { - u32 value; - struct { -#ifdef _BIT_FIELDS_HTOL - u32 unused:21; /* bits 11-31 */ - u32 serv_cpl_wrap:1; /* bit 10 */ - u32 serv_cpl:10; /* bits 0-9 */ -#else - u32 serv_cpl:10; /* bits 0-9 */ - u32 serv_cpl_wrap:1; /* bit 10 */ - u32 unused:21; /* bits 11-31 */ -#endif - } bits; -} TX_STATUS_BLOCK_t, *PTX_STATUS_BLOCK_t; - -/* TCB (Transmit Control Block) */ -typedef struct _MP_TCB { - struct _MP_TCB *Next; - u32 Flags; - u32 Count; - u32 PacketStaleCount; - struct sk_buff *Packet; - u32 PacketLength; - u32 WrIndex; - u32 WrIndexStart; -} MP_TCB, *PMP_TCB; - -/* Structure to hold the skb's in a list */ -typedef struct tx_skb_list_elem { - struct list_head skb_list_elem; - struct sk_buff *skb; -} TX_SKB_LIST_ELEM, *PTX_SKB_LIST_ELEM; - -/* TX_RING_t is sructure representing our local reference(s) to the ring */ -typedef struct _tx_ring_t { + +/* TCB (Transmit Control Block: Host Side) */ +struct tcb { + struct tcb *next; /* Next entry in ring */ + u32 flags; /* Our flags for the packet */ + u32 count; /* Used to spot stuck/lost packets */ + u32 stale; /* Used to spot stuck/lost packets */ + struct sk_buff *skb; /* Network skb we are tied to */ + u32 index; /* Ring indexes */ + u32 index_start; +}; + +/* Structure representing our local reference(s) to the ring */ +struct tx_ring { /* TCB (Transmit Control Block) memory and lists */ - PMP_TCB MpTcbMem; + struct tcb *tcb_ring; /* List of TCBs that are ready to be used */ - PMP_TCB TCBReadyQueueHead; - PMP_TCB TCBReadyQueueTail; + struct tcb *tcb_qhead; + struct tcb *tcb_qtail; /* list of TCBs that are currently being sent. NOTE that access to all - * three of these (including nBusySend) are controlled via the + * three of these (including used) are controlled via the * TCBSendQLock. This lock should be secured prior to incementing / - * decrementing nBusySend, or any queue manipulation on CurrSendHead / - * Tail + * decrementing used, or any queue manipulation on send_head / + * tail */ - PMP_TCB CurrSendHead; - PMP_TCB CurrSendTail; - int32_t nBusySend; - - /* List of packets (not TCBs) that were queued for lack of resources */ - struct list_head SendWaitQueue; - int32_t nWaitSend; + struct tcb *send_head; + struct tcb *send_tail; + int used; /* The actual descriptor ring */ - PTX_DESC_ENTRY_t pTxDescRingVa; - dma_addr_t pTxDescRingPa; - uint64_t pTxDescRingAdjustedPa; - uint64_t TxDescOffset; + struct tx_desc *tx_desc_ring; + dma_addr_t tx_desc_ring_pa; - /* ReadyToSend indicates where we last wrote to in the descriptor ring. */ - u32 txDmaReadyToSend; + /* send_idx indicates where we last wrote to in the descriptor ring. */ + u32 send_idx; /* The location of the write-back status block */ - PTX_STATUS_BLOCK_t pTxStatusVa; - dma_addr_t pTxStatusPa; - - /* A Block of zeroes used to pad packets that are less than 60 bytes */ - void *pTxDummyBlkVa; - dma_addr_t pTxDummyBlkPa; - - TXMAC_ERR_t TxMacErr; - - /* Variables to track the Tx interrupt coalescing features */ - int32_t TxPacketsSinceLastinterrupt; -} TX_RING_t, *PTX_RING_t; + u32 *tx_status; + dma_addr_t tx_status_pa; -/* Forward declaration of the frag-list for the following prototypes */ -typedef struct _MP_FRAG_LIST MP_FRAG_LIST, *PMP_FRAG_LIST; + /* Packets since the last IRQ: used for interrupt coalescing */ + int since_irq; +}; /* Forward declaration of the private adapter structure */ struct et131x_adapter; @@ -231,12 +153,12 @@ struct et131x_adapter; /* PROTOTYPES for et1310_tx.c */ int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter); void et131x_tx_dma_memory_free(struct et131x_adapter *adapter); -void ConfigTxDmaRegs(struct et131x_adapter *pAdapter); +void ConfigTxDmaRegs(struct et131x_adapter *adapter); void et131x_init_send(struct et131x_adapter *adapter); -void et131x_tx_dma_disable(struct et131x_adapter *pAdapter); -void et131x_tx_dma_enable(struct et131x_adapter *pAdapter); -void et131x_handle_send_interrupt(struct et131x_adapter *pAdapter); -void et131x_free_busy_send_packets(struct et131x_adapter *pAdapter); +void et131x_tx_dma_disable(struct et131x_adapter *adapter); +void et131x_tx_dma_enable(struct et131x_adapter *adapter); +void et131x_handle_send_interrupt(struct et131x_adapter *adapter); +void et131x_free_busy_send_packets(struct et131x_adapter *adapter); int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev); #endif /* __ET1310_TX_H__ */ diff --git a/drivers/staging/et131x/et131x_adapter.h b/drivers/staging/et131x/et131x_adapter.h index 1dfe06f1b1a7b83f362ad4dd16004a5daa9c876b..3f7f37a56b6c979df6bd1244d1c9a69ea4cf4357 100644 --- a/drivers/staging/et131x/et131x_adapter.h +++ b/drivers/staging/et131x/et131x_adapter.h @@ -100,12 +100,6 @@ #define LO_MARK_PERCENT_FOR_PSR 15 #define LO_MARK_PERCENT_FOR_RX 15 -/* Macros specific to the private adapter structure */ -#define MP_TCB_RESOURCES_AVAILABLE(_M) ((_M)->TxRing.nBusySend < NUM_TCB) -#define MP_TCB_RESOURCES_NOT_AVAILABLE(_M) ((_M)->TxRing.nBusySend >= NUM_TCB) - -#define MP_SHOULD_FAIL_SEND(_M) ((_M)->Flags & fMP_ADAPTER_FAIL_SEND_MASK) - /* Counters for error rate monitoring */ typedef struct _MP_ERR_COUNTERS { u32 PktCountTxPackets; @@ -168,7 +162,7 @@ typedef struct _ce_stats_t { u32 tx_deferred; /* Rx Statistics. */ - u32 rx_ov_flow; /* Rx Over Flow */ + u32 rx_ov_flow; /* Rx Overflow */ u32 length_err; u32 alignment_err; @@ -203,7 +197,6 @@ struct et131x_adapter { spinlock_t TCBSendQLock; spinlock_t TCBReadyQLock; spinlock_t SendHWLock; - spinlock_t SendWaitLock; spinlock_t RcvLock; spinlock_t RcvPendLock; @@ -220,9 +213,6 @@ struct et131x_adapter { u32 MCAddressCount; u8 MCList[NIC_MAX_MCAST_LIST][ETH_ALEN]; - /* MAC test */ - TXMAC_TXTEST_t TxMacTest; - /* Pointer to the device's PCI register space */ ADDRESS_MAP_t __iomem *regs; @@ -234,9 +224,6 @@ struct et131x_adapter { u32 RegistryRxMemEnd; /* Size of internal rx memory */ u32 RegistryJumboPacket; /* Max supported ethernet packet size */ - /* Validation helpers */ - u8 RegistryNMIDisable; - u8 RegistryPhyLoopbk; /* Enable Phy loopback */ /* Derived from the registry: */ u8 AiForceDpx; /* duplex setting */ @@ -248,7 +235,6 @@ struct et131x_adapter { NETIF_STATUS_MEDIA_DISCONNECT, NETIF_STATUS_MAX } MediaState; - u8 DriverNoPhyAccess; /* Minimize init-time */ struct timer_list ErrorTimer; @@ -259,7 +245,7 @@ struct et131x_adapter { MI_BMSR_t Bmsr; /* Tx Memory Variables */ - TX_RING_t TxRing; + struct tx_ring tx_ring; /* Rx Memory Variables */ RX_RING_t RxRing; diff --git a/drivers/staging/et131x/et131x_defs.h b/drivers/staging/et131x/et131x_defs.h index f98dca5fd26b2ff6c206ff3b0f4455a32fe55815..d81fc77a501fc1840253174f20316871ad71cf3d 100644 --- a/drivers/staging/et131x/et131x_defs.h +++ b/drivers/staging/et131x/et131x_defs.h @@ -102,7 +102,6 @@ /* Some offsets in PCI config space that are actually used. */ #define ET1310_PCI_MAX_PYLD 0x4C -#define ET1310_NMI_DISABLE 0x61 #define ET1310_PCI_MAC_ADDRESS 0xA4 #define ET1310_PCI_EEPROM_STATUS 0xB2 #define ET1310_PCI_ACK_NACK 0xC0 diff --git a/drivers/staging/et131x/et131x_initpci.c b/drivers/staging/et131x/et131x_initpci.c index 9db2056672629340d4ebf331795d6e3cb8fe4c73..0892b6a538dbe7c734f2d2b2c86a82e8f93a5022 100644 --- a/drivers/staging/et131x/et131x_initpci.c +++ b/drivers/staging/et131x/et131x_initpci.c @@ -106,17 +106,6 @@ #define PARM_SPEED_DUPLEX_MIN 0 #define PARM_SPEED_DUPLEX_MAX 5 -/* Module parameter for disabling NMI - * et131x_nmi_disable : - * Disable NMI (0-2) [0] - * 0 : - * 1 : - * 2 : - */ -static u32 et131x_nmi_disable; /* 0-2 */ -module_param(et131x_nmi_disable, uint, 0); -MODULE_PARM_DESC(et131x_nmi_disable, "Disable NMI (0-2) [0]"); - /* Module parameter for manual speed setting * Set Link speed and dublex manually (0-5) [0] * 1 : 10Mb Half-Duplex @@ -132,128 +121,88 @@ MODULE_PARM_DESC(et131x_speed_set, "Set Link speed and dublex manually (0-5) [0] \n 1 : 10Mb Half-Duplex \n 2 : 10Mb Full-Duplex \n 3 : 100Mb Half-Duplex \n 4 : 100Mb Full-Duplex \n 5 : 1000Mb Full-Duplex \n 0 : Auto Speed Auto Dublex"); /** - * et131x_find_adapter - Find the adapter and get all the assigned resources + * et131x_hwaddr_init - set up the MAC Address on the ET1310 * @adapter: pointer to our private adapter structure - * - * Returns 0 on success, errno on failure (as defined in errno.h) */ -int et131x_find_adapter(struct et131x_adapter *adapter, struct pci_dev *pdev) +void et131x_hwaddr_init(struct et131x_adapter *adapter) { - int result; - uint8_t eepromStat; - uint8_t maxPayload = 0; - uint8_t read_size_reg; - u8 rev; - - /* Allow disabling of Non-Maskable Interrupts in I/O space, to - * support validation. + /* If have our default mac from init and no mac address from + * EEPROM then we need to generate the last octet and set it on the + * device */ - if (adapter->RegistryNMIDisable) { - uint8_t RegisterVal; - - RegisterVal = inb(ET1310_NMI_DISABLE); - RegisterVal &= 0xf3; - - if (adapter->RegistryNMIDisable == 2) - RegisterVal |= 0xc; - - outb(ET1310_NMI_DISABLE, RegisterVal); + if (adapter->PermanentAddress[0] == 0x00 && + adapter->PermanentAddress[1] == 0x00 && + adapter->PermanentAddress[2] == 0x00 && + adapter->PermanentAddress[3] == 0x00 && + adapter->PermanentAddress[4] == 0x00 && + adapter->PermanentAddress[5] == 0x00) { + /* + * We need to randomly generate the last octet so we + * decrease our chances of setting the mac address to + * same as another one of our cards in the system + */ + get_random_bytes(&adapter->CurrentAddress[5], 1); + /* + * We have the default value in the register we are + * working with so we need to copy the current + * address into the permanent address + */ + memcpy(adapter->PermanentAddress, + adapter->CurrentAddress, ETH_ALEN); + } else { + /* We do not have an override address, so set the + * current address to the permanent address and add + * it to the device + */ + memcpy(adapter->CurrentAddress, + adapter->PermanentAddress, ETH_ALEN); } +} - /* We first need to check the EEPROM Status code located at offset - * 0xB2 of config space - */ - result = pci_read_config_byte(pdev, ET1310_PCI_EEPROM_STATUS, - &eepromStat); - - /* THIS IS A WORKAROUND: - * I need to call this function twice to get my card in a - * LG M1 Express Dual running. I tried also a msleep before this - * function, because I thougth there could be some time condidions - * but it didn't work. Call the whole function twice also work. - */ - result = pci_read_config_byte(pdev, ET1310_PCI_EEPROM_STATUS, - &eepromStat); - if (result != PCIBIOS_SUCCESSFUL) { - dev_err(&pdev->dev, "Could not read PCI config space for " - "EEPROM Status\n"); - return -EIO; - } - /* Determine if the error(s) we care about are present. If they are - * present, we need to fail. - */ - if (eepromStat & 0x4C) { - result = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); - if (result != PCIBIOS_SUCCESSFUL) { - dev_err(&pdev->dev, - "Could not read PCI config space for " - "Revision ID\n"); - return -EIO; - } else if (rev == 0x01) { - int32_t nLoop; - uint8_t temp[4] = { 0xFE, 0x13, 0x10, 0xFF }; - - /* Re-write the first 4 bytes if we have an eeprom - * present and the revision id is 1, this fixes the - * corruption seen with 1310 B Silicon - */ - for (nLoop = 0; nLoop < 3; nLoop++) { - EepromWriteByte(adapter, nLoop, temp[nLoop]); - } - } +/** + * et131x_pci_init - initial PCI setup + * @adapter: pointer to our private adapter structure + * @pdev: our PCI device + * + * Perform the initial setup of PCI registers and if possible initialise + * the MAC address. At this point the I/O registers have yet to be mapped + */ - dev_err(&pdev->dev, "Fatal EEPROM Status Error - 0x%04x\n", eepromStat); +static int et131x_pci_init(struct et131x_adapter *adapter, + struct pci_dev *pdev) +{ + int i; + u8 max_payload; + u8 read_size_reg; - /* This error could mean that there was an error reading the - * eeprom or that the eeprom doesn't exist. We will treat - * each case the same and not try to gather additional - * information that normally would come from the eeprom, like - * MAC Address - */ - adapter->has_eeprom = 0; + if (et131x_init_eeprom(adapter) < 0) return -EIO; - } else - adapter->has_eeprom = 1; - - /* Read the EEPROM for information regarding LED behavior. Refer to - * ET1310_phy.c, et131x_xcvr_init(), for its use. - */ - EepromReadByte(adapter, 0x70, &adapter->eepromData[0]); - EepromReadByte(adapter, 0x71, &adapter->eepromData[1]); - - if (adapter->eepromData[0] != 0xcd) - /* Disable all optional features */ - adapter->eepromData[1] = 0x00; /* Let's set up the PORT LOGIC Register. First we need to know what * the max_payload_size is */ - result = pci_read_config_byte(pdev, ET1310_PCI_MAX_PYLD, &maxPayload); - if (result != PCIBIOS_SUCCESSFUL) { + if (pci_read_config_byte(pdev, ET1310_PCI_MAX_PYLD, &max_payload)) { dev_err(&pdev->dev, "Could not read PCI config space for Max Payload Size\n"); return -EIO; } /* Program the Ack/Nak latency and replay timers */ - maxPayload &= 0x07; /* Only the lower 3 bits are valid */ + max_payload &= 0x07; /* Only the lower 3 bits are valid */ - if (maxPayload < 2) { - const uint16_t AckNak[2] = { 0x76, 0xD0 }; - const uint16_t Replay[2] = { 0x1E0, 0x2ED }; + if (max_payload < 2) { + static const u16 AckNak[2] = { 0x76, 0xD0 }; + static const u16 Replay[2] = { 0x1E0, 0x2ED }; - result = pci_write_config_word(pdev, ET1310_PCI_ACK_NACK, - AckNak[maxPayload]); - if (result != PCIBIOS_SUCCESSFUL) { + if (pci_write_config_word(pdev, ET1310_PCI_ACK_NACK, + AckNak[max_payload])) { dev_err(&pdev->dev, "Could not write PCI config space for ACK/NAK\n"); return -EIO; } - - result = pci_write_config_word(pdev, ET1310_PCI_REPLAY, - Replay[maxPayload]); - if (result != PCIBIOS_SUCCESSFUL) { + if (pci_write_config_word(pdev, ET1310_PCI_REPLAY, + Replay[max_payload])) { dev_err(&pdev->dev, "Could not write PCI config space for Replay Timer\n"); return -EIO; @@ -263,16 +212,14 @@ int et131x_find_adapter(struct et131x_adapter *adapter, struct pci_dev *pdev) /* l0s and l1 latency timers. We are using default values. * Representing 001 for L0s and 010 for L1 */ - result = pci_write_config_byte(pdev, ET1310_PCI_L0L1LATENCY, 0x11); - if (result != PCIBIOS_SUCCESSFUL) { + if (pci_write_config_byte(pdev, ET1310_PCI_L0L1LATENCY, 0x11)) { dev_err(&pdev->dev, "Could not write PCI config space for Latency Timers\n"); return -EIO; } /* Change the max read size to 2k */ - result = pci_read_config_byte(pdev, 0x51, &read_size_reg); - if (result != PCIBIOS_SUCCESSFUL) { + if (pci_read_config_byte(pdev, 0x51, &read_size_reg)) { dev_err(&pdev->dev, "Could not read PCI config space for Max read size\n"); return -EIO; @@ -281,8 +228,7 @@ int et131x_find_adapter(struct et131x_adapter *adapter, struct pci_dev *pdev) read_size_reg &= 0x8f; read_size_reg |= 0x40; - result = pci_write_config_byte(pdev, 0x51, read_size_reg); - if (result != PCIBIOS_SUCCESSFUL) { + if (pci_write_config_byte(pdev, 0x51, read_size_reg)) { dev_err(&pdev->dev, "Could not write PCI config space for Max read size\n"); return -EIO; @@ -291,19 +237,19 @@ int et131x_find_adapter(struct et131x_adapter *adapter, struct pci_dev *pdev) /* Get MAC address from config space if an eeprom exists, otherwise * the MAC address there will not be valid */ - if (adapter->has_eeprom) { - int i; - - for (i = 0; i < ETH_ALEN; i++) { - result = pci_read_config_byte( - pdev, ET1310_PCI_MAC_ADDRESS + i, - adapter->PermanentAddress + i); - if (result != PCIBIOS_SUCCESSFUL) { - dev_err(&pdev->dev, ";Could not read PCI config space for MAC address\n"); - return -EIO; - } + if (!adapter->has_eeprom) { + et131x_hwaddr_init(adapter); + return 0; + } + + for (i = 0; i < ETH_ALEN; i++) { + if (pci_read_config_byte(pdev, ET1310_PCI_MAC_ADDRESS + i, + adapter->PermanentAddress + i)) { + dev_err(&pdev->dev, "Could not read PCI config space for MAC address\n"); + return -EIO; } } + memcpy(adapter->CurrentAddress, adapter->PermanentAddress, ETH_ALEN); return 0; } @@ -383,52 +329,34 @@ void ConfigGlobalRegs(struct et131x_adapter *etdev) { struct _GLOBAL_t __iomem *regs = &etdev->regs->global; - if (etdev->RegistryPhyLoopbk == false) { - if (etdev->RegistryJumboPacket < 2048) { - /* Tx / RxDMA and Tx/Rx MAC interfaces have a 1k word - * block of RAM that the driver can split between Tx - * and Rx as it desires. Our default is to split it - * 50/50: - */ - writel(0, ®s->rxq_start_addr); - writel(PARM_RX_MEM_END_DEF, ®s->rxq_end_addr); - writel(PARM_RX_MEM_END_DEF + 1, ®s->txq_start_addr); - writel(INTERNAL_MEM_SIZE - 1, ®s->txq_end_addr); - } else if (etdev->RegistryJumboPacket < 8192) { - /* For jumbo packets > 2k but < 8k, split 50-50. */ - writel(0, ®s->rxq_start_addr); - writel(INTERNAL_MEM_RX_OFFSET, ®s->rxq_end_addr); - writel(INTERNAL_MEM_RX_OFFSET + 1, ®s->txq_start_addr); - writel(INTERNAL_MEM_SIZE - 1, ®s->txq_end_addr); - } else { - /* 9216 is the only packet size greater than 8k that - * is available. The Tx buffer has to be big enough - * for one whole packet on the Tx side. We'll make - * the Tx 9408, and give the rest to Rx - */ - writel(0x0000, ®s->rxq_start_addr); - writel(0x01b3, ®s->rxq_end_addr); - writel(0x01b4, ®s->txq_start_addr); - writel(INTERNAL_MEM_SIZE - 1,®s->txq_end_addr); - } + writel(0, ®s->rxq_start_addr); + writel(INTERNAL_MEM_SIZE - 1, ®s->txq_end_addr); - /* Initialize the loopback register. Disable all loopbacks. */ - writel(0, ®s->loopback); + if (etdev->RegistryJumboPacket < 2048) { + /* Tx / RxDMA and Tx/Rx MAC interfaces have a 1k word + * block of RAM that the driver can split between Tx + * and Rx as it desires. Our default is to split it + * 50/50: + */ + writel(PARM_RX_MEM_END_DEF, ®s->rxq_end_addr); + writel(PARM_RX_MEM_END_DEF + 1, ®s->txq_start_addr); + } else if (etdev->RegistryJumboPacket < 8192) { + /* For jumbo packets > 2k but < 8k, split 50-50. */ + writel(INTERNAL_MEM_RX_OFFSET, ®s->rxq_end_addr); + writel(INTERNAL_MEM_RX_OFFSET + 1, ®s->txq_start_addr); } else { - /* For PHY Line loopback, the memory is configured as if Tx - * and Rx both have all the memory. This is because the - * RxMAC will write data into the space, and the TxMAC will - * read it out. + /* 9216 is the only packet size greater than 8k that + * is available. The Tx buffer has to be big enough + * for one whole packet on the Tx side. We'll make + * the Tx 9408, and give the rest to Rx */ - writel(0, ®s->rxq_start_addr); - writel(INTERNAL_MEM_SIZE - 1, ®s->rxq_end_addr); - writel(0, ®s->txq_start_addr); - writel(INTERNAL_MEM_SIZE - 1, ®s->txq_end_addr); - - /* Initialize the loopback register (MAC loopback). */ - writel(ET_LOOP_MAC, ®s->loopback); + writel(0x01b3, ®s->rxq_end_addr); + writel(0x01b4, ®s->txq_start_addr); } + /* Initialize the loopback register. Disable all loopbacks. */ + writel(0, ®s->loopback); + /* MSI Register */ writel(0, ®s->msi_config); @@ -497,45 +425,6 @@ int et131x_adapter_setup(struct et131x_adapter *etdev) ; return status; } -/** - * et131x_setup_hardware_properties - set up the MAC Address on the ET1310 - * @adapter: pointer to our private adapter structure - */ -void et131x_setup_hardware_properties(struct et131x_adapter *adapter) -{ - /* If have our default mac from registry and no mac address from - * EEPROM then we need to generate the last octet and set it on the - * device - */ - if (adapter->PermanentAddress[0] == 0x00 && - adapter->PermanentAddress[1] == 0x00 && - adapter->PermanentAddress[2] == 0x00 && - adapter->PermanentAddress[3] == 0x00 && - adapter->PermanentAddress[4] == 0x00 && - adapter->PermanentAddress[5] == 0x00) { - /* - * We need to randomly generate the last octet so we - * decrease our chances of setting the mac address to - * same as another one of our cards in the system - */ - get_random_bytes(&adapter->CurrentAddress[5], 1); - /* - * We have the default value in the register we are - * working with so we need to copy the current - * address into the permanent address - */ - memcpy(adapter->PermanentAddress, - adapter->CurrentAddress, ETH_ALEN); - } else { - /* We do not have an override address, so set the - * current address to the permanent address and add - * it to the device - */ - memcpy(adapter->CurrentAddress, - adapter->PermanentAddress, ETH_ALEN); - } -} - /** * et131x_soft_reset - Issue a soft reset to the hardware, complete for ET1310 * @adapter: pointer to our private adapter structure @@ -543,12 +432,12 @@ void et131x_setup_hardware_properties(struct et131x_adapter *adapter) void et131x_soft_reset(struct et131x_adapter *adapter) { /* Disable MAC Core */ - writel(0xc00f0000, &adapter->regs->mac.cfg1.value); + writel(0xc00f0000, &adapter->regs->mac.cfg1); /* Set everything to a reset value */ writel(0x7F, &adapter->regs->global.sw_reset); - writel(0x000f0000, &adapter->regs->mac.cfg1.value); - writel(0x00000000, &adapter->regs->mac.cfg1.value); + writel(0x000f0000, &adapter->regs->mac.cfg1); + writel(0x00000000, &adapter->regs->mac.cfg1); } /** @@ -588,36 +477,32 @@ void et131x_align_allocated_memory(struct et131x_adapter *adapter, */ int et131x_adapter_memory_alloc(struct et131x_adapter *adapter) { - int status = 0; - - do { - /* Allocate memory for the Tx Ring */ - status = et131x_tx_dma_memory_alloc(adapter); - if (status != 0) { - dev_err(&adapter->pdev->dev, - "et131x_tx_dma_memory_alloc FAILED\n"); - break; - } + int status; - /* Receive buffer memory allocation */ - status = et131x_rx_dma_memory_alloc(adapter); - if (status != 0) { - dev_err(&adapter->pdev->dev, - "et131x_rx_dma_memory_alloc FAILED\n"); - et131x_tx_dma_memory_free(adapter); - break; - } + /* Allocate memory for the Tx Ring */ + status = et131x_tx_dma_memory_alloc(adapter); + if (status != 0) { + dev_err(&adapter->pdev->dev, + "et131x_tx_dma_memory_alloc FAILED\n"); + return status; + } + /* Receive buffer memory allocation */ + status = et131x_rx_dma_memory_alloc(adapter); + if (status != 0) { + dev_err(&adapter->pdev->dev, + "et131x_rx_dma_memory_alloc FAILED\n"); + et131x_tx_dma_memory_free(adapter); + return status; + } - /* Init receive data structures */ - status = et131x_init_recv(adapter); - if (status != 0) { - dev_err(&adapter->pdev->dev, - "et131x_init_recv FAILED\n"); - et131x_tx_dma_memory_free(adapter); - et131x_rx_dma_memory_free(adapter); - break; - } - } while (0); + /* Init receive data structures */ + status = et131x_init_recv(adapter); + if (status != 0) { + dev_err(&adapter->pdev->dev, + "et131x_init_recv FAILED\n"); + et131x_tx_dma_memory_free(adapter); + et131x_rx_dma_memory_free(adapter); + } return status; } @@ -632,22 +517,50 @@ void et131x_adapter_memory_free(struct et131x_adapter *adapter) et131x_rx_dma_memory_free(adapter); } + + /** - * et131x_config_parse + * et131x_adapter_init * @etdev: pointer to the private adapter struct + * @pdev: pointer to the PCI device * - * Parses a configuration from some location (module parameters, for example) - * into the private adapter struct. This really has no sensible analogy in - * Linux as sysfs parameters are dynamic. Several things that were hee could - * go into sysfs, but other stuff like speed handling is part of the mii - * interfaces/ethtool. + * Initialize the data structures for the et131x_adapter object and link + * them together with the platform provided device structures. */ -void et131x_config_parse(struct et131x_adapter *etdev) + + +static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev, + struct pci_dev *pdev) { static const u8 default_mac[] = { 0x00, 0x05, 0x3d, 0x00, 0x02, 0x00 }; static const u8 duplex[] = { 0, 1, 2, 1, 2, 2 }; static const u16 speed[] = { 0, 10, 10, 100, 100, 1000 }; + struct et131x_adapter *etdev; + + /* Setup the fundamental net_device and private adapter structure elements */ + SET_NETDEV_DEV(netdev, &pdev->dev); + + /* Allocate private adapter struct and copy in relevant information */ + etdev = netdev_priv(netdev); + etdev->pdev = pci_dev_get(pdev); + etdev->netdev = netdev; + + /* Do the same for the netdev struct */ + netdev->irq = pdev->irq; + netdev->base_addr = pci_resource_start(pdev, 0); + + /* Initialize spinlocks here */ + spin_lock_init(&etdev->Lock); + spin_lock_init(&etdev->TCBSendQLock); + spin_lock_init(&etdev->TCBReadyQLock); + spin_lock_init(&etdev->SendHWLock); + spin_lock_init(&etdev->RcvLock); + spin_lock_init(&etdev->RcvPendLock); + spin_lock_init(&etdev->FbrLock); + spin_lock_init(&etdev->PHYLock); + + /* Parse configuration parameters into the private adapter struct */ if (et131x_speed_set) dev_info(&etdev->pdev->dev, "Speed set manually to : %d \n", et131x_speed_set); @@ -655,8 +568,6 @@ void et131x_config_parse(struct et131x_adapter *etdev) etdev->SpeedDuplex = et131x_speed_set; etdev->RegistryJumboPacket = 1514; /* 1514-9216 */ - etdev->RegistryNMIDisable = et131x_nmi_disable; - /* Set the MAC address to a default */ memcpy(etdev->CurrentAddress, default_mac, ETH_ALEN); @@ -674,40 +585,10 @@ void et131x_config_parse(struct et131x_adapter *etdev) etdev->AiForceSpeed = speed[etdev->SpeedDuplex]; etdev->AiForceDpx = duplex[etdev->SpeedDuplex]; /* Auto FDX */ -} - - -/** - * et131x_pci_remove - * @pdev: a pointer to the device's pci_dev structure - * - * Registered in the pci_driver structure, this function is called when the - * PCI subsystem detects that a PCI device which matches the information - * contained in the pci_device_id table has been removed. - */ - -void __devexit et131x_pci_remove(struct pci_dev *pdev) -{ - struct net_device *netdev; - struct et131x_adapter *adapter; - /* Retrieve the net_device pointer from the pci_dev struct, as well - * as the private adapter struct - */ - netdev = (struct net_device *) pci_get_drvdata(pdev); - adapter = netdev_priv(netdev); - - /* Perform device cleanup */ - unregister_netdev(netdev); - et131x_adapter_memory_free(adapter); - iounmap(adapter->regs); - pci_dev_put(adapter->pdev); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); + return etdev; } - /** * et131x_pci_setup - Perform device initialization * @pdev: a pointer to the device's pci_dev structure @@ -721,34 +602,31 @@ void __devexit et131x_pci_remove(struct pci_dev *pdev) * a device insertion routine. */ -int __devinit et131x_pci_setup(struct pci_dev *pdev, +static int __devinit et131x_pci_setup(struct pci_dev *pdev, const struct pci_device_id *ent) { - int result = 0; + int result = -EBUSY; int pm_cap; bool pci_using_dac; - struct net_device *netdev = NULL; - struct et131x_adapter *adapter = NULL; + struct net_device *netdev; + struct et131x_adapter *adapter; /* Enable the device via the PCI subsystem */ - result = pci_enable_device(pdev); - if (result != 0) { - dev_err(&adapter->pdev->dev, + if (pci_enable_device(pdev) != 0) { + dev_err(&pdev->dev, "pci_enable_device() failed\n"); - goto out; + return -EIO; } /* Perform some basic PCI checks */ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - dev_err(&adapter->pdev->dev, + dev_err(&pdev->dev, "Can't find PCI device's base address\n"); - result = -ENODEV; - goto out; + goto err_disable; } - result = pci_request_regions(pdev, DRIVER_NAME); - if (result != 0) { - dev_err(&adapter->pdev->dev, + if (pci_request_regions(pdev, DRIVER_NAME)) { + dev_err(&pdev->dev, "Can't get PCI resources\n"); goto err_disable; } @@ -763,27 +641,26 @@ int __devinit et131x_pci_setup(struct pci_dev *pdev, */ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); if (pm_cap == 0) { - dev_err(&adapter->pdev->dev, + dev_err(&pdev->dev, "Cannot find Power Management capabilities\n"); result = -EIO; goto err_release_res; } /* Check the DMA addressing support of this device */ - if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) { + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { pci_using_dac = true; - result = - pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL); + result = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); if (result != 0) { dev_err(&pdev->dev, "Unable to obtain 64 bit DMA for consistent allocations\n"); goto err_release_res; } - } else if (!pci_set_dma_mask(pdev, 0xffffffffULL)) { + } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { pci_using_dac = false; } else { - dev_err(&adapter->pdev->dev, + dev_err(&pdev->dev, "No usable DMA addressing method\n"); result = -EIO; goto err_release_res; @@ -792,87 +669,22 @@ int __devinit et131x_pci_setup(struct pci_dev *pdev, /* Allocate netdev and private adapter structs */ netdev = et131x_device_alloc(); if (netdev == NULL) { - dev_err(&adapter->pdev->dev, - "Couldn't alloc netdev struct\n"); + dev_err(&pdev->dev, "Couldn't alloc netdev struct\n"); result = -ENOMEM; goto err_release_res; } - - /* Setup the fundamental net_device and private adapter structure elements */ - SET_NETDEV_DEV(netdev, &pdev->dev); - /* - if (pci_using_dac) { - netdev->features |= NETIF_F_HIGHDMA; - } - */ - - /* - * NOTE - Turn this on when we're ready to deal with SG-DMA - * - * NOTE: According to "Linux Device Drivers", 3rd ed, Rubini et al, - * if checksumming is not performed in HW, then the kernel will not - * use SG. - * From pp 510-511: - * - * "Note that the kernel does not perform scatter/gather I/O to your - * device if it does not also provide some form of checksumming as - * well. The reason is that, if the kernel has to make a pass over a - * fragmented ("nonlinear") packet to calculate the checksum, it - * might as well copy the data and coalesce the packet at the same - * time." - * - * This has been verified by setting the flags below and still not - * receiving a scattered buffer from the network stack, so leave it - * off until checksums are calculated in HW. - */ - /* netdev->features |= NETIF_F_SG; */ - /* netdev->features |= NETIF_F_NO_CSUM; */ - /* netdev->features |= NETIF_F_LLTX; */ - - /* Allocate private adapter struct and copy in relevant information */ - adapter = netdev_priv(netdev); - adapter->pdev = pci_dev_get(pdev); - adapter->netdev = netdev; - - /* Do the same for the netdev struct */ - netdev->irq = pdev->irq; - netdev->base_addr = pdev->resource[0].start; - - /* Initialize spinlocks here */ - spin_lock_init(&adapter->Lock); - spin_lock_init(&adapter->TCBSendQLock); - spin_lock_init(&adapter->TCBReadyQLock); - spin_lock_init(&adapter->SendHWLock); - spin_lock_init(&adapter->SendWaitLock); - spin_lock_init(&adapter->RcvLock); - spin_lock_init(&adapter->RcvPendLock); - spin_lock_init(&adapter->FbrLock); - spin_lock_init(&adapter->PHYLock); - - /* Parse configuration parameters into the private adapter struct */ - et131x_config_parse(adapter); - - /* Find the physical adapter - * - * NOTE: This is the equivalent of the MpFindAdapter() routine; can we - * lump it's init with the device specific init below into a - * single init function? - */ - /* while (et131x_find_adapter(adapter, pdev) != 0); */ - et131x_find_adapter(adapter, pdev); + adapter = et131x_adapter_init(netdev, pdev); + /* Initialise the PCI setup for the device */ + et131x_pci_init(adapter, pdev); /* Map the bus-relative registers to system virtual memory */ - - adapter->regs = ioremap_nocache(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); + adapter->regs = pci_ioremap_bar(pdev, 0); if (adapter->regs == NULL) { dev_err(&pdev->dev, "Cannot map device registers\n"); result = -ENOMEM; goto err_free_dev; } - /* Perform device-specific initialization here (See code below) */ - /* If Phy COMA mode was enabled when we went down, disable it here. */ writel(ET_PMCSR_INIT, &adapter->regs->global.pm_csr); @@ -892,20 +704,12 @@ int __devinit et131x_pci_setup(struct pci_dev *pdev, /* Init send data structures */ et131x_init_send(adapter); - /* Register the interrupt - * - * NOTE - This is being done in the open routine, where most other - * Linux drivers setup IRQ handlers. Make sure device - * interrupts are not turned on before the IRQ is registered!! - * - * What we will do here is setup the task structure for the - * ISR's deferred handler + /* + * Set up the task structure for the ISR's deferred handler */ INIT_WORK(&adapter->task, et131x_isr_handler); - /* Determine MAC Address, and copy into the net_device struct */ - et131x_setup_hardware_properties(adapter); - + /* Copy address into the net_device struct */ memcpy(netdev->dev_addr, adapter->CurrentAddress, ETH_ALEN); /* Setup et1310 as per the documentation */ @@ -944,10 +748,7 @@ int __devinit et131x_pci_setup(struct pci_dev *pdev, * been initialized, just in case it needs to be quickly restored. */ pci_set_drvdata(pdev, netdev); - pci_save_state(adapter->pdev); - -out: return result; err_mem_free: @@ -961,7 +762,37 @@ err_release_res: pci_release_regions(pdev); err_disable: pci_disable_device(pdev); - goto out; + return result; +} + +/** + * et131x_pci_remove + * @pdev: a pointer to the device's pci_dev structure + * + * Registered in the pci_driver structure, this function is called when the + * PCI subsystem detects that a PCI device which matches the information + * contained in the pci_device_id table has been removed. + */ + +static void __devexit et131x_pci_remove(struct pci_dev *pdev) +{ + struct net_device *netdev; + struct et131x_adapter *adapter; + + /* Retrieve the net_device pointer from the pci_dev struct, as well + * as the private adapter struct + */ + netdev = (struct net_device *) pci_get_drvdata(pdev); + adapter = netdev_priv(netdev); + + /* Perform device cleanup */ + unregister_netdev(netdev); + et131x_adapter_memory_free(adapter); + iounmap(adapter->regs); + pci_dev_put(adapter->pdev); + free_netdev(netdev); + pci_release_regions(pdev); + pci_disable_device(pdev); } static struct pci_device_id et131x_pci_table[] __devinitdata = { @@ -989,7 +820,7 @@ static struct pci_driver et131x_driver = { * * Returns 0 on success, errno on failure (as defined in errno.h) */ -static int et131x_init_module(void) +static int __init et131x_init_module(void) { if (et131x_speed_set < PARM_SPEED_DUPLEX_MIN || et131x_speed_set > PARM_SPEED_DUPLEX_MAX) { @@ -1002,7 +833,7 @@ static int et131x_init_module(void) /** * et131x_cleanup_module - The entry point called on driver cleanup */ -static void et131x_cleanup_module(void) +static void __exit et131x_cleanup_module(void) { pci_unregister_driver(&et131x_driver); } @@ -1010,7 +841,6 @@ static void et131x_cleanup_module(void) module_init(et131x_init_module); module_exit(et131x_cleanup_module); - /* Modinfo parameters (filled out using defines from et131x_version.h) */ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_INFO); diff --git a/drivers/staging/et131x/et131x_initpci.h b/drivers/staging/et131x/et131x_initpci.h index 8131d6a65c2a7c675d4c81d2fb778e7d499c3b8e..7269569a874b2cd44370ad354ecc4b27a8c3fff8 100644 --- a/drivers/staging/et131x/et131x_initpci.h +++ b/drivers/staging/et131x/et131x_initpci.h @@ -67,7 +67,7 @@ void et131x_align_allocated_memory(struct et131x_adapter *adapter, int et131x_adapter_setup(struct et131x_adapter *adapter); int et131x_adapter_memory_alloc(struct et131x_adapter *adapter); void et131x_adapter_memory_free(struct et131x_adapter *adapter); -void et131x_setup_hardware_properties(struct et131x_adapter *adapter); +void et131x_hwaddr_init(struct et131x_adapter *adapter); void et131x_soft_reset(struct et131x_adapter *adapter); #endif /* __ET131X_INITPCI_H__ */ diff --git a/drivers/staging/et131x/et131x_isr.c b/drivers/staging/et131x/et131x_isr.c index f80189d7cb6d5e8527666c18ab6d7c371ed44082..f6d452dd14e27a0d7cd38b8993a818d40fce74fd 100644 --- a/drivers/staging/et131x/et131x_isr.c +++ b/drivers/staging/et131x/et131x_isr.c @@ -109,9 +109,6 @@ void et131x_enable_interrupts(struct et131x_adapter *adapter) else mask = INT_MASK_ENABLE_NO_FLOW; - if (adapter->DriverNoPhyAccess) - mask |= ET_INTR_PHY; - adapter->CachedMaskValue = mask; writel(mask, &adapter->regs->global.int_mask); } @@ -182,15 +179,15 @@ irqreturn_t et131x_isr(int irq, void *dev_id) /* This is our interrupt, so process accordingly */ if (status & ET_INTR_WATCHDOG) { - PMP_TCB pMpTcb = adapter->TxRing.CurrSendHead; + struct tcb *tcb = adapter->tx_ring.send_head; - if (pMpTcb) - if (++pMpTcb->PacketStaleCount > 1) + if (tcb) + if (++tcb->stale > 1) status |= ET_INTR_TXDMA_ISR; if (adapter->RxRing.UnfinishedReceives) status |= ET_INTR_RXDMA_XFR_DONE; - else if (pMpTcb == NULL) + else if (tcb == NULL) writel(0, &adapter->regs->global.watchdog_timer); status &= ~ET_INTR_WATCHDOG; @@ -290,17 +287,12 @@ void et131x_isr_handler(struct work_struct *work) u32 pm_csr; /* Tell the device to send a pause packet via - * the back pressure register + * the back pressure register (bp req and + * bp xon/xoff) */ pm_csr = readl(&iomem->global.pm_csr); - if ((pm_csr & ET_PM_PHY_SW_COMA) == 0) { - TXMAC_BP_CTRL_t bp_ctrl = { 0 }; - - bp_ctrl.bits.bp_req = 1; - bp_ctrl.bits.bp_xonxoff = 1; - writel(bp_ctrl.value, - &iomem->txmac.bp_ctrl.value); - } + if ((pm_csr & ET_PM_PHY_SW_COMA) == 0) + writel(3, &iomem->txmac.bp_ctrl); } } @@ -340,11 +332,9 @@ void et131x_isr_handler(struct work_struct *work) */ /* TRAP();*/ - etdev->TxMacTest.value = - readl(&iomem->txmac.tx_test.value); dev_warn(&etdev->pdev->dev, "RxDMA_ERR interrupt, error %x\n", - etdev->TxMacTest.value); + readl(&iomem->txmac.tx_test)); } /* Handle the Wake on LAN Event */ @@ -400,8 +390,7 @@ void et131x_isr_handler(struct work_struct *work) /* Let's move on to the TxMac */ if (status & ET_INTR_TXMAC) { - etdev->TxRing.TxMacErr.value = - readl(&iomem->txmac.err.value); + u32 err = readl(&iomem->txmac.err.value); /* * When any of the errors occur and TXMAC generates @@ -415,7 +404,7 @@ void et131x_isr_handler(struct work_struct *work) */ dev_warn(&etdev->pdev->dev, "TXMAC interrupt, error 0x%08x\n", - etdev->TxRing.TxMacErr.value); + err); /* If we are debugging, we want to see this error, * otherwise we just want the device to be reset and diff --git a/drivers/staging/et131x/et131x_netdev.c b/drivers/staging/et131x/et131x_netdev.c index 8c7612f63f9152718120771d862e7e8de6458fd8..24d97b4fa6fbb7e8dab8ca2073389f6816c0cb51 100644 --- a/drivers/staging/et131x/et131x_netdev.c +++ b/drivers/staging/et131x/et131x_netdev.c @@ -519,7 +519,7 @@ int et131x_tx(struct sk_buff *skb, struct net_device *netdev) void et131x_tx_timeout(struct net_device *netdev) { struct et131x_adapter *etdev = netdev_priv(netdev); - PMP_TCB pMpTcb; + struct tcb *tcb; unsigned long flags; /* Just skip this part if the adapter is doing link detection */ @@ -541,28 +541,19 @@ void et131x_tx_timeout(struct net_device *netdev) /* Is send stuck? */ spin_lock_irqsave(&etdev->TCBSendQLock, flags); - pMpTcb = etdev->TxRing.CurrSendHead; + tcb = etdev->tx_ring.send_head; - if (pMpTcb != NULL) { - pMpTcb->Count++; - - if (pMpTcb->Count > NIC_SEND_HANG_THRESHOLD) { - TX_DESC_ENTRY_t StuckDescriptors[10]; - - if (INDEX10(pMpTcb->WrIndex) > 7) { - memcpy(StuckDescriptors, - etdev->TxRing.pTxDescRingVa + - INDEX10(pMpTcb->WrIndex) - 6, - sizeof(TX_DESC_ENTRY_t) * 10); - } + if (tcb != NULL) { + tcb->count++; + if (tcb->count > NIC_SEND_HANG_THRESHOLD) { spin_unlock_irqrestore(&etdev->TCBSendQLock, flags); dev_warn(&etdev->pdev->dev, - "Send stuck - reset. pMpTcb->WrIndex %x, Flags 0x%08x\n", - pMpTcb->WrIndex, - pMpTcb->Flags); + "Send stuck - reset. tcb->WrIndex %x, Flags 0x%08x\n", + tcb->index, + tcb->flags); et131x_close(netdev); et131x_open(netdev); @@ -622,7 +613,7 @@ int et131x_change_mtu(struct net_device *netdev, int new_mtu) et131x_init_send(adapter); - et131x_setup_hardware_properties(adapter); + et131x_hwaddr_init(adapter); memcpy(netdev->dev_addr, adapter->CurrentAddress, ETH_ALEN); /* Init the device with the new settings */ @@ -709,9 +700,7 @@ int et131x_set_mac_addr(struct net_device *netdev, void *new_mac) et131x_init_send(adapter); - et131x_setup_hardware_properties(adapter); - /* memcpy( netdev->dev_addr, adapter->CurrentAddress, ETH_ALEN ); */ - /* blux: no, do not override our nice address */ + et131x_hwaddr_init(adapter); /* Init the device with the new settings */ et131x_adapter_setup(adapter); diff --git a/drivers/staging/hv/hv_api.h b/drivers/staging/hv/hv_api.h index 251e2d155331d61295e582167223db39da9f7800..9eb818ee07ba6cadfb175956dd53ed3b0642a09f 100644 --- a/drivers/staging/hv/hv_api.h +++ b/drivers/staging/hv/hv_api.h @@ -316,13 +316,13 @@ /* * HV_STATUS_VMX_INSTRUCTION_FAILED - * The requested VMX instruction failed to complete succesfully. + * The requested VMX instruction failed to complete successfully. */ #define HV_STATUS_VMX_INSTRUCTION_FAILED ((u16)0x1011) /* * HV_STATUS_VMX_INSTRUCTION_FAILED_WITH_STATUS - * The requested VMX instruction failed to complete succesfully indicating + * The requested VMX instruction failed to complete successfully indicating * status. */ #define HV_STATUS_VMX_INSTRUCTION_FAILED_WITH_STATUS ((u16)0x1012) diff --git a/drivers/staging/iio/Documentation/device.txt b/drivers/staging/iio/Documentation/device.txt index 6916cd3333502cfdd6b38fd9c2fa39869974602e..69d9570f29fca10eb33702af17f88bfb6ae0c351 100644 --- a/drivers/staging/iio/Documentation/device.txt +++ b/drivers/staging/iio/Documentation/device.txt @@ -10,7 +10,7 @@ First allocate one using: struct iio_dev *indio_dev = iio_allocate_device(); -The fill in the following. +Then fill in the following: indio_dev->dev.parent the struct device associated with the underlying hardware. @@ -45,5 +45,5 @@ allocated prior to registering the device with the iio-core, but must be registered afterwards (otherwise the whole parentage of devices gets confused) -On remove iio_device_unregister(indio_dev) will remove the device from +On remove, iio_device_unregister(indio_dev) will remove the device from the core, and iio_free_device will clean up. diff --git a/drivers/staging/iio/Documentation/overview.txt b/drivers/staging/iio/Documentation/overview.txt index 64584ad40241012bc3c24119601fbd96315edc13..e39dfc1705aaba2489f8afd33b007853f830cfec 100644 --- a/drivers/staging/iio/Documentation/overview.txt +++ b/drivers/staging/iio/Documentation/overview.txt @@ -24,11 +24,12 @@ hwmon with simple polled access to device channels via sysfs. * Event chrdevs. These are similar to input in that they provide a route to user space for hardware triggered events. Such events include threshold detectors, free-fall detectors and more complex action -detection. They events themselves are currently very simple with +detection. The events themselves are currently very simple with merely an event code and a timestamp. Any data associated with the -event must be accessed via polling. Note a given device may have one -or more event channel. These events are turned on or off (if possible) -via sysfs interfaces. +event must be accessed via polling. + +Note: A given device may have one or more event channel. These events are +turned on or off (if possible) via sysfs interfaces. * Hardware ring buffer support. Some recent sensors have included fifo / ring buffers on the sensor chip. These greatly reduce the load diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig index 4586650d65c38b30aec09d1314d798b3ff77f9c8..ace99f6d1166ecbb1e6efc80f0c8faa4d48f8098 100644 --- a/drivers/staging/iio/Kconfig +++ b/drivers/staging/iio/Kconfig @@ -8,7 +8,7 @@ menuconfig IIO ---help--- The industrial I/O subsystem provides a unified framework for drivers for many different types of embedded sensors using a - number of different physical interfaces (i2c, spi etc). See + number of different physical interfaces (i2c, spi, etc). See Documentation/industrialio for more information. if IIO @@ -23,10 +23,10 @@ if IIO_RING_BUFFER config IIO_SW_RING tristate "Industrial I/O lock free software ring" help - example software ring buffer implementation. The design aim - of this particular realization was to minize write locking - with the intention that some devices would be able to write - in interrupt context. + Example software ring buffer implementation. The design aim + of this particular realization was to minimize write locking + with the intention that some devices would be able to write + in interrupt context. endif # IIO_RINGBUFFER diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig index fef3da48276c7ad2458094f149458baa96645a06..3d3c3339dbc7f8d436f8aae39e900e43fbf9d0d3 100644 --- a/drivers/staging/iio/accel/Kconfig +++ b/drivers/staging/iio/accel/Kconfig @@ -13,6 +13,8 @@ config KXSD9 config LIS3L02DQ tristate "ST Microelectronics LIS3L02DQ Accelerometer Driver" depends on SPI + select IIO_TRIGGER if IIO_RING_BUFFER + select IIO_SW_RING if IIO_RING_BUFFER help Say yes here to build SPI support for the ST microelectronics accelerometer. The driver supplies direct access via sysfs files diff --git a/drivers/staging/iio/accel/accel.h b/drivers/staging/iio/accel/accel.h index 811fa0527a4360671f2cd00803aa2f6c4b32ede6..d7fc7f98348e8776be3773d35a2616effb68019c 100644 --- a/drivers/staging/iio/accel/accel.h +++ b/drivers/staging/iio/accel/accel.h @@ -31,13 +31,13 @@ IIO_DEVICE_ATTR(accel_z, S_IRUGO, _show, NULL, _addr) /* Thresholds are somewhat chip dependent - may need quite a few defs here */ -/* For unified thesholds (shared across all directions */ +/* For unified thresholds (shared across all directions */ /** * IIO_DEV_ATTR_ACCEL_THRESH: unified threshold * @_mode: read/write * @_show: read detector threshold value - * @_store: write detector theshold value + * @_store: write detector threshold value * @_addr: driver specific data, typically a register address * * This one is for cases where as single threshold covers all directions @@ -48,7 +48,7 @@ /** * IIO_DEV_ATTR_ACCEL_THRESH_X: independant direction threshold, x axis * @_mode: readable / writable - * @_show: read x axis detector theshold value + * @_show: read x axis detector threshold value * @_store: write x axis detector threshold value * @_addr: device driver dependant, typically a register address **/ diff --git a/drivers/staging/iio/accel/sca3000.h b/drivers/staging/iio/accel/sca3000.h index 29e11da095720680fb77c6f13d1a2ffa0f055470..da7d3cb5ae71ba918aae34045ef95301ac338ba3 100644 --- a/drivers/staging/iio/accel/sca3000.h +++ b/drivers/staging/iio/accel/sca3000.h @@ -74,7 +74,7 @@ #define SCA3000_MEAS_MODE_OP_2 0x02 /* In motion detection mode the accelerations are band pass filtered - * (aprox 1 - 25Hz) and then a programmable theshold used to trigger + * (aprox 1 - 25Hz) and then a programmable threshold used to trigger * and interrupt. */ #define SCA3000_MEAS_MODE_MOT_DET 0x03 @@ -139,7 +139,7 @@ /* Values of mulipexed registers (write to ctrl_data after select) */ #define SCA3000_REG_ADDR_CTRL_DATA 0x22 -/* Measurment modes available on some sca3000 series chips. Code assumes others +/* Measurement modes available on some sca3000 series chips. Code assumes others * may become available in the future. * * Bypass - Bypass the low-pass filter in the signal channel so as to increase diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index e27e3b7d1003aeef43285765b55e85e7763d52fa..cedcaa2b3d1f2d5d81d4bac4a59878aeb8be4662 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -720,7 +720,7 @@ error_ret: static IIO_DEV_ATTR_TEMP(sca3000_read_temp); /** - * sca3000_show_thresh() sysfs query of a theshold + * sca3000_show_thresh() sysfs query of a threshold **/ static ssize_t sca3000_show_thresh(struct device *dev, struct device_attribute *attr, diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index b8c2858585f98d4f8834aa9c12137dbc0ce2348e..3989c0ca0e0dff5e96a186fd08b40a17051db91b 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -6,8 +6,18 @@ comment "Analog to digital convertors" config MAX1363 tristate "MAXIM max1363 ADC driver" depends on I2C + select IIO_TRIGGER if IIO_RING_BUFFER help Say yes here to build support for many MAXIM i2c analog to digital convertors (ADC). (max1361, max1362, max1363, max1364, max1136, max1136, max1137, max1138, max1139, max1236, max1237, max11238, max1239) Provides direct access via sysfs. + +config MAX1363_RING_BUFFER + bool "MAXIM max1363: use ring buffer" + depends on MAX1363 + select IIO_RING_BUFFER + select IIO_SW_RING + help + Say yes here to include ring buffer support in the MAX1363 + ADC driver. diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index 0c2b6f39e8c876ca2e183d2da162084aa7461284..08cee5c22b92ba13cb59222bfed1fd5c34bd23d0 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -3,6 +3,6 @@ # max1363-y := max1363_core.o -max1363-$(CONFIG_IIO_RING_BUFFER) += max1363_ring.o +max1363-$(CONFIG_MAX1363_RING_BUFFER) += max1363_ring.o obj-$(CONFIG_MAX1363) += max1363.o diff --git a/drivers/staging/iio/adc/max1363.h b/drivers/staging/iio/adc/max1363.h index 8aca81f14d0beeb217c7ad9ff68bbba4cbc07e9d..c112fbef27050a4f1d36466e92ab4a707611b1e4 100644 --- a/drivers/staging/iio/adc/max1363.h +++ b/drivers/staging/iio/adc/max1363.h @@ -228,7 +228,7 @@ struct max1363_state { struct iio_trigger *trig; struct regulator *reg; }; -#ifdef CONFIG_IIO_RING_BUFFER +#ifdef CONFIG_MAX1363_RING_BUFFER ssize_t max1363_scan_from_ring(struct device *dev, struct device_attribute *attr, @@ -239,7 +239,7 @@ void max1363_ring_cleanup(struct iio_dev *indio_dev); int max1363_initialize_ring(struct iio_ring_buffer *ring); void max1363_uninitialize_ring(struct iio_ring_buffer *ring); -#else /* CONFIG_IIO_RING_BUFFER */ +#else /* CONFIG_MAX1363_RING_BUFFER */ static inline void max1363_uninitialize_ring(struct iio_ring_buffer *ring) { @@ -265,5 +265,5 @@ max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) }; static inline void max1363_ring_cleanup(struct iio_dev *indio_dev) {}; -#endif /* CONFIG_IIO_RING_BUFFER */ +#endif /* CONFIG_MAX1363_RING_BUFFER */ #endif /* _MAX1363_H_ */ diff --git a/drivers/staging/iio/chrdev.h b/drivers/staging/iio/chrdev.h index 8bc64bf0845901c31e2687b5e9403dadb87b3139..f42bafb3a894baa859d6a8076115b3ca6039c92a 100644 --- a/drivers/staging/iio/chrdev.h +++ b/drivers/staging/iio/chrdev.h @@ -75,10 +75,12 @@ struct iio_shared_ev_pointer { * @current_events: number of events in detected list * @id: indentifier to allow the event interface to know which * physical line it corresponds to + * @attr: this chrdev's minor number sysfs attribute * @owner: ensure the driver module owns the file, not iio * @private: driver specific data * @_name: used internally to store the sysfs name for minor id * attribute + * @_attrname: the event interface's attribute name */ struct iio_event_interface { struct device dev; @@ -105,7 +107,7 @@ struct iio_event_interface { * @handler: event handler function - called on event if this * event_handler is enabled. * - * Each device has one list of these per interrupt line + * Each device has one list of these per interrupt line. **/ struct iio_event_handler_list { struct list_head list; diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h index 25ccb809221e0e2e02339ac3d8db8d50ae06dfb6..71dbfe12b5792929ebf661d5e232ab8a24f72ac6 100644 --- a/drivers/staging/iio/iio.h +++ b/drivers/staging/iio/iio.h @@ -166,7 +166,7 @@ static inline int iio_scan_mask_clear(struct iio_dev *dev_info, int bit) * @bit: which number scan element is this **/ static inline int iio_scan_mask_count_to_right(struct iio_dev *dev_info, -int bit) + int bit) { int count = 0; int mask = (1 << bit); @@ -239,7 +239,7 @@ void iio_unregister_interrupt_line(struct iio_dev *dev_info, * @dev_info: IIO device structure * @ev_line: Which event line (hardware interrupt) * @ev_code: What event - * @timestamp: When the event occured + * @timestamp: When the event occurred **/ int iio_push_event(struct iio_dev *dev_info, int ev_line, @@ -248,11 +248,11 @@ int iio_push_event(struct iio_dev *dev_info, /** * struct iio_work_cont - container for when singleton handler case matters - * @ws: [DEVICE]work_struct when not only possible event - * @ws_nocheck: [DEVICE]work_struct when only possible event - * @address: [DEVICE]associated register address - * @mask: [DEVICE]associated mask for identifying event source - * @st: [DEVICE]device specific state information + * @ws: [DEVICE] work_struct when not only possible event + * @ws_nocheck: [DEVICE] work_struct when only possible event + * @address: [DEVICE] associated register address + * @mask: [DEVICE] associated mask for identifying event source + * @st: [DEVICE] device specific state information **/ struct iio_work_cont { struct work_struct ws; @@ -273,9 +273,9 @@ struct iio_work_cont { * @cont: the work container * @_checkfunc: function called when there are multiple possible int sources * @_nocheckfunc: function for when there is only one int source - * @_add: driver dependant, typically a register address - * @_mask: driver dependant, typically a bit mask for a register - * @_st: driver dependant, typically pointer to a device state structure + * @_add: driver dependent, typically a register address + * @_mask: driver dependent, typically a bit mask for a register + * @_st: driver dependent, typically pointer to a device state structure **/ static inline void iio_init_work_cont(struct iio_work_cont *cont, @@ -290,7 +290,7 @@ iio_init_work_cont(struct iio_work_cont *cont, cont->st = _st; } /** - * __iio_push_event() tries to add an event to the list associated with a chrdev + * __iio_push_event() - tries to add an event to the list associated with a chrdev * @ev_int: the event interface to which we are pushing the event * @ev_code: the outgoing event code * @timestamp: timestamp of the event @@ -302,8 +302,8 @@ int __iio_push_event(struct iio_event_interface *ev_int, struct iio_shared_ev_pointer* shared_pointer_p); /** - * __iio_change_event() change an event code in case of event escallation - * @ev: the evnet to be changed + * __iio_change_event() - change an event code in case of event escalation + * @ev: the event to be changed * @ev_code: new event code * @timestamp: new timestamp **/ @@ -312,7 +312,7 @@ void __iio_change_event(struct iio_detected_event_list *ev, s64 timestamp); /** - * iio_setup_ev_int() Configure an event interface (chrdev) + * iio_setup_ev_int() - configure an event interface (chrdev) * @name: name used for resulting sysfs directory etc. * @ev_int: interface we are configuring * @owner: module that is responsible for registering this ev_int @@ -343,7 +343,7 @@ extern dev_t iio_devt; extern struct class iio_class; /** - * iio_put_device() - reference counted deallocated of struct device + * iio_put_device() - reference counted deallocation of struct device * @dev: the iio_device containing the device **/ static inline void iio_put_device(struct iio_dev *dev) @@ -353,7 +353,7 @@ static inline void iio_put_device(struct iio_dev *dev) }; /** - * to_iio_dev() - get iio_dev for which we have have the struct device + * to_iio_dev() - get iio_dev for which we have the struct device * @d: the struct device **/ static inline struct iio_dev *to_iio_dev(struct device *d) @@ -377,6 +377,7 @@ struct iio_dev *iio_allocate_device(void); /** * iio_free_device() - free an iio_dev from a driver + * @dev: the iio_dev associated with the device **/ void iio_free_device(struct iio_dev *dev); @@ -395,7 +396,8 @@ int iio_device_get_chrdev_minor(void); void iio_device_free_chrdev_minor(int val); /** - * iio_ring_enabled() helper function to test if any form of ring enabled + * iio_ring_enabled() - helper function to test if any form of ring is enabled + * @dev_info: IIO device info structure for device **/ static inline bool iio_ring_enabled(struct iio_dev *dev_info) { diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig index 12af0c46fe2237f77f4b326dc19eff76ecc23c9b..80cb6e590fbb6124065a65c835545f0e8bd152e7 100644 --- a/drivers/staging/iio/light/Kconfig +++ b/drivers/staging/iio/light/Kconfig @@ -3,11 +3,13 @@ # comment "Light sensors" -config TSL2561 - tristate "TAOS TSL2561 light-to-digital convertor" - depends on I2C - help - Say yes bere to build support for the TAOS light to digital - convertor. This chip has two light sensors. One is broadband - including infrared whilst the other measures only infrared. - Provides direct access via sysfs. +config SENSORS_TSL2563 + tristate "TAOS TSL256[0-3] ambient light sensor" + depends on I2C + help + If you say yes here you get support for the Taos TSL2560, + TSL2561, TSL2562 and TSL2563 ambient light sensors. + + This driver can also be built as a module. If so, the module + will be called tsl2563. + diff --git a/drivers/staging/iio/light/Makefile b/drivers/staging/iio/light/Makefile index ccff151676096aed51daf9c7234dfe44ea5326f3..30f3300e2a68de45faa4954e5ab41a581c4fcc88 100644 --- a/drivers/staging/iio/light/Makefile +++ b/drivers/staging/iio/light/Makefile @@ -2,4 +2,4 @@ # Makefile for industrial I/O Light sensors # -obj-$(CONFIG_TSL2561) += tsl2561.o +obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o diff --git a/drivers/staging/iio/light/tsl2561.c b/drivers/staging/iio/light/tsl2561.c deleted file mode 100644 index fc2107f4c049b4b88905bbe06ee06aa7f1c45f45..0000000000000000000000000000000000000000 --- a/drivers/staging/iio/light/tsl2561.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * tsl2561.c - Linux kernel modules for light to digital convertor - * - * Copyright (C) 2008-2009 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You 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. - * - * Some portions based upon the tsl2550 driver. - * - * This driver could probably be adapted easily to talk to the tsl2560 (smbus) - * - * Needs some work to support the events this can generate. - * Todo: Implement interrupt handling. Currently a hardware bug means - * this isn't available on my test board. - */ - -#include -#include -#include -#include "../iio.h" -#include "../sysfs.h" -#include "light.h" - -#define TSL2561_CONTROL_REGISTER 0x00 -#define TSL2561_TIMING_REGISTER 0x01 -#define TSL2561_THRESHLOW_LOW_REGISTER 0x02 -#define TSL2561_THRESHLOW_HIGH_REGISTER 0x03 -#define TSL2561_THRESHHIGH_LOW_REGISTER 0x04 -#define TSL2561_THRESHHIGH_HIGH_REGISTER 0x05 -#define TSL2561_INT_CONTROL_REGISTER 0x06 - -#define TSL2561_INT_REG_INT_OFF 0x00 -#define TSL2561_INT_REG_INT_LEVEL 0x08 -#define TSL2561_INT_REG_INT_SMBUS 0x10 -#define TSL2561_INT_REG_INT_TEST 0x18 - -#define TSL2561_ID_REGISTER 0x0A - -#define TSL2561_DATA_0_LOW 0x0C -#define TSL2561_DATA_1_LOW 0x0E - -/* Control Register Values */ -#define TSL2561_CONT_REG_PWR_ON 0x03 -#define TSL2561_CONT_REG_PWR_OFF 0x00 - -/** - * struct tsl2561_state - device specific state - * @indio_dev: the industrialio I/O info structure - * @client: i2c client - * @command_buf: single command buffer used for all operations - * @command_buf_lock: ensure unique access to command_buf - */ -struct tsl2561_state { - struct iio_dev *indio_dev; - struct i2c_client *client; - struct tsl2561_command *command_buf; - struct mutex command_buf_lock; -}; - -/** - * struct tsl2561_command - command byte for smbus - * @address: register address - * @block: is this a block r/w - * @word: is this a word r/w - * @clear: set to 1 to clear pending interrupt - * @cmd: select the command register - always 1. - */ -struct tsl2561_command { - unsigned int address:4; - unsigned int block:1; - unsigned int word:1; - unsigned int clear:1; - unsigned int cmd:1; -}; - -static inline void tsl2561_init_command_buf(struct tsl2561_command *buf) -{ - buf->address = 0; - buf->block = 0; - buf->word = 0; - buf->clear = 0; - buf->cmd = 1; -} - -static ssize_t tsl2561_read_val(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret = 0, data; - ssize_t len = 0; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2561_state *st = indio_dev->dev_data; - - mutex_lock(&st->command_buf_lock); - st->command_buf->cmd = 1; - st->command_buf->word = 1; - st->command_buf->address = this_attr->address; - - data = i2c_smbus_read_word_data(st->client, *(char *)(st->command_buf)); - if (data < 0) { - ret = data; - goto error_ret; - } - len = sprintf(buf, "%u\n", data); - -error_ret: - mutex_unlock(&st->command_buf_lock); - - return ret ? ret : len; -} - -static IIO_DEV_ATTR_LIGHT_INFRARED(0, tsl2561_read_val, TSL2561_DATA_0_LOW); -static IIO_DEV_ATTR_LIGHT_BROAD(0, tsl2561_read_val, TSL2561_DATA_1_LOW); - -static struct attribute *tsl2561_attributes[] = { - &iio_dev_attr_light_infrared0.dev_attr.attr, - &iio_dev_attr_light_broadspectrum0.dev_attr.attr, - NULL, -}; - -static const struct attribute_group tsl2561_attribute_group = { - .attrs = tsl2561_attributes, -}; - -static int tsl2561_initialize(struct tsl2561_state *st) -{ - int err; - - mutex_lock(&st->command_buf_lock); - st->command_buf->word = 0; - st->command_buf->block = 0; - st->command_buf->address = TSL2561_CONTROL_REGISTER; - err = i2c_smbus_write_byte_data(st->client, *(char *)(st->command_buf), - TSL2561_CONT_REG_PWR_ON); - if (err) - goto error_ret; - - st->command_buf->address = TSL2561_INT_CONTROL_REGISTER; - err = i2c_smbus_write_byte_data(st->client, *(char *)(st->command_buf), - TSL2561_INT_REG_INT_TEST); - -error_ret: - mutex_unlock(&st->command_buf_lock); - - return err; -} - -static int tsl2561_powerdown(struct i2c_client *client) -{ - int err; - struct tsl2561_command Command = { - .cmd = 1, - .clear = 0, - .word = 0, - .block = 0, - .address = TSL2561_CONTROL_REGISTER, - }; - - err = i2c_smbus_write_byte_data(client, *(char *)(&Command), - TSL2561_CONT_REG_PWR_OFF); - return (err < 0) ? err : 0; -} -static int __devinit tsl2561_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int ret = 0, regdone = 0; - struct tsl2561_state *st = kzalloc(sizeof(*st), GFP_KERNEL); - - if (st == NULL) { - ret = -ENOMEM; - goto error_ret; - } - i2c_set_clientdata(client, st); - st->client = client; - mutex_init(&st->command_buf_lock); - - st->command_buf = kmalloc(sizeof(*st->command_buf), GFP_KERNEL); - if (st->command_buf == NULL) { - ret = -ENOMEM; - goto error_free_state; - } - tsl2561_init_command_buf(st->command_buf); - - st->indio_dev = iio_allocate_device(); - if (st->indio_dev == NULL) { - ret = -ENOMEM; - goto error_free_command_buf; - } - st->indio_dev->attrs = &tsl2561_attribute_group; - st->indio_dev->dev.parent = &client->dev; - st->indio_dev->dev_data = (void *)(st); - st->indio_dev->driver_module = THIS_MODULE; - st->indio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_device_register(st->indio_dev); - if (ret) - goto error_free_iiodev; - regdone = 1; - /* Intialize the chip */ - ret = tsl2561_initialize(st); - if (ret) - goto error_unregister_iiodev; - - return 0; -error_unregister_iiodev: -error_free_iiodev: - if (regdone) - iio_device_unregister(st->indio_dev); - else - iio_free_device(st->indio_dev); -error_free_command_buf: - kfree(st->command_buf); -error_free_state: - kfree(st); -error_ret: - return ret; - -} - -static int __devexit tsl2561_remove(struct i2c_client *client) -{ - struct tsl2561_state *st = i2c_get_clientdata(client); - - iio_device_unregister(st->indio_dev); - kfree(st); - - return tsl2561_powerdown(client); -} - -static const struct i2c_device_id tsl2561_id[] = { - { "tsl2561", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, tsl2561_id); - - -static struct i2c_driver tsl2561_driver = { - .driver = { - .name = "tsl2561", - }, - .probe = tsl2561_probe, - .remove = __devexit_p(tsl2561_remove), - .id_table = tsl2561_id, -}; - -static __init int tsl2561_init(void) -{ - return i2c_add_driver(&tsl2561_driver); -} -module_init(tsl2561_init); - -static __exit void tsl2561_exit(void) -{ - i2c_del_driver(&tsl2561_driver); -} -module_exit(tsl2561_exit); - -MODULE_AUTHOR("Jonathan Cameron "); -MODULE_DESCRIPTION("TSL2561 light sensor driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c new file mode 100644 index 0000000000000000000000000000000000000000..78b9432c81057bcf8b019bf9835c32d2e5d875b2 --- /dev/null +++ b/drivers/staging/iio/light/tsl2563.c @@ -0,0 +1,773 @@ +/* + * drivers/i2c/chips/tsl2563.c + * + * Copyright (C) 2008 Nokia Corporation + * + * Written by Timo O. Karjalainen + * Contact: Amit Kucheria + * + * Converted to IIO driver + * Amit Kucheria + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "tsl2563.h" + +/* Use this many bits for fraction part. */ +#define ADC_FRAC_BITS (14) + +/* Given number of 1/10000's in ADC_FRAC_BITS precision. */ +#define FRAC10K(f) (((f) * (1L << (ADC_FRAC_BITS))) / (10000)) + +/* Bits used for fraction in calibration coefficients.*/ +#define CALIB_FRAC_BITS (10) +/* 0.5 in CALIB_FRAC_BITS precision */ +#define CALIB_FRAC_HALF (1 << (CALIB_FRAC_BITS - 1)) +/* Make a fraction from a number n that was multiplied with b. */ +#define CALIB_FRAC(n, b) (((n) << CALIB_FRAC_BITS) / (b)) +/* Decimal 10^(digits in sysfs presentation) */ +#define CALIB_BASE_SYSFS (1000) + +#define TSL2563_CMD (0x80) +#define TSL2563_CLEARINT (0x40) + +#define TSL2563_REG_CTRL (0x00) +#define TSL2563_REG_TIMING (0x01) +#define TSL2563_REG_LOWLOW (0x02) /* data0 low threshold, 2 bytes */ +#define TSL2563_REG_LOWHIGH (0x03) +#define TSL2563_REG_HIGHLOW (0x04) /* data0 high threshold, 2 bytes */ +#define TSL2563_REG_HIGHHIGH (0x05) +#define TSL2563_REG_INT (0x06) +#define TSL2563_REG_ID (0x0a) +#define TSL2563_REG_DATA0LOW (0x0c) /* broadband sensor value, 2 bytes */ +#define TSL2563_REG_DATA0HIGH (0x0d) +#define TSL2563_REG_DATA1LOW (0x0e) /* infrared sensor value, 2 bytes */ +#define TSL2563_REG_DATA1HIGH (0x0f) + +#define TSL2563_CMD_POWER_ON (0x03) +#define TSL2563_CMD_POWER_OFF (0x00) +#define TSL2563_CTRL_POWER_MASK (0x03) + +#define TSL2563_TIMING_13MS (0x00) +#define TSL2563_TIMING_100MS (0x01) +#define TSL2563_TIMING_400MS (0x02) +#define TSL2563_TIMING_MASK (0x03) +#define TSL2563_TIMING_GAIN16 (0x10) +#define TSL2563_TIMING_GAIN1 (0x00) + +#define TSL2563_INT_DISBLED (0x00) +#define TSL2563_INT_LEVEL (0x10) +#define TSL2563_INT_PERSIST(n) ((n) & 0x0F) + +struct tsl2563_gainlevel_coeff { + u8 gaintime; + u16 min; + u16 max; +}; + +static struct tsl2563_gainlevel_coeff tsl2563_gainlevel_table[] = { + { + .gaintime = TSL2563_TIMING_400MS | TSL2563_TIMING_GAIN16, + .min = 0, + .max = 65534, + }, { + .gaintime = TSL2563_TIMING_400MS | TSL2563_TIMING_GAIN1, + .min = 2048, + .max = 65534, + }, { + .gaintime = TSL2563_TIMING_100MS | TSL2563_TIMING_GAIN1, + .min = 4095, + .max = 37177, + }, { + .gaintime = TSL2563_TIMING_13MS | TSL2563_TIMING_GAIN1, + .min = 3000, + .max = 65535, + }, +}; + +struct tsl2563_chip { + struct mutex lock; + struct i2c_client *client; + struct iio_dev *indio_dev; + struct delayed_work poweroff_work; + + /* Remember state for suspend and resume functions */ + pm_message_t state; + + struct tsl2563_gainlevel_coeff *gainlevel; + + /* Thresholds are in lux */ + u16 low_thres; + u16 high_thres; + u8 intr; + + /* Calibration coefficients */ + u32 calib0; + u32 calib1; + int cover_comp_gain; + + /* Cache current values, to be returned while suspended */ + u32 data0; + u32 data1; +}; + +static int tsl2563_write(struct i2c_client *client, u8 reg, u8 value) +{ + int ret; + u8 buf[2]; + + buf[0] = TSL2563_CMD | reg; + buf[1] = value; + + ret = i2c_master_send(client, buf, sizeof(buf)); + return (ret == sizeof(buf)) ? 0 : ret; +} + +static int tsl2563_read(struct i2c_client *client, u8 reg, void *buf, int len) +{ + int ret; + u8 cmd = TSL2563_CMD | reg; + + ret = i2c_master_send(client, &cmd, sizeof(cmd)); + if (ret != sizeof(cmd)) + return ret; + + return i2c_master_recv(client, buf, len); +} + +static int tsl2563_set_power(struct tsl2563_chip *chip, int on) +{ + struct i2c_client *client = chip->client; + u8 cmd; + + cmd = on ? TSL2563_CMD_POWER_ON : TSL2563_CMD_POWER_OFF; + return tsl2563_write(client, TSL2563_REG_CTRL, cmd); +} + +/* + * Return value is 0 for off, 1 for on, or a negative error + * code if reading failed. + */ +static int tsl2563_get_power(struct tsl2563_chip *chip) +{ + struct i2c_client *client = chip->client; + int ret; + u8 val; + + ret = tsl2563_read(client, TSL2563_REG_CTRL, &val, sizeof(val)); + if (ret != sizeof(val)) + return ret; + + return (val & TSL2563_CTRL_POWER_MASK) == TSL2563_CMD_POWER_ON; +} + +static int tsl2563_configure(struct tsl2563_chip *chip) +{ + struct i2c_client *client = chip->client; + int ret; + + ret = tsl2563_write(client, TSL2563_REG_TIMING, + chip->gainlevel->gaintime); + if (ret) + goto out; + + ret = tsl2563_write(client, TSL2563_REG_INT, chip->intr); + +out: + return ret; +} + +static void tsl2563_poweroff_work(struct work_struct *work) +{ + struct tsl2563_chip *chip = + container_of(work, struct tsl2563_chip, poweroff_work.work); + tsl2563_set_power(chip, 0); +} + +static int tsl2563_detect(struct tsl2563_chip *chip) +{ + int ret; + + ret = tsl2563_set_power(chip, 1); + if (ret) + return ret; + + ret = tsl2563_get_power(chip); + if (ret < 0) + return ret; + + return ret ? 0 : -ENODEV; +} + +static int tsl2563_read_id(struct tsl2563_chip *chip, u8 *id) +{ + struct i2c_client *client = chip->client; + int ret; + + ret = tsl2563_read(client, TSL2563_REG_ID, id, sizeof(*id)); + if (ret != sizeof(*id)) + return ret; + + return 0; +} + +/* + * "Normalized" ADC value is one obtained with 400ms of integration time and + * 16x gain. This function returns the number of bits of shift needed to + * convert between normalized values and HW values obtained using given + * timing and gain settings. + */ +static int adc_shiftbits(u8 timing) +{ + int shift = 0; + + switch (timing & TSL2563_TIMING_MASK) { + case TSL2563_TIMING_13MS: + shift += 5; + break; + case TSL2563_TIMING_100MS: + shift += 2; + break; + case TSL2563_TIMING_400MS: + /* no-op */ + break; + } + + if (!(timing & TSL2563_TIMING_GAIN16)) + shift += 4; + + return shift; +} + +/* Convert a HW ADC value to normalized scale. */ +static u32 normalize_adc(u16 adc, u8 timing) +{ + return adc << adc_shiftbits(timing); +} + +static void tsl2563_wait_adc(struct tsl2563_chip *chip) +{ + unsigned int delay; + + switch (chip->gainlevel->gaintime & TSL2563_TIMING_MASK) { + case TSL2563_TIMING_13MS: + delay = 14; + break; + case TSL2563_TIMING_100MS: + delay = 101; + break; + default: + delay = 402; + } + /* + * TODO: Make sure that we wait at least required delay but why we + * have to extend it one tick more? + */ + schedule_timeout_interruptible(msecs_to_jiffies(delay) + 2); +} + +static int tsl2563_adjust_gainlevel(struct tsl2563_chip *chip, u16 adc) +{ + struct i2c_client *client = chip->client; + + if (adc > chip->gainlevel->max || adc < chip->gainlevel->min) { + + (adc > chip->gainlevel->max) ? + chip->gainlevel++ : chip->gainlevel--; + + tsl2563_write(client, TSL2563_REG_TIMING, + chip->gainlevel->gaintime); + + tsl2563_wait_adc(chip); + tsl2563_wait_adc(chip); + + return 1; + } else + return 0; +} + +static int tsl2563_get_adc(struct tsl2563_chip *chip) +{ + struct i2c_client *client = chip->client; + u8 buf0[2], buf1[2]; + u16 adc0, adc1; + int retry = 1; + int ret = 0; + + if (chip->state.event != PM_EVENT_ON) + goto out; + + cancel_delayed_work(&chip->poweroff_work); + + if (!tsl2563_get_power(chip)) { + ret = tsl2563_set_power(chip, 1); + if (ret) + goto out; + ret = tsl2563_configure(chip); + if (ret) + goto out; + tsl2563_wait_adc(chip); + } + + while (retry) { + ret = tsl2563_read(client, + TSL2563_REG_DATA0LOW | TSL2563_CLEARINT, + buf0, sizeof(buf0)); + if (ret != sizeof(buf0)) + goto out; + + ret = tsl2563_read(client, TSL2563_REG_DATA1LOW, + buf1, sizeof(buf1)); + if (ret != sizeof(buf1)) + goto out; + + adc0 = (buf0[1] << 8) + buf0[0]; + adc1 = (buf1[1] << 8) + buf1[0]; + + retry = tsl2563_adjust_gainlevel(chip, adc0); + } + + chip->data0 = normalize_adc(adc0, chip->gainlevel->gaintime); + chip->data1 = normalize_adc(adc1, chip->gainlevel->gaintime); + + schedule_delayed_work(&chip->poweroff_work, 5 * HZ); + + ret = 0; +out: + return ret; +} + +static inline int calib_to_sysfs(u32 calib) +{ + return (int) (((calib * CALIB_BASE_SYSFS) + + CALIB_FRAC_HALF) >> CALIB_FRAC_BITS); +} + +static inline u32 calib_from_sysfs(int value) +{ + return (((u32) value) << CALIB_FRAC_BITS) / CALIB_BASE_SYSFS; +} + +/* + * Conversions between lux and ADC values. + * + * The basic formula is lux = c0 * adc0 - c1 * adc1, where c0 and c1 are + * appropriate constants. Different constants are needed for different + * kinds of light, determined by the ratio adc1/adc0 (basically the ratio + * of the intensities in infrared and visible wavelengths). lux_table below + * lists the upper threshold of the adc1/adc0 ratio and the corresponding + * constants. + */ + +struct tsl2563_lux_coeff { + unsigned long ch_ratio; + unsigned long ch0_coeff; + unsigned long ch1_coeff; +}; + +static const struct tsl2563_lux_coeff lux_table[] = { + { + .ch_ratio = FRAC10K(1300), + .ch0_coeff = FRAC10K(315), + .ch1_coeff = FRAC10K(262), + }, { + .ch_ratio = FRAC10K(2600), + .ch0_coeff = FRAC10K(337), + .ch1_coeff = FRAC10K(430), + }, { + .ch_ratio = FRAC10K(3900), + .ch0_coeff = FRAC10K(363), + .ch1_coeff = FRAC10K(529), + }, { + .ch_ratio = FRAC10K(5200), + .ch0_coeff = FRAC10K(392), + .ch1_coeff = FRAC10K(605), + }, { + .ch_ratio = FRAC10K(6500), + .ch0_coeff = FRAC10K(229), + .ch1_coeff = FRAC10K(291), + }, { + .ch_ratio = FRAC10K(8000), + .ch0_coeff = FRAC10K(157), + .ch1_coeff = FRAC10K(180), + }, { + .ch_ratio = FRAC10K(13000), + .ch0_coeff = FRAC10K(34), + .ch1_coeff = FRAC10K(26), + }, { + .ch_ratio = ULONG_MAX, + .ch0_coeff = 0, + .ch1_coeff = 0, + }, +}; + +/* + * Convert normalized, scaled ADC values to lux. + */ +static unsigned int adc_to_lux(u32 adc0, u32 adc1) +{ + const struct tsl2563_lux_coeff *lp = lux_table; + unsigned long ratio, lux, ch0 = adc0, ch1 = adc1; + + ratio = ch0 ? ((ch1 << ADC_FRAC_BITS) / ch0) : ULONG_MAX; + + while (lp->ch_ratio < ratio) + lp++; + + lux = ch0 * lp->ch0_coeff - ch1 * lp->ch1_coeff; + + return (unsigned int) (lux >> ADC_FRAC_BITS); +} + +/*--------------------------------------------------------------*/ +/* Sysfs interface */ +/*--------------------------------------------------------------*/ + +static ssize_t tsl2563_adc0_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tsl2563_chip *chip = indio_dev->dev_data; + int ret; + + mutex_lock(&chip->lock); + + ret = tsl2563_get_adc(chip); + if (ret) + goto out; + + ret = snprintf(buf, PAGE_SIZE, "%d\n", chip->data0); +out: + mutex_unlock(&chip->lock); + return ret; +} + +static ssize_t tsl2563_adc1_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tsl2563_chip *chip = indio_dev->dev_data; + int ret; + + mutex_lock(&chip->lock); + + ret = tsl2563_get_adc(chip); + if (ret) + goto out; + + ret = snprintf(buf, PAGE_SIZE, "%d\n", chip->data1); +out: + mutex_unlock(&chip->lock); + return ret; +} + +/* Apply calibration coefficient to ADC count. */ +static u32 calib_adc(u32 adc, u32 calib) +{ + unsigned long scaled = adc; + + scaled *= calib; + scaled >>= CALIB_FRAC_BITS; + + return (u32) scaled; +} + +static ssize_t tsl2563_lux_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tsl2563_chip *chip = indio_dev->dev_data; + u32 calib0, calib1; + int ret; + + mutex_lock(&chip->lock); + + ret = tsl2563_get_adc(chip); + if (ret) + goto out; + + calib0 = calib_adc(chip->data0, chip->calib0) * chip->cover_comp_gain; + calib1 = calib_adc(chip->data1, chip->calib1) * chip->cover_comp_gain; + + ret = snprintf(buf, PAGE_SIZE, "%d\n", adc_to_lux(calib0, calib1)); + +out: + mutex_unlock(&chip->lock); + return ret; +} + +static ssize_t format_calib(char *buf, int len, u32 calib) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", calib_to_sysfs(calib)); +} + +static ssize_t tsl2563_calib0_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tsl2563_chip *chip = indio_dev->dev_data; + int ret; + + mutex_lock(&chip->lock); + ret = format_calib(buf, PAGE_SIZE, chip->calib0); + mutex_unlock(&chip->lock); + return ret; +} + +static ssize_t tsl2563_calib1_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tsl2563_chip *chip = indio_dev->dev_data; + int ret; + + mutex_lock(&chip->lock); + ret = format_calib(buf, PAGE_SIZE, chip->calib1); + mutex_unlock(&chip->lock); + return ret; +} + +static int do_calib_store(struct device *dev, const char *buf, size_t len, + int ch) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tsl2563_chip *chip = indio_dev->dev_data; + int value; + u32 calib; + + if (1 != sscanf(buf, "%d", &value)) + return -EINVAL; + + calib = calib_from_sysfs(value); + + if (ch) + chip->calib1 = calib; + else + chip->calib0 = calib; + + return len; +} + +static ssize_t tsl2563_calib0_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + return do_calib_store(dev, buf, len, 0); +} + +static ssize_t tsl2563_calib1_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + return do_calib_store(dev, buf, len, 1); +} + +/* AmitXXXX: Convert to IIO_DEV_ATTR_LIGHT* as in tsl2561 + * once I understand what they mean */ +static DEVICE_ATTR(adc0, S_IRUGO, tsl2563_adc0_show, NULL); +static DEVICE_ATTR(adc1, S_IRUGO, tsl2563_adc1_show, NULL); +static DEVICE_ATTR(lux, S_IRUGO, tsl2563_lux_show, NULL); +static DEVICE_ATTR(calib0, S_IRUGO | S_IWUSR, + tsl2563_calib0_show, tsl2563_calib0_store); +static DEVICE_ATTR(calib1, S_IRUGO | S_IWUSR, + tsl2563_calib1_show, tsl2563_calib1_store); + +static struct attribute *tsl2563_attributes[] = { + &dev_attr_adc0.attr, + &dev_attr_adc1.attr, + &dev_attr_lux.attr, + &dev_attr_calib0.attr, + &dev_attr_calib1.attr, + NULL +}; + +static const struct attribute_group tsl2563_group = { + .attrs = tsl2563_attributes, +}; + +/*--------------------------------------------------------------*/ +/* Probe, Attach, Remove */ +/*--------------------------------------------------------------*/ +static struct i2c_driver tsl2563_i2c_driver; + +static int __devinit tsl2563_probe(struct i2c_client *client, + const struct i2c_device_id *device_id) +{ + struct tsl2563_chip *chip; + struct tsl2563_platform_data *pdata = client->dev.platform_data; + int err = 0; + int ret; + u8 id; + + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + i2c_set_clientdata(client, chip); + chip->client = client; + + err = tsl2563_detect(chip); + if (err) { + dev_err(&client->dev, "device not found, error %d \n", -err); + goto fail1; + } + + err = tsl2563_read_id(chip, &id); + if (err) + goto fail1; + + mutex_init(&chip->lock); + + /* Default values used until userspace says otherwise */ + chip->low_thres = 0x0; + chip->high_thres = 0xffff; + chip->gainlevel = tsl2563_gainlevel_table; + chip->intr = TSL2563_INT_PERSIST(4); + chip->calib0 = calib_from_sysfs(CALIB_BASE_SYSFS); + chip->calib1 = calib_from_sysfs(CALIB_BASE_SYSFS); + + if (pdata) + chip->cover_comp_gain = pdata->cover_comp_gain; + else + chip->cover_comp_gain = 1; + + dev_info(&client->dev, "model %d, rev. %d\n", id >> 4, id & 0x0f); + + chip->indio_dev = iio_allocate_device(); + if (!chip->indio_dev) + goto fail1; + chip->indio_dev->attrs = &tsl2563_group; + chip->indio_dev->dev.parent = &client->dev; + chip->indio_dev->dev_data = (void *)(chip); + chip->indio_dev->driver_module = THIS_MODULE; + chip->indio_dev->modes = INDIO_DIRECT_MODE; + ret = iio_device_register(chip->indio_dev); + if (ret) + goto fail1; + + err = tsl2563_configure(chip); + if (err) + goto fail2; + + INIT_DELAYED_WORK(&chip->poweroff_work, tsl2563_poweroff_work); + schedule_delayed_work(&chip->poweroff_work, 5 * HZ); + + return 0; +fail2: + iio_device_unregister(chip->indio_dev); +fail1: + kfree(chip); + return err; +} + +static int tsl2563_remove(struct i2c_client *client) +{ + struct tsl2563_chip *chip = i2c_get_clientdata(client); + + iio_device_unregister(chip->indio_dev); + + kfree(chip); + return 0; +} + +static int tsl2563_suspend(struct i2c_client *client, pm_message_t state) +{ + struct tsl2563_chip *chip = i2c_get_clientdata(client); + int ret; + + mutex_lock(&chip->lock); + + ret = tsl2563_set_power(chip, 0); + if (ret) + goto out; + + chip->state = state; + +out: + mutex_unlock(&chip->lock); + return ret; +} + +static int tsl2563_resume(struct i2c_client *client) +{ + struct tsl2563_chip *chip = i2c_get_clientdata(client); + int ret; + + mutex_lock(&chip->lock); + + ret = tsl2563_set_power(chip, 1); + if (ret) + goto out; + + ret = tsl2563_configure(chip); + if (ret) + goto out; + + chip->state.event = PM_EVENT_ON; + +out: + mutex_unlock(&chip->lock); + return ret; +} + +static const struct i2c_device_id tsl2563_id[] = { + { "tsl2560", 0 }, + { "tsl2561", 1 }, + { "tsl2562", 2 }, + { "tsl2563", 3 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, tsl2563_id); + +static struct i2c_driver tsl2563_i2c_driver = { + .driver = { + .name = "tsl2563", + }, + .suspend = tsl2563_suspend, + .resume = tsl2563_resume, + .probe = tsl2563_probe, + .remove = __devexit_p(tsl2563_remove), + .id_table = tsl2563_id, +}; + +static int __init tsl2563_init(void) +{ + return i2c_add_driver(&tsl2563_i2c_driver); +} + +static void __exit tsl2563_exit(void) +{ + i2c_del_driver(&tsl2563_i2c_driver); +} + +MODULE_AUTHOR("Nokia Corporation"); +MODULE_DESCRIPTION("tsl2563 light sensor driver"); +MODULE_LICENSE("GPL"); + +module_init(tsl2563_init); +module_exit(tsl2563_exit); diff --git a/drivers/staging/iio/light/tsl2563.h b/drivers/staging/iio/light/tsl2563.h new file mode 100644 index 0000000000000000000000000000000000000000..b97368bd7fffd2a4b284832a76d6590965fa1925 --- /dev/null +++ b/drivers/staging/iio/light/tsl2563.h @@ -0,0 +1,9 @@ +#ifndef __LINUX_TSL2563_H +#define __LINUX_TSL2563_H + +struct tsl2563_platform_data { + int cover_comp_gain; +}; + +#endif /* __LINUX_TSL2563_H */ + diff --git a/drivers/staging/iio/ring_generic.h b/drivers/staging/iio/ring_generic.h index d9261897f3324df46bd51af049607f7e33eb1661..93b91b28a02f478ef4fc11b026c4cb36d357a15e 100644 --- a/drivers/staging/iio/ring_generic.h +++ b/drivers/staging/iio/ring_generic.h @@ -25,9 +25,12 @@ int iio_push_ring_event(struct iio_ring_buffer *ring_buf, int event_code, s64 timestamp); /** - * iio_push_or_escallate_ring_event() - escallate or add as appropriate + * iio_push_or_escallate_ring_event() - escalate or add as appropriate + * @ring_buf: ring buffer that is the event source + * @event_code: event indentification code + * @timestamp: time of event * - * Typical usecase is to escallate a 50% ring full to 75% full if noone has yet + * Typical usecase is to escalate a 50% ring full to 75% full if noone has yet * read the first event. Clearly the 50% full is no longer of interest in * typical use case. **/ @@ -37,10 +40,6 @@ int iio_push_or_escallate_ring_event(struct iio_ring_buffer *ring_buf, /** * struct iio_ring_access_funcs - access functions for ring buffers. - * @create: perform allocation - * @init: get ring buffer ready for use - * @_exit: reverse steps in init - * @_free: deallocate ring buffer * @mark_in_use: reference counting, typically to prevent module removal * @unmark_in_use: reduce reference count when no longer using ring buffer * @store_to: actually store stuff to the ring buffer @@ -60,7 +59,7 @@ int iio_push_or_escallate_ring_event(struct iio_ring_buffer *ring_buf, * * The purpose of this structure is to make the ring buffer element * modular as event for a given driver, different usecases may require - * different ring designs (space efficiency vs speed for example. + * different ring designs (space efficiency vs speed for example). * * It is worth noting that a given ring implementation may only support a small * proportion of these functions. The core code 'should' cope fine with any of @@ -91,23 +90,25 @@ struct iio_ring_access_funcs { /** * struct iio_ring_buffer - general ring buffer structure - * @length: [DEVICE]number of datums in ring - * @bpd: [DEVICE]size of individual datum including timestamp - * @loopcount: [INTERN]number of times the ring has looped - * @access_minor_name: [INTERN]store of name of the access chrdev minor number - * sysfs attribute - * @access_handler: [INTERN]chrdev access handling - * @event_minor_name: [INTERN]store of name of the event chrdev minor number - * sysfs attribute - * @ev_int: [INTERN]chrdev interface for the event chrdev - * @shared_ev_pointer: [INTERN]the shared event pointer to allow escalation of + * @dev: ring buffer device struct + * @access_dev: system device struct for the chrdev + * @indio_dev: industrial I/O device structure + * @owner: module that owns the ring buffer (for ref counting) + * @id: unique id number + * @access_id: device id number + * @length: [DEVICE] number of datums in ring + * @bpd: [DEVICE] size of individual datum including timestamp + * @loopcount: [INTERN] number of times the ring has looped + * @access_handler: [INTERN] chrdev access handling + * @ev_int: [INTERN] chrdev interface for the event chrdev + * @shared_ev_pointer: [INTERN] the shared event pointer to allow escalation of * events - * @ring_access: [DRIVER]ring access functions associated with the + * @access: [DRIVER] ring access functions associated with the * implementation. - * @ring_prenable: [DRIVER] function to run prior to marking ring enabled - * @ring_postenable: [DRIVER] function to run after marking ring enabled - * @ring_predisable: [DRIVER] function to run prior to marking ring disabled - * @ring_postdisable: [DRIVER] function to run after marking ring disabled + * @preenable: [DRIVER] function to run prior to marking ring enabled + * @postenable: [DRIVER] function to run after marking ring enabled + * @predisable: [DRIVER] function to run prior to marking ring disabled + * @postdisable: [DRIVER] function to run after marking ring disabled **/ struct iio_ring_buffer { struct device dev; @@ -133,7 +134,10 @@ void iio_ring_buffer_init(struct iio_ring_buffer *ring, struct iio_dev *dev_info); /** - * __iio_init_ring_buffer() - initialize common elements of ring buffers. + * __iio_init_ring_buffer() - initialize common elements of ring buffers + * @ring: ring buffer that is the event source + * @bytes_per_datum: size of individual datum including timestamp + * @length: number of datums in ring **/ static inline void __iio_init_ring_buffer(struct iio_ring_buffer *ring, int bytes_per_datum, int length) @@ -171,7 +175,11 @@ struct iio_scan_el { container_of(_dev_attr, struct iio_scan_el, dev_attr); /** - * iio_scan_el_store() - sysfs scan element selection interface. + * iio_scan_el_store() - sysfs scan element selection interface + * @dev: the target device + * @attr: the device attribute that is being processed + * @buf: input from userspace + * @len: length of input * * A generic function used to enable various scan elements. In some * devices explicit read commands for each channel mean this is merely @@ -184,12 +192,15 @@ ssize_t iio_scan_el_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len); /** * iio_scal_el_show() - sysfs interface to query whether a scan element is - * is enabled or not. + * is enabled or not + * @dev: the target device + * @attr: the device attribute that is being processed + * @buf: output buffer **/ ssize_t iio_scan_el_show(struct device *dev, struct device_attribute *attr, char *buf); /** - * IIO_SCAN_EL: - declare and initialize a scan element without control func + * IIO_SCAN_EL - declare and initialize a scan element without control func * @_name: identifying name. Resulting struct is iio_scan_el_##_name, * sysfs element, scan_en_##_name. * @_number: unique id number for the scan element. @@ -214,8 +225,14 @@ ssize_t iio_scan_el_ts_store(struct device *dev, struct device_attribute *attr, ssize_t iio_scan_el_ts_show(struct device *dev, struct device_attribute *attr, char *buf); /** - * IIO_SCAN_EL_C: - declare and initialize a scan element with a control func + * IIO_SCAN_EL_C - declare and initialize a scan element with a control func * + * @_name: identifying name. Resulting struct is iio_scan_el_##_name, + * sysfs element, scan_en_##_name. + * @_number: unique id number for the scan element. + * @_bits: number of bits in the scan element result (used in mixed bit + * length devices). + * @_label: indentification variable used by drivers. Often a reg address. * @_controlfunc: function used to notify hardware of whether state changes **/ #define IIO_SCAN_EL_C(_name, _number, _bits, _label, _controlfunc) \ @@ -230,7 +247,7 @@ ssize_t iio_scan_el_ts_show(struct device *dev, struct device_attribute *attr, .set_state = _controlfunc, \ } /** - * IIO_SCAN_EL_TIMESTAMP: - declare a special scan element for timestamps + * IIO_SCAN_EL_TIMESTAMP - declare a special scan element for timestamps * * Odd one out. Handled slightly differently from other scan elements. **/ diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h index ae70ee0538fb3f0cf8956b447e973a13942ff198..f0b86f02cd808afc287db224cc1f1f21b9cabe1f 100644 --- a/drivers/staging/iio/ring_sw.h +++ b/drivers/staging/iio/ring_sw.h @@ -36,52 +36,65 @@ #if defined CONFIG_IIO_SW_RING || defined CONFIG_IIO_SW_RING_MODULE /** - * iio_create_sw_rb() software ring buffer allocation + * iio_create_sw_rb() - software ring buffer allocation * @r: pointer to ring buffer pointer **/ int iio_create_sw_rb(struct iio_ring_buffer **r); /** - * iio_init_sw_rb() initialize the software ring buffer + * iio_init_sw_rb() - initialize the software ring buffer * @r: pointer to a software ring buffer created by an - * iio_create_sw_rb call. + * iio_create_sw_rb call + * @indio_dev: industrial I/O device structure **/ int iio_init_sw_rb(struct iio_ring_buffer *r, struct iio_dev *indio_dev); + /** - * iio_exit_sw_rb() reverse what was done in iio_init_sw_rb + * iio_exit_sw_rb() - reverse what was done in iio_init_sw_rb + * @r: pointer to a software ring buffer created by an + * iio_create_sw_rb call **/ void iio_exit_sw_rb(struct iio_ring_buffer *r); /** - * iio_free_sw_rb() free memory occupied by the core ring buffer struct + * iio_free_sw_rb() - free memory occupied by the core ring buffer struct + * @r: pointer to a software ring buffer created by an + * iio_create_sw_rb call **/ void iio_free_sw_rb(struct iio_ring_buffer *r); /** - * iio_mark_sw_rb_in_use() reference counting to prevent incorrect chances + * iio_mark_sw_rb_in_use() - reference counting to prevent incorrect chances + * @r: pointer to a software ring buffer created by an + * iio_create_sw_rb call **/ void iio_mark_sw_rb_in_use(struct iio_ring_buffer *r); /** - * iio_unmark_sw_rb_in_use() notify the ring buffer that we don't care anymore + * iio_unmark_sw_rb_in_use() - notify the ring buffer that we don't care anymore + * @r: pointer to a software ring buffer created by an + * iio_create_sw_rb call **/ void iio_unmark_sw_rb_in_use(struct iio_ring_buffer *r); /** - * iio_read_last_from_sw_rb() attempt to read the last stored datum from the rb + * iio_read_last_from_sw_rb() - attempt to read the last stored datum from the rb + * @r: pointer to a software ring buffer created by an + * iio_create_sw_rb call + * @data: where to store the last datum **/ int iio_read_last_from_sw_rb(struct iio_ring_buffer *r, u8 *data); /** - * iio_store_to_sw_rb() store a new datum to the ring buffer - * @rb: pointer to ring buffer instance - * @data: the datum to be stored including timestamp if relevant. - * @timestamp: timestamp which will be attached to buffer events if relevant. + * iio_store_to_sw_rb() - store a new datum to the ring buffer + * @r: pointer to ring buffer instance + * @data: the datum to be stored including timestamp if relevant + * @timestamp: timestamp which will be attached to buffer events if relevant **/ int iio_store_to_sw_rb(struct iio_ring_buffer *r, u8 *data, s64 timestamp); /** - * iio_rip_sw_rb() attempt to read data from the ring buffer + * iio_rip_sw_rb() - attempt to read data from the ring buffer * @r: ring buffer instance * @count: number of datum's to try and read * @data: where the data will be stored. @@ -94,38 +107,53 @@ int iio_rip_sw_rb(struct iio_ring_buffer *r, int *dead_offset); /** - * iio_request_update_sw_rb() update params if update needed + * iio_request_update_sw_rb() - update params if update needed + * @r: pointer to a software ring buffer created by an + * iio_create_sw_rb call **/ int iio_request_update_sw_rb(struct iio_ring_buffer *r); /** - * iio_mark_update_needed_sw_rb() tell the ring buffer it needs a param update + * iio_mark_update_needed_sw_rb() - tell the ring buffer it needs a param update + * @r: pointer to a software ring buffer created by an + * iio_create_sw_rb call **/ int iio_mark_update_needed_sw_rb(struct iio_ring_buffer *r); /** - * iio_get_bpd_sw_rb() get the datum size in bytes + * iio_get_bpd_sw_rb() - get the datum size in bytes + * @r: pointer to a software ring buffer created by an + * iio_create_sw_rb call **/ int iio_get_bpd_sw_rb(struct iio_ring_buffer *r); /** - * iio_set_bpd_sw_rb() set the datum size in bytes + * iio_set_bpd_sw_rb() - set the datum size in bytes + * @r: pointer to a software ring buffer created by an + * iio_create_sw_rb call + * @bpd: bytes per datum value **/ int iio_set_bpd_sw_rb(struct iio_ring_buffer *r, size_t bpd); /** - * iio_get_length_sw_rb() get how many datums the rb may contain + * iio_get_length_sw_rb() - get how many datums the rb may contain + * @r: pointer to a software ring buffer created by an + * iio_create_sw_rb call **/ int iio_get_length_sw_rb(struct iio_ring_buffer *r); /** - * iio_set_length_sw_rb() set how many datums the rb may contain + * iio_set_length_sw_rb() - set how many datums the rb may contain + * @r: pointer to a software ring buffer created by an + * iio_create_sw_rb call + * @length: max number of data items for the ring buffer **/ int iio_set_length_sw_rb(struct iio_ring_buffer *r, int length); /** - * iio_ring_sw_register_funcs() helper function to set up rb access + * iio_ring_sw_register_funcs() - helper function to set up rb access + * @ra: pointer to @iio_ring_access_funcs **/ static inline void iio_ring_sw_register_funcs(struct iio_ring_access_funcs *ra) { diff --git a/drivers/staging/iio/sysfs.h b/drivers/staging/iio/sysfs.h index bfe4055c0ed2a6d256e772156cb31e42c221b32b..e501e1338e11bb3491af13b2845fd6cd8fdb073d 100644 --- a/drivers/staging/iio/sysfs.h +++ b/drivers/staging/iio/sysfs.h @@ -15,7 +15,7 @@ #include "iio.h" /** - * struct iio_event_attribute - event control attribute + * struct iio_event_attr - event control attribute * @dev_attr: underlying device attribute * @mask: mask for the event when detecting * @listel: list header to allow addition to list of event handlers @@ -54,6 +54,7 @@ __init_iio_chrdev_minor_attr(struct iio_chrdev_minor_attr *minor_attr, * struct iio_dev_attr - iio specific device attribute * @dev_attr: underlying device attribute * @address: associated register address + * @val2: secondary attribute value */ struct iio_dev_attr { struct device_attribute dev_attr; @@ -71,6 +72,8 @@ ssize_t iio_read_const_attr(struct device *dev, /** * struct iio_const_attr - constant device specific attribute * often used for things like available modes + * @string: attribute string + * @dev_attr: underlying device attribute */ struct iio_const_attr { const char *string; @@ -80,7 +83,7 @@ struct iio_const_attr { #define to_iio_const_attr(_dev_attr) \ container_of(_dev_attr, struct iio_const_attr, dev_attr) -/* Some attributes will be hard coded (device dependant) and not require an +/* Some attributes will be hard coded (device dependent) and not require an address, in these cases pass a negative */ #define IIO_ATTR(_name, _mode, _show, _store, _addr) \ { .dev_attr = __ATTR(_name, _mode, _show, _store), \ @@ -108,102 +111,130 @@ struct iio_const_attr { /* Generic attributes of onetype or another */ /** - * IIO_DEV_ATTR_REG: revision number for the device + * IIO_DEV_ATTR_REV - revision number for the device + * @_show: output method for the attribute * * Very much device dependent. **/ #define IIO_DEV_ATTR_REV(_show) \ IIO_DEVICE_ATTR(revision, S_IRUGO, _show, NULL, 0) + /** - * IIO_DEV_ATTR_NAME: chip type dependant identifier + * IIO_DEV_ATTR_NAME - chip type dependent identifier + * @_show: output method for the attribute **/ #define IIO_DEV_ATTR_NAME(_show) \ IIO_DEVICE_ATTR(name, S_IRUGO, _show, NULL, 0) /** - * IIO_DEV_ATTR_SAMP_FREQ: sets any internal clock frequency + * IIO_DEV_ATTR_SAMP_FREQ - sets any internal clock frequency + * @_mode: sysfs file mode/permissions + * @_show: output method for the attribute + * @_store: input method for the attribute **/ #define IIO_DEV_ATTR_SAMP_FREQ(_mode, _show, _store) \ IIO_DEVICE_ATTR(sampling_frequency, _mode, _show, _store, 0) /** - * IIO_DEV_ATTR_AVAIL_SAMP_FREQ: list available sampling frequencies. + * IIO_DEV_ATTR_AVAIL_SAMP_FREQ - list available sampling frequencies + * @_show: output method for the attribute * - * May be mode dependant on some devices + * May be mode dependent on some devices **/ #define IIO_DEV_ATTR_AVAIL_SAMP_FREQ(_show) \ IIO_DEVICE_ATTR(available_sampling_frequency, S_IRUGO, _show, NULL, 0) /** - * IIO_DEV_ATTR_CONST_AVAIL_SAMP_FREQ: list available sampling frequencies. + * IIO_CONST_ATTR_AVAIL_SAMP_FREQ - list available sampling frequencies + * @_string: frequency string for the attribute * * Constant version **/ #define IIO_CONST_ATTR_AVAIL_SAMP_FREQ(_string) \ IIO_CONST_ATTR(available_sampling_frequency, _string) + /** - * IIO_DEV_ATTR_SCAN_MODE: select a scan mode + * IIO_DEV_ATTR_SCAN_MODE - select a scan mode + * @_mode: sysfs file mode/permissions + * @_show: output method for the attribute + * @_store: input method for the attribute * * This is used when only certain combinations of inputs may be read in one * scan. **/ #define IIO_DEV_ATTR_SCAN_MODE(_mode, _show, _store) \ IIO_DEVICE_ATTR(scan_mode, _mode, _show, _store, 0) + /** - * IIO_DEV_ATTR_AVAIL_SCAN_MODES: list available scan modes + * IIO_DEV_ATTR_AVAIL_SCAN_MODES - list available scan modes + * @_show: output method for the attribute **/ #define IIO_DEV_ATTR_AVAIL_SCAN_MODES(_show) \ IIO_DEVICE_ATTR(available_scan_modes, S_IRUGO, _show, NULL, 0) /** - * IIO_DEV_ATTR_SCAN: result of scan of multiple channels + * IIO_DEV_ATTR_SCAN - result of scan of multiple channels + * @_show: output method for the attribute **/ #define IIO_DEV_ATTR_SCAN(_show) \ IIO_DEVICE_ATTR(scan, S_IRUGO, _show, NULL, 0); /** - * IIO_DEV_ATTR_INPUT: direct read of a single input channel + * IIO_DEV_ATTR_INPUT - direct read of a single input channel + * @_number: input channel number + * @_show: output method for the attribute **/ #define IIO_DEV_ATTR_INPUT(_number, _show) \ IIO_DEVICE_ATTR(in##_number, S_IRUGO, _show, NULL, _number) - /** - * IIO_DEV_ATTR_SW_RING_ENABLE: enable software ring buffer + * IIO_DEV_ATTR_SW_RING_ENABLE - enable software ring buffer + * @_show: output method for the attribute + * @_store: input method for the attribute * - * Success may be dependant on attachment of trigger previously + * Success may be dependent on attachment of trigger previously. **/ #define IIO_DEV_ATTR_SW_RING_ENABLE(_show, _store) \ IIO_DEVICE_ATTR(sw_ring_enable, S_IRUGO | S_IWUSR, _show, _store, 0) /** - * IIO_DEV_ATTR_HW_RING_ENABLE: enable hardware ring buffer + * IIO_DEV_ATTR_HW_RING_ENABLE - enable hardware ring buffer + * @_show: output method for the attribute + * @_store: input method for the attribute * - * This is a different attribute from the software one as one can invision + * This is a different attribute from the software one as one can envision * schemes where a combination of the two may be used. **/ #define IIO_DEV_ATTR_HW_RING_ENABLE(_show, _store) \ IIO_DEVICE_ATTR(hw_ring_enable, S_IRUGO | S_IWUSR, _show, _store, 0) /** - * IIO_DEV_ATTR_BPSE: set number of bits per scan element + * IIO_DEV_ATTR_BPSE - set number of bits per scan element + * @_mode: sysfs file mode/permissions + * @_show: output method for the attribute + * @_store: input method for the attribute **/ #define IIO_DEV_ATTR_BPSE(_mode, _show, _store) \ IIO_DEVICE_ATTR(bpse, _mode, _show, _store, 0) /** - * IIO_DEV_ATTR_BPSE_AVAILABLE: no of bits per scan element supported + * IIO_DEV_ATTR_BPSE_AVAILABLE - number of bits per scan element supported + * @_show: output method for the attribute **/ #define IIO_DEV_ATTR_BPSE_AVAILABLE(_show) \ IIO_DEVICE_ATTR(bpse_available, S_IRUGO, _show, NULL, 0) /** - * IIO_DEV_ATTR_TEMP: many sensors have auxiliary temperature sensors + * IIO_DEV_ATTR_TEMP - many sensors have auxiliary temperature sensors + * @_show: output method for the attribute **/ #define IIO_DEV_ATTR_TEMP(_show) \ IIO_DEVICE_ATTR(temp, S_IRUGO, _show, NULL, 0) + /** - * IIO_EVENT_SH: generic shared event handler + * IIO_EVENT_SH - generic shared event handler + * @_name: event name + * @_handler: handler function to be called * * This is used in cases where more than one event may result from a single * handler. Often the case that some alarm register must be read and multiple @@ -221,8 +252,14 @@ struct iio_const_attr { .prev = &iio_event_##_name.list, \ }, \ }; + /** - * IIO_EVENT_ATTR_SH: generic shared event attribute + * IIO_EVENT_ATTR_SH - generic shared event attribute + * @_name: event name + * @_ev_list: event handler list + * @_show: output method for the attribute + * @_store: input method for the attribute + * @_mask: mask used when detecting the event * * An attribute with an associated IIO_EVENT_SH **/ @@ -235,7 +272,12 @@ struct iio_const_attr { .listel = &_ev_list }; /** - * IIO_EVENT_ATTR: non shared event attribute + * IIO_EVENT_ATTR - non-shared event attribute + * @_name: event name + * @_show: output method for the attribute + * @_store: input method for the attribute + * @_mask: mask used when detecting the event + * @_handler: handler function to be called **/ #define IIO_EVENT_ATTR(_name, _show, _store, _mask, _handler) \ static struct iio_event_handler_list \ @@ -251,10 +293,14 @@ struct iio_const_attr { .listel = &iio_event_##_name }; \ /** - * IIO_EVENT_ATTR_DATA_RDY: event driven by data ready signal + * IIO_EVENT_ATTR_DATA_RDY - event driven by data ready signal + * @_show: output method for the attribute + * @_store: input method for the attribute + * @_mask: mask used when detecting the event + * @_handler: handler function to be called * * Not typically implemented in devices where full triggering support - * has been implemented + * has been implemented. **/ #define IIO_EVENT_ATTR_DATA_RDY(_show, _store, _mask, _handler) \ IIO_EVENT_ATTR(data_rdy, _show, _store, _mask, _handler) @@ -269,19 +315,31 @@ struct iio_const_attr { #define IIO_EVENT_CODE_DEVICE_SPECIFIC 1000 /** - * IIO_EVENT_ATTR_RING_50_FULL: ring buffer event to indicate 50% full + * IIO_EVENT_ATTR_RING_50_FULL - ring buffer event to indicate 50% full + * @_show: output method for the attribute + * @_store: input method for the attribute + * @_mask: mask used when detecting the event + * @_handler: handler function to be called **/ #define IIO_EVENT_ATTR_RING_50_FULL(_show, _store, _mask, _handler) \ IIO_EVENT_ATTR(ring_50_full, _show, _store, _mask, _handler) /** - * IIO_EVENT_ATTR_RING_50_FULL_SH: shared ring event to indicate 50% full + * IIO_EVENT_ATTR_RING_50_FULL_SH - shared ring event to indicate 50% full + * @_evlist: event handler list + * @_show: output method for the attribute + * @_store: input method for the attribute + * @_mask: mask used when detecting the event **/ #define IIO_EVENT_ATTR_RING_50_FULL_SH(_evlist, _show, _store, _mask) \ IIO_EVENT_ATTR_SH(ring_50_full, _evlist, _show, _store, _mask) /** - * IIO_EVENT_ATTR_RING_75_FULL_SH: shared ring event to indicate 75% full + * IIO_EVENT_ATTR_RING_75_FULL_SH - shared ring event to indicate 75% full + * @_evlist: event handler list + * @_show: output method for the attribute + * @_store: input method for the attribute + * @_mask: mask used when detecting the event **/ #define IIO_EVENT_ATTR_RING_75_FULL_SH(_evlist, _show, _store, _mask) \ IIO_EVENT_ATTR_SH(ring_75_full, _evlist, _show, _store, _mask) diff --git a/drivers/staging/iio/trigger.h b/drivers/staging/iio/trigger.h index 8284098c9589c2bb7fbadf59602b51c58b5e7a7d..784e7b6fac1cc745157746ca632b288861296684 100644 --- a/drivers/staging/iio/trigger.h +++ b/drivers/staging/iio/trigger.h @@ -19,16 +19,18 @@ * @id: [INTERN] unique id number * @name: [DRIVER] unique name * @dev: [DRIVER] associated device (if relevant) - * @sysfs_dev: [INTERN] sysfs relevant device * @private_data: [DRIVER] device specific data * @list: [INTERN] used in maintenance of global trigger list * @alloc_list: [DRIVER] used for driver specific trigger list - * @poll_func_list_lock:[INTERN] protection of the polling function list + * @pollfunc_list_lock: [INTERN] protection of the polling function list * @pollfunc_list: [INTERN] list of functions to run on trigger. * @control_attrs: [DRIVER] sysfs attributes relevant to trigger type - * @set_trigger_state: [DRIVER] switch on/off the trigger on demand * @timestamp: [INTERN] timestamp usesd by some trigs (e.g. datardy) * @owner: [DRIVER] used to monitor usage count of the trigger. + * @use_count: use count for the trigger + * @set_trigger_state: [DRIVER] switch on/off the trigger on demand + * @try_reenable: function to reenable the trigger when the + * use count is zero (may be NULL) **/ struct iio_trigger { int id; @@ -68,6 +70,9 @@ static inline void iio_get_trigger(struct iio_trigger *trig) /** * iio_trigger_read_name() - sysfs access function to get the trigger name + * @dev: the system device + * @attr: device attributes for the device + * @buf: output buffer to store the trigger name **/ ssize_t iio_trigger_read_name(struct device *dev, struct device_attribute *attr, @@ -79,6 +84,8 @@ ssize_t iio_trigger_read_name(struct device *dev, /** * iio_trigger_find_by_name() - search global trigger list + * @name: trigger name to search for + * @len: trigger name string length to compare **/ struct iio_trigger *iio_trigger_find_by_name(const char *name, size_t len); @@ -90,32 +97,35 @@ int iio_trigger_register(struct iio_trigger *trig_info); /** * iio_trigger_unregister() - unregister a trigger from the core + * @trig_info: trigger to be unregistered **/ void iio_trigger_unregister(struct iio_trigger *trig_info); /** * iio_trigger_attach_poll_func() - add a function pair to be run on trigger * @trig: trigger to which the function pair are being added - * @pf: poll function pair + * @pf: poll function pair **/ int iio_trigger_attach_poll_func(struct iio_trigger *trig, struct iio_poll_func *pf); /** * iio_trigger_dettach_poll_func() - remove function pair from those to be - * run on trigger. - * @trig: trigger from which the function is being removed. + * run on trigger + * @trig: trigger from which the function is being removed * @pf: poll function pair **/ int iio_trigger_dettach_poll_func(struct iio_trigger *trig, struct iio_poll_func *pf); /** - * iio_trigger_poll() - called on a trigger occuring + * iio_trigger_poll() - called on a trigger occurring + * @trig: trigger which occurred + * * Typically called in relevant hardware interrupt handler. **/ -void iio_trigger_poll(struct iio_trigger *); -void iio_trigger_notify_done(struct iio_trigger *); +void iio_trigger_poll(struct iio_trigger *trig); +void iio_trigger_notify_done(struct iio_trigger *trig); /** * struct iio_poll_func - poll function pair @@ -127,11 +137,10 @@ void iio_trigger_notify_done(struct iio_trigger *); * control on sensor supporting it. * @poll_func_main: function in here is run after all immediates. * Reading from sensor etc typically involves - * scheduling - * from here. + * scheduling from here. * - * The two stage approach used here only important when multiple sensors are - * being triggered by a single trigger. This really comes into it's own with + * The two stage approach used here is only important when multiple sensors are + * being triggered by a single trigger. This really comes into its own with * simultaneous sampling devices where a simple latch command can be used to * make the device store the values on all inputs. **/ diff --git a/drivers/staging/iio/trigger/Kconfig b/drivers/staging/iio/trigger/Kconfig index fdd9301271a437177b55ea998f9148fc1694950d..d842a584a3af35155727607d9c4a3a5a00756968 100644 --- a/drivers/staging/iio/trigger/Kconfig +++ b/drivers/staging/iio/trigger/Kconfig @@ -9,13 +9,13 @@ config IIO_PERIODIC_RTC_TRIGGER tristate "Periodic RTC triggers" depends on RTC_CLASS help - Provides support for using periodic capable real time - clocks as IIO triggers. + Provides support for using periodic capable real time + clocks as IIO triggers. config IIO_GPIO_TRIGGER tristate "GPIO trigger" depends on GENERIC_GPIO help - Provides support for using GPIO pins as IIO triggers. + Provides support for using GPIO pins as IIO triggers. endif # IIO_TRIGGER diff --git a/drivers/staging/iio/trigger_consumer.h b/drivers/staging/iio/trigger_consumer.h index 4c7f527dc79f1a0d1b9eebe1660d16868b84c816..a02d70b0d24ad05e6fd9e5d3a8240e2238997954 100644 --- a/drivers/staging/iio/trigger_consumer.h +++ b/drivers/staging/iio/trigger_consumer.h @@ -10,12 +10,13 @@ #ifdef CONFIG_IIO_TRIGGER /** - * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers. + * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers * @dev_info: iio_dev associated with the device that will consume the trigger **/ int iio_device_register_trigger_consumer(struct iio_dev *dev_info); + /** - * iio_device_unregister_trigger_consumer() - reverse the registration process. + * iio_device_unregister_trigger_consumer() - reverse the registration process * @dev_info: iio_dev associated with the device that consumed the trigger **/ int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info); @@ -23,13 +24,14 @@ int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info); #else /** - * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers. + * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers * @dev_info: iio_dev associated with the device that will consume the trigger **/ int iio_device_register_trigger_consumer(struct iio_dev *dev_info) { return 0; }; + /** * iio_device_unregister_trigger_consumer() - reverse the registration process * @dev_info: iio_dev associated with the device that consumed the trigger diff --git a/drivers/staging/line6/capture.c b/drivers/staging/line6/capture.c index ea2060b4919de7ef9b1d55c5193361d3f11052c0..fd4890de8dbcd3cf6837099d29d5fa608ec5d40c 100644 --- a/drivers/staging/line6/capture.c +++ b/drivers/staging/line6/capture.c @@ -20,7 +20,6 @@ #include "pod.h" #include "capture.h" - /* Find a free URB and submit it. */ @@ -33,7 +32,8 @@ static int submit_audio_in_urb(struct snd_pcm_substream *substream) struct urb *urb_in; spin_lock_irqsave(&line6pcm->lock_audio_in, flags); - index = find_first_zero_bit(&line6pcm->active_urb_in, LINE6_ISO_BUFFERS); + index = + find_first_zero_bit(&line6pcm->active_urb_in, LINE6_ISO_BUFFERS); if (index >= LINE6_ISO_BUFFERS) { spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags); @@ -45,20 +45,24 @@ static int submit_audio_in_urb(struct snd_pcm_substream *substream) urb_size = 0; for (i = 0; i < LINE6_ISO_PACKETS; ++i) { - struct usb_iso_packet_descriptor *fin = &urb_in->iso_frame_desc[i]; + struct usb_iso_packet_descriptor *fin = + &urb_in->iso_frame_desc[i]; fin->offset = urb_size; fin->length = line6pcm->max_packet_size; urb_size += line6pcm->max_packet_size; } - urb_in->transfer_buffer = line6pcm->buffer_in + index * LINE6_ISO_PACKETS * line6pcm->max_packet_size; + urb_in->transfer_buffer = + line6pcm->buffer_in + + index * LINE6_ISO_PACKETS * line6pcm->max_packet_size; urb_in->transfer_buffer_length = urb_size; urb_in->context = substream; if (usb_submit_urb(urb_in, GFP_ATOMIC) == 0) set_bit(index, &line6pcm->active_urb_in); else - dev_err(s2m(substream), "URB in #%d submission failed\n", index); + dev_err(s2m(substream), "URB in #%d submission failed\n", + index); spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags); return 0; @@ -143,7 +147,8 @@ static void audio_in_callback(struct urb *urb) int frames; unsigned long flags; - struct snd_pcm_substream *substream = (struct snd_pcm_substream *)urb->context; + struct snd_pcm_substream *substream = + (struct snd_pcm_substream *)urb->context; struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); const int bytes_per_frame = line6pcm->properties->bytes_per_frame; struct snd_pcm_runtime *runtime = substream->runtime; @@ -155,8 +160,11 @@ static void audio_in_callback(struct urb *urb) #if DO_DUMP_PCM_RECEIVE for (i = 0; i < LINE6_ISO_PACKETS; ++i) { - struct usb_iso_packet_descriptor *fout = &urb->iso_frame_desc[i]; - line6_write_hexdump(line6pcm->line6, 'C', urb->transfer_buffer + fout->offset, fout->length); + struct usb_iso_packet_descriptor *fout = + &urb->iso_frame_desc[i]; + line6_write_hexdump(line6pcm->line6, 'C', + urb->transfer_buffer + fout->offset, + fout->length); } #endif @@ -179,25 +187,40 @@ static void audio_in_callback(struct urb *urb) if (fsize > 0) { frames = fsize / bytes_per_frame; - if (line6pcm->pos_in_done + frames > runtime->buffer_size) { + if (line6pcm->pos_in_done + frames > + runtime->buffer_size) { /* - The transferred area goes over buffer boundary, - copy two separate chunks. - */ + The transferred area goes over buffer + boundary, copy two separate chunks. + */ int len; - len = runtime->buffer_size - line6pcm->pos_in_done; + len = + runtime->buffer_size - + line6pcm->pos_in_done; if (len > 0) { - memcpy(runtime->dma_area + line6pcm->pos_in_done * bytes_per_frame, fbuf, len * bytes_per_frame); - memcpy(runtime->dma_area, fbuf + len * bytes_per_frame, (frames - len) * bytes_per_frame); - } else - dev_err(s2m(substream), "driver bug: len = %d\n", len); /* this is somewhat paranoid */ + memcpy(runtime->dma_area + + line6pcm->pos_in_done * + bytes_per_frame, fbuf, + len * bytes_per_frame); + memcpy(runtime->dma_area, + fbuf + len * bytes_per_frame, + (frames - + len) * bytes_per_frame); + } else { + /* this is somewhat paranoid */ + dev_err(s2m(substream), + "driver bug: len = %d\n", len); + } } else { /* copy single chunk */ - memcpy(runtime->dma_area + line6pcm->pos_in_done * bytes_per_frame, fbuf, fsize * bytes_per_frame); + memcpy(runtime->dma_area + + line6pcm->pos_in_done * bytes_per_frame, + fbuf, fsize * bytes_per_frame); } - if ((line6pcm->pos_in_done += frames) >= runtime->buffer_size) + line6pcm->pos_in_done += frames; + if (line6pcm->pos_in_done >= runtime->buffer_size) line6pcm->pos_in_done -= runtime->buffer_size; } } @@ -212,7 +235,8 @@ static void audio_in_callback(struct urb *urb) if (!shutdown) { submit_audio_in_urb(substream); - if ((line6pcm->bytes_in += length) >= line6pcm->period_in) { + line6pcm->bytes_in += length; + if (line6pcm->bytes_in >= line6pcm->period_in) { line6pcm->bytes_in -= line6pcm->period_in; snd_pcm_period_elapsed(substream); } @@ -228,7 +252,8 @@ static int snd_line6_capture_open(struct snd_pcm_substream *substream) err = snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - (&line6pcm->properties->snd_line6_rates)); + (&line6pcm->properties-> + snd_line6_rates)); if (err < 0) return err; @@ -267,7 +292,9 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream, return ret; line6pcm->period_in = params_period_bytes(hw_params); - line6pcm->buffer_in = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * LINE6_ISO_PACKET_SIZE_MAX, GFP_KERNEL); + line6pcm->buffer_in = + kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * + LINE6_ISO_PACKET_SIZE_MAX, GFP_KERNEL); if (!line6pcm->buffer_in) { dev_err(s2m(substream), "cannot malloc buffer_in\n"); @@ -302,7 +329,8 @@ int snd_line6_capture_trigger(struct snd_pcm_substream *substream, int cmd) err = submit_audio_in_all_urbs(substream); if (err < 0) { - clear_bit(BIT_RUNNING_CAPTURE, &line6pcm->flags); + clear_bit(BIT_RUNNING_CAPTURE, + &line6pcm->flags); return err; } } @@ -332,14 +360,14 @@ snd_line6_capture_pointer(struct snd_pcm_substream *substream) /* capture operators */ struct snd_pcm_ops snd_line6_capture_ops = { - .open = snd_line6_capture_open, - .close = snd_line6_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_line6_capture_hw_params, - .hw_free = snd_line6_capture_hw_free, - .prepare = snd_line6_prepare, - .trigger = snd_line6_trigger, - .pointer = snd_line6_capture_pointer, + .open = snd_line6_capture_open, + .close = snd_line6_capture_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_line6_capture_hw_params, + .hw_free = snd_line6_capture_hw_free, + .prepare = snd_line6_prepare, + .trigger = snd_line6_trigger, + .pointer = snd_line6_capture_pointer, }; int create_audio_in_urbs(struct snd_line6_pcm *line6pcm) @@ -351,7 +379,8 @@ int create_audio_in_urbs(struct snd_line6_pcm *line6pcm) struct urb *urb; /* URB for audio in: */ - urb = line6pcm->urb_audio_in[i] = usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL); + urb = line6pcm->urb_audio_in[i] = + usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL); if (urb == NULL) { dev_err(line6pcm->line6->ifcdev, "Out of memory\n"); @@ -359,7 +388,10 @@ int create_audio_in_urbs(struct snd_line6_pcm *line6pcm) } urb->dev = line6pcm->line6->usbdev; - urb->pipe = usb_rcvisocpipe(line6pcm->line6->usbdev, line6pcm->ep_audio_read & USB_ENDPOINT_NUMBER_MASK); + urb->pipe = + usb_rcvisocpipe(line6pcm->line6->usbdev, + line6pcm-> + ep_audio_read & USB_ENDPOINT_NUMBER_MASK); urb->transfer_flags = URB_ISO_ASAP; urb->start_frame = -1; urb->number_of_packets = LINE6_ISO_PACKETS; diff --git a/drivers/staging/line6/control.c b/drivers/staging/line6/control.c index 23ad08e17f84c49fbf0ccbde4bb2227f7233d3e8..0b598526de622cf488a8f729d678e33226f48e58 100644 --- a/drivers/staging/line6/control.c +++ b/drivers/staging/line6/control.c @@ -22,18 +22,18 @@ struct device_attribute dev_attr_##_name1 = __ATTR(_name2, _mode, _show, _store) #define LINE6_PARAM_R(PREFIX, prefix, type, param) \ -static ssize_t prefix ## _get_ ## param(struct device *dev, \ +static ssize_t prefix##_get_##param(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ - return prefix ## _get_param_ ## type(dev, buf, PREFIX ## _ ## param); \ + return prefix##_get_param_##type(dev, buf, PREFIX##_##param); \ } #define LINE6_PARAM_RW(PREFIX, prefix, type, param) \ LINE6_PARAM_R(PREFIX, prefix, type, param); \ -static ssize_t prefix ## _set_ ## param(struct device *dev, \ +static ssize_t prefix##_set_##param(struct device *dev, \ struct device_attribute *attr, const char *buf, size_t count) \ { \ - return prefix ## _set_param_ ## type(dev, buf, count, PREFIX ## _ ## param); \ + return prefix##_set_param_##type(dev, buf, count, PREFIX##_##param); \ } #define POD_PARAM_R(type, param) LINE6_PARAM_R(POD, pod, type, param) @@ -41,7 +41,6 @@ static ssize_t prefix ## _set_ ## param(struct device *dev, \ #define VARIAX_PARAM_R(type, param) LINE6_PARAM_R(VARIAX, variax, type, param) #define VARIAX_PARAM_RW(type, param) LINE6_PARAM_RW(VARIAX, variax, type, param) - static ssize_t pod_get_param_int(struct device *dev, char *buf, int param) { struct usb_interface *interface = to_usb_interface(dev); @@ -52,11 +51,18 @@ static ssize_t pod_get_param_int(struct device *dev, char *buf, int param) return sprintf(buf, "%d\n", pod->prog_data.control[param]); } -static ssize_t pod_set_param_int(struct device *dev, const char *buf, size_t count, int param) +static ssize_t pod_set_param_int(struct device *dev, const char *buf, + size_t count, int param) { struct usb_interface *interface = to_usb_interface(dev); struct usb_line6_pod *pod = usb_get_intfdata(interface); - int value = simple_strtoul(buf, NULL, 10); + unsigned long value; + int retval; + + retval = strict_strtoul(buf, 10, &value); + if (retval) + return retval; + pod_transmit_parameter(pod, param, value); return count; } @@ -74,13 +80,13 @@ static ssize_t variax_get_param_int(struct device *dev, char *buf, int param) static ssize_t variax_get_param_float(struct device *dev, char *buf, int param) { /* - We do our own floating point handling here since floats in the - kernel are problematic for at least two reasons: - many distros - are still shipped with binary kernels optimized for the ancient - 80386 without FPU - - there isn't a printf("%f") - (see http://www.kernelthread.com/publications/faq/335.html) - */ + We do our own floating point handling here since floats in the + kernel are problematic for at least two reasons: - many distros + are still shipped with binary kernels optimized for the ancient + 80386 without FPU + - there isn't a printf("%f") + (see http://www.kernelthread.com/publications/faq/335.html) + */ static const int BIAS = 0x7f; static const int OFFSET = 0xf; @@ -110,10 +116,13 @@ static ssize_t variax_get_param_float(struct device *dev, char *buf, int param) part_frac = (mantissa << (32 + exponent)) & 0xffffffff; } - part_frac = (part_frac / ((1UL << 31) / (PRECISION / 2 * 10)) + 5) / 10; + part_frac = + (part_frac / ((1UL << 31) / (PRECISION / 2 * 10)) + 5) / 10; } - len += sprintf(buf + len, "%s%d.%03d\n", ((p[0] & 0x80) ? "-" : ""), part_int, part_frac); + len += + sprintf(buf + len, "%s%d.%03d\n", ((p[0] & 0x80) ? "-" : ""), + part_int, part_frac); return len; } @@ -260,127 +269,246 @@ VARIAX_PARAM_R(float, mix1); VARIAX_PARAM_R(int, pickup_wiring); static DEVICE_ATTR(tweak, S_IWUGO | S_IRUGO, pod_get_tweak, pod_set_tweak); -static DEVICE_ATTR(wah_position, S_IWUGO | S_IRUGO, pod_get_wah_position, pod_set_wah_position); -static DEVICE_ATTR(compression_gain, S_IWUGO | S_IRUGO, pod_get_compression_gain, pod_set_compression_gain); -static DEVICE_ATTR(vol_pedal_position, S_IWUGO | S_IRUGO, pod_get_vol_pedal_position, pod_set_vol_pedal_position); -static DEVICE_ATTR(compression_threshold, S_IWUGO | S_IRUGO, pod_get_compression_threshold, pod_set_compression_threshold); +static DEVICE_ATTR(wah_position, S_IWUGO | S_IRUGO, pod_get_wah_position, + pod_set_wah_position); +static DEVICE_ATTR(compression_gain, S_IWUGO | S_IRUGO, + pod_get_compression_gain, pod_set_compression_gain); +static DEVICE_ATTR(vol_pedal_position, S_IWUGO | S_IRUGO, + pod_get_vol_pedal_position, pod_set_vol_pedal_position); +static DEVICE_ATTR(compression_threshold, S_IWUGO | S_IRUGO, + pod_get_compression_threshold, + pod_set_compression_threshold); static DEVICE_ATTR(pan, S_IWUGO | S_IRUGO, pod_get_pan, pod_set_pan); -static DEVICE_ATTR(amp_model_setup, S_IWUGO | S_IRUGO, pod_get_amp_model_setup, pod_set_amp_model_setup); -static DEVICE_ATTR(amp_model, S_IWUGO | S_IRUGO, pod_get_amp_model, pod_set_amp_model); +static DEVICE_ATTR(amp_model_setup, S_IWUGO | S_IRUGO, pod_get_amp_model_setup, + pod_set_amp_model_setup); +static DEVICE_ATTR(amp_model, S_IWUGO | S_IRUGO, pod_get_amp_model, + pod_set_amp_model); static DEVICE_ATTR(drive, S_IWUGO | S_IRUGO, pod_get_drive, pod_set_drive); static DEVICE_ATTR(bass, S_IWUGO | S_IRUGO, pod_get_bass, pod_set_bass); static DEVICE_ATTR(mid, S_IWUGO | S_IRUGO, pod_get_mid, pod_set_mid); static DEVICE_ATTR(lowmid, S_IWUGO | S_IRUGO, pod_get_lowmid, pod_set_lowmid); static DEVICE_ATTR(treble, S_IWUGO | S_IRUGO, pod_get_treble, pod_set_treble); -static DEVICE_ATTR(highmid, S_IWUGO | S_IRUGO, pod_get_highmid, pod_set_highmid); -static DEVICE_ATTR(chan_vol, S_IWUGO | S_IRUGO, pod_get_chan_vol, pod_set_chan_vol); -static DEVICE_ATTR(reverb_mix, S_IWUGO | S_IRUGO, pod_get_reverb_mix, pod_set_reverb_mix); -static DEVICE_ATTR(effect_setup, S_IWUGO | S_IRUGO, pod_get_effect_setup, pod_set_effect_setup); -static DEVICE_ATTR(band_1_frequency, S_IWUGO | S_IRUGO, pod_get_band_1_frequency, pod_set_band_1_frequency); -static DEVICE_ATTR(presence, S_IWUGO | S_IRUGO, pod_get_presence, pod_set_presence); -static DEVICE_ATTR2(treble__bass, treble, S_IWUGO | S_IRUGO, pod_get_treble__bass, pod_set_treble__bass); -static DEVICE_ATTR(noise_gate_enable, S_IWUGO | S_IRUGO, pod_get_noise_gate_enable, pod_set_noise_gate_enable); -static DEVICE_ATTR(gate_threshold, S_IWUGO | S_IRUGO, pod_get_gate_threshold, pod_set_gate_threshold); -static DEVICE_ATTR(gate_decay_time, S_IWUGO | S_IRUGO, pod_get_gate_decay_time, pod_set_gate_decay_time); -static DEVICE_ATTR(stomp_enable, S_IWUGO | S_IRUGO, pod_get_stomp_enable, pod_set_stomp_enable); -static DEVICE_ATTR(comp_enable, S_IWUGO | S_IRUGO, pod_get_comp_enable, pod_set_comp_enable); -static DEVICE_ATTR(stomp_time, S_IWUGO | S_IRUGO, pod_get_stomp_time, pod_set_stomp_time); -static DEVICE_ATTR(delay_enable, S_IWUGO | S_IRUGO, pod_get_delay_enable, pod_set_delay_enable); -static DEVICE_ATTR(mod_param_1, S_IWUGO | S_IRUGO, pod_get_mod_param_1, pod_set_mod_param_1); -static DEVICE_ATTR(delay_param_1, S_IWUGO | S_IRUGO, pod_get_delay_param_1, pod_set_delay_param_1); -static DEVICE_ATTR(delay_param_1_note_value, S_IWUGO | S_IRUGO, pod_get_delay_param_1_note_value, pod_set_delay_param_1_note_value); -static DEVICE_ATTR2(band_2_frequency__bass, band_2_frequency, S_IWUGO | S_IRUGO, pod_get_band_2_frequency__bass, pod_set_band_2_frequency__bass); -static DEVICE_ATTR(delay_param_2, S_IWUGO | S_IRUGO, pod_get_delay_param_2, pod_set_delay_param_2); -static DEVICE_ATTR(delay_volume_mix, S_IWUGO | S_IRUGO, pod_get_delay_volume_mix, pod_set_delay_volume_mix); -static DEVICE_ATTR(delay_param_3, S_IWUGO | S_IRUGO, pod_get_delay_param_3, pod_set_delay_param_3); -static DEVICE_ATTR(reverb_enable, S_IWUGO | S_IRUGO, pod_get_reverb_enable, pod_set_reverb_enable); -static DEVICE_ATTR(reverb_type, S_IWUGO | S_IRUGO, pod_get_reverb_type, pod_set_reverb_type); -static DEVICE_ATTR(reverb_decay, S_IWUGO | S_IRUGO, pod_get_reverb_decay, pod_set_reverb_decay); -static DEVICE_ATTR(reverb_tone, S_IWUGO | S_IRUGO, pod_get_reverb_tone, pod_set_reverb_tone); -static DEVICE_ATTR(reverb_pre_delay, S_IWUGO | S_IRUGO, pod_get_reverb_pre_delay, pod_set_reverb_pre_delay); -static DEVICE_ATTR(reverb_pre_post, S_IWUGO | S_IRUGO, pod_get_reverb_pre_post, pod_set_reverb_pre_post); -static DEVICE_ATTR(band_2_frequency, S_IWUGO | S_IRUGO, pod_get_band_2_frequency, pod_set_band_2_frequency); -static DEVICE_ATTR2(band_3_frequency__bass, band_3_frequency, S_IWUGO | S_IRUGO, pod_get_band_3_frequency__bass, pod_set_band_3_frequency__bass); -static DEVICE_ATTR(wah_enable, S_IWUGO | S_IRUGO, pod_get_wah_enable, pod_set_wah_enable); -static DEVICE_ATTR(modulation_lo_cut, S_IWUGO | S_IRUGO, pod_get_modulation_lo_cut, pod_set_modulation_lo_cut); -static DEVICE_ATTR(delay_reverb_lo_cut, S_IWUGO | S_IRUGO, pod_get_delay_reverb_lo_cut, pod_set_delay_reverb_lo_cut); -static DEVICE_ATTR(volume_pedal_minimum, S_IWUGO | S_IRUGO, pod_get_volume_pedal_minimum, pod_set_volume_pedal_minimum); -static DEVICE_ATTR(eq_pre_post, S_IWUGO | S_IRUGO, pod_get_eq_pre_post, pod_set_eq_pre_post); -static DEVICE_ATTR(volume_pre_post, S_IWUGO | S_IRUGO, pod_get_volume_pre_post, pod_set_volume_pre_post); -static DEVICE_ATTR(di_model, S_IWUGO | S_IRUGO, pod_get_di_model, pod_set_di_model); -static DEVICE_ATTR(di_delay, S_IWUGO | S_IRUGO, pod_get_di_delay, pod_set_di_delay); -static DEVICE_ATTR(mod_enable, S_IWUGO | S_IRUGO, pod_get_mod_enable, pod_set_mod_enable); -static DEVICE_ATTR(mod_param_1_note_value, S_IWUGO | S_IRUGO, pod_get_mod_param_1_note_value, pod_set_mod_param_1_note_value); -static DEVICE_ATTR(mod_param_2, S_IWUGO | S_IRUGO, pod_get_mod_param_2, pod_set_mod_param_2); -static DEVICE_ATTR(mod_param_3, S_IWUGO | S_IRUGO, pod_get_mod_param_3, pod_set_mod_param_3); -static DEVICE_ATTR(mod_param_4, S_IWUGO | S_IRUGO, pod_get_mod_param_4, pod_set_mod_param_4); -static DEVICE_ATTR(mod_param_5, S_IWUGO | S_IRUGO, pod_get_mod_param_5, pod_set_mod_param_5); -static DEVICE_ATTR(mod_volume_mix, S_IWUGO | S_IRUGO, pod_get_mod_volume_mix, pod_set_mod_volume_mix); -static DEVICE_ATTR(mod_pre_post, S_IWUGO | S_IRUGO, pod_get_mod_pre_post, pod_set_mod_pre_post); -static DEVICE_ATTR(modulation_model, S_IWUGO | S_IRUGO, pod_get_modulation_model, pod_set_modulation_model); -static DEVICE_ATTR(band_3_frequency, S_IWUGO | S_IRUGO, pod_get_band_3_frequency, pod_set_band_3_frequency); -static DEVICE_ATTR2(band_4_frequency__bass, band_4_frequency, S_IWUGO | S_IRUGO, pod_get_band_4_frequency__bass, pod_set_band_4_frequency__bass); -static DEVICE_ATTR(mod_param_1_double_precision, S_IWUGO | S_IRUGO, pod_get_mod_param_1_double_precision, pod_set_mod_param_1_double_precision); -static DEVICE_ATTR(delay_param_1_double_precision, S_IWUGO | S_IRUGO, pod_get_delay_param_1_double_precision, pod_set_delay_param_1_double_precision); -static DEVICE_ATTR(eq_enable, S_IWUGO | S_IRUGO, pod_get_eq_enable, pod_set_eq_enable); +static DEVICE_ATTR(highmid, S_IWUGO | S_IRUGO, pod_get_highmid, + pod_set_highmid); +static DEVICE_ATTR(chan_vol, S_IWUGO | S_IRUGO, pod_get_chan_vol, + pod_set_chan_vol); +static DEVICE_ATTR(reverb_mix, S_IWUGO | S_IRUGO, pod_get_reverb_mix, + pod_set_reverb_mix); +static DEVICE_ATTR(effect_setup, S_IWUGO | S_IRUGO, pod_get_effect_setup, + pod_set_effect_setup); +static DEVICE_ATTR(band_1_frequency, S_IWUGO | S_IRUGO, + pod_get_band_1_frequency, pod_set_band_1_frequency); +static DEVICE_ATTR(presence, S_IWUGO | S_IRUGO, pod_get_presence, + pod_set_presence); +static DEVICE_ATTR2(treble__bass, treble, S_IWUGO | S_IRUGO, + pod_get_treble__bass, pod_set_treble__bass); +static DEVICE_ATTR(noise_gate_enable, S_IWUGO | S_IRUGO, + pod_get_noise_gate_enable, pod_set_noise_gate_enable); +static DEVICE_ATTR(gate_threshold, S_IWUGO | S_IRUGO, pod_get_gate_threshold, + pod_set_gate_threshold); +static DEVICE_ATTR(gate_decay_time, S_IWUGO | S_IRUGO, pod_get_gate_decay_time, + pod_set_gate_decay_time); +static DEVICE_ATTR(stomp_enable, S_IWUGO | S_IRUGO, pod_get_stomp_enable, + pod_set_stomp_enable); +static DEVICE_ATTR(comp_enable, S_IWUGO | S_IRUGO, pod_get_comp_enable, + pod_set_comp_enable); +static DEVICE_ATTR(stomp_time, S_IWUGO | S_IRUGO, pod_get_stomp_time, + pod_set_stomp_time); +static DEVICE_ATTR(delay_enable, S_IWUGO | S_IRUGO, pod_get_delay_enable, + pod_set_delay_enable); +static DEVICE_ATTR(mod_param_1, S_IWUGO | S_IRUGO, pod_get_mod_param_1, + pod_set_mod_param_1); +static DEVICE_ATTR(delay_param_1, S_IWUGO | S_IRUGO, pod_get_delay_param_1, + pod_set_delay_param_1); +static DEVICE_ATTR(delay_param_1_note_value, S_IWUGO | S_IRUGO, + pod_get_delay_param_1_note_value, + pod_set_delay_param_1_note_value); +static DEVICE_ATTR2(band_2_frequency__bass, band_2_frequency, S_IWUGO | S_IRUGO, + pod_get_band_2_frequency__bass, + pod_set_band_2_frequency__bass); +static DEVICE_ATTR(delay_param_2, S_IWUGO | S_IRUGO, pod_get_delay_param_2, + pod_set_delay_param_2); +static DEVICE_ATTR(delay_volume_mix, S_IWUGO | S_IRUGO, + pod_get_delay_volume_mix, pod_set_delay_volume_mix); +static DEVICE_ATTR(delay_param_3, S_IWUGO | S_IRUGO, pod_get_delay_param_3, + pod_set_delay_param_3); +static DEVICE_ATTR(reverb_enable, S_IWUGO | S_IRUGO, pod_get_reverb_enable, + pod_set_reverb_enable); +static DEVICE_ATTR(reverb_type, S_IWUGO | S_IRUGO, pod_get_reverb_type, + pod_set_reverb_type); +static DEVICE_ATTR(reverb_decay, S_IWUGO | S_IRUGO, pod_get_reverb_decay, + pod_set_reverb_decay); +static DEVICE_ATTR(reverb_tone, S_IWUGO | S_IRUGO, pod_get_reverb_tone, + pod_set_reverb_tone); +static DEVICE_ATTR(reverb_pre_delay, S_IWUGO | S_IRUGO, + pod_get_reverb_pre_delay, pod_set_reverb_pre_delay); +static DEVICE_ATTR(reverb_pre_post, S_IWUGO | S_IRUGO, pod_get_reverb_pre_post, + pod_set_reverb_pre_post); +static DEVICE_ATTR(band_2_frequency, S_IWUGO | S_IRUGO, + pod_get_band_2_frequency, pod_set_band_2_frequency); +static DEVICE_ATTR2(band_3_frequency__bass, band_3_frequency, S_IWUGO | S_IRUGO, + pod_get_band_3_frequency__bass, + pod_set_band_3_frequency__bass); +static DEVICE_ATTR(wah_enable, S_IWUGO | S_IRUGO, pod_get_wah_enable, + pod_set_wah_enable); +static DEVICE_ATTR(modulation_lo_cut, S_IWUGO | S_IRUGO, + pod_get_modulation_lo_cut, pod_set_modulation_lo_cut); +static DEVICE_ATTR(delay_reverb_lo_cut, S_IWUGO | S_IRUGO, + pod_get_delay_reverb_lo_cut, pod_set_delay_reverb_lo_cut); +static DEVICE_ATTR(volume_pedal_minimum, S_IWUGO | S_IRUGO, + pod_get_volume_pedal_minimum, pod_set_volume_pedal_minimum); +static DEVICE_ATTR(eq_pre_post, S_IWUGO | S_IRUGO, pod_get_eq_pre_post, + pod_set_eq_pre_post); +static DEVICE_ATTR(volume_pre_post, S_IWUGO | S_IRUGO, pod_get_volume_pre_post, + pod_set_volume_pre_post); +static DEVICE_ATTR(di_model, S_IWUGO | S_IRUGO, pod_get_di_model, + pod_set_di_model); +static DEVICE_ATTR(di_delay, S_IWUGO | S_IRUGO, pod_get_di_delay, + pod_set_di_delay); +static DEVICE_ATTR(mod_enable, S_IWUGO | S_IRUGO, pod_get_mod_enable, + pod_set_mod_enable); +static DEVICE_ATTR(mod_param_1_note_value, S_IWUGO | S_IRUGO, + pod_get_mod_param_1_note_value, + pod_set_mod_param_1_note_value); +static DEVICE_ATTR(mod_param_2, S_IWUGO | S_IRUGO, pod_get_mod_param_2, + pod_set_mod_param_2); +static DEVICE_ATTR(mod_param_3, S_IWUGO | S_IRUGO, pod_get_mod_param_3, + pod_set_mod_param_3); +static DEVICE_ATTR(mod_param_4, S_IWUGO | S_IRUGO, pod_get_mod_param_4, + pod_set_mod_param_4); +static DEVICE_ATTR(mod_param_5, S_IWUGO | S_IRUGO, pod_get_mod_param_5, + pod_set_mod_param_5); +static DEVICE_ATTR(mod_volume_mix, S_IWUGO | S_IRUGO, pod_get_mod_volume_mix, + pod_set_mod_volume_mix); +static DEVICE_ATTR(mod_pre_post, S_IWUGO | S_IRUGO, pod_get_mod_pre_post, + pod_set_mod_pre_post); +static DEVICE_ATTR(modulation_model, S_IWUGO | S_IRUGO, + pod_get_modulation_model, pod_set_modulation_model); +static DEVICE_ATTR(band_3_frequency, S_IWUGO | S_IRUGO, + pod_get_band_3_frequency, pod_set_band_3_frequency); +static DEVICE_ATTR2(band_4_frequency__bass, band_4_frequency, S_IWUGO | S_IRUGO, + pod_get_band_4_frequency__bass, + pod_set_band_4_frequency__bass); +static DEVICE_ATTR(mod_param_1_double_precision, S_IWUGO | S_IRUGO, + pod_get_mod_param_1_double_precision, + pod_set_mod_param_1_double_precision); +static DEVICE_ATTR(delay_param_1_double_precision, S_IWUGO | S_IRUGO, + pod_get_delay_param_1_double_precision, + pod_set_delay_param_1_double_precision); +static DEVICE_ATTR(eq_enable, S_IWUGO | S_IRUGO, pod_get_eq_enable, + pod_set_eq_enable); static DEVICE_ATTR(tap, S_IWUGO | S_IRUGO, pod_get_tap, pod_set_tap); -static DEVICE_ATTR(volume_tweak_pedal_assign, S_IWUGO | S_IRUGO, pod_get_volume_tweak_pedal_assign, pod_set_volume_tweak_pedal_assign); -static DEVICE_ATTR(band_5_frequency, S_IWUGO | S_IRUGO, pod_get_band_5_frequency, pod_set_band_5_frequency); +static DEVICE_ATTR(volume_tweak_pedal_assign, S_IWUGO | S_IRUGO, + pod_get_volume_tweak_pedal_assign, + pod_set_volume_tweak_pedal_assign); +static DEVICE_ATTR(band_5_frequency, S_IWUGO | S_IRUGO, + pod_get_band_5_frequency, pod_set_band_5_frequency); static DEVICE_ATTR(tuner, S_IWUGO | S_IRUGO, pod_get_tuner, pod_set_tuner); -static DEVICE_ATTR(mic_selection, S_IWUGO | S_IRUGO, pod_get_mic_selection, pod_set_mic_selection); -static DEVICE_ATTR(cabinet_model, S_IWUGO | S_IRUGO, pod_get_cabinet_model, pod_set_cabinet_model); -static DEVICE_ATTR(stomp_model, S_IWUGO | S_IRUGO, pod_get_stomp_model, pod_set_stomp_model); -static DEVICE_ATTR(roomlevel, S_IWUGO | S_IRUGO, pod_get_roomlevel, pod_set_roomlevel); -static DEVICE_ATTR(band_4_frequency, S_IWUGO | S_IRUGO, pod_get_band_4_frequency, pod_set_band_4_frequency); -static DEVICE_ATTR(band_6_frequency, S_IWUGO | S_IRUGO, pod_get_band_6_frequency, pod_set_band_6_frequency); -static DEVICE_ATTR(stomp_param_1_note_value, S_IWUGO | S_IRUGO, pod_get_stomp_param_1_note_value, pod_set_stomp_param_1_note_value); -static DEVICE_ATTR(stomp_param_2, S_IWUGO | S_IRUGO, pod_get_stomp_param_2, pod_set_stomp_param_2); -static DEVICE_ATTR(stomp_param_3, S_IWUGO | S_IRUGO, pod_get_stomp_param_3, pod_set_stomp_param_3); -static DEVICE_ATTR(stomp_param_4, S_IWUGO | S_IRUGO, pod_get_stomp_param_4, pod_set_stomp_param_4); -static DEVICE_ATTR(stomp_param_5, S_IWUGO | S_IRUGO, pod_get_stomp_param_5, pod_set_stomp_param_5); -static DEVICE_ATTR(stomp_param_6, S_IWUGO | S_IRUGO, pod_get_stomp_param_6, pod_set_stomp_param_6); -static DEVICE_ATTR(amp_switch_select, S_IWUGO | S_IRUGO, pod_get_amp_switch_select, pod_set_amp_switch_select); -static DEVICE_ATTR(delay_param_4, S_IWUGO | S_IRUGO, pod_get_delay_param_4, pod_set_delay_param_4); -static DEVICE_ATTR(delay_param_5, S_IWUGO | S_IRUGO, pod_get_delay_param_5, pod_set_delay_param_5); -static DEVICE_ATTR(delay_pre_post, S_IWUGO | S_IRUGO, pod_get_delay_pre_post, pod_set_delay_pre_post); -static DEVICE_ATTR(delay_model, S_IWUGO | S_IRUGO, pod_get_delay_model, pod_set_delay_model); -static DEVICE_ATTR(delay_verb_model, S_IWUGO | S_IRUGO, pod_get_delay_verb_model, pod_set_delay_verb_model); -static DEVICE_ATTR(tempo_msb, S_IWUGO | S_IRUGO, pod_get_tempo_msb, pod_set_tempo_msb); -static DEVICE_ATTR(tempo_lsb, S_IWUGO | S_IRUGO, pod_get_tempo_lsb, pod_set_tempo_lsb); -static DEVICE_ATTR(wah_model, S_IWUGO | S_IRUGO, pod_get_wah_model, pod_set_wah_model); -static DEVICE_ATTR(bypass_volume, S_IWUGO | S_IRUGO, pod_get_bypass_volume, pod_set_bypass_volume); -static DEVICE_ATTR(fx_loop_on_off, S_IWUGO | S_IRUGO, pod_get_fx_loop_on_off, pod_set_fx_loop_on_off); -static DEVICE_ATTR(tweak_param_select, S_IWUGO | S_IRUGO, pod_get_tweak_param_select, pod_set_tweak_param_select); -static DEVICE_ATTR(amp1_engage, S_IWUGO | S_IRUGO, pod_get_amp1_engage, pod_set_amp1_engage); -static DEVICE_ATTR(band_1_gain, S_IWUGO | S_IRUGO, pod_get_band_1_gain, pod_set_band_1_gain); -static DEVICE_ATTR2(band_2_gain__bass, band_2_gain, S_IWUGO | S_IRUGO, pod_get_band_2_gain__bass, pod_set_band_2_gain__bass); -static DEVICE_ATTR(band_2_gain, S_IWUGO | S_IRUGO, pod_get_band_2_gain, pod_set_band_2_gain); -static DEVICE_ATTR2(band_3_gain__bass, band_3_gain, S_IWUGO | S_IRUGO, pod_get_band_3_gain__bass, pod_set_band_3_gain__bass); -static DEVICE_ATTR(band_3_gain, S_IWUGO | S_IRUGO, pod_get_band_3_gain, pod_set_band_3_gain); -static DEVICE_ATTR2(band_4_gain__bass, band_4_gain, S_IWUGO | S_IRUGO, pod_get_band_4_gain__bass, pod_set_band_4_gain__bass); -static DEVICE_ATTR2(band_5_gain__bass, band_5_gain, S_IWUGO | S_IRUGO, pod_get_band_5_gain__bass, pod_set_band_5_gain__bass); -static DEVICE_ATTR(band_4_gain, S_IWUGO | S_IRUGO, pod_get_band_4_gain, pod_set_band_4_gain); -static DEVICE_ATTR2(band_6_gain__bass, band_6_gain, S_IWUGO | S_IRUGO, pod_get_band_6_gain__bass, pod_set_band_6_gain__bass); +static DEVICE_ATTR(mic_selection, S_IWUGO | S_IRUGO, pod_get_mic_selection, + pod_set_mic_selection); +static DEVICE_ATTR(cabinet_model, S_IWUGO | S_IRUGO, pod_get_cabinet_model, + pod_set_cabinet_model); +static DEVICE_ATTR(stomp_model, S_IWUGO | S_IRUGO, pod_get_stomp_model, + pod_set_stomp_model); +static DEVICE_ATTR(roomlevel, S_IWUGO | S_IRUGO, pod_get_roomlevel, + pod_set_roomlevel); +static DEVICE_ATTR(band_4_frequency, S_IWUGO | S_IRUGO, + pod_get_band_4_frequency, pod_set_band_4_frequency); +static DEVICE_ATTR(band_6_frequency, S_IWUGO | S_IRUGO, + pod_get_band_6_frequency, pod_set_band_6_frequency); +static DEVICE_ATTR(stomp_param_1_note_value, S_IWUGO | S_IRUGO, + pod_get_stomp_param_1_note_value, + pod_set_stomp_param_1_note_value); +static DEVICE_ATTR(stomp_param_2, S_IWUGO | S_IRUGO, pod_get_stomp_param_2, + pod_set_stomp_param_2); +static DEVICE_ATTR(stomp_param_3, S_IWUGO | S_IRUGO, pod_get_stomp_param_3, + pod_set_stomp_param_3); +static DEVICE_ATTR(stomp_param_4, S_IWUGO | S_IRUGO, pod_get_stomp_param_4, + pod_set_stomp_param_4); +static DEVICE_ATTR(stomp_param_5, S_IWUGO | S_IRUGO, pod_get_stomp_param_5, + pod_set_stomp_param_5); +static DEVICE_ATTR(stomp_param_6, S_IWUGO | S_IRUGO, pod_get_stomp_param_6, + pod_set_stomp_param_6); +static DEVICE_ATTR(amp_switch_select, S_IWUGO | S_IRUGO, + pod_get_amp_switch_select, pod_set_amp_switch_select); +static DEVICE_ATTR(delay_param_4, S_IWUGO | S_IRUGO, pod_get_delay_param_4, + pod_set_delay_param_4); +static DEVICE_ATTR(delay_param_5, S_IWUGO | S_IRUGO, pod_get_delay_param_5, + pod_set_delay_param_5); +static DEVICE_ATTR(delay_pre_post, S_IWUGO | S_IRUGO, pod_get_delay_pre_post, + pod_set_delay_pre_post); +static DEVICE_ATTR(delay_model, S_IWUGO | S_IRUGO, pod_get_delay_model, + pod_set_delay_model); +static DEVICE_ATTR(delay_verb_model, S_IWUGO | S_IRUGO, + pod_get_delay_verb_model, pod_set_delay_verb_model); +static DEVICE_ATTR(tempo_msb, S_IWUGO | S_IRUGO, pod_get_tempo_msb, + pod_set_tempo_msb); +static DEVICE_ATTR(tempo_lsb, S_IWUGO | S_IRUGO, pod_get_tempo_lsb, + pod_set_tempo_lsb); +static DEVICE_ATTR(wah_model, S_IWUGO | S_IRUGO, pod_get_wah_model, + pod_set_wah_model); +static DEVICE_ATTR(bypass_volume, S_IWUGO | S_IRUGO, pod_get_bypass_volume, + pod_set_bypass_volume); +static DEVICE_ATTR(fx_loop_on_off, S_IWUGO | S_IRUGO, pod_get_fx_loop_on_off, + pod_set_fx_loop_on_off); +static DEVICE_ATTR(tweak_param_select, S_IWUGO | S_IRUGO, + pod_get_tweak_param_select, pod_set_tweak_param_select); +static DEVICE_ATTR(amp1_engage, S_IWUGO | S_IRUGO, pod_get_amp1_engage, + pod_set_amp1_engage); +static DEVICE_ATTR(band_1_gain, S_IWUGO | S_IRUGO, pod_get_band_1_gain, + pod_set_band_1_gain); +static DEVICE_ATTR2(band_2_gain__bass, band_2_gain, S_IWUGO | S_IRUGO, + pod_get_band_2_gain__bass, pod_set_band_2_gain__bass); +static DEVICE_ATTR(band_2_gain, S_IWUGO | S_IRUGO, pod_get_band_2_gain, + pod_set_band_2_gain); +static DEVICE_ATTR2(band_3_gain__bass, band_3_gain, S_IWUGO | S_IRUGO, + pod_get_band_3_gain__bass, pod_set_band_3_gain__bass); +static DEVICE_ATTR(band_3_gain, S_IWUGO | S_IRUGO, pod_get_band_3_gain, + pod_set_band_3_gain); +static DEVICE_ATTR2(band_4_gain__bass, band_4_gain, S_IWUGO | S_IRUGO, + pod_get_band_4_gain__bass, pod_set_band_4_gain__bass); +static DEVICE_ATTR2(band_5_gain__bass, band_5_gain, S_IWUGO | S_IRUGO, + pod_get_band_5_gain__bass, pod_set_band_5_gain__bass); +static DEVICE_ATTR(band_4_gain, S_IWUGO | S_IRUGO, pod_get_band_4_gain, + pod_set_band_4_gain); +static DEVICE_ATTR2(band_6_gain__bass, band_6_gain, S_IWUGO | S_IRUGO, + pod_get_band_6_gain__bass, pod_set_band_6_gain__bass); static DEVICE_ATTR(body, S_IRUGO, variax_get_body, line6_nop_write); -static DEVICE_ATTR(pickup1_enable, S_IRUGO, variax_get_pickup1_enable, line6_nop_write); -static DEVICE_ATTR(pickup1_type, S_IRUGO, variax_get_pickup1_type, line6_nop_write); -static DEVICE_ATTR(pickup1_position, S_IRUGO, variax_get_pickup1_position, line6_nop_write); -static DEVICE_ATTR(pickup1_angle, S_IRUGO, variax_get_pickup1_angle, line6_nop_write); -static DEVICE_ATTR(pickup1_level, S_IRUGO, variax_get_pickup1_level, line6_nop_write); -static DEVICE_ATTR(pickup2_enable, S_IRUGO, variax_get_pickup2_enable, line6_nop_write); -static DEVICE_ATTR(pickup2_type, S_IRUGO, variax_get_pickup2_type, line6_nop_write); -static DEVICE_ATTR(pickup2_position, S_IRUGO, variax_get_pickup2_position, line6_nop_write); -static DEVICE_ATTR(pickup2_angle, S_IRUGO, variax_get_pickup2_angle, line6_nop_write); -static DEVICE_ATTR(pickup2_level, S_IRUGO, variax_get_pickup2_level, line6_nop_write); -static DEVICE_ATTR(pickup_phase, S_IRUGO, variax_get_pickup_phase, line6_nop_write); -static DEVICE_ATTR(capacitance, S_IRUGO, variax_get_capacitance, line6_nop_write); -static DEVICE_ATTR(tone_resistance, S_IRUGO, variax_get_tone_resistance, line6_nop_write); -static DEVICE_ATTR(volume_resistance, S_IRUGO, variax_get_volume_resistance, line6_nop_write); +static DEVICE_ATTR(pickup1_enable, S_IRUGO, variax_get_pickup1_enable, + line6_nop_write); +static DEVICE_ATTR(pickup1_type, S_IRUGO, variax_get_pickup1_type, + line6_nop_write); +static DEVICE_ATTR(pickup1_position, S_IRUGO, variax_get_pickup1_position, + line6_nop_write); +static DEVICE_ATTR(pickup1_angle, S_IRUGO, variax_get_pickup1_angle, + line6_nop_write); +static DEVICE_ATTR(pickup1_level, S_IRUGO, variax_get_pickup1_level, + line6_nop_write); +static DEVICE_ATTR(pickup2_enable, S_IRUGO, variax_get_pickup2_enable, + line6_nop_write); +static DEVICE_ATTR(pickup2_type, S_IRUGO, variax_get_pickup2_type, + line6_nop_write); +static DEVICE_ATTR(pickup2_position, S_IRUGO, variax_get_pickup2_position, + line6_nop_write); +static DEVICE_ATTR(pickup2_angle, S_IRUGO, variax_get_pickup2_angle, + line6_nop_write); +static DEVICE_ATTR(pickup2_level, S_IRUGO, variax_get_pickup2_level, + line6_nop_write); +static DEVICE_ATTR(pickup_phase, S_IRUGO, variax_get_pickup_phase, + line6_nop_write); +static DEVICE_ATTR(capacitance, S_IRUGO, variax_get_capacitance, + line6_nop_write); +static DEVICE_ATTR(tone_resistance, S_IRUGO, variax_get_tone_resistance, + line6_nop_write); +static DEVICE_ATTR(volume_resistance, S_IRUGO, variax_get_volume_resistance, + line6_nop_write); static DEVICE_ATTR(taper, S_IRUGO, variax_get_taper, line6_nop_write); static DEVICE_ATTR(tone_dump, S_IRUGO, variax_get_tone_dump, line6_nop_write); static DEVICE_ATTR(save_tone, S_IRUGO, variax_get_save_tone, line6_nop_write); -static DEVICE_ATTR(volume_dump, S_IRUGO, variax_get_volume_dump, line6_nop_write); -static DEVICE_ATTR(tuning_enable, S_IRUGO, variax_get_tuning_enable, line6_nop_write); +static DEVICE_ATTR(volume_dump, S_IRUGO, variax_get_volume_dump, + line6_nop_write); +static DEVICE_ATTR(tuning_enable, S_IRUGO, variax_get_tuning_enable, + line6_nop_write); static DEVICE_ATTR(tuning6, S_IRUGO, variax_get_tuning6, line6_nop_write); static DEVICE_ATTR(tuning5, S_IRUGO, variax_get_tuning5, line6_nop_write); static DEVICE_ATTR(tuning4, S_IRUGO, variax_get_tuning4, line6_nop_write); @@ -399,7 +527,8 @@ static DEVICE_ATTR(mix4, S_IRUGO, variax_get_mix4, line6_nop_write); static DEVICE_ATTR(mix3, S_IRUGO, variax_get_mix3, line6_nop_write); static DEVICE_ATTR(mix2, S_IRUGO, variax_get_mix2, line6_nop_write); static DEVICE_ATTR(mix1, S_IRUGO, variax_get_mix1, line6_nop_write); -static DEVICE_ATTR(pickup_wiring, S_IRUGO, variax_get_pickup_wiring, line6_nop_write); +static DEVICE_ATTR(pickup_wiring, S_IRUGO, variax_get_pickup_wiring, + line6_nop_write); int pod_create_files(int firmware, int type, struct device *dev) { @@ -407,7 +536,8 @@ int pod_create_files(int firmware, int type, struct device *dev) CHECK_RETURN(device_create_file(dev, &dev_attr_tweak)); CHECK_RETURN(device_create_file(dev, &dev_attr_wah_position)); if ((type & (LINE6_BITS_PODXTALL)) != 0) - CHECK_RETURN(device_create_file(dev, &dev_attr_compression_gain)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_compression_gain)); CHECK_RETURN(device_create_file(dev, &dev_attr_vol_pedal_position)); CHECK_RETURN(device_create_file(dev, &dev_attr_compression_threshold)); CHECK_RETURN(device_create_file(dev, &dev_attr_pan)); @@ -429,7 +559,8 @@ int pod_create_files(int firmware, int type, struct device *dev) CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_mix)); CHECK_RETURN(device_create_file(dev, &dev_attr_effect_setup)); if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_1_frequency)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_1_frequency)); if ((type & (LINE6_BITS_PODXTALL)) != 0) CHECK_RETURN(device_create_file(dev, &dev_attr_presence)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) @@ -443,10 +574,12 @@ int pod_create_files(int firmware, int type, struct device *dev) CHECK_RETURN(device_create_file(dev, &dev_attr_delay_enable)); CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_1)); CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_1)); - CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_1_note_value)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_delay_param_1_note_value)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_2_frequency__bass)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_2_frequency__bass)); CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_2)); CHECK_RETURN(device_create_file(dev, &dev_attr_delay_volume_mix)); CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_3)); @@ -459,26 +592,34 @@ int pod_create_files(int firmware, int type, struct device *dev) if ((type & (LINE6_BITS_PODXTALL)) != 0) CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_tone)); if ((type & (LINE6_BITS_PODXTALL)) != 0) - CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_pre_delay)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_reverb_pre_delay)); if ((type & (LINE6_BITS_PODXTALL)) != 0) - CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_pre_post)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_reverb_pre_post)); if ((type & (LINE6_BITS_PODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_2_frequency)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_2_frequency)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_3_frequency__bass)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_3_frequency__bass)); CHECK_RETURN(device_create_file(dev, &dev_attr_wah_enable)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) - CHECK_RETURN(device_create_file(dev, &dev_attr_modulation_lo_cut)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_modulation_lo_cut)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) - CHECK_RETURN(device_create_file(dev, &dev_attr_delay_reverb_lo_cut)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_delay_reverb_lo_cut)); if ((type & (LINE6_BITS_PODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_volume_pedal_minimum)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_volume_pedal_minimum)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_eq_pre_post)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_eq_pre_post)); CHECK_RETURN(device_create_file(dev, &dev_attr_volume_pre_post)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) CHECK_RETURN(device_create_file(dev, &dev_attr_di_model)); @@ -496,19 +637,25 @@ int pod_create_files(int firmware, int type, struct device *dev) CHECK_RETURN(device_create_file(dev, &dev_attr_modulation_model)); if ((type & (LINE6_BITS_PODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_3_frequency)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_3_frequency)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_4_frequency__bass)); - CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_1_double_precision)); - CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_1_double_precision)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_4_frequency__bass)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_mod_param_1_double_precision)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_delay_param_1_double_precision)); if (firmware >= 200) CHECK_RETURN(device_create_file(dev, &dev_attr_eq_enable)); CHECK_RETURN(device_create_file(dev, &dev_attr_tap)); - CHECK_RETURN(device_create_file(dev, &dev_attr_volume_tweak_pedal_assign)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_volume_tweak_pedal_assign)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_5_frequency)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_5_frequency)); CHECK_RETURN(device_create_file(dev, &dev_attr_tuner)); CHECK_RETURN(device_create_file(dev, &dev_attr_mic_selection)); CHECK_RETURN(device_create_file(dev, &dev_attr_cabinet_model)); @@ -516,25 +663,30 @@ int pod_create_files(int firmware, int type, struct device *dev) CHECK_RETURN(device_create_file(dev, &dev_attr_roomlevel)); if ((type & (LINE6_BITS_PODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_4_frequency)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_4_frequency)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_6_frequency)); - CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_1_note_value)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_6_frequency)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_stomp_param_1_note_value)); CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_2)); CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_3)); CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_4)); CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_5)); CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_6)); if ((type & (LINE6_BITS_LIVE)) != 0) - CHECK_RETURN(device_create_file(dev, &dev_attr_amp_switch_select)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_amp_switch_select)); CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_4)); CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_5)); CHECK_RETURN(device_create_file(dev, &dev_attr_delay_pre_post)); if ((type & (LINE6_BITS_PODXTALL)) != 0) CHECK_RETURN(device_create_file(dev, &dev_attr_delay_model)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) - CHECK_RETURN(device_create_file(dev, &dev_attr_delay_verb_model)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_delay_verb_model)); CHECK_RETURN(device_create_file(dev, &dev_attr_tempo_msb)); CHECK_RETURN(device_create_file(dev, &dev_attr_tempo_lsb)); if (firmware >= 300) @@ -549,30 +701,39 @@ int pod_create_files(int firmware, int type, struct device *dev) CHECK_RETURN(device_create_file(dev, &dev_attr_band_1_gain)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_2_gain__bass)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_2_gain__bass)); if ((type & (LINE6_BITS_PODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_2_gain)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_2_gain)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_3_gain__bass)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_3_gain__bass)); if ((type & (LINE6_BITS_PODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_3_gain)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_3_gain)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_4_gain__bass)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_4_gain__bass)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_5_gain__bass)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_5_gain__bass)); if ((type & (LINE6_BITS_PODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_4_gain)); + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_4_gain)); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) if (firmware >= 200) - CHECK_RETURN(device_create_file(dev, &dev_attr_band_6_gain__bass)); - return 0; + CHECK_RETURN(device_create_file + (dev, &dev_attr_band_6_gain__bass)); + return 0; } +EXPORT_SYMBOL(pod_create_files); void pod_remove_files(int firmware, int type, struct device *dev) { @@ -618,7 +779,8 @@ void pod_remove_files(int firmware, int type, struct device *dev) device_remove_file(dev, &dev_attr_delay_param_1_note_value); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) if (firmware >= 200) - device_remove_file(dev, &dev_attr_band_2_frequency__bass); + device_remove_file(dev, + &dev_attr_band_2_frequency__bass); device_remove_file(dev, &dev_attr_delay_param_2); device_remove_file(dev, &dev_attr_delay_volume_mix); device_remove_file(dev, &dev_attr_delay_param_3); @@ -639,7 +801,8 @@ void pod_remove_files(int firmware, int type, struct device *dev) device_remove_file(dev, &dev_attr_band_2_frequency); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) if (firmware >= 200) - device_remove_file(dev, &dev_attr_band_3_frequency__bass); + device_remove_file(dev, + &dev_attr_band_3_frequency__bass); device_remove_file(dev, &dev_attr_wah_enable); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) device_remove_file(dev, &dev_attr_modulation_lo_cut); @@ -671,7 +834,8 @@ void pod_remove_files(int firmware, int type, struct device *dev) device_remove_file(dev, &dev_attr_band_3_frequency); if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) if (firmware >= 200) - device_remove_file(dev, &dev_attr_band_4_frequency__bass); + device_remove_file(dev, + &dev_attr_band_4_frequency__bass); device_remove_file(dev, &dev_attr_mod_param_1_double_precision); device_remove_file(dev, &dev_attr_delay_param_1_double_precision); if (firmware >= 200) @@ -744,8 +908,6 @@ void pod_remove_files(int firmware, int type, struct device *dev) if (firmware >= 200) device_remove_file(dev, &dev_attr_band_6_gain__bass); } - -EXPORT_SYMBOL(pod_create_files); EXPORT_SYMBOL(pod_remove_files); int variax_create_files(int firmware, int type, struct device *dev) @@ -790,8 +952,9 @@ int variax_create_files(int firmware, int type, struct device *dev) CHECK_RETURN(device_create_file(dev, &dev_attr_mix2)); CHECK_RETURN(device_create_file(dev, &dev_attr_mix1)); CHECK_RETURN(device_create_file(dev, &dev_attr_pickup_wiring)); - return 0; + return 0; } +EXPORT_SYMBOL(variax_create_files); void variax_remove_files(int firmware, int type, struct device *dev) { @@ -835,6 +998,4 @@ void variax_remove_files(int firmware, int type, struct device *dev) device_remove_file(dev, &dev_attr_mix1); device_remove_file(dev, &dev_attr_pickup_wiring); } - -EXPORT_SYMBOL(variax_create_files); EXPORT_SYMBOL(variax_remove_files); diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c index f188ecee502fe172c2faa257183294d18de65ccf..e4078a92d399c13bae12a65a0809dc5f411b556d 100644 --- a/drivers/staging/line6/driver.c +++ b/drivers/staging/line6/driver.c @@ -168,19 +168,19 @@ static void line6_dump_urb(struct urb *urb) #endif /* - Send raw message in pieces of wMaxPacketSize bytes. + Send raw message in pieces of max_packet_size bytes. */ int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, int size) { int i, done = 0; + int actual_size; #if DO_DUMP_URB_SEND line6_write_hexdump(line6, 'S', buffer, size); #endif - for (i = 0; i < size; i += line6->max_packet_size) { - int partial; + for (i = 0; i < size; i += actual_size) { const char *frag_buf = buffer + i; int frag_size = min(line6->max_packet_size, size - i); int retval; @@ -189,7 +189,7 @@ int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, usb_sndintpipe(line6->usbdev, line6->ep_control_write), (char *)frag_buf, frag_size, - &partial, LINE6_TIMEOUT * HZ); + &actual_size, LINE6_TIMEOUT * HZ); if (retval) { dev_err(line6->ifcdev, @@ -197,7 +197,7 @@ int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, break; } - done += frag_size; + done += actual_size; } return done; @@ -395,17 +395,44 @@ static void line6_data_received(struct urb *urb) line6_start_listen(line6); } +static int line6_send(struct usb_line6 *line6, unsigned char *buf, size_t len) +{ + int retval; + unsigned int partial; + +#if DO_DUMP_URB_SEND + line6_write_hexdump(line6, 'S', buf, len); +#endif + + retval = usb_interrupt_msg(line6->usbdev, + usb_sndintpipe(line6->usbdev, + line6->ep_control_write), + buf, len, &partial, + LINE6_TIMEOUT * HZ); + + if (retval) { + dev_err(line6->ifcdev, + "usb_interrupt_msg failed (%d)\n", retval); + } + + if (partial != len) { + dev_err(line6->ifcdev, + "usb_interrupt_msg sent partial message (%d)\n", + retval); + } + + return retval; +} + /* Send channel number (i.e., switch to a different sound). */ int line6_send_program(struct usb_line6 *line6, int value) { - int retval; unsigned char *buffer; - unsigned int partial; - - buffer = kmalloc(2, GFP_KERNEL); + size_t len = 2; + buffer = kmalloc(len, GFP_KERNEL); if (!buffer) { dev_err(line6->ifcdev, "out of memory\n"); return -ENOMEM; @@ -414,20 +441,7 @@ int line6_send_program(struct usb_line6 *line6, int value) buffer[0] = LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST; buffer[1] = value; -#if DO_DUMP_URB_SEND - line6_write_hexdump(line6, 'S', buffer, 2); -#endif - - retval = usb_interrupt_msg(line6->usbdev, - usb_sndintpipe(line6->usbdev, - line6->ep_control_write), - buffer, 2, &partial, LINE6_TIMEOUT * HZ); - - if (retval) - dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n", retval); - - kfree(buffer); - return retval; + return line6_send(line6, buffer, len); } /* @@ -435,12 +449,10 @@ int line6_send_program(struct usb_line6 *line6, int value) */ int line6_transmit_parameter(struct usb_line6 *line6, int param, int value) { - int retval; unsigned char *buffer; - unsigned int partial; - - buffer = kmalloc(3, GFP_KERNEL); + size_t len = 3; + buffer = kmalloc(len, GFP_KERNEL); if (!buffer) { dev_err(line6->ifcdev, "out of memory\n"); return -ENOMEM; @@ -450,19 +462,7 @@ int line6_transmit_parameter(struct usb_line6 *line6, int param, int value) buffer[1] = param; buffer[2] = value; -#if DO_DUMP_URB_SEND - line6_write_hexdump(line6, 'S', buffer, 3); -#endif - - retval = usb_interrupt_msg(line6->usbdev, - usb_sndintpipe(line6->usbdev, line6->ep_control_write), - buffer, 3, &partial, LINE6_TIMEOUT * HZ); - - if (retval) - dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n", retval); - - kfree(buffer); - return retval; + return line6_send(line6, buffer, len); } /* @@ -476,8 +476,10 @@ int line6_read_data(struct usb_line6 *line6, int address, void *data, size_t dat /* query the serial number: */ ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, - (datalen << 8) | 0x21, address, NULL, 0, LINE6_TIMEOUT * HZ); + USB_TYPE_VENDOR | USB_RECIP_DEVICE + | USB_DIR_OUT, + (datalen << 8) | 0x21, address, + NULL, 0, LINE6_TIMEOUT * HZ); if (ret < 0) { dev_err(line6->ifcdev, "read request failed (error %d)\n", ret); @@ -496,9 +498,7 @@ int line6_read_data(struct usb_line6 *line6, int address, void *data, size_t dat "receive length failed (error %d)\n", ret); return ret; } - } - while (len == 0xff) - ; + } while (len == 0xff); if (len != datalen) { /* should be equal or something went wrong */ @@ -682,10 +682,14 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_ return -ENODEV; /* check vendor and product id */ - for (devtype = ARRAY_SIZE(line6_id_table) - 1; devtype--;) - if ((le16_to_cpu(usbdev->descriptor.idVendor) == line6_id_table[devtype].idVendor) && - (le16_to_cpu(usbdev->descriptor.idProduct) == line6_id_table[devtype].idProduct)) + for (devtype = ARRAY_SIZE(line6_id_table) - 1; devtype--;) { + u16 vendor = le16_to_cpu(usbdev->descriptor.idVendor); + u16 product = le16_to_cpu(usbdev->descriptor.idProduct); + + if (vendor == line6_id_table[devtype].idVendor + && product == line6_id_table[devtype].idProduct) break; + } if (devtype < 0) return -ENODEV; @@ -1036,9 +1040,10 @@ static void line6_disconnect(struct usb_interface *interface) dev_info(&interface->dev, "Line6 %s now disconnected\n", line6->properties->name); - for (i = LINE6_MAX_DEVICES; i--;) + for (i = LINE6_MAX_DEVICES; i--;) { if (line6_devices[i] == line6) line6_devices[i] = NULL; + } } line6_destruct(interface); diff --git a/drivers/staging/line6/midi.c b/drivers/staging/line6/midi.c index 89a2b17e9cafc78744752ae41edcc062184db98b..6ef4455d87d8754b1ae6d1f3f7046316f80517a9 100644 --- a/drivers/staging/line6/midi.c +++ b/drivers/staging/line6/midi.c @@ -318,7 +318,13 @@ static ssize_t midi_set_midi_mask_transmit(struct device *dev, { struct usb_interface *interface = to_usb_interface(dev); struct usb_line6 *line6 = usb_get_intfdata(interface); - int value = simple_strtoul(buf, NULL, 10); + unsigned long value; + int ret; + + ret = strict_strtoul(buf, 10, &value); + if (ret) + return ret; + line6->line6midi->midi_mask_transmit = value; return count; } @@ -344,7 +350,13 @@ static ssize_t midi_set_midi_mask_receive(struct device *dev, { struct usb_interface *interface = to_usb_interface(dev); struct usb_line6 *line6 = usb_get_intfdata(interface); - int value = simple_strtoul(buf, NULL, 10); + unsigned long value; + int ret; + + ret = strict_strtoul(buf, 10, &value); + if (ret) + return ret; + line6->line6midi->midi_mask_receive = value; return count; } diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c index fc4113f33159af1bb2118317dc4abf8461d4c5c7..dd98121eb80bb582bf515b8e4a9b740bd6f5a545 100644 --- a/drivers/staging/line6/pcm.c +++ b/drivers/staging/line6/pcm.c @@ -156,7 +156,8 @@ static int snd_line6_new_pcm(struct snd_line6_pcm *line6pcm) strcpy(pcm->name, line6pcm->line6->properties->name); /* set operators */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_line6_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, + &snd_line6_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops); /* pre-allocation of buffers */ diff --git a/drivers/staging/line6/playback.c b/drivers/staging/line6/playback.c index acb06126a6a5bb9a27f1548f30cb12d917e3a9b4..3431f5cd28525d527157f50ab2516a3fd7e277e1 100644 --- a/drivers/staging/line6/playback.c +++ b/drivers/staging/line6/playback.c @@ -20,7 +20,6 @@ #include "pod.h" #include "playback.h" - /* Software stereo volume control. */ @@ -30,7 +29,7 @@ static void change_volume(struct urb *urb_out, int volume[], int chn = 0; if (volume[0] == 256 && volume[1] == 256) - return; /* maximum volume - no change */ + return; /* maximum volume - no change */ if (bytes_per_frame == 4) { short *p, *buf_end; @@ -68,13 +67,17 @@ static int submit_audio_out_urb(struct snd_pcm_substream *substream) int i, urb_size, urb_frames; struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); const int bytes_per_frame = line6pcm->properties->bytes_per_frame; - const int frame_increment = line6pcm->properties->snd_line6_rates.rats[0].num_min; - const int frame_factor = line6pcm->properties->snd_line6_rates.rats[0].den * (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL); + const int frame_increment = + line6pcm->properties->snd_line6_rates.rats[0].num_min; + const int frame_factor = + line6pcm->properties->snd_line6_rates.rats[0].den * + (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL); struct snd_pcm_runtime *runtime = substream->runtime; struct urb *urb_out; spin_lock_irqsave(&line6pcm->lock_audio_out, flags); - index = find_first_zero_bit(&line6pcm->active_urb_out, LINE6_ISO_BUFFERS); + index = + find_first_zero_bit(&line6pcm->active_urb_out, LINE6_ISO_BUFFERS); if (index < 0 || index >= LINE6_ISO_BUFFERS) { spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags); @@ -88,7 +91,8 @@ static int submit_audio_out_urb(struct snd_pcm_substream *substream) for (i = 0; i < LINE6_ISO_PACKETS; ++i) { /* compute frame size for given sampling rate */ int n, fs; - struct usb_iso_packet_descriptor *fout = &urb_out->iso_frame_desc[i]; + struct usb_iso_packet_descriptor *fout = + &urb_out->iso_frame_desc[i]; line6pcm->count_out += frame_increment; n = line6pcm->count_out / frame_factor; line6pcm->count_out -= n * frame_factor; @@ -106,25 +110,36 @@ static int submit_audio_out_urb(struct snd_pcm_substream *substream) } else { if (line6pcm->pos_out + urb_frames > runtime->buffer_size) { /* - The transferred area goes over buffer boundary, - copy the data to the temp buffer. - */ + The transferred area goes over buffer boundary, + copy the data to the temp buffer. + */ int len; len = runtime->buffer_size - line6pcm->pos_out; urb_out->transfer_buffer = line6pcm->wrap_out; if (len > 0) { - memcpy(line6pcm->wrap_out, runtime->dma_area + line6pcm->pos_out * bytes_per_frame, len * bytes_per_frame); - memcpy(line6pcm->wrap_out + len * bytes_per_frame, runtime->dma_area, (urb_frames - len) * bytes_per_frame); - } else - dev_err(s2m(substream), "driver bug: len = %d\n", len); /* this is somewhat paranoid */ + memcpy(line6pcm->wrap_out, + runtime->dma_area + + line6pcm->pos_out * bytes_per_frame, + len * bytes_per_frame); + memcpy(line6pcm->wrap_out + + len * bytes_per_frame, runtime->dma_area, + (urb_frames - len) * bytes_per_frame); + } else { + /* this is somewhat paranoid */ + dev_err(s2m(substream), + "driver bug: len = %d\n", len); + } } else { /* set the buffer pointer */ - urb_out->transfer_buffer = runtime->dma_area + line6pcm->pos_out * bytes_per_frame; + urb_out->transfer_buffer = + runtime->dma_area + + line6pcm->pos_out * bytes_per_frame; } } - if ((line6pcm->pos_out += urb_frames) >= runtime->buffer_size) + line6pcm->pos_out += urb_frames; + if (line6pcm->pos_out >= runtime->buffer_size) line6pcm->pos_out -= runtime->buffer_size; urb_out->transfer_buffer_length = urb_size; @@ -133,15 +148,19 @@ static int submit_audio_out_urb(struct snd_pcm_substream *substream) #if DO_DUMP_PCM_SEND for (i = 0; i < LINE6_ISO_PACKETS; ++i) { - struct usb_iso_packet_descriptor *fout = &urb_out->iso_frame_desc[i]; - line6_write_hexdump(line6pcm->line6, 'P', urb_out->transfer_buffer + fout->offset, fout->length); + struct usb_iso_packet_descriptor *fout = + &urb_out->iso_frame_desc[i]; + line6_write_hexdump(line6pcm->line6, 'P', + urb_out->transfer_buffer + fout->offset, + fout->length); } #endif if (usb_submit_urb(urb_out, GFP_ATOMIC) == 0) set_bit(index, &line6pcm->active_urb_out); else - dev_err(s2m(substream), "URB out #%d submission failed\n", index); + dev_err(s2m(substream), "URB out #%d submission failed\n", + index); spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags); return 0; @@ -181,7 +200,7 @@ static void unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm) } /* - Wait until unlinking of all currently active playback URBs has been finished. + Wait until unlinking of all currently active playback URBs has been finished. */ static void wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) { @@ -224,7 +243,8 @@ static void audio_out_callback(struct urb *urb) int i, index, length = 0, shutdown = 0; unsigned long flags; - struct snd_pcm_substream *substream = (struct snd_pcm_substream *)urb->context; + struct snd_pcm_substream *substream = + (struct snd_pcm_substream *)urb->context; struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; @@ -234,13 +254,14 @@ static void audio_out_callback(struct urb *urb) break; if (index < 0) - return; /* URB has been unlinked asynchronously */ + return; /* URB has been unlinked asynchronously */ for (i = LINE6_ISO_PACKETS; i--;) length += urb->iso_frame_desc[i].length; spin_lock_irqsave(&line6pcm->lock_audio_out, flags); - line6pcm->pos_out_done += length / line6pcm->properties->bytes_per_frame; + line6pcm->pos_out_done += + length / line6pcm->properties->bytes_per_frame; if (line6pcm->pos_out_done >= runtime->buffer_size) line6pcm->pos_out_done -= runtime->buffer_size; @@ -261,7 +282,8 @@ static void audio_out_callback(struct urb *urb) if (!shutdown) { submit_audio_out_urb(substream); - if ((line6pcm->bytes_out += length) >= line6pcm->period_out) { + line6pcm->bytes_out += length; + if (line6pcm->bytes_out >= line6pcm->period_out) { line6pcm->bytes_out -= line6pcm->period_out; snd_pcm_period_elapsed(substream); } @@ -276,7 +298,8 @@ static int snd_line6_playback_open(struct snd_pcm_substream *substream) struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); err = snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - (&line6pcm->properties->snd_line6_rates)); + (&line6pcm->properties-> + snd_line6_rates)); if (err < 0) return err; @@ -291,7 +314,8 @@ static int snd_line6_playback_close(struct snd_pcm_substream *substream) } /* hw_params playback callback */ -static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) +static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) { int ret; struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); @@ -349,7 +373,8 @@ int snd_line6_playback_trigger(struct snd_pcm_substream *substream, int cmd) err = submit_audio_out_all_urbs(substream); if (err < 0) { - clear_bit(BIT_RUNNING_PLAYBACK, &line6pcm->flags); + clear_bit(BIT_RUNNING_PLAYBACK, + &line6pcm->flags); return err; } } @@ -387,14 +412,14 @@ snd_line6_playback_pointer(struct snd_pcm_substream *substream) /* playback operators */ struct snd_pcm_ops snd_line6_playback_ops = { - .open = snd_line6_playback_open, - .close = snd_line6_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_line6_playback_hw_params, - .hw_free = snd_line6_playback_hw_free, - .prepare = snd_line6_prepare, - .trigger = snd_line6_trigger, - .pointer = snd_line6_playback_pointer, + .open = snd_line6_playback_open, + .close = snd_line6_playback_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_line6_playback_hw_params, + .hw_free = snd_line6_playback_hw_free, + .prepare = snd_line6_prepare, + .trigger = snd_line6_trigger, + .pointer = snd_line6_playback_pointer, }; int create_audio_out_urbs(struct snd_line6_pcm *line6pcm) @@ -406,7 +431,8 @@ int create_audio_out_urbs(struct snd_line6_pcm *line6pcm) struct urb *urb; /* URB for audio out: */ - urb = line6pcm->urb_audio_out[i] = usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL); + urb = line6pcm->urb_audio_out[i] = + usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL); if (urb == NULL) { dev_err(line6pcm->line6->ifcdev, "Out of memory\n"); @@ -414,7 +440,10 @@ int create_audio_out_urbs(struct snd_line6_pcm *line6pcm) } urb->dev = line6pcm->line6->usbdev; - urb->pipe = usb_sndisocpipe(line6pcm->line6->usbdev, line6pcm->ep_audio_write & USB_ENDPOINT_NUMBER_MASK); + urb->pipe = + usb_sndisocpipe(line6pcm->line6->usbdev, + line6pcm-> + ep_audio_write & USB_ENDPOINT_NUMBER_MASK); urb->transfer_flags = URB_ISO_ASAP; urb->start_frame = -1; urb->number_of_packets = LINE6_ISO_PACKETS; diff --git a/drivers/staging/line6/pod.c b/drivers/staging/line6/pod.c index 4c5b9d58400041f588241ee48fe250c192652753..685c529950eb56541683a2439b9dfd1a71702354 100644 --- a/drivers/staging/line6/pod.c +++ b/drivers/staging/line6/pod.c @@ -422,13 +422,21 @@ void pod_transmit_parameter(struct usb_line6_pod *pod, int param, int value) /* Resolve value to memory location. */ -static void pod_resolve(const char *buf, short block0, short block1, unsigned char *location) +static int pod_resolve(const char *buf, short block0, short block1, unsigned char *location) { - int value = simple_strtoul(buf, NULL, 10); - short block = (value < 0x40) ? block0 : block1; + unsigned long value; + short block; + int ret; + + ret = strict_strtoul(buf, 10, &value); + if (ret) + return ret; + + block = (value < 0x40) ? block0 : block1; value &= 0x3f; location[0] = block >> 7; location[1] = value | (block & 0x7f); + return 0; } /* @@ -438,14 +446,20 @@ static ssize_t pod_send_store_command(struct device *dev, const char *buf, size_ { struct usb_interface *interface = to_usb_interface(dev); struct usb_line6_pod *pod = usb_get_intfdata(interface); - + int ret; int size = 3 + sizeof(pod->prog_data_buf); char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_STORE, size); + if (!sysex) return 0; sysex[SYSEX_DATA_OFS] = 5; /* see pod_dump() */ - pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS + 1); + ret = pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS + 1); + if (ret) { + kfree(sysex); + return ret; + } + memcpy(sysex + SYSEX_DATA_OFS + 3, &pod->prog_data_buf, sizeof(pod->prog_data_buf)); line6_send_sysex_message(&pod->line6, sysex, size); @@ -461,13 +475,18 @@ static ssize_t pod_send_retrieve_command(struct device *dev, const char *buf, si { struct usb_interface *interface = to_usb_interface(dev); struct usb_line6_pod *pod = usb_get_intfdata(interface); + int ret; int size = 4; char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_DUMPMEM, size); if (!sysex) return 0; - pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS); + ret = pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS); + if (ret) { + kfree(sysex); + return ret; + } sysex[SYSEX_DATA_OFS + 2] = 0; sysex[SYSEX_DATA_OFS + 3] = 0; line6_dump_started(&pod->dumpreq, POD_DUMP_MEMORY); @@ -526,7 +545,13 @@ static ssize_t pod_set_channel(struct device *dev, { struct usb_interface *interface = to_usb_interface(dev); struct usb_line6_pod *pod = usb_get_intfdata(interface); - int value = simple_strtoul(buf, NULL, 10); + unsigned long value; + int ret; + + ret = strict_strtoul(buf, 10, &value); + if (ret) + return ret; + pod_send_channel(pod, value); return count; } @@ -579,7 +604,7 @@ static ssize_t pod_set_dump(struct device *dev, struct device_attribute *attr, if (count != sizeof(pod->prog_data)) { dev_err(pod->line6.ifcdev, - "data block must be exactly %d bytes\n", + "data block must be exactly %zu bytes\n", sizeof(pod->prog_data)); return -EINVAL; } @@ -645,6 +670,8 @@ static ssize_t pod_set_system_param(struct usb_line6_pod *pod, const char *buf, char *sysex; static const int size = 5; unsigned short value; + unsigned long result; + int ret; if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) && tuner) return -EINVAL; @@ -653,7 +680,12 @@ static ssize_t pod_set_system_param(struct usb_line6_pod *pod, const char *buf, sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size); if (!sysex) return 0; - value = simple_strtoul(buf, NULL, 10) & mask; + + ret = strict_strtoul(buf, 10, &result); + if (ret) + return ret; + + value = result & mask; sysex[SYSEX_DATA_OFS] = code; sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f; sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f; @@ -691,7 +723,7 @@ static ssize_t pod_set_dump_buf(struct device *dev, if (count != sizeof(pod->prog_data)) { dev_err(pod->line6.ifcdev, - "data block must be exactly %d bytes\n", + "data block must be exactly %zu bytes\n", sizeof(pod->prog_data)); return -EINVAL; } @@ -812,7 +844,13 @@ static ssize_t pod_set_midi_postprocess(struct device *dev, { struct usb_interface *interface = to_usb_interface(dev); struct usb_line6_pod *pod = usb_get_intfdata(interface); - int value = simple_strtoul(buf, NULL, 10); + unsigned long value; + int ret; + + ret = strict_strtoul(buf, 10, &value); + if (ret) + return ret; + pod->midi_postprocess = value ? 1 : 0; return count; } diff --git a/drivers/staging/line6/toneport.c b/drivers/staging/line6/toneport.c index eaa1229002aac2d8e46c54589296ebf6f029ebff..e6770ea179364e8579d7646d72fec4c0379c64bf 100644 --- a/drivers/staging/line6/toneport.c +++ b/drivers/staging/line6/toneport.c @@ -17,10 +17,8 @@ #include "playback.h" #include "toneport.h" - static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2); - static struct snd_ratden toneport_ratden = { .num_min = 44100, .num_max = 44100, @@ -29,47 +27,44 @@ static struct snd_ratden toneport_ratden = { }; static struct line6_pcm_properties toneport_pcm_properties = { - .snd_line6_playback_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_KNOT, - .rate_min = 44100, - .rate_max = 44100, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 60000, - .period_bytes_min = 180 * 4, - .period_bytes_max = 8192, - .periods_min = 1, - .periods_max = 1024 - }, - .snd_line6_capture_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_KNOT, - .rate_min = 44100, - .rate_max = 44100, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 60000, - .period_bytes_min = 188 * 4, - .period_bytes_max = 8192, - .periods_min = 1, - .periods_max = 1024 - }, + .snd_line6_playback_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_KNOT, + .rate_min = 44100, + .rate_max = 44100, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 60000, + .period_bytes_min = 180 * 4, + .period_bytes_max = 8192, + .periods_min = 1, + .periods_max = 1024}, + .snd_line6_capture_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_SYNC_START), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_KNOT, + .rate_min = 44100, + .rate_max = 44100, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 60000, + .period_bytes_min = 188 * 4, + .period_bytes_max = 8192, + .periods_min = 1, + .periods_max = 1024}, .snd_line6_rates = { - .nrats = 1, - .rats = &toneport_ratden - }, + .nrats = 1, + .rats = &toneport_ratden}, .bytes_per_frame = 4 }; @@ -101,8 +96,14 @@ static ssize_t toneport_set_led_red(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - char *c; - led_red = simple_strtol(buf, &c, 10); + int retval; + long value; + + retval = strict_strtol(buf, 10, &value); + if (retval) + return retval; + + led_red = value; toneport_update_led(dev); return count; } @@ -111,15 +112,22 @@ static ssize_t toneport_set_led_green(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - char *c; - led_green = simple_strtol(buf, &c, 10); + int retval; + long value; + + retval = strict_strtol(buf, 10, &value); + if (retval) + return retval; + + led_green = value; toneport_update_led(dev); return count; } -static DEVICE_ATTR(led_red, S_IWUGO | S_IRUGO, line6_nop_read, toneport_set_led_red); -static DEVICE_ATTR(led_green, S_IWUGO | S_IRUGO, line6_nop_read, toneport_set_led_green); - +static DEVICE_ATTR(led_red, S_IWUGO | S_IRUGO, line6_nop_read, + toneport_set_led_red); +static DEVICE_ATTR(led_green, S_IWUGO | S_IRUGO, line6_nop_read, + toneport_set_led_green); static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) { @@ -196,16 +204,18 @@ int toneport_init(struct usb_interface *interface, line6_write_data(line6, 0x80c6, &ticks, 4); /* - seems to work without the first two... - */ + seems to work without the first two... + */ /* toneport_send_cmd(usbdev, 0x0201, 0x0002); */ /* toneport_send_cmd(usbdev, 0x0801, 0x0000); */ /* only one that works for me; on GP, TP might be different? */ toneport_send_cmd(usbdev, 0x0301, 0x0000); if (usbdev->descriptor.idProduct != LINE6_DEVID_GUITARPORT) { - CHECK_RETURN(device_create_file(&interface->dev, &dev_attr_led_red)); - CHECK_RETURN(device_create_file(&interface->dev, &dev_attr_led_green)); + CHECK_RETURN(device_create_file + (&interface->dev, &dev_attr_led_red)); + CHECK_RETURN(device_create_file + (&interface->dev, &dev_attr_led_green)); toneport_update_led(&usbdev->dev); } @@ -223,7 +233,8 @@ void toneport_disconnect(struct usb_interface *interface) return; toneport = usb_get_intfdata(interface); - if (toneport->line6.usbdev->descriptor.idProduct != LINE6_DEVID_GUITARPORT) { + if (toneport->line6.usbdev->descriptor.idProduct != + LINE6_DEVID_GUITARPORT) { device_remove_file(&interface->dev, &dev_attr_led_red); device_remove_file(&interface->dev, &dev_attr_led_green); } diff --git a/drivers/staging/line6/variax.c b/drivers/staging/line6/variax.c index f9d96984733a8b71aa116d0895037968e3d0c457..48d834b0fa1b3044cb74d4294e5c3790177e37fc 100644 --- a/drivers/staging/line6/variax.c +++ b/drivers/staging/line6/variax.c @@ -184,7 +184,12 @@ static ssize_t variax_set_volume(struct device *dev, const char *buf, size_t count) { struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); - int value = simple_strtoul(buf, NULL, 10); + unsigned long value; + int ret; + + ret = strict_strtoul(buf, 10, &value); + if (ret) + return ret; if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_volume, value) == 0) @@ -211,7 +216,12 @@ static ssize_t variax_set_model(struct device *dev, const char *buf, size_t count) { struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); - int value = simple_strtoul(buf, NULL, 10); + unsigned long value; + int ret; + + ret = strict_strtoul(buf, 10, &value); + if (ret) + return ret; if (line6_send_program(&variax->line6, value) == 0) variax->model = value; @@ -237,8 +247,14 @@ static ssize_t variax_set_active(struct device *dev, const char *buf, size_t count) { struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); - int value = simple_strtoul(buf, NULL, 10) ? 1 : 0; - variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = value; + unsigned long value; + int ret; + + ret = strict_strtoul(buf, 10, &value); + if (ret) + return ret; + + variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = value ? 1: 0; line6_send_raw_message_async(&variax->line6, variax->buffer_activate, sizeof(variax_activate)); return count; @@ -262,7 +278,12 @@ static ssize_t variax_set_tone(struct device *dev, const char *buf, size_t count) { struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); - int value = simple_strtoul(buf, NULL, 10); + unsigned long value; + int ret; + + ret = strict_strtoul(buf, 10, &value); + if (ret) + return ret; if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_tone, value) == 0) diff --git a/drivers/staging/octeon/cvmx-pow.h b/drivers/staging/octeon/cvmx-pow.h index c5d66f272b0d091796fe965afa2a0352fa6e4a87..bf9e069a898ca84aeaee5c9536d69fb1b08107c7 100644 --- a/drivers/staging/octeon/cvmx-pow.h +++ b/drivers/staging/octeon/cvmx-pow.h @@ -1959,7 +1959,7 @@ static inline uint32_t cvmx_pow_tag_get_hw_bits(uint64_t tag) * @buffer_size: * The size of the supplied buffer * - * Returns Zero on sucess, negative on failure + * Returns Zero on success, negative on failure */ extern int cvmx_pow_capture(void *buffer, int buffer_size); diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index 8704133fe1272c03964dc110fa48c39b51d4b394..fbaa465d2fac3e2424d81f92d1a446b9cb107133 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -308,7 +308,7 @@ int cvm_oct_rgmii_init(struct net_device *dev) /* * Due to GMX errata in CN3XXX series chips, it is necessary - * to take the link down immediately whne the PHY changes + * to take the link down immediately when the PHY changes * state. In order to do this we call the poll function every * time the RGMII inband status changes. This may cause * problems if the PHY doesn't implement inband status @@ -317,6 +317,8 @@ int cvm_oct_rgmii_init(struct net_device *dev) if (number_rgmii_ports == 0) { r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt, IRQF_SHARED, "RGMII", &number_rgmii_ports); + if (r != 0) + return r; } number_rgmii_ports++; diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 81a851390f1bfc47d762a912114fbce62d14210f..535294105f6585e37f45e9acb1c5f4bb27e90cfc 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -624,7 +624,7 @@ int cvm_oct_transmit_qos(struct net_device *dev, void *work_queue_entry, EXPORT_SYMBOL(cvm_oct_transmit_qos); /** - * This function frees all skb that are currenty queued for TX. + * This function frees all skb that are currently queued for TX. * * @dev: Device being shutdown */ diff --git a/drivers/staging/otus/80211core/ccmd.c b/drivers/staging/otus/80211core/ccmd.c index 83dd8ba1328c9f0ee6de328d3dcd68582a39ae1f..8da28eee7fb0c63c5842567b9bb935e6b5af2abb 100644 --- a/drivers/staging/otus/80211core/ccmd.c +++ b/drivers/staging/otus/80211core/ccmd.c @@ -899,7 +899,7 @@ u16_t zfiWlanDisable(zdev_t *dev, u8_t ResetKeyCache) zfStaDisableSWEncryption(dev); } - /* Improve WEP/TKIP performace with HT AP, + /* Improve WEP/TKIP performance with HT AP, detail information please look bug#32495 */ /* zfHpSetTTSIFSTime(dev, 0x8); */ @@ -1407,7 +1407,7 @@ u16_t zfWlanReset(zdev_t *dev) zfStaDisableSWEncryption(dev); } - /* Improve WEP/TKIP performace with HT AP, + /* Improve WEP/TKIP performance with HT AP, detail information please look bug#32495 */ /* zfHpSetTTSIFSTime(dev, 0x8); */ diff --git a/drivers/staging/otus/80211core/cmm.c b/drivers/staging/otus/80211core/cmm.c index bed16b581a5f3bf313e68274b934247cd556ffe9..a6c1b41ba8486be970116b2d6986106a9baa5fcb 100644 --- a/drivers/staging/otus/80211core/cmm.c +++ b/drivers/staging/otus/80211core/cmm.c @@ -1428,7 +1428,7 @@ void zfProcessManagement(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInf { /* Beacon */ case ZM_WLAN_FRAME_TYPE_BEACON : - /* if enable 802.11h and current chanel is silent but receive beacon from other AP */ + /* if enable 802.11h and current channel is silent but receive beacon from other AP */ if (((wd->regulationTable.allowChannel[wd->regulationTable.CurChIndex].channelFlags & ZM_REG_FLAG_CHANNEL_CSA) != 0) && wd->sta.DFSEnable) { @@ -1469,7 +1469,7 @@ void zfProcessManagement(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInf break; /* Probe response */ case ZM_WLAN_FRAME_TYPE_PROBERSP : - /* if enable 802.11h and current chanel is silent but receive probe response from other AP */ + /* if enable 802.11h and current channel is silent but receive probe response from other AP */ if (((wd->regulationTable.allowChannel[wd->regulationTable.CurChIndex].channelFlags & ZM_REG_FLAG_CHANNEL_CSA) != 0) && wd->sta.DFSEnable) { diff --git a/drivers/staging/otus/80211core/cmmsta.c b/drivers/staging/otus/80211core/cmmsta.c index b28a4e25e107e80c81bedfbfef409d5de5cf17e5..a11d559167b139fd0a31a008165fbd6434e808a9 100644 --- a/drivers/staging/otus/80211core/cmmsta.c +++ b/drivers/staging/otus/80211core/cmmsta.c @@ -216,7 +216,7 @@ void zfStaConnectFail(zdev_t* dev, u16_t reason, u16_t* bssid, u8_t weight) /* Change internal state */ zfChangeAdapterState(dev, ZM_STA_STATE_DISCONNECT); - /* Improve WEP/TKIP performace with HT AP, detail information please look bug#32495 */ + /* Improve WEP/TKIP performance with HT AP, detail information please look bug#32495 */ //zfHpSetTTSIFSTime(dev, 0x8); /* Notify wrapper of connection status changes */ @@ -4148,7 +4148,7 @@ void zfInfraConnectNetwork(zdev_t* dev) wd->sta.bIsSharedKey = 0; } - /* Improve WEP/TKIP performace with HT AP, detail information please look bug#32495 */ + /* Improve WEP/TKIP performance with HT AP, detail information please look bug#32495 */ /* if ( (pBssInfo->broadcomHTAp == 1) && (wd->sta.SWEncryptEnable != 0) ) diff --git a/drivers/staging/otus/80211core/ctxrx.c b/drivers/staging/otus/80211core/ctxrx.c index e258a7df53632cabc0fe644ae2cd2b12bb3d8416..ac54d5a636b0907d5a17a00bfea4577fc5506ff5 100644 --- a/drivers/staging/otus/80211core/ctxrx.c +++ b/drivers/staging/otus/80211core/ctxrx.c @@ -3093,7 +3093,7 @@ u16_t zfWlanRxFilter(zdev_t* dev, zbuf_t* buf) frameType = zmw_rx_buf_readh(dev, buf, offset); - // Don't divide 2^4 because we don't want the fragementation pkt to be treated as + // Don't divide 2^4 because we don't want the fragmentation pkt to be treated as // duplicated frames seq = zmw_rx_buf_readh(dev, buf, offset+22); dst0 = zmw_rx_buf_readh(dev, buf, offset+4); diff --git a/drivers/staging/otus/80211core/pub_zfi.h b/drivers/staging/otus/80211core/pub_zfi.h index 60b7d1c56deeefad85280e81a5f127923b506871..b7b7f455f357f17d8d30b539daf43cbde595a599 100644 --- a/drivers/staging/otus/80211core/pub_zfi.h +++ b/drivers/staging/otus/80211core/pub_zfi.h @@ -782,7 +782,7 @@ extern void zfiWlanSetDynamicSIFSParam(zdev_t* dev, u8_t val); /***** End of section 2 *****/ -/***** section 3 performace evaluation *****/ +/***** section 3 performance evaluation *****/ #ifdef ZM_ENABLE_PERFORMANCE_EVALUATION extern void zfiTxPerformanceMSDU(zdev_t* dev, u32_t tick); extern void zfiRxPerformanceMPDU(zdev_t* dev, zbuf_t* buf); diff --git a/drivers/staging/otus/apdbg.c b/drivers/staging/otus/apdbg.c index d3e2f62241963ee153233b95096be64231e84932..0eb93f19958a585a888dfab691f6b1193269935e 100644 --- a/drivers/staging/otus/apdbg.c +++ b/drivers/staging/otus/apdbg.c @@ -38,39 +38,39 @@ #include -#define ZM_IOCTL_REG_READ 0x01 -#define ZM_IOCTL_REG_WRITE 0x02 -#define ZM_IOCTL_MEM_DUMP 0x03 -#define ZM_IOCTL_REG_DUMP 0x05 -#define ZM_IOCTL_TXD_DUMP 0x06 -#define ZM_IOCTL_RXD_DUMP 0x07 -#define ZM_IOCTL_MEM_READ 0x0B -#define ZM_IOCTL_MEM_WRITE 0x0C -#define ZM_IOCTL_DMA_TEST 0x10 -#define ZM_IOCTL_REG_TEST 0x11 -#define ZM_IOCTL_TEST 0x80 -#define ZM_IOCTL_TALLY 0x81 //CWYang(+) -#define ZM_IOCTL_RTS 0xA0 -#define ZM_IOCTL_MIX_MODE 0xA1 -#define ZM_IOCTL_FRAG 0xA2 -#define ZM_IOCTL_SCAN 0xA3 -#define ZM_IOCTL_KEY 0xA4 -#define ZM_IOCTL_RATE 0xA5 -#define ZM_IOCTL_ENCRYPTION_MODE 0xA6 -#define ZM_IOCTL_GET_TXCNT 0xA7 -#define ZM_IOCTL_GET_DEAGG_CNT 0xA8 -#define ZM_IOCTL_DURATION_MODE 0xA9 -#define ZM_IOCTL_SET_AES_KEY 0xAA -#define ZM_IOCTL_SET_AES_MODE 0xAB -#define ZM_IOCTL_SIGNAL_STRENGTH 0xAC //CWYang(+) -#define ZM_IOCTL_SIGNAL_QUALITY 0xAD //CWYang(+) -#define ZM_IOCTL_SET_PIBSS_MODE 0xAE -#define ZDAPIOCTL SIOCDEVPRIVATE +#define ZM_IOCTL_REG_READ 0x01 +#define ZM_IOCTL_REG_WRITE 0x02 +#define ZM_IOCTL_MEM_DUMP 0x03 +#define ZM_IOCTL_REG_DUMP 0x05 +#define ZM_IOCTL_TXD_DUMP 0x06 +#define ZM_IOCTL_RXD_DUMP 0x07 +#define ZM_IOCTL_MEM_READ 0x0B +#define ZM_IOCTL_MEM_WRITE 0x0C +#define ZM_IOCTL_DMA_TEST 0x10 +#define ZM_IOCTL_REG_TEST 0x11 +#define ZM_IOCTL_TEST 0x80 +#define ZM_IOCTL_TALLY 0x81 /* CWYang(+) */ +#define ZM_IOCTL_RTS 0xA0 +#define ZM_IOCTL_MIX_MODE 0xA1 +#define ZM_IOCTL_FRAG 0xA2 +#define ZM_IOCTL_SCAN 0xA3 +#define ZM_IOCTL_KEY 0xA4 +#define ZM_IOCTL_RATE 0xA5 +#define ZM_IOCTL_ENCRYPTION_MODE 0xA6 +#define ZM_IOCTL_GET_TXCNT 0xA7 +#define ZM_IOCTL_GET_DEAGG_CNT 0xA8 +#define ZM_IOCTL_DURATION_MODE 0xA9 +#define ZM_IOCTL_SET_AES_KEY 0xAA +#define ZM_IOCTL_SET_AES_MODE 0xAB +#define ZM_IOCTL_SIGNAL_STRENGTH 0xAC /* CWYang(+) */ +#define ZM_IOCTL_SIGNAL_QUALITY 0xAD /* CWYang(+) */ +#define ZM_IOCTL_SET_PIBSS_MODE 0xAE +#define ZDAPIOCTL SIOCDEVPRIVATE struct zdap_ioctl { - unsigned short cmd; /* Command to run */ - unsigned int addr; /* Length of the data buffer */ - unsigned int value; /* Pointer to the data buffer */ + unsigned short cmd; /* Command to run */ + unsigned int addr; /* Length of the data buffer */ + unsigned int value; /* Pointer to the data buffer */ unsigned char data[0x100]; }; @@ -79,13 +79,13 @@ struct zdap_ioctl { #if 0 #define SKIP_ELEM { \ - while(isxdigit(*p)) \ - p++; \ + while (isxdigit(*p)) \ + p++; \ } #define SKIP_DELIMETER { \ - if(*p == ':' || *p == ' ') \ - p++; \ + if (*p == ':' || *p == ' ') \ + p++; \ } #endif @@ -97,361 +97,308 @@ char *prgname; int set_ioctl(int sock, struct ifreq *req) { - if (ioctl(sock, ZDAPIOCTL, req) < 0) { - fprintf(stderr, "%s: ioctl(SIOCGIFMAP): %s\n", - prgname, strerror(errno)); - return -1; - } + if (ioctl(sock, ZDAPIOCTL, req) < 0) { + fprintf(stderr, "%s: ioctl(SIOCGIFMAP): %s\n", + prgname, strerror(errno)); + return -1; + } - return 0; + return 0; } int read_reg(int sock, struct ifreq *req) { - struct zdap_ioctl *zdreq = 0; + struct zdap_ioctl *zdreq = 0; - if (!set_ioctl(sock, req)) - return -1; + if (!set_ioctl(sock, req)) + return -1; - //zdreq = (struct zdap_ioctl *)req->ifr_data; - //printf( "reg = %4x, value = %4x\n", zdreq->addr, zdreq->value); + /* + * zdreq = (struct zdap_ioctl *)req->ifr_data; + * printf( "reg = %4x, value = %4x\n", zdreq->addr, zdreq->value); + */ - return 0; + return 0; } int read_mem(int sock, struct ifreq *req) { - struct zdap_ioctl *zdreq = 0; - int i; - - if (!set_ioctl(sock, req)) - return -1; - - /*zdreq = (struct zdap_ioctl *)req->ifr_data; - printf( "dump mem from %x, length = %x\n", zdreq->addr, zdreq->value); - - for (i=0; ivalue; i++) { - printf("%02x", zdreq->data[i]); - printf(" "); - - if ((i>0) && ((i+1)%16 == 0)) - printf("\n"); - }*/ - - return 0; + struct zdap_ioctl *zdreq = 0; + int i; + + if (!set_ioctl(sock, req)) + return -1; + + /* + * zdreq = (struct zdap_ioctl *)req->ifr_data; + * printf("dump mem from %x, length = %x\n", zdreq->addr, zdreq->value); + * + * for (i=0; ivalue; i++) { + * printf("%02x", zdreq->data[i]); + * printf(" "); + * + * if ((i>0) && ((i+1)%16 == 0)) + * printf("\n"); + * } + */ + + return 0; } int main(int argc, char **argv) { - int sock; - int addr, value; - struct ifreq req; - char *action = NULL; - struct zdap_ioctl zdreq; - - prgname = argv[0]; - - if (argc < 3) { - fprintf(stderr,"%s: usage is \"%s [
] []\"\n", - prgname, prgname); - fprintf(stderr,"valid operation: read, write, mem, reg,\n"); - fprintf(stderr," : txd, rxd, rmem, wmem\n"); - fprintf(stderr," : dmat, regt, test\n"); - - fprintf(stderr," scan, Channel Scan\n"); - fprintf(stderr," rts , Set RTS Threshold\n"); - fprintf(stderr," frag , Set Fragment Threshold\n"); - fprintf(stderr," rate <0-28>, 0:AUTO, 1-4:CCK, 5-12:OFDM, 13-28:HT\n"); - fprintf(stderr," TBD mix <0 or 1>, Set 1 to enable mixed mode\n"); - fprintf(stderr," enc, <0-3>, 0=>OPEN, 1=>WEP64, 2=>WEP128, 3=>WEP256\n"); - fprintf(stderr," skey , Set WEP key\n"); - fprintf(stderr," txcnt, Get TxQ Cnt\n"); - fprintf(stderr," dagcnt, Get Deaggregate Cnt\n"); - fprintf(stderr," durmode , Set Duration Mode 0=>HW, 1=>SW\n"); - fprintf(stderr," aeskey \n"); - fprintf(stderr," aesmode \n"); - fprintf(stderr," wlanmode <0,1> 0:Station mode, 1:PIBSS mode\n"); - fprintf(stderr," tal <0,1>, Get Current Tally Info, 0=>read, 1=>read and reset\n"); - - exit(1); - } - - strcpy(req.ifr_name, argv[1]); - zdreq.addr = 0; - zdreq.value = 0; - - /* a silly raw socket just for ioctl()ling it */ - sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); - if (sock < 0) { - fprintf(stderr, "%s: socket(): %s\n", argv[0], strerror(errno)); - exit(1); - } - - if (argc >= 4) - { - sscanf(argv[3], "%x", &addr); - } - - if (argc >= 5) - { - sscanf(argv[4], "%x", &value); - } - - zdreq.addr = addr; - zdreq.value = value; - - if (!strcmp(argv[2], "read")) - { - zdreq.cmd = ZM_IOCTL_REG_READ; - } - else if (!strcmp(argv[2], "mem")) - { - zdreq.cmd = ZM_IOCTL_MEM_DUMP; - } - else if (!strcmp(argv[2], "write")) - { - zdreq.cmd = ZM_IOCTL_REG_WRITE; - } - else if (!strcmp(argv[2], "reg")) - { - zdreq.cmd = ZM_IOCTL_REG_DUMP; - } - else if (!strcmp(argv[2], "txd")) - { - zdreq.cmd = ZM_IOCTL_TXD_DUMP; - } - else if (!strcmp(argv[2], "rxd")) - { - zdreq.cmd = ZM_IOCTL_RXD_DUMP; - } - else if (!strcmp(argv[2], "rmem")) - { - zdreq.cmd = ZM_IOCTL_MEM_READ; - } - else if (!strcmp(argv[2], "wmem")) - { - zdreq.cmd = ZM_IOCTL_MEM_WRITE; - } - else if (!strcmp(argv[2], "dmat")) - { - zdreq.cmd = ZM_IOCTL_DMA_TEST; - } - else if (!strcmp(argv[2], "regt")) - { - zdreq.cmd = ZM_IOCTL_REG_TEST; - } - else if (!strcmp(argv[2], "test")) - { - zdreq.cmd = ZM_IOCTL_TEST; - } - else if (!strcmp(argv[2], "tal")) - { - sscanf(argv[3], "%d", &addr); - zdreq.addr = addr; - zdreq.cmd = ZM_IOCTL_TALLY; - } - else if (!strcmp(argv[2], "rts")) - { - sscanf(argv[3], "%d", &addr); - zdreq.addr = addr; - zdreq.cmd = ZM_IOCTL_RTS; - } - else if (!strcmp(argv[2], "mix")) - { - zdreq.cmd = ZM_IOCTL_MIX_MODE; - } - else if (!strcmp(argv[2], "frag")) - { - sscanf(argv[3], "%d", &addr); - zdreq.addr = addr; - zdreq.cmd = ZM_IOCTL_FRAG; - } - else if (!strcmp(argv[2], "scan")) - { - zdreq.cmd = ZM_IOCTL_SCAN; - } - else if (!strcmp(argv[2], "skey")) - { - zdreq.cmd = ZM_IOCTL_KEY; - - if (argc >= 4) - { - unsigned char temp[29]; - int i; - int keyLen; - int encType; - - keyLen = strlen(argv[3]); - - if (keyLen == 10) - { - sscanf(argv[3], "%02x%02x%02x%02x%02x", &temp[0], &temp[1], - &temp[2], &temp[3], &temp[4]); - } - else if (keyLen == 26) - { - sscanf(argv[3], "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - &temp[0], &temp[1], &temp[2], &temp[3], &temp[4], - &temp[5], &temp[6], &temp[7], &temp[8], &temp[9], - &temp[10], &temp[11], &temp[12]); - } - else if (keyLen == 58) - { - sscanf(argv[3], "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - &temp[0], &temp[1], &temp[2], &temp[3], &temp[4], - &temp[5], &temp[6], &temp[7], &temp[8], &temp[9], - &temp[10], &temp[11], &temp[12], &temp[13], &temp[14], - &temp[15], &temp[16], &temp[17], &temp[18], &temp[19], - &temp[20], &temp[21], &temp[22], &temp[23], &temp[24], - &temp[25], &temp[26], &temp[27], &temp[28]); - } - else - { - fprintf(stderr, "Invalid key length\n"); - exit(1); - } - zdreq.addr = keyLen/2; - - for(i=0; i 28) - { - fprintf(stderr, "Invalid rate, range:0~28\n"); - exit(1); - } - zdreq.addr = addr; - zdreq.cmd = ZM_IOCTL_RATE; - } - else if (!strcmp(argv[2], "enc")) - { - sscanf(argv[3], "%d", &addr); - - if (addr > 3) - { - fprintf(stderr, "Invalid encryption mode, range:0~3\n"); - exit(1); - } - - if (addr == 2) - { - addr = 5; - } - else if (addr == 3) - { - addr = 6; - } - - zdreq.addr = addr; - zdreq.cmd = ZM_IOCTL_ENCRYPTION_MODE; - } - else if (!strcmp(argv[2], "txcnt")) - { - zdreq.cmd = ZM_IOCTL_GET_TXCNT; - } - else if (!strcmp(argv[2], "dagcnt")) - { - sscanf(argv[3], "%d", &addr); - - if (addr != 0 && addr != 1) - { - fprintf(stderr, "The value should be 0 or 1\n"); - exit(0); - } - - zdreq.addr = addr; - zdreq.cmd = ZM_IOCTL_GET_DEAGG_CNT; - } - else if (!strcmp(argv[2], "durmode")) - { - sscanf(argv[3], "%d", &addr); - - if (addr != 0 && addr != 1) - { - fprintf(stderr, "The Duration mode should be 0 or 1\n"); - exit(0); - } - - zdreq.addr = addr; - zdreq.cmd = ZM_IOCTL_DURATION_MODE; - } - else if (!strcmp(argv[2], "aeskey")) - { - unsigned char temp[16]; - int i; - - sscanf(argv[3], "%d", &addr); - - sscanf(argv[4], "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", &temp[0], &temp[1], &temp[2], &temp[3], &temp[4], &temp[5], &temp[6], &temp[7], &temp[8], &temp[9], &temp[10], &temp[11], &temp[12], &temp[13], &temp[14], &temp[15]); - - for(i = 0; i < 16; i++) - { - zdreq.data[i] = temp[i]; - } - - zdreq.addr = addr; - zdreq.cmd = ZM_IOCTL_SET_AES_KEY; - } - else if (!strcmp(argv[2], "aesmode")) - { - sscanf(argv[3], "%d", &addr); - - zdreq.addr = addr; - zdreq.cmd = ZM_IOCTL_SET_AES_MODE; - } - else if (!strcmp(argv[2], "wlanmode")) - { - sscanf(argv[3], "%d", &addr); - - zdreq.addr = addr; - zdreq.cmd = ZM_IOCTL_SET_PIBSS_MODE; - } - else - { - fprintf(stderr, "error action\n"); - exit(1); - } - - req.ifr_data = (char *)&zdreq; - set_ioctl(sock, &req); + int sock; + int addr, value; + struct ifreq req; + char *action = NULL; + struct zdap_ioctl zdreq; + + prgname = argv[0]; + + if (argc < 3) { + fprintf(stderr, "%s: usage is \"%s " + "[
] []\"\n", prgname, prgname); + fprintf(stderr, "valid operation : read, write, mem, reg, \n"); + fprintf(stderr, " : txd, rxd, rmem, wmem\n"); + fprintf(stderr, " : dmat, regt, test\n"); + + fprintf(stderr, " scan, Channel Scan\n"); + fprintf(stderr, " rts , Set RTS Threshold\n"); + fprintf(stderr, " frag , Set Fragment" + " Threshold\n"); + fprintf(stderr, " rate <0-28>, 0:AUTO, 1-4:CCK," + " 5-12:OFDM, 13-28:HT\n"); + fprintf(stderr, " TBD mix <0 or 1>, Set 1 to enable" + " mixed mode\n"); + fprintf(stderr, " enc, <0-3>, 0=>OPEN, 1=>WEP64, " + "2=>WEP128, 3=>WEP256\n"); + fprintf(stderr, " skey , Set WEP key\n"); + fprintf(stderr, " txcnt, Get TxQ Cnt\n"); + fprintf(stderr, " dagcnt, Get Deaggregate Cnt\n"); + fprintf(stderr, " durmode , Set Duration Mode " + "0=>HW, 1=>SW\n"); + fprintf(stderr, " aeskey \n"); + fprintf(stderr, " aesmode \n"); + fprintf(stderr, " wlanmode <0,1> 0:Station mode, " + "1:PIBSS mode\n"); + fprintf(stderr, " tal <0,1>, Get Current Tally Info, " + "0=>read, 1=>read and reset\n"); + + exit(1); + } + + strcpy(req.ifr_name, argv[1]); + zdreq.addr = 0; + zdreq.value = 0; + + /* a silly raw socket just for ioctl()ling it */ + sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); + if (sock < 0) { + fprintf(stderr, "%s: socket(): %s\n", argv[0], strerror(errno)); + exit(1); + } + + if (argc >= 4) + sscanf(argv[3], "%x", &addr); + + if (argc >= 5) + sscanf(argv[4], "%x", &value); + + zdreq.addr = addr; + zdreq.value = value; + + if (!strcmp(argv[2], "read")) + zdreq.cmd = ZM_IOCTL_REG_READ; + else if (!strcmp(argv[2], "mem")) + zdreq.cmd = ZM_IOCTL_MEM_DUMP; + else if (!strcmp(argv[2], "write")) + zdreq.cmd = ZM_IOCTL_REG_WRITE; + else if (!strcmp(argv[2], "reg")) + zdreq.cmd = ZM_IOCTL_REG_DUMP; + else if (!strcmp(argv[2], "txd")) + zdreq.cmd = ZM_IOCTL_TXD_DUMP; + else if (!strcmp(argv[2], "rxd")) + zdreq.cmd = ZM_IOCTL_RXD_DUMP; + else if (!strcmp(argv[2], "rmem")) + zdreq.cmd = ZM_IOCTL_MEM_READ; + else if (!strcmp(argv[2], "wmem")) + zdreq.cmd = ZM_IOCTL_MEM_WRITE; + else if (!strcmp(argv[2], "dmat")) + zdreq.cmd = ZM_IOCTL_DMA_TEST; + else if (!strcmp(argv[2], "regt")) + zdreq.cmd = ZM_IOCTL_REG_TEST; + else if (!strcmp(argv[2], "test")) + zdreq.cmd = ZM_IOCTL_TEST; + else if (!strcmp(argv[2], "tal")) { + sscanf(argv[3], "%d", &addr); + zdreq.addr = addr; + zdreq.cmd = ZM_IOCTL_TALLY; + } else if (!strcmp(argv[2], "rts")) { + sscanf(argv[3], "%d", &addr); + zdreq.addr = addr; + zdreq.cmd = ZM_IOCTL_RTS; + } else if (!strcmp(argv[2], "mix")) { + zdreq.cmd = ZM_IOCTL_MIX_MODE; + } else if (!strcmp(argv[2], "frag")) { + sscanf(argv[3], "%d", &addr); + zdreq.addr = addr; + zdreq.cmd = ZM_IOCTL_FRAG; + } else if (!strcmp(argv[2], "scan")) { + zdreq.cmd = ZM_IOCTL_SCAN; + } else if (!strcmp(argv[2], "skey")) { + zdreq.cmd = ZM_IOCTL_KEY; + + if (argc >= 4) { + unsigned char temp[29]; + int i; + int keyLen; + int encType; + + keyLen = strlen(argv[3]); + + if (keyLen == 10) + sscanf(argv[3], "%02x%02x%02x%02x%02x", + &temp[0], &temp[1], &temp[2], &temp[3], + &temp[4]); + else if (keyLen == 26) + sscanf(argv[3], "%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x%02x", + &temp[0], &temp[1], &temp[2], &temp[3], + &temp[4], &temp[5], &temp[6], &temp[7], + &temp[8], &temp[9], &temp[10], + &temp[11], &temp[12]); + else if (keyLen == 58) + sscanf(argv[3], "%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x", + &temp[0], &temp[1], &temp[2], &temp[3], + &temp[4], &temp[5], &temp[6], &temp[7], + &temp[8], &temp[9], &temp[10], + &temp[11], &temp[12], &temp[13], + &temp[14], &temp[15], &temp[16], + &temp[17], &temp[18], &temp[19], + &temp[20], &temp[21], &temp[22], + &temp[23], &temp[24], &temp[25], + &temp[26], &temp[27], &temp[28]); + else { + fprintf(stderr, "Invalid key length\n"); + exit(1); + } + zdreq.addr = keyLen/2; + + for (i = 0; i < zdreq.addr; i++) + zdreq.data[i] = temp[i]; + } else { + printf("Error : Key required!\n"); + } + } else if (!strcmp(argv[2], "rate")) { + sscanf(argv[3], "%d", &addr); + + if (addr > 28) { + fprintf(stderr, "Invalid rate, range:0~28\n"); + exit(1); + } + zdreq.addr = addr; + zdreq.cmd = ZM_IOCTL_RATE; + } else if (!strcmp(argv[2], "enc")) { + sscanf(argv[3], "%d", &addr); + + if (addr > 3) { + fprintf(stderr, "Invalid encryption mode, range:0~3\n"); + exit(1); + } + + if (addr == 2) + addr = 5; + else if (addr == 3) + addr = 6; + + zdreq.addr = addr; + zdreq.cmd = ZM_IOCTL_ENCRYPTION_MODE; + } else if (!strcmp(argv[2], "txcnt")) { + zdreq.cmd = ZM_IOCTL_GET_TXCNT; + } else if (!strcmp(argv[2], "dagcnt")) { + sscanf(argv[3], "%d", &addr); + + if (addr != 0 && addr != 1) { + fprintf(stderr, "The value should be 0 or 1\n"); + exit(0); + } + + zdreq.addr = addr; + zdreq.cmd = ZM_IOCTL_GET_DEAGG_CNT; + } else if (!strcmp(argv[2], "durmode")) { + sscanf(argv[3], "%d", &addr); + + if (addr != 0 && addr != 1) { + fprintf(stderr, "The Duration mode should be 0 or 1\n"); + exit(0); + } + + zdreq.addr = addr; + zdreq.cmd = ZM_IOCTL_DURATION_MODE; + } else if (!strcmp(argv[2], "aeskey")) { + unsigned char temp[16]; + int i; + + sscanf(argv[3], "%d", &addr); + + sscanf(argv[4], "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x", &temp[0], &temp[1], + &temp[2], &temp[3], &temp[4], &temp[5], &temp[6], + &temp[7], &temp[8], &temp[9], &temp[10], &temp[11], + &temp[12], &temp[13], &temp[14], &temp[15]); + + for (i = 0; i < 16; i++) + zdreq.data[i] = temp[i]; + + zdreq.addr = addr; + zdreq.cmd = ZM_IOCTL_SET_AES_KEY; + } else if (!strcmp(argv[2], "aesmode")) { + sscanf(argv[3], "%d", &addr); + + zdreq.addr = addr; + zdreq.cmd = ZM_IOCTL_SET_AES_MODE; + } else if (!strcmp(argv[2], "wlanmode")) { + sscanf(argv[3], "%d", &addr); + + zdreq.addr = addr; + zdreq.cmd = ZM_IOCTL_SET_PIBSS_MODE; + } else { + fprintf(stderr, "error action\n"); + exit(1); + } + + req.ifr_data = (char *)&zdreq; + set_ioctl(sock, &req); fail: - exit(0); + exit(0); } unsigned char asctohex(char *str) { - unsigned char value; + unsigned char value; - value = hex(*str) & 0x0f; - value = value << 4; - str++; - value |= hex(*str) & 0x0f; + value = hex(*str) & 0x0f; + value = value << 4; + str++; + value |= hex(*str) & 0x0f; - return value; + return value; } char hex(char v) { - if(isdigit(v)) - return v - '0'; - else if(isxdigit(v)) - return (tolower(v) - 'a' + 10); - else - return 0; + if (isdigit(v)) + return v - '0'; + else if (isxdigit(v)) + return tolower(v) - 'a' + 10; + else + return 0; } diff --git a/drivers/staging/otus/athr_common.h b/drivers/staging/otus/athr_common.h index 620f78a41d5f0935e8d664a059816774011e27c4..3e32f5b4ac684a1eb3a3c3e3aff9285882236698 100644 --- a/drivers/staging/otus/athr_common.h +++ b/drivers/staging/otus/athr_common.h @@ -68,7 +68,7 @@ #define ZM_WAPI_KEY_SIZE 32 #define ZM_WAPI_IV_LEN 16 -#endif //ZM_ENALBE_WAPI +#endif /* ZM_ENALBE_WAPI */ /* structure definition */ struct athr_wlan_param { @@ -123,7 +123,7 @@ struct athr_wapi_param { u8 key[ZM_WAPI_KEY_SIZE]; } crypt; struct { - u8 wapi_policy; + u8 wapi_policy; } info; } u; }; @@ -132,10 +132,10 @@ struct athr_wapi_sta_info { u16 msg_type; u16 datalen; - u8 sta_mac[ETH_ALEN]; + u8 sta_mac[ETH_ALEN]; u8 reserve_data[2]; - u8 gsn[ZM_WAPI_IV_LEN]; + u8 gsn[ZM_WAPI_IV_LEN]; u8 wie[256]; }; -#endif //ZM_ENALBE_WAPI +#endif /* ZM_ENALBE_WAPI */ #endif diff --git a/drivers/staging/otus/oal_dt.h b/drivers/staging/otus/oal_dt.h index e82b9770fca1757b5e069ea0e9f884a9a55ce435..fb6d11a99cc587abbbb17f49d873558a0a0c392a 100644 --- a/drivers/staging/otus/oal_dt.h +++ b/drivers/staging/otus/oal_dt.h @@ -39,15 +39,15 @@ typedef long s32_t; typedef short s16_t; typedef char s8_t; -#ifndef TRUE -#define TRUE (1==1) +#ifndef TRUE +#define TRUE (1 == 1) #endif -#ifndef FALSE -#define FALSE (1==0) +#ifndef FALSE +#define FALSE (1 == 0) #endif -#ifndef NULL +#ifndef NULL #define NULL 0 #endif diff --git a/drivers/staging/otus/oal_marc.h b/drivers/staging/otus/oal_marc.h index 206111616a0354921b14a37314897e618baa0aed..e7a9081b1a7c99089c104af497148ca5ec4f5437 100644 --- a/drivers/staging/otus/oal_marc.h +++ b/drivers/staging/otus/oal_marc.h @@ -34,17 +34,19 @@ /***** Critical section *****/ /* Declare for critical section */ #ifndef ZM_HALPLUS_LOCK -#define zmw_get_wlan_dev(dev) struct zsWlanDev *wd = (struct zsWlanDev*) ((((struct usbdrv_private*)dev->priv)->wd)) +#define zmw_get_wlan_dev(dev) struct zsWlanDev *wd = (struct zsWlanDev *) \ + ((((struct usbdrv_private *)dev->priv)->wd)) #define zmw_declare_for_critical_section() unsigned long irqFlag; /* Enter critical section */ -#define zmw_enter_critical_section(dev) \ - spin_lock_irqsave(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); +#define zmw_enter_critical_section(dev) spin_lock_irqsave( \ + &(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); /* leave critical section */ #define zmw_leave_critical_section(dev) \ - spin_unlock_irqrestore(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); + spin_unlock_irqrestore(&(((struct usbdrv_private *) \ + (dev->priv))->cs_lock), irqFlag); #else #define zmw_get_wlan_dev(dev) struct zsWlanDev *wd = zfwGetWlanDev(dev); @@ -52,31 +54,29 @@ #define zmw_declare_for_critical_section() /* Enter critical section */ -#define zmw_enter_critical_section(dev) \ - zfwEnterCriticalSection(dev); +#define zmw_enter_critical_section(dev) zfwEnterCriticalSection(dev); /* leave critical section */ -#define zmw_leave_critical_section(dev) \ - zfwLeaveCriticalSection(dev); +#define zmw_leave_critical_section(dev) zfwLeaveCriticalSection(dev); #endif /***** Byte order converting *****/ #ifdef ZM_CONFIG_BIG_ENDIAN -#define zmw_cpu_to_le32(v) (((v & 0xff000000) >> 24) | \ - ((v & 0x00ff0000) >> 8) | \ - ((v & 0x0000ff00) << 8) | \ - ((v & 0x000000ff) << 24)) +#define zmw_cpu_to_le32(v) (((v & 0xff000000) >> 24) | \ + ((v & 0x00ff0000) >> 8) | \ + ((v & 0x0000ff00) << 8) | \ + ((v & 0x000000ff) << 24)) -#define zmw_le32_to_cpu(v) (((v & 0xff000000) >> 24) | \ - ((v & 0x00ff0000) >> 8) | \ - ((v & 0x0000ff00) << 8) | \ - ((v & 0x000000ff) << 24)) +#define zmw_le32_to_cpu(v) (((v & 0xff000000) >> 24) | \ + ((v & 0x00ff0000) >> 8) | \ + ((v & 0x0000ff00) << 8) | \ + ((v & 0x000000ff) << 24)) #define zmw_cpu_to_le16(v) (((v & 0xff00) >> 8) | \ - ((v & 0x00ff) << 8)) + ((v & 0x00ff) << 8)) #define zmw_le16_to_cpu(v) (((v & 0xff00) >> 8) | \ - ((v & 0x00ff) << 8)) + ((v & 0x00ff) << 8)) #else #define zmw_cpu_to_le32(v) (v) #define zmw_le32_to_cpu(v) (v) @@ -88,33 +88,41 @@ /* Called to read/write buffer */ #ifndef ZM_HALPLUS_LOCK -#define zmw_buf_readb(dev, buf, offset) *(u8_t*)((u8_t*)buf->data+offset) -#define zmw_buf_readh(dev, buf, offset) zmw_cpu_to_le16(*(u16_t*)((u8_t*)buf->data+offset)) -#define zmw_buf_writeb(dev, buf, offset, value) *(u8_t*)((u8_t*)buf->data+offset) = value -#define zmw_buf_writeh(dev, buf, offset, value) *(u16_t*)((u8_t*)buf->data+offset) = zmw_cpu_to_le16(value) -#define zmw_buf_get_buffer(dev, buf) (u8_t*)(buf->data) +#define zmw_buf_readb(dev, buf, offset) (*(u8_t *)((u8_t *)buf->data+offset)) +#define zmw_buf_readh(dev, buf, offset) zmw_cpu_to_le16(*(u16_t *) \ + ((u8_t *)buf->data+offset)) +#define zmw_buf_writeb(dev, buf, offset, value) (*(u8_t *) \ + ((u8_t *)buf->data+offset) = value) +#define zmw_buf_writeh(dev, buf, offset, value) (*(u16_t *) \ + ((u8_t *)buf->data+offset) = zmw_cpu_to_le16(value)) +#define zmw_buf_get_buffer(dev, buf) (u8_t *)(buf->data) #else #define zmw_buf_readb(dev, buf, offset) zfwBufReadByte(dev, buf, offset) #define zmw_buf_readh(dev, buf, offset) zfwBufReadHalfWord(dev, buf, offset) -#define zmw_buf_writeb(dev, buf, offset, value) zfwBufWriteByte(dev, buf, offset, value) -#define zmw_buf_writeh(dev, buf, offset, value) zfwBufWriteHalfWord(dev, buf, offset, value) +#define zmw_buf_writeb(dev, buf, offset, value) \ + zfwBufWriteByte(dev, buf, offset, value) +#define zmw_buf_writeh(dev, buf, offset, value) \ + zfwBufWriteHalfWord(dev, buf, offset, value) #define zmw_buf_get_buffer(dev, buf) zfwGetBuffer(dev, buf) #endif /***** Debug message *****/ #if 0 -#define zm_debug_msg0(msg) printk("%s:%s\n", __func__, msg); -#define zm_debug_msg1(msg, val) printk("%s:%s%ld\n", __func__, \ - msg, (u32_t)val); -#define zm_debug_msg2(msg, val) printk("%s:%s%lxh\n", __func__, \ - msg, (u32_t)val); -#define zm_debug_msg_s(msg, val) printk("%s:%s%s\n", __func__, \ - msg, val); -#define zm_debug_msg_p(msg, val1, val2) printk("%s:%s%01ld.%02ld\n", __func__, \ - msg, (val1/val2), (((val1*100)/val2)%100)); +#define zm_debug_msg0(msg) printk(KERN_DEBUG "%s:%s\n", __func__, msg); +#define zm_debug_msg1(msg, val) printk(KERN_DEBUG "%s:%s%ld\n", __func__, \ + msg, (u32_t)val); +#define zm_debug_msg2(msg, val) printk(KERN_DEBUG "%s:%s%lxh\n", __func__, \ + msg, (u32_t)val); +#define zm_debug_msg_s(msg, val) printk(KERN_DEBUG "%s:%s%s\n", __func__, \ + msg, val); +#define zm_debug_msg_p(msg, val1, val2) do { \ + printk(KERN_DEBUG "%s:%s%01ld.%02ld\n", \ + __func__, \ + msg, (val1/val2), (((val1*100)/val2)%100)); + } while (0) #define zm_dbg(S) printk S #else #define zm_debug_msg0(msg) @@ -125,10 +133,10 @@ #define zm_dbg(S) #endif -#define zm_assert(expr) if(!(expr)) { \ - printk( "Atheors Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } +#define zm_assert(expr) if (!(expr)) { \ + printk(KERN_ERR "Atheors Assertion failed! %s, %s, %s,line=%d\n",\ + #expr, __FILE__, __func__, __LINE__); \ + } #define DbgPrint printk diff --git a/drivers/staging/otus/usbdrv.c b/drivers/staging/otus/usbdrv.c index 48aa30a621641b77b88c6638cdb9c8f7ce30f937..b0adbc8b2dc2403c9e54bad07ecbfbe0ae70815c 100644 --- a/drivers/staging/otus/usbdrv.c +++ b/drivers/staging/otus/usbdrv.c @@ -111,7 +111,7 @@ extern u8_t zfLnxCreateThread(zdev_t *dev); /* Definition of Wireless Extension */ -//wireless extension helper functions +/* wireless extension helper functions */ extern int usbdrv_ioctl_setessid(struct net_device *dev, struct iw_point *erq); extern int usbdrv_ioctl_setrts(struct net_device *dev, struct iw_param *rrq); /* Wireless Extension Handler functions */ @@ -282,8 +282,8 @@ static struct iw_handler_def p80211wext_handler_def = { }; /* WDS */ -//struct zsWdsStruct wds[ZM_WDS_PORT_NUMBER]; -//void zfInitWdsStruct(void); +/* struct zsWdsStruct wds[ZM_WDS_PORT_NUMBER]; */ +/* void zfInitWdsStruct(void); */ /* VAP */ struct zsVapStruct vap[ZM_VAP_PORT_NUMBER]; @@ -314,13 +314,11 @@ irqreturn_t usbdrv_intr(int irq, void *dev_inst, struct pt_regs *regs) return IRQ_NONE; /* the device is closed, don't continue or else bad things may happen. */ - if (!netif_running(dev)) { + if (!netif_running(dev)) return IRQ_NONE; - } - if (macp->driver_isolated) { + if (macp->driver_isolated) return IRQ_NONE; - } #if (WLAN_HOSTIF == WLAN_PCI) //zfiIsrPci(dev); @@ -340,9 +338,11 @@ int usbdrv_open(struct net_device *dev) printk("Enter open()\n"); -//#ifndef CONFIG_SMP -// read_lock(&(macp->isolate_lock)); -//#endif +/* + * #ifndef CONFIG_SMP + * read_lock(&(macp->isolate_lock)); + * #endif + */ if (macp->driver_isolated) { rc = -EBUSY; goto exit; @@ -393,11 +393,11 @@ int usbdrv_open(struct net_device *dev) dev->dev_addr[4] = addr[4]; dev->dev_addr[5] = addr[5]; #endif - //zfwMacAddressNotify() will be called to setup dev->dev_addr[] + /* zfwMacAddressNotify() will be called to setup dev->dev_addr[] */ zfLnxCreateThread(dev); - mod_timer(&(macp->hbTimer10ms), jiffies + (1*HZ)/100); //10 ms + mod_timer(&(macp->hbTimer10ms), jiffies + (1*HZ)/100); /* 10 ms */ netif_carrier_on(dev); @@ -425,15 +425,15 @@ int usbdrv_open(struct net_device *dev) #if ZM_SHARE_AUTH == 1 zfiWlanSetAuthenticationMode(dev, 1); - #endif //#if ZM_SHARE_AUTH == 1 - #endif //#if ZM_WEP_MOME == 1 + #endif /* #if ZM_SHARE_AUTH == 1 */ + #endif /* #if ZM_WEP_MOME == 1 */ #elif ZM_PIBSS_MODE == 1 zfiWlanSetWlanMode(dev, ZM_MODE_PSEUDO); #else zfiWlanSetWlanMode(dev, ZM_MODE_INFRASTRUCTURE); #endif - //zfiWlanSetChannel(dev, ZM_CHANNEL, FALSE); + /* zfiWlanSetChannel(dev, ZM_CHANNEL, FALSE); */ zfiWlanSetFrequency(dev, 2462000, FALSE); zfiWlanSetRtsThreshold(dev, 32767); zfiWlanSetFragThreshold(dev, 0); @@ -720,7 +720,7 @@ void zfLnxInitVapStruct(void) { u16_t i; - for (i=0; i @@ -86,8 +86,7 @@ struct driver_stats { #define ZM_MAX_RX_URB_NUM 16 #define ZM_MAX_TX_BUF_NUM 128 -typedef struct UsbTxQ -{ +typedef struct UsbTxQ { zbuf_t *buf; u8_t hdr[80]; u16_t hdrlen; @@ -100,17 +99,16 @@ typedef struct UsbTxQ struct zdap_ioctl { - u16_t cmd; /* Command to run */ - u32_t addr; /* Length of the data buffer */ - u32_t value; /* Pointer to the data buffer */ + u16_t cmd; /* Command to run */ + u32_t addr; /* Length of the data buffer */ + u32_t value; /* Pointer to the data buffer */ u8_t data[0x100]; }; #define ZM_OAL_MAX_STA_SUPPORT 16 -struct usbdrv_private -{ - //linux used +struct usbdrv_private { + /* linux used */ struct net_device *device; #if (WLAN_HOSTIF == WLAN_PCI) struct pci_dev *pdev; @@ -121,7 +119,7 @@ struct usbdrv_private #endif struct driver_stats drv_stats; char ifname[IFNAMSIZ]; - int using_dac; + int using_dac; u8_t rev_id; /* adapter PCI revision ID */ rwlock_t isolate_lock; spinlock_t cs_lock; @@ -130,78 +128,76 @@ struct usbdrv_private void *regp; #endif - /* timer for heart beat */ + /* timer for heart beat */ struct timer_list hbTimer10ms; /* For driver core */ - void* wd; + void *wd; #if (WLAN_HOSTIF == WLAN_USB) - u8_t txUsbBuf[ZM_MAX_TX_URB_NUM][ZM_USB_TX_BUF_SIZE]; - u8_t regUsbReadBuf[ZM_USB_REG_MAX_BUF_SIZE]; - u8_t regUsbWriteBuf[ZM_USB_REG_MAX_BUF_SIZE]; + u8_t txUsbBuf[ZM_MAX_TX_URB_NUM][ZM_USB_TX_BUF_SIZE]; + u8_t regUsbReadBuf[ZM_USB_REG_MAX_BUF_SIZE]; + u8_t regUsbWriteBuf[ZM_USB_REG_MAX_BUF_SIZE]; urb_t *WlanTxDataUrb[ZM_MAX_TX_URB_NUM]; urb_t *WlanRxDataUrb[ZM_MAX_RX_URB_NUM]; urb_t *RegOutUrb; urb_t *RegInUrb; - UsbTxQ_t UsbTxBufQ[ZM_MAX_TX_BUF_NUM]; - zbuf_t *UsbRxBufQ[ZM_MAX_RX_URB_NUM]; - u16_t TxBufHead; - u16_t TxBufTail; - u16_t TxBufCnt; - u16_t TxUrbHead; - u16_t TxUrbTail; - u16_t TxUrbCnt; - u16_t RxBufHead; - u16_t RxBufTail; - u16_t RxBufCnt; + UsbTxQ_t UsbTxBufQ[ZM_MAX_TX_BUF_NUM]; + zbuf_t *UsbRxBufQ[ZM_MAX_RX_URB_NUM]; + u16_t TxBufHead; + u16_t TxBufTail; + u16_t TxBufCnt; + u16_t TxUrbHead; + u16_t TxUrbTail; + u16_t TxUrbCnt; + u16_t RxBufHead; + u16_t RxBufTail; + u16_t RxBufCnt; #endif #if ZM_USB_STREAM_MODE == 1 - zbuf_t *reamin_buf; + zbuf_t *reamin_buf; #endif #ifdef ZM_HOSTAPD_SUPPORT - struct athr_wlan_param athr_wpa_req; + struct athr_wlan_param athr_wpa_req; #endif - struct sock *netlink_sk; - u8_t DeviceOpened; //CWYang(+) - u8_t supIe[50]; - u8_t supLen; - struct ieee80211req_wpaie stawpaie[ZM_OAL_MAX_STA_SUPPORT]; - u8_t forwardMgmt; - - struct zfCbUsbFuncTbl usbCbFunctions; - - /* For keventd */ - u32_t flags; - unsigned long kevent_flags; - u16_t kevent_ready; - - struct semaphore ioctl_sem; - struct work_struct kevent; - wait_queue_head_t wait_queue_event; + struct sock *netlink_sk; + u8_t DeviceOpened; /* CWYang(+) */ + u8_t supIe[50]; + u8_t supLen; + struct ieee80211req_wpaie stawpaie[ZM_OAL_MAX_STA_SUPPORT]; + u8_t forwardMgmt; + + struct zfCbUsbFuncTbl usbCbFunctions; + + /* For keventd */ + u32_t flags; + unsigned long kevent_flags; + u16_t kevent_ready; + + struct semaphore ioctl_sem; + struct work_struct kevent; + wait_queue_head_t wait_queue_event; #ifdef ZM_HALPLUS_LOCK - unsigned long hal_irqFlag; + unsigned long hal_irqFlag; #endif - u16_t adapterState; + u16_t adapterState; }; /* WDS */ #define ZM_WDS_PORT_NUMBER 6 -struct zsWdsStruct -{ - struct net_device* dev; +struct zsWdsStruct { + struct net_device *dev; u16_t openFlag; }; /* VAP */ #define ZM_VAP_PORT_NUMBER 7 -struct zsVapStruct -{ - struct net_device* dev; +struct zsVapStruct { + struct net_device *dev; u16_t openFlag; }; @@ -215,25 +211,25 @@ struct zsVapStruct #define ZM_IOCTL_RXD_DUMP 0x07 #define ZM_IOCTL_MEM_READ 0x0B #define ZM_IOCTL_MEM_WRITE 0x0C -#define ZM_IOCTL_DMA_TEST 0x10 -#define ZM_IOCTL_REG_TEST 0x11 -#define ZM_IOCTL_TEST 0x80 -#define ZM_IOCTL_TALLY 0x81 //CWYang(+) -#define ZM_IOCTL_RTS 0xA0 -#define ZM_IOCTL_MIX_MODE 0xA1 -#define ZM_IOCTL_FRAG 0xA2 -#define ZM_IOCTL_SCAN 0xA3 -#define ZM_IOCTL_KEY 0xA4 -#define ZM_IOCTL_RATE 0xA5 -#define ZM_IOCTL_ENCRYPTION_MODE 0xA6 -#define ZM_IOCTL_GET_TXCNT 0xA7 -#define ZM_IOCTL_GET_DEAGG_CNT 0xA8 -#define ZM_IOCTL_DURATION_MODE 0xA9 -#define ZM_IOCTL_SET_AES_KEY 0xAA -#define ZM_IOCTL_SET_AES_MODE 0xAB -#define ZM_IOCTL_SIGNAL_STRENGTH 0xAC //CWYang(+) -#define ZM_IOCTL_SIGNAL_QUALITY 0xAD //CWYang(+) -#define ZM_IOCTL_SET_PIBSS_MODE 0xAE +#define ZM_IOCTL_DMA_TEST 0x10 +#define ZM_IOCTL_REG_TEST 0x11 +#define ZM_IOCTL_TEST 0x80 +#define ZM_IOCTL_TALLY 0x81 /* CWYang(+) */ +#define ZM_IOCTL_RTS 0xA0 +#define ZM_IOCTL_MIX_MODE 0xA1 +#define ZM_IOCTL_FRAG 0xA2 +#define ZM_IOCTL_SCAN 0xA3 +#define ZM_IOCTL_KEY 0xA4 +#define ZM_IOCTL_RATE 0xA5 +#define ZM_IOCTL_ENCRYPTION_MODE 0xA6 +#define ZM_IOCTL_GET_TXCNT 0xA7 +#define ZM_IOCTL_GET_DEAGG_CNT 0xA8 +#define ZM_IOCTL_DURATION_MODE 0xA9 +#define ZM_IOCTL_SET_AES_KEY 0xAA +#define ZM_IOCTL_SET_AES_MODE 0xAB +#define ZM_IOCTL_SIGNAL_STRENGTH 0xAC /* CWYang(+) */ +#define ZM_IOCTL_SIGNAL_QUALITY 0xAD /* CWYang(+) */ +#define ZM_IOCTL_SET_PIBSS_MODE 0xAE #define ZDAPIOCTL SIOCDEVPRIVATE diff --git a/drivers/staging/otus/wrap_buf.c b/drivers/staging/otus/wrap_buf.c index a0f677a52616ba5622d913242f1153a2866f4511..d7ee0b454e9167ac39f68cbdc5f8af7b527db707 100644 --- a/drivers/staging/otus/wrap_buf.c +++ b/drivers/staging/otus/wrap_buf.c @@ -34,9 +34,9 @@ /* Called to allocate buffer, must return a continue buffer space */ -zbuf_t* zfwBufAllocate(zdev_t* dev, u16_t len) +zbuf_t *zfwBufAllocate(zdev_t *dev, u16_t len) { - zbuf_t* buf; + zbuf_t *buf; /* Allocate SKB for packet*/ buf = dev_alloc_skb(len); @@ -46,15 +46,15 @@ zbuf_t* zfwBufAllocate(zdev_t* dev, u16_t len) /* Called to free buffer, replace below 3 functions */ -void zfwBufFree(zdev_t* dev, zbuf_t* buf, u16_t status) +void zfwBufFree(zdev_t *dev, zbuf_t *buf, u16_t status) { dev_kfree_skb_any(buf); } /* Called to adjust buffer size and head pointer */ -u16_t zfwBufRemoveHead(zdev_t* dev, zbuf_t* buf, u16_t size) +u16_t zfwBufRemoveHead(zdev_t *dev, zbuf_t *buf, u16_t size) { - //zm_assert(buf->len > size); + /* zm_assert(buf->len > size); */ buf->data += size; buf->len -= size; @@ -68,7 +68,7 @@ u16_t zfwBufRemoveHead(zdev_t* dev, zbuf_t* buf, u16_t size) /* Used to chain Rx buffer to form a frame. if the prepared Rx buffer */ /* is greater than an ethernet frame(1518+32 byte), then this function */ /* will only be called with head=NULL. */ -u16_t zfwBufChain(zdev_t* dev, zbuf_t** head, zbuf_t* tail) +u16_t zfwBufChain(zdev_t *dev, zbuf_t **head, zbuf_t *tail) { *head = tail; @@ -77,7 +77,7 @@ u16_t zfwBufChain(zdev_t* dev, zbuf_t** head, zbuf_t* tail) /* Called when doing infra-bss forwarding */ -u16_t zfwBufCopy(zdev_t* dev, zbuf_t* dst, zbuf_t* src) +u16_t zfwBufCopy(zdev_t *dev, zbuf_t *dst, zbuf_t *src) { memcpy(dst->data, src->data, src->len); dst->tail = dst->data; @@ -87,7 +87,7 @@ u16_t zfwBufCopy(zdev_t* dev, zbuf_t* dst, zbuf_t* src) /* Called to adjust buffer size and tail pointer */ -u16_t zfwBufSetSize(zdev_t* dev, zbuf_t* buf, u16_t size) +u16_t zfwBufSetSize(zdev_t *dev, zbuf_t *buf, u16_t size) { #ifdef NET_SKBUFF_DATA_USES_OFFSET buf->tail = 0; @@ -101,11 +101,11 @@ u16_t zfwBufSetSize(zdev_t* dev, zbuf_t* buf, u16_t size) return 0; } -u16_t zfwBufGetSize(zdev_t* dev, zbuf_t* buf) +u16_t zfwBufGetSize(zdev_t *dev, zbuf_t *buf) { return buf->len; } -void zfwCopyBufContext(zdev_t* dev, zbuf_t* source, zbuf_t* dst) +void zfwCopyBufContext(zdev_t *dev, zbuf_t *source, zbuf_t *dst) { } diff --git a/drivers/staging/otus/wrap_dbg.c b/drivers/staging/otus/wrap_dbg.c index d47e9ab9179afdc2f836ba5aac19f43edc9e1d91..ee0ee153260119296995c929325001b88219d7d2 100644 --- a/drivers/staging/otus/wrap_dbg.c +++ b/drivers/staging/otus/wrap_dbg.c @@ -29,70 +29,67 @@ #include #include -void zfwDumpBuf(zdev_t* dev, zbuf_t* buf) +void zfwDumpBuf(zdev_t *dev, zbuf_t *buf) { - u16_t i; - - for (i=0; ilen; i++) - { - printk("%02x ", *(((u8_t*)buf->data)+i)); - if ((i&0xf)==0xf) - { - printk("\n"); - } - } - printk("\n"); + u16_t i; + + for (i = 0; i < buf->len; i++) { + printk(KERN_DEBUG "%02x ", *(((u8_t *)buf->data)+i)); + if ((i & 0xf) == 0xf) + printk(KERN_DEBUG "\n"); + } + printk(KERN_DEBUG "\n"); } -void zfwDbgReadRegDone(zdev_t* dev, u32_t addr, u32_t val) +void zfwDbgReadRegDone(zdev_t *dev, u32_t addr, u32_t val) { - printk("Read addr:%x = %x\n", addr, val); + printk(KERN_DEBUG "Read addr:%x = %x\n", addr, val); } -void zfwDbgWriteRegDone(zdev_t* dev, u32_t addr, u32_t val) +void zfwDbgWriteRegDone(zdev_t *dev, u32_t addr, u32_t val) { - printk("Write addr:%x = %x\n", addr, val); + printk(KERN_DEBUG "Write addr:%x = %x\n", addr, val); } -void zfwDbgReadTallyDone(zdev_t* dev) +void zfwDbgReadTallyDone(zdev_t *dev) { - //printk("Read Tall Done\n"); + /* printk(KERN_DEBUG "Read Tall Done\n"); */ } -void zfwDbgWriteEepromDone(zdev_t* dev, u32_t addr, u32_t val) +void zfwDbgWriteEepromDone(zdev_t *dev, u32_t addr, u32_t val) { } -void zfwDbgQueryHwTxBusyDone(zdev_t* dev, u32_t val) +void zfwDbgQueryHwTxBusyDone(zdev_t *dev, u32_t val) { } -//For Evl ++ -void zfwDbgReadFlashDone(zdev_t* dev, u32_t addr, u32_t* rspdata, u32_t datalen) +/* For Evl ++ */ +void zfwDbgReadFlashDone(zdev_t *dev, u32_t addr, u32_t *rspdata, u32_t datalen) { - printk("Read Flash addr:%x length:%x\n", addr, datalen); + printk(KERN_DEBUG "Read Flash addr:%x length:%x\n", addr, datalen); } -void zfwDbgProgrameFlashDone(zdev_t* dev) +void zfwDbgProgrameFlashDone(zdev_t *dev) { - printk("Program Flash Done\n"); + printk(KERN_DEBUG "Program Flash Done\n"); } -void zfwDbgProgrameFlashChkDone(zdev_t* dev) +void zfwDbgProgrameFlashChkDone(zdev_t *dev) { - printk("Program Flash Done\n"); + printk(KERN_DEBUG "Program Flash Done\n"); } -void zfwDbgGetFlashChkSumDone(zdev_t* dev, u32_t* rspdata) +void zfwDbgGetFlashChkSumDone(zdev_t *dev, u32_t *rspdata) { - printk("Get Flash ChkSum Done\n"); + printk(KERN_DEBUG "Get Flash ChkSum Done\n"); } -void zfwDbgDownloadFwInitDone(zdev_t* dev) +void zfwDbgDownloadFwInitDone(zdev_t *dev) { - printk("Download FW Init Done\n"); + printk(KERN_DEBUG "Download FW Init Done\n"); } -//For Evl -- +/* For Evl -- */ /* Leave an empty line below to remove warning message on some compiler */ diff --git a/drivers/staging/otus/wrap_ev.c b/drivers/staging/otus/wrap_ev.c index bcda0b9673dc8db5c69af57f8a60e7423ee1b425..29f560372555f04abfcb4e108f8fec8133e0ca69 100644 --- a/drivers/staging/otus/wrap_ev.c +++ b/drivers/staging/otus/wrap_ev.c @@ -32,202 +32,214 @@ /***** Management *****/ -u16_t zfLnxAuthNotify(zdev_t* dev, u16_t* macAddr) +u16_t zfLnxAuthNotify(zdev_t *dev, u16_t *macAddr) { - return 0; + return 0; } -u16_t zfLnxAsocNotify(zdev_t* dev, u16_t* macAddr, u8_t* body, u16_t bodySize, u16_t port) +u16_t zfLnxAsocNotify(zdev_t *dev, u16_t *macAddr, u8_t *body, u16_t bodySize, + u16_t port) { -//#ifdef ZM_HOSTAPD_SUPPORT - struct usbdrv_private *macp = dev->ml_priv; - union iwreq_data wreq; - u8_t *addr = (u8_t *) macAddr; - u16_t i, j; - - memset(&wreq, 0, sizeof(wreq)); - memcpy(wreq.addr.sa_data, macAddr, ETH_ALEN); - wreq.addr.sa_family = ARPHRD_ETHER; - printk(KERN_DEBUG "join_event of MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - - for(i = 0; i < ZM_OAL_MAX_STA_SUPPORT; i++) - { - for(j = 0; j < IEEE80211_ADDR_LEN; j++) - { - if ((macp->stawpaie[i].wpa_macaddr[j] != 0) && - (macp->stawpaie[i].wpa_macaddr[j] != addr[j])) - break; - } - if (j == 6) - break; - } - if (i < ZM_OAL_MAX_STA_SUPPORT) - { - //printk("zfwAsocNotify - store wpa ie in macp, index = %d\n", i); - memcpy(macp->stawpaie[i].wpa_macaddr, macAddr, IEEE80211_ADDR_LEN); - memcpy(macp->stawpaie[i].wpa_ie, body, bodySize); - } - //if(macp->cardSetting.BssType == INFRASTRUCTURE_BSS) { - // //wireless_send_event(macp->device, SIOCGIWSCAN, &wreq, NULL); - // wireless_send_event(macp->device, SIOCGIWAP, &wreq, NULL); - //} - //else if(macp->cardSetting.BssType == AP_BSS) { -// if (port == 0) -// { - wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL); -// } -// else -// { -// /* Check whether the VAP device is valid */ -// if (vap[port].dev != NULL) -// { -// wireless_send_event(vap[port].dev, IWEVREGISTERED, &wreq, NULL); -// } -// else -// { -// printk(KERN_ERR "Can' find a valid VAP device, port: %d\n", port); -// } -// } - //} -//#endif - - return 0; +/* #ifdef ZM_HOSTAPD_SUPPORT */ + struct usbdrv_private *macp = dev->ml_priv; + union iwreq_data wreq; + u8_t *addr = (u8_t *) macAddr; + u16_t i, j; + + memset(&wreq, 0, sizeof(wreq)); + memcpy(wreq.addr.sa_data, macAddr, ETH_ALEN); + wreq.addr.sa_family = ARPHRD_ETHER; + printk(KERN_DEBUG "join_event of MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + for (i = 0; i < ZM_OAL_MAX_STA_SUPPORT; i++) { + for (j = 0; j < IEEE80211_ADDR_LEN; j++) { + if ((macp->stawpaie[i].wpa_macaddr[j] != 0) && + (macp->stawpaie[i].wpa_macaddr[j] != addr[j])) + break; + } + if (j == 6) + break; + } + if (i < ZM_OAL_MAX_STA_SUPPORT) { + /* + * printk("zfwAsocNotify - store wpa ie in macp, + * index = %d\n", i); + */ + memcpy(macp->stawpaie[i].wpa_macaddr, macAddr, + IEEE80211_ADDR_LEN); + memcpy(macp->stawpaie[i].wpa_ie, body, bodySize); + } + /* + * if(macp->cardSetting.BssType == INFRASTRUCTURE_BSS) { + * wireless_send_event(macp->device, SIOCGIWSCAN, &wreq, NULL); + * wireless_send_event(macp->device, SIOCGIWAP, &wreq, NULL); + * } + * else if(macp->cardSetting.BssType == AP_BSS) { + * if (port == 0) + * { + */ + wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL); + /* + * } + * else + * { + * Check whether the VAP device is valid + * if (vap[port].dev != NULL) + * { + * wireless_send_event(vap[port].dev, + * IWEVREGISTERED, &wreq, NULL); + * } + * else + * { + * printk(KERN_ERR "Can' find a valid VAP device, + * port: %d\n", port); + * } + * } + * } + */ +/* #endif */ + + return 0; } /* Notification that a STA is disassociated from AP */ /* AP mode only */ -u16_t zfLnxDisAsocNotify(zdev_t* dev, u8_t* macAddr, u16_t port) +u16_t zfLnxDisAsocNotify(zdev_t *dev, u8_t *macAddr, u16_t port) { - union iwreq_data wreq; - u8_t *addr = (u8_t *) macAddr; + union iwreq_data wreq; + u8_t *addr = (u8_t *) macAddr; - memset(&wreq, 0, sizeof(wreq)); - memcpy(wreq.addr.sa_data, macAddr, ETH_ALEN); - wreq.addr.sa_family = ARPHRD_ETHER; - printk(KERN_DEBUG "zfwDisAsocNotify(), MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + memset(&wreq, 0, sizeof(wreq)); + memcpy(wreq.addr.sa_data, macAddr, ETH_ALEN); + wreq.addr.sa_family = ARPHRD_ETHER; + printk(KERN_DEBUG "zfwDisAsocNotify(), MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - return 0; + return 0; } /* Notification that a STA is connect to AP */ /* AP mode only */ -u16_t zfLnxApConnectNotify(zdev_t* dev, u8_t* macAddr, u16_t port) +u16_t zfLnxApConnectNotify(zdev_t *dev, u8_t *macAddr, u16_t port) { - union iwreq_data wreq; - u8_t *addr = (u8_t *) macAddr; + union iwreq_data wreq; + u8_t *addr = (u8_t *) macAddr; - memset(&wreq, 0, sizeof(wreq)); - memcpy(wreq.addr.sa_data, macAddr, ETH_ALEN); - wreq.addr.sa_family = ARPHRD_ETHER; - printk(KERN_DEBUG "zfwApConnectNotify(), MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + memset(&wreq, 0, sizeof(wreq)); + memcpy(wreq.addr.sa_data, macAddr, ETH_ALEN); + wreq.addr.sa_family = ARPHRD_ETHER; + printk(KERN_DEBUG "zfwApConnectNotify(), MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - return 0; + return 0; } -void zfLnxConnectNotify(zdev_t* dev, u16_t status, u16_t* bssid) +void zfLnxConnectNotify(zdev_t *dev, u16_t status, u16_t *bssid) { - union iwreq_data wreq; - u8_t *addr = (u8_t *) bssid; - struct usbdrv_private *macp = dev->ml_priv; - - if (bssid != NULL) - { - memset(&wreq, 0, sizeof(wreq)); - if (status == ZM_STATUS_MEDIA_CONNECT) - memcpy(wreq.addr.sa_data, bssid, ETH_ALEN); - wreq.addr.sa_family = ARPHRD_ETHER; - - if (status == ZM_STATUS_MEDIA_CONNECT) - { + union iwreq_data wreq; + u8_t *addr = (u8_t *) bssid; + struct usbdrv_private *macp = dev->ml_priv; + + if (bssid != NULL) { + memset(&wreq, 0, sizeof(wreq)); + if (status == ZM_STATUS_MEDIA_CONNECT) + memcpy(wreq.addr.sa_data, bssid, ETH_ALEN); + wreq.addr.sa_family = ARPHRD_ETHER; + + if (status == ZM_STATUS_MEDIA_CONNECT) { #ifdef ZM_CONFIG_BIG_ENDIAN - printk(KERN_DEBUG "Connected to AP, MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", - addr[1], addr[0], addr[3], addr[2], addr[5], addr[4]); + printk(KERN_DEBUG "Connected to AP, MAC:" + "%02x:%02x:%02x:%02x:%02x:%02x\n", + addr[1], addr[0], addr[3], addr[2], + addr[5], addr[4]); #else - printk(KERN_DEBUG "Connected to AP, MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + printk(KERN_DEBUG "Connected to AP, MAC:" + "%02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], + addr[4], addr[5]); #endif - netif_start_queue(dev); - } - else if ((status == ZM_STATUS_MEDIA_DISCONNECT) || - (status == ZM_STATUS_MEDIA_DISABLED) || - (status == ZM_STATUS_MEDIA_CONNECTION_DISABLED) || - (status == ZM_STATUS_MEDIA_CONNECTION_RESET) || - (status == ZM_STATUS_MEDIA_RESET) || - (status == ZM_STATUS_MEDIA_DISCONNECT_DEAUTH) || - (status == ZM_STATUS_MEDIA_DISCONNECT_DISASOC) || - (status == ZM_STATUS_MEDIA_DISCONNECT_BEACON_MISS) || - (status == ZM_STATUS_MEDIA_DISCONNECT_NOT_FOUND) || - (status == ZM_STATUS_MEDIA_DISCONNECT_TIMEOUT)) - { - printk(KERN_DEBUG "Disconnection Notify\n"); - - netif_stop_queue(dev); - } + netif_start_queue(dev); + } else if ((status == ZM_STATUS_MEDIA_DISCONNECT) || + (status == ZM_STATUS_MEDIA_DISABLED) || + (status == ZM_STATUS_MEDIA_CONNECTION_DISABLED) || + (status == ZM_STATUS_MEDIA_CONNECTION_RESET) || + (status == ZM_STATUS_MEDIA_RESET) || + (status == ZM_STATUS_MEDIA_DISCONNECT_DEAUTH) || + (status == ZM_STATUS_MEDIA_DISCONNECT_DISASOC) || + (status == ZM_STATUS_MEDIA_DISCONNECT_BEACON_MISS) || + (status == ZM_STATUS_MEDIA_DISCONNECT_NOT_FOUND) || + (status == ZM_STATUS_MEDIA_DISCONNECT_TIMEOUT)) { + printk(KERN_DEBUG "Disconnection Notify\n"); + + netif_stop_queue(dev); + } /* Save the connected status */ macp->adapterState = status; - if(zfiWlanQueryWlanMode(dev) == ZM_MODE_INFRASTRUCTURE) { - // //wireless_send_event(dev, SIOCGIWSCAN, &wreq, NULL); - wireless_send_event(dev, SIOCGIWAP, &wreq, NULL); - } - else if(zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) { - //if (port == 0) - //{ - wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL); - //} - //else - //{ - // /* Check whether the VAP device is valid */ - // if (vap[port].dev != NULL) - // { - // wireless_send_event(vap[port].dev, IWEVREGISTERED, &wreq, NULL); - // } - // else - // { - // printk(KERN_ERR "Can' find a valid VAP device, port: %d\n", port); - // } - //} - } - } - //return 0; + if (zfiWlanQueryWlanMode(dev) == ZM_MODE_INFRASTRUCTURE) { + /*wireless_send_event(dev, SIOCGIWSCAN, &wreq, NULL);*/ + wireless_send_event(dev, SIOCGIWAP, &wreq, NULL); + } else if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) { + /* + * if (port == 0) + * { + * wireless_send_event(dev, IWEVREGISTERED, + * &wreq, NULL); + * } + * else + * { + * Check whether the VAP device is valid + * if (vap[port].dev != NULL) + * { + * wireless_send_event(vap[port].dev, + * IWEVREGISTERED, &wreq, NULL); + * } + * else + * { + * printk(KERN_ERR "Can' find a valid VAP" + * " device, port: %d\n", port); + * } + * } + */ + } + } + /* return 0; */ } -void zfLnxScanNotify(zdev_t* dev, struct zsScanResult* result) +void zfLnxScanNotify(zdev_t *dev, struct zsScanResult *result) { - return; + return; } -void zfLnxStatisticsNotify(zdev_t* dev, struct zsStastics* result) +void zfLnxStatisticsNotify(zdev_t *dev, struct zsStastics *result) { - return; + return; } -//void zfwMicFailureNotify(zdev_t* dev, u8_t* message, u16_t event) -void zfLnxMicFailureNotify(zdev_t* dev, u16_t* addr, u16_t status) +/* void zfwMicFailureNotify(zdev_t *dev, u8_t *message, u16_t event) */ +void zfLnxMicFailureNotify(zdev_t *dev, u16_t *addr, u16_t status) { static const char *tag = "MLME-MICHAELMICFAILURE.indication"; union iwreq_data wrqu; char buf[128]; /* TODO: needed parameters: count, type, src address */ - //snprintf(buf, sizeof(buf), "%s(%scast addr=%s)", tag, - // (status == ZM_MIC_GROUP_ERROR) ? "broad" : "uni", - // ether_sprintf((u8_t *)addr)); + /* + * snprintf(buf, sizeof(buf), "%s(%scast addr=%s)", tag, + * (status == ZM_MIC_GROUP_ERROR) ? "broad" : "uni", + * ether_sprintf((u8_t *)addr)); + */ if (zfiWlanQueryWlanMode(dev) == ZM_MODE_INFRASTRUCTURE) - { strcpy(buf, tag); - } memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = strlen(buf); @@ -235,42 +247,46 @@ void zfLnxMicFailureNotify(zdev_t* dev, u16_t* addr, u16_t status) } -void zfLnxApMicFailureNotify(zdev_t* dev, u8_t* addr, zbuf_t* buf) +void zfLnxApMicFailureNotify(zdev_t *dev, u8_t *addr, zbuf_t *buf) { - union iwreq_data wreq; + union iwreq_data wreq; - memset(&wreq, 0, sizeof(wreq)); - memcpy(wreq.addr.sa_data, addr, ETH_ALEN); - wreq.addr.sa_family = ARPHRD_ETHER; - printk(KERN_DEBUG "zfwApMicFailureNotify(), MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + memset(&wreq, 0, sizeof(wreq)); + memcpy(wreq.addr.sa_data, addr, ETH_ALEN); + wreq.addr.sa_family = ARPHRD_ETHER; + printk(KERN_DEBUG "zfwApMicFailureNotify(), " + "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - return; + return; } - -// status = 0 => partner lost -// = 1 => partner alive -//void zfwIbssPartnerNotify(zdev_t* dev, u8_t status) -void zfLnxIbssPartnerNotify(zdev_t* dev, u16_t status, struct zsPartnerNotifyEvent *event) +/* + * status = 0 => partner lost + * = 1 => partner alive + * void zfwIbssPartnerNotify(zdev_t* dev, u8_t status) + */ +void zfLnxIbssPartnerNotify(zdev_t *dev, u16_t status, + struct zsPartnerNotifyEvent *event) { } -void zfLnxMacAddressNotify(zdev_t* dev, u8_t* addr) +void zfLnxMacAddressNotify(zdev_t *dev, u8_t *addr) { - dev->dev_addr[0] = addr[0]; - dev->dev_addr[1] = addr[1]; - dev->dev_addr[2] = addr[2]; - dev->dev_addr[3] = addr[3]; - dev->dev_addr[4] = addr[4]; - dev->dev_addr[5] = addr[5]; + dev->dev_addr[0] = addr[0]; + dev->dev_addr[1] = addr[1]; + dev->dev_addr[2] = addr[2]; + dev->dev_addr[3] = addr[3]; + dev->dev_addr[4] = addr[4]; + dev->dev_addr[5] = addr[5]; } -void zfLnxSendCompleteIndication(zdev_t* dev, zbuf_t* buf) +void zfLnxSendCompleteIndication(zdev_t *dev, zbuf_t *buf) { } -void zfLnxRestoreBufData(zdev_t* dev, zbuf_t* buf) { +void zfLnxRestoreBufData(zdev_t *dev, zbuf_t *buf) +{ } /* Leave an empty line below to remove warning message on some compiler */ diff --git a/drivers/staging/otus/wrap_mem.c b/drivers/staging/otus/wrap_mem.c index 32416d77a471a5b92ece53f96f51b12d197d1b7b..47cbce1346a9384ea820ccf58d53dac061cbf342 100644 --- a/drivers/staging/otus/wrap_mem.c +++ b/drivers/staging/otus/wrap_mem.c @@ -30,69 +30,75 @@ #include /* Memory management */ -/* Called to allocate uncached memory, allocated memory must */ -/* in 4-byte boundary */ -void* zfwMemAllocate(zdev_t* dev, u32_t size) +/* Called to allocate uncached memory, allocated memory must */ +/* in 4-byte boundary */ +void *zfwMemAllocate(zdev_t *dev, u32_t size) { - void* mem = NULL; - mem = kmalloc(size, GFP_ATOMIC); - return mem; + void *mem = NULL; + mem = kmalloc(size, GFP_ATOMIC); + return mem; } /* Called to free allocated memory */ -void zfwMemFree(zdev_t* dev, void* mem, u32_t size) +void zfwMemFree(zdev_t *dev, void *mem, u32_t size) { - kfree(mem); - return; + kfree(mem); + return; } -void zfwMemoryCopy(u8_t* dst, u8_t* src, u16_t length) +void zfwMemoryCopy(u8_t *dst, u8_t *src, u16_t length) { - //u16_t i; + /* u16_t i; */ - memcpy(dst, src, length); - //for(i=0; i #include -//extern struct zsWdsStruct wds[ZM_WDS_PORT_NUMBER]; +/* extern struct zsWdsStruct wds[ZM_WDS_PORT_NUMBER]; */ extern struct zsVapStruct vap[ZM_VAP_PORT_NUMBER]; -extern u16_t zfLnxGetVapId(zdev_t* dev); +extern u16_t zfLnxGetVapId(zdev_t *dev); /* Simply return 0xffff if VAP function is not supported */ -u16_t zfwGetVapId(zdev_t* dev) +u16_t zfwGetVapId(zdev_t *dev) { - return zfLnxGetVapId(dev); + return zfLnxGetVapId(dev); } -void zfwSleep(zdev_t* dev, u32_t ms) +void zfwSleep(zdev_t *dev, u32_t ms) { - if (in_interrupt() == 0) - { - mdelay(ms); - } - else - { - int ii; - int iter = 100000 * ms; - - for (ii = 0; ii < iter; ii++) - { - - } - } + if (in_interrupt() == 0) + mdelay(ms); + else { + int ii; + int iter = 100000 * ms; + + for (ii = 0; ii < iter; ii++) { + } + } } #ifdef ZM_HALPLUS_LOCK -asmlinkage struct zsWlanDev *zfwGetWlanDev(zdev_t* dev) +asmlinkage struct zsWlanDev *zfwGetWlanDev(zdev_t *dev) { struct usbdrv_private *macp = dev->ml_priv; return macp->wd; } -asmlinkage void zfwEnterCriticalSection(zdev_t* dev) +asmlinkage void zfwEnterCriticalSection(zdev_t *dev) { struct usbdrv_private *macp = dev->ml_priv; spin_lock_irqsave(&macp->cs_lock, macp->hal_irqFlag); } -asmlinkage void zfwLeaveCriticalSection(zdev_t* dev) +asmlinkage void zfwLeaveCriticalSection(zdev_t *dev) { struct usbdrv_private *macp = dev->ml_priv; spin_unlock_irqrestore(&macp->cs_lock, macp->hal_irqFlag); } -asmlinkage u8_t zfwBufReadByte(zdev_t* dev, zbuf_t* buf, u16_t offset) +asmlinkage u8_t zfwBufReadByte(zdev_t *dev, zbuf_t *buf, u16_t offset) { - return *(u8_t*)((u8_t*)buf->data+offset); + return *(u8_t *)((u8_t *)buf->data+offset); } -asmlinkage u16_t zfwBufReadHalfWord(zdev_t* dev, zbuf_t* buf, u16_t offset) +asmlinkage u16_t zfwBufReadHalfWord(zdev_t *dev, zbuf_t *buf, u16_t offset) { - return zmw_cpu_to_le16(*(u16_t*)((u8_t*)buf->data+offset)); + return zmw_cpu_to_le16(*(u16_t *)((u8_t *)buf->data+offset)); } -asmlinkage void zfwBufWriteByte(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t value) +asmlinkage void zfwBufWriteByte(zdev_t *dev, zbuf_t *buf, u16_t offset, + u8_t value) { - *(u8_t*)((u8_t*)buf->data+offset) = value; + *(u8_t *)((u8_t *)buf->data+offset) = value; } -asmlinkage void zfwBufWriteHalfWord(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t value) +asmlinkage void zfwBufWriteHalfWord(zdev_t *dev, zbuf_t *buf, u16_t offset, + u16_t value) { - *(u16_t*)((u8_t*)buf->data+offset) = zmw_cpu_to_le16(value); + *(u16_t *)((u8_t *)buf->data+offset) = zmw_cpu_to_le16(value); } -asmlinkage u8_t *zfwGetBuffer(zdev_t* dev, zbuf_t* buf) +asmlinkage u8_t *zfwGetBuffer(zdev_t *dev, zbuf_t *buf) { - return (u8_t*)(buf->data); + return (u8_t *)(buf->data); } #endif diff --git a/drivers/staging/otus/wrap_pkt.c b/drivers/staging/otus/wrap_pkt.c index 0d5920fdf4f3cf595d1c6434bf2171f685212439..75bb952fd0a50789ae26f7b8db26d26c7e64ac65 100644 --- a/drivers/staging/otus/wrap_pkt.c +++ b/drivers/staging/otus/wrap_pkt.c @@ -31,136 +31,122 @@ #include -//extern struct zsWdsStruct wds[ZM_WDS_PORT_NUMBER]; +/* extern struct zsWdsStruct wds[ZM_WDS_PORT_NUMBER]; */ extern struct zsVapStruct vap[ZM_VAP_PORT_NUMBER]; /***** Rx *****/ -void zfLnxRecv80211(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo) +void zfLnxRecv80211(zdev_t *dev, zbuf_t *buf, struct zsAdditionInfo *addInfo) { - u16_t frameType; - u16_t frameCtrl; - u16_t frameSubtype; - zbuf_t *skb1; - struct usbdrv_private *macp = dev->ml_priv; - - //frameCtrl = zmw_buf_readb(dev, buf, 0); - frameCtrl = *(u8_t*)((u8_t*)buf->data); - frameType = frameCtrl & 0xf; - frameSubtype = frameCtrl & 0xf0; - - if ((frameType == 0x0) && (macp->forwardMgmt)) - { - switch (frameSubtype) - { - /* Beacon */ - case 0x80 : - /* Probe response */ - case 0x50 : - skb1 = skb_copy(buf, GFP_ATOMIC); - if(skb1 != NULL) - { - skb1->dev = dev; - skb1->mac_header = skb1->data; - skb1->ip_summed = CHECKSUM_NONE; - skb1->pkt_type = PACKET_OTHERHOST; - skb1->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */ - netif_rx(skb1); - } - break; - default: - break; - } - } - - zfiRecv80211(dev, buf, addInfo); - return; + u16_t frameType; + u16_t frameCtrl; + u16_t frameSubtype; + zbuf_t *skb1; + struct usbdrv_private *macp = dev->ml_priv; + + /* frameCtrl = zmw_buf_readb(dev, buf, 0); */ + frameCtrl = *(u8_t *)((u8_t *)buf->data); + frameType = frameCtrl & 0xf; + frameSubtype = frameCtrl & 0xf0; + + if ((frameType == 0x0) && (macp->forwardMgmt)) { + switch (frameSubtype) { + /* Beacon */ + case 0x80: + /* Probe response */ + case 0x50: + skb1 = skb_copy(buf, GFP_ATOMIC); + if (skb1 != NULL) { + skb1->dev = dev; + skb1->mac_header = skb1->data; + skb1->ip_summed = CHECKSUM_NONE; + skb1->pkt_type = PACKET_OTHERHOST; + /* ETH_P_80211_RAW */ + skb1->protocol = __constant_htons(0x0019); + netif_rx(skb1); + } + break; + default: + break; + } + } + + zfiRecv80211(dev, buf, addInfo); + return; } #define ZM_AVOID_UDP_LARGE_PACKET_FAIL -void zfLnxRecvEth(zdev_t* dev, zbuf_t* buf, u16_t port) +void zfLnxRecvEth(zdev_t *dev, zbuf_t *buf, u16_t port) { - struct usbdrv_private *macp = dev->ml_priv; + struct usbdrv_private *macp = dev->ml_priv; #ifdef ZM_AVOID_UDP_LARGE_PACKET_FAIL - zbuf_t *new_buf; + zbuf_t *new_buf; - //new_buf = dev_alloc_skb(2048); - new_buf = dev_alloc_skb(buf->len); + /* new_buf = dev_alloc_skb(2048); */ + new_buf = dev_alloc_skb(buf->len); #ifdef NET_SKBUFF_DATA_USES_OFFSET - new_buf->tail = 0; - new_buf->len = 0; + new_buf->tail = 0; + new_buf->len = 0; #else - new_buf->tail = new_buf->data; - new_buf->len = 0; + new_buf->tail = new_buf->data; + new_buf->len = 0; #endif - skb_put(new_buf, buf->len); - memcpy(new_buf->data, buf->data, buf->len); - - /* Free buffer */ - dev_kfree_skb_any(buf); - - if (port == 0) - { - new_buf->dev = dev; - new_buf->protocol = eth_type_trans(new_buf, dev); - } - else - { - /* VAP */ - if (vap[0].dev != NULL) - { - new_buf->dev = vap[0].dev; - new_buf->protocol = eth_type_trans(new_buf, vap[0].dev); - } - else - { - new_buf->dev = dev; - new_buf->protocol = eth_type_trans(new_buf, dev); - } - } - - new_buf->ip_summed = CHECKSUM_NONE; - dev->last_rx = jiffies; - - switch(netif_rx(new_buf)) + skb_put(new_buf, buf->len); + memcpy(new_buf->data, buf->data, buf->len); + + /* Free buffer */ + dev_kfree_skb_any(buf); + + if (port == 0) { + new_buf->dev = dev; + new_buf->protocol = eth_type_trans(new_buf, dev); + } else { + /* VAP */ + if (vap[0].dev != NULL) { + new_buf->dev = vap[0].dev; + new_buf->protocol = eth_type_trans(new_buf, vap[0].dev); + } else { + new_buf->dev = dev; + new_buf->protocol = eth_type_trans(new_buf, dev); + } + } + + new_buf->ip_summed = CHECKSUM_NONE; + dev->last_rx = jiffies; + + switch (netif_rx(new_buf)) #else - if (port == 0) - { - buf->dev = dev; - buf->protocol = eth_type_trans(buf, dev); - } - else - { - /* VAP */ - if (vap[0].dev != NULL) - { - buf->dev = vap[0].dev; - buf->protocol = eth_type_trans(buf, vap[0].dev); - } - else - { - buf->dev = dev; - buf->protocol = eth_type_trans(buf, dev); - } - } - - buf->ip_summed = CHECKSUM_NONE; - dev->last_rx = jiffies; - - switch(netif_rx(buf)) + if (port == 0) { + buf->dev = dev; + buf->protocol = eth_type_trans(buf, dev); + } else { + /* VAP */ + if (vap[0].dev != NULL) { + buf->dev = vap[0].dev; + buf->protocol = eth_type_trans(buf, vap[0].dev); + } else { + buf->dev = dev; + buf->protocol = eth_type_trans(buf, dev); + } + } + + buf->ip_summed = CHECKSUM_NONE; + dev->last_rx = jiffies; + + switch (netif_rx(buf)) #endif - { - case NET_RX_DROP: - break; - default: - macp->drv_stats.net_stats.rx_packets++; - macp->drv_stats.net_stats.rx_bytes += buf->len; - break; - } - - return; + { + case NET_RX_DROP: + break; + default: + macp->drv_stats.net_stats.rx_packets++; + macp->drv_stats.net_stats.rx_bytes += buf->len; + break; + } + + return; } /* Leave an empty line below to remove warning message on some compiler */ diff --git a/drivers/staging/otus/wrap_sec.c b/drivers/staging/otus/wrap_sec.c index 0f780bacc598fbf5dd10a6b8c989ed4bb3b9eb4b..0b238e9999bf0d097ff12a85fe17fc05437ebac5 100644 --- a/drivers/staging/otus/wrap_sec.c +++ b/drivers/staging/otus/wrap_sec.c @@ -33,92 +33,93 @@ #ifdef ZM_ENABLE_CENC extern int zfLnxCencSendMsg(struct sock *netlink_sk, u_int8_t *msg, int len); -u16_t zfLnxCencAsocNotify(zdev_t* dev, u16_t* macAddr, u8_t* body, u16_t bodySize, u16_t port) +u16_t zfLnxCencAsocNotify(zdev_t *dev, u16_t *macAddr, u8_t *body, + u16_t bodySize, u16_t port) { - struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; - struct zydas_cenc_sta_info cenc_info; - //struct sock *netlink_sk; - u8_t ie_len; - int ii; + struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; + struct zydas_cenc_sta_info cenc_info; + /* struct sock *netlink_sk; */ + u8_t ie_len; + int ii; - /* Create NETLINK socket */ - //netlink_sk = netlink_kernel_create(NETLINK_USERSOCK, NULL); + /* Create NETLINK socket */ + /*netlink_sk = netlink_kernel_create(NETLINK_USERSOCK, NULL); */ - if (macp->netlink_sk == NULL) - { - printk(KERN_ERR "NETLINK Socket is NULL\n"); - return -1; - } + if (macp->netlink_sk == NULL) { + printk(KERN_ERR "NETLINK Socket is NULL\n"); + return -1; + } - memset(&cenc_info, 0, sizeof(cenc_info)); + memset(&cenc_info, 0, sizeof(cenc_info)); - //memcpy(cenc_info.gsn, vap->iv_cencmsk_keys.wk_txiv, ZM_CENC_IV_LEN); - zfiWlanQueryGSN(dev, cenc_info.gsn, port); - cenc_info.datalen += ZM_CENC_IV_LEN; - ie_len = body[1] + 2; - memcpy(cenc_info.wie, body, ie_len); - cenc_info.datalen += ie_len; + /* memcpy(cenc_info.gsn, vap->iv_cencmsk_keys.wk_txiv, + * ZM_CENC_IV_LEN); + */ + zfiWlanQueryGSN(dev, cenc_info.gsn, port); + cenc_info.datalen += ZM_CENC_IV_LEN; + ie_len = body[1] + 2; + memcpy(cenc_info.wie, body, ie_len); + cenc_info.datalen += ie_len; - memcpy(cenc_info.sta_mac, macAddr, 6); - cenc_info.msg_type = ZM_CENC_WAI_REQUEST; - cenc_info.datalen += 6 + 2; + memcpy(cenc_info.sta_mac, macAddr, 6); + cenc_info.msg_type = ZM_CENC_WAI_REQUEST; + cenc_info.datalen += 6 + 2; - printk(KERN_ERR "===== zfwCencSendMsg, bodySize: %d =====\n", bodySize); + printk(KERN_ERR "===== zfwCencSendMsg, bodySize: %d =====\n", bodySize); - for(ii = 0; ii < bodySize; ii++) - { - printk(KERN_ERR "%02x ", body[ii]); + for (ii = 0; ii < bodySize; ii++) { + printk(KERN_ERR "%02x ", body[ii]); - if ((ii & 0xf) == 0xf) - { - printk(KERN_ERR "\n"); - } - } + if ((ii & 0xf) == 0xf) + printk(KERN_ERR "\n"); + } - zfLnxCencSendMsg(macp->netlink_sk, (u8_t *)&cenc_info, cenc_info.datalen+4); + zfLnxCencSendMsg(macp->netlink_sk, (u8_t *)&cenc_info, + cenc_info.datalen+4); - /* Close NETLINK socket */ - //sock_release(netlink_sk); + /* Close NETLINK socket */ + /* sock_release(netlink_sk); */ - return 0; + return 0; } -#endif //ZM_ENABLE_CENC +#endif /* ZM_ENABLE_CENC */ -u8_t zfwCencHandleBeaconProbrespon(zdev_t* dev, u8_t *pWIEc, - u8_t *pPeerSSIDc, u8_t *pPeerAddrc) +u8_t zfwCencHandleBeaconProbrespon(zdev_t *dev, u8_t *pWIEc, + u8_t *pPeerSSIDc, u8_t *pPeerAddrc) { - return 0; + return 0; } -u8_t zfwGetPktEncExemptionActionType(zdev_t* dev, zbuf_t* buf) +u8_t zfwGetPktEncExemptionActionType(zdev_t *dev, zbuf_t *buf) { - return ZM_ENCRYPTION_EXEMPT_NO_EXEMPTION; + return ZM_ENCRYPTION_EXEMPT_NO_EXEMPTION; } -void copyToIntTxBuffer(zdev_t* dev, zbuf_t* buf, u8_t* src, - u16_t offset, u16_t length) +void copyToIntTxBuffer(zdev_t *dev, zbuf_t *buf, u8_t *src, + u16_t offset, u16_t length) { - u16_t i; + u16_t i; - for(i=0; idata+offset+i) = src[i]; - } + for (i = 0; i < length; i++) { + /* zmw_tx_buf_writeb(dev, buf, offset+i, src[i]); */ + *(u8_t *)((u8_t *)buf->data+offset+i) = src[i]; + } } -u16_t zfwStaAddIeWpaRsn(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t frameType) +u16_t zfwStaAddIeWpaRsn(zdev_t *dev, zbuf_t *buf, u16_t offset, u8_t frameType) { - struct usbdrv_private *macp = dev->ml_priv; - //zm_msg1_mm(ZM_LV_0, "CWY - add wpaie content Length : ", macp->supIe[1]); - if (macp->supIe[1] != 0) - { - copyToIntTxBuffer(dev, buf, macp->supIe, offset, macp->supIe[1]+2); - //memcpy(buf->data[offset], macp->supIe, macp->supIe[1]+2); - offset += (macp->supIe[1]+2); - } - - return offset; + struct usbdrv_private *macp = dev->ml_priv; + /* zm_msg1_mm(ZM_LV_0, "CWY - add wpaie content Length : " + * , macp->supIe[1]); + */ + if (macp->supIe[1] != 0) { + copyToIntTxBuffer(dev, buf, macp->supIe, offset, + macp->supIe[1]+2); + /* memcpy(buf->data[offset], macp->supIe, macp->supIe[1]+2);*/ + offset += (macp->supIe[1]+2); + } + + return offset; } /* Leave an empty line below to remove warning message on some compiler */ diff --git a/drivers/staging/otus/wrap_usb.c b/drivers/staging/otus/wrap_usb.c index 70fd410bc894c8b80da92a16fd9128b34cef29d0..6b336ede8867eaf989986eb869cb5b83de8ed19b 100644 --- a/drivers/staging/otus/wrap_usb.c +++ b/drivers/staging/otus/wrap_usb.c @@ -30,159 +30,152 @@ #include #include -extern void zfLnxInitUsbTxQ(zdev_t* dev); -extern void zfLnxInitUsbRxQ(zdev_t* dev); +extern void zfLnxInitUsbTxQ(zdev_t *dev); +extern void zfLnxInitUsbRxQ(zdev_t *dev); extern u32_t zfLnxSubmitRegInUrb(zdev_t *dev); -u32_t zfLnxUsbOut(zdev_t* dev, u8_t *hdr, u16_t hdrlen, u8_t *snap, u16_t snapLen, - u8_t *tail, u16_t tailLen, zbuf_t *buf, u16_t offset); -u32_t zfLnxUsbWriteReg(zdev_t* dev, u32_t* cmd, u16_t cmdLen); +u32_t zfLnxUsbOut(zdev_t *dev, u8_t *hdr, u16_t hdrlen, u8_t *snap, + u16_t snapLen, u8_t *tail, u16_t tailLen, zbuf_t *buf, + u16_t offset); +u32_t zfLnxUsbWriteReg(zdev_t *dev, u32_t *cmd, u16_t cmdLen); -void zfwUsbRegisterCallBack(zdev_t* dev, struct zfCbUsbFuncTbl *zfUsbFunc) { - struct usbdrv_private *macp = dev->ml_priv; +void zfwUsbRegisterCallBack(zdev_t *dev, struct zfCbUsbFuncTbl *zfUsbFunc) +{ + struct usbdrv_private *macp = dev->ml_priv; - macp->usbCbFunctions.zfcbUsbRecv = zfUsbFunc->zfcbUsbRecv; - macp->usbCbFunctions.zfcbUsbRegIn = zfUsbFunc->zfcbUsbRegIn; - macp->usbCbFunctions.zfcbUsbOutComplete = zfUsbFunc->zfcbUsbOutComplete; + macp->usbCbFunctions.zfcbUsbRecv = zfUsbFunc->zfcbUsbRecv; + macp->usbCbFunctions.zfcbUsbRegIn = zfUsbFunc->zfcbUsbRegIn; + macp->usbCbFunctions.zfcbUsbOutComplete = zfUsbFunc->zfcbUsbOutComplete; - return; + return; } -u32_t zfwUsbGetFreeTxQSize(zdev_t* dev) +u32_t zfwUsbGetFreeTxQSize(zdev_t *dev) { - struct usbdrv_private *macp = dev->ml_priv; - u32_t freeTxQSize; - unsigned long irqFlag; - //zmw_declare_for_critical_section(); + struct usbdrv_private *macp = dev->ml_priv; + u32_t freeTxQSize; + unsigned long irqFlag; + /* zmw_declare_for_critical_section(); */ - //zmw_enter_critical_section(dev); - spin_lock_irqsave(&macp->cs_lock, irqFlag); + /* zmw_enter_critical_section(dev); */ + spin_lock_irqsave(&macp->cs_lock, irqFlag); - freeTxQSize = ZM_MAX_TX_BUF_NUM - macp->TxBufCnt; + freeTxQSize = ZM_MAX_TX_BUF_NUM - macp->TxBufCnt; - //zmw_leave_critical_section(dev); - spin_unlock_irqrestore(&macp->cs_lock, irqFlag); + /* zmw_leave_critical_section(dev); */ + spin_unlock_irqrestore(&macp->cs_lock, irqFlag); - return freeTxQSize; + return freeTxQSize; } -u32_t zfwUsbGetMaxTxQSize(zdev_t* dev) +u32_t zfwUsbGetMaxTxQSize(zdev_t *dev) { - return ZM_MAX_TX_BUF_NUM; + return ZM_MAX_TX_BUF_NUM; } u32_t zfwUsbEnableIntEpt(zdev_t *dev, u8_t endpt) { - /* Initialize USB TxQ */ - zfLnxInitUsbTxQ(dev); + /* Initialize USB TxQ */ + zfLnxInitUsbTxQ(dev); - /* Initialize USB RxQ */ - zfLnxInitUsbRxQ(dev); + /* Initialize USB RxQ */ + zfLnxInitUsbRxQ(dev); - /* Initialize USB Register In URB */ - //zfwUsbSubmitRegIn(dev); - /* Initialize USB Register In URB */ - zfLnxSubmitRegInUrb(dev); + /* Initialize USB Register In URB */ + /* zfwUsbSubmitRegIn(dev); */ + /* Initialize USB Register In URB */ + zfLnxSubmitRegInUrb(dev); - return 0; + return 0; } -int zfwUsbEnableRxEpt(zdev_t* dev, u8_t endpt) +int zfwUsbEnableRxEpt(zdev_t *dev, u8_t endpt) { - return 0; + return 0; } -u32_t zfwUsbSubmitControl(zdev_t* dev, u8_t req, u16_t value, u16_t index, void *data, u32_t size) +u32_t zfwUsbSubmitControl(zdev_t *dev, u8_t req, u16_t value, u16_t index, + void *data, u32_t size) { - int result = 0; - u32_t ret = 0; - struct usbdrv_private *macp = dev->ml_priv; - u8_t* buf; - - if (size > 0) - { - buf = kmalloc(size, GFP_KERNEL); - memcpy(buf, (u8_t*)data, size); - } - else - { - buf = NULL; - } + int result = 0; + u32_t ret = 0; + struct usbdrv_private *macp = dev->ml_priv; + u8_t *buf; + + if (size > 0) { + buf = kmalloc(size, GFP_KERNEL); + memcpy(buf, (u8_t *)data, size); + } else + buf = NULL; #if 0 - printk(KERN_ERR "req = 0x%02x\n", req); - printk(KERN_ERR "value = 0x%04x\n", value); - printk(KERN_ERR "index = 0x%04x\n", index); - printk(KERN_ERR "data = 0x%lx\n", (u32_t) data); - printk(KERN_ERR "size = %ld\n", size); + printk(KERN_ERR "req = 0x%02x\n", req); + printk(KERN_ERR "value = 0x%04x\n", value); + printk(KERN_ERR "index = 0x%04x\n", index); + printk(KERN_ERR "data = 0x%lx\n", (u32_t) data); + printk(KERN_ERR "size = %ld\n", size); #endif - result = usb_control_msg(macp->udev, usb_sndctrlpipe(macp->udev, 0), - req, USB_DIR_OUT | 0x40, value, index, buf, size, HZ); + result = usb_control_msg(macp->udev, usb_sndctrlpipe(macp->udev, 0), + req, USB_DIR_OUT | 0x40, value, index, buf, size, HZ); - if (result < 0) - { - printk("zfwUsbSubmitControl() failed, result=0x%x\n", result); - ret = 1; - } - kfree(buf); + if (result < 0) { + printk(KERN_ERR "zfwUsbSubmitControl() failed, result = 0x%x\n", + result); + ret = 1; + } + kfree(buf); - return ret; + return ret; } -void zfwUsbCmd(zdev_t* dev, u8_t endpt, u32_t* cmd, u16_t cmdLen) +void zfwUsbCmd(zdev_t *dev, u8_t endpt, u32_t *cmd, u16_t cmdLen) { - struct usbdrv_private *macp = dev->ml_priv; - u32_t ret; - - //MPUsbCommand(dev, endpt, cmd, cmdLen); - ret = zfLnxUsbWriteReg(dev, cmd, cmdLen); - - /* if zfLnxUsbWriteReg() return error, free and allocate urb, resend again */ - if (ret != 0) - { - usb_free_urb(macp->RegOutUrb); - macp->RegOutUrb = usb_alloc_urb(0, GFP_ATOMIC); - ret = zfLnxUsbWriteReg(dev, cmd, cmdLen); - } + struct usbdrv_private *macp = dev->ml_priv; + u32_t ret; + + /* MPUsbCommand(dev, endpt, cmd, cmdLen); */ + ret = zfLnxUsbWriteReg(dev, cmd, cmdLen); + + /* + * if zfLnxUsbWriteReg() return error, free and allocate urb, + * resend again + */ + if (ret != 0) { + usb_free_urb(macp->RegOutUrb); + macp->RegOutUrb = usb_alloc_urb(0, GFP_ATOMIC); + ret = zfLnxUsbWriteReg(dev, cmd, cmdLen); + } } -u32_t zfwUsbSend(zdev_t* dev, u8_t endpt, u8_t *hdr, u16_t hdrlen, u8_t *snap, u16_t snapLen, - u8_t *tail, u16_t tailLen, zbuf_t *buf, u16_t offset) +u32_t zfwUsbSend(zdev_t *dev, u8_t endpt, u8_t *hdr, u16_t hdrlen, u8_t *snap, + u16_t snapLen, u8_t *tail, u16_t tailLen, + zbuf_t *buf, u16_t offset) { - u32_t status; + u32_t status; #ifdef ZM_CONFIG_BIG_ENDIAN - u32_t ii = 0; - u16_t *pc = NULL; - - pc = (u16_t *)hdr; - for(ii=0; ii<(hdrlen>>1); ii++) - { - pc[ii] = cpu_to_le16(pc[ii]); - } - - pc = (u16_t *)snap; - for(ii=0; ii<(snapLen>>1); ii++) - { - pc[ii] = cpu_to_le16(pc[ii]); - } - - pc = (u16_t *)tail; - for(ii=0; ii<(tailLen>>1); ii++) - { - pc[ii] = cpu_to_le16(pc[ii]); - } + u32_t ii = 0; + u16_t *pc = NULL; + + pc = (u16_t *)hdr; + for (ii = 0; ii < (hdrlen >> 1); ii++) + pc[ii] = cpu_to_le16(pc[ii]); + + pc = (u16_t *)snap; + for (ii = 0; ii < (snapLen >> 1); ii++) + pc[ii] = cpu_to_le16(pc[ii]); + + pc = (u16_t *)tail; + for (ii = 0; ii < (tailLen>>1); ii++) + pc[ii] = cpu_to_le16(pc[ii]); #endif - status = zfLnxUsbOut(dev, hdr, hdrlen, snap, snapLen, tail, tailLen, buf, offset); - if ( status == 0 ) - { - return 0; - } - else - { - return 1; - } + status = zfLnxUsbOut(dev, hdr, hdrlen, snap, snapLen, tail, tailLen, + buf, offset); + if (status == 0) + return 0; + else + return 1; } /* Leave an empty line below to remove warning message on some compiler */ diff --git a/drivers/staging/otus/zdusb.h b/drivers/staging/otus/zdusb.h index 9f8ab2e96169ac0af00d3ebf3652aab50ed58ce9..97e4ef09567ac90ddb05dbdd69d0842d782e032f 100644 --- a/drivers/staging/otus/zdusb.h +++ b/drivers/staging/otus/zdusb.h @@ -34,10 +34,10 @@ #define VERSIONID "0.0.0.999" /* Define these values to match your device */ -#define VENDOR_ATHR 0x0CF3 //Atheros +#define VENDOR_ATHR 0x0CF3 /* Atheros */ #define PRODUCT_AR9170 0x9170 -#define VENDOR_DLINK 0x07D1 //Dlink +#define VENDOR_DLINK 0x07D1 /* Dlink */ #define PRODUCT_DWA160A 0x3C10 #define VENDOR_NETGEAR 0x0846 /* NetGear */ diff --git a/drivers/staging/p9auth/p9auth.c b/drivers/staging/p9auth/p9auth.c index 8ccfff723eecd6e7863b8d801f68b01f4ed8129b..db7962621210764ccd1c236269d60509633959f6 100644 --- a/drivers/staging/p9auth/p9auth.c +++ b/drivers/staging/p9auth/p9auth.c @@ -334,6 +334,7 @@ static const struct file_operations cap_fops = { .release = cap_release, }; +/* no __exit here because it can be called by the init function */ static void cap_cleanup_module(void) { int i; @@ -360,7 +361,7 @@ static void cap_setup_cdev(struct cap_dev *dev, int index) printk(KERN_NOTICE "Error %d adding cap%d", err, index); } -static int cap_init_module(void) +static int __init cap_init_module(void) { int result, i; dev_t dev = 0; diff --git a/drivers/staging/phison/phison.c b/drivers/staging/phison/phison.c index 270ebcb681a29d4e6eef9f555405335fdccd88f2..3817d7497049b5b12a647cfb9010af6961c532c5 100644 --- a/drivers/staging/phison/phison.c +++ b/drivers/staging/phison/phison.c @@ -87,12 +87,12 @@ static struct pci_driver phison_pci_driver = { #endif }; -static int phison_ide_init(void) +static int __init phison_ide_init(void) { return pci_register_driver(&phison_pci_driver); } -static void phison_ide_exit(void) +static void __exit phison_ide_exit(void) { pci_unregister_driver(&phison_pci_driver); } diff --git a/drivers/staging/poch/README b/drivers/staging/poch/README index 842afd46499388def0f781e25921147d82abf31c..ac76ff969a2ff22efe515373a51cda90ee72ed74 100644 --- a/drivers/staging/poch/README +++ b/drivers/staging/poch/README @@ -1,7 +1,6 @@ TODO: - Rx block size is limited to < 2048, hardware bug? - Group size is limited to < page size, kernel alloc/mmap API issues - - fix/workaround cache issues in circular buffer header - test whether Tx is transmitting data from provided buffers - handle device unplug case - handle temperature above threshold @@ -10,5 +9,128 @@ TODO: - audit userspace interfaces - get reserved major/minor if needed +Sample Code: + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +struct pconsume { + uint32_t * offsets; + uint32_t nfetch; + uint32_t nflush; +}; + +uint32_t offsets[10]; + +void process_group(unsigned char *buf, uint32_t size) +{ + uint16_t *buf16 = (uint16_t *)buf; + + printf("RX: %p %u %04x %04x %04x %04x %04x %04x\n", buf, size, + buf16[0], buf16[1], buf16[2], buf16[3], buf16[4], buf16[5]); +} + +int main() +{ + struct sysfs_attribute *attr; + char *path; + int ret; + unsigned long mmap_size; + int fd; + unsigned char *cbuf; + + uint32_t nflush; + struct pollfd poll_fds; + int count = 0; + int i; + + path = "/sys/class/pocketchange/poch0/ch0/block_size"; + attr = sysfs_open_attribute(path); + ret = sysfs_write_attribute(attr, "256", strlen("256")); + if (ret == -1) + error(1, errno, "error writing attribute %s", path); + sysfs_close_attribute(attr); + + path = "/sys/class/pocketchange/poch0/ch0/group_size"; + attr = sysfs_open_attribute(path); + ret = sysfs_write_attribute(attr, "4096", strlen("4096")); + if (ret == -1) + error(1, errno, "error writing attribute %s", path); + sysfs_close_attribute(attr); + + path = "/sys/class/pocketchange/poch0/ch0/group_count"; + attr = sysfs_open_attribute(path); + ret = sysfs_write_attribute(attr, "64", strlen("64")); + if (ret == -1) + error(1, errno, "error writing attribute %s", path); + sysfs_close_attribute(attr); + + fd = open("/dev/ch0", O_RDWR); + if (fd == -1) + error(1, errno, "error opening device node"); + + path = "/sys/class/pocketchange/poch0/ch0/mmap_size"; + attr = sysfs_open_attribute(path); + ret = sysfs_read_attribute(attr); + if (ret == -1) + error(1, errno, "error reading attribute %s", path); + printf("%s", attr->value); + sscanf(attr->value, "%lu", &mmap_size); + sysfs_close_attribute(attr); + + cbuf = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE, fd, 0); + if (cbuf == MAP_FAILED) + error(1, errno, "error mapping DMA buffers"); + + ret = ioctl(fd, POCH_IOC_TRANSFER_START, 0); + if (ret == -1) + error(1, errno, "error starting transfer"); + + nflush = 0; + while (1) { + struct pconsume consume; + + consume.offsets = offsets; + consume.nfetch = 10; + consume.nflush = nflush; + + ret = ioctl(fd, POCH_IOC_CONSUME, &consume); + if (ret == -1) + error(1, errno, "error consuming groups"); + + nflush = consume.nfetch; + + for (i = 0; i < nflush; i++) { + process_group(cbuf + consume.offsets[i], 4096); + + count++; + if (count == 1000) + break; + } + + if (count == 1000) + break; + } + + ret = ioctl(fd, POCH_IOC_TRANSFER_STOP, 0); + if (ret == -1) + error(1, errno, "error starting transfer"); + + return 0; +} + Please send patches to Greg Kroah-Hartman and Vijay Kumar and Jaya Kumar diff --git a/drivers/staging/poch/poch.c b/drivers/staging/poch/poch.c index 2eb8e3d43c4d6a503ca58cf9de70f44c357ee4a7..9095158fb1b3a1a908c55a1bc5b7f3ff0773681a 100644 --- a/drivers/staging/poch/poch.c +++ b/drivers/staging/poch/poch.c @@ -197,10 +197,9 @@ struct channel_info { /* Contains the header and circular buffer exported to userspace. */ spinlock_t group_offsets_lock; - struct poch_cbuf_header *header; - struct page *header_pg; - unsigned long header_size; + /* Last group consumed by user space. */ + unsigned int consumed; /* Last group indicated as 'complete' to user space. */ unsigned int transfer; @@ -245,6 +244,16 @@ struct poch_dev { struct device *dev; }; +static int synth_rx; +module_param(synth_rx, bool, 0600); +MODULE_PARM_DESC(synth_rx, + "Synthesize received values using a counter. Default: No"); + +static int loopback; +module_param(loopback, bool, 0600); +MODULE_PARM_DESC(loopback, + "Enable hardware loopback of trasnmitted data. Default: No"); + static dev_t poch_first_dev; static struct class *poch_cls; static DEFINE_IDR(poch_ids); @@ -317,14 +326,12 @@ static ssize_t show_mmap_size(struct device *dev, int len; unsigned long mmap_size; unsigned long group_pages; - unsigned long header_pages; unsigned long total_group_pages; group_pages = npages(channel->group_size); - header_pages = npages(channel->header_size); total_group_pages = group_pages * channel->group_count; - mmap_size = (header_pages + total_group_pages) * PAGE_SIZE; + mmap_size = total_group_pages * PAGE_SIZE; len = sprintf(buf, "%lu\n", mmap_size); return len; } @@ -357,10 +364,8 @@ static int poch_channel_alloc_groups(struct channel_info *channel) { unsigned long i; unsigned long group_pages; - unsigned long header_pages; group_pages = npages(channel->group_size); - header_pages = npages(channel->header_size); for (i = 0; i < channel->group_count; i++) { struct poch_group_info *group; @@ -390,8 +395,7 @@ static int poch_channel_alloc_groups(struct channel_info *channel) * this? */ group->dma_addr = page_to_pfn(group->pg) * PAGE_SIZE; - group->user_offset = - (header_pages + (i * group_pages)) * PAGE_SIZE; + group->user_offset = (i * group_pages) * PAGE_SIZE; printk(KERN_INFO PFX "%ld: user_offset: 0x%lx\n", i, group->user_offset); @@ -476,7 +480,7 @@ static void channel_dma_init(struct channel_info *channel) fpga + block_count_reg); iowrite32(channel->group_count, fpga + group_count_reg); /* FIXME: Hardcoded groups per int. Get it from sysfs? */ - iowrite32(1, fpga + groups_per_int_reg); + iowrite32(16, fpga + groups_per_int_reg); /* Unlock PCI address? Not defined in the data sheet, but used * in the reference code by Redrapids. @@ -513,56 +517,6 @@ static void channel_dma_init(struct channel_info *channel) } -static int poch_channel_alloc_header(struct channel_info *channel) -{ - struct poch_cbuf_header *header = channel->header; - unsigned long group_offset_size; - unsigned long tot_group_offsets_size; - - /* Allocate memory to hold header exported userspace */ - group_offset_size = sizeof(header->group_offsets[0]); - tot_group_offsets_size = group_offset_size * channel->group_count; - channel->header_size = sizeof(*header) + tot_group_offsets_size; - channel->header_pg = alloc_pages(GFP_KERNEL | __GFP_ZERO, - get_order(channel->header_size)); - if (!channel->header_pg) - return -ENOMEM; - - channel->header = page_address(channel->header_pg); - - return 0; -} - -static void poch_channel_free_header(struct channel_info *channel) -{ - unsigned int order; - - order = get_order(channel->header_size); - __free_pages(channel->header_pg, order); -} - -static void poch_channel_init_header(struct channel_info *channel) -{ - int i; - struct poch_group_info *groups; - s32 *group_offsets; - - channel->header->group_size_bytes = channel->group_size; - channel->header->group_count = channel->group_count; - - spin_lock_init(&channel->group_offsets_lock); - - group_offsets = channel->header->group_offsets; - groups = channel->groups; - - for (i = 0; i < channel->group_count; i++) { - if (channel->dir == CHANNEL_DIR_RX) - group_offsets[i] = -1; - else - group_offsets[i] = groups[i].user_offset; - } -} - static void __poch_channel_clear_counters(struct channel_info *channel) { channel->counters.pll_unlock = 0; @@ -584,6 +538,7 @@ static int poch_channel_init(struct channel_info *channel, if (ret != 0) goto out; + channel->consumed = 0; channel->transfer = 0; /* Allocate memory to hold group information. */ @@ -604,12 +559,6 @@ static int poch_channel_init(struct channel_info *channel, goto out_free_group_info; } - ret = poch_channel_alloc_header(channel); - if (ret) { - dev_err(dev, "error allocating user space header\n"); - goto out_free_groups; - } - channel->fpga_iomem = poch_dev->fpga_iomem; channel->bridge_iomem = poch_dev->bridge_iomem; channel->iomem_lock = &poch_dev->iomem_lock; @@ -617,14 +566,8 @@ static int poch_channel_init(struct channel_info *channel, __poch_channel_clear_counters(channel); - printk(KERN_WARNING "poch_channel_init_header\n"); - - poch_channel_init_header(channel); - return 0; - out_free_groups: - poch_channel_free_groups(channel); out_free_group_info: kfree(channel->groups); out: @@ -822,14 +765,21 @@ static int poch_open(struct inode *inode, struct file *filp) if (channel->dir == CHANNEL_DIR_TX) { /* Flush TX FIFO and output data from cardbus. */ - iowrite32(FPGA_TX_CTL_FIFO_FLUSH - | FPGA_TX_CTL_OUTPUT_CARDBUS, - fpga + FPGA_TX_CTL_REG); + u32 ctl_val = 0; + + ctl_val |= FPGA_TX_CTL_FIFO_FLUSH; + ctl_val |= FPGA_TX_CTL_OUTPUT_CARDBUS; + if (loopback) + ctl_val |= FPGA_TX_CTL_LOOPBACK; + + iowrite32(ctl_val, fpga + FPGA_TX_CTL_REG); } else { /* Flush RX FIFO and output data to cardbus. */ - iowrite32(FPGA_RX_CTL_CONT_CAP - | FPGA_RX_CTL_FIFO_FLUSH, - fpga + FPGA_RX_CTL_REG); + u32 ctl_val = FPGA_RX_CTL_CONT_CAP | FPGA_RX_CTL_FIFO_FLUSH; + if (synth_rx) + ctl_val |= FPGA_RX_CTL_SYNTH_DATA; + + iowrite32(ctl_val, fpga + FPGA_RX_CTL_REG); } atomic_inc(&channel->inited); @@ -861,7 +811,6 @@ static int poch_release(struct inode *inode, struct file *filp) } atomic_dec(&channel->inited); - poch_channel_free_header(channel); poch_channel_free_groups(channel); kfree(channel->groups); atomic_inc(&channel->free); @@ -870,7 +819,7 @@ static int poch_release(struct inode *inode, struct file *filp) } /* - * Map the header and the group buffers, to user space. + * Map the the group buffers, to user space. */ static int poch_mmap(struct file *filp, struct vm_area_struct *vma) { @@ -880,7 +829,6 @@ static int poch_mmap(struct file *filp, struct vm_area_struct *vma) unsigned long size; unsigned long group_pages; - unsigned long header_pages; unsigned long total_group_pages; int pg_num; @@ -897,30 +845,16 @@ static int poch_mmap(struct file *filp, struct vm_area_struct *vma) } group_pages = npages(channel->group_size); - header_pages = npages(channel->header_size); total_group_pages = group_pages * channel->group_count; size = vma->vm_end - vma->vm_start; - if (size != (header_pages + total_group_pages) * PAGE_SIZE) { + if (size != total_group_pages * PAGE_SIZE) { printk(KERN_WARNING PFX "required %lu bytes\n", size); return -EINVAL; } start = vma->vm_start; - /* FIXME: Cleanup required on failure? */ - pg = channel->header_pg; - for (pg_num = 0; pg_num < header_pages; pg_num++, pg++) { - printk(KERN_DEBUG PFX "page_count: %d\n", page_count(pg)); - printk(KERN_DEBUG PFX "%d: header: 0x%lx\n", pg_num, start); - ret = vm_insert_page(vma, start, pg); - if (ret) { - printk(KERN_DEBUG "vm_insert 1 failed at %lx\n", start); - return ret; - } - start += PAGE_SIZE; - } - for (i = 0; i < channel->group_count; i++) { pg = channel->groups[i].pg; for (pg_num = 0; pg_num < group_pages; pg_num++, pg++) { @@ -947,20 +881,16 @@ static int poch_mmap(struct file *filp, struct vm_area_struct *vma) */ static int poch_channel_available(struct channel_info *channel) { - int i; + int available = 0; spin_lock_irq(&channel->group_offsets_lock); - for (i = 0; i < channel->group_count; i++) { - if (channel->header->group_offsets[i] != -1) { - spin_unlock_irq(&channel->group_offsets_lock); - return 1; - } - } + if (channel->consumed != channel->transfer) + available = 1; spin_unlock_irq(&channel->group_offsets_lock); - return 0; + return available; } static unsigned int poch_poll(struct file *filp, poll_table *pt) @@ -1026,6 +956,51 @@ static int poch_ioctl(struct inode *inode, struct file *filp, break; } break; + case POCH_IOC_CONSUME: + { + int available; + int nfetch; + unsigned int from; + unsigned int count; + unsigned int i, j; + struct poch_consume consume; + struct poch_consume *uconsume; + + uconsume = argp; + ret = copy_from_user(&consume, uconsume, sizeof(consume)); + if (ret) + return ret; + + spin_lock_irq(&channel->group_offsets_lock); + + channel->consumed += consume.nflush; + channel->consumed %= channel->group_count; + + available = channel->transfer - channel->consumed; + if (available < 0) + available += channel->group_count; + + from = channel->consumed; + + spin_unlock_irq(&channel->group_offsets_lock); + + nfetch = consume.nfetch; + count = min(available, nfetch); + + for (i = 0; i < count; i++) { + j = (from + i) % channel->group_count; + ret = put_user(channel->groups[j].user_offset, + &consume.offsets[i]); + if (ret) + return -EFAULT; + } + + ret = put_user(count, &uconsume->nfetch); + if (ret) + return -EFAULT; + + break; + } case POCH_IOC_GET_COUNTERS: if (!access_ok(VERIFY_WRITE, argp, sizeof(struct poch_counters))) return -EFAULT; @@ -1073,7 +1048,6 @@ static void poch_irq_dma(struct channel_info *channel) long groups_done; unsigned long i, j; struct poch_group_info *groups; - s32 *group_offsets; u32 curr_group_reg; if (!atomic_read(&channel->inited)) @@ -1093,20 +1067,24 @@ static void poch_irq_dma(struct channel_info *channel) if (groups_done <= 0) groups_done += channel->group_count; - group_offsets = channel->header->group_offsets; groups = channel->groups; spin_lock(&channel->group_offsets_lock); for (i = 0; i < groups_done; i++) { j = (prev_transfer + i) % channel->group_count; - group_offsets[j] = groups[j].user_offset; + + channel->transfer += 1; + channel->transfer %= channel->group_count; + + if (channel->transfer == channel->consumed) { + channel->consumed += 1; + channel->consumed %= channel->group_count; + } } spin_unlock(&channel->group_offsets_lock); - channel->transfer = curr_transfer; - wake_up_interruptible(&channel->wq); } diff --git a/drivers/staging/poch/poch.h b/drivers/staging/poch/poch.h index 51a2d145798efbf600826eec6064d7c42129d375..8b08385861fdbbd59a0baa801b0a23bc727b50c8 100644 --- a/drivers/staging/poch/poch.h +++ b/drivers/staging/poch/poch.h @@ -7,11 +7,8 @@ * include/linux for final version. * */ -struct poch_cbuf_header { - __s32 group_size_bytes; - __s32 group_count; - __s32 group_offsets[0]; -}; + +#include struct poch_counters { __u32 fifo_empty; @@ -19,6 +16,12 @@ struct poch_counters { __u32 pll_unlock; }; +struct poch_consume { + __u32 __user *offsets; + __u32 nfetch; + __u32 nflush; +}; + #define POCH_IOC_NUM '9' #define POCH_IOC_TRANSFER_START _IO(POCH_IOC_NUM, 0) @@ -27,3 +30,6 @@ struct poch_counters { struct poch_counters) #define POCH_IOC_SYNC_GROUP_FOR_USER _IO(POCH_IOC_NUM, 3) #define POCH_IOC_SYNC_GROUP_FOR_DEVICE _IO(POCH_IOC_NUM, 4) + +#define POCH_IOC_CONSUME _IOWR(POCH_IOC_NUM, 5, \ + struct poch_consume) diff --git a/drivers/staging/quatech_usb2/quatech_usb2.c b/drivers/staging/quatech_usb2/quatech_usb2.c index 2acef9466d47fdd0fbc7793458f6b4c092ee5b20..f7726f1d3641895e238d4364e0c6f15cc46aa2d3 100644 --- a/drivers/staging/quatech_usb2/quatech_usb2.c +++ b/drivers/staging/quatech_usb2/quatech_usb2.c @@ -1670,7 +1670,7 @@ __func__); dbg("%s(): failed resubmitting read urb, error %d", __func__, result); } else { - dbg("%s() sucessfully resumitted read urb", __func__); + dbg("%s() successfully resubmitted read urb", __func__); if (tty_st && RxCount) { /* if some inbound data was processed, then * we need to push that through the tty layer diff --git a/drivers/staging/ramzswap/Kconfig b/drivers/staging/ramzswap/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..24e25691fae2d31bae3bfbf3d746cdf2b0eb88fa --- /dev/null +++ b/drivers/staging/ramzswap/Kconfig @@ -0,0 +1,21 @@ +config RAMZSWAP + tristate "Compressed in-memory swap device (ramzswap)" + depends on SWAP + select LZO_COMPRESS + select LZO_DECOMPRESS + default n + help + Creates virtual block devices which can be used (only) as a swap + disks. Pages swapped to these disks are compressed and stored in + memory itself. + + See ramzswap.txt for more information. + Project home: http://compcache.googlecode.com/ + +config RAMZSWAP_STATS + bool "Enable ramzswap stats" + depends on RAMZSWAP + default y + help + Enable statistics collection for ramzswap. This adds only a minimal + overhead. In unsure, say Y. diff --git a/drivers/staging/ramzswap/Makefile b/drivers/staging/ramzswap/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..507d7dc3b864ab28d4bcfd6bbb9f1c41a61e9ffe --- /dev/null +++ b/drivers/staging/ramzswap/Makefile @@ -0,0 +1,3 @@ +ramzswap-objs := ramzswap_drv.o xvmalloc.o + +obj-$(CONFIG_RAMZSWAP) += ramzswap.o diff --git a/drivers/staging/ramzswap/TODO b/drivers/staging/ramzswap/TODO new file mode 100644 index 0000000000000000000000000000000000000000..bac40d6cb9f13927e445a3dc7860352b16ec0337 --- /dev/null +++ b/drivers/staging/ramzswap/TODO @@ -0,0 +1,6 @@ +TODO: + - Add support for swap notifiers + - Remove CONFIG_ARM hack + +Please send patches to Greg Kroah-Hartman and +Nitin Gupta diff --git a/drivers/staging/ramzswap/ramzswap.txt b/drivers/staging/ramzswap/ramzswap.txt new file mode 100644 index 0000000000000000000000000000000000000000..e9f1619505a05c83635458a2f13f482dfb9fdadb --- /dev/null +++ b/drivers/staging/ramzswap/ramzswap.txt @@ -0,0 +1,51 @@ +ramzswap: Compressed RAM based swap device +------------------------------------------- + +Project home: http://compcache.googlecode.com/ + +* Introduction + +It creates RAM based block devices which can be used (only) as swap disks. +Pages swapped to these devices are compressed and stored in memory itself. +See project home for use cases, performance numbers and a lot more. + +Individual ramzswap devices are configured and initialized using rzscontrol +userspace utility as shown in examples below. See rzscontrol man page for more +details. + +* Usage + +Following shows a typical sequence of steps for using ramzswap. + +1) Load Modules: + modprobe ramzswap num_devices=4 + This creates 4 (uninitialized) devices: /dev/ramzswap{0,1,2,3} + (num_devices parameter is optional. Default: 1) + +2) Initialize: + Use rzscontrol utility to configure and initialize individual + ramzswap devices. Example: + rzscontrol /dev/ramzswap2 --init # uses default value of disksize_kb + + *See rzscontrol man page for more details and examples* + +3) Activate: + swapon /dev/ramzswap2 # or any other initialized ramzswap device + +4) Stats: + rzscontrol /dev/ramzswap2 --stats + +5) Deactivate: + swapoff /dev/ramzswap2 + +6) Reset: + rzscontrol /dev/ramzswap2 --reset + (This frees all the memory allocated for this device). + + +Please report any problems at: + - Mailing list: linux-mm-cc at laptop dot org + - Issue tracker: http://code.google.com/p/compcache/issues/list + +Nitin Gupta +ngupta@vflare.org diff --git a/drivers/staging/ramzswap/ramzswap_drv.c b/drivers/staging/ramzswap/ramzswap_drv.c new file mode 100644 index 0000000000000000000000000000000000000000..b839f05efbcedbd3a70142cebfaef12d654a3a5b --- /dev/null +++ b/drivers/staging/ramzswap/ramzswap_drv.c @@ -0,0 +1,1435 @@ +/* + * Compressed RAM based swap device + * + * Copyright (C) 2008, 2009 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + * + * Project home: http://compcache.googlecode.com + */ + +#define KMSG_COMPONENT "ramzswap" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ramzswap_drv.h" + +/* Globals */ +static int ramzswap_major; +static struct ramzswap *devices; + +/* + * Pages that compress to larger than this size are + * forwarded to backing swap, if present or stored + * uncompressed in memory otherwise. + */ +static unsigned int max_zpage_size; + +/* Module params (documentation at end) */ +static unsigned int num_devices; + +static int rzs_test_flag(struct ramzswap *rzs, u32 index, + enum rzs_pageflags flag) +{ + return rzs->table[index].flags & BIT(flag); +} + +static void rzs_set_flag(struct ramzswap *rzs, u32 index, + enum rzs_pageflags flag) +{ + rzs->table[index].flags |= BIT(flag); +} + +static void rzs_clear_flag(struct ramzswap *rzs, u32 index, + enum rzs_pageflags flag) +{ + rzs->table[index].flags &= ~BIT(flag); +} + +static int page_zero_filled(void *ptr) +{ + unsigned int pos; + unsigned long *page; + + page = (unsigned long *)ptr; + + for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) { + if (page[pos]) + return 0; + } + + return 1; +} + +/* + * memlimit cannot be greater than backing disk size. + */ +static void ramzswap_set_memlimit(struct ramzswap *rzs, size_t totalram_bytes) +{ + int memlimit_valid = 1; + + if (!rzs->memlimit) { + pr_info("Memory limit not set.\n"); + memlimit_valid = 0; + } + + if (rzs->memlimit > rzs->disksize) { + pr_info("Memory limit cannot be greater than " + "disksize: limit=%zu, disksize=%zu\n", + rzs->memlimit, rzs->disksize); + memlimit_valid = 0; + } + + if (!memlimit_valid) { + size_t mempart, disksize; + pr_info("Using default: smaller of (%u%% of RAM) and " + "(backing disk size).\n", + default_memlimit_perc_ram); + mempart = default_memlimit_perc_ram * (totalram_bytes / 100); + disksize = rzs->disksize; + rzs->memlimit = mempart > disksize ? disksize : mempart; + } + + if (rzs->memlimit > totalram_bytes / 2) { + pr_info( + "Its not advisable setting limit more than half of " + "size of memory since we expect a 2:1 compression ratio. " + "Limit represents amount of *compressed* data we can keep " + "in memory!\n" + "\tMemory Size: %zu kB\n" + "\tLimit you selected: %zu kB\n" + "Continuing anyway ...\n", + totalram_bytes >> 10, rzs->memlimit >> 10 + ); + } + + rzs->memlimit &= PAGE_MASK; + BUG_ON(!rzs->memlimit); +} + +static void ramzswap_set_disksize(struct ramzswap *rzs, size_t totalram_bytes) +{ + if (!rzs->disksize) { + pr_info( + "disk size not provided. You can use disksize_kb module " + "param to specify size.\nUsing default: (%u%% of RAM).\n", + default_disksize_perc_ram + ); + rzs->disksize = default_disksize_perc_ram * + (totalram_bytes / 100); + } + + if (rzs->disksize > 2 * (totalram_bytes)) { + pr_info( + "There is little point creating a ramzswap of greater than " + "twice the size of memory since we expect a 2:1 compression " + "ratio. Note that ramzswap uses about 0.1%% of the size of " + "the swap device when not in use so a huge ramzswap is " + "wasteful.\n" + "\tMemory Size: %zu kB\n" + "\tSize you selected: %zu kB\n" + "Continuing anyway ...\n", + totalram_bytes >> 10, rzs->disksize + ); + } + + rzs->disksize &= PAGE_MASK; +} + +/* + * Swap header (1st page of swap device) contains information + * to indentify it as a swap partition. Prepare such a header + * for ramzswap device (ramzswap0) so that swapon can identify + * it as swap partition. In case backing swap device is provided, + * copy its swap header. + */ +static int setup_swap_header(struct ramzswap *rzs, union swap_header *s) +{ + int ret = 0; + struct page *page; + struct address_space *mapping; + union swap_header *backing_swap_header; + + /* + * There is no backing swap device. Create a swap header + * that is acceptable by swapon. + */ + if (!rzs->backing_swap) { + s->info.version = 1; + s->info.last_page = (rzs->disksize >> PAGE_SHIFT) - 1; + s->info.nr_badpages = 0; + memcpy(s->magic.magic, "SWAPSPACE2", 10); + return 0; + } + + /* + * We have a backing swap device. Copy its swap header + * to ramzswap device header. If this header contains + * invalid information (backing device not a swap + * partition, etc.), swapon will fail for ramzswap + * which is correct behavior - we don't want to swap + * over filesystem partition! + */ + + /* Read the backing swap header (code from sys_swapon) */ + mapping = rzs->swap_file->f_mapping; + if (!mapping->a_ops->readpage) { + ret = -EINVAL; + goto out; + } + + page = read_mapping_page(mapping, 0, rzs->swap_file); + if (IS_ERR(page)) { + ret = PTR_ERR(page); + goto out; + } + + backing_swap_header = kmap(page); + memcpy(s, backing_swap_header, sizeof(*s)); + if (s->info.nr_badpages) { + pr_info("Cannot use backing swap with bad pages (%u)\n", + s->info.nr_badpages); + ret = -EINVAL; + } + /* + * ramzswap disksize equals number of usable pages in backing + * swap. Set last_page in swap header to match this disksize + * ('last_page' means 0-based index of last usable swap page). + */ + s->info.last_page = (rzs->disksize >> PAGE_SHIFT) - 1; + kunmap(page); + +out: + return ret; +} + +static void ramzswap_flush_dcache_page(struct page *page) +{ +#ifdef CONFIG_ARM + int flag = 0; + /* + * Ugly hack to get flush_dcache_page() work on ARM. + * page_mapping(page) == NULL after clearing this swap cache flag. + * Without clearing this flag, flush_dcache_page() will simply set + * "PG_dcache_dirty" bit and return. + */ + if (PageSwapCache(page)) { + flag = 1; + ClearPageSwapCache(page); + } +#endif + flush_dcache_page(page); +#ifdef CONFIG_ARM + if (flag) + SetPageSwapCache(page); +#endif +} + +void ramzswap_ioctl_get_stats(struct ramzswap *rzs, + struct ramzswap_ioctl_stats *s) +{ + strncpy(s->backing_swap_name, rzs->backing_swap_name, + MAX_SWAP_NAME_LEN - 1); + s->backing_swap_name[MAX_SWAP_NAME_LEN - 1] = '\0'; + + s->disksize = rzs->disksize; + s->memlimit = rzs->memlimit; + +#if defined(CONFIG_RAMZSWAP_STATS) + { + struct ramzswap_stats *rs = &rzs->stats; + size_t succ_writes, mem_used; + unsigned int good_compress_perc = 0, no_compress_perc = 0; + + mem_used = xv_get_total_size_bytes(rzs->mem_pool) + + (rs->pages_expand << PAGE_SHIFT); + succ_writes = rs->num_writes - rs->failed_writes; + + if (succ_writes && rs->pages_stored) { + good_compress_perc = rs->good_compress * 100 + / rs->pages_stored; + no_compress_perc = rs->pages_expand * 100 + / rs->pages_stored; + } + + s->num_reads = rs->num_reads; + s->num_writes = rs->num_writes; + s->failed_reads = rs->failed_reads; + s->failed_writes = rs->failed_writes; + s->invalid_io = rs->invalid_io; + s->pages_zero = rs->pages_zero; + + s->good_compress_pct = good_compress_perc; + s->pages_expand_pct = no_compress_perc; + + s->pages_stored = rs->pages_stored; + s->pages_used = mem_used >> PAGE_SHIFT; + s->orig_data_size = rs->pages_stored << PAGE_SHIFT; + s->compr_data_size = rs->compr_size; + s->mem_used_total = mem_used; + + s->bdev_num_reads = rs->bdev_num_reads; + s->bdev_num_writes = rs->bdev_num_writes; + } +#endif /* CONFIG_RAMZSWAP_STATS */ +} + +static int add_backing_swap_extent(struct ramzswap *rzs, + pgoff_t phy_pagenum, + pgoff_t num_pages) +{ + unsigned int idx; + struct list_head *head; + struct page *curr_page, *new_page; + unsigned int extents_per_page = PAGE_SIZE / + sizeof(struct ramzswap_backing_extent); + + idx = rzs->num_extents % extents_per_page; + if (!idx) { + new_page = alloc_page(__GFP_ZERO); + if (!new_page) + return -ENOMEM; + + if (rzs->num_extents) { + curr_page = virt_to_page(rzs->curr_extent); + head = &curr_page->lru; + } else { + head = &rzs->backing_swap_extent_list; + } + + list_add(&new_page->lru, head); + rzs->curr_extent = page_address(new_page); + } + + rzs->curr_extent->phy_pagenum = phy_pagenum; + rzs->curr_extent->num_pages = num_pages; + + pr_debug("add_extent: idx=%u, phy_pgnum=%lu, num_pgs=%lu, " + "pg_last=%lu, curr_ext=%p\n", idx, phy_pagenum, num_pages, + phy_pagenum + num_pages - 1, rzs->curr_extent); + + if (idx != extents_per_page - 1) + rzs->curr_extent++; + + return 0; +} + +static int setup_backing_swap_extents(struct ramzswap *rzs, + struct inode *inode, unsigned long *num_pages) +{ + int ret = 0; + unsigned blkbits; + unsigned blocks_per_page; + pgoff_t contig_pages = 0, total_pages = 0; + pgoff_t pagenum = 0, prev_pagenum = 0; + sector_t probe_block = 0; + sector_t last_block; + + blkbits = inode->i_blkbits; + blocks_per_page = PAGE_SIZE >> blkbits; + + last_block = i_size_read(inode) >> blkbits; + while (probe_block + blocks_per_page <= last_block) { + unsigned block_in_page; + sector_t first_block; + + first_block = bmap(inode, probe_block); + if (first_block == 0) + goto bad_bmap; + + /* It must be PAGE_SIZE aligned on-disk */ + if (first_block & (blocks_per_page - 1)) { + probe_block++; + goto probe_next; + } + + /* All blocks within this page must be contiguous on disk */ + for (block_in_page = 1; block_in_page < blocks_per_page; + block_in_page++) { + sector_t block; + + block = bmap(inode, probe_block + block_in_page); + if (block == 0) + goto bad_bmap; + if (block != first_block + block_in_page) { + /* Discontiguity */ + probe_block++; + goto probe_next; + } + } + + /* + * We found a PAGE_SIZE length, PAGE_SIZE aligned + * run of blocks. + */ + pagenum = first_block >> (PAGE_SHIFT - blkbits); + + if (total_pages && (pagenum != prev_pagenum + 1)) { + ret = add_backing_swap_extent(rzs, prev_pagenum - + (contig_pages - 1), contig_pages); + if (ret < 0) + goto out; + rzs->num_extents++; + contig_pages = 0; + } + total_pages++; + contig_pages++; + prev_pagenum = pagenum; + probe_block += blocks_per_page; + +probe_next: + continue; + } + + if (contig_pages) { + pr_debug("adding last extent: pagenum=%lu, " + "contig_pages=%lu\n", pagenum, contig_pages); + ret = add_backing_swap_extent(rzs, + prev_pagenum - (contig_pages - 1), contig_pages); + if (ret < 0) + goto out; + rzs->num_extents++; + } + if (!rzs->num_extents) { + pr_err("No swap extents found!\n"); + ret = -EINVAL; + } + + if (!ret) { + *num_pages = total_pages; + pr_info("Found %lu extents containing %luk\n", + rzs->num_extents, *num_pages << (PAGE_SHIFT - 10)); + } + goto out; + +bad_bmap: + pr_err("Backing swapfile has holes\n"); + ret = -EINVAL; +out: + while (ret && !list_empty(&rzs->backing_swap_extent_list)) { + struct page *page; + struct list_head *entry = rzs->backing_swap_extent_list.next; + page = list_entry(entry, struct page, lru); + list_del(entry); + __free_page(page); + } + return ret; +} + +static void map_backing_swap_extents(struct ramzswap *rzs) +{ + struct ramzswap_backing_extent *se; + struct page *table_page, *se_page; + unsigned long num_pages, num_table_pages, entry; + unsigned long se_idx, span; + unsigned entries_per_page = PAGE_SIZE / sizeof(*rzs->table); + unsigned extents_per_page = PAGE_SIZE / sizeof(*se); + + /* True for block device */ + if (!rzs->num_extents) + return; + + se_page = list_entry(rzs->backing_swap_extent_list.next, + struct page, lru); + se = page_address(se_page); + span = se->num_pages; + num_pages = rzs->disksize >> PAGE_SHIFT; + num_table_pages = DIV_ROUND_UP(num_pages * sizeof(*rzs->table), + PAGE_SIZE); + + entry = 0; + se_idx = 0; + while (num_table_pages--) { + table_page = vmalloc_to_page(&rzs->table[entry]); + while (span <= entry) { + se_idx++; + if (se_idx == rzs->num_extents) + BUG(); + + if (!(se_idx % extents_per_page)) { + se_page = list_entry(se_page->lru.next, + struct page, lru); + se = page_address(se_page); + } else + se++; + + span += se->num_pages; + } + table_page->mapping = (struct address_space *)se; + table_page->private = se->num_pages - (span - entry); + pr_debug("map_table: entry=%lu, span=%lu, map=%p, priv=%lu\n", + entry, span, table_page->mapping, table_page->private); + entry += entries_per_page; + } +} + +/* + * Check if value of backing_swap module param is sane. + * Claim this device and set ramzswap size equal to + * size of this block device. + */ +static int setup_backing_swap(struct ramzswap *rzs) +{ + int ret = 0; + size_t disksize; + unsigned long num_pages = 0; + struct inode *inode; + struct file *swap_file; + struct address_space *mapping; + struct block_device *bdev = NULL; + + if (!rzs->backing_swap_name[0]) { + pr_debug("backing_swap param not given\n"); + goto out; + } + + pr_info("Using backing swap device: %s\n", rzs->backing_swap_name); + + swap_file = filp_open(rzs->backing_swap_name, + O_RDWR | O_LARGEFILE, 0); + if (IS_ERR(swap_file)) { + pr_err("Error opening backing device: %s\n", + rzs->backing_swap_name); + ret = -EINVAL; + goto out; + } + + mapping = swap_file->f_mapping; + inode = mapping->host; + + if (S_ISBLK(inode->i_mode)) { + bdev = I_BDEV(inode); + ret = bd_claim(bdev, setup_backing_swap); + if (ret < 0) { + bdev = NULL; + goto bad_param; + } + disksize = i_size_read(inode); + } else if (S_ISREG(inode->i_mode)) { + bdev = inode->i_sb->s_bdev; + if (IS_SWAPFILE(inode)) { + ret = -EBUSY; + goto bad_param; + } + ret = setup_backing_swap_extents(rzs, inode, &num_pages); + if (ret < 0) + goto bad_param; + disksize = num_pages << PAGE_SHIFT; + } else { + goto bad_param; + } + + rzs->swap_file = swap_file; + rzs->backing_swap = bdev; + rzs->disksize = disksize; + BUG_ON(!rzs->disksize); + + return 0; + +bad_param: + if (bdev) + bd_release(bdev); + filp_close(swap_file, NULL); + +out: + rzs->backing_swap = NULL; + return ret; +} + +/* + * Map logical page number 'pagenum' to physical page number + * on backing swap device. For block device, this is a nop. + */ +u32 map_backing_swap_page(struct ramzswap *rzs, u32 pagenum) +{ + u32 skip_pages, entries_per_page; + size_t delta, se_offset, skipped; + struct page *table_page, *se_page; + struct ramzswap_backing_extent *se; + + if (!rzs->num_extents) + return pagenum; + + entries_per_page = PAGE_SIZE / sizeof(*rzs->table); + + table_page = vmalloc_to_page(&rzs->table[pagenum]); + se = (struct ramzswap_backing_extent *)table_page->mapping; + se_page = virt_to_page(se); + + skip_pages = pagenum - (pagenum / entries_per_page * entries_per_page); + se_offset = table_page->private + skip_pages; + + if (se_offset < se->num_pages) + return se->phy_pagenum + se_offset; + + skipped = se->num_pages - table_page->private; + do { + struct ramzswap_backing_extent *se_base; + u32 se_entries_per_page = PAGE_SIZE / sizeof(*se); + + /* Get next swap extent */ + se_base = (struct ramzswap_backing_extent *) + page_address(se_page); + if (se - se_base == se_entries_per_page - 1) { + se_page = list_entry(se_page->lru.next, + struct page, lru); + se = page_address(se_page); + } else { + se++; + } + + skipped += se->num_pages; + } while (skipped < skip_pages); + + delta = skipped - skip_pages; + se_offset = se->num_pages - delta; + + return se->phy_pagenum + se_offset; +} + +static void ramzswap_free_page(struct ramzswap *rzs, size_t index) +{ + u32 clen; + void *obj; + + struct page *page = rzs->table[index].page; + u32 offset = rzs->table[index].offset; + + if (unlikely(!page)) { + if (rzs_test_flag(rzs, index, RZS_ZERO)) { + rzs_clear_flag(rzs, index, RZS_ZERO); + stat_dec(rzs->stats.pages_zero); + } + return; + } + + if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) { + clen = PAGE_SIZE; + __free_page(page); + rzs_clear_flag(rzs, index, RZS_UNCOMPRESSED); + stat_dec(rzs->stats.pages_expand); + goto out; + } + + obj = kmap_atomic(page, KM_USER0) + offset; + clen = xv_get_object_size(obj) - sizeof(struct zobj_header); + kunmap_atomic(obj, KM_USER0); + + xv_free(rzs->mem_pool, page, offset); + if (clen <= PAGE_SIZE / 2) + stat_dec(rzs->stats.good_compress); + +out: + rzs->stats.compr_size -= clen; + stat_dec(rzs->stats.pages_stored); + + rzs->table[index].page = NULL; + rzs->table[index].offset = 0; +} + +static int handle_zero_page(struct bio *bio) +{ + void *user_mem; + struct page *page = bio->bi_io_vec[0].bv_page; + + user_mem = kmap_atomic(page, KM_USER0); + memset(user_mem, 0, PAGE_SIZE); + kunmap_atomic(user_mem, KM_USER0); + + ramzswap_flush_dcache_page(page); + + set_bit(BIO_UPTODATE, &bio->bi_flags); + bio_endio(bio, 0); + return 0; +} + +static int handle_uncompressed_page(struct ramzswap *rzs, struct bio *bio) +{ + u32 index; + struct page *page; + unsigned char *user_mem, *cmem; + + page = bio->bi_io_vec[0].bv_page; + index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; + + user_mem = kmap_atomic(page, KM_USER0); + cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + + rzs->table[index].offset; + + memcpy(user_mem, cmem, PAGE_SIZE); + kunmap_atomic(user_mem, KM_USER0); + kunmap_atomic(cmem, KM_USER1); + + ramzswap_flush_dcache_page(page); + + set_bit(BIO_UPTODATE, &bio->bi_flags); + bio_endio(bio, 0); + return 0; +} + + +/* + * Called when request page is not present in ramzswap. + * Its either in backing swap device (if present) or + * this is an attempt to read before any previous write + * to this location - this happens due to readahead when + * swap device is read from user-space (e.g. during swapon) + */ +static int handle_ramzswap_fault(struct ramzswap *rzs, struct bio *bio) +{ + /* + * Always forward such requests to backing swap + * device (if present) + */ + if (rzs->backing_swap) { + u32 pagenum; + stat_dec(rzs->stats.num_reads); + stat_inc(rzs->stats.bdev_num_reads); + bio->bi_bdev = rzs->backing_swap; + + /* + * In case backing swap is a file, find the right offset within + * the file corresponding to logical position 'index'. For block + * device, this is a nop. + */ + pagenum = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; + bio->bi_sector = map_backing_swap_page(rzs, pagenum) + << SECTORS_PER_PAGE_SHIFT; + return 1; + } + + /* + * Its unlikely event in case backing dev is + * not present + */ + pr_debug("Read before write on swap device: " + "sector=%lu, size=%u, offset=%u\n", + (ulong)(bio->bi_sector), bio->bi_size, + bio->bi_io_vec[0].bv_offset); + + /* Do nothing. Just return success */ + set_bit(BIO_UPTODATE, &bio->bi_flags); + bio_endio(bio, 0); + return 0; +} + +static int ramzswap_read(struct ramzswap *rzs, struct bio *bio) +{ + int ret; + u32 index; + size_t clen; + struct page *page; + struct zobj_header *zheader; + unsigned char *user_mem, *cmem; + + stat_inc(rzs->stats.num_reads); + + page = bio->bi_io_vec[0].bv_page; + index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; + + if (rzs_test_flag(rzs, index, RZS_ZERO)) + return handle_zero_page(bio); + + /* Requested page is not present in compressed area */ + if (!rzs->table[index].page) + return handle_ramzswap_fault(rzs, bio); + + /* Page is stored uncompressed since its incompressible */ + if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) + return handle_uncompressed_page(rzs, bio); + + user_mem = kmap_atomic(page, KM_USER0); + clen = PAGE_SIZE; + + cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + + rzs->table[index].offset; + + ret = lzo1x_decompress_safe( + cmem + sizeof(*zheader), + xv_get_object_size(cmem) - sizeof(*zheader), + user_mem, &clen); + + kunmap_atomic(user_mem, KM_USER0); + kunmap_atomic(cmem, KM_USER1); + + /* should NEVER happen */ + if (unlikely(ret != LZO_E_OK)) { + pr_err("Decompression failed! err=%d, page=%u\n", + ret, index); + stat_inc(rzs->stats.failed_reads); + goto out; + } + + ramzswap_flush_dcache_page(page); + + set_bit(BIO_UPTODATE, &bio->bi_flags); + bio_endio(bio, 0); + return 0; + +out: + bio_io_error(bio); + return 0; +} + +static int ramzswap_write(struct ramzswap *rzs, struct bio *bio) +{ + int ret, fwd_write_request = 0; + u32 offset, index; + size_t clen; + struct zobj_header *zheader; + struct page *page, *page_store; + unsigned char *user_mem, *cmem, *src; + + stat_inc(rzs->stats.num_writes); + + page = bio->bi_io_vec[0].bv_page; + index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; + + src = rzs->compress_buffer; + + /* + * System swaps to same sector again when the stored page + * is no longer referenced by any process. So, its now safe + * to free the memory that was allocated for this page. + */ + if (rzs->table[index].page) + ramzswap_free_page(rzs, index); + + /* + * No memory ia allocated for zero filled pages. + * Simply clear zero page flag. + */ + if (rzs_test_flag(rzs, index, RZS_ZERO)) { + stat_dec(rzs->stats.pages_zero); + rzs_clear_flag(rzs, index, RZS_ZERO); + } + + mutex_lock(&rzs->lock); + + user_mem = kmap_atomic(page, KM_USER0); + if (page_zero_filled(user_mem)) { + kunmap_atomic(user_mem, KM_USER0); + mutex_unlock(&rzs->lock); + stat_inc(rzs->stats.pages_zero); + rzs_set_flag(rzs, index, RZS_ZERO); + + set_bit(BIO_UPTODATE, &bio->bi_flags); + bio_endio(bio, 0); + return 0; + } + + if (rzs->backing_swap && + (rzs->stats.compr_size > rzs->memlimit - PAGE_SIZE)) { + kunmap_atomic(user_mem, KM_USER0); + mutex_unlock(&rzs->lock); + fwd_write_request = 1; + goto out; + } + + ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen, + rzs->compress_workmem); + + kunmap_atomic(user_mem, KM_USER0); + + if (unlikely(ret != LZO_E_OK)) { + mutex_unlock(&rzs->lock); + pr_err("Compression failed! err=%d\n", ret); + stat_inc(rzs->stats.failed_writes); + goto out; + } + + /* + * Page is incompressible. Forward it to backing swap + * if present. Otherwise, store it as-is (uncompressed) + * since we do not want to return too many swap write + * errors which has side effect of hanging the system. + */ + if (unlikely(clen > max_zpage_size)) { + if (rzs->backing_swap) { + mutex_unlock(&rzs->lock); + fwd_write_request = 1; + goto out; + } + + clen = PAGE_SIZE; + page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM); + if (unlikely(!page_store)) { + mutex_unlock(&rzs->lock); + pr_info("Error allocating memory for incompressible " + "page: %u\n", index); + stat_inc(rzs->stats.failed_writes); + goto out; + } + + offset = 0; + rzs_set_flag(rzs, index, RZS_UNCOMPRESSED); + stat_inc(rzs->stats.pages_expand); + rzs->table[index].page = page_store; + src = kmap_atomic(page, KM_USER0); + goto memstore; + } + + if (xv_malloc(rzs->mem_pool, clen + sizeof(*zheader), + &rzs->table[index].page, &offset, + GFP_NOIO | __GFP_HIGHMEM)) { + mutex_unlock(&rzs->lock); + pr_info("Error allocating memory for compressed " + "page: %u, size=%zu\n", index, clen); + stat_inc(rzs->stats.failed_writes); + if (rzs->backing_swap) + fwd_write_request = 1; + goto out; + } + +memstore: + rzs->table[index].offset = offset; + + cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + + rzs->table[index].offset; + +#if 0 + /* Back-reference needed for memory defragmentation */ + if (!rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)) { + zheader = (struct zobj_header *)cmem; + zheader->table_idx = index; + cmem += sizeof(*zheader); + } +#endif + + memcpy(cmem, src, clen); + + kunmap_atomic(cmem, KM_USER1); + if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) + kunmap_atomic(src, KM_USER0); + + /* Update stats */ + rzs->stats.compr_size += clen; + stat_inc(rzs->stats.pages_stored); + if (clen <= PAGE_SIZE / 2) + stat_inc(rzs->stats.good_compress); + + mutex_unlock(&rzs->lock); + + set_bit(BIO_UPTODATE, &bio->bi_flags); + bio_endio(bio, 0); + return 0; + +out: + if (fwd_write_request) { + stat_inc(rzs->stats.bdev_num_writes); + bio->bi_bdev = rzs->backing_swap; +#if 0 + /* + * TODO: We currently have linear mapping of ramzswap and + * backing swap sectors. This is not desired since we want + * to optimize writes to backing swap to minimize disk seeks + * or have effective wear leveling (for SSDs). Also, a + * non-linear mapping is required to implement compressed + * on-disk swapping. + */ + bio->bi_sector = get_backing_swap_page() + << SECTORS_PER_PAGE_SHIFT; +#endif + /* + * In case backing swap is a file, find the right offset within + * the file corresponding to logical position 'index'. For block + * device, this is a nop. + */ + bio->bi_sector = map_backing_swap_page(rzs, index) + << SECTORS_PER_PAGE_SHIFT; + return 1; + } + + bio_io_error(bio); + return 0; +} + + +/* + * Check if request is within bounds and page aligned. + */ +static inline int valid_swap_request(struct ramzswap *rzs, struct bio *bio) +{ + if (unlikely( + (bio->bi_sector >= (rzs->disksize >> SECTOR_SHIFT)) || + (bio->bi_sector & (SECTORS_PER_PAGE - 1)) || + (bio->bi_vcnt != 1) || + (bio->bi_size != PAGE_SIZE) || + (bio->bi_io_vec[0].bv_offset != 0))) { + + return 0; + } + + /* swap request is valid */ + return 1; +} + +/* + * Handler function for all ramzswap I/O requests. + */ +static int ramzswap_make_request(struct request_queue *queue, struct bio *bio) +{ + int ret = 0; + struct ramzswap *rzs = queue->queuedata; + + if (unlikely(!rzs->init_done)) { + bio_io_error(bio); + return 0; + } + + if (!valid_swap_request(rzs, bio)) { + stat_inc(rzs->stats.invalid_io); + bio_io_error(bio); + return 0; + } + + switch (bio_data_dir(bio)) { + case READ: + ret = ramzswap_read(rzs, bio); + break; + + case WRITE: + ret = ramzswap_write(rzs, bio); + break; + } + + return ret; +} + +static void reset_device(struct ramzswap *rzs) +{ + int is_backing_blkdev = 0; + size_t index, num_pages; + unsigned entries_per_page; + unsigned long num_table_pages, entry = 0; + + if (rzs->backing_swap && !rzs->num_extents) + is_backing_blkdev = 1; + + num_pages = rzs->disksize >> PAGE_SHIFT; + + /* Free various per-device buffers */ + kfree(rzs->compress_workmem); + free_pages((unsigned long)rzs->compress_buffer, 1); + + rzs->compress_workmem = NULL; + rzs->compress_buffer = NULL; + + /* Free all pages that are still in this ramzswap device */ + for (index = 0; index < num_pages; index++) { + struct page *page; + u16 offset; + + page = rzs->table[index].page; + offset = rzs->table[index].offset; + + if (!page) + continue; + + if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) + __free_page(page); + else + xv_free(rzs->mem_pool, page, offset); + } + + entries_per_page = PAGE_SIZE / sizeof(*rzs->table); + num_table_pages = DIV_ROUND_UP(num_pages * sizeof(*rzs->table), + PAGE_SIZE); + /* + * Set page->mapping to NULL for every table page. + * Otherwise, we will hit bad_page() during free. + */ + while (rzs->num_extents && num_table_pages--) { + struct page *page; + page = vmalloc_to_page(&rzs->table[entry]); + page->mapping = NULL; + entry += entries_per_page; + } + vfree(rzs->table); + rzs->table = NULL; + + xv_destroy_pool(rzs->mem_pool); + rzs->mem_pool = NULL; + + /* Free all swap extent pages */ + while (!list_empty(&rzs->backing_swap_extent_list)) { + struct page *page; + struct list_head *entry; + entry = rzs->backing_swap_extent_list.next; + page = list_entry(entry, struct page, lru); + list_del(entry); + __free_page(page); + } + INIT_LIST_HEAD(&rzs->backing_swap_extent_list); + rzs->num_extents = 0; + + /* Close backing swap device, if present */ + if (rzs->backing_swap) { + if (is_backing_blkdev) + bd_release(rzs->backing_swap); + filp_close(rzs->swap_file, NULL); + rzs->backing_swap = NULL; + } + + /* Reset stats */ + memset(&rzs->stats, 0, sizeof(rzs->stats)); + + rzs->disksize = 0; + rzs->memlimit = 0; + + /* Back to uninitialized state */ + rzs->init_done = 0; +} + +static int ramzswap_ioctl_init_device(struct ramzswap *rzs) +{ + int ret; + size_t num_pages; + struct page *page; + union swap_header *swap_header; + + if (rzs->init_done) { + pr_info("Device already initialized!\n"); + return -EBUSY; + } + + ret = setup_backing_swap(rzs); + if (ret) + goto fail; + + if (rzs->backing_swap) + ramzswap_set_memlimit(rzs, totalram_pages << PAGE_SHIFT); + else + ramzswap_set_disksize(rzs, totalram_pages << PAGE_SHIFT); + + rzs->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL); + if (!rzs->compress_workmem) { + pr_err("Error allocating compressor working memory!\n"); + ret = -ENOMEM; + goto fail; + } + + rzs->compress_buffer = (void *)__get_free_pages(__GFP_ZERO, 1); + if (!rzs->compress_buffer) { + pr_err("Error allocating compressor buffer space\n"); + ret = -ENOMEM; + goto fail; + } + + num_pages = rzs->disksize >> PAGE_SHIFT; + rzs->table = vmalloc(num_pages * sizeof(*rzs->table)); + if (!rzs->table) { + pr_err("Error allocating ramzswap address table\n"); + /* To prevent accessing table entries during cleanup */ + rzs->disksize = 0; + ret = -ENOMEM; + goto fail; + } + memset(rzs->table, 0, num_pages * sizeof(*rzs->table)); + + map_backing_swap_extents(rzs); + + page = alloc_page(__GFP_ZERO); + if (!page) { + pr_err("Error allocating swap header page\n"); + ret = -ENOMEM; + goto fail; + } + rzs->table[0].page = page; + rzs_set_flag(rzs, 0, RZS_UNCOMPRESSED); + + swap_header = kmap(page); + ret = setup_swap_header(rzs, swap_header); + kunmap(page); + if (ret) { + pr_err("Error setting swap header\n"); + goto fail; + } + + set_capacity(rzs->disk, rzs->disksize >> SECTOR_SHIFT); + + /* + * We have ident mapping of sectors for ramzswap and + * and the backing swap device. So, this queue flag + * should be according to backing dev. + */ + if (!rzs->backing_swap || + blk_queue_nonrot(rzs->backing_swap->bd_disk->queue)) + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, rzs->disk->queue); + + rzs->mem_pool = xv_create_pool(); + if (!rzs->mem_pool) { + pr_err("Error creating memory pool\n"); + ret = -ENOMEM; + goto fail; + } + + /* + * Pages that compress to size greater than this are forwarded + * to physical swap disk (if backing dev is provided) + * TODO: make this configurable + */ + if (rzs->backing_swap) + max_zpage_size = max_zpage_size_bdev; + else + max_zpage_size = max_zpage_size_nobdev; + pr_debug("Max compressed page size: %u bytes\n", max_zpage_size); + + rzs->init_done = 1; + + pr_debug("Initialization done!\n"); + return 0; + +fail: + reset_device(rzs); + + pr_err("Initialization failed: err=%d\n", ret); + return ret; +} + +static int ramzswap_ioctl_reset_device(struct ramzswap *rzs) +{ + if (rzs->init_done) + reset_device(rzs); + + return 0; +} + +static int ramzswap_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + int ret = 0; + size_t disksize_kb, memlimit_kb; + + struct ramzswap *rzs = bdev->bd_disk->private_data; + + switch (cmd) { + case RZSIO_SET_DISKSIZE_KB: + if (rzs->init_done) { + ret = -EBUSY; + goto out; + } + if (copy_from_user(&disksize_kb, (void *)arg, + _IOC_SIZE(cmd))) { + ret = -EFAULT; + goto out; + } + rzs->disksize = disksize_kb << 10; + pr_info("Disk size set to %zu kB\n", disksize_kb); + break; + + case RZSIO_SET_MEMLIMIT_KB: + if (rzs->init_done) { + /* TODO: allow changing memlimit */ + ret = -EBUSY; + goto out; + } + if (copy_from_user(&memlimit_kb, (void *)arg, + _IOC_SIZE(cmd))) { + ret = -EFAULT; + goto out; + } + rzs->memlimit = memlimit_kb << 10; + pr_info("Memory limit set to %zu kB\n", memlimit_kb); + break; + + case RZSIO_SET_BACKING_SWAP: + if (rzs->init_done) { + ret = -EBUSY; + goto out; + } + + if (copy_from_user(&rzs->backing_swap_name, (void *)arg, + _IOC_SIZE(cmd))) { + ret = -EFAULT; + goto out; + } + rzs->backing_swap_name[MAX_SWAP_NAME_LEN - 1] = '\0'; + pr_info("Backing swap set to %s\n", rzs->backing_swap_name); + break; + + case RZSIO_GET_STATS: + { + struct ramzswap_ioctl_stats *stats; + if (!rzs->init_done) { + ret = -ENOTTY; + goto out; + } + stats = kzalloc(sizeof(*stats), GFP_KERNEL); + if (!stats) { + ret = -ENOMEM; + goto out; + } + ramzswap_ioctl_get_stats(rzs, stats); + if (copy_to_user((void *)arg, stats, sizeof(*stats))) { + kfree(stats); + ret = -EFAULT; + goto out; + } + kfree(stats); + break; + } + case RZSIO_INIT: + ret = ramzswap_ioctl_init_device(rzs); + break; + + case RZSIO_RESET: + /* Do not reset an active device! */ + if (bdev->bd_holders) { + ret = -EBUSY; + goto out; + } + ret = ramzswap_ioctl_reset_device(rzs); + break; + + default: + pr_info("Invalid ioctl %u\n", cmd); + ret = -ENOTTY; + } + +out: + return ret; +} + +static struct block_device_operations ramzswap_devops = { + .ioctl = ramzswap_ioctl, + .owner = THIS_MODULE, +}; + +static void create_device(struct ramzswap *rzs, int device_id) +{ + mutex_init(&rzs->lock); + INIT_LIST_HEAD(&rzs->backing_swap_extent_list); + + rzs->queue = blk_alloc_queue(GFP_KERNEL); + if (!rzs->queue) { + pr_err("Error allocating disk queue for device %d\n", + device_id); + return; + } + + blk_queue_make_request(rzs->queue, ramzswap_make_request); + rzs->queue->queuedata = rzs; + + /* gendisk structure */ + rzs->disk = alloc_disk(1); + if (!rzs->disk) { + blk_cleanup_queue(rzs->queue); + pr_warning("Error allocating disk structure for device %d\n", + device_id); + return; + } + + rzs->disk->major = ramzswap_major; + rzs->disk->first_minor = device_id; + rzs->disk->fops = &ramzswap_devops; + rzs->disk->queue = rzs->queue; + rzs->disk->private_data = rzs; + snprintf(rzs->disk->disk_name, 16, "ramzswap%d", device_id); + + /* + * Actual capacity set using RZSIO_SET_DISKSIZE_KB ioctl + * or set equal to backing swap device (if provided) + */ + set_capacity(rzs->disk, 0); + add_disk(rzs->disk); + + rzs->init_done = 0; +} + +static void destroy_device(struct ramzswap *rzs) +{ + if (rzs->disk) { + del_gendisk(rzs->disk); + put_disk(rzs->disk); + } + + if (rzs->queue) + blk_cleanup_queue(rzs->queue); +} + +static int __init ramzswap_init(void) +{ + int i, ret; + + if (num_devices > max_num_devices) { + pr_warning("Invalid value for num_devices: %u\n", + num_devices); + return -EINVAL; + } + + ramzswap_major = register_blkdev(0, "ramzswap"); + if (ramzswap_major <= 0) { + pr_warning("Unable to get major number\n"); + return -EBUSY; + } + + if (!num_devices) { + pr_info("num_devices not specified. Using default: 1\n"); + num_devices = 1; + } + + /* Allocate the device array and initialize each one */ + pr_info("Creating %u devices ...\n", num_devices); + devices = kzalloc(num_devices * sizeof(struct ramzswap), GFP_KERNEL); + if (!devices) { + ret = -ENOMEM; + goto out; + } + + for (i = 0; i < num_devices; i++) + create_device(&devices[i], i); + + return 0; +out: + unregister_blkdev(ramzswap_major, "ramzswap"); + return ret; +} + +static void __exit ramzswap_exit(void) +{ + int i; + struct ramzswap *rzs; + + for (i = 0; i < num_devices; i++) { + rzs = &devices[i]; + + destroy_device(rzs); + if (rzs->init_done) + reset_device(rzs); + } + + unregister_blkdev(ramzswap_major, "ramzswap"); + + kfree(devices); + pr_debug("Cleanup done!\n"); +} + +module_param(num_devices, uint, 0); +MODULE_PARM_DESC(num_devices, "Number of ramzswap devices"); + +module_init(ramzswap_init); +module_exit(ramzswap_exit); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Nitin Gupta "); +MODULE_DESCRIPTION("Compressed RAM Based Swap Device"); diff --git a/drivers/staging/ramzswap/ramzswap_drv.h b/drivers/staging/ramzswap/ramzswap_drv.h new file mode 100644 index 0000000000000000000000000000000000000000..a6ea240935b66eb9459fb3e1d5f86d88dcced46e --- /dev/null +++ b/drivers/staging/ramzswap/ramzswap_drv.h @@ -0,0 +1,171 @@ +/* + * Compressed RAM based swap device + * + * Copyright (C) 2008, 2009 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + * + * Project home: http://compcache.googlecode.com + */ + +#ifndef _RAMZSWAP_DRV_H_ +#define _RAMZSWAP_DRV_H_ + +#include "ramzswap_ioctl.h" +#include "xvmalloc.h" + +/* + * Some arbitrary value. This is just to catch + * invalid value for num_devices module parameter. + */ +static const unsigned max_num_devices = 32; + +/* + * Stored at beginning of each compressed object. + * + * It stores back-reference to table entry which points to this + * object. This is required to support memory defragmentation or + * migrating compressed pages to backing swap disk. + */ +struct zobj_header { +#if 0 + u32 table_idx; +#endif +}; + +/*-- Configurable parameters */ + +/* Default ramzswap disk size: 25% of total RAM */ +static const unsigned default_disksize_perc_ram = 25; +static const unsigned default_memlimit_perc_ram = 15; + +/* + * Max compressed page size when backing device is provided. + * Pages that compress to size greater than this are sent to + * physical swap disk. + */ +static const unsigned max_zpage_size_bdev = PAGE_SIZE / 2; + +/* + * Max compressed page size when there is no backing dev. + * Pages that compress to size greater than this are stored + * uncompressed in memory. + */ +static const unsigned max_zpage_size_nobdev = PAGE_SIZE / 4 * 3; + +/* + * NOTE: max_zpage_size_{bdev,nobdev} sizes must be + * less than or equal to: + * XV_MAX_ALLOC_SIZE - sizeof(struct zobj_header) + * since otherwise xv_malloc would always return failure. + */ + +/*-- End of configurable params */ + +#define SECTOR_SHIFT 9 +#define SECTOR_SIZE (1 << SECTOR_SHIFT) +#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT) +#define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT) + +/* Debugging and Stats */ +#if defined(CONFIG_RAMZSWAP_STATS) +#define stat_inc(stat) ((stat)++) +#define stat_dec(stat) ((stat)--) +#else +#define stat_inc(x) +#define stat_dec(x) +#endif + +/* Flags for ramzswap pages (table[page_no].flags) */ +enum rzs_pageflags { + /* Page is stored uncompressed */ + RZS_UNCOMPRESSED, + + /* Page consists entirely of zeros */ + RZS_ZERO, + + __NR_RZS_PAGEFLAGS, +}; + +/*-- Data structures */ + +/* + * Allocated for each swap slot, indexed by page no. + * These table entries must fit exactly in a page. + */ +struct table { + struct page *page; + u16 offset; + u8 count; /* object ref count (not yet used) */ + u8 flags; +} __attribute__((aligned(4)));; + +/* + * Swap extent information in case backing swap is a regular + * file. These extent entries must fit exactly in a page. + */ +struct ramzswap_backing_extent { + pgoff_t phy_pagenum; + pgoff_t num_pages; +} __attribute__((aligned(4))); + +struct ramzswap_stats { + /* basic stats */ + size_t compr_size; /* compressed size of pages stored - + * needed to enforce memlimit */ + /* more stats */ +#if defined(CONFIG_RAMZSWAP_STATS) + u64 num_reads; /* failed + successful */ + u64 num_writes; /* --do-- */ + u64 failed_reads; /* can happen when memory is too low */ + u64 failed_writes; /* should NEVER! happen */ + u64 invalid_io; /* non-swap I/O requests */ + u32 pages_zero; /* no. of zero filled pages */ + u32 pages_stored; /* no. of pages currently stored */ + u32 good_compress; /* % of pages with compression ratio<=50% */ + u32 pages_expand; /* % of incompressible pages */ + u64 bdev_num_reads; /* no. of reads on backing dev */ + u64 bdev_num_writes; /* no. of writes on backing dev */ +#endif +}; + +struct ramzswap { + struct xv_pool *mem_pool; + void *compress_workmem; + void *compress_buffer; + struct table *table; + struct mutex lock; + struct request_queue *queue; + struct gendisk *disk; + int init_done; + /* + * This is limit on compressed data size (stats.compr_size) + * Its applicable only when backing swap device is present. + */ + size_t memlimit; /* bytes */ + /* + * This is limit on amount of *uncompressed* worth of data + * we can hold. When backing swap device is provided, it is + * set equal to device size. + */ + size_t disksize; /* bytes */ + + struct ramzswap_stats stats; + + /* backing swap device info */ + struct ramzswap_backing_extent *curr_extent; + struct list_head backing_swap_extent_list; + unsigned long num_extents; + char backing_swap_name[MAX_SWAP_NAME_LEN]; + struct block_device *backing_swap; + struct file *swap_file; +}; + +/*-- */ + +#endif + diff --git a/drivers/staging/ramzswap/ramzswap_ioctl.h b/drivers/staging/ramzswap/ramzswap_ioctl.h new file mode 100644 index 0000000000000000000000000000000000000000..c713a09af5809e695482b07ef5c7623133d23e88 --- /dev/null +++ b/drivers/staging/ramzswap/ramzswap_ioctl.h @@ -0,0 +1,49 @@ +/* + * Compressed RAM based swap device + * + * Copyright (C) 2008, 2009 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + * + * Project home: http://compcache.googlecode.com + */ + +#ifndef _RAMZSWAP_IOCTL_H_ +#define _RAMZSWAP_IOCTL_H_ + +#define MAX_SWAP_NAME_LEN 128 + +struct ramzswap_ioctl_stats { + char backing_swap_name[MAX_SWAP_NAME_LEN]; + u64 memlimit; /* only applicable if backing swap present */ + u64 disksize; /* user specified or equal to backing swap + * size (if present) */ + u64 num_reads; /* failed + successful */ + u64 num_writes; /* --do-- */ + u64 failed_reads; /* can happen when memory is too low */ + u64 failed_writes; /* should NEVER! happen */ + u64 invalid_io; /* non-swap I/O requests */ + u32 pages_zero; /* no. of zero filled pages */ + u32 good_compress_pct; /* no. of pages with compression ratio<=50% */ + u32 pages_expand_pct; /* no. of incompressible pages */ + u32 pages_stored; + u32 pages_used; + u64 orig_data_size; + u64 compr_data_size; + u64 mem_used_total; + u64 bdev_num_reads; /* no. of reads on backing dev */ + u64 bdev_num_writes; /* no. of writes on backing dev */ +} __attribute__ ((packed, aligned(4))); + +#define RZSIO_SET_DISKSIZE_KB _IOW('z', 0, size_t) +#define RZSIO_SET_MEMLIMIT_KB _IOW('z', 1, size_t) +#define RZSIO_SET_BACKING_SWAP _IOW('z', 2, unsigned char[MAX_SWAP_NAME_LEN]) +#define RZSIO_GET_STATS _IOR('z', 3, struct ramzswap_ioctl_stats) +#define RZSIO_INIT _IO('z', 4) +#define RZSIO_RESET _IO('z', 5) + +#endif diff --git a/drivers/staging/ramzswap/xvmalloc.c b/drivers/staging/ramzswap/xvmalloc.c new file mode 100644 index 0000000000000000000000000000000000000000..b3e986c33141115611269ae555893b2f8646d0ee --- /dev/null +++ b/drivers/staging/ramzswap/xvmalloc.c @@ -0,0 +1,507 @@ +/* + * xvmalloc memory allocator + * + * Copyright (C) 2008, 2009 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include "xvmalloc.h" +#include "xvmalloc_int.h" + +static void stat_inc(u64 *value) +{ + *value = *value + 1; +} + +static void stat_dec(u64 *value) +{ + *value = *value - 1; +} + +static int test_flag(struct block_header *block, enum blockflags flag) +{ + return block->prev & BIT(flag); +} + +static void set_flag(struct block_header *block, enum blockflags flag) +{ + block->prev |= BIT(flag); +} + +static void clear_flag(struct block_header *block, enum blockflags flag) +{ + block->prev &= ~BIT(flag); +} + +/* + * Given pair, provide a derefrencable pointer. + * This is called from xv_malloc/xv_free path, so it + * needs to be fast. + */ +static void *get_ptr_atomic(struct page *page, u16 offset, enum km_type type) +{ + unsigned char *base; + + base = kmap_atomic(page, type); + return base + offset; +} + +static void put_ptr_atomic(void *ptr, enum km_type type) +{ + kunmap_atomic(ptr, type); +} + +static u32 get_blockprev(struct block_header *block) +{ + return block->prev & PREV_MASK; +} + +static void set_blockprev(struct block_header *block, u16 new_offset) +{ + block->prev = new_offset | (block->prev & FLAGS_MASK); +} + +static struct block_header *BLOCK_NEXT(struct block_header *block) +{ + return (struct block_header *) + ((char *)block + block->size + XV_ALIGN); +} + +/* + * Get index of free list containing blocks of maximum size + * which is less than or equal to given size. + */ +static u32 get_index_for_insert(u32 size) +{ + if (unlikely(size > XV_MAX_ALLOC_SIZE)) + size = XV_MAX_ALLOC_SIZE; + size &= ~FL_DELTA_MASK; + return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT; +} + +/* + * Get index of free list having blocks of size greater than + * or equal to requested size. + */ +static u32 get_index(u32 size) +{ + if (unlikely(size < XV_MIN_ALLOC_SIZE)) + size = XV_MIN_ALLOC_SIZE; + size = ALIGN(size, FL_DELTA); + return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT; +} + +/** + * find_block - find block of at least given size + * @pool: memory pool to search from + * @size: size of block required + * @page: page containing required block + * @offset: offset within the page where block is located. + * + * Searches two level bitmap to locate block of at least + * the given size. If such a block is found, it provides + * to identify this block and returns index + * in freelist where we found this block. + * Otherwise, returns 0 and params are not touched. + */ +static u32 find_block(struct xv_pool *pool, u32 size, + struct page **page, u32 *offset) +{ + ulong flbitmap, slbitmap; + u32 flindex, slindex, slbitstart; + + /* There are no free blocks in this pool */ + if (!pool->flbitmap) + return 0; + + /* Get freelist index correspoding to this size */ + slindex = get_index(size); + slbitmap = pool->slbitmap[slindex / BITS_PER_LONG]; + slbitstart = slindex % BITS_PER_LONG; + + /* + * If freelist is not empty at this index, we found the + * block - head of this list. This is approximate best-fit match. + */ + if (test_bit(slbitstart, &slbitmap)) { + *page = pool->freelist[slindex].page; + *offset = pool->freelist[slindex].offset; + return slindex; + } + + /* + * No best-fit found. Search a bit further in bitmap for a free block. + * Second level bitmap consists of series of 32-bit chunks. Search + * further in the chunk where we expected a best-fit, starting from + * index location found above. + */ + slbitstart++; + slbitmap >>= slbitstart; + + /* Skip this search if we were already at end of this bitmap chunk */ + if ((slbitstart != BITS_PER_LONG) && slbitmap) { + slindex += __ffs(slbitmap) + 1; + *page = pool->freelist[slindex].page; + *offset = pool->freelist[slindex].offset; + return slindex; + } + + /* Now do a full two-level bitmap search to find next nearest fit */ + flindex = slindex / BITS_PER_LONG; + + flbitmap = (pool->flbitmap) >> (flindex + 1); + if (!flbitmap) + return 0; + + flindex += __ffs(flbitmap) + 1; + slbitmap = pool->slbitmap[flindex]; + slindex = (flindex * BITS_PER_LONG) + __ffs(slbitmap); + *page = pool->freelist[slindex].page; + *offset = pool->freelist[slindex].offset; + + return slindex; +} + +/* + * Insert block at in freelist of given pool. + * freelist used depends on block size. + */ +static void insert_block(struct xv_pool *pool, struct page *page, u32 offset, + struct block_header *block) +{ + u32 flindex, slindex; + struct block_header *nextblock; + + slindex = get_index_for_insert(block->size); + flindex = slindex / BITS_PER_LONG; + + block->link.prev_page = 0; + block->link.prev_offset = 0; + block->link.next_page = pool->freelist[slindex].page; + block->link.next_offset = pool->freelist[slindex].offset; + pool->freelist[slindex].page = page; + pool->freelist[slindex].offset = offset; + + if (block->link.next_page) { + nextblock = get_ptr_atomic(block->link.next_page, + block->link.next_offset, KM_USER1); + nextblock->link.prev_page = page; + nextblock->link.prev_offset = offset; + put_ptr_atomic(nextblock, KM_USER1); + } + + __set_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]); + __set_bit(flindex, &pool->flbitmap); +} + +/* + * Remove block from head of freelist. Index 'slindex' identifies the freelist. + */ +static void remove_block_head(struct xv_pool *pool, + struct block_header *block, u32 slindex) +{ + struct block_header *tmpblock; + u32 flindex = slindex / BITS_PER_LONG; + + pool->freelist[slindex].page = block->link.next_page; + pool->freelist[slindex].offset = block->link.next_offset; + block->link.prev_page = 0; + block->link.prev_offset = 0; + + if (!pool->freelist[slindex].page) { + __clear_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]); + if (!pool->slbitmap[flindex]) + __clear_bit(flindex, &pool->flbitmap); + } else { + /* + * DEBUG ONLY: We need not reinitialize freelist head previous + * pointer to 0 - we never depend on its value. But just for + * sanity, lets do it. + */ + tmpblock = get_ptr_atomic(pool->freelist[slindex].page, + pool->freelist[slindex].offset, KM_USER1); + tmpblock->link.prev_page = 0; + tmpblock->link.prev_offset = 0; + put_ptr_atomic(tmpblock, KM_USER1); + } +} + +/* + * Remove block from freelist. Index 'slindex' identifies the freelist. + */ +static void remove_block(struct xv_pool *pool, struct page *page, u32 offset, + struct block_header *block, u32 slindex) +{ + u32 flindex; + struct block_header *tmpblock; + + if (pool->freelist[slindex].page == page + && pool->freelist[slindex].offset == offset) { + remove_block_head(pool, block, slindex); + return; + } + + flindex = slindex / BITS_PER_LONG; + + if (block->link.prev_page) { + tmpblock = get_ptr_atomic(block->link.prev_page, + block->link.prev_offset, KM_USER1); + tmpblock->link.next_page = block->link.next_page; + tmpblock->link.next_offset = block->link.next_offset; + put_ptr_atomic(tmpblock, KM_USER1); + } + + if (block->link.next_page) { + tmpblock = get_ptr_atomic(block->link.next_page, + block->link.next_offset, KM_USER1); + tmpblock->link.prev_page = block->link.prev_page; + tmpblock->link.prev_offset = block->link.prev_offset; + put_ptr_atomic(tmpblock, KM_USER1); + } +} + +/* + * Allocate a page and add it freelist of given pool. + */ +static int grow_pool(struct xv_pool *pool, gfp_t flags) +{ + struct page *page; + struct block_header *block; + + page = alloc_page(flags); + if (unlikely(!page)) + return -ENOMEM; + + stat_inc(&pool->total_pages); + + spin_lock(&pool->lock); + block = get_ptr_atomic(page, 0, KM_USER0); + + block->size = PAGE_SIZE - XV_ALIGN; + set_flag(block, BLOCK_FREE); + clear_flag(block, PREV_FREE); + set_blockprev(block, 0); + + insert_block(pool, page, 0, block); + + put_ptr_atomic(block, KM_USER0); + spin_unlock(&pool->lock); + + return 0; +} + +/* + * Create a memory pool. Allocates freelist, bitmaps and other + * per-pool metadata. + */ +struct xv_pool *xv_create_pool(void) +{ + u32 ovhd_size; + struct xv_pool *pool; + + ovhd_size = roundup(sizeof(*pool), PAGE_SIZE); + pool = kzalloc(ovhd_size, GFP_KERNEL); + if (!pool) + return NULL; + + spin_lock_init(&pool->lock); + + return pool; +} + +void xv_destroy_pool(struct xv_pool *pool) +{ + kfree(pool); +} + +/** + * xv_malloc - Allocate block of given size from pool. + * @pool: pool to allocate from + * @size: size of block to allocate + * @page: page no. that holds the object + * @offset: location of object within page + * + * On success, identifies block allocated + * and 0 is returned. On failure, is set to + * 0 and -ENOMEM is returned. + * + * Allocation requests with size > XV_MAX_ALLOC_SIZE will fail. + */ +int xv_malloc(struct xv_pool *pool, u32 size, struct page **page, + u32 *offset, gfp_t flags) +{ + int error; + u32 index, tmpsize, origsize, tmpoffset; + struct block_header *block, *tmpblock; + + *page = NULL; + *offset = 0; + origsize = size; + + if (unlikely(!size || size > XV_MAX_ALLOC_SIZE)) + return -ENOMEM; + + size = ALIGN(size, XV_ALIGN); + + spin_lock(&pool->lock); + + index = find_block(pool, size, page, offset); + + if (!*page) { + spin_unlock(&pool->lock); + if (flags & GFP_NOWAIT) + return -ENOMEM; + error = grow_pool(pool, flags); + if (unlikely(error)) + return error; + + spin_lock(&pool->lock); + index = find_block(pool, size, page, offset); + } + + if (!*page) { + spin_unlock(&pool->lock); + return -ENOMEM; + } + + block = get_ptr_atomic(*page, *offset, KM_USER0); + + remove_block_head(pool, block, index); + + /* Split the block if required */ + tmpoffset = *offset + size + XV_ALIGN; + tmpsize = block->size - size; + tmpblock = (struct block_header *)((char *)block + size + XV_ALIGN); + if (tmpsize) { + tmpblock->size = tmpsize - XV_ALIGN; + set_flag(tmpblock, BLOCK_FREE); + clear_flag(tmpblock, PREV_FREE); + + set_blockprev(tmpblock, *offset); + if (tmpblock->size >= XV_MIN_ALLOC_SIZE) + insert_block(pool, *page, tmpoffset, tmpblock); + + if (tmpoffset + XV_ALIGN + tmpblock->size != PAGE_SIZE) { + tmpblock = BLOCK_NEXT(tmpblock); + set_blockprev(tmpblock, tmpoffset); + } + } else { + /* This block is exact fit */ + if (tmpoffset != PAGE_SIZE) + clear_flag(tmpblock, PREV_FREE); + } + + block->size = origsize; + clear_flag(block, BLOCK_FREE); + + put_ptr_atomic(block, KM_USER0); + spin_unlock(&pool->lock); + + *offset += XV_ALIGN; + + return 0; +} + +/* + * Free block identified with + */ +void xv_free(struct xv_pool *pool, struct page *page, u32 offset) +{ + void *page_start; + struct block_header *block, *tmpblock; + + offset -= XV_ALIGN; + + spin_lock(&pool->lock); + + page_start = get_ptr_atomic(page, 0, KM_USER0); + block = (struct block_header *)((char *)page_start + offset); + + /* Catch double free bugs */ + BUG_ON(test_flag(block, BLOCK_FREE)); + + block->size = ALIGN(block->size, XV_ALIGN); + + tmpblock = BLOCK_NEXT(block); + if (offset + block->size + XV_ALIGN == PAGE_SIZE) + tmpblock = NULL; + + /* Merge next block if its free */ + if (tmpblock && test_flag(tmpblock, BLOCK_FREE)) { + /* + * Blocks smaller than XV_MIN_ALLOC_SIZE + * are not inserted in any free list. + */ + if (tmpblock->size >= XV_MIN_ALLOC_SIZE) { + remove_block(pool, page, + offset + block->size + XV_ALIGN, tmpblock, + get_index_for_insert(tmpblock->size)); + } + block->size += tmpblock->size + XV_ALIGN; + } + + /* Merge previous block if its free */ + if (test_flag(block, PREV_FREE)) { + tmpblock = (struct block_header *)((char *)(page_start) + + get_blockprev(block)); + offset = offset - tmpblock->size - XV_ALIGN; + + if (tmpblock->size >= XV_MIN_ALLOC_SIZE) + remove_block(pool, page, offset, tmpblock, + get_index_for_insert(tmpblock->size)); + + tmpblock->size += block->size + XV_ALIGN; + block = tmpblock; + } + + /* No used objects in this page. Free it. */ + if (block->size == PAGE_SIZE - XV_ALIGN) { + put_ptr_atomic(page_start, KM_USER0); + spin_unlock(&pool->lock); + + __free_page(page); + stat_dec(&pool->total_pages); + return; + } + + set_flag(block, BLOCK_FREE); + if (block->size >= XV_MIN_ALLOC_SIZE) + insert_block(pool, page, offset, block); + + if (offset + block->size + XV_ALIGN != PAGE_SIZE) { + tmpblock = BLOCK_NEXT(block); + set_flag(tmpblock, PREV_FREE); + set_blockprev(tmpblock, offset); + } + + put_ptr_atomic(page_start, KM_USER0); + spin_unlock(&pool->lock); +} + +u32 xv_get_object_size(void *obj) +{ + struct block_header *blk; + + blk = (struct block_header *)((char *)(obj) - XV_ALIGN); + return blk->size; +} + +/* + * Returns total memory used by allocator (userdata + metadata) + */ +u64 xv_get_total_size_bytes(struct xv_pool *pool) +{ + return pool->total_pages << PAGE_SHIFT; +} diff --git a/drivers/staging/ramzswap/xvmalloc.h b/drivers/staging/ramzswap/xvmalloc.h new file mode 100644 index 0000000000000000000000000000000000000000..010c6fe5e1732afdc2b3086ec6d2855ed0c41005 --- /dev/null +++ b/drivers/staging/ramzswap/xvmalloc.h @@ -0,0 +1,30 @@ +/* + * xvmalloc memory allocator + * + * Copyright (C) 2008, 2009 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + */ + +#ifndef _XV_MALLOC_H_ +#define _XV_MALLOC_H_ + +#include + +struct xv_pool; + +struct xv_pool *xv_create_pool(void); +void xv_destroy_pool(struct xv_pool *pool); + +int xv_malloc(struct xv_pool *pool, u32 size, struct page **page, + u32 *offset, gfp_t flags); +void xv_free(struct xv_pool *pool, struct page *page, u32 offset); + +u32 xv_get_object_size(void *obj); +u64 xv_get_total_size_bytes(struct xv_pool *pool); + +#endif diff --git a/drivers/staging/ramzswap/xvmalloc_int.h b/drivers/staging/ramzswap/xvmalloc_int.h new file mode 100644 index 0000000000000000000000000000000000000000..03c1a652a3aaf0d01245a0b0765f30a74685d98d --- /dev/null +++ b/drivers/staging/ramzswap/xvmalloc_int.h @@ -0,0 +1,86 @@ +/* + * xvmalloc memory allocator + * + * Copyright (C) 2008, 2009 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + */ + +#ifndef _XV_MALLOC_INT_H_ +#define _XV_MALLOC_INT_H_ + +#include +#include + +/* User configurable params */ + +/* Must be power of two */ +#define XV_ALIGN_SHIFT 2 +#define XV_ALIGN (1 << XV_ALIGN_SHIFT) +#define XV_ALIGN_MASK (XV_ALIGN - 1) + +/* This must be greater than sizeof(link_free) */ +#define XV_MIN_ALLOC_SIZE 32 +#define XV_MAX_ALLOC_SIZE (PAGE_SIZE - XV_ALIGN) + +/* Free lists are separated by FL_DELTA bytes */ +#define FL_DELTA_SHIFT 3 +#define FL_DELTA (1 << FL_DELTA_SHIFT) +#define FL_DELTA_MASK (FL_DELTA - 1) +#define NUM_FREE_LISTS ((XV_MAX_ALLOC_SIZE - XV_MIN_ALLOC_SIZE) \ + / FL_DELTA + 1) + +#define MAX_FLI DIV_ROUND_UP(NUM_FREE_LISTS, BITS_PER_LONG) + +/* End of user params */ + +enum blockflags { + BLOCK_FREE, + PREV_FREE, + __NR_BLOCKFLAGS, +}; + +#define FLAGS_MASK XV_ALIGN_MASK +#define PREV_MASK (~FLAGS_MASK) + +struct freelist_entry { + struct page *page; + u16 offset; + u16 pad; +}; + +struct link_free { + struct page *prev_page; + struct page *next_page; + u16 prev_offset; + u16 next_offset; +}; + +struct block_header { + union { + /* This common header must be ALIGN bytes */ + u8 common[XV_ALIGN]; + struct { + u16 size; + u16 prev; + }; + }; + struct link_free link; +}; + +struct xv_pool { + ulong flbitmap; + ulong slbitmap[MAX_FLI]; + spinlock_t lock; + + struct freelist_entry freelist[NUM_FREE_LISTS]; + + /* stats */ + u64 total_pages; +}; + +#endif diff --git a/drivers/staging/rar/rar_driver.c b/drivers/staging/rar/rar_driver.c index 9805d74bd3411a168d97f02931251f662576f93d..d85d1890e81e1d4bb09a06918c0d3319afc676f4 100644 --- a/drivers/staging/rar/rar_driver.c +++ b/drivers/staging/rar/rar_driver.c @@ -66,7 +66,7 @@ static int __init rar_init_handler(void); static void __exit rar_exit_handler(void); /* - function that is activated on the succesfull probe of the RAR device + function that is activated on the successfull probe of the RAR device */ static int __devinit rar_probe(struct pci_dev *pdev, const struct pci_device_id *ent); @@ -319,7 +319,7 @@ static int memrar_init_rar_params(struct pci_dev *pdev) } /* - function that is activaed on the succesfull probe of the RAR device + function that is activated on the successfull probe of the RAR device */ static int __devinit rar_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { diff --git a/drivers/staging/rt2860/2860_main_dev.c b/drivers/staging/rt2860/2860_main_dev.c deleted file mode 100644 index c2f02963f91ca148c341e8986a20e0992075bfd0..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2860/2860_main_dev.c +++ /dev/null @@ -1,1319 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - 2870_main_dev.c - - Abstract: - Create and register network interface. - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#include "rt_config.h" - -extern INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p, - IN UINT argc, OUT PRTMP_ADAPTER *ppAd); - -static void rx_done_tasklet(unsigned long data); -static void mgmt_dma_done_tasklet(unsigned long data); -static void ac0_dma_done_tasklet(unsigned long data); -static void ac1_dma_done_tasklet(unsigned long data); -static void ac2_dma_done_tasklet(unsigned long data); -static void ac3_dma_done_tasklet(unsigned long data); -static void hcca_dma_done_tasklet(unsigned long data); -static void fifo_statistic_full_tasklet(unsigned long data); - - -/*---------------------------------------------------------------------*/ -/* Symbol & Macro Definitions */ -/*---------------------------------------------------------------------*/ -#define RT2860_INT_RX_DLY (1<<0) // bit 0 -#define RT2860_INT_TX_DLY (1<<1) // bit 1 -#define RT2860_INT_RX_DONE (1<<2) // bit 2 -#define RT2860_INT_AC0_DMA_DONE (1<<3) // bit 3 -#define RT2860_INT_AC1_DMA_DONE (1<<4) // bit 4 -#define RT2860_INT_AC2_DMA_DONE (1<<5) // bit 5 -#define RT2860_INT_AC3_DMA_DONE (1<<6) // bit 6 -#define RT2860_INT_HCCA_DMA_DONE (1<<7) // bit 7 -#define RT2860_INT_MGMT_DONE (1<<8) // bit 8 - -#define INT_RX RT2860_INT_RX_DONE - -#define INT_AC0_DLY (RT2860_INT_AC0_DMA_DONE) //| RT2860_INT_TX_DLY) -#define INT_AC1_DLY (RT2860_INT_AC1_DMA_DONE) //| RT2860_INT_TX_DLY) -#define INT_AC2_DLY (RT2860_INT_AC2_DMA_DONE) //| RT2860_INT_TX_DLY) -#define INT_AC3_DLY (RT2860_INT_AC3_DMA_DONE) //| RT2860_INT_TX_DLY) -#define INT_HCCA_DLY (RT2860_INT_HCCA_DMA_DONE) //| RT2860_INT_TX_DLY) -#define INT_MGMT_DLY RT2860_INT_MGMT_DONE - -/*---------------------------------------------------------------------*/ -/* Prototypes of Functions Used */ -/*---------------------------------------------------------------------*/ -/* function declarations */ -static INT __devinit rt2860_init_one (struct pci_dev *pci_dev, const struct pci_device_id *ent); -static VOID __devexit rt2860_remove_one(struct pci_dev *pci_dev); -static INT __devinit rt2860_probe(struct pci_dev *pci_dev, const struct pci_device_id *ent); -void init_thread_task(PRTMP_ADAPTER pAd); -static void __exit rt2860_cleanup_module(void); -static int __init rt2860_init_module(void); - -#ifdef CONFIG_PM -static int rt2860_suspend(struct pci_dev *pci_dev, pm_message_t state); -static int rt2860_resume(struct pci_dev *pci_dev); -#endif // CONFIG_PM // - - -// -// Ralink PCI device table, include all supported chipsets -// -static struct pci_device_id rt2860_pci_tbl[] __devinitdata = -{ - {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCI_DEVICE_ID)}, //RT28602.4G - {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCIe_DEVICE_ID)}, - {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2760_PCI_DEVICE_ID)}, - {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2790_PCIe_DEVICE_ID)}, - {PCI_DEVICE(VEN_AWT_PCI_VENDOR_ID, VEN_AWT_PCIe_DEVICE_ID)}, - {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7708)}, - {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7728)}, - {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7758)}, - {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7727)}, - {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7738)}, - {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7748)}, - {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7768)}, - {0,} // terminate list -}; - -MODULE_DEVICE_TABLE(pci, rt2860_pci_tbl); -MODULE_LICENSE("GPL"); -#ifdef MODULE_VERSION -MODULE_VERSION(STA_DRIVER_VERSION); -#endif - -// -// Our PCI driver structure -// -static struct pci_driver rt2860_driver = -{ - name: "rt2860", - id_table: rt2860_pci_tbl, - probe: rt2860_init_one, - remove: __devexit_p(rt2860_remove_one), - -#ifdef CONFIG_PM - suspend: rt2860_suspend, - resume: rt2860_resume, -#endif -}; - - -#ifdef CONFIG_PM - -VOID RT2860RejectPendingPackets( - IN PRTMP_ADAPTER pAd) -{ - // clear PS packets - // clear TxSw packets -} - -static int rt2860_suspend( - struct pci_dev *pci_dev, - pm_message_t state) -{ - struct net_device *net_dev = pci_get_drvdata(pci_dev); - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)NULL; - INT32 retval; - - - DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_suspend()\n")); - - if (net_dev == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n")); - } - else - { - pAd = net_dev->ml_priv; - - /* we can not use IFF_UP because ra0 down but ra1 up */ - /* and 1 suspend/resume function for 1 module, not for each interface */ - /* so Linux will call suspend/resume function once */ - if (VIRTUAL_IF_NUM(pAd) > 0) - { - // avoid users do suspend after interface is down - - // stop interface - netif_carrier_off(net_dev); - netif_stop_queue(net_dev); - - // mark device as removed from system and therefore no longer available - netif_device_detach(net_dev); - - // mark halt flag - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - - // take down the device - rt28xx_close((PNET_DEV)net_dev); - - RT_MOD_DEC_USE_COUNT(); - } - } - - // reference to http://vovo2000.com/type-lab/linux/kernel-api/linux-kernel-api.html - // enable device to generate PME# when suspended - // pci_choose_state(): Choose the power state of a PCI device to be suspended - retval = pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1); - // save the PCI configuration space of a device before suspending - pci_save_state(pci_dev); - // disable PCI device after use - pci_disable_device(pci_dev); - - retval = pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); - - DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_suspend()\n")); - return retval; -} - -static int rt2860_resume( - struct pci_dev *pci_dev) -{ - struct net_device *net_dev = pci_get_drvdata(pci_dev); - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)NULL; - INT32 retval; - - - // set the power state of a PCI device - // PCI has 4 power states, DO (normal) ~ D3(less power) - // in include/linux/pci.h, you can find that - // #define PCI_D0 ((pci_power_t __force) 0) - // #define PCI_D1 ((pci_power_t __force) 1) - // #define PCI_D2 ((pci_power_t __force) 2) - // #define PCI_D3hot ((pci_power_t __force) 3) - // #define PCI_D3cold ((pci_power_t __force) 4) - // #define PCI_UNKNOWN ((pci_power_t __force) 5) - // #define PCI_POWER_ERROR ((pci_power_t __force) -1) - retval = pci_set_power_state(pci_dev, PCI_D0); - - // restore the saved state of a PCI device - pci_restore_state(pci_dev); - - // initialize device before it's used by a driver - if (pci_enable_device(pci_dev)) - { - printk("pci enable fail!\n"); - return 0; - } - - DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_resume()\n")); - - if (net_dev == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n")); - } - else - pAd = net_dev->ml_priv; - - if (pAd != NULL) - { - /* we can not use IFF_UP because ra0 down but ra1 up */ - /* and 1 suspend/resume function for 1 module, not for each interface */ - /* so Linux will call suspend/resume function once */ - if (VIRTUAL_IF_NUM(pAd) > 0) - { - // mark device as attached from system and restart if needed - netif_device_attach(net_dev); - - if (rt28xx_open((PNET_DEV)net_dev) != 0) - { - // open fail - DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_resume()\n")); - return 0; - } - - // increase MODULE use count - RT_MOD_INC_USE_COUNT(); - - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - - netif_start_queue(net_dev); - netif_carrier_on(net_dev); - netif_wake_queue(net_dev); - } - } - - DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_resume()\n")); - return 0; -} -#endif // CONFIG_PM // - - -static INT __init rt2860_init_module(VOID) -{ - return pci_register_driver(&rt2860_driver); -} - - -// -// Driver module unload function -// -static VOID __exit rt2860_cleanup_module(VOID) -{ - pci_unregister_driver(&rt2860_driver); -} - -module_init(rt2860_init_module); -module_exit(rt2860_cleanup_module); - - -static INT __devinit rt2860_init_one ( - IN struct pci_dev *pci_dev, - IN const struct pci_device_id *ent) -{ - INT rc; - - DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_init_one\n")); - - // wake up and enable device - if (pci_enable_device (pci_dev)) - { - rc = -EIO; - } - else - { - rc = rt2860_probe(pci_dev, ent); - } - - DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_init_one\n")); - return rc; -} - - -static VOID __devexit rt2860_remove_one( - IN struct pci_dev *pci_dev) -{ - struct net_device *net_dev = pci_get_drvdata(pci_dev); - RTMP_ADAPTER *pAd = net_dev->ml_priv; - - DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_remove_one\n")); - - if (pAd != NULL) - { - // Unregister network device - unregister_netdev(net_dev); - - // Unmap CSR base address - iounmap((char *)(net_dev->base_addr)); - - RTMPFreeAdapter(pAd); - - // release memory region - release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); - } - else - { - // Unregister network device - unregister_netdev(net_dev); - - // Unmap CSR base address - iounmap((char *)(net_dev->base_addr)); - - // release memory region - release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); - } - - // Free pre-allocated net_device memory - free_netdev(net_dev); -} - -// -// PCI device probe & initialization function -// -static INT __devinit rt2860_probe( - IN struct pci_dev *pci_dev, - IN const struct pci_device_id *ent) -{ - PRTMP_ADAPTER pAd; - INT rv = 0; - - rv = (INT)rt28xx_probe((void *)pci_dev, (void *)ent, 0, &pAd); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE); - return rv; -} - - -void init_thread_task(IN PRTMP_ADAPTER pAd) -{ - POS_COOKIE pObj; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - tasklet_init(&pObj->rx_done_task, rx_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->mgmt_dma_done_task, mgmt_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->ac0_dma_done_task, ac0_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->ac1_dma_done_task, ac1_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->ac2_dma_done_task, ac2_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->ac3_dma_done_task, ac3_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->hcca_dma_done_task, hcca_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->tbtt_task, tbtt_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->fifo_statistic_full_task, fifo_statistic_full_tasklet, (unsigned long)pAd); -} - -void kill_thread_task(IN PRTMP_ADAPTER pAd) -{ - POS_COOKIE pObj; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - tasklet_kill(&pObj->rx_done_task); - tasklet_kill(&pObj->mgmt_dma_done_task); - tasklet_kill(&pObj->ac0_dma_done_task); - tasklet_kill(&pObj->ac1_dma_done_task); - tasklet_kill(&pObj->ac2_dma_done_task); - tasklet_kill(&pObj->ac3_dma_done_task); - tasklet_kill(&pObj->hcca_dma_done_task); - tasklet_kill(&pObj->tbtt_task); - tasklet_kill(&pObj->fifo_statistic_full_task); -} - - -static void rt2860_int_enable(PRTMP_ADAPTER pAd, unsigned int mode) -{ - u32 regValue; - - pAd->int_disable_mask &= ~(mode); - regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask); - RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); // 1:enable - - if (regValue != 0) - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE); -} - - -static void rt2860_int_disable(PRTMP_ADAPTER pAd, unsigned int mode) -{ - u32 regValue; - - pAd->int_disable_mask |= mode; - regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask); - RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); // 0: disable - - if (regValue == 0) - { - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE); - } -} - -static void mgmt_dma_done_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - INT_SOURCE_CSR_STRUC IntSource; - POS_COOKIE pObj; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - IntSource.word = 0; - IntSource.field.MgmtDmaDone = 1; - pAd->int_pending &= ~INT_MGMT_DLY; - - RTMPHandleMgmtRingDmaDoneInterrupt(pAd); - - // if you use RTMP_SEM_LOCK, sometimes kernel will hang up, no any - // bug report output - RTMP_INT_LOCK(&pAd->irq_lock, flags); - /* - * double check to avoid lose of interrupts - */ - if (pAd->int_pending & INT_MGMT_DLY) - { - tasklet_hi_schedule(&pObj->mgmt_dma_done_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable TxDataInt again */ - rt2860_int_enable(pAd, INT_MGMT_DLY); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); -} - -static void rx_done_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - BOOLEAN bReschedule = 0; - POS_COOKIE pObj; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - pAd->int_pending &= ~(INT_RX); - - bReschedule = STARxDoneInterruptHandle(pAd, 0); - - RTMP_INT_LOCK(&pAd->irq_lock, flags); - /* - * double check to avoid rotting packet - */ - if (pAd->int_pending & INT_RX || bReschedule) - { - tasklet_hi_schedule(&pObj->rx_done_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable RxINT again */ - rt2860_int_enable(pAd, INT_RX); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - -} - -void fifo_statistic_full_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - POS_COOKIE pObj; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - pAd->int_pending &= ~(FifoStaFullInt); - NICUpdateFifoStaCounters(pAd); - - RTMP_INT_LOCK(&pAd->irq_lock, flags); - /* - * double check to avoid rotting packet - */ - if (pAd->int_pending & FifoStaFullInt) - { - tasklet_hi_schedule(&pObj->fifo_statistic_full_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable RxINT again */ - - rt2860_int_enable(pAd, FifoStaFullInt); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - -} - -static void hcca_dma_done_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - INT_SOURCE_CSR_STRUC IntSource; - POS_COOKIE pObj; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - - IntSource.word = 0; - IntSource.field.HccaDmaDone = 1; - pAd->int_pending &= ~INT_HCCA_DLY; - - RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); - - RTMP_INT_LOCK(&pAd->irq_lock, flags); - /* - * double check to avoid lose of interrupts - */ - if (pAd->int_pending & INT_HCCA_DLY) - { - tasklet_hi_schedule(&pObj->hcca_dma_done_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable TxDataInt again */ - rt2860_int_enable(pAd, INT_HCCA_DLY); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); -} - -static void ac3_dma_done_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - INT_SOURCE_CSR_STRUC IntSource; - POS_COOKIE pObj; - BOOLEAN bReschedule = 0; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - IntSource.word = 0; - IntSource.field.Ac3DmaDone = 1; - pAd->int_pending &= ~INT_AC3_DLY; - - bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); - - RTMP_INT_LOCK(&pAd->irq_lock, flags); - /* - * double check to avoid lose of interrupts - */ - if ((pAd->int_pending & INT_AC3_DLY) || bReschedule) - { - tasklet_hi_schedule(&pObj->ac3_dma_done_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable TxDataInt again */ - rt2860_int_enable(pAd, INT_AC3_DLY); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); -} - -static void ac2_dma_done_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - INT_SOURCE_CSR_STRUC IntSource; - POS_COOKIE pObj; - BOOLEAN bReschedule = 0; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - IntSource.word = 0; - IntSource.field.Ac2DmaDone = 1; - pAd->int_pending &= ~INT_AC2_DLY; - - bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); - - RTMP_INT_LOCK(&pAd->irq_lock, flags); - - /* - * double check to avoid lose of interrupts - */ - if ((pAd->int_pending & INT_AC2_DLY) || bReschedule) - { - tasklet_hi_schedule(&pObj->ac2_dma_done_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable TxDataInt again */ - rt2860_int_enable(pAd, INT_AC2_DLY); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); -} - -static void ac1_dma_done_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - INT_SOURCE_CSR_STRUC IntSource; - POS_COOKIE pObj; - BOOLEAN bReschedule = 0; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - IntSource.word = 0; - IntSource.field.Ac1DmaDone = 1; - pAd->int_pending &= ~INT_AC1_DLY; - - bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); - - RTMP_INT_LOCK(&pAd->irq_lock, flags); - /* - * double check to avoid lose of interrupts - */ - if ((pAd->int_pending & INT_AC1_DLY) || bReschedule) - { - tasklet_hi_schedule(&pObj->ac1_dma_done_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable TxDataInt again */ - rt2860_int_enable(pAd, INT_AC1_DLY); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); -} - -static void ac0_dma_done_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - INT_SOURCE_CSR_STRUC IntSource; - POS_COOKIE pObj; - BOOLEAN bReschedule = 0; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - IntSource.word = 0; - IntSource.field.Ac0DmaDone = 1; - pAd->int_pending &= ~INT_AC0_DLY; - - bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); - - RTMP_INT_LOCK(&pAd->irq_lock, flags); - /* - * double check to avoid lose of interrupts - */ - if ((pAd->int_pending & INT_AC0_DLY) || bReschedule) - { - tasklet_hi_schedule(&pObj->ac0_dma_done_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable TxDataInt again */ - rt2860_int_enable(pAd, INT_AC0_DLY); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); -} - - -int print_int_count; - -IRQ_HANDLE_TYPE -rt2860_interrupt(int irq, void *dev_instance) -{ - struct net_device *net_dev = (struct net_device *) dev_instance; - PRTMP_ADAPTER pAd = net_dev->ml_priv; - INT_SOURCE_CSR_STRUC IntSource; - POS_COOKIE pObj; - BOOLEAN bOldValue; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - - /* Note 03312008: we can not return here before - RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word); - RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word); - Or kernel will panic after ifconfig ra0 down sometimes */ - - - // - // Inital the Interrupt source. - // - IntSource.word = 0x00000000L; -// McuIntSource.word = 0x00000000L; - - // - // Get the interrupt sources & saved to local variable - // - //RTMP_IO_READ32(pAd, where, &McuIntSource.word); - //RTMP_IO_WRITE32(pAd, , McuIntSource.word); - - // - // Flag fOP_STATUS_DOZE On, means ASIC put to sleep, elase means ASICK WakeUp - // And at the same time, clock maybe turned off that say there is no DMA service. - // when ASIC get to sleep. - // To prevent system hang on power saving. - // We need to check it before handle the INT_SOURCE_CSR, ASIC must be wake up. - // - // RT2661 => when ASIC is sleeping, MAC register cannot be read and written. - // RT2860 => when ASIC is sleeping, MAC register can be read and written. - - bOldValue = pAd->bPCIclkOff; - pAd->bPCIclkOff = FALSE; - { - RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word); - RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word); // write 1 to clear - } - pAd->bPCIclkOff = bOldValue; - - // Do nothing if Reset in progress - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) - { - return IRQ_HANDLED; - } - - // - // Handle interrupt, walk through all bits - // Should start from highest priority interrupt - // The priority can be adjust by altering processing if statement - // - - // If required spinlock, each interrupt service routine has to acquire - // and release itself. - // - - // Do nothing if NIC doesn't exist - if (IntSource.word == 0xffffffff) - { - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS); - printk("snowpin - IntSource.word == 0xffffffff\n"); - return IRQ_HANDLED; - } - - if (IntSource.word & TxCoherent) - { - DBGPRINT(RT_DEBUG_ERROR, (">>>TxCoherent<<<\n")); - RTMPHandleRxCoherentInterrupt(pAd); - } - - if (IntSource.word & RxCoherent) - { - DBGPRINT(RT_DEBUG_ERROR, (">>>RxCoherent<<<\n")); - RTMPHandleRxCoherentInterrupt(pAd); - } - - if (IntSource.word & FifoStaFullInt) - { -#if 1 - if ((pAd->int_disable_mask & FifoStaFullInt) == 0) - { - /* mask FifoStaFullInt */ - rt2860_int_disable(pAd, FifoStaFullInt); - tasklet_hi_schedule(&pObj->fifo_statistic_full_task); - } - pAd->int_pending |= FifoStaFullInt; -#else - NICUpdateFifoStaCounters(pAd); -#endif - } - - if (IntSource.word & INT_MGMT_DLY) - { - if ((pAd->int_disable_mask & INT_MGMT_DLY) ==0 ) - { - rt2860_int_disable(pAd, INT_MGMT_DLY); - tasklet_hi_schedule(&pObj->mgmt_dma_done_task); - } - pAd->int_pending |= INT_MGMT_DLY ; - } - - if (IntSource.word & INT_RX) - { - if ((pAd->int_disable_mask & INT_RX) == 0) - { - /* mask RxINT */ - rt2860_int_disable(pAd, INT_RX); - tasklet_hi_schedule(&pObj->rx_done_task); - } - pAd->int_pending |= INT_RX; - } - - if (IntSource.word & INT_HCCA_DLY) - { - - if ((pAd->int_disable_mask & INT_HCCA_DLY) == 0) - { - /* mask TxDataInt */ - rt2860_int_disable(pAd, INT_HCCA_DLY); - tasklet_hi_schedule(&pObj->hcca_dma_done_task); - } - pAd->int_pending |= INT_HCCA_DLY; - } - - if (IntSource.word & INT_AC3_DLY) - { - - if ((pAd->int_disable_mask & INT_AC3_DLY) == 0) - { - /* mask TxDataInt */ - rt2860_int_disable(pAd, INT_AC3_DLY); - tasklet_hi_schedule(&pObj->ac3_dma_done_task); - } - pAd->int_pending |= INT_AC3_DLY; - } - - if (IntSource.word & INT_AC2_DLY) - { - - if ((pAd->int_disable_mask & INT_AC2_DLY) == 0) - { - /* mask TxDataInt */ - rt2860_int_disable(pAd, INT_AC2_DLY); - tasklet_hi_schedule(&pObj->ac2_dma_done_task); - } - pAd->int_pending |= INT_AC2_DLY; - } - - if (IntSource.word & INT_AC1_DLY) - { - - pAd->int_pending |= INT_AC1_DLY; - - if ((pAd->int_disable_mask & INT_AC1_DLY) == 0) - { - /* mask TxDataInt */ - rt2860_int_disable(pAd, INT_AC1_DLY); - tasklet_hi_schedule(&pObj->ac1_dma_done_task); - } - - } - - if (IntSource.word & INT_AC0_DLY) - { - pAd->int_pending |= INT_AC0_DLY; - - if ((pAd->int_disable_mask & INT_AC0_DLY) == 0) - { - /* mask TxDataInt */ - rt2860_int_disable(pAd, INT_AC0_DLY); - tasklet_hi_schedule(&pObj->ac0_dma_done_task); - } - - } - - if (IntSource.word & PreTBTTInt) - { - RTMPHandlePreTBTTInterrupt(pAd); - } - - if (IntSource.word & TBTTInt) - { - RTMPHandleTBTTInterrupt(pAd); - } - - if (IntSource.word & AutoWakeupInt) - RTMPHandleTwakeupInterrupt(pAd); - - return IRQ_HANDLED; -} - -/* -======================================================================== -Routine Description: - Check the chipset vendor/product ID. - -Arguments: - _dev_p Point to the PCI or USB device - -Return Value: - TRUE Check ok - FALSE Check fail - -Note: -======================================================================== -*/ -BOOLEAN RT28XXChipsetCheck( - IN void *_dev_p) -{ - /* always TRUE */ - return TRUE; -} - - -/* -======================================================================== -Routine Description: - Init net device structure. - -Arguments: - _dev_p Point to the PCI or USB device - *net_dev Point to the net device - *pAd the raxx interface data pointer - -Return Value: - TRUE Init ok - FALSE Init fail - -Note: -======================================================================== -*/ -BOOLEAN RT28XXNetDevInit( - IN void *_dev_p, - IN struct net_device *net_dev, - IN RTMP_ADAPTER *pAd) -{ - struct pci_dev *pci_dev = (struct pci_dev *)_dev_p; - const CHAR *print_name; - ULONG csr_addr; - - - print_name = pci_dev ? pci_name(pci_dev) : "rt2860"; - - net_dev->base_addr = 0; - net_dev->irq = 0; - - if (pci_request_regions(pci_dev, print_name)) - goto err_out_free_netdev; - - // interrupt IRQ number - net_dev->irq = pci_dev->irq; - - // map physical address to virtual address for accessing register - csr_addr = (unsigned long) ioremap(pci_resource_start(pci_dev, 0), - pci_resource_len(pci_dev, 0)); - - if (!csr_addr) - { - DBGPRINT(RT_DEBUG_ERROR, - ("ioremap failed for device %s, region 0x%lX @ 0x%lX\n", - print_name, (ULONG)pci_resource_len(pci_dev, 0), - (ULONG)pci_resource_start(pci_dev, 0))); - goto err_out_free_res; - } - - // Save CSR virtual address and irq to device structure - net_dev->base_addr = csr_addr; - pAd->CSRBaseAddress = (PUCHAR)net_dev->base_addr; - - // Set DMA master - pci_set_master(pci_dev); - - net_dev->priv_flags = INT_MAIN; - - DBGPRINT(RT_DEBUG_TRACE, ("%s: at 0x%lx, VA 0x%lx, IRQ %d. \n", - net_dev->name, (ULONG)pci_resource_start(pci_dev, 0), - (ULONG)csr_addr, pci_dev->irq)); - return TRUE; - - - /* --------------------------- ERROR HANDLE --------------------------- */ -err_out_free_res: - pci_release_regions(pci_dev); -err_out_free_netdev: - /* free netdev in caller, not here */ - return FALSE; -} - - -/* -======================================================================== -Routine Description: - Init net device structure. - -Arguments: - _dev_p Point to the PCI or USB device - *pAd the raxx interface data pointer - -Return Value: - TRUE Config ok - FALSE Config fail - -Note: -======================================================================== -*/ -BOOLEAN RT28XXProbePostConfig( - IN void *_dev_p, - IN RTMP_ADAPTER *pAd, - IN INT32 argc) -{ - /* no use */ - return TRUE; -} - - -/* -======================================================================== -Routine Description: - Disable DMA. - -Arguments: - *pAd the raxx interface data pointer - -Return Value: - None - -Note: -======================================================================== -*/ -VOID RT28XXDMADisable( - IN RTMP_ADAPTER *pAd) -{ - WPDMA_GLO_CFG_STRUC GloCfg; - - - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); - GloCfg.word &= 0xff0; - GloCfg.field.EnTXWriteBackDDONE =1; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); -} - - -/* -======================================================================== -Routine Description: - Enable DMA. - -Arguments: - *pAd the raxx interface data pointer - -Return Value: - None - -Note: -======================================================================== -*/ -VOID RT28XXDMAEnable( - IN RTMP_ADAPTER *pAd) -{ - WPDMA_GLO_CFG_STRUC GloCfg; - int i = 0; - - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4); - do - { - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); - if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) - break; - - DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n")); - RTMPusecDelay(1000); - i++; - }while ( i <200); - - RTMPusecDelay(50); - - GloCfg.field.EnTXWriteBackDDONE = 1; - GloCfg.field.WPDMABurstSIZE = 2; - GloCfg.field.EnableRxDMA = 1; - GloCfg.field.EnableTxDMA = 1; - - DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word)); - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); - -} - -/* -======================================================================== -Routine Description: - Write Beacon buffer to Asic. - -Arguments: - *pAd the raxx interface data pointer - -Return Value: - None - -Note: -======================================================================== -*/ -VOID RT28xx_UpdateBeaconToAsic( - IN RTMP_ADAPTER *pAd, - IN INT apidx, - IN ULONG FrameLen, - IN ULONG UpdatePos) -{ - ULONG CapInfoPos = 0; - UCHAR *ptr, *ptr_update, *ptr_capinfo; - UINT i; - BOOLEAN bBcnReq = FALSE; - UCHAR bcn_idx = 0; - - { - DBGPRINT(RT_DEBUG_ERROR, ("%s() : No valid Interface be found.\n", __func__)); - return; - } - - if (bBcnReq == FALSE) - { - /* when the ra interface is down, do not send its beacon frame */ - /* clear all zero */ - for(i=0; iBeaconOffset[bcn_idx] + i, 0x00); - } - else - { - ptr = (PUCHAR)&pAd->BeaconTxWI; - - for (i=0; iBeaconOffset[bcn_idx] + i, longptr); - ptr += 4; - } - - // Update CapabilityInfo in Beacon - for (i = CapInfoPos; i < (CapInfoPos+2); i++) - { - RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, *ptr_capinfo); - ptr_capinfo ++; - } - - if (FrameLen > UpdatePos) - { - for (i= UpdatePos; i< (FrameLen); i++) - { - RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, *ptr_update); - ptr_update ++; - } - } - - } - -} - -VOID RTMPInitPCIeLinkCtrlValue( - IN PRTMP_ADAPTER pAd) -{ -} - -VOID RTMPFindHostPCIDev( - IN PRTMP_ADAPTER pAd) -{ -} - -/* - ======================================================================== - - Routine Description: - - Arguments: - Level = RESTORE_HALT : Restore PCI host and Ralink PCIe Link Control field to its default value. - Level = Other Value : Restore from dot11 power save or radio off status. And force PCI host Link Control fields to 0x1 - - ======================================================================== -*/ -VOID RTMPPCIeLinkCtrlValueRestore( - IN PRTMP_ADAPTER pAd, - IN UCHAR Level) -{ -} - -/* - ======================================================================== - - Routine Description: - - Arguments: - Max : limit Host PCI and Ralink PCIe device's LINK CONTROL field's value. - Because now frequently set our device to mode 1 or mode 3 will cause problem. - - ======================================================================== -*/ -VOID RTMPPCIeLinkCtrlSetting( - IN PRTMP_ADAPTER pAd, - IN USHORT Max) -{ -} - -VOID rt2860_stop(struct net_device *net_dev) -{ - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)NULL; - if (net_dev == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n")); - } - else - pAd = net_dev->ml_priv; - - if (pAd != NULL) - { - // stop interface - netif_carrier_off(net_dev); - netif_stop_queue(net_dev); - - // mark device as removed from system and therefore no longer available - netif_device_detach(net_dev); - - // mark halt flag - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - - // take down the device - rt28xx_close((PNET_DEV)net_dev); - RT_MOD_DEC_USE_COUNT(); - } - return; -} - -/* - * invaild or writeback cache - * and convert virtual address to physical address - */ -dma_addr_t linux_pci_map_single(void *handle, void *ptr, size_t size, int sd_idx, int direction) -{ - PRTMP_ADAPTER pAd; - POS_COOKIE pObj; - - /* - ------ Porting Information ------ - > For Tx Alloc: - mgmt packets => sd_idx = 0 - SwIdx: pAd->MgmtRing.TxCpuIdx - pTxD : pAd->MgmtRing.Cell[SwIdx].AllocVa; - - data packets => sd_idx = 1 - TxIdx : pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx - QueIdx: pTxBlk->QueIdx - pTxD : pAd->TxRing[pTxBlk->QueIdx].Cell[TxIdx].AllocVa; - - > For Rx Alloc: - sd_idx = -1 - */ - - pAd = (PRTMP_ADAPTER)handle; - pObj = (POS_COOKIE)pAd->OS_Cookie; - - if (sd_idx == 1) - { - PTX_BLK pTxBlk; - pTxBlk = (PTX_BLK)ptr; - return pci_map_single(pObj->pci_dev, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, direction); - } - else - { - return pci_map_single(pObj->pci_dev, ptr, size, direction); - } - -} - -void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size, int direction) -{ - PRTMP_ADAPTER pAd; - POS_COOKIE pObj; - - pAd=(PRTMP_ADAPTER)handle; - pObj = (POS_COOKIE)pAd->OS_Cookie; - - pci_unmap_single(pObj->pci_dev, dma_addr, size, direction); - -} - diff --git a/drivers/staging/rt2860/Kconfig b/drivers/staging/rt2860/Kconfig index efe38e25c5ed5c657078c7f96c4fd4507550be14..f9962b6931284197f420d337dd26cad1ce9433b1 100644 --- a/drivers/staging/rt2860/Kconfig +++ b/drivers/staging/rt2860/Kconfig @@ -1,5 +1,8 @@ config RT2860 - tristate "Ralink 2860 wireless support" + tristate "Ralink 2860/3090 wireless support" depends on PCI && X86 && WLAN + select WIRELESS_EXT + select WEXT_PRIV ---help--- - This is an experimental driver for the Ralink 2860 wireless chip. + This is an experimental driver for the Ralink 2860 and 3090 + wireless chips. diff --git a/drivers/staging/rt2860/Makefile b/drivers/staging/rt2860/Makefile index c9fe92583d7ee15f9fc65a84c3306cace513b51b..23ae07f00ead36421767c637cf77f7a084d83cff 100644 --- a/drivers/staging/rt2860/Makefile +++ b/drivers/staging/rt2860/Makefile @@ -2,26 +2,33 @@ obj-$(CONFIG_RT2860) += rt2860sta.o # TODO: all of these should be removed EXTRA_CFLAGS += -DLINUX -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -EXTRA_CFLAGS += -DRT2860 +EXTRA_CFLAGS += -DRTMP_MAC_PCI -DRTMP_PCI_SUPPORT -DRT2860 +EXTRA_CFLAGS += -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DRT30xx -DRT3090 EXTRA_CFLAGS += -DDBG rt2860sta-objs := \ - common/md5.o \ + common/crypt_md5.o \ + common/crypt_sha2.o \ + common/crypt_hmac.o \ common/mlme.o \ - common/rtmp_wep.o \ + common/cmm_wep.o \ common/action.o \ common/cmm_data.o \ common/rtmp_init.o \ - common/rtmp_tkip.o \ + common/cmm_tkip.o \ + common/cmm_aes.o \ common/cmm_sync.o \ common/eeprom.o \ common/cmm_sanity.o \ common/cmm_info.o \ + common/cmm_cfg.o \ common/cmm_wpa.o \ common/dfs.o \ common/spectrum.o \ + common/rtmp_timer.o \ + common/rt_channel.o \ + common/cmm_asic.o \ sta/assoc.o \ - sta/aironet.o \ sta/auth.o \ sta/auth_rsp.o \ sta/sync.o \ @@ -30,10 +37,16 @@ rt2860sta-objs := \ sta/connect.o \ sta/wpa.o \ rt_linux.o \ - rt_profile.o \ rt_main_dev.o \ sta_ioctl.o \ common/ba_action.o \ - common/2860_rtmp_init.o \ - 2860_main_dev.o \ - common/cmm_data_2860.o + pci_main_dev.o \ + rt_pci_rbus.o \ + common/cmm_mac_pci.o \ + common/cmm_data_pci.o \ + common/ee_prom.o \ + common/rtmp_mcu.o \ + common/ee_efuse.o \ + chips/rt30xx.o \ + common/rt_rf.o \ + chips/rt3090.o diff --git a/drivers/staging/rt2860/TODO b/drivers/staging/rt2860/TODO index 6158dc2a4b660c69da3ef50475a16d9f62beb95d..8e2f6ee0a2bee3673152a7cadaa0ea3fbbfafbd3 100644 --- a/drivers/staging/rt2860/TODO +++ b/drivers/staging/rt2860/TODO @@ -9,7 +9,6 @@ TODO: - checkpatch.pl clean - sparse clean - port to in-kernel 80211 stack and common rt2x00 infrastructure - - remove reading from /etc/ config files - review by the wireless developer community Please send any patches or complaints about this driver to Greg diff --git a/drivers/staging/rt2860/aironet.h b/drivers/staging/rt2860/aironet.h deleted file mode 100644 index 1e07b19b8cdc945f8eee7f1ebad729db27ab3c02..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2860/aironet.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - aironet.h - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Name Date Modification logs - Paul Lin 04-06-15 Initial -*/ - -#ifndef __AIRONET_H__ -#define __AIRONET_H__ - -// Measurement Type definition -#define MSRN_TYPE_UNUSED 0 -#define MSRN_TYPE_CHANNEL_LOAD_REQ 1 -#define MSRN_TYPE_NOISE_HIST_REQ 2 -#define MSRN_TYPE_BEACON_REQ 3 -#define MSRN_TYPE_FRAME_REQ 4 - -// Scan Mode in Beacon Request -#define MSRN_SCAN_MODE_PASSIVE 0 -#define MSRN_SCAN_MODE_ACTIVE 1 -#define MSRN_SCAN_MODE_BEACON_TABLE 2 - -// PHY type definition for Aironet beacon report, CCX 2 table 36-9 -#define PHY_FH 1 -#define PHY_DSS 2 -#define PHY_UNUSED 3 -#define PHY_OFDM 4 -#define PHY_HR_DSS 5 -#define PHY_ERP 6 - -// RPI table in dBm -#define RPI_0 0 // Power <= -87 -#define RPI_1 1 // -87 < Power <= -82 -#define RPI_2 2 // -82 < Power <= -77 -#define RPI_3 3 // -77 < Power <= -72 -#define RPI_4 4 // -72 < Power <= -67 -#define RPI_5 5 // -67 < Power <= -62 -#define RPI_6 6 // -62 < Power <= -57 -#define RPI_7 7 // -57 < Power - -// Cisco Aironet IAPP definetions -#define AIRONET_IAPP_TYPE 0x32 -#define AIRONET_IAPP_SUBTYPE_REQUEST 0x01 -#define AIRONET_IAPP_SUBTYPE_REPORT 0x81 - -// Measurement Request detail format -typedef struct _MEASUREMENT_REQUEST { - UCHAR Channel; - UCHAR ScanMode; // Use only in beacon request, other requests did not use this field - USHORT Duration; -} MEASUREMENT_REQUEST, *PMEASUREMENT_REQUEST; - -// Beacon Measurement Report -// All these field might change to UCHAR, because we didn't do anything to these report. -// We copy all these beacons and report to CCX 2 AP. -typedef struct _BEACON_REPORT { - UCHAR Channel; - UCHAR Spare; - USHORT Duration; - UCHAR PhyType; // Definiation is listed above table 36-9 - UCHAR RxPower; - UCHAR BSSID[6]; - UCHAR ParentTSF[4]; - UCHAR TargetTSF[8]; - USHORT BeaconInterval; - USHORT CapabilityInfo; -} BEACON_REPORT, *PBEACON_REPORT; - -// Frame Measurement Report (Optional) -typedef struct _FRAME_REPORT { - UCHAR Channel; - UCHAR Spare; - USHORT Duration; - UCHAR TA; - UCHAR BSSID[6]; - UCHAR RSSI; - UCHAR Count; -} FRAME_REPORT, *PFRAME_REPORT; - -#pragma pack(1) -// Channel Load Report -typedef struct _CHANNEL_LOAD_REPORT { - UCHAR Channel; - UCHAR Spare; - USHORT Duration; - UCHAR CCABusy; -} CHANNEL_LOAD_REPORT, *PCHANNEL_LOAD_REPORT; -#pragma pack() - -// Nosie Histogram Report -typedef struct _NOISE_HIST_REPORT { - UCHAR Channel; - UCHAR Spare; - USHORT Duration; - UCHAR Density[8]; -} NOISE_HIST_REPORT, *PNOISE_HIST_REPORT; - -// Radio Management Capability element -typedef struct _RADIO_MANAGEMENT_CAPABILITY { - UCHAR Eid; // TODO: Why the Eid is 1 byte, not normal 2 bytes??? - UCHAR Length; - UCHAR AironetOui[3]; // AIronet OUI (00 40 96) - UCHAR Type; // Type / Version - USHORT Status; // swap16 required -} RADIO_MANAGEMENT_CAPABILITY, *PRADIO_MANAGEMENT_CAPABILITY; - -// Measurement Mode Bit definition -typedef struct _MEASUREMENT_MODE { - UCHAR Rsvd:4; - UCHAR Report:1; - UCHAR NotUsed:1; - UCHAR Enable:1; - UCHAR Parallel:1; -} MEASUREMENT_MODE, *PMEASUREMENT_MODE; - -// Measurement Request element, This is little endian mode -typedef struct _MEASUREMENT_REQUEST_ELEMENT { - USHORT Eid; - USHORT Length; // swap16 required - USHORT Token; // non-zero unique token - UCHAR Mode; // Measurement Mode - UCHAR Type; // Measurement type -} MEASUREMENT_REQUEST_ELEMENT, *PMEASUREMENT_REQUEST_ELEMENT; - -// Measurement Report element, This is little endian mode -typedef struct _MEASUREMENT_REPORT_ELEMENT { - USHORT Eid; - USHORT Length; // swap16 required - USHORT Token; // non-zero unique token - UCHAR Mode; // Measurement Mode - UCHAR Type; // Measurement type -} MEASUREMENT_REPORT_ELEMENT, *PMEASUREMENT_REPORT_ELEMENT; - -// Cisco Aironet IAPP Frame Header, Network byte order used -typedef struct _AIRONET_IAPP_HEADER { - UCHAR CiscoSnapHeader[8]; // 8 bytes Cisco snap header - USHORT Length; // IAPP ID & length, remember to swap16 in LE system - UCHAR Type; // IAPP type - UCHAR SubType; // IAPP subtype - UCHAR DA[6]; // Destination MAC address - UCHAR SA[6]; // Source MAC address - USHORT Token; // Dialog token, no need to swap16 since it is for yoken usage only -} AIRONET_IAPP_HEADER, *PAIRONET_IAPP_HEADER; - -// Radio Measurement Request frame -typedef struct _AIRONET_RM_REQUEST_FRAME { - AIRONET_IAPP_HEADER IAPP; // Common header - UCHAR Delay; // Activation Delay - UCHAR Offset; // Measurement offset -} AIRONET_RM_REQUEST_FRAME, *PAIRONET_RM_REQUEST_FRAME; - -// Radio Measurement Report frame -typedef struct _AIRONET_RM_REPORT_FRAME { - AIRONET_IAPP_HEADER IAPP; // Common header -} AIRONET_RM_REPORT_FRAME, *PAIRONET_RM_REPORT_FRAME; - -// Saved element request actions which will saved in StaCfg. -typedef struct _RM_REQUEST_ACTION { - MEASUREMENT_REQUEST_ELEMENT ReqElem; // Saved request element - MEASUREMENT_REQUEST Measurement; // Saved measurement within the request element -} RM_REQUEST_ACTION, *PRM_REQUEST_ACTION; - -// CCX administration control -typedef union _CCX_CONTROL { - struct { - UINT32 Enable:1; // Enable CCX2 - UINT32 LeapEnable:1; // Enable LEAP at CCX2 - UINT32 RMEnable:1; // Radio Measurement Enable - UINT32 DCRMEnable:1; // Non serving channel Radio Measurement enable - UINT32 QOSEnable:1; // Enable QOS for CCX 2.0 support - UINT32 FastRoamEnable:1; // Enable fast roaming - UINT32 Rsvd:2; // Not used - UINT32 dBmToRoam:8; // the condition to roam when receiving Rssi less than this value. It's negative value. - UINT32 TuLimit:16; // Limit for different channel scan - } field; - UINT32 word; -} CCX_CONTROL, *PCCX_CONTROL; - -#endif // __AIRONET_H__ diff --git a/drivers/staging/rt2860/ap.h b/drivers/staging/rt2860/ap.h index fcdb35847b10438a49dd461fe30c2889cdcb212e..3f744a52aac79a404abc5925b6007224d49c982d 100644 --- a/drivers/staging/rt2860/ap.h +++ b/drivers/staging/rt2860/ap.h @@ -40,39 +40,27 @@ #ifndef __AP_H__ #define __AP_H__ -// ap_mlme.c +/* ap_wpa.c */ +void WpaStateMachineInit(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *Sm, OUT STATE_MACHINE_FUNC Trans[]); -#ifdef RT2870 -VOID BeaconUpdateExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); -#endif // RT2870 // +#ifdef RTMP_MAC_USB +void BeaconUpdateExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); +#endif /* RTMP_MAC_USB // */ -VOID RTMPSetPiggyBack( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bPiggyBack); +void RTMPSetPiggyBack(struct rt_rtmp_adapter *pAd, IN BOOLEAN bPiggyBack); -// ap.c +void MacTableReset(struct rt_rtmp_adapter *pAd); -VOID MacTableReset( - IN PRTMP_ADAPTER pAd); +struct rt_mac_table_entry *MacTableInsertEntry(struct rt_rtmp_adapter *pAd, + u8 *pAddr, + u8 apidx, IN BOOLEAN CleanAll); -MAC_TABLE_ENTRY *MacTableInsertEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN UCHAR apidx, - IN BOOLEAN CleanAll); +BOOLEAN MacTableDeleteEntry(struct rt_rtmp_adapter *pAd, + u16 wcid, u8 *pAddr); -BOOLEAN MacTableDeleteEntry( - IN PRTMP_ADAPTER pAd, - IN USHORT wcid, - IN PUCHAR pAddr); - -MAC_TABLE_ENTRY *MacTableLookup( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr); - -#endif // __AP_H__ +struct rt_mac_table_entry *MacTableLookup(struct rt_rtmp_adapter *pAd, u8 *pAddr); +#endif /* __AP_H__ */ diff --git a/drivers/staging/rt3090/mac_pci.h b/drivers/staging/rt2860/chip/mac_pci.h similarity index 62% rename from drivers/staging/rt3090/mac_pci.h rename to drivers/staging/rt2860/chip/mac_pci.h index bad04d43ebaeaf4ca517116802f0f380d40d889b..bc704acaa3d76dc742e169a0bec71471e8875dc6 100644 --- a/drivers/staging/rt3090/mac_pci.h +++ b/drivers/staging/rt2860/chip/mac_pci.h @@ -25,7 +25,7 @@ ************************************************************************* Module Name: - mac_pci.h + mac_pci.h Abstract: @@ -37,17 +37,16 @@ #ifndef __MAC_PCI_H__ #define __MAC_PCI_H__ -#include "rtmp_type.h" +#include "../rtmp_type.h" #include "rtmp_mac.h" #include "rtmp_phy.h" -#include "rtmp_iface.h" -#include "rtmp_dot11.h" +#include "../rtmp_iface.h" +#include "../rtmp_dot11.h" - -// -// Device ID & Vendor ID related definitions, -// NOTE: you should not add the new VendorID/DeviceID here unless you not sure it belongs to what chip. -// +/* */ +/* Device ID & Vendor ID related definitions, */ +/* NOTE: you should not add the new VendorID/DeviceID here unless you not sure it belongs to what chip. */ +/* */ #define NIC_PCI_VENDOR_ID 0x1814 #define PCIBUS_INTEL_VENDOR 0x8086 @@ -61,177 +60,95 @@ #define PCI_CLASS_BRIDGE_PCI 0x0604 #endif - - - - #define TXINFO_SIZE 0 #define RTMP_PKT_TAIL_PADDING 0 #define fRTMP_ADAPTER_NEED_STOP_TX 0 #define AUX_CTRL 0x10c -// -// TX descriptor format, Tx ring, Mgmt Ring -// -#ifdef RT_BIG_ENDIAN -typedef struct PACKED _TXD_STRUC { - // Word 0 - UINT32 SDPtr0; - // Word 1 - UINT32 DMADONE:1; - UINT32 LastSec0:1; - UINT32 SDLen0:14; - UINT32 Burst:1; - UINT32 LastSec1:1; - UINT32 SDLen1:14; - // Word 2 - UINT32 SDPtr1; - // Word 3 - UINT32 ICO:1; - UINT32 UCO:1; - UINT32 TCO:1; - UINT32 rsv:2; - UINT32 QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA - UINT32 WIV:1; // Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition - UINT32 rsv2:24; -} TXD_STRUC, *PTXD_STRUC; -#else -typedef struct PACKED _TXD_STRUC { - // Word 0 - UINT32 SDPtr0; - // Word 1 - UINT32 SDLen1:14; - UINT32 LastSec1:1; - UINT32 Burst:1; - UINT32 SDLen0:14; - UINT32 LastSec0:1; - UINT32 DMADONE:1; - //Word2 - UINT32 SDPtr1; - //Word3 - UINT32 rsv2:24; - UINT32 WIV:1; // Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition - UINT32 QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA - UINT32 rsv:2; - UINT32 TCO:1; // - UINT32 UCO:1; // - UINT32 ICO:1; // -} TXD_STRUC, *PTXD_STRUC; -#endif - +/* */ +/* TX descriptor format, Tx ring, Mgmt Ring */ +/* */ +struct PACKED rt_txd { + /* Word 0 */ + u32 SDPtr0; + /* Word 1 */ + u32 SDLen1:14; + u32 LastSec1:1; + u32 Burst:1; + u32 SDLen0:14; + u32 LastSec0:1; + u32 DMADONE:1; + /*Word2 */ + u32 SDPtr1; + /*Word3 */ + u32 rsv2:24; + u32 WIV:1; /* Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition */ + u32 QSEL:2; /* select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA */ + u32 rsv:2; + u32 TCO:1; /* */ + u32 UCO:1; /* */ + u32 ICO:1; /* */ +}; + +/* */ +/* Rx descriptor format, Rx Ring */ +/* */ +typedef struct PACKED rt_rxd { + /* Word 0 */ + u32 SDP0; + /* Word 1 */ + u32 SDL1:14; + u32 Rsv:2; + u32 SDL0:14; + u32 LS0:1; + u32 DDONE:1; + /* Word 2 */ + u32 SDP1; + /* Word 3 */ + u32 BA:1; + u32 DATA:1; + u32 NULLDATA:1; + u32 FRAG:1; + u32 U2M:1; /* 1: this RX frame is unicast to me */ + u32 Mcast:1; /* 1: this is a multicast frame */ + u32 Bcast:1; /* 1: this is a broadcast frame */ + u32 MyBss:1; /* 1: this frame belongs to the same BSSID */ + u32 Crc:1; /* 1: CRC error */ + u32 CipherErr:2; /* 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid */ + u32 AMSDU:1; /* rx with 802.3 header, not 802.11 header. */ + u32 HTC:1; + u32 RSSI:1; + u32 L2PAD:1; + u32 AMPDU:1; + u32 Decrypted:1; /* this frame is being decrypted. */ + u32 PlcpSignal:1; /* To be moved */ + u32 PlcpRssil:1; /* To be moved */ + u32 Rsv1:13; +} RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC; -// -// Rx descriptor format, Rx Ring -// -#ifdef RT_BIG_ENDIAN -typedef struct PACKED _RXD_STRUC{ - // Word 0 - UINT32 SDP0; - // Word 1 - UINT32 DDONE:1; - UINT32 LS0:1; - UINT32 SDL0:14; - UINT32 Rsv:2; - UINT32 SDL1:14; - // Word 2 - UINT32 SDP1; - // Word 3 - UINT32 Rsv1:13; - UINT32 PlcpRssil:1;// To be moved - UINT32 PlcpSignal:1; // To be moved - UINT32 Decrypted:1; // this frame is being decrypted. - UINT32 AMPDU:1; - UINT32 L2PAD:1; - UINT32 RSSI:1; - UINT32 HTC:1; - UINT32 AMSDU:1; // rx with 802.3 header, not 802.11 header. obsolete. - UINT32 CipherErr:2; // 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid - UINT32 Crc:1; // 1: CRC error - UINT32 MyBss:1; // 1: this frame belongs to the same BSSID - UINT32 Bcast:1; // 1: this is a broadcast frame - UINT32 Mcast:1; // 1: this is a multicast frame - UINT32 U2M:1; // 1: this RX frame is unicast to me - UINT32 FRAG:1; - UINT32 NULLDATA:1; - UINT32 DATA:1; - UINT32 BA:1; - -} RXD_STRUC, *PRXD_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC; -#else -typedef struct PACKED _RXD_STRUC{ - // Word 0 - UINT32 SDP0; - // Word 1 - UINT32 SDL1:14; - UINT32 Rsv:2; - UINT32 SDL0:14; - UINT32 LS0:1; - UINT32 DDONE:1; - // Word 2 - UINT32 SDP1; - // Word 3 - UINT32 BA:1; - UINT32 DATA:1; - UINT32 NULLDATA:1; - UINT32 FRAG:1; - UINT32 U2M:1; // 1: this RX frame is unicast to me - UINT32 Mcast:1; // 1: this is a multicast frame - UINT32 Bcast:1; // 1: this is a broadcast frame - UINT32 MyBss:1; // 1: this frame belongs to the same BSSID - UINT32 Crc:1; // 1: CRC error - UINT32 CipherErr:2; // 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid - UINT32 AMSDU:1; // rx with 802.3 header, not 802.11 header. - UINT32 HTC:1; - UINT32 RSSI:1; - UINT32 L2PAD:1; - UINT32 AMPDU:1; - UINT32 Decrypted:1; // this frame is being decrypted. - UINT32 PlcpSignal:1; // To be moved - UINT32 PlcpRssil:1;// To be moved - UINT32 Rsv1:13; -} RXD_STRUC, *PRXD_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC; -#endif - -#ifdef BIG_ENDIAN -typedef union _TX_ATTENUATION_CTRL_STRUC -{ - struct - { - ULONG Reserve1:20; - ULONG PCIE_PHY_TX_ATTEN_EN:1; - ULONG PCIE_PHY_TX_ATTEN_VALUE:3; - ULONG Reserve2:7; - ULONG RF_ISOLATION_ENABLE:1; - } field; - - ULONG word; -} TX_ATTENUATION_CTRL_STRUC, *PTX_ATTENUATION_CTRL_STRUC; -#else typedef union _TX_ATTENUATION_CTRL_STRUC { - struct - { - ULONG RF_ISOLATION_ENABLE:1; - ULONG Reserve2:7; - ULONG PCIE_PHY_TX_ATTEN_VALUE:3; - ULONG PCIE_PHY_TX_ATTEN_EN:1; - ULONG Reserve1:20; + struct { + unsigned long RF_ISOLATION_ENABLE:1; + unsigned long Reserve2:7; + unsigned long PCIE_PHY_TX_ATTEN_VALUE:3; + unsigned long PCIE_PHY_TX_ATTEN_EN:1; + unsigned long Reserve1:20; } field; - ULONG word; + unsigned long word; } TX_ATTENUATION_CTRL_STRUC, *PTX_ATTENUATION_CTRL_STRUC; -#endif + /* ----------------- EEPROM Related MACRO ----------------- */ -// 8051 firmware image for RT2860 - base address = 0x4000 +/* 8051 firmware image for RT2860 - base address = 0x4000 */ #define FIRMWARE_IMAGE_BASE 0x2000 -#define MAX_FIRMWARE_IMAGE_SIZE 0x2000 // 8kbyte - +#define MAX_FIRMWARE_IMAGE_SIZE 0x2000 /* 8kbyte */ /* ----------------- Frimware Related MACRO ----------------- */ #define RTMP_WRITE_FIRMWARE(_pAd, _pFwImage, _FwLen) \ do{ \ - ULONG _i, _firm; \ + unsigned long _i, _firm; \ RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, 0x10000); \ \ for(_i=0; _i<_FwLen; _i+=4) \ @@ -250,27 +167,23 @@ typedef union _TX_ATTENUATION_CTRL_STRUC { RTMP_IO_WRITE32(_pAd, H2M_MAILBOX_CSR, 0); \ }while(0) - /* ----------------- TX Related MACRO ----------------- */ #define RTMP_START_DEQUEUE(pAd, QueIdx, irqFlags) do{}while(0) #define RTMP_STOP_DEQUEUE(pAd, QueIdx, irqFlags) do{}while(0) - #define RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, freeNum, pPacket) \ - ((freeNum) >= (ULONG)(pTxBlk->TotalFragNum + RTMP_GET_PACKET_FRAGMENTS(pPacket) + 3)) /* rough estimate we will use 3 more descriptor. */ + ((freeNum) >= (unsigned long)(pTxBlk->TotalFragNum + RTMP_GET_PACKET_FRAGMENTS(pPacket) + 3)) /* rough estimate we will use 3 more descriptor. */ #define RTMP_RELEASE_DESC_RESOURCE(pAd, QueIdx) \ do{}while(0) #define NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, freeNum, _TxFrameType) \ (((freeNum != (TX_RING_SIZE-1)) && (pAd->TxSwQueue[QueIdx].Number == 0)) || (freeNum<3)) - //(((freeNum) != (TX_RING_SIZE-1)) && (pAd->TxSwQueue[QueIdx].Number == 1 /*0*/)) - #define HAL_KickOutMgmtTx(_pAd, _QueIdx, _pPacket, _pSrcBufVA, _SrcBufLen) \ RtmpPCIMgmtKickOut(_pAd, _QueIdx, _pPacket, _pSrcBufVA, _SrcBufLen) #define HAL_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) \ - /* RtmpPCI_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber)*/ + /* RtmpPCI_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) */ #define HAL_WriteTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) \ RtmpPCI_WriteSingleTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) @@ -285,7 +198,7 @@ typedef union _TX_ATTENUATION_CTRL_STRUC { RtmpPCI_FinalWriteTxResource(_pAd, _pTxBlk, _TotalMPDUSize, _FirstTxIdx) #define HAL_LastTxIdx(_pAd, _QueIdx,_LastTxIdx) \ - /*RtmpPCIDataLastTxIdx(_pAd, _QueIdx,_LastTxIdx)*/ + /*RtmpPCIDataLastTxIdx(_pAd, _QueIdx,_LastTxIdx) */ #define HAL_KickOutTx(_pAd, _pTxBlk, _QueIdx) \ RTMP_IO_WRITE32((_pAd), TX_CTX_IDX0+((_QueIdx)*0x10), (_pAd)->TxRing[(_QueIdx)].TxCpuIdx) @@ -300,37 +213,34 @@ typedef union _TX_ATTENUATION_CTRL_STRUC { : \ (_pAd->TxRing[_QueIdx].TxSwFreeIdx + TX_RING_SIZE - _pAd->TxRing[_QueIdx].TxCpuIdx - 1); - #define GET_MGMTRING_FREENO(_pAd) \ (_pAd->MgmtRing.TxSwFreeIdx > _pAd->MgmtRing.TxCpuIdx) ? \ (_pAd->MgmtRing.TxSwFreeIdx - _pAd->MgmtRing.TxCpuIdx - 1) \ : \ (_pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - _pAd->MgmtRing.TxCpuIdx - 1); - /* ----------------- RX Related MACRO ----------------- */ - /* ----------------- ASIC Related MACRO ----------------- */ -// reset MAC of a station entry to 0x000000000000 +/* reset MAC of a station entry to 0x000000000000 */ #define RTMP_STA_ENTRY_MAC_RESET(pAd, Wcid) \ AsicDelWcidTab(pAd, Wcid); -// add this entry into ASIC RX WCID search table +/* add this entry into ASIC RX WCID search table */ #define RTMP_STA_ENTRY_ADD(pAd, pEntry) \ AsicUpdateRxWCIDTable(pAd, pEntry->Aid, pEntry->Addr); -// add by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet -// Set MAC register value according operation mode +/* add by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet */ +/* Set MAC register value according operation mode */ #define RTMP_UPDATE_PROTECT(pAd) \ AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT), TRUE, 0); -// end johnli +/* end johnli */ -// remove Pair-wise key material from ASIC +/* remove Pair-wise key material from ASIC */ #define RTMP_STA_ENTRY_KEY_DEL(pAd, BssIdx, Wcid) \ - AsicRemovePairwiseKeyEntry(pAd, BssIdx, (UCHAR)Wcid); + AsicRemovePairwiseKeyEntry(pAd, BssIdx, (u8)Wcid); -// add Client security information into ASIC WCID table and IVEIV table +/* add Client security information into ASIC WCID table and IVEIV table */ #define RTMP_STA_SECURITY_INFO_ADD(pAd, apidx, KeyID, pEntry) \ RTMPAddWcidAttributeEntry(pAd, apidx, KeyID, \ pAd->SharedKey[apidx][KeyID].CipherAlg, pEntry); @@ -347,36 +257,33 @@ typedef union _TX_ATTENUATION_CTRL_STRUC { pAd->SharedKey[apidx][KeyID].CipherAlg, \ pEntry); } - -// Insert the BA bitmap to ASIC for the Wcid entry +/* Insert the BA bitmap to ASIC for the Wcid entry */ #define RTMP_ADD_BA_SESSION_TO_ASIC(_pAd, _Aid, _TID) \ do{ \ - UINT32 _Value = 0, _Offset; \ + u32 _Value = 0, _Offset; \ _Offset = MAC_WCID_BASE + (_Aid) * HW_WCID_ENTRY_SIZE + 4; \ RTMP_IO_READ32((_pAd), _Offset, &_Value);\ _Value |= (0x10000<<(_TID)); \ RTMP_IO_WRITE32((_pAd), _Offset, _Value);\ }while(0) - -// Remove the BA bitmap from ASIC for the Wcid entry -// bitmap field starts at 0x10000 in ASIC WCID table +/* Remove the BA bitmap from ASIC for the Wcid entry */ +/* bitmap field starts at 0x10000 in ASIC WCID table */ #define RTMP_DEL_BA_SESSION_FROM_ASIC(_pAd, _Wcid, _TID) \ do{ \ - UINT32 _Value = 0, _Offset; \ + u32 _Value = 0, _Offset; \ _Offset = MAC_WCID_BASE + (_Wcid) * HW_WCID_ENTRY_SIZE + 4; \ RTMP_IO_READ32((_pAd), _Offset, &_Value); \ _Value &= (~(0x10000 << (_TID))); \ RTMP_IO_WRITE32((_pAd), _Offset, _Value); \ }while(0) - /* ----------------- Interface Related MACRO ----------------- */ -// -// Enable & Disable NIC interrupt via writing interrupt mask register -// Since it use ADAPTER structure, it have to be put after structure definition. -// +/* */ +/* Enable & Disable NIC interrupt via writing interrupt mask register */ +/* Since it use ADAPTER structure, it have to be put after structure definition. */ +/* */ #define RTMP_ASIC_INTERRUPT_DISABLE(_pAd) \ do{ \ RTMP_IO_WRITE32((_pAd), INT_MASK_CSR, 0x0); /* 0: disable */ \ @@ -389,7 +296,6 @@ typedef union _TX_ATTENUATION_CTRL_STRUC { RTMP_SET_FLAG((_pAd), fRTMP_ADAPTER_INTERRUPT_ACTIVE); \ }while(0) - #define RTMP_IRQ_INIT(pAd) \ { pAd->int_enable_reg = ((DELAYINTMASK) | \ (RxINT|TxDataInt|TxMgmtInt)) & ~(0x03); \ @@ -401,7 +307,6 @@ typedef union _TX_ATTENUATION_CTRL_STRUC { RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, 0xffffffff);\ RTMP_ASIC_INTERRUPT_ENABLE(pAd); } - /* ----------------- MLME Related MACRO ----------------- */ #define RTMP_MLME_HANDLER(pAd) MlmeHandler(pAd) @@ -419,8 +324,7 @@ typedef union _TX_ATTENUATION_CTRL_STRUC { /* ----------------- Power Save Related MACRO ----------------- */ #define RTMP_PS_POLL_ENQUEUE(pAd) EnqueuePsPoll(pAd) - -// For RTMPPCIePowerLinkCtrlRestore () function +/* For RTMPPCIePowerLinkCtrlRestore () function */ #define RESTORE_HALT 1 #define RESTORE_WAKEUP 2 #define RESTORE_CLOSE 3 @@ -433,8 +337,6 @@ typedef union _TX_ATTENUATION_CTRL_STRUC { #define CID2MASK 0x00ff0000 #define CID3MASK 0xff000000 - -#ifdef CONFIG_STA_SUPPORT #define RTMP_STA_FORCE_WAKEUP(pAd, bFromTx) \ RT28xxPciStaAsicForceWakeup(pAd, bFromTx); @@ -443,7 +345,6 @@ typedef union _TX_ATTENUATION_CTRL_STRUC { #define RTMP_SET_PSM_BIT(_pAd, _val) \ MlmeSetPsmBit(_pAd, _val); -#endif // CONFIG_STA_SUPPORT // #define RTMP_MLME_RADIO_ON(pAd) \ RT28xxPciMlmeRadioOn(pAd); @@ -451,4 +352,4 @@ typedef union _TX_ATTENUATION_CTRL_STRUC { #define RTMP_MLME_RADIO_OFF(pAd) \ RT28xxPciMlmeRadioOFF(pAd); -#endif //__MAC_PCI_H__ // +#endif /*__MAC_PCI_H__ // */ diff --git a/drivers/staging/rt2860/chip/mac_usb.h b/drivers/staging/rt2860/chip/mac_usb.h new file mode 100644 index 0000000000000000000000000000000000000000..0b67c0b1de039913e04c1614d183d083a0521a4f --- /dev/null +++ b/drivers/staging/rt2860/chip/mac_usb.h @@ -0,0 +1,347 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* + + Module Name: + mac_usb.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __MAC_USB_H__ +#define __MAC_USB_H__ + +#include "../rtmp_type.h" +#include "rtmp_mac.h" +#include "rtmp_phy.h" +#include "../rtmp_iface.h" +#include "../rtmp_dot11.h" + +#define USB_CYC_CFG 0x02a4 + +#define BEACON_RING_SIZE 2 +#define MGMTPIPEIDX 0 /* EP6 is highest priority */ + +#define RTMP_PKT_TAIL_PADDING 11 /* 3(max 4 byte padding) + 4 (last packet padding) + 4 (MaxBulkOutsize align padding) */ + +#define fRTMP_ADAPTER_NEED_STOP_TX \ + (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \ + fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_BULKOUT_RESET | \ + fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_REMOVE_IN_PROGRESS) + +/* */ +/* RXINFO appends at the end of each rx packet. */ +/* */ +#define RXINFO_SIZE 4 +#define RT2870_RXDMALEN_FIELD_SIZE 4 + +typedef struct PACKED rt_rxinfo { + u32 BA:1; + u32 DATA:1; + u32 NULLDATA:1; + u32 FRAG:1; + u32 U2M:1; /* 1: this RX frame is unicast to me */ + u32 Mcast:1; /* 1: this is a multicast frame */ + u32 Bcast:1; /* 1: this is a broadcast frame */ + u32 MyBss:1; /* 1: this frame belongs to the same BSSID */ + u32 Crc:1; /* 1: CRC error */ + u32 CipherErr:2; /* 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid */ + u32 AMSDU:1; /* rx with 802.3 header, not 802.11 header. */ + u32 HTC:1; + u32 RSSI:1; + u32 L2PAD:1; + u32 AMPDU:1; /* To be moved */ + u32 Decrypted:1; + u32 PlcpRssil:1; + u32 CipherAlg:1; + u32 LastAMSDU:1; + u32 PlcpSignal:12; +} RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC; + +/* */ +/* TXINFO */ +/* */ +#define TXINFO_SIZE 4 + +struct rt_txinfo { + /* Word 0 */ + u32 USBDMATxPktLen:16; /*used ONLY in USB bulk Aggregation, Total byte counts of all sub-frame. */ + u32 rsv:8; + u32 WIV:1; /* Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition */ + u32 QSEL:2; /* select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA */ + u32 SwUseLastRound:1; /* Software use. */ + u32 rsv2:2; /* Software use. */ + u32 USBDMANextVLD:1; /*used ONLY in USB bulk Aggregation, NextValid */ + u32 USBDMATxburst:1; /*used ONLY in USB bulk Aggre. Force USB DMA transmit frame from current selected endpoint */ +}; + +/* */ +/* Management ring buffer format */ +/* */ +struct rt_mgmt { + BOOLEAN Valid; + u8 *pBuffer; + unsigned long Length; +}; + +/*////////////////////////////////////////////////////////////////////////// */ +/* The struct rt_tx_buffer structure forms the transmitted USB packet to the device */ +/*////////////////////////////////////////////////////////////////////////// */ +struct rt_tx_buffer { + union { + u8 WirelessPacket[TX_BUFFER_NORMSIZE]; + struct rt_header_802_11 NullFrame; + struct rt_pspoll_frame PsPollPacket; + struct rt_rts_frame RTSFrame; + } field; + u8 Aggregation[4]; /*Buffer for save Aggregation size. */ +}; + +struct rt_httx_buffer { + union { + u8 WirelessPacket[MAX_TXBULK_SIZE]; + struct rt_header_802_11 NullFrame; + struct rt_pspoll_frame PsPollPacket; + struct rt_rts_frame RTSFrame; + } field; + u8 Aggregation[4]; /*Buffer for save Aggregation size. */ +}; + +/* used to track driver-generated write irps */ +struct rt_tx_context { + void *pAd; /*Initialized in MiniportInitialize */ + PURB pUrb; /*Initialized in MiniportInitialize */ + PIRP pIrp; /*used to cancel pending bulk out. */ + /*Initialized in MiniportInitialize */ + struct rt_tx_buffer *TransferBuffer; /*Initialized in MiniportInitialize */ + unsigned long BulkOutSize; + u8 BulkOutPipeId; + u8 SelfIdx; + BOOLEAN InUse; + BOOLEAN bWaitingBulkOut; /* at least one packet is in this TxContext, ready for making IRP anytime. */ + BOOLEAN bFullForBulkOut; /* all tx buffer are full , so waiting for tx bulkout. */ + BOOLEAN IRPPending; + BOOLEAN LastOne; + BOOLEAN bAggregatible; + u8 Header_802_3[LENGTH_802_3]; + u8 Rsv[2]; + unsigned long DataOffset; + u32 TxRate; + dma_addr_t data_dma; /* urb dma on linux */ + +}; + +/* used to track driver-generated write irps */ +struct rt_ht_tx_context { + void *pAd; /*Initialized in MiniportInitialize */ + PURB pUrb; /*Initialized in MiniportInitialize */ + PIRP pIrp; /*used to cancel pending bulk out. */ + /*Initialized in MiniportInitialize */ + struct rt_httx_buffer *TransferBuffer; /*Initialized in MiniportInitialize */ + unsigned long BulkOutSize; /* Indicate the total bulk-out size in bytes in one bulk-transmission */ + u8 BulkOutPipeId; + BOOLEAN IRPPending; + BOOLEAN LastOne; + BOOLEAN bCurWriting; + BOOLEAN bRingEmpty; + BOOLEAN bCopySavePad; + u8 SavedPad[8]; + u8 Header_802_3[LENGTH_802_3]; + unsigned long CurWritePosition; /* Indicate the buffer offset which packet will be inserted start from. */ + unsigned long CurWriteRealPos; /* Indicate the buffer offset which packet now are writing to. */ + unsigned long NextBulkOutPosition; /* Indicate the buffer start offset of a bulk-transmission */ + unsigned long ENextBulkOutPosition; /* Indicate the buffer end offset of a bulk-transmission */ + u32 TxRate; + dma_addr_t data_dma; /* urb dma on linux */ +}; + +/* */ +/* Structure to keep track of receive packets and buffers to indicate */ +/* receive data to the protocol. */ +/* */ +struct rt_rx_context { + u8 *TransferBuffer; + void *pAd; + PIRP pIrp; /*used to cancel pending bulk in. */ + PURB pUrb; + /*These 2 Boolean shouldn't both be 1 at the same time. */ + unsigned long BulkInOffset; /* number of packets waiting for reordering . */ +/* BOOLEAN ReorderInUse; // At least one packet in this buffer are in reordering buffer and wait for receive indication */ + BOOLEAN bRxHandling; /* Notify this packet is being process now. */ + BOOLEAN InUse; /* USB Hardware Occupied. Wait for USB HW to put packet. */ + BOOLEAN Readable; /* Receive Complete back. OK for driver to indicate receiving packet. */ + BOOLEAN IRPPending; /* TODO: To be removed */ + atomic_t IrpLock; + spinlock_t RxContextLock; + dma_addr_t data_dma; /* urb dma on linux */ +}; + +/****************************************************************************** + + USB Frimware Related MACRO + +******************************************************************************/ +/* 8051 firmware image for usb - use last-half base address = 0x3000 */ +#define FIRMWARE_IMAGE_BASE 0x3000 +#define MAX_FIRMWARE_IMAGE_SIZE 0x1000 /* 4kbyte */ + +#define RTMP_WRITE_FIRMWARE(_pAd, _pFwImage, _FwLen) \ + RTUSBFirmwareWrite(_pAd, _pFwImage, _FwLen) + +/****************************************************************************** + + USB TX Related MACRO + +******************************************************************************/ +#define RTMP_START_DEQUEUE(pAd, QueIdx, irqFlags) \ + do{ \ + RTMP_IRQ_LOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + if (pAd->DeQueueRunning[QueIdx]) \ + { \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);\ + DBGPRINT(RT_DEBUG_OFF, ("DeQueueRunning[%d]= TRUE!\n", QueIdx)); \ + continue; \ + } \ + else \ + { \ + pAd->DeQueueRunning[QueIdx] = TRUE; \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);\ + } \ + }while(0) + +#define RTMP_STOP_DEQUEUE(pAd, QueIdx, irqFlags) \ + do{ \ + RTMP_IRQ_LOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + pAd->DeQueueRunning[QueIdx] = FALSE; \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + }while(0) + +#define RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, freeNum, pPacket) \ + (RTUSBFreeDescriptorRequest(pAd, pTxBlk->QueIdx, (pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))) == NDIS_STATUS_SUCCESS) + +#define RTMP_RELEASE_DESC_RESOURCE(pAd, QueIdx) \ + do{}while(0) + +#define NEED_QUEUE_BACK_FOR_AGG(_pAd, _QueIdx, _freeNum, _TxFrameType) \ + ((_TxFrameType == TX_RALINK_FRAME) && (RTUSBNeedQueueBackForAgg(_pAd, _QueIdx))) + +#define HAL_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) \ + RtmpUSB_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) + +#define HAL_WriteTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) \ + RtmpUSB_WriteSingleTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) + +#define HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) \ + RtmpUSB_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) + +#define HAL_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) \ + RtmpUSB_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) + +#define HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, TxIdx) \ + RtmpUSB_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, TxIdx) + +#define HAL_LastTxIdx(pAd, QueIdx,TxIdx) \ + /*RtmpUSBDataLastTxIdx(pAd, QueIdx,TxIdx) */ + +#define HAL_KickOutTx(pAd, pTxBlk, QueIdx) \ + RtmpUSBDataKickOut(pAd, pTxBlk, QueIdx) + +#define HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen) \ + RtmpUSBMgmtKickOut(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen) + +#define HAL_KickOutNullFrameTx(_pAd, _QueIdx, _pNullFrame, _frameLen) \ + RtmpUSBNullFrameKickOut(_pAd, _QueIdx, _pNullFrame, _frameLen) + +#define GET_TXRING_FREENO(_pAd, _QueIdx) (_QueIdx) /*(_pAd->TxRing[_QueIdx].TxSwFreeIdx) */ +#define GET_MGMTRING_FREENO(_pAd) (_pAd->MgmtRing.TxSwFreeIdx) + +/* ----------------- RX Related MACRO ----------------- */ + +/* + * Device Hardware Interface Related MACRO + */ +#define RTMP_IRQ_INIT(pAd) do{}while(0) +#define RTMP_IRQ_ENABLE(pAd) do{}while(0) + +/* + * MLME Related MACRO + */ +#define RTMP_MLME_HANDLER(pAd) RTUSBMlmeUp(pAd) + +#define RTMP_MLME_PRE_SANITY_CHECK(pAd) \ + { if ((pAd->CommonCfg.bHardwareRadio == TRUE) && \ + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && \ + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { \ + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_CHECK_GPIO, NULL, 0); } } + +#define RTMP_MLME_STA_QUICK_RSP_WAKE_UP(pAd) \ + { RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_QKERIODIC_EXECUT, NULL, 0); \ + RTUSBMlmeUp(pAd); } + +#define RTMP_MLME_RESET_STATE_MACHINE(pAd) \ + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_RESET_CONF, 0, NULL); \ + RTUSBMlmeUp(pAd); + +#define RTMP_HANDLE_COUNTER_MEASURE(_pAd, _pEntry) \ + { RTUSBEnqueueInternalCmd(_pAd, CMDTHREAD_802_11_COUNTER_MEASURE, _pEntry, sizeof(struct rt_mac_table_entry)); \ + RTUSBMlmeUp(_pAd); \ + } + +/* + * Power Save Related MACRO + */ +#define RTMP_PS_POLL_ENQUEUE(pAd) \ + { RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL); \ + RTUSBKickBulkOut(pAd); } + +#define RTMP_STA_FORCE_WAKEUP(_pAd, bFromTx) \ + RT28xxUsbStaAsicForceWakeup(_pAd, bFromTx); + +#define RTMP_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp) \ + RT28xxUsbStaAsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); + +#define RTMP_SET_PSM_BIT(_pAd, _val) \ + {\ + if ((_pAd)->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP) \ + MlmeSetPsmBit(_pAd, _val);\ + else \ + { \ + u16 _psm_val; \ + _psm_val = _val; \ + RTUSBEnqueueInternalCmd(_pAd, CMDTHREAD_SET_PSM_BIT, &(_psm_val), sizeof(u16)); \ + }\ + } + +#define RTMP_MLME_RADIO_ON(pAd) \ + RT28xxUsbMlmeRadioOn(pAd); + +#define RTMP_MLME_RADIO_OFF(pAd) \ + RT28xxUsbMlmeRadioOFF(pAd); + +#endif /*__MAC_USB_H__ // */ diff --git a/drivers/staging/rt3090/netif_block.h b/drivers/staging/rt2860/chip/rt2860.h similarity index 67% rename from drivers/staging/rt3090/netif_block.h rename to drivers/staging/rt2860/chip/rt2860.h index 9e753894f29441b76f77ac7b84874c0b7bb2fd70..f30b80820b92ad75a50418c8df79da8280ce5be6 100644 --- a/drivers/staging/rt3090/netif_block.h +++ b/drivers/staging/rt2860/chip/rt2860.h @@ -25,32 +25,30 @@ ************************************************************************* */ -#ifndef __NET_IF_BLOCK_H__ -#define __NET_IF_BLOCK_H__ +#ifndef __RT2860_H__ +#define __RT2860_H__ -#include "link_list.h" -#include "rtmp.h" +#include "mac_pci.h" -#define FREE_NETIF_POOL_SIZE 32 +#ifndef RTMP_PCI_SUPPORT +#error "For RT2860, you should define the compile flag -DRTMP_PCI_SUPPORT" +#endif -typedef struct _NETIF_ENTRY -{ - struct _NETIF_ENTRY *pNext; - PNET_DEV pNetDev; -} NETIF_ENTRY, *PNETIF_ENTRY; +#ifndef RTMP_MAC_PCI +#error "For RT2880, you should define the compile flag -DRTMP_MAC_PCI" +#endif -void initblockQueueTab( - IN PRTMP_ADAPTER pAd); +/* */ +/* Device ID & Vendor ID, these values should match EEPROM value */ +/* */ +#define NIC2860_PCI_DEVICE_ID 0x0601 +#define NIC2860_PCIe_DEVICE_ID 0x0681 +#define NIC2760_PCI_DEVICE_ID 0x0701 /* 1T/2R Cardbus ??? */ +#define NIC2790_PCIe_DEVICE_ID 0x0781 /* 1T/2R miniCard */ -BOOLEAN blockNetIf( - IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry, - IN PNET_DEV pNetDev); +#define VEN_AWT_PCIe_DEVICE_ID 0x1059 +#define VEN_AWT_PCI_VENDOR_ID 0x1A3B -VOID releaseNetIf( - IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry); +#define EDIMAX_PCI_VENDOR_ID 0x1432 -VOID StopNetIfQueue( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket); -#endif // __NET_IF_BLOCK_H__ +#endif /*__RT2860_H__ // */ diff --git a/drivers/staging/rt3090/rt33xx.h b/drivers/staging/rt2860/chip/rt2870.h similarity index 77% rename from drivers/staging/rt3090/rt33xx.h rename to drivers/staging/rt2860/chip/rt2870.h index 6eb938860b778cd314e2b97cfa5b91536e25b184..8263f1baefaec7f36e19160ed38b2d241e480aff 100644 --- a/drivers/staging/rt3090/rt33xx.h +++ b/drivers/staging/rt2860/chip/rt2870.h @@ -23,26 +23,24 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * ************************************************************************* - - Module Name: - rt33xx.h - - Abstract: - - Revision History: - Who When What - --------- ---------- ---------------------------------------------- */ +#ifndef __RT2870_H__ +#define __RT2870_H__ -#ifndef __RT33XX_H__ -#define __RT33XX_H__ +#ifdef RT2870 -#ifdef RT33xx +#ifndef RTMP_USB_SUPPORT +#error "For RT2870, you should define the compile flag -DRTMP_USB_SUPPORT" +#endif +#ifndef RTMP_MAC_USB +#error "For RT2870, you should define the compile flag -DRTMP_MAC_USB" +#endif -extern REG_PAIR RFRegTableOverRT3390[]; -extern UCHAR NUM_RF_REG_PARMS_OVER_RT3390; +#include "../rtmp_type.h" +#include "mac_usb.h" -#endif // RT33xx // +/*#define RTMP_CHIP_NAME "RT2870" */ -#endif //__RT33XX_H__ // +#endif /* RT2870 // */ +#endif /*__RT2870_H__ // */ diff --git a/drivers/staging/rt3090/rt3370.h b/drivers/staging/rt2860/chip/rt3070.h similarity index 87% rename from drivers/staging/rt3090/rt3370.h rename to drivers/staging/rt2860/chip/rt3070.h index bfa9006d059aa98bbca52ca502959ecaf5816274..172ce70542338acc4b54bd20aa34b16d02a4c535 100644 --- a/drivers/staging/rt3090/rt3370.h +++ b/drivers/staging/rt2860/chip/rt3070.h @@ -25,7 +25,7 @@ ************************************************************************* Module Name: - rt3370.h + rt3070.h Abstract: @@ -34,31 +34,34 @@ --------- ---------- ---------------------------------------------- */ -#ifndef __RT3370_H__ -#define __RT3370_H__ - -#ifdef RT3370 +#ifndef __RT3070_H__ +#define __RT3070_H__ +#ifdef RT3070 +#ifndef RTMP_USB_SUPPORT #error "For RT3070, you should define the compile flag -DRTMP_USB_SUPPORT" +#endif +#ifndef RTMP_MAC_USB #error "For RT3070, you should define the compile flag -DRTMP_MAC_USB" +#endif #ifndef RTMP_RF_RW_SUPPORT #error "For RT3070, you should define the compile flag -DRTMP_RF_RW_SUPPORT" #endif -#ifndef RT33xx +#ifndef RT30xx #error "For RT3070, you should define the compile flag -DRT30xx" #endif #include "mac_usb.h" -#include "rt33xx.h" +#include "rt30xx.h" -// -// Device ID & Vendor ID, these values should match EEPROM value -// +/* */ +/* Device ID & Vendor ID, these values should match EEPROM value */ +/* */ -#endif // RT3370 // +#endif /* RT3070 // */ -#endif //__RT3370_H__ // +#endif /*__RT3070_H__ // */ diff --git a/drivers/staging/rt3090/rt3090.h b/drivers/staging/rt2860/chip/rt3090.h similarity index 83% rename from drivers/staging/rt3090/rt3090.h rename to drivers/staging/rt2860/chip/rt3090.h index d325cb028c05fe8709f42bf46752af420d9d23bd..102b938e74bd3e4d599e69e5f433a1017153a0d1 100644 --- a/drivers/staging/rt3090/rt3090.h +++ b/drivers/staging/rt2860/chip/rt3090.h @@ -55,23 +55,18 @@ #error "For RT3090, you should define the compile flag -DRT30xx" #endif -#ifdef CARRIER_DETECTION_SUPPORT -#define TONE_RADAR_DETECT_SUPPORT -#define CARRIER_SENSE_NEW_ALGO -#endif // CARRIER_DETECTION_SUPPORT // - #define PCIE_PS_SUPPORT #include "mac_pci.h" #include "rt30xx.h" -// -// Device ID & Vendor ID, these values should match EEPROM value -// -#define NIC3090_PCIe_DEVICE_ID 0x3090 // 1T/1R miniCard -#define NIC3091_PCIe_DEVICE_ID 0x3091 // 1T/2R miniCard -#define NIC3092_PCIe_DEVICE_ID 0x3092 // 2T/2R miniCard +/* */ +/* Device ID & Vendor ID, these values should match EEPROM value */ +/* */ +#define NIC3090_PCIe_DEVICE_ID 0x3090 /* 1T/1R miniCard */ +#define NIC3091_PCIe_DEVICE_ID 0x3091 /* 1T/2R miniCard */ +#define NIC3092_PCIe_DEVICE_ID 0x3092 /* 2T/2R miniCard */ -#endif // RT3090 // +#endif /* RT3090 // */ -#endif //__RT3090_H__ // +#endif /*__RT3090_H__ // */ diff --git a/drivers/staging/rt3090/rt30xx.h b/drivers/staging/rt2860/chip/rt30xx.h similarity index 93% rename from drivers/staging/rt3090/rt30xx.h rename to drivers/staging/rt2860/chip/rt30xx.h index 70971a0626079ee13775a4972cb63195994c2c50..02e1d728fb4141ef46be6bf61b86564c213eff1b 100644 --- a/drivers/staging/rt3090/rt30xx.h +++ b/drivers/staging/rt2860/chip/rt30xx.h @@ -39,10 +39,9 @@ #ifdef RT30xx +extern struct rt_reg_pair RT30xx_RFRegTable[]; +extern u8 NUM_RF_REG_PARMS; -extern REG_PAIR RT30xx_RFRegTable[]; -extern UCHAR NUM_RF_REG_PARMS; +#endif /* RT30xx // */ -#endif // RT30xx // - -#endif //__RT30XX_H__ // +#endif /*__RT30XX_H__ // */ diff --git a/drivers/staging/rt2860/chip/rtmp_mac.h b/drivers/staging/rt2860/chip/rtmp_mac.h new file mode 100644 index 0000000000000000000000000000000000000000..f6a72581d3bdcc4f5544f5aa3ae5d72d4b5eaca2 --- /dev/null +++ b/drivers/staging/rt2860/chip/rtmp_mac.h @@ -0,0 +1,1307 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* + + Module Name: + rtmp_mac.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RTMP_MAC_H__ +#define __RTMP_MAC_H__ + +/* ================================================================================= */ +/* TX / RX ring descriptor format */ +/* ================================================================================= */ + +/* the first 24-byte in TXD is called TXINFO and will be DMAed to MAC block through TXFIFO. */ +/* MAC block use this TXINFO to control the transmission behavior of this frame. */ +#define FIFO_MGMT 0 +#define FIFO_HCCA 1 +#define FIFO_EDCA 2 + +/* */ +/* TXD Wireless Information format for Tx ring and Mgmt Ring */ +/* */ +/*txop : for txop mode */ +/* 0:txop for the MPDU frame will be handles by ASIC by register */ +/* 1/2/3:the MPDU frame is send after PIFS/backoff/SIFS */ +struct PACKED rt_txwi { + /* Word 0 */ + /* ex: 00 03 00 40 means txop = 3, PHYMODE = 1 */ + u32 FRAG:1; /* 1 to inform TKIP engine this is a fragment. */ + u32 MIMOps:1; /* the remote peer is in dynamic MIMO-PS mode */ + u32 CFACK:1; + u32 TS:1; + + u32 AMPDU:1; + u32 MpduDensity:3; + u32 txop:2; /*FOR "THIS" frame. 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful. */ + u32 rsv:6; + + u32 MCS:7; + u32 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + u32 ShortGI:1; + u32 STBC:2; /* 1: STBC support MCS =0-7, 2,3 : RESERVE */ + u32 Ifs:1; /* */ +/* u32 rsv2:2; //channel bandwidth 20MHz or 40 MHz */ + u32 rsv2:1; + u32 TxBF:1; /* 3*3 */ + u32 PHYMODE:2; + /* Word1 */ + /* ex: 1c ff 38 00 means ACK=0, BAWinSize=7, MPDUtotalByteCount = 0x38 */ + u32 ACK:1; + u32 NSEQ:1; + u32 BAWinSize:6; + u32 WirelessCliID:8; + u32 MPDUtotalByteCount:12; + u32 PacketId:4; + /*Word2 */ + u32 IV; + /*Word3 */ + u32 EIV; +}; + +/* */ +/* RXWI wireless information format, in PBF. invisible in driver. */ +/* */ +struct PACKED rt_rxwi { + /* Word 0 */ + u32 WirelessCliID:8; + u32 KeyIndex:2; + u32 BSSID:3; + u32 UDF:3; + u32 MPDUtotalByteCount:12; + u32 TID:4; + /* Word 1 */ + u32 FRAG:4; + u32 SEQUENCE:12; + u32 MCS:7; + u32 BW:1; + u32 ShortGI:1; + u32 STBC:2; + u32 rsv:3; + u32 PHYMODE:2; /* 1: this RX frame is unicast to me */ + /*Word2 */ + u32 RSSI0:8; + u32 RSSI1:8; + u32 RSSI2:8; + u32 rsv1:8; + /*Word3 */ + u32 SNR0:8; + u32 SNR1:8; + u32 FOFFSET:8; /* RT35xx */ + u32 rsv2:8; + /*u32 rsv2:16; */ +}; + +/* ================================================================================= */ +/* Register format */ +/* ================================================================================= */ + +/* */ +/* SCH/DMA registers - base address 0x0200 */ +/* */ +/* INT_SOURCE_CSR: Interrupt source register. Write one to clear corresponding bit */ +/* */ +#define DMA_CSR0 0x200 +#define INT_SOURCE_CSR 0x200 +typedef union _INT_SOURCE_CSR_STRUC { + struct { + u32 RxDelayINT:1; + u32 TxDelayINT:1; + u32 RxDone:1; + u32 Ac0DmaDone:1; /*4 */ + u32 Ac1DmaDone:1; + u32 Ac2DmaDone:1; + u32 Ac3DmaDone:1; + u32 HccaDmaDone:1; /* bit7 */ + u32 MgmtDmaDone:1; + u32 MCUCommandINT:1; /*bit 9 */ + u32 RxTxCoherent:1; + u32 TBTTInt:1; + u32 PreTBTT:1; + u32 TXFifoStatusInt:1; /*FIFO Statistics is full, sw should read 0x171c */ + u32 AutoWakeup:1; /*bit14 */ + u32 GPTimer:1; + u32 RxCoherent:1; /*bit16 */ + u32 TxCoherent:1; + u32 : 14; + } field; + u32 word; +} INT_SOURCE_CSR_STRUC, *PINT_SOURCE_CSR_STRUC; + +/* */ +/* INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF */ +/* */ +#define INT_MASK_CSR 0x204 +typedef union _INT_MASK_CSR_STRUC { + struct { + u32 RXDelay_INT_MSK:1; + u32 TxDelay:1; + u32 RxDone:1; + u32 Ac0DmaDone:1; + u32 Ac1DmaDone:1; + u32 Ac2DmaDone:1; + u32 Ac3DmaDone:1; + u32 HccaDmaDone:1; + u32 MgmtDmaDone:1; + u32 MCUCommandINT:1; + u32 : 20; + u32 RxCoherent:1; + u32 TxCoherent:1; + } field; + u32 word; +} INT_MASK_CSR_STRUC, *PINT_MASK_CSR_STRUC; + +#define WPDMA_GLO_CFG 0x208 +typedef union _WPDMA_GLO_CFG_STRUC { + struct { + u32 EnableTxDMA:1; + u32 TxDMABusy:1; + u32 EnableRxDMA:1; + u32 RxDMABusy:1; + u32 WPDMABurstSIZE:2; + u32 EnTXWriteBackDDONE:1; + u32 BigEndian:1; + u32 RXHdrScater:8; + u32 HDR_SEG_LEN:16; + } field; + u32 word; +} WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC; + +#define WPDMA_RST_IDX 0x20c +typedef union _WPDMA_RST_IDX_STRUC { + struct { + u32 RST_DTX_IDX0:1; + u32 RST_DTX_IDX1:1; + u32 RST_DTX_IDX2:1; + u32 RST_DTX_IDX3:1; + u32 RST_DTX_IDX4:1; + u32 RST_DTX_IDX5:1; + u32 rsv:10; + u32 RST_DRX_IDX0:1; + u32 : 15; + } field; + u32 word; +} WPDMA_RST_IDX_STRUC, *PWPDMA_RST_IDX_STRUC; +#define DELAY_INT_CFG 0x0210 +typedef union _DELAY_INT_CFG_STRUC { + struct { + u32 RXMAX_PTIME:8; + u32 RXMAX_PINT:7; + u32 RXDLY_INT_EN:1; + u32 TXMAX_PTIME:8; + u32 TXMAX_PINT:7; + u32 TXDLY_INT_EN:1; + } field; + u32 word; +} DELAY_INT_CFG_STRUC, *PDELAY_INT_CFG_STRUC; +#define WMM_AIFSN_CFG 0x0214 +typedef union _AIFSN_CSR_STRUC { + struct { + u32 Aifsn0:4; /* for AC_BE */ + u32 Aifsn1:4; /* for AC_BK */ + u32 Aifsn2:4; /* for AC_VI */ + u32 Aifsn3:4; /* for AC_VO */ + u32 Rsv:16; + } field; + u32 word; +} AIFSN_CSR_STRUC, *PAIFSN_CSR_STRUC; +/* */ +/* CWMIN_CSR: CWmin for each EDCA AC */ +/* */ +#define WMM_CWMIN_CFG 0x0218 +typedef union _CWMIN_CSR_STRUC { + struct { + u32 Cwmin0:4; /* for AC_BE */ + u32 Cwmin1:4; /* for AC_BK */ + u32 Cwmin2:4; /* for AC_VI */ + u32 Cwmin3:4; /* for AC_VO */ + u32 Rsv:16; + } field; + u32 word; +} CWMIN_CSR_STRUC, *PCWMIN_CSR_STRUC; + +/* */ +/* CWMAX_CSR: CWmin for each EDCA AC */ +/* */ +#define WMM_CWMAX_CFG 0x021c +typedef union _CWMAX_CSR_STRUC { + struct { + u32 Cwmax0:4; /* for AC_BE */ + u32 Cwmax1:4; /* for AC_BK */ + u32 Cwmax2:4; /* for AC_VI */ + u32 Cwmax3:4; /* for AC_VO */ + u32 Rsv:16; + } field; + u32 word; +} CWMAX_CSR_STRUC, *PCWMAX_CSR_STRUC; + +/* */ +/* AC_TXOP_CSR0: AC_BK/AC_BE TXOP register */ +/* */ +#define WMM_TXOP0_CFG 0x0220 +typedef union _AC_TXOP_CSR0_STRUC { + struct { + u16 Ac0Txop; /* for AC_BK, in unit of 32us */ + u16 Ac1Txop; /* for AC_BE, in unit of 32us */ + } field; + u32 word; +} AC_TXOP_CSR0_STRUC, *PAC_TXOP_CSR0_STRUC; + +/* */ +/* AC_TXOP_CSR1: AC_VO/AC_VI TXOP register */ +/* */ +#define WMM_TXOP1_CFG 0x0224 +typedef union _AC_TXOP_CSR1_STRUC { + struct { + u16 Ac2Txop; /* for AC_VI, in unit of 32us */ + u16 Ac3Txop; /* for AC_VO, in unit of 32us */ + } field; + u32 word; +} AC_TXOP_CSR1_STRUC, *PAC_TXOP_CSR1_STRUC; + +#define RINGREG_DIFF 0x10 +#define GPIO_CTRL_CFG 0x0228 /*MAC_CSR13 */ +#define MCU_CMD_CFG 0x022c +#define TX_BASE_PTR0 0x0230 /*AC_BK base address */ +#define TX_MAX_CNT0 0x0234 +#define TX_CTX_IDX0 0x0238 +#define TX_DTX_IDX0 0x023c +#define TX_BASE_PTR1 0x0240 /*AC_BE base address */ +#define TX_MAX_CNT1 0x0244 +#define TX_CTX_IDX1 0x0248 +#define TX_DTX_IDX1 0x024c +#define TX_BASE_PTR2 0x0250 /*AC_VI base address */ +#define TX_MAX_CNT2 0x0254 +#define TX_CTX_IDX2 0x0258 +#define TX_DTX_IDX2 0x025c +#define TX_BASE_PTR3 0x0260 /*AC_VO base address */ +#define TX_MAX_CNT3 0x0264 +#define TX_CTX_IDX3 0x0268 +#define TX_DTX_IDX3 0x026c +#define TX_BASE_PTR4 0x0270 /*HCCA base address */ +#define TX_MAX_CNT4 0x0274 +#define TX_CTX_IDX4 0x0278 +#define TX_DTX_IDX4 0x027c +#define TX_BASE_PTR5 0x0280 /*MGMT base address */ +#define TX_MAX_CNT5 0x0284 +#define TX_CTX_IDX5 0x0288 +#define TX_DTX_IDX5 0x028c +#define TX_MGMTMAX_CNT TX_MAX_CNT5 +#define TX_MGMTCTX_IDX TX_CTX_IDX5 +#define TX_MGMTDTX_IDX TX_DTX_IDX5 +#define RX_BASE_PTR 0x0290 /*RX base address */ +#define RX_MAX_CNT 0x0294 +#define RX_CRX_IDX 0x0298 +#define RX_DRX_IDX 0x029c + +#define USB_DMA_CFG 0x02a0 +typedef union _USB_DMA_CFG_STRUC { + struct { + u32 RxBulkAggTOut:8; /*Rx Bulk Aggregation TimeOut in unit of 33ns */ + u32 RxBulkAggLmt:8; /*Rx Bulk Aggregation Limit in unit of 256 bytes */ + u32 phyclear:1; /*phy watch dog enable. write 1 */ + u32 rsv:2; + u32 TxClear:1; /*Clear USB DMA TX path */ + u32 TxopHalt:1; /*Halt TXOP count down when TX buffer is full. */ + u32 RxBulkAggEn:1; /*Enable Rx Bulk Aggregation */ + u32 RxBulkEn:1; /*Enable USB DMA Rx */ + u32 TxBulkEn:1; /*Enable USB DMA Tx */ + u32 EpoutValid:6; /*OUT endpoint data valid */ + u32 RxBusy:1; /*USB DMA RX FSM busy */ + u32 TxBusy:1; /*USB DMA TX FSM busy */ + } field; + u32 word; +} USB_DMA_CFG_STRUC, *PUSB_DMA_CFG_STRUC; + +/* */ +/* 3 PBF registers */ +/* */ +/* */ +/* Most are for debug. Driver doesn't touch PBF register. */ +#define PBF_SYS_CTRL 0x0400 +#define PBF_CFG 0x0408 +#define PBF_MAX_PCNT 0x040C +#define PBF_CTRL 0x0410 +#define PBF_INT_STA 0x0414 +#define PBF_INT_ENA 0x0418 +#define TXRXQ_PCNT 0x0438 +#define PBF_DBG 0x043c +#define PBF_CAP_CTRL 0x0440 + +#ifdef RT30xx +#ifdef RTMP_EFUSE_SUPPORT +/* eFuse registers */ +#define EFUSE_CTRL 0x0580 +#define EFUSE_DATA0 0x0590 +#define EFUSE_DATA1 0x0594 +#define EFUSE_DATA2 0x0598 +#define EFUSE_DATA3 0x059c +#endif /* RTMP_EFUSE_SUPPORT // */ +#endif /* RT30xx // */ + +#define OSC_CTRL 0x5a4 +#define PCIE_PHY_TX_ATTENUATION_CTRL 0x05C8 +#define LDO_CFG0 0x05d4 +#define GPIO_SWITCH 0x05dc + +/* */ +/* 4 MAC registers */ +/* */ +/* */ +/* 4.1 MAC SYSTEM configuration registers (offset:0x1000) */ +/* */ +#define MAC_CSR0 0x1000 +typedef union _ASIC_VER_ID_STRUC { + struct { + u16 ASICRev; /* reversion : 0 */ + u16 ASICVer; /* version : 2860 */ + } field; + u32 word; +} ASIC_VER_ID_STRUC, *PASIC_VER_ID_STRUC; +#define MAC_SYS_CTRL 0x1004 /*MAC_CSR1 */ +#define MAC_ADDR_DW0 0x1008 /* MAC ADDR DW0 */ +#define MAC_ADDR_DW1 0x100c /* MAC ADDR DW1 */ +/* */ +/* MAC_CSR2: STA MAC register 0 */ +/* */ +typedef union _MAC_DW0_STRUC { + struct { + u8 Byte0; /* MAC address byte 0 */ + u8 Byte1; /* MAC address byte 1 */ + u8 Byte2; /* MAC address byte 2 */ + u8 Byte3; /* MAC address byte 3 */ + } field; + u32 word; +} MAC_DW0_STRUC, *PMAC_DW0_STRUC; + +/* */ +/* MAC_CSR3: STA MAC register 1 */ +/* */ +typedef union _MAC_DW1_STRUC { + struct { + u8 Byte4; /* MAC address byte 4 */ + u8 Byte5; /* MAC address byte 5 */ + u8 U2MeMask; + u8 Rsvd1; + } field; + u32 word; +} MAC_DW1_STRUC, *PMAC_DW1_STRUC; + +#define MAC_BSSID_DW0 0x1010 /* MAC BSSID DW0 */ +#define MAC_BSSID_DW1 0x1014 /* MAC BSSID DW1 */ + +/* */ +/* MAC_CSR5: BSSID register 1 */ +/* */ +typedef union _MAC_CSR5_STRUC { + struct { + u8 Byte4; /* BSSID byte 4 */ + u8 Byte5; /* BSSID byte 5 */ + u16 BssIdMask:2; /* 0: one BSSID, 10: 4 BSSID, 01: 2 BSSID , 11: 8BSSID */ + u16 MBssBcnNum:3; + u16 Rsvd:11; + } field; + u32 word; +} MAC_CSR5_STRUC, *PMAC_CSR5_STRUC; + +#define MAX_LEN_CFG 0x1018 /* rt2860b max 16k bytes. bit12:13 Maximum PSDU length (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 */ +#define BBP_CSR_CFG 0x101c /* */ +/* */ +/* BBP_CSR_CFG: BBP serial control register */ +/* */ +typedef union _BBP_CSR_CFG_STRUC { + struct { + u32 Value:8; /* Register value to program into BBP */ + u32 RegNum:8; /* Selected BBP register */ + u32 fRead:1; /* 0: Write BBP, 1: Read BBP */ + u32 Busy:1; /* 1: ASIC is busy execute BBP programming. */ + u32 BBP_PAR_DUR:1; /* 0: 4 MAC clock cycles 1: 8 MAC clock cycles */ + u32 BBP_RW_MODE:1; /* 0: use serial mode 1:parallel */ + u32 : 12; + } field; + u32 word; +} BBP_CSR_CFG_STRUC, *PBBP_CSR_CFG_STRUC; +#define RF_CSR_CFG0 0x1020 +/* */ +/* RF_CSR_CFG: RF control register */ +/* */ +typedef union _RF_CSR_CFG0_STRUC { + struct { + u32 RegIdAndContent:24; /* Register value to program into BBP */ + u32 bitwidth:5; /* Selected BBP register */ + u32 StandbyMode:1; /* 0: high when stand by 1: low when standby */ + u32 Sel:1; /* 0:RF_LE0 activate 1:RF_LE1 activate */ + u32 Busy:1; /* 0: idle 1: 8busy */ + } field; + u32 word; +} RF_CSR_CFG0_STRUC, *PRF_CSR_CFG0_STRUC; +#define RF_CSR_CFG1 0x1024 +typedef union _RF_CSR_CFG1_STRUC { + struct { + u32 RegIdAndContent:24; /* Register value to program into BBP */ + u32 RFGap:5; /* Gap between BB_CONTROL_RF and RF_LE. 0: 3 system clock cycle (37.5usec) 1: 5 system clock cycle (62.5usec) */ + u32 rsv:7; /* 0: idle 1: 8busy */ + } field; + u32 word; +} RF_CSR_CFG1_STRUC, *PRF_CSR_CFG1_STRUC; +#define RF_CSR_CFG2 0x1028 /* */ +typedef union _RF_CSR_CFG2_STRUC { + struct { + u32 RegIdAndContent:24; /* Register value to program into BBP */ + u32 rsv:8; /* 0: idle 1: 8busy */ + } field; + u32 word; +} RF_CSR_CFG2_STRUC, *PRF_CSR_CFG2_STRUC; +#define LED_CFG 0x102c /* MAC_CSR14 */ +typedef union _LED_CFG_STRUC { + struct { + u32 OnPeriod:8; /* blinking on period unit 1ms */ + u32 OffPeriod:8; /* blinking off period unit 1ms */ + u32 SlowBlinkPeriod:6; /* slow blinking period. unit:1ms */ + u32 rsv:2; + u32 RLedMode:2; /* red Led Mode 0: off1: blinking upon TX2: periodic slow blinking3: always on */ + u32 GLedMode:2; /* green Led Mode */ + u32 YLedMode:2; /* yellow Led Mode */ + u32 LedPolar:1; /* Led Polarity. 0: active low1: active high */ + u32 : 1; + } field; + u32 word; +} LED_CFG_STRUC, *PLED_CFG_STRUC; +/* */ +/* 4.2 MAC TIMING configuration registers (offset:0x1100) */ +/* */ +#define XIFS_TIME_CFG 0x1100 /* MAC_CSR8 MAC_CSR9 */ +typedef union _IFS_SLOT_CFG_STRUC { + struct { + u32 CckmSifsTime:8; /* unit 1us. Applied after CCK RX/TX */ + u32 OfdmSifsTime:8; /* unit 1us. Applied after OFDM RX/TX */ + u32 OfdmXifsTime:4; /*OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND */ + u32 EIFS:9; /* unit 1us */ + u32 BBRxendEnable:1; /* reference RXEND signal to begin XIFS defer */ + u32 rsv:2; + } field; + u32 word; +} IFS_SLOT_CFG_STRUC, *PIFS_SLOT_CFG_STRUC; + +#define BKOFF_SLOT_CFG 0x1104 /* mac_csr9 last 8 bits */ +#define NAV_TIME_CFG 0x1108 /* NAV (MAC_CSR15) */ +#define CH_TIME_CFG 0x110C /* Count as channel busy */ +#define PBF_LIFE_TIMER 0x1110 /*TX/RX MPDU timestamp timer (free run)Unit: 1us */ +#define BCN_TIME_CFG 0x1114 /* TXRX_CSR9 */ + +#define BCN_OFFSET0 0x042C +#define BCN_OFFSET1 0x0430 + +/* */ +/* BCN_TIME_CFG : Synchronization control register */ +/* */ +typedef union _BCN_TIME_CFG_STRUC { + struct { + u32 BeaconInterval:16; /* in unit of 1/16 TU */ + u32 bTsfTicking:1; /* Enable TSF auto counting */ + u32 TsfSyncMode:2; /* Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode */ + u32 bTBTTEnable:1; + u32 bBeaconGen:1; /* Enable beacon generator */ + u32 : 3; + u32 TxTimestampCompensate:8; + } field; + u32 word; +} BCN_TIME_CFG_STRUC, *PBCN_TIME_CFG_STRUC; +#define TBTT_SYNC_CFG 0x1118 /* txrx_csr10 */ +#define TSF_TIMER_DW0 0x111C /* Local TSF timer lsb 32 bits. Read-only */ +#define TSF_TIMER_DW1 0x1120 /* msb 32 bits. Read-only. */ +#define TBTT_TIMER 0x1124 /* TImer remains till next TBTT. Read-only. TXRX_CSR14 */ +#define INT_TIMER_CFG 0x1128 /* */ +#define INT_TIMER_EN 0x112c /* GP-timer and pre-tbtt Int enable */ +#define CH_IDLE_STA 0x1130 /* channel idle time */ +#define CH_BUSY_STA 0x1134 /* channle busy time */ +/* */ +/* 4.2 MAC POWER configuration registers (offset:0x1200) */ +/* */ +#define MAC_STATUS_CFG 0x1200 /* old MAC_CSR12 */ +#define PWR_PIN_CFG 0x1204 /* old MAC_CSR12 */ +#define AUTO_WAKEUP_CFG 0x1208 /* old MAC_CSR10 */ +/* */ +/* AUTO_WAKEUP_CFG: Manual power control / status register */ +/* */ +typedef union _AUTO_WAKEUP_STRUC { + struct { + u32 AutoLeadTime:8; + u32 NumofSleepingTbtt:7; /* ForceWake has high privilege than PutToSleep when both set */ + u32 EnableAutoWakeup:1; /* 0:sleep, 1:awake */ + u32 : 16; + } field; + u32 word; +} AUTO_WAKEUP_STRUC, *PAUTO_WAKEUP_STRUC; +/* */ +/* 4.3 MAC TX configuration registers (offset:0x1300) */ +/* */ + +#define EDCA_AC0_CFG 0x1300 /*AC_TXOP_CSR0 0x3474 */ +#define EDCA_AC1_CFG 0x1304 +#define EDCA_AC2_CFG 0x1308 +#define EDCA_AC3_CFG 0x130c +typedef union _EDCA_AC_CFG_STRUC { + struct { + u32 AcTxop:8; /* in unit of 32us */ + u32 Aifsn:4; /* # of slot time */ + u32 Cwmin:4; /* */ + u32 Cwmax:4; /*unit power of 2 */ + u32 : 12; /* */ + } field; + u32 word; +} EDCA_AC_CFG_STRUC, *PEDCA_AC_CFG_STRUC; + +#define EDCA_TID_AC_MAP 0x1310 +#define TX_PWR_CFG_0 0x1314 +#define TX_PWR_CFG_1 0x1318 +#define TX_PWR_CFG_2 0x131C +#define TX_PWR_CFG_3 0x1320 +#define TX_PWR_CFG_4 0x1324 +#define TX_PIN_CFG 0x1328 +#define TX_BAND_CFG 0x132c /* 0x1 use upper 20MHz. 0 juse lower 20MHz */ +#define TX_SW_CFG0 0x1330 +#define TX_SW_CFG1 0x1334 +#define TX_SW_CFG2 0x1338 +#define TXOP_THRES_CFG 0x133c +#define TXOP_CTRL_CFG 0x1340 +#define TX_RTS_CFG 0x1344 + +typedef union _TX_RTS_CFG_STRUC { + struct { + u32 AutoRtsRetryLimit:8; + u32 RtsThres:16; /* unit:byte */ + u32 RtsFbkEn:1; /* enable rts rate fallback */ + u32 rsv:7; /* 1: HT non-STBC control frame enable */ + } field; + u32 word; +} TX_RTS_CFG_STRUC, *PTX_RTS_CFG_STRUC; +#define TX_TIMEOUT_CFG 0x1348 +typedef union _TX_TIMEOUT_CFG_STRUC { + struct { + u32 rsv:4; + u32 MpduLifeTime:4; /* expiration time = 2^(9+MPDU LIFE TIME) us */ + u32 RxAckTimeout:8; /* unit:slot. Used for TX precedure */ + u32 TxopTimeout:8; /*TXOP timeout value for TXOP truncation. It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) */ + u32 rsv2:8; /* 1: HT non-STBC control frame enable */ + } field; + u32 word; +} TX_TIMEOUT_CFG_STRUC, *PTX_TIMEOUT_CFG_STRUC; +#define TX_RTY_CFG 0x134c +typedef union PACKED _TX_RTY_CFG_STRUC { + struct { + u32 ShortRtyLimit:8; /* short retry limit */ + u32 LongRtyLimit:8; /*long retry limit */ + u32 LongRtyThre:12; /* Long retry threshoold */ + u32 NonAggRtyMode:1; /* Non-Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer */ + u32 AggRtyMode:1; /* Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer */ + u32 TxautoFBEnable:1; /* Tx retry PHY rate auto fallback enable */ + u32 rsv:1; /* 1: HT non-STBC control frame enable */ + } field; + u32 word; +} TX_RTY_CFG_STRUC, *PTX_RTY_CFG_STRUC; +#define TX_LINK_CFG 0x1350 +typedef union PACKED _TX_LINK_CFG_STRUC { + struct PACKED { + u32 RemoteMFBLifeTime:8; /*remote MFB life time. unit : 32us */ + u32 MFBEnable:1; /* TX apply remote MFB 1:enable */ + u32 RemoteUMFSEnable:1; /* remote unsolicit MFB enable. 0: not apply remote remote unsolicit (MFS=7) */ + u32 TxMRQEn:1; /* MCS request TX enable */ + u32 TxRDGEn:1; /* RDG TX enable */ + u32 TxCFAckEn:1; /* Piggyback CF-ACK enable */ + u32 rsv:3; /* */ + u32 RemotMFB:8; /* remote MCS feedback */ + u32 RemotMFS:8; /*remote MCS feedback sequence number */ + } field; + u32 word; +} TX_LINK_CFG_STRUC, *PTX_LINK_CFG_STRUC; +#define HT_FBK_CFG0 0x1354 +typedef union PACKED _HT_FBK_CFG0_STRUC { + struct { + u32 HTMCS0FBK:4; + u32 HTMCS1FBK:4; + u32 HTMCS2FBK:4; + u32 HTMCS3FBK:4; + u32 HTMCS4FBK:4; + u32 HTMCS5FBK:4; + u32 HTMCS6FBK:4; + u32 HTMCS7FBK:4; + } field; + u32 word; +} HT_FBK_CFG0_STRUC, *PHT_FBK_CFG0_STRUC; +#define HT_FBK_CFG1 0x1358 +typedef union _HT_FBK_CFG1_STRUC { + struct { + u32 HTMCS8FBK:4; + u32 HTMCS9FBK:4; + u32 HTMCS10FBK:4; + u32 HTMCS11FBK:4; + u32 HTMCS12FBK:4; + u32 HTMCS13FBK:4; + u32 HTMCS14FBK:4; + u32 HTMCS15FBK:4; + } field; + u32 word; +} HT_FBK_CFG1_STRUC, *PHT_FBK_CFG1_STRUC; +#define LG_FBK_CFG0 0x135c +typedef union _LG_FBK_CFG0_STRUC { + struct { + u32 OFDMMCS0FBK:4; /*initial value is 0 */ + u32 OFDMMCS1FBK:4; /*initial value is 0 */ + u32 OFDMMCS2FBK:4; /*initial value is 1 */ + u32 OFDMMCS3FBK:4; /*initial value is 2 */ + u32 OFDMMCS4FBK:4; /*initial value is 3 */ + u32 OFDMMCS5FBK:4; /*initial value is 4 */ + u32 OFDMMCS6FBK:4; /*initial value is 5 */ + u32 OFDMMCS7FBK:4; /*initial value is 6 */ + } field; + u32 word; +} LG_FBK_CFG0_STRUC, *PLG_FBK_CFG0_STRUC; +#define LG_FBK_CFG1 0x1360 +typedef union _LG_FBK_CFG1_STRUC { + struct { + u32 CCKMCS0FBK:4; /*initial value is 0 */ + u32 CCKMCS1FBK:4; /*initial value is 0 */ + u32 CCKMCS2FBK:4; /*initial value is 1 */ + u32 CCKMCS3FBK:4; /*initial value is 2 */ + u32 rsv:16; + } field; + u32 word; +} LG_FBK_CFG1_STRUC, *PLG_FBK_CFG1_STRUC; + +/*======================================================= */ +/*================ Protection Paramater================================ */ +/*======================================================= */ +#define CCK_PROT_CFG 0x1364 /*CCK Protection */ +#define ASIC_SHORTNAV 1 +#define ASIC_longNAV 2 +#define ASIC_RTS 1 +#define ASIC_CTS 2 +typedef union _PROT_CFG_STRUC { + struct { + u32 ProtectRate:16; /*Protection control frame rate for CCK TX(RTS/CTS/CFEnd). */ + u32 ProtectCtrl:2; /*Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv */ + u32 ProtectNav:2; /*TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect, 2:LongNAVProtect, 3:rsv */ + u32 TxopAllowCck:1; /*CCK TXOP allowance.0:disallow. */ + u32 TxopAllowOfdm:1; /*CCK TXOP allowance.0:disallow. */ + u32 TxopAllowMM20:1; /*CCK TXOP allowance. 0:disallow. */ + u32 TxopAllowMM40:1; /*CCK TXOP allowance.0:disallow. */ + u32 TxopAllowGF20:1; /*CCK TXOP allowance.0:disallow. */ + u32 TxopAllowGF40:1; /*CCK TXOP allowance.0:disallow. */ + u32 RTSThEn:1; /*RTS threshold enable on CCK TX */ + u32 rsv:5; + } field; + u32 word; +} PROT_CFG_STRUC, *PPROT_CFG_STRUC; + +#define OFDM_PROT_CFG 0x1368 /*OFDM Protection */ +#define MM20_PROT_CFG 0x136C /*MM20 Protection */ +#define MM40_PROT_CFG 0x1370 /*MM40 Protection */ +#define GF20_PROT_CFG 0x1374 /*GF20 Protection */ +#define GF40_PROT_CFG 0x1378 /*GR40 Protection */ +#define EXP_CTS_TIME 0x137C /* */ +#define EXP_ACK_TIME 0x1380 /* */ + +/* */ +/* 4.4 MAC RX configuration registers (offset:0x1400) */ +/* */ +#define RX_FILTR_CFG 0x1400 /*TXRX_CSR0 */ +#define AUTO_RSP_CFG 0x1404 /*TXRX_CSR4 */ +/* */ +/* TXRX_CSR4: Auto-Responder/ */ +/* */ +typedef union _AUTO_RSP_CFG_STRUC { + struct { + u32 AutoResponderEnable:1; + u32 BACAckPolicyEnable:1; /* 0:long, 1:short preamble */ + u32 CTS40MMode:1; /* Response CTS 40MHz duplicate mode */ + u32 CTS40MRef:1; /* Response CTS 40MHz duplicate mode */ + u32 AutoResponderPreamble:1; /* 0:long, 1:short preamble */ + u32 rsv:1; /* Power bit value in conrtrol frame */ + u32 DualCTSEn:1; /* Power bit value in conrtrol frame */ + u32 AckCtsPsmBit:1; /* Power bit value in conrtrol frame */ + u32 : 24; + } field; + u32 word; +} AUTO_RSP_CFG_STRUC, *PAUTO_RSP_CFG_STRUC; + +#define LEGACY_BASIC_RATE 0x1408 /* TXRX_CSR5 0x3054 */ +#define HT_BASIC_RATE 0x140c +#define HT_CTRL_CFG 0x1410 +#define SIFS_COST_CFG 0x1414 +#define RX_PARSER_CFG 0x1418 /*Set NAV for all received frames */ + +/* */ +/* 4.5 MAC Security configuration (offset:0x1500) */ +/* */ +#define TX_SEC_CNT0 0x1500 /* */ +#define RX_SEC_CNT0 0x1504 /* */ +#define CCMP_FC_MUTE 0x1508 /* */ +/* */ +/* 4.6 HCCA/PSMP (offset:0x1600) */ +/* */ +#define TXOP_HLDR_ADDR0 0x1600 +#define TXOP_HLDR_ADDR1 0x1604 +#define TXOP_HLDR_ET 0x1608 +#define QOS_CFPOLL_RA_DW0 0x160c +#define QOS_CFPOLL_A1_DW1 0x1610 +#define QOS_CFPOLL_QC 0x1614 +/* */ +/* 4.7 MAC Statistis registers (offset:0x1700) */ +/* */ +#define RX_STA_CNT0 0x1700 /* */ +#define RX_STA_CNT1 0x1704 /* */ +#define RX_STA_CNT2 0x1708 /* */ + +/* */ +/* RX_STA_CNT0_STRUC: RX PLCP error count & RX CRC error count */ +/* */ +typedef union _RX_STA_CNT0_STRUC { + struct { + u16 CrcErr; + u16 PhyErr; + } field; + u32 word; +} RX_STA_CNT0_STRUC, *PRX_STA_CNT0_STRUC; + +/* */ +/* RX_STA_CNT1_STRUC: RX False CCA count & RX long frame count */ +/* */ +typedef union _RX_STA_CNT1_STRUC { + struct { + u16 FalseCca; + u16 PlcpErr; + } field; + u32 word; +} RX_STA_CNT1_STRUC, *PRX_STA_CNT1_STRUC; + +/* */ +/* RX_STA_CNT2_STRUC: */ +/* */ +typedef union _RX_STA_CNT2_STRUC { + struct { + u16 RxDupliCount; + u16 RxFifoOverflowCount; + } field; + u32 word; +} RX_STA_CNT2_STRUC, *PRX_STA_CNT2_STRUC; +#define TX_STA_CNT0 0x170C /* */ +/* */ +/* STA_CSR3: TX Beacon count */ +/* */ +typedef union _TX_STA_CNT0_STRUC { + struct { + u16 TxFailCount; + u16 TxBeaconCount; + } field; + u32 word; +} TX_STA_CNT0_STRUC, *PTX_STA_CNT0_STRUC; +#define TX_STA_CNT1 0x1710 /* */ +/* */ +/* TX_STA_CNT1: TX tx count */ +/* */ +typedef union _TX_STA_CNT1_STRUC { + struct { + u16 TxSuccess; + u16 TxRetransmit; + } field; + u32 word; +} TX_STA_CNT1_STRUC, *PTX_STA_CNT1_STRUC; +#define TX_STA_CNT2 0x1714 /* */ +/* */ +/* TX_STA_CNT2: TX tx count */ +/* */ +typedef union _TX_STA_CNT2_STRUC { + struct { + u16 TxZeroLenCount; + u16 TxUnderFlowCount; + } field; + u32 word; +} TX_STA_CNT2_STRUC, *PTX_STA_CNT2_STRUC; +#define TX_STA_FIFO 0x1718 /* */ +/* */ +/* TX_STA_FIFO_STRUC: TX Result for specific PID status fifo register */ +/* */ +typedef union PACKED _TX_STA_FIFO_STRUC { + struct { + u32 bValid:1; /* 1:This register contains a valid TX result */ + u32 PidType:4; + u32 TxSuccess:1; /* Tx No retry success */ + u32 TxAggre:1; /* Tx Retry Success */ + u32 TxAckRequired:1; /* Tx fail */ + u32 wcid:8; /*wireless client index */ +/* u32 SuccessRate:16; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. */ + u32 SuccessRate:13; /*include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. */ + u32 TxBF:1; + u32 Reserve:2; + } field; + u32 word; +} TX_STA_FIFO_STRUC, *PTX_STA_FIFO_STRUC; +/* Debug counter */ +#define TX_AGG_CNT 0x171c +typedef union _TX_AGG_CNT_STRUC { + struct { + u16 NonAggTxCount; + u16 AggTxCount; + } field; + u32 word; +} TX_AGG_CNT_STRUC, *PTX_AGG_CNT_STRUC; +/* Debug counter */ +#define TX_AGG_CNT0 0x1720 +typedef union _TX_AGG_CNT0_STRUC { + struct { + u16 AggSize1Count; + u16 AggSize2Count; + } field; + u32 word; +} TX_AGG_CNT0_STRUC, *PTX_AGG_CNT0_STRUC; +/* Debug counter */ +#define TX_AGG_CNT1 0x1724 +typedef union _TX_AGG_CNT1_STRUC { + struct { + u16 AggSize3Count; + u16 AggSize4Count; + } field; + u32 word; +} TX_AGG_CNT1_STRUC, *PTX_AGG_CNT1_STRUC; +#define TX_AGG_CNT2 0x1728 +typedef union _TX_AGG_CNT2_STRUC { + struct { + u16 AggSize5Count; + u16 AggSize6Count; + } field; + u32 word; +} TX_AGG_CNT2_STRUC, *PTX_AGG_CNT2_STRUC; +/* Debug counter */ +#define TX_AGG_CNT3 0x172c +typedef union _TX_AGG_CNT3_STRUC { + struct { + u16 AggSize7Count; + u16 AggSize8Count; + } field; + u32 word; +} TX_AGG_CNT3_STRUC, *PTX_AGG_CNT3_STRUC; +/* Debug counter */ +#define TX_AGG_CNT4 0x1730 +typedef union _TX_AGG_CNT4_STRUC { + struct { + u16 AggSize9Count; + u16 AggSize10Count; + } field; + u32 word; +} TX_AGG_CNT4_STRUC, *PTX_AGG_CNT4_STRUC; +#define TX_AGG_CNT5 0x1734 +typedef union _TX_AGG_CNT5_STRUC { + struct { + u16 AggSize11Count; + u16 AggSize12Count; + } field; + u32 word; +} TX_AGG_CNT5_STRUC, *PTX_AGG_CNT5_STRUC; +#define TX_AGG_CNT6 0x1738 +typedef union _TX_AGG_CNT6_STRUC { + struct { + u16 AggSize13Count; + u16 AggSize14Count; + } field; + u32 word; +} TX_AGG_CNT6_STRUC, *PTX_AGG_CNT6_STRUC; +#define TX_AGG_CNT7 0x173c +typedef union _TX_AGG_CNT7_STRUC { + struct { + u16 AggSize15Count; + u16 AggSize16Count; + } field; + u32 word; +} TX_AGG_CNT7_STRUC, *PTX_AGG_CNT7_STRUC; +#define MPDU_DENSITY_CNT 0x1740 +typedef union _MPDU_DEN_CNT_STRUC { + struct { + u16 TXZeroDelCount; /*TX zero length delimiter count */ + u16 RXZeroDelCount; /*RX zero length delimiter count */ + } field; + u32 word; +} MPDU_DEN_CNT_STRUC, *PMPDU_DEN_CNT_STRUC; +/* */ +/* TXRX control registers - base address 0x3000 */ +/* */ +/* rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. */ +#define TXRX_CSR1 0x77d0 + +/* */ +/* Security key table memory, base address = 0x1000 */ +/* */ +#define MAC_WCID_BASE 0x1800 /*8-bytes(use only 6-bytes) * 256 entry = */ +#define HW_WCID_ENTRY_SIZE 8 +#define PAIRWISE_KEY_TABLE_BASE 0x4000 /* 32-byte * 256-entry = -byte */ +#define HW_KEY_ENTRY_SIZE 0x20 +#define PAIRWISE_IVEIV_TABLE_BASE 0x6000 /* 8-byte * 256-entry = -byte */ +#define MAC_IVEIV_TABLE_BASE 0x6000 /* 8-byte * 256-entry = -byte */ +#define HW_IVEIV_ENTRY_SIZE 8 +#define MAC_WCID_ATTRIBUTE_BASE 0x6800 /* 4-byte * 256-entry = -byte */ +#define HW_WCID_ATTRI_SIZE 4 +#define WCID_RESERVED 0x6bfc +#define SHARED_KEY_TABLE_BASE 0x6c00 /* 32-byte * 16-entry = 512-byte */ +#define SHARED_KEY_MODE_BASE 0x7000 /* 32-byte * 16-entry = 512-byte */ +#define HW_SHARED_KEY_MODE_SIZE 4 +#define SHAREDKEYTABLE 0 +#define PAIRWISEKEYTABLE 1 + +typedef union _SHAREDKEY_MODE_STRUC { + struct { + u32 Bss0Key0CipherAlg:3; + u32 : 1; + u32 Bss0Key1CipherAlg:3; + u32 : 1; + u32 Bss0Key2CipherAlg:3; + u32 : 1; + u32 Bss0Key3CipherAlg:3; + u32 : 1; + u32 Bss1Key0CipherAlg:3; + u32 : 1; + u32 Bss1Key1CipherAlg:3; + u32 : 1; + u32 Bss1Key2CipherAlg:3; + u32 : 1; + u32 Bss1Key3CipherAlg:3; + u32 : 1; + } field; + u32 word; +} SHAREDKEY_MODE_STRUC, *PSHAREDKEY_MODE_STRUC; + +/* 8-byte per entry, 64-entry for pairwise key table */ +struct rt_hw_wcid_entry { + u8 Address[6]; + u8 Rsv[2]; +}; + +/* ================================================================================= */ +/* WCID format */ +/* ================================================================================= */ +/*7.1 WCID ENTRY format : 8bytes */ +struct rt_wcid_entry { + u8 RXBABitmap7; /* bit0 for TID8, bit7 for TID 15 */ + u8 RXBABitmap0; /* bit0 for TID0, bit7 for TID 7 */ + u8 MAC[6]; /* 0 for shared key table. 1 for pairwise key table */ +}; + +/*8.1.1 SECURITY KEY format : 8DW */ +/* 32-byte per entry, total 16-entry for shared key table, 64-entry for pairwise key table */ +struct rt_hw_key_entry { + u8 Key[16]; + u8 TxMic[8]; + u8 RxMic[8]; +}; + +/*8.1.2 IV/EIV format : 2DW */ + +/*8.1.3 RX attribute entry format : 1DW */ +struct rt_mac_attribute { + u32 KeyTab:1; /* 0 for shared key table. 1 for pairwise key table */ + u32 PairKeyMode:3; + u32 BSSIDIdx:3; /*multipleBSS index for the WCID */ + u32 RXWIUDF:3; + u32 rsv:22; +}; + +/* ================================================================================= */ +/* HOST-MCU communication data structure */ +/* ================================================================================= */ + +/* */ +/* H2M_MAILBOX_CSR: Host-to-MCU Mailbox */ +/* */ +typedef union _H2M_MAILBOX_STRUC { + struct { + u32 LowByte:8; + u32 HighByte:8; + u32 CmdToken:8; + u32 Owner:8; + } field; + u32 word; +} H2M_MAILBOX_STRUC, *PH2M_MAILBOX_STRUC; + +/* */ +/* M2H_CMD_DONE_CSR: MCU-to-Host command complete indication */ +/* */ +typedef union _M2H_CMD_DONE_STRUC { + struct { + u32 CmdToken0; + u32 CmdToken1; + u32 CmdToken2; + u32 CmdToken3; + } field; + u32 word; +} M2H_CMD_DONE_STRUC, *PM2H_CMD_DONE_STRUC; + +/*NAV_TIME_CFG :NAV */ +typedef union _NAV_TIME_CFG_STRUC { + struct { + u8 Sifs; /* in unit of 1-us */ + u8 SlotTime; /* in unit of 1-us */ + u16 Eifs:9; /* in unit of 1-us */ + u16 ZeroSifs:1; /* Applied zero SIFS timer after OFDM RX 0: disable */ + u16 rsv:6; + } field; + u32 word; +} NAV_TIME_CFG_STRUC, *PNAV_TIME_CFG_STRUC; + +/* */ +/* RX_FILTR_CFG: /RX configuration register */ +/* */ +typedef union _RX_FILTR_CFG_STRUC { + struct { + u32 DropCRCErr:1; /* Drop CRC error */ + u32 DropPhyErr:1; /* Drop physical error */ + u32 DropNotToMe:1; /* Drop not to me unicast frame */ + u32 DropNotMyBSSID:1; /* Drop fram ToDs bit is true */ + + u32 DropVerErr:1; /* Drop version error frame */ + u32 DropMcast:1; /* Drop multicast frames */ + u32 DropBcast:1; /* Drop broadcast frames */ + u32 DropDuplicate:1; /* Drop duplicate frame */ + + u32 DropCFEndAck:1; /* Drop Ps-Poll */ + u32 DropCFEnd:1; /* Drop Ps-Poll */ + u32 DropAck:1; /* Drop Ps-Poll */ + u32 DropCts:1; /* Drop Ps-Poll */ + + u32 DropRts:1; /* Drop Ps-Poll */ + u32 DropPsPoll:1; /* Drop Ps-Poll */ + u32 DropBA:1; /* */ + u32 DropBAR:1; /* */ + + u32 DropRsvCntlType:1; + u32 : 15; + } field; + u32 word; +} RX_FILTR_CFG_STRUC, *PRX_FILTR_CFG_STRUC; + +/* */ +/* PHY_CSR4: RF serial control register */ +/* */ +typedef union _PHY_CSR4_STRUC { + struct { + u32 RFRegValue:24; /* Register value (include register id) serial out to RF/IF chip. */ + u32 NumberOfBits:5; /* Number of bits used in RFRegValue (I:20, RFMD:22) */ + u32 IFSelect:1; /* 1: select IF to program, 0: select RF to program */ + u32 PLL_LD:1; /* RF PLL_LD status */ + u32 Busy:1; /* 1: ASIC is busy execute RF programming. */ + } field; + u32 word; +} PHY_CSR4_STRUC, *PPHY_CSR4_STRUC; + +/* */ +/* SEC_CSR5: shared key table security mode register */ +/* */ +typedef union _SEC_CSR5_STRUC { + struct { + u32 Bss2Key0CipherAlg:3; + u32 : 1; + u32 Bss2Key1CipherAlg:3; + u32 : 1; + u32 Bss2Key2CipherAlg:3; + u32 : 1; + u32 Bss2Key3CipherAlg:3; + u32 : 1; + u32 Bss3Key0CipherAlg:3; + u32 : 1; + u32 Bss3Key1CipherAlg:3; + u32 : 1; + u32 Bss3Key2CipherAlg:3; + u32 : 1; + u32 Bss3Key3CipherAlg:3; + u32 : 1; + } field; + u32 word; +} SEC_CSR5_STRUC, *PSEC_CSR5_STRUC; + +/* */ +/* HOST_CMD_CSR: For HOST to interrupt embedded processor */ +/* */ +typedef union _HOST_CMD_CSR_STRUC { + struct { + u32 HostCommand:8; + u32 Rsv:24; + } field; + u32 word; +} HOST_CMD_CSR_STRUC, *PHOST_CMD_CSR_STRUC; + +/* */ +/* AIFSN_CSR: AIFSN for each EDCA AC */ +/* */ + +/* */ +/* E2PROM_CSR: EEPROM control register */ +/* */ +typedef union _E2PROM_CSR_STRUC { + struct { + u32 Reload:1; /* Reload EEPROM content, write one to reload, self-cleared. */ + u32 EepromSK:1; + u32 EepromCS:1; + u32 EepromDI:1; + u32 EepromDO:1; + u32 Type:1; /* 1: 93C46, 0:93C66 */ + u32 LoadStatus:1; /* 1:loading, 0:done */ + u32 Rsvd:25; + } field; + u32 word; +} E2PROM_CSR_STRUC, *PE2PROM_CSR_STRUC; + +/* */ +/* QOS_CSR0: TXOP holder address0 register */ +/* */ +typedef union _QOS_CSR0_STRUC { + struct { + u8 Byte0; /* MAC address byte 0 */ + u8 Byte1; /* MAC address byte 1 */ + u8 Byte2; /* MAC address byte 2 */ + u8 Byte3; /* MAC address byte 3 */ + } field; + u32 word; +} QOS_CSR0_STRUC, *PQOS_CSR0_STRUC; + +/* */ +/* QOS_CSR1: TXOP holder address1 register */ +/* */ +typedef union _QOS_CSR1_STRUC { + struct { + u8 Byte4; /* MAC address byte 4 */ + u8 Byte5; /* MAC address byte 5 */ + u8 Rsvd0; + u8 Rsvd1; + } field; + u32 word; +} QOS_CSR1_STRUC, *PQOS_CSR1_STRUC; + +#define RF_CSR_CFG 0x500 +typedef union _RF_CSR_CFG_STRUC { + struct { + u32 RF_CSR_DATA:8; /* DATA */ + u32 TESTCSR_RFACC_REGNUM:5; /* RF register ID */ + u32 Rsvd2:3; /* Reserved */ + u32 RF_CSR_WR:1; /* 0: read 1: write */ + u32 RF_CSR_KICK:1; /* kick RF register read/write */ + u32 Rsvd1:14; /* Reserved */ + } field; + u32 word; +} RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC; + +/* */ +/* Other on-chip shared memory space, base = 0x2000 */ +/* */ + +/* CIS space - base address = 0x2000 */ +#define HW_CIS_BASE 0x2000 + +/* Carrier-sense CTS frame base address. It's where mac stores carrier-sense frame for carrier-sense function. */ +#define HW_CS_CTS_BASE 0x7700 +/* DFS CTS frame base address. It's where mac stores CTS frame for DFS. */ +#define HW_DFS_CTS_BASE 0x7780 +#define HW_CTS_FRAME_SIZE 0x80 + +/* 2004-11-08 john - since NULL frame won't be that long (256 byte). We steal 16 tail bytes */ +/* to save debugging settings */ +#define HW_DEBUG_SETTING_BASE 0x77f0 /* 0x77f0~0x77ff total 16 bytes */ +#define HW_DEBUG_SETTING_BASE2 0x7770 /* 0x77f0~0x77ff total 16 bytes */ + +/* In order to support maximum 8 MBSS and its maximum length is 512 for each beacon */ +/* Three section discontinue memory segments will be used. */ +/* 1. The original region for BCN 0~3 */ +/* 2. Extract memory from FCE table for BCN 4~5 */ +/* 3. Extract memory from Pair-wise key table for BCN 6~7 */ +/* It occupied those memory of wcid 238~253 for BCN 6 */ +/* and wcid 222~237 for BCN 7 */ +#define HW_BEACON_MAX_SIZE 0x1000 /* unit: byte */ +#define HW_BEACON_BASE0 0x7800 +#define HW_BEACON_BASE1 0x7A00 +#define HW_BEACON_BASE2 0x7C00 +#define HW_BEACON_BASE3 0x7E00 +#define HW_BEACON_BASE4 0x7200 +#define HW_BEACON_BASE5 0x7400 +#define HW_BEACON_BASE6 0x5DC0 +#define HW_BEACON_BASE7 0x5BC0 + +#define HW_BEACON_MAX_COUNT 8 +#define HW_BEACON_OFFSET 0x0200 +#define HW_BEACON_CONTENT_LEN (HW_BEACON_OFFSET - TXWI_SIZE) + +/* HOST-MCU shared memory - base address = 0x2100 */ +#define HOST_CMD_CSR 0x404 +#define H2M_MAILBOX_CSR 0x7010 +#define H2M_MAILBOX_CID 0x7014 +#define H2M_MAILBOX_STATUS 0x701c +#define H2M_INT_SRC 0x7024 +#define H2M_BBP_AGENT 0x7028 +#define M2H_CMD_DONE_CSR 0x000c +#define MCU_TXOP_ARRAY_BASE 0x000c /* TODO: to be provided by Albert */ +#define MCU_TXOP_ENTRY_SIZE 32 /* TODO: to be provided by Albert */ +#define MAX_NUM_OF_TXOP_ENTRY 16 /* TODO: must be same with 8051 firmware */ +#define MCU_MBOX_VERSION 0x01 /* TODO: to be confirmed by Albert */ +#define MCU_MBOX_VERSION_OFFSET 5 /* TODO: to be provided by Albert */ + +/* */ +/* Host DMA registers - base address 0x200 . TX0-3=EDCAQid0-3, TX4=HCCA, TX5=MGMT, */ +/* */ +/* */ +/* DMA RING DESCRIPTOR */ +/* */ +#define E2PROM_CSR 0x0004 +#define IO_CNTL_CSR 0x77d0 + +/* ================================================================ */ +/* Tx / Rx / Mgmt ring descriptor definition */ +/* ================================================================ */ + +/* the following PID values are used to mark outgoing frame type in TXD->PID so that */ +/* proper TX statistics can be collected based on these categories */ +/* b3-2 of PID field - */ +#define PID_MGMT 0x05 +#define PID_BEACON 0x0c +#define PID_DATA_NORMALUCAST 0x02 +#define PID_DATA_AMPDU 0x04 +#define PID_DATA_NO_ACK 0x08 +#define PID_DATA_NOT_NORM_ACK 0x03 +/* value domain of pTxD->HostQId (4-bit: 0~15) */ +#define QID_AC_BK 1 /* meet ACI definition in 802.11e */ +#define QID_AC_BE 0 /* meet ACI definition in 802.11e */ +#define QID_AC_VI 2 +#define QID_AC_VO 3 +#define QID_HCCA 4 +#define NUM_OF_TX_RING 4 +#define QID_MGMT 13 +#define QID_RX 14 +#define QID_OTHER 15 + +#endif /* __RTMP_MAC_H__ // */ diff --git a/drivers/staging/rt3090/rtmp_phy.h b/drivers/staging/rt2860/chip/rtmp_phy.h similarity index 78% rename from drivers/staging/rt3090/rtmp_phy.h rename to drivers/staging/rt2860/chip/rtmp_phy.h index b9848cac282e055ce4847d686209106ea0f1e7fe..8b8b0f47f03bc074903767f1a9916a6f75d5e4a3 100644 --- a/drivers/staging/rt3090/rtmp_phy.h +++ b/drivers/staging/rt2860/chip/rtmp_phy.h @@ -38,7 +38,6 @@ #ifndef __RTMP_PHY_H__ #define __RTMP_PHY_H__ - /* RF sections */ @@ -75,31 +74,30 @@ #define RF_R30 30 #define RF_R31 31 - -// value domain of pAd->RfIcType -#define RFIC_2820 1 // 2.4G 2T3R -#define RFIC_2850 2 // 2.4G/5G 2T3R -#define RFIC_2720 3 // 2.4G 1T2R -#define RFIC_2750 4 // 2.4G/5G 1T2R -#define RFIC_3020 5 // 2.4G 1T1R -#define RFIC_2020 6 // 2.4G B/G -#define RFIC_3021 7 // 2.4G 1T2R -#define RFIC_3022 8 // 2.4G 2T2R -#define RFIC_3052 9 // 2.4G/5G 2T2R +/* value domain of pAd->RfIcType */ +#define RFIC_2820 1 /* 2.4G 2T3R */ +#define RFIC_2850 2 /* 2.4G/5G 2T3R */ +#define RFIC_2720 3 /* 2.4G 1T2R */ +#define RFIC_2750 4 /* 2.4G/5G 1T2R */ +#define RFIC_3020 5 /* 2.4G 1T1R */ +#define RFIC_2020 6 /* 2.4G B/G */ +#define RFIC_3021 7 /* 2.4G 1T2R */ +#define RFIC_3022 8 /* 2.4G 2T2R */ +#define RFIC_3052 9 /* 2.4G/5G 2T2R */ /* BBP sections */ -#define BBP_R0 0 // version -#define BBP_R1 1 // TSSI -#define BBP_R2 2 // TX configure +#define BBP_R0 0 /* version */ +#define BBP_R1 1 /* TSSI */ +#define BBP_R2 2 /* TX configure */ #define BBP_R3 3 #define BBP_R4 4 #define BBP_R5 5 #define BBP_R6 6 -#define BBP_R14 14 // RX configure +#define BBP_R14 14 /* RX configure */ #define BBP_R16 16 -#define BBP_R17 17 // RX sensibility +#define BBP_R17 17 /* RX sensibility */ #define BBP_R18 18 #define BBP_R21 21 #define BBP_R22 22 @@ -108,12 +106,12 @@ #define BBP_R26 26 #define BBP_R27 27 #define BBP_R31 31 -#define BBP_R49 49 //TSSI +#define BBP_R49 49 /*TSSI */ #define BBP_R50 50 #define BBP_R51 51 #define BBP_R52 52 #define BBP_R55 55 -#define BBP_R62 62 // Rx SQ0 Threshold HIGH +#define BBP_R62 62 /* Rx SQ0 Threshold HIGH */ #define BBP_R63 63 #define BBP_R64 64 #define BBP_R65 65 @@ -121,7 +119,7 @@ #define BBP_R67 67 #define BBP_R68 68 #define BBP_R69 69 -#define BBP_R70 70 // Rx AGC SQ CCK Xcorr threshold +#define BBP_R70 70 /* Rx AGC SQ CCK Xcorr threshold */ #define BBP_R73 73 #define BBP_R75 75 #define BBP_R77 77 @@ -135,7 +133,7 @@ #define BBP_R86 86 #define BBP_R91 91 #define BBP_R92 92 -#define BBP_R94 94 // Tx Gain Control +#define BBP_R94 94 /* Tx Gain Control */ #define BBP_R103 103 #define BBP_R105 105 #define BBP_R106 106 @@ -151,39 +149,22 @@ #define BBP_R122 122 #define BBP_R123 123 #ifdef RT30xx -#define BBP_R138 138 // add by johnli, RF power sequence setup, ADC dynamic on/off control -#endif // RT30xx // - - -#define BBPR94_DEFAULT 0x06 // Add 1 value will gain 1db - - -#ifdef MERGE_ARCH_TEAM - #define MAX_BBP_ID 200 - #define MAX_BBP_MSG_SIZE 4096 -#else -#ifdef RT30xx - // edit by johnli, RF power sequence setup, add BBP R138 for ADC dynamic on/off control - #define MAX_BBP_ID 138 -#endif // RT30xx // -#ifndef RT30xx - #define MAX_BBP_ID 136 -#endif // RT30xx // - #define MAX_BBP_MSG_SIZE 2048 -#endif // MERGE_ARCH_TEAM // +#define BBP_R138 138 /* add by johnli, RF power sequence setup, ADC dynamic on/off control */ +#endif /* RT30xx // */ +#define BBPR94_DEFAULT 0x06 /* Add 1 value will gain 1db */ -// -// BBP & RF are using indirect access. Before write any value into it. -// We have to make sure there is no outstanding command pending via checking busy bit. -// -#define MAX_BUSY_COUNT 100 // Number of retry before failing access BBP & RF indirect register +/* */ +/* BBP & RF are using indirect access. Before write any value into it. */ +/* We have to make sure there is no outstanding command pending via checking busy bit. */ +/* */ +#define MAX_BUSY_COUNT 100 /* Number of retry before failing access BBP & RF indirect register */ -//#define PHY_TR_SWITCH_TIME 5 // usec +/*#define PHY_TR_SWITCH_TIME 5 // usec */ -//#define BBP_R17_LOW_SENSIBILITY 0x50 -//#define BBP_R17_MID_SENSIBILITY 0x41 -//#define BBP_R17_DYNAMIC_UP_BOUND 0x40 +/*#define BBP_R17_LOW_SENSIBILITY 0x50 */ +/*#define BBP_R17_MID_SENSIBILITY 0x41 */ +/*#define BBP_R17_DYNAMIC_UP_BOUND 0x40 */ #define RSSI_FOR_VERY_LOW_SENSIBILITY -35 #define RSSI_FOR_LOW_SENSIBILITY -58 @@ -199,7 +180,7 @@ if ((_A)->bPCIclkOff == FALSE) \ { \ PHY_CSR4_STRUC _value; \ - ULONG _busyCnt = 0; \ + unsigned long _busyCnt = 0; \ \ do { \ RTMP_IO_READ32((_A), RF_CSR_CFG0, &_value.word); \ @@ -213,15 +194,15 @@ } \ } \ } -#endif // RTMP_MAC_PCI // - - +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB +#define RTMP_RF_IO_WRITE32(_A, _V) RTUSBWriteRFRegister(_A, _V) +#endif /* RTMP_MAC_USB // */ #ifdef RT30xx #define RTMP_RF_IO_READ8_BY_REG_ID(_A, _I, _pV) RT30xxReadRFRegister(_A, _I, _pV) #define RTMP_RF_IO_WRITE8_BY_REG_ID(_A, _I, _V) RT30xxWriteRFRegister(_A, _I, _V) -#endif // RT30xx // - +#endif /* RT30xx // */ /***************************************************************************** BBP register Read/Write marco definitions. @@ -231,7 +212,7 @@ #ifdef RTMP_MAC_PCI /* basic marco for BBP read operation. - _pAd: the data structure pointer of RTMP_ADAPTER + _pAd: the data structure pointer of struct rt_rtmp_adapter _bbpID : the bbp register ID _pV: data pointer used to save the value of queried bbp register. _bViaMCU: if we need access the bbp via the MCU. @@ -267,7 +248,7 @@ if ((BbpCsr.field.Busy == IDLE) && \ (BbpCsr.field.RegNum == _bbpID)) \ { \ - *(_pV) = (UCHAR)BbpCsr.field.Value; \ + *(_pV) = (u8)BbpCsr.field.Value; \ break; \ } \ } \ @@ -295,20 +276,7 @@ But for some chipset which didn't have mcu (e.g., RBUS based chipset), we will use this function too and didn't access the bbp register via the MCU. */ -#ifndef CONFIG_STA_SUPPORT -#define RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \ - do{ \ - if ((_A)->bPCIclkOff == FALSE) \ - { \ - if ((_A)->infType == RTMP_DEV_INF_RBUS) \ - RTMP_BBP_IO_READ8((_A), (_I), (_pV), FALSE); \ - else \ - RTMP_BBP_IO_READ8((_A), (_I), (_pV), TRUE); \ - } \ - }while(0) -#endif // CONFIG_STA_SUPPORT // -#ifdef CONFIG_STA_SUPPORT -// Read BBP register by register's ID. Generate PER to test BA +/* Read BBP register by register's ID. Generate PER to test BA */ #define RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \ { \ BBP_CSR_CFG_STRUC BbpCsr; \ @@ -345,7 +313,7 @@ if ((BbpCsr.field.Busy == IDLE) && \ (BbpCsr.field.RegNum == _I)) \ { \ - *(_pV) = (UCHAR)BbpCsr.field.Value; \ + *(_pV) = (u8)BbpCsr.field.Value; \ break; \ } \ } \ @@ -383,7 +351,7 @@ if ((BbpCsr.field.Busy == IDLE) && \ (BbpCsr.field.RegNum == _I)) \ { \ - *(_pV) = (UCHAR)BbpCsr.field.Value; \ + *(_pV) = (u8)BbpCsr.field.Value; \ break; \ } \ } \ @@ -399,11 +367,10 @@ *(_pV) = (_A)->BbpWriteLatch[_I]; \ } \ } -#endif // CONFIG_STA_SUPPORT // /* basic marco for BBP write operation. - _pAd: the data structure pointer of RTMP_ADAPTER + _pAd: the data structure pointer of struct rt_rtmp_adapter _bbpID : the bbp register ID _pV: data used to save the value of queried bbp register. _bViaMCU: if we need access the bbp via the MCU. @@ -447,7 +414,6 @@ } \ }while(0) - /* This marco used for the BBP write operation which didn't need via MCU. */ @@ -459,24 +425,11 @@ But for some chipset which didn't have mcu (e.g., RBUS based chipset), we will use this function too and didn't access the bbp register via the MCU. */ -#ifndef CONFIG_STA_SUPPORT -#define RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _pV) \ - do{ \ - if ((_A)->bPCIclkOff == FALSE) \ - { \ - if ((_A)->infType == RTMP_DEV_INF_RBUS) \ - RTMP_BBP_IO_WRITE8((_A), (_I), (_pV), FALSE); \ - else \ - RTMP_BBP_IO_WRITE8((_A), (_I), (_pV), TRUE); \ - } \ - }while(0) -#endif // CONFIG_STA_SUPPORT // -#ifdef CONFIG_STA_SUPPORT -// Write BBP register by register's ID & value +/* Write BBP register by register's ID & value */ #define RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) \ { \ BBP_CSR_CFG_STRUC BbpCsr; \ - INT BusyCnt = 0; \ + int BusyCnt = 0; \ BOOLEAN brc; \ if (_I < MAX_NUM_OF_BBP_LATCH) \ { \ @@ -557,48 +510,21 @@ DBGPRINT_ERR(("****** BBP_Write_Latch Buffer exceeds max boundry ****** \n")); \ } \ } -#endif // CONFIG_STA_SUPPORT // -#endif // RTMP_MAC_PCI // +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB +#define RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) RTUSBReadBBPRegister(_A, _I, _pV) +#define RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) RTUSBWriteBBPRegister(_A, _I, _V) +#define BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) RTUSBWriteBBPRegister(_A, _I, _V) +#define BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) RTUSBReadBBPRegister(_A, _I, _pV) +#endif /* RTMP_MAC_USB // */ #ifdef RT30xx -//Need to collect each ant's rssi concurrently -//rssi1 is report to pair2 Ant and rss2 is reprot to pair1 Ant when 4 Ant -#define COLLECT_RX_ANTENNA_AVERAGE_RSSI(_pAd, _rssi1, _rssi2) \ -{ \ - SHORT AvgRssi; \ - UCHAR UsedAnt; \ - if (_pAd->RxAnt.EvaluatePeriod == 0) \ - { \ - UsedAnt = _pAd->RxAnt.Pair1PrimaryRxAnt; \ - AvgRssi = _pAd->RxAnt.Pair1AvgRssi[UsedAnt]; \ - if (AvgRssi < 0) \ - AvgRssi = AvgRssi - (AvgRssi >> 3) + _rssi1; \ - else \ - AvgRssi = _rssi1 << 3; \ - _pAd->RxAnt.Pair1AvgRssi[UsedAnt] = AvgRssi; \ - } \ - else \ - { \ - UsedAnt = _pAd->RxAnt.Pair1SecondaryRxAnt; \ - AvgRssi = _pAd->RxAnt.Pair1AvgRssi[UsedAnt]; \ - if ((AvgRssi < 0) && (_pAd->RxAnt.FirstPktArrivedWhenEvaluate)) \ - AvgRssi = AvgRssi - (AvgRssi >> 3) + _rssi1; \ - else \ - { \ - _pAd->RxAnt.FirstPktArrivedWhenEvaluate = TRUE; \ - AvgRssi = _rssi1 << 3; \ - } \ - _pAd->RxAnt.Pair1AvgRssi[UsedAnt] = AvgRssi; \ - _pAd->RxAnt.RcvPktNumWhenEvaluate++; \ - } \ -} - #define RTMP_ASIC_MMPS_DISABLE(_pAd) \ do{ \ - UCHAR _bbpData; \ - UINT32 _macData; \ + u32 _macData; \ + u8 _bbpData = 0; \ /* disable MMPS BBP control register */ \ RTMP_BBP_IO_READ8_BY_REG_ID(_pAd, BBP_R3, &_bbpData); \ _bbpData &= ~(0x04); /*bit 2*/ \ @@ -610,11 +536,10 @@ RTMP_IO_WRITE32(_pAd, 0x1210, _macData); \ }while(0) - #define RTMP_ASIC_MMPS_ENABLE(_pAd) \ do{ \ - UCHAR _bbpData; \ - UINT32 _macData; \ + u32 _macData; \ + u8 _bbpData = 0; \ /* enable MMPS BBP control register */ \ RTMP_BBP_IO_READ8_BY_REG_ID(_pAd, BBP_R3, &_bbpData); \ _bbpData |= (0x04); /*bit 2*/ \ @@ -626,6 +551,6 @@ RTMP_IO_WRITE32(_pAd, 0x1210, _macData); \ }while(0) -#endif // RT30xx // +#endif /* RT30xx // */ -#endif // __RTMP_PHY_H__ // +#endif /* __RTMP_PHY_H__ // */ diff --git a/drivers/staging/rt2860/chips/rt3070.c b/drivers/staging/rt2860/chips/rt3070.c new file mode 100644 index 0000000000000000000000000000000000000000..627bad943a3c92787f5cd882c227baa14e655fa2 --- /dev/null +++ b/drivers/staging/rt2860/chips/rt3070.c @@ -0,0 +1,169 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* + + Module Name: + rt3070.c + + Abstract: + Specific funcitons and variables for RT3070 + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RT3070 + +#include "../rt_config.h" + +#ifndef RTMP_RF_RW_SUPPORT +#error "You Should Enable compile flag RTMP_RF_RW_SUPPORT for this chip" +#endif /* RTMP_RF_RW_SUPPORT // */ + +void NICInitRT3070RFRegisters(struct rt_rtmp_adapter *pAd) +{ + int i; + u8 RFValue; + + /* Driver must read EEPROM to get RfIcType before initial RF registers */ + /* Initialize RF register to default value */ + if (IS_RT3070(pAd) || IS_RT3071(pAd)) { + /* Init RF calibration */ + /* Driver should toggle RF R30 bit7 before init RF registers */ + u32 RfReg = 0; + u32 data; + + RT30xxReadRFRegister(pAd, RF_R30, (u8 *)& RfReg); + RfReg |= 0x80; + RT30xxWriteRFRegister(pAd, RF_R30, (u8)RfReg); + RTMPusecDelay(1000); + RfReg &= 0x7F; + RT30xxWriteRFRegister(pAd, RF_R30, (u8)RfReg); + + /* Initialize RF register to default value */ + for (i = 0; i < NUM_RF_REG_PARMS; i++) { + RT30xxWriteRFRegister(pAd, + RT30xx_RFRegTable[i].Register, + RT30xx_RFRegTable[i].Value); + } + + /* add by johnli */ + if (IS_RT3070(pAd)) { + /* */ + /* The DAC issue(LDO_CFG0) has been fixed in RT3070(F). */ + /* The voltage raising patch is no longer needed for RT3070(F) */ + /* */ + if ((pAd->MACVersion & 0xffff) < 0x0201) { + /* Update MAC 0x05D4 from 01xxxxxx to 0Dxxxxxx (voltage 1.2V to 1.35V) for RT3070 to improve yield rate */ + RTUSBReadMACRegister(pAd, LDO_CFG0, &data); + data = ((data & 0xF0FFFFFF) | 0x0D000000); + RTUSBWriteMACRegister(pAd, LDO_CFG0, data); + } + } else if (IS_RT3071(pAd)) { + /* Driver should set RF R6 bit6 on before init RF registers */ + RT30xxReadRFRegister(pAd, RF_R06, (u8 *)& RfReg); + RfReg |= 0x40; + RT30xxWriteRFRegister(pAd, RF_R06, (u8)RfReg); + + /* init R31 */ + RT30xxWriteRFRegister(pAd, RF_R31, 0x14); + + /* RT3071 version E has fixed this issue */ + if ((pAd->NicConfig2.field.DACTestBit == 1) + && ((pAd->MACVersion & 0xffff) < 0x0211)) { + /* patch tx EVM issue temporarily */ + RTUSBReadMACRegister(pAd, LDO_CFG0, &data); + data = ((data & 0xE0FFFFFF) | 0x0D000000); + RTUSBWriteMACRegister(pAd, LDO_CFG0, data); + } else { + RTMP_IO_READ32(pAd, LDO_CFG0, &data); + data = ((data & 0xE0FFFFFF) | 0x01000000); + RTMP_IO_WRITE32(pAd, LDO_CFG0, data); + } + + /* patch LNA_PE_G1 failed issue */ + RTUSBReadMACRegister(pAd, GPIO_SWITCH, &data); + data &= ~(0x20); + RTUSBWriteMACRegister(pAd, GPIO_SWITCH, data); + } + /*For RF filter Calibration */ + RTMPFilterCalibration(pAd); + + /* Initialize RF R27 register, set RF R27 must be behind RTMPFilterCalibration() */ + /* */ + /* TX to RX IQ glitch(RF_R27) has been fixed in RT3070(F). */ + /* Raising RF voltage is no longer needed for RT3070(F) */ + /* */ + if ((IS_RT3070(pAd)) && ((pAd->MACVersion & 0xffff) < 0x0201)) { + RT30xxWriteRFRegister(pAd, RF_R27, 0x3); + } else if ((IS_RT3071(pAd)) + && ((pAd->MACVersion & 0xffff) < 0x0211)) { + RT30xxWriteRFRegister(pAd, RF_R27, 0x3); + } + /* set led open drain enable */ + RTUSBReadMACRegister(pAd, OPT_14, &data); + data |= 0x01; + RTUSBWriteMACRegister(pAd, OPT_14, data); + + /* move from RT30xxLoadRFNormalModeSetup because it's needed for both RT3070 and RT3071 */ + /* TX_LO1_en, RF R17 register Bit 3 to 0 */ + RT30xxReadRFRegister(pAd, RF_R17, &RFValue); + RFValue &= (~0x08); + /* to fix rx long range issue */ + if (pAd->NicConfig2.field.ExternalLNAForG == 0) { + if ((IS_RT3071(pAd) + && ((pAd->MACVersion & 0xffff) >= 0x0211)) + || IS_RT3070(pAd)) { + RFValue |= 0x20; + } + } + /* set RF_R17_bit[2:0] equal to EEPROM setting at 0x48h */ + if (pAd->TxMixerGain24G >= 1) { + RFValue &= (~0x7); /* clean bit [2:0] */ + RFValue |= pAd->TxMixerGain24G; + } + RT30xxWriteRFRegister(pAd, RF_R17, RFValue); + + if (IS_RT3071(pAd)) { + /* add by johnli, RF power sequence setup, load RF normal operation-mode setup */ + RT30xxLoadRFNormalModeSetup(pAd); + } else if (IS_RT3070(pAd)) { + /* add by johnli, reset RF_R27 when interface down & up to fix throughput problem */ + /* LDORF_VC, RF R27 register Bit 2 to 0 */ + RT30xxReadRFRegister(pAd, RF_R27, &RFValue); + /* TX to RX IQ glitch(RF_R27) has been fixed in RT3070(F). */ + /* Raising RF voltage is no longer needed for RT3070(F) */ + if ((pAd->MACVersion & 0xffff) < 0x0201) + RFValue = (RFValue & (~0x77)) | 0x3; + else + RFValue = (RFValue & (~0x77)); + RT30xxWriteRFRegister(pAd, RF_R27, RFValue); + /* end johnli */ + } + } + +} +#endif /* RT3070 // */ diff --git a/drivers/staging/rt3090/chips/rt3090.c b/drivers/staging/rt2860/chips/rt3090.c similarity index 65% rename from drivers/staging/rt3090/chips/rt3090.c rename to drivers/staging/rt2860/chips/rt3090.c index 35c549dc4ce1d3680958d8e7c835292209901ef4..5927ba4c5a9b32be4b12f7496e654b4383ca6575 100644 --- a/drivers/staging/rt3090/chips/rt3090.c +++ b/drivers/staging/rt2860/chips/rt3090.c @@ -39,85 +39,81 @@ #include "../rt_config.h" - #ifndef RTMP_RF_RW_SUPPORT #error "You Should Enable compile flag RTMP_RF_RW_SUPPORT for this chip" -#endif // RTMP_RF_RW_SUPPORT // - +#endif /* RTMP_RF_RW_SUPPORT // */ -VOID NICInitRT3090RFRegisters(IN PRTMP_ADAPTER pAd) +void NICInitRT3090RFRegisters(struct rt_rtmp_adapter *pAd) { - INT i; - // Driver must read EEPROM to get RfIcType before initial RF registers - // Initialize RF register to default value - if (IS_RT3090(pAd)) - { - // Init RF calibration - // Driver should toggle RF R30 bit7 before init RF registers - UINT32 RfReg = 0, data; - - RT30xxReadRFRegister(pAd, RF_R30, (PUCHAR)&RfReg); + int i; + /* Driver must read EEPROM to get RfIcType before initial RF registers */ + /* Initialize RF register to default value */ + if (IS_RT3090(pAd)) { + /* Init RF calibration */ + /* Driver should toggle RF R30 bit7 before init RF registers */ + u32 RfReg = 0, data; + + RT30xxReadRFRegister(pAd, RF_R30, (u8 *)& RfReg); RfReg |= 0x80; - RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg); + RT30xxWriteRFRegister(pAd, RF_R30, (u8)RfReg); RTMPusecDelay(1000); RfReg &= 0x7F; - RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg); + RT30xxWriteRFRegister(pAd, RF_R30, (u8)RfReg); - // init R24, R31 + /* init R24, R31 */ RT30xxWriteRFRegister(pAd, RF_R24, 0x0F); RT30xxWriteRFRegister(pAd, RF_R31, 0x0F); - // RT309x version E has fixed this issue - if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211)) - { - // patch tx EVM issue temporarily + /* RT309x version E has fixed this issue */ + if ((pAd->NicConfig2.field.DACTestBit == 1) + && ((pAd->MACVersion & 0xffff) < 0x0211)) { + /* patch tx EVM issue temporarily */ RTMP_IO_READ32(pAd, LDO_CFG0, &data); data = ((data & 0xE0FFFFFF) | 0x0D000000); RTMP_IO_WRITE32(pAd, LDO_CFG0, data); - } - else - { + } else { RTMP_IO_READ32(pAd, LDO_CFG0, &data); data = ((data & 0xE0FFFFFF) | 0x01000000); RTMP_IO_WRITE32(pAd, LDO_CFG0, data); } - // patch LNA_PE_G1 failed issue + /* patch LNA_PE_G1 failed issue */ RTMP_IO_READ32(pAd, GPIO_SWITCH, &data); data &= ~(0x20); RTMP_IO_WRITE32(pAd, GPIO_SWITCH, data); - // Initialize RF register to default value - for (i = 0; i < NUM_RF_REG_PARMS; i++) - { - RT30xxWriteRFRegister(pAd, RT30xx_RFRegTable[i].Register, RT30xx_RFRegTable[i].Value); + /* Initialize RF register to default value */ + for (i = 0; i < NUM_RF_REG_PARMS; i++) { + RT30xxWriteRFRegister(pAd, + RT30xx_RFRegTable[i].Register, + RT30xx_RFRegTable[i].Value); } - // Driver should set RF R6 bit6 on before calibration - RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RfReg); + /* Driver should set RF R6 bit6 on before calibration */ + RT30xxReadRFRegister(pAd, RF_R06, (u8 *)& RfReg); RfReg |= 0x40; - RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RfReg); + RT30xxWriteRFRegister(pAd, RF_R06, (u8)RfReg); - //For RF filter Calibration + /*For RF filter Calibration */ RTMPFilterCalibration(pAd); - // Initialize RF R27 register, set RF R27 must be behind RTMPFilterCalibration() + /* Initialize RF R27 register, set RF R27 must be behind RTMPFilterCalibration() */ if ((pAd->MACVersion & 0xffff) < 0x0211) RT30xxWriteRFRegister(pAd, RF_R27, 0x3); - // set led open drain enable + /* set led open drain enable */ RTMP_IO_READ32(pAd, OPT_14, &data); data |= 0x01; RTMP_IO_WRITE32(pAd, OPT_14, data); - // set default antenna as main + /* set default antenna as main */ if (pAd->RfIcType == RFIC_3020) AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); - // add by johnli, RF power sequence setup, load RF normal operation-mode setup + /* add by johnli, RF power sequence setup, load RF normal operation-mode setup */ RT30xxLoadRFNormalModeSetup(pAd); } } -#endif // RT3090 // +#endif /* RT3090 // */ diff --git a/drivers/staging/rt3090/chips/rt30xx.c b/drivers/staging/rt2860/chips/rt30xx.c similarity index 54% rename from drivers/staging/rt3090/chips/rt30xx.c rename to drivers/staging/rt2860/chips/rt30xx.c index 9c8ae009dff9232ce6861d3cee81c16227985321..6e684a3ccf0ec9038a34f909f6386dc3cf268763 100644 --- a/drivers/staging/rt3090/chips/rt30xx.c +++ b/drivers/staging/rt2860/chips/rt30xx.c @@ -35,104 +35,114 @@ -------- ---------- ---------------------------------------------- */ - #ifdef RT30xx - #ifndef RTMP_RF_RW_SUPPORT #error "You Should Enable compile flag RTMP_RF_RW_SUPPORT for this chip" -#endif // RTMP_RF_RW_SUPPORT // +#endif /* RTMP_RF_RW_SUPPORT // */ #include "../rt_config.h" - -// -// RF register initialization set -// -REG_PAIR RT30xx_RFRegTable[] = { - {RF_R04, 0x40}, - {RF_R05, 0x03}, - {RF_R06, 0x02}, - {RF_R07, 0x70}, - {RF_R09, 0x0F}, - {RF_R10, 0x41}, - {RF_R11, 0x21}, - {RF_R12, 0x7B}, - {RF_R14, 0x90}, - {RF_R15, 0x58}, - {RF_R16, 0xB3}, - {RF_R17, 0x92}, - {RF_R18, 0x2C}, - {RF_R19, 0x02}, - {RF_R20, 0xBA}, - {RF_R21, 0xDB}, - {RF_R24, 0x16}, - {RF_R25, 0x01}, - {RF_R29, 0x1F}, +/* */ +/* RF register initialization set */ +/* */ +struct rt_reg_pair RT30xx_RFRegTable[] = { + {RF_R04, 0x40} + , + {RF_R05, 0x03} + , + {RF_R06, 0x02} + , + {RF_R07, 0x70} + , + {RF_R09, 0x0F} + , + {RF_R10, 0x41} + , + {RF_R11, 0x21} + , + {RF_R12, 0x7B} + , + {RF_R14, 0x90} + , + {RF_R15, 0x58} + , + {RF_R16, 0xB3} + , + {RF_R17, 0x92} + , + {RF_R18, 0x2C} + , + {RF_R19, 0x02} + , + {RF_R20, 0xBA} + , + {RF_R21, 0xDB} + , + {RF_R24, 0x16} + , + {RF_R25, 0x01} + , + {RF_R29, 0x1F} + , }; -UCHAR NUM_RF_REG_PARMS = (sizeof(RT30xx_RFRegTable) / sizeof(REG_PAIR)); +u8 NUM_RF_REG_PARMS = (sizeof(RT30xx_RFRegTable) / sizeof(struct rt_reg_pair)); - - -// Antenna divesity use GPIO3 and EESK pin for control -// Antenna and EEPROM access are both using EESK pin, -// Therefor we should avoid accessing EESK at the same time -// Then restore antenna after EEPROM access -// The original name of this function is AsicSetRxAnt(), now change to -//VOID AsicSetRxAnt( -VOID RT30xxSetRxAnt( - IN PRTMP_ADAPTER pAd, - IN UCHAR Ant) +/* Antenna divesity use GPIO3 and EESK pin for control */ +/* Antenna and EEPROM access are both using EESK pin, */ +/* Therefor we should avoid accessing EESK at the same time */ +/* Then restore antenna after EEPROM access */ +/* The original name of this function is AsicSetRxAnt(), now change to */ +/*void AsicSetRxAnt( */ +void RT30xxSetRxAnt(struct rt_rtmp_adapter *pAd, u8 Ant) { - UINT32 Value; - UINT32 x; + u32 Value; +#ifdef RTMP_MAC_PCI + u32 x; +#endif if ((pAd->EepromAccess) || - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) || - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) || - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) || - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) - { + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { return; } - - // the antenna selection is through firmware and MAC register(GPIO3) - if (Ant == 0) - { - // Main antenna + /* the antenna selection is through firmware and MAC register(GPIO3) */ + if (Ant == 0) { + /* Main antenna */ #ifdef RTMP_MAC_PCI RTMP_IO_READ32(pAd, E2PROM_CSR, &x); x |= (EESK); RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); #else AsicSendCommandToMcu(pAd, 0x73, 0xFF, 0x1, 0x0); -#endif // RTMP_MAC_PCI // +#endif /* RTMP_MAC_PCI // */ RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value); Value &= ~(0x0808); RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n")); - } - else - { - // Aux antenna + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("AsicSetRxAnt, switch to main antenna\n")); + } else { + /* Aux antenna */ #ifdef RTMP_MAC_PCI RTMP_IO_READ32(pAd, E2PROM_CSR, &x); x &= ~(EESK); RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); #else AsicSendCommandToMcu(pAd, 0x73, 0xFF, 0x0, 0x0); -#endif // RTMP_MAC_PCI // +#endif /* RTMP_MAC_PCI // */ RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value); Value &= ~(0x0808); Value |= 0x08; RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n")); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("AsicSetRxAnt, switch to aux antenna\n")); } } - /* ======================================================================== @@ -149,161 +159,145 @@ VOID RT30xxSetRxAnt( ======================================================================== */ -VOID RTMPFilterCalibration( - IN PRTMP_ADAPTER pAd) +void RTMPFilterCalibration(struct rt_rtmp_adapter *pAd) { - UCHAR R55x = 0, value, FilterTarget = 0x1E, BBPValue=0; - UINT loop = 0, count = 0, loopcnt = 0, ReTry = 0; - UCHAR RF_R24_Value = 0; + u8 R55x = 0, value, FilterTarget = 0x1E, BBPValue = 0; + u32 loop = 0, count = 0, loopcnt = 0, ReTry = 0; + u8 RF_R24_Value = 0; - // Give bbp filter initial value + /* Give bbp filter initial value */ pAd->Mlme.CaliBW20RfR24 = 0x1F; - pAd->Mlme.CaliBW40RfR24 = 0x2F; //Bit[5] must be 1 for BW 40 + pAd->Mlme.CaliBW40RfR24 = 0x2F; /*Bit[5] must be 1 for BW 40 */ - do - { - if (loop == 1) //BandWidth = 40 MHz + do { + if (loop == 1) /*BandWidth = 40 MHz */ { - // Write 0x27 to RF_R24 to program filter + /* Write 0x27 to RF_R24 to program filter */ RF_R24_Value = 0x27; RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); - if (IS_RT3090(pAd) || IS_RT3572(pAd)|| IS_RT3390(pAd)) + if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) FilterTarget = 0x15; else FilterTarget = 0x19; - // when calibrate BW40, BBP mask must set to BW40. + /* when calibrate BW40, BBP mask must set to BW40. */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue&= (~0x18); - BBPValue|= (0x10); + BBPValue &= (~0x18); + BBPValue |= (0x10); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - // set to BW40 + /* set to BW40 */ RT30xxReadRFRegister(pAd, RF_R31, &value); value |= 0x20; RT30xxWriteRFRegister(pAd, RF_R31, value); - } - else //BandWidth = 20 MHz + } else /*BandWidth = 20 MHz */ { - // Write 0x07 to RF_R24 to program filter + /* Write 0x07 to RF_R24 to program filter */ RF_R24_Value = 0x07; RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); - if (IS_RT3090(pAd) || IS_RT3572(pAd)|| IS_RT3390(pAd)) + if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) FilterTarget = 0x13; else FilterTarget = 0x16; - // set to BW20 + /* set to BW20 */ RT30xxReadRFRegister(pAd, RF_R31, &value); value &= (~0x20); RT30xxWriteRFRegister(pAd, RF_R31, value); } - // Write 0x01 to RF_R22 to enable baseband loopback mode + /* Write 0x01 to RF_R22 to enable baseband loopback mode */ RT30xxReadRFRegister(pAd, RF_R22, &value); value |= 0x01; RT30xxWriteRFRegister(pAd, RF_R22, value); - // Write 0x00 to BBP_R24 to set power & frequency of passband test tone + /* Write 0x00 to BBP_R24 to set power & frequency of passband test tone */ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0); - do - { - // Write 0x90 to BBP_R25 to transmit test tone + do { + /* Write 0x90 to BBP_R25 to transmit test tone */ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R25, 0x90); RTMPusecDelay(1000); - // Read BBP_R55[6:0] for received power, set R55x = BBP_R55[6:0] + /* Read BBP_R55[6:0] for received power, set R55x = BBP_R55[6:0] */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R55, &value); R55x = value & 0xFF; } while ((ReTry++ < 100) && (R55x == 0)); - // Write 0x06 to BBP_R24 to set power & frequency of stopband test tone + /* Write 0x06 to BBP_R24 to set power & frequency of stopband test tone */ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x06); - while(TRUE) - { - // Write 0x90 to BBP_R25 to transmit test tone + while (TRUE) { + /* Write 0x90 to BBP_R25 to transmit test tone */ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R25, 0x90); - //We need to wait for calibration + /*We need to wait for calibration */ RTMPusecDelay(1000); RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R55, &value); value &= 0xFF; - if ((R55x - value) < FilterTarget) - { - RF_R24_Value ++; - } - else if ((R55x - value) == FilterTarget) - { - RF_R24_Value ++; - count ++; - } - else - { + if ((R55x - value) < FilterTarget) { + RF_R24_Value++; + } else if ((R55x - value) == FilterTarget) { + RF_R24_Value++; + count++; + } else { break; } - // prevent infinite loop cause driver hang. - if (loopcnt++ > 100) - { - DBGPRINT(RT_DEBUG_ERROR, ("RTMPFilterCalibration - can't find a valid value, loopcnt=%d stop calibrating", loopcnt)); + /* prevent infinite loop cause driver hang. */ + if (loopcnt++ > 100) { + DBGPRINT(RT_DEBUG_ERROR, + ("RTMPFilterCalibration - can't find a valid value, loopcnt=%d stop calibrating", + loopcnt)); break; } - - // Write RF_R24 to program filter + /* Write RF_R24 to program filter */ RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); } - if (count > 0) - { + if (count > 0) { RF_R24_Value = RF_R24_Value - ((count) ? (1) : (0)); } - - // Store for future usage - if (loopcnt < 100) - { - if (loop++ == 0) - { - //BandWidth = 20 MHz - pAd->Mlme.CaliBW20RfR24 = (UCHAR)RF_R24_Value; - } - else - { - //BandWidth = 40 MHz - pAd->Mlme.CaliBW40RfR24 = (UCHAR)RF_R24_Value; + /* Store for future usage */ + if (loopcnt < 100) { + if (loop++ == 0) { + /*BandWidth = 20 MHz */ + pAd->Mlme.CaliBW20RfR24 = (u8)RF_R24_Value; + } else { + /*BandWidth = 40 MHz */ + pAd->Mlme.CaliBW40RfR24 = (u8)RF_R24_Value; break; } - } - else + } else break; RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); - // reset count + /* reset count */ count = 0; - } while(TRUE); + } while (TRUE); - // - // Set back to initial state - // + /* */ + /* Set back to initial state */ + /* */ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0); RT30xxReadRFRegister(pAd, RF_R22, &value); value &= ~(0x01); RT30xxWriteRFRegister(pAd, RF_R22, value); - // set BBP back to BW20 + /* set BBP back to BW20 */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue&= (~0x18); + BBPValue &= (~0x18); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - DBGPRINT(RT_DEBUG_TRACE, ("RTMPFilterCalibration - CaliBW20RfR24=0x%x, CaliBW40RfR24=0x%x\n", pAd->Mlme.CaliBW20RfR24, pAd->Mlme.CaliBW40RfR24)); + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPFilterCalibration - CaliBW20RfR24=0x%x, CaliBW40RfR24=0x%x\n", + pAd->Mlme.CaliBW20RfR24, pAd->Mlme.CaliBW40RfR24)); } - -// add by johnli, RF power sequence setup +/* add by johnli, RF power sequence setup */ /* ========================================================================== Description: @@ -312,55 +306,54 @@ VOID RTMPFilterCalibration( ========================================================================== */ -VOID RT30xxLoadRFNormalModeSetup( - IN PRTMP_ADAPTER pAd) +void RT30xxLoadRFNormalModeSetup(struct rt_rtmp_adapter *pAd) { - UCHAR RFValue; + u8 RFValue; - // RX0_PD & TX0_PD, RF R1 register Bit 2 & Bit 3 to 0 and RF_BLOCK_en,RX1_PD & TX1_PD, Bit0, Bit 4 & Bit5 to 1 + /* RX0_PD & TX0_PD, RF R1 register Bit 2 & Bit 3 to 0 and RF_BLOCK_en,RX1_PD & TX1_PD, Bit0, Bit 4 & Bit5 to 1 */ RT30xxReadRFRegister(pAd, RF_R01, &RFValue); RFValue = (RFValue & (~0x0C)) | 0x31; RT30xxWriteRFRegister(pAd, RF_R01, RFValue); - // TX_LO2_en, RF R15 register Bit 3 to 0 + /* TX_LO2_en, RF R15 register Bit 3 to 0 */ RT30xxReadRFRegister(pAd, RF_R15, &RFValue); RFValue &= (~0x08); RT30xxWriteRFRegister(pAd, RF_R15, RFValue); /* move to NICInitRT30xxRFRegisters - // TX_LO1_en, RF R17 register Bit 3 to 0 - RT30xxReadRFRegister(pAd, RF_R17, &RFValue); - RFValue &= (~0x08); - // to fix rx long range issue - if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0)) - { - RFValue |= 0x20; - } - // set RF_R17_bit[2:0] equal to EEPROM setting at 0x48h - if (pAd->TxMixerGain24G >= 2) - { - RFValue &= (~0x7); // clean bit [2:0] - RFValue |= pAd->TxMixerGain24G; - } - RT30xxWriteRFRegister(pAd, RF_R17, RFValue); - */ - - // RX_LO1_en, RF R20 register Bit 3 to 0 + // TX_LO1_en, RF R17 register Bit 3 to 0 + RT30xxReadRFRegister(pAd, RF_R17, &RFValue); + RFValue &= (~0x08); + // to fix rx long range issue + if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0)) + { + RFValue |= 0x20; + } + // set RF_R17_bit[2:0] equal to EEPROM setting at 0x48h + if (pAd->TxMixerGain24G >= 2) + { + RFValue &= (~0x7); // clean bit [2:0] + RFValue |= pAd->TxMixerGain24G; + } + RT30xxWriteRFRegister(pAd, RF_R17, RFValue); + */ + + /* RX_LO1_en, RF R20 register Bit 3 to 0 */ RT30xxReadRFRegister(pAd, RF_R20, &RFValue); RFValue &= (~0x08); RT30xxWriteRFRegister(pAd, RF_R20, RFValue); - // RX_LO2_en, RF R21 register Bit 3 to 0 + /* RX_LO2_en, RF R21 register Bit 3 to 0 */ RT30xxReadRFRegister(pAd, RF_R21, &RFValue); RFValue &= (~0x08); RT30xxWriteRFRegister(pAd, RF_R21, RFValue); - /* add by johnli, reset RF_R27 when interface down & up to fix throughput problem*/ - // LDORF_VC, RF R27 register Bit 2 to 0 + /* add by johnli, reset RF_R27 when interface down & up to fix throughput problem */ + /* LDORF_VC, RF R27 register Bit 2 to 0 */ RT30xxReadRFRegister(pAd, RF_R27, &RFValue); - // TX to RX IQ glitch(RF_R27) has been fixed in RT3070(F). - // Raising RF voltage is no longer needed for RT3070(F) - if (IS_RT3090(pAd)) // RT309x and RT3071/72 + /* TX to RX IQ glitch(RF_R27) has been fixed in RT3070(F). */ + /* Raising RF voltage is no longer needed for RT3070(F) */ + if (IS_RT3090(pAd)) /* RT309x and RT3071/72 */ { if ((pAd->MACVersion & 0xffff) < 0x0211) RFValue = (RFValue & (~0x77)) | 0x3; @@ -379,39 +372,42 @@ VOID RT30xxLoadRFNormalModeSetup( ========================================================================== */ -VOID RT30xxLoadRFSleepModeSetup( - IN PRTMP_ADAPTER pAd) +void RT30xxLoadRFSleepModeSetup(struct rt_rtmp_adapter *pAd) { - UCHAR RFValue; - UINT32 MACValue; - + u8 RFValue; + u32 MACValue; +#ifdef RTMP_MAC_USB + if (!IS_RT3572(pAd)) +#endif /* RTMP_MAC_USB // */ { - // RF_BLOCK_en. RF R1 register Bit 0 to 0 + /* RF_BLOCK_en. RF R1 register Bit 0 to 0 */ RT30xxReadRFRegister(pAd, RF_R01, &RFValue); RFValue &= (~0x01); RT30xxWriteRFRegister(pAd, RF_R01, RFValue); - // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0 + /* VCO_IC, RF R7 register Bit 4 & Bit 5 to 0 */ RT30xxReadRFRegister(pAd, RF_R07, &RFValue); RFValue &= (~0x30); RT30xxWriteRFRegister(pAd, RF_R07, RFValue); - // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0 + /* Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0 */ RT30xxReadRFRegister(pAd, RF_R09, &RFValue); RFValue &= (~0x0E); RT30xxWriteRFRegister(pAd, RF_R09, RFValue); - // RX_CTB_en, RF R21 register Bit 7 to 0 + /* RX_CTB_en, RF R21 register Bit 7 to 0 */ RT30xxReadRFRegister(pAd, RF_R21, &RFValue); RFValue &= (~0x80); RT30xxWriteRFRegister(pAd, RF_R21, RFValue); } - if (IS_RT3090(pAd) || // IS_RT3090 including RT309x and RT3071/72 - IS_RT3572(pAd) || - (IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201))) - { + if (IS_RT3090(pAd) || /* IS_RT3090 including RT309x and RT3071/72 */ + IS_RT3572(pAd) || + (IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201))) { +#ifdef RTMP_MAC_USB + if (!IS_RT3572(pAd)) +#endif /* RTMP_MAC_USB // */ { RT30xxReadRFRegister(pAd, RF_R27, &RFValue); RFValue |= 0x77; @@ -432,39 +428,43 @@ VOID RT30xxLoadRFSleepModeSetup( ========================================================================== */ -VOID RT30xxReverseRFSleepModeSetup( - IN PRTMP_ADAPTER pAd) +void RT30xxReverseRFSleepModeSetup(struct rt_rtmp_adapter *pAd) { - UCHAR RFValue; - UINT32 MACValue; + u8 RFValue; + u32 MACValue; +#ifdef RTMP_MAC_USB + if (!IS_RT3572(pAd)) +#endif /* RTMP_MAC_USB // */ { - // RF_BLOCK_en, RF R1 register Bit 0 to 1 + /* RF_BLOCK_en, RF R1 register Bit 0 to 1 */ RT30xxReadRFRegister(pAd, RF_R01, &RFValue); RFValue |= 0x01; RT30xxWriteRFRegister(pAd, RF_R01, RFValue); - // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1 + /* VCO_IC, RF R7 register Bit 4 & Bit 5 to 1 */ RT30xxReadRFRegister(pAd, RF_R07, &RFValue); RFValue |= 0x30; RT30xxWriteRFRegister(pAd, RF_R07, RFValue); - // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1 + /* Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1 */ RT30xxReadRFRegister(pAd, RF_R09, &RFValue); RFValue |= 0x0E; RT30xxWriteRFRegister(pAd, RF_R09, RFValue); - // RX_CTB_en, RF R21 register Bit 7 to 1 + /* RX_CTB_en, RF R21 register Bit 7 to 1 */ RT30xxReadRFRegister(pAd, RF_R21, &RFValue); RFValue |= 0x80; RT30xxWriteRFRegister(pAd, RF_R21, RFValue); } - if (IS_RT3090(pAd) || // IS_RT3090 including RT309x and RT3071/72 - IS_RT3572(pAd) || - IS_RT3390(pAd) || - (IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201))) - { + if (IS_RT3090(pAd) || /* IS_RT3090 including RT309x and RT3071/72 */ + IS_RT3572(pAd) || + IS_RT3390(pAd) || + (IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201))) { +#ifdef RTMP_MAC_USB + if (!IS_RT3572(pAd)) +#endif /* RTMP_MAC_USB // */ { RT30xxReadRFRegister(pAd, RF_R27, &RFValue); if ((pAd->MACVersion & 0xffff) < 0x0211) @@ -473,48 +473,41 @@ VOID RT30xxReverseRFSleepModeSetup( RFValue = (RFValue & (~0x77)); RT30xxWriteRFRegister(pAd, RF_R27, RFValue); } - - // RT3071 version E has fixed this issue - if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211)) - { - // patch tx EVM issue temporarily + /* RT3071 version E has fixed this issue */ + if ((pAd->NicConfig2.field.DACTestBit == 1) + && ((pAd->MACVersion & 0xffff) < 0x0211)) { + /* patch tx EVM issue temporarily */ RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue); MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000); RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue); - } - else - { + } else { RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue); MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000); RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue); } } - if(IS_RT3572(pAd)) + if (IS_RT3572(pAd)) RT30xxWriteRFRegister(pAd, RF_R08, 0x80); } -// end johnli -VOID RT30xxHaltAction( - IN PRTMP_ADAPTER pAd) +/* end johnli */ + +void RT30xxHaltAction(struct rt_rtmp_adapter *pAd) { - UINT32 TxPinCfg = 0x00050F0F; + u32 TxPinCfg = 0x00050F0F; - // - // Turn off LNA_PE or TRSW_POL - // - if (IS_RT3070(pAd) || IS_RT3071(pAd) || IS_RT3572(pAd)) - { + /* */ + /* Turn off LNA_PE or TRSW_POL */ + /* */ + if (IS_RT3070(pAd) || IS_RT3071(pAd) || IS_RT3572(pAd)) { if ((IS_RT3071(pAd) || IS_RT3572(pAd)) #ifdef RTMP_EFUSE_SUPPORT - && (pAd->bUseEfuse) -#endif // RTMP_EFUSE_SUPPORT // - ) - { - TxPinCfg &= 0xFFFBF0F0; // bit18 off - } - else - { + && (pAd->bUseEfuse) +#endif /* RTMP_EFUSE_SUPPORT // */ + ) { + TxPinCfg &= 0xFFFBF0F0; /* bit18 off */ + } else { TxPinCfg &= 0xFFFFF0F0; } @@ -522,4 +515,4 @@ VOID RT30xxHaltAction( } } -#endif // RT30xx // +#endif /* RT30xx // */ diff --git a/drivers/staging/rt2860/chlist.h b/drivers/staging/rt2860/chlist.h index f49a35c95de67ec79e2e4453964c8433287d0a61..ada65e5ac610934bce514a53b55e2d3df4f163e7 100644 --- a/drivers/staging/rt2860/chlist.h +++ b/drivers/staging/rt2860/chlist.h @@ -41,7 +41,6 @@ #include "rtmp_type.h" #include "rtmp_def.h" - #define ODOR 0 #define IDOR 1 #define BOTH 2 @@ -50,1196 +49,69 @@ #define BAND_24G 1 #define BAND_BOTH 2 -typedef struct _CH_DESP { - UCHAR FirstChannel; - UCHAR NumOfCh; - CHAR MaxTxPwr; // dBm - UCHAR Geography; // 0:out door, 1:in door, 2:both - BOOLEAN DfsReq; // Dfs require, 0: No, 1: yes. -} CH_DESP, *PCH_DESP; - -typedef struct _CH_REGION { - UCHAR CountReg[3]; - UCHAR DfsType; // 0: CE, 1: FCC, 2: JAP, 3:JAP_W53, JAP_W56 - CH_DESP ChDesp[10]; -} CH_REGION, *PCH_REGION; - -static CH_REGION ChRegion[] = -{ - { // Antigua and Berbuda - "AG", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Argentina - "AR", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Aruba - "AW", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Australia - "AU", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Austria - "AT", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, TRUE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Bahamas - "BS", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Barbados - "BB", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Bermuda - "BM", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Brazil - "BR", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 24, BOTH, FALSE}, // 5G, ch 100~140 - { 149, 5, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Belgium - "BE", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 18, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 18, IDOR, FALSE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // Bulgaria - "BG", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Canada - "CA", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Cayman IsLands - "KY", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Chile - "CL", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 20, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // China - "CN", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Colombia - "CO", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Costa Rica - "CR", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Cyprus - "CY", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Czech_Republic - "CZ", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // Denmark - "DK", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Dominican Republic - "DO", - CE, - { - { 1, 0, 20, BOTH, FALSE}, // 2.4 G, ch 0 - { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Equador - "EC", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 100, 11, 27, BOTH, FALSE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // El Salvador - "SV", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 30, BOTH, TRUE}, // 5G, ch 52~64 - { 149, 4, 36, BOTH, TRUE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Finland - "FI", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // France - "FR", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // Germany - "DE", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Greece - "GR", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Guam - "GU", - CE, - { - { 1, 11, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Guatemala - "GT", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Haiti - "HT", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Honduras - "HN", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Hong Kong - "HK", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 - { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Hungary - "HU", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // Iceland - "IS", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // India - "IN", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 149, 4, 24, IDOR, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Indonesia - "ID", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Ireland - "IE", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Israel - "IL", - CE, - { - { 1, 3, 20, IDOR, FALSE}, // 2.4 G, ch 1~3 - { 4, 6, 20, BOTH, FALSE}, // 2.4 G, ch 4~9 - { 10, 4, 20, IDOR, FALSE}, // 2.4 G, ch 10~13 - { 0}, // end - } - }, - - { // Italy - "IT", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Japan - "JP", - JAP, - { - { 1, 14, 20, BOTH, FALSE}, // 2.4 G, ch 1~14 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 0}, // end - } - }, - - { // Jordan - "JO", - CE, - { - { 1, 13, 20, IDOR, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 149, 4, 23, IDOR, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Latvia - "LV", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Liechtenstein - "LI", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Lithuania - "LT", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Luxemburg - "LU", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Malaysia - "MY", - CE, - { - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Malta - "MT", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Marocco - "MA", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 24, IDOR, FALSE}, // 5G, ch 36~48 - { 0}, // end - } - }, - - { // Mexico - "MX", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 5, 30, IDOR, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Netherlands - "NL", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // New Zealand - "NZ", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 24, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Norway - "NO", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 24, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Peru - "PE", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Portugal - "PT", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Poland - "PL", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Romania - "RO", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Russia - "RU", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 149, 4, 20, IDOR, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Saudi Arabia - "SA", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 4, 23, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Serbia_and_Montenegro - "CS", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 0}, // end - } - }, - - { // Singapore - "SG", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Slovakia - "SK", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Slovenia - "SI", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // South Africa - "ZA", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // South Korea - "KR", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 20, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 8, 20, BOTH, FALSE}, // 5G, ch 100~128 - { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Spain - "ES", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 17, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Sweden - "SE", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Switzerland - "CH", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, TRUE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // Taiwan - "TW", - CE, - { - { 1, 11, 30, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // Turkey - "TR", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // UK - "GB", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Ukraine - "UA", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 0}, // end - } - }, - - { // United_Arab_Emirates - "AE", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 0}, // end - } - }, - - { // United_States - "US", - CE, - { - { 1, 11, 30, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 36, 4, 17, IDOR, FALSE}, // 5G, ch 52~64 - { 52, 4, 24, BOTH, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Venezuela - "VE", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Default - "", - CE, - { - { 1, 11, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 36, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 - { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 20, BOTH, FALSE}, // 5G, ch 100~140 - { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, +struct rt_ch_desp { + u8 FirstChannel; + u8 NumOfCh; + char MaxTxPwr; /* dBm */ + u8 Geography; /* 0:out door, 1:in door, 2:both */ + BOOLEAN DfsReq; /* Dfs require, 0: No, 1: yes. */ }; -static inline PCH_REGION GetChRegion( - IN PUCHAR CntryCode) -{ - INT loop = 0; - PCH_REGION pChRegion = NULL; - - while (strcmp(ChRegion[loop].CountReg, "") != 0) - { - if (strncmp(ChRegion[loop].CountReg, CntryCode, 2) == 0) - { - pChRegion = &ChRegion[loop]; - break; - } - loop++; - } - - if (pChRegion == NULL) - pChRegion = &ChRegion[loop]; - return pChRegion; -} - -static inline VOID ChBandCheck( - IN UCHAR PhyMode, - OUT PUCHAR pChType) -{ - switch(PhyMode) - { - case PHY_11A: - case PHY_11AN_MIXED: - *pChType = BAND_5G; - break; - case PHY_11ABG_MIXED: - case PHY_11AGN_MIXED: - case PHY_11ABGN_MIXED: - *pChType = BAND_BOTH; - break; - - default: - *pChType = BAND_24G; - break; - } -} - -static inline UCHAR FillChList( - IN PRTMP_ADAPTER pAd, - IN PCH_DESP pChDesp, - IN UCHAR Offset, - IN UCHAR increment) -{ - INT i, j, l; - UCHAR channel; - - j = Offset; - for (i = 0; i < pChDesp->NumOfCh; i++) - { - channel = pChDesp->FirstChannel + i * increment; - for (l=0; lTxPower[l].Channel) - { - pAd->ChannelList[j].Power = pAd->TxPower[l].Power; - pAd->ChannelList[j].Power2 = pAd->TxPower[l].Power2; - break; - } - } - if (l == MAX_NUM_OF_CHANNELS) - continue; - - pAd->ChannelList[j].Channel = pChDesp->FirstChannel + i * increment; - pAd->ChannelList[j].MaxTxPwr = pChDesp->MaxTxPwr; - pAd->ChannelList[j].DfsReq = pChDesp->DfsReq; - j++; - } - pAd->ChannelListNum = j; - - return j; -} - -static inline VOID CreateChList( - IN PRTMP_ADAPTER pAd, - IN PCH_REGION pChRegion, - IN UCHAR Geography) -{ - INT i; - UCHAR offset = 0; - PCH_DESP pChDesp; - UCHAR ChType; - UCHAR increment; - - if (pChRegion == NULL) - return; - - ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); - - for (i=0; i<10; i++) - { - pChDesp = &pChRegion->ChDesp[i]; - if (pChDesp->FirstChannel == 0) - break; - - if (ChType == BAND_5G) - { - if (pChDesp->FirstChannel <= 14) - continue; - } - else if (ChType == BAND_24G) - { - if (pChDesp->FirstChannel > 14) - continue; - } - - if ((pChDesp->Geography == BOTH) - || (pChDesp->Geography == Geography)) - { - if (pChDesp->FirstChannel > 14) - increment = 4; - else - increment = 1; - offset = FillChList(pAd, pChDesp, offset, increment); - } - } -} - -static inline VOID BuildChannelListEx( - IN PRTMP_ADAPTER pAd) -{ - PCH_REGION pChReg; - - pChReg = GetChRegion(pAd->CommonCfg.CountryCode); - CreateChList(pAd, pChReg, pAd->CommonCfg.Geography); -} - -static inline VOID BuildBeaconChList( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf, - OUT PULONG pBufLen) -{ - INT i; - ULONG TmpLen; - PCH_REGION pChRegion; - PCH_DESP pChDesp; - UCHAR ChType; - - pChRegion = GetChRegion(pAd->CommonCfg.CountryCode); - - if (pChRegion == NULL) - return; - - ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); - *pBufLen = 0; - - for (i=0; i<10; i++) - { - pChDesp = &pChRegion->ChDesp[i]; - if (pChDesp->FirstChannel == 0) - break; - - if (ChType == BAND_5G) - { - if (pChDesp->FirstChannel <= 14) - continue; - } - else if (ChType == BAND_24G) - { - if (pChDesp->FirstChannel > 14) - continue; - } - - if ((pChDesp->Geography == BOTH) - || (pChDesp->Geography == pAd->CommonCfg.Geography)) - { - MakeOutgoingFrame(pBuf + *pBufLen, &TmpLen, - 1, &pChDesp->FirstChannel, - 1, &pChDesp->NumOfCh, - 1, &pChDesp->MaxTxPwr, - END_OF_ARGS); - *pBufLen += TmpLen; - } - } -} - -static inline BOOLEAN IsValidChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR channel) - -{ - INT i; - - for (i = 0; i < pAd->ChannelListNum; i++) - { - if (pAd->ChannelList[i].Channel == channel) - break; - } - - if (i == pAd->ChannelListNum) - return FALSE; - else - return TRUE; -} - - -static inline UCHAR GetExtCh( - IN UCHAR Channel, - IN UCHAR Direction) -{ - CHAR ExtCh; - - if (Direction == EXTCHA_ABOVE) - ExtCh = Channel + 4; - else - ExtCh = (Channel - 4) > 0 ? (Channel - 4) : 0; - - return ExtCh; -} - - -static inline VOID N_ChannelCheck( - IN PRTMP_ADAPTER pAd) -{ - //UCHAR ChannelNum = pAd->ChannelListNum; - UCHAR Channel = pAd->CommonCfg.Channel; - - if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) - { - if (Channel > 14) - { - if ((Channel == 36) || (Channel == 44) || (Channel == 52) || (Channel == 60) || (Channel == 100) || (Channel == 108) || - (Channel == 116) || (Channel == 124) || (Channel == 132) || (Channel == 149) || (Channel == 157)) - { - pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; - } - else if ((Channel == 40) || (Channel == 48) || (Channel == 56) || (Channel == 64) || (Channel == 104) || (Channel == 112) || - (Channel == 120) || (Channel == 128) || (Channel == 136) || (Channel == 153) || (Channel == 161)) - { - pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; - } - else - { - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; - } - } - else - { - do - { - UCHAR ExtCh; - UCHAR Dir = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; - ExtCh = GetExtCh(Channel, Dir); - if (IsValidChannel(pAd, ExtCh)) - break; - - Dir = (Dir == EXTCHA_ABOVE) ? EXTCHA_BELOW : EXTCHA_ABOVE; - ExtCh = GetExtCh(Channel, Dir); - if (IsValidChannel(pAd, ExtCh)) - { - pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = Dir; - break; - } - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; - } while(FALSE); - - if (Channel == 14) - { - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; - //pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; // We didn't set the ExtCh as NONE due to it'll set in RTMPSetHT() - } - } - } - - -} - - -static inline VOID N_SetCenCh( - IN PRTMP_ADAPTER pAd) -{ - if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) - { - if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) - { - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; - } - else - { - if (pAd->CommonCfg.Channel == 14) - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 1; - else - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; - } - } - else - { - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; - } -} +struct rt_ch_region { + u8 CountReg[3]; + u8 DfsType; /* 0: CE, 1: FCC, 2: JAP, 3:JAP_W53, JAP_W56 */ + struct rt_ch_desp ChDesp[10]; +}; -static inline UINT8 GetCuntryMaxTxPwr( - IN PRTMP_ADAPTER pAd, - IN UINT8 channel) -{ - int i; - for (i = 0; i < pAd->ChannelListNum; i++) - { - if (pAd->ChannelList[i].Channel == channel) - break; - } +extern struct rt_ch_region ChRegion[]; - if (i == pAd->ChannelListNum) - return 0xff; - else - return pAd->ChannelList[i].MaxTxPwr; -} -#endif // __CHLIST_H__ +struct rt_ch_freq_map { + u16 channel; + u16 freqKHz; +}; +extern struct rt_ch_freq_map CH_HZ_ID_MAP[]; +extern int CH_HZ_ID_MAP_NUM; + +#define MAP_CHANNEL_ID_TO_KHZ(_ch, _khz) \ + do{ \ + int _chIdx; \ + for (_chIdx = 0; _chIdx < CH_HZ_ID_MAP_NUM; _chIdx++)\ + { \ + if ((_ch) == CH_HZ_ID_MAP[_chIdx].channel) \ + { \ + (_khz) = CH_HZ_ID_MAP[_chIdx].freqKHz * 1000; \ + break; \ + } \ + } \ + if (_chIdx == CH_HZ_ID_MAP_NUM) \ + (_khz) = 2412000; \ + }while(0) + +#define MAP_KHZ_TO_CHANNEL_ID(_khz, _ch) \ + do{ \ + int _chIdx; \ + for (_chIdx = 0; _chIdx < CH_HZ_ID_MAP_NUM; _chIdx++)\ + { \ + if ((_khz) == CH_HZ_ID_MAP[_chIdx].freqKHz) \ + { \ + (_ch) = CH_HZ_ID_MAP[_chIdx].channel; \ + break; \ + } \ + } \ + if (_chIdx == CH_HZ_ID_MAP_NUM) \ + (_ch) = 1; \ + }while(0) + +void BuildChannelListEx(struct rt_rtmp_adapter *pAd); + +void BuildBeaconChList(struct rt_rtmp_adapter *pAd, + u8 *pBuf, unsigned long *pBufLen); + +void N_ChannelCheck(struct rt_rtmp_adapter *pAd); + +void N_SetCenCh(struct rt_rtmp_adapter *pAd); + +u8 GetCuntryMaxTxPwr(struct rt_rtmp_adapter *pAd, u8 channel); + +#endif /* __CHLIST_H__ */ diff --git a/drivers/staging/rt2860/common/2860_rtmp_init.c b/drivers/staging/rt2860/common/2860_rtmp_init.c deleted file mode 100644 index 0bc0fb99d2e40c0692768a3213e2f781405c9e84..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2860/common/2860_rtmp_init.c +++ /dev/null @@ -1,897 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - 2860_rtmp_init.c - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Paul Lin 2002-08-01 created - John Chang 2004-08-20 RT2561/2661 use scatter-gather scheme - Jan Lee 2006-09-15 RT2860. Change for 802.11n , EEPROM, Led, BA, HT. -*/ -#include "../rt_config.h" - - - - -/* - ======================================================================== - - Routine Description: - Allocate DMA memory blocks for send, receive - - Arguments: - Adapter Pointer to our adapter - - Return Value: - NDIS_STATUS_SUCCESS - NDIS_STATUS_FAILURE - NDIS_STATUS_RESOURCES - - IRQL = PASSIVE_LEVEL - - Note: - - ======================================================================== -*/ -NDIS_STATUS RTMPAllocTxRxRingMemory( - IN PRTMP_ADAPTER pAd) -{ - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - ULONG RingBasePaHigh; - ULONG RingBasePaLow; - PVOID RingBaseVa; - INT index, num; - PTXD_STRUC pTxD; - PRXD_STRUC pRxD; - ULONG ErrorValue = 0; - PRTMP_TX_RING pTxRing; - PRTMP_DMABUF pDmaBuf; - PNDIS_PACKET pPacket; - - DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); - do - { - // - // Allocate all ring descriptors, include TxD, RxD, MgmtD. - // Although each size is different, to prevent cacheline and alignment - // issue, I intentional set them all to 64 bytes. - // - for (num=0; numTxDescRing[num].AllocSize = TX_RING_SIZE * TXD_SIZE; - RTMP_AllocateTxDescMemory( - pAd, - num, - pAd->TxDescRing[num].AllocSize, - FALSE, - &pAd->TxDescRing[num].AllocVa, - &pAd->TxDescRing[num].AllocPa); - - if (pAd->TxDescRing[num].AllocVa == NULL) - { - ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; - DBGPRINT_ERR(("Failed to allocate a big buffer\n")); - Status = NDIS_STATUS_RESOURCES; - break; - } - - // Zero init this memory block - NdisZeroMemory(pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocSize); - - // Save PA & VA for further operation - RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num].AllocPa); - RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxDescRing[num].AllocPa); - RingBaseVa = pAd->TxDescRing[num].AllocVa; - - // - // Allocate all 1st TXBuf's memory for this TxRing - // - pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE; - RTMP_AllocateFirstTxBuffer( - pAd, - num, - pAd->TxBufSpace[num].AllocSize, - FALSE, - &pAd->TxBufSpace[num].AllocVa, - &pAd->TxBufSpace[num].AllocPa); - - if (pAd->TxBufSpace[num].AllocVa == NULL) - { - ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; - DBGPRINT_ERR(("Failed to allocate a big buffer\n")); - Status = NDIS_STATUS_RESOURCES; - break; - } - - // Zero init this memory block - NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocSize); - - // Save PA & VA for further operation - BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num].AllocPa); - BufBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxBufSpace[num].AllocPa); - BufBaseVa = pAd->TxBufSpace[num].AllocVa; - - // - // Initialize Tx Ring Descriptor and associated buffer memory - // - pTxRing = &pAd->TxRing[num]; - for (index = 0; index < TX_RING_SIZE; index++) - { - pTxRing->Cell[index].pNdisPacket = NULL; - pTxRing->Cell[index].pNextNdisPacket = NULL; - // Init Tx Ring Size, Va, Pa variables - pTxRing->Cell[index].AllocSize = TXD_SIZE; - pTxRing->Cell[index].AllocVa = RingBaseVa; - RTMP_SetPhysicalAddressHigh(pTxRing->Cell[index].AllocPa, RingBasePaHigh); - RTMP_SetPhysicalAddressLow (pTxRing->Cell[index].AllocPa, RingBasePaLow); - - // Setup Tx Buffer size & address. only 802.11 header will store in this space - pDmaBuf = &pTxRing->Cell[index].DmaBuf; - pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; - pDmaBuf->AllocVa = BufBaseVa; - RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, BufBasePaHigh); - RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow); - - // link the pre-allocated TxBuf to TXD - pTxD = (PTXD_STRUC) pTxRing->Cell[index].AllocVa; - pTxD->SDPtr0 = BufBasePaLow; - // advance to next ring descriptor address - pTxD->DMADONE = 1; - RingBasePaLow += TXD_SIZE; - RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; - - // advance to next TxBuf address - BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE; - BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; - } - DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry allocated\n", num, index)); - } - if (Status == NDIS_STATUS_RESOURCES) - break; - - // - // Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler - // - pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE; - RTMP_AllocateMgmtDescMemory( - pAd, - pAd->MgmtDescRing.AllocSize, - FALSE, - &pAd->MgmtDescRing.AllocVa, - &pAd->MgmtDescRing.AllocPa); - - if (pAd->MgmtDescRing.AllocVa == NULL) - { - ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; - DBGPRINT_ERR(("Failed to allocate a big buffer\n")); - Status = NDIS_STATUS_RESOURCES; - break; - } - - // Zero init this memory block - NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize); - - // Save PA & VA for further operation - RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa); - RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->MgmtDescRing.AllocPa); - RingBaseVa = pAd->MgmtDescRing.AllocVa; - - // - // Initialize MGMT Ring and associated buffer memory - // - for (index = 0; index < MGMT_RING_SIZE; index++) - { - pAd->MgmtRing.Cell[index].pNdisPacket = NULL; - pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL; - // Init MGMT Ring Size, Va, Pa variables - pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE; - pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa; - RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index].AllocPa, RingBasePaHigh); - RTMP_SetPhysicalAddressLow (pAd->MgmtRing.Cell[index].AllocPa, RingBasePaLow); - - // Offset to next ring descriptor address - RingBasePaLow += TXD_SIZE; - RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; - - // link the pre-allocated TxBuf to TXD - pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[index].AllocVa; - pTxD->DMADONE = 1; - - // no pre-allocated buffer required in MgmtRing for scatter-gather case - } - DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index)); - - // - // Allocate RX ring descriptor's memory except Tx ring which allocated eariler - // - pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE; - RTMP_AllocateRxDescMemory( - pAd, - pAd->RxDescRing.AllocSize, - FALSE, - &pAd->RxDescRing.AllocVa, - &pAd->RxDescRing.AllocPa); - - if (pAd->RxDescRing.AllocVa == NULL) - { - ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; - DBGPRINT_ERR(("Failed to allocate a big buffer\n")); - Status = NDIS_STATUS_RESOURCES; - break; - } - - // Zero init this memory block - NdisZeroMemory(pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize); - - - printk("RX DESC %p size = %ld\n", pAd->RxDescRing.AllocVa, - pAd->RxDescRing.AllocSize); - - // Save PA & VA for further operation - RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa); - RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->RxDescRing.AllocPa); - RingBaseVa = pAd->RxDescRing.AllocVa; - - // - // Initialize Rx Ring and associated buffer memory - // - for (index = 0; index < RX_RING_SIZE; index++) - { - // Init RX Ring Size, Va, Pa variables - pAd->RxRing.Cell[index].AllocSize = RXD_SIZE; - pAd->RxRing.Cell[index].AllocVa = RingBaseVa; - RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index].AllocPa, RingBasePaHigh); - RTMP_SetPhysicalAddressLow (pAd->RxRing.Cell[index].AllocPa, RingBasePaLow); - - // Offset to next ring descriptor address - RingBasePaLow += RXD_SIZE; - RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE; - - // Setup Rx associated Buffer size & allocate share memory - pDmaBuf = &pAd->RxRing.Cell[index].DmaBuf; - pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE; - pPacket = RTMP_AllocateRxPacketBuffer( - pAd, - pDmaBuf->AllocSize, - FALSE, - &pDmaBuf->AllocVa, - &pDmaBuf->AllocPa); - - /* keep allocated rx packet */ - pAd->RxRing.Cell[index].pNdisPacket = pPacket; - - // Error handling - if (pDmaBuf->AllocVa == NULL) - { - ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; - DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n")); - Status = NDIS_STATUS_RESOURCES; - break; - } - - // Zero init this memory block - NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize); - - // Write RxD buffer address & allocated buffer length - pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa; - pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); - pRxD->DDONE = 0; - } - - DBGPRINT(RT_DEBUG_TRACE, ("Rx Ring: total %d entry allocated\n", index)); - - } while (FALSE); - - - NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME)); - pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); - - if (pAd->FragFrame.pFragPacket == NULL) - { - Status = NDIS_STATUS_RESOURCES; - } - - if (Status != NDIS_STATUS_SUCCESS) - { - // Log error inforamtion - NdisWriteErrorLogEntry( - pAd->AdapterHandle, - NDIS_ERROR_CODE_OUT_OF_RESOURCES, - 1, - ErrorValue); - } - - DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); - return Status; -} - - -/* - ======================================================================== - - Routine Description: - Initialize transmit data structures - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - Note: - Initialize all transmit releated private buffer, include those define - in RTMP_ADAPTER structure and all private data structures. - - ======================================================================== -*/ -VOID NICInitTxRxRingAndBacklogQueue( - IN PRTMP_ADAPTER pAd) -{ - //WPDMA_GLO_CFG_STRUC GloCfg; - int i; - - DBGPRINT(RT_DEBUG_TRACE, ("<--> NICInitTxRxRingAndBacklogQueue\n")); - - // Initialize all transmit related software queues - InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_BE]); - InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_BK]); - InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_VI]); - InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_VO]); - InitializeQueueHeader(&pAd->TxSwQueue[QID_HCCA]); - - // Init RX Ring index pointer - pAd->RxRing.RxSwReadIdx = 0; - pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1; - - // Init TX rings index pointer - for (i=0; iTxRing[i].TxSwFreeIdx = 0; - pAd->TxRing[i].TxCpuIdx = 0; - } - - // init MGMT ring index pointer - pAd->MgmtRing.TxSwFreeIdx = 0; - pAd->MgmtRing.TxCpuIdx = 0; - - pAd->PrivateInfo.TxRingFullCnt = 0; -} - - -/* - ======================================================================== - - Routine Description: - Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero. - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - Note: - Reset NIC to initial state AS IS system boot up time. - - ======================================================================== -*/ -VOID RTMPRingCleanUp( - IN PRTMP_ADAPTER pAd, - IN UCHAR RingType) -{ - PTXD_STRUC pTxD; - PRXD_STRUC pRxD; - PQUEUE_ENTRY pEntry; - PNDIS_PACKET pPacket; - int i; - PRTMP_TX_RING pTxRing; - unsigned long IrqFlags; - - DBGPRINT(RT_DEBUG_TRACE,("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, pAd->RalinkCounters.PendingNdisPacketCount)); - switch (RingType) - { - case QID_AC_BK: - case QID_AC_BE: - case QID_AC_VI: - case QID_AC_VO: - case QID_HCCA: - RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); - pTxRing = &pAd->TxRing[RingType]; - - // We have to clean all descriptors in case some error happened with reset - for (i=0; iCell[i].AllocVa; - - pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNdisPacket; - // release scatter-and-gather NDIS_PACKET - if (pPacket) - { - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - pTxRing->Cell[i].pNdisPacket = NULL; - } - - pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNextNdisPacket; - // release scatter-and-gather NDIS_PACKET - if (pPacket) - { - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - pTxRing->Cell[i].pNextNdisPacket = NULL; - } - } - - RTMP_IO_READ32(pAd, TX_DTX_IDX0 + RingType * 0x10, &pTxRing->TxDmaIdx); - pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; - pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; - RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + RingType * 0x10, pTxRing->TxCpuIdx); - - RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); - RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); - while (pAd->TxSwQueue[RingType].Head != NULL) - { - pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]); - pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - DBGPRINT(RT_DEBUG_TRACE,("Release 1 NDIS packet from s/w backlog queue\n")); - } - RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); - break; - - case QID_MGMT: - // We have to clean all descriptors in case some error happened with reset - NdisAcquireSpinLock(&pAd->MgmtRingLock); - - for (i=0; iMgmtRing.Cell[i].AllocVa; - - pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNdisPacket; - // rlease scatter-and-gather NDIS_PACKET - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - } - pAd->MgmtRing.Cell[i].pNdisPacket = NULL; - - pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNextNdisPacket; - // release scatter-and-gather NDIS_PACKET - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - } - pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL; - - } - - RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pAd->MgmtRing.TxDmaIdx); - pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx; - pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx; - RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); - - NdisReleaseSpinLock(&pAd->MgmtRingLock); - pAd->RalinkCounters.MgmtRingFullCount = 0; - break; - - case QID_RX: - // We have to clean all descriptors in case some error happened with reset - NdisAcquireSpinLock(&pAd->RxRingLock); - - for (i=0; iRxRing.Cell[i].AllocVa; - pRxD->DDONE = 0 ; - } - - RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx); - pAd->RxRing.RxSwReadIdx = pAd->RxRing.RxDmaIdx; - pAd->RxRing.RxCpuIdx = ((pAd->RxRing.RxDmaIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxDmaIdx-1)); - RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); - - NdisReleaseSpinLock(&pAd->RxRingLock); - break; - - default: - break; - } -} - - -NDIS_STATUS AdapterBlockAllocateMemory( - IN PVOID handle, - OUT PVOID *ppAd) -{ - PPCI_DEV pci_dev; - dma_addr_t *phy_addr; - POS_COOKIE pObj = (POS_COOKIE) handle; - - pci_dev = pObj->pci_dev; - phy_addr = &pObj->pAd_pa; - - *ppAd = (PVOID)vmalloc(sizeof(RTMP_ADAPTER)); //pci_alloc_consistent(pci_dev, sizeof(RTMP_ADAPTER), phy_addr); - - if (*ppAd) - { - NdisZeroMemory(*ppAd, sizeof(RTMP_ADAPTER)); - ((PRTMP_ADAPTER)*ppAd)->OS_Cookie = handle; - return (NDIS_STATUS_SUCCESS); - } else { - return (NDIS_STATUS_FAILURE); - } -} - - -void RTMP_AllocateTxDescMemory( - IN PRTMP_ADAPTER pAd, - IN UINT Index, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - - *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); - -} - -void RTMP_AllocateMgmtDescMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - - *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); - -} - -void RTMP_AllocateRxDescMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - - *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); - -} - -void RTMP_FreeRxDescMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN PVOID VirtualAddress, - IN NDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - - PCI_FREE_CONSISTENT(pObj->pci_dev, Length, VirtualAddress, PhysicalAddress); -} - - -void RTMP_AllocateFirstTxBuffer( - IN PRTMP_ADAPTER pAd, - IN UINT Index, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - - *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); -} - -/* - * FUNCTION: Allocate a common buffer for DMA - * ARGUMENTS: - * AdapterHandle: AdapterHandle - * Length: Number of bytes to allocate - * Cached: Whether or not the memory can be cached - * VirtualAddress: Pointer to memory is returned here - * PhysicalAddress: Physical address corresponding to virtual address - */ - -void RTMP_AllocateSharedMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - - *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); -} - -VOID RTMPFreeTxRxRingMemory( - IN PRTMP_ADAPTER pAd) -{ - int index, num , j; - PRTMP_TX_RING pTxRing; - PTXD_STRUC pTxD; - PNDIS_PACKET pPacket; - unsigned int IrqFlags; - - POS_COOKIE pObj =(POS_COOKIE) pAd->OS_Cookie; - - DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n")); - - // Free TxSwQueue Packet - for (index=0; index irq_lock, IrqFlags); - pQueue = &pAd->TxSwQueue[index]; - while (pQueue->Head) - { - pEntry = RemoveHeadQueue(pQueue); - pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - } - RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); - } - - // Free Tx Ring Packet - for (index=0;index< NUM_OF_TX_RING;index++) - { - pTxRing = &pAd->TxRing[index]; - - for (j=0; j< TX_RING_SIZE; j++) - { - pTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa); - pPacket = pTxRing->Cell[j].pNdisPacket; - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - //Always assign pNdisPacket as NULL after clear - pTxRing->Cell[j].pNdisPacket = NULL; - - pPacket = pTxRing->Cell[j].pNextNdisPacket; - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - //Always assign pNextNdisPacket as NULL after clear - pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; - - } - } - - for (index = RX_RING_SIZE - 1 ; index >= 0; index--) - { - if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) && (pAd->RxRing.Cell[index].pNdisPacket)) - { - PCI_UNMAP_SINGLE(pObj->pci_dev, pAd->RxRing.Cell[index].DmaBuf.AllocPa, pAd->RxRing.Cell[index].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE); - RELEASE_NDIS_PACKET(pAd, pAd->RxRing.Cell[index].pNdisPacket, NDIS_STATUS_SUCCESS); - } - } - NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(RTMP_DMACB)); - - if (pAd->RxDescRing.AllocVa) - { - PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->RxDescRing.AllocSize, pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocPa); - } - NdisZeroMemory(&pAd->RxDescRing, sizeof(RTMP_DMABUF)); - - if (pAd->MgmtDescRing.AllocVa) - { - PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->MgmtDescRing.AllocSize, pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocPa); - } - NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF)); - - for (num = 0; num < NUM_OF_TX_RING; num++) - { - if (pAd->TxBufSpace[num].AllocVa) - { - PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->TxBufSpace[num].AllocSize, pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocPa); - } - NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF)); - - if (pAd->TxDescRing[num].AllocVa) - { - PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->TxDescRing[num].AllocSize, pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocPa); - } - NdisZeroMemory(&pAd->TxDescRing[num], sizeof(RTMP_DMABUF)); - } - - if (pAd->FragFrame.pFragPacket) - RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS); - - DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n")); -} - - -/* - * FUNCTION: Allocate a packet buffer for DMA - * ARGUMENTS: - * AdapterHandle: AdapterHandle - * Length: Number of bytes to allocate - * Cached: Whether or not the memory can be cached - * VirtualAddress: Pointer to memory is returned here - * PhysicalAddress: Physical address corresponding to virtual address - * Notes: - * Cached is ignored: always cached memory - */ -PNDIS_PACKET RTMP_AllocateRxPacketBuffer( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - PNDIS_PACKET pkt; - - pkt = RTPKT_TO_OSPKT(DEV_ALLOC_SKB(Length)); - - if (pkt == NULL) { - DBGPRINT(RT_DEBUG_ERROR, ("can't allocate rx %ld size packet\n",Length)); - } - - if (pkt) { - RTMP_SET_PACKET_SOURCE(pkt, PKTSRC_NDIS); - *VirtualAddress = (PVOID) RTPKT_TO_OSPKT(pkt)->data; - *PhysicalAddress = PCI_MAP_SINGLE(pAd, *VirtualAddress, Length, -1, PCI_DMA_FROMDEVICE); - } else { - *VirtualAddress = (PVOID) NULL; - *PhysicalAddress = (NDIS_PHYSICAL_ADDRESS) NULL; - } - - return (PNDIS_PACKET) pkt; -} - - -VOID Invalid_Remaining_Packet( - IN PRTMP_ADAPTER pAd, - IN ULONG VirtualAddress) -{ - NDIS_PHYSICAL_ADDRESS PhysicalAddress; - - PhysicalAddress = PCI_MAP_SINGLE(pAd, (void *)(VirtualAddress+1600), RX_BUFFER_NORMSIZE-1600, -1, PCI_DMA_FROMDEVICE); -} - -PNDIS_PACKET GetPacketFromRxRing( - IN PRTMP_ADAPTER pAd, - OUT PRT28XX_RXD_STRUC pSaveRxD, - OUT BOOLEAN *pbReschedule, - IN OUT UINT32 *pRxPending) -{ - PRXD_STRUC pRxD; - PNDIS_PACKET pRxPacket = NULL; - PNDIS_PACKET pNewPacket; - PVOID AllocVa; - NDIS_PHYSICAL_ADDRESS AllocPa; - BOOLEAN bReschedule = FALSE; - - RTMP_SEM_LOCK(&pAd->RxRingLock); - - if (*pRxPending == 0) - { - // Get how may packets had been received - RTMP_IO_READ32(pAd, RX_DRX_IDX , &pAd->RxRing.RxDmaIdx); - - if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx) - { - // no more rx packets - bReschedule = FALSE; - goto done; - } - - // get rx pending count - if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx) - *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx; - else - *pRxPending = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx; - - } - - // Point to Rx indexed rx ring descriptor - pRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa; - - if (pRxD->DDONE == 0) - { - *pRxPending = 0; - // DMAIndx had done but DDONE bit not ready - bReschedule = TRUE; - goto done; - } - - - // return rx descriptor - NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE); - - pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa); - - if (pNewPacket) - { - // unmap the rx buffer - PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa, - pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE); - pRxPacket = pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket; - - pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE; - pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket = (PNDIS_PACKET) pNewPacket; - pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocVa = AllocVa; - pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa = AllocPa; - /* update SDP0 to new buffer of rx packet */ - pRxD->SDP0 = AllocPa; - } - else - { - //printk("No Rx Buffer\n"); - pRxPacket = NULL; - bReschedule = TRUE; - } - - pRxD->DDONE = 0; - - // had handled one rx packet - *pRxPending = *pRxPending - 1; - - // update rx descriptor and kick rx - INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); - - pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1); - RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); - -done: - RTMP_SEM_UNLOCK(&pAd->RxRingLock); - *pbReschedule = bReschedule; - return pRxPacket; -} -/* End of 2860_rtmp_init.c */ - diff --git a/drivers/staging/rt2860/common/action.c b/drivers/staging/rt2860/common/action.c index 256cb67e0594ba521782564b6402a051cd336f8c..56ad236e11441f8073976c5712883ca5d3f220c4 100644 --- a/drivers/staging/rt2860/common/action.c +++ b/drivers/staging/rt2860/common/action.c @@ -39,10 +39,7 @@ #include "../rt_config.h" #include "action.h" - -static VOID ReservedAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); +static void ReservedAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); /* ========================================================================== @@ -61,75 +58,89 @@ static VOID ReservedAction( MT2_CLS3ERR cls3err_action ========================================================================== */ -VOID ActionStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]) +void ActionStateMachineInit(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *S, + OUT STATE_MACHINE_FUNC Trans[]) { - StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_ACT_STATE, MAX_ACT_MSG, (STATE_MACHINE_FUNC)Drop, ACT_IDLE, ACT_MACHINE_BASE); - - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE, (STATE_MACHINE_FUNC)PeerSpectrumAction); - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE, (STATE_MACHINE_FUNC)PeerQOSAction); - - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)ReservedAction); - - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE, (STATE_MACHINE_FUNC)PeerBAAction); - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE, (STATE_MACHINE_FUNC)PeerHTAction); - StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE, (STATE_MACHINE_FUNC)MlmeADDBAAction); - StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction); - StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction); - - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE, (STATE_MACHINE_FUNC)PeerPublicAction); - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE, (STATE_MACHINE_FUNC)PeerRMAction); - - StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE, (STATE_MACHINE_FUNC)MlmeQOSAction); - StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE, (STATE_MACHINE_FUNC)MlmeDLSAction); - StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID, (STATE_MACHINE_FUNC)MlmeInvalidAction); + StateMachineInit(S, (STATE_MACHINE_FUNC *) Trans, MAX_ACT_STATE, + MAX_ACT_MSG, (STATE_MACHINE_FUNC) Drop, ACT_IDLE, + ACT_MACHINE_BASE); + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE, + (STATE_MACHINE_FUNC) PeerSpectrumAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE, + (STATE_MACHINE_FUNC) PeerQOSAction); + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, + (STATE_MACHINE_FUNC) ReservedAction); + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE, + (STATE_MACHINE_FUNC) PeerBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE, + (STATE_MACHINE_FUNC) PeerHTAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE, + (STATE_MACHINE_FUNC) MlmeADDBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE, + (STATE_MACHINE_FUNC) MlmeDELBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE, + (STATE_MACHINE_FUNC) MlmeDELBAAction); + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE, + (STATE_MACHINE_FUNC) PeerPublicAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE, + (STATE_MACHINE_FUNC) PeerRMAction); + + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE, + (STATE_MACHINE_FUNC) MlmeQOSAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE, + (STATE_MACHINE_FUNC) MlmeDLSAction); + StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID, + (STATE_MACHINE_FUNC) MlmeInvalidAction); } -VOID MlmeADDBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) - +void MlmeADDBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - MLME_ADDBA_REQ_STRUCT *pInfo; - UCHAR Addr[6]; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG Idx; - FRAME_ADDBA_REQ Frame; - ULONG FrameLen; - BA_ORI_ENTRY *pBAEntry = NULL; - - pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg; - NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ)); - - if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr)) - { - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n")); + struct rt_mlme_addba_req *pInfo; + u8 Addr[6]; + u8 *pOutBuffer = NULL; + int NStatus; + unsigned long Idx; + struct rt_frame_addba_req Frame; + unsigned long FrameLen; + struct rt_ba_ori_entry *pBAEntry = NULL; + + pInfo = (struct rt_mlme_addba_req *)Elem->Msg; + NdisZeroMemory(&Frame, sizeof(struct rt_frame_addba_req)); + + if (MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr)) { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("BA - MlmeADDBAAction() allocate memory failed \n")); return; } - // 1. find entry - Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; - if (Idx == 0) - { + /* 1. find entry */ + Idx = + pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; + if (Idx == 0) { MlmeFreeMemory(pAd, pOutBuffer); - DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n")); + DBGPRINT(RT_DEBUG_ERROR, + ("BA - MlmeADDBAAction() can't find BAOriEntry \n")); return; - } - else - { - pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + } else { + pBAEntry = &pAd->BATable.BAOriEntry[Idx]; } { if (ADHOC_ON(pAd)) - ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, + pAd->CurrentAddress, + pAd->CommonCfg.Bssid); else - ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pInfo->pAddr); + ActHeaderInit(pAd, &Frame.Hdr, + pAd->CommonCfg.Bssid, + pAd->CurrentAddress, + pInfo->pAddr); } Frame.Category = CATEGORY_BA; @@ -141,20 +152,29 @@ VOID MlmeADDBAAction( Frame.Token = pInfo->Token; Frame.TimeOutValue = pInfo->TimeOutValue; Frame.BaStartSeq.field.FragNum = 0; - Frame.BaStartSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; + Frame.BaStartSeq.field.StartSeq = + pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; - *(USHORT *)(&Frame.BaParm) = cpu2le16(*(USHORT *)(&Frame.BaParm)); + *(u16 *) (&Frame.BaParm) = + cpu2le16(*(u16 *) (&Frame.BaParm)); Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue); Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(FRAME_ADDBA_REQ), &Frame, - END_OF_ARGS); - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(struct rt_frame_addba_req), &Frame, END_OF_ARGS); + + MiniportMMRequest(pAd, + (MGMT_USE_QUEUE_FLAG | + MapUserPriorityToAccessCategory[pInfo->TID]), + pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); - DBGPRINT(RT_DEBUG_TRACE, ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize)); - } + DBGPRINT(RT_DEBUG_TRACE, + ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", + Frame.BaStartSeq.field.StartSeq, FrameLen, + Frame.BaParm.BufSize)); + } } /* @@ -162,288 +182,277 @@ VOID MlmeADDBAAction( Description: send DELBA and delete BaEntry if any Parametrs: - Elem - MLME message MLME_DELBA_REQ_STRUCT + Elem - MLME message struct rt_mlme_delba_req IRQL = DISPATCH_LEVEL ========================================================================== */ -VOID MlmeDELBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void MlmeDELBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - MLME_DELBA_REQ_STRUCT *pInfo; - PUCHAR pOutBuffer = NULL; - PUCHAR pOutBuffer2 = NULL; - NDIS_STATUS NStatus; - ULONG Idx; - FRAME_DELBA_REQ Frame; - ULONG FrameLen; - FRAME_BAR FrameBar; - - pInfo = (MLME_DELBA_REQ_STRUCT *)Elem->Msg; - // must send back DELBA - NdisZeroMemory(&Frame, sizeof(FRAME_DELBA_REQ)); - DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator)); - - if(MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen)) - { - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeDELBAAction() allocate memory failed 1. \n")); + struct rt_mlme_delba_req *pInfo; + u8 *pOutBuffer = NULL; + u8 *pOutBuffer2 = NULL; + int NStatus; + unsigned long Idx; + struct rt_frame_delba_req Frame; + unsigned long FrameLen; + struct rt_frame_bar FrameBar; + + pInfo = (struct rt_mlme_delba_req *)Elem->Msg; + /* must send back DELBA */ + NdisZeroMemory(&Frame, sizeof(struct rt_frame_delba_req)); + DBGPRINT(RT_DEBUG_TRACE, + ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator)); + + if (MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen)) { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, + ("BA - MlmeDELBAAction() allocate memory failed 1. \n")); return; } - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { MlmeFreeMemory(pAd, pOutBuffer); - DBGPRINT(RT_DEBUG_ERROR, ("BA - MlmeDELBAAction() allocate memory failed 2. \n")); + DBGPRINT(RT_DEBUG_ERROR, + ("BA - MlmeDELBAAction() allocate memory failed 2. \n")); return; } - - // SEND BAR (Send BAR to refresh peer reordering buffer.) - Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; - - BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress); - - FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL funciton. - FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; // make sure sequence not clear in DEL funciton. - FrameBar.BarControl.TID = pInfo->TID; // make sure sequence not clear in DEL funciton. - FrameBar.BarControl.ACKPolicy = IMMED_BA; // make sure sequence not clear in DEL funciton. - FrameBar.BarControl.Compressed = 1; // make sure sequence not clear in DEL funciton. - FrameBar.BarControl.MTID = 0; // make sure sequence not clear in DEL funciton. - - MakeOutgoingFrame(pOutBuffer2, &FrameLen, - sizeof(FRAME_BAR), &FrameBar, - END_OF_ARGS); + /* SEND BAR (Send BAR to refresh peer reordering buffer.) */ + Idx = + pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; + + BarHeaderInit(pAd, &FrameBar, + pAd->MacTab.Content[pInfo->Wcid].Addr, + pAd->CurrentAddress); + + FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL funciton. */ + FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; /* make sure sequence not clear in DEL funciton. */ + FrameBar.BarControl.TID = pInfo->TID; /* make sure sequence not clear in DEL funciton. */ + FrameBar.BarControl.ACKPolicy = IMMED_BA; /* make sure sequence not clear in DEL funciton. */ + FrameBar.BarControl.Compressed = 1; /* make sure sequence not clear in DEL funciton. */ + FrameBar.BarControl.MTID = 0; /* make sure sequence not clear in DEL funciton. */ + + MakeOutgoingFrame(pOutBuffer2, &FrameLen, + sizeof(struct rt_frame_bar), &FrameBar, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); MlmeFreeMemory(pAd, pOutBuffer2); - DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n")); + DBGPRINT(RT_DEBUG_TRACE, + ("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n")); - // SEND DELBA FRAME + /* SEND DELBA FRAME */ FrameLen = 0; { if (ADHOC_ON(pAd)) - ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + ActHeaderInit(pAd, &Frame.Hdr, + pAd->MacTab.Content[pInfo->Wcid]. + Addr, pAd->CurrentAddress, + pAd->CommonCfg.Bssid); else - ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr); + ActHeaderInit(pAd, &Frame.Hdr, + pAd->CommonCfg.Bssid, + pAd->CurrentAddress, + pAd->MacTab.Content[pInfo->Wcid]. + Addr); } Frame.Category = CATEGORY_BA; Frame.Action = DELBA; Frame.DelbaParm.Initiator = pInfo->Initiator; Frame.DelbaParm.TID = pInfo->TID; - Frame.ReasonCode = 39; // Time Out - *(USHORT *)(&Frame.DelbaParm) = cpu2le16(*(USHORT *)(&Frame.DelbaParm)); + Frame.ReasonCode = 39; /* Time Out */ + *(u16 *) (&Frame.DelbaParm) = + cpu2le16(*(u16 *) (&Frame.DelbaParm)); Frame.ReasonCode = cpu2le16(Frame.ReasonCode); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(FRAME_DELBA_REQ), &Frame, - END_OF_ARGS); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(struct rt_frame_delba_req), &Frame, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); - DBGPRINT(RT_DEBUG_TRACE, ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", pInfo->Initiator)); - } + DBGPRINT(RT_DEBUG_TRACE, + ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", + pInfo->Initiator)); + } } -VOID MlmeQOSAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void MlmeQOSAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { } -VOID MlmeDLSAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void MlmeDLSAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { } -VOID MlmeInvalidAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void MlmeInvalidAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - //PUCHAR pOutBuffer = NULL; - //Return the receiving frame except the MSB of category filed set to 1. 7.3.1.11 + /*u8 * pOutBuffer = NULL; */ + /*Return the receiving frame except the MSB of category filed set to 1. 7.3.1.11 */ } -VOID PeerQOSAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void PeerQOSAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { } -VOID PeerBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void PeerBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Action = Elem->Msg[LENGTH_802_11+1]; - - switch(Action) - { - case ADDBA_REQ: - PeerAddBAReqAction(pAd,Elem); - break; - case ADDBA_RESP: - PeerAddBARspAction(pAd,Elem); - break; - case DELBA: - PeerDelBAAction(pAd,Elem); - break; + u8 Action = Elem->Msg[LENGTH_802_11 + 1]; + + switch (Action) { + case ADDBA_REQ: + PeerAddBAReqAction(pAd, Elem); + break; + case ADDBA_RESP: + PeerAddBARspAction(pAd, Elem); + break; + case DELBA: + PeerDelBAAction(pAd, Elem); + break; } } -VOID PeerPublicAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void PeerPublicAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) return; } - -static VOID ReservedAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +static void ReservedAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Category; + u8 Category; - if (Elem->MsgLen <= LENGTH_802_11) - { + if (Elem->MsgLen <= LENGTH_802_11) { return; } Category = Elem->Msg[LENGTH_802_11]; - DBGPRINT(RT_DEBUG_TRACE,("Rcv reserved category(%d) Action Frame\n", Category)); + DBGPRINT(RT_DEBUG_TRACE, + ("Rcv reserved category(%d) Action Frame\n", Category)); hex_dump("Reserved Action Frame", &Elem->Msg[0], Elem->MsgLen); } -VOID PeerRMAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) - +void PeerRMAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { return; } -static VOID respond_ht_information_exchange_action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +static void respond_ht_information_exchange_action(struct rt_rtmp_adapter *pAd, + struct rt_mlme_queue_elem *Elem) { - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen; - FRAME_HT_INFO HTINFOframe, *pFrame; - UCHAR *pAddr; - - - // 2. Always send back ADDBA Response - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE,("ACTION - respond_ht_information_exchange_action() allocate memory failed \n")); + u8 *pOutBuffer = NULL; + int NStatus; + unsigned long FrameLen; + struct rt_frame_ht_info HTINFOframe, *pFrame; + u8 *pAddr; + + /* 2. Always send back ADDBA Response */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("ACTION - respond_ht_information_exchange_action() allocate memory failed \n")); return; } - - // get RA - pFrame = (FRAME_HT_INFO *) &Elem->Msg[0]; + /* get RA */ + pFrame = (struct rt_frame_ht_info *) & Elem->Msg[0]; pAddr = pFrame->Hdr.Addr2; - NdisZeroMemory(&HTINFOframe, sizeof(FRAME_HT_INFO)); - // 2-1. Prepare ADDBA Response frame. + NdisZeroMemory(&HTINFOframe, sizeof(struct rt_frame_ht_info)); + /* 2-1. Prepare ADDBA Response frame. */ { if (ADHOC_ON(pAd)) - ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, + pAd->CurrentAddress, + pAd->CommonCfg.Bssid); else - ActHeaderInit(pAd, &HTINFOframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr); + ActHeaderInit(pAd, &HTINFOframe.Hdr, + pAd->CommonCfg.Bssid, pAd->CurrentAddress, + pAddr); } HTINFOframe.Category = CATEGORY_HT; HTINFOframe.Action = HT_INFO_EXCHANGE; HTINFOframe.HT_Info.Request = 0; - HTINFOframe.HT_Info.Forty_MHz_Intolerant = pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant; - HTINFOframe.HT_Info.STA_Channel_Width = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; + HTINFOframe.HT_Info.Forty_MHz_Intolerant = + pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant; + HTINFOframe.HT_Info.STA_Channel_Width = + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(FRAME_HT_INFO), &HTINFOframe, - END_OF_ARGS); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(struct rt_frame_ht_info), &HTINFOframe, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } -VOID PeerHTAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void PeerHTAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + u8 Action = Elem->Msg[LENGTH_802_11 + 1]; if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) return; - switch(Action) - { - case NOTIFY_BW_ACTION: - DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Notify Channel bandwidth action----> \n")); - - if(pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) - { - // Note, this is to patch DIR-1353 AP. When the AP set to Wep, it will use legacy mode. But AP still keeps - // sending BW_Notify Action frame, and cause us to linkup and linkdown. - // In legacy mode, don't need to parse HT action frame. - DBGPRINT(RT_DEBUG_TRACE,("ACTION -Ignore HT Notify Channel BW when link as legacy mode. BW = %d---> \n", - Elem->Msg[LENGTH_802_11+2] )); - break; - } - - if (Elem->Msg[LENGTH_802_11+2] == 0) // 7.4.8.2. if value is 1, keep the same as supported channel bandwidth. - pAd->MacTab.Content[Elem->Wcid].HTPhyMode.field.BW = 0; - + switch (Action) { + case NOTIFY_BW_ACTION: + DBGPRINT(RT_DEBUG_TRACE, + ("ACTION - HT Notify Channel bandwidth action----> \n")); + + if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) { + /* Note, this is to patch DIR-1353 AP. When the AP set to Wep, it will use legacy mode. But AP still keeps */ + /* sending BW_Notify Action frame, and cause us to linkup and linkdown. */ + /* In legacy mode, don't need to parse HT action frame. */ + DBGPRINT(RT_DEBUG_TRACE, + ("ACTION -Ignore HT Notify Channel BW when link as legacy mode. BW = %d---> \n", + Elem->Msg[LENGTH_802_11 + 2])); break; - case SMPS_ACTION: - // 7.3.1.25 - DBGPRINT(RT_DEBUG_TRACE,("ACTION - SMPS action----> \n")); - if (((Elem->Msg[LENGTH_802_11+2]&0x1) == 0)) - { - pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_ENABLE; - } - else if (((Elem->Msg[LENGTH_802_11+2]&0x2) == 0)) - { - pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_STATIC; - } - else - { - pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_DYNAMIC; - } + } - DBGPRINT(RT_DEBUG_TRACE,("Aid(%d) MIMO PS = %d\n", Elem->Wcid, pAd->MacTab.Content[Elem->Wcid].MmpsMode)); - // rt2860c : add something for smps change. - break; + if (Elem->Msg[LENGTH_802_11 + 2] == 0) /* 7.4.8.2. if value is 1, keep the same as supported channel bandwidth. */ + pAd->MacTab.Content[Elem->Wcid].HTPhyMode.field.BW = 0; + + break; + case SMPS_ACTION: + /* 7.3.1.25 */ + DBGPRINT(RT_DEBUG_TRACE, ("ACTION - SMPS action----> \n")); + if (((Elem->Msg[LENGTH_802_11 + 2] & 0x1) == 0)) { + pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_ENABLE; + } else if (((Elem->Msg[LENGTH_802_11 + 2] & 0x2) == 0)) { + pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_STATIC; + } else { + pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_DYNAMIC; + } - case SETPCO_ACTION: - break; - case MIMO_CHA_MEASURE_ACTION: - break; - case HT_INFO_EXCHANGE: - { - HT_INFORMATION_OCTET *pHT_info; - - pHT_info = (HT_INFORMATION_OCTET *) &Elem->Msg[LENGTH_802_11+2]; - // 7.4.8.10 - DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Information Exchange action----> \n")); - if (pHT_info->Request) - { - respond_ht_information_exchange_action(pAd, Elem); - } + DBGPRINT(RT_DEBUG_TRACE, + ("Aid(%d) MIMO PS = %d\n", Elem->Wcid, + pAd->MacTab.Content[Elem->Wcid].MmpsMode)); + /* rt2860c : add something for smps change. */ + break; + + case SETPCO_ACTION: + break; + case MIMO_CHA_MEASURE_ACTION: + break; + case HT_INFO_EXCHANGE: + { + struct rt_ht_information_octet *pHT_info; + + pHT_info = + (struct rt_ht_information_octet *) & Elem->Msg[LENGTH_802_11 + + 2]; + /* 7.4.8.10 */ + DBGPRINT(RT_DEBUG_TRACE, + ("ACTION - HT Information Exchange action----> \n")); + if (pHT_info->Request) { + respond_ht_information_exchange_action(pAd, + Elem); } - break; + } + break; } } - /* ========================================================================== Description: @@ -458,120 +467,116 @@ VOID PeerHTAction( FALSE , then continue indicaterx at this moment. ========================================================================== */ -VOID ORIBATimerTimeout( - IN PRTMP_ADAPTER pAd) +void ORIBATimerTimeout(struct rt_rtmp_adapter *pAd) { - MAC_TABLE_ENTRY *pEntry; - INT i, total; - UCHAR TID; + struct rt_mac_table_entry *pEntry; + int i, total; + u8 TID; total = pAd->MacTab.Size * NUM_OF_TID; - for (i = 1; ((i 0)) ; i++) - { - if (pAd->BATable.BAOriEntry[i].ORI_BA_Status == Originator_Done) - { - pEntry = &pAd->MacTab.Content[pAd->BATable.BAOriEntry[i].Wcid]; + for (i = 1; ((i < MAX_LEN_OF_BA_ORI_TABLE) && (total > 0)); i++) { + if (pAd->BATable.BAOriEntry[i].ORI_BA_Status == Originator_Done) { + pEntry = + &pAd->MacTab.Content[pAd->BATable.BAOriEntry[i]. + Wcid]; TID = pAd->BATable.BAOriEntry[i].TID; - ASSERT(pAd->BATable.BAOriEntry[i].Wcid < MAX_LEN_OF_MAC_TABLE); + ASSERT(pAd->BATable.BAOriEntry[i].Wcid < + MAX_LEN_OF_MAC_TABLE); } - total --; + total--; } } - -VOID SendRefreshBAR( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry) +void SendRefreshBAR(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry) { - FRAME_BAR FrameBar; - ULONG FrameLen; - NDIS_STATUS NStatus; - PUCHAR pOutBuffer = NULL; - USHORT Sequence; - UCHAR i, TID; - USHORT idx; - BA_ORI_ENTRY *pBAEntry; - - for (i = 0; i BAOriWcidArray[i]; - if (idx == 0) - { + if (idx == 0) { continue; } pBAEntry = &pAd->BATable.BAOriEntry[idx]; - if (pBAEntry->ORI_BA_Status == Originator_Done) - { + if (pBAEntry->ORI_BA_Status == Originator_Done) { TID = pBAEntry->TID; ASSERT(pBAEntry->Wcid < MAX_LEN_OF_MAC_TABLE); - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, + ("BA - MlmeADDBAAction() allocate memory failed \n")); return; } Sequence = pEntry->TxSeq[TID]; - BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->CurrentAddress); + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, + pAd->CurrentAddress); - FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function. - FrameBar.StartingSeq.field.StartSeq = Sequence; // make sure sequence not clear in DEL funciton. - FrameBar.BarControl.TID = TID; // make sure sequence not clear in DEL funciton. + FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL function. */ + FrameBar.StartingSeq.field.StartSeq = Sequence; /* make sure sequence not clear in DEL funciton. */ + FrameBar.BarControl.TID = TID; /* make sure sequence not clear in DEL funciton. */ - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(FRAME_BAR), &FrameBar, - END_OF_ARGS); - - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(struct rt_frame_bar), &FrameBar, + END_OF_ARGS); + /*if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET))) */ + if (1) /* Now we always send BAR. */ + { + /*MiniportMMRequestUnlock(pAd, 0, pOutBuffer, FrameLen); */ + MiniportMMRequest(pAd, + (MGMT_USE_QUEUE_FLAG | + MapUserPriorityToAccessCategory + [TID]), pOutBuffer, + FrameLen); + } MlmeFreeMemory(pAd, pOutBuffer); } } } -VOID ActHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PHEADER_802_11 pHdr80211, - IN PUCHAR Addr1, - IN PUCHAR Addr2, - IN PUCHAR Addr3) +void ActHeaderInit(struct rt_rtmp_adapter *pAd, + struct rt_header_802_11 * pHdr80211, + u8 *Addr1, u8 *Addr2, u8 *Addr3) { - NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); - pHdr80211->FC.Type = BTYPE_MGMT; - pHdr80211->FC.SubType = SUBTYPE_ACTION; + NdisZeroMemory(pHdr80211, sizeof(struct rt_header_802_11)); + pHdr80211->FC.Type = BTYPE_MGMT; + pHdr80211->FC.SubType = SUBTYPE_ACTION; - COPY_MAC_ADDR(pHdr80211->Addr1, Addr1); + COPY_MAC_ADDR(pHdr80211->Addr1, Addr1); COPY_MAC_ADDR(pHdr80211->Addr2, Addr2); - COPY_MAC_ADDR(pHdr80211->Addr3, Addr3); + COPY_MAC_ADDR(pHdr80211->Addr3, Addr3); } -VOID BarHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PFRAME_BAR pCntlBar, - IN PUCHAR pDA, - IN PUCHAR pSA) +void BarHeaderInit(struct rt_rtmp_adapter *pAd, + struct rt_frame_bar * pCntlBar, u8 *pDA, u8 *pSA) { - NdisZeroMemory(pCntlBar, sizeof(FRAME_BAR)); + NdisZeroMemory(pCntlBar, sizeof(struct rt_frame_bar)); pCntlBar->FC.Type = BTYPE_CNTL; pCntlBar->FC.SubType = SUBTYPE_BLOCK_ACK_REQ; - pCntlBar->BarControl.MTID = 0; + pCntlBar->BarControl.MTID = 0; pCntlBar->BarControl.Compressed = 1; pCntlBar->BarControl.ACKPolicy = 0; - - pCntlBar->Duration = 16 + RTMPCalcDuration(pAd, RATE_1, sizeof(FRAME_BA)); + pCntlBar->Duration = + 16 + RTMPCalcDuration(pAd, RATE_1, sizeof(struct rt_frame_ba)); COPY_MAC_ADDR(pCntlBar->Addr1, pDA); COPY_MAC_ADDR(pCntlBar->Addr2, pSA); } - /* ========================================================================== Description: @@ -586,19 +591,14 @@ VOID BarHeaderInit( Return : None. ========================================================================== */ -VOID InsertActField( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN UINT8 Category, - IN UINT8 ActCode) +void InsertActField(struct rt_rtmp_adapter *pAd, + u8 *pFrameBuf, + unsigned long *pFrameLen, u8 Category, u8 ActCode) { - ULONG TempLen; + unsigned long TempLen; - MakeOutgoingFrame( pFrameBuf, &TempLen, - 1, &Category, - 1, &ActCode, - END_OF_ARGS); + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &Category, 1, &ActCode, END_OF_ARGS); *pFrameLen = *pFrameLen + TempLen; diff --git a/drivers/staging/rt2860/common/action.h b/drivers/staging/rt2860/common/action.h index cfc2a5f8d1aa41eb73333a762c243a9ccae004d9..974f8b84039f9df58024bab98f553ad9bf61b6d6 100644 --- a/drivers/staging/rt2860/common/action.h +++ b/drivers/staging/rt2860/common/action.h @@ -39,23 +39,18 @@ #ifndef __ACTION_H__ #define __ACTION_H__ -typedef struct PACKED __HT_INFO_OCTET -{ - UCHAR Request:1; - UCHAR Forty_MHz_Intolerant:1; - UCHAR STA_Channel_Width:1; - UCHAR Reserved:5; -} HT_INFORMATION_OCTET; - - -typedef struct PACKED __FRAME_HT_INFO -{ - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; - HT_INFORMATION_OCTET HT_Info; -} FRAME_HT_INFO, *PFRAME_HT_INFO; +struct PACKED rt_ht_information_octet { + u8 Request:1; + u8 Forty_MHz_Intolerant:1; + u8 STA_Channel_Width:1; + u8 Reserved:5; +}; + +struct PACKED rt_frame_ht_info { + struct rt_header_802_11 Hdr; + u8 Category; + u8 Action; + struct rt_ht_information_octet HT_Info; +}; #endif /* __ACTION_H__ */ - - diff --git a/drivers/staging/rt2860/common/ba_action.c b/drivers/staging/rt2860/common/ba_action.c index b7bbe99d4d57edf8cb7df564849ea45f77cd81de..174f2a73a1bb646c753ff2e9c0faf176cec0dbf0 100644 --- a/drivers/staging/rt2860/common/ba_action.c +++ b/drivers/staging/rt2860/common/ba_action.c @@ -27,42 +27,33 @@ #include "../rt_config.h" - - -#define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) //1 // inital sequence number of BA session +#define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) /*1 // inital sequence number of BA session */ #define ORI_SESSION_MAX_RETRY 8 -#define ORI_BA_SESSION_TIMEOUT (2000) // ms -#define REC_BA_SESSION_IDLE_TIMEOUT (1000) // ms +#define ORI_BA_SESSION_TIMEOUT (2000) /* ms */ +#define REC_BA_SESSION_IDLE_TIMEOUT (1000) /* ms */ -#define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms -#define MAX_REORDERING_PACKET_TIMEOUT ((3000 * HZ)/1000) // system ticks -- 100 ms +#define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms */ +#define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_HZ)/1000) /* system ticks -- 100 ms */ #define RESET_RCV_SEQ (0xFFFF) -static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk); - +static void ba_mpdu_blk_free(struct rt_rtmp_adapter *pAd, + struct reordering_mpdu *mpdu_blk); -BA_ORI_ENTRY *BATableAllocOriEntry( - IN PRTMP_ADAPTER pAd, - OUT USHORT *Idx); +struct rt_ba_ori_entry *BATableAllocOriEntry(struct rt_rtmp_adapter *pAd, u16 * Idx); -BA_REC_ENTRY *BATableAllocRecEntry( - IN PRTMP_ADAPTER pAd, - OUT USHORT *Idx); +struct rt_ba_rec_entry *BATableAllocRecEntry(struct rt_rtmp_adapter *pAd, u16 * Idx); -VOID BAOriSessionSetupTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID BARecSessionIdleTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); +void BAOriSessionSetupTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, + void *SystemSpecific3); +void BARecSessionIdleTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, + void *SystemSpecific3); BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout); BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout); @@ -70,91 +61,78 @@ BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout); #define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \ Announce_Reordering_Packet(_pAd, _mpdu_blk); -VOID BA_MaxWinSizeReasign( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntryPeer, - OUT UCHAR *pWinSize) +void BA_MaxWinSizeReasign(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntryPeer, u8 * pWinSize) { - UCHAR MaxSize; - + u8 MaxSize; - if (pAd->MACVersion >= RALINK_2883_VERSION) // 3*3 + if (pAd->MACVersion >= RALINK_2883_VERSION) /* 3*3 */ { - if (pAd->MACVersion >= RALINK_3070_VERSION) - { - if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled) - MaxSize = 7; // for non-open mode + if (pAd->MACVersion >= RALINK_3070_VERSION) { + if (pEntryPeer->WepStatus != + Ndis802_11EncryptionDisabled) + MaxSize = 7; /* for non-open mode */ else MaxSize = 13; - } - else + } else MaxSize = 31; - } - else if (pAd->MACVersion >= RALINK_2880E_VERSION) // 2880 e + } else if (pAd->MACVersion >= RALINK_2880E_VERSION) /* 2880 e */ { if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled) - MaxSize = 7; // for non-open mode + MaxSize = 7; /* for non-open mode */ else MaxSize = 13; - } - else + } else MaxSize = 7; DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n", - *pWinSize, MaxSize)); + *pWinSize, MaxSize)); - if ((*pWinSize) > MaxSize) - { - DBGPRINT(RT_DEBUG_TRACE, ("ba> reassign max win size from %d to %d\n", - *pWinSize, MaxSize)); + if ((*pWinSize) > MaxSize) { + DBGPRINT(RT_DEBUG_TRACE, + ("ba> reassign max win size from %d to %d\n", + *pWinSize, MaxSize)); *pWinSize = MaxSize; } } -void Announce_Reordering_Packet(IN PRTMP_ADAPTER pAd, - IN struct reordering_mpdu *mpdu) +void Announce_Reordering_Packet(struct rt_rtmp_adapter *pAd, + IN struct reordering_mpdu *mpdu) { - PNDIS_PACKET pPacket; + void *pPacket; pPacket = mpdu->pPacket; - if (mpdu->bAMSDU) - { + if (mpdu->bAMSDU) { ASSERT(0); BA_Reorder_AMSDU_Annnounce(pAd, pPacket); - } - else - { - // - // pass this 802.3 packet to upper layer or forward this packet to WM directly - // + } else { + /* */ + /* pass this 802.3 packet to upper layer or forward this packet to WM directly */ + /* */ - ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket)); + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, + RTMP_GET_PACKET_IF(pPacket)); } } /* * Insert a reordering mpdu into sorted linked list by sequence no. */ -BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu) +BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, + struct reordering_mpdu *mpdu) { struct reordering_mpdu **ppScan = &list->next; - while (*ppScan != NULL) - { - if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ)) - { + while (*ppScan != NULL) { + if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ)) { ppScan = &(*ppScan)->next; - } - else if ((*ppScan)->Sequence == mpdu->Sequence) - { + } else if ((*ppScan)->Sequence == mpdu->Sequence) { /* give up this duplicated frame */ - return(FALSE); - } - else - { + return (FALSE); + } else { /* find position */ break; } @@ -166,11 +144,11 @@ BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reo return TRUE; } - /* * caller lock critical section if necessary */ -static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk) +static inline void ba_enqueue(struct reordering_list *list, + struct reordering_mpdu *mpdu_blk) { list->qlen++; mpdu_blk->next = list->next; @@ -180,47 +158,46 @@ static inline void ba_enqueue(struct reordering_list *list, struct reordering_mp /* * caller lock critical section if necessary */ -static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list) +static inline struct reordering_mpdu *ba_dequeue(struct reordering_list *list) { struct reordering_mpdu *mpdu_blk = NULL; ASSERT(list); - if (list->qlen) - { - list->qlen--; - mpdu_blk = list->next; - if (mpdu_blk) - { - list->next = mpdu_blk->next; - mpdu_blk->next = NULL; - } + if (list->qlen) { + list->qlen--; + mpdu_blk = list->next; + if (mpdu_blk) { + list->next = mpdu_blk->next; + mpdu_blk->next = NULL; } + } return mpdu_blk; } - -static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct reordering_list *list) +static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct + reordering_list + *list) { - return(ba_dequeue(list)); + return (ba_dequeue(list)); } - -static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct reordering_list *list) - { +static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct + reordering_list + *list) +{ ASSERT(list); - return(list->next); - } - + return (list->next); +} /* * free all resource for reordering mechanism */ -void ba_reordering_resource_release(PRTMP_ADAPTER pAd) +void ba_reordering_resource_release(struct rt_rtmp_adapter *pAd) { - BA_TABLE *Tab; - PBA_REC_ENTRY pBAEntry; + struct rt_ba_table *Tab; + struct rt_ba_rec_entry *pBAEntry; struct reordering_mpdu *mpdu_blk; int i; @@ -228,15 +205,14 @@ void ba_reordering_resource_release(PRTMP_ADAPTER pAd) /* I. release all pending reordering packet */ NdisAcquireSpinLock(&pAd->BATabLock); - for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) - { + for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) { pBAEntry = &Tab->BARecEntry[i]; - if (pBAEntry->REC_BA_Status != Recipient_NONE) - { - while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) - { + if (pBAEntry->REC_BA_Status != Recipient_NONE) { + while ((mpdu_blk = + ba_reordering_mpdu_dequeue(&pBAEntry->list))) { ASSERT(mpdu_blk->pPacket); - RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE); + RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, + NDIS_STATUS_FAILURE); ba_mpdu_blk_free(pAd, mpdu_blk); } } @@ -250,15 +226,13 @@ void ba_reordering_resource_release(PRTMP_ADAPTER pAd) NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); } - - /* * Allocate all resource for reordering mechanism */ -BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num) +BOOLEAN ba_reordering_resource_init(struct rt_rtmp_adapter *pAd, int num) { - int i; - PUCHAR mem; + int i; + u8 *mem; struct reordering_mpdu *mpdu_blk; struct reordering_list *freelist; @@ -270,24 +244,26 @@ BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num) freelist->next = NULL; freelist->qlen = 0; - DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu)))); + DBGPRINT(RT_DEBUG_TRACE, + ("Allocate %d memory for BA reordering\n", + (u32)(num * sizeof(struct reordering_mpdu)))); /* allocate number of mpdu_blk memory */ - os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu))); + os_alloc_mem(pAd, (u8 **) & mem, + (num * sizeof(struct reordering_mpdu))); pAd->mpdu_blk_pool.mem = mem; - if (mem == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n")); - return(FALSE); + if (mem == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("Can't Allocate Memory for BA Reordering\n")); + return (FALSE); } /* build mpdu_blk free list */ - for (i=0; impdu_blk_pool.lock); mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist); - if (mpdu_blk) - { -// blk_count++; + if (mpdu_blk) { +/* blk_count++; */ /* reset mpdu_blk */ NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu)); } @@ -317,43 +292,40 @@ static struct reordering_mpdu *ba_mpdu_blk_alloc(PRTMP_ADAPTER pAd) return mpdu_blk; } -static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk) +static void ba_mpdu_blk_free(struct rt_rtmp_adapter *pAd, + struct reordering_mpdu *mpdu_blk) { ASSERT(mpdu_blk); NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); -// blk_count--; +/* blk_count--; */ ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk); NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); } - -static USHORT ba_indicate_reordering_mpdus_in_order( - IN PRTMP_ADAPTER pAd, - IN PBA_REC_ENTRY pBAEntry, - IN USHORT StartSeq) +static u16 ba_indicate_reordering_mpdus_in_order(struct rt_rtmp_adapter *pAd, + struct rt_ba_rec_entry *pBAEntry, + u16 StartSeq) { struct reordering_mpdu *mpdu_blk; - USHORT LastIndSeq = RESET_RCV_SEQ; + u16 LastIndSeq = RESET_RCV_SEQ; NdisAcquireSpinLock(&pBAEntry->RxReRingLock); - while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) - { - /* find in-order frame */ - if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ)) - { - break; - } - /* dequeue in-order frame from reodering list */ - mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); - /* pass this frame up */ + while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) { + /* find in-order frame */ + if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ)) { + break; + } + /* dequeue in-order frame from reodering list */ + mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); + /* pass this frame up */ ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); /* move to next sequence */ - StartSeq = mpdu_blk->Sequence; + StartSeq = mpdu_blk->Sequence; LastIndSeq = StartSeq; /* free mpdu_blk */ - ba_mpdu_blk_free(pAd, mpdu_blk); + ba_mpdu_blk_free(pAd, mpdu_blk); } NdisReleaseSpinLock(&pBAEntry->RxReRingLock); @@ -362,51 +334,44 @@ static USHORT ba_indicate_reordering_mpdus_in_order( return LastIndSeq; } -static void ba_indicate_reordering_mpdus_le_seq( - IN PRTMP_ADAPTER pAd, - IN PBA_REC_ENTRY pBAEntry, - IN USHORT Sequence) +static void ba_indicate_reordering_mpdus_le_seq(struct rt_rtmp_adapter *pAd, + struct rt_ba_rec_entry *pBAEntry, + u16 Sequence) { struct reordering_mpdu *mpdu_blk; NdisAcquireSpinLock(&pBAEntry->RxReRingLock); - while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) - { - /* find in-order frame */ - if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ)) - { + while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) { + /* find in-order frame */ + if ((mpdu_blk->Sequence == Sequence) + || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ)) { /* dequeue in-order frame from reodering list */ mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); /* pass this frame up */ ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); /* free mpdu_blk */ ba_mpdu_blk_free(pAd, mpdu_blk); + } else { + break; } - else - { - break; - } } NdisReleaseSpinLock(&pBAEntry->RxReRingLock); } - -static void ba_refresh_reordering_mpdus( - IN PRTMP_ADAPTER pAd, - PBA_REC_ENTRY pBAEntry) +static void ba_refresh_reordering_mpdus(struct rt_rtmp_adapter *pAd, + struct rt_ba_rec_entry *pBAEntry) { struct reordering_mpdu *mpdu_blk; NdisAcquireSpinLock(&pBAEntry->RxReRingLock); - /* dequeue in-order frame from reodering list */ - while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) - { - /* pass this frame up */ + /* dequeue in-order frame from reodering list */ + while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) { + /* pass this frame up */ ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); pBAEntry->LastIndSeq = mpdu_blk->Sequence; - ba_mpdu_blk_free(pAd, mpdu_blk); + ba_mpdu_blk_free(pAd, mpdu_blk); /* update last indicated sequence */ } @@ -415,248 +380,240 @@ static void ba_refresh_reordering_mpdus( NdisReleaseSpinLock(&pBAEntry->RxReRingLock); } - -//static -void ba_flush_reordering_timeout_mpdus( - IN PRTMP_ADAPTER pAd, - IN PBA_REC_ENTRY pBAEntry, - IN ULONG Now32) - +/*static */ +void ba_flush_reordering_timeout_mpdus(struct rt_rtmp_adapter *pAd, + struct rt_ba_rec_entry *pBAEntry, + unsigned long Now32) { - USHORT Sequence; - -// if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) && -// (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //|| -// (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) && -// (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8))) - if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT/6))) - &&(pBAEntry->list.qlen > 1) - ) - { - DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer), - (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT, - pBAEntry->LastIndSeq)); + u16 Sequence; + +/* if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) && */ +/* (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //|| */ +/* (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) && */ +/* (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8))) */ + if (RTMP_TIME_AFTER + ((unsigned long)Now32, + (unsigned long)(pBAEntry->LastIndSeqAtTimer + + (MAX_REORDERING_PACKET_TIMEOUT / 6))) + && (pBAEntry->list.qlen > 1) + ) { + DBGPRINT(RT_DEBUG_TRACE, + ("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", + pBAEntry->list.qlen, Now32, + (pBAEntry->LastIndSeqAtTimer), + (int)((long)Now32 - + (long)(pBAEntry->LastIndSeqAtTimer)), + MAX_REORDERING_PACKET_TIMEOUT, pBAEntry->LastIndSeq)); ba_refresh_reordering_mpdus(pAd, pBAEntry); pBAEntry->LastIndSeqAtTimer = Now32; - } - else - if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT))) + } else + if (RTMP_TIME_AFTER + ((unsigned long)Now32, + (unsigned long)(pBAEntry->LastIndSeqAtTimer + + (REORDERING_PACKET_TIMEOUT))) && (pBAEntry->list.qlen > 0) - ) - { - // - // force LastIndSeq to shift to LastIndSeq+1 - // - Sequence = (pBAEntry->LastIndSeq+1) & MAXSEQ; - ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); - pBAEntry->LastIndSeqAtTimer = Now32; + ) { + /* */ + /* force LastIndSeq to shift to LastIndSeq+1 */ + /* */ + Sequence = (pBAEntry->LastIndSeq + 1) & MAXSEQ; + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); + pBAEntry->LastIndSeqAtTimer = Now32; + pBAEntry->LastIndSeq = Sequence; + /* */ + /* indicate in-order mpdus */ + /* */ + Sequence = + ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, + Sequence); + if (Sequence != RESET_RCV_SEQ) { pBAEntry->LastIndSeq = Sequence; - // - // indicate in-order mpdus - // - Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence); - if (Sequence != RESET_RCV_SEQ) - { - pBAEntry->LastIndSeq = Sequence; - } + } + + DBGPRINT(RT_DEBUG_OFF, + ("%x, flush one!\n", pBAEntry->LastIndSeq)); } } - /* * generate ADDBA request to * set up BA agreement */ -VOID BAOriSessionSetUp( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN UCHAR TID, - IN USHORT TimeOut, - IN ULONG DelayTime, - IN BOOLEAN isForced) - +void BAOriSessionSetUp(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + u8 TID, + u16 TimeOut, + unsigned long DelayTime, IN BOOLEAN isForced) { - //MLME_ADDBA_REQ_STRUCT AddbaReq; - BA_ORI_ENTRY *pBAEntry = NULL; - USHORT Idx; - BOOLEAN Cancelled; + /*struct rt_mlme_addba_req AddbaReq; */ + struct rt_ba_ori_entry *pBAEntry = NULL; + u16 Idx; + BOOLEAN Cancelled; - if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE)) + if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) + && (isForced == FALSE)) return; - // if this entry is limited to use legacy tx mode, it doesn't generate BA. + /* if this entry is limited to use legacy tx mode, it doesn't generate BA. */ if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT) return; - if ((pEntry->BADeclineBitmap & (1<BADeclineBitmap & (1 << TID)) && (isForced == FALSE)) { + /* try again after 3 secs */ DelayTime = 3000; -// printk("DeCline BA from Peer\n"); -// return; +/* DBGPRINT(RT_DEBUG_TRACE, ("DeCline BA from Peer\n")); */ +/* return; */ } - Idx = pEntry->BAOriWcidArray[TID]; - if (Idx == 0) - { - // allocate a BA session + if (Idx == 0) { + /* allocate a BA session */ pBAEntry = BATableAllocOriEntry(pAd, &Idx); - if (pBAEntry == NULL) - { - DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n")); + if (pBAEntry == NULL) { + DBGPRINT(RT_DEBUG_TRACE, + ("ADDBA - MlmeADDBAAction() allocate BA session failed \n")); return; } - } - else - { - pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + } else { + pBAEntry = &pAd->BATable.BAOriEntry[Idx]; } - if (pBAEntry->ORI_BA_Status >= Originator_WaitRes) - { + if (pBAEntry->ORI_BA_Status >= Originator_WaitRes) { return; } pEntry->BAOriWcidArray[TID] = Idx; - // Initialize BA session + /* Initialize BA session */ pBAEntry->ORI_BA_Status = Originator_WaitRes; pBAEntry->Wcid = pEntry->Aid; pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; pBAEntry->Sequence = BA_ORI_INIT_SEQ; - pBAEntry->Token = 1; // (2008-01-21) Jan Lee recommends it - this token can't be 0 + pBAEntry->Token = 1; /* (2008-01-21) Jan Lee recommends it - this token can't be 0 */ pBAEntry->TID = TID; pBAEntry->TimeOutValue = TimeOut; pBAEntry->pAdapter = pAd; - DBGPRINT(RT_DEBUG_TRACE,("Send AddBA to %02x:%02x:%02x:%02x:%02x:%02x Tid:%d isForced:%d Wcid:%d\n" - ,pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2] - ,pEntry->Addr[3],pEntry->Addr[4],pEntry->Addr[5] - ,TID,isForced,pEntry->Aid)); - - if (!(pEntry->TXBAbitmap & (1<ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE); - } - else + if (!(pEntry->TXBAbitmap & (1 << TID))) { + RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, + GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), + pBAEntry, FALSE); + } else RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); - // set timer to send ADDBA request + /* set timer to send ADDBA request */ RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime); } -VOID BAOriSessionAdd( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN PFRAME_ADDBA_RSP pFrame) +void BAOriSessionAdd(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_frame_addba_rsp * pFrame) { - BA_ORI_ENTRY *pBAEntry = NULL; - BOOLEAN Cancelled; - UCHAR TID; - USHORT Idx; - PUCHAR pOutBuffer2 = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen; - FRAME_BAR FrameBar; + struct rt_ba_ori_entry *pBAEntry = NULL; + BOOLEAN Cancelled; + u8 TID; + u16 Idx; + u8 *pOutBuffer2 = NULL; + int NStatus; + unsigned long FrameLen; + struct rt_frame_bar FrameBar; TID = pFrame->BaParm.TID; Idx = pEntry->BAOriWcidArray[TID]; - pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + pBAEntry = &pAd->BATable.BAOriEntry[Idx]; - // Start fill in parameters. - if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes)) - { - pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, ((UCHAR)pFrame->BaParm.BufSize)); + /* Start fill in parameters. */ + if ((Idx != 0) && (pBAEntry->TID == TID) + && (pBAEntry->ORI_BA_Status == Originator_WaitRes)) { + pBAEntry->BAWinSize = + min(pBAEntry->BAWinSize, ((u8)pFrame->BaParm.BufSize)); BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize); pBAEntry->TimeOutValue = pFrame->TimeOutValue; pBAEntry->ORI_BA_Status = Originator_Done; - // reset sequence number + pAd->BATable.numDoneOriginator++; + + /* reset sequence number */ pBAEntry->Sequence = BA_ORI_INIT_SEQ; - // Set Bitmap flag. - pEntry->TXBAbitmap |= (1<ORIBATimer, &Cancelled); + /* Set Bitmap flag. */ + pEntry->TXBAbitmap |= (1 << TID); + RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); - pBAEntry->ORIBATimer.TimerValue = 0; //pFrame->TimeOutValue; + pBAEntry->ORIBATimer.TimerValue = 0; /*pFrame->TimeOutValue; */ - DBGPRINT(RT_DEBUG_TRACE,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __func__, pEntry->TXBAbitmap, - pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue)); + DBGPRINT(RT_DEBUG_TRACE, + ("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", + __func__, pEntry->TXBAbitmap, pBAEntry->BAWinSize, + pBAEntry->ORIBATimer.TimerValue)); - // SEND BAR ; - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n")); + /* SEND BAR ; */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("BA - BAOriSessionAdd() allocate memory failed \n")); return; } - BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress); + BarHeaderInit(pAd, &FrameBar, + pAd->MacTab.Content[pBAEntry->Wcid].Addr, + pAd->CurrentAddress); - FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function. - FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; // make sure sequence not clear in DEL funciton. - FrameBar.BarControl.TID = pBAEntry->TID; // make sure sequence not clear in DEL funciton. - MakeOutgoingFrame(pOutBuffer2, &FrameLen, - sizeof(FRAME_BAR), &FrameBar, - END_OF_ARGS); + FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL function. */ + FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; /* make sure sequence not clear in DEL funciton. */ + FrameBar.BarControl.TID = pBAEntry->TID; /* make sure sequence not clear in DEL funciton. */ + MakeOutgoingFrame(pOutBuffer2, &FrameLen, + sizeof(struct rt_frame_bar), &FrameBar, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); MlmeFreeMemory(pAd, pOutBuffer2); - if (pBAEntry->ORIBATimer.TimerValue) - RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); // in mSec + RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); /* in mSec */ } } -BOOLEAN BARecSessionAdd( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN PFRAME_ADDBA_REQ pFrame) +BOOLEAN BARecSessionAdd(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_frame_addba_req * pFrame) { - BA_REC_ENTRY *pBAEntry = NULL; - BOOLEAN Status = TRUE; - BOOLEAN Cancelled; - USHORT Idx; - UCHAR TID; - UCHAR BAWinSize; - //UINT32 Value; - //UINT offset; - + struct rt_ba_rec_entry *pBAEntry = NULL; + BOOLEAN Status = TRUE; + BOOLEAN Cancelled; + u16 Idx; + u8 TID; + u8 BAWinSize; + /*u32 Value; */ + /*u32 offset; */ ASSERT(pEntry); - // find TID + /* find TID */ TID = pFrame->BaParm.TID; - BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); + BAWinSize = + min(((u8)pFrame->BaParm.BufSize), + (u8)pAd->CommonCfg.BACapability.field.RxBAWinLimit); - // Intel patch - if (BAWinSize == 0) - { + /* Intel patch */ + if (BAWinSize == 0) { BAWinSize = 64; } Idx = pEntry->BARecWcidArray[TID]; - - if (Idx == 0) - { + if (Idx == 0) { pBAEntry = BATableAllocRecEntry(pAd, &Idx); - } - else - { + } else { pBAEntry = &pAd->BATable.BARecEntry[Idx]; - // flush all pending reordering mpdus + /* flush all pending reordering mpdus */ ba_refresh_reordering_mpdus(pAd, pBAEntry); } - DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __func__, pAd->BATable.numAsRecipient, Idx, - pFrame->BaParm.BufSize, BAWinSize)); + DBGPRINT(RT_DEBUG_TRACE, + ("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __func__, + pAd->BATable.numAsRecipient, Idx, pFrame->BaParm.BufSize, + BAWinSize)); - // Start fill in parameters. - if (pBAEntry != NULL) - { + /* Start fill in parameters. */ + if (pBAEntry != NULL) { ASSERT(pBAEntry->list.qlen == 0); pBAEntry->REC_BA_Status = Recipient_HandleRes; @@ -665,66 +622,62 @@ BOOLEAN BARecSessionAdd( pBAEntry->TID = TID; pBAEntry->TimeOutValue = pFrame->TimeOutValue; pBAEntry->REC_BA_Status = Recipient_Accept; - // initial sequence number - pBAEntry->LastIndSeq = RESET_RCV_SEQ; //pFrame->BaStartSeq.field.StartSeq; + /* initial sequence number */ + pBAEntry->LastIndSeq = RESET_RCV_SEQ; /*pFrame->BaStartSeq.field.StartSeq; */ - printk("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq); + DBGPRINT(RT_DEBUG_OFF, + ("Start Seq = %08x\n", + pFrame->BaStartSeq.field.StartSeq)); - if (pEntry->RXBAbitmap & (1<RXBAbitmap & (1 << TID)) { RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); - } - else - { - RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE); + } else { + RTMPInitTimer(pAd, &pBAEntry->RECBATimer, + GET_TIMER_FUNCTION + (BARecSessionIdleTimeout), pBAEntry, + TRUE); } - // Set Bitmap flag. - pEntry->RXBAbitmap |= (1<RXBAbitmap |= (1 << TID); pEntry->BARecWcidArray[TID] = Idx; - pEntry->BADeclineBitmap &= ~(1<BADeclineBitmap &= ~(1 << TID); - // Set BA session mask in WCID table. - RT28XX_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID); + /* Set BA session mask in WCID table. */ + RTMP_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID); - DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n", - pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID])); - } - else - { + DBGPRINT(RT_DEBUG_TRACE, + ("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n", + pEntry->Aid, pEntry->RXBAbitmap, + pEntry->BARecWcidArray[TID])); + } else { Status = FALSE; - DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n", - PRINT_MAC(pEntry->Addr), TID)); + DBGPRINT(RT_DEBUG_TRACE, + ("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n", + PRINT_MAC(pEntry->Addr), TID)); } - return(Status); + return (Status); } - -BA_REC_ENTRY *BATableAllocRecEntry( - IN PRTMP_ADAPTER pAd, - OUT USHORT *Idx) +struct rt_ba_rec_entry *BATableAllocRecEntry(struct rt_rtmp_adapter *pAd, u16 * Idx) { - int i; - BA_REC_ENTRY *pBAEntry = NULL; - + int i; + struct rt_ba_rec_entry *pBAEntry = NULL; NdisAcquireSpinLock(&pAd->BATabLock); - if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION) - { - printk("BA Recipeint Session (%ld) > %d\n", pAd->BATable.numAsRecipient, - MAX_BARECI_SESSION); + if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION) { + DBGPRINT(RT_DEBUG_OFF, ("BA Recipeint Session (%ld) > %d\n", + pAd->BATable.numAsRecipient, + MAX_BARECI_SESSION)); goto done; } - - // reserve idx 0 to identify BAWcidArray[TID] as empty - for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++) - { - pBAEntry =&pAd->BATable.BARecEntry[i]; - if ((pBAEntry->REC_BA_Status == Recipient_NONE)) - { - // get one + /* reserve idx 0 to identify BAWcidArray[TID] as empty */ + for (i = 1; i < MAX_LEN_OF_BA_REC_TABLE; i++) { + pBAEntry = &pAd->BATable.BARecEntry[i]; + if ((pBAEntry->REC_BA_Status == Recipient_NONE)) { + /* get one */ pAd->BATable.numAsRecipient++; pBAEntry->REC_BA_Status = Recipient_USED; *Idx = i; @@ -737,27 +690,21 @@ done: return pBAEntry; } -BA_ORI_ENTRY *BATableAllocOriEntry( - IN PRTMP_ADAPTER pAd, - OUT USHORT *Idx) +struct rt_ba_ori_entry *BATableAllocOriEntry(struct rt_rtmp_adapter *pAd, u16 * Idx) { - int i; - BA_ORI_ENTRY *pBAEntry = NULL; + int i; + struct rt_ba_ori_entry *pBAEntry = NULL; NdisAcquireSpinLock(&pAd->BATabLock); - if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE)) - { + if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE)) { goto done; } - - // reserve idx 0 to identify BAWcidArray[TID] as empty - for (i=1; iBATable.BAOriEntry[i]; - if ((pBAEntry->ORI_BA_Status == Originator_NONE)) - { - // get one + /* reserve idx 0 to identify BAWcidArray[TID] as empty */ + for (i = 1; i < MAX_LEN_OF_BA_ORI_TABLE; i++) { + pBAEntry = &pAd->BATable.BAOriEntry[i]; + if ((pBAEntry->ORI_BA_Status == Originator_NONE)) { + /* get one */ pAd->BATable.numAsOriginator++; pBAEntry->ORI_BA_Status = Originator_USED; pBAEntry->pAdapter = pAd; @@ -771,32 +718,28 @@ done: return pBAEntry; } - -VOID BATableFreeOriEntry( - IN PRTMP_ADAPTER pAd, - IN ULONG Idx) +void BATableFreeOriEntry(struct rt_rtmp_adapter *pAd, unsigned long Idx) { - BA_ORI_ENTRY *pBAEntry = NULL; - MAC_TABLE_ENTRY *pEntry; - + struct rt_ba_ori_entry *pBAEntry = NULL; + struct rt_mac_table_entry *pEntry; if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) return; - pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + pBAEntry = &pAd->BATable.BAOriEntry[Idx]; - if (pBAEntry->ORI_BA_Status != Originator_NONE) - { + if (pBAEntry->ORI_BA_Status != Originator_NONE) { pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; pEntry->BAOriWcidArray[pBAEntry->TID] = 0; - NdisAcquireSpinLock(&pAd->BATabLock); - if (pBAEntry->ORI_BA_Status == Originator_Done) - { - pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) )); - DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient)); - // Erase Bitmap flag. + if (pBAEntry->ORI_BA_Status == Originator_Done) { + pAd->BATable.numDoneOriginator -= 1; + pEntry->TXBAbitmap &= (~(1 << (pBAEntry->TID))); + DBGPRINT(RT_DEBUG_TRACE, + ("BATableFreeOriEntry numAsOriginator= %ld\n", + pAd->BATable.numAsRecipient)); + /* Erase Bitmap flag. */ } ASSERT(pAd->BATable.numAsOriginator != 0); @@ -809,22 +752,17 @@ VOID BATableFreeOriEntry( } } - -VOID BATableFreeRecEntry( - IN PRTMP_ADAPTER pAd, - IN ULONG Idx) +void BATableFreeRecEntry(struct rt_rtmp_adapter *pAd, unsigned long Idx) { - BA_REC_ENTRY *pBAEntry = NULL; - MAC_TABLE_ENTRY *pEntry; - + struct rt_ba_rec_entry *pBAEntry = NULL; + struct rt_mac_table_entry *pEntry; if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE)) return; - pBAEntry =&pAd->BATable.BARecEntry[Idx]; + pBAEntry = &pAd->BATable.BARecEntry[Idx]; - if (pBAEntry->REC_BA_Status != Recipient_NONE) - { + if (pBAEntry->REC_BA_Status != Recipient_NONE) { pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; pEntry->BARecWcidArray[pBAEntry->TID] = 0; @@ -839,177 +777,177 @@ VOID BATableFreeRecEntry( } } - -VOID BAOriSessionTearDown( - IN OUT PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR TID, - IN BOOLEAN bPassive, - IN BOOLEAN bForceSend) +void BAOriSessionTearDown(struct rt_rtmp_adapter *pAd, + u8 Wcid, + u8 TID, + IN BOOLEAN bPassive, IN BOOLEAN bForceSend) { - ULONG Idx = 0; - BA_ORI_ENTRY *pBAEntry; - BOOLEAN Cancelled; + unsigned long Idx = 0; + struct rt_ba_ori_entry *pBAEntry; + BOOLEAN Cancelled; - if (Wcid >= MAX_LEN_OF_MAC_TABLE) - { + if (Wcid >= MAX_LEN_OF_MAC_TABLE) { return; } - - // - // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). - // + /* */ + /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). */ + /* */ Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID]; - if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) - { - if (bForceSend == TRUE) - { - // force send specified TID DelBA - MLME_DELBA_REQ_STRUCT DelbaReq; - MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); - if (Elem == NULL) - return; + if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) { + if (bForceSend == TRUE) { + /* force send specified TID DelBA */ + struct rt_mlme_delba_req DelbaReq; + struct rt_mlme_queue_elem *Elem = + (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem), + MEM_ALLOC_FLAG); + if (Elem != NULL) { + NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); + NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem)); + + COPY_MAC_ADDR(DelbaReq.Addr, + pAd->MacTab.Content[Wcid].Addr); + DelbaReq.Wcid = Wcid; + DelbaReq.TID = TID; + DelbaReq.Initiator = ORIGINATOR; + Elem->MsgLen = sizeof(DelbaReq); + NdisMoveMemory(Elem->Msg, &DelbaReq, + sizeof(DelbaReq)); + MlmeDELBAAction(pAd, Elem); + kfree(Elem); + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(bForceSend):alloc memory failed!\n", + __func__)); + } + } + + return; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID)); + pBAEntry = &pAd->BATable.BAOriEntry[Idx]; + DBGPRINT(RT_DEBUG_TRACE, + ("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, + Wcid, TID, pBAEntry->ORI_BA_Status)); + /* */ + /* Prepare DelBA action frame and send to the peer. */ + /* */ + if ((bPassive == FALSE) && (TID == pBAEntry->TID) + && (pBAEntry->ORI_BA_Status == Originator_Done)) { + struct rt_mlme_delba_req DelbaReq; + struct rt_mlme_queue_elem *Elem = + (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem), + MEM_ALLOC_FLAG); + if (Elem != NULL) { NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); - NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); + NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem)); - COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); + COPY_MAC_ADDR(DelbaReq.Addr, + pAd->MacTab.Content[Wcid].Addr); DelbaReq.Wcid = Wcid; - DelbaReq.TID = TID; + DelbaReq.TID = pBAEntry->TID; DelbaReq.Initiator = ORIGINATOR; -#if 1 - Elem->MsgLen = sizeof(DelbaReq); + Elem->MsgLen = sizeof(DelbaReq); NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); MlmeDELBAAction(pAd, Elem); kfree(Elem); -#else - MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq); - RT28XX_MLME_HANDLER(pAd); -#endif - } - - return; - } - - DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID)); - - pBAEntry = &pAd->BATable.BAOriEntry[Idx]; - DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status)); - // - // Prepare DelBA action frame and send to the peer. - // - if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done)) - { - MLME_DELBA_REQ_STRUCT DelbaReq; - MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); - if (Elem == NULL) + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("%s():alloc memory failed!\n", __func__)); return; - - NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); - NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); - - COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); - DelbaReq.Wcid = Wcid; - DelbaReq.TID = pBAEntry->TID; - DelbaReq.Initiator = ORIGINATOR; -#if 1 - Elem->MsgLen = sizeof(DelbaReq); - NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); - MlmeDELBAAction(pAd, Elem); - kfree(Elem); -#else - MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq); - RT28XX_MLME_HANDLER(pAd); -#endif + } } RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); BATableFreeOriEntry(pAd, Idx); - if (bPassive) - { - //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE); + if (bPassive) { + /*BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE); */ } } -VOID BARecSessionTearDown( - IN OUT PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR TID, - IN BOOLEAN bPassive) +void BARecSessionTearDown(struct rt_rtmp_adapter *pAd, + u8 Wcid, u8 TID, IN BOOLEAN bPassive) { - ULONG Idx = 0; - BA_REC_ENTRY *pBAEntry; + unsigned long Idx = 0; + struct rt_ba_rec_entry *pBAEntry; - if (Wcid >= MAX_LEN_OF_MAC_TABLE) - { + if (Wcid >= MAX_LEN_OF_MAC_TABLE) { return; } - - // - // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). - // + /* */ + /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). */ + /* */ Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; if (Idx == 0) return; - DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID)); - + DBGPRINT(RT_DEBUG_TRACE, + ("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID)); pBAEntry = &pAd->BATable.BARecEntry[Idx]; - DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status)); - // - // Prepare DelBA action frame and send to the peer. - // - if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept)) - { - MLME_DELBA_REQ_STRUCT DelbaReq; - BOOLEAN Cancelled; - MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); - //ULONG offset; - //UINT32 VALUE; + DBGPRINT(RT_DEBUG_TRACE, + ("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, + Wcid, TID, pBAEntry->REC_BA_Status)); + /* */ + /* Prepare DelBA action frame and send to the peer. */ + /* */ + if ((TID == pBAEntry->TID) + && (pBAEntry->REC_BA_Status == Recipient_Accept)) { + struct rt_mlme_delba_req DelbaReq; + BOOLEAN Cancelled; + /*unsigned long offset; */ + /*u32 VALUE; */ RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); - // - // 1. Send DELBA Action Frame - // - if (bPassive == FALSE) - { - NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); - NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); - - COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); - DelbaReq.Wcid = Wcid; - DelbaReq.TID = TID; - DelbaReq.Initiator = RECIPIENT; -#if 1 - Elem->MsgLen = sizeof(DelbaReq); - NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); - MlmeDELBAAction(pAd, Elem); - kfree(Elem); -#else - MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq); - RT28XX_MLME_HANDLER(pAd); -#endif + /* */ + /* 1. Send DELBA Action Frame */ + /* */ + if (bPassive == FALSE) { + struct rt_mlme_queue_elem *Elem = + (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem), + MEM_ALLOC_FLAG); + if (Elem != NULL) { + NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); + NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem)); + + COPY_MAC_ADDR(DelbaReq.Addr, + pAd->MacTab.Content[Wcid].Addr); + DelbaReq.Wcid = Wcid; + DelbaReq.TID = TID; + DelbaReq.Initiator = RECIPIENT; + Elem->MsgLen = sizeof(DelbaReq); + NdisMoveMemory(Elem->Msg, &DelbaReq, + sizeof(DelbaReq)); + MlmeDELBAAction(pAd, Elem); + kfree(Elem); + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("%s():alloc memory failed!\n", + __func__)); + return; + } } - - // - // 2. Free resource of BA session - // - // flush all pending reordering mpdus + /* */ + /* 2. Free resource of BA session */ + /* */ + /* flush all pending reordering mpdus */ ba_refresh_reordering_mpdus(pAd, pBAEntry); NdisAcquireSpinLock(&pAd->BATabLock); - // Erase Bitmap flag. + /* Erase Bitmap flag. */ pBAEntry->LastIndSeq = RESET_RCV_SEQ; pBAEntry->BAWinSize = 0; - // Erase Bitmap flag at software mactable - pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID))); + /* Erase Bitmap flag at software mactable */ + pAd->MacTab.Content[Wcid].RXBAbitmap &= + (~(1 << (pBAEntry->TID))); pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0; - RT28XX_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID); + RTMP_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID); NdisReleaseSpinLock(&pAd->BATabLock); @@ -1018,20 +956,16 @@ VOID BARecSessionTearDown( BATableFreeRecEntry(pAd, Idx); } -VOID BASessionTearDownALL( - IN OUT PRTMP_ADAPTER pAd, - IN UCHAR Wcid) +void BASessionTearDownALL(struct rt_rtmp_adapter *pAd, u8 Wcid) { int i; - for (i=0; ipAdapter; - // Do nothing if monitor mode is on - if (MONITOR_ON(pAd)) - return; + { + /* Do nothing if monitor mode is on */ + if (MONITOR_ON(pAd)) + return; + } pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; - if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY)) - { - MLME_ADDBA_REQ_STRUCT AddbaReq; + if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) + && (pBAEntry->Token < ORI_SESSION_MAX_RETRY)) { + struct rt_mlme_addba_req AddbaReq; NdisZeroMemory(&AddbaReq, sizeof(AddbaReq)); COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr); - AddbaReq.Wcid = (UCHAR)(pEntry->Aid); + AddbaReq.Wcid = (u8)(pEntry->Aid); AddbaReq.TID = pBAEntry->TID; - AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; + AddbaReq.BaBufSize = + pAd->CommonCfg.BACapability.field.RxBAWinLimit; AddbaReq.TimeOutValue = 0; AddbaReq.Token = pBAEntry->Token; - MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq); - RT28XX_MLME_HANDLER(pAd); - DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) to %02x:%02x:%02x:%02x:%02x:%02x Tid:%d Wcid:%d\n" - ,pBAEntry->Token - ,pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2] - ,pEntry->Addr[3],pEntry->Addr[4],pEntry->Addr[5] - ,pBAEntry->TID,pEntry->Aid)); + MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, + sizeof(struct rt_mlme_addba_req), (void *)& AddbaReq); + RTMP_MLME_HANDLER(pAd); + DBGPRINT(RT_DEBUG_TRACE, + ("BA Ori Session Timeout(%d) : Send ADD BA again\n", + pBAEntry->Token)); + pBAEntry->Token++; RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT); - } - else - { + } else { BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]); } } @@ -1108,419 +1042,383 @@ VOID BAOriSessionSetupTimeout( FALSE , then continue indicaterx at this moment. ========================================================================== */ -VOID BARecSessionIdleTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) +void BARecSessionIdleTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) { - BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext; - PRTMP_ADAPTER pAd; - ULONG Now32; + struct rt_ba_rec_entry *pBAEntry = (struct rt_ba_rec_entry *)FunctionContext; + struct rt_rtmp_adapter *pAd; + unsigned long Now32; if (pBAEntry == NULL) return; - if ((pBAEntry->REC_BA_Status == Recipient_Accept)) - { + if ((pBAEntry->REC_BA_Status == Recipient_Accept)) { NdisGetSystemUpTime(&Now32); - if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT))) - { + if (RTMP_TIME_AFTER + ((unsigned long)Now32, + (unsigned long)(pBAEntry->LastIndSeqAtTimer + + REC_BA_SESSION_IDLE_TIMEOUT))) { pAd = pBAEntry->pAdapter; - // flush all pending reordering mpdus + /* flush all pending reordering mpdus */ ba_refresh_reordering_mpdus(pAd, pBAEntry); - printk("%ld: REC BA session Timeout\n", Now32); + DBGPRINT(RT_DEBUG_OFF, + ("%ld: REC BA session Timeout\n", Now32)); } } } - -VOID PeerAddBAReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) - +void PeerAddBAReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - // 7.4.4.1 - //ULONG Idx; - UCHAR Status = 1; - UCHAR pAddr[6]; - FRAME_ADDBA_RSP ADDframe; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - PFRAME_ADDBA_REQ pAddreqFrame = NULL; - //UCHAR BufSize; - ULONG FrameLen; - PULONG ptemp; - PMAC_TABLE_ENTRY pMacEntry; - - DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __func__, Elem->Wcid)); - - //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen); - - //ADDBA Request from unknown peer, ignore this. + /* 7.4.4.1 */ + /*unsigned long Idx; */ + u8 Status = 1; + u8 pAddr[6]; + struct rt_frame_addba_rsp ADDframe; + u8 *pOutBuffer = NULL; + int NStatus; + struct rt_frame_addba_req * pAddreqFrame = NULL; + /*u8 BufSize; */ + unsigned long FrameLen; + unsigned long *ptemp; + struct rt_mac_table_entry *pMacEntry; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s ==> (Wcid = %d)\n", __func__, Elem->Wcid)); + + /*hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen); */ + + /*ADDBA Request from unknown peer, ignore this. */ if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) return; pMacEntry = &pAd->MacTab.Content[Elem->Wcid]; - DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n")); - ptemp = (PULONG)Elem->Msg; - //DBGPRINT_RAW(RT_DEBUG_EMU, ("%08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x\n", *(ptemp), *(ptemp+1), *(ptemp+2), *(ptemp+3), *(ptemp+4), *(ptemp+5), *(ptemp+6), *(ptemp+7), *(ptemp+8))); - - if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr)) - { - - if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry)) - { - pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); - printk("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid); - if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame)) + DBGPRINT(RT_DEBUG_TRACE, ("BA - PeerAddBAReqAction----> \n")); + ptemp = (unsigned long *)Elem->Msg; + /*DBGPRINT_RAW(RT_DEBUG_EMU, ("%08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x\n", *(ptemp), *(ptemp+1), *(ptemp+2), *(ptemp+3), *(ptemp+4), *(ptemp+5), *(ptemp+6), *(ptemp+7), *(ptemp+8))); */ + + if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr)) { + + if ((pAd->CommonCfg.bBADecline == FALSE) + && IS_HT_STA(pMacEntry)) { + pAddreqFrame = (struct rt_frame_addba_req *) (&Elem->Msg[0]); + DBGPRINT(RT_DEBUG_OFF, + ("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid)); + if (BARecSessionAdd + (pAd, &pAd->MacTab.Content[Elem->Wcid], + pAddreqFrame)) Status = 0; else - Status = 38; // more parameters have invalid values - } - else - { - Status = 37; // the request has been declined. + Status = 38; /* more parameters have invalid values */ + } else { + Status = 37; /* the request has been declined. */ } } if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI) ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC); - pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); - // 2. Always send back ADDBA Response - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n")); + pAddreqFrame = (struct rt_frame_addba_req *) (&Elem->Msg[0]); + /* 2. Always send back ADDBA Response */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("ACTION - PeerBAAction() allocate memory failed \n")); return; } - NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP)); + NdisZeroMemory(&ADDframe, sizeof(struct rt_frame_addba_rsp)); - // 2-1. Prepare ADDBA Response frame. + /* 2-1. Prepare ADDBA Response frame. */ { if (ADHOC_ON(pAd)) - ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, + pAd->CurrentAddress, + pAd->CommonCfg.Bssid); else - ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr); + ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, + pAd->CurrentAddress, pAddr); } ADDframe.Category = CATEGORY_BA; ADDframe.Action = ADDBA_RESP; ADDframe.Token = pAddreqFrame->Token; - // What is the Status code?? need to check. + /* What is the Status code?? need to check. */ ADDframe.StatusCode = Status; ADDframe.BaParm.BAPolicy = IMMED_BA; ADDframe.BaParm.AMSDUSupported = 0; ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID; - ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); - if (ADDframe.BaParm.BufSize == 0) - { + ADDframe.BaParm.BufSize = + min(((u8)pAddreqFrame->BaParm.BufSize), + (u8)pAd->CommonCfg.BACapability.field.RxBAWinLimit); + if (ADDframe.BaParm.BufSize == 0) { ADDframe.BaParm.BufSize = 64; } - ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue; + ADDframe.TimeOutValue = 0; /*pAddreqFrame->TimeOutValue; */ - *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm)); + *(u16 *) (&ADDframe.BaParm) = + cpu2le16(*(u16 *) (&ADDframe.BaParm)); ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode); ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(FRAME_ADDBA_RSP), &ADDframe, - END_OF_ARGS); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(struct rt_frame_addba_rsp), &ADDframe, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); - DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __func__, Elem->Wcid, ADDframe.BaParm.TID, - ADDframe.BaParm.BufSize)); + DBGPRINT(RT_DEBUG_TRACE, + ("%s(%d): TID(%d), BufSize(%d) <== \n", __func__, Elem->Wcid, + ADDframe.BaParm.TID, ADDframe.BaParm.BufSize)); } - -VOID PeerAddBARspAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) - +void PeerAddBARspAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - //UCHAR Idx, i; - //PUCHAR pOutBuffer = NULL; - PFRAME_ADDBA_RSP pFrame = NULL; - //PBA_ORI_ENTRY pBAEntry; + /*u8 Idx, i; */ + /*u8 * pOutBuffer = NULL; */ + struct rt_frame_addba_rsp * pFrame = NULL; + /*struct rt_ba_ori_entry *pBAEntry; */ - //ADDBA Response from unknown peer, ignore this. + /*ADDBA Response from unknown peer, ignore this. */ if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) return; DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __func__, Elem->Wcid)); - //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen); + /*hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen); */ - if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen)) - { - pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]); + if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen)) { + pFrame = (struct rt_frame_addba_rsp *) (&Elem->Msg[0]); - DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode)); - switch (pFrame->StatusCode) - { - case 0: - // I want a BAsession with this peer as an originator. - BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame); - break; - default: - // check status == USED ??? - BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE); - break; + DBGPRINT(RT_DEBUG_TRACE, + ("\t\t StatusCode = %d\n", pFrame->StatusCode)); + switch (pFrame->StatusCode) { + case 0: + /* I want a BAsession with this peer as an originator. */ + BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], + pFrame); + break; + default: + /* check status == USED ??? */ + BAOriSessionTearDown(pAd, Elem->Wcid, + pFrame->BaParm.TID, TRUE, FALSE); + break; } - // Rcv Decline StatusCode + /* Rcv Decline StatusCode */ if ((pFrame->StatusCode == 37) - || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0)) - ) - { - pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<BaParm.TID; + || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) + && (pFrame->StatusCode != 0)) + ) { + pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= + 1 << pFrame->BaParm.TID; } } } -VOID PeerDelBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) - +void PeerDelBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - //UCHAR Idx; - //PUCHAR pOutBuffer = NULL; - PFRAME_DELBA_REQ pDelFrame = NULL; - - DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __func__)); - //DELBA Request from unknown peer, ignore this. - if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen)) - { - pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]); - if (pDelFrame->DelbaParm.Initiator == ORIGINATOR) - { - DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n")); - BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE); - } - else - { - DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode)); - //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen); - BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE); + /*u8 Idx; */ + /*u8 * pOutBuffer = NULL; */ + struct rt_frame_delba_req * pDelFrame = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==>\n", __func__)); + /*DELBA Request from unknown peer, ignore this. */ + if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen)) { + pDelFrame = (struct rt_frame_delba_req *) (&Elem->Msg[0]); + if (pDelFrame->DelbaParm.Initiator == ORIGINATOR) { + DBGPRINT(RT_DEBUG_TRACE, + ("BA - PeerDelBAAction----> ORIGINATOR\n")); + BARecSessionTearDown(pAd, Elem->Wcid, + pDelFrame->DelbaParm.TID, TRUE); + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", + pDelFrame->ReasonCode)); + /*hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen); */ + BAOriSessionTearDown(pAd, Elem->Wcid, + pDelFrame->DelbaParm.TID, TRUE, + FALSE); } } } - -BOOLEAN CntlEnqueueForRecv( - IN PRTMP_ADAPTER pAd, - IN ULONG Wcid, - IN ULONG MsgLen, - IN PFRAME_BA_REQ pMsg) +BOOLEAN CntlEnqueueForRecv(struct rt_rtmp_adapter *pAd, + unsigned long Wcid, + unsigned long MsgLen, struct rt_frame_ba_req * pMsg) { - PFRAME_BA_REQ pFrame = pMsg; - //PRTMP_REORDERBUF pBuffer; - //PRTMP_REORDERBUF pDmaBuf; - PBA_REC_ENTRY pBAEntry; - //BOOLEAN Result; - ULONG Idx; - //UCHAR NumRxPkt; - UCHAR TID;//, i; - - TID = (UCHAR)pFrame->BARControl.TID; - - DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __func__, Wcid, TID)); - //hex_dump("BAR", (PCHAR) pFrame, MsgLen); - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + struct rt_frame_ba_req * pFrame = pMsg; + /*PRTMP_REORDERBUF pBuffer; */ + /*PRTMP_REORDERBUF pDmaBuf; */ + struct rt_ba_rec_entry *pBAEntry; + /*BOOLEAN Result; */ + unsigned long Idx; + /*u8 NumRxPkt; */ + u8 TID; /*, i; */ + + TID = (u8)pFrame->BARControl.TID; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __func__, Wcid, TID)); + /*hex_dump("BAR", (char *)pFrame, MsgLen); */ + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) return FALSE; - // First check the size, it MUST not exceed the mlme queue size - if (MsgLen > MGMT_DMA_BUFFER_SIZE) - { + /* First check the size, it MUST not exceed the mlme queue size */ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) { DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); return FALSE; - } - else if (MsgLen != sizeof(FRAME_BA_REQ)) - { + } else if (MsgLen != sizeof(struct rt_frame_ba_req)) { DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); return FALSE; - } - else if (MsgLen != sizeof(FRAME_BA_REQ)) - { + } else if (MsgLen != sizeof(struct rt_frame_ba_req)) { DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); return FALSE; } - if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8)) - { - // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search. + if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8)) { + /* if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search. */ Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; pBAEntry = &pAd->BATable.BARecEntry[Idx]; - } - else - { + } else { return FALSE; } - DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq )); + DBGPRINT(RT_DEBUG_TRACE, + ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, + pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq)); - if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ)) - { - //printk("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq); - ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq); - pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1); + if (SEQ_SMALLER + (pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, + MAXSEQ)) { + /*DBGPRINT(RT_DEBUG_TRACE, ("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq)); */ + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, + pFrame->BAStartingSeq.field. + StartSeq); + pBAEntry->LastIndSeq = + (pFrame->BAStartingSeq.field.StartSeq == + 0) ? MAXSEQ : (pFrame->BAStartingSeq.field.StartSeq - 1); } - //ba_refresh_reordering_mpdus(pAd, pBAEntry); + /*ba_refresh_reordering_mpdus(pAd, pBAEntry); */ return TRUE; } /* Description : Send PSMP Action frame If PSMP mode switches. */ -VOID SendPSMPAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR Psmp) +void SendPSMPAction(struct rt_rtmp_adapter *pAd, u8 Wcid, u8 Psmp) { - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - //ULONG Idx; - FRAME_PSMP_ACTION Frame; - ULONG FrameLen; - UCHAR bbpdata=0; - UINT32 macdata; - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); + u8 *pOutBuffer = NULL; + int NStatus; + /*unsigned long Idx; */ + struct rt_frame_psmp_action Frame; + unsigned long FrameLen; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, + ("BA - MlmeADDBAAction() allocate memory failed \n")); return; } - ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr); + ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, + pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr); Frame.Category = CATEGORY_HT; Frame.Action = SMPS_ACTION; - switch (Psmp) - { - case MMPS_ENABLE: - if (IS_RT3090(pAd)) - { - // disable MMPS BBP control register - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &bbpdata); - bbpdata &= ~(0x04); //bit 2 - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbpdata); - - // disable MMPS MAC control register - RTMP_IO_READ32(pAd, 0x1210, &macdata); - macdata &= ~(0x09); //bit 0, 3 - RTMP_IO_WRITE32(pAd, 0x1210, macdata); - } - Frame.Psmp = 0; - break; - case MMPS_DYNAMIC: - if (IS_RT3090(pAd)) - { - // enable MMPS BBP control register - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &bbpdata); - bbpdata |= 0x04; //bit 2 - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbpdata); - - // enable MMPS MAC control register - RTMP_IO_READ32(pAd, 0x1210, &macdata); - macdata |= 0x09; //bit 0, 3 - RTMP_IO_WRITE32(pAd, 0x1210, macdata); - } - Frame.Psmp = 3; - break; - case MMPS_STATIC: - if (IS_RT3090(pAd)) - { - // enable MMPS BBP control register - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &bbpdata); - bbpdata |= 0x04; //bit 2 - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbpdata); - - // enable MMPS MAC control register - RTMP_IO_READ32(pAd, 0x1210, &macdata); - macdata |= 0x09; //bit 0, 3 - RTMP_IO_WRITE32(pAd, 0x1210, macdata); - } - Frame.Psmp = 1; - break; + switch (Psmp) { + case MMPS_ENABLE: +#ifdef RT30xx + if (IS_RT30xx(pAd) + && (pAd->Antenna.field.RxPath > 1 + || pAd->Antenna.field.TxPath > 1)) { + RTMP_ASIC_MMPS_DISABLE(pAd); + } +#endif /* RT30xx // */ + Frame.Psmp = 0; + break; + case MMPS_DYNAMIC: + Frame.Psmp = 3; + break; + case MMPS_STATIC: +#ifdef RT30xx + if (IS_RT30xx(pAd) + && (pAd->Antenna.field.RxPath > 1 + || pAd->Antenna.field.TxPath > 1)) { + RTMP_ASIC_MMPS_ENABLE(pAd); + } +#endif /* RT30xx // */ + Frame.Psmp = 1; + break; } - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(FRAME_PSMP_ACTION), &Frame, - END_OF_ARGS); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(struct rt_frame_psmp_action), &Frame, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); - DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp)); + DBGPRINT(RT_DEBUG_ERROR, ("HT - SendPSMPAction( %d ) \n", Frame.Psmp)); } - #define RADIO_MEASUREMENT_REQUEST_ACTION 0 -typedef struct PACKED -{ - UCHAR RegulatoryClass; - UCHAR ChannelNumber; - USHORT RandomInterval; - USHORT MeasurementDuration; - UCHAR MeasurementMode; - UCHAR BSSID[MAC_ADDR_LEN]; - UCHAR ReportingCondition; - UCHAR Threshold; - UCHAR SSIDIE[2]; // 2 byte -} BEACON_REQUEST; - -typedef struct PACKED -{ - UCHAR ID; - UCHAR Length; - UCHAR Token; - UCHAR RequestMode; - UCHAR Type; -} MEASUREMENT_REQ; - - - - -void convert_reordering_packet_to_preAMSDU_or_802_3_packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) +struct PACKED rt_beacon_request { + u8 RegulatoryClass; + u8 ChannelNumber; + u16 RandomInterval; + u16 MeasurementDuration; + u8 MeasurementMode; + u8 BSSID[MAC_ADDR_LEN]; + u8 ReportingCondition; + u8 Threshold; + u8 SSIDIE[2]; /* 2 byte */ +}; + +struct PACKED rt_measurement_req { + u8 ID; + u8 Length; + u8 Token; + u8 RequestMode; + u8 Type; +}; + +void convert_reordering_packet_to_preAMSDU_or_802_3_packet(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, + u8 + FromWhichBSSID) { - PNDIS_PACKET pRxPkt; - UCHAR Header802_3[LENGTH_802_3]; + void *pRxPkt; + u8 Header802_3[LENGTH_802_3]; - // 1. get 802.3 Header - // 2. remove LLC - // a. pointer pRxBlk->pData to payload - // b. modify pRxBlk->DataSize + /* 1. get 802.3 Header */ + /* 2. remove LLC */ + /* a. pointer pRxBlk->pData to payload */ + /* b. modify pRxBlk->DataSize */ RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); ASSERT(pRxBlk->pRxPacket); pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); - RTPKT_TO_OSPKT(pRxPkt)->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); - RTPKT_TO_OSPKT(pRxPkt)->data = pRxBlk->pData; - RTPKT_TO_OSPKT(pRxPkt)->len = pRxBlk->DataSize; - RTPKT_TO_OSPKT(pRxPkt)->tail = RTPKT_TO_OSPKT(pRxPkt)->data + RTPKT_TO_OSPKT(pRxPkt)->len; + SET_OS_PKT_NETDEV(pRxPkt, get_netdev_from_bssid(pAd, FromWhichBSSID)); + SET_OS_PKT_DATAPTR(pRxPkt, pRxBlk->pData); + SET_OS_PKT_LEN(pRxPkt, pRxBlk->DataSize); + SET_OS_PKT_DATATAIL(pRxPkt, pRxBlk->pData, pRxBlk->DataSize); - // - // copy 802.3 header, if necessary - // - if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) - { + /* */ + /* copy 802.3 header, if necessary */ + /* */ + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) { + { #ifdef LINUX - NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3); + NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), + Header802_3, LENGTH_802_3); #endif + } } } - #define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \ do \ { \ @@ -1538,61 +1436,60 @@ void convert_reordering_packet_to_preAMSDU_or_802_3_packet( } \ } while (0); - - -static VOID ba_enqueue_reordering_packet( - IN PRTMP_ADAPTER pAd, - IN PBA_REC_ENTRY pBAEntry, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) +static void ba_enqueue_reordering_packet(struct rt_rtmp_adapter *pAd, + struct rt_ba_rec_entry *pBAEntry, + struct rt_rx_blk *pRxBlk, + u8 FromWhichBSSID) { struct reordering_mpdu *mpdu_blk; - UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence; + u16 Sequence = (u16)pRxBlk->pHeader->Sequence; mpdu_blk = ba_mpdu_blk_alloc(pAd); - if (mpdu_blk != NULL) - { - // Write RxD buffer address & allocated buffer length + if ((mpdu_blk != NULL) && (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP))) { + /* Write RxD buffer address & allocated buffer length */ NdisAcquireSpinLock(&pBAEntry->RxReRingLock); mpdu_blk->Sequence = Sequence; mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU); - convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID); + convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, + pRxBlk, + FromWhichBSSID); STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); - // - // it is necessary for reordering packet to record - // which BSS it come from - // + /* */ + /* it is necessary for reordering packet to record */ + /* which BSS it come from */ + /* */ RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); mpdu_blk->pPacket = pRxBlk->pRxPacket; - if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE) - { - // had been already within reordering list - // don't indicate - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS); + if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) + == FALSE) { + /* had been already within reordering list */ + /* don't indicate */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_SUCCESS); ba_mpdu_blk_free(pAd, mpdu_blk); } - ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize)); + ASSERT((0 <= pBAEntry->list.qlen) + && (pBAEntry->list.qlen <= pBAEntry->BAWinSize)); NdisReleaseSpinLock(&pBAEntry->RxReRingLock); - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n", - pBAEntry->list.qlen)); + } else { + DBGPRINT(RT_DEBUG_ERROR, + (" (%d) Can't allocate reordering mpdu blk\n", + pBAEntry->list.qlen)); /* * flush all pending reordering mpdus * and receving mpdu to upper layer * make tcp/ip to take care reordering mechanism */ - //ba_refresh_reordering_mpdus(pAd, pBAEntry); + /*ba_refresh_reordering_mpdus(pAd, pBAEntry); */ ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); pBAEntry->LastIndSeq = Sequence; @@ -1600,7 +1497,6 @@ static VOID ba_enqueue_reordering_packet( } } - /* ========================================================================== Description: @@ -1619,139 +1515,134 @@ static VOID ba_enqueue_reordering_packet( ========================================================================== */ -VOID Indicate_AMPDU_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) +void Indicate_AMPDU_Packet(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) { - USHORT Idx; - PBA_REC_ENTRY pBAEntry = NULL; - UINT16 Sequence = pRxBlk->pHeader->Sequence; - ULONG Now32; - UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID; - UCHAR TID = pRxBlk->pRxWI->TID; - - - if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > MAX_RX_PKT_LEN)) - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + u16 Idx; + struct rt_ba_rec_entry *pBAEntry = NULL; + u16 Sequence = pRxBlk->pHeader->Sequence; + unsigned long Now32; + u8 Wcid = pRxBlk->pRxWI->WirelessCliID; + u8 TID = pRxBlk->pRxWI->TID; + + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) + && (pRxBlk->DataSize > MAX_RX_PKT_LEN)) { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); return; } - if (Wcid < MAX_LEN_OF_MAC_TABLE) - { + if (Wcid < MAX_LEN_OF_MAC_TABLE) { Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; - if (Idx == 0) - { + if (Idx == 0) { /* Rec BA Session had been torn down */ INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); return; } pBAEntry = &pAd->BATable.BARecEntry[Idx]; - } - else - { - // impossible !!! + } else { + /* impossible ! */ ASSERT(0); - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); return; } ASSERT(pBAEntry); - // update last rx time + /* update last rx time */ NdisGetSystemUpTime(&Now32); pBAEntry->rcvSeq = Sequence; - ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); pBAEntry->LastIndSeqAtTimer = Now32; - // - // Reset Last Indicate Sequence - // - if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) - { - ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL)); + /* */ + /* Reset Last Indicate Sequence */ + /* */ + if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) { + ASSERT((pBAEntry->list.qlen == 0) + && (pBAEntry->list.next == NULL)); - // reset rcv sequence of BA session + /* reset rcv sequence of BA session */ pBAEntry->LastIndSeq = Sequence; pBAEntry->LastIndSeqAtTimer = Now32; INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); return; } - - // - // I. Check if in order. - // - if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) - { - USHORT LastIndSeq; + /* */ + /* I. Check if in order. */ + /* */ + if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) { + u16 LastIndSeq; pBAEntry->LastIndSeq = Sequence; INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); - LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); - if (LastIndSeq != RESET_RCV_SEQ) - { + LastIndSeq = + ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, + pBAEntry->LastIndSeq); + if (LastIndSeq != RESET_RCV_SEQ) { pBAEntry->LastIndSeq = LastIndSeq; } pBAEntry->LastIndSeqAtTimer = Now32; } - // - // II. Drop Duplicated Packet - // - else if (Sequence == pBAEntry->LastIndSeq) - { + /* */ + /* II. Drop Duplicated Packet */ + /* */ + else if (Sequence == pBAEntry->LastIndSeq) { - // drop and release packet + /* drop and release packet */ pBAEntry->nDropPacket++; - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); } - // - // III. Drop Old Received Packet - // - else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) - { + /* */ + /* III. Drop Old Received Packet */ + /* */ + else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) { - // drop and release packet + /* drop and release packet */ pBAEntry->nDropPacket++; - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); - } - // - // IV. Receive Sequence within Window Size - // - else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ)) - { - ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID); - } - // - // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer - // - else - { - LONG WinStartSeq, TmpSeq; - - - TmpSeq = Sequence - (pBAEntry->BAWinSize) -1; - if (TmpSeq < 0) - { - TmpSeq = (MAXSEQ+1) + TmpSeq; + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); + } + /* */ + /* IV. Receive Sequence within Window Size */ + /* */ + else if (SEQ_SMALLER + (Sequence, + (((pBAEntry->LastIndSeq + pBAEntry->BAWinSize + 1)) & MAXSEQ), + MAXSEQ)) { + ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, + FromWhichBSSID); + } + /* */ + /* V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer */ + /* */ + else { + long WinStartSeq, TmpSeq; + + TmpSeq = Sequence - (pBAEntry->BAWinSize) - 1; + if (TmpSeq < 0) { + TmpSeq = (MAXSEQ + 1) + TmpSeq; } - WinStartSeq = (TmpSeq+1) & MAXSEQ; + WinStartSeq = (TmpSeq + 1) & MAXSEQ; ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq); - pBAEntry->LastIndSeq = WinStartSeq; //TmpSeq; + pBAEntry->LastIndSeq = WinStartSeq; /*TmpSeq; */ pBAEntry->LastIndSeqAtTimer = Now32; - ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID); + ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, + FromWhichBSSID); - TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); - if (TmpSeq != RESET_RCV_SEQ) - { + TmpSeq = + ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, + pBAEntry->LastIndSeq); + if (TmpSeq != RESET_RCV_SEQ) { pBAEntry->LastIndSeq = TmpSeq; } } diff --git a/drivers/staging/rt3090/common/cmm_aes.c b/drivers/staging/rt2860/common/cmm_aes.c similarity index 51% rename from drivers/staging/rt3090/common/cmm_aes.c rename to drivers/staging/rt2860/common/cmm_aes.c index 4ccbbbfe4cca2cf41cfcce515a52c78a87cf42a7..250357c5cd65fe692a5b58c1adbe766e4a8dcbcd 100644 --- a/drivers/staging/rt3090/common/cmm_aes.c +++ b/drivers/staging/rt2860/common/cmm_aes.c @@ -35,23 +35,19 @@ Paul Wu 02-25-02 Initial */ -#include "../rt_config.h" +#include "../rt_config.h" - -typedef struct -{ - UINT32 erk[64]; /* encryption round keys */ - UINT32 drk[64]; /* decryption round keys */ - int nr; /* number of rounds */ -} -aes_context; +struct aes_context { + u32 erk[64]; /* encryption round keys */ + u32 drk[64]; /* decryption round keys */ + int nr; /* number of rounds */ +}; /*****************************/ /******** SBOX Table *********/ /*****************************/ -UCHAR SboxTable[256] = -{ +u8 SboxTable[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, @@ -86,46 +82,34 @@ UCHAR SboxTable[256] = 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; -VOID xor_32( - IN PUCHAR a, - IN PUCHAR b, - OUT PUCHAR out) +void xor_32(u8 *a, u8 *b, u8 *out) { - INT i; + int i; - for (i=0;i<4; i++) - { + for (i = 0; i < 4; i++) { out[i] = a[i] ^ b[i]; } } -VOID xor_128( - IN PUCHAR a, - IN PUCHAR b, - OUT PUCHAR out) +void xor_128(u8 *a, u8 *b, u8 *out) { - INT i; + int i; - for (i=0;i<16; i++) - { + for (i = 0; i < 16; i++) { out[i] = a[i] ^ b[i]; } } -UCHAR RTMPCkipSbox( - IN UCHAR a) +u8 RTMPCkipSbox(u8 a) { return SboxTable[(int)a]; } -VOID next_key( - IN PUCHAR key, - IN INT round) +void next_key(u8 *key, int round) { - UCHAR rcon; - UCHAR sbox_key[4]; - UCHAR rcon_table[12] = - { + u8 rcon; + u8 sbox_key[4]; + u8 rcon_table[12] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x36, 0x36 }; @@ -145,14 +129,11 @@ VOID next_key( xor_32(&key[12], &key[8], &key[12]); } -VOID byte_sub( - IN PUCHAR in, - OUT PUCHAR out) +void byte_sub(u8 *in, u8 *out) { - INT i; + int i; - for (i=0; i< 16; i++) - { + for (i = 0; i < 16; i++) { out[i] = RTMPCkipSbox(in[i]); } } @@ -165,26 +146,23 @@ VOID byte_sub( void bitwise_xor(unsigned char *ina, unsigned char *inb, unsigned char *out) { int i; - for (i=0; i<16; i++) - { + for (i = 0; i < 16; i++) { out[i] = ina[i] ^ inb[i]; } } -VOID shift_row( - IN PUCHAR in, - OUT PUCHAR out) +void shift_row(u8 *in, u8 *out) { - out[0] = in[0]; - out[1] = in[5]; - out[2] = in[10]; - out[3] = in[15]; - out[4] = in[4]; - out[5] = in[9]; - out[6] = in[14]; - out[7] = in[3]; - out[8] = in[8]; - out[9] = in[13]; + out[0] = in[0]; + out[1] = in[5]; + out[2] = in[10]; + out[3] = in[15]; + out[4] = in[4]; + out[5] = in[9]; + out[6] = in[14]; + out[7] = in[3]; + out[8] = in[8]; + out[9] = in[13]; out[10] = in[2]; out[11] = in[7]; out[12] = in[12]; @@ -193,34 +171,31 @@ VOID shift_row( out[15] = in[11]; } -VOID mix_column( - IN PUCHAR in, - OUT PUCHAR out) +void mix_column(u8 *in, u8 *out) { - INT i; - UCHAR add1b[4]; - UCHAR add1bf7[4]; - UCHAR rotl[4]; - UCHAR swap_halfs[4]; - UCHAR andf7[4]; - UCHAR rotr[4]; - UCHAR temp[4]; - UCHAR tempb[4]; - - for (i=0 ; i<4; i++) - { - if ((in[i] & 0x80)== 0x80) + int i; + u8 add1b[4]; + u8 add1bf7[4]; + u8 rotl[4]; + u8 swap_halfs[4]; + u8 andf7[4]; + u8 rotr[4]; + u8 temp[4]; + u8 tempb[4]; + + for (i = 0; i < 4; i++) { + if ((in[i] & 0x80) == 0x80) add1b[i] = 0x1b; else add1b[i] = 0x00; } - swap_halfs[0] = in[2]; /* Swap halfs */ + swap_halfs[0] = in[2]; /* Swap halfs */ swap_halfs[1] = in[3]; swap_halfs[2] = in[0]; swap_halfs[3] = in[1]; - rotl[0] = in[3]; /* Rotate left 8 bits */ + rotl[0] = in[3]; /* Rotate left 8 bits */ rotl[1] = in[0]; rotl[2] = in[1]; rotl[3] = in[2]; @@ -230,11 +205,9 @@ VOID mix_column( andf7[2] = in[2] & 0x7f; andf7[3] = in[3] & 0x7f; - for (i = 3; i>0; i--) /* logical shift left 1 bit */ - { + for (i = 3; i > 0; i--) { /* logical shift left 1 bit */ andf7[i] = andf7[i] << 1; - if ((andf7[i-1] & 0x80) == 0x80) - { + if ((andf7[i - 1] & 0x80) == 0x80) { andf7[i] = (andf7[i] | 0x01); } } @@ -245,40 +218,37 @@ VOID mix_column( xor_32(in, add1bf7, rotr); - temp[0] = rotr[0]; /* Rotate right 8 bits */ + temp[0] = rotr[0]; /* Rotate right 8 bits */ rotr[0] = rotr[1]; rotr[1] = rotr[2]; rotr[2] = rotr[3]; rotr[3] = temp[0]; xor_32(add1bf7, rotr, temp); - xor_32(swap_halfs, rotl,tempb); + xor_32(swap_halfs, rotl, tempb); xor_32(temp, tempb, out); } - /************************************************/ /* construct_mic_header1() */ /* Builds the first MIC header block from */ /* header fields. */ /************************************************/ -void construct_mic_header1( - unsigned char *mic_header1, - int header_length, - unsigned char *mpdu) +void construct_mic_header1(unsigned char *mic_header1, + int header_length, unsigned char *mpdu) { mic_header1[0] = (unsigned char)((header_length - 2) / 256); mic_header1[1] = (unsigned char)((header_length - 2) % 256); - mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ - mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */ - mic_header1[4] = mpdu[4]; /* A1 */ + mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ + mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */ + mic_header1[4] = mpdu[4]; /* A1 */ mic_header1[5] = mpdu[5]; mic_header1[6] = mpdu[6]; mic_header1[7] = mpdu[7]; mic_header1[8] = mpdu[8]; mic_header1[9] = mpdu[9]; - mic_header1[10] = mpdu[10]; /* A2 */ + mic_header1[10] = mpdu[10]; /* A2 */ mic_header1[11] = mpdu[11]; mic_header1[12] = mpdu[12]; mic_header1[13] = mpdu[13]; @@ -292,84 +262,78 @@ void construct_mic_header1( /* header fields. */ /************************************************/ -void construct_mic_header2( - unsigned char *mic_header2, - unsigned char *mpdu, - int a4_exists, - int qc_exists) +void construct_mic_header2(unsigned char *mic_header2, + unsigned char *mpdu, int a4_exists, int qc_exists) { int i; - for (i = 0; i<16; i++) mic_header2[i]=0x00; + for (i = 0; i < 16; i++) + mic_header2[i] = 0x00; - mic_header2[0] = mpdu[16]; /* A3 */ + mic_header2[0] = mpdu[16]; /* A3 */ mic_header2[1] = mpdu[17]; mic_header2[2] = mpdu[18]; mic_header2[3] = mpdu[19]; mic_header2[4] = mpdu[20]; mic_header2[5] = mpdu[21]; - // In Sequence Control field, mute sequence numer bits (12-bit) - mic_header2[6] = mpdu[22] & 0x0f; /* SC */ - mic_header2[7] = 0x00; /* mpdu[23]; */ + /* In Sequence Control field, mute sequence numer bits (12-bit) */ + mic_header2[6] = mpdu[22] & 0x0f; /* SC */ + mic_header2[7] = 0x00; /* mpdu[23]; */ - if ((!qc_exists) & a4_exists) - { - for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */ + if ((!qc_exists) & a4_exists) { + for (i = 0; i < 6; i++) + mic_header2[8 + i] = mpdu[24 + i]; /* A4 */ } - if (qc_exists && (!a4_exists)) - { - mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */ + if (qc_exists && (!a4_exists)) { + mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */ mic_header2[9] = mpdu[25] & 0x00; } - if (qc_exists && a4_exists) - { - for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */ + if (qc_exists && a4_exists) { + for (i = 0; i < 6; i++) + mic_header2[8 + i] = mpdu[24 + i]; /* A4 */ mic_header2[14] = mpdu[30] & 0x0f; mic_header2[15] = mpdu[31] & 0x00; } } - /************************************************/ /* construct_mic_iv() */ /* Builds the MIC IV from header fields and PN */ /************************************************/ -void construct_mic_iv( - unsigned char *mic_iv, - int qc_exists, - int a4_exists, - unsigned char *mpdu, - unsigned int payload_length, - unsigned char *pn_vector) +void construct_mic_iv(unsigned char *mic_iv, + int qc_exists, + int a4_exists, + unsigned char *mpdu, + unsigned int payload_length, unsigned char *pn_vector) { int i; mic_iv[0] = 0x59; if (qc_exists && a4_exists) - mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ + mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ if (qc_exists && !a4_exists) - mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ + mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ if (!qc_exists) mic_iv[1] = 0x00; for (i = 2; i < 8; i++) - mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */ + mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */ #ifdef CONSISTENT_PN_ORDER - for (i = 8; i < 14; i++) - mic_iv[i] = pn_vector[i - 8]; /* mic_iv[8:13] = PN[0:5] */ + for (i = 8; i < 14; i++) + mic_iv[i] = pn_vector[i - 8]; /* mic_iv[8:13] = PN[0:5] */ #else - for (i = 8; i < 14; i++) - mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ + for (i = 8; i < 14; i++) + mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ #endif i = (payload_length / 256); i = (payload_length % 256); - mic_iv[14] = (unsigned char) (payload_length / 256); - mic_iv[15] = (unsigned char) (payload_length % 256); + mic_iv[14] = (unsigned char)(payload_length / 256); + mic_iv[15] = (unsigned char)(payload_length % 256); } @@ -378,7 +342,8 @@ void construct_mic_iv( /* Performs a 128 bit AES encrypt with */ /* 128 bit data. */ /****************************************/ -void aes128k128d(unsigned char *key, unsigned char *data, unsigned char *ciphertext) +void aes128k128d(unsigned char *key, unsigned char *data, + unsigned char *ciphertext) { int round; int i; @@ -386,23 +351,19 @@ void aes128k128d(unsigned char *key, unsigned char *data, unsigned char *ciphert unsigned char intermediateb[16]; unsigned char round_key[16]; - for(i=0; i<16; i++) round_key[i] = key[i]; + for (i = 0; i < 16; i++) + round_key[i] = key[i]; - for (round = 0; round < 11; round++) - { - if (round == 0) - { + for (round = 0; round < 11; round++) { + if (round == 0) { xor_128(round_key, data, ciphertext); next_key(round_key, round); - } - else if (round == 10) - { + } else if (round == 10) { byte_sub(ciphertext, intermediatea); shift_row(intermediatea, intermediateb); xor_128(intermediateb, round_key, ciphertext); - } - else /* 1 - 9 */ - { + } else { /* 1 - 9 */ + byte_sub(ciphertext, intermediatea); shift_row(intermediatea, intermediateb); mix_column(&intermediateb[0], &intermediatea[0]); @@ -416,78 +377,72 @@ void aes128k128d(unsigned char *key, unsigned char *data, unsigned char *ciphert } -void construct_ctr_preload( - unsigned char *ctr_preload, - int a4_exists, - int qc_exists, - unsigned char *mpdu, - unsigned char *pn_vector, - int c) +void construct_ctr_preload(unsigned char *ctr_preload, + int a4_exists, + int qc_exists, + unsigned char *mpdu, unsigned char *pn_vector, int c) { int i = 0; - for (i=0; i<16; i++) ctr_preload[i] = 0x00; + for (i = 0; i < 16; i++) + ctr_preload[i] = 0x00; i = 0; - ctr_preload[0] = 0x01; /* flag */ - if (qc_exists && a4_exists) ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */ - if (qc_exists && !a4_exists) ctr_preload[1] = mpdu[24] & 0x0f; + ctr_preload[0] = 0x01; /* flag */ + if (qc_exists && a4_exists) + ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */ + if (qc_exists && !a4_exists) + ctr_preload[1] = mpdu[24] & 0x0f; for (i = 2; i < 8; i++) - ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */ + ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */ #ifdef CONSISTENT_PN_ORDER - for (i = 8; i < 14; i++) - ctr_preload[i] = pn_vector[i - 8]; /* ctr_preload[8:13] = PN[0:5] */ + for (i = 8; i < 14; i++) + ctr_preload[i] = pn_vector[i - 8]; /* ctr_preload[8:13] = PN[0:5] */ #else - for (i = 8; i < 14; i++) - ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */ + for (i = 8; i < 14; i++) + ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */ #endif - ctr_preload[14] = (unsigned char) (c / 256); // Ctr - ctr_preload[15] = (unsigned char) (c % 256); + ctr_preload[14] = (unsigned char)(c / 256); /* Ctr */ + ctr_preload[15] = (unsigned char)(c % 256); } -BOOLEAN RTMPSoftDecryptAES( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG DataByteCnt, - IN PCIPHER_KEY pWpaKey) +BOOLEAN RTMPSoftDecryptAES(struct rt_rtmp_adapter *pAd, + u8 *pData, + unsigned long DataByteCnt, struct rt_cipher_key *pWpaKey) { - UCHAR KeyID; - UINT HeaderLen; - UCHAR PN[6]; - UINT payload_len; - UINT num_blocks; - UINT payload_remainder; - USHORT fc; - UCHAR fc0; - UCHAR fc1; - UINT frame_type; - UINT frame_subtype; - UINT from_ds; - UINT to_ds; - INT a4_exists; - INT qc_exists; - UCHAR aes_out[16]; - int payload_index; - UINT i; - UCHAR ctr_preload[16]; - UCHAR chain_buffer[16]; - UCHAR padded_buffer[16]; - UCHAR mic_iv[16]; - UCHAR mic_header1[16]; - UCHAR mic_header2[16]; - UCHAR MIC[8]; - UCHAR TrailMIC[8]; - -#ifdef RT_BIG_ENDIAN - RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE); -#endif + u8 KeyID; + u32 HeaderLen; + u8 PN[6]; + u32 payload_len; + u32 num_blocks; + u32 payload_remainder; + u16 fc; + u8 fc0; + u8 fc1; + u32 frame_type; + u32 frame_subtype; + u32 from_ds; + u32 to_ds; + int a4_exists; + int qc_exists; + u8 aes_out[16]; + int payload_index; + u32 i; + u8 ctr_preload[16]; + u8 chain_buffer[16]; + u8 padded_buffer[16]; + u8 mic_iv[16]; + u8 mic_header1[16]; + u8 mic_header2[16]; + u8 MIC[8]; + u8 TrailMIC[8]; fc0 = *pData; fc1 = *(pData + 1); - fc = *((PUSHORT)pData); + fc = *((u16 *)pData); frame_type = ((fc0 >> 2) & 0x03); frame_subtype = ((fc0 >> 4) & 0x0f); @@ -496,49 +451,42 @@ BOOLEAN RTMPSoftDecryptAES( to_ds = (fc1 & 0x1); a4_exists = (from_ds & to_ds); - qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */ - (frame_subtype == 0x09) || /* Likely to change. */ - (frame_subtype == 0x0a) || - (frame_subtype == 0x0b) - ); + qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */ + (frame_subtype == 0x09) || /* Likely to change. */ + (frame_subtype == 0x0a) || (frame_subtype == 0x0b) + ); HeaderLen = 24; if (a4_exists) HeaderLen += 6; - KeyID = *((PUCHAR)(pData+ HeaderLen + 3)); + KeyID = *((u8 *)(pData + HeaderLen + 3)); KeyID = KeyID >> 6; - if (pWpaKey[KeyID].KeyLen == 0) - { - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptAES failed!(KeyID[%d] Length can not be 0)\n", KeyID)); + if (pWpaKey[KeyID].KeyLen == 0) { + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPSoftDecryptAES failed!(KeyID[%d] Length can not be 0)\n", + KeyID)); return FALSE; } - PN[0] = *(pData+ HeaderLen); - PN[1] = *(pData+ HeaderLen + 1); - PN[2] = *(pData+ HeaderLen + 4); - PN[3] = *(pData+ HeaderLen + 5); - PN[4] = *(pData+ HeaderLen + 6); - PN[5] = *(pData+ HeaderLen + 7); + PN[0] = *(pData + HeaderLen); + PN[1] = *(pData + HeaderLen + 1); + PN[2] = *(pData + HeaderLen + 4); + PN[3] = *(pData + HeaderLen + 5); + PN[4] = *(pData + HeaderLen + 6); + PN[5] = *(pData + HeaderLen + 7); - payload_len = DataByteCnt - HeaderLen - 8 - 8; // 8 bytes for CCMP header , 8 bytes for MIC + payload_len = DataByteCnt - HeaderLen - 8 - 8; /* 8 bytes for CCMP header , 8 bytes for MIC */ payload_remainder = (payload_len) % 16; num_blocks = (payload_len) / 16; + /* Find start of payload */ + payload_index = HeaderLen + 8; /*IV+EIV */ - - // Find start of payload - payload_index = HeaderLen + 8; //IV+EIV - - for (i=0; i< num_blocks; i++) - { + for (i = 0; i < num_blocks; i++) { construct_ctr_preload(ctr_preload, - a4_exists, - qc_exists, - pData, - PN, - i+1 ); + a4_exists, qc_exists, pData, PN, i + 1); aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out); @@ -547,38 +495,30 @@ BOOLEAN RTMPSoftDecryptAES( payload_index += 16; } - // - // If there is a short final block, then pad it - // encrypt it and copy the unpadded part back - // - if (payload_remainder > 0) - { + /* */ + /* If there is a short final block, then pad it */ + /* encrypt it and copy the unpadded part back */ + /* */ + if (payload_remainder > 0) { construct_ctr_preload(ctr_preload, - a4_exists, - qc_exists, - pData, - PN, - num_blocks + 1); + a4_exists, + qc_exists, pData, PN, num_blocks + 1); NdisZeroMemory(padded_buffer, 16); - NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder); + NdisMoveMemory(padded_buffer, pData + payload_index, + payload_remainder); aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out); bitwise_xor(aes_out, padded_buffer, chain_buffer); - NdisMoveMemory(pData + payload_index - 8, chain_buffer, payload_remainder); + NdisMoveMemory(pData + payload_index - 8, chain_buffer, + payload_remainder); payload_index += payload_remainder; } - - // - // Descrypt the MIC - // - construct_ctr_preload(ctr_preload, - a4_exists, - qc_exists, - pData, - PN, - 0); + /* */ + /* Descrypt the MIC */ + /* */ + construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pData, PN, 0); NdisZeroMemory(padded_buffer, 16); NdisMoveMemory(padded_buffer, pData + payload_index, 8); @@ -588,36 +528,22 @@ BOOLEAN RTMPSoftDecryptAES( NdisMoveMemory(TrailMIC, chain_buffer, 8); + /* */ + /* Calculate MIC */ + /* */ - // - // Calculate MIC - // - - //Force the protected frame bit on + /*Force the protected frame bit on */ *(pData + 1) = *(pData + 1) | 0x40; - // Find start of payload - // Because the CCMP header has been removed + /* Find start of payload */ + /* Because the CCMP header has been removed */ payload_index = HeaderLen; - construct_mic_iv( - mic_iv, - qc_exists, - a4_exists, - pData, - payload_len, - PN); - - construct_mic_header1( - mic_header1, - HeaderLen, - pData); - - construct_mic_header2( - mic_header2, - pData, - a4_exists, - qc_exists); + construct_mic_iv(mic_iv, qc_exists, a4_exists, pData, payload_len, PN); + + construct_mic_header1(mic_header1, HeaderLen, pData); + + construct_mic_header2(mic_header2, pData, a4_exists, qc_exists); aes128k128d(pWpaKey[KeyID].Key, mic_iv, aes_out); bitwise_xor(aes_out, mic_header1, chain_buffer); @@ -625,38 +551,32 @@ BOOLEAN RTMPSoftDecryptAES( bitwise_xor(aes_out, mic_header2, chain_buffer); aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); - // iterate through each 16 byte payload block - for (i = 0; i < num_blocks; i++) - { + /* iterate through each 16 byte payload block */ + for (i = 0; i < num_blocks; i++) { bitwise_xor(aes_out, pData + payload_index, chain_buffer); payload_index += 16; aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); } - // Add on the final payload block if it needs padding - if (payload_remainder > 0) - { + /* Add on the final payload block if it needs padding */ + if (payload_remainder > 0) { NdisZeroMemory(padded_buffer, 16); - NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder); + NdisMoveMemory(padded_buffer, pData + payload_index, + payload_remainder); bitwise_xor(aes_out, padded_buffer, chain_buffer); aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); } + /* aes_out contains padded mic, discard most significant */ + /* 8 bytes to generate 64 bit MIC */ + for (i = 0; i < 8; i++) + MIC[i] = aes_out[i]; - // aes_out contains padded mic, discard most significant - // 8 bytes to generate 64 bit MIC - for (i = 0 ; i < 8; i++) MIC[i] = aes_out[i]; - - if (!NdisEqualMemory(MIC, TrailMIC, 8)) - { - DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptAES, MIC Error !\n")); //MIC error. + if (!NdisEqualMemory(MIC, TrailMIC, 8)) { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptAES, MIC Error !\n")); /*MIC error. */ return FALSE; } -#ifdef RT_BIG_ENDIAN - RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE); -#endif - return TRUE; } @@ -670,40 +590,39 @@ BOOLEAN RTMPSoftDecryptAES( #endif /* forward S-box */ -static uint32 FSb[256] = -{ - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, - 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, - 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, - 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, - 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, - 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, - 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, - 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, - 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, - 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, - 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, - 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, - 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, - 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, - 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, - 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, - 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, - 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, - 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, - 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, - 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, - 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, - 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, - 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, - 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +static uint32 FSb[256] = { + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 }; /* forward table */ @@ -776,58 +695,61 @@ static uint32 FSb[256] = #define V(a,b,c,d) 0x##a##b##c##d static uint32 FT0[256] = { FT }; + #undef V #define V(a,b,c,d) 0x##d##a##b##c static uint32 FT1[256] = { FT }; + #undef V #define V(a,b,c,d) 0x##c##d##a##b static uint32 FT2[256] = { FT }; + #undef V #define V(a,b,c,d) 0x##b##c##d##a static uint32 FT3[256] = { FT }; + #undef V #undef FT /* reverse S-box */ -static uint32 RSb[256] = -{ - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, - 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, - 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, - 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, - 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, - 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, - 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, - 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, - 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, - 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, - 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, - 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, - 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, - 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, - 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, - 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, - 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, - 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, - 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, - 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, - 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, - 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, - 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, - 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, - 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, - 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +static uint32 RSb[256] = { + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D }; /* reverse table */ @@ -901,29 +823,32 @@ static uint32 RSb[256] = #define V(a,b,c,d) 0x##a##b##c##d static uint32 RT0[256] = { RT }; + #undef V #define V(a,b,c,d) 0x##d##a##b##c static uint32 RT1[256] = { RT }; + #undef V #define V(a,b,c,d) 0x##c##d##a##b static uint32 RT2[256] = { RT }; + #undef V #define V(a,b,c,d) 0x##b##c##d##a static uint32 RT3[256] = { RT }; + #undef V #undef RT /* round constants */ -static uint32 RCON[10] = -{ - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, - 0x1B000000, 0x36000000 +static uint32 RCON[10] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000 }; /* key schedule tables */ @@ -953,60 +878,61 @@ static uint32 KT3[256]; (b)[(i) + 3] = (uint8) ( (n) ); \ } - -int rt_aes_set_key( aes_context *ctx, uint8 *key, int nbits ) +int rt_aes_set_key(struct aes_context * ctx, uint8 * key, int nbits) { - int i; - uint32 *RK, *SK; - - switch( nbits ) - { - case 128: ctx->nr = 10; break; - case 192: ctx->nr = 12; break; - case 256: ctx->nr = 14; break; - default : return( 1 ); + int i; + uint32 *RK, *SK; + + switch (nbits) { + case 128: + ctx->nr = 10; + break; + case 192: + ctx->nr = 12; + break; + case 256: + ctx->nr = 14; + break; + default: + return (1); } RK = (uint32 *) ctx->erk; - for( i = 0; i < (nbits >> 5); i++ ) - { - GET_UINT32( RK[i], key, i * 4 ); + for (i = 0; i < (nbits >> 5); i++) { + GET_UINT32(RK[i], key, i * 4); } - /* setup encryption round keys */ + /* setup encryption round keys */ - switch( nbits ) - { + switch (nbits) { case 128: - for( i = 0; i < 10; i++, RK += 4 ) - { - RK[4] = RK[0] ^ RCON[i] ^ - ( FSb[ (uint8) ( RK[3] >> 16 ) ] << 24 ) ^ - ( FSb[ (uint8) ( RK[3] >> 8 ) ] << 16 ) ^ - ( FSb[ (uint8) ( RK[3] ) ] << 8 ) ^ - ( FSb[ (uint8) ( RK[3] >> 24 ) ] ); - - RK[5] = RK[1] ^ RK[4]; - RK[6] = RK[2] ^ RK[5]; - RK[7] = RK[3] ^ RK[6]; + for (i = 0; i < 10; i++, RK += 4) { + RK[4] = RK[0] ^ RCON[i] ^ + (FSb[(uint8) (RK[3] >> 16)] << 24) ^ + (FSb[(uint8) (RK[3] >> 8)] << 16) ^ + (FSb[(uint8) (RK[3])] << 8) ^ + (FSb[(uint8) (RK[3] >> 24)]); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; } break; case 192: - for( i = 0; i < 8; i++, RK += 6 ) - { - RK[6] = RK[0] ^ RCON[i] ^ - ( FSb[ (uint8) ( RK[5] >> 16 ) ] << 24 ) ^ - ( FSb[ (uint8) ( RK[5] >> 8 ) ] << 16 ) ^ - ( FSb[ (uint8) ( RK[5] ) ] << 8 ) ^ - ( FSb[ (uint8) ( RK[5] >> 24 ) ] ); - - RK[7] = RK[1] ^ RK[6]; - RK[8] = RK[2] ^ RK[7]; - RK[9] = RK[3] ^ RK[8]; + for (i = 0; i < 8; i++, RK += 6) { + RK[6] = RK[0] ^ RCON[i] ^ + (FSb[(uint8) (RK[5] >> 16)] << 24) ^ + (FSb[(uint8) (RK[5] >> 8)] << 16) ^ + (FSb[(uint8) (RK[5])] << 8) ^ + (FSb[(uint8) (RK[5] >> 24)]); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; RK[10] = RK[4] ^ RK[9]; RK[11] = RK[5] ^ RK[10]; } @@ -1014,23 +940,22 @@ int rt_aes_set_key( aes_context *ctx, uint8 *key, int nbits ) case 256: - for( i = 0; i < 7; i++, RK += 8 ) - { - RK[8] = RK[0] ^ RCON[i] ^ - ( FSb[ (uint8) ( RK[7] >> 16 ) ] << 24 ) ^ - ( FSb[ (uint8) ( RK[7] >> 8 ) ] << 16 ) ^ - ( FSb[ (uint8) ( RK[7] ) ] << 8 ) ^ - ( FSb[ (uint8) ( RK[7] >> 24 ) ] ); + for (i = 0; i < 7; i++, RK += 8) { + RK[8] = RK[0] ^ RCON[i] ^ + (FSb[(uint8) (RK[7] >> 16)] << 24) ^ + (FSb[(uint8) (RK[7] >> 8)] << 16) ^ + (FSb[(uint8) (RK[7])] << 8) ^ + (FSb[(uint8) (RK[7] >> 24)]); - RK[9] = RK[1] ^ RK[8]; + RK[9] = RK[1] ^ RK[8]; RK[10] = RK[2] ^ RK[9]; RK[11] = RK[3] ^ RK[10]; RK[12] = RK[4] ^ - ( FSb[ (uint8) ( RK[11] >> 24 ) ] << 24 ) ^ - ( FSb[ (uint8) ( RK[11] >> 16 ) ] << 16 ) ^ - ( FSb[ (uint8) ( RK[11] >> 8 ) ] << 8 ) ^ - ( FSb[ (uint8) ( RK[11] ) ] ); + (FSb[(uint8) (RK[11] >> 24)] << 24) ^ + (FSb[(uint8) (RK[11] >> 16)] << 16) ^ + (FSb[(uint8) (RK[11] >> 8)] << 8) ^ + (FSb[(uint8) (RK[11])]); RK[13] = RK[5] ^ RK[12]; RK[14] = RK[6] ^ RK[13]; @@ -1039,74 +964,75 @@ int rt_aes_set_key( aes_context *ctx, uint8 *key, int nbits ) break; } - /* setup decryption round keys */ + /* setup decryption round keys */ - if( KT_init ) - { - for( i = 0; i < 256; i++ ) - { - KT0[i] = RT0[ FSb[i] ]; - KT1[i] = RT1[ FSb[i] ]; - KT2[i] = RT2[ FSb[i] ]; - KT3[i] = RT3[ FSb[i] ]; + if (KT_init) { + for (i = 0; i < 256; i++) { + KT0[i] = RT0[FSb[i]]; + KT1[i] = RT1[FSb[i]]; + KT2[i] = RT2[FSb[i]]; + KT3[i] = RT3[FSb[i]]; } - KT_init = 0; + KT_init = 0; } SK = (uint32 *) ctx->drk; - *SK++ = *RK++; - *SK++ = *RK++; - *SK++ = *RK++; - *SK++ = *RK++; + *SK++ = *RK++; + *SK++ = *RK++; + *SK++ = *RK++; + *SK++ = *RK++; - for( i = 1; i < ctx->nr; i++ ) - { + for (i = 1; i < ctx->nr; i++) { RK -= 8; - *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ - KT1[ (uint8) ( *RK >> 16 ) ] ^ - KT2[ (uint8) ( *RK >> 8 ) ] ^ - KT3[ (uint8) ( *RK ) ]; RK++; - - *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ - KT1[ (uint8) ( *RK >> 16 ) ] ^ - KT2[ (uint8) ( *RK >> 8 ) ] ^ - KT3[ (uint8) ( *RK ) ]; RK++; - - *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ - KT1[ (uint8) ( *RK >> 16 ) ] ^ - KT2[ (uint8) ( *RK >> 8 ) ] ^ - KT3[ (uint8) ( *RK ) ]; RK++; - - *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ - KT1[ (uint8) ( *RK >> 16 ) ] ^ - KT2[ (uint8) ( *RK >> 8 ) ] ^ - KT3[ (uint8) ( *RK ) ]; RK++; + *SK++ = KT0[(uint8) (*RK >> 24)] ^ + KT1[(uint8) (*RK >> 16)] ^ + KT2[(uint8) (*RK >> 8)] ^ KT3[(uint8) (*RK)]; + RK++; + + *SK++ = KT0[(uint8) (*RK >> 24)] ^ + KT1[(uint8) (*RK >> 16)] ^ + KT2[(uint8) (*RK >> 8)] ^ KT3[(uint8) (*RK)]; + RK++; + + *SK++ = KT0[(uint8) (*RK >> 24)] ^ + KT1[(uint8) (*RK >> 16)] ^ + KT2[(uint8) (*RK >> 8)] ^ KT3[(uint8) (*RK)]; + RK++; + + *SK++ = KT0[(uint8) (*RK >> 24)] ^ + KT1[(uint8) (*RK >> 16)] ^ + KT2[(uint8) (*RK >> 8)] ^ KT3[(uint8) (*RK)]; + RK++; } RK -= 8; - *SK++ = *RK++; - *SK++ = *RK++; - *SK++ = *RK++; - *SK++ = *RK++; + *SK++ = *RK++; + *SK++ = *RK++; + *SK++ = *RK++; + *SK++ = *RK++; - return( 0 ); + return (0); } /* AES 128-bit block encryption routine */ -void rt_aes_encrypt(aes_context *ctx, uint8 input[16], uint8 output[16] ) +void rt_aes_encrypt(struct aes_context * ctx, uint8 input[16], uint8 output[16]) { - uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; RK = (uint32 *) ctx->erk; - GET_UINT32( X0, input, 0 ); X0 ^= RK[0]; - GET_UINT32( X1, input, 4 ); X1 ^= RK[1]; - GET_UINT32( X2, input, 8 ); X2 ^= RK[2]; - GET_UINT32( X3, input, 12 ); X3 ^= RK[3]; + GET_UINT32(X0, input, 0); + X0 ^= RK[0]; + GET_UINT32(X1, input, 4); + X1 ^= RK[1]; + GET_UINT32(X2, input, 8); + X2 ^= RK[2]; + GET_UINT32(X3, input, 12); + X3 ^= RK[3]; #define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ { \ @@ -1133,70 +1059,68 @@ void rt_aes_encrypt(aes_context *ctx, uint8 input[16], uint8 output[16] ) FT3[ (uint8) ( Y2 ) ]; \ } - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */ - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */ - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */ - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */ - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ - - if( ctx->nr > 10 ) - { - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */ + AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 1 */ + AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 2 */ + AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 3 */ + AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 4 */ + AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 5 */ + AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 6 */ + AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 7 */ + AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 8 */ + AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 9 */ + + if (ctx->nr > 10) { + AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 10 */ + AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 11 */ } - if( ctx->nr > 12 ) - { - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */ + if (ctx->nr > 12) { + AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 12 */ + AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 13 */ } - /* last round */ + /* last round */ RK += 4; - X0 = RK[0] ^ ( FSb[ (uint8) ( Y0 >> 24 ) ] << 24 ) ^ - ( FSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^ - ( FSb[ (uint8) ( Y2 >> 8 ) ] << 8 ) ^ - ( FSb[ (uint8) ( Y3 ) ] ); - - X1 = RK[1] ^ ( FSb[ (uint8) ( Y1 >> 24 ) ] << 24 ) ^ - ( FSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^ - ( FSb[ (uint8) ( Y3 >> 8 ) ] << 8 ) ^ - ( FSb[ (uint8) ( Y0 ) ] ); - - X2 = RK[2] ^ ( FSb[ (uint8) ( Y2 >> 24 ) ] << 24 ) ^ - ( FSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^ - ( FSb[ (uint8) ( Y0 >> 8 ) ] << 8 ) ^ - ( FSb[ (uint8) ( Y1 ) ] ); - - X3 = RK[3] ^ ( FSb[ (uint8) ( Y3 >> 24 ) ] << 24 ) ^ - ( FSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^ - ( FSb[ (uint8) ( Y1 >> 8 ) ] << 8 ) ^ - ( FSb[ (uint8) ( Y2 ) ] ); - - PUT_UINT32( X0, output, 0 ); - PUT_UINT32( X1, output, 4 ); - PUT_UINT32( X2, output, 8 ); - PUT_UINT32( X3, output, 12 ); + X0 = RK[0] ^ (FSb[(uint8) (Y0 >> 24)] << 24) ^ + (FSb[(uint8) (Y1 >> 16)] << 16) ^ + (FSb[(uint8) (Y2 >> 8)] << 8) ^ (FSb[(uint8) (Y3)]); + + X1 = RK[1] ^ (FSb[(uint8) (Y1 >> 24)] << 24) ^ + (FSb[(uint8) (Y2 >> 16)] << 16) ^ + (FSb[(uint8) (Y3 >> 8)] << 8) ^ (FSb[(uint8) (Y0)]); + + X2 = RK[2] ^ (FSb[(uint8) (Y2 >> 24)] << 24) ^ + (FSb[(uint8) (Y3 >> 16)] << 16) ^ + (FSb[(uint8) (Y0 >> 8)] << 8) ^ (FSb[(uint8) (Y1)]); + + X3 = RK[3] ^ (FSb[(uint8) (Y3 >> 24)] << 24) ^ + (FSb[(uint8) (Y0 >> 16)] << 16) ^ + (FSb[(uint8) (Y1 >> 8)] << 8) ^ (FSb[(uint8) (Y2)]); + + PUT_UINT32(X0, output, 0); + PUT_UINT32(X1, output, 4); + PUT_UINT32(X2, output, 8); + PUT_UINT32(X3, output, 12); } /* AES 128-bit block decryption routine */ -void rt_aes_decrypt( aes_context *ctx, uint8 input[16], uint8 output[16] ) +void rt_aes_decrypt(struct aes_context * ctx, uint8 input[16], uint8 output[16]) { - uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; RK = (uint32 *) ctx->drk; - GET_UINT32( X0, input, 0 ); X0 ^= RK[0]; - GET_UINT32( X1, input, 4 ); X1 ^= RK[1]; - GET_UINT32( X2, input, 8 ); X2 ^= RK[2]; - GET_UINT32( X3, input, 12 ); X3 ^= RK[3]; + GET_UINT32(X0, input, 0); + X0 ^= RK[0]; + GET_UINT32(X1, input, 4); + X1 ^= RK[1]; + GET_UINT32(X2, input, 8); + X2 ^= RK[2]; + GET_UINT32(X3, input, 12); + X3 ^= RK[3]; #define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ { \ @@ -1223,56 +1147,50 @@ void rt_aes_decrypt( aes_context *ctx, uint8 input[16], uint8 output[16] ) RT3[ (uint8) ( Y0 ) ]; \ } - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */ - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */ - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */ - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */ - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */ - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */ - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */ - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */ - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ - - if( ctx->nr > 10 ) - { - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */ - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */ + AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 1 */ + AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 2 */ + AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 3 */ + AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 4 */ + AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 5 */ + AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 6 */ + AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 7 */ + AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 8 */ + AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 9 */ + + if (ctx->nr > 10) { + AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 10 */ + AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 11 */ } - if( ctx->nr > 12 ) - { - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */ - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */ + if (ctx->nr > 12) { + AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 12 */ + AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 13 */ } - /* last round */ + /* last round */ RK += 4; - X0 = RK[0] ^ ( RSb[ (uint8) ( Y0 >> 24 ) ] << 24 ) ^ - ( RSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^ - ( RSb[ (uint8) ( Y2 >> 8 ) ] << 8 ) ^ - ( RSb[ (uint8) ( Y1 ) ] ); - - X1 = RK[1] ^ ( RSb[ (uint8) ( Y1 >> 24 ) ] << 24 ) ^ - ( RSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^ - ( RSb[ (uint8) ( Y3 >> 8 ) ] << 8 ) ^ - ( RSb[ (uint8) ( Y2 ) ] ); - - X2 = RK[2] ^ ( RSb[ (uint8) ( Y2 >> 24 ) ] << 24 ) ^ - ( RSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^ - ( RSb[ (uint8) ( Y0 >> 8 ) ] << 8 ) ^ - ( RSb[ (uint8) ( Y3 ) ] ); - - X3 = RK[3] ^ ( RSb[ (uint8) ( Y3 >> 24 ) ] << 24 ) ^ - ( RSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^ - ( RSb[ (uint8) ( Y1 >> 8 ) ] << 8 ) ^ - ( RSb[ (uint8) ( Y0 ) ] ); - - PUT_UINT32( X0, output, 0 ); - PUT_UINT32( X1, output, 4 ); - PUT_UINT32( X2, output, 8 ); - PUT_UINT32( X3, output, 12 ); + X0 = RK[0] ^ (RSb[(uint8) (Y0 >> 24)] << 24) ^ + (RSb[(uint8) (Y3 >> 16)] << 16) ^ + (RSb[(uint8) (Y2 >> 8)] << 8) ^ (RSb[(uint8) (Y1)]); + + X1 = RK[1] ^ (RSb[(uint8) (Y1 >> 24)] << 24) ^ + (RSb[(uint8) (Y0 >> 16)] << 16) ^ + (RSb[(uint8) (Y3 >> 8)] << 8) ^ (RSb[(uint8) (Y2)]); + + X2 = RK[2] ^ (RSb[(uint8) (Y2 >> 24)] << 24) ^ + (RSb[(uint8) (Y1 >> 16)] << 16) ^ + (RSb[(uint8) (Y0 >> 8)] << 8) ^ (RSb[(uint8) (Y3)]); + + X3 = RK[3] ^ (RSb[(uint8) (Y3 >> 24)] << 24) ^ + (RSb[(uint8) (Y2 >> 16)] << 16) ^ + (RSb[(uint8) (Y1 >> 8)] << 8) ^ (RSb[(uint8) (Y0)]); + + PUT_UINT32(X0, output, 0); + PUT_UINT32(X1, output, 4); + PUT_UINT32(X2, output, 8); + PUT_UINT32(X3, output, 12); } /* @@ -1284,57 +1202,51 @@ void rt_aes_decrypt( aes_context *ctx, uint8 input[16], uint8 output[16] ) Return: ========================================================================== */ -VOID AES_GTK_KEY_WRAP( - IN UCHAR *key, - IN UCHAR *plaintext, - IN UINT32 p_len, - OUT UCHAR *ciphertext) +void AES_GTK_KEY_WRAP(u8 * key, + u8 * plaintext, + u32 p_len, u8 * ciphertext) { - UCHAR A[8], BIN[16], BOUT[16]; - UCHAR R[512]; - INT num_blocks = p_len/8; // unit:64bits - INT i, j; - aes_context aesctx; - UCHAR xor; - - rt_aes_set_key(&aesctx, key, 128); - - // Init IA - for (i = 0; i < 8; i++) - A[i] = 0xa6; - - //Input plaintext - for (i = 0; i < num_blocks; i++) - { - for (j = 0 ; j < 8; j++) - R[8 * (i + 1) + j] = plaintext[8 * i + j]; - } - - // Key Mix - for (j = 0; j < 6; j++) - { - for(i = 1; i <= num_blocks; i++) - { - //phase 1 - NdisMoveMemory(BIN, A, 8); - NdisMoveMemory(&BIN[8], &R[8 * i], 8); - rt_aes_encrypt(&aesctx, BIN, BOUT); - - NdisMoveMemory(A, &BOUT[0], 8); - xor = num_blocks * j + i; - A[7] = BOUT[7] ^ xor; - NdisMoveMemory(&R[8 * i], &BOUT[8], 8); - } - } - - // Output ciphertext - NdisMoveMemory(ciphertext, A, 8); - - for (i = 1; i <= num_blocks; i++) - { - for (j = 0 ; j < 8; j++) - ciphertext[8 * i + j] = R[8 * i + j]; - } + u8 A[8], BIN[16], BOUT[16]; + u8 R[512]; + int num_blocks = p_len / 8; /* unit:64bits */ + int i, j; + struct aes_context aesctx; + u8 xor; + + rt_aes_set_key(&aesctx, key, 128); + + /* Init IA */ + for (i = 0; i < 8; i++) + A[i] = 0xa6; + + /*Input plaintext */ + for (i = 0; i < num_blocks; i++) { + for (j = 0; j < 8; j++) + R[8 * (i + 1) + j] = plaintext[8 * i + j]; + } + + /* Key Mix */ + for (j = 0; j < 6; j++) { + for (i = 1; i <= num_blocks; i++) { + /*phase 1 */ + NdisMoveMemory(BIN, A, 8); + NdisMoveMemory(&BIN[8], &R[8 * i], 8); + rt_aes_encrypt(&aesctx, BIN, BOUT); + + NdisMoveMemory(A, &BOUT[0], 8); + xor = num_blocks * j + i; + A[7] = BOUT[7] ^ xor; + NdisMoveMemory(&R[8 * i], &BOUT[8], 8); + } + } + + /* Output ciphertext */ + NdisMoveMemory(ciphertext, A, 8); + + for (i = 1; i <= num_blocks; i++) { + for (j = 0; j < 8; j++) + ciphertext[8 * i + j] = R[8 * i + j]; + } } /* @@ -1352,209 +1264,50 @@ VOID AES_GTK_KEY_WRAP( ======================================================================== */ -VOID AES_GTK_KEY_UNWRAP( - IN UCHAR *key, - OUT UCHAR *plaintext, - IN UINT32 c_len, - IN UCHAR *ciphertext) - +void AES_GTK_KEY_UNWRAP(u8 * key, + u8 * plaintext, + u32 c_len, u8 * ciphertext) { - UCHAR A[8], BIN[16], BOUT[16]; - UCHAR xor; - INT i, j; - aes_context aesctx; - UCHAR *R; - INT num_blocks = c_len/8; // unit:64bits - - - os_alloc_mem(NULL, (PUCHAR *)&R, 512); - - if (R == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n")); - return; - } /* End of if */ - - // Initialize + u8 A[8], BIN[16], BOUT[16]; + u8 xor; + int i, j; + struct aes_context aesctx; + u8 *R; + int num_blocks = c_len / 8; /* unit:64bits */ + + os_alloc_mem(NULL, (u8 **) & R, 512); + + if (R == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("AES_GTK_KEY_UNWRAP: no memory!\n")); + return; + } + /* End of if */ + /* Initialize */ NdisMoveMemory(A, ciphertext, 8); - //Input plaintext - for(i = 0; i < (c_len-8); i++) - { - R[ i] = ciphertext[i + 8]; + /*Input plaintext */ + for (i = 0; i < (c_len - 8); i++) { + R[i] = ciphertext[i + 8]; } rt_aes_set_key(&aesctx, key, 128); - for(j = 5; j >= 0; j--) - { - for(i = (num_blocks-1); i > 0; i--) - { - xor = (num_blocks -1 )* j + i; + for (j = 5; j >= 0; j--) { + for (i = (num_blocks - 1); i > 0; i--) { + xor = (num_blocks - 1) * j + i; NdisMoveMemory(BIN, A, 8); BIN[7] = A[7] ^ xor; - NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8); + NdisMoveMemory(&BIN[8], &R[(i - 1) * 8], 8); rt_aes_decrypt(&aesctx, BIN, BOUT); NdisMoveMemory(A, &BOUT[0], 8); - NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8); + NdisMoveMemory(&R[(i - 1) * 8], &BOUT[8], 8); } } - // OUTPUT - for(i = 0; i < c_len; i++) - { + /* OUTPUT */ + for (i = 0; i < c_len; i++) { plaintext[i] = R[i]; } - os_free_mem(NULL, R); } - - -/* ======= The related function of AES-128-CMAC ======= */ -VOID leftshift_onebit( - IN PUCHAR input, - OUT PUCHAR output) -{ - INT i; - UCHAR overflow = 0; - - for (i=15; i>=0; i--) - { - output[i] = input[i] << 1; - output[i] |= overflow; - overflow = (input[i] & 0x80) ? 1 : 0; - } -} - -VOID do_padding( - IN PUCHAR lastb, - OUT PUCHAR pad, - IN INT len) -{ - INT j; - - for (j=0; j<16; j++) - { - if (j < len) - pad[j] = lastb[j]; - else if (j == len) - pad[j] = 0x80; - else - pad[j] = 0x00; - } - - -} - -/* - * The Subkey Generation Algorithm - */ -VOID generate_subkey( - IN PUCHAR key, - OUT PUCHAR K1, - OUT PUCHAR K2) -{ - aes_context aesctx; - UCHAR aes_128_key[16]; - UCHAR const_Zero[16]; - UCHAR tmp[16]; - UCHAR const_Rb[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87}; - - // initial the key material - memset(const_Zero, 0, 16); - memset(aes_128_key, 0, 16); - - // AES-128 with key is applied to an all-zero input block - rt_aes_set_key(&aesctx, key, 128); - rt_aes_encrypt(&aesctx, const_Zero, aes_128_key); - - // derive K1(128-bit first subkey) and K2(128-bit second subkey), refer to rfc-4493 ch 2.3 - if ((aes_128_key[0] & 0x80) == 0) - { - leftshift_onebit(aes_128_key, K1); - } - else - { - leftshift_onebit(aes_128_key, tmp); - xor_128(tmp, const_Rb, K1); - } - - if ((K1[0] & 0x80) == 0) - { - leftshift_onebit(K1, K2); - } - else - { - leftshift_onebit(K1, tmp); - xor_128(tmp, const_Rb, K2); - } - -} - -/* - * AES-CMAC Algorithm. (refer to rfc-4493 and SP800-38B) - * - * Input : key (128-bit key) - * input (message to be authenticated) - * len (length of the message in octets) - * - * output: mac (message authentication code) - */ -VOID AES_128_CMAC( - IN PUCHAR key, - IN PUCHAR input, - IN INT len, - OUT PUCHAR mac) -{ - UCHAR X[16], Y[16], M_last[16], padded[16]; - UCHAR K1[16], K2[16]; - aes_context aesctx; - INT n, i, flag; - - generate_subkey(key, K1, K2); - - n = (len+15) / 16; // n is number of rounds - - if (n == 0) - { - n = 1; - flag = 0; - } - else - { - if ((len%16) == 0) - flag = 1; // indicate that last block is a complete block - else - flag = 0; // indicate that last block is not a complete block - } - - if (flag) - { - xor_128(&input[16*(n-1)], K1, M_last); - } - else - { - do_padding(&input[16*(n-1)], padded, len%16); - xor_128(padded, K2, M_last); - } - - memset(X, 0, 16); - for (i=0; i5. */ + + /* 802.11 HyperLan 2 */ + {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783} + , + + /* 2008.04.30 modified */ + /* The system team has AN to improve the EVM value */ + /* for channel 102 to 108 for the RT2850/RT2750 dual band solution. */ + {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793} + , + {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3} + , + {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193} + , + + {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183} + , + {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b} + , + {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3} + , + {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193} + , + {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183} + , + {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193} + , + {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b} + , /* 0x980ed1bb->0x980ed15b required by Rory 20070927 */ + {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3} + , + {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b} + , + {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193} + , + {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b} + , + {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183} + , + + /* 802.11 UNII */ + {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7} + , + {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187} + , + {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f} + , + {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f} + , + {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7} + , + {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187} + , + {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197} + , + {167, 0x98402ec4, 0x984c03d2, 0x98179855, 0x9815531f} + , + {169, 0x98402ec4, 0x984c03d2, 0x98179855, 0x98155327} + , + {171, 0x98402ec4, 0x984c03d6, 0x98179855, 0x98155307} + , + {173, 0x98402ec4, 0x984c03d6, 0x98179855, 0x9815530f} + , + + /* Japan */ + {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b} + , + {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13} + , + {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b} + , + {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23} + , + {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13} + , + {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b} + , + {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23} + , + + /* still lack of MMAC(Japan) ch 34,38,42,46 */ +}; + +u8 NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(struct rt_rtmp_rf_regs)); + +struct rt_frequency_item FreqItems3020[] = { + /**************************************************/ + /* ISM : 2.4 to 2.483 GHz // */ + /**************************************************/ + /* 11g */ + /**************************************************/ + /*-CH---N-------R---K----------- */ + {1, 241, 2, 2} + , + {2, 241, 2, 7} + , + {3, 242, 2, 2} + , + {4, 242, 2, 7} + , + {5, 243, 2, 2} + , + {6, 243, 2, 7} + , + {7, 244, 2, 2} + , + {8, 244, 2, 7} + , + {9, 245, 2, 2} + , + {10, 245, 2, 7} + , + {11, 246, 2, 2} + , + {12, 246, 2, 7} + , + {13, 247, 2, 2} + , + {14, 248, 2, 4} + , +}; + +u8 NUM_OF_3020_CHNL = (sizeof(FreqItems3020) / sizeof(struct rt_frequency_item)); + +void AsicUpdateAutoFallBackTable(struct rt_rtmp_adapter *pAd, u8 *pRateTable) +{ + u8 i; + HT_FBK_CFG0_STRUC HtCfg0; + HT_FBK_CFG1_STRUC HtCfg1; + LG_FBK_CFG0_STRUC LgCfg0; + LG_FBK_CFG1_STRUC LgCfg1; + struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate; + + /* set to initial value */ + HtCfg0.word = 0x65432100; + HtCfg1.word = 0xedcba988; + LgCfg0.word = 0xedcba988; + LgCfg1.word = 0x00002100; + + pNextTxRate = (struct rt_rtmp_tx_rate_switch *) pRateTable + 1; + for (i = 1; i < *((u8 *)pRateTable); i++) { + pCurrTxRate = (struct rt_rtmp_tx_rate_switch *) pRateTable + 1 + i; + switch (pCurrTxRate->Mode) { + case 0: /*CCK */ + break; + case 1: /*OFDM */ + { + switch (pCurrTxRate->CurrMCS) { + case 0: + LgCfg0.field.OFDMMCS0FBK = + (pNextTxRate->Mode == + MODE_OFDM) ? (pNextTxRate-> + CurrMCS + + 8) : pNextTxRate-> + CurrMCS; + break; + case 1: + LgCfg0.field.OFDMMCS1FBK = + (pNextTxRate->Mode == + MODE_OFDM) ? (pNextTxRate-> + CurrMCS + + 8) : pNextTxRate-> + CurrMCS; + break; + case 2: + LgCfg0.field.OFDMMCS2FBK = + (pNextTxRate->Mode == + MODE_OFDM) ? (pNextTxRate-> + CurrMCS + + 8) : pNextTxRate-> + CurrMCS; + break; + case 3: + LgCfg0.field.OFDMMCS3FBK = + (pNextTxRate->Mode == + MODE_OFDM) ? (pNextTxRate-> + CurrMCS + + 8) : pNextTxRate-> + CurrMCS; + break; + case 4: + LgCfg0.field.OFDMMCS4FBK = + (pNextTxRate->Mode == + MODE_OFDM) ? (pNextTxRate-> + CurrMCS + + 8) : pNextTxRate-> + CurrMCS; + break; + case 5: + LgCfg0.field.OFDMMCS5FBK = + (pNextTxRate->Mode == + MODE_OFDM) ? (pNextTxRate-> + CurrMCS + + 8) : pNextTxRate-> + CurrMCS; + break; + case 6: + LgCfg0.field.OFDMMCS6FBK = + (pNextTxRate->Mode == + MODE_OFDM) ? (pNextTxRate-> + CurrMCS + + 8) : pNextTxRate-> + CurrMCS; + break; + case 7: + LgCfg0.field.OFDMMCS7FBK = + (pNextTxRate->Mode == + MODE_OFDM) ? (pNextTxRate-> + CurrMCS + + 8) : pNextTxRate-> + CurrMCS; + break; + } + } + break; + case 2: /*HT-MIX */ + case 3: /*HT-GF */ + { + if ((pNextTxRate->Mode >= MODE_HTMIX) + && (pCurrTxRate->CurrMCS != + pNextTxRate->CurrMCS)) { + switch (pCurrTxRate->CurrMCS) { + case 0: + HtCfg0.field.HTMCS0FBK = + pNextTxRate->CurrMCS; + break; + case 1: + HtCfg0.field.HTMCS1FBK = + pNextTxRate->CurrMCS; + break; + case 2: + HtCfg0.field.HTMCS2FBK = + pNextTxRate->CurrMCS; + break; + case 3: + HtCfg0.field.HTMCS3FBK = + pNextTxRate->CurrMCS; + break; + case 4: + HtCfg0.field.HTMCS4FBK = + pNextTxRate->CurrMCS; + break; + case 5: + HtCfg0.field.HTMCS5FBK = + pNextTxRate->CurrMCS; + break; + case 6: + HtCfg0.field.HTMCS6FBK = + pNextTxRate->CurrMCS; + break; + case 7: + HtCfg0.field.HTMCS7FBK = + pNextTxRate->CurrMCS; + break; + case 8: + HtCfg1.field.HTMCS8FBK = + pNextTxRate->CurrMCS; + break; + case 9: + HtCfg1.field.HTMCS9FBK = + pNextTxRate->CurrMCS; + break; + case 10: + HtCfg1.field.HTMCS10FBK = + pNextTxRate->CurrMCS; + break; + case 11: + HtCfg1.field.HTMCS11FBK = + pNextTxRate->CurrMCS; + break; + case 12: + HtCfg1.field.HTMCS12FBK = + pNextTxRate->CurrMCS; + break; + case 13: + HtCfg1.field.HTMCS13FBK = + pNextTxRate->CurrMCS; + break; + case 14: + HtCfg1.field.HTMCS14FBK = + pNextTxRate->CurrMCS; + break; + case 15: + HtCfg1.field.HTMCS15FBK = + pNextTxRate->CurrMCS; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, + ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", + pCurrTxRate-> + CurrMCS)); + } + } + } + break; + } + + pNextTxRate = pCurrTxRate; + } + + RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word); + RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word); + RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word); + RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word); +} + +/* + ======================================================================== + + Routine Description: + Set MAC register value according operation mode. + OperationMode AND bNonGFExist are for MM and GF Proteciton. + If MM or GF mask is not set, those passing argument doesn't not take effect. + + Operation mode meaning: + = 0 : Pure HT, no preotection. + = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS. + = 0x10: No Transmission in 40M is protected. + = 0x11: Transmission in both 40M and 20M shall be protected + if (bNonGFExist) + we should choose not to use GF. But still set correct ASIC registers. + ======================================================================== +*/ +void AsicUpdateProtect(struct rt_rtmp_adapter *pAd, + u16 OperationMode, + u8 SetMask, + IN BOOLEAN bDisableBGProtect, IN BOOLEAN bNonGFExist) +{ + PROT_CFG_STRUC ProtCfg, ProtCfg4; + u32 Protect[6]; + u16 offset; + u8 i; + u32 MacReg = 0; + + if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8)) { + return; + } + + if (pAd->BATable.numDoneOriginator) { + /* */ + /* enable the RTS/CTS to avoid channel collision */ + /* */ + SetMask = ALLN_SETPROTECT; + OperationMode = 8; + } + /* Config ASIC RTS threshold register */ + RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); + MacReg &= 0xFF0000FF; + /* If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096 */ + if (((pAd->CommonCfg.BACapability.field.AmsduEnable) || + (pAd->CommonCfg.bAggregationCapable == TRUE)) + && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD) { + MacReg |= (0x1000 << 8); + } else { + MacReg |= (pAd->CommonCfg.RtsThreshold << 8); + } + + RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); + + /* Initial common protection settings */ + RTMPZeroMemory(Protect, sizeof(Protect)); + ProtCfg4.word = 0; + ProtCfg.word = 0; + ProtCfg.field.TxopAllowGF40 = 1; + ProtCfg.field.TxopAllowGF20 = 1; + ProtCfg.field.TxopAllowMM40 = 1; + ProtCfg.field.TxopAllowMM20 = 1; + ProtCfg.field.TxopAllowOfdm = 1; + ProtCfg.field.TxopAllowCck = 1; + ProtCfg.field.RTSThEn = 1; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + + /* update PHY mode and rate */ + if (pAd->CommonCfg.Channel > 14) + ProtCfg.field.ProtectRate = 0x4000; + ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate; + + /* Handle legacy(B/G) protection */ + if (bDisableBGProtect) { + /*ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; */ + ProtCfg.field.ProtectCtrl = 0; + Protect[0] = ProtCfg.word; + Protect[1] = ProtCfg.word; + pAd->FlgCtsEnabled = 0; /* CTS-self is not used */ + } else { + /*ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; */ + ProtCfg.field.ProtectCtrl = 0; /* CCK do not need to be protected */ + Protect[0] = ProtCfg.word; + ProtCfg.field.ProtectCtrl = ASIC_CTS; /* OFDM needs using CCK to protect */ + Protect[1] = ProtCfg.word; + pAd->FlgCtsEnabled = 1; /* CTS-self is used */ + } + + /* Decide HT frame protection. */ + if ((SetMask & ALLN_SETPROTECT) != 0) { + switch (OperationMode) { + case 0x0: + /* NO PROTECT */ + /* 1.All STAs in the BSS are 20/40 MHz HT */ + /* 2. in ai 20/40MHz BSS */ + /* 3. all STAs are 20MHz in a 20MHz BSS */ + /* Pure HT. no protection. */ + + /* MM20_PROT_CFG */ + /* Reserved (31:27) */ + /* PROT_TXOP(25:20) -- 010111 */ + /* PROT_NAV(19:18) -- 01 (Short NAV protection) */ + /* PROT_CTRL(17:16) -- 00 (None) */ + /* PROT_RATE(15:0) -- 0x4004 (OFDM 24M) */ + Protect[2] = 0x01744004; + + /* MM40_PROT_CFG */ + /* Reserved (31:27) */ + /* PROT_TXOP(25:20) -- 111111 */ + /* PROT_NAV(19:18) -- 01 (Short NAV protection) */ + /* PROT_CTRL(17:16) -- 00 (None) */ + /* PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) */ + Protect[3] = 0x03f44084; + + /* CF20_PROT_CFG */ + /* Reserved (31:27) */ + /* PROT_TXOP(25:20) -- 010111 */ + /* PROT_NAV(19:18) -- 01 (Short NAV protection) */ + /* PROT_CTRL(17:16) -- 00 (None) */ + /* PROT_RATE(15:0) -- 0x4004 (OFDM 24M) */ + Protect[4] = 0x01744004; + + /* CF40_PROT_CFG */ + /* Reserved (31:27) */ + /* PROT_TXOP(25:20) -- 111111 */ + /* PROT_NAV(19:18) -- 01 (Short NAV protection) */ + /* PROT_CTRL(17:16) -- 00 (None) */ + /* PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) */ + Protect[5] = 0x03f44084; + + if (bNonGFExist) { + /* PROT_NAV(19:18) -- 01 (Short NAV protectiion) */ + /* PROT_CTRL(17:16) -- 01 (RTS/CTS) */ + Protect[4] = 0x01754004; + Protect[5] = 0x03f54084; + } + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + break; + + case 1: + /* This is "HT non-member protection mode." */ + /* If there may be non-HT STAs my BSS */ + ProtCfg.word = 0x01744004; /* PROT_CTRL(17:16) : 0 (None) */ + ProtCfg4.word = 0x03f44084; /* duplicaet legacy 24M. BW set 1. */ + if (OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_BG_PROTECTION_INUSED)) { + ProtCfg.word = 0x01740003; /*ERP use Protection bit is set, use protection rate at Clause 18.. */ + ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083; */ + } + /*Assign Protection method for 20&40 MHz packets */ + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[2] = ProtCfg.word; + Protect[3] = ProtCfg4.word; + Protect[4] = ProtCfg.word; + Protect[5] = ProtCfg4.word; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + break; + + case 2: + /* If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets */ + ProtCfg.word = 0x01744004; /* PROT_CTRL(17:16) : 0 (None) */ + ProtCfg4.word = 0x03f44084; /* duplicaet legacy 24M. BW set 1. */ + + /*Assign Protection method for 40MHz packets */ + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[2] = ProtCfg.word; + Protect[3] = ProtCfg4.word; + if (bNonGFExist) { + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + } + Protect[4] = ProtCfg.word; + Protect[5] = ProtCfg4.word; + + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + break; + + case 3: + /* HT mixed mode. PROTECT ALL! */ + /* Assign Rate */ + ProtCfg.word = 0x01744004; /*duplicaet legacy 24M. BW set 1. */ + ProtCfg4.word = 0x03f44084; + /* both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the */ + if (OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_BG_PROTECTION_INUSED)) { + ProtCfg.word = 0x01740003; /*ERP use Protection bit is set, use protection rate at Clause 18.. */ + ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083 */ + } + /*Assign Protection method for 20&40 MHz packets */ + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[2] = ProtCfg.word; + Protect[3] = ProtCfg4.word; + Protect[4] = ProtCfg.word; + Protect[5] = ProtCfg4.word; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + break; + + case 8: + /* Special on for Atheros problem n chip. */ + Protect[2] = 0x01754004; + Protect[3] = 0x03f54084; + Protect[4] = 0x01754004; + Protect[5] = 0x03f54084; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + break; + } + } + + offset = CCK_PROT_CFG; + for (i = 0; i < 6; i++) { + if ((SetMask & (1 << i))) { + RTMP_IO_WRITE32(pAd, offset + i * 4, Protect[i]); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +void AsicSwitchChannel(struct rt_rtmp_adapter *pAd, u8 Channel, IN BOOLEAN bScan) +{ + unsigned long R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0; + char TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; /*Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER; */ + u8 index; + u32 Value = 0; /*BbpReg, Value; */ + struct rt_rtmp_rf_regs *RFRegTable; + u8 RFValue; + + RFValue = 0; + /* Search Tx power value */ + /* We can't use ChannelList to search channel, since some central channl's txpowr doesn't list */ + /* in ChannelList, so use TxPower array instead. */ + /* */ + for (index = 0; index < MAX_NUM_OF_CHANNELS; index++) { + if (Channel == pAd->TxPower[index].Channel) { + TxPwer = pAd->TxPower[index].Power; + TxPwer2 = pAd->TxPower[index].Power2; + break; + } + } + + if (index == MAX_NUM_OF_CHANNELS) { + DBGPRINT(RT_DEBUG_ERROR, + ("AsicSwitchChannel: Can't find the Channel#%d \n", + Channel)); + } +#ifdef RT30xx + /* The RF programming sequence is difference between 3xxx and 2xxx */ + if ((IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3390(pAd)) + && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) + || (pAd->RfIcType == RFIC_3021) + || (pAd->RfIcType == RFIC_3022))) { + /* modify by WY for Read RF Reg. error */ + + for (index = 0; index < NUM_OF_3020_CHNL; index++) { + if (Channel == FreqItems3020[index].Channel) { + /* Programming channel parameters */ + RT30xxWriteRFRegister(pAd, RF_R02, + FreqItems3020[index].N); + RT30xxWriteRFRegister(pAd, RF_R03, + FreqItems3020[index].K); + RT30xxReadRFRegister(pAd, RF_R06, &RFValue); + RFValue = + (RFValue & 0xFC) | FreqItems3020[index].R; + RT30xxWriteRFRegister(pAd, RF_R06, RFValue); + + /* Set Tx0 Power */ + RT30xxReadRFRegister(pAd, RF_R12, &RFValue); + RFValue = (RFValue & 0xE0) | TxPwer; + RT30xxWriteRFRegister(pAd, RF_R12, RFValue); + + /* Set Tx1 Power */ + RT30xxReadRFRegister(pAd, RF_R13, &RFValue); + RFValue = (RFValue & 0xE0) | TxPwer2; + RT30xxWriteRFRegister(pAd, RF_R13, RFValue); + + /* Tx/Rx Stream setting */ + RT30xxReadRFRegister(pAd, RF_R01, &RFValue); + /*if (IS_RT3090(pAd)) */ + /* RFValue |= 0x01; // Enable RF block. */ + RFValue &= 0x03; /*clear bit[7~2] */ + if (pAd->Antenna.field.TxPath == 1) + RFValue |= 0xA0; + else if (pAd->Antenna.field.TxPath == 2) + RFValue |= 0x80; + if (pAd->Antenna.field.RxPath == 1) + RFValue |= 0x50; + else if (pAd->Antenna.field.RxPath == 2) + RFValue |= 0x40; + RT30xxWriteRFRegister(pAd, RF_R01, RFValue); + + /* Set RF offset */ + RT30xxReadRFRegister(pAd, RF_R23, &RFValue); + RFValue = (RFValue & 0x80) | pAd->RfFreqOffset; + RT30xxWriteRFRegister(pAd, RF_R23, RFValue); + + /* Set BW */ + if (!bScan + && (pAd->CommonCfg.BBPCurrentBW == BW_40)) { + RFValue = pAd->Mlme.CaliBW40RfR24; + /*DISABLE_11N_CHECK(pAd); */ + } else { + RFValue = pAd->Mlme.CaliBW20RfR24; + } + RT30xxWriteRFRegister(pAd, RF_R24, RFValue); + RT30xxWriteRFRegister(pAd, RF_R31, RFValue); + + /* Enable RF tuning */ + RT30xxReadRFRegister(pAd, RF_R07, &RFValue); + RFValue = RFValue | 0x1; + RT30xxWriteRFRegister(pAd, RF_R07, RFValue); + + /* latch channel for future usage. */ + pAd->LatchRfRegs.Channel = Channel; + + DBGPRINT(RT_DEBUG_TRACE, + ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, pAd->RfIcType, TxPwer, + TxPwer2, pAd->Antenna.field.TxPath, + FreqItems3020[index].N, + FreqItems3020[index].K, + FreqItems3020[index].R)); + + break; + } + } + } else +#endif /* RT30xx // */ + { + RFRegTable = RF2850RegTable; + switch (pAd->RfIcType) { + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: + + for (index = 0; index < NUM_OF_2850_CHNL; index++) { + if (Channel == RFRegTable[index].Channel) { + R2 = RFRegTable[index].R2; + if (pAd->Antenna.field.TxPath == 1) { + R2 |= 0x4000; /* If TXpath is 1, bit 14 = 1; */ + } + + if (pAd->Antenna.field.RxPath == 2) { + R2 |= 0x40; /* write 1 to off Rxpath. */ + } else if (pAd->Antenna.field.RxPath == + 1) { + R2 |= 0x20040; /* write 1 to off RxPath */ + } + + if (Channel > 14) { + /* initialize R3, R4 */ + R3 = (RFRegTable[index]. + R3 & 0xffffc1ff); + R4 = (RFRegTable[index]. + R4 & (~0x001f87c0)) | + (pAd->RfFreqOffset << 15); + + /* 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB */ + /* R3 */ + if ((TxPwer >= -7) + && (TxPwer < 0)) { + TxPwer = (7 + TxPwer); + TxPwer = + (TxPwer > + 0xF) ? (0xF) + : (TxPwer); + R3 |= (TxPwer << 10); + DBGPRINT(RT_DEBUG_ERROR, + ("AsicSwitchChannel: TxPwer=%d \n", + TxPwer)); + } else { + TxPwer = + (TxPwer > + 0xF) ? (0xF) + : (TxPwer); + R3 |= + (TxPwer << 10) | (1 + << + 9); + } + + /* R4 */ + if ((TxPwer2 >= -7) + && (TxPwer2 < 0)) { + TxPwer2 = (7 + TxPwer2); + TxPwer2 = + (TxPwer2 > + 0xF) ? (0xF) + : (TxPwer2); + R4 |= (TxPwer2 << 7); + DBGPRINT(RT_DEBUG_ERROR, + ("AsicSwitchChannel: TxPwer2=%d \n", + TxPwer2)); + } else { + TxPwer2 = + (TxPwer2 > + 0xF) ? (0xF) + : (TxPwer2); + R4 |= + (TxPwer2 << 7) | (1 + << + 6); + } + } else { + R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); /* set TX power0 */ + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 << 6); /* Set freq Offset & TxPwr1 */ + } + + /* Based on BBP current mode before changing RF channel. */ + if (!bScan + && (pAd->CommonCfg.BBPCurrentBW == + BW_40)) { + R4 |= 0x200000; + } + /* Update variables */ + pAd->LatchRfRegs.Channel = Channel; + pAd->LatchRfRegs.R1 = + RFRegTable[index].R1; + pAd->LatchRfRegs.R2 = R2; + pAd->LatchRfRegs.R3 = R3; + pAd->LatchRfRegs.R4 = R4; + + /* Set RF value 1's set R3[bit2] = [0] */ + RTMP_RF_IO_WRITE32(pAd, + pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, + pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, + (pAd->LatchRfRegs. + R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, + pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + /* Set RF value 2's set R3[bit2] = [1] */ + RTMP_RF_IO_WRITE32(pAd, + pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, + pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, + (pAd->LatchRfRegs. + R3 | 0x04)); + RTMP_RF_IO_WRITE32(pAd, + pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + /* Set RF value 3's set R3[bit2] = [0] */ + RTMP_RF_IO_WRITE32(pAd, + pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, + pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, + (pAd->LatchRfRegs. + R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, + pAd->LatchRfRegs.R4); + + break; + } + } + break; + + default: + break; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", + Channel, pAd->RfIcType, (R3 & 0x00003e00) >> 9, + (R4 & 0x000007c0) >> 6, pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, pAd->LatchRfRegs.R4)); + } + + /* Change BBP setting during siwtch from a->g, g->a */ + if (Channel <= 14) { + unsigned long TxPinCfg = 0x00050F0A; /*Gary 2007/08/09 0x050A0A */ + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, + (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, + (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, + (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); /*(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. */ + /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); */ + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForG) { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } else { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + /* 5G band selection PIN, bit1 and bit2 are complement */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* Turn off unused PA or LNA when only 1T or 1R */ + if (pAd->Antenna.field.TxPath == 1) { + TxPinCfg &= 0xFFFFFFF3; + } + if (pAd->Antenna.field.RxPath == 1) { + TxPinCfg &= 0xFFFFF3FF; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + +#if defined(RT3090) || defined(RT3390) + /* PCIe PHY Transmit attenuation adjustment */ + if (IS_RT3090A(pAd) || IS_RT3390(pAd)) { + TX_ATTENUATION_CTRL_STRUC TxAttenuationCtrl = { + .word = 0}; + + RTMP_IO_READ32(pAd, PCIE_PHY_TX_ATTENUATION_CTRL, + &TxAttenuationCtrl.word); + + if (Channel == 14) /* Channel #14 */ + { + TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_EN = 1; /* Enable PCIe PHY Tx attenuation */ + TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_VALUE = 4; /* 9/16 full drive level */ + } else /* Channel #1~#13 */ + { + TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_EN = 0; /* Disable PCIe PHY Tx attenuation */ + TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_VALUE = 0; /* n/a */ + } + + RTMP_IO_WRITE32(pAd, PCIE_PHY_TX_ATTENUATION_CTRL, + TxAttenuationCtrl.word); + } +#endif + } else { + unsigned long TxPinCfg = 0x00050F05; /*Gary 2007/8/9 0x050505 */ + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, + (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, + (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, + (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); /*(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForA) { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } else { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + /* 5G band selection PIN, bit1 and bit2 are complement */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* Turn off unused PA or LNA when only 1T or 1R */ + if (pAd->Antenna.field.TxPath == 1) { + TxPinCfg &= 0xFFFFFFF3; + } + if (pAd->Antenna.field.RxPath == 1) { + TxPinCfg &= 0xFFFFF3FF; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + + } + + /* R66 should be set according to Channel and use 20MHz when scanning */ + /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd))); */ + if (bScan) + RTMPSetAGCInitValue(pAd, BW_20); + else + RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); + + /* */ + /* On 11A, We should delay and wait RF/BBP to be stable */ + /* and the appropriate time should be 1000 micro seconds */ + /* 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL. */ + /* */ + RTMPusecDelay(1000); +} + +void AsicResetBBPAgent(struct rt_rtmp_adapter *pAd) +{ + BBP_CSR_CFG_STRUC BbpCsr; + DBGPRINT(RT_DEBUG_ERROR, ("Reset BBP Agent busy bit!\n")); + /* Still need to find why BBP agent keeps busy, but in fact, hardware still function ok. Now clear busy first. */ + RTMP_IO_READ32(pAd, H2M_BBP_AGENT, &BbpCsr.word); + BbpCsr.field.Busy = 0; + RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, BbpCsr.word); +} + +/* + ========================================================================== + Description: + This function is required for 2421 only, and should not be used during + site survey. It's only required after NIC decided to stay at a channel + for a longer period. + When this function is called, it's always after AsicSwitchChannel(). + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +void AsicLockChannel(struct rt_rtmp_adapter *pAd, u8 Channel) +{ +} + +void AsicRfTuningExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) +{ +} + +/* + ========================================================================== + Description: + Gives CCK TX rate 2 more dB TX power. + This routine works only in LINK UP in INFRASTRUCTURE mode. + + calculate desired Tx power in RF R3.Tx0~5, should consider - + 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) + 1. TxPowerPercentage + 2. auto calibration based on TSSI feedback + 3. extra 2 db for CCK + 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP + + NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), + it should be called AFTER MlmeDynamicTxRatSwitching() + ========================================================================== + */ +void AsicAdjustTxPower(struct rt_rtmp_adapter *pAd) +{ + int i, j; + char DeltaPwr = 0; + BOOLEAN bAutoTxAgc = FALSE; + u8 TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; + u8 BbpR1 = 0, BbpR49 = 0, idx; + char *pTxAgcCompensate; + unsigned long TxPwr[5]; + char Value; + char Rssi = -127; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) || +#ifdef RTMP_MAC_PCI + (pAd->bPCIclkOff == TRUE) || +#endif /* RTMP_MAC_PCI // */ + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + return; + + Rssi = RTMPMaxRssi(pAd, + pAd->StaCfg.RssiSample.AvgRssi0, + pAd->StaCfg.RssiSample.AvgRssi1, + pAd->StaCfg.RssiSample.AvgRssi2); + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) { + if (pAd->CommonCfg.CentralChannel > 14) { + TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; + } else { + TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; + } + } else { + if (pAd->CommonCfg.Channel > 14) { + TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; + } else { + TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; + } + } + + /* TX power compensation for temperature variation based on TSSI. try every 4 second */ + if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) { + if (pAd->CommonCfg.Channel <= 14) { + /* bg channel */ + bAutoTxAgc = pAd->bAutoTxAgcG; + TssiRef = pAd->TssiRefG; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; + TxAgcStep = pAd->TxAgcStepG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } else { + /* a channel */ + bAutoTxAgc = pAd->bAutoTxAgcA; + TssiRef = pAd->TssiRefA; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; + TxAgcStep = pAd->TxAgcStepA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) { + /* BbpR1 is unsigned char */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + + /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ + /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ + /* step value is defined in pAd->TxAgcStepG for tx power value */ + + /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ + /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 + above value are examined in mass factory production */ + /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ + + /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */ + /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ + /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */ + + if (BbpR49 > pTssiMinusBoundary[1]) { + /* Reading is larger than the reference value */ + /* check for how large we need to decrease the Tx power */ + for (idx = 1; idx < 5; idx++) { + if (BbpR49 <= pTssiMinusBoundary[idx]) /* Found the range */ + break; + } + /* The index is the step we should decrease, idx = 0 means there is nothing to compensate */ +/* if (R3 > (unsigned long)(TxAgcStep * (idx-1))) */ + *pTxAgcCompensate = -(TxAgcStep * (idx - 1)); +/* else */ +/* *pTxAgcCompensate = -((u8)R3); */ + + DeltaPwr += (*pTxAgcCompensate); + DBGPRINT(RT_DEBUG_TRACE, + ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", + BbpR49, TssiRef, TxAgcStep, idx - 1)); + } else if (BbpR49 < pTssiPlusBoundary[1]) { + /* Reading is smaller than the reference value */ + /* check for how large we need to increase the Tx power */ + for (idx = 1; idx < 5; idx++) { + if (BbpR49 >= pTssiPlusBoundary[idx]) /* Found the range */ + break; + } + /* The index is the step we should increase, idx = 0 means there is nothing to compensate */ + *pTxAgcCompensate = TxAgcStep * (idx - 1); + DeltaPwr += (*pTxAgcCompensate); + DBGPRINT(RT_DEBUG_TRACE, + ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, idx - 1)); + } else { + *pTxAgcCompensate = 0; + DBGPRINT(RT_DEBUG_TRACE, + (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, 0)); + } + } + } else { + if (pAd->CommonCfg.Channel <= 14) { + bAutoTxAgc = pAd->bAutoTxAgcG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } else { + bAutoTxAgc = pAd->bAutoTxAgcA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + DeltaPwr += (*pTxAgcCompensate); + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); + BbpR1 &= 0xFC; + + /* calculate delta power based on the percentage specified from UI */ + /* E2PROM setting is calibrated for maximum TX power (i.e. 100%) */ + /* We lower TX power here according to the percentage specified from UI */ + if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) /* AUTO TX POWER control */ + { + { + /* to patch high power issue with some APs, like Belkin N1. */ + if (Rssi > -35) { + BbpR1 |= 0x02; /* DeltaPwr -= 12; */ + } else if (Rssi > -40) { + BbpR1 |= 0x01; /* DeltaPwr -= 6; */ + } else; + } + } else if (pAd->CommonCfg.TxPowerPercentage > 90) /* 91 ~ 100% & AUTO, treat as 100% in terms of mW */ + ; + else if (pAd->CommonCfg.TxPowerPercentage > 60) /* 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1; */ + { + DeltaPwr -= 1; + } else if (pAd->CommonCfg.TxPowerPercentage > 30) /* 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3; */ + { + DeltaPwr -= 3; + } else if (pAd->CommonCfg.TxPowerPercentage > 15) /* 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6; */ + { + BbpR1 |= 0x01; + } else if (pAd->CommonCfg.TxPowerPercentage > 9) /* 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9; */ + { + BbpR1 |= 0x01; + DeltaPwr -= 3; + } else /* 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12; */ + { + BbpR1 |= 0x02; + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + + /* reset different new tx power for different TX rate */ + for (i = 0; i < 5; i++) { + if (TxPwr[i] != 0xffffffff) { + for (j = 0; j < 8; j++) { + Value = (char)((TxPwr[i] >> j * 4) & 0x0F); /* 0 ~ 15 */ + + if ((Value + DeltaPwr) < 0) { + Value = 0; /* min */ + } else if ((Value + DeltaPwr) > 0xF) { + Value = 0xF; /* max */ + } else { + Value += DeltaPwr; /* temperature compensation */ + } + + /* fill new value to CSR offset */ + TxPwr[i] = + (TxPwr[i] & ~(0x0000000F << j * 4)) | (Value + << j + * 4); + } + + /* write tx power value to CSR */ + /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M + TX power for OFDM 6M/9M + TX power for CCK5.5M/11M + TX power for CCK1M/2M */ + /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i * 4, TxPwr[i]); + } + } + +} + +/* + ========================================================================== + Description: + put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup + automatically. Instead, MCU will issue a TwakeUpInterrupt to host after + the wakeup timer timeout. Driver has to issue a separate command to wake + PHY up. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +void AsicSleepThenAutoWakeup(struct rt_rtmp_adapter *pAd, + u16 TbttNumToNextWakeUp) +{ + RTMP_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp); +} + +/* + ========================================================================== + Description: + AsicForceWakeup() is used whenever manual wakeup is required + AsicForceSleep() should only be used when not in INFRA BSS. When + in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead. + ========================================================================== + */ +void AsicForceSleep(struct rt_rtmp_adapter *pAd) +{ + +} + +/* + ========================================================================== + Description: + AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup) + expired. + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + ========================================================================== + */ +void AsicForceWakeup(struct rt_rtmp_adapter *pAd, IN BOOLEAN bFromTx) +{ + DBGPRINT(RT_DEBUG_INFO, ("--> AsicForceWakeup \n")); + RTMP_STA_FORCE_WAKEUP(pAd, bFromTx); +} + +/* + ========================================================================== + Description: + Set My BSSID + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +void AsicSetBssid(struct rt_rtmp_adapter *pAd, u8 *pBssid) +{ + unsigned long Addr4; + DBGPRINT(RT_DEBUG_TRACE, + ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n", pBssid[0], + pBssid[1], pBssid[2], pBssid[3], pBssid[4], pBssid[5])); + + Addr4 = (unsigned long)(pBssid[0]) | + (unsigned long)(pBssid[1] << 8) | + (unsigned long)(pBssid[2] << 16) | (unsigned long)(pBssid[3] << 24); + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); + + Addr4 = 0; + /* always one BSSID in STA mode */ + Addr4 = (unsigned long)(pBssid[4]) | (unsigned long)(pBssid[5] << 8); + + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); +} + +void AsicSetMcastWC(struct rt_rtmp_adapter *pAd) +{ + struct rt_mac_table_entry *pEntry = &pAd->MacTab.Content[MCAST_WCID]; + u16 offset; + + pEntry->Sst = SST_ASSOC; + pEntry->Aid = MCAST_WCID; /* Softap supports 1 BSSID and use WCID=0 as multicast Wcid index */ + pEntry->PsMode = PWR_ACTIVE; + pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate; + offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +void AsicDelWcidTab(struct rt_rtmp_adapter *pAd, u8 Wcid) +{ + unsigned long Addr0 = 0x0, Addr1 = 0x0; + unsigned long offset; + + DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n", Wcid)); + offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE; + RTMP_IO_WRITE32(pAd, offset, Addr0); + offset += 4; + RTMP_IO_WRITE32(pAd, offset, Addr1); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +void AsicEnableRDG(struct rt_rtmp_adapter *pAd) +{ + TX_LINK_CFG_STRUC TxLinkCfg; + u32 Data = 0; + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + TxLinkCfg.field.TxRDGEn = 1; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + Data |= 0x80; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); */ +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +void AsicDisableRDG(struct rt_rtmp_adapter *pAd) +{ + TX_LINK_CFG_STRUC TxLinkCfg; + u32 Data = 0; + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + TxLinkCfg.field.TxRDGEn = 0; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + + Data &= 0xFFFFFF00; + /*Data |= 0x20; */ +#ifndef WIFI_TEST + /*if ( pAd->CommonCfg.bEnableTxBurst ) */ + /* Data |= 0x60; // for performance issue not set the TXOP to 0 */ +#endif + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE) + && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE) + ) { + /* For CWC test, change txop from 0x30 to 0x20 in TxBurst mode */ + if (pAd->CommonCfg.bEnableTxBurst) + Data |= 0x20; + } + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +void AsicDisableSync(struct rt_rtmp_adapter *pAd) +{ + BCN_TIME_CFG_STRUC csr; + + DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n")); + + /* 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect */ + /* that NIC will never wakes up because TSF stops and no more */ + /* TBTT interrupts */ + pAd->TbttTickCount = 0; + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + csr.field.bBeaconGen = 0; + csr.field.bTBTTEnable = 0; + csr.field.TsfSyncMode = 0; + csr.field.bTsfTicking = 0; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +void AsicEnableBssSync(struct rt_rtmp_adapter *pAd) +{ + BCN_TIME_CFG_STRUC csr; + + DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n")); + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); +/* RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000); */ + { + csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; /* ASIC register in units of 1/16 TU */ + csr.field.bTsfTicking = 1; + csr.field.TsfSyncMode = 1; /* sync TSF in INFRASTRUCTURE mode */ + csr.field.bBeaconGen = 0; /* do NOT generate BEACON */ + csr.field.bTBTTEnable = 1; + } + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); +} + +/* + ========================================================================== + Description: + Note: + BEACON frame in shared memory should be built ok before this routine + can be called. Otherwise, a garbage frame maybe transmitted out every + Beacon period. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +void AsicEnableIbssSync(struct rt_rtmp_adapter *pAd) +{ + BCN_TIME_CFG_STRUC csr9; + u8 *ptr; + u32 i; + + DBGPRINT(RT_DEBUG_TRACE, + ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", + pAd->BeaconTxWI.MPDUtotalByteCount)); + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word); + csr9.field.bBeaconGen = 0; + csr9.field.bTBTTEnable = 0; + csr9.field.bTsfTicking = 0; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); + +#ifdef RTMP_MAC_PCI + /* move BEACON TXD and frame content to on-chip memory */ + ptr = (u8 *)& pAd->BeaconTxWI; + for (i = 0; i < TXWI_SIZE; i += 4) /* 16-byte TXWI field */ + { + u32 longptr = + *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + + (*(ptr + 3) << 24); + RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr); + ptr += 4; + } + + /* start right after the 16-byte TXWI field */ + ptr = pAd->BeaconBuf; + for (i = 0; i < pAd->BeaconTxWI.MPDUtotalByteCount; i += 4) { + u32 longptr = + *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + + (*(ptr + 3) << 24); + RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr); + ptr += 4; + } +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + /* move BEACON TXD and frame content to on-chip memory */ + ptr = (u8 *)& pAd->BeaconTxWI; + for (i = 0; i < TXWI_SIZE; i += 2) /* 16-byte TXWI field */ + { + /*u32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); */ + /*RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr); */ + RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2); + ptr += 2; + } + + /* start right after the 16-byte TXWI field */ + ptr = pAd->BeaconBuf; + for (i = 0; i < pAd->BeaconTxWI.MPDUtotalByteCount; i += 2) { + /*u32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); */ + /*RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr); */ + RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2); + ptr += 2; + } +#endif /* RTMP_MAC_USB // */ + + /* */ + /* For Wi-Fi faily generated beacons between participating stations. */ + /* Set TBTT phase adaptive adjustment step to 8us (default 16us) */ + /* don't change settings 2006-5- by Jerry */ + /*RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010); */ + + /* start sending BEACON */ + csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; /* ASIC register in units of 1/16 TU */ + csr9.field.bTsfTicking = 1; + csr9.field.TsfSyncMode = 2; /* sync TSF in IBSS mode */ + csr9.field.bTBTTEnable = 1; + csr9.field.bBeaconGen = 1; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +void AsicSetEdcaParm(struct rt_rtmp_adapter *pAd, struct rt_edca_parm *pEdcaParm) +{ + EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg; + AC_TXOP_CSR0_STRUC csr0; + AC_TXOP_CSR1_STRUC csr1; + AIFSN_CSR_STRUC AifsnCsr; + CWMIN_CSR_STRUC CwminCsr; + CWMAX_CSR_STRUC CwmaxCsr; + int i; + + Ac0Cfg.word = 0; + Ac1Cfg.word = 0; + Ac2Cfg.word = 0; + Ac3Cfg.word = 0; + if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE)) { + DBGPRINT(RT_DEBUG_TRACE, ("AsicSetEdcaParm\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED); + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) { + if (pAd->MacTab.Content[i].ValidAsCLI + || pAd->MacTab.Content[i].ValidAsApCli) + CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab. + Content[i], + fCLIENT_STATUS_WMM_CAPABLE); + } + + /*======================================================== */ + /* MAC Register has a copy . */ + /*======================================================== */ +/*#ifndef WIFI_TEST */ + if (pAd->CommonCfg.bEnableTxBurst) { + /* For CWC test, change txop from 0x30 to 0x20 in TxBurst mode */ + Ac0Cfg.field.AcTxop = 0x20; /* Suggest by John for TxBurst in HT Mode */ + } else + Ac0Cfg.field.AcTxop = 0; /* QID_AC_BE */ +/*#else */ +/* Ac0Cfg.field.AcTxop = 0; // QID_AC_BE */ +/*#endif */ + Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac0Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); + + Ac1Cfg.field.AcTxop = 0; /* QID_AC_BK */ + Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac1Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); + + if (pAd->CommonCfg.PhyMode == PHY_11B) { + Ac2Cfg.field.AcTxop = 192; /* AC_VI: 192*32us ~= 6ms */ + Ac3Cfg.field.AcTxop = 96; /* AC_VO: 96*32us ~= 3ms */ + } else { + Ac2Cfg.field.AcTxop = 96; /* AC_VI: 96*32us ~= 3ms */ + Ac3Cfg.field.AcTxop = 48; /* AC_VO: 48*32us ~= 1.5ms */ + } + Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac2Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); + Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac3Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); + + /*======================================================== */ + /* DMA Register has a copy too. */ + /*======================================================== */ + csr0.field.Ac0Txop = 0; /* QID_AC_BE */ + csr0.field.Ac1Txop = 0; /* QID_AC_BK */ + RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); + if (pAd->CommonCfg.PhyMode == PHY_11B) { + csr1.field.Ac2Txop = 192; /* AC_VI: 192*32us ~= 6ms */ + csr1.field.Ac3Txop = 96; /* AC_VO: 96*32us ~= 3ms */ + } else { + csr1.field.Ac2Txop = 96; /* AC_VI: 96*32us ~= 3ms */ + csr1.field.Ac3Txop = 48; /* AC_VO: 48*32us ~= 1.5ms */ + } + RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); + + CwminCsr.word = 0; + CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS; + CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS; + CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS; + CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS; + RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); + + CwmaxCsr.word = 0; + CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS; + CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS; + CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS; + CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS; + RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); + + RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222); + + NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(struct rt_edca_parm)); + } else { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED); + /*======================================================== */ + /* MAC Register has a copy. */ + /*======================================================== */ + /* */ + /* Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27 */ + /* To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue. */ + /* */ + /*pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this */ + + Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE]; + Ac0Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BE]; + Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE]; + Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; /*+1; */ + + Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; + Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; /*+2; */ + Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK]; + Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; /*+1; */ + + Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10; + if (pAd->Antenna.field.TxPath == 1) { + Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI] + 1; + Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI] + 1; + } else { + Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI]; + Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI]; + } + Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI] + 1; +#ifdef RTMP_MAC_USB + Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI] + 3; +#endif /* RTMP_MAC_USB // */ + + { + /* Tuning for Wi-Fi WMM S06 */ + if (pAd->CommonCfg.bWiFiTest && + pEdcaParm->Aifsn[QID_AC_VI] == 10) + Ac2Cfg.field.Aifsn -= 1; + + /* Tuning for TGn Wi-Fi 5.2.32 */ + /* STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta */ + if (STA_TGN_WIFI_ON(pAd) && + pEdcaParm->Aifsn[QID_AC_VI] == 10) { + Ac0Cfg.field.Aifsn = 3; + Ac2Cfg.field.AcTxop = 5; + } +#ifdef RT30xx + if (pAd->RfIcType == RFIC_3020 + || pAd->RfIcType == RFIC_2020) { + /* Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta. */ + Ac2Cfg.field.Aifsn = 5; + } +#endif /* RT30xx // */ + } + + Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO]; + Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO]; + Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO]; + Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO]; + +/*#ifdef WIFI_TEST */ + if (pAd->CommonCfg.bWiFiTest) { + if (Ac3Cfg.field.AcTxop == 102) { + Ac0Cfg.field.AcTxop = + pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm-> + Txop[QID_AC_BE] : 10; + Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE] - 1; /* AIFSN must >= 1 */ + Ac1Cfg.field.AcTxop = + pEdcaParm->Txop[QID_AC_BK]; + Ac1Cfg.field.Aifsn = + pEdcaParm->Aifsn[QID_AC_BK]; + Ac2Cfg.field.AcTxop = + pEdcaParm->Txop[QID_AC_VI]; + } /* End of if */ + } +/*#endif // WIFI_TEST // */ + + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); + RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); + RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); + RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); + + /*======================================================== */ + /* DMA Register has a copy too. */ + /*======================================================== */ + csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop; + csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop; + RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); + + csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop; + csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop; + RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); + + CwminCsr.word = 0; + CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE]; + CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK]; + CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI]; + CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; /*for TGn wifi test */ + RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); + + CwmaxCsr.word = 0; + CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE]; + CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK]; + CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI]; + CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO]; + RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); + + AifsnCsr.word = 0; + AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_BE]; */ + AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_BK]; */ + AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_VI]; */ + + { + /* Tuning for Wi-Fi WMM S06 */ + if (pAd->CommonCfg.bWiFiTest && + pEdcaParm->Aifsn[QID_AC_VI] == 10) + AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4; + + /* Tuning for TGn Wi-Fi 5.2.32 */ + /* STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta */ + if (STA_TGN_WIFI_ON(pAd) && + pEdcaParm->Aifsn[QID_AC_VI] == 10) { + AifsnCsr.field.Aifsn0 = 3; + AifsnCsr.field.Aifsn2 = 7; + } + + if (INFRA_ON(pAd)) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab. + Content[BSSID_WCID], + fCLIENT_STATUS_WMM_CAPABLE); + } + + { + AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; /*pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test */ +#ifdef RT30xx + /* TODO: Shiang, this modification also suitable for RT3052/RT3050 ??? */ + if (pAd->RfIcType == RFIC_3020 + || pAd->RfIcType == RFIC_2020) { + AifsnCsr.field.Aifsn2 = 0x2; /*pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04. */ + } +#endif /* RT30xx // */ + } + RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word); + + NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, + sizeof(struct rt_edca_parm)); + if (!ADHOC_ON(pAd)) { + DBGPRINT(RT_DEBUG_TRACE, + ("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", + pEdcaParm->EdcaUpdateCount)); + DBGPRINT(RT_DEBUG_TRACE, + (" AC_BE %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[0], pEdcaParm->Cwmin[0], + pEdcaParm->Cwmax[0], pEdcaParm->Txop[0] << 5, + pEdcaParm->bACM[0])); + DBGPRINT(RT_DEBUG_TRACE, + (" AC_BK %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[1], pEdcaParm->Cwmin[1], + pEdcaParm->Cwmax[1], pEdcaParm->Txop[1] << 5, + pEdcaParm->bACM[1])); + DBGPRINT(RT_DEBUG_TRACE, + (" AC_VI %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[2], pEdcaParm->Cwmin[2], + pEdcaParm->Cwmax[2], pEdcaParm->Txop[2] << 5, + pEdcaParm->bACM[2])); + DBGPRINT(RT_DEBUG_TRACE, + (" AC_VO %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[3], pEdcaParm->Cwmin[3], + pEdcaParm->Cwmax[3], pEdcaParm->Txop[3] << 5, + pEdcaParm->bACM[3])); + } + } + +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +void AsicSetSlotTime(struct rt_rtmp_adapter *pAd, IN BOOLEAN bUseShortSlotTime) +{ + unsigned long SlotTime; + u32 RegValue = 0; + + if (pAd->CommonCfg.Channel > 14) + bUseShortSlotTime = TRUE; + + if (bUseShortSlotTime + && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED)) + return; + else if ((!bUseShortSlotTime) + && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED))) + return; + + if (bUseShortSlotTime) + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); + else + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); + + SlotTime = (bUseShortSlotTime) ? 9 : 20; + + { + /* force using short SLOT time for FAE to demo performance when TxBurst is ON */ + if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) + && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))) + || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) + && (pAd->CommonCfg.BACapability.field.Policy == + BA_NOTUSE)) + ) { + /* In this case, we will think it is doing Wi-Fi test */ + /* And we will not set to short slot when bEnableTxBurst is TRUE. */ + } else if (pAd->CommonCfg.bEnableTxBurst) { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); + SlotTime = 9; + } + } + + /* */ + /* For some reasons, always set it to short slot time. */ + /* */ + /* ToDo: Should consider capability with 11B */ + /* */ + { + if (pAd->StaCfg.BssType == BSS_ADHOC) { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); + SlotTime = 20; + } + } + + RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); + RegValue = RegValue & 0xFFFFFF00; + + RegValue |= SlotTime; + + RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue); +} + +/* + ======================================================================== + Description: + Add Shared key information into ASIC. + Update shared key, TxMic and RxMic to Asic Shared key table + Update its cipherAlg to Asic Shared key Mode. + + Return: + ======================================================================== +*/ +void AsicAddSharedKeyEntry(struct rt_rtmp_adapter *pAd, + u8 BssIndex, + u8 KeyIdx, + u8 CipherAlg, + u8 *pKey, u8 *pTxMic, u8 *pRxMic) +{ + unsigned long offset; /*, csr0; */ + SHAREDKEY_MODE_STRUC csr1; +#ifdef RTMP_MAC_PCI + int i; +#endif /* RTMP_MAC_PCI // */ + + DBGPRINT(RT_DEBUG_TRACE, + ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex, + KeyIdx)); +/*============================================================================================ */ + + DBGPRINT(RT_DEBUG_TRACE, + ("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], + BssIndex * 4 + KeyIdx)); + DBGPRINT_RAW(RT_DEBUG_TRACE, + (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pKey[0], pKey[1], pKey[2], pKey[3], pKey[4], + pKey[5], pKey[6], pKey[7], pKey[8], pKey[9], + pKey[10], pKey[11], pKey[12], pKey[13], pKey[14], + pKey[15])); + if (pRxMic) { + DBGPRINT_RAW(RT_DEBUG_TRACE, + (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pRxMic[0], pRxMic[1], pRxMic[2], pRxMic[3], + pRxMic[4], pRxMic[5], pRxMic[6], pRxMic[7])); + } + if (pTxMic) { + DBGPRINT_RAW(RT_DEBUG_TRACE, + (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pTxMic[0], pTxMic[1], pTxMic[2], pTxMic[3], + pTxMic[4], pTxMic[5], pTxMic[6], pTxMic[7])); + } +/*============================================================================================ */ + /* */ + /* fill key material - key + TX MIC + RX MIC */ + /* */ +#ifdef RTMP_MAC_PCI + offset = + SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE; + for (i = 0; i < MAX_LEN_OF_SHARE_KEY; i++) { + RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); + } + + offset += MAX_LEN_OF_SHARE_KEY; + if (pTxMic) { + for (i = 0; i < 8; i++) { + RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); + } + } + + offset += 8; + if (pRxMic) { + for (i = 0; i < 8; i++) { + RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); + } + } +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + { + offset = + SHARED_KEY_TABLE_BASE + (4 * BssIndex + + KeyIdx) * HW_KEY_ENTRY_SIZE; + RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY); + + offset += MAX_LEN_OF_SHARE_KEY; + if (pTxMic) { + RTUSBMultiWrite(pAd, offset, pTxMic, 8); + } + + offset += 8; + if (pRxMic) { + RTUSBMultiWrite(pAd, offset, pRxMic, 8); + } + } +#endif /* RTMP_MAC_USB // */ + + /* */ + /* Update cipher algorithm. WSTA always use BSS0 */ + /* */ + RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), + &csr1.word); + DBGPRINT(RT_DEBUG_TRACE, + ("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", + BssIndex, KeyIdx, csr1.word)); + if ((BssIndex % 2) == 0) { + if (KeyIdx == 0) + csr1.field.Bss0Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss0Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss0Key2CipherAlg = CipherAlg; + else + csr1.field.Bss0Key3CipherAlg = CipherAlg; + } else { + if (KeyIdx == 0) + csr1.field.Bss1Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss1Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss1Key2CipherAlg = CipherAlg; + else + csr1.field.Bss1Key3CipherAlg = CipherAlg; + } + DBGPRINT(RT_DEBUG_TRACE, + ("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", + BssIndex, csr1.word)); + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), + csr1.word); + +} + +/* IRQL = DISPATCH_LEVEL */ +void AsicRemoveSharedKeyEntry(struct rt_rtmp_adapter *pAd, + u8 BssIndex, u8 KeyIdx) +{ + /*unsigned long SecCsr0; */ + SHAREDKEY_MODE_STRUC csr1; + + DBGPRINT(RT_DEBUG_TRACE, + ("AsicRemoveSharedKeyEntry: #%d \n", BssIndex * 4 + KeyIdx)); + + RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), + &csr1.word); + if ((BssIndex % 2) == 0) { + if (KeyIdx == 0) + csr1.field.Bss0Key0CipherAlg = 0; + else if (KeyIdx == 1) + csr1.field.Bss0Key1CipherAlg = 0; + else if (KeyIdx == 2) + csr1.field.Bss0Key2CipherAlg = 0; + else + csr1.field.Bss0Key3CipherAlg = 0; + } else { + if (KeyIdx == 0) + csr1.field.Bss1Key0CipherAlg = 0; + else if (KeyIdx == 1) + csr1.field.Bss1Key1CipherAlg = 0; + else if (KeyIdx == 2) + csr1.field.Bss1Key2CipherAlg = 0; + else + csr1.field.Bss1Key3CipherAlg = 0; + } + DBGPRINT(RT_DEBUG_TRACE, + ("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", + BssIndex, csr1.word)); + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), + csr1.word); + ASSERT(BssIndex < 4); + ASSERT(KeyIdx < 4); + +} + +void AsicUpdateWCIDAttribute(struct rt_rtmp_adapter *pAd, + u16 WCID, + u8 BssIndex, + u8 CipherAlg, + IN BOOLEAN bUsePairewiseKeyTable) +{ + unsigned long WCIDAttri = 0, offset; + + /* */ + /* Update WCID attribute. */ + /* Only TxKey could update WCID attribute. */ + /* */ + offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE); + WCIDAttri = + (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable); + RTMP_IO_WRITE32(pAd, offset, WCIDAttri); +} + +void AsicUpdateWCIDIVEIV(struct rt_rtmp_adapter *pAd, + u16 WCID, unsigned long uIV, unsigned long uEIV) +{ + unsigned long offset; + + offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); + + RTMP_IO_WRITE32(pAd, offset, uIV); + RTMP_IO_WRITE32(pAd, offset + 4, uEIV); +} + +void AsicUpdateRxWCIDTable(struct rt_rtmp_adapter *pAd, + u16 WCID, u8 *pAddr) +{ + unsigned long offset; + unsigned long Addr; + + offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE); + Addr = pAddr[0] + (pAddr[1] << 8) + (pAddr[2] << 16) + (pAddr[3] << 24); + RTMP_IO_WRITE32(pAd, offset, Addr); + Addr = pAddr[4] + (pAddr[5] << 8); + RTMP_IO_WRITE32(pAd, offset + 4, Addr); +} + +/* + ======================================================================== + + Routine Description: + Set Cipher Key, Cipher algorithm, IV/EIV to Asic + + Arguments: + pAd Pointer to our adapter + WCID WCID Entry number. + BssIndex BSSID index, station or none multiple BSSID support + this value should be 0. + KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled + pCipherKey Pointer to Cipher Key. + bUsePairewiseKeyTable TRUE means saved the key in SharedKey table, + otherwise PairewiseKey table + bTxKey This is the transmit key if enabled. + + Return Value: + None + + Note: + This routine will set the relative key stuff to Asic including WCID attribute, + Cipher Key, Cipher algorithm and IV/EIV. + + IV/EIV will be update if this CipherKey is the transmission key because + ASIC will base on IV's KeyID value to select Cipher Key. + + If bTxKey sets to FALSE, this is not the TX key, but it could be + RX key + + For AP mode bTxKey must be always set to TRUE. + ======================================================================== +*/ +void AsicAddKeyEntry(struct rt_rtmp_adapter *pAd, + u16 WCID, + u8 BssIndex, + u8 KeyIdx, + struct rt_cipher_key *pCipherKey, + IN BOOLEAN bUsePairewiseKeyTable, IN BOOLEAN bTxKey) +{ + unsigned long offset; +/* unsigned long WCIDAttri = 0; */ + u8 IV4 = 0; + u8 *pKey = pCipherKey->Key; +/* unsigned long KeyLen = pCipherKey->KeyLen; */ + u8 *pTxMic = pCipherKey->TxMic; + u8 *pRxMic = pCipherKey->RxMic; + u8 *pTxtsc = pCipherKey->TxTsc; + u8 CipherAlg = pCipherKey->CipherAlg; + SHAREDKEY_MODE_STRUC csr1; +#ifdef RTMP_MAC_PCI + u8 i; +#endif /* RTMP_MAC_PCI // */ + +/* ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY); */ + + DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n")); + /* */ + /* 1.) decide key table offset */ + /* */ + if (bUsePairewiseKeyTable) + offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); + else + offset = + SHARED_KEY_TABLE_BASE + (4 * BssIndex + + KeyIdx) * HW_KEY_ENTRY_SIZE; + + /* */ + /* 2.) Set Key to Asic */ + /* */ + /*for (i = 0; i < KeyLen; i++) */ +#ifdef RTMP_MAC_PCI + for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++) { + RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); + } + offset += MAX_LEN_OF_PEER_KEY; + + /* */ + /* 3.) Set MIC key if available */ + /* */ + if (pTxMic) { + for (i = 0; i < 8; i++) { + RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); + } + } + offset += LEN_TKIP_TXMICK; + + if (pRxMic) { + for (i = 0; i < 8; i++) { + RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); + } + } +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY); + offset += MAX_LEN_OF_PEER_KEY; + + /* */ + /* 3.) Set MIC key if available */ + /* */ + if (pTxMic) { + RTUSBMultiWrite(pAd, offset, pTxMic, 8); + } + offset += LEN_TKIP_TXMICK; + + if (pRxMic) { + RTUSBMultiWrite(pAd, offset, pRxMic, 8); + } +#endif /* RTMP_MAC_USB // */ + + /* */ + /* 4.) Modify IV/EIV if needs */ + /* This will force Asic to use this key ID by setting IV. */ + /* */ + if (bTxKey) { +#ifdef RTMP_MAC_PCI + offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); + /* */ + /* Write IV */ + /* */ + RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]); + RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f)); + RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]); + + IV4 = (KeyIdx << 6); + if ((CipherAlg == CIPHER_TKIP) + || (CipherAlg == CIPHER_TKIP_NO_MIC) + || (CipherAlg == CIPHER_AES)) + IV4 |= 0x20; /* turn on extension bit means EIV existence */ + + RTMP_IO_WRITE8(pAd, offset + 3, IV4); + + /* */ + /* Write EIV */ + /* */ + offset += 4; + for (i = 0; i < 4; i++) { + RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]); + } +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + u32 tmpVal; + + /* */ + /* Write IV */ + /* */ + IV4 = (KeyIdx << 6); + if ((CipherAlg == CIPHER_TKIP) + || (CipherAlg == CIPHER_TKIP_NO_MIC) + || (CipherAlg == CIPHER_AES)) + IV4 |= 0x20; /* turn on extension bit means EIV existence */ + + tmpVal = + pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + + (pTxtsc[0] << 16) + (IV4 << 24); + RTMP_IO_WRITE32(pAd, offset, tmpVal); + + /* */ + /* Write EIV */ + /* */ + offset += 4; + RTMP_IO_WRITE32(pAd, offset, *(u32 *)& pCipherKey->TxTsc[2]); +#endif /* RTMP_MAC_USB // */ + + AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, + bUsePairewiseKeyTable); + } + + if (!bUsePairewiseKeyTable) { + /* */ + /* Only update the shared key security mode */ + /* */ + RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), + &csr1.word); + if ((BssIndex % 2) == 0) { + if (KeyIdx == 0) + csr1.field.Bss0Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss0Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss0Key2CipherAlg = CipherAlg; + else + csr1.field.Bss0Key3CipherAlg = CipherAlg; + } else { + if (KeyIdx == 0) + csr1.field.Bss1Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss1Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss1Key2CipherAlg = CipherAlg; + else + csr1.field.Bss1Key3CipherAlg = CipherAlg; + } + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), + csr1.word); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n")); +} + +/* + ======================================================================== + Description: + Add Pair-wise key material into ASIC. + Update pairwise key, TxMic and RxMic to Asic Pair-wise key table + + Return: + ======================================================================== +*/ +void AsicAddPairwiseKeyEntry(struct rt_rtmp_adapter *pAd, + u8 *pAddr, + u8 WCID, struct rt_cipher_key *pCipherKey) +{ + int i; + unsigned long offset; + u8 *pKey = pCipherKey->Key; + u8 *pTxMic = pCipherKey->TxMic; + u8 *pRxMic = pCipherKey->RxMic; +#ifdef DBG + u8 CipherAlg = pCipherKey->CipherAlg; +#endif /* DBG // */ + + /* EKEY */ + offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); +#ifdef RTMP_MAC_PCI + for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++) { + RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); + } +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY); +#endif /* RTMP_MAC_USB // */ + for (i = 0; i < MAX_LEN_OF_PEER_KEY; i += 4) { + u32 Value; + RTMP_IO_READ32(pAd, offset + i, &Value); + } + + offset += MAX_LEN_OF_PEER_KEY; + + /* MIC KEY */ + if (pTxMic) { +#ifdef RTMP_MAC_PCI + for (i = 0; i < 8; i++) { + RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); + } +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8); +#endif /* RTMP_MAC_USB // */ + } + offset += 8; + if (pRxMic) { +#ifdef RTMP_MAC_PCI + for (i = 0; i < 8; i++) { + RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); + } +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8); +#endif /* RTMP_MAC_USB // */ + } + + DBGPRINT(RT_DEBUG_TRACE, + ("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n", WCID, + CipherName[CipherAlg])); + DBGPRINT(RT_DEBUG_TRACE, + (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pKey[0], pKey[1], pKey[2], pKey[3], pKey[4], pKey[5], + pKey[6], pKey[7], pKey[8], pKey[9], pKey[10], pKey[11], + pKey[12], pKey[13], pKey[14], pKey[15])); + if (pRxMic) { + DBGPRINT(RT_DEBUG_TRACE, + (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pRxMic[0], pRxMic[1], pRxMic[2], pRxMic[3], + pRxMic[4], pRxMic[5], pRxMic[6], pRxMic[7])); + } + if (pTxMic) { + DBGPRINT(RT_DEBUG_TRACE, + (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pTxMic[0], pTxMic[1], pTxMic[2], pTxMic[3], + pTxMic[4], pTxMic[5], pTxMic[6], pTxMic[7])); + } +} + +/* + ======================================================================== + Description: + Remove Pair-wise key material from ASIC. + + Return: + ======================================================================== +*/ +void AsicRemovePairwiseKeyEntry(struct rt_rtmp_adapter *pAd, + u8 BssIdx, u8 Wcid) +{ + unsigned long WCIDAttri; + u16 offset; + + /* re-set the entry's WCID attribute as OPEN-NONE. */ + offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE); + WCIDAttri = (BssIdx << 4) | PAIRWISEKEYTABLE; + RTMP_IO_WRITE32(pAd, offset, WCIDAttri); +} + +BOOLEAN AsicSendCommandToMcu(struct rt_rtmp_adapter *pAd, + u8 Command, + u8 Token, u8 Arg0, u8 Arg1) +{ + + if (pAd->chipOps.sendCommandToMcu) + pAd->chipOps.sendCommandToMcu(pAd, Command, Token, Arg0, Arg1); + + return TRUE; +} + +void AsicSetRxAnt(struct rt_rtmp_adapter *pAd, u8 Ant) +{ +#ifdef RT30xx + /* RT3572 ATE need not to do this. */ + RT30xxSetRxAnt(pAd, Ant); +#endif /* RT30xx // */ +} + +void AsicTurnOffRFClk(struct rt_rtmp_adapter *pAd, u8 Channel) +{ + if (pAd->chipOps.AsicRfTurnOff) { + pAd->chipOps.AsicRfTurnOff(pAd); + } else { + /* RF R2 bit 18 = 0 */ + u32 R1 = 0, R2 = 0, R3 = 0; + u8 index; + struct rt_rtmp_rf_regs *RFRegTable; + + RFRegTable = RF2850RegTable; + + switch (pAd->RfIcType) { + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: + + for (index = 0; index < NUM_OF_2850_CHNL; index++) { + if (Channel == RFRegTable[index].Channel) { + R1 = RFRegTable[index].R1 & 0xffffdfff; + R2 = RFRegTable[index].R2 & 0xfffbffff; + R3 = RFRegTable[index].R3 & 0xfff3ffff; + + RTMP_RF_IO_WRITE32(pAd, R1); + RTMP_RF_IO_WRITE32(pAd, R2); + + /* Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0. */ + /* Set RF R2 bit18=0, R3 bit[18:19]=0 */ + /*if (pAd->StaCfg.bRadio == FALSE) */ + if (1) { + RTMP_RF_IO_WRITE32(pAd, R3); + + DBGPRINT(RT_DEBUG_TRACE, + ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n", + Channel, + pAd->RfIcType, R2, + R3)); + } else + DBGPRINT(RT_DEBUG_TRACE, + ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n", + Channel, + pAd->RfIcType, R2)); + break; + } + } + break; + + default: + break; + } + } +} + +void AsicTurnOnRFClk(struct rt_rtmp_adapter *pAd, u8 Channel) +{ + /* RF R2 bit 18 = 0 */ + u32 R1 = 0, R2 = 0, R3 = 0; + u8 index; + struct rt_rtmp_rf_regs *RFRegTable; + +#ifdef PCIE_PS_SUPPORT + /* The RF programming sequence is difference between 3xxx and 2xxx */ + if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) { + return; + } +#endif /* PCIE_PS_SUPPORT // */ + + RFRegTable = RF2850RegTable; + + switch (pAd->RfIcType) { + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: + + for (index = 0; index < NUM_OF_2850_CHNL; index++) { + if (Channel == RFRegTable[index].Channel) { + R3 = pAd->LatchRfRegs.R3; + R3 &= 0xfff3ffff; + R3 |= 0x00080000; + RTMP_RF_IO_WRITE32(pAd, R3); + + R1 = RFRegTable[index].R1; + RTMP_RF_IO_WRITE32(pAd, R1); + + R2 = RFRegTable[index].R2; + if (pAd->Antenna.field.TxPath == 1) { + R2 |= 0x4000; /* If TXpath is 1, bit 14 = 1; */ + } + + if (pAd->Antenna.field.RxPath == 2) { + R2 |= 0x40; /* write 1 to off Rxpath. */ + } else if (pAd->Antenna.field.RxPath == 1) { + R2 |= 0x20040; /* write 1 to off RxPath */ + } + RTMP_RF_IO_WRITE32(pAd, R2); + + break; + } + } + break; + + default: + break; + } + + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n", + Channel, pAd->RfIcType, R2)); +} diff --git a/drivers/staging/rt3090/common/cmm_cfg.c b/drivers/staging/rt2860/common/cmm_cfg.c similarity index 56% rename from drivers/staging/rt3090/common/cmm_cfg.c rename to drivers/staging/rt2860/common/cmm_cfg.c index d8be9793c61bc1aa64e608b04bb20e2acdf33eec..24f439378439a8bed39a5e9b566a5688bbe48ad7 100644 --- a/drivers/staging/rt3090/common/cmm_cfg.c +++ b/drivers/staging/rt2860/common/cmm_cfg.c @@ -37,50 +37,39 @@ #include "../rt_config.h" - -char* GetPhyMode( - int Mode) +char *GetPhyMode(int Mode) { - switch(Mode) - { - case MODE_CCK: - return "CCK"; - - case MODE_OFDM: - return "OFDM"; -#ifdef DOT11_N_SUPPORT - case MODE_HTMIX: - return "HTMIX"; - - case MODE_HTGREENFIELD: - return "GREEN"; -#endif // DOT11_N_SUPPORT // - default: - return "N/A"; + switch (Mode) { + case MODE_CCK: + return "CCK"; + + case MODE_OFDM: + return "OFDM"; + case MODE_HTMIX: + return "HTMIX"; + + case MODE_HTGREENFIELD: + return "GREEN"; + default: + return "N/A"; } } - -char* GetBW( - int BW) +char *GetBW(int BW) { - switch(BW) - { - case BW_10: - return "10M"; - - case BW_20: - return "20M"; -#ifdef DOT11_N_SUPPORT - case BW_40: - return "40M"; -#endif // DOT11_N_SUPPORT // - default: - return "N/A"; + switch (BW) { + case BW_10: + return "10M"; + + case BW_20: + return "20M"; + case BW_40: + return "40M"; + default: + return "N/A"; } } - /* ========================================================================== Description: @@ -91,46 +80,37 @@ char* GetBW( TRUE if all parameters are OK, FALSE otherwise ========================================================================== */ -INT RT_CfgSetCountryRegion( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg, - IN INT band) +int RT_CfgSetCountryRegion(struct rt_rtmp_adapter *pAd, char *arg, int band) { - LONG region, regionMax; - UCHAR *pCountryRegion; + long region, regionMax; + u8 *pCountryRegion; region = simple_strtol(arg, 0, 10); - if (band == BAND_24G) - { + if (band == BAND_24G) { pCountryRegion = &pAd->CommonCfg.CountryRegion; regionMax = REGION_MAXIMUM_BG_BAND; - } - else - { + } else { pCountryRegion = &pAd->CommonCfg.CountryRegionForABand; regionMax = REGION_MAXIMUM_A_BAND; } - // TODO: Is it neccesay for following check??? - // Country can be set only when EEPROM not programmed - if (*pCountryRegion & 0x80) - { - DBGPRINT(RT_DEBUG_ERROR, ("CfgSetCountryRegion():CountryRegion in eeprom was programmed\n")); + /* TODO: Is it neccesay for following check??? */ + /* Country can be set only when EEPROM not programmed */ + if (*pCountryRegion & 0x80) { + DBGPRINT(RT_DEBUG_ERROR, + ("CfgSetCountryRegion():CountryRegion in eeprom was programmed\n")); return FALSE; } - if((region >= 0) && (region <= REGION_MAXIMUM_BG_BAND)) - { - *pCountryRegion= (UCHAR) region; - } - else if ((region == REGION_31_BG_BAND) && (band == BAND_24G)) - { - *pCountryRegion = (UCHAR) region; - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("CfgSetCountryRegion():region(%ld) out of range!\n", region)); + if ((region >= 0) && (region <= REGION_MAXIMUM_BG_BAND)) { + *pCountryRegion = (u8)region; + } else if ((region == REGION_31_BG_BAND) && (band == BAND_24G)) { + *pCountryRegion = (u8)region; + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("CfgSetCountryRegion():region(%ld) out of range!\n", + region)); return FALSE; } @@ -138,7 +118,6 @@ INT RT_CfgSetCountryRegion( } - /* ========================================================================== Description: @@ -147,22 +126,16 @@ INT RT_CfgSetCountryRegion( TRUE if all parameters are OK, FALSE otherwise ========================================================================== */ -INT RT_CfgSetWirelessMode( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) +int RT_CfgSetWirelessMode(struct rt_rtmp_adapter *pAd, char *arg) { - INT MaxPhyMode = PHY_11G; - LONG WirelessMode; + int MaxPhyMode = PHY_11G; + long WirelessMode; -#ifdef DOT11_N_SUPPORT MaxPhyMode = PHY_11N_5G; -#endif // DOT11_N_SUPPORT // WirelessMode = simple_strtol(arg, 0, 10); - if (WirelessMode <= MaxPhyMode) - { + if (WirelessMode <= MaxPhyMode) { pAd->CommonCfg.PhyMode = WirelessMode; - pAd->CommonCfg.DesiredPhyMode = WirelessMode; return TRUE; } @@ -170,12 +143,9 @@ INT RT_CfgSetWirelessMode( } - -INT RT_CfgSetShortSlot( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) +int RT_CfgSetShortSlot(struct rt_rtmp_adapter *pAd, char *arg) { - LONG ShortSlot; + long ShortSlot; ShortSlot = simple_strtol(arg, 0, 10); @@ -184,12 +154,11 @@ INT RT_CfgSetShortSlot( else if (ShortSlot == 0) pAd->CommonCfg.bUseShortSlotTime = FALSE; else - return FALSE; //Invalid argument + return FALSE; /*Invalid argument */ return TRUE; } - /* ========================================================================== Description: @@ -198,54 +167,53 @@ INT RT_CfgSetShortSlot( TRUE if all parameters are OK, FALSE otherwise ========================================================================== */ -INT RT_CfgSetWepKey( - IN PRTMP_ADAPTER pAd, - IN PSTRING keyString, - IN CIPHER_KEY *pSharedKey, - IN INT keyIdx) +int RT_CfgSetWepKey(struct rt_rtmp_adapter *pAd, + char *keyString, + struct rt_cipher_key *pSharedKey, int keyIdx) { - INT KeyLen; - INT i; - UCHAR CipherAlg = CIPHER_NONE; - BOOLEAN bKeyIsHex = FALSE; + int KeyLen; + int i; + u8 CipherAlg = CIPHER_NONE; + BOOLEAN bKeyIsHex = FALSE; - // TODO: Shall we do memset for the original key info?? - memset(pSharedKey, 0, sizeof(CIPHER_KEY)); + /* TODO: Shall we do memset for the original key info?? */ + memset(pSharedKey, 0, sizeof(struct rt_cipher_key)); KeyLen = strlen(keyString); - switch (KeyLen) - { - case 5: //wep 40 Ascii type - case 13: //wep 104 Ascii type - bKeyIsHex = FALSE; - pSharedKey->KeyLen = KeyLen; - NdisMoveMemory(pSharedKey->Key, keyString, KeyLen); - break; - - case 10: //wep 40 Hex type - case 26: //wep 104 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(keyString+i)) ) - return FALSE; //Not Hex value; - } - bKeyIsHex = TRUE; - pSharedKey->KeyLen = KeyLen/2 ; - AtoH(keyString, pSharedKey->Key, pSharedKey->KeyLen); - break; - - default: //Invalid argument - DBGPRINT(RT_DEBUG_TRACE, ("RT_CfgSetWepKey(keyIdx=%d):Invalid argument (arg=%s)\n", keyIdx, keyString)); - return FALSE; + switch (KeyLen) { + case 5: /*wep 40 Ascii type */ + case 13: /*wep 104 Ascii type */ + bKeyIsHex = FALSE; + pSharedKey->KeyLen = KeyLen; + NdisMoveMemory(pSharedKey->Key, keyString, KeyLen); + break; + + case 10: /*wep 40 Hex type */ + case 26: /*wep 104 Hex type */ + for (i = 0; i < KeyLen; i++) { + if (!isxdigit(*(keyString + i))) + return FALSE; /*Not Hex value; */ + } + bKeyIsHex = TRUE; + pSharedKey->KeyLen = KeyLen / 2; + AtoH(keyString, pSharedKey->Key, pSharedKey->KeyLen); + break; + + default: /*Invalid argument */ + DBGPRINT(RT_DEBUG_TRACE, + ("RT_CfgSetWepKey(keyIdx=%d):Invalid argument (arg=%s)\n", + keyIdx, keyString)); + return FALSE; } pSharedKey->CipherAlg = ((KeyLen % 5) ? CIPHER_WEP128 : CIPHER_WEP64); - DBGPRINT(RT_DEBUG_TRACE, ("RT_CfgSetWepKey:(KeyIdx=%d,type=%s, Alg=%s)\n", - keyIdx, (bKeyIsHex == FALSE ? "Ascii" : "Hex"), CipherName[CipherAlg])); + DBGPRINT(RT_DEBUG_TRACE, + ("RT_CfgSetWepKey:(KeyIdx=%d,type=%s, Alg=%s)\n", keyIdx, + (bKeyIsHex == FALSE ? "Ascii" : "Hex"), + CipherName[CipherAlg])); return TRUE; } - /* ========================================================================== Description: @@ -262,33 +230,28 @@ INT RT_CfgSetWepKey( TRUE if all parameters are OK, FALSE otherwise ========================================================================== */ -INT RT_CfgSetWPAPSKKey( - IN RTMP_ADAPTER *pAd, - IN PSTRING keyString, - IN UCHAR *pHashStr, - IN INT hashStrLen, - OUT PUCHAR pPMKBuf) +int RT_CfgSetWPAPSKKey(struct rt_rtmp_adapter *pAd, + char *keyString, + u8 * pHashStr, + int hashStrLen, u8 *pPMKBuf) { int keyLen; - UCHAR keyMaterial[40]; + u8 keyMaterial[40]; keyLen = strlen(keyString); - if ((keyLen < 8) || (keyLen > 64)) - { - DBGPRINT(RT_DEBUG_TRACE, ("WPAPSK Key length(%d) error, required 8 ~ 64 characters!(keyStr=%s)\n", - keyLen, keyString)); + if ((keyLen < 8) || (keyLen > 64)) { + DBGPRINT(RT_DEBUG_TRACE, + ("WPAPSK Key length(%d) error, required 8 ~ 64 characters!(keyStr=%s)\n", + keyLen, keyString)); return FALSE; } memset(pPMKBuf, 0, 32); - if (keyLen == 64) - { - AtoH(keyString, pPMKBuf, 32); - } - else - { - PasswordHash(keyString, pHashStr, hashStrLen, keyMaterial); - NdisMoveMemory(pPMKBuf, keyMaterial, 32); + if (keyLen == 64) { + AtoH(keyString, pPMKBuf, 32); + } else { + PasswordHash(keyString, pHashStr, hashStrLen, keyMaterial); + NdisMoveMemory(pPMKBuf, keyMaterial, 32); } return TRUE; diff --git a/drivers/staging/rt2860/common/cmm_data.c b/drivers/staging/rt2860/common/cmm_data.c index 774fabb0be406b6b549ea141ab83385973fbb9b7..68263cee79521ef607703554894e1d58ddd867e6 100644 --- a/drivers/staging/rt2860/common/cmm_data.c +++ b/drivers/staging/rt2860/common/cmm_data.c @@ -27,50 +27,58 @@ #include "../rt_config.h" -#define MAX_TX_IN_TBTT (16) - - -UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; -UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8}; -// Add Cisco Aironet SNAP heade for CCX2 support -UCHAR SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00}; -UCHAR CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02}; -UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e}; -UCHAR EAPOL[] = {0x88, 0x8e}; -UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */ - -UCHAR IPX[] = {0x81, 0x37}; -UCHAR APPLE_TALK[] = {0x80, 0xf3}; -UCHAR RateIdToPlcpSignal[12] = { - 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec - 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14 - 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14 - -UCHAR OfdmSignalToRateId[16] = { - RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 0, 1, 2, 3 respectively - RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 4, 5, 6, 7 respectively - RATE_48, RATE_24, RATE_12, RATE_6, // OFDM PLCP Signal = 8, 9, 10, 11 respectively - RATE_54, RATE_36, RATE_18, RATE_9, // OFDM PLCP Signal = 12, 13, 14, 15 respectively +u8 SNAP_802_1H[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; +u8 SNAP_BRIDGE_TUNNEL[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; + +/* Add Cisco Aironet SNAP heade for CCX2 support */ +u8 SNAP_AIRONET[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00 }; +u8 CKIP_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02 }; +u8 EAPOL_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e }; +u8 EAPOL[] = { 0x88, 0x8e }; +u8 TPID[] = { 0x81, 0x00 }; /* VLAN related */ + +u8 IPX[] = { 0x81, 0x37 }; +u8 APPLE_TALK[] = { 0x80, 0xf3 }; + +u8 RateIdToPlcpSignal[12] = { + 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 *//* see BBP spec */ + 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 *//* see IEEE802.11a-1999 p.14 */ + 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ +}; /* see IEEE802.11a-1999 p.14 */ + +u8 OfdmSignalToRateId[16] = { + RATE_54, RATE_54, RATE_54, RATE_54, /* OFDM PLCP Signal = 0, 1, 2, 3 respectively */ + RATE_54, RATE_54, RATE_54, RATE_54, /* OFDM PLCP Signal = 4, 5, 6, 7 respectively */ + RATE_48, RATE_24, RATE_12, RATE_6, /* OFDM PLCP Signal = 8, 9, 10, 11 respectively */ + RATE_54, RATE_36, RATE_18, RATE_9, /* OFDM PLCP Signal = 12, 13, 14, 15 respectively */ }; -UCHAR OfdmRateToRxwiMCS[12] = { - 0, 0, 0, 0, - 0, 1, 2, 3, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 - 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 -}; -UCHAR RxwiMCSToOfdmRate[12] = { - RATE_6, RATE_9, RATE_12, RATE_18, - RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 - 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 +u8 OfdmRateToRxwiMCS[12] = { + 0, 0, 0, 0, + 0, 1, 2, 3, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */ + 4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */ }; -char* MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"}; +u8 RxwiMCSToOfdmRate[12] = { + RATE_6, RATE_9, RATE_12, RATE_18, + RATE_24, RATE_36, RATE_48, RATE_54, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */ + 4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */ +}; -UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2}; -UCHAR default_sta_aifsn[]={3,7,2,2}; +char *MCSToMbps[] = + { "1Mbps", "2Mbps", "5.5Mbps", "11Mbps", "06Mbps", "09Mbps", "12Mbps", +"18Mbps", "24Mbps", "36Mbps", "48Mbps", "54Mbps", "MM-0", "MM-1", "MM-2", "MM-3", +"MM-4", "MM-5", "MM-6", "MM-7", "MM-8", "MM-9", "MM-10", "MM-11", "MM-12", "MM-13", +"MM-14", "MM-15", "MM-32", "ee1", "ee2", "ee3" }; -UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO}; +u8 default_cwmin[] = + { CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS - 1, CW_MIN_IN_BITS - 2 }; +/*u8 default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1}; */ +u8 default_sta_aifsn[] = { 3, 7, 2, 2 }; +u8 MapUserPriorityToAccessCategory[8] = + { QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, +QID_AC_VO, QID_AC_VO }; /* ======================================================================== @@ -96,162 +104,119 @@ UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID ======================================================================== */ -NDIS_STATUS MiniportMMRequest( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PUCHAR pData, - IN UINT Length) +int MiniportMMRequest(struct rt_rtmp_adapter *pAd, + u8 QueIdx, u8 *pData, u32 Length) { - PNDIS_PACKET pPacket; - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - ULONG FreeNum; -#ifdef RT2860 - unsigned long IrqFlags = 0; -#endif - UCHAR IrqState; - UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN]; + void *pPacket; + int Status = NDIS_STATUS_SUCCESS; + unsigned long FreeNum; + u8 rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; /*RTMP_HW_HDR_LEN]; */ +#ifdef RTMP_MAC_PCI + unsigned long IrqFlags = 0; + u8 IrqState; +#endif /* RTMP_MAC_PCI // */ + BOOLEAN bUseDataQ = FALSE; + int retryCnt = 0; ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); - QueIdx=3; - - // 2860C use Tx Ring - + if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) { + bUseDataQ = TRUE; + QueIdx &= (~MGMT_USE_QUEUE_FLAG); + } +#ifdef RTMP_MAC_PCI + /* 2860C use Tx Ring */ IrqState = pAd->irq_disabled; - -#ifdef RT2860 - if ((pAd->MACVersion == 0x28600100) && (!IrqState)) + if (pAd->MACVersion == 0x28600100) { + QueIdx = (bUseDataQ == TRUE ? QueIdx : 3); + bUseDataQ = TRUE; + } + if (bUseDataQ && (!IrqState)) RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); -#endif - do - { - // Reset is in progress, stop immediately - if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)|| - !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) - { +#endif /* RTMP_MAC_PCI // */ + + do { + /* Reset is in progress, stop immediately */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST) + || !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) { Status = NDIS_STATUS_FAILURE; break; } - - // Check Free priority queue - // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. - - // 2860C use Tx Ring - if (pAd->MACVersion == 0x28600100) - { + /* Check Free priority queue */ + /* Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. */ +#ifdef RTMP_MAC_PCI + if (bUseDataQ) { + retryCnt = MAX_DATAMM_RETRY; + /* free Tx(QueIdx) resources */ + RTMPFreeTXDUponTxDmaDone(pAd, QueIdx); FreeNum = GET_TXRING_FREENO(pAd, QueIdx); - } - else + } else +#endif /* RTMP_MAC_PCI // */ { FreeNum = GET_MGMTRING_FREENO(pAd); } - if ((FreeNum > 0)) - { - // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 + if ((FreeNum > 0)) { + /* We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 */ NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE)); - Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); + Status = + RTMPAllocateNdisPacket(pAd, &pPacket, + (u8 *)& rtmpHwHdr, + (TXINFO_SIZE + TXWI_SIZE), + pData, Length); + if (Status != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_WARN, + ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); break; } - - //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; - //pAd->CommonCfg.MlmeRate = RATE_2; - - - Status = MlmeHardTransmit(pAd, QueIdx, pPacket); - if (Status != NDIS_STATUS_SUCCESS) + /*pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; */ + /*pAd->CommonCfg.MlmeRate = RATE_2; */ + +#ifdef RTMP_MAC_PCI + if (bUseDataQ) { + Status = + MlmeDataHardTransmit(pAd, QueIdx, pPacket); + retryCnt--; + } else +#endif /* RTMP_MAC_PCI // */ + Status = MlmeHardTransmit(pAd, QueIdx, pPacket); + if (Status == NDIS_STATUS_SUCCESS) + retryCnt = 0; + else RTMPFreeNdisPacket(pAd, pPacket); - } - else - { + } else { pAd->RalinkCounters.MgmtRingFullCount++; - DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n", - QueIdx, pAd->RalinkCounters.MgmtRingFullCount)); - } - - } while (FALSE); - -#ifdef RT2860 - // 2860C use Tx Ring - if ((pAd->MACVersion == 0x28600100) && (!IrqState)) - RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); -#endif - return Status; -} - -#ifdef RT2860 -NDIS_STATUS MiniportMMRequestUnlock( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PUCHAR pData, - IN UINT Length) -{ - PNDIS_PACKET pPacket; - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - ULONG FreeNum; - TXWI_STRUC TXWI; - ULONG SW_TX_IDX; - PTXD_STRUC pTxD; - - QueIdx = 3; - ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); - - do - { - // Reset is in progress, stop immediately - if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)|| - !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) - { - Status = NDIS_STATUS_FAILURE; - break; - } - - // Check Free priority queue - // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. - // 2860C use Tx Ring - if (pAd->MACVersion == 0x28600100) - { - FreeNum = GET_TXRING_FREENO(pAd, QueIdx); - SW_TX_IDX = pAd->TxRing[QueIdx].TxCpuIdx; - pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SW_TX_IDX].AllocVa; - } - else - { - FreeNum = GET_MGMTRING_FREENO(pAd); - SW_TX_IDX = pAd->MgmtRing.TxCpuIdx; - pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SW_TX_IDX].AllocVa; - } - if ((FreeNum > 0)) - { - NdisZeroMemory(&TXWI, TXWI_SIZE); - Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&TXWI, TXWI_SIZE, pData, Length); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); - break; +#ifdef RTMP_MAC_PCI + if (bUseDataQ) { + retryCnt--; + DBGPRINT(RT_DEBUG_TRACE, + ("retryCnt %d\n", retryCnt)); + if (retryCnt == 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n", + QueIdx, + pAd->RalinkCounters. + MgmtRingFullCount)); + } } - - Status = MlmeHardTransmit(pAd, QueIdx, pPacket); - if (Status != NDIS_STATUS_SUCCESS) - RTMPFreeNdisPacket(pAd, pPacket); +#endif /* RTMP_MAC_PCI // */ + DBGPRINT(RT_DEBUG_ERROR, + ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n", + QueIdx, + pAd->RalinkCounters.MgmtRingFullCount)); } - else - { - pAd->RalinkCounters.MgmtRingFullCount++; - DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing\n", QueIdx)); - } - - } while (FALSE); + } while (retryCnt > 0); +#ifdef RTMP_MAC_PCI + if (bUseDataQ && (!IrqState)) + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); +#endif /* RTMP_MAC_PCI // */ return Status; } -#endif /* ======================================================================== @@ -277,270 +242,85 @@ NDIS_STATUS MiniportMMRequestUnlock( ======================================================================== */ -NDIS_STATUS MlmeHardTransmit( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket) +int MlmeHardTransmit(struct rt_rtmp_adapter *pAd, + u8 QueIdx, void *pPacket) { - if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) - { + struct rt_packet_info PacketInfo; + u8 *pSrcBufVA; + u32 SrcBufLen; + struct rt_header_802_11 * pHeader_802_11; + + if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) + ) { return NDIS_STATUS_FAILURE; } -#ifdef RT2860 - if ( pAd->MACVersion == 0x28600100 ) - return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket); - else -#endif - return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket); - -} - -#ifdef RT2860 -NDIS_STATUS MlmeHardTransmitTxRing( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket) -{ - PACKET_INFO PacketInfo; - PUCHAR pSrcBufVA; - UINT SrcBufLen; - PTXD_STRUC pTxD; - PHEADER_802_11 pHeader_802_11; - BOOLEAN bAckRequired, bInsertTimestamp; - ULONG SrcBufPA; - UCHAR MlmeRate; - ULONG SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; - PTXWI_STRUC pFirstTxWI; - ULONG FreeNum; - MAC_TABLE_ENTRY *pMacEntry = NULL; - - RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); - if (pSrcBufVA == NULL) - { - // The buffer shouldn't be NULL return NDIS_STATUS_FAILURE; - } - - // Make sure MGMT ring resource won't be used by other threads - //NdisAcquireSpinLock(&pAd->TxRingLock); - - FreeNum = GET_TXRING_FREENO(pAd, QueIdx); - - if (FreeNum == 0) - { - //NdisReleaseSpinLock(&pAd->TxRingLock); - return NDIS_STATUS_FAILURE; - } - - SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; - - pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; - - if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket) - { - printk("MlmeHardTransmit Error\n"); - return NDIS_STATUS_FAILURE; - } - - // outgoing frame always wakeup PHY to prevent frame lost - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - AsicForceWakeup(pAd, FROM_TX); - - pFirstTxWI =(PTXWI_STRUC)pSrcBufVA; - - pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXWI_SIZE); - if (pHeader_802_11->Addr1[0] & 0x01) - { - MlmeRate = pAd->CommonCfg.BasicMlmeRate; - } - else - { - MlmeRate = pAd->CommonCfg.MlmeRate; - } - - if ((pHeader_802_11->FC.Type == BTYPE_DATA) && - (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) - { - pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); - } - - // Verify Mlme rate for a / g bands. - if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band - MlmeRate = RATE_6; - - // - // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) - // Snice it's been set to 0 while on MgtMacHeaderInit - // By the way this will cause frame to be send on PWR_SAVE failed. - // - // - // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame - - // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD - if (pHeader_802_11->FC.Type != BTYPE_DATA) - { - if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) - { - pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; - } - else - { - pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave; - } - } - - bInsertTimestamp = FALSE; - if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL - { - bAckRequired = FALSE; - } - else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame) - { - if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST - { - bAckRequired = FALSE; - pHeader_802_11->Duration = 0; - } - else - { - bAckRequired = TRUE; - pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14); - if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) - { - bInsertTimestamp = TRUE; - } - } - } - pHeader_802_11->Sequence = pAd->Sequence++; - if (pAd->Sequence > 0xfff) - pAd->Sequence = 0; - // Before radar detection done, mgmt frame can not be sent but probe req - // Because we need to use probe req to trigger driver to send probe req in passive scan - if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) - && (pAd->CommonCfg.bIEEE80211H == 1) - && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) - { - DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n")); - return (NDIS_STATUS_FAILURE); - } - - // - // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET - // should always has only one ohysical buffer, and the whole frame size equals - // to the first scatter buffer size - // - // Initialize TX Descriptor - // For inter-frame gap, the number is for this frame and next frame - // For MLME rate, we will fix as 2Mb to match other vendor's implement + pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); -// management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. - // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE. - if (pMacEntry == NULL) - { - RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, - 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); - } +#ifdef RTMP_MAC_PCI + if (pAd->MACVersion == 0x28600100) + return MlmeHardTransmitTxRing(pAd, QueIdx, pPacket); else - { - RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, - bInsertTimestamp, FALSE, bAckRequired, FALSE, - 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE), - pMacEntry->MaxHTPhyMode.field.MCS, 0, - (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS, - IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); - } - - pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket; - pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL; - - SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE); - - - RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA); - pTxD->LastSec0 = 1; - pTxD->LastSec1 = 1; - pTxD->SDLen0 = SrcBufLen; - pTxD->SDLen1 = 0; - pTxD->SDPtr0 = SrcBufPA; - pTxD->DMADONE = 0; - - pAd->RalinkCounters.KickTxCount++; - pAd->RalinkCounters.OneSecTxDoneCount++; +#endif /* RTMP_MAC_PCI // */ + return MlmeHardTransmitMgmtRing(pAd, QueIdx, pPacket); - // Increase TX_CTX_IDX, but write to register later. - INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); - - RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx); - - return NDIS_STATUS_SUCCESS; } -#endif /* RT2860 */ -NDIS_STATUS MlmeHardTransmitMgmtRing( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket) +int MlmeHardTransmitMgmtRing(struct rt_rtmp_adapter *pAd, + u8 QueIdx, void *pPacket) { - PACKET_INFO PacketInfo; - PUCHAR pSrcBufVA; - UINT SrcBufLen; - PHEADER_802_11 pHeader_802_11; - BOOLEAN bAckRequired, bInsertTimestamp; - UCHAR MlmeRate; - PTXWI_STRUC pFirstTxWI; - MAC_TABLE_ENTRY *pMacEntry = NULL; + struct rt_packet_info PacketInfo; + u8 *pSrcBufVA; + u32 SrcBufLen; + struct rt_header_802_11 * pHeader_802_11; + BOOLEAN bAckRequired, bInsertTimestamp; + u8 MlmeRate; + struct rt_txwi * pFirstTxWI; + struct rt_mac_table_entry *pMacEntry = NULL; + u8 PID; RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); - RTMP_SEM_LOCK(&pAd->MgmtRingLock); - - if (pSrcBufVA == NULL) - { + /* Make sure MGMT ring resource won't be used by other threads */ + RTMP_SEM_LOCK(&pAd->MgmtRingLock); + if (pSrcBufVA == NULL) { + /* The buffer shouldn't be NULL */ RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); return NDIS_STATUS_FAILURE; } - // outgoing frame always wakeup PHY to prevent frame lost - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) -#ifdef RT2860 - AsicForceWakeup(pAd, FROM_TX); -#endif -#ifdef RT2870 - AsicForceWakeup(pAd, TRUE); -#endif + { + /* outgoing frame always wakeup PHY to prevent frame lost */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + AsicForceWakeup(pAd, TRUE); + } - pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE); - pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE); + pFirstTxWI = (struct rt_txwi *) (pSrcBufVA + TXINFO_SIZE); + pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); /*TXWI_SIZE); */ - if (pHeader_802_11->Addr1[0] & 0x01) - { + if (pHeader_802_11->Addr1[0] & 0x01) { MlmeRate = pAd->CommonCfg.BasicMlmeRate; - } - else - { + } else { MlmeRate = pAd->CommonCfg.MlmeRate; } - // Verify Mlme rate for a / g bands. - if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band + /* Verify Mlme rate for a / g bands. */ + if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band */ MlmeRate = RATE_6; if ((pHeader_802_11->FC.Type == BTYPE_DATA) && - (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) - { + (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) { pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); } { - // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode. + /* Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode. */ if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED - || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED - ) - { + || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) { if (pAd->LatchRfRegs.Channel > 14) pAd->CommonCfg.MlmeTransmit.field.MODE = 1; else @@ -548,103 +328,121 @@ NDIS_STATUS MlmeHardTransmitMgmtRing( } } - // - // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) - // Snice it's been set to 0 while on MgtMacHeaderInit - // By the way this will cause frame to be send on PWR_SAVE failed. - // - // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE); - // - // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame - - // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD - if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL)) + /* */ + /* Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) */ + /* Snice it's been set to 0 while on MgtMacHeaderInit */ + /* By the way this will cause frame to be send on PWR_SAVE failed. */ + /* */ + pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; /* (pAd->StaCfg.Psm == PWR_SAVE); */ + + /* */ + /* In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame */ + /* Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */ +/* if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL)) */ { - if ((pAd->StaCfg.Psm == PWR_SAVE) && - (pHeader_802_11->FC.SubType == SUBTYPE_ACTION)) - pHeader_802_11->FC.PwrMgmt = PWR_SAVE; - else - pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; + if ((pHeader_802_11->FC.SubType == SUBTYPE_ACTION) || + ((pHeader_802_11->FC.Type == BTYPE_DATA) && + ((pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL) || + (pHeader_802_11->FC.SubType == SUBTYPE_NULL_FUNC)))) { + if (pAd->StaCfg.Psm == PWR_SAVE) + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + else + pHeader_802_11->FC.PwrMgmt = + pAd->CommonCfg.bAPSDForcePowerSave; + } } bInsertTimestamp = FALSE; - if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL + if (pHeader_802_11->FC.Type == BTYPE_CNTL) /* must be PS-POLL */ { - //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue. - if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) - { + /*Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue. */ + if ((pAd->OpMode == OPMODE_STA) + && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) { pHeader_802_11->FC.PwrMgmt = PWR_SAVE; } bAckRequired = FALSE; - } - else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame) + } else /* BTYPE_MGMT or BTYPE_DATA(must be NULL frame) */ { - if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST + /*pAd->Sequence++; */ + /*pHeader_802_11->Sequence = pAd->Sequence; */ + + if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST */ { bAckRequired = FALSE; pHeader_802_11->Duration = 0; - } - else - { + } else { bAckRequired = TRUE; - pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14); - if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) - { + pHeader_802_11->Duration = + RTMPCalcDuration(pAd, MlmeRate, 14); + if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) + && (pHeader_802_11->FC.Type == BTYPE_MGMT)) { bInsertTimestamp = TRUE; + bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Response */ + } else + if ((pHeader_802_11->FC.SubType == + SUBTYPE_PROBE_REQ) + && (pHeader_802_11->FC.Type == BTYPE_MGMT)) { + bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Request */ } } } pHeader_802_11->Sequence = pAd->Sequence++; - if (pAd->Sequence >0xfff) + if (pAd->Sequence > 0xfff) pAd->Sequence = 0; - // Before radar detection done, mgmt frame can not be sent but probe req - // Because we need to use probe req to trigger driver to send probe req in passive scan + /* Before radar detection done, mgmt frame can not be sent but probe req */ + /* Because we need to use probe req to trigger driver to send probe req in passive scan */ if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) - && (pAd->CommonCfg.bIEEE80211H == 1) - && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) - { - DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n")); + && (pAd->CommonCfg.bIEEE80211H == 1) + && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) { + DBGPRINT(RT_DEBUG_ERROR, + ("MlmeHardTransmit --> radar detect not in normal mode!\n")); +/* if (!IrqState) */ RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); return (NDIS_STATUS_FAILURE); } - // - // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET - // should always has only one ohysical buffer, and the whole frame size equals - // to the first scatter buffer size - // - - // Initialize TX Descriptor - // For inter-frame gap, the number is for this frame and next frame - // For MLME rate, we will fix as 2Mb to match other vendor's implement - -// management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. - if (pMacEntry == NULL) - { - RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, - 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); - } - else - { + /* */ + /* fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET */ + /* should always has only one physical buffer, and the whole frame size equals */ + /* to the first scatter buffer size */ + /* */ + + /* Initialize TX Descriptor */ + /* For inter-frame gap, the number is for this frame and next frame */ + /* For MLME rate, we will fix as 2Mb to match other vendor's implement */ +/* pAd->CommonCfg.MlmeTransmit.field.MODE = 1; */ + +/* management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. */ + PID = PID_MGMT; + + if (pMacEntry == NULL) { + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, + FALSE, bAckRequired, FALSE, 0, RESERVED_WCID, + (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID, 0, + (u8)pAd->CommonCfg.MlmeTransmit.field.MCS, + IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); + } else { + /* dont use low rate to send QoS Null data frame */ RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, - bInsertTimestamp, FALSE, bAckRequired, FALSE, - 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), - pMacEntry->MaxHTPhyMode.field.MCS, 0, - (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS, - IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); + bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, pMacEntry->Aid, + (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), + pMacEntry->MaxHTPhyMode.field.MCS, 0, + (u8)pMacEntry->MaxHTPhyMode.field.MCS, + IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); } - // Now do hardware-depened kick out. + /* Now do hardware-depened kick out. */ HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen); - // Make sure to release MGMT ring resource + /* Make sure to release MGMT ring resource */ +/* if (!IrqState) */ RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); return NDIS_STATUS_SUCCESS; } - /******************************************************************************** New DeQueue Procedures. @@ -708,178 +506,153 @@ NDIS_STATUS MlmeHardTransmitMgmtRing( (2).Normal ======================================================================== */ -static UCHAR TxPktClassification( - IN RTMP_ADAPTER *pAd, - IN PNDIS_PACKET pPacket) +static u8 TxPktClassification(struct rt_rtmp_adapter *pAd, void *pPacket) { - UCHAR TxFrameType = TX_UNKOWN_FRAME; - UCHAR Wcid; - MAC_TABLE_ENTRY *pMacEntry = NULL; - BOOLEAN bHTRate = FALSE; + u8 TxFrameType = TX_UNKOWN_FRAME; + u8 Wcid; + struct rt_mac_table_entry *pMacEntry = NULL; + BOOLEAN bHTRate = FALSE; Wcid = RTMP_GET_PACKET_WCID(pPacket); - if (Wcid == MCAST_WCID) - { // Handle for RA is Broadcast/Multicast Address. + if (Wcid == MCAST_WCID) { /* Handle for RA is Broadcast/Multicast Address. */ return TX_MCAST_FRAME; } - - // Handle for unicast packets + /* Handle for unicast packets */ pMacEntry = &pAd->MacTab.Content[Wcid]; - if (RTMP_GET_PACKET_LOWRATE(pPacket)) - { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame + if (RTMP_GET_PACKET_LOWRATE(pPacket)) { /* It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame */ TxFrameType = TX_LEGACY_FRAME; - } - else if (IS_HT_RATE(pMacEntry)) - { // it's a 11n capable packet + } else if (IS_HT_RATE(pMacEntry)) { /* it's a 11n capable packet */ - // Depends on HTPhyMode to check if the peer support the HTRate transmission. - // Currently didn't support A-MSDU embedded in A-MPDU + /* Depends on HTPhyMode to check if the peer support the HTRate transmission. */ + /* Currently didn't support A-MSDU embedded in A-MPDU */ bHTRate = TRUE; - if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE)) - TxFrameType = TX_LEGACY_FRAME; -#ifdef UAPSD_AP_SUPPORT - else if (RTMP_GET_PACKET_EOSP(pPacket)) + if (RTMP_GET_PACKET_MOREDATA(pPacket) + || (pMacEntry->PsMode == PWR_SAVE)) TxFrameType = TX_LEGACY_FRAME; -#endif // UAPSD_AP_SUPPORT // - else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0) + else if ((pMacEntry-> + TXBAbitmap & (1 << (RTMP_GET_PACKET_UP(pPacket)))) != + 0) return TX_AMPDU_FRAME; - else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED)) + else if (CLIENT_STATUS_TEST_FLAG + (pMacEntry, fCLIENT_STATUS_AMSDU_INUSED)) return TX_AMSDU_FRAME; else TxFrameType = TX_LEGACY_FRAME; - } - else - { // it's a legacy b/g packet. - if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) && - (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) && - (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) - { // if peer support Ralink Aggregation, we use it. + } else { /* it's a legacy b/g packet. */ + if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) && (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) { /* if peer support Ralink Aggregation, we use it. */ TxFrameType = TX_RALINK_FRAME; - } - else - { + } else { TxFrameType = TX_LEGACY_FRAME; } } - // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU. - if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME)) + /* Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU. */ + if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) + && (TxFrameType == TX_LEGACY_FRAME)) TxFrameType = TX_FRAG_FRAME; return TxFrameType; } - -BOOLEAN RTMP_FillTxBlkInfo( - IN RTMP_ADAPTER *pAd, - IN TX_BLK *pTxBlk) +BOOLEAN RTMP_FillTxBlkInfo(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk) { - PACKET_INFO PacketInfo; - PNDIS_PACKET pPacket; - PMAC_TABLE_ENTRY pMacEntry = NULL; + struct rt_packet_info PacketInfo; + void *pPacket; + struct rt_mac_table_entry *pMacEntry = NULL; pPacket = pTxBlk->pPacket; - RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, + &pTxBlk->SrcBufLen); - pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket); - pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket); - pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket); - pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap + pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket); + pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket); + pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket); + pTxBlk->FrameGap = IFS_HTTXOP; /* ASIC determine Frame Gap */ if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket)) TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame); else TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame); - // Default to clear this flag + /* Default to clear this flag */ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS); - - if (pTxBlk->Wcid == MCAST_WCID) - { + if (pTxBlk->Wcid == MCAST_WCID) { pTxBlk->pMacEntry = NULL; { -#ifdef MCAST_RATE_SPECIFIC - PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket); - if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff)) - pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode; - else -#endif // MCAST_RATE_SPECIFIC // - pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; + pTxBlk->pTransmit = + &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; } - TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode. - //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate); + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); /* AckRequired = FALSE, when broadcast packet in Adhoc mode. */ + /*TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate); */ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag); TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); - if (RTMP_GET_PACKET_MOREDATA(pPacket)) - { + if (RTMP_GET_PACKET_MOREDATA(pPacket)) { TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); } - } - else - { + } else { pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid]; pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode; pMacEntry = pTxBlk->pMacEntry; - - // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK. + /* For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK. */ if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK) TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); else TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired); - { - // If support WMM, enable it. -#ifdef RT2860 - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) -#endif -#ifdef RT2870 - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && - CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) -#endif - TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM); + if ((pAd->OpMode == OPMODE_STA) && + (ADHOC_ON(pAd)) && + (RX_FILTER_TEST_FLAG(pAd, fRX_FILTER_ACCEPT_PROMISCUOUS))) { + if (pAd->CommonCfg.PSPXlink) + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); } - if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) { - if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) || - ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1))) - { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate. - pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; + { + + /* If support WMM, enable it. */ + if (OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_WMM_INUSED) + && CLIENT_STATUS_TEST_FLAG(pMacEntry, + fCLIENT_STATUS_WMM_CAPABLE)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM); + +/* if (pAd->StaCfg.bAutoTxRateSwitch) */ +/* TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch); */ + } + } - // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it??? + if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) { + if ((RTMP_GET_PACKET_LOWRATE(pPacket)) || ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1))) { /* Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate. */ + pTxBlk->pTransmit = + &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; + + /* Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it??? */ if (IS_HT_STA(pTxBlk->pMacEntry) && - (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) && - ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))) + (CLIENT_STATUS_TEST_FLAG + (pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) + && ((pAd->CommonCfg.bRdg == TRUE) + && CLIENT_STATUS_TEST_FLAG(pMacEntry, + fCLIENT_STATUS_RDG_CAPABLE))) { TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); - TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS); + TX_BLK_SET_FLAG(pTxBlk, + fTX_bForceNonQoS); } } - if ( (IS_HT_RATE(pMacEntry) == FALSE) && - (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE))) - { // Currently piggy-back only support when peer is operate in b/g mode. + if ((IS_HT_RATE(pMacEntry) == FALSE) && (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE))) { /* Currently piggy-back only support when peer is operate in b/g mode. */ TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack); } - if (RTMP_GET_PACKET_MOREDATA(pPacket)) - { + if (RTMP_GET_PACKET_MOREDATA(pPacket)) { TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); } -#ifdef UAPSD_AP_SUPPORT - if (RTMP_GET_PACKET_EOSP(pPacket)) - { - TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP); - } -#endif // UAPSD_AP_SUPPORT // - } - else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) - { + } else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) { TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag); } @@ -889,41 +662,33 @@ BOOLEAN RTMP_FillTxBlkInfo( return TRUE; } - -BOOLEAN CanDoAggregateTransmit( - IN RTMP_ADAPTER *pAd, - IN NDIS_PACKET *pPacket, - IN TX_BLK *pTxBlk) +BOOLEAN CanDoAggregateTransmit(struct rt_rtmp_adapter *pAd, + char * pPacket, struct rt_tx_blk *pTxBlk) { - //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType); + /*DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType)); */ if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID) return FALSE; if (RTMP_GET_PACKET_DHCP(pPacket) || - RTMP_GET_PACKET_EAPOL(pPacket) || - RTMP_GET_PACKET_WAI(pPacket)) + RTMP_GET_PACKET_EAPOL(pPacket) || RTMP_GET_PACKET_WAI(pPacket)) return FALSE; - if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) && - ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100))) - { // For AMSDU, allow the packets with total length < max-amsdu size + if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) && ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket)) > (RX_BUFFER_AGGRESIZE - 100))) { /* For AMSDU, allow the packets with total length < max-amsdu size */ return FALSE; } - if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && - (pTxBlk->TxPacketList.Number == 2)) - { // For RALINK-Aggregation, allow two frames in one batch. + if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && (pTxBlk->TxPacketList.Number == 2)) { /* For RALINK-Aggregation, allow two frames in one batch. */ return FALSE; } - if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP + if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) /* must be unicast to AP */ return TRUE; else return FALSE; -} +} /* ======================================================================== @@ -947,53 +712,42 @@ BOOLEAN CanDoAggregateTransmit( ======================================================================== */ -VOID RTMPDeQueuePacket( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bIntContext, - IN UCHAR QIdx, /* BulkOutPipeId */ - IN UCHAR Max_Tx_Packets) +void RTMPDeQueuePacket(struct rt_rtmp_adapter *pAd, IN BOOLEAN bIntContext, u8 QIdx, /* BulkOutPipeId */ + u8 Max_Tx_Packets) { - PQUEUE_ENTRY pEntry = NULL; - PNDIS_PACKET pPacket; - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - UCHAR Count=0; - PQUEUE_HEADER pQueue; - ULONG FreeNumber[NUM_OF_TX_RING]; - UCHAR QueIdx, sQIdx, eQIdx; - unsigned long IrqFlags = 0; - BOOLEAN hasTxDesc = FALSE; - TX_BLK TxBlk; - TX_BLK *pTxBlk; - - - - if (QIdx == NUM_OF_TX_RING) - { + struct rt_queue_entry *pEntry = NULL; + void *pPacket; + int Status = NDIS_STATUS_SUCCESS; + u8 Count = 0; + struct rt_queue_header *pQueue; + unsigned long FreeNumber[NUM_OF_TX_RING]; + u8 QueIdx, sQIdx, eQIdx; + unsigned long IrqFlags = 0; + BOOLEAN hasTxDesc = FALSE; + struct rt_tx_blk TxBlk; + struct rt_tx_blk *pTxBlk; + + if (QIdx == NUM_OF_TX_RING) { sQIdx = 0; -//PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) - eQIdx = 3; // 4 ACs, start from 0. - } - else - { + eQIdx = 3; /* 4 ACs, start from 0. */ + } else { sQIdx = eQIdx = QIdx; } - for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++) - { - Count=0; - - RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags); + for (QueIdx = sQIdx; QueIdx <= eQIdx; QueIdx++) { + Count = 0; + RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags); - while (1) - { - if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS | - fRTMP_ADAPTER_RADIO_OFF | - fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_NIC_NOT_EXIST)))) - { - RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); + while (1) { + if ((RTMP_TEST_FLAG + (pAd, + (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS | + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) { + RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); return; } @@ -1001,43 +755,47 @@ VOID RTMPDeQueuePacket( break; DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags); - if (&pAd->TxSwQueue[QueIdx] == NULL) - { - DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + if (&pAd->TxSwQueue[QueIdx] == NULL) { + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, + IrqFlags); break; } -#ifdef RT2860 +#ifdef RTMP_MAC_PCI FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); - - if (FreeNumber[QueIdx] <= 5) - { - // free Tx(QueIdx) resources + if (FreeNumber[QueIdx] <= 5) { + /* free Tx(QueIdx) resources */ RTMPFreeTXDUponTxDmaDone(pAd, QueIdx); - FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); + FreeNumber[QueIdx] = + GET_TXRING_FREENO(pAd, QueIdx); } -#endif /* RT2860 */ - // probe the Queue Head +#endif /* RTMP_MAC_PCI // */ + + /* probe the Queue Head */ pQueue = &pAd->TxSwQueue[QueIdx]; - if ((pEntry = pQueue->Head) == NULL) - { - DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + if ((pEntry = pQueue->Head) == NULL) { + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, + IrqFlags); break; } pTxBlk = &TxBlk; - NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK)); + NdisZeroMemory((u8 *)pTxBlk, sizeof(struct rt_tx_blk)); + /*InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it. */ pTxBlk->QueIdx = QueIdx; - pPacket = QUEUE_ENTRY_TO_PKT(pEntry); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); - // Early check to make sure we have enoguh Tx Resource. - hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); - if (!hasTxDesc) - { + /* Early check to make sure we have enoguh Tx Resource. */ + hasTxDesc = + RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, + FreeNumber[QueIdx], + pPacket); + if (!hasTxDesc) { pAd->PrivateInfo.TxRingFullCnt++; - DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, + IrqFlags); break; } @@ -1045,74 +803,89 @@ VOID RTMPDeQueuePacket( pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket); pEntry = RemoveHeadQueue(pQueue); pTxBlk->TotalFrameNum++; - pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary + pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary */ pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); pTxBlk->pPacket = pPacket; - InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); - - if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME) - { - // Enhance SW Aggregation Mechanism - if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType)) - { - InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); - DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + InsertTailQueue(&pTxBlk->TxPacketList, + PACKET_TO_QUEUE_ENTRY(pPacket)); + + if (pTxBlk->TxFrameType == TX_RALINK_FRAME + || pTxBlk->TxFrameType == TX_AMSDU_FRAME) { + /* Enhance SW Aggregation Mechanism */ + if (NEED_QUEUE_BACK_FOR_AGG + (pAd, QueIdx, FreeNumber[QueIdx], + pTxBlk->TxFrameType)) { + InsertHeadQueue(pQueue, + PACKET_TO_QUEUE_ENTRY + (pPacket)); + DEQUEUE_UNLOCK(&pAd->irq_lock, + bIntContext, IrqFlags); break; } - do{ - if((pEntry = pQueue->Head) == NULL) + do { + if ((pEntry = pQueue->Head) == NULL) break; - // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. - pPacket = QUEUE_ENTRY_TO_PKT(pEntry); - FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); - hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); - if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE)) + /* For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. */ + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + FreeNumber[QueIdx] = + GET_TXRING_FREENO(pAd, QueIdx); + hasTxDesc = + RTMP_HAS_ENOUGH_FREE_DESC(pAd, + pTxBlk, + FreeNumber + [QueIdx], + pPacket); + if ((hasTxDesc == FALSE) + || + (CanDoAggregateTransmit + (pAd, pPacket, pTxBlk) == FALSE)) break; - //Remove the packet from the TxSwQueue and insert into pTxBlk + /*Remove the packet from the TxSwQueue and insert into pTxBlk */ pEntry = RemoveHeadQueue(pQueue); ASSERT(pEntry); - pPacket = QUEUE_ENTRY_TO_PKT(pEntry); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); pTxBlk->TotalFrameNum++; - pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary - pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); - InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); - }while(1); + pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary */ + pTxBlk->TotalFrameLen += + GET_OS_PKT_LEN(pPacket); + InsertTailQueue(&pTxBlk->TxPacketList, + PACKET_TO_QUEUE_ENTRY + (pPacket)); + } while (1); if (pTxBlk->TxPacketList.Number == 1) pTxBlk->TxFrameType = TX_LEGACY_FRAME; } - -#ifdef RT2870 +#ifdef RTMP_MAC_USB DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); -#endif // RT2870 // - +#endif /* RTMP_MAC_USB // */ Count += pTxBlk->TxPacketList.Number; - // Do HardTransmit now. + /* Do HardTransmit now. */ Status = STAHardTransmit(pAd, pTxBlk, QueIdx); -#ifdef RT2860 +#ifdef RTMP_MAC_PCI DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); - // static rate also need NICUpdateFifoStaCounters() function. - //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) - NICUpdateFifoStaCounters(pAd); -#endif + /* static rate also need NICUpdateFifoStaCounters() function. */ + /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ + NICUpdateFifoStaCounters(pAd); +#endif /* RTMP_MAC_PCI // */ + } - RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); + RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); -#ifdef RT2870 +#ifdef RTMP_MAC_USB if (!hasTxDesc) RTUSBKickBulkOut(pAd); -#endif // RT2870 // +#endif /* RTMP_MAC_USB // */ } } - /* ======================================================================== @@ -1135,40 +908,37 @@ VOID RTMPDeQueuePacket( ======================================================================== */ -USHORT RTMPCalcDuration( - IN PRTMP_ADAPTER pAd, - IN UCHAR Rate, - IN ULONG Size) +u16 RTMPCalcDuration(struct rt_rtmp_adapter *pAd, u8 Rate, unsigned long Size) { - ULONG Duration = 0; + unsigned long Duration = 0; - if (Rate < RATE_FIRST_OFDM_RATE) // CCK + if (Rate < RATE_FIRST_OFDM_RATE) /* CCK */ { - if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)) - Duration = 96; // 72+24 preamble+plcp + if ((Rate > RATE_1) + && OPSTATUS_TEST_FLAG(pAd, + fOP_STATUS_SHORT_PREAMBLE_INUSED)) + Duration = 96; /* 72+24 preamble+plcp */ else - Duration = 192; // 144+48 preamble+plcp + Duration = 192; /* 144+48 preamble+plcp */ - Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]); + Duration += (u16)((Size << 4) / RateIdTo500Kbps[Rate]); if ((Size << 4) % RateIdTo500Kbps[Rate]) - Duration ++; - } - else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates + Duration++; + } else if (Rate <= RATE_LAST_OFDM_RATE) /* OFDM rates */ { - Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension - Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]); + Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */ + Duration += + 4 * (u16)((11 + Size * 4) / RateIdTo500Kbps[Rate]); if ((11 + Size * 4) % RateIdTo500Kbps[Rate]) Duration += 4; - } - else //mimo rate + } else /*mimo rate */ { - Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension + Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */ } - return (USHORT)Duration; + return (u16)Duration; } - /* ======================================================================== @@ -1194,58 +964,53 @@ USHORT RTMPCalcDuration( IRQL = PASSIVE_LEVEL IRQL = DISPATCH_LEVEL - See also : BASmartHardTransmit() !!! + See also : BASmartHardTransmit() ! ======================================================================== */ -VOID RTMPWriteTxWI( - IN PRTMP_ADAPTER pAd, - IN PTXWI_STRUC pOutTxWI, - IN BOOLEAN FRAG, - IN BOOLEAN CFACK, - IN BOOLEAN InsTimestamp, - IN BOOLEAN AMPDU, - IN BOOLEAN Ack, - IN BOOLEAN NSeq, // HW new a sequence. - IN UCHAR BASize, - IN UCHAR WCID, - IN ULONG Length, - IN UCHAR PID, - IN UCHAR TID, - IN UCHAR TxRate, - IN UCHAR Txopmode, - IN BOOLEAN CfAck, - IN HTTRANSMIT_SETTING *pTransmit) +void RTMPWriteTxWI(struct rt_rtmp_adapter *pAd, struct rt_txwi * pOutTxWI, IN BOOLEAN FRAG, IN BOOLEAN CFACK, IN BOOLEAN InsTimestamp, IN BOOLEAN AMPDU, IN BOOLEAN Ack, IN BOOLEAN NSeq, /* HW new a sequence. */ + u8 BASize, + u8 WCID, + unsigned long Length, + u8 PID, + u8 TID, + u8 TxRate, + u8 Txopmode, + IN BOOLEAN CfAck, IN HTTRANSMIT_SETTING * pTransmit) { - PMAC_TABLE_ENTRY pMac = NULL; - TXWI_STRUC TxWI; - PTXWI_STRUC pTxWI; + struct rt_mac_table_entry *pMac = NULL; + struct rt_txwi TxWI; + struct rt_txwi * pTxWI; if (WCID < MAX_LEN_OF_MAC_TABLE) pMac = &pAd->MacTab.Content[WCID]; - // - // Always use Long preamble before verifiation short preamble functionality works well. - // Todo: remove the following line if short preamble functionality works - // + /* */ + /* Always use Long preamble before verifiation short preamble functionality works well. */ + /* Todo: remove the following line if short preamble functionality works */ + /* */ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); NdisZeroMemory(&TxWI, TXWI_SIZE); pTxWI = &TxWI; - pTxWI->FRAG= FRAG; + pTxWI->FRAG = FRAG; pTxWI->CFACK = CFACK; - pTxWI->TS= InsTimestamp; + pTxWI->TS = InsTimestamp; pTxWI->AMPDU = AMPDU; pTxWI->ACK = Ack; - pTxWI->txop= Txopmode; + pTxWI->txop = Txopmode; pTxWI->NSEQ = NSeq; - // John tune the performace with Intel Client in 20 MHz performance + /* John tune the performace with Intel Client in 20 MHz performance */ BASize = pAd->CommonCfg.TxBASize; - - if( BASize >7 ) - BASize =7; + if (pAd->MACVersion == 0x28720200) { + if (BASize > 13) + BASize = 13; + } else { + if (BASize > 7) + BASize = 7; + } pTxWI->BAWinSize = BASize; pTxWI->ShortGI = pTransmit->field.ShortGI; pTxWI->STBC = pTransmit->field.STBC; @@ -1254,90 +1019,84 @@ VOID RTMPWriteTxWI( pTxWI->MPDUtotalByteCount = Length; pTxWI->PacketId = PID; - // If CCK or OFDM, BW must be 20 - pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + /* If CCK or OFDM, BW must be 20 */ + pTxWI->BW = + (pTransmit->field.MODE <= + MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); pTxWI->MCS = pTransmit->field.MCS; pTxWI->PHYMODE = pTransmit->field.MODE; pTxWI->CFACK = CfAck; - if (pMac) - { - if (pAd->CommonCfg.bMIMOPSEnable) - { - if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) - { - // Dynamic MIMO Power Save Mode + if (pMac) { + if (pAd->CommonCfg.bMIMOPSEnable) { + if ((pMac->MmpsMode == MMPS_DYNAMIC) + && (pTransmit->field.MCS > 7)) { + /* Dynamic MIMO Power Save Mode */ pTxWI->MIMOps = 1; - } - else if (pMac->MmpsMode == MMPS_STATIC) - { - // Static MIMO Power Save Mode - if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) - { + } else if (pMac->MmpsMode == MMPS_STATIC) { + /* Static MIMO Power Save Mode */ + if (pTransmit->field.MODE >= MODE_HTMIX + && pTransmit->field.MCS > 7) { pTxWI->MCS = 7; pTxWI->MIMOps = 0; } } } - //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; - if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled)) - { + /*pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; */ + if (pMac->bIAmBadAtheros + && (pMac->WepStatus != Ndis802_11WEPDisabled)) { pTxWI->MpduDensity = 7; - } - else - { + } else { pTxWI->MpduDensity = pMac->MpduDensity; } } pTxWI->PacketId = pTxWI->MCS; - NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC)); + NdisMoveMemory(pOutTxWI, &TxWI, sizeof(struct rt_txwi)); } - -VOID RTMPWriteTxWI_Data( - IN PRTMP_ADAPTER pAd, - IN OUT PTXWI_STRUC pTxWI, - IN TX_BLK *pTxBlk) +void RTMPWriteTxWI_Data(struct rt_rtmp_adapter *pAd, + struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk) { - HTTRANSMIT_SETTING *pTransmit; - PMAC_TABLE_ENTRY pMacEntry; - UCHAR BASize; + HTTRANSMIT_SETTING *pTransmit; + struct rt_mac_table_entry *pMacEntry; + u8 BASize; ASSERT(pTxWI); pTransmit = pTxBlk->pTransmit; pMacEntry = pTxBlk->pMacEntry; - - // - // Always use Long preamble before verifiation short preamble functionality works well. - // Todo: remove the following line if short preamble functionality works - // + /* */ + /* Always use Long preamble before verifiation short preamble functionality works well. */ + /* Todo: remove the following line if short preamble functionality works */ + /* */ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); NdisZeroMemory(pTxWI, TXWI_SIZE); - pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); - pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); - pTxWI->txop = pTxBlk->FrameGap; + pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); + pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); + pTxWI->txop = pTxBlk->FrameGap; - pTxWI->WirelessCliID = pTxBlk->Wcid; + pTxWI->WirelessCliID = pTxBlk->Wcid; - pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; - pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); + pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); - // If CCK or OFDM, BW must be 20 - pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); - pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE); + /* If CCK or OFDM, BW must be 20 */ + pTxWI->BW = + (pTransmit->field.MODE <= + MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE); - // John tune the performace with Intel Client in 20 MHz performance + /* John tune the performace with Intel Client in 20 MHz performance */ BASize = pAd->CommonCfg.TxBASize; - if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) - { - UCHAR RABAOriIdx = 0; //The RA's BA Originator table index. + if ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) { + u8 RABAOriIdx = 0; /*The RA's BA Originator table index. */ - RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; + RABAOriIdx = + pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize; } @@ -1349,549 +1108,198 @@ VOID RTMPWriteTxWI_Data( pTxWI->MCS = pTransmit->field.MCS; pTxWI->PHYMODE = pTransmit->field.MODE; - if (pMacEntry) - { - if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) - { - // Dynamic MIMO Power Save Mode + if (pMacEntry) { + if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) + && (pTransmit->field.MCS > 7)) { + /* Dynamic MIMO Power Save Mode */ pTxWI->MIMOps = 1; - } - else if (pMacEntry->MmpsMode == MMPS_STATIC) - { - // Static MIMO Power Save Mode - if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) - { + } else if (pMacEntry->MmpsMode == MMPS_STATIC) { + /* Static MIMO Power Save Mode */ + if (pTransmit->field.MODE >= MODE_HTMIX + && pTransmit->field.MCS > 7) { pTxWI->MCS = 7; pTxWI->MIMOps = 0; } } - if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) - { + if (pMacEntry->bIAmBadAtheros + && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) { pTxWI->MpduDensity = 7; - } - else - { + } else { pTxWI->MpduDensity = pMacEntry->MpduDensity; } } - - // for rate adapation + /* for rate adapation */ pTxWI->PacketId = pTxWI->MCS; } - -VOID RTMPWriteTxWI_Cache( - IN PRTMP_ADAPTER pAd, - IN OUT PTXWI_STRUC pTxWI, - IN TX_BLK *pTxBlk) +void RTMPWriteTxWI_Cache(struct rt_rtmp_adapter *pAd, + struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk) { - PHTTRANSMIT_SETTING pTransmit; - PMAC_TABLE_ENTRY pMacEntry; + PHTTRANSMIT_SETTING /*pTxHTPhyMode, */ pTransmit; + struct rt_mac_table_entry *pMacEntry; - // - // update TXWI - // + /* */ + /* update TXWI */ + /* */ pMacEntry = pTxBlk->pMacEntry; - pTransmit = pTxBlk->pTransmit; - - if (pMacEntry->bAutoTxRateSwitch) - { - pTxWI->txop = IFS_HTTXOP; - - // If CCK or OFDM, BW must be 20 - pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); - pTxWI->ShortGI = pTransmit->field.ShortGI; - pTxWI->STBC = pTransmit->field.STBC; - - pTxWI->MCS = pTransmit->field.MCS; - pTxWI->PHYMODE = pTransmit->field.MODE; - - // set PID for TxRateSwitching - pTxWI->PacketId = pTransmit->field.MCS; - } - - pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE); - pTxWI->MIMOps = 0; - - if (pAd->CommonCfg.bMIMOPSEnable) - { - // MIMO Power Save Mode - if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) - { - // Dynamic MIMO Power Save Mode - pTxWI->MIMOps = 1; - } - else if (pMacEntry->MmpsMode == MMPS_STATIC) - { - // Static MIMO Power Save Mode - if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7)) - { - pTxWI->MCS = 7; - pTxWI->MIMOps = 0; - } - } - } - - - pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; - -} - - -/* - ======================================================================== - - Routine Description: - Calculates the duration which is required to transmit out frames - with given size and specified rate. - - Arguments: - pTxD Pointer to transmit descriptor - Ack Setting for Ack requirement bit - Fragment Setting for Fragment bit - RetryMode Setting for retry mode - Ifs Setting for IFS gap - Rate Setting for transmit rate - Service Setting for service - Length Frame length - TxPreamble Short or Long preamble when using CCK rates - QueIdx - 0-3, according to 802.11e/d4.4 June/2003 - - Return Value: - None - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - ======================================================================== -*/ -VOID RTMPWriteTxDescriptor( - IN PRTMP_ADAPTER pAd, - IN PTXD_STRUC pTxD, - IN BOOLEAN bWIV, - IN UCHAR QueueSEL) -{ - // - // Always use Long preamble before verifiation short preamble functionality works well. - // Todo: remove the following line if short preamble functionality works - // - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); - - pTxD->WIV = (bWIV) ? 1: 0; - pTxD->QSEL= (QueueSEL); - if (pAd->bGenOneHCCA == TRUE) - pTxD->QSEL= FIFO_HCCA; - pTxD->DMADONE = 0; -} - - -// should be called only when - -// 1. MEADIA_CONNECTED -// 2. AGGREGATION_IN_USED -// 3. Fragmentation not in used -// 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible -BOOLEAN TxFrameIsAggregatible( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pPrevAddr1, - IN PUCHAR p8023hdr) -{ - - // can't aggregate EAPOL (802.1x) frame - if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e)) - return FALSE; - - // can't aggregate multicast/broadcast frame - if (p8023hdr[0] & 0x01) - return FALSE; - - if (INFRA_ON(pAd)) // must be unicast to AP - return TRUE; - else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA - return TRUE; - else - return FALSE; -} - - -/* - ======================================================================== - - Routine Description: - Check the MSDU Aggregation policy - 1.HT aggregation is A-MSDU - 2.legaacy rate aggregation is software aggregation by Ralink. - - Arguments: - - Return Value: - - Note: - - ======================================================================== -*/ -BOOLEAN PeerIsAggreOn( - IN PRTMP_ADAPTER pAd, - IN ULONG TxRate, - IN PMAC_TABLE_ENTRY pMacEntry) -{ - ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE); - - if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) - { - if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) - { - return TRUE; - } - -#ifdef AGGREGATION_SUPPORT - if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) - { // legacy Ralink Aggregation support - return TRUE; - } -#endif // AGGREGATION_SUPPORT // - } - - return FALSE; - -} - - -/* - ======================================================================== - - Routine Description: - Check and fine the packet waiting in SW queue with highest priority - - Arguments: - pAd Pointer to our adapter - - Return Value: - pQueue Pointer to Waiting Queue - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -PQUEUE_HEADER RTMPCheckTxSwQueue( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pQueIdx) -{ - - ULONG Number; - - Number = pAd->TxSwQueue[QID_AC_BK].Number - + pAd->TxSwQueue[QID_AC_BE].Number - + pAd->TxSwQueue[QID_AC_VI].Number - + pAd->TxSwQueue[QID_AC_VO].Number - + pAd->TxSwQueue[QID_HCCA].Number; - - if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) - { - *pQueIdx = QID_AC_VO; - return (&pAd->TxSwQueue[QID_AC_VO]); - } - else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) - { - *pQueIdx = QID_AC_VI; - return (&pAd->TxSwQueue[QID_AC_VI]); - } - else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) - { - *pQueIdx = QID_AC_BE; - return (&pAd->TxSwQueue[QID_AC_BE]); - } - else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) - { - *pQueIdx = QID_AC_BK; - return (&pAd->TxSwQueue[QID_AC_BK]); - } - else if (pAd->TxSwQueue[QID_HCCA].Head != NULL) - { - *pQueIdx = QID_HCCA; - return (&pAd->TxSwQueue[QID_HCCA]); - } - - // No packet pending in Tx Sw queue - *pQueIdx = QID_AC_BK; - - return (NULL); -} - -#ifdef RT2860 -BOOLEAN RTMPFreeTXDUponTxDmaDone( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx) -{ - PRTMP_TX_RING pTxRing; - PTXD_STRUC pTxD; - PNDIS_PACKET pPacket; - UCHAR FREE = 0; - TXD_STRUC TxD, *pOriTxD; - //ULONG IrqFlags; - BOOLEAN bReschedule = FALSE; - - - ASSERT(QueIdx < NUM_OF_TX_RING); - pTxRing = &pAd->TxRing[QueIdx]; - - RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx); - while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx) - { - // static rate also need NICUpdateFifoStaCounters() function. - //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) - NICUpdateFifoStaCounters(pAd); - - /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */ - FREE++; - pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); - pOriTxD = pTxD; - NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); - pTxD = &TxD; - - pTxD->DMADONE = 0; - -/*====================================================================*/ - { - pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket; - if (pPacket) - { -#ifdef CONFIG_5VT_ENHANCE - if (RTMP_GET_PACKET_5VT(pPacket)) - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE); - else -#endif // CONFIG_5VT_ENHANCE // - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - //Always assign pNdisPacket as NULL after clear - pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL; - - pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket; - - ASSERT(pPacket == NULL); - if (pPacket) - { -#ifdef CONFIG_5VT_ENHANCE - if (RTMP_GET_PACKET_5VT(pPacket)) - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE); - else -#endif // CONFIG_5VT_ENHANCE // - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - //Always assign pNextNdisPacket as NULL after clear - pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; - } -/*====================================================================*/ - - pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); - pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; - INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); - /* get tx_tdx_idx again */ - RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx); - - NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); - } - - - return bReschedule; - -} - - -/* - ======================================================================== - - Routine Description: - Process TX Rings DMA Done interrupt, running in DPC level - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None + pTransmit = pTxBlk->pTransmit; - IRQL = DISPATCH_LEVEL + /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ + /*if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry)) */ + /*if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch)) */ + if (pMacEntry->bAutoTxRateSwitch) { + pTxWI->txop = IFS_HTTXOP; - ======================================================================== -*/ -BOOLEAN RTMPHandleTxRingDmaDoneInterrupt( - IN PRTMP_ADAPTER pAd, - IN INT_SOURCE_CSR_STRUC TxRingBitmap) -{ - unsigned long IrqFlags; - BOOLEAN bReschedule = FALSE; + /* If CCK or OFDM, BW must be 20 */ + pTxWI->BW = + (pTransmit->field.MODE <= + MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + pTxWI->ShortGI = pTransmit->field.ShortGI; + pTxWI->STBC = pTransmit->field.STBC; - // Make sure Tx ring resource won't be used by other threads + pTxWI->MCS = pTransmit->field.MCS; + pTxWI->PHYMODE = pTransmit->field.MODE; - RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + /* set PID for TxRateSwitching */ + pTxWI->PacketId = pTransmit->field.MCS; + } - if (TxRingBitmap.field.Ac0DmaDone) - bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE); + pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE : FALSE); + pTxWI->MIMOps = 0; - if (TxRingBitmap.field.HccaDmaDone) - bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA); + if (pAd->CommonCfg.bMIMOPSEnable) { + /* MIMO Power Save Mode */ + if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) + && (pTransmit->field.MCS > 7)) { + /* Dynamic MIMO Power Save Mode */ + pTxWI->MIMOps = 1; + } else if (pMacEntry->MmpsMode == MMPS_STATIC) { + /* Static MIMO Power Save Mode */ + if ((pTransmit->field.MODE >= MODE_HTMIX) + && (pTransmit->field.MCS > 7)) { + pTxWI->MCS = 7; + pTxWI->MIMOps = 0; + } + } + } - if (TxRingBitmap.field.Ac3DmaDone) - bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO); + pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; - if (TxRingBitmap.field.Ac2DmaDone) - bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI); +} - if (TxRingBitmap.field.Ac1DmaDone) - bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK); +/* should be called only when - */ +/* 1. MEADIA_CONNECTED */ +/* 2. AGGREGATION_IN_USED */ +/* 3. Fragmentation not in used */ +/* 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible */ +BOOLEAN TxFrameIsAggregatible(struct rt_rtmp_adapter *pAd, + u8 *pPrevAddr1, u8 *p8023hdr) +{ - // Make sure to release Tx ring resource - RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + /* can't aggregate EAPOL (802.1x) frame */ + if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e)) + return FALSE; - // Dequeue outgoing frames from TxSwQueue[] and process it - RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + /* can't aggregate multicast/broadcast frame */ + if (p8023hdr[0] & 0x01) + return FALSE; - return bReschedule; + if (INFRA_ON(pAd)) /* must be unicast to AP */ + return TRUE; + else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) /* unicast to same STA */ + return TRUE; + else + return FALSE; } - /* ======================================================================== Routine Description: - Process MGMT ring DMA done interrupt, running in DPC level + Check the MSDU Aggregation policy + 1.HT aggregation is A-MSDU + 2.legaacy rate aggregation is software aggregation by Ralink. Arguments: - pAd Pointer to our adapter Return Value: - None - - IRQL = DISPATCH_LEVEL Note: ======================================================================== */ -VOID RTMPHandleMgmtRingDmaDoneInterrupt( - IN PRTMP_ADAPTER pAd) +BOOLEAN PeerIsAggreOn(struct rt_rtmp_adapter *pAd, + unsigned long TxRate, struct rt_mac_table_entry *pMacEntry) { - PTXD_STRUC pTxD; - PNDIS_PACKET pPacket; - UCHAR FREE = 0; - PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; - - NdisAcquireSpinLock(&pAd->MgmtRingLock); + unsigned long AFlags = + (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE); - RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx); - while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx) - { - FREE++; - pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa); - pTxD->DMADONE = 0; - pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket; - - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) { + if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) { + return TRUE; } - pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL; - - pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket; - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); +#ifdef AGGREGATION_SUPPORT + if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) { /* legacy Ralink Aggregation support */ + return TRUE; } - pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL; - INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE); +#endif /* AGGREGATION_SUPPORT // */ } - NdisReleaseSpinLock(&pAd->MgmtRingLock); - -} - - -/* - ======================================================================== - - Routine Description: - Arguments: - Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon. - IRQL = DISPATCH_LEVEL + return FALSE; - ======================================================================== -*/ -VOID RTMPHandleTBTTInterrupt( - IN PRTMP_ADAPTER pAd) -{ - { - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - } - } } - /* ======================================================================== Routine Description: + Check and fine the packet waiting in SW queue with highest priority + Arguments: - Adapter Pointer to our adapter. Rewrite beacon content before next send-out. + pAd Pointer to our adapter + + Return Value: + pQueue Pointer to Waiting Queue IRQL = DISPATCH_LEVEL + Note: + ======================================================================== */ -VOID RTMPHandlePreTBTTInterrupt( - IN PRTMP_ADAPTER pAd) +struct rt_queue_header *RTMPCheckTxSwQueue(struct rt_rtmp_adapter *pAd, u8 *pQueIdx) { - { - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n")); - } - } + unsigned long Number; + /* 2004-11-15 to be removed. test aggregation only */ +/* if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2)) */ +/* return NULL; */ -} - -VOID RTMPHandleRxCoherentInterrupt( - IN PRTMP_ADAPTER pAd) -{ - WPDMA_GLO_CFG_STRUC GloCfg; + Number = pAd->TxSwQueue[QID_AC_BK].Number + + pAd->TxSwQueue[QID_AC_BE].Number + + pAd->TxSwQueue[QID_AC_VI].Number + + pAd->TxSwQueue[QID_AC_VO].Number; - if (pAd == NULL) - { - DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n")); - return; + if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) { + *pQueIdx = QID_AC_VO; + return (&pAd->TxSwQueue[QID_AC_VO]); + } else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) { + *pQueIdx = QID_AC_VI; + return (&pAd->TxSwQueue[QID_AC_VI]); + } else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) { + *pQueIdx = QID_AC_BE; + return (&pAd->TxSwQueue[QID_AC_BE]); + } else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) { + *pQueIdx = QID_AC_BK; + return (&pAd->TxSwQueue[QID_AC_BK]); } + /* No packet pending in Tx Sw queue */ + *pQueIdx = QID_AC_BK; - DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n")); - - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word); - - GloCfg.field.EnTXWriteBackDDONE = 0; - GloCfg.field.EnableRxDMA = 0; - GloCfg.field.EnableTxDMA = 0; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); - - RTMPRingCleanUp(pAd, QID_AC_BE); - RTMPRingCleanUp(pAd, QID_AC_BK); - RTMPRingCleanUp(pAd, QID_AC_VI); - RTMPRingCleanUp(pAd, QID_AC_VO); - RTMPRingCleanUp(pAd, QID_HCCA); - RTMPRingCleanUp(pAd, QID_MGMT); - RTMPRingCleanUp(pAd, QID_RX); - - RTMPEnableRxTx(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n")); + return (NULL); } -#endif /* RT2860 */ /* ======================================================================== @@ -1909,25 +1317,25 @@ VOID RTMPHandleRxCoherentInterrupt( ======================================================================== */ -VOID RTMPSuspendMsduTransmission( - IN PRTMP_ADAPTER pAd) +void RTMPSuspendMsduTransmission(struct rt_rtmp_adapter *pAd) { - DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n")); - + DBGPRINT(RT_DEBUG_TRACE, ("SCANNING, suspend MSDU transmission ...\n")); - // - // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and - // use Lowbound as R66 value on ScanNextChannel(...) - // - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue); + /* */ + /* Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and */ + /* use Lowbound as R66 value on ScanNextChannel(...) */ + /* */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, + &pAd->BbpTuning.R66CurrentValue); - // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning) + /* set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning) */ + /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); */ RTMPSetAGCInitValue(pAd, BW_20); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + /*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings */ } - /* ======================================================================== @@ -1946,141 +1354,145 @@ VOID RTMPSuspendMsduTransmission( ======================================================================== */ -VOID RTMPResumeMsduTransmission( - IN PRTMP_ADAPTER pAd) +void RTMPResumeMsduTransmission(struct rt_rtmp_adapter *pAd) { - DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n")); +/* u8 IrqState; */ - // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value - // R66 should not be 0 - if (pAd->BbpTuning.R66CurrentValue == 0) - { + DBGPRINT(RT_DEBUG_TRACE, ("SCAN done, resume MSDU transmission ...\n")); + + /* After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value */ + /* R66 should not be 0 */ + if (pAd->BbpTuning.R66CurrentValue == 0) { pAd->BbpTuning.R66CurrentValue = 0x38; DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n")); } - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, + pAd->BbpTuning.R66CurrentValue); RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); +/* sample, for IRQ LOCK to SEM LOCK */ +/* IrqState = pAd->irq_disabled; */ +/* if (IrqState) */ +/* RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); */ +/* else */ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); } - -UINT deaggregate_AMSDU_announce( - IN PRTMP_ADAPTER pAd, - PNDIS_PACKET pPacket, - IN PUCHAR pData, - IN ULONG DataSize) +u32 deaggregate_AMSDU_announce(struct rt_rtmp_adapter *pAd, + void *pPacket, + u8 *pData, unsigned long DataSize) { - USHORT PayloadSize; - USHORT SubFrameSize; - PHEADER_802_3 pAMSDUsubheader; - UINT nMSDU; - UCHAR Header802_3[14]; - - PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP; - PNDIS_PACKET pClonePacket; - + u16 PayloadSize; + u16 SubFrameSize; + struct rt_header_802_3 * pAMSDUsubheader; + u32 nMSDU; + u8 Header802_3[14]; + u8 *pPayload, *pDA, *pSA, *pRemovedLLCSNAP; + void *pClonePacket; nMSDU = 0; - while (DataSize > LENGTH_802_3) - { + while (DataSize > LENGTH_802_3) { nMSDU++; - pAMSDUsubheader = (PHEADER_802_3)pData; - PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8); + /*hex_dump("subheader", pData, 64); */ + pAMSDUsubheader = (struct rt_header_802_3 *) pData; + /*pData += LENGTH_802_3; */ + PayloadSize = + pAMSDUsubheader->Octet[1] + + (pAMSDUsubheader->Octet[0] << 8); SubFrameSize = PayloadSize + LENGTH_802_3; - - if ((DataSize < SubFrameSize) || (PayloadSize > 1518 )) - { + if ((DataSize < SubFrameSize) || (PayloadSize > 1518)) { break; } + /*DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n", nMSDU, PayloadSize)); */ pPayload = pData + LENGTH_802_3; pDA = pData; pSA = pData + MAC_ADDR_LEN; - // convert to 802.3 header - CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP); - - if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) ) - { - // avoid local heap overflow, use dyanamic allocation - MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); - if (Elem == NULL) - return; - memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize); - Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize; - WpaEAPOLKeyAction(pAd, Elem); - kfree(Elem); + /* convert to 802.3 header */ + CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, + pRemovedLLCSNAP); + + if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E)) { + /* avoid local heap overflow, use dyanamic allocation */ + struct rt_mlme_queue_elem *Elem = + (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem), + MEM_ALLOC_FLAG); + if (Elem != NULL) { + memmove(Elem->Msg + + (LENGTH_802_11 + LENGTH_802_1_H), + pPayload, PayloadSize); + Elem->MsgLen = + LENGTH_802_11 + LENGTH_802_1_H + + PayloadSize; + /*WpaEAPOLKeyAction(pAd, Elem); */ + REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID, + Elem->Msg, + Elem->MsgLen, 0, 0, 0, + 0); + kfree(Elem); + } } { - if (pRemovedLLCSNAP) - { - pPayload -= LENGTH_802_3; - PayloadSize += LENGTH_802_3; - NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3); - } + if (pRemovedLLCSNAP) { + pPayload -= LENGTH_802_3; + PayloadSize += LENGTH_802_3; + NdisMoveMemory(pPayload, &Header802_3[0], + LENGTH_802_3); + } } pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize); - if (pClonePacket) - { - ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket)); + if (pClonePacket) { + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, + RTMP_GET_PACKET_IF + (pPacket)); } + /* A-MSDU has padding to multiple of 4 including subframe header. */ + /* align SubFrameSize up to multiple of 4 */ + SubFrameSize = (SubFrameSize + 3) & (~0x3); - // A-MSDU has padding to multiple of 4 including subframe header. - // align SubFrameSize up to multiple of 4 - SubFrameSize = (SubFrameSize+3)&(~0x3); - - - if (SubFrameSize > 1528 || SubFrameSize < 32) - { + if (SubFrameSize > 1528 || SubFrameSize < 32) { break; } - if (DataSize > SubFrameSize) - { + if (DataSize > SubFrameSize) { pData += SubFrameSize; DataSize -= SubFrameSize; - } - else - { - // end of A-MSDU + } else { + /* end of A-MSDU */ DataSize = 0; } } - // finally release original rx packet + /* finally release original rx packet */ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); return nMSDU; } - -UINT BA_Reorder_AMSDU_Annnounce( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket) +u32 BA_Reorder_AMSDU_Annnounce(struct rt_rtmp_adapter *pAd, void *pPacket) { - PUCHAR pData; - USHORT DataSize; - UINT nMSDU = 0; + u8 *pData; + u16 DataSize; + u32 nMSDU = 0; - pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); - DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); + pData = (u8 *)GET_OS_PKT_DATAPTR(pPacket); + DataSize = (u16)GET_OS_PKT_LEN(pPacket); nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize); return nMSDU; } - /* ========================================================================== Description: @@ -2089,40 +1501,37 @@ UINT BA_Reorder_AMSDU_Annnounce( pEntry - pointer to the MAC entry; NULL is not found ========================================================================== */ -MAC_TABLE_ENTRY *MacTableLookup( - IN PRTMP_ADAPTER pAd, - PUCHAR pAddr) +struct rt_mac_table_entry *MacTableLookup(struct rt_rtmp_adapter *pAd, u8 *pAddr) { - ULONG HashIdx; - MAC_TABLE_ENTRY *pEntry = NULL; + unsigned long HashIdx; + struct rt_mac_table_entry *pEntry = NULL; HashIdx = MAC_ADDR_HASH_INDEX(pAddr); pEntry = pAd->MacTab.Hash[HashIdx]; - while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) - { - if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) - { + while (pEntry + && (pEntry->ValidAsCLI || pEntry->ValidAsWDS + || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) { + if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) { break; - } - else + } else pEntry = pEntry->pNext; } return pEntry; } -MAC_TABLE_ENTRY *MacTableInsertEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN UCHAR apidx, - IN BOOLEAN CleanAll) +struct rt_mac_table_entry *MacTableInsertEntry(struct rt_rtmp_adapter *pAd, + u8 *pAddr, + u8 apidx, IN BOOLEAN CleanAll) { - UCHAR HashIdx; + u8 HashIdx; int i, FirstWcid; - MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; + struct rt_mac_table_entry *pEntry = NULL, *pCurrEntry; +/* u16 offset; */ +/* unsigned long addr; */ - // if FULL, return + /* if FULL, return */ if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) return NULL; @@ -2131,23 +1540,21 @@ MAC_TABLE_ENTRY *MacTableInsertEntry( if (pAd->StaCfg.BssType == BSS_INFRA) FirstWcid = 2; - // allocate one MAC entry + /* allocate one MAC entry */ NdisAcquireSpinLock(&pAd->MacTabLock); - for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup + for (i = FirstWcid; i < MAX_LEN_OF_MAC_TABLE; i++) /* skip entry#0 so that "entry index == AID" for fast lookup */ { - // pick up the first available vacancy + /* pick up the first available vacancy */ if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) && - (pAd->MacTab.Content[i].ValidAsWDS == FALSE) && - (pAd->MacTab.Content[i].ValidAsApCli== FALSE) && - (pAd->MacTab.Content[i].ValidAsMesh == FALSE) - ) - { + (pAd->MacTab.Content[i].ValidAsWDS == FALSE) && + (pAd->MacTab.Content[i].ValidAsApCli == FALSE) && + (pAd->MacTab.Content[i].ValidAsMesh == FALSE) + ) { pEntry = &pAd->MacTab.Content[i]; - if (CleanAll == TRUE) - { + if (CleanAll == TRUE) { pEntry->MaxSupportedRate = RATE_11; pEntry->CurrTxRate = RATE_11; - NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); + NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry)); pEntry->PairwiseKey.KeyLen = 0; pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; } @@ -2164,77 +1571,76 @@ MAC_TABLE_ENTRY *MacTableInsertEntry( pEntry->bIAmBadAtheros = FALSE; pEntry->pAd = pAd; pEntry->CMTimerRunning = FALSE; - pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + pEntry->EnqueueEapolStartTimerRunning = + EAPOL_START_DISABLE; pEntry->RSNIE_Len = 0; - NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter)); + NdisZeroMemory(pEntry->R_Counter, + sizeof(pEntry->R_Counter)); pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; if (pEntry->ValidAsMesh) - pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH); + pEntry->apidx = + (apidx - MIN_NET_DEVICE_FOR_MESH); else if (pEntry->ValidAsApCli) - pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI); + pEntry->apidx = + (apidx - MIN_NET_DEVICE_FOR_APCLI); else if (pEntry->ValidAsWDS) - pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS); + pEntry->apidx = + (apidx - MIN_NET_DEVICE_FOR_WDS); else pEntry->apidx = apidx; { { pEntry->AuthMode = pAd->StaCfg.AuthMode; - pEntry->WepStatus = pAd->StaCfg.WepStatus; - pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; -#ifdef RT2860 - AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i); -#endif + pEntry->WepStatus = + pAd->StaCfg.WepStatus; + pEntry->PrivacyFilter = + Ndis802_11PrivFilterAcceptAll; +#ifdef RTMP_MAC_PCI + AsicRemovePairwiseKeyEntry(pAd, + pEntry-> + apidx, + (u8)i); +#endif /* RTMP_MAC_PCI // */ } } pEntry->GTKState = REKEY_NEGOTIATING; pEntry->PairwiseKey.KeyLen = 0; pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; - -#ifdef RT2860 - if ((pAd->OpMode == OPMODE_STA) && - (pAd->StaCfg.BssType == BSS_ADHOC)) - pEntry->PortSecured = WPA_802_1X_PORT_SECURED; - else -#endif pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; COPY_MAC_ADDR(pEntry->Addr, pAddr); pEntry->Sst = SST_NOT_AUTH; pEntry->AuthState = AS_NOT_AUTH; - pEntry->Aid = (USHORT)i; //0; + pEntry->Aid = (u16)i; /*0; */ pEntry->CapabilityInfo = 0; pEntry->PsMode = PWR_ACTIVE; pEntry->PsQIdleCount = 0; pEntry->NoDataIdleCount = 0; + pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT; pEntry->ContinueTxFailCnt = 0; InitializeQueueHeader(&pEntry->PsQueue); + pAd->MacTab.Size++; + /* Add this entry into ASIC RX WCID search table */ + RTMP_STA_ENTRY_ADD(pAd, pEntry); - pAd->MacTab.Size ++; - // Add this entry into ASIC RX WCID search table - RT28XX_STA_ENTRY_ADD(pAd, pEntry); - - - - DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size)); + DBGPRINT(RT_DEBUG_TRACE, + ("MacTableInsertEntry - allocate entry #%d, Total= %d\n", + i, pAd->MacTab.Size)); break; } } - // add this MAC entry into HASH table - if (pEntry) - { + /* add this MAC entry into HASH table */ + if (pEntry) { HashIdx = MAC_ADDR_HASH_INDEX(pAddr); - if (pAd->MacTab.Hash[HashIdx] == NULL) - { + if (pAd->MacTab.Hash[HashIdx] == NULL) { pAd->MacTab.Hash[HashIdx] = pEntry; - } - else - { + } else { pCurrEntry = pAd->MacTab.Hash[HashIdx]; while (pCurrEntry->pNext != NULL) pCurrEntry = pCurrEntry->pNext; @@ -2252,14 +1658,14 @@ MAC_TABLE_ENTRY *MacTableInsertEntry( Delete a specified client from MAC table ========================================================================== */ -BOOLEAN MacTableDeleteEntry( - IN PRTMP_ADAPTER pAd, - IN USHORT wcid, - IN PUCHAR pAddr) +BOOLEAN MacTableDeleteEntry(struct rt_rtmp_adapter *pAd, + u16 wcid, u8 *pAddr) { - USHORT HashIdx; - MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry; + u16 HashIdx; + struct rt_mac_table_entry *pEntry, *pPrevEntry, *pProbeEntry; BOOLEAN Cancelled; + /*u16 offset; // unused variable */ + /*u8 j; // unused variable */ if (wcid >= MAX_LEN_OF_MAC_TABLE) return FALSE; @@ -2267,36 +1673,33 @@ BOOLEAN MacTableDeleteEntry( NdisAcquireSpinLock(&pAd->MacTabLock); HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + /*pEntry = pAd->MacTab.Hash[HashIdx]; */ pEntry = &pAd->MacTab.Content[wcid]; - if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh - )) - { - if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) - { + if (pEntry + && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS + || pEntry->ValidAsMesh)) { + if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) { - // Delete this entry from ASIC on-chip WCID Table - RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid); + /* Delete this entry from ASIC on-chip WCID Table */ + RTMP_STA_ENTRY_MAC_RESET(pAd, wcid); - // free resources of BA + /* free resources of BA */ BASessionTearDownALL(pAd, pEntry->Aid); pPrevEntry = NULL; pProbeEntry = pAd->MacTab.Hash[HashIdx]; ASSERT(pProbeEntry); - // update Hash list - do - { - if (pProbeEntry == pEntry) - { - if (pPrevEntry == NULL) - { - pAd->MacTab.Hash[HashIdx] = pEntry->pNext; - } - else - { - pPrevEntry->pNext = pEntry->pNext; + /* update Hash list */ + do { + if (pProbeEntry == pEntry) { + if (pPrevEntry == NULL) { + pAd->MacTab.Hash[HashIdx] = + pEntry->pNext; + } else { + pPrevEntry->pNext = + pEntry->pNext; } break; } @@ -2305,48 +1708,43 @@ BOOLEAN MacTableDeleteEntry( pProbeEntry = pProbeEntry->pNext; } while (pProbeEntry); - // not found !!! + /* not found ! */ ASSERT(pProbeEntry != NULL); - RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid); - - - if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE) - { - RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); - pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; - } + RTMP_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid); + if (pEntry->EnqueueEapolStartTimerRunning != + EAPOL_START_DISABLE) { + RTMPCancelTimer(&pEntry-> + EnqueueStartForPSKTimer, + &Cancelled); + pEntry->EnqueueEapolStartTimerRunning = + EAPOL_START_DISABLE; + } - NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); - pAd->MacTab.Size --; - DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size)); - } - else - { - printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid); + NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry)); + pAd->MacTab.Size--; + DBGPRINT(RT_DEBUG_TRACE, + ("MacTableDeleteEntry1 - Total= %d\n", + pAd->MacTab.Size)); + } else { + DBGPRINT(RT_DEBUG_OFF, + ("\n%s: Impossible Wcid = %d !\n", + __func__, wcid)); } } NdisReleaseSpinLock(&pAd->MacTabLock); - //Reset operating mode when no Sta. - if (pAd->MacTab.Size == 0) - { + /*Reset operating mode when no Sta. */ + if (pAd->MacTab.Size == 0) { pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0; -#ifdef RT2860 - AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/); -#else - // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet - // Set MAC register value according operation mode - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_UPDATE_PROTECT, NULL, 0); -#endif + RTMP_UPDATE_PROTECT(pAd); /* edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet */ } return TRUE; } - /* ========================================================================== Description: @@ -2354,34 +1752,30 @@ BOOLEAN MacTableDeleteEntry( the power-saving queues are freed here. ========================================================================== */ -VOID MacTableReset( - IN PRTMP_ADAPTER pAd) +void MacTableReset(struct rt_rtmp_adapter *pAd) { - int i; + int i; DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n")); - //NdisAcquireSpinLock(&pAd->MacTabLock); + /*NdisAcquireSpinLock(&pAd->MacTabLock); */ - for (i=1; iMacTab.Content[i].ValidAsCLI == TRUE) - { - // free resources of BA + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { +#ifdef RTMP_MAC_PCI + RTMP_STA_ENTRY_MAC_RESET(pAd, i); +#endif /* RTMP_MAC_PCI // */ + if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) { + + /* free resources of BA */ BASessionTearDownALL(pAd, i); pAd->MacTab.Content[i].ValidAsCLI = FALSE; - - -#ifdef RT2870 +#ifdef RTMP_MAC_USB NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6); - RT28XX_STA_ENTRY_MAC_RESET(pAd, i); -#endif // RT2870 // + RTMP_STA_ENTRY_MAC_RESET(pAd, i); +#endif /* RTMP_MAC_USB // */ - //AsicDelWcidTab(pAd, i); + /*AsicDelWcidTab(pAd, i); */ } } @@ -2396,22 +1790,19 @@ VOID MacTableReset( ========================================================================== */ -VOID AssocParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq, - IN PUCHAR pAddr, - IN USHORT CapabilityInfo, - IN ULONG Timeout, - IN USHORT ListenIntv) +void AssocParmFill(struct rt_rtmp_adapter *pAd, + struct rt_mlme_assoc_req *AssocReq, + u8 *pAddr, + u16 CapabilityInfo, + unsigned long Timeout, u16 ListenIntv) { COPY_MAC_ADDR(AssocReq->Addr, pAddr); - // Add mask to support 802.11b mode only - AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request + /* Add mask to support 802.11b mode only */ + AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; /* not cf-pollable, not cf-poll-request */ AssocReq->Timeout = Timeout; AssocReq->ListenIntv = ListenIntv; } - /* ========================================================================== Description: @@ -2420,17 +1811,14 @@ VOID AssocParmFill( ========================================================================== */ -VOID DisassocParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq, - IN PUCHAR pAddr, - IN USHORT Reason) +void DisassocParmFill(struct rt_rtmp_adapter *pAd, + struct rt_mlme_disassoc_req *DisassocReq, + u8 *pAddr, u16 Reason) { COPY_MAC_ADDR(DisassocReq->Addr, pAddr); DisassocReq->Reason = Reason; } - /* ======================================================================== @@ -2465,76 +1853,69 @@ VOID DisassocParmFill( ======================================================================== */ -BOOLEAN RTMPCheckDHCPFrame( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket) +BOOLEAN RTMPCheckDHCPFrame(struct rt_rtmp_adapter *pAd, void *pPacket) { - PACKET_INFO PacketInfo; - ULONG NumberOfBytesRead = 0; - ULONG CurrentOffset = 0; - PVOID pVirtualAddress = NULL; - UINT NdisBufferLength; - PUCHAR pSrc; - USHORT Protocol; - UCHAR ByteOffset36 = 0; - UCHAR ByteOffset38 = 0; - BOOLEAN ReadFirstParm = TRUE; - - RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength); + struct rt_packet_info PacketInfo; + unsigned long NumberOfBytesRead = 0; + unsigned long CurrentOffset = 0; + void *pVirtualAddress = NULL; + u32 NdisBufferLength; + u8 *pSrc; + u16 Protocol; + u8 ByteOffset36 = 0; + u8 ByteOffset38 = 0; + BOOLEAN ReadFirstParm = TRUE; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, (u8 **) & pVirtualAddress, + &NdisBufferLength); NumberOfBytesRead += NdisBufferLength; - pSrc = (PUCHAR) pVirtualAddress; + pSrc = (u8 *)pVirtualAddress; Protocol = *(pSrc + 12) * 256 + *(pSrc + 13); - // - // Check DHCP & BOOTP protocol - // - while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) - { - if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) - { - CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength); + /* */ + /* Check DHCP & BOOTP protocol */ + /* */ + while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) { + if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) { + CurrentOffset = + 35 - (NumberOfBytesRead - NdisBufferLength); ByteOffset36 = *(pSrc + CurrentOffset); ReadFirstParm = FALSE; } - if (NumberOfBytesRead >= 37) - { - CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength); + if (NumberOfBytesRead >= 37) { + CurrentOffset = + 37 - (NumberOfBytesRead - NdisBufferLength); ByteOffset38 = *(pSrc + CurrentOffset); - //End of Read + /*End of Read */ break; } return FALSE; } - // Check for DHCP & BOOTP protocol - if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) - { - // - // 2054 (hex 0806) for ARP datagrams - // if this packet is not ARP datagrams, then do nothing - // ARP datagrams will also be duplicate at 1mb broadcast frames - // - if (Protocol != 0x0806 ) + /* Check for DHCP & BOOTP protocol */ + if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) { + /* */ + /* 2054 (hex 0806) for ARP datagrams */ + /* if this packet is not ARP datagrams, then do nothing */ + /* ARP datagrams will also be duplicate at 1mb broadcast frames */ + /* */ + if (Protocol != 0x0806) return FALSE; - } + } return TRUE; } - -BOOLEAN RTMPCheckEtherType( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket) +BOOLEAN RTMPCheckEtherType(struct rt_rtmp_adapter *pAd, void *pPacket) { - USHORT TypeLen; - UCHAR Byte0, Byte1; - PUCHAR pSrcBuf; - UINT32 pktLen; - UINT16 srcPort, dstPort; - BOOLEAN status = TRUE; - + u16 TypeLen; + u8 Byte0, Byte1; + u8 *pSrcBuf; + u32 pktLen; + u16 srcPort, dstPort; + BOOLEAN status = TRUE; pSrcBuf = GET_OS_PKT_DATAPTR(pPacket); pktLen = GET_OS_PKT_LEN(pPacket); @@ -2543,35 +1924,31 @@ BOOLEAN RTMPCheckEtherType( RTMP_SET_PACKET_SPECIFIC(pPacket, 0); - // get Ethernet protocol field - TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13]; + /* get Ethernet protocol field */ + TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13]; - pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header. + pSrcBuf += LENGTH_802_3; /* Skip the Ethernet Header. */ - if (TypeLen <= 1500) - { // 802.3, 802.3 LLC + if (TypeLen <= 1500) { /* 802.3, 802.3 LLC */ /* - DestMAC(6) + SrcMAC(6) + Lenght(2) + - DSAP(1) + SSAP(1) + Control(1) + - if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header. - => + SNAP (5, OriginationID(3) + etherType(2)) - */ - if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03) - { - Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1); + DestMAC(6) + SrcMAC(6) + Lenght(2) + + DSAP(1) + SSAP(1) + Control(1) + + if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header. + => + SNAP (5, OriginationID(3) + etherType(2)) + */ + if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA + && pSrcBuf[2] == 0x03) { + Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 6, + &Byte0, &Byte1); RTMP_SET_PACKET_LLCSNAP(pPacket, 1); - TypeLen = (USHORT)((Byte0 << 8) + Byte1); - pSrcBuf += 8; // Skip this LLC/SNAP header - } - else - { - //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. + TypeLen = (u16)((Byte0 << 8) + Byte1); + pSrcBuf += 8; /* Skip this LLC/SNAP header */ + } else { + /*It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. */ } } - - // If it's a VLAN packet, get the real Type/Length field. - if (TypeLen == 0x8100) - { + /* If it's a VLAN packet, get the real Type/Length field. */ + if (TypeLen == 0x8100) { /* 0x8100 means VLAN packets */ /* Dest. MAC Address (6-bytes) + @@ -2584,243 +1961,229 @@ BOOLEAN RTMPCheckEtherType( Frame Check Sequence (4-bytes) */ RTMP_SET_PACKET_VLAN(pPacket, 1); - Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1); - TypeLen = (USHORT)((Byte0 << 8) + Byte1); + Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 2, &Byte0, + &Byte1); + TypeLen = (u16)((Byte0 << 8) + Byte1); - pSrcBuf += 4; // Skip the VLAN Header. + pSrcBuf += 4; /* Skip the VLAN Header. */ } - switch (TypeLen) - { - case 0x0800: - { - ASSERT((pktLen > 34)); - if (*(pSrcBuf + 9) == 0x11) - { // udp packet - ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header - - pSrcBuf += 20; // Skip the IP header - srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf)); - dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2))); - - if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44)) - { //It's a BOOTP/DHCP packet - RTMP_SET_PACKET_DHCP(pPacket, 1); - } + switch (TypeLen) { + case 0x0800: + { + ASSERT((pktLen > 34)); + if (*(pSrcBuf + 9) == 0x11) { /* udp packet */ + ASSERT((pktLen > 34)); /* 14 for ethernet header, 20 for IP header */ + + pSrcBuf += 20; /* Skip the IP header */ + srcPort = + OS_NTOHS(get_unaligned + ((u16 *)(pSrcBuf))); + dstPort = + OS_NTOHS(get_unaligned + ((u16 *)(pSrcBuf + 2))); + + if ((srcPort == 0x44 && dstPort == 0x43) || (srcPort == 0x43 && dstPort == 0x44)) { /*It's a BOOTP/DHCP packet */ + RTMP_SET_PACKET_DHCP(pPacket, 1); } } - break; - case 0x0806: - { - //ARP Packet. - RTMP_SET_PACKET_DHCP(pPacket, 1); - } - break; - case 0x888e: - { - // EAPOL Packet. - RTMP_SET_PACKET_EAPOL(pPacket, 1); - } - break; - default: - status = FALSE; - break; + } + break; + case 0x0806: + { + /*ARP Packet. */ + RTMP_SET_PACKET_DHCP(pPacket, 1); + } + break; + case 0x888e: + { + /* EAPOL Packet. */ + RTMP_SET_PACKET_EAPOL(pPacket, 1); + } + break; + default: + status = FALSE; + break; } return status; } +void Update_Rssi_Sample(struct rt_rtmp_adapter *pAd, + struct rt_rssi_sample *pRssi, struct rt_rxwi * pRxWI) +{ + char rssi0 = pRxWI->RSSI0; + char rssi1 = pRxWI->RSSI1; + char rssi2 = pRxWI->RSSI2; - -VOID Update_Rssi_Sample( - IN PRTMP_ADAPTER pAd, - IN RSSI_SAMPLE *pRssi, - IN PRXWI_STRUC pRxWI) - { - CHAR rssi0 = pRxWI->RSSI0; - CHAR rssi1 = pRxWI->RSSI1; - CHAR rssi2 = pRxWI->RSSI2; - - if (rssi0 != 0) - { - pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0); - pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0; - pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3; + if (rssi0 != 0) { + pRssi->LastRssi0 = ConvertToRssi(pAd, (char)rssi0, RSSI_0); + pRssi->AvgRssi0X8 = + (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0; + pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3; } - if (rssi1 != 0) - { - pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1); - pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1; - pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3; + if (rssi1 != 0) { + pRssi->LastRssi1 = ConvertToRssi(pAd, (char)rssi1, RSSI_1); + pRssi->AvgRssi1X8 = + (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1; + pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3; } - if (rssi2 != 0) - { - pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2); - pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2; + if (rssi2 != 0) { + pRssi->LastRssi2 = ConvertToRssi(pAd, (char)rssi2, RSSI_2); + pRssi->AvgRssi2X8 = + (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2; pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3; } } - - -// Normal legacy Rx packet indication -VOID Indicate_Legacy_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) +/* Normal legacy Rx packet indication */ +void Indicate_Legacy_Packet(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) { - PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; - UCHAR Header802_3[LENGTH_802_3]; + void *pRxPacket = pRxBlk->pRxPacket; + u8 Header802_3[LENGTH_802_3]; - // 1. get 802.3 Header - // 2. remove LLC - // a. pointer pRxBlk->pData to payload - // b. modify pRxBlk->DataSize + /* 1. get 802.3 Header */ + /* 2. remove LLC */ + /* a. pointer pRxBlk->pData to payload */ + /* b. modify pRxBlk->DataSize */ RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); - if (pRxBlk->DataSize > MAX_RX_PKT_LEN) - { + if (pRxBlk->DataSize > MAX_RX_PKT_LEN) { - // release packet + /* release packet */ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); return; } - STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); -#ifdef RT2870 - if (pAd->CommonCfg.bDisableReordering == 0) - { - PBA_REC_ENTRY pBAEntry; - ULONG Now32; - UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID; - UCHAR TID = pRxBlk->pRxWI->TID; - USHORT Idx; +#ifdef RTMP_MAC_USB + if (pAd->CommonCfg.bDisableReordering == 0) { + struct rt_ba_rec_entry *pBAEntry; + unsigned long Now32; + u8 Wcid = pRxBlk->pRxWI->WirelessCliID; + u8 TID = pRxBlk->pRxWI->TID; + u16 Idx; -#define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms +#define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms */ - if (Wcid < MAX_LEN_OF_MAC_TABLE) - { + if (Wcid < MAX_LEN_OF_MAC_TABLE) { Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; - if (Idx != 0) - { + if (Idx != 0) { pBAEntry = &pAd->BATable.BARecEntry[Idx]; - // update last rx time + /* update last rx time */ NdisGetSystemUpTime(&Now32); if ((pBAEntry->list.qlen > 0) && - RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT))) - ) - { - printk("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n", pRxBlk->Flags, pRxBlk->pRxWI->TID, pRxBlk->RxD.AMPDU); - hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64); - ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); + RTMP_TIME_AFTER((unsigned long)Now32, + (unsigned long)(pBAEntry-> + LastIndSeqAtTimer + + + (REORDERING_PACKET_TIMEOUT))) + ) { + DBGPRINT(RT_DEBUG_OFF, + ("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n", + pRxBlk->Flags, + pRxBlk->pRxWI->TID, + pRxBlk->RxD.AMPDU)); + hex_dump("Dump the legacy Packet:", + GET_OS_PKT_DATAPTR(pRxBlk-> + pRxPacket), + 64); + ba_flush_reordering_timeout_mpdus(pAd, + pBAEntry, + Now32); } } } } -#endif // RT2870 // +#endif /* RTMP_MAC_USB // */ wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); - // - // pass this 802.3 packet to upper layer or forward this packet to WM directly - // + /* */ + /* pass this 802.3 packet to upper layer or forward this packet to WM directly */ + /* */ ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); } - -// Normal, AMPDU or AMSDU -VOID CmmRxnonRalinkFrameIndicate( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) +/* Normal, AMPDU or AMSDU */ +void CmmRxnonRalinkFrameIndicate(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) { - if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) - { + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) + && (pAd->CommonCfg.bDisableReordering == 0)) { Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); - } - else - { - if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) - { - // handle A-MSDU + } else { + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) { + /* handle A-MSDU */ Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID); - } - else - { + } else { Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); } } } - -VOID CmmRxRalinkFrameIndicate( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) +void CmmRxRalinkFrameIndicate(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) { - UCHAR Header802_3[LENGTH_802_3]; - UINT16 Msdu2Size; - UINT16 Payload1Size, Payload2Size; - PUCHAR pData2; - PNDIS_PACKET pPacket2 = NULL; - - + u8 Header802_3[LENGTH_802_3]; + u16 Msdu2Size; + u16 Payload1Size, Payload2Size; + u8 *pData2; + void *pPacket2 = NULL; - Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8); + Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData + 1) << 8); - if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) - { + if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) { /* skip two byte MSDU2 len */ pRxBlk->pData += 2; pRxBlk->DataSize -= 2; - } - else - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + } else { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); return; } - // get 802.3 Header and remove LLC + /* get 802.3 Header and remove LLC */ RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); ASSERT(pRxBlk->pRxPacket); - // Ralink Aggregation frame - pAd->RalinkCounters.OneSecRxAggregationCount ++; + /* Ralink Aggregation frame */ + pAd->RalinkCounters.OneSecRxAggregationCount++; Payload1Size = pRxBlk->DataSize - Msdu2Size; Payload2Size = Msdu2Size - LENGTH_802_3; pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3; - pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID); + pPacket2 = + duplicate_pkt(pAd, (pData2 - LENGTH_802_3), LENGTH_802_3, pData2, + Payload2Size, FromWhichBSSID); - if (!pPacket2) - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + if (!pPacket2) { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); return; } - - // update payload size of 1st packet + /* update payload size of 1st packet */ pRxBlk->DataSize = Payload1Size; wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); - ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID); + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, + FromWhichBSSID); - if (pPacket2) - { + if (pPacket2) { ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID); } } - #define RESET_FRAGFRAME(_fragFrame) \ { \ _fragFrame.RxSize = 0; \ @@ -2829,109 +2192,102 @@ VOID CmmRxRalinkFrameIndicate( _fragFrame.Flags = 0; \ } - -PNDIS_PACKET RTMPDeFragmentDataFrame( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk) +void *RTMPDeFragmentDataFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk) { - PHEADER_802_11 pHeader = pRxBlk->pHeader; - PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; - UCHAR *pData = pRxBlk->pData; - USHORT DataSize = pRxBlk->DataSize; - PNDIS_PACKET pRetPacket = NULL; - UCHAR *pFragBuffer = NULL; - BOOLEAN bReassDone = FALSE; - UCHAR HeaderRoom = 0; - + struct rt_header_802_11 * pHeader = pRxBlk->pHeader; + void *pRxPacket = pRxBlk->pRxPacket; + u8 *pData = pRxBlk->pData; + u16 DataSize = pRxBlk->DataSize; + void *pRetPacket = NULL; + u8 *pFragBuffer = NULL; + BOOLEAN bReassDone = FALSE; + u8 HeaderRoom = 0; ASSERT(pHeader); - HeaderRoom = pData - (UCHAR *)pHeader; + HeaderRoom = pData - (u8 *) pHeader; - // Re-assemble the fragmented packets - if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt + /* Re-assemble the fragmented packets */ + if (pHeader->Frag == 0) /* Frag. Number is 0 : First frag or only one pkt */ { - // the first pkt of fragment, record it. - if (pHeader->FC.MoreFrag) - { + /* the first pkt of fragment, record it. */ + if (pHeader->FC.MoreFrag) { ASSERT(pAd->FragFrame.pFragPacket); - pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); - pAd->FragFrame.RxSize = DataSize + HeaderRoom; - NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize); + pFragBuffer = + GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); + pAd->FragFrame.RxSize = DataSize + HeaderRoom; + NdisMoveMemory(pFragBuffer, pHeader, + pAd->FragFrame.RxSize); pAd->FragFrame.Sequence = pHeader->Sequence; - pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0 + pAd->FragFrame.LastFrag = pHeader->Frag; /* Should be 0 */ ASSERT(pAd->FragFrame.LastFrag == 0); - goto done; // end of processing this frame + goto done; /* end of processing this frame */ } - } - else //Middle & End of fragment + } else /*Middle & End of fragment */ { if ((pHeader->Sequence != pAd->FragFrame.Sequence) || - (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) - { - // Fragment is not the same sequence or out of fragment number order - // Reset Fragment control blk + (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) { + /* Fragment is not the same sequence or out of fragment number order */ + /* Reset Fragment control blk */ RESET_FRAGFRAME(pAd->FragFrame); - DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n")); - goto done; // give up this frame - } - else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) - { - // Fragment frame is too large, it exeeds the maximum frame size. - // Reset Fragment control blk + DBGPRINT(RT_DEBUG_ERROR, + ("Fragment is not the same sequence or out of fragment number order.\n")); + goto done; /* give up this frame */ + } else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) { + /* Fragment frame is too large, it exeeds the maximum frame size. */ + /* Reset Fragment control blk */ RESET_FRAGFRAME(pAd->FragFrame); - DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n")); - goto done; // give up this frame + DBGPRINT(RT_DEBUG_ERROR, + ("Fragment frame is too large, it exeeds the maximum frame size.\n")); + goto done; /* give up this frame */ } - - // - // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment. - // In this case, we will dropt it. - // - if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) - { - DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag)); - goto done; // give up this frame + /* */ + /* Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment. */ + /* In this case, we will dropt it. */ + /* */ + if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) { + DBGPRINT(RT_DEBUG_ERROR, + ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", + pHeader->Sequence, pHeader->Frag)); + goto done; /* give up this frame */ } pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); - // concatenate this fragment into the re-assembly buffer - NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize); - pAd->FragFrame.RxSize += DataSize; - pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number + /* concatenate this fragment into the re-assembly buffer */ + NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, + DataSize); + pAd->FragFrame.RxSize += DataSize; + pAd->FragFrame.LastFrag = pHeader->Frag; /* Update fragment number */ - // Last fragment - if (pHeader->FC.MoreFrag == FALSE) - { + /* Last fragment */ + if (pHeader->FC.MoreFrag == FALSE) { bReassDone = TRUE; } } done: - // always release rx fragmented packet + /* always release rx fragmented packet */ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); - // return defragmented packet if packet is reassembled completely - // otherwise return NULL - if (bReassDone) - { - PNDIS_PACKET pNewFragPacket; + /* return defragmented packet if packet is reassembled completely */ + /* otherwise return NULL */ + if (bReassDone) { + void *pNewFragPacket; - // allocate a new packet buffer for fragment - pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); - if (pNewFragPacket) - { - // update RxBlk + /* allocate a new packet buffer for fragment */ + pNewFragPacket = + RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); + if (pNewFragPacket) { + /* update RxBlk */ pRetPacket = pAd->FragFrame.pFragPacket; pAd->FragFrame.pFragPacket = pNewFragPacket; - pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket); - pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom; + pRxBlk->pHeader = + (struct rt_header_802_11 *) GET_OS_PKT_DATAPTR(pRetPacket); + pRxBlk->pData = (u8 *) pRxBlk->pHeader + HeaderRoom; pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom; pRxBlk->pRxPacket = pRetPacket; - } - else - { + } else { RESET_FRAGFRAME(pAd->FragFrame); } } @@ -2939,25 +2295,22 @@ done: return pRetPacket; } - -VOID Indicate_AMSDU_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) +void Indicate_AMSDU_Packet(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) { - UINT nMSDU; + u32 nMSDU; update_os_packet_info(pAd, pRxBlk, FromWhichBSSID); RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); - nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize); + nMSDU = + deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, + pRxBlk->DataSize); } -VOID Indicate_EAPOL_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) +void Indicate_EAPOL_Packet(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) { - MAC_TABLE_ENTRY *pEntry = NULL; + struct rt_mac_table_entry *pEntry = NULL; { pEntry = &pAd->MacTab.Content[BSSID_WCID]; @@ -2965,48 +2318,42 @@ VOID Indicate_EAPOL_Packet( return; } - if (pEntry == NULL) - { - DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n")); - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + if (pEntry == NULL) { + DBGPRINT(RT_DEBUG_WARN, + ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n")); + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); return; } } -#define BCN_TBTT_OFFSET 64 //defer 64 us -VOID ReSyncBeaconTime( - IN PRTMP_ADAPTER pAd) +#define BCN_TBTT_OFFSET 64 /*defer 64 us */ +void ReSyncBeaconTime(struct rt_rtmp_adapter *pAd) { - UINT32 Offset; - + u32 Offset; Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET); pAd->TbttTickCount++; - // - // The updated BeaconInterval Value will affect Beacon Interval after two TBTT - // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER - // - if (Offset == (BCN_TBTT_OFFSET-2)) - { + /* */ + /* The updated BeaconInterval Value will affect Beacon Interval after two TBTT */ + /* beacasue the original BeaconInterval had been loaded into next TBTT_TIMER */ + /* */ + if (Offset == (BCN_TBTT_OFFSET - 2)) { BCN_TIME_CFG_STRUC csr; RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); - csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us + csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1; /* ASIC register in units of 1/16 TU = 64us */ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); - } - else - { - if (Offset == (BCN_TBTT_OFFSET-1)) - { + } else { + if (Offset == (BCN_TBTT_OFFSET - 1)) { BCN_TIME_CFG_STRUC csr; RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); - csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU + csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; /* ASIC register in units of 1/16 TU */ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); } } } - diff --git a/drivers/staging/rt2860/common/cmm_data_2860.c b/drivers/staging/rt2860/common/cmm_data_2860.c deleted file mode 100644 index 857ff450b6c9dbd8798980bd5364a76ba0e60ce1..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2860/common/cmm_data_2860.c +++ /dev/null @@ -1,1199 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* -*/ - -/* - All functions in this file must be PCI-depended, or you should out your function - in other files. - -*/ -#include "../rt_config.h" - -extern RTMP_RF_REGS RF2850RegTable[]; -extern UCHAR NUM_OF_2850_CHNL; - -USHORT RtmpPCI_WriteTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN BOOLEAN bIsLast, - OUT USHORT *FreeNumber) -{ - - UCHAR *pDMAHeaderBufVA; - USHORT TxIdx, RetTxIdx; - PTXD_STRUC pTxD; - UINT32 BufBasePaLow; - PRTMP_TX_RING pTxRing; - USHORT hwHeaderLen; - - // - // get Tx Ring Resource - // - pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; - TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; - pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; - BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); - - // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer - if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) - { - hwHeaderLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; - } - else - { - hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; - } - NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen); - - pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; - pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; - - // - // build Tx Descriptor - // - - pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; - NdisZeroMemory(pTxD, TXD_SIZE); - - pTxD->SDPtr0 = BufBasePaLow; - pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding - pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);; - pTxD->SDLen1 = pTxBlk->SrcBufLen; - pTxD->LastSec0 = 0; - pTxD->LastSec1 = (bIsLast) ? 1 : 0; - - RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); - - RetTxIdx = TxIdx; - // - // Update Tx index - // - INC_RING_INDEX(TxIdx, TX_RING_SIZE); - pTxRing->TxCpuIdx = TxIdx; - - *FreeNumber -= 1; - - return RetTxIdx; -} - - -USHORT RtmpPCI_WriteSingleTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN BOOLEAN bIsLast, - OUT USHORT *FreeNumber) -{ - - UCHAR *pDMAHeaderBufVA; - USHORT TxIdx, RetTxIdx; - PTXD_STRUC pTxD; - UINT32 BufBasePaLow; - PRTMP_TX_RING pTxRing; - USHORT hwHeaderLen; - - // - // get Tx Ring Resource - // - pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; - TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; - pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; - BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); - - // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer - hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; - - NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen); - - pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; - pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; - - // - // build Tx Descriptor - // - pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; - - NdisZeroMemory(pTxD, TXD_SIZE); - - pTxD->SDPtr0 = BufBasePaLow; - pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding - pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);; - pTxD->SDLen1 = pTxBlk->SrcBufLen; - pTxD->LastSec0 = 0; - pTxD->LastSec1 = (bIsLast) ? 1 : 0; - - RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); - - RetTxIdx = TxIdx; - // - // Update Tx index - // - INC_RING_INDEX(TxIdx, TX_RING_SIZE); - pTxRing->TxCpuIdx = TxIdx; - - *FreeNumber -= 1; - - return RetTxIdx; -} - - -USHORT RtmpPCI_WriteMultiTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR frameNum, - OUT USHORT *FreeNumber) -{ - BOOLEAN bIsLast; - UCHAR *pDMAHeaderBufVA; - USHORT TxIdx, RetTxIdx; - PTXD_STRUC pTxD; - UINT32 BufBasePaLow; - PRTMP_TX_RING pTxRing; - USHORT hwHdrLen; - UINT32 firstDMALen; - - bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0); - - // - // get Tx Ring Resource - // - pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; - TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; - pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; - BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); - - if (frameNum == 0) - { - // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer - if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) - //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; - hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; - else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) - //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; - hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; - else - //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); - hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; - - firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; - } - else - { - firstDMALen = pTxBlk->MpduHeaderLen; - } - - NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); - - pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; - pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; - - // - // build Tx Descriptor - // - pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; - - NdisZeroMemory(pTxD, TXD_SIZE); - - pTxD->SDPtr0 = BufBasePaLow; - pTxD->SDLen0 = firstDMALen; // include padding - pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);; - pTxD->SDLen1 = pTxBlk->SrcBufLen; - pTxD->LastSec0 = 0; - pTxD->LastSec1 = (bIsLast) ? 1 : 0; - - RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); - - RetTxIdx = TxIdx; - // - // Update Tx index - // - INC_RING_INDEX(TxIdx, TX_RING_SIZE); - pTxRing->TxCpuIdx = TxIdx; - - *FreeNumber -= 1; - - return RetTxIdx; - -} - - -VOID RtmpPCI_FinalWriteTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN USHORT totalMPDUSize, - IN USHORT FirstTxIdx) -{ - - PTXWI_STRUC pTxWI; - PRTMP_TX_RING pTxRing; - - // - // get Tx Ring Resource - // - pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; - pTxWI = (PTXWI_STRUC) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa; - pTxWI->MPDUtotalByteCount = totalMPDUSize; -} - - -VOID RtmpPCIDataLastTxIdx( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN USHORT LastTxIdx) -{ - PTXD_STRUC pTxD; - PRTMP_TX_RING pTxRing; - - // - // get Tx Ring Resource - // - pTxRing = &pAd->TxRing[QueIdx]; - - // - // build Tx Descriptor - // - pTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa; - - pTxD->LastSec1 = 1; -} - - -USHORT RtmpPCI_WriteFragTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR fragNum, - OUT USHORT *FreeNumber) -{ - UCHAR *pDMAHeaderBufVA; - USHORT TxIdx, RetTxIdx; - PTXD_STRUC pTxD; - UINT32 BufBasePaLow; - PRTMP_TX_RING pTxRing; - USHORT hwHeaderLen; - UINT32 firstDMALen; - - // - // Get Tx Ring Resource - // - pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; - TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; - pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; - BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); - - // - // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer - // - hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; - - firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; - NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); - - - // - // Build Tx Descriptor - // - pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; - - NdisZeroMemory(pTxD, TXD_SIZE); - - if (fragNum == pTxBlk->TotalFragNum) - { - pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; - pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; - } - - pTxD->SDPtr0 = BufBasePaLow; - pTxD->SDLen0 = firstDMALen; // include padding - pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE); - pTxD->SDLen1 = pTxBlk->SrcBufLen; - pTxD->LastSec0 = 0; - pTxD->LastSec1 = 1; - - RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); - - RetTxIdx = TxIdx; - pTxBlk->Priv += pTxBlk->SrcBufLen; - - // - // Update Tx index - // - INC_RING_INDEX(TxIdx, TX_RING_SIZE); - pTxRing->TxCpuIdx = TxIdx; - - *FreeNumber -= 1; - - return RetTxIdx; - -} - -/* - Must be run in Interrupt context - This function handle PCI specific TxDesc and cpu index update and kick the packet out. - */ -int RtmpPCIMgmtKickOut( - IN RTMP_ADAPTER *pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket, - IN PUCHAR pSrcBufVA, - IN UINT SrcBufLen) -{ - PTXD_STRUC pTxD; - ULONG SwIdx = pAd->MgmtRing.TxCpuIdx; - - pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa; - if (!pTxD) - return 0; - - pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket; - pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL; - - RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT); - pTxD->LastSec0 = 1; - pTxD->LastSec1 = 1; - pTxD->DMADONE = 0; - pTxD->SDLen1 = 0; - pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);; - pTxD->SDLen0 = SrcBufLen; - - pAd->RalinkCounters.KickTxCount++; - pAd->RalinkCounters.OneSecTxDoneCount++; - - // Increase TX_CTX_IDX, but write to register later. - INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); - - RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); - - return 0; -} - -/* - ======================================================================== - - Routine Description: - Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound - - Arguments: - pRxD Pointer to the Rx descriptor - - Return Value: - NDIS_STATUS_SUCCESS No err - NDIS_STATUS_FAILURE Error - - Note: - - ======================================================================== -*/ -NDIS_STATUS RTMPCheckRxError( - IN PRTMP_ADAPTER pAd, - IN PHEADER_802_11 pHeader, - IN PRXWI_STRUC pRxWI, - IN PRT28XX_RXD_STRUC pRxD) -{ - PCIPHER_KEY pWpaKey; - INT dBm; - - // Phy errors & CRC errors - if (/*(pRxD->PhyErr) ||*/ (pRxD->Crc)) - { - // Check RSSI for Noise Hist statistic collection. - dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta; - if (dBm <= -87) - pAd->StaCfg.RPIDensity[0] += 1; - else if (dBm <= -82) - pAd->StaCfg.RPIDensity[1] += 1; - else if (dBm <= -77) - pAd->StaCfg.RPIDensity[2] += 1; - else if (dBm <= -72) - pAd->StaCfg.RPIDensity[3] += 1; - else if (dBm <= -67) - pAd->StaCfg.RPIDensity[4] += 1; - else if (dBm <= -62) - pAd->StaCfg.RPIDensity[5] += 1; - else if (dBm <= -57) - pAd->StaCfg.RPIDensity[6] += 1; - else if (dBm > -57) - pAd->StaCfg.RPIDensity[7] += 1; - - return(NDIS_STATUS_FAILURE); - } - - // Add Rx size to channel load counter, we should ignore error counts - pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14); - - // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics - if (pHeader != NULL) - { - if (pHeader->FC.ToDs) - { - return(NDIS_STATUS_FAILURE); - } - } - - // Drop not U2M frames, cant's drop here because we will drop beacon in this case - // I am kind of doubting the U2M bit operation - // if (pRxD->U2M == 0) - // return(NDIS_STATUS_FAILURE); - - // drop decyption fail frame - if (pRxD->CipherErr) - { - if (pRxD->CipherErr == 2) - {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV ok but MICErr "));} - else if (pRxD->CipherErr == 1) - {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV Err "));} - else if (pRxD->CipherErr == 3) - DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: Key not valid ")); - - if (((pRxD->CipherErr & 1) == 1) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd)) - RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - - DBGPRINT_RAW(RT_DEBUG_TRACE,(" %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n", - pRxD->CipherErr, - pRxD->SDL0, - pRxD->Mcast | pRxD->Bcast, - pRxD->MyBss, - pRxWI->WirelessCliID, - pRxWI->KeyIndex)); - - // - // MIC Error - // - if (pRxD->CipherErr == 2) - { - pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex]; - - if (pAd->StaCfg.WpaSupplicantUP) - WpaSendMicFailureToWpaSupplicant(pAd, - (pWpaKey->Type == PAIRWISEKEY) ? TRUE:FALSE); - else - RTMPReportMicError(pAd, pWpaKey); - - if (((pRxD->CipherErr & 2) == 2) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd)) - RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - - DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n")); - } - - if (pHeader == NULL) - return(NDIS_STATUS_SUCCESS); - - return(NDIS_STATUS_FAILURE); - } - - return(NDIS_STATUS_SUCCESS); -} - -/* - ========================================================================== - Description: - This routine sends command to firmware and turn our chip to power save mode. - Both RadioOff and .11 power save function needs to call this routine. - Input: - Level = GUIRADIO_OFF : GUI Radio Off mode - Level = DOT11POWERSAVE : 802.11 power save mode - Level = RTMP_HALT : When Disable device. - - ========================================================================== - */ -VOID RT28xxPciAsicRadioOff( - IN PRTMP_ADAPTER pAd, - IN UCHAR Level, - IN USHORT TbttNumToNextWakeUp) -{ - WPDMA_GLO_CFG_STRUC DmaCfg; - UCHAR i, tempBBP_R3 = 0; - BOOLEAN brc = FALSE, Cancelled; - UINT32 TbTTTime = 0; - UINT32 PsPollTime = 0, MACValue; - ULONG BeaconPeriodTime; - UINT32 RxDmaIdx, RxCpuIdx; - DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> TxCpuIdx = %d, TxDmaIdx = %d. RxCpuIdx = %d, RxDmaIdx = %d.\n", pAd->TxRing[0].TxCpuIdx, pAd->TxRing[0].TxDmaIdx, pAd->RxRing.RxCpuIdx, pAd->RxRing.RxDmaIdx)); - - // Check Rx DMA busy status, if more than half is occupied, give up this radio off. - RTMP_IO_READ32(pAd, RX_DRX_IDX , &RxDmaIdx); - RTMP_IO_READ32(pAd, RX_CRX_IDX , &RxCpuIdx); - if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE/3)) - { - DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return1. RxDmaIdx = %d , RxCpuIdx = %d. \n", RxDmaIdx, RxCpuIdx)); - return; - } - else if ((RxCpuIdx >= RxDmaIdx) && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE/3)) - { - DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return2. RxCpuIdx = %d. RxDmaIdx = %d , \n", RxCpuIdx, RxDmaIdx)); - return; - } - - // Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops. - RTMP_SET_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) - { - RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - - if (Level == DOT11POWERSAVE) - { - RTMP_IO_READ32(pAd, TBTT_TIMER, &TbTTTime); - TbTTTime &= 0x1ffff; - // 00. check if need to do sleep in this DTIM period. If next beacon will arrive within 30ms , ...doesn't necessarily sleep. - // TbTTTime uint = 64us, LEAD_TIME unit = 1024us, PsPollTime unit = 1ms - if (((64*TbTTTime) <((LEAD_TIME*1024) + 40000)) && (TbttNumToNextWakeUp == 0)) - { - DBGPRINT(RT_DEBUG_TRACE, ("TbTTTime = 0x%x , give up this sleep. \n", TbTTTime)); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); - return; - } - else - { - PsPollTime = (64*TbTTTime- LEAD_TIME*1024)/1000; - PsPollTime -= 3; - - BeaconPeriodTime = pAd->CommonCfg.BeaconPeriod*102/100; - if (TbttNumToNextWakeUp > 0) - PsPollTime += ((TbttNumToNextWakeUp -1) * BeaconPeriodTime); - - pAd->Mlme.bPsPollTimerRunning = TRUE; - RTMPSetTimer(&pAd->Mlme.PsPollTimer, PsPollTime); - } - } - } - - // 0. Disable Tx DMA. - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); - DmaCfg.field.EnableTxDMA = 0; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); - - // 1. Wait DMA not busy - i = 0; - do - { - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); - if ((DmaCfg.field.TxDMABusy == 0) && (DmaCfg.field.RxDMABusy == 0)) - break; - RTMPusecDelay(20); - i++; - }while(i < 50); - - if (i >= 50) - { - DBGPRINT(RT_DEBUG_TRACE, ("DMA keeps busy. return on RT28xxPciAsicRadioOff ()\n")); - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); - DmaCfg.field.EnableTxDMA = 1; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); - pAd->CheckDmaBusyCount++; - return; - } - else - { - pAd->CheckDmaBusyCount = 0; - } - - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); - - // Set to 1R. - if (pAd->Antenna.field.RxPath > 1) - { - tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3); - } - - // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. - if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) - && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. - AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); - } - else - { - // Must using 20MHz. - AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); - } - - if (Level != RTMP_HALT) - { - // Change Interrupt bitmask. - RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt); - } - else - { - NICDisableInterrupt(pAd); - } - - RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); - // Disable MAC Rx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL , &MACValue); - MACValue &= 0xf7; - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL , MACValue); - - // 2. Send Sleep command - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); - // send POWER-SAVE command to MCU. high-byte = 1 save power as much as possible. high byte = 0 save less power - AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x1); - // 2-1. Wait command success - // Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task. - brc = AsicCheckCommanOk(pAd, PowerSafeCID); - - if (brc == FALSE) - { - // try again - AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x01); // send POWER-SAVE command to MCU. Timeout unit:40us. - //RTMPusecDelay(200); - brc = AsicCheckCommanOk(pAd, PowerSafeCID); - } - - // 3. After 0x30 command is ok, send radio off command. lowbyte = 0 for power safe. - // If 0x30 command is not ok this time, we can ignore 0x35 command. It will make sure not cause firmware'r problem. - if ((Level == DOT11POWERSAVE) && (brc == TRUE)) - { - AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 0, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio. - // 3-1. Wait command success - AsicCheckCommanOk(pAd, PowerRadioOffCID); - } - else if (brc == TRUE) - { - AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 1, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio. - // 3-1. Wait command success - AsicCheckCommanOk(pAd, PowerRadioOffCID); - } - - // Wait DMA not busy - i = 0; - do - { - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); - if ((DmaCfg.field.RxDMABusy == 0) && (DmaCfg.field.TxDMABusy == 0)) - break; - RTMPusecDelay(20); - i++; - }while(i < 50); - - if (i >= 50) - { - pAd->CheckDmaBusyCount++; - DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy. on RT28xxPciAsicRadioOff ()\n")); - } - else - { - pAd->CheckDmaBusyCount = 0; - } - - if (Level == DOT11POWERSAVE) - { - AUTO_WAKEUP_STRUC AutoWakeupCfg; - //RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90); - - // we have decided to SLEEP, so at least do it for a BEACON period. - if (TbttNumToNextWakeUp == 0) - TbttNumToNextWakeUp = 1; - - AutoWakeupCfg.word = 0; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - - // 1. Set auto wake up timer. - AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; - AutoWakeupCfg.field.EnableAutoWakeup = 1; - AutoWakeupCfg.field.AutoLeadTime = LEAD_TIME; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - } - - // 4-1. If it's to disable our device. Need to restore PCI Configuration Space to its original value. - if (Level == RTMP_HALT) - { - if ((brc == TRUE) && (i < 50)) - RTMPPCIeLinkCtrlSetting(pAd, 0); - } - // 4. Set PCI configuration Space Link Comtrol fields. Only Radio Off needs to call this function - else - { - if ((brc == TRUE) && (i < 50)) - RTMPPCIeLinkCtrlSetting(pAd, 3); - } - - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); -} - - -/* - ========================================================================== - Description: - This routine sends command to firmware and turn our chip to wake up mode from power save mode. - Both RadioOn and .11 power save function needs to call this routine. - Input: - Level = GUIRADIO_OFF : call this function is from Radio Off to Radio On. Need to restore PCI host value. - Level = other value : normal wake up function. - - ========================================================================== - */ -BOOLEAN RT28xxPciAsicRadioOn( - IN PRTMP_ADAPTER pAd, - IN UCHAR Level) -{ - WPDMA_GLO_CFG_STRUC DmaCfg; - BOOLEAN Cancelled, brv = TRUE; - UINT32 MACValue; - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) - { - pAd->Mlme.bPsPollTimerRunning = FALSE; - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - if ((Level == GUIRADIO_OFF) || (Level == GUI_IDLE_POWER_SAVE) - || (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))) - { - DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOn ()\n")); - // 1. Set PCI Link Control in Configuration Space. - RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); - RTMPusecDelay(6000); - } - } - - pAd->bPCIclkOff = FALSE; - RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x3a80); - // 2. Send wake up command. - AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02); - - // 2-1. wait command ok. - brv = AsicCheckCommanOk(pAd, PowerWakeCID); - if (brv) - { - NICEnableInterrupt(pAd); - - // 3. Enable Tx DMA. - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); - DmaCfg.field.EnableTxDMA = 1; - DmaCfg.field.EnableRxDMA = 1; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); - - // Eable MAC Rx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL , &MACValue); - MACValue |= 0x8; - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL , MACValue); - - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); - if (Level == GUI_IDLE_POWER_SAVE) - { - // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. - if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) - && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - } - else - { - // Must using 20MHz. - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - } - } - return TRUE; - } - else - return FALSE; -} - -VOID RT28xxPciStaAsicForceWakeup( - IN PRTMP_ADAPTER pAd, - IN UCHAR Level) -{ - AUTO_WAKEUP_STRUC AutoWakeupCfg; - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) - { - DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); - return; - } - - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) - { - // Support PCIe Advance Power Save - if (((Level == FROM_TX) && (pAd->Mlme.bPsPollTimerRunning == TRUE)) || - (Level == RTMP_HALT)) - { - pAd->Mlme.bPsPollTimerRunning = FALSE; - RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); - RTMPusecDelay(5000); - DBGPRINT(RT_DEBUG_TRACE, ("=======AsicForceWakeup===bFromTx\n")); - } - - AutoWakeupCfg.word = 0; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - - // If this is called from Halt. ALWAYS force wakeup!!! - if (Level == RTMP_HALT) - { - RT28xxPciAsicRadioOn(pAd, RTMP_HALT); - } - else - { - if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE)) - { - // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. - if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) - && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - } - else - { - // Must using 20MHz. - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - } - } - } - } - else - { - // PCI, 2860-PCIe - AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x00); - AutoWakeupCfg.word = 0; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - } - - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); - DBGPRINT(RT_DEBUG_TRACE, ("<=======RT28xxPciStaAsicForceWakeup\n")); -} - -VOID RT28xxPciStaAsicSleepThenAutoWakeup( - IN PRTMP_ADAPTER pAd, - IN USHORT TbttNumToNextWakeUp) -{ - if (pAd->StaCfg.bRadio == FALSE) - { - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); - return; - } - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) - { - ULONG Now = 0; - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) - { - DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); - return; - } - - NdisGetSystemUpTime(&Now); - // If last send NULL fram time is too close to this receiving beacon (within 8ms), don't go to sleep for this DTM. - // Because Some AP can't queuing outgoing frames immediately. - if (((pAd->Mlme.LastSendNULLpsmTime + 8) >= Now) && (pAd->Mlme.LastSendNULLpsmTime <= Now)) - { - DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu : RxCountSinceLastNULL = %lu. \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL)); - return; - } - else if ((pAd->RalinkCounters.RxCountSinceLastNULL > 0) && ((pAd->Mlme.LastSendNULLpsmTime + pAd->CommonCfg.BeaconPeriod) >= Now)) - { - DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu: RxCountSinceLastNULL = %lu > 0 \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL)); - return; - } - - RT28xxPciAsicRadioOff(pAd, DOT11POWERSAVE, TbttNumToNextWakeUp); - } - else - { - AUTO_WAKEUP_STRUC AutoWakeupCfg; - // we have decided to SLEEP, so at least do it for a BEACON period. - if (TbttNumToNextWakeUp == 0) - TbttNumToNextWakeUp = 1; - - AutoWakeupCfg.word = 0; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; - AutoWakeupCfg.field.EnableAutoWakeup = 1; - AutoWakeupCfg.field.AutoLeadTime = 5; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout 40us. - DBGPRINT(RT_DEBUG_TRACE, ("<-- %s, TbttNumToNextWakeUp=%d \n", __func__, TbttNumToNextWakeUp)); - } - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); -} - -VOID PsPollWakeExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; - unsigned long flags; - - DBGPRINT(RT_DEBUG_TRACE,("-->PsPollWakeExec \n")); - RTMP_INT_LOCK(&pAd->irq_lock, flags); - if (pAd->Mlme.bPsPollTimerRunning) - { - RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); - } - pAd->Mlme.bPsPollTimerRunning = FALSE; - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); -} - -VOID RadioOnExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; - WPDMA_GLO_CFG_STRUC DmaCfg; - BOOLEAN Cancelled; - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on fOP_STATUS_DOZE == TRUE; \n")); - RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); - return; - } - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - { - DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on SCAN_IN_PROGRESS; \n")); - RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); - return; - } - pAd->Mlme.bPsPollTimerRunning = FALSE; - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - if (pAd->StaCfg.bRadio == TRUE) - { - pAd->bPCIclkOff = FALSE; - RTMPRingCleanUp(pAd, QID_AC_BK); - RTMPRingCleanUp(pAd, QID_AC_BE); - RTMPRingCleanUp(pAd, QID_AC_VI); - RTMPRingCleanUp(pAd, QID_AC_VO); - RTMPRingCleanUp(pAd, QID_HCCA); - RTMPRingCleanUp(pAd, QID_MGMT); - RTMPRingCleanUp(pAd, QID_RX); - - // 2. Send wake up command. - AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02); - // 2-1. wait command ok. - AsicCheckCommanOk(pAd, PowerWakeCID); - - // When PCI clock is off, don't want to service interrupt. So when back to clock on, enable interrupt. - NICEnableInterrupt(pAd); - - // 3. Enable Tx DMA. - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); - DmaCfg.field.EnableTxDMA = 1; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); - - // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. - if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) - && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - } - else - { - // Must using 20MHz. - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - } - - // Clear Radio off flag - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - - // Set LED - RTMPSetLED(pAd, LED_RADIO_ON); - - if (pAd->StaCfg.Psm == PWR_ACTIVE) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); - } - } - else - { - RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0); - } -} - -VOID RT28xxPciMlmeRadioOn( - IN PRTMP_ADAPTER pAd) -{ - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) - return; - - DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __func__)); - - if ((pAd->OpMode == OPMODE_AP) || - ((pAd->OpMode == OPMODE_STA) && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)))) - { - NICResetFromError(pAd); - - /* - RTMPRingCleanUp(pAd, QID_AC_BK); - RTMPRingCleanUp(pAd, QID_AC_BE); - RTMPRingCleanUp(pAd, QID_AC_VI); - RTMPRingCleanUp(pAd, QID_AC_VO); - RTMPRingCleanUp(pAd, QID_HCCA); - RTMPRingCleanUp(pAd, QID_MGMT); - RTMPRingCleanUp(pAd, QID_RX); - */ - - // Enable Tx/Rx - RTMPEnableRxTx(pAd); - - // Clear Radio off flag - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - - // Set LED - RTMPSetLED(pAd, LED_RADIO_ON); - } - - if ((pAd->OpMode == OPMODE_STA) && - (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))) - { - BOOLEAN Cancelled; - - RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); - - pAd->Mlme.bPsPollTimerRunning = FALSE; - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); - RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); - } -} - -VOID RT28xxPciMlmeRadioOFF( - IN PRTMP_ADAPTER pAd) -{ - WPDMA_GLO_CFG_STRUC GloCfg; - UINT32 i; - - if (pAd->StaCfg.bRadio == TRUE) - { - DBGPRINT(RT_DEBUG_TRACE,("-->MlmeRadioOff() return on bRadio == TRUE; \n")); - return; - } - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) - return; - - DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __func__)); - - // Set LED - RTMPSetLED(pAd, LED_RADIO_OFF); - - { - BOOLEAN Cancelled; - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - { - RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); - } - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) - { - BOOLEAN Cancelled; - - // Always radio on since the NIC needs to set the MCU command (LED_RADIO_OFF). - if ((pAd->OpMode == OPMODE_STA) && - (IDLE_ON(pAd)) && - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) - { - RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); - } - - pAd->Mlme.bPsPollTimerRunning = FALSE; - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); - } - - // Link down first if any association exists - if (INFRA_ON(pAd) || ADHOC_ON(pAd)) - LinkDown(pAd, FALSE); - RTMPusecDelay(10000); - //========================================== - // Clean up old bss table - BssTableInit(&pAd->ScanTab); - - RTMPRingCleanUp(pAd, QID_AC_BK); - RTMPRingCleanUp(pAd, QID_AC_BE); - RTMPRingCleanUp(pAd, QID_AC_VI); - RTMPRingCleanUp(pAd, QID_AC_VO); - RTMPRingCleanUp(pAd, QID_HCCA); - RTMPRingCleanUp(pAd, QID_MGMT); - RTMPRingCleanUp(pAd, QID_RX); - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) - { - RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 500); - return; - } - } - - // Set Radio off flag - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - - // Disable Tx/Rx DMA - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA - GloCfg.field.EnableTxDMA = 0; - GloCfg.field.EnableRxDMA = 0; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); // abort all TX rings - - - // MAC_SYS_CTRL => value = 0x0 => 40mA - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0); - - // PWR_PIN_CFG => value = 0x0 => 40mA - RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0); - - // TX_PIN_CFG => value = 0x0 => 20mA - RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0); - - if (pAd->CommonCfg.BBPCurrentBW == BW_40) - { - // Must using 40MHz. - AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); - } - else - { - // Must using 20MHz. - AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); - } - - // Waiting for DMA idle - i = 0; - do - { - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); - if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) - break; - - RTMPusecDelay(1000); - }while (i++ < 100); -} diff --git a/drivers/staging/rt2860/common/cmm_data_pci.c b/drivers/staging/rt2860/common/cmm_data_pci.c new file mode 100644 index 0000000000000000000000000000000000000000..43d73a05c8eba24a51fbb3a100c8ab5630790c1e --- /dev/null +++ b/drivers/staging/rt2860/common/cmm_data_pci.c @@ -0,0 +1,1096 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* + */ + +/* + All functions in this file must be PCI-depended, or you should out your function + in other files. + +*/ +#include "../rt_config.h" + +u16 RtmpPCI_WriteTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + IN BOOLEAN bIsLast, u16 * FreeNumber) +{ + + u8 *pDMAHeaderBufVA; + u16 TxIdx, RetTxIdx; + struct rt_txd * pTxD; + u32 BufBasePaLow; + struct rt_rtmp_tx_ring *pTxRing; + u16 hwHeaderLen; + + /* */ + /* get Tx Ring Resource */ + /* */ + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; + pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + BufBasePaLow = + RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + + /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ + if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) { + /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */ + hwHeaderLen = + pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; + } else { + /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ + hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + } + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, + TXINFO_SIZE + TXWI_SIZE + hwHeaderLen); + + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + + /* */ + /* build Tx Descriptor */ + /* */ + + pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa; + NdisZeroMemory(pTxD, TXD_SIZE); + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; /* include padding */ + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE); + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = 0; + pTxD->LastSec1 = (bIsLast) ? 1 : 0; + + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); + + RetTxIdx = TxIdx; + /* */ + /* Update Tx index */ + /* */ + INC_RING_INDEX(TxIdx, TX_RING_SIZE); + pTxRing->TxCpuIdx = TxIdx; + + *FreeNumber -= 1; + + return RetTxIdx; +} + +u16 RtmpPCI_WriteSingleTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + IN BOOLEAN bIsLast, + u16 * FreeNumber) +{ + + u8 *pDMAHeaderBufVA; + u16 TxIdx, RetTxIdx; + struct rt_txd * pTxD; + u32 BufBasePaLow; + struct rt_rtmp_tx_ring *pTxRing; + u16 hwHeaderLen; + + /* */ + /* get Tx Ring Resource */ + /* */ + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; + pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + BufBasePaLow = + RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + + /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ + /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ + hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, + TXINFO_SIZE + TXWI_SIZE + hwHeaderLen); + + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + + /* */ + /* build Tx Descriptor */ + /* */ + pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa; + NdisZeroMemory(pTxD, TXD_SIZE); + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; /* include padding */ + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);; + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = 0; + pTxD->LastSec1 = (bIsLast) ? 1 : 0; + + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); + + RetTxIdx = TxIdx; + /* */ + /* Update Tx index */ + /* */ + INC_RING_INDEX(TxIdx, TX_RING_SIZE); + pTxRing->TxCpuIdx = TxIdx; + + *FreeNumber -= 1; + + return RetTxIdx; +} + +u16 RtmpPCI_WriteMultiTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + u8 frameNum, u16 * FreeNumber) +{ + BOOLEAN bIsLast; + u8 *pDMAHeaderBufVA; + u16 TxIdx, RetTxIdx; + struct rt_txd * pTxD; + u32 BufBasePaLow; + struct rt_rtmp_tx_ring *pTxRing; + u16 hwHdrLen; + u32 firstDMALen; + + bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0); + + /* */ + /* get Tx Ring Resource */ + /* */ + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; + pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + BufBasePaLow = + RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + + if (frameNum == 0) { + /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ + if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) + /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */ + hwHdrLen = + pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; + else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) + /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; */ + hwHdrLen = + pTxBlk->MpduHeaderLen - + LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + + LENGTH_ARALINK_HEADER_FIELD; + else + /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ + hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; + } else { + firstDMALen = pTxBlk->MpduHeaderLen; + } + + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); + + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + + /* */ + /* build Tx Descriptor */ + /* */ + pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa; + NdisZeroMemory(pTxD, TXD_SIZE); + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = firstDMALen; /* include padding */ + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);; + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = 0; + pTxD->LastSec1 = (bIsLast) ? 1 : 0; + + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); + + RetTxIdx = TxIdx; + /* */ + /* Update Tx index */ + /* */ + INC_RING_INDEX(TxIdx, TX_RING_SIZE); + pTxRing->TxCpuIdx = TxIdx; + + *FreeNumber -= 1; + + return RetTxIdx; + +} + +void RtmpPCI_FinalWriteTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + u16 totalMPDUSize, u16 FirstTxIdx) +{ + + struct rt_txwi * pTxWI; + struct rt_rtmp_tx_ring *pTxRing; + + /* */ + /* get Tx Ring Resource */ + /* */ + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + pTxWI = (struct rt_txwi *) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa; + pTxWI->MPDUtotalByteCount = totalMPDUSize; + +} + +void RtmpPCIDataLastTxIdx(struct rt_rtmp_adapter *pAd, + u8 QueIdx, u16 LastTxIdx) +{ + struct rt_txd * pTxD; + struct rt_rtmp_tx_ring *pTxRing; + + /* */ + /* get Tx Ring Resource */ + /* */ + pTxRing = &pAd->TxRing[QueIdx]; + + /* */ + /* build Tx Descriptor */ + /* */ + pTxD = (struct rt_txd *) pTxRing->Cell[LastTxIdx].AllocVa; + + pTxD->LastSec1 = 1; + +} + +u16 RtmpPCI_WriteFragTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + u8 fragNum, u16 * FreeNumber) +{ + u8 *pDMAHeaderBufVA; + u16 TxIdx, RetTxIdx; + struct rt_txd * pTxD; + u32 BufBasePaLow; + struct rt_rtmp_tx_ring *pTxRing; + u16 hwHeaderLen; + u32 firstDMALen; + + /* */ + /* Get Tx Ring Resource */ + /* */ + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; + pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + BufBasePaLow = + RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + + /* */ + /* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ + /* */ + /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ + hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); + + /* */ + /* Build Tx Descriptor */ + /* */ + pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa; + NdisZeroMemory(pTxD, TXD_SIZE); + + if (fragNum == pTxBlk->TotalFragNum) { + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + } + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = firstDMALen; /* include padding */ + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE); + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = 0; + pTxD->LastSec1 = 1; + + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); + + RetTxIdx = TxIdx; + pTxBlk->Priv += pTxBlk->SrcBufLen; + + /* */ + /* Update Tx index */ + /* */ + INC_RING_INDEX(TxIdx, TX_RING_SIZE); + pTxRing->TxCpuIdx = TxIdx; + + *FreeNumber -= 1; + + return RetTxIdx; + +} + +/* + Must be run in Interrupt context + This function handle PCI specific TxDesc and cpu index update and kick the packet out. + */ +int RtmpPCIMgmtKickOut(struct rt_rtmp_adapter *pAd, + u8 QueIdx, + void *pPacket, + u8 *pSrcBufVA, u32 SrcBufLen) +{ + struct rt_txd * pTxD; + unsigned long SwIdx = pAd->MgmtRing.TxCpuIdx; + + pTxD = (struct rt_txd *) pAd->MgmtRing.Cell[SwIdx].AllocVa; + + pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket; + pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL; + + RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT); + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 1; + pTxD->DMADONE = 0; + pTxD->SDLen1 = 0; + pTxD->SDPtr0 = + PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE); + pTxD->SDLen0 = SrcBufLen; + +/*================================================================== */ +/* DBGPRINT_RAW(RT_DEBUG_TRACE, ("MLMEHardTransmit\n")); + for (i = 0; i < (TXWI_SIZE+24); i++) + { + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%x:", *(pSrcBufVA+i))); + if ( i%4 == 3) + DBGPRINT_RAW(RT_DEBUG_TRACE, (" :: ")); + if ( i%16 == 15) + DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n ")); + } + DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n "));*/ +/*======================================================================= */ + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + /* Increase TX_CTX_IDX, but write to register later. */ + INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); + + RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); + + return 0; +} + +/* + ======================================================================== + + Routine Description: + Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound + + Arguments: + pRxD Pointer to the Rx descriptor + + Return Value: + NDIS_STATUS_SUCCESS No err + NDIS_STATUS_FAILURE Error + + Note: + + ======================================================================== +*/ +int RTMPCheckRxError(struct rt_rtmp_adapter *pAd, + struct rt_header_802_11 * pHeader, + struct rt_rxwi * pRxWI, IN PRT28XX_RXD_STRUC pRxD) +{ + struct rt_cipher_key *pWpaKey; + int dBm; + + /* Phy errors & CRC errors */ + if ( /*(pRxD->PhyErr) || */ (pRxD->Crc)) { + /* Check RSSI for Noise Hist statistic collection. */ + dBm = (int)(pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta; + if (dBm <= -87) + pAd->StaCfg.RPIDensity[0] += 1; + else if (dBm <= -82) + pAd->StaCfg.RPIDensity[1] += 1; + else if (dBm <= -77) + pAd->StaCfg.RPIDensity[2] += 1; + else if (dBm <= -72) + pAd->StaCfg.RPIDensity[3] += 1; + else if (dBm <= -67) + pAd->StaCfg.RPIDensity[4] += 1; + else if (dBm <= -62) + pAd->StaCfg.RPIDensity[5] += 1; + else if (dBm <= -57) + pAd->StaCfg.RPIDensity[6] += 1; + else if (dBm > -57) + pAd->StaCfg.RPIDensity[7] += 1; + + return (NDIS_STATUS_FAILURE); + } + /* Add Rx size to channel load counter, we should ignore error counts */ + pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14); + + /* Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics */ + if (pHeader != NULL) { + if (pHeader->FC.ToDs) { + return (NDIS_STATUS_FAILURE); + } + } + /* Drop not U2M frames, cant's drop here because we will drop beacon in this case */ + /* I am kind of doubting the U2M bit operation */ + /* if (pRxD->U2M == 0) */ + /* return(NDIS_STATUS_FAILURE); */ + + /* drop decyption fail frame */ + if (pRxD->CipherErr) { + if (pRxD->CipherErr == 2) { + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("pRxD ERROR: ICV ok but MICErr ")); + } else if (pRxD->CipherErr == 1) { + DBGPRINT_RAW(RT_DEBUG_TRACE, ("pRxD ERROR: ICV Err ")); + } else if (pRxD->CipherErr == 3) + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("pRxD ERROR: Key not valid ")); + + if (((pRxD->CipherErr & 1) == 1) + && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd)) + RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, + pAd->MacTab.Content[BSSID_WCID]. + Addr, BSS0, 0); + + DBGPRINT_RAW(RT_DEBUG_TRACE, + (" %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n", + pRxD->CipherErr, pRxD->SDL0, + pRxD->Mcast | pRxD->Bcast, pRxD->MyBss, + pRxWI->WirelessCliID, +/* CipherName[pRxD->CipherAlg], */ + pRxWI->KeyIndex)); + + /* */ + /* MIC Error */ + /* */ + if (pRxD->CipherErr == 2) { + pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex]; + if (pAd->StaCfg.WpaSupplicantUP) + WpaSendMicFailureToWpaSupplicant(pAd, + (pWpaKey-> + Type == + PAIRWISEKEY) ? + TRUE : FALSE); + else + RTMPReportMicError(pAd, pWpaKey); + + if (((pRxD->CipherErr & 2) == 2) + && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd)) + RTMPSendWirelessEvent(pAd, + IW_MIC_ERROR_EVENT_FLAG, + pAd->MacTab. + Content[BSSID_WCID].Addr, + BSS0, 0); + + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Rx MIC Value error\n")); + } + + if (pHeader == NULL) + return (NDIS_STATUS_SUCCESS); + /*if ((pRxD->CipherAlg == CIPHER_AES) && + (pHeader->Sequence == pAd->FragFrame.Sequence)) + { + // + // Acceptable since the First FragFrame no CipherErr problem. + // + return(NDIS_STATUS_SUCCESS); + } */ + + return (NDIS_STATUS_FAILURE); + } + + return (NDIS_STATUS_SUCCESS); +} + +BOOLEAN RTMPFreeTXDUponTxDmaDone(struct rt_rtmp_adapter *pAd, u8 QueIdx) +{ + struct rt_rtmp_tx_ring *pTxRing; + struct rt_txd * pTxD; + void *pPacket; + u8 FREE = 0; + struct rt_txd TxD, *pOriTxD; + /*unsigned long IrqFlags; */ + BOOLEAN bReschedule = FALSE; + + ASSERT(QueIdx < NUM_OF_TX_RING); + pTxRing = &pAd->TxRing[QueIdx]; + + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, + &pTxRing->TxDmaIdx); + while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx) { +/* RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); */ + + /* static rate also need NICUpdateFifoStaCounters() function. */ + /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ + NICUpdateFifoStaCounters(pAd); + + /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */ + FREE++; + pTxD = + (struct rt_txd *) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); + pOriTxD = pTxD; + NdisMoveMemory(&TxD, pTxD, sizeof(struct rt_txd)); + pTxD = &TxD; + + pTxD->DMADONE = 0; + + { + pPacket = + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket; + if (pPacket) { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, + pTxD->SDLen1, + PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, + NDIS_STATUS_SUCCESS); + } + /*Always assign pNdisPacket as NULL after clear */ + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL; + + pPacket = + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket; + + ASSERT(pPacket == NULL); + if (pPacket) { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, + pTxD->SDLen1, + PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, + NDIS_STATUS_SUCCESS); + } + /*Always assign pNextNdisPacket as NULL after clear */ + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = + NULL; + } + + pAd->RalinkCounters.TransmittedByteCount += + (pTxD->SDLen1 + pTxD->SDLen0); + pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx]++; + INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); + /* get tx_tdx_idx again */ + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, + &pTxRing->TxDmaIdx); + NdisMoveMemory(pOriTxD, pTxD, sizeof(struct rt_txd)); + +/* RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); */ + } + + return bReschedule; + +} + +/* + ======================================================================== + + Routine Description: + Process TX Rings DMA Done interrupt, running in DPC level + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(struct rt_rtmp_adapter *pAd, + INT_SOURCE_CSR_STRUC TxRingBitmap) +{ +/* u8 Count = 0; */ + unsigned long IrqFlags; + BOOLEAN bReschedule = FALSE; + + /* Make sure Tx ring resource won't be used by other threads */ + /*NdisAcquireSpinLock(&pAd->TxRingLock); */ + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + + if (TxRingBitmap.field.Ac0DmaDone) + bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE); + + if (TxRingBitmap.field.Ac3DmaDone) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO); + + if (TxRingBitmap.field.Ac2DmaDone) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI); + + if (TxRingBitmap.field.Ac1DmaDone) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK); + + /* Make sure to release Tx ring resource */ + /*NdisReleaseSpinLock(&pAd->TxRingLock); */ + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + /* Dequeue outgoing frames from TxSwQueue[] and process it */ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + + return bReschedule; +} + +/* + ======================================================================== + + Routine Description: + Process MGMT ring DMA done interrupt, running in DPC level + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +void RTMPHandleMgmtRingDmaDoneInterrupt(struct rt_rtmp_adapter *pAd) +{ + struct rt_txd * pTxD; + void *pPacket; +/* int i; */ + u8 FREE = 0; + struct rt_rtmp_mgmt_ring *pMgmtRing = &pAd->MgmtRing; + + NdisAcquireSpinLock(&pAd->MgmtRingLock); + + RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx); + while (pMgmtRing->TxSwFreeIdx != pMgmtRing->TxDmaIdx) { + FREE++; + pTxD = + (struct rt_txd *) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx]. + AllocVa); + pTxD->DMADONE = 0; + pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket; + + if (pPacket) { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, + PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL; + + pPacket = + pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket; + if (pPacket) { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, + PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL; + INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE); + + } + NdisReleaseSpinLock(&pAd->MgmtRingLock); + +} + +/* + ======================================================================== + + Routine Description: + Arguments: + Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon. + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +void RTMPHandleTBTTInterrupt(struct rt_rtmp_adapter *pAd) +{ + { + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { + } + } +} + +/* + ======================================================================== + + Routine Description: + Arguments: + pAd Pointer to our adapter. Rewrite beacon content before next send-out. + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +void RTMPHandlePreTBTTInterrupt(struct rt_rtmp_adapter *pAd) +{ + { + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPHandlePreTBTTInterrupt...\n")); + } + } + +} + +void RTMPHandleRxCoherentInterrupt(struct rt_rtmp_adapter *pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + + if (pAd == NULL) { + DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n")); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n")); + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + + GloCfg.field.EnTXWriteBackDDONE = 0; + GloCfg.field.EnableRxDMA = 0; + GloCfg.field.EnableTxDMA = 0; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + + RTMPRingCleanUp(pAd, QID_AC_BE); + RTMPRingCleanUp(pAd, QID_AC_BK); + RTMPRingCleanUp(pAd, QID_AC_VI); + RTMPRingCleanUp(pAd, QID_AC_VO); + RTMPRingCleanUp(pAd, QID_MGMT); + RTMPRingCleanUp(pAd, QID_RX); + + RTMPEnableRxTx(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n")); +} + +void *GetPacketFromRxRing(struct rt_rtmp_adapter *pAd, + OUT PRT28XX_RXD_STRUC pSaveRxD, + OUT BOOLEAN * pbReschedule, + IN u32 * pRxPending) +{ + struct rt_rxd * pRxD; + void *pRxPacket = NULL; + void *pNewPacket; + void *AllocVa; + dma_addr_t AllocPa; + BOOLEAN bReschedule = FALSE; + struct rt_rtmp_dmacb *pRxCell; + + RTMP_SEM_LOCK(&pAd->RxRingLock); + + if (*pRxPending == 0) { + /* Get how may packets had been received */ + RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx); + + if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx) { + /* no more rx packets */ + bReschedule = FALSE; + goto done; + } + /* get rx pending count */ + if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx) + *pRxPending = + pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx; + else + *pRxPending = + pAd->RxRing.RxDmaIdx + RX_RING_SIZE - + pAd->RxRing.RxSwReadIdx; + + } + + pRxCell = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx]; + + /* Point to Rx indexed rx ring descriptor */ + pRxD = (struct rt_rxd *) pRxCell->AllocVa; + + if (pRxD->DDONE == 0) { + *pRxPending = 0; + /* DMAIndx had done but DDONE bit not ready */ + bReschedule = TRUE; + goto done; + } + + /* return rx descriptor */ + NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE); + + pNewPacket = + RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, + &AllocVa, &AllocPa); + + if (pNewPacket) { + /* unmap the rx buffer */ + PCI_UNMAP_SINGLE(pAd, pRxCell->DmaBuf.AllocPa, + pRxCell->DmaBuf.AllocSize, PCI_DMA_FROMDEVICE); + pRxPacket = pRxCell->pNdisPacket; + + pRxCell->DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE; + pRxCell->pNdisPacket = (void *)pNewPacket; + pRxCell->DmaBuf.AllocVa = AllocVa; + pRxCell->DmaBuf.AllocPa = AllocPa; + /* update SDP0 to new buffer of rx packet */ + pRxD->SDP0 = AllocPa; + } else { + /*DBGPRINT(RT_DEBUG_TRACE,("No Rx Buffer\n")); */ + pRxPacket = NULL; + bReschedule = TRUE; + } + + pRxD->DDONE = 0; + + /* had handled one rx packet */ + *pRxPending = *pRxPending - 1; + + /* update rx descriptor and kick rx */ + INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); + + pAd->RxRing.RxCpuIdx = + (pAd->RxRing.RxSwReadIdx == + 0) ? (RX_RING_SIZE - 1) : (pAd->RxRing.RxSwReadIdx - 1); + RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); + +done: + RTMP_SEM_UNLOCK(&pAd->RxRingLock); + *pbReschedule = bReschedule; + return pRxPacket; +} + +int MlmeHardTransmitTxRing(struct rt_rtmp_adapter *pAd, + u8 QueIdx, void *pPacket) +{ + struct rt_packet_info PacketInfo; + u8 *pSrcBufVA; + u32 SrcBufLen; + struct rt_txd * pTxD; + struct rt_header_802_11 * pHeader_802_11; + BOOLEAN bAckRequired, bInsertTimestamp; + unsigned long SrcBufPA; + /*u8 TxBufIdx; */ + u8 MlmeRate; + unsigned long SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; + struct rt_txwi * pFirstTxWI; + /*unsigned long i; */ + /*HTTRANSMIT_SETTING MlmeTransmit; //Rate for this MGMT frame. */ + unsigned long FreeNum; + struct rt_mac_table_entry *pMacEntry = NULL; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + if (pSrcBufVA == NULL) { + /* The buffer shouldn't be NULL */ + return NDIS_STATUS_FAILURE; + } + /* Make sure MGMT ring resource won't be used by other threads */ + /*NdisAcquireSpinLock(&pAd->TxRingLock); */ + + FreeNum = GET_TXRING_FREENO(pAd, QueIdx); + + if (FreeNum == 0) { + /*NdisReleaseSpinLock(&pAd->TxRingLock); */ + return NDIS_STATUS_FAILURE; + } + + SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; + + pTxD = (struct rt_txd *) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; + + if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket) { + DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n")); + /*NdisReleaseSpinLock(&pAd->TxRingLock); */ + return NDIS_STATUS_FAILURE; + } + + { + /* outgoing frame always wakeup PHY to prevent frame lost */ + /* if (pAd->StaCfg.Psm == PWR_SAVE) */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + AsicForceWakeup(pAd, TRUE); + } + pFirstTxWI = (struct rt_txwi *) pSrcBufVA; + + pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXWI_SIZE); + if (pHeader_802_11->Addr1[0] & 0x01) { + MlmeRate = pAd->CommonCfg.BasicMlmeRate; + } else { + MlmeRate = pAd->CommonCfg.MlmeRate; + } + + if ((pHeader_802_11->FC.Type == BTYPE_DATA) && + (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) { + pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + } + /* Verify Mlme rate for a / g bands. */ + if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band */ + MlmeRate = RATE_6; + + /* */ + /* Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) */ + /* Snice it's been set to 0 while on MgtMacHeaderInit */ + /* By the way this will cause frame to be send on PWR_SAVE failed. */ + /* */ + /* */ + /* In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame */ + /* Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */ + if (pHeader_802_11->FC.Type != BTYPE_DATA) { + if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) + || !(pAd->CommonCfg.bAPSDCapable + && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) { + pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; + } else { + pHeader_802_11->FC.PwrMgmt = + pAd->CommonCfg.bAPSDForcePowerSave; + } + } + + bInsertTimestamp = FALSE; + if (pHeader_802_11->FC.Type == BTYPE_CNTL) /* must be PS-POLL */ + { + bAckRequired = FALSE; + } else /* BTYPE_MGMT or BTYPE_DATA(must be NULL frame) */ + { + if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST */ + { + bAckRequired = FALSE; + pHeader_802_11->Duration = 0; + } else { + bAckRequired = TRUE; + pHeader_802_11->Duration = + RTMPCalcDuration(pAd, MlmeRate, 14); + if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) { + bInsertTimestamp = TRUE; + } + } + } + pHeader_802_11->Sequence = pAd->Sequence++; + if (pAd->Sequence > 0xfff) + pAd->Sequence = 0; + /* Before radar detection done, mgmt frame can not be sent but probe req */ + /* Because we need to use probe req to trigger driver to send probe req in passive scan */ + if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) + && (pAd->CommonCfg.bIEEE80211H == 1) + && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) { + DBGPRINT(RT_DEBUG_ERROR, + ("MlmeHardTransmit --> radar detect not in normal mode!\n")); + /*NdisReleaseSpinLock(&pAd->TxRingLock); */ + return (NDIS_STATUS_FAILURE); + } + /* */ + /* fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET */ + /* should always has only one ohysical buffer, and the whole frame size equals */ + /* to the first scatter buffer size */ + /* */ + + /* Initialize TX Descriptor */ + /* For inter-frame gap, the number is for this frame and next frame */ + /* For MLME rate, we will fix as 2Mb to match other vendor's implement */ +/* pAd->CommonCfg.MlmeTransmit.field.MODE = 1; */ + +/* management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. */ + /* Only beacon use Nseq=TRUE. So here we use Nseq=FALSE. */ + if (pMacEntry == NULL) { + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, + FALSE, bAckRequired, FALSE, 0, RESERVED_WCID, + (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, + (u8)pAd->CommonCfg.MlmeTransmit.field.MCS, + IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); + } else { + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, + bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE), + pMacEntry->MaxHTPhyMode.field.MCS, 0, + (u8)pMacEntry->MaxHTPhyMode.field.MCS, + IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); + } + + pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket; + pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL; +/* pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE; */ + SrcBufPA = + PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE); + + RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA); + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 1; + pTxD->SDLen0 = SrcBufLen; + pTxD->SDLen1 = 0; + pTxD->SDPtr0 = SrcBufPA; + pTxD->DMADONE = 0; + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + /* Increase TX_CTX_IDX, but write to register later. */ + INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); + + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * 0x10, + pAd->TxRing[QueIdx].TxCpuIdx); + + /* Make sure to release MGMT ring resource */ +/* NdisReleaseSpinLock(&pAd->TxRingLock); */ + + return NDIS_STATUS_SUCCESS; +} + +int MlmeDataHardTransmit(struct rt_rtmp_adapter *pAd, + u8 QueIdx, void *pPacket) +{ + if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) + ) { + return NDIS_STATUS_FAILURE; + } + + return MlmeHardTransmitTxRing(pAd, QueIdx, pPacket); +} + +/* + ======================================================================== + + Routine Description: + Calculates the duration which is required to transmit out frames + with given size and specified rate. + + Arguments: + pTxD Pointer to transmit descriptor + Ack Setting for Ack requirement bit + Fragment Setting for Fragment bit + RetryMode Setting for retry mode + Ifs Setting for IFS gap + Rate Setting for transmit rate + Service Setting for service + Length Frame length + TxPreamble Short or Long preamble when using CCK rates + QueIdx - 0-3, according to 802.11e/d4.4 June/2003 + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +void RTMPWriteTxDescriptor(struct rt_rtmp_adapter *pAd, + struct rt_txd * pTxD, + IN BOOLEAN bWIV, u8 QueueSEL) +{ + /* */ + /* Always use Long preamble before verifiation short preamble functionality works well. */ + /* Todo: remove the following line if short preamble functionality works */ + /* */ + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + + pTxD->WIV = (bWIV) ? 1 : 0; + pTxD->QSEL = (QueueSEL); + /*RT2860c?? fixed using EDCA queue for test... We doubt Queue1 has problem. 2006-09-26 Jan */ + /*pTxD->QSEL= FIFO_EDCA; */ + pTxD->DMADONE = 0; +} diff --git a/drivers/staging/rt2860/common/cmm_data_usb.c b/drivers/staging/rt2860/common/cmm_data_usb.c new file mode 100644 index 0000000000000000000000000000000000000000..7c56c2f519876dfe226a0c034e6346fb41af5564 --- /dev/null +++ b/drivers/staging/rt2860/common/cmm_data_usb.c @@ -0,0 +1,951 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* +*/ + +/* + All functions in this file must be USB-depended, or you should out your function + in other files. + +*/ + +#ifdef RTMP_MAC_USB + +#include "../rt_config.h" + +/* + We can do copy the frame into pTxContext when match following conditions. + => + => + => +*/ +static inline int RtmpUSBCanDoWrite(struct rt_rtmp_adapter *pAd, + u8 QueIdx, + struct rt_ht_tx_context *pHTTXContext) +{ + int canWrite = NDIS_STATUS_RESOURCES; + + if (((pHTTXContext->CurWritePosition) < + pHTTXContext->NextBulkOutPosition) + && (pHTTXContext->CurWritePosition + LOCAL_TXBUF_SIZE) > + pHTTXContext->NextBulkOutPosition) { + DBGPRINT(RT_DEBUG_ERROR, ("RtmpUSBCanDoWrite c1!\n")); + RTUSB_SET_BULK_FLAG(pAd, + (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx)); + } else if ((pHTTXContext->CurWritePosition == 8) + && (pHTTXContext->NextBulkOutPosition < LOCAL_TXBUF_SIZE)) { + DBGPRINT(RT_DEBUG_ERROR, ("RtmpUSBCanDoWrite c2!\n")); + RTUSB_SET_BULK_FLAG(pAd, + (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx)); + } else if (pHTTXContext->bCurWriting == TRUE) { + DBGPRINT(RT_DEBUG_ERROR, ("RtmpUSBCanDoWrite c3!\n")); + } else { + canWrite = NDIS_STATUS_SUCCESS; + } + + return canWrite; +} + +u16 RtmpUSB_WriteSubTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + IN BOOLEAN bIsLast, u16 * FreeNumber) +{ + + /* Dummy function. Should be removed in the future. */ + return 0; + +} + +u16 RtmpUSB_WriteFragTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + u8 fragNum, u16 * FreeNumber) +{ + struct rt_ht_tx_context *pHTTXContext; + u16 hwHdrLen; /* The hwHdrLen consist of 802.11 header length plus the header padding length. */ + u32 fillOffset; + struct rt_txinfo *pTxInfo; + struct rt_txwi *pTxWI; + u8 *pWirelessPacket = NULL; + u8 QueIdx; + int Status; + unsigned long IrqFlags; + u32 USBDMApktLen = 0, DMAHdrLen, padding; + BOOLEAN TxQLastRound = FALSE; + + /* */ + /* get Tx Ring Resource & Dma Buffer address */ + /* */ + QueIdx = pTxBlk->QueIdx; + pHTTXContext = &pAd->TxContext[QueIdx]; + + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + pHTTXContext = &pAd->TxContext[QueIdx]; + fillOffset = pHTTXContext->CurWritePosition; + + if (fragNum == 0) { + /* Check if we have enough space for this bulk-out batch. */ + Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); + if (Status == NDIS_STATUS_SUCCESS) { + pHTTXContext->bCurWriting = TRUE; + + /* Reserve space for 8 bytes padding. */ + if ((pHTTXContext->ENextBulkOutPosition == + pHTTXContext->CurWritePosition)) { + pHTTXContext->ENextBulkOutPosition += 8; + pHTTXContext->CurWritePosition += 8; + fillOffset += 8; + } + pTxBlk->Priv = 0; + pHTTXContext->CurWriteRealPos = + pHTTXContext->CurWritePosition; + } else { + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], + IrqFlags); + + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, + NDIS_STATUS_FAILURE); + return (Status); + } + } else { + /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. */ + Status = + ((pHTTXContext->bCurWriting == + TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); + if (Status == NDIS_STATUS_SUCCESS) { + fillOffset += pTxBlk->Priv; + } else { + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], + IrqFlags); + + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, + NDIS_STATUS_FAILURE); + return (Status); + } + } + + NdisZeroMemory((u8 *)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE); + pTxInfo = (struct rt_txinfo *)(&pTxBlk->HeaderBuf[0]); + pTxWI = (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]); + + pWirelessPacket = + &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; + + /* copy TXWI + WLAN Header + LLC into DMA Header Buffer */ + /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ + hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + /* Build our URB for USBD */ + DMAHdrLen = TXWI_SIZE + hwHdrLen; + USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; + padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment */ + USBDMApktLen += padding; + + pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen); + + /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload */ + RTMPWriteTxInfo(pAd, pTxInfo, (u16)(USBDMApktLen), FALSE, FIFO_EDCA, + FALSE /*NextValid */ , FALSE); + + if (fragNum == pTxBlk->TotalFragNum) { + pTxInfo->USBDMATxburst = 0; + if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906) > + MAX_TXBULK_LIMIT) { + pTxInfo->SwUseLastRound = 1; + TxQLastRound = TRUE; + } + } else { + pTxInfo->USBDMATxburst = 1; + } + + NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, + TXINFO_SIZE + TXWI_SIZE + hwHdrLen); + pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); + pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); + + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + + /* Zero the last padding. */ + pWirelessPacket += pTxBlk->SrcBufLen; + NdisZeroMemory(pWirelessPacket, padding + 8); + + if (fragNum == pTxBlk->TotalFragNum) { + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + /* Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame. */ + pHTTXContext->CurWritePosition += pTxBlk->Priv; + if (TxQLastRound == TRUE) + pHTTXContext->CurWritePosition = 8; + pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; + + /* Finally, set bCurWriting as FALSE */ + pHTTXContext->bCurWriting = FALSE; + + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + /* succeed and release the skb buffer */ + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); + } + + return (Status); + +} + +u16 RtmpUSB_WriteSingleTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + IN BOOLEAN bIsLast, + u16 * FreeNumber) +{ + struct rt_ht_tx_context *pHTTXContext; + u16 hwHdrLen; + u32 fillOffset; + struct rt_txinfo *pTxInfo; + struct rt_txwi *pTxWI; + u8 *pWirelessPacket; + u8 QueIdx; + unsigned long IrqFlags; + int Status; + u32 USBDMApktLen = 0, DMAHdrLen, padding; + BOOLEAN bTxQLastRound = FALSE; + + /* For USB, didn't need PCI_MAP_SINGLE() */ + /*SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE); */ + + /* */ + /* get Tx Ring Resource & Dma Buffer address */ + /* */ + QueIdx = pTxBlk->QueIdx; + + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + pHTTXContext = &pAd->TxContext[QueIdx]; + fillOffset = pHTTXContext->CurWritePosition; + + /* Check ring full. */ + Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); + if (Status == NDIS_STATUS_SUCCESS) { + pHTTXContext->bCurWriting = TRUE; + + pTxInfo = (struct rt_txinfo *)(&pTxBlk->HeaderBuf[0]); + pTxWI = (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]); + + /* Reserve space for 8 bytes padding. */ + if ((pHTTXContext->ENextBulkOutPosition == + pHTTXContext->CurWritePosition)) { + pHTTXContext->ENextBulkOutPosition += 8; + pHTTXContext->CurWritePosition += 8; + fillOffset += 8; + } + pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; + + pWirelessPacket = + &pHTTXContext->TransferBuffer->field. + WirelessPacket[fillOffset]; + + /* copy TXWI + WLAN Header + LLC into DMA Header Buffer */ + /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ + hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + /* Build our URB for USBD */ + DMAHdrLen = TXWI_SIZE + hwHdrLen; + USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; + padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment */ + USBDMApktLen += padding; + + pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen); + + /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload */ + RTMPWriteTxInfo(pAd, pTxInfo, (u16)(USBDMApktLen), FALSE, + FIFO_EDCA, FALSE /*NextValid */ , FALSE); + + if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > + MAX_TXBULK_LIMIT) { + pTxInfo->SwUseLastRound = 1; + bTxQLastRound = TRUE; + } + NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, + TXINFO_SIZE + TXWI_SIZE + hwHdrLen); + pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); + + /* We unlock it here to prevent the first 8 bytes maybe over-writed issue. */ + /* 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext. */ + /* 2. An interrupt break our routine and handle bulk-out complete. */ + /* 3. In the bulk-out compllete, it need to do another bulk-out, */ + /* if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, */ + /* but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. */ + /* 4. Interrupt complete. */ + /* 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. */ + /* 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. */ + /* and the packet will wrong. */ + pHTTXContext->CurWriteRealPos += + (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, + pTxBlk->SrcBufLen); + pWirelessPacket += pTxBlk->SrcBufLen; + NdisZeroMemory(pWirelessPacket, padding + 8); + + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + pHTTXContext->CurWritePosition += pTxBlk->Priv; + if (bTxQLastRound) + pHTTXContext->CurWritePosition = 8; + pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; + + pHTTXContext->bCurWriting = FALSE; + } + + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + /* succeed and release the skb buffer */ + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); + + return (Status); + +} + +u16 RtmpUSB_WriteMultiTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + u8 frameNum, u16 * FreeNumber) +{ + struct rt_ht_tx_context *pHTTXContext; + u16 hwHdrLen; /* The hwHdrLen consist of 802.11 header length plus the header padding length. */ + u32 fillOffset; + struct rt_txinfo *pTxInfo; + struct rt_txwi *pTxWI; + u8 *pWirelessPacket = NULL; + u8 QueIdx; + int Status; + unsigned long IrqFlags; + /*u32 USBDMApktLen = 0, DMAHdrLen, padding; */ + + /* */ + /* get Tx Ring Resource & Dma Buffer address */ + /* */ + QueIdx = pTxBlk->QueIdx; + pHTTXContext = &pAd->TxContext[QueIdx]; + + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + if (frameNum == 0) { + /* Check if we have enough space for this bulk-out batch. */ + Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); + if (Status == NDIS_STATUS_SUCCESS) { + pHTTXContext->bCurWriting = TRUE; + + pTxInfo = (struct rt_txinfo *)(&pTxBlk->HeaderBuf[0]); + pTxWI = (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]); + + /* Reserve space for 8 bytes padding. */ + if ((pHTTXContext->ENextBulkOutPosition == + pHTTXContext->CurWritePosition)) { + + pHTTXContext->CurWritePosition += 8; + pHTTXContext->ENextBulkOutPosition += 8; + } + fillOffset = pHTTXContext->CurWritePosition; + pHTTXContext->CurWriteRealPos = + pHTTXContext->CurWritePosition; + + pWirelessPacket = + &pHTTXContext->TransferBuffer->field. + WirelessPacket[fillOffset]; + + /* */ + /* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ + /* */ + if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) + /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */ + hwHdrLen = + pTxBlk->MpduHeaderLen - + LENGTH_AMSDU_SUBFRAMEHEAD + + pTxBlk->HdrPadLen + + LENGTH_AMSDU_SUBFRAMEHEAD; + else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) + /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; */ + hwHdrLen = + pTxBlk->MpduHeaderLen - + LENGTH_ARALINK_HEADER_FIELD + + pTxBlk->HdrPadLen + + LENGTH_ARALINK_HEADER_FIELD; + else + /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ + hwHdrLen = + pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + /* Update the pTxBlk->Priv. */ + pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; + + /* pTxInfo->USBDMApktLen now just a temp value and will to correct latter. */ + RTMPWriteTxInfo(pAd, pTxInfo, (u16)(pTxBlk->Priv), + FALSE, FIFO_EDCA, FALSE /*NextValid */ , + FALSE); + + /* Copy it. */ + NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, + pTxBlk->Priv); + pHTTXContext->CurWriteRealPos += pTxBlk->Priv; + pWirelessPacket += pTxBlk->Priv; + } + } else { /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. */ + + Status = + ((pHTTXContext->bCurWriting == + TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); + if (Status == NDIS_STATUS_SUCCESS) { + fillOffset = + (pHTTXContext->CurWritePosition + pTxBlk->Priv); + pWirelessPacket = + &pHTTXContext->TransferBuffer->field. + WirelessPacket[fillOffset]; + + /*hwHdrLen = pTxBlk->MpduHeaderLen; */ + NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, + pTxBlk->MpduHeaderLen); + pWirelessPacket += (pTxBlk->MpduHeaderLen); + pTxBlk->Priv += pTxBlk->MpduHeaderLen; + } else { /* It should not happened now unless we are going to shutdown. */ + DBGPRINT(RT_DEBUG_ERROR, + ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n")); + Status = NDIS_STATUS_FAILURE; + } + } + + /* We unlock it here to prevent the first 8 bytes maybe over-write issue. */ + /* 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext. */ + /* 2. An interrupt break our routine and handle bulk-out complete. */ + /* 3. In the bulk-out compllete, it need to do another bulk-out, */ + /* if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, */ + /* but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. */ + /* 4. Interrupt complete. */ + /* 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. */ + /* 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. */ + /* and the packet will wrong. */ + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + if (Status != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, + ("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", + pHTTXContext->CurWritePosition, + pHTTXContext->NextBulkOutPosition)); + goto done; + } + /* Copy the frame content into DMA buffer and update the pTxBlk->Priv */ + NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + pWirelessPacket += pTxBlk->SrcBufLen; + pTxBlk->Priv += pTxBlk->SrcBufLen; + +done: + /* Release the skb buffer here */ + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); + + return (Status); + +} + +void RtmpUSB_FinalWriteTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + u16 totalMPDUSize, u16 TxIdx) +{ + u8 QueIdx; + struct rt_ht_tx_context *pHTTXContext; + u32 fillOffset; + struct rt_txinfo *pTxInfo; + struct rt_txwi *pTxWI; + u32 USBDMApktLen, padding; + unsigned long IrqFlags; + u8 *pWirelessPacket; + + QueIdx = pTxBlk->QueIdx; + pHTTXContext = &pAd->TxContext[QueIdx]; + + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + if (pHTTXContext->bCurWriting == TRUE) { + fillOffset = pHTTXContext->CurWritePosition; + if (((pHTTXContext->ENextBulkOutPosition == + pHTTXContext->CurWritePosition) + || ((pHTTXContext->ENextBulkOutPosition - 8) == + pHTTXContext->CurWritePosition)) + && (pHTTXContext->bCopySavePad == TRUE)) + pWirelessPacket = (u8 *)(&pHTTXContext->SavedPad[0]); + else + pWirelessPacket = + (u8 *)(&pHTTXContext->TransferBuffer->field. + WirelessPacket[fillOffset]); + + /* */ + /* Update TxInfo->USBDMApktLen , */ + /* the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding */ + /* */ + pTxInfo = (struct rt_txinfo *)(pWirelessPacket); + + /* Calculate the bulk-out padding */ + USBDMApktLen = pTxBlk->Priv - TXINFO_SIZE; + padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment */ + USBDMApktLen += padding; + + pTxInfo->USBDMATxPktLen = USBDMApktLen; + + /* */ + /* Update TXWI->MPDUtotalByteCount , */ + /* the length = 802.11 header + payload_of_all_batch_frames */ + pTxWI = (struct rt_txwi *) (pWirelessPacket + TXINFO_SIZE); + pTxWI->MPDUtotalByteCount = totalMPDUSize; + + /* */ + /* Update the pHTTXContext->CurWritePosition */ + /* */ + pHTTXContext->CurWritePosition += (TXINFO_SIZE + USBDMApktLen); + if ((pHTTXContext->CurWritePosition + 3906) > MAX_TXBULK_LIMIT) { /* Add 3906 for prevent the NextBulkOut packet size is a A-RALINK/A-MSDU Frame. */ + pHTTXContext->CurWritePosition = 8; + pTxInfo->SwUseLastRound = 1; + } + pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; + + /* */ + /* Zero the last padding. */ + /* */ + pWirelessPacket = + (&pHTTXContext->TransferBuffer->field. + WirelessPacket[fillOffset + pTxBlk->Priv]); + NdisZeroMemory(pWirelessPacket, padding + 8); + + /* Finally, set bCurWriting as FALSE */ + pHTTXContext->bCurWriting = FALSE; + + } else { /* It should not happened now unless we are going to shutdown. */ + DBGPRINT(RT_DEBUG_ERROR, + ("FinalWriteTxResource():bCurWriting is FALSE when handle last frames.\n")); + } + + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + +} + +void RtmpUSBDataLastTxIdx(struct rt_rtmp_adapter *pAd, + u8 QueIdx, u16 TxIdx) +{ + /* DO nothing for USB. */ +} + +/* + When can do bulk-out: + 1. TxSwFreeIdx < TX_RING_SIZE; + It means has at least one Ring entity is ready for bulk-out, kick it out. + 2. If TxSwFreeIdx == TX_RING_SIZE + Check if the CurWriting flag is FALSE, if it's FALSE, we can do kick out. + +*/ +void RtmpUSBDataKickOut(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, u8 QueIdx) +{ + RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx)); + RTUSBKickBulkOut(pAd); + +} + +/* + Must be run in Interrupt context + This function handle RT2870 specific TxDesc and cpu index update and kick the packet out. + */ +int RtmpUSBMgmtKickOut(struct rt_rtmp_adapter *pAd, + u8 QueIdx, + void *pPacket, + u8 *pSrcBufVA, u32 SrcBufLen) +{ + struct rt_txinfo *pTxInfo; + unsigned long BulkOutSize; + u8 padLen; + u8 *pDest; + unsigned long SwIdx = pAd->MgmtRing.TxCpuIdx; + struct rt_tx_context *pMLMEContext = + (struct rt_tx_context *)pAd->MgmtRing.Cell[SwIdx].AllocVa; + unsigned long IrqFlags; + + pTxInfo = (struct rt_txinfo *)(pSrcBufVA); + + /* Build our URB for USBD */ + BulkOutSize = SrcBufLen; + BulkOutSize = (BulkOutSize + 3) & (~3); + RTMPWriteTxInfo(pAd, pTxInfo, (u16)(BulkOutSize - TXINFO_SIZE), + TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); + + BulkOutSize += 4; /* Always add 4 extra bytes at every packet. */ + + /* If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again. */ + if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0) + BulkOutSize += 4; + + padLen = BulkOutSize - SrcBufLen; + ASSERT((padLen <= RTMP_PKT_TAIL_PADDING)); + + /* Now memzero all extra padding bytes. */ + pDest = (u8 *)(pSrcBufVA + SrcBufLen); + skb_put(GET_OS_PKT_TYPE(pPacket), padLen); + NdisZeroMemory(pDest, padLen); + + RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags); + + pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket; + pMLMEContext->TransferBuffer = + (struct rt_tx_buffer *)(GET_OS_PKT_DATAPTR(pPacket)); + + /* Length in TxInfo should be 8 less than bulkout size. */ + pMLMEContext->BulkOutSize = BulkOutSize; + pMLMEContext->InUse = TRUE; + pMLMEContext->bWaitingBulkOut = TRUE; + + /*for debug */ + /*hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize)); */ + + /*pAd->RalinkCounters.KickTxCount++; */ + /*pAd->RalinkCounters.OneSecTxDoneCount++; */ + + /*if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE) */ + /* needKickOut = TRUE; */ + + /* Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX */ + pAd->MgmtRing.TxSwFreeIdx--; + INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); + + RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags); + + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); + /*if (needKickOut) */ + RTUSBKickBulkOut(pAd); + + return 0; +} + +void RtmpUSBNullFrameKickOut(struct rt_rtmp_adapter *pAd, + u8 QueIdx, + u8 * pNullFrame, u32 frameLen) +{ + if (pAd->NullContext.InUse == FALSE) { + struct rt_tx_context *pNullContext; + struct rt_txinfo *pTxInfo; + struct rt_txwi * pTxWI; + u8 *pWirelessPkt; + + pNullContext = &(pAd->NullContext); + + /* Set the in use bit */ + pNullContext->InUse = TRUE; + pWirelessPkt = + (u8 *)& pNullContext->TransferBuffer->field. + WirelessPacket[0]; + + RTMPZeroMemory(&pWirelessPkt[0], 100); + pTxInfo = (struct rt_txinfo *)& pWirelessPkt[0]; + RTMPWriteTxInfo(pAd, pTxInfo, + (u16)(sizeof(struct rt_header_802_11) + TXWI_SIZE), + TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); + pTxInfo->QSEL = FIFO_EDCA; + pTxWI = (struct rt_txwi *) & pWirelessPkt[TXINFO_SIZE]; + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, + FALSE, 0, BSSID_WCID, (sizeof(struct rt_header_802_11)), 0, + 0, (u8)pAd->CommonCfg.MlmeTransmit.field.MCS, + IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit); + + RTMPMoveMemory(&pWirelessPkt[TXWI_SIZE + TXINFO_SIZE], + &pAd->NullFrame, sizeof(struct rt_header_802_11)); + pAd->NullContext.BulkOutSize = + TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4; + + /* Fill out frame length information for global Bulk out arbitor */ + /*pNullContext->BulkOutSize = TransferBufferLength; */ + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - send NULL Frame @%d Mbps...\n", + RateIdToMbps[pAd->CommonCfg.TxRate])); + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL); + + /* Kick bulk out */ + RTUSBKickBulkOut(pAd); + } + +} + +/* +======================================================================== +Routine Description: + Get a received packet. + +Arguments: + pAd device control block + pSaveRxD receive descriptor information + *pbReschedule need reschedule flag + *pRxPending pending received packet flag + +Return Value: + the recieved packet + +Note: +======================================================================== +*/ +void *GetPacketFromRxRing(struct rt_rtmp_adapter *pAd, + OUT PRT28XX_RXD_STRUC pSaveRxD, + OUT BOOLEAN * pbReschedule, + IN u32 * pRxPending) +{ + struct rt_rx_context *pRxContext; + void *pSkb; + u8 *pData; + unsigned long ThisFrameLen; + unsigned long RxBufferLength; + struct rt_rxwi * pRxWI; + + pRxContext = &pAd->RxContext[pAd->NextRxBulkInReadIndex]; + if ((pRxContext->Readable == FALSE) || (pRxContext->InUse == TRUE)) + return NULL; + + RxBufferLength = pRxContext->BulkInOffset - pAd->ReadPosition; + if (RxBufferLength < + (RT2870_RXDMALEN_FIELD_SIZE + sizeof(struct rt_rxwi) + + sizeof(struct rt_rxinfo))) { + goto label_null; + } + + pData = &pRxContext->TransferBuffer[pAd->ReadPosition]; /* 4KB */ + /* The RXDMA field is 4 bytes, now just use the first 2 bytes. The Length including the (RXWI + MSDU + Padding) */ + ThisFrameLen = *pData + (*(pData + 1) << 8); + if (ThisFrameLen == 0) { + DBGPRINT(RT_DEBUG_TRACE, + ("BIRIdx(%d): RXDMALen is zero.[%ld], BulkInBufLen = %ld)\n", + pAd->NextRxBulkInReadIndex, ThisFrameLen, + pRxContext->BulkInOffset)); + goto label_null; + } + if ((ThisFrameLen & 0x3) != 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("BIRIdx(%d): RXDMALen not multiple of 4.[%ld], BulkInBufLen = %ld)\n", + pAd->NextRxBulkInReadIndex, ThisFrameLen, + pRxContext->BulkInOffset)); + goto label_null; + } + + if ((ThisFrameLen + 8) > RxBufferLength) /* 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(struct rt_rxinfo)) */ + { + DBGPRINT(RT_DEBUG_TRACE, + ("BIRIdx(%d):FrameLen(0x%lx) outranges. BulkInLen=0x%lx, remaining RxBufLen=0x%lx, ReadPos=0x%lx\n", + pAd->NextRxBulkInReadIndex, ThisFrameLen, + pRxContext->BulkInOffset, RxBufferLength, + pAd->ReadPosition)); + + /* error frame. finish this loop */ + goto label_null; + } + /* skip USB frame length field */ + pData += RT2870_RXDMALEN_FIELD_SIZE; + pRxWI = (struct rt_rxwi *) pData; + if (pRxWI->MPDUtotalByteCount > ThisFrameLen) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s():pRxWIMPDUtotalByteCount(%d) large than RxDMALen(%ld)\n", + __FUNCTION__, pRxWI->MPDUtotalByteCount, + ThisFrameLen)); + goto label_null; + } + /* allocate a rx packet */ + pSkb = dev_alloc_skb(ThisFrameLen); + if (pSkb == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s():Cannot Allocate sk buffer for this Bulk-In buffer!\n", + __FUNCTION__)); + goto label_null; + } + /* copy the rx packet */ + memcpy(skb_put(pSkb, ThisFrameLen), pData, ThisFrameLen); + RTPKT_TO_OSPKT(pSkb)->dev = get_netdev_from_bssid(pAd, BSS0); + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pSkb), PKTSRC_NDIS); + + /* copy RxD */ + *pSaveRxD = *(struct rt_rxinfo *) (pData + ThisFrameLen); + + /* update next packet read position. */ + pAd->ReadPosition += (ThisFrameLen + RT2870_RXDMALEN_FIELD_SIZE + RXINFO_SIZE); /* 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(struct rt_rxinfo)) */ + + return pSkb; + +label_null: + + return NULL; +} + +/* + ======================================================================== + + Routine Description: + Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound + + Arguments: + pRxD Pointer to the Rx descriptor + + Return Value: + NDIS_STATUS_SUCCESS No err + NDIS_STATUS_FAILURE Error + + Note: + + ======================================================================== +*/ +int RTMPCheckRxError(struct rt_rtmp_adapter *pAd, + struct rt_header_802_11 * pHeader, + struct rt_rxwi * pRxWI, IN PRT28XX_RXD_STRUC pRxINFO) +{ + struct rt_cipher_key *pWpaKey; + int dBm; + + if (pAd->bPromiscuous == TRUE) + return (NDIS_STATUS_SUCCESS); + if (pRxINFO == NULL) + return (NDIS_STATUS_FAILURE); + + /* Phy errors & CRC errors */ + if (pRxINFO->Crc) { + /* Check RSSI for Noise Hist statistic collection. */ + dBm = (int)(pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta; + if (dBm <= -87) + pAd->StaCfg.RPIDensity[0] += 1; + else if (dBm <= -82) + pAd->StaCfg.RPIDensity[1] += 1; + else if (dBm <= -77) + pAd->StaCfg.RPIDensity[2] += 1; + else if (dBm <= -72) + pAd->StaCfg.RPIDensity[3] += 1; + else if (dBm <= -67) + pAd->StaCfg.RPIDensity[4] += 1; + else if (dBm <= -62) + pAd->StaCfg.RPIDensity[5] += 1; + else if (dBm <= -57) + pAd->StaCfg.RPIDensity[6] += 1; + else if (dBm > -57) + pAd->StaCfg.RPIDensity[7] += 1; + + return (NDIS_STATUS_FAILURE); + } + /* Add Rx size to channel load counter, we should ignore error counts */ + pAd->StaCfg.CLBusyBytes += (pRxWI->MPDUtotalByteCount + 14); + + /* Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics */ + if (pHeader->FC.ToDs) { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Err;FC.ToDs\n")); + return NDIS_STATUS_FAILURE; + } + /* Paul 04-03 for OFDM Rx length issue */ + if (pRxWI->MPDUtotalByteCount > MAX_AGGREGATION_SIZE) { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n")); + return NDIS_STATUS_FAILURE; + } + /* Drop not U2M frames, cant's drop here because we will drop beacon in this case */ + /* I am kind of doubting the U2M bit operation */ + /* if (pRxD->U2M == 0) */ + /* return(NDIS_STATUS_FAILURE); */ + + /* drop decyption fail frame */ + if (pRxINFO->Decrypted && pRxINFO->CipherErr) { + + if (((pRxINFO->CipherErr & 1) == 1) + && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd)) + RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, + pAd->MacTab.Content[BSSID_WCID]. + Addr, BSS0, 0); + + if (((pRxINFO->CipherErr & 2) == 2) + && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd)) + RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, + pAd->MacTab.Content[BSSID_WCID]. + Addr, BSS0, 0); + /* */ + /* MIC Error */ + /* */ + if ((pRxINFO->CipherErr == 2) && pRxINFO->MyBss) { + pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex]; + RTMPReportMicError(pAd, pWpaKey); + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Rx MIC Value error\n")); + } + + if (pRxINFO->Decrypted && + (pAd->SharedKey[BSS0][pRxWI->KeyIndex].CipherAlg == + CIPHER_AES) + && (pHeader->Sequence == pAd->FragFrame.Sequence)) { + /* */ + /* Acceptable since the First FragFrame no CipherErr problem. */ + /* */ + return (NDIS_STATUS_SUCCESS); + } + + return (NDIS_STATUS_FAILURE); + } + + return (NDIS_STATUS_SUCCESS); +} + +void RtmpUsbStaAsicForceWakeupTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, + void *SystemSpecific3) +{ + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; + + if (pAd && pAd->Mlme.AutoWakeupTimerRunning) { + AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + pAd->Mlme.AutoWakeupTimerRunning = FALSE; + } +} + +void RT28xxUsbStaAsicForceWakeup(struct rt_rtmp_adapter *pAd, IN BOOLEAN bFromTx) +{ + BOOLEAN Canceled; + + if (pAd->Mlme.AutoWakeupTimerRunning) + RTMPCancelTimer(&pAd->Mlme.AutoWakeupTimer, &Canceled); + + AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); +} + +void RT28xxUsbStaAsicSleepThenAutoWakeup(struct rt_rtmp_adapter *pAd, + u16 TbttNumToNextWakeUp) +{ + + /* we have decided to SLEEP, so at least do it for a BEACON period. */ + if (TbttNumToNextWakeUp == 0) + TbttNumToNextWakeUp = 1; + + RTMPSetTimer(&pAd->Mlme.AutoWakeupTimer, AUTO_WAKEUP_TIMEOUT); + pAd->Mlme.AutoWakeupTimerRunning = TRUE; + + AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); /* send POWER-SAVE command to MCU. Timeout 40us. */ + + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); + +} + +#endif /* RTMP_MAC_USB // */ diff --git a/drivers/staging/rt2860/common/cmm_info.c b/drivers/staging/rt2860/common/cmm_info.c index 019cc4474ce80cfe536a63c7054ab096278c0703..25302e8363b95be73593732c4b7c31c66ca55ccb 100644 --- a/drivers/staging/rt2860/common/cmm_info.c +++ b/drivers/staging/rt2860/common/cmm_info.c @@ -23,3224 +23,933 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * ************************************************************************* -*/ + */ #include #include "../rt_config.h" -INT Show_SSID_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_WirelessMode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); +/* + ======================================================================== -INT Show_TxBurst_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); + Routine Description: + Remove WPA Key process -INT Show_TxPreamble_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); + Arguments: + pAd Pointer to our adapter + pBuf Pointer to the where the key stored -INT Show_TxPower_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); + Return Value: + NDIS_SUCCESS Add key successfully -INT Show_Channel_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); + IRQL = DISPATCH_LEVEL -INT Show_BGProtection_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); + Note: -INT Show_RTSThreshold_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); + ======================================================================== +*/ +void RTMPSetDesiredRates(struct rt_rtmp_adapter *pAdapter, long Rates) +{ + NDIS_802_11_RATES aryRates; + + memset(&aryRates, 0x00, sizeof(NDIS_802_11_RATES)); + switch (pAdapter->CommonCfg.PhyMode) { + case PHY_11A: /* A only */ + switch (Rates) { + case 6000000: /*6M */ + aryRates[0] = 0x0c; /* 6M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_0; + break; + case 9000000: /*9M */ + aryRates[0] = 0x12; /* 9M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_1; + break; + case 12000000: /*12M */ + aryRates[0] = 0x18; /* 12M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_2; + break; + case 18000000: /*18M */ + aryRates[0] = 0x24; /* 18M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_3; + break; + case 24000000: /*24M */ + aryRates[0] = 0x30; /* 24M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_4; + break; + case 36000000: /*36M */ + aryRates[0] = 0x48; /* 36M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_5; + break; + case 48000000: /*48M */ + aryRates[0] = 0x60; /* 48M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_6; + break; + case 54000000: /*54M */ + aryRates[0] = 0x6c; /* 54M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_7; + break; + case -1: /*Auto */ + default: + aryRates[0] = 0x6c; /* 54Mbps */ + aryRates[1] = 0x60; /* 48Mbps */ + aryRates[2] = 0x48; /* 36Mbps */ + aryRates[3] = 0x30; /* 24Mbps */ + aryRates[4] = 0x24; /* 18M */ + aryRates[5] = 0x18; /* 12M */ + aryRates[6] = 0x12; /* 9M */ + aryRates[7] = 0x0c; /* 6M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_AUTO; + break; + } + break; + case PHY_11BG_MIXED: /* B/G Mixed */ + case PHY_11B: /* B only */ + case PHY_11ABG_MIXED: /* A/B/G Mixed */ + default: + switch (Rates) { + case 1000000: /*1M */ + aryRates[0] = 0x02; + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_0; + break; + case 2000000: /*2M */ + aryRates[0] = 0x04; + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_1; + break; + case 5000000: /*5.5M */ + aryRates[0] = 0x0b; /* 5.5M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_2; + break; + case 11000000: /*11M */ + aryRates[0] = 0x16; /* 11M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_3; + break; + case 6000000: /*6M */ + aryRates[0] = 0x0c; /* 6M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_0; + break; + case 9000000: /*9M */ + aryRates[0] = 0x12; /* 9M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_1; + break; + case 12000000: /*12M */ + aryRates[0] = 0x18; /* 12M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_2; + break; + case 18000000: /*18M */ + aryRates[0] = 0x24; /* 18M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_3; + break; + case 24000000: /*24M */ + aryRates[0] = 0x30; /* 24M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_4; + break; + case 36000000: /*36M */ + aryRates[0] = 0x48; /* 36M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_5; + break; + case 48000000: /*48M */ + aryRates[0] = 0x60; /* 48M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_6; + break; + case 54000000: /*54M */ + aryRates[0] = 0x6c; /* 54M */ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_7; + break; + case -1: /*Auto */ + default: + if (pAdapter->CommonCfg.PhyMode == PHY_11B) { /*B Only */ + aryRates[0] = 0x16; /* 11Mbps */ + aryRates[1] = 0x0b; /* 5.5Mbps */ + aryRates[2] = 0x04; /* 2Mbps */ + aryRates[3] = 0x02; /* 1Mbps */ + } else { /*(B/G) Mixed or (A/B/G) Mixed */ + aryRates[0] = 0x6c; /* 54Mbps */ + aryRates[1] = 0x60; /* 48Mbps */ + aryRates[2] = 0x48; /* 36Mbps */ + aryRates[3] = 0x30; /* 24Mbps */ + aryRates[4] = 0x16; /* 11Mbps */ + aryRates[5] = 0x0b; /* 5.5Mbps */ + aryRates[6] = 0x04; /* 2Mbps */ + aryRates[7] = 0x02; /* 1Mbps */ + } + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_AUTO; + break; + } + break; + } + + NdisZeroMemory(pAdapter->CommonCfg.DesireRate, + MAX_LEN_OF_SUPPORTED_RATES); + NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates, + sizeof(NDIS_802_11_RATES)); + DBGPRINT(RT_DEBUG_TRACE, + (" RTMPSetDesiredRates (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n", + pAdapter->CommonCfg.DesireRate[0], + pAdapter->CommonCfg.DesireRate[1], + pAdapter->CommonCfg.DesireRate[2], + pAdapter->CommonCfg.DesireRate[3], + pAdapter->CommonCfg.DesireRate[4], + pAdapter->CommonCfg.DesireRate[5], + pAdapter->CommonCfg.DesireRate[6], + pAdapter->CommonCfg.DesireRate[7])); + /* Changing DesiredRate may affect the MAX TX rate we used to TX frames out */ + MlmeUpdateTxRates(pAdapter, FALSE, 0); +} -INT Show_FragThreshold_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); +/* + ======================================================================== -INT Show_HtBw_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); + Routine Description: + Remove All WPA Keys -INT Show_HtMcs_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_HtGi_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_HtOpMode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_HtExtcha_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_HtMpduDensity_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_HtBaWinSize_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_HtRdg_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_HtAmsdu_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_HtAutoBa_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_CountryRegion_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_CountryRegionABand_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_CountryCode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -#ifdef AGGREGATION_SUPPORT -INT Show_PktAggregate_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); -#endif // AGGREGATION_SUPPORT // - -#ifdef WMM_SUPPORT -INT Show_WmmCapable_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); -#endif // WMM_SUPPORT // - -INT Show_IEEE80211H_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_NetworkType_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_AuthMode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_EncrypType_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_DefaultKeyID_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_Key1_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_Key2_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_Key3_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_Key4_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -INT Show_WPAPSK_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf); - -static struct { - CHAR *name; - INT (*show_proc)(PRTMP_ADAPTER pAdapter, PUCHAR arg); -} *PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC, RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC[] = { - {"SSID", Show_SSID_Proc}, - {"WirelessMode", Show_WirelessMode_Proc}, - {"TxBurst", Show_TxBurst_Proc}, - {"TxPreamble", Show_TxPreamble_Proc}, - {"TxPower", Show_TxPower_Proc}, - {"Channel", Show_Channel_Proc}, - {"BGProtection", Show_BGProtection_Proc}, - {"RTSThreshold", Show_RTSThreshold_Proc}, - {"FragThreshold", Show_FragThreshold_Proc}, - {"HtBw", Show_HtBw_Proc}, - {"HtMcs", Show_HtMcs_Proc}, - {"HtGi", Show_HtGi_Proc}, - {"HtOpMode", Show_HtOpMode_Proc}, - {"HtExtcha", Show_HtExtcha_Proc}, - {"HtMpduDensity", Show_HtMpduDensity_Proc}, - {"HtBaWinSize", Show_HtBaWinSize_Proc}, - {"HtRdg", Show_HtRdg_Proc}, - {"HtAmsdu", Show_HtAmsdu_Proc}, - {"HtAutoBa", Show_HtAutoBa_Proc}, - {"CountryRegion", Show_CountryRegion_Proc}, - {"CountryRegionABand", Show_CountryRegionABand_Proc}, - {"CountryCode", Show_CountryCode_Proc}, -#ifdef AGGREGATION_SUPPORT - {"PktAggregate", Show_PktAggregate_Proc}, -#endif - -#ifdef WMM_SUPPORT - {"WmmCapable", Show_WmmCapable_Proc}, -#endif - {"IEEE80211H", Show_IEEE80211H_Proc}, - {"NetworkType", Show_NetworkType_Proc}, - {"AuthMode", Show_AuthMode_Proc}, - {"EncrypType", Show_EncrypType_Proc}, - {"DefaultKeyID", Show_DefaultKeyID_Proc}, - {"Key1", Show_Key1_Proc}, - {"Key2", Show_Key2_Proc}, - {"Key3", Show_Key3_Proc}, - {"Key4", Show_Key4_Proc}, - {"WPAPSK", Show_WPAPSK_Proc}, - {NULL, NULL} -}; + Arguments: + pAd Pointer to our adapter -/* - ========================================================================== - Description: - Get Driver version. + Return Value: + None - Return: - ========================================================================== -*/ -INT Set_DriverVersion_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - DBGPRINT(RT_DEBUG_TRACE, ("Driver version-%s\n", STA_DRIVER_VERSION)); + IRQL = DISPATCH_LEVEL - return TRUE; -} + Note: -/* - ========================================================================== - Description: - Set Country Region. - This command will not work, if the field of CountryRegion in eeprom is programmed. - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== + ======================================================================== */ -INT Set_CountryRegion_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) +void RTMPWPARemoveAllKeys(struct rt_rtmp_adapter *pAd) { - ULONG region; - region = simple_strtol(arg, 0, 10); + u8 i; - // Country can be set only when EEPROM not programmed - if (pAd->CommonCfg.CountryRegion & 0x80) - { - DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegion_Proc::parameter of CountryRegion in eeprom is programmed \n")); - return FALSE; - } + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPWPARemoveAllKeys(AuthMode=%d, WepStatus=%d)\n", + pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus)); + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); + /* For WEP/CKIP, there is no need to remove it, since WinXP won't set it again after */ + /* Link up. And it will be replaced if user changed it. */ + if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + return; - if((region >= 0) && (region <= REGION_MAXIMUM_BG_BAND)) - { - pAd->CommonCfg.CountryRegion = (UCHAR) region; - } - else if (region == REGION_31_BG_BAND) - { - pAd->CommonCfg.CountryRegion = (UCHAR) region; - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegion_Proc::parameters out of range\n")); - return FALSE; - } + /* For WPA-None, there is no need to remove it, since WinXP won't set it again after */ + /* Link up. And it will be replaced if user changed it. */ + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + return; - // if set country region, driver needs to be reset - BuildChannelList(pAd); + /* set BSSID wcid entry of the Pair-wise Key table as no-security mode */ + AsicRemovePairwiseKeyEntry(pAd, BSS0, BSSID_WCID); - DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegion_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegion)); + /* set all shared key mode as no-security. */ + for (i = 0; i < SHARE_KEY_NUM; i++) { + DBGPRINT(RT_DEBUG_TRACE, + ("remove %s key #%d\n", + CipherName[pAd->SharedKey[BSS0][i].CipherAlg], i)); + NdisZeroMemory(&pAd->SharedKey[BSS0][i], sizeof(struct rt_cipher_key)); - return TRUE; + AsicRemoveSharedKeyEntry(pAd, BSS0, i); + } + RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); } /* - ========================================================================== - Description: - Set Country Region for A band. - This command will not work, if the field of CountryRegion in eeprom is programmed. - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_CountryRegionABand_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG region; - - region = simple_strtol(arg, 0, 10); + ======================================================================== - // Country can be set only when EEPROM not programmed - if (pAd->CommonCfg.CountryRegionForABand & 0x80) - { - DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegionABand_Proc::parameter of CountryRegion in eeprom is programmed \n")); - return FALSE; - } + Routine Description: + As STA's BSSID is a WC too, it uses shared key table. + This function write correct unicast TX key to ASIC WCID. + And we still make a copy in our MacTab.Content[BSSID_WCID].PairwiseKey. + Caller guarantee TKIP/AES always has keyidx = 0. (pairwise key) + Caller guarantee WEP calls this function when set Txkey, default key index=0~3. - if((region >= 0) && (region <= REGION_MAXIMUM_A_BAND)) - { - pAd->CommonCfg.CountryRegionForABand = (UCHAR) region; - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegionABand_Proc::parameters out of range\n")); - return FALSE; - } + Arguments: + pAd Pointer to our adapter + pKey Pointer to the where the key stored - // if set country region, driver needs to be reset - BuildChannelList(pAd); + Return Value: + NDIS_SUCCESS Add key successfully - DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegionABand_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegionForABand)); + IRQL = DISPATCH_LEVEL - return TRUE; -} + Note: -/* - ========================================================================== - Description: - Set Wireless Mode - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== + ======================================================================== */ -INT Set_WirelessMode_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG WirelessMode; - INT success = TRUE; +/* + ======================================================================== + Routine Description: + Change NIC PHY mode. Re-association may be necessary. possible settings + include - PHY_11B, PHY_11BG_MIXED, PHY_11A, and PHY_11ABG_MIXED + + Arguments: + pAd - Pointer to our adapter + phymode - - WirelessMode = simple_strtol(arg, 0, 10); + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL - { - INT MaxPhyMode = PHY_11G; + ======================================================================== +*/ +void RTMPSetPhyMode(struct rt_rtmp_adapter *pAd, unsigned long phymode) +{ + int i; + /* the selected phymode must be supported by the RF IC encoded in E2PROM */ - MaxPhyMode = PHY_11N_5G; + /* if no change, do nothing */ + /* bug fix + if (pAd->CommonCfg.PhyMode == phymode) + return; + */ + pAd->CommonCfg.PhyMode = (u8)phymode; - if (WirelessMode <= MaxPhyMode) - { - RTMPSetPhyMode(pAd, WirelessMode); + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPSetPhyMode : PhyMode=%d, channel=%d \n", + pAd->CommonCfg.PhyMode, pAd->CommonCfg.Channel)); - if (WirelessMode >= PHY_11ABGN_MIXED) - { - pAd->CommonCfg.BACapability.field.AutoBA = TRUE; - pAd->CommonCfg.REGBACapability.field.AutoBA = TRUE; - } - else - { - pAd->CommonCfg.BACapability.field.AutoBA = FALSE; - pAd->CommonCfg.REGBACapability.field.AutoBA = FALSE; - } + BuildChannelList(pAd); - // Set AdhocMode rates - if (pAd->StaCfg.BssType == BSS_ADHOC) - { - MlmeUpdateTxRates(pAd, FALSE, 0); - MakeIbssBeacon(pAd); // re-build BEACON frame - AsicEnableIbssSync(pAd); // copy to on-chip memory - } - } - else - { - success = FALSE; - } + /* sanity check user setting */ + for (i = 0; i < pAd->ChannelListNum; i++) { + if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel) + break; } - // it is needed to set SSID to take effect - if (success == TRUE) - { - SetCommonHT(pAd); - DBGPRINT(RT_DEBUG_TRACE, ("Set_WirelessMode_Proc::(=%ld)\n", WirelessMode)); + if (i == pAd->ChannelListNum) { + pAd->CommonCfg.Channel = FirstChannel(pAd); + DBGPRINT(RT_DEBUG_ERROR, + ("RTMPSetPhyMode: channel is out of range, use first channel=%d \n", + pAd->CommonCfg.Channel)); } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("Set_WirelessMode_Proc::parameters out of range\n")); + + NdisZeroMemory(pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisZeroMemory(pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); + switch (phymode) { + case PHY_11B: + pAd->CommonCfg.SupRate[0] = 0x82; /* 1 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRate[1] = 0x84; /* 2 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRate[2] = 0x8B; /* 5.5 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRate[3] = 0x96; /* 11 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRateLen = 4; + pAd->CommonCfg.ExtRateLen = 0; + pAd->CommonCfg.DesireRate[0] = 2; /* 1 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[1] = 4; /* 2 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[2] = 11; /* 5.5 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[3] = 22; /* 11 mbps, in units of 0.5 Mbps */ + /*pAd->CommonCfg.HTPhyMode.field.MODE = MODE_CCK; // This MODE is only FYI. not use */ + break; + + case PHY_11G: + case PHY_11BG_MIXED: + case PHY_11ABG_MIXED: + case PHY_11N_2_4G: + case PHY_11ABGN_MIXED: + case PHY_11BGN_MIXED: + case PHY_11GN_MIXED: + pAd->CommonCfg.SupRate[0] = 0x82; /* 1 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRate[1] = 0x84; /* 2 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRate[2] = 0x8B; /* 5.5 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRate[3] = 0x96; /* 11 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRate[4] = 0x12; /* 9 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.SupRate[5] = 0x24; /* 18 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.SupRate[6] = 0x48; /* 36 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.SupRateLen = 8; + pAd->CommonCfg.ExtRate[0] = 0x0C; /* 6 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.ExtRate[1] = 0x18; /* 12 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.ExtRate[2] = 0x30; /* 24 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.ExtRate[3] = 0x60; /* 48 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.ExtRateLen = 4; + pAd->CommonCfg.DesireRate[0] = 2; /* 1 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[1] = 4; /* 2 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[2] = 11; /* 5.5 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[3] = 22; /* 11 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[4] = 12; /* 6 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[5] = 18; /* 9 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[6] = 24; /* 12 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[7] = 36; /* 18 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[8] = 48; /* 24 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[9] = 72; /* 36 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[10] = 96; /* 48 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[11] = 108; /* 54 mbps, in units of 0.5 Mbps */ + break; + + case PHY_11A: + case PHY_11AN_MIXED: + case PHY_11AGN_MIXED: + case PHY_11N_5G: + pAd->CommonCfg.SupRate[0] = 0x8C; /* 6 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.SupRate[2] = 0x98; /* 12 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.SupRate[4] = 0xb0; /* 24 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRate[5] = 0x48; /* 36 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.SupRate[6] = 0x60; /* 48 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.SupRateLen = 8; + pAd->CommonCfg.ExtRateLen = 0; + pAd->CommonCfg.DesireRate[0] = 12; /* 6 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[1] = 18; /* 9 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[2] = 24; /* 12 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[3] = 36; /* 18 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[4] = 48; /* 24 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[5] = 72; /* 36 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[6] = 96; /* 48 mbps, in units of 0.5 Mbps */ + pAd->CommonCfg.DesireRate[7] = 108; /* 54 mbps, in units of 0.5 Mbps */ + /*pAd->CommonCfg.HTPhyMode.field.MODE = MODE_OFDM; // This MODE is only FYI. not use */ + break; + + default: + break; } - return success; + pAd->CommonCfg.BandState = UNKNOWN_BAND; } /* - ========================================================================== - Description: - Set Channel - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_Channel_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - INT success = TRUE; - UCHAR Channel; + ======================================================================== + Routine Description: + Caller ensures we has 802.11n support. + Calls at setting HT from AP/STASetinformation - Channel = (UCHAR) simple_strtol(arg, 0, 10); + Arguments: + pAd - Pointer to our adapter + phymode - - // check if this channel is valid - if (ChannelSanity(pAd, Channel) == TRUE) - { - { - pAd->CommonCfg.Channel = Channel; - - if (MONITOR_ON(pAd)) - { - N_ChannelCheck(pAd); - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && - pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) - { - N_SetCenCh(pAd); - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - DBGPRINT(RT_DEBUG_TRACE, ("BW_40, control_channel(%d), CentralChannel(%d) \n", - pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); - } - else - { - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAd->CommonCfg.Channel)); - } - } - } - success = TRUE; - } - else - { - success = FALSE; + ======================================================================== +*/ +void RTMPSetHT(struct rt_rtmp_adapter *pAd, struct rt_oid_set_ht_phymode *pHTPhyMode) +{ + /*unsigned long *pmcs; */ + u32 Value = 0; + u8 BBPValue = 0; + u8 BBP3Value = 0; + u8 RxStream = pAd->CommonCfg.RxStream; + + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPSetHT : HT_mode(%d), ExtOffset(%d), MCS(%d), BW(%d), STBC(%d), SHORTGI(%d)\n", + pHTPhyMode->HtMode, pHTPhyMode->ExtOffset, pHTPhyMode->MCS, + pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->SHORTGI)); + + /* Don't zero supportedHyPhy structure. */ + RTMPZeroMemory(&pAd->CommonCfg.HtCapability, + sizeof(pAd->CommonCfg.HtCapability)); + RTMPZeroMemory(&pAd->CommonCfg.AddHTInfo, + sizeof(pAd->CommonCfg.AddHTInfo)); + RTMPZeroMemory(&pAd->CommonCfg.NewExtChanOffset, + sizeof(pAd->CommonCfg.NewExtChanOffset)); + RTMPZeroMemory(&pAd->CommonCfg.DesiredHtPhy, + sizeof(pAd->CommonCfg.DesiredHtPhy)); + + if (pAd->CommonCfg.bRdg) { + pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 1; + pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 1; + } else { + pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 0; + pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 0; } + pAd->CommonCfg.HtCapability.HtCapParm.MaxRAmpduFactor = 3; + pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor = 3; - if (success == TRUE) - DBGPRINT(RT_DEBUG_TRACE, ("Set_Channel_Proc::(Channel=%d)\n", pAd->CommonCfg.Channel)); - - return success; -} + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPSetHT : RxBAWinLimit = %d\n", + pAd->CommonCfg.BACapability.field.RxBAWinLimit)); + + /* Mimo power save, A-MSDU size, */ + pAd->CommonCfg.DesiredHtPhy.AmsduEnable = + (u16)pAd->CommonCfg.BACapability.field.AmsduEnable; + pAd->CommonCfg.DesiredHtPhy.AmsduSize = + (u8)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.DesiredHtPhy.MimoPs = + (u8)pAd->CommonCfg.BACapability.field.MMPSmode; + pAd->CommonCfg.DesiredHtPhy.MpduDensity = + (u8)pAd->CommonCfg.BACapability.field.MpduDensity; + + pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = + (u16)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = + (u16)pAd->CommonCfg.BACapability.field.MMPSmode; + pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = + (u8)pAd->CommonCfg.BACapability.field.MpduDensity; + + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPSetHT : AMsduSize = %d, MimoPs = %d, MpduDensity = %d, MaxRAmpduFactor = %d\n", + pAd->CommonCfg.DesiredHtPhy.AmsduSize, + pAd->CommonCfg.DesiredHtPhy.MimoPs, + pAd->CommonCfg.DesiredHtPhy.MpduDensity, + pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor)); + + if (pHTPhyMode->HtMode == HTMODE_GF) { + pAd->CommonCfg.HtCapability.HtCapInfo.GF = 1; + pAd->CommonCfg.DesiredHtPhy.GF = 1; + } else + pAd->CommonCfg.DesiredHtPhy.GF = 0; -/* - ========================================================================== - Description: - Set Short Slot Time Enable or Disable - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_ShortSlot_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG ShortSlot; + /* Decide Rx MCSSet */ + switch (RxStream) { + case 1: + pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[1] = 0x00; + break; - ShortSlot = simple_strtol(arg, 0, 10); + case 2: + pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff; + break; - if (ShortSlot == 1) - pAd->CommonCfg.bUseShortSlotTime = TRUE; - else if (ShortSlot == 0) - pAd->CommonCfg.bUseShortSlotTime = FALSE; - else - return FALSE; //Invalid argument + case 3: /* 3*3 */ + pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[2] = 0xff; + break; + } - DBGPRINT(RT_DEBUG_TRACE, ("Set_ShortSlot_Proc::(ShortSlot=%d)\n", pAd->CommonCfg.bUseShortSlotTime)); + if (pAd->CommonCfg.bForty_Mhz_Intolerant + && (pAd->CommonCfg.Channel <= 14) && (pHTPhyMode->BW == BW_40)) { + pHTPhyMode->BW = BW_20; + pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant = 1; + } - return TRUE; -} + if (pHTPhyMode->BW == BW_40) { + pAd->CommonCfg.HtCapability.MCSSet[4] = 0x1; /* MCS 32 */ + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 1; + if (pAd->CommonCfg.Channel <= 14) + pAd->CommonCfg.HtCapability.HtCapInfo.CCKmodein40 = 1; -/* - ========================================================================== - Description: - Set Tx power - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_TxPower_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG TxPower; - INT success = FALSE; + pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 1; + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 1; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = + (pHTPhyMode->ExtOffset == + EXTCHA_BELOW) ? (EXTCHA_BELOW) : EXTCHA_ABOVE; + /* Set Regsiter for extension channel position. */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBP3Value); + if ((pHTPhyMode->ExtOffset == EXTCHA_BELOW)) { + Value |= 0x1; + BBP3Value |= (0x20); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + } else if ((pHTPhyMode->ExtOffset == EXTCHA_ABOVE)) { + Value &= 0xfe; + BBP3Value &= (~0x20); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + } + /* Turn on BBP 40MHz mode now only as AP . */ + /* Sta can turn on BBP 40MHz after connection with 40MHz AP. Sta only broadcast 40MHz capability before connection. */ + if ((pAd->OpMode == OPMODE_AP) || INFRA_ON(pAd) || ADHOC_ON(pAd) + ) { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + BBPValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - TxPower = (ULONG) simple_strtol(arg, 0, 10); - if (TxPower <= 100) - { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBP3Value); + pAd->CommonCfg.BBPCurrentBW = BW_40; + } + } else { + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 0; + pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = EXTCHA_NONE; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + /* Turn on BBP 20MHz mode by request here. */ { - pAd->CommonCfg.TxPowerDefault = TxPower; - pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + pAd->CommonCfg.BBPCurrentBW = BW_20; } - success = TRUE; } - else - success = FALSE; - DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPower_Proc::(TxPowerPercentage=%ld)\n", pAd->CommonCfg.TxPowerPercentage)); - - return success; -} - -/* - ========================================================================== - Description: - Set 11B/11G Protection - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_BGProtection_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - switch (simple_strtol(arg, 0, 10)) - { - case 0: //AUTO - pAd->CommonCfg.UseBGProtection = 0; - break; - case 1: //Always On - pAd->CommonCfg.UseBGProtection = 1; - break; - case 2: //Always OFF - pAd->CommonCfg.UseBGProtection = 2; - break; - default: //Invalid argument - return FALSE; + if (pHTPhyMode->STBC == STBC_USE) { + pAd->CommonCfg.HtCapability.HtCapInfo.TxSTBC = 1; + pAd->CommonCfg.DesiredHtPhy.TxSTBC = 1; + pAd->CommonCfg.HtCapability.HtCapInfo.RxSTBC = 1; + pAd->CommonCfg.DesiredHtPhy.RxSTBC = 1; + } else { + pAd->CommonCfg.DesiredHtPhy.TxSTBC = 0; + pAd->CommonCfg.DesiredHtPhy.RxSTBC = 0; } + if (pHTPhyMode->SHORTGI == GI_400) { + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 1; + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 1; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 1; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 1; + } else { + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 0; + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 0; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 0; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 0; + } - DBGPRINT(RT_DEBUG_TRACE, ("Set_BGProtection_Proc::(BGProtection=%ld)\n", pAd->CommonCfg.UseBGProtection)); + /* We support link adaptation for unsolicit MCS feedback, set to 2. */ + pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_NONE; /*MCSFBK_UNSOLICIT; */ + pAd->CommonCfg.AddHTInfo.ControlChan = pAd->CommonCfg.Channel; + /* 1, the extension channel above the control channel. */ - return TRUE; -} + /* EDCA parameters used for AP's own transmission */ + if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) { + pAd->CommonCfg.APEdcaParm.bValid = TRUE; + pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; + pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; + pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; + pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; -/* - ========================================================================== - Description: - Set TxPreamble - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_TxPreamble_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - RT_802_11_PREAMBLE Preamble; + pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; + pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; - Preamble = simple_strtol(arg, 0, 10); + pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6; + pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10; + pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; + pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; + pAd->CommonCfg.APEdcaParm.Txop[0] = 0; + pAd->CommonCfg.APEdcaParm.Txop[1] = 0; + pAd->CommonCfg.APEdcaParm.Txop[2] = 94; + pAd->CommonCfg.APEdcaParm.Txop[3] = 47; + } + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); - switch (Preamble) { - case Rt802_11PreambleShort: - pAd->CommonCfg.TxPreamble = Preamble; - - MlmeSetTxPreamble(pAd, Rt802_11PreambleShort); - break; - case Rt802_11PreambleLong: - case Rt802_11PreambleAuto: - // if user wants AUTO, initialize to LONG here, then change according to AP's - // capability upon association. - pAd->CommonCfg.TxPreamble = Preamble; - - MlmeSetTxPreamble(pAd, Rt802_11PreambleLong); - break; - default: //Invalid argument - return FALSE; + RTMPSetIndividualHT(pAd, 0); } - DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPreamble_Proc::(TxPreamble=%ld)\n", pAd->CommonCfg.TxPreamble)); - - return TRUE; } /* - ========================================================================== - Description: - Set RTS Threshold - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_RTSThreshold_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - NDIS_802_11_RTS_THRESHOLD RtsThresh; - - RtsThresh = simple_strtol(arg, 0, 10); - - if((RtsThresh > 0) && (RtsThresh <= MAX_RTS_THRESHOLD)) - pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh; - else if (RtsThresh == 0) - pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD; - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_RTSThreshold_Proc::(RTSThreshold=%d)\n", pAd->CommonCfg.RtsThreshold)); + ======================================================================== + Routine Description: + Caller ensures we has 802.11n support. + Calls at setting HT from AP/STASetinformation - return TRUE; -} + Arguments: + pAd - Pointer to our adapter + phymode - -/* - ========================================================================== - Description: - Set Fragment Threshold - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== + ======================================================================== */ -INT Set_FragThreshold_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) +void RTMPSetIndividualHT(struct rt_rtmp_adapter *pAd, u8 apidx) { - NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh; + struct rt_ht_phy_info *pDesired_ht_phy = NULL; + u8 TxStream = pAd->CommonCfg.TxStream; + u8 DesiredMcs = MCS_AUTO; - FragThresh = simple_strtol(arg, 0, 10); + do { + { + pDesired_ht_phy = &pAd->StaCfg.DesiredHtPhyInfo; + DesiredMcs = + pAd->StaCfg.DesiredTransmitSetting.field.MCS; + /*pAd->StaCfg.bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; */ + break; + } + } while (FALSE); - if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD) - { - //Illegal FragThresh so we set it to default - pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; - } - else if (FragThresh % 2 == 1) - { - // The length of each fragment shall always be an even number of octets, except for the last fragment - // of an MSDU or MMPDU, which may be either an even or an odd number of octets. - pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1); - } - else - { - pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh; + if (pDesired_ht_phy == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx)); + return; } + RTMPZeroMemory(pDesired_ht_phy, sizeof(struct rt_ht_phy_info)); - { - if (pAd->CommonCfg.FragmentThreshold == MAX_FRAG_THRESHOLD) - pAd->CommonCfg.bUseZeroToDisableFragment = TRUE; - else - pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPSetIndividualHT : Desired MCS = %d\n", DesiredMcs)); + /* Check the validity of MCS */ + if ((TxStream == 1) + && ((DesiredMcs >= MCS_8) && (DesiredMcs <= MCS_15))) { + DBGPRINT(RT_DEBUG_WARN, + ("RTMPSetIndividualHT: MCS(%d) is invalid in 1S, reset it as MCS_7\n", + DesiredMcs)); + DesiredMcs = MCS_7; } - DBGPRINT(RT_DEBUG_TRACE, ("Set_FragThreshold_Proc::(FragThreshold=%d)\n", pAd->CommonCfg.FragmentThreshold)); + if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_20) + && (DesiredMcs == MCS_32)) { + DBGPRINT(RT_DEBUG_WARN, + ("RTMPSetIndividualHT: MCS_32 is only supported in 40-MHz, reset it as MCS_0\n")); + DesiredMcs = MCS_0; + } - return TRUE; -} + pDesired_ht_phy->bHtEnable = TRUE; -/* - ========================================================================== - Description: - Set TxBurst - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_TxBurst_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG TxBurst; + /* Decide desired Tx MCS */ + switch (TxStream) { + case 1: + if (DesiredMcs == MCS_AUTO) { + pDesired_ht_phy->MCSSet[0] = 0xff; + pDesired_ht_phy->MCSSet[1] = 0x00; + } else if (DesiredMcs <= MCS_7) { + pDesired_ht_phy->MCSSet[0] = 1 << DesiredMcs; + pDesired_ht_phy->MCSSet[1] = 0x00; + } + break; + + case 2: + if (DesiredMcs == MCS_AUTO) { + pDesired_ht_phy->MCSSet[0] = 0xff; + pDesired_ht_phy->MCSSet[1] = 0xff; + } else if (DesiredMcs <= MCS_15) { + unsigned long mode; + + mode = DesiredMcs / 8; + if (mode < 2) + pDesired_ht_phy->MCSSet[mode] = + (1 << (DesiredMcs - mode * 8)); + } + break; + + case 3: /* 3*3 */ + if (DesiredMcs == MCS_AUTO) { + /* MCS0 ~ MCS23, 3 bytes */ + pDesired_ht_phy->MCSSet[0] = 0xff; + pDesired_ht_phy->MCSSet[1] = 0xff; + pDesired_ht_phy->MCSSet[2] = 0xff; + } else if (DesiredMcs <= MCS_23) { + unsigned long mode; + + mode = DesiredMcs / 8; + if (mode < 3) + pDesired_ht_phy->MCSSet[mode] = + (1 << (DesiredMcs - mode * 8)); + } + break; + } - TxBurst = simple_strtol(arg, 0, 10); - if (TxBurst == 1) - pAd->CommonCfg.bEnableTxBurst = TRUE; - else if (TxBurst == 0) - pAd->CommonCfg.bEnableTxBurst = FALSE; + if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_40) { + if (DesiredMcs == MCS_AUTO || DesiredMcs == MCS_32) + pDesired_ht_phy->MCSSet[4] = 0x1; + } + /* update HT Rate setting */ + if (pAd->OpMode == OPMODE_STA) + MlmeUpdateHtTxRates(pAd, BSS0); else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_TxBurst_Proc::(TxBurst=%d)\n", pAd->CommonCfg.bEnableTxBurst)); - - return TRUE; + MlmeUpdateHtTxRates(pAd, apidx); } -#ifdef AGGREGATION_SUPPORT /* - ========================================================================== - Description: - Set TxBurst - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_PktAggregate_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG aggre; - - aggre = simple_strtol(arg, 0, 10); - - if (aggre == 1) - pAd->CommonCfg.bAggregationCapable = TRUE; - else if (aggre == 0) - pAd->CommonCfg.bAggregationCapable = FALSE; - else - return FALSE; //Invalid argument - + ======================================================================== + Routine Description: + Update HT IE from our capability. - DBGPRINT(RT_DEBUG_TRACE, ("Set_PktAggregate_Proc::(AGGRE=%d)\n", pAd->CommonCfg.bAggregationCapable)); + Arguments: + Send all HT IE in beacon/probe rsp/assoc rsp/action frame. - return TRUE; + ======================================================================== +*/ +void RTMPUpdateHTIE(struct rt_ht_capability *pRtHt, + u8 * pMcsSet, + struct rt_ht_capability_ie * pHtCapability, + struct rt_add_ht_info_ie * pAddHtInfo) +{ + RTMPZeroMemory(pHtCapability, sizeof(struct rt_ht_capability_ie)); + RTMPZeroMemory(pAddHtInfo, sizeof(struct rt_add_ht_info_ie)); + + pHtCapability->HtCapInfo.ChannelWidth = pRtHt->ChannelWidth; + pHtCapability->HtCapInfo.MimoPs = pRtHt->MimoPs; + pHtCapability->HtCapInfo.GF = pRtHt->GF; + pHtCapability->HtCapInfo.ShortGIfor20 = pRtHt->ShortGIfor20; + pHtCapability->HtCapInfo.ShortGIfor40 = pRtHt->ShortGIfor40; + pHtCapability->HtCapInfo.TxSTBC = pRtHt->TxSTBC; + pHtCapability->HtCapInfo.RxSTBC = pRtHt->RxSTBC; + pHtCapability->HtCapInfo.AMsduSize = pRtHt->AmsduSize; + pHtCapability->HtCapParm.MaxRAmpduFactor = pRtHt->MaxRAmpduFactor; + pHtCapability->HtCapParm.MpduDensity = pRtHt->MpduDensity; + + pAddHtInfo->AddHtInfo.ExtChanOffset = pRtHt->ExtChanOffset; + pAddHtInfo->AddHtInfo.RecomWidth = pRtHt->RecomWidth; + pAddHtInfo->AddHtInfo2.OperaionMode = pRtHt->OperaionMode; + pAddHtInfo->AddHtInfo2.NonGfPresent = pRtHt->NonGfPresent; + RTMPMoveMemory(pAddHtInfo->MCSSet, /*pRtHt->MCSSet */ pMcsSet, 4); /* rt2860 only support MCS max=32, no need to copy all 16 uchar. */ + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateHTIE <== \n")); } -#endif /* - ========================================================================== - Description: - Set IEEE80211H. - This parameter is 1 when needs radar detection, otherwise 0 + ======================================================================== + Description: + Add Client security information into ASIC WCID table and IVEIV table. Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== + ======================================================================== */ -INT Set_IEEE80211H_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) +void RTMPAddWcidAttributeEntry(struct rt_rtmp_adapter *pAd, + u8 BssIdx, + u8 KeyIdx, + u8 CipherAlg, struct rt_mac_table_entry *pEntry) { - ULONG ieee80211h; - - ieee80211h = simple_strtol(arg, 0, 10); + u32 WCIDAttri = 0; + u16 offset; + u8 IVEIV = 0; + u16 Wcid = 0; - if (ieee80211h == 1) - pAd->CommonCfg.bIEEE80211H = TRUE; - else if (ieee80211h == 0) - pAd->CommonCfg.bIEEE80211H = FALSE; - else - return FALSE; //Invalid argument + { + { + if (BssIdx > BSS0) { + DBGPRINT(RT_DEBUG_ERROR, + ("RTMPAddWcidAttributeEntry: The BSS-index(%d) is out of range for Infra link. \n", + BssIdx)); + return; + } + /* 1. In ADHOC mode, the AID is wcid number. And NO mesh link exists. */ + /* 2. In Infra mode, the AID:1 MUST be wcid of infra STA. */ + /* the AID:2~ assign to mesh link entry. */ + if (pEntry) + Wcid = pEntry->Aid; + else + Wcid = MCAST_WCID; + } + } - DBGPRINT(RT_DEBUG_TRACE, ("Set_IEEE80211H_Proc::(IEEE80211H=%d)\n", pAd->CommonCfg.bIEEE80211H)); + /* Update WCID attribute table */ + offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE); - return TRUE; -} + { + if (pEntry && pEntry->ValidAsMesh) + WCIDAttri = (CipherAlg << 1) | PAIRWISEKEYTABLE; + else + WCIDAttri = (CipherAlg << 1) | SHAREDKEYTABLE; + } + RTMP_IO_WRITE32(pAd, offset, WCIDAttri); -#ifdef DBG -/* - ========================================================================== - Description: - For Debug information - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_Debug_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - DBGPRINT(RT_DEBUG_TRACE, ("==> Set_Debug_Proc *******************\n")); + /* Update IV/EIV table */ + offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_SIZE); - if(simple_strtol(arg, 0, 10) <= RT_DEBUG_LOUD) - RTDebugLevel = simple_strtol(arg, 0, 10); + /* WPA mode */ + if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) + || (CipherAlg == CIPHER_AES)) { + /* Eiv bit on. keyid always is 0 for pairwise key */ + IVEIV = (KeyIdx << 6) | 0x20; + } else { + /* WEP KeyIdx is default tx key. */ + IVEIV = (KeyIdx << 6); + } - DBGPRINT(RT_DEBUG_TRACE, ("<== Set_Debug_Proc(RTDebugLevel = %ld)\n", RTDebugLevel)); + /* For key index and ext IV bit, so only need to update the position(offset+3). */ +#ifdef RTMP_MAC_PCI + RTMP_IO_WRITE8(pAd, offset + 3, IVEIV); +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + RTUSBMultiWrite_OneByte(pAd, offset + 3, &IVEIV); +#endif /* RTMP_MAC_USB // */ - return TRUE; -} -#endif + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPAddWcidAttributeEntry: WCID #%d, KeyIndex #%d, Alg=%s\n", + Wcid, KeyIdx, CipherName[CipherAlg])); + DBGPRINT(RT_DEBUG_TRACE, (" WCIDAttri = 0x%x \n", WCIDAttri)); -INT Show_DescInfo_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ -#ifdef RT2860 - INT i, QueIdx=0; - PRT28XX_RXD_STRUC pRxD; - PTXD_STRUC pTxD; - PRTMP_TX_RING pTxRing = &pAd->TxRing[QueIdx]; - PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; - PRTMP_RX_RING pRxRing = &pAd->RxRing; - - for(i=0;iCell[i].AllocVa; - printk("Desc #%d\n",i); - hex_dump("Tx Descriptor", (char *)pTxD, 16); - printk("pTxD->DMADONE = %x\n", pTxD->DMADONE); - } - printk("---------------------------------------------------\n"); - for(i=0;iCell[i].AllocVa; - printk("Desc #%d\n",i); - hex_dump("Mgmt Descriptor", (char *)pTxD, 16); - printk("pMgmt->DMADONE = %x\n", pTxD->DMADONE); - } - printk("---------------------------------------------------\n"); - for(i=0;iCell[i].AllocVa; - printk("Desc #%d\n",i); - hex_dump("Rx Descriptor", (char *)pRxD, 16); - printk("pRxD->DDONE = %x\n", pRxD->DDONE); - } -#endif /* RT2860 */ - return TRUE; } /* ========================================================================== Description: - Reset statistics counter + Parse encryption type +Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument - Arguments: - pAdapter Pointer to our adapter - arg + Return Value: + None - Return: - TRUE if all parameters are OK, FALSE otherwise + Note: ========================================================================== */ -INT Set_ResetStatCounter_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - DBGPRINT(RT_DEBUG_TRACE, ("==>Set_ResetStatCounter_Proc\n")); - - // add the most up-to-date h/w raw counters into software counters - NICUpdateRawCounters(pAd); - - NdisZeroMemory(&pAd->WlanCounters, sizeof(COUNTER_802_11)); - NdisZeroMemory(&pAd->Counters8023, sizeof(COUNTER_802_3)); - NdisZeroMemory(&pAd->RalinkCounters, sizeof(COUNTER_RALINK)); - - return TRUE; -} - -BOOLEAN RTMPCheckStrPrintAble( - IN CHAR *pInPutStr, - IN UCHAR strLen) -{ - UCHAR i=0; - - for (i=0; i 0x7E)) - return FALSE; - } - - return TRUE; -} - -/* - ======================================================================== +char *GetEncryptType(char enc) +{ + if (enc == Ndis802_11WEPDisabled) + return "NONE"; + if (enc == Ndis802_11WEPEnabled) + return "WEP"; + if (enc == Ndis802_11Encryption2Enabled) + return "TKIP"; + if (enc == Ndis802_11Encryption3Enabled) + return "AES"; + if (enc == Ndis802_11Encryption4Enabled) + return "TKIPAES"; + else + return "UNKNOW"; +} + +char *GetAuthMode(char auth) +{ + if (auth == Ndis802_11AuthModeOpen) + return "OPEN"; + if (auth == Ndis802_11AuthModeShared) + return "SHARED"; + if (auth == Ndis802_11AuthModeAutoSwitch) + return "AUTOWEP"; + if (auth == Ndis802_11AuthModeWPA) + return "WPA"; + if (auth == Ndis802_11AuthModeWPAPSK) + return "WPAPSK"; + if (auth == Ndis802_11AuthModeWPANone) + return "WPANONE"; + if (auth == Ndis802_11AuthModeWPA2) + return "WPA2"; + if (auth == Ndis802_11AuthModeWPA2PSK) + return "WPA2PSK"; + if (auth == Ndis802_11AuthModeWPA1WPA2) + return "WPA1WPA2"; + if (auth == Ndis802_11AuthModeWPA1PSKWPA2PSK) + return "WPA1PSKWPA2PSK"; + + return "UNKNOW"; +} + +int SetCommonHT(struct rt_rtmp_adapter *pAd) +{ + struct rt_oid_set_ht_phymode SetHT; - Routine Description: - Remove WPA Key process - - Arguments: - pAd Pointer to our adapter - pBuf Pointer to the where the key stored - - Return Value: - NDIS_SUCCESS Add key successfully - - IRQL = DISPATCH_LEVEL - - Note: + if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) + return FALSE; - ======================================================================== -*/ -VOID RTMPSetDesiredRates( - IN PRTMP_ADAPTER pAdapter, - IN LONG Rates) -{ - NDIS_802_11_RATES aryRates; - - memset(&aryRates, 0x00, sizeof(NDIS_802_11_RATES)); - switch (pAdapter->CommonCfg.PhyMode) - { - case PHY_11A: // A only - switch (Rates) - { - case 6000000: //6M - aryRates[0] = 0x0c; // 6M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; - break; - case 9000000: //9M - aryRates[0] = 0x12; // 9M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; - break; - case 12000000: //12M - aryRates[0] = 0x18; // 12M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; - break; - case 18000000: //18M - aryRates[0] = 0x24; // 18M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; - break; - case 24000000: //24M - aryRates[0] = 0x30; // 24M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_4; - break; - case 36000000: //36M - aryRates[0] = 0x48; // 36M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_5; - break; - case 48000000: //48M - aryRates[0] = 0x60; // 48M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_6; - break; - case 54000000: //54M - aryRates[0] = 0x6c; // 54M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_7; - break; - case -1: //Auto - default: - aryRates[0] = 0x6c; // 54Mbps - aryRates[1] = 0x60; // 48Mbps - aryRates[2] = 0x48; // 36Mbps - aryRates[3] = 0x30; // 24Mbps - aryRates[4] = 0x24; // 18M - aryRates[5] = 0x18; // 12M - aryRates[6] = 0x12; // 9M - aryRates[7] = 0x0c; // 6M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; - break; - } - break; - case PHY_11BG_MIXED: // B/G Mixed - case PHY_11B: // B only - case PHY_11ABG_MIXED: // A/B/G Mixed - default: - switch (Rates) - { - case 1000000: //1M - aryRates[0] = 0x02; - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; - break; - case 2000000: //2M - aryRates[0] = 0x04; - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; - break; - case 5000000: //5.5M - aryRates[0] = 0x0b; // 5.5M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; - break; - case 11000000: //11M - aryRates[0] = 0x16; // 11M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; - break; - case 6000000: //6M - aryRates[0] = 0x0c; // 6M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; - break; - case 9000000: //9M - aryRates[0] = 0x12; // 9M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; - break; - case 12000000: //12M - aryRates[0] = 0x18; // 12M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; - break; - case 18000000: //18M - aryRates[0] = 0x24; // 18M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; - break; - case 24000000: //24M - aryRates[0] = 0x30; // 24M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_4; - break; - case 36000000: //36M - aryRates[0] = 0x48; // 36M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_5; - break; - case 48000000: //48M - aryRates[0] = 0x60; // 48M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_6; - break; - case 54000000: //54M - aryRates[0] = 0x6c; // 54M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_7; - break; - case -1: //Auto - default: - if (pAdapter->CommonCfg.PhyMode == PHY_11B) - { //B Only - aryRates[0] = 0x16; // 11Mbps - aryRates[1] = 0x0b; // 5.5Mbps - aryRates[2] = 0x04; // 2Mbps - aryRates[3] = 0x02; // 1Mbps - } - else - { //(B/G) Mixed or (A/B/G) Mixed - aryRates[0] = 0x6c; // 54Mbps - aryRates[1] = 0x60; // 48Mbps - aryRates[2] = 0x48; // 36Mbps - aryRates[3] = 0x30; // 24Mbps - aryRates[4] = 0x16; // 11Mbps - aryRates[5] = 0x0b; // 5.5Mbps - aryRates[6] = 0x04; // 2Mbps - aryRates[7] = 0x02; // 1Mbps - } - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; - break; - } - break; - } - - NdisZeroMemory(pAdapter->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); - NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES)); - DBGPRINT(RT_DEBUG_TRACE, (" RTMPSetDesiredRates (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n", - pAdapter->CommonCfg.DesireRate[0],pAdapter->CommonCfg.DesireRate[1], - pAdapter->CommonCfg.DesireRate[2],pAdapter->CommonCfg.DesireRate[3], - pAdapter->CommonCfg.DesireRate[4],pAdapter->CommonCfg.DesireRate[5], - pAdapter->CommonCfg.DesireRate[6],pAdapter->CommonCfg.DesireRate[7] )); - // Changing DesiredRate may affect the MAX TX rate we used to TX frames out - MlmeUpdateTxRates(pAdapter, FALSE, 0); -} + SetHT.PhyMode = pAd->CommonCfg.PhyMode; + SetHT.TransmitNo = ((u8)pAd->Antenna.field.TxPath); + SetHT.HtMode = (u8)pAd->CommonCfg.RegTransmitSetting.field.HTMODE; + SetHT.ExtOffset = + (u8)pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + SetHT.MCS = MCS_AUTO; + SetHT.BW = (u8)pAd->CommonCfg.RegTransmitSetting.field.BW; + SetHT.STBC = (u8)pAd->CommonCfg.RegTransmitSetting.field.STBC; + SetHT.SHORTGI = (u8)pAd->CommonCfg.RegTransmitSetting.field.ShortGI; -NDIS_STATUS RTMPWPARemoveKeyProc( - IN PRTMP_ADAPTER pAd, - IN PVOID pBuf) -{ - PNDIS_802_11_REMOVE_KEY pKey; - ULONG KeyIdx; - NDIS_STATUS Status = NDIS_STATUS_FAILURE; - BOOLEAN bTxKey; // Set the key as transmit key - BOOLEAN bPairwise; // Indicate the key is pairwise key - BOOLEAN bKeyRSC; // indicate the receive SC set by KeyRSC value. - // Otherwise, it will set by the NIC. - BOOLEAN bAuthenticator; // indicate key is set by authenticator. - INT i; - - DBGPRINT(RT_DEBUG_TRACE,("---> RTMPWPARemoveKeyProc\n")); - - pKey = (PNDIS_802_11_REMOVE_KEY) pBuf; - KeyIdx = pKey->KeyIndex & 0xff; - // Bit 31 of Add-key, Tx Key - bTxKey = (pKey->KeyIndex & 0x80000000) ? TRUE : FALSE; - // Bit 30 of Add-key PairwiseKey - bPairwise = (pKey->KeyIndex & 0x40000000) ? TRUE : FALSE; - // Bit 29 of Add-key KeyRSC - bKeyRSC = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE; - // Bit 28 of Add-key Authenticator - bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE; - - // 1. If bTx is TRUE, return failure information - if (bTxKey == TRUE) - return(NDIS_STATUS_INVALID_DATA); - - // 2. Check Pairwise Key - if (bPairwise) - { - // a. If BSSID is broadcast, remove all pairwise keys. - // b. If not broadcast, remove the pairwise specified by BSSID - for (i = 0; i < SHARE_KEY_NUM; i++) - { - if (MAC_ADDR_EQUAL(pAd->SharedKey[BSS0][i].BssId, pKey->BSSID)) - { - DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%d)\n", i)); - pAd->SharedKey[BSS0][i].KeyLen = 0; - pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_NONE; - AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)i); - Status = NDIS_STATUS_SUCCESS; - break; - } - } - } - // 3. Group Key - else - { - // a. If BSSID is broadcast, remove all group keys indexed - // b. If BSSID matched, delete the group key indexed. - DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%ld)\n", KeyIdx)); - pAd->SharedKey[BSS0][KeyIdx].KeyLen = 0; - pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE; - AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)KeyIdx); - Status = NDIS_STATUS_SUCCESS; - } + RTMPSetHT(pAd, &SetHT); - return (Status); + return TRUE; } -/* - ======================================================================== - - Routine Description: - Remove All WPA Keys - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPWPARemoveAllKeys( - IN PRTMP_ADAPTER pAd) +char *RTMPGetRalinkEncryModeStr(u16 encryMode) { - - UCHAR i; - - DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveAllKeys(AuthMode=%d, WepStatus=%d)\n", pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus)); - - // For WEP/CKIP, there is no need to remove it, since WinXP won't set it again after - // Link up. And it will be replaced if user changed it. - if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) - return; - - // For WPA-None, there is no need to remove it, since WinXP won't set it again after - // Link up. And it will be replaced if user changed it. - if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - return; - - // set BSSID wcid entry of the Pair-wise Key table as no-security mode - AsicRemovePairwiseKeyEntry(pAd, BSS0, BSSID_WCID); - - // set all shared key mode as no-security. - for (i = 0; i < SHARE_KEY_NUM; i++) - { - DBGPRINT(RT_DEBUG_TRACE,("remove %s key #%d\n", CipherName[pAd->SharedKey[BSS0][i].CipherAlg], i)); - NdisZeroMemory(&pAd->SharedKey[BSS0][i], sizeof(CIPHER_KEY)); - - AsicRemoveSharedKeyEntry(pAd, BSS0, i); + switch (encryMode) { + case Ndis802_11WEPDisabled: + return "NONE"; + case Ndis802_11WEPEnabled: + return "WEP"; + case Ndis802_11Encryption2Enabled: + return "TKIP"; + case Ndis802_11Encryption3Enabled: + return "AES"; + case Ndis802_11Encryption4Enabled: + return "TKIPAES"; + default: + return "UNKNOW"; } - } - -/* - ======================================================================== - Routine Description: - Change NIC PHY mode. Re-association may be necessary. possible settings - include - PHY_11B, PHY_11BG_MIXED, PHY_11A, and PHY_11ABG_MIXED - - Arguments: - pAd - Pointer to our adapter - phymode - - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - ======================================================================== -*/ -VOID RTMPSetPhyMode( - IN PRTMP_ADAPTER pAd, - IN ULONG phymode) -{ - INT i; - // the selected phymode must be supported by the RF IC encoded in E2PROM - - pAd->CommonCfg.PhyMode = (UCHAR)phymode; - - DBGPRINT(RT_DEBUG_TRACE,("RTMPSetPhyMode : PhyMode=%d, channel=%d \n", pAd->CommonCfg.PhyMode, pAd->CommonCfg.Channel)); - - BuildChannelList(pAd); - - // sanity check user setting - for (i = 0; i < pAd->ChannelListNum; i++) - { - if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel) - break; - } - - if (i == pAd->ChannelListNum) - { - pAd->CommonCfg.Channel = FirstChannel(pAd); - DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetPhyMode: channel is out of range, use first channel=%d \n", pAd->CommonCfg.Channel)); - } - - NdisZeroMemory(pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); - NdisZeroMemory(pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES); - NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); - switch (phymode) { - case PHY_11B: - pAd->CommonCfg.SupRate[0] = 0x82; // 1 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[1] = 0x84; // 2 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[2] = 0x8B; // 5.5 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[3] = 0x96; // 11 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRateLen = 4; - pAd->CommonCfg.ExtRateLen = 0; - pAd->CommonCfg.DesireRate[0] = 2; // 1 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[1] = 4; // 2 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[2] = 11; // 5.5 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[3] = 22; // 11 mbps, in units of 0.5 Mbps - //pAd->CommonCfg.HTPhyMode.field.MODE = MODE_CCK; // This MODE is only FYI. not use - break; - - case PHY_11G: - case PHY_11BG_MIXED: - case PHY_11ABG_MIXED: - case PHY_11N_2_4G: - case PHY_11ABGN_MIXED: - case PHY_11BGN_MIXED: - case PHY_11GN_MIXED: - pAd->CommonCfg.SupRate[0] = 0x82; // 1 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[1] = 0x84; // 2 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[2] = 0x8B; // 5.5 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[3] = 0x96; // 11 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[4] = 0x12; // 9 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRate[5] = 0x24; // 18 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRate[6] = 0x48; // 36 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRateLen = 8; - pAd->CommonCfg.ExtRate[0] = 0x0C; // 6 mbps, in units of 0.5 Mbps - pAd->CommonCfg.ExtRate[1] = 0x18; // 12 mbps, in units of 0.5 Mbps - pAd->CommonCfg.ExtRate[2] = 0x30; // 24 mbps, in units of 0.5 Mbps - pAd->CommonCfg.ExtRate[3] = 0x60; // 48 mbps, in units of 0.5 Mbps - pAd->CommonCfg.ExtRateLen = 4; - pAd->CommonCfg.DesireRate[0] = 2; // 1 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[1] = 4; // 2 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[2] = 11; // 5.5 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[3] = 22; // 11 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[4] = 12; // 6 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[5] = 18; // 9 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[6] = 24; // 12 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[7] = 36; // 18 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[8] = 48; // 24 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[9] = 72; // 36 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[10] = 96; // 48 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[11] = 108; // 54 mbps, in units of 0.5 Mbps - break; - - case PHY_11A: - case PHY_11AN_MIXED: - case PHY_11AGN_MIXED: - case PHY_11N_5G: - pAd->CommonCfg.SupRate[0] = 0x8C; // 6 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRate[2] = 0x98; // 12 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRate[4] = 0xb0; // 24 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRateLen = 8; - pAd->CommonCfg.ExtRateLen = 0; - pAd->CommonCfg.DesireRate[0] = 12; // 6 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[1] = 18; // 9 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[2] = 24; // 12 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[3] = 36; // 18 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[4] = 48; // 24 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[5] = 72; // 36 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[6] = 96; // 48 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[7] = 108; // 54 mbps, in units of 0.5 Mbps - //pAd->CommonCfg.HTPhyMode.field.MODE = MODE_OFDM; // This MODE is only FYI. not use - break; - - default: - break; - } - - - pAd->CommonCfg.BandState = UNKNOWN_BAND; -} - -/* - ======================================================================== - Routine Description: - Caller ensures we has 802.11n support. - Calls at setting HT from AP/STASetinformation - - Arguments: - pAd - Pointer to our adapter - phymode - - - ======================================================================== -*/ -VOID RTMPSetHT( - IN PRTMP_ADAPTER pAd, - IN OID_SET_HT_PHYMODE *pHTPhyMode) -{ - //ULONG *pmcs; - UINT32 Value = 0; - UCHAR BBPValue = 0; - UCHAR BBP3Value = 0; - UCHAR RxStream = pAd->CommonCfg.RxStream; - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : HT_mode(%d), ExtOffset(%d), MCS(%d), BW(%d), STBC(%d), SHORTGI(%d)\n", - pHTPhyMode->HtMode, pHTPhyMode->ExtOffset, - pHTPhyMode->MCS, pHTPhyMode->BW, - pHTPhyMode->STBC, pHTPhyMode->SHORTGI)); - - // Don't zero supportedHyPhy structure. - RTMPZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability)); - RTMPZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo)); - RTMPZeroMemory(&pAd->CommonCfg.NewExtChanOffset, sizeof(pAd->CommonCfg.NewExtChanOffset)); - RTMPZeroMemory(&pAd->CommonCfg.DesiredHtPhy, sizeof(pAd->CommonCfg.DesiredHtPhy)); - - if (pAd->CommonCfg.bRdg) - { - pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 1; - pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 1; - } - else - { - pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 0; - pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 0; - } - - pAd->CommonCfg.HtCapability.HtCapParm.MaxRAmpduFactor = 3; - pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor = 3; - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : RxBAWinLimit = %d\n", pAd->CommonCfg.BACapability.field.RxBAWinLimit)); - - // Mimo power save, A-MSDU size, - pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable; - pAd->CommonCfg.DesiredHtPhy.AmsduSize = (UCHAR)pAd->CommonCfg.BACapability.field.AmsduSize; - pAd->CommonCfg.DesiredHtPhy.MimoPs = (UCHAR)pAd->CommonCfg.BACapability.field.MMPSmode; - pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; - - pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; - pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; - pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : AMsduSize = %d, MimoPs = %d, MpduDensity = %d, MaxRAmpduFactor = %d\n", - pAd->CommonCfg.DesiredHtPhy.AmsduSize, - pAd->CommonCfg.DesiredHtPhy.MimoPs, - pAd->CommonCfg.DesiredHtPhy.MpduDensity, - pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor)); - - if(pHTPhyMode->HtMode == HTMODE_GF) - { - pAd->CommonCfg.HtCapability.HtCapInfo.GF = 1; - pAd->CommonCfg.DesiredHtPhy.GF = 1; - } - else - pAd->CommonCfg.DesiredHtPhy.GF = 0; - - // Decide Rx MCSSet - switch (RxStream) - { - case 1: - pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; - pAd->CommonCfg.HtCapability.MCSSet[1] = 0x00; - break; - - case 2: - pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; - pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff; - break; - - case 3: // 3*3 - pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; - pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff; - pAd->CommonCfg.HtCapability.MCSSet[2] = 0xff; - break; - } - - if (pAd->CommonCfg.bForty_Mhz_Intolerant && (pAd->CommonCfg.Channel <= 14) && (pHTPhyMode->BW == BW_40) ) - { - pHTPhyMode->BW = BW_20; - pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant = 1; - } - - if(pHTPhyMode->BW == BW_40) - { - pAd->CommonCfg.HtCapability.MCSSet[4] = 0x1; // MCS 32 - pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 1; - if (pAd->CommonCfg.Channel <= 14) - pAd->CommonCfg.HtCapability.HtCapInfo.CCKmodein40 = 1; - - pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 1; - pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 1; - pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = (pHTPhyMode->ExtOffset == EXTCHA_BELOW)? (EXTCHA_BELOW): EXTCHA_ABOVE; - // Set Regsiter for extension channel position. - RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBP3Value); - if ((pHTPhyMode->ExtOffset == EXTCHA_BELOW)) - { - Value |= 0x1; - BBP3Value |= (0x20); - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); - } - else if ((pHTPhyMode->ExtOffset == EXTCHA_ABOVE)) - { - Value &= 0xfe; - BBP3Value &= (~0x20); - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); - } - - // Turn on BBP 40MHz mode now only as AP . - // Sta can turn on BBP 40MHz after connection with 40MHz AP. Sta only broadcast 40MHz capability before connection. - if ((pAd->OpMode == OPMODE_AP) || INFRA_ON(pAd) || ADHOC_ON(pAd) - ) - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue &= (~0x18); - BBPValue |= 0x10; - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBP3Value); - pAd->CommonCfg.BBPCurrentBW = BW_40; - } - } - else - { - pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 0; - pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 0; - pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; - pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = EXTCHA_NONE; - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; - // Turn on BBP 20MHz mode by request here. - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue &= (~0x18); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - pAd->CommonCfg.BBPCurrentBW = BW_20; - } - } - - if(pHTPhyMode->STBC == STBC_USE) - { - pAd->CommonCfg.HtCapability.HtCapInfo.TxSTBC = 1; - pAd->CommonCfg.DesiredHtPhy.TxSTBC = 1; - pAd->CommonCfg.HtCapability.HtCapInfo.RxSTBC = 1; - pAd->CommonCfg.DesiredHtPhy.RxSTBC = 1; - } - else - { - pAd->CommonCfg.DesiredHtPhy.TxSTBC = 0; - pAd->CommonCfg.DesiredHtPhy.RxSTBC = 0; - } - - if(pHTPhyMode->SHORTGI == GI_400) - { - pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 1; - pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 1; - pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 1; - pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 1; - } - else - { - pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 0; - pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 0; - pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 0; - pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 0; - } - - // We support link adaptation for unsolicit MCS feedback, set to 2. - pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_NONE; //MCSFBK_UNSOLICIT; - pAd->CommonCfg.AddHTInfo.ControlChan = pAd->CommonCfg.Channel; - // 1, the extension channel above the control channel. - - // EDCA parameters used for AP's own transmission - if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) - { - pAd->CommonCfg.APEdcaParm.bValid = TRUE; - pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; - pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; - pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; - pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; - - pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; - pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; - pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; - pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; - - pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6; - pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10; - pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; - pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; - - pAd->CommonCfg.APEdcaParm.Txop[0] = 0; - pAd->CommonCfg.APEdcaParm.Txop[1] = 0; - pAd->CommonCfg.APEdcaParm.Txop[2] = 94; - pAd->CommonCfg.APEdcaParm.Txop[3] = 47; - } - AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); - - RTMPSetIndividualHT(pAd, 0); -} - -/* - ======================================================================== - Routine Description: - Caller ensures we has 802.11n support. - Calls at setting HT from AP/STASetinformation - - Arguments: - pAd - Pointer to our adapter - phymode - - - ======================================================================== -*/ -VOID RTMPSetIndividualHT( - IN PRTMP_ADAPTER pAd, - IN UCHAR apidx) -{ - PRT_HT_PHY_INFO pDesired_ht_phy = NULL; - UCHAR TxStream = pAd->CommonCfg.TxStream; - UCHAR DesiredMcs = MCS_AUTO; - - do - { - { - pDesired_ht_phy = &pAd->StaCfg.DesiredHtPhyInfo; - DesiredMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS; - //pAd->StaCfg.bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; - break; - } - } while (FALSE); - - if (pDesired_ht_phy == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx)); - return; - } - RTMPZeroMemory(pDesired_ht_phy, sizeof(RT_HT_PHY_INFO)); - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetIndividualHT : Desired MCS = %d\n", DesiredMcs)); - // Check the validity of MCS - if ((TxStream == 1) && ((DesiredMcs >= MCS_8) && (DesiredMcs <= MCS_15))) - { - DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS(%d) is invalid in 1S, reset it as MCS_7\n", DesiredMcs)); - DesiredMcs = MCS_7; - } - - if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_20) && (DesiredMcs == MCS_32)) - { - DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS_32 is only supported in 40-MHz, reset it as MCS_0\n")); - DesiredMcs = MCS_0; - } - - pDesired_ht_phy->bHtEnable = TRUE; - - // Decide desired Tx MCS - switch (TxStream) - { - case 1: - if (DesiredMcs == MCS_AUTO) - { - pDesired_ht_phy->MCSSet[0]= 0xff; - pDesired_ht_phy->MCSSet[1]= 0x00; - } - else if (DesiredMcs <= MCS_7) - { - pDesired_ht_phy->MCSSet[0]= 1<MCSSet[1]= 0x00; - } - break; - - case 2: - if (DesiredMcs == MCS_AUTO) - { - pDesired_ht_phy->MCSSet[0]= 0xff; - pDesired_ht_phy->MCSSet[1]= 0xff; - } - else if (DesiredMcs <= MCS_15) - { - ULONG mode; - - mode = DesiredMcs / 8; - if (mode < 2) - pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8)); - } - break; - - case 3: // 3*3 - if (DesiredMcs == MCS_AUTO) - { - /* MCS0 ~ MCS23, 3 bytes */ - pDesired_ht_phy->MCSSet[0]= 0xff; - pDesired_ht_phy->MCSSet[1]= 0xff; - pDesired_ht_phy->MCSSet[2]= 0xff; - } - else if (DesiredMcs <= MCS_23) - { - ULONG mode; - - mode = DesiredMcs / 8; - if (mode < 3) - pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8)); - } - break; - } - - if(pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_40) - { - if (DesiredMcs == MCS_AUTO || DesiredMcs == MCS_32) - pDesired_ht_phy->MCSSet[4] = 0x1; - } - - // update HT Rate setting - if (pAd->OpMode == OPMODE_STA) - MlmeUpdateHtTxRates(pAd, BSS0); - else - MlmeUpdateHtTxRates(pAd, apidx); -} - - -/* - ======================================================================== - Routine Description: - Update HT IE from our capability. - - Arguments: - Send all HT IE in beacon/probe rsp/assoc rsp/action frame. - - - ======================================================================== -*/ -VOID RTMPUpdateHTIE( - IN RT_HT_CAPABILITY *pRtHt, - IN UCHAR *pMcsSet, - OUT HT_CAPABILITY_IE *pHtCapability, - OUT ADD_HT_INFO_IE *pAddHtInfo) -{ - RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE)); - RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE)); - - pHtCapability->HtCapInfo.ChannelWidth = pRtHt->ChannelWidth; - pHtCapability->HtCapInfo.MimoPs = pRtHt->MimoPs; - pHtCapability->HtCapInfo.GF = pRtHt->GF; - pHtCapability->HtCapInfo.ShortGIfor20 = pRtHt->ShortGIfor20; - pHtCapability->HtCapInfo.ShortGIfor40 = pRtHt->ShortGIfor40; - pHtCapability->HtCapInfo.TxSTBC = pRtHt->TxSTBC; - pHtCapability->HtCapInfo.RxSTBC = pRtHt->RxSTBC; - pHtCapability->HtCapInfo.AMsduSize = pRtHt->AmsduSize; - pHtCapability->HtCapParm.MaxRAmpduFactor = pRtHt->MaxRAmpduFactor; - pHtCapability->HtCapParm.MpduDensity = pRtHt->MpduDensity; - - pAddHtInfo->AddHtInfo.ExtChanOffset = pRtHt->ExtChanOffset ; - pAddHtInfo->AddHtInfo.RecomWidth = pRtHt->RecomWidth; - pAddHtInfo->AddHtInfo2.OperaionMode = pRtHt->OperaionMode; - pAddHtInfo->AddHtInfo2.NonGfPresent = pRtHt->NonGfPresent; - RTMPMoveMemory(pAddHtInfo->MCSSet, /*pRtHt->MCSSet*/pMcsSet, 4); // rt2860 only support MCS max=32, no need to copy all 16 uchar. - - DBGPRINT(RT_DEBUG_TRACE,("RTMPUpdateHTIE <== \n")); -} - -/* - ======================================================================== - Description: - Add Client security information into ASIC WCID table and IVEIV table. - Return: - ======================================================================== -*/ -VOID RTMPAddWcidAttributeEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIdx, - IN UCHAR KeyIdx, - IN UCHAR CipherAlg, - IN MAC_TABLE_ENTRY *pEntry) -{ - UINT32 WCIDAttri = 0; - USHORT offset; - UCHAR IVEIV = 0; - USHORT Wcid = 0; - - { - { - if (BssIdx > BSS0) - { - DBGPRINT(RT_DEBUG_ERROR, ("RTMPAddWcidAttributeEntry: The BSS-index(%d) is out of range for Infra link. \n", BssIdx)); - return; - } - - // 1. In ADHOC mode, the AID is wcid number. And NO mesh link exists. - // 2. In Infra mode, the AID:1 MUST be wcid of infra STA. - // the AID:2~ assign to mesh link entry. - if (pEntry && ADHOC_ON(pAd)) - Wcid = pEntry->Aid; - else if (pEntry && INFRA_ON(pAd)) - { - Wcid = BSSID_WCID; - } - else - Wcid = MCAST_WCID; - } - } - - // Update WCID attribute table - offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE); - - { - if (pEntry && pEntry->ValidAsMesh) - WCIDAttri = (CipherAlg<<1) | PAIRWISEKEYTABLE; - else - WCIDAttri = (CipherAlg<<1) | SHAREDKEYTABLE; - } - - RTMP_IO_WRITE32(pAd, offset, WCIDAttri); - - - // Update IV/EIV table - offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_SIZE); - - // WPA mode - if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) || (CipherAlg == CIPHER_AES)) - { - // Eiv bit on. keyid always is 0 for pairwise key - IVEIV = (KeyIdx <<6) | 0x20; - } - else - { - // WEP KeyIdx is default tx key. - IVEIV = (KeyIdx << 6); - } - - // For key index and ext IV bit, so only need to update the position(offset+3). -#ifdef RT2860 - RTMP_IO_WRITE8(pAd, offset+3, IVEIV); -#endif -#ifdef RT2870 - RTUSBMultiWrite_OneByte(pAd, offset+3, &IVEIV); -#endif // RT2870 // - - DBGPRINT(RT_DEBUG_TRACE,("RTMPAddWcidAttributeEntry: WCID #%d, KeyIndex #%d, Alg=%s\n",Wcid, KeyIdx, CipherName[CipherAlg])); - DBGPRINT(RT_DEBUG_TRACE,(" WCIDAttri = 0x%x \n", WCIDAttri)); - -} - -/* - ========================================================================== - Description: - Parse encryption type -Arguments: - pAdapter Pointer to our adapter - wrq Pointer to the ioctl argument - - Return Value: - None - - Note: - ========================================================================== -*/ -CHAR *GetEncryptType(CHAR enc) -{ - if(enc == Ndis802_11WEPDisabled) - return "NONE"; - if(enc == Ndis802_11WEPEnabled) - return "WEP"; - if(enc == Ndis802_11Encryption2Enabled) - return "TKIP"; - if(enc == Ndis802_11Encryption3Enabled) - return "AES"; - if(enc == Ndis802_11Encryption4Enabled) - return "TKIPAES"; - else - return "UNKNOW"; -} - -CHAR *GetAuthMode(CHAR auth) -{ - if(auth == Ndis802_11AuthModeOpen) - return "OPEN"; - if(auth == Ndis802_11AuthModeShared) - return "SHARED"; - if(auth == Ndis802_11AuthModeAutoSwitch) - return "AUTOWEP"; - if(auth == Ndis802_11AuthModeWPA) - return "WPA"; - if(auth == Ndis802_11AuthModeWPAPSK) - return "WPAPSK"; - if(auth == Ndis802_11AuthModeWPANone) - return "WPANONE"; - if(auth == Ndis802_11AuthModeWPA2) - return "WPA2"; - if(auth == Ndis802_11AuthModeWPA2PSK) - return "WPA2PSK"; - if(auth == Ndis802_11AuthModeWPA1WPA2) - return "WPA1WPA2"; - if(auth == Ndis802_11AuthModeWPA1PSKWPA2PSK) - return "WPA1PSKWPA2PSK"; - - return "UNKNOW"; -} - -/* - ========================================================================== - Description: - Get site survey results - Arguments: - pAdapter Pointer to our adapter - wrq Pointer to the ioctl argument - - Return Value: - None - - Note: - Usage: - 1.) UI needs to wait 4 seconds after issue a site survey command - 2.) iwpriv ra0 get_site_survey - 3.) UI needs to prepare at least 4096bytes to get the results - ========================================================================== -*/ -#define LINE_LEN (4+33+20+8+10+9+7+3) // Channel+SSID+Bssid+WepStatus+AuthMode+Signal+WiressMode+NetworkType -VOID RTMPIoctlGetSiteSurvey( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq) -{ - CHAR *msg; - INT i=0; - INT WaitCnt; - INT Status=0; - CHAR Ssid[MAX_LEN_OF_SSID +1]; - INT Rssi = 0, max_len = LINE_LEN; - UINT Rssi_Quality = 0; - NDIS_802_11_NETWORK_TYPE wireless_mode; - - os_alloc_mem(NULL, (PUCHAR *)&msg, sizeof(CHAR)*((MAX_LEN_OF_BSS_TABLE)*max_len)); - - if (msg == NULL) - { - DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - msg memory alloc fail.\n")); - return; - } - - memset(msg, 0 ,(MAX_LEN_OF_BSS_TABLE)*max_len ); - memset(Ssid, 0 ,(MAX_LEN_OF_SSID +1)); - sprintf(msg,"%s","\n"); - sprintf(msg+strlen(msg),"%-4s%-33s%-20s%-8s%-10s%-9s%-7s%-3s\n", - "Ch", "SSID", "BSSID", "Enc", "Auth", "Siganl(%)", "W-Mode", " NT"); - - WaitCnt = 0; - pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE; - - while ((ScanRunning(pAdapter) == TRUE) && (WaitCnt++ < 200)) - OS_WAIT(500); - - for(i=0; iScanTab.BssNr ;i++) - { - if( pAdapter->ScanTab.BssEntry[i].Channel==0) - break; - - if((strlen(msg)+max_len ) >= IW_SCAN_MAX_DATA) - break; - - //Channel - sprintf(msg+strlen(msg),"%-4d", pAdapter->ScanTab.BssEntry[i].Channel); - //SSID - memcpy(Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen); - Ssid[pAdapter->ScanTab.BssEntry[i].SsidLen] = '\0'; - sprintf(msg+strlen(msg),"%-33s", Ssid); - //BSSID - sprintf(msg+strlen(msg),"%02x:%02x:%02x:%02x:%02x:%02x ", - pAdapter->ScanTab.BssEntry[i].Bssid[0], - pAdapter->ScanTab.BssEntry[i].Bssid[1], - pAdapter->ScanTab.BssEntry[i].Bssid[2], - pAdapter->ScanTab.BssEntry[i].Bssid[3], - pAdapter->ScanTab.BssEntry[i].Bssid[4], - pAdapter->ScanTab.BssEntry[i].Bssid[5]); - //Encryption Type - sprintf(msg+strlen(msg),"%-8s",GetEncryptType(pAdapter->ScanTab.BssEntry[i].WepStatus)); - //Authentication Mode - if (pAdapter->ScanTab.BssEntry[i].WepStatus == Ndis802_11WEPEnabled) - sprintf(msg+strlen(msg),"%-10s", "UNKNOW"); - else - sprintf(msg+strlen(msg),"%-10s",GetAuthMode(pAdapter->ScanTab.BssEntry[i].AuthMode)); - // Rssi - Rssi = (INT)pAdapter->ScanTab.BssEntry[i].Rssi; - if (Rssi >= -50) - Rssi_Quality = 100; - else if (Rssi >= -80) // between -50 ~ -80dbm - Rssi_Quality = (UINT)(24 + ((Rssi + 80) * 26)/10); - else if (Rssi >= -90) // between -80 ~ -90dbm - Rssi_Quality = (UINT)(((Rssi + 90) * 26)/10); - else // < -84 dbm - Rssi_Quality = 0; - sprintf(msg+strlen(msg),"%-9d", Rssi_Quality); - // Wireless Mode - wireless_mode = NetworkTypeInUseSanity(&pAdapter->ScanTab.BssEntry[i]); - if (wireless_mode == Ndis802_11FH || - wireless_mode == Ndis802_11DS) - sprintf(msg+strlen(msg),"%-7s", "11b"); - else if (wireless_mode == Ndis802_11OFDM5) - sprintf(msg+strlen(msg),"%-7s", "11a"); - else if (wireless_mode == Ndis802_11OFDM5_N) - sprintf(msg+strlen(msg),"%-7s", "11a/n"); - else if (wireless_mode == Ndis802_11OFDM24) - sprintf(msg+strlen(msg),"%-7s", "11b/g"); - else if (wireless_mode == Ndis802_11OFDM24_N) - sprintf(msg+strlen(msg),"%-7s", "11b/g/n"); - else - sprintf(msg+strlen(msg),"%-7s", "unknow"); - //Network Type - if (pAdapter->ScanTab.BssEntry[i].BssType == BSS_ADHOC) - sprintf(msg+strlen(msg),"%-3s", " Ad"); - else - sprintf(msg+strlen(msg),"%-3s", " In"); - - sprintf(msg+strlen(msg),"\n"); - } - - pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; - wrq->u.data.length = strlen(msg); - Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - wrq->u.data.length = %d\n", wrq->u.data.length)); - os_free_mem(NULL, (PUCHAR)msg); -} - - -#define MAC_LINE_LEN (14+4+4+10+10+10+6+6) // Addr+aid+psm+datatime+rxbyte+txbyte+current tx rate+last tx rate -VOID RTMPIoctlGetMacTable( - IN PRTMP_ADAPTER pAd, - IN struct iwreq *wrq) -{ - INT i; - RT_802_11_MAC_TABLE MacTab; - char *msg; - - MacTab.Num = 0; - for (i=0; iMacTab.Content[i].ValidAsCLI && (pAd->MacTab.Content[i].Sst == SST_ASSOC)) - { - COPY_MAC_ADDR(MacTab.Entry[MacTab.Num].Addr, &pAd->MacTab.Content[i].Addr); - MacTab.Entry[MacTab.Num].Aid = (UCHAR)pAd->MacTab.Content[i].Aid; - MacTab.Entry[MacTab.Num].Psm = pAd->MacTab.Content[i].PsMode; - MacTab.Entry[MacTab.Num].MimoPs = pAd->MacTab.Content[i].MmpsMode; - - // Fill in RSSI per entry - MacTab.Entry[MacTab.Num].AvgRssi0 = pAd->MacTab.Content[i].RssiSample.AvgRssi0; - MacTab.Entry[MacTab.Num].AvgRssi1 = pAd->MacTab.Content[i].RssiSample.AvgRssi1; - MacTab.Entry[MacTab.Num].AvgRssi2 = pAd->MacTab.Content[i].RssiSample.AvgRssi2; - - // the connected time per entry - MacTab.Entry[MacTab.Num].ConnectedTime = pAd->MacTab.Content[i].StaConnectTime; - MacTab.Entry[MacTab.Num].TxRate.field.MCS = pAd->MacTab.Content[i].HTPhyMode.field.MCS; - MacTab.Entry[MacTab.Num].TxRate.field.BW = pAd->MacTab.Content[i].HTPhyMode.field.BW; - MacTab.Entry[MacTab.Num].TxRate.field.ShortGI = pAd->MacTab.Content[i].HTPhyMode.field.ShortGI; - MacTab.Entry[MacTab.Num].TxRate.field.STBC = pAd->MacTab.Content[i].HTPhyMode.field.STBC; - MacTab.Entry[MacTab.Num].TxRate.field.rsv = pAd->MacTab.Content[i].HTPhyMode.field.rsv; - MacTab.Entry[MacTab.Num].TxRate.field.MODE = pAd->MacTab.Content[i].HTPhyMode.field.MODE; - MacTab.Entry[MacTab.Num].TxRate.word = pAd->MacTab.Content[i].HTPhyMode.word; - - MacTab.Num += 1; - } - } - wrq->u.data.length = sizeof(RT_802_11_MAC_TABLE); - if (copy_to_user(wrq->u.data.pointer, &MacTab, wrq->u.data.length)) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __func__)); - } - - msg = (CHAR *) kmalloc(sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN), MEM_ALLOC_FLAG); - memset(msg, 0 ,MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN ); - sprintf(msg,"%s","\n"); - sprintf(msg+strlen(msg),"%-14s%-4s%-4s%-10s%-10s%-10s%-6s%-6s\n", - "MAC", "AID", "PSM", "LDT", "RxB", "TxB","CTxR", "LTxR"); - - for (i=0; iMacTab.Content[i]; - if (pEntry->ValidAsCLI && (pEntry->Sst == SST_ASSOC)) - { - if((strlen(msg)+MAC_LINE_LEN ) >= (MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN) ) - break; - sprintf(msg+strlen(msg),"%02x%02x%02x%02x%02x%02x ", - pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], - pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); - sprintf(msg+strlen(msg),"%-4d", (int)pEntry->Aid); - sprintf(msg+strlen(msg),"%-4d", (int)pEntry->PsMode); - sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.LastDataPacketTime*/); // ToDo - sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalRxByteCount*/); // ToDo - sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalTxByteCount*/); // ToDo - sprintf(msg+strlen(msg),"%-6d",RateIdToMbps[pAd->MacTab.Content[i].CurrTxRate]); - sprintf(msg+strlen(msg),"%-6d\n",0/*RateIdToMbps[pAd->MacTab.Content[i].LastTxRate]*/); // ToDo - } - } - // for compatible with old API just do the printk to console - //wrq->u.data.length = strlen(msg); - //if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s", msg)); - } - - kfree(msg); -} - -INT Set_BASetup_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - UCHAR mac[6], tid; - char *token, sepValue[] = ":", DASH = '-'; - INT i; - MAC_TABLE_ENTRY *pEntry; - -/* - The BASetup inupt string format should be xx:xx:xx:xx:xx:xx-d, - =>The six 2 digit hex-decimal number previous are the Mac address, - =>The seventh decimal number is the tid value. -*/ - - if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format. - return FALSE; - - token = strchr(arg, DASH); - if ((token != NULL) && (strlen(token)>1)) - { - tid = simple_strtol((token+1), 0, 10); - if (tid > 15) - return FALSE; - - *token = '\0'; - for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) - { - if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) - return FALSE; - AtoH(token, (PUCHAR)(&mac[i]), 1); - } - if(i != 6) - return FALSE; - - printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x\n", mac[0], mac[1], - mac[2], mac[3], mac[4], mac[5], tid); - - pEntry = MacTableLookup(pAd, mac); - - if (pEntry) { - printk("\nSetup BA Session: Tid = %d\n", tid); - BAOriSessionSetUp(pAd, pEntry, tid, 0, 100, TRUE); - } - - return TRUE; - } - - return FALSE; - -} - -INT Set_BADecline_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG bBADecline; - - bBADecline = simple_strtol(arg, 0, 10); - - if (bBADecline == 0) - { - pAd->CommonCfg.bBADecline = FALSE; - } - else if (bBADecline == 1) - { - pAd->CommonCfg.bBADecline = TRUE; - } - else - { - return FALSE; //Invalid argument - } - - DBGPRINT(RT_DEBUG_TRACE, ("Set_BADecline_Proc::(BADecline=%d)\n", pAd->CommonCfg.bBADecline)); - - return TRUE; -} - -INT Set_BAOriTearDown_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - UCHAR mac[6], tid; - char *token, sepValue[] = ":", DASH = '-'; - INT i; - MAC_TABLE_ENTRY *pEntry; - -/* - The BAOriTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, - =>The six 2 digit hex-decimal number previous are the Mac address, - =>The seventh decimal number is the tid value. -*/ - if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format. - return FALSE; - - token = strchr(arg, DASH); - if ((token != NULL) && (strlen(token)>1)) - { - tid = simple_strtol((token+1), 0, 10); - if (tid > NUM_OF_TID) - return FALSE; - - *token = '\0'; - for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) - { - if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) - return FALSE; - AtoH(token, (PUCHAR)(&mac[i]), 1); - } - if(i != 6) - return FALSE; - - printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1], - mac[2], mac[3], mac[4], mac[5], tid); - - pEntry = MacTableLookup(pAd, mac); - - if (pEntry) { - printk("\nTear down Ori BA Session: Tid = %d\n", tid); - BAOriSessionTearDown(pAd, pEntry->Aid, tid, FALSE, TRUE); - } - - return TRUE; - } - - return FALSE; - -} - -INT Set_BARecTearDown_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - UCHAR mac[6], tid; - char *token, sepValue[] = ":", DASH = '-'; - INT i; - MAC_TABLE_ENTRY *pEntry; - - //printk("\n%s\n", arg); -/* - The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, - =>The six 2 digit hex-decimal number previous are the Mac address, - =>The seventh decimal number is the tid value. -*/ - if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format. - return FALSE; - - token = strchr(arg, DASH); - if ((token != NULL) && (strlen(token)>1)) - { - tid = simple_strtol((token+1), 0, 10); - if (tid > NUM_OF_TID) - return FALSE; - - *token = '\0'; - for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) - { - if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) - return FALSE; - AtoH(token, (PUCHAR)(&mac[i]), 1); - } - if(i != 6) - return FALSE; - - printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1], - mac[2], mac[3], mac[4], mac[5], tid); - - pEntry = MacTableLookup(pAd, mac); - - if (pEntry) { - printk("\nTear down Rec BA Session: Tid = %d\n", tid); - BARecSessionTearDown(pAd, pEntry->Aid, tid, FALSE); - } - - return TRUE; - } - - return FALSE; - -} - -INT Set_HtBw_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG HtBw; - - HtBw = simple_strtol(arg, 0, 10); - if (HtBw == BW_40) - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; - else if (HtBw == BW_20) - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBw_Proc::(HtBw=%d)\n", pAd->CommonCfg.RegTransmitSetting.field.BW)); - - return TRUE; -} - -INT Set_HtMcs_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG HtMcs, Mcs_tmp; - BOOLEAN bAutoRate = FALSE; - - Mcs_tmp = simple_strtol(arg, 0, 10); - - if (Mcs_tmp <= 15 || Mcs_tmp == 32) - HtMcs = Mcs_tmp; - else - HtMcs = MCS_AUTO; - - { - pAd->StaCfg.DesiredTransmitSetting.field.MCS = HtMcs; - pAd->StaCfg.bAutoTxRateSwitch = (HtMcs == MCS_AUTO) ? TRUE:FALSE; - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(HtMcs=%d, bAutoTxRateSwitch = %d)\n", - pAd->StaCfg.DesiredTransmitSetting.field.MCS, pAd->StaCfg.bAutoTxRateSwitch)); - - if ((pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) || - (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE < MODE_HTMIX)) - { - if ((pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) && - (HtMcs >= 0 && HtMcs <= 3) && - (pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_CCK)) - { - RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs] * 1000000)); - } - else if ((pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) && - (HtMcs >= 0 && HtMcs <= 7) && - (pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_OFDM)) - { - RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs+4] * 1000000)); - } - else - bAutoRate = TRUE; - - if (bAutoRate) - { - pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; - RTMPSetDesiredRates(pAd, -1); - } - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(FixedTxMode=%d)\n",pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode)); - } - if (ADHOC_ON(pAd)) - return TRUE; - } - - SetCommonHT(pAd); - - return TRUE; -} - -INT Set_HtGi_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG HtGi; - - HtGi = simple_strtol(arg, 0, 10); - - if ( HtGi == GI_400) - pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400; - else if ( HtGi == GI_800 ) - pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtGi_Proc::(ShortGI=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.ShortGI)); - - return TRUE; -} - - -INT Set_HtTxBASize_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - UCHAR Size; - - Size = simple_strtol(arg, 0, 10); - - if (Size <=0 || Size >=64) - { - Size = 8; - } - pAd->CommonCfg.TxBASize = Size-1; - DBGPRINT(RT_DEBUG_ERROR, ("Set_HtTxBASize ::(TxBASize= %d)\n", Size)); - - return TRUE; -} - - -INT Set_HtOpMode_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - if (Value == HTMODE_GF) - pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF; - else if ( Value == HTMODE_MM ) - pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtOpMode_Proc::(HtOpMode=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.HTMODE)); - - return TRUE; - -} - -INT Set_HtStbc_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - if (Value == STBC_USE) - pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE; - else if ( Value == STBC_NONE ) - pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_Stbc_Proc::(HtStbc=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.STBC)); - - return TRUE; -} - -INT Set_HtHtc_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - pAd->HTCEnable = FALSE; - else if ( Value ==1 ) - pAd->HTCEnable = TRUE; - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtHtc_Proc::(HtHtc=%d)\n",pAd->HTCEnable)); - - return TRUE; -} - -INT Set_HtExtcha_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - if (Value == 0) - pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; - else if ( Value ==1 ) - pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtExtcha_Proc::(HtExtcha=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.EXTCHA)); - - return TRUE; -} - -INT Set_HtMpduDensity_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - if (Value <=7 && Value >= 0) - pAd->CommonCfg.BACapability.field.MpduDensity = Value; - else - pAd->CommonCfg.BACapability.field.MpduDensity = 4; - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMpduDensity_Proc::(HtMpduDensity=%d)\n",pAd->CommonCfg.BACapability.field.MpduDensity)); - - return TRUE; -} - -INT Set_HtBaWinSize_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - - if (Value >=1 && Value <= 64) - { - pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value; - pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value; - } - else - { - pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64; - pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; - } - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBaWinSize_Proc::(HtBaWinSize=%d)\n",pAd->CommonCfg.BACapability.field.RxBAWinLimit)); - - return TRUE; -} - -INT Set_HtRdg_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - if (Value == 0) - pAd->CommonCfg.bRdg = FALSE; - else if ( Value ==1 ) - { - pAd->HTCEnable = TRUE; - pAd->CommonCfg.bRdg = TRUE; - } - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtRdg_Proc::(HtRdg=%d)\n",pAd->CommonCfg.bRdg)); - - return TRUE; -} - -INT Set_HtLinkAdapt_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - pAd->bLinkAdapt = FALSE; - else if ( Value ==1 ) - { - pAd->HTCEnable = TRUE; - pAd->bLinkAdapt = TRUE; - } - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtLinkAdapt_Proc::(HtLinkAdapt=%d)\n",pAd->bLinkAdapt)); - - return TRUE; -} - -INT Set_HtAmsdu_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE; - else if ( Value == 1 ) - pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAmsdu_Proc::(HtAmsdu=%d)\n",pAd->CommonCfg.BACapability.field.AmsduEnable)); - - return TRUE; -} - -INT Set_HtAutoBa_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.BACapability.field.AutoBA = FALSE; - pAd->CommonCfg.BACapability.field.Policy = BA_NOTUSE; - } - else if (Value == 1) - { - pAd->CommonCfg.BACapability.field.AutoBA = TRUE; - pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; - } - else - return FALSE; //Invalid argument - - pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA; - pAd->CommonCfg.REGBACapability.field.Policy = pAd->CommonCfg.BACapability.field.Policy; - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAutoBa_Proc::(HtAutoBa=%d)\n",pAd->CommonCfg.BACapability.field.AutoBA)); - - return TRUE; - -} - -INT Set_HtProtect_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - pAd->CommonCfg.bHTProtect = FALSE; - else if (Value == 1) - pAd->CommonCfg.bHTProtect = TRUE; - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtProtect_Proc::(HtProtect=%d)\n",pAd->CommonCfg.bHTProtect)); - - return TRUE; -} - -INT Set_SendPSMPAction_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - UCHAR mac[6], mode; - char *token, sepValue[] = ":", DASH = '-'; - INT i; - MAC_TABLE_ENTRY *pEntry; - - //printk("\n%s\n", arg); -/* - The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, - =>The six 2 digit hex-decimal number previous are the Mac address, - =>The seventh decimal number is the mode value. -*/ - if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and mode value in decimal format. - return FALSE; - - token = strchr(arg, DASH); - if ((token != NULL) && (strlen(token)>1)) - { - mode = simple_strtol((token+1), 0, 10); - if (mode > MMPS_ENABLE) - return FALSE; - - *token = '\0'; - for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) - { - if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) - return FALSE; - AtoH(token, (PUCHAR)(&mac[i]), 1); - } - if(i != 6) - return FALSE; - - printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1], - mac[2], mac[3], mac[4], mac[5], mode); - - pEntry = MacTableLookup(pAd, mac); - - if (pEntry) { - printk("\nSendPSMPAction MIPS mode = %d\n", mode); - SendPSMPAction(pAd, pEntry->Aid, mode); - } - - return TRUE; - } - - return FALSE; - - -} - -INT Set_HtMIMOPSmode_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - if (Value <=3 && Value >= 0) - pAd->CommonCfg.BACapability.field.MMPSmode = Value; - else - pAd->CommonCfg.BACapability.field.MMPSmode = 3; - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMIMOPSmode_Proc::(MIMOPS mode=%d)\n",pAd->CommonCfg.BACapability.field.MMPSmode)); - - return TRUE; -} - - -INT Set_ForceShortGI_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - pAd->WIFItestbed.bShortGI = FALSE; - else if (Value == 1) - pAd->WIFItestbed.bShortGI = TRUE; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceShortGI_Proc::(ForceShortGI=%d)\n", pAd->WIFItestbed.bShortGI)); - - return TRUE; -} - - - -INT Set_ForceGF_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - pAd->WIFItestbed.bGreenField = FALSE; - else if (Value == 1) - pAd->WIFItestbed.bGreenField = TRUE; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceGF_Proc::(ForceGF=%d)\n", pAd->WIFItestbed.bGreenField)); - - return TRUE; -} - -INT Set_HtMimoPs_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - pAd->CommonCfg.bMIMOPSEnable = FALSE; - else if (Value == 1) - pAd->CommonCfg.bMIMOPSEnable = TRUE; - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMimoPs_Proc::(HtMimoPs=%d)\n",pAd->CommonCfg.bMIMOPSEnable)); - - return TRUE; -} - -INT SetCommonHT( - IN PRTMP_ADAPTER pAd) -{ - OID_SET_HT_PHYMODE SetHT; - - if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) - return FALSE; - - SetHT.PhyMode = pAd->CommonCfg.PhyMode; - SetHT.TransmitNo = ((UCHAR)pAd->Antenna.field.TxPath); - SetHT.HtMode = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.HTMODE; - SetHT.ExtOffset = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; - SetHT.MCS = MCS_AUTO; - SetHT.BW = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.BW; - SetHT.STBC = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.STBC; - SetHT.SHORTGI = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.ShortGI; - - RTMPSetHT(pAd, &SetHT); - - return TRUE; -} - -INT Set_FixedTxMode_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - UCHAR fix_tx_mode = FIXED_TXMODE_HT; - - if (strcmp(arg, "OFDM") == 0 || strcmp(arg, "ofdm") == 0) - { - fix_tx_mode = FIXED_TXMODE_OFDM; - } - else if (strcmp(arg, "CCK") == 0 || strcmp(arg, "cck") == 0) - { - fix_tx_mode = FIXED_TXMODE_CCK; - } - - pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode; - - DBGPRINT(RT_DEBUG_TRACE, ("Set_FixedTxMode_Proc::(FixedTxMode=%d)\n", fix_tx_mode)); - - return TRUE; -} - -///////////////////////////////////////////////////////////////////////// -PCHAR RTMPGetRalinkAuthModeStr( - IN NDIS_802_11_AUTHENTICATION_MODE authMode) -{ - switch(authMode) - { - case Ndis802_11AuthModeOpen: - return "OPEN"; - case Ndis802_11AuthModeWPAPSK: - return "WPAPSK"; - case Ndis802_11AuthModeShared: - return "SHARED"; - case Ndis802_11AuthModeWPA: - return "WPA"; - case Ndis802_11AuthModeWPA2: - return "WPA2"; - case Ndis802_11AuthModeWPA2PSK: - return "WPA2PSK"; - case Ndis802_11AuthModeWPA1PSKWPA2PSK: - return "WPAPSKWPA2PSK"; - case Ndis802_11AuthModeWPA1WPA2: - return "WPA1WPA2"; - case Ndis802_11AuthModeWPANone: - return "WPANONE"; - default: - return "UNKNOW"; - } -} - -PCHAR RTMPGetRalinkEncryModeStr( - IN USHORT encryMode) -{ - switch(encryMode) - { -#if defined(RT2860) || defined(RT30xx) - default: -#endif - case Ndis802_11WEPDisabled: - return "NONE"; - case Ndis802_11WEPEnabled: - return "WEP"; - case Ndis802_11Encryption2Enabled: - return "TKIP"; - case Ndis802_11Encryption3Enabled: - return "AES"; - case Ndis802_11Encryption4Enabled: - return "TKIPAES"; -#if !defined(RT2860) && !defined(RT30xx) - default: - return "UNKNOW"; -#endif - } -} - -INT RTMPShowCfgValue( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pName, - IN PUCHAR pBuf) -{ - INT Status = 0; - - for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++) - { - if (!strcmp(pName, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name)) - { - if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->show_proc(pAd, pBuf)) - Status = -EINVAL; - break; //Exit for loop. - } - } - - if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name == NULL) - { - sprintf(pBuf, "\n"); - for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++) - sprintf(pBuf + strlen(pBuf), "%s\n", PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name); - } - - return Status; -} - -INT Show_SSID_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.Ssid); - return 0; -} - -INT Show_WirelessMode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - switch(pAd->CommonCfg.PhyMode) - { - case PHY_11BG_MIXED: - sprintf(pBuf, "\t11B/G"); - break; - case PHY_11B: - sprintf(pBuf, "\t11B"); - break; - case PHY_11A: - sprintf(pBuf, "\t11A"); - break; - case PHY_11ABG_MIXED: - sprintf(pBuf, "\t11A/B/G"); - break; - case PHY_11G: - sprintf(pBuf, "\t11G"); - break; - case PHY_11ABGN_MIXED: - sprintf(pBuf, "\t11A/B/G/N"); - break; - case PHY_11N_2_4G: - sprintf(pBuf, "\t11N only with 2.4G"); - break; - case PHY_11GN_MIXED: - sprintf(pBuf, "\t11G/N"); - break; - case PHY_11AN_MIXED: - sprintf(pBuf, "\t11A/N"); - break; - case PHY_11BGN_MIXED: - sprintf(pBuf, "\t11B/G/N"); - break; - case PHY_11AGN_MIXED: - sprintf(pBuf, "\t11A/G/N"); - break; - case PHY_11N_5G: - sprintf(pBuf, "\t11N only with 5G"); - break; - default: - sprintf(pBuf, "\tUnknow Value(%d)", pAd->CommonCfg.PhyMode); - break; - } - return 0; -} - - -INT Show_TxBurst_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.bEnableTxBurst ? "TRUE":"FALSE"); - return 0; -} - -INT Show_TxPreamble_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - switch(pAd->CommonCfg.TxPreamble) - { - case Rt802_11PreambleShort: - sprintf(pBuf, "\tShort"); - break; - case Rt802_11PreambleLong: - sprintf(pBuf, "\tLong"); - break; - case Rt802_11PreambleAuto: - sprintf(pBuf, "\tAuto"); - break; - default: - sprintf(pBuf, "\tUnknow Value(%lu)", pAd->CommonCfg.TxPreamble); - break; - } - - return 0; -} - -INT Show_TxPower_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%lu", pAd->CommonCfg.TxPowerPercentage); - return 0; -} - -INT Show_Channel_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%d", pAd->CommonCfg.Channel); - return 0; -} - -INT Show_BGProtection_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - switch(pAd->CommonCfg.UseBGProtection) - { - case 1: //Always On - sprintf(pBuf, "\tON"); - break; - case 2: //Always OFF - sprintf(pBuf, "\tOFF"); - break; - case 0: //AUTO - sprintf(pBuf, "\tAuto"); - break; - default: - sprintf(pBuf, "\tUnknow Value(%lu)", pAd->CommonCfg.UseBGProtection); - break; - } - return 0; -} - -INT Show_RTSThreshold_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%u", pAd->CommonCfg.RtsThreshold); - return 0; -} - -INT Show_FragThreshold_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%u", pAd->CommonCfg.FragmentThreshold); - return 0; -} - -INT Show_HtBw_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) - { - sprintf(pBuf, "\t40 MHz"); - } - else - { - sprintf(pBuf, "\t20 MHz"); - } - return 0; -} - -INT Show_HtMcs_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%u", pAd->StaCfg.DesiredTransmitSetting.field.MCS); - return 0; -} - -INT Show_HtGi_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - switch(pAd->CommonCfg.RegTransmitSetting.field.ShortGI) - { - case GI_400: - sprintf(pBuf, "\tGI_400"); - break; - case GI_800: - sprintf(pBuf, "\tGI_800"); - break; - default: - sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.ShortGI); - break; - } - return 0; -} - -INT Show_HtOpMode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - switch(pAd->CommonCfg.RegTransmitSetting.field.HTMODE) - { - case HTMODE_GF: - sprintf(pBuf, "\tGF"); - break; - case HTMODE_MM: - sprintf(pBuf, "\tMM"); - break; - default: - sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.HTMODE); - break; - } - return 0; -} - -INT Show_HtExtcha_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - switch(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA) - { - case EXTCHA_BELOW: - sprintf(pBuf, "\tBelow"); - break; - case EXTCHA_ABOVE: - sprintf(pBuf, "\tAbove"); - break; - default: - sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.EXTCHA); - break; - } - return 0; -} - - -INT Show_HtMpduDensity_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%u", pAd->CommonCfg.BACapability.field.MpduDensity); - return 0; -} - -INT Show_HtBaWinSize_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%u", pAd->CommonCfg.BACapability.field.RxBAWinLimit); - return 0; -} - -INT Show_HtRdg_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.bRdg ? "TRUE":"FALSE"); - return 0; -} - -INT Show_HtAmsdu_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.BACapability.field.AmsduEnable ? "TRUE":"FALSE"); - return 0; -} - -INT Show_HtAutoBa_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.BACapability.field.AutoBA ? "TRUE":"FALSE"); - return 0; -} - -INT Show_CountryRegion_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%d", pAd->CommonCfg.CountryRegion); - return 0; -} - -INT Show_CountryRegionABand_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%d", pAd->CommonCfg.CountryRegionForABand); - return 0; -} - -INT Show_CountryCode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.CountryCode); - return 0; -} - -#ifdef AGGREGATION_SUPPORT -INT Show_PktAggregate_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.bAggregationCapable ? "TRUE":"FALSE"); - return 0; -} -#endif // AGGREGATION_SUPPORT // - -#ifdef WMM_SUPPORT -INT Show_WmmCapable_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.bWmmCapable ? "TRUE":"FALSE"); - - return 0; -} -#endif // WMM_SUPPORT // - -INT Show_IEEE80211H_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.bIEEE80211H ? "TRUE":"FALSE"); - return 0; -} - -INT Show_NetworkType_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - switch(pAd->StaCfg.BssType) - { - case BSS_ADHOC: - sprintf(pBuf, "\tAdhoc"); - break; - case BSS_INFRA: - sprintf(pBuf, "\tInfra"); - break; - case BSS_ANY: - sprintf(pBuf, "\tAny"); - break; - case BSS_MONITOR: - sprintf(pBuf, "\tMonitor"); - break; - default: - sprintf(pBuf, "\tUnknow Value(%d)", pAd->StaCfg.BssType); - break; - } - return 0; -} - -INT Show_AuthMode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeOpen; - - AuthMode = pAd->StaCfg.AuthMode; - - if ((AuthMode >= Ndis802_11AuthModeOpen) && - (AuthMode <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) - sprintf(pBuf, "\t%s", RTMPGetRalinkAuthModeStr(AuthMode)); - else - sprintf(pBuf, "\tUnknow Value(%d)", AuthMode); - - return 0; -} - -INT Show_EncrypType_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - NDIS_802_11_WEP_STATUS WepStatus = Ndis802_11WEPDisabled; - - WepStatus = pAd->StaCfg.WepStatus; - - if ((WepStatus >= Ndis802_11WEPEnabled) && - (WepStatus <= Ndis802_11Encryption4KeyAbsent)) - sprintf(pBuf, "\t%s", RTMPGetRalinkEncryModeStr(WepStatus)); - else - sprintf(pBuf, "\tUnknow Value(%d)", WepStatus); - - return 0; -} - -INT Show_DefaultKeyID_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - UCHAR DefaultKeyId = 0; - - DefaultKeyId = pAd->StaCfg.DefaultKeyId; - - sprintf(pBuf, "\t%d", DefaultKeyId); - - return 0; -} - -INT Show_WepKey_Proc( - IN PRTMP_ADAPTER pAd, - IN INT KeyIdx, - OUT PUCHAR pBuf) -{ - UCHAR Key[16] = {0}, KeyLength = 0; - INT index = BSS0; - - KeyLength = pAd->SharedKey[index][KeyIdx].KeyLen; - NdisMoveMemory(Key, pAd->SharedKey[index][KeyIdx].Key, KeyLength); - - //check key string is ASCII or not - if (RTMPCheckStrPrintAble(Key, KeyLength)) - sprintf(pBuf, "\t%s", Key); - else - { - int idx; - sprintf(pBuf, "\t"); - for (idx = 0; idx < KeyLength; idx++) - sprintf(pBuf+strlen(pBuf), "%02X", Key[idx]); - } - return 0; -} - -INT Show_Key1_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - Show_WepKey_Proc(pAd, 0, pBuf); - return 0; -} - -INT Show_Key2_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - Show_WepKey_Proc(pAd, 1, pBuf); - return 0; -} - -INT Show_Key3_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - Show_WepKey_Proc(pAd, 2, pBuf); - return 0; -} - -INT Show_Key4_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - Show_WepKey_Proc(pAd, 3, pBuf); - return 0; -} - -INT Show_WPAPSK_Proc( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf) -{ - INT idx; - UCHAR PMK[32] = {0}; - - NdisMoveMemory(PMK, pAd->StaCfg.PMK, 32); - - sprintf(pBuf, "\tPMK = "); - for (idx = 0; idx < 32; idx++) - sprintf(pBuf+strlen(pBuf), "%02X", PMK[idx]); - - return 0; -} - diff --git a/drivers/staging/rt2860/common/cmm_mac_pci.c b/drivers/staging/rt2860/common/cmm_mac_pci.c new file mode 100644 index 0000000000000000000000000000000000000000..560ebd398e1d558f2fc9efe01595179ab8ea4c1c --- /dev/null +++ b/drivers/staging/rt2860/common/cmm_mac_pci.c @@ -0,0 +1,1661 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* +*/ + +#ifdef RTMP_MAC_PCI +#include "../rt_config.h" + +/* + ======================================================================== + + Routine Description: + Allocate DMA memory blocks for send, receive + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + NDIS_STATUS_RESOURCES + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +int RTMPAllocTxRxRingMemory(struct rt_rtmp_adapter *pAd) +{ + int Status = NDIS_STATUS_SUCCESS; + unsigned long RingBasePaHigh; + unsigned long RingBasePaLow; + void *RingBaseVa; + int index, num; + struct rt_txd * pTxD; + struct rt_rxd * pRxD; + unsigned long ErrorValue = 0; + struct rt_rtmp_tx_ring *pTxRing; + struct rt_rtmp_dmabuf *pDmaBuf; + void *pPacket; +/* PRTMP_REORDERBUF pReorderBuf; */ + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); + do { + /* */ + /* Allocate all ring descriptors, include TxD, RxD, MgmtD. */ + /* Although each size is different, to prevent cacheline and alignment */ + /* issue, I intentional set them all to 64 bytes. */ + /* */ + for (num = 0; num < NUM_OF_TX_RING; num++) { + unsigned long BufBasePaHigh; + unsigned long BufBasePaLow; + void *BufBaseVa; + + /* */ + /* Allocate Tx ring descriptor's memory (5 TX rings = 4 ACs + 1 HCCA) */ + /* */ + pAd->TxDescRing[num].AllocSize = + TX_RING_SIZE * TXD_SIZE; + RTMP_AllocateTxDescMemory(pAd, num, + pAd->TxDescRing[num]. + AllocSize, FALSE, + &pAd->TxDescRing[num].AllocVa, + &pAd->TxDescRing[num]. + AllocPa); + + if (pAd->TxDescRing[num].AllocVa == NULL) { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + /* Zero init this memory block */ + NdisZeroMemory(pAd->TxDescRing[num].AllocVa, + pAd->TxDescRing[num].AllocSize); + + /* Save PA & VA for further operation */ + RingBasePaHigh = + RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num]. + AllocPa); + RingBasePaLow = + RTMP_GetPhysicalAddressLow(pAd->TxDescRing[num]. + AllocPa); + RingBaseVa = pAd->TxDescRing[num].AllocVa; + + /* */ + /* Allocate all 1st TXBuf's memory for this TxRing */ + /* */ + pAd->TxBufSpace[num].AllocSize = + TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE; + RTMP_AllocateFirstTxBuffer(pAd, num, + pAd->TxBufSpace[num]. + AllocSize, FALSE, + &pAd->TxBufSpace[num]. + AllocVa, + &pAd->TxBufSpace[num]. + AllocPa); + + if (pAd->TxBufSpace[num].AllocVa == NULL) { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + /* Zero init this memory block */ + NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, + pAd->TxBufSpace[num].AllocSize); + + /* Save PA & VA for further operation */ + BufBasePaHigh = + RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num]. + AllocPa); + BufBasePaLow = + RTMP_GetPhysicalAddressLow(pAd->TxBufSpace[num]. + AllocPa); + BufBaseVa = pAd->TxBufSpace[num].AllocVa; + + /* */ + /* Initialize Tx Ring Descriptor and associated buffer memory */ + /* */ + pTxRing = &pAd->TxRing[num]; + for (index = 0; index < TX_RING_SIZE; index++) { + pTxRing->Cell[index].pNdisPacket = NULL; + pTxRing->Cell[index].pNextNdisPacket = NULL; + /* Init Tx Ring Size, Va, Pa variables */ + pTxRing->Cell[index].AllocSize = TXD_SIZE; + pTxRing->Cell[index].AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(pTxRing-> + Cell[index].AllocPa, + RingBasePaHigh); + RTMP_SetPhysicalAddressLow(pTxRing->Cell[index]. + AllocPa, + RingBasePaLow); + + /* Setup Tx Buffer size & address. only 802.11 header will store in this space */ + pDmaBuf = &pTxRing->Cell[index].DmaBuf; + pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; + pDmaBuf->AllocVa = BufBaseVa; + RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, + BufBasePaHigh); + RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, + BufBasePaLow); + + /* link the pre-allocated TxBuf to TXD */ + pTxD = + (struct rt_txd *) pTxRing->Cell[index].AllocVa; + pTxD->SDPtr0 = BufBasePaLow; + /* advance to next ring descriptor address */ + pTxD->DMADONE = 1; + RingBasePaLow += TXD_SIZE; + RingBaseVa = (u8 *)RingBaseVa + TXD_SIZE; + + /* advance to next TxBuf address */ + BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE; + BufBaseVa = + (u8 *)BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; + } + DBGPRINT(RT_DEBUG_TRACE, + ("TxRing[%d]: total %d entry allocated\n", num, + index)); + } + if (Status == NDIS_STATUS_RESOURCES) + break; + + /* */ + /* Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler */ + /* */ + pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE; + RTMP_AllocateMgmtDescMemory(pAd, + pAd->MgmtDescRing.AllocSize, + FALSE, + &pAd->MgmtDescRing.AllocVa, + &pAd->MgmtDescRing.AllocPa); + + if (pAd->MgmtDescRing.AllocVa == NULL) { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + /* Zero init this memory block */ + NdisZeroMemory(pAd->MgmtDescRing.AllocVa, + pAd->MgmtDescRing.AllocSize); + + /* Save PA & VA for further operation */ + RingBasePaHigh = + RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa); + RingBasePaLow = + RTMP_GetPhysicalAddressLow(pAd->MgmtDescRing.AllocPa); + RingBaseVa = pAd->MgmtDescRing.AllocVa; + + /* */ + /* Initialize MGMT Ring and associated buffer memory */ + /* */ + for (index = 0; index < MGMT_RING_SIZE; index++) { + pAd->MgmtRing.Cell[index].pNdisPacket = NULL; + pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL; + /* Init MGMT Ring Size, Va, Pa variables */ + pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE; + pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index]. + AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow(pAd->MgmtRing.Cell[index]. + AllocPa, RingBasePaLow); + + /* Offset to next ring descriptor address */ + RingBasePaLow += TXD_SIZE; + RingBaseVa = (u8 *)RingBaseVa + TXD_SIZE; + + /* link the pre-allocated TxBuf to TXD */ + pTxD = (struct rt_txd *) pAd->MgmtRing.Cell[index].AllocVa; + pTxD->DMADONE = 1; + + /* no pre-allocated buffer required in MgmtRing for scatter-gather case */ + } + DBGPRINT(RT_DEBUG_TRACE, + ("MGMT Ring: total %d entry allocated\n", index)); + + /* */ + /* Allocate RX ring descriptor's memory except Tx ring which allocated eariler */ + /* */ + pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE; + RTMP_AllocateRxDescMemory(pAd, + pAd->RxDescRing.AllocSize, + FALSE, + &pAd->RxDescRing.AllocVa, + &pAd->RxDescRing.AllocPa); + + if (pAd->RxDescRing.AllocVa == NULL) { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + /* Zero init this memory block */ + NdisZeroMemory(pAd->RxDescRing.AllocVa, + pAd->RxDescRing.AllocSize); + + DBGPRINT(RT_DEBUG_OFF, + ("RX DESC %p size = %ld\n", pAd->RxDescRing.AllocVa, + pAd->RxDescRing.AllocSize)); + + /* Save PA & VA for further operation */ + RingBasePaHigh = + RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa); + RingBasePaLow = + RTMP_GetPhysicalAddressLow(pAd->RxDescRing.AllocPa); + RingBaseVa = pAd->RxDescRing.AllocVa; + + /* */ + /* Initialize Rx Ring and associated buffer memory */ + /* */ + for (index = 0; index < RX_RING_SIZE; index++) { + /* Init RX Ring Size, Va, Pa variables */ + pAd->RxRing.Cell[index].AllocSize = RXD_SIZE; + pAd->RxRing.Cell[index].AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index]. + AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow(pAd->RxRing.Cell[index]. + AllocPa, RingBasePaLow); + + /*NdisZeroMemory(RingBaseVa, RXD_SIZE); */ + + /* Offset to next ring descriptor address */ + RingBasePaLow += RXD_SIZE; + RingBaseVa = (u8 *)RingBaseVa + RXD_SIZE; + + /* Setup Rx associated Buffer size & allocate share memory */ + pDmaBuf = &pAd->RxRing.Cell[index].DmaBuf; + pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE; + pPacket = RTMP_AllocateRxPacketBuffer(pAd, + pDmaBuf-> + AllocSize, FALSE, + &pDmaBuf->AllocVa, + &pDmaBuf-> + AllocPa); + + /* keep allocated rx packet */ + pAd->RxRing.Cell[index].pNdisPacket = pPacket; + + /* Error handling */ + if (pDmaBuf->AllocVa == NULL) { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + /* Zero init this memory block */ + NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize); + + /* Write RxD buffer address & allocated buffer length */ + pRxD = (struct rt_rxd *) pAd->RxRing.Cell[index].AllocVa; + pRxD->SDP0 = + RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); + pRxD->DDONE = 0; + + } + + DBGPRINT(RT_DEBUG_TRACE, + ("Rx Ring: total %d entry allocated\n", index)); + + } while (FALSE); + + NdisZeroMemory(&pAd->FragFrame, sizeof(struct rt_fragment_frame)); + pAd->FragFrame.pFragPacket = + RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); + + if (pAd->FragFrame.pFragPacket == NULL) { + Status = NDIS_STATUS_RESOURCES; + } + + if (Status != NDIS_STATUS_SUCCESS) { + /* Log error inforamtion */ + NdisWriteErrorLogEntry(pAd->AdapterHandle, + NDIS_ERROR_CODE_OUT_OF_RESOURCES, + 1, ErrorValue); + } + /* Following code segment get from original func:NICInitTxRxRingAndBacklogQueue(), now should integrate it to here. */ + { + DBGPRINT(RT_DEBUG_TRACE, + ("--> NICInitTxRxRingAndBacklogQueue\n")); + +/* + // Disable DMA. + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + GloCfg.word &= 0xff0; + GloCfg.field.EnTXWriteBackDDONE =1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); +*/ + + /* Initialize all transmit related software queues */ + for (index = 0; index < NUM_OF_TX_RING; index++) { + InitializeQueueHeader(&pAd->TxSwQueue[index]); + /* Init TX rings index pointer */ + pAd->TxRing[index].TxSwFreeIdx = 0; + pAd->TxRing[index].TxCpuIdx = 0; + /*RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10) , pAd->TxRing[i].TX_CTX_IDX); */ + } + + /* Init RX Ring index pointer */ + pAd->RxRing.RxSwReadIdx = 0; + pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1; + /*RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RX_CRX_IDX0); */ + + /* init MGMT ring index pointer */ + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + + pAd->PrivateInfo.TxRingFullCnt = 0; + + DBGPRINT(RT_DEBUG_TRACE, + ("<-- NICInitTxRxRingAndBacklogQueue\n")); + } + + DBGPRINT_S(Status, + ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); + return Status; +} + +/* + ======================================================================== + + Routine Description: + Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero. + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + Reset NIC to initial state AS IS system boot up time. + + ======================================================================== +*/ +void RTMPRingCleanUp(struct rt_rtmp_adapter *pAd, u8 RingType) +{ + struct rt_txd * pTxD; + struct rt_rxd * pRxD; + struct rt_queue_entry *pEntry; + void *pPacket; + int i; + struct rt_rtmp_tx_ring *pTxRing; + unsigned long IrqFlags; + /*u32 RxSwReadIdx; */ + + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, + pAd->RalinkCounters.PendingNdisPacketCount)); + switch (RingType) { + case QID_AC_BK: + case QID_AC_BE: + case QID_AC_VI: + case QID_AC_VO: + + pTxRing = &pAd->TxRing[RingType]; + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + /* We have to clean all descriptors in case some error happened with reset */ + for (i = 0; i < TX_RING_SIZE; i++) /* We have to scan all TX ring */ + { + pTxD = (struct rt_txd *) pTxRing->Cell[i].AllocVa; + + pPacket = (void *)pTxRing->Cell[i].pNdisPacket; + /* release scatter-and-gather char */ + if (pPacket) { + RELEASE_NDIS_PACKET(pAd, pPacket, + NDIS_STATUS_FAILURE); + pTxRing->Cell[i].pNdisPacket = NULL; + } + + pPacket = + (void *)pTxRing->Cell[i].pNextNdisPacket; + /* release scatter-and-gather char */ + if (pPacket) { + RELEASE_NDIS_PACKET(pAd, pPacket, + NDIS_STATUS_FAILURE); + pTxRing->Cell[i].pNextNdisPacket = NULL; + } + } + + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + RingType * 0x10, + &pTxRing->TxDmaIdx); + pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; + pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + RingType * 0x10, + pTxRing->TxCpuIdx); + + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + while (pAd->TxSwQueue[RingType].Head != NULL) { + pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + DBGPRINT(RT_DEBUG_TRACE, + ("Release 1 NDIS packet from s/w backlog queue\n")); + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + break; + + case QID_MGMT: + /* We have to clean all descriptors in case some error happened with reset */ + NdisAcquireSpinLock(&pAd->MgmtRingLock); + + for (i = 0; i < MGMT_RING_SIZE; i++) { + pTxD = (struct rt_txd *) pAd->MgmtRing.Cell[i].AllocVa; + + pPacket = + (void *)pAd->MgmtRing.Cell[i].pNdisPacket; + /* rlease scatter-and-gather char */ + if (pPacket) { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, + pTxD->SDLen0, + PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, + NDIS_STATUS_FAILURE); + } + pAd->MgmtRing.Cell[i].pNdisPacket = NULL; + + pPacket = + (void *)pAd->MgmtRing.Cell[i]. + pNextNdisPacket; + /* release scatter-and-gather char */ + if (pPacket) { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, + pTxD->SDLen1, + PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, + NDIS_STATUS_FAILURE); + } + pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL; + + } + + RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pAd->MgmtRing.TxDmaIdx); + pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx; + pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx; + RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); + + NdisReleaseSpinLock(&pAd->MgmtRingLock); + pAd->RalinkCounters.MgmtRingFullCount = 0; + break; + + case QID_RX: + /* We have to clean all descriptors in case some error happened with reset */ + NdisAcquireSpinLock(&pAd->RxRingLock); + + for (i = 0; i < RX_RING_SIZE; i++) { + pRxD = (struct rt_rxd *) pAd->RxRing.Cell[i].AllocVa; + pRxD->DDONE = 0; + } + + RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx); + pAd->RxRing.RxSwReadIdx = pAd->RxRing.RxDmaIdx; + pAd->RxRing.RxCpuIdx = + ((pAd->RxRing.RxDmaIdx == + 0) ? (RX_RING_SIZE - 1) : (pAd->RxRing.RxDmaIdx - 1)); + RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); + + NdisReleaseSpinLock(&pAd->RxRingLock); + break; + + default: + break; + } +} + +void RTMPFreeTxRxRingMemory(struct rt_rtmp_adapter *pAd) +{ + int index, num, j; + struct rt_rtmp_tx_ring *pTxRing; + struct rt_txd * pTxD; + void *pPacket; + unsigned int IrqFlags; + + /*struct os_cookie *pObj =(struct os_cookie *)pAd->OS_Cookie; */ + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n")); + + /* Free TxSwQueue Packet */ + for (index = 0; index < NUM_OF_TX_RING; index++) { + struct rt_queue_entry *pEntry; + void *pPacket; + struct rt_queue_header *pQueue; + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + pQueue = &pAd->TxSwQueue[index]; + while (pQueue->Head) { + pEntry = RemoveHeadQueue(pQueue); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + } + + /* Free Tx Ring Packet */ + for (index = 0; index < NUM_OF_TX_RING; index++) { + pTxRing = &pAd->TxRing[index]; + + for (j = 0; j < TX_RING_SIZE; j++) { + pTxD = (struct rt_txd *) (pTxRing->Cell[j].AllocVa); + pPacket = pTxRing->Cell[j].pNdisPacket; + + if (pPacket) { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, + pTxD->SDLen0, + PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, + NDIS_STATUS_SUCCESS); + } + /*Always assign pNdisPacket as NULL after clear */ + pTxRing->Cell[j].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[j].pNextNdisPacket; + + if (pPacket) { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, + pTxD->SDLen1, + PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, + NDIS_STATUS_SUCCESS); + } + /*Always assign pNextNdisPacket as NULL after clear */ + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = + NULL; + + } + } + + for (index = RX_RING_SIZE - 1; index >= 0; index--) { + if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) + && (pAd->RxRing.Cell[index].pNdisPacket)) { + PCI_UNMAP_SINGLE(pAd, + pAd->RxRing.Cell[index].DmaBuf.AllocPa, + pAd->RxRing.Cell[index].DmaBuf. + AllocSize, PCI_DMA_FROMDEVICE); + RELEASE_NDIS_PACKET(pAd, + pAd->RxRing.Cell[index].pNdisPacket, + NDIS_STATUS_SUCCESS); + } + } + NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(struct rt_rtmp_dmacb)); + + if (pAd->RxDescRing.AllocVa) { + RTMP_FreeDescMemory(pAd, pAd->RxDescRing.AllocSize, + pAd->RxDescRing.AllocVa, + pAd->RxDescRing.AllocPa); + } + NdisZeroMemory(&pAd->RxDescRing, sizeof(struct rt_rtmp_dmabuf)); + + if (pAd->MgmtDescRing.AllocVa) { + RTMP_FreeDescMemory(pAd, pAd->MgmtDescRing.AllocSize, + pAd->MgmtDescRing.AllocVa, + pAd->MgmtDescRing.AllocPa); + } + NdisZeroMemory(&pAd->MgmtDescRing, sizeof(struct rt_rtmp_dmabuf)); + + for (num = 0; num < NUM_OF_TX_RING; num++) { + if (pAd->TxBufSpace[num].AllocVa) { + RTMP_FreeFirstTxBuffer(pAd, + pAd->TxBufSpace[num].AllocSize, + FALSE, + pAd->TxBufSpace[num].AllocVa, + pAd->TxBufSpace[num].AllocPa); + } + NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(struct rt_rtmp_dmabuf)); + + if (pAd->TxDescRing[num].AllocVa) { + RTMP_FreeDescMemory(pAd, pAd->TxDescRing[num].AllocSize, + pAd->TxDescRing[num].AllocVa, + pAd->TxDescRing[num].AllocPa); + } + NdisZeroMemory(&pAd->TxDescRing[num], sizeof(struct rt_rtmp_dmabuf)); + } + + if (pAd->FragFrame.pFragPacket) + RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, + NDIS_STATUS_SUCCESS); + + DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n")); +} + +/*************************************************************************** + * + * register related procedures. + * + **************************************************************************/ +/* +======================================================================== +Routine Description: + Disable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +void RT28XXDMADisable(struct rt_rtmp_adapter *pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + GloCfg.word &= 0xff0; + GloCfg.field.EnTXWriteBackDDONE = 1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); +} + +/* +======================================================================== +Routine Description: + Enable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +void RT28XXDMAEnable(struct rt_rtmp_adapter *pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + int i = 0; + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4); + do { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) + && (GloCfg.field.RxDMABusy == 0)) + break; + + DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n")); + RTMPusecDelay(1000); + i++; + } while (i < 200); + + RTMPusecDelay(50); + + GloCfg.field.EnTXWriteBackDDONE = 1; + GloCfg.field.WPDMABurstSIZE = 2; + GloCfg.field.EnableRxDMA = 1; + GloCfg.field.EnableTxDMA = 1; + + DBGPRINT(RT_DEBUG_TRACE, + ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word)); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + +} + +BOOLEAN AsicCheckCommanOk(struct rt_rtmp_adapter *pAd, u8 Command) +{ + u32 CmdStatus = 0, CID = 0, i; + u32 ThisCIDMask = 0; + + i = 0; + do { + RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID); + /* Find where the command is. Because this is randomly specified by firmware. */ + if ((CID & CID0MASK) == Command) { + ThisCIDMask = CID0MASK; + break; + } else if ((((CID & CID1MASK) >> 8) & 0xff) == Command) { + ThisCIDMask = CID1MASK; + break; + } else if ((((CID & CID2MASK) >> 16) & 0xff) == Command) { + ThisCIDMask = CID2MASK; + break; + } else if ((((CID & CID3MASK) >> 24) & 0xff) == Command) { + ThisCIDMask = CID3MASK; + break; + } + + RTMPusecDelay(100); + i++; + } while (i < 200); + + /* Get CommandStatus Value */ + RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus); + + /* This command's status is at the same position as command. So AND command position's bitmask to read status. */ + if (i < 200) { + /* If Status is 1, the comamnd is success. */ + if (((CmdStatus & ThisCIDMask) == 0x1) + || ((CmdStatus & ThisCIDMask) == 0x100) + || ((CmdStatus & ThisCIDMask) == 0x10000) + || ((CmdStatus & ThisCIDMask) == 0x1000000)) { + DBGPRINT(RT_DEBUG_TRACE, + ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", + CID, CmdStatus)); + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); + return TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, + ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", + CID, CmdStatus)); + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", + Command, CmdStatus)); + } + /* Clear Command and Status. */ + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); + + return FALSE; +} + +/* +======================================================================== +Routine Description: + Write Beacon buffer to Asic. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +void RT28xx_UpdateBeaconToAsic(struct rt_rtmp_adapter *pAd, + int apidx, + unsigned long FrameLen, unsigned long UpdatePos) +{ + unsigned long CapInfoPos = 0; + u8 *ptr, *ptr_update, *ptr_capinfo; + u32 i; + BOOLEAN bBcnReq = FALSE; + u8 bcn_idx = 0; + + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() : No valid Interface be found.\n", __func__)); + return; + } + + /*if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) */ + /* || ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) */ + /* || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP)) */ + /* ) */ + if (bBcnReq == FALSE) { + /* when the ra interface is down, do not send its beacon frame */ + /* clear all zero */ + for (i = 0; i < TXWI_SIZE; i += 4) + RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, + 0x00); + } else { + ptr = (u8 *)& pAd->BeaconTxWI; + for (i = 0; i < TXWI_SIZE; i += 4) /* 16-byte TXWI field */ + { + u32 longptr = + *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + + (*(ptr + 3) << 24); + RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, + longptr); + ptr += 4; + } + + /* Update CapabilityInfo in Beacon */ + for (i = CapInfoPos; i < (CapInfoPos + 2); i++) { + RTMP_IO_WRITE8(pAd, + pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + + i, *ptr_capinfo); + ptr_capinfo++; + } + + if (FrameLen > UpdatePos) { + for (i = UpdatePos; i < (FrameLen); i++) { + RTMP_IO_WRITE8(pAd, + pAd->BeaconOffset[bcn_idx] + + TXWI_SIZE + i, *ptr_update); + ptr_update++; + } + } + + } + +} + +void RT28xxPciStaAsicForceWakeup(struct rt_rtmp_adapter *pAd, IN BOOLEAN bFromTx) +{ + AUTO_WAKEUP_STRUC AutoWakeupCfg; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + return; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) { + DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); + return; + } + + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); + + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) + && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { + /* Support PCIe Advance Power Save */ + if (bFromTx == TRUE && (pAd->Mlme.bPsPollTimerRunning == TRUE)) { + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); + RTMPusecDelay(3000); + DBGPRINT(RT_DEBUG_TRACE, + ("=======AsicForceWakeup===bFromTx\n")); + } + + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + + if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE)) { +#ifdef PCIE_PS_SUPPORT + /* add by johnli, RF power sequence setup, load RF normal operation-mode setup */ + if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) + && IS_VERSION_AFTER_F(pAd)) { + struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; + + if (pChipOps->AsicReverseRfFromSleepMode) + pChipOps-> + AsicReverseRfFromSleepMode(pAd); + } else +#endif /* PCIE_PS_SUPPORT // */ + { + /* end johnli */ + /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. */ + if (INFRA_ON(pAd) + && (pAd->CommonCfg.CentralChannel != + pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo. + ChannelWidth == BW_40)) { + /* Must using 40MHz. */ + AsicSwitchChannel(pAd, + pAd->CommonCfg. + CentralChannel, + FALSE); + AsicLockChannel(pAd, + pAd->CommonCfg. + CentralChannel); + } else { + /* Must using 20MHz. */ + AsicSwitchChannel(pAd, + pAd->CommonCfg. + Channel, FALSE); + AsicLockChannel(pAd, + pAd->CommonCfg.Channel); + } + } + } +#ifdef PCIE_PS_SUPPORT + /* 3090 MCU Wakeup command needs more time to be stable. */ + /* Before stable, don't issue other MCU command to prevent from firmware error. */ + if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) + && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) + && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { + DBGPRINT(RT_DEBUG_TRACE, + ("<==RT28xxPciStaAsicForceWakeup::Release the MCU Lock(3090)\n")); + RTMP_SEM_LOCK(&pAd->McuCmdLock); + pAd->brt30xxBanMcuCmd = FALSE; + RTMP_SEM_UNLOCK(&pAd->McuCmdLock); + } +#endif /* PCIE_PS_SUPPORT // */ + } else { + /* PCI, 2860-PCIe */ + DBGPRINT(RT_DEBUG_TRACE, + ("<==RT28xxPciStaAsicForceWakeup::Original PCI Power Saving\n")); + AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + } + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); + DBGPRINT(RT_DEBUG_TRACE, ("<=======RT28xxPciStaAsicForceWakeup\n")); +} + +void RT28xxPciStaAsicSleepThenAutoWakeup(struct rt_rtmp_adapter *pAd, + u16 TbttNumToNextWakeUp) +{ + BOOLEAN brc; + + if (pAd->StaCfg.bRadio == FALSE) { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + return; + } + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) + && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { + unsigned long Now = 0; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) { + DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + return; + } + + NdisGetSystemUpTime(&Now); + /* If last send NULL fram time is too close to this receiving beacon (within 8ms), don't go to sleep for this DTM. */ + /* Because Some AP can't queuing outgoing frames immediately. */ + if (((pAd->Mlme.LastSendNULLpsmTime + 8) >= Now) + && (pAd->Mlme.LastSendNULLpsmTime <= Now)) { + DBGPRINT(RT_DEBUG_TRACE, + ("Now = %lu, LastSendNULLpsmTime=%lu : RxCountSinceLastNULL = %lu. \n", + Now, pAd->Mlme.LastSendNULLpsmTime, + pAd->RalinkCounters.RxCountSinceLastNULL)); + return; + } else if ((pAd->RalinkCounters.RxCountSinceLastNULL > 0) + && + ((pAd->Mlme.LastSendNULLpsmTime + + pAd->CommonCfg.BeaconPeriod) >= Now)) { + DBGPRINT(RT_DEBUG_TRACE, + ("Now = %lu, LastSendNULLpsmTime=%lu: RxCountSinceLastNULL = %lu > 0 \n", + Now, pAd->Mlme.LastSendNULLpsmTime, + pAd->RalinkCounters.RxCountSinceLastNULL)); + return; + } + + brc = + RT28xxPciAsicRadioOff(pAd, DOT11POWERSAVE, + TbttNumToNextWakeUp); + if (brc == TRUE) + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); + } else { + AUTO_WAKEUP_STRUC AutoWakeupCfg; + /* we have decided to SLEEP, so at least do it for a BEACON period. */ + if (TbttNumToNextWakeUp == 0) + TbttNumToNextWakeUp = 1; + + /*RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt); */ + + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; + AutoWakeupCfg.field.EnableAutoWakeup = 1; + AutoWakeupCfg.field.AutoLeadTime = 5; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x00); /* send POWER-SAVE command to MCU. Timeout 40us. */ + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); + DBGPRINT(RT_DEBUG_TRACE, + ("<-- %s, TbttNumToNextWakeUp=%d \n", __func__, + TbttNumToNextWakeUp)); + } + +} + +void PsPollWakeExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) +{ + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; + unsigned long flags; + + DBGPRINT(RT_DEBUG_TRACE, ("-->PsPollWakeExec \n")); + RTMP_INT_LOCK(&pAd->irq_lock, flags); + if (pAd->Mlme.bPsPollTimerRunning) { + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); + } + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); +#ifdef PCIE_PS_SUPPORT + /* For rt30xx power solution 3, Use software timer to wake up in psm. So call */ + /* AsicForceWakeup here instead of handling twakeup interrupt. */ + if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) + && IS_VERSION_AFTER_F(pAd)) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) + && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { + DBGPRINT(RT_DEBUG_TRACE, + ("<--PsPollWakeExec::3090 calls AsicForceWakeup(pAd, DOT11POWERSAVE) in advance \n")); + AsicForceWakeup(pAd, DOT11POWERSAVE); + } +#endif /* PCIE_PS_SUPPORT // */ +} + +void RadioOnExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) +{ + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; + struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; + WPDMA_GLO_CFG_STRUC DmaCfg; + BOOLEAN Cancelled; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { + DBGPRINT(RT_DEBUG_TRACE, + ("-->RadioOnExec() return on fOP_STATUS_DOZE == TRUE; \n")); +/*KH Debug: Add the compile flag "RT2860 and condition */ +#ifdef RTMP_PCI_SUPPORT + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) + && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) + RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); +#endif /* RTMP_PCI_SUPPORT // */ + return; + } + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) { + DBGPRINT(RT_DEBUG_TRACE, + ("-->RadioOnExec() return on SCAN_IN_PROGRESS; \n")); +#ifdef RTMP_PCI_SUPPORT + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) + && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) + RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); +#endif /* RTMP_PCI_SUPPORT // */ + return; + } +/*KH Debug: need to check. I add the compile flag "CONFIG_STA_SUPPORT" to enclose the following codes. */ +#ifdef RTMP_PCI_SUPPORT + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) + && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + } +#endif /* RTMP_PCI_SUPPORT // */ + if (pAd->StaCfg.bRadio == TRUE) { + pAd->bPCIclkOff = FALSE; + RTMPRingCleanUp(pAd, QID_AC_BK); + RTMPRingCleanUp(pAd, QID_AC_BE); + RTMPRingCleanUp(pAd, QID_AC_VI); + RTMPRingCleanUp(pAd, QID_AC_VO); + RTMPRingCleanUp(pAd, QID_MGMT); + RTMPRingCleanUp(pAd, QID_RX); + + /* 2. Send wake up command. */ + AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02); + /* 2-1. wait command ok. */ + AsicCheckCommanOk(pAd, PowerWakeCID); + + /* When PCI clock is off, don't want to service interrupt. So when back to clock on, enable interrupt. */ + /*RTMP_IO_WRITE32(pAd, INT_MASK_CSR, (DELAYINTMASK|RxINT)); */ + RTMP_ASIC_INTERRUPT_ENABLE(pAd); + + /* 3. Enable Tx DMA. */ + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); + DmaCfg.field.EnableTxDMA = 1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); + + /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. */ + if (INFRA_ON(pAd) + && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == + BW_40)) { + /* Must using 40MHz. */ + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, + FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + } else { + /* Must using 20MHz. */ + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } + +/*KH Debug:The following codes should be enclosed by RT3090 compile flag */ + if (pChipOps->AsicReverseRfFromSleepMode) + pChipOps->AsicReverseRfFromSleepMode(pAd); + +#ifdef PCIE_PS_SUPPORT +/* 3090 MCU Wakeup command needs more time to be stable. */ +/* Before stable, don't issue other MCU command to prevent from firmware error. */ + if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) + && IS_VERSION_AFTER_F(pAd) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) + && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { + RTMP_SEM_LOCK(&pAd->McuCmdLock); + pAd->brt30xxBanMcuCmd = FALSE; + RTMP_SEM_UNLOCK(&pAd->McuCmdLock); + } +#endif /* PCIE_PS_SUPPORT // */ + + /* Clear Radio off flag */ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + + /* Set LED */ + RTMPSetLED(pAd, LED_RADIO_ON); + + if (pAd->StaCfg.Psm == PWR_ACTIVE) { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, + pAd->StaCfg.BBPR3); + } + } else { + RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0); + } +} + +/* + ========================================================================== + Description: + This routine sends command to firmware and turn our chip to wake up mode from power save mode. + Both RadioOn and .11 power save function needs to call this routine. + Input: + Level = GUIRADIO_OFF : call this function is from Radio Off to Radio On. Need to restore PCI host value. + Level = other value : normal wake up function. + + ========================================================================== + */ +BOOLEAN RT28xxPciAsicRadioOn(struct rt_rtmp_adapter *pAd, u8 Level) +{ + /*WPDMA_GLO_CFG_STRUC DmaCfg; */ + BOOLEAN Cancelled; + /*u32 MACValue; */ + + if (pAd->OpMode == OPMODE_AP && Level == DOT11POWERSAVE) + return FALSE; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { + if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + } + if ((pAd->StaCfg.PSControl.field.EnableNewPS == TRUE && + (Level == GUIRADIO_OFF || Level == GUI_IDLE_POWER_SAVE)) || + RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)) { + /* Some chips don't need to delay 6ms, so copy RTMPPCIePowerLinkCtrlRestore */ + /* return condition here. */ + /* + if (((pAd->MACVersion&0xffff0000) != 0x28600000) + && ((pAd->DeviceID == NIC2860_PCIe_DEVICE_ID) + ||(pAd->DeviceID == NIC2790_PCIe_DEVICE_ID))) + */ + { + DBGPRINT(RT_DEBUG_TRACE, + ("RT28xxPciAsicRadioOn ()\n")); + /* 1. Set PCI Link Control in Configuration Space. */ + RTMPPCIeLinkCtrlValueRestore(pAd, + RESTORE_WAKEUP); + RTMPusecDelay(6000); + } + } + } +#ifdef PCIE_PS_SUPPORT + if (! + (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) + && IS_VERSION_AFTER_F(pAd) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) + && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)))) +#endif /* PCIE_PS_SUPPORT // */ + { + pAd->bPCIclkOff = FALSE; + DBGPRINT(RT_DEBUG_TRACE, + ("PSM :309xbPCIclkOff == %d\n", pAd->bPCIclkOff)); + } + /* 2. Send wake up command. */ + AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02); + pAd->bPCIclkOff = FALSE; + /* 2-1. wait command ok. */ + AsicCheckCommanOk(pAd, PowerWakeCID); + RTMP_ASIC_INTERRUPT_ENABLE(pAd); + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + if (Level == GUI_IDLE_POWER_SAVE) { +#ifdef PCIE_PS_SUPPORT + + /* add by johnli, RF power sequence setup, load RF normal operation-mode setup */ + if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) { + struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; + + if (pChipOps->AsicReverseRfFromSleepMode) + pChipOps->AsicReverseRfFromSleepMode(pAd); + /* 3090 MCU Wakeup command needs more time to be stable. */ + /* Before stable, don't issue other MCU command to prevent from firmware error. */ + if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) + && IS_VERSION_AFTER_F(pAd) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == + 3) + && (pAd->StaCfg.PSControl.field.EnableNewPS == + TRUE)) { + RTMP_SEM_LOCK(&pAd->McuCmdLock); + pAd->brt30xxBanMcuCmd = FALSE; + RTMP_SEM_UNLOCK(&pAd->McuCmdLock); + } + } else + /* end johnli */ +#endif /* PCIE_PS_SUPPORT // */ + { + /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. */ + { + if (INFRA_ON(pAd) + && (pAd->CommonCfg.CentralChannel != + pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo. + ChannelWidth == BW_40)) { + /* Must using 40MHz. */ + AsicSwitchChannel(pAd, + pAd->CommonCfg. + CentralChannel, + FALSE); + AsicLockChannel(pAd, + pAd->CommonCfg. + CentralChannel); + } else { + /* Must using 20MHz. */ + AsicSwitchChannel(pAd, + pAd->CommonCfg. + Channel, FALSE); + AsicLockChannel(pAd, + pAd->CommonCfg.Channel); + } + } + + } + } + return TRUE; + +} + +/* + ========================================================================== + Description: + This routine sends command to firmware and turn our chip to power save mode. + Both RadioOff and .11 power save function needs to call this routine. + Input: + Level = GUIRADIO_OFF : GUI Radio Off mode + Level = DOT11POWERSAVE : 802.11 power save mode + Level = RTMP_HALT : When Disable device. + + ========================================================================== + */ +BOOLEAN RT28xxPciAsicRadioOff(struct rt_rtmp_adapter *pAd, + u8 Level, u16 TbttNumToNextWakeUp) +{ + WPDMA_GLO_CFG_STRUC DmaCfg; + u8 i, tempBBP_R3 = 0; + BOOLEAN brc = FALSE, Cancelled; + u32 TbTTTime = 0; + u32 PsPollTime = 0 /*, MACValue */ ; + unsigned long BeaconPeriodTime; + u32 RxDmaIdx, RxCpuIdx; + DBGPRINT(RT_DEBUG_TRACE, + ("AsicRadioOff ===> Lv= %d, TxCpuIdx = %d, TxDmaIdx = %d. RxCpuIdx = %d, RxDmaIdx = %d.\n", + Level, pAd->TxRing[0].TxCpuIdx, pAd->TxRing[0].TxDmaIdx, + pAd->RxRing.RxCpuIdx, pAd->RxRing.RxDmaIdx)); + + if (pAd->OpMode == OPMODE_AP && Level == DOT11POWERSAVE) + return FALSE; + + /* Check Rx DMA busy status, if more than half is occupied, give up this radio off. */ + RTMP_IO_READ32(pAd, RX_DRX_IDX, &RxDmaIdx); + RTMP_IO_READ32(pAd, RX_CRX_IDX, &RxCpuIdx); + if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE / 3)) { + DBGPRINT(RT_DEBUG_TRACE, + ("AsicRadioOff ===> return1. RxDmaIdx = %d , RxCpuIdx = %d. \n", + RxDmaIdx, RxCpuIdx)); + return FALSE; + } else if ((RxCpuIdx >= RxDmaIdx) + && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE / 3)) { + DBGPRINT(RT_DEBUG_TRACE, + ("AsicRadioOff ===> return2. RxCpuIdx = %d. RxDmaIdx = %d , \n", + RxCpuIdx, RxDmaIdx)); + return FALSE; + } + /* Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops. */ + /*pAd->bPCIclkOffDisableTx = TRUE; */ + RTMP_SET_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) + && pAd->OpMode == OPMODE_STA + && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { + RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + + if (Level == DOT11POWERSAVE) { + RTMP_IO_READ32(pAd, TBTT_TIMER, &TbTTTime); + TbTTTime &= 0x1ffff; + /* 00. check if need to do sleep in this DTIM period. If next beacon will arrive within 30ms , ...doesn't necessarily sleep. */ + /* TbTTTime uint = 64us, LEAD_TIME unit = 1024us, PsPollTime unit = 1ms */ + if (((64 * TbTTTime) < ((LEAD_TIME * 1024) + 40000)) + && (TbttNumToNextWakeUp == 0)) { + DBGPRINT(RT_DEBUG_TRACE, + ("TbTTTime = 0x%x , give up this sleep. \n", + TbTTTime)); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + /*pAd->bPCIclkOffDisableTx = FALSE; */ + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); + return FALSE; + } else { + PsPollTime = + (64 * TbTTTime - LEAD_TIME * 1024) / 1000; +#ifdef PCIE_PS_SUPPORT + if ((IS_RT3090(pAd) || IS_RT3572(pAd) + || IS_RT3390(pAd)) + && IS_VERSION_AFTER_F(pAd) + && (pAd->StaCfg.PSControl.field. + rt30xxPowerMode == 3) + && (pAd->StaCfg.PSControl.field. + EnableNewPS == TRUE)) { + PsPollTime -= 5; + } else +#endif /* PCIE_PS_SUPPORT // */ + PsPollTime -= 3; + + BeaconPeriodTime = + pAd->CommonCfg.BeaconPeriod * 102 / 100; + if (TbttNumToNextWakeUp > 0) + PsPollTime += + ((TbttNumToNextWakeUp - + 1) * BeaconPeriodTime); + + pAd->Mlme.bPsPollTimerRunning = TRUE; + RTMPSetTimer(&pAd->Mlme.PsPollTimer, + PsPollTime); + } + } + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("RT28xxPciAsicRadioOff::Level!=DOT11POWERSAVE \n")); + } + + pAd->bPCIclkOffDisableTx = FALSE; + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + + /* Set to 1R. */ + if (pAd->Antenna.field.RxPath > 1 && pAd->OpMode == OPMODE_STA) { + tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3); + } + /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. */ + if ((INFRA_ON(pAd) || pAd->OpMode == OPMODE_AP) + && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) { + /* Must using 40MHz. */ + AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); + } else { + /* Must using 20MHz. */ + AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); + } + + if (Level != RTMP_HALT) { + /* Change Interrupt bitmask. */ + /* When PCI clock is off, don't want to service interrupt. */ + RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt); + } else { + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + } + + RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); + /* 2. Send Sleep command */ + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); + /* send POWER-SAVE command to MCU. high-byte = 1 save power as much as possible. high byte = 0 save less power */ + AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x1); + /* 2-1. Wait command success */ + /* Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task. */ + brc = AsicCheckCommanOk(pAd, PowerSafeCID); + + /* 3. After 0x30 command is ok, send radio off command. lowbyte = 0 for power safe. */ + /* If 0x30 command is not ok this time, we can ignore 0x35 command. It will make sure not cause firmware'r problem. */ + if ((Level == DOT11POWERSAVE) && (brc == TRUE)) { + AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 0, 0x00); /* lowbyte = 0 means to do power safe, NOT turn off radio. */ + /* 3-1. Wait command success */ + AsicCheckCommanOk(pAd, PowerRadioOffCID); + } else if (brc == TRUE) { + AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 1, 0x00); /* lowbyte = 0 means to do power safe, NOT turn off radio. */ + /* 3-1. Wait command success */ + AsicCheckCommanOk(pAd, PowerRadioOffCID); + } + /* 1. Wait DMA not busy */ + i = 0; + do { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); + if ((DmaCfg.field.RxDMABusy == 0) + && (DmaCfg.field.TxDMABusy == 0)) + break; + RTMPusecDelay(20); + i++; + } while (i < 50); + + /* + if (i >= 50) + { + pAd->CheckDmaBusyCount++; + DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy. return on AsicRadioOff () CheckDmaBusyCount = %d \n", pAd->CheckDmaBusyCount)); + } + else + { + pAd->CheckDmaBusyCount = 0; + } + */ +/*KH Debug:My original codes have the follwoing codes, but currecnt codes do not have it. */ +/* Disable for stability. If PCIE Link Control is modified for advance power save, re-covery this code segment. */ + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x1280); +/*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_CLKSELECT_40MHZ); */ + +#ifdef PCIE_PS_SUPPORT + if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) + && IS_VERSION_AFTER_F(pAd) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) + && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { + DBGPRINT(RT_DEBUG_TRACE, + ("RT28xxPciAsicRadioOff::3090 return to skip the following TbttNumToNextWakeUp setting for 279x\n")); + pAd->bPCIclkOff = TRUE; + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); + /* For this case, doesn't need to below actions, so return here. */ + return brc; + } +#endif /* PCIE_PS_SUPPORT // */ + + if (Level == DOT11POWERSAVE) { + AUTO_WAKEUP_STRUC AutoWakeupCfg; + /*RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90); */ + + /* we have decided to SLEEP, so at least do it for a BEACON period. */ + if (TbttNumToNextWakeUp == 0) + TbttNumToNextWakeUp = 1; + + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + + /* 1. Set auto wake up timer. */ + AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; + AutoWakeupCfg.field.EnableAutoWakeup = 1; + AutoWakeupCfg.field.AutoLeadTime = LEAD_TIME; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + } + /* 4-1. If it's to disable our device. Need to restore PCI Configuration Space to its original value. */ + if (Level == RTMP_HALT && pAd->OpMode == OPMODE_STA) { + if ((brc == TRUE) && (i < 50)) + RTMPPCIeLinkCtrlSetting(pAd, 1); + } + /* 4. Set PCI configuration Space Link Comtrol fields. Only Radio Off needs to call this function */ + else if (pAd->OpMode == OPMODE_STA) { + if ((brc == TRUE) && (i < 50)) + RTMPPCIeLinkCtrlSetting(pAd, 3); + } + /*pAd->bPCIclkOffDisableTx = FALSE; */ + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); + return TRUE; +} + +void RT28xxPciMlmeRadioOn(struct rt_rtmp_adapter *pAd) +{ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("%s===>\n", __func__)); + + if ((pAd->OpMode == OPMODE_AP) || ((pAd->OpMode == OPMODE_STA) + && + (!OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_PCIE_DEVICE) + || pAd->StaCfg.PSControl.field. + EnableNewPS == FALSE))) { + RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); + /*NICResetFromError(pAd); */ + + RTMPRingCleanUp(pAd, QID_AC_BK); + RTMPRingCleanUp(pAd, QID_AC_BE); + RTMPRingCleanUp(pAd, QID_AC_VI); + RTMPRingCleanUp(pAd, QID_AC_VO); + RTMPRingCleanUp(pAd, QID_MGMT); + RTMPRingCleanUp(pAd, QID_RX); + + /* Enable Tx/Rx */ + RTMPEnableRxTx(pAd); + + /* Clear Radio off flag */ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + + /* Set LED */ + RTMPSetLED(pAd, LED_RADIO_ON); + } + + if ((pAd->OpMode == OPMODE_STA) && + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) + && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { + BOOLEAN Cancelled; + + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); + + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); + RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 40); + } +} + +void RT28xxPciMlmeRadioOFF(struct rt_rtmp_adapter *pAd) +{ + BOOLEAN brc = TRUE; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + /* Link down first if any association exists */ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) { + struct rt_mlme_disassoc_req DisReq; + struct rt_mlme_queue_elem *pMsgElem = + (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem), + MEM_ALLOC_FLAG); + + if (pMsgElem) { + COPY_MAC_ADDR(&DisReq.Addr, + pAd->CommonCfg.Bssid); + DisReq.Reason = REASON_DISASSOC_STA_LEAVING; + + pMsgElem->Machine = ASSOC_STATE_MACHINE; + pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ; + pMsgElem->MsgLen = + sizeof(struct rt_mlme_disassoc_req); + NdisMoveMemory(pMsgElem->Msg, &DisReq, + sizeof + (struct rt_mlme_disassoc_req)); + + MlmeDisassocReqAction(pAd, pMsgElem); + kfree(pMsgElem); + + RTMPusecDelay(1000); + } + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s===>\n", __func__)); + + /* Set Radio off flag */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + + { + BOOLEAN Cancelled; + if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { + if (RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) { + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, + &Cancelled); + RTMP_CLEAR_FLAG(pAd, + fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + } + /* If during power safe mode. */ + if (pAd->StaCfg.bRadio == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, + ("-->MlmeRadioOff() return on bRadio == TRUE; \n")); + return; + } + /* Always radio on since the NIC needs to set the MCU command (LED_RADIO_OFF). */ + if (IDLE_ON(pAd) && + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) + { + RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); + } + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { + BOOLEAN Cancelled; + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, + &Cancelled); + RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, + &Cancelled); + } + } + /* Link down first if any association exists */ + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + LinkDown(pAd, FALSE); + RTMPusecDelay(10000); + /*========================================== */ + /* Clean up old bss table */ + BssTableInit(&pAd->ScanTab); + + /* + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) + { + RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); + return; + } + */ + } + + /* Set LED.Move to here for fixing LED bug. This flag must be called after LinkDown */ + RTMPSetLED(pAd, LED_RADIO_OFF); + +/*KH Debug:All PCIe devices need to use timer to execute radio off function, or the PCIe&&EnableNewPS needs. */ +/*KH Ans:It is right, because only when the PCIe and EnableNewPs is true, we need to delay the RadioOffTimer */ +/*to avoid the deadlock with PCIe Power saving function. */ + if (pAd->OpMode == OPMODE_STA && + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) && + pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { + RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); + } else { + brc = RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0); + + if (brc == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s call RT28xxPciAsicRadioOff fail!\n", + __func__)); + } + } +/* +*/ +} + +#endif /* RTMP_MAC_PCI // */ diff --git a/drivers/staging/rt2860/common/cmm_mac_usb.c b/drivers/staging/rt2860/common/cmm_mac_usb.c new file mode 100644 index 0000000000000000000000000000000000000000..9dd6959cd5a58477ffca262a7d05a660a4de4606 --- /dev/null +++ b/drivers/staging/rt2860/common/cmm_mac_usb.c @@ -0,0 +1,1165 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* +*/ + +#ifdef RTMP_MAC_USB + +#include "../rt_config.h" + +/* +======================================================================== +Routine Description: + Initialize receive data structures. + +Arguments: + pAd Pointer to our adapter + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_RESOURCES + +Note: + Initialize all receive releated private buffer, include those define + in struct rt_rtmp_adapter structure and all private data structures. The mahor + work is to allocate buffer for each packet and chain buffer to + NDIS packet descriptor. +======================================================================== +*/ +int NICInitRecv(struct rt_rtmp_adapter *pAd) +{ + u8 i; + int Status = NDIS_STATUS_SUCCESS; + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitRecv\n")); + pObj = pObj; + + /*InterlockedExchange(&pAd->PendingRx, 0); */ + pAd->PendingRx = 0; + pAd->NextRxBulkInReadIndex = 0; /* Next Rx Read index */ + pAd->NextRxBulkInIndex = 0; /*RX_RING_SIZE -1; // Rx Bulk pointer */ + pAd->NextRxBulkInPosition = 0; + + for (i = 0; i < (RX_RING_SIZE); i++) { + struct rt_rx_context *pRxContext = &(pAd->RxContext[i]); + + /*Allocate URB */ + pRxContext->pUrb = RTUSB_ALLOC_URB(0); + if (pRxContext->pUrb == NULL) { + Status = NDIS_STATUS_RESOURCES; + goto out1; + } + /* Allocate transfer buffer */ + pRxContext->TransferBuffer = + RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE, + &pRxContext->data_dma); + if (pRxContext->TransferBuffer == NULL) { + Status = NDIS_STATUS_RESOURCES; + goto out1; + } + + NdisZeroMemory(pRxContext->TransferBuffer, MAX_RXBULK_SIZE); + + pRxContext->pAd = pAd; + pRxContext->pIrp = NULL; + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pRxContext->Readable = FALSE; + /*pRxContext->ReorderInUse = FALSE; */ + pRxContext->bRxHandling = FALSE; + pRxContext->BulkInOffset = 0; + } + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitRecv(Status=%d)\n", Status)); + return Status; + +out1: + for (i = 0; i < (RX_RING_SIZE); i++) { + struct rt_rx_context *pRxContext = &(pAd->RxContext[i]); + + if (NULL != pRxContext->TransferBuffer) { + RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE, + pRxContext->TransferBuffer, + pRxContext->data_dma); + pRxContext->TransferBuffer = NULL; + } + + if (NULL != pRxContext->pUrb) { + RTUSB_UNLINK_URB(pRxContext->pUrb); + RTUSB_FREE_URB(pRxContext->pUrb); + pRxContext->pUrb = NULL; + } + } + + return Status; +} + +/* +======================================================================== +Routine Description: + Initialize transmit data structures. + +Arguments: + pAd Pointer to our adapter + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_RESOURCES + +Note: +======================================================================== +*/ +int NICInitTransmit(struct rt_rtmp_adapter *pAd) +{ +#define LM_USB_ALLOC(pObj, Context, TB_Type, BufferSize, Status, msg1, err1, msg2, err2) \ + Context->pUrb = RTUSB_ALLOC_URB(0); \ + if (Context->pUrb == NULL) { \ + DBGPRINT(RT_DEBUG_ERROR, msg1); \ + Status = NDIS_STATUS_RESOURCES; \ + goto err1; } \ + \ + Context->TransferBuffer = \ + (TB_Type)RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, BufferSize, &Context->data_dma); \ + if (Context->TransferBuffer == NULL) { \ + DBGPRINT(RT_DEBUG_ERROR, msg2); \ + Status = NDIS_STATUS_RESOURCES; \ + goto err2; } + +#define LM_URB_FREE(pObj, Context, BufferSize) \ + if (NULL != Context->pUrb) { \ + RTUSB_UNLINK_URB(Context->pUrb); \ + RTUSB_FREE_URB(Context->pUrb); \ + Context->pUrb = NULL; } \ + if (NULL != Context->TransferBuffer) { \ + RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, BufferSize, \ + Context->TransferBuffer, \ + Context->data_dma); \ + Context->TransferBuffer = NULL; } + + u8 i, acidx; + int Status = NDIS_STATUS_SUCCESS; + struct rt_tx_context *pNullContext = &(pAd->NullContext); + struct rt_tx_context *pPsPollContext = &(pAd->PsPollContext); + struct rt_tx_context *pRTSContext = &(pAd->RTSContext); + struct rt_tx_context *pMLMEContext = NULL; +/* struct rt_ht_tx_context *pHTTXContext = NULL; */ + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; + void *RingBaseVa; +/* struct rt_rtmp_tx_ring *pTxRing; */ + struct rt_rtmp_mgmt_ring *pMgmtRing; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTransmit\n")); + pObj = pObj; + + /* Init 4 set of Tx parameters */ + for (acidx = 0; acidx < NUM_OF_TX_RING; acidx++) { + /* Initialize all Transmit releated queues */ + InitializeQueueHeader(&pAd->TxSwQueue[acidx]); + + /* Next Local tx ring pointer waiting for buck out */ + pAd->NextBulkOutIndex[acidx] = acidx; + pAd->BulkOutPending[acidx] = FALSE; /* Buck Out control flag */ + /*pAd->DataBulkDoneIdx[acidx] = 0; */ + } + + /*pAd->NextMLMEIndex = 0; */ + /*pAd->PushMgmtIndex = 0; */ + /*pAd->PopMgmtIndex = 0; */ + /*InterlockedExchange(&pAd->MgmtQueueSize, 0); */ + /*InterlockedExchange(&pAd->TxCount, 0); */ + + /*pAd->PrioRingFirstIndex = 0; */ + /*pAd->PrioRingTxCnt = 0; */ + + do { + /* */ + /* TX_RING_SIZE, 4 ACs */ + /* */ + for (acidx = 0; acidx < 4; acidx++) { + struct rt_ht_tx_context *pHTTXContext = &(pAd->TxContext[acidx]); + + NdisZeroMemory(pHTTXContext, sizeof(struct rt_ht_tx_context)); + /*Allocate URB */ + LM_USB_ALLOC(pObj, pHTTXContext, struct rt_httx_buffer *, + sizeof(struct rt_httx_buffer), Status, + ("<-- ERROR in Alloc TX TxContext[%d] urb!\n", + acidx), done, + ("<-- ERROR in Alloc TX TxContext[%d] struct rt_httx_buffer!\n", + acidx), out1); + + NdisZeroMemory(pHTTXContext->TransferBuffer-> + Aggregation, 4); + pHTTXContext->pAd = pAd; + pHTTXContext->pIrp = NULL; + pHTTXContext->IRPPending = FALSE; + pHTTXContext->NextBulkOutPosition = 0; + pHTTXContext->ENextBulkOutPosition = 0; + pHTTXContext->CurWritePosition = 0; + pHTTXContext->CurWriteRealPos = 0; + pHTTXContext->BulkOutSize = 0; + pHTTXContext->BulkOutPipeId = acidx; + pHTTXContext->bRingEmpty = TRUE; + pHTTXContext->bCopySavePad = FALSE; + pAd->BulkOutPending[acidx] = FALSE; + } + + /* */ + /* MGMT_RING_SIZE */ + /* */ + + /* Allocate MGMT ring descriptor's memory */ + pAd->MgmtDescRing.AllocSize = + MGMT_RING_SIZE * sizeof(struct rt_tx_context); + os_alloc_mem(pAd, (u8 **) (&pAd->MgmtDescRing.AllocVa), + pAd->MgmtDescRing.AllocSize); + if (pAd->MgmtDescRing.AllocVa == NULL) { + DBGPRINT_ERR(("Failed to allocate a big buffer for MgmtDescRing!\n")); + Status = NDIS_STATUS_RESOURCES; + goto out1; + } + NdisZeroMemory(pAd->MgmtDescRing.AllocVa, + pAd->MgmtDescRing.AllocSize); + RingBaseVa = pAd->MgmtDescRing.AllocVa; + + /* Initialize MGMT Ring and associated buffer memory */ + pMgmtRing = &pAd->MgmtRing; + for (i = 0; i < MGMT_RING_SIZE; i++) { + /* link the pre-allocated Mgmt buffer to MgmtRing.Cell */ + pMgmtRing->Cell[i].AllocSize = sizeof(struct rt_tx_context); + pMgmtRing->Cell[i].AllocVa = RingBaseVa; + pMgmtRing->Cell[i].pNdisPacket = NULL; + pMgmtRing->Cell[i].pNextNdisPacket = NULL; + + /*Allocate URB for MLMEContext */ + pMLMEContext = + (struct rt_tx_context *)pAd->MgmtRing.Cell[i].AllocVa; + pMLMEContext->pUrb = RTUSB_ALLOC_URB(0); + if (pMLMEContext->pUrb == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("<-- ERROR in Alloc TX MLMEContext[%d] urb!\n", + i)); + Status = NDIS_STATUS_RESOURCES; + goto out2; + } + pMLMEContext->pAd = pAd; + pMLMEContext->pIrp = NULL; + pMLMEContext->TransferBuffer = NULL; + pMLMEContext->InUse = FALSE; + pMLMEContext->IRPPending = FALSE; + pMLMEContext->bWaitingBulkOut = FALSE; + pMLMEContext->BulkOutSize = 0; + pMLMEContext->SelfIdx = i; + + /* Offset to next ring descriptor address */ + RingBaseVa = (u8 *)RingBaseVa + sizeof(struct rt_tx_context); + } + DBGPRINT(RT_DEBUG_TRACE, + ("MGMT Ring: total %d entry allocated\n", i)); + + /*pAd->MgmtRing.TxSwFreeIdx = (MGMT_RING_SIZE - 1); */ + pAd->MgmtRing.TxSwFreeIdx = MGMT_RING_SIZE; + pAd->MgmtRing.TxCpuIdx = 0; + pAd->MgmtRing.TxDmaIdx = 0; + + /* */ + /* BEACON_RING_SIZE */ + /* */ + for (i = 0; i < BEACON_RING_SIZE; i++) /* 2 */ + { + struct rt_tx_context *pBeaconContext = &(pAd->BeaconContext[i]); + + NdisZeroMemory(pBeaconContext, sizeof(struct rt_tx_context)); + + /*Allocate URB */ + LM_USB_ALLOC(pObj, pBeaconContext, struct rt_tx_buffer *, + sizeof(struct rt_tx_buffer), Status, + ("<-- ERROR in Alloc TX BeaconContext[%d] urb!\n", + i), out2, + ("<-- ERROR in Alloc TX BeaconContext[%d] struct rt_tx_buffer!\n", + i), out3); + + pBeaconContext->pAd = pAd; + pBeaconContext->pIrp = NULL; + pBeaconContext->InUse = FALSE; + pBeaconContext->IRPPending = FALSE; + } + + /* */ + /* NullContext */ + /* */ + NdisZeroMemory(pNullContext, sizeof(struct rt_tx_context)); + + /*Allocate URB */ + LM_USB_ALLOC(pObj, pNullContext, struct rt_tx_buffer *, sizeof(struct rt_tx_buffer), + Status, + ("<-- ERROR in Alloc TX NullContext urb!\n"), + out3, + ("<-- ERROR in Alloc TX NullContext struct rt_tx_buffer!\n"), + out4); + + pNullContext->pAd = pAd; + pNullContext->pIrp = NULL; + pNullContext->InUse = FALSE; + pNullContext->IRPPending = FALSE; + + /* */ + /* RTSContext */ + /* */ + NdisZeroMemory(pRTSContext, sizeof(struct rt_tx_context)); + + /*Allocate URB */ + LM_USB_ALLOC(pObj, pRTSContext, struct rt_tx_buffer *, sizeof(struct rt_tx_buffer), + Status, + ("<-- ERROR in Alloc TX RTSContext urb!\n"), + out4, + ("<-- ERROR in Alloc TX RTSContext struct rt_tx_buffer!\n"), + out5); + + pRTSContext->pAd = pAd; + pRTSContext->pIrp = NULL; + pRTSContext->InUse = FALSE; + pRTSContext->IRPPending = FALSE; + + /* */ + /* PsPollContext */ + /* */ + /*NdisZeroMemory(pPsPollContext, sizeof(struct rt_tx_context)); */ + /*Allocate URB */ + LM_USB_ALLOC(pObj, pPsPollContext, struct rt_tx_buffer *, + sizeof(struct rt_tx_buffer), Status, + ("<-- ERROR in Alloc TX PsPollContext urb!\n"), + out5, + ("<-- ERROR in Alloc TX PsPollContext struct rt_tx_buffer!\n"), + out6); + + pPsPollContext->pAd = pAd; + pPsPollContext->pIrp = NULL; + pPsPollContext->InUse = FALSE; + pPsPollContext->IRPPending = FALSE; + pPsPollContext->bAggregatible = FALSE; + pPsPollContext->LastOne = TRUE; + + } while (FALSE); + +done: + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTransmit(Status=%d)\n", Status)); + + return Status; + + /* --------------------------- ERROR HANDLE --------------------------- */ +out6: + LM_URB_FREE(pObj, pPsPollContext, sizeof(struct rt_tx_buffer)); + +out5: + LM_URB_FREE(pObj, pRTSContext, sizeof(struct rt_tx_buffer)); + +out4: + LM_URB_FREE(pObj, pNullContext, sizeof(struct rt_tx_buffer)); + +out3: + for (i = 0; i < BEACON_RING_SIZE; i++) { + struct rt_tx_context *pBeaconContext = &(pAd->BeaconContext[i]); + if (pBeaconContext) + LM_URB_FREE(pObj, pBeaconContext, sizeof(struct rt_tx_buffer)); + } + +out2: + if (pAd->MgmtDescRing.AllocVa) { + pMgmtRing = &pAd->MgmtRing; + for (i = 0; i < MGMT_RING_SIZE; i++) { + pMLMEContext = + (struct rt_tx_context *)pAd->MgmtRing.Cell[i].AllocVa; + if (pMLMEContext) + LM_URB_FREE(pObj, pMLMEContext, + sizeof(struct rt_tx_buffer)); + } + os_free_mem(pAd, pAd->MgmtDescRing.AllocVa); + pAd->MgmtDescRing.AllocVa = NULL; + } + +out1: + for (acidx = 0; acidx < 4; acidx++) { + struct rt_ht_tx_context *pTxContext = &(pAd->TxContext[acidx]); + if (pTxContext) + LM_URB_FREE(pObj, pTxContext, sizeof(struct rt_httx_buffer)); + } + + /* Here we didn't have any pre-allocated memory need to free. */ + + return Status; +} + +/* +======================================================================== +Routine Description: + Allocate DMA memory blocks for send, receive. + +Arguments: + pAd Pointer to our adapter + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + NDIS_STATUS_RESOURCES + +Note: +======================================================================== +*/ +int RTMPAllocTxRxRingMemory(struct rt_rtmp_adapter *pAd) +{ +/* struct rt_counter_802_11 pCounter = &pAd->WlanCounters; */ + int Status; + int num; + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); + + do { + /* Init the struct rt_cmdq and CmdQLock */ + NdisAllocateSpinLock(&pAd->CmdQLock); + NdisAcquireSpinLock(&pAd->CmdQLock); + RTUSBInitializeCmdQ(&pAd->CmdQ); + NdisReleaseSpinLock(&pAd->CmdQLock); + + NdisAllocateSpinLock(&pAd->MLMEBulkOutLock); + /*NdisAllocateSpinLock(&pAd->MLMEWaitQueueLock); */ + NdisAllocateSpinLock(&pAd->BulkOutLock[0]); + NdisAllocateSpinLock(&pAd->BulkOutLock[1]); + NdisAllocateSpinLock(&pAd->BulkOutLock[2]); + NdisAllocateSpinLock(&pAd->BulkOutLock[3]); + NdisAllocateSpinLock(&pAd->BulkOutLock[4]); + NdisAllocateSpinLock(&pAd->BulkOutLock[5]); + NdisAllocateSpinLock(&pAd->BulkInLock); + + for (num = 0; num < NUM_OF_TX_RING; num++) { + NdisAllocateSpinLock(&pAd->TxContextQueueLock[num]); + } + +/* NdisAllocateSpinLock(&pAd->MemLock); // Not used in RT28XX */ + +/* NdisAllocateSpinLock(&pAd->MacTabLock); // init it in UserCfgInit() */ +/* NdisAllocateSpinLock(&pAd->BATabLock); // init it in BATableInit() */ + +/* for(num=0; numBATable.BARecEntry[num].RxReRingLock); */ +/* } */ + + /* */ + /* Init Mac Table */ + /* */ +/* MacTableInitialize(pAd); */ + + /* */ + /* Init send data structures and related parameters */ + /* */ + Status = NICInitTransmit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + break; + + /* */ + /* Init receive data structures and related parameters */ + /* */ + Status = NICInitRecv(pAd); + if (Status != NDIS_STATUS_SUCCESS) + break; + + pAd->PendingIoCount = 1; + + } while (FALSE); + + NdisZeroMemory(&pAd->FragFrame, sizeof(struct rt_fragment_frame)); + pAd->FragFrame.pFragPacket = + RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); + + if (pAd->FragFrame.pFragPacket == NULL) { + Status = NDIS_STATUS_RESOURCES; + } + + DBGPRINT_S(Status, + ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); + return Status; +} + +/* +======================================================================== +Routine Description: + Calls USB_InterfaceStop and frees memory allocated for the URBs + calls NdisMDeregisterDevice and frees the memory + allocated in VNetInitialize for the Adapter Object + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +void RTMPFreeTxRxRingMemory(struct rt_rtmp_adapter *pAd) +{ +#define LM_URB_FREE(pObj, Context, BufferSize) \ + if (NULL != Context->pUrb) { \ + RTUSB_UNLINK_URB(Context->pUrb); \ + RTUSB_FREE_URB(Context->pUrb); \ + Context->pUrb = NULL; } \ + if (NULL != Context->TransferBuffer) { \ + RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, BufferSize, \ + Context->TransferBuffer, \ + Context->data_dma); \ + Context->TransferBuffer = NULL; } + + u32 i, acidx; + struct rt_tx_context *pNullContext = &pAd->NullContext; + struct rt_tx_context *pPsPollContext = &pAd->PsPollContext; + struct rt_tx_context *pRTSContext = &pAd->RTSContext; +/* struct rt_ht_tx_context *pHTTXContext; */ + /*PRTMP_REORDERBUF pReorderBuf; */ + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; +/* struct rt_rtmp_tx_ring *pTxRing; */ + + DBGPRINT(RT_DEBUG_ERROR, ("---> RTMPFreeTxRxRingMemory\n")); + pObj = pObj; + + /* Free all resources for the RECEIVE buffer queue. */ + for (i = 0; i < (RX_RING_SIZE); i++) { + struct rt_rx_context *pRxContext = &(pAd->RxContext[i]); + if (pRxContext) + LM_URB_FREE(pObj, pRxContext, MAX_RXBULK_SIZE); + } + + /* Free PsPoll frame resource */ + LM_URB_FREE(pObj, pPsPollContext, sizeof(struct rt_tx_buffer)); + + /* Free NULL frame resource */ + LM_URB_FREE(pObj, pNullContext, sizeof(struct rt_tx_buffer)); + + /* Free RTS frame resource */ + LM_URB_FREE(pObj, pRTSContext, sizeof(struct rt_tx_buffer)); + + /* Free beacon frame resource */ + for (i = 0; i < BEACON_RING_SIZE; i++) { + struct rt_tx_context *pBeaconContext = &(pAd->BeaconContext[i]); + if (pBeaconContext) + LM_URB_FREE(pObj, pBeaconContext, sizeof(struct rt_tx_buffer)); + } + + /* Free mgmt frame resource */ + for (i = 0; i < MGMT_RING_SIZE; i++) { + struct rt_tx_context *pMLMEContext = + (struct rt_tx_context *)pAd->MgmtRing.Cell[i].AllocVa; + /*LM_URB_FREE(pObj, pMLMEContext, sizeof(struct rt_tx_buffer)); */ + if (NULL != pAd->MgmtRing.Cell[i].pNdisPacket) { + RTMPFreeNdisPacket(pAd, + pAd->MgmtRing.Cell[i].pNdisPacket); + pAd->MgmtRing.Cell[i].pNdisPacket = NULL; + pMLMEContext->TransferBuffer = NULL; + } + + if (pMLMEContext) { + if (NULL != pMLMEContext->pUrb) { + RTUSB_UNLINK_URB(pMLMEContext->pUrb); + RTUSB_FREE_URB(pMLMEContext->pUrb); + pMLMEContext->pUrb = NULL; + } + } + } + if (pAd->MgmtDescRing.AllocVa) + os_free_mem(pAd, pAd->MgmtDescRing.AllocVa); + + /* Free Tx frame resource */ + for (acidx = 0; acidx < 4; acidx++) { + struct rt_ht_tx_context *pHTTXContext = &(pAd->TxContext[acidx]); + if (pHTTXContext) + LM_URB_FREE(pObj, pHTTXContext, sizeof(struct rt_httx_buffer)); + } + + if (pAd->FragFrame.pFragPacket) + RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, + NDIS_STATUS_SUCCESS); + + for (i = 0; i < 6; i++) { + NdisFreeSpinLock(&pAd->BulkOutLock[i]); + } + + NdisFreeSpinLock(&pAd->BulkInLock); + NdisFreeSpinLock(&pAd->MLMEBulkOutLock); + + NdisFreeSpinLock(&pAd->CmdQLock); + /* Clear all pending bulk-out request flags. */ + RTUSB_CLEAR_BULK_FLAG(pAd, 0xffffffff); + +/* NdisFreeSpinLock(&pAd->MacTabLock); */ + +/* for(i=0; iBATable.BARecEntry[i].RxReRingLock); */ +/* } */ + + DBGPRINT(RT_DEBUG_ERROR, ("<--- RTMPFreeTxRxRingMemory\n")); +} + +/* +======================================================================== +Routine Description: + Write WLAN MAC address to USB 2870. + +Arguments: + pAd Pointer to our adapter + +Return Value: + NDIS_STATUS_SUCCESS + +Note: +======================================================================== +*/ +int RTUSBWriteHWMACAddress(struct rt_rtmp_adapter *pAd) +{ + MAC_DW0_STRUC StaMacReg0; + MAC_DW1_STRUC StaMacReg1; + int Status = NDIS_STATUS_SUCCESS; + LARGE_INTEGER NOW; + + /* initialize the random number generator */ + RTMP_GetCurrentSystemTime(&NOW); + + if (pAd->bLocalAdminMAC != TRUE) { + pAd->CurrentAddress[0] = pAd->PermanentAddress[0]; + pAd->CurrentAddress[1] = pAd->PermanentAddress[1]; + pAd->CurrentAddress[2] = pAd->PermanentAddress[2]; + pAd->CurrentAddress[3] = pAd->PermanentAddress[3]; + pAd->CurrentAddress[4] = pAd->PermanentAddress[4]; + pAd->CurrentAddress[5] = pAd->PermanentAddress[5]; + } + /* Write New MAC address to MAC_CSR2 & MAC_CSR3 & let ASIC know our new MAC */ + StaMacReg0.field.Byte0 = pAd->CurrentAddress[0]; + StaMacReg0.field.Byte1 = pAd->CurrentAddress[1]; + StaMacReg0.field.Byte2 = pAd->CurrentAddress[2]; + StaMacReg0.field.Byte3 = pAd->CurrentAddress[3]; + StaMacReg1.field.Byte4 = pAd->CurrentAddress[4]; + StaMacReg1.field.Byte5 = pAd->CurrentAddress[5]; + StaMacReg1.field.U2MeMask = 0xff; + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("Local MAC = %02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->CurrentAddress[0], pAd->CurrentAddress[1], + pAd->CurrentAddress[2], pAd->CurrentAddress[3], + pAd->CurrentAddress[4], pAd->CurrentAddress[5])); + + RTUSBWriteMACRegister(pAd, MAC_ADDR_DW0, StaMacReg0.word); + RTUSBWriteMACRegister(pAd, MAC_ADDR_DW1, StaMacReg1.word); + return Status; +} + +/* +======================================================================== +Routine Description: + Disable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +void RT28XXDMADisable(struct rt_rtmp_adapter *pAd) +{ + /* no use */ +} + +/* +======================================================================== +Routine Description: + Enable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +void RT28XXDMAEnable(struct rt_rtmp_adapter *pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + USB_DMA_CFG_STRUC UsbCfg; + int i = 0; + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4); + do { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) + && (GloCfg.field.RxDMABusy == 0)) + break; + + DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n")); + RTMPusecDelay(1000); + i++; + } while (i < 200); + + RTMPusecDelay(50); + GloCfg.field.EnTXWriteBackDDONE = 1; + GloCfg.field.EnableRxDMA = 1; + GloCfg.field.EnableTxDMA = 1; + DBGPRINT(RT_DEBUG_TRACE, + ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word)); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + + UsbCfg.word = 0; + UsbCfg.field.phyclear = 0; + /* usb version is 1.1,do not use bulk in aggregation */ + if (pAd->BulkInMaxPacketSize == 512) + UsbCfg.field.RxBulkAggEn = 1; + /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */ + UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE / 1024) - 3; + UsbCfg.field.RxBulkAggTOut = 0x80; /* 2006-10-18 */ + UsbCfg.field.RxBulkEn = 1; + UsbCfg.field.TxBulkEn = 1; + + RTUSBWriteMACRegister(pAd, USB_DMA_CFG, UsbCfg.word); + +} + +/******************************************************************** + * + * 2870 Beacon Update Related functions. + * + ********************************************************************/ + +/* +======================================================================== +Routine Description: + Write Beacon buffer to Asic. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +void RT28xx_UpdateBeaconToAsic(struct rt_rtmp_adapter *pAd, + int apidx, + unsigned long FrameLen, unsigned long UpdatePos) +{ + u8 *pBeaconFrame = NULL; + u8 *ptr; + u32 i, padding; + struct rt_beacon_sync *pBeaconSync = pAd->CommonCfg.pBeaconSync; + u32 longValue; +/* u16 shortValue; */ + BOOLEAN bBcnReq = FALSE; + u8 bcn_idx = 0; + + if (pBeaconFrame == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("pBeaconFrame is NULL!\n")); + return; + } + + if (pBeaconSync == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("pBeaconSync is NULL!\n")); + return; + } + /*if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) || */ + /* ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP)) */ + /* ) */ + if (bBcnReq == FALSE) { + /* when the ra interface is down, do not send its beacon frame */ + /* clear all zero */ + for (i = 0; i < TXWI_SIZE; i += 4) { + RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, + 0x00); + } + pBeaconSync->BeaconBitMap &= + (~(BEACON_BITMAP_MASK & (1 << bcn_idx))); + NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWI_SIZE); + } else { + ptr = (u8 *)& pAd->BeaconTxWI; + if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE) == FALSE) { /* If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames. */ + pBeaconSync->BeaconBitMap &= + (~(BEACON_BITMAP_MASK & (1 << bcn_idx))); + NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx], + &pAd->BeaconTxWI, TXWI_SIZE); + } + + if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) != + (1 << bcn_idx)) { + for (i = 0; i < TXWI_SIZE; i += 4) /* 16-byte TXWI field */ + { + longValue = + *ptr + (*(ptr + 1) << 8) + + (*(ptr + 2) << 16) + (*(ptr + 3) << 24); + RTMP_IO_WRITE32(pAd, + pAd->BeaconOffset[bcn_idx] + i, + longValue); + ptr += 4; + } + } + + ptr = pBeaconSync->BeaconBuf[bcn_idx]; + padding = (FrameLen & 0x01); + NdisZeroMemory((u8 *)(pBeaconFrame + FrameLen), padding); + FrameLen += padding; + for (i = 0; i < FrameLen /*HW_BEACON_OFFSET */ ; i += 2) { + if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE) { + NdisMoveMemory(ptr, pBeaconFrame, 2); + /*shortValue = *ptr + (*(ptr+1)<<8); */ + /*RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue); */ + RTUSBMultiWrite(pAd, + pAd->BeaconOffset[bcn_idx] + + TXWI_SIZE + i, ptr, 2); + } + ptr += 2; + pBeaconFrame += 2; + } + + pBeaconSync->BeaconBitMap |= (1 << bcn_idx); + + /* For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame. */ + } + +} + +void RTUSBBssBeaconStop(struct rt_rtmp_adapter *pAd) +{ + struct rt_beacon_sync *pBeaconSync; + int i, offset; + BOOLEAN Cancelled = TRUE; + + pBeaconSync = pAd->CommonCfg.pBeaconSync; + if (pBeaconSync && pBeaconSync->EnableBeacon) { + int NumOfBcn; + + { + NumOfBcn = MAX_MESH_NUM; + } + + RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled); + + for (i = 0; i < NumOfBcn; i++) { + NdisZeroMemory(pBeaconSync->BeaconBuf[i], + HW_BEACON_OFFSET); + NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); + + for (offset = 0; offset < HW_BEACON_OFFSET; offset += 4) + RTMP_IO_WRITE32(pAd, + pAd->BeaconOffset[i] + offset, + 0x00); + + pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; + pBeaconSync->TimIELocationInBeacon[i] = 0; + } + pBeaconSync->BeaconBitMap = 0; + pBeaconSync->DtimBitOn = 0; + } +} + +void RTUSBBssBeaconStart(struct rt_rtmp_adapter *pAd) +{ + int apidx; + struct rt_beacon_sync *pBeaconSync; +/* LARGE_INTEGER tsfTime, deltaTime; */ + + pBeaconSync = pAd->CommonCfg.pBeaconSync; + if (pBeaconSync && pBeaconSync->EnableBeacon) { + int NumOfBcn; + + { + NumOfBcn = MAX_MESH_NUM; + } + + for (apidx = 0; apidx < NumOfBcn; apidx++) { + u8 CapabilityInfoLocationInBeacon = 0; + u8 TimIELocationInBeacon = 0; + + NdisZeroMemory(pBeaconSync->BeaconBuf[apidx], + HW_BEACON_OFFSET); + pBeaconSync->CapabilityInfoLocationInBeacon[apidx] = + CapabilityInfoLocationInBeacon; + pBeaconSync->TimIELocationInBeacon[apidx] = + TimIELocationInBeacon; + NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx], + TXWI_SIZE); + } + pBeaconSync->BeaconBitMap = 0; + pBeaconSync->DtimBitOn = 0; + pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE; + + pAd->CommonCfg.BeaconAdjust = 0; + pAd->CommonCfg.BeaconFactor = + 0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10); + pAd->CommonCfg.BeaconRemain = + (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1; + DBGPRINT(RT_DEBUG_TRACE, + ("RTUSBBssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", + pAd->CommonCfg.BeaconFactor, + pAd->CommonCfg.BeaconRemain)); + RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer, + 10 /*pAd->CommonCfg.BeaconPeriod */ ); + + } +} + +void RTUSBBssBeaconInit(struct rt_rtmp_adapter *pAd) +{ + struct rt_beacon_sync *pBeaconSync; + int i; + + os_alloc_mem(pAd, (u8 **) (&pAd->CommonCfg.pBeaconSync), + sizeof(struct rt_beacon_sync)); + /*NdisAllocMemory(pAd->CommonCfg.pBeaconSync, sizeof(struct rt_beacon_sync), MEM_ALLOC_FLAG); */ + if (pAd->CommonCfg.pBeaconSync) { + pBeaconSync = pAd->CommonCfg.pBeaconSync; + NdisZeroMemory(pBeaconSync, sizeof(struct rt_beacon_sync)); + for (i = 0; i < HW_BEACON_MAX_COUNT; i++) { + NdisZeroMemory(pBeaconSync->BeaconBuf[i], + HW_BEACON_OFFSET); + pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; + pBeaconSync->TimIELocationInBeacon[i] = 0; + NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); + } + pBeaconSync->BeaconBitMap = 0; + + /*RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE); */ + pBeaconSync->EnableBeacon = TRUE; + } +} + +void RTUSBBssBeaconExit(struct rt_rtmp_adapter *pAd) +{ + struct rt_beacon_sync *pBeaconSync; + BOOLEAN Cancelled = TRUE; + int i; + + if (pAd->CommonCfg.pBeaconSync) { + pBeaconSync = pAd->CommonCfg.pBeaconSync; + pBeaconSync->EnableBeacon = FALSE; + RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled); + pBeaconSync->BeaconBitMap = 0; + + for (i = 0; i < HW_BEACON_MAX_COUNT; i++) { + NdisZeroMemory(pBeaconSync->BeaconBuf[i], + HW_BEACON_OFFSET); + pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; + pBeaconSync->TimIELocationInBeacon[i] = 0; + NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); + } + + os_free_mem(pAd, pAd->CommonCfg.pBeaconSync); + pAd->CommonCfg.pBeaconSync = NULL; + } +} + +/* + ======================================================================== + Routine Description: + For device work as AP mode but didn't have TBTT interrupt event, we need a mechanism + to update the beacon context in each Beacon interval. Here we use a periodical timer + to simulate the TBTT interrupt to handle the beacon context update. + + Arguments: + SystemSpecific1 - Not used. + FunctionContext - Pointer to our Adapter context. + SystemSpecific2 - Not used. + SystemSpecific3 - Not used. + + Return Value: + None + + ======================================================================== +*/ +void BeaconUpdateExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) +{ + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; + LARGE_INTEGER tsfTime_a; /*, tsfTime_b, deltaTime_exp, deltaTime_ab; */ + u32 delta, delta2MS, period2US, remain, remain_low, remain_high; +/* BOOLEAN positive; */ + + if (pAd->CommonCfg.IsUpdateBeacon == TRUE) { + ReSyncBeaconTime(pAd); + + } + + RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart); + RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart); + + /*positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp); */ + period2US = (pAd->CommonCfg.BeaconPeriod << 10); + remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart; + remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10); + remain = + (remain_high + remain_low) % (pAd->CommonCfg.BeaconPeriod << 10); + delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain; + + delta2MS = (delta >> 10); + if (delta2MS > 150) { + pAd->CommonCfg.BeaconUpdateTimer.TimerValue = 100; + pAd->CommonCfg.IsUpdateBeacon = FALSE; + } else { + pAd->CommonCfg.BeaconUpdateTimer.TimerValue = delta2MS + 10; + pAd->CommonCfg.IsUpdateBeacon = TRUE; + } + +} + +/******************************************************************** + * + * 2870 Radio on/off Related functions. + * + ********************************************************************/ +void RT28xxUsbMlmeRadioOn(struct rt_rtmp_adapter *pAd) +{ + struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; + + DBGPRINT(RT_DEBUG_TRACE, ("RT28xxUsbMlmeRadioOn()\n")); + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + { + AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); + RTMPusecDelay(10000); + } + /*NICResetFromError(pAd); */ + + /* Enable Tx/Rx */ + RTMPEnableRxTx(pAd); + + if (pChipOps->AsicReverseRfFromSleepMode) + pChipOps->AsicReverseRfFromSleepMode(pAd); + + /* Clear Radio off flag */ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + + RTUSBBulkReceive(pAd); + + /* Set LED */ + RTMPSetLED(pAd, LED_RADIO_ON); +} + +void RT28xxUsbMlmeRadioOFF(struct rt_rtmp_adapter *pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + u32 Value, i; + + DBGPRINT(RT_DEBUG_TRACE, ("RT28xxUsbMlmeRadioOFF()\n")); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + /* Clear PMKID cache. */ + pAd->StaCfg.SavedPMKNum = 0; + RTMPZeroMemory(pAd->StaCfg.SavedPMK, (PMKID_NO * sizeof(struct rt_bssid_info))); + + /* Link down first if any association exists */ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) { + struct rt_mlme_disassoc_req DisReq; + struct rt_mlme_queue_elem *pMsgElem = + (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem), + MEM_ALLOC_FLAG); + + if (pMsgElem) { + COPY_MAC_ADDR(&DisReq.Addr, + pAd->CommonCfg.Bssid); + DisReq.Reason = REASON_DISASSOC_STA_LEAVING; + + pMsgElem->Machine = ASSOC_STATE_MACHINE; + pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ; + pMsgElem->MsgLen = + sizeof(struct rt_mlme_disassoc_req); + NdisMoveMemory(pMsgElem->Msg, &DisReq, + sizeof + (struct rt_mlme_disassoc_req)); + + MlmeDisassocReqAction(pAd, pMsgElem); + kfree(pMsgElem); + + RTMPusecDelay(1000); + } + } + } + /* Set Radio off flag */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + + { + /* Link down first if any association exists */ + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + LinkDown(pAd, FALSE); + RTMPusecDelay(10000); + + /*========================================== */ + /* Clean up old bss table */ + BssTableInit(&pAd->ScanTab); + } + + /* Set LED */ + RTMPSetLED(pAd, LED_RADIO_OFF); + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) { + /* Must using 40MHz. */ + AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); + } else { + /* Must using 20MHz. */ + AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); + } + + /* Disable Tx/Rx DMA */ + RTUSBReadMACRegister(pAd, WPDMA_GLO_CFG, &GloCfg.word); /* disable DMA */ + GloCfg.field.EnableTxDMA = 0; + GloCfg.field.EnableRxDMA = 0; + RTUSBWriteMACRegister(pAd, WPDMA_GLO_CFG, GloCfg.word); /* abort all TX rings */ + + /* Waiting for DMA idle */ + i = 0; + do { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) + && (GloCfg.field.RxDMABusy == 0)) + break; + + RTMPusecDelay(1000); + } while (i++ < 100); + + /* Disable MAC Tx/Rx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= (0xfffffff3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + { + AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); + } +} + +#endif /* RTMP_MAC_USB // */ diff --git a/drivers/staging/rt2860/common/cmm_sanity.c b/drivers/staging/rt2860/common/cmm_sanity.c index 85855f7f38cb3abef4500262a4a7c87a12a4e89f..6b003c9034449b2c5c0346dab7a7e97adf41c17b 100644 --- a/drivers/staging/rt2860/common/cmm_sanity.c +++ b/drivers/staging/rt2860/common/cmm_sanity.c @@ -36,17 +36,16 @@ */ #include "../rt_config.h" +extern u8 CISCO_OUI[]; -extern UCHAR CISCO_OUI[]; - -extern UCHAR WPA_OUI[]; -extern UCHAR RSN_OUI[]; -extern UCHAR WME_INFO_ELEM[]; -extern UCHAR WME_PARM_ELEM[]; -extern UCHAR Ccx2QosInfo[]; -extern UCHAR RALINK_OUI[]; -extern UCHAR BROADCOM_OUI[]; -extern UCHAR WPS_OUI[]; +extern u8 WPA_OUI[]; +extern u8 RSN_OUI[]; +extern u8 WME_INFO_ELEM[]; +extern u8 WME_PARM_ELEM[]; +extern u8 Ccx2QosInfo[]; +extern u8 RALINK_OUI[]; +extern u8 BROADCOM_OUI[]; +extern u8 WPS_OUI[]; /* ========================================================================== @@ -59,35 +58,32 @@ extern UCHAR WPS_OUI[]; ========================================================================== */ -BOOLEAN MlmeAddBAReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2) +BOOLEAN MlmeAddBAReqSanity(struct rt_rtmp_adapter *pAd, + void * Msg, unsigned long MsgLen, u8 *pAddr2) { - PMLME_ADDBA_REQ_STRUCT pInfo; + struct rt_mlme_addba_req *pInfo; - pInfo = (MLME_ADDBA_REQ_STRUCT *)Msg; + pInfo = (struct rt_mlme_addba_req *)Msg; - if ((MsgLen != sizeof(MLME_ADDBA_REQ_STRUCT))) - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - message lenght not correct.\n")); - return FALSE; - } + if ((MsgLen != sizeof(struct rt_mlme_addba_req))) { + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeAddBAReqSanity fail - message lenght not correct.\n")); + return FALSE; + } - if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - The peer Mac is not associated yet.\n")); - return FALSE; - } + if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) { + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeAddBAReqSanity fail - The peer Mac is not associated yet.\n")); + return FALSE; + } - if ((pInfo->pAddr[0]&0x01) == 0x01) - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - broadcast address not support BA\n")); - return FALSE; - } + if ((pInfo->pAddr[0] & 0x01) == 0x01) { + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeAddBAReqSanity fail - broadcast address not support BA\n")); + return FALSE; + } - return TRUE; + return TRUE; } /* @@ -101,131 +97,133 @@ BOOLEAN MlmeAddBAReqSanity( ========================================================================== */ -BOOLEAN MlmeDelBAReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen) +BOOLEAN MlmeDelBAReqSanity(struct rt_rtmp_adapter *pAd, void * Msg, unsigned long MsgLen) { - MLME_DELBA_REQ_STRUCT *pInfo; - pInfo = (MLME_DELBA_REQ_STRUCT *)Msg; - - if ((MsgLen != sizeof(MLME_DELBA_REQ_STRUCT))) - { - DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - message lenght not correct.\n")); - return FALSE; - } - - if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) - { - DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer Mac is not associated yet.\n")); - return FALSE; - } - - if ((pInfo->TID & 0xf0)) - { - DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer TID is incorrect.\n")); - return FALSE; - } - - if (NdisEqualMemory(pAd->MacTab.Content[pInfo->Wcid].Addr, pInfo->Addr, MAC_ADDR_LEN) == 0) - { - DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - the peer addr dosen't exist.\n")); - return FALSE; - } - - return TRUE; + struct rt_mlme_delba_req *pInfo; + pInfo = (struct rt_mlme_delba_req *)Msg; + + if ((MsgLen != sizeof(struct rt_mlme_delba_req))) { + DBGPRINT(RT_DEBUG_ERROR, + ("MlmeDelBAReqSanity fail - message lenght not correct.\n")); + return FALSE; + } + + if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) { + DBGPRINT(RT_DEBUG_ERROR, + ("MlmeDelBAReqSanity fail - The peer Mac is not associated yet.\n")); + return FALSE; + } + + if ((pInfo->TID & 0xf0)) { + DBGPRINT(RT_DEBUG_ERROR, + ("MlmeDelBAReqSanity fail - The peer TID is incorrect.\n")); + return FALSE; + } + + if (NdisEqualMemory + (pAd->MacTab.Content[pInfo->Wcid].Addr, pInfo->Addr, + MAC_ADDR_LEN) == 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("MlmeDelBAReqSanity fail - the peer addr dosen't exist.\n")); + return FALSE; + } + + return TRUE; } -BOOLEAN PeerAddBAReqActionSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2) +BOOLEAN PeerAddBAReqActionSanity(struct rt_rtmp_adapter *pAd, + void * pMsg, + unsigned long MsgLen, u8 *pAddr2) { - PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; - PFRAME_ADDBA_REQ pAddFrame; - pAddFrame = (PFRAME_ADDBA_REQ)(pMsg); - if (MsgLen < (sizeof(FRAME_ADDBA_REQ))) - { - DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request frame length size = %ld incorrect\n", MsgLen)); + struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) pMsg; + struct rt_frame_addba_req * pAddFrame; + pAddFrame = (struct rt_frame_addba_req *) (pMsg); + if (MsgLen < (sizeof(struct rt_frame_addba_req))) { + DBGPRINT(RT_DEBUG_ERROR, + ("PeerAddBAReqActionSanity: ADDBA Request frame length size = %ld incorrect\n", + MsgLen)); return FALSE; } - // we support immediate BA. - *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm)); + /* we support immediate BA. */ + *(u16 *) (&pAddFrame->BaParm) = + cpu2le16(*(u16 *) (&pAddFrame->BaParm)); pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); pAddFrame->BaStartSeq.word = cpu2le16(pAddFrame->BaStartSeq.word); - if (pAddFrame->BaParm.BAPolicy != IMMED_BA) - { - DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy)); - DBGPRINT(RT_DEBUG_ERROR,("ADDBA Request. tid=%x, Bufsize=%x, AMSDUSupported=%x \n", pAddFrame->BaParm.TID, pAddFrame->BaParm.BufSize, pAddFrame->BaParm.AMSDUSupported)); + if (pAddFrame->BaParm.BAPolicy != IMMED_BA) { + DBGPRINT(RT_DEBUG_ERROR, + ("PeerAddBAReqActionSanity: ADDBA Request Ba Policy[%d] not support\n", + pAddFrame->BaParm.BAPolicy)); + DBGPRINT(RT_DEBUG_ERROR, + ("ADDBA Request. tid=%x, Bufsize=%x, AMSDUSupported=%x \n", + pAddFrame->BaParm.TID, pAddFrame->BaParm.BufSize, + pAddFrame->BaParm.AMSDUSupported)); return FALSE; } - - // we support immediate BA. - if (pAddFrame->BaParm.TID &0xfff0) - { - DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request incorrect TID = %d\n", pAddFrame->BaParm.TID)); + /* we support immediate BA. */ + if (pAddFrame->BaParm.TID & 0xfff0) { + DBGPRINT(RT_DEBUG_ERROR, + ("PeerAddBAReqActionSanity: ADDBA Request incorrect TID = %d\n", + pAddFrame->BaParm.TID)); return FALSE; } COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); return TRUE; } -BOOLEAN PeerAddBARspActionSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen) +BOOLEAN PeerAddBARspActionSanity(struct rt_rtmp_adapter *pAd, + void * pMsg, unsigned long MsgLen) { - PFRAME_ADDBA_RSP pAddFrame; + struct rt_frame_addba_rsp * pAddFrame; - pAddFrame = (PFRAME_ADDBA_RSP)(pMsg); - if (MsgLen < (sizeof(FRAME_ADDBA_RSP))) - { - DBGPRINT(RT_DEBUG_ERROR,("PeerAddBARspActionSanity: ADDBA Response frame length size = %ld incorrect\n", MsgLen)); + pAddFrame = (struct rt_frame_addba_rsp *) (pMsg); + if (MsgLen < (sizeof(struct rt_frame_addba_rsp))) { + DBGPRINT(RT_DEBUG_ERROR, + ("PeerAddBARspActionSanity: ADDBA Response frame length size = %ld incorrect\n", + MsgLen)); return FALSE; } - // we support immediate BA. - *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm)); + /* we support immediate BA. */ + *(u16 *) (&pAddFrame->BaParm) = + cpu2le16(*(u16 *) (&pAddFrame->BaParm)); pAddFrame->StatusCode = cpu2le16(pAddFrame->StatusCode); pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); - if (pAddFrame->BaParm.BAPolicy != IMMED_BA) - { - DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Response Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy)); + if (pAddFrame->BaParm.BAPolicy != IMMED_BA) { + DBGPRINT(RT_DEBUG_ERROR, + ("PeerAddBAReqActionSanity: ADDBA Response Ba Policy[%d] not support\n", + pAddFrame->BaParm.BAPolicy)); return FALSE; } - - // we support immediate BA. - if (pAddFrame->BaParm.TID &0xfff0) - { - DBGPRINT(RT_DEBUG_ERROR,("PeerAddBARspActionSanity: ADDBA Response incorrect TID = %d\n", pAddFrame->BaParm.TID)); + /* we support immediate BA. */ + if (pAddFrame->BaParm.TID & 0xfff0) { + DBGPRINT(RT_DEBUG_ERROR, + ("PeerAddBARspActionSanity: ADDBA Response incorrect TID = %d\n", + pAddFrame->BaParm.TID)); return FALSE; } return TRUE; } -BOOLEAN PeerDelBAActionSanity( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN VOID *pMsg, - IN ULONG MsgLen ) +BOOLEAN PeerDelBAActionSanity(struct rt_rtmp_adapter *pAd, + u8 Wcid, void * pMsg, unsigned long MsgLen) { - //PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; - PFRAME_DELBA_REQ pDelFrame; - if (MsgLen != (sizeof(FRAME_DELBA_REQ))) + /*struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *)pMsg; */ + struct rt_frame_delba_req * pDelFrame; + if (MsgLen != (sizeof(struct rt_frame_delba_req))) return FALSE; if (Wcid >= MAX_LEN_OF_MAC_TABLE) return FALSE; - pDelFrame = (PFRAME_DELBA_REQ)(pMsg); + pDelFrame = (struct rt_frame_delba_req *) (pMsg); - *(USHORT *)(&pDelFrame->DelbaParm) = cpu2le16(*(USHORT *)(&pDelFrame->DelbaParm)); + *(u16 *) (&pDelFrame->DelbaParm) = + cpu2le16(*(u16 *) (&pDelFrame->DelbaParm)); pDelFrame->ReasonCode = cpu2le16(pDelFrame->ReasonCode); - if (pDelFrame->DelbaParm.TID &0xfff0) + if (pDelFrame->DelbaParm.TID & 0xfff0) return FALSE; return TRUE; @@ -242,472 +240,469 @@ BOOLEAN PeerDelBAActionSanity( ========================================================================== */ -BOOLEAN PeerBeaconAndProbeRspSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - IN UCHAR MsgChannel, - OUT PUCHAR pAddr2, - OUT PUCHAR pBssid, - OUT CHAR Ssid[], - OUT UCHAR *pSsidLen, - OUT UCHAR *pBssType, - OUT USHORT *pBeaconPeriod, - OUT UCHAR *pChannel, - OUT UCHAR *pNewChannel, - OUT LARGE_INTEGER *pTimestamp, - OUT CF_PARM *pCfParm, - OUT USHORT *pAtimWin, - OUT USHORT *pCapabilityInfo, - OUT UCHAR *pErp, - OUT UCHAR *pDtimCount, - OUT UCHAR *pDtimPeriod, - OUT UCHAR *pBcastFlag, - OUT UCHAR *pMessageToMe, - OUT UCHAR SupRate[], - OUT UCHAR *pSupRateLen, - OUT UCHAR ExtRate[], - OUT UCHAR *pExtRateLen, - OUT UCHAR *pCkipFlag, - OUT UCHAR *pAironetCellPowerLimit, - OUT PEDCA_PARM pEdcaParm, - OUT PQBSS_LOAD_PARM pQbssLoad, - OUT PQOS_CAPABILITY_PARM pQosCapability, - OUT ULONG *pRalinkIe, - OUT UCHAR *pHtCapabilityLen, - OUT UCHAR *pPreNHtCapabilityLen, - OUT HT_CAPABILITY_IE *pHtCapability, - OUT UCHAR *AddHtInfoLen, - OUT ADD_HT_INFO_IE *AddHtInfo, - OUT UCHAR *NewExtChannelOffset, // Ht extension channel offset(above or below) - OUT USHORT *LengthVIE, - OUT PNDIS_802_11_VARIABLE_IEs pVIE) +BOOLEAN PeerBeaconAndProbeRspSanity(struct rt_rtmp_adapter *pAd, void * Msg, unsigned long MsgLen, u8 MsgChannel, u8 *pAddr2, u8 *pBssid, char Ssid[], u8 * pSsidLen, u8 * pBssType, u16 * pBeaconPeriod, u8 * pChannel, u8 * pNewChannel, OUT LARGE_INTEGER * pTimestamp, struct rt_cf_parm * pCfParm, u16 * pAtimWin, u16 * pCapabilityInfo, u8 * pErp, u8 * pDtimCount, u8 * pDtimPeriod, u8 * pBcastFlag, u8 * pMessageToMe, u8 SupRate[], u8 * pSupRateLen, u8 ExtRate[], u8 * pExtRateLen, u8 * pCkipFlag, u8 * pAironetCellPowerLimit, struct rt_edca_parm *pEdcaParm, struct rt_qbss_load_parm *pQbssLoad, struct rt_qos_capability_parm *pQosCapability, unsigned long * pRalinkIe, u8 * pHtCapabilityLen, u8 * pPreNHtCapabilityLen, struct rt_ht_capability_ie * pHtCapability, u8 * AddHtInfoLen, struct rt_add_ht_info_ie * AddHtInfo, u8 * NewExtChannelOffset, /* Ht extension channel offset(above or below) */ + u16 * LengthVIE, + struct rt_ndis_802_11_variable_ies *pVIE) { - CHAR *Ptr; - CHAR TimLen; - PFRAME_802_11 pFrame; - PEID_STRUCT pEid; - UCHAR SubType; - UCHAR Sanity; - //UCHAR ECWMin, ECWMax; - //MAC_CSR9_STRUC Csr9; - ULONG Length = 0; - - // For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel - // 1. If the AP is 11n enabled, then check the control channel. - // 2. If the AP didn't have any info about channel, use the channel we received this frame as the channel. (May inaccuracy!!) - UCHAR CtrlChannel = 0; - - // Add for 3 necessary EID field check - Sanity = 0; - - *pAtimWin = 0; - *pErp = 0; - *pDtimCount = 0; - *pDtimPeriod = 0; - *pBcastFlag = 0; - *pMessageToMe = 0; - *pExtRateLen = 0; - *pCkipFlag = 0; // Default of CkipFlag is 0 - *pAironetCellPowerLimit = 0xFF; // Default of AironetCellPowerLimit is 0xFF - *LengthVIE = 0; // Set the length of VIE to init value 0 - *pHtCapabilityLen = 0; // Set the length of VIE to init value 0 + u8 *Ptr; + u8 TimLen; + struct rt_frame_802_11 * pFrame; + struct rt_eid * pEid; + u8 SubType; + u8 Sanity; + /*u8 ECWMin, ECWMax; */ + /*MAC_CSR9_STRUC Csr9; */ + unsigned long Length = 0; + + /* For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel */ + /* 1. If the AP is 11n enabled, then check the control channel. */ + /* 2. If the AP didn't have any info about channel, use the channel we received this frame as the channel. (May inaccuracy!) */ + u8 CtrlChannel = 0; + + /* Add for 3 necessary EID field check */ + Sanity = 0; + + *pAtimWin = 0; + *pErp = 0; + *pDtimCount = 0; + *pDtimPeriod = 0; + *pBcastFlag = 0; + *pMessageToMe = 0; + *pExtRateLen = 0; + *pCkipFlag = 0; /* Default of CkipFlag is 0 */ + *pAironetCellPowerLimit = 0xFF; /* Default of AironetCellPowerLimit is 0xFF */ + *LengthVIE = 0; /* Set the length of VIE to init value 0 */ + *pHtCapabilityLen = 0; /* Set the length of VIE to init value 0 */ if (pAd->OpMode == OPMODE_STA) - *pPreNHtCapabilityLen = 0; // Set the length of VIE to init value 0 - *AddHtInfoLen = 0; // Set the length of VIE to init value 0 - *pRalinkIe = 0; - *pNewChannel = 0; - *NewExtChannelOffset = 0xff; //Default 0xff means no such IE - pCfParm->bValid = FALSE; // default: no IE_CF found - pQbssLoad->bValid = FALSE; // default: no IE_QBSS_LOAD found - pEdcaParm->bValid = FALSE; // default: no IE_EDCA_PARAMETER found - pQosCapability->bValid = FALSE; // default: no IE_QOS_CAPABILITY found + *pPreNHtCapabilityLen = 0; /* Set the length of VIE to init value 0 */ + *AddHtInfoLen = 0; /* Set the length of VIE to init value 0 */ + *pRalinkIe = 0; + *pNewChannel = 0; + *NewExtChannelOffset = 0xff; /*Default 0xff means no such IE */ + pCfParm->bValid = FALSE; /* default: no IE_CF found */ + pQbssLoad->bValid = FALSE; /* default: no IE_QBSS_LOAD found */ + pEdcaParm->bValid = FALSE; /* default: no IE_EDCA_PARAMETER found */ + pQosCapability->bValid = FALSE; /* default: no IE_QOS_CAPABILITY found */ + + pFrame = (struct rt_frame_802_11 *) Msg; + + /* get subtype from header */ + SubType = (u8)pFrame->Hdr.FC.SubType; + + /* get Addr2 and BSSID from header */ + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3); - pFrame = (PFRAME_802_11)Msg; + Ptr = pFrame->Octet; + Length += LENGTH_802_11; - // get subtype from header - SubType = (UCHAR)pFrame->Hdr.FC.SubType; + /* get timestamp from payload and advance the pointer */ + NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN); - // get Addr2 and BSSID from header - COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); - COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3); + pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart); + pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart); - Ptr = pFrame->Octet; - Length += LENGTH_802_11; + Ptr += TIMESTAMP_LEN; + Length += TIMESTAMP_LEN; - // get timestamp from payload and advance the pointer - NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN); + /* get beacon interval from payload and advance the pointer */ + NdisMoveMemory(pBeaconPeriod, Ptr, 2); + Ptr += 2; + Length += 2; - pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart); - pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart); + /* get capability info from payload and advance the pointer */ + NdisMoveMemory(pCapabilityInfo, Ptr, 2); + Ptr += 2; + Length += 2; + + if (CAP_IS_ESS_ON(*pCapabilityInfo)) + *pBssType = BSS_INFRA; + else + *pBssType = BSS_ADHOC; + + pEid = (struct rt_eid *) Ptr; + + /* get variable fields from payload and advance the pointer */ + while ((Length + 2 + pEid->Len) <= MsgLen) { + /* */ + /* Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow. */ + /* */ + if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN) { + DBGPRINT(RT_DEBUG_WARN, + ("PeerBeaconAndProbeRspSanity - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", + (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN)); + break; + } - Ptr += TIMESTAMP_LEN; - Length += TIMESTAMP_LEN; - - // get beacon interval from payload and advance the pointer - NdisMoveMemory(pBeaconPeriod, Ptr, 2); - Ptr += 2; - Length += 2; - - // get capability info from payload and advance the pointer - NdisMoveMemory(pCapabilityInfo, Ptr, 2); - Ptr += 2; - Length += 2; - - if (CAP_IS_ESS_ON(*pCapabilityInfo)) - *pBssType = BSS_INFRA; - else - *pBssType = BSS_ADHOC; - - pEid = (PEID_STRUCT) Ptr; - - // get variable fields from payload and advance the pointer - while ((Length + 2 + pEid->Len) <= MsgLen) - { - // - // Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow. - // - if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN) - { - DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", - (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN)); - break; - } - - switch(pEid->Eid) - { - case IE_SSID: - // Already has one SSID EID in this beacon, ignore the second one - if (Sanity & 0x1) - break; - if(pEid->Len <= MAX_LEN_OF_SSID) - { - NdisMoveMemory(Ssid, pEid->Octet, pEid->Len); - *pSsidLen = pEid->Len; - Sanity |= 0x1; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len)); - return FALSE; - } - break; - - case IE_SUPP_RATES: - if(pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) - { - Sanity |= 0x2; - NdisMoveMemory(SupRate, pEid->Octet, pEid->Len); - *pSupRateLen = pEid->Len; - - // TODO: 2004-09-14 not a good design here, cause it exclude extra rates - // from ScanTab. We should report as is. And filter out unsupported - // rates in MlmeAux. - // Check against the supported rates - // RTMPCheckRates(pAd, SupRate, pSupRateLen); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_RATES (len=%d)\n",pEid->Len)); - return FALSE; - } - break; - - case IE_HT_CAP: - if (pEid->Len >= SIZE_HT_CAP_IE) //Note: allow extension.!! + switch (pEid->Eid) { + case IE_SSID: + /* Already has one SSID EID in this beacon, ignore the second one */ + if (Sanity & 0x1) + break; + if (pEid->Len <= MAX_LEN_OF_SSID) { + NdisMoveMemory(Ssid, pEid->Octet, pEid->Len); + *pSsidLen = pEid->Len; + Sanity |= 0x1; + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n", + pEid->Len)); + return FALSE; + } + break; + + case IE_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) { + Sanity |= 0x2; + NdisMoveMemory(SupRate, pEid->Octet, pEid->Len); + *pSupRateLen = pEid->Len; + + /* TODO: 2004-09-14 not a good design here, cause it exclude extra rates */ + /* from ScanTab. We should report as is. And filter out unsupported */ + /* rates in MlmeAux. */ + /* Check against the supported rates */ + /* RTMPCheckRates(pAd, SupRate, pSupRateLen); */ + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_RATES (len=%d)\n", + pEid->Len)); + return FALSE; + } + break; + + case IE_HT_CAP: + if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension! */ { - NdisMoveMemory(pHtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE)); - *pHtCapabilityLen = SIZE_HT_CAP_IE; // Nnow we only support 26 bytes. + NdisMoveMemory(pHtCapability, pEid->Octet, + sizeof(struct rt_ht_capability_ie)); + *pHtCapabilityLen = SIZE_HT_CAP_IE; /* Nnow we only support 26 bytes. */ - *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); - *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + *(u16 *) (&pHtCapability->HtCapInfo) = + cpu2le16(*(u16 *) + (&pHtCapability->HtCapInfo)); + *(u16 *) (&pHtCapability->ExtHtCapInfo) = + cpu2le16(*(u16 *) + (&pHtCapability->ExtHtCapInfo)); { - *pPreNHtCapabilityLen = 0; // Nnow we only support 26 bytes. + *pPreNHtCapabilityLen = 0; /* Nnow we only support 26 bytes. */ - Ptr = (PUCHAR) pVIE; - NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + Ptr = (u8 *)pVIE; + NdisMoveMemory(Ptr + *LengthVIE, + &pEid->Eid, + pEid->Len + 2); *LengthVIE += (pEid->Len + 2); } - } - else - { - DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_HT_CAP. pEid->Len = %d\n", pEid->Len)); + } else { + DBGPRINT(RT_DEBUG_WARN, + ("PeerBeaconAndProbeRspSanity - wrong IE_HT_CAP. pEid->Len = %d\n", + pEid->Len)); } - break; - case IE_ADD_HT: - if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) - { - // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only - // copy first sizeof(ADD_HT_INFO_IE) - NdisMoveMemory(AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); + break; + case IE_ADD_HT: + if (pEid->Len >= sizeof(struct rt_add_ht_info_ie)) { + /* This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only */ + /* copy first sizeof(struct rt_add_ht_info_ie) */ + NdisMoveMemory(AddHtInfo, pEid->Octet, + sizeof(struct rt_add_ht_info_ie)); *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; CtrlChannel = AddHtInfo->ControlChan; - *(USHORT *)(&AddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo2)); - *(USHORT *)(&AddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo3)); + *(u16 *) (&AddHtInfo->AddHtInfo2) = + cpu2le16(*(u16 *) + (&AddHtInfo->AddHtInfo2)); + *(u16 *) (&AddHtInfo->AddHtInfo3) = + cpu2le16(*(u16 *) + (&AddHtInfo->AddHtInfo3)); { - Ptr = (PUCHAR) pVIE; - NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); - *LengthVIE += (pEid->Len + 2); + Ptr = (u8 *)pVIE; + NdisMoveMemory(Ptr + *LengthVIE, + &pEid->Eid, + pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); } - } - else - { - DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_ADD_HT. \n")); + } else { + DBGPRINT(RT_DEBUG_WARN, + ("PeerBeaconAndProbeRspSanity - wrong IE_ADD_HT. \n")); } - break; - case IE_SECONDARY_CH_OFFSET: - if (pEid->Len == 1) - { + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) { *NewExtChannelOffset = pEid->Octet[0]; - } - else - { - DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); + } else { + DBGPRINT(RT_DEBUG_WARN, + ("PeerBeaconAndProbeRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); } - break; - case IE_FH_PARM: - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity(IE_FH_PARM) \n")); - break; + break; + case IE_FH_PARM: + DBGPRINT(RT_DEBUG_TRACE, + ("PeerBeaconAndProbeRspSanity(IE_FH_PARM) \n")); + break; - case IE_DS_PARM: - if(pEid->Len == 1) - { - *pChannel = *pEid->Octet; + case IE_DS_PARM: + if (pEid->Len == 1) { + *pChannel = *pEid->Octet; - { - if (ChannelSanity(pAd, *pChannel) == 0) - { + { + if (ChannelSanity(pAd, *pChannel) == 0) { - return FALSE; - } + return FALSE; } + } + + Sanity |= 0x4; + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerBeaconAndProbeRspSanity - wrong IE_DS_PARM (len=%d)\n", + pEid->Len)); + return FALSE; + } + break; + + case IE_CF_PARM: + if (pEid->Len == 6) { + pCfParm->bValid = TRUE; + pCfParm->CfpCount = pEid->Octet[0]; + pCfParm->CfpPeriod = pEid->Octet[1]; + pCfParm->CfpMaxDuration = + pEid->Octet[2] + 256 * pEid->Octet[3]; + pCfParm->CfpDurRemaining = + pEid->Octet[4] + 256 * pEid->Octet[5]; + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerBeaconAndProbeRspSanity - wrong IE_CF_PARM\n")); + return FALSE; + } + break; + + case IE_IBSS_PARM: + if (pEid->Len == 2) { + NdisMoveMemory(pAtimWin, pEid->Octet, + pEid->Len); + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerBeaconAndProbeRspSanity - wrong IE_IBSS_PARM\n")); + return FALSE; + } + break; + + case IE_TIM: + if (INFRA_ON(pAd) && SubType == SUBTYPE_BEACON) { + GetTimBit((char *)pEid, pAd->StaActive.Aid, + &TimLen, pBcastFlag, pDtimCount, + pDtimPeriod, pMessageToMe); + } + break; + case IE_CHANNEL_SWITCH_ANNOUNCEMENT: + if (pEid->Len == 3) { + *pNewChannel = pEid->Octet[1]; /*extract new channel number */ + } + break; + + /* New for WPA */ + /* CCX v2 has the same IE, we need to parse that too */ + /* Wifi WMM use the same IE vale, need to parse that too */ + /* case IE_WPA: */ + case IE_VENDOR_SPECIFIC: + /* Check Broadcom/Atheros 802.11n OUI version, for HT Capability IE. */ + /* This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan. */ + /*if (NdisEqualMemory(pEid->Octet, BROADCOM_OUI, 3) && (pEid->Len >= 4)) + { + if ((pEid->Octet[3] == OUI_BROADCOM_HT) && (pEid->Len >= 30)) + { + { + NdisMoveMemory(pHtCapability, &pEid->Octet[4], sizeof(struct rt_ht_capability_ie)); + *pHtCapabilityLen = SIZE_HT_CAP_IE; // Nnow we only support 26 bytes. + } + } + if ((pEid->Octet[3] == OUI_BROADCOM_HT) && (pEid->Len >= 26)) + { + { + NdisMoveMemory(AddHtInfo, &pEid->Octet[4], sizeof(struct rt_add_ht_info_ie)); + *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; // Nnow we only support 26 bytes. + } + } + } + */ + /* Check the OUI version, filter out non-standard usage */ + if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) + && (pEid->Len == 7)) { + /**pRalinkIe = pEid->Octet[3]; */ + if (pEid->Octet[3] != 0) + *pRalinkIe = pEid->Octet[3]; + else + *pRalinkIe = 0xf0000000; /* Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag. */ + } + /* This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan. */ + + /* Other vendors had production before IE_HT_CAP value is assigned. To backward support those old-firmware AP, */ + /* Check broadcom-defiend pre-802.11nD1.0 OUI for HT related IE, including HT Capatilities IE and HT Information IE */ + else if ((*pHtCapabilityLen == 0) + && NdisEqualMemory(pEid->Octet, PRE_N_HT_OUI, + 3) && (pEid->Len >= 4) + && (pAd->OpMode == OPMODE_STA)) { + if ((pEid->Octet[3] == OUI_PREN_HT_CAP) + && (pEid->Len >= 30) + && (*pHtCapabilityLen == 0)) { + NdisMoveMemory(pHtCapability, + &pEid->Octet[4], + sizeof + (struct rt_ht_capability_ie)); + *pPreNHtCapabilityLen = SIZE_HT_CAP_IE; + } + + if ((pEid->Octet[3] == OUI_PREN_ADD_HT) + && (pEid->Len >= 26)) { + NdisMoveMemory(AddHtInfo, + &pEid->Octet[4], + sizeof(struct rt_add_ht_info_ie)); + *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; + } + } else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) { + /* Copy to pVIE which will report to microsoft bssid list. */ + Ptr = (u8 *)pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, + pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } else + if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) + && (pEid->Len == 24)) { + u8 *ptr; + int i; + + /* parsing EDCA parameters */ + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10; */ + pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20; */ + pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40; */ + pEdcaParm->EdcaUpdateCount = + pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = + (pEid->Octet[6] & 0x80) ? 1 : 0; + ptr = &pEid->Octet[8]; + for (i = 0; i < 4; i++) { + u8 aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX */ + pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM */ + pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN */ + pEdcaParm->Cwmin[aci] = *(ptr + 1) & 0x0f; /* b0~4 is Cwmin */ + pEdcaParm->Cwmax[aci] = *(ptr + 1) >> 4; /* b5~8 is Cwmax */ + pEdcaParm->Txop[aci] = *(ptr + 2) + 256 * (*(ptr + 3)); /* in unit of 32-us */ + ptr += 4; /* point to next AC */ + } + } else + if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) + && (pEid->Len == 7)) { + /* parsing EDCA parameters */ + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10; */ + pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20; */ + pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40; */ + pEdcaParm->EdcaUpdateCount = + pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = + (pEid->Octet[6] & 0x80) ? 1 : 0; + + /* use default EDCA parameter */ + pEdcaParm->bACM[QID_AC_BE] = 0; + pEdcaParm->Aifsn[QID_AC_BE] = 3; + pEdcaParm->Cwmin[QID_AC_BE] = CW_MIN_IN_BITS; + pEdcaParm->Cwmax[QID_AC_BE] = CW_MAX_IN_BITS; + pEdcaParm->Txop[QID_AC_BE] = 0; + + pEdcaParm->bACM[QID_AC_BK] = 0; + pEdcaParm->Aifsn[QID_AC_BK] = 7; + pEdcaParm->Cwmin[QID_AC_BK] = CW_MIN_IN_BITS; + pEdcaParm->Cwmax[QID_AC_BK] = CW_MAX_IN_BITS; + pEdcaParm->Txop[QID_AC_BK] = 0; + + pEdcaParm->bACM[QID_AC_VI] = 0; + pEdcaParm->Aifsn[QID_AC_VI] = 2; + pEdcaParm->Cwmin[QID_AC_VI] = + CW_MIN_IN_BITS - 1; + pEdcaParm->Cwmax[QID_AC_VI] = CW_MAX_IN_BITS; + pEdcaParm->Txop[QID_AC_VI] = 96; /* AC_VI: 96*32us ~= 3ms */ + + pEdcaParm->bACM[QID_AC_VO] = 0; + pEdcaParm->Aifsn[QID_AC_VO] = 2; + pEdcaParm->Cwmin[QID_AC_VO] = + CW_MIN_IN_BITS - 2; + pEdcaParm->Cwmax[QID_AC_VO] = + CW_MAX_IN_BITS - 1; + pEdcaParm->Txop[QID_AC_VO] = 48; /* AC_VO: 48*32us ~= 1.5ms */ + } + + break; + + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) { + NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); + *pExtRateLen = pEid->Len; + + /* TODO: 2004-09-14 not a good design here, cause it exclude extra rates */ + /* from ScanTab. We should report as is. And filter out unsupported */ + /* rates in MlmeAux. */ + /* Check against the supported rates */ + /* RTMPCheckRates(pAd, ExtRate, pExtRateLen); */ + } + break; + + case IE_ERP: + if (pEid->Len == 1) { + *pErp = (u8)pEid->Octet[0]; + } + break; + + case IE_AIRONET_CKIP: + /* 0. Check Aironet IE length, it must be larger or equal to 28 */ + /* Cisco AP350 used length as 28 */ + /* Cisco AP12XX used length as 30 */ + if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) + break; + + /* 1. Copy CKIP flag byte to buffer for process */ + *pCkipFlag = *(pEid->Octet + 8); + break; + + case IE_AP_TX_POWER: + /* AP Control of Client Transmit Power */ + /*0. Check Aironet IE length, it must be 6 */ + if (pEid->Len != 0x06) + break; + + /* Get cell power limit in dBm */ + if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) + *pAironetCellPowerLimit = *(pEid->Octet + 4); + break; + + /* WPA2 & 802.11i RSN */ + case IE_RSN: + /* There is no OUI for version anymore, check the group cipher OUI before copying */ + if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) { + /* Copy to pVIE which will report to microsoft bssid list. */ + Ptr = (u8 *)pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, + pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + break; + + default: + break; + } - Sanity |= 0x4; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_DS_PARM (len=%d)\n",pEid->Len)); - return FALSE; - } - break; - - case IE_CF_PARM: - if(pEid->Len == 6) - { - pCfParm->bValid = TRUE; - pCfParm->CfpCount = pEid->Octet[0]; - pCfParm->CfpPeriod = pEid->Octet[1]; - pCfParm->CfpMaxDuration = pEid->Octet[2] + 256 * pEid->Octet[3]; - pCfParm->CfpDurRemaining = pEid->Octet[4] + 256 * pEid->Octet[5]; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_CF_PARM\n")); - return FALSE; - } - break; - - case IE_IBSS_PARM: - if(pEid->Len == 2) - { - NdisMoveMemory(pAtimWin, pEid->Octet, pEid->Len); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_IBSS_PARM\n")); - return FALSE; - } - break; - - case IE_TIM: - if(INFRA_ON(pAd) && SubType == SUBTYPE_BEACON) - { - GetTimBit((PUCHAR)pEid, pAd->StaActive.Aid, &TimLen, pBcastFlag, pDtimCount, pDtimPeriod, pMessageToMe); - } - break; - - case IE_CHANNEL_SWITCH_ANNOUNCEMENT: - if(pEid->Len == 3) - { - *pNewChannel = pEid->Octet[1]; //extract new channel number - } - break; - - // New for WPA - // CCX v2 has the same IE, we need to parse that too - // Wifi WMM use the same IE vale, need to parse that too - // case IE_WPA: - case IE_VENDOR_SPECIFIC: - // Check the OUI version, filter out non-standard usage - if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 7)) - { - //*pRalinkIe = pEid->Octet[3]; - if (pEid->Octet[3] != 0) - *pRalinkIe = pEid->Octet[3]; - else - *pRalinkIe = 0xf0000000; // Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag. - } - // This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan. - - // Other vendors had production before IE_HT_CAP value is assigned. To backward support those old-firmware AP, - // Check broadcom-defiend pre-802.11nD1.0 OUI for HT related IE, including HT Capatilities IE and HT Information IE - else if ((*pHtCapabilityLen == 0) && NdisEqualMemory(pEid->Octet, PRE_N_HT_OUI, 3) && (pEid->Len >= 4) && (pAd->OpMode == OPMODE_STA)) - { - if ((pEid->Octet[3] == OUI_PREN_HT_CAP) && (pEid->Len >= 30) && (*pHtCapabilityLen == 0)) - { - NdisMoveMemory(pHtCapability, &pEid->Octet[4], sizeof(HT_CAPABILITY_IE)); - *pPreNHtCapabilityLen = SIZE_HT_CAP_IE; - } - - if ((pEid->Octet[3] == OUI_PREN_ADD_HT) && (pEid->Len >= 26)) - { - NdisMoveMemory(AddHtInfo, &pEid->Octet[4], sizeof(ADD_HT_INFO_IE)); - *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; - } - } - else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) - { - // Copy to pVIE which will report to microsoft bssid list. - Ptr = (PUCHAR) pVIE; - NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); - *LengthVIE += (pEid->Len + 2); - } - else if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) - { - PUCHAR ptr; - int i; - - // parsing EDCA parameters - pEdcaParm->bValid = TRUE; - pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10; - pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20; - pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40; - pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; - pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; - ptr = &pEid->Octet[8]; - for (i=0; i<4; i++) - { - UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX - pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); // b5 is ACM - pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; // b0~3 is AIFSN - pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; // b0~4 is Cwmin - pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; // b5~8 is Cwmax - pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us - ptr += 4; // point to next AC - } - } - else if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7)) - { - // parsing EDCA parameters - pEdcaParm->bValid = TRUE; - pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10; - pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20; - pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40; - pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; - pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; - - // use default EDCA parameter - pEdcaParm->bACM[QID_AC_BE] = 0; - pEdcaParm->Aifsn[QID_AC_BE] = 3; - pEdcaParm->Cwmin[QID_AC_BE] = CW_MIN_IN_BITS; - pEdcaParm->Cwmax[QID_AC_BE] = CW_MAX_IN_BITS; - pEdcaParm->Txop[QID_AC_BE] = 0; - - pEdcaParm->bACM[QID_AC_BK] = 0; - pEdcaParm->Aifsn[QID_AC_BK] = 7; - pEdcaParm->Cwmin[QID_AC_BK] = CW_MIN_IN_BITS; - pEdcaParm->Cwmax[QID_AC_BK] = CW_MAX_IN_BITS; - pEdcaParm->Txop[QID_AC_BK] = 0; - - pEdcaParm->bACM[QID_AC_VI] = 0; - pEdcaParm->Aifsn[QID_AC_VI] = 2; - pEdcaParm->Cwmin[QID_AC_VI] = CW_MIN_IN_BITS-1; - pEdcaParm->Cwmax[QID_AC_VI] = CW_MAX_IN_BITS; - pEdcaParm->Txop[QID_AC_VI] = 96; // AC_VI: 96*32us ~= 3ms - - pEdcaParm->bACM[QID_AC_VO] = 0; - pEdcaParm->Aifsn[QID_AC_VO] = 2; - pEdcaParm->Cwmin[QID_AC_VO] = CW_MIN_IN_BITS-2; - pEdcaParm->Cwmax[QID_AC_VO] = CW_MAX_IN_BITS-1; - pEdcaParm->Txop[QID_AC_VO] = 48; // AC_VO: 48*32us ~= 1.5ms - } - break; - - case IE_EXT_SUPP_RATES: - if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) - { - NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); - *pExtRateLen = pEid->Len; - - // TODO: 2004-09-14 not a good design here, cause it exclude extra rates - // from ScanTab. We should report as is. And filter out unsupported - // rates in MlmeAux. - // Check against the supported rates - // RTMPCheckRates(pAd, ExtRate, pExtRateLen); - } - break; - - case IE_ERP: - if (pEid->Len == 1) - { - *pErp = (UCHAR)pEid->Octet[0]; - } - break; - - case IE_AIRONET_CKIP: - // 0. Check Aironet IE length, it must be larger or equal to 28 - // Cisco AP350 used length as 28 - // Cisco AP12XX used length as 30 - if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) - break; - - // 1. Copy CKIP flag byte to buffer for process - *pCkipFlag = *(pEid->Octet + 8); - break; - - case IE_AP_TX_POWER: - // AP Control of Client Transmit Power - //0. Check Aironet IE length, it must be 6 - if (pEid->Len != 0x06) - break; - - // Get cell power limit in dBm - if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) - *pAironetCellPowerLimit = *(pEid->Octet + 4); - break; - - // WPA2 & 802.11i RSN - case IE_RSN: - // There is no OUI for version anymore, check the group cipher OUI before copying - if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) - { - // Copy to pVIE which will report to microsoft bssid list. - Ptr = (PUCHAR) pVIE; - NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); - *LengthVIE += (pEid->Len + 2); - } - break; - - default: - break; - } - - Length = Length + 2 + pEid->Len; // Eid[1] + Len[1]+ content[Len] - pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); - } - - // For some 11a AP. it did not have the channel EID, patch here + Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ + pEid = (struct rt_eid *) ((u8 *) pEid + 2 + pEid->Len); + } + + /* For some 11a AP. it did not have the channel EID, patch here */ { - UCHAR LatchRfChannel = MsgChannel; - if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0)) - { + u8 LatchRfChannel = MsgChannel; + if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0)) { if (CtrlChannel != 0) *pChannel = CtrlChannel; else @@ -716,13 +711,12 @@ BOOLEAN PeerBeaconAndProbeRspSanity( } } - if (Sanity != 0x7) - { - DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - missing field, Sanity=0x%02x\n", Sanity)); + if (Sanity != 0x7) { + DBGPRINT(RT_DEBUG_LOUD, + ("PeerBeaconAndProbeRspSanity - missing field, Sanity=0x%02x\n", + Sanity)); return FALSE; - } - else - { + } else { return TRUE; } @@ -736,51 +730,42 @@ BOOLEAN PeerBeaconAndProbeRspSanity( TRUE if all parameters are OK, FALSE otherwise ========================================================================== */ -BOOLEAN MlmeScanReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT UCHAR *pBssType, - OUT CHAR Ssid[], - OUT UCHAR *pSsidLen, - OUT UCHAR *pScanType) +BOOLEAN MlmeScanReqSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 * pBssType, + char Ssid[], + u8 * pSsidLen, u8 * pScanType) { - MLME_SCAN_REQ_STRUCT *Info; + struct rt_mlme_scan_req *Info; - Info = (MLME_SCAN_REQ_STRUCT *)(Msg); + Info = (struct rt_mlme_scan_req *)(Msg); *pBssType = Info->BssType; *pSsidLen = Info->SsidLen; NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen); *pScanType = Info->ScanType; - if ((*pBssType == BSS_INFRA || *pBssType == BSS_ADHOC || *pBssType == BSS_ANY) - && (*pScanType == SCAN_ACTIVE || *pScanType == SCAN_PASSIVE - || *pScanType == SCAN_CISCO_PASSIVE || *pScanType == SCAN_CISCO_ACTIVE - || *pScanType == SCAN_CISCO_CHANNEL_LOAD || *pScanType == SCAN_CISCO_NOISE - )) - { + if ((*pBssType == BSS_INFRA || *pBssType == BSS_ADHOC + || *pBssType == BSS_ANY) + && (*pScanType == SCAN_ACTIVE || *pScanType == SCAN_PASSIVE)) { return TRUE; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqSanity fail - wrong BssType or ScanType\n")); + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeScanReqSanity fail - wrong BssType or ScanType\n")); return FALSE; } } -// IRQL = DISPATCH_LEVEL -UCHAR ChannelSanity( - IN PRTMP_ADAPTER pAd, - IN UCHAR channel) +/* IRQL = DISPATCH_LEVEL */ +u8 ChannelSanity(struct rt_rtmp_adapter *pAd, u8 channel) { - int i; - - for (i = 0; i < pAd->ChannelListNum; i ++) - { - if (channel == pAd->ChannelList[i].Channel) - return 1; - } - return 0; + int i; + + for (i = 0; i < pAd->ChannelListNum; i++) { + if (channel == pAd->ChannelList[i].Channel) + return 1; + } + return 0; } /* @@ -794,19 +779,17 @@ UCHAR ChannelSanity( ========================================================================== */ -BOOLEAN PeerDeauthSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *pReason) +BOOLEAN PeerDeauthSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 *pAddr2, u16 * pReason) { - PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg; - COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); - NdisMoveMemory(pReason, &pFrame->Octet[0], 2); + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + NdisMoveMemory(pReason, &pFrame->Octet[0], 2); - return TRUE; + return TRUE; } /* @@ -820,58 +803,46 @@ BOOLEAN PeerDeauthSanity( ========================================================================== */ -BOOLEAN PeerAuthSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr, - OUT USHORT *pAlg, - OUT USHORT *pSeq, - OUT USHORT *pStatus, - CHAR *pChlgText) +BOOLEAN PeerAuthSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 *pAddr, + u16 * pAlg, + u16 * pSeq, + u16 * pStatus, char * pChlgText) { - PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; - - COPY_MAC_ADDR(pAddr, pFrame->Hdr.Addr2); - NdisMoveMemory(pAlg, &pFrame->Octet[0], 2); - NdisMoveMemory(pSeq, &pFrame->Octet[2], 2); - NdisMoveMemory(pStatus, &pFrame->Octet[4], 2); - - if ((*pAlg == Ndis802_11AuthModeOpen) - ) - { - if (*pSeq == 1 || *pSeq == 2) - { - return TRUE; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n")); - return FALSE; - } - } - else if (*pAlg == Ndis802_11AuthModeShared) - { - if (*pSeq == 1 || *pSeq == 4) - { - return TRUE; - } - else if (*pSeq == 2 || *pSeq == 3) - { - NdisMoveMemory(pChlgText, &pFrame->Octet[8], CIPHER_TEXT_LEN); - return TRUE; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n")); - return FALSE; - } - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong algorithm\n")); - return FALSE; - } + struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg; + + COPY_MAC_ADDR(pAddr, pFrame->Hdr.Addr2); + NdisMoveMemory(pAlg, &pFrame->Octet[0], 2); + NdisMoveMemory(pSeq, &pFrame->Octet[2], 2); + NdisMoveMemory(pStatus, &pFrame->Octet[4], 2); + + if (*pAlg == AUTH_MODE_OPEN) { + if (*pSeq == 1 || *pSeq == 2) { + return TRUE; + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerAuthSanity fail - wrong Seg#\n")); + return FALSE; + } + } else if (*pAlg == AUTH_MODE_KEY) { + if (*pSeq == 1 || *pSeq == 4) { + return TRUE; + } else if (*pSeq == 2 || *pSeq == 3) { + NdisMoveMemory(pChlgText, &pFrame->Octet[8], + CIPHER_TEXT_LEN); + return TRUE; + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerAuthSanity fail - wrong Seg#\n")); + return FALSE; + } + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerAuthSanity fail - wrong algorithm\n")); + return FALSE; + } } /* @@ -882,32 +853,27 @@ BOOLEAN PeerAuthSanity( TRUE if all parameters are OK, FALSE otherwise ========================================================================== */ -BOOLEAN MlmeAuthReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr, - OUT ULONG *pTimeout, - OUT USHORT *pAlg) +BOOLEAN MlmeAuthReqSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 *pAddr, + unsigned long * pTimeout, u16 * pAlg) { - MLME_AUTH_REQ_STRUCT *pInfo; - - pInfo = (MLME_AUTH_REQ_STRUCT *)Msg; - COPY_MAC_ADDR(pAddr, pInfo->Addr); - *pTimeout = pInfo->Timeout; - *pAlg = pInfo->Alg; - - if (((*pAlg == Ndis802_11AuthModeShared) ||(*pAlg == Ndis802_11AuthModeOpen) - ) && - ((*pAddr & 0x01) == 0)) - { - return TRUE; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeAuthReqSanity fail - wrong algorithm\n")); - return FALSE; - } + struct rt_mlme_auth_req *pInfo; + + pInfo = (struct rt_mlme_auth_req *)Msg; + COPY_MAC_ADDR(pAddr, pInfo->Addr); + *pTimeout = pInfo->Timeout; + *pAlg = pInfo->Alg; + + if (((*pAlg == AUTH_MODE_KEY) || (*pAlg == AUTH_MODE_OPEN) + ) && ((*pAddr & 0x01) == 0)) { + return TRUE; + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeAuthReqSanity fail - wrong algorithm\n")); + return FALSE; + } } /* @@ -921,24 +887,22 @@ BOOLEAN MlmeAuthReqSanity( ========================================================================== */ -BOOLEAN MlmeAssocReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pApAddr, - OUT USHORT *pCapabilityInfo, - OUT ULONG *pTimeout, - OUT USHORT *pListenIntv) +BOOLEAN MlmeAssocReqSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 *pApAddr, + u16 * pCapabilityInfo, + unsigned long * pTimeout, u16 * pListenIntv) { - MLME_ASSOC_REQ_STRUCT *pInfo; + struct rt_mlme_assoc_req *pInfo; - pInfo = (MLME_ASSOC_REQ_STRUCT *)Msg; - *pTimeout = pInfo->Timeout; // timeout - COPY_MAC_ADDR(pApAddr, pInfo->Addr); // AP address - *pCapabilityInfo = pInfo->CapabilityInfo; // capability info - *pListenIntv = pInfo->ListenIntv; + pInfo = (struct rt_mlme_assoc_req *)Msg; + *pTimeout = pInfo->Timeout; /* timeout */ + COPY_MAC_ADDR(pApAddr, pInfo->Addr); /* AP address */ + *pCapabilityInfo = pInfo->CapabilityInfo; /* capability info */ + *pListenIntv = pInfo->ListenIntv; - return TRUE; + return TRUE; } /* @@ -952,19 +916,17 @@ BOOLEAN MlmeAssocReqSanity( ========================================================================== */ -BOOLEAN PeerDisassocSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *pReason) +BOOLEAN PeerDisassocSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 *pAddr2, u16 * pReason) { - PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg; - COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); - NdisMoveMemory(pReason, &pFrame->Octet[0], 2); + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + NdisMoveMemory(pReason, &pFrame->Octet[0], 2); - return TRUE; + return TRUE; } /* @@ -984,71 +946,260 @@ BOOLEAN PeerDisassocSanity( ======================================================================== */ -NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity( - IN PBSS_ENTRY pBss) +NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity(struct rt_bss_entry *pBss) { - NDIS_802_11_NETWORK_TYPE NetWorkType; - UCHAR rate, i; + NDIS_802_11_NETWORK_TYPE NetWorkType; + u8 rate, i; NetWorkType = Ndis802_11DS; - if (pBss->Channel <= 14) - { - // - // First check support Rate. - // - for (i = 0; i < pBss->SupRateLen; i++) - { - rate = pBss->SupRate[i] & 0x7f; // Mask out basic rate set bit - if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22)) - { + if (pBss->Channel <= 14) { + /* */ + /* First check support Rate. */ + /* */ + for (i = 0; i < pBss->SupRateLen; i++) { + rate = pBss->SupRate[i] & 0x7f; /* Mask out basic rate set bit */ + if ((rate == 2) || (rate == 4) || (rate == 11) + || (rate == 22)) { continue; - } - else - { - // - // Otherwise (even rate > 108) means Ndis802_11OFDM24 - // + } else { + /* */ + /* Otherwise (even rate > 108) means Ndis802_11OFDM24 */ + /* */ NetWorkType = Ndis802_11OFDM24; break; } } - // - // Second check Extend Rate. - // - if (NetWorkType != Ndis802_11OFDM24) - { - for (i = 0; i < pBss->ExtRateLen; i++) - { - rate = pBss->SupRate[i] & 0x7f; // Mask out basic rate set bit - if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22)) - { + /* */ + /* Second check Extend Rate. */ + /* */ + if (NetWorkType != Ndis802_11OFDM24) { + for (i = 0; i < pBss->ExtRateLen; i++) { + rate = pBss->SupRate[i] & 0x7f; /* Mask out basic rate set bit */ + if ((rate == 2) || (rate == 4) || (rate == 11) + || (rate == 22)) { continue; - } - else - { - // - // Otherwise (even rate > 108) means Ndis802_11OFDM24 - // + } else { + /* */ + /* Otherwise (even rate > 108) means Ndis802_11OFDM24 */ + /* */ NetWorkType = Ndis802_11OFDM24; break; } } } - } - else - { + } else { NetWorkType = Ndis802_11OFDM5; } - if (pBss->HtCapabilityLen != 0) - { - if (NetWorkType == Ndis802_11OFDM5) - NetWorkType = Ndis802_11OFDM5_N; - else - NetWorkType = Ndis802_11OFDM24_N; - } + if (pBss->HtCapabilityLen != 0) { + if (NetWorkType == Ndis802_11OFDM5) + NetWorkType = Ndis802_11OFDM5_N; + else + NetWorkType = Ndis802_11OFDM24_N; + } return NetWorkType; } + +/* + ========================================================================== + Description: + Check the validity of the received EAPoL frame + Return: + TRUE if all parameters are OK, + FALSE otherwise + ========================================================================== + */ +BOOLEAN PeerWpaMessageSanity(struct rt_rtmp_adapter *pAd, + struct rt_eapol_packet * pMsg, + unsigned long MsgLen, + u8 MsgType, struct rt_mac_table_entry *pEntry) +{ + u8 mic[LEN_KEY_DESC_MIC], digest[80], KEYDATA[MAX_LEN_OF_RSNIE]; + BOOLEAN bReplayDiff = FALSE; + BOOLEAN bWPA2 = FALSE; + struct rt_key_info EapolKeyInfo; + u8 GroupKeyIndex = 0; + + NdisZeroMemory(mic, sizeof(mic)); + NdisZeroMemory(digest, sizeof(digest)); + NdisZeroMemory(KEYDATA, sizeof(KEYDATA)); + NdisZeroMemory((u8 *)& EapolKeyInfo, sizeof(EapolKeyInfo)); + + NdisMoveMemory((u8 *)& EapolKeyInfo, + (u8 *)& pMsg->KeyDesc.KeyInfo, sizeof(struct rt_key_info)); + + *((u16 *) & EapolKeyInfo) = cpu2le16(*((u16 *) & EapolKeyInfo)); + + /* Choose WPA2 or not */ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) + || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + bWPA2 = TRUE; + + /* 0. Check MsgType */ + if ((MsgType > EAPOL_GROUP_MSG_2) || (MsgType < EAPOL_PAIR_MSG_1)) { + DBGPRINT(RT_DEBUG_ERROR, + ("The message type is invalid(%d)! \n", MsgType)); + return FALSE; + } + /* 1. Replay counter check */ + if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1) /* For supplicant */ + { + /* First validate replay counter, only accept message with larger replay counter. */ + /* Let equal pass, some AP start with all zero replay counter */ + u8 ZeroReplay[LEN_KEY_DESC_REPLAY]; + + NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); + if ((RTMPCompareMemory + (pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, + LEN_KEY_DESC_REPLAY) != 1) + && + (RTMPCompareMemory + (pMsg->KeyDesc.ReplayCounter, ZeroReplay, + LEN_KEY_DESC_REPLAY) != 0)) { + bReplayDiff = TRUE; + } + } else if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) /* For authenticator */ + { + /* check Replay Counter coresponds to MSG from authenticator, otherwise discard */ + if (!NdisEqualMemory + (pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, + LEN_KEY_DESC_REPLAY)) { + bReplayDiff = TRUE; + } + } + /* Replay Counter different condition */ + if (bReplayDiff) { + /* send wireless event - for replay counter different */ + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, + IW_REPLAY_COUNTER_DIFF_EVENT_FLAG, + pEntry->Addr, pEntry->apidx, 0); + + if (MsgType < EAPOL_GROUP_MSG_1) { + DBGPRINT(RT_DEBUG_ERROR, + ("Replay Counter Different in pairwise msg %d of 4-way handshake!\n", + MsgType)); + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("Replay Counter Different in group msg %d of 2-way handshake!\n", + (MsgType - EAPOL_PAIR_MSG_4))); + } + + hex_dump("Receive replay counter ", pMsg->KeyDesc.ReplayCounter, + LEN_KEY_DESC_REPLAY); + hex_dump("Current replay counter ", pEntry->R_Counter, + LEN_KEY_DESC_REPLAY); + return FALSE; + } + /* 2. Verify MIC except Pairwise Msg1 */ + if (MsgType != EAPOL_PAIR_MSG_1) { + u8 rcvd_mic[LEN_KEY_DESC_MIC]; + + /* Record the received MIC for check later */ + NdisMoveMemory(rcvd_mic, pMsg->KeyDesc.KeyMic, + LEN_KEY_DESC_MIC); + NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + + if (EapolKeyInfo.KeyDescVer == DESC_TYPE_TKIP) /* TKIP */ + { + HMAC_MD5(pEntry->PTK, LEN_EAP_MICK, (u8 *)pMsg, + MsgLen, mic, MD5_DIGEST_SIZE); + } else if (EapolKeyInfo.KeyDescVer == DESC_TYPE_AES) /* AES */ + { + HMAC_SHA1(pEntry->PTK, LEN_EAP_MICK, (u8 *)pMsg, + MsgLen, digest, SHA1_DIGEST_SIZE); + NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); + } + + if (!NdisEqualMemory(rcvd_mic, mic, LEN_KEY_DESC_MIC)) { + /* send wireless event - for MIC different */ + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, + IW_MIC_DIFF_EVENT_FLAG, + pEntry->Addr, + pEntry->apidx, 0); + + if (MsgType < EAPOL_GROUP_MSG_1) { + DBGPRINT(RT_DEBUG_ERROR, + ("MIC Different in pairwise msg %d of 4-way handshake!\n", + MsgType)); + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("MIC Different in group msg %d of 2-way handshake!\n", + (MsgType - EAPOL_PAIR_MSG_4))); + } + + hex_dump("Received MIC", rcvd_mic, LEN_KEY_DESC_MIC); + hex_dump("Desired MIC", mic, LEN_KEY_DESC_MIC); + + return FALSE; + } + } + /* 1. Decrypt the Key Data field if GTK is included. */ + /* 2. Extract the context of the Key Data field if it exist. */ + /* The field in pairwise_msg_2_WPA1(WPA2) & pairwise_msg_3_WPA1 is clear. */ + /* The field in group_msg_1_WPA1(WPA2) & pairwise_msg_3_WPA2 is encrypted. */ + if (CONV_ARRARY_TO_u16(pMsg->KeyDesc.KeyDataLen) > 0) { + /* Decrypt this field */ + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) + || (MsgType == EAPOL_GROUP_MSG_1)) { + if ((EapolKeyInfo.KeyDescVer == DESC_TYPE_AES)) { + /* AES */ + AES_GTK_KEY_UNWRAP(&pEntry->PTK[16], KEYDATA, + CONV_ARRARY_TO_u16(pMsg-> + KeyDesc. + KeyDataLen), + pMsg->KeyDesc.KeyData); + } else { + int i; + u8 Key[32]; + /* Decrypt TKIP GTK */ + /* Construct 32 bytes RC4 Key */ + NdisMoveMemory(Key, pMsg->KeyDesc.KeyIv, 16); + NdisMoveMemory(&Key[16], &pEntry->PTK[16], 16); + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, + 32); + /*discard first 256 bytes */ + for (i = 0; i < 256; i++) + ARCFOUR_BYTE(&pAd->PrivateInfo. + WEPCONTEXT); + /* Decrypt GTK. Becareful, there is no ICV to check the result is correct or not */ + ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, + KEYDATA, pMsg->KeyDesc.KeyData, + CONV_ARRARY_TO_u16(pMsg-> + KeyDesc. + KeyDataLen)); + } + + if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) + GroupKeyIndex = EapolKeyInfo.KeyIndex; + + } else if ((MsgType == EAPOL_PAIR_MSG_2) + || (MsgType == EAPOL_PAIR_MSG_3 && !bWPA2)) { + NdisMoveMemory(KEYDATA, pMsg->KeyDesc.KeyData, + CONV_ARRARY_TO_u16(pMsg->KeyDesc. + KeyDataLen)); + } else { + + return TRUE; + } + + /* Parse Key Data field to */ + /* 1. verify RSN IE for pairwise_msg_2_WPA1(WPA2) ,pairwise_msg_3_WPA1(WPA2) */ + /* 2. verify KDE format for pairwise_msg_3_WPA2, group_msg_1_WPA2 */ + /* 3. update shared key for pairwise_msg_3_WPA2, group_msg_1_WPA1(WPA2) */ + if (!RTMPParseEapolKeyData(pAd, KEYDATA, + CONV_ARRARY_TO_u16(pMsg->KeyDesc. + KeyDataLen), + GroupKeyIndex, MsgType, bWPA2, + pEntry)) { + return FALSE; + } + } + + return TRUE; + +} diff --git a/drivers/staging/rt2860/common/cmm_sync.c b/drivers/staging/rt2860/common/cmm_sync.c index a6e1b6ddfe57ef669d88019a036d9922a846b27d..f84194da47bce9e5b93f58c4deb7050c0fff73b8 100644 --- a/drivers/staging/rt2860/common/cmm_sync.c +++ b/drivers/staging/rt2860/common/cmm_sync.c @@ -25,7 +25,7 @@ ************************************************************************* Module Name: - sync.c + cmm_sync.c Abstract: @@ -36,42 +36,62 @@ */ #include "../rt_config.h" -// 2.4 Ghz channel plan index in the TxPower arrays. -#define BG_BAND_REGION_0_START 0 // 1,2,3,4,5,6,7,8,9,10,11 +/* 2.4 Ghz channel plan index in the TxPower arrays. */ +#define BG_BAND_REGION_0_START 0 /* 1,2,3,4,5,6,7,8,9,10,11 */ #define BG_BAND_REGION_0_SIZE 11 -#define BG_BAND_REGION_1_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13 +#define BG_BAND_REGION_1_START 0 /* 1,2,3,4,5,6,7,8,9,10,11,12,13 */ #define BG_BAND_REGION_1_SIZE 13 -#define BG_BAND_REGION_2_START 9 // 10,11 +#define BG_BAND_REGION_2_START 9 /* 10,11 */ #define BG_BAND_REGION_2_SIZE 2 -#define BG_BAND_REGION_3_START 9 // 10,11,12,13 +#define BG_BAND_REGION_3_START 9 /* 10,11,12,13 */ #define BG_BAND_REGION_3_SIZE 4 -#define BG_BAND_REGION_4_START 13 // 14 +#define BG_BAND_REGION_4_START 13 /* 14 */ #define BG_BAND_REGION_4_SIZE 1 -#define BG_BAND_REGION_5_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13,14 +#define BG_BAND_REGION_5_START 0 /* 1,2,3,4,5,6,7,8,9,10,11,12,13,14 */ #define BG_BAND_REGION_5_SIZE 14 -#define BG_BAND_REGION_6_START 2 // 3,4,5,6,7,8,9 +#define BG_BAND_REGION_6_START 2 /* 3,4,5,6,7,8,9 */ #define BG_BAND_REGION_6_SIZE 7 -#define BG_BAND_REGION_7_START 4 // 5,6,7,8,9,10,11,12,13 +#define BG_BAND_REGION_7_START 4 /* 5,6,7,8,9,10,11,12,13 */ #define BG_BAND_REGION_7_SIZE 9 -#define BG_BAND_REGION_31_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13,14 +#define BG_BAND_REGION_31_START 0 /* 1,2,3,4,5,6,7,8,9,10,11,12,13,14 */ #define BG_BAND_REGION_31_SIZE 14 -// 5 Ghz channel plan index in the TxPower arrays. -UCHAR A_BAND_REGION_0_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}; -UCHAR A_BAND_REGION_1_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; -UCHAR A_BAND_REGION_2_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64}; -UCHAR A_BAND_REGION_3_CHANNEL_LIST[]={52, 56, 60, 64, 149, 153, 157, 161}; -UCHAR A_BAND_REGION_4_CHANNEL_LIST[]={149, 153, 157, 161, 165}; -UCHAR A_BAND_REGION_5_CHANNEL_LIST[]={149, 153, 157, 161}; -UCHAR A_BAND_REGION_6_CHANNEL_LIST[]={36, 40, 44, 48}; -UCHAR A_BAND_REGION_7_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}; -UCHAR A_BAND_REGION_8_CHANNEL_LIST[]={52, 56, 60, 64}; -UCHAR A_BAND_REGION_9_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}; -UCHAR A_BAND_REGION_10_CHANNEL_LIST[]={36, 40, 44, 48, 149, 153, 157, 161, 165}; -UCHAR A_BAND_REGION_11_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161}; - -//BaSizeArray follows the 802.11n definition as MaxRxFactor. 2^(13+factor) bytes. When factor =0, it's about Ba buffer size =8. -UCHAR BaSizeArray[4] = {8,16,32,64}; +/* 5 Ghz channel plan index in the TxPower arrays. */ +u8 A_BAND_REGION_0_CHANNEL_LIST[] = + { 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 }; +u8 A_BAND_REGION_1_CHANNEL_LIST[] = + { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, +132, 136, 140 }; +u8 A_BAND_REGION_2_CHANNEL_LIST[] = { 36, 40, 44, 48, 52, 56, 60, 64 }; +u8 A_BAND_REGION_3_CHANNEL_LIST[] = { 52, 56, 60, 64, 149, 153, 157, 161 }; +u8 A_BAND_REGION_4_CHANNEL_LIST[] = { 149, 153, 157, 161, 165 }; +u8 A_BAND_REGION_5_CHANNEL_LIST[] = { 149, 153, 157, 161 }; +u8 A_BAND_REGION_6_CHANNEL_LIST[] = { 36, 40, 44, 48 }; +u8 A_BAND_REGION_7_CHANNEL_LIST[] = + { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, +132, 136, 140, 149, 153, 157, 161, 165, 169, 173 }; +u8 A_BAND_REGION_8_CHANNEL_LIST[] = { 52, 56, 60, 64 }; +u8 A_BAND_REGION_9_CHANNEL_LIST[] = + { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, +149, 153, 157, 161, 165 }; +u8 A_BAND_REGION_10_CHANNEL_LIST[] = + { 36, 40, 44, 48, 149, 153, 157, 161, 165 }; +u8 A_BAND_REGION_11_CHANNEL_LIST[] = + { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, +157, 161 }; +u8 A_BAND_REGION_12_CHANNEL_LIST[] = + { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, +132, 136, 140 }; +u8 A_BAND_REGION_13_CHANNEL_LIST[] = + { 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, +149, 153, 157, 161 }; +u8 A_BAND_REGION_14_CHANNEL_LIST[] = + { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, +153, 157, 161, 165 }; +u8 A_BAND_REGION_15_CHANNEL_LIST[] = { 149, 153, 157, 161, 165, 169, 173 }; + +/*BaSizeArray follows the 802.11n definition as MaxRxFactor. 2^(13+factor) bytes. When factor =0, it's about Ba buffer size =8. */ +u8 BaSizeArray[4] = { 8, 16, 32, 64 }; /* ========================================================================== @@ -85,155 +105,243 @@ UCHAR BaSizeArray[4] = {8,16,32,64}; ========================================================================== */ -VOID BuildChannelList( - IN PRTMP_ADAPTER pAd) +void BuildChannelList(struct rt_rtmp_adapter *pAd) { - UCHAR i, j, index=0, num=0; - PUCHAR pChannelList = NULL; + u8 i, j, index = 0, num = 0; + u8 *pChannelList = NULL; - NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER)); + NdisZeroMemory(pAd->ChannelList, + MAX_NUM_OF_CHANNELS * sizeof(struct rt_channel_tx_power)); - // if not 11a-only mode, channel list starts from 2.4Ghz band + /* if not 11a-only mode, channel list starts from 2.4Ghz band */ if ((pAd->CommonCfg.PhyMode != PHY_11A) - && (pAd->CommonCfg.PhyMode != PHY_11AN_MIXED) && (pAd->CommonCfg.PhyMode != PHY_11N_5G) - ) - { - switch (pAd->CommonCfg.CountryRegion & 0x7f) - { - case REGION_0_BG_BAND: // 1 -11 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_0_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_0_SIZE); - index += BG_BAND_REGION_0_SIZE; - break; - case REGION_1_BG_BAND: // 1 - 13 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_1_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_1_SIZE); - index += BG_BAND_REGION_1_SIZE; - break; - case REGION_2_BG_BAND: // 10 - 11 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_2_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_2_SIZE); - index += BG_BAND_REGION_2_SIZE; - break; - case REGION_3_BG_BAND: // 10 - 13 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_3_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_3_SIZE); - index += BG_BAND_REGION_3_SIZE; - break; - case REGION_4_BG_BAND: // 14 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_4_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_4_SIZE); - index += BG_BAND_REGION_4_SIZE; - break; - case REGION_5_BG_BAND: // 1 - 14 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_5_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_5_SIZE); - index += BG_BAND_REGION_5_SIZE; - break; - case REGION_6_BG_BAND: // 3 - 9 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_6_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_6_SIZE); - index += BG_BAND_REGION_6_SIZE; - break; - case REGION_7_BG_BAND: // 5 - 13 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_7_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_7_SIZE); - index += BG_BAND_REGION_7_SIZE; - break; - case REGION_31_BG_BAND: // 1 - 14 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_31_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_31_SIZE); - index += BG_BAND_REGION_31_SIZE; - break; - default: // Error. should never happen - break; + && (pAd->CommonCfg.PhyMode != PHY_11AN_MIXED) + && (pAd->CommonCfg.PhyMode != PHY_11N_5G) + ) { + switch (pAd->CommonCfg.CountryRegion & 0x7f) { + case REGION_0_BG_BAND: /* 1 -11 */ + NdisMoveMemory(&pAd->ChannelList[index], + &pAd->TxPower[BG_BAND_REGION_0_START], + sizeof(struct rt_channel_tx_power) * + BG_BAND_REGION_0_SIZE); + index += BG_BAND_REGION_0_SIZE; + break; + case REGION_1_BG_BAND: /* 1 - 13 */ + NdisMoveMemory(&pAd->ChannelList[index], + &pAd->TxPower[BG_BAND_REGION_1_START], + sizeof(struct rt_channel_tx_power) * + BG_BAND_REGION_1_SIZE); + index += BG_BAND_REGION_1_SIZE; + break; + case REGION_2_BG_BAND: /* 10 - 11 */ + NdisMoveMemory(&pAd->ChannelList[index], + &pAd->TxPower[BG_BAND_REGION_2_START], + sizeof(struct rt_channel_tx_power) * + BG_BAND_REGION_2_SIZE); + index += BG_BAND_REGION_2_SIZE; + break; + case REGION_3_BG_BAND: /* 10 - 13 */ + NdisMoveMemory(&pAd->ChannelList[index], + &pAd->TxPower[BG_BAND_REGION_3_START], + sizeof(struct rt_channel_tx_power) * + BG_BAND_REGION_3_SIZE); + index += BG_BAND_REGION_3_SIZE; + break; + case REGION_4_BG_BAND: /* 14 */ + NdisMoveMemory(&pAd->ChannelList[index], + &pAd->TxPower[BG_BAND_REGION_4_START], + sizeof(struct rt_channel_tx_power) * + BG_BAND_REGION_4_SIZE); + index += BG_BAND_REGION_4_SIZE; + break; + case REGION_5_BG_BAND: /* 1 - 14 */ + NdisMoveMemory(&pAd->ChannelList[index], + &pAd->TxPower[BG_BAND_REGION_5_START], + sizeof(struct rt_channel_tx_power) * + BG_BAND_REGION_5_SIZE); + index += BG_BAND_REGION_5_SIZE; + break; + case REGION_6_BG_BAND: /* 3 - 9 */ + NdisMoveMemory(&pAd->ChannelList[index], + &pAd->TxPower[BG_BAND_REGION_6_START], + sizeof(struct rt_channel_tx_power) * + BG_BAND_REGION_6_SIZE); + index += BG_BAND_REGION_6_SIZE; + break; + case REGION_7_BG_BAND: /* 5 - 13 */ + NdisMoveMemory(&pAd->ChannelList[index], + &pAd->TxPower[BG_BAND_REGION_7_START], + sizeof(struct rt_channel_tx_power) * + BG_BAND_REGION_7_SIZE); + index += BG_BAND_REGION_7_SIZE; + break; + case REGION_31_BG_BAND: /* 1 - 14 */ + NdisMoveMemory(&pAd->ChannelList[index], + &pAd->TxPower[BG_BAND_REGION_31_START], + sizeof(struct rt_channel_tx_power) * + BG_BAND_REGION_31_SIZE); + index += BG_BAND_REGION_31_SIZE; + break; + default: /* Error. should never happen */ + break; } - for (i=0; iChannelList[i].MaxTxPwr = 20; } - if ((pAd->CommonCfg.PhyMode == PHY_11A) || (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) - || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) - || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11N_5G) - ) - { - switch (pAd->CommonCfg.CountryRegionForABand & 0x7f) - { - case REGION_0_A_BAND: - num = sizeof(A_BAND_REGION_0_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_0_CHANNEL_LIST; - break; - case REGION_1_A_BAND: - num = sizeof(A_BAND_REGION_1_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_1_CHANNEL_LIST; - break; - case REGION_2_A_BAND: - num = sizeof(A_BAND_REGION_2_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_2_CHANNEL_LIST; - break; - case REGION_3_A_BAND: - num = sizeof(A_BAND_REGION_3_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_3_CHANNEL_LIST; - break; - case REGION_4_A_BAND: - num = sizeof(A_BAND_REGION_4_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_4_CHANNEL_LIST; - break; - case REGION_5_A_BAND: - num = sizeof(A_BAND_REGION_5_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_5_CHANNEL_LIST; - break; - case REGION_6_A_BAND: - num = sizeof(A_BAND_REGION_6_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_6_CHANNEL_LIST; - break; - case REGION_7_A_BAND: - num = sizeof(A_BAND_REGION_7_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_7_CHANNEL_LIST; - break; - case REGION_8_A_BAND: - num = sizeof(A_BAND_REGION_8_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_8_CHANNEL_LIST; - break; - case REGION_9_A_BAND: - num = sizeof(A_BAND_REGION_9_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_9_CHANNEL_LIST; - break; - - case REGION_10_A_BAND: - num = sizeof(A_BAND_REGION_10_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_10_CHANNEL_LIST; - break; - - case REGION_11_A_BAND: - num = sizeof(A_BAND_REGION_11_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_11_CHANNEL_LIST; - break; - - default: // Error. should never happen - DBGPRINT(RT_DEBUG_WARN,("countryregion=%d not support", pAd->CommonCfg.CountryRegionForABand)); - break; + if ((pAd->CommonCfg.PhyMode == PHY_11A) + || (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) + || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) + || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) + || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) + || (pAd->CommonCfg.PhyMode == PHY_11N_5G) + ) { + switch (pAd->CommonCfg.CountryRegionForABand & 0x7f) { + case REGION_0_A_BAND: + num = + sizeof(A_BAND_REGION_0_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_0_CHANNEL_LIST; + break; + case REGION_1_A_BAND: + num = + sizeof(A_BAND_REGION_1_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_1_CHANNEL_LIST; + break; + case REGION_2_A_BAND: + num = + sizeof(A_BAND_REGION_2_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_2_CHANNEL_LIST; + break; + case REGION_3_A_BAND: + num = + sizeof(A_BAND_REGION_3_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_3_CHANNEL_LIST; + break; + case REGION_4_A_BAND: + num = + sizeof(A_BAND_REGION_4_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_4_CHANNEL_LIST; + break; + case REGION_5_A_BAND: + num = + sizeof(A_BAND_REGION_5_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_5_CHANNEL_LIST; + break; + case REGION_6_A_BAND: + num = + sizeof(A_BAND_REGION_6_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_6_CHANNEL_LIST; + break; + case REGION_7_A_BAND: + num = + sizeof(A_BAND_REGION_7_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_7_CHANNEL_LIST; + break; + case REGION_8_A_BAND: + num = + sizeof(A_BAND_REGION_8_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_8_CHANNEL_LIST; + break; + case REGION_9_A_BAND: + num = + sizeof(A_BAND_REGION_9_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_9_CHANNEL_LIST; + break; + + case REGION_10_A_BAND: + num = + sizeof(A_BAND_REGION_10_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_10_CHANNEL_LIST; + break; + + case REGION_11_A_BAND: + num = + sizeof(A_BAND_REGION_11_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_11_CHANNEL_LIST; + break; + case REGION_12_A_BAND: + num = + sizeof(A_BAND_REGION_12_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_12_CHANNEL_LIST; + break; + case REGION_13_A_BAND: + num = + sizeof(A_BAND_REGION_13_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_13_CHANNEL_LIST; + break; + case REGION_14_A_BAND: + num = + sizeof(A_BAND_REGION_14_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_14_CHANNEL_LIST; + break; + case REGION_15_A_BAND: + num = + sizeof(A_BAND_REGION_15_CHANNEL_LIST) / + sizeof(u8); + pChannelList = A_BAND_REGION_15_CHANNEL_LIST; + break; + default: /* Error. should never happen */ + DBGPRINT(RT_DEBUG_WARN, + ("countryregion=%d not support", + pAd->CommonCfg.CountryRegionForABand)); + break; } - if (num != 0) - { - UCHAR RadarCh[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; - for (i=0; iTxPower[j].Channel) - NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER)); - } - for (j=0; j<15; j++) - { + if (num != 0) { + u8 RadarCh[15] = + { 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, + 128, 132, 136, 140 }; + for (i = 0; i < num; i++) { + for (j = 0; j < MAX_NUM_OF_CHANNELS; j++) { + if (pChannelList[i] == + pAd->TxPower[j].Channel) + NdisMoveMemory(&pAd-> + ChannelList[index + + i], + &pAd->TxPower[j], + sizeof + (struct rt_channel_tx_power)); + } + for (j = 0; j < 15; j++) { if (pChannelList[i] == RadarCh[j]) - pAd->ChannelList[index+i].DfsReq = TRUE; + pAd->ChannelList[index + + i].DfsReq = + TRUE; } - pAd->ChannelList[index+i].MaxTxPwr = 20; + pAd->ChannelList[index + i].MaxTxPwr = 20; } index += num; } } pAd->ChannelListNum = index; - DBGPRINT(RT_DEBUG_TRACE,("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n", - pAd->CommonCfg.CountryRegion, pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType, pAd->CommonCfg.PhyMode, pAd->ChannelListNum)); + DBGPRINT(RT_DEBUG_TRACE, + ("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n", + pAd->CommonCfg.CountryRegion, + pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType, + pAd->CommonCfg.PhyMode, pAd->ChannelListNum)); #ifdef DBG - for (i=0;iChannelListNum;i++) - { - DBGPRINT_RAW(RT_DEBUG_TRACE,("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, \n ", pAd->ChannelList[i].Channel, pAd->ChannelList[i].Power, pAd->ChannelList[i].Power2)); + for (i = 0; i < pAd->ChannelListNum; i++) { + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, \n ", + pAd->ChannelList[i].Channel, + pAd->ChannelList[i].Power, + pAd->ChannelList[i].Power2)); } #endif } @@ -251,8 +359,7 @@ VOID BuildChannelList( ========================================================================== */ -UCHAR FirstChannel( - IN PRTMP_ADAPTER pAd) +u8 FirstChannel(struct rt_rtmp_adapter *pAd) { return pAd->ChannelList[0].Channel; } @@ -268,19 +375,16 @@ UCHAR FirstChannel( return 0 if no more next channel ========================================================================== */ -UCHAR NextChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR channel) +u8 NextChannel(struct rt_rtmp_adapter *pAd, u8 channel) { int i; - UCHAR next_channel = 0; + u8 next_channel = 0; for (i = 0; i < (pAd->ChannelListNum - 1); i++) - if (channel == pAd->ChannelList[i].Channel) - { - next_channel = pAd->ChannelList[i+1].Channel; + if (channel == pAd->ChannelList[i].Channel) { + next_channel = pAd->ChannelList[i + 1].Channel; break; - } + } return next_channel; } @@ -304,16 +408,15 @@ UCHAR NextChannel( the minimum value or next lower value. ========================================================================== */ -VOID ChangeToCellPowerLimit( - IN PRTMP_ADAPTER pAd, - IN UCHAR AironetCellPowerLimit) +void ChangeToCellPowerLimit(struct rt_rtmp_adapter *pAd, + u8 AironetCellPowerLimit) { - //valud 0xFF means that hasn't found power limit information - //from the AP's Beacon/Probe response. + /*valud 0xFF means that hasn't found power limit information */ + /*from the AP's Beacon/Probe response. */ if (AironetCellPowerLimit == 0xFF) return; - if (AironetCellPowerLimit < 6) //Used Lowest Power Percentage. + if (AironetCellPowerLimit < 6) /*Used Lowest Power Percentage. */ pAd->CommonCfg.TxPowerPercentage = 6; else if (AironetCellPowerLimit < 9) pAd->CommonCfg.TxPowerPercentage = 10; @@ -324,45 +427,40 @@ VOID ChangeToCellPowerLimit( else if (AironetCellPowerLimit < 15) pAd->CommonCfg.TxPowerPercentage = 75; else - pAd->CommonCfg.TxPowerPercentage = 100; //else used maximum + pAd->CommonCfg.TxPowerPercentage = 100; /*else used maximum */ if (pAd->CommonCfg.TxPowerPercentage > pAd->CommonCfg.TxPowerDefault) - pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + pAd->CommonCfg.TxPowerPercentage = + pAd->CommonCfg.TxPowerDefault; } -CHAR ConvertToRssi( - IN PRTMP_ADAPTER pAd, - IN CHAR Rssi, - IN UCHAR RssiNumber) +char ConvertToRssi(struct rt_rtmp_adapter *pAd, char Rssi, u8 RssiNumber) { - UCHAR RssiOffset, LNAGain; + u8 RssiOffset, LNAGain; - // Rssi equals to zero should be an invalid value + /* Rssi equals to zero should be an invalid value */ if (Rssi == 0) return -99; LNAGain = GET_LNA_GAIN(pAd); - if (pAd->LatchRfRegs.Channel > 14) - { - if (RssiNumber == 0) + if (pAd->LatchRfRegs.Channel > 14) { + if (RssiNumber == 0) RssiOffset = pAd->ARssiOffset0; else if (RssiNumber == 1) RssiOffset = pAd->ARssiOffset1; else RssiOffset = pAd->ARssiOffset2; - } - else - { - if (RssiNumber == 0) + } else { + if (RssiNumber == 0) RssiOffset = pAd->BGRssiOffset0; else if (RssiNumber == 1) RssiOffset = pAd->BGRssiOffset1; else RssiOffset = pAd->BGRssiOffset2; - } + } - return (-12 - RssiOffset - LNAGain - Rssi); + return (-12 - RssiOffset - LNAGain - Rssi); } /* @@ -371,63 +469,75 @@ CHAR ConvertToRssi( Scan next channel ========================================================================== */ -VOID ScanNextChannel( - IN PRTMP_ADAPTER pAd) +void ScanNextChannel(struct rt_rtmp_adapter *pAd) { - HEADER_802_11 Hdr80211; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - UCHAR SsidLen = 0, ScanType = pAd->MlmeAux.ScanType, BBPValue = 0; - USHORT Status; - PHEADER_802_11 pHdr80211; - UINT ScanTimeIn5gChannel = SHORT_CHANNEL_TIME; - - if (MONITOR_ON(pAd)) - return; + struct rt_header_802_11 Hdr80211; + u8 *pOutBuffer = NULL; + int NStatus; + unsigned long FrameLen = 0; + u8 SsidLen = 0, ScanType = pAd->MlmeAux.ScanType, BBPValue = 0; + u16 Status; + struct rt_header_802_11 * pHdr80211; + u32 ScanTimeIn5gChannel = SHORT_CHANNEL_TIME; - if (pAd->MlmeAux.Channel == 0) { + if (MONITOR_ON(pAd)) + return; + } + + if (pAd->MlmeAux.Channel == 0) { if ((pAd->CommonCfg.BBPCurrentBW == BW_40) - && (INFRA_ON(pAd) - || (pAd->OpMode == OPMODE_AP)) - ) - { - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + && (INFRA_ON(pAd) + || (pAd->OpMode == OPMODE_AP)) + ) { + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, + FALSE); AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); BBPValue &= (~0x18); BBPValue |= 0x10; RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); - } - else - { + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n", + pAd->CommonCfg.CentralChannel, + pAd->ScanTab.BssNr)); + } else { AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to channel %d, Total BSS[%02d]\n",pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - End of SCAN, restore to channel %d, Total BSS[%02d]\n", + pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); } { - // - // To prevent data lost. - // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. - // Now, we need to send an NULL data with turned PSM bit off to AP, when scan progress done - // - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) - { - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); - if (NStatus == NDIS_STATUS_SUCCESS) - { - pHdr80211 = (PHEADER_802_11) pOutBuffer; - MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); + /* */ + /* To prevent data lost. */ + /* Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. */ + /* Now, we need to send an NULL data with turned PSM bit off to AP, when scan progress done */ + /* */ + if (OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + && (INFRA_ON(pAd))) { + NStatus = + MlmeAllocateMemory(pAd, + (void *)& pOutBuffer); + if (NStatus == NDIS_STATUS_SUCCESS) { + pHdr80211 = (struct rt_header_802_11 *) pOutBuffer; + MgtMacHeaderInit(pAd, pHdr80211, + SUBTYPE_NULL_FUNC, 1, + pAd->CommonCfg.Bssid, + pAd->CommonCfg.Bssid); pHdr80211->Duration = 0; pHdr80211->FC.Type = BTYPE_DATA; - pHdr80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); - - // Send using priority queue - MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); - DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame\n")); + pHdr80211->FC.PwrMgmt = + (pAd->StaCfg.Psm == PWR_SAVE); + + /* Send using priority queue */ + MiniportMMRequest(pAd, 0, pOutBuffer, + sizeof + (struct rt_header_802_11)); + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeScanReqAction -- Send PSM Data frame\n")); MlmeFreeMemory(pAd, pOutBuffer); RTMPusecDelay(5000); } @@ -435,155 +545,148 @@ VOID ScanNextChannel( pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_SUCCESS; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, + 2, &Status); } RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); } -#ifdef RT2870 - else if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->OpMode == OPMODE_STA)) - { +#ifdef RTMP_MAC_USB + else if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) + && (pAd->OpMode == OPMODE_STA)) { pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; MlmeCntlConfirm(pAd, MT2_SCAN_CONF, MLME_FAIL_NO_RESOURCE); } -#endif // RT2870 // - else - { +#endif /* RTMP_MAC_USB // */ + else { { - // BBP and RF are not accessible in PS mode, we has to wake them up first - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) -#ifdef RT2860 - AsicForceWakeup(pAd, FROM_TX); -#endif -#ifdef RT2870 - AsicForceWakeup(pAd, TRUE); -#endif - // leave PSM during scanning. otherwise we may lost ProbeRsp & BEACON + /* BBP and RF are not accessible in PS mode, we has to wake them up first */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + AsicForceWakeup(pAd, TRUE); + + /* leave PSM during scanning. otherwise we may lost ProbeRsp & BEACON */ if (pAd->StaCfg.Psm == PWR_SAVE) - MlmeSetPsmBit(pAd, PWR_ACTIVE); + RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE); } AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, TRUE); AsicLockChannel(pAd, pAd->MlmeAux.Channel); { - if (pAd->MlmeAux.Channel > 14) - { - if ((pAd->CommonCfg.bIEEE80211H == 1) && RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) - { + if (pAd->MlmeAux.Channel > 14) { + if ((pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, + pAd->MlmeAux. + Channel)) { ScanType = SCAN_PASSIVE; ScanTimeIn5gChannel = MIN_CHANNEL_TIME; } } } - //Global country domain(ch1-11:active scan, ch12-14 passive scan) - if ((pAd->MlmeAux.Channel <= 14) && (pAd->MlmeAux.Channel >= 12) && ((pAd->CommonCfg.CountryRegion & 0x7f) == REGION_31_BG_BAND)) - { + /*Global country domain(ch1-11:active scan, ch12-14 passive scan) */ + if ((pAd->MlmeAux.Channel <= 14) && (pAd->MlmeAux.Channel >= 12) + && ((pAd->CommonCfg.CountryRegion & 0x7f) == + REGION_31_BG_BAND)) { ScanType = SCAN_PASSIVE; } - - // We need to shorten active scan time in order for WZC connect issue - // Chnage the channel scan time for CISCO stuff based on its IAPP announcement + /* We need to shorten active scan time in order for WZC connect issue */ + /* Chnage the channel scan time for CISCO stuff based on its IAPP announcement */ if (ScanType == FAST_SCAN_ACTIVE) - RTMPSetTimer(&pAd->MlmeAux.ScanTimer, FAST_ACTIVE_SCAN_TIME); - else if (((ScanType == SCAN_CISCO_ACTIVE) || - (ScanType == SCAN_CISCO_PASSIVE) || - (ScanType == SCAN_CISCO_CHANNEL_LOAD) || - (ScanType == SCAN_CISCO_NOISE)) && (pAd->OpMode == OPMODE_STA)) - { - if (pAd->StaCfg.CCXScanTime < 25) - RTMPSetTimer(&pAd->MlmeAux.ScanTimer, pAd->StaCfg.CCXScanTime * 2); - else - RTMPSetTimer(&pAd->MlmeAux.ScanTimer, pAd->StaCfg.CCXScanTime); - } - else // must be SCAN_PASSIVE or SCAN_ACTIVE + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, + FAST_ACTIVE_SCAN_TIME); + else /* must be SCAN_PASSIVE or SCAN_ACTIVE */ { if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) - || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) - ) - { + || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) + || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) + ) { if (pAd->MlmeAux.Channel > 14) - RTMPSetTimer(&pAd->MlmeAux.ScanTimer, ScanTimeIn5gChannel); + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, + ScanTimeIn5gChannel); else - RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MIN_CHANNEL_TIME); - } - else - RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MAX_CHANNEL_TIME); + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, + MIN_CHANNEL_TIME); + } else + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, + MAX_CHANNEL_TIME); } - if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) || - (ScanType == SCAN_CISCO_ACTIVE)) - { - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - ScanNextChannel() allocate memory fail\n")); + if ((ScanType == SCAN_ACTIVE) + || (ScanType == FAST_SCAN_ACTIVE) + ) { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - ScanNextChannel() allocate memory fail\n")); { - pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + pAd->Mlme.SyncMachine.CurrState = + SYNC_IDLE; Status = MLME_FAIL_NO_RESOURCE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + MT2_SCAN_CONF, 2, &Status); } return; } - - // There is no need to send broadcast probe request if active scan is in effect. - if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) - ) + /* There is no need to send broadcast probe request if active scan is in effect. */ + if ((ScanType == SCAN_ACTIVE) + || (ScanType == FAST_SCAN_ACTIVE) + ) SsidLen = pAd->MlmeAux.SsidLen; else SsidLen = 0; - MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &Hdr80211, - 1, &SsidIe, - 1, &SsidLen, - SsidLen, pAd->MlmeAux.Ssid, - 1, &SupRateIe, - 1, &pAd->CommonCfg.SupRateLen, - pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, - END_OF_ARGS); - - if (pAd->CommonCfg.ExtRateLen) - { - ULONG Tmp; - MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, - 1, &ExtRateIe, - 1, &pAd->CommonCfg.ExtRateLen, - pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, - END_OF_ARGS); + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, + BROADCAST_ADDR, BROADCAST_ADDR); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(struct rt_header_802_11), &Hdr80211, 1, + &SsidIe, 1, &SsidLen, SsidLen, + pAd->MlmeAux.Ssid, 1, &SupRateIe, 1, + &pAd->CommonCfg.SupRateLen, + pAd->CommonCfg.SupRateLen, + pAd->CommonCfg.SupRate, END_OF_ARGS); + + if (pAd->CommonCfg.ExtRateLen) { + unsigned long Tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &ExtRateIe, + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRate, + END_OF_ARGS); FrameLen += Tmp; } - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) - { - ULONG Tmp; - UCHAR HtLen; - UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; - - if (pAd->bBroadComHT == TRUE) - { - HtLen = pAd->MlmeAux.HtCapabilityLen + 4; - - MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, - 1, &WpaIe, - 1, &HtLen, - 4, &BROADCOM[0], - pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, - END_OF_ARGS); - } - else - { + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) { + unsigned long Tmp; + u8 HtLen; + u8 BROADCOM[4] = { 0x0, 0x90, 0x4c, 0x33 }; + + if (pAd->bBroadComHT == TRUE) { + HtLen = + pAd->MlmeAux.HtCapabilityLen + 4; + + MakeOutgoingFrame(pOutBuffer + FrameLen, + &Tmp, 1, &WpaIe, 1, + &HtLen, 4, + &BROADCOM[0], + pAd->MlmeAux. + HtCapabilityLen, + &pAd->MlmeAux. + HtCapability, + END_OF_ARGS); + } else { HtLen = pAd->MlmeAux.HtCapabilityLen; - MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, - 1, &HtCapIe, - 1, &HtLen, - HtLen, &pAd->CommonCfg.HtCapability, - END_OF_ARGS); + MakeOutgoingFrame(pOutBuffer + FrameLen, + &Tmp, 1, &HtCapIe, 1, + &HtLen, HtLen, + &pAd->CommonCfg. + HtCapability, + END_OF_ARGS); } FrameLen += Tmp; } @@ -591,22 +694,18 @@ VOID ScanNextChannel( MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } - - // For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe reponse + /* For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe reponse */ pAd->Mlme.SyncMachine.CurrState = SCAN_LISTEN; } } -VOID MgtProbReqMacHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PHEADER_802_11 pHdr80211, - IN UCHAR SubType, - IN UCHAR ToDs, - IN PUCHAR pDA, - IN PUCHAR pBssid) +void MgtProbReqMacHeaderInit(struct rt_rtmp_adapter *pAd, + struct rt_header_802_11 * pHdr80211, + u8 SubType, + u8 ToDs, u8 *pDA, u8 *pBssid) { - NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + NdisZeroMemory(pHdr80211, sizeof(struct rt_header_802_11)); pHdr80211->FC.Type = BTYPE_MGMT; pHdr80211->FC.SubType = SubType; @@ -617,5 +716,3 @@ VOID MgtProbReqMacHeaderInit( COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); } - - diff --git a/drivers/staging/rt2860/common/cmm_tkip.c b/drivers/staging/rt2860/common/cmm_tkip.c new file mode 100644 index 0000000000000000000000000000000000000000..4881ef9ba022a98b02f119df537116bc6728ed96 --- /dev/null +++ b/drivers/staging/rt2860/common/cmm_tkip.c @@ -0,0 +1,833 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* + + Module Name: + cmm_tkip.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Wu 02-25-02 Initial +*/ + +#include "../rt_config.h" + +/* Rotation functions on 32 bit values */ +#define ROL32( A, n ) \ + ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) ) +#define ROR32( A, n ) ROL32( (A), 32-(n) ) + +u32 Tkip_Sbox_Lower[256] = { + 0xA5, 0x84, 0x99, 0x8D, 0x0D, 0xBD, 0xB1, 0x54, + 0x50, 0x03, 0xA9, 0x7D, 0x19, 0x62, 0xE6, 0x9A, + 0x45, 0x9D, 0x40, 0x87, 0x15, 0xEB, 0xC9, 0x0B, + 0xEC, 0x67, 0xFD, 0xEA, 0xBF, 0xF7, 0x96, 0x5B, + 0xC2, 0x1C, 0xAE, 0x6A, 0x5A, 0x41, 0x02, 0x4F, + 0x5C, 0xF4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3F, + 0x0C, 0x52, 0x65, 0x5E, 0x28, 0xA1, 0x0F, 0xB5, + 0x09, 0x36, 0x9B, 0x3D, 0x26, 0x69, 0xCD, 0x9F, + 0x1B, 0x9E, 0x74, 0x2E, 0x2D, 0xB2, 0xEE, 0xFB, + 0xF6, 0x4D, 0x61, 0xCE, 0x7B, 0x3E, 0x71, 0x97, + 0xF5, 0x68, 0x00, 0x2C, 0x60, 0x1F, 0xC8, 0xED, + 0xBE, 0x46, 0xD9, 0x4B, 0xDE, 0xD4, 0xE8, 0x4A, + 0x6B, 0x2A, 0xE5, 0x16, 0xC5, 0xD7, 0x55, 0x94, + 0xCF, 0x10, 0x06, 0x81, 0xF0, 0x44, 0xBA, 0xE3, + 0xF3, 0xFE, 0xC0, 0x8A, 0xAD, 0xBC, 0x48, 0x04, + 0xDF, 0xC1, 0x75, 0x63, 0x30, 0x1A, 0x0E, 0x6D, + 0x4C, 0x14, 0x35, 0x2F, 0xE1, 0xA2, 0xCC, 0x39, + 0x57, 0xF2, 0x82, 0x47, 0xAC, 0xE7, 0x2B, 0x95, + 0xA0, 0x98, 0xD1, 0x7F, 0x66, 0x7E, 0xAB, 0x83, + 0xCA, 0x29, 0xD3, 0x3C, 0x79, 0xE2, 0x1D, 0x76, + 0x3B, 0x56, 0x4E, 0x1E, 0xDB, 0x0A, 0x6C, 0xE4, + 0x5D, 0x6E, 0xEF, 0xA6, 0xA8, 0xA4, 0x37, 0x8B, + 0x32, 0x43, 0x59, 0xB7, 0x8C, 0x64, 0xD2, 0xE0, + 0xB4, 0xFA, 0x07, 0x25, 0xAF, 0x8E, 0xE9, 0x18, + 0xD5, 0x88, 0x6F, 0x72, 0x24, 0xF1, 0xC7, 0x51, + 0x23, 0x7C, 0x9C, 0x21, 0xDD, 0xDC, 0x86, 0x85, + 0x90, 0x42, 0xC4, 0xAA, 0xD8, 0x05, 0x01, 0x12, + 0xA3, 0x5F, 0xF9, 0xD0, 0x91, 0x58, 0x27, 0xB9, + 0x38, 0x13, 0xB3, 0x33, 0xBB, 0x70, 0x89, 0xA7, + 0xB6, 0x22, 0x92, 0x20, 0x49, 0xFF, 0x78, 0x7A, + 0x8F, 0xF8, 0x80, 0x17, 0xDA, 0x31, 0xC6, 0xB8, + 0xC3, 0xB0, 0x77, 0x11, 0xCB, 0xFC, 0xD6, 0x3A +}; + +u32 Tkip_Sbox_Upper[256] = { + 0xC6, 0xF8, 0xEE, 0xF6, 0xFF, 0xD6, 0xDE, 0x91, + 0x60, 0x02, 0xCE, 0x56, 0xE7, 0xB5, 0x4D, 0xEC, + 0x8F, 0x1F, 0x89, 0xFA, 0xEF, 0xB2, 0x8E, 0xFB, + 0x41, 0xB3, 0x5F, 0x45, 0x23, 0x53, 0xE4, 0x9B, + 0x75, 0xE1, 0x3D, 0x4C, 0x6C, 0x7E, 0xF5, 0x83, + 0x68, 0x51, 0xD1, 0xF9, 0xE2, 0xAB, 0x62, 0x2A, + 0x08, 0x95, 0x46, 0x9D, 0x30, 0x37, 0x0A, 0x2F, + 0x0E, 0x24, 0x1B, 0xDF, 0xCD, 0x4E, 0x7F, 0xEA, + 0x12, 0x1D, 0x58, 0x34, 0x36, 0xDC, 0xB4, 0x5B, + 0xA4, 0x76, 0xB7, 0x7D, 0x52, 0xDD, 0x5E, 0x13, + 0xA6, 0xB9, 0x00, 0xC1, 0x40, 0xE3, 0x79, 0xB6, + 0xD4, 0x8D, 0x67, 0x72, 0x94, 0x98, 0xB0, 0x85, + 0xBB, 0xC5, 0x4F, 0xED, 0x86, 0x9A, 0x66, 0x11, + 0x8A, 0xE9, 0x04, 0xFE, 0xA0, 0x78, 0x25, 0x4B, + 0xA2, 0x5D, 0x80, 0x05, 0x3F, 0x21, 0x70, 0xF1, + 0x63, 0x77, 0xAF, 0x42, 0x20, 0xE5, 0xFD, 0xBF, + 0x81, 0x18, 0x26, 0xC3, 0xBE, 0x35, 0x88, 0x2E, + 0x93, 0x55, 0xFC, 0x7A, 0xC8, 0xBA, 0x32, 0xE6, + 0xC0, 0x19, 0x9E, 0xA3, 0x44, 0x54, 0x3B, 0x0B, + 0x8C, 0xC7, 0x6B, 0x28, 0xA7, 0xBC, 0x16, 0xAD, + 0xDB, 0x64, 0x74, 0x14, 0x92, 0x0C, 0x48, 0xB8, + 0x9F, 0xBD, 0x43, 0xC4, 0x39, 0x31, 0xD3, 0xF2, + 0xD5, 0x8B, 0x6E, 0xDA, 0x01, 0xB1, 0x9C, 0x49, + 0xD8, 0xAC, 0xF3, 0xCF, 0xCA, 0xF4, 0x47, 0x10, + 0x6F, 0xF0, 0x4A, 0x5C, 0x38, 0x57, 0x73, 0x97, + 0xCB, 0xA1, 0xE8, 0x3E, 0x96, 0x61, 0x0D, 0x0F, + 0xE0, 0x7C, 0x71, 0xCC, 0x90, 0x06, 0xF7, 0x1C, + 0xC2, 0x6A, 0xAE, 0x69, 0x17, 0x99, 0x3A, 0x27, + 0xD9, 0xEB, 0x2B, 0x22, 0xD2, 0xA9, 0x07, 0x33, + 0x2D, 0x3C, 0x15, 0xC9, 0x87, 0xAA, 0x50, 0xA5, + 0x03, 0x59, 0x09, 0x1A, 0x65, 0xD7, 0x84, 0xD0, + 0x82, 0x29, 0x5A, 0x1E, 0x7B, 0xA8, 0x6D, 0x2C +}; + +/* */ +/* Expanded IV for TKIP function. */ +/* */ +struct PACKED rt_tkip_iv { + union PACKED { + struct PACKED { + u8 rc0; + u8 rc1; + u8 rc2; + + union PACKED { + struct PACKED { + u8 Rsvd:5; + u8 ExtIV:1; + u8 KeyID:2; + } field; + u8 Byte; + } CONTROL; + } field; + + unsigned long word; + } IV16; + + unsigned long IV32; +}; + +/* + ======================================================================== + + Routine Description: + Convert from u8[] to unsigned long in a portable way + + Arguments: + pMICKey pointer to MIC Key + + Return Value: + None + + Note: + + ======================================================================== +*/ +unsigned long RTMPTkipGetUInt32(u8 *pMICKey) +{ + unsigned long res = 0; + int i; + + for (i = 0; i < 4; i++) { + res |= (*pMICKey++) << (8 * i); + } + + return res; +} + +/* + ======================================================================== + + Routine Description: + Convert from unsigned long to u8[] in a portable way + + Arguments: + pDst pointer to destination for convert unsigned long to u8[] + val the value for convert + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +void RTMPTkipPutUInt32(IN u8 *pDst, unsigned long val) +{ + int i; + + for (i = 0; i < 4; i++) { + *pDst++ = (u8)(val & 0xff); + val >>= 8; + } +} + +/* + ======================================================================== + + Routine Description: + Set the MIC Key. + + Arguments: + pAd Pointer to our adapter + pMICKey pointer to MIC Key + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +void RTMPTkipSetMICKey(struct rt_tkip_key_info *pTkip, u8 *pMICKey) +{ + /* Set the key */ + pTkip->K0 = RTMPTkipGetUInt32(pMICKey); + pTkip->K1 = RTMPTkipGetUInt32(pMICKey + 4); + /* and reset the message */ + pTkip->L = pTkip->K0; + pTkip->R = pTkip->K1; + pTkip->nBytesInM = 0; + pTkip->M = 0; +} + +/* + ======================================================================== + + Routine Description: + Calculate the MIC Value. + + Arguments: + pAd Pointer to our adapter + uChar Append this uChar + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +void RTMPTkipAppendByte(struct rt_tkip_key_info *pTkip, u8 uChar) +{ + /* Append the byte to our word-sized buffer */ + pTkip->M |= (uChar << (8 * pTkip->nBytesInM)); + pTkip->nBytesInM++; + /* Process the word if it is full. */ + if (pTkip->nBytesInM >= 4) { + pTkip->L ^= pTkip->M; + pTkip->R ^= ROL32(pTkip->L, 17); + pTkip->L += pTkip->R; + pTkip->R ^= + ((pTkip->L & 0xff00ff00) >> 8) | ((pTkip-> + L & 0x00ff00ff) << 8); + pTkip->L += pTkip->R; + pTkip->R ^= ROL32(pTkip->L, 3); + pTkip->L += pTkip->R; + pTkip->R ^= ROR32(pTkip->L, 2); + pTkip->L += pTkip->R; + /* Clear the buffer */ + pTkip->M = 0; + pTkip->nBytesInM = 0; + } +} + +/* + ======================================================================== + + Routine Description: + Calculate the MIC Value. + + Arguments: + pAd Pointer to our adapter + pSrc Pointer to source data for Calculate MIC Value + Len Indicate the length of the source data + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +void RTMPTkipAppend(struct rt_tkip_key_info *pTkip, u8 *pSrc, u32 nBytes) +{ + /* This is simple */ + while (nBytes > 0) { + RTMPTkipAppendByte(pTkip, *pSrc++); + nBytes--; + } +} + +/* + ======================================================================== + + Routine Description: + Get the MIC Value. + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + the MIC Value is store in pAd->PrivateInfo.MIC + ======================================================================== +*/ +void RTMPTkipGetMIC(struct rt_tkip_key_info *pTkip) +{ + /* Append the minimum padding */ + RTMPTkipAppendByte(pTkip, 0x5a); + RTMPTkipAppendByte(pTkip, 0); + RTMPTkipAppendByte(pTkip, 0); + RTMPTkipAppendByte(pTkip, 0); + RTMPTkipAppendByte(pTkip, 0); + /* and then zeroes until the length is a multiple of 4 */ + while (pTkip->nBytesInM != 0) { + RTMPTkipAppendByte(pTkip, 0); + } + /* The appendByte function has already computed the result. */ + RTMPTkipPutUInt32(pTkip->MIC, pTkip->L); + RTMPTkipPutUInt32(pTkip->MIC + 4, pTkip->R); +} + +/* + ======================================================================== + + Routine Description: + Init Tkip function. + + Arguments: + pAd Pointer to our adapter + pTKey Pointer to the Temporal Key (TK), TK shall be 128bits. + KeyId TK Key ID + pTA Pointer to transmitter address + pMICKey pointer to MIC Key + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +void RTMPInitTkipEngine(struct rt_rtmp_adapter *pAd, + u8 *pKey, + u8 KeyId, + u8 *pTA, + u8 *pMICKey, + u8 *pTSC, unsigned long *pIV16, unsigned long *pIV32) +{ + struct rt_tkip_iv tkipIv; + + /* Prepare 8 bytes TKIP encapsulation for MPDU */ + NdisZeroMemory(&tkipIv, sizeof(struct rt_tkip_iv)); + tkipIv.IV16.field.rc0 = *(pTSC + 1); + tkipIv.IV16.field.rc1 = (tkipIv.IV16.field.rc0 | 0x20) & 0x7f; + tkipIv.IV16.field.rc2 = *pTSC; + tkipIv.IV16.field.CONTROL.field.ExtIV = 1; /* 0: non-extended IV, 1: an extended IV */ + tkipIv.IV16.field.CONTROL.field.KeyID = KeyId; +/* tkipIv.IV32 = *(unsigned long *)(pTSC + 2); */ + NdisMoveMemory(&tkipIv.IV32, (pTSC + 2), 4); /* Copy IV */ + + *pIV16 = tkipIv.IV16.word; + *pIV32 = tkipIv.IV32; +} + +/* + ======================================================================== + + Routine Description: + Init MIC Value calculation function which include set MIC key & + calculate first 16 bytes (DA + SA + priority + 0) + + Arguments: + pAd Pointer to our adapter + pTKey Pointer to the Temporal Key (TK), TK shall be 128bits. + pDA Pointer to DA address + pSA Pointer to SA address + pMICKey pointer to MIC Key + + Return Value: + None + + Note: + + ======================================================================== +*/ +void RTMPInitMICEngine(struct rt_rtmp_adapter *pAd, + u8 *pKey, + u8 *pDA, + u8 *pSA, u8 UserPriority, u8 *pMICKey) +{ + unsigned long Priority = UserPriority; + + /* Init MIC value calculation */ + RTMPTkipSetMICKey(&pAd->PrivateInfo.Tx, pMICKey); + /* DA */ + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pDA, MAC_ADDR_LEN); + /* SA */ + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSA, MAC_ADDR_LEN); + /* Priority + 3 bytes of 0 */ + RTMPTkipAppend(&pAd->PrivateInfo.Tx, (u8 *)& Priority, 4); +} + +/* + ======================================================================== + + Routine Description: + Compare MIC value of received MSDU + + Arguments: + pAd Pointer to our adapter + pSrc Pointer to the received Plain text data + pDA Pointer to DA address + pSA Pointer to SA address + pMICKey pointer to MIC Key + Len the length of the received plain text data exclude MIC value + + Return Value: + TRUE MIC value matched + FALSE MIC value mismatched + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPTkipCompareMICValue(struct rt_rtmp_adapter *pAd, + u8 *pSrc, + u8 *pDA, + u8 *pSA, + u8 *pMICKey, + u8 UserPriority, u32 Len) +{ + u8 OldMic[8]; + unsigned long Priority = UserPriority; + + /* Init MIC value calculation */ + RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey); + /* DA */ + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN); + /* SA */ + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN); + /* Priority + 3 bytes of 0 */ + RTMPTkipAppend(&pAd->PrivateInfo.Rx, (u8 *)& Priority, 4); + + /* Calculate MIC value from plain text data */ + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len); + + /* Get MIC valude from received frame */ + NdisMoveMemory(OldMic, pSrc + Len, 8); + + /* Get MIC value from decrypted plain data */ + RTMPTkipGetMIC(&pAd->PrivateInfo.Rx); + + /* Move MIC value from MSDU, this steps should move to data path. */ + /* Since the MIC value might cross MPDUs. */ + if (!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8)) { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValue(): TKIP MIC Error !\n")); /*MIC error. */ + + return (FALSE); + } + return (TRUE); +} + +/* + ======================================================================== + + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware transmit function + + Arguments: + pAd Pointer to our adapter + void * Pointer to Ndis Packet for MIC calculation + pEncap Pointer to LLC encap data + LenEncap Total encap length, might be 0 which indicates no encap + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +void RTMPCalculateMICValue(struct rt_rtmp_adapter *pAd, + void *pPacket, + u8 *pEncap, + struct rt_cipher_key *pKey, u8 apidx) +{ + struct rt_packet_info PacketInfo; + u8 *pSrcBufVA; + u32 SrcBufLen; + u8 *pSrc; + u8 UserPriority; + u8 vlan_offset = 0; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + UserPriority = RTMP_GET_PACKET_UP(pPacket); + pSrc = pSrcBufVA; + + /* determine if this is a vlan packet */ + if (((*(pSrc + 12) << 8) + *(pSrc + 13)) == 0x8100) + vlan_offset = 4; + + { + RTMPInitMICEngine(pAd, + pKey->Key, + pSrc, pSrc + 6, UserPriority, pKey->TxMic); + } + + if (pEncap != NULL) { + /* LLC encapsulation */ + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pEncap, 6); + /* Protocol Type */ + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc + 12 + vlan_offset, + 2); + } + SrcBufLen -= (14 + vlan_offset); + pSrc += (14 + vlan_offset); + do { + if (SrcBufLen > 0) { + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc, SrcBufLen); + } + + break; /* No need handle next packet */ + + } while (TRUE); /* End of copying payload */ + + /* Compute the final MIC Value */ + RTMPTkipGetMIC(&pAd->PrivateInfo.Tx); +} + +/************************************************************/ +/* tkip_sbox() */ +/* Returns a 16 bit value from a 64K entry table. The Table */ +/* is synthesized from two 256 entry byte wide tables. */ +/************************************************************/ + +u32 tkip_sbox(u32 index) +{ + u32 index_low; + u32 index_high; + u32 left, right; + + index_low = (index % 256); + index_high = ((index >> 8) % 256); + + left = Tkip_Sbox_Lower[index_low] + (Tkip_Sbox_Upper[index_low] * 256); + right = + Tkip_Sbox_Upper[index_high] + (Tkip_Sbox_Lower[index_high] * 256); + + return (left ^ right); +} + +u32 rotr1(u32 a) +{ + unsigned int b; + + if ((a & 0x01) == 0x01) { + b = (a >> 1) | 0x8000; + } else { + b = (a >> 1) & 0x7fff; + } + b = b % 65536; + return b; +} + +void RTMPTkipMixKey(u8 * key, u8 * ta, unsigned long pnl, /* Least significant 16 bits of PN */ + unsigned long pnh, /* Most significant 32 bits of PN */ + u8 * rc4key, u32 * p1k) +{ + + u32 tsc0; + u32 tsc1; + u32 tsc2; + + u32 ppk0; + u32 ppk1; + u32 ppk2; + u32 ppk3; + u32 ppk4; + u32 ppk5; + + int i; + int j; + + tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ + tsc1 = (unsigned int)(pnh % 65536); + tsc2 = (unsigned int)(pnl % 65536); /* lsb */ + + /* Phase 1, step 1 */ + p1k[0] = tsc1; + p1k[1] = tsc0; + p1k[2] = (u32)(ta[0] + (ta[1] * 256)); + p1k[3] = (u32)(ta[2] + (ta[3] * 256)); + p1k[4] = (u32)(ta[4] + (ta[5] * 256)); + + /* Phase 1, step 2 */ + for (i = 0; i < 8; i++) { + j = 2 * (i & 1); + p1k[0] = + (p1k[0] + + tkip_sbox((p1k[4] ^ ((256 * key[1 + j]) + key[j])) % + 65536)) % 65536; + p1k[1] = + (p1k[1] + + tkip_sbox((p1k[0] ^ ((256 * key[5 + j]) + key[4 + j])) % + 65536)) % 65536; + p1k[2] = + (p1k[2] + + tkip_sbox((p1k[1] ^ ((256 * key[9 + j]) + key[8 + j])) % + 65536)) % 65536; + p1k[3] = + (p1k[3] + + tkip_sbox((p1k[2] ^ ((256 * key[13 + j]) + key[12 + j])) % + 65536)) % 65536; + p1k[4] = + (p1k[4] + + tkip_sbox((p1k[3] ^ (((256 * key[1 + j]) + key[j]))) % + 65536)) % 65536; + p1k[4] = (p1k[4] + i) % 65536; + } + + /* Phase 2, Step 1 */ + ppk0 = p1k[0]; + ppk1 = p1k[1]; + ppk2 = p1k[2]; + ppk3 = p1k[3]; + ppk4 = p1k[4]; + ppk5 = (p1k[4] + tsc2) % 65536; + + /* Phase2, Step 2 */ + ppk0 = ppk0 + tkip_sbox((ppk5 ^ ((256 * key[1]) + key[0])) % 65536); + ppk1 = ppk1 + tkip_sbox((ppk0 ^ ((256 * key[3]) + key[2])) % 65536); + ppk2 = ppk2 + tkip_sbox((ppk1 ^ ((256 * key[5]) + key[4])) % 65536); + ppk3 = ppk3 + tkip_sbox((ppk2 ^ ((256 * key[7]) + key[6])) % 65536); + ppk4 = ppk4 + tkip_sbox((ppk3 ^ ((256 * key[9]) + key[8])) % 65536); + ppk5 = ppk5 + tkip_sbox((ppk4 ^ ((256 * key[11]) + key[10])) % 65536); + + ppk0 = ppk0 + rotr1(ppk5 ^ ((256 * key[13]) + key[12])); + ppk1 = ppk1 + rotr1(ppk0 ^ ((256 * key[15]) + key[14])); + ppk2 = ppk2 + rotr1(ppk1); + ppk3 = ppk3 + rotr1(ppk2); + ppk4 = ppk4 + rotr1(ppk3); + ppk5 = ppk5 + rotr1(ppk4); + + /* Phase 2, Step 3 */ + /* Phase 2, Step 3 */ + + tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ + tsc1 = (unsigned int)(pnh % 65536); + tsc2 = (unsigned int)(pnl % 65536); /* lsb */ + + rc4key[0] = (tsc2 >> 8) % 256; + rc4key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f; + rc4key[2] = tsc2 % 256; + rc4key[3] = ((ppk5 ^ ((256 * key[1]) + key[0])) >> 1) % 256; + + rc4key[4] = ppk0 % 256; + rc4key[5] = (ppk0 >> 8) % 256; + + rc4key[6] = ppk1 % 256; + rc4key[7] = (ppk1 >> 8) % 256; + + rc4key[8] = ppk2 % 256; + rc4key[9] = (ppk2 >> 8) % 256; + + rc4key[10] = ppk3 % 256; + rc4key[11] = (ppk3 >> 8) % 256; + + rc4key[12] = ppk4 % 256; + rc4key[13] = (ppk4 >> 8) % 256; + + rc4key[14] = ppk5 % 256; + rc4key[15] = (ppk5 >> 8) % 256; +} + +/* */ +/* TRUE: Success! */ +/* FALSE: Decrypt Error! */ +/* */ +BOOLEAN RTMPSoftDecryptTKIP(struct rt_rtmp_adapter *pAd, + u8 *pData, + unsigned long DataByteCnt, + u8 UserPriority, struct rt_cipher_key *pWpaKey) +{ + u8 KeyID; + u32 HeaderLen; + u8 fc0; + u8 fc1; + u16 fc; + u32 frame_type; + u32 frame_subtype; + u32 from_ds; + u32 to_ds; + int a4_exists; + int qc_exists; + u16 duration; + u16 seq_control; + u16 qos_control; + u8 TA[MAC_ADDR_LEN]; + u8 DA[MAC_ADDR_LEN]; + u8 SA[MAC_ADDR_LEN]; + u8 RC4Key[16]; + u32 p1k[5]; /*for mix_key; */ + unsigned long pnl; /* Least significant 16 bits of PN */ + unsigned long pnh; /* Most significant 32 bits of PN */ + u32 num_blocks; + u32 payload_remainder; + struct rt_arcfourcontext ArcFourContext; + u32 crc32 = 0; + u32 trailfcs = 0; + u8 MIC[8]; + u8 TrailMIC[8]; + + fc0 = *pData; + fc1 = *(pData + 1); + + fc = *((u16 *)pData); + + frame_type = ((fc0 >> 2) & 0x03); + frame_subtype = ((fc0 >> 4) & 0x0f); + + from_ds = (fc1 & 0x2) >> 1; + to_ds = (fc1 & 0x1); + + a4_exists = (from_ds & to_ds); + qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */ + (frame_subtype == 0x09) || /* Likely to change. */ + (frame_subtype == 0x0a) || (frame_subtype == 0x0b) + ); + + HeaderLen = 24; + if (a4_exists) + HeaderLen += 6; + + KeyID = *((u8 *)(pData + HeaderLen + 3)); + KeyID = KeyID >> 6; + + if (pWpaKey[KeyID].KeyLen == 0) { + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPSoftDecryptTKIP failed!(KeyID[%d] Length can not be 0)\n", + KeyID)); + return FALSE; + } + + duration = *((u16 *)(pData + 2)); + + seq_control = *((u16 *)(pData + 22)); + + if (qc_exists) { + if (a4_exists) { + qos_control = *((u16 *)(pData + 30)); + } else { + qos_control = *((u16 *)(pData + 24)); + } + } + + if (to_ds == 0 && from_ds == 1) { + NdisMoveMemory(DA, pData + 4, MAC_ADDR_LEN); + NdisMoveMemory(SA, pData + 16, MAC_ADDR_LEN); + NdisMoveMemory(TA, pData + 10, MAC_ADDR_LEN); /*BSSID */ + } else if (to_ds == 0 && from_ds == 0) { + NdisMoveMemory(TA, pData + 10, MAC_ADDR_LEN); + NdisMoveMemory(DA, pData + 4, MAC_ADDR_LEN); + NdisMoveMemory(SA, pData + 10, MAC_ADDR_LEN); + } else if (to_ds == 1 && from_ds == 0) { + NdisMoveMemory(SA, pData + 10, MAC_ADDR_LEN); + NdisMoveMemory(TA, pData + 10, MAC_ADDR_LEN); + NdisMoveMemory(DA, pData + 16, MAC_ADDR_LEN); + } else if (to_ds == 1 && from_ds == 1) { + NdisMoveMemory(TA, pData + 10, MAC_ADDR_LEN); + NdisMoveMemory(DA, pData + 16, MAC_ADDR_LEN); + NdisMoveMemory(SA, pData + 22, MAC_ADDR_LEN); + } + + num_blocks = (DataByteCnt - 16) / 16; + payload_remainder = (DataByteCnt - 16) % 16; + + pnl = (*(pData + HeaderLen)) * 256 + *(pData + HeaderLen + 2); + pnh = *((unsigned long *)(pData + HeaderLen + 4)); + pnh = cpu2le32(pnh); + RTMPTkipMixKey(pWpaKey[KeyID].Key, TA, pnl, pnh, RC4Key, p1k); + + ARCFOUR_INIT(&ArcFourContext, RC4Key, 16); + + ARCFOUR_DECRYPT(&ArcFourContext, pData + HeaderLen, + pData + HeaderLen + 8, DataByteCnt - HeaderLen - 8); + NdisMoveMemory(&trailfcs, pData + DataByteCnt - 8 - 4, 4); + crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pData + HeaderLen, DataByteCnt - HeaderLen - 8 - 4); /*Skip IV+EIV 8 bytes & Skip last 4 bytes(FCS). */ + crc32 ^= 0xffffffff; /* complement */ + + if (crc32 != cpu2le32(trailfcs)) { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptTKIP, WEP Data ICV Error !\n")); /*ICV error. */ + + return (FALSE); + } + + NdisMoveMemory(TrailMIC, pData + DataByteCnt - 8 - 8 - 4, 8); + RTMPInitMICEngine(pAd, pWpaKey[KeyID].Key, DA, SA, UserPriority, + pWpaKey[KeyID].RxMic); + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pData + HeaderLen, + DataByteCnt - HeaderLen - 8 - 12); + RTMPTkipGetMIC(&pAd->PrivateInfo.Tx); + NdisMoveMemory(MIC, pAd->PrivateInfo.Tx.MIC, 8); + + if (!NdisEqualMemory(MIC, TrailMIC, 8)) { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptTKIP, WEP Data MIC Error !\n")); /*MIC error. */ + /*RTMPReportMicError(pAd, &pWpaKey[KeyID]); // marked by AlbertY @ 20060630 */ + return (FALSE); + } + /*DBGPRINT(RT_DEBUG_TRACE, "RTMPSoftDecryptTKIP Decript done!\n"); */ + return TRUE; +} diff --git a/drivers/staging/rt3090/common/cmm_wep.c b/drivers/staging/rt2860/common/cmm_wep.c similarity index 75% rename from drivers/staging/rt3090/common/cmm_wep.c rename to drivers/staging/rt2860/common/cmm_wep.c index d8ddfb2455788f31df9006bffe075dd1959b25ed..76f880cb39b025ac5712355272bbddb3cbb72abd 100644 --- a/drivers/staging/rt3090/common/cmm_wep.c +++ b/drivers/staging/rt2860/common/cmm_wep.c @@ -35,11 +35,9 @@ Paul Wu 10-28-02 Initial */ -#include "../rt_config.h" +#include "../rt_config.h" - -UINT FCSTAB_32[256] = -{ +u32 FCSTAB_32[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, @@ -107,7 +105,7 @@ UINT FCSTAB_32[256] = }; /* -UCHAR WEPKEY[] = { +u8 WEPKEY[] = { //IV 0x00, 0x11, 0x22, //WEP KEY @@ -137,33 +135,31 @@ UCHAR WEPKEY[] = { ======================================================================== */ -VOID RTMPInitWepEngine( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKey, - IN UCHAR KeyId, - IN UCHAR KeyLen, - IN OUT PUCHAR pDest) +void RTMPInitWepEngine(struct rt_rtmp_adapter *pAd, + u8 *pKey, + u8 KeyId, u8 KeyLen, IN u8 *pDest) { - UINT i; - UCHAR WEPKEY[] = { - //IV + u32 i; + u8 WEPKEY[] = { + /*IV */ 0x00, 0x11, 0x22, - //WEP KEY - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC + /*WEP KEY */ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, + 0xAA, 0xBB, 0xCC }; - pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32. + pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; /*Init crc32. */ - { + { NdisMoveMemory(WEPKEY + 3, pKey, KeyLen); - for(i = 0; i < 3; i++) - WEPKEY[i] = RandomByte(pAd); //Call mlme RandomByte() function. - ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, KeyLen + 3); //INIT SBOX, KEYLEN+3(IV) + for (i = 0; i < 3; i++) + WEPKEY[i] = RandomByte(pAd); /*Call mlme RandomByte() function. */ + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, KeyLen + 3); /*INIT SBOX, KEYLEN+3(IV) */ - NdisMoveMemory(pDest, WEPKEY, 3); //Append Init Vector - } - *(pDest+3) = (KeyId << 6); //Append KEYID + NdisMoveMemory(pDest, WEPKEY, 3); /*Append Init Vector */ + } + *(pDest + 3) = (KeyId << 6); /*Append KEYID */ } @@ -188,17 +184,14 @@ VOID RTMPInitWepEngine( ======================================================================== */ -VOID RTMPEncryptData( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pSrc, - IN PUCHAR pDest, - IN UINT Len) +void RTMPEncryptData(struct rt_rtmp_adapter *pAd, + u8 *pSrc, u8 *pDest, u32 Len) { - pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, pSrc, Len); + pAd->PrivateInfo.FCSCRC32 = + RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, pSrc, Len); ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, pSrc, Len); } - /* ======================================================================== @@ -218,40 +211,41 @@ VOID RTMPEncryptData( ======================================================================== */ -BOOLEAN RTMPSoftDecryptWEP( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG DataByteCnt, - IN PCIPHER_KEY pGroupKey) +BOOLEAN RTMPSoftDecryptWEP(struct rt_rtmp_adapter *pAd, + u8 *pData, + unsigned long DataByteCnt, struct rt_cipher_key *pGroupKey) { - UINT trailfcs; - UINT crc32; - UCHAR KeyIdx; - UCHAR WEPKEY[] = { - //IV + u32 trailfcs; + u32 crc32; + u8 KeyIdx; + u8 WEPKEY[] = { + /*IV */ 0x00, 0x11, 0x22, - //WEP KEY - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC + /*WEP KEY */ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, + 0xAA, 0xBB, 0xCC }; - UCHAR *pPayload = (UCHAR *)pData + LENGTH_802_11; - ULONG payload_len = DataByteCnt - LENGTH_802_11; + u8 *pPayload = (u8 *) pData + LENGTH_802_11; + unsigned long payload_len = DataByteCnt - LENGTH_802_11; - NdisMoveMemory(WEPKEY, pPayload, 3); //Get WEP IV + NdisMoveMemory(WEPKEY, pPayload, 3); /*Get WEP IV */ KeyIdx = (*(pPayload + 3) & 0xc0) >> 6; if (pGroupKey[KeyIdx].KeyLen == 0) return (FALSE); - NdisMoveMemory(WEPKEY + 3, pGroupKey[KeyIdx].Key, pGroupKey[KeyIdx].KeyLen); - ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, pGroupKey[KeyIdx].KeyLen + 3); - ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, pPayload, pPayload + 4, payload_len - 4); + NdisMoveMemory(WEPKEY + 3, pGroupKey[KeyIdx].Key, + pGroupKey[KeyIdx].KeyLen); + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, + pGroupKey[KeyIdx].KeyLen + 3); + ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, pPayload, pPayload + 4, + payload_len - 4); NdisMoveMemory(&trailfcs, pPayload + payload_len - 8, 4); - crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pPayload, payload_len - 8); //Skip last 4 bytes(FCS). - crc32 ^= 0xffffffff; /* complement */ + crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pPayload, payload_len - 8); /*Skip last 4 bytes(FCS). */ + crc32 ^= 0xffffffff; /* complement */ - if(crc32 != cpu2le32(trailfcs)) - { - DBGPRINT(RT_DEBUG_TRACE, ("! WEP Data CRC Error !\n")); //CRC error. + if (crc32 != cpu2le32(trailfcs)) { + DBGPRINT(RT_DEBUG_TRACE, ("WEP Data CRC Error!\n")); /*CRC error. */ return (FALSE); } return (TRUE); @@ -261,10 +255,10 @@ BOOLEAN RTMPSoftDecryptWEP( ======================================================================== Routine Description: - The Stream Cipher Encryption Algorithm "ARCFOUR" initialize + The Stream Cipher Encryption Algorithm "struct rt_arcfour" initialize Arguments: - Ctx Pointer to ARCFOUR CONTEXT (SBOX) + Ctx Pointer to struct rt_arcfour CONTEXT (SBOX) pKey Pointer to the WEP KEY KeyLen Indicate the length fo the WEP KEY @@ -277,26 +271,22 @@ BOOLEAN RTMPSoftDecryptWEP( ======================================================================== */ -VOID ARCFOUR_INIT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pKey, - IN UINT KeyLen) +void ARCFOUR_INIT(struct rt_arcfourcontext *Ctx, u8 *pKey, u32 KeyLen) { - UCHAR t, u; - UINT keyindex; - UINT stateindex; - PUCHAR state; - UINT counter; + u8 t, u; + u32 keyindex; + u32 stateindex; + u8 *state; + u32 counter; state = Ctx->STATE; Ctx->X = 0; Ctx->Y = 0; for (counter = 0; counter < 256; counter++) - state[counter] = (UCHAR)counter; + state[counter] = (u8)counter; keyindex = 0; stateindex = 0; - for (counter = 0; counter < 256; counter++) - { + for (counter = 0; counter < 256; counter++) { t = state[counter]; stateindex = (stateindex + pKey[keyindex] + t) & 0xff; u = state[stateindex]; @@ -311,37 +301,36 @@ VOID ARCFOUR_INIT( ======================================================================== Routine Description: - Get bytes from ARCFOUR CONTEXT (S-BOX) + Get bytes from struct rt_arcfour CONTEXT (S-BOX) Arguments: - Ctx Pointer to ARCFOUR CONTEXT (SBOX) + Ctx Pointer to struct rt_arcfour CONTEXT (SBOX) Return Value: - UCHAR - the value of the ARCFOUR CONTEXT (S-BOX) + u8 - the value of the struct rt_arcfour CONTEXT (S-BOX) Note: ======================================================================== */ -UCHAR ARCFOUR_BYTE( - IN PARCFOURCONTEXT Ctx) +u8 ARCFOUR_BYTE(struct rt_arcfourcontext *Ctx) { - UINT x; - UINT y; - UCHAR sx, sy; - PUCHAR state; - - state = Ctx->STATE; - x = (Ctx->X + 1) & 0xff; - sx = state[x]; - y = (sx + Ctx->Y) & 0xff; - sy = state[y]; - Ctx->X = x; - Ctx->Y = y; - state[y] = sx; - state[x] = sy; - - return(state[(sx + sy) & 0xff]); + u32 x; + u32 y; + u8 sx, sy; + u8 *state; + + state = Ctx->STATE; + x = (Ctx->X + 1) & 0xff; + sx = state[x]; + y = (sx + Ctx->Y) & 0xff; + sy = state[y]; + Ctx->X = x; + Ctx->Y = y; + state[y] = sx; + state[x] = sy; + + return (state[(sx + sy) & 0xff]); } @@ -352,7 +341,7 @@ UCHAR ARCFOUR_BYTE( The Stream Cipher Decryption Algorithm Arguments: - Ctx Pointer to ARCFOUR CONTEXT (SBOX) + Ctx Pointer to struct rt_arcfour CONTEXT (SBOX) pDest Pointer to the Destination pSrc Pointer to the Source data Len Indicate the length of the Source data @@ -364,13 +353,10 @@ UCHAR ARCFOUR_BYTE( ======================================================================== */ -VOID ARCFOUR_DECRYPT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pDest, - IN PUCHAR pSrc, - IN UINT Len) +void ARCFOUR_DECRYPT(struct rt_arcfourcontext *Ctx, + u8 *pDest, u8 *pSrc, u32 Len) { - UINT i; + u32 i; for (i = 0; i < Len; i++) pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); @@ -383,7 +369,7 @@ VOID ARCFOUR_DECRYPT( The Stream Cipher Encryption Algorithm Arguments: - Ctx Pointer to ARCFOUR CONTEXT (SBOX) + Ctx Pointer to struct rt_arcfour CONTEXT (SBOX) pDest Pointer to the Destination pSrc Pointer to the Source data Len Indicate the length of the Source dta @@ -397,13 +383,10 @@ VOID ARCFOUR_DECRYPT( ======================================================================== */ -VOID ARCFOUR_ENCRYPT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pDest, - IN PUCHAR pSrc, - IN UINT Len) +void ARCFOUR_ENCRYPT(struct rt_arcfourcontext *Ctx, + u8 *pDest, u8 *pSrc, u32 Len) { - UINT i; + u32 i; for (i = 0; i < Len; i++) pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); @@ -416,31 +399,26 @@ VOID ARCFOUR_ENCRYPT( The Stream Cipher Encryption Algorithm which conform to the special requirement to encrypt GTK. Arguments: - Ctx Pointer to ARCFOUR CONTEXT (SBOX) + Ctx Pointer to struct rt_arcfour CONTEXT (SBOX) pDest Pointer to the Destination pSrc Pointer to the Source data Len Indicate the length of the Source dta - ======================================================================== */ -VOID WPAARCFOUR_ENCRYPT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pDest, - IN PUCHAR pSrc, - IN UINT Len) +void WPAARCFOUR_ENCRYPT(struct rt_arcfourcontext *Ctx, + u8 *pDest, u8 *pSrc, u32 Len) { - UINT i; - //discard first 256 bytes + u32 i; + /*discard first 256 bytes */ for (i = 0; i < 256; i++) - ARCFOUR_BYTE(Ctx); + ARCFOUR_BYTE(Ctx); for (i = 0; i < Len; i++) pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); } - /* ======================================================================== @@ -453,7 +431,7 @@ VOID WPAARCFOUR_ENCRYPT( Len the length of the data Return Value: - UINT - FCS 32 bits + u32 - FCS 32 bits IRQL = DISPATCH_LEVEL @@ -461,18 +439,14 @@ VOID WPAARCFOUR_ENCRYPT( ======================================================================== */ -UINT RTMP_CALC_FCS32( - IN UINT Fcs, - IN PUCHAR Cp, - IN INT Len) +u32 RTMP_CALC_FCS32(u32 Fcs, u8 *Cp, int Len) { while (Len--) - Fcs = (((Fcs) >> 8) ^ FCSTAB_32[((Fcs) ^ (*Cp++)) & 0xff]); + Fcs = (((Fcs) >> 8) ^ FCSTAB_32[((Fcs) ^ (*Cp++)) & 0xff]); return (Fcs); } - /* ======================================================================== @@ -489,12 +463,11 @@ UINT RTMP_CALC_FCS32( ======================================================================== */ -VOID RTMPSetICV( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDest) +void RTMPSetICV(struct rt_rtmp_adapter *pAd, u8 *pDest) { - pAd->PrivateInfo.FCSCRC32 ^= 0xffffffff; /* complement */ + pAd->PrivateInfo.FCSCRC32 ^= 0xffffffff; /* complement */ pAd->PrivateInfo.FCSCRC32 = cpu2le32(pAd->PrivateInfo.FCSCRC32); - ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, (PUCHAR) &pAd->PrivateInfo.FCSCRC32, 4); + ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, + (u8 *)& pAd->PrivateInfo.FCSCRC32, 4); } diff --git a/drivers/staging/rt2860/common/cmm_wpa.c b/drivers/staging/rt2860/common/cmm_wpa.c index 2de29fde2c4034aac0ba6802999d754f95b9a6ea..94e119faaa71b01c04cd7477cc2d7ff7c4c0c0c8 100644 --- a/drivers/staging/rt2860/common/cmm_wpa.c +++ b/drivers/staging/rt2860/common/cmm_wpa.c @@ -36,25 +36,1219 @@ Paul Lin 03-11-28 Modify for supplicant */ #include "../rt_config.h" -// WPA OUI -UCHAR OUI_WPA_NONE_AKM[4] = {0x00, 0x50, 0xF2, 0x00}; -UCHAR OUI_WPA_VERSION[4] = {0x00, 0x50, 0xF2, 0x01}; -UCHAR OUI_WPA_WEP40[4] = {0x00, 0x50, 0xF2, 0x01}; -UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02}; -UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04}; -UCHAR OUI_WPA_WEP104[4] = {0x00, 0x50, 0xF2, 0x05}; -UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01}; -UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02}; -// WPA2 OUI -UCHAR OUI_WPA2_WEP40[4] = {0x00, 0x0F, 0xAC, 0x01}; -UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02}; -UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04}; -UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01}; -UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02}; -UCHAR OUI_WPA2_WEP104[4] = {0x00, 0x0F, 0xAC, 0x05}; -// MSA OUI -UCHAR OUI_MSA_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x05}; // Not yet final - IEEE 802.11s-D1.06 -UCHAR OUI_MSA_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x06}; // Not yet final - IEEE 802.11s-D1.06 +/* WPA OUI */ +u8 OUI_WPA_NONE_AKM[4] = { 0x00, 0x50, 0xF2, 0x00 }; +u8 OUI_WPA_VERSION[4] = { 0x00, 0x50, 0xF2, 0x01 }; +u8 OUI_WPA_WEP40[4] = { 0x00, 0x50, 0xF2, 0x01 }; +u8 OUI_WPA_TKIP[4] = { 0x00, 0x50, 0xF2, 0x02 }; +u8 OUI_WPA_CCMP[4] = { 0x00, 0x50, 0xF2, 0x04 }; +u8 OUI_WPA_WEP104[4] = { 0x00, 0x50, 0xF2, 0x05 }; +u8 OUI_WPA_8021X_AKM[4] = { 0x00, 0x50, 0xF2, 0x01 }; +u8 OUI_WPA_PSK_AKM[4] = { 0x00, 0x50, 0xF2, 0x02 }; + +/* WPA2 OUI */ +u8 OUI_WPA2_WEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 }; +u8 OUI_WPA2_TKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 }; +u8 OUI_WPA2_CCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 }; +u8 OUI_WPA2_8021X_AKM[4] = { 0x00, 0x0F, 0xAC, 0x01 }; +u8 OUI_WPA2_PSK_AKM[4] = { 0x00, 0x0F, 0xAC, 0x02 }; +u8 OUI_WPA2_WEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 }; + +static void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry, + u8 GroupKeyWepStatus, + u8 keyDescVer, + u8 MsgType, + u8 DefaultKeyIdx, + u8 * GTK, + u8 * RSNIE, + u8 RSNIE_LEN, struct rt_eapol_packet * pMsg); + +static void CalculateMIC(u8 KeyDescVer, + u8 * PTK, struct rt_eapol_packet * pMsg); + +static void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +static void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd, + struct rt_mlme_queue_elem *Elem); + +static void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd, + struct rt_mlme_queue_elem *Elem); + +static void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd, + struct rt_mlme_queue_elem *Elem); + +static void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + ========================================================================== + */ +void WpaStateMachineInit(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *S, OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(S, (STATE_MACHINE_FUNC *) Trans, MAX_WPA_PTK_STATE, + MAX_WPA_MSG, (STATE_MACHINE_FUNC) Drop, WPA_PTK, + WPA_MACHINE_BASE); + + StateMachineSetAction(S, WPA_PTK, MT2_EAPPacket, + (STATE_MACHINE_FUNC) WpaEAPPacketAction); + StateMachineSetAction(S, WPA_PTK, MT2_EAPOLStart, + (STATE_MACHINE_FUNC) WpaEAPOLStartAction); + StateMachineSetAction(S, WPA_PTK, MT2_EAPOLLogoff, + (STATE_MACHINE_FUNC) WpaEAPOLLogoffAction); + StateMachineSetAction(S, WPA_PTK, MT2_EAPOLKey, + (STATE_MACHINE_FUNC) WpaEAPOLKeyAction); + StateMachineSetAction(S, WPA_PTK, MT2_EAPOLASFAlert, + (STATE_MACHINE_FUNC) WpaEAPOLASFAlertAction); +} + +/* + ========================================================================== + Description: + this is state machine function. + When receiving EAP packets which is for 802.1x authentication use. + Not use in PSK case + Return: + ========================================================================== +*/ +void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) +{ +} + +void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) +{ +} + +void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) +{ +} + +/* + ========================================================================== + Description: + Start 4-way HS when rcv EAPOL_START which may create by our driver in assoc.c + Return: + ========================================================================== +*/ +void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) +{ + struct rt_mac_table_entry *pEntry; + struct rt_header_802_11 * pHeader; + + DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLStartAction ===> \n")); + + pHeader = (struct rt_header_802_11 *) Elem->Msg; + + /*For normaol PSK, we enqueue an EAPOL-Start command to trigger the process. */ + if (Elem->MsgLen == 6) + pEntry = MacTableLookup(pAd, Elem->Msg); + else { + pEntry = MacTableLookup(pAd, pHeader->Addr2); + } + + if (pEntry) { + DBGPRINT(RT_DEBUG_TRACE, + (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n", + pEntry->PortSecured, pEntry->WpaState, + pEntry->AuthMode, pEntry->PMKID_CacheIdx)); + + if ((pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED) + && (pEntry->WpaState < AS_PTKSTART) + && ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) + || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) + || ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) + && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND)))) { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->WpaState = AS_INITPSK; + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + NdisZeroMemory(pEntry->R_Counter, + sizeof(pEntry->R_Counter)); + pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; + + WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV); + } + } +} + +/* + ========================================================================== + Description: + This is state machine function. + When receiving EAPOL packets which is for 802.1x key management. + Use both in WPA, and WPAPSK case. + In this function, further dispatch to different functions according to the received packet. 3 categories are : + 1. normal 4-way pairwisekey and 2-way groupkey handshake + 2. MIC error (Countermeasures attack) report packet from STA. + 3. Request for pairwise/group key update from STA + Return: + ========================================================================== +*/ +void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) +{ + struct rt_mac_table_entry *pEntry; + struct rt_header_802_11 * pHeader; + struct rt_eapol_packet * pEapol_packet; + struct rt_key_info peerKeyInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLKeyAction ===>\n")); + + pHeader = (struct rt_header_802_11 *) Elem->Msg; + pEapol_packet = + (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + + NdisZeroMemory((u8 *)& peerKeyInfo, sizeof(peerKeyInfo)); + NdisMoveMemory((u8 *)& peerKeyInfo, + (u8 *)& pEapol_packet->KeyDesc.KeyInfo, + sizeof(struct rt_key_info)); + + hex_dump("Received Eapol frame", (unsigned char *)pEapol_packet, + (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H)); + + *((u16 *) & peerKeyInfo) = cpu2le16(*((u16 *) & peerKeyInfo)); + + do { + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if (!pEntry + || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) + break; + + if (pEntry->AuthMode < Ndis802_11AuthModeWPA) + break; + + DBGPRINT(RT_DEBUG_TRACE, + ("Receive EAPoL-Key frame from STA %02X-%02X-%02X-%02X-%02X-%02X\n", + PRINT_MAC(pEntry->Addr))); + + if (((pEapol_packet->ProVer != EAPOL_VER) + && (pEapol_packet->ProVer != EAPOL_VER2)) + || ((pEapol_packet->KeyDesc.Type != WPA1_KEY_DESC) + && (pEapol_packet->KeyDesc.Type != WPA2_KEY_DESC))) { + DBGPRINT(RT_DEBUG_ERROR, + ("Key descripter does not match with WPA rule\n")); + break; + } + /* The value 1 shall be used for all EAPOL-Key frames to and from a STA when */ + /* neither the group nor pairwise ciphers are CCMP for Key Descriptor 1. */ + if ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) + && (peerKeyInfo.KeyDescVer != DESC_TYPE_TKIP)) { + DBGPRINT(RT_DEBUG_ERROR, + ("Key descripter version not match(TKIP) \n")); + break; + } + /* The value 2 shall be used for all EAPOL-Key frames to and from a STA when */ + /* either the pairwise or the group cipher is AES-CCMP for Key Descriptor 2. */ + else if ((pEntry->WepStatus == Ndis802_11Encryption3Enabled) + && (peerKeyInfo.KeyDescVer != DESC_TYPE_AES)) { + DBGPRINT(RT_DEBUG_ERROR, + ("Key descripter version not match(AES) \n")); + break; + } + /* Check if this STA is in class 3 state and the WPA state is started */ + if ((pEntry->Sst == SST_ASSOC) + && (pEntry->WpaState >= AS_INITPSK)) { + /* Check the Key Ack (bit 7) of the Key Information to determine the Authenticator */ + /* or not. */ + /* An EAPOL-Key frame that is sent by the Supplicant in response to an EAPOL- */ + /* Key frame from the Authenticator must not have the Ack bit set. */ + if (peerKeyInfo.KeyAck == 1) { + /* The frame is snet by Authenticator. */ + /* So the Supplicant side shall handle this. */ + + if ((peerKeyInfo.Secure == 0) + && (peerKeyInfo.Request == 0) + && (peerKeyInfo.Error == 0) + && (peerKeyInfo.KeyType == PAIRWISEKEY)) { + /* Process 1. the message 1 of 4-way HS in WPA or WPA2 */ + /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */ + /* 2. the message 3 of 4-way HS in WPA */ + /* EAPOL-Key(0,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) */ + if (peerKeyInfo.KeyMic == 0) + PeerPairMsg1Action(pAd, pEntry, + Elem); + else + PeerPairMsg3Action(pAd, pEntry, + Elem); + } else if ((peerKeyInfo.Secure == 1) + && (peerKeyInfo.KeyMic == 1) + && (peerKeyInfo.Request == 0) + && (peerKeyInfo.Error == 0)) { + /* Process 1. the message 3 of 4-way HS in WPA2 */ + /* EAPOL-Key(1,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) */ + /* 2. the message 1 of group KS in WPA or WPA2 */ + /* EAPOL-Key(1,1,1,0,G,0,Key RSC,0, MIC,GTK[N]) */ + if (peerKeyInfo.KeyType == PAIRWISEKEY) + PeerPairMsg3Action(pAd, pEntry, + Elem); + else + PeerGroupMsg1Action(pAd, pEntry, + Elem); + } + } else { + /* The frame is snet by Supplicant. */ + /* So the Authenticator side shall handle this. */ + if ((peerKeyInfo.Request == 0) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.KeyMic == 1)) { + if (peerKeyInfo.Secure == 0 + && peerKeyInfo.KeyType == + PAIRWISEKEY) { + /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,Data) */ + /* Process 1. message 2 of 4-way HS in WPA or WPA2 */ + /* 2. message 4 of 4-way HS in WPA */ + if (CONV_ARRARY_TO_u16 + (pEapol_packet->KeyDesc. + KeyDataLen) == 0) { + PeerPairMsg4Action(pAd, + pEntry, + Elem); + } else { + PeerPairMsg2Action(pAd, + pEntry, + Elem); + } + } else if (peerKeyInfo.Secure == 1 + && peerKeyInfo.KeyType == + PAIRWISEKEY) { + /* EAPOL-Key(1,1,0,0,P,0,0,0,MIC,0) */ + /* Process message 4 of 4-way HS in WPA2 */ + PeerPairMsg4Action(pAd, pEntry, + Elem); + } else if (peerKeyInfo.Secure == 1 + && peerKeyInfo.KeyType == + GROUPKEY) { + /* EAPOL-Key(1,1,0,0,G,0,0,0,MIC,0) */ + /* Process message 2 of Group key HS in WPA or WPA2 */ + PeerGroupMsg2Action(pAd, pEntry, + &Elem-> + Msg + [LENGTH_802_11], + (Elem-> + MsgLen - + LENGTH_802_11)); + } + } + } + } + } while (FALSE); +} + +/* + ======================================================================== + + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware encryption before really + sent out to air. + + Arguments: + pAd Pointer to our adapter + void * Pointer to outgoing Ndis frame + NumberOfFrag Number of fragment required + + Return Value: + None + + Note: + + ======================================================================== +*/ +void RTMPToWirelessSta(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + u8 *pHeader802_3, + u32 HdrLen, + u8 *pData, u32 DataLen, IN BOOLEAN bClearFrame) +{ + void *pPacket; + int Status; + + if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) + return; + + do { + /* build a NDIS packet */ + Status = + RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, + pData, DataLen); + if (Status != NDIS_STATUS_SUCCESS) + break; + + if (bClearFrame) + RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1); + else + RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0); + { + RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); + + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID); /* set a default value */ + if (pEntry->apidx != 0) + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, + pEntry-> + apidx); + + RTMP_SET_PACKET_WCID(pPacket, (u8)pEntry->Aid); + RTMP_SET_PACKET_MOREDATA(pPacket, FALSE); + } + + { + /* send out the packet */ + Status = STASendPacket(pAd, pPacket); + if (Status == NDIS_STATUS_SUCCESS) { + u8 Index; + + /* Dequeue one frame from TxSwQueue0..3 queue and process it */ + /* There are three place calling dequeue for TX ring. */ + /* 1. Here, right after queueing the frame. */ + /* 2. At the end of TxRingTxDone service routine. */ + /* 3. Upon NDIS call RTMPSendPackets */ + if ((!RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + && + (!RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) { + for (Index = 0; Index < 5; Index++) + if (pAd->TxSwQueue[Index]. + Number > 0) + RTMPDeQueuePacket(pAd, + FALSE, + Index, + MAX_TX_PROCESS); + } + } + } + + } while (FALSE); +} + +/* + ========================================================================== + Description: + This is a function to initilize 4-way handshake + + Return: + + ========================================================================== +*/ +void WPAStart4WayHS(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, unsigned long TimeInterval) +{ + u8 Header802_3[14]; + struct rt_eapol_packet EAPOLPKT; + u8 *pBssid = NULL; + u8 group_cipher = Ndis802_11WEPDisabled; + + DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n")); + + if (RTMP_TEST_FLAG + (pAd, + fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS)) + { + DBGPRINT(RT_DEBUG_ERROR, + ("[ERROR]WPAStart4WayHS : The interface is closed...\n")); + return; + } + + if (pBssid == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n")); + return; + } + /* Check the status */ + if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK)) { + DBGPRINT(RT_DEBUG_ERROR, + ("[ERROR]WPAStart4WayHS : Not expect calling\n")); + return; + } + + /* Increment replay counter by 1 */ + ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); + + /* Randomly generate ANonce */ + GenRandom(pAd, (u8 *) pBssid, pEntry->ANonce); + + /* Construct EAPoL message - Pairwise Msg 1 */ + /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */ + NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); + ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_1, 0, /* Default key index */ + pEntry->ANonce, NULL, /* TxRSC */ + NULL, /* GTK */ + NULL, /* RSNIE */ + 0, /* RSNIE length */ + &EAPOLPKT); + + /* Make outgoing frame */ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); + RTMPToWirelessSta(pAd, pEntry, Header802_3, + LENGTH_802_3, (u8 *)& EAPOLPKT, + CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, + (pEntry->PortSecured == + WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); + + /* Trigger Retry Timer */ + RTMPModTimer(&pEntry->RetryTimer, TimeInterval); + + /* Update State */ + pEntry->WpaState = AS_PTKSTART; + + DBGPRINT(RT_DEBUG_TRACE, + ("<=== WPAStart4WayHS: send Msg1 of 4-way \n")); + +} + +/* + ======================================================================== + + Routine Description: + Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2 + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +void PeerPairMsg1Action(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) +{ + u8 PTK[80]; + u8 Header802_3[14]; + struct rt_eapol_packet * pMsg1; + u32 MsgLen; + struct rt_eapol_packet EAPOLPKT; + u8 *pCurrentAddr = NULL; + u8 *pmk_ptr = NULL; + u8 group_cipher = Ndis802_11WEPDisabled; + u8 *rsnie_ptr = NULL; + u8 rsnie_len = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n")); + + if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) + return; + + if (Elem->MsgLen < + (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + + sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2)) + return; + + { + pCurrentAddr = pAd->CurrentAddress; + pmk_ptr = pAd->StaCfg.PMK; + group_cipher = pAd->StaCfg.GroupCipher; + rsnie_ptr = pAd->StaCfg.RSN_IE; + rsnie_len = pAd->StaCfg.RSNIE_Len; + } + + /* Store the received frame */ + pMsg1 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Sanity Check peer Pairwise message 1 - Replay Counter */ + if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry) + == FALSE) + return; + + /* Store Replay counter, it will use to verify message 3 and construct message 2 */ + NdisMoveMemory(pEntry->R_Counter, pMsg1->KeyDesc.ReplayCounter, + LEN_KEY_DESC_REPLAY); + + /* Store ANonce */ + NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce, + LEN_KEY_DESC_NONCE); + + /* Generate random SNonce */ + GenRandom(pAd, (u8 *) pCurrentAddr, pEntry->SNonce); + + { + /* Calculate PTK(ANonce, SNonce) */ + WpaDerivePTK(pAd, + pmk_ptr, + pEntry->ANonce, + pEntry->Addr, + pEntry->SNonce, pCurrentAddr, PTK, LEN_PTK); + + /* Save key to PTK entry */ + NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK); + } + + /* Update WpaState */ + pEntry->WpaState = AS_PTKINIT_NEGOTIATING; + + /* Construct EAPoL message - Pairwise Msg 2 */ + /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2) */ + NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); + ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_2, 0, /* DefaultKeyIdx */ + pEntry->SNonce, NULL, /* TxRsc */ + NULL, /* GTK */ + (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT); + + /* Make outgoing frame */ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); + + RTMPToWirelessSta(pAd, pEntry, + Header802_3, sizeof(Header802_3), (u8 *)& EAPOLPKT, + CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE); + + DBGPRINT(RT_DEBUG_TRACE, + ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n")); +} + +/* + ========================================================================== + Description: + When receiving the second packet of 4-way pairwisekey handshake. + Return: + ========================================================================== +*/ +void PeerPairMsg2Action(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) +{ + u8 PTK[80]; + BOOLEAN Cancelled; + struct rt_header_802_11 * pHeader; + struct rt_eapol_packet EAPOLPKT; + struct rt_eapol_packet * pMsg2; + u32 MsgLen; + u8 Header802_3[LENGTH_802_3]; + u8 TxTsc[6]; + u8 *pBssid = NULL; + u8 *pmk_ptr = NULL; + u8 *gtk_ptr = NULL; + u8 default_key = 0; + u8 group_cipher = Ndis802_11WEPDisabled; + u8 *rsnie_ptr = NULL; + u8 rsnie_len = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n")); + + if ((!pEntry) || (!pEntry->ValidAsCLI)) + return; + + if (Elem->MsgLen < + (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + + sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2)) + return; + + /* check Entry in valid State */ + if (pEntry->WpaState < AS_PTKSTART) + return; + + /* pointer to 802.11 header */ + pHeader = (struct rt_header_802_11 *) Elem->Msg; + + /* skip 802.11_header(24-byte) and LLC_header(8) */ + pMsg2 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Store SNonce */ + NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce, + LEN_KEY_DESC_NONCE); + + { + /* Derive PTK */ + WpaDerivePTK(pAd, (u8 *) pmk_ptr, pEntry->ANonce, /* ANONCE */ + (u8 *) pBssid, pEntry->SNonce, /* SNONCE */ + pEntry->Addr, PTK, LEN_PTK); + + NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK); + } + + /* Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE */ + if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry) + == FALSE) + return; + + do { + /* delete retry timer */ + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + + /* Change state */ + pEntry->WpaState = AS_PTKINIT_NEGOTIATING; + + /* Increment replay counter by 1 */ + ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); + + /* Construct EAPoL message - Pairwise Msg 3 */ + NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_3, + default_key, + pEntry->ANonce, + TxTsc, + (u8 *) gtk_ptr, + (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT); + + /* Make outgoing frame */ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); + RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3, + (u8 *)& EAPOLPKT, + CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, + (pEntry->PortSecured == + WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); + + pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR; + RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV); + + /* Update State */ + pEntry->WpaState = AS_PTKINIT_NEGOTIATING; + } while (FALSE); + + DBGPRINT(RT_DEBUG_TRACE, + ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n")); +} + +/* + ======================================================================== + + Routine Description: + Process Pairwise key Msg 3 of 4-way handshaking and send Msg 4 + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +void PeerPairMsg3Action(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) +{ + struct rt_header_802_11 * pHeader; + u8 Header802_3[14]; + struct rt_eapol_packet EAPOLPKT; + struct rt_eapol_packet * pMsg3; + u32 MsgLen; + u8 *pCurrentAddr = NULL; + u8 group_cipher = Ndis802_11WEPDisabled; + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n")); + + if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) + return; + + if (Elem->MsgLen < + (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + + sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2)) + return; + + { + pCurrentAddr = pAd->CurrentAddress; + group_cipher = pAd->StaCfg.GroupCipher; + + } + + /* Record 802.11 header & the received EAPOL packet Msg3 */ + pHeader = (struct rt_header_802_11 *) Elem->Msg; + pMsg3 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE */ + if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry) + == FALSE) + return; + + /* Save Replay counter, it will use construct message 4 */ + NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter, + LEN_KEY_DESC_REPLAY); + + /* Double check ANonce */ + if (!NdisEqualMemory + (pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) { + return; + } + /* Construct EAPoL message - Pairwise Msg 4 */ + NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); + ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_4, 0, /* group key index not used in message 4 */ + NULL, /* Nonce not used in message 4 */ + NULL, /* TxRSC not used in message 4 */ + NULL, /* GTK not used in message 4 */ + NULL, /* RSN IE not used in message 4 */ + 0, &EAPOLPKT); + + /* Update WpaState */ + pEntry->WpaState = AS_PTKINITDONE; + + /* Update pairwise key */ + { + struct rt_cipher_key *pSharedKey; + + pSharedKey = &pAd->SharedKey[BSS0][0]; + + NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK); + + /* Prepare pair-wise key information into shared key table */ + NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key)); + pSharedKey->KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32], + LEN_TKIP_EK); + NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48], + LEN_TKIP_RXMICK); + NdisMoveMemory(pSharedKey->TxMic, + &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK], + LEN_TKIP_TXMICK); + + /* Decide its ChiperAlg */ + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + pSharedKey->CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + pSharedKey->CipherAlg = CIPHER_AES; + else + pSharedKey->CipherAlg = CIPHER_NONE; + + /* Update these related information to struct rt_mac_table_entry */ + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], + LEN_TKIP_EK); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], + LEN_TKIP_RXMICK); + NdisMoveMemory(pEntry->PairwiseKey.TxMic, + &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK], + LEN_TKIP_TXMICK); + pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg; + + /* Update pairwise key information to ASIC Shared Key Table */ + AsicAddSharedKeyEntry(pAd, + BSS0, + 0, + pSharedKey->CipherAlg, + pSharedKey->Key, + pSharedKey->TxMic, pSharedKey->RxMic); + + /* Update ASIC WCID attribute table and IVEIV table */ + RTMPAddWcidAttributeEntry(pAd, + BSS0, + 0, pSharedKey->CipherAlg, pEntry); + + } + + /* open 802.1x port control and privacy filter */ + if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK || + pEntry->AuthMode == Ndis802_11AuthModeWPA2) { + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + + STA_PORT_SECURED(pAd); + /* Indicate Connected for GUI */ + pAd->IndicateMediaState = NdisMediaStateConnected; + DBGPRINT(RT_DEBUG_TRACE, + ("PeerPairMsg3Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n", + GetAuthMode(pEntry->AuthMode), + GetEncryptType(pEntry->WepStatus), + GetEncryptType(group_cipher))); + } else { + } + + /* Init 802.3 header and send out */ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); + RTMPToWirelessSta(pAd, pEntry, + Header802_3, sizeof(Header802_3), + (u8 *)& EAPOLPKT, + CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE); + + DBGPRINT(RT_DEBUG_TRACE, + ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n")); +} + +/* + ========================================================================== + Description: + When receiving the last packet of 4-way pairwisekey handshake. + Initilize 2-way groupkey handshake following. + Return: + ========================================================================== +*/ +void PeerPairMsg4Action(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) +{ + struct rt_eapol_packet * pMsg4; + struct rt_header_802_11 * pHeader; + u32 MsgLen; + BOOLEAN Cancelled; + u8 group_cipher = Ndis802_11WEPDisabled; + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n")); + + do { + if ((!pEntry) || (!pEntry->ValidAsCLI)) + break; + + if (Elem->MsgLen < + (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + + sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2)) + break; + + if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING) + break; + + /* pointer to 802.11 header */ + pHeader = (struct rt_header_802_11 *) Elem->Msg; + + /* skip 802.11_header(24-byte) and LLC_header(8) */ + pMsg4 = + (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Sanity Check peer Pairwise message 4 - Replay Counter, MIC */ + if (PeerWpaMessageSanity + (pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE) + break; + + /* 3. uses the MLME.SETKEYS.request to configure PTK into MAC */ + NdisZeroMemory(&pEntry->PairwiseKey, sizeof(struct rt_cipher_key)); + + /* reset IVEIV in Asic */ + AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, 1, 0); + + pEntry->PairwiseKey.KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[32], + LEN_TKIP_EK); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, + &pEntry->PTK[TKIP_AP_RXMICK_OFFSET], + LEN_TKIP_RXMICK); + NdisMoveMemory(pEntry->PairwiseKey.TxMic, + &pEntry->PTK[TKIP_AP_TXMICK_OFFSET], + LEN_TKIP_TXMICK); + + /* Set pairwise key to Asic */ + { + pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; + if (pEntry->WepStatus == Ndis802_11Encryption2Enabled) + pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP; + else if (pEntry->WepStatus == + Ndis802_11Encryption3Enabled) + pEntry->PairwiseKey.CipherAlg = CIPHER_AES; + + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry(pAd, + pEntry->Addr, + (u8)pEntry->Aid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMPAddWcidAttributeEntry(pAd, + pEntry->apidx, + 0, + pEntry->PairwiseKey.CipherAlg, + pEntry); + } + + /* 4. upgrade state */ + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + pEntry->WpaState = AS_PTKINITDONE; + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + + if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 || + pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) { + pEntry->GTKState = REKEY_ESTABLISHED; + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + + /* send wireless event - for set key done WPA2 */ + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, + IW_SET_KEY_DONE_WPA2_EVENT_FLAG, + pEntry->Addr, + pEntry->apidx, 0); + + DBGPRINT(RT_DEBUG_OFF, + ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n", + pEntry->AuthMode, + GetAuthMode(pEntry->AuthMode), + pEntry->WepStatus, + GetEncryptType(pEntry->WepStatus), + group_cipher, GetEncryptType(group_cipher))); + } else { + /* 5. init Group 2-way handshake if necessary. */ + WPAStart2WayGroupHS(pAd, pEntry); + + pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR; + RTMPModTimer(&pEntry->RetryTimer, + PEER_MSG3_RETRY_EXEC_INTV); + } + } while (FALSE); + +} + +/* + ========================================================================== + Description: + This is a function to send the first packet of 2-way groupkey handshake + Return: + + ========================================================================== +*/ +void WPAStart2WayGroupHS(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry) +{ + u8 Header802_3[14]; + u8 TxTsc[6]; + struct rt_eapol_packet EAPOLPKT; + u8 group_cipher = Ndis802_11WEPDisabled; + u8 default_key = 0; + u8 *gnonce_ptr = NULL; + u8 *gtk_ptr = NULL; + u8 *pBssid = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n")); + + if ((!pEntry) || (!pEntry->ValidAsCLI)) + return; + + do { + /* Increment replay counter by 1 */ + ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); + + /* Construct EAPoL message - Group Msg 1 */ + NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_GROUP_MSG_1, + default_key, + (u8 *) gnonce_ptr, + TxTsc, (u8 *) gtk_ptr, NULL, 0, &EAPOLPKT); + + /* Make outgoing frame */ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); + RTMPToWirelessSta(pAd, pEntry, + Header802_3, LENGTH_802_3, + (u8 *)& EAPOLPKT, + CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, + FALSE); + + } while (FALSE); + + DBGPRINT(RT_DEBUG_TRACE, + ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n")); + + return; +} + +/* + ======================================================================== + + Routine Description: + Process Group key 2-way handshaking + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +void PeerGroupMsg1Action(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) +{ + u8 Header802_3[14]; + struct rt_eapol_packet EAPOLPKT; + struct rt_eapol_packet * pGroup; + u32 MsgLen; + BOOLEAN Cancelled; + u8 default_key = 0; + u8 group_cipher = Ndis802_11WEPDisabled; + u8 *pCurrentAddr = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n")); + + if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) + return; + + { + pCurrentAddr = pAd->CurrentAddress; + group_cipher = pAd->StaCfg.GroupCipher; + default_key = pAd->StaCfg.DefaultKeyId; + } + + /* Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8) */ + pGroup = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; + + /* Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE */ + if (PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pEntry) + == FALSE) + return; + + /* delete retry timer */ + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + + /* Save Replay counter, it will use to construct message 2 */ + NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter, + LEN_KEY_DESC_REPLAY); + + /* Construct EAPoL message - Group Msg 2 */ + NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); + ConstructEapolMsg(pEntry, group_cipher, EAPOL_GROUP_MSG_2, default_key, NULL, /* Nonce not used */ + NULL, /* TxRSC not used */ + NULL, /* GTK not used */ + NULL, /* RSN IE not used */ + 0, &EAPOLPKT); + + /* open 802.1x port control and privacy filter */ + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + + STA_PORT_SECURED(pAd); + /* Indicate Connected for GUI */ + pAd->IndicateMediaState = NdisMediaStateConnected; + + DBGPRINT(RT_DEBUG_TRACE, + ("PeerGroupMsg1Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n", + GetAuthMode(pEntry->AuthMode), + GetEncryptType(pEntry->WepStatus), + GetEncryptType(group_cipher))); + + /* init header and Fill Packet and send Msg 2 to authenticator */ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); + RTMPToWirelessSta(pAd, pEntry, + Header802_3, sizeof(Header802_3), + (u8 *)& EAPOLPKT, + CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, + ("<=== PeerGroupMsg1Action: sned group message 2\n")); +} + +/* + ========================================================================== + Description: + When receiving the last packet of 2-way groupkey handshake. + Return: + ========================================================================== +*/ +void PeerGroupMsg2Action(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + void * Msg, u32 MsgLen) +{ + u32 Len; + u8 *pData; + BOOLEAN Cancelled; + struct rt_eapol_packet * pMsg2; + u8 group_cipher = Ndis802_11WEPDisabled; + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n")); + + do { + if ((!pEntry) || (!pEntry->ValidAsCLI)) + break; + + if (MsgLen < + (LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(struct rt_key_descripter) - + MAX_LEN_OF_RSNIE - 2)) + break; + + if (pEntry->WpaState != AS_PTKINITDONE) + break; + + pData = (u8 *)Msg; + pMsg2 = (struct rt_eapol_packet *) (pData + LENGTH_802_1_H); + Len = MsgLen - LENGTH_802_1_H; + + /* Sanity Check peer group message 2 - Replay Counter, MIC */ + if (PeerWpaMessageSanity + (pAd, pMsg2, Len, EAPOL_GROUP_MSG_2, pEntry) == FALSE) + break; + + /* 3. upgrade state */ + + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + pEntry->GTKState = REKEY_ESTABLISHED; + + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) + || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) { + /* send wireless event - for set key done WPA2 */ + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, + IW_SET_KEY_DONE_WPA2_EVENT_FLAG, + pEntry->Addr, + pEntry->apidx, 0); + + DBGPRINT(RT_DEBUG_OFF, + ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n", + pEntry->AuthMode, + GetAuthMode(pEntry->AuthMode), + pEntry->WepStatus, + GetEncryptType(pEntry->WepStatus), + group_cipher, GetEncryptType(group_cipher))); + } else { + /* send wireless event - for set key done WPA */ + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, + IW_SET_KEY_DONE_WPA1_EVENT_FLAG, + pEntry->Addr, + pEntry->apidx, 0); + + DBGPRINT(RT_DEBUG_OFF, + ("AP SETKEYS DONE - WPA1, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n", + pEntry->AuthMode, + GetAuthMode(pEntry->AuthMode), + pEntry->WepStatus, + GetEncryptType(pEntry->WepStatus), + group_cipher, GetEncryptType(group_cipher))); + } + } while (FALSE); +} + +/* + ======================================================================== + + Routine Description: + Classify WPA EAP message type + + Arguments: + EAPType Value of EAP message type + MsgType Internal Message definition for MLME state machine + + Return Value: + TRUE Found appropriate message type + FALSE No appropriate message type + + IRQL = DISPATCH_LEVEL + + Note: + All these constants are defined in wpa.h + For supplicant, there is only EAPOL Key message avaliable + + ======================================================================== +*/ +BOOLEAN WpaMsgTypeSubst(u8 EAPType, int * MsgType) +{ + switch (EAPType) { + case EAPPacket: + *MsgType = MT2_EAPPacket; + break; + case EAPOLStart: + *MsgType = MT2_EAPOLStart; + break; + case EAPOLLogoff: + *MsgType = MT2_EAPOLLogoff; + break; + case EAPOLKey: + *MsgType = MT2_EAPOLKey; + break; + case EAPOLASFAlert: + *MsgType = MT2_EAPOLASFAlert; + break; + default: + return FALSE; + } + return TRUE; +} /* ======================================================================== @@ -67,72 +1261,118 @@ UCHAR OUI_MSA_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x06}; // Not yet final - I It is used to generate PTK, GTK or some specific random value. Arguments: - UCHAR *key, - the key material for HMAC_SHA1 use - INT key_len - the length of key - UCHAR *prefix - a prefix label - INT prefix_len - the length of the label - UCHAR *data - a specific data with variable length - INT data_len - the length of a specific data - INT len - the output lenght + u8 *key, - the key material for HMAC_SHA1 use + int key_len - the length of key + u8 *prefix - a prefix label + int prefix_len - the length of the label + u8 *data - a specific data with variable length + int data_len - the length of a specific data + int len - the output lenght Return Value: - UCHAR *output - the calculated result + u8 *output - the calculated result Note: 802.11i-2004 Annex H.3 ======================================================================== */ -VOID PRF( - IN UCHAR *key, - IN INT key_len, - IN UCHAR *prefix, - IN INT prefix_len, - IN UCHAR *data, - IN INT data_len, - OUT UCHAR *output, - IN INT len) -{ - INT i; - UCHAR *input; - INT currentindex = 0; - INT total_len; - - // Allocate memory for input - os_alloc_mem(NULL, (PUCHAR *)&input, 1024); - - if (input == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n")); - return; - } - - // Generate concatenation input +void PRF(u8 * key, + int key_len, + u8 * prefix, + int prefix_len, + u8 * data, int data_len, u8 * output, int len) +{ + int i; + u8 *input; + int currentindex = 0; + int total_len; + + /* Allocate memory for input */ + os_alloc_mem(NULL, (u8 **) & input, 1024); + + if (input == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("PRF: no memory!\n")); + return; + } + /* Generate concatenation input */ NdisMoveMemory(input, prefix, prefix_len); - // Concatenate a single octet containing 0 - input[prefix_len] = 0; + /* Concatenate a single octet containing 0 */ + input[prefix_len] = 0; - // Concatenate specific data + /* Concatenate specific data */ NdisMoveMemory(&input[prefix_len + 1], data, data_len); - total_len = prefix_len + 1 + data_len; + total_len = prefix_len + 1 + data_len; - // Concatenate a single octet containing 0 - // This octet shall be update later + /* Concatenate a single octet containing 0 */ + /* This octet shall be update later */ input[total_len] = 0; total_len++; - // Iterate to calculate the result by hmac-sha-1 - // Then concatenate to last result - for (i = 0; i < (len + 19) / 20; i++) - { - HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]); - currentindex += 20; + /* Iterate to calculate the result by hmac-sha-1 */ + /* Then concatenate to last result */ + for (i = 0; i < (len + 19) / 20; i++) { + HMAC_SHA1(key, key_len, input, total_len, &output[currentindex], + SHA1_DIGEST_SIZE); + currentindex += 20; - // update the last octet + /* update the last octet */ input[total_len - 1]++; } - os_free_mem(NULL, input); + os_free_mem(NULL, input); +} + +/* +* F(P, S, c, i) = U1 xor U2 xor ... Uc +* U1 = PRF(P, S || Int(i)) +* U2 = PRF(P, U1) +* Uc = PRF(P, Uc-1) +*/ + +static void F(char *password, unsigned char *ssid, int ssidlength, + int iterations, int count, unsigned char *output) +{ + unsigned char digest[36], digest1[SHA1_DIGEST_SIZE]; + int i, j; + + /* U1 = PRF(P, S || int(i)) */ + memcpy(digest, ssid, ssidlength); + digest[ssidlength] = (unsigned char)((count >> 24) & 0xff); + digest[ssidlength + 1] = (unsigned char)((count >> 16) & 0xff); + digest[ssidlength + 2] = (unsigned char)((count >> 8) & 0xff); + digest[ssidlength + 3] = (unsigned char)(count & 0xff); + HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest, ssidlength + 4, digest1, SHA1_DIGEST_SIZE); /* for WPA update */ + + /* output = U1 */ + memcpy(output, digest1, SHA1_DIGEST_SIZE); + + for (i = 1; i < iterations; i++) { + /* Un = PRF(P, Un-1) */ + HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest1, SHA1_DIGEST_SIZE, digest, SHA1_DIGEST_SIZE); /* for WPA update */ + memcpy(digest1, digest, SHA1_DIGEST_SIZE); + + /* output = output xor Un */ + for (j = 0; j < SHA1_DIGEST_SIZE; j++) { + output[j] ^= digest[j]; + } + } +} + +/* +* password - ascii string up to 63 characters in length +* ssid - octet string up to 32 octets +* ssidlength - length of ssid in octets +* output must be 40 octets in length and outputs 256 bits of key +*/ +int PasswordHash(char *password, u8 *ssid, int ssidlength, u8 *output) +{ + if ((strlen(password) > 63) || (ssidlength > 32)) + return 0; + + F(password, ssid, ssidlength, 4096, 1, output); + F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]); + return 1; } /* @@ -143,7 +1383,7 @@ VOID PRF( It shall be called by 4-way handshake processing. Arguments: - pAd - pointer to our pAdapter context + pAd - pointer to our pAdapter context PMK - pointer to PMK ANonce - pointer to ANonce AA - pointer to Authenticator Address @@ -159,56 +1399,55 @@ VOID PRF( ======================================================================== */ -VOID WpaCountPTK( - IN PRTMP_ADAPTER pAd, - IN UCHAR *PMK, - IN UCHAR *ANonce, - IN UCHAR *AA, - IN UCHAR *SNonce, - IN UCHAR *SA, - OUT UCHAR *output, - IN UINT len) -{ - UCHAR concatenation[76]; - UINT CurrPos = 0; - UCHAR temp[32]; - UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ', - 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'}; - - // initiate the concatenation input +void WpaDerivePTK(struct rt_rtmp_adapter *pAd, + u8 * PMK, + u8 * ANonce, + u8 * AA, + u8 * SNonce, + u8 * SA, u8 * output, u32 len) +{ + u8 concatenation[76]; + u32 CurrPos = 0; + u8 temp[32]; + u8 Prefix[] = + { 'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ', + 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n' + }; + + /* initiate the concatenation input */ NdisZeroMemory(temp, sizeof(temp)); NdisZeroMemory(concatenation, 76); - // Get smaller address + /* Get smaller address */ if (RTMPCompareMemory(SA, AA, 6) == 1) NdisMoveMemory(concatenation, AA, 6); else NdisMoveMemory(concatenation, SA, 6); CurrPos += 6; - // Get larger address + /* Get larger address */ if (RTMPCompareMemory(SA, AA, 6) == 1) NdisMoveMemory(&concatenation[CurrPos], SA, 6); else NdisMoveMemory(&concatenation[CurrPos], AA, 6); - // store the larger mac address for backward compatible of - // ralink proprietary STA-key issue + /* store the larger mac address for backward compatible of */ + /* ralink proprietary STA-key issue */ NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN); CurrPos += 6; - // Get smaller Nonce + /* Get smaller Nonce */ if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) - NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue + NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue */ else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); else NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); CurrPos += 32; - // Get larger Nonce + /* Get larger Nonce */ if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) - NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue + NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue */ else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); else @@ -217,7 +1456,7 @@ VOID WpaCountPTK( hex_dump("concatenation=", concatenation, 76); - // Use PRF to generate PTK + /* Use PRF to generate PTK */ PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len); } @@ -239,46 +1478,43 @@ VOID WpaCountPTK( ======================================================================== */ -VOID GenRandom( - IN PRTMP_ADAPTER pAd, - IN UCHAR *macAddr, - OUT UCHAR *random) -{ - INT i, curr; - UCHAR local[80], KeyCounter[32]; - UCHAR result[80]; - ULONG CurrentTime; - UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'}; - - // Zero the related information +void GenRandom(struct rt_rtmp_adapter *pAd, u8 * macAddr, u8 * random) +{ + int i, curr; + u8 local[80], KeyCounter[32]; + u8 result[80]; + unsigned long CurrentTime; + u8 prefix[] = + { 'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r' }; + + /* Zero the related information */ NdisZeroMemory(result, 80); NdisZeroMemory(local, 80); NdisZeroMemory(KeyCounter, 32); - for (i = 0; i < 32; i++) - { - // copy the local MAC address + for (i = 0; i < 32; i++) { + /* copy the local MAC address */ COPY_MAC_ADDR(local, macAddr); - curr = MAC_ADDR_LEN; + curr = MAC_ADDR_LEN; - // concatenate the current time + /* concatenate the current time */ NdisGetSystemUpTime(&CurrentTime); - NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime)); - curr += sizeof(CurrentTime); + NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime)); + curr += sizeof(CurrentTime); - // concatenate the last result - NdisMoveMemory(&local[curr], result, 32); - curr += 32; + /* concatenate the last result */ + NdisMoveMemory(&local[curr], result, 32); + curr += 32; - // concatenate a variable - NdisMoveMemory(&local[curr], &i, 2); - curr += 2; + /* concatenate a variable */ + NdisMoveMemory(&local[curr], &i, 2); + curr += 2; - // calculate the result - PRF(KeyCounter, 32, prefix,12, local, curr, result, 32); + /* calculate the result */ + PRF(KeyCounter, 32, prefix, 12, local, curr, result, 32); } - NdisMoveMemory(random, result, 32); + NdisMoveMemory(random, result, 32); } /* @@ -290,8 +1526,8 @@ VOID GenRandom( Arguments: pAd - pointer to our pAdapter context - ElementID - indicate the WPA1 or WPA2 - WepStatus - indicate the encryption type + ElementID - indicate the WPA1 or WPA2 + WepStatus - indicate the encryption type bMixCipher - a boolean to indicate the pairwise cipher and group cipher are the same or not @@ -301,170 +1537,169 @@ VOID GenRandom( ======================================================================== */ -static VOID RTMPInsertRsnIeCipher( - IN PRTMP_ADAPTER pAd, - IN UCHAR ElementID, - IN UINT WepStatus, - IN BOOLEAN bMixCipher, - IN UCHAR FlexibleCipher, - OUT PUCHAR pRsnIe, - OUT UCHAR *rsn_len) +static void RTMPMakeRsnIeCipher(struct rt_rtmp_adapter *pAd, + u8 ElementID, + u32 WepStatus, + IN BOOLEAN bMixCipher, + u8 FlexibleCipher, + u8 *pRsnIe, u8 * rsn_len) { - UCHAR PairwiseCnt; + u8 PairwiseCnt; *rsn_len = 0; - // decide WPA2 or WPA1 - if (ElementID == Wpa2Ie) - { - RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe; + /* decide WPA2 or WPA1 */ + if (ElementID == Wpa2Ie) { + struct rt_rsnie2 *pRsnie_cipher = (struct rt_rsnie2 *)pRsnIe; - // Assign the verson as 1 + /* Assign the verson as 1 */ pRsnie_cipher->version = 1; - switch (WepStatus) - { - // TKIP mode - case Ndis802_11Encryption2Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); - pRsnie_cipher->ucount = 1; - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); - *rsn_len = sizeof(RSNIE2); - break; - - // AES mode - case Ndis802_11Encryption3Enabled: - if (bMixCipher) - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); - else - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4); - pRsnie_cipher->ucount = 1; - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); - *rsn_len = sizeof(RSNIE2); - break; - - // TKIP-AES mix mode - case Ndis802_11Encryption4Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); - - PairwiseCnt = 1; - // Insert WPA2 TKIP as the first pairwise cipher - if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) - { - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); - // Insert WPA2 AES as the secondary pairwise cipher - if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) - { - NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4); - PairwiseCnt = 2; - } - } - else - { - // Insert WPA2 AES as the first pairwise cipher - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); + switch (WepStatus) { + /* TKIP mode */ + case Ndis802_11Encryption2Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, + OUI_WPA2_TKIP, 4); + *rsn_len = sizeof(struct rt_rsnie2); + break; + + /* AES mode */ + case Ndis802_11Encryption3Enabled: + if (bMixCipher) + NdisMoveMemory(pRsnie_cipher->mcast, + OUI_WPA2_TKIP, 4); + else + NdisMoveMemory(pRsnie_cipher->mcast, + OUI_WPA2_CCMP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, + OUI_WPA2_CCMP, 4); + *rsn_len = sizeof(struct rt_rsnie2); + break; + + /* TKIP-AES mix mode */ + case Ndis802_11Encryption4Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); + + PairwiseCnt = 1; + /* Insert WPA2 TKIP as the first pairwise cipher */ + if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) { + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, + OUI_WPA2_TKIP, 4); + /* Insert WPA2 AES as the secondary pairwise cipher */ + if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) { + NdisMoveMemory(pRsnie_cipher->ucast[0]. + oui + 4, OUI_WPA2_CCMP, + 4); + PairwiseCnt = 2; } + } else { + /* Insert WPA2 AES as the first pairwise cipher */ + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, + OUI_WPA2_CCMP, 4); + } - pRsnie_cipher->ucount = PairwiseCnt; - *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1)); - break; - } + pRsnie_cipher->ucount = PairwiseCnt; + *rsn_len = sizeof(struct rt_rsnie2) + (4 * (PairwiseCnt - 1)); + break; + } if ((pAd->OpMode == OPMODE_STA) && - (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) && - (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) - { - UINT GroupCipher = pAd->StaCfg.GroupCipher; - switch(GroupCipher) - { - case Ndis802_11GroupWEP40Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP40, 4); - break; - case Ndis802_11GroupWEP104Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP104, 4); - break; + (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) { + u32 GroupCipher = pAd->StaCfg.GroupCipher; + switch (GroupCipher) { + case Ndis802_11GroupWEP40Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, + OUI_WPA2_WEP40, 4); + break; + case Ndis802_11GroupWEP104Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, + OUI_WPA2_WEP104, 4); + break; } } - - // swap for big-endian platform + /* swap for big-endian platform */ pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); - pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); - } - else - { - RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe; + pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); + } else { + struct rt_rsnie *pRsnie_cipher = (struct rt_rsnie *)pRsnIe; - // Assign OUI and version + /* Assign OUI and version */ NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4); - pRsnie_cipher->version = 1; + pRsnie_cipher->version = 1; - switch (WepStatus) - { - // TKIP mode - case Ndis802_11Encryption2Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); - pRsnie_cipher->ucount = 1; - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); - *rsn_len = sizeof(RSNIE); - break; - - // AES mode - case Ndis802_11Encryption3Enabled: - if (bMixCipher) - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); - else - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4); - pRsnie_cipher->ucount = 1; - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); - *rsn_len = sizeof(RSNIE); - break; - - // TKIP-AES mix mode - case Ndis802_11Encryption4Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); - - PairwiseCnt = 1; - // Insert WPA TKIP as the first pairwise cipher - if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) - { - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); - // Insert WPA AES as the secondary pairwise cipher - if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) - { - NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4); - PairwiseCnt = 2; - } - } - else - { - // Insert WPA AES as the first pairwise cipher - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); + switch (WepStatus) { + /* TKIP mode */ + case Ndis802_11Encryption2Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, + OUI_WPA_TKIP, 4); + *rsn_len = sizeof(struct rt_rsnie); + break; + + /* AES mode */ + case Ndis802_11Encryption3Enabled: + if (bMixCipher) + NdisMoveMemory(pRsnie_cipher->mcast, + OUI_WPA_TKIP, 4); + else + NdisMoveMemory(pRsnie_cipher->mcast, + OUI_WPA_CCMP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, + OUI_WPA_CCMP, 4); + *rsn_len = sizeof(struct rt_rsnie); + break; + + /* TKIP-AES mix mode */ + case Ndis802_11Encryption4Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); + + PairwiseCnt = 1; + /* Insert WPA TKIP as the first pairwise cipher */ + if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) { + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, + OUI_WPA_TKIP, 4); + /* Insert WPA AES as the secondary pairwise cipher */ + if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) { + NdisMoveMemory(pRsnie_cipher->ucast[0]. + oui + 4, OUI_WPA_CCMP, + 4); + PairwiseCnt = 2; } + } else { + /* Insert WPA AES as the first pairwise cipher */ + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, + OUI_WPA_CCMP, 4); + } - pRsnie_cipher->ucount = PairwiseCnt; - *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1)); - break; - } + pRsnie_cipher->ucount = PairwiseCnt; + *rsn_len = sizeof(struct rt_rsnie) + (4 * (PairwiseCnt - 1)); + break; + } if ((pAd->OpMode == OPMODE_STA) && - (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) && - (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) - { - UINT GroupCipher = pAd->StaCfg.GroupCipher; - switch(GroupCipher) - { - case Ndis802_11GroupWEP40Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP40, 4); - break; - case Ndis802_11GroupWEP104Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP104, 4); - break; + (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) { + u32 GroupCipher = pAd->StaCfg.GroupCipher; + switch (GroupCipher) { + case Ndis802_11GroupWEP40Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, + OUI_WPA_WEP40, 4); + break; + case Ndis802_11GroupWEP104Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, + OUI_WPA_WEP104, 4); + break; } } - - // swap for big-endian platform + /* swap for big-endian platform */ pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); - pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); + pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); } } @@ -477,8 +1712,8 @@ static VOID RTMPInsertRsnIeCipher( Arguments: pAd - pointer to our pAdapter context - ElementID - indicate the WPA1 or WPA2 - AuthMode - indicate the authentication mode + ElementID - indicate the WPA1 or WPA2 + AuthMode - indicate the authentication mode apidx - indicate the interface index Return Value: @@ -487,62 +1722,66 @@ static VOID RTMPInsertRsnIeCipher( ======================================================================== */ -static VOID RTMPInsertRsnIeAKM( - IN PRTMP_ADAPTER pAd, - IN UCHAR ElementID, - IN UINT AuthMode, - IN UCHAR apidx, - OUT PUCHAR pRsnIe, - OUT UCHAR *rsn_len) +static void RTMPMakeRsnIeAKM(struct rt_rtmp_adapter *pAd, + u8 ElementID, + u32 AuthMode, + u8 apidx, + u8 *pRsnIe, u8 * rsn_len) { - RSNIE_AUTH *pRsnie_auth; + struct rt_rsnie_auth *pRsnie_auth; + u8 AkmCnt = 1; /* default as 1 */ + + pRsnie_auth = (struct rt_rsnie_auth *) (pRsnIe + (*rsn_len)); + + /* decide WPA2 or WPA1 */ + if (ElementID == Wpa2Ie) { + + switch (AuthMode) { + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA1WPA2: + NdisMoveMemory(pRsnie_auth->auth[0].oui, + OUI_WPA2_8021X_AKM, 4); + break; + + case Ndis802_11AuthModeWPA2PSK: + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + NdisMoveMemory(pRsnie_auth->auth[0].oui, + OUI_WPA2_PSK_AKM, 4); + break; + default: + AkmCnt = 0; + break; - pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len)); - - // decide WPA2 or WPA1 - if (ElementID == Wpa2Ie) - { - switch (AuthMode) - { - case Ndis802_11AuthModeWPA2: - case Ndis802_11AuthModeWPA1WPA2: - pRsnie_auth->acount = 1; - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4); - break; - - case Ndis802_11AuthModeWPA2PSK: - case Ndis802_11AuthModeWPA1PSKWPA2PSK: - pRsnie_auth->acount = 1; - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4); - break; - } - } - else - { - switch (AuthMode) - { - case Ndis802_11AuthModeWPA: - case Ndis802_11AuthModeWPA1WPA2: - pRsnie_auth->acount = 1; - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4); - break; - - case Ndis802_11AuthModeWPAPSK: - case Ndis802_11AuthModeWPA1PSKWPA2PSK: - pRsnie_auth->acount = 1; - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4); - break; - - case Ndis802_11AuthModeWPANone: - pRsnie_auth->acount = 1; - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4); - break; - } + } + } else { + switch (AuthMode) { + case Ndis802_11AuthModeWPA: + case Ndis802_11AuthModeWPA1WPA2: + NdisMoveMemory(pRsnie_auth->auth[0].oui, + OUI_WPA_8021X_AKM, 4); + break; + + case Ndis802_11AuthModeWPAPSK: + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + NdisMoveMemory(pRsnie_auth->auth[0].oui, + OUI_WPA_PSK_AKM, 4); + break; + + case Ndis802_11AuthModeWPANone: + NdisMoveMemory(pRsnie_auth->auth[0].oui, + OUI_WPA_NONE_AKM, 4); + break; + default: + AkmCnt = 0; + break; + } } + pRsnie_auth->acount = AkmCnt; pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount); - (*rsn_len) += sizeof(RSNIE_AUTH); // update current RSNIE length + /* update current RSNIE length */ + (*rsn_len) += (sizeof(struct rt_rsnie_auth) + (4 * (AkmCnt - 1))); } @@ -555,7 +1794,7 @@ static VOID RTMPInsertRsnIeAKM( Arguments: pAd - pointer to our pAdapter context - ElementID - indicate the WPA1 or WPA2 + ElementID - indicate the WPA1 or WPA2 apidx - indicate the interface index Return Value: @@ -564,29 +1803,25 @@ static VOID RTMPInsertRsnIeAKM( ======================================================================== */ -static VOID RTMPInsertRsnIeCap( - IN PRTMP_ADAPTER pAd, - IN UCHAR ElementID, - IN UCHAR apidx, - OUT PUCHAR pRsnIe, - OUT UCHAR *rsn_len) +static void RTMPMakeRsnIeCap(struct rt_rtmp_adapter *pAd, + u8 ElementID, + u8 apidx, + u8 *pRsnIe, u8 * rsn_len) { - RSN_CAPABILITIES *pRSN_Cap; + RSN_CAPABILITIES *pRSN_Cap; - // it could be ignored in WPA1 mode + /* it could be ignored in WPA1 mode */ if (ElementID == WpaIe) return; - pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len)); - + pRSN_Cap = (RSN_CAPABILITIES *) (pRsnIe + (*rsn_len)); pRSN_Cap->word = cpu2le16(pRSN_Cap->word); - (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length + (*rsn_len) += sizeof(RSN_CAPABILITIES); /* update current RSNIE length */ } - /* ======================================================================== @@ -595,8 +1830,8 @@ static VOID RTMPInsertRsnIeCap( Arguments: pAd - pointer to our pAdapter context - AuthMode - indicate the authentication mode - WepStatus - indicate the encryption type + AuthMode - indicate the authentication mode + WepStatus - indicate the encryption type apidx - indicate the interface index Return Value: @@ -605,48 +1840,43 @@ static VOID RTMPInsertRsnIeCap( ======================================================================== */ -VOID RTMPMakeRSNIE( - IN PRTMP_ADAPTER pAd, - IN UINT AuthMode, - IN UINT WepStatus, - IN UCHAR apidx) -{ - PUCHAR pRsnIe = NULL; // primary RSNIE - UCHAR *rsnielen_cur_p = 0; // the length of the primary RSNIE - UCHAR *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE - UCHAR PrimaryRsnie; - BOOLEAN bMixCipher = FALSE; // indicate the pairwise and group cipher are different - UCHAR p_offset; - WPA_MIX_PAIR_CIPHER FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES; // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode +void RTMPMakeRSNIE(struct rt_rtmp_adapter *pAd, + u32 AuthMode, u32 WepStatus, u8 apidx) +{ + u8 *pRsnIe = NULL; /* primary RSNIE */ + u8 *rsnielen_cur_p = 0; /* the length of the primary RSNIE */ + u8 *rsnielen_ex_cur_p = 0; /* the length of the secondary RSNIE */ + u8 PrimaryRsnie; + BOOLEAN bMixCipher = FALSE; /* indicate the pairwise and group cipher are different */ + u8 p_offset; + WPA_MIX_PAIR_CIPHER FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES; /* it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode */ rsnielen_cur_p = NULL; rsnielen_ex_cur_p = NULL; { { - if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) - { + if (pAd->StaCfg.WpaSupplicantUP != + WPA_SUPPLICANT_DISABLE) { if (AuthMode < Ndis802_11AuthModeWPA) return; - } - else - { - // Support WPAPSK or WPA2PSK in STA-Infra mode - // Support WPANone in STA-Adhoc mode + } else { + /* Support WPAPSK or WPA2PSK in STA-Infra mode */ + /* Support WPANone in STA-Adhoc mode */ if ((AuthMode != Ndis802_11AuthModeWPAPSK) && - (AuthMode != Ndis802_11AuthModeWPA2PSK) && - (AuthMode != Ndis802_11AuthModeWPANone) - ) + (AuthMode != Ndis802_11AuthModeWPA2PSK) && + (AuthMode != Ndis802_11AuthModeWPANone) + ) return; } - DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n")); + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPMakeRSNIE(STA)\n")); - // Zero RSNIE context + /* Zero RSNIE context */ pAd->StaCfg.RSNIE_Len = 0; NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE); - // Pointer to RSNIE + /* Pointer to RSNIE */ rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len; pRsnIe = pAd->StaCfg.RSN_IE; @@ -654,34 +1884,35 @@ VOID RTMPMakeRSNIE( } } - // indicate primary RSNIE as WPA or WPA2 + /* indicate primary RSNIE as WPA or WPA2 */ if ((AuthMode == Ndis802_11AuthModeWPA) || - (AuthMode == Ndis802_11AuthModeWPAPSK) || - (AuthMode == Ndis802_11AuthModeWPANone) || - (AuthMode == Ndis802_11AuthModeWPA1WPA2) || - (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + (AuthMode == Ndis802_11AuthModeWPAPSK) || + (AuthMode == Ndis802_11AuthModeWPANone) || + (AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) PrimaryRsnie = WpaIe; else PrimaryRsnie = Wpa2Ie; { - // Build the primary RSNIE - // 1. insert cipher suite - RTMPInsertRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset); + /* Build the primary RSNIE */ + /* 1. insert cipher suite */ + RTMPMakeRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, + FlexibleCipher, pRsnIe, &p_offset); - // 2. insert AKM - RTMPInsertRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset); + /* 2. insert AKM */ + RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, + &p_offset); - // 3. insert capability - RTMPInsertRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); + /* 3. insert capability */ + RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); } - // 4. update the RSNIE length + /* 4. update the RSNIE length */ *rsnielen_cur_p = p_offset; hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p)); - } /* @@ -693,144 +1924,1093 @@ VOID RTMPMakeRSNIE( pAd - pointer to our pAdapter context pEntry - pointer to active entry pData - the received frame - DataByteCount - the received frame's length + DataByteCount - the received frame's length FromWhichBSSID - indicate the interface index Return: - TRUE - This frame is EAP frame - FALSE - otherwise + TRUE - This frame is EAP frame + FALSE - otherwise ========================================================================== */ -BOOLEAN RTMPCheckWPAframe( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PUCHAR pData, - IN ULONG DataByteCount, - IN UCHAR FromWhichBSSID) -{ - ULONG Body_len; +BOOLEAN RTMPCheckWPAframe(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + u8 *pData, + unsigned long DataByteCount, u8 FromWhichBSSID) +{ + unsigned long Body_len; BOOLEAN Cancelled; + if (DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H)) + return FALSE; + + /* Skip LLC header */ + if (NdisEqualMemory(SNAP_802_1H, pData, 6) || + /* Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL */ + NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) { + pData += 6; + } + /* Skip 2-bytes EAPoL type */ + if (NdisEqualMemory(EAPOL, pData, 2)) { + pData += 2; + } else + return FALSE; + + switch (*(pData + 1)) { + case EAPPacket: + Body_len = (*(pData + 2) << 8) | (*(pData + 3)); + DBGPRINT(RT_DEBUG_TRACE, + ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", + Body_len)); + break; + case EAPOLStart: + DBGPRINT(RT_DEBUG_TRACE, + ("Receive EAPOL-Start frame, TYPE = 1 \n")); + if (pEntry->EnqueueEapolStartTimerRunning != + EAPOL_START_DISABLE) { + DBGPRINT(RT_DEBUG_TRACE, + ("Cancel the EnqueueEapolStartTimerRunning \n")); + RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, + &Cancelled); + pEntry->EnqueueEapolStartTimerRunning = + EAPOL_START_DISABLE; + } + break; + case EAPOLLogoff: + DBGPRINT(RT_DEBUG_TRACE, + ("Receive EAPOLLogoff frame, TYPE = 2 \n")); + break; + case EAPOLKey: + Body_len = (*(pData + 2) << 8) | (*(pData + 3)); + DBGPRINT(RT_DEBUG_TRACE, + ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", + Body_len)); + break; + case EAPOLASFAlert: + DBGPRINT(RT_DEBUG_TRACE, + ("Receive EAPOLASFAlert frame, TYPE = 4 \n")); + break; + default: + return FALSE; + + } + return TRUE; +} + +/* + ========================================================================== + Description: + Report the EAP message type + + Arguments: + msg - EAPOL_PAIR_MSG_1 + EAPOL_PAIR_MSG_2 + EAPOL_PAIR_MSG_3 + EAPOL_PAIR_MSG_4 + EAPOL_GROUP_MSG_1 + EAPOL_GROUP_MSG_2 + + Return: + message type string + + ========================================================================== +*/ +char *GetEapolMsgType(char msg) +{ + if (msg == EAPOL_PAIR_MSG_1) + return "Pairwise Message 1"; + else if (msg == EAPOL_PAIR_MSG_2) + return "Pairwise Message 2"; + else if (msg == EAPOL_PAIR_MSG_3) + return "Pairwise Message 3"; + else if (msg == EAPOL_PAIR_MSG_4) + return "Pairwise Message 4"; + else if (msg == EAPOL_GROUP_MSG_1) + return "Group Message 1"; + else if (msg == EAPOL_GROUP_MSG_2) + return "Group Message 2"; + else + return "Invalid Message"; +} + +/* + ======================================================================== + + Routine Description: + Check Sanity RSN IE of EAPoL message + + Arguments: + + Return Value: + + ======================================================================== +*/ +BOOLEAN RTMPCheckRSNIE(struct rt_rtmp_adapter *pAd, + u8 *pData, + u8 DataLen, + struct rt_mac_table_entry *pEntry, u8 * Offset) +{ + u8 *pVIE; + u8 len; + struct rt_eid * pEid; + BOOLEAN result = FALSE; + + pVIE = pData; + len = DataLen; + *Offset = 0; + + while (len > sizeof(struct rt_rsnie2)) { + pEid = (struct rt_eid *) pVIE; + /* WPA RSN IE */ + if ((pEid->Eid == IE_WPA) + && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) { + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA + || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) + && + (NdisEqualMemory + (pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) + && (pEntry->RSNIE_Len == (pEid->Len + 2))) { + result = TRUE; + } + + *Offset += (pEid->Len + 2); + } + /* WPA2 RSN IE */ + else if ((pEid->Eid == IE_RSN) + && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) { + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 + || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) + && (pEid->Eid == pEntry->RSN_IE[0]) + && ((pEid->Len + 2) >= pEntry->RSNIE_Len) + && + (NdisEqualMemory + (pEid->Octet, &pEntry->RSN_IE[2], + pEntry->RSNIE_Len - 2))) { + + result = TRUE; + } + + *Offset += (pEid->Len + 2); + } else { + break; + } + + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + } + + return result; - if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H)) - return FALSE; - - - // Skip LLC header - if (NdisEqualMemory(SNAP_802_1H, pData, 6) || - // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL - NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) - { - pData += 6; - } - // Skip 2-bytes EAPoL type - if (NdisEqualMemory(EAPOL, pData, 2)) - { - pData += 2; - } - else - return FALSE; - - switch (*(pData+1)) - { - case EAPPacket: - Body_len = (*(pData+2)<<8) | (*(pData+3)); - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len)); - break; - case EAPOLStart: - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n")); - if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE) - { - DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n")); - RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); - pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; - } - break; - case EAPOLLogoff: - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n")); - break; - case EAPOLKey: - Body_len = (*(pData+2)<<8) | (*(pData+3)); - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len)); - break; - case EAPOLASFAlert: - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n")); - break; - default: - return FALSE; - - } - return TRUE; } /* ======================================================================== Routine Description: - Misc function to decrypt AES body + Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK. + GTK is encaptulated in KDE format at p.83 802.11i D10 Arguments: Return Value: Note: - This function references to RFC 3394 for aes key unwrap algorithm. + 802.11i D10 ======================================================================== */ -VOID AES_GTK_KEY_UNWRAP( - IN UCHAR *key, - OUT UCHAR *plaintext, - IN UCHAR c_len, - IN UCHAR *ciphertext) +BOOLEAN RTMPParseEapolKeyData(struct rt_rtmp_adapter *pAd, + u8 *pKeyData, + u8 KeyDataLen, + u8 GroupKeyIndex, + u8 MsgType, + IN BOOLEAN bWPA2, struct rt_mac_table_entry *pEntry) +{ + struct rt_kde_encap * pKDE = NULL; + u8 *pMyKeyData = pKeyData; + u8 KeyDataLength = KeyDataLen; + u8 GTKLEN = 0; + u8 DefaultIdx = 0; + u8 skip_offset; + + /* Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it */ + if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3) { + /* Check RSN IE whether it is WPA2/WPA2PSK */ + if (!RTMPCheckRSNIE + (pAd, pKeyData, KeyDataLen, pEntry, &skip_offset)) { + /* send wireless event - for RSN IE different */ + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, + IW_RSNIE_DIFF_EVENT_FLAG, + pEntry->Addr, + pEntry->apidx, 0); + + DBGPRINT(RT_DEBUG_ERROR, + ("RSN_IE Different in msg %d of 4-way handshake!\n", + MsgType)); + hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen); + hex_dump("Desired RSN_IE ", pEntry->RSN_IE, + pEntry->RSNIE_Len); + + return FALSE; + } else { + if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3) { + WpaShowAllsuite(pMyKeyData, skip_offset); + + /* skip RSN IE */ + pMyKeyData += skip_offset; + KeyDataLength -= skip_offset; + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", + skip_offset)); + } else + return TRUE; + } + } + + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", + KeyDataLength)); + /*hex_dump("remain data", pMyKeyData, KeyDataLength); */ + /* Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2 */ + if (bWPA2 + && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1)) { + if (KeyDataLength >= 8) /* KDE format exclude GTK length */ + { + pKDE = (struct rt_kde_encap *) pMyKeyData; + + DefaultIdx = pKDE->GTKEncap.Kid; + + /* Sanity check - KED length */ + if (KeyDataLength < (pKDE->Len + 2)) { + DBGPRINT(RT_DEBUG_ERROR, + ("ERROR: The len from KDE is too short \n")); + return FALSE; + } + /* Get GTK length - refer to IEEE 802.11i-2004 p.82 */ + GTKLEN = pKDE->Len - 6; + if (GTKLEN < LEN_AES_KEY) { + DBGPRINT(RT_DEBUG_ERROR, + ("ERROR: GTK Key length is too short (%d) \n", + GTKLEN)); + return FALSE; + } + + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("ERROR: KDE format length is too short \n")); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", + DefaultIdx, GTKLEN)); + /* skip it */ + pMyKeyData += 8; + KeyDataLength -= 8; + + } else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1) { + DefaultIdx = GroupKeyIndex; + DBGPRINT(RT_DEBUG_TRACE, + ("GTK DefaultKeyID=%d \n", DefaultIdx)); + } + /* Sanity check - shared key index must be 1 ~ 3 */ + if (DefaultIdx < 1 || DefaultIdx > 3) { + DBGPRINT(RT_DEBUG_ERROR, + ("ERROR: GTK Key index(%d) is invalid in %s %s \n", + DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), + GetEapolMsgType(MsgType))); + return FALSE; + } + + { + struct rt_cipher_key *pSharedKey; + + /* set key material, TxMic and RxMic */ + NdisMoveMemory(pAd->StaCfg.GTK, pMyKeyData, 32); + pAd->StaCfg.DefaultKeyId = DefaultIdx; + + pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId]; + + /* Prepare pair-wise key information into shared key table */ + NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key)); + pSharedKey->KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK); + NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16], + LEN_TKIP_RXMICK); + NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24], + LEN_TKIP_TXMICK); + + /* Update Shared Key CipherAlg */ + pSharedKey->CipherAlg = CIPHER_NONE; + if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) + pSharedKey->CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.GroupCipher == + Ndis802_11Encryption3Enabled) + pSharedKey->CipherAlg = CIPHER_AES; + else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled) + pSharedKey->CipherAlg = CIPHER_WEP64; + else if (pAd->StaCfg.GroupCipher == + Ndis802_11GroupWEP104Enabled) + pSharedKey->CipherAlg = CIPHER_WEP128; + + /* Update group key information to ASIC Shared Key Table */ + AsicAddSharedKeyEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pSharedKey->CipherAlg, + pSharedKey->Key, + pSharedKey->TxMic, pSharedKey->RxMic); + + /* Update ASIC WCID attribute table and IVEIV table */ + RTMPAddWcidAttributeEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pSharedKey->CipherAlg, NULL); + } + + return TRUE; + +} + +/* + ======================================================================== + + Routine Description: + Construct EAPoL message for WPA handshaking + Its format is below, + + +--------------------+ + | Protocol Version | 1 octet + +--------------------+ + | Protocol Type | 1 octet + +--------------------+ + | Body Length | 2 octets + +--------------------+ + | Descriptor Type | 1 octet + +--------------------+ + | Key Information | 2 octets + +--------------------+ + | Key Length | 1 octet + +--------------------+ + | Key Repaly Counter | 8 octets + +--------------------+ + | Key Nonce | 32 octets + +--------------------+ + | Key IV | 16 octets + +--------------------+ + | Key RSC | 8 octets + +--------------------+ + | Key ID or Reserved | 8 octets + +--------------------+ + | Key MIC | 16 octets + +--------------------+ + | Key Data Length | 2 octets + +--------------------+ + | Key Data | n octets + +--------------------+ + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + + ======================================================================== +*/ +void ConstructEapolMsg(struct rt_mac_table_entry *pEntry, + u8 GroupKeyWepStatus, + u8 MsgType, + u8 DefaultKeyIdx, + u8 * KeyNonce, + u8 * TxRSC, + u8 * GTK, + u8 * RSNIE, + u8 RSNIE_Len, struct rt_eapol_packet * pMsg) { - UCHAR A[8], BIN[16], BOUT[16]; - UCHAR xor; - INT i, j; - aes_context aesctx; - UCHAR *R; - INT num_blocks = c_len/8; // unit:64bits + BOOLEAN bWPA2 = FALSE; + u8 KeyDescVer; + /* Choose WPA2 or not */ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + bWPA2 = TRUE; - os_alloc_mem(NULL, (PUCHAR *)&R, 512); + /* Init Packet and Fill header */ + pMsg->ProVer = EAPOL_VER; + pMsg->ProType = EAPOLKey; - if (R == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n")); - return; - } /* End of if */ + /* Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field */ + SET_u16_TO_ARRARY(pMsg->Body_Len, LEN_EAPOL_KEY_MSG); + + /* Fill in EAPoL descriptor */ + if (bWPA2) + pMsg->KeyDesc.Type = WPA2_KEY_DESC; + else + pMsg->KeyDesc.Type = WPA1_KEY_DESC; - // Initialize - NdisMoveMemory(A, ciphertext, 8); - //Input plaintext - for(i = 0; i < (c_len-8); i++) + /* Key Descriptor Version (bits 0-2) specifies the key descriptor version type */ { - R[ i] = ciphertext[i + 8]; + /* Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 */ + /* When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used. */ + KeyDescVer = + (((pEntry->WepStatus == Ndis802_11Encryption3Enabled) + || (GroupKeyWepStatus == + Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) + : (DESC_TYPE_TKIP)); } - rtmp_aes_set_key(&aesctx, key, 128); + pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer; - for(j = 5; j >= 0; j--) + /* Specify Key Type as Group(0) or Pairwise(1) */ + if (MsgType >= EAPOL_GROUP_MSG_1) + pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY; + else + pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; + + /* Specify Key Index, only group_msg1_WPA1 */ + if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)) + pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx; + + if (MsgType == EAPOL_PAIR_MSG_3) + pMsg->KeyDesc.KeyInfo.Install = 1; + + if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) + || (MsgType == EAPOL_GROUP_MSG_1)) + pMsg->KeyDesc.KeyInfo.KeyAck = 1; + + if (MsgType != EAPOL_PAIR_MSG_1) + pMsg->KeyDesc.KeyInfo.KeyMic = 1; + + if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || + (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) { + pMsg->KeyDesc.KeyInfo.Secure = 1; + } + + if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || + (MsgType == EAPOL_GROUP_MSG_1))) { + pMsg->KeyDesc.KeyInfo.EKD_DL = 1; + } + /* key Information element has done. */ + *(u16 *) (&pMsg->KeyDesc.KeyInfo) = + cpu2le16(*(u16 *) (&pMsg->KeyDesc.KeyInfo)); + + /* Fill in Key Length */ { - for(i = (num_blocks-1); i > 0; i--) - { - xor = (num_blocks -1 )* j + i; - NdisMoveMemory(BIN, A, 8); - BIN[7] = A[7] ^ xor; - NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8); - rtmp_aes_decrypt(&aesctx, BIN, BOUT); - NdisMoveMemory(A, &BOUT[0], 8); - NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8); + if (MsgType >= EAPOL_GROUP_MSG_1) { + /* the length of group key cipher */ + pMsg->KeyDesc.KeyLength[1] = + ((GroupKeyWepStatus == + Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : + LEN_AES_KEY); + } else { + /* the length of pairwise key cipher */ + pMsg->KeyDesc.KeyLength[1] = + ((pEntry->WepStatus == + Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : + LEN_AES_KEY); } } - // OUTPUT - for(i = 0; i < c_len; i++) - { - plaintext[i] = R[i]; + /* Fill in replay counter */ + NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, + LEN_KEY_DESC_REPLAY); + + /* Fill Key Nonce field */ + /* ANonce : pairwise_msg1 & pairwise_msg3 */ + /* SNonce : pairwise_msg2 */ + /* GNonce : group_msg1_wpa1 */ + if ((MsgType <= EAPOL_PAIR_MSG_3) + || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)))) + NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, + LEN_KEY_DESC_NONCE); + + /* Fill key IV - WPA2 as 0, WPA1 as random */ + if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) { + /* Suggest IV be random number plus some number, */ + NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], + LEN_KEY_DESC_IV); + pMsg->KeyDesc.KeyIv[15] += 2; + } + /* Fill Key RSC field */ + /* It contains the RSC for the GTK being installed. */ + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) + || (MsgType == EAPOL_GROUP_MSG_1)) { + NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6); + } + /* Clear Key MIC field for MIC calculation later */ + NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + + ConstructEapolKeyData(pEntry, + GroupKeyWepStatus, + KeyDescVer, + MsgType, + DefaultKeyIdx, GTK, RSNIE, RSNIE_Len, pMsg); + + /* Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. */ + if (MsgType != EAPOL_PAIR_MSG_1) { + CalculateMIC(KeyDescVer, pEntry->PTK, pMsg); + } + + DBGPRINT(RT_DEBUG_TRACE, + ("===> ConstructEapolMsg for %s %s\n", + ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); + DBGPRINT(RT_DEBUG_TRACE, + (" Body length = %d \n", + CONV_ARRARY_TO_u16(pMsg->Body_Len))); + DBGPRINT(RT_DEBUG_TRACE, + (" Key length = %d \n", + CONV_ARRARY_TO_u16(pMsg->KeyDesc.KeyLength))); + +} + +/* + ======================================================================== + + Routine Description: + Construct the Key Data field of EAPoL message + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry, + u8 GroupKeyWepStatus, + u8 keyDescVer, + u8 MsgType, + u8 DefaultKeyIdx, + u8 * GTK, + u8 * RSNIE, + u8 RSNIE_LEN, struct rt_eapol_packet * pMsg) +{ + u8 *mpool, *Key_Data, *Rc4GTK; + u8 ekey[(LEN_KEY_DESC_IV + LEN_EAP_EK)]; + unsigned long data_offset; + BOOLEAN bWPA2Capable = FALSE; + struct rt_rtmp_adapter *pAd = pEntry->pAd; + BOOLEAN GTK_Included = FALSE; + + /* Choose WPA2 or not */ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + bWPA2Capable = TRUE; + + if (MsgType == EAPOL_PAIR_MSG_1 || + MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) + return; + + /* allocate memory pool */ + os_alloc_mem(NULL, (u8 **) & mpool, 1500); + + if (mpool == NULL) + return; + + /* Rc4GTK Len = 512 */ + Rc4GTK = (u8 *) ROUND_UP(mpool, 4); + /* Key_Data Len = 512 */ + Key_Data = (u8 *) ROUND_UP(Rc4GTK + 512, 4); + + NdisZeroMemory(Key_Data, 512); + SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0); + data_offset = 0; + + /* Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 */ + if (RSNIE_LEN + && ((MsgType == EAPOL_PAIR_MSG_2) + || (MsgType == EAPOL_PAIR_MSG_3))) { + u8 *pmkid_ptr = NULL; + u8 pmkid_len = 0; + + RTMPInsertRSNIE(&Key_Data[data_offset], + &data_offset, + RSNIE, RSNIE_LEN, pmkid_ptr, pmkid_len); + } + + /* Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2 */ + if (bWPA2Capable + && ((MsgType == EAPOL_PAIR_MSG_3) + || (MsgType == EAPOL_GROUP_MSG_1))) { + /* Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h */ + Key_Data[data_offset + 0] = 0xDD; + + if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) { + Key_Data[data_offset + 1] = 0x16; /* 4+2+16(OUI+DataType+DataField) */ + } else { + Key_Data[data_offset + 1] = 0x26; /* 4+2+32(OUI+DataType+DataField) */ + } + + Key_Data[data_offset + 2] = 0x00; + Key_Data[data_offset + 3] = 0x0F; + Key_Data[data_offset + 4] = 0xAC; + Key_Data[data_offset + 5] = 0x01; + + /* GTK KDE format - 802.11i-2004 Figure-43x */ + Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03); + Key_Data[data_offset + 7] = 0x00; /* Reserved Byte */ + + data_offset += 8; + } + + /* Encapsulate GTK */ + /* Only for pairwise_msg3_WPA2 and group_msg1 */ + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) + || (MsgType == EAPOL_GROUP_MSG_1)) { + /* Fill in GTK */ + if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) { + NdisMoveMemory(&Key_Data[data_offset], GTK, + LEN_AES_KEY); + data_offset += LEN_AES_KEY; + } else { + NdisMoveMemory(&Key_Data[data_offset], GTK, + TKIP_GTK_LENGTH); + data_offset += TKIP_GTK_LENGTH; + } + + GTK_Included = TRUE; + } + + /* This whole key-data field shall be encrypted if a GTK is included. */ + /* Encrypt the data material in key data field with KEK */ + if (GTK_Included) { + /*hex_dump("GTK_Included", Key_Data, data_offset); */ + + if ((keyDescVer == DESC_TYPE_AES)) { + u8 remainder = 0; + u8 pad_len = 0; + + /* Key Descriptor Version 2 or 3: AES key wrap, defined in IETF RFC 3394, */ + /* shall be used to encrypt the Key Data field using the KEK field from */ + /* the derived PTK. */ + + /* If the Key Data field uses the NIST AES key wrap, then the Key Data field */ + /* shall be padded before encrypting if the key data length is less than 16 */ + /* octets or if it is not a multiple of 8. The padding consists of appending */ + /* a single octet 0xdd followed by zero or more 0x00 octets. */ + if ((remainder = data_offset & 0x07) != 0) { + int i; + + pad_len = (8 - remainder); + Key_Data[data_offset] = 0xDD; + for (i = 1; i < pad_len; i++) + Key_Data[data_offset + i] = 0; + + data_offset += pad_len; + } + + AES_GTK_KEY_WRAP(&pEntry->PTK[16], Key_Data, + data_offset, Rc4GTK); + /* AES wrap function will grow 8 bytes in length */ + data_offset += 8; + } else { + /* Key Descriptor Version 1: ARC4 is used to encrypt the Key Data field + using the KEK field from the derived PTK. */ + + /* PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV) */ + /* put TxTsc in Key RSC field */ + pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; /*Init crc32. */ + + /* ekey is the contanetion of IV-field, and PTK[16]->PTK[31] */ + NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, + LEN_KEY_DESC_IV); + NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &pEntry->PTK[16], + LEN_EAP_EK); + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); /*INIT SBOX, KEYLEN+3(IV) */ + pAd->PrivateInfo.FCSCRC32 = + RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, + data_offset); + WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, + Key_Data, data_offset); + } + + NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset); + } else { + NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset); + } + + /* Update key data length field and total body length */ + SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, data_offset); + INC_u16_TO_ARRARY(pMsg->Body_Len, data_offset); + + os_free_mem(NULL, mpool); + +} + +/* + ======================================================================== + + Routine Description: + Calcaulate MIC. It is used during 4-ways handsharking. + + Arguments: + pAd - pointer to our pAdapter context + PeerWepStatus - indicate the encryption type + + Return Value: + + Note: + + ======================================================================== +*/ +static void CalculateMIC(u8 KeyDescVer, + u8 * PTK, struct rt_eapol_packet * pMsg) +{ + u8 *OutBuffer; + unsigned long FrameLen = 0; + u8 mic[LEN_KEY_DESC_MIC]; + u8 digest[80]; + + /* allocate memory for MIC calculation */ + os_alloc_mem(NULL, (u8 **) & OutBuffer, 512); + + if (OutBuffer == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("CalculateMIC: no memory!\n")); + return; + } + /* make a frame for calculating MIC. */ + MakeOutgoingFrame(OutBuffer, &FrameLen, + CONV_ARRARY_TO_u16(pMsg->Body_Len) + 4, pMsg, + END_OF_ARGS); + + NdisZeroMemory(mic, sizeof(mic)); + + /* Calculate MIC */ + if (KeyDescVer == DESC_TYPE_AES) { + HMAC_SHA1(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, digest, + SHA1_DIGEST_SIZE); + NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); + } else { + HMAC_MD5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic, + MD5_DIGEST_SIZE); + } + + /* store the calculated MIC */ + NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC); + + os_free_mem(NULL, OutBuffer); +} + +/* + ======================================================================== + + Routine Description: + Some received frames can't decrypt by Asic, so decrypt them by software. + + Arguments: + pAd - pointer to our pAdapter context + PeerWepStatus - indicate the encryption type + + Return Value: + NDIS_STATUS_SUCCESS - decryption successful + NDIS_STATUS_FAILURE - decryption failure + + ======================================================================== +*/ +int RTMPSoftDecryptBroadCastData(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, + IN NDIS_802_11_ENCRYPTION_STATUS + GroupCipher, struct rt_cipher_key *pShard_key) +{ + struct rt_rxwi * pRxWI = pRxBlk->pRxWI; + + /* handle WEP decryption */ + if (GroupCipher == Ndis802_11Encryption1Enabled) { + if (RTMPSoftDecryptWEP + (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, + pShard_key)) { + + /*Minus IV[4] & ICV[4] */ + pRxWI->MPDUtotalByteCount -= 8; + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("ERROR : Software decrypt WEP data fails.\n")); + /* give up this frame */ + return NDIS_STATUS_FAILURE; + } + } + /* handle TKIP decryption */ + else if (GroupCipher == Ndis802_11Encryption2Enabled) { + if (RTMPSoftDecryptTKIP + (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, + pShard_key)) { + + /*Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV */ + pRxWI->MPDUtotalByteCount -= 20; + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("ERROR : RTMPSoftDecryptTKIP Failed\n")); + /* give up this frame */ + return NDIS_STATUS_FAILURE; + } + } + /* handle AES decryption */ + else if (GroupCipher == Ndis802_11Encryption3Enabled) { + if (RTMPSoftDecryptAES + (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, + pShard_key)) { + + /*8 bytes MIC, 8 bytes IV/EIV (CCMP Header) */ + pRxWI->MPDUtotalByteCount -= 16; + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("ERROR : RTMPSoftDecryptAES Failed\n")); + /* give up this frame */ + return NDIS_STATUS_FAILURE; + } + } else { + /* give up this frame */ + return NDIS_STATUS_FAILURE; + } + + return NDIS_STATUS_SUCCESS; + +} + +u8 *GetSuiteFromRSNIE(u8 *rsnie, + u32 rsnie_len, u8 type, u8 * count) +{ + struct rt_eid * pEid; + int len; + u8 *pBuf; + int offset = 0; + struct rt_rsnie_auth *pAkm; + u16 acount; + BOOLEAN isWPA2 = FALSE; + + pEid = (struct rt_eid *) rsnie; + len = rsnie_len - 2; /* exclude IE and length */ + pBuf = (u8 *)& pEid->Octet[0]; + + /* set default value */ + *count = 0; + + /* Check length */ + if ((len <= 0) || (pEid->Len != len)) { + DBGPRINT_ERR(("%s : The length is invalid\n", __func__)); + return NULL; + } + /* Check WPA or WPA2 */ + if (pEid->Eid == IE_WPA) { + struct rt_rsnie *pRsnie = (struct rt_rsnie *)pBuf; + u16 ucount; + + if (len < sizeof(struct rt_rsnie)) { + DBGPRINT_ERR(("%s : The length is too short for WPA\n", + __func__)); + return NULL; + } + /* Get the count of pairwise cipher */ + ucount = cpu2le16(pRsnie->ucount); + if (ucount > 2) { + DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount)); + return NULL; + } + /* Get the group cipher */ + if (type == GROUP_SUITE) { + *count = 1; + return pRsnie->mcast; + } + /* Get the pairwise cipher suite */ + else if (type == PAIRWISE_SUITE) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s : The count of pairwise cipher is %d\n", + __func__, ucount)); + *count = ucount; + return pRsnie->ucast[0].oui; + } + + offset = sizeof(struct rt_rsnie) + (4 * (ucount - 1)); + + } else if (pEid->Eid == IE_RSN) { + struct rt_rsnie2 *pRsnie = (struct rt_rsnie2 *)pBuf; + u16 ucount; + + isWPA2 = TRUE; + + if (len < sizeof(struct rt_rsnie2)) { + DBGPRINT_ERR(("%s : The length is too short for WPA2\n", + __func__)); + return NULL; + } + /* Get the count of pairwise cipher */ + ucount = cpu2le16(pRsnie->ucount); + if (ucount > 2) { + DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount)); + return NULL; + } + /* Get the group cipher */ + if (type == GROUP_SUITE) { + *count = 1; + return pRsnie->mcast; + } + /* Get the pairwise cipher suite */ + else if (type == PAIRWISE_SUITE) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s : The count of pairwise cipher is %d\n", + __func__, ucount)); + *count = ucount; + return pRsnie->ucast[0].oui; + } + + offset = sizeof(struct rt_rsnie2) + (4 * (ucount - 1)); + + } else { + DBGPRINT_ERR(("%s : Unknown IE (%d)\n", __func__, pEid->Eid)); + return NULL; } + /* skip group cipher and pairwise cipher suite */ + pBuf += offset; + len -= offset; + + if (len < sizeof(struct rt_rsnie_auth)) { + DBGPRINT_ERR(("%s : The length of RSNIE is too short\n", + __func__)); + return NULL; + } + /* pointer to AKM count */ + pAkm = (struct rt_rsnie_auth *)pBuf; + + /* Get the count of pairwise cipher */ + acount = cpu2le16(pAkm->acount); + if (acount > 2) { + DBGPRINT_ERR(("%s : The count(%d) of AKM is invlaid\n", + __func__, acount)); + return NULL; + } + /* Get the AKM suite */ + if (type == AKM_SUITE) { + DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of AKM is %d\n", + __func__, acount)); + *count = acount; + return pAkm->auth[0].oui; + } + offset = sizeof(struct rt_rsnie_auth) + (4 * (acount - 1)); + + pBuf += offset; + len -= offset; + + /* The remaining length must larger than (RSN-Capability(2) + PMKID-Count(2) + PMKID(16~)) */ + if (len >= (sizeof(RSN_CAPABILITIES) + 2 + LEN_PMKID)) { + /* Skip RSN capability and PMKID-Count */ + pBuf += (sizeof(RSN_CAPABILITIES) + 2); + len -= (sizeof(RSN_CAPABILITIES) + 2); + + /* Get PMKID */ + if (type == PMKID_LIST) { + *count = 1; + return pBuf; + } + } else { + DBGPRINT_ERR(("%s : it can't get any more information beyond AKM \n", __func__)); + return NULL; + } + + *count = 0; + /*DBGPRINT_ERR(("%s : The type(%d) doesn't support \n", __func__, type)); */ + return NULL; + +} + +void WpaShowAllsuite(u8 *rsnie, u32 rsnie_len) +{ + u8 *pSuite = NULL; + u8 count; + + hex_dump("RSNIE", rsnie, rsnie_len); + + /* group cipher */ + if ((pSuite = + GetSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE, + &count)) != NULL) { + hex_dump("group cipher", pSuite, 4 * count); + } + /* pairwise cipher */ + if ((pSuite = + GetSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE, + &count)) != NULL) { + hex_dump("pairwise cipher", pSuite, 4 * count); + } + /* AKM */ + if ((pSuite = + GetSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count)) != NULL) { + hex_dump("AKM suite", pSuite, 4 * count); + } + /* PMKID */ + if ((pSuite = + GetSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count)) != NULL) { + hex_dump("PMKID", pSuite, LEN_PMKID); + } + +} + +void RTMPInsertRSNIE(u8 *pFrameBuf, + unsigned long *pFrameLen, + u8 *rsnie_ptr, + u8 rsnie_len, + u8 *pmkid_ptr, u8 pmkid_len) +{ + u8 *pTmpBuf; + unsigned long TempLen = 0; + u8 extra_len = 0; + u16 pmk_count = 0; + u8 ie_num; + u8 total_len = 0; + u8 WPA2_OUI[3] = { 0x00, 0x0F, 0xAC }; + + pTmpBuf = pFrameBuf; + + /* PMKID-List Must larger than 0 and the multiple of 16. */ + if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0)) { + extra_len = sizeof(u16)+ pmkid_len; + + pmk_count = (pmkid_len >> 4); + pmk_count = cpu2le16(pmk_count); + } else { + DBGPRINT(RT_DEBUG_WARN, + ("%s : The length is PMKID-List is invalid (%d), so don't insert it.\n", + __func__, pmkid_len)); + } + + if (rsnie_len != 0) { + ie_num = IE_WPA; + total_len = rsnie_len; + + if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI))) { + ie_num = IE_RSN; + total_len += extra_len; + } + + /* construct RSNIE body */ + MakeOutgoingFrame(pTmpBuf, &TempLen, + 1, &ie_num, + 1, &total_len, + rsnie_len, rsnie_ptr, END_OF_ARGS); + + pTmpBuf += TempLen; + *pFrameLen = *pFrameLen + TempLen; + + if (ie_num == IE_RSN) { + /* Insert PMKID-List field */ + if (extra_len > 0) { + MakeOutgoingFrame(pTmpBuf, &TempLen, + 2, &pmk_count, + pmkid_len, pmkid_ptr, + END_OF_ARGS); + + pTmpBuf += TempLen; + *pFrameLen = *pFrameLen + TempLen; + } + } + } - os_free_mem(NULL, R); + return; } diff --git a/drivers/staging/rt2860/common/crypt_hmac.c b/drivers/staging/rt2860/common/crypt_hmac.c new file mode 100644 index 0000000000000000000000000000000000000000..d7ab08ec1a41799adfe15cca59cb8b667fefc07d --- /dev/null +++ b/drivers/staging/rt2860/common/crypt_hmac.c @@ -0,0 +1,187 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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 "../crypt_hmac.h" + +#ifdef HMAC_SHA1_SUPPORT +/* +======================================================================== +Routine Description: + HMAC using SHA1 hash function + +Arguments: + key Secret key + key_len The length of the key in bytes + message Message context + message_len The length of message in bytes + macLen Request the length of message authentication code + +Return Value: + mac Message authentication code + +Note: + None +======================================================================== +*/ +void HMAC_SHA1(IN const u8 Key[], + u32 KeyLen, + IN const u8 Message[], + u32 MessageLen, u8 MAC[], u32 MACLen) +{ + struct rt_sha1_ctx sha_ctx1; + struct rt_sha1_ctx sha_ctx2; + u8 K0[SHA1_BLOCK_SIZE]; + u8 Digest[SHA1_DIGEST_SIZE]; + u32 index; + + NdisZeroMemory(&sha_ctx1, sizeof(struct rt_sha1_ctx)); + NdisZeroMemory(&sha_ctx2, sizeof(struct rt_sha1_ctx)); + /* + * If the length of K = B(Block size): K0 = K. + * If the length of K > B: hash K to obtain an L byte string, + * then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00). + * If the length of K < B: append zeros to the end of K to create a B-byte string K0 + */ + NdisZeroMemory(K0, SHA1_BLOCK_SIZE); + if (KeyLen <= SHA1_BLOCK_SIZE) + NdisMoveMemory(K0, Key, KeyLen); + else + RT_SHA1(Key, KeyLen, K0); + /* End of if */ + + /* Exclusive-Or K0 with ipad */ + /* ipad: Inner pad; the byte x¡¦36¡¦ repeated B times. */ + for (index = 0; index < SHA1_BLOCK_SIZE; index++) + K0[index] ^= 0x36; + /* End of for */ + + RT_SHA1_Init(&sha_ctx1); + /* H(K0^ipad) */ + SHA1_Append(&sha_ctx1, K0, sizeof(K0)); + /* H((K0^ipad)||text) */ + SHA1_Append(&sha_ctx1, Message, MessageLen); + SHA1_End(&sha_ctx1, Digest); + + /* Exclusive-Or K0 with opad and remove ipad */ + /* opad: Outer pad; the byte x¡¦5c¡¦ repeated B times. */ + for (index = 0; index < SHA1_BLOCK_SIZE; index++) + K0[index] ^= 0x36 ^ 0x5c; + /* End of for */ + + RT_SHA1_Init(&sha_ctx2); + /* H(K0^opad) */ + SHA1_Append(&sha_ctx2, K0, sizeof(K0)); + /* H( (K0^opad) || H((K0^ipad)||text) ) */ + SHA1_Append(&sha_ctx2, Digest, SHA1_DIGEST_SIZE); + SHA1_End(&sha_ctx2, Digest); + + if (MACLen > SHA1_DIGEST_SIZE) + NdisMoveMemory(MAC, Digest, SHA1_DIGEST_SIZE); + else + NdisMoveMemory(MAC, Digest, MACLen); +} /* End of HMAC_SHA1 */ +#endif /* HMAC_SHA1_SUPPORT */ + +#ifdef HMAC_MD5_SUPPORT +/* +======================================================================== +Routine Description: + HMAC using MD5 hash function + +Arguments: + key Secret key + key_len The length of the key in bytes + message Message context + message_len The length of message in bytes + macLen Request the length of message authentication code + +Return Value: + mac Message authentication code + +Note: + None +======================================================================== +*/ +void HMAC_MD5(IN const u8 Key[], + u32 KeyLen, + IN const u8 Message[], + u32 MessageLen, u8 MAC[], u32 MACLen) +{ + struct rt_md5_ctx_struc md5_ctx1; + struct rt_md5_ctx_struc md5_ctx2; + u8 K0[MD5_BLOCK_SIZE]; + u8 Digest[MD5_DIGEST_SIZE]; + u32 index; + + NdisZeroMemory(&md5_ctx1, sizeof(struct rt_md5_ctx_struc)); + NdisZeroMemory(&md5_ctx2, sizeof(struct rt_md5_ctx_struc)); + /* + * If the length of K = B(Block size): K0 = K. + * If the length of K > B: hash K to obtain an L byte string, + * then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00). + * If the length of K < B: append zeros to the end of K to create a B-byte string K0 + */ + NdisZeroMemory(K0, MD5_BLOCK_SIZE); + if (KeyLen <= MD5_BLOCK_SIZE) { + NdisMoveMemory(K0, Key, KeyLen); + } else { + RT_MD5(Key, KeyLen, K0); + } + + /* Exclusive-Or K0 with ipad */ + /* ipad: Inner pad; the byte x¡¦36¡¦ repeated B times. */ + for (index = 0; index < MD5_BLOCK_SIZE; index++) + K0[index] ^= 0x36; + /* End of for */ + + MD5_Init(&md5_ctx1); + /* H(K0^ipad) */ + MD5_Append(&md5_ctx1, K0, sizeof(K0)); + /* H((K0^ipad)||text) */ + MD5_Append(&md5_ctx1, Message, MessageLen); + MD5_End(&md5_ctx1, Digest); + + /* Exclusive-Or K0 with opad and remove ipad */ + /* opad: Outer pad; the byte x¡¦5c¡¦ repeated B times. */ + for (index = 0; index < MD5_BLOCK_SIZE; index++) + K0[index] ^= 0x36 ^ 0x5c; + /* End of for */ + + MD5_Init(&md5_ctx2); + /* H(K0^opad) */ + MD5_Append(&md5_ctx2, K0, sizeof(K0)); + /* H( (K0^opad) || H((K0^ipad)||text) ) */ + MD5_Append(&md5_ctx2, Digest, MD5_DIGEST_SIZE); + MD5_End(&md5_ctx2, Digest); + + if (MACLen > MD5_DIGEST_SIZE) + NdisMoveMemory(MAC, Digest, MD5_DIGEST_SIZE); + else + NdisMoveMemory(MAC, Digest, MACLen); +} /* End of HMAC_SHA256 */ +#endif /* HMAC_MD5_SUPPORT */ + +/* End of crypt_hmac.c */ diff --git a/drivers/staging/rt2860/common/crypt_md5.c b/drivers/staging/rt2860/common/crypt_md5.c new file mode 100644 index 0000000000000000000000000000000000000000..6deab659c22bd0df2c243a9bb19f2f9c30bfa395 --- /dev/null +++ b/drivers/staging/rt2860/common/crypt_md5.c @@ -0,0 +1,339 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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 "../crypt_md5.h" + +#ifdef MD5_SUPPORT +/* + * F, G, H and I are basic MD5 functions. + */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +#define ROTL(x,n,w) ((x << n) | (x >> (w - n))) +#define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */ + +#define ROUND1(a, b, c, d, x, s, ac) { \ + (a) += F((b),(c),(d)) + (x) + (u32)(ac); \ + (a) = ROTL32((a),(s)); \ + (a) += (b); \ +} +#define ROUND2(a, b, c, d, x, s, ac) { \ + (a) += G((b),(c),(d)) + (x) + (u32)(ac); \ + (a) = ROTL32((a),(s)); \ + (a) += (b); \ +} +#define ROUND3(a, b, c, d, x, s, ac) { \ + (a) += H((b),(c),(d)) + (x) + (u32)(ac); \ + (a) = ROTL32((a),(s)); \ + (a) += (b); \ +} +#define ROUND4(a, b, c, d, x, s, ac) { \ + (a) += I((b),(c),(d)) + (x) + (u32)(ac); \ + (a) = ROTL32((a),(s)); \ + (a) += (b); \ +} +static const u32 MD5_DefaultHashValue[4] = { + 0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL +}; +#endif /* MD5_SUPPORT */ + +#ifdef MD5_SUPPORT +/* +======================================================================== +Routine Description: + Initial Md5_CTX_STRUC + +Arguments: + pMD5_CTX Pointer to Md5_CTX_STRUC + +Return Value: + None + +Note: + None +======================================================================== +*/ +void MD5_Init(struct rt_md5_ctx_struc *pMD5_CTX) +{ + NdisMoveMemory(pMD5_CTX->HashValue, MD5_DefaultHashValue, + sizeof(MD5_DefaultHashValue)); + NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE); + pMD5_CTX->BlockLen = 0; + pMD5_CTX->MessageLen = 0; +} /* End of MD5_Init */ + +/* +======================================================================== +Routine Description: + MD5 computation for one block (512 bits) + +Arguments: + pMD5_CTX Pointer to Md5_CTX_STRUC + +Return Value: + None + +Note: + T[i] := floor(abs(sin(i + 1)) * (2 pow 32)), i is number of round +======================================================================== +*/ +void MD5_Hash(struct rt_md5_ctx_struc *pMD5_CTX) +{ + u32 X_i; + u32 X[16]; + u32 a, b, c, d; + + /* Prepare the message schedule, {X_i} */ + NdisMoveMemory(X, pMD5_CTX->Block, MD5_BLOCK_SIZE); + for (X_i = 0; X_i < 16; X_i++) + X[X_i] = cpu2le32(X[X_i]); /* Endian Swap */ + /* End of for */ + + /* MD5 hash computation */ + /* Initialize the working variables */ + a = pMD5_CTX->HashValue[0]; + b = pMD5_CTX->HashValue[1]; + c = pMD5_CTX->HashValue[2]; + d = pMD5_CTX->HashValue[3]; + + /* + * Round 1 + * Let [abcd k s i] denote the operation + * a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s) + */ + ROUND1(a, b, c, d, X[0], 7, 0xd76aa478); /* 1 */ + ROUND1(d, a, b, c, X[1], 12, 0xe8c7b756); /* 2 */ + ROUND1(c, d, a, b, X[2], 17, 0x242070db); /* 3 */ + ROUND1(b, c, d, a, X[3], 22, 0xc1bdceee); /* 4 */ + ROUND1(a, b, c, d, X[4], 7, 0xf57c0faf); /* 5 */ + ROUND1(d, a, b, c, X[5], 12, 0x4787c62a); /* 6 */ + ROUND1(c, d, a, b, X[6], 17, 0xa8304613); /* 7 */ + ROUND1(b, c, d, a, X[7], 22, 0xfd469501); /* 8 */ + ROUND1(a, b, c, d, X[8], 7, 0x698098d8); /* 9 */ + ROUND1(d, a, b, c, X[9], 12, 0x8b44f7af); /* 10 */ + ROUND1(c, d, a, b, X[10], 17, 0xffff5bb1); /* 11 */ + ROUND1(b, c, d, a, X[11], 22, 0x895cd7be); /* 12 */ + ROUND1(a, b, c, d, X[12], 7, 0x6b901122); /* 13 */ + ROUND1(d, a, b, c, X[13], 12, 0xfd987193); /* 14 */ + ROUND1(c, d, a, b, X[14], 17, 0xa679438e); /* 15 */ + ROUND1(b, c, d, a, X[15], 22, 0x49b40821); /* 16 */ + + /* + * Round 2 + * Let [abcd k s i] denote the operation + * a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s) + */ + ROUND2(a, b, c, d, X[1], 5, 0xf61e2562); /* 17 */ + ROUND2(d, a, b, c, X[6], 9, 0xc040b340); /* 18 */ + ROUND2(c, d, a, b, X[11], 14, 0x265e5a51); /* 19 */ + ROUND2(b, c, d, a, X[0], 20, 0xe9b6c7aa); /* 20 */ + ROUND2(a, b, c, d, X[5], 5, 0xd62f105d); /* 21 */ + ROUND2(d, a, b, c, X[10], 9, 0x2441453); /* 22 */ + ROUND2(c, d, a, b, X[15], 14, 0xd8a1e681); /* 23 */ + ROUND2(b, c, d, a, X[4], 20, 0xe7d3fbc8); /* 24 */ + ROUND2(a, b, c, d, X[9], 5, 0x21e1cde6); /* 25 */ + ROUND2(d, a, b, c, X[14], 9, 0xc33707d6); /* 26 */ + ROUND2(c, d, a, b, X[3], 14, 0xf4d50d87); /* 27 */ + ROUND2(b, c, d, a, X[8], 20, 0x455a14ed); /* 28 */ + ROUND2(a, b, c, d, X[13], 5, 0xa9e3e905); /* 29 */ + ROUND2(d, a, b, c, X[2], 9, 0xfcefa3f8); /* 30 */ + ROUND2(c, d, a, b, X[7], 14, 0x676f02d9); /* 31 */ + ROUND2(b, c, d, a, X[12], 20, 0x8d2a4c8a); /* 32 */ + + /* + * Round 3 + * Let [abcd k s t] denote the operation + * a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s) + */ + ROUND3(a, b, c, d, X[5], 4, 0xfffa3942); /* 33 */ + ROUND3(d, a, b, c, X[8], 11, 0x8771f681); /* 34 */ + ROUND3(c, d, a, b, X[11], 16, 0x6d9d6122); /* 35 */ + ROUND3(b, c, d, a, X[14], 23, 0xfde5380c); /* 36 */ + ROUND3(a, b, c, d, X[1], 4, 0xa4beea44); /* 37 */ + ROUND3(d, a, b, c, X[4], 11, 0x4bdecfa9); /* 38 */ + ROUND3(c, d, a, b, X[7], 16, 0xf6bb4b60); /* 39 */ + ROUND3(b, c, d, a, X[10], 23, 0xbebfbc70); /* 40 */ + ROUND3(a, b, c, d, X[13], 4, 0x289b7ec6); /* 41 */ + ROUND3(d, a, b, c, X[0], 11, 0xeaa127fa); /* 42 */ + ROUND3(c, d, a, b, X[3], 16, 0xd4ef3085); /* 43 */ + ROUND3(b, c, d, a, X[6], 23, 0x4881d05); /* 44 */ + ROUND3(a, b, c, d, X[9], 4, 0xd9d4d039); /* 45 */ + ROUND3(d, a, b, c, X[12], 11, 0xe6db99e5); /* 46 */ + ROUND3(c, d, a, b, X[15], 16, 0x1fa27cf8); /* 47 */ + ROUND3(b, c, d, a, X[2], 23, 0xc4ac5665); /* 48 */ + + /* + * Round 4 + * Let [abcd k s t] denote the operation + * a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s) + */ + ROUND4(a, b, c, d, X[0], 6, 0xf4292244); /* 49 */ + ROUND4(d, a, b, c, X[7], 10, 0x432aff97); /* 50 */ + ROUND4(c, d, a, b, X[14], 15, 0xab9423a7); /* 51 */ + ROUND4(b, c, d, a, X[5], 21, 0xfc93a039); /* 52 */ + ROUND4(a, b, c, d, X[12], 6, 0x655b59c3); /* 53 */ + ROUND4(d, a, b, c, X[3], 10, 0x8f0ccc92); /* 54 */ + ROUND4(c, d, a, b, X[10], 15, 0xffeff47d); /* 55 */ + ROUND4(b, c, d, a, X[1], 21, 0x85845dd1); /* 56 */ + ROUND4(a, b, c, d, X[8], 6, 0x6fa87e4f); /* 57 */ + ROUND4(d, a, b, c, X[15], 10, 0xfe2ce6e0); /* 58 */ + ROUND4(c, d, a, b, X[6], 15, 0xa3014314); /* 59 */ + ROUND4(b, c, d, a, X[13], 21, 0x4e0811a1); /* 60 */ + ROUND4(a, b, c, d, X[4], 6, 0xf7537e82); /* 61 */ + ROUND4(d, a, b, c, X[11], 10, 0xbd3af235); /* 62 */ + ROUND4(c, d, a, b, X[2], 15, 0x2ad7d2bb); /* 63 */ + ROUND4(b, c, d, a, X[9], 21, 0xeb86d391); /* 64 */ + + /* Compute the i^th intermediate hash value H^(i) */ + pMD5_CTX->HashValue[0] += a; + pMD5_CTX->HashValue[1] += b; + pMD5_CTX->HashValue[2] += c; + pMD5_CTX->HashValue[3] += d; + + NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE); + pMD5_CTX->BlockLen = 0; +} /* End of MD5_Hash */ + +/* +======================================================================== +Routine Description: + The message is appended to block. If block size > 64 bytes, the MD5_Hash +will be called. + +Arguments: + pMD5_CTX Pointer to struct rt_md5_ctx_struc + message Message context + messageLen The length of message in bytes + +Return Value: + None + +Note: + None +======================================================================== +*/ +void MD5_Append(struct rt_md5_ctx_struc *pMD5_CTX, + IN const u8 Message[], u32 MessageLen) +{ + u32 appendLen = 0; + u32 diffLen = 0; + + while (appendLen != MessageLen) { + diffLen = MessageLen - appendLen; + if ((pMD5_CTX->BlockLen + diffLen) < MD5_BLOCK_SIZE) { + NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, + Message + appendLen, diffLen); + pMD5_CTX->BlockLen += diffLen; + appendLen += diffLen; + } else { + NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, + Message + appendLen, + MD5_BLOCK_SIZE - pMD5_CTX->BlockLen); + appendLen += (MD5_BLOCK_SIZE - pMD5_CTX->BlockLen); + pMD5_CTX->BlockLen = MD5_BLOCK_SIZE; + MD5_Hash(pMD5_CTX); + } /* End of if */ + } /* End of while */ + pMD5_CTX->MessageLen += MessageLen; +} /* End of MD5_Append */ + +/* +======================================================================== +Routine Description: + 1. Append bit 1 to end of the message + 2. Append the length of message in rightmost 64 bits + 3. Transform the Hash Value to digest message + +Arguments: + pMD5_CTX Pointer to struct rt_md5_ctx_struc + +Return Value: + digestMessage Digest message + +Note: + None +======================================================================== +*/ +void MD5_End(struct rt_md5_ctx_struc *pMD5_CTX, u8 DigestMessage[]) +{ + u32 index; + u64 message_length_bits; + + /* append 1 bits to end of the message */ + NdisFillMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, 1, 0x80); + + /* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */ + if (pMD5_CTX->BlockLen > 55) + MD5_Hash(pMD5_CTX); + /* End of if */ + + /* Append the length of message in rightmost 64 bits */ + message_length_bits = pMD5_CTX->MessageLen * 8; + message_length_bits = cpu2le64(message_length_bits); + NdisMoveMemory(&pMD5_CTX->Block[56], &message_length_bits, 8); + MD5_Hash(pMD5_CTX); + + /* Return message digest, transform the u32 hash value to bytes */ + for (index = 0; index < 4; index++) + pMD5_CTX->HashValue[index] = + cpu2le32(pMD5_CTX->HashValue[index]); + /* End of for */ + NdisMoveMemory(DigestMessage, pMD5_CTX->HashValue, MD5_DIGEST_SIZE); +} /* End of MD5_End */ + +/* +======================================================================== +Routine Description: + MD5 algorithm + +Arguments: + message Message context + messageLen The length of message in bytes + +Return Value: + digestMessage Digest message + +Note: + None +======================================================================== +*/ +void RT_MD5(IN const u8 Message[], + u32 MessageLen, u8 DigestMessage[]) +{ + struct rt_md5_ctx_struc md5_ctx; + + NdisZeroMemory(&md5_ctx, sizeof(struct rt_md5_ctx_struc)); + MD5_Init(&md5_ctx); + MD5_Append(&md5_ctx, Message, MessageLen); + MD5_End(&md5_ctx, DigestMessage); +} /* End of RT_MD5 */ + +#endif /* MD5_SUPPORT */ + +/* End of crypt_md5.c */ diff --git a/drivers/staging/rt2860/common/crypt_sha2.c b/drivers/staging/rt2860/common/crypt_sha2.c new file mode 100644 index 0000000000000000000000000000000000000000..fa83fb287fe5302575fcd1179b1094f03a63e254 --- /dev/null +++ b/drivers/staging/rt2860/common/crypt_sha2.c @@ -0,0 +1,269 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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 "../crypt_sha2.h" + +/* Basic operations */ +#define SHR(x,n) (x >> n) /* SHR(x)^n, right shift n bits , x is w-bit word, 0 <= n <= w */ +#define ROTR(x,n,w) ((x >> n) | (x << (w - n))) /* ROTR(x)^n, circular right shift n bits , x is w-bit word, 0 <= n <= w */ +#define ROTL(x,n,w) ((x << n) | (x >> (w - n))) /* ROTL(x)^n, circular left shift n bits , x is w-bit word, 0 <= n <= w */ +#define ROTR32(x,n) ROTR(x,n,32) /* 32 bits word */ +#define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */ + +/* Basic functions */ +#define Ch(x,y,z) ((x & y) ^ ((~x) & z)) +#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) +#define Parity(x,y,z) (x ^ y ^ z) + +#ifdef SHA1_SUPPORT +/* SHA1 constants */ +#define SHA1_MASK 0x0000000f +static const u32 SHA1_K[4] = { + 0x5a827999UL, 0x6ed9eba1UL, 0x8f1bbcdcUL, 0xca62c1d6UL +}; + +static const u32 SHA1_DefaultHashValue[5] = { + 0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL, 0xc3d2e1f0UL +}; + +/* +======================================================================== +Routine Description: + Initial struct rt_sha1_ctx + +Arguments: + pSHA_CTX Pointer to struct rt_sha1_ctx + +Return Value: + None + +Note: + None +======================================================================== +*/ +void RT_SHA1_Init(struct rt_sha1_ctx *pSHA_CTX) +{ + NdisMoveMemory(pSHA_CTX->HashValue, SHA1_DefaultHashValue, + sizeof(SHA1_DefaultHashValue)); + NdisZeroMemory(pSHA_CTX->Block, SHA1_BLOCK_SIZE); + pSHA_CTX->MessageLen = 0; + pSHA_CTX->BlockLen = 0; +} /* End of RT_SHA1_Init */ + +/* +======================================================================== +Routine Description: + SHA1 computation for one block (512 bits) + +Arguments: + pSHA_CTX Pointer to struct rt_sha1_ctx + +Return Value: + None + +Note: + None +======================================================================== +*/ +void SHA1_Hash(struct rt_sha1_ctx *pSHA_CTX) +{ + u32 W_i, t, s; + u32 W[16]; + u32 a, b, c, d, e, T, f_t = 0; + + /* Prepare the message schedule, {W_i}, 0 < t < 15 */ + NdisMoveMemory(W, pSHA_CTX->Block, SHA1_BLOCK_SIZE); + for (W_i = 0; W_i < 16; W_i++) + W[W_i] = cpu2be32(W[W_i]); /* Endian Swap */ + /* End of for */ + + /* SHA256 hash computation */ + /* Initialize the working variables */ + a = pSHA_CTX->HashValue[0]; + b = pSHA_CTX->HashValue[1]; + c = pSHA_CTX->HashValue[2]; + d = pSHA_CTX->HashValue[3]; + e = pSHA_CTX->HashValue[4]; + + /* 80 rounds */ + for (t = 0; t < 80; t++) { + s = t & SHA1_MASK; + if (t > 15) { /* Prepare the message schedule, {W_i}, 16 < t < 79 */ + W[s] = + (W[(s + 13) & SHA1_MASK]) ^ (W[(s + 8) & SHA1_MASK]) + ^ (W[(s + 2) & SHA1_MASK]) ^ W[s]; + W[s] = ROTL32(W[s], 1); + } /* End of if */ + switch (t / 20) { + case 0: + f_t = Ch(b, c, d); + break; + case 1: + f_t = Parity(b, c, d); + break; + case 2: + f_t = Maj(b, c, d); + break; + case 3: + f_t = Parity(b, c, d); + break; + } /* End of switch */ + T = ROTL32(a, 5) + f_t + e + SHA1_K[t / 20] + W[s]; + e = d; + d = c; + c = ROTL32(b, 30); + b = a; + a = T; + } /* End of for */ + + /* Compute the i^th intermediate hash value H^(i) */ + pSHA_CTX->HashValue[0] += a; + pSHA_CTX->HashValue[1] += b; + pSHA_CTX->HashValue[2] += c; + pSHA_CTX->HashValue[3] += d; + pSHA_CTX->HashValue[4] += e; + + NdisZeroMemory(pSHA_CTX->Block, SHA1_BLOCK_SIZE); + pSHA_CTX->BlockLen = 0; +} /* End of SHA1_Hash */ + +/* +======================================================================== +Routine Description: + The message is appended to block. If block size > 64 bytes, the SHA1_Hash +will be called. + +Arguments: + pSHA_CTX Pointer to struct rt_sha1_ctx + message Message context + messageLen The length of message in bytes + +Return Value: + None + +Note: + None +======================================================================== +*/ +void SHA1_Append(struct rt_sha1_ctx *pSHA_CTX, + IN const u8 Message[], u32 MessageLen) +{ + u32 appendLen = 0; + u32 diffLen = 0; + + while (appendLen != MessageLen) { + diffLen = MessageLen - appendLen; + if ((pSHA_CTX->BlockLen + diffLen) < SHA1_BLOCK_SIZE) { + NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, + Message + appendLen, diffLen); + pSHA_CTX->BlockLen += diffLen; + appendLen += diffLen; + } else { + NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, + Message + appendLen, + SHA1_BLOCK_SIZE - pSHA_CTX->BlockLen); + appendLen += (SHA1_BLOCK_SIZE - pSHA_CTX->BlockLen); + pSHA_CTX->BlockLen = SHA1_BLOCK_SIZE; + SHA1_Hash(pSHA_CTX); + } /* End of if */ + } /* End of while */ + pSHA_CTX->MessageLen += MessageLen; +} /* End of SHA1_Append */ + +/* +======================================================================== +Routine Description: + 1. Append bit 1 to end of the message + 2. Append the length of message in rightmost 64 bits + 3. Transform the Hash Value to digest message + +Arguments: + pSHA_CTX Pointer to struct rt_sha1_ctx + +Return Value: + digestMessage Digest message + +Note: + None +======================================================================== +*/ +void SHA1_End(struct rt_sha1_ctx *pSHA_CTX, u8 DigestMessage[]) +{ + u32 index; + u64 message_length_bits; + + /* Append bit 1 to end of the message */ + NdisFillMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, 1, 0x80); + + /* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */ + if (pSHA_CTX->BlockLen > 55) + SHA1_Hash(pSHA_CTX); + /* End of if */ + + /* Append the length of message in rightmost 64 bits */ + message_length_bits = pSHA_CTX->MessageLen * 8; + message_length_bits = cpu2be64(message_length_bits); + NdisMoveMemory(&pSHA_CTX->Block[56], &message_length_bits, 8); + SHA1_Hash(pSHA_CTX); + + /* Return message digest, transform the u32 hash value to bytes */ + for (index = 0; index < 5; index++) + pSHA_CTX->HashValue[index] = + cpu2be32(pSHA_CTX->HashValue[index]); + /* End of for */ + NdisMoveMemory(DigestMessage, pSHA_CTX->HashValue, SHA1_DIGEST_SIZE); +} /* End of SHA1_End */ + +/* +======================================================================== +Routine Description: + SHA1 algorithm + +Arguments: + message Message context + messageLen The length of message in bytes + +Return Value: + digestMessage Digest message + +Note: + None +======================================================================== +*/ +void RT_SHA1(IN const u8 Message[], + u32 MessageLen, u8 DigestMessage[]) +{ + + struct rt_sha1_ctx sha_ctx; + + NdisZeroMemory(&sha_ctx, sizeof(struct rt_sha1_ctx)); + RT_SHA1_Init(&sha_ctx); + SHA1_Append(&sha_ctx, Message, MessageLen); + SHA1_End(&sha_ctx, DigestMessage); +} /* End of RT_SHA1 */ +#endif /* SHA1_SUPPORT */ + +/* End of crypt_sha2.c */ diff --git a/drivers/staging/rt2860/common/dfs.c b/drivers/staging/rt2860/common/dfs.c index 23330f2661d9ba533a08e95494f2629df3e6ab76..71cbb2665243d6a798b2460d890cd549d2350c1b 100644 --- a/drivers/staging/rt2860/common/dfs.c +++ b/drivers/staging/rt2860/common/dfs.c @@ -33,164 +33,10 @@ Revision History: Who When What -------- ---------- ---------------------------------------------- - Fonchi 03-12-2007 created */ #include "../rt_config.h" -typedef struct _RADAR_DURATION_TABLE -{ - ULONG RDDurRegion; - ULONG RadarSignalDuration; - ULONG Tolerance; -} RADAR_DURATION_TABLE, *PRADAR_DURATION_TABLE; - - -static UCHAR RdIdleTimeTable[MAX_RD_REGION][4] = -{ - {9, 250, 250, 250}, // CE - {4, 250, 250, 250}, // FCC - {4, 250, 250, 250}, // JAP - {15, 250, 250, 250}, // JAP_W53 - {4, 250, 250, 250} // JAP_W56 -}; - -/* - ======================================================================== - - Routine Description: - Bbp Radar detection routine - - Arguments: - pAd Pointer to our adapter - - Return Value: - - ======================================================================== -*/ -VOID BbpRadarDetectionStart( - IN PRTMP_ADAPTER pAd) -{ - UINT8 RadarPeriod; - - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 114, 0x02); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 121, 0x20); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 122, 0x00); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 123, 0x08/*0x80*/); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 124, 0x28); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 125, 0xff); - - RadarPeriod = ((UINT)RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + (UINT)pAd->CommonCfg.RadarDetect.DfsSessionTime) < 250 ? - (RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + pAd->CommonCfg.RadarDetect.DfsSessionTime) : 250; - - RTMP_IO_WRITE8(pAd, 0x7020, 0x1d); - RTMP_IO_WRITE8(pAd, 0x7021, 0x40); - - RadarDetectionStart(pAd, 0, RadarPeriod); - return; -} - -/* - ======================================================================== - - Routine Description: - Bbp Radar detection routine - - Arguments: - pAd Pointer to our adapter - - Return Value: - - ======================================================================== -*/ -VOID BbpRadarDetectionStop( - IN PRTMP_ADAPTER pAd) -{ - RTMP_IO_WRITE8(pAd, 0x7020, 0x1d); - RTMP_IO_WRITE8(pAd, 0x7021, 0x60); - - RadarDetectionStop(pAd); - return; -} - -/* - ======================================================================== - - Routine Description: - Radar detection routine - - Arguments: - pAd Pointer to our adapter - - Return Value: - - ======================================================================== -*/ -VOID RadarDetectionStart( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN CTSProtect, - IN UINT8 CTSPeriod) -{ - UINT8 DfsActiveTime = (pAd->CommonCfg.RadarDetect.DfsSessionTime & 0x1f); - UINT8 CtsProtect = (CTSProtect == 1) ? 0x02 : 0x01; // CTS protect. - - if (CTSProtect != 0) - { - switch(pAd->CommonCfg.RadarDetect.RDDurRegion) - { - case FCC: - case JAP_W56: - CtsProtect = 0x03; - break; - - case CE: - case JAP_W53: - default: - CtsProtect = 0x02; - break; - } - } - else - CtsProtect = 0x01; - - - // send start-RD with CTS protection command to MCU - // highbyte [7] reserve - // highbyte [6:5] 0x: stop Carrier/Radar detection - // highbyte [10]: Start Carrier/Radar detection without CTS protection, 11: Start Carrier/Radar detection with CTS protection - // highbyte [4:0] Radar/carrier detection duration. In 1ms. - - // lowbyte [7:0] Radar/carrier detection period, in 1ms. - AsicSendCommandToMcu(pAd, 0x60, 0xff, CTSPeriod, DfsActiveTime | (CtsProtect << 5)); - //AsicSendCommandToMcu(pAd, 0x63, 0xff, 10, 0); - - return; -} - -/* - ======================================================================== - - Routine Description: - Radar detection routine - - Arguments: - pAd Pointer to our adapter - - Return Value: - TRUE Found radar signal - FALSE Not found radar signal - - ======================================================================== -*/ -VOID RadarDetectionStop( - IN PRTMP_ADAPTER pAd) -{ - DBGPRINT(RT_DEBUG_TRACE,("RadarDetectionStop.\n")); - AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x00, 0x00); // send start-RD with CTS protection command to MCU - - return; -} - /* ======================================================================== @@ -206,227 +52,17 @@ VOID RadarDetectionStop( ======================================================================== */ -BOOLEAN RadarChannelCheck( - IN PRTMP_ADAPTER pAd, - IN UCHAR Ch) +BOOLEAN RadarChannelCheck(struct rt_rtmp_adapter *pAd, u8 Ch) { -#if 1 - INT i; + int i; BOOLEAN result = FALSE; - for (i=0; iChannelListNum; i++) - { - if (Ch == pAd->ChannelList[i].Channel) - { + for (i = 0; i < pAd->ChannelListNum; i++) { + if (Ch == pAd->ChannelList[i].Channel) { result = pAd->ChannelList[i].DfsReq; break; } } return result; -#else - INT i; - UCHAR Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; - - for (i=0; i<15; i++) - { - if (Ch == Channel[i]) - { - break; - } - } - - if (i != 15) - return TRUE; - else - return FALSE; -#endif } - -ULONG JapRadarType( - IN PRTMP_ADAPTER pAd) -{ - ULONG i; - const UCHAR Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; - - if (pAd->CommonCfg.RadarDetect.RDDurRegion != JAP) - { - return pAd->CommonCfg.RadarDetect.RDDurRegion; - } - - for (i=0; i<15; i++) - { - if (pAd->CommonCfg.Channel == Channel[i]) - { - break; - } - } - - if (i < 4) - return JAP_W53; - else if (i < 15) - return JAP_W56; - else - return JAP; // W52 - -} - -ULONG RTMPBbpReadRadarDuration( - IN PRTMP_ADAPTER pAd) -{ - UINT8 byteValue = 0; - ULONG result; - - BBP_IO_READ8_BY_REG_ID(pAd, BBP_R115, &byteValue); - - result = 0; - switch (byteValue) - { - case 1: // radar signal detected by pulse mode. - case 2: // radar signal detected by width mode. - result = RTMPReadRadarDuration(pAd); - break; - - case 0: // No radar signal. - default: - - result = 0; - break; - } - - return result; -} - -ULONG RTMPReadRadarDuration( - IN PRTMP_ADAPTER pAd) -{ - ULONG result = 0; - - return result; - -} - -VOID RTMPCleanRadarDuration( - IN PRTMP_ADAPTER pAd) -{ - return; -} - -/* - ======================================================================== - Routine Description: - Radar wave detection. The API should be invoke each second. - - Arguments: - pAd - Adapter pointer - - Return Value: - None - - ======================================================================== -*/ -VOID ApRadarDetectPeriodic( - IN PRTMP_ADAPTER pAd) -{ - INT i; - - pAd->CommonCfg.RadarDetect.InServiceMonitorCount++; - - for (i=0; iChannelListNum; i++) - { - if (pAd->ChannelList[i].RemainingTimeForUse > 0) - { - pAd->ChannelList[i].RemainingTimeForUse --; - if ((pAd->Mlme.PeriodicRound%5) == 0) - { - DBGPRINT(RT_DEBUG_TRACE, ("RadarDetectPeriodic - ch=%d, RemainingTimeForUse=%d\n", pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse)); - } - } - } - - //radar detect - if ((pAd->CommonCfg.Channel > 14) - && (pAd->CommonCfg.bIEEE80211H == 1) - && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) - { - RadarDetectPeriodic(pAd); - } - - return; -} - -// Periodic Radar detection, switch channel will occur in RTMPHandleTBTTInterrupt() -// Before switch channel, driver needs doing channel switch announcement. -VOID RadarDetectPeriodic( - IN PRTMP_ADAPTER pAd) -{ - // need to check channel availability, after switch channel - if (pAd->CommonCfg.RadarDetect.RDMode != RD_SILENCE_MODE) - return; - - // channel availability check time is 60sec, use 65 for assurance - if (pAd->CommonCfg.RadarDetect.RDCount++ > pAd->CommonCfg.RadarDetect.ChMovingTime) - { - DBGPRINT(RT_DEBUG_TRACE, ("Not found radar signal, start send beacon and radar detection in service monitor\n\n")); - BbpRadarDetectionStop(pAd); - AsicEnableBssSync(pAd); - pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE; - - - return; - } - - return; -} - - -/* - ========================================================================== - Description: - change channel moving time for DFS testing. - - Arguments: - pAdapter Pointer to our adapter - wrq Pointer to the ioctl argument - - Return Value: - None - - Note: - Usage: - 1.) iwpriv ra0 set ChMovTime=[value] - ========================================================================== -*/ -INT Set_ChMovingTime_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - UINT8 Value; - - Value = simple_strtol(arg, 0, 10); - - pAd->CommonCfg.RadarDetect.ChMovingTime = Value; - - DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __func__, - pAd->CommonCfg.RadarDetect.ChMovingTime)); - - return TRUE; -} - -INT Set_LongPulseRadarTh_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - UINT8 Value; - - Value = simple_strtol(arg, 0, 10) > 10 ? 10 : simple_strtol(arg, 0, 10); - - pAd->CommonCfg.RadarDetect.LongPulseRadarTh = Value; - - DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __func__, - pAd->CommonCfg.RadarDetect.LongPulseRadarTh)); - - return TRUE; -} - - diff --git a/drivers/staging/rt2860/common/ee_efuse.c b/drivers/staging/rt2860/common/ee_efuse.c new file mode 100644 index 0000000000000000000000000000000000000000..03412f5bc990830493a5991cf41f45f40c304afa --- /dev/null +++ b/drivers/staging/rt2860/common/ee_efuse.c @@ -0,0 +1,344 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* + + Module Name: + ee_efuse.c + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "../rt_config.h" + +#define EFUSE_USAGE_MAP_START 0x2d0 +#define EFUSE_USAGE_MAP_END 0x2fc +#define EFUSE_USAGE_MAP_SIZE 45 + +#define EFUSE_EEPROM_DEFULT_FILE "RT30xxEEPROM.bin" +#define MAX_EEPROM_BIN_FILE_SIZE 1024 + +#define EFUSE_TAG 0x2fe + +typedef union _EFUSE_CTRL_STRUC { + struct { + u32 EFSROM_AOUT:6; + u32 EFSROM_MODE:2; + u32 EFSROM_LDO_OFF_TIME:6; + u32 EFSROM_LDO_ON_TIME:2; + u32 EFSROM_AIN:10; + u32 RESERVED:4; + u32 EFSROM_KICK:1; + u32 SEL_EFUSE:1; + } field; + u32 word; +} EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC; + +/* +======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + +======================================================================== +*/ +u8 eFuseReadRegisters(struct rt_rtmp_adapter *pAd, + u16 Offset, u16 Length, u16 * pData) +{ + EFUSE_CTRL_STRUC eFuseCtrlStruc; + int i; + u16 efuseDataOffset; + u32 data; + + RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); + + /*Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. */ + /*Use the eeprom logical address and covert to address to block number */ + eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; + + /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 0. */ + eFuseCtrlStruc.field.EFSROM_MODE = 0; + + /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. */ + eFuseCtrlStruc.field.EFSROM_KICK = 1; + + NdisMoveMemory(&data, &eFuseCtrlStruc, 4); + RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); + + /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. */ + i = 0; + while (i < 500) { + /*rtmp.HwMemoryReadDword(EFUSE_CTRL, (DWORD *) &eFuseCtrlStruc, 4); */ + RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); + if (eFuseCtrlStruc.field.EFSROM_KICK == 0) { + break; + } + RTMPusecDelay(2); + i++; + } + + /*if EFSROM_AOUT is not found in physical address, write 0xffff */ + if (eFuseCtrlStruc.field.EFSROM_AOUT == 0x3f) { + for (i = 0; i < Length / 2; i++) + *(pData + 2 * i) = 0xffff; + } else { + /*Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x590-0x59C) */ + efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC); + /*data hold 4 bytes data. */ + /*In RTMP_IO_READ32 will automatically execute 32-bytes swapping */ + RTMP_IO_READ32(pAd, efuseDataOffset, &data); + /*Decide the upper 2 bytes or the bottom 2 bytes. */ + /* Little-endian S | S Big-endian */ + /* addr 3 2 1 0 | 0 1 2 3 */ + /* Ori-V D C B A | A B C D */ + /*After swapping */ + /* D C B A | D C B A */ + /*Return 2-bytes */ + /*The return byte statrs from S. Therefore, the little-endian will return BA, the Big-endian will return DC. */ + /*For returning the bottom 2 bytes, the Big-endian should shift right 2-bytes. */ + data = data >> (8 * (Offset & 0x3)); + + NdisMoveMemory(pData, &data, Length); + } + + return (u8)eFuseCtrlStruc.field.EFSROM_AOUT; + +} + +/* +======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + +======================================================================== +*/ +void eFusePhysicalReadRegisters(struct rt_rtmp_adapter *pAd, + u16 Offset, + u16 Length, u16 * pData) +{ + EFUSE_CTRL_STRUC eFuseCtrlStruc; + int i; + u16 efuseDataOffset; + u32 data; + + RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); + + /*Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. */ + eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; + + /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1. */ + /*Read in physical view */ + eFuseCtrlStruc.field.EFSROM_MODE = 1; + + /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. */ + eFuseCtrlStruc.field.EFSROM_KICK = 1; + + NdisMoveMemory(&data, &eFuseCtrlStruc, 4); + RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); + + /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. */ + i = 0; + while (i < 500) { + RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); + if (eFuseCtrlStruc.field.EFSROM_KICK == 0) + break; + RTMPusecDelay(2); + i++; + } + + /*Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590) */ + /*Because the size of each EFUSE_DATA is 4 Bytes, the size of address of each is 2 bits. */ + /*The previous 2 bits is the EFUSE_DATA number, the last 2 bits is used to decide which bytes */ + /*Decide which EFUSE_DATA to read */ + /*590:F E D C */ + /*594:B A 9 8 */ + /*598:7 6 5 4 */ + /*59C:3 2 1 0 */ + efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC); + + RTMP_IO_READ32(pAd, efuseDataOffset, &data); + + data = data >> (8 * (Offset & 0x3)); + + NdisMoveMemory(pData, &data, Length); + +} + +/* +======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + +======================================================================== +*/ +static void eFuseReadPhysical(struct rt_rtmp_adapter *pAd, + u16 *lpInBuffer, + unsigned long nInBufferSize, + u16 *lpOutBuffer, unsigned long nOutBufferSize) +{ + u16 *pInBuf = (u16 *) lpInBuffer; + u16 *pOutBuf = (u16 *) lpOutBuffer; + + u16 Offset = pInBuf[0]; /*addr */ + u16 Length = pInBuf[1]; /*length */ + int i; + + for (i = 0; i < Length; i += 2) { + eFusePhysicalReadRegisters(pAd, Offset + i, 2, &pOutBuf[i / 2]); + } +} + +/* +======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + +======================================================================== +*/ +int set_eFuseGetFreeBlockCount_Proc(struct rt_rtmp_adapter *pAd, char *arg) +{ + u16 i; + u16 LogicalAddress; + u16 efusefreenum = 0; + if (!pAd->bUseEfuse) + return FALSE; + for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i += 2) { + eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + if ((LogicalAddress & 0xff) == 0) { + efusefreenum = (u8)(EFUSE_USAGE_MAP_END - i + 1); + break; + } else if (((LogicalAddress >> 8) & 0xff) == 0) { + efusefreenum = (u8)(EFUSE_USAGE_MAP_END - i); + break; + } + + if (i == EFUSE_USAGE_MAP_END) + efusefreenum = 0; + } + printk("efuseFreeNumber is %d\n", efusefreenum); + return TRUE; +} + +int set_eFusedump_Proc(struct rt_rtmp_adapter *pAd, char *arg) +{ + u16 InBuf[3]; + int i = 0; + if (!pAd->bUseEfuse) + return FALSE; + for (i = 0; i < EFUSE_USAGE_MAP_END / 2; i++) { + InBuf[0] = 2 * i; + InBuf[1] = 2; + InBuf[2] = 0x0; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + if (i % 4 == 0) + printk("\nBlock %x:", i / 8); + printk("%04x ", InBuf[2]); + } + return TRUE; +} + +int rtmp_ee_efuse_read16(struct rt_rtmp_adapter *pAd, + u16 Offset, u16 * pValue) +{ + eFuseReadRegisters(pAd, Offset, 2, pValue); + return (*pValue); +} + +int RtmpEfuseSupportCheck(struct rt_rtmp_adapter *pAd) +{ + u16 value; + + if (IS_RT30xx(pAd)) { + eFusePhysicalReadRegisters(pAd, EFUSE_TAG, 2, &value); + pAd->EFuseTag = (value & 0xff); + } + return 0; +} + +void eFuseGetFreeBlockCount(struct rt_rtmp_adapter *pAd, u32 *EfuseFreeBlock) +{ + u16 i; + u16 LogicalAddress; + if (!pAd->bUseEfuse) { + DBGPRINT(RT_DEBUG_TRACE, + ("eFuseGetFreeBlockCount Only supports efuse Mode\n")); + return; + } + for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i += 2) { + eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + if ((LogicalAddress & 0xff) == 0) { + *EfuseFreeBlock = (u8)(EFUSE_USAGE_MAP_END - i + 1); + break; + } else if (((LogicalAddress >> 8) & 0xff) == 0) { + *EfuseFreeBlock = (u8)(EFUSE_USAGE_MAP_END - i); + break; + } + + if (i == EFUSE_USAGE_MAP_END) + *EfuseFreeBlock = 0; + } + DBGPRINT(RT_DEBUG_TRACE, + ("eFuseGetFreeBlockCount is 0x%x\n", *EfuseFreeBlock)); +} + +int eFuse_init(struct rt_rtmp_adapter *pAd) +{ + u32 EfuseFreeBlock = 0; + DBGPRINT(RT_DEBUG_ERROR, + ("NVM is Efuse and its size =%x[%x-%x] \n", + EFUSE_USAGE_MAP_SIZE, EFUSE_USAGE_MAP_START, + EFUSE_USAGE_MAP_END)); + eFuseGetFreeBlockCount(pAd, &EfuseFreeBlock); + + return 0; +} diff --git a/drivers/staging/rt2860/common/ee_prom.c b/drivers/staging/rt2860/common/ee_prom.c new file mode 100644 index 0000000000000000000000000000000000000000..2083740a844bb29cce3e9927f37cfd235cc46197 --- /dev/null +++ b/drivers/staging/rt2860/common/ee_prom.c @@ -0,0 +1,197 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* + + Module Name: + ee_prom.c + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "../rt_config.h" + +/* IRQL = PASSIVE_LEVEL */ +static inline void RaiseClock(struct rt_rtmp_adapter *pAd, u32 * x) +{ + *x = *x | EESK; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); + RTMPusecDelay(1); /* Max frequency = 1MHz in Spec. definition */ +} + +/* IRQL = PASSIVE_LEVEL */ +static inline void LowerClock(struct rt_rtmp_adapter *pAd, u32 * x) +{ + *x = *x & ~EESK; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); + RTMPusecDelay(1); +} + +/* IRQL = PASSIVE_LEVEL */ +static inline u16 ShiftInBits(struct rt_rtmp_adapter *pAd) +{ + u32 x, i; + u16 data = 0; + + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + + x &= ~(EEDO | EEDI); + + for (i = 0; i < 16; i++) { + data = data << 1; + RaiseClock(pAd, &x); + + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + LowerClock(pAd, &x); /*prevent read failed */ + + x &= ~(EEDI); + if (x & EEDO) + data |= 1; + } + + return data; +} + +/* IRQL = PASSIVE_LEVEL */ +static inline void ShiftOutBits(struct rt_rtmp_adapter *pAd, + u16 data, u16 count) +{ + u32 x, mask; + + mask = 0x01 << (count - 1); + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + + x &= ~(EEDO | EEDI); + + do { + x &= ~EEDI; + if (data & mask) + x |= EEDI; + + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + + mask = mask >> 1; + } while (mask); + + x &= ~EEDI; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); +} + +/* IRQL = PASSIVE_LEVEL */ +static inline void EEpromCleanup(struct rt_rtmp_adapter *pAd) +{ + u32 x; + + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + + x &= ~(EECS | EEDI); + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + RaiseClock(pAd, &x); + LowerClock(pAd, &x); +} + +static inline void EWEN(struct rt_rtmp_adapter *pAd) +{ + u32 x; + + /* reset bits and set EECS */ + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + x &= ~(EEDI | EEDO | EESK); + x |= EECS; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + /* kick a pulse */ + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + + /* output the read_opcode and six pulse in that order */ + ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5); + ShiftOutBits(pAd, 0, 6); + + EEpromCleanup(pAd); +} + +static inline void EWDS(struct rt_rtmp_adapter *pAd) +{ + u32 x; + + /* reset bits and set EECS */ + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + x &= ~(EEDI | EEDO | EESK); + x |= EECS; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + /* kick a pulse */ + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + + /* output the read_opcode and six pulse in that order */ + ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5); + ShiftOutBits(pAd, 0, 6); + + EEpromCleanup(pAd); +} + +/* IRQL = PASSIVE_LEVEL */ +int rtmp_ee_prom_read16(struct rt_rtmp_adapter *pAd, + u16 Offset, u16 * pValue) +{ + u32 x; + u16 data; + + Offset /= 2; + /* reset bits and set EECS */ + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + x &= ~(EEDI | EEDO | EESK); + x |= EECS; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + /* patch can not access e-Fuse issue */ + if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) { + /* kick a pulse */ + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + } + /* output the read_opcode and register number in that order */ + ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3); + ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum); + + /* Now read the data (16 bits) in from the selected EEPROM word */ + data = ShiftInBits(pAd); + + EEpromCleanup(pAd); + + *pValue = data; + + return NDIS_STATUS_SUCCESS; +} diff --git a/drivers/staging/rt2860/common/eeprom.c b/drivers/staging/rt2860/common/eeprom.c index ffcb4ce1a03481836f08426dd2a26998c9a08718..94670076d32ba0ec2cf13cc4a798cde3362962db 100644 --- a/drivers/staging/rt2860/common/eeprom.c +++ b/drivers/staging/rt2860/common/eeprom.c @@ -36,1444 +36,56 @@ */ #include "../rt_config.h" -// IRQL = PASSIVE_LEVEL -VOID RaiseClock( - IN PRTMP_ADAPTER pAd, - IN UINT32 *x) +int RtmpChipOpsEepromHook(struct rt_rtmp_adapter *pAd, int infType) { - *x = *x | EESK; - RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); - RTMPusecDelay(1); // Max frequency = 1MHz in Spec. definition -} - -// IRQL = PASSIVE_LEVEL -VOID LowerClock( - IN PRTMP_ADAPTER pAd, - IN UINT32 *x) -{ - *x = *x & ~EESK; - RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); - RTMPusecDelay(1); -} - -// IRQL = PASSIVE_LEVEL -USHORT ShiftInBits( - IN PRTMP_ADAPTER pAd) -{ - UINT32 x,i; - USHORT data=0; - - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - - x &= ~( EEDO | EEDI); - - for(i=0; i<16; i++) - { - data = data << 1; - RaiseClock(pAd, &x); - - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - - LowerClock(pAd, &x); /* prevent read failed */ - - x &= ~(EEDI); - if(x & EEDO) - data |= 1; - } - - return data; -} - -// IRQL = PASSIVE_LEVEL -VOID ShiftOutBits( - IN PRTMP_ADAPTER pAd, - IN USHORT data, - IN USHORT count) -{ - UINT32 x,mask; - - mask = 0x01 << (count - 1); - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - - x &= ~(EEDO | EEDI); - - do - { - x &= ~EEDI; - if(data & mask) x |= EEDI; - - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - RaiseClock(pAd, &x); - LowerClock(pAd, &x); - - mask = mask >> 1; - } while(mask); - - x &= ~EEDI; - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); -} - -// IRQL = PASSIVE_LEVEL -VOID EEpromCleanup( - IN PRTMP_ADAPTER pAd) -{ - UINT32 x; - - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - - x &= ~(EECS | EEDI); - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - RaiseClock(pAd, &x); - LowerClock(pAd, &x); -} - -VOID EWEN( - IN PRTMP_ADAPTER pAd) -{ - UINT32 x; - - // reset bits and set EECS - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - x &= ~(EEDI | EEDO | EESK); - x |= EECS; - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - // kick a pulse - RaiseClock(pAd, &x); - LowerClock(pAd, &x); - - // output the read_opcode and six pulse in that order - ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5); - ShiftOutBits(pAd, 0, 6); - - EEpromCleanup(pAd); -} - -VOID EWDS( - IN PRTMP_ADAPTER pAd) -{ - UINT32 x; - - // reset bits and set EECS - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - x &= ~(EEDI | EEDO | EESK); - x |= EECS; - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - // kick a pulse - RaiseClock(pAd, &x); - LowerClock(pAd, &x); - - // output the read_opcode and six pulse in that order - ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5); - ShiftOutBits(pAd, 0, 6); - - EEpromCleanup(pAd); -} - -// IRQL = PASSIVE_LEVEL -USHORT RTMP_EEPROM_READ16( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset) -{ - UINT32 x; - USHORT data; + struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; +#ifdef RT30xx +#ifdef RTMP_EFUSE_SUPPORT + u32 eFuseCtrl, MacCsr0; + int index; -#ifdef RT2870 - if (pAd->NicConfig2.field.AntDiversity) - { - pAd->EepromAccess = TRUE; - } -#endif - Offset /= 2; - // reset bits and set EECS - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - x &= ~(EEDI | EEDO | EESK); - x |= EECS; - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + index = 0; + do { + RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); + pAd->MACVersion = MacCsr0; - // patch can not access e-Fuse issue - if (!IS_RT3090(pAd)) - { - // kick a pulse - RaiseClock(pAd, &x); - LowerClock(pAd, &x); - } - - // output the read_opcode and register number in that order - ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3); - ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum); - - // Now read the data (16 bits) in from the selected EEPROM word - data = ShiftInBits(pAd); - - EEpromCleanup(pAd); - -#ifdef RT2870 - // Antenna and EEPROM access are both using EESK pin, - // Therefor we should avoid accessing EESK at the same time - // Then restore antenna after EEPROM access - if ((pAd->NicConfig2.field.AntDiversity) || (pAd->RfIcType == RFIC_3020)) - { - pAd->EepromAccess = FALSE; - AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); - } -#endif - return data; -} //ReadEEprom - -VOID RTMP_EEPROM_WRITE16( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Data) -{ - UINT32 x; - -#ifdef RT2870 - if (pAd->NicConfig2.field.AntDiversity) - { - pAd->EepromAccess = TRUE; - } -#endif - Offset /= 2; - - EWEN(pAd); - - // reset bits and set EECS - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - x &= ~(EEDI | EEDO | EESK); - x |= EECS; - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - // patch can not access e-Fuse issue - if (!IS_RT3090(pAd)) - { - // kick a pulse - RaiseClock(pAd, &x); - LowerClock(pAd, &x); - } - - // output the read_opcode ,register number and data in that order - ShiftOutBits(pAd, EEPROM_WRITE_OPCODE, 3); - ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum); - ShiftOutBits(pAd, Data, 16); // 16-bit access - - // read DO status - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - - EEpromCleanup(pAd); - - RTMPusecDelay(10000); //delay for twp(MAX)=10ms - - EWDS(pAd); - - EEpromCleanup(pAd); - -#ifdef RT2870 - // Antenna and EEPROM access are both using EESK pin, - // Therefor we should avoid accessing EESK at the same time - // Then restore antenna after EEPROM access - if ((pAd->NicConfig2.field.AntDiversity) || (pAd->RfIcType == RFIC_3020)) - { - pAd->EepromAccess = FALSE; - AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); - } -#endif -} - -#ifdef RT2870 -/* - ======================================================================== - - Routine Description: - - Arguments: - - Return Value: - - IRQL = - - Note: - - ======================================================================== -*/ -UCHAR eFuseReadRegisters( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - OUT USHORT* pData) -{ - EFUSE_CTRL_STRUC eFuseCtrlStruc; - int i; - USHORT efuseDataOffset; - UINT32 data; - - RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); - - //Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. - //Use the eeprom logical address and covert to address to block number - eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; - - //Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 0. - eFuseCtrlStruc.field.EFSROM_MODE = 0; - - //Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. - eFuseCtrlStruc.field.EFSROM_KICK = 1; - - NdisMoveMemory(&data, &eFuseCtrlStruc, 4); - RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); - - //Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. - i = 0; - while(i < 100) - { - //rtmp.HwMemoryReadDword(EFUSE_CTRL, (DWORD *) &eFuseCtrlStruc, 4); - RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); - if(eFuseCtrlStruc.field.EFSROM_KICK == 0) - { + if ((pAd->MACVersion != 0x00) + && (pAd->MACVersion != 0xFFFFFFFF)) break; - } - RTMPusecDelay(2); - i++; - } - - //if EFSROM_AOUT is not found in physical address, write 0xffff - if (eFuseCtrlStruc.field.EFSROM_AOUT == 0x3f) - { - for(i=0; i> (8*(Offset & 0x3)); - - NdisMoveMemory(pData, &data, Length); - } - - return (UCHAR) eFuseCtrlStruc.field.EFSROM_AOUT; - -} - -/* - ======================================================================== - - Routine Description: - - Arguments: - - Return Value: - - IRQL = - - Note: - - ======================================================================== -*/ -VOID eFusePhysicalReadRegisters( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - OUT USHORT* pData) -{ - EFUSE_CTRL_STRUC eFuseCtrlStruc; - int i; - USHORT efuseDataOffset; - UINT32 data; - - RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); - - //Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. - eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; - - //Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1. - //Read in physical view - eFuseCtrlStruc.field.EFSROM_MODE = 1; - - //Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. - eFuseCtrlStruc.field.EFSROM_KICK = 1; - - NdisMoveMemory(&data, &eFuseCtrlStruc, 4); - RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); - - //Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. - i = 0; - while(i < 100) - { - RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); - if(eFuseCtrlStruc.field.EFSROM_KICK == 0) - break; - RTMPusecDelay(2); - i++; - } - - //Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590) - //Because the size of each EFUSE_DATA is 4 Bytes, the size of address of each is 2 bits. - //The previous 2 bits is the EFUSE_DATA number, the last 2 bits is used to decide which bytes - //Decide which EFUSE_DATA to read - //590:F E D C - //594:B A 9 8 - //598:7 6 5 4 - //59C:3 2 1 0 - efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC) ; - - RTMP_IO_READ32(pAd, efuseDataOffset, &data); - - data = data >> (8*(Offset & 0x3)); - - NdisMoveMemory(pData, &data, Length); - -} - -/* - ======================================================================== - - Routine Description: - - Arguments: - - Return Value: - - IRQL = - - Note: - - ======================================================================== -*/ -VOID eFuseReadPhysical( - IN PRTMP_ADAPTER pAd, - IN PUSHORT lpInBuffer, - IN ULONG nInBufferSize, - OUT PUSHORT lpOutBuffer, - IN ULONG nOutBufferSize -) -{ - USHORT* pInBuf = (USHORT*)lpInBuffer; - USHORT* pOutBuf = (USHORT*)lpOutBuffer; - - USHORT Offset = pInBuf[0]; //addr - USHORT Length = pInBuf[1]; //length - int i; - - for(i=0; i> 2; - data = pData[0] & 0xffff; - //The offset should be 0x***10 or 0x***00 - if((Offset % 4) != 0) - { - eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff) | (data << 16); - } - else - { - eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff0000) | data; - } - - efuseDataOffset = EFUSE_DATA3; - for(i=0; i< 4; i++) - { - RTMP_IO_WRITE32(pAd, efuseDataOffset, eFuseDataBuffer[i]); - efuseDataOffset -= 4; - } - ///////////////////////////////////////////////////////////////// - - //Step1. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. - eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; - - //Step2. Write EFSROM_MODE (0x580, bit7:bit6) to 3. - eFuseCtrlStruc.field.EFSROM_MODE = 3; - - //Step3. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical write procedure. - eFuseCtrlStruc.field.EFSROM_KICK = 1; - - NdisMoveMemory(&data, &eFuseCtrlStruc, 4); - RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); - - //Step4. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. It��s done. - i = 0; - while(i < 100) - { - RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); - - if(eFuseCtrlStruc.field.EFSROM_KICK == 0) - break; - - RTMPusecDelay(2); - i++; - } -} - -/* - ======================================================================== - - Routine Description: - - Arguments: - - Return Value: - - IRQL = - - Note: - - ======================================================================== -*/ -NTSTATUS eFuseWriteRegisters( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - IN USHORT* pData) -{ - USHORT i; - USHORT eFuseData; - USHORT LogicalAddress, BlkNum = 0xffff; - UCHAR EFSROM_AOUT; - - USHORT addr,tmpaddr, InBuf[3], tmpOffset; - USHORT buffer[8]; - BOOLEAN bWriteSuccess = TRUE; - - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters Offset=%x, pData=%x\n", Offset, *pData)); - - //Step 0. find the entry in the mapping table - //The address of EEPROM is 2-bytes alignment. - //The last bit is used for alignment, so it must be 0. - tmpOffset = Offset & 0xfffe; - EFSROM_AOUT = eFuseReadRegisters(pAd, tmpOffset, 2, &eFuseData); - - if( EFSROM_AOUT == 0x3f) - { //find available logical address pointer - //the logical address does not exist, find an empty one - //from the first address of block 45=16*45=0x2d0 to the last address of block 47 - //==>48*16-3(reserved)=2FC - for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2) - { - //Retrive the logical block nubmer form each logical address pointer - //It will access two logical address pointer each time. - eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); - if( (LogicalAddress & 0xff) == 0) - {//Not used logical address pointer - BlkNum = i-EFUSE_USAGE_MAP_START; - break; - } - else if(( (LogicalAddress >> 8) & 0xff) == 0) - {//Not used logical address pointer - if (i != EFUSE_USAGE_MAP_END) - { - BlkNum = i-EFUSE_USAGE_MAP_START+1; - } - break; - } - } - } - else - { - BlkNum = EFSROM_AOUT; - } - - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters BlkNum = %d \n", BlkNum)); - - if(BlkNum == 0xffff) - { - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); - return FALSE; - } - - //Step 1. Save data of this block which is pointed by the avaible logical address pointer - // read and save the original block data - for(i =0; i<8; i++) - { - addr = BlkNum * 0x10 ; - - InBuf[0] = addr+2*i; - InBuf[1] = 2; - InBuf[2] = 0x0; - - eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); - - buffer[i] = InBuf[2]; - } - - //Step 2. Update the data in buffer, and write the data to Efuse - buffer[ (Offset >> 1) % 8] = pData[0]; - - do - { - //Step 3. Write the data to Efuse - if(!bWriteSuccess) - { - for(i =0; i<8; i++) - { - addr = BlkNum * 0x10 ; - - InBuf[0] = addr+2*i; - InBuf[1] = 2; - InBuf[2] = buffer[i]; - - eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); - } - } - else - { - addr = BlkNum * 0x10 ; - - InBuf[0] = addr+(Offset % 16); - InBuf[1] = 2; - InBuf[2] = pData[0]; - - eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); - } - - //Step 4. Write mapping table - addr = EFUSE_USAGE_MAP_START+BlkNum; - - tmpaddr = addr; - - if(addr % 2 != 0) - addr = addr -1; - InBuf[0] = addr; - InBuf[1] = 2; - - //convert the address from 10 to 8 bit ( bit7, 6 = parity and bit5 ~ 0 = bit9~4), and write to logical map entry - tmpOffset = Offset; - tmpOffset >>= 4; - tmpOffset |= ((~((tmpOffset & 0x01) ^ ( tmpOffset >> 1 & 0x01) ^ (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01))) << 6) & 0x40; - tmpOffset |= ((~( (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01) ^ (tmpOffset >> 4 & 0x01) ^ ( tmpOffset >> 5 & 0x01))) << 7) & 0x80; - - // write the logical address - if(tmpaddr%2 != 0) - InBuf[2] = tmpOffset<<8; - else - InBuf[2] = tmpOffset; - - eFuseWritePhysical(pAd,&InBuf[0], 6, NULL, 0); - - //Step 5. Compare data if not the same, invalidate the mapping entry, then re-write the data until E-fuse is exhausted - bWriteSuccess = TRUE; - for(i =0; i<8; i++) - { - addr = BlkNum * 0x10 ; - - InBuf[0] = addr+2*i; - InBuf[1] = 2; - InBuf[2] = 0x0; - - eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); - - if(buffer[i] != InBuf[2]) - { - bWriteSuccess = FALSE; - break; - } - } - - //Step 6. invlidate mapping entry and find a free mapping entry if not succeed - if (!bWriteSuccess) - { - DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess BlkNum = %d\n", BlkNum)); - - // the offset of current mapping entry - addr = EFUSE_USAGE_MAP_START+BlkNum; - - //find a new mapping entry - BlkNum = 0xffff; - for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2) - { - eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); - if( (LogicalAddress & 0xff) == 0) - { - BlkNum = i-EFUSE_USAGE_MAP_START; - break; - } - else if(( (LogicalAddress >> 8) & 0xff) == 0) - { - if (i != EFUSE_USAGE_MAP_END) - { - BlkNum = i+1-EFUSE_USAGE_MAP_START; - } - break; - } - } - DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess new BlkNum = %d\n", BlkNum)); - if(BlkNum == 0xffff) - { - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); - return FALSE; - } - - //invalidate the original mapping entry if new entry is not found - tmpaddr = addr; - - if(addr % 2 != 0) - addr = addr -1; - InBuf[0] = addr; - InBuf[1] = 2; - - eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); - - // write the logical address - if(tmpaddr%2 != 0) - { - // Invalidate the high byte - for (i=8; i<15; i++) - { - if( ( (InBuf[2] >> i) & 0x01) == 0) - { - InBuf[2] |= (0x1 <> i) & 0x01) == 0) - { - InBuf[2] |= (0x1 <bUseEfuse) - return FALSE; - for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i+=2) - { - eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); - if( (LogicalAddress & 0xff) == 0) - { - efusefreenum= (UCHAR) (EFUSE_USAGE_MAP_END-i+1); - break; - } - else if(( (LogicalAddress >> 8) & 0xff) == 0) - { - efusefreenum = (UCHAR) (EFUSE_USAGE_MAP_END-i); - break; - } - - if(i == EFUSE_USAGE_MAP_END) - efusefreenum = 0; - } - printk("efuseFreeNumber is %d\n",efusefreenum); - return TRUE; -} -INT set_eFusedump_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ -USHORT InBuf[3]; - INT i=0; - if(!pAd->bUseEfuse) - return FALSE; - for(i =0; i0) - { - - NdisMoveMemory(src, arg, strlen(arg)); - } - - else - { - - NdisMoveMemory(src, "RT30xxEEPROM.bin", BinFileSize); - } - - DBGPRINT(RT_DEBUG_TRACE, ("FileName=%s\n",src)); - buffer = kmalloc(MAX_EEPROM_BIN_FILE_SIZE, MEM_ALLOC_FLAG); - - if(buffer == NULL) - { - kfree(src); - return FALSE; -} - PDATA=kmalloc(sizeof(USHORT)*8,MEM_ALLOC_FLAG); - - if(PDATA==NULL) - { - kfree(src); - - kfree(buffer); - return FALSE; - } - - orgfs = get_fs(); - set_fs(KERNEL_DS); - - if (src && *src) - { - srcf = filp_open(src, O_RDONLY, 0); - if (IS_ERR(srcf)) - { - DBGPRINT(RT_DEBUG_ERROR, ("--> Error %ld opening %s\n", -PTR_ERR(srcf),src)); - return FALSE; - } - else - { - // The object must have a read method - if (srcf->f_op && srcf->f_op->read) - { - memset(buffer, 0x00, MAX_EEPROM_BIN_FILE_SIZE); - while(srcf->f_op->read(srcf, &buffer[i], 1, &srcf->f_pos)==1) - { - DBGPRINT(RT_DEBUG_TRACE, ("%02X ",buffer[i])); - if((i+1)%8==0) - DBGPRINT(RT_DEBUG_TRACE, ("\n")); - i++; - if(i>=MAX_EEPROM_BIN_FILE_SIZE) - { - DBGPRINT(RT_DEBUG_ERROR, ("--> Error %ld reading %s, The file is too large[1024]\n", -PTR_ERR(srcf),src)); - kfree(PDATA); - kfree(buffer); - kfree(src); - return FALSE; - } - } - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("--> Error!! System doest not support read function\n")); - kfree(PDATA); - kfree(buffer); - kfree(src); - return FALSE; - } - } - - - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("--> Error src or srcf is null\n")); - kfree(PDATA); - kfree(buffer); - return FALSE; - - } - - - retval=filp_close(srcf,NULL); - - if (retval) - { - DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src)); - } - set_fs(orgfs); - - for(j=0;j48*16-3(reserved)=2FC - bAllocateNewBlk=TRUE; - for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2) - { - //Retrive the logical block nubmer form each logical address pointer - //It will access two logical address pointer each time. - eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); - if( (LogicalAddress & 0xff) == 0) - {//Not used logical address pointer - BlkNum = i-EFUSE_USAGE_MAP_START; - break; - } - else if(( (LogicalAddress >> 8) & 0xff) == 0) - {//Not used logical address pointer - if (i != EFUSE_USAGE_MAP_END) - { - BlkNum = i-EFUSE_USAGE_MAP_START+1; - } - break; - } - } - } - else - { - bAllocateNewBlk=FALSE; - BlkNum = EFSROM_AOUT; - } - - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters BlkNum = %d \n", BlkNum)); - - if(BlkNum == 0xffff) - { - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); - return FALSE; - } - //Step 1.1.0 - //If the block is not existing in mapping table, create one - //and write down the 16-bytes data to the new block - if(bAllocateNewBlk) - { - DBGPRINT(RT_DEBUG_TRACE, ("Allocate New Blk\n")); - efuseDataOffset = EFUSE_DATA3; - for(i=0; i< 4; i++) - { - DBGPRINT(RT_DEBUG_TRACE, ("Allocate New Blk, Data%d=%04x%04x\n",3-i,pData[2*i+1],pData[2*i])); - tempbuffer=((pData[2*i+1]<<16)&0xffff0000)|pData[2*i]; - - - RTMP_IO_WRITE32(pAd, efuseDataOffset,tempbuffer); - efuseDataOffset -= 4; - - } - ///////////////////////////////////////////////////////////////// - - //Step1.1.1. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. - eFuseCtrlStruc.field.EFSROM_AIN = BlkNum* 0x10 ; - - //Step1.1.2. Write EFSROM_MODE (0x580, bit7:bit6) to 3. - eFuseCtrlStruc.field.EFSROM_MODE = 3; - - //Step1.1.3. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical write procedure. - eFuseCtrlStruc.field.EFSROM_KICK = 1; - - NdisMoveMemory(&data, &eFuseCtrlStruc, 4); - - RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); - - //Step1.1.4. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. It��s done. - i = 0; - while(i < 100) - { - RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); - - if(eFuseCtrlStruc.field.EFSROM_KICK == 0) - break; - - RTMPusecDelay(2); - i++; - } - - } - else - { //Step1.2. - //If the same logical number is existing, check if the writting data and the data - //saving in this block are the same. - ///////////////////////////////////////////////////////////////// - //read current values of 16-byte block - RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); - - //Step1.2.0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. - eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; - - //Step1.2.1. Write EFSROM_MODE (0x580, bit7:bit6) to 1. - eFuseCtrlStruc.field.EFSROM_MODE = 0; - - //Step1.2.2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. - eFuseCtrlStruc.field.EFSROM_KICK = 1; - - NdisMoveMemory(&data, &eFuseCtrlStruc, 4); - RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); - - //Step1.2.3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. - i = 0; - while(i < 100) - { - RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); - - if(eFuseCtrlStruc.field.EFSROM_KICK == 0) - break; - RTMPusecDelay(2); - i++; - } - - //Step1.2.4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590) - efuseDataOffset = EFUSE_DATA3; - for(i=0; i< 4; i++) - { - RTMP_IO_READ32(pAd, efuseDataOffset, (PUINT32) &buffer[i]); - efuseDataOffset -= 4; - } - //Step1.2.5. Check if the data of efuse and the writing data are the same. - for(i =0; i<4; i++) - { - tempbuffer=((pData[2*i+1]<<16)&0xffff0000)|pData[2*i]; - DBGPRINT(RT_DEBUG_TRACE, ("buffer[%d]=%x,pData[%d]=%x,pData[%d]=%x,tempbuffer=%x\n",i,buffer[i],2*i,pData[2*i],2*i+1,pData[2*i+1],tempbuffer)); - - if(((buffer[i]&0xffff0000)==(pData[2*i+1]<<16))&&((buffer[i]&0xffff)==pData[2*i])) - bNotWrite&=TRUE; - else - { - bNotWrite&=FALSE; - break; - } - } - if(!bNotWrite) - { - printk("The data is not the same\n"); - - for(i =0; i<8; i++) - { - addr = BlkNum * 0x10 ; - - InBuf[0] = addr+2*i; - InBuf[1] = 2; - InBuf[2] = pData[i]; - - eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); - } - - } - else - return TRUE; - } - - - - //Step 2. Write mapping table - addr = EFUSE_USAGE_MAP_START+BlkNum; - - tmpaddr = addr; - - if(addr % 2 != 0) - addr = addr -1; - InBuf[0] = addr; - InBuf[1] = 2; - - //convert the address from 10 to 8 bit ( bit7, 6 = parity and bit5 ~ 0 = bit9~4), and write to logical map entry - tmpOffset = Offset; - tmpOffset >>= 4; - tmpOffset |= ((~((tmpOffset & 0x01) ^ ( tmpOffset >> 1 & 0x01) ^ (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01))) << 6) & 0x40; - tmpOffset |= ((~( (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01) ^ (tmpOffset >> 4 & 0x01) ^ ( tmpOffset >> 5 & 0x01))) << 7) & 0x80; - - // write the logical address - if(tmpaddr%2 != 0) - InBuf[2] = tmpOffset<<8; - else - InBuf[2] = tmpOffset; - - eFuseWritePhysical(pAd,&InBuf[0], 6, NULL, 0); - - //Step 3. Compare data if not the same, invalidate the mapping entry, then re-write the data until E-fuse is exhausted - bWriteSuccess = TRUE; - for(i =0; i<8; i++) - { - addr = BlkNum * 0x10 ; - - InBuf[0] = addr+2*i; - InBuf[1] = 2; - InBuf[2] = 0x0; - - eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); - DBGPRINT(RT_DEBUG_TRACE, ("addr=%x, buffer[i]=%x,InBuf[2]=%x\n",InBuf[0],pData[i],InBuf[2])); - if(pData[i] != InBuf[2]) - { - bWriteSuccess = FALSE; - break; - } - } - - //Step 4. invlidate mapping entry and find a free mapping entry if not succeed - - if (!bWriteSuccess&&Loop<2) - { - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin::Not bWriteSuccess BlkNum = %d\n", BlkNum)); - - // the offset of current mapping entry - addr = EFUSE_USAGE_MAP_START+BlkNum; - - //find a new mapping entry - BlkNum = 0xffff; - for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2) - { - eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); - if( (LogicalAddress & 0xff) == 0) - { - BlkNum = i-EFUSE_USAGE_MAP_START; - break; - } - else if(( (LogicalAddress >> 8) & 0xff) == 0) - { - if (i != EFUSE_USAGE_MAP_END) - { - BlkNum = i+1-EFUSE_USAGE_MAP_START; - } - break; - } - } - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin::Not bWriteSuccess new BlkNum = %d\n", BlkNum)); - if(BlkNum == 0xffff) - { - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin: out of free E-fuse space!!!\n")); - return FALSE; - } - - //invalidate the original mapping entry if new entry is not found - tmpaddr = addr; - - if(addr % 2 != 0) - addr = addr -1; - InBuf[0] = addr; - InBuf[1] = 2; - - eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); - - // write the logical address - if(tmpaddr%2 != 0) - { - // Invalidate the high byte - for (i=8; i<15; i++) - { - if( ( (InBuf[2] >> i) & 0x01) == 0) - { - InBuf[2] |= (0x1 <> i) & 0x01) == 0) - { - InBuf[2] |= (0x1 <bUseEfuse = FALSE; + RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrl); + pAd->bUseEfuse = ((eFuseCtrl & 0x80000000) == 0x80000000) ? 1 : 0; + if (pAd->bUseEfuse) { + pChipOps->eeinit = eFuse_init; + pChipOps->eeread = rtmp_ee_efuse_read16; + return 0; + } else + DBGPRINT(RT_DEBUG_TRACE, ("NVM is EEPROM\n")); +#endif /* RTMP_EFUSE_SUPPORT // */ +#endif /* RT30xx // */ + + switch (infType) { +#ifdef RTMP_PCI_SUPPORT + case RTMP_DEV_INF_PCI: + pChipOps->eeinit = NULL; + pChipOps->eeread = rtmp_ee_prom_read16; + break; +#endif /* RTMP_PCI_SUPPORT // */ +#ifdef RTMP_USB_SUPPORT + case RTMP_DEV_INF_USB: + pChipOps->eeinit = NULL; + pChipOps->eeread = RTUSBReadEEPROM16; + break; +#endif /* RTMP_USB_SUPPORT // */ + + default: + DBGPRINT(RT_DEBUG_ERROR, ("RtmpChipOpsEepromHook() failed!\n")); + break; + } + + return 0; } -#endif diff --git a/drivers/staging/rt2860/common/firmware.h b/drivers/staging/rt2860/common/firmware.h index e72996f42c07b52ed7f6a975c8b88a1af361e1b6..2fecd32f760012d06855fc9c47149ed5feec236b 100644 --- a/drivers/staging/rt2860/common/firmware.h +++ b/drivers/staging/rt2860/common/firmware.h @@ -43,7 +43,7 @@ /* AUTO GEN PLEASE DO NOT MODIFY IT */ -UCHAR FirmwareImage [] = { +u8 FirmwareImage_2860 [] = { 0x02, 0x03, 0x5e, 0x02, 0x02, 0xb1, 0x22, 0x22, 0xff, 0xff, 0xff, 0x02, 0x01, 0x82, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x01, 0x33, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18, 0xc2, 0xaf, 0x30, 0x45, 0x03, diff --git a/drivers/staging/rt2860/common/firmware_3070.h b/drivers/staging/rt2860/common/firmware_3070.h new file mode 100644 index 0000000000000000000000000000000000000000..b710d40bc04662659b1f991997fa9bbca97bcc60 --- /dev/null +++ b/drivers/staging/rt2860/common/firmware_3070.h @@ -0,0 +1,517 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +u8 FirmwareImage_3070 [] = { +0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x13, 0x1f, 0x02, +0x13, 0x20, 0x02, 0x13, 0x3f, 0x02, 0x13, 0x44, 0x12, 0x13, 0x40, 0x22, 0x02, 0x17, 0xae, 0x02, +0x18, 0xd2, 0x02, 0x14, 0x3d, 0x02, 0x13, 0x78, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x19, +0x95, 0x22, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe3, 0x1b, 0xe5, 0x4c, 0x30, 0xe0, 0x04, 0x7f, 0x40, +0x80, 0x02, 0x7f, 0x00, 0x90, 0x10, 0x2f, 0xef, 0xf0, 0x90, 0x01, 0x8c, 0x74, 0x08, 0xf0, 0xe4, +0x90, 0x01, 0xa7, 0xf0, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe0, 0x1c, 0x90, 0x01, 0x80, 0xe0, 0xb4, +0x02, 0x15, 0xa3, 0xe0, 0xb4, 0x01, 0x10, 0x90, 0x01, 0x84, 0xe0, 0xb4, 0x81, 0x09, 0x90, 0x01, +0x8c, 0x74, 0x01, 0xf0, 0x12, 0x0d, 0xc8, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02, +0x13, 0x1e, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x0a, 0x9d, 0x10, +0xd9, 0x31, 0x10, 0xbd, 0x36, 0x11, 0x02, 0x50, 0x11, 0x39, 0x51, 0x11, 0x42, 0x52, 0x11, 0x42, +0x53, 0x11, 0x42, 0x54, 0x11, 0x83, 0x55, 0x11, 0xd2, 0x56, 0x12, 0x25, 0x70, 0x12, 0x50, 0x71, +0x12, 0x7e, 0x72, 0x12, 0xd5, 0x73, 0x12, 0xf6, 0x80, 0x00, 0x00, 0x13, 0x1e, 0x90, 0x70, 0x11, +0xe0, 0xf5, 0x3c, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe5, 0x56, +0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d, +0x02, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, +0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x85, 0x56, 0x41, 0xd2, +0x02, 0x22, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0xff, 0xbf, 0x0a, 0x0d, 0x90, 0x70, 0x11, 0xe0, +0xb4, 0x08, 0x06, 0x75, 0x4e, 0x01, 0x75, 0x4f, 0x84, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0xff, +0xbf, 0x02, 0x12, 0x90, 0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x04, 0xe0, 0xb4, 0x20, 0x06, 0x75, +0x4e, 0x03, 0x75, 0x4f, 0x20, 0xe4, 0xf5, 0x27, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, +0x47, 0x22, 0x90, 0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0, +0xff, 0x74, 0x47, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48, +0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, +0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, +0x02, 0x13, 0x17, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x1d, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x17, 0xe5, +0x47, 0x64, 0x09, 0x60, 0x11, 0xe5, 0x47, 0x64, 0x0a, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x0b, 0x60, +0x05, 0xe5, 0x47, 0xb4, 0x0c, 0x08, 0x90, 0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe5, 0x47, +0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, 0x03, 0x03, 0xe4, 0xf5, 0x46, 0xe5, 0x47, 0xb4, 0x0a, 0x08, +0xe5, 0x3a, 0xb4, 0x01, 0x03, 0xe4, 0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0xd2, +0x04, 0x22, 0x90, 0x70, 0x11, 0xe0, 0xf4, 0xff, 0x90, 0x70, 0x10, 0xe0, 0x5f, 0xff, 0x90, 0x70, +0x11, 0xe0, 0x55, 0x27, 0x4f, 0x90, 0x70, 0x18, 0xf0, 0x90, 0x70, 0x11, 0xe0, 0x90, 0x70, 0x19, +0xf0, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x30, 0x15, 0x03, 0xd2, 0x14, 0x22, 0x90, 0x70, +0x18, 0xe0, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef, 0x5e, +0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff, 0x90, +0x02, 0x28, 0xef, 0xf0, 0x22, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, +0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, +0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, +0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0, +0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, +0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x90, 0x10, +0x00, 0xe0, 0xf5, 0x57, 0x90, 0x10, 0x02, 0xe0, 0xf5, 0x58, 0xa3, 0xe0, 0xf5, 0x59, 0xe5, 0x58, +0xb4, 0x70, 0x1e, 0xe5, 0x59, 0xb4, 0x30, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd, +0x90, 0x05, 0x05, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe, 0x90, 0x05, 0x08, +0xf0, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x75, 0x3a, 0xff, 0x75, 0x3c, 0xff, 0xad, 0x57, 0xaf, 0x56, +0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, +0xf4, 0x60, 0x4b, 0x80, 0x42, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf, +0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, +0x56, 0xf4, 0x60, 0x2a, 0x80, 0x21, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, +0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, +0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x07, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x22, 0x22, +0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60, 0x09, 0xb2, 0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04, +0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22, +0xc2, 0x42, 0xd3, 0x22, 0x30, 0x14, 0x30, 0x90, 0x70, 0x19, 0xe0, 0x55, 0x27, 0xff, 0x90, 0x70, +0x18, 0xe0, 0x4f, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef, +0x5e, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff, +0x90, 0x02, 0x28, 0xef, 0xf0, 0xc2, 0x14, 0x22, 0xc2, 0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x0a, +0x9d, 0x13, 0x9a, 0x00, 0x14, 0x28, 0x04, 0x14, 0x24, 0x08, 0x14, 0x04, 0x10, 0x13, 0xae, 0x20, +0x13, 0xce, 0x60, 0x13, 0xdf, 0xa0, 0x00, 0x00, 0x14, 0x2a, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42, +0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03, 0x02, 0x14, 0x2a, 0x80, 0x1b, 0xe5, 0x48, +0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54, +0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x61, 0x53, 0x43, 0x0f, 0x80, 0x5c, 0x85, 0x49, +0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4d, 0x80, 0x1b, 0xe5, +0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4, +0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x30, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10, +0xf5, 0x43, 0x80, 0x26, 0xe5, 0x47, 0x64, 0x04, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, +0x5e, 0x04, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, +0xf5, 0x43, 0x80, 0x06, 0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x25, 0xe5, 0x42, 0xc4, +0x54, 0xf0, 0xff, 0xe5, 0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0xd2, 0x60, 0x22, 0xd2, 0x15, 0xe5, +0x47, 0x24, 0xf5, 0x60, 0x0b, 0x24, 0xcb, 0x60, 0x07, 0x24, 0x40, 0x70, 0x06, 0xc2, 0x15, 0x22, +0x12, 0x17, 0x79, 0x12, 0x14, 0x5f, 0xc2, 0x15, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, +0xaf, 0x90, 0x04, 0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45, +0x4f, 0x24, 0xff, 0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74, +0x1e, 0xf0, 0xe5, 0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x25, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5, +0x5f, 0x20, 0xe5, 0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5, +0x25, 0x70, 0x05, 0x75, 0x25, 0x0c, 0x80, 0x02, 0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, +0xe5, 0x5f, 0x30, 0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, +0x47, 0x64, 0x03, 0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x25, +0x70, 0x03, 0x30, 0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x25, 0x70, 0x05, 0x75, 0x25, 0x07, 0x80, 0x02, +0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b, +0xe5, 0x3a, 0x64, 0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0xe5, +0x47, 0xb4, 0x0a, 0x13, 0xe5, 0x3a, 0xb4, 0x01, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x08, 0xe5, +0x3a, 0x70, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2, +0x68, 0x20, 0x6b, 0x07, 0xe5, 0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e, +0x20, 0xe2, 0x02, 0xb2, 0x6c, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x26, 0x30, +0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01, 0x80, +0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, +0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x26, +0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f, 0x01, +0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, +0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80, +0x26, 0xe5, 0x47, 0x64, 0x0a, 0x70, 0x22, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x17, +0xe5, 0x3a, 0xb4, 0x01, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x34, 0xe5, 0x46, 0x20, 0xe4, 0x03, +0x30, 0xe5, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2, +0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe1, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, +0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, +0x71, 0x92, 0x70, 0x90, 0x10, 0x00, 0xe0, 0x90, 0x10, 0x2c, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3, +0x94, 0x30, 0x40, 0x14, 0xa2, 0x71, 0x92, 0x77, 0xa2, 0x70, 0x92, 0x76, 0xe5, 0x2e, 0x13, 0x13, +0x54, 0x3f, 0xf5, 0x2e, 0xc2, 0x77, 0xd2, 0x76, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, +0x64, 0x06, 0x70, 0x39, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, +0x14, 0x60, 0x0c, 0x24, 0xfe, 0x60, 0x0c, 0x24, 0x03, 0x70, 0x13, 0xc2, 0x38, 0x80, 0x0f, 0xd2, +0x38, 0x80, 0x0b, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x38, 0x30, 0x47, +0x05, 0xaf, 0x27, 0x02, 0x17, 0x73, 0xe5, 0x27, 0xf4, 0xff, 0x02, 0x17, 0x73, 0xe5, 0x47, 0x64, +0x07, 0x60, 0x0f, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02, +0x16, 0xf2, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x22, 0x14, 0x60, +0x25, 0x14, 0x60, 0x2d, 0x24, 0xfc, 0x60, 0x49, 0x24, 0xf9, 0x60, 0x14, 0x24, 0x0e, 0x70, 0x50, +0xe5, 0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x24, 0xff, 0x80, 0x3a, +0xd2, 0x39, 0xc2, 0x38, 0x80, 0x3e, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x1d, 0xc3, 0x80, +0x1a, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, +0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0x38, 0xc2, 0x39, 0x80, +0x13, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0xc2, 0x38, 0x80, 0x04, +0xc2, 0x38, 0xc2, 0x39, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff, 0x02, +0x17, 0x73, 0xe5, 0x47, 0x64, 0x0c, 0x60, 0x06, 0xe5, 0x47, 0x64, 0x0b, 0x70, 0x7a, 0x90, 0x02, +0x29, 0xe0, 0x54, 0xfd, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x20, 0x14, 0x60, 0x21, 0x14, 0x60, 0x2b, +0x24, 0xfc, 0x60, 0x45, 0x24, 0xf9, 0x60, 0x12, 0x24, 0x0e, 0x70, 0x4a, 0xe5, 0x46, 0x13, 0x13, +0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x80, 0x29, 0xd2, 0x39, 0x80, 0x3a, 0xe5, 0x46, +0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0x80, 0x2d, 0xe5, 0x46, 0x30, 0xe2, 0x0d, +0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, +0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0x39, 0x80, 0x0f, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, +0x01, 0xc3, 0x92, 0x39, 0x80, 0x02, 0xc2, 0x39, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, +0x27, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0xe5, 0x47, 0xb4, 0x0b, 0x10, 0x90, 0x02, +0x29, 0xe0, 0x54, 0xeb, 0xf0, 0xe5, 0x27, 0x54, 0xeb, 0x45, 0x45, 0xf5, 0x27, 0x22, 0xe4, 0x90, +0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02, +0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5, +0x62, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x48, 0x14, 0x60, 0x66, 0x24, 0x02, 0x60, 0x03, 0x02, +0x18, 0xb6, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0x7f, 0xf0, 0xa3, 0xe0, +0x20, 0xe7, 0x23, 0x90, 0x04, 0x34, 0xe0, 0xb4, 0x02, 0x1c, 0xa3, 0xe0, 0xb4, 0x02, 0x17, 0xa3, +0xe0, 0xb4, 0x02, 0x12, 0x7f, 0x20, 0x12, 0x17, 0xa4, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, +0x75, 0x51, 0x01, 0x02, 0x18, 0xb6, 0xe5, 0x50, 0x70, 0x06, 0x75, 0x62, 0x03, 0x02, 0x18, 0xb6, +0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70, 0x12, 0x7f, 0x20, 0x12, 0x17, 0xa4, 0x90, 0x02, 0xa2, +0xe0, 0x54, 0xbf, 0xf0, 0x75, 0x51, 0x02, 0x02, 0x18, 0xb6, 0xe5, 0x50, 0x70, 0x03, 0x02, 0x18, +0xb1, 0x90, 0x02, 0xa3, 0xe0, 0x30, 0xe6, 0x03, 0x02, 0x18, 0xad, 0x90, 0x04, 0x37, 0xe0, 0x64, +0x22, 0x70, 0x7a, 0x90, 0x01, 0x8a, 0x74, 0x7e, 0xf0, 0x90, 0x01, 0x96, 0xf0, 0x90, 0x12, 0x04, +0x74, 0x0a, 0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x15, 0xe5, 0x59, 0xb4, 0x35, 0x10, 0xe4, 0x90, 0x05, +0x00, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0x7f, 0x01, 0x12, +0x0d, 0x2a, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xf0, 0xf0, 0xe5, 0x59, +0xb4, 0x35, 0x14, 0xe5, 0x3c, 0xf4, 0x60, 0x06, 0xa3, 0xe0, 0x54, 0xf3, 0x80, 0x14, 0x90, 0x13, +0x2a, 0xe0, 0x54, 0xfb, 0xf0, 0x80, 0x14, 0xe5, 0x3c, 0xf4, 0x90, 0x13, 0x2a, 0x60, 0x08, 0xe0, +0x54, 0xf2, 0x45, 0x3c, 0xf0, 0x80, 0x04, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x54, +0xfd, 0xf0, 0x75, 0x62, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, +0x05, 0x75, 0x62, 0x03, 0xf5, 0x51, 0xe5, 0x62, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, +0x59, 0xad, 0x62, 0xaf, 0x40, 0x12, 0x19, 0x61, 0xe5, 0x62, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, +0xaf, 0x22, 0xc2, 0xaf, 0x30, 0x01, 0x12, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xf5, 0x51, 0xc2, 0x59, +0xc2, 0x01, 0x7d, 0x02, 0xaf, 0x40, 0x12, 0x19, 0x61, 0xe5, 0x52, 0x14, 0x60, 0x09, 0x04, 0x70, +0x6d, 0x75, 0x52, 0x01, 0x75, 0x55, 0x03, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0x90, 0x13, +0x28, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, +0x12, 0x04, 0x74, 0x03, 0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x16, 0xe5, 0x59, 0xb4, 0x35, 0x11, 0x90, +0x05, 0x00, 0x74, 0xe2, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, +0x7f, 0x01, 0x12, 0x0d, 0x2a, 0x90, 0x02, 0xa2, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x10, 0x04, 0xe0, +0x44, 0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x09, 0xc2, 0x02, 0x7d, 0x01, 0xaf, +0x41, 0x12, 0x19, 0x61, 0x30, 0x03, 0x02, 0xc2, 0x03, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xd2, 0xaf, +0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, +0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, +0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, +0x04, 0xd5, 0x22, 0x22, 0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x4d, 0xc2, 0xaf, 0x90, 0x70, +0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70, +0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x62, 0x90, 0x10, 0x1e, 0xe0, +0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90, +0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a, 0x07, 0x90, 0x70, +0x24, 0xe0, 0x44, 0x01, 0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x7b, 0xc4, +0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x13, 0x1f, 0x02, +0x13, 0x20, 0x02, 0x13, 0x3f, 0x02, 0x13, 0x44, 0x12, 0x13, 0x40, 0x22, 0x02, 0x17, 0xae, 0x02, +0x18, 0xd2, 0x02, 0x14, 0x3d, 0x02, 0x13, 0x78, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x19, +0x95, 0x22, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe3, 0x1b, 0xe5, 0x4c, 0x30, 0xe0, 0x04, 0x7f, 0x40, +0x80, 0x02, 0x7f, 0x00, 0x90, 0x10, 0x2f, 0xef, 0xf0, 0x90, 0x01, 0x8c, 0x74, 0x08, 0xf0, 0xe4, +0x90, 0x01, 0xa7, 0xf0, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe0, 0x1c, 0x90, 0x01, 0x80, 0xe0, 0xb4, +0x02, 0x15, 0xa3, 0xe0, 0xb4, 0x01, 0x10, 0x90, 0x01, 0x84, 0xe0, 0xb4, 0x81, 0x09, 0x90, 0x01, +0x8c, 0x74, 0x01, 0xf0, 0x12, 0x0d, 0xdd, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02, +0x13, 0x1e, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x0a, 0xb6, 0x10, +0xd9, 0x31, 0x10, 0xbd, 0x36, 0x11, 0x02, 0x50, 0x11, 0x39, 0x51, 0x11, 0x42, 0x52, 0x11, 0x42, +0x53, 0x11, 0x42, 0x54, 0x11, 0x83, 0x55, 0x11, 0xd2, 0x56, 0x12, 0x25, 0x70, 0x12, 0x50, 0x71, +0x12, 0x7e, 0x72, 0x12, 0xd5, 0x73, 0x12, 0xf6, 0x80, 0x00, 0x00, 0x13, 0x1e, 0x90, 0x70, 0x11, +0xe0, 0xf5, 0x3c, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe5, 0x56, +0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d, +0x02, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, +0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x85, 0x56, 0x41, 0xd2, +0x02, 0x22, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0xff, 0xbf, 0x0a, 0x0d, 0x90, 0x70, 0x11, 0xe0, +0xb4, 0x08, 0x06, 0x75, 0x4e, 0x01, 0x75, 0x4f, 0x84, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0xff, +0xbf, 0x02, 0x12, 0x90, 0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x04, 0xe0, 0xb4, 0x20, 0x06, 0x75, +0x4e, 0x03, 0x75, 0x4f, 0x20, 0xe4, 0xf5, 0x27, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, +0x47, 0x22, 0x90, 0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0, +0xff, 0x74, 0x47, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48, +0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, +0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, +0x02, 0x13, 0x17, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x1d, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x17, 0xe5, +0x47, 0x64, 0x09, 0x60, 0x11, 0xe5, 0x47, 0x64, 0x0a, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x0b, 0x60, +0x05, 0xe5, 0x47, 0xb4, 0x0c, 0x08, 0x90, 0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe5, 0x47, +0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, 0x03, 0x03, 0xe4, 0xf5, 0x46, 0xe5, 0x47, 0xb4, 0x0a, 0x08, +0xe5, 0x3a, 0xb4, 0x01, 0x03, 0xe4, 0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0xd2, +0x04, 0x22, 0x90, 0x70, 0x11, 0xe0, 0xf4, 0xff, 0x90, 0x70, 0x10, 0xe0, 0x5f, 0xff, 0x90, 0x70, +0x11, 0xe0, 0x55, 0x27, 0x4f, 0x90, 0x70, 0x18, 0xf0, 0x90, 0x70, 0x11, 0xe0, 0x90, 0x70, 0x19, +0xf0, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x30, 0x15, 0x03, 0xd2, 0x14, 0x22, 0x90, 0x70, +0x18, 0xe0, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef, 0x5e, +0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff, 0x90, +0x02, 0x28, 0xef, 0xf0, 0x22, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, +0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, +0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, +0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0, +0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, +0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x90, 0x10, +0x00, 0xe0, 0xf5, 0x57, 0x90, 0x10, 0x02, 0xe0, 0xf5, 0x58, 0xa3, 0xe0, 0xf5, 0x59, 0xe5, 0x58, +0xb4, 0x70, 0x1e, 0xe5, 0x59, 0xb4, 0x30, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd, +0x90, 0x05, 0x05, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe, 0x90, 0x05, 0x08, +0xf0, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x75, 0x3a, 0xff, 0x75, 0x3c, 0xff, 0xad, 0x57, 0xaf, 0x56, +0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, +0xf4, 0x60, 0x4b, 0x80, 0x42, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf, +0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, +0x56, 0xf4, 0x60, 0x2a, 0x80, 0x21, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, +0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, +0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x07, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x22, 0x22, +0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60, 0x09, 0xb2, 0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04, +0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22, +0xc2, 0x42, 0xd3, 0x22, 0x30, 0x14, 0x30, 0x90, 0x70, 0x19, 0xe0, 0x55, 0x27, 0xff, 0x90, 0x70, +0x18, 0xe0, 0x4f, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef, +0x5e, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff, +0x90, 0x02, 0x28, 0xef, 0xf0, 0xc2, 0x14, 0x22, 0xc2, 0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x0a, +0xb6, 0x13, 0x9a, 0x00, 0x14, 0x28, 0x04, 0x14, 0x24, 0x08, 0x14, 0x04, 0x10, 0x13, 0xae, 0x20, +0x13, 0xce, 0x60, 0x13, 0xdf, 0xa0, 0x00, 0x00, 0x14, 0x2a, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42, +0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03, 0x02, 0x14, 0x2a, 0x80, 0x1b, 0xe5, 0x48, +0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54, +0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x61, 0x53, 0x43, 0x0f, 0x80, 0x5c, 0x85, 0x49, +0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4d, 0x80, 0x1b, 0xe5, +0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4, +0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x30, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10, +0xf5, 0x43, 0x80, 0x26, 0xe5, 0x47, 0x64, 0x04, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, +0x5e, 0x04, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, +0xf5, 0x43, 0x80, 0x06, 0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x25, 0xe5, 0x42, 0xc4, +0x54, 0xf0, 0xff, 0xe5, 0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0xd2, 0x60, 0x22, 0xd2, 0x15, 0xe5, +0x47, 0x24, 0xf5, 0x60, 0x0b, 0x24, 0xcb, 0x60, 0x07, 0x24, 0x40, 0x70, 0x06, 0xc2, 0x15, 0x22, +0x12, 0x17, 0x79, 0x12, 0x14, 0x5f, 0xc2, 0x15, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, +0xaf, 0x90, 0x04, 0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45, +0x4f, 0x24, 0xff, 0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74, +0x1e, 0xf0, 0xe5, 0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x25, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5, +0x5f, 0x20, 0xe5, 0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5, +0x25, 0x70, 0x05, 0x75, 0x25, 0x0c, 0x80, 0x02, 0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, +0xe5, 0x5f, 0x30, 0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, +0x47, 0x64, 0x03, 0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x25, +0x70, 0x03, 0x30, 0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x25, 0x70, 0x05, 0x75, 0x25, 0x07, 0x80, 0x02, +0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b, +0xe5, 0x3a, 0x64, 0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0xe5, +0x47, 0xb4, 0x0a, 0x13, 0xe5, 0x3a, 0xb4, 0x01, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x08, 0xe5, +0x3a, 0x70, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2, +0x68, 0x20, 0x6b, 0x07, 0xe5, 0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e, +0x20, 0xe2, 0x02, 0xb2, 0x6c, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x26, 0x30, +0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01, 0x80, +0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, +0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x26, +0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f, 0x01, +0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, +0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80, +0x26, 0xe5, 0x47, 0x64, 0x0a, 0x70, 0x22, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x17, +0xe5, 0x3a, 0xb4, 0x01, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x34, 0xe5, 0x46, 0x20, 0xe4, 0x03, +0x30, 0xe5, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2, +0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe1, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, +0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, +0x71, 0x92, 0x70, 0x90, 0x10, 0x00, 0xe0, 0x90, 0x10, 0x2c, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3, +0x94, 0x30, 0x40, 0x14, 0xa2, 0x71, 0x92, 0x77, 0xa2, 0x70, 0x92, 0x76, 0xe5, 0x2e, 0x13, 0x13, +0x54, 0x3f, 0xf5, 0x2e, 0xc2, 0x77, 0xd2, 0x76, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, +0x64, 0x06, 0x70, 0x39, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, +0x14, 0x60, 0x0c, 0x24, 0xfe, 0x60, 0x0c, 0x24, 0x03, 0x70, 0x13, 0xc2, 0x38, 0x80, 0x0f, 0xd2, +0x38, 0x80, 0x0b, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x38, 0x30, 0x47, +0x05, 0xaf, 0x27, 0x02, 0x17, 0x73, 0xe5, 0x27, 0xf4, 0xff, 0x02, 0x17, 0x73, 0xe5, 0x47, 0x64, +0x07, 0x60, 0x0f, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02, +0x16, 0xf2, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x22, 0x14, 0x60, +0x25, 0x14, 0x60, 0x2d, 0x24, 0xfc, 0x60, 0x49, 0x24, 0xf9, 0x60, 0x14, 0x24, 0x0e, 0x70, 0x50, +0xe5, 0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x24, 0xff, 0x80, 0x3a, +0xd2, 0x39, 0xc2, 0x38, 0x80, 0x3e, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x1d, 0xc3, 0x80, +0x1a, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, +0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0x38, 0xc2, 0x39, 0x80, +0x13, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0xc2, 0x38, 0x80, 0x04, +0xc2, 0x38, 0xc2, 0x39, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff, 0x02, +0x17, 0x73, 0xe5, 0x47, 0x64, 0x0c, 0x60, 0x06, 0xe5, 0x47, 0x64, 0x0b, 0x70, 0x7a, 0x90, 0x02, +0x29, 0xe0, 0x54, 0xfd, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x20, 0x14, 0x60, 0x21, 0x14, 0x60, 0x2b, +0x24, 0xfc, 0x60, 0x45, 0x24, 0xf9, 0x60, 0x12, 0x24, 0x0e, 0x70, 0x4a, 0xe5, 0x46, 0x13, 0x13, +0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x80, 0x29, 0xd2, 0x39, 0x80, 0x3a, 0xe5, 0x46, +0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0x80, 0x2d, 0xe5, 0x46, 0x30, 0xe2, 0x0d, +0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, +0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0x39, 0x80, 0x0f, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, +0x01, 0xc3, 0x92, 0x39, 0x80, 0x02, 0xc2, 0x39, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, +0x27, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0xe5, 0x47, 0xb4, 0x0b, 0x10, 0x90, 0x02, +0x29, 0xe0, 0x54, 0xeb, 0xf0, 0xe5, 0x27, 0x54, 0xeb, 0x45, 0x45, 0xf5, 0x27, 0x22, 0xe4, 0x90, +0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02, +0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5, +0x62, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x48, 0x14, 0x60, 0x66, 0x24, 0x02, 0x60, 0x03, 0x02, +0x18, 0xb6, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0x7f, 0xf0, 0xa3, 0xe0, +0x20, 0xe7, 0x23, 0x90, 0x04, 0x34, 0xe0, 0xb4, 0x02, 0x1c, 0xa3, 0xe0, 0xb4, 0x02, 0x17, 0xa3, +0xe0, 0xb4, 0x02, 0x12, 0x7f, 0x20, 0x12, 0x17, 0xa4, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, +0x75, 0x51, 0x01, 0x02, 0x18, 0xb6, 0xe5, 0x50, 0x70, 0x06, 0x75, 0x62, 0x03, 0x02, 0x18, 0xb6, +0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70, 0x12, 0x7f, 0x20, 0x12, 0x17, 0xa4, 0x90, 0x02, 0xa2, +0xe0, 0x54, 0xbf, 0xf0, 0x75, 0x51, 0x02, 0x02, 0x18, 0xb6, 0xe5, 0x50, 0x70, 0x03, 0x02, 0x18, +0xb1, 0x90, 0x02, 0xa3, 0xe0, 0x30, 0xe6, 0x03, 0x02, 0x18, 0xad, 0x90, 0x04, 0x37, 0xe0, 0x64, +0x22, 0x70, 0x7a, 0x90, 0x01, 0x8a, 0x74, 0x7e, 0xf0, 0x90, 0x01, 0x96, 0xf0, 0x90, 0x12, 0x04, +0x74, 0x0a, 0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x15, 0xe5, 0x59, 0xb4, 0x35, 0x10, 0xe4, 0x90, 0x05, +0x00, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0x7f, 0x01, 0x12, +0x0d, 0x48, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xf0, 0xf0, 0xe5, 0x59, +0xb4, 0x35, 0x14, 0xe5, 0x3c, 0xf4, 0x60, 0x06, 0xa3, 0xe0, 0x54, 0xf3, 0x80, 0x14, 0x90, 0x13, +0x2a, 0xe0, 0x54, 0xfb, 0xf0, 0x80, 0x14, 0xe5, 0x3c, 0xf4, 0x90, 0x13, 0x2a, 0x60, 0x08, 0xe0, +0x54, 0xf2, 0x45, 0x3c, 0xf0, 0x80, 0x04, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x54, +0xfd, 0xf0, 0x75, 0x62, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, +0x05, 0x75, 0x62, 0x03, 0xf5, 0x51, 0xe5, 0x62, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, +0x59, 0xad, 0x62, 0xaf, 0x40, 0x12, 0x19, 0x61, 0xe5, 0x62, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, +0xaf, 0x22, 0xc2, 0xaf, 0x30, 0x01, 0x12, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xf5, 0x51, 0xc2, 0x59, +0xc2, 0x01, 0x7d, 0x02, 0xaf, 0x40, 0x12, 0x19, 0x61, 0xe5, 0x52, 0x14, 0x60, 0x09, 0x04, 0x70, +0x6d, 0x75, 0x52, 0x01, 0x75, 0x55, 0x03, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0x90, 0x13, +0x28, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, +0x12, 0x04, 0x74, 0x03, 0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x16, 0xe5, 0x59, 0xb4, 0x35, 0x11, 0x90, +0x05, 0x00, 0x74, 0xe2, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, +0x7f, 0x01, 0x12, 0x0d, 0x48, 0x90, 0x02, 0xa2, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x10, 0x04, 0xe0, +0x44, 0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x09, 0xc2, 0x02, 0x7d, 0x01, 0xaf, +0x41, 0x12, 0x19, 0x61, 0x30, 0x03, 0x02, 0xc2, 0x03, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xd2, 0xaf, +0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, +0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, +0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, +0x04, 0xd5, 0x22, 0x22, 0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x4d, 0xc2, 0xaf, 0x90, 0x70, +0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70, +0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x62, 0x90, 0x10, 0x1e, 0xe0, +0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90, +0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a, 0x07, 0x90, 0x70, +0x24, 0xe0, 0x44, 0x01, 0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x65, 0xd3, } ; diff --git a/drivers/staging/rt2860/common/md5.c b/drivers/staging/rt2860/common/md5.c deleted file mode 100644 index ad883ca2ffc8469ef082388fdb8a6562d799d43b..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2860/common/md5.c +++ /dev/null @@ -1,1415 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - md5.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Name Date Modification logs - jan 10-28-03 Initial - Rita 11-23-04 Modify MD5 and SHA-1 - Rita 10-14-05 Modify SHA-1 in big-endian platform - */ -#include "../rt_config.h" - -/** - * md5_mac: - * @key: pointer to the key used for MAC generation - * @key_len: length of the key in bytes - * @data: pointer to the data area for which the MAC is generated - * @data_len: length of the data in bytes - * @mac: pointer to the buffer holding space for the MAC; the buffer should - * have space for 128-bit (16 bytes) MD5 hash value - * - * md5_mac() determines the message authentication code by using secure hash - * MD5(key | data | key). - */ -void md5_mac(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac) -{ - MD5_CTX context; - - MD5Init(&context); - MD5Update(&context, key, key_len); - MD5Update(&context, data, data_len); - MD5Update(&context, key, key_len); - MD5Final(mac, &context); -} - -/** - * hmac_md5: - * @key: pointer to the key used for MAC generation - * @key_len: length of the key in bytes - * @data: pointer to the data area for which the MAC is generated - * @data_len: length of the data in bytes - * @mac: pointer to the buffer holding space for the MAC; the buffer should - * have space for 128-bit (16 bytes) MD5 hash value - * - * hmac_md5() determines the message authentication code using HMAC-MD5. - * This implementation is based on the sample code presented in RFC 2104. - */ -void hmac_md5(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac) -{ - MD5_CTX context; - u8 k_ipad[65]; /* inner padding - key XORd with ipad */ - u8 k_opad[65]; /* outer padding - key XORd with opad */ - u8 tk[16]; - int i; - - //assert(key != NULL && data != NULL && mac != NULL); - - /* if key is longer than 64 bytes reset it to key = MD5(key) */ - if (key_len > 64) { - MD5_CTX ttcontext; - - MD5Init(&ttcontext); - MD5Update(&ttcontext, key, key_len); - MD5Final(tk, &ttcontext); - //key=(PUCHAR)ttcontext.buf; - key = tk; - key_len = 16; - } - - /* the HMAC_MD5 transform looks like: - * - * MD5(K XOR opad, MD5(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected */ - - /* start out by storing key in pads */ - NdisZeroMemory(k_ipad, sizeof(k_ipad)); - NdisZeroMemory(k_opad, sizeof(k_opad)); - //assert(key_len < sizeof(k_ipad)); - NdisMoveMemory(k_ipad, key, key_len); - NdisMoveMemory(k_opad, key, key_len); - - /* XOR key with ipad and opad values */ - for (i = 0; i < 64; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - - /* perform inner MD5 */ - MD5Init(&context); /* init context for 1st pass */ - MD5Update(&context, k_ipad, 64); /* start with inner pad */ - MD5Update(&context, data, data_len); /* then text of datagram */ - MD5Final(mac, &context); /* finish up 1st pass */ - - /* perform outer MD5 */ - MD5Init(&context); /* init context for 2nd pass */ - MD5Update(&context, k_opad, 64); /* start with outer pad */ - MD5Update(&context, mac, 16); /* then results of 1st hash */ - MD5Final(mac, &context); /* finish up 2nd pass */ -} - -#define byteReverse(buf, len) /* Nothing */ - -/* ========================== MD5 implementation =========================== */ -// four base functions for MD5 -#define MD5_F1(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define MD5_F2(x, y, z) (((x) & (z)) | ((y) & (~z))) -#define MD5_F3(x, y, z) ((x) ^ (y) ^ (z)) -#define MD5_F4(x, y, z) ((y) ^ ((x) | (~z))) -#define CYCLIC_LEFT_SHIFT(w, s) (((w) << (s)) | ((w) >> (32-(s)))) - -#define MD5Step(f, w, x, y, z, data, t, s) \ - ( w += f(x, y, z) + data + t, w = (CYCLIC_LEFT_SHIFT(w, s)) & 0xffffffff, w += x ) - - -/* - * Function Description: - * Initiate MD5 Context satisfied in RFC 1321 - * - * Arguments: - * pCtx Pointer to MD5 context - * - * Return Value: - * None - */ -VOID MD5Init(MD5_CTX *pCtx) -{ - pCtx->Buf[0]=0x67452301; - pCtx->Buf[1]=0xefcdab89; - pCtx->Buf[2]=0x98badcfe; - pCtx->Buf[3]=0x10325476; - - pCtx->LenInBitCount[0]=0; - pCtx->LenInBitCount[1]=0; -} - - -/* - * Function Description: - * Update MD5 Context, allow of an arrary of octets as the next portion - * of the message - * - * Arguments: - * pCtx Pointer to MD5 context - * pData Pointer to input data - * LenInBytes The length of input data (unit: byte) - * - * Return Value: - * None - * - * Note: - * Called after MD5Init or MD5Update(itself) - */ -VOID MD5Update(MD5_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes) -{ - - UINT32 TfTimes; - UINT32 temp; - unsigned int i; - - temp = pCtx->LenInBitCount[0]; - - pCtx->LenInBitCount[0] = (UINT32) (pCtx->LenInBitCount[0] + (LenInBytes << 3)); - - if (pCtx->LenInBitCount[0] < temp) - pCtx->LenInBitCount[1]++; //carry in - - pCtx->LenInBitCount[1] += LenInBytes >> 29; - - // mod 64 bytes - temp = (temp >> 3) & 0x3f; - - // process lacks of 64-byte data - if (temp) - { - UCHAR *pAds = (UCHAR *) pCtx->Input + temp; - - if ((temp+LenInBytes) < 64) - { - NdisMoveMemory(pAds, (UCHAR *)pData, LenInBytes); - return; - } - - NdisMoveMemory(pAds, (UCHAR *)pData, 64-temp); - byteReverse(pCtx->Input, 16); - MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); - - pData += 64-temp; - LenInBytes -= 64-temp; - } // end of if (temp) - - - TfTimes = (LenInBytes >> 6); - - for (i=TfTimes; i>0; i--) - { - NdisMoveMemory(pCtx->Input, (UCHAR *)pData, 64); - byteReverse(pCtx->Input, 16); - MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); - pData += 64; - LenInBytes -= 64; - } // end of for - - // buffering lacks of 64-byte data - if(LenInBytes) - NdisMoveMemory(pCtx->Input, (UCHAR *)pData, LenInBytes); - -} - - -/* - * Function Description: - * Append padding bits and length of original message in the tail - * The message digest has to be completed in the end - * - * Arguments: - * Digest Output of Digest-Message for MD5 - * pCtx Pointer to MD5 context - * - * Return Value: - * None - * - * Note: - * Called after MD5Update - */ -VOID MD5Final(UCHAR Digest[16], MD5_CTX *pCtx) -{ - UCHAR Remainder; - UCHAR PadLenInBytes; - UCHAR *pAppend=0; - unsigned int i; - - Remainder = (UCHAR)((pCtx->LenInBitCount[0] >> 3) & 0x3f); - - PadLenInBytes = (Remainder < 56) ? (56-Remainder) : (120-Remainder); - - pAppend = (UCHAR *)pCtx->Input + Remainder; - - // padding bits without crossing block(64-byte based) boundary - if (Remainder < 56) - { - *pAppend = 0x80; - PadLenInBytes --; - - NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, PadLenInBytes); - - // add data-length field, from low to high - for (i=0; i<4; i++) - { - pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[0] >> (i << 3)) & 0xff); - pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[1] >> (i << 3)) & 0xff); - } - - byteReverse(pCtx->Input, 16); - MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); - } // end of if - - // padding bits with crossing block(64-byte based) boundary - else - { - // the first block === - *pAppend = 0x80; - PadLenInBytes --; - - NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, (64-Remainder-1)); - PadLenInBytes -= (64 - Remainder - 1); - - byteReverse(pCtx->Input, 16); - MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); - - - // the second block === - NdisZeroMemory((UCHAR *)pCtx->Input, PadLenInBytes); - - // add data-length field - for (i=0; i<4; i++) - { - pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[0] >> (i << 3)) & 0xff); - pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[1] >> (i << 3)) & 0xff); - } - - byteReverse(pCtx->Input, 16); - MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); - } // end of else - - - NdisMoveMemory((UCHAR *)Digest, (UINT32 *)pCtx->Buf, 16); // output - byteReverse((UCHAR *)Digest, 4); - NdisZeroMemory(pCtx, sizeof(pCtx)); // memory free -} - - -/* - * Function Description: - * The central algorithm of MD5, consists of four rounds and sixteen - * steps per round - * - * Arguments: - * Buf Buffers of four states (output: 16 bytes) - * Mes Input data (input: 64 bytes) - * - * Return Value: - * None - * - * Note: - * Called by MD5Update or MD5Final - */ -VOID MD5Transform(UINT32 Buf[4], UINT32 Mes[16]) -{ - UINT32 Reg[4], Temp; - unsigned int i; - - static UCHAR LShiftVal[16] = - { - 7, 12, 17, 22, - 5, 9 , 14, 20, - 4, 11, 16, 23, - 6, 10, 15, 21, - }; - - - // [equal to 4294967296*abs(sin(index))] - static UINT32 MD5Table[64] = - { - 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, - 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, - 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, - 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, - - 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, - 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, - 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, - 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, - - 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, - 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, - 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, - 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, - - 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, - 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, - 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, - 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 - }; - - - for (i=0; i<4; i++) - Reg[i]=Buf[i]; - - - // 64 steps in MD5 algorithm - for (i=0; i<16; i++) - { - MD5Step(MD5_F1, Reg[0], Reg[1], Reg[2], Reg[3], Mes[i], - MD5Table[i], LShiftVal[i & 0x3]); - - // one-word right shift - Temp = Reg[3]; - Reg[3] = Reg[2]; - Reg[2] = Reg[1]; - Reg[1] = Reg[0]; - Reg[0] = Temp; - } - for (i=16; i<32; i++) - { - MD5Step(MD5_F2, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(5*(i & 0xf)+1) & 0xf], - MD5Table[i], LShiftVal[(0x1 << 2)+(i & 0x3)]); - - // one-word right shift - Temp = Reg[3]; - Reg[3] = Reg[2]; - Reg[2] = Reg[1]; - Reg[1] = Reg[0]; - Reg[0] = Temp; - } - for (i=32; i<48; i++) - { - MD5Step(MD5_F3, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(3*(i & 0xf)+5) & 0xf], - MD5Table[i], LShiftVal[(0x1 << 3)+(i & 0x3)]); - - // one-word right shift - Temp = Reg[3]; - Reg[3] = Reg[2]; - Reg[2] = Reg[1]; - Reg[1] = Reg[0]; - Reg[0] = Temp; - } - for (i=48; i<64; i++) - { - MD5Step(MD5_F4, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(7*(i & 0xf)) & 0xf], - MD5Table[i], LShiftVal[(0x3 << 2)+(i & 0x3)]); - - // one-word right shift - Temp = Reg[3]; - Reg[3] = Reg[2]; - Reg[2] = Reg[1]; - Reg[1] = Reg[0]; - Reg[0] = Temp; - } - - - // (temporary)output - for (i=0; i<4; i++) - Buf[i] += Reg[i]; - -} - - - -/* ========================= SHA-1 implementation ========================== */ -// four base functions for SHA-1 -#define SHA1_F1(b, c, d) (((b) & (c)) | ((~b) & (d))) -#define SHA1_F2(b, c, d) ((b) ^ (c) ^ (d)) -#define SHA1_F3(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) - - -#define SHA1Step(f, a, b, c, d, e, w, k) \ - ( e += ( f(b, c, d) + w + k + CYCLIC_LEFT_SHIFT(a, 5)) & 0xffffffff, \ - b = CYCLIC_LEFT_SHIFT(b, 30) ) - -//Initiate SHA-1 Context satisfied in RFC 3174 -VOID SHAInit(SHA_CTX *pCtx) -{ - pCtx->Buf[0]=0x67452301; - pCtx->Buf[1]=0xefcdab89; - pCtx->Buf[2]=0x98badcfe; - pCtx->Buf[3]=0x10325476; - pCtx->Buf[4]=0xc3d2e1f0; - - pCtx->LenInBitCount[0]=0; - pCtx->LenInBitCount[1]=0; -} - -/* - * Function Description: - * Update SHA-1 Context, allow of an arrary of octets as the next - * portion of the message - * - * Arguments: - * pCtx Pointer to SHA-1 context - * pData Pointer to input data - * LenInBytes The length of input data (unit: byte) - * - * Return Value: - * error indicate more than pow(2,64) bits of data - * - * Note: - * Called after SHAInit or SHAUpdate(itself) - */ -UCHAR SHAUpdate(SHA_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes) -{ - UINT32 TfTimes; - UINT32 temp1,temp2; - unsigned int i; - UCHAR err=1; - - temp1 = pCtx->LenInBitCount[0]; - temp2 = pCtx->LenInBitCount[1]; - - pCtx->LenInBitCount[0] = (UINT32) (pCtx->LenInBitCount[0] + (LenInBytes << 3)); - if (pCtx->LenInBitCount[0] < temp1) - pCtx->LenInBitCount[1]++; //carry in - - - pCtx->LenInBitCount[1] = (UINT32) (pCtx->LenInBitCount[1] +(LenInBytes >> 29)); - if (pCtx->LenInBitCount[1] < temp2) - return (err); //check total length of original data - - - // mod 64 bytes - temp1 = (temp1 >> 3) & 0x3f; - - // process lacks of 64-byte data - if (temp1) - { - UCHAR *pAds = (UCHAR *) pCtx->Input + temp1; - - if ((temp1+LenInBytes) < 64) - { - NdisMoveMemory(pAds, (UCHAR *)pData, LenInBytes); - return (0); - } - - NdisMoveMemory(pAds, (UCHAR *)pData, 64-temp1); - byteReverse((UCHAR *)pCtx->Input, 16); - - NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16); - SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); - - pData += 64-temp1; - LenInBytes -= 64-temp1; - } // end of if (temp1) - - - TfTimes = (LenInBytes >> 6); - - for (i=TfTimes; i>0; i--) - { - NdisMoveMemory(pCtx->Input, (UCHAR *)pData, 64); - byteReverse((UCHAR *)pCtx->Input, 16); - - NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16); - SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); - pData += 64; - LenInBytes -= 64; - } // end of for - - // buffering lacks of 64-byte data - if(LenInBytes) - NdisMoveMemory(pCtx->Input, (UCHAR *)pData, LenInBytes); - - return (0); - -} - -// Append padding bits and length of original message in the tail -// The message digest has to be completed in the end -VOID SHAFinal(SHA_CTX *pCtx, UCHAR Digest[20]) -{ - UCHAR Remainder; - UCHAR PadLenInBytes; - UCHAR *pAppend=0; - unsigned int i; - - Remainder = (UCHAR)((pCtx->LenInBitCount[0] >> 3) & 0x3f); - - pAppend = (UCHAR *)pCtx->Input + Remainder; - - PadLenInBytes = (Remainder < 56) ? (56-Remainder) : (120-Remainder); - - // padding bits without crossing block(64-byte based) boundary - if (Remainder < 56) - { - *pAppend = 0x80; - PadLenInBytes --; - - NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, PadLenInBytes); - - // add data-length field, from high to low - for (i=0; i<4; i++) - { - pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[1] >> ((3-i) << 3)) & 0xff); - pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[0] >> ((3-i) << 3)) & 0xff); - } - - byteReverse((UCHAR *)pCtx->Input, 16); - NdisZeroMemory((UCHAR *)pCtx->Input + 64, 14); - SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); - } // end of if - - // padding bits with crossing block(64-byte based) boundary - else - { - // the first block === - *pAppend = 0x80; - PadLenInBytes --; - - NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, (64-Remainder-1)); - PadLenInBytes -= (64 - Remainder - 1); - - byteReverse((UCHAR *)pCtx->Input, 16); - NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16); - SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); - - - // the second block === - NdisZeroMemory((UCHAR *)pCtx->Input, PadLenInBytes); - - // add data-length field - for (i=0; i<4; i++) - { - pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[1] >> ((3-i) << 3)) & 0xff); - pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[0] >> ((3-i) << 3)) & 0xff); - } - - byteReverse((UCHAR *)pCtx->Input, 16); - NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16); - SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); - } // end of else - - - //Output, bytereverse - for (i=0; i<20; i++) - { - Digest [i] = (UCHAR)(pCtx->Buf[i>>2] >> 8*(3-(i & 0x3))); - } - - NdisZeroMemory(pCtx, sizeof(pCtx)); // memory free -} - - -// The central algorithm of SHA-1, consists of four rounds and -// twenty steps per round -VOID SHATransform(UINT32 Buf[5], UINT32 Mes[20]) -{ - UINT32 Reg[5],Temp; - unsigned int i; - UINT32 W[80]; - - static UINT32 SHA1Table[4] = { 0x5a827999, 0x6ed9eba1, - 0x8f1bbcdc, 0xca62c1d6 }; - - Reg[0]=Buf[0]; - Reg[1]=Buf[1]; - Reg[2]=Buf[2]; - Reg[3]=Buf[3]; - Reg[4]=Buf[4]; - - //the first octet of a word is stored in the 0th element, bytereverse - for(i = 0; i < 16; i++) - { - W[i] = (Mes[i] >> 24) & 0xff; - W[i] |= (Mes[i] >> 8 ) & 0xff00; - W[i] |= (Mes[i] << 8 ) & 0xff0000; - W[i] |= (Mes[i] << 24) & 0xff000000; - } - - - for (i = 0; i < 64; i++) - W[16+i] = CYCLIC_LEFT_SHIFT(W[i] ^ W[2+i] ^ W[8+i] ^ W[13+i], 1); - - - // 80 steps in SHA-1 algorithm - for (i=0; i<80; i++) - { - if (i<20) - SHA1Step(SHA1_F1, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4], - W[i], SHA1Table[0]); - - else if (i>=20 && i<40) - SHA1Step(SHA1_F2, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4], - W[i], SHA1Table[1]); - - else if (i>=40 && i<60) - SHA1Step(SHA1_F3, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4], - W[i], SHA1Table[2]); - - else - SHA1Step(SHA1_F2, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4], - W[i], SHA1Table[3]); - - - // one-word right shift - Temp = Reg[4]; - Reg[4] = Reg[3]; - Reg[3] = Reg[2]; - Reg[2] = Reg[1]; - Reg[1] = Reg[0]; - Reg[0] = Temp; - - } // end of for-loop - - - // (temporary)output - for (i=0; i<5; i++) - Buf[i] += Reg[i]; - -} - - -/* ========================= AES En/Decryption ========================== */ - -/* forward S-box */ -static uint32 FSb[256] = -{ - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, - 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, - 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, - 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, - 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, - 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, - 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, - 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, - 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, - 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, - 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, - 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, - 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, - 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, - 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, - 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, - 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, - 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, - 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, - 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, - 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, - 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, - 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, - 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, - 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 -}; - -/* forward table */ -#define FT \ -\ - V(C6,63,63,A5), V(F8,7C,7C,84), V(EE,77,77,99), V(F6,7B,7B,8D), \ - V(FF,F2,F2,0D), V(D6,6B,6B,BD), V(DE,6F,6F,B1), V(91,C5,C5,54), \ - V(60,30,30,50), V(02,01,01,03), V(CE,67,67,A9), V(56,2B,2B,7D), \ - V(E7,FE,FE,19), V(B5,D7,D7,62), V(4D,AB,AB,E6), V(EC,76,76,9A), \ - V(8F,CA,CA,45), V(1F,82,82,9D), V(89,C9,C9,40), V(FA,7D,7D,87), \ - V(EF,FA,FA,15), V(B2,59,59,EB), V(8E,47,47,C9), V(FB,F0,F0,0B), \ - V(41,AD,AD,EC), V(B3,D4,D4,67), V(5F,A2,A2,FD), V(45,AF,AF,EA), \ - V(23,9C,9C,BF), V(53,A4,A4,F7), V(E4,72,72,96), V(9B,C0,C0,5B), \ - V(75,B7,B7,C2), V(E1,FD,FD,1C), V(3D,93,93,AE), V(4C,26,26,6A), \ - V(6C,36,36,5A), V(7E,3F,3F,41), V(F5,F7,F7,02), V(83,CC,CC,4F), \ - V(68,34,34,5C), V(51,A5,A5,F4), V(D1,E5,E5,34), V(F9,F1,F1,08), \ - V(E2,71,71,93), V(AB,D8,D8,73), V(62,31,31,53), V(2A,15,15,3F), \ - V(08,04,04,0C), V(95,C7,C7,52), V(46,23,23,65), V(9D,C3,C3,5E), \ - V(30,18,18,28), V(37,96,96,A1), V(0A,05,05,0F), V(2F,9A,9A,B5), \ - V(0E,07,07,09), V(24,12,12,36), V(1B,80,80,9B), V(DF,E2,E2,3D), \ - V(CD,EB,EB,26), V(4E,27,27,69), V(7F,B2,B2,CD), V(EA,75,75,9F), \ - V(12,09,09,1B), V(1D,83,83,9E), V(58,2C,2C,74), V(34,1A,1A,2E), \ - V(36,1B,1B,2D), V(DC,6E,6E,B2), V(B4,5A,5A,EE), V(5B,A0,A0,FB), \ - V(A4,52,52,F6), V(76,3B,3B,4D), V(B7,D6,D6,61), V(7D,B3,B3,CE), \ - V(52,29,29,7B), V(DD,E3,E3,3E), V(5E,2F,2F,71), V(13,84,84,97), \ - V(A6,53,53,F5), V(B9,D1,D1,68), V(00,00,00,00), V(C1,ED,ED,2C), \ - V(40,20,20,60), V(E3,FC,FC,1F), V(79,B1,B1,C8), V(B6,5B,5B,ED), \ - V(D4,6A,6A,BE), V(8D,CB,CB,46), V(67,BE,BE,D9), V(72,39,39,4B), \ - V(94,4A,4A,DE), V(98,4C,4C,D4), V(B0,58,58,E8), V(85,CF,CF,4A), \ - V(BB,D0,D0,6B), V(C5,EF,EF,2A), V(4F,AA,AA,E5), V(ED,FB,FB,16), \ - V(86,43,43,C5), V(9A,4D,4D,D7), V(66,33,33,55), V(11,85,85,94), \ - V(8A,45,45,CF), V(E9,F9,F9,10), V(04,02,02,06), V(FE,7F,7F,81), \ - V(A0,50,50,F0), V(78,3C,3C,44), V(25,9F,9F,BA), V(4B,A8,A8,E3), \ - V(A2,51,51,F3), V(5D,A3,A3,FE), V(80,40,40,C0), V(05,8F,8F,8A), \ - V(3F,92,92,AD), V(21,9D,9D,BC), V(70,38,38,48), V(F1,F5,F5,04), \ - V(63,BC,BC,DF), V(77,B6,B6,C1), V(AF,DA,DA,75), V(42,21,21,63), \ - V(20,10,10,30), V(E5,FF,FF,1A), V(FD,F3,F3,0E), V(BF,D2,D2,6D), \ - V(81,CD,CD,4C), V(18,0C,0C,14), V(26,13,13,35), V(C3,EC,EC,2F), \ - V(BE,5F,5F,E1), V(35,97,97,A2), V(88,44,44,CC), V(2E,17,17,39), \ - V(93,C4,C4,57), V(55,A7,A7,F2), V(FC,7E,7E,82), V(7A,3D,3D,47), \ - V(C8,64,64,AC), V(BA,5D,5D,E7), V(32,19,19,2B), V(E6,73,73,95), \ - V(C0,60,60,A0), V(19,81,81,98), V(9E,4F,4F,D1), V(A3,DC,DC,7F), \ - V(44,22,22,66), V(54,2A,2A,7E), V(3B,90,90,AB), V(0B,88,88,83), \ - V(8C,46,46,CA), V(C7,EE,EE,29), V(6B,B8,B8,D3), V(28,14,14,3C), \ - V(A7,DE,DE,79), V(BC,5E,5E,E2), V(16,0B,0B,1D), V(AD,DB,DB,76), \ - V(DB,E0,E0,3B), V(64,32,32,56), V(74,3A,3A,4E), V(14,0A,0A,1E), \ - V(92,49,49,DB), V(0C,06,06,0A), V(48,24,24,6C), V(B8,5C,5C,E4), \ - V(9F,C2,C2,5D), V(BD,D3,D3,6E), V(43,AC,AC,EF), V(C4,62,62,A6), \ - V(39,91,91,A8), V(31,95,95,A4), V(D3,E4,E4,37), V(F2,79,79,8B), \ - V(D5,E7,E7,32), V(8B,C8,C8,43), V(6E,37,37,59), V(DA,6D,6D,B7), \ - V(01,8D,8D,8C), V(B1,D5,D5,64), V(9C,4E,4E,D2), V(49,A9,A9,E0), \ - V(D8,6C,6C,B4), V(AC,56,56,FA), V(F3,F4,F4,07), V(CF,EA,EA,25), \ - V(CA,65,65,AF), V(F4,7A,7A,8E), V(47,AE,AE,E9), V(10,08,08,18), \ - V(6F,BA,BA,D5), V(F0,78,78,88), V(4A,25,25,6F), V(5C,2E,2E,72), \ - V(38,1C,1C,24), V(57,A6,A6,F1), V(73,B4,B4,C7), V(97,C6,C6,51), \ - V(CB,E8,E8,23), V(A1,DD,DD,7C), V(E8,74,74,9C), V(3E,1F,1F,21), \ - V(96,4B,4B,DD), V(61,BD,BD,DC), V(0D,8B,8B,86), V(0F,8A,8A,85), \ - V(E0,70,70,90), V(7C,3E,3E,42), V(71,B5,B5,C4), V(CC,66,66,AA), \ - V(90,48,48,D8), V(06,03,03,05), V(F7,F6,F6,01), V(1C,0E,0E,12), \ - V(C2,61,61,A3), V(6A,35,35,5F), V(AE,57,57,F9), V(69,B9,B9,D0), \ - V(17,86,86,91), V(99,C1,C1,58), V(3A,1D,1D,27), V(27,9E,9E,B9), \ - V(D9,E1,E1,38), V(EB,F8,F8,13), V(2B,98,98,B3), V(22,11,11,33), \ - V(D2,69,69,BB), V(A9,D9,D9,70), V(07,8E,8E,89), V(33,94,94,A7), \ - V(2D,9B,9B,B6), V(3C,1E,1E,22), V(15,87,87,92), V(C9,E9,E9,20), \ - V(87,CE,CE,49), V(AA,55,55,FF), V(50,28,28,78), V(A5,DF,DF,7A), \ - V(03,8C,8C,8F), V(59,A1,A1,F8), V(09,89,89,80), V(1A,0D,0D,17), \ - V(65,BF,BF,DA), V(D7,E6,E6,31), V(84,42,42,C6), V(D0,68,68,B8), \ - V(82,41,41,C3), V(29,99,99,B0), V(5A,2D,2D,77), V(1E,0F,0F,11), \ - V(7B,B0,B0,CB), V(A8,54,54,FC), V(6D,BB,BB,D6), V(2C,16,16,3A) - -#define V(a,b,c,d) 0x##a##b##c##d -static uint32 FT0[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##d##a##b##c -static uint32 FT1[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##c##d##a##b -static uint32 FT2[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##b##c##d##a -static uint32 FT3[256] = { FT }; -#undef V - -#undef FT - -/* reverse S-box */ - -static uint32 RSb[256] = -{ - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, - 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, - 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, - 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, - 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, - 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, - 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, - 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, - 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, - 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, - 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, - 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, - 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, - 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, - 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, - 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, - 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, - 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, - 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, - 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, - 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, - 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, - 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, - 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, - 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, - 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D -}; - -/* reverse table */ - -#define RT \ -\ - V(51,F4,A7,50), V(7E,41,65,53), V(1A,17,A4,C3), V(3A,27,5E,96), \ - V(3B,AB,6B,CB), V(1F,9D,45,F1), V(AC,FA,58,AB), V(4B,E3,03,93), \ - V(20,30,FA,55), V(AD,76,6D,F6), V(88,CC,76,91), V(F5,02,4C,25), \ - V(4F,E5,D7,FC), V(C5,2A,CB,D7), V(26,35,44,80), V(B5,62,A3,8F), \ - V(DE,B1,5A,49), V(25,BA,1B,67), V(45,EA,0E,98), V(5D,FE,C0,E1), \ - V(C3,2F,75,02), V(81,4C,F0,12), V(8D,46,97,A3), V(6B,D3,F9,C6), \ - V(03,8F,5F,E7), V(15,92,9C,95), V(BF,6D,7A,EB), V(95,52,59,DA), \ - V(D4,BE,83,2D), V(58,74,21,D3), V(49,E0,69,29), V(8E,C9,C8,44), \ - V(75,C2,89,6A), V(F4,8E,79,78), V(99,58,3E,6B), V(27,B9,71,DD), \ - V(BE,E1,4F,B6), V(F0,88,AD,17), V(C9,20,AC,66), V(7D,CE,3A,B4), \ - V(63,DF,4A,18), V(E5,1A,31,82), V(97,51,33,60), V(62,53,7F,45), \ - V(B1,64,77,E0), V(BB,6B,AE,84), V(FE,81,A0,1C), V(F9,08,2B,94), \ - V(70,48,68,58), V(8F,45,FD,19), V(94,DE,6C,87), V(52,7B,F8,B7), \ - V(AB,73,D3,23), V(72,4B,02,E2), V(E3,1F,8F,57), V(66,55,AB,2A), \ - V(B2,EB,28,07), V(2F,B5,C2,03), V(86,C5,7B,9A), V(D3,37,08,A5), \ - V(30,28,87,F2), V(23,BF,A5,B2), V(02,03,6A,BA), V(ED,16,82,5C), \ - V(8A,CF,1C,2B), V(A7,79,B4,92), V(F3,07,F2,F0), V(4E,69,E2,A1), \ - V(65,DA,F4,CD), V(06,05,BE,D5), V(D1,34,62,1F), V(C4,A6,FE,8A), \ - V(34,2E,53,9D), V(A2,F3,55,A0), V(05,8A,E1,32), V(A4,F6,EB,75), \ - V(0B,83,EC,39), V(40,60,EF,AA), V(5E,71,9F,06), V(BD,6E,10,51), \ - V(3E,21,8A,F9), V(96,DD,06,3D), V(DD,3E,05,AE), V(4D,E6,BD,46), \ - V(91,54,8D,B5), V(71,C4,5D,05), V(04,06,D4,6F), V(60,50,15,FF), \ - V(19,98,FB,24), V(D6,BD,E9,97), V(89,40,43,CC), V(67,D9,9E,77), \ - V(B0,E8,42,BD), V(07,89,8B,88), V(E7,19,5B,38), V(79,C8,EE,DB), \ - V(A1,7C,0A,47), V(7C,42,0F,E9), V(F8,84,1E,C9), V(00,00,00,00), \ - V(09,80,86,83), V(32,2B,ED,48), V(1E,11,70,AC), V(6C,5A,72,4E), \ - V(FD,0E,FF,FB), V(0F,85,38,56), V(3D,AE,D5,1E), V(36,2D,39,27), \ - V(0A,0F,D9,64), V(68,5C,A6,21), V(9B,5B,54,D1), V(24,36,2E,3A), \ - V(0C,0A,67,B1), V(93,57,E7,0F), V(B4,EE,96,D2), V(1B,9B,91,9E), \ - V(80,C0,C5,4F), V(61,DC,20,A2), V(5A,77,4B,69), V(1C,12,1A,16), \ - V(E2,93,BA,0A), V(C0,A0,2A,E5), V(3C,22,E0,43), V(12,1B,17,1D), \ - V(0E,09,0D,0B), V(F2,8B,C7,AD), V(2D,B6,A8,B9), V(14,1E,A9,C8), \ - V(57,F1,19,85), V(AF,75,07,4C), V(EE,99,DD,BB), V(A3,7F,60,FD), \ - V(F7,01,26,9F), V(5C,72,F5,BC), V(44,66,3B,C5), V(5B,FB,7E,34), \ - V(8B,43,29,76), V(CB,23,C6,DC), V(B6,ED,FC,68), V(B8,E4,F1,63), \ - V(D7,31,DC,CA), V(42,63,85,10), V(13,97,22,40), V(84,C6,11,20), \ - V(85,4A,24,7D), V(D2,BB,3D,F8), V(AE,F9,32,11), V(C7,29,A1,6D), \ - V(1D,9E,2F,4B), V(DC,B2,30,F3), V(0D,86,52,EC), V(77,C1,E3,D0), \ - V(2B,B3,16,6C), V(A9,70,B9,99), V(11,94,48,FA), V(47,E9,64,22), \ - V(A8,FC,8C,C4), V(A0,F0,3F,1A), V(56,7D,2C,D8), V(22,33,90,EF), \ - V(87,49,4E,C7), V(D9,38,D1,C1), V(8C,CA,A2,FE), V(98,D4,0B,36), \ - V(A6,F5,81,CF), V(A5,7A,DE,28), V(DA,B7,8E,26), V(3F,AD,BF,A4), \ - V(2C,3A,9D,E4), V(50,78,92,0D), V(6A,5F,CC,9B), V(54,7E,46,62), \ - V(F6,8D,13,C2), V(90,D8,B8,E8), V(2E,39,F7,5E), V(82,C3,AF,F5), \ - V(9F,5D,80,BE), V(69,D0,93,7C), V(6F,D5,2D,A9), V(CF,25,12,B3), \ - V(C8,AC,99,3B), V(10,18,7D,A7), V(E8,9C,63,6E), V(DB,3B,BB,7B), \ - V(CD,26,78,09), V(6E,59,18,F4), V(EC,9A,B7,01), V(83,4F,9A,A8), \ - V(E6,95,6E,65), V(AA,FF,E6,7E), V(21,BC,CF,08), V(EF,15,E8,E6), \ - V(BA,E7,9B,D9), V(4A,6F,36,CE), V(EA,9F,09,D4), V(29,B0,7C,D6), \ - V(31,A4,B2,AF), V(2A,3F,23,31), V(C6,A5,94,30), V(35,A2,66,C0), \ - V(74,4E,BC,37), V(FC,82,CA,A6), V(E0,90,D0,B0), V(33,A7,D8,15), \ - V(F1,04,98,4A), V(41,EC,DA,F7), V(7F,CD,50,0E), V(17,91,F6,2F), \ - V(76,4D,D6,8D), V(43,EF,B0,4D), V(CC,AA,4D,54), V(E4,96,04,DF), \ - V(9E,D1,B5,E3), V(4C,6A,88,1B), V(C1,2C,1F,B8), V(46,65,51,7F), \ - V(9D,5E,EA,04), V(01,8C,35,5D), V(FA,87,74,73), V(FB,0B,41,2E), \ - V(B3,67,1D,5A), V(92,DB,D2,52), V(E9,10,56,33), V(6D,D6,47,13), \ - V(9A,D7,61,8C), V(37,A1,0C,7A), V(59,F8,14,8E), V(EB,13,3C,89), \ - V(CE,A9,27,EE), V(B7,61,C9,35), V(E1,1C,E5,ED), V(7A,47,B1,3C), \ - V(9C,D2,DF,59), V(55,F2,73,3F), V(18,14,CE,79), V(73,C7,37,BF), \ - V(53,F7,CD,EA), V(5F,FD,AA,5B), V(DF,3D,6F,14), V(78,44,DB,86), \ - V(CA,AF,F3,81), V(B9,68,C4,3E), V(38,24,34,2C), V(C2,A3,40,5F), \ - V(16,1D,C3,72), V(BC,E2,25,0C), V(28,3C,49,8B), V(FF,0D,95,41), \ - V(39,A8,01,71), V(08,0C,B3,DE), V(D8,B4,E4,9C), V(64,56,C1,90), \ - V(7B,CB,84,61), V(D5,32,B6,70), V(48,6C,5C,74), V(D0,B8,57,42) - -#define V(a,b,c,d) 0x##a##b##c##d -static uint32 RT0[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##d##a##b##c -static uint32 RT1[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##c##d##a##b -static uint32 RT2[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##b##c##d##a -static uint32 RT3[256] = { RT }; -#undef V - -#undef RT - -/* round constants */ - -static uint32 RCON[10] = -{ - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, - 0x1B000000, 0x36000000 -}; - -/* key schedule tables */ - -static int KT_init = 1; - -static uint32 KT0[256]; -static uint32 KT1[256]; -static uint32 KT2[256]; -static uint32 KT3[256]; - -/* platform-independant 32-bit integer manipulation macros */ - -#define GET_UINT32(n,b,i) \ -{ \ - (n) = ( (uint32) (b)[(i) ] << 24 ) \ - | ( (uint32) (b)[(i) + 1] << 16 ) \ - | ( (uint32) (b)[(i) + 2] << 8 ) \ - | ( (uint32) (b)[(i) + 3] ); \ -} - -#define PUT_UINT32(n,b,i) \ -{ \ - (b)[(i) ] = (uint8) ( (n) >> 24 ); \ - (b)[(i) + 1] = (uint8) ( (n) >> 16 ); \ - (b)[(i) + 2] = (uint8) ( (n) >> 8 ); \ - (b)[(i) + 3] = (uint8) ( (n) ); \ -} - -/* AES key scheduling routine */ - -int rtmp_aes_set_key( aes_context *ctx, uint8 *key, int nbits ) -{ - int i; - uint32 *RK, *SK; - - switch( nbits ) - { - case 128: ctx->nr = 10; break; - case 192: ctx->nr = 12; break; - case 256: ctx->nr = 14; break; - default : return( 1 ); - } - - RK = ctx->erk; - - for( i = 0; i < (nbits >> 5); i++ ) - { - GET_UINT32( RK[i], key, i * 4 ); - } - - /* setup encryption round keys */ - - switch( nbits ) - { - case 128: - - for( i = 0; i < 10; i++, RK += 4 ) - { - RK[4] = RK[0] ^ RCON[i] ^ - ( FSb[ (uint8) ( RK[3] >> 16 ) ] << 24 ) ^ - ( FSb[ (uint8) ( RK[3] >> 8 ) ] << 16 ) ^ - ( FSb[ (uint8) ( RK[3] ) ] << 8 ) ^ - ( FSb[ (uint8) ( RK[3] >> 24 ) ] ); - - RK[5] = RK[1] ^ RK[4]; - RK[6] = RK[2] ^ RK[5]; - RK[7] = RK[3] ^ RK[6]; - } - break; - - case 192: - - for( i = 0; i < 8; i++, RK += 6 ) - { - RK[6] = RK[0] ^ RCON[i] ^ - ( FSb[ (uint8) ( RK[5] >> 16 ) ] << 24 ) ^ - ( FSb[ (uint8) ( RK[5] >> 8 ) ] << 16 ) ^ - ( FSb[ (uint8) ( RK[5] ) ] << 8 ) ^ - ( FSb[ (uint8) ( RK[5] >> 24 ) ] ); - - RK[7] = RK[1] ^ RK[6]; - RK[8] = RK[2] ^ RK[7]; - RK[9] = RK[3] ^ RK[8]; - RK[10] = RK[4] ^ RK[9]; - RK[11] = RK[5] ^ RK[10]; - } - break; - - case 256: - - for( i = 0; i < 7; i++, RK += 8 ) - { - RK[8] = RK[0] ^ RCON[i] ^ - ( FSb[ (uint8) ( RK[7] >> 16 ) ] << 24 ) ^ - ( FSb[ (uint8) ( RK[7] >> 8 ) ] << 16 ) ^ - ( FSb[ (uint8) ( RK[7] ) ] << 8 ) ^ - ( FSb[ (uint8) ( RK[7] >> 24 ) ] ); - - RK[9] = RK[1] ^ RK[8]; - RK[10] = RK[2] ^ RK[9]; - RK[11] = RK[3] ^ RK[10]; - - RK[12] = RK[4] ^ - ( FSb[ (uint8) ( RK[11] >> 24 ) ] << 24 ) ^ - ( FSb[ (uint8) ( RK[11] >> 16 ) ] << 16 ) ^ - ( FSb[ (uint8) ( RK[11] >> 8 ) ] << 8 ) ^ - ( FSb[ (uint8) ( RK[11] ) ] ); - - RK[13] = RK[5] ^ RK[12]; - RK[14] = RK[6] ^ RK[13]; - RK[15] = RK[7] ^ RK[14]; - } - break; - } - - /* setup decryption round keys */ - - if( KT_init ) - { - for( i = 0; i < 256; i++ ) - { - KT0[i] = RT0[ FSb[i] ]; - KT1[i] = RT1[ FSb[i] ]; - KT2[i] = RT2[ FSb[i] ]; - KT3[i] = RT3[ FSb[i] ]; - } - - KT_init = 0; - } - - SK = ctx->drk; - - *SK++ = *RK++; - *SK++ = *RK++; - *SK++ = *RK++; - *SK++ = *RK++; - - for( i = 1; i < ctx->nr; i++ ) - { - RK -= 8; - - *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ - KT1[ (uint8) ( *RK >> 16 ) ] ^ - KT2[ (uint8) ( *RK >> 8 ) ] ^ - KT3[ (uint8) ( *RK ) ]; RK++; - - *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ - KT1[ (uint8) ( *RK >> 16 ) ] ^ - KT2[ (uint8) ( *RK >> 8 ) ] ^ - KT3[ (uint8) ( *RK ) ]; RK++; - - *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ - KT1[ (uint8) ( *RK >> 16 ) ] ^ - KT2[ (uint8) ( *RK >> 8 ) ] ^ - KT3[ (uint8) ( *RK ) ]; RK++; - - *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ - KT1[ (uint8) ( *RK >> 16 ) ] ^ - KT2[ (uint8) ( *RK >> 8 ) ] ^ - KT3[ (uint8) ( *RK ) ]; RK++; - } - - RK -= 8; - - *SK++ = *RK++; - *SK++ = *RK++; - *SK++ = *RK++; - *SK++ = *RK++; - - return( 0 ); -} - -/* AES 128-bit block encryption routine */ - -void rtmp_aes_encrypt(aes_context *ctx, uint8 input[16], uint8 output[16] ) -{ - uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; - - RK = ctx->erk; - GET_UINT32( X0, input, 0 ); X0 ^= RK[0]; - GET_UINT32( X1, input, 4 ); X1 ^= RK[1]; - GET_UINT32( X2, input, 8 ); X2 ^= RK[2]; - GET_UINT32( X3, input, 12 ); X3 ^= RK[3]; - -#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - RK += 4; \ - \ - X0 = RK[0] ^ FT0[ (uint8) ( Y0 >> 24 ) ] ^ \ - FT1[ (uint8) ( Y1 >> 16 ) ] ^ \ - FT2[ (uint8) ( Y2 >> 8 ) ] ^ \ - FT3[ (uint8) ( Y3 ) ]; \ - \ - X1 = RK[1] ^ FT0[ (uint8) ( Y1 >> 24 ) ] ^ \ - FT1[ (uint8) ( Y2 >> 16 ) ] ^ \ - FT2[ (uint8) ( Y3 >> 8 ) ] ^ \ - FT3[ (uint8) ( Y0 ) ]; \ - \ - X2 = RK[2] ^ FT0[ (uint8) ( Y2 >> 24 ) ] ^ \ - FT1[ (uint8) ( Y3 >> 16 ) ] ^ \ - FT2[ (uint8) ( Y0 >> 8 ) ] ^ \ - FT3[ (uint8) ( Y1 ) ]; \ - \ - X3 = RK[3] ^ FT0[ (uint8) ( Y3 >> 24 ) ] ^ \ - FT1[ (uint8) ( Y0 >> 16 ) ] ^ \ - FT2[ (uint8) ( Y1 >> 8 ) ] ^ \ - FT3[ (uint8) ( Y2 ) ]; \ -} - - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */ - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */ - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */ - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */ - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ - - if( ctx->nr > 10 ) - { - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */ - } - - if( ctx->nr > 12 ) - { - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */ - } - - /* last round */ - - RK += 4; - - X0 = RK[0] ^ ( FSb[ (uint8) ( Y0 >> 24 ) ] << 24 ) ^ - ( FSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^ - ( FSb[ (uint8) ( Y2 >> 8 ) ] << 8 ) ^ - ( FSb[ (uint8) ( Y3 ) ] ); - - X1 = RK[1] ^ ( FSb[ (uint8) ( Y1 >> 24 ) ] << 24 ) ^ - ( FSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^ - ( FSb[ (uint8) ( Y3 >> 8 ) ] << 8 ) ^ - ( FSb[ (uint8) ( Y0 ) ] ); - - X2 = RK[2] ^ ( FSb[ (uint8) ( Y2 >> 24 ) ] << 24 ) ^ - ( FSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^ - ( FSb[ (uint8) ( Y0 >> 8 ) ] << 8 ) ^ - ( FSb[ (uint8) ( Y1 ) ] ); - - X3 = RK[3] ^ ( FSb[ (uint8) ( Y3 >> 24 ) ] << 24 ) ^ - ( FSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^ - ( FSb[ (uint8) ( Y1 >> 8 ) ] << 8 ) ^ - ( FSb[ (uint8) ( Y2 ) ] ); - - PUT_UINT32( X0, output, 0 ); - PUT_UINT32( X1, output, 4 ); - PUT_UINT32( X2, output, 8 ); - PUT_UINT32( X3, output, 12 ); -} - -/* AES 128-bit block decryption routine */ - -void rtmp_aes_decrypt( aes_context *ctx, uint8 input[16], uint8 output[16] ) -{ - uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; - - RK = ctx->drk; - - GET_UINT32( X0, input, 0 ); X0 ^= RK[0]; - GET_UINT32( X1, input, 4 ); X1 ^= RK[1]; - GET_UINT32( X2, input, 8 ); X2 ^= RK[2]; - GET_UINT32( X3, input, 12 ); X3 ^= RK[3]; - -#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - RK += 4; \ - \ - X0 = RK[0] ^ RT0[ (uint8) ( Y0 >> 24 ) ] ^ \ - RT1[ (uint8) ( Y3 >> 16 ) ] ^ \ - RT2[ (uint8) ( Y2 >> 8 ) ] ^ \ - RT3[ (uint8) ( Y1 ) ]; \ - \ - X1 = RK[1] ^ RT0[ (uint8) ( Y1 >> 24 ) ] ^ \ - RT1[ (uint8) ( Y0 >> 16 ) ] ^ \ - RT2[ (uint8) ( Y3 >> 8 ) ] ^ \ - RT3[ (uint8) ( Y2 ) ]; \ - \ - X2 = RK[2] ^ RT0[ (uint8) ( Y2 >> 24 ) ] ^ \ - RT1[ (uint8) ( Y1 >> 16 ) ] ^ \ - RT2[ (uint8) ( Y0 >> 8 ) ] ^ \ - RT3[ (uint8) ( Y3 ) ]; \ - \ - X3 = RK[3] ^ RT0[ (uint8) ( Y3 >> 24 ) ] ^ \ - RT1[ (uint8) ( Y2 >> 16 ) ] ^ \ - RT2[ (uint8) ( Y1 >> 8 ) ] ^ \ - RT3[ (uint8) ( Y0 ) ]; \ -} - - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */ - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */ - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */ - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */ - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */ - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */ - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */ - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */ - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ - - if( ctx->nr > 10 ) - { - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */ - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */ - } - - if( ctx->nr > 12 ) - { - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */ - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */ - } - - /* last round */ - - RK += 4; - - X0 = RK[0] ^ ( RSb[ (uint8) ( Y0 >> 24 ) ] << 24 ) ^ - ( RSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^ - ( RSb[ (uint8) ( Y2 >> 8 ) ] << 8 ) ^ - ( RSb[ (uint8) ( Y1 ) ] ); - - X1 = RK[1] ^ ( RSb[ (uint8) ( Y1 >> 24 ) ] << 24 ) ^ - ( RSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^ - ( RSb[ (uint8) ( Y3 >> 8 ) ] << 8 ) ^ - ( RSb[ (uint8) ( Y2 ) ] ); - - X2 = RK[2] ^ ( RSb[ (uint8) ( Y2 >> 24 ) ] << 24 ) ^ - ( RSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^ - ( RSb[ (uint8) ( Y0 >> 8 ) ] << 8 ) ^ - ( RSb[ (uint8) ( Y3 ) ] ); - - X3 = RK[3] ^ ( RSb[ (uint8) ( Y3 >> 24 ) ] << 24 ) ^ - ( RSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^ - ( RSb[ (uint8) ( Y1 >> 8 ) ] << 8 ) ^ - ( RSb[ (uint8) ( Y0 ) ] ); - - PUT_UINT32( X0, output, 0 ); - PUT_UINT32( X1, output, 4 ); - PUT_UINT32( X2, output, 8 ); - PUT_UINT32( X3, output, 12 ); -} - -/* - ======================================================================== - - Routine Description: - SHA1 function - - Arguments: - - Return Value: - - Note: - - ======================================================================== -*/ -VOID HMAC_SHA1( - IN UCHAR *text, - IN UINT text_len, - IN UCHAR *key, - IN UINT key_len, - IN UCHAR *digest) -{ - SHA_CTX context; - UCHAR k_ipad[65]; /* inner padding - key XORd with ipad */ - UCHAR k_opad[65]; /* outer padding - key XORd with opad */ - INT i; - - // if key is longer than 64 bytes reset it to key=SHA1(key) - if (key_len > 64) - { - SHA_CTX tctx; - SHAInit(&tctx); - SHAUpdate(&tctx, key, key_len); - SHAFinal(&tctx, key); - key_len = 20; - } - NdisZeroMemory(k_ipad, sizeof(k_ipad)); - NdisZeroMemory(k_opad, sizeof(k_opad)); - NdisMoveMemory(k_ipad, key, key_len); - NdisMoveMemory(k_opad, key, key_len); - - // XOR key with ipad and opad values - for (i = 0; i < 64; i++) - { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - - // perform inner SHA1 - SHAInit(&context); /* init context for 1st pass */ - SHAUpdate(&context, k_ipad, 64); /* start with inner pad */ - SHAUpdate(&context, text, text_len); /* then text of datagram */ - SHAFinal(&context, digest); /* finish up 1st pass */ - - //perform outer SHA1 - SHAInit(&context); /* init context for 2nd pass */ - SHAUpdate(&context, k_opad, 64); /* start with outer pad */ - SHAUpdate(&context, digest, 20); /* then results of 1st hash */ - SHAFinal(&context, digest); /* finish up 2nd pass */ - -} - -/* -* F(P, S, c, i) = U1 xor U2 xor ... Uc -* U1 = PRF(P, S || Int(i)) -* U2 = PRF(P, U1) -* Uc = PRF(P, Uc-1) -*/ - -void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output) -{ - unsigned char digest[36], digest1[SHA_DIGEST_LEN]; - int i, j; - - /* U1 = PRF(P, S || int(i)) */ - memcpy(digest, ssid, ssidlength); - digest[ssidlength] = (unsigned char)((count>>24) & 0xff); - digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff); - digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff); - digest[ssidlength+3] = (unsigned char)(count & 0xff); - HMAC_SHA1(digest, ssidlength+4, (unsigned char*) password, (int) strlen(password), digest1); // for WPA update - - /* output = U1 */ - memcpy(output, digest1, SHA_DIGEST_LEN); - - for (i = 1; i < iterations; i++) - { - /* Un = PRF(P, Un-1) */ - HMAC_SHA1(digest1, SHA_DIGEST_LEN, (unsigned char*) password, (int) strlen(password), digest); // for WPA update - memcpy(digest1, digest, SHA_DIGEST_LEN); - - /* output = output xor Un */ - for (j = 0; j < SHA_DIGEST_LEN; j++) - { - output[j] ^= digest[j]; - } - } -} -/* -* password - ascii string up to 63 characters in length -* ssid - octet string up to 32 octets -* ssidlength - length of ssid in octets -* output must be 40 octets in length and outputs 256 bits of key -*/ -int PasswordHash(char *password, unsigned char *ssid, int ssidlength, unsigned char *output) -{ - if ((strlen(password) > 63) || (ssidlength > 32)) - return 0; - - F(password, ssid, ssidlength, 4096, 1, output); - F(password, ssid, ssidlength, 4096, 2, &output[SHA_DIGEST_LEN]); - return 1; -} - - diff --git a/drivers/staging/rt2860/common/mlme.c b/drivers/staging/rt2860/common/mlme.c index 61a2a4eb7140db39d2fa8d01f8735e27f75bb8fc..9fc34a8f218022dc651a984d1c323bc1836e484c 100644 --- a/drivers/staging/rt2860/common/mlme.c +++ b/drivers/staging/rt2860/common/mlme.c @@ -39,413 +39,309 @@ #include "../rt_config.h" #include -UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96}; - -UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01}; -UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac}; -UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; -UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; -UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04}; -UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43}; -UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c}; -UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04}; -UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c}; - -UCHAR RateSwitchTable[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x11, 0x00, 0, 0, 0, // Initial used item after association - 0x00, 0x00, 0, 40, 101, - 0x01, 0x00, 1, 40, 50, - 0x02, 0x00, 2, 35, 45, - 0x03, 0x00, 3, 20, 45, - 0x04, 0x21, 0, 30, 50, - 0x05, 0x21, 1, 20, 50, - 0x06, 0x21, 2, 20, 50, - 0x07, 0x21, 3, 15, 50, - 0x08, 0x21, 4, 15, 30, - 0x09, 0x21, 5, 10, 25, - 0x0a, 0x21, 6, 8, 25, - 0x0b, 0x21, 7, 8, 25, - 0x0c, 0x20, 12, 15, 30, - 0x0d, 0x20, 13, 8, 20, - 0x0e, 0x20, 14, 8, 20, - 0x0f, 0x20, 15, 8, 25, - 0x10, 0x22, 15, 8, 25, - 0x11, 0x00, 0, 0, 0, - 0x12, 0x00, 0, 0, 0, - 0x13, 0x00, 0, 0, 0, - 0x14, 0x00, 0, 0, 0, - 0x15, 0x00, 0, 0, 0, - 0x16, 0x00, 0, 0, 0, - 0x17, 0x00, 0, 0, 0, - 0x18, 0x00, 0, 0, 0, - 0x19, 0x00, 0, 0, 0, - 0x1a, 0x00, 0, 0, 0, - 0x1b, 0x00, 0, 0, 0, - 0x1c, 0x00, 0, 0, 0, - 0x1d, 0x00, 0, 0, 0, - 0x1e, 0x00, 0, 0, 0, - 0x1f, 0x00, 0, 0, 0, +u8 CISCO_OUI[] = { 0x00, 0x40, 0x96 }; + +u8 WPA_OUI[] = { 0x00, 0x50, 0xf2, 0x01 }; +u8 RSN_OUI[] = { 0x00, 0x0f, 0xac }; +u8 WME_INFO_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01 }; +u8 WME_PARM_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01 }; +u8 Ccx2QosInfo[] = { 0x00, 0x40, 0x96, 0x04 }; +u8 RALINK_OUI[] = { 0x00, 0x0c, 0x43 }; +u8 BROADCOM_OUI[] = { 0x00, 0x90, 0x4c }; +u8 WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 }; +u8 PRE_N_HT_OUI[] = { 0x00, 0x90, 0x4c }; + +u8 RateSwitchTable[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x11, 0x00, 0, 0, 0, /* Initial used item after association */ + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 35, 45, + 0x03, 0x00, 3, 20, 45, + 0x04, 0x21, 0, 30, 50, + 0x05, 0x21, 1, 20, 50, + 0x06, 0x21, 2, 20, 50, + 0x07, 0x21, 3, 15, 50, + 0x08, 0x21, 4, 15, 30, + 0x09, 0x21, 5, 10, 25, + 0x0a, 0x21, 6, 8, 25, + 0x0b, 0x21, 7, 8, 25, + 0x0c, 0x20, 12, 15, 30, + 0x0d, 0x20, 13, 8, 20, + 0x0e, 0x20, 14, 8, 20, + 0x0f, 0x20, 15, 8, 25, + 0x10, 0x22, 15, 8, 25, + 0x11, 0x00, 0, 0, 0, + 0x12, 0x00, 0, 0, 0, + 0x13, 0x00, 0, 0, 0, + 0x14, 0x00, 0, 0, 0, + 0x15, 0x00, 0, 0, 0, + 0x16, 0x00, 0, 0, 0, + 0x17, 0x00, 0, 0, 0, + 0x18, 0x00, 0, 0, 0, + 0x19, 0x00, 0, 0, 0, + 0x1a, 0x00, 0, 0, 0, + 0x1b, 0x00, 0, 0, 0, + 0x1c, 0x00, 0, 0, 0, + 0x1d, 0x00, 0, 0, 0, + 0x1e, 0x00, 0, 0, 0, + 0x1f, 0x00, 0, 0, 0, }; -UCHAR RateSwitchTable11B[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x04, 0x03, 0, 0, 0, // Initial used item after association - 0x00, 0x00, 0, 40, 101, - 0x01, 0x00, 1, 40, 50, - 0x02, 0x00, 2, 35, 45, - 0x03, 0x00, 3, 20, 45, +u8 RateSwitchTable11B[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x04, 0x03, 0, 0, 0, /* Initial used item after association */ + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 35, 45, + 0x03, 0x00, 3, 20, 45, }; -UCHAR RateSwitchTable11BG[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0a, 0x00, 0, 0, 0, // Initial used item after association - 0x00, 0x00, 0, 40, 101, - 0x01, 0x00, 1, 40, 50, - 0x02, 0x00, 2, 35, 45, - 0x03, 0x00, 3, 20, 45, - 0x04, 0x10, 2, 20, 35, - 0x05, 0x10, 3, 16, 35, - 0x06, 0x10, 4, 10, 25, - 0x07, 0x10, 5, 16, 25, - 0x08, 0x10, 6, 10, 25, - 0x09, 0x10, 7, 10, 13, +u8 RateSwitchTable11BG[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x0a, 0x00, 0, 0, 0, /* Initial used item after association */ + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 35, 45, + 0x03, 0x00, 3, 20, 45, + 0x04, 0x10, 2, 20, 35, + 0x05, 0x10, 3, 16, 35, + 0x06, 0x10, 4, 10, 25, + 0x07, 0x10, 5, 16, 25, + 0x08, 0x10, 6, 10, 25, + 0x09, 0x10, 7, 10, 13, }; -UCHAR RateSwitchTable11G[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x08, 0x00, 0, 0, 0, // Initial used item after association - 0x00, 0x10, 0, 20, 101, - 0x01, 0x10, 1, 20, 35, - 0x02, 0x10, 2, 20, 35, - 0x03, 0x10, 3, 16, 35, - 0x04, 0x10, 4, 10, 25, - 0x05, 0x10, 5, 16, 25, - 0x06, 0x10, 6, 10, 25, - 0x07, 0x10, 7, 10, 13, +u8 RateSwitchTable11G[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x08, 0x00, 0, 0, 0, /* Initial used item after association */ + 0x00, 0x10, 0, 20, 101, + 0x01, 0x10, 1, 20, 35, + 0x02, 0x10, 2, 20, 35, + 0x03, 0x10, 3, 16, 35, + 0x04, 0x10, 4, 10, 25, + 0x05, 0x10, 5, 16, 25, + 0x06, 0x10, 6, 10, 25, + 0x07, 0x10, 7, 10, 13, }; -UCHAR RateSwitchTable11N1S[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x09, 0x00, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30, 101, - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 15, 50, - 0x04, 0x21, 4, 15, 30, - 0x05, 0x21, 5, 10, 25, - 0x06, 0x21, 6, 8, 14, - 0x07, 0x21, 7, 8, 14, - 0x08, 0x23, 7, 8, 14, +u8 RateSwitchTable11N1S[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x0c, 0x0a, 0, 0, 0, /* Initial used item after association */ + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 25, 45, + 0x03, 0x21, 0, 20, 35, + 0x04, 0x21, 1, 20, 35, + 0x05, 0x21, 2, 20, 35, + 0x06, 0x21, 3, 15, 35, + 0x07, 0x21, 4, 15, 30, + 0x08, 0x21, 5, 10, 25, + 0x09, 0x21, 6, 8, 14, + 0x0a, 0x21, 7, 8, 14, + 0x0b, 0x23, 7, 8, 14, }; -UCHAR RateSwitchTable11N2S[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0a, 0x00, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30, 101, - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 15, 50, - 0x04, 0x21, 4, 15, 30, - 0x05, 0x20, 12, 15, 30, - 0x06, 0x20, 13, 8, 20, - 0x07, 0x20, 14, 8, 20, - 0x08, 0x20, 15, 8, 25, - 0x09, 0x22, 15, 8, 25, +u8 RateSwitchTable11N2S[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x0e, 0x0c, 0, 0, 0, /* Initial used item after association */ + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 25, 45, + 0x03, 0x21, 0, 20, 35, + 0x04, 0x21, 1, 20, 35, + 0x05, 0x21, 2, 20, 35, + 0x06, 0x21, 3, 15, 35, + 0x07, 0x21, 4, 15, 30, + 0x08, 0x20, 11, 15, 30, + 0x09, 0x20, 12, 15, 30, + 0x0a, 0x20, 13, 8, 20, + 0x0b, 0x20, 14, 8, 20, + 0x0c, 0x20, 15, 8, 25, + 0x0d, 0x22, 15, 8, 15, }; -UCHAR RateSwitchTable11N3S[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0a, 0x00, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30, 101, - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 15, 50, - 0x04, 0x21, 4, 15, 30, - 0x05, 0x20, 12, 15, 30, - 0x06, 0x20, 13, 8, 20, - 0x07, 0x20, 14, 8, 20, - 0x08, 0x20, 15, 8, 25, - 0x09, 0x22, 15, 8, 25, +u8 RateSwitchTable11N3S[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x0b, 0x00, 0, 0, 0, /* 0x0a, 0x00, 0, 0, 0, // Initial used item after association */ + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x20, 11, 15, 30, /* Required by System-Alan @ 20080812 */ + 0x06, 0x20, 12, 15, 30, /* 0x05, 0x20, 12, 15, 30, */ + 0x07, 0x20, 13, 8, 20, /* 0x06, 0x20, 13, 8, 20, */ + 0x08, 0x20, 14, 8, 20, /* 0x07, 0x20, 14, 8, 20, */ + 0x09, 0x20, 15, 8, 25, /* 0x08, 0x20, 15, 8, 25, */ + 0x0a, 0x22, 15, 8, 25, /* 0x09, 0x22, 15, 8, 25, */ }; -UCHAR RateSwitchTable11N2SForABand[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0b, 0x09, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30, 101, - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 15, 50, - 0x04, 0x21, 4, 15, 30, - 0x05, 0x21, 5, 15, 30, - 0x06, 0x20, 12, 15, 30, - 0x07, 0x20, 13, 8, 20, - 0x08, 0x20, 14, 8, 20, - 0x09, 0x20, 15, 8, 25, - 0x0a, 0x22, 15, 8, 25, +u8 RateSwitchTable11N2SForABand[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */ + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x20, 12, 15, 30, + 0x07, 0x20, 13, 8, 20, + 0x08, 0x20, 14, 8, 20, + 0x09, 0x20, 15, 8, 25, + 0x0a, 0x22, 15, 8, 25, }; -UCHAR RateSwitchTable11N3SForABand[] = { // 3*3 -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0b, 0x09, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30, 101, - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 15, 50, - 0x04, 0x21, 4, 15, 30, - 0x05, 0x21, 5, 15, 30, - 0x06, 0x20, 12, 15, 30, - 0x07, 0x20, 13, 8, 20, - 0x08, 0x20, 14, 8, 20, - 0x09, 0x20, 15, 8, 25, - 0x0a, 0x22, 15, 8, 25, +u8 RateSwitchTable11N3SForABand[] = { /* 3*3 */ +/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */ + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x20, 12, 15, 30, + 0x07, 0x20, 13, 8, 20, + 0x08, 0x20, 14, 8, 20, + 0x09, 0x20, 15, 8, 25, + 0x0a, 0x22, 15, 8, 25, }; -UCHAR RateSwitchTable11BGN1S[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0d, 0x00, 0, 0, 0, // Initial used item after association - 0x00, 0x00, 0, 40, 101, - 0x01, 0x00, 1, 40, 50, - 0x02, 0x00, 2, 35, 45, - 0x03, 0x00, 3, 20, 45, - 0x04, 0x21, 0, 30,101, //50 - 0x05, 0x21, 1, 20, 50, - 0x06, 0x21, 2, 20, 50, - 0x07, 0x21, 3, 15, 50, - 0x08, 0x21, 4, 15, 30, - 0x09, 0x21, 5, 10, 25, - 0x0a, 0x21, 6, 8, 14, - 0x0b, 0x21, 7, 8, 14, - 0x0c, 0x23, 7, 8, 14, +u8 RateSwitchTable11BGN1S[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x0c, 0x0a, 0, 0, 0, /* Initial used item after association */ + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 25, 45, + 0x03, 0x21, 0, 20, 35, + 0x04, 0x21, 1, 20, 35, + 0x05, 0x21, 2, 20, 35, + 0x06, 0x21, 3, 15, 35, + 0x07, 0x21, 4, 15, 30, + 0x08, 0x21, 5, 10, 25, + 0x09, 0x21, 6, 8, 14, + 0x0a, 0x21, 7, 8, 14, + 0x0b, 0x23, 7, 8, 14, }; -UCHAR RateSwitchTable11BGN2S[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0a, 0x00, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30,101, //50 - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 15, 50, - 0x04, 0x21, 4, 15, 30, - 0x05, 0x20, 12, 15, 30, - 0x06, 0x20, 13, 8, 20, - 0x07, 0x20, 14, 8, 20, - 0x08, 0x20, 15, 8, 25, - 0x09, 0x22, 15, 8, 25, +u8 RateSwitchTable11BGN2S[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x0e, 0x0c, 0, 0, 0, /* Initial used item after association */ + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 25, 45, + 0x03, 0x21, 0, 20, 35, + 0x04, 0x21, 1, 20, 35, + 0x05, 0x21, 2, 20, 35, + 0x06, 0x21, 3, 15, 35, + 0x07, 0x21, 4, 15, 30, + 0x08, 0x20, 11, 15, 30, + 0x09, 0x20, 12, 15, 30, + 0x0a, 0x20, 13, 8, 20, + 0x0b, 0x20, 14, 8, 20, + 0x0c, 0x20, 15, 8, 25, + 0x0d, 0x22, 15, 8, 15, }; -UCHAR RateSwitchTable11BGN3S[] = { // 3*3 -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0a, 0x00, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30,101, //50 - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 20, 50, - 0x04, 0x21, 4, 15, 50, - 0x05, 0x20, 20, 15, 30, - 0x06, 0x20, 21, 8, 20, - 0x07, 0x20, 22, 8, 20, - 0x08, 0x20, 23, 8, 25, - 0x09, 0x22, 23, 8, 25, +u8 RateSwitchTable11BGN3S[] = { /* 3*3 */ +/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x0a, 0x00, 0, 0, 0, /* Initial used item after association */ + 0x00, 0x21, 0, 30, 101, /*50 */ + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 20, 50, + 0x04, 0x21, 4, 15, 50, + 0x05, 0x20, 20, 15, 30, + 0x06, 0x20, 21, 8, 20, + 0x07, 0x20, 22, 8, 20, + 0x08, 0x20, 23, 8, 25, + 0x09, 0x22, 23, 8, 25, }; -UCHAR RateSwitchTable11BGN2SForABand[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0b, 0x09, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30,101, //50 - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 15, 50, - 0x04, 0x21, 4, 15, 30, - 0x05, 0x21, 5, 15, 30, - 0x06, 0x20, 12, 15, 30, - 0x07, 0x20, 13, 8, 20, - 0x08, 0x20, 14, 8, 20, - 0x09, 0x20, 15, 8, 25, - 0x0a, 0x22, 15, 8, 25, +u8 RateSwitchTable11BGN2SForABand[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */ + 0x00, 0x21, 0, 30, 101, /*50 */ + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x20, 12, 15, 30, + 0x07, 0x20, 13, 8, 20, + 0x08, 0x20, 14, 8, 20, + 0x09, 0x20, 15, 8, 25, + 0x0a, 0x22, 15, 8, 25, }; -UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3 -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0c, 0x09, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30,101, //50 - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 15, 50, - 0x04, 0x21, 4, 15, 30, - 0x05, 0x21, 5, 15, 30, - 0x06, 0x21, 12, 15, 30, - 0x07, 0x20, 20, 15, 30, - 0x08, 0x20, 21, 8, 20, - 0x09, 0x20, 22, 8, 20, - 0x0a, 0x20, 23, 8, 25, - 0x0b, 0x22, 23, 8, 25, +u8 RateSwitchTable11BGN3SForABand[] = { /* 3*3 */ +/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + 0x0c, 0x09, 0, 0, 0, /* Initial used item after association */ + 0x00, 0x21, 0, 30, 101, /*50 */ + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x21, 12, 15, 30, + 0x07, 0x20, 20, 15, 30, + 0x08, 0x20, 21, 8, 20, + 0x09, 0x20, 22, 8, 20, + 0x0a, 0x20, 23, 8, 25, + 0x0b, 0x22, 23, 8, 25, }; -PUCHAR ReasonString[] = { - /* 0 */ "Reserved", - /* 1 */ "Unspecified Reason", - /* 2 */ "Previous Auth no longer valid", - /* 3 */ "STA is leaving / has left", - /* 4 */ "DIS-ASSOC due to inactivity", - /* 5 */ "AP unable to hanle all associations", - /* 6 */ "class 2 error", - /* 7 */ "class 3 error", - /* 8 */ "STA is leaving / has left", - /* 9 */ "require auth before assoc/re-assoc", - /* 10 */ "Reserved", - /* 11 */ "Reserved", - /* 12 */ "Reserved", - /* 13 */ "invalid IE", - /* 14 */ "MIC error", - /* 15 */ "4-way handshake timeout", - /* 16 */ "2-way (group key) handshake timeout", - /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon", - /* 18 */ +extern u8 OfdmRateToRxwiMCS[]; +/* since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate. */ +/* otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate */ +unsigned long BasicRateMask[12] = + { 0xfffff001 /* 1-Mbps */ , 0xfffff003 /* 2 Mbps */ , 0xfffff007 /* 5.5 */ , +0xfffff00f /* 11 */ , + 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , + 0xfffff0ff /* 18 */ , + 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , + 0xffffffff /* 54 */ }; -extern UCHAR OfdmRateToRxwiMCS[]; -// since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate. -// otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate -ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */, - 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */, - 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */}; - -UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00}; -UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -// e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than -// this value, then it's quaranteed capable of operating in 36 mbps TX rate in -// clean environment. -// TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100 -CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 }; - -UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100}; -USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200}; - -UCHAR SsidIe = IE_SSID; -UCHAR SupRateIe = IE_SUPP_RATES; -UCHAR ExtRateIe = IE_EXT_SUPP_RATES; -UCHAR HtCapIe = IE_HT_CAP; -UCHAR AddHtInfoIe = IE_ADD_HT; -UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET; -UCHAR ErpIe = IE_ERP; -UCHAR DsIe = IE_DS_PARM; -UCHAR TimIe = IE_TIM; -UCHAR WpaIe = IE_WPA; -UCHAR Wpa2Ie = IE_WPA2; -UCHAR IbssIe = IE_IBSS_PARM; -UCHAR Ccx2Ie = IE_CCX_V2; - -extern UCHAR WPA_OUI[]; - -UCHAR SES_OUI[] = {0x00, 0x90, 0x4c}; - -UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - -// Reset the RFIC setting to new series -RTMP_RF_REGS RF2850RegTable[] = { -// ch R1 R2 R3(TX0~4=0) R4 - {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b}, - {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f}, - {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b}, - {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f}, - {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b}, - {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f}, - {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b}, - {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f}, - {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b}, - {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f}, - {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b}, - {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f}, - {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b}, - {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193}, - - // 802.11 UNI / HyperLan 2 - {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3}, - {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193}, - {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183}, - {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3}, - {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b}, - {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b}, - {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193}, - {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3}, - {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b}, - {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183}, - {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193}, - {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5. - - // 802.11 HyperLan 2 - {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783}, - - // 2008.04.30 modified - // The system team has AN to improve the EVM value - // for channel 102 to 108 for the RT2850/RT2750 dual band solution. - {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793}, - {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3}, - {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193}, - - {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183}, - {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b}, - {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3}, - {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193}, - {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183}, - {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193}, - {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927 - {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3}, - {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b}, - {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193}, - {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b}, - {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183}, - - // 802.11 UNII - {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7}, - {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187}, - {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f}, - {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f}, - {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7}, - {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187}, - {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197}, - - // Japan - {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b}, - {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13}, - {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b}, - {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23}, - {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13}, - {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b}, - {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23}, - - // still lack of MMAC(Japan) ch 34,38,42,46 +u8 BROADCAST_ADDR[MAC_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +u8 ZERO_MAC_ADDR[MAC_ADDR_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +/* e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than */ +/* this value, then it's quaranteed capable of operating in 36 mbps TX rate in */ +/* clean environment. */ +/* TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100 */ +char RssiSafeLevelForTxRate[] = + { -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 }; + +u8 RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100 }; +u16 RateIdTo500Kbps[] = + { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200 }; + +u8 SsidIe = IE_SSID; +u8 SupRateIe = IE_SUPP_RATES; +u8 ExtRateIe = IE_EXT_SUPP_RATES; +u8 HtCapIe = IE_HT_CAP; +u8 AddHtInfoIe = IE_ADD_HT; +u8 NewExtChanIe = IE_SECONDARY_CH_OFFSET; +u8 ErpIe = IE_ERP; +u8 DsIe = IE_DS_PARM; +u8 TimIe = IE_TIM; +u8 WpaIe = IE_WPA; +u8 Wpa2Ie = IE_WPA2; +u8 IbssIe = IE_IBSS_PARM; + +extern u8 WPA_OUI[]; + +u8 SES_OUI[] = { 0x00, 0x90, 0x4c }; + +u8 ZeroSsid[32] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; -UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS)); - -FREQUENCY_ITEM FreqItems3020[] = -{ - /**************************************************/ - // ISM : 2.4 to 2.483 GHz // - /**************************************************/ - // 11g - /**************************************************/ - //-CH---N-------R---K----------- - {1, 241, 2, 2}, - {2, 241, 2, 7}, - {3, 242, 2, 2}, - {4, 242, 2, 7}, - {5, 243, 2, 2}, - {6, 243, 2, 7}, - {7, 244, 2, 2}, - {8, 244, 2, 7}, - {9, 245, 2, 2}, - {10, 245, 2, 7}, - {11, 246, 2, 2}, - {12, 246, 2, 7}, - {13, 247, 2, 2}, - {14, 248, 2, 4}, -}; -UCHAR NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM)); /* ========================================================================== @@ -460,17 +356,15 @@ UCHAR NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM)); ========================================================================== */ -NDIS_STATUS MlmeInit( - IN PRTMP_ADAPTER pAd) +int MlmeInit(struct rt_rtmp_adapter *pAd) { - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + int Status = NDIS_STATUS_SUCCESS; DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n")); - do - { + do { Status = MlmeQueueInit(&pAd->Mlme.Queue); - if(Status != NDIS_STATUS_SUCCESS) + if (Status != NDIS_STATUS_SUCCESS) break; pAd->Mlme.bRunning = FALSE; @@ -479,40 +373,65 @@ NDIS_STATUS MlmeInit( { BssTableInit(&pAd->ScanTab); - // init STA state machines - AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc); - AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc); - AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc); - SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc); - WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc); - AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc); - - // Since we are using switch/case to implement it, the init is different from the above - // state machine init + /* init STA state machines */ + AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, + pAd->Mlme.AssocFunc); + AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, + pAd->Mlme.AuthFunc); + AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, + pAd->Mlme.AuthRspFunc); + SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, + pAd->Mlme.SyncFunc); + + /* Since we are using switch/case to implement it, the init is different from the above */ + /* state machine init */ MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL); } - ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc); + WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine, + pAd->Mlme.WpaFunc); + + ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, + pAd->Mlme.ActFunc); - // Init mlme periodic timer - RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE); + /* Init mlme periodic timer */ + RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, + GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE); - // Set mlme periodic timer + /* Set mlme periodic timer */ RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV); - // software-based RX Antenna diversity - RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE); + /* software-based RX Antenna diversity */ + RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, + GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, + FALSE); + + { +#ifdef RTMP_PCI_SUPPORT + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { + /* only PCIe cards need these two timers */ + RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, + GET_TIMER_FUNCTION + (PsPollWakeExec), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, + GET_TIMER_FUNCTION(RadioOnExec), + pAd, FALSE); + } +#endif /* RTMP_PCI_SUPPORT // */ -#ifdef RT2860 - { - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) - { - // only PCIe cards need these two timers - RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE); - RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE); - } + RTMPInitTimer(pAd, &pAd->Mlme.LinkDownTimer, + GET_TIMER_FUNCTION(LinkDownExec), pAd, + FALSE); + +#ifdef RTMP_MAC_USB + RTMPInitTimer(pAd, &pAd->Mlme.AutoWakeupTimer, + GET_TIMER_FUNCTION + (RtmpUsbStaAsicForceWakeupTimeout), pAd, + FALSE); + pAd->Mlme.AutoWakeupTimerRunning = FALSE; +#endif /* RTMP_MAC_USB // */ } -#endif + } while (FALSE); DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n")); @@ -534,93 +453,102 @@ NDIS_STATUS MlmeInit( ========================================================================== */ -VOID MlmeHandler( - IN PRTMP_ADAPTER pAd) +void MlmeHandler(struct rt_rtmp_adapter *pAd) { - MLME_QUEUE_ELEM *Elem = NULL; + struct rt_mlme_queue_elem *Elem = NULL; - // Only accept MLME and Frame from peer side, no other (control/data) frame should - // get into this state machine + /* Only accept MLME and Frame from peer side, no other (control/data) frame should */ + /* get into this state machine */ NdisAcquireSpinLock(&pAd->Mlme.TaskLock); - if(pAd->Mlme.bRunning) - { + if (pAd->Mlme.bRunning) { NdisReleaseSpinLock(&pAd->Mlme.TaskLock); return; - } - else - { + } else { pAd->Mlme.bRunning = TRUE; } NdisReleaseSpinLock(&pAd->Mlme.TaskLock); - while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) - { + while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) - { - DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num)); + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { + DBGPRINT(RT_DEBUG_TRACE, + ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", + pAd->Mlme.Queue.Num)); break; } - - //From message type, determine which state machine I should drive - if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) - { -#ifdef RT2870 - if (Elem->MsgType == MT2_RESET_CONF) - { - DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n")); + /*From message type, determine which state machine I should drive */ + if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) { +#ifdef RTMP_MAC_USB + if (Elem->MsgType == MT2_RESET_CONF) { + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("reset MLME state machine!\n")); MlmeRestartStateMachine(pAd); Elem->Occupied = FALSE; Elem->MsgLen = 0; continue; } -#endif // RT2870 // - - // if dequeue success - switch (Elem->Machine) - { - // STA state machines - case ASSOC_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem); - break; - case AUTH_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem); - break; - case AUTH_RSP_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem); - break; - case SYNC_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem); - break; - case MLME_CNTL_STATE_MACHINE: - MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem); - break; - case WPA_PSK_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem); - break; - case AIRONET_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem); - break; - case ACTION_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem); - break; - +#endif /* RTMP_MAC_USB // */ + + /* if dequeue success */ + switch (Elem->Machine) { + /* STA state machines */ + case ASSOC_STATE_MACHINE: + StateMachinePerformAction(pAd, + &pAd->Mlme. + AssocMachine, Elem); + break; + case AUTH_STATE_MACHINE: + StateMachinePerformAction(pAd, + &pAd->Mlme. + AuthMachine, Elem); + break; + case AUTH_RSP_STATE_MACHINE: + StateMachinePerformAction(pAd, + &pAd->Mlme. + AuthRspMachine, Elem); + break; + case SYNC_STATE_MACHINE: + StateMachinePerformAction(pAd, + &pAd->Mlme. + SyncMachine, Elem); + break; + case MLME_CNTL_STATE_MACHINE: + MlmeCntlMachinePerformAction(pAd, + &pAd->Mlme. + CntlMachine, Elem); + break; + case WPA_PSK_STATE_MACHINE: + StateMachinePerformAction(pAd, + &pAd->Mlme. + WpaPskMachine, Elem); + break; + case ACTION_STATE_MACHINE: + StateMachinePerformAction(pAd, + &pAd->Mlme.ActMachine, + Elem); + break; + case WPA_STATE_MACHINE: + StateMachinePerformAction(pAd, + &pAd->Mlme.WpaMachine, + Elem); + break; - default: - DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine)); - break; - } // end of switch + default: + DBGPRINT(RT_DEBUG_TRACE, + ("ERROR: Illegal machine %ld in MlmeHandler()\n", + Elem->Machine)); + break; + } /* end of switch */ - // free MLME element + /* free MLME element */ Elem->Occupied = FALSE; Elem->MsgLen = 0; - } - else { + } else { DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n")); } } @@ -643,73 +571,67 @@ VOID MlmeHandler( ========================================================================== */ -VOID MlmeHalt( - IN PRTMP_ADAPTER pAd) +void MlmeHalt(struct rt_rtmp_adapter *pAd) { - BOOLEAN Cancelled; -#ifdef RT3070 - UINT32 TxPinCfg = 0x00050F0F; -#endif // RT3070 // + BOOLEAN Cancelled; DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n")); - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) - { - // disable BEACON generation and other BEACON related hardware timers + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { + /* disable BEACON generation and other BEACON related hardware timers */ AsicDisableSync(pAd); } { - // Cancel pending timers - RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); -#ifdef RT2860 - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) - { - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); + /* Cancel pending timers */ + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + +#ifdef RTMP_MAC_PCI + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) + && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); } -#endif - } +#endif /* RTMP_MAC_PCI // */ + + RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled); - RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); - RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled); +#ifdef RTMP_MAC_USB + RTMPCancelTimer(&pAd->Mlme.AutoWakeupTimer, &Cancelled); +#endif /* RTMP_MAC_USB // */ + } + RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); + RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled); + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { + struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) - { - // Set LED + /* Set LED */ RTMPSetLED(pAd, LED_HALT); - RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it. -#ifdef RT2870 - { - LED_CFG_STRUC LedCfg; - RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word); - LedCfg.field.LedPolar = 0; - LedCfg.field.RLedMode = 0; - LedCfg.field.GLedMode = 0; - LedCfg.field.YLedMode = 0; - RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word); - } -#endif // RT2870 // -#ifdef RT3070 - // - // Turn off LNA_PE - // - if (IS_RT3070(pAd) || IS_RT3071(pAd)) + RTMPSetSignalLED(pAd, -100); /* Force signal strength Led to be turned off, firmware is not done it. */ +#ifdef RTMP_MAC_USB { - TxPinCfg &= 0xFFFFF0F0; - RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg); + LED_CFG_STRUC LedCfg; + RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word); + LedCfg.field.LedPolar = 0; + LedCfg.field.RLedMode = 0; + LedCfg.field.GLedMode = 0; + LedCfg.field.YLedMode = 0; + RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word); } -#endif // RT3070 // +#endif /* RTMP_MAC_USB // */ + + if (pChipOps->AsicHaltAction) + pChipOps->AsicHaltAction(pAd); } - RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled + RTMPusecDelay(5000); /* 5 msec to gurantee Ant Diversity timer canceled */ MlmeQueueDestroy(&pAd->Mlme.Queue); NdisFreeSpinLock(&pAd->Mlme.TaskLock); @@ -717,11 +639,11 @@ VOID MlmeHalt( DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n")); } -VOID MlmeResetRalinkCounters( - IN PRTMP_ADAPTER pAd) +void MlmeResetRalinkCounters(struct rt_rtmp_adapter *pAd) { - pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt; - // clear all OneSecxxx counters. + pAd->RalinkCounters.LastOneSecRxOkDataCnt = + pAd->RalinkCounters.OneSecRxOkDataCnt; + /* clear all OneSecxxx counters. */ pAd->RalinkCounters.OneSecBeaconSentCnt = 0; pAd->RalinkCounters.OneSecFalseCCACnt = 0; pAd->RalinkCounters.OneSecRxFcsErrCnt = 0; @@ -730,8 +652,10 @@ VOID MlmeResetRalinkCounters( pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0; pAd->RalinkCounters.OneSecTxRetryOkCount = 0; pAd->RalinkCounters.OneSecRxOkDataCnt = 0; + pAd->RalinkCounters.OneSecReceivedByteCount = 0; + pAd->RalinkCounters.OneSecTransmittedByteCount = 0; - // TODO: for debug only. to be removed + /* TODO: for debug only. to be removed */ pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0; pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0; pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0; @@ -748,9 +672,6 @@ VOID MlmeResetRalinkCounters( return; } -unsigned long rx_AMSDU; -unsigned long rx_Total; - /* ========================================================================== Description: @@ -767,229 +688,188 @@ unsigned long rx_Total; ========================================================================== */ -#define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec -VOID MlmePeriodicExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) +#define ADHOC_BEACON_LOST_TIME (8*OS_HZ) /* 8 sec */ +void MlmePeriodicExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) { - ULONG TxTotalCnt; - PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; - -#ifdef RT2860 - //Baron 2008/07/10 - //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus)); - //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0. - //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1. - if(pAd->StaCfg.WepStatus<2) - { - pAd->StaCfg.WpaSupplicantUP = 0; - } - else - { - pAd->StaCfg.WpaSupplicantUP = 1; - } - - { - // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second. - // Move code to here, because following code will return when radio is off - if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) && - (pAd->StaCfg.bHardwareRadio == TRUE) && - (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) - { - UINT32 data = 0; - - // Read GPIO pin2 as Hardware controlled radio state - RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data); - if (data & 0x04) - { + unsigned long TxTotalCnt; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; + +#ifdef RTMP_MAC_PCI + { + /* If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second. */ + /* Move code to here, because following code will return when radio is off */ + if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == + 0) && (pAd->StaCfg.bHardwareRadio == TRUE) + && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + /*&&(pAd->bPCIclkOff == FALSE) */ + ) { + u32 data = 0; + + /* Read GPIO pin2 as Hardware controlled radio state */ +#ifndef RT3090 + RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data); +#endif /* RT3090 // */ +/*KH(PCIE PS):Added based on Jane<-- */ +#ifdef RT3090 +/* Read GPIO pin2 as Hardware controlled radio state */ +/* We need to Read GPIO if HW said so no mater what advance power saving */ + if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) + && + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) + && (pAd->StaCfg.PSControl.field.EnablePSinIdle == + TRUE)) { + /* Want to make sure device goes to L0 state before reading register. */ + RTMPPCIeLinkCtrlValueRestore(pAd, 0); + RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data); + RTMPPCIeLinkCtrlSetting(pAd, 3); + } else + RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data); +#endif /* RT3090 // */ +/*KH(PCIE PS):Added based on Jane--> */ + + if (data & 0x04) { pAd->StaCfg.bHwRadio = TRUE; - } - else - { + } else { pAd->StaCfg.bHwRadio = FALSE; } - if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) - { - pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); - if (pAd->StaCfg.bRadio == TRUE) - { + if (pAd->StaCfg.bRadio != + (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) { + pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio + && pAd->StaCfg.bSwRadio); + if (pAd->StaCfg.bRadio == TRUE) { MlmeRadioOn(pAd); - // Update extra information + /* Update extra information */ pAd->ExtraInfo = EXTRA_INFO_CLEAR; - } - else - { + } else { MlmeRadioOff(pAd); - // Update extra information + /* Update extra information */ pAd->ExtraInfo = HW_RADIO_OFF; } } } } -#endif /* RT2860 */ +#endif /* RTMP_MAC_PCI // */ - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_RADIO_OFF | - fRTMP_ADAPTER_RADIO_MEASUREMENT | - fRTMP_ADAPTER_RESET_IN_PROGRESS)))) + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_RADIO_MEASUREMENT | + fRTMP_ADAPTER_RESET_IN_PROGRESS)))) return; -#ifdef RT2860 - { - if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE)) - { - // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1. - pAd->SameRxByteCount++; - } - else - pAd->SameRxByteCount = 0; - - // If after BBP, still not work...need to check to reset PBF&MAC. - if (pAd->SameRxByteCount == 702) - { - pAd->SameRxByteCount = 0; - AsicResetPBF(pAd); - AsicResetMAC(pAd); - } - - // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode. - if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600))) - { - if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700)) - { - DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount)); - pAd->SameRxByteCount = 700; - AsicResetBBP(pAd); - } - } - - // Update lastReceiveByteCount. - pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount; - - if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd))) - { - pAd->CheckDmaBusyCount = 0; - AsicResetFromDMABusy(pAd); - } - } -#endif /* RT2860 */ - RT28XX_MLME_PRE_SANITY_CHECK(pAd); + RTMP_MLME_PRE_SANITY_CHECK(pAd); { - // Do nothing if monitor mode is on + /* Do nothing if monitor mode is on */ if (MONITOR_ON(pAd)) return; - if (pAd->Mlme.PeriodicRound & 0x1) - { - // This is the fix for wifi 11n extension channel overlapping test case. for 2860D + if (pAd->Mlme.PeriodicRound & 0x1) { + /* This is the fix for wifi 11n extension channel overlapping test case. for 2860D */ if (((pAd->MACVersion & 0xffff) == 0x0101) && - (STA_TGN_WIFI_ON(pAd)) && - (pAd->CommonCfg.IOTestParm.bToggle == FALSE)) - - { - RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf); - pAd->CommonCfg.IOTestParm.bToggle = TRUE; - } - else if ((STA_TGN_WIFI_ON(pAd)) && - ((pAd->MACVersion & 0xffff) == 0x0101)) - { - RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f); - pAd->CommonCfg.IOTestParm.bToggle = FALSE; - } + (STA_TGN_WIFI_ON(pAd)) && + (pAd->CommonCfg.IOTestParm.bToggle == FALSE)) + { + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf); + pAd->CommonCfg.IOTestParm.bToggle = TRUE; + } else if ((STA_TGN_WIFI_ON(pAd)) && + ((pAd->MACVersion & 0xffff) == 0x0101)) { + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f); + pAd->CommonCfg.IOTestParm.bToggle = FALSE; + } } } pAd->bUpdateBcnCntDone = FALSE; -// RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3); - pAd->Mlme.PeriodicRound ++; +/* RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3); */ + pAd->Mlme.PeriodicRound++; -#ifdef RT3070 - // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate. +#ifdef RTMP_MAC_USB + /* execute every 100ms, update the Tx FIFO Cnt for update Tx Rate. */ NICUpdateFifoStaCounters(pAd); -#endif // RT3070 // - // execute every 500ms - if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/) +#endif /* RTMP_MAC_USB // */ + + /* execute every 500ms */ + if ((pAd->Mlme.PeriodicRound % 5 == 0) + && RTMPAutoRateSwitchCheck(pAd) + /*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ ) { - // perform dynamic tx rate switching based on past TX history + /* perform dynamic tx rate switching based on past TX history */ { - if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) - ) - && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))) + if ((OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + ) + && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))) MlmeDynamicTxRateSwitching(pAd); } } + /* Normal 1 second Mlme PeriodicExec. */ + if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0) { + pAd->Mlme.OneSecPeriodicRound++; - // Normal 1 second Mlme PeriodicExec. - if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0) - { - pAd->Mlme.OneSecPeriodicRound ++; - - if (rx_Total) - { - - // reset counters - rx_AMSDU = 0; - rx_Total = 0; - } + /*ORIBATimerTimeout(pAd); */ - // Media status changed, report to NDIS - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE)) - { + /* Media status changed, report to NDIS */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE)) { RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE); - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - pAd->IndicateMediaState = NdisMediaStateConnected; + if (OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { + pAd->IndicateMediaState = + NdisMediaStateConnected; RTMP_IndicateMediaState(pAd); - } - else - { - pAd->IndicateMediaState = NdisMediaStateDisconnected; + } else { + pAd->IndicateMediaState = + NdisMediaStateDisconnected; RTMP_IndicateMediaState(pAd); } } NdisGetSystemUpTime(&pAd->Mlme.Now32); - // add the most up-to-date h/w raw counters into software variable, so that - // the dynamic tuning mechanism below are based on most up-to-date information + /* add the most up-to-date h/w raw counters into software variable, so that */ + /* the dynamic tuning mechanism below are based on most up-to-date information */ NICUpdateRawCounters(pAd); -#ifdef RT2870 - RT2870_WatchDog(pAd); -#endif // RT2870 // +#ifdef RTMP_MAC_USB + RTUSBWatchDog(pAd); +#endif /* RTMP_MAC_USB // */ - // Need statistics after read counter. So put after NICUpdateRawCounters + /* Need statistics after read counter. So put after NICUpdateRawCounters */ ORIBATimerTimeout(pAd); - // The time period for checking antenna is according to traffic - if (pAd->Mlme.bEnableAutoAntennaCheck) - { - TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + - pAd->RalinkCounters.OneSecTxRetryOkCount + - pAd->RalinkCounters.OneSecTxFailCount; - - // dynamic adjust antenna evaluation period according to the traffic - if (TxTotalCnt > 50) - { - if (pAd->Mlme.OneSecPeriodicRound % 10 == 0) - { - AsicEvaluateRxAnt(pAd); - } - } - else - { - if (pAd->Mlme.OneSecPeriodicRound % 3 == 0) - { - AsicEvaluateRxAnt(pAd); + /* if MGMT RING is full more than twice within 1 second, we consider there's */ + /* a hardware problem stucking the TX path. In this case, try a hardware reset */ + /* to recover the system */ + /* if (pAd->RalinkCounters.MgmtRingFullCount >= 2) */ + /* RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR); */ + /* else */ + /* pAd->RalinkCounters.MgmtRingFullCount = 0; */ + + /* The time period for checking antenna is according to traffic */ + { + if (pAd->Mlme.bEnableAutoAntennaCheck) { + TxTotalCnt = + pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + /* dynamic adjust antenna evaluation period according to the traffic */ + if (TxTotalCnt > 50) { + if (pAd->Mlme.OneSecPeriodicRound % + 10 == 0) { + AsicEvaluateRxAnt(pAd); + } + } else { + if (pAd->Mlme.OneSecPeriodicRound % 3 == + 0) { + AsicEvaluateRxAnt(pAd); + } } } } @@ -999,305 +879,590 @@ VOID MlmePeriodicExec( MlmeResetRalinkCounters(pAd); { -#ifdef RT2860 - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE)) -#endif +#ifdef RTMP_MAC_PCI + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) + && (pAd->bPCIclkOff == FALSE)) +#endif /* RTMP_MAC_PCI // */ { - // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock - // and sending CTS-to-self over and over. - // Software Patch Solution: - // 1. Polling debug state register 0x10F4 every one second. - // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred. - // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again. + /* When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock */ + /* and sending CTS-to-self over and over. */ + /* Software Patch Solution: */ + /* 1. Polling debug state register 0x10F4 every one second. */ + /* 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred. */ + /* 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again. */ - UINT32 MacReg = 0; + u32 MacReg = 0; RTMP_IO_READ32(pAd, 0x10F4, &MacReg); - if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20))) - { + if (((MacReg & 0x20000000) && (MacReg & 0x80)) + || ((MacReg & 0x20000000) + && (MacReg & 0x20))) { RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); RTMPusecDelay(1); RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC); - DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n")); + DBGPRINT(RT_DEBUG_WARN, + ("Warning, MAC specific condition occurs \n")); } } } - RT28XX_MLME_HANDLER(pAd); + RTMP_MLME_HANDLER(pAd); } pAd->bUpdateBcnCntDone = FALSE; } -VOID STAMlmePeriodicExec( - PRTMP_ADAPTER pAd) +/* + ========================================================================== + Validate SSID for connection try and rescan purpose + Valid SSID will have visible chars only. + The valid length is from 0 to 32. + IRQL = DISPATCH_LEVEL + ========================================================================== + */ +BOOLEAN MlmeValidateSSID(u8 *pSsid, u8 SsidLen) { -#ifdef RT2860 - ULONG TxTotalCnt; -#endif -#ifdef RT2870 - ULONG TxTotalCnt; - int i; -#endif - - if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) - { - // WPA MIC error should block association attempt for 60 seconds - if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32)) - pAd->StaCfg.bBlockAssoc = FALSE; - } - -#ifdef RT2860 - //Baron 2008/07/10 - //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus)); - //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0. - //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1. - if(pAd->StaCfg.WepStatus<2) - { - pAd->StaCfg.WpaSupplicantUP = 0; - } - else - { - pAd->StaCfg.WpaSupplicantUP = 1; - } -#endif + int index; - if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent)) - { - if (pAd->IndicateMediaState == NdisMediaStateConnected) - { - RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - } - pAd->PreMediaState = pAd->IndicateMediaState; - } + if (SsidLen > MAX_LEN_OF_SSID) + return (FALSE); -#ifdef RT2860 - if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) && - (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) && - (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) && - (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && - (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) - { - RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0); + /* Check each character value */ + for (index = 0; index < SsidLen; index++) { + if (pSsid[index] < 0x20) + return (FALSE); } -#endif + /* All checked */ + return (TRUE); +} +void MlmeSelectTxRateTable(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + u8 ** ppTable, + u8 *pTableSize, u8 *pInitTxRateIdx) +{ + do { + /* decide the rate table for tuning */ + if (pAd->CommonCfg.TxRateTableSize > 0) { + *ppTable = RateSwitchTable; + *pTableSize = RateSwitchTable[0]; + *pInitTxRateIdx = RateSwitchTable[1]; - AsicStaBbpTuning(pAd); + break; + } - TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + - pAd->RalinkCounters.OneSecTxRetryOkCount + - pAd->RalinkCounters.OneSecTxFailCount; + if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd)) { + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) { /* 11N 1S Adhoc */ + *ppTable = RateSwitchTable11N1S; + *pTableSize = RateSwitchTable11N1S[0]; + *pInitTxRateIdx = RateSwitchTable11N1S[1]; - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - // update channel quality for Roaming and UI LinkQuality display - MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32); - } + } else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) { /* 11N 2S Adhoc */ + if (pAd->LatchRfRegs.Channel <= 14) { + *ppTable = RateSwitchTable11N2S; + *pTableSize = RateSwitchTable11N2S[0]; + *pInitTxRateIdx = + RateSwitchTable11N2S[1]; + } else { + *ppTable = RateSwitchTable11N2SForABand; + *pTableSize = + RateSwitchTable11N2SForABand[0]; + *pInitTxRateIdx = + RateSwitchTable11N2SForABand[1]; + } - // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if - // Radio is currently in noisy environment - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - AsicAdjustTxPower(pAd); + } else if ((pEntry->RateLen == 4) + && (pEntry->HTCapability.MCSSet[0] == 0) + && (pEntry->HTCapability.MCSSet[1] == 0) + ) { + *ppTable = RateSwitchTable11B; + *pTableSize = RateSwitchTable11B[0]; + *pInitTxRateIdx = RateSwitchTable11B[1]; - if (INFRA_ON(pAd)) - { - // Is PSM bit consistent with user power management policy? - // This is the only place that will set PSM bit ON. - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - MlmeCheckPsmChange(pAd, pAd->Mlme.Now32); + } else if (pAd->LatchRfRegs.Channel <= 14) { + *ppTable = RateSwitchTable11BG; + *pTableSize = RateSwitchTable11BG[0]; + *pInitTxRateIdx = RateSwitchTable11BG[1]; - pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt; + } else { + *ppTable = RateSwitchTable11G; + *pTableSize = RateSwitchTable11G[0]; + *pInitTxRateIdx = RateSwitchTable11G[1]; - if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && - ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600))) - { - RTMPSetAGCInitValue(pAd, BW_20); - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd)))); + } + break; } + /*if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */ + /* ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */ + if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) { /* 11BGN 1S AP */ + *ppTable = RateSwitchTable11BGN1S; + *pTableSize = RateSwitchTable11BGN1S[0]; + *pInitTxRateIdx = RateSwitchTable11BGN1S[1]; - { - if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) - { - // When APSD is enabled, the period changes as 20 sec - if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8) - RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); - } - else - { - // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out) - if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) - { - if (pAd->CommonCfg.bWmmCapable) - RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); - else - RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE); - } - } - } - - if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality)) - { - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount)); - pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE; - pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime; - - // Lost AP, send disconnect & link down event - LinkDown(pAd, FALSE); - - { - union iwreq_data wrqu; - memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); - wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); - } - - MlmeAutoReconnectLastSSID(pAd); - } - else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality)) - { - pAd->RalinkCounters.BadCQIAutoRecoveryCount ++; - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount)); - MlmeAutoReconnectLastSSID(pAd); + break; } + /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */ + /* (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */ + if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) { /* 11BGN 2S AP */ + if (pAd->LatchRfRegs.Channel <= 14) { + *ppTable = RateSwitchTable11BGN2S; + *pTableSize = RateSwitchTable11BGN2S[0]; + *pInitTxRateIdx = RateSwitchTable11BGN2S[1]; - // Add auto seamless roaming - if (pAd->StaCfg.bFastRoaming) - { - SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam; - - DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), (CHAR)dBmToRoam)); + } else { + *ppTable = RateSwitchTable11BGN2SForABand; + *pTableSize = RateSwitchTable11BGN2SForABand[0]; + *pInitTxRateIdx = + RateSwitchTable11BGN2SForABand[1]; - if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam) - { - MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32); } + break; } - } - else if (ADHOC_ON(pAd)) - { -#ifdef RT2860 - // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails - // the "TX BEACON competition" for the entire past 1 sec. - // So that even when ASIC's BEACONgen engine been blocked - // by peer's BEACON due to slower system clock, this STA still can send out - // minimum BEACON to tell the peer I'm alive. - // drawback is that this BEACON won't be well aligned at TBTT boundary. - // EnqueueBeaconFrame(pAd); // software send BEACON - - // if all 11b peers leave this BSS more than 5 seconds, update Tx rate, - // restore outgoing BEACON to support B/G-mixed mode - if ((pAd->CommonCfg.Channel <= 14) && - (pAd->CommonCfg.MaxTxRate <= RATE_11) && - (pAd->CommonCfg.MaxDesiredRate > RATE_11) && - ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32)) - { - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n")); - NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); - pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen; - MlmeUpdateTxRates(pAd, FALSE, 0); - MakeIbssBeacon(pAd); // re-build BEACON frame - AsicEnableIbssSync(pAd); // copy to on-chip memory - pAd->StaCfg.AdhocBOnlyJoined = FALSE; - } + /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */ + if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) { /* 11N 1S AP */ + *ppTable = RateSwitchTable11N1S; + *pTableSize = RateSwitchTable11N1S[0]; + *pInitTxRateIdx = RateSwitchTable11N1S[1]; - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) - { - if ((pAd->StaCfg.AdhocBGJoined) && - ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32)) - { - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n")); - pAd->StaCfg.AdhocBGJoined = FALSE; + break; + } + /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */ + if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) { /* 11N 2S AP */ + if (pAd->LatchRfRegs.Channel <= 14) { + *ppTable = RateSwitchTable11N2S; + *pTableSize = RateSwitchTable11N2S[0]; + *pInitTxRateIdx = RateSwitchTable11N2S[1]; + } else { + *ppTable = RateSwitchTable11N2SForABand; + *pTableSize = RateSwitchTable11N2SForABand[0]; + *pInitTxRateIdx = + RateSwitchTable11N2SForABand[1]; } - if ((pAd->StaCfg.Adhoc20NJoined) && - ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32)) - { - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n")); - pAd->StaCfg.Adhoc20NJoined = FALSE; - } + break; } -#endif /* RT2860 */ + /*else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */ + if ((pEntry->RateLen == 4 || pAd->CommonCfg.PhyMode == PHY_11B) + /*Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode */ + /* && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) */ + ) { /* B only AP */ + *ppTable = RateSwitchTable11B; + *pTableSize = RateSwitchTable11B[0]; + *pInitTxRateIdx = RateSwitchTable11B[1]; - //radar detect - if ((pAd->CommonCfg.Channel > 14) - && (pAd->CommonCfg.bIEEE80211H == 1) - && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) - { - RadarDetectPeriodic(pAd); + break; } + /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */ + if ((pEntry->RateLen > 8) + && (pEntry->HTCapability.MCSSet[0] == 0) + && (pEntry->HTCapability.MCSSet[1] == 0) + ) { /* B/G mixed AP */ + *ppTable = RateSwitchTable11BG; + *pTableSize = RateSwitchTable11BG[0]; + *pInitTxRateIdx = RateSwitchTable11BG[1]; - // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState - // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can - // join later. - if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) && - OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - MLME_START_REQ_STRUCT StartReq; - - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n")); - LinkDown(pAd, FALSE); + break; + } + /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */ + if ((pEntry->RateLen == 8) + && (pEntry->HTCapability.MCSSet[0] == 0) + && (pEntry->HTCapability.MCSSet[1] == 0) + ) { /* G only AP */ + *ppTable = RateSwitchTable11G; + *pTableSize = RateSwitchTable11G[0]; + *pInitTxRateIdx = RateSwitchTable11G[1]; - StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; + break; } -#ifdef RT2870 - for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { - MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i]; - - if (pEntry->ValidAsCLI == FALSE) - continue; + /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */ + if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)) { /* Legacy mode */ + if (pAd->CommonCfg.MaxTxRate <= RATE_11) { + *ppTable = RateSwitchTable11B; + *pTableSize = RateSwitchTable11B[0]; + *pInitTxRateIdx = RateSwitchTable11B[1]; + } else if ((pAd->CommonCfg.MaxTxRate > RATE_11) + && (pAd->CommonCfg.MinTxRate > + RATE_11)) { + *ppTable = RateSwitchTable11G; + *pTableSize = RateSwitchTable11G[0]; + *pInitTxRateIdx = RateSwitchTable11G[1]; - if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) - MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); - } -#endif + } else { + *ppTable = RateSwitchTable11BG; + *pTableSize = RateSwitchTable11BG[0]; + *pInitTxRateIdx = + RateSwitchTable11BG[1]; + } + break; + } + if (pAd->LatchRfRegs.Channel <= 14) { + if (pAd->CommonCfg.TxStream == 1) { + *ppTable = RateSwitchTable11N1S; + *pTableSize = RateSwitchTable11N1S[0]; + *pInitTxRateIdx = + RateSwitchTable11N1S[1]; + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("DRS: unkown mode,default use 11N 1S AP \n")); + } else { + *ppTable = RateSwitchTable11N2S; + *pTableSize = RateSwitchTable11N2S[0]; + *pInitTxRateIdx = + RateSwitchTable11N2S[1]; + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("DRS: unkown mode,default use 11N 2S AP \n")); + } + } else { + if (pAd->CommonCfg.TxStream == 1) { + *ppTable = RateSwitchTable11N1S; + *pTableSize = RateSwitchTable11N1S[0]; + *pInitTxRateIdx = + RateSwitchTable11N1S[1]; + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("DRS: unkown mode,default use 11N 1S AP \n")); + } else { + *ppTable = RateSwitchTable11N2SForABand; + *pTableSize = + RateSwitchTable11N2SForABand[0]; + *pInitTxRateIdx = + RateSwitchTable11N2SForABand[1]; + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("DRS: unkown mode,default use 11N 2S AP \n")); + } + } + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n", + pAd->StaActive.SupRateLen, + pAd->StaActive.ExtRateLen, + pAd->StaActive.SupportedPhyInfo.MCSSet[0], + pAd->StaActive.SupportedPhyInfo. + MCSSet[1])); + } + } while (FALSE); +} + +void STAMlmePeriodicExec(struct rt_rtmp_adapter *pAd) +{ + unsigned long TxTotalCnt; + int i; + + /* + We return here in ATE mode, because the statistics + that ATE need are not collected via this routine. + */ +#if defined(RT305x)||defined(RT3070) + /* request by Gary, if Rssi0 > -42, BBP 82 need to be changed from 0x62 to 0x42, , bbp 67 need to be changed from 0x20 to 0x18 */ + if (!pAd->CommonCfg.HighPowerPatchDisabled) { +#ifdef RT3070 + if ((IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201))) +#endif /* RT3070 // */ + { + if ((pAd->StaCfg.RssiSample.AvgRssi0 != 0) + && (pAd->StaCfg.RssiSample.AvgRssi0 > + (pAd->BbpRssiToDbmDelta - 35))) { + RT30xxWriteRFRegister(pAd, RF_R27, 0x20); + } else { + RT30xxWriteRFRegister(pAd, RF_R27, 0x23); + } + } + } +#endif +#ifdef PCIE_PS_SUPPORT +/* don't perform idle-power-save mechanism within 3 min after driver initialization. */ +/* This can make rebooter test more robust */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { + if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) + && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) + && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) + && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) { + if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) { + if (pAd->StaCfg.PSControl.field.EnableNewPS == + TRUE) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s\n", __func__)); + RT28xxPciAsicRadioOff(pAd, + GUI_IDLE_POWER_SAVE, + 0); + } else { + AsicSendCommandToMcu(pAd, 0x30, + PowerSafeCID, 0xff, + 0x2); + /* Wait command success */ + AsicCheckCommanOk(pAd, PowerSafeCID); + RTMP_SET_FLAG(pAd, + fRTMP_ADAPTER_IDLE_RADIO_OFF); + DBGPRINT(RT_DEBUG_TRACE, + ("PSM - rt30xx Issue Sleep command)\n")); + } + } else if (pAd->Mlme.OneSecPeriodicRound > 180) { + if (pAd->StaCfg.PSControl.field.EnableNewPS == + TRUE) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s\n", __func__)); + RT28xxPciAsicRadioOff(pAd, + GUI_IDLE_POWER_SAVE, + 0); + } else { + AsicSendCommandToMcu(pAd, 0x30, + PowerSafeCID, 0xff, + 0x02); + /* Wait command success */ + AsicCheckCommanOk(pAd, PowerSafeCID); + RTMP_SET_FLAG(pAd, + fRTMP_ADAPTER_IDLE_RADIO_OFF); + DBGPRINT(RT_DEBUG_TRACE, + ("PSM - rt28xx Issue Sleep command)\n")); + } + } + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("STAMlmePeriodicExec MMCHK - CommonCfg.Ssid[%d]=%c%c%c%c... MlmeAux.Ssid[%d]=%c%c%c%c...\n", + pAd->CommonCfg.SsidLen, + pAd->CommonCfg.Ssid[0], + pAd->CommonCfg.Ssid[1], + pAd->CommonCfg.Ssid[2], + pAd->CommonCfg.Ssid[3], pAd->MlmeAux.SsidLen, + pAd->MlmeAux.Ssid[0], pAd->MlmeAux.Ssid[1], + pAd->MlmeAux.Ssid[2], pAd->MlmeAux.Ssid[3])); + } + } +#endif /* PCIE_PS_SUPPORT // */ + + if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) { + /* WPA MIC error should block association attempt for 60 seconds */ + if (pAd->StaCfg.bBlockAssoc && + RTMP_TIME_AFTER(pAd->Mlme.Now32, + pAd->StaCfg.LastMicErrorTime + + (60 * OS_HZ))) + pAd->StaCfg.bBlockAssoc = FALSE; + } + + if ((pAd->PreMediaState != pAd->IndicateMediaState) + && (pAd->CommonCfg.bWirelessEvent)) { + if (pAd->IndicateMediaState == NdisMediaStateConnected) { + RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, + pAd->MacTab.Content[BSSID_WCID]. + Addr, BSS0, 0); + } + pAd->PreMediaState = pAd->IndicateMediaState; } - else // no INFRA nor ADHOC connection + + if (pAd->CommonCfg.PSPXlink && ADHOC_ON(pAd)) { + } else { + AsicStaBbpTuning(pAd); + } + + TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { + /* update channel quality for Roaming and UI LinkQuality display */ + MlmeCalculateChannelQuality(pAd, NULL, pAd->Mlme.Now32); + } + /* must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if */ + /* Radio is currently in noisy environment */ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + AsicAdjustTxPower(pAd); + + if (INFRA_ON(pAd)) { + + /* Is PSM bit consistent with user power management policy? */ + /* This is the only place that will set PSM bit ON. */ + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + MlmeCheckPsmChange(pAd, pAd->Mlme.Now32); + + pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt; + + if ((RTMP_TIME_AFTER + (pAd->Mlme.Now32, + pAd->StaCfg.LastBeaconRxTime + (1 * OS_HZ))) + && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + && + (((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt) < + 600))) { + RTMPSetAGCInitValue(pAd, BW_20); + DBGPRINT(RT_DEBUG_TRACE, + ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", + (0x2E + GET_LNA_GAIN(pAd)))); + } + /*if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && */ + /* (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)) */ + { + if (pAd->CommonCfg.bAPSDCapable + && pAd->CommonCfg.APEdcaParm.bAPSDCapable) { + /* When APSD is enabled, the period changes as 20 sec */ + if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8) + RTMPSendNullFrame(pAd, + pAd->CommonCfg.TxRate, + TRUE); + } else { + /* Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out) */ + if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) { + if (pAd->CommonCfg.bWmmCapable) + RTMPSendNullFrame(pAd, + pAd-> + CommonCfg. + TxRate, TRUE); + else + RTMPSendNullFrame(pAd, + pAd-> + CommonCfg. + TxRate, + FALSE); + } + } + } + + if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality)) { + DBGPRINT(RT_DEBUG_TRACE, + ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", + pAd->RalinkCounters.BadCQIAutoRecoveryCount)); + + /* Lost AP, send disconnect & link down event */ + LinkDown(pAd, FALSE); + + RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, + 0); + + /* RTMPPatchMacBbpBug(pAd); */ + MlmeAutoReconnectLastSSID(pAd); + } else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality)) { + pAd->RalinkCounters.BadCQIAutoRecoveryCount++; + DBGPRINT(RT_DEBUG_TRACE, + ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", + pAd->RalinkCounters.BadCQIAutoRecoveryCount)); + MlmeAutoReconnectLastSSID(pAd); + } + + if (pAd->StaCfg.bAutoRoaming) { + BOOLEAN rv = FALSE; + char dBmToRoam = pAd->StaCfg.dBmToRoam; + char MaxRssi = RTMPMaxRssi(pAd, + pAd->StaCfg.RssiSample. + LastRssi0, + pAd->StaCfg.RssiSample. + LastRssi1, + pAd->StaCfg.RssiSample. + LastRssi2); + + /* Scanning, ignore Roaming */ + if (!RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) + && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) + && (MaxRssi <= dBmToRoam)) { + DBGPRINT(RT_DEBUG_TRACE, + ("Rssi=%d, dBmToRoam=%d\n", MaxRssi, + (char)dBmToRoam)); + + /* Add auto seamless roaming */ + if (rv == FALSE) + rv = MlmeCheckForFastRoaming(pAd); + + if (rv == FALSE) { + if ((pAd->StaCfg.LastScanTime + + 10 * OS_HZ) < pAd->Mlme.Now32) { + DBGPRINT(RT_DEBUG_TRACE, + ("MMCHK - Roaming, No eligable entry, try new scan!\n")); + pAd->StaCfg.ScanCnt = 2; + pAd->StaCfg.LastScanTime = + pAd->Mlme.Now32; + MlmeAutoScan(pAd); + } + } + } + } + } else if (ADHOC_ON(pAd)) { + /* If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState */ + /* to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can */ + /* join later. */ + if (RTMP_TIME_AFTER + (pAd->Mlme.Now32, + pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME) + && OPSTATUS_TEST_FLAG(pAd, + fOP_STATUS_MEDIA_STATE_CONNECTED)) { + struct rt_mlme_start_req StartReq; + + DBGPRINT(RT_DEBUG_TRACE, + ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n")); + LinkDown(pAd, FALSE); + + StartParmFill(pAd, &StartReq, + (char *) pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, + sizeof(struct rt_mlme_start_req), &StartReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; + } + + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { + struct rt_mac_table_entry *pEntry = &pAd->MacTab.Content[i]; + + if (pEntry->ValidAsCLI == FALSE) + continue; + + if (RTMP_TIME_AFTER + (pAd->Mlme.Now32, + pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME)) + MacTableDeleteEntry(pAd, pEntry->Aid, + pEntry->Addr); + } + } else /* no INFRA nor ADHOC connection */ { if (pAd->StaCfg.bScanReqIsFromWebUI && - ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32)) + RTMP_TIME_BEFORE(pAd->Mlme.Now32, + pAd->StaCfg.LastScanTime + (30 * OS_HZ))) goto SKIP_AUTO_SCAN_CONN; - else - pAd->StaCfg.bScanReqIsFromWebUI = FALSE; + else + pAd->StaCfg.bScanReqIsFromWebUI = FALSE; if ((pAd->StaCfg.bAutoReconnect == TRUE) - && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP) - && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) - { - if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) - { - MLME_SCAN_REQ_STRUCT ScanReq; - - if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32) - { - DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid)); - ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; - // Reset Missed scan number - pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; - } - else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room + && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP) + && + (MlmeValidateSSID + (pAd->MlmeAux.AutoReconnectSsid, + pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) { + if ((pAd->ScanTab.BssNr == 0) + && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) { + struct rt_mlme_scan_req ScanReq; + + if (RTMP_TIME_AFTER + (pAd->Mlme.Now32, + pAd->StaCfg.LastScanTime + (10 * OS_HZ))) { + DBGPRINT(RT_DEBUG_TRACE, + ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", + pAd->MlmeAux. + AutoReconnectSsid)); + ScanParmFill(pAd, &ScanReq, + (char *)pAd->MlmeAux. + AutoReconnectSsid, + pAd->MlmeAux. + AutoReconnectSsidLen, + BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, + MT2_MLME_SCAN_REQ, + sizeof + (struct rt_mlme_scan_req), + &ScanReq); + pAd->Mlme.CntlMachine.CurrState = + CNTL_WAIT_OID_LIST_SCAN; + /* Reset Missed scan number */ + pAd->StaCfg.LastScanTime = + pAd->Mlme.Now32; + } else if (pAd->StaCfg.BssType == BSS_ADHOC) /* Quit the forever scan when in a very clean room */ MlmeAutoReconnectLastSSID(pAd); - } - else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) - { - if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0) - { + } else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) { + if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0) { MlmeAutoScan(pAd); - pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; - } - else - { - MlmeAutoReconnectLastSSID(pAd); + pAd->StaCfg.LastScanTime = + pAd->Mlme.Now32; + } else { + MlmeAutoReconnectLastSSID(pAd); } } } @@ -1305,6346 +1470,3763 @@ VOID STAMlmePeriodicExec( SKIP_AUTO_SCAN_CONN: - if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE)) - { + if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap != 0) + && (pAd->MacTab.fAnyBASession == FALSE)) { pAd->MacTab.fAnyBASession = TRUE; - AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE); - } - else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE)) - { + AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, + FALSE); + } else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap == 0) + && (pAd->MacTab.fAnyBASession == TRUE)) { pAd->MacTab.fAnyBASession = FALSE; - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); + AsicUpdateProtect(pAd, + pAd->MlmeAux.AddHtInfo.AddHtInfo2. + OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); } return; } -// Link down report -VOID LinkDownExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) +/* Link down report */ +void LinkDownExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) { + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + if (pAd != NULL) { + struct rt_mlme_disassoc_req DisassocReq; - pAd->IndicateMediaState = NdisMediaStateDisconnected; - RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_DOWN; + if ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) && + (INFRA_ON(pAd))) { + DBGPRINT(RT_DEBUG_TRACE, + ("LinkDownExec(): disassociate with current AP...\n")); + DisassocParmFill(pAd, &DisassocReq, + pAd->CommonCfg.Bssid, + REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_DISASSOC_REQ, + sizeof(struct rt_mlme_disassoc_req), + &DisassocReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + } + } } -// IRQL = DISPATCH_LEVEL -VOID MlmeAutoScan( - IN PRTMP_ADAPTER pAd) +/* IRQL = DISPATCH_LEVEL */ +void MlmeAutoScan(struct rt_rtmp_adapter *pAd) { - // check CntlMachine.CurrState to avoid collision with NDIS SetOID request - if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) - { + /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */ + if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) { DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n")); MlmeEnqueue(pAd, - MLME_CNTL_STATE_MACHINE, - OID_802_11_BSSID_LIST_SCAN, - 0, - NULL); - RT28XX_MLME_HANDLER(pAd); + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID_LIST_SCAN, + pAd->MlmeAux.AutoReconnectSsidLen, + pAd->MlmeAux.AutoReconnectSsid); + RTMP_MLME_HANDLER(pAd); } } -// IRQL = DISPATCH_LEVEL -VOID MlmeAutoReconnectLastSSID( - IN PRTMP_ADAPTER pAd) +/* IRQL = DISPATCH_LEVEL */ +void MlmeAutoReconnectLastSSID(struct rt_rtmp_adapter *pAd) { + if (pAd->StaCfg.bAutoConnectByBssid) { + DBGPRINT(RT_DEBUG_TRACE, + ("Driver auto reconnect to last OID_802_11_BSSID setting - %02X:%02X:%02X:%02X:%02X:%02X\n", + pAd->MlmeAux.Bssid[0], pAd->MlmeAux.Bssid[1], + pAd->MlmeAux.Bssid[2], pAd->MlmeAux.Bssid[3], + pAd->MlmeAux.Bssid[4], pAd->MlmeAux.Bssid[5])); + + pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID, MAC_ADDR_LEN, pAd->MlmeAux.Bssid); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - // check CntlMachine.CurrState to avoid collision with NDIS SetOID request - if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && - (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) - { - NDIS_802_11_SSID OidSsid; + RTMP_MLME_HANDLER(pAd); + } + /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */ + else if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && + (MlmeValidateSSID + (pAd->MlmeAux.AutoReconnectSsid, + pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) { + struct rt_ndis_802_11_ssid OidSsid; OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen; - NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, + pAd->MlmeAux.AutoReconnectSsidLen); - DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen)); - MlmeEnqueue(pAd, - MLME_CNTL_STATE_MACHINE, - OID_802_11_SSID, - sizeof(NDIS_802_11_SSID), - &OidSsid); - RT28XX_MLME_HANDLER(pAd); + DBGPRINT(RT_DEBUG_TRACE, + ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", + pAd->MlmeAux.AutoReconnectSsid, + pAd->MlmeAux.AutoReconnectSsidLen)); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_SSID, + sizeof(struct rt_ndis_802_11_ssid), &OidSsid); + RTMP_MLME_HANDLER(pAd); } } /* ========================================================================== - Validate SSID for connection try and rescan purpose - Valid SSID will have visible chars only. - The valid length is from 0 to 32. + Description: + This routine checks if there're other APs out there capable for + roaming. Caller should call this routine only when Link up in INFRA mode + and channel quality is below CQI_GOOD_THRESHOLD. + IRQL = DISPATCH_LEVEL + + Output: ========================================================================== */ -BOOLEAN MlmeValidateSSID( - IN PUCHAR pSsid, - IN UCHAR SsidLen) +void MlmeCheckForRoaming(struct rt_rtmp_adapter *pAd, unsigned long Now32) { - int index; + u16 i; + struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab; + struct rt_bss_entry *pBss; - if (SsidLen > MAX_LEN_OF_SSID) - return (FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n")); + /* put all roaming candidates into RoamTab, and sort in RSSI order */ + BssTableInit(pRoamTab); + for (i = 0; i < pAd->ScanTab.BssNr; i++) { + pBss = &pAd->ScanTab.BssEntry[i]; - // Check each character value - for (index = 0; index < SsidLen; index++) - { - if (pSsid[index] < 0x20) - return (FALSE); + if ((pBss->LastBeaconRxTime + pAd->StaCfg.BeaconLostTime) < + Now32) + continue; /* AP disappear */ + if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING) + continue; /* RSSI too weak. forget it. */ + if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) + continue; /* skip current AP */ + if (pBss->Rssi < + (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA)) + continue; /* only AP with stronger RSSI is eligible for roaming */ + + /* AP passing all above rules is put into roaming candidate table */ + NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, + sizeof(struct rt_bss_entry)); + pRoamTab->BssNr += 1; } - // All checked - return (TRUE); + if (pRoamTab->BssNr > 0) { + /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */ + if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) { + pAd->RalinkCounters.PoorCQIRoamingCount++; + DBGPRINT(RT_DEBUG_TRACE, + ("MMCHK - Roaming attempt #%ld\n", + pAd->RalinkCounters.PoorCQIRoamingCount)); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, + MT2_MLME_ROAMING_REQ, 0, NULL); + RTMP_MLME_HANDLER(pAd); + } + } + DBGPRINT(RT_DEBUG_TRACE, + ("<== MlmeCheckForRoaming(# of candidate= %d)\n", + pRoamTab->BssNr)); } -VOID MlmeSelectTxRateTable( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PUCHAR *ppTable, - IN PUCHAR pTableSize, - IN PUCHAR pInitTxRateIdx) +/* + ========================================================================== + Description: + This routine checks if there're other APs out there capable for + roaming. Caller should call this routine only when link up in INFRA mode + and channel quality is below CQI_GOOD_THRESHOLD. + + IRQL = DISPATCH_LEVEL + + Output: + ========================================================================== + */ +BOOLEAN MlmeCheckForFastRoaming(struct rt_rtmp_adapter *pAd) { - do - { - // decide the rate table for tuning - if (pAd->CommonCfg.TxRateTableSize > 0) - { - *ppTable = RateSwitchTable; - *pTableSize = RateSwitchTable[0]; - *pInitTxRateIdx = RateSwitchTable[1]; + u16 i; + struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab; + struct rt_bss_entry *pBss; - break; + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n")); + /* put all roaming candidates into RoamTab, and sort in RSSI order */ + BssTableInit(pRoamTab); + for (i = 0; i < pAd->ScanTab.BssNr; i++) { + pBss = &pAd->ScanTab.BssEntry[i]; + + if ((pBss->Rssi <= -50) + && (pBss->Channel == pAd->CommonCfg.Channel)) + continue; /* RSSI too weak. forget it. */ + if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) + continue; /* skip current AP */ + if (!SSID_EQUAL + (pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, + pAd->CommonCfg.SsidLen)) + continue; /* skip different SSID */ + if (pBss->Rssi < + (RTMPMaxRssi + (pAd, pAd->StaCfg.RssiSample.LastRssi0, + pAd->StaCfg.RssiSample.LastRssi1, + pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA)) + continue; /* skip AP without better RSSI */ + + DBGPRINT(RT_DEBUG_TRACE, + ("LastRssi0 = %d, pBss->Rssi = %d\n", + RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, + pAd->StaCfg.RssiSample.LastRssi1, + pAd->StaCfg.RssiSample.LastRssi2), + pBss->Rssi)); + /* AP passing all above rules is put into roaming candidate table */ + NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, + sizeof(struct rt_bss_entry)); + pRoamTab->BssNr += 1; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr)); + if (pRoamTab->BssNr > 0) { + /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */ + if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) { + pAd->RalinkCounters.PoorCQIRoamingCount++; + DBGPRINT(RT_DEBUG_TRACE, + ("MMCHK - Roaming attempt #%ld\n", + pAd->RalinkCounters.PoorCQIRoamingCount)); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, + MT2_MLME_ROAMING_REQ, 0, NULL); + RTMP_MLME_HANDLER(pAd); + return TRUE; } + } - if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd)) - { - if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && -#ifdef RT2860 - !pAd->StaCfg.AdhocBOnlyJoined && - !pAd->StaCfg.AdhocBGJoined && - (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && - ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) -#endif -#ifdef RT2870 - (pEntry->HTCapability.MCSSet[0] == 0xff) && - ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) -#endif - {// 11N 1S Adhoc - *ppTable = RateSwitchTable11N1S; - *pTableSize = RateSwitchTable11N1S[0]; - *pInitTxRateIdx = RateSwitchTable11N1S[1]; + return FALSE; +} - } - else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && -#ifdef RT2860 - !pAd->StaCfg.AdhocBOnlyJoined && - !pAd->StaCfg.AdhocBGJoined && - (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && - (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && -#endif -#ifdef RT2870 - (pEntry->HTCapability.MCSSet[0] == 0xff) && - (pEntry->HTCapability.MCSSet[1] == 0xff) && -#endif - (pAd->Antenna.field.TxPath == 2)) - {// 11N 2S Adhoc - if (pAd->LatchRfRegs.Channel <= 14) - { - *ppTable = RateSwitchTable11N2S; - *pTableSize = RateSwitchTable11N2S[0]; - *pInitTxRateIdx = RateSwitchTable11N2S[1]; - } - else - { - *ppTable = RateSwitchTable11N2SForABand; - *pTableSize = RateSwitchTable11N2SForABand[0]; - *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; - } +void MlmeSetTxRate(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_rtmp_tx_rate_switch * pTxRate) +{ + u8 MaxMode = MODE_OFDM; - } - else -#ifdef RT2860 - if (pAd->CommonCfg.PhyMode == PHY_11B) - { - *ppTable = RateSwitchTable11B; - *pTableSize = RateSwitchTable11B[0]; - *pInitTxRateIdx = RateSwitchTable11B[1]; + MaxMode = MODE_HTGREENFIELD; - } - else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE)) -#endif -#ifdef RT2870 - if ((pEntry->RateLen == 4) - && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) - ) -#endif - { - // USe B Table when Only b-only Station in my IBSS . - *ppTable = RateSwitchTable11B; - *pTableSize = RateSwitchTable11B[0]; - *pInitTxRateIdx = RateSwitchTable11B[1]; + if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) + && (pAd->Antenna.field.TxPath == 2)) + pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE; + else + pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; - } - else if (pAd->LatchRfRegs.Channel <= 14) - { - *ppTable = RateSwitchTable11BG; - *pTableSize = RateSwitchTable11BG[0]; - *pInitTxRateIdx = RateSwitchTable11BG[1]; + if (pTxRate->CurrMCS < MCS_AUTO) + pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS; - } - else - { - *ppTable = RateSwitchTable11G; - *pTableSize = RateSwitchTable11G[0]; - *pInitTxRateIdx = RateSwitchTable11G[1]; + if (pAd->StaCfg.HTPhyMode.field.MCS > 7) + pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; - } - break; - } + if (ADHOC_ON(pAd)) { + /* If peer adhoc is b-only mode, we can't send 11g rate. */ + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; + pEntry->HTPhyMode.field.STBC = STBC_NONE; - if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) && - ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) - {// 11BGN 1S AP - *ppTable = RateSwitchTable11BGN1S; - *pTableSize = RateSwitchTable11BGN1S[0]; - *pInitTxRateIdx = RateSwitchTable11BGN1S[1]; + /* */ + /* For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary */ + /* */ + pEntry->HTPhyMode.field.MODE = pTxRate->Mode; + pEntry->HTPhyMode.field.ShortGI = + pAd->StaCfg.HTPhyMode.field.ShortGI; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - break; - } + /* Patch speed error in status page */ + pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE; + } else { + if (pTxRate->Mode <= MaxMode) + pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode; - if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) && - (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) - {// 11BGN 2S AP - if (pAd->LatchRfRegs.Channel <= 14) - { - *ppTable = RateSwitchTable11BGN2S; - *pTableSize = RateSwitchTable11BGN2S[0]; - *pInitTxRateIdx = RateSwitchTable11BGN2S[1]; + if (pTxRate->ShortGI + && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI)) + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400; + else + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; + /* Reexam each bandwidth's SGI support. */ + if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400) { + if ((pEntry->HTPhyMode.field.BW == BW_20) + && + (!CLIENT_STATUS_TEST_FLAG + (pEntry, fCLIENT_STATUS_SGI20_CAPABLE))) + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; + if ((pEntry->HTPhyMode.field.BW == BW_40) + && + (!CLIENT_STATUS_TEST_FLAG + (pEntry, fCLIENT_STATUS_SGI40_CAPABLE))) + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; + } + /* Turn RTS/CTS rate to 6Mbps. */ + if ((pEntry->HTPhyMode.field.MCS == 0) + && (pAd->StaCfg.HTPhyMode.field.MCS != 0)) { + pEntry->HTPhyMode.field.MCS = + pAd->StaCfg.HTPhyMode.field.MCS; + if (pAd->MacTab.fAnyBASession) { + AsicUpdateProtect(pAd, HT_FORCERTSCTS, + ALLN_SETPROTECT, TRUE, + (BOOLEAN) pAd->MlmeAux. + AddHtInfo.AddHtInfo2. + NonGfPresent); + } else { + AsicUpdateProtect(pAd, + pAd->MlmeAux.AddHtInfo. + AddHtInfo2.OperaionMode, + ALLN_SETPROTECT, TRUE, + (BOOLEAN) pAd->MlmeAux. + AddHtInfo.AddHtInfo2. + NonGfPresent); } - else - { - *ppTable = RateSwitchTable11BGN2SForABand; - *pTableSize = RateSwitchTable11BGN2SForABand[0]; - *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1]; - + } else if ((pEntry->HTPhyMode.field.MCS == 8) + && (pAd->StaCfg.HTPhyMode.field.MCS != 8)) { + pEntry->HTPhyMode.field.MCS = + pAd->StaCfg.HTPhyMode.field.MCS; + if (pAd->MacTab.fAnyBASession) { + AsicUpdateProtect(pAd, HT_FORCERTSCTS, + ALLN_SETPROTECT, TRUE, + (BOOLEAN) pAd->MlmeAux. + AddHtInfo.AddHtInfo2. + NonGfPresent); + } else { + AsicUpdateProtect(pAd, + pAd->MlmeAux.AddHtInfo. + AddHtInfo2.OperaionMode, + ALLN_SETPROTECT, TRUE, + (BOOLEAN) pAd->MlmeAux. + AddHtInfo.AddHtInfo2. + NonGfPresent); } - break; - } - - if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) - {// 11N 1S AP - *ppTable = RateSwitchTable11N1S; - *pTableSize = RateSwitchTable11N1S[0]; - *pInitTxRateIdx = RateSwitchTable11N1S[1]; + } else if ((pEntry->HTPhyMode.field.MCS != 0) + && (pAd->StaCfg.HTPhyMode.field.MCS == 0)) { + AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, + TRUE, + (BOOLEAN) pAd->MlmeAux.AddHtInfo. + AddHtInfo2.NonGfPresent); + + } else if ((pEntry->HTPhyMode.field.MCS != 8) + && (pAd->StaCfg.HTPhyMode.field.MCS == 8)) { + AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, + TRUE, + (BOOLEAN) pAd->MlmeAux.AddHtInfo. + AddHtInfo2.NonGfPresent); + } + + pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC; + pEntry->HTPhyMode.field.ShortGI = + pAd->StaCfg.HTPhyMode.field.ShortGI; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; + if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) + && pAd->WIFItestbed.bGreenField) + pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD; + } + + pAd->LastTxRate = (u16)(pEntry->HTPhyMode.word); +} - break; - } +/* + ========================================================================== + Description: + This routine calculates the acumulated TxPER of eaxh TxRate. And + according to the calculation result, change CommonCfg.TxRate which + is the stable TX Rate we expect the Radio situation could sustained. - if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) - {// 11N 2S AP - if (pAd->LatchRfRegs.Channel <= 14) - { - *ppTable = RateSwitchTable11N2S; - *pTableSize = RateSwitchTable11N2S[0]; - *pInitTxRateIdx = RateSwitchTable11N2S[1]; - } - else - { - *ppTable = RateSwitchTable11N2SForABand; - *pTableSize = RateSwitchTable11N2SForABand[0]; - *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; - } + CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate} + Output: + CommonCfg.TxRate - - break; - } + IRQL = DISPATCH_LEVEL - //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) - if (pEntry->RateLen == 4) - {// B only AP - *ppTable = RateSwitchTable11B; - *pTableSize = RateSwitchTable11B[0]; - *pInitTxRateIdx = RateSwitchTable11B[1]; + NOTE: + call this routine every second + ========================================================================== + */ +void MlmeDynamicTxRateSwitching(struct rt_rtmp_adapter *pAd) +{ + u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx; + unsigned long i, AccuTxTotalCnt = 0, TxTotalCnt; + unsigned long TxErrorRatio = 0; + BOOLEAN bTxRateChanged = FALSE, bUpgradeQuality = FALSE; + struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL; + u8 *pTable; + u8 TableSize = 0; + u8 InitTxRateIdx = 0, TrainUp, TrainDown; + char Rssi, RssiOffset = 0; + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; + struct rt_mac_table_entry *pEntry; + struct rt_rssi_sample *pRssi = &pAd->StaCfg.RssiSample; + + /* */ + /* walk through MAC table, see if need to change AP's TX rate toward each entry */ + /* */ + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { + pEntry = &pAd->MacTab.Content[i]; - break; - } + /* check if this entry need to switch rate automatically */ + if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) + continue; - //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) - if ((pEntry->RateLen > 8) - && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) - ) - {// B/G mixed AP - *ppTable = RateSwitchTable11BG; - *pTableSize = RateSwitchTable11BG[0]; - *pInitTxRateIdx = RateSwitchTable11BG[1]; + if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls)) { + Rssi = RTMPMaxRssi(pAd, + pRssi->AvgRssi0, + pRssi->AvgRssi1, pRssi->AvgRssi2); - break; + /* Update statistic counter */ + RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); + pAd->bUpdateBcnCntDone = TRUE; + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + pAd->RalinkCounters.OneSecTxRetryOkCount += + StaTx1.field.TxRetransmit; + pAd->RalinkCounters.OneSecTxNoRetryOkCount += + StaTx1.field.TxSuccess; + pAd->RalinkCounters.OneSecTxFailCount += + TxStaCnt0.field.TxFailCount; + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += + StaTx1.field.TxSuccess; + pAd->WlanCounters.RetryCount.u.LowPart += + StaTx1.field.TxRetransmit; + pAd->WlanCounters.FailedCount.u.LowPart += + TxStaCnt0.field.TxFailCount; + + /* if no traffic in the past 1-sec period, don't change TX rate, */ + /* but clear all bad history. because the bad history may affect the next */ + /* Chariot throughput test */ + AccuTxTotalCnt = + pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + if (TxTotalCnt) + TxErrorRatio = + ((TxRetransmit + + TxFailCount) * 100) / TxTotalCnt; + } else { + if (INFRA_ON(pAd) && (i == 1)) + Rssi = RTMPMaxRssi(pAd, + pRssi->AvgRssi0, + pRssi->AvgRssi1, + pRssi->AvgRssi2); + else + Rssi = RTMPMaxRssi(pAd, + pEntry->RssiSample.AvgRssi0, + pEntry->RssiSample.AvgRssi1, + pEntry->RssiSample.AvgRssi2); + + TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + + pEntry->OneSecTxRetryOkCount + + pEntry->OneSecTxFailCount; + + if (TxTotalCnt) + TxErrorRatio = + ((pEntry->OneSecTxRetryOkCount + + pEntry->OneSecTxFailCount) * 100) / + TxTotalCnt; + } + + if (TxTotalCnt) { + /* + Three AdHoc connections can not work normally if one AdHoc connection is disappeared from a heavy traffic environment generated by ping tool + We force to set LongRtyLimit and ShortRtyLimit to 0 to stop retransmitting packet, after a while, resoring original settings + */ + if (TxErrorRatio == 100) { + TX_RTY_CFG_STRUC TxRtyCfg, TxRtyCfgtmp; + unsigned long Index; + unsigned long MACValue; + + RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word); + TxRtyCfgtmp.word = TxRtyCfg.word; + TxRtyCfg.field.LongRtyLimit = 0x0; + TxRtyCfg.field.ShortRtyLimit = 0x0; + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word); + + RTMPusecDelay(1); + + Index = 0; + MACValue = 0; + do { + RTMP_IO_READ32(pAd, TXRXQ_PCNT, + &MACValue); + if ((MACValue & 0xffffff) == 0) + break; + Index++; + RTMPusecDelay(1000); + } while ((Index < 330) + && + (!RTMP_TEST_FLAG + (pAd, + fRTMP_ADAPTER_HALT_IN_PROGRESS))); + + RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word); + TxRtyCfg.field.LongRtyLimit = + TxRtyCfgtmp.field.LongRtyLimit; + TxRtyCfg.field.ShortRtyLimit = + TxRtyCfgtmp.field.ShortRtyLimit; + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word); + } } - //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) - if ((pEntry->RateLen == 8) - && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) - ) - {// G only AP - *ppTable = RateSwitchTable11G; - *pTableSize = RateSwitchTable11G[0]; - *pInitTxRateIdx = RateSwitchTable11G[1]; + CurrRateIdx = pEntry->CurrTxRateIndex; - break; + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, + &InitTxRateIdx); + + if (CurrRateIdx >= TableSize) { + CurrRateIdx = TableSize - 1; } + /* When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex. */ + /* So need to sync here. */ + pCurrTxRate = + (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5]; + if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS) + /*&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE) */ + ) { + + /* Need to sync Real Tx rate and our record. */ + /* Then return for next DRS. */ + pCurrTxRate = + (struct rt_rtmp_tx_rate_switch *) & pTable[(InitTxRateIdx + 1) + * 5]; + pEntry->CurrTxRateIndex = InitTxRateIdx; + MlmeSetTxRate(pAd, pEntry, pCurrTxRate); - { - //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) - if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)) - { // Legacy mode - if (pAd->CommonCfg.MaxTxRate <= RATE_11) - { - *ppTable = RateSwitchTable11B; - *pTableSize = RateSwitchTable11B[0]; - *pInitTxRateIdx = RateSwitchTable11B[1]; - } - else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11)) - { - *ppTable = RateSwitchTable11G; - *pTableSize = RateSwitchTable11G[0]; - *pInitTxRateIdx = RateSwitchTable11G[1]; + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + continue; + } + /* decide the next upgrade rate and downgrade rate, if any */ + if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) { + UpRateIdx = CurrRateIdx + 1; + DownRateIdx = CurrRateIdx - 1; + } else if (CurrRateIdx == 0) { + UpRateIdx = CurrRateIdx + 1; + DownRateIdx = CurrRateIdx; + } else if (CurrRateIdx == (TableSize - 1)) { + UpRateIdx = CurrRateIdx; + DownRateIdx = CurrRateIdx - 1; + } + pCurrTxRate = + (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5]; + + if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) { + TrainUp = + (pCurrTxRate->TrainUp + + (pCurrTxRate->TrainUp >> 1)); + TrainDown = + (pCurrTxRate->TrainDown + + (pCurrTxRate->TrainDown >> 1)); + } else { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + /*pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction; */ + + /* */ + /* Keep the last time TxRateChangeAction status. */ + /* */ + pEntry->LastTimeTxRateChangeAction = + pEntry->LastSecTxRateChangeAction; + + /* */ + /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */ + /* (criteria copied from RT2500 for Netopia case) */ + /* */ + if (TxTotalCnt <= 15) { + char idx = 0; + u8 TxRateIdx; + u8 MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = + 0, MCS5 = 0, MCS6 = 0, MCS7 = 0; + u8 MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0; + u8 MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; /* 3*3 */ + + /* check the existence and index of each needed MCS */ + while (idx < pTable[0]) { + pCurrTxRate = + (struct rt_rtmp_tx_rate_switch *) & pTable[(idx + 1) * + 5]; + + if (pCurrTxRate->CurrMCS == MCS_0) { + MCS0 = idx; + } else if (pCurrTxRate->CurrMCS == MCS_1) { + MCS1 = idx; + } else if (pCurrTxRate->CurrMCS == MCS_2) { + MCS2 = idx; + } else if (pCurrTxRate->CurrMCS == MCS_3) { + MCS3 = idx; + } else if (pCurrTxRate->CurrMCS == MCS_4) { + MCS4 = idx; + } else if (pCurrTxRate->CurrMCS == MCS_5) { + MCS5 = idx; + } else if (pCurrTxRate->CurrMCS == MCS_6) { + MCS6 = idx; } - else + /*else if (pCurrTxRate->CurrMCS == MCS_7) */ + else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) /* prevent the highest MCS using short GI when 1T and low throughput */ { - *ppTable = RateSwitchTable11BG; - *pTableSize = RateSwitchTable11BG[0]; - *pInitTxRateIdx = RateSwitchTable11BG[1]; + MCS7 = idx; + } else if (pCurrTxRate->CurrMCS == MCS_12) { + MCS12 = idx; + } else if (pCurrTxRate->CurrMCS == MCS_13) { + MCS13 = idx; + } else if (pCurrTxRate->CurrMCS == MCS_14) { + MCS14 = idx; } - break; - } - - if (pAd->LatchRfRegs.Channel <= 14) - { - if (pAd->CommonCfg.TxStream == 1) + else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) /*we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI */ { - *ppTable = RateSwitchTable11N1S; - *pTableSize = RateSwitchTable11N1S[0]; - *pInitTxRateIdx = RateSwitchTable11N1S[1]; - DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n")); - } - else + MCS15 = idx; + } else if (pCurrTxRate->CurrMCS == MCS_20) /* 3*3 */ { - *ppTable = RateSwitchTable11N2S; - *pTableSize = RateSwitchTable11N2S[0]; - *pInitTxRateIdx = RateSwitchTable11N2S[1]; - DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n")); + MCS20 = idx; + } else if (pCurrTxRate->CurrMCS == MCS_21) { + MCS21 = idx; + } else if (pCurrTxRate->CurrMCS == MCS_22) { + MCS22 = idx; + } else if (pCurrTxRate->CurrMCS == MCS_23) { + MCS23 = idx; } + idx++; } - else - { - if (pAd->CommonCfg.TxStream == 1) - { - *ppTable = RateSwitchTable11N1S; - *pTableSize = RateSwitchTable11N1S[0]; - *pInitTxRateIdx = RateSwitchTable11N1S[1]; - DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n")); + + if (pAd->LatchRfRegs.Channel <= 14) { + if (pAd->NicConfig2.field.ExternalLNAForG) { + RssiOffset = 2; + } else { + RssiOffset = 5; } - else - { - *ppTable = RateSwitchTable11N2SForABand; - *pTableSize = RateSwitchTable11N2SForABand[0]; - *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; - DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n")); + } else { + if (pAd->NicConfig2.field.ExternalLNAForA) { + RssiOffset = 5; + } else { + RssiOffset = 8; } } - DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n", - pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1])); - } - } while(FALSE); -} - -/* - ========================================================================== - Description: - This routine checks if there're other APs out there capable for - roaming. Caller should call this routine only when Link up in INFRA mode - and channel quality is below CQI_GOOD_THRESHOLD. - - IRQL = DISPATCH_LEVEL - - Output: - ========================================================================== - */ -VOID MlmeCheckForRoaming( - IN PRTMP_ADAPTER pAd, - IN ULONG Now32) -{ - USHORT i; - BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; - BSS_ENTRY *pBss; - - DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n")); - // put all roaming candidates into RoamTab, and sort in RSSI order - BssTableInit(pRoamTab); - for (i = 0; i < pAd->ScanTab.BssNr; i++) - { - pBss = &pAd->ScanTab.BssEntry[i]; + /*if (MCS15) */ + if ((pTable == RateSwitchTable11BGN3S) || (pTable == RateSwitchTable11N3S) || (pTable == RateSwitchTable)) { /* N mode with 3 stream // 3*3 */ + if (MCS23 && (Rssi >= -70)) + TxRateIdx = MCS23; + else if (MCS22 && (Rssi >= -72)) + TxRateIdx = MCS22; + else if (MCS21 && (Rssi >= -76)) + TxRateIdx = MCS21; + else if (MCS20 && (Rssi >= -78)) + TxRateIdx = MCS20; + else if (MCS4 && (Rssi >= -82)) + TxRateIdx = MCS4; + else if (MCS3 && (Rssi >= -84)) + TxRateIdx = MCS3; + else if (MCS2 && (Rssi >= -86)) + TxRateIdx = MCS2; + else if (MCS1 && (Rssi >= -88)) + TxRateIdx = MCS1; + else + TxRateIdx = MCS0; + } +/* else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable)) */ + else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) || (pTable == RateSwitchTable11N2S) || (pTable == RateSwitchTable11N2SForABand)) /* 3*3 */ + { /* N mode with 2 stream */ + if (MCS15 && (Rssi >= (-70 + RssiOffset))) + TxRateIdx = MCS15; + else if (MCS14 && (Rssi >= (-72 + RssiOffset))) + TxRateIdx = MCS14; + else if (MCS13 && (Rssi >= (-76 + RssiOffset))) + TxRateIdx = MCS13; + else if (MCS12 && (Rssi >= (-78 + RssiOffset))) + TxRateIdx = MCS12; + else if (MCS4 && (Rssi >= (-82 + RssiOffset))) + TxRateIdx = MCS4; + else if (MCS3 && (Rssi >= (-84 + RssiOffset))) + TxRateIdx = MCS3; + else if (MCS2 && (Rssi >= (-86 + RssiOffset))) + TxRateIdx = MCS2; + else if (MCS1 && (Rssi >= (-88 + RssiOffset))) + TxRateIdx = MCS1; + else + TxRateIdx = MCS0; + } else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S)) { /* N mode with 1 stream */ + if (MCS7 && (Rssi > (-72 + RssiOffset))) + TxRateIdx = MCS7; + else if (MCS6 && (Rssi > (-74 + RssiOffset))) + TxRateIdx = MCS6; + else if (MCS5 && (Rssi > (-77 + RssiOffset))) + TxRateIdx = MCS5; + else if (MCS4 && (Rssi > (-79 + RssiOffset))) + TxRateIdx = MCS4; + else if (MCS3 && (Rssi > (-81 + RssiOffset))) + TxRateIdx = MCS3; + else if (MCS2 && (Rssi > (-83 + RssiOffset))) + TxRateIdx = MCS2; + else if (MCS1 && (Rssi > (-86 + RssiOffset))) + TxRateIdx = MCS1; + else + TxRateIdx = MCS0; + } else { /* Legacy mode */ + if (MCS7 && (Rssi > -70)) + TxRateIdx = MCS7; + else if (MCS6 && (Rssi > -74)) + TxRateIdx = MCS6; + else if (MCS5 && (Rssi > -78)) + TxRateIdx = MCS5; + else if (MCS4 && (Rssi > -82)) + TxRateIdx = MCS4; + else if (MCS4 == 0) /* for B-only mode */ + TxRateIdx = MCS3; + else if (MCS3 && (Rssi > -85)) + TxRateIdx = MCS3; + else if (MCS2 && (Rssi > -87)) + TxRateIdx = MCS2; + else if (MCS1 && (Rssi > -90)) + TxRateIdx = MCS1; + else + TxRateIdx = MCS0; + } - if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32) - continue; // AP disappear - if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING) - continue; // RSSI too weak. forget it. - if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) - continue; // skip current AP - if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA)) - continue; // only AP with stronger RSSI is eligible for roaming + /* if (TxRateIdx != pAd->CommonCfg.TxRateIndex) */ + { + pEntry->CurrTxRateIndex = TxRateIdx; + pNextTxRate = + (struct rt_rtmp_tx_rate_switch *) & + pTable[(pEntry->CurrTxRateIndex + 1) * 5]; + MlmeSetTxRate(pAd, pEntry, pNextTxRate); + } - // AP passing all above rules is put into roaming candidate table - NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); - pRoamTab->BssNr += 1; - } + NdisZeroMemory(pEntry->TxQuality, + sizeof(u16)* + MAX_STEP_OF_TX_RATE_SWITCH); + NdisZeroMemory(pEntry->PER, + sizeof(u8)* + MAX_STEP_OF_TX_RATE_SWITCH); + pEntry->fLastSecAccordingRSSI = TRUE; + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); - if (pRoamTab->BssNr > 0) - { - // check CntlMachine.CurrState to avoid collision with NDIS SetOID request - if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) - { - pAd->RalinkCounters.PoorCQIRoamingCount ++; - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount)); - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); - RT28XX_MLME_HANDLER(pAd); + continue; } - } - DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr)); -} - -/* - ========================================================================== - Description: - This routine checks if there're other APs out there capable for - roaming. Caller should call this routine only when link up in INFRA mode - and channel quality is below CQI_GOOD_THRESHOLD. - - IRQL = DISPATCH_LEVEL - - Output: - ========================================================================== - */ -VOID MlmeCheckForFastRoaming( - IN PRTMP_ADAPTER pAd, - IN ULONG Now) -{ - USHORT i; - BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; - BSS_ENTRY *pBss; - - DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n")); - // put all roaming candidates into RoamTab, and sort in RSSI order - BssTableInit(pRoamTab); - for (i = 0; i < pAd->ScanTab.BssNr; i++) - { - pBss = &pAd->ScanTab.BssEntry[i]; - if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel)) - continue; // RSSI too weak. forget it. - if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) - continue; // skip current AP - if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)) - continue; // skip different SSID - if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA)) - continue; // skip AP without better RSSI - - DBGPRINT(RT_DEBUG_TRACE, ("LastRssi0 = %d, pBss->Rssi = %d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), pBss->Rssi)); - // AP passing all above rules is put into roaming candidate table - NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); - pRoamTab->BssNr += 1; - } + if (pEntry->fLastSecAccordingRSSI == TRUE) { + pEntry->fLastSecAccordingRSSI = FALSE; + pEntry->LastSecTxRateChangeAction = 0; + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); - if (pRoamTab->BssNr > 0) - { - // check CntlMachine.CurrState to avoid collision with NDIS SetOID request - if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) - { - pAd->RalinkCounters.PoorCQIRoamingCount ++; - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount)); - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); - RT28XX_MLME_HANDLER(pAd); - } - } - // Maybe site survey required - else - { - if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now) - { - // check CntlMachine.CurrState to avoid collision with NDIS SetOID request - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n")); - pAd->StaCfg.ScanCnt = 2; - pAd->StaCfg.LastScanTime = Now; - MlmeAutoScan(pAd); + continue; } - } - - DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr)); -} -/* - ========================================================================== - Description: - This routine calculates TxPER, RxPER of the past N-sec period. And - according to the calculation result, ChannelQuality is calculated here - to decide if current AP is still doing the job. + do { + BOOLEAN bTrainUpDown = FALSE; - If ChannelQuality is not good, a ROAMing attempt may be tried later. - Output: - StaCfg.ChannelQuality - 0..100 + pEntry->CurrTxRateStableTime++; - IRQL = DISPATCH_LEVEL + /* downgrade TX quality if PER >= Rate-Down threshold */ + if (TxErrorRatio >= TrainDown) { + bTrainUpDown = TRUE; + pEntry->TxQuality[CurrRateIdx] = + DRS_TX_QUALITY_WORST_BOUND; + } + /* upgrade TX quality if PER <= Rate-Up threshold */ + else if (TxErrorRatio <= TrainUp) { + bTrainUpDown = TRUE; + bUpgradeQuality = TRUE; + if (pEntry->TxQuality[CurrRateIdx]) + pEntry->TxQuality[CurrRateIdx]--; /* quality very good in CurrRate */ - NOTE: This routine decide channle quality based on RX CRC error ratio. - Caller should make sure a function call to NICUpdateRawCounters(pAd) - is performed right before this routine, so that this routine can decide - channel quality based on the most up-to-date information - ========================================================================== - */ -VOID MlmeCalculateChannelQuality( - IN PRTMP_ADAPTER pAd, - IN ULONG Now32) -{ - ULONG TxOkCnt, TxCnt, TxPER, TxPRR; - ULONG RxCnt, RxPER; - UCHAR NorRssi; - CHAR MaxRssi; - ULONG BeaconLostTime = BEACON_LOST_TIME; - - MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2); - - // - // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics - // - TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount; - TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount; - if (TxCnt < 5) - { - TxPER = 0; - TxPRR = 0; - } - else - { - TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt; - TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt; - } - - // - // calculate RX PER - don't take RxPER into consideration if too few sample - // - RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt; - if (RxCnt < 5) - RxPER = 0; - else - RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt; - - // - // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER - // - if (INFRA_ON(pAd) && - (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic - (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32)) - { - DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt)); - pAd->Mlme.ChannelQuality = 0; - } - else - { - // Normalize Rssi - if (MaxRssi > -40) - NorRssi = 100; - else if (MaxRssi < -90) - NorRssi = 0; - else - NorRssi = (MaxRssi + 90) * 2; - - // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) - pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi + - TX_WEIGHTING * (100 - TxPRR) + - RX_WEIGHTING* (100 - RxPER)) / 100; - if (pAd->Mlme.ChannelQuality >= 100) - pAd->Mlme.ChannelQuality = 100; - } - -} - -VOID MlmeSetTxRate( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PRTMP_TX_RATE_SWITCH pTxRate) -{ - UCHAR MaxMode = MODE_OFDM; - - MaxMode = MODE_HTGREENFIELD; - - if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2)) - pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE; - else - pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; - - if (pTxRate->CurrMCS < MCS_AUTO) - pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS; - - if (pAd->StaCfg.HTPhyMode.field.MCS > 7) - pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; - - if (ADHOC_ON(pAd)) - { - // If peer adhoc is b-only mode, we can't send 11g rate. - pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; - pEntry->HTPhyMode.field.STBC = STBC_NONE; - - // - // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary - // - pEntry->HTPhyMode.field.MODE = pTxRate->Mode; - pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI; - pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - - // Patch speed error in status page - pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE; - } - else - { - if (pTxRate->Mode <= MaxMode) - pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode; - - if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI)) - pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400; - else - pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; - - // Reexam each bandwidth's SGI support. - if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400) - { - if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE))) - pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; - if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE))) - pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; - } - - // Turn RTS/CTS rate to 6Mbps. - if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0)) - { - pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - if (pAd->MacTab.fAnyBASession) - { - AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); - } - else - { - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); - } - } - else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8)) - { - pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - if (pAd->MacTab.fAnyBASession) - { - AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); - } - else - { - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); - } - } - else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0)) - { - AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); - - } - else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8)) - { - AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); - } - - pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC; - pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI; - pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; - - if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) && - pAd->WIFItestbed.bGreenField) - pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD; - } - - pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word); -} - -/* - ========================================================================== - Description: - This routine calculates the acumulated TxPER of eaxh TxRate. And - according to the calculation result, change CommonCfg.TxRate which - is the stable TX Rate we expect the Radio situation could sustained. - - CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate} - Output: - CommonCfg.TxRate - - - IRQL = DISPATCH_LEVEL - - NOTE: - call this routine every second - ========================================================================== - */ -VOID MlmeDynamicTxRateSwitching( - IN PRTMP_ADAPTER pAd) -{ - UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx; - ULONG i, AccuTxTotalCnt = 0, TxTotalCnt; - ULONG TxErrorRatio = 0; - BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE; - PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL; - PUCHAR pTable; - UCHAR TableSize = 0; - UCHAR InitTxRateIdx = 0, TrainUp, TrainDown; - CHAR Rssi, RssiOffset = 0; - TX_STA_CNT1_STRUC StaTx1; - TX_STA_CNT0_STRUC TxStaCnt0; - ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; - MAC_TABLE_ENTRY *pEntry; - - // - // walk through MAC table, see if need to change AP's TX rate toward each entry - // - for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) - { - pEntry = &pAd->MacTab.Content[i]; - - // check if this entry need to switch rate automatically - if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) - continue; - - if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls)) - { -#ifdef RT2860 - Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2); -#endif -#ifdef RT2870 - Rssi = RTMPMaxRssi(pAd, - pAd->StaCfg.RssiSample.AvgRssi0, - pAd->StaCfg.RssiSample.AvgRssi1, - pAd->StaCfg.RssiSample.AvgRssi2); -#endif - - // Update statistic counter - RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); - RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); - pAd->bUpdateBcnCntDone = TRUE; - TxRetransmit = StaTx1.field.TxRetransmit; - TxSuccess = StaTx1.field.TxSuccess; - TxFailCount = TxStaCnt0.field.TxFailCount; - TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; - - pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; - pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; - pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount; - pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; - pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; - pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; - - // if no traffic in the past 1-sec period, don't change TX rate, - // but clear all bad history. because the bad history may affect the next - // Chariot throughput test - AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + - pAd->RalinkCounters.OneSecTxRetryOkCount + - pAd->RalinkCounters.OneSecTxFailCount; - - if (TxTotalCnt) - TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; - } - else - { -#ifdef RT2860 - Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2); -#endif -#ifdef RT2870 - if (INFRA_ON(pAd) && (i == 1)) - Rssi = RTMPMaxRssi(pAd, - pAd->StaCfg.RssiSample.AvgRssi0, - pAd->StaCfg.RssiSample.AvgRssi1, - pAd->StaCfg.RssiSample.AvgRssi2); - else - Rssi = RTMPMaxRssi(pAd, - pEntry->RssiSample.AvgRssi0, - pEntry->RssiSample.AvgRssi1, - pEntry->RssiSample.AvgRssi2); -#endif - - TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + - pEntry->OneSecTxRetryOkCount + - pEntry->OneSecTxFailCount; - - if (TxTotalCnt) - TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt; - } - - CurrRateIdx = pEntry->CurrTxRateIndex; - - MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); - - if (CurrRateIdx >= TableSize) - { - CurrRateIdx = TableSize - 1; - } - - // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex. - // So need to sync here. - pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; - if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS) - //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE) - ) - { - - // Need to sync Real Tx rate and our record. - // Then return for next DRS. - pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5]; - pEntry->CurrTxRateIndex = InitTxRateIdx; - MlmeSetTxRate(pAd, pEntry, pCurrTxRate); - - // reset all OneSecTx counters - RESET_ONE_SEC_TX_CNT(pEntry); - continue; - } - - // decide the next upgrade rate and downgrade rate, if any - if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) - { - UpRateIdx = CurrRateIdx + 1; - DownRateIdx = CurrRateIdx -1; - } - else if (CurrRateIdx == 0) - { - UpRateIdx = CurrRateIdx + 1; - DownRateIdx = CurrRateIdx; - } - else if (CurrRateIdx == (TableSize - 1)) - { - UpRateIdx = CurrRateIdx; - DownRateIdx = CurrRateIdx - 1; - } - - pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; - - if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) - { - TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); - TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); - } - else - { - TrainUp = pCurrTxRate->TrainUp; - TrainDown = pCurrTxRate->TrainDown; - } - - //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction; - - // - // Keep the last time TxRateChangeAction status. - // - pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction; - - - - // - // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI - // (criteria copied from RT2500 for Netopia case) - // - if (TxTotalCnt <= 15) - { - CHAR idx = 0; - UCHAR TxRateIdx; - //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0; - UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0; - UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0; - UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3 - - // check the existence and index of each needed MCS - while (idx < pTable[0]) - { - pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5]; - - if (pCurrTxRate->CurrMCS == MCS_0) - { - MCS0 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_1) - { - MCS1 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_2) - { - MCS2 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_3) - { - MCS3 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_4) - { - MCS4 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_5) - { - MCS5 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_6) - { - MCS6 = idx; - } - //else if (pCurrTxRate->CurrMCS == MCS_7) - else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput - { - MCS7 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_12) - { - MCS12 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_13) - { - MCS13 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_14) - { - MCS14 = idx; - } - else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) //we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI - { - MCS15 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3 - { - MCS20 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_21) - { - MCS21 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_22) - { - MCS22 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_23) - { - MCS23 = idx; - } - idx ++; - } - - if (pAd->LatchRfRegs.Channel <= 14) - { - if (pAd->NicConfig2.field.ExternalLNAForG) - { - RssiOffset = 2; - } - else - { - RssiOffset = 5; - } - } - else - { - if (pAd->NicConfig2.field.ExternalLNAForA) - { - RssiOffset = 5; - } - else - { - RssiOffset = 8; - } - } - - /*if (MCS15)*/ - if ((pTable == RateSwitchTable11BGN3S) || - (pTable == RateSwitchTable11N3S) || - (pTable == RateSwitchTable)) - {// N mode with 3 stream // 3*3 - if (MCS23 && (Rssi >= -70)) - TxRateIdx = MCS15; - else if (MCS22 && (Rssi >= -72)) - TxRateIdx = MCS14; - else if (MCS21 && (Rssi >= -76)) - TxRateIdx = MCS13; - else if (MCS20 && (Rssi >= -78)) - TxRateIdx = MCS12; - else if (MCS4 && (Rssi >= -82)) - TxRateIdx = MCS4; - else if (MCS3 && (Rssi >= -84)) - TxRateIdx = MCS3; - else if (MCS2 && (Rssi >= -86)) - TxRateIdx = MCS2; - else if (MCS1 && (Rssi >= -88)) - TxRateIdx = MCS1; - else - TxRateIdx = MCS0; - } - else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3 - {// N mode with 2 stream - if (MCS15 && (Rssi >= (-70+RssiOffset))) - TxRateIdx = MCS15; - else if (MCS14 && (Rssi >= (-72+RssiOffset))) - TxRateIdx = MCS14; - else if (MCS13 && (Rssi >= (-76+RssiOffset))) - TxRateIdx = MCS13; - else if (MCS12 && (Rssi >= (-78+RssiOffset))) - TxRateIdx = MCS12; - else if (MCS4 && (Rssi >= (-82+RssiOffset))) - TxRateIdx = MCS4; - else if (MCS3 && (Rssi >= (-84+RssiOffset))) - TxRateIdx = MCS3; - else if (MCS2 && (Rssi >= (-86+RssiOffset))) - TxRateIdx = MCS2; - else if (MCS1 && (Rssi >= (-88+RssiOffset))) - TxRateIdx = MCS1; - else - TxRateIdx = MCS0; - } - else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S)) - {// N mode with 1 stream - if (MCS7 && (Rssi > (-72+RssiOffset))) - TxRateIdx = MCS7; - else if (MCS6 && (Rssi > (-74+RssiOffset))) - TxRateIdx = MCS6; - else if (MCS5 && (Rssi > (-77+RssiOffset))) - TxRateIdx = MCS5; - else if (MCS4 && (Rssi > (-79+RssiOffset))) - TxRateIdx = MCS4; - else if (MCS3 && (Rssi > (-81+RssiOffset))) - TxRateIdx = MCS3; - else if (MCS2 && (Rssi > (-83+RssiOffset))) - TxRateIdx = MCS2; - else if (MCS1 && (Rssi > (-86+RssiOffset))) - TxRateIdx = MCS1; - else - TxRateIdx = MCS0; - } - else - {// Legacy mode - if (MCS7 && (Rssi > -70)) - TxRateIdx = MCS7; - else if (MCS6 && (Rssi > -74)) - TxRateIdx = MCS6; - else if (MCS5 && (Rssi > -78)) - TxRateIdx = MCS5; - else if (MCS4 && (Rssi > -82)) - TxRateIdx = MCS4; - else if (MCS4 == 0) // for B-only mode - TxRateIdx = MCS3; - else if (MCS3 && (Rssi > -85)) - TxRateIdx = MCS3; - else if (MCS2 && (Rssi > -87)) - TxRateIdx = MCS2; - else if (MCS1 && (Rssi > -90)) - TxRateIdx = MCS1; - else - TxRateIdx = MCS0; - } - - { - pEntry->CurrTxRateIndex = TxRateIdx; - pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5]; - MlmeSetTxRate(pAd, pEntry, pNextTxRate); - } - - NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); - NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); - pEntry->fLastSecAccordingRSSI = TRUE; - // reset all OneSecTx counters - RESET_ONE_SEC_TX_CNT(pEntry); - - continue; - } - - if (pEntry->fLastSecAccordingRSSI == TRUE) - { - pEntry->fLastSecAccordingRSSI = FALSE; - pEntry->LastSecTxRateChangeAction = 0; - // reset all OneSecTx counters - RESET_ONE_SEC_TX_CNT(pEntry); - - continue; - } - - do - { - BOOLEAN bTrainUpDown = FALSE; - - pEntry->CurrTxRateStableTime ++; - - // downgrade TX quality if PER >= Rate-Down threshold - if (TxErrorRatio >= TrainDown) - { - bTrainUpDown = TRUE; - pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; - } - // upgrade TX quality if PER <= Rate-Up threshold - else if (TxErrorRatio <= TrainUp) - { - bTrainUpDown = TRUE; - bUpgradeQuality = TRUE; - if (pEntry->TxQuality[CurrRateIdx]) - pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate - - if (pEntry->TxRateUpPenalty) - pEntry->TxRateUpPenalty --; - else if (pEntry->TxQuality[UpRateIdx]) - pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality - } - - pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio; - - if (bTrainUpDown) - { - // perform DRS - consider TxRate Down first, then rate up. - if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND)) - { - pEntry->CurrTxRateIndex = DownRateIdx; - } - else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0)) - { - pEntry->CurrTxRateIndex = UpRateIdx; - } - } - } while (FALSE); - - // if rate-up happen, clear all bad history of all TX rates - if (pEntry->CurrTxRateIndex > CurrRateIdx) - { - pEntry->CurrTxRateStableTime = 0; - pEntry->TxRateUpPenalty = 0; - pEntry->LastSecTxRateChangeAction = 1; // rate UP - NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); - NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); - - // - // For TxRate fast train up - // - if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) - { - RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100); - - pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; - } - bTxRateChanged = TRUE; - } - // if rate-down happen, only clear DownRate's bad history - else if (pEntry->CurrTxRateIndex < CurrRateIdx) - { - pEntry->CurrTxRateStableTime = 0; - pEntry->TxRateUpPenalty = 0; // no penalty - pEntry->LastSecTxRateChangeAction = 2; // rate DOWN - pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; - pEntry->PER[pEntry->CurrTxRateIndex] = 0; - - // - // For TxRate fast train down - // - if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) - { - RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100); - - pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; - } - bTxRateChanged = TRUE; - } - else - { - pEntry->LastSecTxRateChangeAction = 0; // rate no change - bTxRateChanged = FALSE; - } - - pEntry->LastTxOkCount = TxSuccess; - - // reset all OneSecTx counters - RESET_ONE_SEC_TX_CNT(pEntry); - - pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5]; - if (bTxRateChanged && pNextTxRate) - { - MlmeSetTxRate(pAd, pEntry, pNextTxRate); - } - } -} - -/* - ======================================================================== - Routine Description: - Station side, Auto TxRate faster train up timer call back function. - - Arguments: - SystemSpecific1 - Not used. - FunctionContext - Pointer to our Adapter context. - SystemSpecific2 - Not used. - SystemSpecific3 - Not used. - - Return Value: - None - - ======================================================================== -*/ -VOID StaQuickResponeForRateUpExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; - UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0; - ULONG TxTotalCnt; - ULONG TxErrorRatio = 0; -#ifdef RT2860 - BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE; -#endif -#ifdef RT2870 - BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE; -#endif - PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL; - PUCHAR pTable; - UCHAR TableSize = 0; - UCHAR InitTxRateIdx = 0, TrainUp, TrainDown; - TX_STA_CNT1_STRUC StaTx1; - TX_STA_CNT0_STRUC TxStaCnt0; - CHAR Rssi, ratio; - ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; - MAC_TABLE_ENTRY *pEntry; - ULONG i; - - pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; - - // - // walk through MAC table, see if need to change AP's TX rate toward each entry - // - for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) - { - pEntry = &pAd->MacTab.Content[i]; - - // check if this entry need to switch rate automatically - if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) - continue; - -#ifdef RT2860 - //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2); - if (pAd->Antenna.field.TxPath > 1) - Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1; - else - Rssi = pAd->StaCfg.RssiSample.AvgRssi0; -#endif -#ifdef RT2870 - if (INFRA_ON(pAd) && (i == 1)) - Rssi = RTMPMaxRssi(pAd, - pAd->StaCfg.RssiSample.AvgRssi0, - pAd->StaCfg.RssiSample.AvgRssi1, - pAd->StaCfg.RssiSample.AvgRssi2); - else - Rssi = RTMPMaxRssi(pAd, - pEntry->RssiSample.AvgRssi0, - pEntry->RssiSample.AvgRssi1, - pEntry->RssiSample.AvgRssi2); -#endif - - CurrRateIdx = pAd->CommonCfg.TxRateIndex; - - MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); - - // decide the next upgrade rate and downgrade rate, if any - if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) - { - UpRateIdx = CurrRateIdx + 1; - DownRateIdx = CurrRateIdx -1; - } - else if (CurrRateIdx == 0) - { - UpRateIdx = CurrRateIdx + 1; - DownRateIdx = CurrRateIdx; - } - else if (CurrRateIdx == (TableSize - 1)) - { - UpRateIdx = CurrRateIdx; - DownRateIdx = CurrRateIdx - 1; - } - - pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; - - if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) - { - TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); - TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); - } - else - { - TrainUp = pCurrTxRate->TrainUp; - TrainDown = pCurrTxRate->TrainDown; - } - - if (pAd->MacTab.Size == 1) - { - // Update statistic counter - RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); - RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); - - TxRetransmit = StaTx1.field.TxRetransmit; - TxSuccess = StaTx1.field.TxSuccess; - TxFailCount = TxStaCnt0.field.TxFailCount; - TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; - - pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; - pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; - pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount; - pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; - pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; - pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; - - if (TxTotalCnt) - TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; - } - else - { - TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + - pEntry->OneSecTxRetryOkCount + - pEntry->OneSecTxFailCount; - - if (TxTotalCnt) - TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt; - } - - - // - // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI - // (criteria copied from RT2500 for Netopia case) - // - if (TxTotalCnt <= 12) - { - NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); - NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); - - if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx)) - { - pAd->CommonCfg.TxRateIndex = DownRateIdx; - pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; - } - else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) - { - pAd->CommonCfg.TxRateIndex = UpRateIdx; - } - - DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n")); - return; - } - - do - { - ULONG OneSecTxNoRetryOKRationCount; - - if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0) - ratio = 5; - else - ratio = 4; - - // downgrade TX quality if PER >= Rate-Down threshold - if (TxErrorRatio >= TrainDown) - { - pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; - } - - pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio; - - OneSecTxNoRetryOKRationCount = (TxSuccess * ratio); - - // perform DRS - consider TxRate Down first, then rate up. - if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx)) - { - if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) - { - pAd->CommonCfg.TxRateIndex = DownRateIdx; - pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; - - } - - } - else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) - { - if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown)) - { - - } - else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) - { - pAd->CommonCfg.TxRateIndex = UpRateIdx; - } - } - }while (FALSE); - - // if rate-up happen, clear all bad history of all TX rates - if (pAd->CommonCfg.TxRateIndex > CurrRateIdx) - { - pAd->DrsCounters.TxRateUpPenalty = 0; - NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); - NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); -#ifdef RT2870 - bTxRateChanged = TRUE; -#endif - } - // if rate-down happen, only clear DownRate's bad history - else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx) - { - DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex)); - - pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty - pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0; - pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0; -#ifdef RT2870 - bTxRateChanged = TRUE; -#endif - } - else - { - bTxRateChanged = FALSE; - } - - pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5]; - if (bTxRateChanged && pNextTxRate) - { - MlmeSetTxRate(pAd, pEntry, pNextTxRate); - } - } -} - -/* - ========================================================================== - Description: - This routine is executed periodically inside MlmePeriodicExec() after - association with an AP. - It checks if StaCfg.Psm is consistent with user policy (recorded in - StaCfg.WindowsPowerMode). If not, enforce user policy. However, - there're some conditions to consider: - 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all - the time when Mibss==TRUE - 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE - if outgoing traffic available in TxRing or MgmtRing. - Output: - 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID MlmeCheckPsmChange( - IN PRTMP_ADAPTER pAd, - IN ULONG Now32) -{ - ULONG PowerMode; - - // condition - - // 1. Psm maybe ON only happen in INFRASTRUCTURE mode - // 2. user wants either MAX_PSP or FAST_PSP - // 3. but current psm is not in PWR_SAVE - // 4. CNTL state machine is not doing SCANning - // 5. no TX SUCCESS event for the past 1-sec period -#ifdef NDIS51_MINIPORT - if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery) - PowerMode = pAd->StaCfg.WindowsBatteryPowerMode; - else -#endif - PowerMode = pAd->StaCfg.WindowsPowerMode; - - if (INFRA_ON(pAd) && - (PowerMode != Ndis802_11PowerModeCAM) && - (pAd->StaCfg.Psm == PWR_ACTIVE) && -#ifdef RT2860 - RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)) -#else - (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) -#endif - { - // add by johnli, use Rx OK data count per second to calculate throughput - // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria - // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps - if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) && - (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) || - ((pAd->StaCfg.HTPhyMode.field.MCS > 3) && - (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400))) - { - // Get this time - NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime); - pAd->RalinkCounters.RxCountSinceLastNULL = 0; - MlmeSetPsmBit(pAd, PWR_SAVE); - if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) - { - RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE); - } - else - { - RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); - } - } - } -} - -// IRQL = PASSIVE_LEVEL -// IRQL = DISPATCH_LEVEL -VOID MlmeSetPsmBit( - IN PRTMP_ADAPTER pAd, - IN USHORT psm) -{ - AUTO_RSP_CFG_STRUC csr4; - - pAd->StaCfg.Psm = psm; - RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); - csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0; - RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); - - DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm)); -} - -// IRQL = DISPATCH_LEVEL -VOID MlmeSetTxPreamble( - IN PRTMP_ADAPTER pAd, - IN USHORT TxPreamble) -{ - AUTO_RSP_CFG_STRUC csr4; - - // - // Always use Long preamble before verifiation short preamble functionality works well. - // Todo: remove the following line if short preamble functionality works - // - //TxPreamble = Rt802_11PreambleLong; - - RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); - if (TxPreamble == Rt802_11PreambleLong) - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n")); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); - csr4.field.AutoResponderPreamble = 0; - } - else - { - // NOTE: 1Mbps should always use long preamble - DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n")); - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); - csr4.field.AutoResponderPreamble = 1; - } - - RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); -} - -/* - ========================================================================== - Description: - Update basic rate bitmap - ========================================================================== - */ - -VOID UpdateBasicRateBitmap( - IN PRTMP_ADAPTER pAdapter) -{ - INT i, j; - /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ - UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; - UCHAR *sup_p = pAdapter->CommonCfg.SupRate; - UCHAR *ext_p = pAdapter->CommonCfg.ExtRate; - ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap; - - - /* if A mode, always use fix BasicRateBitMap */ - //if (pAdapter->CommonCfg.Channel == PHY_11A) - if (pAdapter->CommonCfg.Channel > 14) - pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */ - /* End of if */ - - if (pAdapter->CommonCfg.BasicRateBitmap > 4095) - { - /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */ - return; - } /* End of if */ - - for(i=0; iCommonCfg.DesireRate[i] & 0x7f) - { - case 2: Rate = RATE_1; num++; break; - case 4: Rate = RATE_2; num++; break; - case 11: Rate = RATE_5_5; num++; break; - case 22: Rate = RATE_11; num++; break; - case 12: Rate = RATE_6; num++; break; - case 18: Rate = RATE_9; num++; break; - case 24: Rate = RATE_12; num++; break; - case 36: Rate = RATE_18; num++; break; - case 48: Rate = RATE_24; num++; break; - case 72: Rate = RATE_36; num++; break; - case 96: Rate = RATE_48; num++; break; - case 108: Rate = RATE_54; num++; break; - //default: Rate = RATE_1; break; - } - if (MaxDesire < Rate) MaxDesire = Rate; - } - -//=========================================================================== -//=========================================================================== - { - pHtPhy = &pAd->StaCfg.HTPhyMode; - pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; - pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; - - auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; - HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS; - - if ((pAd->StaCfg.BssType == BSS_ADHOC) && - (pAd->CommonCfg.PhyMode == PHY_11B) && - (MaxDesire > RATE_11)) - { - MaxDesire = RATE_11; - } - } - - pAd->CommonCfg.MaxDesiredRate = MaxDesire; - pMinHtPhy->word = 0; - pMaxHtPhy->word = 0; - pHtPhy->word = 0; - - // Auto rate switching is enabled only if more than one DESIRED RATES are - // specified; otherwise disabled - if (num <= 1) - { - *auto_rate_cur_p = FALSE; - } - else - { - *auto_rate_cur_p = TRUE; - } - -#if 1 - if (HtMcs != MCS_AUTO) - { - *auto_rate_cur_p = FALSE; - } - else - { - *auto_rate_cur_p = TRUE; - } -#endif - - if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) - { - pSupRate = &pAd->StaActive.SupRate[0]; - pExtRate = &pAd->StaActive.ExtRate[0]; - SupRateLen = pAd->StaActive.SupRateLen; - ExtRateLen = pAd->StaActive.ExtRateLen; - } - else - { - pSupRate = &pAd->CommonCfg.SupRate[0]; - pExtRate = &pAd->CommonCfg.ExtRate[0]; - SupRateLen = pAd->CommonCfg.SupRateLen; - ExtRateLen = pAd->CommonCfg.ExtRateLen; - } - - // find max supported rate - for (i=0; i Rate) MinSupport = Rate; - } - - for (i=0; i Rate) MinSupport = Rate; - } - - RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap); - - // calculate the exptected ACK rate for each TX rate. This info is used to caculate - // the DURATION field of outgoing uniicast DATA/MGMT frame - for (i=0; iCommonCfg.ExpectedACKRate[i] = CurrBasicRate; - } - - DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire])); - // max tx rate = min {max desire rate, max supported rate} - if (MaxSupport < MaxDesire) - pAd->CommonCfg.MaxTxRate = MaxSupport; - else - pAd->CommonCfg.MaxTxRate = MaxDesire; - - pAd->CommonCfg.MinTxRate = MinSupport; - if (*auto_rate_cur_p) - { - short dbm = 0; - - dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta; - - if (bLinkUp == TRUE) - pAd->CommonCfg.TxRate = RATE_24; - else - pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; - - if (dbm < -75) - pAd->CommonCfg.TxRate = RATE_11; - else if (dbm < -70) - pAd->CommonCfg.TxRate = RATE_24; - - // should never exceed MaxTxRate (consider 11B-only mode) - if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate) - pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; - - pAd->CommonCfg.TxRateIndex = 0; - } - else - { - pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; - pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate; - pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK; - - pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC; - pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI; - pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS; - pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE; - } - - if (pAd->CommonCfg.TxRate <= RATE_11) - { - pMaxHtPhy->field.MODE = MODE_CCK; - pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate; - pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate; - } - else - { - pMaxHtPhy->field.MODE = MODE_OFDM; - pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate]; - if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54)) - {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];} - else - {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;} - } - - pHtPhy->word = (pMaxHtPhy->word); - if (bLinkUp && (pAd->OpMode == OPMODE_STA)) - { - pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word; - pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word; - pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word; - } - else - { - switch (pAd->CommonCfg.PhyMode) - { - case PHY_11BG_MIXED: - case PHY_11B: - case PHY_11BGN_MIXED: - pAd->CommonCfg.MlmeRate = RATE_1; - pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; - pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; - pAd->CommonCfg.RtsRate = RATE_11; - break; - case PHY_11G: - case PHY_11A: - case PHY_11AGN_MIXED: - case PHY_11GN_MIXED: - case PHY_11N_2_4G: - case PHY_11AN_MIXED: - case PHY_11N_5G: - pAd->CommonCfg.MlmeRate = RATE_6; - pAd->CommonCfg.RtsRate = RATE_6; - pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; - pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; - break; - case PHY_11ABG_MIXED: - case PHY_11ABGN_MIXED: - if (pAd->CommonCfg.Channel <= 14) - { - pAd->CommonCfg.MlmeRate = RATE_1; - pAd->CommonCfg.RtsRate = RATE_1; - pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; - pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; - } - else - { - pAd->CommonCfg.MlmeRate = RATE_6; - pAd->CommonCfg.RtsRate = RATE_6; - pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; - pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; - } - break; - default: // error - pAd->CommonCfg.MlmeRate = RATE_6; - pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; - pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; - pAd->CommonCfg.RtsRate = RATE_1; - break; - } - // - // Keep Basic Mlme Rate. - // - pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word; - if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM) - pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24]; - else - pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1; - pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate; - } - - DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n", - RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate], - /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p)); - DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n", - RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap)); - DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n", - pAd->CommonCfg.MlmeTransmit.word, pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word )); -} - -/* - ========================================================================== - Description: - This function update HT Rate setting. - Input Wcid value is valid for 2 case : - 1. it's used for Station in infra mode that copy AP rate to Mactable. - 2. OR Station in adhoc mode to copy peer's HT rate to Mactable. - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID MlmeUpdateHtTxRates( - IN PRTMP_ADAPTER pAd, - IN UCHAR apidx) -{ - UCHAR StbcMcs; //j, StbcMcs, bitmask; - CHAR i; // 3*3 - RT_HT_CAPABILITY *pRtHtCap = NULL; - RT_HT_PHY_INFO *pActiveHtPhy = NULL; - ULONG BasicMCS; - UCHAR j, bitmask; - PRT_HT_PHY_INFO pDesireHtPhy = NULL; - PHTTRANSMIT_SETTING pHtPhy = NULL; - PHTTRANSMIT_SETTING pMaxHtPhy = NULL; - PHTTRANSMIT_SETTING pMinHtPhy = NULL; - BOOLEAN *auto_rate_cur_p; - - DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n")); - - auto_rate_cur_p = NULL; - - { - pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; - pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; - pHtPhy = &pAd->StaCfg.HTPhyMode; - pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; - pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; - - auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; - } - - if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) - { - if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) - return; - - pRtHtCap = &pAd->StaActive.SupportedHtPhy; - pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo; - StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs; - BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16); - if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2)) - pMaxHtPhy->field.STBC = STBC_USE; - else - pMaxHtPhy->field.STBC = STBC_NONE; - } - else - { - if (pDesireHtPhy->bHtEnable == FALSE) - return; - - pRtHtCap = &pAd->CommonCfg.DesiredHtPhy; - StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs; - BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16); - if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2)) - pMaxHtPhy->field.STBC = STBC_USE; - else - pMaxHtPhy->field.STBC = STBC_NONE; - } - - // Decide MAX ht rate. - if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) - pMaxHtPhy->field.MODE = MODE_HTGREENFIELD; - else - pMaxHtPhy->field.MODE = MODE_HTMIX; - - if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth)) - pMaxHtPhy->field.BW = BW_40; - else - pMaxHtPhy->field.BW = BW_20; - - if (pMaxHtPhy->field.BW == BW_20) - pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20); - else - pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40); - - for (i=23; i>=0; i--) // 3*3 - { - j = i/8; - bitmask = (1<<(i-(j*8))); - - if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask)) - { - pMaxHtPhy->field.MCS = i; - break; - } - - if (i==0) - break; - } - - // Copy MIN ht rate. rt2860??? - pMinHtPhy->field.BW = BW_20; - pMinHtPhy->field.MCS = 0; - pMinHtPhy->field.STBC = 0; - pMinHtPhy->field.ShortGI = 0; - //If STA assigns fixed rate. update to fixed here. - if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)) - { - if (pDesireHtPhy->MCSSet[4] != 0) - { - pMaxHtPhy->field.MCS = 32; - pMinHtPhy->field.MCS = 32; - DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS)); - } - - for (i=23; (CHAR)i >= 0; i--) // 3*3 - { - j = i/8; - bitmask = (1<<(i-(j*8))); - if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask)) - { - pMaxHtPhy->field.MCS = i; - pMinHtPhy->field.MCS = i; - break; - } - if (i==0) - break; - } - } - - // Decide ht rate - pHtPhy->field.STBC = pMaxHtPhy->field.STBC; - pHtPhy->field.BW = pMaxHtPhy->field.BW; - pHtPhy->field.MODE = pMaxHtPhy->field.MODE; - pHtPhy->field.MCS = pMaxHtPhy->field.MCS; - pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI; - - // use default now. rt2860 - if (pDesireHtPhy->MCSSet[0] != 0xff) - *auto_rate_cur_p = FALSE; - else - *auto_rate_cur_p = TRUE; - - DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize )); - DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS, - pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE)); - DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n")); -} - -// IRQL = DISPATCH_LEVEL -VOID MlmeRadioOff( - IN PRTMP_ADAPTER pAd) -{ - RT28XX_MLME_RADIO_OFF(pAd); -} - -// IRQL = DISPATCH_LEVEL -VOID MlmeRadioOn( - IN PRTMP_ADAPTER pAd) -{ - RT28XX_MLME_RADIO_ON(pAd); -} - -// =========================================================================================== -// bss_table.c -// =========================================================================================== - - -/*! \brief initialize BSS table - * \param p_tab pointer to the table - * \return none - * \pre - * \post - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - */ -VOID BssTableInit( - IN BSS_TABLE *Tab) -{ - int i; - - Tab->BssNr = 0; - Tab->BssOverlapNr = 0; - for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) - { - NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY)); - Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value - } -} - -VOID BATableInit( - IN PRTMP_ADAPTER pAd, - IN BA_TABLE *Tab) -{ - int i; - - Tab->numAsOriginator = 0; - Tab->numAsRecipient = 0; - NdisAllocateSpinLock(&pAd->BATabLock); - for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) - { - Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE; - NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock)); - } - for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) - { - Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE; - } -} - -/*! \brief search the BSS table by SSID - * \param p_tab pointer to the bss table - * \param ssid SSID string - * \return index of the table, BSS_NOT_FOUND if not in the table - * \pre - * \post - * \note search by sequential search - - IRQL = DISPATCH_LEVEL - - */ -ULONG BssTableSearch( - IN BSS_TABLE *Tab, - IN PUCHAR pBssid, - IN UCHAR Channel) -{ - UCHAR i; - - for (i = 0; i < Tab->BssNr; i++) - { - // - // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. - // We should distinguish this case. - // - if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || - ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && - MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) - { - return i; - } - } - return (ULONG)BSS_NOT_FOUND; -} - -ULONG BssSsidTableSearch( - IN BSS_TABLE *Tab, - IN PUCHAR pBssid, - IN PUCHAR pSsid, - IN UCHAR SsidLen, - IN UCHAR Channel) -{ - UCHAR i; - - for (i = 0; i < Tab->BssNr; i++) - { - // - // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. - // We should distinguish this case. - // - if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || - ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && - MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) && - SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen)) - { - return i; - } - } - return (ULONG)BSS_NOT_FOUND; -} - -ULONG BssTableSearchWithSSID( - IN BSS_TABLE *Tab, - IN PUCHAR Bssid, - IN PUCHAR pSsid, - IN UCHAR SsidLen, - IN UCHAR Channel) -{ - UCHAR i; - - for (i = 0; i < Tab->BssNr; i++) - { - if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || - ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && - MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) && - (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) || - (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) || - (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen)))) - { - return i; - } - } - return (ULONG)BSS_NOT_FOUND; -} - -// IRQL = DISPATCH_LEVEL -VOID BssTableDeleteEntry( - IN OUT BSS_TABLE *Tab, - IN PUCHAR pBssid, - IN UCHAR Channel) -{ - UCHAR i, j; - - for (i = 0; i < Tab->BssNr; i++) - { - if ((Tab->BssEntry[i].Channel == Channel) && - (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) - { - for (j = i; j < Tab->BssNr - 1; j++) - { - NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY)); - } - NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY)); - Tab->BssNr -= 1; - return; - } - } -} - -/* - ======================================================================== - Routine Description: - Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed. - - Arguments: - // IRQL = DISPATCH_LEVEL - ======================================================================== -*/ -VOID BATableDeleteORIEntry( - IN OUT PRTMP_ADAPTER pAd, - IN BA_ORI_ENTRY *pBAORIEntry) -{ - - if (pBAORIEntry->ORI_BA_Status != Originator_NONE) - { - NdisAcquireSpinLock(&pAd->BATabLock); - if (pBAORIEntry->ORI_BA_Status == Originator_Done) - { - pAd->BATable.numAsOriginator -= 1; - DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient)); - // Erase Bitmap flag. - } - pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here - pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here - pBAORIEntry->ORI_BA_Status = Originator_NONE; - pBAORIEntry->Token = 1; - // Not clear Sequence here. - NdisReleaseSpinLock(&pAd->BATabLock); - } -} - -/*! \brief - * \param - * \return - * \pre - * \post - - IRQL = DISPATCH_LEVEL - - */ -VOID BssEntrySet( - IN PRTMP_ADAPTER pAd, - OUT BSS_ENTRY *pBss, - IN PUCHAR pBssid, - IN CHAR Ssid[], - IN UCHAR SsidLen, - IN UCHAR BssType, - IN USHORT BeaconPeriod, - IN PCF_PARM pCfParm, - IN USHORT AtimWin, - IN USHORT CapabilityInfo, - IN UCHAR SupRate[], - IN UCHAR SupRateLen, - IN UCHAR ExtRate[], - IN UCHAR ExtRateLen, - IN HT_CAPABILITY_IE *pHtCapability, - IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE - IN UCHAR HtCapabilityLen, - IN UCHAR AddHtInfoLen, - IN UCHAR NewExtChanOffset, - IN UCHAR Channel, - IN CHAR Rssi, - IN LARGE_INTEGER TimeStamp, - IN UCHAR CkipFlag, - IN PEDCA_PARM pEdcaParm, - IN PQOS_CAPABILITY_PARM pQosCapability, - IN PQBSS_LOAD_PARM pQbssLoad, - IN USHORT LengthVIE, - IN PNDIS_802_11_VARIABLE_IEs pVIE) -{ - COPY_MAC_ADDR(pBss->Bssid, pBssid); - // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID - pBss->Hidden = 1; - if (SsidLen > 0) - { - // For hidden SSID AP, it might send beacon with SSID len equal to 0 - // Or send beacon /probe response with SSID len matching real SSID length, - // but SSID is all zero. such as "00-00-00-00" with length 4. - // We have to prevent this case overwrite correct table - if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) - { - NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID); - NdisMoveMemory(pBss->Ssid, Ssid, SsidLen); - pBss->SsidLen = SsidLen; - pBss->Hidden = 0; - } - } - else - pBss->SsidLen = 0; - pBss->BssType = BssType; - pBss->BeaconPeriod = BeaconPeriod; - if (BssType == BSS_INFRA) - { - if (pCfParm->bValid) - { - pBss->CfpCount = pCfParm->CfpCount; - pBss->CfpPeriod = pCfParm->CfpPeriod; - pBss->CfpMaxDuration = pCfParm->CfpMaxDuration; - pBss->CfpDurRemaining = pCfParm->CfpDurRemaining; - } - } - else - { - pBss->AtimWin = AtimWin; - } - - pBss->CapabilityInfo = CapabilityInfo; - // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES - // Combine with AuthMode, they will decide the connection methods. - pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo); - ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES); - if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) - NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen); - else - NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES); - pBss->SupRateLen = SupRateLen; - ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES); - NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen); - NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen); - NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen); - pBss->NewExtChanOffset = NewExtChanOffset; - pBss->ExtRateLen = ExtRateLen; - pBss->Channel = Channel; - pBss->CentralChannel = Channel; - pBss->Rssi = Rssi; - // Update CkipFlag. if not exists, the value is 0x0 - pBss->CkipFlag = CkipFlag; - - // New for microsoft Fixed IEs - NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8); - pBss->FixIEs.BeaconInterval = BeaconPeriod; - pBss->FixIEs.Capabilities = CapabilityInfo; - - // New for microsoft Variable IEs - if (LengthVIE != 0) - { - pBss->VarIELen = LengthVIE; - NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen); - } - else - { - pBss->VarIELen = 0; - } - - pBss->AddHtInfoLen = 0; - pBss->HtCapabilityLen = 0; - - if (HtCapabilityLen> 0) - { - pBss->HtCapabilityLen = HtCapabilityLen; - NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen); - if (AddHtInfoLen > 0) - { - pBss->AddHtInfoLen = AddHtInfoLen; - NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen); - - if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) - { - pBss->CentralChannel = pAddHtInfo->ControlChan - 2; - } - else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) - { - pBss->CentralChannel = pAddHtInfo->ControlChan + 2; - } - } - } - - BssCipherParse(pBss); - - // new for QOS - if (pEdcaParm) - NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM)); - else - pBss->EdcaParm.bValid = FALSE; - if (pQosCapability) - NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM)); - else - pBss->QosCapability.bValid = FALSE; - if (pQbssLoad) - NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM)); - else - pBss->QbssLoad.bValid = FALSE; - - { - PEID_STRUCT pEid; - USHORT Length = 0; - - - NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN); - NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN); - - pEid = (PEID_STRUCT) pVIE; - - while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE) - { - switch(pEid->Eid) - { - case IE_WPA: - if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) - { - if ((pEid->Len + 2) > MAX_CUSTOM_LEN) - { - pBss->WpaIE.IELen = 0; - break; - } - pBss->WpaIE.IELen = pEid->Len + 2; - NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen); - } - break; - case IE_RSN: - if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) - { - if ((pEid->Len + 2) > MAX_CUSTOM_LEN) - { - pBss->RsnIE.IELen = 0; - break; - } - pBss->RsnIE.IELen = pEid->Len + 2; - NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen); - } - break; - } - Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len] - pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); - } - } -} - -/*! - * \brief insert an entry into the bss table - * \param p_tab The BSS table - * \param Bssid BSSID - * \param ssid SSID - * \param ssid_len Length of SSID - * \param bss_type - * \param beacon_period - * \param timestamp - * \param p_cf - * \param atim_win - * \param cap - * \param rates - * \param rates_len - * \param channel_idx - * \return none - * \pre - * \post - * \note If SSID is identical, the old entry will be replaced by the new one - - IRQL = DISPATCH_LEVEL - - */ -ULONG BssTableSetEntry( - IN PRTMP_ADAPTER pAd, - OUT BSS_TABLE *Tab, - IN PUCHAR pBssid, - IN CHAR Ssid[], - IN UCHAR SsidLen, - IN UCHAR BssType, - IN USHORT BeaconPeriod, - IN CF_PARM *CfParm, - IN USHORT AtimWin, - IN USHORT CapabilityInfo, - IN UCHAR SupRate[], - IN UCHAR SupRateLen, - IN UCHAR ExtRate[], - IN UCHAR ExtRateLen, - IN HT_CAPABILITY_IE *pHtCapability, - IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE - IN UCHAR HtCapabilityLen, - IN UCHAR AddHtInfoLen, - IN UCHAR NewExtChanOffset, - IN UCHAR ChannelNo, - IN CHAR Rssi, - IN LARGE_INTEGER TimeStamp, - IN UCHAR CkipFlag, - IN PEDCA_PARM pEdcaParm, - IN PQOS_CAPABILITY_PARM pQosCapability, - IN PQBSS_LOAD_PARM pQbssLoad, - IN USHORT LengthVIE, - IN PNDIS_802_11_VARIABLE_IEs pVIE) -{ - ULONG Idx; - - Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo); - if (Idx == BSS_NOT_FOUND) - { - if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) - { - // - // It may happen when BSS Table was full. - // The desired AP will not be added into BSS Table - // In this case, if we found the desired AP then overwrite BSS Table. - // - if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) || - SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen)) - { - Idx = Tab->BssOverlapNr; - BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin, - CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, - NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); - Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE; - } - return Idx; - } - else - { - return BSS_NOT_FOUND; - } - } - Idx = Tab->BssNr; - BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin, - CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, - NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); - Tab->BssNr++; - } - else - { - /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */ - if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) || - (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen))) - { - BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin, - CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, - NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); - } - } - - return Idx; -} - -// IRQL = DISPATCH_LEVEL -VOID BssTableSsidSort( - IN PRTMP_ADAPTER pAd, - OUT BSS_TABLE *OutTab, - IN CHAR Ssid[], - IN UCHAR SsidLen) -{ - INT i; - BssTableInit(OutTab); - - for (i = 0; i < pAd->ScanTab.BssNr; i++) - { - BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i]; - BOOLEAN bIsHiddenApIncluded = FALSE; - - if (((pAd->CommonCfg.bIEEE80211H == 1) && - (pAd->MlmeAux.Channel > 14) && - RadarChannelCheck(pAd, pInBss->Channel)) - ) - { - if (pInBss->Hidden) - bIsHiddenApIncluded = TRUE; - } - - if ((pInBss->BssType == pAd->StaCfg.BssType) && - (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded)) - { - BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; - - // 2.4G/5G N only mode - if ((pInBss->HtCapabilityLen == 0) && - ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) - { - DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); - continue; - } - - // New for WPA2 - // Check the Authmode first - if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - { - // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode - if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux)) - // None matched - continue; - - // Check cipher suite, AP must have more secured cipher than station setting - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) - { - // If it's not mixed mode, we should only let BSS pass with the same encryption - if (pInBss->WPA.bMixMode == FALSE) - if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher) - continue; - - // check group cipher - if (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled && - pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled && - pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) - continue; - - // check pairwise cipher, skip if none matched - // If profile set to AES, let it pass without question. - // If profile set to TKIP, we must find one mateched - if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && - (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) && - (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux)) - continue; - } - else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - // If it's not mixed mode, we should only let BSS pass with the same encryption - if (pInBss->WPA2.bMixMode == FALSE) - if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher) - continue; - - // check group cipher - if (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled && - pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled && - pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher) - continue; - - // check pairwise cipher, skip if none matched - // If profile set to AES, let it pass without question. - // If profile set to TKIP, we must find one mateched - if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && - (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) && - (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux)) - continue; - } - } - // Bss Type matched, SSID matched. - // We will check wepstatus for qualification Bss - else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) - { - DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus)); - // - // For the SESv2 case, we will not qualify WepStatus. - // - if (!pInBss->bSES) - continue; - } - - // Since the AP is using hidden SSID, and we are trying to connect to ANY - // It definitely will fail. So, skip it. - // CCX also require not even try to connect it!! - if (SsidLen == 0) - continue; - - // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region - // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, - if ((pInBss->CentralChannel != pInBss->Channel) && - (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) - { - if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE) - { - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; - SetCommonHT(pAd); - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; - } - else - { - if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20) - { - SetCommonHT(pAd); - } - } - } - - // copy matching BSS from InTab to OutTab - NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); - - OutTab->BssNr++; - } - else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0)) - { - BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; - - // 2.4G/5G N only mode - if ((pInBss->HtCapabilityLen == 0) && - ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) - { - DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); - continue; - } - - // New for WPA2 - // Check the Authmode first - if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - { - // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode - if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux)) - // None matched - continue; - - // Check cipher suite, AP must have more secured cipher than station setting - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) - { - // If it's not mixed mode, we should only let BSS pass with the same encryption - if (pInBss->WPA.bMixMode == FALSE) - if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher) - continue; - - // check group cipher - if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) - continue; - - // check pairwise cipher, skip if none matched - // If profile set to AES, let it pass without question. - // If profile set to TKIP, we must find one mateched - if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && - (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) && - (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux)) - continue; - } - else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - // If it's not mixed mode, we should only let BSS pass with the same encryption - if (pInBss->WPA2.bMixMode == FALSE) - if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher) - continue; - - // check group cipher - if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher) - continue; - - // check pairwise cipher, skip if none matched - // If profile set to AES, let it pass without question. - // If profile set to TKIP, we must find one mateched - if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && - (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) && - (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux)) - continue; - } - } - // Bss Type matched, SSID matched. - // We will check wepstatus for qualification Bss - else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) - continue; - - // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region - // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, - if ((pInBss->CentralChannel != pInBss->Channel) && - (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) - { - if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE) - { - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; - SetCommonHT(pAd); - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; - } - } - - // copy matching BSS from InTab to OutTab - NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); - - OutTab->BssNr++; - } - - if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE) - break; - } - - BssTableSortByRssi(OutTab); -} - - -// IRQL = DISPATCH_LEVEL -VOID BssTableSortByRssi( - IN OUT BSS_TABLE *OutTab) -{ - INT i, j; - BSS_ENTRY TmpBss; - - for (i = 0; i < OutTab->BssNr - 1; i++) - { - for (j = i+1; j < OutTab->BssNr; j++) - { - if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi) - { - NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY)); - NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY)); - NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY)); - } - } - } -} - -VOID BssCipherParse( - IN OUT PBSS_ENTRY pBss) -{ - PEID_STRUCT pEid; - PUCHAR pTmp; - PRSN_IE_HEADER_STRUCT pRsnHeader; - PCIPHER_SUITE_STRUCT pCipher; - PAKM_SUITE_STRUCT pAKM; - USHORT Count; - INT Length; - NDIS_802_11_ENCRYPTION_STATUS TmpCipher; - - // - // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame. - // - if (pBss->Privacy) - { - pBss->WepStatus = Ndis802_11WEPEnabled; - } - else - { - pBss->WepStatus = Ndis802_11WEPDisabled; - } - // Set default to disable & open authentication before parsing variable IE - pBss->AuthMode = Ndis802_11AuthModeOpen; - pBss->AuthModeAux = Ndis802_11AuthModeOpen; - - // Init WPA setting - pBss->WPA.PairCipher = Ndis802_11WEPDisabled; - pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled; - pBss->WPA.GroupCipher = Ndis802_11WEPDisabled; - pBss->WPA.RsnCapability = 0; - pBss->WPA.bMixMode = FALSE; - - // Init WPA2 setting - pBss->WPA2.PairCipher = Ndis802_11WEPDisabled; - pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled; - pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled; - pBss->WPA2.RsnCapability = 0; - pBss->WPA2.bMixMode = FALSE; - - - Length = (INT) pBss->VarIELen; - - while (Length > 0) - { - // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently - pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length; - pEid = (PEID_STRUCT) pTmp; - switch (pEid->Eid) - { - case IE_WPA: - //Parse Cisco IE_WPA (LEAP, CCKM, etc.) - if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3)) - { - pTmp += 11; - switch (*pTmp) - { - case 1: - case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway - pBss->WepStatus = Ndis802_11Encryption1Enabled; - pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled; - pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; - break; - case 2: - pBss->WepStatus = Ndis802_11Encryption2Enabled; - pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled; - pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; - break; - case 4: - pBss->WepStatus = Ndis802_11Encryption3Enabled; - pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled; - pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; - break; - default: - break; - } - - // if Cisco IE_WPA, break - break; - } - else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7)) - { - pBss->bSES = TRUE; - break; - } - else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1) - { - // if unsupported vendor specific IE - break; - } - // Skip OUI, version, and multicast suite - // This part should be improved in the future when AP supported multiple cipher suite. - // For now, it's OK since almost all APs have fixed cipher suite supported. - // pTmp = (PUCHAR) pEid->Octet; - pTmp += 11; - - // Cipher Suite Selectors from Spec P802.11i/D3.2 P26. - // Value Meaning - // 0 None - // 1 WEP-40 - // 2 Tkip - // 3 WRAP - // 4 AES - // 5 WEP-104 - // Parse group cipher - switch (*pTmp) - { - case 1: - pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled; - break; - case 5: - pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled; - break; - case 2: - pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled; - break; - case 4: - pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled; - break; - default: - break; - } - // number of unicast suite - pTmp += 1; - - // skip all unicast cipher suites - //Count = *(PUSHORT) pTmp; - Count = (pTmp[1]<<8) + pTmp[0]; - pTmp += sizeof(USHORT); - - // Parsing all unicast cipher suite - while (Count > 0) - { - // Skip OUI - pTmp += 3; - TmpCipher = Ndis802_11WEPDisabled; - switch (*pTmp) - { - case 1: - case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway - TmpCipher = Ndis802_11Encryption1Enabled; - break; - case 2: - TmpCipher = Ndis802_11Encryption2Enabled; - break; - case 4: - TmpCipher = Ndis802_11Encryption3Enabled; - break; - default: - break; - } - if (TmpCipher > pBss->WPA.PairCipher) - { - // Move the lower cipher suite to PairCipherAux - pBss->WPA.PairCipherAux = pBss->WPA.PairCipher; - pBss->WPA.PairCipher = TmpCipher; - } - else - { - pBss->WPA.PairCipherAux = TmpCipher; - } - pTmp++; - Count--; - } - - // 4. get AKM suite counts - //Count = *(PUSHORT) pTmp; - Count = (pTmp[1]<<8) + pTmp[0]; - pTmp += sizeof(USHORT); - pTmp += 3; - - switch (*pTmp) - { - case 1: - // Set AP support WPA mode - if (pBss->AuthMode == Ndis802_11AuthModeOpen) - pBss->AuthMode = Ndis802_11AuthModeWPA; - else - pBss->AuthModeAux = Ndis802_11AuthModeWPA; - break; - case 2: - // Set AP support WPA mode - if (pBss->AuthMode == Ndis802_11AuthModeOpen) - pBss->AuthMode = Ndis802_11AuthModeWPAPSK; - else - pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK; - break; - default: - break; - } - pTmp += 1; - - // Fixed for WPA-None - if (pBss->BssType == BSS_ADHOC) - { - pBss->AuthMode = Ndis802_11AuthModeWPANone; - pBss->AuthModeAux = Ndis802_11AuthModeWPANone; - pBss->WepStatus = pBss->WPA.GroupCipher; - if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) - pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher; - } - else - pBss->WepStatus = pBss->WPA.PairCipher; - - // Check the Pair & Group, if different, turn on mixed mode flag - if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher) - pBss->WPA.bMixMode = TRUE; - - break; - - case IE_RSN: - pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp; - - // 0. Version must be 1 - if (le2cpu16(pRsnHeader->Version) != 1) - break; - pTmp += sizeof(RSN_IE_HEADER_STRUCT); - - // 1. Check group cipher - pCipher = (PCIPHER_SUITE_STRUCT) pTmp; - if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) - break; - - // Parse group cipher - switch (pCipher->Type) - { - case 1: - pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled; - break; - case 5: - pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled; - break; - case 2: - pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled; - break; - case 4: - pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled; - break; - default: - break; - } - // set to correct offset for next parsing - pTmp += sizeof(CIPHER_SUITE_STRUCT); - - // 2. Get pairwise cipher counts - //Count = *(PUSHORT) pTmp; - Count = (pTmp[1]<<8) + pTmp[0]; - pTmp += sizeof(USHORT); - - // 3. Get pairwise cipher - // Parsing all unicast cipher suite - while (Count > 0) - { - // Skip OUI - pCipher = (PCIPHER_SUITE_STRUCT) pTmp; - TmpCipher = Ndis802_11WEPDisabled; - switch (pCipher->Type) - { - case 1: - case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway - TmpCipher = Ndis802_11Encryption1Enabled; - break; - case 2: - TmpCipher = Ndis802_11Encryption2Enabled; - break; - case 4: - TmpCipher = Ndis802_11Encryption3Enabled; - break; - default: - break; - } - if (TmpCipher > pBss->WPA2.PairCipher) - { - // Move the lower cipher suite to PairCipherAux - pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher; - pBss->WPA2.PairCipher = TmpCipher; - } - else - { - pBss->WPA2.PairCipherAux = TmpCipher; - } - pTmp += sizeof(CIPHER_SUITE_STRUCT); - Count--; - } - - // 4. get AKM suite counts - //Count = *(PUSHORT) pTmp; - Count = (pTmp[1]<<8) + pTmp[0]; - pTmp += sizeof(USHORT); - - // 5. Get AKM ciphers - pAKM = (PAKM_SUITE_STRUCT) pTmp; - if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) - break; - - switch (pAKM->Type) - { - case 1: - // Set AP support WPA mode - if (pBss->AuthMode == Ndis802_11AuthModeOpen) - pBss->AuthMode = Ndis802_11AuthModeWPA2; - else - pBss->AuthModeAux = Ndis802_11AuthModeWPA2; - break; - case 2: - // Set AP support WPA mode - if (pBss->AuthMode == Ndis802_11AuthModeOpen) - pBss->AuthMode = Ndis802_11AuthModeWPA2PSK; - else - pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK; - break; - default: - break; - } - pTmp += (Count * sizeof(AKM_SUITE_STRUCT)); - - // Fixed for WPA-None - if (pBss->BssType == BSS_ADHOC) - { - pBss->AuthMode = Ndis802_11AuthModeWPANone; - pBss->AuthModeAux = Ndis802_11AuthModeWPANone; - pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux; - pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher; - pBss->WepStatus = pBss->WPA.GroupCipher; - if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) - pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher; - } - pBss->WepStatus = pBss->WPA2.PairCipher; - - // 6. Get RSN capability - //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp; - pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0]; - pTmp += sizeof(USHORT); - - // Check the Pair & Group, if different, turn on mixed mode flag - if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher) - pBss->WPA2.bMixMode = TRUE; - - break; - default: - break; - } - Length -= (pEid->Len + 2); - } -} - -// =========================================================================================== -// mac_table.c -// =========================================================================================== - -/*! \brief generates a random mac address value for IBSS BSSID - * \param Addr the bssid location - * \return none - * \pre - * \post - */ -VOID MacAddrRandomBssid( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pAddr) -{ - INT i; - - for (i = 0; i < MAC_ADDR_LEN; i++) - { - pAddr[i] = RandomByte(pAd); - } - - pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx -} - -/*! \brief init the management mac frame header - * \param p_hdr mac header - * \param subtype subtype of the frame - * \param p_ds destination address, don't care if it is a broadcast address - * \return none - * \pre the station has the following information in the pAd->StaCfg - * - bssid - * - station address - * \post - * \note this function initializes the following field - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - */ -VOID MgtMacHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PHEADER_802_11 pHdr80211, - IN UCHAR SubType, - IN UCHAR ToDs, - IN PUCHAR pDA, - IN PUCHAR pBssid) -{ - NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); - - pHdr80211->FC.Type = BTYPE_MGMT; - pHdr80211->FC.SubType = SubType; - pHdr80211->FC.ToDs = ToDs; - COPY_MAC_ADDR(pHdr80211->Addr1, pDA); - - COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); - - COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); -} - -// =========================================================================================== -// mem_mgmt.c -// =========================================================================================== - -/*!*************************************************************************** - * This routine build an outgoing frame, and fill all information specified - * in argument list to the frame body. The actual frame size is the summation - * of all arguments. - * input params: - * Buffer - pointer to a pre-allocated memory segment - * args - a list of pairs. - * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this - * function will FAIL!!! - * return: - * Size of the buffer - * usage: - * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS); - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - ****************************************************************************/ -ULONG MakeOutgoingFrame( - OUT CHAR *Buffer, - OUT ULONG *FrameLen, ...) -{ - CHAR *p; - int leng; - ULONG TotLeng; - va_list Args; - - // calculates the total length - TotLeng = 0; - va_start(Args, FrameLen); - do - { - leng = va_arg(Args, int); - if (leng == END_OF_ARGS) - { - break; - } - p = va_arg(Args, PVOID); - NdisMoveMemory(&Buffer[TotLeng], p, leng); - TotLeng = TotLeng + leng; - } while(TRUE); - - va_end(Args); /* clean up */ - *FrameLen = TotLeng; - return TotLeng; -} - -// =========================================================================================== -// mlme_queue.c -// =========================================================================================== - -/*! \brief Initialize The MLME Queue, used by MLME Functions - * \param *Queue The MLME Queue - * \return Always Return NDIS_STATE_SUCCESS in this implementation - * \pre - * \post - * \note Because this is done only once (at the init stage), no need to be locked - - IRQL = PASSIVE_LEVEL - - */ -NDIS_STATUS MlmeQueueInit( - IN MLME_QUEUE *Queue) -{ - INT i; - - NdisAllocateSpinLock(&Queue->Lock); - - Queue->Num = 0; - Queue->Head = 0; - Queue->Tail = 0; + if (pEntry->TxRateUpPenalty) + pEntry->TxRateUpPenalty--; + else if (pEntry->TxQuality[UpRateIdx]) + pEntry->TxQuality[UpRateIdx]--; /* may improve next UP rate's quality */ + } - for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) - { - Queue->Entry[i].Occupied = FALSE; - Queue->Entry[i].MsgLen = 0; - NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE); - } + pEntry->PER[CurrRateIdx] = (u8)TxErrorRatio; - return NDIS_STATUS_SUCCESS; -} + if (bTrainUpDown) { + /* perform DRS - consider TxRate Down first, then rate up. */ + if ((CurrRateIdx != DownRateIdx) + && (pEntry->TxQuality[CurrRateIdx] >= + DRS_TX_QUALITY_WORST_BOUND)) { + pEntry->CurrTxRateIndex = DownRateIdx; + } else if ((CurrRateIdx != UpRateIdx) + && (pEntry->TxQuality[UpRateIdx] <= + 0)) { + pEntry->CurrTxRateIndex = UpRateIdx; + } + } + } while (FALSE); -/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread - * \param *Queue The MLME Queue - * \param Machine The State Machine Id - * \param MsgType The Message Type - * \param MsgLen The Message length - * \param *Msg The message pointer - * \return TRUE if enqueue is successful, FALSE if the queue is full - * \pre - * \post - * \note The message has to be initialized + /* if rate-up happen, clear all bad history of all TX rates */ + if (pEntry->CurrTxRateIndex > CurrRateIdx) { + pEntry->CurrTxRateStableTime = 0; + pEntry->TxRateUpPenalty = 0; + pEntry->LastSecTxRateChangeAction = 1; /* rate UP */ + NdisZeroMemory(pEntry->TxQuality, + sizeof(u16)* + MAX_STEP_OF_TX_RATE_SWITCH); + NdisZeroMemory(pEntry->PER, + sizeof(u8)* + MAX_STEP_OF_TX_RATE_SWITCH); + + /* */ + /* For TxRate fast train up */ + /* */ + if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) { + RTMPSetTimer(&pAd->StaCfg. + StaQuickResponeForRateUpTimer, + 100); + + pAd->StaCfg. + StaQuickResponeForRateUpTimerRunning = TRUE; + } + bTxRateChanged = TRUE; + } + /* if rate-down happen, only clear DownRate's bad history */ + else if (pEntry->CurrTxRateIndex < CurrRateIdx) { + pEntry->CurrTxRateStableTime = 0; + pEntry->TxRateUpPenalty = 0; /* no penalty */ + pEntry->LastSecTxRateChangeAction = 2; /* rate DOWN */ + pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; + pEntry->PER[pEntry->CurrTxRateIndex] = 0; - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL + /* */ + /* For TxRate fast train down */ + /* */ + if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) { + RTMPSetTimer(&pAd->StaCfg. + StaQuickResponeForRateUpTimer, + 100); - */ -BOOLEAN MlmeEnqueue( - IN PRTMP_ADAPTER pAd, - IN ULONG Machine, - IN ULONG MsgType, - IN ULONG MsgLen, - IN VOID *Msg) -{ - INT Tail; - MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; + pAd->StaCfg. + StaQuickResponeForRateUpTimerRunning = TRUE; + } + bTxRateChanged = TRUE; + } else { + pEntry->LastSecTxRateChangeAction = 0; /* rate no change */ + bTxRateChanged = FALSE; + } - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return FALSE; + pEntry->LastTxOkCount = TxSuccess; + { + u8 tmpTxRate; + + /* to fix tcp ack issue */ + if (!bTxRateChanged + && (pAd->RalinkCounters.OneSecReceivedByteCount > + (pAd->RalinkCounters. + OneSecTransmittedByteCount * 5))) { + tmpTxRate = DownRateIdx; + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("DRS: Rx(%d) is 5 times larger than Tx(%d), use low rate (curr=%d, tmp=%d)\n", + pAd->RalinkCounters. + OneSecReceivedByteCount, + pAd->RalinkCounters. + OneSecTransmittedByteCount, + pEntry->CurrTxRateIndex, + tmpTxRate)); + } else { + tmpTxRate = pEntry->CurrTxRateIndex; + } - // First check the size, it MUST not exceed the mlme queue size - if (MsgLen > MGMT_DMA_BUFFER_SIZE) - { - DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen)); - return FALSE; + pNextTxRate = + (struct rt_rtmp_tx_rate_switch *) & pTable[(tmpTxRate + 1) * + 5]; + } + if (bTxRateChanged && pNextTxRate) { + MlmeSetTxRate(pAd, pEntry, pNextTxRate); + } + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); } +} - if (MlmeQueueFull(Queue)) - { - return FALSE; - } +/* + ======================================================================== + Routine Description: + Station side, Auto TxRate faster train up timer call back function. - NdisAcquireSpinLock(&(Queue->Lock)); - Tail = Queue->Tail; - Queue->Tail++; - Queue->Num++; - if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) - { - Queue->Tail = 0; - } + Arguments: + SystemSpecific1 - Not used. + FunctionContext - Pointer to our Adapter context. + SystemSpecific2 - Not used. + SystemSpecific3 - Not used. - Queue->Entry[Tail].Wcid = RESERVED_WCID; - Queue->Entry[Tail].Occupied = TRUE; - Queue->Entry[Tail].Machine = Machine; - Queue->Entry[Tail].MsgType = MsgType; - Queue->Entry[Tail].MsgLen = MsgLen; + Return Value: + None - if (Msg != NULL) - { - NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); - } + ======================================================================== +*/ +void StaQuickResponeForRateUpExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, + void *SystemSpecific3) +{ + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; + u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0; + unsigned long TxTotalCnt; + unsigned long TxErrorRatio = 0; + BOOLEAN bTxRateChanged; /*, bUpgradeQuality = FALSE; */ + struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL; + u8 *pTable; + u8 TableSize = 0; + u8 InitTxRateIdx = 0, TrainUp, TrainDown; + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + char Rssi, ratio; + unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; + struct rt_mac_table_entry *pEntry; + unsigned long i; - NdisReleaseSpinLock(&(Queue->Lock)); - return TRUE; -} + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; -/*! \brief This function is used when Recv gets a MLME message - * \param *Queue The MLME Queue - * \param TimeStampHigh The upper 32 bit of timestamp - * \param TimeStampLow The lower 32 bit of timestamp - * \param Rssi The receiving RSSI strength - * \param MsgLen The length of the message - * \param *Msg The message pointer - * \return TRUE if everything ok, FALSE otherwise (like Queue Full) - * \pre - * \post + /* */ + /* walk through MAC table, see if need to change AP's TX rate toward each entry */ + /* */ + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { + pEntry = &pAd->MacTab.Content[i]; - IRQL = DISPATCH_LEVEL + /* check if this entry need to switch rate automatically */ + if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) + continue; - */ -BOOLEAN MlmeEnqueueForRecv( - IN PRTMP_ADAPTER pAd, - IN ULONG Wcid, - IN ULONG TimeStampHigh, - IN ULONG TimeStampLow, - IN UCHAR Rssi0, - IN UCHAR Rssi1, - IN UCHAR Rssi2, - IN ULONG MsgLen, - IN VOID *Msg, - IN UCHAR Signal) -{ - INT Tail, Machine; - PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; - INT MsgType; - MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - { - DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n")); - return FALSE; - } + if (INFRA_ON(pAd) && (i == 1)) + Rssi = RTMPMaxRssi(pAd, + pAd->StaCfg.RssiSample.AvgRssi0, + pAd->StaCfg.RssiSample.AvgRssi1, + pAd->StaCfg.RssiSample.AvgRssi2); + else + Rssi = RTMPMaxRssi(pAd, + pEntry->RssiSample.AvgRssi0, + pEntry->RssiSample.AvgRssi1, + pEntry->RssiSample.AvgRssi2); - // First check the size, it MUST not exceed the mlme queue size - if (MsgLen > MGMT_DMA_BUFFER_SIZE) - { - DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); - return FALSE; - } + CurrRateIdx = pAd->CommonCfg.TxRateIndex; - if (MlmeQueueFull(Queue)) - { - return FALSE; - } + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, + &InitTxRateIdx); - { - if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) - { - DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType)); - return FALSE; + /* decide the next upgrade rate and downgrade rate, if any */ + if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) { + UpRateIdx = CurrRateIdx + 1; + DownRateIdx = CurrRateIdx - 1; + } else if (CurrRateIdx == 0) { + UpRateIdx = CurrRateIdx + 1; + DownRateIdx = CurrRateIdx; + } else if (CurrRateIdx == (TableSize - 1)) { + UpRateIdx = CurrRateIdx; + DownRateIdx = CurrRateIdx - 1; } - } - // OK, we got all the informations, it is time to put things into queue - NdisAcquireSpinLock(&(Queue->Lock)); - Tail = Queue->Tail; - Queue->Tail++; - Queue->Num++; - if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) - { - Queue->Tail = 0; - } - Queue->Entry[Tail].Occupied = TRUE; - Queue->Entry[Tail].Machine = Machine; - Queue->Entry[Tail].MsgType = MsgType; - Queue->Entry[Tail].MsgLen = MsgLen; - Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow; - Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh; - Queue->Entry[Tail].Rssi0 = Rssi0; - Queue->Entry[Tail].Rssi1 = Rssi1; - Queue->Entry[Tail].Rssi2 = Rssi2; - Queue->Entry[Tail].Signal = Signal; - Queue->Entry[Tail].Wcid = (UCHAR)Wcid; + pCurrTxRate = + (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5]; - Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel; + if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) { + TrainUp = + (pCurrTxRate->TrainUp + + (pCurrTxRate->TrainUp >> 1)); + TrainDown = + (pCurrTxRate->TrainDown + + (pCurrTxRate->TrainDown >> 1)); + } else { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } - if (Msg != NULL) - { - NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); - } + if (pAd->MacTab.Size == 1) { + /* Update statistic counter */ + RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); - NdisReleaseSpinLock(&(Queue->Lock)); + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; - RT28XX_MLME_HANDLER(pAd); + pAd->RalinkCounters.OneSecTxRetryOkCount += + StaTx1.field.TxRetransmit; + pAd->RalinkCounters.OneSecTxNoRetryOkCount += + StaTx1.field.TxSuccess; + pAd->RalinkCounters.OneSecTxFailCount += + TxStaCnt0.field.TxFailCount; + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += + StaTx1.field.TxSuccess; + pAd->WlanCounters.RetryCount.u.LowPart += + StaTx1.field.TxRetransmit; + pAd->WlanCounters.FailedCount.u.LowPart += + TxStaCnt0.field.TxFailCount; - return TRUE; -} + if (TxTotalCnt) + TxErrorRatio = + ((TxRetransmit + + TxFailCount) * 100) / TxTotalCnt; + } else { + TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + + pEntry->OneSecTxRetryOkCount + + pEntry->OneSecTxFailCount; + if (TxTotalCnt) + TxErrorRatio = + ((pEntry->OneSecTxRetryOkCount + + pEntry->OneSecTxFailCount) * 100) / + TxTotalCnt; + } + + /* */ + /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */ + /* (criteria copied from RT2500 for Netopia case) */ + /* */ + if (TxTotalCnt <= 12) { + NdisZeroMemory(pAd->DrsCounters.TxQuality, + sizeof(u16)* + MAX_STEP_OF_TX_RATE_SWITCH); + NdisZeroMemory(pAd->DrsCounters.PER, + sizeof(u8)* + MAX_STEP_OF_TX_RATE_SWITCH); + + if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) + && (CurrRateIdx != DownRateIdx)) { + pAd->CommonCfg.TxRateIndex = DownRateIdx; + pAd->DrsCounters.TxQuality[CurrRateIdx] = + DRS_TX_QUALITY_WORST_BOUND; + } else + if ((pAd->DrsCounters.LastSecTxRateChangeAction == + 2) && (CurrRateIdx != UpRateIdx)) { + pAd->CommonCfg.TxRateIndex = UpRateIdx; + } -/*! \brief Dequeue a message from the MLME Queue - * \param *Queue The MLME Queue - * \param *Elem The message dequeued from MLME Queue - * \return TRUE if the Elem contains something, FALSE otherwise - * \pre - * \post + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("QuickDRS: TxTotalCnt <= 15, train back to original rate \n")); + return; + } - IRQL = DISPATCH_LEVEL + do { + unsigned long OneSecTxNoRetryOKRationCount; - */ -BOOLEAN MlmeDequeue( - IN MLME_QUEUE *Queue, - OUT MLME_QUEUE_ELEM **Elem) -{ - NdisAcquireSpinLock(&(Queue->Lock)); - *Elem = &(Queue->Entry[Queue->Head]); - Queue->Num--; - Queue->Head++; - if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) - { - Queue->Head = 0; - } - NdisReleaseSpinLock(&(Queue->Lock)); - return TRUE; -} + if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0) + ratio = 5; + else + ratio = 4; -// IRQL = DISPATCH_LEVEL -VOID MlmeRestartStateMachine( - IN PRTMP_ADAPTER pAd) -{ -#ifdef RT2860 - MLME_QUEUE_ELEM *Elem = NULL; -#endif - BOOLEAN Cancelled; + /* downgrade TX quality if PER >= Rate-Down threshold */ + if (TxErrorRatio >= TrainDown) { + pAd->DrsCounters.TxQuality[CurrRateIdx] = + DRS_TX_QUALITY_WORST_BOUND; + } - DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n")); + pAd->DrsCounters.PER[CurrRateIdx] = + (u8)TxErrorRatio; -#ifdef RT2860 - NdisAcquireSpinLock(&pAd->Mlme.TaskLock); - if(pAd->Mlme.bRunning) - { - NdisReleaseSpinLock(&pAd->Mlme.TaskLock); - return; - } - else - { - pAd->Mlme.bRunning = TRUE; - } - NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + OneSecTxNoRetryOKRationCount = (TxSuccess * ratio); - // Remove all Mlme queues elements - while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) - { - //From message type, determine which state machine I should drive - if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) - { - // free MLME element - Elem->Occupied = FALSE; - Elem->MsgLen = 0; + /* perform DRS - consider TxRate Down first, then rate up. */ + if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) + && (CurrRateIdx != DownRateIdx)) { + if ((pAd->DrsCounters.LastTxOkCount + 2) >= + OneSecTxNoRetryOKRationCount) { + pAd->CommonCfg.TxRateIndex = + DownRateIdx; + pAd->DrsCounters. + TxQuality[CurrRateIdx] = + DRS_TX_QUALITY_WORST_BOUND; - } - else { - DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n")); - } - } -#endif /* RT2860 */ + } - { - // Cancel all timer events - // Be careful to cancel new added timer - RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); - } + } else + if ((pAd->DrsCounters.LastSecTxRateChangeAction == + 2) && (CurrRateIdx != UpRateIdx)) { + if ((TxErrorRatio >= 50) + || (TxErrorRatio >= TrainDown)) { - // Change back to original channel in case of doing scan - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } else if ((pAd->DrsCounters.LastTxOkCount + 2) + >= OneSecTxNoRetryOKRationCount) { + pAd->CommonCfg.TxRateIndex = UpRateIdx; + } + } + } while (FALSE); - // Resume MSDU which is turned off durning scan - RTMPResumeMsduTransmission(pAd); + /* if rate-up happen, clear all bad history of all TX rates */ + if (pAd->CommonCfg.TxRateIndex > CurrRateIdx) { + pAd->DrsCounters.TxRateUpPenalty = 0; + NdisZeroMemory(pAd->DrsCounters.TxQuality, + sizeof(u16)* + MAX_STEP_OF_TX_RATE_SWITCH); + NdisZeroMemory(pAd->DrsCounters.PER, + sizeof(u8)* + MAX_STEP_OF_TX_RATE_SWITCH); + bTxRateChanged = TRUE; + } + /* if rate-down happen, only clear DownRate's bad history */ + else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx) { + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("QuickDRS: --TX rate from %d to %d \n", + CurrRateIdx, pAd->CommonCfg.TxRateIndex)); - { - // Set all state machines back IDLE - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE; - pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; - pAd->Mlme.ActMachine.CurrState = ACT_IDLE; - } + pAd->DrsCounters.TxRateUpPenalty = 0; /* no penalty */ + pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = + 0; + pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0; + bTxRateChanged = TRUE; + } else { + bTxRateChanged = FALSE; + } -#ifdef RT2860 - // Remove running state - NdisAcquireSpinLock(&pAd->Mlme.TaskLock); - pAd->Mlme.bRunning = FALSE; - NdisReleaseSpinLock(&pAd->Mlme.TaskLock); -#endif + pNextTxRate = + (struct rt_rtmp_tx_rate_switch *) & + pTable[(pAd->CommonCfg.TxRateIndex + 1) * 5]; + if (bTxRateChanged && pNextTxRate) { + MlmeSetTxRate(pAd, pEntry, pNextTxRate); + } + } } -/*! \brief test if the MLME Queue is empty - * \param *Queue The MLME Queue - * \return TRUE if the Queue is empty, FALSE otherwise - * \pre - * \post +/* + ========================================================================== + Description: + This routine is executed periodically inside MlmePeriodicExec() after + association with an AP. + It checks if StaCfg.Psm is consistent with user policy (recorded in + StaCfg.WindowsPowerMode). If not, enforce user policy. However, + there're some conditions to consider: + 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all + the time when Mibss==TRUE + 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE + if outgoing traffic available in TxRing or MgmtRing. + Output: + 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched - IRQL = DISPATCH_LEVEL + IRQL = DISPATCH_LEVEL + ========================================================================== */ -BOOLEAN MlmeQueueEmpty( - IN MLME_QUEUE *Queue) +void MlmeCheckPsmChange(struct rt_rtmp_adapter *pAd, unsigned long Now32) { - BOOLEAN Ans; + unsigned long PowerMode; - NdisAcquireSpinLock(&(Queue->Lock)); - Ans = (Queue->Num == 0); - NdisReleaseSpinLock(&(Queue->Lock)); + /* condition - */ + /* 1. Psm maybe ON only happen in INFRASTRUCTURE mode */ + /* 2. user wants either MAX_PSP or FAST_PSP */ + /* 3. but current psm is not in PWR_SAVE */ + /* 4. CNTL state machine is not doing SCANning */ + /* 5. no TX SUCCESS event for the past 1-sec period */ + PowerMode = pAd->StaCfg.WindowsPowerMode; - return Ans; + if (INFRA_ON(pAd) && + (PowerMode != Ndis802_11PowerModeCAM) && + (pAd->StaCfg.Psm == PWR_ACTIVE) && +/* (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) */ + (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && + RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP) + /*&& + (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && + (pAd->RalinkCounters.OneSecTxRetryOkCount == 0) */ + ) { + NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime); + pAd->RalinkCounters.RxCountSinceLastNULL = 0; + RTMP_SET_PSM_BIT(pAd, PWR_SAVE); + if (! + (pAd->CommonCfg.bAPSDCapable + && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) { + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE); + } else { + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); + } + } } -/*! \brief test if the MLME Queue is full - * \param *Queue The MLME Queue - * \return TRUE if the Queue is empty, FALSE otherwise - * \pre - * \post - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - */ -BOOLEAN MlmeQueueFull( - IN MLME_QUEUE *Queue) +/* IRQL = PASSIVE_LEVEL */ +/* IRQL = DISPATCH_LEVEL */ +void MlmeSetPsmBit(struct rt_rtmp_adapter *pAd, u16 psm) { - BOOLEAN Ans; + AUTO_RSP_CFG_STRUC csr4; - NdisAcquireSpinLock(&(Queue->Lock)); - Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied); - NdisReleaseSpinLock(&(Queue->Lock)); + pAd->StaCfg.Psm = psm; + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); + csr4.field.AckCtsPsmBit = (psm == PWR_SAVE) ? 1 : 0; + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); - return Ans; + DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm)); } -/*! \brief The destructor of MLME Queue - * \param - * \return - * \pre - * \post - * \note Clear Mlme Queue, Set Queue->Num to Zero. +/* + ========================================================================== + Description: + This routine calculates TxPER, RxPER of the past N-sec period. And + according to the calculation result, ChannelQuality is calculated here + to decide if current AP is still doing the job. - IRQL = PASSIVE_LEVEL + If ChannelQuality is not good, a ROAMing attempt may be tried later. + Output: + StaCfg.ChannelQuality - 0..100 + + IRQL = DISPATCH_LEVEL + NOTE: This routine decide channle quality based on RX CRC error ratio. + Caller should make sure a function call to NICUpdateRawCounters(pAd) + is performed right before this routine, so that this routine can decide + channel quality based on the most up-to-date information + ========================================================================== */ -VOID MlmeQueueDestroy( - IN MLME_QUEUE *pQueue) +void MlmeCalculateChannelQuality(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pMacEntry, unsigned long Now32) { - NdisAcquireSpinLock(&(pQueue->Lock)); - pQueue->Num = 0; - pQueue->Head = 0; - pQueue->Tail = 0; - NdisReleaseSpinLock(&(pQueue->Lock)); - NdisFreeSpinLock(&(pQueue->Lock)); + unsigned long TxOkCnt, TxCnt, TxPER, TxPRR; + unsigned long RxCnt, RxPER; + u8 NorRssi; + char MaxRssi; + struct rt_rssi_sample *pRssiSample = NULL; + u32 OneSecTxNoRetryOkCount = 0; + u32 OneSecTxRetryOkCount = 0; + u32 OneSecTxFailCount = 0; + u32 OneSecRxOkCnt = 0; + u32 OneSecRxFcsErrCnt = 0; + unsigned long ChannelQuality = 0; /* 0..100, Channel Quality Indication for Roaming */ + unsigned long BeaconLostTime = pAd->StaCfg.BeaconLostTime; + + if (pAd->OpMode == OPMODE_STA) { + pRssiSample = &pAd->StaCfg.RssiSample; + OneSecTxNoRetryOkCount = + pAd->RalinkCounters.OneSecTxNoRetryOkCount; + OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount; + OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount; + OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt; + OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt; + } + + MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi0, + pRssiSample->LastRssi1, pRssiSample->LastRssi2); + + /* */ + /* calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics */ + /* */ + TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount; + TxCnt = TxOkCnt + OneSecTxFailCount; + if (TxCnt < 5) { + TxPER = 0; + TxPRR = 0; + } else { + TxPER = (OneSecTxFailCount * 100) / TxCnt; + TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt; + } + + /* */ + /* calculate RX PER - don't take RxPER into consideration if too few sample */ + /* */ + RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt; + if (RxCnt < 5) + RxPER = 0; + else + RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt; + + /* */ + /* decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER */ + /* */ + if ((pAd->OpMode == OPMODE_STA) && INFRA_ON(pAd) && (OneSecTxNoRetryOkCount < 2) && /* no heavy traffic */ + ((pAd->StaCfg.LastBeaconRxTime + BeaconLostTime) < Now32)) { + DBGPRINT(RT_DEBUG_TRACE, + ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", + BeaconLostTime, TxOkCnt)); + ChannelQuality = 0; + } else { + /* Normalize Rssi */ + if (MaxRssi > -40) + NorRssi = 100; + else if (MaxRssi < -90) + NorRssi = 0; + else + NorRssi = (MaxRssi + 90) * 2; + + /* ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) */ + ChannelQuality = (RSSI_WEIGHTING * NorRssi + + TX_WEIGHTING * (100 - TxPRR) + + RX_WEIGHTING * (100 - RxPER)) / 100; + } + + if (pAd->OpMode == OPMODE_STA) + pAd->Mlme.ChannelQuality = + (ChannelQuality > 100) ? 100 : ChannelQuality; + } -/*! \brief To substitute the message type if the message is coming from external - * \param pFrame The frame received - * \param *Machine The state machine - * \param *MsgType the message type for the state machine - * \return TRUE if the substitution is successful, FALSE otherwise - * \pre - * \post +/* IRQL = DISPATCH_LEVEL */ +void MlmeSetTxPreamble(struct rt_rtmp_adapter *pAd, u16 TxPreamble) +{ + AUTO_RSP_CFG_STRUC csr4; - IRQL = DISPATCH_LEVEL + /* */ + /* Always use Long preamble before verifiation short preamble functionality works well. */ + /* Todo: remove the following line if short preamble functionality works */ + /* */ + /*TxPreamble = Rt802_11PreambleLong; */ + + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); + if (TxPreamble == Rt802_11PreambleLong) { + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeSetTxPreamble (= long PREAMBLE)\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + csr4.field.AutoResponderPreamble = 0; + } else { + /* NOTE: 1Mbps should always use long preamble */ + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeSetTxPreamble (= short PREAMBLE)\n")); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + csr4.field.AutoResponderPreamble = 1; + } + + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); +} +/* + ========================================================================== + Description: + Update basic rate bitmap + ========================================================================== */ -BOOLEAN MsgTypeSubst( - IN PRTMP_ADAPTER pAd, - IN PFRAME_802_11 pFrame, - OUT INT *Machine, - OUT INT *MsgType) + +void UpdateBasicRateBitmap(struct rt_rtmp_adapter *pAdapter) +{ + int i, j; + /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ + u8 rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; + u8 *sup_p = pAdapter->CommonCfg.SupRate; + u8 *ext_p = pAdapter->CommonCfg.ExtRate; + unsigned long bitmap = pAdapter->CommonCfg.BasicRateBitmap; + + /* if A mode, always use fix BasicRateBitMap */ + /*if (pAdapter->CommonCfg.Channel == PHY_11A) */ + if (pAdapter->CommonCfg.Channel > 14) + pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */ + /* End of if */ + + if (pAdapter->CommonCfg.BasicRateBitmap > 4095) { + /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */ + return; + } + /* End of if */ + for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) { + sup_p[i] &= 0x7f; + ext_p[i] &= 0x7f; + } /* End of for */ + + for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) { + if (bitmap & (1 << i)) { + for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) { + if (sup_p[j] == rate[i]) + sup_p[j] |= 0x80; + /* End of if */ + } /* End of for */ + + for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) { + if (ext_p[j] == rate[i]) + ext_p[j] |= 0x80; + /* End of if */ + } /* End of for */ + } /* End of if */ + } /* End of for */ +} /* End of UpdateBasicRateBitmap */ + +/* IRQL = PASSIVE_LEVEL */ +/* IRQL = DISPATCH_LEVEL */ +/* bLinkUp is to identify the inital link speed. */ +/* TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps. */ +void MlmeUpdateTxRates(struct rt_rtmp_adapter *pAd, IN BOOLEAN bLinkUp, u8 apidx) { - USHORT Seq; - UCHAR EAPType; - PUCHAR pData; + int i, num; + u8 Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1; + u8 MinSupport = RATE_54; + unsigned long BasicRateBitmap = 0; + u8 CurrBasicRate = RATE_1; + u8 *pSupRate, SupRateLen, *pExtRate, ExtRateLen; + PHTTRANSMIT_SETTING pHtPhy = NULL; + PHTTRANSMIT_SETTING pMaxHtPhy = NULL; + PHTTRANSMIT_SETTING pMinHtPhy = NULL; + BOOLEAN *auto_rate_cur_p; + u8 HtMcs = MCS_AUTO; + + /* find max desired rate */ + UpdateBasicRateBitmap(pAd); - // Pointer to start of data frames including SNAP header - pData = (PUCHAR) pFrame + LENGTH_802_11; + num = 0; + auto_rate_cur_p = NULL; + for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) { + switch (pAd->CommonCfg.DesireRate[i] & 0x7f) { + case 2: + Rate = RATE_1; + num++; + break; + case 4: + Rate = RATE_2; + num++; + break; + case 11: + Rate = RATE_5_5; + num++; + break; + case 22: + Rate = RATE_11; + num++; + break; + case 12: + Rate = RATE_6; + num++; + break; + case 18: + Rate = RATE_9; + num++; + break; + case 24: + Rate = RATE_12; + num++; + break; + case 36: + Rate = RATE_18; + num++; + break; + case 48: + Rate = RATE_24; + num++; + break; + case 72: + Rate = RATE_36; + num++; + break; + case 96: + Rate = RATE_48; + num++; + break; + case 108: + Rate = RATE_54; + num++; + break; + /*default: Rate = RATE_1; break; */ + } + if (MaxDesire < Rate) + MaxDesire = Rate; + } - // The only data type will pass to this function is EAPOL frame - if (pFrame->Hdr.FC.Type == BTYPE_DATA) +/*=========================================================================== */ +/*=========================================================================== */ { - if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H)) - { - // Cisco Aironet SNAP header - *Machine = AIRONET_STATE_MACHINE; - *MsgType = MT2_AIRONET_MSG; - return (TRUE); + pHtPhy = &pAd->StaCfg.HTPhyMode; + pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; + pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; + + auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; + HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS; + + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (pAd->CommonCfg.PhyMode == PHY_11B) && + (MaxDesire > RATE_11)) { + MaxDesire = RATE_11; } - { - *Machine = WPA_PSK_STATE_MACHINE; - EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1); - return(WpaMsgTypeSubst(EAPType, MsgType)); + } + + pAd->CommonCfg.MaxDesiredRate = MaxDesire; + pMinHtPhy->word = 0; + pMaxHtPhy->word = 0; + pHtPhy->word = 0; + + /* Auto rate switching is enabled only if more than one DESIRED RATES are */ + /* specified; otherwise disabled */ + if (num <= 1) { + /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */ + /*pAd->CommonCfg.bAutoTxRateSwitch = FALSE; */ + *auto_rate_cur_p = FALSE; + } else { + /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */ + /*pAd->CommonCfg.bAutoTxRateSwitch = TRUE; */ + *auto_rate_cur_p = TRUE; + } + + if (HtMcs != MCS_AUTO) { + /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */ + /*pAd->CommonCfg.bAutoTxRateSwitch = FALSE; */ + *auto_rate_cur_p = FALSE; + } else { + /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */ + /*pAd->CommonCfg.bAutoTxRateSwitch = TRUE; */ + *auto_rate_cur_p = TRUE; + } + + if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) { + pSupRate = &pAd->StaActive.SupRate[0]; + pExtRate = &pAd->StaActive.ExtRate[0]; + SupRateLen = pAd->StaActive.SupRateLen; + ExtRateLen = pAd->StaActive.ExtRateLen; + } else { + pSupRate = &pAd->CommonCfg.SupRate[0]; + pExtRate = &pAd->CommonCfg.ExtRate[0]; + SupRateLen = pAd->CommonCfg.SupRateLen; + ExtRateLen = pAd->CommonCfg.ExtRateLen; + } + + /* find max supported rate */ + for (i = 0; i < SupRateLen; i++) { + switch (pSupRate[i] & 0x7f) { + case 2: + Rate = RATE_1; + if (pSupRate[i] & 0x80) + BasicRateBitmap |= 0x0001; + break; + case 4: + Rate = RATE_2; + if (pSupRate[i] & 0x80) + BasicRateBitmap |= 0x0002; + break; + case 11: + Rate = RATE_5_5; + if (pSupRate[i] & 0x80) + BasicRateBitmap |= 0x0004; + break; + case 22: + Rate = RATE_11; + if (pSupRate[i] & 0x80) + BasicRateBitmap |= 0x0008; + break; + case 12: + Rate = RATE_6; /*if (pSupRate[i] & 0x80) */ + BasicRateBitmap |= 0x0010; + break; + case 18: + Rate = RATE_9; + if (pSupRate[i] & 0x80) + BasicRateBitmap |= 0x0020; + break; + case 24: + Rate = RATE_12; /*if (pSupRate[i] & 0x80) */ + BasicRateBitmap |= 0x0040; + break; + case 36: + Rate = RATE_18; + if (pSupRate[i] & 0x80) + BasicRateBitmap |= 0x0080; + break; + case 48: + Rate = RATE_24; /*if (pSupRate[i] & 0x80) */ + BasicRateBitmap |= 0x0100; + break; + case 72: + Rate = RATE_36; + if (pSupRate[i] & 0x80) + BasicRateBitmap |= 0x0200; + break; + case 96: + Rate = RATE_48; + if (pSupRate[i] & 0x80) + BasicRateBitmap |= 0x0400; + break; + case 108: + Rate = RATE_54; + if (pSupRate[i] & 0x80) + BasicRateBitmap |= 0x0800; + break; + default: + Rate = RATE_1; + break; } + if (MaxSupport < Rate) + MaxSupport = Rate; + + if (MinSupport > Rate) + MinSupport = Rate; } - switch (pFrame->Hdr.FC.SubType) - { - case SUBTYPE_ASSOC_REQ: - *Machine = ASSOC_STATE_MACHINE; - *MsgType = MT2_PEER_ASSOC_REQ; + for (i = 0; i < ExtRateLen; i++) { + switch (pExtRate[i] & 0x7f) { + case 2: + Rate = RATE_1; + if (pExtRate[i] & 0x80) + BasicRateBitmap |= 0x0001; break; - case SUBTYPE_ASSOC_RSP: - *Machine = ASSOC_STATE_MACHINE; - *MsgType = MT2_PEER_ASSOC_RSP; + case 4: + Rate = RATE_2; + if (pExtRate[i] & 0x80) + BasicRateBitmap |= 0x0002; break; - case SUBTYPE_REASSOC_REQ: - *Machine = ASSOC_STATE_MACHINE; - *MsgType = MT2_PEER_REASSOC_REQ; + case 11: + Rate = RATE_5_5; + if (pExtRate[i] & 0x80) + BasicRateBitmap |= 0x0004; break; - case SUBTYPE_REASSOC_RSP: - *Machine = ASSOC_STATE_MACHINE; - *MsgType = MT2_PEER_REASSOC_RSP; + case 22: + Rate = RATE_11; + if (pExtRate[i] & 0x80) + BasicRateBitmap |= 0x0008; break; - case SUBTYPE_PROBE_REQ: - *Machine = SYNC_STATE_MACHINE; - *MsgType = MT2_PEER_PROBE_REQ; + case 12: + Rate = RATE_6; /*if (pExtRate[i] & 0x80) */ + BasicRateBitmap |= 0x0010; break; - case SUBTYPE_PROBE_RSP: - *Machine = SYNC_STATE_MACHINE; - *MsgType = MT2_PEER_PROBE_RSP; + case 18: + Rate = RATE_9; + if (pExtRate[i] & 0x80) + BasicRateBitmap |= 0x0020; break; - case SUBTYPE_BEACON: - *Machine = SYNC_STATE_MACHINE; - *MsgType = MT2_PEER_BEACON; + case 24: + Rate = RATE_12; /*if (pExtRate[i] & 0x80) */ + BasicRateBitmap |= 0x0040; break; - case SUBTYPE_ATIM: - *Machine = SYNC_STATE_MACHINE; - *MsgType = MT2_PEER_ATIM; + case 36: + Rate = RATE_18; + if (pExtRate[i] & 0x80) + BasicRateBitmap |= 0x0080; break; - case SUBTYPE_DISASSOC: - *Machine = ASSOC_STATE_MACHINE; - *MsgType = MT2_PEER_DISASSOC_REQ; + case 48: + Rate = RATE_24; /*if (pExtRate[i] & 0x80) */ + BasicRateBitmap |= 0x0100; break; - case SUBTYPE_AUTH: - // get the sequence number from payload 24 Mac Header + 2 bytes algorithm - NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT)); - if (Seq == 1 || Seq == 3) - { - *Machine = AUTH_RSP_STATE_MACHINE; - *MsgType = MT2_PEER_AUTH_ODD; - } - else if (Seq == 2 || Seq == 4) - { - *Machine = AUTH_STATE_MACHINE; - *MsgType = MT2_PEER_AUTH_EVEN; - } - else - { - return FALSE; - } + case 72: + Rate = RATE_36; + if (pExtRate[i] & 0x80) + BasicRateBitmap |= 0x0200; break; - case SUBTYPE_DEAUTH: - *Machine = AUTH_RSP_STATE_MACHINE; - *MsgType = MT2_PEER_DEAUTH; + case 96: + Rate = RATE_48; + if (pExtRate[i] & 0x80) + BasicRateBitmap |= 0x0400; break; - case SUBTYPE_ACTION: - *Machine = ACTION_STATE_MACHINE; - // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support - if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG) - { - *MsgType = MT2_ACT_INVALID; - } - else - { - *MsgType = (pFrame->Octet[0]&0x7F); - } + case 108: + Rate = RATE_54; + if (pExtRate[i] & 0x80) + BasicRateBitmap |= 0x0800; break; default: - return FALSE; + Rate = RATE_1; break; + } + if (MaxSupport < Rate) + MaxSupport = Rate; + + if (MinSupport > Rate) + MinSupport = Rate; } - return TRUE; -} + RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap); -// =========================================================================================== -// state_machine.c -// =========================================================================================== + /* bug fix */ + /* pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap; */ -/*! \brief Initialize the state machine. - * \param *S pointer to the state machine - * \param Trans State machine transition function - * \param StNr number of states - * \param MsgNr number of messages - * \param DefFunc default function, when there is invalid state/message combination - * \param InitState initial state of the state machine - * \param Base StateMachine base, internal use only - * \pre p_sm should be a legal pointer - * \post + /* calculate the exptected ACK rate for each TX rate. This info is used to caculate */ + /* the DURATION field of outgoing uniicast DATA/MGMT frame */ + for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) { + if (BasicRateBitmap & (0x01 << i)) + CurrBasicRate = (u8)i; + pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate; + } - IRQL = PASSIVE_LEVEL + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", + RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire])); + /* max tx rate = min {max desire rate, max supported rate} */ + if (MaxSupport < MaxDesire) + pAd->CommonCfg.MaxTxRate = MaxSupport; + else + pAd->CommonCfg.MaxTxRate = MaxDesire; - */ -VOID StateMachineInit( - IN STATE_MACHINE *S, - IN STATE_MACHINE_FUNC Trans[], - IN ULONG StNr, - IN ULONG MsgNr, - IN STATE_MACHINE_FUNC DefFunc, - IN ULONG InitState, - IN ULONG Base) -{ - ULONG i, j; + pAd->CommonCfg.MinTxRate = MinSupport; + /* 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success */ + /* ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending */ + /* on average RSSI */ + /* 1. RSSI >= -70db, start at 54 Mbps (short distance) */ + /* 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance) */ + /* 3. -75 > RSSI, start at 11 Mbps (long distance) */ + if (*auto_rate_cur_p) { + short dbm = 0; - // set number of states and messages - S->NrState = StNr; - S->NrMsg = MsgNr; - S->Base = Base; + dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta; + + if (bLinkUp == TRUE) + pAd->CommonCfg.TxRate = RATE_24; + else + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; - S->TransFunc = Trans; + if (dbm < -75) + pAd->CommonCfg.TxRate = RATE_11; + else if (dbm < -70) + pAd->CommonCfg.TxRate = RATE_24; - // init all state transition to default function - for (i = 0; i < StNr; i++) - { - for (j = 0; j < MsgNr; j++) - { - S->TransFunc[i * MsgNr + j] = DefFunc; + /* should never exceed MaxTxRate (consider 11B-only mode) */ + if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate) + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; + + pAd->CommonCfg.TxRateIndex = 0; + } else { + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; + pHtPhy->field.MCS = + (pAd->CommonCfg.MaxTxRate > + 3) ? (pAd->CommonCfg.MaxTxRate - + 4) : pAd->CommonCfg.MaxTxRate; + pHtPhy->field.MODE = + (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK; + + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = + pHtPhy->field.STBC; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = + pHtPhy->field.ShortGI; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = + pHtPhy->field.MCS; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = + pHtPhy->field.MODE; + } + + if (pAd->CommonCfg.TxRate <= RATE_11) { + pMaxHtPhy->field.MODE = MODE_CCK; + pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate; + pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate; + } else { + pMaxHtPhy->field.MODE = MODE_OFDM; + pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate]; + if (pAd->CommonCfg.MinTxRate >= RATE_6 + && (pAd->CommonCfg.MinTxRate <= RATE_54)) { + pMinHtPhy->field.MCS = + OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate]; + } else { + pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate; + } + } + + pHtPhy->word = (pMaxHtPhy->word); + if (bLinkUp && (pAd->OpMode == OPMODE_STA)) { + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word; + pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = + pMaxHtPhy->word; + pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = + pMinHtPhy->word; + } else { + switch (pAd->CommonCfg.PhyMode) { + case PHY_11BG_MIXED: + case PHY_11B: + case PHY_11BGN_MIXED: + pAd->CommonCfg.MlmeRate = RATE_1; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; + +/*#ifdef WIFI_TEST */ + pAd->CommonCfg.RtsRate = RATE_11; +/*#else */ +/* pAd->CommonCfg.RtsRate = RATE_1; */ +/*#endif */ + break; + case PHY_11G: + case PHY_11A: + case PHY_11AGN_MIXED: + case PHY_11GN_MIXED: + case PHY_11N_2_4G: + case PHY_11AN_MIXED: + case PHY_11N_5G: + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.RtsRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = + OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + break; + case PHY_11ABG_MIXED: + case PHY_11ABGN_MIXED: + if (pAd->CommonCfg.Channel <= 14) { + pAd->CommonCfg.MlmeRate = RATE_1; + pAd->CommonCfg.RtsRate = RATE_1; + pAd->CommonCfg.MlmeTransmit.field.MODE = + MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; + } else { + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.RtsRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = + MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = + OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } + break; + default: /* error */ + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = + OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + pAd->CommonCfg.RtsRate = RATE_1; + break; } + /* */ + /* Keep Basic Mlme Rate. */ + /* */ + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = + pAd->CommonCfg.MlmeTransmit.word; + if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM) + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = + OfdmRateToRxwiMCS[RATE_24]; + else + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = + RATE_1; + pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate; } - // set the starting state - S->CurrState = InitState; + DBGPRINT(RT_DEBUG_TRACE, + (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n", + RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], + RateIdToMbps[pAd->CommonCfg.MaxTxRate], + RateIdToMbps[pAd->CommonCfg.MinTxRate], + /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) */ + *auto_rate_cur_p)); + DBGPRINT(RT_DEBUG_TRACE, + (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n", + RateIdToMbps[pAd->CommonCfg.TxRate], + RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap)); + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n", + pAd->CommonCfg.MlmeTransmit.word, + pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word, + pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word, + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word)); } -/*! \brief This function fills in the function pointer into the cell in the state machine - * \param *S pointer to the state machine - * \param St state - * \param Msg incoming message - * \param f the function to be executed when (state, message) combination occurs at the state machine - * \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state - * \post +/* + ========================================================================== + Description: + This function update HT Rate setting. + Input Wcid value is valid for 2 case : + 1. it's used for Station in infra mode that copy AP rate to Mactable. + 2. OR Station in adhoc mode to copy peer's HT rate to Mactable. - IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + ========================================================================== */ -VOID StateMachineSetAction( - IN STATE_MACHINE *S, - IN ULONG St, - IN ULONG Msg, - IN STATE_MACHINE_FUNC Func) +void MlmeUpdateHtTxRates(struct rt_rtmp_adapter *pAd, u8 apidx) { - ULONG MsgIdx; + u8 StbcMcs; /*j, StbcMcs, bitmask; */ + char i; /* 3*3 */ + struct rt_ht_capability *pRtHtCap = NULL; + struct rt_ht_phy_info *pActiveHtPhy = NULL; + unsigned long BasicMCS; + u8 j, bitmask; + struct rt_ht_phy_info *pDesireHtPhy = NULL; + PHTTRANSMIT_SETTING pHtPhy = NULL; + PHTTRANSMIT_SETTING pMaxHtPhy = NULL; + PHTTRANSMIT_SETTING pMinHtPhy = NULL; + BOOLEAN *auto_rate_cur_p; + + DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates===> \n")); - MsgIdx = Msg - S->Base; + auto_rate_cur_p = NULL; - if (St < S->NrState && MsgIdx < S->NrMsg) { - // boundary checking before setting the action - S->TransFunc[St * S->NrMsg + MsgIdx] = Func; - } -} - -/*! \brief This function does the state transition - * \param *Adapter the NIC adapter pointer - * \param *S the state machine - * \param *Elem the message to be executed - * \return None + pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; + pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; + pHtPhy = &pAd->StaCfg.HTPhyMode; + pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; + pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; - IRQL = DISPATCH_LEVEL - - */ -VOID StateMachinePerformAction( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - IN MLME_QUEUE_ELEM *Elem) -{ - (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem); -} - -/* - ========================================================================== - Description: - The drop function, when machine executes this, the message is simply - ignored. This function does nothing, the message is freed in - StateMachinePerformAction() - ========================================================================== - */ -VOID Drop( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ -} + auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; + } -// =========================================================================================== -// lfsr.c -// =========================================================================================== + if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) { + if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) + return; -/* - ========================================================================== - Description: + pRtHtCap = &pAd->StaActive.SupportedHtPhy; + pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo; + StbcMcs = (u8)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs; + BasicMCS = + pAd->MlmeAux.AddHtInfo.MCSSet[0] + + (pAd->MlmeAux.AddHtInfo.MCSSet[1] << 8) + (StbcMcs << 16); + if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) + && (pAd->Antenna.field.TxPath == 2)) + pMaxHtPhy->field.STBC = STBC_USE; + else + pMaxHtPhy->field.STBC = STBC_NONE; + } else { + if (pDesireHtPhy->bHtEnable == FALSE) + return; - IRQL = PASSIVE_LEVEL + pRtHtCap = &pAd->CommonCfg.DesiredHtPhy; + StbcMcs = (u8)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs; + BasicMCS = + pAd->CommonCfg.AddHTInfo.MCSSet[0] + + (pAd->CommonCfg.AddHTInfo.MCSSet[1] << 8) + (StbcMcs << 16); + if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) + && (pAd->Antenna.field.TxPath == 2)) + pMaxHtPhy->field.STBC = STBC_USE; + else + pMaxHtPhy->field.STBC = STBC_NONE; + } - ========================================================================== - */ -VOID LfsrInit( - IN PRTMP_ADAPTER pAd, - IN ULONG Seed) -{ - if (Seed == 0) - pAd->Mlme.ShiftReg = 1; + /* Decide MAX ht rate. */ + if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) + pMaxHtPhy->field.MODE = MODE_HTGREENFIELD; else - pAd->Mlme.ShiftReg = Seed; -} + pMaxHtPhy->field.MODE = MODE_HTMIX; -/* - ========================================================================== - Description: - ========================================================================== - */ -UCHAR RandomByte( - IN PRTMP_ADAPTER pAd) -{ - ULONG i; - UCHAR R, Result; + if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) + && (pRtHtCap->ChannelWidth)) + pMaxHtPhy->field.BW = BW_40; + else + pMaxHtPhy->field.BW = BW_20; - R = 0; + if (pMaxHtPhy->field.BW == BW_20) + pMaxHtPhy->field.ShortGI = + (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap-> + ShortGIfor20); + else + pMaxHtPhy->field.ShortGI = + (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap-> + ShortGIfor40); - if (pAd->Mlme.ShiftReg == 0) - NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg); + if (pDesireHtPhy->MCSSet[4] != 0) { + pMaxHtPhy->field.MCS = 32; + } - for (i = 0; i < 8; i++) + for (i = 23; i >= 0; i--) /* 3*3 */ { - if (pAd->Mlme.ShiftReg & 0x00000001) - { - pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000; - Result = 1; - } - else - { - pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1; - Result = 0; + j = i / 8; + bitmask = (1 << (i - (j * 8))); + + if ((pActiveHtPhy->MCSSet[j] & bitmask) + && (pDesireHtPhy->MCSSet[j] & bitmask)) { + pMaxHtPhy->field.MCS = i; + break; } - R = (R << 1) | Result; + + if (i == 0) + break; } - return R; -} + /* Copy MIN ht rate. rt2860??? */ + pMinHtPhy->field.BW = BW_20; + pMinHtPhy->field.MCS = 0; + pMinHtPhy->field.STBC = 0; + pMinHtPhy->field.ShortGI = 0; + /*If STA assigns fixed rate. update to fixed here. */ + if ((pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)) { + if (pDesireHtPhy->MCSSet[4] != 0) { + pMaxHtPhy->field.MCS = 32; + pMinHtPhy->field.MCS = 32; + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n", + pMinHtPhy->field.MCS)); + } -VOID AsicUpdateAutoFallBackTable( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pRateTable) -{ - UCHAR i; - HT_FBK_CFG0_STRUC HtCfg0; - HT_FBK_CFG1_STRUC HtCfg1; - LG_FBK_CFG0_STRUC LgCfg0; - LG_FBK_CFG1_STRUC LgCfg1; - PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate; - - // set to initial value - HtCfg0.word = 0x65432100; - HtCfg1.word = 0xedcba988; - LgCfg0.word = 0xedcba988; - LgCfg1.word = 0x00002100; - - pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1; - for (i = 1; i < *((PUCHAR) pRateTable); i++) - { - pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i; - switch (pCurrTxRate->Mode) + for (i = 23; (char)i >= 0; i--) /* 3*3 */ { - case 0: //CCK - break; - case 1: //OFDM - { - switch(pCurrTxRate->CurrMCS) - { - case 0: - LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - case 1: - LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - case 2: - LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - case 3: - LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - case 4: - LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - case 5: - LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - case 6: - LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - case 7: - LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - } - } + j = i / 8; + bitmask = (1 << (i - (j * 8))); + if ((pDesireHtPhy->MCSSet[j] & bitmask) + && (pActiveHtPhy->MCSSet[j] & bitmask)) { + pMaxHtPhy->field.MCS = i; + pMinHtPhy->field.MCS = i; break; - case 2: //HT-MIX - case 3: //HT-GF - { - if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS)) - { - switch(pCurrTxRate->CurrMCS) - { - case 0: - HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS; - break; - case 1: - HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS; - break; - case 2: - HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS; - break; - case 3: - HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS; - break; - case 4: - HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS; - break; - case 5: - HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS; - break; - case 6: - HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS; - break; - case 7: - HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS; - break; - case 8: - HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS; - break; - case 9: - HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS; - break; - case 10: - HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS; - break; - case 11: - HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS; - break; - case 12: - HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS; - break; - case 13: - HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS; - break; - case 14: - HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS; - break; - case 15: - HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS; - break; - default: - DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS)); - } - } - } + } + if (i == 0) break; } - - pNextTxRate = pCurrTxRate; } - RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word); - RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word); - RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word); - RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word); -} + /* Decide ht rate */ + pHtPhy->field.STBC = pMaxHtPhy->field.STBC; + pHtPhy->field.BW = pMaxHtPhy->field.BW; + pHtPhy->field.MODE = pMaxHtPhy->field.MODE; + pHtPhy->field.MCS = pMaxHtPhy->field.MCS; + pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI; -/* - ======================================================================== + /* use default now. rt2860 */ + if (pDesireHtPhy->MCSSet[0] != 0xff) + *auto_rate_cur_p = FALSE; + else + *auto_rate_cur_p = TRUE; - Routine Description: - Set MAC register value according operation mode. - OperationMode AND bNonGFExist are for MM and GF Proteciton. - If MM or GF mask is not set, those passing argument doesn't not take effect. - - Operation mode meaning: - = 0 : Pure HT, no preotection. - = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS. - = 0x10: No Transmission in 40M is protected. - = 0x11: Transmission in both 40M and 20M shall be protected - if (bNonGFExist) - we should choose not to use GF. But still set correct ASIC registers. - ======================================================================== -*/ -VOID AsicUpdateProtect( - IN PRTMP_ADAPTER pAd, - IN USHORT OperationMode, - IN UCHAR SetMask, - IN BOOLEAN bDisableBGProtect, - IN BOOLEAN bNonGFExist) + DBGPRINT(RT_DEBUG_TRACE, + (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", + pAd->CommonCfg.DesiredHtPhy.AmsduSize)); + DBGPRINT(RT_DEBUG_TRACE, + ("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", + pActiveHtPhy->MCSSet[0], pHtPhy->field.MCS, pHtPhy->field.BW, + pHtPhy->field.ShortGI, pHtPhy->field.MODE)); + DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates<=== \n")); +} + +void BATableInit(struct rt_rtmp_adapter *pAd, struct rt_ba_table *Tab) { - PROT_CFG_STRUC ProtCfg, ProtCfg4; - UINT32 Protect[6]; - USHORT offset; - UCHAR i; - UINT32 MacReg = 0; + int i; - if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8)) - { - return; + Tab->numAsOriginator = 0; + Tab->numAsRecipient = 0; + Tab->numDoneOriginator = 0; + NdisAllocateSpinLock(&pAd->BATabLock); + for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) { + Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE; + NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock)); } - - if (pAd->BATable.numAsOriginator) - { - // - // enable the RTS/CTS to avoid channel collision - // - SetMask = ALLN_SETPROTECT; - OperationMode = 8; + for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) { + Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE; } +} - // Config ASIC RTS threshold register - RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); - MacReg &= 0xFF0000FF; - - // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096 - if (( - (pAd->CommonCfg.BACapability.field.AmsduEnable) || - (pAd->CommonCfg.bAggregationCapable == TRUE)) - && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD) - { - MacReg |= (0x1000 << 8); - } - else - { - MacReg |= (pAd->CommonCfg.RtsThreshold << 8); - } - - RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); - - // Initial common protection settings - RTMPZeroMemory(Protect, sizeof(Protect)); - ProtCfg4.word = 0; - ProtCfg.word = 0; - ProtCfg.field.TxopAllowGF40 = 1; - ProtCfg.field.TxopAllowGF20 = 1; - ProtCfg.field.TxopAllowMM40 = 1; - ProtCfg.field.TxopAllowMM20 = 1; - ProtCfg.field.TxopAllowOfdm = 1; - ProtCfg.field.TxopAllowCck = 1; - ProtCfg.field.RTSThEn = 1; - ProtCfg.field.ProtectNav = ASIC_SHORTNAV; - - // update PHY mode and rate - if (pAd->CommonCfg.Channel > 14) - ProtCfg.field.ProtectRate = 0x4000; - ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate; - - // Handle legacy(B/G) protection - if (bDisableBGProtect) - { - //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; - ProtCfg.field.ProtectCtrl = 0; - Protect[0] = ProtCfg.word; - Protect[1] = ProtCfg.word; - } - else - { - //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; - ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected - Protect[0] = ProtCfg.word; - ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect - Protect[1] = ProtCfg.word; - } +/* IRQL = DISPATCH_LEVEL */ +void MlmeRadioOff(struct rt_rtmp_adapter *pAd) +{ + RTMP_MLME_RADIO_OFF(pAd); +} - // Decide HT frame protection. - if ((SetMask & ALLN_SETPROTECT) != 0) - { - switch(OperationMode) - { - case 0x0: - // NO PROTECT - // 1.All STAs in the BSS are 20/40 MHz HT - // 2. in ai 20/40MHz BSS - // 3. all STAs are 20MHz in a 20MHz BSS - // Pure HT. no protection. - - // MM20_PROT_CFG - // Reserved (31:27) - // PROT_TXOP(25:20) -- 010111 - // PROT_NAV(19:18) -- 01 (Short NAV protection) - // PROT_CTRL(17:16) -- 00 (None) - // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) - Protect[2] = 0x01744004; - - // MM40_PROT_CFG - // Reserved (31:27) - // PROT_TXOP(25:20) -- 111111 - // PROT_NAV(19:18) -- 01 (Short NAV protection) - // PROT_CTRL(17:16) -- 00 (None) - // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) - Protect[3] = 0x03f44084; - - // CF20_PROT_CFG - // Reserved (31:27) - // PROT_TXOP(25:20) -- 010111 - // PROT_NAV(19:18) -- 01 (Short NAV protection) - // PROT_CTRL(17:16) -- 00 (None) - // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) - Protect[4] = 0x01744004; - - // CF40_PROT_CFG - // Reserved (31:27) - // PROT_TXOP(25:20) -- 111111 - // PROT_NAV(19:18) -- 01 (Short NAV protection) - // PROT_CTRL(17:16) -- 00 (None) - // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) - Protect[5] = 0x03f44084; - - if (bNonGFExist) - { - // PROT_NAV(19:18) -- 01 (Short NAV protectiion) - // PROT_CTRL(17:16) -- 01 (RTS/CTS) - Protect[4] = 0x01754004; - Protect[5] = 0x03f54084; - } - pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; - break; +/* IRQL = DISPATCH_LEVEL */ +void MlmeRadioOn(struct rt_rtmp_adapter *pAd) +{ + RTMP_MLME_RADIO_ON(pAd); +} - case 1: - // This is "HT non-member protection mode." - // If there may be non-HT STAs my BSS - ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None) - ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1. - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) - { - ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18.. - ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083; - } - //Assign Protection method for 20&40 MHz packets - ProtCfg.field.ProtectCtrl = ASIC_RTS; - ProtCfg.field.ProtectNav = ASIC_SHORTNAV; - ProtCfg4.field.ProtectCtrl = ASIC_RTS; - ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; - Protect[2] = ProtCfg.word; - Protect[3] = ProtCfg4.word; - Protect[4] = ProtCfg.word; - Protect[5] = ProtCfg4.word; - pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; - break; +/* =========================================================================================== */ +/* bss_table.c */ +/* =========================================================================================== */ - case 2: - // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets - ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None) - ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1. - - //Assign Protection method for 40MHz packets - ProtCfg4.field.ProtectCtrl = ASIC_RTS; - ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; - Protect[2] = ProtCfg.word; - Protect[3] = ProtCfg4.word; - if (bNonGFExist) - { - ProtCfg.field.ProtectCtrl = ASIC_RTS; - ProtCfg.field.ProtectNav = ASIC_SHORTNAV; - } - Protect[4] = ProtCfg.word; - Protect[5] = ProtCfg4.word; +/*! \brief initialize BSS table + * \param p_tab pointer to the table + * \return none + * \pre + * \post - pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; - break; + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL - case 3: - // HT mixed mode. PROTECT ALL! - // Assign Rate - ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1. - ProtCfg4.word = 0x03f44084; - // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) - { - ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18.. - ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083 - } - //Assign Protection method for 20&40 MHz packets - ProtCfg.field.ProtectCtrl = ASIC_RTS; - ProtCfg.field.ProtectNav = ASIC_SHORTNAV; - ProtCfg4.field.ProtectCtrl = ASIC_RTS; - ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; - Protect[2] = ProtCfg.word; - Protect[3] = ProtCfg4.word; - Protect[4] = ProtCfg.word; - Protect[5] = ProtCfg4.word; - pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; - break; + */ +void BssTableInit(struct rt_bss_table *Tab) +{ + int i; - case 8: - // Special on for Atheros problem n chip. - Protect[2] = 0x01754004; - Protect[3] = 0x03f54084; - Protect[4] = 0x01754004; - Protect[5] = 0x03f54084; - pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; - break; - } + Tab->BssNr = 0; + Tab->BssOverlapNr = 0; + for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) { + NdisZeroMemory(&Tab->BssEntry[i], sizeof(struct rt_bss_entry)); + Tab->BssEntry[i].Rssi = -127; /* initial the rssi as a minimum value */ } +} - offset = CCK_PROT_CFG; - for (i = 0;i < 6;i++) - { - if ((SetMask & (1<< i))) - { - RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]); +/*! \brief search the BSS table by SSID + * \param p_tab pointer to the bss table + * \param ssid SSID string + * \return index of the table, BSS_NOT_FOUND if not in the table + * \pre + * \post + * \note search by sequential search + + IRQL = DISPATCH_LEVEL + + */ +unsigned long BssTableSearch(struct rt_bss_table *Tab, u8 *pBssid, u8 Channel) +{ + u8 i; + + for (i = 0; i < Tab->BssNr; i++) { + /* */ + /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */ + /* We should distinguish this case. */ + /* */ + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) { + return i; } } + return (unsigned long)BSS_NOT_FOUND; } -#ifdef RT2870 -/* - ========================================================================== - Description: +unsigned long BssSsidTableSearch(struct rt_bss_table *Tab, + u8 *pBssid, + u8 *pSsid, u8 SsidLen, u8 Channel) +{ + u8 i; - Load RF normal operation-mode setup + for (i = 0; i < Tab->BssNr; i++) { + /* */ + /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */ + /* We should distinguish this case. */ + /* */ + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) && + SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, + Tab->BssEntry[i].SsidLen)) { + return i; + } + } + return (unsigned long)BSS_NOT_FOUND; +} - ========================================================================== - */ -VOID RT30xxLoadRFNormalModeSetup( - IN PRTMP_ADAPTER pAd) +unsigned long BssTableSearchWithSSID(struct rt_bss_table *Tab, + u8 *Bssid, + u8 *pSsid, + u8 SsidLen, u8 Channel) { - UCHAR RFValue; - - // RX0_PD & TX0_PD, RF R1 register Bit 2 & Bit 3 to 0 and RF_BLOCK_en,RX1_PD & TX1_PD, Bit0, Bit 4 & Bit5 to 1 - RT30xxReadRFRegister(pAd, RF_R01, &RFValue); - RFValue = (RFValue & (~0x0C)) | 0x31; - RT30xxWriteRFRegister(pAd, RF_R01, RFValue); - - // TX_LO2_en, RF R15 register Bit 3 to 0 - RT30xxReadRFRegister(pAd, RF_R15, &RFValue); - RFValue &= (~0x08); - RT30xxWriteRFRegister(pAd, RF_R15, RFValue); - - // TX_LO1_en, RF R17 register Bit 3 to 0 - RT30xxReadRFRegister(pAd, RF_R17, &RFValue); - RFValue &= (~0x08); - // to fix rx long range issue - if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0)) - { - RFValue |= 0x20; + u8 i; + + for (i = 0; i < Tab->BssNr; i++) { + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) && + (SSID_EQUAL + (pSsid, SsidLen, Tab->BssEntry[i].Ssid, + Tab->BssEntry[i].SsidLen) + || (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) + || + (NdisEqualMemory + (Tab->BssEntry[i].Ssid, ZeroSsid, + Tab->BssEntry[i].SsidLen)))) { + return i; + } } - RT30xxWriteRFRegister(pAd, RF_R17, RFValue); - - // RX_LO1_en, RF R20 register Bit 3 to 0 - RT30xxReadRFRegister(pAd, RF_R20, &RFValue); - RFValue &= (~0x08); - RT30xxWriteRFRegister(pAd, RF_R20, RFValue); - - // RX_LO2_en, RF R21 register Bit 3 to 0 - RT30xxReadRFRegister(pAd, RF_R21, &RFValue); - RFValue &= (~0x08); - RT30xxWriteRFRegister(pAd, RF_R21, RFValue); - - // LDORF_VC, RF R27 register Bit 2 to 0 - RT30xxReadRFRegister(pAd, RF_R27, &RFValue); - if ((pAd->MACVersion & 0xffff) < 0x0211) - RFValue = (RFValue & (~0x77)) | 0x3; - else - RFValue = (RFValue & (~0x77)); - RT30xxWriteRFRegister(pAd, RF_R27, RFValue); - /* end johnli */ + return (unsigned long)BSS_NOT_FOUND; } -/* - ========================================================================== - Description: +unsigned long BssSsidTableSearchBySSID(struct rt_bss_table *Tab, + u8 *pSsid, u8 SsidLen) +{ + u8 i; - Load RF sleep-mode setup + for (i = 0; i < Tab->BssNr; i++) { + if (SSID_EQUAL + (pSsid, SsidLen, Tab->BssEntry[i].Ssid, + Tab->BssEntry[i].SsidLen)) { + return i; + } + } + return (unsigned long)BSS_NOT_FOUND; +} - ========================================================================== - */ -VOID RT30xxLoadRFSleepModeSetup( - IN PRTMP_ADAPTER pAd) +/* IRQL = DISPATCH_LEVEL */ +void BssTableDeleteEntry(struct rt_bss_table *Tab, + u8 *pBssid, u8 Channel) { - UCHAR RFValue; - UINT32 MACValue; - - // RF_BLOCK_en. RF R1 register Bit 0 to 0 - RT30xxReadRFRegister(pAd, RF_R01, &RFValue); - RFValue &= (~0x01); - RT30xxWriteRFRegister(pAd, RF_R01, RFValue); - - // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0 - RT30xxReadRFRegister(pAd, RF_R07, &RFValue); - RFValue &= (~0x30); - RT30xxWriteRFRegister(pAd, RF_R07, RFValue); - - // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0 - RT30xxReadRFRegister(pAd, RF_R09, &RFValue); - RFValue &= (~0x0E); - RT30xxWriteRFRegister(pAd, RF_R09, RFValue); - - // RX_CTB_en, RF R21 register Bit 7 to 0 - RT30xxReadRFRegister(pAd, RF_R21, &RFValue); - RFValue &= (~0x80); - RT30xxWriteRFRegister(pAd, RF_R21, RFValue); - - // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1 - RT30xxReadRFRegister(pAd, RF_R27, &RFValue); - RFValue |= 0x77; - RT30xxWriteRFRegister(pAd, RF_R27, RFValue); - - RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue); - MACValue |= 0x1D000000; - RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue); -} + u8 i, j; -/* - ========================================================================== - Description: + for (i = 0; i < Tab->BssNr; i++) { + if ((Tab->BssEntry[i].Channel == Channel) && + (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) { + for (j = i; j < Tab->BssNr - 1; j++) { + NdisMoveMemory(&(Tab->BssEntry[j]), + &(Tab->BssEntry[j + 1]), + sizeof(struct rt_bss_entry)); + } + NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), + sizeof(struct rt_bss_entry)); + Tab->BssNr -= 1; + return; + } + } +} - Reverse RF sleep-mode setup +/* + ======================================================================== + Routine Description: + Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed. - ========================================================================== - */ -VOID RT30xxReverseRFSleepModeSetup( - IN PRTMP_ADAPTER pAd) + Arguments: + // IRQL = DISPATCH_LEVEL + ======================================================================== +*/ +void BATableDeleteORIEntry(struct rt_rtmp_adapter *pAd, + struct rt_ba_ori_entry *pBAORIEntry) { - UCHAR RFValue; - UINT32 MACValue; - - // RF_BLOCK_en, RF R1 register Bit 0 to 1 - RT30xxReadRFRegister(pAd, RF_R01, &RFValue); - RFValue |= 0x01; - RT30xxWriteRFRegister(pAd, RF_R01, RFValue); - - // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1 - RT30xxReadRFRegister(pAd, RF_R07, &RFValue); - RFValue |= 0x30; - RT30xxWriteRFRegister(pAd, RF_R07, RFValue); - - // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1 - RT30xxReadRFRegister(pAd, RF_R09, &RFValue); - RFValue |= 0x0E; - RT30xxWriteRFRegister(pAd, RF_R09, RFValue); - - // RX_CTB_en, RF R21 register Bit 7 to 1 - RT30xxReadRFRegister(pAd, RF_R21, &RFValue); - RFValue |= 0x80; - RT30xxWriteRFRegister(pAd, RF_R21, RFValue); - - // LDORF_VC, RF R27 register Bit 2 to 0 - RT30xxReadRFRegister(pAd, RF_R27, &RFValue); - if ((pAd->MACVersion & 0xffff) < 0x0211) - RFValue = (RFValue & (~0x77)) | 0x3; - else - RFValue = (RFValue & (~0x77)); - RT30xxWriteRFRegister(pAd, RF_R27, RFValue); - // RT3071 version E has fixed this issue - if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211)) - { - // patch tx EVM issue temporarily - RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue); - MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000); - RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue); - } - else - { - RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue); - MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000); - RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue); + if (pBAORIEntry->ORI_BA_Status != Originator_NONE) { + NdisAcquireSpinLock(&pAd->BATabLock); + if (pBAORIEntry->ORI_BA_Status == Originator_Done) { + pAd->BATable.numAsOriginator -= 1; + DBGPRINT(RT_DEBUG_TRACE, + ("BATableDeleteORIEntry numAsOriginator= %ld\n", + pAd->BATable.numAsRecipient)); + /* Erase Bitmap flag. */ + } + pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1 << (pBAORIEntry->TID))); /* If STA mode, erase flag here */ + pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; /* If STA mode, erase flag here */ + pBAORIEntry->ORI_BA_Status = Originator_NONE; + pBAORIEntry->Token = 1; + /* Not clear Sequence here. */ + NdisReleaseSpinLock(&pAd->BATabLock); } } -#endif -/* - ========================================================================== - Description: +/*! \brief + * \param + * \return + * \pre + * \post - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL + IRQL = DISPATCH_LEVEL - ========================================================================== */ -VOID AsicSwitchChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel, - IN BOOLEAN bScan) +void BssEntrySet(struct rt_rtmp_adapter *pAd, struct rt_bss_entry *pBss, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * pCfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo, /* AP might use this additional ht info IE */ + u8 HtCapabilityLen, + u8 AddHtInfoLen, + u8 NewExtChanOffset, + u8 Channel, + char Rssi, + IN LARGE_INTEGER TimeStamp, + u8 CkipFlag, + struct rt_edca_parm *pEdcaParm, + struct rt_qos_capability_parm *pQosCapability, + struct rt_qbss_load_parm *pQbssLoad, + u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE) { - ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0; - CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER; - UCHAR index; - UINT32 Value = 0; //BbpReg, Value; - RTMP_RF_REGS *RFRegTable; - - // Search Tx power value - // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list - // in ChannelList, so use TxPower array instead. - // - for (index = 0; index < MAX_NUM_OF_CHANNELS; index++) - { - if (Channel == pAd->TxPower[index].Channel) - { - TxPwer = pAd->TxPower[index].Power; - TxPwer2 = pAd->TxPower[index].Power2; - break; + COPY_MAC_ADDR(pBss->Bssid, pBssid); + /* Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID */ + pBss->Hidden = 1; + if (SsidLen > 0) { + /* For hidden SSID AP, it might send beacon with SSID len equal to 0 */ + /* Or send beacon /probe response with SSID len matching real SSID length, */ + /* but SSID is all zero. such as "00-00-00-00" with length 4. */ + /* We have to prevent this case overwrite correct table */ + if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) { + NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pBss->Ssid, Ssid, SsidLen); + pBss->SsidLen = SsidLen; + pBss->Hidden = 0; + } + } else + pBss->SsidLen = 0; + pBss->BssType = BssType; + pBss->BeaconPeriod = BeaconPeriod; + if (BssType == BSS_INFRA) { + if (pCfParm->bValid) { + pBss->CfpCount = pCfParm->CfpCount; + pBss->CfpPeriod = pCfParm->CfpPeriod; + pBss->CfpMaxDuration = pCfParm->CfpMaxDuration; + pBss->CfpDurRemaining = pCfParm->CfpDurRemaining; } + } else { + pBss->AtimWin = AtimWin; } - if (index == MAX_NUM_OF_CHANNELS) - DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel)); + pBss->CapabilityInfo = CapabilityInfo; + /* The privacy bit indicate security is ON, it maight be WEP, TKIP or AES */ + /* Combine with AuthMode, they will decide the connection methods. */ + pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo); + ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES); + if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) + NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen); + else + NdisMoveMemory(pBss->SupRate, SupRate, + MAX_LEN_OF_SUPPORTED_RATES); + pBss->SupRateLen = SupRateLen; + ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES); + NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen); + pBss->NewExtChanOffset = NewExtChanOffset; + pBss->ExtRateLen = ExtRateLen; + pBss->Channel = Channel; + pBss->CentralChannel = Channel; + pBss->Rssi = Rssi; + /* Update CkipFlag. if not exists, the value is 0x0 */ + pBss->CkipFlag = CkipFlag; + + /* New for microsoft Fixed IEs */ + NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8); + pBss->FixIEs.BeaconInterval = BeaconPeriod; + pBss->FixIEs.Capabilities = CapabilityInfo; -#ifdef RT2870 - // The RF programming sequence is difference between 3xxx and 2xxx - if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ( - (pAd->RfIcType == RFIC_3022) || (pAd->RfIcType == RFIC_3021) || - (pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020))) - { - /* modify by WY for Read RF Reg. error */ - UCHAR RFValue; + /* New for microsoft Variable IEs */ + if (LengthVIE != 0) { + pBss->VarIELen = LengthVIE; + NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen); + } else { + pBss->VarIELen = 0; + } - for (index = 0; index < NUM_OF_3020_CHNL; index++) - { - if (Channel == FreqItems3020[index].Channel) - { - // Programming channel parameters - RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N); - RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K); - - RT30xxReadRFRegister(pAd, RF_R06, &RFValue); - RFValue = (RFValue & 0xFC) | FreqItems3020[index].R; - RT30xxWriteRFRegister(pAd, RF_R06, RFValue); - - // Set Tx0 Power - RT30xxReadRFRegister(pAd, RF_R12, &RFValue); - RFValue = (RFValue & 0xE0) | TxPwer; - RT30xxWriteRFRegister(pAd, RF_R12, RFValue); - - // Set Tx1 Power - RT30xxReadRFRegister(pAd, RF_R13, &RFValue); - RFValue = (RFValue & 0xE0) | TxPwer2; - RT30xxWriteRFRegister(pAd, RF_R13, RFValue); - - // Tx/Rx Stream setting - RT30xxReadRFRegister(pAd, RF_R01, &RFValue); - //if (IS_RT3090(pAd)) - // RFValue |= 0x01; // Enable RF block. - RFValue &= 0x03; //clear bit[7~2] - if (pAd->Antenna.field.TxPath == 1) - RFValue |= 0xA0; - else if (pAd->Antenna.field.TxPath == 2) - RFValue |= 0x80; - if (pAd->Antenna.field.RxPath == 1) - RFValue |= 0x50; - else if (pAd->Antenna.field.RxPath == 2) - RFValue |= 0x40; - RT30xxWriteRFRegister(pAd, RF_R01, RFValue); - - // Set RF offset - RT30xxReadRFRegister(pAd, RF_R23, &RFValue); - RFValue = (RFValue & 0x80) | pAd->RfFreqOffset; - RT30xxWriteRFRegister(pAd, RF_R23, RFValue); - - // Set BW - if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40)) - { - RFValue = pAd->Mlme.CaliBW40RfR24; - //DISABLE_11N_CHECK(pAd); - } - else - { - RFValue = pAd->Mlme.CaliBW20RfR24; - } - RT30xxWriteRFRegister(pAd, RF_R24, RFValue); - RT30xxWriteRFRegister(pAd, RF_R31, RFValue); - - // Enable RF tuning - RT30xxReadRFRegister(pAd, RF_R07, &RFValue); - RFValue = RFValue | 0x1; - RT30xxWriteRFRegister(pAd, RF_R07, RFValue); - - // latch channel for future usage. - pAd->LatchRfRegs.Channel = Channel; - - DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", - Channel, - pAd->RfIcType, - TxPwer, - TxPwer2, - pAd->Antenna.field.TxPath, - FreqItems3020[index].N, - FreqItems3020[index].K, - FreqItems3020[index].R)); - break; + pBss->AddHtInfoLen = 0; + pBss->HtCapabilityLen = 0; + if (HtCapabilityLen > 0) { + pBss->HtCapabilityLen = HtCapabilityLen; + NdisMoveMemory(&pBss->HtCapability, pHtCapability, + HtCapabilityLen); + if (AddHtInfoLen > 0) { + pBss->AddHtInfoLen = AddHtInfoLen; + NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, + AddHtInfoLen); + + if ((pAddHtInfo->ControlChan > 2) + && (pAddHtInfo->AddHtInfo.ExtChanOffset == + EXTCHA_BELOW) + && (pHtCapability->HtCapInfo.ChannelWidth == + BW_40)) { + pBss->CentralChannel = + pAddHtInfo->ControlChan - 2; + } else + if ((pAddHtInfo->AddHtInfo.ExtChanOffset == + EXTCHA_ABOVE) + && (pHtCapability->HtCapInfo.ChannelWidth == + BW_40)) { + pBss->CentralChannel = + pAddHtInfo->ControlChan + 2; } } - - DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", - Channel, - pAd->RfIcType, - TxPwer, - TxPwer2, - pAd->Antenna.field.TxPath, - FreqItems3020[index].N, - FreqItems3020[index].K, - FreqItems3020[index].R)); } - else -#endif // RT2870 // - { - RFRegTable = RF2850RegTable; - switch (pAd->RfIcType) - { - case RFIC_2820: - case RFIC_2850: - case RFIC_2720: - case RFIC_2750: + BssCipherParse(pBss); - for (index = 0; index < NUM_OF_2850_CHNL; index++) - { - if (Channel == RFRegTable[index].Channel) - { - R2 = RFRegTable[index].R2; - if (pAd->Antenna.field.TxPath == 1) - { - R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; - } + /* new for QOS */ + if (pEdcaParm) + NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(struct rt_edca_parm)); + else + pBss->EdcaParm.bValid = FALSE; + if (pQosCapability) + NdisMoveMemory(&pBss->QosCapability, pQosCapability, + sizeof(struct rt_qos_capability_parm)); + else + pBss->QosCapability.bValid = FALSE; + if (pQbssLoad) + NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, + sizeof(struct rt_qbss_load_parm)); + else + pBss->QbssLoad.bValid = FALSE; - if (pAd->Antenna.field.RxPath == 2) - { - R2 |= 0x40; // write 1 to off Rxpath. - } - else if (pAd->Antenna.field.RxPath == 1) - { - R2 |= 0x20040; // write 1 to off RxPath - } + { + struct rt_eid * pEid; + u16 Length = 0; - if (Channel > 14) - { - // initialize R3, R4 - R3 = (RFRegTable[index].R3 & 0xffffc1ff); - R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15); - - // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB - // R3 - if ((TxPwer >= -7) && (TxPwer < 0)) - { - TxPwer = (7+TxPwer); - TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); - R3 |= (TxPwer << 10); - DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer)); - } - else - { - TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); - R3 |= (TxPwer << 10) | (1 << 9); - } - - // R4 - if ((TxPwer2 >= -7) && (TxPwer2 < 0)) - { - TxPwer2 = (7+TxPwer2); - TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); - R4 |= (TxPwer2 << 7); - DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2)); - } - else - { - TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); - R4 |= (TxPwer2 << 7) | (1 << 6); - } - } - else - { - R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0 - R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1 + NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN); + NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN); + pEid = (struct rt_eid *) pVIE; + while ((Length + 2 + (u16)pEid->Len) <= LengthVIE) { + switch (pEid->Eid) { + case IE_WPA: + if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) { + if ((pEid->Len + 2) > MAX_CUSTOM_LEN) { + pBss->WpaIE.IELen = 0; + break; } - - // Based on BBP current mode before changing RF channel. - if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40)) - { - R4 |=0x200000; + pBss->WpaIE.IELen = pEid->Len + 2; + NdisMoveMemory(pBss->WpaIE.IE, pEid, + pBss->WpaIE.IELen); + } + break; + case IE_RSN: + if (NdisEqualMemory + (pEid->Octet + 2, RSN_OUI, 3)) { + if ((pEid->Len + 2) > MAX_CUSTOM_LEN) { + pBss->RsnIE.IELen = 0; + break; } - - // Update variables - pAd->LatchRfRegs.Channel = Channel; - pAd->LatchRfRegs.R1 = RFRegTable[index].R1; - pAd->LatchRfRegs.R2 = R2; - pAd->LatchRfRegs.R3 = R3; - pAd->LatchRfRegs.R4 = R4; - - // Set RF value 1's set R3[bit2] = [0] - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); - RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); - - RTMPusecDelay(200); - - // Set RF value 2's set R3[bit2] = [1] - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); - RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04)); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); - - RTMPusecDelay(200); - - // Set RF value 3's set R3[bit2] = [0] - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); - RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); - - break; + pBss->RsnIE.IELen = pEid->Len + 2; + NdisMoveMemory(pBss->RsnIE.IE, pEid, + pBss->RsnIE.IELen); } + break; } - break; - - default: - break; + Length = Length + 2 + (u16)pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ + pEid = (struct rt_eid *) ((u8 *) pEid + 2 + pEid->Len); } } +} - // Change BBP setting during siwtch from a->g, g->a - if (Channel <= 14) - { - ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A - - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. - //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); - - // Rx High power VGA offset for LNA select - if (pAd->NicConfig2.field.ExternalLNAForG) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); - } - else - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); - } - - // 5G band selection PIN, bit1 and bit2 are complement - RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); - Value &= (~0x6); - Value |= (0x04); - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); - - // Turn off unused PA or LNA when only 1T or 1R - if (pAd->Antenna.field.TxPath == 1) - { - TxPinCfg &= 0xFFFFFFF3; - } - if (pAd->Antenna.field.RxPath == 1) - { - TxPinCfg &= 0xFFFFF3FF; - } - - RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); - } - else - { - ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505 +/*! + * \brief insert an entry into the bss table + * \param p_tab The BSS table + * \param Bssid BSSID + * \param ssid SSID + * \param ssid_len Length of SSID + * \param bss_type + * \param beacon_period + * \param timestamp + * \param p_cf + * \param atim_win + * \param cap + * \param rates + * \param rates_len + * \param channel_idx + * \return none + * \pre + * \post + * \note If SSID is identical, the old entry will be replaced by the new one - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); + IRQL = DISPATCH_LEVEL - // Rx High power VGA offset for LNA select - if (pAd->NicConfig2.field.ExternalLNAForA) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + */ +unsigned long BssTableSetEntry(struct rt_rtmp_adapter *pAd, struct rt_bss_table *Tab, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * CfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo, /* AP might use this additional ht info IE */ + u8 HtCapabilityLen, + u8 AddHtInfoLen, + u8 NewExtChanOffset, + u8 ChannelNo, + char Rssi, + IN LARGE_INTEGER TimeStamp, + u8 CkipFlag, + struct rt_edca_parm *pEdcaParm, + struct rt_qos_capability_parm *pQosCapability, + struct rt_qbss_load_parm *pQbssLoad, + u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE) +{ + unsigned long Idx; + + Idx = + BssTableSearchWithSSID(Tab, pBssid, (u8 *) Ssid, SsidLen, + ChannelNo); + if (Idx == BSS_NOT_FOUND) { + if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) { + /* */ + /* It may happen when BSS Table was full. */ + /* The desired AP will not be added into BSS Table */ + /* In this case, if we found the desired AP then overwrite BSS Table. */ + /* */ + if (!OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) + || SSID_EQUAL(pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen, Ssid, + SsidLen)) { + Idx = Tab->BssOverlapNr; + BssEntrySet(pAd, &Tab->BssEntry[Idx], + pBssid, Ssid, SsidLen, + BssType, BeaconPeriod, + CfParm, AtimWin, + CapabilityInfo, SupRate, + SupRateLen, ExtRate, + ExtRateLen, pHtCapability, + pAddHtInfo, HtCapabilityLen, + AddHtInfoLen, + NewExtChanOffset, ChannelNo, + Rssi, TimeStamp, CkipFlag, + pEdcaParm, pQosCapability, + pQbssLoad, LengthVIE, pVIE); + Tab->BssOverlapNr = + (Tab->BssOverlapNr++) % + MAX_LEN_OF_BSS_TABLE; + } + return Idx; + } else { + return BSS_NOT_FOUND; + } } - else - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + Idx = Tab->BssNr; + BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, + BssType, BeaconPeriod, CfParm, AtimWin, + CapabilityInfo, SupRate, SupRateLen, ExtRate, + ExtRateLen, pHtCapability, pAddHtInfo, + HtCapabilityLen, AddHtInfoLen, NewExtChanOffset, + ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, + pQosCapability, pQbssLoad, LengthVIE, pVIE); + Tab->BssNr++; + } else { + /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */ + if ((SSID_EQUAL + (Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, + Tab->BssEntry[Idx].SsidLen)) + || + (NdisEqualMemory + (Tab->BssEntry[Idx].Ssid, ZeroSsid, + Tab->BssEntry[Idx].SsidLen))) { + BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, + SsidLen, BssType, BeaconPeriod, CfParm, + AtimWin, CapabilityInfo, SupRate, + SupRateLen, ExtRate, ExtRateLen, + pHtCapability, pAddHtInfo, HtCapabilityLen, + AddHtInfoLen, NewExtChanOffset, ChannelNo, + Rssi, TimeStamp, CkipFlag, pEdcaParm, + pQosCapability, pQbssLoad, LengthVIE, pVIE); } - - // 5G band selection PIN, bit1 and bit2 are complement - RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); - Value &= (~0x6); - Value |= (0x02); - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); - - // Turn off unused PA or LNA when only 1T or 1R - if (pAd->Antenna.field.TxPath == 1) - { - TxPinCfg &= 0xFFFFFFF3; } - if (pAd->Antenna.field.RxPath == 1) - { - TxPinCfg &= 0xFFFFF3FF; - } - - RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); - } - - // R66 should be set according to Channel and use 20MHz when scanning - //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd))); - if (bScan) - RTMPSetAGCInitValue(pAd, BW_20); - else - RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); - - // - // On 11A, We should delay and wait RF/BBP to be stable - // and the appropriate time should be 1000 micro seconds - // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL. - // - RTMPusecDelay(1000); - - DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", - Channel, - pAd->RfIcType, - (R3 & 0x00003e00) >> 9, - (R4 & 0x000007c0) >> 6, - pAd->Antenna.field.TxPath, - pAd->LatchRfRegs.R1, - pAd->LatchRfRegs.R2, - pAd->LatchRfRegs.R3, - pAd->LatchRfRegs.R4)); -} - -/* - ========================================================================== - Description: - This function is required for 2421 only, and should not be used during - site survey. It's only required after NIC decided to stay at a channel - for a longer period. - When this function is called, it's always after AsicSwitchChannel(). - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - ========================================================================== - */ -VOID AsicLockChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel) -{ + return Idx; } -VOID AsicRfTuningExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) +/* IRQL = DISPATCH_LEVEL */ +void BssTableSsidSort(struct rt_rtmp_adapter *pAd, + struct rt_bss_table *OutTab, char Ssid[], u8 SsidLen) { -} + int i; + BssTableInit(OutTab); -/* - ========================================================================== - Description: - Gives CCK TX rate 2 more dB TX power. - This routine works only in LINK UP in INFRASTRUCTURE mode. - - calculate desired Tx power in RF R3.Tx0~5, should consider - - 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) - 1. TxPowerPercentage - 2. auto calibration based on TSSI feedback - 3. extra 2 db for CCK - 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP - - NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), - it should be called AFTER MlmeDynamicTxRatSwitching() - ========================================================================== - */ -VOID AsicAdjustTxPower( - IN PRTMP_ADAPTER pAd) -{ - INT i, j; - CHAR DeltaPwr = 0; - BOOLEAN bAutoTxAgc = FALSE; - UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; - UCHAR BbpR1 = 0, BbpR49 = 0, idx; - PCHAR pTxAgcCompensate; - ULONG TxPwr[5]; - CHAR Value; - -#ifdef RT2860 - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) - || (pAd->bPCIclkOff == TRUE) - || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF) - || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - return; -#endif + for (i = 0; i < pAd->ScanTab.BssNr; i++) { + struct rt_bss_entry *pInBss = &pAd->ScanTab.BssEntry[i]; + BOOLEAN bIsHiddenApIncluded = FALSE; - if (pAd->CommonCfg.BBPCurrentBW == BW_40) - { - if (pAd->CommonCfg.CentralChannel > 14) - { - TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; - TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; - TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; - TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; - TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; - } - else - { - TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; - TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; - TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; - TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; - TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; - } - } - else - { - if (pAd->CommonCfg.Channel > 14) - { - TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; - TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; - TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; - TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; - TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; - } - else - { - TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; - TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; - TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; - TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; - TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; + if (((pAd->CommonCfg.bIEEE80211H == 1) && + (pAd->MlmeAux.Channel > 14) && + RadarChannelCheck(pAd, pInBss->Channel)) + ) { + if (pInBss->Hidden) + bIsHiddenApIncluded = TRUE; } - } - // TX power compensation for temperature variation based on TSSI. try every 4 second - if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) - { - if (pAd->CommonCfg.Channel <= 14) - { - /* bg channel */ - bAutoTxAgc = pAd->bAutoTxAgcG; - TssiRef = pAd->TssiRefG; - pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; - pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; - TxAgcStep = pAd->TxAgcStepG; - pTxAgcCompensate = &pAd->TxAgcCompensateG; - } - else - { - /* a channel */ - bAutoTxAgc = pAd->bAutoTxAgcA; - TssiRef = pAd->TssiRefA; - pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; - pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; - TxAgcStep = pAd->TxAgcStepA; - pTxAgcCompensate = &pAd->TxAgcCompensateA; - } + if ((pInBss->BssType == pAd->StaCfg.BssType) && + (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) + || bIsHiddenApIncluded)) { + struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; - if (bAutoTxAgc) - { - /* BbpR1 is unsigned char */ - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + /* 2.4G/5G N only mode */ + if ((pInBss->HtCapabilityLen == 0) && + ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) + || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) { + DBGPRINT(RT_DEBUG_TRACE, + ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); + continue; + } + /* New for WPA2 */ + /* Check the Authmode first */ + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) { + /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */ + if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) + && (pAd->StaCfg.AuthMode != + pInBss->AuthModeAux)) + /* None matched */ + continue; + + /* Check cipher suite, AP must have more secured cipher than station setting */ + if ((pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA) + || (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPAPSK)) { + /* If it's not mixed mode, we should only let BSS pass with the same encryption */ + if (pInBss->WPA.bMixMode == FALSE) + if (pAd->StaCfg.WepStatus != + pInBss->WPA.GroupCipher) + continue; - /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ - /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ - /* step value is defined in pAd->TxAgcStepG for tx power value */ + /* check group cipher */ + if ((pAd->StaCfg.WepStatus < + pInBss->WPA.GroupCipher) + && (pInBss->WPA.GroupCipher != + Ndis802_11GroupWEP40Enabled) + && (pInBss->WPA.GroupCipher != + Ndis802_11GroupWEP104Enabled)) + continue; - /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ - /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 - above value are examined in mass factory production */ - /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ + /* check pairwise cipher, skip if none matched */ + /* If profile set to AES, let it pass without question. */ + /* If profile set to TKIP, we must find one mateched */ + if ((pAd->StaCfg.WepStatus == + Ndis802_11Encryption2Enabled) + && (pAd->StaCfg.WepStatus != + pInBss->WPA.PairCipher) + && (pAd->StaCfg.WepStatus != + pInBss->WPA.PairCipherAux)) + continue; + } else + if ((pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2) + || (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2PSK)) { + /* If it's not mixed mode, we should only let BSS pass with the same encryption */ + if (pInBss->WPA2.bMixMode == FALSE) + if (pAd->StaCfg.WepStatus != + pInBss->WPA2.GroupCipher) + continue; - /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */ - /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ - /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */ + /* check group cipher */ + if ((pAd->StaCfg.WepStatus < + pInBss->WPA.GroupCipher) + && (pInBss->WPA2.GroupCipher != + Ndis802_11GroupWEP40Enabled) + && (pInBss->WPA2.GroupCipher != + Ndis802_11GroupWEP104Enabled)) + continue; - if (BbpR49 > pTssiMinusBoundary[1]) - { - // Reading is larger than the reference value - // check for how large we need to decrease the Tx power - for (idx = 1; idx < 5; idx++) - { - if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range - break; + /* check pairwise cipher, skip if none matched */ + /* If profile set to AES, let it pass without question. */ + /* If profile set to TKIP, we must find one mateched */ + if ((pAd->StaCfg.WepStatus == + Ndis802_11Encryption2Enabled) + && (pAd->StaCfg.WepStatus != + pInBss->WPA2.PairCipher) + && (pAd->StaCfg.WepStatus != + pInBss->WPA2.PairCipherAux)) + continue; } - // The index is the step we should decrease, idx = 0 means there is nothing to compensate - *pTxAgcCompensate = -(TxAgcStep * (idx-1)); - - DeltaPwr += (*pTxAgcCompensate); - DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", - BbpR49, TssiRef, TxAgcStep, idx-1)); } - else if (BbpR49 < pTssiPlusBoundary[1]) - { - // Reading is smaller than the reference value - // check for how large we need to increase the Tx power - for (idx = 1; idx < 5; idx++) - { - if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range - break; + /* Bss Type matched, SSID matched. */ + /* We will check wepstatus for qualification Bss */ + else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) { + DBGPRINT(RT_DEBUG_TRACE, + ("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", + pAd->StaCfg.WepStatus, + pInBss->WepStatus)); + /* */ + /* For the SESv2 case, we will not qualify WepStatus. */ + /* */ + if (!pInBss->bSES) + continue; + } + /* Since the AP is using hidden SSID, and we are trying to connect to ANY */ + /* It definitely will fail. So, skip it. */ + /* CCX also require not even try to connect it! */ + if (SsidLen == 0) + continue; + + /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */ + /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */ + if ((pInBss->CentralChannel != pInBss->Channel) && + (pAd->CommonCfg.RegTransmitSetting.field.BW == + BW_40)) { + if (RTMPCheckChannel + (pAd, pInBss->CentralChannel, + pInBss->Channel) == FALSE) { + pAd->CommonCfg.RegTransmitSetting.field. + BW = BW_20; + SetCommonHT(pAd); + pAd->CommonCfg.RegTransmitSetting.field. + BW = BW_40; + } else { + if (pAd->CommonCfg.DesiredHtPhy. + ChannelWidth == BAND_WIDTH_20) { + SetCommonHT(pAd); + } } - // The index is the step we should increase, idx = 0 means there is nothing to compensate - *pTxAgcCompensate = TxAgcStep * (idx-1); - DeltaPwr += (*pTxAgcCompensate); - DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", - BbpR49, TssiRef, TxAgcStep, idx-1)); } - else - { - *pTxAgcCompensate = 0; - DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", - BbpR49, TssiRef, TxAgcStep, 0)); + /* copy matching BSS from InTab to OutTab */ + NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry)); + + OutTab->BssNr++; + } else if ((pInBss->BssType == pAd->StaCfg.BssType) + && (SsidLen == 0)) { + struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; + + /* 2.4G/5G N only mode */ + if ((pInBss->HtCapabilityLen == 0) && + ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) + || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) { + DBGPRINT(RT_DEBUG_TRACE, + ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); + continue; } - } - } - else - { - if (pAd->CommonCfg.Channel <= 14) - { - bAutoTxAgc = pAd->bAutoTxAgcG; - pTxAgcCompensate = &pAd->TxAgcCompensateG; - } - else - { - bAutoTxAgc = pAd->bAutoTxAgcA; - pTxAgcCompensate = &pAd->TxAgcCompensateA; - } + /* New for WPA2 */ + /* Check the Authmode first */ + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) { + /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */ + if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) + && (pAd->StaCfg.AuthMode != + pInBss->AuthModeAux)) + /* None matched */ + continue; - if (bAutoTxAgc) - DeltaPwr += (*pTxAgcCompensate); - } + /* Check cipher suite, AP must have more secured cipher than station setting */ + if ((pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA) + || (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPAPSK)) { + /* If it's not mixed mode, we should only let BSS pass with the same encryption */ + if (pInBss->WPA.bMixMode == FALSE) + if (pAd->StaCfg.WepStatus != + pInBss->WPA.GroupCipher) + continue; - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); - BbpR1 &= 0xFC; - - /* calculate delta power based on the percentage specified from UI */ - // E2PROM setting is calibrated for maximum TX power (i.e. 100%) - // We lower TX power here according to the percentage specified from UI - if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control - ; - else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW - ; - else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1; - { - DeltaPwr -= 1; - } - else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3; - { - DeltaPwr -= 3; - } - else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6; - { - BbpR1 |= 0x01; - } - else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9; - { - BbpR1 |= 0x01; - DeltaPwr -= 3; - } - else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12; - { - BbpR1 |= 0x02; - } + /* check group cipher */ + if (pAd->StaCfg.WepStatus < + pInBss->WPA.GroupCipher) + continue; - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + /* check pairwise cipher, skip if none matched */ + /* If profile set to AES, let it pass without question. */ + /* If profile set to TKIP, we must find one mateched */ + if ((pAd->StaCfg.WepStatus == + Ndis802_11Encryption2Enabled) + && (pAd->StaCfg.WepStatus != + pInBss->WPA.PairCipher) + && (pAd->StaCfg.WepStatus != + pInBss->WPA.PairCipherAux)) + continue; + } else + if ((pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2) + || (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2PSK)) { + /* If it's not mixed mode, we should only let BSS pass with the same encryption */ + if (pInBss->WPA2.bMixMode == FALSE) + if (pAd->StaCfg.WepStatus != + pInBss->WPA2.GroupCipher) + continue; - /* reset different new tx power for different TX rate */ - for(i=0; i<5; i++) - { - if (TxPwr[i] != 0xffffffff) - { - for (j=0; j<8; j++) - { - Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */ + /* check group cipher */ + if (pAd->StaCfg.WepStatus < + pInBss->WPA2.GroupCipher) + continue; - if ((Value + DeltaPwr) < 0) - { - Value = 0; /* min */ - } - else if ((Value + DeltaPwr) > 0xF) - { - Value = 0xF; /* max */ - } - else - { - Value += DeltaPwr; /* temperature compensation */ + /* check pairwise cipher, skip if none matched */ + /* If profile set to AES, let it pass without question. */ + /* If profile set to TKIP, we must find one mateched */ + if ((pAd->StaCfg.WepStatus == + Ndis802_11Encryption2Enabled) + && (pAd->StaCfg.WepStatus != + pInBss->WPA2.PairCipher) + && (pAd->StaCfg.WepStatus != + pInBss->WPA2.PairCipherAux)) + continue; } + } + /* Bss Type matched, SSID matched. */ + /* We will check wepstatus for qualification Bss */ + else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) + continue; - /* fill new value to CSR offset */ - TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); + /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */ + /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */ + if ((pInBss->CentralChannel != pInBss->Channel) && + (pAd->CommonCfg.RegTransmitSetting.field.BW == + BW_40)) { + if (RTMPCheckChannel + (pAd, pInBss->CentralChannel, + pInBss->Channel) == FALSE) { + pAd->CommonCfg.RegTransmitSetting.field. + BW = BW_20; + SetCommonHT(pAd); + pAd->CommonCfg.RegTransmitSetting.field. + BW = BW_40; + } } + /* copy matching BSS from InTab to OutTab */ + NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry)); - /* write tx power value to CSR */ - /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M - TX power for OFDM 6M/9M - TX power for CCK5.5M/11M - TX power for CCK1M/2M */ - /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ - RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]); + OutTab->BssNr++; } + + if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE) + break; } + BssTableSortByRssi(OutTab); } -/* - ========================================================================== - Description: - put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup - automatically. Instead, MCU will issue a TwakeUpInterrupt to host after - the wakeup timer timeout. Driver has to issue a separate command to wake - PHY up. - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AsicSleepThenAutoWakeup( - IN PRTMP_ADAPTER pAd, - IN USHORT TbttNumToNextWakeUp) +/* IRQL = DISPATCH_LEVEL */ +void BssTableSortByRssi(struct rt_bss_table *OutTab) { - RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp); + int i, j; + struct rt_bss_entry TmpBss; + + for (i = 0; i < OutTab->BssNr - 1; i++) { + for (j = i + 1; j < OutTab->BssNr; j++) { + if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi) { + NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], + sizeof(struct rt_bss_entry)); + NdisMoveMemory(&OutTab->BssEntry[j], + &OutTab->BssEntry[i], + sizeof(struct rt_bss_entry)); + NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, + sizeof(struct rt_bss_entry)); + } + } + } } -/* - ========================================================================== - Description: - AsicForceWakeup() is used whenever manual wakeup is required - AsicForceSleep() should only be used when not in INFRA BSS. When - in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead. - ========================================================================== - */ -VOID AsicForceSleep( - IN PRTMP_ADAPTER pAd) +void BssCipherParse(struct rt_bss_entry *pBss) { + struct rt_eid * pEid; + u8 *pTmp; + struct rt_rsn_ie_header * pRsnHeader; + struct rt_cipher_suite_struct * pCipher; + struct rt_akm_suite * pAKM; + u16 Count; + int Length; + NDIS_802_11_ENCRYPTION_STATUS TmpCipher; + + /* */ + /* WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame. */ + /* */ + if (pBss->Privacy) { + pBss->WepStatus = Ndis802_11WEPEnabled; + } else { + pBss->WepStatus = Ndis802_11WEPDisabled; + } + /* Set default to disable & open authentication before parsing variable IE */ + pBss->AuthMode = Ndis802_11AuthModeOpen; + pBss->AuthModeAux = Ndis802_11AuthModeOpen; + + /* Init WPA setting */ + pBss->WPA.PairCipher = Ndis802_11WEPDisabled; + pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled; + pBss->WPA.GroupCipher = Ndis802_11WEPDisabled; + pBss->WPA.RsnCapability = 0; + pBss->WPA.bMixMode = FALSE; -} + /* Init WPA2 setting */ + pBss->WPA2.PairCipher = Ndis802_11WEPDisabled; + pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled; + pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled; + pBss->WPA2.RsnCapability = 0; + pBss->WPA2.bMixMode = FALSE; + + Length = (int)pBss->VarIELen; + + while (Length > 0) { + /* Parse cipher suite base on WPA1 & WPA2, they should be parsed differently */ + pTmp = ((u8 *)pBss->VarIEs) + pBss->VarIELen - Length; + pEid = (struct rt_eid *) pTmp; + switch (pEid->Eid) { + case IE_WPA: + if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) + && (pEid->Len == 7)) { + pBss->bSES = TRUE; + break; + } else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != + 1) { + /* if unsupported vendor specific IE */ + break; + } + /* Skip OUI, version, and multicast suite */ + /* This part should be improved in the future when AP supported multiple cipher suite. */ + /* For now, it's OK since almost all APs have fixed cipher suite supported. */ + /* pTmp = (u8 *)pEid->Octet; */ + pTmp += 11; + + /* Cipher Suite Selectors from Spec P802.11i/D3.2 P26. */ + /* Value Meaning */ + /* 0 None */ + /* 1 WEP-40 */ + /* 2 Tkip */ + /* 3 WRAP */ + /* 4 AES */ + /* 5 WEP-104 */ + /* Parse group cipher */ + switch (*pTmp) { + case 1: + pBss->WPA.GroupCipher = + Ndis802_11GroupWEP40Enabled; + break; + case 5: + pBss->WPA.GroupCipher = + Ndis802_11GroupWEP104Enabled; + break; + case 2: + pBss->WPA.GroupCipher = + Ndis802_11Encryption2Enabled; + break; + case 4: + pBss->WPA.GroupCipher = + Ndis802_11Encryption3Enabled; + break; + default: + break; + } + /* number of unicast suite */ + pTmp += 1; + + /* skip all unicast cipher suites */ + /*Count = *(u16 *)pTmp; */ + Count = (pTmp[1] << 8) + pTmp[0]; + pTmp += sizeof(u16); + + /* Parsing all unicast cipher suite */ + while (Count > 0) { + /* Skip OUI */ + pTmp += 3; + TmpCipher = Ndis802_11WEPDisabled; + switch (*pTmp) { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ + TmpCipher = + Ndis802_11Encryption1Enabled; + break; + case 2: + TmpCipher = + Ndis802_11Encryption2Enabled; + break; + case 4: + TmpCipher = + Ndis802_11Encryption3Enabled; + break; + default: + break; + } + if (TmpCipher > pBss->WPA.PairCipher) { + /* Move the lower cipher suite to PairCipherAux */ + pBss->WPA.PairCipherAux = + pBss->WPA.PairCipher; + pBss->WPA.PairCipher = TmpCipher; + } else { + pBss->WPA.PairCipherAux = TmpCipher; + } + pTmp++; + Count--; + } -/* - ========================================================================== - Description: - AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup) - expired. + /* 4. get AKM suite counts */ + /*Count = *(u16 *)pTmp; */ + Count = (pTmp[1] << 8) + pTmp[0]; + pTmp += sizeof(u16); + pTmp += 3; + + switch (*pTmp) { + case 1: + /* Set AP support WPA-enterprise mode */ + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA; + else + pBss->AuthModeAux = + Ndis802_11AuthModeWPA; + break; + case 2: + /* Set AP support WPA-PSK mode */ + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = + Ndis802_11AuthModeWPAPSK; + else + pBss->AuthModeAux = + Ndis802_11AuthModeWPAPSK; + break; + default: + break; + } + pTmp += 1; + + /* Fixed for WPA-None */ + if (pBss->BssType == BSS_ADHOC) { + pBss->AuthMode = Ndis802_11AuthModeWPANone; + pBss->AuthModeAux = Ndis802_11AuthModeWPANone; + pBss->WepStatus = pBss->WPA.GroupCipher; + /* Patched bugs for old driver */ + if (pBss->WPA.PairCipherAux == + Ndis802_11WEPDisabled) + pBss->WPA.PairCipherAux = + pBss->WPA.GroupCipher; + } else + pBss->WepStatus = pBss->WPA.PairCipher; + + /* Check the Pair & Group, if different, turn on mixed mode flag */ + if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher) + pBss->WPA.bMixMode = TRUE; - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - ========================================================================== - */ -VOID AsicForceWakeup( - IN PRTMP_ADAPTER pAd, -#ifdef RT2860 - IN UCHAR Level) -#endif -#ifdef RT2870 - IN BOOLEAN bFromTx) -#endif -{ - DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n")); -#ifdef RT2860 - RT28XX_STA_FORCE_WAKEUP(pAd, Level); -#endif -#ifdef RT2870 - RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx); -#endif -} + break; -/* - ========================================================================== - Description: - Set My BSSID + case IE_RSN: + pRsnHeader = (struct rt_rsn_ie_header *) pTmp; - IRQL = DISPATCH_LEVEL + /* 0. Version must be 1 */ + if (le2cpu16(pRsnHeader->Version) != 1) + break; + pTmp += sizeof(struct rt_rsn_ie_header); - ========================================================================== - */ -VOID AsicSetBssid( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pBssid) -{ - ULONG Addr4; - DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n", - pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5])); + /* 1. Check group cipher */ + pCipher = (struct rt_cipher_suite_struct *) pTmp; + if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) + break; - Addr4 = (ULONG)(pBssid[0]) | - (ULONG)(pBssid[1] << 8) | - (ULONG)(pBssid[2] << 16) | - (ULONG)(pBssid[3] << 24); - RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); + /* Parse group cipher */ + switch (pCipher->Type) { + case 1: + pBss->WPA2.GroupCipher = + Ndis802_11GroupWEP40Enabled; + break; + case 5: + pBss->WPA2.GroupCipher = + Ndis802_11GroupWEP104Enabled; + break; + case 2: + pBss->WPA2.GroupCipher = + Ndis802_11Encryption2Enabled; + break; + case 4: + pBss->WPA2.GroupCipher = + Ndis802_11Encryption3Enabled; + break; + default: + break; + } + /* set to correct offset for next parsing */ + pTmp += sizeof(struct rt_cipher_suite_struct); + + /* 2. Get pairwise cipher counts */ + /*Count = *(u16 *)pTmp; */ + Count = (pTmp[1] << 8) + pTmp[0]; + pTmp += sizeof(u16); + + /* 3. Get pairwise cipher */ + /* Parsing all unicast cipher suite */ + while (Count > 0) { + /* Skip OUI */ + pCipher = (struct rt_cipher_suite_struct *) pTmp; + TmpCipher = Ndis802_11WEPDisabled; + switch (pCipher->Type) { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ + TmpCipher = + Ndis802_11Encryption1Enabled; + break; + case 2: + TmpCipher = + Ndis802_11Encryption2Enabled; + break; + case 4: + TmpCipher = + Ndis802_11Encryption3Enabled; + break; + default: + break; + } + if (TmpCipher > pBss->WPA2.PairCipher) { + /* Move the lower cipher suite to PairCipherAux */ + pBss->WPA2.PairCipherAux = + pBss->WPA2.PairCipher; + pBss->WPA2.PairCipher = TmpCipher; + } else { + pBss->WPA2.PairCipherAux = TmpCipher; + } + pTmp += sizeof(struct rt_cipher_suite_struct); + Count--; + } - Addr4 = 0; - // always one BSSID in STA mode - Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8); + /* 4. get AKM suite counts */ + /*Count = *(u16 *)pTmp; */ + Count = (pTmp[1] << 8) + pTmp[0]; + pTmp += sizeof(u16); - RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); -} + /* 5. Get AKM ciphers */ + /* Parsing all AKM ciphers */ + while (Count > 0) { + pAKM = (struct rt_akm_suite *) pTmp; + if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) + break; -VOID AsicSetMcastWC( - IN PRTMP_ADAPTER pAd) -{ - MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID]; - USHORT offset; - - pEntry->Sst = SST_ASSOC; - pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index - pEntry->PsMode = PWR_ACTIVE; - pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate; - offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE; -} + switch (pAKM->Type) { + case 1: + /* Set AP support WPA-enterprise mode */ + if (pBss->AuthMode == + Ndis802_11AuthModeOpen) + pBss->AuthMode = + Ndis802_11AuthModeWPA2; + else + pBss->AuthModeAux = + Ndis802_11AuthModeWPA2; + break; + case 2: + /* Set AP support WPA-PSK mode */ + if (pBss->AuthMode == + Ndis802_11AuthModeOpen) + pBss->AuthMode = + Ndis802_11AuthModeWPA2PSK; + else + pBss->AuthModeAux = + Ndis802_11AuthModeWPA2PSK; + break; + default: + if (pBss->AuthMode == + Ndis802_11AuthModeOpen) + pBss->AuthMode = + Ndis802_11AuthModeMax; + else + pBss->AuthModeAux = + Ndis802_11AuthModeMax; + break; + } + pTmp += (Count * sizeof(struct rt_akm_suite)); + Count--; + } -/* - ========================================================================== - Description: + /* Fixed for WPA-None */ + if (pBss->BssType == BSS_ADHOC) { + pBss->AuthMode = Ndis802_11AuthModeWPANone; + pBss->AuthModeAux = Ndis802_11AuthModeWPANone; + pBss->WPA.PairCipherAux = + pBss->WPA2.PairCipherAux; + pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher; + pBss->WepStatus = pBss->WPA.GroupCipher; + /* Patched bugs for old driver */ + if (pBss->WPA.PairCipherAux == + Ndis802_11WEPDisabled) + pBss->WPA.PairCipherAux = + pBss->WPA.GroupCipher; + } + pBss->WepStatus = pBss->WPA2.PairCipher; - IRQL = DISPATCH_LEVEL + /* 6. Get RSN capability */ + /*pBss->WPA2.RsnCapability = *(u16 *)pTmp; */ + pBss->WPA2.RsnCapability = (pTmp[1] << 8) + pTmp[0]; + pTmp += sizeof(u16); - ========================================================================== - */ -VOID AsicDelWcidTab( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid) -{ - ULONG Addr0 = 0x0, Addr1 = 0x0; - ULONG offset; - - DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid)); - offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE; - RTMP_IO_WRITE32(pAd, offset, Addr0); - offset += 4; - RTMP_IO_WRITE32(pAd, offset, Addr1); -} + /* Check the Pair & Group, if different, turn on mixed mode flag */ + if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher) + pBss->WPA2.bMixMode = TRUE; -/* - ========================================================================== - Description: + break; + default: + break; + } + Length -= (pEid->Len + 2); + } +} - IRQL = DISPATCH_LEVEL +/* =========================================================================================== */ +/* mac_table.c */ +/* =========================================================================================== */ - ========================================================================== +/*! \brief generates a random mac address value for IBSS BSSID + * \param Addr the bssid location + * \return none + * \pre + * \post */ -VOID AsicEnableRDG( - IN PRTMP_ADAPTER pAd) +void MacAddrRandomBssid(struct rt_rtmp_adapter *pAd, u8 *pAddr) { - TX_LINK_CFG_STRUC TxLinkCfg; - UINT32 Data = 0; - - RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); - TxLinkCfg.field.TxRDGEn = 1; - RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + int i; - RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); - Data &= 0xFFFFFF00; - Data |= 0x80; - RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + for (i = 0; i < MAC_ADDR_LEN; i++) { + pAddr[i] = RandomByte(pAd); + } - //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + pAddr[0] = (pAddr[0] & 0xfe) | 0x02; /* the first 2 bits must be 01xxxxxxxx */ } -/* - ========================================================================== - Description: +/*! \brief init the management mac frame header + * \param p_hdr mac header + * \param subtype subtype of the frame + * \param p_ds destination address, don't care if it is a broadcast address + * \return none + * \pre the station has the following information in the pAd->StaCfg + * - bssid + * - station address + * \post + * \note this function initializes the following field + IRQL = PASSIVE_LEVEL IRQL = DISPATCH_LEVEL - ========================================================================== */ -VOID AsicDisableRDG( - IN PRTMP_ADAPTER pAd) +void MgtMacHeaderInit(struct rt_rtmp_adapter *pAd, + struct rt_header_802_11 * pHdr80211, + u8 SubType, + u8 ToDs, u8 *pDA, u8 *pBssid) { - TX_LINK_CFG_STRUC TxLinkCfg; - UINT32 Data = 0; + NdisZeroMemory(pHdr80211, sizeof(struct rt_header_802_11)); - - RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); - TxLinkCfg.field.TxRDGEn = 0; - RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); - - RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); - - Data &= 0xFFFFFF00; - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE) - && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE) - ) - { - // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode - if (pAd->CommonCfg.bEnableTxBurst) - Data |= 0x20; - } - RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + pHdr80211->FC.Type = BTYPE_MGMT; + pHdr80211->FC.SubType = SubType; +/* if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type */ +/* pHdr80211->FC.Type = BTYPE_CNTL; */ + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pDA); + COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); } -/* - ========================================================================== - Description: +/* =========================================================================================== */ +/* mem_mgmt.c */ +/* =========================================================================================== */ - IRQL = PASSIVE_LEVEL +/*!*************************************************************************** + * This routine build an outgoing frame, and fill all information specified + * in argument list to the frame body. The actual frame size is the summation + * of all arguments. + * input params: + * Buffer - pointer to a pre-allocated memory segment + * args - a list of pairs. + * NOTE NOTE NOTE! the last argument must be NULL, otherwise this + * function will FAIL! + * return: + * Size of the buffer + * usage: + * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS); + + IRQL = PASSIVE_LEVEL IRQL = DISPATCH_LEVEL - ========================================================================== - */ -VOID AsicDisableSync( - IN PRTMP_ADAPTER pAd) + ****************************************************************************/ +unsigned long MakeOutgoingFrame(u8 * Buffer, unsigned long * FrameLen, ...) { - BCN_TIME_CFG_STRUC csr; - - DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n")); + u8 *p; + int leng; + unsigned long TotLeng; + va_list Args; - // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect - // that NIC will never wakes up because TSF stops and no more - // TBTT interrupts - pAd->TbttTickCount = 0; - RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); - csr.field.bBeaconGen = 0; - csr.field.bTBTTEnable = 0; - csr.field.TsfSyncMode = 0; - csr.field.bTsfTicking = 0; - RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + /* calculates the total length */ + TotLeng = 0; + va_start(Args, FrameLen); + do { + leng = va_arg(Args, int); + if (leng == END_OF_ARGS) { + break; + } + p = va_arg(Args, void *); + NdisMoveMemory(&Buffer[TotLeng], p, leng); + TotLeng = TotLeng + leng; + } while (TRUE); + va_end(Args); /* clean up */ + *FrameLen = TotLeng; + return TotLeng; } -/* - ========================================================================== - Description: +/* =========================================================================================== */ +/* mlme_queue.c */ +/* =========================================================================================== */ + +/*! \brief Initialize The MLME Queue, used by MLME Functions + * \param *Queue The MLME Queue + * \return Always Return NDIS_STATE_SUCCESS in this implementation + * \pre + * \post + * \note Because this is done only once (at the init stage), no need to be locked - IRQL = DISPATCH_LEVEL + IRQL = PASSIVE_LEVEL - ========================================================================== */ -VOID AsicEnableBssSync( - IN PRTMP_ADAPTER pAd) +int MlmeQueueInit(struct rt_mlme_queue *Queue) { - BCN_TIME_CFG_STRUC csr; + int i; - DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n")); + NdisAllocateSpinLock(&Queue->Lock); - RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + Queue->Num = 0; + Queue->Head = 0; + Queue->Tail = 0; - { - csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU - csr.field.bTsfTicking = 1; - csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode - csr.field.bBeaconGen = 0; // do NOT generate BEACON - csr.field.bTBTTEnable = 1; + for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) { + Queue->Entry[i].Occupied = FALSE; + Queue->Entry[i].MsgLen = 0; + NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE); } - RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + return NDIS_STATUS_SUCCESS; } -/* - ========================================================================== - Description: - Note: - BEACON frame in shared memory should be built ok before this routine - can be called. Otherwise, a garbage frame maybe transmitted out every - Beacon period. +/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread + * \param *Queue The MLME Queue + * \param Machine The State Machine Id + * \param MsgType The Message Type + * \param MsgLen The Message length + * \param *Msg The message pointer + * \return TRUE if enqueue is successful, FALSE if the queue is full + * \pre + * \post + * \note The message has to be initialized + IRQL = PASSIVE_LEVEL IRQL = DISPATCH_LEVEL - ========================================================================== */ -VOID AsicEnableIbssSync( - IN PRTMP_ADAPTER pAd) +BOOLEAN MlmeEnqueue(struct rt_rtmp_adapter *pAd, + unsigned long Machine, + unsigned long MsgType, unsigned long MsgLen, void * Msg) { - BCN_TIME_CFG_STRUC csr9; - PUCHAR ptr; - UINT i; - - DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount)); - - RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word); - csr9.field.bBeaconGen = 0; - csr9.field.bTBTTEnable = 0; - csr9.field.bTsfTicking = 0; - RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); - -#ifdef RT2860 - // move BEACON TXD and frame content to on-chip memory - ptr = (PUCHAR)&pAd->BeaconTxWI; - for (i=0; iMlme.Queue; + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + + /* First check the size, it MUST not exceed the mlme queue size */ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) { + DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", + MsgLen)); + return FALSE; } - // start right after the 16-byte TXWI field - ptr = pAd->BeaconBuf; - for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4) - { - UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); - RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr); - ptr +=4; + if (MlmeQueueFull(Queue)) { + return FALSE; } -#endif -#ifdef RT2870 - // move BEACON TXD and frame content to on-chip memory - ptr = (PUCHAR)&pAd->BeaconTxWI; - for (i=0; iLock)); + Tail = Queue->Tail; + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) { + Queue->Tail = 0; } - // start right after the 16-byte TXWI field - ptr = pAd->BeaconBuf; - for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2) - { - RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2); - ptr +=2; + Queue->Entry[Tail].Wcid = RESERVED_WCID; + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Machine; + Queue->Entry[Tail].MsgType = MsgType; + Queue->Entry[Tail].MsgLen = MsgLen; + + if (Msg != NULL) { + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); } -#endif // RT2870 // - - // start sending BEACON - csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU - csr9.field.bTsfTicking = 1; - csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode - csr9.field.bTBTTEnable = 1; - csr9.field.bBeaconGen = 1; - RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); + + NdisReleaseSpinLock(&(Queue->Lock)); + return TRUE; } -/* - ========================================================================== - Description: +/*! \brief This function is used when Recv gets a MLME message + * \param *Queue The MLME Queue + * \param TimeStampHigh The upper 32 bit of timestamp + * \param TimeStampLow The lower 32 bit of timestamp + * \param Rssi The receiving RSSI strength + * \param MsgLen The length of the message + * \param *Msg The message pointer + * \return TRUE if everything ok, FALSE otherwise (like Queue Full) + * \pre + * \post - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL + IRQL = DISPATCH_LEVEL - ========================================================================== */ -VOID AsicSetEdcaParm( - IN PRTMP_ADAPTER pAd, - IN PEDCA_PARM pEdcaParm) +BOOLEAN MlmeEnqueueForRecv(struct rt_rtmp_adapter *pAd, + unsigned long Wcid, + unsigned long TimeStampHigh, + unsigned long TimeStampLow, + u8 Rssi0, + u8 Rssi1, + u8 Rssi2, + unsigned long MsgLen, void * Msg, u8 Signal) { - EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg; - AC_TXOP_CSR0_STRUC csr0; - AC_TXOP_CSR1_STRUC csr1; - AIFSN_CSR_STRUC AifsnCsr; - CWMIN_CSR_STRUC CwminCsr; - CWMAX_CSR_STRUC CwmaxCsr; - int i; - - Ac0Cfg.word = 0; - Ac1Cfg.word = 0; - Ac2Cfg.word = 0; - Ac3Cfg.word = 0; - if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE)) - { - DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n")); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED); - for (i=0; iMacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli) - CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE); - } - - //======================================================== - // MAC Register has a copy . - //======================================================== - if( pAd->CommonCfg.bEnableTxBurst ) - { - // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode - Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode - } - else - Ac0Cfg.field.AcTxop = 0; // QID_AC_BE - Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS; - Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS; - Ac0Cfg.field.Aifsn = 2; - RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); - - Ac1Cfg.field.AcTxop = 0; // QID_AC_BK - Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS; - Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS; - Ac1Cfg.field.Aifsn = 2; - RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); - - if (pAd->CommonCfg.PhyMode == PHY_11B) - { - Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms - Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms - } - else - { - Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms - Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms - } - Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS; - Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS; - Ac2Cfg.field.Aifsn = 2; - RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); - Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS; - Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS; - Ac3Cfg.field.Aifsn = 2; - RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); - - //======================================================== - // DMA Register has a copy too. - //======================================================== - csr0.field.Ac0Txop = 0; // QID_AC_BE - csr0.field.Ac1Txop = 0; // QID_AC_BK - RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); - if (pAd->CommonCfg.PhyMode == PHY_11B) - { - csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms - csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms - } - else - { - csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms - csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms - } - RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); - - CwminCsr.word = 0; - CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS; - CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS; - CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS; - CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS; - RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); - - CwmaxCsr.word = 0; - CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS; - CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS; - CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS; - CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS; - RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); - - RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222); - - NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM)); + int Tail, Machine; + struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg; + int MsgType; + struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue; + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG + (pAd, + fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) { + DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n")); + return FALSE; + } + /* First check the size, it MUST not exceed the mlme queue size */ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) { + DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); + return FALSE; } - else - { - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED); - //======================================================== - // MAC Register has a copy. - //======================================================== - // - // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27 - // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue. - // - //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this - - Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE]; - Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE]; - Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE]; - Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1; - - Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; - Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2; - Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK]; - Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1; - - Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10; - Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI]; - Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI]; - Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI]; - - { - // Tuning for Wi-Fi WMM S06 - if (pAd->CommonCfg.bWiFiTest && - pEdcaParm->Aifsn[QID_AC_VI] == 10) - Ac2Cfg.field.Aifsn -= 1; - - // Tuning for TGn Wi-Fi 5.2.32 - // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta - if (STA_TGN_WIFI_ON(pAd) && - pEdcaParm->Aifsn[QID_AC_VI] == 10) - { - Ac0Cfg.field.Aifsn = 3; - Ac2Cfg.field.AcTxop = 5; - } - -#ifdef RT2870 - if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020) - { - // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta. - Ac2Cfg.field.Aifsn = 5; - } -#endif - } - Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO]; - Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO]; - Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO]; - Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO]; + if (MlmeQueueFull(Queue)) { + return FALSE; + } -//#ifdef WIFI_TEST - if (pAd->CommonCfg.bWiFiTest) - { - if (Ac3Cfg.field.AcTxop == 102) - { - Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10; - Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */ - Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; - Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; - Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI]; - } /* End of if */ + { + if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) { + DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n", pFrame->Hdr.FC.SubType)); + return FALSE; } -//#endif // WIFI_TEST // - - RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); - RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); - RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); - RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); - - - //======================================================== - // DMA Register has a copy too. - //======================================================== - csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop; - csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop; - RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); - - csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop; - csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop; - RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); - - CwminCsr.word = 0; - CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE]; - CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK]; - CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI]; - - CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test + } - RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); + /* OK, we got all the informations, it is time to put things into queue */ + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) { + Queue->Tail = 0; + } + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Machine; + Queue->Entry[Tail].MsgType = MsgType; + Queue->Entry[Tail].MsgLen = MsgLen; + Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow; + Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh; + Queue->Entry[Tail].Rssi0 = Rssi0; + Queue->Entry[Tail].Rssi1 = Rssi1; + Queue->Entry[Tail].Rssi2 = Rssi2; + Queue->Entry[Tail].Signal = Signal; + Queue->Entry[Tail].Wcid = (u8)Wcid; - CwmaxCsr.word = 0; - CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE]; - CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK]; - CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI]; - CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO]; - RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); + Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel; - AifsnCsr.word = 0; - AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE]; - AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK]; - AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI]; + if (Msg != NULL) { + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + } - { - // Tuning for Wi-Fi WMM S06 - if (pAd->CommonCfg.bWiFiTest && - pEdcaParm->Aifsn[QID_AC_VI] == 10) - AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4; - - // Tuning for TGn Wi-Fi 5.2.32 - // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta - if (STA_TGN_WIFI_ON(pAd) && - pEdcaParm->Aifsn[QID_AC_VI] == 10) - { - AifsnCsr.field.Aifsn0 = 3; - AifsnCsr.field.Aifsn2 = 7; - } -#ifdef RT2870 - if (INFRA_ON(pAd)) - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE); -#endif - } + NdisReleaseSpinLock(&(Queue->Lock)); - AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test -#ifdef RT2870 - if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020) - AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04. -#endif - RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word); + RTMP_MLME_HANDLER(pAd); - NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM)); - if (!ADHOC_ON(pAd)) - { - DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount)); - DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n", - pEdcaParm->Aifsn[0], - pEdcaParm->Cwmin[0], - pEdcaParm->Cwmax[0], - pEdcaParm->Txop[0]<<5, - pEdcaParm->bACM[0])); - DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n", - pEdcaParm->Aifsn[1], - pEdcaParm->Cwmin[1], - pEdcaParm->Cwmax[1], - pEdcaParm->Txop[1]<<5, - pEdcaParm->bACM[1])); - DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n", - pEdcaParm->Aifsn[2], - pEdcaParm->Cwmin[2], - pEdcaParm->Cwmax[2], - pEdcaParm->Txop[2]<<5, - pEdcaParm->bACM[2])); - DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n", - pEdcaParm->Aifsn[3], - pEdcaParm->Cwmin[3], - pEdcaParm->Cwmax[3], - pEdcaParm->Txop[3]<<5, - pEdcaParm->bACM[3])); - } - } + return TRUE; } -/* - ========================================================================== - Description: +/*! \brief Dequeue a message from the MLME Queue + * \param *Queue The MLME Queue + * \param *Elem The message dequeued from MLME Queue + * \return TRUE if the Elem contains something, FALSE otherwise + * \pre + * \post - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL + IRQL = DISPATCH_LEVEL - ========================================================================== */ -VOID AsicSetSlotTime( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bUseShortSlotTime) +BOOLEAN MlmeDequeue(struct rt_mlme_queue *Queue, struct rt_mlme_queue_elem ** Elem) { - ULONG SlotTime; - UINT32 RegValue = 0; - - if (pAd->CommonCfg.Channel > 14) - bUseShortSlotTime = TRUE; - - if (bUseShortSlotTime) - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); - else - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); - - SlotTime = (bUseShortSlotTime)? 9 : 20; - - { - // force using short SLOT time for FAE to demo performance when TxBurst is ON - if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))) - || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE)) - ) - { - // In this case, we will think it is doing Wi-Fi test - // And we will not set to short slot when bEnableTxBurst is TRUE. - } - else if (pAd->CommonCfg.bEnableTxBurst) - SlotTime = 9; + NdisAcquireSpinLock(&(Queue->Lock)); + *Elem = &(Queue->Entry[Queue->Head]); + Queue->Num--; + Queue->Head++; + if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) { + Queue->Head = 0; } - - // - // For some reasons, always set it to short slot time. - // - // ToDo: Should consider capability with 11B - // - if (pAd->StaCfg.BssType == BSS_ADHOC) - SlotTime = 20; - - RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); - RegValue = RegValue & 0xFFFFFF00; - - RegValue |= SlotTime; - - RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue); + NdisReleaseSpinLock(&(Queue->Lock)); + return TRUE; } -/* - ======================================================================== - Description: - Add Shared key information into ASIC. - Update shared key, TxMic and RxMic to Asic Shared key table - Update its cipherAlg to Asic Shared key Mode. - - Return: - ======================================================================== -*/ -VOID AsicAddSharedKeyEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIndex, - IN UCHAR KeyIdx, - IN UCHAR CipherAlg, - IN PUCHAR pKey, - IN PUCHAR pTxMic, - IN PUCHAR pRxMic) +/* IRQL = DISPATCH_LEVEL */ +void MlmeRestartStateMachine(struct rt_rtmp_adapter *pAd) { - ULONG offset; //, csr0; - SHAREDKEY_MODE_STRUC csr1; -#ifdef RT2860 - INT i; -#endif +#ifdef RTMP_MAC_PCI + struct rt_mlme_queue_elem *Elem = NULL; +#endif /* RTMP_MAC_PCI // */ + BOOLEAN Cancelled; - DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx)); -//============================================================================================ + DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n")); - DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx)); - DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15])); - if (pRxMic) - { - DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); - } - if (pTxMic) - { - DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); - } -//============================================================================================ - // - // fill key material - key + TX MIC + RX MIC - // - - offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE; -#ifdef RT2860 - for (i=0; iMlme.TaskLock); + if (pAd->Mlme.bRunning) { + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + return; + } else { + pAd->Mlme.bRunning = TRUE; } -#endif -#ifdef RT2870 - RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY); -#endif - offset += MAX_LEN_OF_SHARE_KEY; - if (pTxMic) - { -#ifdef RT2860 - for (i=0; i<8; i++) - { - RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + + /* Remove all Mlme queues elements */ + while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) { + /*From message type, determine which state machine I should drive */ + if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) { + /* free MLME element */ + Elem->Occupied = FALSE; + Elem->MsgLen = 0; + + } else { + DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n")); } -#endif -#ifdef RT2870 - RTUSBMultiWrite(pAd, offset, pTxMic, 8); -#endif } +#endif /* RTMP_MAC_PCI // */ - offset += 8; - if (pRxMic) { -#ifdef RT2860 - for (i=0; i<8; i++) - { - RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); - } -#endif -#ifdef RT2870 - RTUSBMultiWrite(pAd, offset, pRxMic, 8); -#endif + /* Cancel all timer events */ + /* Be careful to cancel new added timer */ + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + } + /* Change back to original channel in case of doing scan */ + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + /* Resume MSDU which is turned off durning scan */ + RTMPResumeMsduTransmission(pAd); - // - // Update cipher algorithm. WSTA always use BSS0 - // - RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word); - DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word)); - if ((BssIndex%2) == 0) - { - if (KeyIdx == 0) - csr1.field.Bss0Key0CipherAlg = CipherAlg; - else if (KeyIdx == 1) - csr1.field.Bss0Key1CipherAlg = CipherAlg; - else if (KeyIdx == 2) - csr1.field.Bss0Key2CipherAlg = CipherAlg; - else - csr1.field.Bss0Key3CipherAlg = CipherAlg; - } - else { - if (KeyIdx == 0) - csr1.field.Bss1Key0CipherAlg = CipherAlg; - else if (KeyIdx == 1) - csr1.field.Bss1Key1CipherAlg = CipherAlg; - else if (KeyIdx == 2) - csr1.field.Bss1Key2CipherAlg = CipherAlg; - else - csr1.field.Bss1Key3CipherAlg = CipherAlg; + /* Set all state machines back IDLE */ + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE; + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + pAd->Mlme.ActMachine.CurrState = ACT_IDLE; } - DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word)); - RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word); +#ifdef RTMP_MAC_PCI + /* Remove running state */ + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + pAd->Mlme.bRunning = FALSE; + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); +#endif /* RTMP_MAC_PCI // */ } -// IRQL = DISPATCH_LEVEL -VOID AsicRemoveSharedKeyEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIndex, - IN UCHAR KeyIdx) -{ - //ULONG SecCsr0; - SHAREDKEY_MODE_STRUC csr1; +/*! \brief test if the MLME Queue is empty + * \param *Queue The MLME Queue + * \return TRUE if the Queue is empty, FALSE otherwise + * \pre + * \post - DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx)); + IRQL = DISPATCH_LEVEL - RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word); - if ((BssIndex%2) == 0) - { - if (KeyIdx == 0) - csr1.field.Bss0Key0CipherAlg = 0; - else if (KeyIdx == 1) - csr1.field.Bss0Key1CipherAlg = 0; - else if (KeyIdx == 2) - csr1.field.Bss0Key2CipherAlg = 0; - else - csr1.field.Bss0Key3CipherAlg = 0; - } - else - { - if (KeyIdx == 0) - csr1.field.Bss1Key0CipherAlg = 0; - else if (KeyIdx == 1) - csr1.field.Bss1Key1CipherAlg = 0; - else if (KeyIdx == 2) - csr1.field.Bss1Key2CipherAlg = 0; - else - csr1.field.Bss1Key3CipherAlg = 0; - } - DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word)); - RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word); - ASSERT(BssIndex < 4); - ASSERT(KeyIdx < 4); + */ +BOOLEAN MlmeQueueEmpty(struct rt_mlme_queue *Queue) +{ + BOOLEAN Ans; + + NdisAcquireSpinLock(&(Queue->Lock)); + Ans = (Queue->Num == 0); + NdisReleaseSpinLock(&(Queue->Lock)); + return Ans; } +/*! \brief test if the MLME Queue is full + * \param *Queue The MLME Queue + * \return TRUE if the Queue is empty, FALSE otherwise + * \pre + * \post -VOID AsicUpdateWCIDAttribute( - IN PRTMP_ADAPTER pAd, - IN USHORT WCID, - IN UCHAR BssIndex, - IN UCHAR CipherAlg, - IN BOOLEAN bUsePairewiseKeyTable) -{ - ULONG WCIDAttri = 0, offset; - - // - // Update WCID attribute. - // Only TxKey could update WCID attribute. - // - offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE); - WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable); - RTMP_IO_WRITE32(pAd, offset, WCIDAttri); -} + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL -VOID AsicUpdateWCIDIVEIV( - IN PRTMP_ADAPTER pAd, - IN USHORT WCID, - IN ULONG uIV, - IN ULONG uEIV) + */ +BOOLEAN MlmeQueueFull(struct rt_mlme_queue *Queue) { - ULONG offset; + BOOLEAN Ans; - offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); + NdisAcquireSpinLock(&(Queue->Lock)); + Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE + || Queue->Entry[Queue->Tail].Occupied); + NdisReleaseSpinLock(&(Queue->Lock)); - RTMP_IO_WRITE32(pAd, offset, uIV); - RTMP_IO_WRITE32(pAd, offset + 4, uEIV); + return Ans; } -VOID AsicUpdateRxWCIDTable( - IN PRTMP_ADAPTER pAd, - IN USHORT WCID, - IN PUCHAR pAddr) +/*! \brief The destructor of MLME Queue + * \param + * \return + * \pre + * \post + * \note Clear Mlme Queue, Set Queue->Num to Zero. + + IRQL = PASSIVE_LEVEL + + */ +void MlmeQueueDestroy(struct rt_mlme_queue *pQueue) { - ULONG offset; - ULONG Addr; - - offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE); - Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24); - RTMP_IO_WRITE32(pAd, offset, Addr); - Addr = pAddr[4] + (pAddr[5] << 8); - RTMP_IO_WRITE32(pAd, offset + 4, Addr); + NdisAcquireSpinLock(&(pQueue->Lock)); + pQueue->Num = 0; + pQueue->Head = 0; + pQueue->Tail = 0; + NdisReleaseSpinLock(&(pQueue->Lock)); + NdisFreeSpinLock(&(pQueue->Lock)); } +/*! \brief To substitute the message type if the message is coming from external + * \param pFrame The frame received + * \param *Machine The state machine + * \param *MsgType the message type for the state machine + * \return TRUE if the substitution is successful, FALSE otherwise + * \pre + * \post -/* - ======================================================================== - - Routine Description: - Set Cipher Key, Cipher algorithm, IV/EIV to Asic + IRQL = DISPATCH_LEVEL - Arguments: - pAd Pointer to our adapter - WCID WCID Entry number. - BssIndex BSSID index, station or none multiple BSSID support - this value should be 0. - KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled - pCipherKey Pointer to Cipher Key. - bUsePairewiseKeyTable TRUE means saved the key in SharedKey table, - otherwise PairewiseKey table - bTxKey This is the transmit key if enabled. + */ +BOOLEAN MsgTypeSubst(struct rt_rtmp_adapter *pAd, + struct rt_frame_802_11 * pFrame, + int * Machine, int * MsgType) +{ + u16 Seq, Alg; + u8 EAPType; + u8 *pData; + + /* Pointer to start of data frames including SNAP header */ + pData = (u8 *)pFrame + LENGTH_802_11; + + /* The only data type will pass to this function is EAPOL frame */ + if (pFrame->Hdr.FC.Type == BTYPE_DATA) { + { + *Machine = WPA_STATE_MACHINE; + EAPType = + *((u8 *) pFrame + LENGTH_802_11 + + LENGTH_802_1_H + 1); + return (WpaMsgTypeSubst(EAPType, (int *) MsgType)); + } + } + + switch (pFrame->Hdr.FC.SubType) { + case SUBTYPE_ASSOC_REQ: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_ASSOC_REQ; + break; + case SUBTYPE_ASSOC_RSP: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_ASSOC_RSP; + break; + case SUBTYPE_REASSOC_REQ: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_REASSOC_REQ; + break; + case SUBTYPE_REASSOC_RSP: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_REASSOC_RSP; + break; + case SUBTYPE_PROBE_REQ: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_PROBE_REQ; + break; + case SUBTYPE_PROBE_RSP: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_PROBE_RSP; + break; + case SUBTYPE_BEACON: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_BEACON; + break; + case SUBTYPE_ATIM: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_ATIM; + break; + case SUBTYPE_DISASSOC: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_DISASSOC_REQ; + break; + case SUBTYPE_AUTH: + /* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */ + NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(u16)); + NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(u16)); + if (Seq == 1 || Seq == 3) { + *Machine = AUTH_RSP_STATE_MACHINE; + *MsgType = MT2_PEER_AUTH_ODD; + } else if (Seq == 2 || Seq == 4) { + if (Alg == AUTH_MODE_OPEN || Alg == AUTH_MODE_KEY) { + *Machine = AUTH_STATE_MACHINE; + *MsgType = MT2_PEER_AUTH_EVEN; + } + } else { + return FALSE; + } + break; + case SUBTYPE_DEAUTH: + *Machine = AUTH_RSP_STATE_MACHINE; + *MsgType = MT2_PEER_DEAUTH; + break; + case SUBTYPE_ACTION: + *Machine = ACTION_STATE_MACHINE; + /* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */ + if ((pFrame->Octet[0] & 0x7F) > MAX_PEER_CATE_MSG) { + *MsgType = MT2_ACT_INVALID; + } else { + *MsgType = (pFrame->Octet[0] & 0x7F); + } + break; + default: + return FALSE; + break; + } - Return Value: - None + return TRUE; +} - Note: - This routine will set the relative key stuff to Asic including WCID attribute, - Cipher Key, Cipher algorithm and IV/EIV. +/* =========================================================================================== */ +/* state_machine.c */ +/* =========================================================================================== */ - IV/EIV will be update if this CipherKey is the transmission key because - ASIC will base on IV's KeyID value to select Cipher Key. +/*! \brief Initialize the state machine. + * \param *S pointer to the state machine + * \param Trans State machine transition function + * \param StNr number of states + * \param MsgNr number of messages + * \param DefFunc default function, when there is invalid state/message combination + * \param InitState initial state of the state machine + * \param Base StateMachine base, internal use only + * \pre p_sm should be a legal pointer + * \post - If bTxKey sets to FALSE, this is not the TX key, but it could be - RX key + IRQL = PASSIVE_LEVEL - For AP mode bTxKey must be always set to TRUE. - ======================================================================== -*/ -VOID AsicAddKeyEntry( - IN PRTMP_ADAPTER pAd, - IN USHORT WCID, - IN UCHAR BssIndex, - IN UCHAR KeyIdx, - IN PCIPHER_KEY pCipherKey, - IN BOOLEAN bUsePairewiseKeyTable, - IN BOOLEAN bTxKey) + */ +void StateMachineInit(struct rt_state_machine *S, + IN STATE_MACHINE_FUNC Trans[], + unsigned long StNr, + unsigned long MsgNr, + IN STATE_MACHINE_FUNC DefFunc, + unsigned long InitState, unsigned long Base) { - ULONG offset; - UCHAR IV4 = 0; - PUCHAR pKey = pCipherKey->Key; - PUCHAR pTxMic = pCipherKey->TxMic; - PUCHAR pRxMic = pCipherKey->RxMic; - PUCHAR pTxtsc = pCipherKey->TxTsc; - UCHAR CipherAlg = pCipherKey->CipherAlg; - SHAREDKEY_MODE_STRUC csr1; -#ifdef RT2860 - UCHAR i; -#endif - - DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n")); - // - // 1.) decide key table offset - // - if (bUsePairewiseKeyTable) - offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); - else - offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE; - - // - // 2.) Set Key to Asic - // - //for (i = 0; i < KeyLen; i++) -#ifdef RT2860 - for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++) - { - RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); - } -#endif -#ifdef RT2870 - RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY); -#endif - offset += MAX_LEN_OF_PEER_KEY; - - // - // 3.) Set MIC key if available - // - if (pTxMic) - { -#ifdef RT2860 - for (i = 0; i < 8; i++) - { - RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); - } -#endif -#ifdef RT2870 - RTUSBMultiWrite(pAd, offset, pTxMic, 8); -#endif - } - offset += LEN_TKIP_TXMICK; - - if (pRxMic) - { -#ifdef RT2860 - for (i = 0; i < 8; i++) - { - RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); - } -#endif -#ifdef RT2870 - RTUSBMultiWrite(pAd, offset, pRxMic, 8); -#endif - } + unsigned long i, j; + /* set number of states and messages */ + S->NrState = StNr; + S->NrMsg = MsgNr; + S->Base = Base; - // - // 4.) Modify IV/EIV if needs - // This will force Asic to use this key ID by setting IV. - // - if (bTxKey) - { -#ifdef RT2860 - offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); - // - // Write IV - // - RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]); - RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f)); - RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]); - - IV4 = (KeyIdx << 6); - if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES)) - IV4 |= 0x20; // turn on extension bit means EIV existence - - RTMP_IO_WRITE8(pAd, offset + 3, IV4); - - // - // Write EIV - // - offset += 4; - for (i = 0; i < 4; i++) - { - RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]); - } - -#endif -#ifdef RT2870 - UINT32 tmpVal; - - // - // Write IV - // - IV4 = (KeyIdx << 6); - if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES)) - IV4 |= 0x20; // turn on extension bit means EIV existence - - tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24); - RTMP_IO_WRITE32(pAd, offset, tmpVal); - - // - // Write EIV - // - offset += 4; - RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]); -#endif // RT2870 // - AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable); - } + S->TransFunc = Trans; - if (!bUsePairewiseKeyTable) - { - // - // Only update the shared key security mode - // - RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word); - if ((BssIndex % 2) == 0) - { - if (KeyIdx == 0) - csr1.field.Bss0Key0CipherAlg = CipherAlg; - else if (KeyIdx == 1) - csr1.field.Bss0Key1CipherAlg = CipherAlg; - else if (KeyIdx == 2) - csr1.field.Bss0Key2CipherAlg = CipherAlg; - else - csr1.field.Bss0Key3CipherAlg = CipherAlg; - } - else - { - if (KeyIdx == 0) - csr1.field.Bss1Key0CipherAlg = CipherAlg; - else if (KeyIdx == 1) - csr1.field.Bss1Key1CipherAlg = CipherAlg; - else if (KeyIdx == 2) - csr1.field.Bss1Key2CipherAlg = CipherAlg; - else - csr1.field.Bss1Key3CipherAlg = CipherAlg; + /* init all state transition to default function */ + for (i = 0; i < StNr; i++) { + for (j = 0; j < MsgNr; j++) { + S->TransFunc[i * MsgNr + j] = DefFunc; } - RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word); } - DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n")); + /* set the starting state */ + S->CurrState = InitState; } +/*! \brief This function fills in the function pointer into the cell in the state machine + * \param *S pointer to the state machine + * \param St state + * \param Msg incoming message + * \param f the function to be executed when (state, message) combination occurs at the state machine + * \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state + * \post -/* - ======================================================================== - Description: - Add Pair-wise key material into ASIC. - Update pairwise key, TxMic and RxMic to Asic Pair-wise key table + IRQL = PASSIVE_LEVEL - Return: - ======================================================================== -*/ -VOID AsicAddPairwiseKeyEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN UCHAR WCID, - IN CIPHER_KEY *pCipherKey) + */ +void StateMachineSetAction(struct rt_state_machine *S, + unsigned long St, + unsigned long Msg, IN STATE_MACHINE_FUNC Func) { - INT i; - ULONG offset; - PUCHAR pKey = pCipherKey->Key; - PUCHAR pTxMic = pCipherKey->TxMic; - PUCHAR pRxMic = pCipherKey->RxMic; -#ifdef DBG - UCHAR CipherAlg = pCipherKey->CipherAlg; -#endif // DBG // - - // EKEY - offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); -#ifdef RT2860 - for (i=0; iKey[0], MAX_LEN_OF_PEER_KEY); -#endif // RT2870 // - for (i=0; iTxMic[0], 8); -#endif // RT2870 // - } - offset += 8; - if (pRxMic) - { -#ifdef RT2860 - for (i=0; i<8; i++) - { - RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]); - } -#endif -#ifdef RT2870 - RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8); -#endif // RT2870 // - } + MsgIdx = Msg - S->Base; - DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg])); - DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15])); - if (pRxMic) - { - DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); - } - if (pTxMic) - { - DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); + if (St < S->NrState && MsgIdx < S->NrMsg) { + /* boundary checking before setting the action */ + S->TransFunc[St * S->NrMsg + MsgIdx] = Func; } } -/* - ======================================================================== - Description: - Remove Pair-wise key material from ASIC. - Return: - ======================================================================== -*/ -VOID AsicRemovePairwiseKeyEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIdx, - IN UCHAR Wcid) -{ - ULONG WCIDAttri; - USHORT offset; +/*! \brief This function does the state transition + * \param *Adapter the NIC adapter pointer + * \param *S the state machine + * \param *Elem the message to be executed + * \return None - // re-set the entry's WCID attribute as OPEN-NONE. - offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE); - WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE; - RTMP_IO_WRITE32(pAd, offset, WCIDAttri); -} + IRQL = DISPATCH_LEVEL -BOOLEAN AsicSendCommandToMcu( - IN PRTMP_ADAPTER pAd, - IN UCHAR Command, - IN UCHAR Token, - IN UCHAR Arg0, - IN UCHAR Arg1) + */ +void StateMachinePerformAction(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *S, struct rt_mlme_queue_elem *Elem) { - HOST_CMD_CSR_STRUC H2MCmd; - H2M_MAILBOX_STRUC H2MMailbox; - ULONG i = 0; - - do - { - RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word); - if (H2MMailbox.field.Owner == 0) - break; - - RTMPusecDelay(2); - } while(i++ < 100); + (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base])) + (pAd, Elem); +} - if (i > 100) - { - { -#ifdef RT2860 - UINT32 Data; - - // Reset DMA - RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); - Data |= 0x2; - RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); - - // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too. - // Reset DMA/CPU ring index - RTMPRingCleanUp(pAd, QID_AC_BK); - RTMPRingCleanUp(pAd, QID_AC_BE); - RTMPRingCleanUp(pAd, QID_AC_VI); - RTMPRingCleanUp(pAd, QID_AC_VO); - RTMPRingCleanUp(pAd, QID_HCCA); - RTMPRingCleanUp(pAd, QID_MGMT); - RTMPRingCleanUp(pAd, QID_RX); - - // Clear Reset - RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); - Data &= 0xfffffffd; - RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); -#endif /* RT2860 */ - DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n")); - } - //return FALSE; -#ifdef RT2870 - return FALSE; -#endif - } +/* + ========================================================================== + Description: + The drop function, when machine executes this, the message is simply + ignored. This function does nothing, the message is freed in + StateMachinePerformAction() + ========================================================================== + */ +void Drop(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) +{ +} - H2MMailbox.field.Owner = 1; // pass ownership to MCU - H2MMailbox.field.CmdToken = Token; - H2MMailbox.field.HighByte = Arg1; - H2MMailbox.field.LowByte = Arg0; - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word); +/* =========================================================================================== */ +/* lfsr.c */ +/* =========================================================================================== */ - H2MCmd.word = 0; - H2MCmd.field.HostCommand = Command; - RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word); +/* + ========================================================================== + Description: - if (Command != 0x80) - { - } + IRQL = PASSIVE_LEVEL - return TRUE; + ========================================================================== + */ +void LfsrInit(struct rt_rtmp_adapter *pAd, unsigned long Seed) +{ + if (Seed == 0) + pAd->Mlme.ShiftReg = 1; + else + pAd->Mlme.ShiftReg = Seed; } -#ifdef RT2860 -BOOLEAN AsicCheckCommanOk( - IN PRTMP_ADAPTER pAd, - IN UCHAR Command) +/* + ========================================================================== + Description: + ========================================================================== + */ +u8 RandomByte(struct rt_rtmp_adapter *pAd) { - UINT32 CmdStatus = 0, CID = 0, i; - UINT32 ThisCIDMask = 0; - - i = 0; - do - { - RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID); - // Find where the command is. Because this is randomly specified by firmware. - if ((CID & CID0MASK) == Command) - { - ThisCIDMask = CID0MASK; - break; - } - else if ((((CID & CID1MASK)>>8) & 0xff) == Command) - { - ThisCIDMask = CID1MASK; - break; - } - else if ((((CID & CID2MASK)>>16) & 0xff) == Command) - { - ThisCIDMask = CID2MASK; - break; - } - else if ((((CID & CID3MASK)>>24) & 0xff) == Command) - { - ThisCIDMask = CID3MASK; - break; - } + unsigned long i; + u8 R, Result; - RTMPusecDelay(100); - i++; - }while (i < 200); + R = 0; - // Get CommandStatus Value - RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus); + if (pAd->Mlme.ShiftReg == 0) + NdisGetSystemUpTime((unsigned long *) & pAd->Mlme.ShiftReg); - // This command's status is at the same position as command. So AND command position's bitmask to read status. - if (i < 200) - { - // If Status is 1, the comamnd is success. - if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100) - || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000)) - { - DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus)); - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); - return TRUE; + for (i = 0; i < 8; i++) { + if (pAd->Mlme.ShiftReg & 0x00000001) { + pAd->Mlme.ShiftReg = + ((pAd->Mlme. + ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000; + Result = 1; + } else { + pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1; + Result = 0; } - DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus)); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus)); + R = (R << 1) | Result; } - // Clear Command and Status. - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); - return FALSE; + return R; } -#endif /* RT8260 */ /* ======================================================================== @@ -7662,13 +5244,11 @@ BOOLEAN AsicCheckCommanOk( ======================================================================== */ -VOID RTMPCheckRates( - IN PRTMP_ADAPTER pAd, - IN OUT UCHAR SupRate[], - IN OUT UCHAR *SupRateLen) +void RTMPCheckRates(struct rt_rtmp_adapter *pAd, + IN u8 SupRate[], IN u8 * SupRateLen) { - UCHAR RateIdx, i, j; - UCHAR NewRate[12], NewRateLen; + u8 RateIdx, i, j; + u8 NewRate[12], NewRateLen; NewRateLen = 0; @@ -7677,7 +5257,7 @@ VOID RTMPCheckRates( else RateIdx = 12; - // Check for support rates exclude basic rate bit + /* Check for support rates exclude basic rate bit */ for (i = 0; i < *SupRateLen; i++) for (j = 0; j < RateIdx; j++) if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) @@ -7687,43 +5267,37 @@ VOID RTMPCheckRates( NdisMoveMemory(SupRate, NewRate, NewRateLen); } -BOOLEAN RTMPCheckChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR CentralChannel, - IN UCHAR Channel) +BOOLEAN RTMPCheckChannel(struct rt_rtmp_adapter *pAd, + u8 CentralChannel, u8 Channel) { - UCHAR k; - UCHAR UpperChannel = 0, LowerChannel = 0; - UCHAR NoEffectChannelinList = 0; + u8 k; + u8 UpperChannel = 0, LowerChannel = 0; + u8 NoEffectChannelinList = 0; - // Find upper and lower channel according to 40MHz current operation. - if (CentralChannel < Channel) - { + /* Find upper and lower channel according to 40MHz current operation. */ + if (CentralChannel < Channel) { UpperChannel = Channel; if (CentralChannel > 2) LowerChannel = CentralChannel - 2; else return FALSE; - } - else if (CentralChannel > Channel) - { + } else if (CentralChannel > Channel) { UpperChannel = CentralChannel + 2; LowerChannel = Channel; } - for (k = 0;k < pAd->ChannelListNum;k++) - { - if (pAd->ChannelList[k].Channel == UpperChannel) - { - NoEffectChannelinList ++; + for (k = 0; k < pAd->ChannelListNum; k++) { + if (pAd->ChannelList[k].Channel == UpperChannel) { + NoEffectChannelinList++; } - if (pAd->ChannelList[k].Channel == LowerChannel) - { - NoEffectChannelinList ++; + if (pAd->ChannelList[k].Channel == LowerChannel) { + NoEffectChannelinList++; } } - DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList)); + DBGPRINT(RT_DEBUG_TRACE, + ("Total Channel in Channel List = [%d]\n", + NoEffectChannelinList)); if (NoEffectChannelinList == 2) return TRUE; else @@ -7746,88 +5320,114 @@ BOOLEAN RTMPCheckChannel( ======================================================================== */ -BOOLEAN RTMPCheckHt( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN HT_CAPABILITY_IE *pHtCapability, - IN ADD_HT_INFO_IE *pAddHtInfo) +BOOLEAN RTMPCheckHt(struct rt_rtmp_adapter *pAd, + u8 Wcid, + struct rt_ht_capability_ie * pHtCapability, + struct rt_add_ht_info_ie * pAddHtInfo) { if (Wcid >= MAX_LEN_OF_MAC_TABLE) return FALSE; - // If use AMSDU, set flag. + /* If use AMSDU, set flag. */ if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable) - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED); - // Save Peer Capability + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], + fCLIENT_STATUS_AMSDU_INUSED); + /* Save Peer Capability */ if (pHtCapability->HtCapInfo.ShortGIfor20) - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE); + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], + fCLIENT_STATUS_SGI20_CAPABLE); if (pHtCapability->HtCapInfo.ShortGIfor40) - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE); + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], + fCLIENT_STATUS_SGI40_CAPABLE); if (pHtCapability->HtCapInfo.TxSTBC) - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE); + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], + fCLIENT_STATUS_TxSTBC_CAPABLE); if (pHtCapability->HtCapInfo.RxSTBC) - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE); - if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) - { - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE); + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], + fCLIENT_STATUS_RxSTBC_CAPABLE); + if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) { + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], + fCLIENT_STATUS_RDG_CAPABLE); } - if (Wcid < MAX_LEN_OF_MAC_TABLE) - { - pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity; + if (Wcid < MAX_LEN_OF_MAC_TABLE) { + pAd->MacTab.Content[Wcid].MpduDensity = + pHtCapability->HtCapParm.MpduDensity; } - - // Will check ChannelWidth for MCSSet[4] below + /* Will check ChannelWidth for MCSSet[4] below */ pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1; - switch (pAd->CommonCfg.RxStream) - { - case 1: - pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; - pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00; - pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; - pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; - break; - case 2: - pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; - pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; - pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; - pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; - break; - case 3: - pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; - pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; - pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff; - pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; - break; - } - - pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth; - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n", - pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth, - pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode)); - - pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF; - - // Send Assoc Req with my HT capability. - pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize; - pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs; - pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20); - pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40); - pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC); - pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC); - pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor; - pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity; - pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; - pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; - if (pAd->CommonCfg.bRdg) - { - pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport; - pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1; - } - - if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20) - pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32 + switch (pAd->CommonCfg.RxStream) { + case 1: + pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00; + pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; + pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + case 2: + pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; + pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + case 3: + pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + } + + pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = + pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy. + ChannelWidth; + + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n", + pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, + pAddHtInfo->AddHtInfo.RecomWidth, + pAd->CommonCfg.DesiredHtPhy.ChannelWidth, + pAd->NicConfig2.field.BW40MAvailForA, + pAd->NicConfig2.field.BW40MAvailForG, + pAd->CommonCfg.PhyMode)); + + pAd->MlmeAux.HtCapability.HtCapInfo.GF = + pHtCapability->HtCapInfo.GF & pAd->CommonCfg.DesiredHtPhy.GF; + + /* Send Assoc Req with my HT capability. */ + pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = + pAd->CommonCfg.DesiredHtPhy.AmsduSize; + pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = + pAd->CommonCfg.DesiredHtPhy.MimoPs; + pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = + (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability-> + HtCapInfo. + ShortGIfor20); + pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = + (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability-> + HtCapInfo. + ShortGIfor40); + pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = + (pAd->CommonCfg.DesiredHtPhy.TxSTBC) & (pHtCapability->HtCapInfo. + RxSTBC); + pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = + (pAd->CommonCfg.DesiredHtPhy.RxSTBC) & (pHtCapability->HtCapInfo. + TxSTBC); + pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = + pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor; + pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = + pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity; + pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = + pHtCapability->ExtHtCapInfo.PlusHTC; + pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = + pHtCapability->ExtHtCapInfo.PlusHTC; + if (pAd->CommonCfg.bRdg) { + pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = + pHtCapability->ExtHtCapInfo.RDGSupport; + pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1; + } + + if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20) + pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; /* BW20 can't transmit MCS32 */ COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability); return TRUE; @@ -7845,69 +5445,64 @@ BOOLEAN RTMPCheckHt( Return Value: None - IRQL = PASSIVE_LEVEL - - ======================================================================== -*/ -VOID RTMPUpdateMlmeRate( - IN PRTMP_ADAPTER pAd) -{ - UCHAR MinimumRate; - UCHAR ProperMlmeRate; //= RATE_54; - UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 - BOOLEAN bMatch = FALSE; - - switch (pAd->CommonCfg.PhyMode) - { - case PHY_11B: - ProperMlmeRate = RATE_11; - MinimumRate = RATE_1; - break; - case PHY_11BG_MIXED: - case PHY_11ABGN_MIXED: - case PHY_11BGN_MIXED: - if ((pAd->MlmeAux.SupRateLen == 4) && - (pAd->MlmeAux.ExtRateLen == 0)) - // B only AP - ProperMlmeRate = RATE_11; - else - ProperMlmeRate = RATE_24; + IRQL = PASSIVE_LEVEL - if (pAd->MlmeAux.Channel <= 14) - MinimumRate = RATE_1; - else - MinimumRate = RATE_6; - break; - case PHY_11A: - case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n - case PHY_11GN_MIXED: - case PHY_11AGN_MIXED: - case PHY_11AN_MIXED: - case PHY_11N_5G: + ======================================================================== +*/ +void RTMPUpdateMlmeRate(struct rt_rtmp_adapter *pAd) +{ + u8 MinimumRate; + u8 ProperMlmeRate; /*= RATE_54; */ + u8 i, j, RateIdx = 12; /*1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ + BOOLEAN bMatch = FALSE; + + switch (pAd->CommonCfg.PhyMode) { + case PHY_11B: + ProperMlmeRate = RATE_11; + MinimumRate = RATE_1; + break; + case PHY_11BG_MIXED: + case PHY_11ABGN_MIXED: + case PHY_11BGN_MIXED: + if ((pAd->MlmeAux.SupRateLen == 4) && + (pAd->MlmeAux.ExtRateLen == 0)) + /* B only AP */ + ProperMlmeRate = RATE_11; + else ProperMlmeRate = RATE_24; + + if (pAd->MlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else MinimumRate = RATE_6; - break; - case PHY_11ABG_MIXED: - ProperMlmeRate = RATE_24; - if (pAd->MlmeAux.Channel <= 14) - MinimumRate = RATE_1; - else - MinimumRate = RATE_6; - break; - default: // error - ProperMlmeRate = RATE_1; + break; + case PHY_11A: + case PHY_11N_2_4G: /* rt2860 need to check mlmerate for 802.11n */ + case PHY_11GN_MIXED: + case PHY_11AGN_MIXED: + case PHY_11AN_MIXED: + case PHY_11N_5G: + ProperMlmeRate = RATE_24; + MinimumRate = RATE_6; + break; + case PHY_11ABG_MIXED: + ProperMlmeRate = RATE_24; + if (pAd->MlmeAux.Channel <= 14) MinimumRate = RATE_1; - break; - } - - for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) - { - for (j = 0; j < RateIdx; j++) - { - if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) - { - if (j == ProperMlmeRate) - { + else + MinimumRate = RATE_6; + break; + default: /* error */ + ProperMlmeRate = RATE_1; + MinimumRate = RATE_1; + break; + } + + for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) { + for (j = 0; j < RateIdx; j++) { + if ((pAd->MlmeAux.SupRate[i] & 0x7f) == + RateIdTo500Kbps[j]) { + if (j == ProperMlmeRate) { bMatch = TRUE; break; } @@ -7918,16 +5513,12 @@ VOID RTMPUpdateMlmeRate( break; } - if (bMatch == FALSE) - { - for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) - { - for (j = 0; j < RateIdx; j++) - { - if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j]) - { - if (j == ProperMlmeRate) - { + if (bMatch == FALSE) { + for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) { + for (j = 0; j < RateIdx; j++) { + if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == + RateIdTo500Kbps[j]) { + if (j == ProperMlmeRate) { bMatch = TRUE; break; } @@ -7939,51 +5530,48 @@ VOID RTMPUpdateMlmeRate( } } - if (bMatch == FALSE) - { + if (bMatch == FALSE) { ProperMlmeRate = MinimumRate; } pAd->CommonCfg.MlmeRate = MinimumRate; pAd->CommonCfg.RtsRate = ProperMlmeRate; - if (pAd->CommonCfg.MlmeRate >= RATE_6) - { + if (pAd->CommonCfg.MlmeRate >= RATE_6) { pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; - pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; - pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM; - pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; - } - else - { + pAd->CommonCfg.MlmeTransmit.field.MCS = + OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = + MODE_OFDM; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = + OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } else { pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate; - pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK; - pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = + MODE_CCK; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = + pAd->CommonCfg.MlmeRate; } - DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word)); + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n", + pAd->CommonCfg.MlmeTransmit.word)); } -CHAR RTMPMaxRssi( - IN PRTMP_ADAPTER pAd, - IN CHAR Rssi0, - IN CHAR Rssi1, - IN CHAR Rssi2) +char RTMPMaxRssi(struct rt_rtmp_adapter *pAd, + char Rssi0, char Rssi1, char Rssi2) { - CHAR larger = -127; + char larger = -127; - if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) - { + if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) { larger = Rssi0; } - if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) - { + if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) { larger = max(Rssi0, Rssi1); } - if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) - { + if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) { larger = max(larger, Rssi2); } @@ -7993,56 +5581,6 @@ CHAR RTMPMaxRssi( return larger; } -#ifdef RT2870 -// Antenna divesity use GPIO3 and EESK pin for control -// Antenna and EEPROM access are both using EESK pin, -// Therefor we should avoid accessing EESK at the same time -// Then restore antenna after EEPROM access -VOID AsicSetRxAnt( - IN PRTMP_ADAPTER pAd, - IN UCHAR Ant) -{ - UINT32 Value; - UINT32 x; - - if ((pAd->EepromAccess) || - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) || - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) || - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) || - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) - { - return; - } - - // the antenna selection is through firmware and MAC register(GPIO3) - if (Ant == 0) - { - // Main antenna - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - x |= (EESK); - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value); - Value &= ~(0x0808); - RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n")); - } - else - { - // Aux antenna - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - x &= ~(EESK); - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value); - Value &= ~(0x0808); - Value |= 0x08; - RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n")); - } -} -#endif - /* ======================================================================== Routine Description: @@ -8056,91 +5594,70 @@ VOID AsicSetRxAnt( ======================================================================== */ -VOID AsicEvaluateRxAnt( - IN PRTMP_ADAPTER pAd) +void AsicEvaluateRxAnt(struct rt_rtmp_adapter *pAd) { - UCHAR BBPR3 = 0; + u8 BBPR3 = 0; if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_RADIO_OFF | - fRTMP_ADAPTER_NIC_NOT_EXIST | - fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) - || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) -#ifdef RT2870 - || (pAd->EepromAccess) -#endif - ) - return; - + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_NIC_NOT_EXIST | + fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) || + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) #ifdef RT30xx - // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove - // one is antenna diversity:there is only one antenna can rx and tx - // the other is failed antenna remove:two physical antenna can rx and tx - if (pAd->NicConfig2.field.AntDiversity) - { - DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n", - pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt)); - - AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt); - - pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt - pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE; - pAd->RxAnt.RcvPktNumWhenEvaluate = 0; + || (pAd->EepromAccess) +#endif /* RT30xx // */ +#ifdef RT3090 + || (pAd->bPCIclkOff == TRUE) +#endif /* RT3090 // */ + ) + return; - // a one-shot timer to end the evalution - // dynamic adjust antenna evaluation period according to the traffic - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100); - else - RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300); - } - else -#endif { - if (pAd->StaCfg.Psm == PWR_SAVE) - return; + /*if (pAd->StaCfg.Psm == PWR_SAVE) */ + /* return; */ - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); - BBPR3 &= (~0x18); - if(pAd->Antenna.field.RxPath == 3) - { - BBPR3 |= (0x10); - } - else if(pAd->Antenna.field.RxPath == 2) - { - BBPR3 |= (0x8); - } - else if(pAd->Antenna.field.RxPath == 1) { - BBPR3 |= (0x0); - } - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); - -#ifdef RT2860 - pAd->StaCfg.BBPR3 = BBPR3; -#endif - } - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) - ) - { - ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + - pAd->RalinkCounters.OneSecTxRetryOkCount + - pAd->RalinkCounters.OneSecTxFailCount; + if (pAd->StaCfg.Psm == PWR_SAVE) + return; - // dynamic adjust antenna evaluation period according to the traffic - if (TxTotalCnt > 50) - { - RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20); - pAd->Mlme.bLowThroughput = FALSE; - } - else - { - RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300); - pAd->Mlme.bLowThroughput = TRUE; + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + if (pAd->Antenna.field.RxPath == 3) { + BBPR3 |= (0x10); + } else if (pAd->Antenna.field.RxPath == 2) { + BBPR3 |= (0x8); + } else if (pAd->Antenna.field.RxPath == 1) { + BBPR3 |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); +#ifdef RTMP_MAC_PCI + pAd->StaCfg.BBPR3 = BBPR3; +#endif /* RTMP_MAC_PCI // */ + if (OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + ) { + unsigned long TxTotalCnt = + pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + /* dynamic adjust antenna evaluation period according to the traffic */ + if (TxTotalCnt > 50) { + RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, + 20); + pAd->Mlme.bLowThroughput = FALSE; + } else { + RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, + 300); + pAd->Mlme.bLowThroughput = TRUE; + } + } } + } + } /* @@ -8156,90 +5673,54 @@ VOID AsicEvaluateRxAnt( ======================================================================== */ -VOID AsicRxAntEvalTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) +void AsicRxAntEvalTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) { - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; - UCHAR BBPR3 = 0; - CHAR larger = -127, rssi0, rssi1, rssi2; - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_RADIO_OFF | - fRTMP_ADAPTER_NIC_NOT_EXIST) - || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) -#ifdef RT2870 - || (pAd->EepromAccess) -#endif - ) - return; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; + u8 BBPR3 = 0; + char larger = -127, rssi0, rssi1, rssi2; - { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_NIC_NOT_EXIST) || + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) #ifdef RT30xx - if (pAd->NicConfig2.field.AntDiversity) - { - if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt])) - { - UCHAR temp; - - // - // select PrimaryRxAntPair - // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair. - // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt - // - temp = pAd->RxAnt.Pair1PrimaryRxAnt; - pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt; - pAd->RxAnt.Pair1SecondaryRxAnt = temp; - - pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3); - pAd->RxAnt.EvaluateStableCnt = 0; - } - else - { - // if the evaluated antenna is not better than original, switch back to original antenna - AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); - pAd->RxAnt.EvaluateStableCnt ++; - } - - pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt + || (pAd->EepromAccess) +#endif /* RT30xx // */ +#ifdef RT3090 + || (pAd->bPCIclkOff == TRUE) +#endif /* RT3090 // */ + ) + return; - DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n", - pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate)); - } - else -#endif + { + /*if (pAd->StaCfg.Psm == PWR_SAVE) */ + /* return; */ { if (pAd->StaCfg.Psm == PWR_SAVE) return; - // if the traffic is low, use average rssi as the criteria - if (pAd->Mlme.bLowThroughput == TRUE) - { + /* if the traffic is low, use average rssi as the criteria */ + if (pAd->Mlme.bLowThroughput == TRUE) { rssi0 = pAd->StaCfg.RssiSample.LastRssi0; rssi1 = pAd->StaCfg.RssiSample.LastRssi1; rssi2 = pAd->StaCfg.RssiSample.LastRssi2; - } - else - { + } else { rssi0 = pAd->StaCfg.RssiSample.AvgRssi0; rssi1 = pAd->StaCfg.RssiSample.AvgRssi1; rssi2 = pAd->StaCfg.RssiSample.AvgRssi2; } - if(pAd->Antenna.field.RxPath == 3) - { + if (pAd->Antenna.field.RxPath == 3) { larger = max(rssi0, rssi1); if (larger > (rssi2 + 20)) pAd->Mlme.RealRxPath = 2; else pAd->Mlme.RealRxPath = 3; - } - else if(pAd->Antenna.field.RxPath == 2) - { + } else if (pAd->Antenna.field.RxPath == 2) { if (rssi0 > (rssi1 + 20)) pAd->Mlme.RealRxPath = 1; else @@ -8248,39 +5729,45 @@ VOID AsicRxAntEvalTimeout( RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); BBPR3 &= (~0x18); - if(pAd->Mlme.RealRxPath == 3) - { + if (pAd->Mlme.RealRxPath == 3) { BBPR3 |= (0x10); - } - else if(pAd->Mlme.RealRxPath == 2) - { + } else if (pAd->Mlme.RealRxPath == 2) { BBPR3 |= (0x8); - } - else if(pAd->Mlme.RealRxPath == 1) - { + } else if (pAd->Mlme.RealRxPath == 1) { BBPR3 |= (0x0); } RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); -#ifdef RT2860 +#ifdef RTMP_MAC_PCI pAd->StaCfg.BBPR3 = BBPR3; -#endif +#endif /* RTMP_MAC_PCI // */ } } + } -VOID APSDPeriodicExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) +void APSDPeriodicExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) { - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) return; pAd->CommonCfg.TriggerTimerCount++; +/* Driver should not send trigger frame, it should be send by application layer */ +/* + if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable + && (pAd->CommonCfg.bNeedSendTriggerFrame || + (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO)))) + { + DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n")); + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); + pAd->CommonCfg.bNeedSendTriggerFrame = FALSE; + pAd->CommonCfg.TriggerTimerCount = 0; + pAd->CommonCfg.bInServicePeriod = TRUE; + }*/ } /* @@ -8297,11 +5784,9 @@ VOID APSDPeriodicExec( ======================================================================== */ -VOID RTMPSetPiggyBack( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bPiggyBack) +void RTMPSetPiggyBack(struct rt_rtmp_adapter *pAd, IN BOOLEAN bPiggyBack) { - TX_LINK_CFG_STRUC TxLinkCfg; + TX_LINK_CFG_STRUC TxLinkCfg; RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); @@ -8324,36 +5809,32 @@ VOID RTMPSetPiggyBack( ======================================================================== */ -BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry) +BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry) { - BOOLEAN result = TRUE; + BOOLEAN result = TRUE; { - // only associated STA counts - if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC)) - { + /* only associated STA counts */ + if (pEntry && (pEntry->ValidAsCLI) + && (pEntry->Sst == SST_ASSOC)) { result = pAd->StaCfg.bAutoTxRateSwitch; - } - else + } else result = FALSE; } return result; } - -BOOLEAN RTMPAutoRateSwitchCheck( - IN PRTMP_ADAPTER pAd) +BOOLEAN RTMPAutoRateSwitchCheck(struct rt_rtmp_adapter *pAd) { - if (pAd->StaCfg.bAutoTxRateSwitch) - return TRUE; - + { + if (pAd->StaCfg.bAutoTxRateSwitch) + return TRUE; + } return FALSE; } - /* ======================================================================== Routine Description: @@ -8369,13 +5850,15 @@ BOOLEAN RTMPAutoRateSwitchCheck( ======================================================================== */ -UCHAR RTMPStaFixedTxMode( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry) +u8 RTMPStaFixedTxMode(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry) { - UCHAR tx_mode = FIXED_TXMODE_HT; + u8 tx_mode = FIXED_TXMODE_HT; - tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode; + { + tx_mode = + (u8)pAd->StaCfg.DesiredTransmitSetting.field. + FixedTxMode; + } return tx_mode; } @@ -8395,9 +5878,7 @@ UCHAR RTMPStaFixedTxMode( ======================================================================== */ -VOID RTMPUpdateLegacyTxSetting( - UCHAR fixed_tx_mode, - PMAC_TABLE_ENTRY pEntry) +void RTMPUpdateLegacyTxSetting(u8 fixed_tx_mode, struct rt_mac_table_entry *pEntry) { HTTRANSMIT_SETTING TransmitSetting; @@ -8409,26 +5890,24 @@ VOID RTMPUpdateLegacyTxSetting( TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE; TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS; - if (fixed_tx_mode == FIXED_TXMODE_CCK) - { + if (fixed_tx_mode == FIXED_TXMODE_CCK) { TransmitSetting.field.MODE = MODE_CCK; - // CCK mode allow MCS 0~3 + /* CCK mode allow MCS 0~3 */ if (TransmitSetting.field.MCS > MCS_3) TransmitSetting.field.MCS = MCS_3; - } - else - { + } else { TransmitSetting.field.MODE = MODE_OFDM; - // OFDM mode allow MCS 0~7 + /* OFDM mode allow MCS 0~7 */ if (TransmitSetting.field.MCS > MCS_7) TransmitSetting.field.MCS = MCS_7; } - if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) - { + if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) { pEntry->HTPhyMode.word = TransmitSetting.word; - DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n", - pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS)); + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n", + pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), + pEntry->HTPhyMode.field.MCS)); } } @@ -8442,381 +5921,150 @@ VOID RTMPUpdateLegacyTxSetting( ========================================================================== */ -VOID AsicStaBbpTuning( - IN PRTMP_ADAPTER pAd) +void AsicStaBbpTuning(struct rt_rtmp_adapter *pAd) { - UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30; - CHAR Rssi; + u8 OrigR66Value = 0, R66; /*, R66UpperBound = 0x30, R66LowerBound = 0x30; */ + char Rssi; - // 2860C did not support Fase CCA, therefore can't tune + /* 2860C did not support Fase CCA, therefore can't tune */ if (pAd->MACVersion == 0x28600100) return; - // - // work as a STA - // - if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING + /* */ + /* work as a STA */ + /* */ + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) /* no R66 tuning when SCANNING */ return; if ((pAd->OpMode == OPMODE_STA) - && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) - ) - && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) -#ifdef RT2860 - && (pAd->bPCIclkOff == FALSE)) -#endif -#ifdef RT2870 - ) -#endif - { + && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + ) + && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) +#ifdef RTMP_MAC_PCI + && (pAd->bPCIclkOff == FALSE) +#endif /* RTMP_MAC_PCI // */ + ) { RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value); R66 = OrigR66Value; if (pAd->Antenna.field.RxPath > 1) - Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1; + Rssi = + (pAd->StaCfg.RssiSample.AvgRssi0 + + pAd->StaCfg.RssiSample.AvgRssi1) >> 1; else Rssi = pAd->StaCfg.RssiSample.AvgRssi0; - if (pAd->LatchRfRegs.Channel <= 14) - { //BG band -#ifdef RT2870 - // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control - // Otherwise, it will have some throughput side effect when low RSSI - if (IS_RT30xx(pAd)) - { - if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) - { - R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20; - if (OrigR66Value != R66) - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - else - { - R66 = 0x1C + 2*GET_LNA_GAIN(pAd); - if (OrigR66Value != R66) - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + if (pAd->LatchRfRegs.Channel <= 14) { /*BG band */ +#ifdef RT30xx + /* RT3070 is a no LNA solution, it should have different control regarding to AGC gain control */ + /* Otherwise, it will have some throughput side effect when low RSSI */ + + if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd) + || IS_RT3390(pAd)) { + if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) { + R66 = + 0x1C + 2 * GET_LNA_GAIN(pAd) + 0x20; + if (OrigR66Value != R66) { + RTMP_BBP_IO_WRITE8_BY_REG_ID + (pAd, BBP_R66, R66); + } + } else { + R66 = 0x1C + 2 * GET_LNA_GAIN(pAd); + if (OrigR66Value != R66) { + RTMP_BBP_IO_WRITE8_BY_REG_ID + (pAd, BBP_R66, R66); + } } - } - else -#endif // RT2870 // + } else +#endif /* RT30xx // */ { - if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) - { + if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) { R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10; - if (OrigR66Value != R66) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + if (OrigR66Value != R66) { + RTMP_BBP_IO_WRITE8_BY_REG_ID + (pAd, BBP_R66, R66); } - } - else - { + } else { R66 = 0x2E + GET_LNA_GAIN(pAd); - if (OrigR66Value != R66) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + if (OrigR66Value != R66) { + RTMP_BBP_IO_WRITE8_BY_REG_ID + (pAd, BBP_R66, R66); } } } - } - else - { //A band - if (pAd->CommonCfg.BBPCurrentBW == BW_20) - { - if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) - { - R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10; - if (OrigR66Value != R66) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } else { /*A band */ + if (pAd->CommonCfg.BBPCurrentBW == BW_20) { + if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) { + R66 = + 0x32 + (GET_LNA_GAIN(pAd) * 5) / 3 + + 0x10; + if (OrigR66Value != R66) { + RTMP_BBP_IO_WRITE8_BY_REG_ID + (pAd, BBP_R66, R66); } - } - else - { - R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3; - if (OrigR66Value != R66) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } else { + R66 = + 0x32 + (GET_LNA_GAIN(pAd) * 5) / 3; + if (OrigR66Value != R66) { + RTMP_BBP_IO_WRITE8_BY_REG_ID + (pAd, BBP_R66, R66); } } - } - else - { - if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) - { - R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10; - if (OrigR66Value != R66) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } else { + if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) { + R66 = + 0x3A + (GET_LNA_GAIN(pAd) * 5) / 3 + + 0x10; + if (OrigR66Value != R66) { + RTMP_BBP_IO_WRITE8_BY_REG_ID + (pAd, BBP_R66, R66); } - } - else - { - R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3; - if (OrigR66Value != R66) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } else { + R66 = + 0x3A + (GET_LNA_GAIN(pAd) * 5) / 3; + if (OrigR66Value != R66) { + RTMP_BBP_IO_WRITE8_BY_REG_ID + (pAd, BBP_R66, R66); } } } } - - } -} - -#ifdef RT2860 -VOID AsicResetFromDMABusy( - IN PRTMP_ADAPTER pAd) -{ - UINT32 Data; - BOOLEAN bCtrl = FALSE; - - DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n")); - - // Be sure restore link control value so we can write register. - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); - if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)) - { - DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n")); - RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT); - RTMPusecDelay(6000); - pAd->bPCIclkOff = FALSE; - bCtrl = TRUE; } - // Reset DMA - RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); - Data |= 0x2; - RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); - - // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too. - // Reset DMA/CPU ring index - RTMPRingCleanUp(pAd, QID_AC_BK); - RTMPRingCleanUp(pAd, QID_AC_BE); - RTMPRingCleanUp(pAd, QID_AC_VI); - RTMPRingCleanUp(pAd, QID_AC_VO); - RTMPRingCleanUp(pAd, QID_HCCA); - RTMPRingCleanUp(pAd, QID_MGMT); - RTMPRingCleanUp(pAd, QID_RX); - - // Clear Reset - RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); - Data &= 0xfffffffd; - RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); - - // If in Radio off, should call RTMPPCIePowerLinkCtrl again. - if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE)) - RTMPPCIeLinkCtrlSetting(pAd, 3); - - RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS); - DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n")); -} - -VOID AsicResetBBP( - IN PRTMP_ADAPTER pAd) -{ - DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n")); - - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc); - - // After hard-reset BBP, initialize all BBP values. - NICRestoreBBPValue(pAd); - DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n")); -} - -VOID AsicResetMAC( - IN PRTMP_ADAPTER pAd) -{ - ULONG Data; - - DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n")); - RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); - Data |= 0x4; - RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); - Data &= 0xfffffffb; - RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); - - DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n")); } -VOID AsicResetPBF( - IN PRTMP_ADAPTER pAd) +void RTMPSetAGCInitValue(struct rt_rtmp_adapter *pAd, u8 BandWidth) { - ULONG Value1, Value2; - ULONG Data; + u8 R66 = 0x30; - RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1); - RTMP_IO_READ32(pAd, PBF_DBG, &Value2); - - Value2 &= 0xff; - // sum should be equals to 0xff, which is the total buffer size. - if ((Value1 + Value2) < 0xff) - { - DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n")); - RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); - Data |= 0x8; - RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); - Data &= 0xfffffff7; - RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); - - DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n")); - } -} -#endif /* RT2860 */ - -VOID RTMPSetAGCInitValue( - IN PRTMP_ADAPTER pAd, - IN UCHAR BandWidth) -{ - UCHAR R66 = 0x30; + if (pAd->LatchRfRegs.Channel <= 14) { /* BG band */ +#ifdef RT30xx + /* Gary was verified Amazon AP and find that RT307x has BBP_R66 invalid default value */ - if (pAd->LatchRfRegs.Channel <= 14) - { // BG band - R66 = 0x2E + GET_LNA_GAIN(pAd); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - else - { //A band - if (BandWidth == BW_20) - { - R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3); + if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd) + || IS_RT3390(pAd)) { + R66 = 0x1C + 2 * GET_LNA_GAIN(pAd); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - else + } else +#endif /* RT30xx // */ { - R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3); + R66 = 0x2E + GET_LNA_GAIN(pAd); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); } - } - -} - -VOID AsicTurnOffRFClk( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel) -{ - - // RF R2 bit 18 = 0 - UINT32 R1 = 0, R2 = 0, R3 = 0; - UCHAR index; - RTMP_RF_REGS *RFRegTable; - - // The RF programming sequence is difference between 3xxx and 2xxx - if (IS_RT3090(pAd)) - { - RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup - return; - } - - RFRegTable = RF2850RegTable; - - switch (pAd->RfIcType) - { - case RFIC_2820: - case RFIC_2850: - case RFIC_2720: - case RFIC_2750: - - for (index = 0; index < NUM_OF_2850_CHNL; index++) - { - if (Channel == RFRegTable[index].Channel) - { - R1 = RFRegTable[index].R1 & 0xffffdfff; - R2 = RFRegTable[index].R2 & 0xfffbffff; - R3 = RFRegTable[index].R3 & 0xfff3ffff; - - RTMP_RF_IO_WRITE32(pAd, R1); - RTMP_RF_IO_WRITE32(pAd, R2); - - // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0. - // Set RF R2 bit18=0, R3 bit[18:19]=0 - //if (pAd->StaCfg.bRadio == FALSE) - if (1) - { - RTMP_RF_IO_WRITE32(pAd, R3); - - DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n", - Channel, pAd->RfIcType, R2, R3)); - } - else - DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n", - Channel, pAd->RfIcType, R2)); - break; - } + } else { /*A band */ + { + if (BandWidth == BW_20) { + R66 = + (u8)(0x32 + + (GET_LNA_GAIN(pAd) * 5) / 3); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } else { + R66 = + (u8)(0x3A + + (GET_LNA_GAIN(pAd) * 5) / 3); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); } - break; - - default: - break; - } -} - - -VOID AsicTurnOnRFClk( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel) -{ - - // RF R2 bit 18 = 0 - UINT32 R1 = 0, R2 = 0, R3 = 0; - UCHAR index; - RTMP_RF_REGS *RFRegTable; - - // The RF programming sequence is difference between 3xxx and 2xxx - if (IS_RT3090(pAd)) - return; - - RFRegTable = RF2850RegTable; - - switch (pAd->RfIcType) - { - case RFIC_2820: - case RFIC_2850: - case RFIC_2720: - case RFIC_2750: - - for (index = 0; index < NUM_OF_2850_CHNL; index++) - { - if (Channel == RFRegTable[index].Channel) - { - R3 = pAd->LatchRfRegs.R3; - R3 &= 0xfff3ffff; - R3 |= 0x00080000; - RTMP_RF_IO_WRITE32(pAd, R3); - - R1 = RFRegTable[index].R1; - RTMP_RF_IO_WRITE32(pAd, R1); - - R2 = RFRegTable[index].R2; - if (pAd->Antenna.field.TxPath == 1) - { - R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; - } - - if (pAd->Antenna.field.RxPath == 2) - { - R2 |= 0x40; // write 1 to off Rxpath. - } - else if (pAd->Antenna.field.RxPath == 1) - { - R2 |= 0x20040; // write 1 to off RxPath - } - RTMP_RF_IO_WRITE32(pAd, R2); - - break; - } - } - break; - - default: - break; + } } - DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n", - Channel, - pAd->RfIcType, - R2)); } - diff --git a/drivers/staging/rt2860/common/rt_channel.c b/drivers/staging/rt2860/common/rt_channel.c new file mode 100644 index 0000000000000000000000000000000000000000..5387989811777ba1b3ae36a335bcfd830d9e2b2f --- /dev/null +++ b/drivers/staging/rt2860/common/rt_channel.c @@ -0,0 +1,1705 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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 "../rt_config.h" + +struct rt_ch_freq_map CH_HZ_ID_MAP[] = { + {1, 2412} + , + {2, 2417} + , + {3, 2422} + , + {4, 2427} + , + {5, 2432} + , + {6, 2437} + , + {7, 2442} + , + {8, 2447} + , + {9, 2452} + , + {10, 2457} + , + {11, 2462} + , + {12, 2467} + , + {13, 2472} + , + {14, 2484} + , + + /* UNII */ + {36, 5180} + , + {40, 5200} + , + {44, 5220} + , + {48, 5240} + , + {52, 5260} + , + {56, 5280} + , + {60, 5300} + , + {64, 5320} + , + {149, 5745} + , + {153, 5765} + , + {157, 5785} + , + {161, 5805} + , + {165, 5825} + , + {167, 5835} + , + {169, 5845} + , + {171, 5855} + , + {173, 5865} + , + + /* HiperLAN2 */ + {100, 5500} + , + {104, 5520} + , + {108, 5540} + , + {112, 5560} + , + {116, 5580} + , + {120, 5600} + , + {124, 5620} + , + {128, 5640} + , + {132, 5660} + , + {136, 5680} + , + {140, 5700} + , + + /* Japan MMAC */ + {34, 5170} + , + {38, 5190} + , + {42, 5210} + , + {46, 5230} + , + + /* Japan */ + {184, 4920} + , + {188, 4940} + , + {192, 4960} + , + {196, 4980} + , + + {208, 5040} + , /* Japan, means J08 */ + {212, 5060} + , /* Japan, means J12 */ + {216, 5080} + , /* Japan, means J16 */ +}; + +int CH_HZ_ID_MAP_NUM = (sizeof(CH_HZ_ID_MAP) / sizeof(struct rt_ch_freq_map)); + +struct rt_ch_region ChRegion[] = { + { /* Antigua and Berbuda */ + "AG", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, FALSE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Argentina */ + "AR", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {52, 4, 24, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {149, 4, 30, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Aruba */ + "AW", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, FALSE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Australia */ + "AU", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {149, 5, 30, BOTH, FALSE} + , /* 5G, ch 149~165 */ + {0} + , /* end */ + } + } + , + + { /* Austria */ + "AT", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, TRUE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Bahamas */ + "BS", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {149, 5, 30, BOTH, FALSE} + , /* 5G, ch 149~165 */ + {0} + , /* end */ + } + } + , + + { /* Barbados */ + "BB", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, FALSE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Bermuda */ + "BM", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, FALSE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Brazil */ + "BR", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {100, 11, 24, BOTH, FALSE} + , /* 5G, ch 100~140 */ + {149, 5, 30, BOTH, FALSE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Belgium */ + "BE", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 18, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 18, IDOR, FALSE} + , /* 5G, ch 52~64 */ + {0} + , /* end */ + } + } + , + + { /* Bulgaria */ + "BG", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, ODOR, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Canada */ + "CA", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {149, 5, 30, BOTH, FALSE} + , /* 5G, ch 149~165 */ + {0} + , /* end */ + } + } + , + + { /* Cayman IsLands */ + "KY", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, FALSE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Chile */ + "CL", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 20, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 20, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {149, 5, 20, BOTH, FALSE} + , /* 5G, ch 149~165 */ + {0} + , /* end */ + } + } + , + + { /* China */ + "CN", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {149, 4, 27, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Colombia */ + "CO", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 17, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, FALSE} + , /* 5G, ch 100~140 */ + {149, 5, 30, BOTH, FALSE} + , /* 5G, ch 149~165 */ + {0} + , /* end */ + } + } + , + + { /* Costa Rica */ + "CR", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 17, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {149, 4, 30, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Cyprus */ + "CY", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Czech_Republic */ + "CZ", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {0} + , /* end */ + } + } + , + + { /* Denmark */ + "DK", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Dominican Republic */ + "DO", + CE, + { + {1, 0, 20, BOTH, FALSE} + , /* 2.4 G, ch 0 */ + {149, 4, 20, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Equador */ + "EC", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {100, 11, 27, BOTH, FALSE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* El Salvador */ + "SV", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 30, BOTH, TRUE} + , /* 5G, ch 52~64 */ + {149, 4, 36, BOTH, TRUE} + , /* 5G, ch 149~165 */ + {0} + , /* end */ + } + } + , + + { /* Finland */ + "FI", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* France */ + "FR", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {0} + , /* end */ + } + } + , + + { /* Germany */ + "DE", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Greece */ + "GR", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, ODOR, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Guam */ + "GU", + CE, + { + {1, 11, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~11 */ + {36, 4, 17, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, FALSE} + , /* 5G, ch 100~140 */ + {149, 5, 30, BOTH, FALSE} + , /* 5G, ch 149~165 */ + {0} + , /* end */ + } + } + , + + { /* Guatemala */ + "GT", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 17, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {149, 4, 30, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Haiti */ + "HT", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 17, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {149, 4, 30, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Honduras */ + "HN", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {149, 4, 27, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Hong Kong */ + "HK", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, FALSE} + , /* 5G, ch 52~64 */ + {149, 4, 30, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Hungary */ + "HU", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {0} + , /* end */ + } + } + , + + { /* Iceland */ + "IS", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* India */ + "IN", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {149, 4, 24, IDOR, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Indonesia */ + "ID", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {149, 4, 27, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Ireland */ + "IE", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, ODOR, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Israel */ + "IL", + CE, + { + {1, 3, 20, IDOR, FALSE} + , /* 2.4 G, ch 1~3 */ + {4, 6, 20, BOTH, FALSE} + , /* 2.4 G, ch 4~9 */ + {10, 4, 20, IDOR, FALSE} + , /* 2.4 G, ch 10~13 */ + {0} + , /* end */ + } + } + , + + { /* Italy */ + "IT", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, ODOR, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Japan */ + "JP", + JAP, + { + {1, 14, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~14 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {0} + , /* end */ + } + } + , + + { /* Jordan */ + "JO", + CE, + { + {1, 13, 20, IDOR, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {149, 4, 23, IDOR, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Latvia */ + "LV", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Liechtenstein */ + "LI", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Lithuania */ + "LT", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Luxemburg */ + "LU", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Malaysia */ + "MY", + CE, + { + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {149, 5, 20, BOTH, FALSE} + , /* 5G, ch 149~165 */ + {0} + , /* end */ + } + } + , + + { /* Malta */ + "MT", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Marocco */ + "MA", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 24, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {0} + , /* end */ + } + } + , + + { /* Mexico */ + "MX", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {149, 5, 30, IDOR, FALSE} + , /* 5G, ch 149~165 */ + {0} + , /* end */ + } + } + , + + { /* Netherlands */ + "NL", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* New Zealand */ + "NZ", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 24, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {149, 4, 30, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Norway */ + "NO", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 24, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 24, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Peru */ + "PE", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {149, 4, 27, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Portugal */ + "PT", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Poland */ + "PL", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Romania */ + "RO", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Russia */ + "RU", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {149, 4, 20, IDOR, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Saudi Arabia */ + "SA", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {149, 4, 23, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Serbia_and_Montenegro */ + "CS", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {0} + , /* end */ + } + } + , + + { /* Singapore */ + "SG", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {149, 4, 20, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Slovakia */ + "SK", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Slovenia */ + "SI", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {0} + , /* end */ + } + } + , + + { /* South Africa */ + "ZA", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, FALSE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {149, 4, 30, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* South Korea */ + "KR", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 20, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 20, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {100, 8, 20, BOTH, FALSE} + , /* 5G, ch 100~128 */ + {149, 4, 20, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Spain */ + "ES", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 17, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Sweden */ + "SE", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Switzerland */ + "CH", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~13 */ + {36, 4, 23, IDOR, TRUE} + , /* 5G, ch 36~48 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {0} + , /* end */ + } + } + , + + { /* Taiwan */ + "TW", + CE, + { + {1, 11, 30, BOTH, FALSE} + , /* 2.4 G, ch 1~11 */ + {52, 4, 23, IDOR, FALSE} + , /* 5G, ch 52~64 */ + {0} + , /* end */ + } + } + , + + { /* Turkey */ + "TR", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~11 */ + {36, 4, 23, BOTH, FALSE} + , /* 5G, ch 36~48 */ + {52, 4, 23, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {0} + , /* end */ + } + } + , + + { /* UK */ + "GB", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~11 */ + {36, 4, 23, IDOR, FALSE} + , /* 5G, ch 52~64 */ + {52, 4, 23, IDOR, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {0} + , /* end */ + } + } + , + + { /* Ukraine */ + "UA", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~11 */ + {0} + , /* end */ + } + } + , + + { /* United_Arab_Emirates */ + "AE", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~11 */ + {0} + , /* end */ + } + } + , + + { /* United_States */ + "US", + CE, + { + {1, 11, 30, BOTH, FALSE} + , /* 2.4 G, ch 1~11 */ + {36, 4, 17, IDOR, FALSE} + , /* 5G, ch 52~64 */ + {52, 4, 24, BOTH, TRUE} + , /* 5G, ch 52~64 */ + {100, 11, 30, BOTH, TRUE} + , /* 5G, ch 100~140 */ + {149, 5, 30, BOTH, FALSE} + , /* 5G, ch 149~165 */ + {0} + , /* end */ + } + } + , + + { /* Venezuela */ + "VE", + CE, + { + {1, 13, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~11 */ + {149, 4, 27, BOTH, FALSE} + , /* 5G, ch 149~161 */ + {0} + , /* end */ + } + } + , + + { /* Default */ + "", + CE, + { + {1, 11, 20, BOTH, FALSE} + , /* 2.4 G, ch 1~11 */ + {36, 4, 20, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {52, 4, 20, BOTH, FALSE} + , /* 5G, ch 52~64 */ + {100, 11, 20, BOTH, FALSE} + , /* 5G, ch 100~140 */ + {149, 5, 20, BOTH, FALSE} + , /* 5G, ch 149~165 */ + {0} + , /* end */ + } + } + , +}; + +static struct rt_ch_region *GetChRegion(u8 *CntryCode) +{ + int loop = 0; + struct rt_ch_region *pChRegion = NULL; + + while (strcmp((char *)ChRegion[loop].CountReg, "") != 0) { + if (strncmp + ((char *)ChRegion[loop].CountReg, (char *)CntryCode, + 2) == 0) { + pChRegion = &ChRegion[loop]; + break; + } + loop++; + } + + if (pChRegion == NULL) + pChRegion = &ChRegion[loop]; + return pChRegion; +} + +static void ChBandCheck(u8 PhyMode, u8 *pChType) +{ + switch (PhyMode) { + case PHY_11A: + case PHY_11AN_MIXED: + *pChType = BAND_5G; + break; + case PHY_11ABG_MIXED: + case PHY_11AGN_MIXED: + case PHY_11ABGN_MIXED: + *pChType = BAND_BOTH; + break; + + default: + *pChType = BAND_24G; + break; + } +} + +static u8 FillChList(struct rt_rtmp_adapter *pAd, + struct rt_ch_desp *pChDesp, + u8 Offset, u8 increment) +{ + int i, j, l; + u8 channel; + + j = Offset; + for (i = 0; i < pChDesp->NumOfCh; i++) { + channel = pChDesp->FirstChannel + i * increment; + for (l = 0; l < MAX_NUM_OF_CHANNELS; l++) { + if (channel == pAd->TxPower[l].Channel) { + pAd->ChannelList[j].Power = + pAd->TxPower[l].Power; + pAd->ChannelList[j].Power2 = + pAd->TxPower[l].Power2; + break; + } + } + if (l == MAX_NUM_OF_CHANNELS) + continue; + + pAd->ChannelList[j].Channel = + pChDesp->FirstChannel + i * increment; + pAd->ChannelList[j].MaxTxPwr = pChDesp->MaxTxPwr; + pAd->ChannelList[j].DfsReq = pChDesp->DfsReq; + j++; + } + pAd->ChannelListNum = j; + + return j; +} + +static inline void CreateChList(struct rt_rtmp_adapter *pAd, + struct rt_ch_region *pChRegion, u8 Geography) +{ + int i; + u8 offset = 0; + struct rt_ch_desp *pChDesp; + u8 ChType; + u8 increment; + + if (pChRegion == NULL) + return; + + ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); + + for (i = 0; i < 10; i++) { + pChDesp = &pChRegion->ChDesp[i]; + if (pChDesp->FirstChannel == 0) + break; + + if (ChType == BAND_5G) { + if (pChDesp->FirstChannel <= 14) + continue; + } else if (ChType == BAND_24G) { + if (pChDesp->FirstChannel > 14) + continue; + } + + if ((pChDesp->Geography == BOTH) + || (pChDesp->Geography == Geography)) { + if (pChDesp->FirstChannel > 14) + increment = 4; + else + increment = 1; + offset = FillChList(pAd, pChDesp, offset, increment); + } + } +} + +void BuildChannelListEx(struct rt_rtmp_adapter *pAd) +{ + struct rt_ch_region *pChReg; + + pChReg = GetChRegion(pAd->CommonCfg.CountryCode); + CreateChList(pAd, pChReg, pAd->CommonCfg.Geography); +} + +void BuildBeaconChList(struct rt_rtmp_adapter *pAd, + u8 *pBuf, unsigned long *pBufLen) +{ + int i; + unsigned long TmpLen; + struct rt_ch_region *pChRegion; + struct rt_ch_desp *pChDesp; + u8 ChType; + + pChRegion = GetChRegion(pAd->CommonCfg.CountryCode); + + if (pChRegion == NULL) + return; + + ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); + *pBufLen = 0; + + for (i = 0; i < 10; i++) { + pChDesp = &pChRegion->ChDesp[i]; + if (pChDesp->FirstChannel == 0) + break; + + if (ChType == BAND_5G) { + if (pChDesp->FirstChannel <= 14) + continue; + } else if (ChType == BAND_24G) { + if (pChDesp->FirstChannel > 14) + continue; + } + + if ((pChDesp->Geography == BOTH) + || (pChDesp->Geography == pAd->CommonCfg.Geography)) { + MakeOutgoingFrame(pBuf + *pBufLen, &TmpLen, + 1, &pChDesp->FirstChannel, + 1, &pChDesp->NumOfCh, + 1, &pChDesp->MaxTxPwr, END_OF_ARGS); + *pBufLen += TmpLen; + } + } +} + +static BOOLEAN IsValidChannel(struct rt_rtmp_adapter *pAd, u8 channel) +{ + int i; + + for (i = 0; i < pAd->ChannelListNum; i++) { + if (pAd->ChannelList[i].Channel == channel) + break; + } + + if (i == pAd->ChannelListNum) + return FALSE; + else + return TRUE; +} + +static u8 GetExtCh(u8 Channel, u8 Direction) +{ + char ExtCh; + + if (Direction == EXTCHA_ABOVE) + ExtCh = Channel + 4; + else + ExtCh = (Channel - 4) > 0 ? (Channel - 4) : 0; + + return ExtCh; +} + +void N_ChannelCheck(struct rt_rtmp_adapter *pAd) +{ + /*u8 ChannelNum = pAd->ChannelListNum; */ + u8 Channel = pAd->CommonCfg.Channel; + + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + && (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) { + if (Channel > 14) { + if ((Channel == 36) || (Channel == 44) + || (Channel == 52) || (Channel == 60) + || (Channel == 100) || (Channel == 108) + || (Channel == 116) || (Channel == 124) + || (Channel == 132) || (Channel == 149) + || (Channel == 157)) { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = + EXTCHA_ABOVE; + } else if ((Channel == 40) || (Channel == 48) + || (Channel == 56) || (Channel == 64) + || (Channel == 104) || (Channel == 112) + || (Channel == 120) || (Channel == 128) + || (Channel == 136) || (Channel == 153) + || (Channel == 161)) { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = + EXTCHA_BELOW; + } else { + pAd->CommonCfg.RegTransmitSetting.field.BW = + BW_20; + } + } else { + do { + u8 ExtCh; + u8 Dir = + pAd->CommonCfg.RegTransmitSetting.field. + EXTCHA; + ExtCh = GetExtCh(Channel, Dir); + if (IsValidChannel(pAd, ExtCh)) + break; + + Dir = + (Dir == + EXTCHA_ABOVE) ? EXTCHA_BELOW : + EXTCHA_ABOVE; + ExtCh = GetExtCh(Channel, Dir); + if (IsValidChannel(pAd, ExtCh)) { + pAd->CommonCfg.RegTransmitSetting.field. + EXTCHA = Dir; + break; + } + pAd->CommonCfg.RegTransmitSetting.field.BW = + BW_20; + } while (FALSE); + + if (Channel == 14) { + pAd->CommonCfg.RegTransmitSetting.field.BW = + BW_20; + /*pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; // We didn't set the ExtCh as NONE due to it'll set in RTMPSetHT() */ + } + } + } + +} + +void N_SetCenCh(struct rt_rtmp_adapter *pAd) +{ + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) { + if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == + EXTCHA_ABOVE) { + pAd->CommonCfg.CentralChannel = + pAd->CommonCfg.Channel + 2; + } else { + if (pAd->CommonCfg.Channel == 14) + pAd->CommonCfg.CentralChannel = + pAd->CommonCfg.Channel - 1; + else + pAd->CommonCfg.CentralChannel = + pAd->CommonCfg.Channel - 2; + } + } else { + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + } +} + +u8 GetCuntryMaxTxPwr(struct rt_rtmp_adapter *pAd, u8 channel) +{ + int i; + for (i = 0; i < pAd->ChannelListNum; i++) { + if (pAd->ChannelList[i].Channel == channel) + break; + } + + if (i == pAd->ChannelListNum) + return 0xff; + else + return pAd->ChannelList[i].MaxTxPwr; +} diff --git a/drivers/staging/rt3090/common/rt_rf.c b/drivers/staging/rt2860/common/rt_rf.c similarity index 69% rename from drivers/staging/rt3090/common/rt_rf.c rename to drivers/staging/rt2860/common/rt_rf.c index 9d638f71dbe5f5b99558d39360e437a5035c4d87..519121d8104007677e7b141c4e9b9c5a2a85d529 100644 --- a/drivers/staging/rt3090/common/rt_rf.c +++ b/drivers/staging/rt2860/common/rt_rf.c @@ -37,7 +37,6 @@ #include "../rt_config.h" - #ifdef RTMP_RF_RW_SUPPORT /* ======================================================================== @@ -54,27 +53,26 @@ ======================================================================== */ -NDIS_STATUS RT30xxWriteRFRegister( - IN PRTMP_ADAPTER pAd, - IN UCHAR regID, - IN UCHAR value) +int RT30xxWriteRFRegister(struct rt_rtmp_adapter *pAd, + u8 regID, u8 value) { - RF_CSR_CFG_STRUC rfcsr; - UINT i = 0; + RF_CSR_CFG_STRUC rfcsr; + u32 i = 0; - do - { + do { RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word); if (!rfcsr.field.RF_CSR_KICK) break; i++; } - while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); + while ((i < RETRY_LIMIT) + && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); - if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); + if ((i == RETRY_LIMIT) + || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("Retry count exhausted or device removed!\n")); return STATUS_UNSUCCESSFUL; } @@ -88,7 +86,6 @@ NDIS_STATUS RT30xxWriteRFRegister( return NDIS_STATUS_SUCCESS; } - /* ======================================================================== @@ -104,20 +101,16 @@ NDIS_STATUS RT30xxWriteRFRegister( ======================================================================== */ -NDIS_STATUS RT30xxReadRFRegister( - IN PRTMP_ADAPTER pAd, - IN UCHAR regID, - IN PUCHAR pValue) +int RT30xxReadRFRegister(struct rt_rtmp_adapter *pAd, + u8 regID, u8 *pValue) { - RF_CSR_CFG_STRUC rfcsr; - UINT i=0, k=0; + RF_CSR_CFG_STRUC rfcsr; + u32 i = 0, k = 0; - for (i=0; ichipOps.AsicRfInit) pAd->chipOps.AsicRfInit(pAd); } - -VOID RtmpChipOpsRFHook( - IN RTMP_ADAPTER *pAd) +void RtmpChipOpsRFHook(struct rt_rtmp_adapter *pAd) { - RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; pChipOps->pRFRegTable = NULL; pChipOps->AsicRfInit = NULL; @@ -168,34 +155,34 @@ VOID RtmpChipOpsRFHook( pChipOps->AsicRfTurnOff = NULL; pChipOps->AsicReverseRfFromSleepMode = NULL; pChipOps->AsicHaltAction = NULL; -#ifdef RT33xx -if (IS_RT3390(pAd) && (pAd->infType == RTMP_DEV_INF_PCI)) - { - pChipOps->pRFRegTable = RFRegTableOverRT3390; - pChipOps->AsicHaltAction = RT33xxHaltAction; - pChipOps->AsicRfTurnOff = RT33xxLoadRFSleepModeSetup; - pChipOps->AsicRfInit = NICInitRT3390RFRegisters; - pChipOps->AsicReverseRfFromSleepMode = RT33xxReverseRFSleepModeSetup; - } -#else // RT33xx // /* We depends on RfICType and MACVersion to assign the corresponding operation callbacks. */ #ifdef RT30xx - if (IS_RT30xx(pAd)) - { + if (IS_RT30xx(pAd)) { pChipOps->pRFRegTable = RT30xx_RFRegTable; pChipOps->AsicHaltAction = RT30xxHaltAction; +#ifdef RT3070 + if ((IS_RT3070(pAd) || IS_RT3071(pAd)) + && (pAd->infType == RTMP_DEV_INF_USB)) { + pChipOps->AsicRfInit = NICInitRT3070RFRegisters; + if (IS_RT3071(pAd)) { + pChipOps->AsicRfTurnOff = + RT30xxLoadRFSleepModeSetup; + pChipOps->AsicReverseRfFromSleepMode = + RT30xxReverseRFSleepModeSetup; + } + } +#endif /* RT3070 // */ #ifdef RT3090 - if (IS_RT3090(pAd) && (pAd->infType == RTMP_DEV_INF_PCI)) - { + if (IS_RT3090(pAd) && (pAd->infType == RTMP_DEV_INF_PCI)) { pChipOps->AsicRfTurnOff = RT30xxLoadRFSleepModeSetup; pChipOps->AsicRfInit = NICInitRT3090RFRegisters; - pChipOps->AsicReverseRfFromSleepMode = RT30xxReverseRFSleepModeSetup; + pChipOps->AsicReverseRfFromSleepMode = + RT30xxReverseRFSleepModeSetup; } -#endif // RT3090 // +#endif /* RT3090 // */ } -#endif // RT30xx // -#endif // RT33xx // +#endif /* RT30xx // */ } -#endif // RTMP_RF_RW_SUPPORT // +#endif /* RTMP_RF_RW_SUPPORT // */ diff --git a/drivers/staging/rt2860/common/rtmp_init.c b/drivers/staging/rt2860/common/rtmp_init.c index 20c2ce26bc9df3531f25e918eb321a81b3c124fe..21a95ffdfb865aa461e2eb5bb63b9b09f925b331 100644 --- a/drivers/staging/rt2860/common/rtmp_init.c +++ b/drivers/staging/rt2860/common/rtmp_init.c @@ -33,172 +33,111 @@ Revision History: Who When What -------- ---------- ---------------------------------------------- - Paul Lin 2002-08-01 created - John Chang 2004-08-20 RT2561/2661 use scatter-gather scheme - Jan Lee 2006-09-15 RT2860. Change for 802.11n , EEPROM, Led, BA, HT. */ #include "../rt_config.h" -#ifdef RT2860 -#include "firmware.h" -#include -#endif -#ifdef RT2870 -/* New firmware handles both RT2870 and RT3070. */ -#include "../../rt3070/firmware.h" -#endif - -UCHAR BIT8[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; -ULONG BIT32[] = {0x00000001, 0x00000002, 0x00000004, 0x00000008, - 0x00000010, 0x00000020, 0x00000040, 0x00000080, - 0x00000100, 0x00000200, 0x00000400, 0x00000800, - 0x00001000, 0x00002000, 0x00004000, 0x00008000, - 0x00010000, 0x00020000, 0x00040000, 0x00080000, - 0x00100000, 0x00200000, 0x00400000, 0x00800000, - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000}; - -char* CipherName[] = {"none","wep64","wep128","TKIP","AES","CKIP64","CKIP128"}; - -// -// BBP register initialization set -// -REG_PAIR BBPRegTable[] = { - {BBP_R65, 0x2C}, // fix rssi issue - {BBP_R66, 0x38}, // Also set this default value to pAd->BbpTuning.R66CurrentValue at initial - {BBP_R69, 0x12}, - {BBP_R70, 0xa}, // BBP_R70 will change to 0x8 in ApStartUp and LinkUp for rt2860C, otherwise value is 0xa - {BBP_R73, 0x10}, - {BBP_R81, 0x37}, - {BBP_R82, 0x62}, - {BBP_R83, 0x6A}, - {BBP_R84, 0x99}, // 0x19 is for rt2860E and after. This is for extension channel overlapping IOT. 0x99 is for rt2860D and before - {BBP_R86, 0x00}, // middle range issue, Rory @2008-01-28 - {BBP_R91, 0x04}, // middle range issue, Rory @2008-01-28 - {BBP_R92, 0x00}, // middle range issue, Rory @2008-01-28 - {BBP_R103, 0x00}, // near range high-power issue, requested from Gary @2008-0528 - {BBP_R105, 0x05}, // 0x05 is for rt2860E to turn on FEQ control. It is safe for rt2860D and before, because Bit 7:2 are reserved in rt2860D and before. -}; -#define NUM_BBP_REG_PARMS (sizeof(BBPRegTable) / sizeof(REG_PAIR)) - -// -// RF register initialization set -// -#ifdef RT2870 -REG_PAIR RT30xx_RFRegTable[] = { - {RF_R04, 0x40}, - {RF_R05, 0x03}, - {RF_R06, 0x02}, - {RF_R07, 0x70}, - {RF_R09, 0x0F}, - {RF_R10, 0x41}, - {RF_R11, 0x21}, - {RF_R12, 0x7B}, - {RF_R14, 0x90}, - {RF_R15, 0x58}, - {RF_R16, 0xB3}, - {RF_R17, 0x92}, - {RF_R18, 0x2C}, - {RF_R19, 0x02}, - {RF_R20, 0xBA}, - {RF_R21, 0xDB}, - {RF_R24, 0x16}, - {RF_R25, 0x01}, - {RF_R29, 0x1F}, + +u8 BIT8[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; +char *CipherName[] = + { "none", "wep64", "wep128", "TKIP", "AES", "CKIP64", "CKIP128" }; + +/* */ +/* BBP register initialization set */ +/* */ +struct rt_reg_pair BBPRegTable[] = { + {BBP_R65, 0x2C}, /* fix rssi issue */ + {BBP_R66, 0x38}, /* Also set this default value to pAd->BbpTuning.R66CurrentValue at initial */ + {BBP_R69, 0x12}, + {BBP_R70, 0xa}, /* BBP_R70 will change to 0x8 in ApStartUp and LinkUp for rt2860C, otherwise value is 0xa */ + {BBP_R73, 0x10}, + {BBP_R81, 0x37}, + {BBP_R82, 0x62}, + {BBP_R83, 0x6A}, + {BBP_R84, 0x99}, /* 0x19 is for rt2860E and after. This is for extension channel overlapping IOT. 0x99 is for rt2860D and before */ + {BBP_R86, 0x00}, /* middle range issue, Rory @2008-01-28 */ + {BBP_R91, 0x04}, /* middle range issue, Rory @2008-01-28 */ + {BBP_R92, 0x00}, /* middle range issue, Rory @2008-01-28 */ + {BBP_R103, 0x00}, /* near range high-power issue, requested from Gary @2008-0528 */ + {BBP_R105, 0x05}, /* 0x05 is for rt2860E to turn on FEQ control. It is safe for rt2860D and before, because Bit 7:2 are reserved in rt2860D and before. */ + {BBP_R106, 0x35}, /* for ShortGI throughput */ }; -#define NUM_RF_REG_PARMS (sizeof(RT30xx_RFRegTable) / sizeof(REG_PAIR)) -#endif // RT2870 // -// -// ASIC register initialization sets -// +#define NUM_BBP_REG_PARMS (sizeof(BBPRegTable) / sizeof(struct rt_reg_pair)) -RTMP_REG_PAIR MACRegTable[] = { +/* */ +/* ASIC register initialization sets */ +/* */ + +struct rt_rtmp_reg_pair MACRegTable[] = { #if defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x200) - {BCN_OFFSET0, 0xf8f0e8e0}, /* 0x3800(e0), 0x3A00(e8), 0x3C00(f0), 0x3E00(f8), 512B for each beacon */ - {BCN_OFFSET1, 0x6f77d0c8}, /* 0x3200(c8), 0x3400(d0), 0x1DC0(77), 0x1BC0(6f), 512B for each beacon */ + {BCN_OFFSET0, 0xf8f0e8e0}, /* 0x3800(e0), 0x3A00(e8), 0x3C00(f0), 0x3E00(f8), 512B for each beacon */ + {BCN_OFFSET1, 0x6f77d0c8}, /* 0x3200(c8), 0x3400(d0), 0x1DC0(77), 0x1BC0(6f), 512B for each beacon */ #elif defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x100) - {BCN_OFFSET0, 0xece8e4e0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ - {BCN_OFFSET1, 0xfcf8f4f0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ + {BCN_OFFSET0, 0xece8e4e0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ + {BCN_OFFSET1, 0xfcf8f4f0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ #else - #error You must re-calculate new value for BCN_OFFSET0 & BCN_OFFSET1 in MACRegTable[]!!! -#endif // HW_BEACON_OFFSET // - - {LEGACY_BASIC_RATE, 0x0000013f}, // Basic rate set bitmap - {HT_BASIC_RATE, 0x00008003}, // Basic HT rate set , 20M, MCS=3, MM. Format is the same as in TXWI. - {MAC_SYS_CTRL, 0x00}, // 0x1004, , default Disable RX - {RX_FILTR_CFG, 0x17f97}, //0x1400 , RX filter control, - {BKOFF_SLOT_CFG, 0x209}, // default set short slot time, CC_DELAY_TIME should be 2 - {TX_SW_CFG0, 0x0}, // Gary,2008-05-21 for CWC test - {TX_SW_CFG1, 0x80606}, // Gary,2006-08-23 - {TX_LINK_CFG, 0x1020}, // Gary,2006-08-23 - {TX_TIMEOUT_CFG, 0x000a2090}, // CCK has some problem. So increase timieout value. 2006-10-09// MArvek RT , Modify for 2860E ,2007-08-01 - {MAX_LEN_CFG, MAX_AGGREGATION_SIZE | 0x00001000}, // 0x3018, MAX frame length. Max PSDU = 16kbytes. - {LED_CFG, 0x7f031e46}, // Gary, 2006-08-23 - {PBF_MAX_PCNT, 0x1F3FBF9F}, //0x1F3f7f9f}, //Jan, 2006/04/20 - {TX_RTY_CFG, 0x47d01f0f}, // Jan, 2006/11/16, Set TxWI->ACK =0 in Probe Rsp Modify for 2860E ,2007-08-03 - {AUTO_RSP_CFG, 0x00000013}, // Initial Auto_Responder, because QA will turn off Auto-Responder - {CCK_PROT_CFG, 0x05740003 /*0x01740003*/}, // Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. - {OFDM_PROT_CFG, 0x05740003 /*0x01740003*/}, // Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. -//PS packets use Tx1Q (for HCCA) when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) -#ifdef RT2870 - {PBF_CFG, 0xf40006}, // Only enable Queue 2 - {MM40_PROT_CFG, 0x3F44084}, // Initial Auto_Responder, because QA will turn off Auto-Responder - {WPDMA_GLO_CFG, 0x00000030}, -#endif // RT2870 // - {GF20_PROT_CFG, 0x01744004}, // set 19:18 --> Short NAV for MIMO PS - {GF40_PROT_CFG, 0x03F44084}, - {MM20_PROT_CFG, 0x01744004}, -#ifdef RT2860 - {MM40_PROT_CFG, 0x03F54084}, -#endif - {TXOP_CTRL_CFG, 0x0000583f, /*0x0000243f*/ /*0x000024bf*/}, //Extension channel backoff. - {TX_RTS_CFG, 0x00092b20}, - {EXP_ACK_TIME, 0x002400ca}, // default value - {TXOP_HLDR_ET, 0x00000002}, +#error You must re-calculate new value for BCN_OFFSET0 & BCN_OFFSET1 in MACRegTable[]! +#endif /* HW_BEACON_OFFSET // */ + + {LEGACY_BASIC_RATE, 0x0000013f}, /* Basic rate set bitmap */ + {HT_BASIC_RATE, 0x00008003}, /* Basic HT rate set , 20M, MCS=3, MM. Format is the same as in TXWI. */ + {MAC_SYS_CTRL, 0x00}, /* 0x1004, , default Disable RX */ + {RX_FILTR_CFG, 0x17f97}, /*0x1400 , RX filter control, */ + {BKOFF_SLOT_CFG, 0x209}, /* default set short slot time, CC_DELAY_TIME should be 2 */ + /*{TX_SW_CFG0, 0x40a06}, // Gary,2006-08-23 */ + {TX_SW_CFG0, 0x0}, /* Gary,2008-05-21 for CWC test */ + {TX_SW_CFG1, 0x80606}, /* Gary,2006-08-23 */ + {TX_LINK_CFG, 0x1020}, /* Gary,2006-08-23 */ + /*{TX_TIMEOUT_CFG, 0x00182090}, // CCK has some problem. So increase timieout value. 2006-10-09// MArvek RT */ + {TX_TIMEOUT_CFG, 0x000a2090}, /* CCK has some problem. So increase timieout value. 2006-10-09// MArvek RT , Modify for 2860E ,2007-08-01 */ + {MAX_LEN_CFG, MAX_AGGREGATION_SIZE | 0x00001000}, /* 0x3018, MAX frame length. Max PSDU = 16kbytes. */ + {LED_CFG, 0x7f031e46}, /* Gary, 2006-08-23 */ + + {PBF_MAX_PCNT, 0x1F3FBF9F}, /*0x1F3f7f9f}, //Jan, 2006/04/20 */ + + {TX_RTY_CFG, 0x47d01f0f}, /* Jan, 2006/11/16, Set TxWI->ACK =0 in Probe Rsp Modify for 2860E ,2007-08-03 */ + + {AUTO_RSP_CFG, 0x00000013}, /* Initial Auto_Responder, because QA will turn off Auto-Responder */ + {CCK_PROT_CFG, 0x05740003 /*0x01740003 */ }, /* Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. */ + {OFDM_PROT_CFG, 0x05740003 /*0x01740003 */ }, /* Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. */ +#ifdef RTMP_MAC_USB + {PBF_CFG, 0xf40006}, /* Only enable Queue 2 */ + {MM40_PROT_CFG, 0x3F44084}, /* Initial Auto_Responder, because QA will turn off Auto-Responder */ + {WPDMA_GLO_CFG, 0x00000030}, +#endif /* RTMP_MAC_USB // */ + {GF20_PROT_CFG, 0x01744004}, /* set 19:18 --> Short NAV for MIMO PS */ + {GF40_PROT_CFG, 0x03F44084}, + {MM20_PROT_CFG, 0x01744004}, +#ifdef RTMP_MAC_PCI + {MM40_PROT_CFG, 0x03F54084}, +#endif /* RTMP_MAC_PCI // */ + {TXOP_CTRL_CFG, 0x0000583f, /*0x0000243f *//*0x000024bf */ }, /*Extension channel backoff. */ + {TX_RTS_CFG, 0x00092b20}, + {EXP_ACK_TIME, 0x002400ca}, /* default value */ + + {TXOP_HLDR_ET, 0x00000002}, /* Jerry comments 2008/01/16: we use SIFS = 10us in CCK defaultly, but it seems that 10us - is too small for INTEL 2200bg card, so in MBSS mode, the delta time between beacon0 - and beacon1 is SIFS (10us), so if INTEL 2200bg card connects to BSS0, the ping - will always lost. So we change the SIFS of CCK from 10us to 16us. */ - {XIFS_TIME_CFG, 0x33a41010}, - {PWR_PIN_CFG, 0x00000003}, // patch for 2880-E + is too small for INTEL 2200bg card, so in MBSS mode, the delta time between beacon0 + and beacon1 is SIFS (10us), so if INTEL 2200bg card connects to BSS0, the ping + will always lost. So we change the SIFS of CCK from 10us to 16us. */ + {XIFS_TIME_CFG, 0x33a41010}, + {PWR_PIN_CFG, 0x00000003}, /* patch for 2880-E */ }; -RTMP_REG_PAIR STAMACRegTable[] = { - {WMM_AIFSN_CFG, 0x00002273}, - {WMM_CWMIN_CFG, 0x00002344}, - {WMM_CWMAX_CFG, 0x000034aa}, +struct rt_rtmp_reg_pair STAMACRegTable[] = { + {WMM_AIFSN_CFG, 0x00002273}, + {WMM_CWMIN_CFG, 0x00002344}, + {WMM_CWMAX_CFG, 0x000034aa}, }; -#define NUM_MAC_REG_PARMS (sizeof(MACRegTable) / sizeof(RTMP_REG_PAIR)) -#define NUM_STA_MAC_REG_PARMS (sizeof(STAMACRegTable) / sizeof(RTMP_REG_PAIR)) - -#ifdef RT2870 -// -// RT2870 Firmware Spec only used 1 oct for version expression -// -#define FIRMWARE_MINOR_VERSION 7 - -#endif // RT2870 // - -// New 8k byte firmware size for RT3071/RT3072 -#define FIRMWAREIMAGE_MAX_LENGTH 0x2000 -#define FIRMWAREIMAGE_LENGTH (sizeof (FirmwareImage) / sizeof(UCHAR)) -#define FIRMWARE_MAJOR_VERSION 0 - -#define FIRMWAREIMAGEV1_LENGTH 0x1000 -#define FIRMWAREIMAGEV2_LENGTH 0x1000 - -#ifdef RT2860 -#define FIRMWARE_MINOR_VERSION 2 -#endif - +#define NUM_MAC_REG_PARMS (sizeof(MACRegTable) / sizeof(struct rt_rtmp_reg_pair)) +#define NUM_STA_MAC_REG_PARMS (sizeof(STAMACRegTable) / sizeof(struct rt_rtmp_reg_pair)) /* ======================================================================== Routine Description: - Allocate RTMP_ADAPTER data block and do some initialization + Allocate struct rt_rtmp_adapter data block and do some initialization Arguments: Adapter Pointer to our adapter @@ -213,48 +152,48 @@ RTMP_REG_PAIR STAMACRegTable[] = { ======================================================================== */ -NDIS_STATUS RTMPAllocAdapterBlock( - IN PVOID handle, - OUT PRTMP_ADAPTER *ppAdapter) +int RTMPAllocAdapterBlock(void *handle, + struct rt_rtmp_adapter * * ppAdapter) { - PRTMP_ADAPTER pAd; - NDIS_STATUS Status; - INT index; - UCHAR *pBeaconBuf = NULL; + struct rt_rtmp_adapter *pAd; + int Status; + int index; + u8 *pBeaconBuf = NULL; DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocAdapterBlock\n")); *ppAdapter = NULL; - do - { - // Allocate RTMP_ADAPTER memory block + do { + /* Allocate struct rt_rtmp_adapter memory block */ pBeaconBuf = kmalloc(MAX_BEACON_SIZE, MEM_ALLOC_FLAG); - if (pBeaconBuf == NULL) - { + if (pBeaconBuf == NULL) { Status = NDIS_STATUS_FAILURE; DBGPRINT_ERR(("Failed to allocate memory - BeaconBuf!\n")); break; } + NdisZeroMemory(pBeaconBuf, MAX_BEACON_SIZE); - Status = AdapterBlockAllocateMemory(handle, (PVOID *)&pAd); - if (Status != NDIS_STATUS_SUCCESS) - { + Status = AdapterBlockAllocateMemory(handle, (void **) & pAd); + if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT_ERR(("Failed to allocate memory - ADAPTER\n")); break; } pAd->BeaconBuf = pBeaconBuf; - printk("\n\n=== pAd = %p, size = %d ===\n\n", pAd, (UINT32)sizeof(RTMP_ADAPTER)); + DBGPRINT(RT_DEBUG_OFF, + ("=== pAd = %p, size = %d ===\n", pAd, + (u32)sizeof(struct rt_rtmp_adapter))); - - // Init spin locks + /* Init spin locks */ NdisAllocateSpinLock(&pAd->MgmtRingLock); -#ifdef RT2860 +#ifdef RTMP_MAC_PCI NdisAllocateSpinLock(&pAd->RxRingLock); -#endif +#ifdef RT3090 + NdisAllocateSpinLock(&pAd->McuCmdLock); +#endif /* RT3090 // */ +#endif /* RTMP_MAC_PCI // */ - for (index =0 ; index < NUM_OF_TX_RING; index++) - { + for (index = 0; index < NUM_OF_TX_RING; index++) { NdisAllocateSpinLock(&pAd->TxSwQueueLock[index]); NdisAllocateSpinLock(&pAd->DeQueueLock[index]); pAd->DeQueueRunning[index] = FALSE; @@ -291,518 +230,199 @@ NDIS_STATUS RTMPAllocAdapterBlock( ======================================================================== */ -VOID RTMPReadTxPwrPerRate( - IN PRTMP_ADAPTER pAd) +void RTMPReadTxPwrPerRate(struct rt_rtmp_adapter *pAd) { - ULONG data, Adata, Gdata; - USHORT i, value, value2; - INT Apwrdelta, Gpwrdelta; - UCHAR t1,t2,t3,t4; - BOOLEAN bValid, bApwrdeltaMinus = TRUE, bGpwrdeltaMinus = TRUE; - - // - // Get power delta for 20MHz and 40MHz. - // + unsigned long data, Adata, Gdata; + u16 i, value, value2; + int Apwrdelta, Gpwrdelta; + u8 t1, t2, t3, t4; + BOOLEAN bApwrdeltaMinus = TRUE, bGpwrdeltaMinus = TRUE; + + /* */ + /* Get power delta for 20MHz and 40MHz. */ + /* */ DBGPRINT(RT_DEBUG_TRACE, ("Txpower per Rate\n")); RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, value2); Apwrdelta = 0; Gpwrdelta = 0; - if ((value2 & 0xff) != 0xff) - { + if ((value2 & 0xff) != 0xff) { if ((value2 & 0x80)) - Gpwrdelta = (value2&0xf); + Gpwrdelta = (value2 & 0xf); if ((value2 & 0x40)) bGpwrdeltaMinus = FALSE; else bGpwrdeltaMinus = TRUE; } - if ((value2 & 0xff00) != 0xff00) - { + if ((value2 & 0xff00) != 0xff00) { if ((value2 & 0x8000)) - Apwrdelta = ((value2&0xf00)>>8); + Apwrdelta = ((value2 & 0xf00) >> 8); if ((value2 & 0x4000)) bApwrdeltaMinus = FALSE; else bApwrdeltaMinus = TRUE; } - DBGPRINT(RT_DEBUG_TRACE, ("Gpwrdelta = %x, Apwrdelta = %x .\n", Gpwrdelta, Apwrdelta)); + DBGPRINT(RT_DEBUG_TRACE, + ("Gpwrdelta = %x, Apwrdelta = %x .\n", Gpwrdelta, Apwrdelta)); - // - // Get Txpower per MCS for 20MHz in 2.4G. - // - for (i=0; i<5; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4, value); + /* */ + /* Get Txpower per MCS for 20MHz in 2.4G. */ + /* */ + for (i = 0; i < 5; i++) { + RT28xx_EEPROM_READ16(pAd, + EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i * 4, + value); data = value; - if (bApwrdeltaMinus == FALSE) - { - t1 = (value&0xf)+(Apwrdelta); + if (bApwrdeltaMinus == FALSE) { + t1 = (value & 0xf) + (Apwrdelta); if (t1 > 0xf) t1 = 0xf; - t2 = ((value&0xf0)>>4)+(Apwrdelta); + t2 = ((value & 0xf0) >> 4) + (Apwrdelta); if (t2 > 0xf) t2 = 0xf; - t3 = ((value&0xf00)>>8)+(Apwrdelta); + t3 = ((value & 0xf00) >> 8) + (Apwrdelta); if (t3 > 0xf) t3 = 0xf; - t4 = ((value&0xf000)>>12)+(Apwrdelta); + t4 = ((value & 0xf000) >> 12) + (Apwrdelta); if (t4 > 0xf) t4 = 0xf; - } - else - { - if ((value&0xf) > Apwrdelta) - t1 = (value&0xf)-(Apwrdelta); + } else { + if ((value & 0xf) > Apwrdelta) + t1 = (value & 0xf) - (Apwrdelta); else t1 = 0; - if (((value&0xf0)>>4) > Apwrdelta) - t2 = ((value&0xf0)>>4)-(Apwrdelta); + if (((value & 0xf0) >> 4) > Apwrdelta) + t2 = ((value & 0xf0) >> 4) - (Apwrdelta); else t2 = 0; - if (((value&0xf00)>>8) > Apwrdelta) - t3 = ((value&0xf00)>>8)-(Apwrdelta); + if (((value & 0xf00) >> 8) > Apwrdelta) + t3 = ((value & 0xf00) >> 8) - (Apwrdelta); else t3 = 0; - if (((value&0xf000)>>12) > Apwrdelta) - t4 = ((value&0xf000)>>12)-(Apwrdelta); + if (((value & 0xf000) >> 12) > Apwrdelta) + t4 = ((value & 0xf000) >> 12) - (Apwrdelta); else t4 = 0; } - Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12); - if (bGpwrdeltaMinus == FALSE) - { - t1 = (value&0xf)+(Gpwrdelta); + Adata = t1 + (t2 << 4) + (t3 << 8) + (t4 << 12); + if (bGpwrdeltaMinus == FALSE) { + t1 = (value & 0xf) + (Gpwrdelta); if (t1 > 0xf) t1 = 0xf; - t2 = ((value&0xf0)>>4)+(Gpwrdelta); + t2 = ((value & 0xf0) >> 4) + (Gpwrdelta); if (t2 > 0xf) t2 = 0xf; - t3 = ((value&0xf00)>>8)+(Gpwrdelta); + t3 = ((value & 0xf00) >> 8) + (Gpwrdelta); if (t3 > 0xf) t3 = 0xf; - t4 = ((value&0xf000)>>12)+(Gpwrdelta); + t4 = ((value & 0xf000) >> 12) + (Gpwrdelta); if (t4 > 0xf) t4 = 0xf; - } - else - { - if ((value&0xf) > Gpwrdelta) - t1 = (value&0xf)-(Gpwrdelta); + } else { + if ((value & 0xf) > Gpwrdelta) + t1 = (value & 0xf) - (Gpwrdelta); else t1 = 0; - if (((value&0xf0)>>4) > Gpwrdelta) - t2 = ((value&0xf0)>>4)-(Gpwrdelta); + if (((value & 0xf0) >> 4) > Gpwrdelta) + t2 = ((value & 0xf0) >> 4) - (Gpwrdelta); else t2 = 0; - if (((value&0xf00)>>8) > Gpwrdelta) - t3 = ((value&0xf00)>>8)-(Gpwrdelta); + if (((value & 0xf00) >> 8) > Gpwrdelta) + t3 = ((value & 0xf00) >> 8) - (Gpwrdelta); else t3 = 0; - if (((value&0xf000)>>12) > Gpwrdelta) - t4 = ((value&0xf000)>>12)-(Gpwrdelta); + if (((value & 0xf000) >> 12) > Gpwrdelta) + t4 = ((value & 0xf000) >> 12) - (Gpwrdelta); else t4 = 0; } - Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + Gdata = t1 + (t2 << 4) + (t3 << 8) + (t4 << 12); - RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4 + 2, value); - if (bApwrdeltaMinus == FALSE) - { - t1 = (value&0xf)+(Apwrdelta); + RT28xx_EEPROM_READ16(pAd, + EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i * 4 + + 2, value); + if (bApwrdeltaMinus == FALSE) { + t1 = (value & 0xf) + (Apwrdelta); if (t1 > 0xf) t1 = 0xf; - t2 = ((value&0xf0)>>4)+(Apwrdelta); + t2 = ((value & 0xf0) >> 4) + (Apwrdelta); if (t2 > 0xf) t2 = 0xf; - t3 = ((value&0xf00)>>8)+(Apwrdelta); + t3 = ((value & 0xf00) >> 8) + (Apwrdelta); if (t3 > 0xf) t3 = 0xf; - t4 = ((value&0xf000)>>12)+(Apwrdelta); + t4 = ((value & 0xf000) >> 12) + (Apwrdelta); if (t4 > 0xf) t4 = 0xf; - } - else - { - if ((value&0xf) > Apwrdelta) - t1 = (value&0xf)-(Apwrdelta); + } else { + if ((value & 0xf) > Apwrdelta) + t1 = (value & 0xf) - (Apwrdelta); else t1 = 0; - if (((value&0xf0)>>4) > Apwrdelta) - t2 = ((value&0xf0)>>4)-(Apwrdelta); + if (((value & 0xf0) >> 4) > Apwrdelta) + t2 = ((value & 0xf0) >> 4) - (Apwrdelta); else t2 = 0; - if (((value&0xf00)>>8) > Apwrdelta) - t3 = ((value&0xf00)>>8)-(Apwrdelta); + if (((value & 0xf00) >> 8) > Apwrdelta) + t3 = ((value & 0xf00) >> 8) - (Apwrdelta); else t3 = 0; - if (((value&0xf000)>>12) > Apwrdelta) - t4 = ((value&0xf000)>>12)-(Apwrdelta); + if (((value & 0xf000) >> 12) > Apwrdelta) + t4 = ((value & 0xf000) >> 12) - (Apwrdelta); else t4 = 0; } - Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); - if (bGpwrdeltaMinus == FALSE) - { - t1 = (value&0xf)+(Gpwrdelta); + Adata |= ((t1 << 16) + (t2 << 20) + (t3 << 24) + (t4 << 28)); + if (bGpwrdeltaMinus == FALSE) { + t1 = (value & 0xf) + (Gpwrdelta); if (t1 > 0xf) t1 = 0xf; - t2 = ((value&0xf0)>>4)+(Gpwrdelta); + t2 = ((value & 0xf0) >> 4) + (Gpwrdelta); if (t2 > 0xf) t2 = 0xf; - t3 = ((value&0xf00)>>8)+(Gpwrdelta); + t3 = ((value & 0xf00) >> 8) + (Gpwrdelta); if (t3 > 0xf) t3 = 0xf; - t4 = ((value&0xf000)>>12)+(Gpwrdelta); + t4 = ((value & 0xf000) >> 12) + (Gpwrdelta); if (t4 > 0xf) t4 = 0xf; - } - else - { - if ((value&0xf) > Gpwrdelta) - t1 = (value&0xf)-(Gpwrdelta); + } else { + if ((value & 0xf) > Gpwrdelta) + t1 = (value & 0xf) - (Gpwrdelta); else t1 = 0; - if (((value&0xf0)>>4) > Gpwrdelta) - t2 = ((value&0xf0)>>4)-(Gpwrdelta); + if (((value & 0xf0) >> 4) > Gpwrdelta) + t2 = ((value & 0xf0) >> 4) - (Gpwrdelta); else t2 = 0; - if (((value&0xf00)>>8) > Gpwrdelta) - t3 = ((value&0xf00)>>8)-(Gpwrdelta); + if (((value & 0xf00) >> 8) > Gpwrdelta) + t3 = ((value & 0xf00) >> 8) - (Gpwrdelta); else t3 = 0; - if (((value&0xf000)>>12) > Gpwrdelta) - t4 = ((value&0xf000)>>12)-(Gpwrdelta); + if (((value & 0xf000) >> 12) > Gpwrdelta) + t4 = ((value & 0xf000) >> 12) - (Gpwrdelta); else t4 = 0; } - Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); - data |= (value<<16); + Gdata |= ((t1 << 16) + (t2 << 20) + (t3 << 24) + (t4 << 28)); + data |= (value << 16); - pAd->Tx20MPwrCfgABand[i] = pAd->Tx40MPwrCfgABand[i] = Adata; - pAd->Tx20MPwrCfgGBand[i] = pAd->Tx40MPwrCfgGBand[i] = Gdata; + /* For 20M/40M Power Delta issue */ + pAd->Tx20MPwrCfgABand[i] = data; + pAd->Tx20MPwrCfgGBand[i] = data; + pAd->Tx40MPwrCfgABand[i] = Adata; + pAd->Tx40MPwrCfgGBand[i] = Gdata; if (data != 0xffffffff) - RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, data); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band-%lx, Adata = %lx, Gdata = %lx \n", data, Adata, Gdata)); - } - - // - // Check this block is valid for 40MHz in 2.4G. If invalid, use parameter for 20MHz in 2.4G - // - bValid = TRUE; - for (i=0; i<6; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 2 + i*2, value); - if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00)) - { - bValid = FALSE; - break; - } - } - - // - // Get Txpower per MCS for 40MHz in 2.4G. - // - if (bValid) - { - for (i=0; i<4; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + i*4, value); - if (bGpwrdeltaMinus == FALSE) - { - t1 = (value&0xf)+(Gpwrdelta); - if (t1 > 0xf) - t1 = 0xf; - t2 = ((value&0xf0)>>4)+(Gpwrdelta); - if (t2 > 0xf) - t2 = 0xf; - t3 = ((value&0xf00)>>8)+(Gpwrdelta); - if (t3 > 0xf) - t3 = 0xf; - t4 = ((value&0xf000)>>12)+(Gpwrdelta); - if (t4 > 0xf) - t4 = 0xf; - } - else - { - if ((value&0xf) > Gpwrdelta) - t1 = (value&0xf)-(Gpwrdelta); - else - t1 = 0; - if (((value&0xf0)>>4) > Gpwrdelta) - t2 = ((value&0xf0)>>4)-(Gpwrdelta); - else - t2 = 0; - if (((value&0xf00)>>8) > Gpwrdelta) - t3 = ((value&0xf00)>>8)-(Gpwrdelta); - else - t3 = 0; - if (((value&0xf000)>>12) > Gpwrdelta) - t4 = ((value&0xf000)>>12)-(Gpwrdelta); - else - t4 = 0; - } - Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12); - - RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + i*4 + 2, value); - if (bGpwrdeltaMinus == FALSE) - { - t1 = (value&0xf)+(Gpwrdelta); - if (t1 > 0xf) - t1 = 0xf; - t2 = ((value&0xf0)>>4)+(Gpwrdelta); - if (t2 > 0xf) - t2 = 0xf; - t3 = ((value&0xf00)>>8)+(Gpwrdelta); - if (t3 > 0xf) - t3 = 0xf; - t4 = ((value&0xf000)>>12)+(Gpwrdelta); - if (t4 > 0xf) - t4 = 0xf; - } - else - { - if ((value&0xf) > Gpwrdelta) - t1 = (value&0xf)-(Gpwrdelta); - else - t1 = 0; - if (((value&0xf0)>>4) > Gpwrdelta) - t2 = ((value&0xf0)>>4)-(Gpwrdelta); - else - t2 = 0; - if (((value&0xf00)>>8) > Gpwrdelta) - t3 = ((value&0xf00)>>8)-(Gpwrdelta); - else - t3 = 0; - if (((value&0xf000)>>12) > Gpwrdelta) - t4 = ((value&0xf000)>>12)-(Gpwrdelta); - else - t4 = 0; - } - Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); - - if (i == 0) - pAd->Tx40MPwrCfgGBand[i+1] = (pAd->Tx40MPwrCfgGBand[i+1] & 0x0000FFFF) | (Gdata & 0xFFFF0000); - else - pAd->Tx40MPwrCfgGBand[i+1] = Gdata; - - DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 2.4G band, Gdata = %lx \n", Gdata)); - } - } - - // - // Check this block is valid for 20MHz in 5G. If invalid, use parameter for 20MHz in 2.4G - // - bValid = TRUE; - for (i=0; i<8; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 2 + i*2, value); - if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00)) - { - bValid = FALSE; - break; - } - } - - // - // Get Txpower per MCS for 20MHz in 5G. - // - if (bValid) - { - for (i=0; i<5; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + i*4, value); - if (bApwrdeltaMinus == FALSE) - { - t1 = (value&0xf)+(Apwrdelta); - if (t1 > 0xf) - t1 = 0xf; - t2 = ((value&0xf0)>>4)+(Apwrdelta); - if (t2 > 0xf) - t2 = 0xf; - t3 = ((value&0xf00)>>8)+(Apwrdelta); - if (t3 > 0xf) - t3 = 0xf; - t4 = ((value&0xf000)>>12)+(Apwrdelta); - if (t4 > 0xf) - t4 = 0xf; - } - else - { - if ((value&0xf) > Apwrdelta) - t1 = (value&0xf)-(Apwrdelta); - else - t1 = 0; - if (((value&0xf0)>>4) > Apwrdelta) - t2 = ((value&0xf0)>>4)-(Apwrdelta); - else - t2 = 0; - if (((value&0xf00)>>8) > Apwrdelta) - t3 = ((value&0xf00)>>8)-(Apwrdelta); - else - t3 = 0; - if (((value&0xf000)>>12) > Apwrdelta) - t4 = ((value&0xf000)>>12)-(Apwrdelta); - else - t4 = 0; - } - Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12); - - RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + i*4 + 2, value); - if (bApwrdeltaMinus == FALSE) - { - t1 = (value&0xf)+(Apwrdelta); - if (t1 > 0xf) - t1 = 0xf; - t2 = ((value&0xf0)>>4)+(Apwrdelta); - if (t2 > 0xf) - t2 = 0xf; - t3 = ((value&0xf00)>>8)+(Apwrdelta); - if (t3 > 0xf) - t3 = 0xf; - t4 = ((value&0xf000)>>12)+(Apwrdelta); - if (t4 > 0xf) - t4 = 0xf; - } - else - { - if ((value&0xf) > Apwrdelta) - t1 = (value&0xf)-(Apwrdelta); - else - t1 = 0; - if (((value&0xf0)>>4) > Apwrdelta) - t2 = ((value&0xf0)>>4)-(Apwrdelta); - else - t2 = 0; - if (((value&0xf00)>>8) > Apwrdelta) - t3 = ((value&0xf00)>>8)-(Apwrdelta); - else - t3 = 0; - if (((value&0xf000)>>12) > Apwrdelta) - t4 = ((value&0xf000)>>12)-(Apwrdelta); - else - t4 = 0; - } - Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); - - if (i == 0) - pAd->Tx20MPwrCfgABand[i] = (pAd->Tx20MPwrCfgABand[i] & 0x0000FFFF) | (Adata & 0xFFFF0000); - else - pAd->Tx20MPwrCfgABand[i] = Adata; - - DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 5GHz band, Adata = %lx \n", Adata)); - } - } - - // - // Check this block is valid for 40MHz in 5G. If invalid, use parameter for 20MHz in 2.4G - // - bValid = TRUE; - for (i=0; i<6; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 2 + i*2, value); - if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00)) - { - bValid = FALSE; - break; - } - } - - // - // Get Txpower per MCS for 40MHz in 5G. - // - if (bValid) - { - for (i=0; i<4; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + i*4, value); - if (bApwrdeltaMinus == FALSE) - { - t1 = (value&0xf)+(Apwrdelta); - if (t1 > 0xf) - t1 = 0xf; - t2 = ((value&0xf0)>>4)+(Apwrdelta); - if (t2 > 0xf) - t2 = 0xf; - t3 = ((value&0xf00)>>8)+(Apwrdelta); - if (t3 > 0xf) - t3 = 0xf; - t4 = ((value&0xf000)>>12)+(Apwrdelta); - if (t4 > 0xf) - t4 = 0xf; - } - else - { - if ((value&0xf) > Apwrdelta) - t1 = (value&0xf)-(Apwrdelta); - else - t1 = 0; - if (((value&0xf0)>>4) > Apwrdelta) - t2 = ((value&0xf0)>>4)-(Apwrdelta); - else - t2 = 0; - if (((value&0xf00)>>8) > Apwrdelta) - t3 = ((value&0xf00)>>8)-(Apwrdelta); - else - t3 = 0; - if (((value&0xf000)>>12) > Apwrdelta) - t4 = ((value&0xf000)>>12)-(Apwrdelta); - else - t4 = 0; - } - Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12); - - RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + i*4 + 2, value); - if (bApwrdeltaMinus == FALSE) - { - t1 = (value&0xf)+(Apwrdelta); - if (t1 > 0xf) - t1 = 0xf; - t2 = ((value&0xf0)>>4)+(Apwrdelta); - if (t2 > 0xf) - t2 = 0xf; - t3 = ((value&0xf00)>>8)+(Apwrdelta); - if (t3 > 0xf) - t3 = 0xf; - t4 = ((value&0xf000)>>12)+(Apwrdelta); - if (t4 > 0xf) - t4 = 0xf; - } - else - { - if ((value&0xf) > Apwrdelta) - t1 = (value&0xf)-(Apwrdelta); - else - t1 = 0; - if (((value&0xf0)>>4) > Apwrdelta) - t2 = ((value&0xf0)>>4)-(Apwrdelta); - else - t2 = 0; - if (((value&0xf00)>>8) > Apwrdelta) - t3 = ((value&0xf00)>>8)-(Apwrdelta); - else - t3 = 0; - if (((value&0xf000)>>12) > Apwrdelta) - t4 = ((value&0xf000)>>12)-(Apwrdelta); - else - t4 = 0; - } - Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); - - if (i == 0) - pAd->Tx40MPwrCfgABand[i+1] = (pAd->Tx40MPwrCfgABand[i+1] & 0x0000FFFF) | (Adata & 0xFFFF0000); - else - pAd->Tx40MPwrCfgABand[i+1] = Adata; - - DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 5GHz band, Adata = %lx \n", Adata)); - } + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i * 4, data); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("20MHz BW, 2.4G band-%lx, Adata = %lx, Gdata = %lx \n", + data, Adata, Gdata)); } } - /* ======================================================================== @@ -821,23 +441,23 @@ VOID RTMPReadTxPwrPerRate( ======================================================================== */ -VOID RTMPReadChannelPwr( - IN PRTMP_ADAPTER pAd) +void RTMPReadChannelPwr(struct rt_rtmp_adapter *pAd) { - UCHAR i, choffset; - EEPROM_TX_PWR_STRUC Power; - EEPROM_TX_PWR_STRUC Power2; - - // Read Tx power value for all channels - // Value from 1 - 0x7f. Default value is 24. - // Power value : 2.4G 0x00 (0) ~ 0x1F (31) - // : 5.5G 0xF9 (-7) ~ 0x0F (15) - - // 0. 11b/g, ch1 - ch 14 - for (i = 0; i < 7; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2, Power.word); - RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2, Power2.word); + u8 i, choffset; + EEPROM_TX_PWR_STRUC Power; + EEPROM_TX_PWR_STRUC Power2; + + /* Read Tx power value for all channels */ + /* Value from 1 - 0x7f. Default value is 24. */ + /* Power value : 2.4G 0x00 (0) ~ 0x1F (31) */ + /* : 5.5G 0xF9 (-7) ~ 0x0F (15) */ + + /* 0. 11b/g, ch1 - ch 14 */ + for (i = 0; i < 7; i++) { + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2, + Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2, + Power2.word); pAd->TxPower[i * 2].Channel = i * 2 + 1; pAd->TxPower[i * 2 + 1].Channel = i * 2 + 2; @@ -862,125 +482,149 @@ VOID RTMPReadChannelPwr( pAd->TxPower[i * 2 + 1].Power2 = Power2.field.Byte1; } - // 1. U-NII lower/middle band: 36, 38, 40; 44, 46, 48; 52, 54, 56; 60, 62, 64 (including central frequency in BW 40MHz) - // 1.1 Fill up channel + /* 1. U-NII lower/middle band: 36, 38, 40; 44, 46, 48; 52, 54, 56; 60, 62, 64 (including central frequency in BW 40MHz) */ + /* 1.1 Fill up channel */ choffset = 14; - for (i = 0; i < 4; i++) - { - pAd->TxPower[3 * i + choffset + 0].Channel = 36 + i * 8 + 0; - pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + for (i = 0; i < 4; i++) { + pAd->TxPower[3 * i + choffset + 0].Channel = 36 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 1].Channel = 36 + i * 8 + 2; - pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Channel = 36 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 2].Channel = 36 + i * 8 + 4; - pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Channel = 36 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; } - // 1.2 Fill up power - for (i = 0; i < 6; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + i * 2, Power.word); - RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + i * 2, Power2.word); + /* 1.2 Fill up power */ + for (i = 0; i < 6; i++) { + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + i * 2, + Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + i * 2, + Power2.word); if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) - pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + pAd->TxPower[i * 2 + choffset + 0].Power = + Power.field.Byte0; if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) - pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + pAd->TxPower[i * 2 + choffset + 1].Power = + Power.field.Byte1; if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) - pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + pAd->TxPower[i * 2 + choffset + 0].Power2 = + Power2.field.Byte0; if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) - pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + pAd->TxPower[i * 2 + choffset + 1].Power2 = + Power2.field.Byte1; } - // 2. HipperLAN 2 100, 102 ,104; 108, 110, 112; 116, 118, 120; 124, 126, 128; 132, 134, 136; 140 (including central frequency in BW 40MHz) - // 2.1 Fill up channel + /* 2. HipperLAN 2 100, 102 ,104; 108, 110, 112; 116, 118, 120; 124, 126, 128; 132, 134, 136; 140 (including central frequency in BW 40MHz) */ + /* 2.1 Fill up channel */ choffset = 14 + 12; - for (i = 0; i < 5; i++) - { - pAd->TxPower[3 * i + choffset + 0].Channel = 100 + i * 8 + 0; - pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; - - pAd->TxPower[3 * i + choffset + 1].Channel = 100 + i * 8 + 2; - pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; - - pAd->TxPower[3 * i + choffset + 2].Channel = 100 + i * 8 + 4; - pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; - } - pAd->TxPower[3 * 5 + choffset + 0].Channel = 140; - pAd->TxPower[3 * 5 + choffset + 0].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * 5 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; - - // 2.2 Fill up power - for (i = 0; i < 8; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word); - RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word); + for (i = 0; i < 5; i++) { + pAd->TxPower[3 * i + choffset + 0].Channel = 100 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 1].Channel = 100 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 2].Channel = 100 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + } + pAd->TxPower[3 * 5 + choffset + 0].Channel = 140; + pAd->TxPower[3 * 5 + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 5 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + /* 2.2 Fill up power */ + for (i = 0; i < 8; i++) { + RT28xx_EEPROM_READ16(pAd, + EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, + EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + + i * 2, Power2.word); if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) - pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + pAd->TxPower[i * 2 + choffset + 0].Power = + Power.field.Byte0; if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) - pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + pAd->TxPower[i * 2 + choffset + 1].Power = + Power.field.Byte1; if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) - pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + pAd->TxPower[i * 2 + choffset + 0].Power2 = + Power2.field.Byte0; if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) - pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + pAd->TxPower[i * 2 + choffset + 1].Power2 = + Power2.field.Byte1; } - // 3. U-NII upper band: 149, 151, 153; 157, 159, 161; 165 (including central frequency in BW 40MHz) - // 3.1 Fill up channel + /* 3. U-NII upper band: 149, 151, 153; 157, 159, 161; 165, 167, 169; 171, 173 (including central frequency in BW 40MHz) */ + /* 3.1 Fill up channel */ choffset = 14 + 12 + 16; - for (i = 0; i < 2; i++) - { - pAd->TxPower[3 * i + choffset + 0].Channel = 149 + i * 8 + 0; - pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; - - pAd->TxPower[3 * i + choffset + 1].Channel = 149 + i * 8 + 2; - pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; - - pAd->TxPower[3 * i + choffset + 2].Channel = 149 + i * 8 + 4; - pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; - } - pAd->TxPower[3 * 2 + choffset + 0].Channel = 165; - pAd->TxPower[3 * 2 + choffset + 0].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * 2 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; - - // 3.2 Fill up power - for (i = 0; i < 4; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word); - RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word); + /*for (i = 0; i < 2; i++) */ + for (i = 0; i < 3; i++) { + pAd->TxPower[3 * i + choffset + 0].Channel = 149 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 1].Channel = 149 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 2].Channel = 149 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + } + pAd->TxPower[3 * 3 + choffset + 0].Channel = 171; + pAd->TxPower[3 * 3 + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 3 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * 3 + choffset + 1].Channel = 173; + pAd->TxPower[3 * 3 + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 3 + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + /* 3.2 Fill up power */ + /*for (i = 0; i < 4; i++) */ + for (i = 0; i < 6; i++) { + RT28xx_EEPROM_READ16(pAd, + EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, + EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + + i * 2, Power2.word); if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) - pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + pAd->TxPower[i * 2 + choffset + 0].Power = + Power.field.Byte0; if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) - pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + pAd->TxPower[i * 2 + choffset + 1].Power = + Power.field.Byte1; if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) - pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + pAd->TxPower[i * 2 + choffset + 0].Power2 = + Power2.field.Byte0; if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) - pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + pAd->TxPower[i * 2 + choffset + 1].Power2 = + Power2.field.Byte1; } - // 4. Print and Debug - choffset = 14 + 12 + 16 + 7; + /* 4. Print and Debug */ + /*choffset = 14 + 12 + 16 + 7; */ + choffset = 14 + 12 + 16 + 11; + } /* @@ -1006,278 +650,14 @@ VOID RTMPReadChannelPwr( ======================================================================== */ -NDIS_STATUS NICReadRegParameters( - IN PRTMP_ADAPTER pAd, - IN NDIS_HANDLE WrapperConfigurationContext - ) +int NICReadRegParameters(struct rt_rtmp_adapter *pAd, + void *WrapperConfigurationContext) { - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + int Status = NDIS_STATUS_SUCCESS; DBGPRINT_S(Status, ("<-- NICReadRegParameters, Status=%x\n", Status)); return Status; } - -#ifdef RT2870 -/* - ======================================================================== - - Routine Description: - For RF filter calibration purpose - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - ======================================================================== -*/ -VOID RTMPFilterCalibration( - IN PRTMP_ADAPTER pAd) -{ - UCHAR R55x = 0, value, FilterTarget = 0x1E, BBPValue=0; - UINT loop = 0, count = 0, loopcnt = 0, ReTry = 0; - UCHAR RF_R24_Value = 0; - - // Give bbp filter initial value -#ifndef RT2870 - pAd->Mlme.CaliBW20RfR24 = 0x16; - pAd->Mlme.CaliBW40RfR24 = 0x36; //Bit[5] must be 1 for BW 40 -#else - pAd->Mlme.CaliBW20RfR24 = 0x1F; - pAd->Mlme.CaliBW40RfR24 = 0x2F; //Bit[5] must be 1 for BW 40 -#endif - do - { - if (loop == 1) //BandWidth = 40 MHz - { - // Write 0x27 to RF_R24 to program filter - RF_R24_Value = 0x27; - RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); - if (IS_RT3090(pAd)) - FilterTarget = 0x15; - else - FilterTarget = 0x19; - - // when calibrate BW40, BBP mask must set to BW40. - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue&= (~0x18); - BBPValue|= (0x10); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); -#ifdef RT2870 - // set to BW40 - RT30xxReadRFRegister(pAd, RF_R31, &value); - value |= 0x20; - RT30xxWriteRFRegister(pAd, RF_R31, value); -#endif - } - else //BandWidth = 20 MHz - { - // Write 0x07 to RF_R24 to program filter - RF_R24_Value = 0x07; - RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); - if (IS_RT3090(pAd)) - FilterTarget = 0x13; - else - FilterTarget = 0x16; -#ifdef RT2870 - // set to BW20 - RT30xxReadRFRegister(pAd, RF_R31, &value); - value &= (~0x20); - RT30xxWriteRFRegister(pAd, RF_R31, value); -#endif - } - - // Write 0x01 to RF_R22 to enable baseband loopback mode - RT30xxReadRFRegister(pAd, RF_R22, &value); - value |= 0x01; - RT30xxWriteRFRegister(pAd, RF_R22, value); - - // Write 0x00 to BBP_R24 to set power & frequency of passband test tone - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0); - - do - { - // Write 0x90 to BBP_R25 to transmit test tone - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R25, 0x90); - - RTMPusecDelay(1000); - // Read BBP_R55[6:0] for received power, set R55x = BBP_R55[6:0] - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R55, &value); - R55x = value & 0xFF; - - } while ((ReTry++ < 100) && (R55x == 0)); - - // Write 0x06 to BBP_R24 to set power & frequency of stopband test tone - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x06); - - while(TRUE) - { - // Write 0x90 to BBP_R25 to transmit test tone - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R25, 0x90); - - //We need to wait for calibration - RTMPusecDelay(1000); - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R55, &value); - value &= 0xFF; - if ((R55x - value) < FilterTarget) - { - RF_R24_Value ++; - } - else if ((R55x - value) == FilterTarget) - { - RF_R24_Value ++; - count ++; - } - else - { - break; - } - - // prevent infinite loop cause driver hang. - if (loopcnt++ > 100) - { - DBGPRINT(RT_DEBUG_ERROR, ("RTMPFilterCalibration - can't find a valid value, loopcnt=%d stop calibrating", loopcnt)); - break; - } - - // Write RF_R24 to program filter - RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); - } - - if (count > 0) - { - RF_R24_Value = RF_R24_Value - ((count) ? (1) : (0)); - } - - // Store for future usage - if (loopcnt < 100) - { - if (loop++ == 0) - { - //BandWidth = 20 MHz - pAd->Mlme.CaliBW20RfR24 = (UCHAR)RF_R24_Value; - } - else - { - //BandWidth = 40 MHz - pAd->Mlme.CaliBW40RfR24 = (UCHAR)RF_R24_Value; - break; - } - } - else - break; - - RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); - - // reset count - count = 0; - } while(TRUE); - - // - // Set back to initial state - // - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0); - - RT30xxReadRFRegister(pAd, RF_R22, &value); - value &= ~(0x01); - RT30xxWriteRFRegister(pAd, RF_R22, value); - - // set BBP back to BW20 - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue&= (~0x18); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPFilterCalibration - CaliBW20RfR24=0x%x, CaliBW40RfR24=0x%x\n", pAd->Mlme.CaliBW20RfR24, pAd->Mlme.CaliBW40RfR24)); -} - -VOID NICInitRT30xxRFRegisters(IN PRTMP_ADAPTER pAd) -{ - INT i; - // Driver must read EEPROM to get RfIcType before initial RF registers - // Initialize RF register to default value - if (IS_RT3070(pAd) || IS_RT3071(pAd)) - { - // Init RF calibration - // Driver should toggle RF R30 bit7 before init RF registers - UINT32 RfReg = 0; - UINT32 data; - - RT30xxReadRFRegister(pAd, RF_R30, (PUCHAR)&RfReg); - RfReg |= 0x80; - RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg); - RTMPusecDelay(1000); - RfReg &= 0x7F; - RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg); - - // Initialize RF register to default value - for (i = 0; i < NUM_RF_REG_PARMS; i++) - { - RT30xxWriteRFRegister(pAd, RT30xx_RFRegTable[i].Register, RT30xx_RFRegTable[i].Value); - } - - if (IS_RT3070(pAd)) - { - // Update MAC 0x05D4 from 01xxxxxx to 0Dxxxxxx (voltage 1.2V to 1.35V) for RT3070 to improve yield rate - RTUSBReadMACRegister(pAd, LDO_CFG0, &data); - data = ((data & 0xF0FFFFFF) | 0x0D000000); - RTUSBWriteMACRegister(pAd, LDO_CFG0, data); - } - else if (IS_RT3071(pAd)) - { - // Driver should set RF R6 bit6 on before init RF registers - RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RfReg); - RfReg |= 0x40; - RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RfReg); - - // init R31 - RT30xxWriteRFRegister(pAd, RF_R31, 0x14); - - // RT3071 version E has fixed this issue - if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211)) - { - // patch tx EVM issue temporarily - RTUSBReadMACRegister(pAd, LDO_CFG0, &data); - data = ((data & 0xE0FFFFFF) | 0x0D000000); - RTUSBWriteMACRegister(pAd, LDO_CFG0, data); - } - else - { - RTMP_IO_READ32(pAd, LDO_CFG0, &data); - data = ((data & 0xE0FFFFFF) | 0x01000000); - RTMP_IO_WRITE32(pAd, LDO_CFG0, data); - } - - // patch LNA_PE_G1 failed issue - RTUSBReadMACRegister(pAd, GPIO_SWITCH, &data); - data &= ~(0x20); - RTUSBWriteMACRegister(pAd, GPIO_SWITCH, data); - } - - //For RF filter Calibration - RTMPFilterCalibration(pAd); - - // Initialize RF R27 register, set RF R27 must be behind RTMPFilterCalibration() - if ((pAd->MACVersion & 0xffff) < 0x0211) - RT30xxWriteRFRegister(pAd, RF_R27, 0x3); - - // set led open drain enable - RTUSBReadMACRegister(pAd, OPT_14, &data); - data |= 0x01; - RTUSBWriteMACRegister(pAd, OPT_14, data); - - if (IS_RT3071(pAd)) - { - // add by johnli, RF power sequence setup, load RF normal operation-mode setup - RT30xxLoadRFNormalModeSetup(pAd); - } - } -} -#endif // RT2870 // - - /* ======================================================================== @@ -1296,88 +676,91 @@ VOID NICInitRT30xxRFRegisters(IN PRTMP_ADAPTER pAd) ======================================================================== */ -VOID NICReadEEPROMParameters( - IN PRTMP_ADAPTER pAd, - IN PUCHAR mac_addr) +void NICReadEEPROMParameters(struct rt_rtmp_adapter *pAd, u8 *mac_addr) { - UINT32 data = 0; - USHORT i, value, value2; - UCHAR TmpPhy; - EEPROM_TX_PWR_STRUC Power; - EEPROM_VERSION_STRUC Version; - EEPROM_ANTENNA_STRUC Antenna; - EEPROM_NIC_CONFIG2_STRUC NicConfig2; + u32 data = 0; + u16 i, value, value2; + u8 TmpPhy; + EEPROM_TX_PWR_STRUC Power; + EEPROM_VERSION_STRUC Version; + EEPROM_ANTENNA_STRUC Antenna; + EEPROM_NIC_CONFIG2_STRUC NicConfig2; DBGPRINT(RT_DEBUG_TRACE, ("--> NICReadEEPROMParameters\n")); - // Init EEPROM Address Number, before access EEPROM; if 93c46, EEPROMAddressNum=6, else if 93c66, EEPROMAddressNum=8 + if (pAd->chipOps.eeinit) + pAd->chipOps.eeinit(pAd); + + /* Init EEPROM Address Number, before access EEPROM; if 93c46, EEPROMAddressNum=6, else if 93c66, EEPROMAddressNum=8 */ RTMP_IO_READ32(pAd, E2PROM_CSR, &data); DBGPRINT(RT_DEBUG_TRACE, ("--> E2PROM_CSR = 0x%x\n", data)); - if((data & 0x30) == 0) - pAd->EEPROMAddressNum = 6; // 93C46 - else if((data & 0x30) == 0x10) - pAd->EEPROMAddressNum = 8; // 93C66 + if ((data & 0x30) == 0) + pAd->EEPROMAddressNum = 6; /* 93C46 */ + else if ((data & 0x30) == 0x10) + pAd->EEPROMAddressNum = 8; /* 93C66 */ else - pAd->EEPROMAddressNum = 8; // 93C86 - DBGPRINT(RT_DEBUG_TRACE, ("--> EEPROMAddressNum = %d\n", pAd->EEPROMAddressNum )); + pAd->EEPROMAddressNum = 8; /* 93C86 */ + DBGPRINT(RT_DEBUG_TRACE, + ("--> EEPROMAddressNum = %d\n", pAd->EEPROMAddressNum)); - // RT2860 MAC no longer auto load MAC address from E2PROM. Driver has to intialize - // MAC address registers according to E2PROM setting + /* RT2860 MAC no longer auto load MAC address from E2PROM. Driver has to intialize */ + /* MAC address registers according to E2PROM setting */ if (mac_addr == NULL || - strlen(mac_addr) != 17 || - mac_addr[2] != ':' || mac_addr[5] != ':' || mac_addr[8] != ':' || - mac_addr[11] != ':' || mac_addr[14] != ':') - { - USHORT Addr01,Addr23,Addr45 ; + strlen((char *)mac_addr) != 17 || + mac_addr[2] != ':' || mac_addr[5] != ':' || mac_addr[8] != ':' || + mac_addr[11] != ':' || mac_addr[14] != ':') { + u16 Addr01, Addr23, Addr45; RT28xx_EEPROM_READ16(pAd, 0x04, Addr01); RT28xx_EEPROM_READ16(pAd, 0x06, Addr23); RT28xx_EEPROM_READ16(pAd, 0x08, Addr45); - pAd->PermanentAddress[0] = (UCHAR)(Addr01 & 0xff); - pAd->PermanentAddress[1] = (UCHAR)(Addr01 >> 8); - pAd->PermanentAddress[2] = (UCHAR)(Addr23 & 0xff); - pAd->PermanentAddress[3] = (UCHAR)(Addr23 >> 8); - pAd->PermanentAddress[4] = (UCHAR)(Addr45 & 0xff); - pAd->PermanentAddress[5] = (UCHAR)(Addr45 >> 8); + pAd->PermanentAddress[0] = (u8)(Addr01 & 0xff); + pAd->PermanentAddress[1] = (u8)(Addr01 >> 8); + pAd->PermanentAddress[2] = (u8)(Addr23 & 0xff); + pAd->PermanentAddress[3] = (u8)(Addr23 >> 8); + pAd->PermanentAddress[4] = (u8)(Addr45 & 0xff); + pAd->PermanentAddress[5] = (u8)(Addr45 >> 8); - DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from E2PROM \n")); - } - else - { - INT j; - PUCHAR macptr; + DBGPRINT(RT_DEBUG_TRACE, + ("Initialize MAC Address from E2PROM \n")); + } else { + int j; + char *macptr; - macptr = mac_addr; + macptr = (char *)mac_addr; - for (j=0; jPermanentAddress[j], 1); - macptr=macptr+3; + macptr = macptr + 3; } - DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from module parameter \n")); + DBGPRINT(RT_DEBUG_TRACE, + ("Initialize MAC Address from module parameter \n")); } - { - //more conveninet to test mbssid, so ap's bssid &0xf1 + /*more conveninet to test mbssid, so ap's bssid &0xf1 */ if (pAd->PermanentAddress[0] == 0xff) - pAd->PermanentAddress[0] = RandomByte(pAd)&0xf8; - - //if (pAd->PermanentAddress[5] == 0xff) - // pAd->PermanentAddress[5] = RandomByte(pAd)&0xf8; - - DBGPRINT_RAW(RT_DEBUG_TRACE,("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n", - pAd->PermanentAddress[0], pAd->PermanentAddress[1], - pAd->PermanentAddress[2], pAd->PermanentAddress[3], - pAd->PermanentAddress[4], pAd->PermanentAddress[5])); - if (pAd->bLocalAdminMAC == FALSE) - { + pAd->PermanentAddress[0] = RandomByte(pAd) & 0xf8; + + /*if (pAd->PermanentAddress[5] == 0xff) */ + /* pAd->PermanentAddress[5] = RandomByte(pAd)&0xf8; */ + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->PermanentAddress[0], + pAd->PermanentAddress[1], + pAd->PermanentAddress[2], + pAd->PermanentAddress[3], + pAd->PermanentAddress[4], + pAd->PermanentAddress[5])); + if (pAd->bLocalAdminMAC == FALSE) { MAC_DW0_STRUC csr2; MAC_DW1_STRUC csr3; - COPY_MAC_ADDR(pAd->CurrentAddress, pAd->PermanentAddress); + COPY_MAC_ADDR(pAd->CurrentAddress, + pAd->PermanentAddress); csr2.field.Byte0 = pAd->CurrentAddress[0]; csr2.field.Byte1 = pAd->CurrentAddress[1]; csr2.field.Byte2 = pAd->CurrentAddress[2]; @@ -1388,118 +771,116 @@ VOID NICReadEEPROMParameters( csr3.field.Byte5 = pAd->CurrentAddress[5]; csr3.field.U2MeMask = 0xff; RTMP_IO_WRITE32(pAd, MAC_ADDR_DW1, csr3.word); - DBGPRINT_RAW(RT_DEBUG_TRACE,("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n", - pAd->PermanentAddress[0], pAd->PermanentAddress[1], - pAd->PermanentAddress[2], pAd->PermanentAddress[3], - pAd->PermanentAddress[4], pAd->PermanentAddress[5])); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pAd->PermanentAddress))); } } - // if not return early. cause fail at emulation. - // Init the channel number for TX channel power + /* if not return early. cause fail at emulation. */ + /* Init the channel number for TX channel power */ RTMPReadChannelPwr(pAd); - // if E2PROM version mismatch with driver's expectation, then skip - // all subsequent E2RPOM retieval and set a system error bit to notify GUI + /* if E2PROM version mismatch with driver's expectation, then skip */ + /* all subsequent E2RPOM retieval and set a system error bit to notify GUI */ RT28xx_EEPROM_READ16(pAd, EEPROM_VERSION_OFFSET, Version.word); - pAd->EepromVersion = Version.field.Version + Version.field.FaeReleaseNumber * 256; - DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: Version = %d, FAE release #%d\n", Version.field.Version, Version.field.FaeReleaseNumber)); - - if (Version.field.Version > VALID_EEPROM_VERSION) - { - DBGPRINT_ERR(("E2PROM: WRONG VERSION 0x%x, should be %d\n",Version.field.Version, VALID_EEPROM_VERSION)); + pAd->EepromVersion = + Version.field.Version + Version.field.FaeReleaseNumber * 256; + DBGPRINT(RT_DEBUG_TRACE, + ("E2PROM: Version = %d, FAE release #%d\n", + Version.field.Version, Version.field.FaeReleaseNumber)); + + if (Version.field.Version > VALID_EEPROM_VERSION) { + DBGPRINT_ERR(("E2PROM: WRONG VERSION 0x%x, should be %d\n", + Version.field.Version, VALID_EEPROM_VERSION)); /*pAd->SystemErrorBitmap |= 0x00000001; - // hard-code default value when no proper E2PROM installed - pAd->bAutoTxAgcA = FALSE; - pAd->bAutoTxAgcG = FALSE; + // hard-code default value when no proper E2PROM installed + pAd->bAutoTxAgcA = FALSE; + pAd->bAutoTxAgcG = FALSE; - // Default the channel power - for (i = 0; i < MAX_NUM_OF_CHANNELS; i++) - pAd->TxPower[i].Power = DEFAULT_RF_TX_POWER; + // Default the channel power + for (i = 0; i < MAX_NUM_OF_CHANNELS; i++) + pAd->TxPower[i].Power = DEFAULT_RF_TX_POWER; - // Default the channel power - for (i = 0; i < MAX_NUM_OF_11JCHANNELS; i++) - pAd->TxPower11J[i].Power = DEFAULT_RF_TX_POWER; + // Default the channel power + for (i = 0; i < MAX_NUM_OF_11JCHANNELS; i++) + pAd->TxPower11J[i].Power = DEFAULT_RF_TX_POWER; - for(i = 0; i < NUM_EEPROM_BBP_PARMS; i++) - pAd->EEPROMDefaultValue[i] = 0xffff; - return; */ + for(i = 0; i < NUM_EEPROM_BBP_PARMS; i++) + pAd->EEPROMDefaultValue[i] = 0xffff; + return; */ } - - // Read BBP default value from EEPROM and store to array(EEPROMDefaultValue) in pAd + /* Read BBP default value from EEPROM and store to array(EEPROMDefaultValue) in pAd */ RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, value); pAd->EEPROMDefaultValue[0] = value; RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value); pAd->EEPROMDefaultValue[1] = value; - RT28xx_EEPROM_READ16(pAd, 0x38, value); // Country Region + RT28xx_EEPROM_READ16(pAd, 0x38, value); /* Country Region */ pAd->EEPROMDefaultValue[2] = value; - for(i = 0; i < 8; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_BBP_BASE_OFFSET + i*2, value); - pAd->EEPROMDefaultValue[i+3] = value; + for (i = 0; i < 8; i++) { + RT28xx_EEPROM_READ16(pAd, EEPROM_BBP_BASE_OFFSET + i * 2, + value); + pAd->EEPROMDefaultValue[i + 3] = value; } - // We have to parse NIC configuration 0 at here. - // If TSSI did not have preloaded value, it should reset the TxAutoAgc to false - // Therefore, we have to read TxAutoAgc control beforehand. - // Read Tx AGC control bit + /* We have to parse NIC configuration 0 at here. */ + /* If TSSI did not have preloaded value, it should reset the TxAutoAgc to false */ + /* Therefore, we have to read TxAutoAgc control beforehand. */ + /* Read Tx AGC control bit */ Antenna.word = pAd->EEPROMDefaultValue[0]; - if (Antenna.word == 0xFFFF) - { - if(IS_RT3090(pAd)) - { + if (Antenna.word == 0xFFFF) { +#ifdef RT30xx + if (IS_RT3090(pAd) || IS_RT3390(pAd)) { Antenna.word = 0; Antenna.field.RfIcType = RFIC_3020; Antenna.field.TxPath = 1; Antenna.field.RxPath = 1; - } - else + } else +#endif /* RT30xx // */ { - Antenna.word = 0; - Antenna.field.RfIcType = RFIC_2820; - Antenna.field.TxPath = 1; - Antenna.field.RxPath = 2; - DBGPRINT(RT_DEBUG_WARN, ("E2PROM error, hard code as 0x%04x\n", Antenna.word)); + + Antenna.word = 0; + Antenna.field.RfIcType = RFIC_2820; + Antenna.field.TxPath = 1; + Antenna.field.RxPath = 2; + DBGPRINT(RT_DEBUG_WARN, + ("E2PROM error, hard code as 0x%04x\n", + Antenna.word)); } } - - // Choose the desired Tx&Rx stream. - if ((pAd->CommonCfg.TxStream == 0) || (pAd->CommonCfg.TxStream > Antenna.field.TxPath)) + /* Choose the desired Tx&Rx stream. */ + if ((pAd->CommonCfg.TxStream == 0) + || (pAd->CommonCfg.TxStream > Antenna.field.TxPath)) pAd->CommonCfg.TxStream = Antenna.field.TxPath; - if ((pAd->CommonCfg.RxStream == 0) || (pAd->CommonCfg.RxStream > Antenna.field.RxPath)) - { + if ((pAd->CommonCfg.RxStream == 0) + || (pAd->CommonCfg.RxStream > Antenna.field.RxPath)) { pAd->CommonCfg.RxStream = Antenna.field.RxPath; if ((pAd->MACVersion < RALINK_2883_VERSION) && - (pAd->CommonCfg.RxStream > 2)) - { - // only 2 Rx streams for RT2860 series + (pAd->CommonCfg.RxStream > 2)) { + /* only 2 Rx streams for RT2860 series */ pAd->CommonCfg.RxStream = 2; } } - - // 3*3 - // read value from EEPROM and set them to CSR174 ~ 177 in chain0 ~ chain2 - // yet implement - for(i=0; i<3; i++) - { + /* 3*3 */ + /* read value from EEPROM and set them to CSR174 ~ 177 in chain0 ~ chain2 */ + /* yet implement */ + for (i = 0; i < 3; i++) { } NicConfig2.word = pAd->EEPROMDefaultValue[1]; { - if ((NicConfig2.word & 0x00ff) == 0xff) - { + if ((NicConfig2.word & 0x00ff) == 0xff) { NicConfig2.word &= 0xff00; } - if ((NicConfig2.word >> 8) == 0xff) - { + if ((NicConfig2.word >> 8) == 0xff) { NicConfig2.word &= 0x00ff; } } @@ -1509,29 +890,43 @@ VOID NICReadEEPROMParameters( else pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE; - DBGPRINT_RAW(RT_DEBUG_TRACE, ("NICReadEEPROMParameters: RxPath = %d, TxPath = %d\n", Antenna.field.RxPath, Antenna.field.TxPath)); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("NICReadEEPROMParameters: RxPath = %d, TxPath = %d\n", + Antenna.field.RxPath, Antenna.field.TxPath)); - // Save the antenna for future use + /* Save the antenna for future use */ pAd->Antenna.word = Antenna.word; - // - // Reset PhyMode if we don't support 802.11a - // Only RFIC_2850 & RFIC_2750 support 802.11a - // - if ((Antenna.field.RfIcType != RFIC_2850) && (Antenna.field.RfIcType != RFIC_2750)) - { + /* Set the RfICType here, then we can initialize RFIC related operation callbacks */ + pAd->Mlme.RealRxPath = (u8)Antenna.field.RxPath; + pAd->RfIcType = (u8)Antenna.field.RfIcType; + +#ifdef RTMP_RF_RW_SUPPORT + RtmpChipOpsRFHook(pAd); +#endif /* RTMP_RF_RW_SUPPORT // */ + +#ifdef RTMP_MAC_PCI + sprintf((char *)pAd->nickname, "RT2860STA"); +#endif /* RTMP_MAC_PCI // */ + + /* */ + /* Reset PhyMode if we don't support 802.11a */ + /* Only RFIC_2850 & RFIC_2750 support 802.11a */ + /* */ + if ((Antenna.field.RfIcType != RFIC_2850) + && (Antenna.field.RfIcType != RFIC_2750) + && (Antenna.field.RfIcType != RFIC_3052)) { if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) || - (pAd->CommonCfg.PhyMode == PHY_11A)) + (pAd->CommonCfg.PhyMode == PHY_11A)) pAd->CommonCfg.PhyMode = PHY_11BG_MIXED; - else if ((pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || - (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) || - (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || - (pAd->CommonCfg.PhyMode == PHY_11N_5G)) + else if ((pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11N_5G)) pAd->CommonCfg.PhyMode = PHY_11BGN_MIXED; } - - // Read TSSI reference and TSSI boundary for temperature compensation. This is ugly - // 0. 11b/g + /* Read TSSI reference and TSSI boundary for temperature compensation. This is ugly */ + /* 0. 11b/g */ { /* these are tempature reference value (0x00 ~ 0xFE) ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 @@ -1544,7 +939,7 @@ VOID NICReadEEPROMParameters( pAd->TssiMinusBoundaryG[2] = Power.field.Byte0; pAd->TssiMinusBoundaryG[1] = Power.field.Byte1; RT28xx_EEPROM_READ16(pAd, 0x72, Power.word); - pAd->TssiRefG = Power.field.Byte0; /* reference value [0] */ + pAd->TssiRefG = Power.field.Byte0; /* reference value [0] */ pAd->TssiPlusBoundaryG[1] = Power.field.Byte1; RT28xx_EEPROM_READ16(pAd, 0x74, Power.word); pAd->TssiPlusBoundaryG[2] = Power.field.Byte0; @@ -1554,19 +949,23 @@ VOID NICReadEEPROMParameters( pAd->TxAgcStepG = Power.field.Byte1; pAd->TxAgcCompensateG = 0; pAd->TssiMinusBoundaryG[0] = pAd->TssiRefG; - pAd->TssiPlusBoundaryG[0] = pAd->TssiRefG; + pAd->TssiPlusBoundaryG[0] = pAd->TssiRefG; - // Disable TxAgc if the based value is not right + /* Disable TxAgc if the based value is not right */ if (pAd->TssiRefG == 0xff) pAd->bAutoTxAgcG = FALSE; - DBGPRINT(RT_DEBUG_TRACE,("E2PROM: G Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", - pAd->TssiMinusBoundaryG[4], pAd->TssiMinusBoundaryG[3], pAd->TssiMinusBoundaryG[2], pAd->TssiMinusBoundaryG[1], - pAd->TssiRefG, - pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4], - pAd->TxAgcStepG, pAd->bAutoTxAgcG)); + DBGPRINT(RT_DEBUG_TRACE, + ("E2PROM: G Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", + pAd->TssiMinusBoundaryG[4], + pAd->TssiMinusBoundaryG[3], + pAd->TssiMinusBoundaryG[2], + pAd->TssiMinusBoundaryG[1], pAd->TssiRefG, + pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], + pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4], + pAd->TxAgcStepG, pAd->bAutoTxAgcG)); } - // 1. 11a + /* 1. 11a */ { RT28xx_EEPROM_READ16(pAd, 0xD4, Power.word); pAd->TssiMinusBoundaryA[4] = Power.field.Byte0; @@ -1575,7 +974,7 @@ VOID NICReadEEPROMParameters( pAd->TssiMinusBoundaryA[2] = Power.field.Byte0; pAd->TssiMinusBoundaryA[1] = Power.field.Byte1; RT28xx_EEPROM_READ16(pAd, 0xD8, Power.word); - pAd->TssiRefA = Power.field.Byte0; + pAd->TssiRefA = Power.field.Byte0; pAd->TssiPlusBoundaryA[1] = Power.field.Byte1; RT28xx_EEPROM_READ16(pAd, 0xDA, Power.word); pAd->TssiPlusBoundaryA[2] = Power.field.Byte0; @@ -1585,97 +984,119 @@ VOID NICReadEEPROMParameters( pAd->TxAgcStepA = Power.field.Byte1; pAd->TxAgcCompensateA = 0; pAd->TssiMinusBoundaryA[0] = pAd->TssiRefA; - pAd->TssiPlusBoundaryA[0] = pAd->TssiRefA; + pAd->TssiPlusBoundaryA[0] = pAd->TssiRefA; - // Disable TxAgc if the based value is not right + /* Disable TxAgc if the based value is not right */ if (pAd->TssiRefA == 0xff) pAd->bAutoTxAgcA = FALSE; - DBGPRINT(RT_DEBUG_TRACE,("E2PROM: A Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", - pAd->TssiMinusBoundaryA[4], pAd->TssiMinusBoundaryA[3], pAd->TssiMinusBoundaryA[2], pAd->TssiMinusBoundaryA[1], - pAd->TssiRefA, - pAd->TssiPlusBoundaryA[1], pAd->TssiPlusBoundaryA[2], pAd->TssiPlusBoundaryA[3], pAd->TssiPlusBoundaryA[4], - pAd->TxAgcStepA, pAd->bAutoTxAgcA)); + DBGPRINT(RT_DEBUG_TRACE, + ("E2PROM: A Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", + pAd->TssiMinusBoundaryA[4], + pAd->TssiMinusBoundaryA[3], + pAd->TssiMinusBoundaryA[2], + pAd->TssiMinusBoundaryA[1], pAd->TssiRefA, + pAd->TssiPlusBoundaryA[1], pAd->TssiPlusBoundaryA[2], + pAd->TssiPlusBoundaryA[3], pAd->TssiPlusBoundaryA[4], + pAd->TxAgcStepA, pAd->bAutoTxAgcA)); } pAd->BbpRssiToDbmDelta = 0x0; - // Read frequency offset setting for RF + /* Read frequency offset setting for RF */ RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, value); if ((value & 0x00FF) != 0x00FF) - pAd->RfFreqOffset = (ULONG) (value & 0x00FF); + pAd->RfFreqOffset = (unsigned long)(value & 0x00FF); else pAd->RfFreqOffset = 0; - DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: RF FreqOffset=0x%lx \n", pAd->RfFreqOffset)); + DBGPRINT(RT_DEBUG_TRACE, + ("E2PROM: RF FreqOffset=0x%lx \n", pAd->RfFreqOffset)); - //CountryRegion byte offset (38h) - value = pAd->EEPROMDefaultValue[2] >> 8; // 2.4G band - value2 = pAd->EEPROMDefaultValue[2] & 0x00FF; // 5G band + /*CountryRegion byte offset (38h) */ + value = pAd->EEPROMDefaultValue[2] >> 8; /* 2.4G band */ + value2 = pAd->EEPROMDefaultValue[2] & 0x00FF; /* 5G band */ - if ((value <= REGION_MAXIMUM_BG_BAND) && (value2 <= REGION_MAXIMUM_A_BAND)) - { - pAd->CommonCfg.CountryRegion = ((UCHAR) value) | 0x80; - pAd->CommonCfg.CountryRegionForABand = ((UCHAR) value2) | 0x80; + if ((value <= REGION_MAXIMUM_BG_BAND) + && (value2 <= REGION_MAXIMUM_A_BAND)) { + pAd->CommonCfg.CountryRegion = ((u8)value) | 0x80; + pAd->CommonCfg.CountryRegionForABand = ((u8)value2) | 0x80; TmpPhy = pAd->CommonCfg.PhyMode; pAd->CommonCfg.PhyMode = 0xff; RTMPSetPhyMode(pAd, TmpPhy); SetCommonHT(pAd); } - - // - // Get RSSI Offset on EEPROM 0x9Ah & 0x9Ch. - // The valid value are (-10 ~ 10) - // + /* */ + /* Get RSSI Offset on EEPROM 0x9Ah & 0x9Ch. */ + /* The valid value are (-10 ~ 10) */ + /* */ RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, value); pAd->BGRssiOffset0 = value & 0x00ff; pAd->BGRssiOffset1 = (value >> 8); - RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET+2, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET + 2, value); pAd->BGRssiOffset2 = value & 0x00ff; pAd->ALNAGain1 = (value >> 8); RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, value); pAd->BLNAGain = value & 0x00ff; pAd->ALNAGain0 = (value >> 8); - // Validate 11b/g RSSI_0 offset. + /* Validate 11b/g RSSI_0 offset. */ if ((pAd->BGRssiOffset0 < -10) || (pAd->BGRssiOffset0 > 10)) pAd->BGRssiOffset0 = 0; - // Validate 11b/g RSSI_1 offset. + /* Validate 11b/g RSSI_1 offset. */ if ((pAd->BGRssiOffset1 < -10) || (pAd->BGRssiOffset1 > 10)) pAd->BGRssiOffset1 = 0; - // Validate 11b/g RSSI_2 offset. + /* Validate 11b/g RSSI_2 offset. */ if ((pAd->BGRssiOffset2 < -10) || (pAd->BGRssiOffset2 > 10)) pAd->BGRssiOffset2 = 0; RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, value); pAd->ARssiOffset0 = value & 0x00ff; pAd->ARssiOffset1 = (value >> 8); - RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET+2), value); + RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET + 2), value); pAd->ARssiOffset2 = value & 0x00ff; pAd->ALNAGain2 = (value >> 8); - if (((UCHAR)pAd->ALNAGain1 == 0xFF) || (pAd->ALNAGain1 == 0x00)) + if (((u8)pAd->ALNAGain1 == 0xFF) || (pAd->ALNAGain1 == 0x00)) pAd->ALNAGain1 = pAd->ALNAGain0; - if (((UCHAR)pAd->ALNAGain2 == 0xFF) || (pAd->ALNAGain2 == 0x00)) + if (((u8)pAd->ALNAGain2 == 0xFF) || (pAd->ALNAGain2 == 0x00)) pAd->ALNAGain2 = pAd->ALNAGain0; - // Validate 11a RSSI_0 offset. + /* Validate 11a RSSI_0 offset. */ if ((pAd->ARssiOffset0 < -10) || (pAd->ARssiOffset0 > 10)) pAd->ARssiOffset0 = 0; - // Validate 11a RSSI_1 offset. + /* Validate 11a RSSI_1 offset. */ if ((pAd->ARssiOffset1 < -10) || (pAd->ARssiOffset1 > 10)) pAd->ARssiOffset1 = 0; - //Validate 11a RSSI_2 offset. + /*Validate 11a RSSI_2 offset. */ if ((pAd->ARssiOffset2 < -10) || (pAd->ARssiOffset2 > 10)) pAd->ARssiOffset2 = 0; - // - // Get LED Setting. - // +#ifdef RT30xx + /* */ + /* Get TX mixer gain setting */ + /* 0xff are invalid value */ + /* Note: RT30xX default value is 0x00 and will program to RF_R17 only when this value is not zero. */ + /* RT359X default value is 0x02 */ + /* */ + if (IS_RT30xx(pAd) || IS_RT3572(pAd)) { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXMIXER_GAIN_2_4G, value); + pAd->TxMixerGain24G = 0; + value &= 0x00ff; + if (value != 0xff) { + value &= 0x07; + pAd->TxMixerGain24G = (u8)value; + } + } +#endif /* RT30xx // */ + + /* */ + /* Get LED Setting. */ + /* */ RT28xx_EEPROM_READ16(pAd, 0x3a, value); - pAd->LedCntl.word = (value&0xff00) >> 8; + pAd->LedCntl.word = (value >> 8); RT28xx_EEPROM_READ16(pAd, EEPROM_LED1_OFFSET, value); pAd->Led1 = value; RT28xx_EEPROM_READ16(pAd, EEPROM_LED2_OFFSET, value); @@ -1685,6 +1106,12 @@ VOID NICReadEEPROMParameters( RTMPReadTxPwrPerRate(pAd); +#ifdef RT30xx +#ifdef RTMP_EFUSE_SUPPORT + RtmpEfuseSupportCheck(pAd); +#endif /* RTMP_EFUSE_SUPPORT // */ +#endif /* RT30xx // */ + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICReadEEPROMParameters\n")); } @@ -1706,170 +1133,218 @@ VOID NICReadEEPROMParameters( ======================================================================== */ -VOID NICInitAsicFromEEPROM( - IN PRTMP_ADAPTER pAd) +void NICInitAsicFromEEPROM(struct rt_rtmp_adapter *pAd) { - UINT32 data = 0; - UCHAR BBPR1 = 0; - USHORT i; - EEPROM_ANTENNA_STRUC Antenna; - EEPROM_NIC_CONFIG2_STRUC NicConfig2; - UCHAR BBPR3 = 0; + u32 data = 0; + u8 BBPR1 = 0; + u16 i; +/* EEPROM_ANTENNA_STRUC Antenna; */ + EEPROM_NIC_CONFIG2_STRUC NicConfig2; + u8 BBPR3 = 0; DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitAsicFromEEPROM\n")); - for(i = 3; i < NUM_EEPROM_BBP_PARMS; i++) - { - UCHAR BbpRegIdx, BbpValue; + for (i = 3; i < NUM_EEPROM_BBP_PARMS; i++) { + u8 BbpRegIdx, BbpValue; - if ((pAd->EEPROMDefaultValue[i] != 0xFFFF) && (pAd->EEPROMDefaultValue[i] != 0)) - { - BbpRegIdx = (UCHAR)(pAd->EEPROMDefaultValue[i] >> 8); - BbpValue = (UCHAR)(pAd->EEPROMDefaultValue[i] & 0xff); + if ((pAd->EEPROMDefaultValue[i] != 0xFFFF) + && (pAd->EEPROMDefaultValue[i] != 0)) { + BbpRegIdx = (u8)(pAd->EEPROMDefaultValue[i] >> 8); + BbpValue = (u8)(pAd->EEPROMDefaultValue[i] & 0xff); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BbpRegIdx, BbpValue); } } -#ifndef RT2870 - Antenna.word = pAd->Antenna.word; -#else - Antenna.word = pAd->EEPROMDefaultValue[0]; - if (Antenna.word == 0xFFFF) - { - DBGPRINT(RT_DEBUG_ERROR, ("E2PROM error, hard code as 0x%04x\n", Antenna.word)); - BUG_ON(Antenna.word == 0xFFFF); - } -#endif - pAd->Mlme.RealRxPath = (UCHAR) Antenna.field.RxPath; - pAd->RfIcType = (UCHAR) Antenna.field.RfIcType; - -#ifdef RT2870 - DBGPRINT(RT_DEBUG_WARN, ("pAd->RfIcType = %d, RealRxPath=%d, TxPath = %d\n", pAd->RfIcType, pAd->Mlme.RealRxPath,Antenna.field.TxPath)); - - // Save the antenna for future use - pAd->Antenna.word = Antenna.word; -#endif NicConfig2.word = pAd->EEPROMDefaultValue[1]; -#ifdef RT2870 { - if ((NicConfig2.word & 0x00ff) == 0xff) - { + if ((NicConfig2.word & 0x00ff) == 0xff) { NicConfig2.word &= 0xff00; } - if ((NicConfig2.word >> 8) == 0xff) - { + if ((NicConfig2.word >> 8) == 0xff) { NicConfig2.word &= 0x00ff; } } -#endif - // Save the antenna for future use + + /* Save the antenna for future use */ pAd->NicConfig2.word = NicConfig2.word; -#ifdef RT2870 - // set default antenna as main +#ifdef RT30xx + /* set default antenna as main */ if (pAd->RfIcType == RFIC_3020) AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); -#endif - // - // Send LED Setting to MCU. - // - if (pAd->LedCntl.word == 0xFF) - { +#endif /* RT30xx // */ + + /* */ + /* Send LED Setting to MCU. */ + /* */ + if (pAd->LedCntl.word == 0xFF) { pAd->LedCntl.word = 0x01; pAd->Led1 = 0x5555; pAd->Led2 = 0x2221; -#ifdef RT2860 - pAd->Led3 = 0xA9F8; -#endif -#ifdef RT2870 +#ifdef RTMP_MAC_PCI + pAd->Led3 = 0xA9F8; +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB pAd->Led3 = 0x5627; -#endif // RT2870 // +#endif /* RTMP_MAC_USB // */ } - AsicSendCommandToMcu(pAd, 0x52, 0xff, (UCHAR)pAd->Led1, (UCHAR)(pAd->Led1 >> 8)); - AsicSendCommandToMcu(pAd, 0x53, 0xff, (UCHAR)pAd->Led2, (UCHAR)(pAd->Led2 >> 8)); - AsicSendCommandToMcu(pAd, 0x54, 0xff, (UCHAR)pAd->Led3, (UCHAR)(pAd->Led3 >> 8)); - pAd->LedIndicatorStregth = 0xFF; - RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, before link up + AsicSendCommandToMcu(pAd, 0x52, 0xff, (u8)pAd->Led1, + (u8)(pAd->Led1 >> 8)); + AsicSendCommandToMcu(pAd, 0x53, 0xff, (u8)pAd->Led2, + (u8)(pAd->Led2 >> 8)); + AsicSendCommandToMcu(pAd, 0x54, 0xff, (u8)pAd->Led3, + (u8)(pAd->Led3 >> 8)); + AsicSendCommandToMcu(pAd, 0x51, 0xff, 0, pAd->LedCntl.field.Polarity); + + pAd->LedIndicatorStrength = 0xFF; + RTMPSetSignalLED(pAd, -100); /* Force signal strength Led to be turned off, before link up */ { - // Read Hardware controlled Radio state enable bit - if (NicConfig2.field.HardwareRadioControl == 1) - { + /* Read Hardware controlled Radio state enable bit */ + if (NicConfig2.field.HardwareRadioControl == 1) { pAd->StaCfg.bHardwareRadio = TRUE; - // Read GPIO pin2 as Hardware controlled radio state + /* Read GPIO pin2 as Hardware controlled radio state */ RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data); - if ((data & 0x04) == 0) - { + if ((data & 0x04) == 0) { pAd->StaCfg.bHwRadio = FALSE; pAd->StaCfg.bRadio = FALSE; +/* RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818); */ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); } - } - else + } else pAd->StaCfg.bHardwareRadio = FALSE; - if (pAd->StaCfg.bRadio == FALSE) - { + if (pAd->StaCfg.bRadio == FALSE) { RTMPSetLED(pAd, LED_RADIO_OFF); - } - else - { + } else { RTMPSetLED(pAd, LED_RADIO_ON); -#ifdef RT2860 +#ifdef RTMP_MAC_PCI +#ifdef RT3090 + AsicSendCommandToMcu(pAd, 0x30, PowerRadioOffCID, 0xff, + 0x02); + AsicCheckCommanOk(pAd, PowerRadioOffCID); +#endif /* RT3090 // */ +#ifndef RT3090 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); - AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x00); - // 2-1. wait command ok. +#endif /* RT3090 // */ + AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, + 0x00); + /* 2-1. wait command ok. */ AsicCheckCommanOk(pAd, PowerWakeCID); -#endif +#endif /* RTMP_MAC_PCI // */ } } - // Turn off patching for cardbus controller - if (NicConfig2.field.CardbusAcceleration == 1) - { +#ifdef RTMP_MAC_PCI +#ifdef RT30xx + if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) { + struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; + if (pChipOps->AsicReverseRfFromSleepMode) + pChipOps->AsicReverseRfFromSleepMode(pAd); + } + /* 3090 MCU Wakeup command needs more time to be stable. */ + /* Before stable, don't issue other MCU command to prevent from firmware error. */ + + if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) + && IS_VERSION_AFTER_F(pAd) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) + && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { + DBGPRINT(RT_DEBUG_TRACE, ("%s, release Mcu Lock\n", __func__)); + RTMP_SEM_LOCK(&pAd->McuCmdLock); + pAd->brt30xxBanMcuCmd = FALSE; + RTMP_SEM_UNLOCK(&pAd->McuCmdLock); + } +#endif /* RT30xx // */ +#endif /* RTMP_MAC_PCI // */ + + /* Turn off patching for cardbus controller */ + if (NicConfig2.field.CardbusAcceleration == 1) { +/* pAd->bTest1 = TRUE; */ } if (NicConfig2.field.DynamicTxAgcControl == 1) pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE; else pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE; - - /* BBP has been programmed so reset to UNKNOWN_BAND */ + /* */ + /* Since BBP has been progamed, to make sure BBP setting will be */ + /* upate inside of AsicAntennaSelect, so reset to UNKNOWN_BAND! */ + /* */ pAd->CommonCfg.BandState = UNKNOWN_BAND; RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); BBPR3 &= (~0x18); - if(pAd->Antenna.field.RxPath == 3) - { + if (pAd->Antenna.field.RxPath == 3) { BBPR3 |= (0x10); - } - else if(pAd->Antenna.field.RxPath == 2) - { + } else if (pAd->Antenna.field.RxPath == 2) { BBPR3 |= (0x8); - } - else if(pAd->Antenna.field.RxPath == 1) - { + } else if (pAd->Antenna.field.RxPath == 1) { BBPR3 |= (0x0); } RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); { - // Handle the difference when 1T + /* Handle the difference when 1T */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); - if(pAd->Antenna.field.TxPath == 1) - { - BBPR1 &= (~0x18); + if (pAd->Antenna.field.TxPath == 1) { + BBPR1 &= (~0x18); } RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); - DBGPRINT(RT_DEBUG_TRACE, ("Use Hw Radio Control Pin=%d; if used Pin=%d;\n", pAd->CommonCfg.bHardwareRadio, pAd->CommonCfg.bHardwareRadio)); + DBGPRINT(RT_DEBUG_TRACE, + ("Use Hw Radio Control Pin=%d; if used Pin=%d;\n", + pAd->CommonCfg.bHardwareRadio, + pAd->CommonCfg.bHardwareRadio)); + } + +#ifdef RTMP_MAC_USB +#ifdef RT30xx + /* update registers from EEPROM for RT3071 or later(3572/3592). */ + + if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) { + u8 RegIdx, RegValue; + u16 value; + + /* after RT3071, write BBP from EEPROM 0xF0 to 0x102 */ + for (i = 0xF0; i <= 0x102; i = i + 2) { + value = 0xFFFF; + RT28xx_EEPROM_READ16(pAd, i, value); + if ((value != 0xFFFF) && (value != 0)) { + RegIdx = (u8)(value >> 8); + RegValue = (u8)(value & 0xff); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, RegIdx, + RegValue); + DBGPRINT(RT_DEBUG_TRACE, + ("Update BBP Registers from EEPROM(0x%0x), BBP(0x%x) = 0x%x\n", + i, RegIdx, RegValue)); + } + } + + /* after RT3071, write RF from EEPROM 0x104 to 0x116 */ + for (i = 0x104; i <= 0x116; i = i + 2) { + value = 0xFFFF; + RT28xx_EEPROM_READ16(pAd, i, value); + if ((value != 0xFFFF) && (value != 0)) { + RegIdx = (u8)(value >> 8); + RegValue = (u8)(value & 0xff); + RT30xxWriteRFRegister(pAd, RegIdx, RegValue); + DBGPRINT(RT_DEBUG_TRACE, + ("Update RF Registers from EEPROM0x%x), BBP(0x%x) = 0x%x\n", + i, RegIdx, RegValue)); + } + } } +#endif /* RT30xx // */ +#endif /* RTMP_MAC_USB // */ - DBGPRINT(RT_DEBUG_TRACE, ("TxPath = %d, RxPath = %d, RFIC=%d, Polar+LED mode=%x\n", pAd->Antenna.field.TxPath, pAd->Antenna.field.RxPath, pAd->RfIcType, pAd->LedCntl.word)); + DBGPRINT(RT_DEBUG_TRACE, + ("TxPath = %d, RxPath = %d, RFIC=%d, Polar+LED mode=%x\n", + pAd->Antenna.field.TxPath, pAd->Antenna.field.RxPath, + pAd->RfIcType, pAd->LedCntl.word)); DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitAsicFromEEPROM\n")); } @@ -1891,39 +1366,39 @@ VOID NICInitAsicFromEEPROM( ======================================================================== */ -NDIS_STATUS NICInitializeAdapter( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bHardReset) +int NICInitializeAdapter(struct rt_rtmp_adapter *pAd, IN BOOLEAN bHardReset) { - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - WPDMA_GLO_CFG_STRUC GloCfg; -#ifdef RT2860 - UINT32 Value; - DELAY_INT_CFG_STRUC IntCfg; -#endif - ULONG i =0, j=0; - AC_TXOP_CSR0_STRUC csr0; + int Status = NDIS_STATUS_SUCCESS; + WPDMA_GLO_CFG_STRUC GloCfg; +#ifdef RTMP_MAC_PCI + u32 Value; + DELAY_INT_CFG_STRUC IntCfg; +#endif /* RTMP_MAC_PCI // */ +/* INT_MASK_CSR_STRUC IntMask; */ + unsigned long i = 0, j = 0; + AC_TXOP_CSR0_STRUC csr0; DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAdapter\n")); - // 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits: + /* 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits: */ retry: i = 0; - do - { + do { RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); - if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) + if ((GloCfg.field.TxDMABusy == 0) + && (GloCfg.field.RxDMABusy == 0)) break; RTMPusecDelay(1000); i++; - }while ( i<100); - DBGPRINT(RT_DEBUG_TRACE, ("<== DMA offset 0x208 = 0x%x\n", GloCfg.word)); + } while (i < 100); + DBGPRINT(RT_DEBUG_TRACE, + ("<== DMA offset 0x208 = 0x%x\n", GloCfg.word)); GloCfg.word &= 0xff0; - GloCfg.field.EnTXWriteBackDDONE =1; + GloCfg.field.EnTXWriteBackDDONE = 1; RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); - // Record HW Beacon offset + /* Record HW Beacon offset */ pAd->BeaconOffset[0] = HW_BEACON_BASE0; pAd->BeaconOffset[1] = HW_BEACON_BASE1; pAd->BeaconOffset[2] = HW_BEACON_BASE2; @@ -1933,91 +1408,87 @@ retry: pAd->BeaconOffset[6] = HW_BEACON_BASE6; pAd->BeaconOffset[7] = HW_BEACON_BASE7; - // - // write all shared Ring's base address into ASIC - // + /* */ + /* write all shared Ring's base address into ASIC */ + /* */ - // asic simulation sequence put this ahead before loading firmware. - // pbf hardware reset -#ifdef RT2860 - RTMP_IO_WRITE32(pAd, WPDMA_RST_IDX, 0x1003f); // 0x10000 for reset rx, 0x3f resets all 6 tx rings. + /* asic simulation sequence put this ahead before loading firmware. */ + /* pbf hardware reset */ +#ifdef RTMP_MAC_PCI + RTMP_IO_WRITE32(pAd, WPDMA_RST_IDX, 0x1003f); /* 0x10000 for reset rx, 0x3f resets all 6 tx rings. */ RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe1f); RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe00); -#endif +#endif /* RTMP_MAC_PCI // */ - // Initialze ASIC for TX & Rx operation - if (NICInitializeAsic(pAd , bHardReset) != NDIS_STATUS_SUCCESS) - { - if (j++ == 0) - { + /* Initialze ASIC for TX & Rx operation */ + if (NICInitializeAsic(pAd, bHardReset) != NDIS_STATUS_SUCCESS) { + if (j++ == 0) { NICLoadFirmware(pAd); goto retry; } return NDIS_STATUS_FAILURE; } - -#ifdef RT2860 - // Write AC_BK base address register - Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BK].Cell[0].AllocPa); +#ifdef RTMP_MAC_PCI + /* Write AC_BK base address register */ + Value = + RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BK].Cell[0].AllocPa); RTMP_IO_WRITE32(pAd, TX_BASE_PTR1, Value); DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR1 : 0x%x\n", Value)); - // Write AC_BE base address register - Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BE].Cell[0].AllocPa); + /* Write AC_BE base address register */ + Value = + RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BE].Cell[0].AllocPa); RTMP_IO_WRITE32(pAd, TX_BASE_PTR0, Value); DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR0 : 0x%x\n", Value)); - // Write AC_VI base address register - Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VI].Cell[0].AllocPa); + /* Write AC_VI base address register */ + Value = + RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VI].Cell[0].AllocPa); RTMP_IO_WRITE32(pAd, TX_BASE_PTR2, Value); DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR2 : 0x%x\n", Value)); - // Write AC_VO base address register - Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VO].Cell[0].AllocPa); + /* Write AC_VO base address register */ + Value = + RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VO].Cell[0].AllocPa); RTMP_IO_WRITE32(pAd, TX_BASE_PTR3, Value); DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR3 : 0x%x\n", Value)); - // Write HCCA base address register - Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_HCCA].Cell[0].AllocPa); - RTMP_IO_WRITE32(pAd, TX_BASE_PTR4, Value); - DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR4 : 0x%x\n", Value)); - - // Write MGMT_BASE_CSR register + /* Write MGMT_BASE_CSR register */ Value = RTMP_GetPhysicalAddressLow(pAd->MgmtRing.Cell[0].AllocPa); RTMP_IO_WRITE32(pAd, TX_BASE_PTR5, Value); DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR5 : 0x%x\n", Value)); - // Write RX_BASE_CSR register + /* Write RX_BASE_CSR register */ Value = RTMP_GetPhysicalAddressLow(pAd->RxRing.Cell[0].AllocPa); RTMP_IO_WRITE32(pAd, RX_BASE_PTR, Value); DBGPRINT(RT_DEBUG_TRACE, ("--> RX_BASE_PTR : 0x%x\n", Value)); - // Init RX Ring index pointer + /* Init RX Ring index pointer */ pAd->RxRing.RxSwReadIdx = 0; - pAd->RxRing.RxCpuIdx = RX_RING_SIZE-1; + pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1; RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); - // Init TX rings index pointer + /* Init TX rings index pointer */ { - for (i=0; iTxRing[i].TxSwFreeIdx = 0; pAd->TxRing[i].TxCpuIdx = 0; - RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10) , pAd->TxRing[i].TxCpuIdx); + RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10), + pAd->TxRing[i].TxCpuIdx); } } - // init MGMT ring index pointer + /* init MGMT ring index pointer */ pAd->MgmtRing.TxSwFreeIdx = 0; pAd->MgmtRing.TxCpuIdx = 0; - RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); + RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); - // - // set each Ring's SIZE into ASIC. Descriptor Size is fixed by design. - // + /* */ + /* set each Ring's SIZE into ASIC. Descriptor Size is fixed by design. */ + /* */ - // Write TX_RING_CSR0 register + /* Write TX_RING_CSR0 register */ Value = TX_RING_SIZE; RTMP_IO_WRITE32(pAd, TX_MAX_CNT0, Value); RTMP_IO_WRITE32(pAd, TX_MAX_CNT1, Value); @@ -2027,53 +1498,47 @@ retry: Value = MGMT_RING_SIZE; RTMP_IO_WRITE32(pAd, TX_MGMTMAX_CNT, Value); - // Write RX_RING_CSR register + /* Write RX_RING_CSR register */ Value = RX_RING_SIZE; RTMP_IO_WRITE32(pAd, RX_MAX_CNT, Value); -#endif /* RT2860 */ - +#endif /* RTMP_MAC_PCI // */ - // WMM parameter + /* WMM parameter */ csr0.word = 0; RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); - if (pAd->CommonCfg.PhyMode == PHY_11B) - { - csr0.field.Ac0Txop = 192; // AC_VI: 192*32us ~= 6ms - csr0.field.Ac1Txop = 96; // AC_VO: 96*32us ~= 3ms - } - else - { - csr0.field.Ac0Txop = 96; // AC_VI: 96*32us ~= 3ms - csr0.field.Ac1Txop = 48; // AC_VO: 48*32us ~= 1.5ms + if (pAd->CommonCfg.PhyMode == PHY_11B) { + csr0.field.Ac0Txop = 192; /* AC_VI: 192*32us ~= 6ms */ + csr0.field.Ac1Txop = 96; /* AC_VO: 96*32us ~= 3ms */ + } else { + csr0.field.Ac0Txop = 96; /* AC_VI: 96*32us ~= 3ms */ + csr0.field.Ac1Txop = 48; /* AC_VO: 48*32us ~= 1.5ms */ } RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr0.word); - -#ifdef RT2860 - // 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits: +#ifdef RTMP_MAC_PCI + /* 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits: */ i = 0; - do - { + do { RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); - if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) + if ((GloCfg.field.TxDMABusy == 0) + && (GloCfg.field.RxDMABusy == 0)) break; RTMPusecDelay(1000); i++; - }while ( i < 100); + } while (i < 100); GloCfg.word &= 0xff0; - GloCfg.field.EnTXWriteBackDDONE =1; + GloCfg.field.EnTXWriteBackDDONE = 1; RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); IntCfg.word = 0; RTMP_IO_WRITE32(pAd, DELAY_INT_CFG, IntCfg.word); -#endif - +#endif /* RTMP_MAC_PCI // */ - // reset action - // Load firmware - // Status = NICLoadFirmware(pAd); + /* reset action */ + /* Load firmware */ + /* Status = NICLoadFirmware(pAd); */ DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAdapter\n")); return Status; @@ -2097,42 +1562,55 @@ retry: ======================================================================== */ -NDIS_STATUS NICInitializeAsic( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bHardReset) +int NICInitializeAsic(struct rt_rtmp_adapter *pAd, IN BOOLEAN bHardReset) { - ULONG Index = 0; - UCHAR R0 = 0xff; - UINT32 MacCsr12 = 0, Counter = 0; -#ifdef RT2870 - UINT32 MacCsr0 = 0; - NTSTATUS Status; - UCHAR Value = 0xff; - UINT32 eFuseCtrl; -#endif - USHORT KeyIdx; - INT i,apidx; + unsigned long Index = 0; + u8 R0 = 0xff; + u32 MacCsr12 = 0, Counter = 0; +#ifdef RTMP_MAC_USB + u32 MacCsr0 = 0; + int Status; + u8 Value = 0xff; +#endif /* RTMP_MAC_USB // */ +#ifdef RT30xx + u8 bbpreg = 0; + u8 RFValue = 0; +#endif /* RT30xx // */ + u16 KeyIdx; + int i, apidx; DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAsic\n")); -#ifdef RT2860 - if (bHardReset == TRUE) - { +#ifdef RTMP_MAC_PCI + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x3); /* To fix driver disable/enable hang issue when radio off */ + if (bHardReset == TRUE) { RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3); - } - else + } else RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); -#endif -#ifdef RT2870 - // - // Make sure MAC gets ready after NICLoadFirmware(). - // - Index = 0; - //To avoid hang-on issue when interface up in kernel 2.4, - //we use a local variable "MacCsr0" instead of using "pAd->MACVersion" directly. - do + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + /* Initialize MAC register to default value */ + for (Index = 0; Index < NUM_MAC_REG_PARMS; Index++) { + RTMP_IO_WRITE32(pAd, MACRegTable[Index].Register, + MACRegTable[Index].Value); + } + { + for (Index = 0; Index < NUM_STA_MAC_REG_PARMS; Index++) { + RTMP_IO_WRITE32(pAd, STAMACRegTable[Index].Register, + STAMACRegTable[Index].Value); + } + } +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + /* */ + /* Make sure MAC gets ready after NICLoadFirmware(). */ + /* */ + Index = 0; + + /*To avoid hang-on issue when interface up in kernel 2.4, */ + /*we use a local variable "MacCsr0" instead of using "pAd->MACVersion" directly. */ + do { RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); if ((MacCsr0 != 0x00) && (MacCsr0 != 0xFFFFFFFF)) @@ -2142,8 +1620,9 @@ NDIS_STATUS NICInitializeAsic( } while (Index++ < 100); pAd->MACVersion = MacCsr0; - DBGPRINT(RT_DEBUG_TRACE, ("MAC_CSR0 [ Ver:Rev=0x%08x]\n", pAd->MACVersion)); - // turn on bit13 (set to zero) after rt2860D. This is to solve high-current issue. + DBGPRINT(RT_DEBUG_TRACE, + ("MAC_CSR0 [ Ver:Rev=0x%08x]\n", pAd->MACVersion)); + /* turn on bit13 (set to zero) after rt2860D. This is to solve high-current issue. */ RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacCsr12); MacCsr12 &= (~0x2000); RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, MacCsr12); @@ -2151,203 +1630,223 @@ NDIS_STATUS NICInitializeAsic( RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3); RTMP_IO_WRITE32(pAd, USB_DMA_CFG, 0x0); Status = RTUSBVenderReset(pAd); -#endif RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); - // Initialize MAC register to default value -#ifdef RT2860 - for (Index = 0; Index < NUM_MAC_REG_PARMS; Index++) - { - RTMP_IO_WRITE32(pAd, MACRegTable[Index].Register, MACRegTable[Index].Value); - } -#endif -#ifdef RT2870 - for(Index=0; IndexMACVersion & 0xffff) < 0x0211) - { - if (pAd->NicConfig2.field.DACTestBit == 1) - { - RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x1F); // To fix throughput drop drastically + /* RT3071 version E has fixed this issue */ + if ((pAd->MACVersion & 0xffff) < 0x0211) { + if (pAd->NicConfig2.field.DACTestBit == 1) { + RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x2C); /* To fix throughput drop drastically */ + } else { + RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x0F); /* To fix throughput drop drastically */ } - else - { - RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x0F); // To fix throughput drop drastically - } - } - else - { + } else { RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x0); } + } else if (IS_RT3070(pAd)) { + if (((pAd->MACVersion & 0xffff) < 0x0201)) { + RTMP_IO_WRITE32(pAd, TX_SW_CFG1, 0); + RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x2C); /* To fix throughput drop drastically */ + } else { + RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0); + } } -#ifdef RT2870 - else if (IS_RT3070(pAd)) - { - RTMP_IO_WRITE32(pAd, TX_SW_CFG1, 0); - RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x1F); // To fix throughput drop drastically - } -#endif // RT30xx // +#endif /* RT30xx // */ - // - // Before program BBP, we need to wait BBP/RF get wake up. - // + /* */ + /* Before program BBP, we need to wait BBP/RF get wake up. */ + /* */ Index = 0; - do - { + do { RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacCsr12); - if ((MacCsr12 & 0x03) == 0) // if BB.RF is stable + if ((MacCsr12 & 0x03) == 0) /* if BB.RF is stable */ break; - DBGPRINT(RT_DEBUG_TRACE, ("Check MAC_STATUS_CFG = Busy = %x\n", MacCsr12)); + DBGPRINT(RT_DEBUG_TRACE, + ("Check MAC_STATUS_CFG = Busy = %x\n", MacCsr12)); RTMPusecDelay(1000); } while (Index++ < 100); - // The commands to firmware should be after these commands, these commands will init firmware - // PCI and USB are not the same because PCI driver needs to wait for PCI bus ready - RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, 0); // initialize BBP R/W access agent + /* The commands to firmware should be after these commands, these commands will init firmware */ + /* PCI and USB are not the same because PCI driver needs to wait for PCI bus ready */ + RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, 0); /* initialize BBP R/W access agent */ RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, 0); +#ifdef RT3090 + /*2008/11/28:KH add to fix the dead rf frequency offset bug<-- */ + AsicSendCommandToMcu(pAd, 0x72, 0, 0, 0); + /*2008/11/28:KH add to fix the dead rf frequency offset bug--> */ +#endif /* RT3090 // */ RTMPusecDelay(1000); - // Read BBP register, make sure BBP is up and running before write new data + /* Read BBP register, make sure BBP is up and running before write new data */ Index = 0; - do - { + do { RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R0, &R0); DBGPRINT(RT_DEBUG_TRACE, ("BBP version = %x\n", R0)); } while ((++Index < 20) && ((R0 == 0xff) || (R0 == 0x00))); - //ASSERT(Index < 20); //this will cause BSOD on Check-build driver + /*ASSERT(Index < 20); //this will cause BSOD on Check-build driver */ if ((R0 == 0xff) || (R0 == 0x00)) return NDIS_STATUS_FAILURE; - // Initialize BBP register to default value - for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, BBPRegTable[Index].Value); + /* Initialize BBP register to default value */ + for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++) { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, + BBPRegTable[Index].Value); } -#ifndef RT2870 - // for rt2860E and after, init BBP_R84 with 0x19. This is for extension channel overlapping IOT. - if ((pAd->MACVersion&0xffff) != 0x0101) - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R84, 0x19); -#else - // for rt2860E and after, init BBP_R84 with 0x19. This is for extension channel overlapping IOT. - // RT3090 should not program BBP R84 to 0x19, otherwise TX will block. - if (((pAd->MACVersion&0xffff) != 0x0101) && (!IS_RT30xx(pAd))) +#ifdef RTMP_MAC_PCI + /* TODO: shiang, check MACVersion, currently, rbus-based chip use this. */ + if (pAd->MACVersion == 0x28720200) { + /*u8 value; */ + unsigned long value2; + + /*disable MLD by Bruce 20080704 */ + /*BBP_IO_READ8_BY_REG_ID(pAd, BBP_R105, &value); */ + /*BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R105, value | 4); */ + + /*Maximum PSDU length from 16K to 32K bytes */ + RTMP_IO_READ32(pAd, MAX_LEN_CFG, &value2); + value2 &= ~(0x3 << 12); + value2 |= (0x2 << 12); + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, value2); + } +#endif /* RTMP_MAC_PCI // */ + + /* for rt2860E and after, init BBP_R84 with 0x19. This is for extension channel overlapping IOT. */ + /* RT3090 should not program BBP R84 to 0x19, otherwise TX will block. */ + /*3070/71/72,3090,3090A( are included in RT30xx),3572,3390 */ + if (((pAd->MACVersion & 0xffff) != 0x0101) + && !(IS_RT30xx(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R84, 0x19); -// add by johnli, RF power sequence setup - if (IS_RT30xx(pAd)) - { //update for RT3070/71/72/90/91/92. +#ifdef RT30xx +/* add by johnli, RF power sequence setup */ + if (IS_RT30xx(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) { /*update for RT3070/71/72/90/91/92,3572,3390. */ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R79, 0x13); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R80, 0x05); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R81, 0x33); } - if (IS_RT3090(pAd)) + if (IS_RT3090(pAd) || IS_RT3390(pAd)) /* RT309x, RT3071/72 */ { - UCHAR bbpreg=0; - - // enable DC filter - if ((pAd->MACVersion & 0xffff) >= 0x0211) - { + /* enable DC filter */ + if ((pAd->MACVersion & 0xffff) >= 0x0211) { RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R103, 0xc0); } - - // improve power consumption + /* improve power consumption */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R138, &bbpreg); - if (pAd->Antenna.field.TxPath == 1) - { - // turn off tx DAC_1 + if (pAd->Antenna.field.TxPath == 1) { + /* turn off tx DAC_1 */ bbpreg = (bbpreg | 0x20); } - if (pAd->Antenna.field.RxPath == 1) - { - // turn off tx ADC_1 + if (pAd->Antenna.field.RxPath == 1) { + /* turn off tx ADC_1 */ bbpreg &= (~0x2); } RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R138, bbpreg); - // improve power consumption in RT3071 Ver.E - if ((pAd->MACVersion & 0xffff) >= 0x0211) - { + /* improve power consumption in RT3071 Ver.E */ + if ((pAd->MACVersion & 0xffff) >= 0x0211) { RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R31, &bbpreg); bbpreg &= (~0x3); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R31, bbpreg); } + } else if (IS_RT3070(pAd)) { + if ((pAd->MACVersion & 0xffff) >= 0x0201) { + /* enable DC filter */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R103, 0xc0); + + /* improve power consumption in RT3070 Ver.F */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R31, &bbpreg); + bbpreg &= (~0x3); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R31, bbpreg); + } + /* TX_LO1_en, RF R17 register Bit 3 to 0 */ + RT30xxReadRFRegister(pAd, RF_R17, &RFValue); + RFValue &= (~0x08); + /* to fix rx long range issue */ + if (pAd->NicConfig2.field.ExternalLNAForG == 0) { + RFValue |= 0x20; + } + /* set RF_R17_bit[2:0] equal to EEPROM setting at 0x48h */ + if (pAd->TxMixerGain24G >= 1) { + RFValue &= (~0x7); /* clean bit [2:0] */ + RFValue |= pAd->TxMixerGain24G; + } + RT30xxWriteRFRegister(pAd, RF_R17, RFValue); } -#endif - if (pAd->MACVersion == 0x28600100) - { +/* end johnli */ +#endif /* RT30xx // */ + + if (pAd->MACVersion == 0x28600100) { RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x12); - } + } - if (pAd->MACVersion >= RALINK_2880E_VERSION && pAd->MACVersion < RALINK_3070_VERSION) // 3*3 + if (pAd->MACVersion >= RALINK_2880E_VERSION && pAd->MACVersion < RALINK_3070_VERSION) /* 3*3 */ { - // enlarge MAX_LEN_CFG - UINT32 csr; + /* enlarge MAX_LEN_CFG */ + u32 csr; RTMP_IO_READ32(pAd, MAX_LEN_CFG, &csr); csr &= 0xFFF; csr |= 0x2000; RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, csr); } - -#ifdef RT2870 -{ - UCHAR MAC_Value[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0,0}; - - //Initialize WCID table - Value = 0xff; - for(Index =0 ;Index < 254;Index++) +#ifdef RTMP_MAC_USB { - RTUSBMultiWrite(pAd, (USHORT)(MAC_WCID_BASE + Index * 8), MAC_Value, 8); + u8 MAC_Value[] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0 }; + + /*Initialize WCID table */ + Value = 0xff; + for (Index = 0; Index < 254; Index++) { + RTUSBMultiWrite(pAd, + (u16)(MAC_WCID_BASE + Index * 8), + MAC_Value, 8); + } } -} -#endif // RT2870 // +#endif /* RTMP_MAC_USB // */ - // Add radio off control + /* Add radio off control */ { - if (pAd->StaCfg.bRadio == FALSE) - { -// RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818); + if (pAd->StaCfg.bRadio == FALSE) { +/* RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818); */ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); DBGPRINT(RT_DEBUG_TRACE, ("Set Radio Off\n")); } } - // Clear raw counters + /* Clear raw counters */ RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter); RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter); RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter); @@ -2355,65 +1854,55 @@ NDIS_STATUS NICInitializeAsic( RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter); RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter); - // ASIC will keep garbage value after boot - // Clear all seared key table when initial - // This routine can be ignored in radio-ON/OFF operation. - if (bHardReset) - { - for (KeyIdx = 0; KeyIdx < 4; KeyIdx++) - { - RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4*KeyIdx, 0); + /* ASIC will keep garbage value after boot */ + /* Clear all shared key table when initial */ + /* This routine can be ignored in radio-ON/OFF operation. */ + if (bHardReset) { + for (KeyIdx = 0; KeyIdx < 4; KeyIdx++) { + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * KeyIdx, + 0); } - // Clear all pairwise key table when initial - for (KeyIdx = 0; KeyIdx < 256; KeyIdx++) - { - RTMP_IO_WRITE32(pAd, MAC_WCID_ATTRIBUTE_BASE + (KeyIdx * HW_WCID_ATTRI_SIZE), 1); + /* Clear all pairwise key table when initial */ + for (KeyIdx = 0; KeyIdx < 256; KeyIdx++) { + RTMP_IO_WRITE32(pAd, + MAC_WCID_ATTRIBUTE_BASE + + (KeyIdx * HW_WCID_ATTRI_SIZE), 1); } } + /* assert HOST ready bit */ +/* RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x0); // 2004-09-14 asked by Mark */ +/* RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x4); */ - - // It isn't necessary to clear this space when not hard reset. - if (bHardReset == TRUE) - { - // clear all on-chip BEACON frame space - for (apidx = 0; apidx < HW_BEACON_MAX_COUNT; apidx++) - { - for (i = 0; i < HW_BEACON_OFFSET>>2; i+=4) - RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[apidx] + i, 0x00); + /* It isn't necessary to clear this space when not hard reset. */ + if (bHardReset == TRUE) { + /* clear all on-chip BEACON frame space */ + for (apidx = 0; apidx < HW_BEACON_MAX_COUNT; apidx++) { + for (i = 0; i < HW_BEACON_OFFSET >> 2; i += 4) + RTMP_IO_WRITE32(pAd, + pAd->BeaconOffset[apidx] + i, + 0x00); } } -#ifdef RT2870 +#ifdef RTMP_MAC_USB AsicDisableSync(pAd); - // Clear raw counters + /* Clear raw counters */ RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter); RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter); RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter); RTMP_IO_READ32(pAd, TX_STA_CNT0, &Counter); RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter); RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter); - // Default PCI clock cycle per ms is different as default setting, which is based on PCI. + /* Default PCI clock cycle per ms is different as default setting, which is based on PCI. */ RTMP_IO_READ32(pAd, USB_CYC_CFG, &Counter); - Counter&=0xffffff00; - Counter|=0x000001e; + Counter &= 0xffffff00; + Counter |= 0x000001e; RTMP_IO_WRITE32(pAd, USB_CYC_CFG, Counter); +#endif /* RTMP_MAC_USB // */ - pAd->bUseEfuse=FALSE; - RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrl); - pAd->bUseEfuse = ( (eFuseCtrl & 0x80000000) == 0x80000000) ? 1 : 0; - if(pAd->bUseEfuse) - { - DBGPRINT(RT_DEBUG_TRACE, ("NVM is Efuse\n")); - } - else { - DBGPRINT(RT_DEBUG_TRACE, ("NVM is EEPROM\n")); - } -#endif - - { - // for rt2860E and after, init TXOP_CTRL_CFG with 0x583f. This is for extension channel overlapping IOT. - if ((pAd->MACVersion&0xffff) != 0x0101) + /* for rt2860E and after, init TXOP_CTRL_CFG with 0x583f. This is for extension channel overlapping IOT. */ + if ((pAd->MACVersion & 0xffff) != 0x0101) RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x583f); } @@ -2421,133 +1910,6 @@ NDIS_STATUS NICInitializeAsic( return NDIS_STATUS_SUCCESS; } - -#ifdef RT2860 -VOID NICRestoreBBPValue( - IN PRTMP_ADAPTER pAd) -{ - UCHAR index; - UCHAR Value = 0; - ULONG Data; - - DBGPRINT(RT_DEBUG_TRACE, ("---> NICRestoreBBPValue !!!!!!!!!!!!!!!!!!!!!!! \n")); - // Initialize BBP register to default value (rtmp_init.c) - for (index = 0; index < NUM_BBP_REG_PARMS; index++) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[index].Register, BBPRegTable[index].Value); - } - // copy from (rtmp_init.c) - if (pAd->MACVersion == 0x28600100) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x12); - } - - // copy from (connect.c LinkUp function) - if (INFRA_ON(pAd)) - { - // Change to AP channel - if ((pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. - pAd->CommonCfg.BBPCurrentBW = BW_40; - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); - Value &= (~0x18); - Value |= 0x10; - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); - - // RX : control channel at lower - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); - Value &= (~0x20); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); - // Record BBPR3 setting, But don't keep R Antenna # information. - pAd->StaCfg.BBPR3 = Value; - - RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); - Data &= 0xfffffffe; - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); - - if (pAd->MACVersion == 0x28600100) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); - DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); - } - - DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel )); - } - else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. - pAd->CommonCfg.BBPCurrentBW = BW_40; - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); - Value &= (~0x18); - Value |= 0x10; - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); - - RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); - Data |= 0x1; - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); - - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); - Value |= (0x20); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); - // Record BBPR3 setting, But don't keep R Antenna # information. - pAd->StaCfg.BBPR3 = Value; - - if (pAd->MACVersion == 0x28600100) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); - DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); - } - - DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel )); - } - else - { - pAd->CommonCfg.BBPCurrentBW = BW_20; - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); - Value &= (~0x18); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); - - RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); - Data &= 0xfffffffe; - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); - - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); - Value &= (~0x20); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); - // Record BBPR3 setting, But don't keep R Antenna # information. - pAd->StaCfg.BBPR3 = Value; - - if (pAd->MACVersion == 0x28600100) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11); - DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); - } - - DBGPRINT(RT_DEBUG_TRACE, ("!!!20MHz LINK UP !!! \n" )); - } - } - - DBGPRINT(RT_DEBUG_TRACE, ("<--- NICRestoreBBPValue !!!!!!!!!!!!!!!!!!!!!!! \n")); -} -#endif /* RT2860 */ - /* ======================================================================== @@ -2567,19 +1929,21 @@ VOID NICRestoreBBPValue( ======================================================================== */ -VOID NICIssueReset( - IN PRTMP_ADAPTER pAd) +void NICIssueReset(struct rt_rtmp_adapter *pAd) { - UINT32 Value = 0; + u32 Value = 0; DBGPRINT(RT_DEBUG_TRACE, ("--> NICIssueReset\n")); - // Disable Rx, register value supposed will remain after reset + /* Abort Tx, prevent ASIC from writing to Host memory */ + /*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x001f0000); */ + + /* Disable Rx, register value supposed will remain after reset */ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); Value &= (0xfffffff3); RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - // Issue reset and clear from reset state - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x03); // 2004-09-17 change from 0x01 + /* Issue reset and clear from reset state */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x03); /* 2004-09-17 change from 0x01 */ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); DBGPRINT(RT_DEBUG_TRACE, ("<-- NICIssueReset\n")); @@ -2601,134 +1965,115 @@ VOID NICIssueReset( ======================================================================== */ -BOOLEAN NICCheckForHang( - IN PRTMP_ADAPTER pAd) +BOOLEAN NICCheckForHang(struct rt_rtmp_adapter *pAd) { return (FALSE); } -VOID NICUpdateFifoStaCounters( - IN PRTMP_ADAPTER pAd) +void NICUpdateFifoStaCounters(struct rt_rtmp_adapter *pAd) { - TX_STA_FIFO_STRUC StaFifo; - MAC_TABLE_ENTRY *pEntry; - UCHAR i = 0; - UCHAR pid = 0, wcid = 0; - CHAR reTry; - UCHAR succMCS; - - do - { - RTMP_IO_READ32(pAd, TX_STA_FIFO, &StaFifo.word); + TX_STA_FIFO_STRUC StaFifo; + struct rt_mac_table_entry *pEntry; + u8 i = 0; + u8 pid = 0, wcid = 0; + char reTry; + u8 succMCS; - if (StaFifo.field.bValid == 0) - break; + do { + RTMP_IO_READ32(pAd, TX_STA_FIFO, &StaFifo.word); - wcid = (UCHAR)StaFifo.field.wcid; + if (StaFifo.field.bValid == 0) + break; + wcid = (u8)StaFifo.field.wcid; /* ignore NoACK and MGMT frame use 0xFF as WCID */ - if ((StaFifo.field.TxAckRequired == 0) || (wcid >= MAX_LEN_OF_MAC_TABLE)) - { - i++; - continue; - } - - /* PID store Tx MCS Rate */ - pid = (UCHAR)StaFifo.field.PidType; - - pEntry = &pAd->MacTab.Content[wcid]; + if ((StaFifo.field.TxAckRequired == 0) + || (wcid >= MAX_LEN_OF_MAC_TABLE)) { + i++; + continue; + } - pEntry->DebugFIFOCount++; + /* PID store Tx MCS Rate */ + pid = (u8)StaFifo.field.PidType; - if (StaFifo.field.TxBF) // 3*3 - pEntry->TxBFCount++; + pEntry = &pAd->MacTab.Content[wcid]; -#ifdef UAPSD_AP_SUPPORT - UAPSD_SP_AUE_Handle(pAd, pEntry, StaFifo.field.TxSuccess); -#endif // UAPSD_AP_SUPPORT // + pEntry->DebugFIFOCount++; - if (!StaFifo.field.TxSuccess) - { - pEntry->FIFOCount++; - pEntry->OneSecTxFailCount++; + if (StaFifo.field.TxBF) /* 3*3 */ + pEntry->TxBFCount++; - if (pEntry->FIFOCount >= 1) - { - DBGPRINT(RT_DEBUG_TRACE, ("#")); - pEntry->NoBADataCountDown = 64; + if (!StaFifo.field.TxSuccess) { + pEntry->FIFOCount++; + pEntry->OneSecTxFailCount++; - if(pEntry->PsMode == PWR_ACTIVE) - { - int tid; - for (tid=0; tidAid, tid, FALSE, FALSE); - } + if (pEntry->FIFOCount >= 1) { + DBGPRINT(RT_DEBUG_TRACE, ("#")); + pEntry->NoBADataCountDown = 64; - // Update the continuous transmission counter except PS mode - pEntry->ContinueTxFailCnt++; - } - else - { - // Clear the FIFOCount when sta in Power Save mode. Basically we assume - // this tx error happened due to sta just go to sleep. - pEntry->FIFOCount = 0; - pEntry->ContinueTxFailCnt = 0; + if (pEntry->PsMode == PWR_ACTIVE) { + int tid; + for (tid = 0; tid < NUM_OF_TID; tid++) { + BAOriSessionTearDown(pAd, + pEntry-> + Aid, tid, + FALSE, + FALSE); } + + /* Update the continuous transmission counter except PS mode */ + pEntry->ContinueTxFailCnt++; + } else { + /* Clear the FIFOCount when sta in Power Save mode. Basically we assume */ + /* this tx error happened due to sta just go to sleep. */ + pEntry->FIFOCount = 0; + pEntry->ContinueTxFailCnt = 0; } + /*pEntry->FIFOCount = 0; */ } - else - { - if ((pEntry->PsMode != PWR_SAVE) && (pEntry->NoBADataCountDown > 0)) - { - pEntry->NoBADataCountDown--; - if (pEntry->NoBADataCountDown==0) - { - DBGPRINT(RT_DEBUG_TRACE, ("@\n")); - } + /*pEntry->bSendBAR = TRUE; */ + } else { + if ((pEntry->PsMode != PWR_SAVE) + && (pEntry->NoBADataCountDown > 0)) { + pEntry->NoBADataCountDown--; + if (pEntry->NoBADataCountDown == 0) { + DBGPRINT(RT_DEBUG_TRACE, ("@\n")); } - - pEntry->FIFOCount = 0; - pEntry->OneSecTxNoRetryOkCount++; - // update NoDataIdleCount when sucessful send packet to STA. - pEntry->NoDataIdleCount = 0; - pEntry->ContinueTxFailCnt = 0; } - succMCS = StaFifo.field.SuccessRate & 0x7F; - - reTry = pid - succMCS; - - if (StaFifo.field.TxSuccess) - { - pEntry->TXMCSExpected[pid]++; - if (pid == succMCS) - { - pEntry->TXMCSSuccessful[pid]++; - } - else - { - pEntry->TXMCSAutoFallBack[pid][succMCS]++; - } - } - else - { - pEntry->TXMCSFailed[pid]++; + pEntry->FIFOCount = 0; + pEntry->OneSecTxNoRetryOkCount++; + /* update NoDataIdleCount when sucessful send packet to STA. */ + pEntry->NoDataIdleCount = 0; + pEntry->ContinueTxFailCnt = 0; + } + + succMCS = StaFifo.field.SuccessRate & 0x7F; + + reTry = pid - succMCS; + + if (StaFifo.field.TxSuccess) { + pEntry->TXMCSExpected[pid]++; + if (pid == succMCS) { + pEntry->TXMCSSuccessful[pid]++; + } else { + pEntry->TXMCSAutoFallBack[pid][succMCS]++; } + } else { + pEntry->TXMCSFailed[pid]++; + } - if (reTry > 0) - { - if ((pid >= 12) && succMCS <=7) - { - reTry -= 4; - } - pEntry->OneSecTxRetryOkCount += reTry; + if (reTry > 0) { + if ((pid >= 12) && succMCS <= 7) { + reTry -= 4; } + pEntry->OneSecTxRetryOkCount += reTry; + } - i++; - // ASIC store 16 stack - } while ( i < (2*TX_RING_SIZE) ); + i++; + /* ASIC store 16 stack */ + } while (i < (2 * TX_RING_SIZE)); } @@ -2749,87 +2094,99 @@ VOID NICUpdateFifoStaCounters( ======================================================================== */ -VOID NICUpdateRawCounters( - IN PRTMP_ADAPTER pAd) +void NICUpdateRawCounters(struct rt_rtmp_adapter *pAd) { - UINT32 OldValue; - RX_STA_CNT0_STRUC RxStaCnt0; - RX_STA_CNT1_STRUC RxStaCnt1; - RX_STA_CNT2_STRUC RxStaCnt2; - TX_STA_CNT0_STRUC TxStaCnt0; - TX_STA_CNT1_STRUC StaTx1; - TX_STA_CNT2_STRUC StaTx2; - TX_AGG_CNT_STRUC TxAggCnt; - TX_AGG_CNT0_STRUC TxAggCnt0; - TX_AGG_CNT1_STRUC TxAggCnt1; - TX_AGG_CNT2_STRUC TxAggCnt2; - TX_AGG_CNT3_STRUC TxAggCnt3; - TX_AGG_CNT4_STRUC TxAggCnt4; - TX_AGG_CNT5_STRUC TxAggCnt5; - TX_AGG_CNT6_STRUC TxAggCnt6; - TX_AGG_CNT7_STRUC TxAggCnt7; + u32 OldValue; /*, Value2; */ + /*unsigned long PageSum, OneSecTransmitCount; */ + /*unsigned long TxErrorRatio, Retry, Fail; */ + RX_STA_CNT0_STRUC RxStaCnt0; + RX_STA_CNT1_STRUC RxStaCnt1; + RX_STA_CNT2_STRUC RxStaCnt2; + TX_STA_CNT0_STRUC TxStaCnt0; + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT2_STRUC StaTx2; + TX_AGG_CNT_STRUC TxAggCnt; + TX_AGG_CNT0_STRUC TxAggCnt0; + TX_AGG_CNT1_STRUC TxAggCnt1; + TX_AGG_CNT2_STRUC TxAggCnt2; + TX_AGG_CNT3_STRUC TxAggCnt3; + TX_AGG_CNT4_STRUC TxAggCnt4; + TX_AGG_CNT5_STRUC TxAggCnt5; + TX_AGG_CNT6_STRUC TxAggCnt6; + TX_AGG_CNT7_STRUC TxAggCnt7; + struct rt_counter_ralink *pRalinkCounters; + + pRalinkCounters = &pAd->RalinkCounters; RTMP_IO_READ32(pAd, RX_STA_CNT0, &RxStaCnt0.word); RTMP_IO_READ32(pAd, RX_STA_CNT2, &RxStaCnt2.word); { RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word); - // Update RX PLCP error counter - pAd->PrivateInfo.PhyRxErrCnt += RxStaCnt1.field.PlcpErr; - // Update False CCA counter - pAd->RalinkCounters.OneSecFalseCCACnt += RxStaCnt1.field.FalseCca; + /* Update RX PLCP error counter */ + pAd->PrivateInfo.PhyRxErrCnt += RxStaCnt1.field.PlcpErr; + /* Update False CCA counter */ + pAd->RalinkCounters.OneSecFalseCCACnt += + RxStaCnt1.field.FalseCca; } - // Update FCS counters - OldValue= pAd->WlanCounters.FCSErrorCount.u.LowPart; - pAd->WlanCounters.FCSErrorCount.u.LowPart += (RxStaCnt0.field.CrcErr); // >> 7); + /* Update FCS counters */ + OldValue = pAd->WlanCounters.FCSErrorCount.u.LowPart; + pAd->WlanCounters.FCSErrorCount.u.LowPart += (RxStaCnt0.field.CrcErr); /* >> 7); */ if (pAd->WlanCounters.FCSErrorCount.u.LowPart < OldValue) pAd->WlanCounters.FCSErrorCount.u.HighPart++; - // Add FCS error count to private counters - pAd->RalinkCounters.OneSecRxFcsErrCnt += RxStaCnt0.field.CrcErr; - OldValue = pAd->RalinkCounters.RealFcsErrCount.u.LowPart; - pAd->RalinkCounters.RealFcsErrCount.u.LowPart += RxStaCnt0.field.CrcErr; - if (pAd->RalinkCounters.RealFcsErrCount.u.LowPart < OldValue) - pAd->RalinkCounters.RealFcsErrCount.u.HighPart++; - - // Update Duplicate Rcv check - pAd->RalinkCounters.DuplicateRcv += RxStaCnt2.field.RxDupliCount; - pAd->WlanCounters.FrameDuplicateCount.u.LowPart += RxStaCnt2.field.RxDupliCount; - // Update RX Overflow counter + /* Add FCS error count to private counters */ + pRalinkCounters->OneSecRxFcsErrCnt += RxStaCnt0.field.CrcErr; + OldValue = pRalinkCounters->RealFcsErrCount.u.LowPart; + pRalinkCounters->RealFcsErrCount.u.LowPart += RxStaCnt0.field.CrcErr; + if (pRalinkCounters->RealFcsErrCount.u.LowPart < OldValue) + pRalinkCounters->RealFcsErrCount.u.HighPart++; + + /* Update Duplicate Rcv check */ + pRalinkCounters->DuplicateRcv += RxStaCnt2.field.RxDupliCount; + pAd->WlanCounters.FrameDuplicateCount.u.LowPart += + RxStaCnt2.field.RxDupliCount; + /* Update RX Overflow counter */ pAd->Counters8023.RxNoBuffer += (RxStaCnt2.field.RxFifoOverflowCount); -#ifdef RT2870 - if (pAd->RalinkCounters.RxCount != pAd->watchDogRxCnt) - { - pAd->watchDogRxCnt = pAd->RalinkCounters.RxCount; + /*pAd->RalinkCounters.RxCount = 0; */ +#ifdef RTMP_MAC_USB + if (pRalinkCounters->RxCount != pAd->watchDogRxCnt) { + pAd->watchDogRxCnt = pRalinkCounters->RxCount; pAd->watchDogRxOverFlowCnt = 0; - } - else - { + } else { if (RxStaCnt2.field.RxFifoOverflowCount) pAd->watchDogRxOverFlowCnt++; else pAd->watchDogRxOverFlowCnt = 0; } -#endif // RT2870 // - - - if (!pAd->bUpdateBcnCntDone) - { - // Update BEACON sent count - RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); - RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); - RTMP_IO_READ32(pAd, TX_STA_CNT2, &StaTx2.word); - pAd->RalinkCounters.OneSecBeaconSentCnt += TxStaCnt0.field.TxBeaconCount; - pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; - pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; - pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount; - pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; - pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; - pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; - } - +#endif /* RTMP_MAC_USB // */ + + /*if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) || */ + /* (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) && (pAd->MacTab.Size != 1))) */ + if (!pAd->bUpdateBcnCntDone) { + /* Update BEACON sent count */ + RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); + RTMP_IO_READ32(pAd, TX_STA_CNT2, &StaTx2.word); + pRalinkCounters->OneSecBeaconSentCnt += + TxStaCnt0.field.TxBeaconCount; + pRalinkCounters->OneSecTxRetryOkCount += + StaTx1.field.TxRetransmit; + pRalinkCounters->OneSecTxNoRetryOkCount += + StaTx1.field.TxSuccess; + pRalinkCounters->OneSecTxFailCount += + TxStaCnt0.field.TxFailCount; + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += + StaTx1.field.TxSuccess; + pAd->WlanCounters.RetryCount.u.LowPart += + StaTx1.field.TxRetransmit; + pAd->WlanCounters.FailedCount.u.LowPart += + TxStaCnt0.field.TxFailCount; + } + + /*if (pAd->bStaFifoTest == TRUE) */ { RTMP_IO_READ32(pAd, TX_AGG_CNT, &TxAggCnt.word); RTMP_IO_READ32(pAd, TX_AGG_CNT0, &TxAggCnt0.word); @@ -2840,60 +2197,89 @@ VOID NICUpdateRawCounters( RTMP_IO_READ32(pAd, TX_AGG_CNT5, &TxAggCnt5.word); RTMP_IO_READ32(pAd, TX_AGG_CNT6, &TxAggCnt6.word); RTMP_IO_READ32(pAd, TX_AGG_CNT7, &TxAggCnt7.word); - pAd->RalinkCounters.TxAggCount += TxAggCnt.field.AggTxCount; - pAd->RalinkCounters.TxNonAggCount += TxAggCnt.field.NonAggTxCount; - pAd->RalinkCounters.TxAgg1MPDUCount += TxAggCnt0.field.AggSize1Count; - pAd->RalinkCounters.TxAgg2MPDUCount += TxAggCnt0.field.AggSize2Count; - - pAd->RalinkCounters.TxAgg3MPDUCount += TxAggCnt1.field.AggSize3Count; - pAd->RalinkCounters.TxAgg4MPDUCount += TxAggCnt1.field.AggSize4Count; - pAd->RalinkCounters.TxAgg5MPDUCount += TxAggCnt2.field.AggSize5Count; - pAd->RalinkCounters.TxAgg6MPDUCount += TxAggCnt2.field.AggSize6Count; - - pAd->RalinkCounters.TxAgg7MPDUCount += TxAggCnt3.field.AggSize7Count; - pAd->RalinkCounters.TxAgg8MPDUCount += TxAggCnt3.field.AggSize8Count; - pAd->RalinkCounters.TxAgg9MPDUCount += TxAggCnt4.field.AggSize9Count; - pAd->RalinkCounters.TxAgg10MPDUCount += TxAggCnt4.field.AggSize10Count; - - pAd->RalinkCounters.TxAgg11MPDUCount += TxAggCnt5.field.AggSize11Count; - pAd->RalinkCounters.TxAgg12MPDUCount += TxAggCnt5.field.AggSize12Count; - pAd->RalinkCounters.TxAgg13MPDUCount += TxAggCnt6.field.AggSize13Count; - pAd->RalinkCounters.TxAgg14MPDUCount += TxAggCnt6.field.AggSize14Count; - - pAd->RalinkCounters.TxAgg15MPDUCount += TxAggCnt7.field.AggSize15Count; - pAd->RalinkCounters.TxAgg16MPDUCount += TxAggCnt7.field.AggSize16Count; - - // Calculate the transmitted A-MPDU count - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += TxAggCnt0.field.AggSize1Count; - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt0.field.AggSize2Count / 2); - - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize3Count / 3); - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize4Count / 4); - - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize5Count / 5); - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize6Count / 6); - - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize7Count / 7); - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize8Count / 8); - - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize9Count / 9); - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize10Count / 10); - - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize11Count / 11); - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize12Count / 12); - - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize13Count / 13); - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize14Count / 14); - - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize15Count / 15); - pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize16Count / 16); + pRalinkCounters->TxAggCount += TxAggCnt.field.AggTxCount; + pRalinkCounters->TxNonAggCount += TxAggCnt.field.NonAggTxCount; + pRalinkCounters->TxAgg1MPDUCount += + TxAggCnt0.field.AggSize1Count; + pRalinkCounters->TxAgg2MPDUCount += + TxAggCnt0.field.AggSize2Count; + + pRalinkCounters->TxAgg3MPDUCount += + TxAggCnt1.field.AggSize3Count; + pRalinkCounters->TxAgg4MPDUCount += + TxAggCnt1.field.AggSize4Count; + pRalinkCounters->TxAgg5MPDUCount += + TxAggCnt2.field.AggSize5Count; + pRalinkCounters->TxAgg6MPDUCount += + TxAggCnt2.field.AggSize6Count; + + pRalinkCounters->TxAgg7MPDUCount += + TxAggCnt3.field.AggSize7Count; + pRalinkCounters->TxAgg8MPDUCount += + TxAggCnt3.field.AggSize8Count; + pRalinkCounters->TxAgg9MPDUCount += + TxAggCnt4.field.AggSize9Count; + pRalinkCounters->TxAgg10MPDUCount += + TxAggCnt4.field.AggSize10Count; + + pRalinkCounters->TxAgg11MPDUCount += + TxAggCnt5.field.AggSize11Count; + pRalinkCounters->TxAgg12MPDUCount += + TxAggCnt5.field.AggSize12Count; + pRalinkCounters->TxAgg13MPDUCount += + TxAggCnt6.field.AggSize13Count; + pRalinkCounters->TxAgg14MPDUCount += + TxAggCnt6.field.AggSize14Count; + + pRalinkCounters->TxAgg15MPDUCount += + TxAggCnt7.field.AggSize15Count; + pRalinkCounters->TxAgg16MPDUCount += + TxAggCnt7.field.AggSize16Count; + + /* Calculate the transmitted A-MPDU count */ + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + TxAggCnt0.field.AggSize1Count; + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt0.field.AggSize2Count / 2); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt1.field.AggSize3Count / 3); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt1.field.AggSize4Count / 4); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt2.field.AggSize5Count / 5); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt2.field.AggSize6Count / 6); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt3.field.AggSize7Count / 7); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt3.field.AggSize8Count / 8); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt4.field.AggSize9Count / 9); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt4.field.AggSize10Count / 10); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt5.field.AggSize11Count / 11); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt5.field.AggSize12Count / 12); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt6.field.AggSize13Count / 13); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt6.field.AggSize14Count / 14); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt7.field.AggSize15Count / 15); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += + (TxAggCnt7.field.AggSize16Count / 16); } - - } - /* ======================================================================== @@ -2913,132 +2299,52 @@ VOID NICUpdateRawCounters( ======================================================================== */ -VOID NICResetFromError( - IN PRTMP_ADAPTER pAd) +void NICResetFromError(struct rt_rtmp_adapter *pAd) { - // Reset BBP (according to alex, reset ASIC will force reset BBP - // Therefore, skip the reset BBP - // RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x2); + /* Reset BBP (according to alex, reset ASIC will force reset BBP */ + /* Therefore, skip the reset BBP */ + /* RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x2); */ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); - // Remove ASIC from reset state + /* Remove ASIC from reset state */ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); NICInitializeAdapter(pAd, FALSE); NICInitAsicFromEEPROM(pAd); - // Switch to current channel, since during reset process, the connection should remains on. + /* Switch to current channel, since during reset process, the connection should remains on. */ AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); } -/* - ======================================================================== - - Routine Description: - erase 8051 firmware image in MAC ASIC - - Arguments: - Adapter Pointer to our adapter - - IRQL = PASSIVE_LEVEL - - ======================================================================== -*/ -VOID NICEraseFirmware( - IN PRTMP_ADAPTER pAd) +int NICLoadFirmware(struct rt_rtmp_adapter *pAd) { - ULONG i; - - for(i=0; ichipOps.loadFirmware) + status = pAd->chipOps.loadFirmware(pAd); -}/* End of NICEraseFirmware */ + return status; +} /* ======================================================================== Routine Description: - Load 8051 firmware RT2561.BIN file into MAC ASIC + erase 8051 firmware image in MAC ASIC Arguments: Adapter Pointer to our adapter - Return Value: - NDIS_STATUS_SUCCESS firmware image load ok - NDIS_STATUS_FAILURE image not found - IRQL = PASSIVE_LEVEL ======================================================================== */ -NDIS_STATUS NICLoadFirmware( - IN PRTMP_ADAPTER pAd) +void NICEraseFirmware(struct rt_rtmp_adapter *pAd) { - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - PUCHAR pFirmwareImage; - ULONG FileLength, Index; - //ULONG firm; - UINT32 MacReg = 0; -#ifdef RT2870 - UINT32 Version = (pAd->MACVersion >> 16); -#endif // RT2870 // - - pFirmwareImage = FirmwareImage; - FileLength = sizeof(FirmwareImage); -#ifdef RT2870 - // New 8k byte firmware size for RT3071/RT3072 - //printk("Usb Chip\n"); - if (FIRMWAREIMAGE_LENGTH == FIRMWAREIMAGE_MAX_LENGTH) - //The firmware image consists of two parts. One is the origianl and the other is the new. - //Use Second Part - { - if ((Version != 0x2860) && (Version != 0x2872) && (Version != 0x3070)) - { // Use Firmware V2. - //printk("KH:Use New Version,part2\n"); - pFirmwareImage = (PUCHAR)&FirmwareImage[FIRMWAREIMAGEV1_LENGTH]; - FileLength = FIRMWAREIMAGEV2_LENGTH; - } - else - { - //printk("KH:Use New Version,part1\n"); - pFirmwareImage = FirmwareImage; - FileLength = FIRMWAREIMAGEV1_LENGTH; - } - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("KH: bin file should be 8KB.\n")); - Status = NDIS_STATUS_FAILURE; - } - -#endif // RT2870 // - - RT28XX_WRITE_FIRMWARE(pAd, pFirmwareImage, FileLength); - - /* check if MCU is ready */ - Index = 0; - do - { - RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacReg); - - if (MacReg & 0x80) - break; - - RTMPusecDelay(1000); - } while (Index++ < 1000); - - if (Index > 1000) - { - Status = NDIS_STATUS_FAILURE; - DBGPRINT(RT_DEBUG_ERROR, ("NICLoadFirmware: MCU is not ready\n\n\n")); - } /* End of if */ - - DBGPRINT(RT_DEBUG_TRACE, - ("<=== %s (status=%d)\n", __func__, Status)); - return Status; -} /* End of NICLoadFirmware */ + if (pAd->chipOps.eraseFirmware) + pAd->chipOps.eraseFirmware(pAd); +} /* End of NICEraseFirmware */ /* ======================================================================== @@ -3061,59 +2367,11 @@ NDIS_STATUS NICLoadFirmware( ======================================================================== */ -NDIS_STATUS NICLoadRateSwitchingParams( - IN PRTMP_ADAPTER pAd) +int NICLoadRateSwitchingParams(struct rt_rtmp_adapter *pAd) { return NDIS_STATUS_SUCCESS; } -/* - ======================================================================== - - Routine Description: - if pSrc1 all zero with length Length, return 0. - If not all zero, return 1 - - Arguments: - pSrc1 - - Return Value: - 1: not all zero - 0: all zero - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -ULONG RTMPNotAllZero( - IN PVOID pSrc1, - IN ULONG Length) -{ - PUCHAR pMem1; - ULONG Index = 0; - - pMem1 = (PUCHAR) pSrc1; - - for (Index = 0; Index < Length; Index++) - { - if (pMem1[Index] != 0x0) - { - break; - } - } - - if (Index == Length) - { - return (0); - } - else - { - return (1); - } -} - /* ======================================================================== @@ -3135,27 +2393,23 @@ ULONG RTMPNotAllZero( ======================================================================== */ -ULONG RTMPCompareMemory( - IN PVOID pSrc1, - IN PVOID pSrc2, - IN ULONG Length) +unsigned long RTMPCompareMemory(void *pSrc1, void *pSrc2, unsigned long Length) { - PUCHAR pMem1; - PUCHAR pMem2; - ULONG Index = 0; + u8 *pMem1; + u8 *pMem2; + unsigned long Index = 0; - pMem1 = (PUCHAR) pSrc1; - pMem2 = (PUCHAR) pSrc2; + pMem1 = (u8 *)pSrc1; + pMem2 = (u8 *)pSrc2; - for (Index = 0; Index < Length; Index++) - { + for (Index = 0; Index < Length; Index++) { if (pMem1[Index] > pMem2[Index]) return (1); else if (pMem1[Index] < pMem2[Index]) return (2); } - // Equal + /* Equal */ return (0); } @@ -3179,37 +2433,18 @@ ULONG RTMPCompareMemory( ======================================================================== */ -VOID RTMPZeroMemory( - IN PVOID pSrc, - IN ULONG Length) +void RTMPZeroMemory(void *pSrc, unsigned long Length) { - PUCHAR pMem; - ULONG Index = 0; + u8 *pMem; + unsigned long Index = 0; - pMem = (PUCHAR) pSrc; + pMem = (u8 *)pSrc; - for (Index = 0; Index < Length; Index++) - { + for (Index = 0; Index < Length; Index++) { pMem[Index] = 0x00; } } -VOID RTMPFillMemory( - IN PVOID pSrc, - IN ULONG Length, - IN UCHAR Fill) -{ - PUCHAR pMem; - ULONG Index = 0; - - pMem = (PUCHAR) pSrc; - - for (Index = 0; Index < Length; Index++) - { - pMem[Index] = Fill; - } -} - /* ======================================================================== @@ -3231,22 +2466,18 @@ VOID RTMPFillMemory( ======================================================================== */ -VOID RTMPMoveMemory( - OUT PVOID pDest, - IN PVOID pSrc, - IN ULONG Length) +void RTMPMoveMemory(void *pDest, void *pSrc, unsigned long Length) { - PUCHAR pMem1; - PUCHAR pMem2; - UINT Index; + u8 *pMem1; + u8 *pMem2; + u32 Index; - ASSERT((Length==0) || (pDest && pSrc)); + ASSERT((Length == 0) || (pDest && pSrc)); - pMem1 = (PUCHAR) pDest; - pMem2 = (PUCHAR) pSrc; + pMem1 = (u8 *)pDest; + pMem2 = (u8 *)pSrc; - for (Index = 0; Index < Length; Index++) - { + for (Index = 0; Index < Length; Index++) { pMem1[Index] = pMem2[Index]; } } @@ -3269,17 +2500,16 @@ VOID RTMPMoveMemory( ======================================================================== */ -VOID UserCfgInit( - IN PRTMP_ADAPTER pAd) +void UserCfgInit(struct rt_rtmp_adapter *pAd) { - UINT key_index, bss_index; + u32 key_index, bss_index; DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit\n")); - // - // part I. intialize common configuration - // -#ifdef RT2870 + /* */ + /* part I. intialize common configuration */ + /* */ +#ifdef RTMP_MAC_USB pAd->BulkOutReq = 0; pAd->BulkOutComplete = 0; @@ -3289,72 +2519,71 @@ VOID UserCfgInit( pAd->BulkInComplete = 0; pAd->BulkInCompleteFail = 0; - //pAd->QuickTimerP = 100; - //pAd->TurnAggrBulkInCount = 0; + /*pAd->QuickTimerP = 100; */ + /*pAd->TurnAggrBulkInCount = 0; */ pAd->bUsbTxBulkAggre = 0; - // init as unsed value to ensure driver will set to MCU once. - pAd->LedIndicatorStregth = 0xFF; + /* init as unsed value to ensure driver will set to MCU once. */ + pAd->LedIndicatorStrength = 0xFF; pAd->CommonCfg.MaxPktOneTxBulk = 2; pAd->CommonCfg.TxBulkFactor = 1; - pAd->CommonCfg.RxBulkFactor =1; + pAd->CommonCfg.RxBulkFactor = 1; - pAd->CommonCfg.TxPower = 100; //mW + pAd->CommonCfg.TxPower = 100; /*mW */ - NdisZeroMemory(&pAd->CommonCfg.IOTestParm, sizeof(pAd->CommonCfg.IOTestParm)); -#endif // RT2870 // + NdisZeroMemory(&pAd->CommonCfg.IOTestParm, + sizeof(pAd->CommonCfg.IOTestParm)); +#endif /* RTMP_MAC_USB // */ - for(key_index=0; key_indexSharedKey[bss_index][key_index].KeyLen = 0; - pAd->SharedKey[bss_index][key_index].CipherAlg = CIPHER_NONE; + pAd->SharedKey[bss_index][key_index].CipherAlg = + CIPHER_NONE; } } -#ifdef RT2870 pAd->EepromAccess = FALSE; -#endif + pAd->Antenna.word = 0; pAd->CommonCfg.BBPCurrentBW = BW_20; pAd->LedCntl.word = 0; -#ifdef RT2860 - pAd->LedIndicatorStregth = 0; +#ifdef RTMP_MAC_PCI + pAd->LedIndicatorStrength = 0; pAd->RLnkCtrlOffset = 0; pAd->HostLnkCtrlOffset = 0; + pAd->StaCfg.PSControl.field.EnableNewPS = TRUE; pAd->CheckDmaBusyCount = 0; -#endif +#endif /* RTMP_MAC_PCI // */ - pAd->bAutoTxAgcA = FALSE; // Default is OFF - pAd->bAutoTxAgcG = FALSE; // Default is OFF + pAd->bAutoTxAgcA = FALSE; /* Default is OFF */ + pAd->bAutoTxAgcG = FALSE; /* Default is OFF */ pAd->RfIcType = RFIC_2820; - // Init timer for reset complete event + /* Init timer for reset complete event */ pAd->CommonCfg.CentralChannel = 1; pAd->bForcePrintTX = FALSE; pAd->bForcePrintRX = FALSE; pAd->bStaFifoTest = FALSE; pAd->bProtectionTest = FALSE; - pAd->bHCCATest = FALSE; - pAd->bGenOneHCCA = FALSE; - pAd->CommonCfg.Dsifs = 10; // in units of usec - pAd->CommonCfg.TxPower = 100; //mW - pAd->CommonCfg.TxPowerPercentage = 0xffffffff; // AUTO - pAd->CommonCfg.TxPowerDefault = 0xffffffff; // AUTO - pAd->CommonCfg.TxPreamble = Rt802_11PreambleAuto; // use Long preamble on TX by defaut + pAd->CommonCfg.Dsifs = 10; /* in units of usec */ + pAd->CommonCfg.TxPower = 100; /*mW */ + pAd->CommonCfg.TxPowerPercentage = 0xffffffff; /* AUTO */ + pAd->CommonCfg.TxPowerDefault = 0xffffffff; /* AUTO */ + pAd->CommonCfg.TxPreamble = Rt802_11PreambleAuto; /* use Long preamble on TX by defaut */ pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; pAd->CommonCfg.RtsThreshold = 2347; pAd->CommonCfg.FragmentThreshold = 2346; - pAd->CommonCfg.UseBGProtection = 0; // 0: AUTO - pAd->CommonCfg.bEnableTxBurst = TRUE; //0; - pAd->CommonCfg.PhyMode = 0xff; // unknown + pAd->CommonCfg.UseBGProtection = 0; /* 0: AUTO */ + pAd->CommonCfg.bEnableTxBurst = TRUE; /*0; */ + pAd->CommonCfg.PhyMode = 0xff; /* unknown */ pAd->CommonCfg.BandState = UNKNOWN_BAND; pAd->CommonCfg.RadarDetect.CSPeriod = 10; pAd->CommonCfg.RadarDetect.CSCount = 0; pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE; + pAd->CommonCfg.RadarDetect.ChMovingTime = 65; pAd->CommonCfg.RadarDetect.LongPulseRadarTh = 3; pAd->CommonCfg.bAPSDCapable = FALSE; @@ -3367,18 +2596,22 @@ VOID UserCfgInit( NdisZeroMemory(&pAd->BeaconTxWI, sizeof(pAd->BeaconTxWI)); - NdisZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability)); + NdisZeroMemory(&pAd->CommonCfg.HtCapability, + sizeof(pAd->CommonCfg.HtCapability)); pAd->HTCEnable = FALSE; pAd->bBroadComHT = FALSE; pAd->CommonCfg.bRdg = FALSE; - NdisZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo)); + NdisZeroMemory(&pAd->CommonCfg.AddHTInfo, + sizeof(pAd->CommonCfg.AddHTInfo)); pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; pAd->CommonCfg.BACapability.field.MpduDensity = 0; pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; - pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; //32; - pAd->CommonCfg.BACapability.field.TxBAWinLimit = 64; //32; - DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit. BACapability = 0x%x\n", pAd->CommonCfg.BACapability.word)); + pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; /*32; */ + pAd->CommonCfg.BACapability.field.TxBAWinLimit = 64; /*32; */ + DBGPRINT(RT_DEBUG_TRACE, + ("--> UserCfgInit. BACapability = 0x%x\n", + pAd->CommonCfg.BACapability.word)); pAd->CommonCfg.BACapability.field.AutoBA = FALSE; BATableInit(pAd, &pAd->BATable); @@ -3386,28 +2619,35 @@ VOID UserCfgInit( pAd->CommonCfg.bExtChannelSwitchAnnouncement = 1; pAd->CommonCfg.bHTProtect = 1; pAd->CommonCfg.bMIMOPSEnable = TRUE; + /*2008/11/05:KH add to support Antenna power-saving of AP<-- */ + pAd->CommonCfg.bGreenAPEnable = FALSE; + /*2008/11/05:KH add to support Antenna power-saving of AP--> */ pAd->CommonCfg.bBADecline = FALSE; pAd->CommonCfg.bDisableReordering = FALSE; - pAd->CommonCfg.TxBASize = 7; + if (pAd->MACVersion == 0x28720200) { + pAd->CommonCfg.TxBASize = 13; /*by Jerry recommend */ + } else { + pAd->CommonCfg.TxBASize = 7; + } pAd->CommonCfg.REGBACapability.word = pAd->CommonCfg.BACapability.word; - //pAd->CommonCfg.HTPhyMode.field.BW = BW_20; - //pAd->CommonCfg.HTPhyMode.field.MCS = MCS_AUTO; - //pAd->CommonCfg.HTPhyMode.field.ShortGI = GI_800; - //pAd->CommonCfg.HTPhyMode.field.STBC = STBC_NONE; + /*pAd->CommonCfg.HTPhyMode.field.BW = BW_20; */ + /*pAd->CommonCfg.HTPhyMode.field.MCS = MCS_AUTO; */ + /*pAd->CommonCfg.HTPhyMode.field.ShortGI = GI_800; */ + /*pAd->CommonCfg.HTPhyMode.field.STBC = STBC_NONE; */ pAd->CommonCfg.TxRate = RATE_6; pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_RATE_6; pAd->CommonCfg.MlmeTransmit.field.BW = BW_20; pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; - pAd->CommonCfg.BeaconPeriod = 100; // in mSec + pAd->CommonCfg.BeaconPeriod = 100; /* in mSec */ - // - // part II. intialize STA specific configuration - // + /* */ + /* part II. intialize STA specific configuration */ + /* */ { RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_DIRECT); RX_FILTER_CLEAR_FLAG(pAd, fRX_FILTER_ACCEPT_MULTICAST); @@ -3422,22 +2662,23 @@ VOID UserCfgInit( pAd->StaCfg.bMixCipher = FALSE; pAd->StaCfg.DefaultKeyId = 0; - // 802.1x port control + /* 802.1x port control */ pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; pAd->StaCfg.LastMicErrorTime = 0; - pAd->StaCfg.MicErrCnt = 0; - pAd->StaCfg.bBlockAssoc = FALSE; - pAd->StaCfg.WpaState = SS_NOTUSE; + pAd->StaCfg.MicErrCnt = 0; + pAd->StaCfg.bBlockAssoc = FALSE; + pAd->StaCfg.WpaState = SS_NOTUSE; - pAd->CommonCfg.NdisRadioStateOff = FALSE; // New to support microsoft disable radio with OID command + pAd->CommonCfg.NdisRadioStateOff = FALSE; /* New to support microsoft disable radio with OID command */ pAd->StaCfg.RssiTrigger = 0; - NdisZeroMemory(&pAd->StaCfg.RssiSample, sizeof(RSSI_SAMPLE)); - pAd->StaCfg.RssiTriggerMode = RSSI_TRIGGERED_UPON_BELOW_THRESHOLD; + NdisZeroMemory(&pAd->StaCfg.RssiSample, sizeof(struct rt_rssi_sample)); + pAd->StaCfg.RssiTriggerMode = + RSSI_TRIGGERED_UPON_BELOW_THRESHOLD; pAd->StaCfg.AtimWin = 0; - pAd->StaCfg.DefaultListenCount = 3;//default listen count; - pAd->StaCfg.BssType = BSS_INFRA; // BSS_INFRA or BSS_ADHOC or BSS_MONITOR + pAd->StaCfg.DefaultListenCount = 3; /*default listen count; */ + pAd->StaCfg.BssType = BSS_INFRA; /* BSS_INFRA or BSS_ADHOC or BSS_MONITOR */ pAd->StaCfg.bScanReqIsFromWebUI = FALSE; OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); @@ -3446,158 +2687,174 @@ VOID UserCfgInit( pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; } - // global variables mXXXX used in MAC protocol state machines +#ifdef PCIE_PS_SUPPORT + pAd->brt30xxBanMcuCmd = FALSE; + pAd->b3090ESpecialChip = FALSE; +/*KH Debug:the following must be removed */ + pAd->StaCfg.PSControl.field.rt30xxPowerMode = 3; + pAd->StaCfg.PSControl.field.rt30xxForceASPMTest = 0; + pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM = 1; +#endif /* PCIE_PS_SUPPORT // */ + + /* global variables mXXXX used in MAC protocol state machines */ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); - // PHY specification - pAd->CommonCfg.PhyMode = PHY_11BG_MIXED; // default PHY mode - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); // CCK use LONG preamble + /* PHY specification */ + pAd->CommonCfg.PhyMode = PHY_11BG_MIXED; /* default PHY mode */ + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); /* CCK use long preamble */ { - // user desired power mode + /* user desired power mode */ pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; pAd->StaCfg.bWindowsACCAMEnable = FALSE; - RTMPInitTimer(pAd, &pAd->StaCfg.StaQuickResponeForRateUpTimer, GET_TIMER_FUNCTION(StaQuickResponeForRateUpExec), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->StaCfg.StaQuickResponeForRateUpTimer, + GET_TIMER_FUNCTION(StaQuickResponeForRateUpExec), + pAd, FALSE); pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; - // Patch for Ndtest + /* Patch for Ndtest */ pAd->StaCfg.ScanCnt = 0; - // CCX 2.0 control flag init - pAd->StaCfg.CCXEnable = FALSE; - pAd->StaCfg.CCXReqType = MSRN_TYPE_UNUSED; - pAd->StaCfg.CCXQosECWMin = 4; - pAd->StaCfg.CCXQosECWMax = 10; + pAd->StaCfg.bHwRadio = TRUE; /* Default Hardware Radio status is On */ + pAd->StaCfg.bSwRadio = TRUE; /* Default Software Radio status is On */ + pAd->StaCfg.bRadio = TRUE; /* bHwRadio && bSwRadio */ + pAd->StaCfg.bHardwareRadio = FALSE; /* Default is OFF */ + pAd->StaCfg.bShowHiddenSSID = FALSE; /* Default no show */ - pAd->StaCfg.bHwRadio = TRUE; // Default Hardware Radio status is On - pAd->StaCfg.bSwRadio = TRUE; // Default Software Radio status is On - pAd->StaCfg.bRadio = TRUE; // bHwRadio && bSwRadio - pAd->StaCfg.bHardwareRadio = FALSE; // Default is OFF - pAd->StaCfg.bShowHiddenSSID = FALSE; // Default no show - - // Nitro mode control + /* Nitro mode control */ pAd->StaCfg.bAutoReconnect = TRUE; - // Save the init time as last scan time, the system should do scan after 2 seconds. - // This patch is for driver wake up from standby mode, system will do scan right away. - pAd->StaCfg.LastScanTime = 0; - NdisZeroMemory(pAd->nickname, IW_ESSID_MAX_SIZE+1); - sprintf(pAd->nickname, "%s", STA_NIC_DEVICE_NAME); - RTMPInitTimer(pAd, &pAd->StaCfg.WpaDisassocAndBlockAssocTimer, GET_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc), pAd, FALSE); + /* Save the init time as last scan time, the system should do scan after 2 seconds. */ + /* This patch is for driver wake up from standby mode, system will do scan right away. */ + NdisGetSystemUpTime(&pAd->StaCfg.LastScanTime); + if (pAd->StaCfg.LastScanTime > 10 * OS_HZ) + pAd->StaCfg.LastScanTime -= (10 * OS_HZ); + + NdisZeroMemory(pAd->nickname, IW_ESSID_MAX_SIZE + 1); +#ifdef RTMP_MAC_PCI + sprintf((char *)pAd->nickname, "RT2860STA"); +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + sprintf((char *)pAd->nickname, "RT2870STA"); +#endif /* RTMP_MAC_USB // */ + RTMPInitTimer(pAd, &pAd->StaCfg.WpaDisassocAndBlockAssocTimer, + GET_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc), + pAd, FALSE); pAd->StaCfg.IEEE8021X = FALSE; pAd->StaCfg.IEEE8021x_required_keys = FALSE; pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; + pAd->StaCfg.bRSN_IE_FromWpaSupplicant = FALSE; pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; + + NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); + + pAd->StaCfg.bAutoConnectByBssid = FALSE; + pAd->StaCfg.BeaconLostTime = BEACON_LOST_TIME; + NdisZeroMemory(pAd->StaCfg.WpaPassPhrase, 64); + pAd->StaCfg.WpaPassPhraseLen = 0; + pAd->StaCfg.bAutoRoaming = FALSE; + pAd->StaCfg.bForceTxBurst = FALSE; } - // Default for extra information is not valid + /* Default for extra information is not valid */ pAd->ExtraInfo = EXTRA_INFO_CLEAR; - // Default Config change flag + /* Default Config change flag */ pAd->bConfigChanged = FALSE; - // - // part III. AP configurations - // - + /* */ + /* part III. AP configurations */ + /* */ - // - // part IV. others - // - // dynamic BBP R66:sensibity tuning to overcome background noise - pAd->BbpTuning.bEnable = TRUE; + /* */ + /* part IV. others */ + /* */ + /* dynamic BBP R66:sensibity tuning to overcome background noise */ + pAd->BbpTuning.bEnable = TRUE; pAd->BbpTuning.FalseCcaLowerThreshold = 100; pAd->BbpTuning.FalseCcaUpperThreshold = 512; - pAd->BbpTuning.R66Delta = 4; + pAd->BbpTuning.R66Delta = 4; pAd->Mlme.bEnableAutoAntennaCheck = TRUE; - // - // Also initial R66CurrentValue, RTUSBResumeMsduTransmission might use this value. - // if not initial this value, the default value will be 0. - // + /* */ + /* Also initial R66CurrentValue, RTUSBResumeMsduTransmission might use this value. */ + /* if not initial this value, the default value will be 0. */ + /* */ pAd->BbpTuning.R66CurrentValue = 0x38; pAd->Bbp94 = BBPR94_DEFAULT; pAd->BbpForCCK = FALSE; - // initialize MAC table and allocate spin lock - NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE)); + /* Default is FALSE for test bit 1 */ + /*pAd->bTest1 = FALSE; */ + + /* initialize MAC table and allocate spin lock */ + NdisZeroMemory(&pAd->MacTab, sizeof(struct rt_mac_table)); InitializeQueueHeader(&pAd->MacTab.McastPsQueue); NdisAllocateSpinLock(&pAd->MacTabLock); + /*RTMPInitTimer(pAd, &pAd->RECBATimer, RECBATimerTimeout, pAd, TRUE); */ + /*RTMPSetTimer(&pAd->RECBATimer, REORDER_EXEC_INTV); */ + pAd->CommonCfg.bWiFiTest = FALSE; -#ifdef RT2860 +#ifdef RTMP_MAC_PCI pAd->bPCIclkOff = FALSE; +#endif /* RTMP_MAC_PCI // */ RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); -#endif DBGPRINT(RT_DEBUG_TRACE, ("<-- UserCfgInit\n")); } -// IRQL = PASSIVE_LEVEL -UCHAR BtoH(char ch) +/* IRQL = PASSIVE_LEVEL */ +u8 BtoH(char ch) { - if (ch >= '0' && ch <= '9') return (ch - '0'); // Handle numerals - if (ch >= 'A' && ch <= 'F') return (ch - 'A' + 0xA); // Handle capitol hex digits - if (ch >= 'a' && ch <= 'f') return (ch - 'a' + 0xA); // Handle small hex digits - return(255); + if (ch >= '0' && ch <= '9') + return (ch - '0'); /* Handle numerals */ + if (ch >= 'A' && ch <= 'F') + return (ch - 'A' + 0xA); /* Handle capitol hex digits */ + if (ch >= 'a' && ch <= 'f') + return (ch - 'a' + 0xA); /* Handle small hex digits */ + return (255); } -// -// FUNCTION: AtoH(char *, UCHAR *, int) -// -// PURPOSE: Converts ascii string to network order hex -// -// PARAMETERS: -// src - pointer to input ascii string -// dest - pointer to output hex -// destlen - size of dest -// -// COMMENTS: -// -// 2 ascii bytes make a hex byte so must put 1st ascii byte of pair -// into upper nibble and 2nd ascii byte of pair into lower nibble. -// -// IRQL = PASSIVE_LEVEL - -void AtoH(char * src, UCHAR * dest, int destlen) +/* */ +/* FUNCTION: AtoH(char *, u8 *, int) */ +/* */ +/* PURPOSE: Converts ascii string to network order hex */ +/* */ +/* PARAMETERS: */ +/* src - pointer to input ascii string */ +/* dest - pointer to output hex */ +/* destlen - size of dest */ +/* */ +/* COMMENTS: */ +/* */ +/* 2 ascii bytes make a hex byte so must put 1st ascii byte of pair */ +/* into upper nibble and 2nd ascii byte of pair into lower nibble. */ +/* */ +/* IRQL = PASSIVE_LEVEL */ + +void AtoH(char *src, u8 *dest, int destlen) { - char * srcptr; - PUCHAR destTemp; + char *srcptr; + u8 *destTemp; srcptr = src; - destTemp = (PUCHAR) dest; + destTemp = (u8 *)dest; - while(destlen--) - { - *destTemp = BtoH(*srcptr++) << 4; // Put 1st ascii byte in upper nibble. - *destTemp += BtoH(*srcptr++); // Add 2nd ascii byte to above. + while (destlen--) { + *destTemp = BtoH(*srcptr++) << 4; /* Put 1st ascii byte in upper nibble. */ + *destTemp += BtoH(*srcptr++); /* Add 2nd ascii byte to above. */ destTemp++; } } -VOID RTMPPatchMacBbpBug( - IN PRTMP_ADAPTER pAd) -{ - ULONG Index; - - // Initialize BBP register to default value - for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, (UCHAR)BBPRegTable[Index].Value); - } - - // Initialize RF register to default value - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - - // Re-init BBP register from EEPROM value - NICInitAsicFromEEPROM(pAd); -} +/*+++Mark by shiang, not use now, need to remove after confirm */ +/*---Mark by shiang, not use now, need to remove after confirm */ /* ======================================================================== @@ -3618,29 +2875,26 @@ VOID RTMPPatchMacBbpBug( ======================================================================== */ -VOID RTMPInitTimer( - IN PRTMP_ADAPTER pAd, - IN PRALINK_TIMER_STRUCT pTimer, - IN PVOID pTimerFunc, - IN PVOID pData, - IN BOOLEAN Repeat) +void RTMPInitTimer(struct rt_rtmp_adapter *pAd, + struct rt_ralink_timer *pTimer, + void *pTimerFunc, void *pData, IN BOOLEAN Repeat) { - // - // Set Valid to TRUE for later used. - // It will crash if we cancel a timer or set a timer - // that we haven't initialize before. - // - pTimer->Valid = TRUE; + /* */ + /* Set Valid to TRUE for later used. */ + /* It will crash if we cancel a timer or set a timer */ + /* that we haven't initialize before. */ + /* */ + pTimer->Valid = TRUE; pTimer->PeriodicType = Repeat; - pTimer->State = FALSE; - pTimer->cookie = (ULONG) pData; + pTimer->State = FALSE; + pTimer->cookie = (unsigned long)pData; -#ifdef RT2870 +#ifdef RTMP_TIMER_TASK_SUPPORT pTimer->pAd = pAd; -#endif // RT2870 // +#endif /* RTMP_TIMER_TASK_SUPPORT // */ - RTMP_OS_Init_Timer(pAd, &pTimer->TimerObj, pTimerFunc, (PVOID) pTimer); + RTMP_OS_Init_Timer(pAd, &pTimer->TimerObj, pTimerFunc, (void *)pTimer); } /* @@ -3661,32 +2915,23 @@ VOID RTMPInitTimer( ======================================================================== */ -VOID RTMPSetTimer( - IN PRALINK_TIMER_STRUCT pTimer, - IN ULONG Value) +void RTMPSetTimer(struct rt_ralink_timer *pTimer, unsigned long Value) { - if (pTimer->Valid) - { + if (pTimer->Valid) { pTimer->TimerValue = Value; - pTimer->State = FALSE; - if (pTimer->PeriodicType == TRUE) - { + pTimer->State = FALSE; + if (pTimer->PeriodicType == TRUE) { pTimer->Repeat = TRUE; RTMP_SetPeriodicTimer(&pTimer->TimerObj, Value); - } - else - { + } else { pTimer->Repeat = FALSE; RTMP_OS_Add_Timer(&pTimer->TimerObj, Value); } - } - else - { + } else { DBGPRINT_ERR(("RTMPSetTimer failed, Timer hasn't been initialize!\n")); } } - /* ======================================================================== @@ -3705,28 +2950,20 @@ VOID RTMPSetTimer( ======================================================================== */ -VOID RTMPModTimer( - IN PRALINK_TIMER_STRUCT pTimer, - IN ULONG Value) +void RTMPModTimer(struct rt_ralink_timer *pTimer, unsigned long Value) { - BOOLEAN Cancel; + BOOLEAN Cancel; - if (pTimer->Valid) - { + if (pTimer->Valid) { pTimer->TimerValue = Value; - pTimer->State = FALSE; - if (pTimer->PeriodicType == TRUE) - { + pTimer->State = FALSE; + if (pTimer->PeriodicType == TRUE) { RTMPCancelTimer(pTimer, &Cancel); RTMPSetTimer(pTimer, Value); - } - else - { + } else { RTMP_OS_Mod_Timer(&pTimer->TimerObj, Value); } - } - else - { + } else { DBGPRINT_ERR(("RTMPModTimer failed, Timer hasn't been initialize!\n")); } } @@ -3752,32 +2989,23 @@ VOID RTMPModTimer( ======================================================================== */ -VOID RTMPCancelTimer( - IN PRALINK_TIMER_STRUCT pTimer, - OUT BOOLEAN *pCancelled) +void RTMPCancelTimer(struct rt_ralink_timer *pTimer, OUT BOOLEAN * pCancelled) { - if (pTimer->Valid) - { + if (pTimer->Valid) { if (pTimer->State == FALSE) pTimer->Repeat = FALSE; - RTMP_OS_Del_Timer(&pTimer->TimerObj, pCancelled); + + RTMP_OS_Del_Timer(&pTimer->TimerObj, pCancelled); if (*pCancelled == TRUE) pTimer->State = TRUE; -#ifdef RT2870 - // We need to go-through the TimerQ to findout this timer handler and remove it if - // it's still waiting for execution. - - RT2870_TimerQ_Remove(pTimer->pAd, pTimer); -#endif // RT2870 // - } - else - { - // - // NdisMCancelTimer just canced the timer and not mean release the timer. - // And don't set the "Valid" to False. So that we can use this timer again. - // +#ifdef RTMP_TIMER_TASK_SUPPORT + /* We need to go-through the TimerQ to findout this timer handler and remove it if */ + /* it's still waiting for execution. */ + RtmpTimerQRemove(pTimer->pAd, pTimer); +#endif /* RTMP_TIMER_TASK_SUPPORT // */ + } else { DBGPRINT_ERR(("RTMPCancelTimer failed, Timer hasn't been initialize!\n")); } } @@ -3802,64 +3030,64 @@ VOID RTMPCancelTimer( ======================================================================== */ -VOID RTMPSetLED( - IN PRTMP_ADAPTER pAd, - IN UCHAR Status) +void RTMPSetLED(struct rt_rtmp_adapter *pAd, u8 Status) { - //ULONG data; - UCHAR HighByte = 0; - UCHAR LowByte; - - LowByte = pAd->LedCntl.field.LedMode&0x7f; - switch (Status) - { - case LED_LINK_DOWN: - HighByte = 0x20; - AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); - pAd->LedIndicatorStregth = 0; - break; - case LED_LINK_UP: - if (pAd->CommonCfg.Channel > 14) - HighByte = 0xa0; - else - HighByte = 0x60; - AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); - break; - case LED_RADIO_ON: - HighByte = 0x20; - AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); - break; - case LED_HALT: - LowByte = 0; // Driver sets MAC register and MAC controls LED - case LED_RADIO_OFF: - HighByte = 0; - AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); - break; - case LED_WPS: - HighByte = 0x10; - AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); - break; - case LED_ON_SITE_SURVEY: - HighByte = 0x08; - AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); - break; - case LED_POWER_UP: - HighByte = 0x04; - AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); - break; - default: - DBGPRINT(RT_DEBUG_WARN, ("RTMPSetLED::Unknown Status %d\n", Status)); - break; - } - - // - // Keep LED status for LED SiteSurvey mode. - // After SiteSurvey, we will set the LED mode to previous status. - // + /*unsigned long data; */ + u8 HighByte = 0; + u8 LowByte; + + LowByte = pAd->LedCntl.field.LedMode & 0x7f; + switch (Status) { + case LED_LINK_DOWN: + HighByte = 0x20; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + pAd->LedIndicatorStrength = 0; + break; + case LED_LINK_UP: + if (pAd->CommonCfg.Channel > 14) + HighByte = 0xa0; + else + HighByte = 0x60; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_RADIO_ON: + HighByte = 0x20; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_HALT: + LowByte = 0; /* Driver sets MAC register and MAC controls LED */ + case LED_RADIO_OFF: + HighByte = 0; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_WPS: + HighByte = 0x10; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_ON_SITE_SURVEY: + HighByte = 0x08; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_POWER_UP: + HighByte = 0x04; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + default: + DBGPRINT(RT_DEBUG_WARN, + ("RTMPSetLED::Unknown Status %d\n", Status)); + break; + } + + /* */ + /* Keep LED status for LED SiteSurvey mode. */ + /* After SiteSurvey, we will set the LED mode to previous status. */ + /* */ if ((Status != LED_ON_SITE_SURVEY) && (Status != LED_POWER_UP)) pAd->LedStatus = Status; - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetLED::Mode=%d,HighByte=0x%02x,LowByte=0x%02x\n", pAd->LedCntl.field.LedMode, HighByte, LowByte)); + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPSetLED::Mode=%d,HighByte=0x%02x,LowByte=0x%02x\n", + pAd->LedCntl.field.LedMode, HighByte, LowByte)); } /* @@ -3889,40 +3117,32 @@ VOID RTMPSetLED( > -57 Excellent ======================================================================== */ -VOID RTMPSetSignalLED( - IN PRTMP_ADAPTER pAd, - IN NDIS_802_11_RSSI Dbm) +void RTMPSetSignalLED(struct rt_rtmp_adapter *pAd, IN NDIS_802_11_RSSI Dbm) { - UCHAR nLed = 0; - - // - // if not Signal Stregth, then do nothing. - // - if (pAd->LedCntl.field.LedMode != LED_MODE_SIGNAL_STREGTH) - { - return; - } - - if (Dbm <= -90) - nLed = 0; - else if (Dbm <= -81) - nLed = 1; - else if (Dbm <= -71) - nLed = 3; - else if (Dbm <= -67) - nLed = 7; - else if (Dbm <= -57) - nLed = 15; - else - nLed = 31; + u8 nLed = 0; + + if (pAd->LedCntl.field.LedMode == LED_MODE_SIGNAL_STREGTH) { + if (Dbm <= -90) + nLed = 0; + else if (Dbm <= -81) + nLed = 1; + else if (Dbm <= -71) + nLed = 3; + else if (Dbm <= -67) + nLed = 7; + else if (Dbm <= -57) + nLed = 15; + else + nLed = 31; - // - // Update Signal Stregth to firmware if changed. - // - if (pAd->LedIndicatorStregth != nLed) - { - AsicSendCommandToMcu(pAd, 0x51, 0xff, nLed, pAd->LedCntl.field.Polarity); - pAd->LedIndicatorStregth = nLed; + /* */ + /* Update Signal Stregth to firmware if changed. */ + /* */ + if (pAd->LedIndicatorStrength != nLed) { + AsicSendCommandToMcu(pAd, 0x51, 0xff, nLed, + pAd->LedCntl.field.Polarity); + pAd->LedIndicatorStrength = nLed; + } } } @@ -3944,29 +3164,394 @@ VOID RTMPSetSignalLED( Before Enable RX, make sure you have enabled Interrupt. ======================================================================== */ -VOID RTMPEnableRxTx( - IN PRTMP_ADAPTER pAd) +void RTMPEnableRxTx(struct rt_rtmp_adapter *pAd) { +/* WPDMA_GLO_CFG_STRUC GloCfg; */ +/* unsigned long i = 0; */ + u32 rx_filter_flag; + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPEnableRxTx\n")); - // Enable Rx DMA. + /* Enable Rx DMA. */ RT28XXDMAEnable(pAd); - // enable RX of MAC block - if (pAd->OpMode == OPMODE_AP) + /* enable RX of MAC block */ + if (pAd->OpMode == OPMODE_AP) { + rx_filter_flag = APNORMAL; + + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); /* enable RX of DMA block */ + } else { + if (pAd->CommonCfg.PSPXlink) + rx_filter_flag = PSPXLINK; + else + rx_filter_flag = STANORMAL; /* Staion not drop control frame will fail WiFi Certification. */ + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); + } + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc); + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPEnableRxTx\n")); +} + +/*+++Add by shiang, move from os/linux/rt_main_dev.c */ +void CfgInitHook(struct rt_rtmp_adapter *pAd) +{ + pAd->bBroadComHT = TRUE; +} + +int rt28xx_init(struct rt_rtmp_adapter *pAd, + char *pDefaultMac, char *pHostName) +{ + u32 index; + u8 TmpPhy; + int Status; + u32 MacCsr0 = 0; + +#ifdef RTMP_MAC_PCI { - UINT32 rx_filter_flag = APNORMAL; + /* If dirver doesn't wake up firmware here, */ + /* NICLoadFirmware will hang forever when interface is up again. */ + /* RT2860 PCI */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) && + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { + AUTO_WAKEUP_STRUC AutoWakeupCfg; + AsicForceWakeup(pAd, TRUE); + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, + AutoWakeupCfg.word); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + } + } +#endif /* RTMP_MAC_PCI // */ + + /* reset Adapter flags */ + RTMP_CLEAR_FLAGS(pAd); + + /* Init BssTab & ChannelInfo tabbles for auto channel select. */ + + /* Allocate BA Reordering memory */ + ba_reordering_resource_init(pAd, MAX_REORDERING_MPDU_NUM); + + /* Make sure MAC gets ready. */ + index = 0; + do { + RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); + pAd->MACVersion = MacCsr0; + + if ((pAd->MACVersion != 0x00) + && (pAd->MACVersion != 0xFFFFFFFF)) + break; + + RTMPusecDelay(10); + } while (index++ < 100); + DBGPRINT(RT_DEBUG_TRACE, + ("MAC_CSR0 [ Ver:Rev=0x%08x]\n", pAd->MACVersion)); + +#ifdef RTMP_MAC_PCI +#ifdef PCIE_PS_SUPPORT + /*Iverson patch PCIE L1 issue to make sure that driver can be read,write ,BBP and RF register at pcie L.1 level */ + if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) + && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { + RTMP_IO_READ32(pAd, AUX_CTRL, &MacCsr0); + MacCsr0 |= 0x402; + RTMP_IO_WRITE32(pAd, AUX_CTRL, MacCsr0); + DBGPRINT(RT_DEBUG_TRACE, ("AUX_CTRL = 0x%x\n", MacCsr0)); + } +#endif /* PCIE_PS_SUPPORT // */ + + /* To fix driver disable/enable hang issue when radio off */ + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x2); +#endif /* RTMP_MAC_PCI // */ + + /* Disable DMA */ + RT28XXDMADisable(pAd); + + /* Load 8051 firmware */ + Status = NICLoadFirmware(pAd); + if (Status != NDIS_STATUS_SUCCESS) { + DBGPRINT_ERR(("NICLoadFirmware failed, Status[=0x%08x]\n", + Status)); + goto err1; + } + + NICLoadRateSwitchingParams(pAd); + + /* Disable interrupts here which is as soon as possible */ + /* This statement should never be true. We might consider to remove it later */ +#ifdef RTMP_MAC_PCI + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) { + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + } +#endif /* RTMP_MAC_PCI // */ + + Status = RTMPAllocTxRxRingMemory(pAd); + if (Status != NDIS_STATUS_SUCCESS) { + DBGPRINT_ERR(("RTMPAllocDMAMemory failed, Status[=0x%08x]\n", + Status)); + goto err1; + } + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + + /* initialize MLME */ + /* */ + + Status = RtmpMgmtTaskInit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + goto err2; + + Status = MlmeInit(pAd); + if (Status != NDIS_STATUS_SUCCESS) { + DBGPRINT_ERR(("MlmeInit failed, Status[=0x%08x]\n", Status)); + goto err2; + } + /* Initialize pAd->StaCfg, pAd->ApCfg, pAd->CommonCfg to manufacture default */ + /* */ + UserCfgInit(pAd); + Status = RtmpNetTaskInit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + goto err3; + +/* COPY_MAC_ADDR(pAd->ApCfg.MBSSID[apidx].Bssid, netif->hwaddr); */ +/* pAd->bForcePrintTX = TRUE; */ + + CfgInitHook(pAd); + + NdisAllocateSpinLock(&pAd->MacTabLock); + MeasureReqTabInit(pAd); + TpcReqTabInit(pAd); - RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); // enable RX of DMA block + /* */ + /* Init the hardware, we need to init asic before read registry, otherwise mac register will be reset */ + /* */ + Status = NICInitializeAdapter(pAd, TRUE); + if (Status != NDIS_STATUS_SUCCESS) { + DBGPRINT_ERR(("NICInitializeAdapter failed, Status[=0x%08x]\n", + Status)); + if (Status != NDIS_STATUS_SUCCESS) + goto err3; } + + DBGPRINT(RT_DEBUG_OFF, ("1. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); + +#ifdef RTMP_MAC_USB + pAd->CommonCfg.bMultipleIRP = FALSE; + + if (pAd->CommonCfg.bMultipleIRP) + pAd->CommonCfg.NumOfBulkInIRP = RX_RING_SIZE; else - { - RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification. + pAd->CommonCfg.NumOfBulkInIRP = 1; +#endif /* RTMP_MAC_USB // */ + + /*Init Ba Capability parameters. */ +/* RT28XX_BA_INIT(pAd); */ + pAd->CommonCfg.DesiredHtPhy.MpduDensity = + (u8)pAd->CommonCfg.BACapability.field.MpduDensity; + pAd->CommonCfg.DesiredHtPhy.AmsduEnable = + (u16)pAd->CommonCfg.BACapability.field.AmsduEnable; + pAd->CommonCfg.DesiredHtPhy.AmsduSize = + (u16)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.DesiredHtPhy.MimoPs = + (u16)pAd->CommonCfg.BACapability.field.MMPSmode; + /* UPdata to HT IE */ + pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = + (u16)pAd->CommonCfg.BACapability.field.MMPSmode; + pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = + (u16)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = + (u8)pAd->CommonCfg.BACapability.field.MpduDensity; + + /* after reading Registry, we now know if in AP mode or STA mode */ + + /* Load 8051 firmware; crash when FW image not existent */ + /* Status = NICLoadFirmware(pAd); */ + /* if (Status != NDIS_STATUS_SUCCESS) */ + /* break; */ + + DBGPRINT(RT_DEBUG_OFF, ("2. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); + + /* We should read EEPROM for all cases. rt2860b */ + NICReadEEPROMParameters(pAd, (u8 *)pDefaultMac); + + DBGPRINT(RT_DEBUG_OFF, ("3. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); + + NICInitAsicFromEEPROM(pAd); /*rt2860b */ + + /* Set PHY to appropriate mode */ + TmpPhy = pAd->CommonCfg.PhyMode; + pAd->CommonCfg.PhyMode = 0xff; + RTMPSetPhyMode(pAd, TmpPhy); + SetCommonHT(pAd); + + /* No valid channels. */ + if (pAd->ChannelListNum == 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("Wrong configuration. No valid channel found. Check \"ContryCode\" and \"ChannelGeography\" setting.\n")); + goto err4; + } + + DBGPRINT(RT_DEBUG_OFF, + ("MCS Set = %02x %02x %02x %02x %02x\n", + pAd->CommonCfg.HtCapability.MCSSet[0], + pAd->CommonCfg.HtCapability.MCSSet[1], + pAd->CommonCfg.HtCapability.MCSSet[2], + pAd->CommonCfg.HtCapability.MCSSet[3], + pAd->CommonCfg.HtCapability.MCSSet[4])); + +#ifdef RTMP_RF_RW_SUPPORT + /*Init RT30xx RFRegisters after read RFIC type from EEPROM */ + NICInitRFRegisters(pAd); +#endif /* RTMP_RF_RW_SUPPORT // */ + +/* APInitialize(pAd); */ + + /* */ + /* Initialize RF register to default value */ + /* */ + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + /* 8051 firmware require the signal during booting time. */ + /*2008/11/28:KH marked the following codes to patch Frequency offset bug */ + /*AsicSendCommandToMcu(pAd, 0x72, 0xFF, 0x00, 0x00); */ + + if (pAd && (Status != NDIS_STATUS_SUCCESS)) { + /* */ + /* Undo everything if it failed */ + /* */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { +/* NdisMDeregisterInterrupt(&pAd->Interrupt); */ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + } +/* RTMPFreeAdapter(pAd); // we will free it in disconnect() */ + } else if (pAd) { + /* Microsoft HCT require driver send a disconnect event after driver initialization. */ + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); +/* pAd->IndicateMediaState = NdisMediaStateDisconnected; */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE); + + DBGPRINT(RT_DEBUG_TRACE, + ("NDIS_STATUS_MEDIA_DISCONNECT Event B!\n")); + +#ifdef RTMP_MAC_USB + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS); + + /* */ + /* Support multiple BulkIn IRP, */ + /* the value on pAd->CommonCfg.NumOfBulkInIRP may be large than 1. */ + /* */ + for (index = 0; index < pAd->CommonCfg.NumOfBulkInIRP; index++) { + RTUSBBulkReceive(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBulkReceive!\n")); + } +#endif /* RTMP_MAC_USB // */ + } /* end of else */ + + /* Set up the Mac address */ + RtmpOSNetDevAddrSet(pAd->net_dev, &pAd->CurrentAddress[0]); + + DBGPRINT_S(Status, ("<==== rt28xx_init, Status=%x\n", Status)); + + return TRUE; + +err4: +err3: + MlmeHalt(pAd); +err2: + RTMPFreeTxRxRingMemory(pAd); +err1: + + os_free_mem(pAd, pAd->mpdu_blk_pool.mem); /* free BA pool */ + + /* shall not set priv to NULL here because the priv didn't been free yet. */ + /*net_dev->ml_priv = 0; */ +#ifdef ST +err0: +#endif /* ST // */ + + DBGPRINT(RT_DEBUG_ERROR, ("rt28xx Initialized fail!\n")); + return FALSE; +} + +/*---Add by shiang, move from os/linux/rt_main_dev.c */ + +static int RtmpChipOpsRegister(struct rt_rtmp_adapter *pAd, int infType) +{ + struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; + int status; + + memset(pChipOps, 0, sizeof(struct rt_rtmp_chip_op)); + + /* set eeprom related hook functions */ + status = RtmpChipOpsEepromHook(pAd, infType); + + /* set mcu related hook functions */ + switch (infType) { +#ifdef RTMP_PCI_SUPPORT + case RTMP_DEV_INF_PCI: + pChipOps->loadFirmware = RtmpAsicLoadFirmware; + pChipOps->eraseFirmware = RtmpAsicEraseFirmware; + pChipOps->sendCommandToMcu = RtmpAsicSendCommandToMcu; + break; +#endif /* RTMP_PCI_SUPPORT // */ +#ifdef RTMP_USB_SUPPORT + case RTMP_DEV_INF_USB: + pChipOps->loadFirmware = RtmpAsicLoadFirmware; + pChipOps->sendCommandToMcu = RtmpAsicSendCommandToMcu; + break; +#endif /* RTMP_USB_SUPPORT // */ + default: + break; + } + + return status; +} + +int RtmpRaDevCtrlInit(struct rt_rtmp_adapter *pAd, IN RTMP_INF_TYPE infType) +{ + /*void *handle; */ + + /* Assign the interface type. We need use it when do register/EEPROM access. */ + pAd->infType = infType; + + pAd->OpMode = OPMODE_STA; + DBGPRINT(RT_DEBUG_TRACE, + ("STA Driver version-%s\n", STA_DRIVER_VERSION)); + +#ifdef RTMP_MAC_USB + init_MUTEX(&(pAd->UsbVendorReq_semaphore)); + os_alloc_mem(pAd, (u8 **) & pAd->UsbVendorReqBuf, + MAX_PARAM_BUFFER_SIZE - 1); + if (pAd->UsbVendorReqBuf == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("Allocate vendor request temp buffer failed!\n")); + return FALSE; } +#endif /* RTMP_MAC_USB // */ - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc); - DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPEnableRxTx\n")); + RtmpChipOpsRegister(pAd, infType); + + return 0; +} + +BOOLEAN RtmpRaDevCtrlExit(struct rt_rtmp_adapter *pAd) +{ + + RTMPFreeAdapter(pAd); + + return TRUE; } +/* not yet support MBSS */ +struct net_device *get_netdev_from_bssid(struct rt_rtmp_adapter *pAd, u8 FromWhichBSSID) +{ + struct net_device *dev_p = NULL; + + { + dev_p = pAd->net_dev; + } + ASSERT(dev_p); + return dev_p; /* return one of MBSS */ +} diff --git a/drivers/staging/rt2860/common/rtmp_mcu.c b/drivers/staging/rt2860/common/rtmp_mcu.c new file mode 100644 index 0000000000000000000000000000000000000000..9f03901433bbddb05c756ca4a2db9666ca2c0b38 --- /dev/null +++ b/drivers/staging/rt2860/common/rtmp_mcu.c @@ -0,0 +1,291 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* + + Module Name: + rtmp_mcu.c + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "../rt_config.h" + +#if defined(RT2860) || defined(RT3090) +#include "firmware.h" +#include "../../rt3090/firmware.h" +#endif +#ifdef RT2870 +#include "../../rt3070/firmware.h" +#include "firmware_3070.h" +#endif + +#include + +#ifdef RTMP_MAC_USB +/* */ +/* RT2870 Firmware Spec only used 1 oct for version expression */ +/* */ +#define FIRMWARE_MINOR_VERSION 7 +#endif /* RTMP_MAC_USB // */ + +/* New 8k byte firmware size for RT3071/RT3072 */ +#define FIRMWAREIMAGE_MAX_LENGTH 0x2000 +#define FIRMWAREIMAGE_LENGTH (sizeof (FirmwareImage) / sizeof(u8)) +#define FIRMWARE_MAJOR_VERSION 0 + +#define FIRMWAREIMAGEV1_LENGTH 0x1000 +#define FIRMWAREIMAGEV2_LENGTH 0x1000 + +#ifdef RTMP_MAC_PCI +#define FIRMWARE_MINOR_VERSION 2 +#endif /* RTMP_MAC_PCI // */ + +/* + ======================================================================== + + Routine Description: + erase 8051 firmware image in MAC ASIC + + Arguments: + Adapter Pointer to our adapter + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +int RtmpAsicEraseFirmware(struct rt_rtmp_adapter *pAd) +{ + unsigned long i; + + for (i = 0; i < MAX_FIRMWARE_IMAGE_SIZE; i += 4) + RTMP_IO_WRITE32(pAd, FIRMWARE_IMAGE_BASE + i, 0); + + return 0; +} + +/* + ======================================================================== + + Routine Description: + Load 8051 firmware file into MAC ASIC + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS firmware image load ok + NDIS_STATUS_FAILURE image not found + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +int RtmpAsicLoadFirmware(struct rt_rtmp_adapter *pAd) +{ + + int Status = NDIS_STATUS_SUCCESS; + u8 *pFirmwareImage = NULL; + unsigned long FileLength, Index; + u32 MacReg = 0; +#ifdef RTMP_MAC_USB + u32 Version = (pAd->MACVersion >> 16); +#endif + + /* New 8k byte firmware size for RT3071/RT3072 */ + { +#ifdef RTMP_MAC_PCI + if (IS_RT3090(pAd) || IS_RT3390(pAd)) { + pFirmwareImage = FirmwareImage_3090; + FileLength = FIRMWAREIMAGE_MAX_LENGTH; + } else { + pFirmwareImage = FirmwareImage_2860; + FileLength = FIRMWAREIMAGE_MAX_LENGTH; + } +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + /* the firmware image consists of two parts */ + if ((Version != 0x2860) && (Version != 0x2872) && (Version != 0x3070)) { /* use the second part */ + /*printk("KH:Use New Version,part2\n"); */ + pFirmwareImage = + (u8 *)& + FirmwareImage_3070[FIRMWAREIMAGEV1_LENGTH]; + FileLength = FIRMWAREIMAGEV2_LENGTH; + } else { + /*printk("KH:Use New Version,part1\n"); */ + if (Version == 0x3070) + pFirmwareImage = FirmwareImage_3070; + else + pFirmwareImage = FirmwareImage_2870; + FileLength = FIRMWAREIMAGEV1_LENGTH; + } +#endif /* RTMP_MAC_USB // */ + } + + RTMP_WRITE_FIRMWARE(pAd, pFirmwareImage, FileLength); + + /* check if MCU is ready */ + Index = 0; + do { + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacReg); + + if (MacReg & 0x80) + break; + + RTMPusecDelay(1000); + } while (Index++ < 1000); + + if (Index > 1000) { + DBGPRINT(RT_DEBUG_ERROR, + ("NICLoadFirmware: MCU is not ready\n")); + Status = NDIS_STATUS_FAILURE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s (status=%d)\n", __func__, Status)); + + return Status; +} + +int RtmpAsicSendCommandToMcu(struct rt_rtmp_adapter *pAd, + u8 Command, + u8 Token, u8 Arg0, u8 Arg1) +{ + HOST_CMD_CSR_STRUC H2MCmd; + H2M_MAILBOX_STRUC H2MMailbox; + unsigned long i = 0; + +#ifdef PCIE_PS_SUPPORT + /* 3090F power solution 3 has hw limitation that needs to ban all mcu command */ + /* when firmware is in radio state. For other chip doesn't have this limitation. */ + if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) + && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) + && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { + RTMP_SEM_LOCK(&pAd->McuCmdLock); + if ((pAd->brt30xxBanMcuCmd == TRUE) + && (Command != WAKE_MCU_CMD) && (Command != RFOFF_MCU_CMD)) { + RTMP_SEM_UNLOCK(&pAd->McuCmdLock); + DBGPRINT(RT_DEBUG_TRACE, + (" Ban Mcu Cmd %x in sleep mode\n", Command)); + return FALSE; + } else if ((Command == SLEEP_MCU_CMD) + || (Command == RFOFF_MCU_CMD)) { + pAd->brt30xxBanMcuCmd = TRUE; + } else if (Command != WAKE_MCU_CMD) { + pAd->brt30xxBanMcuCmd = FALSE; + } + + RTMP_SEM_UNLOCK(&pAd->McuCmdLock); + + } + if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) + && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) + && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) + && (Command == WAKE_MCU_CMD)) { + + do { + RTMP_IO_FORCE_READ32(pAd, H2M_MAILBOX_CSR, + &H2MMailbox.word); + if (H2MMailbox.field.Owner == 0) + break; + + RTMPusecDelay(2); + DBGPRINT(RT_DEBUG_INFO, + ("AsicSendCommanToMcu::Mail box is busy\n")); + } while (i++ < 100); + + if (i >= 100) { + DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n")); + return FALSE; + } + + H2MMailbox.field.Owner = 1; /* pass ownership to MCU */ + H2MMailbox.field.CmdToken = Token; + H2MMailbox.field.HighByte = Arg1; + H2MMailbox.field.LowByte = Arg0; + RTMP_IO_FORCE_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word); + + H2MCmd.word = 0; + H2MCmd.field.HostCommand = Command; + RTMP_IO_FORCE_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word); + + } else +#endif /* PCIE_PS_SUPPORT // */ + { + do { + RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word); + if (H2MMailbox.field.Owner == 0) + break; + + RTMPusecDelay(2); + } while (i++ < 100); + + if (i > 100) { +#ifdef RTMP_MAC_PCI +#endif /* RTMP_MAC_PCI // */ + { + DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n")); + } + return FALSE; + } +#ifdef RTMP_MAC_PCI +#endif /* RTMP_MAC_PCI // */ + + H2MMailbox.field.Owner = 1; /* pass ownership to MCU */ + H2MMailbox.field.CmdToken = Token; + H2MMailbox.field.HighByte = Arg1; + H2MMailbox.field.LowByte = Arg0; + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word); + + H2MCmd.word = 0; + H2MCmd.field.HostCommand = Command; + RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word); + + if (Command != 0x80) { + } + } +#ifdef PCIE_PS_SUPPORT + /* 3090 MCU Wakeup command needs more time to be stable. */ + /* Before stable, don't issue other MCU command to prevent from firmware error. */ + if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) + && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) + && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) + && (Command == WAKE_MCU_CMD)) { + RTMPusecDelay(2000); + /*Put this is after RF programming. */ + /*NdisAcquireSpinLock(&pAd->McuCmdLock); */ + /*pAd->brt30xxBanMcuCmd = FALSE; */ + /*NdisReleaseSpinLock(&pAd->McuCmdLock); */ + } +#endif /* PCIE_PS_SUPPORT // */ + + return TRUE; +} diff --git a/drivers/staging/rt3090/common/rtmp_timer.c b/drivers/staging/rt2860/common/rtmp_timer.c similarity index 69% rename from drivers/staging/rt3090/common/rtmp_timer.c rename to drivers/staging/rt2860/common/rtmp_timer.c index 5253e8768145a4fb91f950ca922ee1137a4e62ff..42e47d9dc2c90416395357b38bd4312b9b5b47bd 100644 --- a/drivers/staging/rt3090/common/rtmp_timer.c +++ b/drivers/staging/rt2860/common/rtmp_timer.c @@ -40,15 +40,15 @@ #include "../rt_config.h" - BUILD_TIMER_FUNCTION(MlmePeriodicExec); -//BUILD_TIMER_FUNCTION(MlmeRssiReportExec); +/*BUILD_TIMER_FUNCTION(MlmeRssiReportExec); */ BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout); BUILD_TIMER_FUNCTION(APSDPeriodicExec); BUILD_TIMER_FUNCTION(AsicRfTuningExec); +#ifdef RTMP_MAC_USB +BUILD_TIMER_FUNCTION(BeaconUpdateExec); +#endif /* RTMP_MAC_USB // */ - -#ifdef CONFIG_STA_SUPPORT BUILD_TIMER_FUNCTION(BeaconTimeout); BUILD_TIMER_FUNCTION(ScanTimeout); BUILD_TIMER_FUNCTION(AuthTimeout); @@ -61,41 +61,31 @@ BUILD_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc); #ifdef RTMP_MAC_PCI BUILD_TIMER_FUNCTION(PsPollWakeExec); BUILD_TIMER_FUNCTION(RadioOnExec); -#endif // RTMP_MAC_PCI // -#ifdef QOS_DLS_SUPPORT -BUILD_TIMER_FUNCTION(DlsTimeoutAction); -#endif // QOS_DLS_SUPPORT // - - -#endif // CONFIG_STA_SUPPORT // - - +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB +BUILD_TIMER_FUNCTION(RtmpUsbStaAsicForceWakeupTimeout); +#endif /* RTMP_MAC_USB // */ #if defined(AP_LED) || defined(STA_LED) -extern void LedCtrlMain( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); +extern void LedCtrlMain(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); BUILD_TIMER_FUNCTION(LedCtrlMain); #endif - #ifdef RTMP_TIMER_TASK_SUPPORT -static void RtmpTimerQHandle(RTMP_ADAPTER *pAd) +static void RtmpTimerQHandle(struct rt_rtmp_adapter *pAd) { #ifndef KTHREAD_SUPPORT int status; #endif - RALINK_TIMER_STRUCT *pTimer; - RTMP_TIMER_TASK_ENTRY *pEntry; - unsigned long irqFlag; - RTMP_OS_TASK *pTask; - + struct rt_ralink_timer *pTimer; + struct rt_rtmp_timer_task_entry *pEntry; + unsigned long irqFlag; + struct rt_rtmp_os_task *pTask; pTask = &pAd->timerTask; - while(!pTask->task_killed) - { + while (!pTask->task_killed) { pTimer = NULL; #ifdef KTHREAD_SUPPORT @@ -107,38 +97,39 @@ static void RtmpTimerQHandle(RTMP_ADAPTER *pAd) if (pAd->TimerQ.status == RTMP_TASK_STAT_STOPED) break; - // event happened. - while(pAd->TimerQ.pQHead) - { + /* event happened. */ + while (pAd->TimerQ.pQHead) { RTMP_INT_LOCK(&pAd->TimerQLock, irqFlag); pEntry = pAd->TimerQ.pQHead; - if (pEntry) - { + if (pEntry) { pTimer = pEntry->pRaTimer; - // update pQHead + /* update pQHead */ pAd->TimerQ.pQHead = pEntry->pNext; if (pEntry == pAd->TimerQ.pQTail) pAd->TimerQ.pQTail = NULL; - // return this queue entry to timerQFreeList. + /* return this queue entry to timerQFreeList. */ pEntry->pNext = pAd->TimerQ.pQPollFreeList; pAd->TimerQ.pQPollFreeList = pEntry; } RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlag); - if (pTimer) - { - if ((pTimer->handle != NULL) && (!pAd->PM_FlgSuspend)) - pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer); - if ((pTimer->Repeat) && (pTimer->State == FALSE)) - RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue); + if (pTimer) { + if ((pTimer->handle != NULL) + && (!pAd->PM_FlgSuspend)) + pTimer->handle(NULL, + (void *)pTimer->cookie, + NULL, pTimer); + if ((pTimer->Repeat) + && (pTimer->State == FALSE)) + RTMP_OS_Add_Timer(&pTimer->TimerObj, + pTimer->TimerValue); } } #ifndef KTHREAD_SUPPORT - if (status != 0) - { + if (status != 0) { pAd->TimerQ.status = RTMP_TASK_STAT_STOPED; RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); break; @@ -147,22 +138,19 @@ static void RtmpTimerQHandle(RTMP_ADAPTER *pAd) } } - -INT RtmpTimerQThread( - IN OUT PVOID Context) +int RtmpTimerQThread(IN void *Context) { - RTMP_OS_TASK *pTask; - PRTMP_ADAPTER pAd; + struct rt_rtmp_os_task *pTask; + struct rt_rtmp_adapter *pAd; - - pTask = (RTMP_OS_TASK *)Context; - pAd = (PRTMP_ADAPTER)pTask->priv; + pTask = (struct rt_rtmp_os_task *)Context; + pAd = (struct rt_rtmp_adapter *)pTask->priv; RtmpOSTaskCustomize(pTask); RtmpTimerQHandle(pAd); - DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__)); + DBGPRINT(RT_DEBUG_TRACE, ("<---%s\n", __func__)); #ifndef KTHREAD_SUPPORT pTask->taskPID = THREAD_PID_INIT_VALUE; #endif @@ -186,20 +174,16 @@ INT RtmpTimerQThread( } - -RTMP_TIMER_TASK_ENTRY *RtmpTimerQInsert( - IN RTMP_ADAPTER *pAd, - IN RALINK_TIMER_STRUCT *pTimer) +struct rt_rtmp_timer_task_entry *RtmpTimerQInsert(struct rt_rtmp_adapter *pAd, + struct rt_ralink_timer *pTimer) { - RTMP_TIMER_TASK_ENTRY *pQNode = NULL, *pQTail; + struct rt_rtmp_timer_task_entry *pQNode = NULL, *pQTail; unsigned long irqFlags; - RTMP_OS_TASK *pTask = &pAd->timerTask; + struct rt_rtmp_os_task *pTask = &pAd->timerTask; RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); - if (pAd->TimerQ.status & RTMP_TASK_CAN_DO_INSERT) - { - if(pAd->TimerQ.pQPollFreeList) - { + if (pAd->TimerQ.status & RTMP_TASK_CAN_DO_INSERT) { + if (pAd->TimerQ.pQPollFreeList) { pQNode = pAd->TimerQ.pQPollFreeList; pAd->TimerQ.pQPollFreeList = pQNode->pNext; @@ -216,8 +200,7 @@ RTMP_TIMER_TASK_ENTRY *RtmpTimerQInsert( } RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); - if (pQNode) - { + if (pQNode) { #ifdef KTHREAD_SUPPORT WAKE_UP(pTask); #else @@ -228,29 +211,23 @@ RTMP_TIMER_TASK_ENTRY *RtmpTimerQInsert( return pQNode; } - -BOOLEAN RtmpTimerQRemove( - IN RTMP_ADAPTER *pAd, - IN RALINK_TIMER_STRUCT *pTimer) +BOOLEAN RtmpTimerQRemove(struct rt_rtmp_adapter *pAd, struct rt_ralink_timer *pTimer) { - RTMP_TIMER_TASK_ENTRY *pNode, *pPrev = NULL; + struct rt_rtmp_timer_task_entry *pNode, *pPrev = NULL; unsigned long irqFlags; RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); - if (pAd->TimerQ.status >= RTMP_TASK_STAT_INITED) - { + if (pAd->TimerQ.status >= RTMP_TASK_STAT_INITED) { pNode = pAd->TimerQ.pQHead; - while (pNode) - { + while (pNode) { if (pNode->pRaTimer == pTimer) break; pPrev = pNode; pNode = pNode->pNext; } - // Now move it to freeList queue. - if (pNode) - { + /* Now move it to freeList queue. */ + if (pNode) { if (pNode == pAd->TimerQ.pQHead) pAd->TimerQ.pQHead = pNode->pNext; if (pNode == pAd->TimerQ.pQTail) @@ -258,7 +235,7 @@ BOOLEAN RtmpTimerQRemove( if (pPrev != NULL) pPrev->pNext = pNode->pNext; - // return this queue entry to timerQFreeList. + /* return this queue entry to timerQFreeList. */ pNode->pNext = pAd->TimerQ.pQPollFreeList; pAd->TimerQ.pQPollFreeList = pNode; } @@ -268,18 +245,16 @@ BOOLEAN RtmpTimerQRemove( return TRUE; } - -void RtmpTimerQExit(RTMP_ADAPTER *pAd) +void RtmpTimerQExit(struct rt_rtmp_adapter *pAd) { - RTMP_TIMER_TASK_ENTRY *pTimerQ; + struct rt_rtmp_timer_task_entry *pTimerQ; unsigned long irqFlags; RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); - while (pAd->TimerQ.pQHead) - { + while (pAd->TimerQ.pQHead) { pTimerQ = pAd->TimerQ.pQHead; pAd->TimerQ.pQHead = pTimerQ->pNext; - // remove the timeQ + /* remove the timeQ */ } pAd->TimerQ.pQPollFreeList = NULL; os_free_mem(pAd, pAd->TimerQ.pTimerQPoll); @@ -292,27 +267,27 @@ void RtmpTimerQExit(RTMP_ADAPTER *pAd) } - -void RtmpTimerQInit(RTMP_ADAPTER *pAd) +void RtmpTimerQInit(struct rt_rtmp_adapter *pAd) { - int i; - RTMP_TIMER_TASK_ENTRY *pQNode, *pEntry; + int i; + struct rt_rtmp_timer_task_entry *pQNode, *pEntry; unsigned long irqFlags; NdisAllocateSpinLock(&pAd->TimerQLock); NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ)); - os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX); - if (pAd->TimerQ.pTimerQPoll) - { + os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, + sizeof(struct rt_rtmp_timer_task_entry) * TIMER_QUEUE_SIZE_MAX); + if (pAd->TimerQ.pTimerQPoll) { pEntry = NULL; - pQNode = (RTMP_TIMER_TASK_ENTRY *)pAd->TimerQ.pTimerQPoll; - NdisZeroMemory(pAd->TimerQ.pTimerQPoll, sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX); + pQNode = (struct rt_rtmp_timer_task_entry *)pAd->TimerQ.pTimerQPoll; + NdisZeroMemory(pAd->TimerQ.pTimerQPoll, + sizeof(struct rt_rtmp_timer_task_entry) * + TIMER_QUEUE_SIZE_MAX); RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); - for (i = 0 ;i pNext = pEntry; pEntry = pQNode; pQNode++; @@ -324,4 +299,4 @@ void RtmpTimerQInit(RTMP_ADAPTER *pAd) RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); } } -#endif // RTMP_TIMER_TASK_SUPPORT // +#endif /* RTMP_TIMER_TASK_SUPPORT // */ diff --git a/drivers/staging/rt2860/common/rtmp_tkip.c b/drivers/staging/rt2860/common/rtmp_tkip.c deleted file mode 100644 index 4a7fda69f9b4d4b29c3146aa734e8e6117a1aa87..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2860/common/rtmp_tkip.c +++ /dev/null @@ -1,1586 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rtmp_tkip.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Paul Wu 02-25-02 Initial -*/ - -#include "../rt_config.h" - -// Rotation functions on 32 bit values -#define ROL32( A, n ) \ - ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) ) -#define ROR32( A, n ) ROL32( (A), 32-(n) ) - -UINT Tkip_Sbox_Lower[256] = -{ - 0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54, - 0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A, - 0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B, - 0xEC,0x67,0xFD,0xEA,0xBF,0xF7,0x96,0x5B, - 0xC2,0x1C,0xAE,0x6A,0x5A,0x41,0x02,0x4F, - 0x5C,0xF4,0x34,0x08,0x93,0x73,0x53,0x3F, - 0x0C,0x52,0x65,0x5E,0x28,0xA1,0x0F,0xB5, - 0x09,0x36,0x9B,0x3D,0x26,0x69,0xCD,0x9F, - 0x1B,0x9E,0x74,0x2E,0x2D,0xB2,0xEE,0xFB, - 0xF6,0x4D,0x61,0xCE,0x7B,0x3E,0x71,0x97, - 0xF5,0x68,0x00,0x2C,0x60,0x1F,0xC8,0xED, - 0xBE,0x46,0xD9,0x4B,0xDE,0xD4,0xE8,0x4A, - 0x6B,0x2A,0xE5,0x16,0xC5,0xD7,0x55,0x94, - 0xCF,0x10,0x06,0x81,0xF0,0x44,0xBA,0xE3, - 0xF3,0xFE,0xC0,0x8A,0xAD,0xBC,0x48,0x04, - 0xDF,0xC1,0x75,0x63,0x30,0x1A,0x0E,0x6D, - 0x4C,0x14,0x35,0x2F,0xE1,0xA2,0xCC,0x39, - 0x57,0xF2,0x82,0x47,0xAC,0xE7,0x2B,0x95, - 0xA0,0x98,0xD1,0x7F,0x66,0x7E,0xAB,0x83, - 0xCA,0x29,0xD3,0x3C,0x79,0xE2,0x1D,0x76, - 0x3B,0x56,0x4E,0x1E,0xDB,0x0A,0x6C,0xE4, - 0x5D,0x6E,0xEF,0xA6,0xA8,0xA4,0x37,0x8B, - 0x32,0x43,0x59,0xB7,0x8C,0x64,0xD2,0xE0, - 0xB4,0xFA,0x07,0x25,0xAF,0x8E,0xE9,0x18, - 0xD5,0x88,0x6F,0x72,0x24,0xF1,0xC7,0x51, - 0x23,0x7C,0x9C,0x21,0xDD,0xDC,0x86,0x85, - 0x90,0x42,0xC4,0xAA,0xD8,0x05,0x01,0x12, - 0xA3,0x5F,0xF9,0xD0,0x91,0x58,0x27,0xB9, - 0x38,0x13,0xB3,0x33,0xBB,0x70,0x89,0xA7, - 0xB6,0x22,0x92,0x20,0x49,0xFF,0x78,0x7A, - 0x8F,0xF8,0x80,0x17,0xDA,0x31,0xC6,0xB8, - 0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A -}; - -UINT Tkip_Sbox_Upper[256] = -{ - 0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91, - 0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC, - 0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB, - 0x41,0xB3,0x5F,0x45,0x23,0x53,0xE4,0x9B, - 0x75,0xE1,0x3D,0x4C,0x6C,0x7E,0xF5,0x83, - 0x68,0x51,0xD1,0xF9,0xE2,0xAB,0x62,0x2A, - 0x08,0x95,0x46,0x9D,0x30,0x37,0x0A,0x2F, - 0x0E,0x24,0x1B,0xDF,0xCD,0x4E,0x7F,0xEA, - 0x12,0x1D,0x58,0x34,0x36,0xDC,0xB4,0x5B, - 0xA4,0x76,0xB7,0x7D,0x52,0xDD,0x5E,0x13, - 0xA6,0xB9,0x00,0xC1,0x40,0xE3,0x79,0xB6, - 0xD4,0x8D,0x67,0x72,0x94,0x98,0xB0,0x85, - 0xBB,0xC5,0x4F,0xED,0x86,0x9A,0x66,0x11, - 0x8A,0xE9,0x04,0xFE,0xA0,0x78,0x25,0x4B, - 0xA2,0x5D,0x80,0x05,0x3F,0x21,0x70,0xF1, - 0x63,0x77,0xAF,0x42,0x20,0xE5,0xFD,0xBF, - 0x81,0x18,0x26,0xC3,0xBE,0x35,0x88,0x2E, - 0x93,0x55,0xFC,0x7A,0xC8,0xBA,0x32,0xE6, - 0xC0,0x19,0x9E,0xA3,0x44,0x54,0x3B,0x0B, - 0x8C,0xC7,0x6B,0x28,0xA7,0xBC,0x16,0xAD, - 0xDB,0x64,0x74,0x14,0x92,0x0C,0x48,0xB8, - 0x9F,0xBD,0x43,0xC4,0x39,0x31,0xD3,0xF2, - 0xD5,0x8B,0x6E,0xDA,0x01,0xB1,0x9C,0x49, - 0xD8,0xAC,0xF3,0xCF,0xCA,0xF4,0x47,0x10, - 0x6F,0xF0,0x4A,0x5C,0x38,0x57,0x73,0x97, - 0xCB,0xA1,0xE8,0x3E,0x96,0x61,0x0D,0x0F, - 0xE0,0x7C,0x71,0xCC,0x90,0x06,0xF7,0x1C, - 0xC2,0x6A,0xAE,0x69,0x17,0x99,0x3A,0x27, - 0xD9,0xEB,0x2B,0x22,0xD2,0xA9,0x07,0x33, - 0x2D,0x3C,0x15,0xC9,0x87,0xAA,0x50,0xA5, - 0x03,0x59,0x09,0x1A,0x65,0xD7,0x84,0xD0, - 0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C -}; - -/*****************************/ -/******** SBOX Table *********/ -/*****************************/ - -UCHAR SboxTable[256] = -{ - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, - 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, - 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, - 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, - 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, - 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, - 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, - 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, - 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, - 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, - 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, - 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 -}; - -VOID xor_32( - IN PUCHAR a, - IN PUCHAR b, - OUT PUCHAR out); - -VOID xor_128( - IN PUCHAR a, - IN PUCHAR b, - OUT PUCHAR out); - -VOID next_key( - IN PUCHAR key, - IN INT round); - -VOID byte_sub( - IN PUCHAR in, - OUT PUCHAR out); - -VOID shift_row( - IN PUCHAR in, - OUT PUCHAR out); - -VOID mix_column( - IN PUCHAR in, - OUT PUCHAR out); - -UCHAR RTMPCkipSbox( - IN UCHAR a); -// -// Expanded IV for TKIP function. -// -typedef struct PACKED _IV_CONTROL_ -{ - union PACKED - { - struct PACKED - { - UCHAR rc0; - UCHAR rc1; - UCHAR rc2; - - union PACKED - { - struct PACKED - { - UCHAR Rsvd:5; - UCHAR ExtIV:1; - UCHAR KeyID:2; - } field; - UCHAR Byte; - } CONTROL; - } field; - - ULONG word; - } IV16; - - ULONG IV32; -} TKIP_IV, *PTKIP_IV; - - -/* - ======================================================================== - - Routine Description: - Convert from UCHAR[] to ULONG in a portable way - - Arguments: - pMICKey pointer to MIC Key - - Return Value: - None - - Note: - - ======================================================================== -*/ -ULONG RTMPTkipGetUInt32( - IN PUCHAR pMICKey) -{ - ULONG res = 0; - INT i; - - for (i = 0; i < 4; i++) - { - res |= (*pMICKey++) << (8 * i); - } - - return res; -} - -/* - ======================================================================== - - Routine Description: - Convert from ULONG to UCHAR[] in a portable way - - Arguments: - pDst pointer to destination for convert ULONG to UCHAR[] - val the value for convert - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPTkipPutUInt32( - IN OUT PUCHAR pDst, - IN ULONG val) -{ - INT i; - - for(i = 0; i < 4; i++) - { - *pDst++ = (UCHAR) (val & 0xff); - val >>= 8; - } -} - -/* - ======================================================================== - - Routine Description: - Set the MIC Key. - - Arguments: - pAd Pointer to our adapter - pMICKey pointer to MIC Key - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPTkipSetMICKey( - IN PTKIP_KEY_INFO pTkip, - IN PUCHAR pMICKey) -{ - // Set the key - pTkip->K0 = RTMPTkipGetUInt32(pMICKey); - pTkip->K1 = RTMPTkipGetUInt32(pMICKey + 4); - // and reset the message - pTkip->L = pTkip->K0; - pTkip->R = pTkip->K1; - pTkip->nBytesInM = 0; - pTkip->M = 0; -} - -/* - ======================================================================== - - Routine Description: - Calculate the MIC Value. - - Arguments: - pAd Pointer to our adapter - uChar Append this uChar - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPTkipAppendByte( - IN PTKIP_KEY_INFO pTkip, - IN UCHAR uChar) -{ - // Append the byte to our word-sized buffer - pTkip->M |= (uChar << (8* pTkip->nBytesInM)); - pTkip->nBytesInM++; - // Process the word if it is full. - if( pTkip->nBytesInM >= 4 ) - { - pTkip->L ^= pTkip->M; - pTkip->R ^= ROL32( pTkip->L, 17 ); - pTkip->L += pTkip->R; - pTkip->R ^= ((pTkip->L & 0xff00ff00) >> 8) | ((pTkip->L & 0x00ff00ff) << 8); - pTkip->L += pTkip->R; - pTkip->R ^= ROL32( pTkip->L, 3 ); - pTkip->L += pTkip->R; - pTkip->R ^= ROR32( pTkip->L, 2 ); - pTkip->L += pTkip->R; - // Clear the buffer - pTkip->M = 0; - pTkip->nBytesInM = 0; - } -} - -/* - ======================================================================== - - Routine Description: - Calculate the MIC Value. - - Arguments: - pAd Pointer to our adapter - pSrc Pointer to source data for Calculate MIC Value - Len Indicate the length of the source data - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPTkipAppend( - IN PTKIP_KEY_INFO pTkip, - IN PUCHAR pSrc, - IN UINT nBytes) -{ - // This is simple - while(nBytes > 0) - { - RTMPTkipAppendByte(pTkip, *pSrc++); - nBytes--; - } -} - -/* - ======================================================================== - - Routine Description: - Get the MIC Value. - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - the MIC Value is store in pAd->PrivateInfo.MIC - ======================================================================== -*/ -VOID RTMPTkipGetMIC( - IN PTKIP_KEY_INFO pTkip) -{ - // Append the minimum padding - RTMPTkipAppendByte(pTkip, 0x5a ); - RTMPTkipAppendByte(pTkip, 0 ); - RTMPTkipAppendByte(pTkip, 0 ); - RTMPTkipAppendByte(pTkip, 0 ); - RTMPTkipAppendByte(pTkip, 0 ); - // and then zeroes until the length is a multiple of 4 - while( pTkip->nBytesInM != 0 ) - { - RTMPTkipAppendByte(pTkip, 0 ); - } - // The appendByte function has already computed the result. - RTMPTkipPutUInt32(pTkip->MIC, pTkip->L); - RTMPTkipPutUInt32(pTkip->MIC + 4, pTkip->R); -} - -/* - ======================================================================== - - Routine Description: - Init Tkip function. - - Arguments: - pAd Pointer to our adapter - pTKey Pointer to the Temporal Key (TK), TK shall be 128bits. - KeyId TK Key ID - pTA Pointer to transmitter address - pMICKey pointer to MIC Key - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPInitTkipEngine( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKey, - IN UCHAR KeyId, - IN PUCHAR pTA, - IN PUCHAR pMICKey, - IN PUCHAR pTSC, - OUT PULONG pIV16, - OUT PULONG pIV32) -{ - TKIP_IV tkipIv; - - // Prepare 8 bytes TKIP encapsulation for MPDU - NdisZeroMemory(&tkipIv, sizeof(TKIP_IV)); - tkipIv.IV16.field.rc0 = *(pTSC + 1); - tkipIv.IV16.field.rc1 = (tkipIv.IV16.field.rc0 | 0x20) & 0x7f; - tkipIv.IV16.field.rc2 = *pTSC; - tkipIv.IV16.field.CONTROL.field.ExtIV = 1; // 0: non-extended IV, 1: an extended IV - tkipIv.IV16.field.CONTROL.field.KeyID = KeyId; - NdisMoveMemory(&tkipIv.IV32, (pTSC + 2), 4); // Copy IV - - *pIV16 = tkipIv.IV16.word; - *pIV32 = tkipIv.IV32; -} - -/* - ======================================================================== - - Routine Description: - Init MIC Value calculation function which include set MIC key & - calculate first 16 bytes (DA + SA + priority + 0) - - Arguments: - pAd Pointer to our adapter - pTKey Pointer to the Temporal Key (TK), TK shall be 128bits. - pDA Pointer to DA address - pSA Pointer to SA address - pMICKey pointer to MIC Key - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID RTMPInitMICEngine( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKey, - IN PUCHAR pDA, - IN PUCHAR pSA, - IN UCHAR UserPriority, - IN PUCHAR pMICKey) -{ - ULONG Priority = UserPriority; - - // Init MIC value calculation - RTMPTkipSetMICKey(&pAd->PrivateInfo.Tx, pMICKey); - // DA - RTMPTkipAppend(&pAd->PrivateInfo.Tx, pDA, MAC_ADDR_LEN); - // SA - RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSA, MAC_ADDR_LEN); - // Priority + 3 bytes of 0 - RTMPTkipAppend(&pAd->PrivateInfo.Tx, (PUCHAR)&Priority, 4); -} - -/* - ======================================================================== - - Routine Description: - Compare MIC value of received MSDU - - Arguments: - pAd Pointer to our adapter - pSrc Pointer to the received Plain text data - pDA Pointer to DA address - pSA Pointer to SA address - pMICKey pointer to MIC Key - Len the length of the received plain text data exclude MIC value - - Return Value: - TRUE MIC value matched - FALSE MIC value mismatched - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -BOOLEAN RTMPTkipCompareMICValue( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pSrc, - IN PUCHAR pDA, - IN PUCHAR pSA, - IN PUCHAR pMICKey, - IN UCHAR UserPriority, - IN UINT Len) -{ - UCHAR OldMic[8]; - ULONG Priority = UserPriority; - - // Init MIC value calculation - RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey); - // DA - RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN); - // SA - RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN); - // Priority + 3 bytes of 0 - RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4); - - // Calculate MIC value from plain text data - RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len); - - // Get MIC valude from received frame - NdisMoveMemory(OldMic, pSrc + Len, 8); - - // Get MIC value from decrypted plain data - RTMPTkipGetMIC(&pAd->PrivateInfo.Rx); - - // Move MIC value from MSDU, this steps should move to data path. - // Since the MIC value might cross MPDUs. - if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8)) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValue(): TKIP MIC Error !\n")); //MIC error. - - - return (FALSE); - } - return (TRUE); -} - -/* - ======================================================================== - - Routine Description: - Compare MIC value of received MSDU - - Arguments: - pAd Pointer to our adapter - pLLC LLC header - pSrc Pointer to the received Plain text data - pDA Pointer to DA address - pSA Pointer to SA address - pMICKey pointer to MIC Key - Len the length of the received plain text data exclude MIC value - - Return Value: - TRUE MIC value matched - FALSE MIC value mismatched - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -BOOLEAN RTMPTkipCompareMICValueWithLLC( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pLLC, - IN PUCHAR pSrc, - IN PUCHAR pDA, - IN PUCHAR pSA, - IN PUCHAR pMICKey, - IN UINT Len) -{ - UCHAR OldMic[8]; - ULONG Priority = 0; - - // Init MIC value calculation - RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey); - // DA - RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN); - // SA - RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN); - // Priority + 3 bytes of 0 - RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4); - - // Start with LLC header - RTMPTkipAppend(&pAd->PrivateInfo.Rx, pLLC, 8); - - // Calculate MIC value from plain text data - RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len); - - // Get MIC valude from received frame - NdisMoveMemory(OldMic, pSrc + Len, 8); - - // Get MIC value from decrypted plain data - RTMPTkipGetMIC(&pAd->PrivateInfo.Rx); - - // Move MIC value from MSDU, this steps should move to data path. - // Since the MIC value might cross MPDUs. - if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8)) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValueWithLLC(): TKIP MIC Error !\n")); //MIC error. - - - return (FALSE); - } - return (TRUE); -} -/* - ======================================================================== - - Routine Description: - Copy frame from waiting queue into relative ring buffer and set - appropriate ASIC register to kick hardware transmit function - - Arguments: - pAd Pointer to our adapter - PNDIS_PACKET Pointer to Ndis Packet for MIC calculation - pEncap Pointer to LLC encap data - LenEncap Total encap length, might be 0 which indicates no encap - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPCalculateMICValue( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN PUCHAR pEncap, - IN PCIPHER_KEY pKey, - IN UCHAR apidx) -{ - PACKET_INFO PacketInfo; - PUCHAR pSrcBufVA; - UINT SrcBufLen; - PUCHAR pSrc; - UCHAR UserPriority; - UCHAR vlan_offset = 0; - - RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); - - UserPriority = RTMP_GET_PACKET_UP(pPacket); - pSrc = pSrcBufVA; - - // determine if this is a vlan packet - if (((*(pSrc + 12) << 8) + *(pSrc + 13)) == 0x8100) - vlan_offset = 4; - - { - RTMPInitMICEngine( - pAd, - pKey->Key, - pSrc, - pSrc + 6, - UserPriority, - pKey->TxMic); - } - - - if (pEncap != NULL) - { - // LLC encapsulation - RTMPTkipAppend(&pAd->PrivateInfo.Tx, pEncap, 6); - // Protocol Type - RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc + 12 + vlan_offset, 2); - } - SrcBufLen -= (14 + vlan_offset); - pSrc += (14 + vlan_offset); - do - { - if (SrcBufLen > 0) - { - RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc, SrcBufLen); - } - - break; // No need handle next packet - - } while (TRUE); // End of copying payload - - // Compute the final MIC Value - RTMPTkipGetMIC(&pAd->PrivateInfo.Tx); -} - - -/************************************************************/ -/* tkip_sbox() */ -/* Returns a 16 bit value from a 64K entry table. The Table */ -/* is synthesized from two 256 entry byte wide tables. */ -/************************************************************/ - -UINT tkip_sbox(UINT index) -{ - UINT index_low; - UINT index_high; - UINT left, right; - - index_low = (index % 256); - index_high = ((index >> 8) % 256); - - left = Tkip_Sbox_Lower[index_low] + (Tkip_Sbox_Upper[index_low] * 256); - right = Tkip_Sbox_Upper[index_high] + (Tkip_Sbox_Lower[index_high] * 256); - - return (left ^ right); -} - -UINT rotr1(UINT a) -{ - unsigned int b; - - if ((a & 0x01) == 0x01) - { - b = (a >> 1) | 0x8000; - } - else - { - b = (a >> 1) & 0x7fff; - } - b = b % 65536; - return b; -} - -VOID RTMPTkipMixKey( - UCHAR *key, - UCHAR *ta, - ULONG pnl, /* Least significant 16 bits of PN */ - ULONG pnh, /* Most significant 32 bits of PN */ - UCHAR *rc4key, - UINT *p1k) -{ - - UINT tsc0; - UINT tsc1; - UINT tsc2; - - UINT ppk0; - UINT ppk1; - UINT ppk2; - UINT ppk3; - UINT ppk4; - UINT ppk5; - - INT i; - INT j; - - tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ - tsc1 = (unsigned int)(pnh % 65536); - tsc2 = (unsigned int)(pnl % 65536); /* lsb */ - - /* Phase 1, step 1 */ - p1k[0] = tsc1; - p1k[1] = tsc0; - p1k[2] = (UINT)(ta[0] + (ta[1]*256)); - p1k[3] = (UINT)(ta[2] + (ta[3]*256)); - p1k[4] = (UINT)(ta[4] + (ta[5]*256)); - - /* Phase 1, step 2 */ - for (i=0; i<8; i++) - { - j = 2*(i & 1); - p1k[0] = (p1k[0] + tkip_sbox( (p1k[4] ^ ((256*key[1+j]) + key[j])) % 65536 )) % 65536; - p1k[1] = (p1k[1] + tkip_sbox( (p1k[0] ^ ((256*key[5+j]) + key[4+j])) % 65536 )) % 65536; - p1k[2] = (p1k[2] + tkip_sbox( (p1k[1] ^ ((256*key[9+j]) + key[8+j])) % 65536 )) % 65536; - p1k[3] = (p1k[3] + tkip_sbox( (p1k[2] ^ ((256*key[13+j]) + key[12+j])) % 65536 )) % 65536; - p1k[4] = (p1k[4] + tkip_sbox( (p1k[3] ^ (((256*key[1+j]) + key[j]))) % 65536 )) % 65536; - p1k[4] = (p1k[4] + i) % 65536; - } - - /* Phase 2, Step 1 */ - ppk0 = p1k[0]; - ppk1 = p1k[1]; - ppk2 = p1k[2]; - ppk3 = p1k[3]; - ppk4 = p1k[4]; - ppk5 = (p1k[4] + tsc2) % 65536; - - /* Phase2, Step 2 */ - ppk0 = ppk0 + tkip_sbox( (ppk5 ^ ((256*key[1]) + key[0])) % 65536); - ppk1 = ppk1 + tkip_sbox( (ppk0 ^ ((256*key[3]) + key[2])) % 65536); - ppk2 = ppk2 + tkip_sbox( (ppk1 ^ ((256*key[5]) + key[4])) % 65536); - ppk3 = ppk3 + tkip_sbox( (ppk2 ^ ((256*key[7]) + key[6])) % 65536); - ppk4 = ppk4 + tkip_sbox( (ppk3 ^ ((256*key[9]) + key[8])) % 65536); - ppk5 = ppk5 + tkip_sbox( (ppk4 ^ ((256*key[11]) + key[10])) % 65536); - - ppk0 = ppk0 + rotr1(ppk5 ^ ((256*key[13]) + key[12])); - ppk1 = ppk1 + rotr1(ppk0 ^ ((256*key[15]) + key[14])); - ppk2 = ppk2 + rotr1(ppk1); - ppk3 = ppk3 + rotr1(ppk2); - ppk4 = ppk4 + rotr1(ppk3); - ppk5 = ppk5 + rotr1(ppk4); - - /* Phase 2, Step 3 */ - /* Phase 2, Step 3 */ - - tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ - tsc1 = (unsigned int)(pnh % 65536); - tsc2 = (unsigned int)(pnl % 65536); /* lsb */ - - rc4key[0] = (tsc2 >> 8) % 256; - rc4key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f; - rc4key[2] = tsc2 % 256; - rc4key[3] = ((ppk5 ^ ((256*key[1]) + key[0])) >> 1) % 256; - - rc4key[4] = ppk0 % 256; - rc4key[5] = (ppk0 >> 8) % 256; - - rc4key[6] = ppk1 % 256; - rc4key[7] = (ppk1 >> 8) % 256; - - rc4key[8] = ppk2 % 256; - rc4key[9] = (ppk2 >> 8) % 256; - - rc4key[10] = ppk3 % 256; - rc4key[11] = (ppk3 >> 8) % 256; - - rc4key[12] = ppk4 % 256; - rc4key[13] = (ppk4 >> 8) % 256; - - rc4key[14] = ppk5 % 256; - rc4key[15] = (ppk5 >> 8) % 256; -} - - -/************************************************/ -/* construct_mic_header1() */ -/* Builds the first MIC header block from */ -/* header fields. */ -/************************************************/ - -void construct_mic_header1( - unsigned char *mic_header1, - int header_length, - unsigned char *mpdu) -{ - mic_header1[0] = (unsigned char)((header_length - 2) / 256); - mic_header1[1] = (unsigned char)((header_length - 2) % 256); - mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ - mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */ - mic_header1[4] = mpdu[4]; /* A1 */ - mic_header1[5] = mpdu[5]; - mic_header1[6] = mpdu[6]; - mic_header1[7] = mpdu[7]; - mic_header1[8] = mpdu[8]; - mic_header1[9] = mpdu[9]; - mic_header1[10] = mpdu[10]; /* A2 */ - mic_header1[11] = mpdu[11]; - mic_header1[12] = mpdu[12]; - mic_header1[13] = mpdu[13]; - mic_header1[14] = mpdu[14]; - mic_header1[15] = mpdu[15]; -} - -/************************************************/ -/* construct_mic_header2() */ -/* Builds the last MIC header block from */ -/* header fields. */ -/************************************************/ - -void construct_mic_header2( - unsigned char *mic_header2, - unsigned char *mpdu, - int a4_exists, - int qc_exists) -{ - int i; - - for (i = 0; i<16; i++) mic_header2[i]=0x00; - - mic_header2[0] = mpdu[16]; /* A3 */ - mic_header2[1] = mpdu[17]; - mic_header2[2] = mpdu[18]; - mic_header2[3] = mpdu[19]; - mic_header2[4] = mpdu[20]; - mic_header2[5] = mpdu[21]; - - // In Sequence Control field, mute sequence numer bits (12-bit) - mic_header2[6] = mpdu[22] & 0x0f; /* SC */ - mic_header2[7] = 0x00; /* mpdu[23]; */ - - if ((!qc_exists) & a4_exists) - { - for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */ - - } - - if (qc_exists && (!a4_exists)) - { - mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */ - mic_header2[9] = mpdu[25] & 0x00; - } - - if (qc_exists && a4_exists) - { - for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */ - - mic_header2[14] = mpdu[30] & 0x0f; - mic_header2[15] = mpdu[31] & 0x00; - } -} - - -/************************************************/ -/* construct_mic_iv() */ -/* Builds the MIC IV from header fields and PN */ -/************************************************/ - -void construct_mic_iv( - unsigned char *mic_iv, - int qc_exists, - int a4_exists, - unsigned char *mpdu, - unsigned int payload_length, - unsigned char *pn_vector) -{ - int i; - - mic_iv[0] = 0x59; - if (qc_exists && a4_exists) - mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ - if (qc_exists && !a4_exists) - mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ - if (!qc_exists) - mic_iv[1] = 0x00; - for (i = 2; i < 8; i++) - mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */ -#ifdef CONSISTENT_PN_ORDER - for (i = 8; i < 14; i++) - mic_iv[i] = pn_vector[i - 8]; /* mic_iv[8:13] = PN[0:5] */ -#else - for (i = 8; i < 14; i++) - mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ -#endif - i = (payload_length / 256); - i = (payload_length % 256); - mic_iv[14] = (unsigned char) (payload_length / 256); - mic_iv[15] = (unsigned char) (payload_length % 256); - -} - - - -/************************************/ -/* bitwise_xor() */ -/* A 128 bit, bitwise exclusive or */ -/************************************/ - -void bitwise_xor(unsigned char *ina, unsigned char *inb, unsigned char *out) -{ - int i; - for (i=0; i<16; i++) - { - out[i] = ina[i] ^ inb[i]; - } -} - - -void aes128k128d(unsigned char *key, unsigned char *data, unsigned char *ciphertext) -{ - int round; - int i; - unsigned char intermediatea[16]; - unsigned char intermediateb[16]; - unsigned char round_key[16]; - - for(i=0; i<16; i++) round_key[i] = key[i]; - - for (round = 0; round < 11; round++) - { - if (round == 0) - { - xor_128(round_key, data, ciphertext); - next_key(round_key, round); - } - else if (round == 10) - { - byte_sub(ciphertext, intermediatea); - shift_row(intermediatea, intermediateb); - xor_128(intermediateb, round_key, ciphertext); - } - else /* 1 - 9 */ - { - byte_sub(ciphertext, intermediatea); - shift_row(intermediatea, intermediateb); - mix_column(&intermediateb[0], &intermediatea[0]); - mix_column(&intermediateb[4], &intermediatea[4]); - mix_column(&intermediateb[8], &intermediatea[8]); - mix_column(&intermediateb[12], &intermediatea[12]); - xor_128(intermediatea, round_key, ciphertext); - next_key(round_key, round); - } - } - -} - -void construct_ctr_preload( - unsigned char *ctr_preload, - int a4_exists, - int qc_exists, - unsigned char *mpdu, - unsigned char *pn_vector, - int c) -{ - - int i = 0; - for (i=0; i<16; i++) ctr_preload[i] = 0x00; - i = 0; - - ctr_preload[0] = 0x01; /* flag */ - if (qc_exists && a4_exists) ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */ - if (qc_exists && !a4_exists) ctr_preload[1] = mpdu[24] & 0x0f; - - for (i = 2; i < 8; i++) - ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */ -#ifdef CONSISTENT_PN_ORDER - for (i = 8; i < 14; i++) - ctr_preload[i] = pn_vector[i - 8]; /* ctr_preload[8:13] = PN[0:5] */ -#else - for (i = 8; i < 14; i++) - ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */ -#endif - ctr_preload[14] = (unsigned char) (c / 256); // Ctr - ctr_preload[15] = (unsigned char) (c % 256); - -} - - -// -// TRUE: Success! -// FALSE: Decrypt Error! -// -BOOLEAN RTMPSoftDecryptTKIP( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG DataByteCnt, - IN UCHAR UserPriority, - IN PCIPHER_KEY pWpaKey) -{ - UCHAR KeyID; - UINT HeaderLen; - UCHAR fc0; - UCHAR fc1; - USHORT fc; - UINT frame_type; - UINT frame_subtype; - UINT from_ds; - UINT to_ds; - INT a4_exists; - INT qc_exists; - USHORT duration; - USHORT seq_control; - USHORT qos_control; - UCHAR TA[MAC_ADDR_LEN]; - UCHAR DA[MAC_ADDR_LEN]; - UCHAR SA[MAC_ADDR_LEN]; - UCHAR RC4Key[16]; - UINT p1k[5]; //for mix_key; - ULONG pnl;/* Least significant 16 bits of PN */ - ULONG pnh;/* Most significant 32 bits of PN */ - UINT num_blocks; - UINT payload_remainder; - ARCFOURCONTEXT ArcFourContext; - UINT crc32 = 0; - UINT trailfcs = 0; - UCHAR MIC[8]; - UCHAR TrailMIC[8]; - - fc0 = *pData; - fc1 = *(pData + 1); - - fc = *((PUSHORT)pData); - - frame_type = ((fc0 >> 2) & 0x03); - frame_subtype = ((fc0 >> 4) & 0x0f); - - from_ds = (fc1 & 0x2) >> 1; - to_ds = (fc1 & 0x1); - - a4_exists = (from_ds & to_ds); - qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */ - (frame_subtype == 0x09) || /* Likely to change. */ - (frame_subtype == 0x0a) || - (frame_subtype == 0x0b) - ); - - HeaderLen = 24; - if (a4_exists) - HeaderLen += 6; - - KeyID = *((PUCHAR)(pData+ HeaderLen + 3)); - KeyID = KeyID >> 6; - - if (pWpaKey[KeyID].KeyLen == 0) - { - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptTKIP failed!(KeyID[%d] Length can not be 0)\n", KeyID)); - return FALSE; - } - - duration = *((PUSHORT)(pData+2)); - - seq_control = *((PUSHORT)(pData+22)); - - if (qc_exists) - { - if (a4_exists) - { - qos_control = *((PUSHORT)(pData+30)); - } - else - { - qos_control = *((PUSHORT)(pData+24)); - } - } - - if (to_ds == 0 && from_ds == 1) - { - NdisMoveMemory(DA, pData+4, MAC_ADDR_LEN); - NdisMoveMemory(SA, pData+16, MAC_ADDR_LEN); - NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); //BSSID - } - else if (to_ds == 0 && from_ds == 0 ) - { - NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); - NdisMoveMemory(DA, pData+4, MAC_ADDR_LEN); - NdisMoveMemory(SA, pData+10, MAC_ADDR_LEN); - } - else if (to_ds == 1 && from_ds == 0) - { - NdisMoveMemory(SA, pData+10, MAC_ADDR_LEN); - NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); - NdisMoveMemory(DA, pData+16, MAC_ADDR_LEN); - } - else if (to_ds == 1 && from_ds == 1) - { - NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); - NdisMoveMemory(DA, pData+16, MAC_ADDR_LEN); - NdisMoveMemory(SA, pData+22, MAC_ADDR_LEN); - } - - num_blocks = (DataByteCnt - 16) / 16; - payload_remainder = (DataByteCnt - 16) % 16; - - pnl = (*(pData + HeaderLen)) * 256 + *(pData + HeaderLen + 2); - pnh = *((PULONG)(pData + HeaderLen + 4)); - pnh = cpu2le32(pnh); - RTMPTkipMixKey(pWpaKey[KeyID].Key, TA, pnl, pnh, RC4Key, p1k); - - ARCFOUR_INIT(&ArcFourContext, RC4Key, 16); - - ARCFOUR_DECRYPT(&ArcFourContext, pData + HeaderLen, pData + HeaderLen + 8, DataByteCnt - HeaderLen - 8); - NdisMoveMemory(&trailfcs, pData + DataByteCnt - 8 - 4, 4); - crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pData + HeaderLen, DataByteCnt - HeaderLen - 8 - 4); //Skip IV+EIV 8 bytes & Skip last 4 bytes(FCS). - crc32 ^= 0xffffffff; /* complement */ - - if(crc32 != cpu2le32(trailfcs)) - { - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptTKIP, WEP Data ICV Error !\n")); //ICV error. - - return (FALSE); - } - - NdisMoveMemory(TrailMIC, pData + DataByteCnt - 8 - 8 - 4, 8); - RTMPInitMICEngine(pAd, pWpaKey[KeyID].Key, DA, SA, UserPriority, pWpaKey[KeyID].RxMic); - RTMPTkipAppend(&pAd->PrivateInfo.Tx, pData + HeaderLen, DataByteCnt - HeaderLen - 8 - 12); - RTMPTkipGetMIC(&pAd->PrivateInfo.Tx); - NdisMoveMemory(MIC, pAd->PrivateInfo.Tx.MIC, 8); - - if (!NdisEqualMemory(MIC, TrailMIC, 8)) - { - DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptTKIP, WEP Data MIC Error !\n")); //MIC error. - return (FALSE); - } - - return TRUE; -} - - - - -BOOLEAN RTMPSoftDecryptAES( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG DataByteCnt, - IN PCIPHER_KEY pWpaKey) -{ - UCHAR KeyID; - UINT HeaderLen; - UCHAR PN[6]; - UINT payload_len; - UINT num_blocks; - UINT payload_remainder; - USHORT fc; - UCHAR fc0; - UCHAR fc1; - UINT frame_type; - UINT frame_subtype; - UINT from_ds; - UINT to_ds; - INT a4_exists; - INT qc_exists; - UCHAR aes_out[16]; - int payload_index; - UINT i; - UCHAR ctr_preload[16]; - UCHAR chain_buffer[16]; - UCHAR padded_buffer[16]; - UCHAR mic_iv[16]; - UCHAR mic_header1[16]; - UCHAR mic_header2[16]; - UCHAR MIC[8]; - UCHAR TrailMIC[8]; - - fc0 = *pData; - fc1 = *(pData + 1); - - fc = *((PUSHORT)pData); - - frame_type = ((fc0 >> 2) & 0x03); - frame_subtype = ((fc0 >> 4) & 0x0f); - - from_ds = (fc1 & 0x2) >> 1; - to_ds = (fc1 & 0x1); - - a4_exists = (from_ds & to_ds); - qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */ - (frame_subtype == 0x09) || /* Likely to change. */ - (frame_subtype == 0x0a) || - (frame_subtype == 0x0b) - ); - - HeaderLen = 24; - if (a4_exists) - HeaderLen += 6; - - KeyID = *((PUCHAR)(pData+ HeaderLen + 3)); - KeyID = KeyID >> 6; - - if (pWpaKey[KeyID].KeyLen == 0) - { - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptAES failed!(KeyID[%d] Length can not be 0)\n", KeyID)); - return FALSE; - } - - PN[0] = *(pData+ HeaderLen); - PN[1] = *(pData+ HeaderLen + 1); - PN[2] = *(pData+ HeaderLen + 4); - PN[3] = *(pData+ HeaderLen + 5); - PN[4] = *(pData+ HeaderLen + 6); - PN[5] = *(pData+ HeaderLen + 7); - - payload_len = DataByteCnt - HeaderLen - 8 - 8; // 8 bytes for CCMP header , 8 bytes for MIC - payload_remainder = (payload_len) % 16; - num_blocks = (payload_len) / 16; - - - - // Find start of payload - payload_index = HeaderLen + 8; //IV+EIV - - for (i=0; i< num_blocks; i++) - { - construct_ctr_preload(ctr_preload, - a4_exists, - qc_exists, - pData, - PN, - i+1 ); - - aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out); - - bitwise_xor(aes_out, pData + payload_index, chain_buffer); - NdisMoveMemory(pData + payload_index - 8, chain_buffer, 16); - payload_index += 16; - } - - // - // If there is a short final block, then pad it - // encrypt it and copy the unpadded part back - // - if (payload_remainder > 0) - { - construct_ctr_preload(ctr_preload, - a4_exists, - qc_exists, - pData, - PN, - num_blocks + 1); - - NdisZeroMemory(padded_buffer, 16); - NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder); - - aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out); - - bitwise_xor(aes_out, padded_buffer, chain_buffer); - NdisMoveMemory(pData + payload_index - 8, chain_buffer, payload_remainder); - payload_index += payload_remainder; - } - - // - // Descrypt the MIC - // - construct_ctr_preload(ctr_preload, - a4_exists, - qc_exists, - pData, - PN, - 0); - NdisZeroMemory(padded_buffer, 16); - NdisMoveMemory(padded_buffer, pData + payload_index, 8); - - aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out); - - bitwise_xor(aes_out, padded_buffer, chain_buffer); - - NdisMoveMemory(TrailMIC, chain_buffer, 8); - - // - // Calculate MIC - // - - //Force the protected frame bit on - *(pData + 1) = *(pData + 1) | 0x40; - - // Find start of payload - // Because the CCMP header has been removed - payload_index = HeaderLen; - - construct_mic_iv( - mic_iv, - qc_exists, - a4_exists, - pData, - payload_len, - PN); - - construct_mic_header1( - mic_header1, - HeaderLen, - pData); - - construct_mic_header2( - mic_header2, - pData, - a4_exists, - qc_exists); - - aes128k128d(pWpaKey[KeyID].Key, mic_iv, aes_out); - bitwise_xor(aes_out, mic_header1, chain_buffer); - aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); - bitwise_xor(aes_out, mic_header2, chain_buffer); - aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); - - // iterate through each 16 byte payload block - for (i = 0; i < num_blocks; i++) - { - bitwise_xor(aes_out, pData + payload_index, chain_buffer); - payload_index += 16; - aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); - } - - // Add on the final payload block if it needs padding - if (payload_remainder > 0) - { - NdisZeroMemory(padded_buffer, 16); - NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder); - - bitwise_xor(aes_out, padded_buffer, chain_buffer); - aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); - } - // aes_out contains padded mic, discard most significant - // 8 bytes to generate 64 bit MIC - for (i = 0 ; i < 8; i++) MIC[i] = aes_out[i]; - - if (!NdisEqualMemory(MIC, TrailMIC, 8)) - { - DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptAES, MIC Error !\n")); //MIC error. - return FALSE; - } - - return TRUE; -} - -/****************************************/ -/* aes128k128d() */ -/* Performs a 128 bit AES encrypt with */ -/* 128 bit data. */ -/****************************************/ -VOID xor_128( - IN PUCHAR a, - IN PUCHAR b, - OUT PUCHAR out) -{ - INT i; - - for (i=0;i<16; i++) - { - out[i] = a[i] ^ b[i]; - } -} - -VOID next_key( - IN PUCHAR key, - IN INT round) -{ - UCHAR rcon; - UCHAR sbox_key[4]; - UCHAR rcon_table[12] = - { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, - 0x1b, 0x36, 0x36, 0x36 - }; - - sbox_key[0] = RTMPCkipSbox(key[13]); - sbox_key[1] = RTMPCkipSbox(key[14]); - sbox_key[2] = RTMPCkipSbox(key[15]); - sbox_key[3] = RTMPCkipSbox(key[12]); - - rcon = rcon_table[round]; - - xor_32(&key[0], sbox_key, &key[0]); - key[0] = key[0] ^ rcon; - - xor_32(&key[4], &key[0], &key[4]); - xor_32(&key[8], &key[4], &key[8]); - xor_32(&key[12], &key[8], &key[12]); -} - -VOID xor_32( - IN PUCHAR a, - IN PUCHAR b, - OUT PUCHAR out) -{ - INT i; - - for (i=0;i<4; i++) - { - out[i] = a[i] ^ b[i]; - } -} - -VOID byte_sub( - IN PUCHAR in, - OUT PUCHAR out) -{ - INT i; - - for (i=0; i< 16; i++) - { - out[i] = RTMPCkipSbox(in[i]); - } -} - -UCHAR RTMPCkipSbox( - IN UCHAR a) -{ - return SboxTable[(int)a]; -} - -VOID shift_row( - IN PUCHAR in, - OUT PUCHAR out) -{ - out[0] = in[0]; - out[1] = in[5]; - out[2] = in[10]; - out[3] = in[15]; - out[4] = in[4]; - out[5] = in[9]; - out[6] = in[14]; - out[7] = in[3]; - out[8] = in[8]; - out[9] = in[13]; - out[10] = in[2]; - out[11] = in[7]; - out[12] = in[12]; - out[13] = in[1]; - out[14] = in[6]; - out[15] = in[11]; -} - -VOID mix_column( - IN PUCHAR in, - OUT PUCHAR out) -{ - INT i; - UCHAR add1b[4]; - UCHAR add1bf7[4]; - UCHAR rotl[4]; - UCHAR swap_halfs[4]; - UCHAR andf7[4]; - UCHAR rotr[4]; - UCHAR temp[4]; - UCHAR tempb[4]; - - for (i=0 ; i<4; i++) - { - if ((in[i] & 0x80)== 0x80) - add1b[i] = 0x1b; - else - add1b[i] = 0x00; - } - - swap_halfs[0] = in[2]; /* Swap halfs */ - swap_halfs[1] = in[3]; - swap_halfs[2] = in[0]; - swap_halfs[3] = in[1]; - - rotl[0] = in[3]; /* Rotate left 8 bits */ - rotl[1] = in[0]; - rotl[2] = in[1]; - rotl[3] = in[2]; - - andf7[0] = in[0] & 0x7f; - andf7[1] = in[1] & 0x7f; - andf7[2] = in[2] & 0x7f; - andf7[3] = in[3] & 0x7f; - - for (i = 3; i>0; i--) /* logical shift left 1 bit */ - { - andf7[i] = andf7[i] << 1; - if ((andf7[i-1] & 0x80) == 0x80) - { - andf7[i] = (andf7[i] | 0x01); - } - } - andf7[0] = andf7[0] << 1; - andf7[0] = andf7[0] & 0xfe; - - xor_32(add1b, andf7, add1bf7); - - xor_32(in, add1bf7, rotr); - - temp[0] = rotr[0]; /* Rotate right 8 bits */ - rotr[0] = rotr[1]; - rotr[1] = rotr[2]; - rotr[2] = rotr[3]; - rotr[3] = temp[0]; - - xor_32(add1bf7, rotr, temp); - xor_32(swap_halfs, rotl,tempb); - xor_32(temp, tempb, out); -} - diff --git a/drivers/staging/rt2860/common/rtmp_wep.c b/drivers/staging/rt2860/common/rtmp_wep.c deleted file mode 100644 index 8e833e7011bdcc1bd663f9a5451966ea618b8623..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2860/common/rtmp_wep.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rtmp_wep.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Paul Wu 10-28-02 Initial -*/ - -#include "../rt_config.h" - -UINT FCSTAB_32[256] = -{ - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, - 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, - 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, - 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, - 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, - 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, - 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, - 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, - 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, - 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, - 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, - 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, - 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, - 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, - 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, - 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, - 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, - 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, - 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, - 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, - 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, - 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, - 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, - 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, - 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, - 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - -/* - ======================================================================== - - Routine Description: - Init WEP function. - - Arguments: - pAd Pointer to our adapter - pKey Pointer to the WEP KEY - KeyId WEP Key ID - KeyLen the length of WEP KEY - pDest Pointer to the destination which Encryption data will store in. - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPInitWepEngine( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKey, - IN UCHAR KeyId, - IN UCHAR KeyLen, - IN OUT PUCHAR pDest) -{ - UINT i; - UCHAR WEPKEY[] = { - //IV - 0x00, 0x11, 0x22, - //WEP KEY - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC - }; - - pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32. - - if (pAd->StaCfg.bCkipOn && (pAd->StaCfg.CkipFlag & 0x10) && (pAd->OpMode == OPMODE_STA)) - { - ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, pKey, KeyLen); //INIT SBOX, KEYLEN+3(IV) - NdisMoveMemory(pDest, pKey, 3); //Append Init Vector - } - else - { - NdisMoveMemory(WEPKEY + 3, pKey, KeyLen); - - for(i = 0; i < 3; i++) - WEPKEY[i] = RandomByte(pAd); //Call mlme RandomByte() function. - ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, KeyLen + 3); //INIT SBOX, KEYLEN+3(IV) - - NdisMoveMemory(pDest, WEPKEY, 3); //Append Init Vector - } - *(pDest+3) = (KeyId << 6); //Append KEYID - -} - -/* - ======================================================================== - - Routine Description: - Encrypt transimitted data - - Arguments: - pAd Pointer to our adapter - pSrc Pointer to the transimitted source data that will be encrypt - pDest Pointer to the destination where entryption data will be store in. - Len Indicate the length of the source data - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPEncryptData( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pSrc, - IN PUCHAR pDest, - IN UINT Len) -{ - pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, pSrc, Len); - ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, pSrc, Len); -} - - -/* - ======================================================================== - - Routine Description: - Decrypt received WEP data - - Arguments: - pAdapter Pointer to our adapter - pSrc Pointer to the received data - Len the length of the received data - - Return Value: - TRUE Decrypt WEP data success - FALSE Decrypt WEP data failed - - Note: - - ======================================================================== -*/ -BOOLEAN RTMPSoftDecryptWEP( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG DataByteCnt, - IN PCIPHER_KEY pGroupKey) -{ - UINT trailfcs; - UINT crc32; - UCHAR KeyIdx; - UCHAR WEPKEY[] = { - //IV - 0x00, 0x11, 0x22, - //WEP KEY - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC - }; - UCHAR *pPayload = (UCHAR *)pData + LENGTH_802_11; - ULONG payload_len = DataByteCnt - LENGTH_802_11; - - NdisMoveMemory(WEPKEY, pPayload, 3); //Get WEP IV - - KeyIdx = (*(pPayload + 3) & 0xc0) >> 6; - if (pGroupKey[KeyIdx].KeyLen == 0) - return (FALSE); - - NdisMoveMemory(WEPKEY + 3, pGroupKey[KeyIdx].Key, pGroupKey[KeyIdx].KeyLen); - ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, pGroupKey[KeyIdx].KeyLen + 3); - ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, pPayload, pPayload + 4, payload_len - 4); - NdisMoveMemory(&trailfcs, pPayload + payload_len - 8, 4); - crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pPayload, payload_len - 8); //Skip last 4 bytes(FCS). - crc32 ^= 0xffffffff; /* complement */ - - if(crc32 != cpu2le32(trailfcs)) - { - DBGPRINT(RT_DEBUG_TRACE, ("! WEP Data CRC Error !\n")); //CRC error. - return (FALSE); - } - return (TRUE); -} - -/* - ======================================================================== - - Routine Description: - The Stream Cipher Encryption Algorithm "ARCFOUR" initialize - - Arguments: - Ctx Pointer to ARCFOUR CONTEXT (SBOX) - pKey Pointer to the WEP KEY - KeyLen Indicate the length fo the WEP KEY - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID ARCFOUR_INIT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pKey, - IN UINT KeyLen) -{ - UCHAR t, u; - UINT keyindex; - UINT stateindex; - PUCHAR state; - UINT counter; - - state = Ctx->STATE; - Ctx->X = 0; - Ctx->Y = 0; - for (counter = 0; counter < 256; counter++) - state[counter] = (UCHAR)counter; - keyindex = 0; - stateindex = 0; - for (counter = 0; counter < 256; counter++) - { - t = state[counter]; - stateindex = (stateindex + pKey[keyindex] + t) & 0xff; - u = state[stateindex]; - state[stateindex] = t; - state[counter] = u; - if (++keyindex >= KeyLen) - keyindex = 0; - } -} - -/* - ======================================================================== - - Routine Description: - Get bytes from ARCFOUR CONTEXT (S-BOX) - - Arguments: - Ctx Pointer to ARCFOUR CONTEXT (SBOX) - - Return Value: - UCHAR - the value of the ARCFOUR CONTEXT (S-BOX) - - Note: - - ======================================================================== -*/ -UCHAR ARCFOUR_BYTE( - IN PARCFOURCONTEXT Ctx) -{ - UINT x; - UINT y; - UCHAR sx, sy; - PUCHAR state; - - state = Ctx->STATE; - x = (Ctx->X + 1) & 0xff; - sx = state[x]; - y = (sx + Ctx->Y) & 0xff; - sy = state[y]; - Ctx->X = x; - Ctx->Y = y; - state[y] = sx; - state[x] = sy; - - return(state[(sx + sy) & 0xff]); - -} - -/* - ======================================================================== - - Routine Description: - The Stream Cipher Decryption Algorithm - - Arguments: - Ctx Pointer to ARCFOUR CONTEXT (SBOX) - pDest Pointer to the Destination - pSrc Pointer to the Source data - Len Indicate the length of the Source data - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID ARCFOUR_DECRYPT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pDest, - IN PUCHAR pSrc, - IN UINT Len) -{ - UINT i; - - for (i = 0; i < Len; i++) - pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); -} - -/* - ======================================================================== - - Routine Description: - The Stream Cipher Encryption Algorithm - - Arguments: - Ctx Pointer to ARCFOUR CONTEXT (SBOX) - pDest Pointer to the Destination - pSrc Pointer to the Source data - Len Indicate the length of the Source dta - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID ARCFOUR_ENCRYPT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pDest, - IN PUCHAR pSrc, - IN UINT Len) -{ - UINT i; - - for (i = 0; i < Len; i++) - pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); -} - -/* - ======================================================================== - - Routine Description: - The Stream Cipher Encryption Algorithm which conform to the special requirement to encrypt GTK. - - Arguments: - Ctx Pointer to ARCFOUR CONTEXT (SBOX) - pDest Pointer to the Destination - pSrc Pointer to the Source data - Len Indicate the length of the Source dta - - - ======================================================================== -*/ - -VOID WPAARCFOUR_ENCRYPT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pDest, - IN PUCHAR pSrc, - IN UINT Len) -{ - UINT i; - //discard first 256 bytes - for (i = 0; i < 256; i++) - ARCFOUR_BYTE(Ctx); - - for (i = 0; i < Len; i++) - pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); -} - - -/* - ======================================================================== - - Routine Description: - Calculate a new FCS given the current FCS and the new data. - - Arguments: - Fcs the original FCS value - Cp pointer to the data which will be calculate the FCS - Len the length of the data - - Return Value: - UINT - FCS 32 bits - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -UINT RTMP_CALC_FCS32( - IN UINT Fcs, - IN PUCHAR Cp, - IN INT Len) -{ - while (Len--) - Fcs = (((Fcs) >> 8) ^ FCSTAB_32[((Fcs) ^ (*Cp++)) & 0xff]); - - return (Fcs); -} - - -/* - ======================================================================== - - Routine Description: - Get last FCS and encrypt it to the destination - - Arguments: - pDest Pointer to the Destination - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID RTMPSetICV( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDest) -{ - pAd->PrivateInfo.FCSCRC32 ^= 0xffffffff; /* complement */ - pAd->PrivateInfo.FCSCRC32 = cpu2le32(pAd->PrivateInfo.FCSCRC32); - - ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, (PUCHAR) &pAd->PrivateInfo.FCSCRC32, 4); -} - diff --git a/drivers/staging/rt2860/common/spectrum.c b/drivers/staging/rt2860/common/spectrum.c index c658bf3082c31debc547042722966327939839c2..51e38d80933349161ed147e739e36902ba9ef61b 100644 --- a/drivers/staging/rt2860/common/spectrum.c +++ b/drivers/staging/rt2860/common/spectrum.c @@ -24,7 +24,6 @@ * * ************************************************************************* - Module Name: action.c @@ -40,24 +39,382 @@ #include "../rt_config.h" #include "action.h" -VOID MeasureReqTabInit( - IN PRTMP_ADAPTER pAd) +/* The regulatory information in the USA (US) */ +struct rt_dot11_regulatory_information USARegulatoryInfo[] = { +/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ + {0, {0, 0, {0} + } + } + , /* Invlid entry */ + {1, {4, 16, {36, 40, 44, 48} + } + } + , + {2, {4, 23, {52, 56, 60, 64} + } + } + , + {3, {4, 29, {149, 153, 157, 161} + } + } + , + {4, {11, 23, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140} + } + } + , + {5, {5, 30, {149, 153, 157, 161, 165} + } + } + , + {6, {10, 14, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + } + } + , + {7, {10, 27, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + } + } + , + {8, {5, 17, {11, 13, 15, 17, 19} + } + } + , + {9, {5, 30, {11, 13, 15, 17, 19} + } + } + , + {10, {2, 20, {21, 25} + } + } + , + {11, {2, 33, {21, 25} + } + } + , + {12, {11, 30, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} + } + } +}; + +#define USA_REGULATORY_INFO_SIZE (sizeof(USARegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information)) + +/* The regulatory information in Europe */ +struct rt_dot11_regulatory_information EuropeRegulatoryInfo[] = { +/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ + {0, {0, 0, {0} + } + } + , /* Invalid entry */ + {1, {4, 20, {36, 40, 44, 48} + } + } + , + {2, {4, 20, {52, 56, 60, 64} + } + } + , + {3, {11, 30, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140} + } + } + , + {4, {13, 20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} + } + } +}; + +#define EU_REGULATORY_INFO_SIZE (sizeof(EuropeRegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information)) + +/* The regulatory information in Japan */ +struct rt_dot11_regulatory_information JapanRegulatoryInfo[] = { +/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ + {0, {0, 0, {0} + } + } + , /* Invalid entry */ + {1, {4, 22, {34, 38, 42, 46} + } + } + , + {2, {3, 24, {8, 12, 16} + } + } + , + {3, {3, 24, {8, 12, 16} + } + } + , + {4, {3, 24, {8, 12, 16} + } + } + , + {5, {3, 24, {8, 12, 16} + } + } + , + {6, {3, 22, {8, 12, 16} + } + } + , + {7, {4, 24, {184, 188, 192, 196} + } + } + , + {8, {4, 24, {184, 188, 192, 196} + } + } + , + {9, {4, 24, {184, 188, 192, 196} + } + } + , + {10, {4, 24, {184, 188, 192, 196} + } + } + , + {11, {4, 22, {184, 188, 192, 196} + } + } + , + {12, {4, 24, {7, 8, 9, 11} + } + } + , + {13, {4, 24, {7, 8, 9, 11} + } + } + , + {14, {4, 24, {7, 8, 9, 11} + } + } + , + {15, {4, 24, {7, 8, 9, 11} + } + } + , + {16, {6, 24, {183, 184, 185, 187, 188, 189} + } + } + , + {17, {6, 24, {183, 184, 185, 187, 188, 189} + } + } + , + {18, {6, 24, {183, 184, 185, 187, 188, 189} + } + } + , + {19, {6, 24, {183, 184, 185, 187, 188, 189} + } + } + , + {20, {6, 17, {183, 184, 185, 187, 188, 189} + } + } + , + {21, {6, 24, {6, 7, 8, 9, 10, 11} + } + } + , + {22, {6, 24, {6, 7, 8, 9, 10, 11} + } + } + , + {23, {6, 24, {6, 7, 8, 9, 10, 11} + } + } + , + {24, {6, 24, {6, 7, 8, 9, 10, 11} + } + } + , + {25, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189} + } + } + , + {26, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189} + } + } + , + {27, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189} + } + } + , + {28, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189} + } + } + , + {29, {8, 17, {182, 183, 184, 185, 186, 187, 188, 189} + } + } + , + {30, {13, 23, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} + } + } + , + {31, {1, 23, {14} + } + } + , + {32, {4, 22, {52, 56, 60, 64} + } + } +}; + +#define JP_REGULATORY_INFO_SIZE (sizeof(JapanRegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information)) + +char RTMP_GetTxPwr(struct rt_rtmp_adapter *pAd, IN HTTRANSMIT_SETTING HTTxMode) +{ + struct tx_pwr_cfg { + u8 Mode; + u8 MCS; + u16 req; + u8 shift; + u32 BitMask; + }; + + u32 Value; + int Idx; + u8 PhyMode; + char CurTxPwr; + u8 TxPwrRef = 0; + char DaltaPwr; + unsigned long TxPwr[5]; + + struct tx_pwr_cfg TxPwrCfg[] = { + {MODE_CCK, 0, 0, 4, 0x000000f0}, + {MODE_CCK, 1, 0, 0, 0x0000000f}, + {MODE_CCK, 2, 0, 12, 0x0000f000}, + {MODE_CCK, 3, 0, 8, 0x00000f00}, + + {MODE_OFDM, 0, 0, 20, 0x00f00000}, + {MODE_OFDM, 1, 0, 16, 0x000f0000}, + {MODE_OFDM, 2, 0, 28, 0xf0000000}, + {MODE_OFDM, 3, 0, 24, 0x0f000000}, + {MODE_OFDM, 4, 1, 4, 0x000000f0}, + {MODE_OFDM, 5, 1, 0, 0x0000000f}, + {MODE_OFDM, 6, 1, 12, 0x0000f000}, + {MODE_OFDM, 7, 1, 8, 0x00000f00} + , {MODE_HTMIX, 0, 1, 20, 0x00f00000}, + {MODE_HTMIX, 1, 1, 16, 0x000f0000}, + {MODE_HTMIX, 2, 1, 28, 0xf0000000}, + {MODE_HTMIX, 3, 1, 24, 0x0f000000}, + {MODE_HTMIX, 4, 2, 4, 0x000000f0}, + {MODE_HTMIX, 5, 2, 0, 0x0000000f}, + {MODE_HTMIX, 6, 2, 12, 0x0000f000}, + {MODE_HTMIX, 7, 2, 8, 0x00000f00}, + {MODE_HTMIX, 8, 2, 20, 0x00f00000}, + {MODE_HTMIX, 9, 2, 16, 0x000f0000}, + {MODE_HTMIX, 10, 2, 28, 0xf0000000}, + {MODE_HTMIX, 11, 2, 24, 0x0f000000}, + {MODE_HTMIX, 12, 3, 4, 0x000000f0}, + {MODE_HTMIX, 13, 3, 0, 0x0000000f}, + {MODE_HTMIX, 14, 3, 12, 0x0000f000}, + {MODE_HTMIX, 15, 3, 8, 0x00000f00} + }; +#define MAX_TXPWR_TAB_SIZE (sizeof(TxPwrCfg) / sizeof(struct tx_pwr_cfg)) + + CurTxPwr = 19; + + /* check Tx Power setting from UI. */ + if (pAd->CommonCfg.TxPowerPercentage > 90) ; + else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */ + CurTxPwr -= 1; + else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */ + CurTxPwr -= 3; + else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */ + CurTxPwr -= 6; + else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */ + CurTxPwr -= 9; + else /* reduce Pwr for 12 dB. */ + CurTxPwr -= 12; + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) { + if (pAd->CommonCfg.CentralChannel > 14) { + TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; + } else { + TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; + } + } else { + if (pAd->CommonCfg.Channel > 14) { + TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; + } else { + TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; + } + } + + switch (HTTxMode.field.MODE) { + case MODE_CCK: + case MODE_OFDM: + Value = TxPwr[1]; + TxPwrRef = (Value & 0x00000f00) >> 8; + + break; + + case MODE_HTMIX: + case MODE_HTGREENFIELD: + if (pAd->CommonCfg.TxStream == 1) { + Value = TxPwr[2]; + TxPwrRef = (Value & 0x00000f00) >> 8; + } else if (pAd->CommonCfg.TxStream == 2) { + Value = TxPwr[3]; + TxPwrRef = (Value & 0x00000f00) >> 8; + } + break; + } + + PhyMode = (HTTxMode.field.MODE == MODE_HTGREENFIELD) + ? MODE_HTMIX : HTTxMode.field.MODE; + + for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++) { + if ((TxPwrCfg[Idx].Mode == PhyMode) + && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS)) { + Value = TxPwr[TxPwrCfg[Idx].req]; + DaltaPwr = + TxPwrRef - (char)((Value & TxPwrCfg[Idx].BitMask) + >> TxPwrCfg[Idx].shift); + CurTxPwr -= DaltaPwr; + break; + } + } + + return CurTxPwr; +} + +void MeasureReqTabInit(struct rt_rtmp_adapter *pAd) { NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock); - pAd->CommonCfg.pMeasureReqTab = kmalloc(sizeof(MEASURE_REQ_TAB), GFP_ATOMIC); + pAd->CommonCfg.pMeasureReqTab = + kmalloc(sizeof(struct rt_measure_req_tab), GFP_ATOMIC); if (pAd->CommonCfg.pMeasureReqTab) - NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, sizeof(MEASURE_REQ_TAB)); + NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, + sizeof(struct rt_measure_req_tab)); else - DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __func__)); + DBGPRINT(RT_DEBUG_ERROR, + ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", + __func__)); return; } -VOID MeasureReqTabExit( - IN PRTMP_ADAPTER pAd) +void MeasureReqTabExit(struct rt_rtmp_adapter *pAd) { - NdisFreeSpinLock(pAd->CommonCfg.MeasureReqTabLock); + NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock); if (pAd->CommonCfg.pMeasureReqTab) kfree(pAd->CommonCfg.pMeasureReqTab); @@ -66,18 +423,16 @@ VOID MeasureReqTabExit( return; } -static PMEASURE_REQ_ENTRY MeasureReqLookUp( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken) +struct rt_measure_req_entry *MeasureReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken) { - UINT HashIdx; - PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; - PMEASURE_REQ_ENTRY pEntry = NULL; - PMEASURE_REQ_ENTRY pPrevEntry = NULL; - - if (pTab == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__)); + u32 HashIdx; + struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab; + struct rt_measure_req_entry *pEntry = NULL; + struct rt_measure_req_entry *pPrevEntry = NULL; + + if (pTab == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: pMeasureReqTab doesn't exist.\n", __func__)); return NULL; } @@ -86,12 +441,10 @@ static PMEASURE_REQ_ENTRY MeasureReqLookUp( HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken); pEntry = pTab->Hash[HashIdx]; - while (pEntry) - { + while (pEntry) { if (pEntry->DialogToken == DialogToken) break; - else - { + else { pPrevEntry = pEntry; pEntry = pEntry->pNext; } @@ -102,50 +455,49 @@ static PMEASURE_REQ_ENTRY MeasureReqLookUp( return pEntry; } -static PMEASURE_REQ_ENTRY MeasureReqInsert( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken) +struct rt_measure_req_entry *MeasureReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken) { - INT i; - ULONG HashIdx; - PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; - PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry; - ULONG Now; - - if(pTab == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__)); + int i; + unsigned long HashIdx; + struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab; + struct rt_measure_req_entry *pEntry = NULL, *pCurrEntry; + unsigned long Now; + + if (pTab == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: pMeasureReqTab doesn't exist.\n", __func__)); return NULL; } pEntry = MeasureReqLookUp(pAd, DialogToken); - if (pEntry == NULL) - { + if (pEntry == NULL) { RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); - for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++) - { + for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++) { NdisGetSystemUpTime(&Now); pEntry = &pTab->Content[i]; if ((pEntry->Valid == TRUE) - && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + MQ_REQ_AGE_OUT))) + && RTMP_TIME_AFTER((unsigned long)Now, + (unsigned long)(pEntry-> + lastTime + + MQ_REQ_AGE_OUT))) { - PMEASURE_REQ_ENTRY pPrevEntry = NULL; - ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); - PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; - - // update Hash list - do - { - if (pProbeEntry == pEntry) - { - if (pPrevEntry == NULL) - { - pTab->Hash[HashIdx] = pEntry->pNext; - } - else - { - pPrevEntry->pNext = pEntry->pNext; + struct rt_measure_req_entry *pPrevEntry = NULL; + unsigned long HashIdx = + MQ_DIALOGTOKEN_HASH_INDEX(pEntry-> + DialogToken); + struct rt_measure_req_entry *pProbeEntry = + pTab->Hash[HashIdx]; + + /* update Hash list */ + do { + if (pProbeEntry == pEntry) { + if (pPrevEntry == NULL) { + pTab->Hash[HashIdx] = + pEntry->pNext; + } else { + pPrevEntry->pNext = + pEntry->pNext; } break; } @@ -154,7 +506,8 @@ static PMEASURE_REQ_ENTRY MeasureReqInsert( pProbeEntry = pProbeEntry->pNext; } while (pProbeEntry); - NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY)); + NdisZeroMemory(pEntry, + sizeof(struct rt_measure_req_entry)); pTab->Size--; break; @@ -164,30 +517,24 @@ static PMEASURE_REQ_ENTRY MeasureReqInsert( break; } - if (i < MAX_MEASURE_REQ_TAB_SIZE) - { + if (i < MAX_MEASURE_REQ_TAB_SIZE) { NdisGetSystemUpTime(&Now); pEntry->lastTime = Now; pEntry->Valid = TRUE; pEntry->DialogToken = DialogToken; pTab->Size++; - } - else - { + } else { pEntry = NULL; - DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab tab full.\n", __func__)); + DBGPRINT(RT_DEBUG_ERROR, + ("%s: pMeasureReqTab tab full.\n", __func__)); } - // add this Neighbor entry into HASH table - if (pEntry) - { + /* add this Neighbor entry into HASH table */ + if (pEntry) { HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken); - if (pTab->Hash[HashIdx] == NULL) - { + if (pTab->Hash[HashIdx] == NULL) { pTab->Hash[HashIdx] = pEntry; - } - else - { + } else { pCurrEntry = pTab->Hash[HashIdx]; while (pCurrEntry->pNext != NULL) pCurrEntry = pCurrEntry->pNext; @@ -201,45 +548,35 @@ static PMEASURE_REQ_ENTRY MeasureReqInsert( return pEntry; } -static VOID MeasureReqDelete( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken) +void MeasureReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken) { - PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; - PMEASURE_REQ_ENTRY pEntry = NULL; + struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab; + struct rt_measure_req_entry *pEntry = NULL; - if(pTab == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__)); + if (pTab == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: pMeasureReqTab doesn't exist.\n", __func__)); return; } - - // if empty, return - if (pTab->Size == 0) - { + /* if empty, return */ + if (pTab->Size == 0) { DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n")); return; } pEntry = MeasureReqLookUp(pAd, DialogToken); - if (pEntry != NULL) - { - PMEASURE_REQ_ENTRY pPrevEntry = NULL; - ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); - PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + if (pEntry != NULL) { + struct rt_measure_req_entry *pPrevEntry = NULL; + unsigned long HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); + struct rt_measure_req_entry *pProbeEntry = pTab->Hash[HashIdx]; RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); - // update Hash list - do - { - if (pProbeEntry == pEntry) - { - if (pPrevEntry == NULL) - { + /* update Hash list */ + do { + if (pProbeEntry == pEntry) { + if (pPrevEntry == NULL) { pTab->Hash[HashIdx] = pEntry->pNext; - } - else - { + } else { pPrevEntry->pNext = pEntry->pNext; } break; @@ -249,7 +586,7 @@ static VOID MeasureReqDelete( pProbeEntry = pProbeEntry->pNext; } while (pProbeEntry); - NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY)); + NdisZeroMemory(pEntry, sizeof(struct rt_measure_req_entry)); pTab->Size--; RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); @@ -258,24 +595,24 @@ static VOID MeasureReqDelete( return; } -VOID TpcReqTabInit( - IN PRTMP_ADAPTER pAd) +void TpcReqTabInit(struct rt_rtmp_adapter *pAd) { NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock); - pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(TPC_REQ_TAB), GFP_ATOMIC); + pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(struct rt_tpc_req_tab), GFP_ATOMIC); if (pAd->CommonCfg.pTpcReqTab) - NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(TPC_REQ_TAB)); + NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(struct rt_tpc_req_tab)); else - DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __func__)); + DBGPRINT(RT_DEBUG_ERROR, + ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", + __func__)); return; } -VOID TpcReqTabExit( - IN PRTMP_ADAPTER pAd) +void TpcReqTabExit(struct rt_rtmp_adapter *pAd) { - NdisFreeSpinLock(pAd->CommonCfg.TpcReqTabLock); + NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock); if (pAd->CommonCfg.pTpcReqTab) kfree(pAd->CommonCfg.pTpcReqTab); @@ -284,18 +621,16 @@ VOID TpcReqTabExit( return; } -static PTPC_REQ_ENTRY TpcReqLookUp( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken) +static struct rt_tpc_req_entry *TpcReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken) { - UINT HashIdx; - PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; - PTPC_REQ_ENTRY pEntry = NULL; - PTPC_REQ_ENTRY pPrevEntry = NULL; - - if (pTab == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__)); + u32 HashIdx; + struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab; + struct rt_tpc_req_entry *pEntry = NULL; + struct rt_tpc_req_entry *pPrevEntry = NULL; + + if (pTab == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: pTpcReqTab doesn't exist.\n", __func__)); return NULL; } @@ -304,12 +639,10 @@ static PTPC_REQ_ENTRY TpcReqLookUp( HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken); pEntry = pTab->Hash[HashIdx]; - while (pEntry) - { + while (pEntry) { if (pEntry->DialogToken == DialogToken) break; - else - { + else { pPrevEntry = pEntry; pEntry = pEntry->pNext; } @@ -320,51 +653,49 @@ static PTPC_REQ_ENTRY TpcReqLookUp( return pEntry; } - -static PTPC_REQ_ENTRY TpcReqInsert( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken) +static struct rt_tpc_req_entry *TpcReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken) { - INT i; - ULONG HashIdx; - PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; - PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry; - ULONG Now; - - if(pTab == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__)); + int i; + unsigned long HashIdx; + struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab; + struct rt_tpc_req_entry *pEntry = NULL, *pCurrEntry; + unsigned long Now; + + if (pTab == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: pTpcReqTab doesn't exist.\n", __func__)); return NULL; } pEntry = TpcReqLookUp(pAd, DialogToken); - if (pEntry == NULL) - { + if (pEntry == NULL) { RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); - for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++) - { + for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++) { NdisGetSystemUpTime(&Now); pEntry = &pTab->Content[i]; if ((pEntry->Valid == TRUE) - && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + TPC_REQ_AGE_OUT))) + && RTMP_TIME_AFTER((unsigned long)Now, + (unsigned long)(pEntry-> + lastTime + + TPC_REQ_AGE_OUT))) { - PTPC_REQ_ENTRY pPrevEntry = NULL; - ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); - PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; - - // update Hash list - do - { - if (pProbeEntry == pEntry) - { - if (pPrevEntry == NULL) - { - pTab->Hash[HashIdx] = pEntry->pNext; - } - else - { - pPrevEntry->pNext = pEntry->pNext; + struct rt_tpc_req_entry *pPrevEntry = NULL; + unsigned long HashIdx = + TPC_DIALOGTOKEN_HASH_INDEX(pEntry-> + DialogToken); + struct rt_tpc_req_entry *pProbeEntry = + pTab->Hash[HashIdx]; + + /* update Hash list */ + do { + if (pProbeEntry == pEntry) { + if (pPrevEntry == NULL) { + pTab->Hash[HashIdx] = + pEntry->pNext; + } else { + pPrevEntry->pNext = + pEntry->pNext; } break; } @@ -373,7 +704,7 @@ static PTPC_REQ_ENTRY TpcReqInsert( pProbeEntry = pProbeEntry->pNext; } while (pProbeEntry); - NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY)); + NdisZeroMemory(pEntry, sizeof(struct rt_tpc_req_entry)); pTab->Size--; break; @@ -383,30 +714,24 @@ static PTPC_REQ_ENTRY TpcReqInsert( break; } - if (i < MAX_TPC_REQ_TAB_SIZE) - { + if (i < MAX_TPC_REQ_TAB_SIZE) { NdisGetSystemUpTime(&Now); pEntry->lastTime = Now; pEntry->Valid = TRUE; pEntry->DialogToken = DialogToken; pTab->Size++; - } - else - { + } else { pEntry = NULL; - DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab tab full.\n", __func__)); + DBGPRINT(RT_DEBUG_ERROR, + ("%s: pTpcReqTab tab full.\n", __func__)); } - // add this Neighbor entry into HASH table - if (pEntry) - { + /* add this Neighbor entry into HASH table */ + if (pEntry) { HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken); - if (pTab->Hash[HashIdx] == NULL) - { + if (pTab->Hash[HashIdx] == NULL) { pTab->Hash[HashIdx] = pEntry; - } - else - { + } else { pCurrEntry = pTab->Hash[HashIdx]; while (pCurrEntry->pNext != NULL) pCurrEntry = pCurrEntry->pNext; @@ -420,45 +745,35 @@ static PTPC_REQ_ENTRY TpcReqInsert( return pEntry; } -static VOID TpcReqDelete( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken) +static void TpcReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken) { - PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; - PTPC_REQ_ENTRY pEntry = NULL; + struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab; + struct rt_tpc_req_entry *pEntry = NULL; - if(pTab == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__)); + if (pTab == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: pTpcReqTab doesn't exist.\n", __func__)); return; } - - // if empty, return - if (pTab->Size == 0) - { + /* if empty, return */ + if (pTab->Size == 0) { DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n")); return; } pEntry = TpcReqLookUp(pAd, DialogToken); - if (pEntry != NULL) - { - PTPC_REQ_ENTRY pPrevEntry = NULL; - ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); - PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + if (pEntry != NULL) { + struct rt_tpc_req_entry *pPrevEntry = NULL; + unsigned long HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); + struct rt_tpc_req_entry *pProbeEntry = pTab->Hash[HashIdx]; RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); - // update Hash list - do - { - if (pProbeEntry == pEntry) - { - if (pPrevEntry == NULL) - { + /* update Hash list */ + do { + if (pProbeEntry == pEntry) { + if (pPrevEntry == NULL) { pTab->Hash[HashIdx] = pEntry->pNext; - } - else - { + } else { pPrevEntry->pNext = pEntry->pNext; } break; @@ -468,7 +783,7 @@ static VOID TpcReqDelete( pProbeEntry = pProbeEntry->pNext; } while (pProbeEntry); - NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY)); + NdisZeroMemory(pEntry, sizeof(struct rt_tpc_req_entry)); pTab->Size--; RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); @@ -487,10 +802,9 @@ static VOID TpcReqDelete( Return : Current Time Stamp. ========================================================================== */ -static UINT64 GetCurrentTimeStamp( - IN PRTMP_ADAPTER pAd) +static u64 GetCurrentTimeStamp(struct rt_rtmp_adapter *pAd) { - // get current time stamp. + /* get current time stamp. */ return 0; } @@ -504,11 +818,73 @@ static UINT64 GetCurrentTimeStamp( Return : Current Time Stamp. ========================================================================== */ -static UINT8 GetCurTxPwr( - IN PRTMP_ADAPTER pAd, - IN UINT8 Wcid) +static u8 GetCurTxPwr(struct rt_rtmp_adapter *pAd, u8 Wcid) +{ + return 16; /* 16 dBm */ +} + +/* + ========================================================================== + Description: + Get Current Transmit Power. + + Parametrs: + + Return : Current Time Stamp. + ========================================================================== + */ +void InsertChannelRepIE(struct rt_rtmp_adapter *pAd, + u8 *pFrameBuf, + unsigned long *pFrameLen, + char *pCountry, u8 RegulatoryClass) { - return 16; /* 16 dBm */ + unsigned long TempLen; + u8 Len; + u8 IEId = IE_AP_CHANNEL_REPORT; + u8 *pChListPtr = NULL; + + Len = 1; + if (strncmp(pCountry, "US", 2) == 0) { + if (RegulatoryClass >= USA_REGULATORY_INFO_SIZE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: USA Unknow Requlatory class (%d)\n", + __func__, RegulatoryClass)); + return; + } + + Len += + USARegulatoryInfo[RegulatoryClass].ChannelSet. + NumberOfChannels; + pChListPtr = + USARegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList; + } else if (strncmp(pCountry, "JP", 2) == 0) { + if (RegulatoryClass >= JP_REGULATORY_INFO_SIZE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: JP Unknow Requlatory class (%d)\n", + __func__, RegulatoryClass)); + return; + } + + Len += + JapanRegulatoryInfo[RegulatoryClass].ChannelSet. + NumberOfChannels; + pChListPtr = + JapanRegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList; + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n", + __func__, pCountry)); + return; + } + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &IEId, + 1, &Len, + 1, &RegulatoryClass, + Len - 1, pChListPtr, END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; } /* @@ -524,16 +900,12 @@ static UINT8 GetCurTxPwr( Return : None. ========================================================================== */ -static VOID InsertDialogToken( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN UINT8 DialogToken) +void InsertDialogToken(struct rt_rtmp_adapter *pAd, + u8 *pFrameBuf, + unsigned long *pFrameLen, u8 DialogToken) { - ULONG TempLen; - MakeOutgoingFrame(pFrameBuf, &TempLen, - 1, &DialogToken, - END_OF_ARGS); + unsigned long TempLen; + MakeOutgoingFrame(pFrameBuf, &TempLen, 1, &DialogToken, END_OF_ARGS); *pFrameLen = *pFrameLen + TempLen; @@ -552,19 +924,15 @@ static VOID InsertDialogToken( Return : None. ========================================================================== */ - static VOID InsertTpcReqIE( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen) +static void InsertTpcReqIE(struct rt_rtmp_adapter *pAd, + u8 *pFrameBuf, unsigned long *pFrameLen) { - ULONG TempLen; - ULONG Len = 0; - UINT8 ElementID = IE_TPC_REQUEST; + unsigned long TempLen; + unsigned long Len = 0; + u8 ElementID = IE_TPC_REQUEST; - MakeOutgoingFrame(pFrameBuf, &TempLen, - 1, &ElementID, - 1, &Len, - END_OF_ARGS); + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, 1, &Len, END_OF_ARGS); *pFrameLen = *pFrameLen + TempLen; @@ -585,30 +953,25 @@ static VOID InsertDialogToken( Return : None. ========================================================================== */ - static VOID InsertTpcReportIE( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN UINT8 TxPwr, - IN UINT8 LinkMargin) +void InsertTpcReportIE(struct rt_rtmp_adapter *pAd, + u8 *pFrameBuf, + unsigned long *pFrameLen, + u8 TxPwr, u8 LinkMargin) { - ULONG TempLen; - ULONG Len = sizeof(TPC_REPORT_INFO); - UINT8 ElementID = IE_TPC_REPORT; - TPC_REPORT_INFO TpcReportIE; + unsigned long TempLen; + unsigned long Len = sizeof(struct rt_tpc_report_info); + u8 ElementID = IE_TPC_REPORT; + struct rt_tpc_report_info TpcReportIE; TpcReportIE.TxPwr = TxPwr; TpcReportIE.LinkMargin = LinkMargin; - MakeOutgoingFrame(pFrameBuf, &TempLen, - 1, &ElementID, - 1, &Len, - Len, &TpcReportIE, - END_OF_ARGS); + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, Len, &TpcReportIE, END_OF_ARGS); *pFrameLen = *pFrameLen + TempLen; - return; } @@ -627,32 +990,26 @@ static VOID InsertDialogToken( Return : None. ========================================================================== */ -static VOID InsertChSwAnnIE( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN UINT8 ChSwMode, - IN UINT8 NewChannel, - IN UINT8 ChSwCnt) +static void InsertChSwAnnIE(struct rt_rtmp_adapter *pAd, + u8 *pFrameBuf, + unsigned long *pFrameLen, + u8 ChSwMode, + u8 NewChannel, u8 ChSwCnt) { - ULONG TempLen; - ULONG Len = sizeof(CH_SW_ANN_INFO); - UINT8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT; - CH_SW_ANN_INFO ChSwAnnIE; + unsigned long TempLen; + unsigned long Len = sizeof(struct rt_ch_sw_ann_info); + u8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT; + struct rt_ch_sw_ann_info ChSwAnnIE; ChSwAnnIE.ChSwMode = ChSwMode; ChSwAnnIE.Channel = NewChannel; ChSwAnnIE.ChSwCnt = ChSwCnt; - MakeOutgoingFrame(pFrameBuf, &TempLen, - 1, &ElementID, - 1, &Len, - Len, &ChSwAnnIE, - END_OF_ARGS); + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, 1, &Len, Len, &ChSwAnnIE, END_OF_ARGS); *pFrameLen = *pFrameLen + TempLen; - return; } @@ -671,25 +1028,21 @@ static VOID InsertChSwAnnIE( 7. Measure Start time. 8. Measure Duration. - Return : None. ========================================================================== */ -static VOID InsertMeasureReqIE( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN PMEASURE_REQ_INFO pMeasureReqIE) +static void InsertMeasureReqIE(struct rt_rtmp_adapter *pAd, + u8 *pFrameBuf, + unsigned long *pFrameLen, + u8 Len, struct rt_measure_req_info * pMeasureReqIE) { - ULONG TempLen; - UINT8 Len = sizeof(MEASURE_REQ_INFO); - UINT8 ElementID = IE_MEASUREMENT_REQUEST; + unsigned long TempLen; + u8 ElementID = IE_MEASUREMENT_REQUEST; - MakeOutgoingFrame(pFrameBuf, &TempLen, - 1, &ElementID, - 1, &Len, - Len, pMeasureReqIE, - END_OF_ARGS); + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + sizeof(struct rt_measure_req_info), pMeasureReqIE, END_OF_ARGS); *pFrameLen = *pFrameLen + TempLen; @@ -713,33 +1066,27 @@ static VOID InsertMeasureReqIE( Return : None. ========================================================================== */ -static VOID InsertMeasureReportIE( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN PMEASURE_REPORT_INFO pMeasureReportIE, - IN UINT8 ReportLnfoLen, - IN PUINT8 pReportInfo) +static void InsertMeasureReportIE(struct rt_rtmp_adapter *pAd, + u8 *pFrameBuf, + unsigned long *pFrameLen, + struct rt_measure_report_info * pMeasureReportIE, + u8 ReportLnfoLen, u8 *pReportInfo) { - ULONG TempLen; - ULONG Len; - UINT8 ElementID = IE_MEASUREMENT_REPORT; + unsigned long TempLen; + unsigned long Len; + u8 ElementID = IE_MEASUREMENT_REPORT; - Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen; + Len = sizeof(struct rt_measure_report_info) + ReportLnfoLen; - MakeOutgoingFrame(pFrameBuf, &TempLen, - 1, &ElementID, - 1, &Len, - Len, pMeasureReportIE, - END_OF_ARGS); + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, Len, pMeasureReportIE, END_OF_ARGS); *pFrameLen = *pFrameLen + TempLen; - if ((ReportLnfoLen > 0) && (pReportInfo != NULL)) - { - MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen, - ReportLnfoLen, pReportInfo, - END_OF_ARGS); + if ((ReportLnfoLen > 0) && (pReportInfo != NULL)) { + MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen, + ReportLnfoLen, pReportInfo, END_OF_ARGS); *pFrameLen = *pFrameLen + TempLen; } @@ -758,53 +1105,40 @@ static VOID InsertMeasureReportIE( Return : None. ========================================================================== */ -VOID EnqueueMeasurementReq( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UINT8 MeasureToken, - IN UINT8 MeasureReqMode, - IN UINT8 MeasureReqType, - IN UINT8 MeasureCh, - IN UINT16 MeasureDuration) +void MakeMeasurementReqFrame(struct rt_rtmp_adapter *pAd, + u8 *pOutBuffer, + unsigned long *pFrameLen, + u8 TotalLen, + u8 Category, + u8 Action, + u8 MeasureToken, + u8 MeasureReqMode, + u8 MeasureReqType, u8 NumOfRepetitions) { - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen; - HEADER_802_11 ActHdr; - MEASURE_REQ_INFO MeasureReqIE; - UINT8 RmReqDailogToken = RandomByte(pAd); - UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd); - - // build action frame header. - MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, - pAd->CurrentAddress); + unsigned long TempLen; + struct rt_measure_req_info MeasureReqIE; - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__)); - return; - } - NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); - FrameLen = sizeof(HEADER_802_11); + InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category, + Action); - InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRQ); + /* fill Dialog Token */ + InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen, + MeasureToken); - // fill Dialog Token - InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, MeasureToken); + /* fill Number of repetitions. */ + if (Category == CATEGORY_RM) { + MakeOutgoingFrame((pOutBuffer + *pFrameLen), &TempLen, + 2, &NumOfRepetitions, END_OF_ARGS); - // prepare Measurement IE. - NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO)); - MeasureReqIE.Token = RmReqDailogToken; + *pFrameLen += TempLen; + } + /* prepare Measurement IE. */ + NdisZeroMemory(&MeasureReqIE, sizeof(struct rt_measure_req_info)); + MeasureReqIE.Token = MeasureToken; MeasureReqIE.ReqMode.word = MeasureReqMode; MeasureReqIE.ReqType = MeasureReqType; - MeasureReqIE.MeasureReq.ChNum = MeasureCh; - MeasureReqIE.MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime); - MeasureReqIE.MeasureReq.MeasureDuration = cpu2le16(MeasureDuration); - InsertMeasureReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureReqIE); - - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); + InsertMeasureReqIE(pAd, (pOutBuffer + *pFrameLen), pFrameLen, + TotalLen, &MeasureReqIE); return; } @@ -821,46 +1155,46 @@ VOID EnqueueMeasurementReq( Return : None. ========================================================================== */ -VOID EnqueueMeasurementRep( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UINT8 DialogToken, - IN UINT8 MeasureToken, - IN UINT8 MeasureReqMode, - IN UINT8 MeasureReqType, - IN UINT8 ReportInfoLen, - IN PUINT8 pReportInfo) +void EnqueueMeasurementRep(struct rt_rtmp_adapter *pAd, + u8 *pDA, + u8 DialogToken, + u8 MeasureToken, + u8 MeasureReqMode, + u8 MeasureReqType, + u8 ReportInfoLen, u8 *pReportInfo) { - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen; - HEADER_802_11 ActHdr; - MEASURE_REPORT_INFO MeasureRepIE; + u8 *pOutBuffer = NULL; + int NStatus; + unsigned long FrameLen; + struct rt_header_802_11 ActHdr; + struct rt_measure_report_info MeasureRepIE; - // build action frame header. + /* build action frame header. */ MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, - pAd->CurrentAddress); + pAd->CurrentAddress); - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__)); + NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s() allocate memory failed \n", __func__)); return; } - NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); - FrameLen = sizeof(HEADER_802_11); + NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); + FrameLen = sizeof(struct rt_header_802_11); - InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRP); + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, + CATEGORY_SPECTRUM, SPEC_MRP); - // fill Dialog Token + /* fill Dialog Token */ InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); - // prepare Measurement IE. - NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO)); + /* prepare Measurement IE. */ + NdisZeroMemory(&MeasureRepIE, sizeof(struct rt_measure_report_info)); MeasureRepIE.Token = MeasureToken; - MeasureRepIE.ReportMode.word = MeasureReqMode; + MeasureRepIE.ReportMode = MeasureReqMode; MeasureRepIE.ReportType = MeasureReqType; - InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureRepIE, ReportInfoLen, pReportInfo); + InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, + &MeasureRepIE, ReportInfoLen, pReportInfo); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); @@ -880,36 +1214,34 @@ VOID EnqueueMeasurementRep( Return : None. ========================================================================== */ -VOID EnqueueTPCReq( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UCHAR DialogToken) +void EnqueueTPCReq(struct rt_rtmp_adapter *pAd, u8 *pDA, u8 DialogToken) { - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen; + u8 *pOutBuffer = NULL; + int NStatus; + unsigned long FrameLen; - HEADER_802_11 ActHdr; + struct rt_header_802_11 ActHdr; - // build action frame header. + /* build action frame header. */ MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, - pAd->CurrentAddress); + pAd->CurrentAddress); - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__)); + NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s() allocate memory failed \n", __func__)); return; } - NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); - FrameLen = sizeof(HEADER_802_11); + NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); + FrameLen = sizeof(struct rt_header_802_11); - InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRQ); + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, + CATEGORY_SPECTRUM, SPEC_TPCRQ); - // fill Dialog Token + /* fill Dialog Token */ InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); - // Insert TPC Request IE. + /* Insert TPC Request IE. */ InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); @@ -930,39 +1262,38 @@ VOID EnqueueTPCReq( Return : None. ========================================================================== */ -VOID EnqueueTPCRep( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UINT8 DialogToken, - IN UINT8 TxPwr, - IN UINT8 LinkMargin) +void EnqueueTPCRep(struct rt_rtmp_adapter *pAd, + u8 *pDA, + u8 DialogToken, u8 TxPwr, u8 LinkMargin) { - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen; + u8 *pOutBuffer = NULL; + int NStatus; + unsigned long FrameLen; - HEADER_802_11 ActHdr; + struct rt_header_802_11 ActHdr; - // build action frame header. + /* build action frame header. */ MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, - pAd->CurrentAddress); + pAd->CurrentAddress); - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__)); + NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s() allocate memory failed \n", __func__)); return; } - NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); - FrameLen = sizeof(HEADER_802_11); + NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); + FrameLen = sizeof(struct rt_header_802_11); - InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRP); + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, + CATEGORY_SPECTRUM, SPEC_TPCRP); - // fill Dialog Token + /* fill Dialog Token */ InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); - // Insert TPC Request IE. - InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, LinkMargin); + /* Insert TPC Request IE. */ + InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, + LinkMargin); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); @@ -984,34 +1315,33 @@ VOID EnqueueTPCRep( Return : None. ========================================================================== */ -VOID EnqueueChSwAnn( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UINT8 ChSwMode, - IN UINT8 NewCh) +void EnqueueChSwAnn(struct rt_rtmp_adapter *pAd, + u8 *pDA, u8 ChSwMode, u8 NewCh) { - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen; + u8 *pOutBuffer = NULL; + int NStatus; + unsigned long FrameLen; - HEADER_802_11 ActHdr; + struct rt_header_802_11 ActHdr; - // build action frame header. + /* build action frame header. */ MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, - pAd->CurrentAddress); + pAd->CurrentAddress); - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__)); + NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s() allocate memory failed \n", __func__)); return; } - NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); - FrameLen = sizeof(HEADER_802_11); + NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); + FrameLen = sizeof(struct rt_header_802_11); - InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH); + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, + CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH); - InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, 0); + InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, + NewCh, 0); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); @@ -1019,55 +1349,43 @@ VOID EnqueueChSwAnn( return; } -static BOOLEAN DfsRequirementCheck( - IN PRTMP_ADAPTER pAd, - IN UINT8 Channel) +static BOOLEAN DfsRequirementCheck(struct rt_rtmp_adapter *pAd, u8 Channel) { BOOLEAN Result = FALSE; - INT i; + int i; - do - { - // check DFS procedure is running. - // make sure DFS procedure won't start twice. - if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) - { + do { + /* check DFS procedure is running. */ + /* make sure DFS procedure won't start twice. */ + if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) { Result = FALSE; break; } - - // check the new channel carried from Channel Switch Announcemnet is valid. - for (i=0; iChannelListNum; i++) - { + /* check the new channel carried from Channel Switch Announcemnet is valid. */ + for (i = 0; i < pAd->ChannelListNum; i++) { if ((Channel == pAd->ChannelList[i].Channel) - &&(pAd->ChannelList[i].RemainingTimeForUse == 0)) - { - // found radar signal in the channel. the channel can't use at least for 30 minutes. - pAd->ChannelList[i].RemainingTimeForUse = 1800;//30 min = 1800 sec + && (pAd->ChannelList[i].RemainingTimeForUse == 0)) { + /* found radar signal in the channel. the channel can't use at least for 30 minutes. */ + pAd->ChannelList[i].RemainingTimeForUse = 1800; /*30 min = 1800 sec */ Result = TRUE; break; } } - } while(FALSE); + } while (FALSE); return Result; } -VOID NotifyChSwAnnToPeerAPs( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pRA, - IN PUCHAR pTA, - IN UINT8 ChSwMode, - IN UINT8 Channel) +void NotifyChSwAnnToPeerAPs(struct rt_rtmp_adapter *pAd, + u8 *pRA, + u8 *pTA, u8 ChSwMode, u8 Channel) { } -static VOID StartDFSProcedure( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel, - IN UINT8 ChSwMode) +static void StartDFSProcedure(struct rt_rtmp_adapter *pAd, + u8 Channel, u8 ChSwMode) { - // start DFS procedure + /* start DFS procedure */ pAd->CommonCfg.Channel = Channel; N_ChannelCheck(pAd); @@ -1086,7 +1404,6 @@ static VOID StartDFSProcedure( 2. message length. 3. Channel switch announcement infomation buffer. - Return : None. ========================================================================== */ @@ -1098,44 +1415,45 @@ static VOID StartDFSProcedure( +----+-----+-----------+------------+-----------+ 1 1 1 1 1 */ -static BOOLEAN PeerChSwAnnSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PCH_SW_ANN_INFO pChSwAnnInfo) +static BOOLEAN PeerChSwAnnSanity(struct rt_rtmp_adapter *pAd, + void * pMsg, + unsigned long MsgLen, + struct rt_ch_sw_ann_info * pChSwAnnInfo) { - PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; - PUCHAR pFramePtr = Fr->Octet; + struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; + u8 *pFramePtr = Fr->Octet; BOOLEAN result = FALSE; - PEID_STRUCT eid_ptr; + struct rt_eid * eid_ptr; - // skip 802.11 header. - MsgLen -= sizeof(HEADER_802_11); + /* skip 802.11 header. */ + MsgLen -= sizeof(struct rt_header_802_11); - // skip category and action code. + /* skip category and action code. */ pFramePtr += 2; MsgLen -= 2; if (pChSwAnnInfo == NULL) return result; - eid_ptr = (PEID_STRUCT)pFramePtr; - while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) - { - switch(eid_ptr->Eid) - { - case IE_CHANNEL_SWITCH_ANNOUNCEMENT: - NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, 1); - NdisMoveMemory(&pChSwAnnInfo->Channel, eid_ptr->Octet + 1, 1); - NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, eid_ptr->Octet + 2, 1); - - result = TRUE; - break; + eid_ptr = (struct rt_eid *) pFramePtr; + while (((u8 *) eid_ptr + eid_ptr->Len + 1) < + ((u8 *)pFramePtr + MsgLen)) { + switch (eid_ptr->Eid) { + case IE_CHANNEL_SWITCH_ANNOUNCEMENT: + NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, + 1); + NdisMoveMemory(&pChSwAnnInfo->Channel, + eid_ptr->Octet + 1, 1); + NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, + eid_ptr->Octet + 2, 1); + + result = TRUE; + break; - default: - break; + default: + break; } - eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); } return result; @@ -1154,25 +1472,25 @@ static BOOLEAN PeerChSwAnnSanity( Return : None. ========================================================================== */ -static BOOLEAN PeerMeasureReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUINT8 pDialogToken, - OUT PMEASURE_REQ_INFO pMeasureReqInfo) +static BOOLEAN PeerMeasureReqSanity(struct rt_rtmp_adapter *pAd, + void * pMsg, + unsigned long MsgLen, + u8 *pDialogToken, + struct rt_measure_req_info * pMeasureReqInfo, + struct rt_measure_req * pMeasureReq) { - PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; - PUCHAR pFramePtr = Fr->Octet; + struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; + u8 *pFramePtr = Fr->Octet; BOOLEAN result = FALSE; - PEID_STRUCT eid_ptr; - PUCHAR ptr; - UINT64 MeasureStartTime; - UINT16 MeasureDuration; + struct rt_eid * eid_ptr; + u8 *ptr; + u64 MeasureStartTime; + u16 MeasureDuration; - // skip 802.11 header. - MsgLen -= sizeof(HEADER_802_11); + /* skip 802.11 header. */ + MsgLen -= sizeof(struct rt_header_802_11); - // skip category and action code. + /* skip category and action code. */ pFramePtr += 2; MsgLen -= 2; @@ -1183,29 +1501,32 @@ static BOOLEAN PeerMeasureReqSanity( pFramePtr += 1; MsgLen -= 1; - eid_ptr = (PEID_STRUCT)pFramePtr; - while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) - { - switch(eid_ptr->Eid) - { - case IE_MEASUREMENT_REQUEST: - NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, 1); - NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, eid_ptr->Octet + 1, 1); - NdisMoveMemory(&pMeasureReqInfo->ReqType, eid_ptr->Octet + 2, 1); - ptr = eid_ptr->Octet + 3; - NdisMoveMemory(&pMeasureReqInfo->MeasureReq.ChNum, ptr, 1); - NdisMoveMemory(&MeasureStartTime, ptr + 1, 8); - pMeasureReqInfo->MeasureReq.MeasureStartTime = SWAP64(MeasureStartTime); - NdisMoveMemory(&MeasureDuration, ptr + 9, 2); - pMeasureReqInfo->MeasureReq.MeasureDuration = SWAP16(MeasureDuration); - - result = TRUE; - break; + eid_ptr = (struct rt_eid *) pFramePtr; + while (((u8 *) eid_ptr + eid_ptr->Len + 1) < + ((u8 *)pFramePtr + MsgLen)) { + switch (eid_ptr->Eid) { + case IE_MEASUREMENT_REQUEST: + NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, + 1); + NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, + eid_ptr->Octet + 1, 1); + NdisMoveMemory(&pMeasureReqInfo->ReqType, + eid_ptr->Octet + 2, 1); + ptr = (u8 *)(eid_ptr->Octet + 3); + NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1); + NdisMoveMemory(&MeasureStartTime, ptr + 1, 8); + pMeasureReq->MeasureStartTime = + SWAP64(MeasureStartTime); + NdisMoveMemory(&MeasureDuration, ptr + 9, 2); + pMeasureReq->MeasureDuration = SWAP16(MeasureDuration); + + result = TRUE; + break; - default: - break; + default: + break; } - eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); } return result; @@ -1245,24 +1566,24 @@ static BOOLEAN PeerMeasureReqSanity( +-----+---------------+---------------------+-------+------------+----------+ 0 1 2 3 4 5-7 */ -static BOOLEAN PeerMeasureReportSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUINT8 pDialogToken, - OUT PMEASURE_REPORT_INFO pMeasureReportInfo, - OUT PUINT8 pReportBuf) +static BOOLEAN PeerMeasureReportSanity(struct rt_rtmp_adapter *pAd, + void * pMsg, + unsigned long MsgLen, + u8 *pDialogToken, + struct rt_measure_report_info * + pMeasureReportInfo, + u8 *pReportBuf) { - PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; - PUCHAR pFramePtr = Fr->Octet; + struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; + u8 *pFramePtr = Fr->Octet; BOOLEAN result = FALSE; - PEID_STRUCT eid_ptr; - PUCHAR ptr; + struct rt_eid * eid_ptr; + u8 *ptr; - // skip 802.11 header. - MsgLen -= sizeof(HEADER_802_11); + /* skip 802.11 header. */ + MsgLen -= sizeof(struct rt_header_802_11); - // skip category and action code. + /* skip category and action code. */ pFramePtr += 2; MsgLen -= 2; @@ -1273,51 +1594,60 @@ static BOOLEAN PeerMeasureReportSanity( pFramePtr += 1; MsgLen -= 1; - eid_ptr = (PEID_STRUCT)pFramePtr; - while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) - { - switch(eid_ptr->Eid) - { - case IE_MEASUREMENT_REPORT: - NdisMoveMemory(&pMeasureReportInfo->Token, eid_ptr->Octet, 1); - NdisMoveMemory(&pMeasureReportInfo->ReportMode, eid_ptr->Octet + 1, 1); - NdisMoveMemory(&pMeasureReportInfo->ReportType, eid_ptr->Octet + 2, 1); - if (pMeasureReportInfo->ReportType == RM_BASIC) - { - PMEASURE_BASIC_REPORT pReport = (PMEASURE_BASIC_REPORT)pReportBuf; - ptr = eid_ptr->Octet + 3; - NdisMoveMemory(&pReport->ChNum, ptr, 1); - NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); - NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); - NdisMoveMemory(&pReport->Map, ptr + 11, 1); - - } - else if (pMeasureReportInfo->ReportType == RM_CCA) - { - PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf; - ptr = eid_ptr->Octet + 3; - NdisMoveMemory(&pReport->ChNum, ptr, 1); - NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); - NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); - NdisMoveMemory(&pReport->CCA_Busy_Fraction, ptr + 11, 1); - - } - else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM) - { - PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf; - ptr = eid_ptr->Octet + 3; - NdisMoveMemory(&pReport->ChNum, ptr, 1); - NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); - NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); - NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 8); - } - result = TRUE; - break; + eid_ptr = (struct rt_eid *) pFramePtr; + while (((u8 *) eid_ptr + eid_ptr->Len + 1) < + ((u8 *)pFramePtr + MsgLen)) { + switch (eid_ptr->Eid) { + case IE_MEASUREMENT_REPORT: + NdisMoveMemory(&pMeasureReportInfo->Token, + eid_ptr->Octet, 1); + NdisMoveMemory(&pMeasureReportInfo->ReportMode, + eid_ptr->Octet + 1, 1); + NdisMoveMemory(&pMeasureReportInfo->ReportType, + eid_ptr->Octet + 2, 1); + if (pMeasureReportInfo->ReportType == RM_BASIC) { + struct rt_measure_basic_report * pReport = + (struct rt_measure_basic_report *) pReportBuf; + ptr = (u8 *)(eid_ptr->Octet + 3); + NdisMoveMemory(&pReport->ChNum, ptr, 1); + NdisMoveMemory(&pReport->MeasureStartTime, + ptr + 1, 8); + NdisMoveMemory(&pReport->MeasureDuration, + ptr + 9, 2); + NdisMoveMemory(&pReport->Map, ptr + 11, 1); + + } else if (pMeasureReportInfo->ReportType == RM_CCA) { + struct rt_measure_cca_report * pReport = + (struct rt_measure_cca_report *) pReportBuf; + ptr = (u8 *)(eid_ptr->Octet + 3); + NdisMoveMemory(&pReport->ChNum, ptr, 1); + NdisMoveMemory(&pReport->MeasureStartTime, + ptr + 1, 8); + NdisMoveMemory(&pReport->MeasureDuration, + ptr + 9, 2); + NdisMoveMemory(&pReport->CCA_Busy_Fraction, + ptr + 11, 1); + + } else if (pMeasureReportInfo->ReportType == + RM_RPI_HISTOGRAM) { + struct rt_measure_rpi_report * pReport = + (struct rt_measure_rpi_report *) pReportBuf; + ptr = (u8 *)(eid_ptr->Octet + 3); + NdisMoveMemory(&pReport->ChNum, ptr, 1); + NdisMoveMemory(&pReport->MeasureStartTime, + ptr + 1, 8); + NdisMoveMemory(&pReport->MeasureDuration, + ptr + 9, 2); + NdisMoveMemory(&pReport->RPI_Density, ptr + 11, + 8); + } + result = TRUE; + break; - default: - break; + default: + break; } - eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); } return result; @@ -1336,20 +1666,18 @@ static BOOLEAN PeerMeasureReportSanity( Return : None. ========================================================================== */ -static BOOLEAN PeerTpcReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUINT8 pDialogToken) +static BOOLEAN PeerTpcReqSanity(struct rt_rtmp_adapter *pAd, + void * pMsg, + unsigned long MsgLen, u8 *pDialogToken) { - PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; - PUCHAR pFramePtr = Fr->Octet; + struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; + u8 *pFramePtr = Fr->Octet; BOOLEAN result = FALSE; - PEID_STRUCT eid_ptr; + struct rt_eid * eid_ptr; - MsgLen -= sizeof(HEADER_802_11); + MsgLen -= sizeof(struct rt_header_802_11); - // skip category and action code. + /* skip category and action code. */ pFramePtr += 2; MsgLen -= 2; @@ -1360,19 +1688,18 @@ static BOOLEAN PeerTpcReqSanity( pFramePtr += 1; MsgLen -= 1; - eid_ptr = (PEID_STRUCT)pFramePtr; - while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) - { - switch(eid_ptr->Eid) - { - case IE_TPC_REQUEST: - result = TRUE; - break; + eid_ptr = (struct rt_eid *) pFramePtr; + while (((u8 *) eid_ptr + eid_ptr->Len + 1) < + ((u8 *)pFramePtr + MsgLen)) { + switch (eid_ptr->Eid) { + case IE_TPC_REQUEST: + result = TRUE; + break; - default: - break; + default: + break; } - eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); } return result; @@ -1392,21 +1719,20 @@ static BOOLEAN PeerTpcReqSanity( Return : None. ========================================================================== */ -static BOOLEAN PeerTpcRepSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUINT8 pDialogToken, - OUT PTPC_REPORT_INFO pTpcRepInfo) +static BOOLEAN PeerTpcRepSanity(struct rt_rtmp_adapter *pAd, + void * pMsg, + unsigned long MsgLen, + u8 *pDialogToken, + struct rt_tpc_report_info * pTpcRepInfo) { - PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; - PUCHAR pFramePtr = Fr->Octet; + struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; + u8 *pFramePtr = Fr->Octet; BOOLEAN result = FALSE; - PEID_STRUCT eid_ptr; + struct rt_eid * eid_ptr; - MsgLen -= sizeof(HEADER_802_11); + MsgLen -= sizeof(struct rt_header_802_11); - // skip category and action code. + /* skip category and action code. */ pFramePtr += 2; MsgLen -= 2; @@ -1417,21 +1743,21 @@ static BOOLEAN PeerTpcRepSanity( pFramePtr += 1; MsgLen -= 1; - eid_ptr = (PEID_STRUCT)pFramePtr; - while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) - { - switch(eid_ptr->Eid) - { - case IE_TPC_REPORT: - NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1); - NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1); - result = TRUE; - break; - - default: - break; + eid_ptr = (struct rt_eid *) pFramePtr; + while (((u8 *) eid_ptr + eid_ptr->Len + 1) < + ((u8 *)pFramePtr + MsgLen)) { + switch (eid_ptr->Eid) { + case IE_TPC_REPORT: + NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1); + NdisMoveMemory(&pTpcRepInfo->LinkMargin, + eid_ptr->Octet + 1, 1); + result = TRUE; + break; + + default: + break; } - eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); } return result; @@ -1448,64 +1774,69 @@ static BOOLEAN PeerTpcRepSanity( Return : None. ========================================================================== */ -static VOID PeerChSwAnnAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +static void PeerChSwAnnAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - CH_SW_ANN_INFO ChSwAnnInfo; - PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; - UCHAR index = 0, Channel = 0, NewChannel = 0; - ULONG Bssidx = 0; - - NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO)); - if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) - { - DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n")); + struct rt_ch_sw_ann_info ChSwAnnInfo; + struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg; + u8 index = 0, Channel = 0, NewChannel = 0; + unsigned long Bssidx = 0; + + NdisZeroMemory(&ChSwAnnInfo, sizeof(struct rt_ch_sw_ann_info)); + if (!PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) { + DBGPRINT(RT_DEBUG_TRACE, + ("Invalid Channel Switch Action Frame.\n")); return; } - if (pAd->OpMode == OPMODE_STA) - { - Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel); - if (Bssidx == BSS_NOT_FOUND) - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n")); + if (pAd->OpMode == OPMODE_STA) { + Bssidx = + BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, + pAd->CommonCfg.Channel); + if (Bssidx == BSS_NOT_FOUND) { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerChSwAnnAction - Bssidx is not found\n")); return; } - DBGPRINT(RT_DEBUG_TRACE, ("\n****Bssidx is %d, Channel = %d\n", index, pAd->ScanTab.BssEntry[Bssidx].Channel)); - hex_dump("SSID",pAd->ScanTab.BssEntry[Bssidx].Bssid ,6); + DBGPRINT(RT_DEBUG_TRACE, + ("\n****Bssidx is %d, Channel = %d\n", index, + pAd->ScanTab.BssEntry[Bssidx].Channel)); + hex_dump("SSID", pAd->ScanTab.BssEntry[Bssidx].Bssid, 6); Channel = pAd->CommonCfg.Channel; NewChannel = ChSwAnnInfo.Channel; - if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel)) - { - // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). - // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. + if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) + && (Channel != NewChannel)) { + /* Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). */ + /* In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. */ AsicSwitchChannel(pAd, 1, FALSE); AsicLockChannel(pAd, 1); - LinkDown(pAd, FALSE); + LinkDown(pAd, FALSE); MlmeQueueInit(&pAd->Mlme.Queue); BssTableInit(&pAd->ScanTab); - RTMPusecDelay(1000000); // use delay to prevent STA do reassoc - - // channel sanity check - for (index = 0 ; index < pAd->ChannelListNum; index++) - { - if (pAd->ChannelList[index].Channel == NewChannel) - { - pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel; + RTMPusecDelay(1000000); /* use delay to prevent STA do reassoc */ + + /* channel sanity check */ + for (index = 0; index < pAd->ChannelListNum; index++) { + if (pAd->ChannelList[index].Channel == + NewChannel) { + pAd->ScanTab.BssEntry[Bssidx].Channel = + NewChannel; pAd->CommonCfg.Channel = NewChannel; - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel)); + AsicSwitchChannel(pAd, + pAd->CommonCfg. + Channel, FALSE); + AsicLockChannel(pAd, + pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, + ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", + NewChannel)); break; } } - if (index >= pAd->ChannelListNum) - { + if (index >= pAd->ChannelListNum) { DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); } } @@ -1514,7 +1845,6 @@ static VOID PeerChSwAnnAction( return; } - /* ========================================================================== Description: @@ -1526,20 +1856,23 @@ static VOID PeerChSwAnnAction( Return : None. ========================================================================== */ -static VOID PeerMeasureReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +static void PeerMeasureReqAction(struct rt_rtmp_adapter *pAd, + struct rt_mlme_queue_elem *Elem) { - PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; - UINT8 DialogToken; - MEASURE_REQ_INFO MeasureReqInfo; + struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg; + u8 DialogToken; + struct rt_measure_req_info MeasureReqInfo; + struct rt_measure_req MeasureReq; MEASURE_REPORT_MODE ReportMode; - if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo)) - { + if (PeerMeasureReqSanity + (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo, + &MeasureReq)) { ReportMode.word = 0; ReportMode.field.Incapable = 1; - EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL); + EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, + MeasureReqInfo.Token, ReportMode.word, + MeasureReqInfo.ReqType, 0, NULL); } return; @@ -1556,54 +1889,65 @@ static VOID PeerMeasureReqAction( Return : None. ========================================================================== */ -static VOID PeerMeasureReportAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +static void PeerMeasureReportAction(struct rt_rtmp_adapter *pAd, + struct rt_mlme_queue_elem *Elem) { - MEASURE_REPORT_INFO MeasureReportInfo; - PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; - UINT8 DialogToken; - PUINT8 pMeasureReportInfo; - -// if (pAd->CommonCfg.bIEEE80211H != TRUE) -// return; - - if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%zu).\n", __func__, sizeof(MEASURE_RPI_REPORT))); + struct rt_measure_report_info MeasureReportInfo; + struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg; + u8 DialogToken; + u8 *pMeasureReportInfo; + +/* if (pAd->CommonCfg.bIEEE80211H != TRUE) */ +/* return; */ + + if ((pMeasureReportInfo = + kmalloc(sizeof(struct rt_measure_rpi_report), GFP_ATOMIC)) == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s unable to alloc memory for measure report buffer (size=%zu).\n", + __func__, sizeof(struct rt_measure_rpi_report))); return; } - NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO)); - NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT)); - if (PeerMeasureReportSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, pMeasureReportInfo)) - { + NdisZeroMemory(&MeasureReportInfo, sizeof(struct rt_measure_report_info)); + NdisZeroMemory(pMeasureReportInfo, sizeof(struct rt_measure_rpi_report)); + if (PeerMeasureReportSanity + (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, + pMeasureReportInfo)) { do { - PMEASURE_REQ_ENTRY pEntry = NULL; + struct rt_measure_req_entry *pEntry = NULL; - // Not a autonomous measure report. - // check the dialog token field. drop it if the dialog token doesn't match. + /* Not a autonomous measure report. */ + /* check the dialog token field. drop it if the dialog token doesn't match. */ if ((DialogToken != 0) - && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL)) + && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == + NULL)) break; if (pEntry != NULL) MeasureReqDelete(pAd, pEntry->DialogToken); - if (MeasureReportInfo.ReportType == RM_BASIC) - { - PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo; + if (MeasureReportInfo.ReportType == RM_BASIC) { + struct rt_measure_basic_report * pBasicReport = + (struct rt_measure_basic_report *) pMeasureReportInfo; if ((pBasicReport->Map.field.Radar) - && (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE)) - { - NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum); - StartDFSProcedure(pAd, pBasicReport->ChNum, 1); + && + (DfsRequirementCheck + (pAd, pBasicReport->ChNum) == TRUE)) { + NotifyChSwAnnToPeerAPs(pAd, + pFr->Hdr.Addr1, + pFr->Hdr.Addr2, + 1, + pBasicReport-> + ChNum); + StartDFSProcedure(pAd, + pBasicReport->ChNum, + 1); } } } while (FALSE); - } - else - DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n")); + } else + DBGPRINT(RT_DEBUG_TRACE, + ("Invalid Measurement Report Frame.\n")); kfree(pMeasureReportInfo); @@ -1621,34 +1965,33 @@ static VOID PeerMeasureReportAction( Return : None. ========================================================================== */ -static VOID PeerTpcReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +static void PeerTpcReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; - PUCHAR pFramePtr = pFr->Octet; - UINT8 DialogToken; - UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid); - UINT8 LinkMargin = 0; - CHAR RealRssi; + struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg; + u8 *pFramePtr = pFr->Octet; + u8 DialogToken; + u8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid); + u8 LinkMargin = 0; + char RealRssi; - // link margin: Ratio of the received signal power to the minimum desired by the station (STA). The - // STA may incorporate rate information and channel conditions, including interference, into its computation - // of link margin. + /* link margin: Ratio of the received signal power to the minimum desired by the station (STA). The */ + /* STA may incorporate rate information and channel conditions, including interference, into its computation */ + /* of link margin. */ RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), - ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), - ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); - // skip Category and action code. + /* skip Category and action code. */ pFramePtr += 2; - // Dialog token. + /* Dialog token. */ NdisMoveMemory(&DialogToken, pFramePtr, 1); LinkMargin = (RealRssi / MIN_RCV_PWR); if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken)) - EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin); + EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, + LinkMargin); return; } @@ -1664,22 +2007,21 @@ static VOID PeerTpcReqAction( Return : None. ========================================================================== */ -static VOID PeerTpcRepAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +static void PeerTpcRepAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UINT8 DialogToken; - TPC_REPORT_INFO TpcRepInfo; - PTPC_REQ_ENTRY pEntry = NULL; - - NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO)); - if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) - { - if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL) - { + u8 DialogToken; + struct rt_tpc_report_info TpcRepInfo; + struct rt_tpc_req_entry *pEntry = NULL; + + NdisZeroMemory(&TpcRepInfo, sizeof(struct rt_tpc_report_info)); + if (PeerTpcRepSanity + (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) { + if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL) { TpcReqDelete(pAd, pEntry->DialogToken); - DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n", - __func__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin)); + DBGPRINT(RT_DEBUG_TRACE, + ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n", + __func__, DialogToken, TpcRepInfo.TxPwr, + TpcRepInfo.LinkMargin)); } } @@ -1698,41 +2040,37 @@ static VOID PeerTpcRepAction( Return : None. ========================================================================== */ -VOID PeerSpectrumAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void PeerSpectrumAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + u8 Action = Elem->Msg[LENGTH_802_11 + 1]; if (pAd->CommonCfg.bIEEE80211H != TRUE) return; - switch(Action) - { - case SPEC_MRQ: - // current rt2860 unable do such measure specified in Measurement Request. - // reject all measurement request. - PeerMeasureReqAction(pAd, Elem); - break; + switch (Action) { + case SPEC_MRQ: + /* current rt2860 unable do such measure specified in Measurement Request. */ + /* reject all measurement request. */ + PeerMeasureReqAction(pAd, Elem); + break; - case SPEC_MRP: - PeerMeasureReportAction(pAd, Elem); - break; + case SPEC_MRP: + PeerMeasureReportAction(pAd, Elem); + break; - case SPEC_TPCRQ: - PeerTpcReqAction(pAd, Elem); - break; + case SPEC_TPCRQ: + PeerTpcReqAction(pAd, Elem); + break; - case SPEC_TPCRP: - PeerTpcRepAction(pAd, Elem); - break; + case SPEC_TPCRP: + PeerTpcRepAction(pAd, Elem); + break; - case SPEC_CHANNEL_SWITCH: -{ -} - PeerChSwAnnAction(pAd, Elem); - break; + case SPEC_CHANNEL_SWITCH: + + PeerChSwAnnAction(pAd, Elem); + break; } return; @@ -1747,49 +2085,63 @@ VOID PeerSpectrumAction( Return : None. ========================================================================== */ -INT Set_MeasureReq_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) +int Set_MeasureReq_Proc(struct rt_rtmp_adapter *pAd, char *arg) { - UINT Aid = 1; - UINT ArgIdx; - PUCHAR thisChar; + u32 Aid = 1; + u32 ArgIdx; + char *thisChar; MEASURE_REQ_MODE MeasureReqMode; - UINT8 MeasureReqToken = RandomByte(pAd); - UINT8 MeasureReqType = RM_BASIC; - UINT8 MeasureCh = 1; + u8 MeasureReqToken = RandomByte(pAd); + u8 MeasureReqType = RM_BASIC; + u8 MeasureCh = 1; + u64 MeasureStartTime = GetCurrentTimeStamp(pAd); + struct rt_measure_req MeasureReq; + u8 TotalLen; + + struct rt_header_802_11 ActHdr; + u8 *pOutBuffer = NULL; + int NStatus; + unsigned long FrameLen; + + NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s() allocate memory failed \n", __func__)); + goto END_OF_MEASURE_REQ; + } ArgIdx = 1; - while ((thisChar = strsep((char **)&arg, "-")) != NULL) - { - switch(ArgIdx) - { - case 1: // Aid. - Aid = simple_strtol(thisChar, 0, 16); - break; + while ((thisChar = strsep((char **)&arg, "-")) != NULL) { + switch (ArgIdx) { + case 1: /* Aid. */ + Aid = (u8)simple_strtol(thisChar, 0, 16); + break; - case 2: // Measurement Request Type. - MeasureReqType = simple_strtol(thisChar, 0, 16); - if (MeasureReqType > 3) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __func__, MeasureReqType)); - return TRUE; - } - break; + case 2: /* Measurement Request Type. */ + MeasureReqType = simple_strtol(thisChar, 0, 16); + if (MeasureReqType > 3) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: unknow MeasureReqType(%d)\n", + __func__, MeasureReqType)); + goto END_OF_MEASURE_REQ; + } + break; - case 3: // Measurement channel. - MeasureCh = simple_strtol(thisChar, 0, 16); - break; + case 3: /* Measurement channel. */ + MeasureCh = (u8)simple_strtol(thisChar, 0, 16); + break; } ArgIdx++; } - DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__, Aid, MeasureReqType, MeasureCh)); - if (!VALID_WCID(Aid)) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid)); - return TRUE; + DBGPRINT(RT_DEBUG_TRACE, + ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__, + Aid, MeasureReqType, MeasureCh)); + if (!VALID_WCID(Aid)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: unknow sta of Aid(%d)\n", __func__, Aid)); + goto END_OF_MEASURE_REQ; } MeasureReqMode.word = 0; @@ -1797,26 +2149,52 @@ INT Set_MeasureReq_Proc( MeasureReqInsert(pAd, MeasureReqToken); - EnqueueMeasurementReq(pAd, pAd->MacTab.Content[Aid].Addr, - MeasureReqToken, MeasureReqMode.word, MeasureReqType, MeasureCh, 2000); + /* build action frame header. */ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, + pAd->MacTab.Content[Aid].Addr, pAd->CurrentAddress); + + NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); + FrameLen = sizeof(struct rt_header_802_11); + + TotalLen = sizeof(struct rt_measure_req_info) + sizeof(struct rt_measure_req); + + MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen, + sizeof(struct rt_measure_req_info), CATEGORY_RM, RM_BASIC, + MeasureReqToken, MeasureReqMode.word, + MeasureReqType, 0); + + MeasureReq.ChNum = MeasureCh; + MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime); + MeasureReq.MeasureDuration = cpu2le16(2000); + + { + unsigned long TempLen; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen, + sizeof(struct rt_measure_req), &MeasureReq, + END_OF_ARGS); + FrameLen += TempLen; + } + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (u32)FrameLen); + +END_OF_MEASURE_REQ: + MlmeFreeMemory(pAd, pOutBuffer); return TRUE; } -INT Set_TpcReq_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) +int Set_TpcReq_Proc(struct rt_rtmp_adapter *pAd, char *arg) { - UINT Aid; + u32 Aid; - UINT8 TpcReqToken = RandomByte(pAd); + u8 TpcReqToken = RandomByte(pAd); - Aid = simple_strtol(arg, 0, 16); + Aid = (u32)simple_strtol(arg, 0, 16); DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid)); - if (!VALID_WCID(Aid)) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid)); + if (!VALID_WCID(Aid)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: unknow sta of Aid(%d)\n", __func__, Aid)); return TRUE; } @@ -1826,4 +2204,3 @@ INT Set_TpcReq_Proc( return TRUE; } - diff --git a/drivers/staging/rt2860/config.mk b/drivers/staging/rt2860/config.mk deleted file mode 100644 index 25bd55a7aab36a2cbd64cdd7538dd72b655e5827..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2860/config.mk +++ /dev/null @@ -1,241 +0,0 @@ -# Support ATE function -HAS_ATE=n - -# Support 28xx QA ATE function -HAS_28xx_QA=n - -# Support Wpa_Supplicant -HAS_WPA_SUPPLICANT=n - -# Support Native WpaSupplicant for Network Maganger -HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=n - -#Support Net interface block while Tx-Sw queue full -HAS_BLOCK_NET_IF=n - -#Support DFS function -HAS_DFS_SUPPORT=n - -#Support Carrier-Sense function -HAS_CS_SUPPORT=n - -#ifdef MULTI_CARD -# Support for Multiple Cards -HAS_MC_SUPPORT=n -#endif // MULTI_CARD // - -#Support for IEEE802.11e DLS -HAS_QOS_DLS_SUPPORT=n - -#Support for EXT_CHANNEL -HAS_EXT_BUILD_CHANNEL_LIST=n - -#Support for Net-SNMP -HAS_SNMP_SUPPORT=n - -#Support features of Single SKU. -HAS_SINGLE_SKU_SUPPORT=n - -#Support features of 802.11n -HAS_DOT11_N_SUPPORT=y - - -################################################# - -CC := $(CROSS_COMPILE)gcc -LD := $(CROSS_COMPILE)ld - -WFLAGS := -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -DLINUX -Wall -Wstrict-prototypes -Wno-trigraphs - - -################################################# - -#ifdef CONFIG_STA_SUPPORT -# config for STA mode - -ifeq ($(RT28xx_MODE),STA) -WFLAGS += -DCONFIG_STA_SUPPORT -DDBG - -ifeq ($(HAS_WPA_SUPPLICANT),y) -WFLAGS += -DWPA_SUPPLICANT_SUPPORT -endif - -ifeq ($(HAS_NATIVE_WPA_SUPPLICANT_SUPPORT),y) -WFLAGS += -DNATIVE_WPA_SUPPLICANT_SUPPORT -endif - -ifeq ($(HAS_ATE),y) -WFLAGS += -DRALINK_ATE -ifeq ($(HAS_28xx_QA),y) -WFLAGS += -DRALINK_28xx_QA -endif -endif - -ifeq ($(HAS_SNMP_SUPPORT),y) -WFLAGS += -DSNMP_SUPPORT -endif - -ifeq ($(HAS_QOS_DLS_SUPPORT),y) -WFLAGS += -DQOS_DLS_SUPPORT -endif - -ifeq ($(HAS_DOT11_N_SUPPORT),y) -WFLAGS += -DDOT11_N_SUPPORT -endif - -ifeq ($(HAS_CS_SUPPORT),y) -WFLAGS += -DCARRIER_DETECTION_SUPPORT -endif - -ifeq ($(HAS_SINGLE_SKU_SUPPORT),y) -WFLAGS += -DSINGLE_SKU -endif - -endif -# endif of ifeq ($(RT28xx_MODE),STA) -#endif // CONFIG_STA_SUPPORT // - -################################################# - -################################################# - -# -# Common compiler flag -# - - -ifeq ($(HAS_EXT_BUILD_CHANNEL_LIST),y) -WFLAGS += -DEXT_BUILD_CHANNEL_LIST -endif - -ifeq ($(CHIPSET),2870) -WFLAGS +=-DRT2870 -endif - -ifeq ($(PLATFORM),5VT) -#WFLAGS += -DCONFIG_5VT_ENHANCE -endif - -ifeq ($(HAS_BLOCK_NET_IF),y) -WFLAGS += -DBLOCK_NET_IF -endif - -ifeq ($(HAS_DFS_SUPPORT),y) -WFLAGS += -DDFS_SUPPORT -endif - -#ifdef MULTI_CARD -ifeq ($(HAS_MC_SUPPORT),y) -WFLAGS += -DMULTIPLE_CARD_SUPPORT -endif -#endif // MULTI_CARD // - -ifeq ($(HAS_LLTD),y) -WFLAGS += -DLLTD_SUPPORT -endif - -ifeq ($(PLATFORM),IXP) -WFLAGS += -DRT_BIG_ENDIAN -endif - -ifeq ($(PLATFORM),IKANOS_V160) -WFLAGS += -DRT_BIG_ENDIAN -DIKANOS_VX_1X0 -endif - -ifeq ($(PLATFORM),IKANOS_V180) -WFLAGS += -DRT_BIG_ENDIAN -DIKANOS_VX_1X0 -endif - -ifeq ($(PLATFORM),INF_TWINPASS) -WFLAGS += -DRT_BIG_ENDIAN -DINF_TWINPASS -endif - -ifeq ($(PLATFORM),INF_DANUBE) -WFLAGS += -DINF_DANUBE -DRT_BIG_ENDIAN -endif - -ifeq ($(PLATFORM),CAVM_OCTEON) -WFLAGS += -DRT_BIG_ENDIAN -endif - -ifeq ($(PLATFORM),BRCM_6358) -WFLAGS += -DRT_BIG_ENDIAN -endif - -ifeq ($(PLATFORM),INF_AMAZON_SE) -#WFLAGS += -DRT_BIG_ENDIAN -DINF_AMAZON_SE -DBG_FT_SUPPORT -WFLAGS += -DRT_BIG_ENDIAN -DINF_AMAZON_SE -endif - -#kernel build options for 2.4 -# move to Makefile outside LINUX_SRC := /opt/star/kernel/linux-2.4.27-star - -ifeq ($(PLATFORM),STAR) -CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -Uarm -fno-common -pipe -mapcs-32 -D__LINUX_ARM_ARCH__=4 -march=armv4 -mshort-load-bytes -msoft-float -Uarm -DMODULE -DMODVERSIONS -include $(LINUX_SRC)/include/linux/modversions.h $(WFLAGS) - -export CFLAGS -endif - -ifeq ($(PLATFORM),SIGMA) -CFLAGS := -D__KERNEL__ -I$(RT28xx_DIR)/include -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -DEM86XX_CHIP=EM86XX_CHIPID_TANGO2 -DEM86XX_REVISION=6 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT2860_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -mabi=32 -march=mips32r2 -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap -DMODULE $(WFLAGS) - -export CFLAGS -endif - -ifeq ($(PLATFORM),SIGMA_8622) -CFLAGS := -D__KERNEL__ -I$(CROSS_COMPILE_INCLUDE)/include -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fno-common -pipe -fno-builtin -D__linux__ -DNO_MM -mapcs-32 -march=armv4 -mtune=arm7tdmi -msoft-float -DMODULE -mshort-load-bytes -nostdinc -iwithprefix -DMODULE $(WFLAGS) -export CFLAGS -endif - -ifeq ($(PLATFORM),5VT) -CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -mlittle-endian -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-omit-frame-pointer -mapcs -mno-sched-prolog -mabi=apcs-gnu -mno-thumb-interwork -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm926ej-s --param max-inline-insns-single=40000 -Uarm -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE $(WFLAGS) - -export CFLAGS -endif - -ifeq ($(PLATFORM),IKANOS_V160) -CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT28xx_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -march=lx4189 -Wa, -DMODULE $(WFLAGS) -export CFLAGS -endif - -ifeq ($(PLATFORM),IKANOS_V180) -CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT28xx_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -mips32r2 -Wa, -DMODULE $(WFLAGS) -export CFLAGS -endif - -ifeq ($(PLATFORM),INF_TWINPASS) -CFLAGS := -D__KERNEL__ -DMODULE -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -G 0 -mno-abicalls -fno-pic -march=4kc -mips32 -Wa,--trap -pipe -mlong-calls $(WFLAGS) -export CFLAGS -endif - -ifeq ($(PLATFORM),INF_DANUBE) -CFLAGS := -I$(RT28xx_DIR)/include $(WFLAGS) -Wundef -fno-strict-aliasing -fno-common -ffreestanding -Os -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap -I$(LINUX_SRC)/include/asm-mips/mach-generic -export CFLAGS -endif - -ifeq ($(PLATFORM),BRCM_6358) -CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include -nostdinc -iwithprefix include -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -I $(LINUX_SRC)/include/asm/gcc -G 0 -mno-abicalls -fno-pic -pipe -finline-limit=100000 -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap -I$(LINUX_SRC)/include/asm-mips/mach-bcm963xx -I$(LINUX_SRC)/include/asm-mips/mach-generic -Os -fomit-frame-pointer -Wdeclaration-after-statement -DMODULE -mlong-calls -export CFLAGS -endif - -ifeq ($(PLATFORM),PC) - ifneq (,$(findstring 2.4,$(LINUX_SRC))) - # Linux 2.4 - CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=i686 -DMODULE -DMODVERSIONS -include $(LINUX_SRC)/include/linux/modversions.h $(WFLAGS) - export CFLAGS - else - # Linux 2.6 - EXTRA_CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include - endif -endif - -ifeq ($(PLATFORM),IXP) - EXTRA_CFLAGS := -v $(WFLAGS) -I$(RT28xx_DIR)/include -mbig-endian -endif - -ifeq ($(PLATFORM),CAVM_OCTEON) - EXTRA_CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include \ - -mabi=64 $(WFLAGS) -export CFLAGS -endif - diff --git a/drivers/staging/rt3090/crypt_hmac.h b/drivers/staging/rt2860/crypt_hmac.h similarity index 71% rename from drivers/staging/rt3090/crypt_hmac.h rename to drivers/staging/rt2860/crypt_hmac.h index 557ca733d398e103e83701a93e8f6d93f4c5ca71..7a56515d7266c2805863fb8a845cd5fd91803e77 100644 --- a/drivers/staging/rt3090/crypt_hmac.h +++ b/drivers/staging/rt2860/crypt_hmac.h @@ -23,19 +23,20 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * ************************************************************************* + */ +/**************************************************************************** Module Name: - crypt_hmac.h + HMAC Abstract: - Miniport generic portion header file + FIPS 198: The Keyed-Hash Message Authentication Code (HMAC) Revision History: - Who When What - -------- ---------- ---------------------------------------------- + Who When What + -------- ---------- ------------------------------------------ Eddy 2008/11/24 Create HMAC-SHA1, HMAC-SHA256 -*/ - +***************************************************************************/ #ifndef __CRYPT_HMAC_H__ #define __CRYPT_HMAC_H__ @@ -47,35 +48,18 @@ #ifdef SHA1_SUPPORT #define HMAC_SHA1_SUPPORT -VOID HMAC_SHA1 ( - IN const UINT8 Key[], - IN UINT KeyLen, - IN const UINT8 Message[], - IN UINT MessageLen, - OUT UINT8 MAC[], - IN UINT MACLen); +void HMAC_SHA1(IN const u8 Key[], + u32 KeyLen, + IN const u8 Message[], + u32 MessageLen, u8 MAC[], u32 MACLen); #endif /* SHA1_SUPPORT */ -#ifdef SHA256_SUPPORT -#define HMAC_SHA256_SUPPORT -VOID HMAC_SHA256 ( - IN const UINT8 Key[], - IN UINT KeyLen, - IN const UINT8 Message[], - IN UINT MessageLen, - OUT UINT8 MAC[], - IN UINT MACLen); -#endif /* SHA256_SUPPORT */ - #ifdef MD5_SUPPORT #define HMAC_MD5_SUPPORT -VOID HMAC_MD5 ( - IN const UINT8 Key[], - IN UINT KeyLen, - IN const UINT8 Message[], - IN UINT MessageLen, - OUT UINT8 MAC[], - IN UINT MACLen); +void HMAC_MD5(IN const u8 Key[], + u32 KeyLen, + IN const u8 Message[], + u32 MessageLen, u8 MAC[], u32 MACLen); #endif /* MD5_SUPPORT */ #endif /* __CRYPT_HMAC_H__ */ diff --git a/drivers/staging/rt3090/crypt_md5.h b/drivers/staging/rt2860/crypt_md5.h similarity index 67% rename from drivers/staging/rt3090/crypt_md5.h rename to drivers/staging/rt2860/crypt_md5.h index 7ee3f4233fad0fa6da6e98a4d7cea64c9004e14f..26f974554b26354aa04701f3404f90e49d11aad0 100644 --- a/drivers/staging/rt3090/crypt_md5.h +++ b/drivers/staging/rt2860/crypt_md5.h @@ -23,18 +23,20 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * ************************************************************************* + */ +/**************************************************************************** Module Name: - crypt_md5.h + MD5 Abstract: - Miniport generic portion header file + RFC1321: The MD5 Message-Digest Algorithm Revision History: - Who When What - -------- ---------- ---------------------------------------------- + Who When What + -------- ---------- ------------------------------------------ Eddy 2008/11/24 Create md5 -*/ +***************************************************************************/ #ifndef __CRYPT_MD5_H__ #define __CRYPT_MD5_H__ @@ -49,30 +51,23 @@ #define MD5_SUPPORT #ifdef MD5_SUPPORT -#define MD5_BLOCK_SIZE 64 /* 512 bits = 64 bytes */ -#define MD5_DIGEST_SIZE 16 /* 128 bits = 16 bytes */ -typedef struct { - UINT32 HashValue[4]; - UINT64 MessageLen; - UINT8 Block[MD5_BLOCK_SIZE]; - UINT BlockLen; -} MD5_CTX_STRUC, *PMD5_CTX_STRUC; +#define MD5_BLOCK_SIZE 64 /* 512 bits = 64 bytes */ +#define MD5_DIGEST_SIZE 16 /* 128 bits = 16 bytes */ -VOID MD5_Init ( - IN MD5_CTX_STRUC *pMD5_CTX); -VOID MD5_Hash ( - IN MD5_CTX_STRUC *pMD5_CTX); -VOID MD5_Append ( - IN MD5_CTX_STRUC *pMD5_CTX, - IN const UINT8 Message[], - IN UINT MessageLen); -VOID MD5_End ( - IN MD5_CTX_STRUC *pMD5_CTX, - OUT UINT8 DigestMessage[]); -VOID RT_MD5 ( - IN const UINT8 Message[], - IN UINT MessageLen, - OUT UINT8 DigestMessage[]); +struct rt_md5_ctx_struc { + u32 HashValue[4]; + u64 MessageLen; + u8 Block[MD5_BLOCK_SIZE]; + u32 BlockLen; +}; + +void MD5_Init(struct rt_md5_ctx_struc *pMD5_CTX); +void MD5_Hash(struct rt_md5_ctx_struc *pMD5_CTX); +void MD5_Append(struct rt_md5_ctx_struc *pMD5_CTX, + IN const u8 Message[], u32 MessageLen); +void MD5_End(struct rt_md5_ctx_struc *pMD5_CTX, u8 DigestMessage[]); +void RT_MD5(IN const u8 Message[], + u32 MessageLen, u8 DigestMessage[]); #endif /* MD5_SUPPORT */ #endif /* __CRYPT_MD5_H__ */ diff --git a/drivers/staging/rt3090/vr_ikans.h b/drivers/staging/rt2860/crypt_sha2.h similarity index 54% rename from drivers/staging/rt3090/vr_ikans.h rename to drivers/staging/rt2860/crypt_sha2.h index 16bff3bec43b22d066a86437f8bf9e28d8b518a7..20d11ab865c12744441d029737187f238be3d728 100644 --- a/drivers/staging/rt3090/vr_ikans.h +++ b/drivers/staging/rt2860/crypt_sha2.h @@ -23,49 +23,51 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * ************************************************************************* + */ +/**************************************************************************** Module Name: - vr_ikans.h + SHA2 Abstract: - Handle association related requests either from WSTA or from local MLME + FIPS 180-2: Secure Hash Standard (SHS) Revision History: - Who When What - --------- ---------- ---------------------------------------------- - Sample Lin 01-28-2008 Created - */ + Who When What + -------- ---------- ------------------------------------------ + Eddy 2008/11/24 Create SHA1 + Eddy 2008/07/23 Create SHA256 +***************************************************************************/ -#ifndef __VR_IKANS_H__ -#define __VR_IKANS_H__ +#ifndef __CRYPT_SHA2_H__ +#define __CRYPT_SHA2_H__ -#ifndef MODULE_IKANOS -#define IKANOS_EXTERN extern +#ifdef CRYPT_TESTPLAN +#include "crypt_testplan.h" #else -#define IKANOS_EXTERN -#endif // MODULE_IKANOS // - -#ifdef IKANOS_VX_1X0 - typedef void (*IkanosWlanTxCbFuncP)(void *, void *); - - struct IKANOS_TX_INFO - { - struct net_device *netdev; - IkanosWlanTxCbFuncP *fp; - }; -#endif // IKANOS_VX_1X0 // - - -IKANOS_EXTERN void VR_IKANOS_FP_Init(UINT8 BssNum, UINT8 *pApMac); +#include "rt_config.h" +#endif /* CRYPT_TESTPLAN */ -IKANOS_EXTERN INT32 IKANOS_DataFramesTx(struct sk_buff *pSkb, - struct net_device *pNetDev); +/* Algorithm options */ +#define SHA1_SUPPORT -IKANOS_EXTERN void IKANOS_DataFrameRx(PRTMP_ADAPTER pAd, - void *pRxParam, - struct sk_buff *pSkb, - UINT32 Length); +#ifdef SHA1_SUPPORT +#define SHA1_BLOCK_SIZE 64 /* 512 bits = 64 bytes */ +#define SHA1_DIGEST_SIZE 20 /* 160 bits = 20 bytes */ +struct rt_sha1_ctx { + u32 HashValue[5]; /* 5 = (SHA1_DIGEST_SIZE / 32) */ + u64 MessageLen; /* total size */ + u8 Block[SHA1_BLOCK_SIZE]; + u32 BlockLen; +}; -#endif // __VR_IKANS_H__ // +void RT_SHA1_Init(struct rt_sha1_ctx *pSHA_CTX); +void SHA1_Hash(struct rt_sha1_ctx *pSHA_CTX); +void SHA1_Append(struct rt_sha1_ctx *pSHA_CTX, + IN const u8 Message[], u32 MessageLen); +void SHA1_End(struct rt_sha1_ctx *pSHA_CTX, u8 DigestMessage[]); +void RT_SHA1(IN const u8 Message[], + u32 MessageLen, u8 DigestMessage[]); +#endif /* SHA1_SUPPORT */ -/* End of vr_ikans.h */ +#endif /* __CRYPT_SHA2_H__ */ diff --git a/drivers/staging/rt2860/dfs.h b/drivers/staging/rt2860/dfs.h index f34f6183625ca46f6087d190c10c2877bb2f9d6b..5fbab259acae1ead903565e2ffb806c64bc86b3d 100644 --- a/drivers/staging/rt2860/dfs.h +++ b/drivers/staging/rt2860/dfs.h @@ -36,53 +36,4 @@ Fonchi 03-12-2007 created */ -#define RADAR_PULSE 1 -#define RADAR_WIDTH 2 - -#define WIDTH_RD_IDLE 0 -#define WIDTH_RD_CHECK 1 - - -VOID BbpRadarDetectionStart( - IN PRTMP_ADAPTER pAd); - -VOID BbpRadarDetectionStop( - IN PRTMP_ADAPTER pAd); - -VOID RadarDetectionStart( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN CTS_Protect, - IN UINT8 CTSPeriod); - -VOID RadarDetectionStop( - IN PRTMP_ADAPTER pAd); - -VOID RadarDetectPeriodic( - IN PRTMP_ADAPTER pAd); - - -BOOLEAN RadarChannelCheck( - IN PRTMP_ADAPTER pAd, - IN UCHAR Ch); - -ULONG JapRadarType( - IN PRTMP_ADAPTER pAd); - -ULONG RTMPBbpReadRadarDuration( - IN PRTMP_ADAPTER pAd); - -ULONG RTMPReadRadarDuration( - IN PRTMP_ADAPTER pAd); - -VOID RTMPCleanRadarDuration( - IN PRTMP_ADAPTER pAd); - -INT Set_ChMovingTime_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -INT Set_LongPulseRadarTh_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - - +BOOLEAN RadarChannelCheck(struct rt_rtmp_adapter *pAd, u8 Ch); diff --git a/drivers/staging/rt3090/eeprom.h b/drivers/staging/rt2860/eeprom.h similarity index 68% rename from drivers/staging/rt3090/eeprom.h rename to drivers/staging/rt2860/eeprom.h index ee0e807decb492681195608a09f7f1f2719e3f48..039801a97099d25cdcd7f511a25649bf6039ad3f 100644 --- a/drivers/staging/rt3090/eeprom.h +++ b/drivers/staging/rt2860/eeprom.h @@ -24,59 +24,44 @@ * * ************************************************************************* - Module Name: - eeprom.h + Module Name: + eeprom.h - Abstract: - Miniport generic portion header file + Abstract: + Miniport header file for eeprom related information - Revision History: - Who When What - -------- ---------- ---------------------------------------------- + Revision History: + Who When What + -------- ---------- ---------------------------------------------- */ #ifndef __EEPROM_H__ #define __EEPROM_H__ - - #ifdef RTMP_PCI_SUPPORT /************************************************************************* * Public function declarations for prom-based chipset ************************************************************************/ -int rtmp_ee_prom_read16( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - OUT USHORT *pValue); - -int rtmp_ee_prom_write16( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT value); -#endif // RTMP_PCI_SUPPORT // - - - - +int rtmp_ee_prom_read16(struct rt_rtmp_adapter *pAd, + u16 Offset, u16 * pValue); +#endif /* RTMP_PCI_SUPPORT // */ +#ifdef RTMP_USB_SUPPORT +/************************************************************************* + * Public function declarations for usb-based prom chipset + ************************************************************************/ +int RTUSBReadEEPROM16(struct rt_rtmp_adapter *pAd, + u16 offset, u16 *pData); +#endif /* RTMP_USB_SUPPORT // */ #ifdef RT30xx #ifdef RTMP_EFUSE_SUPPORT -int rtmp_ee_efuse_read16( - IN RTMP_ADAPTER *pAd, - IN USHORT Offset, - OUT USHORT *pValue); - -int rtmp_ee_efuse_write16( - IN RTMP_ADAPTER *pAd, - IN USHORT Offset, - IN USHORT data); -#endif // RTMP_EFUSE_SUPPORT // -#endif // RT30xx // +int rtmp_ee_efuse_read16(struct rt_rtmp_adapter *pAd, + u16 Offset, u16 * pValue); +#endif /* RTMP_EFUSE_SUPPORT // */ +#endif /* RT30xx // */ /************************************************************************* * Public function declarations for prom operation callback functions setting ************************************************************************/ -INT RtmpChipOpsEepromHook( - IN RTMP_ADAPTER *pAd, - IN INT infType); +int RtmpChipOpsEepromHook(struct rt_rtmp_adapter *pAd, int infType); -#endif // __EEPROM_H__ // +#endif /* __EEPROM_H__ // */ diff --git a/drivers/staging/rt3090/rtmp_pci.h b/drivers/staging/rt2860/iface/rtmp_pci.h similarity index 62% rename from drivers/staging/rt3090/rtmp_pci.h rename to drivers/staging/rt2860/iface/rtmp_pci.h index c2fed29058f4cfbb8f73e7d186487065169e2c81..7759d56a3043acb2a05a0a47db965a711c284e31 100644 --- a/drivers/staging/rt3090/rtmp_pci.h +++ b/drivers/staging/rt2860/iface/rtmp_pci.h @@ -25,13 +25,11 @@ ************************************************************************* */ - #ifndef __RTMP_PCI_H__ #define __RTMP_PCI_H__ #define RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p) \ - ((POS_COOKIE)handle)->pci_dev = dev_p; - + ((struct os_cookie *)handle)->pci_dev = dev_p; #ifdef LINUX // set driver data @@ -39,26 +37,25 @@ #define RT28XX_PUT_DEVICE(dev_p) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) #define SA_SHIRQ IRQF_SHARED -#endif #ifdef PCI_MSI_SUPPORT #define RTMP_MSI_ENABLE(_pAd) \ -{ POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ - (_pAd)->HaveMsi = pci_enable_msi(_pObj->pci_dev) == 0 ? TRUE : FALSE; } + { struct os_cookie *_pObj = (struct os_cookie *)(_pAd->OS_Cookie); \ + (_pAd)->HaveMsi = pci_enable_msi(_pObj->pci_dev) == 0 ? TRUE : FALSE; \ + } #define RTMP_MSI_DISABLE(_pAd) \ -{ POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ - if (_pAd->HaveMsi == TRUE) \ - pci_disable_msi(_pObj->pci_dev); \ - _pAd->HaveMsi = FALSE; } + { struct os_cookie *_pObj = (struct os_cookie *)(_pAd->OS_Cookie); \ + if (_pAd->HaveMsi == TRUE) \ + pci_disable_msi(_pObj->pci_dev); \ + _pAd->HaveMsi = FALSE; \ + } #else -#define RTMP_MSI_ENABLE(_pAd) -#define RTMP_MSI_DISABLE(_pAd) +#define RTMP_MSI_ENABLE(_pAd) do{}while(0) +#define RTMP_MSI_DISABLE(_pAd) do{}while(0) #endif // PCI_MSI_SUPPORT // - #define RTMP_PCI_DEV_UNMAP() \ { if (net_dev->base_addr) { \ iounmap((void *)(net_dev->base_addr)); \ @@ -66,32 +63,6 @@ pci_resource_len(dev_p, 0)); } \ if (net_dev->irq) pci_release_regions(dev_p); } - -#define RTMP_IRQ_REQUEST(net_dev) \ -{ PRTMP_ADAPTER _pAd = (PRTMP_ADAPTER)(RTMP_OS_NETDEV_GET_PRIV(net_dev)); \ - POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ - RTMP_MSI_ENABLE(_pAd); \ - if ((retval = request_irq(_pObj->pci_dev->irq, \ - rt2860_interrupt, SA_SHIRQ, \ - (net_dev)->name, (net_dev)))) { \ - DBGPRINT(RT_DEBUG_ERROR, ("request_irq error(%d)\n", retval)); \ - return retval; } } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#define RTMP_IRQ_RELEASE(net_dev) \ -{ PRTMP_ADAPTER _pAd = (PRTMP_ADAPTER)(RTMP_OS_NETDEV_GET_PRIV(net_dev)); \ - POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ - synchronize_irq(_pObj->pci_dev->irq); \ - free_irq(_pObj->pci_dev->irq, (net_dev)); \ - RTMP_MSI_DISABLE(_pAd); } -#else -#define RTMP_IRQ_RELEASE(net_dev) \ -{ PRTMP_ADAPTER _pAd = (PRTMP_ADAPTER)(RTMP_OS_NETDEV_GET_PRIV(net_dev)); \ - POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ - free_irq(_pObj->pci_dev->irq, (net_dev)); \ - RTMP_MSI_DISABLE(_pAd); } -#endif - #define PCI_REG_READ_WORD(pci_dev, offset, Configuration) \ if (pci_read_config_word(pci_dev, offset, ®16) == 0) \ Configuration = le2cpu16(reg16); \ @@ -100,11 +71,8 @@ #define PCI_REG_WIRTE_WORD(pci_dev, offset, Configuration) \ reg16 = cpu2le16(Configuration); \ - pci_write_config_word(pci_dev, offset, reg16); \ + pci_write_config_word(pci_dev, offset, reg16); #endif // LINUX // - - - #endif // __RTMP_PCI_H__ // diff --git a/drivers/staging/rt2860/iface/rtmp_usb.h b/drivers/staging/rt2860/iface/rtmp_usb.h new file mode 100644 index 0000000000000000000000000000000000000000..6bb384a74660ad5a945a3ae3a523c4a9289f53bb --- /dev/null +++ b/drivers/staging/rt2860/iface/rtmp_usb.h @@ -0,0 +1,182 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* +*/ + +#ifndef __RTMP_USB_H__ +#define __RTMP_USB_H__ + +#include "../rtusb_io.h" + +#ifdef LINUX +#include +#endif // LINUX // + +extern u8 EpToQueue[6]; + +#define RXBULKAGGRE_ZISE 12 +#define MAX_TXBULK_LIMIT (LOCAL_TXBUF_SIZE*(BULKAGGRE_ZISE-1)) +#define MAX_TXBULK_SIZE (LOCAL_TXBUF_SIZE*BULKAGGRE_ZISE) +#define MAX_RXBULK_SIZE (LOCAL_TXBUF_SIZE*RXBULKAGGRE_ZISE) +#define MAX_MLME_HANDLER_MEMORY 20 + +// Flags for Bulkflags control for bulk out data +// +#define fRTUSB_BULK_OUT_DATA_NULL 0x00000001 +#define fRTUSB_BULK_OUT_RTS 0x00000002 +#define fRTUSB_BULK_OUT_MLME 0x00000004 + +#define fRTUSB_BULK_OUT_PSPOLL 0x00000010 +#define fRTUSB_BULK_OUT_DATA_FRAG 0x00000020 +#define fRTUSB_BULK_OUT_DATA_FRAG_2 0x00000040 +#define fRTUSB_BULK_OUT_DATA_FRAG_3 0x00000080 +#define fRTUSB_BULK_OUT_DATA_FRAG_4 0x00000100 + +#define fRTUSB_BULK_OUT_DATA_NORMAL 0x00010000 +#define fRTUSB_BULK_OUT_DATA_NORMAL_2 0x00020000 +#define fRTUSB_BULK_OUT_DATA_NORMAL_3 0x00040000 +#define fRTUSB_BULK_OUT_DATA_NORMAL_4 0x00080000 + +// TODO:move to ./ate/include/iface/ate_usb.h + +#define FREE_HTTX_RING(_pCookie, _pipeId, _txContext) \ +{ \ + if ((_txContext)->ENextBulkOutPosition == (_txContext)->CurWritePosition) \ + { \ + (_txContext)->bRingEmpty = TRUE; \ + } \ + /*NdisInterlockedDecrement(&(_p)->TxCount); */\ +} + +/****************************************************************************** + + USB Bulk operation related definitions + +******************************************************************************/ + +#ifdef LINUX +#define BULKAGGRE_ZISE 100 +#define RT28XX_PUT_DEVICE usb_put_dev +#define RTUSB_ALLOC_URB(iso) usb_alloc_urb(iso, GFP_ATOMIC) +#define RTUSB_SUBMIT_URB(pUrb) usb_submit_urb(pUrb, GFP_ATOMIC) +#define RTUSB_URB_ALLOC_BUFFER(pUsb_Dev, BufSize, pDma_addr) usb_buffer_alloc(pUsb_Dev, BufSize, GFP_ATOMIC, pDma_addr) +#define RTUSB_URB_FREE_BUFFER(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) usb_buffer_free(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) + +#define RTUSB_FREE_URB(pUrb) usb_free_urb(pUrb) + +// unlink urb +#define RTUSB_UNLINK_URB(pUrb) usb_kill_urb(pUrb) + +extern void dump_urb(struct urb *purb); + +#define InterlockedIncrement atomic_inc +#define NdisInterlockedIncrement atomic_inc +#define InterlockedDecrement atomic_dec +#define NdisInterlockedDecrement atomic_dec +#define InterlockedExchange atomic_set + +#endif // LINUX // + +#define NT_SUCCESS(status) (((status) >=0) ? (TRUE):(FALSE)) + +#define USBD_TRANSFER_DIRECTION_OUT 0 +#define USBD_TRANSFER_DIRECTION_IN 0 +#define USBD_SHORT_TRANSFER_OK 0 +#define PURB struct urb * + +#define PIRP void * +#define NDIS_OID u32 +#ifndef USB_ST_NOERROR +#define USB_ST_NOERROR 0 +#endif + +// vendor-specific control operations +#define CONTROL_TIMEOUT_JIFFIES ( (100 * OS_HZ) / 1000) +#define UNLINK_TIMEOUT_MS 3 + +void RTUSBBulkOutDataPacketComplete(struct urb *purb, struct pt_regs *pt_regs); +void RTUSBBulkOutMLMEPacketComplete(struct urb *pUrb, struct pt_regs *pt_regs); +void RTUSBBulkOutNullFrameComplete(struct urb *pUrb, struct pt_regs *pt_regs); +void RTUSBBulkOutRTSFrameComplete(struct urb *pUrb, struct pt_regs *pt_regs); +void RTUSBBulkOutPsPollComplete(struct urb *pUrb, struct pt_regs *pt_regs); +void RTUSBBulkRxComplete(struct urb *pUrb, struct pt_regs *pt_regs); + +#ifdef KTHREAD_SUPPORT +#define RTUSBMlmeUp(pAd) \ + do{ \ + struct rt_rtmp_os_task *_pTask = &((pAd)->mlmeTask);\ + if (_pTask->kthread_task) \ + { \ + _pTask->kthread_running = TRUE; \ + wake_up(&_pTask->kthread_q); \ + } \ + }while(0) +#else +#define RTUSBMlmeUp(pAd) \ + do{ \ + struct rt_rtmp_os_task *_pTask = &((pAd)->mlmeTask);\ + CHECK_PID_LEGALITY(_pTask->taskPID) \ + { \ + RTMP_SEM_EVENT_UP(&(_pTask->taskSema)); \ + }\ + }while(0) +#endif + +#ifdef KTHREAD_SUPPORT +#define RTUSBCMDUp(pAd) \ + do{ \ + struct rt_rtmp_os_task *_pTask = &((pAd)->cmdQTask); \ + { \ + _pTask->kthread_running = TRUE; \ + wake_up(&_pTask->kthread_q); \ + } \ + }while(0) + +#else +#define RTUSBCMDUp(pAd) \ + do{ \ + struct rt_rtmp_os_task *_pTask = &((pAd)->cmdQTask); \ + CHECK_PID_LEGALITY(_pTask->taskPID) \ + {\ + RTMP_SEM_EVENT_UP(&(_pTask->taskSema)); \ + }\ + }while(0) +#endif + +#define DEVICE_VENDOR_REQUEST_OUT 0x40 +#define DEVICE_VENDOR_REQUEST_IN 0xc0 +//#define INTERFACE_VENDOR_REQUEST_OUT 0x41 +//#define INTERFACE_VENDOR_REQUEST_IN 0xc1 + +#define BULKOUT_MGMT_RESET_FLAG 0x80 + +#define RTUSB_SET_BULK_FLAG(_M, _F) ((_M)->BulkFlags |= (_F)) +#define RTUSB_CLEAR_BULK_FLAG(_M, _F) ((_M)->BulkFlags &= ~(_F)) +#define RTUSB_TEST_BULK_FLAG(_M, _F) (((_M)->BulkFlags & (_F)) != 0) + +#define RTMP_IRQ_REQUEST(net_dev) do{}while(0) +#define RTMP_IRQ_RELEASE(net_dev) do{}while(0) + +#endif // __RTMP_USB_H__ // diff --git a/drivers/staging/rt2860/md5.h b/drivers/staging/rt2860/md5.h deleted file mode 100644 index d85db12170d5d102acc8bdcdc51e7cfd5fef9346..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2860/md5.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - md5.h - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Name Date Modification logs - jan 10-28-03 Initial - Rita 11-23-04 Modify MD5 and SHA-1 -*/ - -#ifndef uint8 -#define uint8 unsigned char -#endif - -#ifndef uint32 -#define uint32 unsigned long int -#endif - - -#ifndef __MD5_H__ -#define __MD5_H__ - -#define MD5_MAC_LEN 16 - -typedef struct _MD5_CTX { - UINT32 Buf[4]; // buffers of four states - UCHAR Input[64]; // input message - UINT32 LenInBitCount[2]; // length counter for input message, 0 up to 64 bits -} MD5_CTX; - -VOID MD5Init(MD5_CTX *pCtx); -VOID MD5Update(MD5_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes); -VOID MD5Final(UCHAR Digest[16], MD5_CTX *pCtx); -VOID MD5Transform(UINT32 Buf[4], UINT32 Mes[16]); - -void md5_mac(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac); -void hmac_md5(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac); - -// -// SHA context -// -typedef struct _SHA_CTX -{ - UINT32 Buf[5]; // buffers of five states - UCHAR Input[80]; // input message - UINT32 LenInBitCount[2]; // length counter for input message, 0 up to 64 bits - -} SHA_CTX; - -VOID SHAInit(SHA_CTX *pCtx); -UCHAR SHAUpdate(SHA_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes); -VOID SHAFinal(SHA_CTX *pCtx, UCHAR Digest[20]); -VOID SHATransform(UINT32 Buf[5], UINT32 Mes[20]); - -#define SHA_DIGEST_LEN 20 -#endif // __MD5_H__ - -/******************************************************************************/ -#ifndef _AES_H -#define _AES_H - -typedef struct -{ - uint32 erk[64]; /* encryption round keys */ - uint32 drk[64]; /* decryption round keys */ - int nr; /* number of rounds */ -} -aes_context; - -int rtmp_aes_set_key( aes_context *ctx, uint8 *key, int nbits ); -void rtmp_aes_encrypt( aes_context *ctx, uint8 input[16], uint8 output[16] ); -void rtmp_aes_decrypt( aes_context *ctx, uint8 input[16], uint8 output[16] ); - -void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output); -int PasswordHash(char *password, unsigned char *ssid, int ssidlength, unsigned char *output); - -#endif /* aes.h */ - diff --git a/drivers/staging/rt2860/mlme.h b/drivers/staging/rt2860/mlme.h index 3d1a8284fbd4f92235c59d952a54fa7bf13470a4..11434132f93b7434bc036283a6c561a8a90f1964 100644 --- a/drivers/staging/rt2860/mlme.h +++ b/drivers/staging/rt2860/mlme.h @@ -39,18 +39,20 @@ #ifndef __MLME_H__ #define __MLME_H__ -// maximum supported capability information - -// ESS, IBSS, Privacy, Short Preamble, Spectrum mgmt, Short Slot +#include "rtmp_dot11.h" + +/* maximum supported capability information - */ +/* ESS, IBSS, Privacy, Short Preamble, Spectrum mgmt, Short Slot */ #define SUPPORTED_CAPABILITY_INFO 0x0533 #define END_OF_ARGS -1 #define LFSR_MASK 0x80000057 -#define MLME_TASK_EXEC_INTV 100/*200*/ // +#define MLME_TASK_EXEC_INTV 100/*200*/ /* */ #define LEAD_TIME 5 -#define MLME_TASK_EXEC_MULTIPLE 10 /*5*/ // MLME_TASK_EXEC_MULTIPLE * MLME_TASK_EXEC_INTV = 1 sec -#define REORDER_EXEC_INTV 100 // 0.1 sec +#define MLME_TASK_EXEC_MULTIPLE 10 /*5*/ /* MLME_TASK_EXEC_MULTIPLE * MLME_TASK_EXEC_INTV = 1 sec */ +#define REORDER_EXEC_INTV 100 /* 0.1 sec */ -// The definition of Radar detection duration region +/* The definition of Radar detection duration region */ #define CE 0 #define FCC 1 #define JAP 2 @@ -58,62 +60,61 @@ #define JAP_W56 4 #define MAX_RD_REGION 5 -#ifdef NDIS51_MINIPORT -#define BEACON_LOST_TIME 4000 // 2048 msec = 2 sec -#else -#define BEACON_LOST_TIME 4 * OS_HZ // 2048 msec = 2 sec -#endif - -#define DLS_TIMEOUT 1200 // unit: msec -#define AUTH_TIMEOUT 300 // unit: msec -#define ASSOC_TIMEOUT 300 // unit: msec -#define JOIN_TIMEOUT 2 * OS_HZ // unit: msec -#define SHORT_CHANNEL_TIME 90 // unit: msec -#define MIN_CHANNEL_TIME 110 // unit: msec, for dual band scan -#define MAX_CHANNEL_TIME 140 // unit: msec, for single band scan -#define FAST_ACTIVE_SCAN_TIME 30 // Active scan waiting for probe response time -#define CW_MIN_IN_BITS 4 // actual CwMin = 2^CW_MIN_IN_BITS - 1 -#define CW_MAX_IN_BITS 10 // actual CwMax = 2^CW_MAX_IN_BITS - 1 - -// Note: RSSI_TO_DBM_OFFSET has been changed to variable for new RF (2004-0720). -// SHould not refer to this constant anymore -//#define RSSI_TO_DBM_OFFSET 120 // for RT2530 RSSI-115 = dBm -#define RSSI_FOR_MID_TX_POWER -55 // -55 db is considered mid-distance -#define RSSI_FOR_LOW_TX_POWER -45 // -45 db is considered very short distance and - // eligible to use a lower TX power +#define BEACON_LOST_TIME 4 * OS_HZ /* 2048 msec = 2 sec */ + +#define DLS_TIMEOUT 1200 /* unit: msec */ +#define AUTH_TIMEOUT 300 /* unit: msec */ +#define ASSOC_TIMEOUT 300 /* unit: msec */ +#define JOIN_TIMEOUT 2000 /* unit: msec */ +#define SHORT_CHANNEL_TIME 90 /* unit: msec */ +#define MIN_CHANNEL_TIME 110 /* unit: msec, for dual band scan */ +#define MAX_CHANNEL_TIME 140 /* unit: msec, for single band scan */ +#define FAST_ACTIVE_SCAN_TIME 30 /* Active scan waiting for probe response time */ +#define CW_MIN_IN_BITS 4 /* actual CwMin = 2^CW_MIN_IN_BITS - 1 */ +#define LINK_DOWN_TIMEOUT 20000 /* unit: msec */ +#define AUTO_WAKEUP_TIMEOUT 70 /*unit: msec */ + +#define CW_MAX_IN_BITS 10 /* actual CwMax = 2^CW_MAX_IN_BITS - 1 */ + +/* Note: RSSI_TO_DBM_OFFSET has been changed to variable for new RF (2004-0720). */ +/* SHould not refer to this constant anymore */ +/*#define RSSI_TO_DBM_OFFSET 120 // for RT2530 RSSI-115 = dBm */ +#define RSSI_FOR_MID_TX_POWER -55 /* -55 db is considered mid-distance */ +#define RSSI_FOR_LOW_TX_POWER -45 /* -45 db is considered very short distance and */ + /* eligible to use a lower TX power */ #define RSSI_FOR_LOWEST_TX_POWER -30 -//#define MID_TX_POWER_DELTA 0 // 0 db from full TX power upon mid-distance to AP -#define LOW_TX_POWER_DELTA 6 // -3 db from full TX power upon very short distance. 1 grade is 0.5 db -#define LOWEST_TX_POWER_DELTA 16 // -8 db from full TX power upon shortest distance. 1 grade is 0.5 db +/*#define MID_TX_POWER_DELTA 0 // 0 db from full TX power upon mid-distance to AP */ +#define LOW_TX_POWER_DELTA 6 /* -3 db from full TX power upon very short distance. 1 grade is 0.5 db */ +#define LOWEST_TX_POWER_DELTA 16 /* -8 db from full TX power upon shortest distance. 1 grade is 0.5 db */ #define RSSI_TRIGGERED_UPON_BELOW_THRESHOLD 0 #define RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD 1 #define RSSI_THRESHOLD_FOR_ROAMING 25 #define RSSI_DELTA 5 -// Channel Quality Indication +/* Channel Quality Indication */ #define CQI_IS_GOOD(cqi) ((cqi) >= 50) -//#define CQI_IS_FAIR(cqi) (((cqi) >= 20) && ((cqi) < 50)) -#define CQI_IS_POOR(cqi) (cqi < 50) //(((cqi) >= 5) && ((cqi) < 20)) +/*#define CQI_IS_FAIR(cqi) (((cqi) >= 20) && ((cqi) < 50)) */ +#define CQI_IS_POOR(cqi) (cqi < 50) /*(((cqi) >= 5) && ((cqi) < 20)) */ #define CQI_IS_BAD(cqi) (cqi < 5) #define CQI_IS_DEAD(cqi) (cqi == 0) -// weighting factor to calculate Channel quality, total should be 100% +/* weighting factor to calculate Channel quality, total should be 100% */ #define RSSI_WEIGHTING 50 #define TX_WEIGHTING 30 #define RX_WEIGHTING 20 #define BSS_NOT_FOUND 0xFFFFFFFF -#define MAX_LEN_OF_MLME_QUEUE 40 //10 +#define MAX_LEN_OF_MLME_QUEUE 40 /*10 */ -#define SCAN_PASSIVE 18 // scan with no probe request, only wait beacon and probe response -#define SCAN_ACTIVE 19 // scan with probe request, and wait beacon and probe response -#define SCAN_CISCO_PASSIVE 20 // Single channel passive scan -#define SCAN_CISCO_ACTIVE 21 // Single channel active scan -#define SCAN_CISCO_NOISE 22 // Single channel passive scan for noise histogram collection -#define SCAN_CISCO_CHANNEL_LOAD 23 // Single channel passive scan for channel load collection -#define FAST_SCAN_ACTIVE 24 // scan with probe request, and wait beacon and probe response +#define SCAN_PASSIVE 18 /* scan with no probe request, only wait beacon and probe response */ +#define SCAN_ACTIVE 19 /* scan with probe request, and wait beacon and probe response */ +#define SCAN_CISCO_PASSIVE 20 /* Single channel passive scan */ +#define SCAN_CISCO_ACTIVE 21 /* Single channel active scan */ +#define SCAN_CISCO_NOISE 22 /* Single channel passive scan for noise histogram collection */ +#define SCAN_CISCO_CHANNEL_LOAD 23 /* Single channel passive scan for channel load collection */ +#define FAST_SCAN_ACTIVE 24 /* scan with probe request, and wait beacon and probe response */ #define MAC_ADDR_IS_GROUP(Addr) (((Addr[0]) & 0x01)) #define MAC_ADDR_HASH(Addr) (Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5]) @@ -121,13 +122,13 @@ #define TID_MAC_HASH(Addr,TID) (TID^Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5]) #define TID_MAC_HASH_INDEX(Addr,TID) (TID_MAC_HASH(Addr,TID) % HASH_TABLE_SIZE) -// LED Control -// assoiation ON. one LED ON. another blinking when TX, OFF when idle -// no association, both LED off +/* LED Control */ +/* assoiation ON. one LED ON. another blinking when TX, OFF when idle */ +/* no association, both LED off */ #define ASIC_LED_ACT_ON(pAd) RTMP_IO_WRITE32(pAd, MAC_CSR14, 0x00031e46) #define ASIC_LED_ACT_OFF(pAd) RTMP_IO_WRITE32(pAd, MAC_CSR14, 0x00001e46) -// bit definition of the 2-byte pBEACON->Capability field +/* bit definition of the 2-byte pBEACON->Capability field */ #define CAP_IS_ESS_ON(x) (((x) & 0x0001) != 0) #define CAP_IS_IBSS_ON(x) (((x) & 0x0002) != 0) #define CAP_IS_CF_POLLABLE_ON(x) (((x) & 0x0004) != 0) @@ -136,44 +137,44 @@ #define CAP_IS_SHORT_PREAMBLE_ON(x) (((x) & 0x0020) != 0) #define CAP_IS_PBCC_ON(x) (((x) & 0x0040) != 0) #define CAP_IS_AGILITY_ON(x) (((x) & 0x0080) != 0) -#define CAP_IS_SPECTRUM_MGMT(x) (((x) & 0x0100) != 0) // 802.11e d9 -#define CAP_IS_QOS(x) (((x) & 0x0200) != 0) // 802.11e d9 +#define CAP_IS_SPECTRUM_MGMT(x) (((x) & 0x0100) != 0) /* 802.11e d9 */ +#define CAP_IS_QOS(x) (((x) & 0x0200) != 0) /* 802.11e d9 */ #define CAP_IS_SHORT_SLOT(x) (((x) & 0x0400) != 0) -#define CAP_IS_APSD(x) (((x) & 0x0800) != 0) // 802.11e d9 -#define CAP_IS_IMMED_BA(x) (((x) & 0x1000) != 0) // 802.11e d9 +#define CAP_IS_APSD(x) (((x) & 0x0800) != 0) /* 802.11e d9 */ +#define CAP_IS_IMMED_BA(x) (((x) & 0x1000) != 0) /* 802.11e d9 */ #define CAP_IS_DSSS_OFDM(x) (((x) & 0x2000) != 0) -#define CAP_IS_DELAY_BA(x) (((x) & 0x4000) != 0) // 802.11e d9 +#define CAP_IS_DELAY_BA(x) (((x) & 0x4000) != 0) /* 802.11e d9 */ #define CAP_GENERATE(ess,ibss,priv,s_pre,s_slot,spectrum) (((ess) ? 0x0001 : 0x0000) | ((ibss) ? 0x0002 : 0x0000) | ((priv) ? 0x0010 : 0x0000) | ((s_pre) ? 0x0020 : 0x0000) | ((s_slot) ? 0x0400 : 0x0000) | ((spectrum) ? 0x0100 : 0x0000)) -#define ERP_IS_NON_ERP_PRESENT(x) (((x) & 0x01) != 0) // 802.11g -#define ERP_IS_USE_PROTECTION(x) (((x) & 0x02) != 0) // 802.11g -#define ERP_IS_USE_BARKER_PREAMBLE(x) (((x) & 0x04) != 0) // 802.11g +#define ERP_IS_NON_ERP_PRESENT(x) (((x) & 0x01) != 0) /* 802.11g */ +#define ERP_IS_USE_PROTECTION(x) (((x) & 0x02) != 0) /* 802.11g */ +#define ERP_IS_USE_BARKER_PREAMBLE(x) (((x) & 0x04) != 0) /* 802.11g */ -#define DRS_TX_QUALITY_WORST_BOUND 8// 3 // just test by gary +#define DRS_TX_QUALITY_WORST_BOUND 8 /* 3 // just test by gary */ #define DRS_PENALTY 8 #define BA_NOTUSE 2 -//BA Policy subfiled value in ADDBA frame +/*BA Policy subfiled value in ADDBA frame */ #define IMMED_BA 1 #define DELAY_BA 0 -// BA Initiator subfield in DELBA frame +/* BA Initiator subfield in DELBA frame */ #define ORIGINATOR 1 #define RECIPIENT 0 -// ADDBA Status Code +/* ADDBA Status Code */ #define ADDBA_RESULTCODE_SUCCESS 0 #define ADDBA_RESULTCODE_REFUSED 37 #define ADDBA_RESULTCODE_INVALID_PARAMETERS 38 -// DELBA Reason Code +/* DELBA Reason Code */ #define DELBA_REASONCODE_QSTA_LEAVING 36 #define DELBA_REASONCODE_END_BA 37 #define DELBA_REASONCODE_UNKNOWN_BA 38 #define DELBA_REASONCODE_TIMEOUT 39 -// reset all OneSecTx counters +/* reset all OneSecTx counters */ #define RESET_ONE_SEC_TX_CNT(__pEntry) \ if (((__pEntry)) != NULL) \ { \ @@ -182,957 +183,868 @@ if (((__pEntry)) != NULL) \ (__pEntry)->OneSecTxNoRetryOkCount = 0; \ } -// -// 802.11 frame formats -// -// HT Capability INFO field in HT Cap IE . -typedef struct PACKED { - USHORT AdvCoding:1; - USHORT ChannelWidth:1; - USHORT MimoPs:2;//momi power safe - USHORT GF:1; //green field - USHORT ShortGIfor20:1; - USHORT ShortGIfor40:1; //for40MHz - USHORT TxSTBC:1; - USHORT RxSTBC:2; - USHORT DelayedBA:1; //rt2860c not support - USHORT AMsduSize:1; // only support as zero - USHORT CCKmodein40:1; - USHORT PSMP:1; - USHORT Forty_Mhz_Intolerant:1; - USHORT LSIGTxopProSup:1; -} HT_CAP_INFO, *PHT_CAP_INFO; - -// HT Capability INFO field in HT Cap IE . -typedef struct PACKED { - UCHAR MaxRAmpduFactor:2; - UCHAR MpduDensity:3; - UCHAR rsv:3;//momi power safe -} HT_CAP_PARM, *PHT_CAP_PARM; - -// HT Capability INFO field in HT Cap IE . -typedef struct PACKED { - UCHAR MCSSet[10]; - UCHAR SupRate[2]; // unit : 1Mbps - UCHAR TxMCSSetDefined:1; - UCHAR TxRxNotEqual:1; - UCHAR TxStream:2; - UCHAR MpduDensity:1; - UCHAR rsv:3; - UCHAR rsv3[3]; -} HT_MCS_SET, *PHT_MCS_SET; - -// HT Capability INFO field in HT Cap IE . -typedef struct PACKED { - USHORT Pco:1; - USHORT TranTime:2; - USHORT rsv:5;//momi power safe - USHORT MCSFeedback:2; //0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv. - USHORT PlusHTC:1; //+HTC control field support - USHORT RDGSupport:1; //reverse Direction Grant support - USHORT rsv2:4; -} EXT_HT_CAP_INFO, *PEXT_HT_CAP_INFO; - -// HT Beamforming field in HT Cap IE . -typedef struct PACKED _HT_BF_CAP{ - ULONG TxBFRecCapable:1; - ULONG RxSoundCapable:1; - ULONG TxSoundCapable:1; - ULONG RxNDPCapable:1; - ULONG TxNDPCapable:1; - ULONG ImpTxBFCapable:1; - ULONG Calibration:2; - ULONG ExpCSICapable:1; - ULONG ExpNoComSteerCapable:1; - ULONG ExpComSteerCapable:1; - ULONG ExpCSIFbk:2; - ULONG ExpNoComBF:2; - ULONG ExpComBF:2; - ULONG MinGrouping:2; - ULONG CSIBFAntSup:2; - ULONG NoComSteerBFAntSup:2; - ULONG ComSteerBFAntSup:2; - ULONG CSIRowBFSup:2; - ULONG ChanEstimation:2; - ULONG rsv:3; -} HT_BF_CAP, *PHT_BF_CAP; - -// HT antenna selection field in HT Cap IE . -typedef struct PACKED _HT_AS_CAP{ - UCHAR AntSelect:1; - UCHAR ExpCSIFbkTxASEL:1; - UCHAR AntIndFbkTxASEL:1; - UCHAR ExpCSIFbk:1; - UCHAR AntIndFbk:1; - UCHAR RxASel:1; - UCHAR TxSoundPPDU:1; - UCHAR rsv:1; -} HT_AS_CAP, *PHT_AS_CAP; - -// Draft 1.0 set IE length 26, but is extensible.. +/* */ +/* 802.11 frame formats */ +/* */ +/* HT Capability INFO field in HT Cap IE . */ +struct PACKED rt_ht_cap_info { + u16 AdvCoding:1; + u16 ChannelWidth:1; + u16 MimoPs:2; /*momi power safe */ + u16 GF:1; /*green field */ + u16 ShortGIfor20:1; + u16 ShortGIfor40:1; /*for40MHz */ + u16 TxSTBC:1; + u16 RxSTBC:2; + u16 DelayedBA:1; /*rt2860c not support */ + u16 AMsduSize:1; /* only support as zero */ + u16 CCKmodein40:1; + u16 PSMP:1; + u16 Forty_Mhz_Intolerant:1; + u16 LSIGTxopProSup:1; +}; + +/* HT Capability INFO field in HT Cap IE . */ +struct PACKED rt_ht_cap_parm { + u8 MaxRAmpduFactor:2; + u8 MpduDensity:3; + u8 rsv:3; /*momi power safe */ +}; + +/* HT Capability INFO field in HT Cap IE . */ +struct PACKED rt_ht_mcs_set { + u8 MCSSet[10]; + u8 SupRate[2]; /* unit : 1Mbps */ + u8 TxMCSSetDefined:1; + u8 TxRxNotEqual:1; + u8 TxStream:2; + u8 MpduDensity:1; + u8 rsv:3; + u8 rsv3[3]; +}; + +/* HT Capability INFO field in HT Cap IE . */ +struct PACKED rt_ext_ht_cap_info { + u16 Pco:1; + u16 TranTime:2; + u16 rsv:5; /*momi power safe */ + u16 MCSFeedback:2; /*0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv. */ + u16 PlusHTC:1; /*+HTC control field support */ + u16 RDGSupport:1; /*reverse Direction Grant support */ + u16 rsv2:4; +}; + +/* HT Beamforming field in HT Cap IE . */ +struct PACKED rt_ht_bf_cap { + unsigned long TxBFRecCapable:1; + unsigned long RxSoundCapable:1; + unsigned long TxSoundCapable:1; + unsigned long RxNDPCapable:1; + unsigned long TxNDPCapable:1; + unsigned long ImpTxBFCapable:1; + unsigned long Calibration:2; + unsigned long ExpCSICapable:1; + unsigned long ExpNoComSteerCapable:1; + unsigned long ExpComSteerCapable:1; + unsigned long ExpCSIFbk:2; + unsigned long ExpNoComBF:2; + unsigned long ExpComBF:2; + unsigned long MinGrouping:2; + unsigned long CSIBFAntSup:2; + unsigned long NoComSteerBFAntSup:2; + unsigned long ComSteerBFAntSup:2; + unsigned long CSIRowBFSup:2; + unsigned long ChanEstimation:2; + unsigned long rsv:3; +}; + +/* HT antenna selection field in HT Cap IE . */ +struct PACKED rt_ht_as_cap { + u8 AntSelect:1; + u8 ExpCSIFbkTxASEL:1; + u8 AntIndFbkTxASEL:1; + u8 ExpCSIFbk:1; + u8 AntIndFbk:1; + u8 RxASel:1; + u8 TxSoundPPDU:1; + u8 rsv:1; +}; + +/* Draft 1.0 set IE length 26, but is extensible.. */ #define SIZE_HT_CAP_IE 26 -// The structure for HT Capability IE. -typedef struct PACKED _HT_CAPABILITY_IE{ - HT_CAP_INFO HtCapInfo; - HT_CAP_PARM HtCapParm; -// HT_MCS_SET HtMCSSet; - UCHAR MCSSet[16]; - EXT_HT_CAP_INFO ExtHtCapInfo; - HT_BF_CAP TxBFCap; // beamforming cap. rt2860c not support beamforming. - HT_AS_CAP ASCap; //antenna selection. -} HT_CAPABILITY_IE, *PHT_CAPABILITY_IE; - - -// 802.11n draft3 related structure definitions. -// 7.3.2.60 -#define dot11OBSSScanPassiveDwell 20 // in TU. min amount of time that the STA continously scans each channel when performing an active OBSS scan. -#define dot11OBSSScanActiveDwell 10 // in TU.min amount of time that the STA continously scans each channel when performing an passive OBSS scan. -#define dot11BSSWidthTriggerScanInterval 300 // in sec. max interval between scan operations to be performed to detect BSS channel width trigger events. -#define dot11OBSSScanPassiveTotalPerChannel 200 // in TU. min total amount of time that the STA scans each channel when performing a passive OBSS scan. -#define dot11OBSSScanActiveTotalPerChannel 20 //in TU. min total amount of time that the STA scans each channel when performing a active OBSS scan -#define dot11BSSWidthChannelTransactionDelayFactor 5 // min ratio between the delay time in performing a switch from 20MHz BSS to 20/40 BSS operation and the maxima - // interval between overlapping BSS scan operations. -#define dot11BSSScanActivityThreshold 25 // in %%, max total time that a STA may be active on the medium during a period of - // (dot11BSSWidthChannelTransactionDelayFactor * dot11BSSWidthTriggerScanInterval) seconds without - // being obligated to perform OBSS Scan operations. default is 25(== 0.25%) - -typedef struct PACKED _OVERLAP_BSS_SCAN_IE{ - USHORT ScanPassiveDwell; - USHORT ScanActiveDwell; - USHORT TriggerScanInt; // Trigger scan interval - USHORT PassiveTalPerChannel; // passive total per channel - USHORT ActiveTalPerChannel; // active total per channel - USHORT DelayFactor; // BSS width channel transition delay factor - USHORT ScanActThre; // Scan Activity threshold -}OVERLAP_BSS_SCAN_IE, *POVERLAP_BSS_SCAN_IE; - - -// 7.3.2.56. 20/40 Coexistence element used in Element ID = 72 = IE_2040_BSS_COEXIST -typedef union PACKED _BSS_2040_COEXIST_IE{ - struct PACKED { - UCHAR InfoReq:1; - UCHAR Intolerant40:1; // Inter-BSS. set 1 when prohibits a receiving BSS from operating as a 20/40 Mhz BSS. - UCHAR BSS20WidthReq:1; // Intra-BSS set 1 when prohibits a receiving AP from operating its BSS as a 20/40MHz BSS. - UCHAR rsv:5; - } field; - UCHAR word; +/* The structure for HT Capability IE. */ +struct PACKED rt_ht_capability_ie { + struct rt_ht_cap_info HtCapInfo; + struct rt_ht_cap_parm HtCapParm; +/* struct rt_ht_mcs_set HtMCSSet; */ + u8 MCSSet[16]; + struct rt_ext_ht_cap_info ExtHtCapInfo; + struct rt_ht_bf_cap TxBFCap; /* beamforming cap. rt2860c not support beamforming. */ + struct rt_ht_as_cap ASCap; /*antenna selection. */ +}; + +/* 802.11n draft3 related structure definitions. */ +/* 7.3.2.60 */ +#define dot11OBSSScanPassiveDwell 20 /* in TU. min amount of time that the STA continously scans each channel when performing an active OBSS scan. */ +#define dot11OBSSScanActiveDwell 10 /* in TU.min amount of time that the STA continously scans each channel when performing an passive OBSS scan. */ +#define dot11BSSWidthTriggerScanInterval 300 /* in sec. max interval between scan operations to be performed to detect BSS channel width trigger events. */ +#define dot11OBSSScanPassiveTotalPerChannel 200 /* in TU. min total amount of time that the STA scans each channel when performing a passive OBSS scan. */ +#define dot11OBSSScanActiveTotalPerChannel 20 /*in TU. min total amount of time that the STA scans each channel when performing a active OBSS scan */ +#define dot11BSSWidthChannelTransactionDelayFactor 5 /* min ratio between the delay time in performing a switch from 20MHz BSS to 20/40 BSS operation and the maximum */ + /* interval between overlapping BSS scan operations. */ +#define dot11BSSScanActivityThreshold 25 /* in %%, max total time that a STA may be active on the medium during a period of */ + /* (dot11BSSWidthChannelTransactionDelayFactor * dot11BSSWidthTriggerScanInterval) seconds without */ + /* being obligated to perform OBSS Scan operations. default is 25(== 0.25%) */ + +struct PACKED rt_overlap_bss_scan_ie { + u16 ScanPassiveDwell; + u16 ScanActiveDwell; + u16 TriggerScanInt; /* Trigger scan interval */ + u16 PassiveTalPerChannel; /* passive total per channel */ + u16 ActiveTalPerChannel; /* active total per channel */ + u16 DelayFactor; /* BSS width channel transition delay factor */ + u16 ScanActThre; /* Scan Activity threshold */ +}; + +/* 7.3.2.56. 20/40 Coexistence element used in Element ID = 72 = IE_2040_BSS_COEXIST */ +typedef union PACKED _BSS_2040_COEXIST_IE { + struct PACKED { + u8 InfoReq:1; + u8 Intolerant40:1; /* Inter-BSS. set 1 when prohibits a receiving BSS from operating as a 20/40 Mhz BSS. */ + u8 BSS20WidthReq:1; /* Intra-BSS set 1 when prohibits a receiving AP from operating its BSS as a 20/40MHz BSS. */ + u8 rsv:5; + } field; + u8 word; } BSS_2040_COEXIST_IE, *PBSS_2040_COEXIST_IE; +struct rt_trigger_eventa { + BOOLEAN bValid; + u8 BSSID[6]; + u8 RegClass; /* Regulatory Class */ + u16 Channel; + unsigned long CDCounter; /* Maintain a seperate count down counter for each Event A. */ +}; -typedef struct _TRIGGER_EVENTA{ - BOOLEAN bValid; - UCHAR BSSID[6]; - UCHAR RegClass; // Regulatory Class - USHORT Channel; - ULONG CDCounter; // Maintain a seperate count down counter for each Event A. -} TRIGGER_EVENTA, *PTRIGGER_EVENTA; - -// 20/40 trigger event table -// If one Event A delete or created, or if Event B is detected or not detected, STA should send 2040BSSCoexistence to AP. +/* 20/40 trigger event table */ +/* If one Event A delete or created, or if Event B is detected or not detected, STA should send 2040BSSCoexistence to AP. */ #define MAX_TRIGGER_EVENT 64 -typedef struct _TRIGGER_EVENT_TAB{ - UCHAR EventANo; - TRIGGER_EVENTA EventA[MAX_TRIGGER_EVENT]; - ULONG EventBCountDown; // Count down counter for Event B. -} TRIGGER_EVENT_TAB, *PTRIGGER_EVENT_TAB; - -// 7.3.27 20/40 Bss Coexistence Mgmt capability used in extended capabilities information IE( ID = 127 = IE_EXT_CAPABILITY). -// This is the first octet and was defined in 802.11n D3.03 and 802.11yD9.0 -typedef struct PACKED _EXT_CAP_INFO_ELEMENT{ - UCHAR BssCoexistMgmtSupport:1; - UCHAR rsv:1; - UCHAR ExtendChannelSwitch:1; - UCHAR rsv2:5; -}EXT_CAP_INFO_ELEMENT, *PEXT_CAP_INFO_ELEMENT; - - -// 802.11n 7.3.2.61 -typedef struct PACKED _BSS_2040_COEXIST_ELEMENT{ - UCHAR ElementID; // ID = IE_2040_BSS_COEXIST = 72 - UCHAR Len; - BSS_2040_COEXIST_IE BssCoexistIe; -}BSS_2040_COEXIST_ELEMENT, *PBSS_2040_COEXIST_ELEMENT; - - -//802.11n 7.3.2.59 -typedef struct PACKED _BSS_2040_INTOLERANT_CH_REPORT{ - UCHAR ElementID; // ID = IE_2040_BSS_INTOLERANT_REPORT = 73 - UCHAR Len; - UCHAR RegulatoryClass; - UCHAR ChList[0]; -}BSS_2040_INTOLERANT_CH_REPORT, *PBSS_2040_INTOLERANT_CH_REPORT; - - -// The structure for channel switch annoucement IE. This is in 802.11n D3.03 -typedef struct PACKED _CHA_SWITCH_ANNOUNCE_IE{ - UCHAR SwitchMode; //channel switch mode - UCHAR NewChannel; // - UCHAR SwitchCount; // -} CHA_SWITCH_ANNOUNCE_IE, *PCHA_SWITCH_ANNOUNCE_IE; - - -// The structure for channel switch annoucement IE. This is in 802.11n D3.03 -typedef struct PACKED _SEC_CHA_OFFSET_IE{ - UCHAR SecondaryChannelOffset; // 1: Secondary above, 3: Secondary below, 0: no Secondary -} SEC_CHA_OFFSET_IE, *PSEC_CHA_OFFSET_IE; - - -// This structure is extracted from struct RT_HT_CAPABILITY -typedef struct { - BOOLEAN bHtEnable; // If we should use ht rate. - BOOLEAN bPreNHt; // If we should use ht rate. - //Substract from HT Capability IE - UCHAR MCSSet[16]; //only supoort MCS=0-15,32 , -} RT_HT_PHY_INFO, *PRT_HT_PHY_INFO; - -//This structure substracts ralink supports from all 802.11n-related features. -//Features not listed here but contained in 802.11n spec are not supported in rt2860. -typedef struct { - USHORT ChannelWidth:1; - USHORT MimoPs:2;//mimo power safe MMPS_ - USHORT GF:1; //green field - USHORT ShortGIfor20:1; - USHORT ShortGIfor40:1; //for40MHz - USHORT TxSTBC:1; - USHORT RxSTBC:2; // 2 bits - USHORT AmsduEnable:1; // Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n - USHORT AmsduSize:1; // Max receiving A-MSDU size - USHORT rsv:5; - - //Substract from Addiont HT INFO IE - UCHAR MaxRAmpduFactor:2; - UCHAR MpduDensity:3; - UCHAR ExtChanOffset:2; // Please not the difference with following UCHAR NewExtChannelOffset; from 802.11n - UCHAR RecomWidth:1; - - USHORT OperaionMode:2; - USHORT NonGfPresent:1; - USHORT rsv3:1; - USHORT OBSS_NonHTExist:1; - USHORT rsv2:11; - - // New Extension Channel Offset IE - UCHAR NewExtChannelOffset; - // Extension Capability IE = 127 - UCHAR BSSCoexist2040; -} RT_HT_CAPABILITY, *PRT_HT_CAPABILITY; - -// field in Addtional HT Information IE . -typedef struct PACKED { - UCHAR ExtChanOffset:2; - UCHAR RecomWidth:1; - UCHAR RifsMode:1; - UCHAR S_PSMPSup:1; //Indicate support for scheduled PSMP - UCHAR SerInterGranu:3; //service interval granularity -} ADD_HTINFO, *PADD_HTINFO; - -typedef struct PACKED{ - USHORT OperaionMode:2; - USHORT NonGfPresent:1; - USHORT rsv:1; - USHORT OBSS_NonHTExist:1; - USHORT rsv2:11; -} ADD_HTINFO2, *PADD_HTINFO2; - - -// TODO: Need sync with spec about the definition of StbcMcs. In Draft 3.03, it's reserved. -typedef struct PACKED{ - USHORT StbcMcs:6; - USHORT DualBeacon:1; - USHORT DualCTSProtect:1; - USHORT STBCBeacon:1; - USHORT LsigTxopProt:1; // L-SIG TXOP protection full support - USHORT PcoActive:1; - USHORT PcoPhase:1; - USHORT rsv:4; -} ADD_HTINFO3, *PADD_HTINFO3; +struct rt_trigger_event_tab { + u8 EventANo; + struct rt_trigger_eventa EventA[MAX_TRIGGER_EVENT]; + unsigned long EventBCountDown; /* Count down counter for Event B. */ +}; + +/* 7.3.27 20/40 Bss Coexistence Mgmt capability used in extended capabilities information IE( ID = 127 = IE_EXT_CAPABILITY). */ +/* This is the first octet and was defined in 802.11n D3.03 and 802.11yD9.0 */ +struct PACKED rt_ext_cap_info_element { + u8 BssCoexistMgmtSupport:1; + u8 rsv:1; + u8 ExtendChannelSwitch:1; + u8 rsv2:5; +}; + +/* 802.11n 7.3.2.61 */ +struct PACKED rt_bss_2040_coexist_element { + u8 ElementID; /* ID = IE_2040_BSS_COEXIST = 72 */ + u8 Len; + BSS_2040_COEXIST_IE BssCoexistIe; +}; + +/*802.11n 7.3.2.59 */ +struct PACKED rt_bss_2040_intolerant_ch_report { + u8 ElementID; /* ID = IE_2040_BSS_INTOLERANT_REPORT = 73 */ + u8 Len; + u8 RegulatoryClass; + u8 ChList[0]; +}; + +/* The structure for channel switch annoucement IE. This is in 802.11n D3.03 */ +struct PACKED rt_cha_switch_announce_ie { + u8 SwitchMode; /*channel switch mode */ + u8 NewChannel; /* */ + u8 SwitchCount; /* */ +}; + +/* The structure for channel switch annoucement IE. This is in 802.11n D3.03 */ +struct PACKED rt_sec_cha_offset_ie { + u8 SecondaryChannelOffset; /* 1: Secondary above, 3: Secondary below, 0: no Secondary */ +}; + +/* This structure is extracted from struct struct rt_ht_capability */ +struct rt_ht_phy_info { + BOOLEAN bHtEnable; /* If we should use ht rate. */ + BOOLEAN bPreNHt; /* If we should use ht rate. */ + /*Substract from HT Capability IE */ + u8 MCSSet[16]; +}; + +/*This structure substracts ralink supports from all 802.11n-related features. */ +/*Features not listed here but contained in 802.11n spec are not supported in rt2860. */ +struct rt_ht_capability { + u16 ChannelWidth:1; + u16 MimoPs:2; /*mimo power safe MMPS_ */ + u16 GF:1; /*green field */ + u16 ShortGIfor20:1; + u16 ShortGIfor40:1; /*for40MHz */ + u16 TxSTBC:1; + u16 RxSTBC:2; /* 2 bits */ + u16 AmsduEnable:1; /* Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n */ + u16 AmsduSize:1; /* Max receiving A-MSDU size */ + u16 rsv:5; + + /*Substract from Addiont HT INFO IE */ + u8 MaxRAmpduFactor:2; + u8 MpduDensity:3; + u8 ExtChanOffset:2; /* Please not the difference with following u8 NewExtChannelOffset; from 802.11n */ + u8 RecomWidth:1; + + u16 OperaionMode:2; + u16 NonGfPresent:1; + u16 rsv3:1; + u16 OBSS_NonHTExist:1; + u16 rsv2:11; + + /* New Extension Channel Offset IE */ + u8 NewExtChannelOffset; + /* Extension Capability IE = 127 */ + u8 BSSCoexist2040; +}; + +/* field in Addtional HT Information IE . */ +struct PACKED rt_add_htinfo { + u8 ExtChanOffset:2; + u8 RecomWidth:1; + u8 RifsMode:1; + u8 S_PSMPSup:1; /*Indicate support for scheduled PSMP */ + u8 SerInterGranu:3; /*service interval granularity */ +}; + +struct PACKED rt_add_htinfo2 { + u16 OperaionMode:2; + u16 NonGfPresent:1; + u16 rsv:1; + u16 OBSS_NonHTExist:1; + u16 rsv2:11; +}; + +/* TODO: Need sync with spec about the definition of StbcMcs. In Draft 3.03, it's reserved. */ +struct PACKED rt_add_htinfo3 { + u16 StbcMcs:6; + u16 DualBeacon:1; + u16 DualCTSProtect:1; + u16 STBCBeacon:1; + u16 LsigTxopProt:1; /* L-SIG TXOP protection full support */ + u16 PcoActive:1; + u16 PcoPhase:1; + u16 rsv:4; +}; #define SIZE_ADD_HT_INFO_IE 22 -typedef struct PACKED{ - UCHAR ControlChan; - ADD_HTINFO AddHtInfo; - ADD_HTINFO2 AddHtInfo2; - ADD_HTINFO3 AddHtInfo3; - UCHAR MCSSet[16]; // Basic MCS set -} ADD_HT_INFO_IE, *PADD_HT_INFO_IE; - -typedef struct PACKED{ - UCHAR NewExtChanOffset; -} NEW_EXT_CHAN_IE, *PNEW_EXT_CHAN_IE; - - -// 4-byte HTC field. maybe included in any frame except non-QOS data frame. The Order bit must set 1. -typedef struct PACKED { - UINT32 MA:1; //management action payload exist in (QoS Null+HTC) - UINT32 TRQ:1; //sounding request - UINT32 MRQ:1; //MCS feedback. Request for a MCS feedback - UINT32 MRSorASI:3; // MRQ Sequence identifier. unchanged during entire procedure. 0x000-0x110. - UINT32 MFS:3; //SET to the received value of MRS. 0x111 for unsolicited MFB. - UINT32 MFBorASC:7; //Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available - UINT32 CalPos:2; // calibration position - UINT32 CalSeq:2; //calibration sequence - UINT32 FBKReq:2; //feedback request - UINT32 CSISTEERING:2; //CSI/ STEERING - UINT32 ZLFAnnouce:1; // ZLF announcement - UINT32 rsv:5; //calibration sequence - UINT32 ACConstraint:1; //feedback request - UINT32 RDG:1; //RDG / More PPDU -} HT_CONTROL, *PHT_CONTROL; - -// 2-byte QOS CONTROL field -typedef struct PACKED { - USHORT TID:4; - USHORT EOSP:1; - USHORT AckPolicy:2; //0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP 3: BA - USHORT AMsduPresent:1; - USHORT Txop_QueueSize:8; -} QOS_CONTROL, *PQOS_CONTROL; - -// 2-byte Frame control field -typedef struct PACKED { - USHORT Ver:2; // Protocol version - USHORT Type:2; // MSDU type - USHORT SubType:4; // MSDU subtype - USHORT ToDs:1; // To DS indication - USHORT FrDs:1; // From DS indication - USHORT MoreFrag:1; // More fragment bit - USHORT Retry:1; // Retry status bit - USHORT PwrMgmt:1; // Power management bit - USHORT MoreData:1; // More data bit - USHORT Wep:1; // Wep data - USHORT Order:1; // Strict order expected -} FRAME_CONTROL, *PFRAME_CONTROL; - -typedef struct PACKED _HEADER_802_11 { - FRAME_CONTROL FC; - USHORT Duration; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; - UCHAR Addr3[MAC_ADDR_LEN]; - USHORT Frag:4; - USHORT Sequence:12; - UCHAR Octet[0]; -} HEADER_802_11, *PHEADER_802_11; - -typedef struct PACKED _FRAME_802_11 { - HEADER_802_11 Hdr; - UCHAR Octet[1]; -} FRAME_802_11, *PFRAME_802_11; - -// QoSNull embedding of management action. When HT Control MA field set to 1. -typedef struct PACKED _MA_BODY { - UCHAR Category; - UCHAR Action; - UCHAR Octet[1]; -} MA_BODY, *PMA_BODY; - -typedef struct PACKED _HEADER_802_3 { - UCHAR DAAddr1[MAC_ADDR_LEN]; - UCHAR SAAddr2[MAC_ADDR_LEN]; - UCHAR Octet[2]; -} HEADER_802_3, *PHEADER_802_3; -////Block ACK related format -// 2-byte BA Parameter field in DELBA frames to terminate an already set up bA -typedef struct PACKED{ - USHORT Rsv:11; // always set to 0 - USHORT Initiator:1; // 1: originator 0:recipient - USHORT TID:4; // value of TC os TS -} DELBA_PARM, *PDELBA_PARM; - -// 2-byte BA Parameter Set field in ADDBA frames to signal parm for setting up a BA -typedef struct PACKED { - USHORT AMSDUSupported:1; // 0: not permitted 1: permitted - USHORT BAPolicy:1; // 1: immediately BA 0:delayed BA - USHORT TID:4; // value of TC os TS - USHORT BufSize:10; // number of buffe of size 2304 octetsr -} BA_PARM, *PBA_PARM; - -// 2-byte BA Starting Seq CONTROL field -typedef union PACKED { - struct PACKED { - USHORT FragNum:4; // always set to 0 - USHORT StartSeq:12; // sequence number of the 1st MSDU for which this BAR is sent - } field; - USHORT word; +struct PACKED rt_add_ht_info_ie { + u8 ControlChan; + struct rt_add_htinfo AddHtInfo; + struct rt_add_htinfo2 AddHtInfo2; + struct rt_add_htinfo3 AddHtInfo3; + u8 MCSSet[16]; /* Basic MCS set */ +}; + +struct PACKED rt_new_ext_chan_ie { + u8 NewExtChanOffset; +}; + +struct PACKED rt_frame_802_11 { + struct rt_header_802_11 Hdr; + u8 Octet[1]; +}; + +/* QoSNull embedding of management action. When HT Control MA field set to 1. */ +struct PACKED rt_ma_body { + u8 Category; + u8 Action; + u8 Octet[1]; +}; + +struct PACKED rt_header_802_3 { + u8 DAAddr1[MAC_ADDR_LEN]; + u8 SAAddr2[MAC_ADDR_LEN]; + u8 Octet[2]; +}; +/*//Block ACK related format */ +/* 2-byte BA Parameter field in DELBA frames to terminate an already set up bA */ +struct PACKED rt_delba_parm { + u16 Rsv:11; /* always set to 0 */ + u16 Initiator:1; /* 1: originator 0:recipient */ + u16 TID:4; /* value of TC os TS */ +}; + +/* 2-byte BA Parameter Set field in ADDBA frames to signal parm for setting up a BA */ +struct PACKED rt_ba_parm { + u16 AMSDUSupported:1; /* 0: not permitted 1: permitted */ + u16 BAPolicy:1; /* 1: immediately BA 0:delayed BA */ + u16 TID:4; /* value of TC os TS */ + u16 BufSize:10; /* number of buffe of size 2304 octetsr */ +}; + +/* 2-byte BA Starting Seq CONTROL field */ +typedef union PACKED _BASEQ_CONTROL { + struct PACKED { + u16 FragNum:4; /* always set to 0 */ + u16 StartSeq:12; /* sequence number of the 1st MSDU for which this BAR is sent */ + } field; + u16 word; } BASEQ_CONTROL, *PBASEQ_CONTROL; -//BAControl and BARControl are the same -// 2-byte BA CONTROL field in BA frame -typedef struct PACKED { - USHORT ACKPolicy:1; // only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK 1:No ACK - USHORT MTID:1; //EWC V1.24 - USHORT Compressed:1; - USHORT Rsv:9; - USHORT TID:4; -} BA_CONTROL, *PBA_CONTROL; - -// 2-byte BAR CONTROL field in BAR frame -typedef struct PACKED { - USHORT ACKPolicy:1; // 0:normal ack, 1:no ack. - USHORT MTID:1; //if this bit1, use FRAME_MTBA_REQ, if 0, use FRAME_BA_REQ - USHORT Compressed:1; - USHORT Rsv1:9; - USHORT TID:4; -} BAR_CONTROL, *PBAR_CONTROL; - -// BARControl in MTBAR frame -typedef struct PACKED { - USHORT ACKPolicy:1; - USHORT MTID:1; - USHORT Compressed:1; - USHORT Rsv1:9; - USHORT NumTID:4; -} MTBAR_CONTROL, *PMTBAR_CONTROL; - -typedef struct PACKED { - USHORT Rsv1:12; - USHORT TID:4; -} PER_TID_INFO, *PPER_TID_INFO; - -typedef struct { - PER_TID_INFO PerTID; - BASEQ_CONTROL BAStartingSeq; -} EACH_TID, *PEACH_TID; - - -typedef struct PACKED _PSPOLL_FRAME { - FRAME_CONTROL FC; - USHORT Aid; - UCHAR Bssid[MAC_ADDR_LEN]; - UCHAR Ta[MAC_ADDR_LEN]; -} PSPOLL_FRAME, *PPSPOLL_FRAME; - -typedef struct PACKED _RTS_FRAME { - FRAME_CONTROL FC; - USHORT Duration; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; -}RTS_FRAME, *PRTS_FRAME; - -// BAREQ AND MTBAREQ have the same subtype BAR, 802.11n BAR use compressed bitmap. -typedef struct PACKED _FRAME_BA_REQ { - FRAME_CONTROL FC; - USHORT Duration; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; - BAR_CONTROL BARControl; - BASEQ_CONTROL BAStartingSeq; -} FRAME_BA_REQ, *PFRAME_BA_REQ; - -typedef struct PACKED _FRAME_MTBA_REQ { - FRAME_CONTROL FC; - USHORT Duration; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; - MTBAR_CONTROL MTBARControl; - PER_TID_INFO PerTIDInfo; - BASEQ_CONTROL BAStartingSeq; -} FRAME_MTBA_REQ, *PFRAME_MTBA_REQ; - -// Compressed format is mandantory in HT STA -typedef struct PACKED _FRAME_MTBA { - FRAME_CONTROL FC; - USHORT Duration; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; - BA_CONTROL BAControl; - BASEQ_CONTROL BAStartingSeq; - UCHAR BitMap[8]; -} FRAME_MTBA, *PFRAME_MTBA; - -typedef struct PACKED _FRAME_PSMP_ACTION { - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; - UCHAR Psmp; // 7.3.1.25 -} FRAME_PSMP_ACTION, *PFRAME_PSMP_ACTION; - -typedef struct PACKED _FRAME_ACTION_HDR { - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; -} FRAME_ACTION_HDR, *PFRAME_ACTION_HDR; - -//Action Frame -//Action Frame Category:Spectrum, Action:Channel Switch. 7.3.2.20 -typedef struct PACKED _CHAN_SWITCH_ANNOUNCE { - UCHAR ElementID; // ID = IE_CHANNEL_SWITCH_ANNOUNCEMENT = 37 - UCHAR Len; - CHA_SWITCH_ANNOUNCE_IE CSAnnounceIe; -} CHAN_SWITCH_ANNOUNCE, *PCHAN_SWITCH_ANNOUNCE; - - -//802.11n : 7.3.2.20a -typedef struct PACKED _SECOND_CHAN_OFFSET { - UCHAR ElementID; // ID = IE_SECONDARY_CH_OFFSET = 62 - UCHAR Len; - SEC_CHA_OFFSET_IE SecChOffsetIe; -} SECOND_CHAN_OFFSET, *PSECOND_CHAN_OFFSET; - - -typedef struct PACKED _FRAME_SPETRUM_CS { - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; - CHAN_SWITCH_ANNOUNCE CSAnnounce; - SECOND_CHAN_OFFSET SecondChannel; -} FRAME_SPETRUM_CS, *PFRAME_SPETRUM_CS; - - -typedef struct PACKED _FRAME_ADDBA_REQ { - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; - UCHAR Token; // 1 - BA_PARM BaParm; // 2 - 10 - USHORT TimeOutValue; // 0 - 0 - BASEQ_CONTROL BaStartSeq; // 0-0 -} FRAME_ADDBA_REQ, *PFRAME_ADDBA_REQ; - -typedef struct PACKED _FRAME_ADDBA_RSP { - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; - UCHAR Token; - USHORT StatusCode; - BA_PARM BaParm; //0 - 2 - USHORT TimeOutValue; -} FRAME_ADDBA_RSP, *PFRAME_ADDBA_RSP; - -typedef struct PACKED _FRAME_DELBA_REQ { - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; - DELBA_PARM DelbaParm; - USHORT ReasonCode; -} FRAME_DELBA_REQ, *PFRAME_DELBA_REQ; - - -//7.2.1.7 -typedef struct PACKED _FRAME_BAR { - FRAME_CONTROL FC; - USHORT Duration; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; - BAR_CONTROL BarControl; - BASEQ_CONTROL StartingSeq; -} FRAME_BAR, *PFRAME_BAR; - -//7.2.1.7 -typedef struct PACKED _FRAME_BA { - FRAME_CONTROL FC; - USHORT Duration; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; - BAR_CONTROL BarControl; - BASEQ_CONTROL StartingSeq; - UCHAR bitmask[8]; -} FRAME_BA, *PFRAME_BA; - - -// Radio Measuement Request Frame Format -typedef struct PACKED _FRAME_RM_REQ_ACTION { - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; - UCHAR Token; - USHORT Repetition; - UCHAR data[0]; -} FRAME_RM_REQ_ACTION, *PFRAME_RM_REQ_ACTION; - -typedef struct PACKED { - UCHAR ID; - UCHAR Length; - UCHAR ChannelSwitchMode; - UCHAR NewRegClass; - UCHAR NewChannelNum; - UCHAR ChannelSwitchCount; -} HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE, *PHT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE; - - -// -// _Limit must be the 2**n - 1 -// _SEQ1 , _SEQ2 must be within 0 ~ _Limit -// +/*BAControl and BARControl are the same */ +/* 2-byte BA CONTROL field in BA frame */ +struct PACKED rt_ba_control { + u16 ACKPolicy:1; /* only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK 1:No ACK */ + u16 MTID:1; /*EWC V1.24 */ + u16 Compressed:1; + u16 Rsv:9; + u16 TID:4; +}; + +/* 2-byte BAR CONTROL field in BAR frame */ +struct PACKED rt_bar_control { + u16 ACKPolicy:1; /* 0:normal ack, 1:no ack. */ + u16 MTID:1; /*if this bit1, use struct rt_frame_mtba_req, if 0, use struct rt_frame_ba_req */ + u16 Compressed:1; + u16 Rsv1:9; + u16 TID:4; +}; + +/* BARControl in MTBAR frame */ +struct PACKED rt_mtbar_control { + u16 ACKPolicy:1; + u16 MTID:1; + u16 Compressed:1; + u16 Rsv1:9; + u16 NumTID:4; +}; + +struct PACKED rt_per_tid_info { + u16 Rsv1:12; + u16 TID:4; +}; + +struct rt_each_tid { + struct rt_per_tid_info PerTID; + BASEQ_CONTROL BAStartingSeq; +}; + +/* BAREQ AND MTBAREQ have the same subtype BAR, 802.11n BAR use compressed bitmap. */ +struct PACKED rt_frame_ba_req { + struct rt_frame_control FC; + u16 Duration; + u8 Addr1[MAC_ADDR_LEN]; + u8 Addr2[MAC_ADDR_LEN]; + struct rt_bar_control BARControl; + BASEQ_CONTROL BAStartingSeq; +}; + +struct PACKED rt_frame_mtba_req { + struct rt_frame_control FC; + u16 Duration; + u8 Addr1[MAC_ADDR_LEN]; + u8 Addr2[MAC_ADDR_LEN]; + struct rt_mtbar_control MTBARControl; + struct rt_per_tid_info PerTIDInfo; + BASEQ_CONTROL BAStartingSeq; +}; + +/* Compressed format is mandantory in HT STA */ +struct PACKED rt_frame_mtba { + struct rt_frame_control FC; + u16 Duration; + u8 Addr1[MAC_ADDR_LEN]; + u8 Addr2[MAC_ADDR_LEN]; + struct rt_ba_control BAControl; + BASEQ_CONTROL BAStartingSeq; + u8 BitMap[8]; +}; + +struct PACKED rt_frame_psmp_action { + struct rt_header_802_11 Hdr; + u8 Category; + u8 Action; + u8 Psmp; /* 7.3.1.25 */ +}; + +struct PACKED rt_frame_action_hdr { + struct rt_header_802_11 Hdr; + u8 Category; + u8 Action; +}; + +/*Action Frame */ +/*Action Frame Category:Spectrum, Action:Channel Switch. 7.3.2.20 */ +struct PACKED rt_chan_switch_announce { + u8 ElementID; /* ID = IE_CHANNEL_SWITCH_ANNOUNCEMENT = 37 */ + u8 Len; + struct rt_cha_switch_announce_ie CSAnnounceIe; +}; + +/*802.11n : 7.3.2.20a */ +struct PACKED rt_second_chan_offset { + u8 ElementID; /* ID = IE_SECONDARY_CH_OFFSET = 62 */ + u8 Len; + struct rt_sec_cha_offset_ie SecChOffsetIe; +}; + +struct PACKED rt_frame_spetrum_cs { + struct rt_header_802_11 Hdr; + u8 Category; + u8 Action; + struct rt_chan_switch_announce CSAnnounce; + struct rt_second_chan_offset SecondChannel; +}; + +struct PACKED rt_frame_addba_req { + struct rt_header_802_11 Hdr; + u8 Category; + u8 Action; + u8 Token; /* 1 */ + struct rt_ba_parm BaParm; /* 2 - 10 */ + u16 TimeOutValue; /* 0 - 0 */ + BASEQ_CONTROL BaStartSeq; /* 0-0 */ +}; + +struct PACKED rt_frame_addba_rsp { + struct rt_header_802_11 Hdr; + u8 Category; + u8 Action; + u8 Token; + u16 StatusCode; + struct rt_ba_parm BaParm; /*0 - 2 */ + u16 TimeOutValue; +}; + +struct PACKED rt_frame_delba_req { + struct rt_header_802_11 Hdr; + u8 Category; + u8 Action; + struct rt_delba_parm DelbaParm; + u16 ReasonCode; +}; + +/*7.2.1.7 */ +struct PACKED rt_frame_bar { + struct rt_frame_control FC; + u16 Duration; + u8 Addr1[MAC_ADDR_LEN]; + u8 Addr2[MAC_ADDR_LEN]; + struct rt_bar_control BarControl; + BASEQ_CONTROL StartingSeq; +}; + +/*7.2.1.7 */ +struct PACKED rt_frame_ba { + struct rt_frame_control FC; + u16 Duration; + u8 Addr1[MAC_ADDR_LEN]; + u8 Addr2[MAC_ADDR_LEN]; + struct rt_bar_control BarControl; + BASEQ_CONTROL StartingSeq; + u8 bitmask[8]; +}; + +/* Radio Measuement Request Frame Format */ +struct PACKED rt_frame_rm_req_action { + struct rt_header_802_11 Hdr; + u8 Category; + u8 Action; + u8 Token; + u16 Repetition; + u8 data[0]; +}; + +struct PACKED rt_ht_ext_channel_switch_announcement_ie { + u8 ID; + u8 Length; + u8 ChannelSwitchMode; + u8 NewRegClass; + u8 NewChannelNum; + u8 ChannelSwitchCount; +}; + +/* */ +/* _Limit must be the 2**n - 1 */ +/* _SEQ1 , _SEQ2 must be within 0 ~ _Limit */ +/* */ #define SEQ_STEPONE(_SEQ1, _SEQ2, _Limit) ((_SEQ1 == ((_SEQ2+1) & _Limit))) #define SEQ_SMALLER(_SEQ1, _SEQ2, _Limit) (((_SEQ1-_SEQ2) & ((_Limit+1)>>1))) #define SEQ_LARGER(_SEQ1, _SEQ2, _Limit) ((_SEQ1 != _SEQ2) && !(((_SEQ1-_SEQ2) & ((_Limit+1)>>1)))) #define SEQ_WITHIN_WIN(_SEQ1, _SEQ2, _WIN, _Limit) (SEQ_LARGER(_SEQ1, _SEQ2, _Limit) && \ SEQ_SMALLER(_SEQ1, ((_SEQ2+_WIN+1)&_Limit), _Limit)) -// -// Contention-free parameter (without ID and Length) -// -typedef struct PACKED { - BOOLEAN bValid; // 1: variable contains valid value - UCHAR CfpCount; - UCHAR CfpPeriod; - USHORT CfpMaxDuration; - USHORT CfpDurRemaining; -} CF_PARM, *PCF_PARM; - -typedef struct _CIPHER_SUITE { - NDIS_802_11_ENCRYPTION_STATUS PairCipher; // Unicast cipher 1, this one has more secured cipher suite - NDIS_802_11_ENCRYPTION_STATUS PairCipherAux; // Unicast cipher 2 if AP announce two unicast cipher suite - NDIS_802_11_ENCRYPTION_STATUS GroupCipher; // Group cipher - USHORT RsnCapability; // RSN capability from beacon - BOOLEAN bMixMode; // Indicate Pair & Group cipher might be different -} CIPHER_SUITE, *PCIPHER_SUITE; - -// EDCA configuration from AP's BEACON/ProbeRsp -typedef struct { - BOOLEAN bValid; // 1: variable contains valid value - BOOLEAN bAdd; // 1: variable contains valid value - BOOLEAN bQAck; - BOOLEAN bQueueRequest; - BOOLEAN bTxopRequest; - BOOLEAN bAPSDCapable; -// BOOLEAN bMoreDataAck; - UCHAR EdcaUpdateCount; - UCHAR Aifsn[4]; // 0:AC_BK, 1:AC_BE, 2:AC_VI, 3:AC_VO - UCHAR Cwmin[4]; - UCHAR Cwmax[4]; - USHORT Txop[4]; // in unit of 32-us - BOOLEAN bACM[4]; // 1: Admission Control of AC_BK is mandattory -} EDCA_PARM, *PEDCA_PARM; - -// QBSS LOAD information from QAP's BEACON/ProbeRsp -typedef struct { - BOOLEAN bValid; // 1: variable contains valid value - USHORT StaNum; - UCHAR ChannelUtilization; - USHORT RemainingAdmissionControl; // in unit of 32-us -} QBSS_LOAD_PARM, *PQBSS_LOAD_PARM; - -// QBSS Info field in QSTA's assoc req -typedef struct PACKED { - UCHAR UAPSD_AC_VO:1; - UCHAR UAPSD_AC_VI:1; - UCHAR UAPSD_AC_BK:1; - UCHAR UAPSD_AC_BE:1; - UCHAR Rsv1:1; - UCHAR MaxSPLength:2; - UCHAR Rsv2:1; -} QBSS_STA_INFO_PARM, *PQBSS_STA_INFO_PARM; - -// QBSS Info field in QAP's Beacon/ProbeRsp -typedef struct PACKED { - UCHAR ParamSetCount:4; - UCHAR Rsv:3; - UCHAR UAPSD:1; -} QBSS_AP_INFO_PARM, *PQBSS_AP_INFO_PARM; - -// QOS Capability reported in QAP's BEACON/ProbeRsp -// QOS Capability sent out in QSTA's AssociateReq/ReAssociateReq -typedef struct { - BOOLEAN bValid; // 1: variable contains valid value - BOOLEAN bQAck; - BOOLEAN bQueueRequest; - BOOLEAN bTxopRequest; -// BOOLEAN bMoreDataAck; - UCHAR EdcaUpdateCount; -} QOS_CAPABILITY_PARM, *PQOS_CAPABILITY_PARM; - -typedef struct { - UCHAR IELen; - UCHAR IE[MAX_CUSTOM_LEN]; -} WPA_IE_; - -typedef struct { - UCHAR Bssid[MAC_ADDR_LEN]; - UCHAR Channel; - UCHAR CentralChannel; //Store the wide-band central channel for 40MHz. .used in 40MHz AP. Or this is the same as Channel. - UCHAR BssType; - USHORT AtimWin; - USHORT BeaconPeriod; - - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen; - UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR ExtRateLen; - HT_CAPABILITY_IE HtCapability; - UCHAR HtCapabilityLen; - ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE - UCHAR AddHtInfoLen; - UCHAR NewExtChanOffset; - CHAR Rssi; - UCHAR Privacy; // Indicate security function ON/OFF. Don't mess up with auth mode. - UCHAR Hidden; - - USHORT DtimPeriod; - USHORT CapabilityInfo; - - USHORT CfpCount; - USHORT CfpPeriod; - USHORT CfpMaxDuration; - USHORT CfpDurRemaining; - UCHAR SsidLen; - CHAR Ssid[MAX_LEN_OF_SSID]; - - ULONG LastBeaconRxTime; // OS's timestamp - - BOOLEAN bSES; - - // New for WPA2 - CIPHER_SUITE WPA; // AP announced WPA cipher suite - CIPHER_SUITE WPA2; // AP announced WPA2 cipher suite - - // New for microsoft WPA support - NDIS_802_11_FIXED_IEs FixIEs; - NDIS_802_11_AUTHENTICATION_MODE AuthModeAux; // Addition mode for WPA2 / WPA capable AP - NDIS_802_11_AUTHENTICATION_MODE AuthMode; - NDIS_802_11_WEP_STATUS WepStatus; // Unicast Encryption Algorithm extract from VAR_IE - USHORT VarIELen; // Length of next VIE include EID & Length - UCHAR VarIEs[MAX_VIE_LEN]; - - // CCX Ckip information - UCHAR CkipFlag; - - // CCX 2 TSF - UCHAR PTSF[4]; // Parent TSF - UCHAR TTSF[8]; // Target TSF - - // 802.11e d9, and WMM - EDCA_PARM EdcaParm; - QOS_CAPABILITY_PARM QosCapability; - QBSS_LOAD_PARM QbssLoad; - WPA_IE_ WpaIE; - WPA_IE_ RsnIE; -} BSS_ENTRY, *PBSS_ENTRY; - -typedef struct { - UCHAR BssNr; - UCHAR BssOverlapNr; - BSS_ENTRY BssEntry[MAX_LEN_OF_BSS_TABLE]; -} BSS_TABLE, *PBSS_TABLE; - - -typedef struct _MLME_QUEUE_ELEM { - ULONG Machine; - ULONG MsgType; - ULONG MsgLen; - UCHAR Msg[MGMT_DMA_BUFFER_SIZE]; - LARGE_INTEGER TimeStamp; - UCHAR Rssi0; - UCHAR Rssi1; - UCHAR Rssi2; - UCHAR Signal; - UCHAR Channel; - UCHAR Wcid; - BOOLEAN Occupied; -} MLME_QUEUE_ELEM, *PMLME_QUEUE_ELEM; - -typedef struct _MLME_QUEUE { - ULONG Num; - ULONG Head; - ULONG Tail; - NDIS_SPIN_LOCK Lock; - MLME_QUEUE_ELEM Entry[MAX_LEN_OF_MLME_QUEUE]; -} MLME_QUEUE, *PMLME_QUEUE; - -typedef VOID (*STATE_MACHINE_FUNC)(VOID *Adaptor, MLME_QUEUE_ELEM *Elem); - -typedef struct _STATE_MACHINE { - ULONG Base; - ULONG NrState; - ULONG NrMsg; - ULONG CurrState; - STATE_MACHINE_FUNC *TransFunc; -} STATE_MACHINE, *PSTATE_MACHINE; - - -// MLME AUX data structure that hold temporarliy settings during a connection attempt. -// Once this attemp succeeds, all settings will be copy to pAd->StaActive. -// A connection attempt (user set OID, roaming, CCX fast roaming,..) consists of -// several steps (JOIN, AUTH, ASSOC or REASSOC) and may fail at any step. We purposely -// separate this under-trial settings away from pAd->StaActive so that once -// this new attempt failed, driver can auto-recover back to the active settings. -typedef struct _MLME_AUX { - UCHAR BssType; - UCHAR Ssid[MAX_LEN_OF_SSID]; - UCHAR SsidLen; - UCHAR Bssid[MAC_ADDR_LEN]; - UCHAR AutoReconnectSsid[MAX_LEN_OF_SSID]; - UCHAR AutoReconnectSsidLen; - USHORT Alg; - UCHAR ScanType; - UCHAR Channel; - UCHAR CentralChannel; - USHORT Aid; - USHORT CapabilityInfo; - USHORT BeaconPeriod; - USHORT CfpMaxDuration; - USHORT CfpPeriod; - USHORT AtimWin; - - // Copy supported rate from desired AP's beacon. We are trying to match - // AP's supported and extended rate settings. - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen; - UCHAR ExtRateLen; - HT_CAPABILITY_IE HtCapability; - UCHAR HtCapabilityLen; - ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE - UCHAR NewExtChannelOffset; - //RT_HT_CAPABILITY SupportedHtPhy; - - // new for QOS - QOS_CAPABILITY_PARM APQosCapability; // QOS capability of the current associated AP - EDCA_PARM APEdcaParm; // EDCA parameters of the current associated AP - QBSS_LOAD_PARM APQbssLoad; // QBSS load of the current associated AP - - // new to keep Ralink specific feature - ULONG APRalinkIe; - - BSS_TABLE SsidBssTab; // AP list for the same SSID - BSS_TABLE RoamTab; // AP list eligible for roaming - ULONG BssIdx; - ULONG RoamIdx; - - BOOLEAN CurrReqIsFromNdis; - - RALINK_TIMER_STRUCT BeaconTimer, ScanTimer; - RALINK_TIMER_STRUCT AuthTimer; - RALINK_TIMER_STRUCT AssocTimer, ReassocTimer, DisassocTimer; -} MLME_AUX, *PMLME_AUX; - -typedef struct _MLME_ADDBA_REQ_STRUCT{ - UCHAR Wcid; // - UCHAR pAddr[MAC_ADDR_LEN]; - UCHAR BaBufSize; - USHORT TimeOutValue; - UCHAR TID; - UCHAR Token; - USHORT BaStartSeq; -} MLME_ADDBA_REQ_STRUCT, *PMLME_ADDBA_REQ_STRUCT; - - -typedef struct _MLME_DELBA_REQ_STRUCT{ - UCHAR Wcid; // - UCHAR Addr[MAC_ADDR_LEN]; - UCHAR TID; - UCHAR Initiator; -} MLME_DELBA_REQ_STRUCT, *PMLME_DELBA_REQ_STRUCT; - -// assoc struct is equal to reassoc -typedef struct _MLME_ASSOC_REQ_STRUCT{ - UCHAR Addr[MAC_ADDR_LEN]; - USHORT CapabilityInfo; - USHORT ListenIntv; - ULONG Timeout; -} MLME_ASSOC_REQ_STRUCT, *PMLME_ASSOC_REQ_STRUCT, MLME_REASSOC_REQ_STRUCT, *PMLME_REASSOC_REQ_STRUCT; - -typedef struct _MLME_DISASSOC_REQ_STRUCT{ - UCHAR Addr[MAC_ADDR_LEN]; - USHORT Reason; -} MLME_DISASSOC_REQ_STRUCT, *PMLME_DISASSOC_REQ_STRUCT; - -typedef struct _MLME_AUTH_REQ_STRUCT { - UCHAR Addr[MAC_ADDR_LEN]; - USHORT Alg; - ULONG Timeout; -} MLME_AUTH_REQ_STRUCT, *PMLME_AUTH_REQ_STRUCT; - -typedef struct _MLME_DEAUTH_REQ_STRUCT { - UCHAR Addr[MAC_ADDR_LEN]; - USHORT Reason; -} MLME_DEAUTH_REQ_STRUCT, *PMLME_DEAUTH_REQ_STRUCT; - -typedef struct { - ULONG BssIdx; -} MLME_JOIN_REQ_STRUCT; - -typedef struct _MLME_SCAN_REQ_STRUCT { - UCHAR Bssid[MAC_ADDR_LEN]; - UCHAR BssType; - UCHAR ScanType; - UCHAR SsidLen; - CHAR Ssid[MAX_LEN_OF_SSID]; -} MLME_SCAN_REQ_STRUCT, *PMLME_SCAN_REQ_STRUCT; - -typedef struct _MLME_START_REQ_STRUCT { - CHAR Ssid[MAX_LEN_OF_SSID]; - UCHAR SsidLen; -} MLME_START_REQ_STRUCT, *PMLME_START_REQ_STRUCT; - -typedef struct PACKED { - UCHAR Eid; - UCHAR Len; - CHAR Octet[1]; -} EID_STRUCT,*PEID_STRUCT, BEACON_EID_STRUCT, *PBEACON_EID_STRUCT; - -typedef struct PACKED _RTMP_TX_RATE_SWITCH -{ - UCHAR ItemNo; - UCHAR STBC:1; - UCHAR ShortGI:1; - UCHAR BW:1; - UCHAR Rsv1:1; - UCHAR Mode:2; - UCHAR Rsv2:2; - UCHAR CurrMCS; - UCHAR TrainUp; - UCHAR TrainDown; -} RRTMP_TX_RATE_SWITCH, *PRTMP_TX_RATE_SWITCH; - -// ========================== AP mlme.h =============================== -#define TBTT_PRELOAD_TIME 384 // usec. LomgPreamble + 24-byte at 1Mbps +/* */ +/* Contention-free parameter (without ID and Length) */ +/* */ +struct PACKED rt_cf_parm { + BOOLEAN bValid; /* 1: variable contains valid value */ + u8 CfpCount; + u8 CfpPeriod; + u16 CfpMaxDuration; + u16 CfpDurRemaining; +}; + +struct rt_cipher_suite { + NDIS_802_11_ENCRYPTION_STATUS PairCipher; /* Unicast cipher 1, this one has more secured cipher suite */ + NDIS_802_11_ENCRYPTION_STATUS PairCipherAux; /* Unicast cipher 2 if AP announce two unicast cipher suite */ + NDIS_802_11_ENCRYPTION_STATUS GroupCipher; /* Group cipher */ + u16 RsnCapability; /* RSN capability from beacon */ + BOOLEAN bMixMode; /* Indicate Pair & Group cipher might be different */ +}; + +/* EDCA configuration from AP's BEACON/ProbeRsp */ +struct rt_edca_parm { + BOOLEAN bValid; /* 1: variable contains valid value */ + BOOLEAN bAdd; /* 1: variable contains valid value */ + BOOLEAN bQAck; + BOOLEAN bQueueRequest; + BOOLEAN bTxopRequest; + BOOLEAN bAPSDCapable; +/* BOOLEAN bMoreDataAck; */ + u8 EdcaUpdateCount; + u8 Aifsn[4]; /* 0:AC_BK, 1:AC_BE, 2:AC_VI, 3:AC_VO */ + u8 Cwmin[4]; + u8 Cwmax[4]; + u16 Txop[4]; /* in unit of 32-us */ + BOOLEAN bACM[4]; /* 1: Admission Control of AC_BK is mandattory */ +}; + +/* QBSS LOAD information from QAP's BEACON/ProbeRsp */ +struct rt_qbss_load_parm { + BOOLEAN bValid; /* 1: variable contains valid value */ + u16 StaNum; + u8 ChannelUtilization; + u16 RemainingAdmissionControl; /* in unit of 32-us */ +}; + +/* QBSS Info field in QSTA's assoc req */ +struct PACKED rt_qbss_sta_info_parm { + u8 UAPSD_AC_VO:1; + u8 UAPSD_AC_VI:1; + u8 UAPSD_AC_BK:1; + u8 UAPSD_AC_BE:1; + u8 Rsv1:1; + u8 MaxSPLength:2; + u8 Rsv2:1; +}; + +/* QBSS Info field in QAP's Beacon/ProbeRsp */ +struct PACKED rt_qbss_ap_info_parm { + u8 ParamSetCount:4; + u8 Rsv:3; + u8 UAPSD:1; +}; + +/* QOS Capability reported in QAP's BEACON/ProbeRsp */ +/* QOS Capability sent out in QSTA's AssociateReq/ReAssociateReq */ +struct rt_qos_capability_parm { + BOOLEAN bValid; /* 1: variable contains valid value */ + BOOLEAN bQAck; + BOOLEAN bQueueRequest; + BOOLEAN bTxopRequest; +/* BOOLEAN bMoreDataAck; */ + u8 EdcaUpdateCount; +}; + +struct rt_wpa_ie { + u8 IELen; + u8 IE[MAX_CUSTOM_LEN]; +}; + +struct rt_bss_entry { + u8 Bssid[MAC_ADDR_LEN]; + u8 Channel; + u8 CentralChannel; /*Store the wide-band central channel for 40MHz. .used in 40MHz AP. Or this is the same as Channel. */ + u8 BssType; + u16 AtimWin; + u16 BeaconPeriod; + + u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + u8 SupRateLen; + u8 ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + u8 ExtRateLen; + struct rt_ht_capability_ie HtCapability; + u8 HtCapabilityLen; + struct rt_add_ht_info_ie AddHtInfo; /* AP might use this additional ht info IE */ + u8 AddHtInfoLen; + u8 NewExtChanOffset; + char Rssi; + u8 Privacy; /* Indicate security function ON/OFF. Don't mess up with auth mode. */ + u8 Hidden; + + u16 DtimPeriod; + u16 CapabilityInfo; + + u16 CfpCount; + u16 CfpPeriod; + u16 CfpMaxDuration; + u16 CfpDurRemaining; + u8 SsidLen; + char Ssid[MAX_LEN_OF_SSID]; + + unsigned long LastBeaconRxTime; /* OS's timestamp */ + + BOOLEAN bSES; + + /* New for WPA2 */ + struct rt_cipher_suite WPA; /* AP announced WPA cipher suite */ + struct rt_cipher_suite WPA2; /* AP announced WPA2 cipher suite */ + + /* New for microsoft WPA support */ + struct rt_ndis_802_11_fixed_ies FixIEs; + NDIS_802_11_AUTHENTICATION_MODE AuthModeAux; /* Addition mode for WPA2 / WPA capable AP */ + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; /* Unicast Encryption Algorithm extract from VAR_IE */ + u16 VarIELen; /* Length of next VIE include EID & Length */ + u8 VarIEs[MAX_VIE_LEN]; + + /* CCX Ckip information */ + u8 CkipFlag; + + /* CCX 2 TSF */ + u8 PTSF[4]; /* Parent TSF */ + u8 TTSF[8]; /* Target TSF */ + + /* 802.11e d9, and WMM */ + struct rt_edca_parm EdcaParm; + struct rt_qos_capability_parm QosCapability; + struct rt_qbss_load_parm QbssLoad; + struct rt_wpa_ie WpaIE; + struct rt_wpa_ie RsnIE; +}; + +struct rt_bss_table { + u8 BssNr; + u8 BssOverlapNr; + struct rt_bss_entry BssEntry[MAX_LEN_OF_BSS_TABLE]; +}; + +struct rt_mlme_queue_elem { + unsigned long Machine; + unsigned long MsgType; + unsigned long MsgLen; + u8 Msg[MGMT_DMA_BUFFER_SIZE]; + LARGE_INTEGER TimeStamp; + u8 Rssi0; + u8 Rssi1; + u8 Rssi2; + u8 Signal; + u8 Channel; + u8 Wcid; + BOOLEAN Occupied; +}; + +struct rt_mlme_queue { + unsigned long Num; + unsigned long Head; + unsigned long Tail; + spinlock_t Lock; + struct rt_mlme_queue_elem Entry[MAX_LEN_OF_MLME_QUEUE]; +}; + +typedef void(*STATE_MACHINE_FUNC) (void * Adaptor, struct rt_mlme_queue_elem *Elem); + +struct rt_state_machine { + unsigned long Base; + unsigned long NrState; + unsigned long NrMsg; + unsigned long CurrState; + STATE_MACHINE_FUNC *TransFunc; +}; + +/* MLME AUX data structure that hold temporarliy settings during a connection attempt. */ +/* Once this attemp succeeds, all settings will be copy to pAd->StaActive. */ +/* A connection attempt (user set OID, roaming, CCX fast roaming,..) consists of */ +/* several steps (JOIN, AUTH, ASSOC or REASSOC) and may fail at any step. We purposely */ +/* separate this under-trial settings away from pAd->StaActive so that once */ +/* this new attempt failed, driver can auto-recover back to the active settings. */ +struct rt_mlme_aux { + u8 BssType; + u8 Ssid[MAX_LEN_OF_SSID]; + u8 SsidLen; + u8 Bssid[MAC_ADDR_LEN]; + u8 AutoReconnectSsid[MAX_LEN_OF_SSID]; + u8 AutoReconnectSsidLen; + u16 Alg; + u8 ScanType; + u8 Channel; + u8 CentralChannel; + u16 Aid; + u16 CapabilityInfo; + u16 BeaconPeriod; + u16 CfpMaxDuration; + u16 CfpPeriod; + u16 AtimWin; + + /* Copy supported rate from desired AP's beacon. We are trying to match */ + /* AP's supported and extended rate settings. */ + u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + u8 ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + u8 SupRateLen; + u8 ExtRateLen; + struct rt_ht_capability_ie HtCapability; + u8 HtCapabilityLen; + struct rt_add_ht_info_ie AddHtInfo; /* AP might use this additional ht info IE */ + u8 NewExtChannelOffset; + /*struct rt_ht_capability SupportedHtPhy; */ + + /* new for QOS */ + struct rt_qos_capability_parm APQosCapability; /* QOS capability of the current associated AP */ + struct rt_edca_parm APEdcaParm; /* EDCA parameters of the current associated AP */ + struct rt_qbss_load_parm APQbssLoad; /* QBSS load of the current associated AP */ + + /* new to keep Ralink specific feature */ + unsigned long APRalinkIe; + + struct rt_bss_table SsidBssTab; /* AP list for the same SSID */ + struct rt_bss_table RoamTab; /* AP list eligible for roaming */ + unsigned long BssIdx; + unsigned long RoamIdx; + + BOOLEAN CurrReqIsFromNdis; + + struct rt_ralink_timer BeaconTimer, ScanTimer; + struct rt_ralink_timer AuthTimer; + struct rt_ralink_timer AssocTimer, ReassocTimer, DisassocTimer; +}; + +struct rt_mlme_addba_req { + u8 Wcid; /* */ + u8 pAddr[MAC_ADDR_LEN]; + u8 BaBufSize; + u16 TimeOutValue; + u8 TID; + u8 Token; + u16 BaStartSeq; +}; + +struct rt_mlme_delba_req { + u8 Wcid; /* */ + u8 Addr[MAC_ADDR_LEN]; + u8 TID; + u8 Initiator; +}; + +/* assoc struct is equal to reassoc */ +struct rt_mlme_assoc_req { + u8 Addr[MAC_ADDR_LEN]; + u16 CapabilityInfo; + u16 ListenIntv; + unsigned long Timeout; +}; + +struct rt_mlme_disassoc_req { + u8 Addr[MAC_ADDR_LEN]; + u16 Reason; +}; + +struct rt_mlme_auth_req { + u8 Addr[MAC_ADDR_LEN]; + u16 Alg; + unsigned long Timeout; +}; + +struct rt_mlme_deauth_req { + u8 Addr[MAC_ADDR_LEN]; + u16 Reason; +}; + +struct rt_mlme_join_req { + unsigned long BssIdx; +}; + +struct rt_mlme_scan_req { + u8 Bssid[MAC_ADDR_LEN]; + u8 BssType; + u8 ScanType; + u8 SsidLen; + char Ssid[MAX_LEN_OF_SSID]; +}; + +struct rt_mlme_start_req { + char Ssid[MAX_LEN_OF_SSID]; + u8 SsidLen; +}; + +struct PACKED rt_eid { + u8 Eid; + u8 Len; + u8 Octet[1]; +}; + +struct PACKED rt_rtmp_tx_rate_switch { + u8 ItemNo; + u8 STBC:1; + u8 ShortGI:1; + u8 BW:1; + u8 Rsv1:1; + u8 Mode:2; + u8 Rsv2:2; + u8 CurrMCS; + u8 TrainUp; + u8 TrainDown; +}; + +/* ========================== AP mlme.h =============================== */ +#define TBTT_PRELOAD_TIME 384 /* usec. LomgPreamble + 24-byte at 1Mbps */ #define DEFAULT_DTIM_PERIOD 1 -#define MAC_TABLE_AGEOUT_TIME 300 // unit: sec -#define MAC_TABLE_ASSOC_TIMEOUT 5 // unit: sec +#define MAC_TABLE_AGEOUT_TIME 300 /* unit: sec */ +#define MAC_TABLE_ASSOC_TIMEOUT 5 /* unit: sec */ #define MAC_TABLE_FULL(Tab) ((Tab).size == MAX_LEN_OF_MAC_TABLE) -// AP shall drop the sta if contine Tx fail count reach it. -#define MAC_ENTRY_LIFE_CHECK_CNT 20 // packet cnt. +/* AP shall drop the sta if contine Tx fail count reach it. */ +#define MAC_ENTRY_LIFE_CHECK_CNT 20 /* packet cnt. */ -// Value domain of pMacEntry->Sst +/* Value domain of pMacEntry->Sst */ typedef enum _Sst { - SST_NOT_AUTH, // 0: equivalent to IEEE 802.11/1999 state 1 - SST_AUTH, // 1: equivalent to IEEE 802.11/1999 state 2 - SST_ASSOC // 2: equivalent to IEEE 802.11/1999 state 3 + SST_NOT_AUTH, /* 0: equivalent to IEEE 802.11/1999 state 1 */ + SST_AUTH, /* 1: equivalent to IEEE 802.11/1999 state 2 */ + SST_ASSOC /* 2: equivalent to IEEE 802.11/1999 state 3 */ } SST; -// value domain of pMacEntry->AuthState +/* value domain of pMacEntry->AuthState */ typedef enum _AuthState { - AS_NOT_AUTH, - AS_AUTH_OPEN, // STA has been authenticated using OPEN SYSTEM - AS_AUTH_KEY, // STA has been authenticated using SHARED KEY - AS_AUTHENTICATING // STA is waiting for AUTH seq#3 using SHARED KEY + AS_NOT_AUTH, + AS_AUTH_OPEN, /* STA has been authenticated using OPEN SYSTEM */ + AS_AUTH_KEY, /* STA has been authenticated using SHARED KEY */ + AS_AUTHENTICATING /* STA is waiting for AUTH seq#3 using SHARED KEY */ } AUTH_STATE; -//for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 +/*for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 */ typedef enum _ApWpaState { - AS_NOTUSE, // 0 - AS_DISCONNECT, // 1 - AS_DISCONNECTED, // 2 - AS_INITIALIZE, // 3 - AS_AUTHENTICATION, // 4 - AS_AUTHENTICATION2, // 5 - AS_INITPMK, // 6 - AS_INITPSK, // 7 - AS_PTKSTART, // 8 - AS_PTKINIT_NEGOTIATING, // 9 - AS_PTKINITDONE, // 10 - AS_UPDATEKEYS, // 11 - AS_INTEGRITY_FAILURE, // 12 - AS_KEYUPDATE, // 13 + AS_NOTUSE, /* 0 */ + AS_DISCONNECT, /* 1 */ + AS_DISCONNECTED, /* 2 */ + AS_INITIALIZE, /* 3 */ + AS_AUTHENTICATION, /* 4 */ + AS_AUTHENTICATION2, /* 5 */ + AS_INITPMK, /* 6 */ + AS_INITPSK, /* 7 */ + AS_PTKSTART, /* 8 */ + AS_PTKINIT_NEGOTIATING, /* 9 */ + AS_PTKINITDONE, /* 10 */ + AS_UPDATEKEYS, /* 11 */ + AS_INTEGRITY_FAILURE, /* 12 */ + AS_KEYUPDATE, /* 13 */ } AP_WPA_STATE; -// for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 +/* for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 */ typedef enum _GTKState { - REKEY_NEGOTIATING, - REKEY_ESTABLISHED, - KEYERROR, + REKEY_NEGOTIATING, + REKEY_ESTABLISHED, + KEYERROR, } GTK_STATE; -// for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 +/* for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 */ typedef enum _WpaGTKState { - SETKEYS, - SETKEYS_DONE, + SETKEYS, + SETKEYS_DONE, } WPA_GTK_STATE; -// ====================== end of AP mlme.h ============================ - +/* ====================== end of AP mlme.h ============================ */ -#endif // MLME_H__ +#endif /* MLME_H__ */ diff --git a/drivers/staging/rt2860/oid.h b/drivers/staging/rt2860/oid.h index 0227c4a38f9f0c89d0121f05d7cf3e7211ec7f53..fd1c1419245160c510e1238e3f6ee57cc6958b0f 100644 --- a/drivers/staging/rt2860/oid.h +++ b/drivers/staging/rt2860/oid.h @@ -37,32 +37,37 @@ #ifndef _OID_H_ #define _OID_H_ +/*#include */ +#ifndef TRUE #define TRUE 1 +#endif +#ifndef FALSE #define FALSE 0 -// -// IEEE 802.11 Structures and definitions -// -#define MAX_TX_POWER_LEVEL 100 /* mW */ -#define MAX_RSSI_TRIGGER -10 /* dBm */ -#define MIN_RSSI_TRIGGER -200 /* dBm */ -#define MAX_FRAG_THRESHOLD 2346 /* byte count */ -#define MIN_FRAG_THRESHOLD 256 /* byte count */ -#define MAX_RTS_THRESHOLD 2347 /* byte count */ - -// new types for Media Specific Indications -// Extension channel offset +#endif +/* */ +/* IEEE 802.11 Structures and definitions */ +/* */ +#define MAX_TX_POWER_LEVEL 100 /* mW */ +#define MAX_RSSI_TRIGGER -10 /* dBm */ +#define MIN_RSSI_TRIGGER -200 /* dBm */ +#define MAX_FRAG_THRESHOLD 2346 /* byte count */ +#define MIN_FRAG_THRESHOLD 256 /* byte count */ +#define MAX_RTS_THRESHOLD 2347 /* byte count */ + +/* new types for Media Specific Indications */ +/* Extension channel offset */ #define EXTCHA_NONE 0 #define EXTCHA_ABOVE 0x1 #define EXTCHA_BELOW 0x3 -// BW +/* BW */ #define BAND_WIDTH_20 0 #define BAND_WIDTH_40 1 #define BAND_WIDTH_BOTH 2 -#define BAND_WIDTH_10 3 // 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. -// SHORTGI -#define GAP_INTERVAL_400 1 // only support in HT mode +#define BAND_WIDTH_10 3 /* 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. */ +/* SHORTGI */ +#define GAP_INTERVAL_400 1 /* only support in HT mode */ #define GAP_INTERVAL_800 0 #define GAP_INTERVAL_BOTH 2 @@ -73,24 +78,24 @@ #define NDIS_802_11_LENGTH_RATES 8 #define NDIS_802_11_LENGTH_RATES_EX 16 #define MAC_ADDR_LENGTH 6 -#define MAX_NUM_OF_CHS 49 // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL terminationc -#define MAX_NUMBER_OF_EVENT 10 // entry # in EVENT table -#define MAX_NUMBER_OF_MAC 32 // if MAX_MBSSID_NUM is 8, this value can't be larger than 211 +/*#define MAX_NUM_OF_CHS 49 // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL terminationc */ +#define MAX_NUM_OF_CHS 54 /* 14 channels @2.4G + 12@UNII(lower/middle) + 16@HiperLAN2 + 11@UNII(upper) + 0 @Japan + 1 as NULL termination */ +#define MAX_NUMBER_OF_EVENT 10 /* entry # in EVENT table */ +#define MAX_NUMBER_OF_MAC 32 /* if MAX_MBSSID_NUM is 8, this value can't be larger than 211 */ #define MAX_NUMBER_OF_ACL 64 -#define MAX_LENGTH_OF_SUPPORT_RATES 12 // 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 +#define MAX_LENGTH_OF_SUPPORT_RATES 12 /* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ #define MAX_NUMBER_OF_DLS_ENTRY 4 -#define OID_GEN_MACHINE_NAME 0x0001021A - #define RT_QUERY_SIGNAL_CONTEXT 0x0402 #define RT_SET_IAPP_PID 0x0404 #define RT_SET_APD_PID 0x0405 #define RT_SET_DEL_MAC_ENTRY 0x0406 - -// -// IEEE 802.11 OIDs -// +#define RT_QUERY_EVENT_TABLE 0x0407 +/* */ +/* IEEE 802.11 OIDs */ +/* */ #define OID_GET_SET_TOGGLE 0x8000 +#define OID_GET_SET_FROM_UI 0x4000 #define OID_802_11_ADD_WEP 0x0112 #define OID_802_11_DISASSOCIATE 0x0114 @@ -101,38 +106,42 @@ #define RT_OID_DEVICE_NAME 0x0607 #define RT_OID_VERSION_INFO 0x0608 +#define OID_802_11_BSSID_LIST 0x0609 +#define OID_802_3_CURRENT_ADDRESS 0x060A #define OID_GEN_MEDIA_CONNECT_STATUS 0x060B +#define RT_OID_802_11_QUERY_LINK_STATUS 0x060C +#define OID_802_11_RSSI 0x060D +#define OID_802_11_STATISTICS 0x060E #define OID_GEN_RCV_OK 0x060F #define OID_GEN_RCV_NO_BUFFER 0x0610 - +#define RT_OID_802_11_QUERY_EEPROM_VERSION 0x0611 +#define RT_OID_802_11_QUERY_FIRMWARE_VERSION 0x0612 +#define RT_OID_802_11_QUERY_LAST_RX_RATE 0x0613 +#define RT_OID_802_11_TX_POWER_LEVEL_1 0x0614 +#define RT_OID_802_11_QUERY_PIDVID 0x0615 +/*for WPA_SUPPLICANT_SUPPORT */ #define OID_SET_COUNTERMEASURES 0x0616 #define RT_OID_WPA_SUPPLICANT_SUPPORT 0x0621 #define RT_OID_WE_VERSION_COMPILED 0x0622 #define RT_OID_NEW_DRIVER 0x0623 -//rt2860 , kathy #define RT_OID_DRIVER_DEVICE_NAME 0x0645 #define RT_OID_QUERY_MULTIPLE_CARD_SUPPORT 0x0647 -// Ralink defined OIDs -// Dennis Lee move to platform specific - -typedef enum _NDIS_802_11_STATUS_TYPE -{ - Ndis802_11StatusType_Authentication, - Ndis802_11StatusType_MediaStreamMode, - Ndis802_11StatusType_PMKID_CandidateList, - Ndis802_11StatusTypeMax // not a real type, defined as an upper bound +typedef enum _NDIS_802_11_STATUS_TYPE { + Ndis802_11StatusType_Authentication, + Ndis802_11StatusType_MediaStreamMode, + Ndis802_11StatusType_PMKID_CandidateList, + Ndis802_11StatusTypeMax /* not a real type, defined as an upper bound */ } NDIS_802_11_STATUS_TYPE, *PNDIS_802_11_STATUS_TYPE; -typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; +typedef u8 NDIS_802_11_MAC_ADDRESS[6]; -typedef struct _NDIS_802_11_STATUS_INDICATION -{ - NDIS_802_11_STATUS_TYPE StatusType; -} NDIS_802_11_STATUS_INDICATION, *PNDIS_802_11_STATUS_INDICATION; +struct rt_ndis_802_11_status_indication { + NDIS_802_11_STATUS_TYPE StatusType; +}; -// mask for authentication/integrity fields +/* mask for authentication/integrity fields */ #define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f #define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 @@ -140,304 +149,283 @@ typedef struct _NDIS_802_11_STATUS_INDICATION #define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 #define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E -typedef struct _NDIS_802_11_AUTHENTICATION_REQUEST -{ - ULONG Length; // Length of structure - NDIS_802_11_MAC_ADDRESS Bssid; - ULONG Flags; -} NDIS_802_11_AUTHENTICATION_REQUEST, *PNDIS_802_11_AUTHENTICATION_REQUEST; - -//Added new types for PMKID Candidate lists. -typedef struct _PMKID_CANDIDATE { - NDIS_802_11_MAC_ADDRESS BSSID; - ULONG Flags; -} PMKID_CANDIDATE, *PPMKID_CANDIDATE; - -typedef struct _NDIS_802_11_PMKID_CANDIDATE_LIST -{ - ULONG Version; // Version of the structure - ULONG NumCandidates; // No. of pmkid candidates - PMKID_CANDIDATE CandidateList[1]; -} NDIS_802_11_PMKID_CANDIDATE_LIST, *PNDIS_802_11_PMKID_CANDIDATE_LIST; - -//Flags for PMKID Candidate list structure +struct rt_ndis_802_11_authentication_request { + unsigned long Length; /* Length of structure */ + NDIS_802_11_MAC_ADDRESS Bssid; + unsigned long Flags; +}; + +/*Added new types for PMKID Candidate lists. */ +struct rt_pmkid_candidate { + NDIS_802_11_MAC_ADDRESS BSSID; + unsigned long Flags; +}; + +struct rt_ndis_802_11_pmkid_candidate_list { + unsigned long Version; /* Version of the structure */ + unsigned long NumCandidates; /* No. of pmkid candidates */ + struct rt_pmkid_candidate CandidateList[1]; +}; + +/*Flags for PMKID Candidate list structure */ #define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 -// Added new types for OFDM 5G and 2.4G -typedef enum _NDIS_802_11_NETWORK_TYPE -{ - Ndis802_11FH, - Ndis802_11DS, - Ndis802_11OFDM5, - Ndis802_11OFDM5_N, - Ndis802_11OFDM24, - Ndis802_11OFDM24_N, - Ndis802_11Automode, - Ndis802_11NetworkTypeMax // not a real type, defined as an upper bound +/* Added new types for OFDM 5G and 2.4G */ +typedef enum _NDIS_802_11_NETWORK_TYPE { + Ndis802_11FH, + Ndis802_11DS, + Ndis802_11OFDM5, + Ndis802_11OFDM24, + Ndis802_11Automode, + Ndis802_11OFDM5_N, + Ndis802_11OFDM24_N, + Ndis802_11NetworkTypeMax /* not a real type, defined as an upper bound */ } NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE; -typedef struct _NDIS_802_11_NETWORK_TYPE_LIST -{ - UINT NumberOfItems; // in list below, at least 1 - NDIS_802_11_NETWORK_TYPE NetworkType [1]; -} NDIS_802_11_NETWORK_TYPE_LIST, *PNDIS_802_11_NETWORK_TYPE_LIST; - -typedef enum _NDIS_802_11_POWER_MODE -{ - Ndis802_11PowerModeCAM, - Ndis802_11PowerModeMAX_PSP, - Ndis802_11PowerModeFast_PSP, - Ndis802_11PowerModeLegacy_PSP, - Ndis802_11PowerModeMax // not a real mode, defined as an upper bound +struct rt_ndis_802_11_network_type_list { + u32 NumberOfItems; /* in list below, at least 1 */ + NDIS_802_11_NETWORK_TYPE NetworkType[1]; +}; + +typedef enum _NDIS_802_11_POWER_MODE { + Ndis802_11PowerModeCAM, + Ndis802_11PowerModeMAX_PSP, + Ndis802_11PowerModeFast_PSP, + Ndis802_11PowerModeLegacy_PSP, + Ndis802_11PowerModeMax /* not a real mode, defined as an upper bound */ } NDIS_802_11_POWER_MODE, *PNDIS_802_11_POWER_MODE; -typedef ULONG NDIS_802_11_TX_POWER_LEVEL; // in milliwatts - -// -// Received Signal Strength Indication -// -typedef LONG NDIS_802_11_RSSI; // in dBm - -typedef struct _NDIS_802_11_CONFIGURATION_FH -{ - ULONG Length; // Length of structure - ULONG HopPattern; // As defined by 802.11, MSB set - ULONG HopSet; // to one if non-802.11 - ULONG DwellTime; // units are Kusec -} NDIS_802_11_CONFIGURATION_FH, *PNDIS_802_11_CONFIGURATION_FH; - -typedef struct _NDIS_802_11_CONFIGURATION -{ - ULONG Length; // Length of structure - ULONG BeaconPeriod; // units are Kusec - ULONG ATIMWindow; // units are Kusec - ULONG DSConfig; // Frequency, units are kHz - NDIS_802_11_CONFIGURATION_FH FHConfig; -} NDIS_802_11_CONFIGURATION, *PNDIS_802_11_CONFIGURATION; - -typedef struct _NDIS_802_11_STATISTICS -{ - ULONG Length; // Length of structure - LARGE_INTEGER TransmittedFragmentCount; - LARGE_INTEGER MulticastTransmittedFrameCount; - LARGE_INTEGER FailedCount; - LARGE_INTEGER RetryCount; - LARGE_INTEGER MultipleRetryCount; - LARGE_INTEGER RTSSuccessCount; - LARGE_INTEGER RTSFailureCount; - LARGE_INTEGER ACKFailureCount; - LARGE_INTEGER FrameDuplicateCount; - LARGE_INTEGER ReceivedFragmentCount; - LARGE_INTEGER MulticastReceivedFrameCount; - LARGE_INTEGER FCSErrorCount; - LARGE_INTEGER TKIPLocalMICFailures; - LARGE_INTEGER TKIPRemoteMICErrors; - LARGE_INTEGER TKIPICVErrors; - LARGE_INTEGER TKIPCounterMeasuresInvoked; - LARGE_INTEGER TKIPReplays; - LARGE_INTEGER CCMPFormatErrors; - LARGE_INTEGER CCMPReplays; - LARGE_INTEGER CCMPDecryptErrors; - LARGE_INTEGER FourWayHandshakeFailures; -} NDIS_802_11_STATISTICS, *PNDIS_802_11_STATISTICS; - -typedef ULONG NDIS_802_11_KEY_INDEX; -typedef ULONGLONG NDIS_802_11_KEY_RSC; - -#define MAX_RADIUS_SRV_NUM 2 // 802.1x failover number - -typedef struct PACKED _RADIUS_SRV_INFO { - UINT32 radius_ip; - UINT32 radius_port; - UCHAR radius_key[64]; - UCHAR radius_key_len; -} RADIUS_SRV_INFO, *PRADIUS_SRV_INFO; - -typedef struct PACKED _RADIUS_KEY_INFO -{ - UCHAR radius_srv_num; - RADIUS_SRV_INFO radius_srv_info[MAX_RADIUS_SRV_NUM]; - UCHAR ieee8021xWEP; // dynamic WEP - UCHAR key_index; - UCHAR key_length; // length of key in bytes - UCHAR key_material[13]; -} RADIUS_KEY_INFO, *PRADIUS_KEY_INFO; - -// It's used by 802.1x daemon to require relative configuration -typedef struct PACKED _RADIUS_CONF -{ - UINT32 Length; // Length of this structure - UCHAR mbss_num; // indicate multiple BSS number - UINT32 own_ip_addr; - UINT32 retry_interval; - UINT32 session_timeout_interval; - UCHAR EAPifname[IFNAMSIZ]; - UCHAR EAPifname_len; - UCHAR PreAuthifname[IFNAMSIZ]; - UCHAR PreAuthifname_len; - RADIUS_KEY_INFO RadiusInfo[8/*MAX_MBSSID_NUM*/]; -} RADIUS_CONF, *PRADIUS_CONF; - -// Key mapping keys require a BSSID -typedef struct _NDIS_802_11_KEY -{ - UINT Length; // Length of this structure - UINT KeyIndex; - UINT KeyLength; // length of key in bytes - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_KEY_RSC KeyRSC; - UCHAR KeyMaterial[1]; // variable length depending on above field -} NDIS_802_11_KEY, *PNDIS_802_11_KEY; - -typedef struct _NDIS_802_11_REMOVE_KEY -{ - UINT Length; // Length of this structure - UINT KeyIndex; - NDIS_802_11_MAC_ADDRESS BSSID; -} NDIS_802_11_REMOVE_KEY, *PNDIS_802_11_REMOVE_KEY; - -typedef struct _NDIS_802_11_WEP -{ - UINT Length; // Length of this structure - UINT KeyIndex; // 0 is the per-client key, 1-N are the - // global keys - UINT KeyLength; // length of key in bytes - UCHAR KeyMaterial[1];// variable length depending on above field -} NDIS_802_11_WEP, *PNDIS_802_11_WEP; - - -typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE -{ - Ndis802_11IBSS, - Ndis802_11Infrastructure, - Ndis802_11AutoUnknown, - Ndis802_11Monitor, - Ndis802_11InfrastructureMax // Not a real value, defined as upper bound +typedef unsigned long NDIS_802_11_TX_POWER_LEVEL; /* in milliwatts */ + +/* */ +/* Received Signal Strength Indication */ +/* */ +typedef long NDIS_802_11_RSSI; /* in dBm */ + +struct rt_ndis_802_11_configuration_fh { + unsigned long Length; /* Length of structure */ + unsigned long HopPattern; /* As defined by 802.11, MSB set */ + unsigned long HopSet; /* to one if non-802.11 */ + unsigned long DwellTime; /* units are Kusec */ +}; + +struct rt_ndis_802_11_configuration { + unsigned long Length; /* Length of structure */ + unsigned long BeaconPeriod; /* units are Kusec */ + unsigned long ATIMWindow; /* units are Kusec */ + unsigned long DSConfig; /* Frequency, units are kHz */ + struct rt_ndis_802_11_configuration_fh FHConfig; +}; + +struct rt_ndis_802_11_statistics { + unsigned long Length; /* Length of structure */ + LARGE_INTEGER TransmittedFragmentCount; + LARGE_INTEGER MulticastTransmittedFrameCount; + LARGE_INTEGER FailedCount; + LARGE_INTEGER RetryCount; + LARGE_INTEGER MultipleRetryCount; + LARGE_INTEGER RTSSuccessCount; + LARGE_INTEGER RTSFailureCount; + LARGE_INTEGER ACKFailureCount; + LARGE_INTEGER FrameDuplicateCount; + LARGE_INTEGER ReceivedFragmentCount; + LARGE_INTEGER MulticastReceivedFrameCount; + LARGE_INTEGER FCSErrorCount; + LARGE_INTEGER TKIPLocalMICFailures; + LARGE_INTEGER TKIPRemoteMICErrors; + LARGE_INTEGER TKIPICVErrors; + LARGE_INTEGER TKIPCounterMeasuresInvoked; + LARGE_INTEGER TKIPReplays; + LARGE_INTEGER CCMPFormatErrors; + LARGE_INTEGER CCMPReplays; + LARGE_INTEGER CCMPDecryptErrors; + LARGE_INTEGER FourWayHandshakeFailures; +}; + +typedef unsigned long NDIS_802_11_KEY_INDEX; +typedef unsigned long long NDIS_802_11_KEY_RSC; + +#define MAX_RADIUS_SRV_NUM 2 /* 802.1x failover number */ + +struct PACKED rt_radius_srv_info { + u32 radius_ip; + u32 radius_port; + u8 radius_key[64]; + u8 radius_key_len; +}; + +struct PACKED rt_radius_key_info { + u8 radius_srv_num; + struct rt_radius_srv_info radius_srv_info[MAX_RADIUS_SRV_NUM]; + u8 ieee8021xWEP; /* dynamic WEP */ + u8 key_index; + u8 key_length; /* length of key in bytes */ + u8 key_material[13]; +}; + +/* It's used by 802.1x daemon to require relative configuration */ +struct PACKED rt_radius_conf { + u32 Length; /* Length of this structure */ + u8 mbss_num; /* indicate multiple BSS number */ + u32 own_ip_addr; + u32 retry_interval; + u32 session_timeout_interval; + u8 EAPifname[8][IFNAMSIZ]; + u8 EAPifname_len[8]; + u8 PreAuthifname[8][IFNAMSIZ]; + u8 PreAuthifname_len[8]; + struct rt_radius_key_info RadiusInfo[8]; +}; + +/* Key mapping keys require a BSSID */ +struct rt_ndis_802_11_key { + u32 Length; /* Length of this structure */ + u32 KeyIndex; + u32 KeyLength; /* length of key in bytes */ + NDIS_802_11_MAC_ADDRESS BSSID; + NDIS_802_11_KEY_RSC KeyRSC; + u8 KeyMaterial[1]; /* variable length depending on above field */ +}; + +struct rt_ndis_802_11_passphrase { + u32 KeyLength; /* length of key in bytes */ + NDIS_802_11_MAC_ADDRESS BSSID; + u8 KeyMaterial[1]; /* variable length depending on above field */ +}; + +struct rt_ndis_802_11_remove_key { + u32 Length; /* Length of this structure */ + u32 KeyIndex; + NDIS_802_11_MAC_ADDRESS BSSID; +}; + +struct rt_ndis_802_11_wep { + u32 Length; /* Length of this structure */ + u32 KeyIndex; /* 0 is the per-client key, 1-N are the */ + /* global keys */ + u32 KeyLength; /* length of key in bytes */ + u8 KeyMaterial[1]; /* variable length depending on above field */ +}; + +typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE { + Ndis802_11IBSS, + Ndis802_11Infrastructure, + Ndis802_11AutoUnknown, + Ndis802_11Monitor, + Ndis802_11InfrastructureMax /* Not a real value, defined as upper bound */ } NDIS_802_11_NETWORK_INFRASTRUCTURE, *PNDIS_802_11_NETWORK_INFRASTRUCTURE; -// Add new authentication modes -typedef enum _NDIS_802_11_AUTHENTICATION_MODE -{ - Ndis802_11AuthModeOpen, - Ndis802_11AuthModeShared, - Ndis802_11AuthModeAutoSwitch, - Ndis802_11AuthModeWPA, - Ndis802_11AuthModeWPAPSK, - Ndis802_11AuthModeWPANone, - Ndis802_11AuthModeWPA2, - Ndis802_11AuthModeWPA2PSK, - Ndis802_11AuthModeWPA1WPA2, +/* Add new authentication modes */ +typedef enum _NDIS_802_11_AUTHENTICATION_MODE { + Ndis802_11AuthModeOpen, + Ndis802_11AuthModeShared, + Ndis802_11AuthModeAutoSwitch, + Ndis802_11AuthModeWPA, + Ndis802_11AuthModeWPAPSK, + Ndis802_11AuthModeWPANone, + Ndis802_11AuthModeWPA2, + Ndis802_11AuthModeWPA2PSK, + Ndis802_11AuthModeWPA1WPA2, Ndis802_11AuthModeWPA1PSKWPA2PSK, - Ndis802_11AuthModeMax // Not a real mode, defined as upper bound + Ndis802_11AuthModeMax /* Not a real mode, defined as upper bound */ } NDIS_802_11_AUTHENTICATION_MODE, *PNDIS_802_11_AUTHENTICATION_MODE; -typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; // Set of 8 data rates -typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; // Set of 16 data rates - -typedef struct PACKED _NDIS_802_11_SSID -{ - UINT SsidLength; // length of SSID field below, in bytes; - // this can be zero. - UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; // SSID information field -} NDIS_802_11_SSID, *PNDIS_802_11_SSID; - - -typedef struct PACKED _NDIS_WLAN_BSSID -{ - ULONG Length; // Length of this structure - NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID - UCHAR Reserved[2]; - NDIS_802_11_SSID Ssid; // SSID - ULONG Privacy; // WEP encryption requirement - NDIS_802_11_RSSI Rssi; // receive signal strength in dBm - NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; - NDIS_802_11_CONFIGURATION Configuration; - NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; - NDIS_802_11_RATES SupportedRates; -} NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID; - -typedef struct PACKED _NDIS_802_11_BSSID_LIST -{ - UINT NumberOfItems; // in list below, at least 1 - NDIS_WLAN_BSSID Bssid[1]; -} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST; - -// Added Capabilities, IELength and IEs for each BSSID -typedef struct PACKED _NDIS_WLAN_BSSID_EX -{ - ULONG Length; // Length of this structure - NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID - UCHAR Reserved[2]; - NDIS_802_11_SSID Ssid; // SSID - UINT Privacy; // WEP encryption requirement - NDIS_802_11_RSSI Rssi; // receive signal - // strength in dBm - NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; - NDIS_802_11_CONFIGURATION Configuration; - NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; - NDIS_802_11_RATES_EX SupportedRates; - ULONG IELength; - UCHAR IEs[1]; -} NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX; - -typedef struct PACKED _NDIS_802_11_BSSID_LIST_EX -{ - UINT NumberOfItems; // in list below, at least 1 - NDIS_WLAN_BSSID_EX Bssid[1]; -} NDIS_802_11_BSSID_LIST_EX, *PNDIS_802_11_BSSID_LIST_EX; - -typedef struct PACKED _NDIS_802_11_FIXED_IEs -{ - UCHAR Timestamp[8]; - USHORT BeaconInterval; - USHORT Capabilities; -} NDIS_802_11_FIXED_IEs, *PNDIS_802_11_FIXED_IEs; - -typedef struct _NDIS_802_11_VARIABLE_IEs -{ - UCHAR ElementID; - UCHAR Length; // Number of bytes in data field - UCHAR data[1]; -} NDIS_802_11_VARIABLE_IEs, *PNDIS_802_11_VARIABLE_IEs; - -typedef ULONG NDIS_802_11_FRAGMENTATION_THRESHOLD; - -typedef ULONG NDIS_802_11_RTS_THRESHOLD; - -typedef ULONG NDIS_802_11_ANTENNA; - -typedef enum _NDIS_802_11_PRIVACY_FILTER -{ - Ndis802_11PrivFilterAcceptAll, - Ndis802_11PrivFilter8021xWEP +typedef u8 NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; /* Set of 8 data rates */ +typedef u8 NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; /* Set of 16 data rates */ + +struct PACKED rt_ndis_802_11_ssid { + u32 SsidLength; /* length of SSID field below, in bytes; */ + /* this can be zero. */ + u8 Ssid[NDIS_802_11_LENGTH_SSID]; /* SSID information field */ +}; + +struct PACKED rt_ndis_wlan_bssid { + unsigned long Length; /* Length of this structure */ + NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */ + u8 Reserved[2]; + struct rt_ndis_802_11_ssid Ssid; /* SSID */ + unsigned long Privacy; /* WEP encryption requirement */ + NDIS_802_11_RSSI Rssi; /* receive signal strength in dBm */ + NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + struct rt_ndis_802_11_configuration Configuration; + NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; + NDIS_802_11_RATES SupportedRates; +}; + +struct PACKED rt_ndis_802_11_bssid_list { + u32 NumberOfItems; /* in list below, at least 1 */ + struct rt_ndis_wlan_bssid Bssid[1]; +}; + +/* Added Capabilities, IELength and IEs for each BSSID */ +struct PACKED rt_ndis_wlan_bssid_ex { + unsigned long Length; /* Length of this structure */ + NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */ + u8 Reserved[2]; + struct rt_ndis_802_11_ssid Ssid; /* SSID */ + u32 Privacy; /* WEP encryption requirement */ + NDIS_802_11_RSSI Rssi; /* receive signal */ + /* strength in dBm */ + NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + struct rt_ndis_802_11_configuration Configuration; + NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; + NDIS_802_11_RATES_EX SupportedRates; + unsigned long IELength; + u8 IEs[1]; +}; + +struct PACKED rt_ndis_802_11_bssid_list_ex { + u32 NumberOfItems; /* in list below, at least 1 */ + struct rt_ndis_wlan_bssid_ex Bssid[1]; +}; + +struct PACKED rt_ndis_802_11_fixed_ies { + u8 Timestamp[8]; + u16 BeaconInterval; + u16 Capabilities; +}; + +struct rt_ndis_802_11_variable_ies { + u8 ElementID; + u8 Length; /* Number of bytes in data field */ + u8 data[1]; +}; + +typedef unsigned long NDIS_802_11_FRAGMENTATION_THRESHOLD; + +typedef unsigned long NDIS_802_11_RTS_THRESHOLD; + +typedef unsigned long NDIS_802_11_ANTENNA; + +typedef enum _NDIS_802_11_PRIVACY_FILTER { + Ndis802_11PrivFilterAcceptAll, + Ndis802_11PrivFilter8021xWEP } NDIS_802_11_PRIVACY_FILTER, *PNDIS_802_11_PRIVACY_FILTER; -// Added new encryption types -// Also aliased typedef to new name -typedef enum _NDIS_802_11_WEP_STATUS -{ - Ndis802_11WEPEnabled, - Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, - Ndis802_11WEPDisabled, - Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, - Ndis802_11WEPKeyAbsent, - Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, - Ndis802_11WEPNotSupported, - Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, - Ndis802_11Encryption2Enabled, - Ndis802_11Encryption2KeyAbsent, - Ndis802_11Encryption3Enabled, - Ndis802_11Encryption3KeyAbsent, - Ndis802_11Encryption4Enabled, // TKIP or AES mix - Ndis802_11Encryption4KeyAbsent, - Ndis802_11GroupWEP40Enabled, +/* Added new encryption types */ +/* Also aliased typedef to new name */ +typedef enum _NDIS_802_11_WEP_STATUS { + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11Encryption2Enabled, + Ndis802_11Encryption2KeyAbsent, + Ndis802_11Encryption3Enabled, + Ndis802_11Encryption3KeyAbsent, + Ndis802_11Encryption4Enabled, /* TKIP or AES mix */ + Ndis802_11Encryption4KeyAbsent, + Ndis802_11GroupWEP40Enabled, Ndis802_11GroupWEP104Enabled, } NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS, - NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS; + NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS; -typedef enum _NDIS_802_11_RELOAD_DEFAULTS -{ - Ndis802_11ReloadWEPKeys +typedef enum _NDIS_802_11_RELOAD_DEFAULTS { + Ndis802_11ReloadWEPKeys } NDIS_802_11_RELOAD_DEFAULTS, *PNDIS_802_11_RELOAD_DEFAULTS; #define NDIS_802_11_AI_REQFI_CAPABILITIES 1 @@ -448,351 +436,343 @@ typedef enum _NDIS_802_11_RELOAD_DEFAULTS #define NDIS_802_11_AI_RESFI_STATUSCODE 2 #define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4 -typedef struct _NDIS_802_11_AI_REQFI -{ - USHORT Capabilities; - USHORT ListenInterval; - NDIS_802_11_MAC_ADDRESS CurrentAPAddress; -} NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI; - -typedef struct _NDIS_802_11_AI_RESFI -{ - USHORT Capabilities; - USHORT StatusCode; - USHORT AssociationId; -} NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI; - -typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION -{ - ULONG Length; - USHORT AvailableRequestFixedIEs; - NDIS_802_11_AI_REQFI RequestFixedIEs; - ULONG RequestIELength; - ULONG OffsetRequestIEs; - USHORT AvailableResponseFixedIEs; - NDIS_802_11_AI_RESFI ResponseFixedIEs; - ULONG ResponseIELength; - ULONG OffsetResponseIEs; -} NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION; - -typedef struct _NDIS_802_11_AUTHENTICATION_EVENT -{ - NDIS_802_11_STATUS_INDICATION Status; - NDIS_802_11_AUTHENTICATION_REQUEST Request[1]; -} NDIS_802_11_AUTHENTICATION_EVENT, *PNDIS_802_11_AUTHENTICATION_EVENT; - -// 802.11 Media stream constraints, associated with OID_802_11_MEDIA_STREAM_MODE -typedef enum _NDIS_802_11_MEDIA_STREAM_MODE -{ - Ndis802_11MediaStreamOff, - Ndis802_11MediaStreamOn, +struct rt_ndis_802_11_ai_reqfi { + u16 Capabilities; + u16 ListenInterval; + NDIS_802_11_MAC_ADDRESS CurrentAPAddress; +}; + +struct rt_ndis_802_11_ai_resfi { + u16 Capabilities; + u16 StatusCode; + u16 AssociationId; +}; + +struct rt_ndis_802_11_association_information { + unsigned long Length; + u16 AvailableRequestFixedIEs; + struct rt_ndis_802_11_ai_reqfi RequestFixedIEs; + unsigned long RequestIELength; + unsigned long OffsetRequestIEs; + u16 AvailableResponseFixedIEs; + struct rt_ndis_802_11_ai_resfi ResponseFixedIEs; + unsigned long ResponseIELength; + unsigned long OffsetResponseIEs; +}; + +struct rt_ndis_802_11_authentication_event { + struct rt_ndis_802_11_status_indication Status; + struct rt_ndis_802_11_authentication_request Request[1]; +}; + +/* 802.11 Media stream constraints, associated with OID_802_11_MEDIA_STREAM_MODE */ +typedef enum _NDIS_802_11_MEDIA_STREAM_MODE { + Ndis802_11MediaStreamOff, + Ndis802_11MediaStreamOn, } NDIS_802_11_MEDIA_STREAM_MODE, *PNDIS_802_11_MEDIA_STREAM_MODE; -// PMKID Structures -typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; - -typedef struct _BSSID_INFO -{ - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_PMKID_VALUE PMKID; -} BSSID_INFO, *PBSSID_INFO; - -typedef struct _NDIS_802_11_PMKID -{ - UINT Length; - UINT BSSIDInfoCount; - BSSID_INFO BSSIDInfo[1]; -} NDIS_802_11_PMKID, *PNDIS_802_11_PMKID; - -typedef struct _NDIS_802_11_AUTHENTICATION_ENCRYPTION -{ - NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; - NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; -} NDIS_802_11_AUTHENTICATION_ENCRYPTION, *PNDIS_802_11_AUTHENTICATION_ENCRYPTION; - -typedef struct _NDIS_802_11_CAPABILITY -{ - ULONG Length; - ULONG Version; - ULONG NoOfPMKIDs; - ULONG NoOfAuthEncryptPairsSupported; - NDIS_802_11_AUTHENTICATION_ENCRYPTION AuthenticationEncryptionSupported[1]; -} NDIS_802_11_CAPABILITY, *PNDIS_802_11_CAPABILITY; - -#define RT_PRIV_IOCTL_EXT (SIOCIWFIRSTPRIV + 0x01) // Sync. with AP for wsc upnp daemon +/* PMKID Structures */ +typedef u8 NDIS_802_11_PMKID_VALUE[16]; + +struct rt_bssid_info { + NDIS_802_11_MAC_ADDRESS BSSID; + NDIS_802_11_PMKID_VALUE PMKID; +}; + +struct rt_ndis_802_11_pmkid { + u32 Length; + u32 BSSIDInfoCount; + struct rt_bssid_info BSSIDInfo[1]; +}; + +struct rt_ndis_802_11_authentication_encryption { + NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; + NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; +}; + +struct rt_ndis_802_11_capability { + unsigned long Length; + unsigned long Version; + unsigned long NoOfPMKIDs; + unsigned long NoOfAuthEncryptPairsSupported; + struct rt_ndis_802_11_authentication_encryption + AuthenticationEncryptionSupported[1]; +}; + +#define RT_PRIV_IOCTL (SIOCIWFIRSTPRIV + 0x01) /* Sync. with AP for wsc upnp daemon */ #define RTPRIV_IOCTL_SET (SIOCIWFIRSTPRIV + 0x02) #define RTPRIV_IOCTL_STATISTICS (SIOCIWFIRSTPRIV + 0x09) #define RTPRIV_IOCTL_ADD_PMKID_CACHE (SIOCIWFIRSTPRIV + 0x0A) #define RTPRIV_IOCTL_RADIUS_DATA (SIOCIWFIRSTPRIV + 0x0C) #define RTPRIV_IOCTL_GSITESURVEY (SIOCIWFIRSTPRIV + 0x0D) -#define RT_PRIV_IOCTL (SIOCIWFIRSTPRIV + 0x0E) // Sync. with RT61 (for wpa_supplicant) +#define RT_PRIV_IOCTL_EXT (SIOCIWFIRSTPRIV + 0x0E) /* Sync. with RT61 (for wpa_supplicant) */ #define RTPRIV_IOCTL_GET_MAC_TABLE (SIOCIWFIRSTPRIV + 0x0F) #define RTPRIV_IOCTL_SHOW (SIOCIWFIRSTPRIV + 0x11) enum { - SHOW_CONN_STATUS = 4, - SHOW_DRVIER_VERION = 5, - SHOW_BA_INFO = 6, + SHOW_CONN_STATUS = 4, + SHOW_DRVIER_VERION = 5, + SHOW_BA_INFO = 6, SHOW_DESC_INFO = 7, -#ifdef RT2870 +#ifdef RTMP_MAC_USB SHOW_RXBULK_INFO = 8, SHOW_TXBULK_INFO = 9, -#endif // RT2870 // - RAIO_OFF = 10, - RAIO_ON = 11, +#endif /* RTMP_MAC_USB // */ + RAIO_OFF = 10, + RAIO_ON = 11, SHOW_CFG_VALUE = 20, -#if !defined(RT2860) SHOW_ADHOC_ENTRY_INFO = 21, -#endif }; -#ifdef LLTD_SUPPORT -// for consistency with RT61 -#define RT_OID_GET_PHY_MODE 0x761 -#endif // LLTD_SUPPORT // - -#if defined(RT2860) || defined(RT30xx) -// New for MeetingHouse Api support +#define OID_802_11_BUILD_CHANNEL_EX 0x0714 +#define OID_802_11_GET_CH_LIST 0x0715 +#define OID_802_11_GET_COUNTRY_CODE 0x0716 +#define OID_802_11_GET_CHANNEL_GEOGRAPHY 0x0717 + +#define RT_OID_WSC_SET_PASSPHRASE 0x0740 /* passphrase for wpa(2)-psk */ +#define RT_OID_WSC_DRIVER_AUTO_CONNECT 0x0741 +#define RT_OID_WSC_QUERY_DEFAULT_PROFILE 0x0742 +#define RT_OID_WSC_SET_CONN_BY_PROFILE_INDEX 0x0743 +#define RT_OID_WSC_SET_ACTION 0x0744 +#define RT_OID_WSC_SET_SSID 0x0745 +#define RT_OID_WSC_SET_PIN_CODE 0x0746 +#define RT_OID_WSC_SET_MODE 0x0747 /* PIN or PBC */ +#define RT_OID_WSC_SET_CONF_MODE 0x0748 /* Enrollee or Registrar */ +#define RT_OID_WSC_SET_PROFILE 0x0749 +#define RT_OID_WSC_CONFIG_STATUS 0x074F +#define RT_OID_802_11_WSC_QUERY_PROFILE 0x0750 +/* for consistency with RT61 */ +#define RT_OID_WSC_QUERY_STATUS 0x0751 +#define RT_OID_WSC_PIN_CODE 0x0752 +#define RT_OID_WSC_UUID 0x0753 +#define RT_OID_WSC_SET_SELECTED_REGISTRAR 0x0754 +#define RT_OID_WSC_EAPMSG 0x0755 +#define RT_OID_WSC_MANUFACTURER 0x0756 +#define RT_OID_WSC_MODEL_NAME 0x0757 +#define RT_OID_WSC_MODEL_NO 0x0758 +#define RT_OID_WSC_SERIAL_NO 0x0759 +#define RT_OID_WSC_MAC_ADDRESS 0x0760 + +/* New for MeetingHouse Api support */ #define OID_MH_802_1X_SUPPORTED 0xFFEDC100 -#endif -// MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition!!! -typedef union _HTTRANSMIT_SETTING { - struct { - USHORT MCS:7; // MCS - USHORT BW:1; //channel bandwidth 20MHz or 40 MHz - USHORT ShortGI:1; - USHORT STBC:2; //SPACE - USHORT rsv:2; - USHORT TxBF:1; - USHORT MODE:2; // Use definition MODE_xxx. - } field; - USHORT word; - } HTTRANSMIT_SETTING, *PHTTRANSMIT_SETTING; +/* MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition! */ +typedef union _HTTRANSMIT_SETTING { + struct { + u16 MCS:7; /* MCS */ + u16 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + u16 ShortGI:1; + u16 STBC:2; /*SPACE */ +/* u16 rsv:3; */ + u16 rsv:2; + u16 TxBF:1; + u16 MODE:2; /* Use definition MODE_xxx. */ + } field; + u16 word; +} HTTRANSMIT_SETTING, *PHTTRANSMIT_SETTING; typedef enum _RT_802_11_PREAMBLE { - Rt802_11PreambleLong, - Rt802_11PreambleShort, - Rt802_11PreambleAuto + Rt802_11PreambleLong, + Rt802_11PreambleShort, + Rt802_11PreambleAuto } RT_802_11_PREAMBLE, *PRT_802_11_PREAMBLE; -// Only for STA, need to sync with AP typedef enum _RT_802_11_PHY_MODE { PHY_11BG_MIXED = 0, PHY_11B, PHY_11A, PHY_11ABG_MIXED, PHY_11G, - PHY_11ABGN_MIXED, // both band 5 - PHY_11N_2_4G, // 11n-only with 2.4G band 6 - PHY_11GN_MIXED, // 2.4G band 7 - PHY_11AN_MIXED, // 5G band 8 - PHY_11BGN_MIXED, // if check 802.11b. 9 - PHY_11AGN_MIXED, // if check 802.11b. 10 - PHY_11N_5G, // 11n-only with 5G band 11 + PHY_11ABGN_MIXED, /* both band 5 */ + PHY_11N_2_4G, /* 11n-only with 2.4G band 6 */ + PHY_11GN_MIXED, /* 2.4G band 7 */ + PHY_11AN_MIXED, /* 5G band 8 */ + PHY_11BGN_MIXED, /* if check 802.11b. 9 */ + PHY_11AGN_MIXED, /* if check 802.11b. 10 */ + PHY_11N_5G, /* 11n-only with 5G band 11 */ } RT_802_11_PHY_MODE; -// put all proprietery for-query objects here to reduce # of Query_OID -typedef struct _RT_802_11_LINK_STATUS { - ULONG CurrTxRate; // in units of 0.5Mbps - ULONG ChannelQuality; // 0..100 % - ULONG TxByteCount; // both ok and fail - ULONG RxByteCount; // both ok and fail - ULONG CentralChannel; // 40MHz central channel number -} RT_802_11_LINK_STATUS, *PRT_802_11_LINK_STATUS; - -typedef struct _RT_802_11_EVENT_LOG { - LARGE_INTEGER SystemTime; // timestammp via NdisGetCurrentSystemTime() - UCHAR Addr[MAC_ADDR_LENGTH]; - USHORT Event; // EVENT_xxx -} RT_802_11_EVENT_LOG, *PRT_802_11_EVENT_LOG; - -typedef struct _RT_802_11_EVENT_TABLE { - ULONG Num; - ULONG Rsv; // to align Log[] at LARGE_INEGER boundary - RT_802_11_EVENT_LOG Log[MAX_NUMBER_OF_EVENT]; -} RT_802_11_EVENT_TABLE, PRT_802_11_EVENT_TABLE; - -// MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition!!! -typedef union _MACHTTRANSMIT_SETTING { - struct { - USHORT MCS:7; // MCS - USHORT BW:1; //channel bandwidth 20MHz or 40 MHz - USHORT ShortGI:1; - USHORT STBC:2; //SPACE - USHORT rsv:3; - USHORT MODE:2; // Use definition MODE_xxx. - } field; - USHORT word; - } MACHTTRANSMIT_SETTING, *PMACHTTRANSMIT_SETTING; - -typedef struct _RT_802_11_MAC_ENTRY { - UCHAR Addr[MAC_ADDR_LENGTH]; - UCHAR Aid; - UCHAR Psm; // 0:PWR_ACTIVE, 1:PWR_SAVE - UCHAR MimoPs; // 0:MMPS_STATIC, 1:MMPS_DYNAMIC, 3:MMPS_Enabled - CHAR AvgRssi0; - CHAR AvgRssi1; - CHAR AvgRssi2; - UINT32 ConnectedTime; - MACHTTRANSMIT_SETTING TxRate; -} RT_802_11_MAC_ENTRY, *PRT_802_11_MAC_ENTRY; - -typedef struct _RT_802_11_MAC_TABLE { - ULONG Num; - RT_802_11_MAC_ENTRY Entry[MAX_NUMBER_OF_MAC]; -} RT_802_11_MAC_TABLE, *PRT_802_11_MAC_TABLE; - -// structure for query/set hardware register - MAC, BBP, RF register -typedef struct _RT_802_11_HARDWARE_REGISTER { - ULONG HardwareType; // 0:MAC, 1:BBP, 2:RF register, 3:EEPROM - ULONG Offset; // Q/S register offset addr - ULONG Data; // R/W data buffer -} RT_802_11_HARDWARE_REGISTER, *PRT_802_11_HARDWARE_REGISTER; - -typedef struct _RT_802_11_AP_CONFIG { - ULONG EnableTxBurst; // 0-disable, 1-enable - ULONG EnableTurboRate; // 0-disable, 1-enable 72/100mbps turbo rate - ULONG IsolateInterStaTraffic; // 0-disable, 1-enable isolation - ULONG HideSsid; // 0-disable, 1-enable hiding - ULONG UseBGProtection; // 0-AUTO, 1-always ON, 2-always OFF - ULONG UseShortSlotTime; // 0-no use, 1-use 9-us short slot time - ULONG Rsv1; // must be 0 - ULONG SystemErrorBitmap; // ignore upon SET, return system error upon QUERY -} RT_802_11_AP_CONFIG, *PRT_802_11_AP_CONFIG; - -// structure to query/set STA_CONFIG -typedef struct _RT_802_11_STA_CONFIG { - ULONG EnableTxBurst; // 0-disable, 1-enable - ULONG EnableTurboRate; // 0-disable, 1-enable 72/100mbps turbo rate - ULONG UseBGProtection; // 0-AUTO, 1-always ON, 2-always OFF - ULONG UseShortSlotTime; // 0-no use, 1-use 9-us short slot time when applicable - ULONG AdhocMode; // 0-11b rates only (WIFI spec), 1 - b/g mixed, 2 - g only - ULONG HwRadioStatus; // 0-OFF, 1-ON, default is 1, Read-Only - ULONG Rsv1; // must be 0 - ULONG SystemErrorBitmap; // ignore upon SET, return system error upon QUERY -} RT_802_11_STA_CONFIG, *PRT_802_11_STA_CONFIG; - -// -// For OID Query or Set about BA structure -// -typedef struct _OID_BACAP_STRUC { - UCHAR RxBAWinLimit; - UCHAR TxBAWinLimit; - UCHAR Policy; // 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid - UCHAR MpduDensity; // 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid - UCHAR AmsduEnable; //Enable AMSDU transmisstion - UCHAR AmsduSize; // 0:3839, 1:7935 bytes. UINT MSDUSizeToBytes[] = { 3839, 7935}; - UCHAR MMPSmode; // MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable - BOOLEAN AutoBA; // Auto BA will automatically -} OID_BACAP_STRUC, *POID_BACAP_STRUC; - -typedef struct _RT_802_11_ACL_ENTRY { - UCHAR Addr[MAC_ADDR_LENGTH]; - USHORT Rsv; -} RT_802_11_ACL_ENTRY, *PRT_802_11_ACL_ENTRY; - -typedef struct PACKED _RT_802_11_ACL { - ULONG Policy; // 0-disable, 1-positive list, 2-negative list - ULONG Num; - RT_802_11_ACL_ENTRY Entry[MAX_NUMBER_OF_ACL]; -} RT_802_11_ACL, *PRT_802_11_ACL; - -typedef struct _RT_802_11_WDS { - ULONG Num; - NDIS_802_11_MAC_ADDRESS Entry[24/*MAX_NUM_OF_WDS_LINK*/]; - ULONG KeyLength; - UCHAR KeyMaterial[32]; -} RT_802_11_WDS, *PRT_802_11_WDS; - -typedef struct _RT_802_11_TX_RATES_ { - UCHAR SupRateLen; - UCHAR SupRate[MAX_LENGTH_OF_SUPPORT_RATES]; - UCHAR ExtRateLen; - UCHAR ExtRate[MAX_LENGTH_OF_SUPPORT_RATES]; -} RT_802_11_TX_RATES, *PRT_802_11_TX_RATES; - - -// Definition of extra information code -#define GENERAL_LINK_UP 0x0 // Link is Up -#define GENERAL_LINK_DOWN 0x1 // Link is Down -#define HW_RADIO_OFF 0x2 // Hardware radio off -#define SW_RADIO_OFF 0x3 // Software radio off -#define AUTH_FAIL 0x4 // Open authentication fail -#define AUTH_FAIL_KEYS 0x5 // Shared authentication fail -#define ASSOC_FAIL 0x6 // Association failed -#define EAP_MIC_FAILURE 0x7 // Deauthencation because MIC failure -#define EAP_4WAY_TIMEOUT 0x8 // Deauthencation on 4-way handshake timeout -#define EAP_GROUP_KEY_TIMEOUT 0x9 // Deauthencation on group key handshake timeout -#define EAP_SUCCESS 0xa // EAP succeed -#define DETECT_RADAR_SIGNAL 0xb // Radar signal occur in current channel -#define EXTRA_INFO_MAX 0xb // Indicate Last OID +/* put all proprietery for-query objects here to reduce # of Query_OID */ +struct rt_802_11_link_status { + unsigned long CurrTxRate; /* in units of 0.5Mbps */ + unsigned long ChannelQuality; /* 0..100 % */ + unsigned long TxByteCount; /* both ok and fail */ + unsigned long RxByteCount; /* both ok and fail */ + unsigned long CentralChannel; /* 40MHz central channel number */ +}; + +struct rt_802_11_event_log { + LARGE_INTEGER SystemTime; /* timestammp via NdisGetCurrentSystemTime() */ + u8 Addr[MAC_ADDR_LENGTH]; + u16 Event; /* EVENT_xxx */ +}; + +struct rt_802_11_event_table { + unsigned long Num; + unsigned long Rsv; /* to align Log[] at LARGE_INEGER boundary */ + struct rt_802_11_event_log Log[MAX_NUMBER_OF_EVENT]; +}; + +/* MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition! */ +typedef union _MACHTTRANSMIT_SETTING { + struct { + u16 MCS:7; /* MCS */ + u16 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + u16 ShortGI:1; + u16 STBC:2; /*SPACE */ + u16 rsv:3; + u16 MODE:2; /* Use definition MODE_xxx. */ + } field; + u16 word; +} MACHTTRANSMIT_SETTING, *PMACHTTRANSMIT_SETTING; + +struct rt_802_11_mac_entry { + u8 Addr[MAC_ADDR_LENGTH]; + u8 Aid; + u8 Psm; /* 0:PWR_ACTIVE, 1:PWR_SAVE */ + u8 MimoPs; /* 0:MMPS_STATIC, 1:MMPS_DYNAMIC, 3:MMPS_Enabled */ + char AvgRssi0; + char AvgRssi1; + char AvgRssi2; + u32 ConnectedTime; + MACHTTRANSMIT_SETTING TxRate; +}; + +struct rt_802_11_mac_table { + unsigned long Num; + struct rt_802_11_mac_entry Entry[MAX_NUMBER_OF_MAC]; +}; + +/* structure for query/set hardware register - MAC, BBP, RF register */ +struct rt_802_11_hardware_register { + unsigned long HardwareType; /* 0:MAC, 1:BBP, 2:RF register, 3:EEPROM */ + unsigned long Offset; /* Q/S register offset addr */ + unsigned long Data; /* R/W data buffer */ +}; + +struct rt_802_11_ap_config { + unsigned long EnableTxBurst; /* 0-disable, 1-enable */ + unsigned long EnableTurboRate; /* 0-disable, 1-enable 72/100mbps turbo rate */ + unsigned long IsolateInterStaTraffic; /* 0-disable, 1-enable isolation */ + unsigned long HideSsid; /* 0-disable, 1-enable hiding */ + unsigned long UseBGProtection; /* 0-AUTO, 1-always ON, 2-always OFF */ + unsigned long UseShortSlotTime; /* 0-no use, 1-use 9-us short slot time */ + unsigned long Rsv1; /* must be 0 */ + unsigned long SystemErrorBitmap; /* ignore upon SET, return system error upon QUERY */ +}; + +/* structure to query/set STA_CONFIG */ +struct rt_802_11_sta_config { + unsigned long EnableTxBurst; /* 0-disable, 1-enable */ + unsigned long EnableTurboRate; /* 0-disable, 1-enable 72/100mbps turbo rate */ + unsigned long UseBGProtection; /* 0-AUTO, 1-always ON, 2-always OFF */ + unsigned long UseShortSlotTime; /* 0-no use, 1-use 9-us short slot time when applicable */ + unsigned long AdhocMode; /* 0-11b rates only (WIFI spec), 1 - b/g mixed, 2 - g only */ + unsigned long HwRadioStatus; /* 0-OFF, 1-ON, default is 1, Read-Only */ + unsigned long Rsv1; /* must be 0 */ + unsigned long SystemErrorBitmap; /* ignore upon SET, return system error upon QUERY */ +}; + +/* */ +/* For OID Query or Set about BA structure */ +/* */ +struct rt_oid_bacap { + u8 RxBAWinLimit; + u8 TxBAWinLimit; + u8 Policy; /* 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid */ + u8 MpduDensity; /* 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid */ + u8 AmsduEnable; /*Enable AMSDU transmisstion */ + u8 AmsduSize; /* 0:3839, 1:7935 bytes. u32 MSDUSizeToBytes[] = { 3839, 7935}; */ + u8 MMPSmode; /* MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable */ + BOOLEAN AutoBA; /* Auto BA will automatically */ +}; + +struct rt_802_11_acl_entry { + u8 Addr[MAC_ADDR_LENGTH]; + u16 Rsv; +}; + +struct PACKED rt_rt_802_11_acl { + unsigned long Policy; /* 0-disable, 1-positive list, 2-negative list */ + unsigned long Num; + struct rt_802_11_acl_entry Entry[MAX_NUMBER_OF_ACL]; +}; + +struct rt_802_11_wds { + unsigned long Num; + NDIS_802_11_MAC_ADDRESS Entry[24 /*MAX_NUM_OF_WDS_LINK */ ]; + unsigned long KeyLength; + u8 KeyMaterial[32]; +}; + +struct rt_802_11_tx_rates { + u8 SupRateLen; + u8 SupRate[MAX_LENGTH_OF_SUPPORT_RATES]; + u8 ExtRateLen; + u8 ExtRate[MAX_LENGTH_OF_SUPPORT_RATES]; +}; + +/* Definition of extra information code */ +#define GENERAL_LINK_UP 0x0 /* Link is Up */ +#define GENERAL_LINK_DOWN 0x1 /* Link is Down */ +#define HW_RADIO_OFF 0x2 /* Hardware radio off */ +#define SW_RADIO_OFF 0x3 /* Software radio off */ +#define AUTH_FAIL 0x4 /* Open authentication fail */ +#define AUTH_FAIL_KEYS 0x5 /* Shared authentication fail */ +#define ASSOC_FAIL 0x6 /* Association failed */ +#define EAP_MIC_FAILURE 0x7 /* Deauthencation because MIC failure */ +#define EAP_4WAY_TIMEOUT 0x8 /* Deauthencation on 4-way handshake timeout */ +#define EAP_GROUP_KEY_TIMEOUT 0x9 /* Deauthencation on group key handshake timeout */ +#define EAP_SUCCESS 0xa /* EAP succeed */ +#define DETECT_RADAR_SIGNAL 0xb /* Radar signal occur in current channel */ +#define EXTRA_INFO_MAX 0xb /* Indicate Last OID */ #define EXTRA_INFO_CLEAR 0xffffffff -// This is OID setting structure. So only GF or MM as Mode. This is valid when our wirelss mode has 802.11n in use. -typedef struct { - RT_802_11_PHY_MODE PhyMode; // - UCHAR TransmitNo; - UCHAR HtMode; //HTMODE_GF or HTMODE_MM - UCHAR ExtOffset; //extension channel above or below - UCHAR MCS; - UCHAR BW; - UCHAR STBC; - UCHAR SHORTGI; - UCHAR rsv; -} OID_SET_HT_PHYMODE, *POID_SET_HT_PHYMODE; - -#ifdef LLTD_SUPPORT -typedef struct _RT_LLTD_ASSOICATION_ENTRY { - UCHAR Addr[ETH_LENGTH_OF_ADDRESS]; - unsigned short MOR; // maximum operational rate - UCHAR phyMode; -} RT_LLTD_ASSOICATION_ENTRY, *PRT_LLTD_ASSOICATION_ENTRY; - -typedef struct _RT_LLTD_ASSOICATION_TABLE { - unsigned int Num; - RT_LLTD_ASSOICATION_ENTRY Entry[MAX_NUMBER_OF_MAC]; -} RT_LLTD_ASSOICATION_TABLE, *PRT_LLTD_ASSOICATION_TABLE; -#endif // LLTD_SUPPORT // +/* This is OID setting structure. So only GF or MM as Mode. This is valid when our wirelss mode has 802.11n in use. */ +struct rt_oid_set_ht_phymode { + RT_802_11_PHY_MODE PhyMode; /* */ + u8 TransmitNo; + u8 HtMode; /*HTMODE_GF or HTMODE_MM */ + u8 ExtOffset; /*extension channel above or below */ + u8 MCS; + u8 BW; + u8 STBC; + u8 SHORTGI; + u8 rsv; +}; #define MAX_CUSTOM_LEN 128 -typedef enum _RT_802_11_D_CLIENT_MODE -{ - Rt802_11_D_None, - Rt802_11_D_Flexible, - Rt802_11_D_Strict, +typedef enum _RT_802_11_D_CLIENT_MODE { + Rt802_11_D_None, + Rt802_11_D_Flexible, + Rt802_11_D_Strict, } RT_802_11_D_CLIENT_MODE, *PRT_802_11_D_CLIENT_MODE; -typedef struct _RT_CHANNEL_LIST_INFO -{ - UCHAR ChannelList[MAX_NUM_OF_CHS]; // list all supported channels for site survey - UCHAR ChannelListNum; // number of channel in ChannelList[] -} RT_CHANNEL_LIST_INFO, *PRT_CHANNEL_LIST_INFO; - -#ifdef RT2870 -// WSC configured credential -typedef struct _WSC_CREDENTIAL -{ - NDIS_802_11_SSID SSID; // mandatory - USHORT AuthType; // mandatory, 1: open, 2: wpa-psk, 4: shared, 8:wpa, 0x10: wpa2, 0x20: wpa2-psk - USHORT EncrType; // mandatory, 1: none, 2: wep, 4: tkip, 8: aes - UCHAR Key[64]; // mandatory, Maximum 64 byte - USHORT KeyLength; - UCHAR MacAddr[6]; // mandatory, AP MAC address - UCHAR KeyIndex; // optional, default is 1 - UCHAR Rsvd[3]; // Make alignment -} WSC_CREDENTIAL, *PWSC_CREDENTIAL; - -// WSC configured profiles -typedef struct _WSC_PROFILE -{ - UINT ProfileCnt; - WSC_CREDENTIAL Profile[8]; // Support up to 8 profiles -} WSC_PROFILE, *PWSC_PROFILE; -#endif +struct rt_channel_list_info { + u8 ChannelList[MAX_NUM_OF_CHS]; /* list all supported channels for site survey */ + u8 ChannelListNum; /* number of channel in ChannelList[] */ +}; -#endif // _OID_H_ +/* WSC configured credential */ +struct rt_wsc_credential { + struct rt_ndis_802_11_ssid SSID; /* mandatory */ + u16 AuthType; /* mandatory, 1: open, 2: wpa-psk, 4: shared, 8:wpa, 0x10: wpa2, 0x20: wpa2-psk */ + u16 EncrType; /* mandatory, 1: none, 2: wep, 4: tkip, 8: aes */ + u8 Key[64]; /* mandatory, Maximum 64 byte */ + u16 KeyLength; + u8 MacAddr[6]; /* mandatory, AP MAC address */ + u8 KeyIndex; /* optional, default is 1 */ + u8 Rsvd[3]; /* Make alignment */ +}; + +/* WSC configured profiles */ +struct rt_wsc_profile { + u32 ProfileCnt; + u32 ApplyProfileIdx; /* add by johnli, fix WPS test plan 5.1.1 */ + struct rt_wsc_credential Profile[8]; /* Support up to 8 profiles */ +}; +#endif /* _OID_H_ */ diff --git a/drivers/staging/rt2860/pci_main_dev.c b/drivers/staging/rt2860/pci_main_dev.c new file mode 100644 index 0000000000000000000000000000000000000000..6af430419070046c8277f75ae3c8b24ef1ff9acc --- /dev/null +++ b/drivers/staging/rt2860/pci_main_dev.c @@ -0,0 +1,1190 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* + + Module Name: + pci_main_dev.c + + Abstract: + Create and register network interface for PCI based chipsets in Linux platform. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" +#include + +/* Following information will be show when you run 'modinfo' */ +/* *** If you have a solution for the bug in current version of driver, please mail to me. */ +/* Otherwise post to forum in ralinktech's web site(www.ralinktech.com) and let all users help you. *** */ +MODULE_AUTHOR("Jett Chen "); +MODULE_DESCRIPTION("RT2860/RT3090 Wireless Lan Linux Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("rt3090sta"); + +/* */ +/* Function declarations */ +/* */ +extern int rt28xx_close(IN struct net_device *net_dev); +extern int rt28xx_open(struct net_device *net_dev); + +static void __devexit rt2860_remove_one(struct pci_dev *pci_dev); +static int __devinit rt2860_probe(struct pci_dev *pci_dev, + const struct pci_device_id *ent); +static void __exit rt2860_cleanup_module(void); +static int __init rt2860_init_module(void); + +static void RTMPInitPCIeDevice(IN struct pci_dev *pci_dev, + struct rt_rtmp_adapter *pAd); + +#ifdef CONFIG_PM +static int rt2860_suspend(struct pci_dev *pci_dev, pm_message_t state); +static int rt2860_resume(struct pci_dev *pci_dev); +#endif /* CONFIG_PM // */ + +/* */ +/* Ralink PCI device table, include all supported chipsets */ +/* */ +static struct pci_device_id rt2860_pci_tbl[] __devinitdata = { +#ifdef RT2860 + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCI_DEVICE_ID)}, /*RT28602.4G */ + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCIe_DEVICE_ID)}, + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2760_PCI_DEVICE_ID)}, + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2790_PCIe_DEVICE_ID)}, + {PCI_DEVICE(VEN_AWT_PCI_VENDOR_ID, VEN_AWT_PCIe_DEVICE_ID)}, + {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7708)}, + {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7728)}, + {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7758)}, + {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7727)}, + {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7738)}, + {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7748)}, + {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7768)}, +#endif +#ifdef RT3090 + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3090_PCIe_DEVICE_ID)}, + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3091_PCIe_DEVICE_ID)}, + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3092_PCIe_DEVICE_ID)}, +#endif /* RT3090 // */ +#ifdef RT3390 + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3390_PCIe_DEVICE_ID)}, + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3391_PCIe_DEVICE_ID)}, + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3392_PCIe_DEVICE_ID)}, +#endif /* RT3390 // */ + {0,} /* terminate list */ +}; + +MODULE_DEVICE_TABLE(pci, rt2860_pci_tbl); +#ifdef MODULE_VERSION +MODULE_VERSION(STA_DRIVER_VERSION); +#endif + +/* */ +/* Our PCI driver structure */ +/* */ +static struct pci_driver rt2860_driver = { +name: "rt2860", +id_table:rt2860_pci_tbl, +probe: rt2860_probe, +remove:__devexit_p(rt2860_remove_one), +#ifdef CONFIG_PM +suspend:rt2860_suspend, +resume:rt2860_resume, +#endif +}; + +/*************************************************************************** + * + * PCI device initialization related procedures. + * + ***************************************************************************/ +#ifdef CONFIG_PM + +void RT2860RejectPendingPackets(struct rt_rtmp_adapter *pAd) +{ + /* clear PS packets */ + /* clear TxSw packets */ +} + +static int rt2860_suspend(struct pci_dev *pci_dev, pm_message_t state) +{ + struct net_device *net_dev = pci_get_drvdata(pci_dev); + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)NULL; + int retval = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_suspend()\n")); + + if (net_dev == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n")); + } else { + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + /* we can not use IFF_UP because ra0 down but ra1 up */ + /* and 1 suspend/resume function for 1 module, not for each interface */ + /* so Linux will call suspend/resume function once */ + if (VIRTUAL_IF_NUM(pAd) > 0) { + /* avoid users do suspend after interface is down */ + + /* stop interface */ + netif_carrier_off(net_dev); + netif_stop_queue(net_dev); + + /* mark device as removed from system and therefore no longer available */ + netif_device_detach(net_dev); + + /* mark halt flag */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + + /* take down the device */ + rt28xx_close((struct net_device *)net_dev); + + RT_MOD_DEC_USE_COUNT(); + } + } + + /* reference to http://vovo2000.com/type-lab/linux/kernel-api/linux-kernel-api.html */ + /* enable device to generate PME# when suspended */ + /* pci_choose_state(): Choose the power state of a PCI device to be suspended */ + retval = pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1); + /* save the PCI configuration space of a device before suspending */ + pci_save_state(pci_dev); + /* disable PCI device after use */ + pci_disable_device(pci_dev); + + retval = pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_suspend()\n")); + return retval; +} + +static int rt2860_resume(struct pci_dev *pci_dev) +{ + struct net_device *net_dev = pci_get_drvdata(pci_dev); + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)NULL; + int retval; + + /* set the power state of a PCI device */ + /* PCI has 4 power states, DO (normal) ~ D3(less power) */ + /* in include/linux/pci.h, you can find that */ + /* #define PCI_D0 ((pci_power_t __force) 0) */ + /* #define PCI_D1 ((pci_power_t __force) 1) */ + /* #define PCI_D2 ((pci_power_t __force) 2) */ + /* #define PCI_D3hot ((pci_power_t __force) 3) */ + /* #define PCI_D3cold ((pci_power_t __force) 4) */ + /* #define PCI_UNKNOWN ((pci_power_t __force) 5) */ + /* #define PCI_POWER_ERROR ((pci_power_t __force) -1) */ + retval = pci_set_power_state(pci_dev, PCI_D0); + + /* restore the saved state of a PCI device */ + pci_restore_state(pci_dev); + + /* initialize device before it's used by a driver */ + if (pci_enable_device(pci_dev)) { + printk("pci enable fail!\n"); + return 0; + } + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_resume()\n")); + + if (net_dev == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n")); + } else + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + if (pAd != NULL) { + /* we can not use IFF_UP because ra0 down but ra1 up */ + /* and 1 suspend/resume function for 1 module, not for each interface */ + /* so Linux will call suspend/resume function once */ + if (VIRTUAL_IF_NUM(pAd) > 0) { + /* mark device as attached from system and restart if needed */ + netif_device_attach(net_dev); + + if (rt28xx_open((struct net_device *)net_dev) != 0) { + /* open fail */ + DBGPRINT(RT_DEBUG_TRACE, + ("<=== rt2860_resume()\n")); + return 0; + } + /* increase MODULE use count */ + RT_MOD_INC_USE_COUNT(); + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + + netif_start_queue(net_dev); + netif_carrier_on(net_dev); + netif_wake_queue(net_dev); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_resume()\n")); + return 0; +} +#endif /* CONFIG_PM // */ + +static int __init rt2860_init_module(void) +{ + return pci_register_driver(&rt2860_driver); +} + +/* */ +/* Driver module unload function */ +/* */ +static void __exit rt2860_cleanup_module(void) +{ + pci_unregister_driver(&rt2860_driver); +} + +module_init(rt2860_init_module); +module_exit(rt2860_cleanup_module); + +/* */ +/* PCI device probe & initialization function */ +/* */ +static int __devinit rt2860_probe(IN struct pci_dev *pci_dev, + IN const struct pci_device_id *pci_id) +{ + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)NULL; + struct net_device *net_dev; + void *handle; + char *print_name; + unsigned long csr_addr; + int rv = 0; + struct rt_rtmp_os_netdev_op_hook netDevHook; + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_probe\n")); + +/*PCIDevInit============================================== */ + /* wake up and enable device */ + if ((rv = pci_enable_device(pci_dev)) != 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("Enable PCI device failed, errno=%d!\n", rv)); + return rv; + } + + print_name = (char *)pci_name(pci_dev); + + if ((rv = pci_request_regions(pci_dev, print_name)) != 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("Request PCI resource failed, errno=%d!\n", rv)); + goto err_out; + } + /* map physical address to virtual address for accessing register */ + csr_addr = + (unsigned long)ioremap(pci_resource_start(pci_dev, 0), + pci_resource_len(pci_dev, 0)); + if (!csr_addr) { + DBGPRINT(RT_DEBUG_ERROR, + ("ioremap failed for device %s, region 0x%lX @ 0x%lX\n", + print_name, (unsigned long)pci_resource_len(pci_dev, 0), + (unsigned long)pci_resource_start(pci_dev, 0))); + goto err_out_free_res; + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("%s: at 0x%lx, VA 0x%lx, IRQ %d. \n", print_name, + (unsigned long)pci_resource_start(pci_dev, 0), + (unsigned long)csr_addr, pci_dev->irq)); + } + + /* Set DMA master */ + pci_set_master(pci_dev); + +/*RtmpDevInit============================================== */ + /* Allocate struct rt_rtmp_adapter adapter structure */ + handle = kmalloc(sizeof(struct os_cookie), GFP_KERNEL); + if (handle == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): Allocate memory for os handle failed!\n", + __func__)); + goto err_out_iounmap; + } + + ((struct os_cookie *)handle)->pci_dev = pci_dev; + + rv = RTMPAllocAdapterBlock(handle, &pAd); /*shiang: we may need the pci_dev for allocate structure of "struct rt_rtmp_adapter" */ + if (rv != NDIS_STATUS_SUCCESS) + goto err_out_iounmap; + /* Here are the struct rt_rtmp_adapter structure with pci-bus specific parameters. */ + pAd->CSRBaseAddress = (u8 *)csr_addr; + DBGPRINT(RT_DEBUG_ERROR, + ("pAd->CSRBaseAddress =0x%lx, csr_addr=0x%lx!\n", + (unsigned long)pAd->CSRBaseAddress, csr_addr)); + RtmpRaDevCtrlInit(pAd, RTMP_DEV_INF_PCI); + +/*NetDevInit============================================== */ + net_dev = RtmpPhyNetDevInit(pAd, &netDevHook); + if (net_dev == NULL) + goto err_out_free_radev; + + /* Here are the net_device structure with pci-bus specific parameters. */ + net_dev->irq = pci_dev->irq; /* Interrupt IRQ number */ + net_dev->base_addr = csr_addr; /* Save CSR virtual address and irq to device structure */ + pci_set_drvdata(pci_dev, net_dev); /* Set driver data */ + +/* for supporting Network Manager */ + /* Set the sysfs physical device reference for the network logical device + * if set prior to registration will cause a symlink during initialization. + */ + SET_NETDEV_DEV(net_dev, &(pci_dev->dev)); + +/*All done, it's time to register the net device to linux kernel. */ + /* Register this device */ + rv = RtmpOSNetDevAttach(net_dev, &netDevHook); + if (rv) + goto err_out_free_netdev; + + pAd->StaCfg.OriDevType = net_dev->type; + RTMPInitPCIeDevice(pci_dev, pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_probe\n")); + + return 0; /* probe ok */ + + /* --------------------------- ERROR HANDLE --------------------------- */ +err_out_free_netdev: + RtmpOSNetDevFree(net_dev); + +err_out_free_radev: + /* free struct rt_rtmp_adapter strcuture and os_cookie */ + RTMPFreeAdapter(pAd); + +err_out_iounmap: + iounmap((void *)(csr_addr)); + release_mem_region(pci_resource_start(pci_dev, 0), + pci_resource_len(pci_dev, 0)); + +err_out_free_res: + pci_release_regions(pci_dev); + +err_out: + pci_disable_device(pci_dev); + + DBGPRINT(RT_DEBUG_ERROR, + ("<=== rt2860_probe failed with rv = %d!\n", rv)); + + return -ENODEV; /* probe fail */ +} + +static void __devexit rt2860_remove_one(IN struct pci_dev *pci_dev) +{ + struct net_device *net_dev = pci_get_drvdata(pci_dev); + struct rt_rtmp_adapter *pAd = NULL; + unsigned long csr_addr = net_dev->base_addr; /* pAd->CSRBaseAddress; */ + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_remove_one\n")); + + if (pAd != NULL) { + /* Unregister/Free all allocated net_device. */ + RtmpPhyNetDevExit(pAd, net_dev); + + /* Unmap CSR base address */ + iounmap((char *)(csr_addr)); + + /* release memory region */ + release_mem_region(pci_resource_start(pci_dev, 0), + pci_resource_len(pci_dev, 0)); + + /* Free struct rt_rtmp_adapter related structures. */ + RtmpRaDevCtrlExit(pAd); + + } else { + /* Unregister network device */ + RtmpOSNetDevDetach(net_dev); + + /* Unmap CSR base address */ + iounmap((char *)(net_dev->base_addr)); + + /* release memory region */ + release_mem_region(pci_resource_start(pci_dev, 0), + pci_resource_len(pci_dev, 0)); + } + + /* Free the root net_device */ + RtmpOSNetDevFree(net_dev); + +} + +/* +======================================================================== +Routine Description: + Check the chipset vendor/product ID. + +Arguments: + _dev_p Point to the PCI or USB device + +Return Value: + TRUE Check ok + FALSE Check fail + +Note: +======================================================================== +*/ +BOOLEAN RT28XXChipsetCheck(IN void *_dev_p) +{ + /* always TRUE */ + return TRUE; +} + +/*************************************************************************** + * + * PCIe device initialization related procedures. + * + ***************************************************************************/ +static void RTMPInitPCIeDevice(struct pci_dev *pci_dev, struct rt_rtmp_adapter *pAd) +{ + u16 device_id; + struct os_cookie *pObj; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + pci_read_config_word(pci_dev, PCI_DEVICE_ID, &device_id); + device_id = le2cpu16(device_id); + pObj->DeviceID = device_id; + if ( +#ifdef RT2860 + (device_id == NIC2860_PCIe_DEVICE_ID) || + (device_id == NIC2790_PCIe_DEVICE_ID) || + (device_id == VEN_AWT_PCIe_DEVICE_ID) || +#endif +#ifdef RT3090 + (device_id == NIC3090_PCIe_DEVICE_ID) || + (device_id == NIC3091_PCIe_DEVICE_ID) || + (device_id == NIC3092_PCIe_DEVICE_ID) || +#endif /* RT3090 // */ + 0) { + u32 MacCsr0 = 0, Index = 0; + do { + RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); + + if ((MacCsr0 != 0x00) && (MacCsr0 != 0xFFFFFFFF)) + break; + + RTMPusecDelay(10); + } while (Index++ < 100); + + /* Support advanced power save after 2892/2790. */ + /* MAC version at offset 0x1000 is 0x2872XXXX/0x2870XXXX(PCIe, USB, SDIO). */ + if ((MacCsr0 & 0xffff0000) != 0x28600000) { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_PCIE_DEVICE); + } + } +} + +void RTMPInitPCIeLinkCtrlValue(struct rt_rtmp_adapter *pAd) +{ + int pos; + u16 reg16, data2, PCIePowerSaveLevel, Configuration; + u32 MacValue; + BOOLEAN bFindIntel = FALSE; + struct os_cookie *pObj; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __func__)); + /* Init EEPROM, and save settings */ + if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) { + RT28xx_EEPROM_READ16(pAd, 0x22, PCIePowerSaveLevel); + pAd->PCIePowerSaveLevel = PCIePowerSaveLevel & 0xff; + + pAd->LnkCtrlBitMask = 0; + if ((PCIePowerSaveLevel & 0xff) == 0xff) { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_PCIE_DEVICE); + DBGPRINT(RT_DEBUG_TRACE, + ("====> PCIePowerSaveLevel = 0x%x.\n", + PCIePowerSaveLevel)); + return; + } else { + PCIePowerSaveLevel &= 0x3; + RT28xx_EEPROM_READ16(pAd, 0x24, data2); + + if (! + (((data2 & 0xff00) == 0x9200) + && ((data2 & 0x80) != 0))) { + if (PCIePowerSaveLevel > 1) + PCIePowerSaveLevel = 1; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("====> Write 0x83 = 0x%x.\n", + PCIePowerSaveLevel)); + AsicSendCommandToMcu(pAd, 0x83, 0xff, + (u8)PCIePowerSaveLevel, 0x00); + RT28xx_EEPROM_READ16(pAd, 0x22, PCIePowerSaveLevel); + PCIePowerSaveLevel &= 0xff; + PCIePowerSaveLevel = PCIePowerSaveLevel >> 6; + switch (PCIePowerSaveLevel) { + case 0: /* Only support L0 */ + pAd->LnkCtrlBitMask = 0; + break; + case 1: /* Only enable L0s */ + pAd->LnkCtrlBitMask = 1; + break; + case 2: /* enable L1, L0s */ + pAd->LnkCtrlBitMask = 3; + break; + case 3: /* sync with host clk and enable L1, L0s */ + pAd->LnkCtrlBitMask = 0x103; + break; + } + RT28xx_EEPROM_READ16(pAd, 0x24, data2); + if ((PCIePowerSaveLevel & 0xff) != 0xff) { + PCIePowerSaveLevel &= 0x3; + + if (! + (((data2 & 0xff00) == 0x9200) + && ((data2 & 0x80) != 0))) { + if (PCIePowerSaveLevel > 1) + PCIePowerSaveLevel = 1; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("====> rt28xx Write 0x83 Command = 0x%x.\n", + PCIePowerSaveLevel)); + + AsicSendCommandToMcu(pAd, 0x83, 0xff, + (u8)PCIePowerSaveLevel, + 0x00); + } + DBGPRINT(RT_DEBUG_TRACE, + ("====> LnkCtrlBitMask = 0x%x.\n", + pAd->LnkCtrlBitMask)); + } + } else if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) { + u8 LinkCtrlSetting = 0; + + /* Check 3090E special setting chip. */ + RT28xx_EEPROM_READ16(pAd, 0x24, data2); + if ((data2 == 0x9280) && ((pAd->MACVersion & 0xffff) == 0x0211)) { + pAd->b3090ESpecialChip = TRUE; + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Special 3090E chip \n")); + } + + RTMP_IO_READ32(pAd, AUX_CTRL, &MacValue); + /*enable WAKE_PCIE function, which forces to enable PCIE clock when mpu interrupt asserting. */ + /*Force PCIE 125MHz CLK to toggle */ + MacValue |= 0x402; + RTMP_IO_WRITE32(pAd, AUX_CTRL, MacValue); + DBGPRINT_RAW(RT_DEBUG_ERROR, + (" AUX_CTRL = 0x%32x\n", MacValue)); + + /* for RT30xx F and after, PCIe infterface, and for power solution 3 */ + if ((IS_VERSION_AFTER_F(pAd)) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode >= 2) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode <= 3)) { + RTMP_IO_READ32(pAd, AUX_CTRL, &MacValue); + DBGPRINT_RAW(RT_DEBUG_ERROR, + (" Read AUX_CTRL = 0x%x\n", MacValue)); + /* turn on bit 12. */ + /*enable 32KHz clock mode for power saving */ + MacValue |= 0x1000; + if (MacValue != 0xffffffff) { + RTMP_IO_WRITE32(pAd, AUX_CTRL, MacValue); + DBGPRINT_RAW(RT_DEBUG_ERROR, + (" Write AUX_CTRL = 0x%x\n", + MacValue)); + /* 1. if use PCIePowerSetting is 2 or 3, need to program OSC_CTRL to 0x3ff11. */ + MacValue = 0x3ff11; + RTMP_IO_WRITE32(pAd, OSC_CTRL, MacValue); + DBGPRINT_RAW(RT_DEBUG_ERROR, + (" OSC_CTRL = 0x%x\n", MacValue)); + /* 2. Write PCI register Clk ref bit */ + RTMPrt3xSetPCIePowerLinkCtrl(pAd); + } else { + /* Error read Aux_Ctrl value. Force to use solution 1 */ + DBGPRINT(RT_DEBUG_ERROR, + (" Error Value in AUX_CTRL = 0x%x\n", + MacValue)); + pAd->StaCfg.PSControl.field.rt30xxPowerMode = 1; + DBGPRINT(RT_DEBUG_ERROR, + (" Force to use power solution1 \n")); + } + } + /* 1. read setting from inf file. */ + + PCIePowerSaveLevel = + (u16)pAd->StaCfg.PSControl.field.rt30xxPowerMode; + DBGPRINT(RT_DEBUG_ERROR, + ("====> rt30xx Read PowerLevelMode = 0x%x.\n", + PCIePowerSaveLevel)); + /* 2. Check EnableNewPS. */ + if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) + PCIePowerSaveLevel = 1; + + if (IS_VERSION_BEFORE_F(pAd) + && (pAd->b3090ESpecialChip == FALSE)) { + /* Chip Version E only allow 1, So force set 1. */ + PCIePowerSaveLevel &= 0x1; + pAd->PCIePowerSaveLevel = (u16)PCIePowerSaveLevel; + DBGPRINT(RT_DEBUG_TRACE, + ("====> rt30xx E Write 0x83 Command = 0x%x.\n", + PCIePowerSaveLevel)); + + AsicSendCommandToMcu(pAd, 0x83, 0xff, + (u8)PCIePowerSaveLevel, 0x00); + } else { + /* Chip Version F and after only allow 1 or 2 or 3. This might be modified after new chip version come out. */ + if (! + ((PCIePowerSaveLevel == 1) + || (PCIePowerSaveLevel == 3))) + PCIePowerSaveLevel = 1; + DBGPRINT(RT_DEBUG_ERROR, + ("====> rt30xx F Write 0x83 Command = 0x%x.\n", + PCIePowerSaveLevel)); + pAd->PCIePowerSaveLevel = (u16)PCIePowerSaveLevel; + /* for 3090F , we need to add high-byte arg for 0x83 command to indicate the link control setting in */ + /* PCI Configuration Space. Because firmware can't read PCI Configuration Space */ + if ((pAd->Rt3xxRalinkLinkCtrl & 0x2) + && (pAd->Rt3xxHostLinkCtrl & 0x2)) { + LinkCtrlSetting = 1; + } + DBGPRINT(RT_DEBUG_TRACE, + ("====> rt30xxF LinkCtrlSetting = 0x%x.\n", + LinkCtrlSetting)); + AsicSendCommandToMcu(pAd, 0x83, 0xff, + (u8)PCIePowerSaveLevel, + LinkCtrlSetting); + } + } + /* Find Ralink PCIe Device's Express Capability Offset */ + pos = pci_find_capability(pObj->pci_dev, PCI_CAP_ID_EXP); + + if (pos != 0) { + /* Ralink PCIe Device's Link Control Register Offset */ + pAd->RLnkCtrlOffset = pos + PCI_EXP_LNKCTL; + pci_read_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset, + ®16); + Configuration = le2cpu16(reg16); + DBGPRINT(RT_DEBUG_TRACE, + ("Read (Ralink PCIe Link Control Register) offset 0x%x = 0x%x\n", + pAd->RLnkCtrlOffset, Configuration)); + pAd->RLnkCtrlConfiguration = (Configuration & 0x103); + Configuration &= 0xfefc; + Configuration |= (0x0); +#ifdef RT2860 + if ((pObj->DeviceID == NIC2860_PCIe_DEVICE_ID) + || (pObj->DeviceID == NIC2790_PCIe_DEVICE_ID)) { + reg16 = cpu2le16(Configuration); + pci_write_config_word(pObj->pci_dev, + pAd->RLnkCtrlOffset, reg16); + DBGPRINT(RT_DEBUG_TRACE, + ("Write (Ralink PCIe Link Control Register) offset 0x%x = 0x%x\n", + pos + PCI_EXP_LNKCTL, Configuration)); + } +#endif /* RT2860 // */ + + RTMPFindHostPCIDev(pAd); + if (pObj->parent_pci_dev) { + u16 vendor_id; + + pci_read_config_word(pObj->parent_pci_dev, + PCI_VENDOR_ID, &vendor_id); + vendor_id = le2cpu16(vendor_id); + if (vendor_id == PCIBUS_INTEL_VENDOR) { + bFindIntel = TRUE; + RTMP_SET_PSFLAG(pAd, fRTMP_PS_TOGGLE_L1); + } + /* Find PCI-to-PCI Bridge Express Capability Offset */ + pos = + pci_find_capability(pObj->parent_pci_dev, + PCI_CAP_ID_EXP); + + if (pos != 0) { + BOOLEAN bChange = FALSE; + /* PCI-to-PCI Bridge Link Control Register Offset */ + pAd->HostLnkCtrlOffset = pos + PCI_EXP_LNKCTL; + pci_read_config_word(pObj->parent_pci_dev, + pAd->HostLnkCtrlOffset, + ®16); + Configuration = le2cpu16(reg16); + DBGPRINT(RT_DEBUG_TRACE, + ("Read (Host PCI-to-PCI Bridge Link Control Register) offset 0x%x = 0x%x\n", + pAd->HostLnkCtrlOffset, + Configuration)); + pAd->HostLnkCtrlConfiguration = + (Configuration & 0x103); + Configuration &= 0xfefc; + Configuration |= (0x0); + + switch (pObj->DeviceID) { +#ifdef RT2860 + case NIC2860_PCIe_DEVICE_ID: + case NIC2790_PCIe_DEVICE_ID: + bChange = TRUE; + break; +#endif /* RT2860 // */ +#ifdef RT3090 + case NIC3090_PCIe_DEVICE_ID: + case NIC3091_PCIe_DEVICE_ID: + case NIC3092_PCIe_DEVICE_ID: + if (bFindIntel == FALSE) + bChange = TRUE; + break; +#endif /* RT3090 // */ + default: + break; + } + + if (bChange) { + reg16 = cpu2le16(Configuration); + pci_write_config_word(pObj-> + parent_pci_dev, + pAd-> + HostLnkCtrlOffset, + reg16); + DBGPRINT(RT_DEBUG_TRACE, + ("Write (Host PCI-to-PCI Bridge Link Control Register) offset 0x%x = 0x%x\n", + pAd->HostLnkCtrlOffset, + Configuration)); + } + } else { + pAd->HostLnkCtrlOffset = 0; + DBGPRINT(RT_DEBUG_ERROR, + ("%s: cannot find PCI-to-PCI Bridge PCI Express Capability!\n", + __func__)); + } + } + } else { + pAd->RLnkCtrlOffset = 0; + pAd->HostLnkCtrlOffset = 0; + DBGPRINT(RT_DEBUG_ERROR, + ("%s: cannot find Ralink PCIe Device's PCI Express Capability!\n", + __func__)); + } + + if (bFindIntel == FALSE) { + DBGPRINT(RT_DEBUG_TRACE, + ("Doesn't find Intel PCI host controller. \n")); + /* Doesn't switch L0, L1, So set PCIePowerSaveLevel to 0xff */ + pAd->PCIePowerSaveLevel = 0xff; + if ((pAd->RLnkCtrlOffset != 0) +#ifdef RT3090 + && ((pObj->DeviceID == NIC3090_PCIe_DEVICE_ID) + || (pObj->DeviceID == NIC3091_PCIe_DEVICE_ID) + || (pObj->DeviceID == NIC3092_PCIe_DEVICE_ID)) +#endif /* RT3090 // */ + ) { + pci_read_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset, + ®16); + Configuration = le2cpu16(reg16); + DBGPRINT(RT_DEBUG_TRACE, + ("Read (Ralink 30xx PCIe Link Control Register) offset 0x%x = 0x%x\n", + pAd->RLnkCtrlOffset, Configuration)); + pAd->RLnkCtrlConfiguration = (Configuration & 0x103); + Configuration &= 0xfefc; + Configuration |= (0x0); + reg16 = cpu2le16(Configuration); + pci_write_config_word(pObj->pci_dev, + pAd->RLnkCtrlOffset, reg16); + DBGPRINT(RT_DEBUG_TRACE, + ("Write (Ralink PCIe Link Control Register) offset 0x%x = 0x%x\n", + pos + PCI_EXP_LNKCTL, Configuration)); + } + } +} + +void RTMPFindHostPCIDev(struct rt_rtmp_adapter *pAd) +{ + u16 reg16; + u8 reg8; + u32 DevFn; + struct pci_dev *pPci_dev; + struct os_cookie *pObj; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __func__)); + + pObj->parent_pci_dev = NULL; + if (pObj->pci_dev->bus->parent) { + for (DevFn = 0; DevFn < 255; DevFn++) { + pPci_dev = + pci_get_slot(pObj->pci_dev->bus->parent, DevFn); + if (pPci_dev) { + pci_read_config_word(pPci_dev, PCI_CLASS_DEVICE, + ®16); + reg16 = le2cpu16(reg16); + pci_read_config_byte(pPci_dev, PCI_CB_CARD_BUS, + ®8); + if ((reg16 == PCI_CLASS_BRIDGE_PCI) + && (reg8 == pObj->pci_dev->bus->number)) { + pObj->parent_pci_dev = pPci_dev; + } + } + } + } +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + Level = RESTORE_HALT : Restore PCI host and Ralink PCIe Link Control field to its default value. + Level = Other Value : Restore from dot11 power save or radio off status. And force PCI host Link Control fields to 0x1 + + ======================================================================== +*/ +void RTMPPCIeLinkCtrlValueRestore(struct rt_rtmp_adapter *pAd, u8 Level) +{ + u16 PCIePowerSaveLevel, reg16; + u16 Configuration; + struct os_cookie *pObj; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) + return; + +#ifdef RT2860 + if (!((pObj->DeviceID == NIC2860_PCIe_DEVICE_ID) + || (pObj->DeviceID == NIC2790_PCIe_DEVICE_ID))) + return; +#endif /* RT2860 // */ + /* Check PSControl Configuration */ + if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) + return; + + /*3090 will not execute the following codes. */ + /* Check interface : If not PCIe interface, return. */ + +#ifdef RT3090 + if ((pObj->DeviceID == NIC3090_PCIe_DEVICE_ID) + || (pObj->DeviceID == NIC3091_PCIe_DEVICE_ID) + || (pObj->DeviceID == NIC3092_PCIe_DEVICE_ID)) + return; +#endif /* RT3090 // */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __func__)); + PCIePowerSaveLevel = pAd->PCIePowerSaveLevel; + if ((PCIePowerSaveLevel & 0xff) == 0xff) { + DBGPRINT(RT_DEBUG_TRACE, ("return \n")); + return; + } + + if (pObj->parent_pci_dev && (pAd->HostLnkCtrlOffset != 0)) { + PCI_REG_READ_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, + Configuration); + if ((Configuration != 0) && (Configuration != 0xFFFF)) { + Configuration &= 0xfefc; + /* If call from interface down, restore to orginial setting. */ + if (Level == RESTORE_CLOSE) { + Configuration |= pAd->HostLnkCtrlConfiguration; + } else + Configuration |= 0x0; + PCI_REG_WIRTE_WORD(pObj->parent_pci_dev, + pAd->HostLnkCtrlOffset, + Configuration); + DBGPRINT(RT_DEBUG_TRACE, + ("Restore PCI host : offset 0x%x = 0x%x\n", + pAd->HostLnkCtrlOffset, Configuration)); + } else + DBGPRINT(RT_DEBUG_ERROR, + ("Restore PCI host : PCI_REG_READ_WORD failed (Configuration = 0x%x)\n", + Configuration)); + } + + if (pObj->pci_dev && (pAd->RLnkCtrlOffset != 0)) { + PCI_REG_READ_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset, + Configuration); + if ((Configuration != 0) && (Configuration != 0xFFFF)) { + Configuration &= 0xfefc; + /* If call from interface down, restore to orginial setting. */ + if (Level == RESTORE_CLOSE) + Configuration |= pAd->RLnkCtrlConfiguration; + else + Configuration |= 0x0; + PCI_REG_WIRTE_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset, + Configuration); + DBGPRINT(RT_DEBUG_TRACE, + ("Restore Ralink : offset 0x%x = 0x%x\n", + pAd->RLnkCtrlOffset, Configuration)); + } else + DBGPRINT(RT_DEBUG_ERROR, + ("Restore Ralink : PCI_REG_READ_WORD failed (Configuration = 0x%x)\n", + Configuration)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s <===\n", __func__)); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + Max : limit Host PCI and Ralink PCIe device's LINK CONTROL field's value. + Because now frequently set our device to mode 1 or mode 3 will cause problem. + + ======================================================================== +*/ +void RTMPPCIeLinkCtrlSetting(struct rt_rtmp_adapter *pAd, u16 Max) +{ + u16 PCIePowerSaveLevel, reg16; + u16 Configuration; + struct os_cookie *pObj; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) + return; + +#ifdef RT2860 + if (!((pObj->DeviceID == NIC2860_PCIe_DEVICE_ID) + || (pObj->DeviceID == NIC2790_PCIe_DEVICE_ID))) + return; +#endif /* RT2860 // */ + /* Check PSControl Configuration */ + if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) + return; + + /* Check interface : If not PCIe interface, return. */ + /*Block 3090 to enter the following function */ + +#ifdef RT3090 + if ((pObj->DeviceID == NIC3090_PCIe_DEVICE_ID) + || (pObj->DeviceID == NIC3091_PCIe_DEVICE_ID) + || (pObj->DeviceID == NIC3092_PCIe_DEVICE_ID)) + return; +#endif /* RT3090 // */ + if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)) { + DBGPRINT(RT_DEBUG_INFO, + ("RTMPPCIePowerLinkCtrl return on fRTMP_PS_CAN_GO_SLEEP flag\n")); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s===>\n", __func__)); + PCIePowerSaveLevel = pAd->PCIePowerSaveLevel; + if ((PCIePowerSaveLevel & 0xff) == 0xff) { + DBGPRINT(RT_DEBUG_TRACE, ("return \n")); + return; + } + PCIePowerSaveLevel = PCIePowerSaveLevel >> 6; + + /* Skip non-exist deice right away */ + if (pObj->parent_pci_dev && (pAd->HostLnkCtrlOffset != 0)) { + PCI_REG_READ_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, + Configuration); + switch (PCIePowerSaveLevel) { + case 0: + /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 00 */ + Configuration &= 0xfefc; + break; + case 1: + /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 01 */ + Configuration &= 0xfefc; + Configuration |= 0x1; + break; + case 2: + /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 */ + Configuration &= 0xfefc; + Configuration |= 0x3; + break; + case 3: + /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 and bit 8 of LinkControl of 2892 to 1 */ + Configuration &= 0xfefc; + Configuration |= 0x103; + break; + } + PCI_REG_WIRTE_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, + Configuration); + DBGPRINT(RT_DEBUG_TRACE, + ("Write PCI host offset 0x%x = 0x%x\n", + pAd->HostLnkCtrlOffset, Configuration)); + } + + if (pObj->pci_dev && (pAd->RLnkCtrlOffset != 0)) { + /* first 2892 chip not allow to frequently set mode 3. will cause hang problem. */ + if (PCIePowerSaveLevel > Max) + PCIePowerSaveLevel = Max; + + PCI_REG_READ_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset, + Configuration); + switch (PCIePowerSaveLevel) { + case 0: + /* No PCI power safe */ + /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 00 . */ + Configuration &= 0xfefc; + break; + case 1: + /* L0 */ + /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 01 . */ + Configuration &= 0xfefc; + Configuration |= 0x1; + break; + case 2: + /* L0 and L1 */ + /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 */ + Configuration &= 0xfefc; + Configuration |= 0x3; + break; + case 3: + /* L0 , L1 and clock management. */ + /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 and bit 8 of LinkControl of 2892 to 1 */ + Configuration &= 0xfefc; + Configuration |= 0x103; + pAd->bPCIclkOff = TRUE; + break; + } + PCI_REG_WIRTE_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset, + Configuration); + DBGPRINT(RT_DEBUG_TRACE, + ("Write Ralink device : offset 0x%x = 0x%x\n", + pAd->RLnkCtrlOffset, Configuration)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPPCIePowerLinkCtrl <==============\n")); +} + +/* + ======================================================================== + + Routine Description: + 1. Write a PCI register for rt30xx power solution 3 + + ======================================================================== +*/ +void RTMPrt3xSetPCIePowerLinkCtrl(struct rt_rtmp_adapter *pAd) +{ + + unsigned long HostConfiguration = 0; + unsigned long Configuration; + struct os_cookie *pObj; + int pos; + u16 reg16; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + + DBGPRINT(RT_DEBUG_INFO, + ("RTMPrt3xSetPCIePowerLinkCtrl.===> %lx\n", + pAd->StaCfg.PSControl.word)); + + /* Check PSControl Configuration */ + if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) + return; + RTMPFindHostPCIDev(pAd); + if (pObj->parent_pci_dev) { + /* Find PCI-to-PCI Bridge Express Capability Offset */ + pos = pci_find_capability(pObj->parent_pci_dev, PCI_CAP_ID_EXP); + + if (pos != 0) { + pAd->HostLnkCtrlOffset = pos + PCI_EXP_LNKCTL; + } + /* If configurared to turn on L1. */ + HostConfiguration = 0; + if (pAd->StaCfg.PSControl.field.rt30xxForceASPMTest == 1) { + DBGPRINT(RT_DEBUG_TRACE, ("Enter,PSM : Force ASPM \n")); + + /* Skip non-exist deice right away */ + if ((pAd->HostLnkCtrlOffset != 0)) { + PCI_REG_READ_WORD(pObj->parent_pci_dev, + pAd->HostLnkCtrlOffset, + HostConfiguration); + /* Prepare Configuration to write to Host */ + HostConfiguration |= 0x3; + PCI_REG_WIRTE_WORD(pObj->parent_pci_dev, + pAd->HostLnkCtrlOffset, + HostConfiguration); + pAd->Rt3xxHostLinkCtrl = HostConfiguration; + /* Because in rt30xxForceASPMTest Mode, Force turn on L0s, L1. */ + /* Fix HostConfiguration bit0:1 = 0x3 for later use. */ + HostConfiguration = 0x3; + DBGPRINT(RT_DEBUG_TRACE, + ("PSM : Force ASPM : " + "Host device L1/L0s Value = 0x%lx\n", + HostConfiguration)); + } + } else if (pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM == + 1) { + + /* Skip non-exist deice right away */ + if ((pAd->HostLnkCtrlOffset != 0)) { + PCI_REG_READ_WORD(pObj->parent_pci_dev, + pAd->HostLnkCtrlOffset, + HostConfiguration); + pAd->Rt3xxHostLinkCtrl = HostConfiguration; + HostConfiguration &= 0x3; + DBGPRINT(RT_DEBUG_TRACE, + ("PSM : Follow Host ASPM : " + "Host device L1/L0s Value = 0x%lx\n", + HostConfiguration)); + } + } + } + /* Prepare to write Ralink setting. */ + /* Find Ralink PCIe Device's Express Capability Offset */ + pos = pci_find_capability(pObj->pci_dev, PCI_CAP_ID_EXP); + + if (pos != 0) { + /* Ralink PCIe Device's Link Control Register Offset */ + pAd->RLnkCtrlOffset = pos + PCI_EXP_LNKCTL; + pci_read_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset, + ®16); + Configuration = le2cpu16(reg16); + DBGPRINT(RT_DEBUG_TRACE, + ("Read (Ralink PCIe Link Control Register) " + "offset 0x%x = 0x%lx\n", + pAd->RLnkCtrlOffset, Configuration)); + Configuration |= 0x100; + if ((pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM == 1) + || (pAd->StaCfg.PSControl.field.rt30xxForceASPMTest == 1)) { + switch (HostConfiguration) { + case 0: + Configuration &= 0xffffffc; + break; + case 1: + Configuration &= 0xffffffc; + Configuration |= 0x1; + break; + case 2: + Configuration &= 0xffffffc; + Configuration |= 0x2; + break; + case 3: + Configuration |= 0x3; + break; + } + } + reg16 = cpu2le16(Configuration); + pci_write_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset, + reg16); + pAd->Rt3xxRalinkLinkCtrl = Configuration; + DBGPRINT(RT_DEBUG_TRACE, + ("PSM :Write Ralink device L1/L0s Value = 0x%lx\n", + Configuration)); + } + DBGPRINT(RT_DEBUG_INFO, + ("PSM :RTMPrt3xSetPCIePowerLinkCtrl <==============\n")); +} diff --git a/drivers/staging/rt2860/rt2860.h b/drivers/staging/rt2860/rt2860.h deleted file mode 100644 index ed28fe5757c9b85366cf913522ffa471dd0fc794..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2860/rt2860.h +++ /dev/null @@ -1,333 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - */ - -#ifndef __RT2860_H__ -#define __RT2860_H__ - -#define RT28xx_CHIP_NAME "RT2860" - -#define TXINFO_SIZE 0 -#define TXPADDING_SIZE 0 - -/* ----------------- EEPROM Related MACRO ----------------- */ -#define RT28xx_EEPROM_READ16(pAd, offset, var) \ - var = RTMP_EEPROM_READ16(pAd, offset) - -#define RT28xx_EEPROM_WRITE16(pAd, offset, var) \ - RTMP_EEPROM_WRITE16(pAd, offset, var) - -/* ----------------- TASK/THREAD Related MACRO ----------------- */ -#define RT28XX_TASK_THREAD_INIT(pAd, Status) \ - init_thread_task(pAd); NICInitTxRxRingAndBacklogQueue(pAd); \ - Status = NDIS_STATUS_SUCCESS; - -/* function declarations */ -#define IRQ_HANDLE_TYPE irqreturn_t - -IRQ_HANDLE_TYPE -rt2860_interrupt(int irq, void *dev_instance); - -/* ----------------- Frimware Related MACRO ----------------- */ -#define RT28XX_WRITE_FIRMWARE(_pAd, _pFwImage, _FwLen) \ - do{ \ - ULONG _i, _firm; \ - RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, 0x10000); \ - \ - for(_i=0; _i<_FwLen; _i+=4) \ - { \ - _firm = _pFwImage[_i] + \ - (_pFwImage[_i+3] << 24) + \ - (_pFwImage[_i+2] << 16) + \ - (_pFwImage[_i+1] << 8); \ - RTMP_IO_WRITE32(_pAd, FIRMWARE_IMAGE_BASE + _i, _firm); \ - } \ - RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, 0x00000); \ - RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, 0x00001); \ - \ - /* initialize BBP R/W access agent */ \ - RTMP_IO_WRITE32(_pAd, H2M_BBP_AGENT, 0); \ - RTMP_IO_WRITE32(_pAd, H2M_MAILBOX_CSR, 0); \ - }while(0) - -/* ----------------- TX Related MACRO ----------------- */ -#define RT28XX_START_DEQUEUE(pAd, QueIdx, irqFlags) do{}while(0) -#define RT28XX_STOP_DEQUEUE(pAd, QueIdx, irqFlags) do{}while(0) - - -#define RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, freeNum, pPacket) \ - ((freeNum) >= (ULONG)(pTxBlk->TotalFragNum + RTMP_GET_PACKET_FRAGMENTS(pPacket) + 3)) /* rough estimate we will use 3 more descriptor. */ -#define RT28XX_RELEASE_DESC_RESOURCE(pAd, QueIdx) \ - do{}while(0) - -#define NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, freeNum, _TxFrameType) \ - (((freeNum != (TX_RING_SIZE-1)) && (pAd->TxSwQueue[QueIdx].Number == 0)) || (freeNum<3)) - //(((freeNum) != (TX_RING_SIZE-1)) && (pAd->TxSwQueue[QueIdx].Number == 1 /*0*/)) - - -#define HAL_KickOutMgmtTx(_pAd, _QueIdx, _pPacket, _pSrcBufVA, _SrcBufLen) \ - RtmpPCIMgmtKickOut(_pAd, _QueIdx, _pPacket, _pSrcBufVA, _SrcBufLen) - -#define RTMP_PKT_TAIL_PADDING 0 - -#define fRTMP_ADAPTER_NEED_STOP_TX 0 - -#define HAL_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) \ - /* RtmpPCI_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber)*/ - -#define HAL_WriteTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) \ - RtmpPCI_WriteSingleTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) - -#define HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) \ - RtmpPCI_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) - -#define HAL_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) \ - RtmpPCI_WriteMultiTxResource(pAd, pTxBlk, frameNum, pFreeNumber) - -#define HAL_FinalWriteTxResource(_pAd, _pTxBlk, _TotalMPDUSize, _FirstTxIdx) \ - RtmpPCI_FinalWriteTxResource(_pAd, _pTxBlk, _TotalMPDUSize, _FirstTxIdx) - -#define HAL_LastTxIdx(_pAd, _QueIdx,_LastTxIdx) \ - /*RtmpPCIDataLastTxIdx(_pAd, _QueIdx,_LastTxIdx)*/ - -#define HAL_KickOutTx(_pAd, _pTxBlk, _QueIdx) \ - RTMP_IO_WRITE32((_pAd), TX_CTX_IDX0+((_QueIdx)*0x10), (_pAd)->TxRing[(_QueIdx)].TxCpuIdx) -/* RtmpPCIDataKickOut(_pAd, _pTxBlk, _QueIdx)*/ - -#define HAL_KickOutNullFrameTx(_pAd, _QueIdx, _pNullFrame, _frameLen) \ - MiniportMMRequest(_pAd, _QueIdx, _pNullFrame, _frameLen) - -#define GET_TXRING_FREENO(_pAd, _QueIdx) \ - (_pAd->TxRing[_QueIdx].TxSwFreeIdx > _pAd->TxRing[_QueIdx].TxCpuIdx) ? \ - (_pAd->TxRing[_QueIdx].TxSwFreeIdx - _pAd->TxRing[_QueIdx].TxCpuIdx - 1) \ - : \ - (_pAd->TxRing[_QueIdx].TxSwFreeIdx + TX_RING_SIZE - _pAd->TxRing[_QueIdx].TxCpuIdx - 1); - - -#define GET_MGMTRING_FREENO(_pAd) \ - (_pAd->MgmtRing.TxSwFreeIdx > _pAd->MgmtRing.TxCpuIdx) ? \ - (_pAd->MgmtRing.TxSwFreeIdx - _pAd->MgmtRing.TxCpuIdx - 1) \ - : \ - (_pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - _pAd->MgmtRing.TxCpuIdx - 1); - - -/* ----------------- RX Related MACRO ----------------- */ - -// no use -#define RT28XX_RCV_PKT_GET_INIT(pAd) -#define RT28XX_RV_A_BUF_END -//#define RT28XX_RV_ALL_BUF_END - - -/* ----------------- ASIC Related MACRO ----------------- */ -// no use -#define RT28XX_DMA_POST_WRITE(pAd) - -// reset MAC of a station entry to 0x000000000000 -#define RT28XX_STA_ENTRY_MAC_RESET(pAd, Wcid) \ - AsicDelWcidTab(pAd, Wcid); - -// add this entry into ASIC RX WCID search table -#define RT28XX_STA_ENTRY_ADD(pAd, pEntry) \ - AsicUpdateRxWCIDTable(pAd, pEntry->Aid, pEntry->Addr); - -// remove Pair-wise key material from ASIC -#define RT28XX_STA_ENTRY_KEY_DEL(pAd, BssIdx, Wcid) \ - AsicRemovePairwiseKeyEntry(pAd, BssIdx, (UCHAR)Wcid); - -// add Client security information into ASIC WCID table and IVEIV table -#define RT28XX_STA_SECURITY_INFO_ADD(pAd, apidx, KeyID, pEntry) \ - RTMPAddWcidAttributeEntry(pAd, apidx, KeyID, \ - pAd->SharedKey[apidx][KeyID].CipherAlg, pEntry); - -#define RT28XX_SECURITY_KEY_ADD(pAd, apidx, KeyID, pEntry) \ - { /* update pairwise key information to ASIC Shared Key Table */ \ - AsicAddSharedKeyEntry(pAd, apidx, KeyID, \ - pAd->SharedKey[apidx][KeyID].CipherAlg, \ - pAd->SharedKey[apidx][KeyID].Key, \ - pAd->SharedKey[apidx][KeyID].TxMic, \ - pAd->SharedKey[apidx][KeyID].RxMic); \ - /* update ASIC WCID attribute table and IVEIV table */ \ - RTMPAddWcidAttributeEntry(pAd, apidx, KeyID, \ - pAd->SharedKey[apidx][KeyID].CipherAlg, \ - pEntry); } - - -// Insert the BA bitmap to ASIC for the Wcid entry -#define RT28XX_ADD_BA_SESSION_TO_ASIC(_pAd, _Aid, _TID) \ - do{ \ - UINT32 _Value = 0, _Offset; \ - _Offset = MAC_WCID_BASE + (_Aid) * HW_WCID_ENTRY_SIZE + 4; \ - RTMP_IO_READ32((_pAd), _Offset, &_Value); \ - _Value |= (0x10000<<(_TID)); \ - RTMP_IO_WRITE32((_pAd), _Offset, _Value); \ - }while(0) - - -// Remove the BA bitmap from ASIC for the Wcid entry -// bitmap field starts at 0x10000 in ASIC WCID table -#define RT28XX_DEL_BA_SESSION_FROM_ASIC(_pAd, _Wcid, _TID) \ - do{ \ - UINT32 _Value = 0, _Offset; \ - _Offset = MAC_WCID_BASE + (_Wcid) * HW_WCID_ENTRY_SIZE + 4; \ - RTMP_IO_READ32((_pAd), _Offset, &_Value); \ - _Value &= (~(0x10000 << (_TID))); \ - RTMP_IO_WRITE32((_pAd), _Offset, _Value); \ - }while(0) - - -/* ----------------- PCI/USB Related MACRO ----------------- */ - -#define RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p) \ - ((POS_COOKIE)handle)->pci_dev = dev_p; - -// set driver data -#define RT28XX_DRVDATA_SET(_a) pci_set_drvdata(_a, net_dev); - -#define RT28XX_UNMAP() \ -{ if (net_dev->base_addr) { \ - iounmap((void *)(net_dev->base_addr)); \ - release_mem_region(pci_resource_start(dev_p, 0), \ - pci_resource_len(dev_p, 0)); } \ - if (net_dev->irq) pci_release_regions(dev_p); } - -#ifdef PCI_MSI_SUPPORT -#define RTMP_MSI_ENABLE(_pAd) \ -{ POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ - (_pAd)->HaveMsi = pci_enable_msi(_pObj->pci_dev) == 0 ? TRUE : FALSE; } - -#define RTMP_MSI_DISABLE(_pAd) \ -{ POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ - if (_pAd->HaveMsi == TRUE) \ - pci_disable_msi(_pObj->pci_dev); \ - _pAd->HaveMsi = FALSE; } -#else -#define RTMP_MSI_ENABLE(_pAd) -#define RTMP_MSI_DISABLE(_pAd) -#endif // PCI_MSI_SUPPORT // - -#define SA_SHIRQ IRQF_SHARED - -#define RT28XX_IRQ_REQUEST(net_dev) \ -{ PRTMP_ADAPTER _pAd = (PRTMP_ADAPTER)((net_dev)->ml_priv); \ - POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ - RTMP_MSI_ENABLE(_pAd); \ - if ((retval = request_irq(_pObj->pci_dev->irq, \ - rt2860_interrupt, SA_SHIRQ, \ - (net_dev)->name, (net_dev)))) { \ - printk("RT2860: request_irq ERROR(%d)\n", retval); \ - return retval; } } - -#define RT28XX_IRQ_RELEASE(net_dev) \ -{ PRTMP_ADAPTER _pAd = (PRTMP_ADAPTER)((net_dev)->ml_priv); \ - POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ - synchronize_irq(_pObj->pci_dev->irq); \ - free_irq(_pObj->pci_dev->irq, (net_dev)); \ - RTMP_MSI_DISABLE(_pAd); } - -#define RT28XX_IRQ_INIT(pAd) \ - { pAd->int_enable_reg = ((DELAYINTMASK) | \ - (RxINT|TxDataInt|TxMgmtInt)) & ~(0x03); \ - pAd->int_disable_mask = 0; \ - pAd->int_pending = 0; } - -#define RT28XX_IRQ_ENABLE(pAd) \ - { /* clear garbage ints */ \ - RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, 0xffffffff); \ - NICEnableInterrupt(pAd); } - -#define RT28XX_PUT_DEVICE(dev_p) - - -/* ----------------- MLME Related MACRO ----------------- */ -#define RT28XX_MLME_HANDLER(pAd) MlmeHandler(pAd) - -#define RT28XX_MLME_PRE_SANITY_CHECK(pAd) - -#define RT28XX_MLME_STA_QUICK_RSP_WAKE_UP(pAd) \ - RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100); - -#define RT28XX_MLME_RESET_STATE_MACHINE(pAd) \ - MlmeRestartStateMachine(pAd) - -#define RT28XX_HANDLE_COUNTER_MEASURE(_pAd, _pEntry) \ - HandleCounterMeasure(_pAd, _pEntry) - -/* ----------------- Power Save Related MACRO ----------------- */ -#define RT28XX_PS_POLL_ENQUEUE(pAd) EnqueuePsPoll(pAd) - -// -// Device ID & Vendor ID, these values should match EEPROM value -// -#define NIC2860_PCI_DEVICE_ID 0x0601 -#define NIC2860_PCIe_DEVICE_ID 0x0681 -#define NIC2760_PCI_DEVICE_ID 0x0701 // 1T/2R Cardbus ??? -#define NIC2790_PCIe_DEVICE_ID 0x0781 // 1T/2R miniCard - -#define NIC_PCI_VENDOR_ID 0x1814 - -#define VEN_AWT_PCIe_DEVICE_ID 0x1059 -#define VEN_AWT_PCI_VENDOR_ID 0x1A3B - -#define EDIMAX_PCI_VENDOR_ID 0x1432 - -// For RTMPPCIePowerLinkCtrlRestore () function -#define RESTORE_HALT 1 -#define RESTORE_WAKEUP 2 -#define RESTORE_CLOSE 3 - -#define PowerSafeCID 1 -#define PowerRadioOffCID 2 -#define PowerWakeCID 3 -#define CID0MASK 0x000000ff -#define CID1MASK 0x0000ff00 -#define CID2MASK 0x00ff0000 -#define CID3MASK 0xff000000 - -#define PCI_REG_READ_WORD(pci_dev, offset, Configuration) \ - if (pci_read_config_word(pci_dev, offset, ®16) == 0) \ - Configuration = le2cpu16(reg16); \ - else \ - Configuration = 0; - -#define PCI_REG_WIRTE_WORD(pci_dev, offset, Configuration) \ - reg16 = cpu2le16(Configuration); \ - pci_write_config_word(pci_dev, offset, reg16); \ - -#define RT28XX_STA_FORCE_WAKEUP(pAd, Level) \ - RT28xxPciStaAsicForceWakeup(pAd, Level); - -#define RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp) \ - RT28xxPciStaAsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); - -#define RT28XX_MLME_RADIO_ON(pAd) \ - RT28xxPciMlmeRadioOn(pAd); - -#define RT28XX_MLME_RADIO_OFF(pAd) \ - RT28xxPciMlmeRadioOFF(pAd); - -#endif //__RT2860_H__ - diff --git a/drivers/staging/rt2860/rt28xx.h b/drivers/staging/rt2860/rt28xx.h deleted file mode 100644 index c08525002cc2d2ec964e2ab028966d6d655b6c5b..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2860/rt28xx.h +++ /dev/null @@ -1,1688 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rt28xx.h - - Abstract: - RT28xx ASIC related definition & structures - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Jan Lee Jan-3-2006 created for RT2860c -*/ - -#ifndef __RT28XX_H__ -#define __RT28XX_H__ - - -// -// PCI registers - base address 0x0000 -// -#define PCI_CFG 0x0000 -#define PCI_EECTRL 0x0004 -#define PCI_MCUCTRL 0x0008 - -typedef int NTSTATUS; - -#define OPT_14 0x114 - -// -// SCH/DMA registers - base address 0x0200 -// -// INT_SOURCE_CSR: Interrupt source register. Write one to clear corresponding bit -// -#define DMA_CSR0 0x200 -#define INT_SOURCE_CSR 0x200 -typedef union _INT_SOURCE_CSR_STRUC { - struct { - UINT32 RxDelayINT:1; - UINT32 TxDelayINT:1; - UINT32 RxDone:1; - UINT32 Ac0DmaDone:1;//4 - UINT32 Ac1DmaDone:1; - UINT32 Ac2DmaDone:1; - UINT32 Ac3DmaDone:1; - UINT32 HccaDmaDone:1; // bit7 - UINT32 MgmtDmaDone:1; - UINT32 MCUCommandINT:1;//bit 9 - UINT32 RxTxCoherent:1; - UINT32 TBTTInt:1; - UINT32 PreTBTT:1; - UINT32 TXFifoStatusInt:1;//FIFO Statistics is full, sw should read 0x171c - UINT32 AutoWakeup:1;//bit14 - UINT32 GPTimer:1; - UINT32 RxCoherent:1;//bit16 - UINT32 TxCoherent:1; - UINT32 :14; - } field; - UINT32 word; -} INT_SOURCE_CSR_STRUC, *PINT_SOURCE_CSR_STRUC; - -// -// INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF -// -#define INT_MASK_CSR 0x204 -typedef union _INT_MASK_CSR_STRUC { - struct { - UINT32 RXDelay_INT_MSK:1; - UINT32 TxDelay:1; - UINT32 RxDone:1; - UINT32 Ac0DmaDone:1; - UINT32 Ac1DmaDone:1; - UINT32 Ac2DmaDone:1; - UINT32 Ac3DmaDone:1; - UINT32 HccaDmaDone:1; - UINT32 MgmtDmaDone:1; - UINT32 MCUCommandINT:1; - UINT32 :20; - UINT32 RxCoherent:1; - UINT32 TxCoherent:1; - } field; - UINT32 word; -} INT_MASK_CSR_STRUC, *PINT_MASK_CSR_STRUC; - -#define WPDMA_GLO_CFG 0x208 -typedef union _WPDMA_GLO_CFG_STRUC { - struct { - UINT32 EnableTxDMA:1; - UINT32 TxDMABusy:1; - UINT32 EnableRxDMA:1; - UINT32 RxDMABusy:1; - UINT32 WPDMABurstSIZE:2; - UINT32 EnTXWriteBackDDONE:1; - UINT32 BigEndian:1; - UINT32 RXHdrScater:8; - UINT32 HDR_SEG_LEN:16; - } field; - UINT32 word; -} WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC; - -#define WPDMA_RST_IDX 0x20c -typedef union _WPDMA_RST_IDX_STRUC { - struct { - UINT32 RST_DTX_IDX0:1; - UINT32 RST_DTX_IDX1:1; - UINT32 RST_DTX_IDX2:1; - UINT32 RST_DTX_IDX3:1; - UINT32 RST_DTX_IDX4:1; - UINT32 RST_DTX_IDX5:1; - UINT32 rsv:10; - UINT32 RST_DRX_IDX0:1; - UINT32 :15; - } field; - UINT32 word; -} WPDMA_RST_IDX_STRUC, *PWPDMA_RST_IDX_STRUC; - -#define DELAY_INT_CFG 0x0210 -typedef union _DELAY_INT_CFG_STRUC { - struct { - UINT32 RXMAX_PTIME:8; - UINT32 RXMAX_PINT:7; - UINT32 RXDLY_INT_EN:1; - UINT32 TXMAX_PTIME:8; - UINT32 TXMAX_PINT:7; - UINT32 TXDLY_INT_EN:1; - } field; - UINT32 word; -} DELAY_INT_CFG_STRUC, *PDELAY_INT_CFG_STRUC; - -#define WMM_AIFSN_CFG 0x0214 -typedef union _AIFSN_CSR_STRUC { - struct { - UINT32 Aifsn0:4; // for AC_BE - UINT32 Aifsn1:4; // for AC_BK - UINT32 Aifsn2:4; // for AC_VI - UINT32 Aifsn3:4; // for AC_VO - UINT32 Rsv:16; - } field; - UINT32 word; -} AIFSN_CSR_STRUC, *PAIFSN_CSR_STRUC; - -// -// CWMIN_CSR: CWmin for each EDCA AC -// -#define WMM_CWMIN_CFG 0x0218 -typedef union _CWMIN_CSR_STRUC { - struct { - UINT32 Cwmin0:4; // for AC_BE - UINT32 Cwmin1:4; // for AC_BK - UINT32 Cwmin2:4; // for AC_VI - UINT32 Cwmin3:4; // for AC_VO - UINT32 Rsv:16; - } field; - UINT32 word; -} CWMIN_CSR_STRUC, *PCWMIN_CSR_STRUC; - -// -// CWMAX_CSR: CWmin for each EDCA AC -// -#define WMM_CWMAX_CFG 0x021c -typedef union _CWMAX_CSR_STRUC { - struct { - UINT32 Cwmax0:4; // for AC_BE - UINT32 Cwmax1:4; // for AC_BK - UINT32 Cwmax2:4; // for AC_VI - UINT32 Cwmax3:4; // for AC_VO - UINT32 Rsv:16; - } field; - UINT32 word; -} CWMAX_CSR_STRUC, *PCWMAX_CSR_STRUC; - -// -// AC_TXOP_CSR0: AC_BK/AC_BE TXOP register -// -#define WMM_TXOP0_CFG 0x0220 -typedef union _AC_TXOP_CSR0_STRUC { - struct { - USHORT Ac0Txop; // for AC_BK, in unit of 32us - USHORT Ac1Txop; // for AC_BE, in unit of 32us - } field; - UINT32 word; -} AC_TXOP_CSR0_STRUC, *PAC_TXOP_CSR0_STRUC; - -// -// AC_TXOP_CSR1: AC_VO/AC_VI TXOP register -// -#define WMM_TXOP1_CFG 0x0224 -typedef union _AC_TXOP_CSR1_STRUC { - struct { - USHORT Ac2Txop; // for AC_VI, in unit of 32us - USHORT Ac3Txop; // for AC_VO, in unit of 32us - } field; - UINT32 word; -} AC_TXOP_CSR1_STRUC, *PAC_TXOP_CSR1_STRUC; - -#define RINGREG_DIFF 0x10 -#define GPIO_CTRL_CFG 0x0228 //MAC_CSR13 -#define MCU_CMD_CFG 0x022c -#define TX_BASE_PTR0 0x0230 //AC_BK base address -#define TX_MAX_CNT0 0x0234 -#define TX_CTX_IDX0 0x0238 -#define TX_DTX_IDX0 0x023c -#define TX_BASE_PTR1 0x0240 //AC_BE base address -#define TX_MAX_CNT1 0x0244 -#define TX_CTX_IDX1 0x0248 -#define TX_DTX_IDX1 0x024c -#define TX_BASE_PTR2 0x0250 //AC_VI base address -#define TX_MAX_CNT2 0x0254 -#define TX_CTX_IDX2 0x0258 -#define TX_DTX_IDX2 0x025c -#define TX_BASE_PTR3 0x0260 //AC_VO base address -#define TX_MAX_CNT3 0x0264 -#define TX_CTX_IDX3 0x0268 -#define TX_DTX_IDX3 0x026c -#define TX_BASE_PTR4 0x0270 //HCCA base address -#define TX_MAX_CNT4 0x0274 -#define TX_CTX_IDX4 0x0278 -#define TX_DTX_IDX4 0x027c -#define TX_BASE_PTR5 0x0280 //MGMT base address -#define TX_MAX_CNT5 0x0284 -#define TX_CTX_IDX5 0x0288 -#define TX_DTX_IDX5 0x028c -#define TX_MGMTMAX_CNT TX_MAX_CNT5 -#define TX_MGMTCTX_IDX TX_CTX_IDX5 -#define TX_MGMTDTX_IDX TX_DTX_IDX5 -#define RX_BASE_PTR 0x0290 //RX base address -#define RX_MAX_CNT 0x0294 -#define RX_CRX_IDX 0x0298 -#define RX_DRX_IDX 0x029c -#define USB_DMA_CFG 0x02a0 - -typedef union _USB_DMA_CFG_STRUC { - struct { - UINT32 RxBulkAggTOut:8; //Rx Bulk Aggregation TimeOut in unit of 33ns - UINT32 RxBulkAggLmt:8; //Rx Bulk Aggregation Limit in unit of 256 bytes - UINT32 phyclear:1; //phy watch dog enable. write 1 - UINT32 rsv:2; - UINT32 TxClear:1; //Clear USB DMA TX path - UINT32 TxopHalt:1; //Halt TXOP count down when TX buffer is full. - UINT32 RxBulkAggEn:1; //Enable Rx Bulk Aggregation - UINT32 RxBulkEn:1; //Enable USB DMA Rx - UINT32 TxBulkEn:1; //Enable USB DMA Tx - UINT32 EpoutValid:6; //OUT endpoint data valid - UINT32 RxBusy:1; //USB DMA RX FSM busy - UINT32 TxBusy:1; //USB DMA TX FSM busy - } field; - UINT32 word; -} USB_DMA_CFG_STRUC, *PUSB_DMA_CFG_STRUC; - -// -// 3 PBF registers -// -// -// Most are for debug. Driver doesn't touch PBF register. -#define PBF_SYS_CTRL 0x0400 -#define PBF_CFG 0x0408 -#define PBF_MAX_PCNT 0x040C -#define PBF_CTRL 0x0410 -#define PBF_INT_STA 0x0414 -#define PBF_INT_ENA 0x0418 -#define TXRXQ_PCNT 0x0438 -#define PBF_DBG 0x043c -#define PBF_CAP_CTRL 0x0440 - -// eFuse registers -#define EFUSE_CTRL 0x0580 -#define EFUSE_DATA0 0x0590 -#define EFUSE_DATA1 0x0594 -#define EFUSE_DATA2 0x0598 -#define EFUSE_DATA3 0x059c -#define EFUSE_USAGE_MAP_START 0x2d0 -#define EFUSE_USAGE_MAP_END 0x2fc -#define EFUSE_TAG 0x2fe -#define EFUSE_USAGE_MAP_SIZE 45 - -typedef union _EFUSE_CTRL_STRUC { - struct { - UINT32 EFSROM_AOUT:6; - UINT32 EFSROM_MODE:2; - UINT32 EFSROM_LDO_OFF_TIME:6; - UINT32 EFSROM_LDO_ON_TIME:2; - UINT32 EFSROM_AIN:10; - UINT32 RESERVED:4; - UINT32 EFSROM_KICK:1; - UINT32 SEL_EFUSE:1; - } field; - UINT32 word; -} EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC; - -#define LDO_CFG0 0x05d4 -#define GPIO_SWITCH 0x05dc - -// -// 4 MAC registers -// -// -// 4.1 MAC SYSTEM configuration registers (offset:0x1000) -// -#define MAC_CSR0 0x1000 -typedef union _ASIC_VER_ID_STRUC { - struct { - USHORT ASICRev; // reversion : 0 - USHORT ASICVer; // version : 2860 - } field; - UINT32 word; -} ASIC_VER_ID_STRUC, *PASIC_VER_ID_STRUC; - -#define MAC_SYS_CTRL 0x1004 //MAC_CSR1 -#define MAC_ADDR_DW0 0x1008 // MAC ADDR DW0 -#define MAC_ADDR_DW1 0x100c // MAC ADDR DW1 -// -// MAC_CSR2: STA MAC register 0 -// -typedef union _MAC_DW0_STRUC { - struct { - UCHAR Byte0; // MAC address byte 0 - UCHAR Byte1; // MAC address byte 1 - UCHAR Byte2; // MAC address byte 2 - UCHAR Byte3; // MAC address byte 3 - } field; - UINT32 word; -} MAC_DW0_STRUC, *PMAC_DW0_STRUC; - -// -// MAC_CSR3: STA MAC register 1 -// -typedef union _MAC_DW1_STRUC { - struct { - UCHAR Byte4; // MAC address byte 4 - UCHAR Byte5; // MAC address byte 5 - UCHAR U2MeMask; - UCHAR Rsvd1; - } field; - UINT32 word; -} MAC_DW1_STRUC, *PMAC_DW1_STRUC; - -#define MAC_BSSID_DW0 0x1010 // MAC BSSID DW0 -#define MAC_BSSID_DW1 0x1014 // MAC BSSID DW1 - -// -// MAC_CSR5: BSSID register 1 -// -typedef union _MAC_CSR5_STRUC { - struct { - UCHAR Byte4; // BSSID byte 4 - UCHAR Byte5; // BSSID byte 5 - USHORT BssIdMask:2; // 0: one BSSID, 10: 4 BSSID, 01: 2 BSSID , 11: 8BSSID - USHORT MBssBcnNum:3; - USHORT Rsvd:11; - } field; - UINT32 word; -} MAC_CSR5_STRUC, *PMAC_CSR5_STRUC; - -#define MAX_LEN_CFG 0x1018 // rt2860b max 16k bytes. bit12:13 Maximum PSDU length (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 -#define BBP_CSR_CFG 0x101c // -// -// BBP_CSR_CFG: BBP serial control register -// -typedef union _BBP_CSR_CFG_STRUC { - struct { - UINT32 Value:8; // Register value to program into BBP - UINT32 RegNum:8; // Selected BBP register - UINT32 fRead:1; // 0: Write BBP, 1: Read BBP - UINT32 Busy:1; // 1: ASIC is busy execute BBP programming. - UINT32 BBP_PAR_DUR:1; // 0: 4 MAC clock cycles 1: 8 MAC clock cycles - UINT32 BBP_RW_MODE:1; // 0: use serial mode 1:parallel - UINT32 :12; - } field; - UINT32 word; -} BBP_CSR_CFG_STRUC, *PBBP_CSR_CFG_STRUC; - -#define RF_CSR_CFG0 0x1020 -// -// RF_CSR_CFG: RF control register -// -typedef union _RF_CSR_CFG0_STRUC { - struct { - UINT32 RegIdAndContent:24; // Register value to program into BBP - UINT32 bitwidth:5; // Selected BBP register - UINT32 StandbyMode:1; // 0: high when stand by 1: low when standby - UINT32 Sel:1; // 0:RF_LE0 activate 1:RF_LE1 activate - UINT32 Busy:1; // 0: idle 1: 8busy - } field; - UINT32 word; -} RF_CSR_CFG0_STRUC, *PRF_CSR_CFG0_STRUC; - -#define RF_CSR_CFG1 0x1024 -typedef union _RF_CSR_CFG1_STRUC { - struct { - UINT32 RegIdAndContent:24; // Register value to program into BBP - UINT32 RFGap:5; // Gap between BB_CONTROL_RF and RF_LE. 0: 3 system clock cycle (37.5usec) 1: 5 system clock cycle (62.5usec) - UINT32 rsv:7; // 0: idle 1: 8busy - } field; - UINT32 word; -} RF_CSR_CFG1_STRUC, *PRF_CSR_CFG1_STRUC; - -#define RF_CSR_CFG2 0x1028 // -typedef union _RF_CSR_CFG2_STRUC { - struct { - UINT32 RegIdAndContent:24; // Register value to program into BBP - UINT32 rsv:8; // 0: idle 1: 8busy - } field; - UINT32 word; -} RF_CSR_CFG2_STRUC, *PRF_CSR_CFG2_STRUC; - -#define LED_CFG 0x102c // MAC_CSR14 -typedef union _LED_CFG_STRUC { - struct { - UINT32 OnPeriod:8; // blinking on period unit 1ms - UINT32 OffPeriod:8; // blinking off period unit 1ms - UINT32 SlowBlinkPeriod:6; // slow blinking period. unit:1ms - UINT32 rsv:2; - UINT32 RLedMode:2; // red Led Mode 0: off1: blinking upon TX2: periodic slow blinking3: always on - UINT32 GLedMode:2; // green Led Mode - UINT32 YLedMode:2; // yellow Led Mode - UINT32 LedPolar:1; // Led Polarity. 0: active low1: active high - UINT32 :1; - } field; - UINT32 word; -} LED_CFG_STRUC, *PLED_CFG_STRUC; - -// -// 4.2 MAC TIMING configuration registers (offset:0x1100) -// -#define XIFS_TIME_CFG 0x1100 // MAC_CSR8 MAC_CSR9 -typedef union _IFS_SLOT_CFG_STRUC { - struct { - UINT32 CckmSifsTime:8; // unit 1us. Applied after CCK RX/TX - UINT32 OfdmSifsTime:8; // unit 1us. Applied after OFDM RX/TX - UINT32 OfdmXifsTime:4; //OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND - UINT32 EIFS:9; // unit 1us - UINT32 BBRxendEnable:1; // reference RXEND signal to begin XIFS defer - UINT32 rsv:2; - } field; - UINT32 word; -} IFS_SLOT_CFG_STRUC, *PIFS_SLOT_CFG_STRUC; - -#define BKOFF_SLOT_CFG 0x1104 // mac_csr9 last 8 bits -#define NAV_TIME_CFG 0x1108 // NAV (MAC_CSR15) -#define CH_TIME_CFG 0x110C // Count as channel busy -#define PBF_LIFE_TIMER 0x1110 //TX/RX MPDU timestamp timer (free run)Unit: 1us -#define BCN_TIME_CFG 0x1114 // TXRX_CSR9 - -#define BCN_OFFSET0 0x042C -#define BCN_OFFSET1 0x0430 - -// -// BCN_TIME_CFG : Synchronization control register -// -typedef union _BCN_TIME_CFG_STRUC { - struct { - UINT32 BeaconInterval:16; // in unit of 1/16 TU - UINT32 bTsfTicking:1; // Enable TSF auto counting - UINT32 TsfSyncMode:2; // Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode - UINT32 bTBTTEnable:1; - UINT32 bBeaconGen:1; // Enable beacon generator - UINT32 :3; - UINT32 TxTimestampCompensate:8; - } field; - UINT32 word; -} BCN_TIME_CFG_STRUC, *PBCN_TIME_CFG_STRUC; - -#define TBTT_SYNC_CFG 0x1118 // txrx_csr10 -#define TSF_TIMER_DW0 0x111C // Local TSF timer lsb 32 bits. Read-only -#define TSF_TIMER_DW1 0x1120 // msb 32 bits. Read-only. -#define TBTT_TIMER 0x1124 // TImer remains till next TBTT. Read-only. TXRX_CSR14 -#define INT_TIMER_CFG 0x1128 // -#define INT_TIMER_EN 0x112c // GP-timer and pre-tbtt Int enable -#define CH_IDLE_STA 0x1130 // channel idle time -#define CH_BUSY_STA 0x1134 // channle busy time -// -// 4.2 MAC POWER configuration registers (offset:0x1200) -// -#define MAC_STATUS_CFG 0x1200 // old MAC_CSR12 -#define PWR_PIN_CFG 0x1204 // old MAC_CSR12 -#define AUTO_WAKEUP_CFG 0x1208 // old MAC_CSR10 -// -// AUTO_WAKEUP_CFG: Manual power control / status register -// -typedef union _AUTO_WAKEUP_STRUC { - struct { - UINT32 AutoLeadTime:8; - UINT32 NumofSleepingTbtt:7; // ForceWake has high privilege than PutToSleep when both set - UINT32 EnableAutoWakeup:1; // 0:sleep, 1:awake - UINT32 :16; - } field; - UINT32 word; -} AUTO_WAKEUP_STRUC, *PAUTO_WAKEUP_STRUC; - -// -// 4.3 MAC TX configuration registers (offset:0x1300) -// - -#define EDCA_AC0_CFG 0x1300 //AC_TXOP_CSR0 0x3474 -#define EDCA_AC1_CFG 0x1304 -#define EDCA_AC2_CFG 0x1308 -#define EDCA_AC3_CFG 0x130c -typedef union _EDCA_AC_CFG_STRUC { - struct { - UINT32 AcTxop:8; // in unit of 32us - UINT32 Aifsn:4; // # of slot time - UINT32 Cwmin:4; // - UINT32 Cwmax:4; //unit power of 2 - UINT32 :12; // - } field; - UINT32 word; -} EDCA_AC_CFG_STRUC, *PEDCA_AC_CFG_STRUC; - -#define EDCA_TID_AC_MAP 0x1310 -#define TX_PWR_CFG_0 0x1314 -#define TX_PWR_CFG_1 0x1318 -#define TX_PWR_CFG_2 0x131C -#define TX_PWR_CFG_3 0x1320 -#define TX_PWR_CFG_4 0x1324 -#define TX_PIN_CFG 0x1328 -#define TX_BAND_CFG 0x132c // 0x1 use upper 20MHz. 0 juse lower 20MHz -#define TX_SW_CFG0 0x1330 -#define TX_SW_CFG1 0x1334 -#define TX_SW_CFG2 0x1338 -#define TXOP_THRES_CFG 0x133c -#define TXOP_CTRL_CFG 0x1340 -#define TX_RTS_CFG 0x1344 - -typedef union _TX_RTS_CFG_STRUC { - struct { - UINT32 AutoRtsRetryLimit:8; - UINT32 RtsThres:16; // unit:byte - UINT32 RtsFbkEn:1; // enable rts rate fallback - UINT32 rsv:7; // 1: HT non-STBC control frame enable - } field; - UINT32 word; -} TX_RTS_CFG_STRUC, *PTX_RTS_CFG_STRUC; - -#define TX_TIMEOUT_CFG 0x1348 -typedef union _TX_TIMEOUT_CFG_STRUC { - struct { - UINT32 rsv:4; - UINT32 MpduLifeTime:4; // expiration time = 2^(9+MPDU LIFE TIME) us - UINT32 RxAckTimeout:8; // unit:slot. Used for TX precedure - UINT32 TxopTimeout:8; //TXOP timeout value for TXOP truncation. It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) - UINT32 rsv2:8; // 1: HT non-STBC control frame enable - } field; - UINT32 word; -} TX_TIMEOUT_CFG_STRUC, *PTX_TIMEOUT_CFG_STRUC; - -#define TX_RTY_CFG 0x134c -typedef union PACKED _TX_RTY_CFG_STRUC { - struct { - UINT32 ShortRtyLimit:8; // short retry limit - UINT32 LongRtyLimit:8; //long retry limit - UINT32 LongRtyThre:12; // Long retry threshoold - UINT32 NonAggRtyMode:1; // Non-Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer - UINT32 AggRtyMode:1; // Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer - UINT32 TxautoFBEnable:1; // Tx retry PHY rate auto fallback enable - UINT32 rsv:1; // 1: HT non-STBC control frame enable - } field; - UINT32 word; -} TX_RTY_CFG_STRUC, *PTX_RTY_CFG_STRUC; - -#define TX_LINK_CFG 0x1350 -typedef union PACKED _TX_LINK_CFG_STRUC { - struct PACKED { - UINT32 RemoteMFBLifeTime:8; //remote MFB life time. unit : 32us - UINT32 MFBEnable:1; // TX apply remote MFB 1:enable - UINT32 RemoteUMFSEnable:1; // remote unsolicit MFB enable. 0: not apply remote remote unsolicit (MFS=7) - UINT32 TxMRQEn:1; // MCS request TX enable - UINT32 TxRDGEn:1; // RDG TX enable - UINT32 TxCFAckEn:1; // Piggyback CF-ACK enable - UINT32 rsv:3; // - UINT32 RemotMFB:8; // remote MCS feedback - UINT32 RemotMFS:8; //remote MCS feedback sequence number - } field; - UINT32 word; -} TX_LINK_CFG_STRUC, *PTX_LINK_CFG_STRUC; - -#define HT_FBK_CFG0 0x1354 -typedef union PACKED _HT_FBK_CFG0_STRUC { - struct { - UINT32 HTMCS0FBK:4; - UINT32 HTMCS1FBK:4; - UINT32 HTMCS2FBK:4; - UINT32 HTMCS3FBK:4; - UINT32 HTMCS4FBK:4; - UINT32 HTMCS5FBK:4; - UINT32 HTMCS6FBK:4; - UINT32 HTMCS7FBK:4; - } field; - UINT32 word; -} HT_FBK_CFG0_STRUC, *PHT_FBK_CFG0_STRUC; - -#define HT_FBK_CFG1 0x1358 -typedef union _HT_FBK_CFG1_STRUC { - struct { - UINT32 HTMCS8FBK:4; - UINT32 HTMCS9FBK:4; - UINT32 HTMCS10FBK:4; - UINT32 HTMCS11FBK:4; - UINT32 HTMCS12FBK:4; - UINT32 HTMCS13FBK:4; - UINT32 HTMCS14FBK:4; - UINT32 HTMCS15FBK:4; - } field; - UINT32 word; -} HT_FBK_CFG1_STRUC, *PHT_FBK_CFG1_STRUC; - -#define LG_FBK_CFG0 0x135c -typedef union _LG_FBK_CFG0_STRUC { - struct { - UINT32 OFDMMCS0FBK:4; //initial value is 0 - UINT32 OFDMMCS1FBK:4; //initial value is 0 - UINT32 OFDMMCS2FBK:4; //initial value is 1 - UINT32 OFDMMCS3FBK:4; //initial value is 2 - UINT32 OFDMMCS4FBK:4; //initial value is 3 - UINT32 OFDMMCS5FBK:4; //initial value is 4 - UINT32 OFDMMCS6FBK:4; //initial value is 5 - UINT32 OFDMMCS7FBK:4; //initial value is 6 - } field; - UINT32 word; -} LG_FBK_CFG0_STRUC, *PLG_FBK_CFG0_STRUC; - -#define LG_FBK_CFG1 0x1360 -typedef union _LG_FBK_CFG1_STRUC { - struct { - UINT32 CCKMCS0FBK:4; //initial value is 0 - UINT32 CCKMCS1FBK:4; //initial value is 0 - UINT32 CCKMCS2FBK:4; //initial value is 1 - UINT32 CCKMCS3FBK:4; //initial value is 2 - UINT32 rsv:16; - } field; - UINT32 word; -} LG_FBK_CFG1_STRUC, *PLG_FBK_CFG1_STRUC; - -//======================================================= -//================ Protection Paramater================================ -//======================================================= -#define CCK_PROT_CFG 0x1364 //CCK Protection -#define ASIC_SHORTNAV 1 -#define ASIC_LONGNAV 2 -#define ASIC_RTS 1 -#define ASIC_CTS 2 -typedef union _PROT_CFG_STRUC { - struct { - UINT32 ProtectRate:16; //Protection control frame rate for CCK TX(RTS/CTS/CFEnd). - UINT32 ProtectCtrl:2; //Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv - UINT32 ProtectNav:2; //TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect, 2:LongNAVProtect, 3:rsv - UINT32 TxopAllowCck:1; //CCK TXOP allowance.0:disallow. - UINT32 TxopAllowOfdm:1; //CCK TXOP allowance.0:disallow. - UINT32 TxopAllowMM20:1; //CCK TXOP allowance. 0:disallow. - UINT32 TxopAllowMM40:1; //CCK TXOP allowance.0:disallow. - UINT32 TxopAllowGF20:1; //CCK TXOP allowance.0:disallow. - UINT32 TxopAllowGF40:1; //CCK TXOP allowance.0:disallow. - UINT32 RTSThEn:1; //RTS threshold enable on CCK TX - UINT32 rsv:5; - } field; - UINT32 word; -} PROT_CFG_STRUC, *PPROT_CFG_STRUC; - -#define OFDM_PROT_CFG 0x1368 //OFDM Protection -#define MM20_PROT_CFG 0x136C //MM20 Protection -#define MM40_PROT_CFG 0x1370 //MM40 Protection -#define GF20_PROT_CFG 0x1374 //GF20 Protection -#define GF40_PROT_CFG 0x1378 //GR40 Protection -#define EXP_CTS_TIME 0x137C // -#define EXP_ACK_TIME 0x1380 // - -// -// 4.4 MAC RX configuration registers (offset:0x1400) -// -#define RX_FILTR_CFG 0x1400 //TXRX_CSR0 -#define AUTO_RSP_CFG 0x1404 //TXRX_CSR4 -// -// TXRX_CSR4: Auto-Responder/ -// -typedef union _AUTO_RSP_CFG_STRUC { - struct { - UINT32 AutoResponderEnable:1; - UINT32 BACAckPolicyEnable:1; // 0:long, 1:short preamble - UINT32 CTS40MMode:1; // Response CTS 40MHz duplicate mode - UINT32 CTS40MRef:1; // Response CTS 40MHz duplicate mode - UINT32 AutoResponderPreamble:1; // 0:long, 1:short preamble - UINT32 rsv:1; // Power bit value in conrtrol frame - UINT32 DualCTSEn:1; // Power bit value in conrtrol frame - UINT32 AckCtsPsmBit:1; // Power bit value in conrtrol frame - UINT32 :24; - } field; - UINT32 word; -} AUTO_RSP_CFG_STRUC, *PAUTO_RSP_CFG_STRUC; - -#define LEGACY_BASIC_RATE 0x1408 // TXRX_CSR5 0x3054 -#define HT_BASIC_RATE 0x140c -#define HT_CTRL_CFG 0x1410 -#define SIFS_COST_CFG 0x1414 -#define RX_PARSER_CFG 0x1418 //Set NAV for all received frames - -// -// 4.5 MAC Security configuration (offset:0x1500) -// -#define TX_SEC_CNT0 0x1500 // -#define RX_SEC_CNT0 0x1504 // -#define CCMP_FC_MUTE 0x1508 // -// -// 4.6 HCCA/PSMP (offset:0x1600) -// -#define TXOP_HLDR_ADDR0 0x1600 -#define TXOP_HLDR_ADDR1 0x1604 -#define TXOP_HLDR_ET 0x1608 -#define QOS_CFPOLL_RA_DW0 0x160c -#define QOS_CFPOLL_A1_DW1 0x1610 -#define QOS_CFPOLL_QC 0x1614 -// -// 4.7 MAC Statistis registers (offset:0x1700) -// -#define RX_STA_CNT0 0x1700 // -#define RX_STA_CNT1 0x1704 // -#define RX_STA_CNT2 0x1708 // - -// -// RX_STA_CNT0_STRUC: RX PLCP error count & RX CRC error count -// -typedef union _RX_STA_CNT0_STRUC { - struct { - USHORT CrcErr; - USHORT PhyErr; - } field; - UINT32 word; -} RX_STA_CNT0_STRUC, *PRX_STA_CNT0_STRUC; - -// -// RX_STA_CNT1_STRUC: RX False CCA count & RX LONG frame count -// -typedef union _RX_STA_CNT1_STRUC { - struct { - USHORT FalseCca; - USHORT PlcpErr; - } field; - UINT32 word; -} RX_STA_CNT1_STRUC, *PRX_STA_CNT1_STRUC; - -// -// RX_STA_CNT2_STRUC: -// -typedef union _RX_STA_CNT2_STRUC { - struct { - USHORT RxDupliCount; - USHORT RxFifoOverflowCount; - } field; - UINT32 word; -} RX_STA_CNT2_STRUC, *PRX_STA_CNT2_STRUC; - -#define TX_STA_CNT0 0x170C // -// -// STA_CSR3: TX Beacon count -// -typedef union _TX_STA_CNT0_STRUC { - struct { - USHORT TxFailCount; - USHORT TxBeaconCount; - } field; - UINT32 word; -} TX_STA_CNT0_STRUC, *PTX_STA_CNT0_STRUC; - -#define TX_STA_CNT1 0x1710 // -// -// TX_STA_CNT1: TX tx count -// -typedef union _TX_STA_CNT1_STRUC { - struct { - USHORT TxSuccess; - USHORT TxRetransmit; - } field; - UINT32 word; -} TX_STA_CNT1_STRUC, *PTX_STA_CNT1_STRUC; - -#define TX_STA_CNT2 0x1714 // -// -// TX_STA_CNT2: TX tx count -// -typedef union _TX_STA_CNT2_STRUC { - struct { - USHORT TxZeroLenCount; - USHORT TxUnderFlowCount; - } field; - UINT32 word; -} TX_STA_CNT2_STRUC, *PTX_STA_CNT2_STRUC; - -#define TX_STA_FIFO 0x1718 // -// -// TX_STA_FIFO_STRUC: TX Result for specific PID status fifo register -// -typedef union PACKED _TX_STA_FIFO_STRUC { - struct { - UINT32 bValid:1; // 1:This register contains a valid TX result - UINT32 PidType:4; - UINT32 TxSuccess:1; // Tx No retry success - UINT32 TxAggre:1; // Tx Retry Success - UINT32 TxAckRequired:1; // Tx fail - UINT32 wcid:8; //wireless client index -// UINT32 SuccessRate:16; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. - UINT32 SuccessRate:13; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. - UINT32 TxBF:1; - UINT32 Reserve:2; - } field; - UINT32 word; -} TX_STA_FIFO_STRUC, *PTX_STA_FIFO_STRUC; - -// Debug counter -#define TX_AGG_CNT 0x171c -typedef union _TX_AGG_CNT_STRUC { - struct { - USHORT NonAggTxCount; - USHORT AggTxCount; - } field; - UINT32 word; -} TX_AGG_CNT_STRUC, *PTX_AGG_CNT_STRUC; - -// Debug counter -#define TX_AGG_CNT0 0x1720 -typedef union _TX_AGG_CNT0_STRUC { - struct { - USHORT AggSize1Count; - USHORT AggSize2Count; - } field; - UINT32 word; -} TX_AGG_CNT0_STRUC, *PTX_AGG_CNT0_STRUC; - -// Debug counter -#define TX_AGG_CNT1 0x1724 -typedef union _TX_AGG_CNT1_STRUC { - struct { - USHORT AggSize3Count; - USHORT AggSize4Count; - } field; - UINT32 word; -} TX_AGG_CNT1_STRUC, *PTX_AGG_CNT1_STRUC; - -#define TX_AGG_CNT2 0x1728 -typedef union _TX_AGG_CNT2_STRUC { - struct { - USHORT AggSize5Count; - USHORT AggSize6Count; - } field; - UINT32 word; -} TX_AGG_CNT2_STRUC, *PTX_AGG_CNT2_STRUC; - -// Debug counter -#define TX_AGG_CNT3 0x172c -typedef union _TX_AGG_CNT3_STRUC { - struct { - USHORT AggSize7Count; - USHORT AggSize8Count; - } field; - UINT32 word; -} TX_AGG_CNT3_STRUC, *PTX_AGG_CNT3_STRUC; - -// Debug counter -#define TX_AGG_CNT4 0x1730 -typedef union _TX_AGG_CNT4_STRUC { - struct { - USHORT AggSize9Count; - USHORT AggSize10Count; - } field; - UINT32 word; -} TX_AGG_CNT4_STRUC, *PTX_AGG_CNT4_STRUC; - -#define TX_AGG_CNT5 0x1734 -typedef union _TX_AGG_CNT5_STRUC { - struct { - USHORT AggSize11Count; - USHORT AggSize12Count; - } field; - UINT32 word; -} TX_AGG_CNT5_STRUC, *PTX_AGG_CNT5_STRUC; - -#define TX_AGG_CNT6 0x1738 -typedef union _TX_AGG_CNT6_STRUC { - struct { - USHORT AggSize13Count; - USHORT AggSize14Count; - } field; - UINT32 word; -} TX_AGG_CNT6_STRUC, *PTX_AGG_CNT6_STRUC; - -#define TX_AGG_CNT7 0x173c -typedef union _TX_AGG_CNT7_STRUC { - struct { - USHORT AggSize15Count; - USHORT AggSize16Count; - } field; - UINT32 word; -} TX_AGG_CNT7_STRUC, *PTX_AGG_CNT7_STRUC; - -#define MPDU_DENSITY_CNT 0x1740 -typedef union _MPDU_DEN_CNT_STRUC { - struct { - USHORT TXZeroDelCount; //TX zero length delimiter count - USHORT RXZeroDelCount; //RX zero length delimiter count - } field; - UINT32 word; -} MPDU_DEN_CNT_STRUC, *PMPDU_DEN_CNT_STRUC; - -// -// TXRX control registers - base address 0x3000 -// -// rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. -#define TXRX_CSR1 0x77d0 - -// -// Security key table memory, base address = 0x1000 -// -#define MAC_WCID_BASE 0x1800 //8-bytes(use only 6-bytes) * 256 entry = -#define HW_WCID_ENTRY_SIZE 8 -#define PAIRWISE_KEY_TABLE_BASE 0x4000 // 32-byte * 256-entry = -byte -#define HW_KEY_ENTRY_SIZE 0x20 -#define PAIRWISE_IVEIV_TABLE_BASE 0x6000 // 8-byte * 256-entry = -byte -#define MAC_IVEIV_TABLE_BASE 0x6000 // 8-byte * 256-entry = -byte -#define HW_IVEIV_ENTRY_SIZE 8 -#define MAC_WCID_ATTRIBUTE_BASE 0x6800 // 4-byte * 256-entry = -byte -#define HW_WCID_ATTRI_SIZE 4 -#define WCID_RESERVED 0x6bfc -#define SHARED_KEY_TABLE_BASE 0x6c00 // 32-byte * 16-entry = 512-byte -#define SHARED_KEY_MODE_BASE 0x7000 // 32-byte * 16-entry = 512-byte -#define HW_SHARED_KEY_MODE_SIZE 4 -#define SHAREDKEYTABLE 0 -#define PAIRWISEKEYTABLE 1 - -typedef union _SHAREDKEY_MODE_STRUC { - struct { - UINT32 Bss0Key0CipherAlg:3; - UINT32 :1; - UINT32 Bss0Key1CipherAlg:3; - UINT32 :1; - UINT32 Bss0Key2CipherAlg:3; - UINT32 :1; - UINT32 Bss0Key3CipherAlg:3; - UINT32 :1; - UINT32 Bss1Key0CipherAlg:3; - UINT32 :1; - UINT32 Bss1Key1CipherAlg:3; - UINT32 :1; - UINT32 Bss1Key2CipherAlg:3; - UINT32 :1; - UINT32 Bss1Key3CipherAlg:3; - UINT32 :1; - } field; - UINT32 word; -} SHAREDKEY_MODE_STRUC, *PSHAREDKEY_MODE_STRUC; - -// 64-entry for pairwise key table -typedef struct _HW_WCID_ENTRY { // 8-byte per entry - UCHAR Address[6]; - UCHAR Rsv[2]; -} HW_WCID_ENTRY, PHW_WCID_ENTRY; - - - -// -// Other on-chip shared memory space, base = 0x2000 -// - -// CIS space - base address = 0x2000 -#define HW_CIS_BASE 0x2000 - -// Carrier-sense CTS frame base address. It's where mac stores carrier-sense frame for carrier-sense function. -#define HW_CS_CTS_BASE 0x7700 -// DFS CTS frame base address. It's where mac stores CTS frame for DFS. -#define HW_DFS_CTS_BASE 0x7780 -#define HW_CTS_FRAME_SIZE 0x80 - -// 2004-11-08 john - since NULL frame won't be that long (256 byte). We steal 16 tail bytes -// to save debugging settings -#define HW_DEBUG_SETTING_BASE 0x77f0 // 0x77f0~0x77ff total 16 bytes -#define HW_DEBUG_SETTING_BASE2 0x7770 // 0x77f0~0x77ff total 16 bytes - -// In order to support maximum 8 MBSS and its maximum length is 512 for each beacon -// Three section discontinue memory segments will be used. -// 1. The original region for BCN 0~3 -// 2. Extract memory from FCE table for BCN 4~5 -// 3. Extract memory from Pair-wise key table for BCN 6~7 -// It occupied those memory of wcid 238~253 for BCN 6 -// and wcid 222~237 for BCN 7 -#define HW_BEACON_MAX_SIZE 0x1000 /* unit: byte */ -#define HW_BEACON_BASE0 0x7800 -#define HW_BEACON_BASE1 0x7A00 -#define HW_BEACON_BASE2 0x7C00 -#define HW_BEACON_BASE3 0x7E00 -#define HW_BEACON_BASE4 0x7200 -#define HW_BEACON_BASE5 0x7400 -#define HW_BEACON_BASE6 0x5DC0 -#define HW_BEACON_BASE7 0x5BC0 - -#define HW_BEACON_MAX_COUNT 8 -#define HW_BEACON_OFFSET 0x0200 -#define HW_BEACON_CONTENT_LEN (HW_BEACON_OFFSET - TXWI_SIZE) - -// HOST-MCU shared memory - base address = 0x2100 -#define HOST_CMD_CSR 0x404 -#define H2M_MAILBOX_CSR 0x7010 -#define H2M_MAILBOX_CID 0x7014 -#define H2M_MAILBOX_STATUS 0x701c -#define H2M_INT_SRC 0x7024 -#define H2M_BBP_AGENT 0x7028 -#define M2H_CMD_DONE_CSR 0x000c -#define MCU_TXOP_ARRAY_BASE 0x000c // TODO: to be provided by Albert -#define MCU_TXOP_ENTRY_SIZE 32 // TODO: to be provided by Albert -#define MAX_NUM_OF_TXOP_ENTRY 16 // TODO: must be same with 8051 firmware -#define MCU_MBOX_VERSION 0x01 // TODO: to be confirmed by Albert -#define MCU_MBOX_VERSION_OFFSET 5 // TODO: to be provided by Albert - -// -// Host DMA registers - base address 0x200 . TX0-3=EDCAQid0-3, TX4=HCCA, TX5=MGMT, -// -// -// DMA RING DESCRIPTOR -// -#define E2PROM_CSR 0x0004 -#define IO_CNTL_CSR 0x77d0 - -#ifdef RT2860 -// 8051 firmware image for RT2860 - base address = 0x4000 -#define FIRMWARE_IMAGE_BASE 0x2000 -#define MAX_FIRMWARE_IMAGE_SIZE 0x2000 // 8kbyte -#endif -#ifdef RT2870 -// 8051 firmware image for usb - use last-half base address = 0x3000 -#define FIRMWARE_IMAGE_BASE 0x3000 -#define MAX_FIRMWARE_IMAGE_SIZE 0x1000 // 4kbyte -#endif // RT2870 // - -// ================================================================ -// Tx / Rx / Mgmt ring descriptor definition -// ================================================================ - -// the following PID values are used to mark outgoing frame type in TXD->PID so that -// proper TX statistics can be collected based on these categories -// b3-2 of PID field - -#define PID_MGMT 0x05 -#define PID_BEACON 0x0c -#define PID_DATA_NORMALUCAST 0x02 -#define PID_DATA_AMPDU 0x04 -#define PID_DATA_NO_ACK 0x08 -#define PID_DATA_NOT_NORM_ACK 0x03 -// value domain of pTxD->HostQId (4-bit: 0~15) -#define QID_AC_BK 1 // meet ACI definition in 802.11e -#define QID_AC_BE 0 // meet ACI definition in 802.11e -#define QID_AC_VI 2 -#define QID_AC_VO 3 -#define QID_HCCA 4 -#define NUM_OF_TX_RING 5 -#define QID_MGMT 13 -#define QID_RX 14 -#define QID_OTHER 15 - - -// ------------------------------------------------------ -// BBP & RF definition -// ------------------------------------------------------ -#define BUSY 1 -#define IDLE 0 - -#define RF_R00 0 -#define RF_R01 1 -#define RF_R02 2 -#define RF_R03 3 -#define RF_R04 4 -#define RF_R05 5 -#define RF_R06 6 -#define RF_R07 7 -#define RF_R08 8 -#define RF_R09 9 -#define RF_R10 10 -#define RF_R11 11 -#define RF_R12 12 -#define RF_R13 13 -#define RF_R14 14 -#define RF_R15 15 -#define RF_R16 16 -#define RF_R17 17 -#define RF_R18 18 -#define RF_R19 19 -#define RF_R20 20 -#define RF_R21 21 -#define RF_R22 22 -#define RF_R23 23 -#define RF_R24 24 -#define RF_R25 25 -#define RF_R26 26 -#define RF_R27 27 -#define RF_R28 28 -#define RF_R29 29 -#define RF_R30 30 -#define RF_R31 31 - -#define BBP_R0 0 // version -#define BBP_R1 1 // TSSI -#define BBP_R2 2 // TX configure -#define BBP_R3 3 -#define BBP_R4 4 -#define BBP_R5 5 -#define BBP_R6 6 -#define BBP_R14 14 // RX configure -#define BBP_R16 16 -#define BBP_R17 17 // RX sensibility -#define BBP_R18 18 -#define BBP_R21 21 -#define BBP_R22 22 -#define BBP_R24 24 -#define BBP_R25 25 -#define BBP_R31 31 -#define BBP_R49 49 //TSSI -#define BBP_R50 50 -#define BBP_R51 51 -#define BBP_R52 52 -#define BBP_R55 55 -#define BBP_R62 62 // Rx SQ0 Threshold HIGH -#define BBP_R63 63 -#define BBP_R64 64 -#define BBP_R65 65 -#define BBP_R66 66 -#define BBP_R67 67 -#define BBP_R68 68 -#define BBP_R69 69 -#define BBP_R70 70 // Rx AGC SQ CCK Xcorr threshold -#define BBP_R73 73 -#define BBP_R75 75 -#define BBP_R77 77 -#define BBP_R79 79 -#define BBP_R80 80 -#define BBP_R81 81 -#define BBP_R82 82 -#define BBP_R83 83 -#define BBP_R84 84 -#define BBP_R86 86 -#define BBP_R91 91 -#define BBP_R92 92 -#define BBP_R94 94 // Tx Gain Control -#define BBP_R103 103 -#define BBP_R105 105 -#define BBP_R113 113 -#define BBP_R114 114 -#define BBP_R115 115 -#define BBP_R116 116 -#define BBP_R117 117 -#define BBP_R118 118 -#define BBP_R119 119 -#define BBP_R120 120 -#define BBP_R121 121 -#define BBP_R122 122 -#define BBP_R123 123 -#define BBP_R138 138 // add by johnli, RF power sequence setup, ADC dynamic on/off control - - -#define BBPR94_DEFAULT 0x06 // Add 1 value will gain 1db - -#define RSSI_FOR_VERY_LOW_SENSIBILITY -35 -#define RSSI_FOR_LOW_SENSIBILITY -58 -#define RSSI_FOR_MID_LOW_SENSIBILITY -80 -#define RSSI_FOR_MID_SENSIBILITY -90 - -//------------------------------------------------------------------------- -// EEPROM definition -//------------------------------------------------------------------------- -#define EEDO 0x08 -#define EEDI 0x04 -#define EECS 0x02 -#define EESK 0x01 -#define EERL 0x80 - -#define EEPROM_WRITE_OPCODE 0x05 -#define EEPROM_READ_OPCODE 0x06 -#define EEPROM_EWDS_OPCODE 0x10 -#define EEPROM_EWEN_OPCODE 0x13 - -#define NUM_EEPROM_BBP_PARMS 19 // Include NIC Config 0, 1, CR, TX ALC step, BBPs -#define NUM_EEPROM_TX_G_PARMS 7 -#define EEPROM_NIC1_OFFSET 0x34 // The address is from NIC config 0, not BBP register ID -#define EEPROM_NIC2_OFFSET 0x36 // The address is from NIC config 0, not BBP register ID -#define EEPROM_BBP_BASE_OFFSET 0xf0 // The address is from NIC config 0, not BBP register ID -#define EEPROM_G_TX_PWR_OFFSET 0x52 -#define EEPROM_G_TX2_PWR_OFFSET 0x60 -#define EEPROM_LED1_OFFSET 0x3c -#define EEPROM_LED2_OFFSET 0x3e -#define EEPROM_LED3_OFFSET 0x40 -#define EEPROM_LNA_OFFSET 0x44 -#define EEPROM_RSSI_BG_OFFSET 0x46 -#define EEPROM_RSSI_A_OFFSET 0x4a -#define EEPROM_DEFINE_MAX_TXPWR 0x4e -#define EEPROM_TXPOWER_BYRATE_20MHZ_2_4G 0xde // 20MHZ 2.4G tx power. -#define EEPROM_TXPOWER_BYRATE_40MHZ_2_4G 0xee // 40MHZ 2.4G tx power. -#define EEPROM_TXPOWER_BYRATE_20MHZ_5G 0xfa // 20MHZ 5G tx power. -#define EEPROM_TXPOWER_BYRATE_40MHZ_5G 0x10a // 40MHZ 5G tx power. -#define EEPROM_A_TX_PWR_OFFSET 0x78 -#define EEPROM_A_TX2_PWR_OFFSET 0xa6 -#define EEPROM_VERSION_OFFSET 0x02 -#define EEPROM_FREQ_OFFSET 0x3a -#define EEPROM_TXPOWER_BYRATE 0xde // 20MHZ power. -#define EEPROM_TXPOWER_DELTA 0x50 // 20MHZ AND 40 MHZ use different power. This is delta in 40MHZ. -#define VALID_EEPROM_VERSION 1 - -// PairKeyMode definition -#define PKMODE_NONE 0 -#define PKMODE_WEP64 1 -#define PKMODE_WEP128 2 -#define PKMODE_TKIP 3 -#define PKMODE_AES 4 -#define PKMODE_CKIP64 5 -#define PKMODE_CKIP128 6 -#define PKMODE_TKIP_NO_MIC 7 // MIC appended by driver: not a valid value in hardware key table - -// ================================================================================= -// WCID format -// ================================================================================= -//7.1 WCID ENTRY format : 8bytes -typedef struct _WCID_ENTRY_STRUC { - UCHAR RXBABitmap7; // bit0 for TID8, bit7 for TID 15 - UCHAR RXBABitmap0; // bit0 for TID0, bit7 for TID 7 - UCHAR MAC[6]; // 0 for shared key table. 1 for pairwise key table -} WCID_ENTRY_STRUC, *PWCID_ENTRY_STRUC; - -//8.1.1 SECURITY KEY format : 8DW -// 32-byte per entry, total 16-entry for shared key table, 64-entry for pairwise key table -typedef struct _HW_KEY_ENTRY { // 32-byte per entry - UCHAR Key[16]; - UCHAR TxMic[8]; - UCHAR RxMic[8]; -} HW_KEY_ENTRY, *PHW_KEY_ENTRY; - -//8.1.2 IV/EIV format : 2DW - -//8.1.3 RX attribute entry format : 1DW -typedef struct _MAC_ATTRIBUTE_STRUC { - UINT32 KeyTab:1; // 0 for shared key table. 1 for pairwise key table - UINT32 PairKeyMode:3; - UINT32 BSSIDIdx:3; //multipleBSS index for the WCID - UINT32 RXWIUDF:3; - UINT32 rsv:22; -} MAC_ATTRIBUTE_STRUC, *PMAC_ATTRIBUTE_STRUC; - -// ================================================================================= -// TX / RX ring descriptor format -// ================================================================================= - -// the first 24-byte in TXD is called TXINFO and will be DMAed to MAC block through TXFIFO. -// MAC block use this TXINFO to control the transmission behavior of this frame. -#define FIFO_MGMT 0 -#define FIFO_HCCA 1 -#define FIFO_EDCA 2 - -// -// TX descriptor format, Tx ring, Mgmt Ring -// -typedef struct PACKED _TXD_STRUC { - // Word 0 - UINT32 SDPtr0; - // Word 1 - UINT32 SDLen1:14; - UINT32 LastSec1:1; - UINT32 Burst:1; - UINT32 SDLen0:14; - UINT32 LastSec0:1; - UINT32 DMADONE:1; - //Word2 - UINT32 SDPtr1; - //Word3 - UINT32 rsv2:24; - UINT32 WIV:1; // Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition - UINT32 QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA - UINT32 rsv:2; - UINT32 TCO:1; // - UINT32 UCO:1; // - UINT32 ICO:1; // -} TXD_STRUC, *PTXD_STRUC; - -// -// TXD Wireless Information format for Tx ring and Mgmt Ring -// -//txop : for txop mode -// 0:txop for the MPDU frame will be handles by ASIC by register -// 1/2/3:the MPDU frame is send after PIFS/backoff/SIFS -typedef struct PACKED _TXWI_STRUC { - // Word 0 - UINT32 FRAG:1; // 1 to inform TKIP engine this is a fragment. - UINT32 MIMOps:1; // the remote peer is in dynamic MIMO-PS mode - UINT32 CFACK:1; - UINT32 TS:1; - - UINT32 AMPDU:1; - UINT32 MpduDensity:3; - UINT32 txop:2; //FOR "THIS" frame. 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful. - UINT32 rsv:6; - - UINT32 MCS:7; - UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz - UINT32 ShortGI:1; - UINT32 STBC:2; // 1: STBC support MCS =0-7, 2,3 : RESERVE - UINT32 Ifs:1; // - UINT32 rsv2:1; - UINT32 TxBF:1; // 3*3 - UINT32 PHYMODE:2; - // Word 1 - UINT32 ACK:1; - UINT32 NSEQ:1; - UINT32 BAWinSize:6; - UINT32 WirelessCliID:8; - UINT32 MPDUtotalByteCount:12; - UINT32 PacketId:4; - //Word2 - UINT32 IV; - //Word3 - UINT32 EIV; -} TXWI_STRUC, *PTXWI_STRUC; - -// -// Rx descriptor format, Rx Ring -// -#ifdef RT2860 -typedef struct PACKED _RXD_STRUC { - // Word 0 - UINT32 SDP0; - // Word 1 - UINT32 SDL1:14; - UINT32 Rsv:2; - UINT32 SDL0:14; - UINT32 LS0:1; - UINT32 DDONE:1; - // Word 2 - UINT32 SDP1; - // Word 3 - UINT32 BA:1; - UINT32 DATA:1; - UINT32 NULLDATA:1; - UINT32 FRAG:1; - UINT32 U2M:1; // 1: this RX frame is unicast to me - UINT32 Mcast:1; // 1: this is a multicast frame - UINT32 Bcast:1; // 1: this is a broadcast frame - UINT32 MyBss:1; // 1: this frame belongs to the same BSSID - UINT32 Crc:1; // 1: CRC error - UINT32 CipherErr:2; // 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid - UINT32 AMSDU:1; // rx with 802.3 header, not 802.11 header. - UINT32 HTC:1; - UINT32 RSSI:1; - UINT32 L2PAD:1; - UINT32 AMPDU:1; - UINT32 Decrypted:1; // this frame is being decrypted. - UINT32 PlcpSignal:1; // To be moved - UINT32 PlcpRssil:1;// To be moved - UINT32 Rsv1:13; -} RXD_STRUC, *PRXD_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC; -#endif /* RT2860 */ - -// -// RXWI wireless information format, in PBF. invisible in driver. -// -typedef struct PACKED _RXWI_STRUC { - // Word 0 - UINT32 WirelessCliID:8; - UINT32 KeyIndex:2; - UINT32 BSSID:3; - UINT32 UDF:3; - UINT32 MPDUtotalByteCount:12; - UINT32 TID:4; - // Word 1 - UINT32 FRAG:4; - UINT32 SEQUENCE:12; - UINT32 MCS:7; - UINT32 BW:1; - UINT32 ShortGI:1; - UINT32 STBC:2; - UINT32 rsv:3; - UINT32 PHYMODE:2; // 1: this RX frame is unicast to me - //Word2 - UINT32 RSSI0:8; - UINT32 RSSI1:8; - UINT32 RSSI2:8; - UINT32 rsv1:8; - //Word3 - UINT32 SNR0:8; - UINT32 SNR1:8; - UINT32 rsv2:16; -} RXWI_STRUC, *PRXWI_STRUC; - -// ================================================================================= -// HOST-MCU communication data structure -// ================================================================================= - -// -// H2M_MAILBOX_CSR: Host-to-MCU Mailbox -// -typedef union _H2M_MAILBOX_STRUC { - struct { - UINT32 LowByte:8; - UINT32 HighByte:8; - UINT32 CmdToken:8; - UINT32 Owner:8; - } field; - UINT32 word; -} H2M_MAILBOX_STRUC, *PH2M_MAILBOX_STRUC; - -// -// M2H_CMD_DONE_CSR: MCU-to-Host command complete indication -// -typedef union _M2H_CMD_DONE_STRUC { - struct { - UINT32 CmdToken0; - UINT32 CmdToken1; - UINT32 CmdToken2; - UINT32 CmdToken3; - } field; - UINT32 word; -} M2H_CMD_DONE_STRUC, *PM2H_CMD_DONE_STRUC; - -// -// MCU_LEDCS: MCU LED Control Setting. -// -typedef union _MCU_LEDCS_STRUC { - struct { - UCHAR LedMode:7; - UCHAR Polarity:1; - } field; - UCHAR word; -} MCU_LEDCS_STRUC, *PMCU_LEDCS_STRUC; - -// ================================================================================= -// Register format -// ================================================================================= - - - -//NAV_TIME_CFG :NAV -typedef union _NAV_TIME_CFG_STRUC { - struct { - UCHAR Sifs; // in unit of 1-us - UCHAR SlotTime; // in unit of 1-us - USHORT Eifs:9; // in unit of 1-us - USHORT ZeroSifs:1; // Applied zero SIFS timer after OFDM RX 0: disable - USHORT rsv:6; - } field; - UINT32 word; -} NAV_TIME_CFG_STRUC, *PNAV_TIME_CFG_STRUC; - -// -// RX_FILTR_CFG: /RX configuration register -// -typedef union _RX_FILTR_CFG_STRUC { - struct { - UINT32 DropCRCErr:1; // Drop CRC error - UINT32 DropPhyErr:1; // Drop physical error - UINT32 DropNotToMe:1; // Drop not to me unicast frame - UINT32 DropNotMyBSSID:1; // Drop fram ToDs bit is true - - UINT32 DropVerErr:1; // Drop version error frame - UINT32 DropMcast:1; // Drop multicast frames - UINT32 DropBcast:1; // Drop broadcast frames - UINT32 DropDuplicate:1; // Drop duplicate frame - - UINT32 DropCFEndAck:1; // Drop Ps-Poll - UINT32 DropCFEnd:1; // Drop Ps-Poll - UINT32 DropAck:1; // Drop Ps-Poll - UINT32 DropCts:1; // Drop Ps-Poll - - UINT32 DropRts:1; // Drop Ps-Poll - UINT32 DropPsPoll:1; // Drop Ps-Poll - UINT32 DropBA:1; // - UINT32 DropBAR:1; // - - UINT32 DropRsvCntlType:1; - UINT32 :15; - } field; - UINT32 word; -} RX_FILTR_CFG_STRUC, *PRX_FILTR_CFG_STRUC; - -// -// PHY_CSR4: RF serial control register -// -typedef union _PHY_CSR4_STRUC { - struct { - UINT32 RFRegValue:24; // Register value (include register id) serial out to RF/IF chip. - UINT32 NumberOfBits:5; // Number of bits used in RFRegValue (I:20, RFMD:22) - UINT32 IFSelect:1; // 1: select IF to program, 0: select RF to program - UINT32 PLL_LD:1; // RF PLL_LD status - UINT32 Busy:1; // 1: ASIC is busy execute RF programming. - } field; - UINT32 word; -} PHY_CSR4_STRUC, *PPHY_CSR4_STRUC; - -// -// SEC_CSR5: shared key table security mode register -// -typedef union _SEC_CSR5_STRUC { - struct { - UINT32 Bss2Key0CipherAlg:3; - UINT32 :1; - UINT32 Bss2Key1CipherAlg:3; - UINT32 :1; - UINT32 Bss2Key2CipherAlg:3; - UINT32 :1; - UINT32 Bss2Key3CipherAlg:3; - UINT32 :1; - UINT32 Bss3Key0CipherAlg:3; - UINT32 :1; - UINT32 Bss3Key1CipherAlg:3; - UINT32 :1; - UINT32 Bss3Key2CipherAlg:3; - UINT32 :1; - UINT32 Bss3Key3CipherAlg:3; - UINT32 :1; - } field; - UINT32 word; -} SEC_CSR5_STRUC, *PSEC_CSR5_STRUC; - -// -// HOST_CMD_CSR: For HOST to interrupt embedded processor -// -typedef union _HOST_CMD_CSR_STRUC { - struct { - UINT32 HostCommand:8; - UINT32 Rsv:24; - } field; - UINT32 word; -} HOST_CMD_CSR_STRUC, *PHOST_CMD_CSR_STRUC; - -// -// AIFSN_CSR: AIFSN for each EDCA AC -// - - - -// -// E2PROM_CSR: EEPROM control register -// -typedef union _E2PROM_CSR_STRUC { - struct { - UINT32 Reload:1; // Reload EEPROM content, write one to reload, self-cleared. - UINT32 EepromSK:1; - UINT32 EepromCS:1; - UINT32 EepromDI:1; - UINT32 EepromDO:1; - UINT32 Type:1; // 1: 93C46, 0:93C66 - UINT32 LoadStatus:1; // 1:loading, 0:done - UINT32 Rsvd:25; - } field; - UINT32 word; -} E2PROM_CSR_STRUC, *PE2PROM_CSR_STRUC; - -// ------------------------------------------------------------------- -// E2PROM data layout -// ------------------------------------------------------------------- - -// -// EEPROM antenna select format -// -typedef union _EEPROM_ANTENNA_STRUC { - struct { - USHORT RxPath:4; // 1: 1R, 2: 2R, 3: 3R - USHORT TxPath:4; // 1: 1T, 2: 2T - USHORT RfIcType:4; // see E2PROM document - USHORT Rsv:4; - } field; - USHORT word; -} EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC; - -typedef union _EEPROM_NIC_CINFIG2_STRUC { - struct { - USHORT HardwareRadioControl:1; // 1:enable, 0:disable - USHORT DynamicTxAgcControl:1; // - USHORT ExternalLNAForG:1; // - USHORT ExternalLNAForA:1; // external LNA enable for 2.4G - USHORT CardbusAcceleration:1; // !!! NOTE: 0 - enable, 1 - disable - USHORT BW40MSidebandForG:1; - USHORT BW40MSidebandForA:1; - USHORT EnableWPSPBC:1; // WPS PBC Control bit - USHORT BW40MAvailForG:1; // 0:enable, 1:disable - USHORT BW40MAvailForA:1; // 0:enable, 1:disable - USHORT Rsv1:1; // must be 0 - USHORT AntDiversity:1; // Antenna diversity - USHORT Rsv2:3; // must be 0 - USHORT DACTestBit:1; // control if driver should patch the DAC issue - } field; - USHORT word; -} EEPROM_NIC_CONFIG2_STRUC, *PEEPROM_NIC_CONFIG2_STRUC; - -// -// TX_PWR Value valid range 0xFA(-6) ~ 0x24(36) -// -typedef union _EEPROM_TX_PWR_STRUC { - struct { - CHAR Byte0; // Low Byte - CHAR Byte1; // High Byte - } field; - USHORT word; -} EEPROM_TX_PWR_STRUC, *PEEPROM_TX_PWR_STRUC; - -typedef union _EEPROM_VERSION_STRUC { - struct { - UCHAR FaeReleaseNumber; // Low Byte - UCHAR Version; // High Byte - } field; - USHORT word; -} EEPROM_VERSION_STRUC, *PEEPROM_VERSION_STRUC; - -typedef union _EEPROM_LED_STRUC { - struct { - USHORT PolarityRDY_G:1; // Polarity RDY_G setting. - USHORT PolarityRDY_A:1; // Polarity RDY_A setting. - USHORT PolarityACT:1; // Polarity ACT setting. - USHORT PolarityGPIO_0:1; // Polarity GPIO#0 setting. - USHORT PolarityGPIO_1:1; // Polarity GPIO#1 setting. - USHORT PolarityGPIO_2:1; // Polarity GPIO#2 setting. - USHORT PolarityGPIO_3:1; // Polarity GPIO#3 setting. - USHORT PolarityGPIO_4:1; // Polarity GPIO#4 setting. - USHORT LedMode:5; // Led mode. - USHORT Rsvd:3; // Reserved - } field; - USHORT word; -} EEPROM_LED_STRUC, *PEEPROM_LED_STRUC; - -typedef union _EEPROM_TXPOWER_DELTA_STRUC { - struct { - UCHAR DeltaValue:6; // Tx Power dalta value (MAX=4) - UCHAR Type:1; // 1: plus the delta value, 0: minus the delta value - UCHAR TxPowerEnable:1;// Enable - } field; - UCHAR value; -} EEPROM_TXPOWER_DELTA_STRUC, *PEEPROM_TXPOWER_DELTA_STRUC; - -// -// QOS_CSR0: TXOP holder address0 register -// -typedef union _QOS_CSR0_STRUC { - struct { - UCHAR Byte0; // MAC address byte 0 - UCHAR Byte1; // MAC address byte 1 - UCHAR Byte2; // MAC address byte 2 - UCHAR Byte3; // MAC address byte 3 - } field; - UINT32 word; -} QOS_CSR0_STRUC, *PQOS_CSR0_STRUC; - -// -// QOS_CSR1: TXOP holder address1 register -// -typedef union _QOS_CSR1_STRUC { - struct { - UCHAR Byte4; // MAC address byte 4 - UCHAR Byte5; // MAC address byte 5 - UCHAR Rsvd0; - UCHAR Rsvd1; - } field; - UINT32 word; -} QOS_CSR1_STRUC, *PQOS_CSR1_STRUC; - -#define RF_CSR_CFG 0x500 -typedef union _RF_CSR_CFG_STRUC { - struct { - UINT RF_CSR_DATA:8; // DATA - UINT TESTCSR_RFACC_REGNUM:5; // RF register ID - UINT Rsvd2:3; // Reserved - UINT RF_CSR_WR:1; // 0: read 1: write - UINT RF_CSR_KICK:1; // kick RF register read/write - UINT Rsvd1:14; // Reserved - } field; - UINT word; -} RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC; - -#endif // __RT28XX_H__ diff --git a/drivers/staging/rt2860/rt_config.h b/drivers/staging/rt2860/rt_config.h index 2093a80b19df1a54e5adf440542a319783bb7a88..d1adef8948afa88c4c3a94795c52fe482486f215 100644 --- a/drivers/staging/rt2860/rt_config.h +++ b/drivers/staging/rt2860/rt_config.h @@ -41,32 +41,31 @@ #define __RT_CONFIG_H__ #include "rtmp_type.h" -#ifdef LINUX -#include "rt_linux.h" -#endif -#include "rtmp_def.h" -#include "rt28xx.h" +#include "rtmp_os.h" -#ifdef RT2860 -#include "rt2860.h" -#endif -#ifdef RT2870 -#include "../rt2870/rt2870.h" -#endif // RT2870 // +#include "rtmp_def.h" +#include "rtmp_chip.h" +#include "rtmp_timer.h" #include "oid.h" #include "mlme.h" #include "wpa.h" -#include "md5.h" +#include "crypt_md5.h" +#include "crypt_sha2.h" +#include "crypt_hmac.h" #include "rtmp.h" #include "ap.h" #include "dfs.h" #include "chlist.h" #include "spectrum.h" +#include "eeprom.h" +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) +#include "rtmp_mcu.h" +#endif + #ifdef IGMP_SNOOP_SUPPORT #include "igmp_snoop.h" -#endif // IGMP_SNOOP_SUPPORT // - -#endif // __RT_CONFIG_H__ +#endif /* IGMP_SNOOP_SUPPORT // */ +#endif /* __RT_CONFIG_H__ */ diff --git a/drivers/staging/rt2860/rt_linux.c b/drivers/staging/rt2860/rt_linux.c index ed27b8545a1b3d507251f4387a4ac17284dd2160..9357fb26cc2a7ac75c4ceddf60c49f0e862d718a 100644 --- a/drivers/staging/rt2860/rt_linux.c +++ b/drivers/staging/rt2860/rt_linux.c @@ -28,149 +28,114 @@ #include #include "rt_config.h" -ULONG RTDebugLevel = RT_DEBUG_ERROR; - -BUILD_TIMER_FUNCTION(MlmePeriodicExec); -BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout); -BUILD_TIMER_FUNCTION(APSDPeriodicExec); -BUILD_TIMER_FUNCTION(AsicRfTuningExec); -#ifdef RT2870 -BUILD_TIMER_FUNCTION(BeaconUpdateExec); -#endif // RT2870 // - -BUILD_TIMER_FUNCTION(BeaconTimeout); -BUILD_TIMER_FUNCTION(ScanTimeout); -BUILD_TIMER_FUNCTION(AuthTimeout); -BUILD_TIMER_FUNCTION(AssocTimeout); -BUILD_TIMER_FUNCTION(ReassocTimeout); -BUILD_TIMER_FUNCTION(DisassocTimeout); -BUILD_TIMER_FUNCTION(LinkDownExec); -BUILD_TIMER_FUNCTION(StaQuickResponeForRateUpExec); -BUILD_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc); -#ifdef RT2860 -BUILD_TIMER_FUNCTION(PsPollWakeExec); -BUILD_TIMER_FUNCTION(RadioOnExec); -#endif +unsigned long RTDebugLevel = RT_DEBUG_ERROR; -// for wireless system event message +/* for wireless system event message */ char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = { - // system status event - "had associated successfully", /* IW_ASSOC_EVENT_FLAG */ - "had disassociated", /* IW_DISASSOC_EVENT_FLAG */ - "had deauthenticated", /* IW_DEAUTH_EVENT_FLAG */ - "had been aged-out and disassociated", /* IW_AGEOUT_EVENT_FLAG */ - "occurred CounterMeasures attack", /* IW_COUNTER_MEASURES_EVENT_FLAG */ - "occurred replay counter different in Key Handshaking", /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */ - "occurred RSNIE different in Key Handshaking", /* IW_RSNIE_DIFF_EVENT_FLAG */ - "occurred MIC different in Key Handshaking", /* IW_MIC_DIFF_EVENT_FLAG */ - "occurred ICV error in RX", /* IW_ICV_ERROR_EVENT_FLAG */ - "occurred MIC error in RX", /* IW_MIC_ERROR_EVENT_FLAG */ - "Group Key Handshaking timeout", /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */ - "Pairwise Key Handshaking timeout", /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */ - "RSN IE sanity check failure", /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */ - "set key done in WPA/WPAPSK", /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */ - "set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */ - "connects with our wireless client", /* IW_STA_LINKUP_EVENT_FLAG */ - "disconnects with our wireless client", /* IW_STA_LINKDOWN_EVENT_FLAG */ - "scan completed" /* IW_SCAN_COMPLETED_EVENT_FLAG */ - "scan terminate!! Busy!! Enqueue fail!!" /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */ - }; - -// for wireless IDS_spoof_attack event message + /* system status event */ + "had associated successfully", /* IW_ASSOC_EVENT_FLAG */ + "had disassociated", /* IW_DISASSOC_EVENT_FLAG */ + "had deauthenticated", /* IW_DEAUTH_EVENT_FLAG */ + "had been aged-out and disassociated", /* IW_AGEOUT_EVENT_FLAG */ + "occurred CounterMeasures attack", /* IW_COUNTER_MEASURES_EVENT_FLAG */ + "occurred replay counter different in Key Handshaking", /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */ + "occurred RSNIE different in Key Handshaking", /* IW_RSNIE_DIFF_EVENT_FLAG */ + "occurred MIC different in Key Handshaking", /* IW_MIC_DIFF_EVENT_FLAG */ + "occurred ICV error in RX", /* IW_ICV_ERROR_EVENT_FLAG */ + "occurred MIC error in RX", /* IW_MIC_ERROR_EVENT_FLAG */ + "Group Key Handshaking timeout", /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */ + "Pairwise Key Handshaking timeout", /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */ + "RSN IE sanity check failure", /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */ + "set key done in WPA/WPAPSK", /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */ + "set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */ + "connects with our wireless client", /* IW_STA_LINKUP_EVENT_FLAG */ + "disconnects with our wireless client", /* IW_STA_LINKDOWN_EVENT_FLAG */ + "scan completed" /* IW_SCAN_COMPLETED_EVENT_FLAG */ + "scan terminate! Busy! Enqueue fail!" /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */ +}; + +/* for wireless IDS_spoof_attack event message */ char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = { - "detected conflict SSID", /* IW_CONFLICT_SSID_EVENT_FLAG */ - "detected spoofed association response", /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */ - "detected spoofed reassociation responses", /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */ - "detected spoofed probe response", /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */ - "detected spoofed beacon", /* IW_SPOOF_BEACON_EVENT_FLAG */ - "detected spoofed disassociation", /* IW_SPOOF_DISASSOC_EVENT_FLAG */ - "detected spoofed authentication", /* IW_SPOOF_AUTH_EVENT_FLAG */ - "detected spoofed deauthentication", /* IW_SPOOF_DEAUTH_EVENT_FLAG */ - "detected spoofed unknown management frame", /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */ - "detected replay attack" /* IW_REPLAY_ATTACK_EVENT_FLAG */ - }; - -// for wireless IDS_flooding_attack event message + "detected conflict SSID", /* IW_CONFLICT_SSID_EVENT_FLAG */ + "detected spoofed association response", /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */ + "detected spoofed reassociation responses", /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */ + "detected spoofed probe response", /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */ + "detected spoofed beacon", /* IW_SPOOF_BEACON_EVENT_FLAG */ + "detected spoofed disassociation", /* IW_SPOOF_DISASSOC_EVENT_FLAG */ + "detected spoofed authentication", /* IW_SPOOF_AUTH_EVENT_FLAG */ + "detected spoofed deauthentication", /* IW_SPOOF_DEAUTH_EVENT_FLAG */ + "detected spoofed unknown management frame", /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */ + "detected replay attack" /* IW_REPLAY_ATTACK_EVENT_FLAG */ +}; + +/* for wireless IDS_flooding_attack event message */ char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = { - "detected authentication flooding", /* IW_FLOOD_AUTH_EVENT_FLAG */ - "detected association request flooding", /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */ - "detected reassociation request flooding", /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */ - "detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */ - "detected disassociation flooding", /* IW_FLOOD_DISASSOC_EVENT_FLAG */ - "detected deauthentication flooding", /* IW_FLOOD_DEAUTH_EVENT_FLAG */ - "detected 802.1x eap-request flooding" /* IW_FLOOD_EAP_REQ_EVENT_FLAG */ - }; + "detected authentication flooding", /* IW_FLOOD_AUTH_EVENT_FLAG */ + "detected association request flooding", /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */ + "detected reassociation request flooding", /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */ + "detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */ + "detected disassociation flooding", /* IW_FLOOD_DISASSOC_EVENT_FLAG */ + "detected deauthentication flooding", /* IW_FLOOD_DEAUTH_EVENT_FLAG */ + "detected 802.1x eap-request flooding" /* IW_FLOOD_EAP_REQ_EVENT_FLAG */ +}; /* timeout -- ms */ -VOID RTMP_SetPeriodicTimer( - IN NDIS_MINIPORT_TIMER *pTimer, - IN unsigned long timeout) +void RTMP_SetPeriodicTimer(struct timer_list * pTimer, + IN unsigned long timeout) { - timeout = ((timeout*HZ) / 1000); + timeout = ((timeout * OS_HZ) / 1000); pTimer->expires = jiffies + timeout; add_timer(pTimer); } /* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */ -VOID RTMP_OS_Init_Timer( - IN PRTMP_ADAPTER pAd, - IN NDIS_MINIPORT_TIMER *pTimer, - IN TIMER_FUNCTION function, - IN PVOID data) +void RTMP_OS_Init_Timer(struct rt_rtmp_adapter *pAd, + struct timer_list * pTimer, + IN TIMER_FUNCTION function, void *data) { init_timer(pTimer); - pTimer->data = (unsigned long)data; - pTimer->function = function; + pTimer->data = (unsigned long)data; + pTimer->function = function; } - -VOID RTMP_OS_Add_Timer( - IN NDIS_MINIPORT_TIMER *pTimer, - IN unsigned long timeout) +void RTMP_OS_Add_Timer(struct timer_list * pTimer, + IN unsigned long timeout) { if (timer_pending(pTimer)) return; - timeout = ((timeout*HZ) / 1000); + timeout = ((timeout * OS_HZ) / 1000); pTimer->expires = jiffies + timeout; add_timer(pTimer); } -VOID RTMP_OS_Mod_Timer( - IN NDIS_MINIPORT_TIMER *pTimer, - IN unsigned long timeout) +void RTMP_OS_Mod_Timer(struct timer_list * pTimer, + IN unsigned long timeout) { - timeout = ((timeout*HZ) / 1000); + timeout = ((timeout * OS_HZ) / 1000); mod_timer(pTimer, jiffies + timeout); } -VOID RTMP_OS_Del_Timer( - IN NDIS_MINIPORT_TIMER *pTimer, - OUT BOOLEAN *pCancelled) +void RTMP_OS_Del_Timer(struct timer_list * pTimer, + OUT BOOLEAN * pCancelled) { - if (timer_pending(pTimer)) - { + if (timer_pending(pTimer)) { *pCancelled = del_timer_sync(pTimer); - } - else - { + } else { *pCancelled = TRUE; } } -VOID RTMP_OS_Release_Packet( - IN PRTMP_ADAPTER pAd, - IN PQUEUE_ENTRY pEntry) +void RTMP_OS_Release_Packet(struct rt_rtmp_adapter *pAd, struct rt_queue_entry *pEntry) { - //RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry); + /*RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry); */ } -// Unify all delay routine by using udelay -VOID RTMPusecDelay( - IN ULONG usec) +/* Unify all delay routine by using udelay */ +void RTMPusecDelay(unsigned long usec) { - ULONG i; + unsigned long i; for (i = 0; i < (usec / 50); i++) udelay(50); @@ -179,28 +144,23 @@ VOID RTMPusecDelay( udelay(usec % 50); } -void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time) +void RTMP_GetCurrentSystemTime(LARGE_INTEGER * time) { time->u.LowPart = jiffies; } -// pAd MUST allow to be NULL -NDIS_STATUS os_alloc_mem( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR *mem, - IN ULONG size) +/* pAd MUST allow to be NULL */ +int os_alloc_mem(struct rt_rtmp_adapter *pAd, u8 ** mem, unsigned long size) { - *mem = (PUCHAR) kmalloc(size, GFP_ATOMIC); + *mem = (u8 *)kmalloc(size, GFP_ATOMIC); if (*mem) return (NDIS_STATUS_SUCCESS); else return (NDIS_STATUS_FAILURE); } -// pAd MUST allow to be NULL -NDIS_STATUS os_free_mem( - IN PRTMP_ADAPTER pAd, - IN PUCHAR mem) +/* pAd MUST allow to be NULL */ +int os_free_mem(struct rt_rtmp_adapter *pAd, void *mem) { ASSERT(mem); @@ -208,66 +168,64 @@ NDIS_STATUS os_free_mem( return (NDIS_STATUS_SUCCESS); } +void *RtmpOSNetPktAlloc(struct rt_rtmp_adapter *pAd, IN int size) +{ + struct sk_buff *skb; + /* Add 2 more bytes for ip header alignment */ + skb = dev_alloc_skb(size + 2); + + return ((void *)skb); +} -PNDIS_PACKET RTMP_AllocateFragPacketBuffer( - IN PRTMP_ADAPTER pAd, - IN ULONG Length) +void *RTMP_AllocateFragPacketBuffer(struct rt_rtmp_adapter *pAd, + unsigned long Length) { struct sk_buff *pkt; pkt = dev_alloc_skb(Length); - if (pkt == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("can't allocate frag rx %ld size packet\n",Length)); + if (pkt == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("can't allocate frag rx %ld size packet\n", Length)); } - if (pkt) - { + if (pkt) { RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); } - return (PNDIS_PACKET) pkt; + return (void *)pkt; } - -PNDIS_PACKET RTMP_AllocateTxPacketBuffer( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress) +void *RTMP_AllocateTxPacketBuffer(struct rt_rtmp_adapter *pAd, + unsigned long Length, + IN BOOLEAN Cached, + void ** VirtualAddress) { struct sk_buff *pkt; pkt = dev_alloc_skb(Length); - if (pkt == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("can't allocate tx %ld size packet\n",Length)); + if (pkt == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("can't allocate tx %ld size packet\n", Length)); } - if (pkt) - { + if (pkt) { RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); - *VirtualAddress = (PVOID) pkt->data; - } - else - { - *VirtualAddress = (PVOID) NULL; + *VirtualAddress = (void *)pkt->data; + } else { + *VirtualAddress = (void *)NULL; } - return (PNDIS_PACKET) pkt; + return (void *)pkt; } - -VOID build_tx_packet( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN PUCHAR pFrame, - IN ULONG FrameLen) +void build_tx_packet(struct rt_rtmp_adapter *pAd, + void *pPacket, + u8 *pFrame, unsigned long FrameLen) { - struct sk_buff *pTxPkt; + struct sk_buff *pTxPkt; ASSERT(pPacket); pTxPkt = RTPKT_TO_OSPKT(pPacket); @@ -275,32 +233,36 @@ VOID build_tx_packet( NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen); } -VOID RTMPFreeAdapter( - IN PRTMP_ADAPTER pAd) +void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd) { - POS_COOKIE os_cookie; + struct os_cookie *os_cookie; int index; - os_cookie=(POS_COOKIE)pAd->OS_Cookie; - - kfree(pAd->BeaconBuf); + os_cookie = (struct os_cookie *)pAd->OS_Cookie; + if (pAd->BeaconBuf) + kfree(pAd->BeaconBuf); NdisFreeSpinLock(&pAd->MgmtRingLock); -#ifdef RT2860 + +#ifdef RTMP_MAC_PCI NdisFreeSpinLock(&pAd->RxRingLock); -#endif - for (index =0 ; index < NUM_OF_TX_RING; index++) - { - NdisFreeSpinLock(&pAd->TxSwQueueLock[index]); +#ifdef RT3090 + NdisFreeSpinLock(&pAd->McuCmdLock); +#endif /* RT3090 // */ +#endif /* RTMP_MAC_PCI // */ + + for (index = 0; index < NUM_OF_TX_RING; index++) { + NdisFreeSpinLock(&pAd->TxSwQueueLock[index]); NdisFreeSpinLock(&pAd->DeQueueLock[index]); pAd->DeQueueRunning[index] = FALSE; } NdisFreeSpinLock(&pAd->irq_lock); - vfree(pAd); // pci_free_consistent(os_cookie->pci_dev,sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa); - kfree(os_cookie); + vfree(pAd); /* pci_free_consistent(os_cookie->pci_dev,sizeof(struct rt_rtmp_adapter),pAd,os_cookie->pAd_pa); */ + if (os_cookie) + kfree(os_cookie); } BOOLEAN OS_Need_Clone_Packet(void) @@ -308,8 +270,6 @@ BOOLEAN OS_Need_Clone_Packet(void) return (FALSE); } - - /* ======================================================================== @@ -317,7 +277,7 @@ BOOLEAN OS_Need_Clone_Packet(void) clone an input NDIS PACKET to another one. The new internally created NDIS PACKET must have only one NDIS BUFFER return - byte copied. 0 means can't create NDIS PACKET - NOTE: internally created NDIS_PACKET should be destroyed by RTMPFreeNdisPacket + NOTE: internally created char should be destroyed by RTMPFreeNdisPacket Arguments: pAd Pointer to our adapter @@ -332,11 +292,10 @@ BOOLEAN OS_Need_Clone_Packet(void) ======================================================================== */ -NDIS_STATUS RTMPCloneNdisPacket( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN pInsAMSDUHdr, - IN PNDIS_PACKET pInPacket, - OUT PNDIS_PACKET *ppOutPacket) +int RTMPCloneNdisPacket(struct rt_rtmp_adapter *pAd, + IN BOOLEAN pInsAMSDUHdr, + void *pInPacket, + void ** ppOutPacket) { struct sk_buff *pkt; @@ -344,19 +303,18 @@ NDIS_STATUS RTMPCloneNdisPacket( ASSERT(pInPacket); ASSERT(ppOutPacket); - // 1. Allocate a packet + /* 1. Allocate a packet */ pkt = dev_alloc_skb(2048); - if (pkt == NULL) - { + if (pkt == NULL) { return NDIS_STATUS_FAILURE; } - skb_put(pkt, GET_OS_PKT_LEN(pInPacket)); - NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket), GET_OS_PKT_LEN(pInPacket)); + skb_put(pkt, GET_OS_PKT_LEN(pInPacket)); + NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket), + GET_OS_PKT_LEN(pInPacket)); *ppOutPacket = OSPKT_TO_RTPKT(pkt); - RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); printk("###Clone###\n"); @@ -364,42 +322,40 @@ NDIS_STATUS RTMPCloneNdisPacket( return NDIS_STATUS_SUCCESS; } - -// the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket() -NDIS_STATUS RTMPAllocateNdisPacket( - IN PRTMP_ADAPTER pAd, - OUT PNDIS_PACKET *ppPacket, - IN PUCHAR pHeader, - IN UINT HeaderLen, - IN PUCHAR pData, - IN UINT DataLen) +/* the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket() */ +int RTMPAllocateNdisPacket(struct rt_rtmp_adapter *pAd, + void ** ppPacket, + u8 *pHeader, + u32 HeaderLen, + u8 *pData, u32 DataLen) { - PNDIS_PACKET pPacket; + void *pPacket; ASSERT(pData); ASSERT(DataLen); - // 1. Allocate a packet - pPacket = (PNDIS_PACKET *) dev_alloc_skb(HeaderLen + DataLen + TXPADDING_SIZE); - if (pPacket == NULL) - { + /* 1. Allocate a packet */ + pPacket = + (void **) dev_alloc_skb(HeaderLen + DataLen + + RTMP_PKT_TAIL_PADDING); + if (pPacket == NULL) { *ppPacket = NULL; #ifdef DEBUG - printk("RTMPAllocateNdisPacket Fail\n\n"); + printk("RTMPAllocateNdisPacket Fail\n"); #endif return NDIS_STATUS_FAILURE; } - - // 2. clone the frame content + /* 2. clone the frame content */ if (HeaderLen > 0) NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen); if (DataLen > 0) - NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData, DataLen); + NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData, + DataLen); - // 3. update length of packet - skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen+DataLen); + /* 3. update length of packet */ + skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen + DataLen); RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); -// printk("%s : pPacket = %p, len = %d\n", __func__, pPacket, GET_OS_PKT_LEN(pPacket)); +/* printk("%s : pPacket = %p, len = %d\n", __func__, pPacket, GET_OS_PKT_LEN(pPacket)); */ *ppPacket = pPacket; return NDIS_STATUS_SUCCESS; } @@ -407,42 +363,34 @@ NDIS_STATUS RTMPAllocateNdisPacket( /* ======================================================================== Description: - This routine frees a miniport internally allocated NDIS_PACKET and its + This routine frees a miniport internally allocated char and its corresponding NDIS_BUFFER and allocated memory. ======================================================================== */ -VOID RTMPFreeNdisPacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket) +void RTMPFreeNdisPacket(struct rt_rtmp_adapter *pAd, void *pPacket) { dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket)); } - -// IRQL = DISPATCH_LEVEL -// NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same -// scatter gather buffer -NDIS_STATUS Sniff2BytesFromNdisBuffer( - IN PNDIS_BUFFER pFirstBuffer, - IN UCHAR DesiredOffset, - OUT PUCHAR pByte0, - OUT PUCHAR pByte1) +/* IRQL = DISPATCH_LEVEL */ +/* NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same */ +/* scatter gather buffer */ +int Sniff2BytesFromNdisBuffer(char *pFirstBuffer, + u8 DesiredOffset, + u8 *pByte0, u8 *pByte1) { - *pByte0 = *(PUCHAR)(pFirstBuffer + DesiredOffset); - *pByte1 = *(PUCHAR)(pFirstBuffer + DesiredOffset + 1); + *pByte0 = *(u8 *)(pFirstBuffer + DesiredOffset); + *pByte1 = *(u8 *)(pFirstBuffer + DesiredOffset + 1); return NDIS_STATUS_SUCCESS; } - -void RTMP_QueryPacketInfo( - IN PNDIS_PACKET pPacket, - OUT PACKET_INFO *pPacketInfo, - OUT PUCHAR *pSrcBufVA, - OUT UINT *pSrcBufLen) +void RTMP_QueryPacketInfo(void *pPacket, + struct rt_packet_info *pPacketInfo, + u8 ** pSrcBufVA, u32 * pSrcBufLen) { pPacketInfo->BufferCount = 1; - pPacketInfo->pFirstBuffer = GET_OS_PKT_DATAPTR(pPacket); + pPacketInfo->pFirstBuffer = (char *)GET_OS_PKT_DATAPTR(pPacket); pPacketInfo->PhysicalBufferCount = 1; pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket); @@ -450,30 +398,26 @@ void RTMP_QueryPacketInfo( *pSrcBufLen = GET_OS_PKT_LEN(pPacket); } -void RTMP_QueryNextPacketInfo( - IN PNDIS_PACKET *ppPacket, - OUT PACKET_INFO *pPacketInfo, - OUT PUCHAR *pSrcBufVA, - OUT UINT *pSrcBufLen) +void RTMP_QueryNextPacketInfo(void ** ppPacket, + struct rt_packet_info *pPacketInfo, + u8 ** pSrcBufVA, u32 * pSrcBufLen) { - PNDIS_PACKET pPacket = NULL; + void *pPacket = NULL; if (*ppPacket) pPacket = GET_OS_PKT_NEXT(*ppPacket); - if (pPacket) - { + if (pPacket) { pPacketInfo->BufferCount = 1; - pPacketInfo->pFirstBuffer = GET_OS_PKT_DATAPTR(pPacket); + pPacketInfo->pFirstBuffer = + (char *)GET_OS_PKT_DATAPTR(pPacket); pPacketInfo->PhysicalBufferCount = 1; pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket); *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); *pSrcBufLen = GET_OS_PKT_LEN(pPacket); *ppPacket = GET_OS_PKT_NEXT(pPacket); - } - else - { + } else { pPacketInfo->BufferCount = 0; pPacketInfo->pFirstBuffer = NULL; pPacketInfo->PhysicalBufferCount = 0; @@ -485,36 +429,19 @@ void RTMP_QueryNextPacketInfo( } } -// not yet support MBSS -PNET_DEV get_netdev_from_bssid( - IN PRTMP_ADAPTER pAd, - IN UCHAR FromWhichBSSID) -{ - PNET_DEV dev_p = NULL; - - dev_p = pAd->net_dev; - - ASSERT(dev_p); - return dev_p; /* return one of MBSS */ -} - -PNDIS_PACKET DuplicatePacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR FromWhichBSSID) +void *DuplicatePacket(struct rt_rtmp_adapter *pAd, + void *pPacket, u8 FromWhichBSSID) { - struct sk_buff *skb; - PNDIS_PACKET pRetPacket = NULL; - USHORT DataSize; - UCHAR *pData; - - DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); - pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); + struct sk_buff *skb; + void *pRetPacket = NULL; + u16 DataSize; + u8 *pData; + DataSize = (u16)GET_OS_PKT_LEN(pPacket); + pData = (u8 *)GET_OS_PKT_DATAPTR(pPacket); skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG); - if (skb) - { + if (skb) { skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); pRetPacket = OSPKT_TO_RTPKT(skb); } @@ -523,24 +450,21 @@ PNDIS_PACKET DuplicatePacket( } -PNDIS_PACKET duplicate_pkt( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pHeader802_3, - IN UINT HdrLen, - IN PUCHAR pData, - IN ULONG DataSize, - IN UCHAR FromWhichBSSID) +void *duplicate_pkt(struct rt_rtmp_adapter *pAd, + u8 *pHeader802_3, + u32 HdrLen, + u8 *pData, + unsigned long DataSize, u8 FromWhichBSSID) { - struct sk_buff *skb; - PNDIS_PACKET pPacket = NULL; - + struct sk_buff *skb; + void *pPacket = NULL; - if ((skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL) - { + if ((skb = + __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL) { skb_reserve(skb, 2); - NdisMoveMemory(skb_tail_pointer(skb), pHeader802_3, HdrLen); + NdisMoveMemory(skb->tail, pHeader802_3, HdrLen); skb_put(skb, HdrLen); - NdisMoveMemory(skb_tail_pointer(skb), pData, DataSize); + NdisMoveMemory(skb->tail, pData, DataSize); skb_put(skb, DataSize); skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); pPacket = OSPKT_TO_RTPKT(skb); @@ -549,24 +473,22 @@ PNDIS_PACKET duplicate_pkt( return pPacket; } - #define TKIP_TX_MIC_SIZE 8 -PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket) +void *duplicate_pkt_with_TKIP_MIC(struct rt_rtmp_adapter *pAd, + void *pPacket) { - struct sk_buff *skb, *newskb; - + struct sk_buff *skb, *newskb; skb = RTPKT_TO_OSPKT(pPacket); - if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE) - { - // alloc a new skb and copy the packet - newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC); + if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE) { + /* alloc a new skb and copy the packet */ + newskb = + skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, + GFP_ATOMIC); dev_kfree_skb_any(skb); - if (newskb == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n")); + if (newskb == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("Extend Tx.MIC for packet failed!, dropping packet!\n")); return NULL; } skb = newskb; @@ -575,45 +497,37 @@ PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( return OSPKT_TO_RTPKT(skb); } - - - -PNDIS_PACKET ClonePacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN PUCHAR pData, - IN ULONG DataSize) +void *ClonePacket(struct rt_rtmp_adapter *pAd, + void *pPacket, + u8 *pData, unsigned long DataSize) { - struct sk_buff *pRxPkt; - struct sk_buff *pClonedPkt; + struct sk_buff *pRxPkt; + struct sk_buff *pClonedPkt; ASSERT(pPacket); pRxPkt = RTPKT_TO_OSPKT(pPacket); - // clone the packet + /* clone the packet */ pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG); - if (pClonedPkt) - { - // set the correct dataptr and data len - pClonedPkt->dev = pRxPkt->dev; - pClonedPkt->data = pData; - pClonedPkt->len = DataSize; - pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len; + if (pClonedPkt) { + /* set the correct dataptr and data len */ + pClonedPkt->dev = pRxPkt->dev; + pClonedPkt->data = pData; + pClonedPkt->len = DataSize; + pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len; ASSERT(DataSize < 1530); } return pClonedPkt; } -// -// change OS packet DataPtr and DataLen -// -void update_os_packet_info( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) +/* */ +/* change OS packet DataPtr and DataLen */ +/* */ +void update_os_packet_info(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) { - struct sk_buff *pOSPkt; + struct sk_buff *pOSPkt; ASSERT(pRxBlk->pRxPacket); pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); @@ -624,14 +538,12 @@ void update_os_packet_info( pOSPkt->tail = pOSPkt->data + pOSPkt->len; } - -void wlan_802_11_to_802_3_packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN PUCHAR pHeader802_3, - IN UCHAR FromWhichBSSID) +void wlan_802_11_to_802_3_packet(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, + u8 *pHeader802_3, + u8 FromWhichBSSID) { - struct sk_buff *pOSPkt; + struct sk_buff *pOSPkt; ASSERT(pRxBlk->pRxPacket); ASSERT(pHeader802_3); @@ -643,37 +555,35 @@ void wlan_802_11_to_802_3_packet( pOSPkt->len = pRxBlk->DataSize; pOSPkt->tail = pOSPkt->data + pOSPkt->len; - // - // copy 802.3 header - // - // + /* */ + /* copy 802.3 header */ + /* */ + /* */ - NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3); + NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, + LENGTH_802_3); } -void announce_802_3_packet( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket) +void announce_802_3_packet(struct rt_rtmp_adapter *pAd, void *pPacket) { - struct sk_buff *pRxPkt; + struct sk_buff *pRxPkt; ASSERT(pPacket); pRxPkt = RTPKT_TO_OSPKT(pPacket); - /* Push up the protocol stack */ + /* Push up the protocol stack */ pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); netif_rx(pRxPkt); } - -PRTMP_SCATTER_GATHER_LIST -rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg) +struct rt_rtmp_sg_list * +rt_get_sg_list_from_packet(void *pPacket, struct rt_rtmp_sg_list *sg) { sg->NumberOfElements = 1; - sg->Elements[0].Address = GET_OS_PKT_DATAPTR(pPacket); + sg->Elements[0].Address = GET_OS_PKT_DATAPTR(pPacket); sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket); return (sg); } @@ -687,13 +597,13 @@ void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen) return; pt = pSrcBufVA; - printk("%s: %p, len = %d\n",str, pSrcBufVA, SrcBufLen); - for (x=0; x= event_table_len) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s : The event(%0x02x) is not valid.\n", __func__, event)); + if (event >= event_table_len) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s : The event(%0x02x) is not valid.\n", __func__, + event)); return; } - - //Allocate memory and copy the msg. - if((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL) - { - //Prepare the payload + /*Allocate memory and copy the msg. */ + if ((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL) { + /*Prepare the payload */ memset(pBuf, 0, IW_CUSTOM_MAX_LEN); pBufPtr = pBuf; if (pAddr) - pBufPtr += sprintf(pBufPtr, "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", PRINT_MAC(pAddr)); + pBufPtr += + sprintf(pBufPtr, + "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", + PRINT_MAC(pAddr)); else if (BssIdx < MAX_MBSSID_NUM) - pBufPtr += sprintf(pBufPtr, "(RT2860) BSS(wlan%d) ", BssIdx); + pBufPtr += + sprintf(pBufPtr, "(RT2860) BSS(wlan%d) ", BssIdx); else pBufPtr += sprintf(pBufPtr, "(RT2860) "); if (type == IW_SYS_EVENT_FLAG_START) - pBufPtr += sprintf(pBufPtr, "%s", pWirelessSysEventText[event]); + pBufPtr += + sprintf(pBufPtr, "%s", + pWirelessSysEventText[event]); else if (type == IW_SPOOF_EVENT_FLAG_START) - pBufPtr += sprintf(pBufPtr, "%s (RSSI=%d)", pWirelessSpoofEventText[event], Rssi); + pBufPtr += + sprintf(pBufPtr, "%s (RSSI=%d)", + pWirelessSpoofEventText[event], Rssi); else if (type == IW_FLOOD_EVENT_FLAG_START) - pBufPtr += sprintf(pBufPtr, "%s", pWirelessFloodEventText[event]); + pBufPtr += + sprintf(pBufPtr, "%s", + pWirelessFloodEventText[event]); else pBufPtr += sprintf(pBufPtr, "%s", "unknown event"); pBufPtr[pBufPtr - pBuf] = '\0'; BufLen = pBufPtr - pBuf; - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.flags = Event_flag; - wrqu.data.length = BufLen; - - //send wireless event - wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, pBuf); - - //DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __func__, pBuf)); + RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, Event_flag, NULL, + (u8 *)pBuf, BufLen); + /*DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __func__, pBuf)); */ kfree(pBuf); - } - else - DBGPRINT(RT_DEBUG_ERROR, ("%s : Can't allocate memory for wireless event.\n", __func__)); + } else + DBGPRINT(RT_DEBUG_ERROR, + ("%s : Can't allocate memory for wireless event.\n", + __func__)); } -void send_monitor_packets( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk) +void send_monitor_packets(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk) { - struct sk_buff *pOSPkt; - wlan_ng_prism2_header *ph; - int rate_index = 0; - USHORT header_len = 0; - UCHAR temp_header[40] = {0}; - - u_int32_t ralinkrate[256] = {2,4,11,22, 12,18,24,36,48,72,96, 108, 109, 110, 111, 112, 13, 26, 39, 52,78,104, 117, 130, 26, 52, 78,104, 156, 208, 234, 260, 27, 54,81,108,162, 216, 243, 270, // Last 38 - 54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115, 130, 144, 29, 59,87,115, 173, 230,260, 288, 30, 60,90,120,180,240,270,300,60,120,180,240,360,480,540,600, 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,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80}; - + struct sk_buff *pOSPkt; + struct rt_wlan_ng_prism2_header *ph; + int rate_index = 0; + u16 header_len = 0; + u8 temp_header[40] = { 0 }; + + u_int32_t ralinkrate[256] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 109, 110, 111, 112, 13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, 27, 54, 81, 108, 162, 216, 243, 270, /* Last 38 */ + 54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115, + 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, 30, 60, 90, + 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, + 600, 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, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80 + }; - ASSERT(pRxBlk->pRxPacket); - if (pRxBlk->DataSize < 10) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too small! (%d)\n", __func__, pRxBlk->DataSize)); + ASSERT(pRxBlk->pRxPacket); + if (pRxBlk->DataSize < 10) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s : Size is too small! (%d)\n", __func__, + pRxBlk->DataSize)); goto err_free_sk_buff; - } + } - if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%zu)\n", __func__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header))); + if (pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header) > + RX_BUFFER_AGGRESIZE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s : Size is too large! (%zu)\n", __func__, + pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header))); goto err_free_sk_buff; - } + } - pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); + pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0); - if (pRxBlk->pHeader->FC.Type == BTYPE_DATA) - { - pRxBlk->DataSize -= LENGTH_802_11; - if ((pRxBlk->pHeader->FC.ToDs == 1) && - (pRxBlk->pHeader->FC.FrDs == 1)) - header_len = LENGTH_802_11_WITH_ADDR4; - else - header_len = LENGTH_802_11; - - // QOS - if (pRxBlk->pHeader->FC.SubType & 0x08) - { - header_len += 2; - // Data skip QOS contorl field - pRxBlk->DataSize -=2; - } - - // Order bit: A-Ralink or HTC+ - if (pRxBlk->pHeader->FC.Order) - { - header_len += 4; - // Data skip HTC contorl field - pRxBlk->DataSize -= 4; - } - - // Copy Header - if (header_len <= 40) - NdisMoveMemory(temp_header, pRxBlk->pData, header_len); + if (pRxBlk->pHeader->FC.Type == BTYPE_DATA) { + pRxBlk->DataSize -= LENGTH_802_11; + if ((pRxBlk->pHeader->FC.ToDs == 1) && + (pRxBlk->pHeader->FC.FrDs == 1)) + header_len = LENGTH_802_11_WITH_ADDR4; + else + header_len = LENGTH_802_11; - // skip HW padding - if (pRxBlk->RxD.L2PAD) - pRxBlk->pData += (header_len + 2); - else - pRxBlk->pData += header_len; - } //end if + /* QOS */ + if (pRxBlk->pHeader->FC.SubType & 0x08) { + header_len += 2; + /* Data skip QOS contorl field */ + pRxBlk->DataSize -= 2; + } + /* Order bit: A-Ralink or HTC+ */ + if (pRxBlk->pHeader->FC.Order) { + header_len += 4; + /* Data skip HTC contorl field */ + pRxBlk->DataSize -= 4; + } + /* Copy Header */ + if (header_len <= 40) + NdisMoveMemory(temp_header, pRxBlk->pData, header_len); + /* skip HW padding */ + if (pRxBlk->RxD.L2PAD) + pRxBlk->pData += (header_len + 2); + else + pRxBlk->pData += header_len; + } /*end if */ if (pRxBlk->DataSize < pOSPkt->len) { - skb_trim(pOSPkt,pRxBlk->DataSize); - } else { - skb_put(pOSPkt,(pRxBlk->DataSize - pOSPkt->len)); - } //end if - - if ((pRxBlk->pData - pOSPkt->data) > 0) { - skb_put(pOSPkt,(pRxBlk->pData - pOSPkt->data)); - skb_pull(pOSPkt,(pRxBlk->pData - pOSPkt->data)); - } //end if - - if (skb_headroom(pOSPkt) < (sizeof(wlan_ng_prism2_header)+ header_len)) { - if (pskb_expand_head(pOSPkt, (sizeof(wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) { - DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __func__)); + skb_trim(pOSPkt, pRxBlk->DataSize); + } else { + skb_put(pOSPkt, (pRxBlk->DataSize - pOSPkt->len)); + } /*end if */ + + if ((pRxBlk->pData - pOSPkt->data) > 0) { + skb_put(pOSPkt, (pRxBlk->pData - pOSPkt->data)); + skb_pull(pOSPkt, (pRxBlk->pData - pOSPkt->data)); + } /*end if */ + + if (skb_headroom(pOSPkt) < (sizeof(struct rt_wlan_ng_prism2_header) + header_len)) { + if (pskb_expand_head + (pOSPkt, (sizeof(struct rt_wlan_ng_prism2_header) + header_len), 0, + GFP_ATOMIC)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s : Reallocate header size of sk_buff fail!\n", + __func__)); goto err_free_sk_buff; - } //end if - } //end if + } /*end if */ + } /*end if */ - if (header_len > 0) - NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len); + if (header_len > 0) + NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, + header_len); - ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, sizeof(wlan_ng_prism2_header)); - NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header)); + ph = (struct rt_wlan_ng_prism2_header *)skb_push(pOSPkt, + sizeof(struct rt_wlan_ng_prism2_header)); + NdisZeroMemory(ph, sizeof(struct rt_wlan_ng_prism2_header)); - ph->msgcode = DIDmsg_lnxind_wlansniffrm; - ph->msglen = sizeof(wlan_ng_prism2_header); - strcpy(ph->devname, pAd->net_dev->name); + ph->msgcode = DIDmsg_lnxind_wlansniffrm; + ph->msglen = sizeof(struct rt_wlan_ng_prism2_header); + strcpy((char *)ph->devname, (char *)pAd->net_dev->name); - ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; + ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; ph->hosttime.status = 0; ph->hosttime.len = 4; ph->hosttime.data = jiffies; @@ -908,63 +828,71 @@ void send_monitor_packets( ph->mactime.len = 0; ph->mactime.data = 0; - ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; + ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; ph->istx.status = 0; ph->istx.len = 0; ph->istx.data = 0; - ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; + ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; ph->channel.status = 0; ph->channel.len = 4; - ph->channel.data = (u_int32_t)pAd->CommonCfg.Channel; + ph->channel.data = (u_int32_t) pAd->CommonCfg.Channel; - ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; + ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; ph->rssi.status = 0; ph->rssi.len = 4; - ph->rssi.data = (u_int32_t)RTMPMaxRssi(pAd, ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0, RSSI_0), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI1, RSSI_1), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2, RSSI_2));; + ph->rssi.data = + (u_int32_t) RTMPMaxRssi(pAd, + ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0, + RSSI_0), ConvertToRssi(pAd, + pRxBlk-> + pRxWI-> + RSSI1, + RSSI_1), + ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2, + RSSI_2));; ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal; ph->signal.status = 0; ph->signal.len = 4; - ph->signal.data = 0; //rssi + noise; + ph->signal.data = 0; /*rssi + noise; */ ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise; ph->noise.status = 0; ph->noise.len = 4; ph->noise.data = 0; - if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX) - { - rate_index = 16 + ((UCHAR)pRxBlk->pRxWI->BW *16) + ((UCHAR)pRxBlk->pRxWI->ShortGI *32) + ((UCHAR)pRxBlk->pRxWI->MCS); - } - else - if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM) - rate_index = (UCHAR)(pRxBlk->pRxWI->MCS) + 4; - else - rate_index = (UCHAR)(pRxBlk->pRxWI->MCS); - if (rate_index < 0) - rate_index = 0; - if (rate_index > 255) - rate_index = 255; + if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX) { + rate_index = + 16 + ((u8)pRxBlk->pRxWI->BW * 16) + + ((u8)pRxBlk->pRxWI->ShortGI * 32) + + ((u8)pRxBlk->pRxWI->MCS); + } else if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM) + rate_index = (u8)(pRxBlk->pRxWI->MCS) + 4; + else + rate_index = (u8)(pRxBlk->pRxWI->MCS); + if (rate_index < 0) + rate_index = 0; + if (rate_index > 255) + rate_index = 255; ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; ph->rate.status = 0; ph->rate.len = 4; - ph->rate.data = ralinkrate[rate_index]; + ph->rate.data = ralinkrate[rate_index]; ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; - ph->frmlen.status = 0; + ph->frmlen.status = 0; ph->frmlen.len = 4; - ph->frmlen.data = (u_int32_t)pRxBlk->DataSize; - + ph->frmlen.data = (u_int32_t) pRxBlk->DataSize; - pOSPkt->pkt_type = PACKET_OTHERHOST; - pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev); - pOSPkt->ip_summed = CHECKSUM_NONE; - netif_rx(pOSPkt); + pOSPkt->pkt_type = PACKET_OTHERHOST; + pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev); + pOSPkt->ip_summed = CHECKSUM_NONE; + netif_rx(pOSPkt); - return; + return; err_free_sk_buff: RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); @@ -972,31 +900,470 @@ err_free_sk_buff: } -void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify) +/******************************************************************************* + + Device IRQ related functions. + + *******************************************************************************/ +int RtmpOSIRQRequest(struct net_device *pNetDev) +{ +#ifdef RTMP_PCI_SUPPORT + struct net_device *net_dev = pNetDev; + struct rt_rtmp_adapter *pAd = NULL; + int retval = 0; + + GET_PAD_FROM_NET_DEV(pAd, pNetDev); + + ASSERT(pAd); + + if (pAd->infType == RTMP_DEV_INF_PCI) { + struct os_cookie *_pObj = (struct os_cookie *)(pAd->OS_Cookie); + RTMP_MSI_ENABLE(pAd); + retval = + request_irq(_pObj->pci_dev->irq, rt2860_interrupt, SA_SHIRQ, + (net_dev)->name, (net_dev)); + if (retval != 0) + printk("RT2860: request_irq ERROR(%d)\n", retval); + } + + return retval; +#else + return 0; +#endif +} + +int RtmpOSIRQRelease(struct net_device *pNetDev) +{ + struct net_device *net_dev = pNetDev; + struct rt_rtmp_adapter *pAd = NULL; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + ASSERT(pAd); + +#ifdef RTMP_PCI_SUPPORT + if (pAd->infType == RTMP_DEV_INF_PCI) { + struct os_cookie *pObj = (struct os_cookie *)(pAd->OS_Cookie); + synchronize_irq(pObj->pci_dev->irq); + free_irq(pObj->pci_dev->irq, (net_dev)); + RTMP_MSI_DISABLE(pAd); + } +#endif /* RTMP_PCI_SUPPORT // */ + + return 0; +} + +/******************************************************************************* + + File open/close related functions. + + *******************************************************************************/ +struct file *RtmpOSFileOpen(char *pPath, int flag, int mode) { - daemonize(pThreadName /*"%s",pAd->net_dev->name*/); + struct file *filePtr; + + filePtr = filp_open(pPath, flag, 0); + if (IS_ERR(filePtr)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): Error %ld opening %s\n", __func__, + -PTR_ERR(filePtr), pPath)); + } + + return (struct file *)filePtr; +} + +int RtmpOSFileClose(struct file *osfd) +{ + filp_close(osfd, NULL); + return 0; +} + +void RtmpOSFileSeek(struct file *osfd, int offset) +{ + osfd->f_pos = offset; +} + +int RtmpOSFileRead(struct file *osfd, char *pDataPtr, int readLen) +{ + /* The object must have a read method */ + if (osfd->f_op && osfd->f_op->read) { + return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n")); + return -1; + } +} + +int RtmpOSFileWrite(struct file *osfd, char *pDataPtr, int writeLen) +{ + return osfd->f_op->write(osfd, pDataPtr, (size_t) writeLen, + &osfd->f_pos); +} + +/******************************************************************************* + + Task create/management/kill related functions. + + *******************************************************************************/ +int RtmpOSTaskKill(struct rt_rtmp_os_task *pTask) +{ + struct rt_rtmp_adapter *pAd; + int ret = NDIS_STATUS_FAILURE; + + pAd = (struct rt_rtmp_adapter *)pTask->priv; + +#ifdef KTHREAD_SUPPORT + if (pTask->kthread_task) { + kthread_stop(pTask->kthread_task); + ret = NDIS_STATUS_SUCCESS; + } +#else + CHECK_PID_LEGALITY(pTask->taskPID) { + printk("Terminate the task(%s) with pid(%d)!\n", + pTask->taskName, GET_PID_NUMBER(pTask->taskPID)); + mb(); + pTask->task_killed = 1; + mb(); + ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1); + if (ret) { + printk(KERN_WARNING + "kill task(%s) with pid(%d) failed(retVal=%d)!\n", + pTask->taskName, GET_PID_NUMBER(pTask->taskPID), + ret); + } else { + wait_for_completion(&pTask->taskComplete); + pTask->taskPID = THREAD_PID_INIT_VALUE; + pTask->task_killed = 0; + ret = NDIS_STATUS_SUCCESS; + } + } +#endif + + return ret; + +} + +int RtmpOSTaskNotifyToExit(struct rt_rtmp_os_task *pTask) +{ + +#ifndef KTHREAD_SUPPORT + complete_and_exit(&pTask->taskComplete, 0); +#endif + + return 0; +} + +void RtmpOSTaskCustomize(struct rt_rtmp_os_task *pTask) +{ + +#ifndef KTHREAD_SUPPORT + + daemonize((char *)& pTask->taskName[0] /*"%s",pAd->net_dev->name */ ); allow_signal(SIGTERM); allow_signal(SIGKILL); current->flags |= PF_NOFREEZE; /* signal that we've started the thread */ - complete(pNotify); + complete(&pTask->taskComplete); + +#endif } -void RTMP_IndicateMediaState( - IN PRTMP_ADAPTER pAd) +int RtmpOSTaskAttach(struct rt_rtmp_os_task *pTask, + IN int (*fn) (void *), IN void *arg) { - if (pAd->CommonCfg.bWirelessEvent) - { - if (pAd->IndicateMediaState == NdisMediaStateConnected) - { - RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + int status = NDIS_STATUS_SUCCESS; + +#ifdef KTHREAD_SUPPORT + pTask->task_killed = 0; + pTask->kthread_task = NULL; + pTask->kthread_task = kthread_run(fn, arg, pTask->taskName); + if (IS_ERR(pTask->kthread_task)) + status = NDIS_STATUS_FAILURE; +#else + pid_number = kernel_thread(fn, arg, RTMP_OS_MGMT_TASK_FLAGS); + if (pid_number < 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("Attach task(%s) failed!\n", pTask->taskName)); + status = NDIS_STATUS_FAILURE; + } else { + pTask->taskPID = GET_PID(pid_number); + + /* Wait for the thread to start */ + wait_for_completion(&pTask->taskComplete); + status = NDIS_STATUS_SUCCESS; + } +#endif + return status; +} + +int RtmpOSTaskInit(struct rt_rtmp_os_task *pTask, + char *pTaskName, void * pPriv) +{ + int len; + + ASSERT(pTask); + +#ifndef KTHREAD_SUPPORT + NdisZeroMemory((u8 *)(pTask), sizeof(struct rt_rtmp_os_task)); +#endif + + len = strlen(pTaskName); + len = + len > + (RTMP_OS_TASK_NAME_LEN - 1) ? (RTMP_OS_TASK_NAME_LEN - 1) : len; + NdisMoveMemory(&pTask->taskName[0], pTaskName, len); + pTask->priv = pPriv; + +#ifndef KTHREAD_SUPPORT + RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema)); + pTask->taskPID = THREAD_PID_INIT_VALUE; + + init_completion(&pTask->taskComplete); +#endif + + return NDIS_STATUS_SUCCESS; +} + +void RTMP_IndicateMediaState(struct rt_rtmp_adapter *pAd) +{ + if (pAd->CommonCfg.bWirelessEvent) { + if (pAd->IndicateMediaState == NdisMediaStateConnected) { + RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, + pAd->MacTab.Content[BSSID_WCID]. + Addr, BSS0, 0); + } else { + RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, + pAd->MacTab.Content[BSSID_WCID]. + Addr, BSS0, 0); } + } +} + +int RtmpOSWrielessEventSend(struct rt_rtmp_adapter *pAd, + u32 eventType, + int flags, + u8 *pSrcMac, + u8 *pData, u32 dataLen) +{ + union iwreq_data wrqu; + + memset(&wrqu, 0, sizeof(wrqu)); + + if (flags > -1) + wrqu.data.flags = flags; + + if (pSrcMac) + memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN); + + if ((pData != NULL) && (dataLen > 0)) + wrqu.data.length = dataLen; + + wireless_send_event(pAd->net_dev, eventType, &wrqu, (char *)pData); + return 0; +} + +int RtmpOSNetDevAddrSet(struct net_device *pNetDev, u8 *pMacAddr) +{ + struct net_device *net_dev; + struct rt_rtmp_adapter *pAd; + + net_dev = pNetDev; + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + /* work-around for the SuSE due to it has it's own interface name management system. */ + { + NdisZeroMemory(pAd->StaCfg.dev_name, 16); + NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, + strlen(net_dev->name)); + } + + NdisMoveMemory(net_dev->dev_addr, pMacAddr, 6); + + return 0; +} + +/* + * Assign the network dev name for created Ralink WiFi interface. + */ +static int RtmpOSNetDevRequestName(struct rt_rtmp_adapter *pAd, + struct net_device *dev, + char *pPrefixStr, int devIdx) +{ + struct net_device *existNetDev; + char suffixName[IFNAMSIZ]; + char desiredName[IFNAMSIZ]; + int ifNameIdx, prefixLen, slotNameLen; + int Status; + + prefixLen = strlen(pPrefixStr); + ASSERT((prefixLen < IFNAMSIZ)); + + for (ifNameIdx = devIdx; ifNameIdx < 32; ifNameIdx++) { + memset(suffixName, 0, IFNAMSIZ); + memset(desiredName, 0, IFNAMSIZ); + strncpy(&desiredName[0], pPrefixStr, prefixLen); + + sprintf(suffixName, "%d", ifNameIdx); + + slotNameLen = strlen(suffixName); + ASSERT(((slotNameLen + prefixLen) < IFNAMSIZ)); + strcat(desiredName, suffixName); + + existNetDev = RtmpOSNetDevGetByName(dev, &desiredName[0]); + if (existNetDev == NULL) + break; else - { - RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + RtmpOSNetDeviceRefPut(existNetDev); + } + + if (ifNameIdx < 32) { + strcpy(&dev->name[0], &desiredName[0]); + Status = NDIS_STATUS_SUCCESS; + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("Cannot request DevName with preifx(%s) and in range(0~32) as suffix from OS!\n", + pPrefixStr)); + Status = NDIS_STATUS_FAILURE; + } + + return Status; +} + +void RtmpOSNetDevClose(struct net_device *pNetDev) +{ + dev_close(pNetDev); +} + +void RtmpOSNetDevFree(struct net_device *pNetDev) +{ + ASSERT(pNetDev); + + free_netdev(pNetDev); +} + +int RtmpOSNetDevAlloc(struct net_device ** new_dev_p, u32 privDataSize) +{ + /* assign it as null first. */ + *new_dev_p = NULL; + + DBGPRINT(RT_DEBUG_TRACE, + ("Allocate a net device with private data size=%d!\n", + privDataSize)); + *new_dev_p = alloc_etherdev(privDataSize); + if (*new_dev_p) + return NDIS_STATUS_SUCCESS; + else + return NDIS_STATUS_FAILURE; +} + +struct net_device *RtmpOSNetDevGetByName(struct net_device *pNetDev, char *pDevName) +{ + struct net_device *pTargetNetDev = NULL; + + pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName); + + return pTargetNetDev; +} + +void RtmpOSNetDeviceRefPut(struct net_device *pNetDev) +{ + /* + every time dev_get_by_name is called, and it has returned a valid struct + net_device*, dev_put should be called afterwards, because otherwise the + machine hangs when the device is unregistered (since dev->refcnt > 1). + */ + if (pNetDev) + dev_put(pNetDev); +} + +int RtmpOSNetDevDestory(struct rt_rtmp_adapter *pAd, struct net_device *pNetDev) +{ + + /* TODO: Need to fix this */ + printk("WARNING: This function(%s) not implement yet!\n", __func__); + return 0; +} + +void RtmpOSNetDevDetach(struct net_device *pNetDev) +{ + unregister_netdev(pNetDev); +} + +int RtmpOSNetDevAttach(struct net_device *pNetDev, + struct rt_rtmp_os_netdev_op_hook *pDevOpHook) +{ + int ret, rtnl_locked = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n")); + /* If we need hook some callback function to the net device structrue, now do it. */ + if (pDevOpHook) { + struct rt_rtmp_adapter *pAd = NULL; + + GET_PAD_FROM_NET_DEV(pAd, pNetDev); + + pNetDev->netdev_ops = pDevOpHook->netdev_ops; + + /* OS specific flags, here we used to indicate if we are virtual interface */ + pNetDev->priv_flags = pDevOpHook->priv_flags; + + if (pAd->OpMode == OPMODE_STA) { + pNetDev->wireless_handlers = &rt28xx_iw_handler_def; } + + /* copy the net device mac address to the net_device structure. */ + NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0], + MAC_ADDR_LEN); + + rtnl_locked = pDevOpHook->needProtcted; } + + if (rtnl_locked) + ret = register_netdevice(pNetDev); + else + ret = register_netdev(pNetDev); + + DBGPRINT(RT_DEBUG_TRACE, ("<---RtmpOSNetDevAttach(), ret=%d\n", ret)); + if (ret == 0) + return NDIS_STATUS_SUCCESS; + else + return NDIS_STATUS_FAILURE; } +struct net_device *RtmpOSNetDevCreate(struct rt_rtmp_adapter *pAd, + int devType, + int devNum, + int privMemSize, char *pNamePrefix) +{ + struct net_device *pNetDev = NULL; + int status; + + /* allocate a new network device */ + status = RtmpOSNetDevAlloc(&pNetDev, 0 /*privMemSize */ ); + if (status != NDIS_STATUS_SUCCESS) { + /* allocation fail, exit */ + DBGPRINT(RT_DEBUG_ERROR, + ("Allocate network device fail (%s)...\n", + pNamePrefix)); + return NULL; + } + + /* find a available interface name, max 32 interfaces */ + status = RtmpOSNetDevRequestName(pAd, pNetDev, pNamePrefix, devNum); + if (status != NDIS_STATUS_SUCCESS) { + /* error! no any available ra name can be used! */ + DBGPRINT(RT_DEBUG_ERROR, + ("Assign interface name (%s with suffix 0~32) failed...\n", + pNamePrefix)); + RtmpOSNetDevFree(pNetDev); + + return NULL; + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("The name of the new %s interface is %s...\n", + pNamePrefix, pNetDev->name)); + } + + return pNetDev; +} diff --git a/drivers/staging/rt2860/rt_linux.h b/drivers/staging/rt2860/rt_linux.h index e8d64c30b906753c32124f02a33473ff8fa6d0e5..f85508d9d5a99cd9e237e1e886eb62cbd1d9ea2e 100644 --- a/drivers/staging/rt2860/rt_linux.h +++ b/drivers/staging/rt2860/rt_linux.h @@ -23,27 +23,22 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * ************************************************************************* - */ -/***********************************************************************/ -/* */ -/* Program: rt_linux.c */ -/* Created: 4/21/2006 1:17:38 PM */ -/* Author: Wu Xi-Kun */ -/* Comments: `description` */ -/* */ -/*---------------------------------------------------------------------*/ -/* */ -/* History: */ -/* Revision 1.1 4/21/2006 1:17:38 PM xsikun */ -/* Initial revision */ -/* */ -/***********************************************************************/ - -#include "rtmp_type.h" + Module Name: + rt_linux.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + +#ifndef __RT_LINUX_H__ +#define __RT_LINUX_H__ + #include #include - #include #include #include @@ -65,64 +60,57 @@ #include -// load firmware +/* load firmware */ #define __KERNEL_SYSCALLS__ #include #include - - -#define MEM_ALLOC_FLAG (GFP_ATOMIC) //(GFP_DMA | GFP_ATOMIC) - -#ifndef IFNAMSIZ -#define IFNAMSIZ 16 -#endif - -//#define CONFIG_CKIP_SUPPORT - +#include +#include /* for get_unaligned() */ + +#define KTHREAD_SUPPORT 1 +/* RT2870 2.1.0.0 has it disabled */ + +#ifdef KTHREAD_SUPPORT +#include +#include +#endif /* KTHREAD_SUPPORT // */ + +/*********************************************************************************** + * Profile related sections + ***********************************************************************************/ + +#ifdef RTMP_MAC_PCI +#define STA_DRIVER_VERSION "2.1.0.0" +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB +#define STA_DRIVER_VERSION "2.1.0.0" +/* RT3070 version: 2.1.1.0 */ +#endif /* RTMP_MAC_USB // */ + +extern const struct iw_handler_def rt28xx_iw_handler_def; + +/*********************************************************************************** + * Compiler related definitions + ***********************************************************************************/ #undef __inline #define __inline static inline +#define IN +#define OUT +#define INOUT -typedef int (*HARD_START_XMIT_FUNC)(struct sk_buff *skb, struct net_device *net_dev); - -// add by kathy - -/* order of "if defined()" is important, because for 3070 driver - both RT2870 and RT3070 are defined */ -#if defined(RT2860) - #define STA_PROFILE_PATH "/etc/Wireless/RT2860STA/RT2860STA.dat" - #define STA_RTMP_FIRMWARE_FILE_NAME "/etc/Wireless/RT2860STA/RT2860STA.bin" - #define STA_NIC_DEVICE_NAME "RT2860STA" - #define STA_DRIVER_VERSION "1.8.1.1" -#elif defined(RT3070) - #define STA_PROFILE_PATH "/etc/Wireless/RT3070STA/RT3070STA.dat" - #define STA_RT2870_IMAGE_FILE_NAME "/etc/Wireless/RT3070STA/rt2870.bin" - #define STA_NIC_DEVICE_NAME "RT3070STA" - #define STA_DRIVER_VERSION "2.0.1.0" -#elif defined(RT2870) - #define STA_PROFILE_PATH "/etc/Wireless/RT2870STA/RT2870STA.dat" - #define STA_RT2870_IMAGE_FILE_NAME "/etc/Wireless/RT2870STA/rt2870.bin" - #define STA_NIC_DEVICE_NAME "RT2870STA" - #define STA_DRIVER_VERSION "1.4.0.0" -#endif +/*********************************************************************************** + * OS Specific definitions and data structures + ***********************************************************************************/ +typedef int (*HARD_START_XMIT_FUNC) (struct sk_buff * skb, + struct net_device * net_dev); -#ifdef RT2860 +#ifdef RTMP_MAC_PCI #ifndef PCI_DEVICE #define PCI_DEVICE(vend,dev) \ .vendor = (vend), .device = (dev), \ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID -#endif // PCI_DEVICE // -#endif - -#define RTMP_TIME_AFTER(a,b) \ - (typecheck(unsigned long, (unsigned long)a) && \ - typecheck(unsigned long, (unsigned long)b) && \ - ((long)(b) - (long)(a) < 0)) - -#define RTMP_TIME_AFTER_EQ(a,b) \ - (typecheck(unsigned long, (unsigned long)a) && \ - typecheck(unsigned long, (unsigned long)b) && \ - ((long)(a) - (long)(b) >= 0)) -#define RTMP_TIME_BEFORE(a,b) RTMP_TIME_AFTER_EQ(b,a) +#endif /* PCI_DEVICE // */ +#endif /* RTMP_MAC_PCI // */ #define RT_MOD_INC_USE_COUNT() \ if (!try_module_get(THIS_MODULE)) \ @@ -133,227 +121,313 @@ typedef int (*HARD_START_XMIT_FUNC)(struct sk_buff *skb, struct net_device *net_ #define RT_MOD_DEC_USE_COUNT() module_put(THIS_MODULE); -#define OS_HZ HZ +#define RTMP_INC_REF(_A) 0 +#define RTMP_DEC_REF(_A) 0 +#define RTMP_GET_REF(_A) 0 -#define ETH_LENGTH_OF_ADDRESS 6 +/* This function will be called when query /proc */ +struct iw_statistics *rt28xx_get_wireless_stats(IN struct net_device *net_dev); -#define IN -#define OUT +/*********************************************************************************** + * Network related constant definitions + ***********************************************************************************/ +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif + +#define ETH_LENGTH_OF_ADDRESS 6 -#define NDIS_STATUS INT #define NDIS_STATUS_SUCCESS 0x00 #define NDIS_STATUS_FAILURE 0x01 #define NDIS_STATUS_INVALID_DATA 0x02 #define NDIS_STATUS_RESOURCES 0x03 -#define MIN_NET_DEVICE_FOR_AID 0x00 //0x00~0x3f -#define MIN_NET_DEVICE_FOR_MBSSID 0x00 //0x00,0x10,0x20,0x30 -#define MIN_NET_DEVICE_FOR_WDS 0x10 //0x40,0x50,0x60,0x70 +#define NDIS_SET_PACKET_STATUS(_p, _status) do{} while(0) +#define NdisWriteErrorLogEntry(_a, _b, _c, _d) do{} while(0) + +/* statistics counter */ +#define STATS_INC_RX_PACKETS(_pAd, _dev) +#define STATS_INC_TX_PACKETS(_pAd, _dev) + +#define STATS_INC_RX_BYTESS(_pAd, _dev, len) +#define STATS_INC_TX_BYTESS(_pAd, _dev, len) + +#define STATS_INC_RX_ERRORS(_pAd, _dev) +#define STATS_INC_TX_ERRORS(_pAd, _dev) + +#define STATS_INC_RX_DROPPED(_pAd, _dev) +#define STATS_INC_TX_DROPPED(_pAd, _dev) + +/*********************************************************************************** + * Ralink Specific network related constant definitions + ***********************************************************************************/ +#define MIN_NET_DEVICE_FOR_AID 0x00 /*0x00~0x3f */ +#define MIN_NET_DEVICE_FOR_MBSSID 0x00 /*0x00,0x10,0x20,0x30 */ +#define MIN_NET_DEVICE_FOR_WDS 0x10 /*0x40,0x50,0x60,0x70 */ #define MIN_NET_DEVICE_FOR_APCLI 0x20 #define MIN_NET_DEVICE_FOR_MESH 0x30 #define MIN_NET_DEVICE_FOR_DLS 0x40 +#define NET_DEVICE_REAL_IDX_MASK 0x0f /* for each operation mode, we maximum support 15 entities. */ #define NDIS_PACKET_TYPE_DIRECTED 0 #define NDIS_PACKET_TYPE_MULTICAST 1 #define NDIS_PACKET_TYPE_BROADCAST 2 #define NDIS_PACKET_TYPE_ALL_MULTICAST 3 - -struct os_lock { - spinlock_t lock; - unsigned long flags; +#define NDIS_PACKET_TYPE_PROMISCUOUS 4 + +/*********************************************************************************** + * OS signaling related constant definitions + ***********************************************************************************/ + +/*********************************************************************************** + * OS file operation related data structure definitions + ***********************************************************************************/ +struct rt_rtmp_os_fs_info { + int fsuid; + int fsgid; + mm_segment_t fs; }; +#define IS_FILE_OPEN_ERR(_fd) IS_ERR((_fd)) -struct os_cookie { -#ifdef RT2860 - struct pci_dev *pci_dev; - struct pci_dev *parent_pci_dev; - dma_addr_t pAd_pa; -#endif -#ifdef RT2870 - struct usb_device *pUsb_Dev; - - struct pid *MLMEThr_pid; - struct pid *RTUSBCmdThr_pid; - struct pid *TimerQThr_pid; -#endif // RT2870 // - - struct tasklet_struct rx_done_task; - struct tasklet_struct mgmt_dma_done_task; - struct tasklet_struct ac0_dma_done_task; - struct tasklet_struct ac1_dma_done_task; - struct tasklet_struct ac2_dma_done_task; - struct tasklet_struct ac3_dma_done_task; - struct tasklet_struct hcca_dma_done_task; - struct tasklet_struct tbtt_task; -#ifdef RT2860 - struct tasklet_struct fifo_statistic_full_task; -#endif -#ifdef RT2870 - struct tasklet_struct null_frame_complete_task; - struct tasklet_struct rts_frame_complete_task; - struct tasklet_struct pspoll_frame_complete_task; -#endif // RT2870 // - - unsigned long apd_pid; //802.1x daemon pid - INT ioctl_if_type; - INT ioctl_if; +/*********************************************************************************** + * OS semaphore related data structure and definitions + ***********************************************************************************/ +struct os_lock { + spinlock_t lock; + unsigned long flags; }; -#undef ASSERT -#define ASSERT(x) - -typedef struct os_cookie * POS_COOKIE; -typedef struct pci_dev * PPCI_DEV; -typedef struct net_device * PNET_DEV; -typedef void * PNDIS_PACKET; -typedef char NDIS_PACKET; -typedef PNDIS_PACKET * PPNDIS_PACKET; -typedef dma_addr_t NDIS_PHYSICAL_ADDRESS; -typedef dma_addr_t * PNDIS_PHYSICAL_ADDRESS; -typedef spinlock_t NDIS_SPIN_LOCK; -typedef struct timer_list NDIS_MINIPORT_TIMER; -typedef void * NDIS_HANDLE; -typedef char * PNDIS_BUFFER; - - - -void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen); +/* */ +/* spin_lock enhanced for Nested spin lock */ +/* */ +#define NdisAllocateSpinLock(__lock) \ +{ \ + spin_lock_init((spinlock_t *)(__lock)); \ +} -dma_addr_t linux_pci_map_single(void *handle, void *ptr, size_t size, int sd_idx, int direction); -void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size, int direction); +#define NdisFreeSpinLock(lock) \ + do{}while(0) +#define RTMP_SEM_LOCK(__lock) \ +{ \ + spin_lock_bh((spinlock_t *)(__lock)); \ +} -//////////////////////////////////////// -// MOVE TO rtmp.h ? -///////////////////////////////////////// -#define PKTSRC_NDIS 0x7f -#define PKTSRC_DRIVER 0x0f -#define PRINT_MAC(addr) \ - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] +#define RTMP_SEM_UNLOCK(__lock) \ +{ \ + spin_unlock_bh((spinlock_t *)(__lock)); \ +} +/* sample, use semaphore lock to replace IRQ lock, 2007/11/15 */ +#define RTMP_IRQ_LOCK(__lock, __irqflags) \ +{ \ + __irqflags = 0; \ + spin_lock_bh((spinlock_t *)(__lock)); \ + pAd->irq_disabled |= 1; \ +} -#define RT2860_PCI_DEVICE_ID 0x0601 +#define RTMP_IRQ_UNLOCK(__lock, __irqflag) \ +{ \ + pAd->irq_disabled &= 0; \ + spin_unlock_bh((spinlock_t *)(__lock)); \ +} -#ifdef RT2860 -#define PCI_MAP_SINGLE(_handle, _ptr, _size, _sd_idx, _dir) \ - linux_pci_map_single(_handle, _ptr, _size, _sd_idx, _dir) +#define RTMP_INT_LOCK(__lock, __irqflags) \ +{ \ + spin_lock_irqsave((spinlock_t *)__lock, __irqflags); \ +} -#define PCI_UNMAP_SINGLE(_handle, _ptr, _size, _dir) \ - linux_pci_unmap_single(_handle, _ptr, _size, _dir) +#define RTMP_INT_UNLOCK(__lock, __irqflag) \ +{ \ + spin_unlock_irqrestore((spinlock_t *)(__lock), ((unsigned long)__irqflag)); \ +} -#define PCI_ALLOC_CONSISTENT(_pci_dev, _size, _ptr) \ - pci_alloc_consistent(_pci_dev, _size, _ptr) +#define NdisAcquireSpinLock RTMP_SEM_LOCK +#define NdisReleaseSpinLock RTMP_SEM_UNLOCK -#define PCI_FREE_CONSISTENT(_pci_dev, _size, _virtual_addr, _physical_addr) \ - pci_free_consistent(_pci_dev, _size, _virtual_addr, _physical_addr) +#ifndef wait_event_interruptible_timeout +#define __wait_event_interruptible_timeout(wq, condition, 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)) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) -#define DEV_ALLOC_SKB(_length) \ - dev_alloc_skb(_length) +#define wait_event_interruptible_timeout(wq, condition, timeout) \ +({ \ + long __ret = timeout; \ + if (!(condition)) \ + __wait_event_interruptible_timeout(wq, condition, __ret); \ + __ret; \ +}) #endif -#ifdef RT2870 -#define PCI_MAP_SINGLE(_handle, _ptr, _size, _dir) (ULONG)0 - -#define PCI_UNMAP_SINGLE(_handle, _ptr, _size, _dir) -#endif // RT2870 // - - -#define BEACON_FRAME_DMA_CACHE_WBACK(_ptr, _size) \ - dma_cache_wback(_ptr, _size) - -////////////////////////////////////////// -// -////////////////////////////////////////// +#define RTMP_SEM_EVENT_INIT_LOCKED(_pSema) sema_init((_pSema), 0) +#define RTMP_SEM_EVENT_INIT(_pSema) sema_init((_pSema), 1) +#define RTMP_SEM_EVENT_WAIT(_pSema, _status) ((_status) = down_interruptible((_pSema))) +#define RTMP_SEM_EVENT_UP(_pSema) up(_pSema) + +#ifdef KTHREAD_SUPPORT +#define RTMP_WAIT_EVENT_INTERRUPTIBLE(_pAd, _pTask) \ +{ \ + wait_event_interruptible(_pTask->kthread_q, \ + _pTask->kthread_running || kthread_should_stop()); \ + _pTask->kthread_running = FALSE; \ + if (kthread_should_stop()) \ + { \ + RTMP_SET_FLAG(_pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); \ + break; \ + } \ +} +#endif +#ifdef KTHREAD_SUPPORT +#define WAKE_UP(_pTask) \ + do{ \ + if ((_pTask)->kthread_task) \ + { \ + (_pTask)->kthread_running = TRUE; \ + wake_up(&(_pTask)->kthread_q); \ + } \ + }while(0) +#endif -#define NdisMIndicateStatus(_w, _x, _y, _z) +/*********************************************************************************** + * OS Memory Access related data structure and definitions + ***********************************************************************************/ +#define MEM_ALLOC_FLAG (GFP_ATOMIC) /*(GFP_DMA | GFP_ATOMIC) */ -typedef struct timer_list RTMP_OS_TIMER; +#define NdisMoveMemory(Destination, Source, Length) memmove(Destination, Source, Length) +#define NdisCopyMemory(Destination, Source, Length) memcpy(Destination, Source, Length) +#define NdisZeroMemory(Destination, Length) memset(Destination, 0, Length) +#define NdisFillMemory(Destination, Length, Fill) memset(Destination, Fill, Length) +#define NdisCmpMemory(Destination, Source, Length) memcmp(Destination, Source, Length) +#define NdisEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) +#define RTMPEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) -#ifdef RT2870 -/* ----------------- Timer Related MARCO ---------------*/ -// In RT2870, we have a lot of timer functions and will read/write register, it's -// not allowed in Linux USB sub-system to do it ( because of sleep issue when submit -// to ctrl pipe). So we need a wrapper function to take care it. +#define MlmeAllocateMemory(_pAd, _ppVA) os_alloc_mem(_pAd, _ppVA, MGMT_DMA_BUFFER_SIZE) +#define MlmeFreeMemory(_pAd, _pVA) os_free_mem(_pAd, _pVA) -typedef VOID (*RT2870_TIMER_HANDLE)( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); -#endif // RT2870 // +#define COPY_MAC_ADDR(Addr1, Addr2) memcpy((Addr1), (Addr2), MAC_ADDR_LEN) +/*********************************************************************************** + * OS task related data structure and definitions + ***********************************************************************************/ +#define RTMP_OS_MGMT_TASK_FLAGS CLONE_VM -typedef struct _RALINK_TIMER_STRUCT { - RTMP_OS_TIMER TimerObj; // Ndis Timer object - BOOLEAN Valid; // Set to True when call RTMPInitTimer - BOOLEAN State; // True if timer cancelled - BOOLEAN PeriodicType; // True if timer is periodic timer - BOOLEAN Repeat; // True if periodic timer - ULONG TimerValue; // Timer value in milliseconds - ULONG cookie; // os specific object -#ifdef RT2870 - RT2870_TIMER_HANDLE handle; - void *pAd; -#endif // RT2870 // -} RALINK_TIMER_STRUCT, *PRALINK_TIMER_STRUCT; +#define THREAD_PID_INIT_VALUE NULL +#define GET_PID(_v) find_get_pid((_v)) +#define GET_PID_NUMBER(_v) pid_nr((_v)) +#define CHECK_PID_LEGALITY(_pid) if (pid_nr((_pid)) > 0) +#define KILL_THREAD_PID(_A, _B, _C) kill_pid((_A), (_B), (_C)) +/*********************************************************************************** + * Timer related definitions and data structures. + **********************************************************************************/ +#define OS_HZ HZ -#ifdef RT2870 +typedef void (*TIMER_FUNCTION) (unsigned long); -typedef enum _RT2870_KERNEL_THREAD_STATUS_ -{ - RT2870_THREAD_UNKNOWN = 0, - RT2870_THREAD_INITED = 1, - RT2870_THREAD_RUNNING = 2, - RT2870_THREAD_STOPED = 4, -}RT2870_KERNEL_THREAD_STATUS; +#define OS_WAIT(_time) \ +{ int _i; \ + long _loop = ((_time)/(1000/OS_HZ)) > 0 ? ((_time)/(1000/OS_HZ)) : 1;\ + wait_queue_head_t _wait; \ + init_waitqueue_head(&_wait); \ + for (_i=0; _i<(_loop); _i++) \ + wait_event_interruptible_timeout(_wait, 0, ONE_TICK); } -#define RT2870_THREAD_CAN_DO_INSERT (RT2870_THREAD_INITED |RT2870_THREAD_RUNNING) +#define RTMP_TIME_AFTER(a,b) \ + (typecheck(unsigned long, (unsigned long)a) && \ + typecheck(unsigned long, (unsigned long)b) && \ + ((long)(b) - (long)(a) < 0)) -typedef struct _RT2870_TIMER_ENTRY_ -{ - RALINK_TIMER_STRUCT *pRaTimer; - struct _RT2870_TIMER_ENTRY_ *pNext; -}RT2870_TIMER_ENTRY; +#define RTMP_TIME_AFTER_EQ(a,b) \ + (typecheck(unsigned long, (unsigned long)a) && \ + typecheck(unsigned long, (unsigned long)b) && \ + ((long)(a) - (long)(b) >= 0)) +#define RTMP_TIME_BEFORE(a,b) RTMP_TIME_AFTER_EQ(b,a) +#define ONE_TICK 1 -#define TIMER_QUEUE_SIZE_MAX 128 -typedef struct _RT2870_TIMER_QUEUE_ +static inline void NdisGetSystemUpTime(unsigned long * time) { - unsigned int status; - UCHAR *pTimerQPoll; - RT2870_TIMER_ENTRY *pQPollFreeList; - RT2870_TIMER_ENTRY *pQHead; - RT2870_TIMER_ENTRY *pQTail; -}RT2870_TIMER_QUEUE; -#endif // RT2870 // + *time = jiffies; +} +/*********************************************************************************** + * OS specific cookie data structure binding to struct rt_rtmp_adapter + ***********************************************************************************/ -//#define DBG 1 +struct os_cookie { +#ifdef RTMP_MAC_PCI + struct pci_dev *pci_dev; + struct pci_dev *parent_pci_dev; + u16 DeviceID; + dma_addr_t pAd_pa; +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + struct usb_device *pUsb_Dev; +#endif /* RTMP_MAC_USB // */ + + struct tasklet_struct rx_done_task; + struct tasklet_struct mgmt_dma_done_task; + struct tasklet_struct ac0_dma_done_task; + struct tasklet_struct ac1_dma_done_task; + struct tasklet_struct ac2_dma_done_task; + struct tasklet_struct ac3_dma_done_task; + struct tasklet_struct tbtt_task; +#ifdef RTMP_MAC_PCI + struct tasklet_struct fifo_statistic_full_task; +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + struct tasklet_struct null_frame_complete_task; + struct tasklet_struct rts_frame_complete_task; + struct tasklet_struct pspoll_frame_complete_task; +#endif /* RTMP_MAC_USB // */ + + unsigned long apd_pid; /*802.1x daemon pid */ + int ioctl_if_type; + int ioctl_if; +}; -// -// MACRO for debugging information -// +/*********************************************************************************** + * OS debugging and printing related definitions and data structure + ***********************************************************************************/ +#define PRINT_MAC(addr) \ + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] #ifdef DBG -extern ULONG RTDebugLevel; +extern unsigned long RTDebugLevel; #define DBGPRINT_RAW(Level, Fmt) \ -{ \ +do{ \ if (Level <= RTDebugLevel) \ { \ printk Fmt; \ } \ -} +}while(0) #define DBGPRINT(Level, Fmt) DBGPRINT_RAW(Level, Fmt) - #define DBGPRINT_ERR(Fmt) \ { \ - printk("ERROR!!! "); \ + printk("ERROR! "); \ printk Fmt; \ } @@ -362,7 +436,6 @@ extern ULONG RTDebugLevel; printk Fmt; \ } - #else #define DBGPRINT(Level, Fmt) #define DBGPRINT_RAW(Level, Fmt) @@ -370,56 +443,82 @@ extern ULONG RTDebugLevel; #define DBGPRINT_ERR(Fmt) #endif +#define ASSERT(x) -// -// spin_lock enhanced for Nested spin lock -// -#define NdisAllocateSpinLock(__lock) \ -{ \ - spin_lock_init((spinlock_t *)(__lock)); \ -} +void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen); -#define NdisFreeSpinLock(lock) \ -{ \ -} +/********************************************************************************************************* + The following code are not revised, temporary put it here. + *********************************************************************************************************/ +/*********************************************************************************** + * Device DMA Access related definitions and data structures. + **********************************************************************************/ +#ifdef RTMP_MAC_PCI +dma_addr_t linux_pci_map_single(void *handle, void *ptr, size_t size, + int sd_idx, int direction); +void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size, + int direction); -#define RTMP_SEM_LOCK(__lock) \ -{ \ - spin_lock_bh((spinlock_t *)(__lock)); \ -} +#define PCI_MAP_SINGLE(_handle, _ptr, _size, _sd_idx, _dir) \ + linux_pci_map_single(_handle, _ptr, _size, _sd_idx, _dir) -#define RTMP_SEM_UNLOCK(__lock) \ -{ \ - spin_unlock_bh((spinlock_t *)(__lock)); \ -} +#define PCI_UNMAP_SINGLE(_handle, _ptr, _size, _dir) \ + linux_pci_unmap_single(_handle, _ptr, _size, _dir) -// sample, use semaphore lock to replace IRQ lock, 2007/11/15 -#define RTMP_IRQ_LOCK(__lock, __irqflags) \ -{ \ - __irqflags = 0; \ - spin_lock_bh((spinlock_t *)(__lock)); \ - pAd->irq_disabled |= 1; \ -} +#define PCI_ALLOC_CONSISTENT(_pci_dev, _size, _ptr) \ + pci_alloc_consistent(_pci_dev, _size, _ptr) -#define RTMP_IRQ_UNLOCK(__lock, __irqflag) \ -{ \ - pAd->irq_disabled &= 0; \ - spin_unlock_bh((spinlock_t *)(__lock)); \ -} +#define PCI_FREE_CONSISTENT(_pci_dev, _size, _virtual_addr, _physical_addr) \ + pci_free_consistent(_pci_dev, _size, _virtual_addr, _physical_addr) -#define RTMP_INT_LOCK(__lock, __irqflags) \ -{ \ - spin_lock_irqsave((spinlock_t *)__lock, __irqflags); \ -} +#define DEV_ALLOC_SKB(_length) \ + dev_alloc_skb(_length) +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB +#define PCI_MAP_SINGLE(_handle, _ptr, _size, _dir) (unsigned long)0 -#define RTMP_INT_UNLOCK(__lock, __irqflag) \ -{ \ - spin_unlock_irqrestore((spinlock_t *)(__lock), ((unsigned long)__irqflag)); \ -} +#define PCI_UNMAP_SINGLE(_handle, _ptr, _size, _dir) +#endif /* RTMP_MAC_USB // */ + +/* + * unsigned long + * RTMP_GetPhysicalAddressLow( + * dma_addr_t PhysicalAddress); + */ +#define RTMP_GetPhysicalAddressLow(PhysicalAddress) (PhysicalAddress) + +/* + * unsigned long + * RTMP_GetPhysicalAddressHigh( + * dma_addr_t PhysicalAddress); + */ +#define RTMP_GetPhysicalAddressHigh(PhysicalAddress) (0) + +/* + * void + * RTMP_SetPhysicalAddressLow( + * dma_addr_t PhysicalAddress, + * unsigned long Value); + */ +#define RTMP_SetPhysicalAddressLow(PhysicalAddress, Value) \ + PhysicalAddress = Value; + +/* + * void + * RTMP_SetPhysicalAddressHigh( + * dma_addr_t PhysicalAddress, + * unsigned long Value); + */ +#define RTMP_SetPhysicalAddressHigh(PhysicalAddress, Value) + +#define NdisMIndicateStatus(_w, _x, _y, _z) -#ifdef RT2860 -//Patch for ASIC turst read/write bug, needs to remove after metel fix +/*********************************************************************************** + * Device Register I/O Access related definitions and data structures. + **********************************************************************************/ +#ifdef RTMP_MAC_PCI +/*Patch for ASIC turst read/write bug, needs to remove after metel fix */ #define RTMP_IO_READ32(_A, _R, _pV) \ { \ if ((_A)->bPCIclkOff == FALSE) \ @@ -430,11 +529,13 @@ extern ULONG RTDebugLevel; else \ *_pV = 0; \ } + #define RTMP_IO_FORCE_READ32(_A, _R, _pV) \ { \ (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ } + #define RTMP_IO_READ8(_A, _R, _pV) \ { \ (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ @@ -444,155 +545,99 @@ extern ULONG RTDebugLevel; { \ if ((_A)->bPCIclkOff == FALSE) \ { \ - UINT Val; \ + u32 Val; \ Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ - writel(_V, (void *)((_A)->CSRBaseAddress + (_R))); \ + writel((_V), (void *)((_A)->CSRBaseAddress + (_R))); \ } \ } + +#define RTMP_IO_FORCE_WRITE32(_A, _R, _V) \ +{ \ + u32 Val; \ + Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ + writel(_V, (void *)((_A)->CSRBaseAddress + (_R))); \ +} + +#if defined(RALINK_2880) || defined(RALINK_3052) +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + unsigned long Val; \ + u8 _i; \ + _i = ((_R) & 0x3); \ + Val = readl((void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ + Val = Val & (~(0x000000ff << ((_i)*8))); \ + Val = Val | ((unsigned long)(_V) << ((_i)*8)); \ + writel((Val), (void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ +} +#else #define RTMP_IO_WRITE8(_A, _R, _V) \ { \ - UINT Val; \ + u32 Val; \ Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ - writeb((_V), (PUCHAR)((_A)->CSRBaseAddress + (_R))); \ + writeb((_V), (u8 *)((_A)->CSRBaseAddress + (_R))); \ } +#endif /* #if defined(BRCM_6358) || defined(RALINK_2880) // */ + #define RTMP_IO_WRITE16(_A, _R, _V) \ { \ - UINT Val; \ + u32 Val; \ Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ - writew((_V), (PUSHORT)((_A)->CSRBaseAddress + (_R))); \ + writew((_V), (u16 *)((_A)->CSRBaseAddress + (_R))); \ } -#endif /* RT2860 */ -#ifdef RT2870 -//Patch for ASIC turst read/write bug, needs to remove after metel fix +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB +/*Patch for ASIC turst read/write bug, needs to remove after metel fix */ #define RTMP_IO_READ32(_A, _R, _pV) \ - RTUSBReadMACRegister(_A, _R, _pV) + RTUSBReadMACRegister((_A), (_R), (u32 *)(_pV)) #define RTMP_IO_READ8(_A, _R, _pV) \ { \ } #define RTMP_IO_WRITE32(_A, _R, _V) \ - RTUSBWriteMACRegister(_A, _R, _V) - + RTUSBWriteMACRegister((_A), (_R), (u32)(_V)) #define RTMP_IO_WRITE8(_A, _R, _V) \ { \ - USHORT _Val = _V; \ - RTUSBSingleWrite(_A, _R, _Val); \ + u16 _Val = _V; \ + RTUSBSingleWrite((_A), (_R), (u16)(_Val)); \ } - #define RTMP_IO_WRITE16(_A, _R, _V) \ { \ - RTUSBSingleWrite(_A, _R, _V); \ + RTUSBSingleWrite((_A), (_R), (u16)(_V)); \ } -#endif // RT2870 // +#endif /* RTMP_MAC_USB // */ -#ifndef wait_event_interruptible_timeout -#define __wait_event_interruptible_timeout(wq, condition, 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)) { \ - ret = schedule_timeout(ret); \ - if (!ret) \ - break; \ - continue; \ - } \ - ret = -ERESTARTSYS; \ - break; \ - } \ - current->state = TASK_RUNNING; \ - remove_wait_queue(&wq, &__wait); \ -} while (0) +/*********************************************************************************** + * Network Related data structure and marco definitions + ***********************************************************************************/ +#define PKTSRC_NDIS 0x7f +#define PKTSRC_DRIVER 0x0f -#define wait_event_interruptible_timeout(wq, condition, timeout) \ -({ \ - long __ret = timeout; \ - if (!(condition)) \ - __wait_event_interruptible_timeout(wq, condition, __ret); \ - __ret; \ -}) -#endif -#define ONE_TICK 1 -#define OS_WAIT(_time) \ -{ int _i; \ - long _loop = ((_time)/(1000/OS_HZ)) > 0 ? ((_time)/(1000/OS_HZ)) : 1;\ - wait_queue_head_t _wait; \ - init_waitqueue_head(&_wait); \ - for (_i=0; _i<(_loop); _i++) \ - wait_event_interruptible_timeout(_wait, 0, ONE_TICK); } +#define RTMP_OS_NETDEV_SET_PRIV(_pNetDev, _pPriv) ((_pNetDev)->ml_priv = (_pPriv)) +#define RTMP_OS_NETDEV_GET_PRIV(_pNetDev) ((_pNetDev)->ml_priv) +#define RTMP_OS_NETDEV_GET_DEVNAME(_pNetDev) ((_pNetDev)->name) +#define RTMP_OS_NETDEV_GET_PHYADDR(_PNETDEV) ((_PNETDEV)->dev_addr) +#define RTMP_OS_NETDEV_START_QUEUE(_pNetDev) netif_start_queue((_pNetDev)) +#define RTMP_OS_NETDEV_STOP_QUEUE(_pNetDev) netif_stop_queue((_pNetDev)) +#define RTMP_OS_NETDEV_WAKE_QUEUE(_pNetDev) netif_wake_queue((_pNetDev)) +#define RTMP_OS_NETDEV_CARRIER_OFF(_pNetDev) netif_carrier_off((_pNetDev)) -typedef void (*TIMER_FUNCTION)(unsigned long); +#define QUEUE_ENTRY_TO_PACKET(pEntry) \ + (void *)(pEntry) -#define COPY_MAC_ADDR(Addr1, Addr2) memcpy((Addr1), (Addr2), MAC_ADDR_LEN) +#define PACKET_TO_QUEUE_ENTRY(pPacket) \ + (struct rt_queue_entry *)(pPacket) -#define MlmeAllocateMemory(_pAd, _ppVA) os_alloc_mem(_pAd, _ppVA, MGMT_DMA_BUFFER_SIZE) -#define MlmeFreeMemory(_pAd, _pVA) os_free_mem(_pAd, _pVA) +#define GET_SG_LIST_FROM_PACKET(_p, _sc) \ + rt_get_sg_list_from_packet(_p, _sc) -#ifdef RT2860 -#define BUILD_TIMER_FUNCTION(_func) \ -void linux_##_func(unsigned long data) \ -{ \ - PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) data; \ - \ - _func(NULL, (PVOID) pTimer->cookie, NULL, pTimer); \ - if (pTimer->Repeat) \ - RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue); \ -} -#endif -#ifdef RT2870 -#define BUILD_TIMER_FUNCTION(_func) \ -void linux_##_func(unsigned long data) \ -{ \ - PRALINK_TIMER_STRUCT _pTimer = (PRALINK_TIMER_STRUCT)data; \ - RT2870_TIMER_ENTRY *_pQNode; \ - RTMP_ADAPTER *_pAd; \ - \ - _pTimer->handle = _func; \ - _pAd = (RTMP_ADAPTER *)_pTimer->pAd; \ - _pQNode = RT2870_TimerQ_Insert(_pAd, _pTimer); \ - if ((_pQNode == NULL) && (_pAd->TimerQ.status & RT2870_THREAD_CAN_DO_INSERT)) \ - RTMP_OS_Add_Timer(&_pTimer->TimerObj, HZ); \ +#define RELEASE_NDIS_PACKET(_pAd, _pPacket, _Status) \ +{ \ + RTMPFreeNdisPacket(_pAd, _pPacket); \ } -#endif // RT2870 // - - -#define DECLARE_TIMER_FUNCTION(_func) \ -void linux_##_func(unsigned long data) - -#define GET_TIMER_FUNCTION(_func) \ - linux_##_func - -DECLARE_TIMER_FUNCTION(MlmePeriodicExec); -DECLARE_TIMER_FUNCTION(MlmeRssiReportExec); -DECLARE_TIMER_FUNCTION(AsicRxAntEvalTimeout); -DECLARE_TIMER_FUNCTION(APSDPeriodicExec); -DECLARE_TIMER_FUNCTION(AsicRfTuningExec); -#ifdef RT2870 -DECLARE_TIMER_FUNCTION(BeaconUpdateExec); -#endif // RT2870 // - -DECLARE_TIMER_FUNCTION(BeaconTimeout); -DECLARE_TIMER_FUNCTION(ScanTimeout); -DECLARE_TIMER_FUNCTION(AuthTimeout); -DECLARE_TIMER_FUNCTION(AssocTimeout); -DECLARE_TIMER_FUNCTION(ReassocTimeout); -DECLARE_TIMER_FUNCTION(DisassocTimeout); -DECLARE_TIMER_FUNCTION(LinkDownExec); -DECLARE_TIMER_FUNCTION(StaQuickResponeForRateUpExec); -DECLARE_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc); -DECLARE_TIMER_FUNCTION(PsPollWakeExec); -DECLARE_TIMER_FUNCTION(RadioOnExec); - -void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); - /* * packet helper @@ -600,16 +645,22 @@ void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); * os packet to rt packet */ #define RTPKT_TO_OSPKT(_p) ((struct sk_buff *)(_p)) -#define OSPKT_TO_RTPKT(_p) ((PNDIS_PACKET)(_p)) +#define OSPKT_TO_RTPKT(_p) ((void *)(_p)) #define GET_OS_PKT_DATAPTR(_pkt) \ (RTPKT_TO_OSPKT(_pkt)->data) +#define SET_OS_PKT_DATAPTR(_pkt, _dataPtr) \ + (RTPKT_TO_OSPKT(_pkt)->data) = (_dataPtr) #define GET_OS_PKT_LEN(_pkt) \ (RTPKT_TO_OSPKT(_pkt)->len) +#define SET_OS_PKT_LEN(_pkt, _len) \ + (RTPKT_TO_OSPKT(_pkt)->len) = (_len) #define GET_OS_PKT_DATATAIL(_pkt) \ (RTPKT_TO_OSPKT(_pkt)->tail) +#define SET_OS_PKT_DATATAIL(_pkt, _start, _len) \ + ((RTPKT_TO_OSPKT(_pkt))->tail) = (u8 *)((_start) + (_len)) #define GET_OS_PKT_HEAD(_pkt) \ (RTPKT_TO_OSPKT(_pkt)->head) @@ -619,6 +670,8 @@ void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); #define GET_OS_PKT_NETDEV(_pkt) \ (RTPKT_TO_OSPKT(_pkt)->dev) +#define SET_OS_PKT_NETDEV(_pkt, _pNetDev) \ + (RTPKT_TO_OSPKT(_pkt)->dev) = (_pNetDev) #define GET_OS_PKT_TYPE(_pkt) \ (RTPKT_TO_OSPKT(_pkt)) @@ -626,6 +679,7 @@ void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); #define GET_OS_PKT_NEXT(_pkt) \ (RTPKT_TO_OSPKT(_pkt)->next) +#define OS_PKT_CLONED(_pkt) skb_cloned(RTPKT_TO_OSPKT(_pkt)) #define OS_NTOHS(_Val) \ (ntohs(_Val)) @@ -636,55 +690,36 @@ void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); #define OS_HTONL(_Val) \ (htonl(_Val)) -/* statistics counter */ -#define STATS_INC_RX_PACKETS(_pAd, _dev) -#define STATS_INC_TX_PACKETS(_pAd, _dev) - -#define STATS_INC_RX_BYTESS(_pAd, _dev, len) -#define STATS_INC_TX_BYTESS(_pAd, _dev, len) - -#define STATS_INC_RX_ERRORS(_pAd, _dev) -#define STATS_INC_TX_ERRORS(_pAd, _dev) - -#define STATS_INC_RX_DROPPED(_pAd, _dev) -#define STATS_INC_TX_DROPPED(_pAd, _dev) - - #define CB_OFF 10 - -// check DDK NDIS_PACKET data structure and find out only MiniportReservedEx[0..7] can be used by our driver without -// ambiguity. Fields after pPacket->MiniportReservedEx[8] may be used by other wrapper layer thus crashes the driver -// - -// User Priority +/* User Priority */ #define RTMP_SET_PACKET_UP(_p, _prio) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+0] = _prio) #define RTMP_GET_PACKET_UP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+0]) -// Fragment # +/* Fragment # */ #define RTMP_SET_PACKET_FRAGMENTS(_p, _num) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+1] = _num) #define RTMP_GET_PACKET_FRAGMENTS(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+1]) -// 0x0 ~0x7f: TX to AP's own BSS which has the specified AID. if AID>127, set bit 7 in RTMP_SET_PACKET_EMACTAB too. -//(this value also as MAC(on-chip WCID) table index) -// 0x80~0xff: TX to a WDS link. b0~6: WDS index +/* 0x0 ~0x7f: TX to AP's own BSS which has the specified AID. if AID>127, set bit 7 in RTMP_SET_PACKET_EMACTAB too. */ +/*(this value also as MAC(on-chip WCID) table index) */ +/* 0x80~0xff: TX to a WDS link. b0~6: WDS index */ #define RTMP_SET_PACKET_WCID(_p, _wdsidx) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2] = _wdsidx) -#define RTMP_GET_PACKET_WCID(_p) ((UCHAR)(RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2])) +#define RTMP_GET_PACKET_WCID(_p) ((u8)(RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2])) -// 0xff: PKTSRC_NDIS, others: local TX buffer index. This value affects how to a packet +/* 0xff: PKTSRC_NDIS, others: local TX buffer index. This value affects how to a packet */ #define RTMP_SET_PACKET_SOURCE(_p, _pktsrc) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+3] = _pktsrc) #define RTMP_GET_PACKET_SOURCE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+3]) -// RTS/CTS-to-self protection method +/* RTS/CTS-to-self protection method */ #define RTMP_SET_PACKET_RTS(_p, _num) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+4] = _num) #define RTMP_GET_PACKET_RTS(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+4]) -// see RTMP_S(G)ET_PACKET_EMACTAB +/* see RTMP_S(G)ET_PACKET_EMACTAB */ -// TX rate index +/* TX rate index */ #define RTMP_SET_PACKET_TXRATE(_p, _rate) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+5] = _rate) #define RTMP_GET_PACKET_TXRATE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+5]) -// From which Interface +/* From which Interface */ #define RTMP_SET_PACKET_IF(_p, _ifdx) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+6] = _ifdx) #define RTMP_GET_PACKET_IF(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+6]) #define RTMP_SET_PACKET_NET_DEVICE_MBSSID(_p, _bss) RTMP_SET_PACKET_IF((_p), (_bss)) @@ -697,10 +732,9 @@ void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); #define RTMP_SET_PACKET_MOREDATA(_p, _morebit) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+7] = _morebit) #define RTMP_GET_PACKET_MOREDATA(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+7]) - -// -// Sepcific Pakcet Type definition -// +/* */ +/* Sepcific Pakcet Type definition */ +/* */ #define RTMP_PACKET_SPECIFIC_CB_OFFSET 11 #define RTMP_PACKET_SPECIFIC_DHCP 0x01 @@ -710,10 +744,10 @@ void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); #define RTMP_PACKET_SPECIFIC_VLAN 0x10 #define RTMP_PACKET_SPECIFIC_LLCSNAP 0x20 -//Specific +/*Specific */ #define RTMP_SET_PACKET_SPECIFIC(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] = _flg) -//DHCP +/*DHCP */ #define RTMP_SET_PACKET_DHCP(_p, _flg) \ do{ \ if (_flg) \ @@ -723,7 +757,7 @@ void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); }while(0) #define RTMP_GET_PACKET_DHCP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_DHCP) -//EAPOL +/*EAPOL */ #define RTMP_SET_PACKET_EAPOL(_p, _flg) \ do{ \ if (_flg) \ @@ -733,7 +767,7 @@ void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); }while(0) #define RTMP_GET_PACKET_EAPOL(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_EAPOL) -//WAI +/*WAI */ #define RTMP_SET_PACKET_WAI(_p, _flg) \ do{ \ if (_flg) \ @@ -745,7 +779,7 @@ void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); #define RTMP_GET_PACKET_LOWRATE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & (RTMP_PACKET_SPECIFIC_EAPOL | RTMP_PACKET_SPECIFIC_DHCP | RTMP_PACKET_SPECIFIC_WAI)) -//VLAN +/*VLAN */ #define RTMP_SET_PACKET_VLAN(_p, _flg) \ do{ \ if (_flg) \ @@ -755,7 +789,7 @@ void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); }while(0) #define RTMP_GET_PACKET_VLAN(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_VLAN) -//LLC/SNAP +/*LLC/SNAP */ #define RTMP_SET_PACKET_LLCSNAP(_p, _flg) \ do{ \ if (_flg) \ @@ -766,7 +800,7 @@ void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); #define RTMP_GET_PACKET_LLCSNAP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_LLCSNAP) -// IP +/* IP */ #define RTMP_SET_PACKET_IPV4(_p, _flg) \ do{ \ if (_flg) \ @@ -777,142 +811,35 @@ void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); #define RTMP_GET_PACKET_IPV4(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_IPV4) - -// If this flag is set, it indicates that this EAPoL frame MUST be clear. +/* If this flag is set, it indicates that this EAPoL frame MUST be clear. */ #define RTMP_SET_PACKET_CLEAR_EAP_FRAME(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+12] = _flg) #define RTMP_GET_PACKET_CLEAR_EAP_FRAME(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+12]) +/* use bit3 of cb[CB_OFF+16] */ + #define RTMP_SET_PACKET_5VT(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+22] = _flg) #define RTMP_GET_PACKET_5VT(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+22]) -#ifdef CONFIG_5VT_ENHANCE -#define BRIDGE_TAG 0x35564252 // depends on 5VT define in br_input.c -#endif - - -#define NDIS_SET_PACKET_STATUS(_p, _status) - - -#define GET_SG_LIST_FROM_PACKET(_p, _sc) \ - rt_get_sg_list_from_packet(_p, _sc) - -#define NdisMoveMemory(Destination, Source, Length) memmove(Destination, Source, Length) -#define NdisZeroMemory(Destination, Length) memset(Destination, 0, Length) -#define NdisFillMemory(Destination, Length, Fill) memset(Destination, Fill, Length) -#define NdisEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) -#define RTMPEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) - - -#define RTMP_INC_REF(_A) 0 -#define RTMP_DEC_REF(_A) 0 -#define RTMP_GET_REF(_A) 0 - - - -/* - * ULONG - * RTMP_GetPhysicalAddressLow( - * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); - */ -#define RTMP_GetPhysicalAddressLow(PhysicalAddress) (PhysicalAddress) - -/* - * ULONG - * RTMP_GetPhysicalAddressHigh( - * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); - */ -#define RTMP_GetPhysicalAddressHigh(PhysicalAddress) (0) - -/* - * VOID - * RTMP_SetPhysicalAddressLow( - * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, - * IN ULONG Value); - */ -#define RTMP_SetPhysicalAddressLow(PhysicalAddress, Value) \ - PhysicalAddress = Value; - -/* - * VOID - * RTMP_SetPhysicalAddressHigh( - * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, - * IN ULONG Value); - */ -#define RTMP_SetPhysicalAddressHigh(PhysicalAddress, Value) - - -//CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx); -#define QUEUE_ENTRY_TO_PACKET(pEntry) \ - (PNDIS_PACKET)(pEntry) - -#define PACKET_TO_QUEUE_ENTRY(pPacket) \ - (PQUEUE_ENTRY)(pPacket) - - -#ifndef CONTAINING_RECORD -#define CONTAINING_RECORD(address, type, field) \ -((type *)((PCHAR)(address) - offsetof(type, field))) -#endif - - -#define RELEASE_NDIS_PACKET(_pAd, _pPacket, _Status) \ -{ \ - RTMPFreeNdisPacket(_pAd, _pPacket); \ -} - - -#define SWITCH_PhyAB(_pAA, _pBB) \ -{ \ - ULONG AABasePaHigh; \ - ULONG AABasePaLow; \ - ULONG BBBasePaHigh; \ - ULONG BBBasePaLow; \ - BBBasePaHigh = RTMP_GetPhysicalAddressHigh(_pBB); \ - BBBasePaLow = RTMP_GetPhysicalAddressLow(_pBB); \ - AABasePaHigh = RTMP_GetPhysicalAddressHigh(_pAA); \ - AABasePaLow = RTMP_GetPhysicalAddressLow(_pAA); \ - RTMP_SetPhysicalAddressHigh(_pAA, BBBasePaHigh); \ - RTMP_SetPhysicalAddressLow(_pAA, BBBasePaLow); \ - RTMP_SetPhysicalAddressHigh(_pBB, AABasePaHigh); \ - RTMP_SetPhysicalAddressLow(_pBB, AABasePaLow); \ -} - - -#define NdisWriteErrorLogEntry(_a, _b, _c, _d) -#define NdisMAllocateMapRegisters(_a, _b, _c, _d, _e) NDIS_STATUS_SUCCESS - - -#define NdisAcquireSpinLock RTMP_SEM_LOCK -#define NdisReleaseSpinLock RTMP_SEM_UNLOCK - -static inline void NdisGetSystemUpTime(ULONG *time) -{ - *time = jiffies; -} - -//pPacket = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx); -#define QUEUE_ENTRY_TO_PKT(pEntry) \ - ((PNDIS_PACKET) (pEntry)) +/* Max skb->cb = 48B = [CB_OFF+38] */ +/*********************************************************************************** + * Other function prototypes definitions + ***********************************************************************************/ +void RTMP_GetCurrentSystemTime(LARGE_INTEGER * time); int rt28xx_packet_xmit(struct sk_buff *skb); +#ifdef RTMP_MAC_PCI +/* function declarations */ +#define IRQ_HANDLE_TYPE irqreturn_t +IRQ_HANDLE_TYPE rt2860_interrupt(int irq, void *dev_instance); +#endif /* RTMP_MAC_PCI // */ -void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify); +int rt28xx_sta_ioctl(struct net_device *net_dev, IN OUT struct ifreq *rq, int cmd); -#ifdef RT2860 -#if !defined(PCI_CAP_ID_EXP) -#define PCI_CAP_ID_EXP 0x10 -#endif - -#if !defined(PCI_EXP_LNKCTL) -#define PCI_EXP_LNKCTL 0x10 -#endif +extern int ra_mtd_write(int num, loff_t to, size_t len, const u_char * buf); +extern int ra_mtd_read(int num, loff_t from, size_t len, u_char * buf); -#if !defined(PCI_CLASS_BRIDGE_PCI) -#define PCI_CLASS_BRIDGE_PCI 0x0604 -#endif - -#define PCIBUS_INTEL_VENDOR 0x8086 -#endif +#define GET_PAD_FROM_NET_DEV(_pAd, _net_dev) (_pAd) = (struct rt_rtmp_adapter *)(_net_dev)->ml_priv; +#endif /* __RT_LINUX_H__ // */ diff --git a/drivers/staging/rt2860/rt_main_dev.c b/drivers/staging/rt2860/rt_main_dev.c index 22f37cfbefbee133a3b63690ce14d974899fa2a3..c3d92802d0c966dfbe12ca11ee23acb8cd888df9 100644 --- a/drivers/staging/rt2860/rt_main_dev.c +++ b/drivers/staging/rt2860/rt_main_dev.c @@ -33,53 +33,33 @@ Revision History: Who When What -------- ---------- ---------------------------------------------- - Sample Mar/21/07 Merge RT2870 and RT2860 drivers. */ #include "rt_config.h" -#define FORTY_MHZ_INTOLERANT_INTERVAL (60*1000) // 1 min - /*---------------------------------------------------------------------*/ /* Private Variables Used */ /*---------------------------------------------------------------------*/ -//static RALINK_TIMER_STRUCT PeriodicTimer; - -char *mac = ""; // default 00:00:00:00:00:00 -char *hostname = ""; // default CMPC -module_param (mac, charp, 0); -MODULE_PARM_DESC (mac, "rt28xx: wireless mac addr"); +char *mac = ""; /* default 00:00:00:00:00:00 */ +char *hostname = ""; /* default CMPC */ +module_param(mac, charp, 0); +MODULE_PARM_DESC(mac, "rt28xx: wireless mac addr"); /*---------------------------------------------------------------------*/ /* Prototypes of Functions Used */ /*---------------------------------------------------------------------*/ -extern BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num); -extern void ba_reordering_resource_release(PRTMP_ADAPTER pAd); -extern NDIS_STATUS NICLoadRateSwitchingParams(IN PRTMP_ADAPTER pAd); - -#ifdef RT2860 -extern void init_thread_task(PRTMP_ADAPTER pAd); -#endif - -// public function prototype -INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p, - IN UINT argc, OUT PRTMP_ADAPTER *ppAd); -// private function prototype -static int rt28xx_init(IN struct net_device *net_dev); -INT rt28xx_send_packets(IN struct sk_buff *skb_p, IN struct net_device *net_dev); +/* public function prototype */ +int rt28xx_close(IN struct net_device *net_dev); +int rt28xx_open(struct net_device *net_dev); -static void CfgInitHook(PRTMP_ADAPTER pAd); +/* private function prototype */ +static int rt28xx_send_packets(IN struct sk_buff *skb_p, + IN struct net_device *net_dev); -extern const struct iw_handler_def rt28xx_iw_handler_def; - -// This function will be called when query /proc -struct iw_statistics *rt28xx_get_wireless_stats( - IN struct net_device *net_dev); - -struct net_device_stats *RT28xx_get_ether_stats( - IN struct net_device *net_dev); +static struct net_device_stats *RT28xx_get_ether_stats(IN struct net_device + *net_dev); /* ======================================================================== @@ -103,21 +83,66 @@ Note: */ int MainVirtualIF_close(IN struct net_device *net_dev) { - RTMP_ADAPTER *pAd = net_dev->ml_priv; + struct rt_rtmp_adapter *pAd = NULL; - // Sanity check for pAd + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + /* Sanity check for pAd */ if (pAd == NULL) - return 0; // close ok + return 0; /* close ok */ netif_carrier_off(pAd->net_dev); netif_stop_queue(pAd->net_dev); + { + BOOLEAN Cancelled; + + if (INFRA_ON(pAd) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { + struct rt_mlme_disassoc_req DisReq; + struct rt_mlme_queue_elem *MsgElem = + (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem), + MEM_ALLOC_FLAG); + + if (MsgElem) { + COPY_MAC_ADDR(DisReq.Addr, + pAd->CommonCfg.Bssid); + DisReq.Reason = REASON_DEAUTH_STA_LEAVING; + + MsgElem->Machine = ASSOC_STATE_MACHINE; + MsgElem->MsgType = MT2_MLME_DISASSOC_REQ; + MsgElem->MsgLen = + sizeof(struct rt_mlme_disassoc_req); + NdisMoveMemory(MsgElem->Msg, &DisReq, + sizeof + (struct rt_mlme_disassoc_req)); + + /* Prevent to connect AP again in STAMlmePeriodicExec */ + pAd->MlmeAux.AutoReconnectSsidLen = 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, + pAd->MlmeAux. + AutoReconnectSsidLen); + + pAd->Mlme.CntlMachine.CurrState = + CNTL_WAIT_OID_DISASSOC; + MlmeDisassocReqAction(pAd, MsgElem); + kfree(MsgElem); + } + + RTMPusecDelay(1000); + } + + RTMPCancelTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, + &Cancelled); + RTMPCancelTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, + &Cancelled); + } VIRTUAL_IF_DOWN(pAd); RT_MOD_DEC_USE_COUNT(); - return 0; // close ok + return 0; /* close ok */ } /* @@ -142,16 +167,18 @@ Note: */ int MainVirtualIF_open(IN struct net_device *net_dev) { - RTMP_ADAPTER *pAd = net_dev->ml_priv; + struct rt_rtmp_adapter *pAd = NULL; - // Sanity check for pAd + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + /* Sanity check for pAd */ if (pAd == NULL) - return 0; // close ok + return 0; /* close ok */ if (VIRTUAL_IF_UP(pAd) != 0) return -1; - // increase MODULE use count + /* increase MODULE use count */ RT_MOD_INC_USE_COUNT(); netif_start_queue(net_dev); @@ -181,409 +208,160 @@ Note: (3) BA Reordering: ba_reordering_resource_release() ======================================================================== */ -int rt28xx_close(IN PNET_DEV dev) +int rt28xx_close(struct net_device *dev) { - struct net_device * net_dev = (struct net_device *)dev; - RTMP_ADAPTER *pAd = net_dev->ml_priv; - BOOLEAN Cancelled = FALSE; - UINT32 i = 0; -#ifdef RT2870 - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup); - DECLARE_WAITQUEUE(wait, current); + struct net_device *net_dev = (struct net_device *)dev; + struct rt_rtmp_adapter *pAd = NULL; + BOOLEAN Cancelled; + u32 i = 0; - //RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS); -#endif // RT2870 // +#ifdef RTMP_MAC_USB + DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup); + DECLARE_WAITQUEUE(wait, current); +#endif /* RTMP_MAC_USB // */ + GET_PAD_FROM_NET_DEV(pAd, net_dev); - DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n")); + DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n")); - // Sanity check for pAd + Cancelled = FALSE; + /* Sanity check for pAd */ if (pAd == NULL) - return 0; // close ok + return 0; /* close ok */ { - // If dirver doesn't wake up firmware here, - // NICLoadFirmware will hang forever when interface is up again. -#ifdef RT2860 - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) || - RTMP_SET_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) -#endif -#ifdef RT2870 - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) -#endif - { -#ifdef RT2860 - AsicForceWakeup(pAd, RTMP_HALT); -#endif -#ifdef RT2870 - AsicForceWakeup(pAd, TRUE); -#endif - } - - if (INFRA_ON(pAd) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) - { - MLME_DISASSOC_REQ_STRUCT DisReq; - MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); - - COPY_MAC_ADDR(DisReq.Addr, pAd->CommonCfg.Bssid); - DisReq.Reason = REASON_DEAUTH_STA_LEAVING; - - MsgElem->Machine = ASSOC_STATE_MACHINE; - MsgElem->MsgType = MT2_MLME_DISASSOC_REQ; - MsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); - NdisMoveMemory(MsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); - - // Prevent to connect AP again in STAMlmePeriodicExec - pAd->MlmeAux.AutoReconnectSsidLen= 32; - NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); - - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; - MlmeDisassocReqAction(pAd, MsgElem); - kfree(MsgElem); - - RTMPusecDelay(1000); +#ifdef RTMP_MAC_PCI + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_CLOSE); +#endif /* RTMP_MAC_PCI // */ + + /* If dirver doesn't wake up firmware here, */ + /* NICLoadFirmware will hang forever when interface is up again. */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { + AsicForceWakeup(pAd, TRUE); } - -#ifdef RT2870 - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS); -#endif // RT2870 // - -#ifdef CCX_SUPPORT - RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &Cancelled); -#endif - - RTMPCancelTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, &Cancelled); - RTMPCancelTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, &Cancelled); +#ifdef RTMP_MAC_USB + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS); +#endif /* RTMP_MAC_USB // */ MlmeRadioOff(pAd); -#ifdef RT2860 +#ifdef RTMP_MAC_PCI pAd->bPCIclkOff = FALSE; -#endif +#endif /* RTMP_MAC_PCI // */ } RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); - for (i = 0 ; i < NUM_OF_TX_RING; i++) - { - while (pAd->DeQueueRunning[i] == TRUE) - { - printk("Waiting for TxQueue[%d] done..........\n", i); + for (i = 0; i < NUM_OF_TX_RING; i++) { + while (pAd->DeQueueRunning[i] == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, + ("Waiting for TxQueue[%d] done..........\n", + i)); RTMPusecDelay(1000); } } -#ifdef RT2870 - // ensure there are no more active urbs. - add_wait_queue (&unlink_wakeup, &wait); +#ifdef RTMP_MAC_USB + /* ensure there are no more active urbs. */ + add_wait_queue(&unlink_wakeup, &wait); pAd->wait = &unlink_wakeup; - // maybe wait for deletions to finish. + /* maybe wait for deletions to finish. */ i = 0; - //while((i < 25) && atomic_read(&pAd->PendingRx) > 0) - while(i < 25) - { + /*while((i < 25) && atomic_read(&pAd->PendingRx) > 0) */ + while (i < 25) { unsigned long IrqFlags; RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); - if (pAd->PendingRx == 0) - { + if (pAd->PendingRx == 0) { RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); break; } RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); - msleep(UNLINK_TIMEOUT_MS); //Time in millisecond + msleep(UNLINK_TIMEOUT_MS); /*Time in millisecond */ i++; } pAd->wait = NULL; - remove_wait_queue (&unlink_wakeup, &wait); -#endif // RT2870 // + remove_wait_queue(&unlink_wakeup, &wait); +#endif /* RTMP_MAC_USB // */ -#ifdef RT2870 - // We need clear timerQ related structure before exits of the timer thread. - RT2870_TimerQ_Exit(pAd); - // Close kernel threads or tasklets - RT28xxThreadTerminate(pAd); -#endif // RT2870 // - - // Stop Mlme state machine + /* Stop Mlme state machine */ MlmeHalt(pAd); - // Close kernel threads or tasklets - kill_thread_task(pAd); - - MacTableReset(pAd); - - MeasureReqTabExit(pAd); - TpcReqTabExit(pAd); - -#ifdef RT2860 - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) - { - NICDisableInterrupt(pAd); - } - - // Disable Rx, register value supposed will remain after reset - NICIssueReset(pAd); + /* Close net tasklets */ + RtmpNetTaskExit(pAd); - // Free IRQ - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { - // Deregister interrupt function - RT28XX_IRQ_RELEASE(net_dev) - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + MacTableReset(pAd); } -#endif - - // Free Ring or USB buffers - RTMPFreeTxRxRingMemory(pAd); - - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); - - // Free BA reorder resource - ba_reordering_resource_release(pAd); - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP); + MeasureReqTabExit(pAd); + TpcReqTabExit(pAd); - return 0; // close ok -} /* End of rt28xx_close */ + /* Close kernel threads */ + RtmpMgmtTaskExit(pAd); -static int rt28xx_init(IN struct net_device *net_dev) -{ -#ifdef RT2860 - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)net_dev->ml_priv; -#endif -#ifdef RT2870 - PRTMP_ADAPTER pAd = net_dev->ml_priv; -#endif - UINT index; - UCHAR TmpPhy; - NDIS_STATUS Status; - UINT32 MacCsr0 = 0; - - // Allocate BA Reordering memory - ba_reordering_resource_init(pAd, MAX_REORDERING_MPDU_NUM); - - // Make sure MAC gets ready. - index = 0; - do +#ifdef RTMP_MAC_PCI { - RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); - pAd->MACVersion = MacCsr0; + BOOLEAN brc; + /* unsigned long Value; */ - if ((pAd->MACVersion != 0x00) && (pAd->MACVersion != 0xFFFFFFFF)) - break; - - RTMPusecDelay(10); - } while (index++ < 100); + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) { + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + } + /* Receive packets to clear DMA index after disable interrupt. */ + /*RTMPHandleRxDoneInterrupt(pAd); */ + /* put to radio off to save power when driver unload. After radiooff, can't write /read register. So need to finish all */ + /* register access before Radio off. */ - DBGPRINT(RT_DEBUG_TRACE, ("MAC_CSR0 [ Ver:Rev=0x%08x]\n", pAd->MACVersion)); -/*Iverson patch PCIE L1 issue */ + brc = RT28xxPciAsicRadioOff(pAd, RTMP_HALT, 0); - // Disable DMA - RT28XXDMADisable(pAd); +/*In solution 3 of 3090F, the bPCIclkOff will be set to TRUE after calling RT28xxPciAsicRadioOff */ + pAd->bPCIclkOff = FALSE; - // Load 8051 firmware - Status = NICLoadFirmware(pAd); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT_ERR(("NICLoadFirmware failed, Status[=0x%08x]\n", Status)); - goto err1; + if (brc == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s call RT28xxPciAsicRadioOff fail!\n", + __func__)); + } } - NICLoadRateSwitchingParams(pAd); - - // Disable interrupts here which is as soon as possible - // This statement should never be true. We might consider to remove it later -#ifdef RT2860 +/* if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) { - NICDisableInterrupt(pAd); - } -#endif - - Status = RTMPAllocTxRxRingMemory(pAd); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT_ERR(("RTMPAllocDMAMemory failed, Status[=0x%08x]\n", Status)); - goto err1; + RTMP_ASIC_INTERRUPT_DISABLE(pAd); } - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); - - // initialize MLME - // - - Status = MlmeInit(pAd); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT_ERR(("MlmeInit failed, Status[=0x%08x]\n", Status)); - goto err2; - } - - // Initialize pAd->StaCfg, pAd->ApCfg, pAd->CommonCfg to manufacture default - // - UserCfgInit(pAd); - -#ifdef RT2870 - // We need init timerQ related structure before create the timer thread. - RT2870_TimerQ_Init(pAd); -#endif // RT2870 // - - RT28XX_TASK_THREAD_INIT(pAd, Status); - if (Status != NDIS_STATUS_SUCCESS) - goto err1; - - CfgInitHook(pAd); - - NdisAllocateSpinLock(&pAd->MacTabLock); - - MeasureReqTabInit(pAd); - TpcReqTabInit(pAd); - - // - // Init the hardware, we need to init asic before read registry, otherwise mac register will be reset - // - Status = NICInitializeAdapter(pAd, TRUE); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT_ERR(("NICInitializeAdapter failed, Status[=0x%08x]\n", Status)); - if (Status != NDIS_STATUS_SUCCESS) - goto err3; - } - - // Read parameters from Config File - Status = RTMPReadParametersHook(pAd); - - printk("1. Phy Mode = %d\n", pAd->CommonCfg.PhyMode); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT_ERR(("NICReadRegParameters failed, Status[=0x%08x]\n",Status)); - goto err4; - } - -#ifdef RT2870 - pAd->CommonCfg.bMultipleIRP = FALSE; - - if (pAd->CommonCfg.bMultipleIRP) - pAd->CommonCfg.NumOfBulkInIRP = RX_RING_SIZE; - else - pAd->CommonCfg.NumOfBulkInIRP = 1; -#endif // RT2870 // - - - //Init Ba Capability parameters. - pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; - pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable; - pAd->CommonCfg.DesiredHtPhy.AmsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; - pAd->CommonCfg.DesiredHtPhy.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; - // UPdata to HT IE - pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; - pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; - pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; - - printk("2. Phy Mode = %d\n", pAd->CommonCfg.PhyMode); - - // We should read EEPROM for all cases. rt2860b - NICReadEEPROMParameters(pAd, mac); - - printk("3. Phy Mode = %d\n", pAd->CommonCfg.PhyMode); - - NICInitAsicFromEEPROM(pAd); //rt2860b - - // Set PHY to appropriate mode - TmpPhy = pAd->CommonCfg.PhyMode; - pAd->CommonCfg.PhyMode = 0xff; - RTMPSetPhyMode(pAd, TmpPhy); - SetCommonHT(pAd); - - // No valid channels. - if (pAd->ChannelListNum == 0) - { - printk("Wrong configuration. No valid channel found. Check \"ContryCode\" and \"ChannelGeography\" setting.\n"); - goto err4; + // Disable Rx, register value supposed will remain after reset + NICIssueReset(pAd); +*/ +#endif /* RTMP_MAC_PCI // */ + + /* Free IRQ */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { +#ifdef RTMP_MAC_PCI + /* Deregister interrupt function */ + RtmpOSIRQRelease(net_dev); +#endif /* RTMP_MAC_PCI // */ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); } + /* Free Ring or USB buffers */ + RTMPFreeTxRxRingMemory(pAd); - printk("MCS Set = %02x %02x %02x %02x %02x\n", pAd->CommonCfg.HtCapability.MCSSet[0], - pAd->CommonCfg.HtCapability.MCSSet[1], pAd->CommonCfg.HtCapability.MCSSet[2], - pAd->CommonCfg.HtCapability.MCSSet[3], pAd->CommonCfg.HtCapability.MCSSet[4]); - -#ifdef RT2870 - //Init RT30xx RFRegisters after read RFIC type from EEPROM - NICInitRT30xxRFRegisters(pAd); -#endif // RT2870 // - + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); - // - // Initialize RF register to default value - // - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); + /* Free BA reorder resource */ + ba_reordering_resource_release(pAd); -#ifndef RT2870 - // 8051 firmware require the signal during booting time. - AsicSendCommandToMcu(pAd, 0x72, 0xFF, 0x00, 0x00); -#endif + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP); - if (pAd && (Status != NDIS_STATUS_SUCCESS)) +/*+++Modify by woody to solve the bulk fail+++*/ { - // - // Undo everything if it failed - // - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); - } } - else if (pAd) - { - // Microsoft HCT require driver send a disconnect event after driver initialization. - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE); - - DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event B!\n")); - - -#ifdef RT2870 - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS); - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS); - - // - // Support multiple BulkIn IRP, - // the value on pAd->CommonCfg.NumOfBulkInIRP may be large than 1. - // - for(index=0; indexCommonCfg.NumOfBulkInIRP; index++) - { - RTUSBBulkReceive(pAd); - DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBulkReceive!\n" )); - } -#endif // RT2870 // - }// end of else - - - DBGPRINT_S(Status, ("<==== RTMPInitialize, Status=%x\n", Status)); - - return TRUE; - - -err4: -err3: - MlmeHalt(pAd); -err2: - RTMPFreeTxRxRingMemory(pAd); -err1: - os_free_mem(pAd, pAd->mpdu_blk_pool.mem); // free BA pool - RT28XX_IRQ_RELEASE(net_dev); - - // shall not set ml_priv to NULL here because the ml_priv didn't been free yet. - //net_dev->ml_priv = 0; - - printk("!!! %s Initialized fail !!!\n", RT28xx_CHIP_NAME); - return FALSE; -} /* End of rt28xx_init */ + DBGPRINT(RT_DEBUG_TRACE, ("<=== rt28xx_close\n")); + return 0; /* close ok */ +} /* End of rt28xx_close */ /* ======================================================================== @@ -600,234 +378,116 @@ Return Value: Note: ======================================================================== */ -int rt28xx_open(IN PNET_DEV dev) +int rt28xx_open(struct net_device *dev) { - struct net_device * net_dev = (struct net_device *)dev; - PRTMP_ADAPTER pAd = net_dev->ml_priv; + struct net_device *net_dev = (struct net_device *)dev; + struct rt_rtmp_adapter *pAd = NULL; int retval = 0; - POS_COOKIE pObj; + /*struct os_cookie *pObj; */ + GET_PAD_FROM_NET_DEV(pAd, net_dev); - // Sanity check for pAd - if (pAd == NULL) - { + /* Sanity check for pAd */ + if (pAd == NULL) { /* if 1st open fail, pAd will be free; So the net_dev->ml_priv will be NULL in 2rd open */ return -1; } - // Init - pObj = (POS_COOKIE)pAd->OS_Cookie; - - // reset Adapter flags - RTMP_CLEAR_FLAGS(pAd); - - // Request interrupt service routine for PCI device - // register the interrupt routine with the os - RT28XX_IRQ_REQUEST(net_dev); - - - // Init BssTab & ChannelInfo tabbles for auto channel select. + if (net_dev->priv_flags == INT_MAIN) { + if (pAd->OpMode == OPMODE_STA) + net_dev->wireless_handlers = + (struct iw_handler_def *)&rt28xx_iw_handler_def; + } + /* Request interrupt service routine for PCI device */ + /* register the interrupt routine with the os */ + RtmpOSIRQRequest(net_dev); + /* Init IRQ parameters stored in pAd */ + RTMP_IRQ_INIT(pAd); - // Chip & other init - if (rt28xx_init(net_dev) == FALSE) + /* Chip & other init */ + if (rt28xx_init(pAd, mac, hostname) == FALSE) goto err; - NdisZeroMemory(pAd->StaCfg.dev_name, 16); - NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, strlen(net_dev->name)); + /* Enable Interrupt */ + RTMP_IRQ_ENABLE(pAd); - // Set up the Mac address - NdisMoveMemory(net_dev->dev_addr, (void *) pAd->CurrentAddress, 6); + /* Now Enable RxTx */ + RTMPEnableRxTx(pAd); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); - // Init IRQ parameters - RT28XX_IRQ_INIT(pAd); + { + u32 reg = 0; + RTMP_IO_READ32(pAd, 0x1300, ®); /* clear garbage interrupts */ + printk("0x1300 = %08x\n", reg); + } - // Various AP function init + { +/* u32 reg; */ +/* u8 byte; */ +/* u16 tmp; */ - // Enable Interrupt - RT28XX_IRQ_ENABLE(pAd); +/* RTMP_IO_READ32(pAd, XIFS_TIME_CFG, ®); */ - // Now Enable RxTx - RTMPEnableRxTx(pAd); - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); +/* tmp = 0x0805; */ +/* reg = (reg & 0xffff0000) | tmp; */ +/* RTMP_IO_WRITE32(pAd, XIFS_TIME_CFG, reg); */ - { - UINT32 reg = 0; - RTMP_IO_READ32(pAd, 0x1300, ®); // clear garbage interrupts - printk("0x1300 = %08x\n", reg); } +#ifdef RTMP_MAC_PCI + RTMPInitPCIeLinkCtrlValue(pAd); +#endif /* RTMP_MAC_PCI // */ -#ifdef RT2860 - RTMPInitPCIeLinkCtrlValue(pAd); -#endif return (retval); err: +/*+++Add by shiang, move from rt28xx_init() to here. */ + RtmpOSIRQRelease(net_dev); +/*---Add by shiang, move from rt28xx_init() to here. */ return (-1); -} /* End of rt28xx_open */ +} /* End of rt28xx_open */ static const struct net_device_ops rt2860_netdev_ops = { - .ndo_open = MainVirtualIF_open, - .ndo_stop = MainVirtualIF_close, - .ndo_do_ioctl = rt28xx_sta_ioctl, - .ndo_get_stats = RT28xx_get_ether_stats, - .ndo_validate_addr = NULL, - .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, - .ndo_start_xmit = rt28xx_send_packets, + .ndo_open = MainVirtualIF_open, + .ndo_stop = MainVirtualIF_close, + .ndo_do_ioctl = rt28xx_sta_ioctl, + .ndo_get_stats = RT28xx_get_ether_stats, + .ndo_validate_addr = NULL, + .ndo_set_mac_address = eth_mac_addr, + .ndo_change_mtu = eth_change_mtu, + .ndo_start_xmit = rt28xx_send_packets, }; -/* Must not be called for mdev and apdev */ -static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER pAd) +struct net_device *RtmpPhyNetDevInit(struct rt_rtmp_adapter *pAd, + struct rt_rtmp_os_netdev_op_hook *pNetDevHook) { - NDIS_STATUS Status; - INT i=0; - CHAR slot_name[IFNAMSIZ]; - struct net_device *device; - - if (pAd->OpMode == OPMODE_STA) - { - dev->wireless_handlers = &rt28xx_iw_handler_def; + struct net_device *net_dev = NULL; +/* int Status; */ + + net_dev = + RtmpOSNetDevCreate(pAd, INT_MAIN, 0, sizeof(struct rt_rtmp_adapter *), + INF_MAIN_DEV_NAME); + if (net_dev == NULL) { + printk + ("RtmpPhyNetDevInit(): creation failed for main physical net device!\n"); + return NULL; } - dev->priv_flags = INT_MAIN; - dev->netdev_ops = &rt2860_netdev_ops; - // find available device name - for (i = 0; i < 8; i++) - { - sprintf(slot_name, "wlan%d", i); + NdisZeroMemory((unsigned char *)pNetDevHook, + sizeof(struct rt_rtmp_os_netdev_op_hook)); + pNetDevHook->netdev_ops = &rt2860_netdev_ops; + pNetDevHook->priv_flags = INT_MAIN; + pNetDevHook->needProtcted = FALSE; - device = dev_get_by_name(dev_net(dev), slot_name); - if (device != NULL) - dev_put(device); - - if (device == NULL) - break; - } - - if(i == 8) - { - DBGPRINT(RT_DEBUG_ERROR, ("No available slot name\n")); - Status = NDIS_STATUS_FAILURE; - } - else - { - sprintf(dev->name, "wlan%d", i); - Status = NDIS_STATUS_SUCCESS; - } - - return Status; - -} - -/* -======================================================================== -Routine Description: - Probe RT28XX chipset. - -Arguments: - _dev_p Point to the PCI or USB device - _dev_id_p Point to the PCI or USB device ID - -Return Value: - 0 Probe OK - -ENODEV Probe Fail - -Note: -======================================================================== -*/ -INT __devinit rt28xx_probe( - IN void *_dev_p, - IN void *_dev_id_p, - IN UINT argc, - OUT PRTMP_ADAPTER *ppAd) -{ - struct net_device *net_dev; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) NULL; - INT status; - PVOID handle; -#ifdef RT2860 - struct pci_dev *dev_p = (struct pci_dev *)_dev_p; -#endif -#ifdef RT2870 - struct usb_interface *intf = (struct usb_interface *)_dev_p; - struct usb_device *dev_p = interface_to_usbdev(intf); - - dev_p = usb_get_dev(dev_p); -#endif // RT2870 // - - DBGPRINT(RT_DEBUG_TRACE, ("STA Driver version-%s\n", STA_DRIVER_VERSION)); - - net_dev = alloc_etherdev(sizeof(PRTMP_ADAPTER)); - if (net_dev == NULL) - { - printk("alloc_netdev failed\n"); - - goto err_out; - } + net_dev->ml_priv = (void *)pAd; + pAd->net_dev = net_dev; netif_stop_queue(net_dev); -/* for supporting Network Manager */ -/* Set the sysfs physical device reference for the network logical device - * if set prior to registration will cause a symlink during initialization. - */ - SET_NETDEV_DEV(net_dev, &(dev_p->dev)); - - // Allocate RTMP_ADAPTER miniport adapter structure - handle = kmalloc(sizeof(struct os_cookie), GFP_KERNEL); - if (handle == NULL) - goto err_out_free_netdev;; - RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p); - - status = RTMPAllocAdapterBlock(handle, &pAd); - if (status != NDIS_STATUS_SUCCESS) - goto err_out_free_netdev; - - net_dev->ml_priv = (PVOID)pAd; - pAd->net_dev = net_dev; // must be before RT28XXNetDevInit() - - RT28XXNetDevInit(_dev_p, net_dev, pAd); - - pAd->StaCfg.OriDevType = net_dev->type; - - // Post config - if (RT28XXProbePostConfig(_dev_p, pAd, 0) == FALSE) - goto err_out_unmap; - - pAd->OpMode = OPMODE_STA; - - // sample move - if (rt_ieee80211_if_setup(net_dev, pAd) != NDIS_STATUS_SUCCESS) - goto err_out_unmap; - - // Register this device - status = register_netdev(net_dev); - if (status) - goto err_out_unmap; - - // Set driver data - RT28XX_DRVDATA_SET(_dev_p); - - *ppAd = pAd; - return 0; // probe ok - - - /* --------------------------- ERROR HANDLE --------------------------- */ -err_out_unmap: - RTMPFreeAdapter(pAd); - RT28XX_UNMAP(); - -err_out_free_netdev: - free_netdev(net_dev); - -err_out: - RT28XX_PUT_DEVICE(dev_p); - - return -ENODEV; /* probe fail */ -} /* End of rt28xx_probe */ + return net_dev; +} /* ======================================================================== @@ -849,36 +509,32 @@ Note: int rt28xx_packet_xmit(struct sk_buff *skb) { struct net_device *net_dev = skb->dev; - PRTMP_ADAPTER pAd = net_dev->ml_priv; + struct rt_rtmp_adapter *pAd = NULL; int status = NETDEV_TX_OK; - PNDIS_PACKET pPacket = (PNDIS_PACKET) skb; + void *pPacket = (void *)skb; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + /* RT2870STA does this in RTMPSendPackets() */ { - // Drop send request since we are in monitor mode - if (MONITOR_ON(pAd)) - { + /* Drop send request since we are in monitor mode */ + if (MONITOR_ON(pAd)) { RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); goto done; } } - // EapolStart size is 18 - if (skb->len < 14) - { - //printk("bad packet size: %d\n", pkt->len); + /* EapolStart size is 18 */ + if (skb->len < 14) { + /*printk("bad packet size: %d\n", pkt->len); */ hex_dump("bad packet", skb->data, skb->len); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); goto done; } RTMP_SET_PACKET_5VT(pPacket, 0); -#ifdef CONFIG_5VT_ENHANCE - if (*(int*)(skb->cb) == BRIDGE_TAG) { - RTMP_SET_PACKET_5VT(pPacket, 1); - } -#endif - - STASendPackets((NDIS_HANDLE)pAd, (PPNDIS_PACKET) &pPacket, 1); + STASendPackets((void *)pAd, (void **)& pPacket, 1); status = NETDEV_TX_OK; done: @@ -886,7 +542,6 @@ done: return status; } - /* ======================================================================== Routine Description: @@ -903,72 +558,69 @@ Return Value: Note: ======================================================================== */ -INT rt28xx_send_packets( - IN struct sk_buff *skb_p, - IN struct net_device *net_dev) +static int rt28xx_send_packets(IN struct sk_buff *skb_p, + IN struct net_device *net_dev) { - RTMP_ADAPTER *pAd = net_dev->ml_priv; - if (!(net_dev->flags & IFF_UP)) - { - RELEASE_NDIS_PACKET(pAd, (PNDIS_PACKET)skb_p, NDIS_STATUS_FAILURE); + struct rt_rtmp_adapter *pAd = NULL; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + if (!(net_dev->flags & IFF_UP)) { + RELEASE_NDIS_PACKET(pAd, (void *)skb_p, + NDIS_STATUS_FAILURE); return NETDEV_TX_OK; } - NdisZeroMemory((PUCHAR)&skb_p->cb[CB_OFF], 15); + NdisZeroMemory((u8 *)& skb_p->cb[CB_OFF], 15); RTMP_SET_PACKET_NET_DEVICE_MBSSID(skb_p, MAIN_MBSSID); return rt28xx_packet_xmit(skb_p); +} -} /* End of MBSS_VirtualIF_PacketSend */ - - - - -void CfgInitHook(PRTMP_ADAPTER pAd) -{ - pAd->bBroadComHT = TRUE; -} /* End of CfgInitHook */ - - -// This function will be called when query /proc -struct iw_statistics *rt28xx_get_wireless_stats( - IN struct net_device *net_dev) +/* This function will be called when query /proc */ +struct iw_statistics *rt28xx_get_wireless_stats(IN struct net_device *net_dev) { - PRTMP_ADAPTER pAd = net_dev->ml_priv; + struct rt_rtmp_adapter *pAd = NULL; + GET_PAD_FROM_NET_DEV(pAd, net_dev); DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_get_wireless_stats --->\n")); - pAd->iw_stats.status = 0; // Status - device dependent for now + pAd->iw_stats.status = 0; /* Status - device dependent for now */ - // link quality - pAd->iw_stats.qual.qual = ((pAd->Mlme.ChannelQuality * 12)/10 + 10); - if(pAd->iw_stats.qual.qual > 100) + /* link quality */ + if (pAd->OpMode == OPMODE_STA) + pAd->iw_stats.qual.qual = + ((pAd->Mlme.ChannelQuality * 12) / 10 + 10); + + if (pAd->iw_stats.qual.qual > 100) pAd->iw_stats.qual.qual = 100; - if (pAd->OpMode == OPMODE_STA) - pAd->iw_stats.qual.level = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2); + if (pAd->OpMode == OPMODE_STA) { + pAd->iw_stats.qual.level = + RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, + pAd->StaCfg.RssiSample.LastRssi1, + pAd->StaCfg.RssiSample.LastRssi2); + } - pAd->iw_stats.qual.noise = pAd->BbpWriteLatch[66]; // noise level (dBm) + pAd->iw_stats.qual.noise = pAd->BbpWriteLatch[66]; /* noise level (dBm) */ pAd->iw_stats.qual.noise += 256 - 143; - pAd->iw_stats.qual.updated = 1; // Flags to know if updated + pAd->iw_stats.qual.updated = 1; /* Flags to know if updated */ #ifdef IW_QUAL_DBM - pAd->iw_stats.qual.updated |= IW_QUAL_DBM; // Level + Noise are dBm -#endif // IW_QUAL_DBM // + pAd->iw_stats.qual.updated |= IW_QUAL_DBM; /* Level + Noise are dBm */ +#endif /* IW_QUAL_DBM // */ - pAd->iw_stats.discard.nwid = 0; // Rx : Wrong nwid/essid - pAd->iw_stats.miss.beacon = 0; // Missed beacons/superframe + pAd->iw_stats.discard.nwid = 0; /* Rx : Wrong nwid/essid */ + pAd->iw_stats.miss.beacon = 0; /* Missed beacons/superframe */ DBGPRINT(RT_DEBUG_TRACE, ("<--- rt28xx_get_wireless_stats\n")); return &pAd->iw_stats; -} /* End of rt28xx_get_wireless_stats */ - - +} void tbtt_tasklet(unsigned long data) { -#define MAX_TX_IN_TBTT (16) +/*#define MAX_TX_IN_TBTT (16) */ } @@ -988,19 +640,20 @@ void tbtt_tasklet(unsigned long data) ======================================================================== */ -struct net_device_stats *RT28xx_get_ether_stats( - IN struct net_device *net_dev) +static struct net_device_stats *RT28xx_get_ether_stats(IN struct net_device + *net_dev) { - RTMP_ADAPTER *pAd = NULL; + struct rt_rtmp_adapter *pAd = NULL; if (net_dev) - pAd = net_dev->ml_priv; + GET_PAD_FROM_NET_DEV(pAd, net_dev); - if (pAd) - { + if (pAd) { - pAd->stats.rx_packets = pAd->WlanCounters.ReceivedFragmentCount.QuadPart; - pAd->stats.tx_packets = pAd->WlanCounters.TransmittedFragmentCount.QuadPart; + pAd->stats.rx_packets = + pAd->WlanCounters.ReceivedFragmentCount.QuadPart; + pAd->stats.tx_packets = + pAd->WlanCounters.TransmittedFragmentCount.QuadPart; pAd->stats.rx_bytes = pAd->RalinkCounters.ReceivedByteCount; pAd->stats.tx_bytes = pAd->RalinkCounters.TransmittedByteCount; @@ -1011,30 +664,73 @@ struct net_device_stats *RT28xx_get_ether_stats( pAd->stats.rx_dropped = 0; pAd->stats.tx_dropped = 0; - pAd->stats.multicast = pAd->WlanCounters.MulticastReceivedFrameCount.QuadPart; // multicast packets received - pAd->stats.collisions = pAd->Counters8023.OneCollision + pAd->Counters8023.MoreCollisions; // Collision packets + pAd->stats.multicast = pAd->WlanCounters.MulticastReceivedFrameCount.QuadPart; /* multicast packets received */ + pAd->stats.collisions = pAd->Counters8023.OneCollision + pAd->Counters8023.MoreCollisions; /* Collision packets */ - pAd->stats.rx_length_errors = 0; - pAd->stats.rx_over_errors = pAd->Counters8023.RxNoBuffer; // receiver ring buff overflow - pAd->stats.rx_crc_errors = 0;//pAd->WlanCounters.FCSErrorCount; // recved pkt with crc error - pAd->stats.rx_frame_errors = pAd->Counters8023.RcvAlignmentErrors; // recv'd frame alignment error - pAd->stats.rx_fifo_errors = pAd->Counters8023.RxNoBuffer; // recv'r fifo overrun - pAd->stats.rx_missed_errors = 0; // receiver missed packet + pAd->stats.rx_length_errors = 0; + pAd->stats.rx_over_errors = pAd->Counters8023.RxNoBuffer; /* receiver ring buff overflow */ + pAd->stats.rx_crc_errors = 0; /*pAd->WlanCounters.FCSErrorCount; // recved pkt with crc error */ + pAd->stats.rx_frame_errors = pAd->Counters8023.RcvAlignmentErrors; /* recv'd frame alignment error */ + pAd->stats.rx_fifo_errors = pAd->Counters8023.RxNoBuffer; /* recv'r fifo overrun */ + pAd->stats.rx_missed_errors = 0; /* receiver missed packet */ - // detailed tx_errors - pAd->stats.tx_aborted_errors = 0; - pAd->stats.tx_carrier_errors = 0; - pAd->stats.tx_fifo_errors = 0; - pAd->stats.tx_heartbeat_errors = 0; - pAd->stats.tx_window_errors = 0; + /* detailed tx_errors */ + pAd->stats.tx_aborted_errors = 0; + pAd->stats.tx_carrier_errors = 0; + pAd->stats.tx_fifo_errors = 0; + pAd->stats.tx_heartbeat_errors = 0; + pAd->stats.tx_window_errors = 0; - // for cslip etc - pAd->stats.rx_compressed = 0; - pAd->stats.tx_compressed = 0; + /* for cslip etc */ + pAd->stats.rx_compressed = 0; + pAd->stats.tx_compressed = 0; return &pAd->stats; + } else + return NULL; +} + +BOOLEAN RtmpPhyNetDevExit(struct rt_rtmp_adapter *pAd, struct net_device *net_dev) +{ + + /* Unregister network device */ + if (net_dev != NULL) { + printk + ("RtmpOSNetDevDetach(): RtmpOSNetDeviceDetach(), dev->name=%s!\n", + net_dev->name); + RtmpOSNetDevDetach(net_dev); } - else - return NULL; + + return TRUE; + } +/* +======================================================================== +Routine Description: + Allocate memory for adapter control block. + +Arguments: + pAd Pointer to our adapter + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + NDIS_STATUS_RESOURCES + +Note: +======================================================================== +*/ +int AdapterBlockAllocateMemory(void *handle, void ** ppAd) +{ + + *ppAd = (void *)vmalloc(sizeof(struct rt_rtmp_adapter)); /*pci_alloc_consistent(pci_dev, sizeof(struct rt_rtmp_adapter), phy_addr); */ + + if (*ppAd) { + NdisZeroMemory(*ppAd, sizeof(struct rt_rtmp_adapter)); + ((struct rt_rtmp_adapter *)* ppAd)->OS_Cookie = handle; + return (NDIS_STATUS_SUCCESS); + } else { + return (NDIS_STATUS_FAILURE); + } +} diff --git a/drivers/staging/rt2860/rt_pci_rbus.c b/drivers/staging/rt2860/rt_pci_rbus.c new file mode 100644 index 0000000000000000000000000000000000000000..e0a0aeeb17a2c8b192513527f5128c5f572691bf --- /dev/null +++ b/drivers/staging/rt2860/rt_pci_rbus.c @@ -0,0 +1,840 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* + + Module Name: + rt_pci_rbus.c + + Abstract: + Create and register network interface. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" +#include + +IRQ_HANDLE_TYPE rt2860_interrupt(int irq, void *dev_instance); + +static void rx_done_tasklet(unsigned long data); +static void mgmt_dma_done_tasklet(unsigned long data); +static void ac0_dma_done_tasklet(unsigned long data); +static void ac1_dma_done_tasklet(unsigned long data); +static void ac2_dma_done_tasklet(unsigned long data); +static void ac3_dma_done_tasklet(unsigned long data); +static void fifo_statistic_full_tasklet(unsigned long data); + +/*---------------------------------------------------------------------*/ +/* Symbol & Macro Definitions */ +/*---------------------------------------------------------------------*/ +#define RT2860_INT_RX_DLY (1<<0) /* bit 0 */ +#define RT2860_INT_TX_DLY (1<<1) /* bit 1 */ +#define RT2860_INT_RX_DONE (1<<2) /* bit 2 */ +#define RT2860_INT_AC0_DMA_DONE (1<<3) /* bit 3 */ +#define RT2860_INT_AC1_DMA_DONE (1<<4) /* bit 4 */ +#define RT2860_INT_AC2_DMA_DONE (1<<5) /* bit 5 */ +#define RT2860_INT_AC3_DMA_DONE (1<<6) /* bit 6 */ +#define RT2860_INT_HCCA_DMA_DONE (1<<7) /* bit 7 */ +#define RT2860_INT_MGMT_DONE (1<<8) /* bit 8 */ + +#define INT_RX RT2860_INT_RX_DONE + +#define INT_AC0_DLY (RT2860_INT_AC0_DMA_DONE) /*| RT2860_INT_TX_DLY) */ +#define INT_AC1_DLY (RT2860_INT_AC1_DMA_DONE) /*| RT2860_INT_TX_DLY) */ +#define INT_AC2_DLY (RT2860_INT_AC2_DMA_DONE) /*| RT2860_INT_TX_DLY) */ +#define INT_AC3_DLY (RT2860_INT_AC3_DMA_DONE) /*| RT2860_INT_TX_DLY) */ +#define INT_HCCA_DLY (RT2860_INT_HCCA_DMA_DONE) /*| RT2860_INT_TX_DLY) */ +#define INT_MGMT_DLY RT2860_INT_MGMT_DONE + +/*************************************************************************** + * + * Interface-depended memory allocation/Free related procedures. + * Mainly for Hardware TxDesc/RxDesc/MgmtDesc, DMA Memory for TxData/RxData, etc., + * + **************************************************************************/ +/* Function for TxDesc Memory allocation. */ +void RTMP_AllocateTxDescMemory(struct rt_rtmp_adapter *pAd, + u32 Index, + unsigned long Length, + IN BOOLEAN Cached, + void ** VirtualAddress, + dma_addr_t *PhysicalAddress) +{ + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; + + *VirtualAddress = + (void *)pci_alloc_consistent(pObj->pci_dev, sizeof(char) * Length, + PhysicalAddress); + +} + +/* Function for MgmtDesc Memory allocation. */ +void RTMP_AllocateMgmtDescMemory(struct rt_rtmp_adapter *pAd, + unsigned long Length, + IN BOOLEAN Cached, + void ** VirtualAddress, + dma_addr_t *PhysicalAddress) +{ + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; + + *VirtualAddress = + (void *)pci_alloc_consistent(pObj->pci_dev, sizeof(char) * Length, + PhysicalAddress); + +} + +/* Function for RxDesc Memory allocation. */ +void RTMP_AllocateRxDescMemory(struct rt_rtmp_adapter *pAd, + unsigned long Length, + IN BOOLEAN Cached, + void ** VirtualAddress, + dma_addr_t *PhysicalAddress) +{ + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; + + *VirtualAddress = + (void *)pci_alloc_consistent(pObj->pci_dev, sizeof(char) * Length, + PhysicalAddress); + +} + +/* Function for free allocated Desc Memory. */ +void RTMP_FreeDescMemory(struct rt_rtmp_adapter *pAd, + unsigned long Length, + void *VirtualAddress, + dma_addr_t PhysicalAddress) +{ + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; + + pci_free_consistent(pObj->pci_dev, Length, VirtualAddress, + PhysicalAddress); +} + +/* Function for TxData DMA Memory allocation. */ +void RTMP_AllocateFirstTxBuffer(struct rt_rtmp_adapter *pAd, + u32 Index, + unsigned long Length, + IN BOOLEAN Cached, + void ** VirtualAddress, + dma_addr_t *PhysicalAddress) +{ + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; + + *VirtualAddress = + (void *)pci_alloc_consistent(pObj->pci_dev, sizeof(char) * Length, + PhysicalAddress); +} + +void RTMP_FreeFirstTxBuffer(struct rt_rtmp_adapter *pAd, + unsigned long Length, + IN BOOLEAN Cached, + void *VirtualAddress, + dma_addr_t PhysicalAddress) +{ + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; + + pci_free_consistent(pObj->pci_dev, Length, VirtualAddress, + PhysicalAddress); +} + +/* + * FUNCTION: Allocate a common buffer for DMA + * ARGUMENTS: + * AdapterHandle: AdapterHandle + * Length: Number of bytes to allocate + * Cached: Whether or not the memory can be cached + * VirtualAddress: Pointer to memory is returned here + * PhysicalAddress: Physical address corresponding to virtual address + */ +void RTMP_AllocateSharedMemory(struct rt_rtmp_adapter *pAd, + unsigned long Length, + IN BOOLEAN Cached, + void ** VirtualAddress, + dma_addr_t *PhysicalAddress) +{ + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; + + *VirtualAddress = + (void *)pci_alloc_consistent(pObj->pci_dev, sizeof(char) * Length, + PhysicalAddress); +} + +/* + * FUNCTION: Allocate a packet buffer for DMA + * ARGUMENTS: + * AdapterHandle: AdapterHandle + * Length: Number of bytes to allocate + * Cached: Whether or not the memory can be cached + * VirtualAddress: Pointer to memory is returned here + * PhysicalAddress: Physical address corresponding to virtual address + * Notes: + * Cached is ignored: always cached memory + */ +void *RTMP_AllocateRxPacketBuffer(struct rt_rtmp_adapter *pAd, + unsigned long Length, + IN BOOLEAN Cached, + void ** VirtualAddress, + OUT dma_addr_t * + PhysicalAddress) +{ + struct sk_buff *pkt; + + pkt = dev_alloc_skb(Length); + + if (pkt == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("can't allocate rx %ld size packet\n", Length)); + } + + if (pkt) { + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); + *VirtualAddress = (void *)pkt->data; + *PhysicalAddress = + PCI_MAP_SINGLE(pAd, *VirtualAddress, Length, -1, + PCI_DMA_FROMDEVICE); + } else { + *VirtualAddress = (void *)NULL; + *PhysicalAddress = (dma_addr_t)NULL; + } + + return (void *)pkt; +} + +void Invalid_Remaining_Packet(struct rt_rtmp_adapter *pAd, unsigned long VirtualAddress) +{ + dma_addr_t PhysicalAddress; + + PhysicalAddress = + PCI_MAP_SINGLE(pAd, (void *)(VirtualAddress + 1600), + RX_BUFFER_NORMSIZE - 1600, -1, PCI_DMA_FROMDEVICE); +} + +int RtmpNetTaskInit(struct rt_rtmp_adapter *pAd) +{ + struct os_cookie *pObj; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + + tasklet_init(&pObj->rx_done_task, rx_done_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->mgmt_dma_done_task, mgmt_dma_done_tasklet, + (unsigned long)pAd); + tasklet_init(&pObj->ac0_dma_done_task, ac0_dma_done_tasklet, + (unsigned long)pAd); + tasklet_init(&pObj->ac1_dma_done_task, ac1_dma_done_tasklet, + (unsigned long)pAd); + tasklet_init(&pObj->ac2_dma_done_task, ac2_dma_done_tasklet, + (unsigned long)pAd); + tasklet_init(&pObj->ac3_dma_done_task, ac3_dma_done_tasklet, + (unsigned long)pAd); + tasklet_init(&pObj->tbtt_task, tbtt_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->fifo_statistic_full_task, + fifo_statistic_full_tasklet, (unsigned long)pAd); + + return NDIS_STATUS_SUCCESS; +} + +void RtmpNetTaskExit(struct rt_rtmp_adapter *pAd) +{ + struct os_cookie *pObj; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + + tasklet_kill(&pObj->rx_done_task); + tasklet_kill(&pObj->mgmt_dma_done_task); + tasklet_kill(&pObj->ac0_dma_done_task); + tasklet_kill(&pObj->ac1_dma_done_task); + tasklet_kill(&pObj->ac2_dma_done_task); + tasklet_kill(&pObj->ac3_dma_done_task); + tasklet_kill(&pObj->tbtt_task); + tasklet_kill(&pObj->fifo_statistic_full_task); +} + +int RtmpMgmtTaskInit(struct rt_rtmp_adapter *pAd) +{ + + return NDIS_STATUS_SUCCESS; +} + +/* +======================================================================== +Routine Description: + Close kernel threads. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + NONE + +Note: +======================================================================== +*/ +void RtmpMgmtTaskExit(struct rt_rtmp_adapter *pAd) +{ + + return; +} + +static inline void rt2860_int_enable(struct rt_rtmp_adapter *pAd, unsigned int mode) +{ + u32 regValue; + + pAd->int_disable_mask &= ~(mode); + regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask); + /*if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) */ + { + RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); /* 1:enable */ + } + /*else */ + /* DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_DOZE !\n")); */ + + if (regValue != 0) + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE); +} + +static inline void rt2860_int_disable(struct rt_rtmp_adapter *pAd, unsigned int mode) +{ + u32 regValue; + + pAd->int_disable_mask |= mode; + regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask); + RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); /* 0: disable */ + + if (regValue == 0) { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE); + } +} + +/*************************************************************************** + * + * tasklet related procedures. + * + **************************************************************************/ +static void mgmt_dma_done_tasklet(unsigned long data) +{ + unsigned long flags; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)data; + INT_SOURCE_CSR_STRUC IntSource; + struct os_cookie *pObj; + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + +/* printk("mgmt_dma_done_process\n"); */ + IntSource.word = 0; + IntSource.field.MgmtDmaDone = 1; + pAd->int_pending &= ~INT_MGMT_DLY; + + RTMPHandleMgmtRingDmaDoneInterrupt(pAd); + + /* if you use RTMP_SEM_LOCK, sometimes kernel will hang up, no any */ + /* bug report output */ + RTMP_INT_LOCK(&pAd->irq_lock, flags); + /* + * double check to avoid lose of interrupts + */ + if (pAd->int_pending & INT_MGMT_DLY) { + tasklet_hi_schedule(&pObj->mgmt_dma_done_task); + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); + return; + } + + /* enable TxDataInt again */ + rt2860_int_enable(pAd, INT_MGMT_DLY); + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); +} + +static void rx_done_tasklet(unsigned long data) +{ + unsigned long flags; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)data; + BOOLEAN bReschedule = 0; + struct os_cookie *pObj; + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + + pAd->int_pending &= ~(INT_RX); + bReschedule = STARxDoneInterruptHandle(pAd, 0); + + RTMP_INT_LOCK(&pAd->irq_lock, flags); + /* + * double check to avoid rotting packet + */ + if (pAd->int_pending & INT_RX || bReschedule) { + tasklet_hi_schedule(&pObj->rx_done_task); + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); + return; + } + + /* enable Rxint again */ + rt2860_int_enable(pAd, INT_RX); + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); + +} + +void fifo_statistic_full_tasklet(unsigned long data) +{ + unsigned long flags; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)data; + struct os_cookie *pObj; + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + + pAd->int_pending &= ~(FifoStaFullInt); + NICUpdateFifoStaCounters(pAd); + + RTMP_INT_LOCK(&pAd->irq_lock, flags); + /* + * double check to avoid rotting packet + */ + if (pAd->int_pending & FifoStaFullInt) { + tasklet_hi_schedule(&pObj->fifo_statistic_full_task); + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); + return; + } + + /* enable Rxint again */ + + rt2860_int_enable(pAd, FifoStaFullInt); + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); + +} + +static void ac3_dma_done_tasklet(unsigned long data) +{ + unsigned long flags; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)data; + INT_SOURCE_CSR_STRUC IntSource; + struct os_cookie *pObj; + BOOLEAN bReschedule = 0; + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + +/* printk("ac0_dma_done_process\n"); */ + IntSource.word = 0; + IntSource.field.Ac3DmaDone = 1; + pAd->int_pending &= ~INT_AC3_DLY; + + bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); + + RTMP_INT_LOCK(&pAd->irq_lock, flags); + /* + * double check to avoid lose of interrupts + */ + if ((pAd->int_pending & INT_AC3_DLY) || bReschedule) { + tasklet_hi_schedule(&pObj->ac3_dma_done_task); + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); + return; + } + + /* enable TxDataInt again */ + rt2860_int_enable(pAd, INT_AC3_DLY); + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); +} + +static void ac2_dma_done_tasklet(unsigned long data) +{ + unsigned long flags; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)data; + INT_SOURCE_CSR_STRUC IntSource; + struct os_cookie *pObj; + BOOLEAN bReschedule = 0; + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + + IntSource.word = 0; + IntSource.field.Ac2DmaDone = 1; + pAd->int_pending &= ~INT_AC2_DLY; + + bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); + + RTMP_INT_LOCK(&pAd->irq_lock, flags); + + /* + * double check to avoid lose of interrupts + */ + if ((pAd->int_pending & INT_AC2_DLY) || bReschedule) { + tasklet_hi_schedule(&pObj->ac2_dma_done_task); + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); + return; + } + + /* enable TxDataInt again */ + rt2860_int_enable(pAd, INT_AC2_DLY); + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); +} + +static void ac1_dma_done_tasklet(unsigned long data) +{ + unsigned long flags; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)data; + INT_SOURCE_CSR_STRUC IntSource; + struct os_cookie *pObj; + BOOLEAN bReschedule = 0; + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + +/* printk("ac0_dma_done_process\n"); */ + IntSource.word = 0; + IntSource.field.Ac1DmaDone = 1; + pAd->int_pending &= ~INT_AC1_DLY; + + bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); + + RTMP_INT_LOCK(&pAd->irq_lock, flags); + /* + * double check to avoid lose of interrupts + */ + if ((pAd->int_pending & INT_AC1_DLY) || bReschedule) { + tasklet_hi_schedule(&pObj->ac1_dma_done_task); + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); + return; + } + + /* enable TxDataInt again */ + rt2860_int_enable(pAd, INT_AC1_DLY); + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); +} + +static void ac0_dma_done_tasklet(unsigned long data) +{ + unsigned long flags; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)data; + INT_SOURCE_CSR_STRUC IntSource; + struct os_cookie *pObj; + BOOLEAN bReschedule = 0; + + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + +/* printk("ac0_dma_done_process\n"); */ + IntSource.word = 0; + IntSource.field.Ac0DmaDone = 1; + pAd->int_pending &= ~INT_AC0_DLY; + +/* RTMPHandleMgmtRingDmaDoneInterrupt(pAd); */ + bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); + + RTMP_INT_LOCK(&pAd->irq_lock, flags); + /* + * double check to avoid lose of interrupts + */ + if ((pAd->int_pending & INT_AC0_DLY) || bReschedule) { + tasklet_hi_schedule(&pObj->ac0_dma_done_task); + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); + return; + } + + /* enable TxDataInt again */ + rt2860_int_enable(pAd, INT_AC0_DLY); + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); +} + +/*************************************************************************** + * + * interrupt handler related procedures. + * + **************************************************************************/ +int print_int_count; + +IRQ_HANDLE_TYPE rt2860_interrupt(int irq, void *dev_instance) +{ + struct net_device *net_dev = (struct net_device *)dev_instance; + struct rt_rtmp_adapter *pAd = NULL; + INT_SOURCE_CSR_STRUC IntSource; + struct os_cookie *pObj; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + pObj = (struct os_cookie *)pAd->OS_Cookie; + + /* Note 03312008: we can not return here before + RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word); + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word); + Or kernel will panic after ifconfig ra0 down sometimes */ + + /* */ + /* Inital the Interrupt source. */ + /* */ + IntSource.word = 0x00000000L; +/* McuIntSource.word = 0x00000000L; */ + + /* */ + /* Get the interrupt sources & saved to local variable */ + /* */ + /*RTMP_IO_READ32(pAd, where, &McuIntSource.word); */ + /*RTMP_IO_WRITE32(pAd, , McuIntSource.word); */ + + /* */ + /* Flag fOP_STATUS_DOZE On, means ASIC put to sleep, elase means ASICK WakeUp */ + /* And at the same time, clock maybe turned off that say there is no DMA service. */ + /* when ASIC get to sleep. */ + /* To prevent system hang on power saving. */ + /* We need to check it before handle the INT_SOURCE_CSR, ASIC must be wake up. */ + /* */ + /* RT2661 => when ASIC is sleeping, MAC register cannot be read and written. */ + /* RT2860 => when ASIC is sleeping, MAC register can be read and written. */ +/* if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) */ + { + RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word); + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word); /* write 1 to clear */ + } +/* else */ +/* DBGPRINT(RT_DEBUG_TRACE, (">>>fOP_STATUS_DOZE<<<\n")); */ + +/* RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IsrAfterClear); */ +/* RTMP_IO_READ32(pAd, MCU_INT_SOURCE_CSR, &McuIsrAfterClear); */ +/* DBGPRINT(RT_DEBUG_INFO, ("====> RTMPHandleInterrupt(ISR=%08x,Mcu ISR=%08x, After clear ISR=%08x, MCU ISR=%08x)\n", */ +/* IntSource.word, McuIntSource.word, IsrAfterClear, McuIsrAfterClear)); */ + + /* Do nothing if Reset in progress */ + if (RTMP_TEST_FLAG + (pAd, + (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS))) { + return IRQ_HANDLED; + } + /* */ + /* Handle interrupt, walk through all bits */ + /* Should start from highest priority interrupt */ + /* The priority can be adjust by altering processing if statement */ + /* */ + +#ifdef DBG + +#endif + + pAd->bPCIclkOff = FALSE; + + /* If required spinlock, each interrupt service routine has to acquire */ + /* and release itself. */ + /* */ + + /* Do nothing if NIC doesn't exist */ + if (IntSource.word == 0xffffffff) { + RTMP_SET_FLAG(pAd, + (fRTMP_ADAPTER_NIC_NOT_EXIST | + fRTMP_ADAPTER_HALT_IN_PROGRESS)); + return IRQ_HANDLED; + } + + if (IntSource.word & TxCoherent) { + DBGPRINT(RT_DEBUG_ERROR, (">>>TxCoherent<<<\n")); + RTMPHandleRxCoherentInterrupt(pAd); + } + + if (IntSource.word & RxCoherent) { + DBGPRINT(RT_DEBUG_ERROR, (">>>RxCoherent<<<\n")); + RTMPHandleRxCoherentInterrupt(pAd); + } + + if (IntSource.word & FifoStaFullInt) { + if ((pAd->int_disable_mask & FifoStaFullInt) == 0) { + /* mask FifoStaFullInt */ + rt2860_int_disable(pAd, FifoStaFullInt); + tasklet_hi_schedule(&pObj->fifo_statistic_full_task); + } + pAd->int_pending |= FifoStaFullInt; + } + + if (IntSource.word & INT_MGMT_DLY) { + if ((pAd->int_disable_mask & INT_MGMT_DLY) == 0) { + rt2860_int_disable(pAd, INT_MGMT_DLY); + tasklet_hi_schedule(&pObj->mgmt_dma_done_task); + } + pAd->int_pending |= INT_MGMT_DLY; + } + + if (IntSource.word & INT_RX) { + if ((pAd->int_disable_mask & INT_RX) == 0) { + + /* mask Rxint */ + rt2860_int_disable(pAd, INT_RX); + tasklet_hi_schedule(&pObj->rx_done_task); + } + pAd->int_pending |= INT_RX; + } + + if (IntSource.word & INT_AC3_DLY) { + + if ((pAd->int_disable_mask & INT_AC3_DLY) == 0) { + /* mask TxDataInt */ + rt2860_int_disable(pAd, INT_AC3_DLY); + tasklet_hi_schedule(&pObj->ac3_dma_done_task); + } + pAd->int_pending |= INT_AC3_DLY; + } + + if (IntSource.word & INT_AC2_DLY) { + + if ((pAd->int_disable_mask & INT_AC2_DLY) == 0) { + /* mask TxDataInt */ + rt2860_int_disable(pAd, INT_AC2_DLY); + tasklet_hi_schedule(&pObj->ac2_dma_done_task); + } + pAd->int_pending |= INT_AC2_DLY; + } + + if (IntSource.word & INT_AC1_DLY) { + + pAd->int_pending |= INT_AC1_DLY; + + if ((pAd->int_disable_mask & INT_AC1_DLY) == 0) { + /* mask TxDataInt */ + rt2860_int_disable(pAd, INT_AC1_DLY); + tasklet_hi_schedule(&pObj->ac1_dma_done_task); + } + + } + + if (IntSource.word & INT_AC0_DLY) { + +/* + if (IntSource.word & 0x2) { + u32 reg; + RTMP_IO_READ32(pAd, DELAY_INT_CFG, ®); + printk("IntSource.word = %08x, DELAY_REG = %08x\n", IntSource.word, reg); + } +*/ + pAd->int_pending |= INT_AC0_DLY; + + if ((pAd->int_disable_mask & INT_AC0_DLY) == 0) { + /* mask TxDataInt */ + rt2860_int_disable(pAd, INT_AC0_DLY); + tasklet_hi_schedule(&pObj->ac0_dma_done_task); + } + + } + + if (IntSource.word & PreTBTTInt) { + RTMPHandlePreTBTTInterrupt(pAd); + } + + if (IntSource.word & TBTTInt) { + RTMPHandleTBTTInterrupt(pAd); + } + + { + if (IntSource.word & AutoWakeupInt) + RTMPHandleTwakeupInterrupt(pAd); + } + + return IRQ_HANDLED; +} + +/* + * invaild or writeback cache + * and convert virtual address to physical address + */ +dma_addr_t linux_pci_map_single(void *handle, void *ptr, size_t size, + int sd_idx, int direction) +{ + struct rt_rtmp_adapter *pAd; + struct os_cookie *pObj; + + /* + ------ Porting Information ------ + > For Tx Alloc: + mgmt packets => sd_idx = 0 + SwIdx: pAd->MgmtRing.TxCpuIdx + pTxD : pAd->MgmtRing.Cell[SwIdx].AllocVa; + + data packets => sd_idx = 1 + TxIdx : pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx + QueIdx: pTxBlk->QueIdx + pTxD : pAd->TxRing[pTxBlk->QueIdx].Cell[TxIdx].AllocVa; + + > For Rx Alloc: + sd_idx = -1 + */ + + pAd = (struct rt_rtmp_adapter *)handle; + pObj = (struct os_cookie *)pAd->OS_Cookie; + + if (sd_idx == 1) { + struct rt_tx_blk *pTxBlk; + pTxBlk = (struct rt_tx_blk *)ptr; + return pci_map_single(pObj->pci_dev, pTxBlk->pSrcBufData, + pTxBlk->SrcBufLen, direction); + } else { + return pci_map_single(pObj->pci_dev, ptr, size, direction); + } + +} + +void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size, + int direction) +{ + struct rt_rtmp_adapter *pAd; + struct os_cookie *pObj; + + pAd = (struct rt_rtmp_adapter *)handle; + pObj = (struct os_cookie *)pAd->OS_Cookie; + + pci_unmap_single(pObj->pci_dev, dma_addr, size, direction); + +} diff --git a/drivers/staging/rt2860/rt_profile.c b/drivers/staging/rt2860/rt_profile.c deleted file mode 100644 index 3bc41f83f624ce0a2d176d08b3eb4fd86f9e5ae4..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2860/rt_profile.c +++ /dev/null @@ -1,1862 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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 "rt_config.h" - -static void HTParametersHook( - IN PRTMP_ADAPTER pAd, - IN CHAR *pValueStr, - IN CHAR *pInput); - -#define ETH_MAC_ADDR_STR_LEN 17 // in format of xx:xx:xx:xx:xx:xx - -// We assume the s1 is a sting, s2 is a memory space with 6 bytes. and content of s1 will be changed. -BOOLEAN rtstrmactohex(char *s1, char *s2) -{ - int i = 0; - char *ptokS = s1, *ptokE = s1; - - if (strlen(s1) != ETH_MAC_ADDR_STR_LEN) - return FALSE; - - while((*ptokS) != '\0') - { - if((ptokE = strchr(ptokS, ':')) != NULL) - *ptokE++ = '\0'; - if ((strlen(ptokS) != 2) || (!isxdigit(*ptokS)) || (!isxdigit(*(ptokS+1)))) - break; // fail - AtoH(ptokS, &s2[i++], 1); - ptokS = ptokE; - if (i == 6) - break; // parsing finished - } - - return ( i == 6 ? TRUE : FALSE); - -} - - -// we assume the s1 and s2 both are strings. -BOOLEAN rtstrcasecmp(char *s1, char *s2) -{ - char *p1 = s1, *p2 = s2; - - if (strlen(s1) != strlen(s2)) - return FALSE; - - while(*p1 != '\0') - { - if((*p1 != *p2) && ((*p1 ^ *p2) != 0x20)) - return FALSE; - p1++; - p2++; - } - - return TRUE; -} - -// we assume the s1 (buffer) and s2 (key) both are strings. -char * rtstrstruncasecmp(char * s1, char * s2) -{ - INT l1, l2, i; - char temp1, temp2; - - l2 = strlen(s2); - if (!l2) - return (char *) s1; - - l1 = strlen(s1); - - while (l1 >= l2) - { - l1--; - - for(i=0; i= l2) - { - l1--; - if (!memcmp(s1,s2,l2)) - return (char *) s1; - s1++; - } - - return NULL; -} - -/** - * rstrtok - Split a string into tokens - * @s: The string to be searched - * @ct: The characters to search for - * * WARNING: strtok is deprecated, use strsep instead. However strsep is not compatible with old architecture. - */ -char * __rstrtok; -char * rstrtok(char * s,const char * ct) -{ - char *sbegin, *send; - - sbegin = s ? s : __rstrtok; - if (!sbegin) - { - return NULL; - } - - sbegin += strspn(sbegin,ct); - if (*sbegin == '\0') - { - __rstrtok = NULL; - return( NULL ); - } - - send = strpbrk( sbegin, ct); - if (send && *send != '\0') - *send++ = '\0'; - - __rstrtok = send; - - return (sbegin); -} - -/** - * delimitcnt - return the count of a given delimiter in a given string. - * @s: The string to be searched. - * @ct: The delimiter to search for. - * Notice : We suppose the delimiter is a single-char string(for example : ";"). - */ -INT delimitcnt(char * s,const char * ct) -{ - INT count = 0; - /* point to the beginning of the line */ - const char *token = s; - - for ( ;; ) - { - token = strpbrk(token, ct); /* search for delimiters */ - - if ( token == NULL ) - { - /* advanced to the terminating null character */ - break; - } - /* skip the delimiter */ - ++token; - - /* - * Print the found text: use len with %.*s to specify field width. - */ - - /* accumulate delimiter count */ - ++count; - } - return count; -} - -/* - * converts the Internet host address from the standard numbers-and-dots notation - * into binary data. - * returns nonzero if the address is valid, zero if not. - */ -int rtinet_aton(const char *cp, unsigned int *addr) -{ - unsigned int val; - int base, n; - char c; - unsigned int parts[4]; - unsigned int *pp = parts; - - for (;;) - { - /* - * Collect number up to ``.''. - * Values are specified as for C: - * 0x=hex, 0=octal, other=decimal. - */ - val = 0; - base = 10; - if (*cp == '0') - { - if (*++cp == 'x' || *cp == 'X') - base = 16, cp++; - else - base = 8; - } - while ((c = *cp) != '\0') - { - if (isdigit((unsigned char) c)) - { - val = (val * base) + (c - '0'); - cp++; - continue; - } - if (base == 16 && isxdigit((unsigned char) c)) - { - val = (val << 4) + - (c + 10 - (islower((unsigned char) c) ? 'a' : 'A')); - cp++; - continue; - } - break; - } - if (*cp == '.') - { - /* - * Internet format: a.b.c.d a.b.c (with c treated as 16-bits) - * a.b (with b treated as 24 bits) - */ - if (pp >= parts + 3 || val > 0xff) - return 0; - *pp++ = val, cp++; - } - else - break; - } - - /* - * Check for trailing junk. - */ - while (*cp) - if (!isspace((unsigned char) *cp++)) - return 0; - - /* - * Concoct the address according to the number of parts specified. - */ - n = pp - parts + 1; - switch (n) - { - - case 1: /* a -- 32 bits */ - break; - - case 2: /* a.b -- 8.24 bits */ - if (val > 0xffffff) - return 0; - val |= parts[0] << 24; - break; - - case 3: /* a.b.c -- 8.8.16 bits */ - if (val > 0xffff) - return 0; - val |= (parts[0] << 24) | (parts[1] << 16); - break; - - case 4: /* a.b.c.d -- 8.8.8.8 bits */ - if (val > 0xff) - return 0; - val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); - break; - } - - *addr = htonl(val); - return 1; - -} - -/* - ======================================================================== - - Routine Description: - Find key section for Get key parameter. - - Arguments: - buffer Pointer to the buffer to start find the key section - section the key of the secion to be find - - Return Value: - NULL Fail - Others Success - ======================================================================== -*/ -PUCHAR RTMPFindSection( - IN PCHAR buffer) -{ - CHAR temp_buf[32]; - PUCHAR ptr; - - strcpy(temp_buf, "Default"); - - if((ptr = rtstrstr(buffer, temp_buf)) != NULL) - return (ptr+strlen("\n")); - else - return NULL; -} - -/* - ======================================================================== - - Routine Description: - Get key parameter. - - Arguments: - key Pointer to key string - dest Pointer to destination - destsize The datasize of the destination - buffer Pointer to the buffer to start find the key - - Return Value: - TRUE Success - FALSE Fail - - Note: - This routine get the value with the matched key (case case-sensitive) - ======================================================================== -*/ -INT RTMPGetKeyParameter( - IN PCHAR key, - OUT PCHAR dest, - IN INT destsize, - IN PCHAR buffer) -{ - UCHAR *temp_buf1 = NULL; - UCHAR *temp_buf2 = NULL; - CHAR *start_ptr; - CHAR *end_ptr; - CHAR *ptr; - CHAR *offset = 0; - INT len; - - //temp_buf1 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG); - os_alloc_mem(NULL, &temp_buf1, MAX_PARAM_BUFFER_SIZE); - - if(temp_buf1 == NULL) - return (FALSE); - - //temp_buf2 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG); - os_alloc_mem(NULL, &temp_buf2, MAX_PARAM_BUFFER_SIZE); - if(temp_buf2 == NULL) - { - os_free_mem(NULL, temp_buf1); - return (FALSE); - } - - //find section - if((offset = RTMPFindSection(buffer)) == NULL) - { - os_free_mem(NULL, temp_buf1); - os_free_mem(NULL, temp_buf2); - return (FALSE); - } - - strcpy(temp_buf1, "\n"); - strcat(temp_buf1, key); - strcat(temp_buf1, "="); - - //search key - if((start_ptr=rtstrstr(offset, temp_buf1))==NULL) - { - os_free_mem(NULL, temp_buf1); - os_free_mem(NULL, temp_buf2); - return (FALSE); - } - - start_ptr+=strlen("\n"); - if((end_ptr=rtstrstr(start_ptr, "\n"))==NULL) - end_ptr=start_ptr+strlen(start_ptr); - - if (end_ptrSharedKey[i][idx].KeyLen = KeyLen / 2; - AtoH(keybuff, pAd->SharedKey[i][idx].Key, KeyLen / 2); - if (KeyLen == 10) - CipherAlg = CIPHER_WEP64; - else - CipherAlg = CIPHER_WEP128; - pAd->SharedKey[i][idx].CipherAlg = CipherAlg; - - DBGPRINT(RT_DEBUG_TRACE, ("I/F(wlan%d) Key%dStr=%s and type=%s\n", i, idx+1, keybuff, (KeyType == 0) ? "Hex":"Ascii")); - return 1; - } - else - {//Invalid key length - DBGPRINT(RT_DEBUG_ERROR, ("I/F(wlan%d) Key%dStr is Invalid key length! KeyLen = %ld!\n", i, idx+1, KeyLen)); - return 0; - } - } -} -static void rtmp_read_key_parms_from_file(IN PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer) -{ - char tok_str[16]; - PUCHAR macptr; - INT i = 0, idx; - ULONG KeyType[MAX_MBSSID_NUM]; - ULONG KeyIdx; - - NdisZeroMemory(KeyType, MAX_MBSSID_NUM); - - //DefaultKeyID - if(RTMPGetKeyParameter("DefaultKeyID", tmpbuf, 25, buffer)) - { - { - KeyIdx = simple_strtol(tmpbuf, 0, 10); - if((KeyIdx >= 1 ) && (KeyIdx <= 4)) - pAd->StaCfg.DefaultKeyId = (UCHAR) (KeyIdx - 1); - else - pAd->StaCfg.DefaultKeyId = 0; - - DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyID(0~3)=%d\n", pAd->StaCfg.DefaultKeyId)); - } - } - - - for (idx = 0; idx < 4; idx++) - { - sprintf(tok_str, "Key%dType", idx + 1); - //Key1Type - if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer)) - { - for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) - { - KeyType[i] = simple_strtol(macptr, 0, 10); - } - - { - sprintf(tok_str, "Key%dStr", idx + 1); - if (RTMPGetCriticalParameter(tok_str, tmpbuf, 128, buffer)) - { - rtmp_parse_key_buffer_from_file(pAd, tmpbuf, KeyType[BSS0], BSS0, idx); - } - } - } - } -} - -static void rtmp_read_sta_wmm_parms_from_file(IN PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer) -{ - PUCHAR macptr; - INT i=0; - BOOLEAN bWmmEnable = FALSE; - - //WmmCapable - if(RTMPGetKeyParameter("WmmCapable", tmpbuf, 32, buffer)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable - { - pAd->CommonCfg.bWmmCapable = TRUE; - bWmmEnable = TRUE; - } - else //Disable - { - pAd->CommonCfg.bWmmCapable = FALSE; - } - - DBGPRINT(RT_DEBUG_TRACE, ("WmmCapable=%d\n", pAd->CommonCfg.bWmmCapable)); - } - - //AckPolicy for AC_BK, AC_BE, AC_VI, AC_VO - if(RTMPGetKeyParameter("AckPolicy", tmpbuf, 32, buffer)) - { - for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) - { - pAd->CommonCfg.AckPolicy[i] = (UCHAR)simple_strtol(macptr, 0, 10); - - DBGPRINT(RT_DEBUG_TRACE, ("AckPolicy[%d]=%d\n", i, pAd->CommonCfg.AckPolicy[i])); - } - } - - if (bWmmEnable) - { - //APSDCapable - if(RTMPGetKeyParameter("APSDCapable", tmpbuf, 10, buffer)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable - pAd->CommonCfg.bAPSDCapable = TRUE; - else - pAd->CommonCfg.bAPSDCapable = FALSE; - - DBGPRINT(RT_DEBUG_TRACE, ("APSDCapable=%d\n", pAd->CommonCfg.bAPSDCapable)); - } - - //APSDAC for AC_BE, AC_BK, AC_VI, AC_VO - if(RTMPGetKeyParameter("APSDAC", tmpbuf, 32, buffer)) - { - BOOLEAN apsd_ac[4]; - - for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) - { - apsd_ac[i] = (BOOLEAN)simple_strtol(macptr, 0, 10); - - DBGPRINT(RT_DEBUG_TRACE, ("APSDAC%d %d\n", i, apsd_ac[i])); - } - - pAd->CommonCfg.bAPSDAC_BE = apsd_ac[0]; - pAd->CommonCfg.bAPSDAC_BK = apsd_ac[1]; - pAd->CommonCfg.bAPSDAC_VI = apsd_ac[2]; - pAd->CommonCfg.bAPSDAC_VO = apsd_ac[3]; - } - } - -} - -NDIS_STATUS RTMPReadParametersHook( - IN PRTMP_ADAPTER pAd) -{ - PUCHAR src = NULL; - struct file *srcf; - INT retval; - mm_segment_t orgfs; - CHAR *buffer; - CHAR *tmpbuf; - ULONG RtsThresh; - ULONG FragThresh; - UCHAR keyMaterial[40]; - - PUCHAR macptr; - INT i = 0; - - buffer = kmalloc(MAX_INI_BUFFER_SIZE, MEM_ALLOC_FLAG); - if(buffer == NULL) - return NDIS_STATUS_FAILURE; - - tmpbuf = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG); - if(tmpbuf == NULL) - { - kfree(buffer); - return NDIS_STATUS_FAILURE; - } - - src = STA_PROFILE_PATH; - - orgfs = get_fs(); - set_fs(KERNEL_DS); - - if (src && *src) - { - srcf = filp_open(src, O_RDONLY, 0); - if (IS_ERR(srcf)) - { - DBGPRINT(RT_DEBUG_ERROR, ("--> Error %ld opening %s\n", -PTR_ERR(srcf),src)); - } - else - { - // The object must have a read method - if (srcf->f_op && srcf->f_op->read) - { - memset(buffer, 0x00, MAX_INI_BUFFER_SIZE); - retval=srcf->f_op->read(srcf, buffer, MAX_INI_BUFFER_SIZE, &srcf->f_pos); - if (retval < 0) - { - DBGPRINT(RT_DEBUG_TRACE, ("--> Read %s error %d\n", src, -retval)); - } - else - { - // set file parameter to portcfg - //CountryRegion - if(RTMPGetKeyParameter("CountryRegion", tmpbuf, 25, buffer)) - { - pAd->CommonCfg.CountryRegion = (UCHAR) simple_strtol(tmpbuf, 0, 10); - DBGPRINT(RT_DEBUG_TRACE, ("CountryRegion=%d\n", pAd->CommonCfg.CountryRegion)); - } - //CountryRegionABand - if(RTMPGetKeyParameter("CountryRegionABand", tmpbuf, 25, buffer)) - { - pAd->CommonCfg.CountryRegionForABand= (UCHAR) simple_strtol(tmpbuf, 0, 10); - DBGPRINT(RT_DEBUG_TRACE, ("CountryRegionABand=%d\n", pAd->CommonCfg.CountryRegionForABand)); - } - //CountryCode - if(RTMPGetKeyParameter("CountryCode", tmpbuf, 25, buffer)) - { - NdisMoveMemory(pAd->CommonCfg.CountryCode, tmpbuf , 2); - - if (strlen(pAd->CommonCfg.CountryCode) != 0) - { - pAd->CommonCfg.bCountryFlag = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("CountryCode=%s\n", pAd->CommonCfg.CountryCode)); - } - //ChannelGeography - if(RTMPGetKeyParameter("ChannelGeography", tmpbuf, 25, buffer)) - { - UCHAR Geography = (UCHAR) simple_strtol(tmpbuf, 0, 10); - if (Geography <= BOTH) - { - pAd->CommonCfg.Geography = Geography; - pAd->CommonCfg.CountryCode[2] = - (pAd->CommonCfg.Geography == BOTH) ? ' ' : ((pAd->CommonCfg.Geography == IDOR) ? 'I' : 'O'); - DBGPRINT(RT_DEBUG_TRACE, ("ChannelGeography=%d\n", pAd->CommonCfg.Geography)); - } - } - else - { - pAd->CommonCfg.Geography = BOTH; - pAd->CommonCfg.CountryCode[2] = ' '; - } - - { - //SSID - if (RTMPGetCriticalParameter("SSID", tmpbuf, 256, buffer)) - { - if (strlen(tmpbuf) <= 32) - { - pAd->CommonCfg.SsidLen = (UCHAR) strlen(tmpbuf); - NdisZeroMemory(pAd->CommonCfg.Ssid, NDIS_802_11_LENGTH_SSID); - NdisMoveMemory(pAd->CommonCfg.Ssid, tmpbuf, pAd->CommonCfg.SsidLen); - pAd->MlmeAux.AutoReconnectSsidLen = pAd->CommonCfg.SsidLen; - NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, NDIS_802_11_LENGTH_SSID); - NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, tmpbuf, pAd->MlmeAux.AutoReconnectSsidLen); - pAd->MlmeAux.SsidLen = pAd->CommonCfg.SsidLen; - NdisZeroMemory(pAd->MlmeAux.Ssid, NDIS_802_11_LENGTH_SSID); - NdisMoveMemory(pAd->MlmeAux.Ssid, tmpbuf, pAd->MlmeAux.SsidLen); - DBGPRINT(RT_DEBUG_TRACE, ("%s::(SSID=%s)\n", __func__, tmpbuf)); - } - } - } - - { - //NetworkType - if (RTMPGetKeyParameter("NetworkType", tmpbuf, 25, buffer)) - { - pAd->bConfigChanged = TRUE; - if (strcmp(tmpbuf, "Adhoc") == 0) - pAd->StaCfg.BssType = BSS_ADHOC; - else //Default Infrastructure mode - pAd->StaCfg.BssType = BSS_INFRA; - // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key - pAd->StaCfg.WpaState = SS_NOTUSE; - DBGPRINT(RT_DEBUG_TRACE, ("%s::(NetworkType=%d)\n", __func__, pAd->StaCfg.BssType)); - } - } - - //Channel - if(RTMPGetKeyParameter("Channel", tmpbuf, 10, buffer)) - { - pAd->CommonCfg.Channel = (UCHAR) simple_strtol(tmpbuf, 0, 10); - DBGPRINT(RT_DEBUG_TRACE, ("Channel=%d\n", pAd->CommonCfg.Channel)); - } - //WirelessMode - if(RTMPGetKeyParameter("WirelessMode", tmpbuf, 10, buffer)) - { - int value = 0, maxPhyMode = PHY_11G; - - maxPhyMode = PHY_11N_5G; - - value = simple_strtol(tmpbuf, 0, 10); - - if (value <= maxPhyMode) - { - pAd->CommonCfg.PhyMode = value; - } - DBGPRINT(RT_DEBUG_TRACE, ("PhyMode=%d\n", pAd->CommonCfg.PhyMode)); - } - //BasicRate - if(RTMPGetKeyParameter("BasicRate", tmpbuf, 10, buffer)) - { - pAd->CommonCfg.BasicRateBitmap = (ULONG) simple_strtol(tmpbuf, 0, 10); - DBGPRINT(RT_DEBUG_TRACE, ("BasicRate=%ld\n", pAd->CommonCfg.BasicRateBitmap)); - } - //BeaconPeriod - if(RTMPGetKeyParameter("BeaconPeriod", tmpbuf, 10, buffer)) - { - pAd->CommonCfg.BeaconPeriod = (USHORT) simple_strtol(tmpbuf, 0, 10); - DBGPRINT(RT_DEBUG_TRACE, ("BeaconPeriod=%d\n", pAd->CommonCfg.BeaconPeriod)); - } - //TxPower - if(RTMPGetKeyParameter("TxPower", tmpbuf, 10, buffer)) - { - pAd->CommonCfg.TxPowerPercentage = (ULONG) simple_strtol(tmpbuf, 0, 10); - - pAd->CommonCfg.TxPowerDefault = pAd->CommonCfg.TxPowerPercentage; - - DBGPRINT(RT_DEBUG_TRACE, ("TxPower=%ld\n", pAd->CommonCfg.TxPowerPercentage)); - } - //BGProtection - if(RTMPGetKeyParameter("BGProtection", tmpbuf, 10, buffer)) - { - switch (simple_strtol(tmpbuf, 0, 10)) - { - case 1: //Always On - pAd->CommonCfg.UseBGProtection = 1; - break; - case 2: //Always OFF - pAd->CommonCfg.UseBGProtection = 2; - break; - case 0: //AUTO - default: - pAd->CommonCfg.UseBGProtection = 0; - break; - } - DBGPRINT(RT_DEBUG_TRACE, ("BGProtection=%ld\n", pAd->CommonCfg.UseBGProtection)); - } - //OLBCDetection - if(RTMPGetKeyParameter("DisableOLBC", tmpbuf, 10, buffer)) - { - switch (simple_strtol(tmpbuf, 0, 10)) - { - case 1: //disable OLBC Detection - pAd->CommonCfg.DisableOLBCDetect = 1; - break; - case 0: //enable OLBC Detection - pAd->CommonCfg.DisableOLBCDetect = 0; - break; - default: - pAd->CommonCfg.DisableOLBCDetect= 0; - break; - } - DBGPRINT(RT_DEBUG_TRACE, ("OLBCDetection=%ld\n", pAd->CommonCfg.DisableOLBCDetect)); - } - //TxPreamble - if(RTMPGetKeyParameter("TxPreamble", tmpbuf, 10, buffer)) - { - switch (simple_strtol(tmpbuf, 0, 10)) - { - case Rt802_11PreambleShort: - pAd->CommonCfg.TxPreamble = Rt802_11PreambleShort; - break; - case Rt802_11PreambleLong: - default: - pAd->CommonCfg.TxPreamble = Rt802_11PreambleLong; - break; - } - DBGPRINT(RT_DEBUG_TRACE, ("TxPreamble=%ld\n", pAd->CommonCfg.TxPreamble)); - } - //RTSThreshold - if(RTMPGetKeyParameter("RTSThreshold", tmpbuf, 10, buffer)) - { - RtsThresh = simple_strtol(tmpbuf, 0, 10); - if( (RtsThresh >= 1) && (RtsThresh <= MAX_RTS_THRESHOLD) ) - pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh; - else - pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD; - - DBGPRINT(RT_DEBUG_TRACE, ("RTSThreshold=%d\n", pAd->CommonCfg.RtsThreshold)); - } - //FragThreshold - if(RTMPGetKeyParameter("FragThreshold", tmpbuf, 10, buffer)) - { - FragThresh = simple_strtol(tmpbuf, 0, 10); - pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; - - if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD) - { //illegal FragThresh so we set it to default - pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; - pAd->CommonCfg.bUseZeroToDisableFragment = TRUE; - } - else if (FragThresh % 2 == 1) - { - // The length of each fragment shall always be an even number of octets, except for the last fragment - // of an MSDU or MMPDU, which may be either an even or an odd number of octets. - pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1); - } - else - { - pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh; - } - //pAd->CommonCfg.AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; - DBGPRINT(RT_DEBUG_TRACE, ("FragThreshold=%d\n", pAd->CommonCfg.FragmentThreshold)); - } - //TxBurst - if(RTMPGetKeyParameter("TxBurst", tmpbuf, 10, buffer)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable - pAd->CommonCfg.bEnableTxBurst = TRUE; - else //Disable - pAd->CommonCfg.bEnableTxBurst = FALSE; - DBGPRINT(RT_DEBUG_TRACE, ("TxBurst=%d\n", pAd->CommonCfg.bEnableTxBurst)); - } - -#ifdef AGGREGATION_SUPPORT - //PktAggregate - if(RTMPGetKeyParameter("PktAggregate", tmpbuf, 10, buffer)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable - pAd->CommonCfg.bAggregationCapable = TRUE; - else //Disable - pAd->CommonCfg.bAggregationCapable = FALSE; -#ifdef PIGGYBACK_SUPPORT - pAd->CommonCfg.bPiggyBackCapable = pAd->CommonCfg.bAggregationCapable; -#endif // PIGGYBACK_SUPPORT // - DBGPRINT(RT_DEBUG_TRACE, ("PktAggregate=%d\n", pAd->CommonCfg.bAggregationCapable)); - } -#else - pAd->CommonCfg.bAggregationCapable = FALSE; - pAd->CommonCfg.bPiggyBackCapable = FALSE; -#endif // AGGREGATION_SUPPORT // - - // WmmCapable - rtmp_read_sta_wmm_parms_from_file(pAd, tmpbuf, buffer); - - //ShortSlot - if(RTMPGetKeyParameter("ShortSlot", tmpbuf, 10, buffer)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable - pAd->CommonCfg.bUseShortSlotTime = TRUE; - else //Disable - pAd->CommonCfg.bUseShortSlotTime = FALSE; - - DBGPRINT(RT_DEBUG_TRACE, ("ShortSlot=%d\n", pAd->CommonCfg.bUseShortSlotTime)); - } - //IEEE80211H - if(RTMPGetKeyParameter("IEEE80211H", tmpbuf, 10, buffer)) - { - for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) - { - if(simple_strtol(macptr, 0, 10) != 0) //Enable - pAd->CommonCfg.bIEEE80211H = TRUE; - else //Disable - pAd->CommonCfg.bIEEE80211H = FALSE; - - DBGPRINT(RT_DEBUG_TRACE, ("IEEE80211H=%d\n", pAd->CommonCfg.bIEEE80211H)); - } - } - //CSPeriod - if(RTMPGetKeyParameter("CSPeriod", tmpbuf, 10, buffer)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) - pAd->CommonCfg.RadarDetect.CSPeriod = simple_strtol(tmpbuf, 0, 10); - else - pAd->CommonCfg.RadarDetect.CSPeriod = 0; - - DBGPRINT(RT_DEBUG_TRACE, ("CSPeriod=%d\n", pAd->CommonCfg.RadarDetect.CSPeriod)); - } - - //RDRegion - if(RTMPGetKeyParameter("RDRegion", tmpbuf, 128, buffer)) - { - if ((strncmp(tmpbuf, "JAP_W53", 7) == 0) || (strncmp(tmpbuf, "jap_w53", 7) == 0)) - { - pAd->CommonCfg.RadarDetect.RDDurRegion = JAP_W53; - pAd->CommonCfg.RadarDetect.DfsSessionTime = 15; - } - else if ((strncmp(tmpbuf, "JAP_W56", 7) == 0) || (strncmp(tmpbuf, "jap_w56", 7) == 0)) - { - pAd->CommonCfg.RadarDetect.RDDurRegion = JAP_W56; - pAd->CommonCfg.RadarDetect.DfsSessionTime = 13; - } - else if ((strncmp(tmpbuf, "JAP", 3) == 0) || (strncmp(tmpbuf, "jap", 3) == 0)) - { - pAd->CommonCfg.RadarDetect.RDDurRegion = JAP; - pAd->CommonCfg.RadarDetect.DfsSessionTime = 5; - } - else if ((strncmp(tmpbuf, "FCC", 3) == 0) || (strncmp(tmpbuf, "fcc", 3) == 0)) - { - pAd->CommonCfg.RadarDetect.RDDurRegion = FCC; - pAd->CommonCfg.RadarDetect.DfsSessionTime = 5; - } - else if ((strncmp(tmpbuf, "CE", 2) == 0) || (strncmp(tmpbuf, "ce", 2) == 0)) - { - pAd->CommonCfg.RadarDetect.RDDurRegion = CE; - pAd->CommonCfg.RadarDetect.DfsSessionTime = 13; - } - else - { - pAd->CommonCfg.RadarDetect.RDDurRegion = CE; - pAd->CommonCfg.RadarDetect.DfsSessionTime = 13; - } - - DBGPRINT(RT_DEBUG_TRACE, ("RDRegion=%d\n", pAd->CommonCfg.RadarDetect.RDDurRegion)); - } - else - { - pAd->CommonCfg.RadarDetect.RDDurRegion = CE; - pAd->CommonCfg.RadarDetect.DfsSessionTime = 13; - } - - //WirelessEvent - if(RTMPGetKeyParameter("WirelessEvent", tmpbuf, 10, buffer)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) - pAd->CommonCfg.bWirelessEvent = simple_strtol(tmpbuf, 0, 10); - else - pAd->CommonCfg.bWirelessEvent = 0; // disable - DBGPRINT(RT_DEBUG_TRACE, ("WirelessEvent=%d\n", pAd->CommonCfg.bWirelessEvent)); - } - if(RTMPGetKeyParameter("WiFiTest", tmpbuf, 10, buffer)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) - pAd->CommonCfg.bWiFiTest= simple_strtol(tmpbuf, 0, 10); - else - pAd->CommonCfg.bWiFiTest = 0; // disable - - DBGPRINT(RT_DEBUG_TRACE, ("WiFiTest=%d\n", pAd->CommonCfg.bWiFiTest)); - } - //AuthMode - if(RTMPGetKeyParameter("AuthMode", tmpbuf, 128, buffer)) - { - { - if ((strcmp(tmpbuf, "WEPAUTO") == 0) || (strcmp(tmpbuf, "wepauto") == 0)) - pAd->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch; - else if ((strcmp(tmpbuf, "SHARED") == 0) || (strcmp(tmpbuf, "shared") == 0)) - pAd->StaCfg.AuthMode = Ndis802_11AuthModeShared; - else if ((strcmp(tmpbuf, "WPAPSK") == 0) || (strcmp(tmpbuf, "wpapsk") == 0)) - pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; - else if ((strcmp(tmpbuf, "WPANONE") == 0) || (strcmp(tmpbuf, "wpanone") == 0)) - pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; - else if ((strcmp(tmpbuf, "WPA2PSK") == 0) || (strcmp(tmpbuf, "wpa2psk") == 0)) - pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; - else if ((strcmp(tmpbuf, "WPA") == 0) || (strcmp(tmpbuf, "wpa") == 0)) - pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA; - else if ((strcmp(tmpbuf, "WPA2") == 0) || (strcmp(tmpbuf, "wpa2") == 0)) - pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; - else - pAd->StaCfg.AuthMode = Ndis802_11AuthModeOpen; - - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - - DBGPRINT(RT_DEBUG_TRACE, ("%s::(EncrypType=%d)\n", __func__, pAd->StaCfg.WepStatus)); - } - } - //EncrypType - if(RTMPGetKeyParameter("EncrypType", tmpbuf, 128, buffer)) - { - { - if ((strcmp(tmpbuf, "WEP") == 0) || (strcmp(tmpbuf, "wep") == 0)) - pAd->StaCfg.WepStatus = Ndis802_11WEPEnabled; - else if ((strcmp(tmpbuf, "TKIP") == 0) || (strcmp(tmpbuf, "tkip") == 0)) - pAd->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; - else if ((strcmp(tmpbuf, "AES") == 0) || (strcmp(tmpbuf, "aes") == 0)) - pAd->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; - else - pAd->StaCfg.WepStatus = Ndis802_11WEPDisabled; - - // Update all wepstatus related - pAd->StaCfg.PairCipher = pAd->StaCfg.WepStatus; - pAd->StaCfg.GroupCipher = pAd->StaCfg.WepStatus; - pAd->StaCfg.OrigWepStatus = pAd->StaCfg.WepStatus; - pAd->StaCfg.bMixCipher = FALSE; - - DBGPRINT(RT_DEBUG_TRACE, ("%s::(EncrypType=%d)\n", __func__, pAd->StaCfg.WepStatus)); - } - } - - { - if(RTMPGetCriticalParameter("WPAPSK", tmpbuf, 512, buffer)) - { - int err=0; - - tmpbuf[strlen(tmpbuf)] = '\0'; // make STA can process .$^& for WPAPSK input - - if ((pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && - (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) && - (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) - ) - { - err = 1; - } - else if ((strlen(tmpbuf) >= 8) && (strlen(tmpbuf) < 64)) - { - PasswordHash((char *)tmpbuf, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, keyMaterial); - NdisMoveMemory(pAd->StaCfg.PMK, keyMaterial, 32); - - } - else if (strlen(tmpbuf) == 64) - { - AtoH(tmpbuf, keyMaterial, 32); - NdisMoveMemory(pAd->StaCfg.PMK, keyMaterial, 32); - } - else - { - err = 1; - DBGPRINT(RT_DEBUG_ERROR, ("%s::(WPAPSK key-string required 8 ~ 64 characters!)\n", __func__)); - } - - if (err == 0) - { - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - // Start STA supplicant state machine - pAd->StaCfg.WpaState = SS_START; - } - else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - { - pAd->StaCfg.WpaState = SS_NOTUSE; - } - - DBGPRINT(RT_DEBUG_TRACE, ("%s::(WPAPSK=%s)\n", __func__, tmpbuf)); - } - } - } - - //DefaultKeyID, KeyType, KeyStr - rtmp_read_key_parms_from_file(pAd, tmpbuf, buffer); - - HTParametersHook(pAd, tmpbuf, buffer); - - { - //PSMode -#ifdef RT2860 - if (RTMPGetKeyParameter("PSMode", tmpbuf, 32, buffer)) -#endif -#ifdef RT2870 - if (RTMPGetKeyParameter("PSMode", tmpbuf, 10, buffer)) -#endif - { - if (pAd->StaCfg.BssType == BSS_INFRA) - { - if ((strcmp(tmpbuf, "MAX_PSP") == 0) || (strcmp(tmpbuf, "max_psp") == 0)) - { - // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() - // to exclude certain situations. - // MlmeSetPsm(pAd, PWR_SAVE); - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); - if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) - pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP; - pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP; - pAd->StaCfg.DefaultListenCount = 5; - } - else if ((strcmp(tmpbuf, "Fast_PSP") == 0) || (strcmp(tmpbuf, "fast_psp") == 0) - || (strcmp(tmpbuf, "FAST_PSP") == 0)) - { - // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() - // to exclude certain situations. - // MlmeSetPsmBit(pAd, PWR_SAVE); - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); - if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) - pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP; - pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP; - pAd->StaCfg.DefaultListenCount = 3; - } - else if ((strcmp(tmpbuf, "Legacy_PSP") == 0) || (strcmp(tmpbuf, "legacy_psp") == 0) - || (strcmp(tmpbuf, "LEGACY_PSP") == 0)) - { - // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() - // to exclude certain situations. - // MlmeSetPsmBit(pAd, PWR_SAVE); - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); - if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) - pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP; - pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP; - pAd->StaCfg.DefaultListenCount = 3; - } - else - { //Default Ndis802_11PowerModeCAM - // clear PSM bit immediately - MlmeSetPsmBit(pAd, PWR_ACTIVE); - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); - if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) - pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; - pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; - } - DBGPRINT(RT_DEBUG_TRACE, ("PSMode=%ld\n", pAd->StaCfg.WindowsPowerMode)); - } - } - // FastRoaming - if (RTMPGetKeyParameter("FastRoaming", tmpbuf, 32, buffer)) - { - if (simple_strtol(tmpbuf, 0, 10) == 0) - pAd->StaCfg.bFastRoaming = FALSE; - else - pAd->StaCfg.bFastRoaming = TRUE; - - DBGPRINT(RT_DEBUG_TRACE, ("FastRoaming=%d\n", pAd->StaCfg.bFastRoaming)); - } - // RoamThreshold - if (RTMPGetKeyParameter("RoamThreshold", tmpbuf, 32, buffer)) - { - long lInfo = simple_strtol(tmpbuf, 0, 10); - - if (lInfo > 90 || lInfo < 60) - pAd->StaCfg.dBmToRoam = -70; - else - pAd->StaCfg.dBmToRoam = (CHAR)(-1)*lInfo; - - DBGPRINT(RT_DEBUG_TRACE, ("RoamThreshold=%d dBm\n", pAd->StaCfg.dBmToRoam)); - } - - if(RTMPGetKeyParameter("TGnWifiTest", tmpbuf, 10, buffer)) - { - if(simple_strtol(tmpbuf, 0, 10) == 0) - pAd->StaCfg.bTGnWifiTest = FALSE; - else - pAd->StaCfg.bTGnWifiTest = TRUE; - DBGPRINT(RT_DEBUG_TRACE, ("TGnWifiTest=%d\n", pAd->StaCfg.bTGnWifiTest)); - } - } - } - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("--> %s does not have a write method\n", src)); - } - - retval=filp_close(srcf,NULL); - - if (retval) - { - DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src)); - } - } - } - - set_fs(orgfs); - - kfree(buffer); - kfree(tmpbuf); - - return (NDIS_STATUS_SUCCESS); -} - -static void HTParametersHook( - IN PRTMP_ADAPTER pAd, - IN CHAR *pValueStr, - IN CHAR *pInput) -{ - - INT Value; - - if (RTMPGetKeyParameter("HT_PROTECT", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.bHTProtect = FALSE; - } - else - { - pAd->CommonCfg.bHTProtect = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: Protection = %s\n", (Value==0) ? "Disable" : "Enable")); - } - - if (RTMPGetKeyParameter("HT_MIMOPSEnable", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.bMIMOPSEnable = FALSE; - } - else - { - pAd->CommonCfg.bMIMOPSEnable = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPSEnable = %s\n", (Value==0) ? "Disable" : "Enable")); - } - - - if (RTMPGetKeyParameter("HT_MIMOPSMode", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value > MMPS_ENABLE) - { - pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; - } - else - { - //TODO: add mimo power saving mechanism - pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; - //pAd->CommonCfg.BACapability.field.MMPSmode = Value; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPS Mode = %d\n", Value)); - } - - if (RTMPGetKeyParameter("HT_BADecline", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.bBADecline = FALSE; - } - else - { - pAd->CommonCfg.bBADecline = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Decline = %s\n", (Value==0) ? "Disable" : "Enable")); - } - - - if (RTMPGetKeyParameter("HT_DisableReordering", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.bDisableReordering = FALSE; - } - else - { - pAd->CommonCfg.bDisableReordering = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: DisableReordering = %s\n", (Value==0) ? "Disable" : "Enable")); - } - - if (RTMPGetKeyParameter("HT_AutoBA", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.BACapability.field.AutoBA = FALSE; - pAd->CommonCfg.BACapability.field.Policy = BA_NOTUSE; - } - else - { - pAd->CommonCfg.BACapability.field.AutoBA = TRUE; - pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; - } - pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA; - pAd->CommonCfg.REGBACapability.field.Policy = pAd->CommonCfg.BACapability.field.Policy; - DBGPRINT(RT_DEBUG_TRACE, ("HT: Auto BA = %s\n", (Value==0) ? "Disable" : "Enable")); - } - - // Tx_+HTC frame - if (RTMPGetKeyParameter("HT_HTC", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->HTCEnable = FALSE; - } - else - { - pAd->HTCEnable = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx +HTC frame = %s\n", (Value==0) ? "Disable" : "Enable")); - } - - // Enable HT Link Adaptation Control - if (RTMPGetKeyParameter("HT_LinkAdapt", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->bLinkAdapt = FALSE; - } - else - { - pAd->HTCEnable = TRUE; - pAd->bLinkAdapt = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: Link Adaptation Control = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)")); - } - - // Reverse Direction Mechanism - if (RTMPGetKeyParameter("HT_RDG", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.bRdg = FALSE; - } - else - { - pAd->HTCEnable = TRUE; - pAd->CommonCfg.bRdg = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: RDG = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)")); - } - - - - - // Tx A-MSUD ? - if (RTMPGetKeyParameter("HT_AMSDU", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE; - } - else - { - pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx A-MSDU = %s\n", (Value==0) ? "Disable" : "Enable")); - } - - // MPDU Density - if (RTMPGetKeyParameter("HT_MpduDensity", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value <=7 && Value >= 0) - { - pAd->CommonCfg.BACapability.field.MpduDensity = Value; - DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d\n", Value)); - } - else - { - pAd->CommonCfg.BACapability.field.MpduDensity = 4; - DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d (Default)\n", 4)); - } - } - - // Max Rx BA Window Size - if (RTMPGetKeyParameter("HT_BAWinSize", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - - if (Value >=1 && Value <= 64) - { - pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value; - pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value; - DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = %d\n", Value)); - } - else - { - pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64; - pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; - DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = 64 (Defualt)\n")); - } - - } - - // Guard Interval - if (RTMPGetKeyParameter("HT_GI", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - - if (Value == GI_400) - { - pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400; - } - else - { - pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800; - } - - DBGPRINT(RT_DEBUG_TRACE, ("HT: Guard Interval = %s\n", (Value==GI_400) ? "400" : "800" )); - } - - // HT Operation Mode : Mixed Mode , Green Field - if (RTMPGetKeyParameter("HT_OpMode", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - - if (Value == HTMODE_GF) - { - - pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF; - } - else - { - pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM; - } - - DBGPRINT(RT_DEBUG_TRACE, ("HT: Operate Mode = %s\n", (Value==HTMODE_GF) ? "Green Field" : "Mixed Mode" )); - } - - // Fixed Tx mode : CCK, OFDM - if (RTMPGetKeyParameter("FixedTxMode", pValueStr, 25, pInput)) - { - UCHAR fix_tx_mode; - - { - fix_tx_mode = FIXED_TXMODE_HT; - - if (strcmp(pValueStr, "OFDM") == 0 || strcmp(pValueStr, "ofdm") == 0) - { - fix_tx_mode = FIXED_TXMODE_OFDM; - } - else if (strcmp(pValueStr, "CCK") == 0 || strcmp(pValueStr, "cck") == 0) - { - fix_tx_mode = FIXED_TXMODE_CCK; - } - else if (strcmp(pValueStr, "HT") == 0 || strcmp(pValueStr, "ht") == 0) - { - fix_tx_mode = FIXED_TXMODE_HT; - } - else - { - Value = simple_strtol(pValueStr, 0, 10); - // 1 : CCK - // 2 : OFDM - // otherwise : HT - if (Value == FIXED_TXMODE_CCK || Value == FIXED_TXMODE_OFDM) - fix_tx_mode = Value; - else - fix_tx_mode = FIXED_TXMODE_HT; - } - - pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode; - DBGPRINT(RT_DEBUG_TRACE, ("Fixed Tx Mode = %d\n", fix_tx_mode)); - - } - } - - - // Channel Width - if (RTMPGetKeyParameter("HT_BW", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - - if (Value == BW_40) - { - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; - } - else - { - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; - } - -#ifdef MCAST_RATE_SPECIFIC - pAd->CommonCfg.MCastPhyMode.field.BW = pAd->CommonCfg.RegTransmitSetting.field.BW; -#endif // MCAST_RATE_SPECIFIC // - - DBGPRINT(RT_DEBUG_TRACE, ("HT: Channel Width = %s\n", (Value==BW_40) ? "40 MHz" : "20 MHz" )); - } - - if (RTMPGetKeyParameter("HT_EXTCHA", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - - if (Value == 0) - { - - pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; - } - else - { - pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; - } - - DBGPRINT(RT_DEBUG_TRACE, ("HT: Ext Channel = %s\n", (Value==0) ? "BELOW" : "ABOVE" )); - } - - // MSC - if (RTMPGetKeyParameter("HT_MCS", pValueStr, 50, pInput)) - { - { - Value = simple_strtol(pValueStr, 0, 10); - - if ((Value >= 0 && Value <= 23) || (Value == 32)) // 3*3 - { - pAd->StaCfg.DesiredTransmitSetting.field.MCS = Value; - pAd->StaCfg.bAutoTxRateSwitch = FALSE; - DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = %d\n", pAd->StaCfg.DesiredTransmitSetting.field.MCS)); - } - else - { - pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; - pAd->StaCfg.bAutoTxRateSwitch = TRUE; - DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = AUTO\n")); - } - } - } - - // STBC - if (RTMPGetKeyParameter("HT_STBC", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == STBC_USE) - { - pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE; - } - else - { - pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: STBC = %d\n", pAd->CommonCfg.RegTransmitSetting.field.STBC)); - } - - // 40_Mhz_Intolerant - if (RTMPGetKeyParameter("HT_40MHZ_INTOLERANT", pValueStr, 25, pInput)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.bForty_Mhz_Intolerant = FALSE; - } - else - { - pAd->CommonCfg.bForty_Mhz_Intolerant = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: 40MHZ INTOLERANT = %d\n", pAd->CommonCfg.bForty_Mhz_Intolerant)); - } - //HT_TxStream - if(RTMPGetKeyParameter("HT_TxStream", pValueStr, 10, pInput)) - { - switch (simple_strtol(pValueStr, 0, 10)) - { - case 1: - pAd->CommonCfg.TxStream = 1; - break; - case 2: - pAd->CommonCfg.TxStream = 2; - break; - case 3: // 3*3 - default: - pAd->CommonCfg.TxStream = 3; - - if (pAd->MACVersion < RALINK_2883_VERSION) - pAd->CommonCfg.TxStream = 2; // only 2 tx streams for RT2860 series - break; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx Stream = %d\n", pAd->CommonCfg.TxStream)); - } - //HT_RxStream - if(RTMPGetKeyParameter("HT_RxStream", pValueStr, 10, pInput)) - { - switch (simple_strtol(pValueStr, 0, 10)) - { - case 1: - pAd->CommonCfg.RxStream = 1; - break; - case 2: - pAd->CommonCfg.RxStream = 2; - break; - case 3: - default: - pAd->CommonCfg.RxStream = 3; - - if (pAd->MACVersion < RALINK_2883_VERSION) - pAd->CommonCfg.RxStream = 2; // only 2 rx streams for RT2860 series - break; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: Rx Stream = %d\n", pAd->CommonCfg.RxStream)); - } - -} diff --git a/drivers/staging/rt2860/rt_usb.c b/drivers/staging/rt2860/rt_usb.c new file mode 100644 index 0000000000000000000000000000000000000000..01a7eb4e8ba8cb3a6f3eacafdb5920987a2d77d0 --- /dev/null +++ b/drivers/staging/rt2860/rt_usb.c @@ -0,0 +1,799 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* + + Module Name: + rtusb_bulk.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + +*/ + +#include "rt_config.h" + +void dump_urb(struct urb *purb) +{ + printk("urb :0x%08lx\n", (unsigned long)purb); + printk("\tdev :0x%08lx\n", (unsigned long)purb->dev); + printk("\t\tdev->state :0x%d\n", purb->dev->state); + printk("\tpipe :0x%08x\n", purb->pipe); + printk("\tstatus :%d\n", purb->status); + printk("\ttransfer_flags :0x%08x\n", purb->transfer_flags); + printk("\ttransfer_buffer :0x%08lx\n", + (unsigned long)purb->transfer_buffer); + printk("\ttransfer_buffer_length:%d\n", purb->transfer_buffer_length); + printk("\tactual_length :%d\n", purb->actual_length); + printk("\tsetup_packet :0x%08lx\n", + (unsigned long)purb->setup_packet); + printk("\tstart_frame :%d\n", purb->start_frame); + printk("\tnumber_of_packets :%d\n", purb->number_of_packets); + printk("\tinterval :%d\n", purb->interval); + printk("\terror_count :%d\n", purb->error_count); + printk("\tcontext :0x%08lx\n", + (unsigned long)purb->context); + printk("\tcomplete :0x%08lx\n\n", + (unsigned long)purb->complete); +} + +/* +======================================================================== +Routine Description: + Create kernel threads & tasklets. + +Arguments: + *net_dev Pointer to wireless net device interface + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +int RtmpMgmtTaskInit(struct rt_rtmp_adapter *pAd) +{ + struct rt_rtmp_os_task *pTask; + int status; + + /* + Creat TimerQ Thread, We need init timerQ related structure before create the timer thread. + */ + RtmpTimerQInit(pAd); + + pTask = &pAd->timerTask; + RtmpOSTaskInit(pTask, "RtmpTimerTask", pAd); + status = RtmpOSTaskAttach(pTask, RtmpTimerQThread, pTask); + if (status == NDIS_STATUS_FAILURE) { + printk(KERN_WARNING "%s: unable to start RtmpTimerQThread\n", + RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev)); + return NDIS_STATUS_FAILURE; + } + + /* Creat MLME Thread */ + pTask = &pAd->mlmeTask; + RtmpOSTaskInit(pTask, "RtmpMlmeTask", pAd); + status = RtmpOSTaskAttach(pTask, MlmeThread, pTask); + if (status == NDIS_STATUS_FAILURE) { + printk(KERN_WARNING "%s: unable to start MlmeThread\n", + RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev)); + return NDIS_STATUS_FAILURE; + } + + /* Creat Command Thread */ + pTask = &pAd->cmdQTask; + RtmpOSTaskInit(pTask, "RtmpCmdQTask", pAd); + status = RtmpOSTaskAttach(pTask, RTUSBCmdThread, pTask); + if (status == NDIS_STATUS_FAILURE) { + printk(KERN_WARNING "%s: unable to start RTUSBCmdThread\n", + RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev)); + return NDIS_STATUS_FAILURE; + } + + return NDIS_STATUS_SUCCESS; +} + +/* +======================================================================== +Routine Description: + Close kernel threads. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + NONE + +Note: +======================================================================== +*/ +void RtmpMgmtTaskExit(struct rt_rtmp_adapter *pAd) +{ + int ret; + struct rt_rtmp_os_task *pTask; + + /* Sleep 50 milliseconds so pending io might finish normally */ + RTMPusecDelay(50000); + + /* We want to wait until all pending receives and sends to the */ + /* device object. We cancel any */ + /* irps. Wait until sends and receives have stopped. */ + RTUSBCancelPendingIRPs(pAd); + + /* We need clear timerQ related structure before exits of the timer thread. */ + RtmpTimerQExit(pAd); + + /* Terminate Mlme Thread */ + pTask = &pAd->mlmeTask; + ret = RtmpOSTaskKill(pTask); + if (ret == NDIS_STATUS_FAILURE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: kill task(%s) failed!\n", + RTMP_OS_NETDEV_GET_DEVNAME(pAd-> + net_dev), + pTask->taskName)); + } + + /* Terminate cmdQ thread */ + pTask = &pAd->cmdQTask; +#ifdef KTHREAD_SUPPORT + if (pTask->kthread_task) +#else + CHECK_PID_LEGALITY(pTask->taskPID) +#endif + { + mb(); + NdisAcquireSpinLock(&pAd->CmdQLock); + pAd->CmdQ.CmdQState = RTMP_TASK_STAT_STOPED; + NdisReleaseSpinLock(&pAd->CmdQLock); + mb(); + /*RTUSBCMDUp(pAd); */ + ret = RtmpOSTaskKill(pTask); + if (ret == NDIS_STATUS_FAILURE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: kill task(%s) failed!\n", + RTMP_OS_NETDEV_GET_DEVNAME + (pAd->net_dev), + pTask->taskName)); + } + pAd->CmdQ.CmdQState = RTMP_TASK_STAT_UNKNOWN; + } + + /* Terminate timer thread */ + pTask = &pAd->timerTask; + ret = RtmpOSTaskKill(pTask); + if (ret == NDIS_STATUS_FAILURE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: kill task(%s) failed!\n", + RTMP_OS_NETDEV_GET_DEVNAME(pAd-> + net_dev), + pTask->taskName)); + } + +} + +static void rtusb_dataout_complete(unsigned long data) +{ + struct rt_rtmp_adapter *pAd; + struct urb *pUrb; + struct os_cookie *pObj; + struct rt_ht_tx_context *pHTTXContext; + u8 BulkOutPipeId; + int Status; + unsigned long IrqFlags; + + pUrb = (struct urb *)data; + pHTTXContext = (struct rt_ht_tx_context *)pUrb->context; + pAd = pHTTXContext->pAd; + pObj = (struct os_cookie *)pAd->OS_Cookie; + Status = pUrb->status; + + /* Store BulkOut PipeId */ + BulkOutPipeId = pHTTXContext->BulkOutPipeId; + pAd->BulkOutDataOneSecCount++; + + /*DBGPRINT(RT_DEBUG_LOUD, ("Done-B(%d):I=0x%lx, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", BulkOutPipeId, in_interrupt(), pHTTXContext->CurWritePosition, */ + /* pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); */ + + RTMP_IRQ_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + pAd->BulkOutPending[BulkOutPipeId] = FALSE; + pHTTXContext->IRPPending = FALSE; + pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0; + + if (Status == USB_ST_NOERROR) { + pAd->BulkOutComplete++; + + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + + pAd->Counters8023.GoodTransmits++; + /*RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); */ + FREE_HTTX_RING(pAd, BulkOutPipeId, pHTTXContext); + /*RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); */ + + } else /* STATUS_OTHER */ + { + u8 *pBuf; + + pAd->BulkOutCompleteOther++; + + pBuf = + &pHTTXContext->TransferBuffer->field. + WirelessPacket[pHTTXContext->NextBulkOutPosition]; + + if (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST | + fRTMP_ADAPTER_BULKOUT_RESET))) { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + pAd->bulkResetPipeid = BulkOutPipeId; + pAd->bulkResetReq[BulkOutPipeId] = pAd->BulkOutReq; + } + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("BulkOutDataPacket failed: ReasonCode=%d!\n", + Status)); + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("\t>>BulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", + pAd->BulkOutReq, pAd->BulkOutComplete, + pAd->BulkOutCompleteOther)); + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("\t>>BulkOut Header:%x %x %x %x %x %x %x %x\n", + pBuf[0], pBuf[1], pBuf[2], pBuf[3], pBuf[4], + pBuf[5], pBuf[6], pBuf[7])); + /*DBGPRINT_RAW(RT_DEBUG_ERROR, (">>BulkOutCompleteCancel=0x%x, BulkOutCompleteOther=0x%x\n", pAd->BulkOutCompleteCancel, pAd->BulkOutCompleteOther)); */ + + } + + /* */ + /* bInUse = TRUE, means some process are filling TX data, after that must turn on bWaitingBulkOut */ + /* bWaitingBulkOut = TRUE, means the TX data are waiting for bulk out. */ + /* */ + /*RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); */ + if ((pHTTXContext->ENextBulkOutPosition != + pHTTXContext->CurWritePosition) + && (pHTTXContext->ENextBulkOutPosition != + (pHTTXContext->CurWritePosition + 8)) + && !RTUSB_TEST_BULK_FLAG(pAd, + (fRTUSB_BULK_OUT_DATA_FRAG << + BulkOutPipeId))) { + /* Indicate There is data avaliable */ + RTUSB_SET_BULK_FLAG(pAd, + (fRTUSB_BULK_OUT_DATA_NORMAL << + BulkOutPipeId)); + } + /*RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); */ + + /* Always call Bulk routine, even reset bulk. */ + /* The protection of rest bulk should be in BulkOut routine */ + RTUSBKickBulkOut(pAd); +} + +static void rtusb_null_frame_done_tasklet(unsigned long data) +{ + struct rt_rtmp_adapter *pAd; + struct rt_tx_context *pNullContext; + struct urb *pUrb; + int Status; + unsigned long irqFlag; + + pUrb = (struct urb *)data; + pNullContext = (struct rt_tx_context *)pUrb->context; + pAd = pNullContext->pAd; + Status = pUrb->status; + + /* Reset Null frame context flags */ + RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag); + pNullContext->IRPPending = FALSE; + pNullContext->InUse = FALSE; + pAd->BulkOutPending[0] = FALSE; + pAd->watchDogTxPendingCnt[0] = 0; + + if (Status == USB_ST_NOERROR) { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); + + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } else /* STATUS_OTHER */ + { + if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("Bulk Out Null Frame Failed, ReasonCode=%d!\n", + Status)); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + pAd->bulkResetPipeid = + (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, + NULL, 0); + } else { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); + } + } + + /* Always call Bulk routine, even reset bulk. */ + /* The protectioon of rest bulk should be in BulkOut routine */ + RTUSBKickBulkOut(pAd); +} + +static void rtusb_rts_frame_done_tasklet(unsigned long data) +{ + struct rt_rtmp_adapter *pAd; + struct rt_tx_context *pRTSContext; + struct urb *pUrb; + int Status; + unsigned long irqFlag; + + pUrb = (struct urb *)data; + pRTSContext = (struct rt_tx_context *)pUrb->context; + pAd = pRTSContext->pAd; + Status = pUrb->status; + + /* Reset RTS frame context flags */ + RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag); + pRTSContext->IRPPending = FALSE; + pRTSContext->InUse = FALSE; + + if (Status == USB_ST_NOERROR) { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } else /* STATUS_OTHER */ + { + if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("Bulk Out RTS Frame Failed\n")); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + pAd->bulkResetPipeid = + (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, + NULL, 0); + } else { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); + } + } + + RTMP_SEM_LOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId]); + pAd->BulkOutPending[pRTSContext->BulkOutPipeId] = FALSE; + RTMP_SEM_UNLOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId]); + + /* Always call Bulk routine, even reset bulk. */ + /* The protectioon of rest bulk should be in BulkOut routine */ + RTUSBKickBulkOut(pAd); + +} + +static void rtusb_pspoll_frame_done_tasklet(unsigned long data) +{ + struct rt_rtmp_adapter *pAd; + struct rt_tx_context *pPsPollContext; + struct urb *pUrb; + int Status; + + pUrb = (struct urb *)data; + pPsPollContext = (struct rt_tx_context *)pUrb->context; + pAd = pPsPollContext->pAd; + Status = pUrb->status; + + /* Reset PsPoll context flags */ + pPsPollContext->IRPPending = FALSE; + pPsPollContext->InUse = FALSE; + pAd->watchDogTxPendingCnt[0] = 0; + + if (Status == USB_ST_NOERROR) { + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } else /* STATUS_OTHER */ + { + if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("Bulk Out PSPoll Failed\n")); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + pAd->bulkResetPipeid = + (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, + NULL, 0); + } + } + + RTMP_SEM_LOCK(&pAd->BulkOutLock[0]); + pAd->BulkOutPending[0] = FALSE; + RTMP_SEM_UNLOCK(&pAd->BulkOutLock[0]); + + /* Always call Bulk routine, even reset bulk. */ + /* The protectioon of rest bulk should be in BulkOut routine */ + RTUSBKickBulkOut(pAd); + +} + +/* +======================================================================== +Routine Description: + Handle received packets. + +Arguments: + data - URB information pointer + +Return Value: + None + +Note: +======================================================================== +*/ +static void rx_done_tasklet(unsigned long data) +{ + struct urb *pUrb; + struct rt_rx_context *pRxContext; + struct rt_rtmp_adapter *pAd; + int Status; + unsigned int IrqFlags; + + pUrb = (struct urb *)data; + pRxContext = (struct rt_rx_context *)pUrb->context; + pAd = pRxContext->pAd; + Status = pUrb->status; + + RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pRxContext->BulkInOffset += pUrb->actual_length; + /*NdisInterlockedDecrement(&pAd->PendingRx); */ + pAd->PendingRx--; + + if (Status == USB_ST_NOERROR) { + pAd->BulkInComplete++; + pAd->NextRxBulkInPosition = 0; + if (pRxContext->BulkInOffset) /* As jan's comment, it may bulk-in success but size is zero. */ + { + pRxContext->Readable = TRUE; + INC_RING_INDEX(pAd->NextRxBulkInIndex, RX_RING_SIZE); + } + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + } else /* STATUS_OTHER */ + { + pAd->BulkInCompleteFail++; + /* Still read this packet although it may comtain wrong bytes. */ + pRxContext->Readable = FALSE; + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + + /* Parsing all packets. because after reset, the index will reset to all zero. */ + if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_BULKIN_RESET | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) { + + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("Bulk In Failed. Status=%d, BIIdx=0x%x, BIRIdx=0x%x, actual_length= 0x%x\n", + Status, pAd->NextRxBulkInIndex, + pAd->NextRxBulkInReadIndex, + pRxContext->pUrb->actual_length)); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, + NULL, 0); + } + } + + ASSERT((pRxContext->InUse == pRxContext->IRPPending)); + + RTUSBBulkReceive(pAd); + + return; + +} + +static void rtusb_mgmt_dma_done_tasklet(unsigned long data) +{ + struct rt_rtmp_adapter *pAd; + struct rt_tx_context *pMLMEContext; + int index; + void *pPacket; + struct urb *pUrb; + int Status; + unsigned long IrqFlags; + + pUrb = (struct urb *)data; + pMLMEContext = (struct rt_tx_context *)pUrb->context; + pAd = pMLMEContext->pAd; + Status = pUrb->status; + index = pMLMEContext->SelfIdx; + + ASSERT((pAd->MgmtRing.TxDmaIdx == index)); + + RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); + + if (Status != USB_ST_NOERROR) { + /*Bulk-Out fail status handle */ + if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("Bulk Out MLME Failed, Status=%d!\n", + Status)); + /* TODO: How to handle about the MLMEBulkOut failed issue. Need to resend the mgmt pkt? */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + pAd->bulkResetPipeid = + (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); + } + } + + pAd->BulkOutPending[MGMTPIPEIDX] = FALSE; + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); + + RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags); + /* Reset MLME context flags */ + pMLMEContext->IRPPending = FALSE; + pMLMEContext->InUse = FALSE; + pMLMEContext->bWaitingBulkOut = FALSE; + pMLMEContext->BulkOutSize = 0; + + pPacket = pAd->MgmtRing.Cell[index].pNdisPacket; + pAd->MgmtRing.Cell[index].pNdisPacket = NULL; + + /* Increase MgmtRing Index */ + INC_RING_INDEX(pAd->MgmtRing.TxDmaIdx, MGMT_RING_SIZE); + pAd->MgmtRing.TxSwFreeIdx++; + RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags); + + /* No-matter success or fail, we free the mgmt packet. */ + if (pPacket) + RTMPFreeNdisPacket(pAd, pPacket); + + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) { + /* do nothing and return directly. */ + } else { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET) && ((pAd->bulkResetPipeid & BULKOUT_MGMT_RESET_FLAG) == BULKOUT_MGMT_RESET_FLAG)) { /* For Mgmt Bulk-Out failed, ignore it now. */ + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, + NULL, 0); + } else { + + /* Always call Bulk routine, even reset bulk. */ + /* The protectioon of rest bulk should be in BulkOut routine */ + if (pAd->MgmtRing.TxSwFreeIdx < + MGMT_RING_SIZE + /* pMLMEContext->bWaitingBulkOut == TRUE */ ) { + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); + } + RTUSBKickBulkOut(pAd); + } + } + +} + +static void rtusb_ac3_dma_done_tasklet(unsigned long data) +{ + struct rt_rtmp_adapter *pAd; + struct rt_ht_tx_context *pHTTXContext; + u8 BulkOutPipeId = 3; + struct urb *pUrb; + + pUrb = (struct urb *)data; + pHTTXContext = (struct rt_ht_tx_context *)pUrb->context; + pAd = pHTTXContext->pAd; + + rtusb_dataout_complete((unsigned long)pUrb); + + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) { + /* do nothing and return directly. */ + } else { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) { + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, + NULL, 0); + } else { + pHTTXContext = &pAd->TxContext[BulkOutPipeId]; + if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && + /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ + (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && + (pHTTXContext->bCurWriting == FALSE)) { + RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, + MAX_TX_PROCESS); + } + + RTUSB_SET_BULK_FLAG(pAd, + fRTUSB_BULK_OUT_DATA_NORMAL << 3); + RTUSBKickBulkOut(pAd); + } + } + + return; +} + +static void rtusb_ac2_dma_done_tasklet(unsigned long data) +{ + struct rt_rtmp_adapter *pAd; + struct rt_ht_tx_context *pHTTXContext; + u8 BulkOutPipeId = 2; + struct urb *pUrb; + + pUrb = (struct urb *)data; + pHTTXContext = (struct rt_ht_tx_context *)pUrb->context; + pAd = pHTTXContext->pAd; + + rtusb_dataout_complete((unsigned long)pUrb); + + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) { + /* do nothing and return directly. */ + } else { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) { + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, + NULL, 0); + } else { + pHTTXContext = &pAd->TxContext[BulkOutPipeId]; + if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && + /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ + (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && + (pHTTXContext->bCurWriting == FALSE)) { + RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, + MAX_TX_PROCESS); + } + + RTUSB_SET_BULK_FLAG(pAd, + fRTUSB_BULK_OUT_DATA_NORMAL << 2); + RTUSBKickBulkOut(pAd); + } + } + + return; +} + +static void rtusb_ac1_dma_done_tasklet(unsigned long data) +{ + struct rt_rtmp_adapter *pAd; + struct rt_ht_tx_context *pHTTXContext; + u8 BulkOutPipeId = 1; + struct urb *pUrb; + + pUrb = (struct urb *)data; + pHTTXContext = (struct rt_ht_tx_context *)pUrb->context; + pAd = pHTTXContext->pAd; + + rtusb_dataout_complete((unsigned long)pUrb); + + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) { + /* do nothing and return directly. */ + } else { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) { + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, + NULL, 0); + } else { + pHTTXContext = &pAd->TxContext[BulkOutPipeId]; + if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && + /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ + (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && + (pHTTXContext->bCurWriting == FALSE)) { + RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, + MAX_TX_PROCESS); + } + + RTUSB_SET_BULK_FLAG(pAd, + fRTUSB_BULK_OUT_DATA_NORMAL << 1); + RTUSBKickBulkOut(pAd); + } + } + return; + +} + +static void rtusb_ac0_dma_done_tasklet(unsigned long data) +{ + struct rt_rtmp_adapter *pAd; + struct rt_ht_tx_context *pHTTXContext; + u8 BulkOutPipeId = 0; + struct urb *pUrb; + + pUrb = (struct urb *)data; + pHTTXContext = (struct rt_ht_tx_context *)pUrb->context; + pAd = pHTTXContext->pAd; + + rtusb_dataout_complete((unsigned long)pUrb); + + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) { + /* do nothing and return directly. */ + } else { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) { + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, + NULL, 0); + } else { + pHTTXContext = &pAd->TxContext[BulkOutPipeId]; + if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && + /* ((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ + (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && + (pHTTXContext->bCurWriting == FALSE)) { + RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, + MAX_TX_PROCESS); + } + + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL); + RTUSBKickBulkOut(pAd); + } + } + + return; + +} + +int RtmpNetTaskInit(struct rt_rtmp_adapter *pAd) +{ + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; + + /* Create receive tasklet */ + tasklet_init(&pObj->rx_done_task, rx_done_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->mgmt_dma_done_task, rtusb_mgmt_dma_done_tasklet, + (unsigned long)pAd); + tasklet_init(&pObj->ac0_dma_done_task, rtusb_ac0_dma_done_tasklet, + (unsigned long)pAd); + tasklet_init(&pObj->ac1_dma_done_task, rtusb_ac1_dma_done_tasklet, + (unsigned long)pAd); + tasklet_init(&pObj->ac2_dma_done_task, rtusb_ac2_dma_done_tasklet, + (unsigned long)pAd); + tasklet_init(&pObj->ac3_dma_done_task, rtusb_ac3_dma_done_tasklet, + (unsigned long)pAd); + tasklet_init(&pObj->tbtt_task, tbtt_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->null_frame_complete_task, + rtusb_null_frame_done_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->rts_frame_complete_task, + rtusb_rts_frame_done_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->pspoll_frame_complete_task, + rtusb_pspoll_frame_done_tasklet, (unsigned long)pAd); + + return NDIS_STATUS_SUCCESS; +} + +void RtmpNetTaskExit(struct rt_rtmp_adapter *pAd) +{ + struct os_cookie *pObj; + + pObj = (struct os_cookie *)pAd->OS_Cookie; + + tasklet_kill(&pObj->rx_done_task); + tasklet_kill(&pObj->mgmt_dma_done_task); + tasklet_kill(&pObj->ac0_dma_done_task); + tasklet_kill(&pObj->ac1_dma_done_task); + tasklet_kill(&pObj->ac2_dma_done_task); + tasklet_kill(&pObj->ac3_dma_done_task); + tasklet_kill(&pObj->tbtt_task); + tasklet_kill(&pObj->null_frame_complete_task); + tasklet_kill(&pObj->rts_frame_complete_task); + tasklet_kill(&pObj->pspoll_frame_complete_task); +} diff --git a/drivers/staging/rt2860/rtmp.h b/drivers/staging/rt2860/rtmp.h index 90fd40f24734244b52fb617ed642e3da45810088..c50abf4b806864e5e9ab4dca4960b2479b2f1f3d 100644 --- a/drivers/staging/rt2860/rtmp.h +++ b/drivers/staging/rt2860/rtmp.h @@ -41,269 +41,135 @@ #define __RTMP_H__ #include "spectrum_def.h" +#include "rtmp_dot11.h" +#include "rtmp_chip.h" -#include "aironet.h" +struct rt_rtmp_adapter; -#define VIRTUAL_IF_INC(__pAd) ((__pAd)->VirtualIfCnt++) -#define VIRTUAL_IF_DEC(__pAd) ((__pAd)->VirtualIfCnt--) -#define VIRTUAL_IF_NUM(__pAd) ((__pAd)->VirtualIfCnt) - -#ifdef RT2870 -//////////////////////////////////////////////////////////////////////////// -// The TX_BUFFER structure forms the transmitted USB packet to the device -//////////////////////////////////////////////////////////////////////////// -typedef struct __TX_BUFFER{ - union { - UCHAR WirelessPacket[TX_BUFFER_NORMSIZE]; - HEADER_802_11 NullFrame; - PSPOLL_FRAME PsPollPacket; - RTS_FRAME RTSFrame; - }field; - UCHAR Aggregation[4]; //Buffer for save Aggregation size. -} TX_BUFFER, *PTX_BUFFER; - -typedef struct __HTTX_BUFFER{ - union { - UCHAR WirelessPacket[MAX_TXBULK_SIZE]; - HEADER_802_11 NullFrame; - PSPOLL_FRAME PsPollPacket; - RTS_FRAME RTSFrame; - }field; - UCHAR Aggregation[4]; //Buffer for save Aggregation size. -} HTTX_BUFFER, *PHTTX_BUFFER; - - -// used to track driver-generated write irps -typedef struct _TX_CONTEXT -{ - PVOID pAd; //Initialized in MiniportInitialize - PURB pUrb; //Initialized in MiniportInitialize - PIRP pIrp; //used to cancel pending bulk out. - //Initialized in MiniportInitialize - PTX_BUFFER TransferBuffer; //Initialized in MiniportInitialize - ULONG BulkOutSize; - UCHAR BulkOutPipeId; - UCHAR SelfIdx; - BOOLEAN InUse; - BOOLEAN bWaitingBulkOut; // at least one packet is in this TxContext, ready for making IRP anytime. - BOOLEAN bFullForBulkOut; // all tx buffer are full , so waiting for tx bulkout. - BOOLEAN IRPPending; - BOOLEAN LastOne; - BOOLEAN bAggregatible; - UCHAR Header_802_3[LENGTH_802_3]; - UCHAR Rsv[2]; - ULONG DataOffset; - UINT TxRate; - dma_addr_t data_dma; // urb dma on linux - -} TX_CONTEXT, *PTX_CONTEXT, **PPTX_CONTEXT; - - -// used to track driver-generated write irps -typedef struct _HT_TX_CONTEXT -{ - PVOID pAd; //Initialized in MiniportInitialize - PURB pUrb; //Initialized in MiniportInitialize - PIRP pIrp; //used to cancel pending bulk out. - //Initialized in MiniportInitialize - PHTTX_BUFFER TransferBuffer; //Initialized in MiniportInitialize - ULONG BulkOutSize; // Indicate the total bulk-out size in bytes in one bulk-transmission - UCHAR BulkOutPipeId; - BOOLEAN IRPPending; - BOOLEAN LastOne; - BOOLEAN bCurWriting; - BOOLEAN bRingEmpty; - BOOLEAN bCopySavePad; - UCHAR SavedPad[8]; - UCHAR Header_802_3[LENGTH_802_3]; - ULONG CurWritePosition; // Indicate the buffer offset which packet will be inserted start from. - ULONG CurWriteRealPos; // Indicate the buffer offset which packet now are writing to. - ULONG NextBulkOutPosition; // Indicate the buffer start offset of a bulk-transmission - ULONG ENextBulkOutPosition; // Indicate the buffer end offset of a bulk-transmission - UINT TxRate; - dma_addr_t data_dma; // urb dma on linux -} HT_TX_CONTEXT, *PHT_TX_CONTEXT, **PPHT_TX_CONTEXT; - - -// -// Structure to keep track of receive packets and buffers to indicate -// receive data to the protocol. -// -typedef struct _RX_CONTEXT -{ - PUCHAR TransferBuffer; - PVOID pAd; - PIRP pIrp;//used to cancel pending bulk in. - PURB pUrb; - //These 2 Boolean shouldn't both be 1 at the same time. - ULONG BulkInOffset; // number of packets waiting for reordering . - BOOLEAN bRxHandling; // Notify this packet is being process now. - BOOLEAN InUse; // USB Hardware Occupied. Wait for USB HW to put packet. - BOOLEAN Readable; // Receive Complete back. OK for driver to indicate receiving packet. - BOOLEAN IRPPending; // TODO: To be removed - atomic_t IrpLock; - NDIS_SPIN_LOCK RxContextLock; - dma_addr_t data_dma; // urb dma on linux -} RX_CONTEXT, *PRX_CONTEXT; -#endif // RT2870 // - - -// -// NDIS Version definitions -// -#ifdef NDIS50_MINIPORT -#define RTMP_NDIS_MAJOR_VERSION 5 -#define RTMP_NDIS_MINOR_VERSION 0 -#endif +/*#define DBG 1 */ -#ifdef NDIS51_MINIPORT -#define RTMP_NDIS_MAJOR_VERSION 5 -#define RTMP_NDIS_MINOR_VERSION 1 -#endif +/*#define DBG_DIAGNOSE 1 */ -extern char NIC_VENDOR_DESC[]; -extern int NIC_VENDOR_DESC_LEN; - -extern unsigned char SNAP_AIRONET[]; -extern unsigned char CipherSuiteCiscoCCKM[]; -extern unsigned char CipherSuiteCiscoCCKMLen; -extern unsigned char CipherSuiteCiscoCCKM24[]; -extern unsigned char CipherSuiteCiscoCCKM24Len; -extern unsigned char CipherSuiteCCXTkip[]; -extern unsigned char CipherSuiteCCXTkipLen; -extern unsigned char CISCO_OUI[]; -extern UCHAR BaSizeArray[4]; - -extern UCHAR BROADCAST_ADDR[MAC_ADDR_LEN]; -extern UCHAR MULTICAST_ADDR[MAC_ADDR_LEN]; -extern UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN]; -extern ULONG BIT32[32]; -extern UCHAR BIT8[8]; -extern char* CipherName[]; -extern char* MCSToMbps[]; -extern UCHAR RxwiMCSToOfdmRate[12]; -extern UCHAR SNAP_802_1H[6]; -extern UCHAR SNAP_BRIDGE_TUNNEL[6]; -extern UCHAR SNAP_AIRONET[8]; -extern UCHAR CKIP_LLC_SNAP[8]; -extern UCHAR EAPOL_LLC_SNAP[8]; -extern UCHAR EAPOL[2]; -extern UCHAR IPX[2]; -extern UCHAR APPLE_TALK[2]; -extern UCHAR RateIdToPlcpSignal[12]; // see IEEE802.11a-1999 p.14 -extern UCHAR OfdmRateToRxwiMCS[]; -extern UCHAR OfdmSignalToRateId[16] ; -extern UCHAR default_cwmin[4]; -extern UCHAR default_cwmax[4]; -extern UCHAR default_sta_aifsn[4]; -extern UCHAR MapUserPriorityToAccessCategory[8]; - -extern USHORT RateUpPER[]; -extern USHORT RateDownPER[]; -extern UCHAR Phy11BNextRateDownward[]; -extern UCHAR Phy11BNextRateUpward[]; -extern UCHAR Phy11BGNextRateDownward[]; -extern UCHAR Phy11BGNextRateUpward[]; -extern UCHAR Phy11ANextRateDownward[]; -extern UCHAR Phy11ANextRateUpward[]; -extern CHAR RssiSafeLevelForTxRate[]; -extern UCHAR RateIdToMbps[]; -extern USHORT RateIdTo500Kbps[]; - -extern UCHAR CipherSuiteWpaNoneTkip[]; -extern UCHAR CipherSuiteWpaNoneTkipLen; - -extern UCHAR CipherSuiteWpaNoneAes[]; -extern UCHAR CipherSuiteWpaNoneAesLen; - -extern UCHAR SsidIe; -extern UCHAR SupRateIe; -extern UCHAR ExtRateIe; - -extern UCHAR HtCapIe; -extern UCHAR AddHtInfoIe; -extern UCHAR NewExtChanIe; - -extern UCHAR ErpIe; -extern UCHAR DsIe; -extern UCHAR TimIe; -extern UCHAR WpaIe; -extern UCHAR Wpa2Ie; -extern UCHAR IbssIe; -extern UCHAR Ccx2Ie; - -extern UCHAR WPA_OUI[]; -extern UCHAR RSN_OUI[]; -extern UCHAR WME_INFO_ELEM[]; -extern UCHAR WME_PARM_ELEM[]; -extern UCHAR Ccx2QosInfo[]; -extern UCHAR Ccx2IeInfo[]; -extern UCHAR RALINK_OUI[]; -extern UCHAR PowerConstraintIE[]; - - -extern UCHAR RateSwitchTable[]; -extern UCHAR RateSwitchTable11B[]; -extern UCHAR RateSwitchTable11G[]; -extern UCHAR RateSwitchTable11BG[]; - -extern UCHAR RateSwitchTable11BGN1S[]; -extern UCHAR RateSwitchTable11BGN2S[]; -extern UCHAR RateSwitchTable11BGN2SForABand[]; -extern UCHAR RateSwitchTable11N1S[]; -extern UCHAR RateSwitchTable11N2S[]; -extern UCHAR RateSwitchTable11N2SForABand[]; - -extern UCHAR PRE_N_HT_OUI[]; +/*+++Add by shiang for merge MiniportMMRequest() and MiniportDataMMRequest() into one function */ +#define MAX_DATAMM_RETRY 3 +#define MGMT_USE_QUEUE_FLAG 0x80 +/*---Add by shiang for merge MiniportMMRequest() and MiniportDataMMRequest() into one function */ #define MAXSEQ (0xFFF) -struct reordering_mpdu -{ - struct reordering_mpdu *next; - PNDIS_PACKET pPacket; /* coverted to 802.3 frame */ - int Sequence; /* sequence number of MPDU */ - BOOLEAN bAMSDU; +extern unsigned char SNAP_AIRONET[]; +extern unsigned char CISCO_OUI[]; +extern u8 BaSizeArray[4]; + +extern u8 BROADCAST_ADDR[MAC_ADDR_LEN]; +extern u8 ZERO_MAC_ADDR[MAC_ADDR_LEN]; +extern unsigned long BIT32[32]; +extern u8 BIT8[8]; +extern char *CipherName[]; +extern char *MCSToMbps[]; +extern u8 RxwiMCSToOfdmRate[12]; +extern u8 SNAP_802_1H[6]; +extern u8 SNAP_BRIDGE_TUNNEL[6]; +extern u8 SNAP_AIRONET[8]; +extern u8 CKIP_LLC_SNAP[8]; +extern u8 EAPOL_LLC_SNAP[8]; +extern u8 EAPOL[2]; +extern u8 IPX[2]; +extern u8 APPLE_TALK[2]; +extern u8 RateIdToPlcpSignal[12]; /* see IEEE802.11a-1999 p.14 */ +extern u8 OfdmRateToRxwiMCS[]; +extern u8 OfdmSignalToRateId[16]; +extern u8 default_cwmin[4]; +extern u8 default_cwmax[4]; +extern u8 default_sta_aifsn[4]; +extern u8 MapUserPriorityToAccessCategory[8]; + +extern u16 RateUpPER[]; +extern u16 RateDownPER[]; +extern u8 Phy11BNextRateDownward[]; +extern u8 Phy11BNextRateUpward[]; +extern u8 Phy11BGNextRateDownward[]; +extern u8 Phy11BGNextRateUpward[]; +extern u8 Phy11ANextRateDownward[]; +extern u8 Phy11ANextRateUpward[]; +extern char RssiSafeLevelForTxRate[]; +extern u8 RateIdToMbps[]; +extern u16 RateIdTo500Kbps[]; + +extern u8 CipherSuiteWpaNoneTkip[]; +extern u8 CipherSuiteWpaNoneTkipLen; + +extern u8 CipherSuiteWpaNoneAes[]; +extern u8 CipherSuiteWpaNoneAesLen; + +extern u8 SsidIe; +extern u8 SupRateIe; +extern u8 ExtRateIe; + +extern u8 HtCapIe; +extern u8 AddHtInfoIe; +extern u8 NewExtChanIe; + +extern u8 ErpIe; +extern u8 DsIe; +extern u8 TimIe; +extern u8 WpaIe; +extern u8 Wpa2Ie; +extern u8 IbssIe; +extern u8 Ccx2Ie; +extern u8 WapiIe; + +extern u8 WPA_OUI[]; +extern u8 RSN_OUI[]; +extern u8 WAPI_OUI[]; +extern u8 WME_INFO_ELEM[]; +extern u8 WME_PARM_ELEM[]; +extern u8 Ccx2QosInfo[]; +extern u8 Ccx2IeInfo[]; +extern u8 RALINK_OUI[]; +extern u8 PowerConstraintIE[]; + +extern u8 RateSwitchTable[]; +extern u8 RateSwitchTable11B[]; +extern u8 RateSwitchTable11G[]; +extern u8 RateSwitchTable11BG[]; + +extern u8 RateSwitchTable11BGN1S[]; +extern u8 RateSwitchTable11BGN2S[]; +extern u8 RateSwitchTable11BGN2SForABand[]; +extern u8 RateSwitchTable11N1S[]; +extern u8 RateSwitchTable11N2S[]; +extern u8 RateSwitchTable11N2SForABand[]; + +extern u8 PRE_N_HT_OUI[]; + +struct rt_rssi_sample { + char LastRssi0; /* last received RSSI */ + char LastRssi1; /* last received RSSI */ + char LastRssi2; /* last received RSSI */ + char AvgRssi0; + char AvgRssi1; + char AvgRssi2; + short AvgRssi0X8; + short AvgRssi1X8; + short AvgRssi2X8; }; -struct reordering_list -{ - struct reordering_mpdu *next; - int qlen; -}; +/* */ +/* Queue structure and macros */ +/* */ +struct rt_queue_entry; -struct reordering_mpdu_pool -{ - PVOID mem; - NDIS_SPIN_LOCK lock; - struct reordering_list freelist; +struct rt_queue_entry { + struct rt_queue_entry *Next; }; -typedef struct _RSSI_SAMPLE { - CHAR LastRssi0; // last received RSSI - CHAR LastRssi1; // last received RSSI - CHAR LastRssi2; // last received RSSI - CHAR AvgRssi0; - CHAR AvgRssi1; - CHAR AvgRssi2; - SHORT AvgRssi0X8; - SHORT AvgRssi1X8; - SHORT AvgRssi2X8; -} RSSI_SAMPLE; - -// -// Queue structure and macros -// -typedef struct _QUEUE_ENTRY { - struct _QUEUE_ENTRY *Next; -} QUEUE_ENTRY, *PQUEUE_ENTRY; - -// Queue structure -typedef struct _QUEUE_HEADER { - PQUEUE_ENTRY Head; - PQUEUE_ENTRY Tail; - ULONG Number; -} QUEUE_HEADER, *PQUEUE_HEADER; +/* Queue structure */ +struct rt_queue_header { + struct rt_queue_entry *Head; + struct rt_queue_entry *Tail; + unsigned long Number; +}; #define InitializeQueueHeader(QueueHeader) \ { \ @@ -314,10 +180,11 @@ typedef struct _QUEUE_HEADER { #define RemoveHeadQueue(QueueHeader) \ (QueueHeader)->Head; \ { \ - PQUEUE_ENTRY pNext; \ + struct rt_queue_entry *pNext; \ if ((QueueHeader)->Head != NULL) \ { \ pNext = (QueueHeader)->Head->Next; \ + (QueueHeader)->Head->Next = NULL; \ (QueueHeader)->Head = pNext; \ if (pNext == NULL) \ (QueueHeader)->Tail = NULL; \ @@ -327,41 +194,49 @@ typedef struct _QUEUE_HEADER { #define InsertHeadQueue(QueueHeader, QueueEntry) \ { \ - ((PQUEUE_ENTRY)QueueEntry)->Next = (QueueHeader)->Head; \ - (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ + ((struct rt_queue_entry *)QueueEntry)->Next = (QueueHeader)->Head; \ + (QueueHeader)->Head = (struct rt_queue_entry *)(QueueEntry); \ if ((QueueHeader)->Tail == NULL) \ - (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Tail = (struct rt_queue_entry *)(QueueEntry); \ (QueueHeader)->Number++; \ } #define InsertTailQueue(QueueHeader, QueueEntry) \ { \ - ((PQUEUE_ENTRY)QueueEntry)->Next = NULL; \ + ((struct rt_queue_entry *)QueueEntry)->Next = NULL; \ if ((QueueHeader)->Tail) \ - (QueueHeader)->Tail->Next = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Tail->Next = (struct rt_queue_entry *)(QueueEntry); \ else \ - (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ - (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Head = (struct rt_queue_entry *)(QueueEntry); \ + (QueueHeader)->Tail = (struct rt_queue_entry *)(QueueEntry); \ (QueueHeader)->Number++; \ } -// -// Macros for flag and ref count operations -// +#define InsertTailQueueAc(pAd, pEntry, QueueHeader, QueueEntry) \ +{ \ + ((struct rt_queue_entry *)QueueEntry)->Next = NULL; \ + if ((QueueHeader)->Tail) \ + (QueueHeader)->Tail->Next = (struct rt_queue_entry *)(QueueEntry); \ + else \ + (QueueHeader)->Head = (struct rt_queue_entry *)(QueueEntry); \ + (QueueHeader)->Tail = (struct rt_queue_entry *)(QueueEntry); \ + (QueueHeader)->Number++; \ +} + +/* */ +/* Macros for flag and ref count operations */ +/* */ #define RTMP_SET_FLAG(_M, _F) ((_M)->Flags |= (_F)) #define RTMP_CLEAR_FLAG(_M, _F) ((_M)->Flags &= ~(_F)) #define RTMP_CLEAR_FLAGS(_M) ((_M)->Flags = 0) #define RTMP_TEST_FLAG(_M, _F) (((_M)->Flags & (_F)) != 0) #define RTMP_TEST_FLAGS(_M, _F) (((_M)->Flags & (_F)) == (_F)) - -#ifdef RT2860 -// Macro for power save flag. +/* Macro for power save flag. */ #define RTMP_SET_PSFLAG(_M, _F) ((_M)->PSFlags |= (_F)) #define RTMP_CLEAR_PSFLAG(_M, _F) ((_M)->PSFlags &= ~(_F)) #define RTMP_CLEAR_PSFLAGS(_M) ((_M)->PSFlags = 0) #define RTMP_TEST_PSFLAG(_M, _F) (((_M)->PSFlags & (_F)) != 0) #define RTMP_TEST_PSFLAGS(_M, _F) (((_M)->PSFlags & (_F)) == (_F)) -#endif #define OPSTATUS_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags |= (_F)) #define OPSTATUS_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags &= ~(_F)) @@ -385,59 +260,12 @@ typedef struct _QUEUE_HEADER { #define CKIP_KP_ON(_p) ((((_p)->StaCfg.CkipFlag) & 0x10) && ((_p)->StaCfg.bCkipCmicOn == TRUE)) #define CKIP_CMIC_ON(_p) ((((_p)->StaCfg.CkipFlag) & 0x08) && ((_p)->StaCfg.bCkipCmicOn == TRUE)) - #define INC_RING_INDEX(_idx, _RingSize) \ { \ (_idx) = (_idx+1) % (_RingSize); \ } -#ifdef RT2870 -// We will have a cost down version which mac version is 0x3090xxxx -#define IS_RT3090(_pAd) ((((_pAd)->MACVersion & 0xffff0000) == 0x30710000) || (((_pAd)->MACVersion & 0xffff0000) == 0x30900000)) -#else -#define IS_RT3090(_pAd) 0 -#endif -#define IS_RT3070(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x30700000) -#ifdef RT2870 -#define IS_RT3071(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x30710000) -#define IS_RT30xx(_pAd) (((_pAd)->MACVersion & 0xfff00000) == 0x30700000) -#endif - -#define RING_PACKET_INIT(_TxRing, _idx) \ -{ \ - _TxRing->Cell[_idx].pNdisPacket = NULL; \ - _TxRing->Cell[_idx].pNextNdisPacket = NULL; \ -} - -#define TXDT_INIT(_TxD) \ -{ \ - NdisZeroMemory(_TxD, TXD_SIZE); \ - _TxD->DMADONE = 1; \ -} - -//Set last data segment -#define RING_SET_LASTDS(_TxD, _IsSD0) \ -{ \ - if (_IsSD0) {_TxD->LastSec0 = 1;} \ - else {_TxD->LastSec1 = 1;} \ -} - -// Increase TxTsc value for next transmission -// TODO: -// When i==6, means TSC has done one full cycle, do re-keying stuff follow specs -// Should send a special event microsoft defined to request re-key -#define INC_TX_TSC(_tsc) \ -{ \ - int i=0; \ - while (++_tsc[i] == 0x0) \ - { \ - i++; \ - if (i == 6) \ - break; \ - } \ -} - -// StaActive.SupportedHtPhy.MCSSet is copied from AP beacon. Don't need to update here. +/* StaActive.SupportedHtPhy.MCSSet is copied from AP beacon. Don't need to update here. */ #define COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \ { \ _pAd->StaActive.SupportedHtPhy.ChannelWidth = _pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth; \ @@ -451,343 +279,52 @@ typedef struct _QUEUE_HEADER { _pAd->StaActive.SupportedHtPhy.RecomWidth = _pAd->MlmeAux.AddHtInfo.AddHtInfo.RecomWidth; \ _pAd->StaActive.SupportedHtPhy.OperaionMode = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode; \ _pAd->StaActive.SupportedHtPhy.NonGfPresent = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent; \ - NdisMoveMemory((_pAd)->MacTab.Content[BSSID_WCID].HTCapability.MCSSet, (_pAd)->StaActive.SupportedPhyInfo.MCSSet, sizeof(UCHAR) * 16);\ + NdisMoveMemory((_pAd)->MacTab.Content[BSSID_WCID].HTCapability.MCSSet, (_pAd)->StaActive.SupportedPhyInfo.MCSSet, sizeof(u8)* 16);\ } #define COPY_AP_HTSETTINGS_FROM_BEACON(_pAd, _pHtCapability) \ { \ - _pAd->MacTab.Content[BSSID_WCID].AMsduSize = (UCHAR)(_pHtCapability->HtCapInfo.AMsduSize); \ - _pAd->MacTab.Content[BSSID_WCID].MmpsMode= (UCHAR)(_pHtCapability->HtCapInfo.MimoPs); \ - _pAd->MacTab.Content[BSSID_WCID].MaxRAmpduFactor = (UCHAR)(_pHtCapability->HtCapParm.MaxRAmpduFactor); \ -} - -// -// MACRO for 32-bit PCI register read / write -// -// Usage : RTMP_IO_READ32( -// PRTMP_ADAPTER pAd, -// ULONG Register_Offset, -// PULONG pValue) -// -// RTMP_IO_WRITE32( -// PRTMP_ADAPTER pAd, -// ULONG Register_Offset, -// ULONG Value) -// - -// -// BBP & RF are using indirect access. Before write any value into it. -// We have to make sure there is no outstanding command pending via checking busy bit. -// -#define MAX_BUSY_COUNT 100 // Number of retry before failing access BBP & RF indirect register -// -#ifdef RT2860 -#define RTMP_RF_IO_WRITE32(_A, _V) \ -{ \ - PHY_CSR4_STRUC Value; \ - ULONG BusyCnt = 0; \ - if ((_A)->bPCIclkOff) \ - { \ - return; \ - } \ - do { \ - RTMP_IO_READ32(_A, RF_CSR_CFG0, &Value.word); \ - if (Value.field.Busy == IDLE) \ - break; \ - BusyCnt++; \ - } while (BusyCnt < MAX_BUSY_COUNT); \ - if (BusyCnt < MAX_BUSY_COUNT) \ - { \ - RTMP_IO_WRITE32(_A, RF_CSR_CFG0, _V); \ - } \ -} - -#define BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \ -{ \ - BBP_CSR_CFG_STRUC BbpCsr; \ - int i, k; \ - for (i=0; iBbpWriteLatch[_I]; \ - } \ -} - -//#define RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) {} -// Read BBP register by register's ID. Generate PER to test BA -#define RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \ -{ \ - BBP_CSR_CFG_STRUC BbpCsr; \ - int i, k; \ - if ((_A)->bPCIclkOff == FALSE) \ - { \ - for (i=0; iBbpWriteLatch[_I]; \ - RTMP_IO_READ32(_A, H2M_BBP_AGENT, &BbpCsr.word); \ - BbpCsr.field.Busy = 0; \ - RTMP_IO_WRITE32(_A, H2M_BBP_AGENT, BbpCsr.word); \ - } \ - } \ + _pAd->MacTab.Content[BSSID_WCID].AMsduSize = (u8)(_pHtCapability->HtCapInfo.AMsduSize); \ + _pAd->MacTab.Content[BSSID_WCID].MmpsMode= (u8)(_pHtCapability->HtCapInfo.MimoPs); \ + _pAd->MacTab.Content[BSSID_WCID].MaxRAmpduFactor = (u8)(_pHtCapability->HtCapParm.MaxRAmpduFactor); \ } -#define BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) \ -{ \ - BBP_CSR_CFG_STRUC BbpCsr; \ - int BusyCnt; \ - for (BusyCnt=0; BusyCntBbpWriteLatch[_I] = _V; \ - break; \ - } \ - if (BusyCnt == MAX_BUSY_COUNT) \ - { \ - DBGPRINT_ERR(("BBP write R%d fail\n", _I)); \ - } \ -} - -// Write BBP register by register's ID & value -#define RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) \ -{ \ - BBP_CSR_CFG_STRUC BbpCsr; \ - int BusyCnt; \ - if ((_A)->bPCIclkOff == FALSE) \ - { \ - for (BusyCnt=0; BusyCntOpMode == OPMODE_AP) \ - RTMPusecDelay(1000); \ - (_A)->BbpWriteLatch[_I] = _V; \ - break; \ - } \ - if (BusyCnt == MAX_BUSY_COUNT) \ - { \ - DBGPRINT_ERR(("BBP write R%d=0x%x fail\n", _I, BbpCsr.word)); \ - RTMP_IO_READ32(_A, H2M_BBP_AGENT, &BbpCsr.word); \ - BbpCsr.field.Busy = 0; \ - RTMP_IO_WRITE32(_A, H2M_BBP_AGENT, BbpCsr.word); \ - } \ - } \ -} -#endif /* RT2860 */ -#ifdef RT2870 -#define RTMP_RF_IO_WRITE32(_A, _V) RTUSBWriteRFRegister(_A, _V) -#define RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) RTUSBReadBBPRegister(_A, _I, _pV) -#define RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) RTUSBWriteBBPRegister(_A, _I, _V) - -#define BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) RTUSBWriteBBPRegister(_A, _I, _V) -#define BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) RTUSBReadBBPRegister(_A, _I, _pV) -#endif // RT2870 // - -#define MAP_CHANNEL_ID_TO_KHZ(ch, khz) { \ - switch (ch) \ - { \ - case 1: khz = 2412000; break; \ - case 2: khz = 2417000; break; \ - case 3: khz = 2422000; break; \ - case 4: khz = 2427000; break; \ - case 5: khz = 2432000; break; \ - case 6: khz = 2437000; break; \ - case 7: khz = 2442000; break; \ - case 8: khz = 2447000; break; \ - case 9: khz = 2452000; break; \ - case 10: khz = 2457000; break; \ - case 11: khz = 2462000; break; \ - case 12: khz = 2467000; break; \ - case 13: khz = 2472000; break; \ - case 14: khz = 2484000; break; \ - case 36: /* UNII */ khz = 5180000; break; \ - case 40: /* UNII */ khz = 5200000; break; \ - case 44: /* UNII */ khz = 5220000; break; \ - case 48: /* UNII */ khz = 5240000; break; \ - case 52: /* UNII */ khz = 5260000; break; \ - case 56: /* UNII */ khz = 5280000; break; \ - case 60: /* UNII */ khz = 5300000; break; \ - case 64: /* UNII */ khz = 5320000; break; \ - case 149: /* UNII */ khz = 5745000; break; \ - case 153: /* UNII */ khz = 5765000; break; \ - case 157: /* UNII */ khz = 5785000; break; \ - case 161: /* UNII */ khz = 5805000; break; \ - case 165: /* UNII */ khz = 5825000; break; \ - case 100: /* HiperLAN2 */ khz = 5500000; break; \ - case 104: /* HiperLAN2 */ khz = 5520000; break; \ - case 108: /* HiperLAN2 */ khz = 5540000; break; \ - case 112: /* HiperLAN2 */ khz = 5560000; break; \ - case 116: /* HiperLAN2 */ khz = 5580000; break; \ - case 120: /* HiperLAN2 */ khz = 5600000; break; \ - case 124: /* HiperLAN2 */ khz = 5620000; break; \ - case 128: /* HiperLAN2 */ khz = 5640000; break; \ - case 132: /* HiperLAN2 */ khz = 5660000; break; \ - case 136: /* HiperLAN2 */ khz = 5680000; break; \ - case 140: /* HiperLAN2 */ khz = 5700000; break; \ - case 34: /* Japan MMAC */ khz = 5170000; break; \ - case 38: /* Japan MMAC */ khz = 5190000; break; \ - case 42: /* Japan MMAC */ khz = 5210000; break; \ - case 46: /* Japan MMAC */ khz = 5230000; break; \ - case 184: /* Japan */ khz = 4920000; break; \ - case 188: /* Japan */ khz = 4940000; break; \ - case 192: /* Japan */ khz = 4960000; break; \ - case 196: /* Japan */ khz = 4980000; break; \ - case 208: /* Japan, means J08 */ khz = 5040000; break; \ - case 212: /* Japan, means J12 */ khz = 5060000; break; \ - case 216: /* Japan, means J16 */ khz = 5080000; break; \ - default: khz = 2412000; break; \ - } \ - } - -#define MAP_KHZ_TO_CHANNEL_ID(khz, ch) { \ - switch (khz) \ - { \ - case 2412000: ch = 1; break; \ - case 2417000: ch = 2; break; \ - case 2422000: ch = 3; break; \ - case 2427000: ch = 4; break; \ - case 2432000: ch = 5; break; \ - case 2437000: ch = 6; break; \ - case 2442000: ch = 7; break; \ - case 2447000: ch = 8; break; \ - case 2452000: ch = 9; break; \ - case 2457000: ch = 10; break; \ - case 2462000: ch = 11; break; \ - case 2467000: ch = 12; break; \ - case 2472000: ch = 13; break; \ - case 2484000: ch = 14; break; \ - case 5180000: ch = 36; /* UNII */ break; \ - case 5200000: ch = 40; /* UNII */ break; \ - case 5220000: ch = 44; /* UNII */ break; \ - case 5240000: ch = 48; /* UNII */ break; \ - case 5260000: ch = 52; /* UNII */ break; \ - case 5280000: ch = 56; /* UNII */ break; \ - case 5300000: ch = 60; /* UNII */ break; \ - case 5320000: ch = 64; /* UNII */ break; \ - case 5745000: ch = 149; /* UNII */ break; \ - case 5765000: ch = 153; /* UNII */ break; \ - case 5785000: ch = 157; /* UNII */ break; \ - case 5805000: ch = 161; /* UNII */ break; \ - case 5825000: ch = 165; /* UNII */ break; \ - case 5500000: ch = 100; /* HiperLAN2 */ break; \ - case 5520000: ch = 104; /* HiperLAN2 */ break; \ - case 5540000: ch = 108; /* HiperLAN2 */ break; \ - case 5560000: ch = 112; /* HiperLAN2 */ break; \ - case 5580000: ch = 116; /* HiperLAN2 */ break; \ - case 5600000: ch = 120; /* HiperLAN2 */ break; \ - case 5620000: ch = 124; /* HiperLAN2 */ break; \ - case 5640000: ch = 128; /* HiperLAN2 */ break; \ - case 5660000: ch = 132; /* HiperLAN2 */ break; \ - case 5680000: ch = 136; /* HiperLAN2 */ break; \ - case 5700000: ch = 140; /* HiperLAN2 */ break; \ - case 5170000: ch = 34; /* Japan MMAC */ break; \ - case 5190000: ch = 38; /* Japan MMAC */ break; \ - case 5210000: ch = 42; /* Japan MMAC */ break; \ - case 5230000: ch = 46; /* Japan MMAC */ break; \ - case 4920000: ch = 184; /* Japan */ break; \ - case 4940000: ch = 188; /* Japan */ break; \ - case 4960000: ch = 192; /* Japan */ break; \ - case 4980000: ch = 196; /* Japan */ break; \ - case 5040000: ch = 208; /* Japan, means J08 */ break; \ - case 5060000: ch = 212; /* Japan, means J12 */ break; \ - case 5080000: ch = 216; /* Japan, means J16 */ break; \ - default: ch = 1; break; \ - } \ - } - -// -// Common fragment list structure - Identical to the scatter gather frag list structure -// +/* */ +/* MACRO for 32-bit PCI register read / write */ +/* */ +/* Usage : RTMP_IO_READ32( */ +/* struct rt_rtmp_adapter *pAd, */ +/* unsigned long Register_Offset, */ +/* unsigned long * pValue) */ +/* */ +/* RTMP_IO_WRITE32( */ +/* struct rt_rtmp_adapter *pAd, */ +/* unsigned long Register_Offset, */ +/* unsigned long Value) */ +/* */ + +/* */ +/* Common fragment list structure - Identical to the scatter gather frag list structure */ +/* */ +/*#define struct rt_rtmp_sg_element SCATTER_GATHER_ELEMENT */ +/*#define struct rt_rtmp_sg_element *PSCATTER_GATHER_ELEMENT */ #define NIC_MAX_PHYS_BUF_COUNT 8 -typedef struct _RTMP_SCATTER_GATHER_ELEMENT { - PVOID Address; - ULONG Length; - PULONG Reserved; -} RTMP_SCATTER_GATHER_ELEMENT, *PRTMP_SCATTER_GATHER_ELEMENT; - +struct rt_rtmp_sg_element { + void *Address; + unsigned long Length; + unsigned long *Reserved; +}; -typedef struct _RTMP_SCATTER_GATHER_LIST { - ULONG NumberOfElements; - PULONG Reserved; - RTMP_SCATTER_GATHER_ELEMENT Elements[NIC_MAX_PHYS_BUF_COUNT]; -} RTMP_SCATTER_GATHER_LIST, *PRTMP_SCATTER_GATHER_LIST; +struct rt_rtmp_sg_list { + unsigned long NumberOfElements; + unsigned long *Reserved; + struct rt_rtmp_sg_element Elements[NIC_MAX_PHYS_BUF_COUNT]; +}; -// -// Some utility macros -// +/* */ +/* Some utility macros */ +/* */ #ifndef min #define min(_a, _b) (((_a) < (_b)) ? (_a) : (_b)) #endif @@ -805,11 +342,11 @@ typedef struct _RTMP_SCATTER_GATHER_LIST { #define MONITOR_ON(_p) (((_p)->StaCfg.BssType) == BSS_MONITOR) #define IDLE_ON(_p) (!INFRA_ON(_p) && !ADHOC_ON(_p)) -// Check LEAP & CCKM flags +/* Check LEAP & CCKM flags */ #define LEAP_ON(_p) (((_p)->StaCfg.LeapAuthMode) == CISCO_AuthModeLEAP) #define LEAP_CCKM_ON(_p) ((((_p)->StaCfg.LeapAuthMode) == CISCO_AuthModeLEAP) && ((_p)->StaCfg.LeapAuthInfo.CCKM == TRUE)) -// if orginal Ethernet frame contains no LLC/SNAP, then an extra LLC/SNAP encap is required +/* if orginal Ethernet frame contains no LLC/SNAP, then an extra LLC/SNAP encap is required */ #define EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(_pBufVA, _pExtraLlcSnapEncap) \ { \ if (((*(_pBufVA + 12) << 8) + *(_pBufVA + 13)) > 1500) \ @@ -827,7 +364,7 @@ typedef struct _RTMP_SCATTER_GATHER_LIST { } \ } -// New Define for new Tx Path. +/* New Define for new Tx Path. */ #define EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(_pBufVA, _pExtraLlcSnapEncap) \ { \ if (((*(_pBufVA) << 8) + *(_pBufVA + 1)) > 1500) \ @@ -845,7 +382,6 @@ typedef struct _RTMP_SCATTER_GATHER_LIST { } \ } - #define MAKE_802_3_HEADER(_p, _pMac1, _pMac2, _pType) \ { \ NdisMoveMemory(_p, _pMac1, MAC_ADDR_LEN); \ @@ -853,13 +389,13 @@ typedef struct _RTMP_SCATTER_GATHER_LIST { NdisMoveMemory((_p + MAC_ADDR_LEN * 2), _pType, LENGTH_802_3_TYPE); \ } -// if pData has no LLC/SNAP (neither RFC1042 nor Bridge tunnel), keep it that way. -// else if the received frame is LLC/SNAP-encaped IPX or APPLETALK, preserve the LLC/SNAP field -// else remove the LLC/SNAP field from the result Ethernet frame -// Patch for WHQL only, which did not turn on Netbios but use IPX within its payload -// Note: -// _pData & _DataSize may be altered (remove 8-byte LLC/SNAP) by this MACRO -// _pRemovedLLCSNAP: pointer to removed LLC/SNAP; NULL is not removed +/* if pData has no LLC/SNAP (neither RFC1042 nor Bridge tunnel), keep it that way. */ +/* else if the received frame is LLC/SNAP-encaped IPX or APPLETALK, preserve the LLC/SNAP field */ +/* else remove the LLC/SNAP field from the result Ethernet frame */ +/* Patch for WHQL only, which did not turn on Netbios but use IPX within its payload */ +/* Note: */ +/* _pData & _DataSize may be altered (remove 8-byte LLC/SNAP) by this MACRO */ +/* _pRemovedLLCSNAP: pointer to removed LLC/SNAP; NULL is not removed */ #define CONVERT_TO_802_3(_p8023hdr, _pDA, _pSA, _pData, _DataSize, _pRemovedLLCSNAP) \ { \ char LLC_Len[2]; \ @@ -868,13 +404,13 @@ typedef struct _RTMP_SCATTER_GATHER_LIST { if (NdisEqualMemory(SNAP_802_1H, _pData, 6) || \ NdisEqualMemory(SNAP_BRIDGE_TUNNEL, _pData, 6)) \ { \ - PUCHAR pProto = _pData + 6; \ + u8 *pProto = _pData + 6; \ \ if ((NdisEqualMemory(IPX, pProto, 2) || NdisEqualMemory(APPLE_TALK, pProto, 2)) && \ NdisEqualMemory(SNAP_802_1H, _pData, 6)) \ { \ - LLC_Len[0] = (UCHAR)(_DataSize / 256); \ - LLC_Len[1] = (UCHAR)(_DataSize % 256); \ + LLC_Len[0] = (u8)(_DataSize / 256); \ + LLC_Len[1] = (u8)(_DataSize % 256); \ MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len); \ } \ else \ @@ -887,551 +423,437 @@ typedef struct _RTMP_SCATTER_GATHER_LIST { } \ else \ { \ - LLC_Len[0] = (UCHAR)(_DataSize / 256); \ - LLC_Len[1] = (UCHAR)(_DataSize % 256); \ + LLC_Len[0] = (u8)(_DataSize / 256); \ + LLC_Len[1] = (u8)(_DataSize % 256); \ MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len); \ } \ } -#define SWITCH_AB( _pAA, _pBB) \ -{ \ - PVOID pCC; \ - pCC = _pBB; \ - _pBB = _pAA; \ - _pAA = pCC; \ -} - -// Enqueue this frame to MLME engine -// We need to enqueue the whole frame because MLME need to pass data type -// information from 802.11 header -#ifdef RT2860 +/* Enqueue this frame to MLME engine */ +/* We need to enqueue the whole frame because MLME need to pass data type */ +/* information from 802.11 header */ +#ifdef RTMP_MAC_PCI #define REPORT_MGMT_FRAME_TO_MLME(_pAd, Wcid, _pFrame, _FrameSize, _Rssi0, _Rssi1, _Rssi2, _PlcpSignal) \ { \ - UINT32 High32TSF, Low32TSF; \ + u32 High32TSF, Low32TSF; \ RTMP_IO_READ32(_pAd, TSF_TIMER_DW1, &High32TSF); \ RTMP_IO_READ32(_pAd, TSF_TIMER_DW0, &Low32TSF); \ - MlmeEnqueueForRecv(_pAd, Wcid, High32TSF, Low32TSF, (UCHAR)_Rssi0, (UCHAR)_Rssi1,(UCHAR)_Rssi2,_FrameSize, _pFrame, (UCHAR)_PlcpSignal); \ + MlmeEnqueueForRecv(_pAd, Wcid, High32TSF, Low32TSF, (u8)_Rssi0, (u8)_Rssi1,(u8)_Rssi2,_FrameSize, _pFrame, (u8)_PlcpSignal); \ } -#endif -#ifdef RT2870 +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB #define REPORT_MGMT_FRAME_TO_MLME(_pAd, Wcid, _pFrame, _FrameSize, _Rssi0, _Rssi1, _Rssi2, _PlcpSignal) \ { \ - UINT32 High32TSF=0, Low32TSF=0; \ - MlmeEnqueueForRecv(_pAd, Wcid, High32TSF, Low32TSF, (UCHAR)_Rssi0, (UCHAR)_Rssi1,(UCHAR)_Rssi2,_FrameSize, _pFrame, (UCHAR)_PlcpSignal); \ + u32 High32TSF=0, Low32TSF=0; \ + MlmeEnqueueForRecv(_pAd, Wcid, High32TSF, Low32TSF, (u8)_Rssi0, (u8)_Rssi1,(u8)_Rssi2,_FrameSize, _pFrame, (u8)_PlcpSignal); \ } -#endif // RT2870 // +#endif /* RTMP_MAC_USB // */ -//Need to collect each ant's rssi concurrently -//rssi1 is report to pair2 Ant and rss2 is reprot to pair1 Ant when 4 Ant -#define COLLECT_RX_ANTENNA_AVERAGE_RSSI(_pAd, _rssi1, _rssi2) \ -{ \ - SHORT AvgRssi; \ - UCHAR UsedAnt; \ - if (_pAd->RxAnt.EvaluatePeriod == 0) \ - { \ - UsedAnt = _pAd->RxAnt.Pair1PrimaryRxAnt; \ - AvgRssi = _pAd->RxAnt.Pair1AvgRssi[UsedAnt]; \ - if (AvgRssi < 0) \ - AvgRssi = AvgRssi - (AvgRssi >> 3) + _rssi1; \ - else \ - AvgRssi = _rssi1 << 3; \ - _pAd->RxAnt.Pair1AvgRssi[UsedAnt] = AvgRssi; \ - } \ - else \ - { \ - UsedAnt = _pAd->RxAnt.Pair1SecondaryRxAnt; \ - AvgRssi = _pAd->RxAnt.Pair1AvgRssi[UsedAnt]; \ - if ((AvgRssi < 0) && (_pAd->RxAnt.FirstPktArrivedWhenEvaluate)) \ - AvgRssi = AvgRssi - (AvgRssi >> 3) + _rssi1; \ - else \ - { \ - _pAd->RxAnt.FirstPktArrivedWhenEvaluate = TRUE; \ - AvgRssi = _rssi1 << 3; \ - } \ - _pAd->RxAnt.Pair1AvgRssi[UsedAnt] = AvgRssi; \ - _pAd->RxAnt.RcvPktNumWhenEvaluate++; \ - } \ -} - -#define NDIS_QUERY_BUFFER(_NdisBuf, _ppVA, _pBufLen) \ - NdisQueryBuffer(_NdisBuf, _ppVA, _pBufLen) - -#define MAC_ADDR_EQUAL(pAddr1,pAddr2) RTMPEqualMemory((PVOID)(pAddr1), (PVOID)(pAddr2), MAC_ADDR_LEN) +#define MAC_ADDR_EQUAL(pAddr1,pAddr2) RTMPEqualMemory((void *)(pAddr1), (void *)(pAddr2), MAC_ADDR_LEN) #define SSID_EQUAL(ssid1, len1, ssid2, len2) ((len1==len2) && (RTMPEqualMemory(ssid1, ssid2, len1))) -// -// Check if it is Japan W53(ch52,56,60,64) channel. -// +/* */ +/* Check if it is Japan W53(ch52,56,60,64) channel. */ +/* */ #define JapanChannelCheck(channel) ((channel == 52) || (channel == 56) || (channel == 60) || (channel == 64)) -#ifdef RT2860 +#define STA_EXTRA_SETTING(_pAd) + #define STA_PORT_SECURED(_pAd) \ { \ - _pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; \ - RTMP_SET_PSFLAG(_pAd, fRTMP_PS_CAN_GO_SLEEP); \ - NdisAcquireSpinLock(&(_pAd)->MacTabLock); \ - _pAd->MacTab.Content[BSSID_WCID].PortSecured = _pAd->StaCfg.PortSecured; \ + BOOLEAN Cancelled; \ + (_pAd)->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; \ + NdisAcquireSpinLock(&((_pAd)->MacTabLock)); \ + (_pAd)->MacTab.Content[BSSID_WCID].PortSecured = (_pAd)->StaCfg.PortSecured; \ + (_pAd)->MacTab.Content[BSSID_WCID].PrivacyFilter = Ndis802_11PrivFilterAcceptAll;\ NdisReleaseSpinLock(&(_pAd)->MacTabLock); \ + RTMPCancelTimer(&((_pAd)->Mlme.LinkDownTimer), &Cancelled);\ + STA_EXTRA_SETTING(_pAd); \ } -#endif -#ifdef RT2870 -#define STA_PORT_SECURED(_pAd) \ -{ \ - _pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; \ - NdisAcquireSpinLock(&_pAd->MacTabLock); \ - _pAd->MacTab.Content[BSSID_WCID].PortSecured = _pAd->StaCfg.PortSecured; \ - NdisReleaseSpinLock(&_pAd->MacTabLock); \ -} -#endif -// -// Register set pair for initialzation register set definition -// -typedef struct _RTMP_REG_PAIR -{ - ULONG Register; - ULONG Value; -} RTMP_REG_PAIR, *PRTMP_REG_PAIR; +/* */ +/* Data buffer for DMA operation, the buffer must be contiguous physical memory */ +/* Both DMA to / from CPU use the same structure. */ +/* */ +struct rt_rtmp_dmabuf { + unsigned long AllocSize; + void *AllocVa; /* TxBuf virtual address */ + dma_addr_t AllocPa; /* TxBuf physical address */ +}; -typedef struct _REG_PAIR -{ - UCHAR Register; - UCHAR Value; -} REG_PAIR, *PREG_PAIR; - -// -// Register set pair for initialzation register set definition -// -typedef struct _RTMP_RF_REGS -{ - UCHAR Channel; - ULONG R1; - ULONG R2; - ULONG R3; - ULONG R4; -} RTMP_RF_REGS, *PRTMP_RF_REGS; - -typedef struct _FREQUENCY_ITEM { - UCHAR Channel; - UCHAR N; - UCHAR R; - UCHAR K; -} FREQUENCY_ITEM, *PFREQUENCY_ITEM; - -// -// Data buffer for DMA operation, the buffer must be contiguous physical memory -// Both DMA to / from CPU use the same structure. -// -typedef struct _RTMP_DMABUF -{ - ULONG AllocSize; - PVOID AllocVa; // TxBuf virtual address - NDIS_PHYSICAL_ADDRESS AllocPa; // TxBuf physical address -} RTMP_DMABUF, *PRTMP_DMABUF; - - -typedef union _HEADER_802_11_SEQ{ - struct { - USHORT Frag:4; - USHORT Sequence:12; - } field; - USHORT value; -} HEADER_802_11_SEQ, *PHEADER_802_11_SEQ; - -// -// Data buffer for DMA operation, the buffer must be contiguous physical memory -// Both DMA to / from CPU use the same structure. -// -typedef struct _RTMP_REORDERBUF -{ - BOOLEAN IsFull; - PVOID AllocVa; // TxBuf virtual address - UCHAR Header802_3[14]; - HEADER_802_11_SEQ Sequence; //support compressed bitmap BA, so no consider fragment in BA - UCHAR DataOffset; - USHORT Datasize; - ULONG AllocSize; -#ifdef RT2860 - NDIS_PHYSICAL_ADDRESS AllocPa; // TxBuf physical address -#endif -#ifdef RT2870 - PUCHAR AllocPa; -#endif // RT2870 // -} RTMP_REORDERBUF, *PRTMP_REORDERBUF; - -// -// Control block (Descriptor) for all ring descriptor DMA operation, buffer must be -// contiguous physical memory. NDIS_PACKET stored the binding Rx packet descriptor -// which won't be released, driver has to wait until upper layer return the packet -// before giveing up this rx ring descriptor to ASIC. NDIS_BUFFER is assocaited pair -// to describe the packet buffer. For Tx, NDIS_PACKET stored the tx packet descriptor -// which driver should ACK upper layer when the tx is physically done or failed. -// -typedef struct _RTMP_DMACB -{ - ULONG AllocSize; // Control block size - PVOID AllocVa; // Control block virtual address - NDIS_PHYSICAL_ADDRESS AllocPa; // Control block physical address - PNDIS_PACKET pNdisPacket; - PNDIS_PACKET pNextNdisPacket; +/* */ +/* Control block (Descriptor) for all ring descriptor DMA operation, buffer must be */ +/* contiguous physical memory. char stored the binding Rx packet descriptor */ +/* which won't be released, driver has to wait until upper layer return the packet */ +/* before giveing up this rx ring descriptor to ASIC. NDIS_BUFFER is assocaited pair */ +/* to describe the packet buffer. For Tx, char stored the tx packet descriptor */ +/* which driver should ACK upper layer when the tx is physically done or failed. */ +/* */ +struct rt_rtmp_dmacb { + unsigned long AllocSize; /* Control block size */ + void *AllocVa; /* Control block virtual address */ + dma_addr_t AllocPa; /* Control block physical address */ + void *pNdisPacket; + void *pNextNdisPacket; + + struct rt_rtmp_dmabuf DmaBuf; /* Associated DMA buffer structure */ +}; - RTMP_DMABUF DmaBuf; // Associated DMA buffer structure -} RTMP_DMACB, *PRTMP_DMACB; +struct rt_rtmp_tx_ring { + struct rt_rtmp_dmacb Cell[TX_RING_SIZE]; + u32 TxCpuIdx; + u32 TxDmaIdx; + u32 TxSwFreeIdx; /* software next free tx index */ +}; -typedef struct _RTMP_TX_BUF -{ - PQUEUE_ENTRY Next; - UCHAR Index; - ULONG AllocSize; // Control block size - PVOID AllocVa; // Control block virtual address - NDIS_PHYSICAL_ADDRESS AllocPa; // Control block physical address -} RTMP_TXBUF, *PRTMP_TXBUF; - -typedef struct _RTMP_RX_BUF -{ - BOOLEAN InUse; - ULONG ByBaRecIndex; - RTMP_REORDERBUF MAP_RXBuf[MAX_RX_REORDERBUF]; -} RTMP_RXBUF, *PRTMP_RXBUF; -typedef struct _RTMP_TX_RING -{ - RTMP_DMACB Cell[TX_RING_SIZE]; - UINT32 TxCpuIdx; - UINT32 TxDmaIdx; - UINT32 TxSwFreeIdx; // software next free tx index -} RTMP_TX_RING, *PRTMP_TX_RING; +struct rt_rtmp_rx_ring { + struct rt_rtmp_dmacb Cell[RX_RING_SIZE]; + u32 RxCpuIdx; + u32 RxDmaIdx; + int RxSwReadIdx; /* software next read index */ +}; -typedef struct _RTMP_RX_RING -{ - RTMP_DMACB Cell[RX_RING_SIZE]; - UINT32 RxCpuIdx; - UINT32 RxDmaIdx; - INT32 RxSwReadIdx; // software next read index -} RTMP_RX_RING, *PRTMP_RX_RING; +struct rt_rtmp_mgmt_ring { + struct rt_rtmp_dmacb Cell[MGMT_RING_SIZE]; + u32 TxCpuIdx; + u32 TxDmaIdx; + u32 TxSwFreeIdx; /* software next free tx index */ +}; -typedef struct _RTMP_MGMT_RING -{ - RTMP_DMACB Cell[MGMT_RING_SIZE]; - UINT32 TxCpuIdx; - UINT32 TxDmaIdx; - UINT32 TxSwFreeIdx; // software next free tx index -} RTMP_MGMT_RING, *PRTMP_MGMT_RING; - -// -// Statistic counter structure -// -typedef struct _COUNTER_802_3 -{ - // General Stats - ULONG GoodTransmits; - ULONG GoodReceives; - ULONG TxErrors; - ULONG RxErrors; - ULONG RxNoBuffer; - - // Ethernet Stats - ULONG RcvAlignmentErrors; - ULONG OneCollision; - ULONG MoreCollisions; - -} COUNTER_802_3, *PCOUNTER_802_3; - -typedef struct _COUNTER_802_11 { - ULONG Length; - LARGE_INTEGER LastTransmittedFragmentCount; - LARGE_INTEGER TransmittedFragmentCount; - LARGE_INTEGER MulticastTransmittedFrameCount; - LARGE_INTEGER FailedCount; - LARGE_INTEGER RetryCount; - LARGE_INTEGER MultipleRetryCount; - LARGE_INTEGER RTSSuccessCount; - LARGE_INTEGER RTSFailureCount; - LARGE_INTEGER ACKFailureCount; - LARGE_INTEGER FrameDuplicateCount; - LARGE_INTEGER ReceivedFragmentCount; - LARGE_INTEGER MulticastReceivedFrameCount; - LARGE_INTEGER FCSErrorCount; -} COUNTER_802_11, *PCOUNTER_802_11; - -typedef struct _COUNTER_RALINK { - ULONG TransmittedByteCount; // both successful and failure, used to calculate TX throughput -#ifdef RT2860 - ULONG LastReceivedByteCount; -#endif - ULONG ReceivedByteCount; // both CRC okay and CRC error, used to calculate RX throughput - ULONG BeenDisassociatedCount; - ULONG BadCQIAutoRecoveryCount; - ULONG PoorCQIRoamingCount; - ULONG MgmtRingFullCount; - ULONG RxCountSinceLastNULL; - ULONG RxCount; - ULONG RxRingErrCount; - ULONG KickTxCount; - ULONG TxRingErrCount; - LARGE_INTEGER RealFcsErrCount; - ULONG PendingNdisPacketCount; - - ULONG OneSecOsTxCount[NUM_OF_TX_RING]; - ULONG OneSecDmaDoneCount[NUM_OF_TX_RING]; - UINT32 OneSecTxDoneCount; - ULONG OneSecRxCount; - UINT32 OneSecTxAggregationCount; - UINT32 OneSecRxAggregationCount; - - UINT32 OneSecFrameDuplicateCount; - -#ifdef RT2870 - ULONG OneSecTransmittedByteCount; // both successful and failure, used to calculate TX throughput -#endif // RT2870 // - - UINT32 OneSecTxNoRetryOkCount; - UINT32 OneSecTxRetryOkCount; - UINT32 OneSecTxFailCount; - UINT32 OneSecFalseCCACnt; // CCA error count, for debug purpose, might move to global counter - UINT32 OneSecRxOkCnt; // RX without error - UINT32 OneSecRxOkDataCnt; // unicast-to-me DATA frame count - UINT32 OneSecRxFcsErrCnt; // CRC error - UINT32 OneSecBeaconSentCnt; - UINT32 LastOneSecTotalTxCount; // OneSecTxNoRetryOkCount + OneSecTxRetryOkCount + OneSecTxFailCount - UINT32 LastOneSecRxOkDataCnt; // OneSecRxOkDataCnt - ULONG DuplicateRcv; - ULONG TxAggCount; - ULONG TxNonAggCount; - ULONG TxAgg1MPDUCount; - ULONG TxAgg2MPDUCount; - ULONG TxAgg3MPDUCount; - ULONG TxAgg4MPDUCount; - ULONG TxAgg5MPDUCount; - ULONG TxAgg6MPDUCount; - ULONG TxAgg7MPDUCount; - ULONG TxAgg8MPDUCount; - ULONG TxAgg9MPDUCount; - ULONG TxAgg10MPDUCount; - ULONG TxAgg11MPDUCount; - ULONG TxAgg12MPDUCount; - ULONG TxAgg13MPDUCount; - ULONG TxAgg14MPDUCount; - ULONG TxAgg15MPDUCount; - ULONG TxAgg16MPDUCount; - - LARGE_INTEGER TransmittedOctetsInAMSDU; - LARGE_INTEGER TransmittedAMSDUCount; - LARGE_INTEGER ReceivedOctesInAMSDUCount; - LARGE_INTEGER ReceivedAMSDUCount; - LARGE_INTEGER TransmittedAMPDUCount; - LARGE_INTEGER TransmittedMPDUsInAMPDUCount; - LARGE_INTEGER TransmittedOctetsInAMPDUCount; - LARGE_INTEGER MPDUInReceivedAMPDUCount; -} COUNTER_RALINK, *PCOUNTER_RALINK; - -typedef struct _PID_COUNTER { - ULONG TxAckRequiredCount; // CRC error - ULONG TxAggreCount; - ULONG TxSuccessCount; // OneSecTxNoRetryOkCount + OneSecTxRetryOkCount + OneSecTxFailCount - ULONG LastSuccessRate; -} PID_COUNTER, *PPID_COUNTER; - -typedef struct _COUNTER_DRS { - // to record the each TX rate's quality. 0 is best, the bigger the worse. - USHORT TxQuality[MAX_STEP_OF_TX_RATE_SWITCH]; - UCHAR PER[MAX_STEP_OF_TX_RATE_SWITCH]; - UCHAR TxRateUpPenalty; // extra # of second penalty due to last unstable condition - ULONG CurrTxRateStableTime; // # of second in current TX rate - BOOLEAN fNoisyEnvironment; - BOOLEAN fLastSecAccordingRSSI; - UCHAR LastSecTxRateChangeAction; // 0: no change, 1:rate UP, 2:rate down - UCHAR LastTimeTxRateChangeAction; //Keep last time value of LastSecTxRateChangeAction - ULONG LastTxOkCount; -} COUNTER_DRS, *PCOUNTER_DRS; - -// -// Arcfour Structure Added by PaulWu -// -typedef struct _ARCFOUR -{ - UINT X; - UINT Y; - UCHAR STATE[256]; -} ARCFOURCONTEXT, *PARCFOURCONTEXT; - -// MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI too. just copy to TXWI. -typedef struct _RECEIVE_SETTING { - USHORT NumOfRX:2; // MIMO. WE HAVE 3R - USHORT Mode:2; //channel bandwidth 20MHz or 40 MHz - USHORT ShortGI:1; - USHORT STBC:2; //SPACE - USHORT rsv:3; - USHORT OFDM:1; - USHORT MIMO:1; - } RECEIVE_SETTING, *PRECEIVE_SETTING; - -// Shared key data structure -typedef struct _WEP_KEY { - UCHAR KeyLen; // Key length for each key, 0: entry is invalid - UCHAR Key[MAX_LEN_OF_KEY]; // right now we implement 4 keys, 128 bits max -} WEP_KEY, *PWEP_KEY; - -typedef struct _CIPHER_KEY { - UCHAR Key[16]; // right now we implement 4 keys, 128 bits max - UCHAR RxMic[8]; // make alignment - UCHAR TxMic[8]; - UCHAR TxTsc[6]; // 48bit TSC value - UCHAR RxTsc[6]; // 48bit TSC value - UCHAR CipherAlg; // 0-none, 1:WEP64, 2:WEP128, 3:TKIP, 4:AES, 5:CKIP64, 6:CKIP128 - UCHAR KeyLen; - UCHAR BssId[6]; - // Key length for each key, 0: entry is invalid - UCHAR Type; // Indicate Pairwise/Group when reporting MIC error -} CIPHER_KEY, *PCIPHER_KEY; - -typedef struct _BBP_TUNING_STRUCT { - BOOLEAN Enable; - UCHAR FalseCcaCountUpperBound; // 100 per sec - UCHAR FalseCcaCountLowerBound; // 10 per sec - UCHAR R17LowerBound; // specified in E2PROM - UCHAR R17UpperBound; // 0x68 according to David Tung - UCHAR CurrentR17Value; -} BBP_TUNING, *PBBP_TUNING; - -typedef struct _SOFT_RX_ANT_DIVERSITY_STRUCT { - UCHAR EvaluatePeriod; // 0:not evalute status, 1: evaluate status, 2: switching status -#ifdef RT2870 - UCHAR EvaluateStableCnt; -#endif - UCHAR Pair1PrimaryRxAnt; // 0:Ant-E1, 1:Ant-E2 - UCHAR Pair1SecondaryRxAnt; // 0:Ant-E1, 1:Ant-E2 - UCHAR Pair2PrimaryRxAnt; // 0:Ant-E3, 1:Ant-E4 - UCHAR Pair2SecondaryRxAnt; // 0:Ant-E3, 1:Ant-E4 - SHORT Pair1AvgRssi[2]; // AvgRssi[0]:E1, AvgRssi[1]:E2 - SHORT Pair2AvgRssi[2]; // AvgRssi[0]:E3, AvgRssi[1]:E4 - SHORT Pair1LastAvgRssi; // - SHORT Pair2LastAvgRssi; // - ULONG RcvPktNumWhenEvaluate; - BOOLEAN FirstPktArrivedWhenEvaluate; - RALINK_TIMER_STRUCT RxAntDiversityTimer; -} SOFT_RX_ANT_DIVERSITY, *PSOFT_RX_ANT_DIVERSITY; - -typedef struct _LEAP_AUTH_INFO { - BOOLEAN Enabled; //Ture: Enable LEAP Authentication - BOOLEAN CCKM; //Ture: Use Fast Reauthentication with CCKM - UCHAR Reserve[2]; - UCHAR UserName[256]; //LEAP, User name - ULONG UserNameLen; - UCHAR Password[256]; //LEAP, User Password - ULONG PasswordLen; -} LEAP_AUTH_INFO, *PLEAP_AUTH_INFO; - -typedef struct { - UCHAR Addr[MAC_ADDR_LEN]; - UCHAR ErrorCode[2]; //00 01-Invalid authentication type - //00 02-Authentication timeout - //00 03-Challenge from AP failed - //00 04-Challenge to AP failed - BOOLEAN Reported; -} ROGUEAP_ENTRY, *PROGUEAP_ENTRY; - -typedef struct { - UCHAR RogueApNr; - ROGUEAP_ENTRY RogueApEntry[MAX_LEN_OF_BSS_TABLE]; -} ROGUEAP_TABLE, *PROGUEAP_TABLE; - -typedef struct { - BOOLEAN Enable; - UCHAR Delta; - BOOLEAN PlusSign; -} CCK_TX_POWER_CALIBRATE, *PCCK_TX_POWER_CALIBRATE; - -// -// Receive Tuple Cache Format -// -typedef struct _TUPLE_CACHE { - BOOLEAN Valid; - UCHAR MacAddress[MAC_ADDR_LEN]; - USHORT Sequence; - USHORT Frag; -} TUPLE_CACHE, *PTUPLE_CACHE; - -// -// Fragment Frame structure -// -typedef struct _FRAGMENT_FRAME { - PNDIS_PACKET pFragPacket; - ULONG RxSize; - USHORT Sequence; - USHORT LastFrag; - ULONG Flags; // Some extra frame information. bit 0: LLC presented -} FRAGMENT_FRAME, *PFRAGMENT_FRAME; - - -// -// Packet information for NdisQueryPacket -// -typedef struct _PACKET_INFO { - UINT PhysicalBufferCount; // Physical breaks of buffer descripor chained - UINT BufferCount ; // Number of Buffer descriptor chained - UINT TotalPacketLength ; // Self explained - PNDIS_BUFFER pFirstBuffer; // Pointer to first buffer descriptor -} PACKET_INFO, *PPACKET_INFO; - -// -// Tkip Key structure which RC4 key & MIC calculation -// -typedef struct _TKIP_KEY_INFO { - UINT nBytesInM; // # bytes in M for MICKEY - ULONG IV16; - ULONG IV32; - ULONG K0; // for MICKEY Low - ULONG K1; // for MICKEY Hig - ULONG L; // Current state for MICKEY - ULONG R; // Current state for MICKEY - ULONG M; // Message accumulator for MICKEY - UCHAR RC4KEY[16]; - UCHAR MIC[8]; -} TKIP_KEY_INFO, *PTKIP_KEY_INFO; - -// -// Private / Misc data, counters for driver internal use -// -typedef struct __PRIVATE_STRUC { - UINT SystemResetCnt; // System reset counter - UINT TxRingFullCnt; // Tx ring full occurrance number - UINT PhyRxErrCnt; // PHY Rx error count, for debug purpose, might move to global counter - // Variables for WEP encryption / decryption in rtmp_wep.c - UINT FCSCRC32; - ARCFOURCONTEXT WEPCONTEXT; - // Tkip stuff - TKIP_KEY_INFO Tx; - TKIP_KEY_INFO Rx; -} PRIVATE_STRUC, *PPRIVATE_STRUC; - -// structure to tune BBP R66 (BBP TUNING) -typedef struct _BBP_R66_TUNING { - BOOLEAN bEnable; - USHORT FalseCcaLowerThreshold; // default 100 - USHORT FalseCcaUpperThreshold; // default 512 - UCHAR R66Delta; - UCHAR R66CurrentValue; - BOOLEAN R66LowerUpperSelect; //Before LinkUp, Used LowerBound or UpperBound as R66 value. -} BBP_R66_TUNING, *PBBP_R66_TUNING; - -// structure to store channel TX power -typedef struct _CHANNEL_TX_POWER { - USHORT RemainingTimeForUse; //unit: sec - UCHAR Channel; - CHAR Power; - CHAR Power2; - UCHAR MaxTxPwr; - UCHAR DfsReq; -} CHANNEL_TX_POWER, *PCHANNEL_TX_POWER; - -// structure to store 802.11j channel TX power -typedef struct _CHANNEL_11J_TX_POWER { - UCHAR Channel; - UCHAR BW; // BW_10 or BW_20 - CHAR Power; - CHAR Power2; - USHORT RemainingTimeForUse; //unit: sec -} CHANNEL_11J_TX_POWER, *PCHANNEL_11J_TX_POWER; +/* */ +/* Statistic counter structure */ +/* */ +struct rt_counter_802_3 { + /* General Stats */ + unsigned long GoodTransmits; + unsigned long GoodReceives; + unsigned long TxErrors; + unsigned long RxErrors; + unsigned long RxNoBuffer; + + /* Ethernet Stats */ + unsigned long RcvAlignmentErrors; + unsigned long OneCollision; + unsigned long MoreCollisions; + +}; + +struct rt_counter_802_11 { + unsigned long Length; + LARGE_INTEGER LastTransmittedFragmentCount; + LARGE_INTEGER TransmittedFragmentCount; + LARGE_INTEGER MulticastTransmittedFrameCount; + LARGE_INTEGER FailedCount; + LARGE_INTEGER RetryCount; + LARGE_INTEGER MultipleRetryCount; + LARGE_INTEGER RTSSuccessCount; + LARGE_INTEGER RTSFailureCount; + LARGE_INTEGER ACKFailureCount; + LARGE_INTEGER FrameDuplicateCount; + LARGE_INTEGER ReceivedFragmentCount; + LARGE_INTEGER MulticastReceivedFrameCount; + LARGE_INTEGER FCSErrorCount; +}; + +struct rt_counter_ralink { + unsigned long TransmittedByteCount; /* both successful and failure, used to calculate TX throughput */ + unsigned long ReceivedByteCount; /* both CRC okay and CRC error, used to calculate RX throughput */ + unsigned long BeenDisassociatedCount; + unsigned long BadCQIAutoRecoveryCount; + unsigned long PoorCQIRoamingCount; + unsigned long MgmtRingFullCount; + unsigned long RxCountSinceLastNULL; + unsigned long RxCount; + unsigned long RxRingErrCount; + unsigned long KickTxCount; + unsigned long TxRingErrCount; + LARGE_INTEGER RealFcsErrCount; + unsigned long PendingNdisPacketCount; + + unsigned long OneSecOsTxCount[NUM_OF_TX_RING]; + unsigned long OneSecDmaDoneCount[NUM_OF_TX_RING]; + u32 OneSecTxDoneCount; + unsigned long OneSecRxCount; + u32 OneSecTxAggregationCount; + u32 OneSecRxAggregationCount; + u32 OneSecReceivedByteCount; + u32 OneSecFrameDuplicateCount; + + u32 OneSecTransmittedByteCount; /* both successful and failure, used to calculate TX throughput */ + u32 OneSecTxNoRetryOkCount; + u32 OneSecTxRetryOkCount; + u32 OneSecTxFailCount; + u32 OneSecFalseCCACnt; /* CCA error count, for debug purpose, might move to global counter */ + u32 OneSecRxOkCnt; /* RX without error */ + u32 OneSecRxOkDataCnt; /* unicast-to-me DATA frame count */ + u32 OneSecRxFcsErrCnt; /* CRC error */ + u32 OneSecBeaconSentCnt; + u32 LastOneSecTotalTxCount; /* OneSecTxNoRetryOkCount + OneSecTxRetryOkCount + OneSecTxFailCount */ + u32 LastOneSecRxOkDataCnt; /* OneSecRxOkDataCnt */ + unsigned long DuplicateRcv; + unsigned long TxAggCount; + unsigned long TxNonAggCount; + unsigned long TxAgg1MPDUCount; + unsigned long TxAgg2MPDUCount; + unsigned long TxAgg3MPDUCount; + unsigned long TxAgg4MPDUCount; + unsigned long TxAgg5MPDUCount; + unsigned long TxAgg6MPDUCount; + unsigned long TxAgg7MPDUCount; + unsigned long TxAgg8MPDUCount; + unsigned long TxAgg9MPDUCount; + unsigned long TxAgg10MPDUCount; + unsigned long TxAgg11MPDUCount; + unsigned long TxAgg12MPDUCount; + unsigned long TxAgg13MPDUCount; + unsigned long TxAgg14MPDUCount; + unsigned long TxAgg15MPDUCount; + unsigned long TxAgg16MPDUCount; + + LARGE_INTEGER TransmittedOctetsInAMSDU; + LARGE_INTEGER TransmittedAMSDUCount; + LARGE_INTEGER ReceivedOctesInAMSDUCount; + LARGE_INTEGER ReceivedAMSDUCount; + LARGE_INTEGER TransmittedAMPDUCount; + LARGE_INTEGER TransmittedMPDUsInAMPDUCount; + LARGE_INTEGER TransmittedOctetsInAMPDUCount; + LARGE_INTEGER MPDUInReceivedAMPDUCount; +}; + +struct rt_counter_drs { + /* to record the each TX rate's quality. 0 is best, the bigger the worse. */ + u16 TxQuality[MAX_STEP_OF_TX_RATE_SWITCH]; + u8 PER[MAX_STEP_OF_TX_RATE_SWITCH]; + u8 TxRateUpPenalty; /* extra # of second penalty due to last unstable condition */ + unsigned long CurrTxRateStableTime; /* # of second in current TX rate */ + BOOLEAN fNoisyEnvironment; + BOOLEAN fLastSecAccordingRSSI; + u8 LastSecTxRateChangeAction; /* 0: no change, 1:rate UP, 2:rate down */ + u8 LastTimeTxRateChangeAction; /*Keep last time value of LastSecTxRateChangeAction */ + unsigned long LastTxOkCount; +}; + +/*************************************************************************** + * security key related data structure + **************************************************************************/ +struct rt_cipher_key { + u8 Key[16]; /* right now we implement 4 keys, 128 bits max */ + u8 RxMic[8]; /* make alignment */ + u8 TxMic[8]; + u8 TxTsc[6]; /* 48bit TSC value */ + u8 RxTsc[6]; /* 48bit TSC value */ + u8 CipherAlg; /* 0-none, 1:WEP64, 2:WEP128, 3:TKIP, 4:AES, 5:CKIP64, 6:CKIP128 */ + u8 KeyLen; + u8 BssId[6]; + /* Key length for each key, 0: entry is invalid */ + u8 Type; /* Indicate Pairwise/Group when reporting MIC error */ +}; + +/* structure to define WPA Group Key Rekey Interval */ +struct PACKED rt_802_11_wpa_rekey { + unsigned long ReKeyMethod; /* mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based */ + unsigned long ReKeyInterval; /* time-based: seconds, packet-based: kilo-packets */ +}; + +#ifdef RTMP_MAC_USB +/*************************************************************************** + * RTUSB I/O related data structure + **************************************************************************/ +struct rt_set_asic_wcid { + unsigned long WCID; /* mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based */ + unsigned long SetTid; /* time-based: seconds, packet-based: kilo-packets */ + unsigned long DeleteTid; /* time-based: seconds, packet-based: kilo-packets */ + u8 Addr[MAC_ADDR_LEN]; /* avoid in interrupt when write key */ +}; + +struct rt_set_asic_wcid_attri { + unsigned long WCID; /* mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based */ + unsigned long Cipher; /* ASIC Cipher definition */ + u8 Addr[ETH_LENGTH_OF_ADDRESS]; +}; + +/* for USB interface, avoid in interrupt when write key */ +struct rt_add_pairwise_key_entry { + u8 MacAddr[6]; + u16 MacTabMatchWCID; /* ASIC */ + struct rt_cipher_key CipherKey; +}; + +/* Cipher suite type for mixed mode group cipher, P802.11i-2004 */ +typedef enum _RT_802_11_CIPHER_SUITE_TYPE { + Cipher_Type_NONE, + Cipher_Type_WEP40, + Cipher_Type_TKIP, + Cipher_Type_RSVD, + Cipher_Type_CCMP, + Cipher_Type_WEP104 +} RT_802_11_CIPHER_SUITE_TYPE, *PRT_802_11_CIPHER_SUITE_TYPE; +#endif /* RTMP_MAC_USB // */ + +struct rt_rogueap_entry { + u8 Addr[MAC_ADDR_LEN]; + u8 ErrorCode[2]; /*00 01-Invalid authentication type */ + /*00 02-Authentication timeout */ + /*00 03-Challenge from AP failed */ + /*00 04-Challenge to AP failed */ + BOOLEAN Reported; +}; + +struct rt_rogueap_table { + u8 RogueApNr; + struct rt_rogueap_entry RogueApEntry[MAX_LEN_OF_BSS_TABLE]; +}; + +/* */ +/* Cisco IAPP format */ +/* */ +struct rt_cisco_iapp_content { + u16 Length; /*IAPP Length */ + u8 MessageType; /*IAPP type */ + u8 FunctionCode; /*IAPP function type */ + u8 DestinaionMAC[MAC_ADDR_LEN]; + u8 SourceMAC[MAC_ADDR_LEN]; + u16 Tag; /*Tag(element IE) - Adjacent AP report */ + u16 TagLength; /*Length of element not including 4 byte header */ + u8 OUI[4]; /*0x00, 0x40, 0x96, 0x00 */ + u8 PreviousAP[MAC_ADDR_LEN]; /*MAC Address of access point */ + u16 Channel; + u16 SsidLen; + u8 Ssid[MAX_LEN_OF_SSID]; + u16 Seconds; /*Seconds that the client has been disassociated. */ +}; + +/* + * Fragment Frame structure + */ +struct rt_fragment_frame { + void *pFragPacket; + unsigned long RxSize; + u16 Sequence; + u16 LastFrag; + unsigned long Flags; /* Some extra frame information. bit 0: LLC presented */ +}; + +/* */ +/* Packet information for NdisQueryPacket */ +/* */ +struct rt_packet_info { + u32 PhysicalBufferCount; /* Physical breaks of buffer descripor chained */ + u32 BufferCount; /* Number of Buffer descriptor chained */ + u32 TotalPacketLength; /* Self explained */ + char *pFirstBuffer; /* Pointer to first buffer descriptor */ +}; + +/* */ +/* Arcfour Structure Added by PaulWu */ +/* */ +struct rt_arcfourcontext { + u32 X; + u32 Y; + u8 STATE[256]; +}; + +/* */ +/* Tkip Key structure which RC4 key & MIC calculation */ +/* */ +struct rt_tkip_key_info { + u32 nBytesInM; /* # bytes in M for MICKEY */ + unsigned long IV16; + unsigned long IV32; + unsigned long K0; /* for MICKEY Low */ + unsigned long K1; /* for MICKEY Hig */ + unsigned long L; /* Current state for MICKEY */ + unsigned long R; /* Current state for MICKEY */ + unsigned long M; /* Message accumulator for MICKEY */ + u8 RC4KEY[16]; + u8 MIC[8]; +}; + +/* */ +/* Private / Misc data, counters for driver internal use */ +/* */ +struct rt_private { + u32 SystemResetCnt; /* System reset counter */ + u32 TxRingFullCnt; /* Tx ring full occurrance number */ + u32 PhyRxErrCnt; /* PHY Rx error count, for debug purpose, might move to global counter */ + /* Variables for WEP encryption / decryption in rtmp_wep.c */ + u32 FCSCRC32; + struct rt_arcfourcontext WEPCONTEXT; + /* Tkip stuff */ + struct rt_tkip_key_info Tx; + struct rt_tkip_key_info Rx; +}; + +/*************************************************************************** + * Channel and BBP related data structures + **************************************************************************/ +/* structure to tune BBP R66 (BBP TUNING) */ +struct rt_bbp_r66_tuning { + BOOLEAN bEnable; + u16 FalseCcaLowerThreshold; /* default 100 */ + u16 FalseCcaUpperThreshold; /* default 512 */ + u8 R66Delta; + u8 R66CurrentValue; + BOOLEAN R66LowerUpperSelect; /*Before LinkUp, Used LowerBound or UpperBound as R66 value. */ +}; + +/* structure to store channel TX power */ +struct rt_channel_tx_power { + u16 RemainingTimeForUse; /*unit: sec */ + u8 Channel; + char Power; + char Power2; + u8 MaxTxPwr; + u8 DfsReq; +}; + +/* structure to store 802.11j channel TX power */ +struct rt_channel_11j_tx_power { + u8 Channel; + u8 BW; /* BW_10 or BW_20 */ + char Power; + char Power2; + u16 RemainingTimeForUse; /*unit: sec */ +}; + +struct rt_soft_rx_ant_diversity { + u8 EvaluatePeriod; /* 0:not evalute status, 1: evaluate status, 2: switching status */ + u8 EvaluateStableCnt; + u8 Pair1PrimaryRxAnt; /* 0:Ant-E1, 1:Ant-E2 */ + u8 Pair1SecondaryRxAnt; /* 0:Ant-E1, 1:Ant-E2 */ + u8 Pair2PrimaryRxAnt; /* 0:Ant-E3, 1:Ant-E4 */ + u8 Pair2SecondaryRxAnt; /* 0:Ant-E3, 1:Ant-E4 */ + short Pair1AvgRssi[2]; /* AvgRssi[0]:E1, AvgRssi[1]:E2 */ + short Pair2AvgRssi[2]; /* AvgRssi[0]:E3, AvgRssi[1]:E4 */ + short Pair1LastAvgRssi; /* */ + short Pair2LastAvgRssi; /* */ + unsigned long RcvPktNumWhenEvaluate; + BOOLEAN FirstPktArrivedWhenEvaluate; + struct rt_ralink_timer RxAntDiversityTimer; +}; + +/*************************************************************************** + * structure for radar detection and channel switch + **************************************************************************/ +struct rt_radar_detect { + /*BOOLEAN IEEE80211H; // 0: disable, 1: enable IEEE802.11h */ + u8 CSCount; /*Channel switch counter */ + u8 CSPeriod; /*Channel switch period (beacon count) */ + u8 RDCount; /*Radar detection counter */ + u8 RDMode; /*Radar Detection mode */ + u8 RDDurRegion; /*Radar detection duration region */ + u8 BBPR16; + u8 BBPR17; + u8 BBPR18; + u8 BBPR21; + u8 BBPR22; + u8 BBPR64; + unsigned long InServiceMonitorCount; /* unit: sec */ + u8 DfsSessionTime; + BOOLEAN bFastDfs; + u8 ChMovingTime; + u8 LongPulseRadarTh; +}; typedef enum _ABGBAND_STATE_ { UNKNOWN_BAND, @@ -1439,4110 +861,2865 @@ typedef enum _ABGBAND_STATE_ { A_BAND, } ABGBAND_STATE; -typedef struct _MLME_STRUCT { - // STA state machines - STATE_MACHINE CntlMachine; - STATE_MACHINE AssocMachine; - STATE_MACHINE AuthMachine; - STATE_MACHINE AuthRspMachine; - STATE_MACHINE SyncMachine; - STATE_MACHINE WpaPskMachine; - STATE_MACHINE LeapMachine; - STATE_MACHINE AironetMachine; - STATE_MACHINE_FUNC AssocFunc[ASSOC_FUNC_SIZE]; - STATE_MACHINE_FUNC AuthFunc[AUTH_FUNC_SIZE]; - STATE_MACHINE_FUNC AuthRspFunc[AUTH_RSP_FUNC_SIZE]; - STATE_MACHINE_FUNC SyncFunc[SYNC_FUNC_SIZE]; - STATE_MACHINE_FUNC WpaPskFunc[WPA_PSK_FUNC_SIZE]; - STATE_MACHINE_FUNC AironetFunc[AIRONET_FUNC_SIZE]; - STATE_MACHINE_FUNC ActFunc[ACT_FUNC_SIZE]; - // Action - STATE_MACHINE ActMachine; - - ULONG ChannelQuality; // 0..100, Channel Quality Indication for Roaming - ULONG Now32; // latch the value of NdisGetSystemUpTime() - ULONG LastSendNULLpsmTime; - - BOOLEAN bRunning; - NDIS_SPIN_LOCK TaskLock; - MLME_QUEUE Queue; - - UINT ShiftReg; - - RALINK_TIMER_STRUCT PeriodicTimer; - RALINK_TIMER_STRUCT APSDPeriodicTimer; - RALINK_TIMER_STRUCT LinkDownTimer; - RALINK_TIMER_STRUCT LinkUpTimer; -#ifdef RT2860 - UCHAR bPsPollTimerRunning; - RALINK_TIMER_STRUCT PsPollTimer; - RALINK_TIMER_STRUCT RadioOnOffTimer; -#endif - ULONG PeriodicRound; - ULONG OneSecPeriodicRound; - - UCHAR RealRxPath; - BOOLEAN bLowThroughput; - BOOLEAN bEnableAutoAntennaCheck; - RALINK_TIMER_STRUCT RxAntEvalTimer; - -#ifdef RT2870 - UCHAR CaliBW40RfR24; - UCHAR CaliBW20RfR24; -#endif // RT2870 // -} MLME_STRUCT, *PMLME_STRUCT; - -// structure for radar detection and channel switch -typedef struct _RADAR_DETECT_STRUCT { - UCHAR CSCount; //Channel switch counter - UCHAR CSPeriod; //Channel switch period (beacon count) - UCHAR RDCount; //Radar detection counter - UCHAR RDMode; //Radar Detection mode - UCHAR RDDurRegion; //Radar detection duration region - UCHAR BBPR16; - UCHAR BBPR17; - UCHAR BBPR18; - UCHAR BBPR21; - UCHAR BBPR22; - UCHAR BBPR64; - ULONG InServiceMonitorCount; // unit: sec - UINT8 DfsSessionTime; - BOOLEAN bFastDfs; - UINT8 ChMovingTime; - UINT8 LongPulseRadarTh; -} RADAR_DETECT_STRUCT, *PRADAR_DETECT_STRUCT; - -typedef enum _REC_BLOCKACK_STATUS -{ - Recipient_NONE=0, +#ifdef RTMP_MAC_PCI +/* Power save method control */ +typedef union _PS_CONTROL { + struct { + unsigned long EnablePSinIdle:1; /* Enable radio off when not connect to AP. radio on only when sitesurvey, */ + unsigned long EnableNewPS:1; /* Enable new Chip power save fucntion . New method can only be applied in chip version after 2872. and PCIe. */ + unsigned long rt30xxPowerMode:2; /* Power Level Mode for rt30xx chip */ + unsigned long rt30xxFollowHostASPM:1; /* Card Follows Host's setting for rt30xx chip. */ + unsigned long rt30xxForceASPMTest:1; /* Force enable L1 for rt30xx chip. This has higher priority than rt30xxFollowHostASPM Mode. */ + unsigned long rsv:26; /* Radio Measurement Enable */ + } field; + unsigned long word; +} PS_CONTROL, *PPS_CONTROL; +#endif /* RTMP_MAC_PCI // */ + +/*************************************************************************** + * structure for MLME state machine + **************************************************************************/ +struct rt_mlme { + /* STA state machines */ + struct rt_state_machine CntlMachine; + struct rt_state_machine AssocMachine; + struct rt_state_machine AuthMachine; + struct rt_state_machine AuthRspMachine; + struct rt_state_machine SyncMachine; + struct rt_state_machine WpaPskMachine; + struct rt_state_machine LeapMachine; + STATE_MACHINE_FUNC AssocFunc[ASSOC_FUNC_SIZE]; + STATE_MACHINE_FUNC AuthFunc[AUTH_FUNC_SIZE]; + STATE_MACHINE_FUNC AuthRspFunc[AUTH_RSP_FUNC_SIZE]; + STATE_MACHINE_FUNC SyncFunc[SYNC_FUNC_SIZE]; + STATE_MACHINE_FUNC ActFunc[ACT_FUNC_SIZE]; + /* Action */ + struct rt_state_machine ActMachine; + + /* common WPA state machine */ + struct rt_state_machine WpaMachine; + STATE_MACHINE_FUNC WpaFunc[WPA_FUNC_SIZE]; + + unsigned long ChannelQuality; /* 0..100, Channel Quality Indication for Roaming */ + unsigned long Now32; /* latch the value of NdisGetSystemUpTime() */ + unsigned long LastSendNULLpsmTime; + + BOOLEAN bRunning; + spinlock_t TaskLock; + struct rt_mlme_queue Queue; + + u32 ShiftReg; + + struct rt_ralink_timer PeriodicTimer; + struct rt_ralink_timer APSDPeriodicTimer; + struct rt_ralink_timer LinkDownTimer; + struct rt_ralink_timer LinkUpTimer; +#ifdef RTMP_MAC_PCI + u8 bPsPollTimerRunning; + struct rt_ralink_timer PsPollTimer; + struct rt_ralink_timer RadioOnOffTimer; +#endif /* RTMP_MAC_PCI // */ + unsigned long PeriodicRound; + unsigned long OneSecPeriodicRound; + + u8 RealRxPath; + BOOLEAN bLowThroughput; + BOOLEAN bEnableAutoAntennaCheck; + struct rt_ralink_timer RxAntEvalTimer; + +#ifdef RT30xx + u8 CaliBW40RfR24; + u8 CaliBW20RfR24; +#endif /* RT30xx // */ + +#ifdef RTMP_MAC_USB + struct rt_ralink_timer AutoWakeupTimer; + BOOLEAN AutoWakeupTimerRunning; +#endif /* RTMP_MAC_USB // */ +}; + +/*************************************************************************** + * 802.11 N related data structures + **************************************************************************/ +struct reordering_mpdu { + struct reordering_mpdu *next; + void *pPacket; /* coverted to 802.3 frame */ + int Sequence; /* sequence number of MPDU */ + BOOLEAN bAMSDU; +}; + +struct reordering_list { + struct reordering_mpdu *next; + int qlen; +}; + +struct reordering_mpdu_pool { + void *mem; + spinlock_t lock; + struct reordering_list freelist; +}; + +typedef enum _REC_BLOCKACK_STATUS { + Recipient_NONE = 0, Recipient_USED, Recipient_HandleRes, - Recipient_Accept + Recipient_Accept } REC_BLOCKACK_STATUS, *PREC_BLOCKACK_STATUS; -typedef enum _ORI_BLOCKACK_STATUS -{ - Originator_NONE=0, - Originator_USED, - Originator_WaitRes, - Originator_Done -} ORI_BLOCKACK_STATUS, *PORI_BLOCKACK_STATUS; +typedef enum _ORI_BLOCKACK_STATUS { + Originator_NONE = 0, + Originator_USED, + Originator_WaitRes, + Originator_Done +} ORI_BLOCKACK_STATUS, *PORI_BLOCKACK_STATUS; + +struct rt_ba_ori_entry { + u8 Wcid; + u8 TID; + u8 BAWinSize; + u8 Token; +/* Sequence is to fill every outgoing QoS DATA frame's sequence field in 802.11 header. */ + u16 Sequence; + u16 TimeOutValue; + ORI_BLOCKACK_STATUS ORI_BA_Status; + struct rt_ralink_timer ORIBATimer; + void *pAdapter; +}; + +struct rt_ba_rec_entry { + u8 Wcid; + u8 TID; + u8 BAWinSize; /* 7.3.1.14. each buffer is capable of holding a max AMSDU or MSDU. */ + /*u8 NumOfRxPkt; */ + /*u8 Curindidx; // the head in the RX reordering buffer */ + u16 LastIndSeq; +/* u16 LastIndSeqAtTimer; */ + u16 TimeOutValue; + struct rt_ralink_timer RECBATimer; + unsigned long LastIndSeqAtTimer; + unsigned long nDropPacket; + unsigned long rcvSeq; + REC_BLOCKACK_STATUS REC_BA_Status; +/* u8 RxBufIdxUsed; */ + /* corresponding virtual address for RX reordering packet storage. */ + /*RTMP_REORDERDMABUF MAP_RXBuf[MAX_RX_REORDERBUF]; */ + spinlock_t RxReRingLock; /* Rx Ring spinlock */ +/* struct _BA_REC_ENTRY *pNext; */ + void *pAdapter; + struct reordering_list list; +}; + +struct rt_ba_table { + unsigned long numAsRecipient; /* I am recipient of numAsRecipient clients. These client are in the BARecEntry[] */ + unsigned long numAsOriginator; /* I am originator of numAsOriginator clients. These clients are in the BAOriEntry[] */ + unsigned long numDoneOriginator; /* count Done Originator sessions */ + struct rt_ba_ori_entry BAOriEntry[MAX_LEN_OF_BA_ORI_TABLE]; + struct rt_ba_rec_entry BARecEntry[MAX_LEN_OF_BA_REC_TABLE]; +}; + +/*For QureyBATableOID use; */ +struct PACKED rt_oid_ba_rec_entry { + u8 MACAddr[MAC_ADDR_LEN]; + u8 BaBitmap; /* if (BaBitmap&(1<MaxHTPhyMode.field.MODE >= MODE_HTMIX) + +#define IS_HT_RATE(_pMacEntry) \ + (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) + +#define PEER_IS_HT_RATE(_pMacEntry) \ + (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) + +/*This structure is for all 802.11n card InterOptibilityTest action. Reset all Num every n second. (Details see MLMEPeriodic) */ +struct rt_iot { + u8 Threshold[2]; + u8 ReorderTimeOutNum[MAX_LEN_OF_BA_REC_TABLE]; /* compare with threshold[0] */ + u8 RefreshNum[MAX_LEN_OF_BA_REC_TABLE]; /* compare with threshold[1] */ + unsigned long OneSecInWindowCount; + unsigned long OneSecFrameDuplicateCount; + unsigned long OneSecOutWindowCount; + u8 DelOriAct; + u8 DelRecAct; + u8 RTSShortProt; + u8 RTSLongProt; + BOOLEAN bRTSLongProtOn; + BOOLEAN bLastAtheros; + BOOLEAN bCurrentAtheros; + BOOLEAN bNowAtherosBurstOn; + BOOLEAN bNextDisableRxBA; + BOOLEAN bToggle; +}; + +/* This is the registry setting for 802.11n transmit setting. Used in advanced page. */ +typedef union _REG_TRANSMIT_SETTING { + struct { + /*u32 PhyMode:4; */ + /*u32 MCS:7; // MCS */ + u32 rsv0:10; + u32 TxBF:1; + u32 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + u32 ShortGI:1; + u32 STBC:1; /*SPACE */ + u32 TRANSNO:2; + u32 HTMODE:1; + u32 EXTCHA:2; + u32 rsv:13; + } field; + u32 word; +} REG_TRANSMIT_SETTING, *PREG_TRANSMIT_SETTING; + +typedef union _DESIRED_TRANSMIT_SETTING { + struct { + u16 MCS:7; /* MCS */ + u16 PhyMode:4; + u16 FixedTxMode:2; /* If MCS isn't AUTO, fix rate in CCK, OFDM or HT mode. */ + u16 rsv:3; + } field; + u16 word; +} DESIRED_TRANSMIT_SETTING, *PDESIRED_TRANSMIT_SETTING; + +#ifdef RTMP_MAC_USB +/*************************************************************************** + * USB-based chip Beacon related data structures + **************************************************************************/ +#define BEACON_BITMAP_MASK 0xff +struct rt_beacon_sync { + u8 BeaconBuf[HW_BEACON_MAX_COUNT][HW_BEACON_OFFSET]; + u8 BeaconTxWI[HW_BEACON_MAX_COUNT][TXWI_SIZE]; + unsigned long TimIELocationInBeacon[HW_BEACON_MAX_COUNT]; + unsigned long CapabilityInfoLocationInBeacon[HW_BEACON_MAX_COUNT]; + BOOLEAN EnableBeacon; /* trigger to enable beacon transmission. */ + u8 BeaconBitMap; /* NOTE: If the MAX_MBSSID_NUM is larger than 8, this parameter need to change. */ + u8 DtimBitOn; /* NOTE: If the MAX_MBSSID_NUM is larger than 8, this parameter need to change. */ +}; +#endif /* RTMP_MAC_USB // */ + +/*************************************************************************** + * Multiple SSID related data structures + **************************************************************************/ +#define WLAN_MAX_NUM_OF_TIM ((MAX_LEN_OF_MAC_TABLE >> 3) + 1) /* /8 + 1 */ +#define WLAN_CT_TIM_BCMC_OFFSET 0 /* unit: 32B */ + +/* clear bcmc TIM bit */ +#define WLAN_MR_TIM_BCMC_CLEAR(apidx) \ + pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] &= ~BIT8[0]; + +/* set bcmc TIM bit */ +#define WLAN_MR_TIM_BCMC_SET(apidx) \ + pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] |= BIT8[0]; + +/* clear a station PS TIM bit */ +#define WLAN_MR_TIM_BIT_CLEAR(ad_p, apidx, wcid) \ + { u8 tim_offset = wcid >> 3; \ + u8 bit_offset = wcid & 0x7; \ + ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] &= (~BIT8[bit_offset]); } + +/* set a station PS TIM bit */ +#define WLAN_MR_TIM_BIT_SET(ad_p, apidx, wcid) \ + { u8 tim_offset = wcid >> 3; \ + u8 bit_offset = wcid & 0x7; \ + ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] |= BIT8[bit_offset]; } + +/* configuration common to OPMODE_AP as well as OPMODE_STA */ +struct rt_common_config { + + BOOLEAN bCountryFlag; + u8 CountryCode[3]; + u8 Geography; + u8 CountryRegion; /* Enum of country region, 0:FCC, 1:IC, 2:ETSI, 3:SPAIN, 4:France, 5:MKK, 6:MKK1, 7:Israel */ + u8 CountryRegionForABand; /* Enum of country region for A band */ + u8 PhyMode; /* PHY_11A, PHY_11B, PHY_11BG_MIXED, PHY_ABG_MIXED */ + u16 Dsifs; /* in units of usec */ + unsigned long PacketFilter; /* Packet filter for receiving */ + u8 RegulatoryClass; + + char Ssid[MAX_LEN_OF_SSID]; /* NOT NULL-terminated */ + u8 SsidLen; /* the actual ssid length in used */ + u8 LastSsidLen; /* the actual ssid length in used */ + char LastSsid[MAX_LEN_OF_SSID]; /* NOT NULL-terminated */ + u8 LastBssid[MAC_ADDR_LEN]; + + u8 Bssid[MAC_ADDR_LEN]; + u16 BeaconPeriod; + u8 Channel; + u8 CentralChannel; /* Central Channel when using 40MHz is indicating. not real channel. */ + + u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + u8 SupRateLen; + u8 ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + u8 ExtRateLen; + u8 DesireRate[MAX_LEN_OF_SUPPORTED_RATES]; /* OID_802_11_DESIRED_RATES */ + u8 MaxDesiredRate; + u8 ExpectedACKRate[MAX_LEN_OF_SUPPORTED_RATES]; + + unsigned long BasicRateBitmap; /* backup basic ratebitmap */ + + BOOLEAN bAPSDCapable; + BOOLEAN bInServicePeriod; + BOOLEAN bAPSDAC_BE; + BOOLEAN bAPSDAC_BK; + BOOLEAN bAPSDAC_VI; + BOOLEAN bAPSDAC_VO; + + /* because TSPEC can modify the APSD flag, we need to keep the APSD flag + requested in association stage from the station; + we need to recover the APSD flag after the TSPEC is deleted. */ + BOOLEAN bACMAPSDBackup[4]; /* for delivery-enabled & trigger-enabled both */ + BOOLEAN bACMAPSDTr[4]; /* no use */ + + BOOLEAN bNeedSendTriggerFrame; + BOOLEAN bAPSDForcePowerSave; /* Force power save mode, should only use in APSD-STAUT */ + unsigned long TriggerTimerCount; + u8 MaxSPLength; + u8 BBPCurrentBW; /* BW_10, BW_20, BW_40 */ + /* move to MULTISSID_STRUCT for MBSS */ + /*HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. */ + REG_TRANSMIT_SETTING RegTransmitSetting; /*registry transmit setting. this is for reading registry setting only. not useful. */ + /*u8 FixedTxMode; // Fixed Tx Mode (CCK, OFDM), for HT fixed tx mode (GF, MIX) , refer to RegTransmitSetting.field.HTMode */ + u8 TxRate; /* Same value to fill in TXD. TxRate is 6-bit */ + u8 MaxTxRate; /* RATE_1, RATE_2, RATE_5_5, RATE_11 */ + u8 TxRateIndex; /* Tx rate index in RateSwitchTable */ + u8 TxRateTableSize; /* Valid Tx rate table size in RateSwitchTable */ + /*BOOLEAN bAutoTxRateSwitch; */ + u8 MinTxRate; /* RATE_1, RATE_2, RATE_5_5, RATE_11 */ + u8 RtsRate; /* RATE_xxx */ + HTTRANSMIT_SETTING MlmeTransmit; /* MGMT frame PHY rate setting when operatin at Ht rate. */ + u8 MlmeRate; /* RATE_xxx, used to send MLME frames */ + u8 BasicMlmeRate; /* Default Rate for sending MLME frames */ + + u16 RtsThreshold; /* in unit of BYTE */ + u16 FragmentThreshold; /* in unit of BYTE */ + + u8 TxPower; /* in unit of mW */ + unsigned long TxPowerPercentage; /* 0~100 % */ + unsigned long TxPowerDefault; /* keep for TxPowerPercentage */ + u8 PwrConstraint; + + BACAP_STRUC BACapability; /* NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0 */ + BACAP_STRUC REGBACapability; /* NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0 */ + + struct rt_iot IOTestParm; /* 802.11n InterOpbility Test Parameter; */ + unsigned long TxPreamble; /* Rt802_11PreambleLong, Rt802_11PreambleShort, Rt802_11PreambleAuto */ + BOOLEAN bUseZeroToDisableFragment; /* Microsoft use 0 as disable */ + unsigned long UseBGProtection; /* 0: auto, 1: always use, 2: always not use */ + BOOLEAN bUseShortSlotTime; /* 0: disable, 1 - use short slot (9us) */ + BOOLEAN bEnableTxBurst; /* 1: enble TX PACKET BURST (when BA is established or AP is not a legacy WMM AP), 0: disable TX PACKET BURST */ + BOOLEAN bAggregationCapable; /* 1: enable TX aggregation when the peer supports it */ + BOOLEAN bPiggyBackCapable; /* 1: enable TX piggy-back according MAC's version */ + BOOLEAN bIEEE80211H; /* 1: enable IEEE802.11h spec. */ + unsigned long DisableOLBCDetect; /* 0: enable OLBC detect; 1 disable OLBC detect */ + + BOOLEAN bRdg; + + BOOLEAN bWmmCapable; /* 0:disable WMM, 1:enable WMM */ + struct rt_qos_capability_parm APQosCapability; /* QOS capability of the current associated AP */ + struct rt_edca_parm APEdcaParm; /* EDCA parameters of the current associated AP */ + struct rt_qbss_load_parm APQbssLoad; /* QBSS load of the current associated AP */ + u8 AckPolicy[4]; /* ACK policy of the specified AC. see ACK_xxx */ + BOOLEAN bDLSCapable; /* 0:disable DLS, 1:enable DLS */ + /* a bitmap of BOOLEAN flags. each bit represent an operation status of a particular */ + /* BOOLEAN control, either ON or OFF. These flags should always be accessed via */ + /* OPSTATUS_TEST_FLAG(), OPSTATUS_SET_FLAG(), OP_STATUS_CLEAR_FLAG() macros. */ + /* see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition */ + unsigned long OpStatusFlags; + + BOOLEAN NdisRadioStateOff; /*For HCT 12.0, set this flag to TRUE instead of called MlmeRadioOff. */ + ABGBAND_STATE BandState; /* For setting BBP used on B/G or A mode. */ + + /* IEEE802.11H--DFS. */ + struct rt_radar_detect RadarDetect; + + /* HT */ + u8 BASize; /* USer desired BAWindowSize. Should not exceed our max capability */ + /*struct rt_ht_capability SupportedHtPhy; */ + struct rt_ht_capability DesiredHtPhy; + struct rt_ht_capability_ie HtCapability; + struct rt_add_ht_info_ie AddHTInfo; /* Useful as AP. */ + /*This IE is used with channel switch announcement element when changing to a new 40MHz. */ + /*This IE is included in channel switch ammouncement frames 7.4.1.5, beacons, probe Rsp. */ + struct rt_new_ext_chan_ie NewExtChanOffset; /*7.3.2.20A, 1 if extension channel is above the control channel, 3 if below, 0 if not present */ + + BOOLEAN bHTProtect; + BOOLEAN bMIMOPSEnable; + BOOLEAN bBADecline; +/*2008/11/05: KH add to support Antenna power-saving of AP<-- */ + BOOLEAN bGreenAPEnable; +/*2008/11/05: KH add to support Antenna power-saving of AP--> */ + BOOLEAN bDisableReordering; + BOOLEAN bForty_Mhz_Intolerant; + BOOLEAN bExtChannelSwitchAnnouncement; + BOOLEAN bRcvBSSWidthTriggerEvents; + unsigned long LastRcvBSSWidthTriggerEventsTime; + + u8 TxBASize; + + /* Enable wireless event */ + BOOLEAN bWirelessEvent; + BOOLEAN bWiFiTest; /* Enable this parameter for WiFi test */ + + /* Tx & Rx Stream number selection */ + u8 TxStream; + u8 RxStream; + + BOOLEAN bHardwareRadio; /* Hardware controlled Radio enabled */ + +#ifdef RTMP_MAC_USB + BOOLEAN bMultipleIRP; /* Multiple Bulk IN flag */ + u8 NumOfBulkInIRP; /* if bMultipleIRP == TRUE, NumOfBulkInIRP will be 4 otherwise be 1 */ + struct rt_ht_capability SupportedHtPhy; + unsigned long MaxPktOneTxBulk; + u8 TxBulkFactor; + u8 RxBulkFactor; + + BOOLEAN IsUpdateBeacon; + struct rt_beacon_sync *pBeaconSync; + struct rt_ralink_timer BeaconUpdateTimer; + u32 BeaconAdjust; + u32 BeaconFactor; + u32 BeaconRemain; +#endif /* RTMP_MAC_USB // */ + + spinlock_t MeasureReqTabLock; + struct rt_measure_req_tab *pMeasureReqTab; + + spinlock_t TpcReqTabLock; + struct rt_tpc_req_tab *pTpcReqTab; + + BOOLEAN PSPXlink; /* 0: Disable. 1: Enable */ + +#if defined(RT305x)||defined(RT30xx) + /* request by Gary, for High Power issue */ + u8 HighPowerPatchDisabled; +#endif + + BOOLEAN HT_DisallowTKIP; /* Restrict the encryption type in 11n HT mode */ +}; + +/* Modified by Wu Xi-Kun 4/21/2006 */ +/* STA configuration and status */ +struct rt_sta_admin_config { + /* GROUP 1 - */ + /* User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe */ + /* the user intended configuration, but not necessary fully equal to the final */ + /* settings in ACTIVE BSS after negotiation/compromize with the BSS holder (either */ + /* AP or IBSS holder). */ + /* Once initialized, user configuration can only be changed via OID_xxx */ + u8 BssType; /* BSS_INFRA or BSS_ADHOC */ + u16 AtimWin; /* used when starting a new IBSS */ + + /* GROUP 2 - */ + /* User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe */ + /* the user intended configuration, and should be always applied to the final */ + /* settings in ACTIVE BSS without compromising with the BSS holder. */ + /* Once initialized, user configuration can only be changed via OID_xxx */ + u8 RssiTrigger; + u8 RssiTriggerMode; /* RSSI_TRIGGERED_UPON_BELOW_THRESHOLD or RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD */ + u16 DefaultListenCount; /* default listen count; */ + unsigned long WindowsPowerMode; /* Power mode for AC power */ + unsigned long WindowsBatteryPowerMode; /* Power mode for battery if exists */ + BOOLEAN bWindowsACCAMEnable; /* Enable CAM power mode when AC on */ + BOOLEAN bAutoReconnect; /* Set to TRUE when setting OID_802_11_SSID with no matching BSSID */ + unsigned long WindowsPowerProfile; /* Windows power profile, for NDIS5.1 PnP */ + + /* MIB:ieee802dot11.dot11smt(1).dot11StationConfigTable(1) */ + u16 Psm; /* power management mode (PWR_ACTIVE|PWR_SAVE) */ + u16 DisassocReason; + u8 DisassocSta[MAC_ADDR_LEN]; + u16 DeauthReason; + u8 DeauthSta[MAC_ADDR_LEN]; + u16 AuthFailReason; + u8 AuthFailSta[MAC_ADDR_LEN]; + + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; /* PrivacyFilter enum for 802.1X */ + NDIS_802_11_AUTHENTICATION_MODE AuthMode; /* This should match to whatever microsoft defined */ + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_WEP_STATUS OrigWepStatus; /* Original wep status set from OID */ + + /* Add to support different cipher suite for WPA2/WPA mode */ + NDIS_802_11_ENCRYPTION_STATUS GroupCipher; /* Multicast cipher suite */ + NDIS_802_11_ENCRYPTION_STATUS PairCipher; /* Unicast cipher suite */ + BOOLEAN bMixCipher; /* Indicate current Pair & Group use different cipher suites */ + u16 RsnCapability; + + NDIS_802_11_WEP_STATUS GroupKeyWepStatus; + + u8 WpaPassPhrase[64]; /* WPA PSK pass phrase */ + u32 WpaPassPhraseLen; /* the length of WPA PSK pass phrase */ + u8 PMK[32]; /* WPA PSK mode PMK */ + u8 PTK[64]; /* WPA PSK mode PTK */ + u8 GTK[32]; /* GTK from authenticator */ + struct rt_bssid_info SavedPMK[PMKID_NO]; + u32 SavedPMKNum; /* Saved PMKID number */ + + u8 DefaultKeyId; + + /* WPA 802.1x port control, WPA_802_1X_PORT_SECURED, WPA_802_1X_PORT_NOT_SECURED */ + u8 PortSecured; + + /* For WPA countermeasures */ + unsigned long LastMicErrorTime; /* record last MIC error time */ + unsigned long MicErrCnt; /* Should be 0, 1, 2, then reset to zero (after disassoiciation). */ + BOOLEAN bBlockAssoc; /* Block associate attempt for 60 seconds after counter measure occurred. */ + /* For WPA-PSK supplicant state */ + WPA_STATE WpaState; /* Default is SS_NOTUSE and handled by microsoft 802.1x */ + u8 ReplayCounter[8]; + u8 ANonce[32]; /* ANonce for WPA-PSK from aurhenticator */ + u8 SNonce[32]; /* SNonce for WPA-PSK */ + + u8 LastSNR0; /* last received BEACON's SNR */ + u8 LastSNR1; /* last received BEACON's SNR for 2nd antenna */ + struct rt_rssi_sample RssiSample; + unsigned long NumOfAvgRssiSample; + + unsigned long LastBeaconRxTime; /* OS's timestamp of the last BEACON RX time */ + unsigned long Last11bBeaconRxTime; /* OS's timestamp of the last 11B BEACON RX time */ + unsigned long Last11gBeaconRxTime; /* OS's timestamp of the last 11G BEACON RX time */ + unsigned long Last20NBeaconRxTime; /* OS's timestamp of the last 20MHz N BEACON RX time */ + + unsigned long LastScanTime; /* Record last scan time for issue BSSID_SCAN_LIST */ + unsigned long ScanCnt; /* Scan counts since most recent SSID, BSSID, SCAN OID request */ + BOOLEAN bSwRadio; /* Software controlled Radio On/Off, TRUE: On */ + BOOLEAN bHwRadio; /* Hardware controlled Radio On/Off, TRUE: On */ + BOOLEAN bRadio; /* Radio state, And of Sw & Hw radio state */ + BOOLEAN bHardwareRadio; /* Hardware controlled Radio enabled */ + BOOLEAN bShowHiddenSSID; /* Show all known SSID in SSID list get operation */ + + /* New for WPA, windows want us to keep association information and */ + /* Fixed IEs from last association response */ + struct rt_ndis_802_11_association_information AssocInfo; + u16 ReqVarIELen; /* Length of next VIE include EID & Length */ + u8 ReqVarIEs[MAX_VIE_LEN]; /* The content saved here should be little-endian format. */ + u16 ResVarIELen; /* Length of next VIE include EID & Length */ + u8 ResVarIEs[MAX_VIE_LEN]; + + u8 RSNIE_Len; + u8 RSN_IE[MAX_LEN_OF_RSNIE]; /* The content saved here should be little-endian format. */ + + unsigned long CLBusyBytes; /* Save the total bytes received durning channel load scan time */ + u16 RPIDensity[8]; /* Array for RPI density collection */ + + u8 RMReqCnt; /* Number of measurement request saved. */ + u8 CurrentRMReqIdx; /* Number of measurement request saved. */ + BOOLEAN ParallelReq; /* Parallel measurement, only one request performed, */ + /* It must be the same channel with maximum duration */ + u16 ParallelDuration; /* Maximum duration for parallel measurement */ + u8 ParallelChannel; /* Only one channel with parallel measurement */ + u16 IAPPToken; /* IAPP dialog token */ + /* Hack for channel load and noise histogram parameters */ + u8 NHFactor; /* Parameter for Noise histogram */ + u8 CLFactor; /* Parameter for channel load */ + + struct rt_ralink_timer StaQuickResponeForRateUpTimer; + BOOLEAN StaQuickResponeForRateUpTimerRunning; + + u8 DtimCount; /* 0.. DtimPeriod-1 */ + u8 DtimPeriod; /* default = 3 */ + + /*////////////////////////////////////////////////////////////////////////////////////// */ + /* This is only for WHQL test. */ + BOOLEAN WhqlTest; + /*////////////////////////////////////////////////////////////////////////////////////// */ + + struct rt_ralink_timer WpaDisassocAndBlockAssocTimer; + /* Fast Roaming */ + BOOLEAN bAutoRoaming; /* 0:disable auto roaming by RSSI, 1:enable auto roaming by RSSI */ + char dBmToRoam; /* the condition to roam when receiving Rssi less than this value. It's negative value. */ + + BOOLEAN IEEE8021X; + BOOLEAN IEEE8021x_required_keys; + struct rt_cipher_key DesireSharedKey[4]; /* Record user desired WEP keys */ + u8 DesireSharedKeyId; + + /* 0: driver ignores wpa_supplicant */ + /* 1: wpa_supplicant initiates scanning and AP selection */ + /* 2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters */ + u8 WpaSupplicantUP; + u8 WpaSupplicantScanCount; + BOOLEAN bRSN_IE_FromWpaSupplicant; + + char dev_name[16]; + u16 OriDevType; + + BOOLEAN bTGnWifiTest; + BOOLEAN bScanReqIsFromWebUI; + + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; /* For transmit phy setting in TXWI. */ + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; + struct rt_ht_phy_info DesiredHtPhyInfo; + BOOLEAN bAutoTxRateSwitch; + +#ifdef RTMP_MAC_PCI + u8 BBPR3; + /* PS Control has 2 meanings for advanced power save function. */ + /* 1. EnablePSinIdle : When no connection, always radio off except need to do site survey. */ + /* 2. EnableNewPS : will save more current in sleep or radio off mode. */ + PS_CONTROL PSControl; +#endif /* RTMP_MAC_PCI // */ + + BOOLEAN bAutoConnectByBssid; + unsigned long BeaconLostTime; /* seconds */ + BOOLEAN bForceTxBurst; /* 1: force enble TX PACKET BURST, 0: disable */ +}; + +/* This data structure keep the current active BSS/IBSS's configuration that this STA */ +/* had agreed upon joining the network. Which means these parameters are usually decided */ +/* by the BSS/IBSS creator instead of user configuration. Data in this data structurre */ +/* is valid only when either ADHOC_ON(pAd) or INFRA_ON(pAd) is TRUE. */ +/* Normally, after SCAN or failed roaming attempts, we need to recover back to */ +/* the current active settings. */ +struct rt_sta_active_config { + u16 Aid; + u16 AtimWin; /* in kusec; IBSS parameter set element */ + u16 CapabilityInfo; + u16 CfpMaxDuration; + u16 CfpPeriod; + + /* Copy supported rate from desired AP's beacon. We are trying to match */ + /* AP's supported and extended rate settings. */ + u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + u8 ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + u8 SupRateLen; + u8 ExtRateLen; + /* Copy supported ht from desired AP's beacon. We are trying to match */ + struct rt_ht_phy_info SupportedPhyInfo; + struct rt_ht_capability SupportedHtPhy; +}; + +struct rt_mac_table_entry; + +struct rt_mac_table_entry { + /*Choose 1 from ValidAsWDS and ValidAsCLI to validize. */ + BOOLEAN ValidAsCLI; /* Sta mode, set this TRUE after Linkup,too. */ + BOOLEAN ValidAsWDS; /* This is WDS Entry. only for AP mode. */ + BOOLEAN ValidAsApCli; /*This is a AP-Client entry, only for AP mode which enable AP-Client functions. */ + BOOLEAN ValidAsMesh; + BOOLEAN ValidAsDls; /* This is DLS Entry. only for STA mode. */ + BOOLEAN isCached; + BOOLEAN bIAmBadAtheros; /* Flag if this is Atheros chip that has IOT problem. We need to turn on RTS/CTS protection. */ + + u8 EnqueueEapolStartTimerRunning; /* Enqueue EAPoL-Start for triggering EAP SM */ + /*jan for wpa */ + /* record which entry revoke MIC Failure , if it leaves the BSS itself, AP won't update aMICFailTime MIB */ + u8 CMTimerRunning; + u8 apidx; /* MBSS number */ + u8 RSNIE_Len; + u8 RSN_IE[MAX_LEN_OF_RSNIE]; + u8 ANonce[LEN_KEY_DESC_NONCE]; + u8 SNonce[LEN_KEY_DESC_NONCE]; + u8 R_Counter[LEN_KEY_DESC_REPLAY]; + u8 PTK[64]; + u8 ReTryCounter; + struct rt_ralink_timer RetryTimer; + struct rt_ralink_timer EnqueueStartForPSKTimer; /* A timer which enqueue EAPoL-Start for triggering PSK SM */ + NDIS_802_11_AUTHENTICATION_MODE AuthMode; /* This should match to whatever microsoft defined */ + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_WEP_STATUS GroupKeyWepStatus; + AP_WPA_STATE WpaState; + GTK_STATE GTKState; + u16 PortSecured; + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; /* PrivacyFilter enum for 802.1X */ + struct rt_cipher_key PairwiseKey; + void *pAd; + int PMKID_CacheIdx; + u8 PMKID[LEN_PMKID]; + + u8 Addr[MAC_ADDR_LEN]; + u8 PsMode; + SST Sst; + AUTH_STATE AuthState; /* for SHARED KEY authentication state machine used only */ + BOOLEAN IsReassocSta; /* Indicate whether this is a reassociation procedure */ + u16 Aid; + u16 CapabilityInfo; + u8 LastRssi; + unsigned long NoDataIdleCount; + u16 StationKeepAliveCount; /* unit: second */ + unsigned long PsQIdleCount; + struct rt_queue_header PsQueue; + + u32 StaConnectTime; /* the live time of this station since associated with AP */ + + BOOLEAN bSendBAR; + u16 NoBADataCountDown; + + u32 CachedBuf[16]; /* u32 (4 bytes) for alignment */ + u32 TxBFCount; /* 3*3 */ + u32 FIFOCount; + u32 DebugFIFOCount; + u32 DebugTxCount; + BOOLEAN bDlsInit; + +/*==================================================== */ +/*WDS entry needs these */ +/* if ValidAsWDS==TRUE, MatchWDSTabIdx is the index in WdsTab.MacTab */ + u32 MatchWDSTabIdx; + u8 MaxSupportedRate; + u8 CurrTxRate; + u8 CurrTxRateIndex; + /* to record the each TX rate's quality. 0 is best, the bigger the worse. */ + u16 TxQuality[MAX_STEP_OF_TX_RATE_SWITCH]; +/* u16 OneSecTxOkCount; */ + u32 OneSecTxNoRetryOkCount; + u32 OneSecTxRetryOkCount; + u32 OneSecTxFailCount; + u32 ContinueTxFailCnt; + u32 CurrTxRateStableTime; /* # of second in current TX rate */ + u8 TxRateUpPenalty; /* extra # of second penalty due to last unstable condition */ +/*==================================================== */ + + BOOLEAN fNoisyEnvironment; + BOOLEAN fLastSecAccordingRSSI; + u8 LastSecTxRateChangeAction; /* 0: no change, 1:rate UP, 2:rate down */ + char LastTimeTxRateChangeAction; /*Keep last time value of LastSecTxRateChangeAction */ + unsigned long LastTxOkCount; + u8 PER[MAX_STEP_OF_TX_RATE_SWITCH]; + + /* a bitmap of BOOLEAN flags. each bit represent an operation status of a particular */ + /* BOOLEAN control, either ON or OFF. These flags should always be accessed via */ + /* CLIENT_STATUS_TEST_FLAG(), CLIENT_STATUS_SET_FLAG(), CLIENT_STATUS_CLEAR_FLAG() macros. */ + /* see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition. fCLIENT_STATUS_AMSDU_INUSED */ + unsigned long ClientStatusFlags; + + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; /* For transmit phy setting in TXWI. */ + + /* HT EWC MIMO-N used parameters */ + u16 RXBAbitmap; /* fill to on-chip RXWI_BA_BITMASK in 8.1.3RX attribute entry format */ + u16 TXBAbitmap; /* This bitmap as originator, only keep in software used to mark AMPDU bit in TXWI */ + u16 TXAutoBAbitmap; + u16 BADeclineBitmap; + u16 BARecWcidArray[NUM_OF_TID]; /* The mapping wcid of recipient session. if RXBAbitmap bit is masked */ + u16 BAOriWcidArray[NUM_OF_TID]; /* The mapping wcid of originator session. if TXBAbitmap bit is masked */ + u16 BAOriSequence[NUM_OF_TID]; /* The mapping wcid of originator session. if TXBAbitmap bit is masked */ + + /* 802.11n features. */ + u8 MpduDensity; + u8 MaxRAmpduFactor; + u8 AMsduSize; + u8 MmpsMode; /* MIMO power save more. */ + + struct rt_ht_capability_ie HTCapability; + + BOOLEAN bAutoTxRateSwitch; + + u8 RateLen; + struct rt_mac_table_entry *pNext; + u16 TxSeq[NUM_OF_TID]; + u16 NonQosDataSeq; + + struct rt_rssi_sample RssiSample; + + u32 TXMCSExpected[16]; + u32 TXMCSSuccessful[16]; + u32 TXMCSFailed[16]; + u32 TXMCSAutoFallBack[16][16]; + + unsigned long LastBeaconRxTime; + + unsigned long AssocDeadLine; +}; + +struct rt_mac_table { + u16 Size; + struct rt_mac_table_entry *Hash[HASH_TABLE_SIZE]; + struct rt_mac_table_entry Content[MAX_LEN_OF_MAC_TABLE]; + struct rt_queue_header McastPsQueue; + unsigned long PsQIdleCount; + BOOLEAN fAnyStationInPsm; + BOOLEAN fAnyStationBadAtheros; /* Check if any Station is atheros 802.11n Chip. We need to use RTS/CTS with Atheros 802,.11n chip. */ + BOOLEAN fAnyTxOPForceDisable; /* Check if it is necessary to disable BE TxOP */ + BOOLEAN fAllStationAsRalink; /* Check if all stations are ralink-chipset */ + BOOLEAN fAnyStationIsLegacy; /* Check if I use legacy rate to transmit to my BSS Station/ */ + BOOLEAN fAnyStationNonGF; /* Check if any Station can't support GF. */ + BOOLEAN fAnyStation20Only; /* Check if any Station can't support GF. */ + BOOLEAN fAnyStationMIMOPSDynamic; /* Check if any Station is MIMO Dynamic */ + BOOLEAN fAnyBASession; /* Check if there is BA session. Force turn on RTS/CTS */ +/*2008/10/28: KH add to support Antenna power-saving of AP<-- */ +/*2008/10/28: KH add to support Antenna power-saving of AP--> */ +}; + +struct wificonf { + BOOLEAN bShortGI; + BOOLEAN bGreenField; +}; + +struct rt_rtmp_dev_info { + u8 chipName[16]; + RTMP_INF_TYPE infType; +}; + +struct rt_rtmp_chip_op { + /* Calibration access related callback functions */ + int (*eeinit) (struct rt_rtmp_adapter *pAd); /* int (*eeinit)(struct rt_rtmp_adapter *pAd); */ + int (*eeread) (struct rt_rtmp_adapter *pAd, u16 offset, u16 *pValue); /* int (*eeread)(struct rt_rtmp_adapter *pAd, int offset, u16 *pValue); */ + + /* MCU related callback functions */ + int (*loadFirmware) (struct rt_rtmp_adapter *pAd); /* int (*loadFirmware)(struct rt_rtmp_adapter *pAd); */ + int (*eraseFirmware) (struct rt_rtmp_adapter *pAd); /* int (*eraseFirmware)(struct rt_rtmp_adapter *pAd); */ + int (*sendCommandToMcu) (struct rt_rtmp_adapter *pAd, u8 cmd, u8 token, u8 arg0, u8 arg1);; /* int (*sendCommandToMcu)(struct rt_rtmp_adapter *pAd, u8 cmd, u8 token, u8 arg0, u8 arg1); */ + + /* RF access related callback functions */ + struct rt_reg_pair *pRFRegTable; + void (*AsicRfInit) (struct rt_rtmp_adapter *pAd); + void (*AsicRfTurnOn) (struct rt_rtmp_adapter *pAd); + void (*AsicRfTurnOff) (struct rt_rtmp_adapter *pAd); + void (*AsicReverseRfFromSleepMode) (struct rt_rtmp_adapter *pAd); + void (*AsicHaltAction) (struct rt_rtmp_adapter *pAd); +}; + +/* */ +/* The miniport adapter structure */ +/* */ +struct rt_rtmp_adapter { + void *OS_Cookie; /* save specific structure relative to OS */ + struct net_device *net_dev; + unsigned long VirtualIfCnt; + + struct rt_rtmp_chip_op chipOps; + u16 ThisTbttNumToNextWakeUp; + +#ifdef RTMP_MAC_PCI +/*****************************************************************************************/ +/* PCI related parameters */ +/*****************************************************************************************/ + u8 *CSRBaseAddress; /* PCI MMIO Base Address, all access will use */ + unsigned int irq_num; + + u16 LnkCtrlBitMask; + u16 RLnkCtrlConfiguration; + u16 RLnkCtrlOffset; + u16 HostLnkCtrlConfiguration; + u16 HostLnkCtrlOffset; + u16 PCIePowerSaveLevel; + unsigned long Rt3xxHostLinkCtrl; /* USed for 3090F chip */ + unsigned long Rt3xxRalinkLinkCtrl; /* USed for 3090F chip */ + u16 DeviceID; /* Read from PCI config */ + unsigned long AccessBBPFailCount; + BOOLEAN bPCIclkOff; /* flag that indicate if the PICE power status in Configuration SPace.. */ + BOOLEAN bPCIclkOffDisableTx; /* */ + + BOOLEAN brt30xxBanMcuCmd; /*when = 0xff means all commands are ok to set . */ + BOOLEAN b3090ESpecialChip; /*3090E special chip that write EEPROM 0x24=0x9280. */ + unsigned long CheckDmaBusyCount; /* Check Interrupt Status Register Count. */ + + u32 int_enable_reg; + u32 int_disable_mask; + u32 int_pending; + + struct rt_rtmp_dmabuf TxBufSpace[NUM_OF_TX_RING]; /* Shared memory of all 1st pre-allocated TxBuf associated with each TXD */ + struct rt_rtmp_dmabuf RxDescRing; /* Shared memory for RX descriptors */ + struct rt_rtmp_dmabuf TxDescRing[NUM_OF_TX_RING]; /* Shared memory for Tx descriptors */ + struct rt_rtmp_tx_ring TxRing[NUM_OF_TX_RING]; /* AC0~4 + HCCA */ +#endif /* RTMP_MAC_PCI // */ + + spinlock_t irq_lock; + u8 irq_disabled; + +#ifdef RTMP_MAC_USB +/*****************************************************************************************/ +/* USB related parameters */ +/*****************************************************************************************/ + struct usb_config_descriptor *config; + u32 BulkInEpAddr; /* bulk-in endpoint address */ + u32 BulkOutEpAddr[6]; /* bulk-out endpoint address */ + + u32 NumberOfPipes; + u16 BulkOutMaxPacketSize; + u16 BulkInMaxPacketSize; + + /*======Control Flags */ + long PendingIoCount; + unsigned long BulkFlags; + BOOLEAN bUsbTxBulkAggre; /* Flags for bulk out data priority */ + + /*======Cmd Thread */ + struct rt_cmdq CmdQ; + spinlock_t CmdQLock; /* CmdQLock spinlock */ + struct rt_rtmp_os_task cmdQTask; + + /*======Semaphores (event) */ + struct semaphore UsbVendorReq_semaphore; + void *UsbVendorReqBuf; + wait_queue_head_t *wait; +#endif /* RTMP_MAC_USB // */ + +/*****************************************************************************************/ +/* RBUS related parameters */ +/*****************************************************************************************/ + +/*****************************************************************************************/ +/* Both PCI/USB related parameters */ +/*****************************************************************************************/ + /*struct rt_rtmp_dev_info chipInfo; */ + RTMP_INF_TYPE infType; + +/*****************************************************************************************/ +/* Driver Mgmt related parameters */ +/*****************************************************************************************/ + struct rt_rtmp_os_task mlmeTask; +#ifdef RTMP_TIMER_TASK_SUPPORT + /* If you want use timer task to handle the timer related jobs, enable this. */ + struct rt_rtmp_timer_task_queue TimerQ; + spinlock_t TimerQLock; + struct rt_rtmp_os_task timerTask; +#endif /* RTMP_TIMER_TASK_SUPPORT // */ + +/*****************************************************************************************/ +/* Tx related parameters */ +/*****************************************************************************************/ + BOOLEAN DeQueueRunning[NUM_OF_TX_RING]; /* for ensuring RTUSBDeQueuePacket get call once */ + spinlock_t DeQueueLock[NUM_OF_TX_RING]; + +#ifdef RTMP_MAC_USB + /* Data related context and AC specified, 4 AC supported */ + spinlock_t BulkOutLock[6]; /* BulkOut spinlock for 4 ACs */ + spinlock_t MLMEBulkOutLock; /* MLME BulkOut lock */ + + struct rt_ht_tx_context TxContext[NUM_OF_TX_RING]; + spinlock_t TxContextQueueLock[NUM_OF_TX_RING]; /* TxContextQueue spinlock */ + + /* 4 sets of Bulk Out index and pending flag */ + u8 NextBulkOutIndex[4]; /* only used for 4 EDCA bulkout pipe */ + + BOOLEAN BulkOutPending[6]; /* used for total 6 bulkout pipe */ + u8 bulkResetPipeid; + BOOLEAN MgmtBulkPending; + unsigned long bulkResetReq[6]; +#endif /* RTMP_MAC_USB // */ + + /* resource for software backlog queues */ + struct rt_queue_header TxSwQueue[NUM_OF_TX_RING]; /* 4 AC + 1 HCCA */ + spinlock_t TxSwQueueLock[NUM_OF_TX_RING]; /* TxSwQueue spinlock */ + + struct rt_rtmp_dmabuf MgmtDescRing; /* Shared memory for MGMT descriptors */ + struct rt_rtmp_mgmt_ring MgmtRing; + spinlock_t MgmtRingLock; /* Prio Ring spinlock */ + +/*****************************************************************************************/ +/* Rx related parameters */ +/*****************************************************************************************/ + +#ifdef RTMP_MAC_PCI + struct rt_rtmp_rx_ring RxRing; + spinlock_t RxRingLock; /* Rx Ring spinlock */ +#ifdef RT3090 + spinlock_t McuCmdLock; /*MCU Command Queue spinlock */ +#endif /* RT3090 // */ +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + struct rt_rx_context RxContext[RX_RING_SIZE]; /* 1 for redundant multiple IRP bulk in. */ + spinlock_t BulkInLock; /* BulkIn spinlock for 4 ACs */ + u8 PendingRx; /* The Maximum pending Rx value should be RX_RING_SIZE. */ + u8 NextRxBulkInIndex; /* Indicate the current RxContext Index which hold by Host controller. */ + u8 NextRxBulkInReadIndex; /* Indicate the current RxContext Index which driver can read & process it. */ + unsigned long NextRxBulkInPosition; /* Want to contatenate 2 URB buffer while 1st is bulkin failed URB. This Position is 1st URB TransferLength. */ + unsigned long TransferBufferLength; /* current length of the packet buffer */ + unsigned long ReadPosition; /* current read position in a packet buffer */ +#endif /* RTMP_MAC_USB // */ + +/*****************************************************************************************/ +/* ASIC related parameters */ +/*****************************************************************************************/ + u32 MACVersion; /* MAC version. Record rt2860C(0x28600100) or rt2860D (0x28600101).. */ + + /* --------------------------- */ + /* E2PROM */ + /* --------------------------- */ + unsigned long EepromVersion; /* byte 0: version, byte 1: revision, byte 2~3: unused */ + unsigned long FirmwareVersion; /* byte 0: Minor version, byte 1: Major version, otherwise unused. */ + u16 EEPROMDefaultValue[NUM_EEPROM_BBP_PARMS]; + u8 EEPROMAddressNum; /* 93c46=6 93c66=8 */ + BOOLEAN EepromAccess; + u8 EFuseTag; + + /* --------------------------- */ + /* BBP Control */ + /* --------------------------- */ + u8 BbpWriteLatch[140]; /* record last BBP register value written via BBP_IO_WRITE/BBP_IO_WRITE_VY_REG_ID */ + char BbpRssiToDbmDelta; /* change from u8 to char for high power */ + struct rt_bbp_r66_tuning BbpTuning; + + /* ---------------------------- */ + /* RFIC control */ + /* ---------------------------- */ + u8 RfIcType; /* RFIC_xxx */ + unsigned long RfFreqOffset; /* Frequency offset for channel switching */ + struct rt_rtmp_rf_regs LatchRfRegs; /* latch th latest RF programming value since RF IC doesn't support READ */ + + EEPROM_ANTENNA_STRUC Antenna; /* Since ANtenna definition is different for a & g. We need to save it for future reference. */ + EEPROM_NIC_CONFIG2_STRUC NicConfig2; + + /* This soft Rx Antenna Diversity mechanism is used only when user set */ + /* RX Antenna = DIVERSITY ON */ + struct rt_soft_rx_ant_diversity RxAnt; + + u8 RFProgSeq; + struct rt_channel_tx_power TxPower[MAX_NUM_OF_CHANNELS]; /* Store Tx power value for all channels. */ + struct rt_channel_tx_power ChannelList[MAX_NUM_OF_CHANNELS]; /* list all supported channels for site survey */ + struct rt_channel_11j_tx_power TxPower11J[MAX_NUM_OF_11JCHANNELS]; /* 802.11j channel and bw */ + struct rt_channel_11j_tx_power ChannelList11J[MAX_NUM_OF_11JCHANNELS]; /* list all supported channels for site survey */ + + u8 ChannelListNum; /* number of channel in ChannelList[] */ + u8 Bbp94; + BOOLEAN BbpForCCK; + unsigned long Tx20MPwrCfgABand[5]; + unsigned long Tx20MPwrCfgGBand[5]; + unsigned long Tx40MPwrCfgABand[5]; + unsigned long Tx40MPwrCfgGBand[5]; + + BOOLEAN bAutoTxAgcA; /* Enable driver auto Tx Agc control */ + u8 TssiRefA; /* Store Tssi reference value as 25 temperature. */ + u8 TssiPlusBoundaryA[5]; /* Tssi boundary for increase Tx power to compensate. */ + u8 TssiMinusBoundaryA[5]; /* Tssi boundary for decrease Tx power to compensate. */ + u8 TxAgcStepA; /* Store Tx TSSI delta increment / decrement value */ + char TxAgcCompensateA; /* Store the compensation (TxAgcStep * (idx-1)) */ + + BOOLEAN bAutoTxAgcG; /* Enable driver auto Tx Agc control */ + u8 TssiRefG; /* Store Tssi reference value as 25 temperature. */ + u8 TssiPlusBoundaryG[5]; /* Tssi boundary for increase Tx power to compensate. */ + u8 TssiMinusBoundaryG[5]; /* Tssi boundary for decrease Tx power to compensate. */ + u8 TxAgcStepG; /* Store Tx TSSI delta increment / decrement value */ + char TxAgcCompensateG; /* Store the compensation (TxAgcStep * (idx-1)) */ + + char BGRssiOffset0; /* Store B/G RSSI#0 Offset value on EEPROM 0x46h */ + char BGRssiOffset1; /* Store B/G RSSI#1 Offset value */ + char BGRssiOffset2; /* Store B/G RSSI#2 Offset value */ + + char ARssiOffset0; /* Store A RSSI#0 Offset value on EEPROM 0x4Ah */ + char ARssiOffset1; /* Store A RSSI#1 Offset value */ + char ARssiOffset2; /* Store A RSSI#2 Offset value */ + + char BLNAGain; /* Store B/G external LNA#0 value on EEPROM 0x44h */ + char ALNAGain0; /* Store A external LNA#0 value for ch36~64 */ + char ALNAGain1; /* Store A external LNA#1 value for ch100~128 */ + char ALNAGain2; /* Store A external LNA#2 value for ch132~165 */ +#ifdef RT30xx + /* for 3572 */ + u8 Bbp25; + u8 Bbp26; + + u8 TxMixerGain24G; /* Tx mixer gain value from EEPROM to improve Tx EVM / Tx DAC, 2.4G */ + u8 TxMixerGain5G; +#endif /* RT30xx // */ + /* ---------------------------- */ + /* LED control */ + /* ---------------------------- */ + MCU_LEDCS_STRUC LedCntl; + u16 Led1; /* read from EEPROM 0x3c */ + u16 Led2; /* EEPROM 0x3e */ + u16 Led3; /* EEPROM 0x40 */ + u8 LedIndicatorStrength; + u8 RssiSingalstrengthOffet; + BOOLEAN bLedOnScanning; + u8 LedStatus; + +/*****************************************************************************************/ +/* 802.11 related parameters */ +/*****************************************************************************************/ + /* outgoing BEACON frame buffer and corresponding TXD */ + struct rt_txwi BeaconTxWI; + u8 *BeaconBuf; + u16 BeaconOffset[HW_BEACON_MAX_COUNT]; + + /* pre-build PS-POLL and NULL frame upon link up. for efficiency purpose. */ + struct rt_pspoll_frame PsPollFrame; + struct rt_header_802_11 NullFrame; + +#ifdef RTMP_MAC_USB + struct rt_tx_context BeaconContext[BEACON_RING_SIZE]; + struct rt_tx_context NullContext; + struct rt_tx_context PsPollContext; + struct rt_tx_context RTSContext; +#endif /* RTMP_MAC_USB // */ + +/*=========AP=========== */ + +/*=======STA=========== */ + /* ----------------------------------------------- */ + /* STA specific configuration & operation status */ + /* used only when pAd->OpMode == OPMODE_STA */ + /* ----------------------------------------------- */ + struct rt_sta_admin_config StaCfg; /* user desired settings */ + struct rt_sta_active_config StaActive; /* valid only when ADHOC_ON(pAd) || INFRA_ON(pAd) */ + char nickname[IW_ESSID_MAX_SIZE + 1]; /* nickname, only used in the iwconfig i/f */ + int PreMediaState; + +/*=======Common=========== */ + /* OP mode: either AP or STA */ + u8 OpMode; /* OPMODE_STA, OPMODE_AP */ + + int IndicateMediaState; /* Base on Indication state, default is NdisMediaStateDisConnected */ + + /* MAT related parameters */ + + /* configuration: read from Registry & E2PROM */ + BOOLEAN bLocalAdminMAC; /* Use user changed MAC */ + u8 PermanentAddress[MAC_ADDR_LEN]; /* Factory default MAC address */ + u8 CurrentAddress[MAC_ADDR_LEN]; /* User changed MAC address */ + + /* ------------------------------------------------------ */ + /* common configuration to both OPMODE_STA and OPMODE_AP */ + /* ------------------------------------------------------ */ + struct rt_common_config CommonCfg; + struct rt_mlme Mlme; + + /* AP needs those vaiables for site survey feature. */ + struct rt_mlme_aux MlmeAux; /* temporary settings used during MLME state machine */ + struct rt_bss_table ScanTab; /* store the latest SCAN result */ + + /*About MacTab, the sta driver will use #0 and #1 for multicast and AP. */ + struct rt_mac_table MacTab; /* ASIC on-chip WCID entry table. At TX, ASIC always use key according to this on-chip table. */ + spinlock_t MacTabLock; + + struct rt_ba_table BATable; + + spinlock_t BATabLock; + struct rt_ralink_timer RECBATimer; + + /* encryption/decryption KEY tables */ + struct rt_cipher_key SharedKey[MAX_MBSSID_NUM][4]; /* STA always use SharedKey[BSS0][0..3] */ + + /* RX re-assembly buffer for fragmentation */ + struct rt_fragment_frame FragFrame; /* Frame storage for fragment frame */ + + /* various Counters */ + struct rt_counter_802_3 Counters8023; /* 802.3 counters */ + struct rt_counter_802_11 WlanCounters; /* 802.11 MIB counters */ + struct rt_counter_ralink RalinkCounters; /* Ralink propriety counters */ + struct rt_counter_drs DrsCounters; /* counters for Dynamic TX Rate Switching */ + struct rt_private PrivateInfo; /* Private information & counters */ + + /* flags, see fRTMP_ADAPTER_xxx flags */ + unsigned long Flags; /* Represent current device status */ + unsigned long PSFlags; /* Power Save operation flag. */ + + /* current TX sequence # */ + u16 Sequence; + + /* Control disconnect / connect event generation */ + /*+++Didn't used anymore */ + unsigned long LinkDownTime; + /*--- */ + unsigned long LastRxRate; + unsigned long LastTxRate; + /*+++Used only for Station */ + BOOLEAN bConfigChanged; /* Config Change flag for the same SSID setting */ + /*--- */ + + unsigned long ExtraInfo; /* Extra information for displaying status */ + unsigned long SystemErrorBitmap; /* b0: E2PROM version error */ + + /*+++Didn't used anymore */ + unsigned long MacIcVersion; /* MAC/BBP serial interface issue solved after ver.D */ + /*--- */ + + /* --------------------------- */ + /* System event log */ + /* --------------------------- */ + struct rt_802_11_event_table EventTab; + + BOOLEAN HTCEnable; + + /*****************************************************************************************/ + /* Statistic related parameters */ + /*****************************************************************************************/ +#ifdef RTMP_MAC_USB + unsigned long BulkOutDataOneSecCount; + unsigned long BulkInDataOneSecCount; + unsigned long BulkLastOneSecCount; /* BulkOutDataOneSecCount + BulkInDataOneSecCount */ + unsigned long watchDogRxCnt; + unsigned long watchDogRxOverFlowCnt; + unsigned long watchDogTxPendingCnt[NUM_OF_TX_RING]; + int TransferedLength[NUM_OF_TX_RING]; +#endif /* RTMP_MAC_USB // */ + + BOOLEAN bUpdateBcnCntDone; + unsigned long watchDogMacDeadlock; /* prevent MAC/BBP into deadlock condition */ + /* ---------------------------- */ + /* DEBUG paramerts */ + /* ---------------------------- */ + /*unsigned long DebugSetting[4]; */ + BOOLEAN bBanAllBaSetup; + BOOLEAN bPromiscuous; + + /* ---------------------------- */ + /* rt2860c emulation-use Parameters */ + /* ---------------------------- */ + /*unsigned long rtsaccu[30]; */ + /*unsigned long ctsaccu[30]; */ + /*unsigned long cfendaccu[30]; */ + /*unsigned long bacontent[16]; */ + /*unsigned long rxint[RX_RING_SIZE+1]; */ + /*u8 rcvba[60]; */ + BOOLEAN bLinkAdapt; + BOOLEAN bForcePrintTX; + BOOLEAN bForcePrintRX; + /*BOOLEAN bDisablescanning; //defined in RT2870 USB */ + BOOLEAN bStaFifoTest; + BOOLEAN bProtectionTest; + BOOLEAN bBroadComHT; + /*+++Following add from RT2870 USB. */ + unsigned long BulkOutReq; + unsigned long BulkOutComplete; + unsigned long BulkOutCompleteOther; + unsigned long BulkOutCompleteCancel; /* seems not use now? */ + unsigned long BulkInReq; + unsigned long BulkInComplete; + unsigned long BulkInCompleteFail; + /*--- */ + + struct wificonf WIFItestbed; + + struct reordering_mpdu_pool mpdu_blk_pool; + + unsigned long OneSecondnonBEpackets; /* record non BE packets per second */ + +#ifdef LINUX + struct iw_statistics iw_stats; + + struct net_device_stats stats; +#endif /* LINUX // */ + + unsigned long TbttTickCount; +#ifdef PCI_MSI_SUPPORT + BOOLEAN HaveMsi; +#endif /* PCI_MSI_SUPPORT // */ + + u8 is_on; + +#define TIME_BASE (1000000/OS_HZ) +#define TIME_ONE_SECOND (1000000/TIME_BASE) + u8 flg_be_adjust; + unsigned long be_adjust_last_time; + + u8 FlgCtsEnabled; + u8 PM_FlgSuspend; + +#ifdef RT30xx +#ifdef RTMP_EFUSE_SUPPORT + BOOLEAN bUseEfuse; + u8 EEPROMImage[1024]; +#endif /* RTMP_EFUSE_SUPPORT // */ +#endif /* RT30xx // */ +}; + +#define DELAYINTMASK 0x0003fffb +#define INTMASK 0x0003fffb +#define IndMask 0x0003fffc +#define RxINT 0x00000005 /* Delayed Rx or indivi rx */ +#define TxDataInt 0x000000fa /* Delayed Tx or indivi tx */ +#define TxMgmtInt 0x00000102 /* Delayed Tx or indivi tx */ +#define TxCoherent 0x00020000 /* tx coherent */ +#define RxCoherent 0x00010000 /* rx coherent */ +#define McuCommand 0x00000200 /* mcu */ +#define PreTBTTInt 0x00001000 /* Pre-TBTT interrupt */ +#define TBTTInt 0x00000800 /* TBTT interrupt */ +#define GPTimeOutInt 0x00008000 /* GPtimeout interrupt */ +#define AutoWakeupInt 0x00004000 /* AutoWakeupInt interrupt */ +#define FifoStaFullInt 0x00002000 /* fifo statistics full interrupt */ + +/*************************************************************************** + * Rx Path software control block related data structures + **************************************************************************/ +struct rt_rx_blk { + RT28XX_RXD_STRUC RxD; + struct rt_rxwi * pRxWI; + struct rt_header_802_11 * pHeader; + void *pRxPacket; + u8 *pData; + u16 DataSize; + u16 Flags; + u8 UserPriority; /* for calculate TKIP MIC using */ +}; + +#define RX_BLK_SET_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags |= _flag) +#define RX_BLK_TEST_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags & _flag) +#define RX_BLK_CLEAR_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags &= ~(_flag)) + +#define fRX_WDS 0x0001 +#define fRX_AMSDU 0x0002 +#define fRX_ARALINK 0x0004 +#define fRX_HTC 0x0008 +#define fRX_PAD 0x0010 +#define fRX_AMPDU 0x0020 +#define fRX_QOS 0x0040 +#define fRX_INFRA 0x0080 +#define fRX_EAP 0x0100 +#define fRX_MESH 0x0200 +#define fRX_APCLI 0x0400 +#define fRX_DLS 0x0800 +#define fRX_WPI 0x1000 + +#define LENGTH_AMSDU_SUBFRAMEHEAD 14 +#define LENGTH_ARALINK_SUBFRAMEHEAD 14 +#define LENGTH_ARALINK_HEADER_FIELD 2 + +/*************************************************************************** + * Tx Path software control block related data structures + **************************************************************************/ +#define TX_UNKOWN_FRAME 0x00 +#define TX_MCAST_FRAME 0x01 +#define TX_LEGACY_FRAME 0x02 +#define TX_AMPDU_FRAME 0x04 +#define TX_AMSDU_FRAME 0x08 +#define TX_RALINK_FRAME 0x10 +#define TX_FRAG_FRAME 0x20 + +/* Currently the sizeof(struct rt_tx_blk) is 148 bytes. */ +struct rt_tx_blk { + u8 QueIdx; + u8 TxFrameType; /* Indicate the Transmission type of the all frames in one batch */ + u8 TotalFrameNum; /* Total frame number want to send-out in one batch */ + u16 TotalFragNum; /* Total frame fragments required in one batch */ + u16 TotalFrameLen; /* Total length of all frames want to send-out in one batch */ + + struct rt_queue_header TxPacketList; + struct rt_mac_table_entry *pMacEntry; /* NULL: packet with 802.11 RA field is multicast/broadcast address */ + HTTRANSMIT_SETTING *pTransmit; + + /* Following structure used for the characteristics of a specific packet. */ + void *pPacket; + u8 *pSrcBufHeader; /* Reference to the head of sk_buff->data */ + u8 *pSrcBufData; /* Reference to the sk_buff->data, will changed depends on hanlding progresss */ + u32 SrcBufLen; /* Length of packet payload which not including Layer 2 header */ + u8 *pExtraLlcSnapEncap; /* NULL means no extra LLC/SNAP is required */ + u8 HeaderBuf[128]; /* TempBuffer for TX_INFO + TX_WI + 802.11 Header + padding + AMSDU SubHeader + LLC/SNAP */ + /*RT2870 2.1.0.0 uses only 80 bytes */ + /*RT3070 2.1.1.0 uses only 96 bytes */ + /*RT3090 2.1.0.0 uses only 96 bytes */ + u8 MpduHeaderLen; /* 802.11 header length NOT including the padding */ + u8 HdrPadLen; /* recording Header Padding Length; */ + u8 apidx; /* The interface associated to this packet */ + u8 Wcid; /* The MAC entry associated to this packet */ + u8 UserPriority; /* priority class of packet */ + u8 FrameGap; /* what kind of IFS this packet use */ + u8 MpduReqNum; /* number of fragments of this frame */ + u8 TxRate; /* TODO: Obsoleted? Should change to MCS? */ + u8 CipherAlg; /* cipher alogrithm */ + struct rt_cipher_key *pKey; + + u16 Flags; /*See following definitions for detail. */ + + /*YOU SHOULD NOT TOUCH IT! Following parameters are used for hardware-depended layer. */ + unsigned long Priv; /* Hardware specific value saved in here. */ +}; + +#define fTX_bRtsRequired 0x0001 /* Indicate if need send RTS frame for protection. Not used in RT2860/RT2870. */ +#define fTX_bAckRequired 0x0002 /* the packet need ack response */ +#define fTX_bPiggyBack 0x0004 /* Legacy device use Piggback or not */ +#define fTX_bHTRate 0x0008 /* allow to use HT rate */ +#define fTX_bForceNonQoS 0x0010 /* force to transmit frame without WMM-QoS in HT mode */ +#define fTX_bAllowFrag 0x0020 /* allow to fragment the packet, A-MPDU, A-MSDU, A-Ralink is not allowed to fragment */ +#define fTX_bMoreData 0x0040 /* there are more data packets in PowerSave Queue */ +#define fTX_bWMM 0x0080 /* QOS Data */ +#define fTX_bClearEAPFrame 0x0100 + +#define TX_BLK_SET_FLAG(_pTxBlk, _flag) (_pTxBlk->Flags |= _flag) +#define TX_BLK_TEST_FLAG(_pTxBlk, _flag) (((_pTxBlk->Flags & _flag) == _flag) ? 1 : 0) +#define TX_BLK_CLEAR_FLAG(_pTxBlk, _flag) (_pTxBlk->Flags &= ~(_flag)) + +/*************************************************************************** + * Other static inline function definitions + **************************************************************************/ +static inline void ConvertMulticastIP2MAC(u8 *pIpAddr, + u8 ** ppMacAddr, + u16 ProtoType) +{ + if (pIpAddr == NULL) + return; + + if (ppMacAddr == NULL || *ppMacAddr == NULL) + return; + + switch (ProtoType) { + case ETH_P_IPV6: +/* memset(*ppMacAddr, 0, ETH_LENGTH_OF_ADDRESS); */ + *(*ppMacAddr) = 0x33; + *(*ppMacAddr + 1) = 0x33; + *(*ppMacAddr + 2) = pIpAddr[12]; + *(*ppMacAddr + 3) = pIpAddr[13]; + *(*ppMacAddr + 4) = pIpAddr[14]; + *(*ppMacAddr + 5) = pIpAddr[15]; + break; + + case ETH_P_IP: + default: +/* memset(*ppMacAddr, 0, ETH_LENGTH_OF_ADDRESS); */ + *(*ppMacAddr) = 0x01; + *(*ppMacAddr + 1) = 0x00; + *(*ppMacAddr + 2) = 0x5e; + *(*ppMacAddr + 3) = pIpAddr[1] & 0x7f; + *(*ppMacAddr + 4) = pIpAddr[2]; + *(*ppMacAddr + 5) = pIpAddr[3]; + break; + } + + return; +} + +char *GetPhyMode(int Mode); +char *GetBW(int BW); + +/* */ +/* Private routines in rtmp_init.c */ +/* */ +int RTMPAllocAdapterBlock(void *handle, + struct rt_rtmp_adapter * * ppAdapter); + +int RTMPAllocTxRxRingMemory(struct rt_rtmp_adapter *pAd); + +void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd); + +int NICReadRegParameters(struct rt_rtmp_adapter *pAd, + void *WrapperConfigurationContext); + +#ifdef RTMP_RF_RW_SUPPORT +void NICInitRFRegisters(struct rt_rtmp_adapter *pAd); + +void RtmpChipOpsRFHook(struct rt_rtmp_adapter *pAd); + +int RT30xxWriteRFRegister(struct rt_rtmp_adapter *pAd, + u8 regID, u8 value); + +int RT30xxReadRFRegister(struct rt_rtmp_adapter *pAd, + u8 regID, u8 *pValue); +#endif /* RTMP_RF_RW_SUPPORT // */ + +void NICReadEEPROMParameters(struct rt_rtmp_adapter *pAd, u8 *mac_addr); + +void NICInitAsicFromEEPROM(struct rt_rtmp_adapter *pAd); + +int NICInitializeAdapter(struct rt_rtmp_adapter *pAd, IN BOOLEAN bHardReset); + +int NICInitializeAsic(struct rt_rtmp_adapter *pAd, IN BOOLEAN bHardReset); + +void NICIssueReset(struct rt_rtmp_adapter *pAd); + +void RTMPRingCleanUp(struct rt_rtmp_adapter *pAd, u8 RingType); + +void UserCfgInit(struct rt_rtmp_adapter *pAd); + +void NICResetFromError(struct rt_rtmp_adapter *pAd); + +int NICLoadFirmware(struct rt_rtmp_adapter *pAd); + +void NICEraseFirmware(struct rt_rtmp_adapter *pAd); + +int NICLoadRateSwitchingParams(struct rt_rtmp_adapter *pAd); + +BOOLEAN NICCheckForHang(struct rt_rtmp_adapter *pAd); + +void NICUpdateFifoStaCounters(struct rt_rtmp_adapter *pAd); + +void NICUpdateRawCounters(struct rt_rtmp_adapter *pAd); + +void RTMPZeroMemory(void *pSrc, unsigned long Length); + +unsigned long RTMPCompareMemory(void *pSrc1, void *pSrc2, unsigned long Length); + +void RTMPMoveMemory(void *pDest, void *pSrc, unsigned long Length); + +void AtoH(char *src, u8 *dest, int destlen); + +u8 BtoH(char ch); + +void RTMPPatchMacBbpBug(struct rt_rtmp_adapter *pAd); + +void RTMPInitTimer(struct rt_rtmp_adapter *pAd, + struct rt_ralink_timer *pTimer, + void *pTimerFunc, void *pData, IN BOOLEAN Repeat); + +void RTMPSetTimer(struct rt_ralink_timer *pTimer, unsigned long Value); + +void RTMPModTimer(struct rt_ralink_timer *pTimer, unsigned long Value); + +void RTMPCancelTimer(struct rt_ralink_timer *pTimer, OUT BOOLEAN * pCancelled); + +void RTMPSetLED(struct rt_rtmp_adapter *pAd, u8 Status); + +void RTMPSetSignalLED(struct rt_rtmp_adapter *pAd, IN NDIS_802_11_RSSI Dbm); + +void RTMPEnableRxTx(struct rt_rtmp_adapter *pAd); + +/* */ +/* prototype in action.c */ +/* */ +void ActionStateMachineInit(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *S, + OUT STATE_MACHINE_FUNC Trans[]); + +void MlmeADDBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void MlmeDELBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void MlmeDLSAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void MlmeInvalidAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void MlmeQOSAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void PeerAddBAReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void PeerAddBARspAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void PeerDelBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void PeerBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void SendPSMPAction(struct rt_rtmp_adapter *pAd, u8 Wcid, u8 Psmp); + +void PeerRMAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void PeerPublicAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void PeerHTAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void PeerQOSAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void RECBATimerTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); + +void ORIBATimerTimeout(struct rt_rtmp_adapter *pAd); + +void SendRefreshBAR(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry); + +void ActHeaderInit(struct rt_rtmp_adapter *pAd, + struct rt_header_802_11 * pHdr80211, + u8 *Addr1, u8 *Addr2, u8 *Addr3); + +void BarHeaderInit(struct rt_rtmp_adapter *pAd, + struct rt_frame_bar * pCntlBar, u8 *pDA, u8 *pSA); + +void InsertActField(struct rt_rtmp_adapter *pAd, + u8 *pFrameBuf, + unsigned long *pFrameLen, u8 Category, u8 ActCode); + +BOOLEAN CntlEnqueueForRecv(struct rt_rtmp_adapter *pAd, + unsigned long Wcid, + unsigned long MsgLen, struct rt_frame_ba_req * pMsg); + +/* */ +/* Private routines in rtmp_data.c */ +/* */ +BOOLEAN RTMPHandleRxDoneInterrupt(struct rt_rtmp_adapter *pAd); + +BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(struct rt_rtmp_adapter *pAd, + INT_SOURCE_CSR_STRUC TxRingBitmap); + +void RTMPHandleMgmtRingDmaDoneInterrupt(struct rt_rtmp_adapter *pAd); + +void RTMPHandleTBTTInterrupt(struct rt_rtmp_adapter *pAd); + +void RTMPHandlePreTBTTInterrupt(struct rt_rtmp_adapter *pAd); + +void RTMPHandleTwakeupInterrupt(struct rt_rtmp_adapter *pAd); + +void RTMPHandleRxCoherentInterrupt(struct rt_rtmp_adapter *pAd); + +BOOLEAN TxFrameIsAggregatible(struct rt_rtmp_adapter *pAd, + u8 *pPrevAddr1, u8 *p8023hdr); + +BOOLEAN PeerIsAggreOn(struct rt_rtmp_adapter *pAd, + unsigned long TxRate, struct rt_mac_table_entry *pMacEntry); + +int Sniff2BytesFromNdisBuffer(char *pFirstBuffer, + u8 DesiredOffset, + u8 *pByte0, u8 *pByte1); + +int STASendPacket(struct rt_rtmp_adapter *pAd, void *pPacket); + +void STASendPackets(void *MiniportAdapterContext, + void **ppPacketArray, u32 NumberOfPackets); + +void RTMPDeQueuePacket(struct rt_rtmp_adapter *pAd, + IN BOOLEAN bIntContext, + u8 QueIdx, u8 Max_Tx_Packets); + +int RTMPHardTransmit(struct rt_rtmp_adapter *pAd, + void *pPacket, + u8 QueIdx, unsigned long *pFreeTXDLeft); + +int STAHardTransmit(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, u8 QueIdx); + +void STARxEAPOLFrameIndicate(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID); + +int RTMPFreeTXDRequest(struct rt_rtmp_adapter *pAd, + u8 RingType, + u8 NumberRequired, u8 *FreeNumberIs); + +int MlmeHardTransmit(struct rt_rtmp_adapter *pAd, + u8 QueIdx, void *pPacket); + +int MlmeHardTransmitMgmtRing(struct rt_rtmp_adapter *pAd, + u8 QueIdx, void *pPacket); + +#ifdef RTMP_MAC_PCI +int MlmeHardTransmitTxRing(struct rt_rtmp_adapter *pAd, + u8 QueIdx, void *pPacket); + +int MlmeDataHardTransmit(struct rt_rtmp_adapter *pAd, + u8 QueIdx, void *pPacket); + +void RTMPWriteTxDescriptor(struct rt_rtmp_adapter *pAd, + struct rt_txd * pTxD, IN BOOLEAN bWIV, u8 QSEL); +#endif /* RTMP_MAC_PCI // */ + +u16 RTMPCalcDuration(struct rt_rtmp_adapter *pAd, u8 Rate, unsigned long Size); + +void RTMPWriteTxWI(struct rt_rtmp_adapter *pAd, struct rt_txwi * pTxWI, IN BOOLEAN FRAG, IN BOOLEAN CFACK, IN BOOLEAN InsTimestamp, IN BOOLEAN AMPDU, IN BOOLEAN Ack, IN BOOLEAN NSeq, /* HW new a sequence. */ + u8 BASize, + u8 WCID, + unsigned long Length, + u8 PID, + u8 TID, + u8 TxRate, + u8 Txopmode, + IN BOOLEAN CfAck, IN HTTRANSMIT_SETTING * pTransmit); + +void RTMPWriteTxWI_Data(struct rt_rtmp_adapter *pAd, + struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk); + +void RTMPWriteTxWI_Cache(struct rt_rtmp_adapter *pAd, + struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk); + +void RTMPSuspendMsduTransmission(struct rt_rtmp_adapter *pAd); + +void RTMPResumeMsduTransmission(struct rt_rtmp_adapter *pAd); + +int MiniportMMRequest(struct rt_rtmp_adapter *pAd, + u8 QueIdx, u8 *pData, u32 Length); + +/*+++mark by shiang, now this function merge to MiniportMMRequest() */ +/*---mark by shiang, now this function merge to MiniportMMRequest() */ + +void RTMPSendNullFrame(struct rt_rtmp_adapter *pAd, + u8 TxRate, IN BOOLEAN bQosNull); + +void RTMPSendDisassociationFrame(struct rt_rtmp_adapter *pAd); + +void RTMPSendRTSFrame(struct rt_rtmp_adapter *pAd, + u8 *pDA, + IN unsigned int NextMpduSize, + u8 TxRate, + u8 RTSRate, + u16 AckDuration, + u8 QueIdx, u8 FrameGap); + +struct rt_queue_header *RTMPCheckTxSwQueue(struct rt_rtmp_adapter *pAd, u8 * QueIdx); + +void RTMPReportMicError(struct rt_rtmp_adapter *pAd, struct rt_cipher_key *pWpaKey); + +void WpaMicFailureReportFrame(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void WpaDisassocApAndBlockAssoc(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, + void *SystemSpecific3); + +void WpaStaPairwiseKeySetting(struct rt_rtmp_adapter *pAd); + +void WpaStaGroupKeySetting(struct rt_rtmp_adapter *pAd); + +int RTMPCloneNdisPacket(struct rt_rtmp_adapter *pAd, + IN BOOLEAN pInsAMSDUHdr, + void *pInPacket, + void ** ppOutPacket); + +int RTMPAllocateNdisPacket(struct rt_rtmp_adapter *pAd, + void ** pPacket, + u8 *pHeader, + u32 HeaderLen, + u8 *pData, u32 DataLen); + +void RTMPFreeNdisPacket(struct rt_rtmp_adapter *pAd, void *pPacket); + +BOOLEAN RTMPFreeTXDUponTxDmaDone(struct rt_rtmp_adapter *pAd, u8 QueIdx); + +BOOLEAN RTMPCheckDHCPFrame(struct rt_rtmp_adapter *pAd, void *pPacket); + +BOOLEAN RTMPCheckEtherType(struct rt_rtmp_adapter *pAd, void *pPacket); + +/* */ +/* Private routines in rtmp_wep.c */ +/* */ +void RTMPInitWepEngine(struct rt_rtmp_adapter *pAd, + u8 *pKey, + u8 KeyId, u8 KeyLen, u8 *pDest); + +void RTMPEncryptData(struct rt_rtmp_adapter *pAd, + u8 *pSrc, u8 *pDest, u32 Len); + +BOOLEAN RTMPSoftDecryptWEP(struct rt_rtmp_adapter *pAd, + u8 *pData, + unsigned long DataByteCnt, struct rt_cipher_key *pGroupKey); + +void RTMPSetICV(struct rt_rtmp_adapter *pAd, u8 *pDest); + +void ARCFOUR_INIT(struct rt_arcfourcontext *Ctx, u8 *pKey, u32 KeyLen); + +u8 ARCFOUR_BYTE(struct rt_arcfourcontext *Ctx); + +void ARCFOUR_DECRYPT(struct rt_arcfourcontext *Ctx, + u8 *pDest, u8 *pSrc, u32 Len); + +void ARCFOUR_ENCRYPT(struct rt_arcfourcontext *Ctx, + u8 *pDest, u8 *pSrc, u32 Len); + +void WPAARCFOUR_ENCRYPT(struct rt_arcfourcontext *Ctx, + u8 *pDest, u8 *pSrc, u32 Len); + +u32 RTMP_CALC_FCS32(u32 Fcs, u8 *Cp, int Len); + +/* */ +/* MLME routines */ +/* */ + +/* Asic/RF/BBP related functions */ + +void AsicAdjustTxPower(struct rt_rtmp_adapter *pAd); + +void AsicUpdateProtect(struct rt_rtmp_adapter *pAd, + u16 OperaionMode, + u8 SetMask, + IN BOOLEAN bDisableBGProtect, IN BOOLEAN bNonGFExist); + +void AsicSwitchChannel(struct rt_rtmp_adapter *pAd, + u8 Channel, IN BOOLEAN bScan); + +void AsicLockChannel(struct rt_rtmp_adapter *pAd, u8 Channel); + +void AsicRfTuningExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); + +void AsicResetBBPAgent(struct rt_rtmp_adapter *pAd); + +void AsicSleepThenAutoWakeup(struct rt_rtmp_adapter *pAd, + u16 TbttNumToNextWakeUp); + +void AsicForceSleep(struct rt_rtmp_adapter *pAd); + +void AsicForceWakeup(struct rt_rtmp_adapter *pAd, IN BOOLEAN bFromTx); + +void AsicSetBssid(struct rt_rtmp_adapter *pAd, u8 *pBssid); + +void AsicSetMcastWC(struct rt_rtmp_adapter *pAd); + +void AsicDelWcidTab(struct rt_rtmp_adapter *pAd, u8 Wcid); + +void AsicEnableRDG(struct rt_rtmp_adapter *pAd); + +void AsicDisableRDG(struct rt_rtmp_adapter *pAd); + +void AsicDisableSync(struct rt_rtmp_adapter *pAd); + +void AsicEnableBssSync(struct rt_rtmp_adapter *pAd); + +void AsicEnableIbssSync(struct rt_rtmp_adapter *pAd); + +void AsicSetEdcaParm(struct rt_rtmp_adapter *pAd, struct rt_edca_parm *pEdcaParm); + +void AsicSetSlotTime(struct rt_rtmp_adapter *pAd, IN BOOLEAN bUseShortSlotTime); + +void AsicAddSharedKeyEntry(struct rt_rtmp_adapter *pAd, + u8 BssIndex, + u8 KeyIdx, + u8 CipherAlg, + u8 *pKey, u8 *pTxMic, u8 *pRxMic); + +void AsicRemoveSharedKeyEntry(struct rt_rtmp_adapter *pAd, + u8 BssIndex, u8 KeyIdx); + +void AsicUpdateWCIDAttribute(struct rt_rtmp_adapter *pAd, + u16 WCID, + u8 BssIndex, + u8 CipherAlg, + IN BOOLEAN bUsePairewiseKeyTable); + +void AsicUpdateWCIDIVEIV(struct rt_rtmp_adapter *pAd, + u16 WCID, unsigned long uIV, unsigned long uEIV); + +void AsicUpdateRxWCIDTable(struct rt_rtmp_adapter *pAd, + u16 WCID, u8 *pAddr); + +void AsicAddKeyEntry(struct rt_rtmp_adapter *pAd, + u16 WCID, + u8 BssIndex, + u8 KeyIdx, + struct rt_cipher_key *pCipherKey, + IN BOOLEAN bUsePairewiseKeyTable, IN BOOLEAN bTxKey); + +void AsicAddPairwiseKeyEntry(struct rt_rtmp_adapter *pAd, + u8 *pAddr, + u8 WCID, struct rt_cipher_key *pCipherKey); + +void AsicRemovePairwiseKeyEntry(struct rt_rtmp_adapter *pAd, + u8 BssIdx, u8 Wcid); + +BOOLEAN AsicSendCommandToMcu(struct rt_rtmp_adapter *pAd, + u8 Command, + u8 Token, u8 Arg0, u8 Arg1); + +#ifdef RTMP_MAC_PCI +BOOLEAN AsicCheckCommanOk(struct rt_rtmp_adapter *pAd, u8 Command); +#endif /* RTMP_MAC_PCI // */ + +void MacAddrRandomBssid(struct rt_rtmp_adapter *pAd, u8 *pAddr); + +void MgtMacHeaderInit(struct rt_rtmp_adapter *pAd, + struct rt_header_802_11 * pHdr80211, + u8 SubType, + u8 ToDs, u8 *pDA, u8 *pBssid); + +void MlmeRadioOff(struct rt_rtmp_adapter *pAd); + +void MlmeRadioOn(struct rt_rtmp_adapter *pAd); + +void BssTableInit(struct rt_bss_table *Tab); + +void BATableInit(struct rt_rtmp_adapter *pAd, struct rt_ba_table *Tab); + +unsigned long BssTableSearch(struct rt_bss_table *Tab, u8 *pBssid, u8 Channel); + +unsigned long BssSsidTableSearch(struct rt_bss_table *Tab, + u8 *pBssid, + u8 *pSsid, u8 SsidLen, u8 Channel); + +unsigned long BssTableSearchWithSSID(struct rt_bss_table *Tab, + u8 *Bssid, + u8 *pSsid, + u8 SsidLen, u8 Channel); + +unsigned long BssSsidTableSearchBySSID(struct rt_bss_table *Tab, + u8 *pSsid, u8 SsidLen); + +void BssTableDeleteEntry(struct rt_bss_table *pTab, + u8 *pBssid, u8 Channel); + +void BATableDeleteORIEntry(struct rt_rtmp_adapter *pAd, + struct rt_ba_ori_entry *pBAORIEntry); + +void BssEntrySet(struct rt_rtmp_adapter *pAd, struct rt_bss_entry *pBss, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * CfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo, /* AP might use this additional ht info IE */ + u8 HtCapabilityLen, + u8 AddHtInfoLen, + u8 NewExtChanOffset, + u8 Channel, + char Rssi, + IN LARGE_INTEGER TimeStamp, + u8 CkipFlag, + struct rt_edca_parm *pEdcaParm, + struct rt_qos_capability_parm *pQosCapability, + struct rt_qbss_load_parm *pQbssLoad, + u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE); + +unsigned long BssTableSetEntry(struct rt_rtmp_adapter *pAd, struct rt_bss_table *pTab, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * CfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo, /* AP might use this additional ht info IE */ + u8 HtCapabilityLen, + u8 AddHtInfoLen, + u8 NewExtChanOffset, + u8 Channel, + char Rssi, + IN LARGE_INTEGER TimeStamp, + u8 CkipFlag, + struct rt_edca_parm *pEdcaParm, + struct rt_qos_capability_parm *pQosCapability, + struct rt_qbss_load_parm *pQbssLoad, + u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE); + +void BATableInsertEntry(struct rt_rtmp_adapter *pAd, + u16 Aid, + u16 TimeOutValue, + u16 StartingSeq, + u8 TID, + u8 BAWinSize, + u8 OriginatorStatus, IN BOOLEAN IsRecipient); + +void BssTableSsidSort(struct rt_rtmp_adapter *pAd, + struct rt_bss_table *OutTab, char Ssid[], u8 SsidLen); + +void BssTableSortByRssi(struct rt_bss_table *OutTab); + +void BssCipherParse(struct rt_bss_entry *pBss); + +int MlmeQueueInit(struct rt_mlme_queue *Queue); + +void MlmeQueueDestroy(struct rt_mlme_queue *Queue); + +BOOLEAN MlmeEnqueue(struct rt_rtmp_adapter *pAd, + unsigned long Machine, + unsigned long MsgType, unsigned long MsgLen, void * Msg); + +BOOLEAN MlmeEnqueueForRecv(struct rt_rtmp_adapter *pAd, + unsigned long Wcid, + unsigned long TimeStampHigh, + unsigned long TimeStampLow, + u8 Rssi0, + u8 Rssi1, + u8 Rssi2, + unsigned long MsgLen, void *Msg, u8 Signal); + +BOOLEAN MlmeDequeue(struct rt_mlme_queue *Queue, struct rt_mlme_queue_elem ** Elem); + +void MlmeRestartStateMachine(struct rt_rtmp_adapter *pAd); + +BOOLEAN MlmeQueueEmpty(struct rt_mlme_queue *Queue); + +BOOLEAN MlmeQueueFull(struct rt_mlme_queue *Queue); + +BOOLEAN MsgTypeSubst(struct rt_rtmp_adapter *pAd, + struct rt_frame_802_11 * pFrame, + int * Machine, int * MsgType); + +void StateMachineInit(struct rt_state_machine *Sm, + IN STATE_MACHINE_FUNC Trans[], + unsigned long StNr, + unsigned long MsgNr, + IN STATE_MACHINE_FUNC DefFunc, + unsigned long InitState, unsigned long Base); + +void StateMachineSetAction(struct rt_state_machine *S, + unsigned long St, unsigned long Msg, IN STATE_MACHINE_FUNC F); + +void StateMachinePerformAction(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *S, struct rt_mlme_queue_elem *Elem); + +void Drop(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void AssocStateMachineInit(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +void ReassocTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); + +void AssocTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); + +void DisassocTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); + +/*---------------------------------------------- */ +void MlmeAssocReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void MlmeReassocReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void MlmeDisassocReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void PeerAssocRspAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void PeerReassocRspAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void PeerDisassocAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void DisassocTimeoutAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void AssocTimeoutAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void ReassocTimeoutAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void Cls3errAction(struct rt_rtmp_adapter *pAd, u8 *pAddr); + +void InvalidStateWhenAssoc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void InvalidStateWhenReassoc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void InvalidStateWhenDisassociate(struct rt_rtmp_adapter *pAd, + struct rt_mlme_queue_elem *Elem); + +#ifdef RTMP_MAC_USB +void MlmeCntlConfirm(struct rt_rtmp_adapter *pAd, unsigned long MsgType, u16 Msg); +#endif /* RTMP_MAC_USB // */ + +void ComposePsPoll(struct rt_rtmp_adapter *pAd); + +void ComposeNullFrame(struct rt_rtmp_adapter *pAd); + +void AssocPostProc(struct rt_rtmp_adapter *pAd, + u8 *pAddr2, + u16 CapabilityInfo, + u16 Aid, + u8 SupRate[], + u8 SupRateLen, + u8 ExtRate[], + u8 ExtRateLen, + struct rt_edca_parm *pEdcaParm, + struct rt_ht_capability_ie * pHtCapability, + u8 HtCapabilityLen, struct rt_add_ht_info_ie * pAddHtInfo); + +void AuthStateMachineInit(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *sm, OUT STATE_MACHINE_FUNC Trans[]); + +void AuthTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); + +void MlmeAuthReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void PeerAuthRspAtSeq2Action(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void PeerAuthRspAtSeq4Action(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void AuthTimeoutAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void Cls2errAction(struct rt_rtmp_adapter *pAd, u8 *pAddr); + +void MlmeDeauthReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void InvalidStateWhenAuth(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +/*============================================= */ + +void AuthRspStateMachineInit(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *Sm, + IN STATE_MACHINE_FUNC Trans[]); + +void PeerDeauthAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void PeerAuthSimpleRspGenAndSend(struct rt_rtmp_adapter *pAd, + struct rt_header_802_11 * pHdr80211, + u16 Alg, + u16 Seq, + u16 Reason, u16 Status); + +/* */ +/* Private routines in dls.c */ +/* */ + +/*======================================== */ + +void SyncStateMachineInit(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +void BeaconTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); + +void ScanTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); + +void InvalidStateWhenScan(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void InvalidStateWhenJoin(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void InvalidStateWhenStart(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void EnqueueProbeRequest(struct rt_rtmp_adapter *pAd); + +BOOLEAN ScanRunning(struct rt_rtmp_adapter *pAd); +/*========================================= */ + +void MlmeCntlInit(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *S, OUT STATE_MACHINE_FUNC Trans[]); + +void MlmeCntlMachinePerformAction(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *S, + struct rt_mlme_queue_elem *Elem); + +void CntlIdleProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void CntlOidScanProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void CntlOidSsidProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); + +void CntlOidRTBssidProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); -typedef struct _BA_ORI_ENTRY{ - UCHAR Wcid; - UCHAR TID; - UCHAR BAWinSize; - UCHAR Token; -// Sequence is to fill every outgoing QoS DATA frame's sequence field in 802.11 header. - USHORT Sequence; - USHORT TimeOutValue; - ORI_BLOCKACK_STATUS ORI_BA_Status; - RALINK_TIMER_STRUCT ORIBATimer; - PVOID pAdapter; -} BA_ORI_ENTRY, *PBA_ORI_ENTRY; - -typedef struct _BA_REC_ENTRY { - UCHAR Wcid; - UCHAR TID; - UCHAR BAWinSize; // 7.3.1.14. each buffer is capable of holding a max AMSDU or MSDU. - USHORT LastIndSeq; - USHORT TimeOutValue; - RALINK_TIMER_STRUCT RECBATimer; - ULONG LastIndSeqAtTimer; - ULONG nDropPacket; - ULONG rcvSeq; - REC_BLOCKACK_STATUS REC_BA_Status; - NDIS_SPIN_LOCK RxReRingLock; // Rx Ring spinlock - PVOID pAdapter; - struct reordering_list list; -} BA_REC_ENTRY, *PBA_REC_ENTRY; - - -typedef struct { - ULONG numAsRecipient; // I am recipient of numAsRecipient clients. These client are in the BARecEntry[] - ULONG numAsOriginator; // I am originator of numAsOriginator clients. These clients are in the BAOriEntry[] - BA_ORI_ENTRY BAOriEntry[MAX_LEN_OF_BA_ORI_TABLE]; - BA_REC_ENTRY BARecEntry[MAX_LEN_OF_BA_REC_TABLE]; -} BA_TABLE, *PBA_TABLE; - -//For QureyBATableOID use; -typedef struct PACKED _OID_BA_REC_ENTRY{ - UCHAR MACAddr[MAC_ADDR_LEN]; - UCHAR BaBitmap; // if (BaBitmap&(1<> 3) + 1) /* /8 + 1 */ -#define WLAN_CT_TIM_BCMC_OFFSET 0 /* unit: 32B */ +void CntlWaitJoinProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); -/* clear bcmc TIM bit */ -#define WLAN_MR_TIM_BCMC_CLEAR(apidx) \ - pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] &= ~BIT8[0]; +void CntlWaitReassocProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); -/* set bcmc TIM bit */ -#define WLAN_MR_TIM_BCMC_SET(apidx) \ - pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] |= BIT8[0]; +void CntlWaitStartProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); -/* clear a station PS TIM bit */ -#define WLAN_MR_TIM_BIT_CLEAR(ad_p, apidx, wcid) \ - { UCHAR tim_offset = wcid >> 3; \ - UCHAR bit_offset = wcid & 0x7; \ - ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] &= (~BIT8[bit_offset]); } +void CntlWaitAuthProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); -/* set a station PS TIM bit */ -#define WLAN_MR_TIM_BIT_SET(ad_p, apidx, wcid) \ - { UCHAR tim_offset = wcid >> 3; \ - UCHAR bit_offset = wcid & 0x7; \ - ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] |= BIT8[bit_offset]; } +void CntlWaitAuthProc2(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); -#ifdef RT2870 -#define BEACON_BITMAP_MASK 0xff -typedef struct _BEACON_SYNC_STRUCT_ -{ - UCHAR BeaconBuf[HW_BEACON_MAX_COUNT][HW_BEACON_OFFSET]; - UCHAR BeaconTxWI[HW_BEACON_MAX_COUNT][TXWI_SIZE]; - ULONG TimIELocationInBeacon[HW_BEACON_MAX_COUNT]; - ULONG CapabilityInfoLocationInBeacon[HW_BEACON_MAX_COUNT]; - BOOLEAN EnableBeacon; // trigger to enable beacon transmission. - UCHAR BeaconBitMap; // NOTE: If the MAX_MBSSID_NUM is larger than 8, this parameter need to change. - UCHAR DtimBitOn; // NOTE: If the MAX_MBSSID_NUM is larger than 8, this parameter need to change. -}BEACON_SYNC_STRUCT; -#endif // RT2870 // - -typedef struct _MULTISSID_STRUCT { - UCHAR Bssid[MAC_ADDR_LEN]; - UCHAR SsidLen; - CHAR Ssid[MAX_LEN_OF_SSID]; - USHORT CapabilityInfo; - - PNET_DEV MSSIDDev; - - NDIS_802_11_AUTHENTICATION_MODE AuthMode; - NDIS_802_11_WEP_STATUS WepStatus; - NDIS_802_11_WEP_STATUS GroupKeyWepStatus; - WPA_MIX_PAIR_CIPHER WpaMixPairCipher; - - ULONG TxCount; - ULONG RxCount; - ULONG ReceivedByteCount; - ULONG TransmittedByteCount; - ULONG RxErrorCount; - ULONG RxDropCount; - - HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. - RT_HT_PHY_INFO DesiredHtPhyInfo; - DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; // Desired transmit setting. this is for reading registry setting only. not useful. - BOOLEAN bAutoTxRateSwitch; - - UCHAR DefaultKeyId; - - UCHAR TxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11, ... - UCHAR DesiredRates[MAX_LEN_OF_SUPPORTED_RATES];// OID_802_11_DESIRED_RATES - UCHAR DesiredRatesIndex; - UCHAR MaxTxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11 - - UCHAR TimBitmaps[WLAN_MAX_NUM_OF_TIM]; - - // WPA - UCHAR GMK[32]; - UCHAR PMK[32]; - UCHAR GTK[32]; - BOOLEAN IEEE8021X; - BOOLEAN PreAuth; - UCHAR GNonce[32]; - UCHAR PortSecured; - NDIS_802_11_PRIVACY_FILTER PrivacyFilter; - UCHAR BANClass3Data; - ULONG IsolateInterStaTraffic; - - UCHAR RSNIE_Len[2]; - UCHAR RSN_IE[2][MAX_LEN_OF_RSNIE]; - - - UCHAR TimIELocationInBeacon; - UCHAR CapabilityInfoLocationInBeacon; - // outgoing BEACON frame buffer and corresponding TXWI - // PTXWI_STRUC BeaconTxWI; // - CHAR BeaconBuf[MAX_BEACON_SIZE]; // NOTE: BeaconBuf should be 4-byte aligned - - BOOLEAN bHideSsid; - UINT16 StationKeepAliveTime; // unit: second - - USHORT VLAN_VID; - USHORT VLAN_Priority; - - RT_802_11_ACL AccessControlList; - - // EDCA Qos - BOOLEAN bWmmCapable; // 0:disable WMM, 1:enable WMM - BOOLEAN bDLSCapable; // 0:disable DLS, 1:enable DLS - - UCHAR DlsPTK[64]; // Due to windows dirver count on meetinghouse to handle 4-way shake - - // For 802.1x daemon setting per BSS - UCHAR radius_srv_num; - RADIUS_SRV_INFO radius_srv_info[MAX_RADIUS_SRV_NUM]; - -#ifdef RTL865X_SOC - unsigned int mylinkid; -#endif +void CntlWaitAssocProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); +void LinkUp(struct rt_rtmp_adapter *pAd, u8 BssType); - UINT32 RcvdConflictSsidCount; - UINT32 RcvdSpoofedAssocRespCount; - UINT32 RcvdSpoofedReassocRespCount; - UINT32 RcvdSpoofedProbeRespCount; - UINT32 RcvdSpoofedBeaconCount; - UINT32 RcvdSpoofedDisassocCount; - UINT32 RcvdSpoofedAuthCount; - UINT32 RcvdSpoofedDeauthCount; - UINT32 RcvdSpoofedUnknownMgmtCount; - UINT32 RcvdReplayAttackCount; - - CHAR RssiOfRcvdConflictSsid; - CHAR RssiOfRcvdSpoofedAssocResp; - CHAR RssiOfRcvdSpoofedReassocResp; - CHAR RssiOfRcvdSpoofedProbeResp; - CHAR RssiOfRcvdSpoofedBeacon; - CHAR RssiOfRcvdSpoofedDisassoc; - CHAR RssiOfRcvdSpoofedAuth; - CHAR RssiOfRcvdSpoofedDeauth; - CHAR RssiOfRcvdSpoofedUnknownMgmt; - CHAR RssiOfRcvdReplayAttack; - - BOOLEAN bBcnSntReq; - UCHAR BcnBufIdx; -} MULTISSID_STRUCT, *PMULTISSID_STRUCT; - -// configuration common to OPMODE_AP as well as OPMODE_STA -typedef struct _COMMON_CONFIG { - - BOOLEAN bCountryFlag; - UCHAR CountryCode[3]; - UCHAR Geography; - UCHAR CountryRegion; // Enum of country region, 0:FCC, 1:IC, 2:ETSI, 3:SPAIN, 4:France, 5:MKK, 6:MKK1, 7:Israel - UCHAR CountryRegionForABand; // Enum of country region for A band - UCHAR PhyMode; // PHY_11A, PHY_11B, PHY_11BG_MIXED, PHY_ABG_MIXED - USHORT Dsifs; // in units of usec - ULONG PacketFilter; // Packet filter for receiving - - CHAR Ssid[MAX_LEN_OF_SSID]; // NOT NULL-terminated - UCHAR SsidLen; // the actual ssid length in used - UCHAR LastSsidLen; // the actual ssid length in used - CHAR LastSsid[MAX_LEN_OF_SSID]; // NOT NULL-terminated - UCHAR LastBssid[MAC_ADDR_LEN]; - - UCHAR Bssid[MAC_ADDR_LEN]; - USHORT BeaconPeriod; - UCHAR Channel; - UCHAR CentralChannel; // Central Channel when using 40MHz is indicating. not real channel. - - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen; - UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR ExtRateLen; - UCHAR DesireRate[MAX_LEN_OF_SUPPORTED_RATES]; // OID_802_11_DESIRED_RATES - UCHAR MaxDesiredRate; - UCHAR ExpectedACKRate[MAX_LEN_OF_SUPPORTED_RATES]; - - ULONG BasicRateBitmap; // backup basic ratebitmap - - BOOLEAN bAPSDCapable; - BOOLEAN bInServicePeriod; - BOOLEAN bAPSDAC_BE; - BOOLEAN bAPSDAC_BK; - BOOLEAN bAPSDAC_VI; - BOOLEAN bAPSDAC_VO; - BOOLEAN bNeedSendTriggerFrame; - BOOLEAN bAPSDForcePowerSave; // Force power save mode, should only use in APSD-STAUT - ULONG TriggerTimerCount; - UCHAR MaxSPLength; - UCHAR BBPCurrentBW; // BW_10, BW_20, BW_40 - REG_TRANSMIT_SETTING RegTransmitSetting; //registry transmit setting. this is for reading registry setting only. not useful. - UCHAR TxRate; // Same value to fill in TXD. TxRate is 6-bit - UCHAR MaxTxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11 - UCHAR TxRateIndex; // Tx rate index in RateSwitchTable - UCHAR TxRateTableSize; // Valid Tx rate table size in RateSwitchTable - UCHAR MinTxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11 - UCHAR RtsRate; // RATE_xxx - HTTRANSMIT_SETTING MlmeTransmit; // MGMT frame PHY rate setting when operatin at Ht rate. - UCHAR MlmeRate; // RATE_xxx, used to send MLME frames - UCHAR BasicMlmeRate; // Default Rate for sending MLME frames - - USHORT RtsThreshold; // in unit of BYTE - USHORT FragmentThreshold; // in unit of BYTE - - UCHAR TxPower; // in unit of mW - ULONG TxPowerPercentage; // 0~100 % - ULONG TxPowerDefault; // keep for TxPowerPercentage - - BACAP_STRUC BACapability; // NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0 - BACAP_STRUC REGBACapability; // NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0 - - IOT_STRUC IOTestParm; // 802.11n InterOpbility Test Parameter; - ULONG TxPreamble; // Rt802_11PreambleLong, Rt802_11PreambleShort, Rt802_11PreambleAuto - BOOLEAN bUseZeroToDisableFragment; // Microsoft use 0 as disable - ULONG UseBGProtection; // 0: auto, 1: always use, 2: always not use - BOOLEAN bUseShortSlotTime; // 0: disable, 1 - use short slot (9us) - BOOLEAN bEnableTxBurst; // 1: enble TX PACKET BURST, 0: disable TX PACKET BURST - BOOLEAN bAggregationCapable; // 1: enable TX aggregation when the peer supports it - BOOLEAN bPiggyBackCapable; // 1: enable TX piggy-back according MAC's version - BOOLEAN bIEEE80211H; // 1: enable IEEE802.11h spec. - ULONG DisableOLBCDetect; // 0: enable OLBC detect; 1 disable OLBC detect - - BOOLEAN bRdg; - - BOOLEAN bWmmCapable; // 0:disable WMM, 1:enable WMM - QOS_CAPABILITY_PARM APQosCapability; // QOS capability of the current associated AP - EDCA_PARM APEdcaParm; // EDCA parameters of the current associated AP - QBSS_LOAD_PARM APQbssLoad; // QBSS load of the current associated AP - UCHAR AckPolicy[4]; // ACK policy of the specified AC. see ACK_xxx - BOOLEAN bDLSCapable; // 0:disable DLS, 1:enable DLS - // a bitmap of BOOLEAN flags. each bit represent an operation status of a particular - // BOOLEAN control, either ON or OFF. These flags should always be accessed via - // OPSTATUS_TEST_FLAG(), OPSTATUS_SET_FLAG(), OP_STATUS_CLEAR_FLAG() macros. - // see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition - ULONG OpStatusFlags; - - BOOLEAN NdisRadioStateOff; //For HCT 12.0, set this flag to TRUE instead of called MlmeRadioOff. - ABGBAND_STATE BandState; // For setting BBP used on B/G or A mode. - - // IEEE802.11H--DFS. - RADAR_DETECT_STRUCT RadarDetect; - - // HT - UCHAR BASize; // USer desired BAWindowSize. Should not exceed our max capability - //RT_HT_CAPABILITY SupportedHtPhy; - RT_HT_CAPABILITY DesiredHtPhy; - HT_CAPABILITY_IE HtCapability; - ADD_HT_INFO_IE AddHTInfo; // Useful as AP. - //This IE is used with channel switch announcement element when changing to a new 40MHz. - //This IE is included in channel switch ammouncement frames 7.4.1.5, beacons, probe Rsp. - NEW_EXT_CHAN_IE NewExtChanOffset; //7.3.2.20A, 1 if extension channel is above the control channel, 3 if below, 0 if not present - - BOOLEAN bHTProtect; - BOOLEAN bMIMOPSEnable; - BOOLEAN bBADecline; - BOOLEAN bDisableReordering; - BOOLEAN bForty_Mhz_Intolerant; - BOOLEAN bExtChannelSwitchAnnouncement; - BOOLEAN bRcvBSSWidthTriggerEvents; - ULONG LastRcvBSSWidthTriggerEventsTime; - - UCHAR TxBASize; - - // Enable wireless event - BOOLEAN bWirelessEvent; - BOOLEAN bWiFiTest; // Enable this parameter for WiFi test - - // Tx & Rx Stream number selection - UCHAR TxStream; - UCHAR RxStream; - - // transmit phy mode, trasmit rate for Multicast. -#ifdef MCAST_RATE_SPECIFIC - UCHAR McastTransmitMcs; - UCHAR McastTransmitPhyMode; -#endif // MCAST_RATE_SPECIFIC // - - BOOLEAN bHardwareRadio; // Hardware controlled Radio enabled - -#ifdef RT2870 - BOOLEAN bMultipleIRP; // Multiple Bulk IN flag - UCHAR NumOfBulkInIRP; // if bMultipleIRP == TRUE, NumOfBulkInIRP will be 4 otherwise be 1 - RT_HT_CAPABILITY SupportedHtPhy; - ULONG MaxPktOneTxBulk; - UCHAR TxBulkFactor; - UCHAR RxBulkFactor; - - BEACON_SYNC_STRUCT *pBeaconSync; - RALINK_TIMER_STRUCT BeaconUpdateTimer; - UINT32 BeaconAdjust; - UINT32 BeaconFactor; - UINT32 BeaconRemain; -#endif // RT2870 // - - - NDIS_SPIN_LOCK MeasureReqTabLock; - PMEASURE_REQ_TAB pMeasureReqTab; - - NDIS_SPIN_LOCK TpcReqTabLock; - PTPC_REQ_TAB pTpcReqTab; - - // transmit phy mode, trasmit rate for Multicast. -#ifdef MCAST_RATE_SPECIFIC - HTTRANSMIT_SETTING MCastPhyMode; -#endif // MCAST_RATE_SPECIFIC // -} COMMON_CONFIG, *PCOMMON_CONFIG; +void LinkDown(struct rt_rtmp_adapter *pAd, IN BOOLEAN IsReqFromAP); -/* Modified by Wu Xi-Kun 4/21/2006 */ -// STA configuration and status -typedef struct _STA_ADMIN_CONFIG { - // GROUP 1 - - // User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe - // the user intended configuration, but not necessary fully equal to the final - // settings in ACTIVE BSS after negotiation/compromize with the BSS holder (either - // AP or IBSS holder). - // Once initialized, user configuration can only be changed via OID_xxx - UCHAR BssType; // BSS_INFRA or BSS_ADHOC - USHORT AtimWin; // used when starting a new IBSS - - // GROUP 2 - - // User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe - // the user intended configuration, and should be always applied to the final - // settings in ACTIVE BSS without compromising with the BSS holder. - // Once initialized, user configuration can only be changed via OID_xxx - UCHAR RssiTrigger; - UCHAR RssiTriggerMode; // RSSI_TRIGGERED_UPON_BELOW_THRESHOLD or RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD - USHORT DefaultListenCount; // default listen count; - ULONG WindowsPowerMode; // Power mode for AC power - ULONG WindowsBatteryPowerMode; // Power mode for battery if exists - BOOLEAN bWindowsACCAMEnable; // Enable CAM power mode when AC on - BOOLEAN bAutoReconnect; // Set to TRUE when setting OID_802_11_SSID with no matching BSSID - ULONG WindowsPowerProfile; // Windows power profile, for NDIS5.1 PnP - - // MIB:ieee802dot11.dot11smt(1).dot11StationConfigTable(1) - USHORT Psm; // power management mode (PWR_ACTIVE|PWR_SAVE) - USHORT DisassocReason; - UCHAR DisassocSta[MAC_ADDR_LEN]; - USHORT DeauthReason; - UCHAR DeauthSta[MAC_ADDR_LEN]; - USHORT AuthFailReason; - UCHAR AuthFailSta[MAC_ADDR_LEN]; - - NDIS_802_11_PRIVACY_FILTER PrivacyFilter; // PrivacyFilter enum for 802.1X - NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined - NDIS_802_11_WEP_STATUS WepStatus; - NDIS_802_11_WEP_STATUS OrigWepStatus; // Original wep status set from OID - - // Add to support different cipher suite for WPA2/WPA mode - NDIS_802_11_ENCRYPTION_STATUS GroupCipher; // Multicast cipher suite - NDIS_802_11_ENCRYPTION_STATUS PairCipher; // Unicast cipher suite - BOOLEAN bMixCipher; // Indicate current Pair & Group use different cipher suites - USHORT RsnCapability; - - NDIS_802_11_WEP_STATUS GroupKeyWepStatus; - - UCHAR PMK[32]; // WPA PSK mode PMK - UCHAR PTK[64]; // WPA PSK mode PTK - UCHAR GTK[32]; // GTK from authenticator - BSSID_INFO SavedPMK[PMKID_NO]; - UINT SavedPMKNum; // Saved PMKID number - - UCHAR DefaultKeyId; - - - // WPA 802.1x port control, WPA_802_1X_PORT_SECURED, WPA_802_1X_PORT_NOT_SECURED - UCHAR PortSecured; - - // For WPA countermeasures - ULONG LastMicErrorTime; // record last MIC error time - ULONG MicErrCnt; // Should be 0, 1, 2, then reset to zero (after disassoiciation). - BOOLEAN bBlockAssoc; // Block associate attempt for 60 seconds after counter measure occurred. - // For WPA-PSK supplicant state - WPA_STATE WpaState; // Default is SS_NOTUSE and handled by microsoft 802.1x - UCHAR ReplayCounter[8]; - UCHAR ANonce[32]; // ANonce for WPA-PSK from aurhenticator - UCHAR SNonce[32]; // SNonce for WPA-PSK - - UCHAR LastSNR0; // last received BEACON's SNR - UCHAR LastSNR1; // last received BEACON's SNR for 2nd antenna - RSSI_SAMPLE RssiSample; - ULONG NumOfAvgRssiSample; - - ULONG LastBeaconRxTime; // OS's timestamp of the last BEACON RX time - ULONG Last11bBeaconRxTime; // OS's timestamp of the last 11B BEACON RX time - ULONG Last11gBeaconRxTime; // OS's timestamp of the last 11G BEACON RX time - ULONG Last20NBeaconRxTime; // OS's timestamp of the last 20MHz N BEACON RX time - - ULONG LastScanTime; // Record last scan time for issue BSSID_SCAN_LIST - ULONG ScanCnt; // Scan counts since most recent SSID, BSSID, SCAN OID request - BOOLEAN bSwRadio; // Software controlled Radio On/Off, TRUE: On - BOOLEAN bHwRadio; // Hardware controlled Radio On/Off, TRUE: On - BOOLEAN bRadio; // Radio state, And of Sw & Hw radio state - BOOLEAN bHardwareRadio; // Hardware controlled Radio enabled - BOOLEAN bShowHiddenSSID; // Show all known SSID in SSID list get operation -#ifdef RT2860 - BOOLEAN AdhocBOnlyJoined; // Indicate Adhoc B Join. - BOOLEAN AdhocBGJoined; // Indicate Adhoc B/G Join. - BOOLEAN Adhoc20NJoined; // Indicate Adhoc 20MHz N Join. -#endif - // New for WPA, windows want us to keep association information and - // Fixed IEs from last association response - NDIS_802_11_ASSOCIATION_INFORMATION AssocInfo; - USHORT ReqVarIELen; // Length of next VIE include EID & Length - UCHAR ReqVarIEs[MAX_VIE_LEN]; // The content saved here should be little-endian format. - USHORT ResVarIELen; // Length of next VIE include EID & Length - UCHAR ResVarIEs[MAX_VIE_LEN]; - - UCHAR RSNIE_Len; - UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; // The content saved here should be little-endian format. - - // New variables used for CCX 1.0 - BOOLEAN bCkipOn; - BOOLEAN bCkipCmicOn; - UCHAR CkipFlag; - UCHAR GIV[3]; //for CCX iv - UCHAR RxSEQ[4]; - UCHAR TxSEQ[4]; - UCHAR CKIPMIC[4]; - UCHAR LeapAuthMode; - LEAP_AUTH_INFO LeapAuthInfo; - UCHAR HashPwd[16]; - UCHAR NetworkChallenge[8]; - UCHAR NetworkChallengeResponse[24]; - UCHAR PeerChallenge[8]; - - UCHAR PeerChallengeResponse[24]; - UCHAR SessionKey[16]; //Network session keys (NSK) - RALINK_TIMER_STRUCT LeapAuthTimer; - ROGUEAP_TABLE RogueApTab; //Cisco CCX1 Rogue AP Detection - - // New control flags for CCX - CCX_CONTROL CCXControl; // Master administration state - BOOLEAN CCXEnable; // Actual CCX state - UCHAR CCXScanChannel; // Selected channel for CCX beacon request - USHORT CCXScanTime; // Time out to wait for beacon and probe response - UCHAR CCXReqType; // Current processing CCX request type - BSS_TABLE CCXBssTab; // BSS Table - UCHAR FrameReportBuf[2048]; // Buffer for creating frame report - USHORT FrameReportLen; // Current Frame report length - ULONG CLBusyBytes; // Save the total bytes received durning channel load scan time - USHORT RPIDensity[8]; // Array for RPI density collection - // Start address of each BSS table within FrameReportBuf - // It's important to update the RxPower of the corresponding Bss - USHORT BssReportOffset[MAX_LEN_OF_BSS_TABLE]; - USHORT BeaconToken; // Token for beacon report - ULONG LastBssIndex; // Most current reported Bss index - RM_REQUEST_ACTION MeasurementRequest[16]; // Saved measurement request - UCHAR RMReqCnt; // Number of measurement request saved. - UCHAR CurrentRMReqIdx; // Number of measurement request saved. - BOOLEAN ParallelReq; // Parallel measurement, only one request performed, - // It must be the same channel with maximum duration - USHORT ParallelDuration; // Maximum duration for parallel measurement - UCHAR ParallelChannel; // Only one channel with parallel measurement - USHORT IAPPToken; // IAPP dialog token - UCHAR CCXQosECWMin; // Cisco QOS ECWMin for AC 0 - UCHAR CCXQosECWMax; // Cisco QOS ECWMax for AC 0 - // Hack for channel load and noise histogram parameters - UCHAR NHFactor; // Parameter for Noise histogram - UCHAR CLFactor; // Parameter for channel load - - UCHAR KRK[16]; //Key Refresh Key. - UCHAR BTK[32]; //Base Transient Key - BOOLEAN CCKMLinkUpFlag; - ULONG CCKMRN; //(Re)Association request number. - LARGE_INTEGER CCKMBeaconAtJoinTimeStamp; //TSF timer for Re-assocaite to the new AP - UCHAR AironetCellPowerLimit; //in dBm - UCHAR AironetIPAddress[4]; //eg. 192.168.1.1 - BOOLEAN CCXAdjacentAPReportFlag; //flag for determining report Assoc Lost time - CHAR CCXAdjacentAPSsid[MAX_LEN_OF_SSID]; //Adjacent AP's SSID report - UCHAR CCXAdjacentAPSsidLen; // the actual ssid length in used - UCHAR CCXAdjacentAPBssid[MAC_ADDR_LEN]; //Adjacent AP's BSSID report - USHORT CCXAdjacentAPChannel; - ULONG CCXAdjacentAPLinkDownTime; //for Spec S32. - - RALINK_TIMER_STRUCT StaQuickResponeForRateUpTimer; - BOOLEAN StaQuickResponeForRateUpTimerRunning; - - UCHAR DtimCount; // 0.. DtimPeriod-1 - UCHAR DtimPeriod; // default = 3 - - //////////////////////////////////////////////////////////////////////////////////////// - // This is only for WHQL test. - BOOLEAN WhqlTest; - //////////////////////////////////////////////////////////////////////////////////////// - - RALINK_TIMER_STRUCT WpaDisassocAndBlockAssocTimer; - // Fast Roaming - BOOLEAN bFastRoaming; // 0:disable fast roaming, 1:enable fast roaming - CHAR dBmToRoam; // the condition to roam when receiving Rssi less than this value. It's negative value. - - BOOLEAN IEEE8021X; - BOOLEAN IEEE8021x_required_keys; - CIPHER_KEY DesireSharedKey[4]; // Record user desired WEP keys - UCHAR DesireSharedKeyId; - - // 0: driver ignores wpa_supplicant - // 1: wpa_supplicant initiates scanning and AP selection - // 2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters - UCHAR WpaSupplicantUP; - UCHAR WpaSupplicantScanCount; - - CHAR dev_name[16]; - USHORT OriDevType; - - BOOLEAN bTGnWifiTest; - BOOLEAN bScanReqIsFromWebUI; - - HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. - DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; - RT_HT_PHY_INFO DesiredHtPhyInfo; - BOOLEAN bAutoTxRateSwitch; - -#ifdef RT2860 - UCHAR BBPR3; -#endif -} STA_ADMIN_CONFIG, *PSTA_ADMIN_CONFIG; - -// This data structure keep the current active BSS/IBSS's configuration that this STA -// had agreed upon joining the network. Which means these parameters are usually decided -// by the BSS/IBSS creator instead of user configuration. Data in this data structurre -// is valid only when either ADHOC_ON(pAd) or INFRA_ON(pAd) is TRUE. -// Normally, after SCAN or failed roaming attempts, we need to recover back to -// the current active settings. -typedef struct _STA_ACTIVE_CONFIG { - USHORT Aid; - USHORT AtimWin; // in kusec; IBSS parameter set element - USHORT CapabilityInfo; - USHORT CfpMaxDuration; - USHORT CfpPeriod; - - // Copy supported rate from desired AP's beacon. We are trying to match - // AP's supported and extended rate settings. - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen; - UCHAR ExtRateLen; - // Copy supported ht from desired AP's beacon. We are trying to match - RT_HT_PHY_INFO SupportedPhyInfo; - RT_HT_CAPABILITY SupportedHtPhy; -} STA_ACTIVE_CONFIG, *PSTA_ACTIVE_CONFIG; - -#ifdef RT2870 -// for USB interface, avoid in interrupt when write key -typedef struct RT_ADD_PAIRWISE_KEY_ENTRY { - NDIS_802_11_MAC_ADDRESS MacAddr; - USHORT MacTabMatchWCID; // ASIC - CIPHER_KEY CipherKey; -} RT_ADD_PAIRWISE_KEY_ENTRY,*PRT_ADD_PAIRWISE_KEY_ENTRY; -#endif // RT2870 // - -// ----------- start of AP -------------------------- -// AUTH-RSP State Machine Aux data structure -typedef struct _AP_MLME_AUX { - UCHAR Addr[MAC_ADDR_LEN]; - USHORT Alg; - CHAR Challenge[CIPHER_TEXT_LEN]; -} AP_MLME_AUX, *PAP_MLME_AUX; - -// structure to define WPA Group Key Rekey Interval -typedef struct PACKED _RT_802_11_WPA_REKEY { - ULONG ReKeyMethod; // mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based - ULONG ReKeyInterval; // time-based: seconds, packet-based: kilo-packets -} RT_WPA_REKEY,*PRT_WPA_REKEY, RT_802_11_WPA_REKEY, *PRT_802_11_WPA_REKEY; - -typedef struct _MAC_TABLE_ENTRY { - //Choose 1 from ValidAsWDS and ValidAsCLI to validize. - BOOLEAN ValidAsCLI; // Sta mode, set this TRUE after Linkup,too. - BOOLEAN ValidAsWDS; // This is WDS Entry. only for AP mode. - BOOLEAN ValidAsApCli; //This is a AP-Client entry, only for AP mode which enable AP-Client functions. - BOOLEAN ValidAsMesh; - BOOLEAN ValidAsDls; // This is DLS Entry. only for STA mode. - BOOLEAN isCached; - BOOLEAN bIAmBadAtheros; // Flag if this is Atheros chip that has IOT problem. We need to turn on RTS/CTS protection. - - UCHAR EnqueueEapolStartTimerRunning; // Enqueue EAPoL-Start for triggering EAP SM - //jan for wpa - // record which entry revoke MIC Failure , if it leaves the BSS itself, AP won't update aMICFailTime MIB - UCHAR CMTimerRunning; - UCHAR apidx; // MBSS number - UCHAR RSNIE_Len; - UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; - UCHAR ANonce[LEN_KEY_DESC_NONCE]; - UCHAR R_Counter[LEN_KEY_DESC_REPLAY]; - UCHAR PTK[64]; - UCHAR ReTryCounter; - RALINK_TIMER_STRUCT RetryTimer; - RALINK_TIMER_STRUCT EnqueueStartForPSKTimer; // A timer which enqueue EAPoL-Start for triggering PSK SM - NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined - NDIS_802_11_WEP_STATUS WepStatus; - AP_WPA_STATE WpaState; - GTK_STATE GTKState; - USHORT PortSecured; - NDIS_802_11_PRIVACY_FILTER PrivacyFilter; // PrivacyFilter enum for 802.1X - CIPHER_KEY PairwiseKey; - PVOID pAd; - INT PMKID_CacheIdx; - UCHAR PMKID[LEN_PMKID]; - - - UCHAR Addr[MAC_ADDR_LEN]; - UCHAR PsMode; - SST Sst; - AUTH_STATE AuthState; // for SHARED KEY authentication state machine used only - BOOLEAN IsReassocSta; // Indicate whether this is a reassociation procedure - USHORT Aid; - USHORT CapabilityInfo; - UCHAR LastRssi; - ULONG NoDataIdleCount; - UINT16 StationKeepAliveCount; // unit: second - ULONG PsQIdleCount; - QUEUE_HEADER PsQueue; - - UINT32 StaConnectTime; // the live time of this station since associated with AP - - BOOLEAN bSendBAR; - USHORT NoBADataCountDown; - - UINT32 CachedBuf[16]; // UINT (4 bytes) for alignment - UINT TxBFCount; // 3*3 - UINT FIFOCount; - UINT DebugFIFOCount; - UINT DebugTxCount; - BOOLEAN bDlsInit; - - -//==================================================== -//WDS entry needs these -// rt2860 add this. if ValidAsWDS==TRUE, MatchWDSTabIdx is the index in WdsTab.MacTab - UINT MatchWDSTabIdx; - UCHAR MaxSupportedRate; - UCHAR CurrTxRate; - UCHAR CurrTxRateIndex; - // to record the each TX rate's quality. 0 is best, the bigger the worse. - USHORT TxQuality[MAX_STEP_OF_TX_RATE_SWITCH]; - UINT32 OneSecTxNoRetryOkCount; - UINT32 OneSecTxRetryOkCount; - UINT32 OneSecTxFailCount; - UINT32 ContinueTxFailCnt; - UINT32 CurrTxRateStableTime; // # of second in current TX rate - UCHAR TxRateUpPenalty; // extra # of second penalty due to last unstable condition -//==================================================== - - BOOLEAN fNoisyEnvironment; - BOOLEAN fLastSecAccordingRSSI; - UCHAR LastSecTxRateChangeAction; // 0: no change, 1:rate UP, 2:rate down - CHAR LastTimeTxRateChangeAction; //Keep last time value of LastSecTxRateChangeAction - ULONG LastTxOkCount; - UCHAR PER[MAX_STEP_OF_TX_RATE_SWITCH]; - - // a bitmap of BOOLEAN flags. each bit represent an operation status of a particular - // BOOLEAN control, either ON or OFF. These flags should always be accessed via - // CLIENT_STATUS_TEST_FLAG(), CLIENT_STATUS_SET_FLAG(), CLIENT_STATUS_CLEAR_FLAG() macros. - // see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition. fCLIENT_STATUS_AMSDU_INUSED - ULONG ClientStatusFlags; - - HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. - - // HT EWC MIMO-N used parameters - USHORT RXBAbitmap; // fill to on-chip RXWI_BA_BITMASK in 8.1.3RX attribute entry format - USHORT TXBAbitmap; // This bitmap as originator, only keep in software used to mark AMPDU bit in TXWI - USHORT TXAutoBAbitmap; - USHORT BADeclineBitmap; - USHORT BARecWcidArray[NUM_OF_TID]; // The mapping wcid of recipient session. if RXBAbitmap bit is masked - USHORT BAOriWcidArray[NUM_OF_TID]; // The mapping wcid of originator session. if TXBAbitmap bit is masked - USHORT BAOriSequence[NUM_OF_TID]; // The mapping wcid of originator session. if TXBAbitmap bit is masked - - // 802.11n features. - UCHAR MpduDensity; - UCHAR MaxRAmpduFactor; - UCHAR AMsduSize; - UCHAR MmpsMode; // MIMO power save more. - - HT_CAPABILITY_IE HTCapability; - - BOOLEAN bAutoTxRateSwitch; - - UCHAR RateLen; - struct _MAC_TABLE_ENTRY *pNext; - USHORT TxSeq[NUM_OF_TID]; - USHORT NonQosDataSeq; - - RSSI_SAMPLE RssiSample; - - UINT32 TXMCSExpected[16]; - UINT32 TXMCSSuccessful[16]; - UINT32 TXMCSFailed[16]; - UINT32 TXMCSAutoFallBack[16][16]; -#ifdef RT2870 - ULONG LastBeaconRxTime; -#endif -} MAC_TABLE_ENTRY, *PMAC_TABLE_ENTRY; - -typedef struct _MAC_TABLE { - USHORT Size; - MAC_TABLE_ENTRY *Hash[HASH_TABLE_SIZE]; - MAC_TABLE_ENTRY Content[MAX_LEN_OF_MAC_TABLE]; - QUEUE_HEADER McastPsQueue; - ULONG PsQIdleCount; - BOOLEAN fAnyStationInPsm; - BOOLEAN fAnyStationBadAtheros; // Check if any Station is atheros 802.11n Chip. We need to use RTS/CTS with Atheros 802,.11n chip. - BOOLEAN fAnyTxOPForceDisable; // Check if it is necessary to disable BE TxOP -#ifdef RT2870 - BOOLEAN fAllStationAsRalink; // Check if all stations are ralink-chipset -#endif - BOOLEAN fAnyStationIsLegacy; // Check if I use legacy rate to transmit to my BSS Station/ - BOOLEAN fAnyStationNonGF; // Check if any Station can't support GF. - BOOLEAN fAnyStation20Only; // Check if any Station can't support GF. - BOOLEAN fAnyStationMIMOPSDynamic; // Check if any Station is MIMO Dynamic - BOOLEAN fAnyBASession; // Check if there is BA session. Force turn on RTS/CTS -} MAC_TABLE, *PMAC_TABLE; +void IterateOnBssTab(struct rt_rtmp_adapter *pAd); -#define IS_HT_STA(_pMacEntry) \ - (_pMacEntry->MaxHTPhyMode.field.MODE >= MODE_HTMIX) +void IterateOnBssTab2(struct rt_rtmp_adapter *pAd);; -#define IS_HT_RATE(_pMacEntry) \ - (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) +void JoinParmFill(struct rt_rtmp_adapter *pAd, + struct rt_mlme_join_req *JoinReq, unsigned long BssIdx); -#define PEER_IS_HT_RATE(_pMacEntry) \ - (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) +void AssocParmFill(struct rt_rtmp_adapter *pAd, + struct rt_mlme_assoc_req *AssocReq, + u8 *pAddr, + u16 CapabilityInfo, + unsigned long Timeout, u16 ListenIntv); -typedef struct _WDS_ENTRY { - BOOLEAN Valid; - UCHAR Addr[MAC_ADDR_LEN]; - ULONG NoDataIdleCount; - struct _WDS_ENTRY *pNext; -} WDS_ENTRY, *PWDS_ENTRY; - -typedef struct _WDS_TABLE_ENTRY { - USHORT Size; - UCHAR WdsAddr[MAC_ADDR_LEN]; - WDS_ENTRY *Hash[HASH_TABLE_SIZE]; - WDS_ENTRY Content[MAX_LEN_OF_MAC_TABLE]; - UCHAR MaxSupportedRate; - UCHAR CurrTxRate; - USHORT TxQuality[MAX_LEN_OF_SUPPORTED_RATES]; - USHORT OneSecTxOkCount; - USHORT OneSecTxRetryOkCount; - USHORT OneSecTxFailCount; - ULONG CurrTxRateStableTime; // # of second in current TX rate - UCHAR TxRateUpPenalty; // extra # of second penalty due to last unstable condition -} WDS_TABLE_ENTRY, *PWDS_TABLE_ENTRY; - -typedef struct _RT_802_11_WDS_ENTRY { - PNET_DEV dev; - UCHAR Valid; - UCHAR PhyMode; - UCHAR PeerWdsAddr[MAC_ADDR_LEN]; - UCHAR MacTabMatchWCID; // ASIC - NDIS_802_11_WEP_STATUS WepStatus; - UCHAR KeyIdx; - CIPHER_KEY WdsKey; - HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; - RT_HT_PHY_INFO DesiredHtPhyInfo; - BOOLEAN bAutoTxRateSwitch; - DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; // Desired transmit setting. -} RT_802_11_WDS_ENTRY, *PRT_802_11_WDS_ENTRY; - -typedef struct _WDS_TABLE { - UCHAR Mode; - ULONG Size; - RT_802_11_WDS_ENTRY WdsEntry[MAX_WDS_ENTRY]; -} WDS_TABLE, *PWDS_TABLE; - -typedef struct _APCLI_STRUCT { - PNET_DEV dev; -#ifdef RTL865X_SOC - unsigned int mylinkid; -#endif - BOOLEAN Enable; // Set it as 1 if the apcli interface was configured to "1" or by iwpriv cmd "ApCliEnable" - BOOLEAN Valid; // Set it as 1 if the apcli interface associated success to remote AP. - UCHAR MacTabWCID; //WCID value, which point to the entry of ASIC Mac table. - UCHAR SsidLen; - CHAR Ssid[MAX_LEN_OF_SSID]; +void ScanParmFill(struct rt_rtmp_adapter *pAd, + struct rt_mlme_scan_req *ScanReq, + char Ssid[], + u8 SsidLen, u8 BssType, u8 ScanType); - UCHAR CfgSsidLen; - CHAR CfgSsid[MAX_LEN_OF_SSID]; - UCHAR CfgApCliBssid[ETH_LENGTH_OF_ADDRESS]; - UCHAR CurrentAddress[ETH_LENGTH_OF_ADDRESS]; +void DisassocParmFill(struct rt_rtmp_adapter *pAd, + struct rt_mlme_disassoc_req *DisassocReq, + u8 *pAddr, u16 Reason); - ULONG ApCliRcvBeaconTime; +void StartParmFill(struct rt_rtmp_adapter *pAd, + struct rt_mlme_start_req *StartReq, + char Ssid[], u8 SsidLen); - ULONG CtrlCurrState; - ULONG SyncCurrState; - ULONG AuthCurrState; - ULONG AssocCurrState; - ULONG WpaPskCurrState; +void AuthParmFill(struct rt_rtmp_adapter *pAd, + struct rt_mlme_auth_req *AuthReq, + u8 *pAddr, u16 Alg); - USHORT AuthReqCnt; - USHORT AssocReqCnt; +void EnqueuePsPoll(struct rt_rtmp_adapter *pAd); - ULONG ClientStatusFlags; - UCHAR MpduDensity; +void EnqueueBeaconFrame(struct rt_rtmp_adapter *pAd); - NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined - NDIS_802_11_WEP_STATUS WepStatus; +void MlmeJoinReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); - // Add to support different cipher suite for WPA2/WPA mode - NDIS_802_11_ENCRYPTION_STATUS GroupCipher; // Multicast cipher suite - NDIS_802_11_ENCRYPTION_STATUS PairCipher; // Unicast cipher suite - BOOLEAN bMixCipher; // Indicate current Pair & Group use different cipher suites - USHORT RsnCapability; +void MlmeScanReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); - UCHAR PSK[100]; // reserve PSK key material - UCHAR PSKLen; - UCHAR PMK[32]; // WPA PSK mode PMK - UCHAR GTK[32]; // GTK from authenticator +void MlmeStartReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); - CIPHER_KEY SharedKey[SHARE_KEY_NUM]; - UCHAR DefaultKeyId; +void ScanTimeoutAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); - // store RSN_IE built by driver - UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; // The content saved here should be convert to little-endian format. - UCHAR RSNIE_Len; +void BeaconTimeoutAtJoinAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); - // For WPA countermeasures - ULONG LastMicErrorTime; // record last MIC error time - BOOLEAN bBlockAssoc; // Block associate attempt for 60 seconds after counter measure occurred. +void PeerBeaconAtScanAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); - // For WPA-PSK supplicant state - UCHAR SNonce[32]; // SNonce for WPA-PSK - UCHAR GNonce[32]; // GNonce for WPA-PSK from authenticator +void PeerBeaconAtJoinAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); - HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; - RT_HT_PHY_INFO DesiredHtPhyInfo; - BOOLEAN bAutoTxRateSwitch; - DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; // Desired transmit setting. -} APCLI_STRUCT, *PAPCLI_STRUCT; +void PeerBeacon(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); -// ----------- end of AP ---------------------------- +void PeerProbeReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); -struct wificonf -{ - BOOLEAN bShortGI; - BOOLEAN bGreenField; -}; +void ScanNextChannel(struct rt_rtmp_adapter *pAd); +unsigned long MakeIbssBeacon(struct rt_rtmp_adapter *pAd); +BOOLEAN MlmeScanReqSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 * BssType, + char ssid[], + u8 * SsidLen, u8 * ScanType); +BOOLEAN PeerBeaconAndProbeRspSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 MsgChannel, + u8 *pAddr2, + u8 *pBssid, + char Ssid[], + u8 * pSsidLen, + u8 * pBssType, + u16 * pBeaconPeriod, + u8 * pChannel, + u8 * pNewChannel, + OUT LARGE_INTEGER * pTimestamp, + struct rt_cf_parm * pCfParm, + u16 * pAtimWin, + u16 * pCapabilityInfo, + u8 * pErp, + u8 * pDtimCount, + u8 * pDtimPeriod, + u8 * pBcastFlag, + u8 * pMessageToMe, + u8 SupRate[], + u8 * pSupRateLen, + u8 ExtRate[], + u8 * pExtRateLen, + u8 * pCkipFlag, + u8 * pAironetCellPowerLimit, + struct rt_edca_parm *pEdcaParm, + struct rt_qbss_load_parm *pQbssLoad, + struct rt_qos_capability_parm *pQosCapability, + unsigned long * pRalinkIe, + u8 * pHtCapabilityLen, + u8 * pPreNHtCapabilityLen, + struct rt_ht_capability_ie * pHtCapability, + u8 * AddHtInfoLen, + struct rt_add_ht_info_ie * AddHtInfo, + u8 * NewExtChannel, + u16 * LengthVIE, + struct rt_ndis_802_11_variable_ies *pVIE); + +BOOLEAN PeerAddBAReqActionSanity(struct rt_rtmp_adapter *pAd, + void * pMsg, + unsigned long MsgLen, u8 *pAddr2); + +BOOLEAN PeerAddBARspActionSanity(struct rt_rtmp_adapter *pAd, + void * pMsg, unsigned long MsgLen); + +BOOLEAN PeerDelBAActionSanity(struct rt_rtmp_adapter *pAd, + u8 Wcid, void * pMsg, unsigned long MsgLen); -typedef struct _INF_PCI_CONFIG -{ - PUCHAR CSRBaseAddress; // PCI MMIO Base Address, all access will use -}INF_PCI_CONFIG; +BOOLEAN MlmeAssocReqSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 *pApAddr, + u16 * CapabilityInfo, + unsigned long * Timeout, u16 * ListenIntv); + +BOOLEAN MlmeAuthReqSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 *pAddr, + unsigned long * Timeout, u16 * Alg); -typedef struct _INF_USB_CONFIG -{ - UINT BulkInEpAddr; // bulk-in endpoint address - UINT BulkOutEpAddr[6]; // bulk-out endpoint address +BOOLEAN MlmeStartReqSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + char Ssid[], u8 * Ssidlen); -}INF_USB_CONFIG; +BOOLEAN PeerAuthSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 *pAddr, + u16 * Alg, + u16 * Seq, + u16 * Status, char ChlgText[]); +BOOLEAN PeerAssocRspSanity(struct rt_rtmp_adapter *pAd, void * pMsg, unsigned long MsgLen, u8 *pAddr2, u16 * pCapabilityInfo, u16 * pStatus, u16 * pAid, u8 SupRate[], u8 * pSupRateLen, u8 ExtRate[], u8 * pExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo, /* AP might use this additional ht info IE */ + u8 * pHtCapabilityLen, + u8 * pAddHtInfoLen, + u8 * pNewExtChannelOffset, + struct rt_edca_parm *pEdcaParm, u8 * pCkipFlag); + +BOOLEAN PeerDisassocSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 *pAddr2, u16 * Reason); + +BOOLEAN PeerWpaMessageSanity(struct rt_rtmp_adapter *pAd, + struct rt_eapol_packet * pMsg, + unsigned long MsgLen, + u8 MsgType, struct rt_mac_table_entry *pEntry); + +BOOLEAN PeerDeauthSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 *pAddr2, u16 * Reason); + +BOOLEAN PeerProbeReqSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 *pAddr2, + char Ssid[], u8 * pSsidLen); + +BOOLEAN GetTimBit(char * Ptr, + u16 Aid, + u8 * TimLen, + u8 * BcastFlag, + u8 * DtimCount, + u8 * DtimPeriod, u8 * MessageToMe); +u8 ChannelSanity(struct rt_rtmp_adapter *pAd, u8 channel); -// -// The miniport adapter structure -// -typedef struct _RTMP_ADAPTER -{ - PVOID OS_Cookie; // save specific structure relative to OS - PNET_DEV net_dev; - ULONG VirtualIfCnt; - -#ifdef RT2860 - USHORT LnkCtrlBitMask; - USHORT RLnkCtrlConfiguration; - USHORT RLnkCtrlOffset; - USHORT HostLnkCtrlConfiguration; - USHORT HostLnkCtrlOffset; - USHORT PCIePowerSaveLevel; - BOOLEAN bPCIclkOff; // flag that indicate if the PICE power status in Configuration SPace.. - ULONG CheckDmaBusyCount; // Check Interrupt Status Register Count. - USHORT ThisTbttNumToNextWakeUp; - ULONG SameRxByteCount; +NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity(struct rt_bss_entry *pBss); +BOOLEAN MlmeDelBAReqSanity(struct rt_rtmp_adapter *pAd, + void * Msg, unsigned long MsgLen); -/*****************************************************************************************/ -/* PCI related parameters */ -/*****************************************************************************************/ - PUCHAR CSRBaseAddress; // PCI MMIO Base Address, all access will use +BOOLEAN MlmeAddBAReqSanity(struct rt_rtmp_adapter *pAd, + void * Msg, unsigned long MsgLen, u8 *pAddr2); - UINT int_enable_reg; - UINT int_disable_mask; - UINT int_pending; +unsigned long MakeOutgoingFrame(u8 * Buffer, unsigned long * Length, ...); +void LfsrInit(struct rt_rtmp_adapter *pAd, unsigned long Seed); - RTMP_DMABUF TxBufSpace[NUM_OF_TX_RING]; // Shared memory of all 1st pre-allocated TxBuf associated with each TXD - RTMP_DMABUF RxDescRing; // Shared memory for RX descriptors - RTMP_DMABUF TxDescRing[NUM_OF_TX_RING]; // Shared memory for Tx descriptors - RTMP_TX_RING TxRing[NUM_OF_TX_RING]; // AC0~4 + HCCA -#endif +u8 RandomByte(struct rt_rtmp_adapter *pAd); - NDIS_SPIN_LOCK irq_lock; - UCHAR irq_disabled; +void AsicUpdateAutoFallBackTable(struct rt_rtmp_adapter *pAd, u8 *pTxRate); -#ifdef RT2870 -/*****************************************************************************************/ -/* USB related parameters */ -/*****************************************************************************************/ - struct usb_config_descriptor *config; - UINT BulkInEpAddr; // bulk-in endpoint address - UINT BulkOutEpAddr[6]; // bulk-out endpoint address +void MlmePeriodicExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); - UINT NumberOfPipes; - USHORT BulkOutMaxPacketSize; - USHORT BulkInMaxPacketSize; +void LinkDownExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); - //======Control Flags - LONG PendingIoCount; - ULONG BulkFlags; - BOOLEAN bUsbTxBulkAggre; // Flags for bulk out data priority +void STAMlmePeriodicExec(struct rt_rtmp_adapter *pAd); +void MlmeAutoScan(struct rt_rtmp_adapter *pAd); - //======Timer Thread - RT2870_TIMER_QUEUE TimerQ; - NDIS_SPIN_LOCK TimerQLock; +void MlmeAutoReconnectLastSSID(struct rt_rtmp_adapter *pAd); +BOOLEAN MlmeValidateSSID(u8 *pSsid, u8 SsidLen); - //======Cmd Thread - CmdQ CmdQ; - NDIS_SPIN_LOCK CmdQLock; // CmdQLock spinlock +void MlmeCheckForRoaming(struct rt_rtmp_adapter *pAd, unsigned long Now32); - BOOLEAN TimerFunc_kill; - BOOLEAN mlme_kill; +BOOLEAN MlmeCheckForFastRoaming(struct rt_rtmp_adapter *pAd); +void MlmeDynamicTxRateSwitching(struct rt_rtmp_adapter *pAd); - //======Semaphores (event) - struct semaphore mlme_semaphore; /* to sleep thread on */ - struct semaphore RTUSBCmd_semaphore; /* to sleep thread on */ - struct semaphore RTUSBTimer_semaphore; - struct completion TimerQComplete; - struct completion mlmeComplete; - struct completion CmdQComplete; - wait_queue_head_t *wait; -#endif // RT2870 // +void MlmeSetTxRate(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_rtmp_tx_rate_switch * pTxRate); +void MlmeSelectTxRateTable(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + u8 ** ppTable, + u8 *pTableSize, u8 *pInitTxRateIdx); -/*****************************************************************************************/ - /* Both PCI/USB related parameters */ -/*****************************************************************************************/ +void MlmeCalculateChannelQuality(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pMacEntry, unsigned long Now); +void MlmeCheckPsmChange(struct rt_rtmp_adapter *pAd, unsigned long Now32); -/*****************************************************************************************/ -/* Tx related parameters */ -/*****************************************************************************************/ - BOOLEAN DeQueueRunning[NUM_OF_TX_RING]; // for ensuring RTUSBDeQueuePacket get call once - NDIS_SPIN_LOCK DeQueueLock[NUM_OF_TX_RING]; +void MlmeSetPsmBit(struct rt_rtmp_adapter *pAd, u16 psm); -#ifdef RT2870 - // Data related context and AC specified, 4 AC supported - NDIS_SPIN_LOCK BulkOutLock[6]; // BulkOut spinlock for 4 ACs - NDIS_SPIN_LOCK MLMEBulkOutLock; // MLME BulkOut lock +void MlmeSetTxPreamble(struct rt_rtmp_adapter *pAd, u16 TxPreamble); - HT_TX_CONTEXT TxContext[NUM_OF_TX_RING]; - NDIS_SPIN_LOCK TxContextQueueLock[NUM_OF_TX_RING]; // TxContextQueue spinlock +void UpdateBasicRateBitmap(struct rt_rtmp_adapter *pAd); - // 4 sets of Bulk Out index and pending flag - UCHAR NextBulkOutIndex[4]; // only used for 4 EDCA bulkout pipe +void MlmeUpdateTxRates(struct rt_rtmp_adapter *pAd, + IN BOOLEAN bLinkUp, u8 apidx); - BOOLEAN BulkOutPending[6]; // used for total 6 bulkout pipe - UCHAR bulkResetPipeid; - BOOLEAN MgmtBulkPending; - ULONG bulkResetReq[6]; -#endif // RT2870 // +void MlmeUpdateHtTxRates(struct rt_rtmp_adapter *pAd, u8 apidx); - // resource for software backlog queues - QUEUE_HEADER TxSwQueue[NUM_OF_TX_RING]; // 4 AC + 1 HCCA - NDIS_SPIN_LOCK TxSwQueueLock[NUM_OF_TX_RING]; // TxSwQueue spinlock +void RTMPCheckRates(struct rt_rtmp_adapter *pAd, + IN u8 SupRate[], IN u8 * SupRateLen); - RTMP_DMABUF MgmtDescRing; // Shared memory for MGMT descriptors - RTMP_MGMT_RING MgmtRing; - NDIS_SPIN_LOCK MgmtRingLock; // Prio Ring spinlock +BOOLEAN RTMPCheckChannel(struct rt_rtmp_adapter *pAd, + u8 CentralChannel, u8 Channel); +BOOLEAN RTMPCheckHt(struct rt_rtmp_adapter *pAd, + u8 Wcid, + struct rt_ht_capability_ie * pHtCapability, + struct rt_add_ht_info_ie * pAddHtInfo); -/*****************************************************************************************/ -/* Rx related parameters */ -/*****************************************************************************************/ -#ifdef RT2860 - RTMP_RX_RING RxRing; - NDIS_SPIN_LOCK RxRingLock; // Rx Ring spinlock -#endif -#ifdef RT2870 - RX_CONTEXT RxContext[RX_RING_SIZE]; // 1 for redundant multiple IRP bulk in. - NDIS_SPIN_LOCK BulkInLock; // BulkIn spinlock for 4 ACs - UCHAR PendingRx; // The Maxima pending Rx value should be RX_RING_SIZE. - UCHAR NextRxBulkInIndex; // Indicate the current RxContext Index which hold by Host controller. - UCHAR NextRxBulkInReadIndex; // Indicate the current RxContext Index which driver can read & process it. - ULONG NextRxBulkInPosition; // Want to contatenate 2 URB buffer while 1st is bulkin failed URB. This Position is 1st URB TransferLength. - ULONG TransferBufferLength; // current length of the packet buffer - ULONG ReadPosition; // current read position in a packet buffer -#endif // RT2870 // +void StaQuickResponeForRateUpExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, + void *SystemSpecific3); +void RTMPUpdateMlmeRate(struct rt_rtmp_adapter *pAd); -/*****************************************************************************************/ -/* ASIC related parameters */ -/*****************************************************************************************/ - UINT32 MACVersion; // MAC version. Record rt2860C(0x28600100) or rt2860D (0x28600101).. - - // --------------------------- - // E2PROM - // --------------------------- - ULONG EepromVersion; // byte 0: version, byte 1: revision, byte 2~3: unused - UCHAR EEPROMAddressNum; // 93c46=6 93c66=8 - USHORT EEPROMDefaultValue[NUM_EEPROM_BBP_PARMS]; -#ifdef RT2870 - BOOLEAN EepromAccess; -#endif - ULONG FirmwareVersion; // byte 0: Minor version, byte 1: Major version, otherwise unused. - - // --------------------------- - // BBP Control - // --------------------------- - UCHAR BbpWriteLatch[140]; // record last BBP register value written via BBP_IO_WRITE/BBP_IO_WRITE_VY_REG_ID - UCHAR BbpRssiToDbmDelta; - BBP_R66_TUNING BbpTuning; - - // ---------------------------- - // RFIC control - // ---------------------------- - UCHAR RfIcType; // RFIC_xxx - ULONG RfFreqOffset; // Frequency offset for channel switching - RTMP_RF_REGS LatchRfRegs; // latch th latest RF programming value since RF IC doesn't support READ - - EEPROM_ANTENNA_STRUC Antenna; // Since ANtenna definition is different for a & g. We need to save it for future reference. - EEPROM_NIC_CONFIG2_STRUC NicConfig2; - - // This soft Rx Antenna Diversity mechanism is used only when user set - // RX Antenna = DIVERSITY ON - SOFT_RX_ANT_DIVERSITY RxAnt; - - UCHAR RFProgSeq; - CHANNEL_TX_POWER TxPower[MAX_NUM_OF_CHANNELS]; // Store Tx power value for all channels. - CHANNEL_TX_POWER ChannelList[MAX_NUM_OF_CHANNELS]; // list all supported channels for site survey - CHANNEL_11J_TX_POWER TxPower11J[MAX_NUM_OF_11JCHANNELS]; // 802.11j channel and bw - CHANNEL_11J_TX_POWER ChannelList11J[MAX_NUM_OF_11JCHANNELS]; // list all supported channels for site survey - - UCHAR ChannelListNum; // number of channel in ChannelList[] - UCHAR Bbp94; - BOOLEAN BbpForCCK; - ULONG Tx20MPwrCfgABand[5]; - ULONG Tx20MPwrCfgGBand[5]; - ULONG Tx40MPwrCfgABand[5]; - ULONG Tx40MPwrCfgGBand[5]; - - BOOLEAN bAutoTxAgcA; // Enable driver auto Tx Agc control - UCHAR TssiRefA; // Store Tssi reference value as 25 temperature. - UCHAR TssiPlusBoundaryA[5]; // Tssi boundary for increase Tx power to compensate. - UCHAR TssiMinusBoundaryA[5]; // Tssi boundary for decrease Tx power to compensate. - UCHAR TxAgcStepA; // Store Tx TSSI delta increment / decrement value - CHAR TxAgcCompensateA; // Store the compensation (TxAgcStep * (idx-1)) - - BOOLEAN bAutoTxAgcG; // Enable driver auto Tx Agc control - UCHAR TssiRefG; // Store Tssi reference value as 25 temperature. - UCHAR TssiPlusBoundaryG[5]; // Tssi boundary for increase Tx power to compensate. - UCHAR TssiMinusBoundaryG[5]; // Tssi boundary for decrease Tx power to compensate. - UCHAR TxAgcStepG; // Store Tx TSSI delta increment / decrement value - CHAR TxAgcCompensateG; // Store the compensation (TxAgcStep * (idx-1)) - - //+++For RT2870, the parameteres is start from BGRssiOffset1 ~ BGRssiOffset3 - CHAR BGRssiOffset0; // Store B/G RSSI#0 Offset value on EEPROM 0x46h - CHAR BGRssiOffset1; // Store B/G RSSI#1 Offset value - CHAR BGRssiOffset2; // Store B/G RSSI#2 Offset value - //--- - - //+++For RT2870, the parameteres is start from ARssiOffset1 ~ ARssiOffset3 - CHAR ARssiOffset0; // Store A RSSI#0 Offset value on EEPROM 0x4Ah - CHAR ARssiOffset1; // Store A RSSI#1 Offset value - CHAR ARssiOffset2; // Store A RSSI#2 Offset value - //--- - - CHAR BLNAGain; // Store B/G external LNA#0 value on EEPROM 0x44h - CHAR ALNAGain0; // Store A external LNA#0 value for ch36~64 - CHAR ALNAGain1; // Store A external LNA#1 value for ch100~128 - CHAR ALNAGain2; // Store A external LNA#2 value for ch132~165 - - // ---------------------------- - // LED control - // ---------------------------- - MCU_LEDCS_STRUC LedCntl; - USHORT Led1; // read from EEPROM 0x3c - USHORT Led2; // EEPROM 0x3e - USHORT Led3; // EEPROM 0x40 - UCHAR LedIndicatorStregth; - UCHAR RssiSingalstrengthOffet; - BOOLEAN bLedOnScanning; - UCHAR LedStatus; +char RTMPMaxRssi(struct rt_rtmp_adapter *pAd, + char Rssi0, char Rssi1, char Rssi2); -/*****************************************************************************************/ -/* 802.11 related parameters */ -/*****************************************************************************************/ - // outgoing BEACON frame buffer and corresponding TXD - TXWI_STRUC BeaconTxWI; - PUCHAR BeaconBuf; - USHORT BeaconOffset[HW_BEACON_MAX_COUNT]; +#ifdef RT30xx +void AsicSetRxAnt(struct rt_rtmp_adapter *pAd, u8 Ant); - // pre-build PS-POLL and NULL frame upon link up. for efficiency purpose. - PSPOLL_FRAME PsPollFrame; - HEADER_802_11 NullFrame; +void RTMPFilterCalibration(struct rt_rtmp_adapter *pAd); -#ifdef RT2870 - TX_CONTEXT BeaconContext[BEACON_RING_SIZE]; - TX_CONTEXT NullContext; - TX_CONTEXT PsPollContext; - TX_CONTEXT RTSContext; -#endif // RT2870 // +#ifdef RTMP_EFUSE_SUPPORT +/*2008/09/11:KH add to support efuse<-- */ +int set_eFuseGetFreeBlockCount_Proc(struct rt_rtmp_adapter *pAd, char *arg); +int set_eFusedump_Proc(struct rt_rtmp_adapter *pAd, char *arg); +void eFusePhysicalReadRegisters(struct rt_rtmp_adapter *pAd, + u16 Offset, + u16 Length, u16 * pData); -//=========AP=========== +int RtmpEfuseSupportCheck(struct rt_rtmp_adapter *pAd); +void eFuseGetFreeBlockCount(struct rt_rtmp_adapter *pAd, u32 *EfuseFreeBlock); -//=======STA=========== -/* Modified by Wu Xi-Kun 4/21/2006 */ - // ----------------------------------------------- - // STA specific configuration & operation status - // used only when pAd->OpMode == OPMODE_STA - // ----------------------------------------------- - STA_ADMIN_CONFIG StaCfg; // user desired settings - STA_ACTIVE_CONFIG StaActive; // valid only when ADHOC_ON(pAd) || INFRA_ON(pAd) - CHAR nickname[IW_ESSID_MAX_SIZE+1]; // nickname, only used in the iwconfig i/f - NDIS_MEDIA_STATE PreMediaState; - -//=======Common=========== - // OP mode: either AP or STA - UCHAR OpMode; // OPMODE_STA, OPMODE_AP - - NDIS_MEDIA_STATE IndicateMediaState; // Base on Indication state, default is NdisMediaStateDisConnected - - - // configuration: read from Registry & E2PROM - BOOLEAN bLocalAdminMAC; // Use user changed MAC - UCHAR PermanentAddress[MAC_ADDR_LEN]; // Factory default MAC address - UCHAR CurrentAddress[MAC_ADDR_LEN]; // User changed MAC address - - // ------------------------------------------------------ - // common configuration to both OPMODE_STA and OPMODE_AP - // ------------------------------------------------------ - COMMON_CONFIG CommonCfg; - MLME_STRUCT Mlme; - - // AP needs those vaiables for site survey feature. - MLME_AUX MlmeAux; // temporary settings used during MLME state machine - BSS_TABLE ScanTab; // store the latest SCAN result - - //About MacTab, the sta driver will use #0 and #1 for multicast and AP. - MAC_TABLE MacTab; // ASIC on-chip WCID entry table. At TX, ASIC always use key according to this on-chip table. - NDIS_SPIN_LOCK MacTabLock; - - BA_TABLE BATable; - - NDIS_SPIN_LOCK BATabLock; - RALINK_TIMER_STRUCT RECBATimer; - - // encryption/decryption KEY tables - CIPHER_KEY SharedKey[MAX_MBSSID_NUM][4]; // STA always use SharedKey[BSS0][0..3] - - // RX re-assembly buffer for fragmentation - FRAGMENT_FRAME FragFrame; // Frame storage for fragment frame - - // various Counters - COUNTER_802_3 Counters8023; // 802.3 counters - COUNTER_802_11 WlanCounters; // 802.11 MIB counters - COUNTER_RALINK RalinkCounters; // Ralink propriety counters - COUNTER_DRS DrsCounters; // counters for Dynamic TX Rate Switching - PRIVATE_STRUC PrivateInfo; // Private information & counters - - // flags, see fRTMP_ADAPTER_xxx flags - ULONG Flags; // Represent current device status -#ifdef RT2860 - ULONG PSFlags; // Power Save operation flag. -#endif +int eFuse_init(struct rt_rtmp_adapter *pAd); +/*2008/09/11:KH add to support efuse--> */ +#endif /* RTMP_EFUSE_SUPPORT // */ - // current TX sequence # - USHORT Sequence; +/* add by johnli, RF power sequence setup */ +void RT30xxLoadRFNormalModeSetup(struct rt_rtmp_adapter *pAd); - // Control disconnect / connect event generation - //+++Didn't used anymore - ULONG LinkDownTime; - //--- - ULONG LastRxRate; - ULONG LastTxRate; - //+++Used only for Station - BOOLEAN bConfigChanged; // Config Change flag for the same SSID setting - //--- +void RT30xxLoadRFSleepModeSetup(struct rt_rtmp_adapter *pAd); - ULONG ExtraInfo; // Extra information for displaying status - ULONG SystemErrorBitmap; // b0: E2PROM version error +void RT30xxReverseRFSleepModeSetup(struct rt_rtmp_adapter *pAd); +/* end johnli */ - //+++Didn't used anymore - ULONG MacIcVersion; // MAC/BBP serial interface issue solved after ver.D - //--- +#ifdef RT3070 +void NICInitRT3070RFRegisters(struct rt_rtmp_adapter *pAd); +#endif /* RT3070 // */ +#ifdef RT3090 +void NICInitRT3090RFRegisters(struct rt_rtmp_adapter *pAd); +#endif /* RT3090 // */ - // --------------------------- - // System event log - // --------------------------- - RT_802_11_EVENT_TABLE EventTab; +void RT30xxHaltAction(struct rt_rtmp_adapter *pAd); +void RT30xxSetRxAnt(struct rt_rtmp_adapter *pAd, u8 Ant); +#endif /* RT30xx // */ - BOOLEAN HTCEnable; +void AsicEvaluateRxAnt(struct rt_rtmp_adapter *pAd); - /*****************************************************************************************/ - /* Statistic related parameters */ - /*****************************************************************************************/ -#ifdef RT2870 - ULONG BulkOutDataOneSecCount; - ULONG BulkInDataOneSecCount; - ULONG BulkLastOneSecCount; // BulkOutDataOneSecCount + BulkInDataOneSecCount - ULONG watchDogRxCnt; - ULONG watchDogRxOverFlowCnt; - ULONG watchDogTxPendingCnt[NUM_OF_TX_RING]; -#endif // RT2870 // - - BOOLEAN bUpdateBcnCntDone; - ULONG watchDogMacDeadlock; // prevent MAC/BBP into deadlock condition - // ---------------------------- - // DEBUG paramerts - // ---------------------------- - BOOLEAN bBanAllBaSetup; - BOOLEAN bPromiscuous; - - // ---------------------------- - // rt2860c emulation-use Parameters - // ---------------------------- - ULONG rtsaccu[30]; - ULONG ctsaccu[30]; - ULONG cfendaccu[30]; - ULONG bacontent[16]; - ULONG rxint[RX_RING_SIZE+1]; - UCHAR rcvba[60]; - BOOLEAN bLinkAdapt; - BOOLEAN bForcePrintTX; - BOOLEAN bForcePrintRX; - BOOLEAN bDisablescanning; //defined in RT2870 USB - BOOLEAN bStaFifoTest; - BOOLEAN bProtectionTest; - BOOLEAN bHCCATest; - BOOLEAN bGenOneHCCA; - BOOLEAN bBroadComHT; - //+++Following add from RT2870 USB. - ULONG BulkOutReq; - ULONG BulkOutComplete; - ULONG BulkOutCompleteOther; - ULONG BulkOutCompleteCancel; // seems not use now? - ULONG BulkInReq; - ULONG BulkInComplete; - ULONG BulkInCompleteFail; - //--- - - struct wificonf WIFItestbed; +void AsicRxAntEvalTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); - struct reordering_mpdu_pool mpdu_blk_pool; +void APSDPeriodicExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); - ULONG OneSecondnonBEpackets; // record non BE packets per second +BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry); - struct iw_statistics iw_stats; +u8 RTMPStaFixedTxMode(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry); - struct net_device_stats stats; +void RTMPUpdateLegacyTxSetting(u8 fixed_tx_mode, struct rt_mac_table_entry *pEntry); - ULONG TbttTickCount; -#ifdef PCI_MSI_SUPPORT - BOOLEAN HaveMsi; -#endif // PCI_MSI_SUPPORT // +BOOLEAN RTMPAutoRateSwitchCheck(struct rt_rtmp_adapter *pAd); +int MlmeInit(struct rt_rtmp_adapter *pAd); - UCHAR is_on; +void MlmeHandler(struct rt_rtmp_adapter *pAd); -#define TIME_BASE (1000000/OS_HZ) -#define TIME_ONE_SECOND (1000000/TIME_BASE) - UCHAR flg_be_adjust; - ULONG be_adjust_last_time; +void MlmeHalt(struct rt_rtmp_adapter *pAd); +void MlmeResetRalinkCounters(struct rt_rtmp_adapter *pAd); +void BuildChannelList(struct rt_rtmp_adapter *pAd); - UINT8 PM_FlgSuspend; +u8 FirstChannel(struct rt_rtmp_adapter *pAd); -#ifdef RT2870 - BOOLEAN bUseEfuse; -#endif -} RTMP_ADAPTER, *PRTMP_ADAPTER; +u8 NextChannel(struct rt_rtmp_adapter *pAd, u8 channel); -// -// Cisco IAPP format -// -typedef struct _CISCO_IAPP_CONTENT_ -{ - USHORT Length; //IAPP Length - UCHAR MessageType; //IAPP type - UCHAR FunctionCode; //IAPP function type - UCHAR DestinaionMAC[MAC_ADDR_LEN]; - UCHAR SourceMAC[MAC_ADDR_LEN]; - USHORT Tag; //Tag(element IE) - Adjacent AP report - USHORT TagLength; //Length of element not including 4 byte header - UCHAR OUI[4]; //0x00, 0x40, 0x96, 0x00 - UCHAR PreviousAP[MAC_ADDR_LEN]; //MAC Address of access point - USHORT Channel; - USHORT SsidLen; - UCHAR Ssid[MAX_LEN_OF_SSID]; - USHORT Seconds; //Seconds that the client has been disassociated. -} CISCO_IAPP_CONTENT, *PCISCO_IAPP_CONTENT; +void ChangeToCellPowerLimit(struct rt_rtmp_adapter *pAd, + u8 AironetCellPowerLimit); -#define DELAYINTMASK 0x0003fffb -#define INTMASK 0x0003fffb -#define IndMask 0x0003fffc -#define RxINT 0x00000005 // Delayed Rx or indivi rx -#define TxDataInt 0x000000fa // Delayed Tx or indivi tx -#define TxMgmtInt 0x00000102 // Delayed Tx or indivi tx -#define TxCoherent 0x00020000 // tx coherent -#define RxCoherent 0x00010000 // rx coherent -#define McuCommand 0x00000200 // mcu -#define PreTBTTInt 0x00001000 // Pre-TBTT interrupt -#define TBTTInt 0x00000800 // TBTT interrupt -#define GPTimeOutInt 0x00008000 // GPtimeout interrupt -#define AutoWakeupInt 0x00004000 // AutoWakeupInt interrupt -#define FifoStaFullInt 0x00002000 // fifo statistics full interrupt - - -typedef struct _RX_BLK_ -{ - RT28XX_RXD_STRUC RxD; - PRXWI_STRUC pRxWI; - PHEADER_802_11 pHeader; - PNDIS_PACKET pRxPacket; - UCHAR *pData; - USHORT DataSize; - USHORT Flags; - UCHAR UserPriority; // for calculate TKIP MIC using -} RX_BLK; +/* */ +/* Prototypes of function definition in rtmp_tkip.c */ +/* */ +void RTMPInitTkipEngine(struct rt_rtmp_adapter *pAd, + u8 *pTKey, + u8 KeyId, + u8 *pTA, + u8 *pMICKey, + u8 *pTSC, unsigned long *pIV16, unsigned long *pIV32); +void RTMPInitMICEngine(struct rt_rtmp_adapter *pAd, + u8 *pKey, + u8 *pDA, + u8 *pSA, u8 UserPriority, u8 *pMICKey); -#define RX_BLK_SET_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags |= _flag) -#define RX_BLK_TEST_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags & _flag) -#define RX_BLK_CLEAR_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags &= ~(_flag)) +BOOLEAN RTMPTkipCompareMICValue(struct rt_rtmp_adapter *pAd, + u8 *pSrc, + u8 *pDA, + u8 *pSA, + u8 *pMICKey, + u8 UserPriority, u32 Len); +void RTMPCalculateMICValue(struct rt_rtmp_adapter *pAd, + void *pPacket, + u8 *pEncap, + struct rt_cipher_key *pKey, u8 apidx); -#define fRX_WDS 0x0001 -#define fRX_AMSDU 0x0002 -#define fRX_ARALINK 0x0004 -#define fRX_HTC 0x0008 -#define fRX_PAD 0x0010 -#define fRX_AMPDU 0x0020 -#define fRX_QOS 0x0040 -#define fRX_INFRA 0x0080 -#define fRX_EAP 0x0100 -#define fRX_MESH 0x0200 -#define fRX_APCLI 0x0400 -#define fRX_DLS 0x0800 -#define fRX_WPI 0x1000 +void RTMPTkipAppendByte(struct rt_tkip_key_info *pTkip, u8 uChar); -#define LENGTH_AMSDU_SUBFRAMEHEAD 14 -#define LENGTH_ARALINK_SUBFRAMEHEAD 14 -#define LENGTH_ARALINK_HEADER_FIELD 2 +void RTMPTkipAppend(struct rt_tkip_key_info *pTkip, u8 *pSrc, u32 nBytes); -#define TX_UNKOWN_FRAME 0x00 -#define TX_MCAST_FRAME 0x01 -#define TX_LEGACY_FRAME 0x02 -#define TX_AMPDU_FRAME 0x04 -#define TX_AMSDU_FRAME 0x08 -#define TX_RALINK_FRAME 0x10 -#define TX_FRAG_FRAME 0x20 +void RTMPTkipGetMIC(struct rt_tkip_key_info *pTkip); +BOOLEAN RTMPSoftDecryptTKIP(struct rt_rtmp_adapter *pAd, + u8 *pData, + unsigned long DataByteCnt, + u8 UserPriority, struct rt_cipher_key *pWpaKey); -// Currently the sizeof(TX_BLK) is 148 bytes. -typedef struct _TX_BLK_ -{ - UCHAR QueIdx; - UCHAR TxFrameType; // Indicate the Transmission type of the all frames in one batch - UCHAR TotalFrameNum; // Total frame number want to send-out in one batch - USHORT TotalFragNum; // Total frame fragments required in one batch - USHORT TotalFrameLen; // Total length of all frames want to send-out in one batch - - QUEUE_HEADER TxPacketList; - MAC_TABLE_ENTRY *pMacEntry; // NULL: packet with 802.11 RA field is multicast/broadcast address - HTTRANSMIT_SETTING *pTransmit; - - // Following structure used for the characteristics of a specific packet. - PNDIS_PACKET pPacket; - PUCHAR pSrcBufHeader; // Reference to the head of sk_buff->data - PUCHAR pSrcBufData; // Reference to the sk_buff->data, will changed depends on hanlding progresss - UINT SrcBufLen; // Length of packet payload which not including Layer 2 header - PUCHAR pExtraLlcSnapEncap; // NULL means no extra LLC/SNAP is required - UCHAR HeaderBuf[80]; // TempBuffer for TX_INFO + TX_WI + 802.11 Header + padding + AMSDU SubHeader + LLC/SNAP - UCHAR MpduHeaderLen; // 802.11 header length NOT including the padding - UCHAR HdrPadLen; // recording Header Padding Length; - UCHAR apidx; // The interface associated to this packet - UCHAR Wcid; // The MAC entry associated to this packet - UCHAR UserPriority; // priority class of packet - UCHAR FrameGap; // what kind of IFS this packet use - UCHAR MpduReqNum; // number of fragments of this frame - UCHAR TxRate; // TODO: Obsoleted? Should change to MCS? - UCHAR CipherAlg; // cipher alogrithm - PCIPHER_KEY pKey; - - - - USHORT Flags; //See following definitions for detail. - - //YOU SHOULD NOT TOUCH IT! Following parameters are used for hardware-depended layer. - ULONG Priv; // Hardware specific value saved in here. -} TX_BLK, *PTX_BLK; - - -#define fTX_bRtsRequired 0x0001 // Indicate if need send RTS frame for protection. Not used in RT2860/RT2870. -#define fTX_bAckRequired 0x0002 // the packet need ack response -#define fTX_bPiggyBack 0x0004 // Legacy device use Piggback or not -#define fTX_bHTRate 0x0008 // allow to use HT rate -#define fTX_bForceNonQoS 0x0010 // force to transmit frame without WMM-QoS in HT mode -#define fTX_bAllowFrag 0x0020 // allow to fragment the packet, A-MPDU, A-MSDU, A-Ralink is not allowed to fragment -#define fTX_bMoreData 0x0040 // there are more data packets in PowerSave Queue -#define fTX_bWMM 0x0080 // QOS Data +BOOLEAN RTMPSoftDecryptAES(struct rt_rtmp_adapter *pAd, + u8 *pData, + unsigned long DataByteCnt, struct rt_cipher_key *pWpaKey); -#define fTX_bClearEAPFrame 0x0100 +/* */ +/* Prototypes of function definition in cmm_info.c */ +/* */ +int RT_CfgSetCountryRegion(struct rt_rtmp_adapter *pAd, char *arg, int band); -#define TX_BLK_ASSIGN_FLAG(_pTxBlk, _flag, value) \ - do { \ - if (value) \ - (_pTxBlk->Flags |= _flag) \ - else \ - (_pTxBlk->Flags &= ~(_flag)) \ - }while(0) +int RT_CfgSetWirelessMode(struct rt_rtmp_adapter *pAd, char *arg); -#define TX_BLK_SET_FLAG(_pTxBlk, _flag) (_pTxBlk->Flags |= _flag) -#define TX_BLK_TEST_FLAG(_pTxBlk, _flag) (((_pTxBlk->Flags & _flag) == _flag) ? 1 : 0) -#define TX_BLK_CLEAR_FLAG(_pTxBlk, _flag) (_pTxBlk->Flags &= ~(_flag)) +int RT_CfgSetShortSlot(struct rt_rtmp_adapter *pAd, char *arg); +int RT_CfgSetWepKey(struct rt_rtmp_adapter *pAd, + char *keyString, + struct rt_cipher_key *pSharedKey, int keyIdx); +int RT_CfgSetWPAPSKKey(struct rt_rtmp_adapter *pAd, + char *keyString, + u8 * pHashStr, + int hashStrLen, u8 *pPMKBuf); +/* */ +/* Prototypes of function definition in cmm_info.c */ +/* */ +void RTMPWPARemoveAllKeys(struct rt_rtmp_adapter *pAd); +void RTMPSetPhyMode(struct rt_rtmp_adapter *pAd, unsigned long phymode); -//------------------------------------------------------------------------------------------ +void RTMPUpdateHTIE(struct rt_ht_capability *pRtHt, + u8 * pMcsSet, + struct rt_ht_capability_ie * pHtCapability, + struct rt_add_ht_info_ie * pAddHtInfo); -#ifdef RT2860 -// -// Enable & Disable NIC interrupt via writing interrupt mask register -// Since it use ADAPTER structure, it have to be put after structure definition. -// -__inline VOID NICDisableInterrupt( - IN PRTMP_ADAPTER pAd) -{ - RTMP_IO_WRITE32(pAd, INT_MASK_CSR, 0x0); // 0: disable - //RTMP_IO_WRITE32(pAd, PBF_INT_ENA, 0x0); // 0x418 is for firmware . SW doesn't handle here. - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE); -} +void RTMPAddWcidAttributeEntry(struct rt_rtmp_adapter *pAd, + u8 BssIdx, + u8 KeyIdx, + u8 CipherAlg, struct rt_mac_table_entry *pEntry); -__inline VOID NICEnableInterrupt( - IN PRTMP_ADAPTER pAd) -{ - // - // Flag "fOP_STATUS_DOZE" On, means ASIC put to sleep, else means ASIC WakeUp - // To prevent System hang, we should enalbe the interrupt when - // ASIC is already Wake Up. - // - // RT2661 => when ASIC is sleeping, MAC register cannot be read and written. - // RT2860 => when ASIC is sleeping, MAC register can be read and written. - //if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - RTMP_IO_WRITE32(pAd, INT_MASK_CSR, pAd->int_enable_reg /*DELAYINTMASK*/); // 1:enable - } - //else - // DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_DOZE !\n")); +char *GetEncryptType(char enc); - //RTMP_IO_WRITE32(pAd, PBF_INT_ENA, 0x00000030); // 1 : enable - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE); -} +char *GetAuthMode(char auth); -static inline VOID ConvertMulticastIP2MAC( - IN PUCHAR pIpAddr, - IN PUCHAR *ppMacAddr, - IN UINT16 ProtoType) -{ - if (pIpAddr == NULL) - return; +void RTMPSetHT(struct rt_rtmp_adapter *pAd, struct rt_oid_set_ht_phymode *pHTPhyMode); - if (ppMacAddr == NULL || *ppMacAddr == NULL) - return; +void RTMPSetIndividualHT(struct rt_rtmp_adapter *pAd, u8 apidx); - switch (ProtoType) - { - case ETH_P_IPV6: -// memset(*ppMacAddr, 0, ETH_LENGTH_OF_ADDRESS); - *(*ppMacAddr) = 0x33; - *(*ppMacAddr + 1) = 0x33; - *(*ppMacAddr + 2) = pIpAddr[12]; - *(*ppMacAddr + 3) = pIpAddr[13]; - *(*ppMacAddr + 4) = pIpAddr[14]; - *(*ppMacAddr + 5) = pIpAddr[15]; - break; - - case ETH_P_IP: - default: -// memset(*ppMacAddr, 0, ETH_LENGTH_OF_ADDRESS); - *(*ppMacAddr) = 0x01; - *(*ppMacAddr + 1) = 0x00; - *(*ppMacAddr + 2) = 0x5e; - *(*ppMacAddr + 3) = pIpAddr[1] & 0x7f; - *(*ppMacAddr + 4) = pIpAddr[2]; - *(*ppMacAddr + 5) = pIpAddr[3]; - break; - } +void RTMPSendWirelessEvent(struct rt_rtmp_adapter *pAd, + u16 Event_flag, + u8 *pAddr, u8 BssIdx, char Rssi); - return; -} -#endif /* RT2860 */ - -// -// Private routines in rtmp_init.c -// -NDIS_STATUS RTMPAllocAdapterBlock( - IN PVOID handle, - OUT PRTMP_ADAPTER *ppAdapter - ); - -NDIS_STATUS RTMPAllocTxRxRingMemory( - IN PRTMP_ADAPTER pAd - ); - -NDIS_STATUS RTMPReadParametersHook( - IN PRTMP_ADAPTER pAd - ); - -VOID RTMPFreeAdapter( - IN PRTMP_ADAPTER pAd - ); - -NDIS_STATUS NICReadRegParameters( - IN PRTMP_ADAPTER pAd, - IN NDIS_HANDLE WrapperConfigurationContext - ); - -#ifdef RT2870 -VOID NICInitRT30xxRFRegisters( - IN PRTMP_ADAPTER pAd); -#endif // RT2870 // - -VOID NICReadEEPROMParameters( - IN PRTMP_ADAPTER pAd, - IN PUCHAR mac_addr); - -VOID NICInitAsicFromEEPROM( - IN PRTMP_ADAPTER pAd); - -VOID NICInitTxRxRingAndBacklogQueue( - IN PRTMP_ADAPTER pAd); - -NDIS_STATUS NICInitializeAdapter( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bHardReset); - -NDIS_STATUS NICInitializeAsic( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bHardReset); -#ifdef RT2860 -VOID NICRestoreBBPValue( - IN PRTMP_ADAPTER pAd); -#endif -VOID NICIssueReset( - IN PRTMP_ADAPTER pAd); +char ConvertToRssi(struct rt_rtmp_adapter *pAd, char Rssi, u8 RssiNumber); -VOID RTMPRingCleanUp( - IN PRTMP_ADAPTER pAd, - IN UCHAR RingType); +/*=================================== + Function prototype in cmm_wpa.c + =================================== */ +void RTMPToWirelessSta(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + u8 *pHeader802_3, + u32 HdrLen, + u8 *pData, + u32 DataLen, IN BOOLEAN bClearFrame); -VOID UserCfgInit( - IN PRTMP_ADAPTER pAd); +void WpaDerivePTK(struct rt_rtmp_adapter *pAd, + u8 * PMK, + u8 * ANonce, + u8 * AA, + u8 * SNonce, + u8 * SA, u8 * output, u32 len); -VOID NICResetFromError( - IN PRTMP_ADAPTER pAd); +void GenRandom(struct rt_rtmp_adapter *pAd, u8 * macAddr, u8 * random); -VOID NICEraseFirmware( - IN PRTMP_ADAPTER pAd); +BOOLEAN RTMPCheckWPAframe(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + u8 *pData, + unsigned long DataByteCount, u8 FromWhichBSSID); -NDIS_STATUS NICLoadFirmware( - IN PRTMP_ADAPTER pAd); +void AES_GTK_KEY_UNWRAP(u8 * key, + u8 * plaintext, + u32 c_len, u8 * ciphertext); -NDIS_STATUS NICLoadRateSwitchingParams( - IN PRTMP_ADAPTER pAd); +BOOLEAN RTMPParseEapolKeyData(struct rt_rtmp_adapter *pAd, + u8 *pKeyData, + u8 KeyDataLen, + u8 GroupKeyIndex, + u8 MsgType, + IN BOOLEAN bWPA2, struct rt_mac_table_entry *pEntry); -BOOLEAN NICCheckForHang( - IN PRTMP_ADAPTER pAd); +void ConstructEapolMsg(struct rt_mac_table_entry *pEntry, + u8 GroupKeyWepStatus, + u8 MsgType, + u8 DefaultKeyIdx, + u8 * KeyNonce, + u8 * TxRSC, + u8 * GTK, + u8 * RSNIE, + u8 RSNIE_Len, struct rt_eapol_packet * pMsg); -VOID NICUpdateFifoStaCounters( - IN PRTMP_ADAPTER pAd); +int RTMPSoftDecryptBroadCastData(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, + IN NDIS_802_11_ENCRYPTION_STATUS + GroupCipher, + struct rt_cipher_key *pShard_key); -VOID NICUpdateRawCounters( - IN PRTMP_ADAPTER pAd); +void RTMPMakeRSNIE(struct rt_rtmp_adapter *pAd, + u32 AuthMode, u32 WepStatus, u8 apidx); -ULONG RTMPNotAllZero( - IN PVOID pSrc1, - IN ULONG Length); +/* */ +/* function prototype in ap_wpa.c */ +/* */ +void RTMPGetTxTscFromAsic(struct rt_rtmp_adapter *pAd, + u8 apidx, u8 *pTxTsc); -VOID RTMPZeroMemory( - IN PVOID pSrc, - IN ULONG Length); +void APInstallPairwiseKey(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry); -ULONG RTMPCompareMemory( - IN PVOID pSrc1, - IN PVOID pSrc2, - IN ULONG Length); +u32 APValidateRSNIE(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + u8 *pRsnIe, u8 rsnie_len); -VOID RTMPMoveMemory( - OUT PVOID pDest, - IN PVOID pSrc, - IN ULONG Length); +void HandleCounterMeasure(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry); -VOID AtoH( - char *src, - UCHAR *dest, - int destlen); +void WPAStart4WayHS(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, unsigned long TimeInterval); -UCHAR BtoH( - char ch); +void WPAStart2WayGroupHS(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry); -VOID RTMPPatchMacBbpBug( - IN PRTMP_ADAPTER pAd); +void PeerPairMsg1Action(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem); -VOID RTMPInitTimer( - IN PRTMP_ADAPTER pAd, - IN PRALINK_TIMER_STRUCT pTimer, - IN PVOID pTimerFunc, - IN PVOID pData, - IN BOOLEAN Repeat); +void PeerPairMsg2Action(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem); -VOID RTMPSetTimer( - IN PRALINK_TIMER_STRUCT pTimer, - IN ULONG Value); +void PeerPairMsg3Action(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem); +void PeerPairMsg4Action(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem); -VOID RTMPModTimer( - IN PRALINK_TIMER_STRUCT pTimer, - IN ULONG Value); +void PeerGroupMsg1Action(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem); -VOID RTMPCancelTimer( - IN PRALINK_TIMER_STRUCT pTimer, - OUT BOOLEAN *pCancelled); - -VOID RTMPSetLED( - IN PRTMP_ADAPTER pAd, - IN UCHAR Status); - -VOID RTMPSetSignalLED( - IN PRTMP_ADAPTER pAd, - IN NDIS_802_11_RSSI Dbm); - -VOID RTMPEnableRxTx( - IN PRTMP_ADAPTER pAd); - -// -// prototype in action.c -// -VOID ActionStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID MlmeADDBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeDELBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeDLSAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeInvalidAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeQOSAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerAddBAReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerAddBARspAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerDelBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID SendPSMPAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR Psmp); - -VOID PeerRMAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerPublicAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerHTAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerQOSAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID RECBATimerTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID ORIBATimerTimeout( - IN PRTMP_ADAPTER pAd); - -VOID SendRefreshBAR( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry); - -VOID ActHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PHEADER_802_11 pHdr80211, - IN PUCHAR Addr1, - IN PUCHAR Addr2, - IN PUCHAR Addr3); - -VOID BarHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PFRAME_BAR pCntlBar, - IN PUCHAR pDA, - IN PUCHAR pSA); - -VOID InsertActField( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN UINT8 Category, - IN UINT8 ActCode); - -BOOLEAN CntlEnqueueForRecv( - IN PRTMP_ADAPTER pAd, - IN ULONG Wcid, - IN ULONG MsgLen, - IN PFRAME_BA_REQ pMsg); - -// -// Private routines in rtmp_data.c -// -BOOLEAN RTMPHandleRxDoneInterrupt( - IN PRTMP_ADAPTER pAd); - -BOOLEAN RTMPHandleTxRingDmaDoneInterrupt( - IN PRTMP_ADAPTER pAd, - IN INT_SOURCE_CSR_STRUC TxRingBitmap); - -VOID RTMPHandleMgmtRingDmaDoneInterrupt( - IN PRTMP_ADAPTER pAd); - -VOID RTMPHandleTBTTInterrupt( - IN PRTMP_ADAPTER pAd); - -VOID RTMPHandlePreTBTTInterrupt( - IN PRTMP_ADAPTER pAd); - -void RTMPHandleTwakeupInterrupt( - IN PRTMP_ADAPTER pAd); - -VOID RTMPHandleRxCoherentInterrupt( - IN PRTMP_ADAPTER pAd); - -BOOLEAN TxFrameIsAggregatible( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pPrevAddr1, - IN PUCHAR p8023hdr); - -BOOLEAN PeerIsAggreOn( - IN PRTMP_ADAPTER pAd, - IN ULONG TxRate, - IN PMAC_TABLE_ENTRY pMacEntry); - -NDIS_STATUS Sniff2BytesFromNdisBuffer( - IN PNDIS_BUFFER pFirstBuffer, - IN UCHAR DesiredOffset, - OUT PUCHAR pByte0, - OUT PUCHAR pByte1); - -NDIS_STATUS STASendPacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket); - -VOID STASendPackets( - IN NDIS_HANDLE MiniportAdapterContext, - IN PPNDIS_PACKET ppPacketArray, - IN UINT NumberOfPackets); - -VOID RTMPDeQueuePacket( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bIntContext, - IN UCHAR QueIdx, - IN UCHAR Max_Tx_Packets); - -NDIS_STATUS RTMPHardTransmit( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR QueIdx, - OUT PULONG pFreeTXDLeft); - -NDIS_STATUS STAHardTransmit( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR QueIdx); - -VOID STARxEAPOLFrameIndicate( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); - -NDIS_STATUS RTMPFreeTXDRequest( - IN PRTMP_ADAPTER pAd, - IN UCHAR RingType, - IN UCHAR NumberRequired, - IN PUCHAR FreeNumberIs); - -NDIS_STATUS MlmeHardTransmit( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket); - -NDIS_STATUS MlmeHardTransmitMgmtRing( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket); - -NDIS_STATUS MlmeHardTransmitTxRing( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket); - -USHORT RTMPCalcDuration( - IN PRTMP_ADAPTER pAd, - IN UCHAR Rate, - IN ULONG Size); - -VOID RTMPWriteTxWI( - IN PRTMP_ADAPTER pAd, - IN PTXWI_STRUC pTxWI, - IN BOOLEAN FRAG, - IN BOOLEAN CFACK, - IN BOOLEAN InsTimestamp, - IN BOOLEAN AMPDU, - IN BOOLEAN Ack, - IN BOOLEAN NSeq, // HW new a sequence. - IN UCHAR BASize, - IN UCHAR WCID, - IN ULONG Length, - IN UCHAR PID, - IN UCHAR TID, - IN UCHAR TxRate, - IN UCHAR Txopmode, - IN BOOLEAN CfAck, - IN HTTRANSMIT_SETTING *pTransmit); - - -VOID RTMPWriteTxWI_Data( - IN PRTMP_ADAPTER pAd, - IN OUT PTXWI_STRUC pTxWI, - IN TX_BLK *pTxBlk); - - -VOID RTMPWriteTxWI_Cache( - IN PRTMP_ADAPTER pAd, - IN OUT PTXWI_STRUC pTxWI, - IN TX_BLK *pTxBlk); - -VOID RTMPWriteTxDescriptor( - IN PRTMP_ADAPTER pAd, - IN PTXD_STRUC pTxD, - IN BOOLEAN bWIV, - IN UCHAR QSEL); - -VOID RTMPSuspendMsduTransmission( - IN PRTMP_ADAPTER pAd); - -VOID RTMPResumeMsduTransmission( - IN PRTMP_ADAPTER pAd); - -NDIS_STATUS MiniportMMRequest( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PUCHAR pData, - IN UINT Length); - -VOID RTMPSendNullFrame( - IN PRTMP_ADAPTER pAd, - IN UCHAR TxRate, - IN BOOLEAN bQosNull); - -VOID RTMPSendDisassociationFrame( - IN PRTMP_ADAPTER pAd); - -VOID RTMPSendRTSFrame( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN unsigned int NextMpduSize, - IN UCHAR TxRate, - IN UCHAR RTSRate, - IN USHORT AckDuration, - IN UCHAR QueIdx, - IN UCHAR FrameGap); - -PQUEUE_HEADER RTMPCheckTxSwQueue( - IN PRTMP_ADAPTER pAd, - OUT UCHAR *QueIdx); - -VOID RTMPReportMicError( - IN PRTMP_ADAPTER pAd, - IN PCIPHER_KEY pWpaKey); - -VOID WpaMicFailureReportFrame( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID WpaDisassocApAndBlockAssoc( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -NDIS_STATUS RTMPCloneNdisPacket( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN pInsAMSDUHdr, - IN PNDIS_PACKET pInPacket, - OUT PNDIS_PACKET *ppOutPacket); - -NDIS_STATUS RTMPAllocateNdisPacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET *pPacket, - IN PUCHAR pHeader, - IN UINT HeaderLen, - IN PUCHAR pData, - IN UINT DataLen); - -VOID RTMPFreeNdisPacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket); - -BOOLEAN RTMPFreeTXDUponTxDmaDone( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx); - -BOOLEAN RTMPCheckDHCPFrame( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket); - - -BOOLEAN RTMPCheckEtherType( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket); - - -// -// Private routines in rtmp_wep.c -// -VOID RTMPInitWepEngine( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKey, - IN UCHAR KeyId, - IN UCHAR KeyLen, - IN PUCHAR pDest); - -VOID RTMPEncryptData( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pSrc, - IN PUCHAR pDest, - IN UINT Len); - -BOOLEAN RTMPSoftDecryptWEP( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG DataByteCnt, - IN PCIPHER_KEY pGroupKey); - -VOID RTMPSetICV( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDest); - -VOID ARCFOUR_INIT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pKey, - IN UINT KeyLen); - -UCHAR ARCFOUR_BYTE( - IN PARCFOURCONTEXT Ctx); - -VOID ARCFOUR_DECRYPT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pDest, - IN PUCHAR pSrc, - IN UINT Len); - -VOID ARCFOUR_ENCRYPT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pDest, - IN PUCHAR pSrc, - IN UINT Len); - -VOID WPAARCFOUR_ENCRYPT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pDest, - IN PUCHAR pSrc, - IN UINT Len); - -UINT RTMP_CALC_FCS32( - IN UINT Fcs, - IN PUCHAR Cp, - IN INT Len); - -// -// MLME routines -// - -// Asic/RF/BBP related functions - -VOID AsicAdjustTxPower( - IN PRTMP_ADAPTER pAd); - -VOID AsicUpdateProtect( - IN PRTMP_ADAPTER pAd, - IN USHORT OperaionMode, - IN UCHAR SetMask, - IN BOOLEAN bDisableBGProtect, - IN BOOLEAN bNonGFExist); - -VOID AsicSwitchChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel, - IN BOOLEAN bScan); - -VOID AsicLockChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel) ; - -VOID AsicRfTuningExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID AsicSleepThenAutoWakeup( - IN PRTMP_ADAPTER pAd, - IN USHORT TbttNumToNextWakeUp); - -VOID AsicForceSleep( - IN PRTMP_ADAPTER pAd); - -VOID AsicForceWakeup( - IN PRTMP_ADAPTER pAd, -#ifdef RT2860 - IN UCHAR Level); -#endif -#ifdef RT2870 - IN BOOLEAN bFromTx); -#endif +void PeerGroupMsg2Action(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + void * Msg, u32 MsgLen); -VOID AsicSetBssid( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pBssid); - -VOID AsicSetMcastWC( - IN PRTMP_ADAPTER pAd); - -VOID AsicDelWcidTab( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid); - -VOID AsicEnableRDG( - IN PRTMP_ADAPTER pAd); - -VOID AsicDisableRDG( - IN PRTMP_ADAPTER pAd); - -VOID AsicDisableSync( - IN PRTMP_ADAPTER pAd); - -VOID AsicEnableBssSync( - IN PRTMP_ADAPTER pAd); - -VOID AsicEnableIbssSync( - IN PRTMP_ADAPTER pAd); - -VOID AsicSetEdcaParm( - IN PRTMP_ADAPTER pAd, - IN PEDCA_PARM pEdcaParm); - -VOID AsicSetSlotTime( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bUseShortSlotTime); - -VOID AsicAddSharedKeyEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIndex, - IN UCHAR KeyIdx, - IN UCHAR CipherAlg, - IN PUCHAR pKey, - IN PUCHAR pTxMic, - IN PUCHAR pRxMic); - -VOID AsicRemoveSharedKeyEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIndex, - IN UCHAR KeyIdx); - -VOID AsicUpdateWCIDAttribute( - IN PRTMP_ADAPTER pAd, - IN USHORT WCID, - IN UCHAR BssIndex, - IN UCHAR CipherAlg, - IN BOOLEAN bUsePairewiseKeyTable); - -VOID AsicUpdateWCIDIVEIV( - IN PRTMP_ADAPTER pAd, - IN USHORT WCID, - IN ULONG uIV, - IN ULONG uEIV); - -VOID AsicUpdateRxWCIDTable( - IN PRTMP_ADAPTER pAd, - IN USHORT WCID, - IN PUCHAR pAddr); - -VOID AsicAddKeyEntry( - IN PRTMP_ADAPTER pAd, - IN USHORT WCID, - IN UCHAR BssIndex, - IN UCHAR KeyIdx, - IN PCIPHER_KEY pCipherKey, - IN BOOLEAN bUsePairewiseKeyTable, - IN BOOLEAN bTxKey); - -VOID AsicAddPairwiseKeyEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN UCHAR WCID, - IN CIPHER_KEY *pCipherKey); - -VOID AsicRemovePairwiseKeyEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIdx, - IN UCHAR Wcid); - -BOOLEAN AsicSendCommandToMcu( - IN PRTMP_ADAPTER pAd, - IN UCHAR Command, - IN UCHAR Token, - IN UCHAR Arg0, - IN UCHAR Arg1); -#ifdef RT2860 -BOOLEAN AsicCheckCommanOk( - IN PRTMP_ADAPTER pAd, - IN UCHAR Command); -#endif -VOID MacAddrRandomBssid( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pAddr); - -VOID MgtMacHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PHEADER_802_11 pHdr80211, - IN UCHAR SubType, - IN UCHAR ToDs, - IN PUCHAR pDA, - IN PUCHAR pBssid); - -VOID MlmeRadioOff( - IN PRTMP_ADAPTER pAd); - -VOID MlmeRadioOn( - IN PRTMP_ADAPTER pAd); - - -VOID BssTableInit( - IN BSS_TABLE *Tab); - -VOID BATableInit( - IN PRTMP_ADAPTER pAd, - IN BA_TABLE *Tab); - -ULONG BssTableSearch( - IN BSS_TABLE *Tab, - IN PUCHAR pBssid, - IN UCHAR Channel); - -ULONG BssSsidTableSearch( - IN BSS_TABLE *Tab, - IN PUCHAR pBssid, - IN PUCHAR pSsid, - IN UCHAR SsidLen, - IN UCHAR Channel); - -ULONG BssTableSearchWithSSID( - IN BSS_TABLE *Tab, - IN PUCHAR Bssid, - IN PUCHAR pSsid, - IN UCHAR SsidLen, - IN UCHAR Channel); - -VOID BssTableDeleteEntry( - IN OUT PBSS_TABLE pTab, - IN PUCHAR pBssid, - IN UCHAR Channel); - -VOID BATableDeleteORIEntry( - IN OUT PRTMP_ADAPTER pAd, - IN BA_ORI_ENTRY *pBAORIEntry); - -VOID BssEntrySet( - IN PRTMP_ADAPTER pAd, - OUT PBSS_ENTRY pBss, - IN PUCHAR pBssid, - IN CHAR Ssid[], - IN UCHAR SsidLen, - IN UCHAR BssType, - IN USHORT BeaconPeriod, - IN PCF_PARM CfParm, - IN USHORT AtimWin, - IN USHORT CapabilityInfo, - IN UCHAR SupRate[], - IN UCHAR SupRateLen, - IN UCHAR ExtRate[], - IN UCHAR ExtRateLen, - IN HT_CAPABILITY_IE *pHtCapability, - IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE - IN UCHAR HtCapabilityLen, - IN UCHAR AddHtInfoLen, - IN UCHAR NewExtChanOffset, - IN UCHAR Channel, - IN CHAR Rssi, - IN LARGE_INTEGER TimeStamp, - IN UCHAR CkipFlag, - IN PEDCA_PARM pEdcaParm, - IN PQOS_CAPABILITY_PARM pQosCapability, - IN PQBSS_LOAD_PARM pQbssLoad, - IN USHORT LengthVIE, - IN PNDIS_802_11_VARIABLE_IEs pVIE); - -ULONG BssTableSetEntry( - IN PRTMP_ADAPTER pAd, - OUT PBSS_TABLE pTab, - IN PUCHAR pBssid, - IN CHAR Ssid[], - IN UCHAR SsidLen, - IN UCHAR BssType, - IN USHORT BeaconPeriod, - IN CF_PARM *CfParm, - IN USHORT AtimWin, - IN USHORT CapabilityInfo, - IN UCHAR SupRate[], - IN UCHAR SupRateLen, - IN UCHAR ExtRate[], - IN UCHAR ExtRateLen, - IN HT_CAPABILITY_IE *pHtCapability, - IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE - IN UCHAR HtCapabilityLen, - IN UCHAR AddHtInfoLen, - IN UCHAR NewExtChanOffset, - IN UCHAR Channel, - IN CHAR Rssi, - IN LARGE_INTEGER TimeStamp, - IN UCHAR CkipFlag, - IN PEDCA_PARM pEdcaParm, - IN PQOS_CAPABILITY_PARM pQosCapability, - IN PQBSS_LOAD_PARM pQbssLoad, - IN USHORT LengthVIE, - IN PNDIS_802_11_VARIABLE_IEs pVIE); - -VOID BATableInsertEntry( - IN PRTMP_ADAPTER pAd, - IN USHORT Aid, - IN USHORT TimeOutValue, - IN USHORT StartingSeq, - IN UCHAR TID, - IN UCHAR BAWinSize, - IN UCHAR OriginatorStatus, - IN BOOLEAN IsRecipient); - -VOID BssTableSsidSort( - IN PRTMP_ADAPTER pAd, - OUT BSS_TABLE *OutTab, - IN CHAR Ssid[], - IN UCHAR SsidLen); - -VOID BssTableSortByRssi( - IN OUT BSS_TABLE *OutTab); - -VOID BssCipherParse( - IN OUT PBSS_ENTRY pBss); - -NDIS_STATUS MlmeQueueInit( - IN MLME_QUEUE *Queue); - -VOID MlmeQueueDestroy( - IN MLME_QUEUE *Queue); - -BOOLEAN MlmeEnqueue( - IN PRTMP_ADAPTER pAd, - IN ULONG Machine, - IN ULONG MsgType, - IN ULONG MsgLen, - IN VOID *Msg); - -BOOLEAN MlmeEnqueueForRecv( - IN PRTMP_ADAPTER pAd, - IN ULONG Wcid, - IN ULONG TimeStampHigh, - IN ULONG TimeStampLow, - IN UCHAR Rssi0, - IN UCHAR Rssi1, - IN UCHAR Rssi2, - IN ULONG MsgLen, - IN PVOID Msg, - IN UCHAR Signal); - - -BOOLEAN MlmeDequeue( - IN MLME_QUEUE *Queue, - OUT MLME_QUEUE_ELEM **Elem); - -VOID MlmeRestartStateMachine( - IN PRTMP_ADAPTER pAd); - -BOOLEAN MlmeQueueEmpty( - IN MLME_QUEUE *Queue); - -BOOLEAN MlmeQueueFull( - IN MLME_QUEUE *Queue); - -BOOLEAN MsgTypeSubst( - IN PRTMP_ADAPTER pAd, - IN PFRAME_802_11 pFrame, - OUT INT *Machine, - OUT INT *MsgType); - -VOID StateMachineInit( - IN STATE_MACHINE *Sm, - IN STATE_MACHINE_FUNC Trans[], - IN ULONG StNr, - IN ULONG MsgNr, - IN STATE_MACHINE_FUNC DefFunc, - IN ULONG InitState, - IN ULONG Base); - -VOID StateMachineSetAction( - IN STATE_MACHINE *S, - IN ULONG St, - ULONG Msg, - IN STATE_MACHINE_FUNC F); - -VOID StateMachinePerformAction( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - IN MLME_QUEUE_ELEM *Elem); - -VOID Drop( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID AssocStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *Sm, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID ReassocTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID AssocTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID DisassocTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -//---------------------------------------------- -VOID MlmeAssocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeReassocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeDisassocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerAssocRspAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerReassocRspAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerDisassocAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID DisassocTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID AssocTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID ReassocTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID Cls3errAction( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr); - -VOID SwitchBetweenWepAndCkip( - IN PRTMP_ADAPTER pAd); - -VOID InvalidStateWhenAssoc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID InvalidStateWhenReassoc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID InvalidStateWhenDisassociate( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -#ifdef RT2870 -VOID MlmeCntlConfirm( - IN PRTMP_ADAPTER pAd, - IN ULONG MsgType, - IN USHORT Msg); -#endif // RT2870 // - -VOID ComposePsPoll( - IN PRTMP_ADAPTER pAd); - -VOID ComposeNullFrame( - IN PRTMP_ADAPTER pAd); - -VOID AssocPostProc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr2, - IN USHORT CapabilityInfo, - IN USHORT Aid, - IN UCHAR SupRate[], - IN UCHAR SupRateLen, - IN UCHAR ExtRate[], - IN UCHAR ExtRateLen, - IN PEDCA_PARM pEdcaParm, - IN HT_CAPABILITY_IE *pHtCapability, - IN UCHAR HtCapabilityLen, - IN ADD_HT_INFO_IE *pAddHtInfo); - -VOID AuthStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN PSTATE_MACHINE sm, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID AuthTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID MlmeAuthReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerAuthRspAtSeq2Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerAuthRspAtSeq4Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID AuthTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID Cls2errAction( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr); - -VOID MlmeDeauthReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID InvalidStateWhenAuth( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -//============================================= - -VOID AuthRspStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN PSTATE_MACHINE Sm, - IN STATE_MACHINE_FUNC Trans[]); - -VOID PeerDeauthAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerAuthSimpleRspGenAndSend( - IN PRTMP_ADAPTER pAd, - IN PHEADER_802_11 pHdr80211, - IN USHORT Alg, - IN USHORT Seq, - IN USHORT Reason, - IN USHORT Status); - -// -// Private routines in dls.c -// - -//======================================== - -VOID SyncStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *Sm, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID BeaconTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID ScanTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID InvalidStateWhenScan( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID InvalidStateWhenJoin( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID InvalidStateWhenStart( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID EnqueueProbeRequest( - IN PRTMP_ADAPTER pAd); - -BOOLEAN ScanRunning( - IN PRTMP_ADAPTER pAd); -//========================================= - -VOID MlmeCntlInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID MlmeCntlMachinePerformAction( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlIdleProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlOidScanProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlOidSsidProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM * Elem); - -VOID CntlOidRTBssidProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM * Elem); - -VOID CntlMlmeRoamingProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM * Elem); - -VOID CntlWaitDisassocProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlWaitJoinProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlWaitReassocProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlWaitStartProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlWaitAuthProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlWaitAuthProc2( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlWaitAssocProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID LinkUp( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssType); - -VOID LinkDown( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN IsReqFromAP); - -VOID IterateOnBssTab( - IN PRTMP_ADAPTER pAd); - -VOID IterateOnBssTab2( - IN PRTMP_ADAPTER pAd);; - -VOID JoinParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_JOIN_REQ_STRUCT *JoinReq, - IN ULONG BssIdx); - -VOID AssocParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq, - IN PUCHAR pAddr, - IN USHORT CapabilityInfo, - IN ULONG Timeout, - IN USHORT ListenIntv); - -VOID ScanParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_SCAN_REQ_STRUCT *ScanReq, - IN CHAR Ssid[], - IN UCHAR SsidLen, - IN UCHAR BssType, - IN UCHAR ScanType); - -VOID DisassocParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq, - IN PUCHAR pAddr, - IN USHORT Reason); - -VOID StartParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_START_REQ_STRUCT *StartReq, - IN CHAR Ssid[], - IN UCHAR SsidLen); - -VOID AuthParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_AUTH_REQ_STRUCT *AuthReq, - IN PUCHAR pAddr, - IN USHORT Alg); - -VOID EnqueuePsPoll( - IN PRTMP_ADAPTER pAd); - -VOID EnqueueBeaconFrame( - IN PRTMP_ADAPTER pAd); - -VOID MlmeJoinReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeScanReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeStartReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID ScanTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID BeaconTimeoutAtJoinAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerBeaconAtScanAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerBeaconAtJoinAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerBeacon( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerProbeReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID ScanNextChannel( - IN PRTMP_ADAPTER pAd); - -ULONG MakeIbssBeacon( - IN PRTMP_ADAPTER pAd); - -VOID CCXAdjacentAPReport( - IN PRTMP_ADAPTER pAd); - -BOOLEAN MlmeScanReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT UCHAR *BssType, - OUT CHAR ssid[], - OUT UCHAR *SsidLen, - OUT UCHAR *ScanType); - -BOOLEAN PeerBeaconAndProbeRspSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - IN UCHAR MsgChannel, - OUT PUCHAR pAddr2, - OUT PUCHAR pBssid, - OUT CHAR Ssid[], - OUT UCHAR *pSsidLen, - OUT UCHAR *pBssType, - OUT USHORT *pBeaconPeriod, - OUT UCHAR *pChannel, - OUT UCHAR *pNewChannel, - OUT LARGE_INTEGER *pTimestamp, - OUT CF_PARM *pCfParm, - OUT USHORT *pAtimWin, - OUT USHORT *pCapabilityInfo, - OUT UCHAR *pErp, - OUT UCHAR *pDtimCount, - OUT UCHAR *pDtimPeriod, - OUT UCHAR *pBcastFlag, - OUT UCHAR *pMessageToMe, - OUT UCHAR SupRate[], - OUT UCHAR *pSupRateLen, - OUT UCHAR ExtRate[], - OUT UCHAR *pExtRateLen, - OUT UCHAR *pCkipFlag, - OUT UCHAR *pAironetCellPowerLimit, - OUT PEDCA_PARM pEdcaParm, - OUT PQBSS_LOAD_PARM pQbssLoad, - OUT PQOS_CAPABILITY_PARM pQosCapability, - OUT ULONG *pRalinkIe, - OUT UCHAR *pHtCapabilityLen, - OUT UCHAR *pPreNHtCapabilityLen, - OUT HT_CAPABILITY_IE *pHtCapability, - OUT UCHAR *AddHtInfoLen, - OUT ADD_HT_INFO_IE *AddHtInfo, - OUT UCHAR *NewExtChannel, - OUT USHORT *LengthVIE, - OUT PNDIS_802_11_VARIABLE_IEs pVIE); - -BOOLEAN PeerAddBAReqActionSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2); - -BOOLEAN PeerAddBARspActionSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen); - -BOOLEAN PeerDelBAActionSanity( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN VOID *pMsg, - IN ULONG MsgLen); - -BOOLEAN MlmeAssocReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pApAddr, - OUT USHORT *CapabilityInfo, - OUT ULONG *Timeout, - OUT USHORT *ListenIntv); - -BOOLEAN MlmeAuthReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr, - OUT ULONG *Timeout, - OUT USHORT *Alg); - -BOOLEAN MlmeStartReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT CHAR Ssid[], - OUT UCHAR *Ssidlen); - -BOOLEAN PeerAuthSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr, - OUT USHORT *Alg, - OUT USHORT *Seq, - OUT USHORT *Status, - OUT CHAR ChlgText[]); - -BOOLEAN PeerAssocRspSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *pCapabilityInfo, - OUT USHORT *pStatus, - OUT USHORT *pAid, - OUT UCHAR SupRate[], - OUT UCHAR *pSupRateLen, - OUT UCHAR ExtRate[], - OUT UCHAR *pExtRateLen, - OUT HT_CAPABILITY_IE *pHtCapability, - OUT ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE - OUT UCHAR *pHtCapabilityLen, - OUT UCHAR *pAddHtInfoLen, - OUT UCHAR *pNewExtChannelOffset, - OUT PEDCA_PARM pEdcaParm, - OUT UCHAR *pCkipFlag); - -BOOLEAN PeerDisassocSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *Reason); - -BOOLEAN PeerDeauthSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *Reason); - -BOOLEAN PeerProbeReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT CHAR Ssid[], - OUT UCHAR *pSsidLen); - -BOOLEAN GetTimBit( - IN CHAR *Ptr, - IN USHORT Aid, - OUT UCHAR *TimLen, - OUT UCHAR *BcastFlag, - OUT UCHAR *DtimCount, - OUT UCHAR *DtimPeriod, - OUT UCHAR *MessageToMe); - -UCHAR ChannelSanity( - IN PRTMP_ADAPTER pAd, - IN UCHAR channel); - -NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity( - IN PBSS_ENTRY pBss); - -BOOLEAN MlmeDelBAReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen); - -BOOLEAN MlmeAddBAReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2); - -ULONG MakeOutgoingFrame( - OUT CHAR *Buffer, - OUT ULONG *Length, ...); - -VOID LfsrInit( - IN PRTMP_ADAPTER pAd, - IN ULONG Seed); - -UCHAR RandomByte( - IN PRTMP_ADAPTER pAd); - -VOID AsicUpdateAutoFallBackTable( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pTxRate); - -VOID MlmePeriodicExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID LinkDownExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID STAMlmePeriodicExec( - PRTMP_ADAPTER pAd); - -VOID MlmeAutoScan( - IN PRTMP_ADAPTER pAd); - -VOID MlmeAutoReconnectLastSSID( - IN PRTMP_ADAPTER pAd); - -BOOLEAN MlmeValidateSSID( - IN PUCHAR pSsid, - IN UCHAR SsidLen); - -VOID MlmeCheckForRoaming( - IN PRTMP_ADAPTER pAd, - IN ULONG Now32); - -VOID MlmeCheckForFastRoaming( - IN PRTMP_ADAPTER pAd, - IN ULONG Now); - -VOID MlmeDynamicTxRateSwitching( - IN PRTMP_ADAPTER pAd); - -VOID MlmeSetTxRate( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PRTMP_TX_RATE_SWITCH pTxRate); - -VOID MlmeSelectTxRateTable( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PUCHAR *ppTable, - IN PUCHAR pTableSize, - IN PUCHAR pInitTxRateIdx); - -VOID MlmeCalculateChannelQuality( - IN PRTMP_ADAPTER pAd, - IN ULONG Now); - -VOID MlmeCheckPsmChange( - IN PRTMP_ADAPTER pAd, - IN ULONG Now32); - -VOID MlmeSetPsmBit( - IN PRTMP_ADAPTER pAd, - IN USHORT psm); - -VOID MlmeSetTxPreamble( - IN PRTMP_ADAPTER pAd, - IN USHORT TxPreamble); - -VOID UpdateBasicRateBitmap( - IN PRTMP_ADAPTER pAd); - -VOID MlmeUpdateTxRates( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bLinkUp, - IN UCHAR apidx); - -VOID MlmeUpdateHtTxRates( - IN PRTMP_ADAPTER pAd, - IN UCHAR apidx); - -VOID RTMPCheckRates( - IN PRTMP_ADAPTER pAd, - IN OUT UCHAR SupRate[], - IN OUT UCHAR *SupRateLen); - -BOOLEAN RTMPCheckChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR CentralChannel, - IN UCHAR Channel); - -BOOLEAN RTMPCheckHt( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN OUT HT_CAPABILITY_IE *pHtCapability, - IN OUT ADD_HT_INFO_IE *pAddHtInfo); - -VOID StaQuickResponeForRateUpExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID RTMPUpdateMlmeRate( - IN PRTMP_ADAPTER pAd); - -CHAR RTMPMaxRssi( - IN PRTMP_ADAPTER pAd, - IN CHAR Rssi0, - IN CHAR Rssi1, - IN CHAR Rssi2); - -VOID AsicSetRxAnt( - IN PRTMP_ADAPTER pAd, - IN UCHAR Ant); - -VOID AsicEvaluateRxAnt( - IN PRTMP_ADAPTER pAd); - -VOID AsicRxAntEvalTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID APSDPeriodicExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry); - -UCHAR RTMPStaFixedTxMode( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry); - -VOID RTMPUpdateLegacyTxSetting( - UCHAR fixed_tx_mode, - PMAC_TABLE_ENTRY pEntry); - -BOOLEAN RTMPAutoRateSwitchCheck( - IN PRTMP_ADAPTER pAd); - -NDIS_STATUS MlmeInit( - IN PRTMP_ADAPTER pAd); - -VOID MlmeHandler( - IN PRTMP_ADAPTER pAd); - -VOID MlmeHalt( - IN PRTMP_ADAPTER pAd); - -VOID MlmeResetRalinkCounters( - IN PRTMP_ADAPTER pAd); - -VOID BuildChannelList( - IN PRTMP_ADAPTER pAd); - -UCHAR FirstChannel( - IN PRTMP_ADAPTER pAd); - -UCHAR NextChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR channel); - -VOID ChangeToCellPowerLimit( - IN PRTMP_ADAPTER pAd, - IN UCHAR AironetCellPowerLimit); - -USHORT RTMP_EEPROM_READ16( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset); - -VOID RTMP_EEPROM_WRITE16( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Data); - -// -// Prototypes of function definition in rtmp_tkip.c -// -VOID RTMPInitTkipEngine( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pTKey, - IN UCHAR KeyId, - IN PUCHAR pTA, - IN PUCHAR pMICKey, - IN PUCHAR pTSC, - OUT PULONG pIV16, - OUT PULONG pIV32); - -VOID RTMPInitMICEngine( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKey, - IN PUCHAR pDA, - IN PUCHAR pSA, - IN UCHAR UserPriority, - IN PUCHAR pMICKey); - -BOOLEAN RTMPTkipCompareMICValue( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pSrc, - IN PUCHAR pDA, - IN PUCHAR pSA, - IN PUCHAR pMICKey, - IN UCHAR UserPriority, - IN UINT Len); - -VOID RTMPCalculateMICValue( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN PUCHAR pEncap, - IN PCIPHER_KEY pKey, - IN UCHAR apidx); - -BOOLEAN RTMPTkipCompareMICValueWithLLC( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pLLC, - IN PUCHAR pSrc, - IN PUCHAR pDA, - IN PUCHAR pSA, - IN PUCHAR pMICKey, - IN UINT Len); - -VOID RTMPTkipAppendByte( - IN PTKIP_KEY_INFO pTkip, - IN UCHAR uChar); - -VOID RTMPTkipAppend( - IN PTKIP_KEY_INFO pTkip, - IN PUCHAR pSrc, - IN UINT nBytes); - -VOID RTMPTkipGetMIC( - IN PTKIP_KEY_INFO pTkip); - -BOOLEAN RTMPSoftDecryptTKIP( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG DataByteCnt, - IN UCHAR UserPriority, - IN PCIPHER_KEY pWpaKey); - -BOOLEAN RTMPSoftDecryptAES( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG DataByteCnt, - IN PCIPHER_KEY pWpaKey); - -// -// Prototypes of function definition in cmm_info.c -// -NDIS_STATUS RTMPWPARemoveKeyProc( - IN PRTMP_ADAPTER pAd, - IN PVOID pBuf); - -VOID RTMPWPARemoveAllKeys( - IN PRTMP_ADAPTER pAd); - -BOOLEAN RTMPCheckStrPrintAble( - IN CHAR *pInPutStr, - IN UCHAR strLen); - -VOID RTMPSetPhyMode( - IN PRTMP_ADAPTER pAd, - IN ULONG phymode); - -VOID RTMPUpdateHTIE( - IN RT_HT_CAPABILITY *pRtHt, - IN UCHAR *pMcsSet, - OUT HT_CAPABILITY_IE *pHtCapability, - OUT ADD_HT_INFO_IE *pAddHtInfo); - -VOID RTMPAddWcidAttributeEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIdx, - IN UCHAR KeyIdx, - IN UCHAR CipherAlg, - IN MAC_TABLE_ENTRY *pEntry); - -CHAR *GetEncryptType( - CHAR enc); - -CHAR *GetAuthMode( - CHAR auth); - -VOID RTMPIoctlGetSiteSurvey( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq); - -VOID RTMPIoctlGetMacTable( - IN PRTMP_ADAPTER pAd, - IN struct iwreq *wrq); - -VOID RTMPAddBSSIDCipher( - IN PRTMP_ADAPTER pAd, - IN UCHAR Aid, - IN PNDIS_802_11_KEY pKey, - IN UCHAR CipherAlg); - -VOID RTMPSetHT( - IN PRTMP_ADAPTER pAd, - IN OID_SET_HT_PHYMODE *pHTPhyMode); - -VOID RTMPSetIndividualHT( - IN PRTMP_ADAPTER pAd, - IN UCHAR apidx); - -VOID RTMPSendWirelessEvent( - IN PRTMP_ADAPTER pAd, - IN USHORT Event_flag, - IN PUCHAR pAddr, - IN UCHAR BssIdx, - IN CHAR Rssi); - -// -// prototype in wpa.c -// -BOOLEAN WpaMsgTypeSubst( - IN UCHAR EAPType, - OUT INT *MsgType); - -VOID WpaPskStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID WpaEAPOLKeyAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID WpaPairMsg1Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID WpaPairMsg3Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID WpaGroupMsg1Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID WpaMacHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PHEADER_802_11 pHdr80211, - IN UCHAR wep, - IN PUCHAR pAddr1); - -VOID Wpa2PairMsg1Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID Wpa2PairMsg3Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -BOOLEAN ParseKeyData( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKeyData, - IN UCHAR KeyDataLen, - IN UCHAR bPairewise); - -VOID RTMPToWirelessSta( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pHeader802_3, - IN UINT HdrLen, - IN PUCHAR pData, - IN UINT DataLen, - IN BOOLEAN is4wayFrame); - -VOID HMAC_SHA1( - IN UCHAR *text, - IN UINT text_len, - IN UCHAR *key, - IN UINT key_len, - IN UCHAR *digest); - -VOID PRF( - IN UCHAR *key, - IN INT key_len, - IN UCHAR *prefix, - IN INT prefix_len, - IN UCHAR *data, - IN INT data_len, - OUT UCHAR *output, - IN INT len); - -VOID CCKMPRF( - IN UCHAR *key, - IN INT key_len, - IN UCHAR *data, - IN INT data_len, - OUT UCHAR *output, - IN INT len); - -VOID WpaCountPTK( - IN PRTMP_ADAPTER pAd, - IN UCHAR *PMK, - IN UCHAR *ANonce, - IN UCHAR *AA, - IN UCHAR *SNonce, - IN UCHAR *SA, - OUT UCHAR *output, - IN UINT len); - -VOID GenRandom( - IN PRTMP_ADAPTER pAd, - IN UCHAR *macAddr, - OUT UCHAR *random); - -// -// prototype in aironet.c -// -VOID AironetStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID AironetMsgAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID AironetRequestAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID ChannelLoadRequestAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Index); - -VOID NoiseHistRequestAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Index); - -VOID BeaconRequestAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Index); - -VOID AironetReportAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID ChannelLoadReportAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Index); - -VOID NoiseHistReportAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Index); - -VOID AironetFinalReportAction( - IN PRTMP_ADAPTER pAd); - -VOID BeaconReportAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Index); - -VOID AironetAddBeaconReport( - IN PRTMP_ADAPTER pAd, - IN ULONG Index, - IN PMLME_QUEUE_ELEM pElem); - -VOID AironetCreateBeaconReportFromBssTable( - IN PRTMP_ADAPTER pAd); - -CHAR ConvertToRssi( - IN PRTMP_ADAPTER pAd, - IN CHAR Rssi, - IN UCHAR RssiNumber); - -// -// function prototype in cmm_wpa.c -// -BOOLEAN RTMPCheckWPAframe( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PUCHAR pData, - IN ULONG DataByteCount, - IN UCHAR FromWhichBSSID); - -VOID AES_GTK_KEY_UNWRAP( - IN UCHAR *key, - OUT UCHAR *plaintext, - IN UCHAR c_len, - IN UCHAR *ciphertext); - -VOID RTMPMakeRSNIE( - IN PRTMP_ADAPTER pAd, - IN UINT AuthMode, - IN UINT WepStatus, - IN UCHAR apidx); - -// -// function prototype in ap_wpa.c -// - -VOID HandleCounterMeasure( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry); +void WpaDeriveGTK(u8 * PMK, + u8 * GNonce, + u8 * AA, u8 * output, u32 len); + +void AES_GTK_KEY_WRAP(u8 * key, + u8 * plaintext, + u32 p_len, u8 * ciphertext); + +/*typedef void (*TIMER_FUNCTION)(unsigned long); */ /* timeout -- ms */ -VOID RTMP_SetPeriodicTimer( - IN NDIS_MINIPORT_TIMER *pTimer, - IN unsigned long timeout); - -VOID RTMP_OS_Init_Timer( - IN PRTMP_ADAPTER pAd, - IN NDIS_MINIPORT_TIMER *pTimer, - IN TIMER_FUNCTION function, - IN PVOID data); - -VOID RTMP_OS_Add_Timer( - IN NDIS_MINIPORT_TIMER *pTimer, - IN unsigned long timeout); - -VOID RTMP_OS_Mod_Timer( - IN NDIS_MINIPORT_TIMER *pTimer, - IN unsigned long timeout); - - -VOID RTMP_OS_Del_Timer( - IN NDIS_MINIPORT_TIMER *pTimer, - OUT BOOLEAN *pCancelled); - - -VOID RTMP_OS_Release_Packet( - IN PRTMP_ADAPTER pAd, - IN PQUEUE_ENTRY pEntry); - -VOID RTMPusecDelay( - IN ULONG usec); - -NDIS_STATUS os_alloc_mem( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR *mem, - IN ULONG size); - -NDIS_STATUS os_free_mem( - IN PRTMP_ADAPTER pAd, - IN PUCHAR mem); - - -void RTMP_AllocateSharedMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); - -VOID RTMPFreeTxRxRingMemory( - IN PRTMP_ADAPTER pAd); +void RTMP_SetPeriodicTimer(struct timer_list * pTimer, + IN unsigned long timeout); -NDIS_STATUS AdapterBlockAllocateMemory( - IN PVOID handle, - OUT PVOID *ppAd); - -void RTMP_AllocateTxDescMemory( - IN PRTMP_ADAPTER pAd, - IN UINT Index, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); - -void RTMP_AllocateFirstTxBuffer( - IN PRTMP_ADAPTER pAd, - IN UINT Index, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); - -void RTMP_AllocateMgmtDescMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); - -void RTMP_AllocateRxDescMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); - -PNDIS_PACKET RTMP_AllocateRxPacketBuffer( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); - -PNDIS_PACKET RTMP_AllocateTxPacketBuffer( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress); - -PNDIS_PACKET RTMP_AllocateFragPacketBuffer( - IN PRTMP_ADAPTER pAd, - IN ULONG Length); - -void RTMP_QueryPacketInfo( - IN PNDIS_PACKET pPacket, - OUT PACKET_INFO *pPacketInfo, - OUT PUCHAR *pSrcBufVA, - OUT UINT *pSrcBufLen); +void RTMP_OS_Init_Timer(struct rt_rtmp_adapter *pAd, + struct timer_list * pTimer, + IN TIMER_FUNCTION function, void *data); -void RTMP_QueryNextPacketInfo( - IN PNDIS_PACKET *ppPacket, - OUT PACKET_INFO *pPacketInfo, - OUT PUCHAR *pSrcBufVA, - OUT UINT *pSrcBufLen); +void RTMP_OS_Add_Timer(struct timer_list * pTimer, + IN unsigned long timeout); +void RTMP_OS_Mod_Timer(struct timer_list * pTimer, + IN unsigned long timeout); -BOOLEAN RTMP_FillTxBlkInfo( - IN RTMP_ADAPTER *pAd, - IN TX_BLK *pTxBlk); +void RTMP_OS_Del_Timer(struct timer_list * pTimer, + OUT BOOLEAN * pCancelled); +void RTMP_OS_Release_Packet(struct rt_rtmp_adapter *pAd, struct rt_queue_entry *pEntry); -PRTMP_SCATTER_GATHER_LIST -rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg); - - - void announce_802_3_packet( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket); - - -UINT BA_Reorder_AMSDU_Annnounce( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket); - -PNET_DEV get_netdev_from_bssid( - IN PRTMP_ADAPTER pAd, - IN UCHAR FromWhichBSSID); - - -PNDIS_PACKET duplicate_pkt( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pHeader802_3, - IN UINT HdrLen, - IN PUCHAR pData, - IN ULONG DataSize, - IN UCHAR FromWhichBSSID); - - -PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pOldPkt); - -void ba_flush_reordering_timeout_mpdus( - IN PRTMP_ADAPTER pAd, - IN PBA_REC_ENTRY pBAEntry, - IN ULONG Now32); - - -VOID BAOriSessionSetUp( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN UCHAR TID, - IN USHORT TimeOut, - IN ULONG DelayTime, - IN BOOLEAN isForced); - -VOID BASessionTearDownALL( - IN OUT PRTMP_ADAPTER pAd, - IN UCHAR Wcid); +void RTMPusecDelay(unsigned long usec); -BOOLEAN OS_Need_Clone_Packet(void); +int os_alloc_mem(struct rt_rtmp_adapter *pAd, + u8 ** mem, unsigned long size); +int os_free_mem(struct rt_rtmp_adapter *pAd, void *mem); -VOID build_tx_packet( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN PUCHAR pFrame, - IN ULONG FrameLen); +void RTMP_AllocateSharedMemory(struct rt_rtmp_adapter *pAd, + unsigned long Length, + IN BOOLEAN Cached, + void ** VirtualAddress, + dma_addr_t *PhysicalAddress); +void RTMPFreeTxRxRingMemory(struct rt_rtmp_adapter *pAd); -VOID BAOriSessionTearDown( - IN OUT PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR TID, - IN BOOLEAN bPassive, - IN BOOLEAN bForceSend); +int AdapterBlockAllocateMemory(void *handle, void ** ppAd); -VOID BARecSessionTearDown( - IN OUT PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR TID, - IN BOOLEAN bPassive); +void RTMP_AllocateTxDescMemory(struct rt_rtmp_adapter *pAd, + u32 Index, + unsigned long Length, + IN BOOLEAN Cached, + void ** VirtualAddress, + dma_addr_t *PhysicalAddress); -BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num); -void ba_reordering_resource_release(PRTMP_ADAPTER pAd); +void RTMP_AllocateFirstTxBuffer(struct rt_rtmp_adapter *pAd, + u32 Index, + unsigned long Length, + IN BOOLEAN Cached, + void ** VirtualAddress, + dma_addr_t *PhysicalAddress); -BOOLEAN rtstrmactohex( - IN char *s1, - IN char *s2); +void RTMP_FreeFirstTxBuffer(struct rt_rtmp_adapter *pAd, + unsigned long Length, + IN BOOLEAN Cached, + void *VirtualAddress, + dma_addr_t PhysicalAddress); -BOOLEAN rtstrcasecmp( - IN char *s1, - IN char *s2); +void RTMP_AllocateMgmtDescMemory(struct rt_rtmp_adapter *pAd, + unsigned long Length, + IN BOOLEAN Cached, + void ** VirtualAddress, + dma_addr_t *PhysicalAddress); -char *rtstrstruncasecmp( - IN char *s1, - IN char *s2); +void RTMP_AllocateRxDescMemory(struct rt_rtmp_adapter *pAd, + unsigned long Length, + IN BOOLEAN Cached, + void ** VirtualAddress, + dma_addr_t *PhysicalAddress); -char *rtstrstr( - IN const char * s1, - IN const char * s2); +void RTMP_FreeDescMemory(struct rt_rtmp_adapter *pAd, + unsigned long Length, + void *VirtualAddress, + dma_addr_t PhysicalAddress); -char *rstrtok( - IN char * s, - IN const char * ct); +void *RtmpOSNetPktAlloc(struct rt_rtmp_adapter *pAd, IN int size); -int rtinet_aton( - const char *cp, - unsigned int *addr); +void *RTMP_AllocateRxPacketBuffer(struct rt_rtmp_adapter *pAd, + unsigned long Length, + IN BOOLEAN Cached, + void ** VirtualAddress, + OUT dma_addr_t * + PhysicalAddress); -////////// common ioctl functions ////////// -INT Set_DriverVersion_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void *RTMP_AllocateTxPacketBuffer(struct rt_rtmp_adapter *pAd, + unsigned long Length, + IN BOOLEAN Cached, + void ** VirtualAddress); -INT Set_CountryRegion_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void *RTMP_AllocateFragPacketBuffer(struct rt_rtmp_adapter *pAd, + unsigned long Length); -INT Set_CountryRegionABand_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void RTMP_QueryPacketInfo(void *pPacket, + struct rt_packet_info *pPacketInfo, + u8 ** pSrcBufVA, u32 * pSrcBufLen); -INT Set_WirelessMode_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void RTMP_QueryNextPacketInfo(void ** ppPacket, + struct rt_packet_info *pPacketInfo, + u8 ** pSrcBufVA, u32 * pSrcBufLen); -INT Set_Channel_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +BOOLEAN RTMP_FillTxBlkInfo(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk); -INT Set_ShortSlot_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +struct rt_rtmp_sg_list * +rt_get_sg_list_from_packet(void *pPacket, struct rt_rtmp_sg_list *sg); -INT Set_TxPower_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void announce_802_3_packet(struct rt_rtmp_adapter *pAd, void *pPacket); -INT Set_BGProtection_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +u32 BA_Reorder_AMSDU_Annnounce(struct rt_rtmp_adapter *pAd, void *pPacket); -INT Set_TxPreamble_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +struct net_device *get_netdev_from_bssid(struct rt_rtmp_adapter *pAd, u8 FromWhichBSSID); -INT Set_RTSThreshold_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void *duplicate_pkt(struct rt_rtmp_adapter *pAd, + u8 *pHeader802_3, + u32 HdrLen, + u8 *pData, + unsigned long DataSize, u8 FromWhichBSSID); -INT Set_FragThreshold_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void *duplicate_pkt_with_TKIP_MIC(struct rt_rtmp_adapter *pAd, + void *pOldPkt); -INT Set_TxBurst_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void ba_flush_reordering_timeout_mpdus(struct rt_rtmp_adapter *pAd, + struct rt_ba_rec_entry *pBAEntry, + unsigned long Now32); -#ifdef AGGREGATION_SUPPORT -INT Set_PktAggregate_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); -#endif +void BAOriSessionSetUp(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + u8 TID, + u16 TimeOut, + unsigned long DelayTime, IN BOOLEAN isForced); -INT Set_IEEE80211H_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void BASessionTearDownALL(struct rt_rtmp_adapter *pAd, u8 Wcid); -#ifdef DBG -INT Set_Debug_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); -#endif +BOOLEAN OS_Need_Clone_Packet(void); -INT Show_DescInfo_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void build_tx_packet(struct rt_rtmp_adapter *pAd, + void *pPacket, + u8 *pFrame, unsigned long FrameLen); -INT Set_ResetStatCounter_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void BAOriSessionTearDown(struct rt_rtmp_adapter *pAd, + u8 Wcid, + u8 TID, + IN BOOLEAN bPassive, IN BOOLEAN bForceSend); -INT Set_BASetup_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void BARecSessionTearDown(struct rt_rtmp_adapter *pAd, + u8 Wcid, u8 TID, IN BOOLEAN bPassive); -INT Set_BADecline_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +BOOLEAN ba_reordering_resource_init(struct rt_rtmp_adapter *pAd, int num); +void ba_reordering_resource_release(struct rt_rtmp_adapter *pAd); -INT Set_BAOriTearDown_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +char *rstrtok(char *s, IN const char *ct); -INT Set_BARecTearDown_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +/*//////// common ioctl functions ////////// */ +int SetCommonHT(struct rt_rtmp_adapter *pAd); -INT Set_HtBw_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +int WpaCheckEapCode(struct rt_rtmp_adapter *pAd, + u8 *pFrame, u16 FrameLen, u16 OffSet); -INT Set_HtMcs_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void WpaSendMicFailureToWpaSupplicant(struct rt_rtmp_adapter *pAd, + IN BOOLEAN bUnicast); -INT Set_HtGi_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +int wext_notify_event_assoc(struct rt_rtmp_adapter *pAd); -INT Set_HtOpMode_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +BOOLEAN STARxDoneInterruptHandle(struct rt_rtmp_adapter *pAd, IN BOOLEAN argc); -INT Set_HtStbc_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +/* AMPDU packet indication */ +void Indicate_AMPDU_Packet(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID); -INT Set_HtHtc_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +/* AMSDU packet indication */ +void Indicate_AMSDU_Packet(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID); -INT Set_HtExtcha_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +/* Normal legacy Rx packet indication */ +void Indicate_Legacy_Packet(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID); -INT Set_HtMpduDensity_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void Indicate_EAPOL_Packet(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID); -INT Set_HtBaWinSize_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void update_os_packet_info(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID); -INT Set_HtRdg_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -INT Set_HtLinkAdapt_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -INT Set_HtAmsdu_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -INT Set_HtAutoBa_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -INT Set_HtProtect_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -INT Set_HtMimoPs_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - - -INT Set_ForceShortGI_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -INT Set_ForceGF_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -INT SetCommonHT( - IN PRTMP_ADAPTER pAd); - -INT Set_SendPSMPAction_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -INT Set_HtMIMOPSmode_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - - -INT Set_HtTxBASize_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -INT WpaCheckEapCode( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pFrame, - IN USHORT FrameLen, - IN USHORT OffSet); - -VOID WpaSendMicFailureToWpaSupplicant( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bUnicast); - -int wext_notify_event_assoc( - IN RTMP_ADAPTER *pAd); - -BOOLEAN STARxDoneInterruptHandle( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN argc); - -// AMPDU packet indication -VOID Indicate_AMPDU_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); - -// AMSDU packet indication -VOID Indicate_AMSDU_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); - -// Normal legacy Rx packet indication -VOID Indicate_Legacy_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); - -VOID Indicate_EAPOL_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); - -void update_os_packet_info( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); - -void wlan_802_11_to_802_3_packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN PUCHAR pHeader802_3, - IN UCHAR FromWhichBSSID); - -UINT deaggregate_AMSDU_announce( - IN PRTMP_ADAPTER pAd, - PNDIS_PACKET pPacket, - IN PUCHAR pData, - IN ULONG DataSize); - -// remove LLC and get 802_3 Header +void wlan_802_11_to_802_3_packet(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, + u8 *pHeader802_3, + u8 FromWhichBSSID); + +/* remove LLC and get 802_3 Header */ #define RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(_pRxBlk, _pHeader802_3) \ { \ - PUCHAR _pRemovedLLCSNAP = NULL, _pDA, _pSA; \ + u8 *_pRemovedLLCSNAP = NULL, *_pDA, *_pSA; \ \ if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_MESH)) \ { \ _pDA = _pRxBlk->pHeader->Addr3; \ - _pSA = (PUCHAR)_pRxBlk->pHeader + sizeof(HEADER_802_11); \ + _pSA = (u8 *)_pRxBlk->pHeader + sizeof(struct rt_header_802_11); \ } \ else \ { \ @@ -5565,133 +3742,122 @@ UINT deaggregate_AMSDU_announce( _pRxBlk->DataSize, _pRemovedLLCSNAP); \ } -VOID Sta_Announce_or_Forward_802_3_Packet( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR FromWhichBSSID); +void Sta_Announce_or_Forward_802_3_Packet(struct rt_rtmp_adapter *pAd, + void *pPacket, + u8 FromWhichBSSID); #define ANNOUNCE_OR_FORWARD_802_3_PACKET(_pAd, _pPacket, _FromWhichBSS)\ Sta_Announce_or_Forward_802_3_Packet(_pAd, _pPacket, _FromWhichBSS); - //announce_802_3_packet(_pAd, _pPacket); - -PNDIS_PACKET DuplicatePacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR FromWhichBSSID); + /*announce_802_3_packet(_pAd, _pPacket); */ +void *DuplicatePacket(struct rt_rtmp_adapter *pAd, + void *pPacket, u8 FromWhichBSSID); -PNDIS_PACKET ClonePacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN PUCHAR pData, - IN ULONG DataSize); +void *ClonePacket(struct rt_rtmp_adapter *pAd, + void *pPacket, + u8 *pData, unsigned long DataSize); +/* Normal, AMPDU or AMSDU */ +void CmmRxnonRalinkFrameIndicate(struct rt_rtmp_adapter *pAd, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID); -// Normal, AMPDU or AMSDU -VOID CmmRxnonRalinkFrameIndicate( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); +void CmmRxRalinkFrameIndicate(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID); -VOID CmmRxRalinkFrameIndicate( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); +void Update_Rssi_Sample(struct rt_rtmp_adapter *pAd, + struct rt_rssi_sample *pRssi, struct rt_rxwi * pRxWI); -VOID Update_Rssi_Sample( - IN PRTMP_ADAPTER pAd, - IN RSSI_SAMPLE *pRssi, - IN PRXWI_STRUC pRxWI); +void *GetPacketFromRxRing(struct rt_rtmp_adapter *pAd, + OUT PRT28XX_RXD_STRUC pSaveRxD, + OUT BOOLEAN * pbReschedule, + IN u32 * pRxPending); -PNDIS_PACKET RTMPDeFragmentDataFrame( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk); +void *RTMPDeFragmentDataFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk); -//////////////////////////////////////// enum { - DIDmsg_lnxind_wlansniffrm = 0x00000044, - DIDmsg_lnxind_wlansniffrm_hosttime = 0x00010044, - DIDmsg_lnxind_wlansniffrm_mactime = 0x00020044, - DIDmsg_lnxind_wlansniffrm_channel = 0x00030044, - DIDmsg_lnxind_wlansniffrm_rssi = 0x00040044, - DIDmsg_lnxind_wlansniffrm_sq = 0x00050044, - DIDmsg_lnxind_wlansniffrm_signal = 0x00060044, - DIDmsg_lnxind_wlansniffrm_noise = 0x00070044, - DIDmsg_lnxind_wlansniffrm_rate = 0x00080044, - DIDmsg_lnxind_wlansniffrm_istx = 0x00090044, - DIDmsg_lnxind_wlansniffrm_frmlen = 0x000A0044 + DIDmsg_lnxind_wlansniffrm = 0x00000044, + DIDmsg_lnxind_wlansniffrm_hosttime = 0x00010044, + DIDmsg_lnxind_wlansniffrm_mactime = 0x00020044, + DIDmsg_lnxind_wlansniffrm_channel = 0x00030044, + DIDmsg_lnxind_wlansniffrm_rssi = 0x00040044, + DIDmsg_lnxind_wlansniffrm_sq = 0x00050044, + DIDmsg_lnxind_wlansniffrm_signal = 0x00060044, + DIDmsg_lnxind_wlansniffrm_noise = 0x00070044, + DIDmsg_lnxind_wlansniffrm_rate = 0x00080044, + DIDmsg_lnxind_wlansniffrm_istx = 0x00090044, + DIDmsg_lnxind_wlansniffrm_frmlen = 0x000A0044 }; enum { - P80211ENUM_msgitem_status_no_value = 0x00 + P80211ENUM_msgitem_status_no_value = 0x00 }; enum { - P80211ENUM_truth_false = 0x00, - P80211ENUM_truth_true = 0x01 + P80211ENUM_truth_false = 0x00, + P80211ENUM_truth_true = 0x01 }; /* Definition from madwifi */ -typedef struct { - UINT32 did; - UINT16 status; - UINT16 len; - UINT32 data; -} p80211item_uint32_t; - -typedef struct { - UINT32 msgcode; - UINT32 msglen; +struct rt_p80211item_uint32 { + u32 did; + u16 status; + u16 len; + u32 data; +}; + +struct rt_wlan_ng_prism2_header { + u32 msgcode; + u32 msglen; #define WLAN_DEVNAMELEN_MAX 16 - UINT8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t hosttime; - p80211item_uint32_t mactime; - p80211item_uint32_t channel; - p80211item_uint32_t rssi; - p80211item_uint32_t sq; - p80211item_uint32_t signal; - p80211item_uint32_t noise; - p80211item_uint32_t rate; - p80211item_uint32_t istx; - p80211item_uint32_t frmlen; -} wlan_ng_prism2_header; + u8 devname[WLAN_DEVNAMELEN_MAX]; + struct rt_p80211item_uint32 hosttime; + struct rt_p80211item_uint32 mactime; + struct rt_p80211item_uint32 channel; + struct rt_p80211item_uint32 rssi; + struct rt_p80211item_uint32 sq; + struct rt_p80211item_uint32 signal; + struct rt_p80211item_uint32 noise; + struct rt_p80211item_uint32 rate; + struct rt_p80211item_uint32 istx; + struct rt_p80211item_uint32 frmlen; +}; /* The radio capture header precedes the 802.11 header. */ -typedef struct PACKED _ieee80211_radiotap_header { - UINT8 it_version; /* Version 0. Only increases +struct PACKED rt_ieee80211_radiotap_header { + u8 it_version; /* Version 0. Only increases * for drastic changes, * introduction of compatible * new fields does not count. */ - UINT8 it_pad; - UINT16 it_len; /* length of the whole + u8 it_pad; + u16 it_len; /* length of the whole * header in bytes, including * it_version, it_pad, * it_len, and data fields. */ - UINT32 it_present; /* A bitmap telling which - * fields are present. Set bit 31 - * (0x80000000) to extend the - * bitmap by another 32 bits. - * Additional extensions are made - * by setting bit 31. - */ -}ieee80211_radiotap_header ; + u32 it_present; /* A bitmap telling which + * fields are present. Set bit 31 + * (0x80000000) to extend the + * bitmap by another 32 bits. + * Additional extensions are made + * by setting bit 31. + */ +}; enum ieee80211_radiotap_type { - IEEE80211_RADIOTAP_TSFT = 0, - IEEE80211_RADIOTAP_FLAGS = 1, - IEEE80211_RADIOTAP_RATE = 2, - IEEE80211_RADIOTAP_CHANNEL = 3, - IEEE80211_RADIOTAP_FHSS = 4, - IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, - IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, - IEEE80211_RADIOTAP_LOCK_QUALITY = 7, - IEEE80211_RADIOTAP_TX_ATTENUATION = 8, - IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, - IEEE80211_RADIOTAP_DBM_TX_POWER = 10, - IEEE80211_RADIOTAP_ANTENNA = 11, - IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, - IEEE80211_RADIOTAP_DB_ANTNOISE = 13 + IEEE80211_RADIOTAP_TSFT = 0, + IEEE80211_RADIOTAP_FLAGS = 1, + IEEE80211_RADIOTAP_RATE = 2, + IEEE80211_RADIOTAP_CHANNEL = 3, + IEEE80211_RADIOTAP_FHSS = 4, + IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, + IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, + IEEE80211_RADIOTAP_LOCK_QUALITY = 7, + IEEE80211_RADIOTAP_TX_ATTENUATION = 8, + IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, + IEEE80211_RADIOTAP_DBM_TX_POWER = 10, + IEEE80211_RADIOTAP_ANTENNA = 11, + IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, + IEEE80211_RADIOTAP_DB_ANTNOISE = 13 }; #define WLAN_RADIOTAP_PRESENT ( \ @@ -5700,737 +3866,491 @@ enum ieee80211_radiotap_type { (1 << IEEE80211_RADIOTAP_RATE) | \ 0) -typedef struct _wlan_radiotap_header { - ieee80211_radiotap_header wt_ihdr; - INT64 wt_tsft; - UINT8 wt_flags; - UINT8 wt_rate; -} wlan_radiotap_header; +struct rt_wlan_radiotap_header { + struct rt_ieee80211_radiotap_header wt_ihdr; + long long wt_tsft; + u8 wt_flags; + u8 wt_rate; +}; /* Definition from madwifi */ -void send_monitor_packets( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk); +void send_monitor_packets(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk); -// This function will be called when query /proc -struct iw_statistics *rt28xx_get_wireless_stats( - IN struct net_device *net_dev); +void RTMPSetDesiredRates(struct rt_rtmp_adapter *pAdapter, long Rates); -VOID RTMPSetDesiredRates( - IN PRTMP_ADAPTER pAdapter, - IN LONG Rates); +int Set_FixedTxMode_Proc(struct rt_rtmp_adapter *pAd, char *arg); -INT Set_FixedTxMode_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +BOOLEAN RT28XXChipsetCheck(IN void *_dev_p); -static inline char* GetPhyMode( - int Mode) -{ - switch(Mode) - { - case MODE_CCK: - return "CCK"; - - case MODE_OFDM: - return "OFDM"; - case MODE_HTMIX: - return "HTMIX"; - - case MODE_HTGREENFIELD: - return "GREEN"; - default: - return "N/A"; - } -} +void RT28XXDMADisable(struct rt_rtmp_adapter *pAd); +void RT28XXDMAEnable(struct rt_rtmp_adapter *pAd); -static inline char* GetBW( - int BW) -{ - switch(BW) - { - case BW_10: - return "10M"; - - case BW_20: - return "20M"; - case BW_40: - return "40M"; - default: - return "N/A"; - } -} +void RT28xx_UpdateBeaconToAsic(struct rt_rtmp_adapter *pAd, + int apidx, + unsigned long BeaconLen, unsigned long UpdatePos); +int rt28xx_init(struct rt_rtmp_adapter *pAd, + char *pDefaultMac, char *pHostName); -VOID RT28xxThreadTerminate( - IN RTMP_ADAPTER *pAd); +int RtmpNetTaskInit(struct rt_rtmp_adapter *pAd); -BOOLEAN RT28XXChipsetCheck( - IN void *_dev_p); +void RtmpNetTaskExit(struct rt_rtmp_adapter *pAd); -BOOLEAN RT28XXNetDevInit( - IN void *_dev_p, - IN struct net_device *net_dev, - IN RTMP_ADAPTER *pAd); +int RtmpMgmtTaskInit(struct rt_rtmp_adapter *pAd); -BOOLEAN RT28XXProbePostConfig( - IN void *_dev_p, - IN RTMP_ADAPTER *pAd, - IN INT32 argc); +void RtmpMgmtTaskExit(struct rt_rtmp_adapter *pAd); -VOID RT28XXDMADisable( - IN RTMP_ADAPTER *pAd); +void tbtt_tasklet(unsigned long data); -VOID RT28XXDMAEnable( - IN RTMP_ADAPTER *pAd); +struct net_device *RtmpPhyNetDevInit(struct rt_rtmp_adapter *pAd, + struct rt_rtmp_os_netdev_op_hook *pNetHook); -VOID RT28xx_UpdateBeaconToAsic( - IN RTMP_ADAPTER * pAd, - IN INT apidx, - IN ULONG BeaconLen, - IN ULONG UpdatePos); +BOOLEAN RtmpPhyNetDevExit(struct rt_rtmp_adapter *pAd, struct net_device *net_dev); -INT rt28xx_sta_ioctl( - IN struct net_device *net_dev, - IN OUT struct ifreq *rq, - IN INT cmd); +int RtmpRaDevCtrlInit(struct rt_rtmp_adapter *pAd, IN RTMP_INF_TYPE infType); -//////////////////////////////////////// -PNDIS_PACKET GetPacketFromRxRing( - IN PRTMP_ADAPTER pAd, - OUT PRT28XX_RXD_STRUC pSaveRxD, - OUT BOOLEAN *pbReschedule, - IN OUT UINT32 *pRxPending); +BOOLEAN RtmpRaDevCtrlExit(struct rt_rtmp_adapter *pAd); +#ifdef RTMP_MAC_PCI +/* */ +/* Function Prototype in cmm_data_pci.c */ +/* */ +u16 RtmpPCI_WriteTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + IN BOOLEAN bIsLast, u16 * FreeNumber); -void kill_thread_task(PRTMP_ADAPTER pAd); +u16 RtmpPCI_WriteSingleTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + IN BOOLEAN bIsLast, + u16 * FreeNumber); -void tbtt_tasklet(unsigned long data); +u16 RtmpPCI_WriteMultiTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + u8 frameNum, u16 * FreeNumber); -#ifdef RT2860 -// -// Function Prototype in cmm_data_2860.c -// -USHORT RtmpPCI_WriteTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN BOOLEAN bIsLast, - OUT USHORT *FreeNumber); - -USHORT RtmpPCI_WriteSingleTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN BOOLEAN bIsLast, - OUT USHORT *FreeNumber); - -USHORT RtmpPCI_WriteMultiTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR frameNum, - OUT USHORT *FreeNumber); - -USHORT RtmpPCI_WriteFragTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR fragNum, - OUT USHORT *FreeNumber); - -USHORT RtmpPCI_WriteSubTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN BOOLEAN bIsLast, - OUT USHORT *FreeNumber); - -VOID RtmpPCI_FinalWriteTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN USHORT totalMPDUSize, - IN USHORT FirstTxIdx); - -VOID RtmpPCIDataLastTxIdx( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN USHORT LastTxIdx); - -VOID RtmpPCIDataKickOut( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR QueIdx); - - -int RtmpPCIMgmtKickOut( - IN RTMP_ADAPTER *pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket, - IN PUCHAR pSrcBufVA, - IN UINT SrcBufLen); - - -NDIS_STATUS RTMPCheckRxError( - IN PRTMP_ADAPTER pAd, - IN PHEADER_802_11 pHeader, - IN PRXWI_STRUC pRxWI, - IN PRT28XX_RXD_STRUC pRxD); - -VOID RTMPInitPCIeLinkCtrlValue( - IN PRTMP_ADAPTER pAd); - -VOID RTMPFindHostPCIDev( - IN PRTMP_ADAPTER pAd); - -VOID RTMPPCIeLinkCtrlValueRestore( - IN PRTMP_ADAPTER pAd, - IN UCHAR Level); - -VOID RTMPPCIeLinkCtrlSetting( - IN PRTMP_ADAPTER pAd, - IN USHORT Max); - -VOID RT28xxPciAsicRadioOff( - IN PRTMP_ADAPTER pAd, - IN UCHAR Level, - IN USHORT TbttNumToNextWakeUp); - -BOOLEAN RT28xxPciAsicRadioOn( - IN PRTMP_ADAPTER pAd, - IN UCHAR Level); - -VOID RT28xxPciStaAsicForceWakeup( - IN PRTMP_ADAPTER pAd, - IN UCHAR Level); - -VOID RT28xxPciStaAsicSleepThenAutoWakeup( - IN PRTMP_ADAPTER pAd, - IN USHORT TbttNumToNextWakeUp); - -VOID PsPollWakeExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID RadioOnExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID RT28xxPciMlmeRadioOn( - IN PRTMP_ADAPTER pAd); - -VOID RT28xxPciMlmeRadioOFF( - IN PRTMP_ADAPTER pAd); -#endif /* RT2860 */ - -VOID AsicTurnOffRFClk( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel); - -VOID AsicTurnOnRFClk( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel); - -NTSTATUS RT30xxWriteRFRegister( - IN PRTMP_ADAPTER pAd, - IN UCHAR RegID, - IN UCHAR Value); - -NTSTATUS RT30xxReadRFRegister( - IN PRTMP_ADAPTER pAd, - IN UCHAR RegID, - IN PUCHAR pValue); - -UCHAR eFuseReadRegisters( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - OUT USHORT* pData); - -VOID eFuseReadPhysical( - IN PRTMP_ADAPTER pAd, - IN PUSHORT lpInBuffer, - IN ULONG nInBufferSize, - OUT PUSHORT lpOutBuffer, - IN ULONG nOutBufferSize -); - -NTSTATUS eFuseRead( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - OUT PUCHAR pData, - IN USHORT Length); - -VOID eFusePhysicalWriteRegisters( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - OUT USHORT* pData); - -NTSTATUS eFuseWriteRegisters( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - IN USHORT* pData); - -VOID eFuseWritePhysical( - IN PRTMP_ADAPTER pAd, - PUSHORT lpInBuffer, - ULONG nInBufferSize, - PUCHAR lpOutBuffer, - ULONG nOutBufferSize -); - -NTSTATUS eFuseWrite( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN PUCHAR pData, - IN USHORT length); - -INT set_eFuseGetFreeBlockCount_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -INT set_eFusedump_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -INT set_eFuseLoadFromBin_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -NTSTATUS eFuseWriteRegistersFromBin( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - IN USHORT* pData); - -VOID eFusePhysicalReadRegisters( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - OUT USHORT* pData); - -VOID RT30xxLoadRFNormalModeSetup( - IN PRTMP_ADAPTER pAd); - -VOID RT30xxLoadRFSleepModeSetup( - IN PRTMP_ADAPTER pAd); - -VOID RT30xxReverseRFSleepModeSetup( - IN PRTMP_ADAPTER pAd); - -#ifdef RT2870 -// -// Function Prototype in rtusb_bulk.c -// -VOID RTUSBInitTxDesc( - IN PRTMP_ADAPTER pAd, - IN PTX_CONTEXT pTxContext, - IN UCHAR BulkOutPipeId, - IN usb_complete_t Func); - -VOID RTUSBInitHTTxDesc( - IN PRTMP_ADAPTER pAd, - IN PHT_TX_CONTEXT pTxContext, - IN UCHAR BulkOutPipeId, - IN ULONG BulkOutSize, - IN usb_complete_t Func); - -VOID RTUSBCleanUpDataBulkOutQueue( - IN PRTMP_ADAPTER pAd); - -VOID RTUSBCancelPendingBulkOutIRP( - IN PRTMP_ADAPTER pAd); - -VOID RTUSBBulkOutDataPacket( - IN PRTMP_ADAPTER pAd, - IN UCHAR BulkOutPipeId, - IN UCHAR Index); - -VOID RTUSBBulkOutNullFrame( - IN PRTMP_ADAPTER pAd); - -VOID RTUSBBulkOutRTSFrame( - IN PRTMP_ADAPTER pAd); - -VOID RTUSBCancelPendingBulkInIRP( - IN PRTMP_ADAPTER pAd); - -VOID RTUSBCancelPendingIRPs( - IN PRTMP_ADAPTER pAd); - -VOID RTUSBBulkOutMLMEPacket( - IN PRTMP_ADAPTER pAd, - IN UCHAR Index); - -VOID RTUSBBulkOutPsPoll( - IN PRTMP_ADAPTER pAd); - -VOID RTUSBCleanUpMLMEBulkOutQueue( - IN PRTMP_ADAPTER pAd); - -VOID RTUSBKickBulkOut( - IN PRTMP_ADAPTER pAd); - -VOID RTUSBBulkReceive( - IN PRTMP_ADAPTER pAd); - -VOID DoBulkIn( - IN RTMP_ADAPTER *pAd); - -VOID RTUSBInitRxDesc( - IN PRTMP_ADAPTER pAd, - IN PRX_CONTEXT pRxContext); - -// -// Function Prototype in rtusb_io.c -// -NTSTATUS RTUSBMultiRead( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - OUT PUCHAR pData, - IN USHORT length); - -NTSTATUS RTUSBMultiWrite( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN PUCHAR pData, - IN USHORT length); - -NTSTATUS RTUSBMultiWrite_OneByte( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN PUCHAR pData); - -NTSTATUS RTUSBReadBBPRegister( - IN PRTMP_ADAPTER pAd, - IN UCHAR Id, - IN PUCHAR pValue); - -NTSTATUS RTUSBWriteBBPRegister( - IN PRTMP_ADAPTER pAd, - IN UCHAR Id, - IN UCHAR Value); - -NTSTATUS RTUSBWriteRFRegister( - IN PRTMP_ADAPTER pAd, - IN UINT32 Value); - -NTSTATUS RTUSB_VendorRequest( - IN PRTMP_ADAPTER pAd, - IN UINT32 TransferFlags, - IN UCHAR ReservedBits, - IN UCHAR Request, - IN USHORT Value, - IN USHORT Index, - IN PVOID TransferBuffer, - IN UINT32 TransferBufferLength); - -NTSTATUS RTUSBReadEEPROM( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - OUT PUCHAR pData, - IN USHORT length); - -NTSTATUS RTUSBWriteEEPROM( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN PUCHAR pData, - IN USHORT length); +u16 RtmpPCI_WriteFragTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + u8 fragNum, u16 * FreeNumber); -VOID RTUSBPutToSleep( - IN PRTMP_ADAPTER pAd); +u16 RtmpPCI_WriteSubTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + IN BOOLEAN bIsLast, u16 * FreeNumber); -NTSTATUS RTUSBWakeUp( - IN PRTMP_ADAPTER pAd); +void RtmpPCI_FinalWriteTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + u16 totalMPDUSize, + u16 FirstTxIdx); -VOID RTUSBInitializeCmdQ( - IN PCmdQ cmdq); +void RtmpPCIDataLastTxIdx(struct rt_rtmp_adapter *pAd, + u8 QueIdx, u16 LastTxIdx); -NDIS_STATUS RTUSBEnqueueCmdFromNdis( - IN PRTMP_ADAPTER pAd, - IN NDIS_OID Oid, - IN BOOLEAN SetInformation, - IN PVOID pInformationBuffer, - IN UINT32 InformationBufferLength); +void RtmpPCIDataKickOut(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, u8 QueIdx); -NDIS_STATUS RTUSBEnqueueInternalCmd( - IN PRTMP_ADAPTER pAd, - IN NDIS_OID Oid, - IN PVOID pInformationBuffer, - IN UINT32 InformationBufferLength); +int RtmpPCIMgmtKickOut(struct rt_rtmp_adapter *pAd, + u8 QueIdx, + void *pPacket, + u8 *pSrcBufVA, u32 SrcBufLen); -VOID RTUSBDequeueCmd( - IN PCmdQ cmdq, - OUT PCmdQElmt *pcmdqelmt); - -INT RTUSBCmdThread( - IN OUT PVOID Context); - -INT TimerQThread( - IN OUT PVOID Context); - -RT2870_TIMER_ENTRY *RT2870_TimerQ_Insert( - IN RTMP_ADAPTER *pAd, - IN RALINK_TIMER_STRUCT *pTimer); +int RTMPCheckRxError(struct rt_rtmp_adapter *pAd, + struct rt_header_802_11 * pHeader, + struct rt_rxwi * pRxWI, IN PRT28XX_RXD_STRUC pRxD); -BOOLEAN RT2870_TimerQ_Remove( - IN RTMP_ADAPTER *pAd, - IN RALINK_TIMER_STRUCT *pTimer); - -void RT2870_TimerQ_Exit( - IN RTMP_ADAPTER *pAd); - -void RT2870_TimerQ_Init( - IN RTMP_ADAPTER *pAd); - -VOID RT2870_BssBeaconExit( - IN RTMP_ADAPTER *pAd); - -VOID RT2870_BssBeaconStop( - IN RTMP_ADAPTER *pAd); - -VOID RT2870_BssBeaconStart( - IN RTMP_ADAPTER * pAd); - -VOID RT2870_BssBeaconInit( - IN RTMP_ADAPTER *pAd); - -VOID RT2870_WatchDog( - IN RTMP_ADAPTER *pAd); - -NTSTATUS RTUSBWriteMACRegister( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN UINT32 Value); - -NTSTATUS RTUSBReadMACRegister( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - OUT PUINT32 pValue); - -NTSTATUS RTUSBSingleWrite( - IN RTMP_ADAPTER *pAd, - IN USHORT Offset, - IN USHORT Value); - -NTSTATUS RTUSBFirmwareRun( - IN PRTMP_ADAPTER pAd); - -NTSTATUS RTUSBFirmwareWrite( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pFwImage, - IN ULONG FwLen); - -NTSTATUS RTUSBFirmwareOpmode( - IN PRTMP_ADAPTER pAd, - OUT PUINT32 pValue); - -NTSTATUS RTUSBVenderReset( - IN PRTMP_ADAPTER pAd); - -VOID CMDHandler( - IN PRTMP_ADAPTER pAd); - - -NDIS_STATUS CreateThreads( - IN struct net_device *net_dev ); - - -VOID MacTableInitialize( - IN PRTMP_ADAPTER pAd); - -VOID MlmeSetPsm( - IN PRTMP_ADAPTER pAd, - IN USHORT psm); - -NDIS_STATUS RTMPWPAAddKeyProc( - IN PRTMP_ADAPTER pAd, - IN PVOID pBuf); - -VOID AsicRxAntEvalAction( - IN PRTMP_ADAPTER pAd); - -NDIS_STATUS RTMPCheckRxError( - IN PRTMP_ADAPTER pAd, - IN PHEADER_802_11 pHeader, - IN PRXWI_STRUC pRxWI, - IN PRT28XX_RXD_STRUC pRxINFO); - -INT MlmeThread( - IN PVOID Context); - -// -// Function Prototype in rtusb_data.c -// -NDIS_STATUS RTUSBFreeDescriptorRequest( - IN PRTMP_ADAPTER pAd, - IN UCHAR BulkOutPipeId, - IN UINT32 NumberRequired); - - -BOOLEAN RTUSBNeedQueueBackForAgg( - IN RTMP_ADAPTER *pAd, - IN UCHAR BulkOutPipeId); +BOOLEAN RT28xxPciAsicRadioOff(struct rt_rtmp_adapter *pAd, + u8 Level, u16 TbttNumToNextWakeUp); +BOOLEAN RT28xxPciAsicRadioOn(struct rt_rtmp_adapter *pAd, u8 Level); -VOID RTMPWriteTxInfo( - IN PRTMP_ADAPTER pAd, - IN PTXINFO_STRUC pTxInfo, - IN USHORT USBDMApktLen, - IN BOOLEAN bWiv, - IN UCHAR QueueSel, - IN UCHAR NextValid, - IN UCHAR TxBurst); - -// -// Function Prototype in cmm_data_2870.c -// -USHORT RtmpUSB_WriteSubTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN BOOLEAN bIsLast, - OUT USHORT *FreeNumber); - -USHORT RtmpUSB_WriteSingleTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN BOOLEAN bIsLast, - OUT USHORT *FreeNumber); - -USHORT RtmpUSB_WriteFragTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR fragNum, - OUT USHORT *FreeNumber); - -USHORT RtmpUSB_WriteMultiTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR frameNum, - OUT USHORT *FreeNumber); - -VOID RtmpUSB_FinalWriteTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN USHORT totalMPDUSize, -#ifdef RT2860 - IN USHORT FirstTxIdx); -#endif - IN USHORT TxIdx); +void RTMPInitPCIeLinkCtrlValue(struct rt_rtmp_adapter *pAd); -VOID RtmpUSBDataLastTxIdx( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN USHORT TxIdx); +void RTMPFindHostPCIDev(struct rt_rtmp_adapter *pAd); -VOID RtmpUSBDataKickOut( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR QueIdx); +void RTMPPCIeLinkCtrlValueRestore(struct rt_rtmp_adapter *pAd, u8 Level); +void RTMPPCIeLinkCtrlSetting(struct rt_rtmp_adapter *pAd, u16 Max); -int RtmpUSBMgmtKickOut( - IN RTMP_ADAPTER *pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket, - IN PUCHAR pSrcBufVA, - IN UINT SrcBufLen); +void RTMPrt3xSetPCIePowerLinkCtrl(struct rt_rtmp_adapter *pAd); -VOID RtmpUSBNullFrameKickOut( - IN RTMP_ADAPTER *pAd, - IN UCHAR QueIdx, - IN UCHAR *pNullFrame, - IN UINT32 frameLen); +void PsPollWakeExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); -VOID RT28xxUsbStaAsicForceWakeup( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bFromTx); +void RadioOnExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3); -VOID RT28xxUsbStaAsicSleepThenAutoWakeup( - IN PRTMP_ADAPTER pAd, - IN USHORT TbttNumToNextWakeUp); +void RT28xxPciStaAsicForceWakeup(struct rt_rtmp_adapter *pAd, IN BOOLEAN bFromTx); -VOID RT28xxUsbMlmeRadioOn( - IN PRTMP_ADAPTER pAd); +void RT28xxPciStaAsicSleepThenAutoWakeup(struct rt_rtmp_adapter *pAd, + u16 TbttNumToNextWakeUp); -VOID RT28xxUsbMlmeRadioOFF( - IN PRTMP_ADAPTER pAd); -#endif // RT2870 // +void RT28xxPciMlmeRadioOn(struct rt_rtmp_adapter *pAd); -INT RTMPShowCfgValue( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pName, - IN PUCHAR pBuf); +void RT28xxPciMlmeRadioOFF(struct rt_rtmp_adapter *pAd); +#endif /* RTMP_MAC_PCI // */ -PCHAR RTMPGetRalinkAuthModeStr( - IN NDIS_802_11_AUTHENTICATION_MODE authMode); +#ifdef RTMP_MAC_USB +/* */ +/* Function Prototype in rtusb_bulk.c */ +/* */ +void RTUSBInitTxDesc(struct rt_rtmp_adapter *pAd, + struct rt_tx_context *pTxContext, + u8 BulkOutPipeId, IN usb_complete_t Func); -PCHAR RTMPGetRalinkEncryModeStr( - IN USHORT encryMode); +void RTUSBInitHTTxDesc(struct rt_rtmp_adapter *pAd, + struct rt_ht_tx_context *pTxContext, + u8 BulkOutPipeId, + unsigned long BulkOutSize, IN usb_complete_t Func); -VOID AsicStaBbpTuning( - IN PRTMP_ADAPTER pAd); +void RTUSBInitRxDesc(struct rt_rtmp_adapter *pAd, struct rt_rx_context *pRxContext); -#ifdef RT2860 -VOID AsicResetFromDMABusy( - IN PRTMP_ADAPTER pAd); +void RTUSBCleanUpDataBulkOutQueue(struct rt_rtmp_adapter *pAd); -VOID AsicResetBBP( - IN PRTMP_ADAPTER pAd); +void RTUSBCancelPendingBulkOutIRP(struct rt_rtmp_adapter *pAd); -VOID AsicResetMAC( - IN PRTMP_ADAPTER pAd); +void RTUSBBulkOutDataPacket(struct rt_rtmp_adapter *pAd, + u8 BulkOutPipeId, u8 Index); -VOID AsicResetPBF( - IN PRTMP_ADAPTER pAd); -#endif -#ifdef RT2870 -BOOLEAN StaAddMacTableEntry( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN UCHAR MaxSupportedRateIn500Kbps, - IN HT_CAPABILITY_IE *pHtCapability, - IN UCHAR HtCapabilityLen, - IN USHORT CapabilityInfo); -#endif +void RTUSBBulkOutNullFrame(struct rt_rtmp_adapter *pAd); + +void RTUSBBulkOutRTSFrame(struct rt_rtmp_adapter *pAd); + +void RTUSBCancelPendingBulkInIRP(struct rt_rtmp_adapter *pAd); + +void RTUSBCancelPendingIRPs(struct rt_rtmp_adapter *pAd); + +void RTUSBBulkOutMLMEPacket(struct rt_rtmp_adapter *pAd, u8 Index); + +void RTUSBBulkOutPsPoll(struct rt_rtmp_adapter *pAd); + +void RTUSBCleanUpMLMEBulkOutQueue(struct rt_rtmp_adapter *pAd); + +void RTUSBKickBulkOut(struct rt_rtmp_adapter *pAd); + +void RTUSBBulkReceive(struct rt_rtmp_adapter *pAd); + +void DoBulkIn(struct rt_rtmp_adapter *pAd); + +void RTUSBInitRxDesc(struct rt_rtmp_adapter *pAd, struct rt_rx_context *pRxContext); + +void RTUSBBulkRxHandle(IN unsigned long data); + +/* */ +/* Function Prototype in rtusb_io.c */ +/* */ +int RTUSBMultiRead(struct rt_rtmp_adapter *pAd, + u16 Offset, u8 *pData, u16 length); + +int RTUSBMultiWrite(struct rt_rtmp_adapter *pAd, + u16 Offset, u8 *pData, u16 length); + +int RTUSBMultiWrite_OneByte(struct rt_rtmp_adapter *pAd, + u16 Offset, u8 *pData); + +int RTUSBReadBBPRegister(struct rt_rtmp_adapter *pAd, + u8 Id, u8 *pValue); + +int RTUSBWriteBBPRegister(struct rt_rtmp_adapter *pAd, + u8 Id, u8 Value); + +int RTUSBWriteRFRegister(struct rt_rtmp_adapter *pAd, u32 Value); + +int RTUSB_VendorRequest(struct rt_rtmp_adapter *pAd, + u32 TransferFlags, + u8 ReservedBits, + u8 Request, + u16 Value, + u16 Index, + void *TransferBuffer, + u32 TransferBufferLength); + +int RTUSBReadEEPROM(struct rt_rtmp_adapter *pAd, + u16 Offset, u8 *pData, u16 length); + +int RTUSBWriteEEPROM(struct rt_rtmp_adapter *pAd, + u16 Offset, u8 *pData, u16 length); + +void RTUSBPutToSleep(struct rt_rtmp_adapter *pAd); + +int RTUSBWakeUp(struct rt_rtmp_adapter *pAd); + +void RTUSBInitializeCmdQ(struct rt_cmdq *cmdq); + +int RTUSBEnqueueCmdFromNdis(struct rt_rtmp_adapter *pAd, + IN NDIS_OID Oid, + IN BOOLEAN SetInformation, + void *pInformationBuffer, + u32 InformationBufferLength); + +int RTUSBEnqueueInternalCmd(struct rt_rtmp_adapter *pAd, + IN NDIS_OID Oid, + void *pInformationBuffer, + u32 InformationBufferLength); + +void RTUSBDequeueCmd(struct rt_cmdq *cmdq, struct rt_cmdqelmt * * pcmdqelmt); + +int RTUSBCmdThread(IN void *Context); + +void RTUSBBssBeaconExit(struct rt_rtmp_adapter *pAd); + +void RTUSBBssBeaconStop(struct rt_rtmp_adapter *pAd); + +void RTUSBBssBeaconStart(struct rt_rtmp_adapter *pAd); + +void RTUSBBssBeaconInit(struct rt_rtmp_adapter *pAd); + +void RTUSBWatchDog(struct rt_rtmp_adapter *pAd); + +int RTUSBWriteMACRegister(struct rt_rtmp_adapter *pAd, + u16 Offset, u32 Value); + +int RTUSBReadMACRegister(struct rt_rtmp_adapter *pAd, + u16 Offset, u32 *pValue); + +int RTUSBSingleWrite(struct rt_rtmp_adapter *pAd, + u16 Offset, u16 Value); + +int RTUSBFirmwareWrite(struct rt_rtmp_adapter *pAd, + u8 *pFwImage, unsigned long FwLen); + +int RTUSBVenderReset(struct rt_rtmp_adapter *pAd); + +int RTUSBSetHardWareRegister(struct rt_rtmp_adapter *pAdapter, void *pBuf); + +int RTUSBQueryHardWareRegister(struct rt_rtmp_adapter *pAdapter, + void *pBuf); + +void CMDHandler(struct rt_rtmp_adapter *pAd); + +int RTUSBWriteHWMACAddress(struct rt_rtmp_adapter *pAdapter); + +void MacTableInitialize(struct rt_rtmp_adapter *pAd); + +void MlmeSetPsm(struct rt_rtmp_adapter *pAd, u16 psm); -void RTMP_IndicateMediaState( - IN PRTMP_ADAPTER pAd); +int RTMPWPAAddKeyProc(struct rt_rtmp_adapter *pAd, void *pBuf); -VOID ReSyncBeaconTime( - IN PRTMP_ADAPTER pAd); +void AsicRxAntEvalAction(struct rt_rtmp_adapter *pAd); -VOID RTMPSetAGCInitValue( - IN PRTMP_ADAPTER pAd, - IN UCHAR BandWidth); +void append_pkt(struct rt_rtmp_adapter *pAd, + u8 *pHeader802_3, + u32 HdrLen, + u8 *pData, + unsigned long DataSize, void ** ppPacket); -int rt28xx_close(IN PNET_DEV dev); -int rt28xx_open(IN PNET_DEV dev); +u32 deaggregate_AMSDU_announce(struct rt_rtmp_adapter *pAd, + void *pPacket, + u8 *pData, unsigned long DataSize); -__inline INT VIRTUAL_IF_UP(PRTMP_ADAPTER pAd) +int RTMPCheckRxError(struct rt_rtmp_adapter *pAd, + struct rt_header_802_11 * pHeader, + struct rt_rxwi * pRxWI, + IN PRT28XX_RXD_STRUC pRxINFO); + +void RTUSBMlmeHardTransmit(struct rt_rtmp_adapter *pAd, struct rt_mgmt *pMgmt); + +int MlmeThread(void *Context); + +/* */ +/* Function Prototype in rtusb_data.c */ +/* */ +int RTUSBFreeDescriptorRequest(struct rt_rtmp_adapter *pAd, + u8 BulkOutPipeId, + u32 NumberRequired); + +BOOLEAN RTUSBNeedQueueBackForAgg(struct rt_rtmp_adapter *pAd, u8 BulkOutPipeId); + +void RTMPWriteTxInfo(struct rt_rtmp_adapter *pAd, + struct rt_txinfo *pTxInfo, + u16 USBDMApktLen, + IN BOOLEAN bWiv, + u8 QueueSel, u8 NextValid, u8 TxBurst); + +/* */ +/* Function Prototype in cmm_data_usb.c */ +/* */ +u16 RtmpUSB_WriteSubTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + IN BOOLEAN bIsLast, u16 * FreeNumber); + +u16 RtmpUSB_WriteSingleTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + IN BOOLEAN bIsLast, + u16 * FreeNumber); + +u16 RtmpUSB_WriteFragTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + u8 fragNum, u16 * FreeNumber); + +u16 RtmpUSB_WriteMultiTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + u8 frameNum, u16 * FreeNumber); + +void RtmpUSB_FinalWriteTxResource(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, + u16 totalMPDUSize, u16 TxIdx); + +void RtmpUSBDataLastTxIdx(struct rt_rtmp_adapter *pAd, + u8 QueIdx, u16 TxIdx); + +void RtmpUSBDataKickOut(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, u8 QueIdx); + +int RtmpUSBMgmtKickOut(struct rt_rtmp_adapter *pAd, + u8 QueIdx, + void *pPacket, + u8 *pSrcBufVA, u32 SrcBufLen); + +void RtmpUSBNullFrameKickOut(struct rt_rtmp_adapter *pAd, + u8 QueIdx, + u8 * pNullFrame, u32 frameLen); + +void RtmpUsbStaAsicForceWakeupTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, + void *SystemSpecific3); + +void RT28xxUsbStaAsicForceWakeup(struct rt_rtmp_adapter *pAd, IN BOOLEAN bFromTx); + +void RT28xxUsbStaAsicSleepThenAutoWakeup(struct rt_rtmp_adapter *pAd, + u16 TbttNumToNextWakeUp); + +void RT28xxUsbMlmeRadioOn(struct rt_rtmp_adapter *pAd); + +void RT28xxUsbMlmeRadioOFF(struct rt_rtmp_adapter *pAd); +#endif /* RTMP_MAC_USB // */ + +void AsicTurnOffRFClk(struct rt_rtmp_adapter *pAd, u8 Channel); + +void AsicTurnOnRFClk(struct rt_rtmp_adapter *pAd, u8 Channel); + +#ifdef RTMP_TIMER_TASK_SUPPORT +int RtmpTimerQThread(IN void *Context); + +struct rt_rtmp_timer_task_entry *RtmpTimerQInsert(struct rt_rtmp_adapter *pAd, + struct rt_ralink_timer *pTimer); + +BOOLEAN RtmpTimerQRemove(struct rt_rtmp_adapter *pAd, + struct rt_ralink_timer *pTimer); + +void RtmpTimerQExit(struct rt_rtmp_adapter *pAd); + +void RtmpTimerQInit(struct rt_rtmp_adapter *pAd); +#endif /* RTMP_TIMER_TASK_SUPPORT // */ + +void AsicStaBbpTuning(struct rt_rtmp_adapter *pAd); + +BOOLEAN StaAddMacTableEntry(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + u8 MaxSupportedRateIn500Kbps, + struct rt_ht_capability_ie * pHtCapability, + u8 HtCapabilityLen, + struct rt_add_ht_info_ie * pAddHtInfo, + u8 AddHtInfoLen, u16 CapabilityInfo); + +BOOLEAN AUTH_ReqSend(struct rt_rtmp_adapter *pAd, + struct rt_mlme_queue_elem *pElem, + struct rt_ralink_timer *pAuthTimer, + char *pSMName, + u16 SeqNo, + u8 *pNewElement, unsigned long ElementLen); + +void RTMP_IndicateMediaState(struct rt_rtmp_adapter *pAd); + +void ReSyncBeaconTime(struct rt_rtmp_adapter *pAd); + +void RTMPSetAGCInitValue(struct rt_rtmp_adapter *pAd, u8 BandWidth); + +int rt28xx_close(struct net_device *dev); +int rt28xx_open(struct net_device *dev); + +#define VIRTUAL_IF_INC(__pAd) ((__pAd)->VirtualIfCnt++) +#define VIRTUAL_IF_DEC(__pAd) ((__pAd)->VirtualIfCnt--) +#define VIRTUAL_IF_NUM(__pAd) ((__pAd)->VirtualIfCnt) + +#ifdef LINUX +__inline int VIRTUAL_IF_UP(struct rt_rtmp_adapter *pAd) { - if (VIRTUAL_IF_NUM(pAd) == 0) - { - if (rt28xx_open(pAd->net_dev) != 0) + if (VIRTUAL_IF_NUM(pAd) == 0) { + if (rt28xx_open(pAd->net_dev) != 0) { + DBGPRINT(RT_DEBUG_TRACE, + ("rt28xx_open return fail!\n")); return -1; - } - else - { + } + } else { } VIRTUAL_IF_INC(pAd); return 0; } -__inline VOID VIRTUAL_IF_DOWN(PRTMP_ADAPTER pAd) +__inline void VIRTUAL_IF_DOWN(struct rt_rtmp_adapter *pAd) { VIRTUAL_IF_DEC(pAd); if (VIRTUAL_IF_NUM(pAd) == 0) rt28xx_close(pAd->net_dev); return; } +#endif /* LINUX // */ + +/* + OS Related funciton prototype definitions. + TODO: Maybe we need to move these function prototypes to other proper place. +*/ +int RtmpOSWrielessEventSend(struct rt_rtmp_adapter *pAd, + u32 eventType, + int flags, + u8 *pSrcMac, + u8 *pData, u32 dataLen); + +int RtmpOSNetDevAddrSet(struct net_device *pNetDev, u8 *pMacAddr); + +int RtmpOSNetDevAttach(struct net_device *pNetDev, + struct rt_rtmp_os_netdev_op_hook *pDevOpHook); + +void RtmpOSNetDevClose(struct net_device *pNetDev); + +void RtmpOSNetDevDetach(struct net_device *pNetDev); + +int RtmpOSNetDevAlloc(struct net_device ** pNewNetDev, u32 privDataSize); + +void RtmpOSNetDevFree(struct net_device *pNetDev); + +struct net_device *RtmpOSNetDevGetByName(struct net_device *pNetDev, char *pDevName); + +void RtmpOSNetDeviceRefPut(struct net_device *pNetDev); + +struct net_device *RtmpOSNetDevCreate(struct rt_rtmp_adapter *pAd, + int devType, + int devNum, + int privMemSize, char *pNamePrefix); + +/* + Task operation related function prototypes +*/ +void RtmpOSTaskCustomize(struct rt_rtmp_os_task *pTask); + +int RtmpOSTaskNotifyToExit(struct rt_rtmp_os_task *pTask); + +int RtmpOSTaskKill(struct rt_rtmp_os_task *pTask); + +int RtmpOSTaskInit(struct rt_rtmp_os_task *pTask, + char *pTaskName, void * pPriv); + +int RtmpOSTaskAttach(struct rt_rtmp_os_task *pTask, + IN int (*fn) (void *), IN void *arg); + +/* + File operation related function prototypes +*/ +struct file *RtmpOSFileOpen(IN char *pPath, IN int flag, IN int mode); + +int RtmpOSFileClose(struct file *osfd); + +void RtmpOSFileSeek(struct file *osfd, IN int offset); +int RtmpOSFileRead(struct file *osfd, IN char *pDataPtr, IN int readLen); -#endif // __RTMP_H__ +int RtmpOSFileWrite(struct file *osfd, IN char *pDataPtr, IN int writeLen); +#endif /* __RTMP_H__ */ diff --git a/drivers/staging/rt2860/rtmp_chip.h b/drivers/staging/rt2860/rtmp_chip.h new file mode 100644 index 0000000000000000000000000000000000000000..0adf2cd2deb75ab632d7a4d6c57dad648944edcd --- /dev/null +++ b/drivers/staging/rt2860/rtmp_chip.h @@ -0,0 +1,258 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* + + Module Name: + rtmp_chip.h + + Abstract: + Ralink Wireless Chip related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RTMP_CHIP_H__ +#define __RTMP_CHIP_H__ + +#include "rtmp_type.h" + +#ifdef RT2860 +#include "chip/rt2860.h" +#endif /* RT2860 // */ +#ifdef RT2870 +#include "chip/rt2870.h" +#endif /* RT2870 // */ +#ifdef RT3070 +#include "chip/rt3070.h" +#endif /* RT3070 // */ +#ifdef RT3090 +#include "chip/rt3090.h" +#endif /* RT3090 // */ + +/* We will have a cost down version which mac version is 0x3090xxxx */ +/* */ +/* RT3090A facts */ +/* */ +/* a) 2.4 GHz */ +/* b) Replacement for RT3090 */ +/* c) Internal LNA */ +/* d) Interference over channel #14 */ +/* e) New BBP features (e.g., SIG re-modulation) */ +/* */ +#define IS_RT3090A(_pAd) ((((_pAd)->MACVersion & 0xffff0000) == 0x30900000)) + +/* We will have a cost down version which mac version is 0x3090xxxx */ +#define IS_RT3090(_pAd) ((((_pAd)->MACVersion & 0xffff0000) == 0x30710000) || (IS_RT3090A(_pAd))) + +#define IS_RT3070(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x30700000) +#define IS_RT3071(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x30710000) +#define IS_RT2070(_pAd) (((_pAd)->RfIcType == RFIC_2020) || ((_pAd)->EFuseTag == 0x27)) + +#define IS_RT30xx(_pAd) (((_pAd)->MACVersion & 0xfff00000) == 0x30700000||IS_RT3090A(_pAd)) +/*#define IS_RT305X(_pAd) ((_pAd)->MACVersion == 0x28720200) */ + +/* RT3572, 3592, 3562, 3062 share the same MAC version */ +#define IS_RT3572(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x35720000) +#define IS_VERSION_BEFORE_F(_pAd) (((_pAd)->MACVersion&0xffff) <= 0x0211) +/* F version is 0x0212, E version is 0x0211. 309x can save more power after F version. */ +#define IS_VERSION_AFTER_F(_pAd) ((((_pAd)->MACVersion&0xffff) >= 0x0212) || (((_pAd)->b3090ESpecialChip == TRUE))) +/* */ +/* RT3390 facts */ +/* */ +/* a) Base on RT3090 (RF IC: RT3020) */ +/* b) 2.4 GHz */ +/* c) 1x1 */ +/* d) Single chip */ +/* e) Internal components: PA and LNA */ +/* */ +/*RT3390,RT3370 */ +#define IS_RT3390(_pAd) (((_pAd)->MACVersion & 0xFFFF0000) == 0x33900000) + +/* ------------------------------------------------------ */ +/* PCI registers - base address 0x0000 */ +/* ------------------------------------------------------ */ +#define CHIP_PCI_CFG 0x0000 +#define CHIP_PCI_EECTRL 0x0004 +#define CHIP_PCI_MCUCTRL 0x0008 + +#define OPT_14 0x114 + +#define RETRY_LIMIT 10 + +/* ------------------------------------------------------ */ +/* BBP & RF definition */ +/* ------------------------------------------------------ */ +#define BUSY 1 +#define IDLE 0 + +/*------------------------------------------------------------------------- */ +/* EEPROM definition */ +/*------------------------------------------------------------------------- */ +#define EEDO 0x08 +#define EEDI 0x04 +#define EECS 0x02 +#define EESK 0x01 +#define EERL 0x80 + +#define EEPROM_WRITE_OPCODE 0x05 +#define EEPROM_READ_OPCODE 0x06 +#define EEPROM_EWDS_OPCODE 0x10 +#define EEPROM_EWEN_OPCODE 0x13 + +#define NUM_EEPROM_BBP_PARMS 19 /* Include NIC Config 0, 1, CR, TX ALC step, BBPs */ +#define NUM_EEPROM_TX_G_PARMS 7 +#define EEPROM_NIC1_OFFSET 0x34 /* The address is from NIC config 0, not BBP register ID */ +#define EEPROM_NIC2_OFFSET 0x36 /* The address is from NIC config 0, not BBP register ID */ +#define EEPROM_BBP_BASE_OFFSET 0xf0 /* The address is from NIC config 0, not BBP register ID */ +#define EEPROM_G_TX_PWR_OFFSET 0x52 +#define EEPROM_G_TX2_PWR_OFFSET 0x60 +#define EEPROM_LED1_OFFSET 0x3c +#define EEPROM_LED2_OFFSET 0x3e +#define EEPROM_LED3_OFFSET 0x40 +#define EEPROM_LNA_OFFSET 0x44 +#define EEPROM_RSSI_BG_OFFSET 0x46 +#define EEPROM_TXMIXER_GAIN_2_4G 0x48 +#define EEPROM_RSSI_A_OFFSET 0x4a +#define EEPROM_TXMIXER_GAIN_5G 0x4c +#define EEPROM_DEFINE_MAX_TXPWR 0x4e +#define EEPROM_TXPOWER_BYRATE_20MHZ_2_4G 0xde /* 20MHZ 2.4G tx power. */ +#define EEPROM_TXPOWER_BYRATE_40MHZ_2_4G 0xee /* 40MHZ 2.4G tx power. */ +#define EEPROM_TXPOWER_BYRATE_20MHZ_5G 0xfa /* 20MHZ 5G tx power. */ +#define EEPROM_TXPOWER_BYRATE_40MHZ_5G 0x10a /* 40MHZ 5G tx power. */ +#define EEPROM_A_TX_PWR_OFFSET 0x78 +#define EEPROM_A_TX2_PWR_OFFSET 0xa6 +/*#define EEPROM_Japan_TX_PWR_OFFSET 0x90 // 802.11j */ +/*#define EEPROM_Japan_TX2_PWR_OFFSET 0xbe */ +/*#define EEPROM_TSSI_REF_OFFSET 0x54 */ +/*#define EEPROM_TSSI_DELTA_OFFSET 0x24 */ +/*#define EEPROM_CCK_TX_PWR_OFFSET 0x62 */ +/*#define EEPROM_CALIBRATE_OFFSET 0x7c */ +#define EEPROM_VERSION_OFFSET 0x02 +#define EEPROM_FREQ_OFFSET 0x3a +#define EEPROM_TXPOWER_BYRATE 0xde /* 20MHZ power. */ +#define EEPROM_TXPOWER_DELTA 0x50 /* 20MHZ AND 40 MHZ use different power. This is delta in 40MHZ. */ +#define VALID_EEPROM_VERSION 1 + +/* + * EEPROM operation related marcos + */ +#define RT28xx_EEPROM_READ16(_pAd, _offset, _value) \ + (_pAd)->chipOps.eeread((struct rt_rtmp_adapter *)(_pAd), (u16)(_offset), (u16 *)&(_value)) + +/* ------------------------------------------------------------------- */ +/* E2PROM data layout */ +/* ------------------------------------------------------------------- */ + +/* */ +/* MCU_LEDCS: MCU LED Control Setting. */ +/* */ +typedef union _MCU_LEDCS_STRUC { + struct { + u8 LedMode:7; + u8 Polarity:1; + } field; + u8 word; +} MCU_LEDCS_STRUC, *PMCU_LEDCS_STRUC; + +/* */ +/* EEPROM antenna select format */ +/* */ +typedef union _EEPROM_ANTENNA_STRUC { + struct { + u16 RxPath:4; /* 1: 1R, 2: 2R, 3: 3R */ + u16 TxPath:4; /* 1: 1T, 2: 2T */ + u16 RfIcType:4; /* see E2PROM document */ + u16 Rsv:4; + } field; + u16 word; +} EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC; + +typedef union _EEPROM_NIC_CINFIG2_STRUC { + struct { + u16 HardwareRadioControl:1; /* 1:enable, 0:disable */ + u16 DynamicTxAgcControl:1; /* */ + u16 ExternalLNAForG:1; /* */ + u16 ExternalLNAForA:1; /* external LNA enable for 2.4G */ + u16 CardbusAcceleration:1; /* ! NOTE: 0 - enable, 1 - disable */ + u16 BW40MSidebandForG:1; + u16 BW40MSidebandForA:1; + u16 EnableWPSPBC:1; /* WPS PBC Control bit */ + u16 BW40MAvailForG:1; /* 0:enable, 1:disable */ + u16 BW40MAvailForA:1; /* 0:enable, 1:disable */ + u16 Rsv1:1; /* must be 0 */ + u16 AntDiversity:1; /* Antenna diversity */ + u16 Rsv2:3; /* must be 0 */ + u16 DACTestBit:1; /* control if driver should patch the DAC issue */ + } field; + u16 word; +} EEPROM_NIC_CONFIG2_STRUC, *PEEPROM_NIC_CONFIG2_STRUC; + +/* */ +/* TX_PWR Value valid range 0xFA(-6) ~ 0x24(36) */ +/* */ +typedef union _EEPROM_TX_PWR_STRUC { + struct { + char Byte0; /* Low Byte */ + char Byte1; /* High Byte */ + } field; + u16 word; +} EEPROM_TX_PWR_STRUC, *PEEPROM_TX_PWR_STRUC; + +typedef union _EEPROM_VERSION_STRUC { + struct { + u8 FaeReleaseNumber; /* Low Byte */ + u8 Version; /* High Byte */ + } field; + u16 word; +} EEPROM_VERSION_STRUC, *PEEPROM_VERSION_STRUC; + +typedef union _EEPROM_LED_STRUC { + struct { + u16 PolarityRDY_G:1; /* Polarity RDY_G setting. */ + u16 PolarityRDY_A:1; /* Polarity RDY_A setting. */ + u16 PolarityACT:1; /* Polarity ACT setting. */ + u16 PolarityGPIO_0:1; /* Polarity GPIO#0 setting. */ + u16 PolarityGPIO_1:1; /* Polarity GPIO#1 setting. */ + u16 PolarityGPIO_2:1; /* Polarity GPIO#2 setting. */ + u16 PolarityGPIO_3:1; /* Polarity GPIO#3 setting. */ + u16 PolarityGPIO_4:1; /* Polarity GPIO#4 setting. */ + u16 LedMode:5; /* Led mode. */ + u16 Rsvd:3; /* Reserved */ + } field; + u16 word; +} EEPROM_LED_STRUC, *PEEPROM_LED_STRUC; + +typedef union _EEPROM_TXPOWER_DELTA_STRUC { + struct { + u8 DeltaValue:6; /* Tx Power dalta value (MAX=4) */ + u8 Type:1; /* 1: plus the delta value, 0: minus the delta value */ + u8 TxPowerEnable:1; /* Enable */ + } field; + u8 value; +} EEPROM_TXPOWER_DELTA_STRUC, *PEEPROM_TXPOWER_DELTA_STRUC; + +#endif /* __RTMP_CHIP_H__ // */ diff --git a/drivers/staging/rt2860/rtmp_ckipmic.h b/drivers/staging/rt2860/rtmp_ckipmic.h index 39955b914de7de4f65ed7b9b08e1e9b96f1929ac..6ff935dd3dd16d0c220a856c7a58bc9a708484e9 100644 --- a/drivers/staging/rt2860/rtmp_ckipmic.h +++ b/drivers/staging/rt2860/rtmp_ckipmic.h @@ -37,42 +37,27 @@ #ifndef __RTMP_CKIPMIC_H__ #define __RTMP_CKIPMIC_H__ -typedef struct _MIC_CONTEXT { +struct rt_mic_context { /* --- MMH context */ - UCHAR CK[16]; /* the key */ - UCHAR coefficient[16]; /* current aes counter mode coefficients */ - ULONGLONG accum; /* accumulated mic, reduced to u32 in final() */ - UINT position; /* current position (byte offset) in message */ - UCHAR part[4]; /* for conversion of message to u32 for mmh */ -} MIC_CONTEXT, *PMIC_CONTEXT; + u8 CK[16]; /* the key */ + u8 coefficient[16]; /* current aes counter mode coefficients */ + unsigned long long accum; /* accumulated mic, reduced to u32 in final() */ + u32 position; /* current position (byte offset) in message */ + u8 part[4]; /* for conversion of message to u32 for mmh */ +}; -VOID xor_128( - IN PUCHAR a, - IN PUCHAR b, - OUT PUCHAR out); +void xor_128(u8 *a, u8 *b, u8 *out); -UCHAR RTMPCkipSbox( - IN UCHAR a); +u8 RTMPCkipSbox(u8 a); -VOID xor_32( - IN PUCHAR a, - IN PUCHAR b, - OUT PUCHAR out); +void xor_32(u8 *a, u8 *b, u8 *out); -VOID next_key( - IN PUCHAR key, - IN INT round); +void next_key(u8 *key, int round); -VOID byte_sub( - IN PUCHAR in, - OUT PUCHAR out); +void byte_sub(u8 *in, u8 *out); -VOID shift_row( - IN PUCHAR in, - OUT PUCHAR out); +void shift_row(u8 *in, u8 *out); -VOID mix_column( - IN PUCHAR in, - OUT PUCHAR out); +void mix_column(u8 *in, u8 *out); -#endif //__RTMP_CKIPMIC_H__ +#endif /*__RTMP_CKIPMIC_H__ */ diff --git a/drivers/staging/rt2860/rtmp_def.h b/drivers/staging/rt2860/rtmp_def.h index f5fee57fbe3e34c5a068940b0fb071a00564ef2d..9c54bacb845bd743a1cb9db0d53376005ef1c1c2 100644 --- a/drivers/staging/rt2860/rtmp_def.h +++ b/drivers/staging/rt2860/rtmp_def.h @@ -41,9 +41,9 @@ #include "oid.h" -// -// Debug information verbosity: lower values indicate higher urgency -// +/* */ +/* Debug information verbosity: lower values indicate higher urgency */ +/* */ #define RT_DEBUG_OFF 0 #define RT_DEBUG_ERROR 1 #define RT_DEBUG_WARN 2 @@ -51,111 +51,101 @@ #define RT_DEBUG_INFO 4 #define RT_DEBUG_LOUD 5 -#define NIC_TAG ((ULONG)'0682') -#define NIC_DBG_STRING ("**RT28xx**") +#define NIC_TAG ((unsigned long)'0682') +#define NIC_DBG_char ("**RT28xx**") -#define RALINK_2883_VERSION ((UINT32)0x28830300) -#define RALINK_2880E_VERSION ((UINT32)0x28720200) -#define RALINK_3070_VERSION ((UINT32)0x30700200) +#ifdef RTMP_MAC_USB +#define TX_RING_SIZE 8 /* 1 */ +#define PRIO_RING_SIZE 8 +#define MGMT_RING_SIZE 32 /* PRIO_RING_SIZE */ +#define RX_RING_SIZE 8 +#define MAX_TX_PROCESS 4 +#define LOCAL_TXBUF_SIZE 2048 +#endif /* RTMP_MAC_USB // */ -// -// NDIS version in use by the NIC driver. -// The high byte is the major version. The low byte is the minor version. -// -#ifdef NDIS51_MINIPORT -#define NIC_DRIVER_VERSION 0x0501 -#else -#define NIC_DRIVER_VERSION 0x0500 -#endif +/*#define PACKED */ -// -// NDIS media type, current is ethernet, change if native wireless supported -// -#define NIC_MEDIA_TYPE NdisMedium802_3 -#define NIC_PCI_HDR_LENGTH 0xe2 -#define NIC_MAX_PACKET_SIZE 2304 -#define NIC_HEADER_SIZE 14 -#define MAX_MAP_REGISTERS_NEEDED 32 -#define MIN_MAP_REGISTERS_NEEDED 2 //Todo: should consider fragment issue. - -// -// interface type, we use PCI -// -#define NIC_INTERFACE_TYPE NdisInterfacePci -#define NIC_INTERRUPT_MODE NdisInterruptLevelSensitive - -// -// buffer size passed in NdisMQueryAdapterResources -// We should only need three adapter resources (IO, interrupt and memory), -// Some devices get extra resources, so have room for 10 resources -// UF_SIZE (sizeof(NDIS_RESOURCE_LIST) + (10*sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR))) - - -#define NIC_RESOURCE_B// -// IO space length -// -#define NIC_MAP_IOSPACE_LENGTH sizeof(CSR_STRUC) +#define RALINK_2883_VERSION ((u32)0x28830300) +#define RALINK_2880E_VERSION ((u32)0x28720200) +#define RALINK_3070_VERSION ((u32)0x30700200) #define MAX_RX_PKT_LEN 1520 -// -// Entry number for each DMA descriptor ring -// +/* */ +/* Entry number for each DMA descriptor ring */ +/* */ -#ifdef RT2860 -#define TX_RING_SIZE 64 //64 +#ifdef RTMP_MAC_PCI +#define TX_RING_SIZE 64 /*64 */ #define MGMT_RING_SIZE 128 -#define RX_RING_SIZE 128 //64 -#define MAX_TX_PROCESS TX_RING_SIZE //8 +#define RX_RING_SIZE 128 /*64 */ +#define MAX_TX_PROCESS TX_RING_SIZE /*8 */ #define MAX_DMA_DONE_PROCESS TX_RING_SIZE -#define MAX_TX_DONE_PROCESS TX_RING_SIZE //8 +#define MAX_TX_DONE_PROCESS TX_RING_SIZE /*8 */ #define LOCAL_TXBUF_SIZE 2 -#endif -#ifdef RT2870 -#define TX_RING_SIZE 8 // 1 -#define PRIO_RING_SIZE 8 -#define MGMT_RING_SIZE 32 // PRIO_RING_SIZE -#define RX_RING_SIZE 8 -#define MAX_TX_PROCESS 4 -#define LOCAL_TXBUF_SIZE 2048 -#endif // RT2870 // +#endif /* RTMP_MAC_PCI // */ -#define MAX_RX_PROCESS 128 //64 //32 +#define MAX_RX_PROCESS 128 /*64 //32 */ #define NUM_OF_LOCAL_TXBUF 2 #define TXD_SIZE 16 #define TXWI_SIZE 16 #define RXD_SIZE 16 #define RXWI_SIZE 16 -// TXINFO_SIZE + TXWI_SIZE + 802.11 Header Size + AMSDU sub frame header -#define TX_DMA_1ST_BUFFER_SIZE 96 // only the 1st physical buffer is pre-allocated -#define MGMT_DMA_BUFFER_SIZE 1536 //2048 -#define RX_BUFFER_AGGRESIZE 3840 //3904 //3968 //4096 //2048 //4096 -#define RX_BUFFER_NORMSIZE 3840 //3904 //3968 //4096 //2048 //4096 +/* TXINFO_SIZE + TXWI_SIZE + 802.11 Header Size + AMSDU sub frame header */ +#define TX_DMA_1ST_BUFFER_SIZE 96 /* only the 1st physical buffer is pre-allocated */ +#define MGMT_DMA_BUFFER_SIZE 1536 /*2048 */ +#define RX_BUFFER_AGGRESIZE 3840 /*3904 //3968 //4096 //2048 //4096 */ +#define RX_BUFFER_NORMSIZE 3840 /*3904 //3968 //4096 //2048 //4096 */ #define TX_BUFFER_NORMSIZE RX_BUFFER_NORMSIZE -#define MAX_FRAME_SIZE 2346 // Maximum 802.11 frame size -#define MAX_AGGREGATION_SIZE 3840 //3904 //3968 //4096 +#define MAX_FRAME_SIZE 2346 /* Maximum 802.11 frame size */ +#define MAX_AGGREGATION_SIZE 3840 /*3904 //3968 //4096 */ #define MAX_NUM_OF_TUPLE_CACHE 2 #define MAX_MCAST_LIST_SIZE 32 #define MAX_LEN_OF_VENDOR_DESC 64 -//#define MAX_SIZE_OF_MCAST_PSQ (NUM_OF_LOCAL_TXBUF >> 2) // AP won't spend more than 1/4 of total buffers on M/BCAST PSQ +/*#define MAX_SIZE_OF_MCAST_PSQ (NUM_OF_LOCAL_TXBUF >> 2) // AP won't spend more than 1/4 of total buffers on M/BCAST PSQ */ #define MAX_SIZE_OF_MCAST_PSQ 32 #define MAX_RX_PROCESS_CNT (RX_RING_SIZE) +/* + WMM Note: If memory of your system is not much, please reduce the definition; + or when you do WMM test, the queue for low priority AC will be full, i.e. + TX_RING_SIZE + MAX_PACKETS_IN_QUEUE packets for the AC will be buffered in + WLAN, maybe no any packet buffer can be got in Ethernet driver. + + Sometimes no packet buffer can be got in Ethernet driver, the system will + send flow control packet to the sender to slow down its sending rate. + So no WMM can be saw in the air. +*/ + +/* + Need to use 64 in vxworks for test case WMM A5-T07 + Two dnlink (10Mbps) from a WMM station to a non-WMM station. + If use 256, queue is not enough. + And in rt_main_end.c, clConfig.clNum = RX_RING_SIZE * 3; is changed to + clConfig.clNum = RX_RING_SIZE * 4; +*/ +/* TODO: For VxWorks the size is 256. Shall we cahnge the value as 256 for all OS????? */ +#define MAX_PACKETS_IN_QUEUE (512) /*(512) // to pass WMM A5-WPAPSK */ -#define MAX_PACKETS_IN_QUEUE (512) //(512) // to pass WMM A5-WPAPSK #define MAX_PACKETS_IN_MCAST_PS_QUEUE 32 -#define MAX_PACKETS_IN_PS_QUEUE 128 //32 -#define WMM_NUM_OF_AC 4 /* AC0, AC1, AC2, and AC3 */ +#define MAX_PACKETS_IN_PS_QUEUE 128 /*32 */ +#define WMM_NUM_OF_AC 4 /* AC0, AC1, AC2, and AC3 */ +#ifdef RTMP_EFUSE_SUPPORT +/*2008/09/11:KH add to support efuse<-- */ #define MAX_EEPROM_BIN_FILE_SIZE 1024 +#define EFUSE_BUFFER_PATH "/tmp/RT30xxEEPROM.bin" +/*2008/09/11:KH add to support efuse--> */ +#endif /* RTMP_EFUSE_SUPPORT // */ -// RxFilter +/* RxFilter */ #define STANORMAL 0x17f97 #define APNORMAL 0x15f97 -// -// RTMP_ADAPTER flags -// +#define PSPXLINK 0x17f93 +/* */ +/* struct rt_rtmp_adapter flags */ +/* */ #define fRTMP_ADAPTER_MAP_REGISTER 0x00000001 #define fRTMP_ADAPTER_INTERRUPT_IN_USE 0x00000002 #define fRTMP_ADAPTER_HARDWARE_ERROR 0x00000004 @@ -181,13 +171,13 @@ #define fRTMP_ADAPTER_SCAN_2040 0x04000000 #define fRTMP_ADAPTER_RADIO_MEASUREMENT 0x08000000 -#define fRTMP_ADAPTER_START_UP 0x10000000 //Devive already initialized and enabled Tx/Rx. +#define fRTMP_ADAPTER_START_UP 0x10000000 /*Devive already initialized and enabled Tx/Rx. */ #define fRTMP_ADAPTER_MEDIA_STATE_CHANGE 0x20000000 #define fRTMP_ADAPTER_IDLE_RADIO_OFF 0x40000000 -// -// STA operation status flags -// +/* */ +/* STA operation status flags */ +/* */ #define fOP_STATUS_INFRA_ON 0x00000001 #define fOP_STATUS_ADHOC_ON 0x00000002 #define fOP_STATUS_BG_PROTECTION_INUSED 0x00000004 @@ -197,28 +187,34 @@ #define fOP_STATUS_MEDIA_STATE_CONNECTED 0x00000080 #define fOP_STATUS_WMM_INUSED 0x00000100 #define fOP_STATUS_AGGREGATION_INUSED 0x00000200 -#define fOP_STATUS_DOZE 0x00000400 // debug purpose -#define fOP_STATUS_PIGGYBACK_INUSED 0x00000800 // piggy-back, and aggregation +#define fOP_STATUS_DOZE 0x00000400 /* debug purpose */ +#define fOP_STATUS_PIGGYBACK_INUSED 0x00000800 /* piggy-back, and aggregation */ #define fOP_STATUS_APSD_INUSED 0x00001000 #define fOP_STATUS_TX_AMSDU_INUSED 0x00002000 #define fOP_STATUS_MAX_RETRY_ENABLED 0x00004000 #define fOP_STATUS_WAKEUP_NOW 0x00008000 -#define fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE 0x00020000 +#define fOP_STATUS_PCIE_DEVICE 0x00020000 +#define fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE fOP_STATUS_PCIE_DEVICE -#ifdef RT2860 -// -// RTMP_ADAPTER PSFlags : related to advanced power save. -// -// Indicate whether driver can go to sleep mode from now. This flag is useful AFTER link up +/* */ +/* struct rt_rtmp_adapter PSFlags : related to advanced power save. */ +/* */ +/* Indicate whether driver can go to sleep mode from now. This flag is useful AFTER link up */ #define fRTMP_PS_CAN_GO_SLEEP 0x00000001 -// Indicate whether driver has issue a LinkControl command to PCIe L1 +/* Indicate whether driver has issue a LinkControl command to PCIe L1 */ #define fRTMP_PS_SET_PCI_CLK_OFF_COMMAND 0x00000002 -// Indicate driver should disable kick off hardware to send packets from now. +/* Indicate driver should disable kick off hardware to send packets from now. */ #define fRTMP_PS_DISABLE_TX 0x00000004 -// Indicate driver should IMMEDIATELY fo to sleep after receiving AP's beacon in which doesn't indicate unicate nor multicast packets for me -//. This flag is used ONLY in RTMPHandleRxDoneInterrupt routine. +/* Indicate driver should IMMEDIATELY fo to sleep after receiving AP's beacon in which doesn't indicate unicate nor multicast packets for me */ +/*. This flag is used ONLY in RTMPHandleRxDoneInterrupt routine. */ #define fRTMP_PS_GO_TO_SLEEP_NOW 0x00000008 -#endif +#define fRTMP_PS_TOGGLE_L1 0x00000010 /* Use Toggle L1 mechanism for rt28xx PCIe */ + +#ifdef RT3090 +#define WAKE_MCU_CMD 0x31 +#define SLEEP_MCU_CMD 0x30 +#define RFOFF_MCU_CMD 0x35 +#endif /* RT3090 // */ #define CCKSETPROTECT 0x1 #define OFDMSETPROTECT 0x2 @@ -228,12 +224,12 @@ #define GR40SETPROTECT 0x20 #define ALLN_SETPROTECT (GR40SETPROTECT | GF20SETPROTECT | MM40SETPROTECT | MM20SETPROTECT) -// -// AP's client table operation status flags -// -#define fCLIENT_STATUS_WMM_CAPABLE 0x00000001 // CLIENT can parse QOS DATA frame -#define fCLIENT_STATUS_AGGREGATION_CAPABLE 0x00000002 // CLIENT can receive Ralink's proprietary TX aggregation frame -#define fCLIENT_STATUS_PIGGYBACK_CAPABLE 0x00000004 // CLIENT support piggy-back +/* */ +/* AP's client table operation status flags */ +/* */ +#define fCLIENT_STATUS_WMM_CAPABLE 0x00000001 /* CLIENT can parse QOS DATA frame */ +#define fCLIENT_STATUS_AGGREGATION_CAPABLE 0x00000002 /* CLIENT can receive Ralink's proprietary TX aggregation frame */ +#define fCLIENT_STATUS_PIGGYBACK_CAPABLE 0x00000004 /* CLIENT support piggy-back */ #define fCLIENT_STATUS_AMSDU_INUSED 0x00000008 #define fCLIENT_STATUS_SGI20_CAPABLE 0x00000010 #define fCLIENT_STATUS_SGI40_CAPABLE 0x00000020 @@ -242,47 +238,48 @@ #define fCLIENT_STATUS_HTC_CAPABLE 0x00000100 #define fCLIENT_STATUS_RDG_CAPABLE 0x00000200 #define fCLIENT_STATUS_MCSFEEDBACK_CAPABLE 0x00000400 -#define fCLIENT_STATUS_APSD_CAPABLE 0x00000800 /* UAPSD STATION */ +#define fCLIENT_STATUS_APSD_CAPABLE 0x00000800 /* UAPSD STATION */ #define fCLIENT_STATUS_RALINK_CHIPSET 0x00100000 -// -// STA configuration flags -// +/* */ +/* STA configuration flags */ +/* */ -// 802.11n Operating Mode Definition. 0-3 also used in ASICUPdateProtect switch case +/* 802.11n Operating Mode Definition. 0-3 also used in ASICUPdateProtect switch case */ #define HT_NO_PROTECT 0 #define HT_LEGACY_PROTECT 1 #define HT_40_PROTECT 2 #define HT_2040_PROTECT 3 #define HT_RTSCTS_6M 7 -//following is our own definition in order to turn on our ASIC protection register in INFRASTRUCTURE. -#define HT_ATHEROS 8 // rt2860c has problem with atheros chip. we need to turn on RTS/CTS . -#define HT_FORCERTSCTS 9 // Force turn on RTS/CTS first. then go to evaluate if this force RTS is necessary. +/*following is our own definition in order to turn on our ASIC protection register in INFRASTRUCTURE. */ +#define HT_ATHEROS 8 /* rt2860c has problem with atheros chip. we need to turn on RTS/CTS . */ +#define HT_FORCERTSCTS 9 /* Force turn on RTS/CTS first. then go to evaluate if this force RTS is necessary. */ -// -// RX Packet Filter control flags. Apply on pAd->PacketFilter -// +/* */ +/* RX Packet Filter control flags. Apply on pAd->PacketFilter */ +/* */ #define fRX_FILTER_ACCEPT_DIRECT NDIS_PACKET_TYPE_DIRECTED #define fRX_FILTER_ACCEPT_MULTICAST NDIS_PACKET_TYPE_MULTICAST #define fRX_FILTER_ACCEPT_BROADCAST NDIS_PACKET_TYPE_BROADCAST #define fRX_FILTER_ACCEPT_ALL_MULTICAST NDIS_PACKET_TYPE_ALL_MULTICAST +#define fRX_FILTER_ACCEPT_PROMISCUOUS NDIS_PACKET_TYPE_PROMISCUOUS -// -// Error code section -// -// NDIS_ERROR_CODE_ADAPTER_NOT_FOUND +/* */ +/* Error code section */ +/* */ +/* NDIS_ERROR_CODE_ADAPTER_NOT_FOUND */ #define ERRLOG_READ_PCI_SLOT_FAILED 0x00000101L #define ERRLOG_WRITE_PCI_SLOT_FAILED 0x00000102L #define ERRLOG_VENDOR_DEVICE_NOMATCH 0x00000103L -// NDIS_ERROR_CODE_ADAPTER_DISABLED +/* NDIS_ERROR_CODE_ADAPTER_DISABLED */ #define ERRLOG_BUS_MASTER_DISABLED 0x00000201L -// NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION +/* NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION */ #define ERRLOG_INVALID_SPEED_DUPLEX 0x00000301L #define ERRLOG_SET_SECONDARY_FAILED 0x00000302L -// NDIS_ERROR_CODE_OUT_OF_RESOURCES +/* NDIS_ERROR_CODE_OUT_OF_RESOURCES */ #define ERRLOG_OUT_OF_MEMORY 0x00000401L #define ERRLOG_OUT_OF_SHARED_MEMORY 0x00000402L #define ERRLOG_OUT_OF_MAP_REGISTERS 0x00000403L @@ -292,22 +289,21 @@ #define ERRLOG_OUT_OF_NDIS_PACKET 0x00000407L #define ERRLOG_OUT_OF_LOOKASIDE_MEMORY 0x00000408L -// NDIS_ERROR_CODE_HARDWARE_FAILURE +/* NDIS_ERROR_CODE_HARDWARE_FAILURE */ #define ERRLOG_SELFTEST_FAILED 0x00000501L #define ERRLOG_INITIALIZE_ADAPTER 0x00000502L #define ERRLOG_REMOVE_MINIPORT 0x00000503L -// NDIS_ERROR_CODE_RESOURCE_CONFLICT +/* NDIS_ERROR_CODE_RESOURCE_CONFLICT */ #define ERRLOG_MAP_IO_SPACE 0x00000601L #define ERRLOG_QUERY_ADAPTER_RESOURCES 0x00000602L #define ERRLOG_NO_IO_RESOURCE 0x00000603L #define ERRLOG_NO_INTERRUPT_RESOURCE 0x00000604L #define ERRLOG_NO_MEMORY_RESOURCE 0x00000605L - -// WDS definition +/* WDS definition */ #define MAX_WDS_ENTRY 4 -#define WDS_PAIRWISE_KEY_OFFSET 60 // WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table +#define WDS_PAIRWISE_KEY_OFFSET 60 /* WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table */ #define WDS_DISABLE_MODE 0 #define WDS_RESTRICT_MODE 1 @@ -315,23 +311,20 @@ #define WDS_REPEATER_MODE 3 #define WDS_LAZY_MODE 4 - #define MAX_MESH_NUM 0 #define MAX_APCLI_NUM 0 #define MAX_MBSSID_NUM 1 -#if defined(RT2860) || defined(RT30xx) #ifdef MBSS_SUPPORT #undef MAX_MBSSID_NUM #define MAX_MBSSID_NUM (8 - MAX_MESH_NUM - MAX_APCLI_NUM) -#endif // MBSS_SUPPORT // -#endif +#endif /* MBSS_SUPPORT // */ /* sanity check for apidx */ #define MBSS_MR_APIDX_SANITY_CHECK(apidx) \ { if (apidx > MAX_MBSSID_NUM) { \ - printk("%s> Error! apidx = %d > MAX_MBSSID_NUM!\n", __func__, apidx); \ + DBGPRINT(RT_DEBUG_ERROR, ("%s> Error! apidx = %d > MAX_MBSSID_NUM!\n", __func__, apidx)); \ apidx = MAIN_MBSSID; } } #define VALID_WCID(_wcid) ((_wcid) > 0 && (_wcid) < MAX_LEN_OF_MAC_TABLE ) @@ -339,12 +332,11 @@ #define MAIN_MBSSID 0 #define FIRST_MBSSID 1 - #define MAX_BEACON_SIZE 512 -// If the MAX_MBSSID_NUM is larger than 6, -// it shall reserve some WCID space(wcid 222~253) for beacon frames. -// - these wcid 238~253 are reserved for beacon#6(ra6). -// - these wcid 222~237 are reserved for beacon#7(ra7). +/* If the MAX_MBSSID_NUM is larger than 6, */ +/* it shall reserve some WCID space(wcid 222~253) for beacon frames. */ +/* - these wcid 238~253 are reserved for beacon#6(ra6). */ +/* - these wcid 222~237 are reserved for beacon#7(ra7). */ #if defined(MAX_MBSSID_NUM) && (MAX_MBSSID_NUM == 8) #define HW_RESERVED_WCID 222 #elif defined(MAX_MBSSID_NUM) && (MAX_MBSSID_NUM == 7) @@ -353,17 +345,17 @@ #define HW_RESERVED_WCID 255 #endif -// Then dedicate wcid of DFS and Carrier-Sense. +/* Then dedicate wcid of DFS and Carrier-Sense. */ #define DFS_CTS_WCID (HW_RESERVED_WCID - 1) #define CS_CTS_WCID (HW_RESERVED_WCID - 2) #define LAST_SPECIFIC_WCID (HW_RESERVED_WCID - 2) -// If MAX_MBSSID_NUM is 8, the maximum available wcid for the associated STA is 211. -// If MAX_MBSSID_NUM is 7, the maximum available wcid for the associated STA is 228. +/* If MAX_MBSSID_NUM is 8, the maximum available wcid for the associated STA is 211. */ +/* If MAX_MBSSID_NUM is 7, the maximum available wcid for the associated STA is 228. */ #define MAX_AVAILABLE_CLIENT_WCID (LAST_SPECIFIC_WCID - MAX_MBSSID_NUM - 1) -// TX need WCID to find Cipher Key -// these wcid 212 ~ 219 are reserved for bc/mc packets if MAX_MBSSID_NUM is 8. +/* TX need WCID to find Cipher Key */ +/* these wcid 212 ~ 219 are reserved for bc/mc packets if MAX_MBSSID_NUM is 8. */ #define GET_GroupKey_WCID(__wcid, __bssidx) \ { \ __wcid = LAST_SPECIFIC_WCID - (MAX_MBSSID_NUM) + __bssidx; \ @@ -371,8 +363,7 @@ #define IsGroupKeyWCID(__wcid) (((__wcid) < LAST_SPECIFIC_WCID) && ((__wcid) >= (LAST_SPECIFIC_WCID - (MAX_MBSSID_NUM)))) - -// definition to support multiple BSSID +/* definition to support multiple BSSID */ #define BSS0 0 #define BSS1 1 #define BSS2 2 @@ -382,26 +373,26 @@ #define BSS6 6 #define BSS7 7 - -//============================================================ -// Length definitions +/*============================================================ */ +/* Length definitions */ #define PEER_KEY_NO 2 #define MAC_ADDR_LEN 6 #define TIMESTAMP_LEN 8 -#define MAX_LEN_OF_SUPPORTED_RATES MAX_LENGTH_OF_SUPPORT_RATES // 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 -#define MAX_LEN_OF_KEY 32 // 32 octets == 256 bits, Redefine for WPA -#define MAX_NUM_OF_CHANNELS MAX_NUM_OF_CHS // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination -#define MAX_NUM_OF_11JCHANNELS 20 // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination +#define MAX_LEN_OF_SUPPORTED_RATES MAX_LENGTH_OF_SUPPORT_RATES /* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ +#define MAX_LEN_OF_KEY 32 /* 32 octets == 256 bits, Redefine for WPA */ +#define MAX_NUM_OF_CHANNELS MAX_NUM_OF_CHS /* 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination */ +#define MAX_NUM_OF_11JCHANNELS 20 /* 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination */ #define MAX_LEN_OF_SSID 32 #define CIPHER_TEXT_LEN 128 #define HASH_TABLE_SIZE 256 -#define MAX_VIE_LEN 1024 // New for WPA cipher suite variable IE sizes. +#define MAX_VIE_LEN 1024 /* New for WPA cipher suite variable IE sizes. */ #define MAX_SUPPORT_MCS 32 +#define MAX_NUM_OF_BBP_LATCH 140 -//============================================================ -// ASIC WCID Table definition. -//============================================================ -#define BSSID_WCID 1 // in infra mode, always put bssid with this WCID +/*============================================================ */ +/* ASIC WCID Table definition. */ +/*============================================================ */ +#define BSSID_WCID 1 /* in infra mode, always put bssid with this WCID */ #define MCAST_WCID 0x0 #define BSS0Mcast_WCID 0x0 #define BSS1Mcast_WCID 0xf8 @@ -415,10 +406,10 @@ #define MAX_NUM_OF_ACL_LIST MAX_NUMBER_OF_ACL -#define MAX_LEN_OF_MAC_TABLE MAX_NUMBER_OF_MAC // if MAX_MBSSID_NUM is 8, this value can't be larger than 211 +#define MAX_LEN_OF_MAC_TABLE MAX_NUMBER_OF_MAC /* if MAX_MBSSID_NUM is 8, this value can't be larger than 211 */ #if MAX_LEN_OF_MAC_TABLE>MAX_AVAILABLE_CLIENT_WCID -#error MAX_LEN_OF_MAC_TABLE can not be larger than MAX_AVAILABLE_CLIENT_WCID!!!! +#error MAX_LEN_OF_MAC_TABLE can not be larger than MAX_AVAILABLE_CLIENT_WCID! #endif #define MAX_NUM_OF_WDS_LINK_PERBSSID 3 @@ -428,42 +419,41 @@ #define NUM_OF_TID 8 #define MAX_AID_BA 4 -#define MAX_LEN_OF_BA_REC_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2)// (NUM_OF_TID*MAX_AID_BA + 32) //Block ACK recipient -#define MAX_LEN_OF_BA_ORI_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2)// (NUM_OF_TID*MAX_AID_BA + 32) // Block ACK originator +#define MAX_LEN_OF_BA_REC_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2) /* (NUM_OF_TID*MAX_AID_BA + 32) //Block ACK recipient */ +#define MAX_LEN_OF_BA_ORI_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2) /* (NUM_OF_TID*MAX_AID_BA + 32) // Block ACK originator */ #define MAX_LEN_OF_BSS_TABLE 64 #define MAX_REORDERING_MPDU_NUM 512 -// key related definitions +/* key related definitions */ #define SHARE_KEY_NUM 4 -#define MAX_LEN_OF_SHARE_KEY 16 // byte count -#define MAX_LEN_OF_PEER_KEY 16 // byte count -#define PAIRWISE_KEY_NUM 64 // in MAC ASIC pairwise key table +#define MAX_LEN_OF_SHARE_KEY 16 /* byte count */ +#define MAX_LEN_OF_PEER_KEY 16 /* byte count */ +#define PAIRWISE_KEY_NUM 64 /* in MAC ASIC pairwise key table */ #define GROUP_KEY_NUM 4 #define PMK_LEN 32 -#define WDS_PAIRWISE_KEY_OFFSET 60 // WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table -#define PMKID_NO 4 // Number of PMKID saved supported +#define WDS_PAIRWISE_KEY_OFFSET 60 /* WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table */ +#define PMKID_NO 4 /* Number of PMKID saved supported */ #define MAX_LEN_OF_MLME_BUFFER 2048 -// power status related definitions +/* power status related definitions */ #define PWR_ACTIVE 0 #define PWR_SAVE 1 -#define PWR_MMPS 2 //MIMO power save +#define PWR_MMPS 2 /*MIMO power save */ -// Auth and Assoc mode related definitions +/* Auth and Assoc mode related definitions */ #define AUTH_MODE_OPEN 0x00 #define AUTH_MODE_KEY 0x01 -// BSS Type definitions -#define BSS_ADHOC 0 // = Ndis802_11IBSS -#define BSS_INFRA 1 // = Ndis802_11Infrastructure -#define BSS_ANY 2 // = Ndis802_11AutoUnknown -#define BSS_MONITOR 3 // = Ndis802_11Monitor - +/* BSS Type definitions */ +#define BSS_ADHOC 0 /* = Ndis802_11IBSS */ +#define BSS_INFRA 1 /* = Ndis802_11Infrastructure */ +#define BSS_ANY 2 /* = Ndis802_11AutoUnknown */ +#define BSS_MONITOR 3 /* = Ndis802_11Monitor */ -// Reason code definitions +/* Reason code definitions */ #define REASON_RESERVED 0 #define REASON_UNSPECIFY 1 -#define REASON_NO_LONGER_VALID 2 +#define REASON_NO_longER_VALID 2 #define REASON_DEAUTH_STA_LEAVING 3 #define REASON_DISASSOC_INACTIVE 4 #define REASON_DISASSPC_AP_UNABLE 5 @@ -495,7 +485,7 @@ #define REASON_QOS_REQUEST_TIMEOUT 39 #define REASON_QOS_CIPHER_NOT_SUPPORT 45 -// Status code definitions +/* Status code definitions */ #define MLME_SUCCESS 0 #define MLME_UNSPECIFY_FAIL 1 #define MLME_CANNOT_SUPPORT_CAP 10 @@ -515,6 +505,9 @@ #define MLME_QOS_UNSPECIFY 32 #define MLME_REQUEST_DECLINED 37 #define MLME_REQUEST_WITH_INVALID_PARAM 38 +#define MLME_INVALID_GROUP_CIPHER 41 +#define MLME_INVALID_PAIRWISE_CIPHER 42 +#define MLME_INVALID_AKMP 43 #define MLME_DLS_NOT_ALLOW_IN_QBSS 48 #define MLME_DEST_STA_NOT_IN_QBSS 49 #define MLME_DEST_STA_IS_NOT_A_QSTA 50 @@ -524,7 +517,7 @@ #define MLME_STATE_MACHINE_REJECT 0x53 #define MLME_MAC_TABLE_FAIL 0x54 -// IE code +/* IE code */ #define IE_SSID 0 #define IE_SUPP_RATES 1 #define IE_FH_PARM 2 @@ -532,94 +525,95 @@ #define IE_CF_PARM 4 #define IE_TIM 5 #define IE_IBSS_PARM 6 -#define IE_COUNTRY 7 // 802.11d -#define IE_802_11D_REQUEST 10 // 802.11d -#define IE_QBSS_LOAD 11 // 802.11e d9 -#define IE_EDCA_PARAMETER 12 // 802.11e d9 -#define IE_TSPEC 13 // 802.11e d9 -#define IE_TCLAS 14 // 802.11e d9 -#define IE_SCHEDULE 15 // 802.11e d9 +#define IE_COUNTRY 7 /* 802.11d */ +#define IE_802_11D_REQUEST 10 /* 802.11d */ +#define IE_QBSS_LOAD 11 /* 802.11e d9 */ +#define IE_EDCA_PARAMETER 12 /* 802.11e d9 */ +#define IE_TSPEC 13 /* 802.11e d9 */ +#define IE_TCLAS 14 /* 802.11e d9 */ +#define IE_SCHEDULE 15 /* 802.11e d9 */ #define IE_CHALLENGE_TEXT 16 -#define IE_POWER_CONSTRAINT 32 // 802.11h d3.3 -#define IE_POWER_CAPABILITY 33 // 802.11h d3.3 -#define IE_TPC_REQUEST 34 // 802.11h d3.3 -#define IE_TPC_REPORT 35 // 802.11h d3.3 -#define IE_SUPP_CHANNELS 36 // 802.11h d3.3 -#define IE_CHANNEL_SWITCH_ANNOUNCEMENT 37 // 802.11h d3.3 -#define IE_MEASUREMENT_REQUEST 38 // 802.11h d3.3 -#define IE_MEASUREMENT_REPORT 39 // 802.11h d3.3 -#define IE_QUIET 40 // 802.11h d3.3 -#define IE_IBSS_DFS 41 // 802.11h d3.3 -#define IE_ERP 42 // 802.11g -#define IE_TS_DELAY 43 // 802.11e d9 -#define IE_TCLAS_PROCESSING 44 // 802.11e d9 -#define IE_QOS_CAPABILITY 46 // 802.11e d6 -#define IE_HT_CAP 45 // 802.11n d1. HT CAPABILITY. ELEMENT ID TBD -#define IE_AP_CHANNEL_REPORT 51 // 802.11k d6 -#define IE_HT_CAP2 52 // 802.11n d1. HT CAPABILITY. ELEMENT ID TBD -#define IE_RSN 48 // 802.11i d3.0 -#define IE_WPA2 48 // WPA2 -#define IE_EXT_SUPP_RATES 50 // 802.11g -#define IE_SUPP_REG_CLASS 59 // 802.11y. Supported regulatory classes. -#define IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT 60 // 802.11n -#define IE_ADD_HT 61 // 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD -#define IE_ADD_HT2 53 // 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD - - -// For 802.11n D3.03 -//#define IE_NEW_EXT_CHA_OFFSET 62 // 802.11n d1. New extension channel offset elemet -#define IE_SECONDARY_CH_OFFSET 62 // 802.11n D3.03 Secondary Channel Offset element -#define IE_2040_BSS_COEXIST 72 // 802.11n D3.0.3 -#define IE_2040_BSS_INTOLERANT_REPORT 73 // 802.11n D3.03 -#define IE_OVERLAPBSS_SCAN_PARM 74 // 802.11n D3.03 -#define IE_EXT_CAPABILITY 127 // 802.11n D3.03 - - -#define IE_WPA 221 // WPA -#define IE_VENDOR_SPECIFIC 221 // Wifi WMM (WME) - -#define OUI_BROADCOM_HT 51 // -#define OUI_BROADCOM_HTADD 52 // -#define OUI_PREN_HT_CAP 51 // -#define OUI_PREN_ADD_HT 52 // - -// CCX information -#define IE_AIRONET_CKIP 133 // CCX1.0 ID 85H for CKIP -#define IE_AP_TX_POWER 150 // CCX 2.0 for AP transmit power -#define IE_MEASUREMENT_CAPABILITY 221 // CCX 2.0 +#define IE_POWER_CONSTRAint 32 /* 802.11h d3.3 */ +#define IE_POWER_CAPABILITY 33 /* 802.11h d3.3 */ +#define IE_TPC_REQUEST 34 /* 802.11h d3.3 */ +#define IE_TPC_REPORT 35 /* 802.11h d3.3 */ +#define IE_SUPP_CHANNELS 36 /* 802.11h d3.3 */ +#define IE_CHANNEL_SWITCH_ANNOUNCEMENT 37 /* 802.11h d3.3 */ +#define IE_MEASUREMENT_REQUEST 38 /* 802.11h d3.3 */ +#define IE_MEASUREMENT_REPORT 39 /* 802.11h d3.3 */ +#define IE_QUIET 40 /* 802.11h d3.3 */ +#define IE_IBSS_DFS 41 /* 802.11h d3.3 */ +#define IE_ERP 42 /* 802.11g */ +#define IE_TS_DELAY 43 /* 802.11e d9 */ +#define IE_TCLAS_PROCESSING 44 /* 802.11e d9 */ +#define IE_QOS_CAPABILITY 46 /* 802.11e d6 */ +#define IE_HT_CAP 45 /* 802.11n d1. HT CAPABILITY. ELEMENT ID TBD */ +#define IE_AP_CHANNEL_REPORT 51 /* 802.11k d6 */ +#define IE_HT_CAP2 52 /* 802.11n d1. HT CAPABILITY. ELEMENT ID TBD */ +#define IE_RSN 48 /* 802.11i d3.0 */ +#define IE_WPA2 48 /* WPA2 */ +#define IE_EXT_SUPP_RATES 50 /* 802.11g */ +#define IE_SUPP_REG_CLASS 59 /* 802.11y. Supported regulatory classes. */ +#define IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT 60 /* 802.11n */ +#define IE_ADD_HT 61 /* 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD */ +#define IE_ADD_HT2 53 /* 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD */ + +/* For 802.11n D3.03 */ +/*#define IE_NEW_EXT_CHA_OFFSET 62 // 802.11n d1. New extension channel offset elemet */ +#define IE_SECONDARY_CH_OFFSET 62 /* 802.11n D3.03 Secondary Channel Offset element */ +#define IE_WAPI 68 /* WAPI information element */ +#define IE_2040_BSS_COEXIST 72 /* 802.11n D3.0.3 */ +#define IE_2040_BSS_INTOLERANT_REPORT 73 /* 802.11n D3.03 */ +#define IE_OVERLAPBSS_SCAN_PARM 74 /* 802.11n D3.03 */ +#define IE_EXT_CAPABILITY 127 /* 802.11n D3.03 */ + +#define IE_WPA 221 /* WPA */ +#define IE_VENDOR_SPECIFIC 221 /* Wifi WMM (WME) */ + +#define OUI_BROADCOM_HT 51 /* */ +#define OUI_BROADCOM_HTADD 52 /* */ +#define OUI_PREN_HT_CAP 51 /* */ +#define OUI_PREN_ADD_HT 52 /* */ + +/* CCX information */ +#define IE_AIRONET_CKIP 133 /* CCX1.0 ID 85H for CKIP */ +#define IE_AP_TX_POWER 150 /* CCX 2.0 for AP transmit power */ +#define IE_MEASUREMENT_CAPABILITY 221 /* CCX 2.0 */ #define IE_CCX_V2 221 -#define IE_AIRONET_IPADDRESS 149 // CCX ID 95H for IP Address -#define IE_AIRONET_CCKMREASSOC 156 // CCX ID 9CH for CCKM Reassociation Request element +#define IE_AIRONET_IPADDRESS 149 /* CCX ID 95H for IP Address */ +#define IE_AIRONET_CCKMREASSOC 156 /* CCX ID 9CH for CCKM Reassociation Request element */ #define CKIP_NEGOTIATION_LENGTH 30 #define AIRONET_IPADDRESS_LENGTH 10 #define AIRONET_CCKMREASSOC_LENGTH 24 -// ======================================================== -// MLME state machine definition -// ======================================================== +/* ======================================================== */ +/* MLME state machine definition */ +/* ======================================================== */ -// STA MLME state mahcines +/* STA MLME state mahcines */ #define ASSOC_STATE_MACHINE 1 #define AUTH_STATE_MACHINE 2 #define AUTH_RSP_STATE_MACHINE 3 #define SYNC_STATE_MACHINE 4 #define MLME_CNTL_STATE_MACHINE 5 #define WPA_PSK_STATE_MACHINE 6 -#define LEAP_STATE_MACHINE 7 +/*#define LEAP_STATE_MACHINE 7 */ #define AIRONET_STATE_MACHINE 8 #define ACTION_STATE_MACHINE 9 -// AP MLME state machines +/* AP MLME state machines */ #define AP_ASSOC_STATE_MACHINE 11 #define AP_AUTH_STATE_MACHINE 12 -#define AP_AUTH_RSP_STATE_MACHINE 13 #define AP_SYNC_STATE_MACHINE 14 #define AP_CNTL_STATE_MACHINE 15 -#define AP_WPA_STATE_MACHINE 16 +#define WSC_STATE_MACHINE 17 +#define WSC_UPNP_STATE_MACHINE 18 + +#define WPA_STATE_MACHINE 23 -// -// STA's CONTROL/CONNECT state machine: states, events, total function # -// +/* */ +/* STA's CONTROL/CONNECT state machine: states, events, total function # */ +/* */ #define CNTL_IDLE 0 #define CNTL_WAIT_DISASSOC 1 #define CNTL_WAIT_JOIN 2 @@ -630,9 +624,9 @@ #define CNTL_WAIT_AUTH2 7 #define CNTL_WAIT_OID_LIST_SCAN 8 #define CNTL_WAIT_OID_DISASSOC 9 -#ifdef RT2870 +#ifdef RTMP_MAC_USB #define CNTL_WAIT_SCAN_FOR_CONNECT 10 -#endif // RT2870 // +#endif /* RTMP_MAC_USB // */ #define MT2_ASSOC_CONF 34 #define MT2_AUTH_CONF 35 @@ -646,13 +640,14 @@ #define MT2_GET_CONF 43 #define MT2_SET_CONF 44 #define MT2_RESET_CONF 45 +#define MT2_FT_OTD_CONF 46 #define MT2_MLME_ROAMING_REQ 52 #define CNTL_FUNC_SIZE 1 -// -// STA's ASSOC state machine: states, events, total function # -// +/* */ +/* STA's ASSOC state machine: states, events, total function # */ +/* */ #define ASSOC_IDLE 0 #define ASSOC_WAIT_RSP 1 #define REASSOC_WAIT_RSP 2 @@ -675,24 +670,26 @@ #define ASSOC_FUNC_SIZE (MAX_ASSOC_STATE * MAX_ASSOC_MSG) -// -// ACT state machine: states, events, total function # -// +/* */ +/* ACT state machine: states, events, total function # */ +/* */ #define ACT_IDLE 0 #define MAX_ACT_STATE 1 #define ACT_MACHINE_BASE 0 -//Those PEER_xx_CATE number is based on real Categary value in IEEE spec. Please don'es modify it by your self. -//Category +/*Those PEER_xx_CATE number is based on real Categary value in IEEE spec. Please don'es modify it by your self. */ +/*Category */ #define MT2_PEER_SPECTRUM_CATE 0 #define MT2_PEER_QOS_CATE 1 #define MT2_PEER_DLS_CATE 2 #define MT2_PEER_BA_CATE 3 #define MT2_PEER_PUBLIC_CATE 4 #define MT2_PEER_RM_CATE 5 -#define MT2_PEER_HT_CATE 7 // 7.4.7 +/* "FT_CATEGORY_BSS_TRANSITION equal to 6" is defined file of "dot11r_ft.h" */ +#define MT2_PEER_HT_CATE 7 /* 7.4.7 */ #define MAX_PEER_CATE_MSG 7 + #define MT2_MLME_ADD_BA_CATE 8 #define MT2_MLME_ORI_DELBA_CATE 9 #define MT2_MLME_REC_DELBA_CATE 10 @@ -701,7 +698,7 @@ #define MT2_ACT_INVALID 13 #define MAX_ACT_MSG 14 -//Category field +/*Category field */ #define CATEGORY_SPECTRUM 0 #define CATEGORY_QOS 1 #define CATEGORY_DLS 2 @@ -710,38 +707,35 @@ #define CATEGORY_RM 5 #define CATEGORY_HT 7 - -// DLS Action frame definition +/* DLS Action frame definition */ #define ACTION_DLS_REQUEST 0 #define ACTION_DLS_RESPONSE 1 #define ACTION_DLS_TEARDOWN 2 -//Spectrum Action field value 802.11h 7.4.1 -#define SPEC_MRQ 0 // Request -#define SPEC_MRP 1 //Report +/*Spectrum Action field value 802.11h 7.4.1 */ +#define SPEC_MRQ 0 /* Request */ +#define SPEC_MRP 1 /*Report */ #define SPEC_TPCRQ 2 #define SPEC_TPCRP 3 #define SPEC_CHANNEL_SWITCH 4 - -//BA Action field value +/*BA Action field value */ #define ADDBA_REQ 0 #define ADDBA_RESP 1 #define DELBA 2 -//Public's Action field value in Public Category. Some in 802.11y and some in 11n -#define ACTION_BSS_2040_COEXIST 0 // 11n -#define ACTION_DSE_ENABLEMENT 1 // 11y D9.0 -#define ACTION_DSE_DEENABLEMENT 2 // 11y D9.0 -#define ACTION_DSE_REG_LOCATION_ANNOUNCE 3 // 11y D9.0 -#define ACTION_EXT_CH_SWITCH_ANNOUNCE 4 // 11y D9.0 -#define ACTION_DSE_MEASUREMENT_REQ 5 // 11y D9.0 -#define ACTION_DSE_MEASUREMENT_REPORT 6 // 11y D9.0 -#define ACTION_MEASUREMENT_PILOT_ACTION 7 // 11y D9.0 -#define ACTION_DSE_POWER_CONSTRAINT 8 // 11y D9.0 - - -//HT Action field value +/*Public's Action field value in Public Category. Some in 802.11y and some in 11n */ +#define ACTION_BSS_2040_COEXIST 0 /* 11n */ +#define ACTION_DSE_ENABLEMENT 1 /* 11y D9.0 */ +#define ACTION_DSE_DEENABLEMENT 2 /* 11y D9.0 */ +#define ACTION_DSE_REG_LOCATION_ANNOUNCE 3 /* 11y D9.0 */ +#define ACTION_EXT_CH_SWITCH_ANNOUNCE 4 /* 11y D9.0 */ +#define ACTION_DSE_MEASUREMENT_REQ 5 /* 11y D9.0 */ +#define ACTION_DSE_MEASUREMENT_REPORT 6 /* 11y D9.0 */ +#define ACTION_MEASUREMENT_PILOT_ACTION 7 /* 11y D9.0 */ +#define ACTION_DSE_POWER_CONSTRAINT 8 /* 11y D9.0 */ + +/*HT Action field value */ #define NOTIFY_BW_ACTION 0 #define SMPS_ACTION 1 #define PSMP_ACTION 2 @@ -753,9 +747,9 @@ #define HT_INFO_EXCHANGE 8 #define ACT_FUNC_SIZE (MAX_ACT_STATE * MAX_ACT_MSG) -// -// STA's AUTHENTICATION state machine: states, evvents, total function # -// +/* */ +/* STA's AUTHENTICATION state machine: states, evvents, total function # */ +/* */ #define AUTH_REQ_IDLE 0 #define AUTH_WAIT_SEQ2 1 #define AUTH_WAIT_SEQ4 2 @@ -769,9 +763,9 @@ #define AUTH_FUNC_SIZE (MAX_AUTH_STATE * MAX_AUTH_MSG) -// -// STA's AUTH_RSP state machine: states, events, total function # -// +/* */ +/* STA's AUTH_RSP state machine: states, events, total function # */ +/* */ #define AUTH_RSP_IDLE 0 #define AUTH_RSP_WAIT_CHAL 1 #define MAX_AUTH_RSP_STATE 2 @@ -784,10 +778,10 @@ #define AUTH_RSP_FUNC_SIZE (MAX_AUTH_RSP_STATE * MAX_AUTH_RSP_MSG) -// -// STA's SYNC state machine: states, events, total function # -// -#define SYNC_IDLE 0 // merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state +/* */ +/* STA's SYNC state machine: states, events, total function # */ +/* */ +#define SYNC_IDLE 0 /* merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state */ #define JOIN_WAIT_BEACON 1 #define SCAN_LISTEN 2 #define MAX_SYNC_STATE 3 @@ -807,7 +801,7 @@ #define SYNC_FUNC_SIZE (MAX_SYNC_STATE * MAX_SYNC_MSG) -//Messages for the DLS state machine +/*Messages for the DLS state machine */ #define DLS_IDLE 0 #define MAX_DLS_STATE 1 @@ -821,45 +815,18 @@ #define DLS_FUNC_SIZE (MAX_DLS_STATE * MAX_DLS_MSG) -// -// STA's WPA-PSK State machine: states, events, total function # -// -#define WPA_PSK_IDLE 0 -#define MAX_WPA_PSK_STATE 1 - -#define WPA_MACHINE_BASE 0 -#define MT2_EAPPacket 0 -#define MT2_EAPOLStart 1 -#define MT2_EAPOLLogoff 2 -#define MT2_EAPOLKey 3 -#define MT2_EAPOLASFAlert 4 -#define MAX_WPA_PSK_MSG 5 - -#define WPA_PSK_FUNC_SIZE (MAX_WPA_PSK_STATE * MAX_WPA_PSK_MSG) - -// -// STA's CISCO-AIRONET State machine: states, events, total function # -// -#define AIRONET_IDLE 0 -#define AIRONET_SCANNING 1 -#define MAX_AIRONET_STATE 2 - -#define AIRONET_MACHINE_BASE 0 -#define MT2_AIRONET_MSG 0 -#define MT2_AIRONET_SCAN_REQ 1 -#define MT2_AIRONET_SCAN_DONE 2 -#define MAX_AIRONET_MSG 3 - -#define AIRONET_FUNC_SIZE (MAX_AIRONET_STATE * MAX_AIRONET_MSG) - -// -// AP's CONTROL/CONNECT state machine: states, events, total function # -// +/* */ +/* WSC State machine: states, events, total function # */ +/* */ + +/* */ +/* AP's CONTROL/CONNECT state machine: states, events, total function # */ +/* */ #define AP_CNTL_FUNC_SIZE 1 -// -// AP's ASSOC state machine: states, events, total function # -// +/* */ +/* AP's ASSOC state machine: states, events, total function # */ +/* */ #define AP_ASSOC_IDLE 0 #define AP_MAX_ASSOC_STATE 1 @@ -873,36 +840,25 @@ #define AP_ASSOC_FUNC_SIZE (AP_MAX_ASSOC_STATE * AP_MAX_ASSOC_MSG) -// -// AP's AUTHENTICATION state machine: states, events, total function # -// +/* */ +/* AP's AUTHENTICATION state machine: states, events, total function # */ +/* */ #define AP_AUTH_REQ_IDLE 0 #define AP_MAX_AUTH_STATE 1 #define AP_AUTH_MACHINE_BASE 0 #define APMT2_MLME_DEAUTH_REQ 0 #define APMT2_CLS2ERR 1 -#define AP_MAX_AUTH_MSG 2 - -#define AP_AUTH_FUNC_SIZE (AP_MAX_AUTH_STATE * AP_MAX_AUTH_MSG) - -// -// AP's AUTH-RSP state machine: states, events, total function # -// -#define AP_AUTH_RSP_IDLE 0 -#define AP_MAX_AUTH_RSP_STATE 1 - -#define AP_AUTH_RSP_MACHINE_BASE 0 -#define APMT2_AUTH_CHALLENGE_TIMEOUT 0 -#define APMT2_PEER_AUTH_ODD 1 #define APMT2_PEER_DEAUTH 2 -#define AP_MAX_AUTH_RSP_MSG 3 +#define APMT2_PEER_AUTH_REQ 3 +#define APMT2_PEER_AUTH_CONFIRM 4 +#define AP_MAX_AUTH_MSG 5 -#define AP_AUTH_RSP_FUNC_SIZE (AP_MAX_AUTH_RSP_STATE * AP_MAX_AUTH_RSP_MSG) +#define AP_AUTH_FUNC_SIZE (AP_MAX_AUTH_STATE * AP_MAX_AUTH_MSG) -// -// AP's SYNC state machine: states, events, total function # -// +/* */ +/* AP's SYNC state machine: states, events, total function # */ +/* */ #define AP_SYNC_IDLE 0 #define AP_SCAN_LISTEN 1 #define AP_MAX_SYNC_STATE 2 @@ -918,30 +874,30 @@ #define AP_SYNC_FUNC_SIZE (AP_MAX_SYNC_STATE * AP_MAX_SYNC_MSG) -// -// AP's WPA state machine: states, events, total function # -// -#define AP_WPA_PTK 0 -#define AP_MAX_WPA_PTK_STATE 1 +/* */ +/* Common WPA state machine: states, events, total function # */ +/* */ +#define WPA_PTK 0 +#define MAX_WPA_PTK_STATE 1 -#define AP_WPA_MACHINE_BASE 0 -#define APMT2_EAPPacket 0 -#define APMT2_EAPOLStart 1 -#define APMT2_EAPOLLogoff 2 -#define APMT2_EAPOLKey 3 -#define APMT2_EAPOLASFAlert 4 -#define AP_MAX_WPA_MSG 5 +#define WPA_MACHINE_BASE 0 +#define MT2_EAPPacket 0 +#define MT2_EAPOLStart 1 +#define MT2_EAPOLLogoff 2 +#define MT2_EAPOLKey 3 +#define MT2_EAPOLASFAlert 4 +#define MAX_WPA_MSG 5 -#define AP_WPA_FUNC_SIZE (AP_MAX_WPA_PTK_STATE * AP_MAX_WPA_MSG) +#define WPA_FUNC_SIZE (MAX_WPA_PTK_STATE * MAX_WPA_MSG) -// ============================================================================= +/* ============================================================================= */ -// value domain of 802.11 header FC.Tyte, which is b3..b2 of the 1st-byte of MAC header +/* value domain of 802.11 header FC.Tyte, which is b3..b2 of the 1st-byte of MAC header */ #define BTYPE_MGMT 0 #define BTYPE_CNTL 1 #define BTYPE_DATA 2 -// value domain of 802.11 MGMT frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header +/* value domain of 802.11 MGMT frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header */ #define SUBTYPE_ASSOC_REQ 0 #define SUBTYPE_ASSOC_RSP 1 #define SUBTYPE_REASSOC_REQ 2 @@ -956,7 +912,7 @@ #define SUBTYPE_ACTION 13 #define SUBTYPE_ACTION_NO_ACK 14 -// value domain of 802.11 CNTL frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header +/* value domain of 802.11 CNTL frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header */ #define SUBTYPE_WRAPPER 7 #define SUBTYPE_BLOCK_ACK_REQ 8 #define SUBTYPE_BLOCK_ACK 9 @@ -967,7 +923,7 @@ #define SUBTYPE_CFEND 14 #define SUBTYPE_CFEND_CFACK 15 -// value domain of 802.11 DATA frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header +/* value domain of 802.11 DATA frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header */ #define SUBTYPE_DATA 0 #define SUBTYPE_DATA_CFACK 1 #define SUBTYPE_DATA_CFPOLL 2 @@ -985,15 +941,15 @@ #define SUBTYPE_QOS_CFPOLL 14 #define SUBTYPE_QOS_CFACK_CFPOLL 15 -// ACK policy of QOS Control field bit 6:5 -#define NORMAL_ACK 0x00 // b6:5 = 00 -#define NO_ACK 0x20 // b6:5 = 01 -#define NO_EXPLICIT_ACK 0x40 // b6:5 = 10 -#define BLOCK_ACK 0x60 // b6:5 = 11 +/* ACK policy of QOS Control field bit 6:5 */ +#define NORMAL_ACK 0x00 /* b6:5 = 00 */ +#define NO_ACK 0x20 /* b6:5 = 01 */ +#define NO_EXPLICIT_ACK 0x40 /* b6:5 = 10 */ +#define BLOCK_ACK 0x60 /* b6:5 = 11 */ -// -// rtmp_data.c use these definition -// +/* */ +/* rtmp_data.c use these definition */ +/* */ #define LENGTH_802_11 24 #define LENGTH_802_11_AND_H 30 #define LENGTH_802_11_CRC_H 34 @@ -1007,42 +963,42 @@ #define LENGTH_CRC 4 #define MAX_SEQ_NUMBER 0x0fff #define LENGTH_802_3_NO_TYPE 12 -#define LENGTH_802_1Q 4 /* VLAN related */ +#define LENGTH_802_1Q 4 /* VLAN related */ -// STA_CSR4.field.TxResult +/* STA_CSR4.field.TxResult */ #define TX_RESULT_SUCCESS 0 #define TX_RESULT_ZERO_LENGTH 1 #define TX_RESULT_UNDER_RUN 2 #define TX_RESULT_OHY_ERROR 4 #define TX_RESULT_RETRY_FAIL 6 -// All PHY rate summary in TXD -// Preamble MODE in TxD +/* All PHY rate summary in TXD */ +/* Preamble MODE in TxD */ #define MODE_CCK 0 #define MODE_OFDM 1 #define MODE_HTMIX 2 #define MODE_HTGREENFIELD 3 -// MCS for CCK. BW.SGI.STBC are reserved -#define MCS_LONGP_RATE_1 0 // long preamble CCK 1Mbps -#define MCS_LONGP_RATE_2 1 // long preamble CCK 1Mbps -#define MCS_LONGP_RATE_5_5 2 -#define MCS_LONGP_RATE_11 3 -#define MCS_SHORTP_RATE_1 4 // long preamble CCK 1Mbps. short is forbidden in 1Mbps -#define MCS_SHORTP_RATE_2 5 // short preamble CCK 2Mbps +/* MCS for CCK. BW.SGI.STBC are reserved */ +#define MCS_longP_RATE_1 0 /* long preamble CCK 1Mbps */ +#define MCS_longP_RATE_2 1 /* long preamble CCK 1Mbps */ +#define MCS_longP_RATE_5_5 2 +#define MCS_longP_RATE_11 3 +#define MCS_SHORTP_RATE_1 4 /* long preamble CCK 1Mbps. short is forbidden in 1Mbps */ +#define MCS_SHORTP_RATE_2 5 /* short preamble CCK 2Mbps */ #define MCS_SHORTP_RATE_5_5 6 #define MCS_SHORTP_RATE_11 7 -// To send duplicate legacy OFDM. set BW=BW_40. SGI.STBC are reserved -#define MCS_RATE_6 0 // legacy OFDM -#define MCS_RATE_9 1 // OFDM -#define MCS_RATE_12 2 // OFDM -#define MCS_RATE_18 3 // OFDM -#define MCS_RATE_24 4 // OFDM -#define MCS_RATE_36 5 // OFDM -#define MCS_RATE_48 6 // OFDM -#define MCS_RATE_54 7 // OFDM -// HT -#define MCS_0 0 // 1S +/* To send duplicate legacy OFDM. set BW=BW_40. SGI.STBC are reserved */ +#define MCS_RATE_6 0 /* legacy OFDM */ +#define MCS_RATE_9 1 /* OFDM */ +#define MCS_RATE_12 2 /* OFDM */ +#define MCS_RATE_18 3 /* OFDM */ +#define MCS_RATE_24 4 /* OFDM */ +#define MCS_RATE_36 5 /* OFDM */ +#define MCS_RATE_48 6 /* OFDM */ +#define MCS_RATE_54 7 /* OFDM */ +/* HT */ +#define MCS_0 0 /* 1S */ #define MCS_1 1 #define MCS_2 2 #define MCS_3 3 @@ -1050,7 +1006,7 @@ #define MCS_5 5 #define MCS_6 6 #define MCS_7 7 -#define MCS_8 8 // 2S +#define MCS_8 8 /* 2S */ #define MCS_9 9 #define MCS_10 10 #define MCS_11 11 @@ -1058,7 +1014,7 @@ #define MCS_13 13 #define MCS_14 14 #define MCS_15 15 -#define MCS_16 16 // 3*3 +#define MCS_16 16 /* 3*3 */ #define MCS_17 17 #define MCS_18 18 #define MCS_19 19 @@ -1069,49 +1025,48 @@ #define MCS_32 32 #define MCS_AUTO 33 -// OID_HTPHYMODE -// MODE +/* OID_HTPHYMODE */ +/* MODE */ #define HTMODE_MM 0 #define HTMODE_GF 1 -// Fixed Tx MODE - HT, CCK or OFDM +/* Fixed Tx MODE - HT, CCK or OFDM */ #define FIXED_TXMODE_HT 0 #define FIXED_TXMODE_CCK 1 #define FIXED_TXMODE_OFDM 2 -// BW +/* BW */ #define BW_20 BAND_WIDTH_20 #define BW_40 BAND_WIDTH_40 #define BW_BOTH BAND_WIDTH_BOTH -#define BW_10 BAND_WIDTH_10 // 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. +#define BW_10 BAND_WIDTH_10 /* 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. */ -// SHORTGI -#define GI_400 GAP_INTERVAL_400 // only support in HT mode +/* SHORTGI */ +#define GI_400 GAP_INTERVAL_400 /* only support in HT mode */ #define GI_BOTH GAP_INTERVAL_BOTH #define GI_800 GAP_INTERVAL_800 -// STBC +/* STBC */ #define STBC_NONE 0 -#define STBC_USE 1 // limited use in rt2860b phy -#define RXSTBC_ONE 1 // rx support of one spatial stream -#define RXSTBC_TWO 2 // rx support of 1 and 2 spatial stream -#define RXSTBC_THR 3 // rx support of 1~3 spatial stream -// MCS FEEDBACK -#define MCSFBK_NONE 0 // not support mcs feedback / -#define MCSFBK_RSV 1 // reserved -#define MCSFBK_UNSOLICIT 2 // only support unsolict mcs feedback -#define MCSFBK_MRQ 3 // response to both MRQ and unsolict mcs feedback - -// MIMO power safe +#define STBC_USE 1 /* limited use in rt2860b phy */ +#define RXSTBC_ONE 1 /* rx support of one spatial stream */ +#define RXSTBC_TWO 2 /* rx support of 1 and 2 spatial stream */ +#define RXSTBC_THR 3 /* rx support of 1~3 spatial stream */ +/* MCS FEEDBACK */ +#define MCSFBK_NONE 0 /* not support mcs feedback / */ +#define MCSFBK_RSV 1 /* reserved */ +#define MCSFBK_UNSOLICIT 2 /* only support unsolict mcs feedback */ +#define MCSFBK_MRQ 3 /* response to both MRQ and unsolict mcs feedback */ + +/* MIMO power safe */ #define MMPS_STATIC 0 #define MMPS_DYNAMIC 1 #define MMPS_RSV 2 #define MMPS_ENABLE 3 - -// A-MSDU size +/* A-MSDU size */ #define AMSDU_0 0 #define AMSDU_1 1 -// MCS use 7 bits +/* MCS use 7 bits */ #define TXRATEMIMO 0x80 #define TXRATEMCS 0x7F #define TXRATEOFDM 0x7F @@ -1119,73 +1074,77 @@ #define RATE_2 1 #define RATE_5_5 2 #define RATE_11 3 -#define RATE_6 4 // OFDM -#define RATE_9 5 // OFDM -#define RATE_12 6 // OFDM -#define RATE_18 7 // OFDM -#define RATE_24 8 // OFDM -#define RATE_36 9 // OFDM -#define RATE_48 10 // OFDM -#define RATE_54 11 // OFDM +#define RATE_6 4 /* OFDM */ +#define RATE_9 5 /* OFDM */ +#define RATE_12 6 /* OFDM */ +#define RATE_18 7 /* OFDM */ +#define RATE_24 8 /* OFDM */ +#define RATE_36 9 /* OFDM */ +#define RATE_48 10 /* OFDM */ +#define RATE_54 11 /* OFDM */ #define RATE_FIRST_OFDM_RATE RATE_6 #define RATE_LAST_OFDM_RATE RATE_54 -#define RATE_6_5 12 // HT mix -#define RATE_13 13 // HT mix -#define RATE_19_5 14 // HT mix -#define RATE_26 15 // HT mix -#define RATE_39 16 // HT mix -#define RATE_52 17 // HT mix -#define RATE_58_5 18 // HT mix -#define RATE_65 19 // HT mix -#define RATE_78 20 // HT mix -#define RATE_104 21 // HT mix -#define RATE_117 22 // HT mix -#define RATE_130 23 // HT mix -//#define RATE_AUTO_SWITCH 255 // for StaCfg.FixedTxRate only +#define RATE_6_5 12 /* HT mix */ +#define RATE_13 13 /* HT mix */ +#define RATE_19_5 14 /* HT mix */ +#define RATE_26 15 /* HT mix */ +#define RATE_39 16 /* HT mix */ +#define RATE_52 17 /* HT mix */ +#define RATE_58_5 18 /* HT mix */ +#define RATE_65 19 /* HT mix */ +#define RATE_78 20 /* HT mix */ +#define RATE_104 21 /* HT mix */ +#define RATE_117 22 /* HT mix */ +#define RATE_130 23 /* HT mix */ +/*#define RATE_AUTO_SWITCH 255 // for StaCfg.FixedTxRate only */ #define HTRATE_0 12 #define RATE_FIRST_MM_RATE HTRATE_0 #define RATE_FIRST_HT_RATE HTRATE_0 #define RATE_LAST_HT_RATE HTRATE_0 -// pTxWI->txop -#define IFS_HTTXOP 0 // The txop will be handles by ASIC. +/* pTxWI->txop */ +#define IFS_HTTXOP 0 /* The txop will be handles by ASIC. */ #define IFS_PIFS 1 #define IFS_SIFS 2 #define IFS_BACKOFF 3 -// pTxD->RetryMode -#define LONG_RETRY 1 +/* pTxD->RetryMode */ +#define long_RETRY 1 #define SHORT_RETRY 0 -// Country Region definition +/* Country Region definition */ #define REGION_MINIMUM_BG_BAND 0 -#define REGION_0_BG_BAND 0 // 1-11 -#define REGION_1_BG_BAND 1 // 1-13 -#define REGION_2_BG_BAND 2 // 10-11 -#define REGION_3_BG_BAND 3 // 10-13 -#define REGION_4_BG_BAND 4 // 14 -#define REGION_5_BG_BAND 5 // 1-14 -#define REGION_6_BG_BAND 6 // 3-9 -#define REGION_7_BG_BAND 7 // 5-13 -#define REGION_31_BG_BAND 31 // 5-13 +#define REGION_0_BG_BAND 0 /* 1-11 */ +#define REGION_1_BG_BAND 1 /* 1-13 */ +#define REGION_2_BG_BAND 2 /* 10-11 */ +#define REGION_3_BG_BAND 3 /* 10-13 */ +#define REGION_4_BG_BAND 4 /* 14 */ +#define REGION_5_BG_BAND 5 /* 1-14 */ +#define REGION_6_BG_BAND 6 /* 3-9 */ +#define REGION_7_BG_BAND 7 /* 5-13 */ +#define REGION_31_BG_BAND 31 /* 5-13 */ #define REGION_MAXIMUM_BG_BAND 7 #define REGION_MINIMUM_A_BAND 0 -#define REGION_0_A_BAND 0 // 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 -#define REGION_1_A_BAND 1 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 -#define REGION_2_A_BAND 2 // 36, 40, 44, 48, 52, 56, 60, 64 -#define REGION_3_A_BAND 3 // 52, 56, 60, 64, 149, 153, 157, 161 -#define REGION_4_A_BAND 4 // 149, 153, 157, 161, 165 -#define REGION_5_A_BAND 5 // 149, 153, 157, 161 -#define REGION_6_A_BAND 6 // 36, 40, 44, 48 -#define REGION_7_A_BAND 7 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 -#define REGION_8_A_BAND 8 // 52, 56, 60, 64 -#define REGION_9_A_BAND 9 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165 -#define REGION_10_A_BAND 10 // 36, 40, 44, 48, 149, 153, 157, 161, 165 -#define REGION_11_A_BAND 11 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161 -#define REGION_MAXIMUM_A_BAND 11 - -// pTxD->CipherAlg +#define REGION_0_A_BAND 0 /* 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 */ +#define REGION_1_A_BAND 1 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 */ +#define REGION_2_A_BAND 2 /* 36, 40, 44, 48, 52, 56, 60, 64 */ +#define REGION_3_A_BAND 3 /* 52, 56, 60, 64, 149, 153, 157, 161 */ +#define REGION_4_A_BAND 4 /* 149, 153, 157, 161, 165 */ +#define REGION_5_A_BAND 5 /* 149, 153, 157, 161 */ +#define REGION_6_A_BAND 6 /* 36, 40, 44, 48 */ +#define REGION_7_A_BAND 7 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 169, 173 */ +#define REGION_8_A_BAND 8 /* 52, 56, 60, 64 */ +#define REGION_9_A_BAND 9 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165 */ +#define REGION_10_A_BAND 10 /* 36, 40, 44, 48, 149, 153, 157, 161, 165 */ +#define REGION_11_A_BAND 11 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161 */ +#define REGION_12_A_BAND 12 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 */ +#define REGION_13_A_BAND 13 /* 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161 */ +#define REGION_14_A_BAND 14 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165 */ +#define REGION_15_A_BAND 15 /* 149, 153, 157, 161, 165, 169, 173 */ +#define REGION_MAXIMUM_A_BAND 15 + +/* pTxD->CipherAlg */ #define CIPHER_NONE 0 #define CIPHER_WEP64 1 #define CIPHER_WEP128 2 @@ -1193,20 +1152,10 @@ #define CIPHER_AES 4 #define CIPHER_CKIP64 5 #define CIPHER_CKIP128 6 -#define CIPHER_TKIP_NO_MIC 7 // MIC appended by driver: not a valid value in hardware key table +#define CIPHER_TKIP_NO_MIC 7 /* MIC appended by driver: not a valid value in hardware key table */ #define CIPHER_SMS4 8 -// value domain of pAd->RfIcType -#define RFIC_2820 1 // 2.4G 2T3R -#define RFIC_2850 2 // 2.4G/5G 2T3R -#define RFIC_2720 3 // 2.4G 1T2R -#define RFIC_2750 4 // 2.4G/5G 1T2R -#define RFIC_3020 5 // 2.4G 1T1R -#define RFIC_2020 6 // 2.4G B/G -#define RFIC_3021 7 // 2.4G 1T2R -#define RFIC_3022 8 // 2.4G 2T2R - -// LED Status. +/* LED Status. */ #define LED_LINK_DOWN 0 #define LED_LINK_UP 1 #define LED_RADIO_OFF 2 @@ -1216,35 +1165,35 @@ #define LED_ON_SITE_SURVEY 6 #define LED_POWER_UP 7 -// value domain of pAd->LedCntl.LedMode and E2PROM +/* value domain of pAd->LedCntl.LedMode and E2PROM */ #define LED_MODE_DEFAULT 0 #define LED_MODE_TWO_LED 1 -#define LED_MODE_SIGNAL_STREGTH 8 // EEPROM define =8 +/*#define LED_MODE_SIGNAL_STREGTH 8 // EEPROM define =8 */ +#define LED_MODE_SIGNAL_STREGTH 0x40 /* EEPROM define = 64 */ -// RC4 init value, used fro WEP & TKIP -#define PPPINITFCS32 0xffffffff /* Initial FCS value */ +/* RC4 init value, used fro WEP & TKIP */ +#define PPPINITFCS32 0xffffffff /* Initial FCS value */ -// value domain of pAd->StaCfg.PortSecured. 802.1X controlled port definition +/* value domain of pAd->StaCfg.PortSecured. 802.1X controlled port definition */ #define WPA_802_1X_PORT_SECURED 1 #define WPA_802_1X_PORT_NOT_SECURED 2 #define PAIRWISE_KEY 1 #define GROUP_KEY 2 -//definition of DRS +/*definition of DRS */ #define MAX_STEP_OF_TX_RATE_SWITCH 32 - -// pre-allocated free NDIS PACKET/BUFFER poll for internal usage +/* pre-allocated free NDIS PACKET/BUFFER poll for internal usage */ #define MAX_NUM_OF_FREE_NDIS_PACKET 128 -//Block ACK +/*Block ACK */ #define MAX_TX_REORDERBUF 64 #define MAX_RX_REORDERBUF 64 #define DEFAULT_TX_TIMEOUT 30 #define DEFAULT_RX_TIMEOUT 30 -// definition of Recipient or Originator +/* definition of Recipient or Originator */ #define I_RECIPIENT TRUE #define I_ORIGINATOR FALSE @@ -1252,46 +1201,45 @@ #define DEFAULT_RF_TX_POWER 5 #define MAX_INI_BUFFER_SIZE 4096 -#define MAX_PARAM_BUFFER_SIZE (2048) // enough for ACL (18*64) - //18 : the length of Mac address acceptable format "01:02:03:04:05:06;") - //64 : MAX_NUM_OF_ACL_LIST -// definition of pAd->OpMode +#define MAX_PARAM_BUFFER_SIZE (2048) /* enough for ACL (18*64) */ + /*18 : the length of Mac address acceptable format "01:02:03:04:05:06;") */ + /*64 : MAX_NUM_OF_ACL_LIST */ +/* definition of pAd->OpMode */ #define OPMODE_STA 0 #define OPMODE_AP 1 -//#define OPMODE_L3_BRG 2 // as AP and STA at the same time - -// ========================= AP rtmp_def.h =========================== -// value domain for pAd->EventTab.Log[].Event -#define EVENT_RESET_ACCESS_POINT 0 // Log = "hh:mm:ss Restart Access Point" -#define EVENT_ASSOCIATED 1 // Log = "hh:mm:ss STA 00:01:02:03:04:05 associated" -#define EVENT_DISASSOCIATED 2 // Log = "hh:mm:ss STA 00:01:02:03:04:05 left this BSS" -#define EVENT_AGED_OUT 3 // Log = "hh:mm:ss STA 00:01:02:03:04:05 was aged-out and removed from this BSS" +/*#define OPMODE_L3_BRG 2 // as AP and STA at the same time */ + +/* ========================= AP rtmp_def.h =========================== */ +/* value domain for pAd->EventTab.Log[].Event */ +#define EVENT_RESET_ACCESS_POint 0 /* Log = "hh:mm:ss Restart Access Point" */ +#define EVENT_ASSOCIATED 1 /* Log = "hh:mm:ss STA 00:01:02:03:04:05 associated" */ +#define EVENT_DISASSOCIATED 2 /* Log = "hh:mm:ss STA 00:01:02:03:04:05 left this BSS" */ +#define EVENT_AGED_OUT 3 /* Log = "hh:mm:ss STA 00:01:02:03:04:05 was aged-out and removed from this BSS" */ #define EVENT_COUNTER_M 4 #define EVENT_INVALID_PSK 5 #define EVENT_MAX_EVENT_TYPE 6 -// ==== end of AP rtmp_def.h ============ +/* ==== end of AP rtmp_def.h ============ */ -// definition RSSI Number +/* definition RSSI Number */ #define RSSI_0 0 #define RSSI_1 1 #define RSSI_2 2 -// definition of radar detection -#define RD_NORMAL_MODE 0 // Not found radar signal -#define RD_SWITCHING_MODE 1 // Found radar signal, and doing channel switch -#define RD_SILENCE_MODE 2 // After channel switch, need to be silence a while to ensure radar not found +/* definition of radar detection */ +#define RD_NORMAL_MODE 0 /* Not found radar signal */ +#define RD_SWITCHING_MODE 1 /* Found radar signal, and doing channel switch */ +#define RD_SILENCE_MODE 2 /* After channel switch, need to be silence a while to ensure radar not found */ -//Driver defined cid for mapping status and command. +/*Driver defined cid for mapping status and command. */ #define SLEEPCID 0x11 #define WAKECID 0x22 #define QUERYPOWERCID 0x33 #define OWNERMCU 0x1 #define OWNERCPU 0x0 -// MBSSID definition +/* MBSSID definition */ #define ENTRY_NOT_FOUND 0xFF - /* After Linux 2.6.9, * VLAN module use Private (from user) interface flags (netdevice->priv_flags). * #define IFF_802_1Q_VLAN 0x1 -- 802.1Q VLAN device. in if.h @@ -1305,19 +1253,21 @@ #define INT_APCLI 0x0400 #define INT_MESH 0x0500 -// Use bitmap to allow coexist of ATE_TXFRAME and ATE_RXFRAME(i.e.,to support LoopBack mode) +#define INF_MAIN_DEV_NAME "wlan" +#define INF_MBSSID_DEV_NAME "ra" +#define INF_WDS_DEV_NAME "wds" +#define INF_APCLI_DEV_NAME "apcli" +#define INF_MESH_DEV_NAME "mesh" -// WEP Key TYPE +/* WEP Key TYPE */ #define WEP_HEXADECIMAL_TYPE 0 #define WEP_ASCII_TYPE 1 - - -// WIRELESS EVENTS definition +/* WIRELESS EVENTS definition */ /* Max number of char in custom event, refer to wireless_tools.28/wireless.20.h */ #define IW_CUSTOM_MAX_LEN 255 /* In bytes */ -// For system event - start +/* For system event - start */ #define IW_SYS_EVENT_FLAG_START 0x0200 #define IW_ASSOC_EVENT_FLAG 0x0200 #define IW_DISASSOC_EVENT_FLAG 0x0201 @@ -1338,12 +1288,12 @@ #define IW_STA_LINKDOWN_EVENT_FLAG 0x0210 #define IW_SCAN_COMPLETED_EVENT_FLAG 0x0211 #define IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG 0x0212 -// if add new system event flag, please upadte the IW_SYS_EVENT_FLAG_END +/* if add new system event flag, please upadte the IW_SYS_EVENT_FLAG_END */ #define IW_SYS_EVENT_FLAG_END 0x0212 #define IW_SYS_EVENT_TYPE_NUM (IW_SYS_EVENT_FLAG_END - IW_SYS_EVENT_FLAG_START + 1) -// For system event - end +/* For system event - end */ -// For spoof attack event - start +/* For spoof attack event - start */ #define IW_SPOOF_EVENT_FLAG_START 0x0300 #define IW_CONFLICT_SSID_EVENT_FLAG 0x0300 #define IW_SPOOF_ASSOC_RESP_EVENT_FLAG 0x0301 @@ -1355,12 +1305,12 @@ #define IW_SPOOF_DEAUTH_EVENT_FLAG 0x0307 #define IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG 0x0308 #define IW_REPLAY_ATTACK_EVENT_FLAG 0x0309 -// if add new spoof attack event flag, please upadte the IW_SPOOF_EVENT_FLAG_END +/* if add new spoof attack event flag, please upadte the IW_SPOOF_EVENT_FLAG_END */ #define IW_SPOOF_EVENT_FLAG_END 0x0309 #define IW_SPOOF_EVENT_TYPE_NUM (IW_SPOOF_EVENT_FLAG_END - IW_SPOOF_EVENT_FLAG_START + 1) -// For spoof attack event - end +/* For spoof attack event - end */ -// For flooding attack event - start +/* For flooding attack event - start */ #define IW_FLOOD_EVENT_FLAG_START 0x0400 #define IW_FLOOD_AUTH_EVENT_FLAG 0x0400 #define IW_FLOOD_ASSOC_REQ_EVENT_FLAG 0x0401 @@ -1369,18 +1319,18 @@ #define IW_FLOOD_DISASSOC_EVENT_FLAG 0x0404 #define IW_FLOOD_DEAUTH_EVENT_FLAG 0x0405 #define IW_FLOOD_EAP_REQ_EVENT_FLAG 0x0406 -// if add new flooding attack event flag, please upadte the IW_FLOOD_EVENT_FLAG_END +/* if add new flooding attack event flag, please upadte the IW_FLOOD_EVENT_FLAG_END */ #define IW_FLOOD_EVENT_FLAG_END 0x0406 #define IW_FLOOD_EVENT_TYPE_NUM (IW_FLOOD_EVENT_FLAG_END - IW_FLOOD_EVENT_FLAG_START + 1) -// For flooding attack - end +/* For flooding attack - end */ -// End - WIRELESS EVENTS definition +/* End - WIRELESS EVENTS definition */ -// definition for DLS, kathy +/* definition for DLS, kathy */ #define MAX_NUM_OF_INIT_DLS_ENTRY 1 #define MAX_NUM_OF_DLS_ENTRY MAX_NUMBER_OF_DLS_ENTRY -//Block ACK , rt2860, kathy +/*Block ACK, kathy */ #define MAX_TX_REORDERBUF 64 #define MAX_RX_REORDERBUF 64 #define DEFAULT_TX_TIMEOUT 30 @@ -1392,65 +1342,48 @@ #define IW_ESSID_MAX_SIZE 32 #endif -#ifdef MCAST_RATE_SPECIFIC -#define MCAST_DISABLE 0 -#define MCAST_CCK 1 -#define MCAST_OFDM 2 -#define MCAST_HTMIX 3 -#endif // MCAST_RATE_SPECIFIC // - -#ifdef RT2860 -// For AsicRadioOff/AsicRadioOn/AsicForceWakeup function -// This is to indicate from where to call this function. -#define DOT11POWERSAVE 0 // TO do .11 power save sleep -#define GUIRADIO_OFF 1 // To perform Radio OFf command from GUI -#define RTMP_HALT 2 // Called from Halt handler. -#define GUI_IDLE_POWER_SAVE 3 // Call to sleep before link up with AP -#define FROM_TX 4 // Force wake up from Tx packet. -#endif -#ifdef RT2870 -// For AsicRadioOff/AsicRadioOn function +/* For AsicRadioOff/AsicRadioOn function */ #define DOT11POWERSAVE 0 #define GUIRADIO_OFF 1 #define RTMP_HALT 2 #define GUI_IDLE_POWER_SAVE 3 -#endif +/* -- */ -// definition for WpaSupport flag +/* definition for WpaSupport flag */ #define WPA_SUPPLICANT_DISABLE 0 #define WPA_SUPPLICANT_ENABLE 1 #define WPA_SUPPLICANT_ENABLE_WITH_WEB_UI 2 -// Endian byte swapping codes +/* Endian byte swapping codes */ #define SWAP16(x) \ - ((UINT16)( \ - (((UINT16)(x) & (UINT16) 0x00ffU) << 8) | \ - (((UINT16)(x) & (UINT16) 0xff00U) >> 8) )) + ((u16)( \ + (((u16)(x) & (u16)0x00ffU) << 8) | \ + (((u16)(x) & (u16)0xff00U) >> 8) )) #define SWAP32(x) \ - ((UINT32)( \ - (((UINT32)(x) & (UINT32) 0x000000ffUL) << 24) | \ - (((UINT32)(x) & (UINT32) 0x0000ff00UL) << 8) | \ - (((UINT32)(x) & (UINT32) 0x00ff0000UL) >> 8) | \ - (((UINT32)(x) & (UINT32) 0xff000000UL) >> 24) )) + ((u32)( \ + (((u32)(x) & (u32)0x000000ffUL) << 24) | \ + (((u32)(x) & (u32)0x0000ff00UL) << 8) | \ + (((u32)(x) & (u32)0x00ff0000UL) >> 8) | \ + (((u32)(x) & (u32)0xff000000UL) >> 24) )) #define SWAP64(x) \ - ((UINT64)( \ - (UINT64)(((UINT64)(x) & (UINT64) 0x00000000000000ffULL) << 56) | \ - (UINT64)(((UINT64)(x) & (UINT64) 0x000000000000ff00ULL) << 40) | \ - (UINT64)(((UINT64)(x) & (UINT64) 0x0000000000ff0000ULL) << 24) | \ - (UINT64)(((UINT64)(x) & (UINT64) 0x00000000ff000000ULL) << 8) | \ - (UINT64)(((UINT64)(x) & (UINT64) 0x000000ff00000000ULL) >> 8) | \ - (UINT64)(((UINT64)(x) & (UINT64) 0x0000ff0000000000ULL) >> 24) | \ - (UINT64)(((UINT64)(x) & (UINT64) 0x00ff000000000000ULL) >> 40) | \ - (UINT64)(((UINT64)(x) & (UINT64) 0xff00000000000000ULL) >> 56) )) - -#define cpu2le64(x) ((UINT64)(x)) -#define le2cpu64(x) ((UINT64)(x)) -#define cpu2le32(x) ((UINT32)(x)) -#define le2cpu32(x) ((UINT32)(x)) -#define cpu2le16(x) ((UINT16)(x)) -#define le2cpu16(x) ((UINT16)(x)) + ((u64)( \ + (u64)(((u64)(x) & (u64)0x00000000000000ffULL) << 56) | \ + (u64)(((u64)(x) & (u64)0x000000000000ff00ULL) << 40) | \ + (u64)(((u64)(x) & (u64)0x0000000000ff0000ULL) << 24) | \ + (u64)(((u64)(x) & (u64)0x00000000ff000000ULL) << 8) | \ + (u64)(((u64)(x) & (u64)0x000000ff00000000ULL) >> 8) | \ + (u64)(((u64)(x) & (u64)0x0000ff0000000000ULL) >> 24) | \ + (u64)(((u64)(x) & (u64)0x00ff000000000000ULL) >> 40) | \ + (u64)(((u64)(x) & (u64)0xff00000000000000ULL) >> 56) )) + +#define cpu2le64(x) ((u64)(x)) +#define le2cpu64(x) ((u64)(x)) +#define cpu2le32(x) ((u32)(x)) +#define le2cpu32(x) ((u32)(x)) +#define cpu2le16(x) ((u16)(x)) +#define le2cpu16(x) ((u16)(x)) #define cpu2be64(x) SWAP64((x)) #define be2cpu64(x) SWAP64((x)) #define cpu2be32(x) SWAP32((x)) @@ -1458,6 +1391,36 @@ #define cpu2be16(x) SWAP16((x)) #define be2cpu16(x) SWAP16((x)) -#endif // __RTMP_DEF_H__ - - +#define ABS(_x, _y) ((_x) > (_y)) ? ((_x) -(_y)) : ((_y) -(_x)) + +#define A2Dec(_X, _p) \ +{ \ + u8 *p; \ + _X = 0; \ + p = _p; \ + while (((*p >= '0') && (*p <= '9'))) \ + { \ + if ((*p >= '0') && (*p <= '9')) \ + _X = _X * 10 + *p - 48; \ + p++; \ + } \ +} + +#define A2Hex(_X, _p) \ +do{ \ + char *__p; \ + (_X) = 0; \ + __p = (char *)(_p); \ + while (((*__p >= 'a') && (*__p <= 'f')) || ((*__p >= 'A') && (*__p <= 'F')) || ((*__p >= '0') && (*__p <= '9'))) \ + { \ + if ((*__p >= 'a') && (*__p <= 'f')) \ + (_X) = (_X) * 16 + *__p - 87; \ + else if ((*__p >= 'A') && (*__p <= 'F')) \ + (_X) = (_X) * 16 + *__p - 55; \ + else if ((*__p >= '0') && (*__p <= '9')) \ + (_X) = (_X) * 16 + *__p - 48; \ + __p++; \ + } \ +}while(0) + +#endif /* __RTMP_DEF_H__ */ diff --git a/drivers/staging/rt2860/rtmp_dot11.h b/drivers/staging/rt2860/rtmp_dot11.h new file mode 100644 index 0000000000000000000000000000000000000000..4f8abd77ada5e5f545de3ed0677e62d5bed080f7 --- /dev/null +++ b/drivers/staging/rt2860/rtmp_dot11.h @@ -0,0 +1,100 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* +*/ + +#ifndef __DOT11_BASE_H__ +#define __DOT11_BASE_H__ + +#include "rtmp_type.h" + +/* 4-byte HTC field. maybe included in any frame except non-QOS data frame. The Order bit must set 1. */ +struct PACKED rt_ht_control { + u32 MA:1; /*management action payload exist in (QoS Null+HTC) */ + u32 TRQ:1; /*sounding request */ + u32 MRQ:1; /*MCS feedback. Request for a MCS feedback */ + u32 MRSorASI:3; /* MRQ Sequence identifier. unchanged during entire procedure. 0x000-0x110. */ + u32 MFS:3; /*SET to the received value of MRS. 0x111 for unsolicited MFB. */ + u32 MFBorASC:7; /*Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available */ + u32 CalPos:2; /* calibration position */ + u32 CalSeq:2; /*calibration sequence */ + u32 FBKReq:2; /*feedback request */ + u32 CSISTEERING:2; /*CSI/ STEERING */ + u32 ZLFAnnouce:1; /* ZLF announcement */ + u32 rsv:5; /*calibration sequence */ + u32 ACConstraint:1; /*feedback request */ + u32 RDG:1; /*RDG / More PPDU */ +}; + +/* 2-byte QOS CONTROL field */ +struct PACKED rt_qos_control { + u16 TID:4; + u16 EOSP:1; + u16 AckPolicy:2; /*0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP 3: BA */ + u16 AMsduPresent:1; + u16 Txop_QueueSize:8; +}; + +/* 2-byte Frame control field */ +struct PACKED rt_frame_control { + u16 Ver:2; /* Protocol version */ + u16 Type:2; /* MSDU type */ + u16 SubType:4; /* MSDU subtype */ + u16 ToDs:1; /* To DS indication */ + u16 FrDs:1; /* From DS indication */ + u16 MoreFrag:1; /* More fragment bit */ + u16 Retry:1; /* Retry status bit */ + u16 PwrMgmt:1; /* Power management bit */ + u16 MoreData:1; /* More data bit */ + u16 Wep:1; /* Wep data */ + u16 Order:1; /* Strict order expected */ +}; + +struct PACKED rt_header_802_11 { + struct rt_frame_control FC; + u16 Duration; + u8 Addr1[MAC_ADDR_LEN]; + u8 Addr2[MAC_ADDR_LEN]; + u8 Addr3[MAC_ADDR_LEN]; + u16 Frag:4; + u16 Sequence:12; + u8 Octet[0]; +}; + +struct PACKED rt_pspoll_frame { + struct rt_frame_control FC; + u16 Aid; + u8 Bssid[MAC_ADDR_LEN]; + u8 Ta[MAC_ADDR_LEN]; +}; + +struct PACKED rt_rts_frame { + struct rt_frame_control FC; + u16 Duration; + u8 Addr1[MAC_ADDR_LEN]; + u8 Addr2[MAC_ADDR_LEN]; +}; + +#endif /* __DOT11_BASE_H__ // */ diff --git a/drivers/staging/rt3090/rtmp_iface.h b/drivers/staging/rt2860/rtmp_iface.h similarity index 70% rename from drivers/staging/rt3090/rtmp_iface.h rename to drivers/staging/rt2860/rtmp_iface.h index 168d0797fb6a73897e7e7f08c8468444dae05d63..808c05529848ce7f697657d82794d423cc85070e 100644 --- a/drivers/staging/rt3090/rtmp_iface.h +++ b/drivers/staging/rt2860/rtmp_iface.h @@ -38,44 +38,38 @@ #define __RTMP_IFACE_H__ #ifdef RTMP_PCI_SUPPORT -#include "rtmp_pci.h" -#endif // RTMP_PCI_SUPPORT // - - -typedef struct _INF_PCI_CONFIG_ -{ - unsigned long CSRBaseAddress; // PCI MMIO Base Address, all access will use - unsigned int irq_num; -}INF_PCI_CONFIG; - - -typedef struct _INF_USB_CONFIG_ -{ - UINT8 BulkInEpAddr; // bulk-in endpoint address - UINT8 BulkOutEpAddr[6]; // bulk-out endpoint address -}INF_USB_CONFIG; - - -typedef struct _INF_RBUS_CONFIG_ -{ - unsigned long csr_addr; - unsigned int irq; -}INF_RBUS_CONFIG; - - -typedef enum _RTMP_INF_TYPE_ -{ +#include "iface/rtmp_pci.h" +#endif /* RTMP_PCI_SUPPORT // */ +#ifdef RTMP_USB_SUPPORT +#include "iface/rtmp_usb.h" +#endif /* RTMP_USB_SUPPORT // */ + +struct rt_inf_pci_config { + unsigned long CSRBaseAddress; /* PCI MMIO Base Address, all access will use */ + unsigned int irq_num; +}; + +struct rt_inf_usb_config { + u8 BulkInEpAddr; /* bulk-in endpoint address */ + u8 BulkOutEpAddr[6]; /* bulk-out endpoint address */ +}; + +struct rt_inf_rbus_config { + unsigned long csr_addr; + unsigned int irq; +}; + +typedef enum _RTMP_INF_TYPE_ { RTMP_DEV_INF_UNKNOWN = 0, RTMP_DEV_INF_PCI = 1, RTMP_DEV_INF_USB = 2, RTMP_DEV_INF_RBUS = 4, -}RTMP_INF_TYPE; - +} RTMP_INF_TYPE; -typedef union _RTMP_INF_CONFIG_{ - struct _INF_PCI_CONFIG_ pciConfig; - struct _INF_USB_CONFIG_ usbConfig; - struct _INF_RBUS_CONFIG_ rbusConfig; -}RTMP_INF_CONFIG; +typedef union _RTMP_INF_CONFIG_ { + struct rt_inf_pci_config pciConfig; + struct rt_inf_usb_config usbConfig; + struct rt_inf_rbus_config rbusConfig; +} RTMP_INF_CONFIG; -#endif // __RTMP_IFACE_H__ // +#endif /* __RTMP_IFACE_H__ // */ diff --git a/drivers/staging/rt3090/rtmp_mcu.h b/drivers/staging/rt2860/rtmp_mcu.h similarity index 86% rename from drivers/staging/rt3090/rtmp_mcu.h rename to drivers/staging/rt2860/rtmp_mcu.h index e1b2fee9e1056b5417bc188a2970b91cb2fda7ad..d0987e55cdadc4de5b664fd4cb3dca128d5beae1 100644 --- a/drivers/staging/rt3090/rtmp_mcu.h +++ b/drivers/staging/rt2860/rtmp_mcu.h @@ -38,18 +38,12 @@ #ifndef __RTMP_MCU_H__ #define __RTMP_MCU_H__ +int RtmpAsicEraseFirmware(struct rt_rtmp_adapter *pAd); -INT RtmpAsicEraseFirmware( - IN PRTMP_ADAPTER pAd); +int RtmpAsicLoadFirmware(struct rt_rtmp_adapter *pAd); -NDIS_STATUS RtmpAsicLoadFirmware( - IN PRTMP_ADAPTER pAd); +int RtmpAsicSendCommandToMcu(struct rt_rtmp_adapter *pAd, + u8 Command, + u8 Token, u8 Arg0, u8 Arg1); -INT RtmpAsicSendCommandToMcu( - IN PRTMP_ADAPTER pAd, - IN UCHAR Command, - IN UCHAR Token, - IN UCHAR Arg0, - IN UCHAR Arg1); - -#endif // __RTMP_MCU_H__ // +#endif /* __RTMP_MCU_H__ // */ diff --git a/drivers/staging/rt3090/rtmp_os.h b/drivers/staging/rt2860/rtmp_os.h similarity index 77% rename from drivers/staging/rt3090/rtmp_os.h rename to drivers/staging/rt2860/rtmp_os.h index 5646b2dfd6a8d3cc6cecd462266c530c697aaa46..94c30c8ca6624f0410bf5b0e54d8d8fce91cd32f 100644 --- a/drivers/staging/rt3090/rtmp_os.h +++ b/drivers/staging/rt2860/rtmp_os.h @@ -34,14 +34,12 @@ --------- ---------- ---------------------------------------------- */ - #ifndef __RTMP_OS_H__ #define __RTMP_OS_H__ #ifdef LINUX #include "rt_linux.h" -#endif // LINUX // - +#endif /* LINUX // */ /* This data structure mainly strip some callback function defined in @@ -50,44 +48,43 @@ The definition of this data structure may various depends on different OS. Use it carefully. */ -typedef struct _RTMP_OS_NETDEV_OP_HOOK_ -{ +struct rt_rtmp_os_netdev_op_hook { const struct net_device_ops *netdev_ops; - void *priv; - int priv_flags; + void *priv; + int priv_flags; unsigned char devAddr[6]; - unsigned char devName[16]; - unsigned char needProtcted; -}RTMP_OS_NETDEV_OP_HOOK, *PRTMP_OS_NETDEV_OP_HOOK; + unsigned char devName[16]; + unsigned char needProtcted; +}; - -typedef enum _RTMP_TASK_STATUS_ -{ +typedef enum _RTMP_TASK_STATUS_ { RTMP_TASK_STAT_UNKNOWN = 0, RTMP_TASK_STAT_INITED = 1, RTMP_TASK_STAT_RUNNING = 2, RTMP_TASK_STAT_STOPED = 4, -}RTMP_TASK_STATUS; +} RTMP_TASK_STATUS; #define RTMP_TASK_CAN_DO_INSERT (RTMP_TASK_STAT_INITED |RTMP_TASK_STAT_RUNNING) #define RTMP_OS_TASK_NAME_LEN 16 -typedef struct _RTMP_OS_TASK_ -{ - char taskName[RTMP_OS_TASK_NAME_LEN]; - void *priv; - //unsigned long taskFlags; - RTMP_TASK_STATUS taskStatus; +struct rt_rtmp_os_task { + char taskName[RTMP_OS_TASK_NAME_LEN]; + void *priv; + /*unsigned long taskFlags; */ + RTMP_TASK_STATUS taskStatus; #ifndef KTHREAD_SUPPORT - RTMP_OS_SEM taskSema; - RTMP_OS_PID taskPID; - struct completion taskComplete; + struct semaphore taskSema; + struct pid *taskPID; + struct completion taskComplete; #endif - unsigned char task_killed; + unsigned char task_killed; #ifdef KTHREAD_SUPPORT - struct task_struct *kthread_task; - wait_queue_head_t kthread_q; - BOOLEAN kthread_running; + struct task_struct *kthread_task; + wait_queue_head_t kthread_q; + BOOLEAN kthread_running; #endif -}RTMP_OS_TASK; +}; + +int RtmpOSIRQRequest(struct net_device *pNetDev); +int RtmpOSIRQRelease(struct net_device *pNetDev); -#endif // __RMTP_OS_H__ // +#endif /* __RMTP_OS_H__ // */ diff --git a/drivers/staging/rt3090/rtmp_timer.h b/drivers/staging/rt2860/rtmp_timer.h similarity index 65% rename from drivers/staging/rt3090/rtmp_timer.h rename to drivers/staging/rt2860/rtmp_timer.h index dfac124ebf144764aba70a191d9c7cd9bea2f118..28b8ac6e835282de06475dc66bf580b9d6e504de 100644 --- a/drivers/staging/rt3090/rtmp_timer.h +++ b/drivers/staging/rt2860/rtmp_timer.h @@ -43,69 +43,62 @@ #include "rtmp_os.h" - #define DECLARE_TIMER_FUNCTION(_func) \ void rtmp_timer_##_func(unsigned long data) #define GET_TIMER_FUNCTION(_func) \ rtmp_timer_##_func - /* ----------------- Timer Related MARCO ---------------*/ -// In some os or chipset, we have a lot of timer functions and will read/write register, -// it's not allowed in Linux USB sub-system to do it ( because of sleep issue when -// submit to ctrl pipe). So we need a wrapper function to take care it. +/* In some os or chipset, we have a lot of timer functions and will read/write register, */ +/* it's not allowed in Linux USB sub-system to do it ( because of sleep issue when */ +/* submit to ctrl pipe). So we need a wrapper function to take care it. */ #ifdef RTMP_TIMER_TASK_SUPPORT -typedef VOID (*RTMP_TIMER_TASK_HANDLE)( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); -#endif // RTMP_TIMER_TASK_SUPPORT // - -typedef struct _RALINK_TIMER_STRUCT { - RTMP_OS_TIMER TimerObj; // Ndis Timer object - BOOLEAN Valid; // Set to True when call RTMPInitTimer - BOOLEAN State; // True if timer cancelled - BOOLEAN PeriodicType; // True if timer is periodic timer - BOOLEAN Repeat; // True if periodic timer - ULONG TimerValue; // Timer value in milliseconds - ULONG cookie; // os specific object +typedef void(*RTMP_TIMER_TASK_HANDLE) (void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, + void *SystemSpecific3); +#endif /* RTMP_TIMER_TASK_SUPPORT // */ + +struct rt_ralink_timer { + struct timer_list TimerObj; /* Ndis Timer object */ + BOOLEAN Valid; /* Set to True when call RTMPInitTimer */ + BOOLEAN State; /* True if timer cancelled */ + BOOLEAN PeriodicType; /* True if timer is periodic timer */ + BOOLEAN Repeat; /* True if periodic timer */ + unsigned long TimerValue; /* Timer value in milliseconds */ + unsigned long cookie; /* os specific object */ #ifdef RTMP_TIMER_TASK_SUPPORT - RTMP_TIMER_TASK_HANDLE handle; - void *pAd; -#endif // RTMP_TIMER_TASK_SUPPORT // -}RALINK_TIMER_STRUCT, *PRALINK_TIMER_STRUCT; - + RTMP_TIMER_TASK_HANDLE handle; + void *pAd; +#endif /* RTMP_TIMER_TASK_SUPPORT // */ +}; #ifdef RTMP_TIMER_TASK_SUPPORT -typedef struct _RTMP_TIMER_TASK_ENTRY_ -{ - RALINK_TIMER_STRUCT *pRaTimer; - struct _RTMP_TIMER_TASK_ENTRY_ *pNext; -}RTMP_TIMER_TASK_ENTRY; - +struct rt_rtmp_timer_task_entry { + struct rt_ralink_timer *pRaTimer; + struct rt_rtmp_timer_task_entry *pNext; +}; #define TIMER_QUEUE_SIZE_MAX 128 -typedef struct _RTMP_TIMER_TASK_QUEUE_ -{ - unsigned int status; - unsigned char *pTimerQPoll; - RTMP_TIMER_TASK_ENTRY *pQPollFreeList; - RTMP_TIMER_TASK_ENTRY *pQHead; - RTMP_TIMER_TASK_ENTRY *pQTail; -}RTMP_TIMER_TASK_QUEUE; +struct rt_rtmp_timer_task_queue { + unsigned int status; + unsigned char *pTimerQPoll; + struct rt_rtmp_timer_task_entry *pQPollFreeList; + struct rt_rtmp_timer_task_entry *pQHead; + struct rt_rtmp_timer_task_entry *pQTail; +}; #define BUILD_TIMER_FUNCTION(_func) \ void rtmp_timer_##_func(unsigned long data) \ { \ - PRALINK_TIMER_STRUCT _pTimer = (PRALINK_TIMER_STRUCT)data; \ - RTMP_TIMER_TASK_ENTRY *_pQNode; \ - RTMP_ADAPTER *_pAd; \ + struct rt_ralink_timer *_pTimer = (struct rt_ralink_timer *)data; \ + struct rt_rtmp_timer_task_entry *_pQNode; \ + struct rt_rtmp_adapter *_pAd; \ \ _pTimer->handle = _func; \ - _pAd = (RTMP_ADAPTER *)_pTimer->pAd; \ + _pAd = (struct rt_rtmp_adapter *)_pTimer->pAd; \ _pQNode = RtmpTimerQInsert(_pAd, _pTimer); \ if ((_pQNode == NULL) && (_pAd->TimerQ.status & RTMP_TASK_CAN_DO_INSERT)) \ RTMP_OS_Add_Timer(&_pTimer->TimerObj, OS_HZ); \ @@ -114,23 +107,23 @@ void rtmp_timer_##_func(unsigned long data) \ #define BUILD_TIMER_FUNCTION(_func) \ void rtmp_timer_##_func(unsigned long data) \ { \ - PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) data; \ + struct rt_ralink_timer *pTimer = (struct rt_ralink_timer *)data; \ \ - _func(NULL, (PVOID) pTimer->cookie, NULL, pTimer); \ + _func(NULL, (void *)pTimer->cookie, NULL, pTimer); \ if (pTimer->Repeat) \ RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue); \ } -#endif // RTMP_TIMER_TASK_SUPPORT // - +#endif /* RTMP_TIMER_TASK_SUPPORT // */ DECLARE_TIMER_FUNCTION(MlmePeriodicExec); DECLARE_TIMER_FUNCTION(MlmeRssiReportExec); DECLARE_TIMER_FUNCTION(AsicRxAntEvalTimeout); DECLARE_TIMER_FUNCTION(APSDPeriodicExec); DECLARE_TIMER_FUNCTION(AsicRfTuningExec); +#ifdef RTMP_MAC_USB +DECLARE_TIMER_FUNCTION(BeaconUpdateExec); +#endif /* RTMP_MAC_USB // */ - -#ifdef CONFIG_STA_SUPPORT DECLARE_TIMER_FUNCTION(BeaconTimeout); DECLARE_TIMER_FUNCTION(ScanTimeout); DECLARE_TIMER_FUNCTION(AuthTimeout); @@ -143,20 +136,12 @@ DECLARE_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc); DECLARE_TIMER_FUNCTION(PsPollWakeExec); DECLARE_TIMER_FUNCTION(RadioOnExec); -#ifdef QOS_DLS_SUPPORT -DECLARE_TIMER_FUNCTION(DlsTimeoutAction); -#endif // QOS_DLS_SUPPORT // - - -#endif // CONFIG_STA_SUPPORT // - - - +#ifdef RTMP_MAC_USB +DECLARE_TIMER_FUNCTION(RtmpUsbStaAsicForceWakeupTimeout); +#endif /* RTMP_MAC_USB // */ #if defined(AP_LED) || defined(STA_LED) DECLARE_TIMER_FUNCTION(LedCtrlMain); #endif - - -#endif // __RTMP_TIMER_H__ // +#endif /* __RTMP_TIMER_H__ // */ diff --git a/drivers/staging/rt2860/rtmp_type.h b/drivers/staging/rt2860/rtmp_type.h index 1fd7df1e1791c428188f853d37b528cdcc36b0c3..d9bb2d64c8b8b3424b99f8ec0eee9ed718029c7e 100644 --- a/drivers/staging/rt2860/rtmp_type.h +++ b/drivers/staging/rt2860/rtmp_type.h @@ -38,57 +38,52 @@ #ifndef __RTMP_TYPE_H__ #define __RTMP_TYPE_H__ -#define PACKED __attribute__ ((packed)) - -// Put platform dependent declaration here -// For example, linux type definition -typedef unsigned char UINT8; -typedef unsigned short UINT16; -typedef unsigned int UINT32; -typedef unsigned long long UINT64; -typedef int INT32; -typedef long long INT64; +#include -typedef unsigned char * PUINT8; -typedef unsigned short * PUINT16; -typedef unsigned int * PUINT32; -typedef unsigned long long * PUINT64; -typedef int * PINT32; -typedef long long * PINT64; - -typedef signed char CHAR; -typedef signed short SHORT; -typedef signed int INT; -typedef signed long LONG; -typedef signed long long LONGLONG; +#define PACKED __attribute__ ((packed)) +typedef unsigned char BOOLEAN; -typedef unsigned char UCHAR; -typedef unsigned short USHORT; -typedef unsigned int UINT; -typedef unsigned long ULONG; -typedef unsigned long long ULONGLONG; +typedef union _LARGE_INTEGER { + struct { + u32 LowPart; + int HighPart; + } u; + long long QuadPart; +} LARGE_INTEGER; -typedef unsigned char BOOLEAN; -typedef void VOID; +/* */ +/* Register set pair for initialzation register set definition */ +/* */ +struct rt_rtmp_reg_pair { + unsigned long Register; + unsigned long Value; +}; -typedef VOID * PVOID; -typedef CHAR * PCHAR; -typedef UCHAR * PUCHAR; -typedef USHORT * PUSHORT; -typedef LONG * PLONG; -typedef ULONG * PULONG; -typedef UINT * PUINT; +struct rt_reg_pair { + u8 Register; + u8 Value; +}; -typedef unsigned int NDIS_MEDIA_STATE; +/* */ +/* Register set pair for initialzation register set definition */ +/* */ +struct rt_rtmp_rf_regs { + u8 Channel; + unsigned long R1; + unsigned long R2; + unsigned long R3; + unsigned long R4; +}; -typedef union _LARGE_INTEGER { - struct { - UINT LowPart; - INT32 HighPart; - } u; - INT64 QuadPart; -} LARGE_INTEGER; +struct rt_frequency_item { + u8 Channel; + u8 N; + u8 R; + u8 K; +}; -#endif // __RTMP_TYPE_H__ +#define STATUS_SUCCESS 0x00 +#define STATUS_UNSUCCESSFUL 0x01 +#endif /* __RTMP_TYPE_H__ // */ diff --git a/drivers/staging/rt2860/rtusb_io.h b/drivers/staging/rt2860/rtusb_io.h new file mode 100644 index 0000000000000000000000000000000000000000..64a2fe43528427e1341f0f9c66fc16857b2ed81f --- /dev/null +++ b/drivers/staging/rt2860/rtusb_io.h @@ -0,0 +1,185 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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. * + * * + ************************************************************************* +*/ + +#ifndef __RTUSB_IO_H__ +#define __RTUSB_IO_H__ + +#include "rtmp_type.h" + +/* New for MeetingHouse Api support */ +#define CMDTHREAD_VENDOR_RESET 0x0D730101 /* cmd */ +#define CMDTHREAD_VENDOR_UNPLUG 0x0D730102 /* cmd */ +#define CMDTHREAD_VENDOR_SWITCH_FUNCTION 0x0D730103 /* cmd */ +#define CMDTHREAD_MULTI_WRITE_MAC 0x0D730107 /* cmd */ +#define CMDTHREAD_MULTI_READ_MAC 0x0D730108 /* cmd */ +#define CMDTHREAD_VENDOR_EEPROM_WRITE 0x0D73010A /* cmd */ +#define CMDTHREAD_VENDOR_EEPROM_READ 0x0D73010B /* cmd */ +#define CMDTHREAD_VENDOR_ENTER_TESTMODE 0x0D73010C /* cmd */ +#define CMDTHREAD_VENDOR_EXIT_TESTMODE 0x0D73010D /* cmd */ +#define CMDTHREAD_VENDOR_WRITE_BBP 0x0D730119 /* cmd */ +#define CMDTHREAD_VENDOR_READ_BBP 0x0D730118 /* cmd */ +#define CMDTHREAD_VENDOR_WRITE_RF 0x0D73011A /* cmd */ +#define CMDTHREAD_VENDOR_FLIP_IQ 0x0D73011D /* cmd */ +#define CMDTHREAD_RESET_BULK_OUT 0x0D730210 /* cmd */ +#define CMDTHREAD_RESET_BULK_IN 0x0D730211 /* cmd */ +#define CMDTHREAD_SET_PSM_BIT 0x0D730212 /* cmd */ +#define CMDTHREAD_SET_RADIO 0x0D730214 /* cmd */ +#define CMDTHREAD_UPDATE_TX_RATE 0x0D730216 /* cmd */ +#define CMDTHREAD_802_11_ADD_KEY_WEP 0x0D730218 /* cmd */ +#define CMDTHREAD_RESET_FROM_ERROR 0x0D73021A /* cmd */ +#define CMDTHREAD_LINK_DOWN 0x0D73021B /* cmd */ +#define CMDTHREAD_RESET_FROM_NDIS 0x0D73021C /* cmd */ +#define CMDTHREAD_CHECK_GPIO 0x0D730215 /* cmd */ +#define CMDTHREAD_FORCE_WAKE_UP 0x0D730222 /* cmd */ +#define CMDTHREAD_SET_BW 0x0D730225 /* cmd */ +#define CMDTHREAD_SET_ASIC_WCID 0x0D730226 /* cmd */ +#define CMDTHREAD_SET_ASIC_WCID_CIPHER 0x0D730227 /* cmd */ +#define CMDTHREAD_QKERIODIC_EXECUT 0x0D73023D /* cmd */ +#define RT_CMD_SET_KEY_TABLE 0x0D730228 /* cmd */ +#define RT_CMD_SET_RX_WCID_TABLE 0x0D730229 /* cmd */ +#define CMDTHREAD_SET_CLIENT_MAC_ENTRY 0x0D73023E /* cmd */ +#define CMDTHREAD_SET_GROUP_KEY 0x0D73023F /* cmd */ +#define CMDTHREAD_SET_PAIRWISE_KEY 0x0D730240 /* cmd */ + +#define CMDTHREAD_802_11_QUERY_HARDWARE_REGISTER 0x0D710105 /* cmd */ +#define CMDTHREAD_802_11_SET_PHY_MODE 0x0D79010C /* cmd */ +#define CMDTHREAD_802_11_SET_STA_CONFIG 0x0D790111 /* cmd */ +#define CMDTHREAD_802_11_SET_PREAMBLE 0x0D790101 /* cmd */ +#define CMDTHREAD_802_11_COUNTER_MEASURE 0x0D790102 /* cmd */ +/* add by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet */ +#define CMDTHREAD_UPDATE_PROTECT 0x0D790103 /* cmd */ +/* end johnli */ + +/*CMDTHREAD_MULTI_READ_MAC */ +/*CMDTHREAD_MULTI_WRITE_MAC */ +/*CMDTHREAD_VENDOR_EEPROM_READ */ +/*CMDTHREAD_VENDOR_EEPROM_WRITE */ +struct rt_cmdhandler_tlv { + u16 Offset; + u16 Length; + u8 DataFirst; +}; + +struct rt_cmdqelmt; + +struct rt_cmdqelmt { + u32 command; + void *buffer; + unsigned long bufferlength; + BOOLEAN CmdFromNdis; + BOOLEAN SetOperation; + struct rt_cmdqelmt *next; +}; + +struct rt_cmdq { + u32 size; + struct rt_cmdqelmt *head; + struct rt_cmdqelmt *tail; + u32 CmdQState; +}; + +#define EnqueueCmd(cmdq, cmdqelmt) \ +{ \ + if (cmdq->size == 0) \ + cmdq->head = cmdqelmt; \ + else \ + cmdq->tail->next = cmdqelmt; \ + cmdq->tail = cmdqelmt; \ + cmdqelmt->next = NULL; \ + cmdq->size++; \ +} + +/****************************************************************************** + + USB Cmd to ASIC Related MACRO + +******************************************************************************/ +/* reset MAC of a station entry to 0xFFFFFFFFFFFF */ +#define RTMP_STA_ENTRY_MAC_RESET(pAd, Wcid) \ + { struct rt_set_asic_wcid SetAsicWcid; \ + SetAsicWcid.WCID = Wcid; \ + SetAsicWcid.SetTid = 0xffffffff; \ + SetAsicWcid.DeleteTid = 0xffffffff; \ + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_SET_ASIC_WCID, \ + &SetAsicWcid, sizeof(struct rt_set_asic_wcid)); } + +/* add this entry into ASIC RX WCID search table */ +#define RTMP_STA_ENTRY_ADD(pAd, pEntry) \ + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_SET_CLIENT_MAC_ENTRY, \ + pEntry, sizeof(struct rt_mac_table_entry)); + +/* add by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet */ +/* Set MAC register value according operation mode */ +#define RTMP_UPDATE_PROTECT(pAd) \ + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_UPDATE_PROTECT, NULL, 0); +/* end johnli */ + +/* remove Pair-wise key material from ASIC */ +/* yet implement */ +#define RTMP_STA_ENTRY_KEY_DEL(pAd, BssIdx, Wcid) + +/* add Client security information into ASIC WCID table and IVEIV table */ +#define RTMP_STA_SECURITY_INFO_ADD(pAd, apidx, KeyID, pEntry) \ + { RTMP_STA_ENTRY_MAC_RESET(pAd, pEntry->Aid); \ + if (pEntry->Aid >= 1) { \ + struct rt_set_asic_wcid_attri SetAsicWcidAttri; \ + SetAsicWcidAttri.WCID = pEntry->Aid; \ + if ((pEntry->AuthMode <= Ndis802_11AuthModeAutoSwitch) && \ + (pEntry->WepStatus == Ndis802_11Encryption1Enabled)) \ + { \ + SetAsicWcidAttri.Cipher = pAd->SharedKey[apidx][KeyID].CipherAlg; \ + } \ + else if (pEntry->AuthMode == Ndis802_11AuthModeWPANone) \ + { \ + SetAsicWcidAttri.Cipher = pAd->SharedKey[apidx][KeyID].CipherAlg; \ + } \ + else SetAsicWcidAttri.Cipher = 0; \ + DBGPRINT(RT_DEBUG_TRACE, ("aid cipher = %ld\n",SetAsicWcidAttri.Cipher)); \ + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_SET_ASIC_WCID_CIPHER, \ + &SetAsicWcidAttri, sizeof(struct rt_set_asic_wcid_attri)); } } + +/* Insert the BA bitmap to ASIC for the Wcid entry */ +#define RTMP_ADD_BA_SESSION_TO_ASIC(_pAd, _Aid, _TID) \ + do{ \ + struct rt_set_asic_wcid SetAsicWcid; \ + SetAsicWcid.WCID = (_Aid); \ + SetAsicWcid.SetTid = (0x10000<<(_TID)); \ + SetAsicWcid.DeleteTid = 0xffffffff; \ + RTUSBEnqueueInternalCmd((_pAd), CMDTHREAD_SET_ASIC_WCID, &SetAsicWcid, sizeof(struct rt_set_asic_wcid)); \ + }while(0) + +/* Remove the BA bitmap from ASIC for the Wcid entry */ +#define RTMP_DEL_BA_SESSION_FROM_ASIC(_pAd, _Wcid, _TID) \ + do{ \ + struct rt_set_asic_wcid SetAsicWcid; \ + SetAsicWcid.WCID = (_Wcid); \ + SetAsicWcid.SetTid = (0xffffffff); \ + SetAsicWcid.DeleteTid = (0x10000<<(_TID) ); \ + RTUSBEnqueueInternalCmd((_pAd), CMDTHREAD_SET_ASIC_WCID, &SetAsicWcid, sizeof(struct rt_set_asic_wcid)); \ + }while(0) + +#endif /* __RTUSB_IO_H__ // */ diff --git a/drivers/staging/rt2860/spectrum.h b/drivers/staging/rt2860/spectrum.h index 0a878ba81b48fe2bc8d5545500669fe43e903eac..648fd632b606d5ec60179939c27d5bbccfafaf90 100644 --- a/drivers/staging/rt2860/spectrum.h +++ b/drivers/staging/rt2860/spectrum.h @@ -23,7 +23,7 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * ************************************************************************* -*/ + */ #ifndef __SPECTRUM_H__ #define __SPECTRUM_H__ @@ -31,112 +31,7 @@ #include "rtmp_type.h" #include "spectrum_def.h" -typedef struct PACKED _TPC_REPORT_INFO -{ - UINT8 TxPwr; - UINT8 LinkMargin; -} TPC_REPORT_INFO, *PTPC_REPORT_INFO; - -typedef struct PACKED _CH_SW_ANN_INFO -{ - UINT8 ChSwMode; - UINT8 Channel; - UINT8 ChSwCnt; -} CH_SW_ANN_INFO, *PCH_SW_ANN_INFO; - -typedef union PACKED _MEASURE_REQ_MODE -{ - struct PACKED - { - UINT8 Rev0:1; - UINT8 Enable:1; - UINT8 Request:1; - UINT8 Report:1; - UINT8 Rev1:4; - } field; - UINT8 word; -} MEASURE_REQ_MODE, *PMEASURE_REQ_MODE; - -typedef struct PACKED _MEASURE_REQ -{ - UINT8 ChNum; - UINT64 MeasureStartTime; - UINT16 MeasureDuration; -} MEASURE_REQ, *PMEASURE_REQ; - -typedef struct PACKED _MEASURE_REQ_INFO -{ - UINT8 Token; - MEASURE_REQ_MODE ReqMode; - UINT8 ReqType; - MEASURE_REQ MeasureReq; -} MEASURE_REQ_INFO, *PMEASURE_REQ_INFO; - -typedef union PACKED _MEASURE_BASIC_REPORT_MAP -{ - struct PACKED - { - UINT8 BSS:1; - UINT8 OfdmPreamble:1; - UINT8 UnidentifiedSignal:1; - UINT8 Radar:1; - UINT8 Unmeasure:1; - UINT8 Rev:3; - } field; - UINT8 word; -} MEASURE_BASIC_REPORT_MAP, *PMEASURE_BASIC_REPORT_MAP; - -typedef struct PACKED _MEASURE_BASIC_REPORT -{ - UINT8 ChNum; - UINT64 MeasureStartTime; - UINT16 MeasureDuration; - MEASURE_BASIC_REPORT_MAP Map; -} MEASURE_BASIC_REPORT, *PMEASURE_BASIC_REPORT; - -typedef struct PACKED _MEASURE_CCA_REPORT -{ - UINT8 ChNum; - UINT64 MeasureStartTime; - UINT16 MeasureDuration; - UINT8 CCA_Busy_Fraction; -} MEASURE_CCA_REPORT, *PMEASURE_CCA_REPORT; - -typedef struct PACKED _MEASURE_RPI_REPORT -{ - UINT8 ChNum; - UINT64 MeasureStartTime; - UINT16 MeasureDuration; - UINT8 RPI_Density[8]; -} MEASURE_RPI_REPORT, *PMEASURE_RPI_REPORT; - -typedef union PACKED _MEASURE_REPORT_MODE -{ - struct PACKED - { - UINT8 Late:1; - UINT8 Incapable:1; - UINT8 Refused:1; - UINT8 Rev:5; - } field; - UINT8 word; -} MEASURE_REPORT_MODE, *PMEASURE_REPORT_MODE; - -typedef struct PACKED _MEASURE_REPORT_INFO -{ - UINT8 Token; - MEASURE_REPORT_MODE ReportMode; - UINT8 ReportType; - UINT8 Octect[0]; -} MEASURE_REPORT_INFO, *PMEASURE_REPORT_INFO; - -typedef struct PACKED _QUIET_INFO -{ - UINT8 QuietCnt; - UINT8 QuietPeriod; - UINT8 QuietDuration; - UINT8 QuietOffset; -} QUIET_INFO, *PQUIET_INFO; +char RTMP_GetTxPwr(struct rt_rtmp_adapter *pAd, IN HTTRANSMIT_SETTING HTTxMode); /* ========================================================================== @@ -150,14 +45,16 @@ typedef struct PACKED _QUIET_INFO Return : None. ========================================================================== */ -VOID EnqueueMeasurementReq( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UINT8 MeasureToken, - IN UINT8 MeasureReqMode, - IN UINT8 MeasureReqType, - IN UINT8 MeasureCh, - IN UINT16 MeasureDuration); +void MakeMeasurementReqFrame(struct rt_rtmp_adapter *pAd, + u8 *pOutBuffer, + unsigned long *pFrameLen, + u8 TotalLen, + u8 Category, + u8 Action, + u8 MeasureToken, + u8 MeasureReqMode, + u8 MeasureReqType, + u8 NumOfRepetitions); /* ========================================================================== @@ -171,15 +68,13 @@ VOID EnqueueMeasurementReq( Return : None. ========================================================================== */ -VOID EnqueueMeasurementRep( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UINT8 DialogToken, - IN UINT8 MeasureToken, - IN UINT8 MeasureReqMode, - IN UINT8 MeasureReqType, - IN UINT8 ReportInfoLen, - IN PUINT8 pReportInfo); +void EnqueueMeasurementRep(struct rt_rtmp_adapter *pAd, + u8 *pDA, + u8 DialogToken, + u8 MeasureToken, + u8 MeasureReqMode, + u8 MeasureReqType, + u8 ReportInfoLen, u8 *pReportInfo); /* ========================================================================== @@ -193,10 +88,7 @@ VOID EnqueueMeasurementRep( Return : None. ========================================================================== */ -VOID EnqueueTPCReq( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UCHAR DialogToken); +void EnqueueTPCReq(struct rt_rtmp_adapter *pAd, u8 *pDA, u8 DialogToken); /* ========================================================================== @@ -210,12 +102,9 @@ VOID EnqueueTPCReq( Return : None. ========================================================================== */ -VOID EnqueueTPCRep( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UINT8 DialogToken, - IN UINT8 TxPwr, - IN UINT8 LinkMargin); +void EnqueueTPCRep(struct rt_rtmp_adapter *pAd, + u8 *pDA, + u8 DialogToken, u8 TxPwr, u8 LinkMargin); /* ========================================================================== @@ -231,11 +120,8 @@ VOID EnqueueTPCRep( Return : None. ========================================================================== */ -VOID EnqueueChSwAnn( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UINT8 ChSwMode, - IN UINT8 NewCh); +void EnqueueChSwAnn(struct rt_rtmp_adapter *pAd, + u8 *pDA, u8 ChSwMode, u8 NewCh); /* ========================================================================== @@ -249,9 +135,7 @@ VOID EnqueueChSwAnn( Return : None. ========================================================================== */ -VOID PeerSpectrumAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); +void PeerSpectrumAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); /* ========================================================================== @@ -262,31 +146,44 @@ VOID PeerSpectrumAction( Return : None. ========================================================================== */ -INT Set_MeasureReq_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +int Set_MeasureReq_Proc(struct rt_rtmp_adapter *pAd, char *arg); + +int Set_TpcReq_Proc(struct rt_rtmp_adapter *pAd, char *arg); + +int Set_PwrConstraint(struct rt_rtmp_adapter *pAd, char *arg); + +void MeasureReqTabInit(struct rt_rtmp_adapter *pAd); + +void MeasureReqTabExit(struct rt_rtmp_adapter *pAd); + +struct rt_measure_req_entry *MeasureReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken); + +struct rt_measure_req_entry *MeasureReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken); + +void MeasureReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken); -INT Set_TpcReq_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); +void InsertChannelRepIE(struct rt_rtmp_adapter *pAd, + u8 *pFrameBuf, + unsigned long *pFrameLen, + char *pCountry, u8 RegulatoryClass); -VOID MeasureReqTabInit( - IN PRTMP_ADAPTER pAd); +void InsertTpcReportIE(struct rt_rtmp_adapter *pAd, + u8 *pFrameBuf, + unsigned long *pFrameLen, + u8 TxPwr, u8 LinkMargin); -VOID MeasureReqTabExit( - IN PRTMP_ADAPTER pAd); +void InsertDialogToken(struct rt_rtmp_adapter *pAd, + u8 *pFrameBuf, + unsigned long *pFrameLen, u8 DialogToken); -VOID TpcReqTabInit( - IN PRTMP_ADAPTER pAd); +void TpcReqTabInit(struct rt_rtmp_adapter *pAd); -VOID TpcReqTabExit( - IN PRTMP_ADAPTER pAd); +void TpcReqTabExit(struct rt_rtmp_adapter *pAd); -VOID NotifyChSwAnnToPeerAPs( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pRA, - IN PUCHAR pTA, - IN UINT8 ChSwMode, - IN UINT8 Channel); -#endif // __SPECTRUM_H__ // +void NotifyChSwAnnToPeerAPs(struct rt_rtmp_adapter *pAd, + u8 *pRA, + u8 *pTA, u8 ChSwMode, u8 Channel); +void RguClass_BuildBcnChList(struct rt_rtmp_adapter *pAd, + u8 *pBuf, unsigned long *pBufLen); +#endif /* __SPECTRUM_H__ // */ diff --git a/drivers/staging/rt2860/spectrum_def.h b/drivers/staging/rt2860/spectrum_def.h index 4ca4817bba050ba716a3e605f58385eef68330a6..8ffcfb0d04f8f6751b79b2e9635434d5d44705c7 100644 --- a/drivers/staging/rt2860/spectrum_def.h +++ b/drivers/staging/rt2860/spectrum_def.h @@ -39,57 +39,164 @@ #ifndef __SPECTRUM_DEF_H__ #define __SPECTRUM_DEF_H__ -#define MAX_MEASURE_REQ_TAB_SIZE 3 +#define MAX_MEASURE_REQ_TAB_SIZE 32 #define MAX_HASH_MEASURE_REQ_TAB_SIZE MAX_MEASURE_REQ_TAB_SIZE -#define MAX_TPC_REQ_TAB_SIZE 3 +#define MAX_TPC_REQ_TAB_SIZE 32 #define MAX_HASH_TPC_REQ_TAB_SIZE MAX_TPC_REQ_TAB_SIZE -#define MIN_RCV_PWR 100 /* Negative value ((dBm) */ +#define MIN_RCV_PWR 100 /* Negative value ((dBm) */ -#define RM_TPC_REQ 0 -#define RM_MEASURE_REQ 1 - -#define RM_BASIC 0 -#define RM_CCA 1 -#define RM_RPI_HISTOGRAM 2 - -#define TPC_REQ_AGE_OUT 500 /* ms */ -#define MQ_REQ_AGE_OUT 500 /* ms */ +#define TPC_REQ_AGE_OUT 500 /* ms */ +#define MQ_REQ_AGE_OUT 500 /* ms */ #define TPC_DIALOGTOKEN_HASH_INDEX(_DialogToken) ((_DialogToken) % MAX_HASH_TPC_REQ_TAB_SIZE) #define MQ_DIALOGTOKEN_HASH_INDEX(_DialogToken) ((_DialogToken) % MAX_MEASURE_REQ_TAB_SIZE) -typedef struct _MEASURE_REQ_ENTRY -{ - struct _MEASURE_REQ_ENTRY *pNext; - ULONG lastTime; - BOOLEAN Valid; - UINT8 DialogToken; - UINT8 MeasureDialogToken[3]; // 0:basic measure, 1: CCA measure, 2: RPI_Histogram measure. -} MEASURE_REQ_ENTRY, *PMEASURE_REQ_ENTRY; - -typedef struct _MEASURE_REQ_TAB -{ - UCHAR Size; - PMEASURE_REQ_ENTRY Hash[MAX_HASH_MEASURE_REQ_TAB_SIZE]; - MEASURE_REQ_ENTRY Content[MAX_MEASURE_REQ_TAB_SIZE]; -} MEASURE_REQ_TAB, *PMEASURE_REQ_TAB; - -typedef struct _TPC_REQ_ENTRY -{ - struct _TPC_REQ_ENTRY *pNext; - ULONG lastTime; +struct rt_measure_req_entry; + +struct rt_measure_req_entry { + struct rt_measure_req_entry *pNext; + unsigned long lastTime; BOOLEAN Valid; - UINT8 DialogToken; -} TPC_REQ_ENTRY, *PTPC_REQ_ENTRY; + u8 DialogToken; + u8 MeasureDialogToken[3]; /* 0:basic measure, 1: CCA measure, 2: RPI_Histogram measure. */ +}; -typedef struct _TPC_REQ_TAB -{ - UCHAR Size; - PTPC_REQ_ENTRY Hash[MAX_HASH_TPC_REQ_TAB_SIZE]; - TPC_REQ_ENTRY Content[MAX_TPC_REQ_TAB_SIZE]; -} TPC_REQ_TAB, *PTPC_REQ_TAB; +struct rt_measure_req_tab { + u8 Size; + struct rt_measure_req_entry *Hash[MAX_HASH_MEASURE_REQ_TAB_SIZE]; + struct rt_measure_req_entry Content[MAX_MEASURE_REQ_TAB_SIZE]; +}; -#endif // __SPECTRUM_DEF_H__ // +struct rt_tpc_req_entry; +struct rt_tpc_req_entry { + struct rt_tpc_req_entry *pNext; + unsigned long lastTime; + BOOLEAN Valid; + u8 DialogToken; +}; + +struct rt_tpc_req_tab { + u8 Size; + struct rt_tpc_req_entry *Hash[MAX_HASH_TPC_REQ_TAB_SIZE]; + struct rt_tpc_req_entry Content[MAX_TPC_REQ_TAB_SIZE]; +}; + +/* The regulatory information */ +struct rt_dot11_channel_set { + u8 NumberOfChannels; + u8 MaxTxPwr; + u8 ChannelList[16]; +}; + +struct rt_dot11_regulatory_information { + u8 RegulatoryClass; + struct rt_dot11_channel_set ChannelSet; +}; + +#define RM_TPC_REQ 0 +#define RM_MEASURE_REQ 1 + +#define RM_BASIC 0 +#define RM_CCA 1 +#define RM_RPI_HISTOGRAM 2 +#define RM_CH_LOAD 3 +#define RM_NOISE_HISTOGRAM 4 + +struct PACKED rt_tpc_report_info { + u8 TxPwr; + u8 LinkMargin; +}; + +struct PACKED rt_ch_sw_ann_info { + u8 ChSwMode; + u8 Channel; + u8 ChSwCnt; +}; + +typedef union PACKED _MEASURE_REQ_MODE { + struct PACKED { + u8 Parallel:1; + u8 Enable:1; + u8 Request:1; + u8 Report:1; + u8 DurationMandatory:1; + u8:3; + } field; + u8 word; +} MEASURE_REQ_MODE, *PMEASURE_REQ_MODE; + +struct PACKED rt_measure_req { + u8 ChNum; + u64 MeasureStartTime; + u16 MeasureDuration; +}; + +struct PACKED rt_measure_req_info { + u8 Token; + MEASURE_REQ_MODE ReqMode; + u8 ReqType; + u8 Oct[0]; +}; + +typedef union PACKED _MEASURE_BASIC_REPORT_MAP { + struct PACKED { + u8 BSS:1; + + u8 OfdmPreamble:1; + u8 UnidentifiedSignal:1; + u8 Radar:1; + u8 Unmeasure:1; + u8 Rev:3; + } field; + u8 word; +} MEASURE_BASIC_REPORT_MAP, *PMEASURE_BASIC_REPORT_MAP; + +struct PACKED rt_measure_basic_report { + u8 ChNum; + u64 MeasureStartTime; + u16 MeasureDuration; + MEASURE_BASIC_REPORT_MAP Map; +}; + +struct PACKED rt_measure_cca_report { + u8 ChNum; + u64 MeasureStartTime; + u16 MeasureDuration; + u8 CCA_Busy_Fraction; +}; + +struct PACKED rt_measure_rpi_report { + u8 ChNum; + u64 MeasureStartTime; + u16 MeasureDuration; + u8 RPI_Density[8]; +}; + +typedef union PACKED _MEASURE_REPORT_MODE { + struct PACKED { + u8 Late:1; + u8 Incapable:1; + u8 Refused:1; + u8 Rev:5; + } field; + u8 word; +} MEASURE_REPORT_MODE, *PMEASURE_REPORT_MODE; + +struct PACKED rt_measure_report_info { + u8 Token; + u8 ReportMode; + u8 ReportType; + u8 Octect[0]; +}; + +struct PACKED rt_quiet_info { + u8 QuietCnt; + u8 QuietPeriod; + u16 QuietDuration; + u16 QuietOffset; +}; + +#endif /* __SPECTRUM_DEF_H__ // */ diff --git a/drivers/staging/rt2860/sta/aironet.c b/drivers/staging/rt2860/sta/aironet.c deleted file mode 100644 index 4af4a1906181133a98dc751c56d5c1ed9064b470..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2860/sta/aironet.c +++ /dev/null @@ -1,1312 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - aironet.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Paul Lin 04-06-15 Initial -*/ -#include "../rt_config.h" - -/* - ========================================================================== - Description: - association state machine init, including state transition and timer init - Parameters: - S - pointer to the association state machine - ========================================================================== - */ -VOID AironetStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]) -{ - StateMachineInit(S, Trans, MAX_AIRONET_STATE, MAX_AIRONET_MSG, (STATE_MACHINE_FUNC)Drop, AIRONET_IDLE, AIRONET_MACHINE_BASE); - StateMachineSetAction(S, AIRONET_IDLE, MT2_AIRONET_MSG, (STATE_MACHINE_FUNC)AironetMsgAction); - StateMachineSetAction(S, AIRONET_IDLE, MT2_AIRONET_SCAN_REQ, (STATE_MACHINE_FUNC)AironetRequestAction); - StateMachineSetAction(S, AIRONET_SCANNING, MT2_AIRONET_SCAN_DONE, (STATE_MACHINE_FUNC)AironetReportAction); -} - -/* - ========================================================================== - Description: - This is state machine function. - When receiving EAPOL packets which is for 802.1x key management. - Use both in WPA, and WPAPSK case. - In this function, further dispatch to different functions according to the received packet. 3 categories are : - 1. normal 4-way pairwisekey and 2-way groupkey handshake - 2. MIC error (Countermeasures attack) report packet from STA. - 3. Request for pairwise/group key update from STA - Return: - ========================================================================== -*/ -VOID AironetMsgAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Length; - UCHAR Index, i; - PUCHAR pData; - PAIRONET_RM_REQUEST_FRAME pRMReq; - PRM_REQUEST_ACTION pReqElem; - - DBGPRINT(RT_DEBUG_TRACE, ("-----> AironetMsgAction\n")); - - // 0. Get Aironet IAPP header first - pRMReq = (PAIRONET_RM_REQUEST_FRAME) &Elem->Msg[LENGTH_802_11]; - pData = (PUCHAR) &Elem->Msg[LENGTH_802_11]; - - // 1. Change endian format form network to little endian - Length = be2cpu16(pRMReq->IAPP.Length); - - // 2.0 Sanity check, this should only happen when CCX 2.0 support is enabled - if (pAd->StaCfg.CCXEnable != TRUE) - return; - - // 2.1 Radio measurement must be on - if (pAd->StaCfg.CCXControl.field.RMEnable != 1) - return; - - // 2.2. Debug print all bit information - DBGPRINT(RT_DEBUG_TRACE, ("IAPP ID & Length %d\n", Length)); - DBGPRINT(RT_DEBUG_TRACE, ("IAPP Type %x\n", pRMReq->IAPP.Type)); - DBGPRINT(RT_DEBUG_TRACE, ("IAPP SubType %x\n", pRMReq->IAPP.SubType)); - DBGPRINT(RT_DEBUG_TRACE, ("IAPP Dialog Token %x\n", pRMReq->IAPP.Token)); - DBGPRINT(RT_DEBUG_TRACE, ("IAPP Activation Delay %x\n", pRMReq->Delay)); - DBGPRINT(RT_DEBUG_TRACE, ("IAPP Measurement Offset %x\n", pRMReq->Offset)); - - // 3. Check IAPP frame type, it must be 0x32 for Cisco Aironet extension - if (pRMReq->IAPP.Type != AIRONET_IAPP_TYPE) - { - DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP type for Cisco Aironet extension\n")); - return; - } - - // 4. Check IAPP frame subtype, it must be 0x01 for Cisco Aironet extension request. - // Since we are acting as client only, we will disregards reply subtype. - if (pRMReq->IAPP.SubType != AIRONET_IAPP_SUBTYPE_REQUEST) - { - DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP subtype for Cisco Aironet extension\n")); - return; - } - - // 5. Verify Destination MAC and Source MAC, both should be all zeros. - if (! MAC_ADDR_EQUAL(pRMReq->IAPP.DA, ZERO_MAC_ADDR)) - { - DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP DA for Cisco Aironet extension, it's not Zero\n")); - return; - } - - if (! MAC_ADDR_EQUAL(pRMReq->IAPP.SA, ZERO_MAC_ADDR)) - { - DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP SA for Cisco Aironet extension, it's not Zero\n")); - return; - } - - // 6. Reinit all report related fields - NdisZeroMemory(pAd->StaCfg.FrameReportBuf, 2048); - NdisZeroMemory(pAd->StaCfg.BssReportOffset, sizeof(USHORT) * MAX_LEN_OF_BSS_TABLE); - NdisZeroMemory(pAd->StaCfg.MeasurementRequest, sizeof(RM_REQUEST_ACTION) * 4); - - // 7. Point to the start of first element report element - pAd->StaCfg.FrameReportLen = LENGTH_802_11 + sizeof(AIRONET_IAPP_HEADER); - DBGPRINT(RT_DEBUG_TRACE, ("FR len = %d\n", pAd->StaCfg.FrameReportLen)); - pAd->StaCfg.LastBssIndex = 0xff; - pAd->StaCfg.RMReqCnt = 0; - pAd->StaCfg.ParallelReq = FALSE; - pAd->StaCfg.ParallelDuration = 0; - pAd->StaCfg.ParallelChannel = 0; - pAd->StaCfg.IAPPToken = pRMReq->IAPP.Token; - pAd->StaCfg.CurrentRMReqIdx = 0; - pAd->StaCfg.CLBusyBytes = 0; - // Reset the statistics - for (i = 0; i < 8; i++) - pAd->StaCfg.RPIDensity[i] = 0; - - Index = 0; - - // 8. Save dialog token for report - pAd->StaCfg.IAPPToken = pRMReq->IAPP.Token; - - // Save Activation delay & measurement offset, Not really needed - - // 9. Point to the first request element - pData += sizeof(AIRONET_RM_REQUEST_FRAME); - // Length should exclude the CISCO Aironet SNAP header - Length -= (sizeof(AIRONET_RM_REQUEST_FRAME) - LENGTH_802_1_H); - - // 10. Start Parsing the Measurement elements. - // Be careful about multiple MR elements within one frames. - while (Length > 0) - { - pReqElem = (PRM_REQUEST_ACTION) pData; - switch (pReqElem->ReqElem.Eid) - { - case IE_MEASUREMENT_REQUEST: - // From the example, it seems we only need to support one request in one frame - // There is no multiple request in one frame. - // Besides, looks like we need to take care the measurement request only. - // The measurement request is always 4 bytes. - - // Start parsing this type of request. - // 0. Eid is IE_MEASUREMENT_REQUEST - // 1. Length didn't include Eid and Length field, it always be 8. - // 2. Measurement Token, we nned to save it for the corresponding report. - // 3. Measurement Mode, Although there are definitions, but we din't see value other than - // 0 from test specs examples. - // 4. Measurement Type, this is what we need to do. - switch (pReqElem->ReqElem.Type) - { - case MSRN_TYPE_CHANNEL_LOAD_REQ: - case MSRN_TYPE_NOISE_HIST_REQ: - case MSRN_TYPE_BEACON_REQ: - // Check the Enable non-serving channel measurement control - if (pAd->StaCfg.CCXControl.field.DCRMEnable == 0) - { - // Check channel before enqueue the action - if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel) - break; - } - else - { - // If off channel measurement, check the TU duration limit - if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel) - if (pReqElem->Measurement.Duration > pAd->StaCfg.CCXControl.field.TuLimit) - break; - } - - // Save requests and execute actions later - NdisMoveMemory(&pAd->StaCfg.MeasurementRequest[Index], pReqElem, sizeof(RM_REQUEST_ACTION)); - Index += 1; - break; - - case MSRN_TYPE_FRAME_REQ: - // Since it's option, we will support later - // FrameRequestAction(pAd, pData); - break; - - default: - break; - } - - // Point to next Measurement request - pData += sizeof(RM_REQUEST_ACTION); - Length -= sizeof(RM_REQUEST_ACTION); - break; - - // We accept request only, all others are dropped - case IE_MEASUREMENT_REPORT: - case IE_AP_TX_POWER: - case IE_MEASUREMENT_CAPABILITY: - default: - return; - } - } - - // 11. Update some flags and index - pAd->StaCfg.RMReqCnt = Index; - - if (Index) - { - MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL); - RT28XX_MLME_HANDLER(pAd); - } - - DBGPRINT(RT_DEBUG_TRACE, ("<----- AironetMsgAction\n")); -} - -/* - ======================================================================== - - Routine Description: - - Arguments: - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID AironetRequestAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - PRM_REQUEST_ACTION pReq; - - // 1. Point to next request element - pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; - - // 2. Parse measurement type and call appropriate functions - if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ) - // Channel Load measurement request - ChannelLoadRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx); - else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ) - // Noise Histogram measurement request - NoiseHistRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx); - else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ) - // Beacon measurement request - BeaconRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx); - else - // Unknown. Do nothing and return, this should never happen - return; - - // 3. Peek into the next request, if it's parallel, we will update the scan time to the largest one - if ((pAd->StaCfg.CurrentRMReqIdx + 1) < pAd->StaCfg.RMReqCnt) - { - pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx + 1]; - // Check for parallel bit - if ((pReq->ReqElem.Mode & 0x01) && (pReq->Measurement.Channel == pAd->StaCfg.CCXScanChannel)) - { - // Update parallel mode request information - pAd->StaCfg.ParallelReq = TRUE; - pAd->StaCfg.CCXScanTime = ((pReq->Measurement.Duration > pAd->StaCfg.CCXScanTime) ? - (pReq->Measurement.Duration) : (pAd->StaCfg.CCXScanTime)); - } - } - - // 4. Call RT28XX_MLME_HANDLER to execute the request mlme commands, Scan request is the only one used - RT28XX_MLME_HANDLER(pAd); - -} - - -/* - ======================================================================== - - Routine Description: - Prepare channel load report action, special scan operation added - to support - - Arguments: - pAd Pointer to our adapter - pData Start from element ID - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID ChannelLoadRequestAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Index) -{ - PRM_REQUEST_ACTION pReq; - MLME_SCAN_REQ_STRUCT ScanReq; - UCHAR ZeroSsid[32]; - NDIS_STATUS NStatus; - PUCHAR pOutBuffer = NULL; - PHEADER_802_11 pNullFrame; - - DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction ----->\n")); - - pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index]; - NdisZeroMemory(ZeroSsid, 32); - - // Prepare for special scan request - // The scan definition is different with our Active, Passive scan definition. - // For CCX2, Active means send out probe request with broadcast BSSID. - // Passive means no probe request sent, only listen to the beacons. - // The channel scanned is fixed as specified, no need to scan all channels. - // The scan wait time is specified in the request too. - // Passive scan Mode - - // Control state machine is not idle, reject the request - if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0)) - return; - - // Fill out stuff for scan request - ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_CHANNEL_LOAD); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; - - // Reset some internal control flags to make sure this scan works. - BssTableInit(&pAd->StaCfg.CCXBssTab); - pAd->StaCfg.ScanCnt = 0; - pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; - pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; - - DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel)); - - // If it's non serving channel scan, send out a null frame with PSM bit on. - if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) - { - // Use MLME enqueue method - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - return; - - pNullFrame = (PHEADER_802_11) pOutBuffer;; - // Make the power save Null frame with PSM bit on - MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); - pNullFrame->Duration = 0; - pNullFrame->FC.Type = BTYPE_DATA; - pNullFrame->FC.PwrMgmt = PWR_SAVE; - - // Send using priority queue - MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); - MlmeFreeMemory(pAd, pOutBuffer); - DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); - RTMPusecDelay(5000); - } - - pAd->StaCfg.CCXReqType = MSRN_TYPE_CHANNEL_LOAD_REQ; - pAd->StaCfg.CLBusyBytes = 0; - // Enable Rx with promiscuous reception - RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010); - - // Set channel load measurement flag - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT); - - pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; - - DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction <-----\n")); -} - -/* - ======================================================================== - - Routine Description: - Prepare noise histogram report action, special scan operation added - to support - - Arguments: - pAd Pointer to our adapter - pData Start from element ID - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID NoiseHistRequestAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Index) -{ - PRM_REQUEST_ACTION pReq; - MLME_SCAN_REQ_STRUCT ScanReq; - UCHAR ZeroSsid[32], i; - NDIS_STATUS NStatus; - PUCHAR pOutBuffer = NULL; - PHEADER_802_11 pNullFrame; - - DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction ----->\n")); - - pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index]; - NdisZeroMemory(ZeroSsid, 32); - - // Prepare for special scan request - // The scan definition is different with our Active, Passive scan definition. - // For CCX2, Active means send out probe request with broadcast BSSID. - // Passive means no probe request sent, only listen to the beacons. - // The channel scanned is fixed as specified, no need to scan all channels. - // The scan wait time is specified in the request too. - // Passive scan Mode - - // Control state machine is not idle, reject the request - if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0)) - return; - - // Fill out stuff for scan request - ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_NOISE); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; - - // Reset some internal control flags to make sure this scan works. - BssTableInit(&pAd->StaCfg.CCXBssTab); - pAd->StaCfg.ScanCnt = 0; - pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; - pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; - pAd->StaCfg.CCXReqType = MSRN_TYPE_NOISE_HIST_REQ; - - DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel)); - - // If it's non serving channel scan, send out a null frame with PSM bit on. - if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) - { - // Use MLME enqueue method - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - return; - - pNullFrame = (PHEADER_802_11) pOutBuffer; - // Make the power save Null frame with PSM bit on - MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); - pNullFrame->Duration = 0; - pNullFrame->FC.Type = BTYPE_DATA; - pNullFrame->FC.PwrMgmt = PWR_SAVE; - - // Send using priority queue - MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); - MlmeFreeMemory(pAd, pOutBuffer); - DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); - RTMPusecDelay(5000); - } - - // Reset the statistics - for (i = 0; i < 8; i++) - pAd->StaCfg.RPIDensity[i] = 0; - - // Enable Rx with promiscuous reception - RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010); - - // Set channel load measurement flag - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT); - - pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; - - DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction <-----\n")); -} - -/* - ======================================================================== - - Routine Description: - Prepare Beacon report action, special scan operation added - to support - - Arguments: - pAd Pointer to our adapter - pData Start from element ID - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID BeaconRequestAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Index) -{ - PRM_REQUEST_ACTION pReq; - NDIS_STATUS NStatus; - PUCHAR pOutBuffer = NULL; - PHEADER_802_11 pNullFrame; - MLME_SCAN_REQ_STRUCT ScanReq; - UCHAR ZeroSsid[32]; - - DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction ----->\n")); - - pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index]; - NdisZeroMemory(ZeroSsid, 32); - - // Prepare for special scan request - // The scan definition is different with our Active, Passive scan definition. - // For CCX2, Active means send out probe request with broadcast BSSID. - // Passive means no probe request sent, only listen to the beacons. - // The channel scanned is fixed as specified, no need to scan all channels. - // The scan wait time is specified in the request too. - if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_PASSIVE) - { - // Passive scan Mode - DBGPRINT(RT_DEBUG_TRACE, ("Passive Scan Mode!\n")); - - // Control state machine is not idle, reject the request - if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0)) - return; - - // Fill out stuff for scan request - ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_PASSIVE); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; - - // Reset some internal control flags to make sure this scan works. - BssTableInit(&pAd->StaCfg.CCXBssTab); - pAd->StaCfg.ScanCnt = 0; - pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; - pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; - pAd->StaCfg.CCXReqType = MSRN_TYPE_BEACON_REQ; - DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration)); - - // If it's non serving channel scan, send out a null frame with PSM bit on. - if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) - { - // Use MLME enqueue method - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - return; - - pNullFrame = (PHEADER_802_11) pOutBuffer; - // Make the power save Null frame with PSM bit on - MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); - pNullFrame->Duration = 0; - pNullFrame->FC.Type = BTYPE_DATA; - pNullFrame->FC.PwrMgmt = PWR_SAVE; - - // Send using priority queue - MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); - MlmeFreeMemory(pAd, pOutBuffer); - DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); - RTMPusecDelay(5000); - } - - pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; - } - else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_ACTIVE) - { - // Active scan Mode - DBGPRINT(RT_DEBUG_TRACE, ("Active Scan Mode!\n")); - - // Control state machine is not idle, reject the request - if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) - return; - - // Fill out stuff for scan request - ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_ACTIVE); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; - - // Reset some internal control flags to make sure this scan works. - BssTableInit(&pAd->StaCfg.CCXBssTab); - pAd->StaCfg.ScanCnt = 0; - pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; - pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; - pAd->StaCfg.CCXReqType = MSRN_TYPE_BEACON_REQ; - DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration)); - - // If it's non serving channel scan, send out a null frame with PSM bit on. - if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) - { - // Use MLME enqueue method - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - return; - - pNullFrame = (PHEADER_802_11) pOutBuffer; - // Make the power save Null frame with PSM bit on - MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); - pNullFrame->Duration = 0; - pNullFrame->FC.Type = BTYPE_DATA; - pNullFrame->FC.PwrMgmt = PWR_SAVE; - - // Send using priority queue - MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); - MlmeFreeMemory(pAd, pOutBuffer); - DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); - RTMPusecDelay(5000); - } - - pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; - } - else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_BEACON_TABLE) - { - // Beacon report Mode, report all the APS in current bss table - DBGPRINT(RT_DEBUG_TRACE, ("Beacon Report Mode!\n")); - - // Copy current BSS table to CCX table, we can omit this step later on. - NdisMoveMemory(&pAd->StaCfg.CCXBssTab, &pAd->ScanTab, sizeof(BSS_TABLE)); - - // Create beacon report from Bss table - AironetCreateBeaconReportFromBssTable(pAd); - - // Set state to scanning - pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; - - // Enqueue report request - // Cisco scan request is finished, prepare beacon report - MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL); - } - else - { - // Wrong scan Mode - DBGPRINT(RT_DEBUG_TRACE, ("Wrong Scan Mode!\n")); - } - - DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction <-----\n")); -} - -/* - ======================================================================== - - Routine Description: - - Arguments: - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID AironetReportAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - PRM_REQUEST_ACTION pReq; - ULONG Now32; - - NdisGetSystemUpTime(&Now32); - pAd->StaCfg.LastBeaconRxTime = Now32; - - pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; - - DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction ----->\n")); - - // 1. Parse measurement type and call appropriate functions - if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ) - // Channel Load measurement request - ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); - else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ) - // Noise Histogram measurement request - NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); - else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ) - // Beacon measurement request - BeaconReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); - else - // Unknown. Do nothing and return - ; - - // 2. Point to the correct index of action element, start from 0 - pAd->StaCfg.CurrentRMReqIdx++; - - // 3. Check for parallel actions - if (pAd->StaCfg.ParallelReq == TRUE) - { - pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; - - // Process next action right away - if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ) - // Channel Load measurement request - ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); - else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ) - // Noise Histogram measurement request - NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); - - pAd->StaCfg.ParallelReq = FALSE; - pAd->StaCfg.CurrentRMReqIdx++; - } - - if (pAd->StaCfg.CurrentRMReqIdx >= pAd->StaCfg.RMReqCnt) - { - // 4. There is no more unprocessed measurement request, go for transmit this report - AironetFinalReportAction(pAd); - pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE; - } - else - { - pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; - - if (pReq->Measurement.Channel != pAd->CommonCfg.Channel) - { - RTMPusecDelay(100000); - } - - // 5. There are more requests to be measure - MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL); - RT28XX_MLME_HANDLER(pAd); - } - - DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction <-----\n")); -} - -/* - ======================================================================== - - Routine Description: - - Arguments: - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID AironetFinalReportAction( - IN PRTMP_ADAPTER pAd) -{ - PUCHAR pDest; - PAIRONET_IAPP_HEADER pIAPP; - PHEADER_802_11 pHeader; - UCHAR AckRate = RATE_2; - USHORT AckDuration = 0; - NDIS_STATUS NStatus; - PUCHAR pOutBuffer = NULL; - ULONG FrameLen = 0; - - DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction ----->\n")); - - // 0. Set up the frame pointer, Frame was inited at the end of message action - pDest = &pAd->StaCfg.FrameReportBuf[LENGTH_802_11]; - - // 1. Update report IAPP fields - pIAPP = (PAIRONET_IAPP_HEADER) pDest; - - // 2. Copy Cisco SNAP header - NdisMoveMemory(pIAPP->CiscoSnapHeader, SNAP_AIRONET, LENGTH_802_1_H); - - // 3. network order for this 16bit length - pIAPP->Length = cpu2be16(pAd->StaCfg.FrameReportLen - LENGTH_802_11 - LENGTH_802_1_H); - - // 3.1 sanity check the report length, ignore it if there is nothing to report - if (be2cpu16(pIAPP->Length) <= 18) - return; - - // 4. Type must be 0x32 - pIAPP->Type = AIRONET_IAPP_TYPE; - - // 5. SubType for report must be 0x81 - pIAPP->SubType = AIRONET_IAPP_SUBTYPE_REPORT; - - // 6. DA is not used and must be zero, although the whole frame was cleared at the start of function - // We will do it again here. We can use BSSID instead - COPY_MAC_ADDR(pIAPP->DA, pAd->CommonCfg.Bssid); - - // 7. SA is the client reporting which must be our MAC - COPY_MAC_ADDR(pIAPP->SA, pAd->CurrentAddress); - - // 8. Copy the saved dialog token - pIAPP->Token = pAd->StaCfg.IAPPToken; - - // 9. Make the Report frame 802.11 header - // Reuse function in wpa.c - pHeader = (PHEADER_802_11) pAd->StaCfg.FrameReportBuf; - pAd->Sequence ++; - WpaMacHeaderInit(pAd, pHeader, 0, pAd->CommonCfg.Bssid); - - // ACK size is 14 include CRC, and its rate is based on real time information - AckRate = pAd->CommonCfg.ExpectedACKRate[pAd->CommonCfg.MlmeRate]; - AckDuration = RTMPCalcDuration(pAd, AckRate, 14); - pHeader->Duration = pAd->CommonCfg.Dsifs + AckDuration; - - // Use MLME enqueue method - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - return; - - // 10. Prepare report frame with dynamic outbuffer. Just simply copy everything. - MakeOutgoingFrame(pOutBuffer, &FrameLen, - pAd->StaCfg.FrameReportLen, pAd->StaCfg.FrameReportBuf, - END_OF_ARGS); - - // 11. Send using priority queue - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - pAd->StaCfg.CCXReqType = MSRN_TYPE_UNUSED; - - DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction <-----\n")); -} - -/* - ======================================================================== - - Routine Description: - - Arguments: - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID ChannelLoadReportAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Index) -{ - PMEASUREMENT_REPORT_ELEMENT pReport; - PCHANNEL_LOAD_REPORT pLoad; - PUCHAR pDest; - UCHAR CCABusyFraction; - - DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction ----->\n")); - - // Disable Rx with promiscuous reception, make it back to normal - RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification. - - // 0. Setup pointer for processing beacon & probe response - pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen]; - pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest; - - // 1. Fill Measurement report element field. - pReport->Eid = IE_MEASUREMENT_REPORT; - // Fixed Length at 9, not include Eid and length fields - pReport->Length = 9; - pReport->Token = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token; - pReport->Mode = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode; - pReport->Type = MSRN_TYPE_CHANNEL_LOAD_REQ; - - // 2. Fill channel report measurement data - pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); - pLoad = (PCHANNEL_LOAD_REPORT) pDest; - pLoad->Channel = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel; - pLoad->Spare = 0; - pLoad->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration; - - // 3. Calculate the CCA Busy Fraction - // (Bytes + ACK size) * 8 / Tx speed * 255 / 1000 / measurement duration, use 24 us Tx speed - // = (Bytes + ACK) / 12 / duration - // 9 is the good value for pAd->StaCfg.CLFactor - // CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 9 / pLoad->Duration); - CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / pAd->StaCfg.CLFactor / pLoad->Duration); - if (CCABusyFraction < 10) - CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 3 / pLoad->Duration) + 1; - - pLoad->CCABusy = CCABusyFraction; - DBGPRINT(RT_DEBUG_TRACE, ("CLBusyByte %ld, Duration %d, Result, %d\n", pAd->StaCfg.CLBusyBytes, pLoad->Duration, CCABusyFraction)); - - DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen %d\n", pAd->StaCfg.FrameReportLen)); - pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(CHANNEL_LOAD_REPORT)); - DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen %d\n", pAd->StaCfg.FrameReportLen)); - - // 4. Clear channel load measurement flag - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT); - - // 5. reset to idle state - pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE; - - DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction <-----\n")); -} - -/* - ======================================================================== - - Routine Description: - - Arguments: - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID NoiseHistReportAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Index) -{ - PMEASUREMENT_REPORT_ELEMENT pReport; - PNOISE_HIST_REPORT pNoise; - PUCHAR pDest; - UCHAR i,NoiseCnt; - USHORT TotalRPICnt, TotalRPISum; - - DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction ----->\n")); - - // 0. Disable Rx with promiscuous reception, make it back to normal - RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification. - // 1. Setup pointer for processing beacon & probe response - pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen]; - pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest; - - // 2. Fill Measurement report element field. - pReport->Eid = IE_MEASUREMENT_REPORT; - // Fixed Length at 16, not include Eid and length fields - pReport->Length = 16; - pReport->Token = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token; - pReport->Mode = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode; - pReport->Type = MSRN_TYPE_NOISE_HIST_REQ; - - // 3. Fill noise histogram report measurement data - pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); - pNoise = (PNOISE_HIST_REPORT) pDest; - pNoise->Channel = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel; - pNoise->Spare = 0; - pNoise->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration; - // 4. Fill Noise histogram, the total RPI counts should be 0.4 * TU - // We estimate 4000 normal packets received durning 10 seconds test. - // Adjust it if required. - // 3 is a good value for pAd->StaCfg.NHFactor - // TotalRPICnt = pNoise->Duration * 3 / 10; - TotalRPICnt = pNoise->Duration * pAd->StaCfg.NHFactor / 10; - TotalRPISum = 0; - - for (i = 0; i < 8; i++) - { - TotalRPISum += pAd->StaCfg.RPIDensity[i]; - DBGPRINT(RT_DEBUG_TRACE, ("RPI %d Conuts %d\n", i, pAd->StaCfg.RPIDensity[i])); - } - - // Double check if the counter is larger than our expectation. - // We will replace it with the total number plus a fraction. - if (TotalRPISum > TotalRPICnt) - TotalRPICnt = TotalRPISum + pNoise->Duration / 20; - - DBGPRINT(RT_DEBUG_TRACE, ("Total RPI Conuts %d\n", TotalRPICnt)); - - // 5. Initialize noise count for the total summation of 0xff - NoiseCnt = 0; - for (i = 1; i < 8; i++) - { - pNoise->Density[i] = (UCHAR) (pAd->StaCfg.RPIDensity[i] * 255 / TotalRPICnt); - if ((pNoise->Density[i] == 0) && (pAd->StaCfg.RPIDensity[i] != 0)) - pNoise->Density[i]++; - NoiseCnt += pNoise->Density[i]; - DBGPRINT(RT_DEBUG_TRACE, ("Reported RPI[%d] = 0x%02x\n", i, pNoise->Density[i])); - } - - // 6. RPI[0] represents the rest of counts - pNoise->Density[0] = 0xff - NoiseCnt; - DBGPRINT(RT_DEBUG_TRACE, ("Reported RPI[0] = 0x%02x\n", pNoise->Density[0])); - - pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(NOISE_HIST_REPORT)); - - // 7. Clear channel load measurement flag - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT); - - // 8. reset to idle state - pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE; - - DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction <-----\n")); -} - -/* - ======================================================================== - - Routine Description: - Prepare Beacon report action, - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID BeaconReportAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Index) -{ - DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction ----->\n")); - - // Looks like we don't have anything thing need to do here. - // All measurement report already finished in AddBeaconReport - // The length is in the FrameReportLen - - // reset Beacon index for next beacon request - pAd->StaCfg.LastBssIndex = 0xff; - - // reset to idle state - pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE; - - DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction <-----\n")); -} - -/* - ======================================================================== - - Routine Description: - - Arguments: - Index Current BSSID in CCXBsstab entry index - - Return Value: - - Note: - - ======================================================================== -*/ -VOID AironetAddBeaconReport( - IN PRTMP_ADAPTER pAd, - IN ULONG Index, - IN PMLME_QUEUE_ELEM pElem) -{ - PVOID pMsg; - PUCHAR pSrc, pDest; - UCHAR ReqIdx; - ULONG MsgLen; - USHORT Length; - PFRAME_802_11 pFrame; - PMEASUREMENT_REPORT_ELEMENT pReport; - PEID_STRUCT pEid; - PBEACON_REPORT pBeaconReport; - PBSS_ENTRY pBss; - - // 0. Setup pointer for processing beacon & probe response - pMsg = pElem->Msg; - MsgLen = pElem->MsgLen; - pFrame = (PFRAME_802_11) pMsg; - pSrc = pFrame->Octet; // Start from AP TSF - pBss = (PBSS_ENTRY) &pAd->StaCfg.CCXBssTab.BssEntry[Index]; - ReqIdx = pAd->StaCfg.CurrentRMReqIdx; - - // 1 Check the Index, if we already create this entry, only update the average RSSI - if ((Index <= pAd->StaCfg.LastBssIndex) && (pAd->StaCfg.LastBssIndex != 0xff)) - { - pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.BssReportOffset[Index]]; - // Point to bss report information - pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); - pBeaconReport = (PBEACON_REPORT) pDest; - - // Update Rx power, in dBm - // Get the original RSSI readback from BBP - pBeaconReport->RxPower += pAd->BbpRssiToDbmDelta; - // Average the Rssi reading - pBeaconReport->RxPower = (pBeaconReport->RxPower + pBss->Rssi) / 2; - // Get to dBm format - pBeaconReport->RxPower -= pAd->BbpRssiToDbmDelta; - - DBGPRINT(RT_DEBUG_TRACE, ("Bssid %02x:%02x:%02x:%02x:%02x:%02x ", - pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], - pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); - DBGPRINT(RT_DEBUG_TRACE, ("RxPower[%ld] Rssi %d, Avg Rssi %d\n", Index, (pBss->Rssi - pAd->BbpRssiToDbmDelta), pBeaconReport->RxPower - 256)); - DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen = %d\n", pAd->StaCfg.BssReportOffset[Index])); - - // Update other information here - - // Done - return; - } - - // 2. Update reported Index - pAd->StaCfg.LastBssIndex = Index; - - // 3. Setup the buffer address for copying this BSSID into reporting frame - // The offset should start after 802.11 header and report frame header. - pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen]; - - // 4. Save the start offset of each Bss in report frame - pAd->StaCfg.BssReportOffset[Index] = pAd->StaCfg.FrameReportLen; - - // 5. Fill Measurement report fields - pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest; - pReport->Eid = IE_MEASUREMENT_REPORT; - pReport->Length = 0; - pReport->Token = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Token; - pReport->Mode = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Mode; - pReport->Type = MSRN_TYPE_BEACON_REQ; - Length = sizeof(MEASUREMENT_REPORT_ELEMENT); - pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); - - // 6. Start thebeacon report format - pBeaconReport = (PBEACON_REPORT) pDest; - pDest += sizeof(BEACON_REPORT); - Length += sizeof(BEACON_REPORT); - - // 7. Copy Channel number - pBeaconReport->Channel = pBss->Channel; - pBeaconReport->Spare = 0; - pBeaconReport->Duration = pAd->StaCfg.MeasurementRequest[ReqIdx].Measurement.Duration; - pBeaconReport->PhyType = ((pBss->SupRateLen+pBss->ExtRateLen > 4) ? PHY_ERP : PHY_DSS); - // 8. Rx power, in dBm - pBeaconReport->RxPower = pBss->Rssi - pAd->BbpRssiToDbmDelta; - - DBGPRINT(RT_DEBUG_TRACE, ("Bssid %02x:%02x:%02x:%02x:%02x:%02x ", - pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], - pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); - DBGPRINT(RT_DEBUG_TRACE, ("RxPower[%ld], Rssi %d\n", Index, pBeaconReport->RxPower - 256)); - DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen = %d\n", pAd->StaCfg.FrameReportLen)); - - pBeaconReport->BeaconInterval = pBss->BeaconPeriod; - COPY_MAC_ADDR(pBeaconReport->BSSID, pFrame->Hdr.Addr3); - NdisMoveMemory(pBeaconReport->ParentTSF, pSrc, 4); - NdisMoveMemory(pBeaconReport->TargetTSF, &pElem->TimeStamp.u.LowPart, 4); - NdisMoveMemory(&pBeaconReport->TargetTSF[4], &pElem->TimeStamp.u.HighPart, 4); - - // 9. Skip the beacon frame and offset to start of capabilityinfo since we already processed capabilityinfo - pSrc += (TIMESTAMP_LEN + 2); - pBeaconReport->CapabilityInfo = *(USHORT *)pSrc; - - // 10. Point to start of element ID - pSrc += 2; - pEid = (PEID_STRUCT) pSrc; - - // 11. Start process all variable Eid oayload and add the appropriate to the frame report - while (((PUCHAR) pEid + pEid->Len + 1) < ((PUCHAR) pFrame + MsgLen)) - { - // Only limited EID are required to report for CCX 2. It includes SSID, Supported rate, - // FH paramenter set, DS parameter set, CF parameter set, IBSS parameter set, - // TIM (report first 4 bytes only, radio measurement capability - switch (pEid->Eid) - { - case IE_SSID: - case IE_SUPP_RATES: - case IE_FH_PARM: - case IE_DS_PARM: - case IE_CF_PARM: - case IE_IBSS_PARM: - NdisMoveMemory(pDest, pEid, pEid->Len + 2); - pDest += (pEid->Len + 2); - Length += (pEid->Len + 2); - break; - - case IE_MEASUREMENT_CAPABILITY: - // Since this IE is duplicated with WPA security IE, we has to do sanity check before - // recognize it. - // 1. It also has fixed 6 bytes IE length. - if (pEid->Len != 6) - break; - // 2. Check the Cisco Aironet OUI - if (NdisEqualMemory(CISCO_OUI, (pSrc + 2), 3)) - { - // Matched, this is what we want - NdisMoveMemory(pDest, pEid, pEid->Len + 2); - pDest += (pEid->Len + 2); - Length += (pEid->Len + 2); - } - break; - - case IE_TIM: - if (pEid->Len > 4) - { - // May truncate and report the first 4 bytes only, with the eid & len, total should be 6 - NdisMoveMemory(pDest, pEid, 6); - pDest += 6; - Length += 6; - } - else - { - NdisMoveMemory(pDest, pEid, pEid->Len + 2); - pDest += (pEid->Len + 2); - Length += (pEid->Len + 2); - } - break; - - default: - break; - } - // 12. Move to next element ID - pSrc += (2 + pEid->Len); - pEid = (PEID_STRUCT) pSrc; - } - - // 13. Update the length in the header, not include EID and length - pReport->Length = Length - 4; - - // 14. Update the frame report buffer data length - pAd->StaCfg.FrameReportLen += Length; - DBGPRINT(RT_DEBUG_TRACE, ("FR len = %d\n", pAd->StaCfg.FrameReportLen)); -} - -/* - ======================================================================== - - Routine Description: - - Arguments: - Index Current BSSID in CCXBsstab entry index - - Return Value: - - Note: - - ======================================================================== -*/ -VOID AironetCreateBeaconReportFromBssTable( - IN PRTMP_ADAPTER pAd) -{ - PMEASUREMENT_REPORT_ELEMENT pReport; - PBEACON_REPORT pBeaconReport; - UCHAR Index, ReqIdx; - USHORT Length; - PUCHAR pDest; - PBSS_ENTRY pBss; - - // 0. setup base pointer - ReqIdx = pAd->StaCfg.CurrentRMReqIdx; - - for (Index = 0; Index < pAd->StaCfg.CCXBssTab.BssNr; Index++) - { - // 1. Setup the buffer address for copying this BSSID into reporting frame - // The offset should start after 802.11 header and report frame header. - pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen]; - pBss = (PBSS_ENTRY) &pAd->StaCfg.CCXBssTab.BssEntry[Index]; - Length = 0; - - // 2. Fill Measurement report fields - pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest; - pReport->Eid = IE_MEASUREMENT_REPORT; - pReport->Length = 0; - pReport->Token = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Token; - pReport->Mode = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Mode; - pReport->Type = MSRN_TYPE_BEACON_REQ; - Length = sizeof(MEASUREMENT_REPORT_ELEMENT); - pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); - - // 3. Start the beacon report format - pBeaconReport = (PBEACON_REPORT) pDest; - pDest += sizeof(BEACON_REPORT); - Length += sizeof(BEACON_REPORT); - - // 4. Copy Channel number - pBeaconReport->Channel = pBss->Channel; - pBeaconReport->Spare = 0; - pBeaconReport->Duration = pAd->StaCfg.MeasurementRequest[ReqIdx].Measurement.Duration; - pBeaconReport->PhyType = ((pBss->SupRateLen+pBss->ExtRateLen > 4) ? PHY_ERP : PHY_DSS); - pBeaconReport->RxPower = pBss->Rssi - pAd->BbpRssiToDbmDelta; - pBeaconReport->BeaconInterval = pBss->BeaconPeriod; - pBeaconReport->CapabilityInfo = pBss->CapabilityInfo; - COPY_MAC_ADDR(pBeaconReport->BSSID, pBss->Bssid); - NdisMoveMemory(pBeaconReport->ParentTSF, pBss->PTSF, 4); - NdisMoveMemory(pBeaconReport->TargetTSF, pBss->TTSF, 8); - - // 5. Create SSID - *pDest++ = 0x00; - *pDest++ = pBss->SsidLen; - NdisMoveMemory(pDest, pBss->Ssid, pBss->SsidLen); - pDest += pBss->SsidLen; - Length += (2 + pBss->SsidLen); - - // 6. Create SupportRates - *pDest++ = 0x01; - *pDest++ = pBss->SupRateLen; - NdisMoveMemory(pDest, pBss->SupRate, pBss->SupRateLen); - pDest += pBss->SupRateLen; - Length += (2 + pBss->SupRateLen); - - // 7. DS Parameter - *pDest++ = 0x03; - *pDest++ = 1; - *pDest++ = pBss->Channel; - Length += 3; - - // 8. IBSS parameter if presents - if (pBss->BssType == BSS_ADHOC) - { - *pDest++ = 0x06; - *pDest++ = 2; - *(PUSHORT) pDest = pBss->AtimWin; - pDest += 2; - Length += 4; - } - - // 9. Update length field, not include EID and length - pReport->Length = Length - 4; - - // 10. Update total frame size - pAd->StaCfg.FrameReportLen += Length; - } -} diff --git a/drivers/staging/rt2860/sta/assoc.c b/drivers/staging/rt2860/sta/assoc.c index 1a587153c75ea5055eed4cf55eb0811f9983c892..7055f229e511d9f93d8153da922d0ac7f6141f1d 100644 --- a/drivers/staging/rt2860/sta/assoc.c +++ b/drivers/staging/rt2860/sta/assoc.c @@ -36,31 +36,31 @@ */ #include "../rt_config.h" -UCHAR CipherWpaTemplate[] = { - 0xdd, // WPA IE - 0x16, // Length - 0x00, 0x50, 0xf2, 0x01, // oui - 0x01, 0x00, // Version - 0x00, 0x50, 0xf2, 0x02, // Multicast - 0x01, 0x00, // Number of unicast - 0x00, 0x50, 0xf2, 0x02, // unicast - 0x01, 0x00, // number of authentication method - 0x00, 0x50, 0xf2, 0x01 // authentication - }; - -UCHAR CipherWpa2Template[] = { - 0x30, // RSN IE - 0x14, // Length - 0x01, 0x00, // Version - 0x00, 0x0f, 0xac, 0x02, // group cipher, TKIP - 0x01, 0x00, // number of pairwise - 0x00, 0x0f, 0xac, 0x02, // unicast - 0x01, 0x00, // number of authentication method - 0x00, 0x0f, 0xac, 0x02, // authentication - 0x00, 0x00, // RSN capability - }; - -UCHAR Ccx2IeInfo[] = { 0x00, 0x40, 0x96, 0x03, 0x02}; +u8 CipherWpaTemplate[] = { + 0xdd, /* WPA IE */ + 0x16, /* Length */ + 0x00, 0x50, 0xf2, 0x01, /* oui */ + 0x01, 0x00, /* Version */ + 0x00, 0x50, 0xf2, 0x02, /* Multicast */ + 0x01, 0x00, /* Number of unicast */ + 0x00, 0x50, 0xf2, 0x02, /* unicast */ + 0x01, 0x00, /* number of authentication method */ + 0x00, 0x50, 0xf2, 0x01 /* authentication */ +}; + +u8 CipherWpa2Template[] = { + 0x30, /* RSN IE */ + 0x14, /* Length */ + 0x01, 0x00, /* Version */ + 0x00, 0x0f, 0xac, 0x02, /* group cipher, TKIP */ + 0x01, 0x00, /* number of pairwise */ + 0x00, 0x0f, 0xac, 0x02, /* unicast */ + 0x01, 0x00, /* number of authentication method */ + 0x00, 0x0f, 0xac, 0x02, /* authentication */ + 0x00, 0x00, /* RSN capability */ +}; + +u8 Ccx2IeInfo[] = { 0x00, 0x40, 0x96, 0x03, 0x02 }; /* ========================================================================== @@ -73,55 +73,84 @@ UCHAR Ccx2IeInfo[] = { 0x00, 0x40, 0x96, 0x03, 0x02}; ========================================================================== */ -VOID AssocStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]) +void AssocStateMachineInit(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *S, OUT STATE_MACHINE_FUNC Trans[]) { - StateMachineInit(S, Trans, MAX_ASSOC_STATE, MAX_ASSOC_MSG, (STATE_MACHINE_FUNC)Drop, ASSOC_IDLE, ASSOC_MACHINE_BASE); - - // first column - StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)MlmeAssocReqAction); - StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)MlmeReassocReqAction); - StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)MlmeDisassocReqAction); - StateMachineSetAction(S, ASSOC_IDLE, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); - - // second column - StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc); - StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc); - StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate); - StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); - StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction); - // - // Patch 3Com AP MOde:3CRWE454G72 - // We send Assoc request frame to this AP, it always send Reassoc Rsp not Associate Rsp. - // - StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction); - StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_ASSOC_TIMEOUT, (STATE_MACHINE_FUNC)AssocTimeoutAction); - - // third column - StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc); - StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc); - StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate); - StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); - StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction); - // - // Patch, AP doesn't send Reassociate Rsp frame to Station. - // - StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction); - StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_REASSOC_TIMEOUT, (STATE_MACHINE_FUNC)ReassocTimeoutAction); - - // fourth column - StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc); - StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc); - StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate); - StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); - StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_DISASSOC_TIMEOUT, (STATE_MACHINE_FUNC)DisassocTimeoutAction); - - // initialize the timer - RTMPInitTimer(pAd, &pAd->MlmeAux.AssocTimer, GET_TIMER_FUNCTION(AssocTimeout), pAd, FALSE); - RTMPInitTimer(pAd, &pAd->MlmeAux.ReassocTimer, GET_TIMER_FUNCTION(ReassocTimeout), pAd, FALSE); - RTMPInitTimer(pAd, &pAd->MlmeAux.DisassocTimer, GET_TIMER_FUNCTION(DisassocTimeout), pAd, FALSE); + StateMachineInit(S, Trans, MAX_ASSOC_STATE, MAX_ASSOC_MSG, + (STATE_MACHINE_FUNC) Drop, ASSOC_IDLE, + ASSOC_MACHINE_BASE); + + /* first column */ + StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_ASSOC_REQ, + (STATE_MACHINE_FUNC) MlmeAssocReqAction); + StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_REASSOC_REQ, + (STATE_MACHINE_FUNC) MlmeReassocReqAction); + StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_DISASSOC_REQ, + (STATE_MACHINE_FUNC) MlmeDisassocReqAction); + StateMachineSetAction(S, ASSOC_IDLE, MT2_PEER_DISASSOC_REQ, + (STATE_MACHINE_FUNC) PeerDisassocAction); + + /* second column */ + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenAssoc); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenReassoc); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, + (STATE_MACHINE_FUNC) + InvalidStateWhenDisassociate); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, + (STATE_MACHINE_FUNC) PeerDisassocAction); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, + (STATE_MACHINE_FUNC) PeerAssocRspAction); + /* */ + /* Patch 3Com AP MOde:3CRWE454G72 */ + /* We send Assoc request frame to this AP, it always send Reassoc Rsp not Associate Rsp. */ + /* */ + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, + (STATE_MACHINE_FUNC) PeerAssocRspAction); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_ASSOC_TIMEOUT, + (STATE_MACHINE_FUNC) AssocTimeoutAction); + + /* third column */ + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenAssoc); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenReassoc); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, + (STATE_MACHINE_FUNC) + InvalidStateWhenDisassociate); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, + (STATE_MACHINE_FUNC) PeerDisassocAction); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, + (STATE_MACHINE_FUNC) PeerReassocRspAction); + /* */ + /* Patch, AP doesn't send Reassociate Rsp frame to Station. */ + /* */ + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, + (STATE_MACHINE_FUNC) PeerReassocRspAction); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_REASSOC_TIMEOUT, + (STATE_MACHINE_FUNC) ReassocTimeoutAction); + + /* fourth column */ + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenAssoc); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenReassoc); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, + (STATE_MACHINE_FUNC) + InvalidStateWhenDisassociate); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, + (STATE_MACHINE_FUNC) PeerDisassocAction); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_DISASSOC_TIMEOUT, + (STATE_MACHINE_FUNC) DisassocTimeoutAction); + + /* initialize the timer */ + RTMPInitTimer(pAd, &pAd->MlmeAux.AssocTimer, + GET_TIMER_FUNCTION(AssocTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MlmeAux.ReassocTimer, + GET_TIMER_FUNCTION(ReassocTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MlmeAux.DisassocTimer, + GET_TIMER_FUNCTION(DisassocTimeout), pAd, FALSE); } /* @@ -136,20 +165,20 @@ VOID AssocStateMachineInit( ========================================================================== */ -VOID AssocTimeout(IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) +void AssocTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) { - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) return; MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_ASSOC_TIMEOUT, 0, NULL); - RT28XX_MLME_HANDLER(pAd); + RTMP_MLME_HANDLER(pAd); } /* @@ -164,20 +193,20 @@ VOID AssocTimeout(IN PVOID SystemSpecific1, ========================================================================== */ -VOID ReassocTimeout(IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) +void ReassocTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) { - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) return; MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_REASSOC_TIMEOUT, 0, NULL); - RT28XX_MLME_HANDLER(pAd); + RTMP_MLME_HANDLER(pAd); } /* @@ -192,20 +221,20 @@ VOID ReassocTimeout(IN PVOID SystemSpecific1, ========================================================================== */ -VOID DisassocTimeout(IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) +void DisassocTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) { - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) return; MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_DISASSOC_TIMEOUT, 0, NULL); - RT28XX_MLME_HANDLER(pAd); + RTMP_MLME_HANDLER(pAd); } /* @@ -230,349 +259,315 @@ VOID DisassocTimeout(IN PVOID SystemSpecific1, ========================================================================== */ -VOID MlmeAssocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void MlmeAssocReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR ApAddr[6]; - HEADER_802_11 AssocHdr; - UCHAR Ccx2Len = 5; - UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; - USHORT ListenIntv; - ULONG Timeout; - USHORT CapabilityInfo; - BOOLEAN TimerCancelled; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - ULONG tmp; - USHORT VarIesOffset; - UCHAR CkipFlag; - UCHAR CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH]; - UCHAR AironetCkipIe = IE_AIRONET_CKIP; - UCHAR AironetCkipLen = CKIP_NEGOTIATION_LENGTH; - UCHAR AironetIPAddressIE = IE_AIRONET_IPADDRESS; - UCHAR AironetIPAddressLen = AIRONET_IPADDRESS_LENGTH; - UCHAR AironetIPAddressBuffer[AIRONET_IPADDRESS_LENGTH] = {0x00, 0x40, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}; - USHORT Status; - - // Block all authentication request durning WPA block period - if (pAd->StaCfg.bBlockAssoc == TRUE) - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block Assoc request durning WPA block period!\n")); + u8 ApAddr[6]; + struct rt_header_802_11 AssocHdr; + u8 WmeIe[9] = + { IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, + 0x00 }; + u16 ListenIntv; + unsigned long Timeout; + u16 CapabilityInfo; + BOOLEAN TimerCancelled; + u8 *pOutBuffer = NULL; + int NStatus; + unsigned long FrameLen = 0; + unsigned long tmp; + u16 VarIesOffset; + u16 Status; + + /* Block all authentication request durning WPA block period */ + if (pAd->StaCfg.bBlockAssoc == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - Block Assoc request durning WPA block period!\n")); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, + &Status); } - // check sanity first - else if (MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) - { + /* check sanity first */ + else if (MlmeAssocReqSanity + (pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, + &Timeout, &ListenIntv)) { RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled); COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr); - // Get an unused nonpaged memory + /* Get an unused nonpaged memory */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() allocate memory failed \n")); + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - MlmeAssocReqAction() allocate memory failed \n")); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_FAIL_NO_RESOURCE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, + MT2_ASSOC_CONF, 2, &Status); return; } - - // Add by James 03/06/27 - pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); - // Association don't need to report MAC address + /* Add by James 03/06/27 */ + pAd->StaCfg.AssocInfo.Length = + sizeof(struct rt_ndis_802_11_association_information); + /* Association don't need to report MAC address */ pAd->StaCfg.AssocInfo.AvailableRequestFixedIEs = - NDIS_802_11_AI_REQFI_CAPABILITIES | NDIS_802_11_AI_REQFI_LISTENINTERVAL; - pAd->StaCfg.AssocInfo.RequestFixedIEs.Capabilities = CapabilityInfo; - pAd->StaCfg.AssocInfo.RequestFixedIEs.ListenInterval = ListenIntv; - // Only reassociate need this - //COPY_MAC_ADDR(pAd->StaCfg.AssocInfo.RequestFixedIEs.CurrentAPAddress, ApAddr); - pAd->StaCfg.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); - - NdisZeroMemory(pAd->StaCfg.ReqVarIEs, MAX_VIE_LEN); - // First add SSID + NDIS_802_11_AI_REQFI_CAPABILITIES | + NDIS_802_11_AI_REQFI_LISTENINTERVAL; + pAd->StaCfg.AssocInfo.RequestFixedIEs.Capabilities = + CapabilityInfo; + pAd->StaCfg.AssocInfo.RequestFixedIEs.ListenInterval = + ListenIntv; + /* Only reassociate need this */ + /*COPY_MAC_ADDR(pAd->StaCfg.AssocInfo.RequestFixedIEs.CurrentAPAddress, ApAddr); */ + pAd->StaCfg.AssocInfo.OffsetRequestIEs = + sizeof(struct rt_ndis_802_11_association_information); + + NdisZeroMemory(pAd->StaCfg.ReqVarIEs, MAX_VIE_LEN); + /* First add SSID */ VarIesOffset = 0; - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SsidIe, 1); + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SsidIe, + 1); VarIesOffset += 1; - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SsidLen, 1); + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, + &pAd->MlmeAux.SsidLen, 1); VarIesOffset += 1; - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, + pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); VarIesOffset += pAd->MlmeAux.SsidLen; - // Second add Supported rates - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SupRateIe, 1); + /* Second add Supported rates */ + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SupRateIe, + 1); VarIesOffset += 1; - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SupRateLen, 1); + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, + &pAd->MlmeAux.SupRateLen, 1); VarIesOffset += 1; - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.SupRate, pAd->MlmeAux.SupRateLen); + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, + pAd->MlmeAux.SupRate, pAd->MlmeAux.SupRateLen); VarIesOffset += pAd->MlmeAux.SupRateLen; - // End Add by James + /* End Add by James */ - if ((pAd->CommonCfg.Channel > 14) && - (pAd->CommonCfg.bIEEE80211H == TRUE)) - CapabilityInfo |= 0x0100; + if ((pAd->CommonCfg.Channel > 14) && + (pAd->CommonCfg.bIEEE80211H == TRUE)) + CapabilityInfo |= 0x0100; DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send ASSOC request...\n")); - MgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, ApAddr); - - // Build basic frame first - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &AssocHdr, - 2, &CapabilityInfo, - 2, &ListenIntv, - 1, &SsidIe, - 1, &pAd->MlmeAux.SsidLen, - pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, - 1, &SupRateIe, - 1, &pAd->MlmeAux.SupRateLen, - pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, - END_OF_ARGS); - - if (pAd->MlmeAux.ExtRateLen != 0) - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &ExtRateIe, - 1, &pAd->MlmeAux.ExtRateLen, - pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, - END_OF_ARGS); + MgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, + ApAddr); + + /* Build basic frame first */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(struct rt_header_802_11), &AssocHdr, + 2, &CapabilityInfo, + 2, &ListenIntv, + 1, &SsidIe, + 1, &pAd->MlmeAux.SsidLen, + pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, + END_OF_ARGS); + + if (pAd->MlmeAux.ExtRateLen != 0) { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRate, END_OF_ARGS); FrameLen += tmp; } - - // HT - if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - ULONG TmpLen; - UCHAR HtLen; - UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; - if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE) - { + /* HT */ + if ((pAd->MlmeAux.HtCapabilityLen > 0) + && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) { + unsigned long TmpLen; + u8 HtLen; + u8 BROADCOM[4] = { 0x0, 0x90, 0x4c, 0x33 }; + if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE) { HtLen = SIZE_HT_CAP_IE + 4; - MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, - 1, &WpaIe, - 1, &HtLen, - 4, &BROADCOM[0], - pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, - END_OF_ARGS); - } - else - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, - 1, &HtCapIe, - 1, &pAd->MlmeAux.HtCapabilityLen, - pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, - END_OF_ARGS); + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 1, &WpaIe, 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, + &pAd->MlmeAux.HtCapability, + END_OF_ARGS); + } else { + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 1, &HtCapIe, 1, + &pAd->MlmeAux.HtCapabilityLen, + pAd->MlmeAux.HtCapabilityLen, + &pAd->MlmeAux.HtCapability, + END_OF_ARGS); } FrameLen += TmpLen; } - - // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION - // Case I: (Aggregation + Piggy-Back) - // 1. user enable aggregation, AND - // 2. Mac support piggy-back - // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON - // Case II: (Aggregation) - // 1. user enable aggregation, AND - // 2. AP annouces it's AGGREGATION-capable in BEACON - if (pAd->CommonCfg.bAggregationCapable) - { - if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)) - { - ULONG TmpLen; - UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00}; - MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, - 9, RalinkIe, - END_OF_ARGS); + /* add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION */ + /* Case I: (Aggregation + Piggy-Back) */ + /* 1. user enable aggregation, AND */ + /* 2. Mac support piggy-back */ + /* 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON */ + /* Case II: (Aggregation) */ + /* 1. user enable aggregation, AND */ + /* 2. AP annouces it's AGGREGATION-capable in BEACON */ + if (pAd->CommonCfg.bAggregationCapable) { + if ((pAd->CommonCfg.bPiggyBackCapable) + && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)) { + unsigned long TmpLen; + u8 RalinkIe[9] = + { IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, + 0x03, 0x00, 0x00, 0x00 }; + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 9, RalinkIe, + END_OF_ARGS); FrameLen += TmpLen; - } - else if (pAd->MlmeAux.APRalinkIe & 0x00000001) - { - ULONG TmpLen; - UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00}; - MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, - 9, RalinkIe, - END_OF_ARGS); + } else if (pAd->MlmeAux.APRalinkIe & 0x00000001) { + unsigned long TmpLen; + u8 RalinkIe[9] = + { IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, + 0x01, 0x00, 0x00, 0x00 }; + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 9, RalinkIe, + END_OF_ARGS); FrameLen += TmpLen; } - } - else - { - ULONG TmpLen; - UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06, 0x00, 0x00, 0x00}; - MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, - 9, RalinkIe, - END_OF_ARGS); + } else { + unsigned long TmpLen; + u8 RalinkIe[9] = + { IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06, + 0x00, 0x00, 0x00 }; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 9, + RalinkIe, END_OF_ARGS); FrameLen += TmpLen; } - if (pAd->MlmeAux.APEdcaParm.bValid) - { - if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable) - { - QBSS_STA_INFO_PARM QosInfo; + if (pAd->MlmeAux.APEdcaParm.bValid) { + if (pAd->CommonCfg.bAPSDCapable + && pAd->MlmeAux.APEdcaParm.bAPSDCapable) { + struct rt_qbss_sta_info_parm QosInfo; - NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); + NdisZeroMemory(&QosInfo, + sizeof(struct rt_qbss_sta_info_parm)); QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE; QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK; QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI; QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO; - QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength; - WmeIe[8] |= *(PUCHAR)&QosInfo; - } - else - { - // The Parameter Set Count is set to ¡§0¡¨ in the association request frames - // WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f); + QosInfo.MaxSPLength = + pAd->CommonCfg.MaxSPLength; + WmeIe[8] |= *(u8 *)& QosInfo; + } else { + /* The Parameter Set Count is set to ¡§0¡¨ in the association request frames */ + /* WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f); */ } - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 9, &WmeIe[0], - END_OF_ARGS); + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 9, &WmeIe[0], END_OF_ARGS); FrameLen += tmp; } - - // - // Let WPA(#221) Element ID on the end of this association frame. - // Otherwise some AP will fail on parsing Element ID and set status fail on Assoc Rsp. - // For example: Put Vendor Specific IE on the front of WPA IE. - // This happens on AP (Model No:Linksys WRK54G) - // + /* */ + /* Let WPA(#221) Element ID on the end of this association frame. */ + /* Otherwise some AP will fail on parsing Element ID and set status fail on Assoc Rsp. */ + /* For example: Put Vendor Specific IE on the front of WPA IE. */ + /* This happens on AP (Model No:Linksys WRK54G) */ + /* */ if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) - ) - ) - { - UCHAR RSNIe = IE_WPA; - - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)) - { + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) + ) + ) { + u8 RSNIe = IE_WPA; + + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + || (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2)) { RSNIe = IE_WPA2; } - if (pAd->StaCfg.WpaSupplicantUP != 1) - RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0); - - // Check for WPA PMK cache list - if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) - { - INT idx; - BOOLEAN FoundPMK = FALSE; - // Search chched PMKID, append it if existed - for (idx = 0; idx < PMKID_NO; idx++) - { - if (NdisEqualMemory(ApAddr, &pAd->StaCfg.SavedPMK[idx].BSSID, 6)) - { + if ((pAd->StaCfg.WpaSupplicantUP != + WPA_SUPPLICANT_ENABLE) + && (pAd->StaCfg.bRSN_IE_FromWpaSupplicant == FALSE)) + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, + pAd->StaCfg.WepStatus, BSS0); + + /* Check for WPA PMK cache list */ + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) { + int idx; + BOOLEAN FoundPMK = FALSE; + /* Search chched PMKID, append it if existed */ + for (idx = 0; idx < PMKID_NO; idx++) { + if (NdisEqualMemory + (ApAddr, + &pAd->StaCfg.SavedPMK[idx].BSSID, + 6)) { FoundPMK = TRUE; break; } } - - if (FoundPMK) - { - // Set PMK number - *(PUSHORT) &pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len] = 1; - NdisMoveMemory(&pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len + 2], &pAd->StaCfg.SavedPMK[idx].PMKID, 16); - pAd->StaCfg.RSNIE_Len += 18; + if (FoundPMK) { + /* Set PMK number */ + *(u16 *)& pAd->StaCfg.RSN_IE[pAd-> + StaCfg. + RSNIE_Len] + = 1; + NdisMoveMemory(&pAd->StaCfg. + RSN_IE[pAd->StaCfg. + RSNIE_Len + 2], + &pAd->StaCfg. + SavedPMK[idx].PMKID, 16); + pAd->StaCfg.RSNIE_Len += 18; } } - if (pAd->StaCfg.WpaSupplicantUP == 1) - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, - END_OF_ARGS); - } - else - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &RSNIe, - 1, &pAd->StaCfg.RSNIE_Len, - pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, - END_OF_ARGS); + if ((pAd->StaCfg.WpaSupplicantUP == + WPA_SUPPLICANT_ENABLE) + && (pAd->StaCfg.bRSN_IE_FromWpaSupplicant == + TRUE)) { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSN_IE, + END_OF_ARGS); + } else { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &RSNIe, + 1, &pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSN_IE, + END_OF_ARGS); } FrameLen += tmp; - if (pAd->StaCfg.WpaSupplicantUP != 1) - { - // Append Variable IE - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &RSNIe, 1); - VarIesOffset += 1; - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->StaCfg.RSNIE_Len, 1); - VarIesOffset += 1; + if ((pAd->StaCfg.WpaSupplicantUP != + WPA_SUPPLICANT_ENABLE) + || (pAd->StaCfg.bRSN_IE_FromWpaSupplicant == + FALSE)) { + /* Append Variable IE */ + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + + VarIesOffset, &RSNIe, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + + VarIesOffset, + &pAd->StaCfg.RSNIE_Len, 1); + VarIesOffset += 1; } - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len); + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, + pAd->StaCfg.RSN_IE, + pAd->StaCfg.RSNIE_Len); VarIesOffset += pAd->StaCfg.RSNIE_Len; - // Set Variable IEs Length - pAd->StaCfg.ReqVarIELen = VarIesOffset; - } - - // We have update that at PeerBeaconAtJoinRequest() - CkipFlag = pAd->StaCfg.CkipFlag; - if (CkipFlag != 0) - { - NdisZeroMemory(CkipNegotiationBuffer, CKIP_NEGOTIATION_LENGTH); - CkipNegotiationBuffer[2] = 0x66; - // Make it try KP & MIC, since we have to follow the result from AssocRsp - CkipNegotiationBuffer[8] = 0x18; - CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH - 1] = 0x22; - CkipFlag = 0x18; - - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &AironetCkipIe, - 1, &AironetCkipLen, - AironetCkipLen, CkipNegotiationBuffer, - END_OF_ARGS); - FrameLen += tmp; - } - - // Add CCX v2 request if CCX2 admin state is on - if (pAd->StaCfg.CCXControl.field.Enable == 1) - { - - // - // Add AironetIPAddressIE for Cisco CCX 2.X - // Add CCX Version - // - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &AironetIPAddressIE, - 1, &AironetIPAddressLen, - AironetIPAddressLen, AironetIPAddressBuffer, - 1, &Ccx2Ie, - 1, &Ccx2Len, - Ccx2Len, Ccx2IeInfo, - END_OF_ARGS); - FrameLen += tmp; - - // Add by James 03/06/27 - // Set Variable IEs Length + /* Set Variable IEs Length */ pAd->StaCfg.ReqVarIELen = VarIesOffset; - pAd->StaCfg.AssocInfo.RequestIELength = VarIesOffset; - - // OffsetResponseIEs follow ReqVarIE - pAd->StaCfg.AssocInfo.OffsetResponseIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION) + pAd->StaCfg.ReqVarIELen; - // End Add by James } - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); RTMPSetTimer(&pAd->MlmeAux.AssocTimer, Timeout); pAd->Mlme.AssocMachine.CurrState = ASSOC_WAIT_RSP; - } - else - { - DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() sanity check failed. BUG!!!!!! \n")); + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - MlmeAssocReqAction() sanity check failed. BUG!\n")); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_INVALID_FORMAT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, + &Status); } } @@ -594,187 +589,168 @@ VOID MlmeAssocReqAction( ========================================================================== */ -VOID MlmeReassocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void MlmeReassocReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR ApAddr[6]; - HEADER_802_11 ReassocHdr; - UCHAR Ccx2Len = 5; - UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; - USHORT CapabilityInfo, ListenIntv; - ULONG Timeout; - ULONG FrameLen = 0; - BOOLEAN TimerCancelled; - NDIS_STATUS NStatus; - ULONG tmp; - PUCHAR pOutBuffer = NULL; - USHORT Status; - - // Block all authentication request durning WPA block period - if (pAd->StaCfg.bBlockAssoc == TRUE) - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block ReAssoc request durning WPA block period!\n")); + u8 ApAddr[6]; + struct rt_header_802_11 ReassocHdr; + u8 WmeIe[9] = + { IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, + 0x00 }; + u16 CapabilityInfo, ListenIntv; + unsigned long Timeout; + unsigned long FrameLen = 0; + BOOLEAN TimerCancelled; + int NStatus; + unsigned long tmp; + u8 *pOutBuffer = NULL; + u16 Status; + + /* Block all authentication request durning WPA block period */ + if (pAd->StaCfg.bBlockAssoc == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - Block ReAssoc request durning WPA block period!\n")); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, + &Status); } - // the parameters are the same as the association - else if(MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) - { + /* the parameters are the same as the association */ + else if (MlmeAssocReqSanity + (pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, + &Timeout, &ListenIntv)) { RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled); - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() allocate memory failed \n")); + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - MlmeReassocReqAction() allocate memory failed \n")); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_FAIL_NO_RESOURCE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, + MT2_REASSOC_CONF, 2, &Status); return; } COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr); - // make frame, use bssid as the AP address?? - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send RE-ASSOC request...\n")); - MgtMacHeaderInit(pAd, &ReassocHdr, SUBTYPE_REASSOC_REQ, 0, ApAddr, ApAddr); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &ReassocHdr, - 2, &CapabilityInfo, - 2, &ListenIntv, - MAC_ADDR_LEN, ApAddr, - 1, &SsidIe, - 1, &pAd->MlmeAux.SsidLen, - pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, - 1, &SupRateIe, - 1, &pAd->MlmeAux.SupRateLen, - pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, - END_OF_ARGS); - - if (pAd->MlmeAux.ExtRateLen != 0) - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &ExtRateIe, - 1, &pAd->MlmeAux.ExtRateLen, - pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, - END_OF_ARGS); + /* make frame, use bssid as the AP address?? */ + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - Send RE-ASSOC request...\n")); + MgtMacHeaderInit(pAd, &ReassocHdr, SUBTYPE_REASSOC_REQ, 0, + ApAddr, ApAddr); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(struct rt_header_802_11), + &ReassocHdr, 2, &CapabilityInfo, 2, + &ListenIntv, MAC_ADDR_LEN, ApAddr, 1, &SsidIe, + 1, &pAd->MlmeAux.SsidLen, + pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, 1, + &SupRateIe, 1, &pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, + END_OF_ARGS); + + if (pAd->MlmeAux.ExtRateLen != 0) { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRate, END_OF_ARGS); FrameLen += tmp; } - if (pAd->MlmeAux.APEdcaParm.bValid) - { - if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable) - { - QBSS_STA_INFO_PARM QosInfo; + if (pAd->MlmeAux.APEdcaParm.bValid) { + if (pAd->CommonCfg.bAPSDCapable + && pAd->MlmeAux.APEdcaParm.bAPSDCapable) { + struct rt_qbss_sta_info_parm QosInfo; - NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); + NdisZeroMemory(&QosInfo, + sizeof(struct rt_qbss_sta_info_parm)); QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE; QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK; QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI; QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO; - QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength; - WmeIe[8] |= *(PUCHAR)&QosInfo; + QosInfo.MaxSPLength = + pAd->CommonCfg.MaxSPLength; + WmeIe[8] |= *(u8 *)& QosInfo; } - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 9, &WmeIe[0], - END_OF_ARGS); + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 9, &WmeIe[0], END_OF_ARGS); FrameLen += tmp; } - - // HT - if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - ULONG TmpLen; - UCHAR HtLen; - UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; - if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE) - { + /* HT */ + if ((pAd->MlmeAux.HtCapabilityLen > 0) + && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) { + unsigned long TmpLen; + u8 HtLen; + u8 BROADCOM[4] = { 0x0, 0x90, 0x4c, 0x33 }; + if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE) { HtLen = SIZE_HT_CAP_IE + 4; - MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, - 1, &WpaIe, - 1, &HtLen, - 4, &BROADCOM[0], - pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, - END_OF_ARGS); - } - else - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, - 1, &HtCapIe, - 1, &pAd->MlmeAux.HtCapabilityLen, - pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, - END_OF_ARGS); + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 1, &WpaIe, 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, + &pAd->MlmeAux.HtCapability, + END_OF_ARGS); + } else { + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 1, &HtCapIe, 1, + &pAd->MlmeAux.HtCapabilityLen, + pAd->MlmeAux.HtCapabilityLen, + &pAd->MlmeAux.HtCapability, + END_OF_ARGS); } FrameLen += TmpLen; } - - // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION - // Case I: (Aggregation + Piggy-Back) - // 1. user enable aggregation, AND - // 2. Mac support piggy-back - // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON - // Case II: (Aggregation) - // 1. user enable aggregation, AND - // 2. AP annouces it's AGGREGATION-capable in BEACON - if (pAd->CommonCfg.bAggregationCapable) - { - if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)) - { - ULONG TmpLen; - UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00}; - MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, - 9, RalinkIe, - END_OF_ARGS); + /* add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION */ + /* Case I: (Aggregation + Piggy-Back) */ + /* 1. user enable aggregation, AND */ + /* 2. Mac support piggy-back */ + /* 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON */ + /* Case II: (Aggregation) */ + /* 1. user enable aggregation, AND */ + /* 2. AP annouces it's AGGREGATION-capable in BEACON */ + if (pAd->CommonCfg.bAggregationCapable) { + if ((pAd->CommonCfg.bPiggyBackCapable) + && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)) { + unsigned long TmpLen; + u8 RalinkIe[9] = + { IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, + 0x03, 0x00, 0x00, 0x00 }; + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 9, RalinkIe, + END_OF_ARGS); FrameLen += TmpLen; - } - else if (pAd->MlmeAux.APRalinkIe & 0x00000001) - { - ULONG TmpLen; - UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00}; - MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, - 9, RalinkIe, - END_OF_ARGS); + } else if (pAd->MlmeAux.APRalinkIe & 0x00000001) { + unsigned long TmpLen; + u8 RalinkIe[9] = + { IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, + 0x01, 0x00, 0x00, 0x00 }; + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 9, RalinkIe, + END_OF_ARGS); FrameLen += TmpLen; } - } - else - { - ULONG TmpLen; - UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x04, 0x00, 0x00, 0x00}; - MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, - 9, RalinkIe, - END_OF_ARGS); + } else { + unsigned long TmpLen; + u8 RalinkIe[9] = + { IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x04, + 0x00, 0x00, 0x00 }; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 9, + RalinkIe, END_OF_ARGS); FrameLen += TmpLen; } - // Add CCX v2 request if CCX2 admin state is on - if (pAd->StaCfg.CCXControl.field.Enable == 1) - { - // - // Add CCX Version - // - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &Ccx2Ie, - 1, &Ccx2Len, - Ccx2Len, Ccx2IeInfo, - END_OF_ARGS); - FrameLen += tmp; - } - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); - RTMPSetTimer(&pAd->MlmeAux.ReassocTimer, Timeout); /* in mSec */ + RTMPSetTimer(&pAd->MlmeAux.ReassocTimer, Timeout); /* in mSec */ pAd->Mlme.AssocMachine.CurrState = REASSOC_WAIT_RSP; - } - else - { - DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() sanity check failed. BUG!!!! \n")); + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - MlmeReassocReqAction() sanity check failed. BUG!\n")); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_INVALID_FORMAT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, + &Status); } } @@ -789,51 +765,50 @@ VOID MlmeReassocReqAction( ========================================================================== */ -VOID MlmeDisassocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void MlmeDisassocReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - PMLME_DISASSOC_REQ_STRUCT pDisassocReq; - HEADER_802_11 DisassocHdr; - PHEADER_802_11 pDisassocHdr; - PUCHAR pOutBuffer = NULL; - ULONG FrameLen = 0; - NDIS_STATUS NStatus; - BOOLEAN TimerCancelled; - ULONG Timeout = 0; - USHORT Status; - - // skip sanity check - pDisassocReq = (PMLME_DISASSOC_REQ_STRUCT)(Elem->Msg); - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - MlmeDisassocReqAction() allocate memory failed\n")); + struct rt_mlme_disassoc_req *pDisassocReq; + struct rt_header_802_11 DisassocHdr; + struct rt_header_802_11 * pDisassocHdr; + u8 *pOutBuffer = NULL; + unsigned long FrameLen = 0; + int NStatus; + BOOLEAN TimerCancelled; + unsigned long Timeout = 500; + u16 Status; + + /* skip sanity check */ + pDisassocReq = (struct rt_mlme_disassoc_req *)(Elem->Msg); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - MlmeDisassocReqAction() allocate memory failed\n")); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_FAIL_NO_RESOURCE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, + &Status); return; } - - RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &TimerCancelled); - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send DISASSOC request[BSSID::%02x:%02x:%02x:%02x:%02x:%02x (Reason=%d)\n", - pDisassocReq->Addr[0], pDisassocReq->Addr[1], pDisassocReq->Addr[2], - pDisassocReq->Addr[3], pDisassocReq->Addr[4], pDisassocReq->Addr[5], pDisassocReq->Reason)); - MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, pDisassocReq->Addr); // patch peap ttls switching issue - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11),&DisassocHdr, - 2, &pDisassocReq->Reason, - END_OF_ARGS); + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - Send DISASSOC request[BSSID::%02x:%02x:%02x:%02x:%02x:%02x (Reason=%d)\n", + pDisassocReq->Addr[0], pDisassocReq->Addr[1], + pDisassocReq->Addr[2], pDisassocReq->Addr[3], + pDisassocReq->Addr[4], pDisassocReq->Addr[5], + pDisassocReq->Reason)); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, pDisassocReq->Addr); /* patch peap ttls switching issue */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(struct rt_header_802_11), &DisassocHdr, + 2, &pDisassocReq->Reason, END_OF_ARGS); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - // To patch Instance and Buffalo(N) AP - // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine - // Therefore, we send both of them. - pDisassocHdr = (PHEADER_802_11)pOutBuffer; + /* To patch Instance and Buffalo(N) AP */ + /* Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine */ + /* Therefore, we send both of them. */ + pDisassocHdr = (struct rt_header_802_11 *) pOutBuffer; pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH; MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); @@ -842,14 +817,11 @@ VOID MlmeDisassocReqAction( pAd->StaCfg.DisassocReason = REASON_DISASSOC_STA_LEAVING; COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pDisassocReq->Addr); - RTMPSetTimer(&pAd->MlmeAux.DisassocTimer, Timeout); /* in mSec */ + RTMPSetTimer(&pAd->MlmeAux.DisassocTimer, Timeout); /* in mSec */ pAd->Mlme.AssocMachine.CurrState = DISASSOC_WAIT_RSP; - { - union iwreq_data wrqu; - memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); - wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); - } + RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, 0); + } /* @@ -863,94 +835,81 @@ VOID MlmeDisassocReqAction( ========================================================================== */ -VOID PeerAssocRspAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void PeerAssocRspAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT CapabilityInfo, Status, Aid; - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; - UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; - UCHAR Addr2[MAC_ADDR_LEN]; - BOOLEAN TimerCancelled; - UCHAR CkipFlag; - EDCA_PARM EdcaParm; - HT_CAPABILITY_IE HtCapability; - ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE - UCHAR HtCapabilityLen; - UCHAR AddHtInfoLen; - UCHAR NewExtChannelOffset = 0xff; - - if (PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, - &HtCapability,&AddHtInfo, &HtCapabilityLen,&AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag)) - { - // The frame is for me ? - if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():ASSOC - receive ASSOC_RSP to me (status=%d)\n", Status)); - DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():MacTable [%d].AMsduSize = %d. ClientStatusFlags = 0x%lx \n",Elem->Wcid, pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); - RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled); - if(Status == MLME_SUCCESS) - { -#ifdef RT2860 - // go to procedure listed on page 376 - AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, SupRate, SupRateLen, ExtRate, ExtRateLen, - &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo); - - { - union iwreq_data wrqu; - wext_notify_event_assoc(pAd); - - memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); - memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); - wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); - - } -#endif -#ifdef RT2870 - UCHAR MaxSupportedRateIn500Kbps = 0; - UCHAR idx; - - // supported rates array may not be sorted. sort it and find the maximum rate - for (idx=0; idxMacTab.Content[BSSID_WCID], MaxSupportedRateIn500Kbps, &HtCapability, HtCapabilityLen, CapabilityInfo); -#endif - pAd->StaCfg.CkipFlag = CkipFlag; - if (CkipFlag & 0x18) - { - NdisZeroMemory(pAd->StaCfg.TxSEQ, 4); - NdisZeroMemory(pAd->StaCfg.RxSEQ, 4); - NdisZeroMemory(pAd->StaCfg.CKIPMIC, 4); - pAd->StaCfg.GIV[0] = RandomByte(pAd); - pAd->StaCfg.GIV[1] = RandomByte(pAd); - pAd->StaCfg.GIV[2] = RandomByte(pAd); - pAd->StaCfg.bCkipOn = TRUE; - DBGPRINT(RT_DEBUG_TRACE, (" pAd->StaCfg.CkipFlag = 0x%02x\n", pAd->StaCfg.CkipFlag)); + u16 CapabilityInfo, Status, Aid; + u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; + u8 ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; + u8 Addr2[MAC_ADDR_LEN]; + BOOLEAN TimerCancelled; + u8 CkipFlag; + struct rt_edca_parm EdcaParm; + struct rt_ht_capability_ie HtCapability; + struct rt_add_ht_info_ie AddHtInfo; /* AP might use this additional ht info IE */ + u8 HtCapabilityLen = 0; + u8 AddHtInfoLen; + u8 NewExtChannelOffset = 0xff; + + if (PeerAssocRspSanity + (pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, + &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, &HtCapability, + &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen, &NewExtChannelOffset, + &EdcaParm, &CkipFlag)) { + /* The frame is for me ? */ + if (MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerAssocRspAction():ASSOC - receive ASSOC_RSP to me (status=%d)\n", + Status)); + DBGPRINT(RT_DEBUG_TRACE, + ("PeerAssocRspAction():MacTable [%d].AMsduSize = %d. ClientStatusFlags = 0x%lx \n", + Elem->Wcid, + pAd->MacTab.Content[BSSID_WCID].AMsduSize, + pAd->MacTab.Content[BSSID_WCID]. + ClientStatusFlags)); + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, + &TimerCancelled); + + if (Status == MLME_SUCCESS) { + u8 MaxSupportedRateIn500Kbps = 0; + u8 idx; + + /* supported rates array may not be sorted. sort it and find the maximum rate */ + for (idx = 0; idx < SupRateLen; idx++) { + if (MaxSupportedRateIn500Kbps < + (SupRate[idx] & 0x7f)) + MaxSupportedRateIn500Kbps = + SupRate[idx] & 0x7f; } - } - else - { + + for (idx = 0; idx < ExtRateLen; idx++) { + if (MaxSupportedRateIn500Kbps < + (ExtRate[idx] & 0x7f)) + MaxSupportedRateIn500Kbps = + ExtRate[idx] & 0x7f; + } + /* go to procedure listed on page 376 */ + AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, + SupRate, SupRateLen, ExtRate, + ExtRateLen, &EdcaParm, + &HtCapability, HtCapabilityLen, + &AddHtInfo); + + StaAddMacTableEntry(pAd, + &pAd->MacTab. + Content[BSSID_WCID], + MaxSupportedRateIn500Kbps, + &HtCapability, + HtCapabilityLen, &AddHtInfo, + AddHtInfoLen, + CapabilityInfo); } pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, + MT2_ASSOC_CONF, 2, &Status); } - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerAssocRspAction() sanity check fail\n")); + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - PeerAssocRspAction() sanity check fail\n")); } } @@ -965,61 +924,62 @@ VOID PeerAssocRspAction( ========================================================================== */ -VOID PeerReassocRspAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void PeerReassocRspAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT CapabilityInfo; - USHORT Status; - USHORT Aid; - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; - UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; - UCHAR Addr2[MAC_ADDR_LEN]; - UCHAR CkipFlag; - BOOLEAN TimerCancelled; - EDCA_PARM EdcaParm; - HT_CAPABILITY_IE HtCapability; - ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE - UCHAR HtCapabilityLen; - UCHAR AddHtInfoLen; - UCHAR NewExtChannelOffset = 0xff; - - if(PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, - &HtCapability, &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag)) - { - if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) // The frame is for me ? + u16 CapabilityInfo; + u16 Status; + u16 Aid; + u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; + u8 ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; + u8 Addr2[MAC_ADDR_LEN]; + u8 CkipFlag; + BOOLEAN TimerCancelled; + struct rt_edca_parm EdcaParm; + struct rt_ht_capability_ie HtCapability; + struct rt_add_ht_info_ie AddHtInfo; /* AP might use this additional ht info IE */ + u8 HtCapabilityLen; + u8 AddHtInfoLen; + u8 NewExtChannelOffset = 0xff; + + if (PeerAssocRspSanity + (pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, + &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, &HtCapability, + &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen, &NewExtChannelOffset, + &EdcaParm, &CkipFlag)) { + if (MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) /* The frame is for me ? */ { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - receive REASSOC_RSP to me (status=%d)\n", Status)); - RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled); - - if(Status == MLME_SUCCESS) - { - // go to procedure listed on page 376 - AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, SupRate, SupRateLen, ExtRate, ExtRateLen, - &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo); + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - receive REASSOC_RSP to me (status=%d)\n", + Status)); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, + &TimerCancelled); + + if (Status == MLME_SUCCESS) { + /* go to procedure listed on page 376 */ + AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, + SupRate, SupRateLen, ExtRate, + ExtRateLen, &EdcaParm, + &HtCapability, HtCapabilityLen, + &AddHtInfo); - { - union iwreq_data wrqu; - wext_notify_event_assoc(pAd); - - memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); - memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); - wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); - - } - - } + { + wext_notify_event_assoc(pAd); + RtmpOSWrielessEventSend(pAd, SIOCGIWAP, + -1, + &pAd->MlmeAux. + Bssid[0], NULL, + 0); + } - { - // CkipFlag is no use for reassociate - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); } + /* CkipFlag is no use for reassociate */ + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, + MT2_REASSOC_CONF, 2, &Status); } - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerReassocRspAction() sanity check fail\n")); + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - PeerReassocRspAction() sanity check fail\n")); } } @@ -1034,30 +994,18 @@ VOID PeerReassocRspAction( ========================================================================== */ -VOID AssocPostProc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr2, - IN USHORT CapabilityInfo, - IN USHORT Aid, - IN UCHAR SupRate[], - IN UCHAR SupRateLen, - IN UCHAR ExtRate[], - IN UCHAR ExtRateLen, - IN PEDCA_PARM pEdcaParm, - IN HT_CAPABILITY_IE *pHtCapability, - IN UCHAR HtCapabilityLen, - IN ADD_HT_INFO_IE *pAddHtInfo) // AP might use this additional ht info IE +void AssocPostProc(struct rt_rtmp_adapter *pAd, u8 *pAddr2, u16 CapabilityInfo, u16 Aid, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_edca_parm *pEdcaParm, struct rt_ht_capability_ie * pHtCapability, u8 HtCapabilityLen, struct rt_add_ht_info_ie * pAddHtInfo) /* AP might use this additional ht info IE */ { - ULONG Idx; + unsigned long Idx; pAd->MlmeAux.BssType = BSS_INFRA; COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pAddr2); pAd->MlmeAux.Aid = Aid; - pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + pAd->MlmeAux.CapabilityInfo = + CapabilityInfo & SUPPORTED_CAPABILITY_INFO; - // Some HT AP might lost WMM IE. We add WMM ourselves. beacuase HT requires QoS on. - if ((HtCapabilityLen > 0) && (pEdcaParm->bValid == FALSE)) - { + /* Some HT AP might lost WMM IE. We add WMM ourselves. beacuase HT requires QoS on. */ + if ((HtCapabilityLen > 0) && (pEdcaParm->bValid == FALSE)) { pEdcaParm->bValid = TRUE; pEdcaParm->Aifsn[0] = 3; pEdcaParm->Aifsn[1] = 7; @@ -1074,88 +1022,113 @@ VOID AssocPostProc( pEdcaParm->Cwmax[2] = 4; pEdcaParm->Cwmax[3] = 3; - pEdcaParm->Txop[0] = 0; - pEdcaParm->Txop[1] = 0; - pEdcaParm->Txop[2] = 96; - pEdcaParm->Txop[3] = 48; + pEdcaParm->Txop[0] = 0; + pEdcaParm->Txop[1] = 0; + pEdcaParm->Txop[2] = 96; + pEdcaParm->Txop[3] = 48; } - NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM)); + NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, pEdcaParm, sizeof(struct rt_edca_parm)); - // filter out un-supported rates + /* filter out un-supported rates */ pAd->MlmeAux.SupRateLen = SupRateLen; NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen); RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); - // filter out un-supported rates + /* filter out un-supported rates */ pAd->MlmeAux.ExtRateLen = ExtRateLen; NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen); RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); - if (HtCapabilityLen > 0) - { + if (HtCapabilityLen > 0) { RTMPCheckHt(pAd, BSSID_WCID, pHtCapability, pAddHtInfo); } - DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> AP.AMsduSize = %d. ClientStatusFlags = 0x%lx \n", pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); + DBGPRINT(RT_DEBUG_TRACE, + ("AssocPostProc===> AP.AMsduSize = %d. ClientStatusFlags = 0x%lx \n", + pAd->MacTab.Content[BSSID_WCID].AMsduSize, + pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); - DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> (Mmps=%d, AmsduSize=%d, )\n", - pAd->MacTab.Content[BSSID_WCID].MmpsMode, pAd->MacTab.Content[BSSID_WCID].AMsduSize)); + DBGPRINT(RT_DEBUG_TRACE, + ("AssocPostProc===> (Mmps=%d, AmsduSize=%d, )\n", + pAd->MacTab.Content[BSSID_WCID].MmpsMode, + pAd->MacTab.Content[BSSID_WCID].AMsduSize)); - // Set New WPA information + /* Set New WPA information */ Idx = BssTableSearch(&pAd->ScanTab, pAddr2, pAd->MlmeAux.Channel); - if (Idx == BSS_NOT_FOUND) - { + if (Idx == BSS_NOT_FOUND) { DBGPRINT_ERR(("ASSOC - Can't find BSS after receiving Assoc response\n")); - } - else - { - // Init variable + } else { + /* Init variable */ pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = 0; - NdisZeroMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, MAX_LEN_OF_RSNIE); + NdisZeroMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, + MAX_LEN_OF_RSNIE); - // Store appropriate RSN_IE for WPA SM negotiation later - if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAd->ScanTab.BssEntry[Idx].VarIELen != 0)) - { - PUCHAR pVIE; - USHORT len; - PEID_STRUCT pEid; + /* Store appropriate RSN_IE for WPA SM negotiation later */ + if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + && (pAd->ScanTab.BssEntry[Idx].VarIELen != 0)) { + u8 *pVIE; + u16 len; + struct rt_eid * pEid; pVIE = pAd->ScanTab.BssEntry[Idx].VarIEs; - len = pAd->ScanTab.BssEntry[Idx].VarIELen; - - while (len > 0) - { - pEid = (PEID_STRUCT) pVIE; - // For WPA/WPAPSK - if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) - && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) - { - NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2)); - pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2); - DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA SM negotiation \n")); + len = pAd->ScanTab.BssEntry[Idx].VarIELen; + /*KH need to check again */ + /* Don't allow to go to sleep mode if authmode is WPA-related. */ + /*This can make Authentication process more smoothly. */ + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); + + while (len > 0) { + pEid = (struct rt_eid *) pVIE; + /* For WPA/WPAPSK */ + if ((pEid->Eid == IE_WPA) + && + (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + && (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA + || pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPAPSK)) { + NdisMoveMemory(pAd->MacTab. + Content[BSSID_WCID]. + RSN_IE, pVIE, + (pEid->Len + 2)); + pAd->MacTab.Content[BSSID_WCID]. + RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, + ("AssocPostProc===> Store RSN_IE for WPA SM negotiation \n")); } - // For WPA2/WPA2PSK - else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) - && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2)); - pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2); - DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA2 SM negotiation \n")); + /* For WPA2/WPA2PSK */ + else if ((pEid->Eid == IE_RSN) + && + (NdisEqualMemory + (pEid->Octet + 2, RSN_OUI, 3)) + && (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2 + || pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2PSK)) { + NdisMoveMemory(pAd->MacTab. + Content[BSSID_WCID]. + RSN_IE, pVIE, + (pEid->Len + 2)); + pAd->MacTab.Content[BSSID_WCID]. + RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, + ("AssocPostProc===> Store RSN_IE for WPA2 SM negotiation \n")); } pVIE += (pEid->Len + 2); - len -= (pEid->Len + 2); + len -= (pEid->Len + 2); } - } - if (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == 0) - { - DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> no RSN_IE \n")); } - else - { - hex_dump("RSN_IE", pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len); + + if (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == 0) { + DBGPRINT(RT_DEBUG_TRACE, + ("AssocPostProc===> no RSN_IE \n")); + } else { + hex_dump("RSN_IE", + pAd->MacTab.Content[BSSID_WCID].RSN_IE, + pAd->MacTab.Content[BSSID_WCID].RSNIE_Len); } } } @@ -1171,43 +1144,36 @@ VOID AssocPostProc( ========================================================================== */ -VOID PeerDisassocAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void PeerDisassocAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Addr2[MAC_ADDR_LEN]; - USHORT Reason; + u8 Addr2[MAC_ADDR_LEN]; + u16 Reason; DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction()\n")); - if(PeerDisassocSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() Reason = %d\n", Reason)); - if (INFRA_ON(pAd) && MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, Addr2)) - { - - if (pAd->CommonCfg.bWirelessEvent) - { - RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + if (PeerDisassocSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - PeerDisassocAction() Reason = %d\n", + Reason)); + if (INFRA_ON(pAd) + && MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, Addr2)) { + + if (pAd->CommonCfg.bWirelessEvent) { + RTMPSendWirelessEvent(pAd, + IW_DISASSOC_EVENT_FLAG, + pAd->MacTab. + Content[BSSID_WCID].Addr, + BSS0, 0); } - // - // Get Current System time and Turn on AdjacentAPReport - // - NdisGetSystemUpTime(&pAd->StaCfg.CCXAdjacentAPLinkDownTime); - pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE; LinkDown(pAd, TRUE); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - { - union iwreq_data wrqu; - memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); - wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); - } + RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, + 0); } - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() sanity check fail\n")); + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - PeerDisassocAction() sanity check fail\n")); } } @@ -1223,11 +1189,9 @@ VOID PeerDisassocAction( ========================================================================== */ -VOID AssocTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void AssocTimeoutAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Status; + u16 Status; DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - AssocTimeoutAction\n")); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_REJ_TIMEOUT; @@ -1243,11 +1207,9 @@ VOID AssocTimeoutAction( ========================================================================== */ -VOID ReassocTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void ReassocTimeoutAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Status; + u16 Status; DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - ReassocTimeoutAction\n")); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_REJ_TIMEOUT; @@ -1263,51 +1225,49 @@ VOID ReassocTimeoutAction( ========================================================================== */ -VOID DisassocTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void DisassocTimeoutAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Status; + u16 Status; DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - DisassocTimeoutAction\n")); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_SUCCESS; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, + &Status); } -VOID InvalidStateWhenAssoc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void InvalidStateWhenAssoc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenAssoc(state=%ld), reset ASSOC state machine\n", - pAd->Mlme.AssocMachine.CurrState)); + u16 Status; + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - InvalidStateWhenAssoc(state=%ld), reset ASSOC state machine\n", + pAd->Mlme.AssocMachine.CurrState)); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_STATE_MACHINE_REJECT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); } -VOID InvalidStateWhenReassoc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void InvalidStateWhenReassoc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenReassoc(state=%ld), reset ASSOC state machine\n", - pAd->Mlme.AssocMachine.CurrState)); + u16 Status; + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - InvalidStateWhenReassoc(state=%ld), reset ASSOC state machine\n", + pAd->Mlme.AssocMachine.CurrState)); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_STATE_MACHINE_REJECT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); } -VOID InvalidStateWhenDisassociate( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void InvalidStateWhenDisassociate(struct rt_rtmp_adapter *pAd, + struct rt_mlme_queue_elem *Elem) { - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenDisassoc(state=%ld), reset ASSOC state machine\n", - pAd->Mlme.AssocMachine.CurrState)); + u16 Status; + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - InvalidStateWhenDisassoc(state=%ld), reset ASSOC state machine\n", + pAd->Mlme.AssocMachine.CurrState)); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, + &Status); } /* @@ -1323,33 +1283,31 @@ VOID InvalidStateWhenDisassociate( ========================================================================== */ -VOID Cls3errAction( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr) +void Cls3errAction(struct rt_rtmp_adapter *pAd, u8 *pAddr) { - HEADER_802_11 DisassocHdr; - PHEADER_802_11 pDisassocHdr; - PUCHAR pOutBuffer = NULL; - ULONG FrameLen = 0; - NDIS_STATUS NStatus; - USHORT Reason = REASON_CLS3ERR; - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + struct rt_header_802_11 DisassocHdr; + struct rt_header_802_11 * pDisassocHdr; + u8 *pOutBuffer = NULL; + unsigned long FrameLen = 0; + int NStatus; + u16 Reason = REASON_CLS3ERR; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ if (NStatus != NDIS_STATUS_SUCCESS) return; - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Class 3 Error, Send DISASSOC frame\n")); - MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pAddr, pAd->CommonCfg.Bssid); // patch peap ttls switching issue - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11),&DisassocHdr, - 2, &Reason, - END_OF_ARGS); + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - Class 3 Error, Send DISASSOC frame\n")); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pAddr, pAd->CommonCfg.Bssid); /* patch peap ttls switching issue */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(struct rt_header_802_11), &DisassocHdr, + 2, &Reason, END_OF_ARGS); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - // To patch Instance and Buffalo(N) AP - // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine - // Therefore, we send both of them. - pDisassocHdr = (PHEADER_802_11)pOutBuffer; + /* To patch Instance and Buffalo(N) AP */ + /* Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine */ + /* Therefore, we send both of them. */ + pDisassocHdr = (struct rt_header_802_11 *) pOutBuffer; pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH; MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); @@ -1359,352 +1317,271 @@ VOID Cls3errAction( COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pAddr); } - /* - ========================================================================== - Description: - Switch between WEP and CKIP upon new association up. - Parameters: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID SwitchBetweenWepAndCkip( - IN PRTMP_ADAPTER pAd) +int wext_notify_event_assoc(struct rt_rtmp_adapter *pAd) { - int i; - SHAREDKEY_MODE_STRUC csr1; - - // if KP is required. change the CipherAlg in hardware shard key table from WEP - // to CKIP. else remain as WEP - if (pAd->StaCfg.bCkipOn && (pAd->StaCfg.CkipFlag & 0x10)) - { - // modify hardware key table so that MAC use correct algorithm to decrypt RX - RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE, &csr1.word); - if (csr1.field.Bss0Key0CipherAlg == CIPHER_WEP64) - csr1.field.Bss0Key0CipherAlg = CIPHER_CKIP64; - else if (csr1.field.Bss0Key0CipherAlg == CIPHER_WEP128) - csr1.field.Bss0Key0CipherAlg = CIPHER_CKIP128; - - if (csr1.field.Bss0Key1CipherAlg == CIPHER_WEP64) - csr1.field.Bss0Key1CipherAlg = CIPHER_CKIP64; - else if (csr1.field.Bss0Key1CipherAlg == CIPHER_WEP128) - csr1.field.Bss0Key1CipherAlg = CIPHER_CKIP128; - - if (csr1.field.Bss0Key2CipherAlg == CIPHER_WEP64) - csr1.field.Bss0Key2CipherAlg = CIPHER_CKIP64; - else if (csr1.field.Bss0Key2CipherAlg == CIPHER_WEP128) - csr1.field.Bss0Key2CipherAlg = CIPHER_CKIP128; - - if (csr1.field.Bss0Key3CipherAlg == CIPHER_WEP64) - csr1.field.Bss0Key3CipherAlg = CIPHER_CKIP64; - else if (csr1.field.Bss0Key3CipherAlg == CIPHER_WEP128) - csr1.field.Bss0Key3CipherAlg = CIPHER_CKIP128; - RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE, csr1.word); - DBGPRINT(RT_DEBUG_TRACE, ("SwitchBetweenWepAndCkip: modify BSS0 cipher to %s\n", CipherName[csr1.field.Bss0Key0CipherAlg])); - - // modify software key table so that driver can specify correct algorithm in TXD upon TX - for (i=0; iSharedKey[BSS0][i].CipherAlg == CIPHER_WEP64) - pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_CKIP64; - else if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_WEP128) - pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_CKIP128; - } - } - - // else if KP NOT inused. change the CipherAlg in hardware shard key table from CKIP - // to WEP. - else - { - // modify hardware key table so that MAC use correct algorithm to decrypt RX - RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE, &csr1.word); - if (csr1.field.Bss0Key0CipherAlg == CIPHER_CKIP64) - csr1.field.Bss0Key0CipherAlg = CIPHER_WEP64; - else if (csr1.field.Bss0Key0CipherAlg == CIPHER_CKIP128) - csr1.field.Bss0Key0CipherAlg = CIPHER_WEP128; - - if (csr1.field.Bss0Key1CipherAlg == CIPHER_CKIP64) - csr1.field.Bss0Key1CipherAlg = CIPHER_WEP64; - else if (csr1.field.Bss0Key1CipherAlg == CIPHER_CKIP128) - csr1.field.Bss0Key1CipherAlg = CIPHER_WEP128; - - if (csr1.field.Bss0Key2CipherAlg == CIPHER_CKIP64) - csr1.field.Bss0Key2CipherAlg = CIPHER_WEP64; - else if (csr1.field.Bss0Key2CipherAlg == CIPHER_CKIP128) - csr1.field.Bss0Key2CipherAlg = CIPHER_WEP128; - - if (csr1.field.Bss0Key3CipherAlg == CIPHER_CKIP64) - csr1.field.Bss0Key3CipherAlg = CIPHER_WEP64; - else if (csr1.field.Bss0Key3CipherAlg == CIPHER_CKIP128) - csr1.field.Bss0Key3CipherAlg = CIPHER_WEP128; - - // modify software key table so that driver can specify correct algorithm in TXD upon TX - for (i=0; iSharedKey[BSS0][i].CipherAlg == CIPHER_CKIP64) - pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_WEP64; - else if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_CKIP128) - pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_WEP128; - } + char custom[IW_CUSTOM_MAX] = { 0 }; - // - // On WPA-NONE, must update CipherAlg. - // Because the OID_802_11_WEP_STATUS was been set after OID_802_11_ADD_KEY - // and CipherAlg will be CIPHER_NONE by Windows ZeroConfig. - // So we need to update CipherAlg after connect. - // - if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - { - for (i = 0; i < SHARE_KEY_NUM; i++) - { - if (pAd->SharedKey[BSS0][i].KeyLen != 0) - { - if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) - { - pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_TKIP; - } - else if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_AES; - } - } - else - { - pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_NONE; - } - } - - csr1.field.Bss0Key0CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; - csr1.field.Bss0Key1CipherAlg = pAd->SharedKey[BSS0][1].CipherAlg; - csr1.field.Bss0Key2CipherAlg = pAd->SharedKey[BSS0][2].CipherAlg; - csr1.field.Bss0Key3CipherAlg = pAd->SharedKey[BSS0][3].CipherAlg; - } - RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE, csr1.word); - DBGPRINT(RT_DEBUG_TRACE, ("SwitchBetweenWepAndCkip: modify BSS0 cipher to %s\n", CipherName[csr1.field.Bss0Key0CipherAlg])); - } -} - -int wext_notify_event_assoc( - IN RTMP_ADAPTER *pAd) -{ - union iwreq_data wrqu; - char custom[IW_CUSTOM_MAX] = {0}; - - if (pAd->StaCfg.ReqVarIELen <= IW_CUSTOM_MAX) - { - wrqu.data.length = pAd->StaCfg.ReqVarIELen; - memcpy(custom, pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen); - wireless_send_event(pAd->net_dev, IWEVASSOCREQIE, &wrqu, custom); - } - else - DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen > MAX_CUSTOM_LEN\n")); + if (pAd->StaCfg.ReqVarIELen <= IW_CUSTOM_MAX) { + NdisMoveMemory(custom, pAd->StaCfg.ReqVarIEs, + pAd->StaCfg.ReqVarIELen); + RtmpOSWrielessEventSend(pAd, IWEVASSOCREQIE, -1, NULL, custom, + pAd->StaCfg.ReqVarIELen); + } else + DBGPRINT(RT_DEBUG_TRACE, + ("pAd->StaCfg.ReqVarIELen > MAX_CUSTOM_LEN\n")); return 0; } -#ifdef RT2870 -BOOLEAN StaAddMacTableEntry( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN UCHAR MaxSupportedRateIn500Kbps, - IN HT_CAPABILITY_IE *pHtCapability, - IN UCHAR HtCapabilityLen, - IN USHORT CapabilityInfo) +BOOLEAN StaAddMacTableEntry(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + u8 MaxSupportedRateIn500Kbps, + struct rt_ht_capability_ie * pHtCapability, + u8 HtCapabilityLen, + struct rt_add_ht_info_ie * pAddHtInfo, + u8 AddHtInfoLen, u16 CapabilityInfo) { - UCHAR MaxSupportedRate = RATE_11; + u8 MaxSupportedRate = RATE_11; if (ADHOC_ON(pAd)) CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); - switch (MaxSupportedRateIn500Kbps) - { - case 108: MaxSupportedRate = RATE_54; break; - case 96: MaxSupportedRate = RATE_48; break; - case 72: MaxSupportedRate = RATE_36; break; - case 48: MaxSupportedRate = RATE_24; break; - case 36: MaxSupportedRate = RATE_18; break; - case 24: MaxSupportedRate = RATE_12; break; - case 18: MaxSupportedRate = RATE_9; break; - case 12: MaxSupportedRate = RATE_6; break; - case 22: MaxSupportedRate = RATE_11; break; - case 11: MaxSupportedRate = RATE_5_5; break; - case 4: MaxSupportedRate = RATE_2; break; - case 2: MaxSupportedRate = RATE_1; break; - default: MaxSupportedRate = RATE_11; break; - } - - if ((pAd->CommonCfg.PhyMode == PHY_11G) && (MaxSupportedRate < RATE_FIRST_OFDM_RATE)) - return FALSE; - - // 11n only - if (((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))&& (HtCapabilityLen == 0)) + switch (MaxSupportedRateIn500Kbps) { + case 108: + MaxSupportedRate = RATE_54; + break; + case 96: + MaxSupportedRate = RATE_48; + break; + case 72: + MaxSupportedRate = RATE_36; + break; + case 48: + MaxSupportedRate = RATE_24; + break; + case 36: + MaxSupportedRate = RATE_18; + break; + case 24: + MaxSupportedRate = RATE_12; + break; + case 18: + MaxSupportedRate = RATE_9; + break; + case 12: + MaxSupportedRate = RATE_6; + break; + case 22: + MaxSupportedRate = RATE_11; + break; + case 11: + MaxSupportedRate = RATE_5_5; + break; + case 4: + MaxSupportedRate = RATE_2; + break; + case 2: + MaxSupportedRate = RATE_1; + break; + default: + MaxSupportedRate = RATE_11; + break; + } + + if ((pAd->CommonCfg.PhyMode == PHY_11G) + && (MaxSupportedRate < RATE_FIRST_OFDM_RATE)) + return FALSE; + + /* 11n only */ + if (((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) + || (pAd->CommonCfg.PhyMode == PHY_11N_5G)) + && (HtCapabilityLen == 0)) return FALSE; if (!pEntry) - return FALSE; + return FALSE; NdisAcquireSpinLock(&pAd->MacTabLock); - if (pEntry) - { + if (pEntry) { pEntry->PortSecured = WPA_802_1X_PORT_SECURED; if ((MaxSupportedRate < RATE_FIRST_OFDM_RATE) || - (pAd->CommonCfg.PhyMode == PHY_11B)) - { + (pAd->CommonCfg.PhyMode == PHY_11B)) { pEntry->RateLen = 4; if (MaxSupportedRate >= RATE_FIRST_OFDM_RATE) MaxSupportedRate = RATE_11; - } - else + } else pEntry->RateLen = 12; pEntry->MaxHTPhyMode.word = 0; pEntry->MinHTPhyMode.word = 0; pEntry->HTPhyMode.word = 0; pEntry->MaxSupportedRate = MaxSupportedRate; - if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) - { + if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) { pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; - pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->MaxHTPhyMode.field.MCS = + pEntry->MaxSupportedRate; pEntry->MinHTPhyMode.field.MODE = MODE_CCK; - pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->MinHTPhyMode.field.MCS = + pEntry->MaxSupportedRate; pEntry->HTPhyMode.field.MODE = MODE_CCK; pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; - } - else - { + } else { pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; - pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->MaxHTPhyMode.field.MCS = + OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; - pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->MinHTPhyMode.field.MCS = + OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; pEntry->HTPhyMode.field.MODE = MODE_OFDM; - pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->HTPhyMode.field.MCS = + OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; } pEntry->CapabilityInfo = CapabilityInfo; - CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); - CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); + CLIENT_STATUS_CLEAR_FLAG(pEntry, + fCLIENT_STATUS_AGGREGATION_CAPABLE); + CLIENT_STATUS_CLEAR_FLAG(pEntry, + fCLIENT_STATUS_PIGGYBACK_CAPABLE); } - // If this Entry supports 802.11n, upgrade to HT rate. - if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - UCHAR j, bitmask; //k,bitmask; - CHAR i; + NdisZeroMemory(&pEntry->HTCapability, sizeof(pEntry->HTCapability)); + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if ((HtCapabilityLen != 0) + && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) { + u8 j, bitmask; /*k,bitmask; */ + char i; if (ADHOC_ON(pAd)) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); - if ((pHtCapability->HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) - { + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_WMM_CAPABLE); + if ((pHtCapability->HtCapInfo.GF) + && (pAd->CommonCfg.DesiredHtPhy.GF)) { pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; - } - else - { + } else { pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; pAd->MacTab.fAnyStationNonGF = TRUE; pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; } - if ((pHtCapability->HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) - { - pEntry->MaxHTPhyMode.field.BW= BW_40; - pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(pHtCapability->HtCapInfo.ShortGIfor40)); - } - else - { + if ((pHtCapability->HtCapInfo.ChannelWidth) && + (pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && + ((pAd->StaCfg.BssType == BSS_INFRA) + || ((pAd->StaCfg.BssType == BSS_ADHOC) + && (pAddHtInfo->AddHtInfo.ExtChanOffset == + pAd->CommonCfg.AddHTInfo.AddHtInfo. + ExtChanOffset)))) { + pEntry->MaxHTPhyMode.field.BW = BW_40; + pEntry->MaxHTPhyMode.field.ShortGI = + ((pAd->CommonCfg.DesiredHtPhy. + ShortGIfor40) & (pHtCapability->HtCapInfo. + ShortGIfor40)); + } else { pEntry->MaxHTPhyMode.field.BW = BW_20; - pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(pHtCapability->HtCapInfo.ShortGIfor20)); + pEntry->MaxHTPhyMode.field.ShortGI = + ((pAd->CommonCfg.DesiredHtPhy. + ShortGIfor20) & (pHtCapability->HtCapInfo. + ShortGIfor20)); pAd->MacTab.fAnyStation20Only = TRUE; } - // 3*3 - if (pAd->MACVersion >= RALINK_2883_VERSION && pAd->MACVersion < RALINK_3070_VERSION) - pEntry->MaxHTPhyMode.field.TxBF = pAd->CommonCfg.RegTransmitSetting.field.TxBF; + /* 3*3 */ + if (pAd->MACVersion >= RALINK_2883_VERSION + && pAd->MACVersion < RALINK_3070_VERSION) + pEntry->MaxHTPhyMode.field.TxBF = + pAd->CommonCfg.RegTransmitSetting.field.TxBF; - // find max fixed rate - for (i=23; i>=0; i--) // 3*3 + /* find max fixed rate */ + for (i = 23; i >= 0; i--) /* 3*3 */ { - j = i/8; - bitmask = (1<<(i-(j*8))); - if ((pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j] & bitmask) && (pHtCapability->MCSSet[j] & bitmask)) - { + j = i / 8; + bitmask = (1 << (i - (j * 8))); + if ((pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j] & bitmask) + && (pHtCapability->MCSSet[j] & bitmask)) { pEntry->MaxHTPhyMode.field.MCS = i; break; } - if (i==0) + if (i == 0) break; } - - if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) - { - if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32) - { - // Fix MCS as HT Duplicated Mode + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) { + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32) { + /* Fix MCS as HT Duplicated Mode */ pEntry->MaxHTPhyMode.field.BW = 1; pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; pEntry->MaxHTPhyMode.field.STBC = 0; pEntry->MaxHTPhyMode.field.ShortGI = 0; pEntry->MaxHTPhyMode.field.MCS = 32; - } - else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS) - { - // STA supports fixed MCS - pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + } else if (pEntry->MaxHTPhyMode.field.MCS > + pAd->StaCfg.HTPhyMode.field.MCS) { + /* STA supports fixed MCS */ + pEntry->MaxHTPhyMode.field.MCS = + pAd->StaCfg.HTPhyMode.field.MCS; } } - pEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MaxHTPhyMode.field.STBC = + (pHtCapability->HtCapInfo. + RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); pEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity; - pEntry->MaxRAmpduFactor = pHtCapability->HtCapParm.MaxRAmpduFactor; - pEntry->MmpsMode = (UCHAR)pHtCapability->HtCapInfo.MimoPs; - pEntry->AMsduSize = (UCHAR)pHtCapability->HtCapInfo.AMsduSize; + pEntry->MaxRAmpduFactor = + pHtCapability->HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (u8)pHtCapability->HtCapInfo.MimoPs; + pEntry->AMsduSize = (u8)pHtCapability->HtCapInfo.AMsduSize; pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; - if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED); + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable + && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_AMSDU_INUSED); if (pHtCapability->HtCapInfo.ShortGIfor20) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_SGI20_CAPABLE); if (pHtCapability->HtCapInfo.ShortGIfor40) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_SGI40_CAPABLE); if (pHtCapability->HtCapInfo.TxSTBC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_TxSTBC_CAPABLE); if (pHtCapability->HtCapInfo.RxSTBC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_RxSTBC_CAPABLE); if (pHtCapability->ExtHtCapInfo.PlusHTC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); - if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg + && pHtCapability->ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_RDG_CAPABLE); if (pHtCapability->ExtHtCapInfo.MCSFeedback == 0x03) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); - } - else - { + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + NdisMoveMemory(&pEntry->HTCapability, pHtCapability, + HtCapabilityLen); + } else { pAd->MacTab.fAnyStationIsLegacy = TRUE; } - NdisMoveMemory(&pEntry->HTCapability, pHtCapability, sizeof(HT_CAPABILITY_IE)); - pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; pEntry->CurrTxRate = pEntry->MaxSupportedRate; - // Set asic auto fall back - if (pAd->StaCfg.bAutoTxRateSwitch == TRUE) - { - PUCHAR pTable; - UCHAR TableSize = 0; + /* Set asic auto fall back */ + if (pAd->StaCfg.bAutoTxRateSwitch == TRUE) { + u8 *pTable; + u8 TableSize = 0; - MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex); + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, + &pEntry->CurrTxRateIndex); pEntry->bAutoTxRateSwitch = TRUE; - } - else - { - pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; - pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + } else { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; pEntry->bAutoTxRateSwitch = FALSE; - // If the legacy mode is set, overwrite the transmit setting of this entry. - RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((u8)pAd->StaCfg. + DesiredTransmitSetting.field. + FixedTxMode, pEntry); } pEntry->PortSecured = WPA_802_1X_PORT_SECURED; @@ -1715,15 +1592,14 @@ BOOLEAN StaAddMacTableEntry( NdisReleaseSpinLock(&pAd->MacTabLock); - { - union iwreq_data wrqu; - wext_notify_event_assoc(pAd); + { + union iwreq_data wrqu; + wext_notify_event_assoc(pAd); - memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); - memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); - wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); - } + } return TRUE; } -#endif /* RT2870 */ diff --git a/drivers/staging/rt2860/sta/auth.c b/drivers/staging/rt2860/sta/auth.c index d8414eac42f8136d7ecf29aeffe421fc231d4456..404bd220679d3377a72b268b150b465421603218 100644 --- a/drivers/staging/rt2860/sta/auth.c +++ b/drivers/staging/rt2860/sta/auth.c @@ -55,27 +55,35 @@ ========================================================================== */ -void AuthStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *Sm, - OUT STATE_MACHINE_FUNC Trans[]) +void AuthStateMachineInit(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *Sm, OUT STATE_MACHINE_FUNC Trans[]) { - StateMachineInit(Sm, Trans, MAX_AUTH_STATE, MAX_AUTH_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_REQ_IDLE, AUTH_MACHINE_BASE); - - // the first column - StateMachineSetAction(Sm, AUTH_REQ_IDLE, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)MlmeAuthReqAction); - - // the second column - StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth); - StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq2Action); - StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction); - - // the third column - StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth); - StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq4Action); - StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction); - - RTMPInitTimer(pAd, &pAd->MlmeAux.AuthTimer, GET_TIMER_FUNCTION(AuthTimeout), pAd, FALSE); + StateMachineInit(Sm, Trans, MAX_AUTH_STATE, MAX_AUTH_MSG, + (STATE_MACHINE_FUNC) Drop, AUTH_REQ_IDLE, + AUTH_MACHINE_BASE); + + /* the first column */ + StateMachineSetAction(Sm, AUTH_REQ_IDLE, MT2_MLME_AUTH_REQ, + (STATE_MACHINE_FUNC) MlmeAuthReqAction); + + /* the second column */ + StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_MLME_AUTH_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenAuth); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_PEER_AUTH_EVEN, + (STATE_MACHINE_FUNC) PeerAuthRspAtSeq2Action); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_AUTH_TIMEOUT, + (STATE_MACHINE_FUNC) AuthTimeoutAction); + + /* the third column */ + StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_MLME_AUTH_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenAuth); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_PEER_AUTH_EVEN, + (STATE_MACHINE_FUNC) PeerAuthRspAtSeq4Action); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_AUTH_TIMEOUT, + (STATE_MACHINE_FUNC) AuthTimeoutAction); + + RTMPInitTimer(pAd, &pAd->MlmeAux.AuthTimer, + GET_TIMER_FUNCTION(AuthTimeout), pAd, FALSE); } /* @@ -87,31 +95,28 @@ void AuthStateMachineInit( ========================================================================== */ -VOID AuthTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) +void AuthTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) { - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; - DBGPRINT(RT_DEBUG_TRACE,("AUTH - AuthTimeout\n")); + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - AuthTimeout\n")); - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ + if (RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) return; - // send a de-auth to reset AP's state machine (Patch AP-Dir635) + /* send a de-auth to reset AP's state machine (Patch AP-Dir635) */ if (pAd->Mlme.AuthMachine.CurrState == AUTH_WAIT_SEQ2) Cls2errAction(pAd, pAd->MlmeAux.Bssid); - - MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_AUTH_TIMEOUT, 0, NULL); - RT28XX_MLME_HANDLER(pAd); + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_AUTH_TIMEOUT, 0, NULL); + RTMP_MLME_HANDLER(pAd); } - /* ========================================================================== Description: @@ -120,67 +125,19 @@ VOID AuthTimeout( ========================================================================== */ -VOID MlmeAuthReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void MlmeAuthReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Addr[6]; - USHORT Alg, Seq, Status; - ULONG Timeout; - HEADER_802_11 AuthHdr; - BOOLEAN TimerCancelled; - NDIS_STATUS NStatus; - PUCHAR pOutBuffer = NULL; - ULONG FrameLen = 0; - - // Block all authentication request durning WPA block period - if (pAd->StaCfg.bBlockAssoc == TRUE) - { - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Block Auth request durning WPA block period!\n")); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + if (AUTH_ReqSend + (pAd, Elem, &pAd->MlmeAux.AuthTimer, "AUTH", 1, NULL, 0)) + pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ2; + else { + u16 Status; + + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, + &Status); } - else if(MlmeAuthReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr, &Timeout, &Alg)) - { - // reset timer - RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); - COPY_MAC_ADDR(pAd->MlmeAux.Bssid, Addr); - pAd->MlmeAux.Alg = Alg; - Seq = 1; - Status = MLME_SUCCESS; - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeAuthReqAction(Alg:%d) allocate memory failed\n", Alg)); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status = MLME_FAIL_NO_RESOURCE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); - return; - } - - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#1 (Alg=%d)...\n", Alg)); - MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, pAd->MlmeAux.Bssid); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11),&AuthHdr, - 2, &Alg, - 2, &Seq, - 2, &Status, - END_OF_ARGS); - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - RTMPSetTimer(&pAd->MlmeAux.AuthTimer, Timeout); - pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ2; - } - else - { - DBGPRINT_ERR(("AUTH - MlmeAuthReqAction() sanity check failed\n")); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status = MLME_INVALID_FORMAT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); - } } /* @@ -191,102 +148,130 @@ VOID MlmeAuthReqAction( ========================================================================== */ -VOID PeerAuthRspAtSeq2Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void PeerAuthRspAtSeq2Action(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Addr2[MAC_ADDR_LEN]; - USHORT Seq, Status, RemoteStatus, Alg; - UCHAR ChlgText[CIPHER_TEXT_LEN]; - UCHAR CyperChlgText[CIPHER_TEXT_LEN + 8 + 8]; - UCHAR Element[2]; - HEADER_802_11 AuthHdr; - BOOLEAN TimerCancelled; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - USHORT Status2; - - if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText)) - { - if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2) - { - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status)); - RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); - - if (Status == MLME_SUCCESS) - { - // Authentication Mode "LEAP" has allow for CCX 1.X - if ((pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen) - ) - { - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); - } - else - { - // 2. shared key, need to be challenged - Seq++; - RemoteStatus = MLME_SUCCESS; - - // Get an unused nonpaged memory - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n")); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status2 = MLME_FAIL_NO_RESOURCE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2); - return; - } - - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n")); - MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->MlmeAux.Bssid); - AuthHdr.FC.Wep = 1; - // Encrypt challenge text & auth information - RTMPInitWepEngine( - pAd, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, - pAd->StaCfg.DefaultKeyId, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen, - CyperChlgText); - - Alg = cpu2le16(*(USHORT *)&Alg); - Seq = cpu2le16(*(USHORT *)&Seq); - RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus); - - RTMPEncryptData(pAd, (PUCHAR) &Alg, CyperChlgText + 4, 2); - RTMPEncryptData(pAd, (PUCHAR) &Seq, CyperChlgText + 6, 2); - RTMPEncryptData(pAd, (PUCHAR) &RemoteStatus, CyperChlgText + 8, 2); + u8 Addr2[MAC_ADDR_LEN]; + u16 Seq, Status, RemoteStatus, Alg; + u8 ChlgText[CIPHER_TEXT_LEN]; + u8 CyperChlgText[CIPHER_TEXT_LEN + 8 + 8]; + u8 Element[2]; + struct rt_header_802_11 AuthHdr; + BOOLEAN TimerCancelled; + u8 *pOutBuffer = NULL; + int NStatus; + unsigned long FrameLen = 0; + u16 Status2; + + if (PeerAuthSanity + (pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, + (char *)ChlgText)) { + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2) { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", + Alg, Status)); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, + &TimerCancelled); + + if (Status == MLME_SUCCESS) { + /* Authentication Mode "LEAP" has allow for CCX 1.X */ + if (pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen) { + pAd->Mlme.AuthMachine.CurrState = + AUTH_REQ_IDLE; + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + MT2_AUTH_CONF, 2, &Status); + } else { + /* 2. shared key, need to be challenged */ + Seq++; + RemoteStatus = MLME_SUCCESS; + + /* Get an unused nonpaged memory */ + NStatus = + MlmeAllocateMemory(pAd, + &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n")); + pAd->Mlme.AuthMachine. + CurrState = AUTH_REQ_IDLE; + Status2 = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + MT2_AUTH_CONF, 2, + &Status2); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - Send AUTH request seq#3...\n")); + MgtMacHeaderInit(pAd, &AuthHdr, + SUBTYPE_AUTH, 0, Addr2, + pAd->MlmeAux.Bssid); + AuthHdr.FC.Wep = 1; + /* Encrypt challenge text & auth information */ + RTMPInitWepEngine(pAd, + pAd-> + SharedKey[BSS0][pAd-> + StaCfg. + DefaultKeyId]. + Key, + pAd->StaCfg. + DefaultKeyId, + pAd-> + SharedKey[BSS0][pAd-> + StaCfg. + DefaultKeyId]. + KeyLen, + CyperChlgText); + + Alg = cpu2le16(*(u16 *) & Alg); + Seq = cpu2le16(*(u16 *) & Seq); + RemoteStatus = + cpu2le16(*(u16 *) & + RemoteStatus); + + RTMPEncryptData(pAd, (u8 *)& Alg, + CyperChlgText + 4, 2); + RTMPEncryptData(pAd, (u8 *)& Seq, + CyperChlgText + 6, 2); + RTMPEncryptData(pAd, + (u8 *)& RemoteStatus, + CyperChlgText + 8, 2); Element[0] = 16; Element[1] = 128; - RTMPEncryptData(pAd, Element, CyperChlgText + 10, 2); - RTMPEncryptData(pAd, ChlgText, CyperChlgText + 12, 128); + RTMPEncryptData(pAd, Element, + CyperChlgText + 10, 2); + RTMPEncryptData(pAd, ChlgText, + CyperChlgText + 12, + 128); RTMPSetICV(pAd, CyperChlgText + 140); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &AuthHdr, - CIPHER_TEXT_LEN + 16, CyperChlgText, - END_OF_ARGS); - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT); - pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4; - } - } - else - { - pAd->StaCfg.AuthFailReason = Status; - COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); - } - } - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n")); - } + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(struct rt_header_802_11), + &AuthHdr, + CIPHER_TEXT_LEN + 16, + CyperChlgText, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, + FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pAd->MlmeAux.AuthTimer, + AUTH_TIMEOUT); + pAd->Mlme.AuthMachine.CurrState = + AUTH_WAIT_SEQ4; + } + } else { + pAd->StaCfg.AuthFailReason = Status; + COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, + MT2_AUTH_CONF, 2, &Status); + } + } + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - PeerAuthSanity() sanity check fail\n")); + } } /* @@ -297,36 +282,35 @@ VOID PeerAuthRspAtSeq2Action( ========================================================================== */ -VOID PeerAuthRspAtSeq4Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void PeerAuthRspAtSeq4Action(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Addr2[MAC_ADDR_LEN]; - USHORT Alg, Seq, Status; - CHAR ChlgText[CIPHER_TEXT_LEN]; - BOOLEAN TimerCancelled; - - if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText)) - { - if(MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 4) - { - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#4 to me\n")); - RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); - - if (Status != MLME_SUCCESS) - { - pAd->StaCfg.AuthFailReason = Status; - COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); - } - - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); - } - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq4Action() sanity check fail\n")); - } + u8 Addr2[MAC_ADDR_LEN]; + u16 Alg, Seq, Status; + char ChlgText[CIPHER_TEXT_LEN]; + BOOLEAN TimerCancelled; + + if (PeerAuthSanity + (pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, + ChlgText)) { + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 4) { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - Receive AUTH_RSP seq#4 to me\n")); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, + &TimerCancelled); + + if (Status != MLME_SUCCESS) { + pAd->StaCfg.AuthFailReason = Status; + COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); + } + + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, + 2, &Status); + } + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - PeerAuthRspAtSeq4Action() sanity check fail\n")); + } } /* @@ -337,47 +321,49 @@ VOID PeerAuthRspAtSeq4Action( ========================================================================== */ -VOID MlmeDeauthReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void MlmeDeauthReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - MLME_DEAUTH_REQ_STRUCT *pInfo; - HEADER_802_11 DeauthHdr; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - USHORT Status; - - pInfo = (MLME_DEAUTH_REQ_STRUCT *)Elem->Msg; - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeDeauthReqAction() allocate memory fail\n")); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status = MLME_FAIL_NO_RESOURCE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status); - return; - } - - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send DE-AUTH request (Reason=%d)...\n", pInfo->Reason)); - MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, pAd->MlmeAux.Bssid); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11),&DeauthHdr, - 2, &pInfo->Reason, - END_OF_ARGS); - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + struct rt_mlme_deauth_req *pInfo; + struct rt_header_802_11 DeauthHdr; + u8 *pOutBuffer = NULL; + int NStatus; + unsigned long FrameLen = 0; + u16 Status; + + pInfo = (struct rt_mlme_deauth_req *)Elem->Msg; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - MlmeDeauthReqAction() allocate memory fail\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, + &Status); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - Send DE-AUTH request (Reason=%d)...\n", + pInfo->Reason)); + MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, + pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(struct rt_header_802_11), + &DeauthHdr, 2, &pInfo->Reason, END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); - pAd->StaCfg.DeauthReason = pInfo->Reason; - COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pInfo->Addr); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status = MLME_SUCCESS; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status); + pAd->StaCfg.DeauthReason = pInfo->Reason; + COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pInfo->Addr); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status); - // send wireless event - for deauthentication + /* send wireless event - for deauthentication */ if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, + pAd->MacTab.Content[BSSID_WCID].Addr, + BSS0, 0); } /* @@ -388,15 +374,13 @@ VOID MlmeDeauthReqAction( ========================================================================== */ -VOID AuthTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void AuthTimeoutAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - AuthTimeoutAction\n")); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status = MLME_REJ_TIMEOUT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + u16 Status; + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - AuthTimeoutAction\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_REJ_TIMEOUT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); } /* @@ -407,15 +391,15 @@ VOID AuthTimeoutAction( ========================================================================== */ -VOID InvalidStateWhenAuth( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void InvalidStateWhenAuth(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", pAd->Mlme.AuthMachine.CurrState)); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + u16 Status; + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", + pAd->Mlme.AuthMachine.CurrState)); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); } /* @@ -430,31 +414,104 @@ VOID InvalidStateWhenAuth( ========================================================================== */ -VOID Cls2errAction( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr) +void Cls2errAction(struct rt_rtmp_adapter *pAd, u8 *pAddr) { - HEADER_802_11 DeauthHdr; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - USHORT Reason = REASON_CLS2ERR; - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - return; - - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Class 2 error, Send DEAUTH frame...\n")); - MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pAddr, pAd->MlmeAux.Bssid); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11),&DeauthHdr, - 2, &Reason, - END_OF_ARGS); - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + struct rt_header_802_11 DeauthHdr; + u8 *pOutBuffer = NULL; + int NStatus; + unsigned long FrameLen = 0; + u16 Reason = REASON_CLS2ERR; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - Class 2 error, Send DEAUTH frame...\n")); + MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pAddr, + pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(struct rt_header_802_11), + &DeauthHdr, 2, &Reason, END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); - pAd->StaCfg.DeauthReason = Reason; - COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pAddr); + pAd->StaCfg.DeauthReason = Reason; + COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pAddr); } +BOOLEAN AUTH_ReqSend(struct rt_rtmp_adapter *pAd, + struct rt_mlme_queue_elem *pElem, + struct rt_ralink_timer *pAuthTimer, + char *pSMName, + u16 SeqNo, + u8 *pNewElement, unsigned long ElementLen) +{ + u16 Alg, Seq, Status; + u8 Addr[6]; + unsigned long Timeout; + struct rt_header_802_11 AuthHdr; + BOOLEAN TimerCancelled; + int NStatus; + u8 *pOutBuffer = NULL; + unsigned long FrameLen = 0, tmp = 0; + + /* Block all authentication request durning WPA block period */ + if (pAd->StaCfg.bBlockAssoc == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s - Block Auth request durning WPA block period!\n", + pSMName)); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, + &Status); + } else + if (MlmeAuthReqSanity + (pAd, pElem->Msg, pElem->MsgLen, Addr, &Timeout, &Alg)) { + /* reset timer */ + RTMPCancelTimer(pAuthTimer, &TimerCancelled); + + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, Addr); + pAd->MlmeAux.Alg = Alg; + Seq = SeqNo; + Status = MLME_SUCCESS; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s - MlmeAuthReqAction(Alg:%d) allocate memory failed\n", + pSMName, Alg)); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, + 2, &Status); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("%s - Send AUTH request seq#1 (Alg=%d)...\n", pSMName, + Alg)); + MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, + pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(struct rt_header_802_11), + &AuthHdr, 2, &Alg, 2, &Seq, 2, &Status, + END_OF_ARGS); + + if (pNewElement && ElementLen) { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + ElementLen, pNewElement, END_OF_ARGS); + FrameLen += tmp; + } + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(pAuthTimer, Timeout); + return TRUE; + } else { + DBGPRINT_ERR(("%s - MlmeAuthReqAction() sanity check failed\n", + pSMName)); + return FALSE; + } + return TRUE; +} diff --git a/drivers/staging/rt2860/sta/auth_rsp.c b/drivers/staging/rt2860/sta/auth_rsp.c index cc639b1c6c136b7179f90bf9b3fc88656756680a..5b018b7573088b07b2d3f2bfa707fd882deceb6f 100644 --- a/drivers/staging/rt2860/sta/auth_rsp.c +++ b/drivers/staging/rt2860/sta/auth_rsp.c @@ -47,18 +47,21 @@ ========================================================================== */ -VOID AuthRspStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN PSTATE_MACHINE Sm, - IN STATE_MACHINE_FUNC Trans[]) +void AuthRspStateMachineInit(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *Sm, + IN STATE_MACHINE_FUNC Trans[]) { - StateMachineInit(Sm, Trans, MAX_AUTH_RSP_STATE, MAX_AUTH_RSP_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_RSP_IDLE, AUTH_RSP_MACHINE_BASE); + StateMachineInit(Sm, Trans, MAX_AUTH_RSP_STATE, MAX_AUTH_RSP_MSG, + (STATE_MACHINE_FUNC) Drop, AUTH_RSP_IDLE, + AUTH_RSP_MACHINE_BASE); - // column 1 - StateMachineSetAction(Sm, AUTH_RSP_IDLE, MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)PeerDeauthAction); + /* column 1 */ + StateMachineSetAction(Sm, AUTH_RSP_IDLE, MT2_PEER_DEAUTH, + (STATE_MACHINE_FUNC) PeerDeauthAction); - // column 2 - StateMachineSetAction(Sm, AUTH_RSP_WAIT_CHAL, MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)PeerDeauthAction); + /* column 2 */ + StateMachineSetAction(Sm, AUTH_RSP_WAIT_CHAL, MT2_PEER_DEAUTH, + (STATE_MACHINE_FUNC) PeerDeauthAction); } @@ -70,39 +73,32 @@ VOID AuthRspStateMachineInit( ========================================================================== */ -VOID PeerAuthSimpleRspGenAndSend( - IN PRTMP_ADAPTER pAd, - IN PHEADER_802_11 pHdr80211, - IN USHORT Alg, - IN USHORT Seq, - IN USHORT Reason, - IN USHORT Status) +void PeerAuthSimpleRspGenAndSend(struct rt_rtmp_adapter *pAd, + struct rt_header_802_11 * pHdr80211, + u16 Alg, + u16 Seq, + u16 Reason, u16 Status) { - HEADER_802_11 AuthHdr; - ULONG FrameLen = 0; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - - if (Reason != MLME_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("Peer AUTH fail...\n")); - return; - } - - //Get an unused nonpaged memory - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); - if (NStatus != NDIS_STATUS_SUCCESS) - return; - - DBGPRINT(RT_DEBUG_TRACE, ("Send AUTH response (seq#2)...\n")); - MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, pHdr80211->Addr2, pAd->MlmeAux.Bssid); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &AuthHdr, - 2, &Alg, - 2, &Seq, - 2, &Reason, - END_OF_ARGS); - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + struct rt_header_802_11 AuthHdr; + unsigned long FrameLen = 0; + u8 *pOutBuffer = NULL; + int NStatus; + + if (Reason != MLME_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, ("Peer AUTH fail...\n")); + return; + } + /*Get an unused nonpaged memory */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("Send AUTH response (seq#2)...\n")); + MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, pHdr80211->Addr2, + pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(struct rt_header_802_11), + &AuthHdr, 2, &Alg, 2, &Seq, 2, &Reason, END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } @@ -114,35 +110,33 @@ VOID PeerAuthSimpleRspGenAndSend( ========================================================================== */ -VOID PeerDeauthAction( - IN PRTMP_ADAPTER pAd, - IN PMLME_QUEUE_ELEM Elem) +void PeerDeauthAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Addr2[MAC_ADDR_LEN]; - USHORT Reason; - - if (PeerDeauthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) - { - if (INFRA_ON(pAd) && MAC_ADDR_EQUAL(Addr2, pAd->CommonCfg.Bssid)) - { - DBGPRINT(RT_DEBUG_TRACE,("AUTH_RSP - receive DE-AUTH from our AP (Reason=%d)\n", Reason)); - - { - union iwreq_data wrqu; - memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); - wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); - } - - // send wireless event - for deauthentication + u8 Addr2[MAC_ADDR_LEN]; + u16 Reason; + + if (PeerDeauthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) { + if (INFRA_ON(pAd) + && MAC_ADDR_EQUAL(Addr2, pAd->CommonCfg.Bssid) + ) { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH_RSP - receive DE-AUTH from our AP (Reason=%d)\n", + Reason)); + + RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, + 0); + + /* send wireless event - for deauthentication */ if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - - LinkDown(pAd, TRUE); - } - } - else - { - DBGPRINT(RT_DEBUG_TRACE,("AUTH_RSP - PeerDeauthAction() sanity check fail\n")); - } + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, + pAd->MacTab. + Content[BSSID_WCID].Addr, + BSS0, 0); + + LinkDown(pAd, TRUE); + } + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH_RSP - PeerDeauthAction() sanity check fail\n")); + } } - diff --git a/drivers/staging/rt2860/sta/connect.c b/drivers/staging/rt2860/sta/connect.c index 7bc75ab971f95a47df6d2f42d3c06d57f375fa03..17e59ba3d80712fd207fe8d80327af995ebc23c8 100644 --- a/drivers/staging/rt2860/sta/connect.c +++ b/drivers/staging/rt2860/sta/connect.c @@ -36,34 +36,39 @@ */ #include "../rt_config.h" -UCHAR CipherSuiteWpaNoneTkip[] = { - 0x00, 0x50, 0xf2, 0x01, // oui - 0x01, 0x00, // Version - 0x00, 0x50, 0xf2, 0x02, // Multicast - 0x01, 0x00, // Number of unicast - 0x00, 0x50, 0xf2, 0x02, // unicast - 0x01, 0x00, // number of authentication method - 0x00, 0x50, 0xf2, 0x00 // authentication - }; -UCHAR CipherSuiteWpaNoneTkipLen = (sizeof(CipherSuiteWpaNoneTkip) / sizeof(UCHAR)); - -UCHAR CipherSuiteWpaNoneAes[] = { - 0x00, 0x50, 0xf2, 0x01, // oui - 0x01, 0x00, // Version - 0x00, 0x50, 0xf2, 0x04, // Multicast - 0x01, 0x00, // Number of unicast - 0x00, 0x50, 0xf2, 0x04, // unicast - 0x01, 0x00, // number of authentication method - 0x00, 0x50, 0xf2, 0x00 // authentication - }; -UCHAR CipherSuiteWpaNoneAesLen = (sizeof(CipherSuiteWpaNoneAes) / sizeof(UCHAR)); - -// The following MACRO is called after 1. starting an new IBSS, 2. succesfully JOIN an IBSS, -// or 3. succesfully ASSOCIATE to a BSS, 4. successfully RE_ASSOCIATE to a BSS -// All settings successfuly negotiated furing MLME state machines become final settings -// and are copied to pAd->StaActive +u8 CipherSuiteWpaNoneTkip[] = { + 0x00, 0x50, 0xf2, 0x01, /* oui */ + 0x01, 0x00, /* Version */ + 0x00, 0x50, 0xf2, 0x02, /* Multicast */ + 0x01, 0x00, /* Number of unicast */ + 0x00, 0x50, 0xf2, 0x02, /* unicast */ + 0x01, 0x00, /* number of authentication method */ + 0x00, 0x50, 0xf2, 0x00 /* authentication */ +}; + +u8 CipherSuiteWpaNoneTkipLen = + (sizeof(CipherSuiteWpaNoneTkip) / sizeof(u8)); + +u8 CipherSuiteWpaNoneAes[] = { + 0x00, 0x50, 0xf2, 0x01, /* oui */ + 0x01, 0x00, /* Version */ + 0x00, 0x50, 0xf2, 0x04, /* Multicast */ + 0x01, 0x00, /* Number of unicast */ + 0x00, 0x50, 0xf2, 0x04, /* unicast */ + 0x01, 0x00, /* number of authentication method */ + 0x00, 0x50, 0xf2, 0x00 /* authentication */ +}; + +u8 CipherSuiteWpaNoneAesLen = + (sizeof(CipherSuiteWpaNoneAes) / sizeof(u8)); + +/* The following MACRO is called after 1. starting an new IBSS, 2. succesfully JOIN an IBSS, */ +/* or 3. succesfully ASSOCIATE to a BSS, 4. successfully RE_ASSOCIATE to a BSS */ +/* All settings successfuly negotiated furing MLME state machines become final settings */ +/* and are copied to pAd->StaActive */ #define COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \ { \ + NdisZeroMemory((_pAd)->CommonCfg.Ssid, MAX_LEN_OF_SSID); \ (_pAd)->CommonCfg.SsidLen = (_pAd)->MlmeAux.SsidLen; \ NdisMoveMemory((_pAd)->CommonCfg.Ssid, (_pAd)->MlmeAux.Ssid, (_pAd)->MlmeAux.SsidLen); \ COPY_MAC_ADDR((_pAd)->CommonCfg.Bssid, (_pAd)->MlmeAux.Bssid); \ @@ -79,9 +84,9 @@ UCHAR CipherSuiteWpaNoneAesLen = (sizeof(CipherSuiteWpaNoneAes) / sizeof(UCHAR)) NdisMoveMemory((_pAd)->StaActive.SupRate, (_pAd)->MlmeAux.SupRate, (_pAd)->MlmeAux.SupRateLen);\ (_pAd)->StaActive.ExtRateLen = (_pAd)->MlmeAux.ExtRateLen; \ NdisMoveMemory((_pAd)->StaActive.ExtRate, (_pAd)->MlmeAux.ExtRate, (_pAd)->MlmeAux.ExtRateLen);\ - NdisMoveMemory(&(_pAd)->CommonCfg.APEdcaParm, &(_pAd)->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));\ - NdisMoveMemory(&(_pAd)->CommonCfg.APQosCapability, &(_pAd)->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));\ - NdisMoveMemory(&(_pAd)->CommonCfg.APQbssLoad, &(_pAd)->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));\ + NdisMoveMemory(&(_pAd)->CommonCfg.APEdcaParm, &(_pAd)->MlmeAux.APEdcaParm, sizeof(struct rt_edca_parm));\ + NdisMoveMemory(&(_pAd)->CommonCfg.APQosCapability, &(_pAd)->MlmeAux.APQosCapability, sizeof(struct rt_qos_capability_parm));\ + NdisMoveMemory(&(_pAd)->CommonCfg.APQbssLoad, &(_pAd)->MlmeAux.APQbssLoad, sizeof(struct rt_qbss_load_parm));\ COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].Addr, (_pAd)->MlmeAux.Bssid); \ (_pAd)->MacTab.Content[BSSID_WCID].Aid = (_pAd)->MlmeAux.Aid; \ (_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = (_pAd)->StaCfg.PairCipher;\ @@ -97,13 +102,11 @@ UCHAR CipherSuiteWpaNoneAesLen = (sizeof(CipherSuiteWpaNoneAes) / sizeof(UCHAR)) ========================================================================== */ -VOID MlmeCntlInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]) +void MlmeCntlInit(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *S, OUT STATE_MACHINE_FUNC Trans[]) { - // Control state machine differs from other state machines, the interface - // follows the standard interface + /* Control state machine differs from other state machines, the interface */ + /* follows the standard interface */ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; } @@ -115,118 +118,108 @@ VOID MlmeCntlInit( ========================================================================== */ -VOID MlmeCntlMachinePerformAction( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - IN MLME_QUEUE_ELEM *Elem) +void MlmeCntlMachinePerformAction(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *S, + struct rt_mlme_queue_elem *Elem) { - switch(pAd->Mlme.CntlMachine.CurrState) - { - case CNTL_IDLE: - { - CntlIdleProc(pAd, Elem); - } - break; - case CNTL_WAIT_DISASSOC: - CntlWaitDisassocProc(pAd, Elem); - break; - case CNTL_WAIT_JOIN: - CntlWaitJoinProc(pAd, Elem); - break; - - // CNTL_WAIT_REASSOC is the only state in CNTL machine that does - // not triggered directly or indirectly by "RTMPSetInformation(OID_xxx)". - // Therefore not protected by NDIS's "only one outstanding OID request" - // rule. Which means NDIS may SET OID in the middle of ROAMing attempts. - // Current approach is to block new SET request at RTMPSetInformation() - // when CntlMachine.CurrState is not CNTL_IDLE - case CNTL_WAIT_REASSOC: - CntlWaitReassocProc(pAd, Elem); - break; - - case CNTL_WAIT_START: - CntlWaitStartProc(pAd, Elem); - break; - case CNTL_WAIT_AUTH: - CntlWaitAuthProc(pAd, Elem); - break; - case CNTL_WAIT_AUTH2: - CntlWaitAuthProc2(pAd, Elem); - break; - case CNTL_WAIT_ASSOC: - CntlWaitAssocProc(pAd, Elem); - break; + switch (pAd->Mlme.CntlMachine.CurrState) { + case CNTL_IDLE: + CntlIdleProc(pAd, Elem); + break; + case CNTL_WAIT_DISASSOC: + CntlWaitDisassocProc(pAd, Elem); + break; + case CNTL_WAIT_JOIN: + CntlWaitJoinProc(pAd, Elem); + break; + + /* CNTL_WAIT_REASSOC is the only state in CNTL machine that does */ + /* not triggered directly or indirectly by "RTMPSetInformation(OID_xxx)". */ + /* Therefore not protected by NDIS's "only one outstanding OID request" */ + /* rule. Which means NDIS may SET OID in the middle of ROAMing attempts. */ + /* Current approach is to block new SET request at RTMPSetInformation() */ + /* when CntlMachine.CurrState is not CNTL_IDLE */ + case CNTL_WAIT_REASSOC: + CntlWaitReassocProc(pAd, Elem); + break; + + case CNTL_WAIT_START: + CntlWaitStartProc(pAd, Elem); + break; + case CNTL_WAIT_AUTH: + CntlWaitAuthProc(pAd, Elem); + break; + case CNTL_WAIT_AUTH2: + CntlWaitAuthProc2(pAd, Elem); + break; + case CNTL_WAIT_ASSOC: + CntlWaitAssocProc(pAd, Elem); + break; + + case CNTL_WAIT_OID_LIST_SCAN: + if (Elem->MsgType == MT2_SCAN_CONF) { + /* Resume TxRing after SCANING complete. We hope the out-of-service time */ + /* won't be too long to let upper layer time-out the waiting frames */ + RTMPResumeMsduTransmission(pAd); - case CNTL_WAIT_OID_LIST_SCAN: - if(Elem->MsgType == MT2_SCAN_CONF) - { - // Resume TxRing after SCANING complete. We hope the out-of-service time - // won't be too long to let upper layer time-out the waiting frames - RTMPResumeMsduTransmission(pAd); - if (pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) - { - // Cisco scan request is finished, prepare beacon report - MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL); - } - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - // - // Set LED status to previous status. - // - if (pAd->bLedOnScanning) - { - pAd->bLedOnScanning = FALSE; - RTMPSetLED(pAd, pAd->LedStatus); - } + /* */ + /* Set LED status to previous status. */ + /* */ + if (pAd->bLedOnScanning) { + pAd->bLedOnScanning = FALSE; + RTMPSetLED(pAd, pAd->LedStatus); } - break; + } + break; - case CNTL_WAIT_OID_DISASSOC: - if (Elem->MsgType == MT2_DISASSOC_CONF) - { - LinkDown(pAd, FALSE); - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - } - break; -#ifdef RT2870 - // - // This state is for that we want to connect to an AP but - // it didn't find on BSS List table. So we need to scan the air first, - // after that we can try to connect to the desired AP if available. - // - case CNTL_WAIT_SCAN_FOR_CONNECT: - if(Elem->MsgType == MT2_SCAN_CONF) - { - // Resume TxRing after SCANING complete. We hope the out-of-service time - // won't be too long to let upper layer time-out the waiting frames - RTMPResumeMsduTransmission(pAd); + case CNTL_WAIT_OID_DISASSOC: + if (Elem->MsgType == MT2_DISASSOC_CONF) { + LinkDown(pAd, FALSE); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + } + break; +#ifdef RTMP_MAC_USB + /* */ + /* This state is for that we want to connect to an AP but */ + /* it didn't find on BSS List table. So we need to scan the air first, */ + /* after that we can try to connect to the desired AP if available. */ + /* */ + case CNTL_WAIT_SCAN_FOR_CONNECT: + if (Elem->MsgType == MT2_SCAN_CONF) { + /* Resume TxRing after SCANING complete. We hope the out-of-service time */ + /* won't be too long to let upper layer time-out the waiting frames */ + RTMPResumeMsduTransmission(pAd); #ifdef CCX_SUPPORT - if (pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) - { - // Cisco scan request is finished, prepare beacon report - MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL); - } -#endif // CCX_SUPPORT // - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + if (pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) { + /* Cisco scan request is finished, prepare beacon report */ + MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, + MT2_AIRONET_SCAN_DONE, 0, NULL); + } +#endif /* CCX_SUPPORT // */ + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - // - // Check if we can connect to. - // - BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); - if (pAd->MlmeAux.SsidBssTab.BssNr > 0) - { - MlmeAutoReconnectLastSSID(pAd); - } + /* */ + /* Check if we can connect to. */ + /* */ + BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, + (char *) pAd->MlmeAux. + AutoReconnectSsid, + pAd->MlmeAux.AutoReconnectSsidLen); + if (pAd->MlmeAux.SsidBssTab.BssNr > 0) { + MlmeAutoReconnectLastSSID(pAd); } - break; -#endif // RT2870 // - default: - DBGPRINT_ERR(("!ERROR! CNTL - Illegal message type(=%ld)", Elem->MsgType)); - break; + } + break; +#endif /* RTMP_MAC_USB // */ + default: + DBGPRINT_ERR(("ERROR! CNTL - Illegal message type(=%ld)", + Elem->MsgType)); + break; } } - /* ========================================================================== Description: @@ -235,92 +228,95 @@ VOID MlmeCntlMachinePerformAction( ========================================================================== */ -VOID CntlIdleProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void CntlIdleProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - MLME_DISASSOC_REQ_STRUCT DisassocReq; + struct rt_mlme_disassoc_req DisassocReq; if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) return; - switch(Elem->MsgType) - { - case OID_802_11_SSID: - CntlOidSsidProc(pAd, Elem); - break; + switch (Elem->MsgType) { + case OID_802_11_SSID: + CntlOidSsidProc(pAd, Elem); + break; - case OID_802_11_BSSID: - CntlOidRTBssidProc(pAd,Elem); - break; + case OID_802_11_BSSID: + CntlOidRTBssidProc(pAd, Elem); + break; - case OID_802_11_BSSID_LIST_SCAN: - CntlOidScanProc(pAd,Elem); - break; + case OID_802_11_BSSID_LIST_SCAN: + CntlOidScanProc(pAd, Elem); + break; - case OID_802_11_DISASSOCIATE: - DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; - - if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_ENABLE_WITH_WEB_UI) - { - // Set the AutoReconnectSsid to prevent it reconnect to old SSID - // Since calling this indicate user don't want to connect to that SSID anymore. - pAd->MlmeAux.AutoReconnectSsidLen= 32; - NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); - } - break; + case OID_802_11_DISASSOCIATE: + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, + REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof(struct rt_mlme_disassoc_req), &DisassocReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; + + if (pAd->StaCfg.WpaSupplicantUP != + WPA_SUPPLICANT_ENABLE_WITH_WEB_UI) { + /* Set the AutoReconnectSsid to prevent it reconnect to old SSID */ + /* Since calling this indicate user don't want to connect to that SSID anymore. */ + pAd->MlmeAux.AutoReconnectSsidLen = 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, + pAd->MlmeAux.AutoReconnectSsidLen); + } + break; - case MT2_MLME_ROAMING_REQ: - CntlMlmeRoamingProc(pAd, Elem); - break; + case MT2_MLME_ROAMING_REQ: + CntlMlmeRoamingProc(pAd, Elem); + break; - case OID_802_11_MIC_FAILURE_REPORT_FRAME: - WpaMicFailureReportFrame(pAd, Elem); - break; + case OID_802_11_MIC_FAILURE_REPORT_FRAME: + WpaMicFailureReportFrame(pAd, Elem); + break; - default: - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Illegal message in CntlIdleProc(MsgType=%ld)\n",Elem->MsgType)); - break; + default: + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Illegal message in CntlIdleProc(MsgType=%ld)\n", + Elem->MsgType)); + break; } } -VOID CntlOidScanProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void CntlOidScanProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - MLME_SCAN_REQ_STRUCT ScanReq; - ULONG BssIdx = BSS_NOT_FOUND; - BSS_ENTRY CurrBss; - - // record current BSS if network is connected. - // 2003-2-13 do not include current IBSS if this is the only STA in this IBSS. - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - BssIdx = BssSsidTableSearch(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->CommonCfg.Channel); - if (BssIdx != BSS_NOT_FOUND) - { - NdisMoveMemory(&CurrBss, &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY)); + struct rt_mlme_scan_req ScanReq; + unsigned long BssIdx = BSS_NOT_FOUND; + struct rt_bss_entry CurrBss; + + /* record current BSS if network is connected. */ + /* 2003-2-13 do not include current IBSS if this is the only STA in this IBSS. */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { + BssIdx = + BssSsidTableSearch(&pAd->ScanTab, pAd->CommonCfg.Bssid, + (u8 *)pAd->CommonCfg.Ssid, + pAd->CommonCfg.SsidLen, + pAd->CommonCfg.Channel); + if (BssIdx != BSS_NOT_FOUND) { + NdisMoveMemory(&CurrBss, &pAd->ScanTab.BssEntry[BssIdx], + sizeof(struct rt_bss_entry)); } } - - // clean up previous SCAN result, add current BSS back to table if any + /* clean up previous SCAN result, add current BSS back to table if any */ BssTableInit(&pAd->ScanTab); - if (BssIdx != BSS_NOT_FOUND) - { - // DDK Note: If the NIC is associated with a particular BSSID and SSID - // that are not contained in the list of BSSIDs generated by this scan, the - // BSSID description of the currently associated BSSID and SSID should be - // appended to the list of BSSIDs in the NIC's database. - // To ensure this, we append this BSS as the first entry in SCAN result - NdisMoveMemory(&pAd->ScanTab.BssEntry[0], &CurrBss, sizeof(BSS_ENTRY)); + if (BssIdx != BSS_NOT_FOUND) { + /* DDK Note: If the NIC is associated with a particular BSSID and SSID */ + /* that are not contained in the list of BSSIDs generated by this scan, the */ + /* BSSID description of the currently associated BSSID and SSID should be */ + /* appended to the list of BSSIDs in the NIC's database. */ + /* To ensure this, we append this BSS as the first entry in SCAN result */ + NdisMoveMemory(&pAd->ScanTab.BssEntry[0], &CurrBss, + sizeof(struct rt_bss_entry)); pAd->ScanTab.BssNr = 1; } - ScanParmFill(pAd, &ScanReq, "", 0, BSS_ANY, SCAN_ACTIVE); + ScanParmFill(pAd, &ScanReq, (char *)Elem->Msg, Elem->MsgLen, BSS_ANY, + SCAN_ACTIVE); MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, - sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + sizeof(struct rt_mlme_scan_req), &ScanReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; } @@ -333,171 +329,174 @@ VOID CntlOidScanProc( ========================================================================== */ -VOID CntlOidSsidProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM * Elem) +void CntlOidSsidProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - PNDIS_802_11_SSID pOidSsid = (NDIS_802_11_SSID *)Elem->Msg; - MLME_DISASSOC_REQ_STRUCT DisassocReq; - ULONG Now; - -#ifdef RT2860 - // BBP and RF are not accessible in PS mode, we has to wake them up first - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - AsicForceWakeup(pAd, RTMP_HALT); -#endif + struct rt_ndis_802_11_ssid * pOidSsid = (struct rt_ndis_802_11_ssid *) Elem->Msg; + struct rt_mlme_disassoc_req DisassocReq; + unsigned long Now; - // Step 1. record the desired user settings to MlmeAux + /* Step 1. record the desired user settings to MlmeAux */ NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); NdisMoveMemory(pAd->MlmeAux.Ssid, pOidSsid->Ssid, pOidSsid->SsidLength); - pAd->MlmeAux.SsidLen = (UCHAR)pOidSsid->SsidLength; + pAd->MlmeAux.SsidLen = (u8)pOidSsid->SsidLength; NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN); pAd->MlmeAux.BssType = pAd->StaCfg.BssType; + pAd->StaCfg.bAutoConnectByBssid = FALSE; - // - // Update Reconnect Ssid, that user desired to connect. - // + /* */ + /* Update Reconnect Ssid, that user desired to connect. */ + /* */ NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); - NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen); pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen; - // step 2. find all matching BSS in the lastest SCAN result (inBssTab) - // & log them into MlmeAux.SsidBssTab for later-on iteration. Sort by RSSI order - BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + /* step 2. find all matching BSS in the lastest SCAN result (inBssTab) */ + /* & log them into MlmeAux.SsidBssTab for later-on iteration. Sort by RSSI order */ + BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, + (char *)pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - %d BSS of %d BSS match the desire (%d)SSID - %s\n", - pAd->MlmeAux.SsidBssTab.BssNr, pAd->ScanTab.BssNr, pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid)); + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():CNTL - %d BSS of %d BSS match the desire (%d)SSID - %s\n", + pAd->MlmeAux.SsidBssTab.BssNr, pAd->ScanTab.BssNr, + pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid)); NdisGetSystemUpTime(&Now); if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && - (pAd->CommonCfg.SsidLen == pAd->MlmeAux.SsidBssTab.BssEntry[0].SsidLen) && - NdisEqualMemory(pAd->CommonCfg.Ssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Ssid, pAd->CommonCfg.SsidLen) && - MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Bssid)) - { - // Case 1. already connected with an AP who has the desired SSID - // with highest RSSI - - // Add checking Mode "LEAP" for CCX 1.0 + (pAd->CommonCfg.SsidLen == + pAd->MlmeAux.SsidBssTab.BssEntry[0].SsidLen) + && NdisEqualMemory(pAd->CommonCfg.Ssid, + pAd->MlmeAux.SsidBssTab.BssEntry[0].Ssid, + pAd->CommonCfg.SsidLen) + && MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, + pAd->MlmeAux.SsidBssTab.BssEntry[0].Bssid)) { + /* Case 1. already connected with an AP who has the desired SSID */ + /* with highest RSSI */ + + /* Add checking Mode "LEAP" for CCX 1.0 */ if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) - ) && - (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) - { - // case 1.1 For WPA, WPA-PSK, if the 1x port is not secured, we have to redo - // connection process - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP...\n")); - DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, - sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + ) && + (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) { + /* case 1.1 For WPA, WPA-PSK, if the 1x port is not secured, we have to redo */ + /* connection process */ + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():CNTL - disassociate with current AP...\n")); + DisassocParmFill(pAd, &DisassocReq, + pAd->CommonCfg.Bssid, + REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_DISASSOC_REQ, + sizeof(struct rt_mlme_disassoc_req), + &DisassocReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; - } - else if (pAd->bConfigChanged == TRUE) - { - // case 1.2 Important Config has changed, we have to reconnect to the same AP - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP Because config changed...\n")); - DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, - sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + } else if (pAd->bConfigChanged == TRUE) { + /* case 1.2 Important Config has changed, we have to reconnect to the same AP */ + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():CNTL - disassociate with current AP Because config changed...\n")); + DisassocParmFill(pAd, &DisassocReq, + pAd->CommonCfg.Bssid, + REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_DISASSOC_REQ, + sizeof(struct rt_mlme_disassoc_req), + &DisassocReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; - } - else - { - // case 1.3. already connected to the SSID with highest RSSI. - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - already with this BSSID. ignore this SET_SSID request\n")); - // - // (HCT 12.1) 1c_wlan_mediaevents required - // media connect events are indicated when associating with the same AP - // - if (INFRA_ON(pAd)) - { - // - // Since MediaState already is NdisMediaStateConnected - // We just indicate the connect event again to meet the WHQL required. - // - pAd->IndicateMediaState = NdisMediaStateConnected; + } else { + /* case 1.3. already connected to the SSID with highest RSSI. */ + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():CNTL - already with this BSSID. ignore this SET_SSID request\n")); + /* */ + /* (HCT 12.1) 1c_wlan_mediaevents required */ + /* media connect events are indicated when associating with the same AP */ + /* */ + if (INFRA_ON(pAd)) { + /* */ + /* Since MediaState already is NdisMediaStateConnected */ + /* We just indicate the connect event again to meet the WHQL required. */ + /* */ + pAd->IndicateMediaState = + NdisMediaStateConnected; RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_UP; // Update extra information to link is up + pAd->ExtraInfo = GENERAL_LINK_UP; /* Update extra information to link is up */ } pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - - { - union iwreq_data wrqu; - - memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); - memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); - wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); - - } + RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, + &pAd->MlmeAux.Bssid[0], NULL, + 0); } - } - else if (INFRA_ON(pAd)) - { - // - // For RT61 - // [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: ) - // RT61 may lost SSID, and not connect to NDTEST_WEP_AP2 and will connect to NDTEST_WEP_AP2 by Autoreconnect - // But media status is connected, so the SSID not report correctly. - // - if (!SSID_EQUAL(pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen)) - { - // - // Different SSID means not Roaming case, so we let LinkDown() to Indicate a disconnect event. - // + } else if (INFRA_ON(pAd)) { + /* */ + /* For RT61 */ + /* [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: ) */ + /* RT61 may lost SSID, and not connect to NDTEST_WEP_AP2 and will connect to NDTEST_WEP_AP2 by Autoreconnect */ + /* But media status is connected, so the SSID not report correctly. */ + /* */ + if (!SSID_EQUAL + (pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, + pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen)) { + /* */ + /* Different SSID means not Roaming case, so we let LinkDown() to Indicate a disconnect event. */ + /* */ pAd->MlmeAux.CurrReqIsFromNdis = TRUE; } - // case 2. active INFRA association existent - // roaming is done within miniport driver, nothing to do with configuration - // utility. so upon a new SET(OID_802_11_SSID) is received, we just - // disassociate with the current associated AP, - // then perform a new association with this new SSID, no matter the - // new/old SSID are the same or not. - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP...\n")); - DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + /* case 2. active INFRA association existent */ + /* roaming is done within miniport driver, nothing to do with configuration */ + /* utility. so upon a new SET(OID_802_11_SSID) is received, we just */ + /* disassociate with the current associated AP, */ + /* then perform a new association with this new SSID, no matter the */ + /* new/old SSID are the same or not. */ + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():CNTL - disassociate with current AP...\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, + REASON_DISASSOC_STA_LEAVING); MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, - sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + sizeof(struct rt_mlme_disassoc_req), &DisassocReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; - } - else - { - if (ADHOC_ON(pAd)) - { - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - drop current ADHOC\n")); + } else { + if (ADHOC_ON(pAd)) { + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():CNTL - drop current ADHOC\n")); LinkDown(pAd, FALSE); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + OPSTATUS_CLEAR_FLAG(pAd, + fOP_STATUS_MEDIA_STATE_CONNECTED); pAd->IndicateMediaState = NdisMediaStateDisconnected; RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_DOWN; - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():NDIS_STATUS_MEDIA_DISCONNECT Event C!\n")); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():NDIS_STATUS_MEDIA_DISCONNECT Event C!\n")); } if ((pAd->MlmeAux.SsidBssTab.BssNr == 0) && - (pAd->StaCfg.bAutoReconnect == TRUE) && - (pAd->MlmeAux.BssType == BSS_INFRA) && - (MlmeValidateSSID(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen) == TRUE) - ) - { - MLME_SCAN_REQ_STRUCT ScanReq; - - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - No matching BSS, start a new scan\n")); - ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; - // Reset Missed scan number + (pAd->StaCfg.bAutoReconnect == TRUE) && + (pAd->MlmeAux.BssType == BSS_INFRA) && + (MlmeValidateSSID(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen) + == TRUE) + ) { + struct rt_mlme_scan_req ScanReq; + + DBGPRINT(RT_DEBUG_TRACE, + ("CntlOidSsidProc():CNTL - No matching BSS, start a new scan\n")); + ScanParmFill(pAd, &ScanReq, (char *)pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen, BSS_ANY, + SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, + sizeof(struct rt_mlme_scan_req), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = + CNTL_WAIT_OID_LIST_SCAN; + /* Reset Missed scan number */ pAd->StaCfg.LastScanTime = Now; - } - else - { + } else { pAd->MlmeAux.BssIdx = 0; IterateOnBssTab(pAd); } } } - /* ========================================================================== Description: @@ -506,165 +505,196 @@ VOID CntlOidSsidProc( ========================================================================== */ -VOID CntlOidRTBssidProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM * Elem) +void CntlOidRTBssidProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - ULONG BssIdx; - PUCHAR pOidBssid = (PUCHAR)Elem->Msg; - MLME_DISASSOC_REQ_STRUCT DisassocReq; - MLME_JOIN_REQ_STRUCT JoinReq; + unsigned long BssIdx; + u8 *pOidBssid = (u8 *)Elem->Msg; + struct rt_mlme_disassoc_req DisassocReq; + struct rt_mlme_join_req JoinReq; - // record user desired settings + /* record user desired settings */ COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pOidBssid); pAd->MlmeAux.BssType = pAd->StaCfg.BssType; - // - // Update Reconnect Ssid, that user desired to connect. - // - NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); - pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen; - NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); - - // find the desired BSS in the latest SCAN result table + /* find the desired BSS in the latest SCAN result table */ BssIdx = BssTableSearch(&pAd->ScanTab, pOidBssid, pAd->MlmeAux.Channel); - if (BssIdx == BSS_NOT_FOUND) - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - BSSID not found. reply NDIS_STATUS_NOT_ACCEPTED\n")); - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + if (BssIdx == BSS_NOT_FOUND) { + struct rt_mlme_scan_req ScanReq; + + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - BSSID not found. reply NDIS_STATUS_NOT_ACCEPTED\n")); + /*pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; */ + + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - BSSID not found. start a new scan\n")); + ScanParmFill(pAd, &ScanReq, (char *)pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, + sizeof(struct rt_mlme_scan_req), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + /* Reset Missed scan number */ + NdisGetSystemUpTime(&pAd->StaCfg.LastScanTime); return; } - - // copy the matched BSS entry from ScanTab to MlmeAux.SsidBssTab. Why? - // Because we need this entry to become the JOIN target in later on SYNC state machine + /* */ + /* Update Reconnect Ssid, that user desired to connect. */ + /* */ + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); + pAd->MlmeAux.AutoReconnectSsidLen = + pAd->ScanTab.BssEntry[BssIdx].SsidLen; + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, + pAd->ScanTab.BssEntry[BssIdx].Ssid, + pAd->ScanTab.BssEntry[BssIdx].SsidLen); + + /* copy the matched BSS entry from ScanTab to MlmeAux.SsidBssTab. Why? */ + /* Because we need this entry to become the JOIN target in later on SYNC state machine */ pAd->MlmeAux.BssIdx = 0; pAd->MlmeAux.SsidBssTab.BssNr = 1; - NdisMoveMemory(&pAd->MlmeAux.SsidBssTab.BssEntry[0], &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY)); - - // 2002-11-26 skip the following checking. i.e. if user wants to re-connect to same AP - // we just follow normal procedure. The reason of user doing this may because he/she changed - // AP to another channel, but we still received BEACON from it thus don't claim Link Down. - // Since user knows he's changed AP channel, he'll re-connect again. By skipping the following - // checking, we'll disassociate then re-do normal association with this AP at the new channel. - // 2003-1-6 Re-enable this feature based on microsoft requirement which prefer not to re-do - // connection when setting the same BSSID. - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && - MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pOidBssid)) - { - // already connected to the same BSSID, go back to idle state directly - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - already in this BSSID. ignore this SET_BSSID request\n")); - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - - { - union iwreq_data wrqu; - - memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); - memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); - wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); - - } - } - else - { - if (INFRA_ON(pAd)) - { - // disassoc from current AP first - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - disassociate with current AP ...\n")); - DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, - sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + NdisMoveMemory(&pAd->MlmeAux.SsidBssTab.BssEntry[0], + &pAd->ScanTab.BssEntry[BssIdx], sizeof(struct rt_bss_entry)); + + /* Add SSID into MlmeAux for site surey joining hidden SSID */ + pAd->MlmeAux.SsidLen = pAd->ScanTab.BssEntry[BssIdx].SsidLen; + NdisMoveMemory(pAd->MlmeAux.Ssid, pAd->ScanTab.BssEntry[BssIdx].Ssid, + pAd->MlmeAux.SsidLen); + + { + if (INFRA_ON(pAd)) { + /* disassoc from current AP first */ + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - disassociate with current AP ...\n")); + DisassocParmFill(pAd, &DisassocReq, + pAd->CommonCfg.Bssid, + REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_DISASSOC_REQ, + sizeof(struct rt_mlme_disassoc_req), + &DisassocReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; - } - else - { - if (ADHOC_ON(pAd)) - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - drop current ADHOC\n")); + } else { + if (ADHOC_ON(pAd)) { + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - drop current ADHOC\n")); LinkDown(pAd, FALSE); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); - pAd->IndicateMediaState = NdisMediaStateDisconnected; + OPSTATUS_CLEAR_FLAG(pAd, + fOP_STATUS_MEDIA_STATE_CONNECTED); + pAd->IndicateMediaState = + NdisMediaStateDisconnected; RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_DOWN; - DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event C!\n")); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, + ("NDIS_STATUS_MEDIA_DISCONNECT Event C!\n")); } - - // Change the wepstatus to original wepstatus - pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus; - pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus; + /* Change the wepstatus to original wepstatus */ + pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus; + pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus; pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus; - // Check cipher suite, AP must have more secured cipher than station setting - // Set the Pairwise and Group cipher to match the intended AP setting - // We can only connect to AP with less secured cipher setting - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) - { - pAd->StaCfg.GroupCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.GroupCipher; - - if (pAd->StaCfg.WepStatus == pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipher) - pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipher; - else if (pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipherAux != Ndis802_11WEPDisabled) - pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipherAux; - else // There is no PairCipher Aux, downgrade our capability to TKIP - pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + /* Check cipher suite, AP must have more secured cipher than station setting */ + /* Set the Pairwise and Group cipher to match the intended AP setting */ + /* We can only connect to AP with less secured cipher setting */ + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) + || (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPAPSK)) { + pAd->StaCfg.GroupCipher = + pAd->ScanTab.BssEntry[BssIdx].WPA. + GroupCipher; + + if (pAd->StaCfg.WepStatus == + pAd->ScanTab.BssEntry[BssIdx].WPA. + PairCipher) + pAd->StaCfg.PairCipher = + pAd->ScanTab.BssEntry[BssIdx].WPA. + PairCipher; + else if (pAd->ScanTab.BssEntry[BssIdx].WPA. + PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = + pAd->ScanTab.BssEntry[BssIdx].WPA. + PairCipherAux; + else /* There is no PairCipher Aux, downgrade our capability to TKIP */ + pAd->StaCfg.PairCipher = + Ndis802_11Encryption2Enabled; + } else + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) + || (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2PSK)) { + pAd->StaCfg.GroupCipher = + pAd->ScanTab.BssEntry[BssIdx].WPA2. + GroupCipher; + + if (pAd->StaCfg.WepStatus == + pAd->ScanTab.BssEntry[BssIdx].WPA2. + PairCipher) + pAd->StaCfg.PairCipher = + pAd->ScanTab.BssEntry[BssIdx].WPA2. + PairCipher; + else if (pAd->ScanTab.BssEntry[BssIdx].WPA2. + PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = + pAd->ScanTab.BssEntry[BssIdx].WPA2. + PairCipherAux; + else /* There is no PairCipher Aux, downgrade our capability to TKIP */ + pAd->StaCfg.PairCipher = + Ndis802_11Encryption2Enabled; + + /* RSN capability */ + pAd->StaCfg.RsnCapability = + pAd->ScanTab.BssEntry[BssIdx].WPA2. + RsnCapability; } - else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - pAd->StaCfg.GroupCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.GroupCipher; - - if (pAd->StaCfg.WepStatus == pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipher) - pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipher; - else if (pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipherAux != Ndis802_11WEPDisabled) - pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipherAux; - else // There is no PairCipher Aux, downgrade our capability to TKIP - pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; - - // RSN capability - pAd->StaCfg.RsnCapability = pAd->ScanTab.BssEntry[BssIdx].WPA2.RsnCapability; - } - - // Set Mix cipher flag - pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE; - if (pAd->StaCfg.bMixCipher == TRUE) - { - // If mix cipher, re-build RSNIE - RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0); - } - // No active association, join the BSS immediately - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - joining %02x:%02x:%02x:%02x:%02x:%02x ...\n", - pOidBssid[0],pOidBssid[1],pOidBssid[2],pOidBssid[3],pOidBssid[4],pOidBssid[5])); + /* Set Mix cipher flag */ + pAd->StaCfg.bMixCipher = + (pAd->StaCfg.PairCipher == + pAd->StaCfg.GroupCipher) ? FALSE : TRUE; + /*if (pAd->StaCfg.bMixCipher == TRUE) + { + // If mix cipher, re-build RSNIE + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0); + } */ + /* No active association, join the BSS immediately */ + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - joining %02x:%02x:%02x:%02x:%02x:%02x ...\n", + pOidBssid[0], pOidBssid[1], pOidBssid[2], + pOidBssid[3], pOidBssid[4], pOidBssid[5])); JoinParmFill(pAd, &JoinReq, pAd->MlmeAux.BssIdx); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT), &JoinReq); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, + sizeof(struct rt_mlme_join_req), &JoinReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN; } } } -// Roaming is the only external request triggering CNTL state machine -// despite of other "SET OID" operation. All "SET OID" related oerations -// happen in sequence, because no other SET OID will be sent to this device -// until the the previous SET operation is complete (successful o failed). -// So, how do we quarantee this ROAMING request won't corrupt other "SET OID"? -// or been corrupted by other "SET OID"? -// -// IRQL = DISPATCH_LEVEL -VOID CntlMlmeRoamingProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +/* Roaming is the only external request triggering CNTL state machine */ +/* despite of other "SET OID" operation. All "SET OID" related oerations */ +/* happen in sequence, because no other SET OID will be sent to this device */ +/* until the the previous SET operation is complete (successful o failed). */ +/* So, how do we quarantee this ROAMING request won't corrupt other "SET OID"? */ +/* or been corrupted by other "SET OID"? */ +/* */ +/* IRQL = DISPATCH_LEVEL */ +void CntlMlmeRoamingProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - // TODO: - // AP in different channel may show lower RSSI than actual value?? - // should we add a weighting factor to compensate it? - DBGPRINT(RT_DEBUG_TRACE,("CNTL - Roaming in MlmeAux.RoamTab...\n")); + u8 BBPValue = 0; - NdisMoveMemory(&pAd->MlmeAux.SsidBssTab, &pAd->MlmeAux.RoamTab, sizeof(pAd->MlmeAux.RoamTab)); - pAd->MlmeAux.SsidBssTab.BssNr = pAd->MlmeAux.RoamTab.BssNr; + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Roaming in MlmeAux.RoamTab...\n")); - BssTableSortByRssi(&pAd->MlmeAux.SsidBssTab); - pAd->MlmeAux.BssIdx = 0; - IterateOnBssTab(pAd); + { + /*Let BBP register at 20MHz to do (fast) roaming. */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + NdisMoveMemory(&pAd->MlmeAux.SsidBssTab, &pAd->MlmeAux.RoamTab, + sizeof(pAd->MlmeAux.RoamTab)); + pAd->MlmeAux.SsidBssTab.BssNr = pAd->MlmeAux.RoamTab.BssNr; + + BssTableSortByRssi(&pAd->MlmeAux.SsidBssTab); + pAd->MlmeAux.BssIdx = 0; + IterateOnBssTab(pAd); + } } /* @@ -675,34 +705,35 @@ VOID CntlMlmeRoamingProc( ========================================================================== */ -VOID CntlWaitDisassocProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void CntlWaitDisassocProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - MLME_START_REQ_STRUCT StartReq; + struct rt_mlme_start_req StartReq; - if (Elem->MsgType == MT2_DISASSOC_CONF) - { + if (Elem->MsgType == MT2_DISASSOC_CONF) { DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Dis-associate successful\n")); - if (pAd->CommonCfg.bWirelessEvent) - { - RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + if (pAd->CommonCfg.bWirelessEvent) { + RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, + pAd->MacTab.Content[BSSID_WCID]. + Addr, BSS0, 0); } LinkDown(pAd, FALSE); - // case 1. no matching BSS, and user wants ADHOC, so we just start a new one - if ((pAd->MlmeAux.SsidBssTab.BssNr==0) && (pAd->StaCfg.BssType == BSS_ADHOC)) - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - No matching BSS, start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid)); - StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq); + /* case 1. no matching BSS, and user wants ADHOC, so we just start a new one */ + if ((pAd->MlmeAux.SsidBssTab.BssNr == 0) + && (pAd->StaCfg.BssType == BSS_ADHOC)) { + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - No matching BSS, start a new ADHOC (Ssid=%s)...\n", + pAd->MlmeAux.Ssid)); + StartParmFill(pAd, &StartReq, (char *)pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, + sizeof(struct rt_mlme_start_req), &StartReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; } - // case 2. try each matched BSS - else - { + /* case 2. try each matched BSS */ + else { pAd->MlmeAux.BssIdx = 0; IterateOnBssTab(pAd); @@ -718,74 +749,81 @@ VOID CntlWaitDisassocProc( ========================================================================== */ -VOID CntlWaitJoinProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void CntlWaitJoinProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Reason; - MLME_AUTH_REQ_STRUCT AuthReq; - - if (Elem->MsgType == MT2_JOIN_CONF) - { - NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); - if (Reason == MLME_SUCCESS) - { - // 1. joined an IBSS, we are pretty much done here - if (pAd->MlmeAux.BssType == BSS_ADHOC) - { - // - // 5G bands rules of Japan: - // Ad hoc must be disabled in W53(ch52,56,60,64) channels. - // - if ( (pAd->CommonCfg.bIEEE80211H == 1) && - RadarChannelCheck(pAd, pAd->CommonCfg.Channel) - ) - { - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Channel=%d, Join adhoc on W53(52,56,60,64) Channels are not accepted\n", pAd->CommonCfg.Channel)); + u16 Reason; + struct rt_mlme_auth_req AuthReq; + + if (Elem->MsgType == MT2_JOIN_CONF) { + NdisMoveMemory(&Reason, Elem->Msg, sizeof(u16)); + if (Reason == MLME_SUCCESS) { + /* 1. joined an IBSS, we are pretty much done here */ + if (pAd->MlmeAux.BssType == BSS_ADHOC) { + /* */ + /* 5G bands rules of Japan: */ + /* Ad hoc must be disabled in W53(ch52,56,60,64) channels. */ + /* */ + if ((pAd->CommonCfg.bIEEE80211H == 1) && + RadarChannelCheck(pAd, + pAd->CommonCfg.Channel) + ) { + pAd->Mlme.CntlMachine.CurrState = + CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Channel=%d, Join adhoc on W53(52,56,60,64) Channels are not accepted\n", + pAd->CommonCfg.Channel)); return; } LinkUp(pAd, BSS_ADHOC); pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - join the IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n", - pAd->CommonCfg.Bssid[0],pAd->CommonCfg.Bssid[1],pAd->CommonCfg.Bssid[2], - pAd->CommonCfg.Bssid[3],pAd->CommonCfg.Bssid[4],pAd->CommonCfg.Bssid[5])); - - pAd->IndicateMediaState = NdisMediaStateConnected; - pAd->ExtraInfo = GENERAL_LINK_UP; + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - join the IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n", + pAd->CommonCfg.Bssid[0], + pAd->CommonCfg.Bssid[1], + pAd->CommonCfg.Bssid[2], + pAd->CommonCfg.Bssid[3], + pAd->CommonCfg.Bssid[4], + pAd->CommonCfg.Bssid[5])); + + pAd->IndicateMediaState = + NdisMediaStateConnected; + pAd->ExtraInfo = GENERAL_LINK_UP; } - // 2. joined a new INFRA network, start from authentication - else - { + /* 2. joined a new INFRA network, start from authentication */ + else { { - // either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch)) - { - AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeShared); - } - else - { - AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen); + /* either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first */ + if ((pAd->StaCfg.AuthMode == + Ndis802_11AuthModeShared) + || (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeAutoSwitch)) { + AuthParmFill(pAd, &AuthReq, + pAd->MlmeAux.Bssid, + AUTH_MODE_KEY); + } else { + AuthParmFill(pAd, &AuthReq, + pAd->MlmeAux.Bssid, + AUTH_MODE_OPEN); } + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, + MT2_MLME_AUTH_REQ, + sizeof + (struct rt_mlme_auth_req), + &AuthReq); } - MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ, - sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH; + pAd->Mlme.CntlMachine.CurrState = + CNTL_WAIT_AUTH; } - } - else - { - // 3. failed, try next BSS + } else { + /* 3. failed, try next BSS */ pAd->MlmeAux.BssIdx++; IterateOnBssTab(pAd); } } } - /* ========================================================================== Description: @@ -794,74 +832,86 @@ VOID CntlWaitJoinProc( ========================================================================== */ -VOID CntlWaitStartProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void CntlWaitStartProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Result; - - if (Elem->MsgType == MT2_START_CONF) - { - NdisMoveMemory(&Result, Elem->Msg, sizeof(USHORT)); - if (Result == MLME_SUCCESS) - { - // - // 5G bands rules of Japan: - // Ad hoc must be disabled in W53(ch52,56,60,64) channels. - // - if ( (pAd->CommonCfg.bIEEE80211H == 1) && - RadarChannelCheck(pAd, pAd->CommonCfg.Channel) - ) - { + u16 Result; + + if (Elem->MsgType == MT2_START_CONF) { + NdisMoveMemory(&Result, Elem->Msg, sizeof(u16)); + if (Result == MLME_SUCCESS) { + /* */ + /* 5G bands rules of Japan: */ + /* Ad hoc must be disabled in W53(ch52,56,60,64) channels. */ + /* */ + if ((pAd->CommonCfg.bIEEE80211H == 1) && + RadarChannelCheck(pAd, pAd->CommonCfg.Channel) + ) { pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Channel=%d, Start adhoc on W53(52,56,60,64) Channels are not accepted\n", pAd->CommonCfg.Channel)); + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Channel=%d, Start adhoc on W53(52,56,60,64) Channels are not accepted\n", + pAd->CommonCfg.Channel)); return; } - - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) - { + NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo. + MCSSet[0], 16); + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) { N_ChannelCheck(pAd); SetCommonHT(pAd); - NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, &pAd->CommonCfg.AddHTInfo, sizeof(ADD_HT_INFO_IE)); - RTMPCheckHt(pAd, BSSID_WCID, &pAd->CommonCfg.HtCapability, &pAd->CommonCfg.AddHTInfo); - pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE; - NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], 16); - NdisMoveMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], &pAd->CommonCfg.HtCapability.MCSSet[0], 16); - COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); - - if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && - (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE)) - { - pAd->MlmeAux.CentralChannel = pAd->CommonCfg.Channel + 2; - } - else if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && - (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW)) - { - pAd->MlmeAux.CentralChannel = pAd->CommonCfg.Channel - 2; + NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, + &pAd->CommonCfg.AddHTInfo, + sizeof(struct rt_add_ht_info_ie)); + RTMPCheckHt(pAd, BSSID_WCID, + &pAd->CommonCfg.HtCapability, + &pAd->CommonCfg.AddHTInfo); + pAd->StaActive.SupportedPhyInfo.bHtEnable = + TRUE; + NdisMoveMemory(&pAd->StaActive.SupportedPhyInfo. + MCSSet[0], + &pAd->CommonCfg.HtCapability. + MCSSet[0], 16); + COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG + (pAd); + + if ((pAd->CommonCfg.HtCapability.HtCapInfo. + ChannelWidth == BW_40) + && (pAd->CommonCfg.AddHTInfo.AddHtInfo. + ExtChanOffset == EXTCHA_ABOVE)) { + pAd->MlmeAux.CentralChannel = + pAd->CommonCfg.Channel + 2; + } else + if ((pAd->CommonCfg.HtCapability.HtCapInfo. + ChannelWidth == BW_40) + && (pAd->CommonCfg.AddHTInfo.AddHtInfo. + ExtChanOffset == EXTCHA_BELOW)) { + pAd->MlmeAux.CentralChannel = + pAd->CommonCfg.Channel - 2; } - } - else - { - pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + } else { + pAd->StaActive.SupportedPhyInfo.bHtEnable = + FALSE; } LinkUp(pAd, BSS_ADHOC); pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - // Before send beacon, driver need do radar detection - if ((pAd->CommonCfg.Channel > 14 ) - && (pAd->CommonCfg.bIEEE80211H == 1) - && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) - { - pAd->CommonCfg.RadarDetect.RDMode = RD_SILENCE_MODE; + /* Before send beacon, driver need do radar detection */ + if ((pAd->CommonCfg.Channel > 14) + && (pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) { + pAd->CommonCfg.RadarDetect.RDMode = + RD_SILENCE_MODE; pAd->CommonCfg.RadarDetect.RDCount = 0; } - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - start a new IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n", - pAd->CommonCfg.Bssid[0],pAd->CommonCfg.Bssid[1],pAd->CommonCfg.Bssid[2], - pAd->CommonCfg.Bssid[3],pAd->CommonCfg.Bssid[4],pAd->CommonCfg.Bssid[5])); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Start IBSS fail. BUG!!!!!\n")); + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - start a new IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n", + pAd->CommonCfg.Bssid[0], + pAd->CommonCfg.Bssid[1], + pAd->CommonCfg.Bssid[2], + pAd->CommonCfg.Bssid[3], + pAd->CommonCfg.Bssid[4], + pAd->CommonCfg.Bssid[5])); + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Start IBSS fail. BUG!\n")); pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; } } @@ -875,52 +925,57 @@ VOID CntlWaitStartProc( ========================================================================== */ -VOID CntlWaitAuthProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void CntlWaitAuthProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Reason; - MLME_ASSOC_REQ_STRUCT AssocReq; - MLME_AUTH_REQ_STRUCT AuthReq; + u16 Reason; + struct rt_mlme_assoc_req AssocReq; + struct rt_mlme_auth_req AuthReq; - if (Elem->MsgType == MT2_AUTH_CONF) - { - NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); - if (Reason == MLME_SUCCESS) - { + if (Elem->MsgType == MT2_AUTH_CONF) { + NdisMoveMemory(&Reason, Elem->Msg, sizeof(u16)); + if (Reason == MLME_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n")); - AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, pAd->MlmeAux.CapabilityInfo, - ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount); + AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, + pAd->MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, + pAd->StaCfg.DefaultListenCount); { - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_ASSOC_REQ, - sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_ASSOC_REQ, + sizeof(struct rt_mlme_assoc_req), + &AssocReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC; + pAd->Mlme.CntlMachine.CurrState = + CNTL_WAIT_ASSOC; } - } - else - { - // This fail may because of the AP already keep us in its MAC table without - // ageing-out. The previous authentication attempt must have let it remove us. - // so try Authentication again may help. For D-Link DWL-900AP+ compatibility. - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, try again...\n")); + } else { + /* This fail may because of the AP already keep us in its MAC table without */ + /* ageing-out. The previous authentication attempt must have let it remove us. */ + /* so try Authentication again may help. For D-Link DWL-900AP+ compatibility. */ + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - AUTH FAIL, try again...\n")); { - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch)) - { - // either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first - AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeShared); + if ((pAd->StaCfg.AuthMode == + Ndis802_11AuthModeShared) + || (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeAutoSwitch)) { + /* either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first */ + AuthParmFill(pAd, &AuthReq, + pAd->MlmeAux.Bssid, + AUTH_MODE_KEY); + } else { + AuthParmFill(pAd, &AuthReq, + pAd->MlmeAux.Bssid, + AUTH_MODE_OPEN); } - else - { - AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen); - } - } - MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ, - sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq); + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, + MT2_MLME_AUTH_REQ, + sizeof(struct rt_mlme_auth_req), + &AuthReq); + } pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2; } } @@ -934,44 +989,49 @@ VOID CntlWaitAuthProc( ========================================================================== */ -VOID CntlWaitAuthProc2( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void CntlWaitAuthProc2(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Reason; - MLME_ASSOC_REQ_STRUCT AssocReq; - MLME_AUTH_REQ_STRUCT AuthReq; + u16 Reason; + struct rt_mlme_assoc_req AssocReq; + struct rt_mlme_auth_req AuthReq; - if (Elem->MsgType == MT2_AUTH_CONF) - { - NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); - if (Reason == MLME_SUCCESS) - { + if (Elem->MsgType == MT2_AUTH_CONF) { + NdisMoveMemory(&Reason, Elem->Msg, sizeof(u16)); + if (Reason == MLME_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n")); - AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, pAd->MlmeAux.CapabilityInfo, - ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount); - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_ASSOC_REQ, - sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq); - - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC; - } - else - { - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch) && - (pAd->MlmeAux.Alg == Ndis802_11AuthModeShared)) + AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, + pAd->MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, + pAd->StaCfg.DefaultListenCount); { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, try OPEN system...\n")); - AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen); - MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ, - sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_ASSOC_REQ, + sizeof(struct rt_mlme_assoc_req), + &AssocReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2; + pAd->Mlme.CntlMachine.CurrState = + CNTL_WAIT_ASSOC; } - else - { - // not success, try next BSS - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, give up; try next BSS\n")); - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; //??????? + } else { + if ((pAd->StaCfg.AuthMode == + Ndis802_11AuthModeAutoSwitch) + && (pAd->MlmeAux.Alg == Ndis802_11AuthModeShared)) { + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - AUTH FAIL, try OPEN system...\n")); + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, + Ndis802_11AuthModeOpen); + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, + MT2_MLME_AUTH_REQ, + sizeof(struct rt_mlme_auth_req), + &AuthReq); + + pAd->Mlme.CntlMachine.CurrState = + CNTL_WAIT_AUTH2; + } else { + /* not success, try next BSS */ + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - AUTH FAIL, give up; try next BSS\n")); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; /*??????? */ pAd->MlmeAux.BssIdx++; IterateOnBssTab(pAd); } @@ -987,30 +1047,30 @@ VOID CntlWaitAuthProc2( ========================================================================== */ -VOID CntlWaitAssocProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void CntlWaitAssocProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Reason; + u16 Reason; + + if (Elem->MsgType == MT2_ASSOC_CONF) { + NdisMoveMemory(&Reason, Elem->Msg, sizeof(u16)); + if (Reason == MLME_SUCCESS) { + if (pAd->CommonCfg.bWirelessEvent) { + RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, + pAd->MacTab. + Content[BSSID_WCID].Addr, + BSS0, 0); + } - if (Elem->MsgType == MT2_ASSOC_CONF) - { - NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); - if (Reason == MLME_SUCCESS) - { LinkUp(pAd, BSS_INFRA); pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Association successful on BSS #%ld\n",pAd->MlmeAux.BssIdx)); - - if (pAd->CommonCfg.bWirelessEvent) - { - RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - } - } - else - { - // not success, try next BSS - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Association fails on BSS #%ld\n",pAd->MlmeAux.BssIdx)); + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Association successful on BSS #%ld\n", + pAd->MlmeAux.BssIdx)); + } else { + /* not success, try next BSS */ + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Association fails on BSS #%ld\n", + pAd->MlmeAux.BssIdx)); pAd->MlmeAux.BssIdx++; IterateOnBssTab(pAd); } @@ -1025,52 +1085,51 @@ VOID CntlWaitAssocProc( ========================================================================== */ -VOID CntlWaitReassocProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void CntlWaitReassocProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Result; - - if (Elem->MsgType == MT2_REASSOC_CONF) - { - NdisMoveMemory(&Result, Elem->Msg, sizeof(USHORT)); - if (Result == MLME_SUCCESS) - { - // - // NDIS requires a new Link UP indication but no Link Down for RE-ASSOC - // - LinkUp(pAd, BSS_INFRA); + u16 Result; - // send wireless event - for association + if (Elem->MsgType == MT2_REASSOC_CONF) { + NdisMoveMemory(&Result, Elem->Msg, sizeof(u16)); + if (Result == MLME_SUCCESS) { + /* send wireless event - for association */ if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, + pAd->MacTab. + Content[BSSID_WCID].Addr, + BSS0, 0); + + /* */ + /* NDIS requires a new Link UP indication but no Link Down for RE-ASSOC */ + /* */ + LinkUp(pAd, BSS_INFRA); pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Re-assocition successful on BSS #%ld\n", pAd->MlmeAux.RoamIdx)); - } - else - { - // reassoc failed, try to pick next BSS in the BSS Table - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Re-assocition fails on BSS #%ld\n", pAd->MlmeAux.RoamIdx)); - pAd->MlmeAux.RoamIdx++; - IterateOnBssTab2(pAd); + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Re-assocition successful on BSS #%ld\n", + pAd->MlmeAux.RoamIdx)); + } else { + /* reassoc failed, try to pick next BSS in the BSS Table */ + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - Re-assocition fails on BSS #%ld\n", + pAd->MlmeAux.RoamIdx)); + { + pAd->MlmeAux.RoamIdx++; + IterateOnBssTab2(pAd); + } } } } - -#ifdef RT2870 -VOID AdhocTurnOnQos( - IN PRTMP_ADAPTER pAd) +void AdhocTurnOnQos(struct rt_rtmp_adapter *pAd) { #define AC0_DEF_TXOP 0 #define AC1_DEF_TXOP 0 #define AC2_DEF_TXOP 94 #define AC3_DEF_TXOP 47 - // Turn on QOs if use HT rate. - if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) - { + /* Turn on QOs if use HT rate. */ + if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) { pAd->CommonCfg.APEdcaParm.bValid = TRUE; pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; @@ -1087,14 +1146,13 @@ VOID AdhocTurnOnQos( pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; - pAd->CommonCfg.APEdcaParm.Txop[0] = 0; - pAd->CommonCfg.APEdcaParm.Txop[1] = 0; - pAd->CommonCfg.APEdcaParm.Txop[2] = AC2_DEF_TXOP; - pAd->CommonCfg.APEdcaParm.Txop[3] = AC3_DEF_TXOP; + pAd->CommonCfg.APEdcaParm.Txop[0] = 0; + pAd->CommonCfg.APEdcaParm.Txop[1] = 0; + pAd->CommonCfg.APEdcaParm.Txop[2] = AC2_DEF_TXOP; + pAd->CommonCfg.APEdcaParm.Txop[3] = AC3_DEF_TXOP; } AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); } -#endif /* RT2870 */ /* ========================================================================== @@ -1104,110 +1162,81 @@ VOID AdhocTurnOnQos( ========================================================================== */ -VOID LinkUp( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssType) +void LinkUp(struct rt_rtmp_adapter *pAd, u8 BssType) { - ULONG Now; - UINT32 Data; - BOOLEAN Cancelled; - UCHAR Value = 0, idx; - MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; - -#ifdef RT2860 - if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)) - { - RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT); - RTMPusecDelay(6000); - pAd->bPCIclkOff = FALSE; + unsigned long Now; + u32 Data; + BOOLEAN Cancelled; + u8 Value = 0, idx = 0, HashIdx = 0; + struct rt_mac_table_entry *pEntry = NULL, *pCurrEntry = NULL; + + /* Init ChannelQuality to prevent DEAD_CQI at initial LinkUp */ + pAd->Mlme.ChannelQuality = 50; + + pEntry = MacTableLookup(pAd, pAd->CommonCfg.Bssid); + if (pEntry) { + MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); + pEntry = NULL; } -#endif pEntry = &pAd->MacTab.Content[BSSID_WCID]; - // - // ASSOC - DisassocTimeoutAction - // CNTL - Dis-associate successful - // !!! LINK DOWN !!! - // [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: ) - // - // To prevent DisassocTimeoutAction to call Link down after we link up, - // cancel the DisassocTimer no matter what it start or not. - // - RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + /* */ + /* ASSOC - DisassocTimeoutAction */ + /* CNTL - Dis-associate successful */ + /* ! LINK DOWN ! */ + /* [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: ) */ + /* */ + /* To prevent DisassocTimeoutAction to call Link down after we link up, */ + /* cancel the DisassocTimer no matter what it start or not. */ + /* */ + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); - // It's quite difficult to tell if a newly added KEY is WEP or CKIP until a new BSS - // is formed (either ASSOC/RE-ASSOC done or IBSS started. LinkUP should be a safe place - // to examine if cipher algorithm switching is required. - //rt2860b. Don't know why need this - SwitchBetweenWepAndCkip(pAd); - -#ifdef RT2860 - // Before power save before link up function, We will force use 1R. - // So after link up, check Rx antenna # again. +#ifdef RTMP_MAC_PCI + /* Before power save before link up function, We will force use 1R. */ + /* So after link up, check Rx antenna # again. */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); - if(pAd->Antenna.field.RxPath == 3) - { + if (pAd->Antenna.field.RxPath == 3) { Value |= (0x10); - } - else if(pAd->Antenna.field.RxPath == 2) - { + } else if (pAd->Antenna.field.RxPath == 2) { Value |= (0x8); - } - else if(pAd->Antenna.field.RxPath == 1) - { + } else if (pAd->Antenna.field.RxPath == 1) { Value |= (0x0); } RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); pAd->StaCfg.BBPR3 = Value; -#endif /* RT2860 */ +#endif /* RTMP_MAC_PCI // */ - if (BssType == BSS_ADHOC) - { + if (BssType == BSS_ADHOC) { OPSTATUS_SET_FLAG(pAd, fOP_STATUS_ADHOC_ON); OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); - if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && - (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE)) - { - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; - } - else if ((pAd->CommonCfg.Channel > 2) && - (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && - (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW)) - { - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; - } -#ifdef RT2870 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) AdhocTurnOnQos(pAd); -#endif - DBGPRINT(RT_DEBUG_TRACE, ("!!!Adhoc LINK UP !!! \n" )); - } - else - { + DBGPRINT(RT_DEBUG_TRACE, ("Adhoc LINK UP!\n")); + } else { OPSTATUS_SET_FLAG(pAd, fOP_STATUS_INFRA_ON); OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); - DBGPRINT(RT_DEBUG_TRACE, ("!!!Infra LINK UP !!! \n" )); + DBGPRINT(RT_DEBUG_TRACE, ("Infra LINK UP!\n")); } - // 3*3 - // reset Tx beamforming bit + /* 3*3 */ + /* reset Tx beamforming bit */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); Value &= (~0x01); Value |= pAd->CommonCfg.RegTransmitSetting.field.TxBF; RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); - // Change to AP channel - if ((pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. + /* Change to AP channel */ + if ((pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) { + /* Must using 40MHz. */ pAd->CommonCfg.BBPCurrentBW = BW_40; AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); @@ -1217,34 +1246,35 @@ VOID LinkUp( Value |= 0x10; RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); - // RX : control channel at lower + /* RX : control channel at lower */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); Value &= (~0x20); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); -#ifdef RT2860 - pAd->StaCfg.BBPR3 = Value; -#endif +#ifdef RTMP_MAC_PCI + pAd->StaCfg.BBPR3 = Value; +#endif /* RTMP_MAC_PCI // */ RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); Data &= 0xfffffffe; RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); - if (pAd->MACVersion == 0x28600100) - { + if (pAd->MACVersion == 0x28600100) { RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); - DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + DBGPRINT(RT_DEBUG_TRACE, ("rt2860C !\n")); } - DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel )); - } - else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. + DBGPRINT(RT_DEBUG_TRACE, + ("40MHz Lower LINK UP! Control Channel at Below. Central = %d \n", + pAd->CommonCfg.CentralChannel)); + } else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == + BW_40)) { + /* Must using 40MHz. */ pAd->CommonCfg.BBPCurrentBW = BW_40; AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); Value &= (~0x18); @@ -1256,25 +1286,24 @@ VOID LinkUp( RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); - Value |= (0x20); + Value |= (0x20); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); -#ifdef RT2860 - pAd->StaCfg.BBPR3 = Value; -#endif +#ifdef RTMP_MAC_PCI + pAd->StaCfg.BBPR3 = Value; +#endif /* RTMP_MAC_PCI // */ - if (pAd->MACVersion == 0x28600100) - { + if (pAd->MACVersion == 0x28600100) { RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); - DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + DBGPRINT(RT_DEBUG_TRACE, ("rt2860C !\n")); } - DBGPRINT(RT_DEBUG_TRACE, ("!!! 40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel )); - } - else - { - pAd->CommonCfg.BBPCurrentBW = BW_20; + DBGPRINT(RT_DEBUG_TRACE, + ("40MHz Upper LINK UP! Control Channel at UpperCentral = %d \n", + pAd->CommonCfg.CentralChannel)); + } else { + pAd->CommonCfg.BBPCurrentBW = BW_20; pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.Channel); @@ -1290,511 +1319,533 @@ VOID LinkUp( RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); Value &= (~0x20); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); -#ifdef RT2860 - pAd->StaCfg.BBPR3 = Value; -#endif +#ifdef RTMP_MAC_PCI + pAd->StaCfg.BBPR3 = Value; +#endif /* RTMP_MAC_PCI // */ - if (pAd->MACVersion == 0x28600100) - { + if (pAd->MACVersion == 0x28600100) { RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11); - DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + DBGPRINT(RT_DEBUG_TRACE, ("rt2860C !\n")); } - DBGPRINT(RT_DEBUG_TRACE, ("!!! 20MHz LINK UP !!! \n" )); - } + DBGPRINT(RT_DEBUG_TRACE, ("20MHz LINK UP!\n")); + } RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); - // - // Save BBP_R66 value, it will be used in RTUSBResumeMsduTransmission - // - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue); - DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (BssType=%d, AID=%d, ssid=%s, Channel=%d, CentralChannel = %d)\n", - BssType, pAd->StaActive.Aid, pAd->CommonCfg.Ssid, pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); + /* */ + /* Save BBP_R66 value, it will be used in RTUSBResumeMsduTransmission */ + /* */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, + &pAd->BbpTuning.R66CurrentValue); - DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (Density =%d, )\n", pAd->MacTab.Content[BSSID_WCID].MpduDensity)); + DBGPRINT(RT_DEBUG_TRACE, + ("LINK UP! (BssType=%d, AID=%d, ssid=%s, Channel=%d, CentralChannel = %d)\n", + BssType, pAd->StaActive.Aid, pAd->CommonCfg.Ssid, + pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); - AsicSetBssid(pAd, pAd->CommonCfg.Bssid); + DBGPRINT(RT_DEBUG_TRACE, + ("LINK UP! (Density =%d, )\n", + pAd->MacTab.Content[BSSID_WCID].MpduDensity)); + + AsicSetBssid(pAd, pAd->CommonCfg.Bssid); AsicSetSlotTime(pAd, TRUE); AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); - // Call this for RTS protectionfor legacy rate, we will always enable RTS threshold, but normally it will not hit - AsicUpdateProtect(pAd, 0, (OFDMSETPROTECT | CCKSETPROTECT), TRUE, FALSE); + /* Call this for RTS protectionfor legacy rate, we will always enable RTS threshold, but normally it will not hit */ + AsicUpdateProtect(pAd, 0, (OFDMSETPROTECT | CCKSETPROTECT), TRUE, + FALSE); - if ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE)) - { - // Update HT protectionfor based on AP's operating mode. - if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1) - { - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE); - } - else - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); + if ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE)) { + /* Update HT protectionfor based on AP's operating mode. */ + if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1) { + AsicUpdateProtect(pAd, + pAd->MlmeAux.AddHtInfo.AddHtInfo2. + OperaionMode, ALLN_SETPROTECT, FALSE, + TRUE); + } else + AsicUpdateProtect(pAd, + pAd->MlmeAux.AddHtInfo.AddHtInfo2. + OperaionMode, ALLN_SETPROTECT, FALSE, + FALSE); } - NdisZeroMemory(&pAd->DrsCounters, sizeof(COUNTER_DRS)); + NdisZeroMemory(&pAd->DrsCounters, sizeof(struct rt_counter_drs)); NdisGetSystemUpTime(&Now); - pAd->StaCfg.LastBeaconRxTime = Now; // last RX timestamp + pAd->StaCfg.LastBeaconRxTime = Now; /* last RX timestamp */ if ((pAd->CommonCfg.TxPreamble != Rt802_11PreambleLong) && - CAP_IS_SHORT_PREAMBLE_ON(pAd->StaActive.CapabilityInfo)) - { + CAP_IS_SHORT_PREAMBLE_ON(pAd->StaActive.CapabilityInfo)) { MlmeSetTxPreamble(pAd, Rt802_11PreambleShort); } OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); - if (pAd->CommonCfg.RadarDetect.RDMode == RD_SILENCE_MODE) - { + if (pAd->CommonCfg.RadarDetect.RDMode == RD_SILENCE_MODE) { } pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE; - if (BssType == BSS_ADHOC) - { + if (BssType == BSS_ADHOC) { MakeIbssBeacon(pAd); if ((pAd->CommonCfg.Channel > 14) - && (pAd->CommonCfg.bIEEE80211H == 1) - && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) - { - ; //Do nothing - } - else - { + && (pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) { + ; /*Do nothing */ + } else { AsicEnableIbssSync(pAd); } - // In ad hoc mode, use MAC table from index 1. - // p.s ASIC use all 0xff as termination of WCID table search.To prevent it's 0xff-ff-ff-ff-ff-ff, Write 0 here. + /* In ad hoc mode, use MAC table from index 1. */ + /* p.s ASIC use all 0xff as termination of WCID table search.To prevent it's 0xff-ff-ff-ff-ff-ff, Write 0 here. */ RTMP_IO_WRITE32(pAd, MAC_WCID_BASE, 0x00); RTMP_IO_WRITE32(pAd, 0x1808, 0x00); - // If WEP is enabled, add key material and cipherAlg into Asic - // Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000) + /* If WEP is enabled, add key material and cipherAlg into Asic */ + /* Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000) */ - if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) - { - PUCHAR Key; - UCHAR CipherAlg; + if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) { + u8 *Key; + u8 CipherAlg; - for (idx=0; idx < SHARE_KEY_NUM; idx++) - { + for (idx = 0; idx < SHARE_KEY_NUM; idx++) { CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg; - Key = pAd->SharedKey[BSS0][idx].Key; - - if (pAd->SharedKey[BSS0][idx].KeyLen > 0) - { - // Set key material and cipherAlg to Asic - AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL); - - if (idx == pAd->StaCfg.DefaultKeyId) - { - // Update WCID attribute table and IVEIV table for this group key table - RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL); + Key = pAd->SharedKey[BSS0][idx].Key; + + if (pAd->SharedKey[BSS0][idx].KeyLen > 0) { + /* Set key material and cipherAlg to Asic */ + AsicAddSharedKeyEntry(pAd, BSS0, idx, + CipherAlg, Key, + NULL, NULL); + + if (idx == pAd->StaCfg.DefaultKeyId) { + /* Update WCID attribute table and IVEIV table for this group key table */ + RTMPAddWcidAttributeEntry(pAd, + BSS0, + idx, + CipherAlg, + NULL); } } - } } - // If WPANone is enabled, add key material and cipherAlg into Asic - // Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000) - else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - { - pAd->StaCfg.DefaultKeyId = 0; // always be zero - - NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); - pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pAd->StaCfg.PMK, LEN_TKIP_EK); - - if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) - { - NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_RXMICK); - NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_TXMICK); - } - - // Decide its ChiperAlg - if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + /* If WPANone is enabled, add key material and cipherAlg into Asic */ + /* Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000) */ + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) { + pAd->StaCfg.DefaultKeyId = 0; /* always be zero */ + + NdisZeroMemory(&pAd->SharedKey[BSS0][0], + sizeof(struct rt_cipher_key)); + pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, + pAd->StaCfg.PMK, LEN_TKIP_EK); + + if (pAd->StaCfg.PairCipher == + Ndis802_11Encryption2Enabled) { + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, + &pAd->StaCfg.PMK[16], + LEN_TKIP_RXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, + &pAd->StaCfg.PMK[16], + LEN_TKIP_TXMICK); + } + /* Decide its ChiperAlg */ + if (pAd->StaCfg.PairCipher == + Ndis802_11Encryption2Enabled) pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + else if (pAd->StaCfg.PairCipher == + Ndis802_11Encryption3Enabled) pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; - else - { - DBGPRINT(RT_DEBUG_TRACE, ("Unknow Cipher (=%d), set Cipher to AES\n", pAd->StaCfg.PairCipher)); + else { + DBGPRINT(RT_DEBUG_TRACE, + ("Unknow Cipher (=%d), set Cipher to AES\n", + pAd->StaCfg.PairCipher)); pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; - } + } - // Set key material and cipherAlg to Asic + /* Set key material and cipherAlg to Asic */ AsicAddSharedKeyEntry(pAd, - BSS0, - 0, - pAd->SharedKey[BSS0][0].CipherAlg, - pAd->SharedKey[BSS0][0].Key, - pAd->SharedKey[BSS0][0].TxMic, - pAd->SharedKey[BSS0][0].RxMic); - - // Update WCID attribute table and IVEIV table for this group key table - RTMPAddWcidAttributeEntry(pAd, BSS0, 0, pAd->SharedKey[BSS0][0].CipherAlg, NULL); + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pAd->SharedKey[BSS0][0].Key, + pAd->SharedKey[BSS0][0].TxMic, + pAd->SharedKey[BSS0][0].RxMic); + + /* Update WCID attribute table and IVEIV table for this group key table */ + RTMPAddWcidAttributeEntry(pAd, BSS0, 0, + pAd->SharedKey[BSS0][0]. + CipherAlg, NULL); } - } - else // BSS_INFRA - { - // Check the new SSID with last SSID - while (Cancelled == TRUE) - { - if (pAd->CommonCfg.LastSsidLen == pAd->CommonCfg.SsidLen) - { - if (RTMPCompareMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen) == 0) - { - // Link to the old one no linkdown is required. + } else /* BSS_INFRA */ + { + /* Check the new SSID with last SSID */ + while (Cancelled == TRUE) { + if (pAd->CommonCfg.LastSsidLen == + pAd->CommonCfg.SsidLen) { + if (RTMPCompareMemory + (pAd->CommonCfg.LastSsid, + pAd->CommonCfg.Ssid, + pAd->CommonCfg.LastSsidLen) == 0) { + /* Link to the old one no linkdown is required. */ break; } } - // Send link down event before set to link up + /* Send link down event before set to link up */ pAd->IndicateMediaState = NdisMediaStateDisconnected; RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_DOWN; - DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event AA!\n")); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, + ("NDIS_STATUS_MEDIA_DISCONNECT Event AA!\n")); break; } - // - // On WPA mode, Remove All Keys if not connect to the last BSSID - // Key will be set after 4-way handshake. - // - if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) - { - ULONG IV; + /* */ + /* On WPA mode, Remove All Keys if not connect to the last BSSID */ + /* Key will be set after 4-way handshake. */ + /* */ + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) { + unsigned long IV; - // Remove all WPA keys + /* Remove all WPA keys */ + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); RTMPWPARemoveAllKeys(pAd); pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pAd->StaCfg.PrivacyFilter = + Ndis802_11PrivFilter8021xWEP; - // Fixed connection failed with Range Maximizer - 515 AP (Marvell Chip) when security is WPAPSK/TKIP - // If IV related values are too large in GroupMsg2, AP would ignore this message. - IV = 0; + /* Fixed connection failed with Range Maximizer - 515 AP (Marvell Chip) when security is WPAPSK/TKIP */ + /* If IV related values are too large in GroupMsg2, AP would ignore this message. */ + IV = 1; IV |= (pAd->StaCfg.DefaultKeyId << 30); AsicUpdateWCIDIVEIV(pAd, BSSID_WCID, IV, 0); - -#ifdef RT2860 - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); -#endif } - // NOTE: - // the decision of using "short slot time" or not may change dynamically due to - // new STA association to the AP. so we have to decide that upon parsing BEACON, not here + /* NOTE: */ + /* the decision of using "short slot time" or not may change dynamically due to */ + /* new STA association to the AP. so we have to decide that upon parsing BEACON, not here */ - // NOTE: - // the decision to use "RTC/CTS" or "CTS-to-self" protection or not may change dynamically - // due to new STA association to the AP. so we have to decide that upon parsing BEACON, not here + /* NOTE: */ + /* the decision to use "RTC/CTS" or "CTS-to-self" protection or not may change dynamically */ + /* due to new STA association to the AP. so we have to decide that upon parsing BEACON, not here */ ComposePsPoll(pAd); ComposeNullFrame(pAd); - AsicEnableBssSync(pAd); + AsicEnableBssSync(pAd); - // Add BSSID to WCID search table + /* Add BSSID to WCID search table */ AsicUpdateRxWCIDTable(pAd, BSSID_WCID, pAd->CommonCfg.Bssid); - NdisAcquireSpinLock(&pAd->MacTabLock); - // add this BSSID entry into HASH table - { - UCHAR HashIdx; + /* If WEP is enabled, add paiewise and shared key */ + if (((pAd->StaCfg.WpaSupplicantUP) && + (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) && + (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED)) || + ((pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) && + (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled))) { + u8 *Key; + u8 CipherAlg; - //pEntry = &pAd->MacTab.Content[BSSID_WCID]; - HashIdx = MAC_ADDR_HASH_INDEX(pAd->CommonCfg.Bssid); - if (pAd->MacTab.Hash[HashIdx] == NULL) - { - pAd->MacTab.Hash[HashIdx] = pEntry; - } - else - { - pCurrEntry = pAd->MacTab.Hash[HashIdx]; - while (pCurrEntry->pNext != NULL) - pCurrEntry = pCurrEntry->pNext; - pCurrEntry->pNext = pEntry; - } - } - NdisReleaseSpinLock(&pAd->MacTabLock); - - - // If WEP is enabled, add paiewise and shared key - if (((pAd->StaCfg.WpaSupplicantUP)&& - (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)&& - (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED)) || - ((pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)&& - (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled))) - { - PUCHAR Key; - UCHAR CipherAlg; - - for (idx=0; idx < SHARE_KEY_NUM; idx++) - { + for (idx = 0; idx < SHARE_KEY_NUM; idx++) { CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg; - Key = pAd->SharedKey[BSS0][idx].Key; - - if (pAd->SharedKey[BSS0][idx].KeyLen > 0) - { - // Set key material and cipherAlg to Asic - AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL); - - if (idx == pAd->StaCfg.DefaultKeyId) - { - // Assign group key info - RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL); - - // Assign pairwise key info - RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry); + Key = pAd->SharedKey[BSS0][idx].Key; + + if (pAd->SharedKey[BSS0][idx].KeyLen > 0) { + /* Set key material and cipherAlg to Asic */ + AsicAddSharedKeyEntry(pAd, BSS0, idx, + CipherAlg, Key, + NULL, NULL); + + if (idx == pAd->StaCfg.DefaultKeyId) { + /* Assign group key info */ + RTMPAddWcidAttributeEntry(pAd, + BSS0, + idx, + CipherAlg, + NULL); + + pEntry->Aid = BSSID_WCID; + /* Assign pairwise key info */ + RTMPAddWcidAttributeEntry(pAd, + BSS0, + idx, + CipherAlg, + pEntry); } } } } - - // only INFRASTRUCTURE mode need to indicate connectivity immediately; ADHOC mode - // should wait until at least 2 active nodes in this BSSID. + /* only INFRASTRUCTURE mode need to indicate connectivity immediately; ADHOC mode */ + /* should wait until at least 2 active nodes in this BSSID. */ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); - // For GUI ++ - if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) - { + /* For GUI ++ */ + if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) { pAd->IndicateMediaState = NdisMediaStateConnected; pAd->ExtraInfo = GENERAL_LINK_UP; -#ifdef RT2870 RTMP_IndicateMediaState(pAd); -#endif + } else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + if (pAd->StaCfg.WpaSupplicantUP == + WPA_SUPPLICANT_DISABLE) + RTMPSetTimer(&pAd->Mlme.LinkDownTimer, + LINK_DOWN_TIMEOUT); } - // -- -#ifdef RT2860 - RTMP_IndicateMediaState(pAd); -#endif - - // Add BSSID in my MAC Table. - NdisAcquireSpinLock(&pAd->MacTabLock); - RTMPMoveMemory(pAd->MacTab.Content[BSSID_WCID].Addr, pAd->CommonCfg.Bssid, MAC_ADDR_LEN); - pAd->MacTab.Content[BSSID_WCID].Aid = BSSID_WCID; - pAd->MacTab.Content[BSSID_WCID].pAd = pAd; - pAd->MacTab.Content[BSSID_WCID].ValidAsCLI = TRUE; //Although this is bssid..still set ValidAsCl - pAd->MacTab.Size = 1; // infra mode always set MACtab size =1. - pAd->MacTab.Content[BSSID_WCID].Sst = SST_ASSOC; - pAd->MacTab.Content[BSSID_WCID].AuthState = SST_ASSOC; - pAd->MacTab.Content[BSSID_WCID].AuthMode = pAd->StaCfg.AuthMode; - pAd->MacTab.Content[BSSID_WCID].WepStatus = pAd->StaCfg.WepStatus; - NdisReleaseSpinLock(&pAd->MacTabLock); - - DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! ClientStatusFlags=%lx)\n", - pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); + /* -- */ - MlmeUpdateTxRates(pAd, TRUE, BSS0); - MlmeUpdateHtTxRates(pAd, BSS0); - DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !! (StaActive.bHtEnable =%d, )\n", pAd->StaActive.SupportedPhyInfo.bHtEnable)); + /* Add BSSID in my MAC Table. */ + NdisAcquireSpinLock(&pAd->MacTabLock); + /* add this MAC entry into HASH table */ + if (pEntry) { + HashIdx = MAC_ADDR_HASH_INDEX(pAd->CommonCfg.Bssid); + if (pAd->MacTab.Hash[HashIdx] == NULL) { + pAd->MacTab.Hash[HashIdx] = pEntry; + } else { + pCurrEntry = pAd->MacTab.Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) { + pCurrEntry = pCurrEntry->pNext; + } + pCurrEntry->pNext = pEntry; + } + } + RTMPMoveMemory(pEntry->Addr, pAd->CommonCfg.Bssid, + MAC_ADDR_LEN); + pEntry->Aid = BSSID_WCID; + pEntry->pAd = pAd; + pEntry->ValidAsCLI = TRUE; /*Although this is bssid..still set ValidAsCl */ + pAd->MacTab.Size = 1; /* infra mode always set MACtab size =1. */ + pEntry->Sst = SST_ASSOC; + pEntry->AuthState = SST_ASSOC; + pEntry->AuthMode = pAd->StaCfg.AuthMode; + pEntry->WepStatus = pAd->StaCfg.WepStatus; + if (pEntry->AuthMode < Ndis802_11AuthModeWPA) { + pEntry->WpaState = AS_NOTUSE; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } else { + pEntry->WpaState = AS_PTKSTART; + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + } + NdisReleaseSpinLock(&pAd->MacTabLock); - if (pAd->CommonCfg.bAggregationCapable) - { - if ((pAd->CommonCfg.bPiggyBackCapable) && (pAd->MlmeAux.APRalinkIe & 0x00000003) == 3) - { + DBGPRINT(RT_DEBUG_TRACE, + ("LINK UP! ClientStatusFlags=%lx)\n", + pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED); - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); - RTMPSetPiggyBack(pAd, TRUE); - DBGPRINT(RT_DEBUG_TRACE, ("Turn on Piggy-Back\n")); - } - else if (pAd->MlmeAux.APRalinkIe & 0x00000001) - { - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + MlmeUpdateTxRates(pAd, TRUE, BSS0); + MlmeUpdateHtTxRates(pAd, BSS0); + DBGPRINT(RT_DEBUG_TRACE, + ("LINK UP! (StaActive.bHtEnable =%d, )\n", + pAd->StaActive.SupportedPhyInfo.bHtEnable)); + + if (pAd->CommonCfg.bAggregationCapable) { + if ((pAd->CommonCfg.bPiggyBackCapable) + && (pAd->MlmeAux.APRalinkIe & 0x00000003) == 3) { + OPSTATUS_SET_FLAG(pAd, + fOP_STATUS_PIGGYBACK_INUSED); + OPSTATUS_SET_FLAG(pAd, + fOP_STATUS_AGGREGATION_INUSED); + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_AGGREGATION_CAPABLE); + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_PIGGYBACK_CAPABLE); + RTMPSetPiggyBack(pAd, TRUE); + DBGPRINT(RT_DEBUG_TRACE, + ("Turn on Piggy-Back\n")); + } else if (pAd->MlmeAux.APRalinkIe & 0x00000001) { + OPSTATUS_SET_FLAG(pAd, + fOP_STATUS_AGGREGATION_INUSED); + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_AGGREGATION_CAPABLE); + DBGPRINT(RT_DEBUG_TRACE, + ("Ralink Aggregation\n")); } } - if (pAd->MlmeAux.APRalinkIe != 0x0) - { - if (CLIENT_STATUS_TEST_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RDG_CAPABLE)) - { + if (pAd->MlmeAux.APRalinkIe != 0x0) { + if (CLIENT_STATUS_TEST_FLAG + (pEntry, fCLIENT_STATUS_RDG_CAPABLE)) { AsicEnableRDG(pAd); } - OPSTATUS_SET_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET); - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RALINK_CHIPSET); - } - else - { + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_RALINK_CHIPSET); + } else { OPSTATUS_CLEAR_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET); - CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RALINK_CHIPSET); + CLIENT_STATUS_CLEAR_FLAG(pEntry, + fCLIENT_STATUS_RALINK_CHIPSET); } } - DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_CONNECT Event B!.BACapability = %x. ClientStatusFlags = %lx\n", pAd->CommonCfg.BACapability.word, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); + DBGPRINT(RT_DEBUG_TRACE, + ("NDIS_STATUS_MEDIA_CONNECT Event B!.BACapability = %x. ClientStatusFlags = %lx\n", + pAd->CommonCfg.BACapability.word, + pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); - // Set LED + /* Set LED */ RTMPSetLED(pAd, LED_LINK_UP); pAd->Mlme.PeriodicRound = 0; pAd->Mlme.OneSecPeriodicRound = 0; - pAd->bConfigChanged = FALSE; // Reset config flag - pAd->ExtraInfo = GENERAL_LINK_UP; // Update extra information to link is up + pAd->bConfigChanged = FALSE; /* Reset config flag */ + pAd->ExtraInfo = GENERAL_LINK_UP; /* Update extra information to link is up */ - // Set asic auto fall back + /* Set asic auto fall back */ { - PUCHAR pTable; - UCHAR TableSize = 0; + u8 *pTable; + u8 TableSize = 0; - MlmeSelectTxRateTable(pAd, &pAd->MacTab.Content[BSSID_WCID], &pTable, &TableSize, &pAd->CommonCfg.TxRateIndex); + MlmeSelectTxRateTable(pAd, &pAd->MacTab.Content[BSSID_WCID], + &pTable, &TableSize, + &pAd->CommonCfg.TxRateIndex); AsicUpdateAutoFallBackTable(pAd, pTable); } NdisAcquireSpinLock(&pAd->MacTabLock); - pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word; - pEntry->MaxHTPhyMode.word = pAd->StaCfg.HTPhyMode.word; - if (pAd->StaCfg.bAutoTxRateSwitch == FALSE) - { + pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word; + pEntry->MaxHTPhyMode.word = pAd->StaCfg.HTPhyMode.word; + if (pAd->StaCfg.bAutoTxRateSwitch == FALSE) { pEntry->bAutoTxRateSwitch = FALSE; if (pEntry->HTPhyMode.field.MCS == 32) pEntry->HTPhyMode.field.ShortGI = GI_800; - if ((pEntry->HTPhyMode.field.MCS > MCS_7) || (pEntry->HTPhyMode.field.MCS == 32)) + if ((pEntry->HTPhyMode.field.MCS > MCS_7) + || (pEntry->HTPhyMode.field.MCS == 32)) pEntry->HTPhyMode.field.STBC = STBC_NONE; - // If the legacy mode is set, overwrite the transmit setting of this entry. + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ if (pEntry->HTPhyMode.field.MODE <= MODE_OFDM) - RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); - } - else + RTMPUpdateLegacyTxSetting((u8)pAd->StaCfg. + DesiredTransmitSetting.field. + FixedTxMode, pEntry); + } else pEntry->bAutoTxRateSwitch = TRUE; NdisReleaseSpinLock(&pAd->MacTabLock); - // Let Link Status Page display first initial rate. - pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word); - // Select DAC according to HT or Legacy - if (pAd->StaActive.SupportedPhyInfo.MCSSet[0] != 0x00) - { + /* Let Link Status Page display first initial rate. */ + pAd->LastTxRate = (u16)(pEntry->HTPhyMode.word); + /* Select DAC according to HT or Legacy */ + if (pAd->StaActive.SupportedPhyInfo.MCSSet[0] != 0x00) { RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value); Value &= (~0x18); - if (pAd->Antenna.field.TxPath == 2) - { - Value |= 0x10; + if (pAd->Antenna.field.TxPath == 2) { + Value |= 0x10; } RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value); - } - else - { + } else { RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value); Value &= (~0x18); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value); } - if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) - { - } - else if (pEntry->MaxRAmpduFactor == 0) - { - // If HT AP doesn't support MaxRAmpduFactor = 1, we need to set max PSDU to 0. - // Because our Init value is 1 at MACRegTable. + if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) { + } else if (pEntry->MaxRAmpduFactor == 0) { + /* If HT AP doesn't support MaxRAmpduFactor = 1, we need to set max PSDU to 0. */ + /* Because our Init value is 1 at MACRegTable. */ RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x0fff); } - - // Patch for Marvel AP to gain high throughput - // Need to set as following, - // 1. Set txop in register-EDCA_AC0_CFG as 0x60 - // 2. Set EnTXWriteBackDDONE in register-WPDMA_GLO_CFG as zero - // 3. PBF_MAX_PCNT as 0x1F3FBF9F - // 4. kick per two packets when dequeue - // - // Txop can only be modified when RDG is off, WMM is disable and TxBurst is enable - // - // if 1. Legacy AP WMM on, or 2. 11n AP, AMPDU disable. Force turn off burst no matter what bEnableTxBurst is. - if ( - !(pAd->CommonCfg.RxStream == 1 && pAd->CommonCfg.TxStream == 1) && - (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) - || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE)))) - { + /* Patch for Marvel AP to gain high throughput */ + /* Need to set as following, */ + /* 1. Set txop in register-EDCA_AC0_CFG as 0x60 */ + /* 2. Set EnTXWriteBackDDONE in register-WPDMA_GLO_CFG as zero */ + /* 3. PBF_MAX_PCNT as 0x1F3FBF9F */ + /* 4. kick per two packets when dequeue */ + /* */ + /* Txop can only be modified when RDG is off, WMM is disable and TxBurst is enable */ + /* */ + /* if 1. Legacy AP WMM on, or 2. 11n AP, AMPDU disable. Force turn off burst no matter what bEnableTxBurst is. */ + if (!((pAd->CommonCfg.RxStream == 1) && (pAd->CommonCfg.TxStream == 1)) + && (pAd->StaCfg.bForceTxBurst == FALSE) + && + (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) + && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) + || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) + && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE)))) { RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); - Data &= 0xFFFFFF00; + Data &= 0xFFFFFF00; RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F); DBGPRINT(RT_DEBUG_TRACE, ("Txburst 1\n")); - } - else - if (pAd->CommonCfg.bEnableTxBurst) - { + } else if (pAd->CommonCfg.bEnableTxBurst) { RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); - Data &= 0xFFFFFF00; - Data |= 0x60; + Data &= 0xFFFFFF00; + Data |= 0x60; RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = TRUE; RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3FBF9F); DBGPRINT(RT_DEBUG_TRACE, ("Txburst 2\n")); - } - else - { + } else { RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); - Data &= 0xFFFFFF00; + Data &= 0xFFFFFF00; RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F); DBGPRINT(RT_DEBUG_TRACE, ("Txburst 3\n")); } - // Re-check to turn on TX burst or not. - if ((pAd->CommonCfg.IOTestParm.bLastAtheros == TRUE) && ((STA_WEP_ON(pAd))||(STA_TKIP_ON(pAd)))) - { + /* Re-check to turn on TX burst or not. */ + if ((pAd->CommonCfg.IOTestParm.bLastAtheros == TRUE) + && ((STA_WEP_ON(pAd)) || (STA_TKIP_ON(pAd)))) { pAd->CommonCfg.IOTestParm.bNextDisableRxBA = TRUE; - if (pAd->CommonCfg.bEnableTxBurst) - { - UINT32 MACValue = 0; - // Force disable TXOP value in this case. The same action in MLMEUpdateProtect too. - // I didn't change PBF_MAX_PCNT setting. + if (pAd->CommonCfg.bEnableTxBurst) { + u32 MACValue = 0; + /* Force disable TXOP value in this case. The same action in MLMEUpdateProtect too. */ + /* I didn't change PBF_MAX_PCNT setting. */ RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &MACValue); - MACValue &= 0xFFFFFF00; + MACValue &= 0xFFFFFF00; RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, MACValue); pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE; } - } - else - { + } else { pAd->CommonCfg.IOTestParm.bNextDisableRxBA = FALSE; } pAd->CommonCfg.IOTestParm.bLastAtheros = FALSE; COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid); - DBGPRINT(RT_DEBUG_TRACE, ("!!!pAd->bNextDisableRxBA= %d \n", pAd->CommonCfg.IOTestParm.bNextDisableRxBA)); - // BSSID add in one MAC entry too. Because in Tx, ASIC need to check Cipher and IV/EIV, BAbitmap - // Pther information in MACTab.Content[BSSID_WCID] is not necessary for driver. - // Note: As STA, The MACTab.Content[BSSID_WCID]. PairwiseKey and Shared Key for BSS0 are the same. - - if (pAd->StaCfg.WepStatus <= Ndis802_11WEPDisabled) - { - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + DBGPRINT(RT_DEBUG_TRACE, + ("pAd->bNextDisableRxBA= %d \n", + pAd->CommonCfg.IOTestParm.bNextDisableRxBA)); + /* BSSID add in one MAC entry too. Because in Tx, ASIC need to check Cipher and IV/EIV, BAbitmap */ + /* Pther information in MACTab.Content[BSSID_WCID] is not necessary for driver. */ + /* Note: As STA, The MACTab.Content[BSSID_WCID]. PairwiseKey and Shared Key for BSS0 are the same. */ + + if (pAd->StaCfg.WepStatus <= Ndis802_11WEPDisabled) { + if (pAd->StaCfg.WpaSupplicantUP && + (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) && + (pAd->StaCfg.IEEE8021X == TRUE)) ; + else { + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + pAd->StaCfg.PrivacyFilter = + Ndis802_11PrivFilterAcceptAll; + } } NdisAcquireSpinLock(&pAd->MacTabLock); pEntry->PortSecured = pAd->StaCfg.PortSecured; NdisReleaseSpinLock(&pAd->MacTabLock); - // - // Patch Atheros AP TX will breakdown issue. - // AP Model: DLink DWL-8200AP - // - if (INFRA_ON(pAd) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && STA_TKIP_ON(pAd)) - { + /* */ + /* Patch Atheros AP TX will breakdown issue. */ + /* AP Model: DLink DWL-8200AP */ + /* */ + if (INFRA_ON(pAd) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) + && STA_TKIP_ON(pAd)) { RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x01); - } - else - { + } else { RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x00); } RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); -#ifdef RT2860 + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); -#endif } /* @@ -1822,220 +1873,190 @@ VOID LinkUp( ========================================================================== */ -VOID LinkDown( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN IsReqFromAP) +void LinkDown(struct rt_rtmp_adapter *pAd, IN BOOLEAN IsReqFromAP) { - UCHAR i, ByteValue = 0; -#ifdef RT2860 - BOOLEAN Cancelled; -#endif + u8 i, ByteValue = 0; - // Do nothing if monitor mode is on + /* Do nothing if monitor mode is on */ if (MONITOR_ON(pAd)) return; -#ifdef RT2860 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - - // Not allow go to sleep within linkdown function. + /*Comment the codes, beasue the line 2291 call the same function. */ + /*RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); */ + /* Not allow go to sleep within linkdown function. */ RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); -#endif - if (pAd->CommonCfg.bWirelessEvent) - { - RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + if (pAd->CommonCfg.bWirelessEvent) { + RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, + pAd->MacTab.Content[BSSID_WCID].Addr, + BSS0, 0); } - DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN !!!\n")); + DBGPRINT(RT_DEBUG_TRACE, ("LINK DOWN!\n")); OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); -#ifdef RT2860 - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) - { - BOOLEAN Cancelled; - pAd->Mlme.bPsPollTimerRunning = FALSE; - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - } - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) || - RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) - { - AsicForceWakeup(pAd, RTMP_HALT); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); - } - - pAd->bPCIclkOff = FALSE; -#endif - if (ADHOC_ON(pAd)) // Adhoc mode link down +#ifdef RTMP_MAC_PCI + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { + BOOLEAN Cancelled; + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + } + + pAd->bPCIclkOff = FALSE; +#endif /* RTMP_MAC_PCI // */ + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) + || RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND) + || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) { + AUTO_WAKEUP_STRUC AutoWakeupCfg; + AsicForceWakeup(pAd, TRUE); + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + } +#ifdef RTMP_MAC_PCI + pAd->bPCIclkOff = FALSE; +#endif /* RTMP_MAC_PCI // */ + + if (ADHOC_ON(pAd)) /* Adhoc mode link down */ { - DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 1!!!\n")); + DBGPRINT(RT_DEBUG_TRACE, ("LINK DOWN 1!\n")); OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); pAd->IndicateMediaState = NdisMediaStateDisconnected; RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_DOWN; - BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("!!! MacTab.Size=%d !!!\n", pAd->MacTab.Size)); - } - else // Infra structure mode + pAd->ExtraInfo = GENERAL_LINK_DOWN; + BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, + pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, + (" MacTab.Size=%d !\n", pAd->MacTab.Size)); + } else /* Infra structure mode */ { - DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 2!!!\n")); + DBGPRINT(RT_DEBUG_TRACE, ("LINK DOWN 2!\n")); OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); - // Saved last SSID for linkup comparison + /* Saved last SSID for linkup comparison */ pAd->CommonCfg.LastSsidLen = pAd->CommonCfg.SsidLen; - NdisMoveMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen); + NdisMoveMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, + pAd->CommonCfg.LastSsidLen); COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid); - if (pAd->MlmeAux.CurrReqIsFromNdis == TRUE) - { + if (pAd->MlmeAux.CurrReqIsFromNdis == TRUE) { pAd->IndicateMediaState = NdisMediaStateDisconnected; RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_DOWN; - DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event A!\n")); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, + ("NDIS_STATUS_MEDIA_DISCONNECT Event A!\n")); pAd->MlmeAux.CurrReqIsFromNdis = FALSE; - } - else - { - // - // If disassociation request is from NDIS, then we don't need to delete BSSID from entry. - // Otherwise lost beacon or receive De-Authentication from AP, - // then we should delete BSSID from BssTable. - // If we don't delete from entry, roaming will fail. - // - BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel); + } else { + /* */ + /* If disassociation request is from NDIS, then we don't need to delete BSSID from entry. */ + /* Otherwise lost beacon or receive De-Authentication from AP, */ + /* then we should delete BSSID from BssTable. */ + /* If we don't delete from entry, roaming will fail. */ + /* */ + BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, + pAd->CommonCfg.Channel); } - // restore back to - - // 1. long slot (20 us) or short slot (9 us) time - // 2. turn on/off RTS/CTS and/or CTS-to-self protection - // 3. short preamble + /* restore back to - */ + /* 1. long slot (20 us) or short slot (9 us) time */ + /* 2. turn on/off RTS/CTS and/or CTS-to-self protection */ + /* 3. short preamble */ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); - if (pAd->StaCfg.CCXAdjacentAPReportFlag == TRUE) - { - // - // Record current AP's information. - // for later used reporting Adjacent AP report. - // - pAd->StaCfg.CCXAdjacentAPChannel = pAd->CommonCfg.Channel; - pAd->StaCfg.CCXAdjacentAPSsidLen = pAd->CommonCfg.SsidLen; - NdisMoveMemory(pAd->StaCfg.CCXAdjacentAPSsid, pAd->CommonCfg.Ssid, pAd->StaCfg.CCXAdjacentAPSsidLen); - COPY_MAC_ADDR(pAd->StaCfg.CCXAdjacentAPBssid, pAd->CommonCfg.Bssid); - } } - for (i=1; iMacTab.Content[i].ValidAsCLI == TRUE) - MacTableDeleteEntry(pAd, pAd->MacTab.Content[i].Aid, pAd->MacTab.Content[i].Addr); + MacTableDeleteEntry(pAd, pAd->MacTab.Content[i].Aid, + pAd->MacTab.Content[i].Addr); } - pAd->StaCfg.CCXQosECWMin = 4; - pAd->StaCfg.CCXQosECWMax = 10; - - AsicSetSlotTime(pAd, TRUE); //FALSE); + AsicSetSlotTime(pAd, TRUE); /*FALSE); */ AsicSetEdcaParm(pAd, NULL); - // Set LED + /* Set LED */ RTMPSetLED(pAd, LED_LINK_DOWN); - pAd->LedIndicatorStregth = 0xF0; - RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it. + pAd->LedIndicatorStrength = 0xF0; + RTMPSetSignalLED(pAd, -100); /* Force signal strength Led to be turned off, firmware is not done it. */ - AsicDisableSync(pAd); + AsicDisableSync(pAd); pAd->Mlme.PeriodicRound = 0; pAd->Mlme.OneSecPeriodicRound = 0; - if (pAd->StaCfg.BssType == BSS_INFRA) - { - // Remove StaCfg Information after link down + if (pAd->StaCfg.BssType == BSS_INFRA) { + /* Remove StaCfg Information after link down */ NdisZeroMemory(pAd->CommonCfg.Bssid, MAC_ADDR_LEN); NdisZeroMemory(pAd->CommonCfg.Ssid, MAX_LEN_OF_SSID); pAd->CommonCfg.SsidLen = 0; } - NdisZeroMemory(&pAd->MlmeAux.HtCapability, sizeof(HT_CAPABILITY_IE)); - NdisZeroMemory(&pAd->MlmeAux.AddHtInfo, sizeof(ADD_HT_INFO_IE)); + NdisZeroMemory(&pAd->MlmeAux.HtCapability, sizeof(struct rt_ht_capability_ie)); + NdisZeroMemory(&pAd->MlmeAux.AddHtInfo, sizeof(struct rt_add_ht_info_ie)); pAd->MlmeAux.HtCapabilityLen = 0; pAd->MlmeAux.NewExtChannelOffset = 0xff; - // Reset WPA-PSK state. Only reset when supplicant enabled - if (pAd->StaCfg.WpaState != SS_NOTUSE) - { + /* Reset WPA-PSK state. Only reset when supplicant enabled */ + if (pAd->StaCfg.WpaState != SS_NOTUSE) { pAd->StaCfg.WpaState = SS_START; - // Clear Replay counter + /* Clear Replay counter */ NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); - } - - // - // if link down come from AP, we need to remove all WPA keys on WPA mode. - // otherwise will cause 4-way handshaking failed, since the WPA key not empty. - // - if ((IsReqFromAP) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) - { - // Remove all WPA keys + } + /* */ + /* if link down come from AP, we need to remove all WPA keys on WPA mode. */ + /* otherwise will cause 4-way handshaking failed, since the WPA key not empty. */ + /* */ + if ((IsReqFromAP) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) { + /* Remove all WPA keys */ RTMPWPARemoveAllKeys(pAd); } + /* 802.1x port control */ - // 802.1x port control - - // Prevent clear PortSecured here with static WEP - // NetworkManger set security policy first then set SSID to connect AP. + /* Prevent clear PortSecured here with static WEP */ + /* NetworkManger set security policy first then set SSID to connect AP. */ if (pAd->StaCfg.WpaSupplicantUP && - (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) && - (pAd->StaCfg.IEEE8021X == FALSE)) - { + (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) && + (pAd->StaCfg.IEEE8021X == FALSE)) { pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - } - else - { + } else { pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; } NdisAcquireSpinLock(&pAd->MacTabLock); + NdisZeroMemory(&pAd->MacTab, sizeof(struct rt_mac_table)); pAd->MacTab.Content[BSSID_WCID].PortSecured = pAd->StaCfg.PortSecured; NdisReleaseSpinLock(&pAd->MacTabLock); pAd->StaCfg.MicErrCnt = 0; - // Turn off Ckip control flag - pAd->StaCfg.bCkipOn = FALSE; - pAd->StaCfg.CCXEnable = FALSE; - - pAd->IndicateMediaState = NdisMediaStateDisconnected; - // Update extra information to link is up + pAd->IndicateMediaState = NdisMediaStateDisconnected; + /* Update extra information to link is up */ pAd->ExtraInfo = GENERAL_LINK_DOWN; -#ifdef RT2860 - pAd->StaCfg.AdhocBOnlyJoined = FALSE; - pAd->StaCfg.AdhocBGJoined = FALSE; - pAd->StaCfg.Adhoc20NJoined = FALSE; -#endif - pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; - // Reset the Current AP's IP address - NdisZeroMemory(pAd->StaCfg.AironetIPAddress, 4); -#ifdef RT2870 +#ifdef RTMP_MAC_USB pAd->bUsbTxBulkAggre = FALSE; -#endif // RT2870 // +#endif /* RTMP_MAC_USB // */ - // Clean association information - NdisZeroMemory(&pAd->StaCfg.AssocInfo, sizeof(NDIS_802_11_ASSOCIATION_INFORMATION)); - pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + /* Clean association information */ + NdisZeroMemory(&pAd->StaCfg.AssocInfo, + sizeof(struct rt_ndis_802_11_association_information)); + pAd->StaCfg.AssocInfo.Length = + sizeof(struct rt_ndis_802_11_association_information); pAd->StaCfg.ReqVarIELen = 0; pAd->StaCfg.ResVarIELen = 0; - // - // Reset RSSI value after link down - // + /* */ + /* Reset RSSI value after link down */ + /* */ pAd->StaCfg.RssiSample.AvgRssi0 = 0; pAd->StaCfg.RssiSample.AvgRssi0X8 = 0; pAd->StaCfg.RssiSample.AvgRssi1 = 0; @@ -2043,37 +2064,36 @@ VOID LinkDown( pAd->StaCfg.RssiSample.AvgRssi2 = 0; pAd->StaCfg.RssiSample.AvgRssi2X8 = 0; - // Restore MlmeRate + /* Restore MlmeRate */ pAd->CommonCfg.MlmeRate = pAd->CommonCfg.BasicMlmeRate; pAd->CommonCfg.RtsRate = pAd->CommonCfg.BasicMlmeRate; - // - // After Link down, reset piggy-back setting in ASIC. Disable RDG. - // - if (pAd->CommonCfg.BBPCurrentBW == BW_40) - { + /* */ + /* After Link down, reset piggy-back setting in ASIC. Disable RDG. */ + /* */ + if (pAd->CommonCfg.BBPCurrentBW == BW_40) { pAd->CommonCfg.BBPCurrentBW = BW_20; RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &ByteValue); ByteValue &= (~0x18); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, ByteValue); } - - // Reset DAC + /* Reset DAC */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &ByteValue); ByteValue &= (~0x18); - if (pAd->Antenna.field.TxPath == 2) - { + if (pAd->Antenna.field.TxPath == 2) { ByteValue |= 0x10; } RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, ByteValue); - RTMPSetPiggyBack(pAd,FALSE); + RTMPSetPiggyBack(pAd, FALSE); OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED); pAd->CommonCfg.BACapability.word = pAd->CommonCfg.REGBACapability.word; - // Restore all settings in the following. - AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE); + /* Restore all settings in the following. */ + AsicUpdateProtect(pAd, 0, + (ALLN_SETPROTECT | CCKSETPROTECT | OFDMSETPROTECT), + TRUE, FALSE); AsicDisableRDG(pAd); pAd->CommonCfg.IOTestParm.bCurrentAtheros = FALSE; pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE; @@ -2081,30 +2101,17 @@ VOID LinkDown( RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x1fff); RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); -#ifdef RT2860 - // Allow go to sleep after linkdown steps. +/* Allow go to sleep after linkdown steps. */ RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); -#endif - { - union iwreq_data wrqu; - memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); - wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); - } + RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, 0); - if (IS_RT3090(pAd)) - { - UINT32 macdata; - // disable MMPS BBP control register - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &ByteValue); - ByteValue &= ~(0x04); //bit 2 - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, ByteValue); - - // disable MMPS MAC control register - RTMP_IO_READ32(pAd, 0x1210, &macdata); - macdata &= ~(0x09); //bit 0, 3 - RTMP_IO_WRITE32(pAd, 0x1210, macdata); +#ifdef RT30xx + if ((IS_RT30xx(pAd) || IS_RT3090(pAd) || IS_RT3390(pAd)) + && (pAd->Antenna.field.RxPath > 1 || pAd->Antenna.field.TxPath > 1)) { + RTMP_ASIC_MMPS_DISABLE(pAd); } +#endif /* RT30xx // */ } /* @@ -2115,112 +2122,148 @@ VOID LinkDown( ========================================================================== */ -VOID IterateOnBssTab( - IN PRTMP_ADAPTER pAd) +void IterateOnBssTab(struct rt_rtmp_adapter *pAd) { - MLME_START_REQ_STRUCT StartReq; - MLME_JOIN_REQ_STRUCT JoinReq; - ULONG BssIdx; + struct rt_mlme_start_req StartReq; + struct rt_mlme_join_req JoinReq; + unsigned long BssIdx; - // Change the wepstatus to original wepstatus - pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus; - pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus; + /* Change the wepstatus to original wepstatus */ + pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus; + pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus; pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus; BssIdx = pAd->MlmeAux.BssIdx; - if (BssIdx < pAd->MlmeAux.SsidBssTab.BssNr) - { - // Check cipher suite, AP must have more secured cipher than station setting - // Set the Pairwise and Group cipher to match the intended AP setting - // We can only connect to AP with less secured cipher setting - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) - { - pAd->StaCfg.GroupCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.GroupCipher; - - if (pAd->StaCfg.WepStatus == pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipher) - pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipher; - else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipherAux != Ndis802_11WEPDisabled) - pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipherAux; - else // There is no PairCipher Aux, downgrade our capability to TKIP - pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; - } - else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - pAd->StaCfg.GroupCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.GroupCipher; - - if (pAd->StaCfg.WepStatus == pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipher) - pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipher; - else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipherAux != Ndis802_11WEPDisabled) - pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipherAux; - else // There is no PairCipher Aux, downgrade our capability to TKIP - pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; - - // RSN capability - pAd->StaCfg.RsnCapability = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.RsnCapability; - } - - // Set Mix cipher flag - pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE; - if (pAd->StaCfg.bMixCipher == TRUE) - { - // If mix cipher, re-build RSNIE - RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0); + if (BssIdx < pAd->MlmeAux.SsidBssTab.BssNr) { + /* Check cipher suite, AP must have more secured cipher than station setting */ + /* Set the Pairwise and Group cipher to match the intended AP setting */ + /* We can only connect to AP with less secured cipher setting */ + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) { + pAd->StaCfg.GroupCipher = + pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA. + GroupCipher; + + if (pAd->StaCfg.WepStatus == + pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA. + PairCipher) + pAd->StaCfg.PairCipher = + pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx]. + WPA.PairCipher; + else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA. + PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = + pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx]. + WPA.PairCipherAux; + else /* There is no PairCipher Aux, downgrade our capability to TKIP */ + pAd->StaCfg.PairCipher = + Ndis802_11Encryption2Enabled; + } else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) + || (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2PSK)) { + pAd->StaCfg.GroupCipher = + pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2. + GroupCipher; + + if (pAd->StaCfg.WepStatus == + pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2. + PairCipher) + pAd->StaCfg.PairCipher = + pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx]. + WPA2.PairCipher; + else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2. + PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = + pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx]. + WPA2.PairCipherAux; + else /* There is no PairCipher Aux, downgrade our capability to TKIP */ + pAd->StaCfg.PairCipher = + Ndis802_11Encryption2Enabled; + + /* RSN capability */ + pAd->StaCfg.RsnCapability = + pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2. + RsnCapability; } - - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - iterate BSS %ld of %d\n", BssIdx, pAd->MlmeAux.SsidBssTab.BssNr)); + /* Set Mix cipher flag */ + pAd->StaCfg.bMixCipher = + (pAd->StaCfg.PairCipher == + pAd->StaCfg.GroupCipher) ? FALSE : TRUE; + /*if (pAd->StaCfg.bMixCipher == TRUE) + { + // If mix cipher, re-build RSNIE + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0); + } */ + + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - iterate BSS %ld of %d\n", BssIdx, + pAd->MlmeAux.SsidBssTab.BssNr)); JoinParmFill(pAd, &JoinReq, BssIdx); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT), - &JoinReq); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, + sizeof(struct rt_mlme_join_req), &JoinReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN; - } - else if (pAd->StaCfg.BssType == BSS_ADHOC) - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All BSS fail; start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid)); - StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq); + } else if (pAd->StaCfg.BssType == BSS_ADHOC) { + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - All BSS fail; start a new ADHOC (Ssid=%s)...\n", + pAd->MlmeAux.Ssid)); + StartParmFill(pAd, &StartReq, (char *)pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, + sizeof(struct rt_mlme_start_req), &StartReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; - } - else // no more BSS + } else /* no more BSS */ { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All roaming failed, stay @ ch #%d\n", pAd->CommonCfg.Channel)); - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - All roaming failed, restore to channel %d, Total BSS[%02d]\n", + pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); + } + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; } } -// for re-association only -// IRQL = DISPATCH_LEVEL -VOID IterateOnBssTab2( - IN PRTMP_ADAPTER pAd) +/* for re-association only */ +/* IRQL = DISPATCH_LEVEL */ +void IterateOnBssTab2(struct rt_rtmp_adapter *pAd) { - MLME_REASSOC_REQ_STRUCT ReassocReq; - ULONG BssIdx; - BSS_ENTRY *pBss; + struct rt_mlme_assoc_req ReassocReq; + unsigned long BssIdx; + struct rt_bss_entry *pBss; BssIdx = pAd->MlmeAux.RoamIdx; pBss = &pAd->MlmeAux.RoamTab.BssEntry[BssIdx]; - if (BssIdx < pAd->MlmeAux.RoamTab.BssNr) - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - iterate BSS %ld of %d\n", BssIdx, pAd->MlmeAux.RoamTab.BssNr)); + if (BssIdx < pAd->MlmeAux.RoamTab.BssNr) { + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - iterate BSS %ld of %d\n", BssIdx, + pAd->MlmeAux.RoamTab.BssNr)); AsicSwitchChannel(pAd, pBss->Channel, FALSE); AsicLockChannel(pAd, pBss->Channel); - // reassociate message has the same structure as associate message - AssocParmFill(pAd, &ReassocReq, pBss->Bssid, pBss->CapabilityInfo, - ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount); + /* reassociate message has the same structure as associate message */ + AssocParmFill(pAd, &ReassocReq, pBss->Bssid, + pBss->CapabilityInfo, ASSOC_TIMEOUT, + pAd->StaCfg.DefaultListenCount); MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_REASSOC_REQ, - sizeof(MLME_REASSOC_REQ_STRUCT), &ReassocReq); + sizeof(struct rt_mlme_assoc_req), &ReassocReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC; - } - else // no more BSS + } else /* no more BSS */ { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All fast roaming failed, back to ch #%d\n",pAd->CommonCfg.Channel)); - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - All roaming failed, restore to channel %d, Total BSS[%02d]\n", + pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); + } + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; } } @@ -2233,10 +2276,8 @@ VOID IterateOnBssTab2( ========================================================================== */ -VOID JoinParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_JOIN_REQ_STRUCT *JoinReq, - IN ULONG BssIdx) +void JoinParmFill(struct rt_rtmp_adapter *pAd, + struct rt_mlme_join_req *JoinReq, unsigned long BssIdx) { JoinReq->BssIdx = BssIdx; } @@ -2249,15 +2290,12 @@ VOID JoinParmFill( ========================================================================== */ -VOID ScanParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_SCAN_REQ_STRUCT *ScanReq, - IN CHAR Ssid[], - IN UCHAR SsidLen, - IN UCHAR BssType, - IN UCHAR ScanType) +void ScanParmFill(struct rt_rtmp_adapter *pAd, + struct rt_mlme_scan_req *ScanReq, + char Ssid[], + u8 SsidLen, u8 BssType, u8 ScanType) { - NdisZeroMemory(ScanReq->Ssid, MAX_LEN_OF_SSID); + NdisZeroMemory(ScanReq->Ssid, MAX_LEN_OF_SSID); ScanReq->SsidLen = SsidLen; NdisMoveMemory(ScanReq->Ssid, Ssid, SsidLen); ScanReq->BssType = BssType; @@ -2272,11 +2310,9 @@ VOID ScanParmFill( ========================================================================== */ -VOID StartParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_START_REQ_STRUCT *StartReq, - IN CHAR Ssid[], - IN UCHAR SsidLen) +void StartParmFill(struct rt_rtmp_adapter *pAd, + struct rt_mlme_start_req *StartReq, + char Ssid[], u8 SsidLen) { ASSERT(SsidLen <= MAX_LEN_OF_SSID); NdisMoveMemory(StartReq->Ssid, Ssid, SsidLen); @@ -2291,11 +2327,9 @@ VOID StartParmFill( ========================================================================== */ -VOID AuthParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_AUTH_REQ_STRUCT *AuthReq, - IN PUCHAR pAddr, - IN USHORT Alg) +void AuthParmFill(struct rt_rtmp_adapter *pAd, + struct rt_mlme_auth_req *AuthReq, + u8 *pAddr, u16 Alg) { COPY_MAC_ADDR(AuthReq->Addr, pAddr); AuthReq->Alg = Alg; @@ -2310,82 +2344,109 @@ VOID AuthParmFill( ========================================================================== */ +#ifdef RTMP_MAC_PCI +void ComposePsPoll(struct rt_rtmp_adapter *pAd) +{ + NdisZeroMemory(&pAd->PsPollFrame, sizeof(struct rt_pspoll_frame)); + pAd->PsPollFrame.FC.Type = BTYPE_CNTL; + pAd->PsPollFrame.FC.SubType = SUBTYPE_PS_POLL; + pAd->PsPollFrame.Aid = pAd->StaActive.Aid | 0xC000; + COPY_MAC_ADDR(pAd->PsPollFrame.Bssid, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pAd->PsPollFrame.Ta, pAd->CurrentAddress); +} - -#ifdef RT2870 - -VOID MlmeCntlConfirm( - IN PRTMP_ADAPTER pAd, - IN ULONG MsgType, - IN USHORT Msg) +/* IRQL = DISPATCH_LEVEL */ +void ComposeNullFrame(struct rt_rtmp_adapter *pAd) { - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MsgType, sizeof(USHORT), &Msg); + NdisZeroMemory(&pAd->NullFrame, sizeof(struct rt_header_802_11)); + pAd->NullFrame.FC.Type = BTYPE_DATA; + pAd->NullFrame.FC.SubType = SUBTYPE_NULL_FUNC; + pAd->NullFrame.FC.ToDs = 1; + COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->CommonCfg.Bssid); +} +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB +void MlmeCntlConfirm(struct rt_rtmp_adapter *pAd, unsigned long MsgType, u16 Msg) +{ + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MsgType, sizeof(u16), + &Msg); } -#endif -VOID ComposePsPoll( - IN PRTMP_ADAPTER pAd) +void ComposePsPoll(struct rt_rtmp_adapter *pAd) { -#ifdef RT2870 - PTXINFO_STRUC pTxInfo; - PTXWI_STRUC pTxWI; + struct rt_txinfo *pTxInfo; + struct rt_txwi * pTxWI; DBGPRINT(RT_DEBUG_TRACE, ("ComposePsPoll\n")); -#endif - NdisZeroMemory(&pAd->PsPollFrame, sizeof(PSPOLL_FRAME)); + NdisZeroMemory(&pAd->PsPollFrame, sizeof(struct rt_pspoll_frame)); -#ifdef RT2870 pAd->PsPollFrame.FC.PwrMgmt = 0; -#endif pAd->PsPollFrame.FC.Type = BTYPE_CNTL; pAd->PsPollFrame.FC.SubType = SUBTYPE_PS_POLL; pAd->PsPollFrame.Aid = pAd->StaActive.Aid | 0xC000; COPY_MAC_ADDR(pAd->PsPollFrame.Bssid, pAd->CommonCfg.Bssid); COPY_MAC_ADDR(pAd->PsPollFrame.Ta, pAd->CurrentAddress); -#ifdef RT2870 - RTMPZeroMemory(&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[0], 100); - pTxInfo = (PTXINFO_STRUC)&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[0]; - RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(PSPOLL_FRAME)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); - pTxWI = (PTXWI_STRUC)&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE]; - RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(PSPOLL_FRAME)), - 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); - RTMPMoveMemory(&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[TXWI_SIZE+TXINFO_SIZE], &pAd->PsPollFrame, sizeof(PSPOLL_FRAME)); - // Append 4 extra zero bytes. - pAd->PsPollContext.BulkOutSize = TXINFO_SIZE + TXWI_SIZE + sizeof(PSPOLL_FRAME) + 4; -#endif + RTMPZeroMemory(&pAd->PsPollContext.TransferBuffer->field. + WirelessPacket[0], 100); + pTxInfo = + (struct rt_txinfo *)& pAd->PsPollContext.TransferBuffer->field. + WirelessPacket[0]; + RTMPWriteTxInfo(pAd, pTxInfo, + (u16)(sizeof(struct rt_pspoll_frame) + TXWI_SIZE), TRUE, + EpToQueue[MGMTPIPEIDX], FALSE, FALSE); + pTxWI = + (struct rt_txwi *) & pAd->PsPollContext.TransferBuffer->field. + WirelessPacket[TXINFO_SIZE]; + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, + BSSID_WCID, (sizeof(struct rt_pspoll_frame)), 0, 0, + (u8)pAd->CommonCfg.MlmeTransmit.field.MCS, + IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); + RTMPMoveMemory(&pAd->PsPollContext.TransferBuffer->field. + WirelessPacket[TXWI_SIZE + TXINFO_SIZE], + &pAd->PsPollFrame, sizeof(struct rt_pspoll_frame)); + /* Append 4 extra zero bytes. */ + pAd->PsPollContext.BulkOutSize = + TXINFO_SIZE + TXWI_SIZE + sizeof(struct rt_pspoll_frame) + 4; } -// IRQL = DISPATCH_LEVEL -VOID ComposeNullFrame( - IN PRTMP_ADAPTER pAd) +/* IRQL = DISPATCH_LEVEL */ +void ComposeNullFrame(struct rt_rtmp_adapter *pAd) { -#ifdef RT2870 - PTXINFO_STRUC pTxInfo; - PTXWI_STRUC pTxWI; -#endif + struct rt_txinfo *pTxInfo; + struct rt_txwi * pTxWI; - NdisZeroMemory(&pAd->NullFrame, sizeof(HEADER_802_11)); + NdisZeroMemory(&pAd->NullFrame, sizeof(struct rt_header_802_11)); pAd->NullFrame.FC.Type = BTYPE_DATA; pAd->NullFrame.FC.SubType = SUBTYPE_NULL_FUNC; pAd->NullFrame.FC.ToDs = 1; COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->CommonCfg.Bssid); COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->CurrentAddress); COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->CommonCfg.Bssid); -#ifdef RT2870 - RTMPZeroMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[0], 100); - pTxInfo = (PTXINFO_STRUC)&pAd->NullContext.TransferBuffer->field.WirelessPacket[0]; - RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(HEADER_802_11)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); - pTxWI = (PTXWI_STRUC)&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE]; - RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(HEADER_802_11)), - 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); - RTMPMoveMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXWI_SIZE+TXINFO_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11)); - pAd->NullContext.BulkOutSize = TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4; -#endif + RTMPZeroMemory(&pAd->NullContext.TransferBuffer->field. + WirelessPacket[0], 100); + pTxInfo = + (struct rt_txinfo *)& pAd->NullContext.TransferBuffer->field. + WirelessPacket[0]; + RTMPWriteTxInfo(pAd, pTxInfo, + (u16)(sizeof(struct rt_header_802_11) + TXWI_SIZE), TRUE, + EpToQueue[MGMTPIPEIDX], FALSE, FALSE); + pTxWI = + (struct rt_txwi *) & pAd->NullContext.TransferBuffer->field. + WirelessPacket[TXINFO_SIZE]; + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, + BSSID_WCID, (sizeof(struct rt_header_802_11)), 0, 0, + (u8)pAd->CommonCfg.MlmeTransmit.field.MCS, + IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); + RTMPMoveMemory(&pAd->NullContext.TransferBuffer->field. + WirelessPacket[TXWI_SIZE + TXINFO_SIZE], &pAd->NullFrame, + sizeof(struct rt_header_802_11)); + pAd->NullContext.BulkOutSize = + TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4; } - - - +#endif /* RTMP_MAC_USB // */ /* ========================================================================== @@ -2397,73 +2458,71 @@ VOID ComposeNullFrame( ========================================================================== */ -ULONG MakeIbssBeacon( - IN PRTMP_ADAPTER pAd) +unsigned long MakeIbssBeacon(struct rt_rtmp_adapter *pAd) { - UCHAR DsLen = 1, IbssLen = 2; - UCHAR LocalErpIe[3] = {IE_ERP, 1, 0x04}; - HEADER_802_11 BcnHdr; - USHORT CapabilityInfo; + u8 DsLen = 1, IbssLen = 2; + u8 LocalErpIe[3] = { IE_ERP, 1, 0x04 }; + struct rt_header_802_11 BcnHdr; + u16 CapabilityInfo; LARGE_INTEGER FakeTimestamp; - ULONG FrameLen = 0; - PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; - CHAR *pBeaconFrame = pAd->BeaconBuf; - BOOLEAN Privacy; - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen = 0; - UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR ExtRateLen = 0; - UCHAR RSNIe = IE_WPA; - - if ((pAd->CommonCfg.PhyMode == PHY_11B) && (pAd->CommonCfg.Channel <= 14)) - { - SupRate[0] = 0x82; // 1 mbps - SupRate[1] = 0x84; // 2 mbps - SupRate[2] = 0x8b; // 5.5 mbps - SupRate[3] = 0x96; // 11 mbps + unsigned long FrameLen = 0; + struct rt_txwi * pTxWI = &pAd->BeaconTxWI; + u8 *pBeaconFrame = pAd->BeaconBuf; + BOOLEAN Privacy; + u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + u8 SupRateLen = 0; + u8 ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + u8 ExtRateLen = 0; + u8 RSNIe = IE_WPA; + + if ((pAd->CommonCfg.PhyMode == PHY_11B) + && (pAd->CommonCfg.Channel <= 14)) { + SupRate[0] = 0x82; /* 1 mbps */ + SupRate[1] = 0x84; /* 2 mbps */ + SupRate[2] = 0x8b; /* 5.5 mbps */ + SupRate[3] = 0x96; /* 11 mbps */ SupRateLen = 4; ExtRateLen = 0; - } - else if (pAd->CommonCfg.Channel > 14) - { - SupRate[0] = 0x8C; // 6 mbps, in units of 0.5 Mbps, basic rate - SupRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps - SupRate[2] = 0x98; // 12 mbps, in units of 0.5 Mbps, basic rate - SupRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps - SupRate[4] = 0xb0; // 24 mbps, in units of 0.5 Mbps, basic rate - SupRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps - SupRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps - SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps - SupRateLen = 8; - ExtRateLen = 0; - - // - // Also Update MlmeRate & RtsRate for G only & A only - // + } else if (pAd->CommonCfg.Channel > 14) { + SupRate[0] = 0x8C; /* 6 mbps, in units of 0.5 Mbps, basic rate */ + SupRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps */ + SupRate[2] = 0x98; /* 12 mbps, in units of 0.5 Mbps, basic rate */ + SupRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps */ + SupRate[4] = 0xb0; /* 24 mbps, in units of 0.5 Mbps, basic rate */ + SupRate[5] = 0x48; /* 36 mbps, in units of 0.5 Mbps */ + SupRate[6] = 0x60; /* 48 mbps, in units of 0.5 Mbps */ + SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps */ + SupRateLen = 8; + ExtRateLen = 0; + + /* */ + /* Also Update MlmeRate & RtsRate for G only & A only */ + /* */ pAd->CommonCfg.MlmeRate = RATE_6; pAd->CommonCfg.RtsRate = RATE_6; pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; - pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; - pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM; - pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; - } - else - { - SupRate[0] = 0x82; // 1 mbps - SupRate[1] = 0x84; // 2 mbps - SupRate[2] = 0x8b; // 5.5 mbps - SupRate[3] = 0x96; // 11 mbps + pAd->CommonCfg.MlmeTransmit.field.MCS = + OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = + MODE_OFDM; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = + OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } else { + SupRate[0] = 0x82; /* 1 mbps */ + SupRate[1] = 0x84; /* 2 mbps */ + SupRate[2] = 0x8b; /* 5.5 mbps */ + SupRate[3] = 0x96; /* 11 mbps */ SupRateLen = 4; - ExtRate[0] = 0x0C; // 6 mbps, in units of 0.5 Mbps, - ExtRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps - ExtRate[2] = 0x18; // 12 mbps, in units of 0.5 Mbps, - ExtRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps - ExtRate[4] = 0x30; // 24 mbps, in units of 0.5 Mbps, - ExtRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps - ExtRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps - ExtRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps - ExtRateLen = 8; + ExtRate[0] = 0x0C; /* 6 mbps, in units of 0.5 Mbps, */ + ExtRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps */ + ExtRate[2] = 0x18; /* 12 mbps, in units of 0.5 Mbps, */ + ExtRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps */ + ExtRate[4] = 0x30; /* 24 mbps, in units of 0.5 Mbps, */ + ExtRate[5] = 0x48; /* 36 mbps, in units of 0.5 Mbps */ + ExtRate[6] = 0x60; /* 48 mbps, in units of 0.5 Mbps */ + ExtRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps */ + ExtRateLen = 8; } pAd->StaActive.SupRateLen = SupRateLen; @@ -2471,99 +2530,96 @@ ULONG MakeIbssBeacon( pAd->StaActive.ExtRateLen = ExtRateLen; NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, ExtRateLen); - // compose IBSS beacon frame - MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pAd->CommonCfg.Bssid); - Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || - (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || - (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); - CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0); - - MakeOutgoingFrame(pBeaconFrame, &FrameLen, - sizeof(HEADER_802_11), &BcnHdr, - TIMESTAMP_LEN, &FakeTimestamp, - 2, &pAd->CommonCfg.BeaconPeriod, - 2, &CapabilityInfo, - 1, &SsidIe, - 1, &pAd->CommonCfg.SsidLen, - pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, - 1, &SupRateIe, - 1, &SupRateLen, - SupRateLen, SupRate, - 1, &DsIe, - 1, &DsLen, - 1, &pAd->CommonCfg.Channel, - 1, &IbssIe, - 1, &IbssLen, - 2, &pAd->StaActive.AtimWin, - END_OF_ARGS); - - // add ERP_IE and EXT_RAE IE of in 802.11g - if (ExtRateLen) - { - ULONG tmp; - - MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp, - 3, LocalErpIe, - 1, &ExtRateIe, - 1, &ExtRateLen, - ExtRateLen, ExtRate, - END_OF_ARGS); + /* compose IBSS beacon frame */ + MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, + pAd->CommonCfg.Bssid); + Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) + || (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) + || (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); + CapabilityInfo = + CAP_GENERATE(0, 1, Privacy, + (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), + 0, 0); + + MakeOutgoingFrame(pBeaconFrame, &FrameLen, + sizeof(struct rt_header_802_11), &BcnHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &CapabilityInfo, + 1, &SsidIe, + 1, &pAd->CommonCfg.SsidLen, + pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, SupRate, + 1, &DsIe, + 1, &DsLen, + 1, &pAd->CommonCfg.Channel, + 1, &IbssIe, + 1, &IbssLen, 2, &pAd->StaActive.AtimWin, END_OF_ARGS); + + /* add ERP_IE and EXT_RAE IE of in 802.11g */ + if (ExtRateLen) { + unsigned long tmp; + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp, + 3, LocalErpIe, + 1, &ExtRateIe, + 1, &ExtRateLen, + ExtRateLen, ExtRate, END_OF_ARGS); FrameLen += tmp; } - - // If adhoc secruity is set for WPA-None, append the cipher suite IE - if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - { - ULONG tmp; - RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0); - - MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp, - 1, &RSNIe, - 1, &pAd->StaCfg.RSNIE_Len, - pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, - END_OF_ARGS); + /* If adhoc secruity is set for WPA-None, append the cipher suite IE */ + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) { + unsigned long tmp; + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, + BSS0); + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp, + 1, &RSNIe, + 1, &pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, + END_OF_ARGS); FrameLen += tmp; } - if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - ULONG TmpLen; - UCHAR HtLen, HtLen1; + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) { + unsigned long TmpLen; + u8 HtLen, HtLen1; - // add HT Capability IE + /* add HT Capability IE */ HtLen = sizeof(pAd->CommonCfg.HtCapability); HtLen1 = sizeof(pAd->CommonCfg.AddHTInfo); - MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, - 1, &HtCapIe, - 1, &HtLen, - HtLen, &pAd->CommonCfg.HtCapability, - 1, &AddHtInfoIe, - 1, &HtLen1, - HtLen1, &pAd->CommonCfg.AddHTInfo, - END_OF_ARGS); + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); FrameLen += TmpLen; } - - //beacon use reserved WCID 0xff - if (pAd->CommonCfg.Channel > 14) - { - RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen, - PID_MGMT, PID_BEACON, RATE_1, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit); - } - else - { - // Set to use 1Mbps for Adhoc beacon. + /*beacon use reserved WCID 0xff */ + if (pAd->CommonCfg.Channel > 14) { + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, + TRUE, 0, 0xff, FrameLen, PID_MGMT, PID_BEACON, + RATE_1, IFS_HTTXOP, FALSE, + &pAd->CommonCfg.MlmeTransmit); + } else { + /* Set to use 1Mbps for Adhoc beacon. */ HTTRANSMIT_SETTING Transmit; - Transmit.word = 0; - RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen, - PID_MGMT, PID_BEACON, RATE_1, IFS_HTTXOP, FALSE, &Transmit); - } + Transmit.word = 0; + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, + TRUE, 0, 0xff, FrameLen, PID_MGMT, PID_BEACON, + RATE_1, IFS_HTTXOP, FALSE, &Transmit); + } - DBGPRINT(RT_DEBUG_TRACE, ("MakeIbssBeacon (len=%ld), SupRateLen=%d, ExtRateLen=%d, Channel=%d, PhyMode=%d\n", - FrameLen, SupRateLen, ExtRateLen, pAd->CommonCfg.Channel, pAd->CommonCfg.PhyMode)); + DBGPRINT(RT_DEBUG_TRACE, + ("MakeIbssBeacon (len=%ld), SupRateLen=%d, ExtRateLen=%d, Channel=%d, PhyMode=%d\n", + FrameLen, SupRateLen, ExtRateLen, pAd->CommonCfg.Channel, + pAd->CommonCfg.PhyMode)); return FrameLen; } - - diff --git a/drivers/staging/rt2860/sta/rtmp_data.c b/drivers/staging/rt2860/sta/rtmp_data.c index f751ab61c43844d01a8f284034085dd3cf0d45a2..5d348e9d9b797c1a09528290664e896307a9dbb7 100644 --- a/drivers/staging/rt2860/sta/rtmp_data.c +++ b/drivers/staging/rt2860/sta/rtmp_data.c @@ -33,111 +33,167 @@ Revision History: Who When What -------- ---------- ---------------------------------------------- - John Aug/17/04 major modification for RT2561/2661 - Jan Lee Mar/17/06 major modification for RT2860 New Ring Design */ #include "../rt_config.h" - - -VOID STARxEAPOLFrameIndicate( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) +void STARxEAPOLFrameIndicate(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) { - PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); - PRXWI_STRUC pRxWI = pRxBlk->pRxWI; - UCHAR *pTmpBuf; - - if (pAd->StaCfg.WpaSupplicantUP) - { - // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon) - // TBD : process fragmented EAPol frames - { - // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable - if ( pAd->StaCfg.IEEE8021X == TRUE && - (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H))) - { - PUCHAR Key; - UCHAR CipherAlg; - int idx = 0; - - DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n")); + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + struct rt_rxwi * pRxWI = pRxBlk->pRxWI; + u8 *pTmpBuf; + + if (pAd->StaCfg.WpaSupplicantUP) { + /* All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon) */ + /* TBD : process fragmented EAPol frames */ + { + /* In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable */ + if (pAd->StaCfg.IEEE8021X == TRUE && + (EAP_CODE_SUCCESS == + WpaCheckEapCode(pAd, pRxBlk->pData, + pRxBlk->DataSize, + LENGTH_802_1_H))) { + u8 *Key; + u8 CipherAlg; + int idx = 0; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("Receive EAP-SUCCESS Packet\n")); + /*pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */ STA_PORT_SECURED(pAd); - if (pAd->StaCfg.IEEE8021x_required_keys == FALSE) - { - idx = pAd->StaCfg.DesireSharedKeyId; - CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg; - Key = pAd->StaCfg.DesireSharedKey[idx].Key; - - if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0) - { -#ifdef RT2860 - MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID]; - - // Set key material and cipherAlg to Asic - AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL); - - // Assign group key info - RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL); - - // Assign pairwise key info - RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry); - - pAd->IndicateMediaState = NdisMediaStateConnected; - pAd->ExtraInfo = GENERAL_LINK_UP; -#endif -#ifdef RT2870 - union - { - char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1]; - NDIS_802_11_WEP keyinfo; - } WepKey; + if (pAd->StaCfg.IEEE8021x_required_keys == + FALSE) { + idx = pAd->StaCfg.DesireSharedKeyId; + CipherAlg = + pAd->StaCfg.DesireSharedKey[idx]. + CipherAlg; + Key = + pAd->StaCfg.DesireSharedKey[idx]. + Key; + + if (pAd->StaCfg.DesireSharedKey[idx]. + KeyLen > 0) { +#ifdef RTMP_MAC_PCI + struct rt_mac_table_entry *pEntry = + &pAd->MacTab. + Content[BSSID_WCID]; + + /* Set key material and cipherAlg to Asic */ + AsicAddSharedKeyEntry(pAd, BSS0, + idx, + CipherAlg, + Key, NULL, + NULL); + + /* Assign group key info */ + RTMPAddWcidAttributeEntry(pAd, + BSS0, + idx, + CipherAlg, + NULL); + + /* Assign pairwise key info */ + RTMPAddWcidAttributeEntry(pAd, + BSS0, + idx, + CipherAlg, + pEntry); + + pAd->IndicateMediaState = + NdisMediaStateConnected; + pAd->ExtraInfo = + GENERAL_LINK_UP; +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + union { + char buf[sizeof + (struct rt_ndis_802_11_wep) + + + MAX_LEN_OF_KEY + - 1]; + struct rt_ndis_802_11_wep keyinfo; + } + WepKey; int len; - - NdisZeroMemory(&WepKey, sizeof(WepKey)); - len =pAd->StaCfg.DesireSharedKey[idx].KeyLen; - - NdisMoveMemory(WepKey.keyinfo.KeyMaterial, - pAd->StaCfg.DesireSharedKey[idx].Key, - pAd->StaCfg.DesireSharedKey[idx].KeyLen); - - WepKey.keyinfo.KeyIndex = 0x80000000 + idx; + NdisZeroMemory(&WepKey, + sizeof(WepKey)); + len = + pAd->StaCfg. + DesireSharedKey[idx].KeyLen; + + NdisMoveMemory(WepKey.keyinfo. + KeyMaterial, + pAd->StaCfg. + DesireSharedKey + [idx].Key, + pAd->StaCfg. + DesireSharedKey + [idx].KeyLen); + + WepKey.keyinfo.KeyIndex = + 0x80000000 + idx; WepKey.keyinfo.KeyLength = len; - pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13); - - pAd->IndicateMediaState = NdisMediaStateConnected; - pAd->ExtraInfo = GENERAL_LINK_UP; - // need to enqueue cmd to thread - RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1); -#endif // RT2870 // - // For Preventing ShardKey Table is cleared by remove key procedure. - pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg; - pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen; - NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key, - pAd->StaCfg.DesireSharedKey[idx].Key, - pAd->StaCfg.DesireSharedKey[idx].KeyLen); - } + pAd->SharedKey[BSS0][idx]. + KeyLen = + (u8)(len <= 5 ? 5 : 13); + + pAd->IndicateMediaState = + NdisMediaStateConnected; + pAd->ExtraInfo = + GENERAL_LINK_UP; + /* need to enqueue cmd to thread */ + RTUSBEnqueueCmdFromNdis(pAd, + OID_802_11_ADD_WEP, + TRUE, + &WepKey, + sizeof + (WepKey. + keyinfo) + + len - + 1); +#endif /* RTMP_MAC_USB // */ + /* For Preventing ShardKey Table is cleared by remove key procedure. */ + pAd->SharedKey[BSS0][idx]. + CipherAlg = CipherAlg; + pAd->SharedKey[BSS0][idx]. + KeyLen = + pAd->StaCfg. + DesireSharedKey[idx].KeyLen; + NdisMoveMemory(pAd-> + SharedKey[BSS0] + [idx].Key, + pAd->StaCfg. + DesireSharedKey + [idx].Key, + pAd->StaCfg. + DesireSharedKey + [idx].KeyLen); + } } } Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); return; } - } - else - { - // Special DATA frame that has to pass to MLME - // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process - // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process + } else { + /* Special DATA frame that has to pass to MLME */ + /* 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process */ + /* 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process */ { pTmpBuf = pRxBlk->pData - LENGTH_802_11; NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11); - REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize)); + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, + pTmpBuf, + pRxBlk->DataSize + + LENGTH_802_11, pRxWI->RSSI0, + pRxWI->RSSI1, pRxWI->RSSI2, + pRxD->PlcpSignal); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("report EAPOL/AIRONET DATA to MLME (len=%d) !\n", + pRxBlk->DataSize)); } } @@ -146,495 +202,483 @@ VOID STARxEAPOLFrameIndicate( } -VOID STARxDataFrameAnnounce( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) +void STARxDataFrameAnnounce(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, + struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) { - // non-EAP frame - if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID)) - { - { - // drop all non-EAP DATA frame before - // this client's Port-Access-Control is secured - if (pRxBlk->pHeader->FC.Wep) - { - // unsupported cipher suite - if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled) - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + /* non-EAP frame */ + if (!RTMPCheckWPAframe + (pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID)) { + + { + /* drop all non-EAP DATA frame before */ + /* this client's Port-Access-Control is secured */ + if (pRxBlk->pHeader->FC.Wep) { + /* unsupported cipher suite */ + if (pAd->StaCfg.WepStatus == + Ndis802_11EncryptionDisabled) { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, + pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); return; } - } - else - { - // encryption in-use but receive a non-EAPOL clear text frame, drop it - if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) && - (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + } else { + /* encryption in-use but receive a non-EAPOL clear text frame, drop it */ + if ((pAd->StaCfg.WepStatus != + Ndis802_11EncryptionDisabled) + && (pAd->StaCfg.PortSecured == + WPA_802_1X_PORT_NOT_SECURED)) { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, + pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); return; } } } RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP); - if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) - { - // Normal legacy, AMPDU or AMSDU - CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID); + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) { + /* Normal legacy, AMPDU or AMSDU */ + CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, + FromWhichBSSID); + } else { + /* ARALINK */ + CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, + FromWhichBSSID); } - else - { - // ARALINK - CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); - } - } - else - { + } else { RX_BLK_SET_FLAG(pRxBlk, fRX_EAP); - if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) - { + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) + && (pAd->CommonCfg.bDisableReordering == 0)) { Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); - } - else - { - // Determin the destination of the EAP frame - // to WPA state machine or upper layer - STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + } else { + /* Determin the destination of the EAP frame */ + /* to WPA state machine or upper layer */ + STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, + FromWhichBSSID); } } } - -// For TKIP frame, calculate the MIC value -BOOLEAN STACheckTkipMICValue( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN RX_BLK *pRxBlk) +/* For TKIP frame, calculate the MIC value */ +BOOLEAN STACheckTkipMICValue(struct rt_rtmp_adapter *pAd, + struct rt_mac_table_entry *pEntry, struct rt_rx_blk *pRxBlk) { - PHEADER_802_11 pHeader = pRxBlk->pHeader; - UCHAR *pData = pRxBlk->pData; - USHORT DataSize = pRxBlk->DataSize; - UCHAR UserPriority = pRxBlk->UserPriority; - PCIPHER_KEY pWpaKey; - UCHAR *pDA, *pSA; + struct rt_header_802_11 * pHeader = pRxBlk->pHeader; + u8 *pData = pRxBlk->pData; + u16 DataSize = pRxBlk->DataSize; + u8 UserPriority = pRxBlk->UserPriority; + struct rt_cipher_key *pWpaKey; + u8 *pDA, *pSA; pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex]; pDA = pHeader->Addr1; - if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA)) - { + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA)) { pSA = pHeader->Addr3; - } - else - { + } else { pSA = pHeader->Addr2; } if (RTMPTkipCompareMICValue(pAd, - pData, - pDA, - pSA, - pWpaKey->RxMic, - UserPriority, - DataSize) == FALSE) - { - DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n")); - - if (pAd->StaCfg.WpaSupplicantUP) - { - WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE); - } - else - { + pData, + pDA, + pSA, + pWpaKey->RxMic, + UserPriority, DataSize) == FALSE) { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Rx MIC Value error 2\n")); + + if (pAd->StaCfg.WpaSupplicantUP) { + WpaSendMicFailureToWpaSupplicant(pAd, + (pWpaKey->Type == + PAIRWISEKEY) ? TRUE : + FALSE); + } else { RTMPReportMicError(pAd, pWpaKey); } - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); return FALSE; } return TRUE; } - -// -// All Rx routines use RX_BLK structure to hande rx events -// It is very important to build pRxBlk attributes -// 1. pHeader pointer to 802.11 Header -// 2. pData pointer to payload including LLC (just skip Header) -// 3. set payload size including LLC to DataSize -// 4. set some flags with RX_BLK_SET_FLAG() -// -VOID STAHandleRxDataFrame( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk) +/* */ +/* All Rx routines use struct rt_rx_blk structure to hande rx events */ +/* It is very important to build pRxBlk attributes */ +/* 1. pHeader pointer to 802.11 Header */ +/* 2. pData pointer to payload including LLC (just skip Header) */ +/* 3. set payload size including LLC to DataSize */ +/* 4. set some flags with RX_BLK_SET_FLAG() */ +/* */ +void STAHandleRxDataFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk) { - PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); - PRXWI_STRUC pRxWI = pRxBlk->pRxWI; - PHEADER_802_11 pHeader = pRxBlk->pHeader; - PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; - BOOLEAN bFragment = FALSE; - MAC_TABLE_ENTRY *pEntry = NULL; - UCHAR FromWhichBSSID = BSS0; - UCHAR UserPriority = 0; + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + struct rt_rxwi * pRxWI = pRxBlk->pRxWI; + struct rt_header_802_11 * pHeader = pRxBlk->pHeader; + void *pRxPacket = pRxBlk->pRxPacket; + BOOLEAN bFragment = FALSE; + struct rt_mac_table_entry *pEntry = NULL; + u8 FromWhichBSSID = BSS0; + u8 UserPriority = 0; { - // before LINK UP, all DATA frames are rejected - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + /* before LINK UP, all DATA frames are rejected */ + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, + NDIS_STATUS_FAILURE); return; } - - // Drop not my BSS frames - if (pRxD->MyBss == 0) - { + /* Drop not my BSS frames */ + if (pRxD->MyBss == 0) { { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, + NDIS_STATUS_FAILURE); return; } } pAd->RalinkCounters.RxCountSinceLastNULL++; - if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08)) - { - UCHAR *pData; - DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n")); - - // Qos bit 4 - pData = (PUCHAR)pHeader + LENGTH_802_11; - if ((*pData >> 4) & 0x01) - { - DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n")); + if (pAd->CommonCfg.bAPSDCapable + && pAd->CommonCfg.APEdcaParm.bAPSDCapable + && (pHeader->FC.SubType & 0x08)) { + u8 *pData; + DBGPRINT(RT_DEBUG_INFO, ("bAPSDCapable\n")); + + /* Qos bit 4 */ + pData = (u8 *)pHeader + LENGTH_802_11; + if ((*pData >> 4) & 0x01) { + DBGPRINT(RT_DEBUG_INFO, + ("RxDone- Rcv EOSP frame, driver may fall into sleep\n")); pAd->CommonCfg.bInServicePeriod = FALSE; - // Force driver to fall into sleep mode when rcv EOSP frame - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - USHORT TbttNumToNextWakeUp; - USHORT NextDtim = pAd->StaCfg.DtimPeriod; - ULONG Now; + /* Force driver to fall into sleep mode when rcv EOSP frame */ + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { + u16 TbttNumToNextWakeUp; + u16 NextDtim = + pAd->StaCfg.DtimPeriod; + unsigned long Now; NdisGetSystemUpTime(&Now); - NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod; - - TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) + NextDtim -= + (u16)(Now - + pAd->StaCfg. + LastBeaconRxTime) / + pAd->CommonCfg.BeaconPeriod; + + TbttNumToNextWakeUp = + pAd->StaCfg.DefaultListenCount; + if (OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_RECEIVE_DTIM) + && (TbttNumToNextWakeUp > NextDtim)) TbttNumToNextWakeUp = NextDtim; - MlmeSetPsmBit(pAd, PWR_SAVE); - // if WMM-APSD is failed, try to disable following line - AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); + RTMP_SET_PSM_BIT(pAd, PWR_SAVE); + /* if WMM-APSD is failed, try to disable following line */ + AsicSleepThenAutoWakeup(pAd, + TbttNumToNextWakeUp); } } - if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod)) - { - DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n")); + if ((pHeader->FC.MoreData) + && (pAd->CommonCfg.bInServicePeriod)) { + DBGPRINT(RT_DEBUG_TRACE, + ("Sending another trigger frame when More Data bit is set to 1\n")); } } - - // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame - if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA + /* Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame */ + if ((pHeader->FC.SubType & 0x04)) /* bit 2 : no DATA */ { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, + NDIS_STATUS_FAILURE); return; } + /* Drop not my BSS frame (we can not only check the MyBss bit in RxD) */ - // Drop not my BSS frame (we can not only check the MyBss bit in RxD) - - if (INFRA_ON(pAd)) - { - // Infrastructure mode, check address 2 for BSSID - if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6)) - { - // Receive frame not my BSSID - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + if (INFRA_ON(pAd)) { + /* Infrastructure mode, check address 2 for BSSID */ + if (!RTMPEqualMemory + (&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6)) { + /* Receive frame not my BSSID */ + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, + NDIS_STATUS_FAILURE); return; } - } - else // Ad-Hoc mode or Not associated - { - // Ad-Hoc mode, check address 3 for BSSID - if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6)) - { - // Receive frame not my BSSID - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + } else /* Ad-Hoc mode or Not associated */ + { + /* Ad-Hoc mode, check address 3 for BSSID */ + if (!RTMPEqualMemory + (&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6)) { + /* Receive frame not my BSSID */ + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, + NDIS_STATUS_FAILURE); return; } } - // - // find pEntry - // - if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE) - { + /* */ + /* find pEntry */ + /* */ + if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE) { pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; - } - else - { - // 1. release packet if infra mode - // 2. new a pEntry if ad-hoc mode - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + } else { + /* 1. release packet if infra mode */ + /* 2. new a pEntry if ad-hoc mode */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, + NDIS_STATUS_FAILURE); return; } - // infra or ad-hoc - if (INFRA_ON(pAd)) - { + /* infra or ad-hoc */ + if (INFRA_ON(pAd)) { RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA); ASSERT(pRxWI->WirelessCliID == BSSID_WCID); } - - // check Atheros Client - if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry )) - { + /* check Atheros Client */ + if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) + && (pHeader->FC.Retry)) { pEntry->bIAmBadAtheros = TRUE; pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE; pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE; - if (!STA_AES_ON(pAd)) - { - AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE); + if (!STA_AES_ON(pAd)) { + AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, + FALSE); } } } - pRxBlk->pData = (UCHAR *)pHeader; + pRxBlk->pData = (u8 *) pHeader; - // - // update RxBlk->pData, DataSize - // 802.11 Header, QOS, HTC, Hw Padding - // + /* */ + /* update RxBlk->pData, DataSize */ + /* 802.11 Header, QOS, HTC, Hw Padding */ + /* */ - // 1. skip 802.11 HEADER + /* 1. skip 802.11 HEADER */ { pRxBlk->pData += LENGTH_802_11; pRxBlk->DataSize -= LENGTH_802_11; } - // 2. QOS - if (pHeader->FC.SubType & 0x08) - { + /* 2. QOS */ + if (pHeader->FC.SubType & 0x08) { RX_BLK_SET_FLAG(pRxBlk, fRX_QOS); UserPriority = *(pRxBlk->pData) & 0x0f; - // bit 7 in QoS Control field signals the HT A-MSDU format - if ((*pRxBlk->pData) & 0x80) - { + /* bit 7 in QoS Control field signals the HT A-MSDU format */ + if ((*pRxBlk->pData) & 0x80) { RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU); } - - // skip QOS contorl field + /* skip QOS contorl field */ pRxBlk->pData += 2; - pRxBlk->DataSize -=2; + pRxBlk->DataSize -= 2; } pRxBlk->UserPriority = UserPriority; - // 3. Order bit: A-Ralink or HTC+ - if (pHeader->FC.Order) - { + /* check if need to resend PS Poll when received packet with MoreData = 1 */ + if ((pAd->StaCfg.Psm == PWR_SAVE) && (pHeader->FC.MoreData == 1)) { + if ((((UserPriority == 0) || (UserPriority == 3)) && + pAd->CommonCfg.bAPSDAC_BE == 0) || + (((UserPriority == 1) || (UserPriority == 2)) && + pAd->CommonCfg.bAPSDAC_BK == 0) || + (((UserPriority == 4) || (UserPriority == 5)) && + pAd->CommonCfg.bAPSDAC_VI == 0) || + (((UserPriority == 6) || (UserPriority == 7)) && + pAd->CommonCfg.bAPSDAC_VO == 0)) { + /* non-UAPSD delivery-enabled AC */ + RTMP_PS_POLL_ENQUEUE(pAd); + } + } + /* 3. Order bit: A-Ralink or HTC+ */ + if (pHeader->FC.Order) { #ifdef AGGREGATION_SUPPORT - if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))) + if ((pRxWI->PHYMODE <= MODE_OFDM) + && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))) { RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK); - } - else -#endif + } else +#endif /* AGGREGATION_SUPPORT // */ { RX_BLK_SET_FLAG(pRxBlk, fRX_HTC); - // skip HTC contorl field + /* skip HTC contorl field */ pRxBlk->pData += 4; pRxBlk->DataSize -= 4; } } - - // 4. skip HW padding - if (pRxD->L2PAD) - { - // just move pData pointer - // because DataSize excluding HW padding + /* 4. skip HW padding */ + if (pRxD->L2PAD) { + /* just move pData pointer */ + /* because DataSize excluding HW padding */ RX_BLK_SET_FLAG(pRxBlk, fRX_PAD); pRxBlk->pData += 2; } - if (pRxD->BA) - { + if (pRxD->BA) { RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU); } - - // - // Case I Process Broadcast & Multicast data frame - // - if (pRxD->Bcast || pRxD->Mcast) - { + /* */ + /* Case I Process Broadcast & Multicast data frame */ + /* */ + if (pRxD->Bcast || pRxD->Mcast) { INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount); - // Drop Mcast/Bcast frame with fragment bit on - if (pHeader->FC.MoreFrag) - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + /* Drop Mcast/Bcast frame with fragment bit on */ + if (pHeader->FC.MoreFrag) { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, + NDIS_STATUS_FAILURE); return; } - - // Filter out Bcast frame which AP relayed for us - if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + /* Filter out Bcast frame which AP relayed for us */ + if (pHeader->FC.FrDs + && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, + NDIS_STATUS_FAILURE); return; } Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); return; - } - else if (pRxD->U2M) - { - pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ; + } else if (pRxD->U2M) { + pAd->LastRxRate = + (u16)((pRxWI->MCS) + (pRxWI->BW << 7) + + (pRxWI->ShortGI << 8) + (pRxWI->PHYMODE << 14)); - if (ADHOC_ON(pAd)) - { + if (ADHOC_ON(pAd)) { pEntry = MacTableLookup(pAd, pHeader->Addr2); if (pEntry) - Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI); + Update_Rssi_Sample(pAd, &pEntry->RssiSample, + pRxWI); } - Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI); - pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0); - pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1); + pAd->StaCfg.LastSNR0 = (u8)(pRxWI->SNR0); + pAd->StaCfg.LastSNR1 = (u8)(pRxWI->SNR1); pAd->RalinkCounters.OneSecRxOkDataCnt++; + if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0))) { + /* re-assemble the fragmented packets */ + /* return complete frame (pRxPacket) or NULL */ + bFragment = TRUE; + pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk); + } - if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0))) - { - // re-assemble the fragmented packets - // return complete frame (pRxPacket) or NULL - bFragment = TRUE; - pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk); - } - - if (pRxPacket) - { + if (pRxPacket) { pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; - // process complete frame - if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled)) - { - // Minus MIC length + /* process complete frame */ + if (bFragment && (pRxD->Decrypted) + && (pEntry->WepStatus == + Ndis802_11Encryption2Enabled)) { + /* Minus MIC length */ pRxBlk->DataSize -= 8; - // For TKIP frame, calculate the MIC value - if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE) - { - return; - } - } + /* For TKIP frame, calculate the MIC value */ + if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == + FALSE) { + return; + } + } - STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID); + STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, + FromWhichBSSID); + return; + } else { + /* just return */ + /* because RTMPDeFragmentDataFrame() will release rx packet, */ + /* if packet is fragmented */ return; - } - else - { - // just return - // because RTMPDeFragmentDataFrame() will release rx packet, - // if packet is fragmented - return; - } + } } ASSERT(0); - // release packet + /* release packet */ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); } -VOID STAHandleRxMgmtFrame( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk) +void STAHandleRxMgmtFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk) { - PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); - PRXWI_STRUC pRxWI = pRxBlk->pRxWI; - PHEADER_802_11 pHeader = pRxBlk->pHeader; - PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + struct rt_rxwi * pRxWI = pRxBlk->pRxWI; + struct rt_header_802_11 * pHeader = pRxBlk->pHeader; + void *pRxPacket = pRxBlk->pRxPacket; - do - { - - // We should collect RSSI not only U2M data but also my beacon - if (pAd->RxAnt.EvaluatePeriod == 0 && - pHeader->FC.SubType == SUBTYPE_BEACON && - MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)) { - Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI); + do { - pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0); - pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1); + /* check if need to resend PS Poll when received packet with MoreData = 1 */ + if ((pAd->StaCfg.Psm == PWR_SAVE) + && (pHeader->FC.MoreData == 1)) { + /* for UAPSD, all management frames will be VO priority */ + if (pAd->CommonCfg.bAPSDAC_VO == 0) { + /* non-UAPSD delivery-enabled AC */ + RTMP_PS_POLL_ENQUEUE(pAd); + } } -#ifdef RT2870 - // collect rssi information for antenna diversity - if (pAd->NicConfig2.field.AntDiversity) - { - if ((pRxD->U2M) || ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))) - { - COLLECT_RX_ANTENNA_AVERAGE_RSSI(pAd, ConvertToRssi(pAd, (UCHAR)pRxWI->RSSI0, RSSI_0), 0); //Note: RSSI2 not used on RT73 - pAd->StaCfg.NumOfAvgRssiSample ++; - } + /* TODO: if MoreData == 0, station can go to sleep */ + + /* We should collect RSSI not only U2M data but also my beacon */ + if ((pHeader->FC.SubType == SUBTYPE_BEACON) + && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)) + && (pAd->RxAnt.EvaluatePeriod == 0)) { + Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI); + + pAd->StaCfg.LastSNR0 = (u8)(pRxWI->SNR0); + pAd->StaCfg.LastSNR1 = (u8)(pRxWI->SNR1); } -#endif - // First check the size, it MUST not exceed the mlme queue size - if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE) - { + /* First check the size, it MUST not exceed the mlme queue size */ + if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE) { DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount)); break; } - REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount, - pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal); + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, + pRxWI->MPDUtotalByteCount, + pRxWI->RSSI0, pRxWI->RSSI1, + pRxWI->RSSI2, pRxD->PlcpSignal); } while (FALSE); RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); } -VOID STAHandleRxControlFrame( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk) +void STAHandleRxControlFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk) { - PRXWI_STRUC pRxWI = pRxBlk->pRxWI; - PHEADER_802_11 pHeader = pRxBlk->pHeader; - PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; - - switch (pHeader->FC.SubType) - { - case SUBTYPE_BLOCK_ACK_REQ: - { - CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader); - } - break; - case SUBTYPE_BLOCK_ACK: - case SUBTYPE_ACK: - default: - break; + struct rt_rxwi * pRxWI = pRxBlk->pRxWI; + struct rt_header_802_11 * pHeader = pRxBlk->pHeader; + void *pRxPacket = pRxBlk->pRxPacket; + + switch (pHeader->FC.SubType) { + case SUBTYPE_BLOCK_ACK_REQ: + { + CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, + (pRxWI->MPDUtotalByteCount), + (struct rt_frame_ba_req *) pHeader); + } + break; + case SUBTYPE_BLOCK_ACK: + case SUBTYPE_ACK: + default: + break; } RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); } - /* ======================================================================== @@ -654,141 +698,127 @@ VOID STAHandleRxControlFrame( Need to consider QOS DATA format when converting to 802.3 ======================================================================== */ -BOOLEAN STARxDoneInterruptHandle( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN argc) +BOOLEAN STARxDoneInterruptHandle(struct rt_rtmp_adapter *pAd, IN BOOLEAN argc) { - NDIS_STATUS Status; - UINT32 RxProcessed, RxPending; - BOOLEAN bReschedule = FALSE; - RT28XX_RXD_STRUC *pRxD; - UCHAR *pData; - PRXWI_STRUC pRxWI; - PNDIS_PACKET pRxPacket; - PHEADER_802_11 pHeader; - RX_BLK RxCell; + int Status; + u32 RxProcessed, RxPending; + BOOLEAN bReschedule = FALSE; + PRT28XX_RXD_STRUC pRxD; + u8 *pData; + struct rt_rxwi * pRxWI; + void *pRxPacket; + struct rt_header_802_11 * pHeader; + struct rt_rx_blk RxCell; RxProcessed = RxPending = 0; - // process whole rx ring - while (1) - { + /* process whole rx ring */ + while (1) { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF | - fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_NIC_NOT_EXIST) || - !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP)) - { + fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST) || + !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) { break; } - -#ifdef RT2860 - if (RxProcessed++ > MAX_RX_PROCESS_CNT) - { - // need to reschedule rx handle +#ifdef RTMP_MAC_PCI + if (RxProcessed++ > MAX_RX_PROCESS_CNT) { + /* need to reschedule rx handle */ bReschedule = TRUE; break; } -#endif - - RxProcessed ++; // test - - // 1. allocate a new data packet into rx ring to replace received packet - // then processing the received packet - // 2. the callee must take charge of release of packet - // 3. As far as driver is concerned , - // the rx packet must - // a. be indicated to upper layer or - // b. be released if it is discarded - pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending); - if (pRxPacket == NULL) - { - // no more packet to process +#endif /* RTMP_MAC_PCI // */ + + RxProcessed++; /* test */ + + /* 1. allocate a new data packet into rx ring to replace received packet */ + /* then processing the received packet */ + /* 2. the callee must take charge of release of packet */ + /* 3. As far as driver is concerned , */ + /* the rx packet must */ + /* a. be indicated to upper layer or */ + /* b. be released if it is discarded */ + pRxPacket = + GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, + &RxPending); + if (pRxPacket == NULL) { + /* no more packet to process */ break; } - - // get rx ring descriptor + /* get rx ring descriptor */ pRxD = &(RxCell.RxD); - // get rx data buffer - pData = GET_OS_PKT_DATAPTR(pRxPacket); - pRxWI = (PRXWI_STRUC) pData; - pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ; + /* get rx data buffer */ + pData = GET_OS_PKT_DATAPTR(pRxPacket); + pRxWI = (struct rt_rxwi *) pData; + pHeader = (struct rt_header_802_11 *) (pData + RXWI_SIZE); - // build RxCell + /* build RxCell */ RxCell.pRxWI = pRxWI; RxCell.pHeader = pHeader; RxCell.pRxPacket = pRxPacket; - RxCell.pData = (UCHAR *) pHeader; + RxCell.pData = (u8 *) pHeader; RxCell.DataSize = pRxWI->MPDUtotalByteCount; RxCell.Flags = 0; - // Increase Total receive byte counter after real data received no mater any error or not - pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount; - pAd->RalinkCounters.RxCount ++; + /* Increase Total receive byte counter after real data received no mater any error or not */ + pAd->RalinkCounters.ReceivedByteCount += + pRxWI->MPDUtotalByteCount; + pAd->RalinkCounters.OneSecReceivedByteCount += + pRxWI->MPDUtotalByteCount; + pAd->RalinkCounters.RxCount++; INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount); if (pRxWI->MPDUtotalByteCount < 14) Status = NDIS_STATUS_FAILURE; - if (MONITOR_ON(pAd)) - { - send_monitor_packets(pAd, &RxCell); + if (MONITOR_ON(pAd)) { + send_monitor_packets(pAd, &RxCell); break; } - /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */ - // Check for all RxD errors + /* STARxDoneInterruptHandle() is called in rtusb_bulk.c */ + + /* Check for all RxD errors */ Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD); - // Handle the received frame - if (Status == NDIS_STATUS_SUCCESS) - { - switch (pHeader->FC.Type) - { - // CASE I, receive a DATA frame - case BTYPE_DATA: + /* Handle the received frame */ + if (Status == NDIS_STATUS_SUCCESS) { + switch (pHeader->FC.Type) { + /* CASE I, receive a DATA frame */ + case BTYPE_DATA: { - // process DATA frame + /* process DATA frame */ STAHandleRxDataFrame(pAd, &RxCell); } break; - // CASE II, receive a MGMT frame - case BTYPE_MGMT: + /* CASE II, receive a MGMT frame */ + case BTYPE_MGMT: { STAHandleRxMgmtFrame(pAd, &RxCell); } break; - // CASE III. receive a CNTL frame - case BTYPE_CNTL: + /* CASE III. receive a CNTL frame */ + case BTYPE_CNTL: { STAHandleRxControlFrame(pAd, &RxCell); } break; - // discard other type - default: - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); - break; + /* discard other type */ + default: + RELEASE_NDIS_PACKET(pAd, pRxPacket, + NDIS_STATUS_FAILURE); + break; } - } - else - { + } else { pAd->Counters8023.RxErrors++; - // discard this frame - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + /* discard this frame */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, + NDIS_STATUS_FAILURE); } } -#ifdef RT2860 - // fRTMP_PS_GO_TO_SLEEP_NOW is set if receiving beacon. - if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW) && (INFRA_ON(pAd))) - { - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); - AsicSleepThenAutoWakeup(pAd, pAd->ThisTbttNumToNextWakeUp); - bReschedule = FALSE; - } -#endif return bReschedule; } @@ -803,15 +833,9 @@ BOOLEAN STARxDoneInterruptHandle( ======================================================================== */ -VOID RTMPHandleTwakeupInterrupt( - IN PRTMP_ADAPTER pAd) +void RTMPHandleTwakeupInterrupt(struct rt_rtmp_adapter *pAd) { -#ifdef RT2860 - AsicForceWakeup(pAd, DOT11POWERSAVE); -#endif -#ifdef RT2870 AsicForceWakeup(pAd, FALSE); -#endif } /* @@ -820,9 +844,9 @@ Routine Description: Early checking and OS-depened parsing for Tx packet send to our STA driver. Arguments: - NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd. - PPNDIS_PACKET ppPacketArray The packet array need to do transmission. - UINT NumberOfPackets Number of packet in packet array. + void * MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd. + void ** ppPacketArray The packet array need to do transmission. + u32 NumberOfPackets Number of packet in packet array. Return Value: NONE @@ -832,47 +856,39 @@ Note: You only can put OS-depened & STA related code in here. ======================================================================== */ -VOID STASendPackets( - IN NDIS_HANDLE MiniportAdapterContext, - IN PPNDIS_PACKET ppPacketArray, - IN UINT NumberOfPackets) +void STASendPackets(void *MiniportAdapterContext, + void **ppPacketArray, u32 NumberOfPackets) { - UINT Index; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext; - PNDIS_PACKET pPacket; - BOOLEAN allowToSend = FALSE; + u32 Index; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)MiniportAdapterContext; + void *pPacket; + BOOLEAN allowToSend = FALSE; - - for (Index = 0; Index < NumberOfPackets; Index++) - { + for (Index = 0; Index < NumberOfPackets; Index++) { pPacket = ppPacketArray[Index]; - do - { - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) - { - // Drop send request since hardware is in reset state - break; - } - else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd)) - { - // Drop send request since there are no physical connection yet - break; - } - else - { - // Record that orignal packet source is from NDIS layer,so that - // later on driver knows how to release this NDIS PACKET - RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode + do { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) + || RTMP_TEST_FLAG(pAd, + fRTMP_ADAPTER_HALT_IN_PROGRESS) + || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) { + /* Drop send request since hardware is in reset state */ + break; + } else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd)) { + /* Drop send request since there are no physical connection yet */ + break; + } else { + /* Record that orignal packet source is from NDIS layer,so that */ + /* later on driver knows how to release this NDIS PACKET */ + RTMP_SET_PACKET_WCID(pPacket, 0); /* this field is useless when in STA mode */ RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); - NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING); + NDIS_SET_PACKET_STATUS(pPacket, + NDIS_STATUS_PENDING); pAd->RalinkCounters.PendingNdisPacketCount++; allowToSend = TRUE; } - } while(FALSE); + } while (FALSE); if (allowToSend == TRUE) STASendPacket(pAd, pPacket); @@ -880,12 +896,11 @@ VOID STASendPackets( RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); } - // Dequeue outgoing frames from TxSwQueue[] and process it + /* Dequeue outgoing frames from TxSwQueue[] and process it */ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); } - /* ======================================================================== Routine Description: @@ -898,201 +913,199 @@ Arguments: pPacket Pointer to send packet Return Value: - NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue. + NDIS_STATUS_SUCCESS If success to queue the packet into TxSwQueue. NDIS_STATUS_FAILURE If failed to do en-queue. Note: You only can put OS-indepened & STA related code in here. ======================================================================== */ -NDIS_STATUS STASendPacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket) +int STASendPacket(struct rt_rtmp_adapter *pAd, void *pPacket) { - PACKET_INFO PacketInfo; - PUCHAR pSrcBufVA; - UINT SrcBufLen; - UINT AllowFragSize; - UCHAR NumberOfFrag; - UCHAR QueIdx, UserPriority; - MAC_TABLE_ENTRY *pEntry = NULL; - unsigned int IrqFlags; - UCHAR FlgIsIP = 0; - UCHAR Rate; - - // Prepare packet information structure for buffer descriptor - // chained within a single NDIS packet. + struct rt_packet_info PacketInfo; + u8 *pSrcBufVA; + u32 SrcBufLen; + u32 AllowFragSize; + u8 NumberOfFrag; + u8 RTSRequired; + u8 QueIdx, UserPriority; + struct rt_mac_table_entry *pEntry = NULL; + unsigned int IrqFlags; + u8 FlgIsIP = 0; + u8 Rate; + + /* Prepare packet information structure for buffer descriptor */ + /* chained within a single NDIS packet. */ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); - if (pSrcBufVA == NULL) - { - DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen)); - // Resourece is low, system did not allocate virtual address - // return NDIS_STATUS_FAILURE directly to upper layer + if (pSrcBufVA == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("STASendPacket --> pSrcBufVA == NULL !SrcBufLen=%x\n", + SrcBufLen)); + /* Resourece is low, system did not allocate virtual address */ + /* return NDIS_STATUS_FAILURE directly to upper layer */ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return NDIS_STATUS_FAILURE; } - - if (SrcBufLen < 14) - { - DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n")); + if (SrcBufLen < 14) { + DBGPRINT(RT_DEBUG_ERROR, + ("STASendPacket --> Ndis Packet buffer error!\n")); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return (NDIS_STATUS_FAILURE); } - - // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry. - // Note multicast packets in adhoc also use BSSID_WCID index. + /* In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry. */ + /* Note multicast packets in adhoc also use BSSID_WCID index. */ { - if(INFRA_ON(pAd)) - { - { - pEntry = &pAd->MacTab.Content[BSSID_WCID]; - RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID); - Rate = pAd->CommonCfg.TxRate; - } - } - else if (ADHOC_ON(pAd)) - { - if (*pSrcBufVA & 0x01) + if (INFRA_ON(pAd)) { { + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID); + Rate = pAd->CommonCfg.TxRate; + } + } else if (ADHOC_ON(pAd)) { + if (*pSrcBufVA & 0x01) { RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID); pEntry = &pAd->MacTab.Content[MCAST_WCID]; - } - else - { + } else { pEntry = MacTableLookup(pAd, pSrcBufVA); } Rate = pAd->CommonCfg.TxRate; } } - if (!pEntry) - { - DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA))); - // Resourece is low, system did not allocate virtual address - // return NDIS_STATUS_FAILURE directly to upper layer + if (!pEntry) { + DBGPRINT(RT_DEBUG_ERROR, + ("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", + PRINT_MAC(pSrcBufVA))); + /* Resourece is low, system did not allocate virtual address */ + /* return NDIS_STATUS_FAILURE directly to upper layer */ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return NDIS_STATUS_FAILURE; } if (ADHOC_ON(pAd) - ) - { - RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid); + ) { + RTMP_SET_PACKET_WCID(pPacket, (u8)pEntry->Aid); } - - // - // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags. - // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL). + /* */ + /* Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags. */ + /* Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL). */ RTMPCheckEtherType(pAd, pPacket); - - - // - // WPA 802.1x secured port control - drop all non-802.1x frame before port secured - // + /* */ + /* WPA 802.1x secured port control - drop all non-802.1x frame before port secured */ + /* */ if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) - || (pAd->StaCfg.IEEE8021X == TRUE) - ) - && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2)) - && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE) - ) - { - DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n")); + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + || (pAd->StaCfg.IEEE8021X == TRUE) + ) + && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) + || (pAd->StaCfg.MicErrCnt >= 2)) + && (RTMP_GET_PACKET_EAPOL(pPacket) == FALSE) + ) { + DBGPRINT(RT_DEBUG_TRACE, + ("STASendPacket --> Drop packet before port secured!\n")); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return (NDIS_STATUS_FAILURE); } + /* STEP 1. Decide number of fragments required to deliver this MSDU. */ + /* The estimation here is not very accurate because difficult to */ + /* take encryption overhead into consideration here. The result */ + /* "NumberOfFrag" is then just used to pre-check if enough free */ + /* TXD are available to hold this MSDU. */ - // STEP 1. Decide number of fragments required to deliver this MSDU. - // The estimation here is not very accurate because difficult to - // take encryption overhead into consideration here. The result - // "NumberOfFrag" is then just used to pre-check if enough free - // TXD are available to hold this MSDU. - - - if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast + if (*pSrcBufVA & 0x01) /* fragmentation not allowed on multicast & broadcast */ NumberOfFrag = 1; else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) - NumberOfFrag = 1; // Aggregation overwhelms fragmentation + NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */ else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED)) - NumberOfFrag = 1; // Aggregation overwhelms fragmentation - else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD)) - NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation - else - { - // The calculated "NumberOfFrag" is a rough estimation because of various - // encryption/encapsulation overhead not taken into consideration. This number is just - // used to make sure enough free TXD are available before fragmentation takes place. - // In case the actual required number of fragments of an NDIS packet - // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the - // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of - // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should - // rarely happen and the penalty is just like a TX RETRY fail. Affordable. - - AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; - NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1; - // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size - if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0) - { + NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */ + else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) + || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD)) + NumberOfFrag = 1; /* MIMO RATE overwhelms fragmentation */ + else { + /* The calculated "NumberOfFrag" is a rough estimation because of various */ + /* encryption/encapsulation overhead not taken into consideration. This number is just */ + /* used to make sure enough free TXD are available before fragmentation takes place. */ + /* In case the actual required number of fragments of an NDIS packet */ + /* excceeds "NumberOfFrag"caculated here and not enough free TXD available, the */ + /* last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of */ + /* resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should */ + /* rarely happen and the penalty is just like a TX RETRY fail. Affordable. */ + + AllowFragSize = + (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - + LENGTH_CRC; + NumberOfFrag = + ((PacketInfo.TotalPacketLength - LENGTH_802_3 + + LENGTH_802_1_H) / AllowFragSize) + 1; + /* To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size */ + if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + + LENGTH_802_1_H) % AllowFragSize) == 0) { NumberOfFrag--; } } - // Save fragment number to Ndis packet reserved field + /* Save fragment number to Ndis packet reserved field */ RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag); + /* STEP 2. Check the requirement of RTS: */ + /* If multiple fragment required, RTS is required only for the first fragment */ + /* if the fragment size large than RTS threshold */ + /* For RT28xx, Let ASIC send RTS/CTS */ +/* RTMP_SET_PACKET_RTS(pPacket, 0); */ + if (NumberOfFrag > 1) + RTSRequired = + (pAd->CommonCfg.FragmentThreshold > + pAd->CommonCfg.RtsThreshold) ? 1 : 0; + else + RTSRequired = + (PacketInfo.TotalPacketLength > + pAd->CommonCfg.RtsThreshold) ? 1 : 0; - // STEP 2. Check the requirement of RTS: - // If multiple fragment required, RTS is required only for the first fragment - // if the fragment size large than RTS threshold - // For RT28xx, Let ASIC send RTS/CTS - RTMP_SET_PACKET_RTS(pPacket, 0); + /* Save RTS requirement to Ndis packet reserved field */ + RTMP_SET_PACKET_RTS(pPacket, RTSRequired); RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate); - // - // STEP 3. Traffic classification. outcome = - // + /* */ + /* STEP 3. Traffic classification. outcome = */ + /* */ UserPriority = 0; - QueIdx = QID_AC_BE; -#ifdef RT2860 - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) -#endif -#ifdef RT2870 + QueIdx = QID_AC_BE; if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && - CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) -#endif - { - USHORT Protocol; - UCHAR LlcSnapLen = 0, Byte0, Byte1; - do - { - // get Ethernet protocol field - Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]); - if (Protocol <= 1500) - { - // get Ethernet protocol field from LLC/SNAP - if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS) + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) { + u16 Protocol; + u8 LlcSnapLen = 0, Byte0, Byte1; + do { + /* get Ethernet protocol field */ + Protocol = + (u16)((pSrcBufVA[12] << 8) + pSrcBufVA[13]); + if (Protocol <= 1500) { + /* get Ethernet protocol field from LLC/SNAP */ + if (Sniff2BytesFromNdisBuffer + (PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, + &Byte0, &Byte1) != NDIS_STATUS_SUCCESS) break; - Protocol = (USHORT)((Byte0 << 8) + Byte1); + Protocol = (u16)((Byte0 << 8) + Byte1); LlcSnapLen = 8; } - - // always AC_BE for non-IP packet + /* always AC_BE for non-IP packet */ if (Protocol != 0x0800) break; - // get IP header - if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS) + /* get IP header */ + if (Sniff2BytesFromNdisBuffer + (PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, + &Byte0, &Byte1) != NDIS_STATUS_SUCCESS) break; - // return AC_BE if packet is not IPv4 + /* return AC_BE if packet is not IPv4 */ if ((Byte0 & 0xf0) != 0x40) break; @@ -1100,63 +1113,59 @@ NDIS_STATUS STASendPacket( UserPriority = (Byte1 & 0xe0) >> 5; QueIdx = MapUserPriorityToAccessCategory[UserPriority]; - // TODO: have to check ACM bit. apply TSPEC if ACM is ON - // TODO: downgrade UP & QueIdx before passing ACM - if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx]) - { + /* TODO: have to check ACM bit. apply TSPEC if ACM is ON */ + /* TODO: downgrade UP & QueIdx before passing ACM */ + /* + Under WMM ACM control, we dont need to check the bit; + Or when a TSPEC is built for VO but we will change to issue + BA session for BE here, so we will not use BA to send VO packets. + */ + if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx]) { UserPriority = 0; - QueIdx = QID_AC_BE; + QueIdx = QID_AC_BE; } } while (FALSE); } RTMP_SET_PACKET_UP(pPacket, UserPriority); - - - // Make sure SendTxWait queue resource won't be used by other threads + /* Make sure SendTxWait queue resource won't be used by other threads */ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); - if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE) - { + if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE) { RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return NDIS_STATUS_FAILURE; - } - else - { - InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket)); + } else { + InsertTailQueueAc(pAd, pEntry, &pAd->TxSwQueue[QueIdx], + PACKET_TO_QUEUE_ENTRY(pPacket)); } RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); - if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&& -#ifdef RT2860 - (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE)) -#endif -#ifdef RT2870 - IS_HT_STA(pEntry)) -#endif - { - if (((pEntry->TXBAbitmap & (1<BADeclineBitmap & (1<PortSecured == WPA_802_1X_PORT_SECURED) - // For IOT compatibility, if - // 1. It is Ralink chip or - // 2. It is OPEN or AES mode, - // then BA session can be bulit. - && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) || - (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled)) - ) - { - BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE); + if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE) && + IS_HT_STA(pEntry)) { + /*struct rt_mac_table_entry *pMacEntry = &pAd->MacTab.Content[BSSID_WCID]; */ + if (((pEntry->TXBAbitmap & (1 << UserPriority)) == 0) && + ((pEntry->BADeclineBitmap & (1 << UserPriority)) == 0) && + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) + /* For IOT compatibility, if */ + /* 1. It is Ralink chip or */ + /* 2. It is OPEN or AES mode, */ + /* then BA session can be bulit. */ + && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) + || (pEntry->WepStatus != Ndis802_11WEPEnabled + && pEntry->WepStatus != + Ndis802_11Encryption2Enabled)) + ) { + BAOriSessionSetUp(pAd, pEntry, UserPriority, 0, 10, + FALSE); } } - pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed + pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; /* TODO: for debug only. to be removed */ return NDIS_STATUS_SUCCESS; } - /* ======================================================================== @@ -1179,123 +1188,132 @@ NDIS_STATUS STASendPacket( ======================================================================== */ +#ifdef RTMP_MAC_PCI +int RTMPFreeTXDRequest(struct rt_rtmp_adapter *pAd, + u8 QueIdx, + u8 NumberRequired, u8 *FreeNumberIs) +{ + unsigned long FreeNumber = 0; + int Status = NDIS_STATUS_FAILURE; + + switch (QueIdx) { + case QID_AC_BK: + case QID_AC_BE: + case QID_AC_VI: + case QID_AC_VO: + if (pAd->TxRing[QueIdx].TxSwFreeIdx > + pAd->TxRing[QueIdx].TxCpuIdx) + FreeNumber = + pAd->TxRing[QueIdx].TxSwFreeIdx - + pAd->TxRing[QueIdx].TxCpuIdx - 1; + else + FreeNumber = + pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - + pAd->TxRing[QueIdx].TxCpuIdx - 1; + + if (FreeNumber >= NumberRequired) + Status = NDIS_STATUS_SUCCESS; + break; + + case QID_MGMT: + if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx) + FreeNumber = + pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - + 1; + else + FreeNumber = + pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - + pAd->MgmtRing.TxCpuIdx - 1; + + if (FreeNumber >= NumberRequired) + Status = NDIS_STATUS_SUCCESS; + break; + + default: + DBGPRINT(RT_DEBUG_ERROR, + ("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx)); + break; + } + *FreeNumberIs = (u8)FreeNumber; -#ifdef RT2870 + return (Status); +} +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB /* Actually, this function used to check if the TxHardware Queue still has frame need to send. If no frame need to send, go to sleep, else, still wake up. */ -#endif -NDIS_STATUS RTMPFreeTXDRequest( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN UCHAR NumberRequired, - IN PUCHAR FreeNumberIs) +int RTMPFreeTXDRequest(struct rt_rtmp_adapter *pAd, + u8 QueIdx, + u8 NumberRequired, u8 *FreeNumberIs) { -#ifdef RT2860 - ULONG FreeNumber = 0; -#endif - NDIS_STATUS Status = NDIS_STATUS_FAILURE; -#ifdef RT2870 - unsigned long IrqFlags; - HT_TX_CONTEXT *pHTTXContext; -#endif - - switch (QueIdx) - { - case QID_AC_BK: - case QID_AC_BE: - case QID_AC_VI: - case QID_AC_VO: - case QID_HCCA: -#ifdef RT2860 - if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx) - FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1; - else - FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1; - - if (FreeNumber >= NumberRequired) - Status = NDIS_STATUS_SUCCESS; -#endif -#ifdef RT2870 - { - pHTTXContext = &pAd->TxContext[QueIdx]; - RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) || - (pHTTXContext->IRPPending == TRUE)) - { - Status = NDIS_STATUS_FAILURE; - } - else - { - Status = NDIS_STATUS_SUCCESS; - } - RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - } -#endif - break; - - case QID_MGMT: -#ifdef RT2860 - if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx) - FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1; - else - FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1; - - if (FreeNumber >= NumberRequired) - Status = NDIS_STATUS_SUCCESS; -#endif -#ifdef RT2870 - if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE) + /*unsigned long FreeNumber = 0; */ + int Status = NDIS_STATUS_FAILURE; + unsigned long IrqFlags; + struct rt_ht_tx_context *pHTTXContext; + + switch (QueIdx) { + case QID_AC_BK: + case QID_AC_BE: + case QID_AC_VI: + case QID_AC_VO: + { + pHTTXContext = &pAd->TxContext[QueIdx]; + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], + IrqFlags); + if ((pHTTXContext->CurWritePosition != + pHTTXContext->ENextBulkOutPosition) + || (pHTTXContext->IRPPending == TRUE)) { Status = NDIS_STATUS_FAILURE; - else + } else { Status = NDIS_STATUS_SUCCESS; -#endif - break; - - default: - DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx)); - break; + } + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], + IrqFlags); + } + break; + case QID_MGMT: + if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE) + Status = NDIS_STATUS_FAILURE; + else + Status = NDIS_STATUS_SUCCESS; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, + ("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx)); + break; } -#ifdef RT2860 - *FreeNumberIs = (UCHAR)FreeNumber; -#endif return (Status); } +#endif /* RTMP_MAC_USB // */ - - -VOID RTMPSendDisassociationFrame( - IN PRTMP_ADAPTER pAd) +void RTMPSendDisassociationFrame(struct rt_rtmp_adapter *pAd) { } -VOID RTMPSendNullFrame( - IN PRTMP_ADAPTER pAd, - IN UCHAR TxRate, - IN BOOLEAN bQosNull) +void RTMPSendNullFrame(struct rt_rtmp_adapter *pAd, + u8 TxRate, IN BOOLEAN bQosNull) { - UCHAR NullFrame[48]; - ULONG Length; - PHEADER_802_11 pHeader_802_11; - - // WPA 802.1x secured port control - if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) - || (pAd->StaCfg.IEEE8021X == TRUE) - ) && - (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) - { + u8 NullFrame[48]; + unsigned long Length; + struct rt_header_802_11 * pHeader_802_11; + + /* WPA 802.1x secured port control */ + if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + || (pAd->StaCfg.IEEE8021X == TRUE) + ) && (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) { return; } NdisZeroMemory(NullFrame, 48); - Length = sizeof(HEADER_802_11); + Length = sizeof(struct rt_header_802_11); - pHeader_802_11 = (PHEADER_802_11) NullFrame; + pHeader_802_11 = (struct rt_header_802_11 *) NullFrame; pHeader_802_11->FC.Type = BTYPE_DATA; pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC; @@ -1304,97 +1322,84 @@ VOID RTMPSendNullFrame( COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); - if (pAd->CommonCfg.bAPSDForcePowerSave) - { + if (pAd->CommonCfg.bAPSDForcePowerSave) { pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + } else { + pHeader_802_11->FC.PwrMgmt = + (pAd->StaCfg.Psm == PWR_SAVE) ? 1 : 0; } - else - { - pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0; - } - pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14); + pHeader_802_11->Duration = + pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14); pAd->Sequence++; pHeader_802_11->Sequence = pAd->Sequence; - // Prepare QosNull function frame - if (bQosNull) - { + /* Prepare QosNull function frame */ + if (bQosNull) { pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL; - // copy QOS control bytes - NullFrame[Length] = 0; - NullFrame[Length+1] = 0; - Length += 2;// if pad with 2 bytes for alignment, APSD will fail + /* copy QOS control bytes */ + NullFrame[Length] = 0; + NullFrame[Length + 1] = 0; + Length += 2; /* if pad with 2 bytes for alignment, APSD will fail */ } HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length); } -// IRQL = DISPATCH_LEVEL -VOID RTMPSendRTSFrame( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN unsigned int NextMpduSize, - IN UCHAR TxRate, - IN UCHAR RTSRate, - IN USHORT AckDuration, - IN UCHAR QueIdx, - IN UCHAR FrameGap) +/* IRQL = DISPATCH_LEVEL */ +void RTMPSendRTSFrame(struct rt_rtmp_adapter *pAd, + u8 *pDA, + IN unsigned int NextMpduSize, + u8 TxRate, + u8 RTSRate, + u16 AckDuration, u8 QueIdx, u8 FrameGap) { } - - -// -------------------------------------------------------- -// FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM -// Find the WPA key, either Group or Pairwise Key -// LEAP + TKIP also use WPA key. -// -------------------------------------------------------- -// Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst -// In Cisco CCX 2.0 Leap Authentication -// WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey -// Instead of the SharedKey, SharedKey Length may be Zero. -VOID STAFindCipherAlgorithm( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk) +/* -------------------------------------------------------- */ +/* FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM */ +/* Find the WPA key, either Group or Pairwise Key */ +/* LEAP + TKIP also use WPA key. */ +/* -------------------------------------------------------- */ +/* Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst */ +/* In Cisco CCX 2.0 Leap Authentication */ +/* WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey */ +/* Instead of the SharedKey, SharedKey Length may be Zero. */ +void STAFindCipherAlgorithm(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk) { - NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet - UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm - UCHAR KeyIdx = 0xff; - PUCHAR pSrcBufVA; - PCIPHER_KEY pKey = NULL; + NDIS_802_11_ENCRYPTION_STATUS Cipher; /* To indicate cipher used for this packet */ + u8 CipherAlg = CIPHER_NONE; /* cipher alogrithm */ + u8 KeyIdx = 0xff; + u8 *pSrcBufVA; + struct rt_cipher_key *pKey = NULL; pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket); { - // Select Cipher - if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) - Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast - else - Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast + /* Select Cipher */ + if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) + Cipher = pAd->StaCfg.GroupCipher; /* Cipher for Multicast or Broadcast */ + else + Cipher = pAd->StaCfg.PairCipher; /* Cipher for Unicast */ - if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) - { - ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128); + if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) { + ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= + CIPHER_CKIP128); - // 4-way handshaking frame must be clear - if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) && - (pAd->SharedKey[BSS0][0].KeyLen)) - { + /* 4-way handshaking frame must be clear */ + if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) + && (pAd->SharedKey[BSS0][0].CipherAlg) + && (pAd->SharedKey[BSS0][0].KeyLen)) { CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; KeyIdx = 0; } - } - else if (Cipher == Ndis802_11Encryption1Enabled) - { - KeyIdx = pAd->StaCfg.DefaultKeyId; - } - else if ((Cipher == Ndis802_11Encryption2Enabled) || - (Cipher == Ndis802_11Encryption3Enabled)) - { - if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast + } else if (Cipher == Ndis802_11Encryption1Enabled) { + KeyIdx = pAd->StaCfg.DefaultKeyId; + } else if ((Cipher == Ndis802_11Encryption2Enabled) || + (Cipher == Ndis802_11Encryption3Enabled)) { + if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) /* multicast */ KeyIdx = pAd->StaCfg.DefaultKeyId; else if (pAd->SharedKey[BSS0][0].KeyLen) KeyIdx = 0; @@ -1404,16 +1409,17 @@ VOID STAFindCipherAlgorithm( if (KeyIdx == 0xff) CipherAlg = CIPHER_NONE; - else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0)) + else if ((Cipher == Ndis802_11EncryptionDisabled) + || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0)) CipherAlg = CIPHER_NONE; - else if ( pAd->StaCfg.WpaSupplicantUP && - (Cipher == Ndis802_11Encryption1Enabled) && - (pAd->StaCfg.IEEE8021X == TRUE) && - (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) - CipherAlg = CIPHER_NONE; - else - { - //Header_802_11.FC.Wep = 1; + else if (pAd->StaCfg.WpaSupplicantUP && + (Cipher == Ndis802_11Encryption1Enabled) && + (pAd->StaCfg.IEEE8021X == TRUE) && + (pAd->StaCfg.PortSecured == + WPA_802_1X_PORT_NOT_SECURED)) + CipherAlg = CIPHER_NONE; + else { + /*Header_802_11.FC.Wep = 1; */ CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; pKey = &pAd->SharedKey[BSS0][KeyIdx]; } @@ -1423,47 +1429,47 @@ VOID STAFindCipherAlgorithm( pTxBlk->pKey = pKey; } - -VOID STABuildCommon802_11Header( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk) +void STABuildCommon802_11Header(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk) { - HEADER_802_11 *pHeader_802_11; + struct rt_header_802_11 *pHeader_802_11; - // - // MAKE A COMMON 802.11 HEADER - // + /* */ + /* MAKE A COMMON 802.11 HEADER */ + /* */ - // normal wlan header size : 24 octets - pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11); + /* normal wlan header size : 24 octets */ + pTxBlk->MpduHeaderLen = sizeof(struct rt_header_802_11); - pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; + pHeader_802_11 = + (struct rt_header_802_11 *) & pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; - NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11)); + NdisZeroMemory(pHeader_802_11, sizeof(struct rt_header_802_11)); pHeader_802_11->FC.FrDs = 0; pHeader_802_11->FC.Type = BTYPE_DATA; - pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA); - - if (pTxBlk->pMacEntry) - { - if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS)) - { - pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq; - pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ; - } - else - { + pHeader_802_11->FC.SubType = + ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : + SUBTYPE_DATA); + + if (pTxBlk->pMacEntry) { + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS)) { + pHeader_802_11->Sequence = + pTxBlk->pMacEntry->NonQosDataSeq; + pTxBlk->pMacEntry->NonQosDataSeq = + (pTxBlk->pMacEntry->NonQosDataSeq + 1) & MAXSEQ; + } else { { - pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]; - pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; - } - } - } - else - { + pHeader_802_11->Sequence = + pTxBlk->pMacEntry->TxSeq[pTxBlk-> + UserPriority]; + pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = + (pTxBlk->pMacEntry-> + TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ; + } + } + } else { pHeader_802_11->Sequence = pAd->Sequence; - pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence + pAd->Sequence = (pAd->Sequence + 1) & MAXSEQ; /* next sequence */ } pHeader_802_11->Frag = 0; @@ -1471,20 +1477,23 @@ VOID STABuildCommon802_11Header( pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); { - if (INFRA_ON(pAd)) - { + if (INFRA_ON(pAd)) { { - COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid); - COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); - COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader); - pHeader_802_11->FC.ToDs = 1; - } - } - else if (ADHOC_ON(pAd)) - { - COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader); - COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); - COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pHeader_802_11->Addr1, + pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pHeader_802_11->Addr2, + pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, + pTxBlk->pSrcBufHeader); + pHeader_802_11->FC.ToDs = 1; + } + } else if (ADHOC_ON(pAd)) { + COPY_MAC_ADDR(pHeader_802_11->Addr1, + pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(pHeader_802_11->Addr2, + pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, + pAd->CommonCfg.Bssid); pHeader_802_11->FC.ToDs = 0; } } @@ -1492,107 +1501,107 @@ VOID STABuildCommon802_11Header( if (pTxBlk->CipherAlg != CIPHER_NONE) pHeader_802_11->FC.Wep = 1; - // ----------------------------------------------------------------- - // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. - // ----------------------------------------------------------------- + /* ----------------------------------------------------------------- */ + /* STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. */ + /* ----------------------------------------------------------------- */ if (pAd->CommonCfg.bAPSDForcePowerSave) - pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; else - pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); + pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); } -VOID STABuildCache802_11Header( - IN RTMP_ADAPTER *pAd, - IN TX_BLK *pTxBlk, - IN UCHAR *pHeader) +void STABuildCache802_11Header(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, u8 * pHeader) { - MAC_TABLE_ENTRY *pMacEntry; - PHEADER_802_11 pHeader80211; + struct rt_mac_table_entry *pMacEntry; + struct rt_header_802_11 * pHeader80211; - pHeader80211 = (PHEADER_802_11)pHeader; + pHeader80211 = (struct rt_header_802_11 *) pHeader; pMacEntry = pTxBlk->pMacEntry; - // - // Update the cached 802.11 HEADER - // + /* */ + /* Update the cached 802.11 HEADER */ + /* */ - // normal wlan header size : 24 octets - pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11); + /* normal wlan header size : 24 octets */ + pTxBlk->MpduHeaderLen = sizeof(struct rt_header_802_11); - // More Bit + /* More Bit */ pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); - // Sequence + /* Sequence */ pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority]; - pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; + pMacEntry->TxSeq[pTxBlk->UserPriority] = + (pMacEntry->TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ; { - // The addr3 of normal packet send from DS is Dest Mac address. + /* Check if the frame can be sent through DLS direct link interface */ + /* If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) */ + + /* The addr3 of normal packet send from DS is Dest Mac address. */ if (ADHOC_ON(pAd)) - COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pHeader80211->Addr3, + pAd->CommonCfg.Bssid); else - COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(pHeader80211->Addr3, + pTxBlk->pSrcBufHeader); } - // ----------------------------------------------------------------- - // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. - // ----------------------------------------------------------------- + /* ----------------------------------------------------------------- */ + /* STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. */ + /* ----------------------------------------------------------------- */ if (pAd->CommonCfg.bAPSDForcePowerSave) - pHeader80211->FC.PwrMgmt = PWR_SAVE; + pHeader80211->FC.PwrMgmt = PWR_SAVE; else - pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); + pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); } -static inline PUCHAR STA_Build_ARalink_Frame_Header( - IN RTMP_ADAPTER *pAd, - IN TX_BLK *pTxBlk) +static inline u8 *STA_Build_ARalink_Frame_Header(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk) { - PUCHAR pHeaderBufPtr; - HEADER_802_11 *pHeader_802_11; - PNDIS_PACKET pNextPacket; - UINT32 nextBufLen; - PQUEUE_ENTRY pQEntry; + u8 *pHeaderBufPtr; + struct rt_header_802_11 *pHeader_802_11; + void *pNextPacket; + u32 nextBufLen; + struct rt_queue_entry *pQEntry; STAFindCipherAlgorithm(pAd, pTxBlk); STABuildCommon802_11Header(pAd, pTxBlk); - pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; - pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr; - // steal "order" bit to mark "aggregation" + /* steal "order" bit to mark "aggregation" */ pHeader_802_11->FC.Order = 1; - // skip common header + /* skip common header */ pHeaderBufPtr += pTxBlk->MpduHeaderLen; - if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) - { - // - // build QOS Control bytes - // + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) { + /* */ + /* build QOS Control bytes */ + /* */ *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); - *(pHeaderBufPtr+1) = 0; - pHeaderBufPtr +=2; + *(pHeaderBufPtr + 1) = 0; + pHeaderBufPtr += 2; pTxBlk->MpduHeaderLen += 2; } + /* padding at front of LLC header. LLC header should at 4-bytes aligment. */ + pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr; + pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen); - // padding at front of LLC header. LLC header should at 4-bytes aligment. - pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; - pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4); - pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); - - // For RA Aggregation, - // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format + /* For RA Aggregation, */ + /* put the 2nd MSDU length(extra 2-byte field) after struct rt_qos_control in little endian format */ pQEntry = pTxBlk->TxPacketList.Head; - pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry); + pNextPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); nextBufLen = GET_OS_PKT_LEN(pNextPacket); if (RTMP_GET_PACKET_VLAN(pNextPacket)) nextBufLen -= LENGTH_802_1Q; - *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff; - *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8); + *pHeaderBufPtr = (u8)nextBufLen & 0xff; + *(pHeaderBufPtr + 1) = (u8)(nextBufLen >> 8); pHeaderBufPtr += 2; pTxBlk->MpduHeaderLen += 2; @@ -1601,198 +1610,207 @@ static inline PUCHAR STA_Build_ARalink_Frame_Header( } -static inline PUCHAR STA_Build_AMSDU_Frame_Header( - IN RTMP_ADAPTER *pAd, - IN TX_BLK *pTxBlk) +static inline u8 *STA_Build_AMSDU_Frame_Header(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk) { - PUCHAR pHeaderBufPtr;//, pSaveBufPtr; - HEADER_802_11 *pHeader_802_11; - + u8 *pHeaderBufPtr; /*, pSaveBufPtr; */ + struct rt_header_802_11 *pHeader_802_11; STAFindCipherAlgorithm(pAd, pTxBlk); STABuildCommon802_11Header(pAd, pTxBlk); pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; - pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr; - // skip common header + /* skip common header */ pHeaderBufPtr += pTxBlk->MpduHeaderLen; - // - // build QOS Control bytes - // + /* */ + /* build QOS Control bytes */ + /* */ *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); - // - // A-MSDU packet - // + /* */ + /* A-MSDU packet */ + /* */ *pHeaderBufPtr |= 0x80; - *(pHeaderBufPtr+1) = 0; - pHeaderBufPtr +=2; + *(pHeaderBufPtr + 1) = 0; + pHeaderBufPtr += 2; pTxBlk->MpduHeaderLen += 2; - //pSaveBufPtr = pHeaderBufPtr; + /*pSaveBufPtr = pHeaderBufPtr; */ - // - // padding at front of LLC header - // LLC header should locate at 4-octets aligment - // - // @@@ MpduHeaderLen excluding padding @@@ - // - pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; - pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4); - pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + /* */ + /* padding at front of LLC header */ + /* LLC header should locate at 4-octets aligment */ + /* */ + /* @@@ MpduHeaderLen excluding padding @@@ */ + /* */ + pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr; + pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen); return pHeaderBufPtr; } - -VOID STA_AMPDU_Frame_Tx( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk) +void STA_AMPDU_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk) { - HEADER_802_11 *pHeader_802_11; - PUCHAR pHeaderBufPtr; - USHORT FreeNumber; - MAC_TABLE_ENTRY *pMacEntry; - BOOLEAN bVLANPkt; - PQUEUE_ENTRY pQEntry; + struct rt_header_802_11 *pHeader_802_11; + u8 *pHeaderBufPtr; + u16 FreeNumber; + struct rt_mac_table_entry *pMacEntry; + BOOLEAN bVLANPkt; + struct rt_queue_entry *pQEntry; ASSERT(pTxBlk); - while(pTxBlk->TxPacketList.Head) - { + while (pTxBlk->TxPacketList.Head) { pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); - if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) - { - RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, + NDIS_STATUS_FAILURE); continue; } - bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + bVLANPkt = + (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); pMacEntry = pTxBlk->pMacEntry; - if (pMacEntry->isCached) - { - // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!! - NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11)); - pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]); + if (pMacEntry->isCached) { + /* NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]! */ + NdisMoveMemory((u8 *)& pTxBlk-> + HeaderBuf[TXINFO_SIZE], + (u8 *)& pMacEntry->CachedBuf[0], + TXWI_SIZE + sizeof(struct rt_header_802_11)); + pHeaderBufPtr = + (u8 *)(&pTxBlk-> + HeaderBuf[TXINFO_SIZE + TXWI_SIZE]); STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr); - } - else - { + } else { STAFindCipherAlgorithm(pAd, pTxBlk); STABuildCommon802_11Header(pAd, pTxBlk); - pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; + pHeaderBufPtr = + &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; } + pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr; - pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; - - // skip common header + /* skip common header */ pHeaderBufPtr += pTxBlk->MpduHeaderLen; - // - // build QOS Control bytes - // + /* */ + /* build QOS Control bytes */ + /* */ *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); - *(pHeaderBufPtr+1) = 0; - pHeaderBufPtr +=2; + *(pHeaderBufPtr + 1) = 0; + pHeaderBufPtr += 2; pTxBlk->MpduHeaderLen += 2; - // - // build HTC+ - // HTC control filed following QoS field - // - if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)) - { - if (pMacEntry->isCached == FALSE) - { - // mark HTC bit + /* */ + /* build HTC+ */ + /* HTC control filed following QoS field */ + /* */ + if ((pAd->CommonCfg.bRdg == TRUE) + && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, + fCLIENT_STATUS_RDG_CAPABLE)) { + if (pMacEntry->isCached == FALSE) { + /* mark HTC bit */ pHeader_802_11->FC.Order = 1; NdisZeroMemory(pHeaderBufPtr, 4); - *(pHeaderBufPtr+3) |= 0x80; + *(pHeaderBufPtr + 3) |= 0x80; } pHeaderBufPtr += 4; pTxBlk->MpduHeaderLen += 4; } - - //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE; + /*pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE; */ ASSERT(pTxBlk->MpduHeaderLen >= 24); - // skip 802.3 header + /* skip 802.3 header */ pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; - pTxBlk->SrcBufLen -= LENGTH_802_3; - - // skip vlan tag - if (bVLANPkt) - { - pTxBlk->pSrcBufData += LENGTH_802_1Q; - pTxBlk->SrcBufLen -= LENGTH_802_1Q; - } - - // - // padding at front of LLC header - // LLC header should locate at 4-octets aligment - // - // @@@ MpduHeaderLen excluding padding @@@ - // - pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; - pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4); - pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); - - { - - // - // Insert LLC-SNAP encapsulation - 8 octets - // - EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); - if (pTxBlk->pExtraLlcSnapEncap) - { - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + if (bVLANPkt) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + /* */ + /* padding at front of LLC header */ + /* LLC header should locate at 4-octets aligment */ + /* */ + /* @@@ MpduHeaderLen excluding padding @@@ */ + /* */ + pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr; + pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen); + + { + + /* */ + /* Insert LLC-SNAP encapsulation - 8 octets */ + /* */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk-> + pSrcBufData - 2, + pTxBlk-> + pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) { + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pExtraLlcSnapEncap, 6); pHeaderBufPtr += 6; - // get 2 octets (TypeofLen) - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pSrcBufData - 2, 2); pHeaderBufPtr += 2; pTxBlk->MpduHeaderLen += LENGTH_802_1_H; } } - if (pMacEntry->isCached) - { - RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); - } - else - { - RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); - - NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf)); - NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]))); + if (pMacEntry->isCached) { + RTMPWriteTxWI_Cache(pAd, + (struct rt_txwi *) (&pTxBlk-> + HeaderBuf + [TXINFO_SIZE]), + pTxBlk); + } else { + RTMPWriteTxWI_Data(pAd, + (struct rt_txwi *) (&pTxBlk-> + HeaderBuf + [TXINFO_SIZE]), + pTxBlk); + + NdisZeroMemory((u8 *)(&pMacEntry->CachedBuf[0]), + sizeof(pMacEntry->CachedBuf)); + NdisMoveMemory((u8 *)(&pMacEntry->CachedBuf[0]), + (u8 *)(&pTxBlk-> + HeaderBuf[TXINFO_SIZE]), + (pHeaderBufPtr - + (u8 *)(&pTxBlk-> + HeaderBuf[TXINFO_SIZE]))); pMacEntry->isCached = TRUE; } - // calculate Transmitted AMPDU count and ByteCount + /* calculate Transmitted AMPDU count and ByteCount */ { - pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++; - pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen; + pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u. + LowPart++; + pAd->RalinkCounters.TransmittedOctetsInAMPDUCount. + QuadPart += pTxBlk->SrcBufLen; } - //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); + /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */ HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); - // - // Kick out Tx - // -#ifdef RT2860 + /* */ + /* Kick out Tx */ + /* */ if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) -#endif HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); pAd->RalinkCounters.KickTxCount++; @@ -1801,118 +1819,124 @@ VOID STA_AMPDU_Frame_Tx( } - -VOID STA_AMSDU_Frame_Tx( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk) +void STA_AMSDU_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk) { - PUCHAR pHeaderBufPtr; - USHORT FreeNumber; - USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding. - USHORT totalMPDUSize=0; - UCHAR *subFrameHeader; - UCHAR padding = 0; - USHORT FirstTx = 0, LastTxIdx = 0; - BOOLEAN bVLANPkt; - int frameNum = 0; - PQUEUE_ENTRY pQEntry; - + u8 *pHeaderBufPtr; + u16 FreeNumber; + u16 subFramePayloadLen = 0; /* AMSDU Subframe length without AMSDU-Header / Padding. */ + u16 totalMPDUSize = 0; + u8 *subFrameHeader; + u8 padding = 0; + u16 FirstTx = 0, LastTxIdx = 0; + BOOLEAN bVLANPkt; + int frameNum = 0; + struct rt_queue_entry *pQEntry; ASSERT(pTxBlk); ASSERT((pTxBlk->TxPacketList.Number > 1)); - while(pTxBlk->TxPacketList.Head) - { + while (pTxBlk->TxPacketList.Head) { pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); - if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) - { - RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, + NDIS_STATUS_FAILURE); continue; } - bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + bVLANPkt = + (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); - // skip 802.3 header + /* skip 802.3 header */ pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; - pTxBlk->SrcBufLen -= LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; - // skip vlan tag - if (bVLANPkt) - { - pTxBlk->pSrcBufData += LENGTH_802_1Q; - pTxBlk->SrcBufLen -= LENGTH_802_1Q; + /* skip vlan tag */ + if (bVLANPkt) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; } - if (frameNum == 0) - { - pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk); + if (frameNum == 0) { + pHeaderBufPtr = + STA_Build_AMSDU_Frame_Header(pAd, pTxBlk); - // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled. - RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); - } - else - { + /* NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled. */ + RTMPWriteTxWI_Data(pAd, + (struct rt_txwi *) (&pTxBlk-> + HeaderBuf + [TXINFO_SIZE]), + pTxBlk); + } else { pHeaderBufPtr = &pTxBlk->HeaderBuf[0]; - padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen); - NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD); + padding = + ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + + subFramePayloadLen, + 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + + subFramePayloadLen); + NdisZeroMemory(pHeaderBufPtr, + padding + LENGTH_AMSDU_SUBFRAMEHEAD); pHeaderBufPtr += padding; pTxBlk->MpduHeaderLen = padding; } - // - // A-MSDU subframe - // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap - // + /* */ + /* A-MSDU subframe */ + /* DA(6)+SA(6)+Length(2) + LLC/SNAP Encap */ + /* */ subFrameHeader = pHeaderBufPtr; subFramePayloadLen = pTxBlk->SrcBufLen; NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12); - pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD; pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD; - - // - // Insert LLC-SNAP encapsulation - 8 octets - // - EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); + /* */ + /* Insert LLC-SNAP encapsulation - 8 octets */ + /* */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, + pTxBlk->pExtraLlcSnapEncap); subFramePayloadLen = pTxBlk->SrcBufLen; - if (pTxBlk->pExtraLlcSnapEncap) - { - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + if (pTxBlk->pExtraLlcSnapEncap) { + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pExtraLlcSnapEncap, 6); pHeaderBufPtr += 6; - // get 2 octets (TypeofLen) - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2, + 2); pHeaderBufPtr += 2; pTxBlk->MpduHeaderLen += LENGTH_802_1_H; subFramePayloadLen += LENGTH_802_1_H; } - - // update subFrame Length field + /* update subFrame Length field */ subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8; subFrameHeader[13] = subFramePayloadLen & 0xFF; totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; - if (frameNum ==0) - FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); + if (frameNum == 0) + FirstTx = + HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, + &FreeNumber); else - LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); + LastTxIdx = + HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, + &FreeNumber); frameNum++; pAd->RalinkCounters.KickTxCount++; pAd->RalinkCounters.OneSecTxDoneCount++; - // calculate Transmitted AMSDU Count and ByteCount + /* calculate Transmitted AMSDU Count and ByteCount */ { - pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++; - pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize; + pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart++; + pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += + totalMPDUSize; } } @@ -1920,38 +1944,31 @@ VOID STA_AMSDU_Frame_Tx( HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx); HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx); - // - // Kick out Tx - // -#ifdef RT2860 + /* */ + /* Kick out Tx */ + /* */ if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) -#endif HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); } -VOID STA_Legacy_Frame_Tx( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk) +void STA_Legacy_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk) { - HEADER_802_11 *pHeader_802_11; - PUCHAR pHeaderBufPtr; - USHORT FreeNumber; - BOOLEAN bVLANPkt; - PQUEUE_ENTRY pQEntry; + struct rt_header_802_11 *pHeader_802_11; + u8 *pHeaderBufPtr; + u16 FreeNumber; + BOOLEAN bVLANPkt; + struct rt_queue_entry *pQEntry; ASSERT(pTxBlk); - pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); - if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) - { + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) { RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return; } - if (pTxBlk->TxFrameType == TX_MCAST_FRAME) - { + if (pTxBlk->TxFrameType == TX_MCAST_FRAME) { INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount); } @@ -1968,181 +1985,187 @@ VOID STA_Legacy_Frame_Tx( STAFindCipherAlgorithm(pAd, pTxBlk); STABuildCommon802_11Header(pAd, pTxBlk); - - // skip 802.3 header + /* skip 802.3 header */ pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; - pTxBlk->SrcBufLen -= LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; - // skip vlan tag - if (bVLANPkt) - { - pTxBlk->pSrcBufData += LENGTH_802_1Q; - pTxBlk->SrcBufLen -= LENGTH_802_1Q; + /* skip vlan tag */ + if (bVLANPkt) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; } pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; - pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr; - // skip common header + /* skip common header */ pHeaderBufPtr += pTxBlk->MpduHeaderLen; - if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) - { - // - // build QOS Control bytes - // - *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); - *(pHeaderBufPtr+1) = 0; - pHeaderBufPtr +=2; + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) { + /* */ + /* build QOS Control bytes */ + /* */ + *(pHeaderBufPtr) = + ((pTxBlk->UserPriority & 0x0F) | (pAd->CommonCfg. + AckPolicy[pTxBlk-> + QueIdx] << 5)); + *(pHeaderBufPtr + 1) = 0; + pHeaderBufPtr += 2; pTxBlk->MpduHeaderLen += 2; } - - // The remaining content of MPDU header should locate at 4-octets aligment - pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; - pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4); - pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + /* The remaining content of MPDU header should locate at 4-octets aligment */ + pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr; + pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen); { - // - // Insert LLC-SNAP encapsulation - 8 octets - // - // - // if original Ethernet frame contains no LLC/SNAP, - // then an extra LLC/SNAP encap is required - // - EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap); - if (pTxBlk->pExtraLlcSnapEncap) - { - UCHAR vlan_size; - - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + /* */ + /* Insert LLC-SNAP encapsulation - 8 octets */ + /* */ + /* */ + /* if original Ethernet frame contains no LLC/SNAP, */ + /* then an extra LLC/SNAP encap is required */ + /* */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, + pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) { + u8 vlan_size; + + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pExtraLlcSnapEncap, 6); pHeaderBufPtr += 6; - // skip vlan tag - vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; - // get 2 octets (TypeofLen) - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2); + /* skip vlan tag */ + vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pSrcBufHeader + 12 + vlan_size, + 2); pHeaderBufPtr += 2; pTxBlk->MpduHeaderLen += LENGTH_802_1_H; } } - // - // prepare for TXWI - // use Wcid as Key Index - // + /* */ + /* prepare for TXWI */ + /* use Wcid as Key Index */ + /* */ - RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + RTMPWriteTxWI_Data(pAd, (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]), + pTxBlk); - //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); + /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */ HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); pAd->RalinkCounters.KickTxCount++; pAd->RalinkCounters.OneSecTxDoneCount++; - // - // Kick out Tx - // -#ifdef RT2860 + /* */ + /* Kick out Tx */ + /* */ if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) -#endif HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); } - -VOID STA_ARalink_Frame_Tx( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk) +void STA_ARalink_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk) { - PUCHAR pHeaderBufPtr; - USHORT FreeNumber; - USHORT totalMPDUSize=0; - USHORT FirstTx, LastTxIdx; - int frameNum = 0; - BOOLEAN bVLANPkt; - PQUEUE_ENTRY pQEntry; - + u8 *pHeaderBufPtr; + u16 FreeNumber; + u16 totalMPDUSize = 0; + u16 FirstTx, LastTxIdx; + int frameNum = 0; + BOOLEAN bVLANPkt; + struct rt_queue_entry *pQEntry; ASSERT(pTxBlk); - ASSERT((pTxBlk->TxPacketList.Number== 2)); - + ASSERT((pTxBlk->TxPacketList.Number == 2)); - FirstTx = LastTxIdx = 0; // Is it ok init they as 0? - while(pTxBlk->TxPacketList.Head) - { + FirstTx = LastTxIdx = 0; /* Is it ok init they as 0? */ + while (pTxBlk->TxPacketList.Head) { pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); - if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) - { - RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, + NDIS_STATUS_FAILURE); continue; } - bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + bVLANPkt = + (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); - // skip 802.3 header + /* skip 802.3 header */ pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; - pTxBlk->SrcBufLen -= LENGTH_802_3; - - // skip vlan tag - if (bVLANPkt) - { - pTxBlk->pSrcBufData += LENGTH_802_1Q; - pTxBlk->SrcBufLen -= LENGTH_802_1Q; - } - - if (frameNum == 0) - { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header - - pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk); - - // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount - // will be updated after final frame was handled. - RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); - - - // - // Insert LLC-SNAP encapsulation - 8 octets - // - EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); - - if (pTxBlk->pExtraLlcSnapEncap) - { - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + if (bVLANPkt) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + if (frameNum == 0) { /* For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header */ + + pHeaderBufPtr = + STA_Build_ARalink_Frame_Header(pAd, pTxBlk); + + /* It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount */ + /* will be updated after final frame was handled. */ + RTMPWriteTxWI_Data(pAd, + (struct rt_txwi *) (&pTxBlk-> + HeaderBuf + [TXINFO_SIZE]), + pTxBlk); + + /* */ + /* Insert LLC-SNAP encapsulation - 8 octets */ + /* */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk-> + pSrcBufData - 2, + pTxBlk-> + pExtraLlcSnapEncap); + + if (pTxBlk->pExtraLlcSnapEncap) { + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pExtraLlcSnapEncap, 6); pHeaderBufPtr += 6; - // get 2 octets (TypeofLen) - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pSrcBufData - 2, 2); pHeaderBufPtr += 2; pTxBlk->MpduHeaderLen += LENGTH_802_1_H; } - } - else - { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0. + } else { /* For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0. */ pHeaderBufPtr = &pTxBlk->HeaderBuf[0]; pTxBlk->MpduHeaderLen = 0; - // A-Ralink sub-sequent frame header is the same as 802.3 header. - // DA(6)+SA(6)+FrameType(2) - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12); + /* A-Ralink sub-sequent frame header is the same as 802.3 header. */ + /* DA(6)+SA(6)+FrameType(2) */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, + 12); pHeaderBufPtr += 12; - // get 2 octets (TypeofLen) - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2, + 2); pHeaderBufPtr += 2; pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD; } totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; - //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); - if (frameNum ==0) - FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); + /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */ + if (frameNum == 0) + FirstTx = + HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, + &FreeNumber); else - LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); + LastTxIdx = + HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, + &FreeNumber); frameNum++; @@ -2155,40 +2178,34 @@ VOID STA_ARalink_Frame_Tx( HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx); HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx); - // - // Kick out Tx - // -#ifdef RT2860 + /* */ + /* Kick out Tx */ + /* */ if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) -#endif HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); } - -VOID STA_Fragment_Frame_Tx( - IN RTMP_ADAPTER *pAd, - IN TX_BLK *pTxBlk) +void STA_Fragment_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk) { - HEADER_802_11 *pHeader_802_11; - PUCHAR pHeaderBufPtr; - USHORT FreeNumber; - UCHAR fragNum = 0; - PACKET_INFO PacketInfo; - USHORT EncryptionOverhead = 0; - UINT32 FreeMpduSize, SrcRemainingBytes; - USHORT AckDuration; - UINT NextMpduSize; - BOOLEAN bVLANPkt; - PQUEUE_ENTRY pQEntry; - + struct rt_header_802_11 *pHeader_802_11; + u8 *pHeaderBufPtr; + u16 FreeNumber; + u8 fragNum = 0; + struct rt_packet_info PacketInfo; + u16 EncryptionOverhead = 0; + u32 FreeMpduSize, SrcRemainingBytes; + u16 AckDuration; + u32 NextMpduSize; + BOOLEAN bVLANPkt; + struct rt_queue_entry *pQEntry; + HTTRANSMIT_SETTING *pTransmit; ASSERT(pTxBlk); pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); - if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) - { + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) { RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return; } @@ -2199,112 +2216,125 @@ VOID STA_Fragment_Frame_Tx( STAFindCipherAlgorithm(pAd, pTxBlk); STABuildCommon802_11Header(pAd, pTxBlk); - if (pTxBlk->CipherAlg == CIPHER_TKIP) - { - pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket); + if (pTxBlk->CipherAlg == CIPHER_TKIP) { + pTxBlk->pPacket = + duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket); if (pTxBlk->pPacket == NULL) return; - RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); + RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, + &pTxBlk->pSrcBufHeader, + &pTxBlk->SrcBufLen); } - - // skip 802.3 header + /* skip 802.3 header */ pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; - pTxBlk->SrcBufLen -= LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; - - // skip vlan tag - if (bVLANPkt) - { - pTxBlk->pSrcBufData += LENGTH_802_1Q; - pTxBlk->SrcBufLen -= LENGTH_802_1Q; + /* skip vlan tag */ + if (bVLANPkt) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; } pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; - pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr; - + pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr; - // skip common header + /* skip common header */ pHeaderBufPtr += pTxBlk->MpduHeaderLen; - if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) - { - // - // build QOS Control bytes - // + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) { + /* */ + /* build QOS Control bytes */ + /* */ *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); - *(pHeaderBufPtr+1) = 0; - pHeaderBufPtr +=2; + *(pHeaderBufPtr + 1) = 0; + pHeaderBufPtr += 2; pTxBlk->MpduHeaderLen += 2; } - - // - // padding at front of LLC header - // LLC header should locate at 4-octets aligment - // - pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; - pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4); - pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); - - - - // - // Insert LLC-SNAP encapsulation - 8 octets - // - // - // if original Ethernet frame contains no LLC/SNAP, - // then an extra LLC/SNAP encap is required - // - EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap); - if (pTxBlk->pExtraLlcSnapEncap) - { - UCHAR vlan_size; + /* */ + /* padding at front of LLC header */ + /* LLC header should locate at 4-octets aligment */ + /* */ + pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr; + pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen); + + /* */ + /* Insert LLC-SNAP encapsulation - 8 octets */ + /* */ + /* */ + /* if original Ethernet frame contains no LLC/SNAP, */ + /* then an extra LLC/SNAP encap is required */ + /* */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, + pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) { + u8 vlan_size; NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); pHeaderBufPtr += 6; - // skip vlan tag - vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; - // get 2 octets (TypeofLen) - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2); + /* skip vlan tag */ + vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pSrcBufHeader + 12 + vlan_size, 2); pHeaderBufPtr += 2; pTxBlk->MpduHeaderLen += LENGTH_802_1_H; } - - // If TKIP is used and fragmentation is required. Driver has to - // append TKIP MIC at tail of the scatter buffer - // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC - if (pTxBlk->CipherAlg == CIPHER_TKIP) - { - - // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust - // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress. - NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8); - //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8); + /* If TKIP is used and fragmentation is required. Driver has to */ + /* append TKIP MIC at tail of the scatter buffer */ + /* MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC */ + if (pTxBlk->CipherAlg == CIPHER_TKIP) { + RTMPCalculateMICValue(pAd, pTxBlk->pPacket, + pTxBlk->pExtraLlcSnapEncap, pTxBlk->pKey, + 0); + + /* NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust */ + /* to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress. */ + NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, + &pAd->PrivateInfo.Tx.MIC[0], 8); + /*skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8); */ pTxBlk->SrcBufLen += 8; pTxBlk->TotalFrameLen += 8; pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC; } - - // - // calcuate the overhead bytes that encryption algorithm may add. This - // affects the calculate of "duration" field - // - if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128)) - EncryptionOverhead = 8; //WEP: IV[4] + ICV[4]; + /* */ + /* calcuate the overhead bytes that encryption algorithm may add. This */ + /* affects the calculate of "duration" field */ + /* */ + if ((pTxBlk->CipherAlg == CIPHER_WEP64) + || (pTxBlk->CipherAlg == CIPHER_WEP128)) + EncryptionOverhead = 8; /*WEP: IV[4] + ICV[4]; */ else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC) - EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength + EncryptionOverhead = 12; /*TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength */ else if (pTxBlk->CipherAlg == CIPHER_TKIP) - EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8] + EncryptionOverhead = 20; /*TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8] */ else if (pTxBlk->CipherAlg == CIPHER_AES) - EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8] + EncryptionOverhead = 16; /* AES: IV[4] + EIV[4] + MIC[8] */ else EncryptionOverhead = 0; - // decide how much time an ACK/CTS frame will consume in the air - AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14); + pTransmit = pTxBlk->pTransmit; + /* Decide the TX rate */ + if (pTransmit->field.MODE == MODE_CCK) + pTxBlk->TxRate = pTransmit->field.MCS; + else if (pTransmit->field.MODE == MODE_OFDM) + pTxBlk->TxRate = pTransmit->field.MCS + RATE_FIRST_OFDM_RATE; + else + pTxBlk->TxRate = RATE_6_5; + + /* decide how much time an ACK/CTS frame will consume in the air */ + if (pTxBlk->TxRate <= RATE_LAST_OFDM_RATE) + AckDuration = + RTMPCalcDuration(pAd, + pAd->CommonCfg.ExpectedACKRate[pTxBlk-> + TxRate], + 14); + else + AckDuration = RTMPCalcDuration(pAd, RATE_6_5, 14); - // Init the total payload length of this frame. + /* Init the total payload length of this frame. */ SrcRemainingBytes = pTxBlk->SrcBufLen; pTxBlk->TotalFragNum = 0xff; @@ -2315,25 +2345,28 @@ VOID STA_Fragment_Frame_Tx( FreeMpduSize -= pTxBlk->MpduHeaderLen; - if (SrcRemainingBytes <= FreeMpduSize) - { // this is the last or only fragment + if (SrcRemainingBytes <= FreeMpduSize) { /* this is the last or only fragment */ pTxBlk->SrcBufLen = SrcRemainingBytes; pHeader_802_11->FC.MoreFrag = 0; - pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration; + pHeader_802_11->Duration = + pAd->CommonCfg.Dsifs + AckDuration; - // Indicate the lower layer that this's the last fragment. + /* Indicate the lower layer that this's the last fragment. */ pTxBlk->TotalFragNum = fragNum; - } - else - { // more fragment is required + } else { /* more fragment is required */ pTxBlk->SrcBufLen = FreeMpduSize; - NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold)); + NextMpduSize = + min(((u32)SrcRemainingBytes - pTxBlk->SrcBufLen), + ((u32)pAd->CommonCfg.FragmentThreshold)); pHeader_802_11->FC.MoreFrag = 1; - pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead); + pHeader_802_11->Duration = + (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + + RTMPCalcDuration(pAd, pTxBlk->TxRate, + NextMpduSize + EncryptionOverhead); } if (fragNum == 0) @@ -2341,16 +2374,19 @@ VOID STA_Fragment_Frame_Tx( else pTxBlk->FrameGap = IFS_SIFS; - RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + RTMPWriteTxWI_Data(pAd, + (struct rt_txwi *) (&pTxBlk-> + HeaderBuf[TXINFO_SIZE]), + pTxBlk); HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber); pAd->RalinkCounters.KickTxCount++; pAd->RalinkCounters.OneSecTxDoneCount++; - // Update the frame number, remaining size of the NDIS packet payload. + /* Update the frame number, remaining size of the NDIS packet payload. */ - // space for 802.11 header. + /* space for 802.11 header. */ if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap) pTxBlk->MpduHeaderLen -= LENGTH_802_1_H; @@ -2358,17 +2394,17 @@ VOID STA_Fragment_Frame_Tx( SrcRemainingBytes -= pTxBlk->SrcBufLen; pTxBlk->pSrcBufData += pTxBlk->SrcBufLen; - pHeader_802_11->Frag++; // increase Frag # + pHeader_802_11->Frag++; /* increase Frag # */ - }while(SrcRemainingBytes > 0); + } while (SrcRemainingBytes > 0); - // - // Kick out Tx - // - HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + /* */ + /* Kick out Tx */ + /* */ + if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); } - #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \ while(_pTxBlk->TxPacketList.Head) \ { \ @@ -2376,7 +2412,6 @@ VOID STA_Fragment_Frame_Tx( RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \ } - /* ======================================================================== @@ -2387,7 +2422,7 @@ VOID STA_Fragment_Frame_Tx( Arguments: pAd Pointer to our adapter - PNDIS_PACKET Pointer to outgoing Ndis frame + void * Pointer to outgoing Ndis frame NumberOfFrag Number of fragment required Return Value: @@ -2399,122 +2434,117 @@ VOID STA_Fragment_Frame_Tx( ======================================================================== */ -NDIS_STATUS STAHardTransmit( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR QueIdx) +int STAHardTransmit(struct rt_rtmp_adapter *pAd, + struct rt_tx_blk *pTxBlk, u8 QueIdx) { - NDIS_PACKET *pPacket; - PQUEUE_ENTRY pQEntry; + char *pPacket; + struct rt_queue_entry *pQEntry; - // --------------------------------------------- - // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION. - // --------------------------------------------- - // + /* --------------------------------------------- */ + /* STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION. */ + /* --------------------------------------------- */ + /* */ ASSERT(pTxBlk->TxPacketList.Number); - if (pTxBlk->TxPacketList.Head == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number)); + if (pTxBlk->TxPacketList.Head == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("pTxBlk->TotalFrameNum == %ld!\n", + pTxBlk->TxPacketList.Number)); return NDIS_STATUS_FAILURE; } pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head); - // ------------------------------------------------------------------ - // STEP 1. WAKE UP PHY - // outgoing frame always wakeup PHY to prevent frame lost and - // turn off PSM bit to improve performance - // ------------------------------------------------------------------ - // not to change PSM bit, just send this frame out? - if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n")); -#ifdef RT2860 - AsicForceWakeup(pAd, FROM_TX); -#endif -#ifdef RT2870 + /* ------------------------------------------------------------------ */ + /* STEP 1. WAKE UP PHY */ + /* outgoing frame always wakeup PHY to prevent frame lost and */ + /* turn off PSM bit to improve performance */ + /* ------------------------------------------------------------------ */ + /* not to change PSM bit, just send this frame out? */ + if ((pAd->StaCfg.Psm == PWR_SAVE) + && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { + DBGPRINT_RAW(RT_DEBUG_INFO, ("AsicForceWakeup At HardTx\n")); +#ifdef RTMP_MAC_PCI AsicForceWakeup(pAd, TRUE); -#endif +#endif /* RTMP_MAC_PCI // */ +#ifdef RTMP_MAC_USB + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_FORCE_WAKE_UP, NULL, 0); +#endif /* RTMP_MAC_USB // */ } - - // It should not change PSM bit, when APSD turn on. - if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE)) - || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) - || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket))) - { + /* It should not change PSM bit, when APSD turn on. */ + if ((! + (pAd->CommonCfg.bAPSDCapable + && pAd->CommonCfg.APEdcaParm.bAPSDCapable) + && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE)) + || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) + || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket))) { if ((pAd->StaCfg.Psm == PWR_SAVE) && - (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP)) - MlmeSetPsmBit(pAd, PWR_ACTIVE); + (pAd->StaCfg.WindowsPowerMode == + Ndis802_11PowerModeFast_PSP)) + RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE); } - switch (pTxBlk->TxFrameType) - { - case TX_AMPDU_FRAME: - STA_AMPDU_Frame_Tx(pAd, pTxBlk); - break; - case TX_AMSDU_FRAME: - STA_AMSDU_Frame_Tx(pAd, pTxBlk); - break; - case TX_LEGACY_FRAME: - STA_Legacy_Frame_Tx(pAd, pTxBlk); - break; - case TX_MCAST_FRAME: - STA_Legacy_Frame_Tx(pAd, pTxBlk); - break; - case TX_RALINK_FRAME: - STA_ARalink_Frame_Tx(pAd, pTxBlk); - break; - case TX_FRAG_FRAME: - STA_Fragment_Frame_Tx(pAd, pTxBlk); - break; - default: - { - // It should not happened! - DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n")); - while(pTxBlk->TxPacketList.Number) - { - pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); - pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); - if (pPacket) - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - } + switch (pTxBlk->TxFrameType) { + case TX_AMPDU_FRAME: + STA_AMPDU_Frame_Tx(pAd, pTxBlk); + break; + case TX_AMSDU_FRAME: + STA_AMSDU_Frame_Tx(pAd, pTxBlk); + break; + case TX_LEGACY_FRAME: + STA_Legacy_Frame_Tx(pAd, pTxBlk); + break; + case TX_MCAST_FRAME: + STA_Legacy_Frame_Tx(pAd, pTxBlk); + break; + case TX_RALINK_FRAME: + STA_ARalink_Frame_Tx(pAd, pTxBlk); + break; + case TX_FRAG_FRAME: + STA_Fragment_Frame_Tx(pAd, pTxBlk); + break; + default: + { + /* It should not happened! */ + DBGPRINT(RT_DEBUG_ERROR, + ("Send a packet was not classified! It should not happen!\n")); + while (pTxBlk->TxPacketList.Number) { + pQEntry = + RemoveHeadQueue(&pTxBlk->TxPacketList); + pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (pPacket) + RELEASE_NDIS_PACKET(pAd, pPacket, + NDIS_STATUS_FAILURE); } - break; + } + break; } return (NDIS_STATUS_SUCCESS); } -ULONG HashBytesPolynomial(UCHAR *value, unsigned int len) +unsigned long HashBytesPolynomial(u8 * value, unsigned int len) { - unsigned char *word = value; - unsigned int ret = 0; - unsigned int i; - - for(i=0; i < len; i++) - { - int mod = i % 32; - ret ^=(unsigned int) (word[i]) << mod; - ret ^=(unsigned int) (word[i]) >> (32 - mod); - } - return ret; + unsigned char *word = value; + unsigned int ret = 0; + unsigned int i; + + for (i = 0; i < len; i++) { + int mod = i % 32; + ret ^= (unsigned int)(word[i]) << mod; + ret ^= (unsigned int)(word[i]) >> (32 - mod); + } + return ret; } -VOID Sta_Announce_or_Forward_802_3_Packet( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR FromWhichBSSID) +void Sta_Announce_or_Forward_802_3_Packet(struct rt_rtmp_adapter *pAd, + void *pPacket, + u8 FromWhichBSSID) { - if (TRUE - ) - { + if (TRUE) { announce_802_3_packet(pAd, pPacket); - } - else - { - // release packet + } else { + /* release packet */ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); } } - diff --git a/drivers/staging/rt2860/sta/sanity.c b/drivers/staging/rt2860/sta/sanity.c index 7d530f601602958d84c5bd7027c24c32b6c024f9..8f9fd19be1514ab158a31e59aba66ba0afb8e2be 100644 --- a/drivers/staging/rt2860/sta/sanity.c +++ b/drivers/staging/rt2860/sta/sanity.c @@ -36,15 +36,15 @@ */ #include "../rt_config.h" -extern UCHAR CISCO_OUI[]; +extern u8 CISCO_OUI[]; -extern UCHAR WPA_OUI[]; -extern UCHAR RSN_OUI[]; -extern UCHAR WME_INFO_ELEM[]; -extern UCHAR WME_PARM_ELEM[]; -extern UCHAR Ccx2QosInfo[]; -extern UCHAR RALINK_OUI[]; -extern UCHAR BROADCOM_OUI[]; +extern u8 WPA_OUI[]; +extern u8 RSN_OUI[]; +extern u8 WME_INFO_ELEM[]; +extern u8 WME_PARM_ELEM[]; +extern u8 Ccx2QosInfo[]; +extern u8 RALINK_OUI[]; +extern u8 BROADCOM_OUI[]; /* ========================================================================== @@ -54,27 +54,25 @@ extern UCHAR BROADCOM_OUI[]; TRUE if all parameters are OK, FALSE otherwise ========================================================================== */ -BOOLEAN MlmeStartReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT CHAR Ssid[], - OUT UCHAR *pSsidLen) +BOOLEAN MlmeStartReqSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + char Ssid[], u8 * pSsidLen) { - MLME_START_REQ_STRUCT *Info; + struct rt_mlme_start_req *Info; - Info = (MLME_START_REQ_STRUCT *)(Msg); + Info = (struct rt_mlme_start_req *)(Msg); - if (Info->SsidLen > MAX_LEN_OF_SSID) - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqSanity fail - wrong SSID length\n")); - return FALSE; - } + if (Info->SsidLen > MAX_LEN_OF_SSID) { + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeStartReqSanity fail - wrong SSID length\n")); + return FALSE; + } - *pSsidLen = Info->SsidLen; - NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen); + *pSsidLen = Info->SsidLen; + NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen); - return TRUE; + return TRUE; } /* @@ -88,211 +86,161 @@ BOOLEAN MlmeStartReqSanity( ========================================================================== */ -BOOLEAN PeerAssocRspSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *pCapabilityInfo, - OUT USHORT *pStatus, - OUT USHORT *pAid, - OUT UCHAR SupRate[], - OUT UCHAR *pSupRateLen, - OUT UCHAR ExtRate[], - OUT UCHAR *pExtRateLen, - OUT HT_CAPABILITY_IE *pHtCapability, - OUT ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE - OUT UCHAR *pHtCapabilityLen, - OUT UCHAR *pAddHtInfoLen, - OUT UCHAR *pNewExtChannelOffset, - OUT PEDCA_PARM pEdcaParm, - OUT UCHAR *pCkipFlag) +BOOLEAN PeerAssocRspSanity(struct rt_rtmp_adapter *pAd, void * pMsg, unsigned long MsgLen, u8 *pAddr2, u16 * pCapabilityInfo, u16 * pStatus, u16 * pAid, u8 SupRate[], u8 * pSupRateLen, u8 ExtRate[], u8 * pExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo, /* AP might use this additional ht info IE */ + u8 * pHtCapabilityLen, + u8 * pAddHtInfoLen, + u8 * pNewExtChannelOffset, + struct rt_edca_parm *pEdcaParm, u8 * pCkipFlag) { - CHAR IeType, *Ptr; - PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; - PEID_STRUCT pEid; - ULONG Length = 0; + char IeType, *Ptr; + struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) pMsg; + struct rt_eid * pEid; + unsigned long Length = 0; *pNewExtChannelOffset = 0xff; *pHtCapabilityLen = 0; *pAddHtInfoLen = 0; - COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); - Ptr = pFrame->Octet; - Length += LENGTH_802_11; - - NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2); - Length += 2; - NdisMoveMemory(pStatus, &pFrame->Octet[2], 2); - Length += 2; - *pCkipFlag = 0; - *pExtRateLen = 0; - pEdcaParm->bValid = FALSE; - - if (*pStatus != MLME_SUCCESS) - return TRUE; - - NdisMoveMemory(pAid, &pFrame->Octet[4], 2); - Length += 2; - - // Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform - *pAid = (*pAid) & 0x3fff; // AID is low 14-bit - - // -- get supported rates from payload and advance the pointer - IeType = pFrame->Octet[6]; - *pSupRateLen = pFrame->Octet[7]; - if ((IeType != IE_SUPP_RATES) || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES)) - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity fail - wrong SupportedRates IE\n")); - return FALSE; - } - else - NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen); - - Length = Length + 2 + *pSupRateLen; - - // many AP implement proprietary IEs in non-standard order, we'd better - // tolerate mis-ordered IEs to get best compatibility - pEid = (PEID_STRUCT) &pFrame->Octet[8 + (*pSupRateLen)]; - - // get variable fields from payload and advance the pointer - while ((Length + 2 + pEid->Len) <= MsgLen) - { - switch (pEid->Eid) - { - case IE_EXT_SUPP_RATES: - if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) - { - NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); - *pExtRateLen = pEid->Len; - } - break; - - case IE_HT_CAP: - case IE_HT_CAP2: - if (pEid->Len >= SIZE_HT_CAP_IE) //Note: allow extension.!! + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + Ptr = (char *)pFrame->Octet; + Length += LENGTH_802_11; + + NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2); + Length += 2; + NdisMoveMemory(pStatus, &pFrame->Octet[2], 2); + Length += 2; + *pCkipFlag = 0; + *pExtRateLen = 0; + pEdcaParm->bValid = FALSE; + + if (*pStatus != MLME_SUCCESS) + return TRUE; + + NdisMoveMemory(pAid, &pFrame->Octet[4], 2); + Length += 2; + + /* Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform */ + *pAid = (*pAid) & 0x3fff; /* AID is low 14-bit */ + + /* -- get supported rates from payload and advance the pointer */ + IeType = pFrame->Octet[6]; + *pSupRateLen = pFrame->Octet[7]; + if ((IeType != IE_SUPP_RATES) + || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES)) { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerAssocRspSanity fail - wrong SupportedRates IE\n")); + return FALSE; + } else + NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen); + + Length = Length + 2 + *pSupRateLen; + + /* many AP implement proprietary IEs in non-standard order, we'd better */ + /* tolerate mis-ordered IEs to get best compatibility */ + pEid = (struct rt_eid *) & pFrame->Octet[8 + (*pSupRateLen)]; + + /* get variable fields from payload and advance the pointer */ + while ((Length + 2 + pEid->Len) <= MsgLen) { + switch (pEid->Eid) { + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) { + NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); + *pExtRateLen = pEid->Len; + } + break; + + case IE_HT_CAP: + case IE_HT_CAP2: + if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension! */ { - NdisMoveMemory(pHtCapability, pEid->Octet, SIZE_HT_CAP_IE); + NdisMoveMemory(pHtCapability, pEid->Octet, + SIZE_HT_CAP_IE); - *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); - *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + *(u16 *) (&pHtCapability->HtCapInfo) = + cpu2le16(*(u16 *) + (&pHtCapability->HtCapInfo)); + *(u16 *) (&pHtCapability->ExtHtCapInfo) = + cpu2le16(*(u16 *) + (&pHtCapability->ExtHtCapInfo)); *pHtCapabilityLen = SIZE_HT_CAP_IE; + } else { + DBGPRINT(RT_DEBUG_WARN, + ("PeerAssocRspSanity - wrong IE_HT_CAP. \n")); } - else - { - DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_HT_CAP. \n")); - } - - break; - case IE_ADD_HT: - case IE_ADD_HT2: - if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) - { - // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only - // copy first sizeof(ADD_HT_INFO_IE) - NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); - *(USHORT *)(&pAddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo2)); - *(USHORT *)(&pAddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo3)); + break; + case IE_ADD_HT: + case IE_ADD_HT2: + if (pEid->Len >= sizeof(struct rt_add_ht_info_ie)) { + /* This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only */ + /* copy first sizeof(struct rt_add_ht_info_ie) */ + NdisMoveMemory(pAddHtInfo, pEid->Octet, + sizeof(struct rt_add_ht_info_ie)); + + *(u16 *) (&pAddHtInfo->AddHtInfo2) = + cpu2le16(*(u16 *) + (&pAddHtInfo->AddHtInfo2)); + *(u16 *) (&pAddHtInfo->AddHtInfo3) = + cpu2le16(*(u16 *) + (&pAddHtInfo->AddHtInfo3)); *pAddHtInfoLen = SIZE_ADD_HT_INFO_IE; - } - else - { - DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_ADD_HT. \n")); + } else { + DBGPRINT(RT_DEBUG_WARN, + ("PeerAssocRspSanity - wrong IE_ADD_HT. \n")); } - break; - case IE_SECONDARY_CH_OFFSET: - if (pEid->Len == 1) - { + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) { *pNewExtChannelOffset = pEid->Octet[0]; + } else { + DBGPRINT(RT_DEBUG_WARN, + ("PeerAssocRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); } - else - { - DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); + break; + + case IE_VENDOR_SPECIFIC: + /* handle WME PARAMTER ELEMENT */ + if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) + && (pEid->Len == 24)) { + u8 *ptr; + int i; + + /* parsing EDCA parameters */ + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10; */ + pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20; */ + pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40; */ + /*pEdcaParm->bMoreDataAck = FALSE; // pEid->Octet[0] & 0x80; */ + pEdcaParm->EdcaUpdateCount = + pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = + (pEid->Octet[6] & 0x80) ? 1 : 0; + ptr = (u8 *)& pEid->Octet[8]; + for (i = 0; i < 4; i++) { + u8 aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX */ + pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM */ + pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN */ + pEdcaParm->Cwmin[aci] = *(ptr + 1) & 0x0f; /* b0~4 is Cwmin */ + pEdcaParm->Cwmax[aci] = *(ptr + 1) >> 4; /* b5~8 is Cwmax */ + pEdcaParm->Txop[aci] = *(ptr + 2) + 256 * (*(ptr + 3)); /* in unit of 32-us */ + ptr += 4; /* point to next AC */ + } } - break; - case IE_AIRONET_CKIP: - // 0. Check Aironet IE length, it must be larger or equal to 28 - // Cisco's AP VxWork version(will not be supported) used this IE length as 28 - // Cisco's AP IOS version used this IE length as 30 - if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) - break; - - // 1. Copy CKIP flag byte to buffer for process - *pCkipFlag = *(pEid->Octet + 8); - break; - - case IE_AIRONET_IPADDRESS: - if (pEid->Len != 0x0A) - break; - - // Get Cisco Aironet IP information - if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) - NdisMoveMemory(pAd->StaCfg.AironetIPAddress, pEid->Octet + 4, 4); - break; - - // CCX2, WMM use the same IE value - // case IE_CCX_V2: - case IE_VENDOR_SPECIFIC: - // handle WME PARAMTER ELEMENT - if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) - { - PUCHAR ptr; - int i; - - // parsing EDCA parameters - pEdcaParm->bValid = TRUE; - pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10; - pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20; - pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40; - //pEdcaParm->bMoreDataAck = FALSE; // pEid->Octet[0] & 0x80; - pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; - pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; - ptr = &pEid->Octet[8]; - for (i=0; i<4; i++) - { - UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX - pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); // b5 is ACM - pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; // b0~3 is AIFSN - pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; // b0~4 is Cwmin - pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; // b5~8 is Cwmax - pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us - ptr += 4; // point to next AC - } - } - - // handle CCX IE - else - { - // 0. Check the size and CCX admin control - if (pAd->StaCfg.CCXControl.field.Enable == 0) - break; - if (pEid->Len != 5) - break; - - // Turn CCX2 if matched - if (NdisEqualMemory(pEid->Octet, Ccx2IeInfo, 5) == 1) - pAd->StaCfg.CCXEnable = TRUE; - break; - } - break; - - default: - DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity - ignore unrecognized EID = %d\n", pEid->Eid)); - break; - } - - Length = Length + 2 + pEid->Len; - pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); - } - - // Force CCX2 enable to TRUE for those AP didn't replay CCX v2 IE, we still force it to be on - if (pAd->StaCfg.CCXControl.field.Enable == 1) - pAd->StaCfg.CCXEnable = TRUE; - - return TRUE; + break; + default: + DBGPRINT(RT_DEBUG_TRACE, + ("PeerAssocRspSanity - ignore unrecognized EID = %d\n", + pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (struct rt_eid *) ((u8 *) pEid + 2 + pEid->Len); + } + + return TRUE; } /* @@ -306,47 +254,46 @@ BOOLEAN PeerAssocRspSanity( ========================================================================== */ -BOOLEAN PeerProbeReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT CHAR Ssid[], - OUT UCHAR *pSsidLen) +BOOLEAN PeerProbeReqSanity(struct rt_rtmp_adapter *pAd, + void * Msg, + unsigned long MsgLen, + u8 *pAddr2, + char Ssid[], u8 * pSsidLen) { - UCHAR Idx; - UCHAR RateLen; - CHAR IeType; - PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; - - COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); - - if ((pFrame->Octet[0] != IE_SSID) || (pFrame->Octet[1] > MAX_LEN_OF_SSID)) - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SSID IE(Type=%d,Len=%d)\n",pFrame->Octet[0],pFrame->Octet[1])); - return FALSE; - } - - *pSsidLen = pFrame->Octet[1]; - NdisMoveMemory(Ssid, &pFrame->Octet[2], *pSsidLen); - - Idx = *pSsidLen + 2; - - // -- get supported rates from payload and advance the pointer - IeType = pFrame->Octet[Idx]; - RateLen = pFrame->Octet[Idx + 1]; - if (IeType != IE_SUPP_RATES) - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SupportRates IE(Type=%d,Len=%d)\n",pFrame->Octet[Idx],pFrame->Octet[Idx+1])); - return FALSE; - } - else - { - if ((pAd->CommonCfg.PhyMode == PHY_11G) && (RateLen < 8)) - return (FALSE); - } - - return TRUE; + u8 Idx; + u8 RateLen; + char IeType; + struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg; + + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + + if ((pFrame->Octet[0] != IE_SSID) + || (pFrame->Octet[1] > MAX_LEN_OF_SSID)) { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerProbeReqSanity fail - wrong SSID IE(Type=%d,Len=%d)\n", + pFrame->Octet[0], pFrame->Octet[1])); + return FALSE; + } + + *pSsidLen = pFrame->Octet[1]; + NdisMoveMemory(Ssid, &pFrame->Octet[2], *pSsidLen); + + Idx = *pSsidLen + 2; + + /* -- get supported rates from payload and advance the pointer */ + IeType = pFrame->Octet[Idx]; + RateLen = pFrame->Octet[Idx + 1]; + if (IeType != IE_SUPP_RATES) { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerProbeReqSanity fail - wrong SupportRates IE(Type=%d,Len=%d)\n", + pFrame->Octet[Idx], pFrame->Octet[Idx + 1])); + return FALSE; + } else { + if ((pAd->CommonCfg.PhyMode == PHY_11G) && (RateLen < 8)) + return (FALSE); + } + + return TRUE; } /* @@ -357,62 +304,58 @@ BOOLEAN PeerProbeReqSanity( ========================================================================== */ -BOOLEAN GetTimBit( - IN CHAR *Ptr, - IN USHORT Aid, - OUT UCHAR *TimLen, - OUT UCHAR *BcastFlag, - OUT UCHAR *DtimCount, - OUT UCHAR *DtimPeriod, - OUT UCHAR *MessageToMe) +BOOLEAN GetTimBit(char * Ptr, + u16 Aid, + u8 * TimLen, + u8 * BcastFlag, + u8 * DtimCount, + u8 * DtimPeriod, u8 * MessageToMe) { - UCHAR BitCntl, N1, N2, MyByte, MyBit; - CHAR *IdxPtr; + u8 BitCntl, N1, N2, MyByte, MyBit; + char *IdxPtr; - IdxPtr = Ptr; + IdxPtr = Ptr; - IdxPtr ++; - *TimLen = *IdxPtr; + IdxPtr++; + *TimLen = *IdxPtr; - // get DTIM Count from TIM element - IdxPtr ++; - *DtimCount = *IdxPtr; + /* get DTIM Count from TIM element */ + IdxPtr++; + *DtimCount = *IdxPtr; - // get DTIM Period from TIM element - IdxPtr++; - *DtimPeriod = *IdxPtr; + /* get DTIM Period from TIM element */ + IdxPtr++; + *DtimPeriod = *IdxPtr; - // get Bitmap Control from TIM element - IdxPtr++; - BitCntl = *IdxPtr; + /* get Bitmap Control from TIM element */ + IdxPtr++; + BitCntl = *IdxPtr; - if ((*DtimCount == 0) && (BitCntl & 0x01)) - *BcastFlag = TRUE; - else - *BcastFlag = FALSE; + if ((*DtimCount == 0) && (BitCntl & 0x01)) + *BcastFlag = TRUE; + else + *BcastFlag = FALSE; - // Parse Partial Virtual Bitmap from TIM element - N1 = BitCntl & 0xfe; // N1 is the first bitmap byte# - N2 = *TimLen - 4 + N1; // N2 is the last bitmap byte# + /* Parse Partial Virtual Bitmap from TIM element */ + N1 = BitCntl & 0xfe; /* N1 is the first bitmap byte# */ + N2 = *TimLen - 4 + N1; /* N2 is the last bitmap byte# */ - if ((Aid < (N1 << 3)) || (Aid >= ((N2 + 1) << 3))) - *MessageToMe = FALSE; - else - { - MyByte = (Aid >> 3) - N1; // my byte position in the bitmap byte-stream - MyBit = Aid % 16 - ((MyByte & 0x01)? 8:0); + if ((Aid < (N1 << 3)) || (Aid >= ((N2 + 1) << 3))) + *MessageToMe = FALSE; + else { + MyByte = (Aid >> 3) - N1; /* my byte position in the bitmap byte-stream */ + MyBit = Aid % 16 - ((MyByte & 0x01) ? 8 : 0); - IdxPtr += (MyByte + 1); + IdxPtr += (MyByte + 1); - //if (*IdxPtr) - // DBGPRINT(RT_DEBUG_WARN, ("TIM bitmap = 0x%02x\n", *IdxPtr)); + /*if (*IdxPtr) */ + /* DBGPRINT(RT_DEBUG_WARN, ("TIM bitmap = 0x%02x\n", *IdxPtr)); */ - if (*IdxPtr & (0x01 << MyBit)) - *MessageToMe = TRUE; - else - *MessageToMe = FALSE; - } + if (*IdxPtr & (0x01 << MyBit)) + *MessageToMe = TRUE; + else + *MessageToMe = FALSE; + } - return TRUE; + return TRUE; } - diff --git a/drivers/staging/rt2860/sta/sync.c b/drivers/staging/rt2860/sta/sync.c index a6e4362fc5cc19e069857bc20cbcceddfda006c8..cbe90a6496d2c9f5c38db06aafa3edc9d706ee6e 100644 --- a/drivers/staging/rt2860/sta/sync.c +++ b/drivers/staging/rt2860/sta/sync.c @@ -37,45 +37,7 @@ */ #include "../rt_config.h" -#ifdef RT2860 -#define AC0_DEF_TXOP 0 -#define AC1_DEF_TXOP 0 -#define AC2_DEF_TXOP 94 -#define AC3_DEF_TXOP 47 - -VOID AdhocTurnOnQos( - IN PRTMP_ADAPTER pAd) -{ - // Turn on QOs if use HT rate. - if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) - { - pAd->CommonCfg.APEdcaParm.bValid = TRUE; - pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; - pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; - pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; - pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; - - pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; - pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; - pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; - pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; - - pAd->CommonCfg.APEdcaParm.Cwmax[0] = 10; - pAd->CommonCfg.APEdcaParm.Cwmax[1] = 6; - pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; - pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; - - pAd->CommonCfg.APEdcaParm.Txop[0] = 0; - pAd->CommonCfg.APEdcaParm.Txop[1] = 0; - pAd->CommonCfg.APEdcaParm.Txop[2] = AC2_DEF_TXOP; - pAd->CommonCfg.APEdcaParm.Txop[3] = AC3_DEF_TXOP; - } - AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); -} -#endif /* RT2860 */ -#ifdef RT2870 -#define ADHOC_ENTRY_BEACON_LOST_TIME (2*OS_HZ) // 2 sec -#endif +#define ADHOC_ENTRY_BEACON_LOST_TIME (2*OS_HZ) /* 2 sec */ /* ========================================================================== @@ -88,38 +50,56 @@ VOID AdhocTurnOnQos( ========================================================================== */ -VOID SyncStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *Sm, - OUT STATE_MACHINE_FUNC Trans[]) +void SyncStateMachineInit(struct rt_rtmp_adapter *pAd, + struct rt_state_machine *Sm, OUT STATE_MACHINE_FUNC Trans[]) { - StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, SYNC_IDLE, SYNC_MACHINE_BASE); - - // column 1 - StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction); - StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction); - StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)MlmeStartReqAction); - StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon); - StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)PeerProbeReqAction); - - //column 2 - StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan); - StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin); - StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart); - StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtJoinAction); - StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, (STATE_MACHINE_FUNC)BeaconTimeoutAtJoinAction); - - // column 3 - StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan); - StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin); - StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart); - StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction); - StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction); - StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)ScanTimeoutAction); - - // timer init - RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE); - RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE); + StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, + (STATE_MACHINE_FUNC) Drop, SYNC_IDLE, + SYNC_MACHINE_BASE); + + /* column 1 */ + StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, + (STATE_MACHINE_FUNC) MlmeScanReqAction); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, + (STATE_MACHINE_FUNC) MlmeJoinReqAction); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, + (STATE_MACHINE_FUNC) MlmeStartReqAction); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, + (STATE_MACHINE_FUNC) PeerBeacon); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, + (STATE_MACHINE_FUNC) PeerProbeReqAction); + + /*column 2 */ + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenScan); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenJoin); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenStart); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, + (STATE_MACHINE_FUNC) PeerBeaconAtJoinAction); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, + (STATE_MACHINE_FUNC) BeaconTimeoutAtJoinAction); + + /* column 3 */ + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenScan); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenJoin); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, + (STATE_MACHINE_FUNC) InvalidStateWhenStart); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, + (STATE_MACHINE_FUNC) PeerBeaconAtScanAction); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, + (STATE_MACHINE_FUNC) PeerBeaconAtScanAction); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, + (STATE_MACHINE_FUNC) ScanTimeoutAction); + + /* timer init */ + RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, + GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, + GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE); } /* @@ -131,36 +111,35 @@ VOID SyncStateMachineInit( ========================================================================== */ -VOID BeaconTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) +void BeaconTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) { - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; - DBGPRINT(RT_DEBUG_TRACE,("SYNC - BeaconTimeout\n")); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeout\n")); - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) return; if ((pAd->CommonCfg.BBPCurrentBW == BW_40) - ) - { - UCHAR BBPValue = 0; + ) { + u8 BBPValue = 0; AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); BBPValue &= (~0x18); BBPValue |= 0x10; RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n", + pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); } MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL); - RT28XX_MLME_HANDLER(pAd); + RTMP_MLME_HANDLER(pAd); } /* @@ -172,32 +151,28 @@ VOID BeaconTimeout( ========================================================================== */ -VOID ScanTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) +void ScanTimeout(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) { - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt + /* Do nothing if the driver is starting halt state. */ + /* This might happen when timer already been fired before cancel timer with mlmehalt */ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) return; - if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL)) - { - RT28XX_MLME_HANDLER(pAd); - } - else - { - // To prevent SyncMachine.CurrState is SCAN_LISTEN forever. + if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL)) { + RTMP_MLME_HANDLER(pAd); + } else { + /* To prevent SyncMachine.CurrState is SCAN_LISTEN forever. */ pAd->MlmeAux.Channel = 0; ScanNextChannel(pAd); - if (pAd->CommonCfg.bWirelessEvent) - { - RTMPSendWirelessEvent(pAd, IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + if (pAd->CommonCfg.bWirelessEvent) { + RTMPSendWirelessEvent(pAd, + IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, + pAd->MacTab.Content[BSSID_WCID]. + Addr, BSS0, 0); } } } @@ -208,81 +183,78 @@ VOID ScanTimeout( MLME SCAN req state machine procedure ========================================================================== */ -VOID MlmeScanReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void MlmeScanReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0; - BOOLEAN TimerCancelled; - ULONG Now; - USHORT Status; - PHEADER_802_11 pHdr80211; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - - // Check the total scan tries for one single OID command - // If this is the CCX 2.0 Case, skip that! - if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) - { - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n")); + u8 Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0; + BOOLEAN TimerCancelled; + unsigned long Now; + u16 Status; + struct rt_header_802_11 * pHdr80211; + u8 *pOutBuffer = NULL; + int NStatus; + + /* Check the total scan tries for one single OID command */ + /* If this is the CCX 2.0 Case, skip that! */ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) { + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - MlmeScanReqAction before Startup\n")); return; } - - // Increase the scan retry counters. + /* Increase the scan retry counters. */ pAd->StaCfg.ScanCnt++; -#ifdef RT2860 - if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) && - (IDLE_ON(pAd)) && - (pAd->StaCfg.bRadio == TRUE) && - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) - { - RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); +#ifdef RTMP_MAC_PCI + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) && + (IDLE_ON(pAd)) && + (pAd->StaCfg.bRadio == TRUE) && + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) { + if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) { + AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, + 0x02); + AsicCheckCommanOk(pAd, PowerWakeCID); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + DBGPRINT(RT_DEBUG_TRACE, + ("PSM - Issue Wake up command \n")); + } else { + RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); + } } -#endif +#endif /* RTMP_MAC_PCI // */ - // first check the parameter sanity + /* first check the parameter sanity */ if (MlmeScanReqSanity(pAd, - Elem->Msg, - Elem->MsgLen, - &BssType, - Ssid, - &SsidLen, - &ScanType)) - { - - // Check for channel load and noise hist request - // Suspend MSDU only at scan request, not the last two mentioned - if ((ScanType == SCAN_CISCO_NOISE) || (ScanType == SCAN_CISCO_CHANNEL_LOAD)) - { - if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) - RTMPSuspendMsduTransmission(pAd); // Suspend MSDU transmission here - } - else - { - // Suspend MSDU transmission here - RTMPSuspendMsduTransmission(pAd); - } - - // - // To prevent data lost. - // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. - // And should send an NULL data with turned PSM bit off to AP, when scan progress done - // - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) - { - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); - if (NStatus == NDIS_STATUS_SUCCESS) - { - pHdr80211 = (PHEADER_802_11) pOutBuffer; - MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); + Elem->Msg, + Elem->MsgLen, + &BssType, (char *)Ssid, &SsidLen, &ScanType)) { + + /* Check for channel load and noise hist request */ + /* Suspend MSDU only at scan request, not the last two mentioned */ + /* Suspend MSDU transmission here */ + RTMPSuspendMsduTransmission(pAd); + + /* */ + /* To prevent data lost. */ + /* Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. */ + /* And should send an NULL data with turned PSM bit off to AP, when scan progress done */ + /* */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + && (INFRA_ON(pAd))) { + NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); + if (NStatus == NDIS_STATUS_SUCCESS) { + pHdr80211 = (struct rt_header_802_11 *) pOutBuffer; + MgtMacHeaderInit(pAd, pHdr80211, + SUBTYPE_NULL_FUNC, 1, + pAd->CommonCfg.Bssid, + pAd->CommonCfg.Bssid); pHdr80211->Duration = 0; pHdr80211->FC.Type = BTYPE_DATA; pHdr80211->FC.PwrMgmt = PWR_SAVE; - // Send using priority queue - MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); - DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n")); + /* Send using priority queue */ + MiniportMMRequest(pAd, 0, pOutBuffer, + sizeof(struct rt_header_802_11)); + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n")); MlmeFreeMemory(pAd, pOutBuffer); RTMPusecDelay(5000); } @@ -290,38 +262,32 @@ VOID MlmeScanReqAction( NdisGetSystemUpTime(&Now); pAd->StaCfg.LastScanTime = Now; - // reset all the timers + /* reset all the timers */ RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); - // record desired BSS parameters + /* record desired BSS parameters */ pAd->MlmeAux.BssType = BssType; pAd->MlmeAux.ScanType = ScanType; pAd->MlmeAux.SsidLen = SsidLen; - NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); - // start from the first channel + /* start from the first channel */ pAd->MlmeAux.Channel = FirstChannel(pAd); - // Change the scan channel when dealing with CCX beacon report - if ((ScanType == SCAN_CISCO_PASSIVE) || (ScanType == SCAN_CISCO_ACTIVE) || - (ScanType == SCAN_CISCO_CHANNEL_LOAD) || (ScanType == SCAN_CISCO_NOISE)) - pAd->MlmeAux.Channel = pAd->StaCfg.CCXScanChannel; - - // Let BBP register at 20MHz to do scan + /* Let BBP register at 20MHz to do scan */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); BBPValue &= (~0x18); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); ScanNextChannel(pAd); - } - else - { + } else { DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n")); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_INVALID_FORMAT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, + &Status); } } @@ -331,49 +297,47 @@ VOID MlmeScanReqAction( MLME JOIN req state machine procedure ========================================================================== */ -VOID MlmeJoinReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void MlmeJoinReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR BBPValue = 0; - BSS_ENTRY *pBss; - BOOLEAN TimerCancelled; - HEADER_802_11 Hdr80211; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - PUCHAR pOutBuffer = NULL; - PUCHAR pSupRate = NULL; - UCHAR SupRateLen; - PUCHAR pExtRate = NULL; - UCHAR ExtRateLen; - UCHAR ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C}; - UCHAR ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR); - MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg); - - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx)); - -#ifdef RT2860 - if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) && - (IDLE_ON(pAd)) && - (pAd->StaCfg.bRadio == TRUE) && - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) - { + u8 BBPValue = 0; + struct rt_bss_entry *pBss; + BOOLEAN TimerCancelled; + struct rt_header_802_11 Hdr80211; + int NStatus; + unsigned long FrameLen = 0; + u8 *pOutBuffer = NULL; + u8 *pSupRate = NULL; + u8 SupRateLen; + u8 *pExtRate = NULL; + u8 ExtRateLen; + u8 ASupRate[] = { 0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C }; + u8 ASupRateLen = sizeof(ASupRate) / sizeof(u8); + struct rt_mlme_join_req *pInfo = (struct rt_mlme_join_req *)(Elem->Msg); + + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx)); + +#ifdef RTMP_MAC_PCI + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) && + (IDLE_ON(pAd)) && + (pAd->StaCfg.bRadio == TRUE) && + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) { RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); } -#endif +#endif /* RTMP_MAC_PCI // */ - // reset all the timers + /* reset all the timers */ RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx]; - // record the desired SSID & BSSID we're waiting for + /* record the desired SSID & BSSID we're waiting for */ COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid); - // If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again. - if (pBss->Hidden == 0) - { + /* If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again. */ + if (pBss->Hidden == 0) { + RTMPZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen); pAd->MlmeAux.SsidLen = pBss->SsidLen; } @@ -382,88 +346,87 @@ VOID MlmeJoinReqAction( pAd->MlmeAux.Channel = pBss->Channel; pAd->MlmeAux.CentralChannel = pBss->CentralChannel; - // Let BBP register at 20MHz to do scan + /* Let BBP register at 20MHz to do scan */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); BBPValue &= (~0x18); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); - // switch channel and waiting for beacon timer + /* switch channel and waiting for beacon timer */ AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); AsicLockChannel(pAd, pAd->MlmeAux.Channel); RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT); - do - { + do { if (((pAd->CommonCfg.bIEEE80211H == 1) && - (pAd->MlmeAux.Channel > 14) && - RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) - ) - { - // - // We can't send any Probe request frame to meet 802.11h. - // + (pAd->MlmeAux.Channel > 14) && + RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) + ) { + /* */ + /* We can't send any Probe request frame to meet 802.11h. */ + /* */ if (pBss->Hidden == 0) break; } - - // - // send probe request - // + /* */ + /* send probe request */ + /* */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); - if (NStatus == NDIS_STATUS_SUCCESS) - { - if (pAd->MlmeAux.Channel <= 14) - { + if (NStatus == NDIS_STATUS_SUCCESS) { + if (pAd->MlmeAux.Channel <= 14) { pSupRate = pAd->CommonCfg.SupRate; SupRateLen = pAd->CommonCfg.SupRateLen; pExtRate = pAd->CommonCfg.ExtRate; ExtRateLen = pAd->CommonCfg.ExtRateLen; - } - else - { - // - // Overwrite Support Rate, CCK rate are not allowed - // + } else { + /* */ + /* Overwrite Support Rate, CCK rate are not allowed */ + /* */ pSupRate = ASupRate; SupRateLen = ASupRateLen; ExtRateLen = 0; } if (pAd->MlmeAux.BssType == BSS_INFRA) - MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, pAd->MlmeAux.Bssid); + MgtMacHeaderInit(pAd, &Hdr80211, + SUBTYPE_PROBE_REQ, 0, + pAd->MlmeAux.Bssid, + pAd->MlmeAux.Bssid); else - MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &Hdr80211, - 1, &SsidIe, - 1, &pAd->MlmeAux.SsidLen, - pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, - 1, &SupRateIe, - 1, &SupRateLen, - SupRateLen, pSupRate, - END_OF_ARGS); - - if (ExtRateLen) - { - ULONG Tmp; - MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, - 1, &ExtRateIe, - 1, &ExtRateLen, - ExtRateLen, pExtRate, - END_OF_ARGS); + MgtMacHeaderInit(pAd, &Hdr80211, + SUBTYPE_PROBE_REQ, 0, + BROADCAST_ADDR, + BROADCAST_ADDR); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(struct rt_header_802_11), &Hdr80211, + 1, &SsidIe, + 1, &pAd->MlmeAux.SsidLen, + pAd->MlmeAux.SsidLen, + pAd->MlmeAux.Ssid, 1, &SupRateIe, 1, + &SupRateLen, SupRateLen, pSupRate, + END_OF_ARGS); + + if (ExtRateLen) { + unsigned long Tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &ExtRateIe, + 1, &ExtRateLen, + ExtRateLen, pExtRate, + END_OF_ARGS); FrameLen += Tmp; } - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } - } while (FALSE); + } while (FALSE); - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n", - pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n", + pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], + pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON; } @@ -474,95 +437,110 @@ VOID MlmeJoinReqAction( MLME START Request state machine procedure, starting an IBSS ========================================================================== */ -VOID MlmeStartReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void MlmeStartReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen; - BOOLEAN TimerCancelled; + u8 Ssid[MAX_LEN_OF_SSID], SsidLen; + BOOLEAN TimerCancelled; - // New for WPA security suites - UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 - NDIS_802_11_VARIABLE_IEs *pVIE = NULL; - LARGE_INTEGER TimeStamp; + /* New for WPA security suites */ + u8 VarIE[MAX_VIE_LEN]; /* Total VIE length = MAX_VIE_LEN - -5 */ + struct rt_ndis_802_11_variable_ies *pVIE = NULL; + LARGE_INTEGER TimeStamp; BOOLEAN Privacy; - USHORT Status; + u16 Status; - // Init Variable IE structure - pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + /* Init Variable IE structure */ + pVIE = (struct rt_ndis_802_11_variable_ies *)VarIE; pVIE->Length = 0; - TimeStamp.u.LowPart = 0; + TimeStamp.u.LowPart = 0; TimeStamp.u.HighPart = 0; - if (MlmeStartReqSanity(pAd, Elem->Msg, Elem->MsgLen, Ssid, &SsidLen)) - { - // reset all the timers + if (MlmeStartReqSanity + (pAd, Elem->Msg, Elem->MsgLen, (char *)Ssid, &SsidLen)) { + /* reset all the timers */ RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); - // - // Start a new IBSS. All IBSS parameters are decided now.... - // - DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n")); - pAd->MlmeAux.BssType = BSS_ADHOC; + /* */ + /* Start a new IBSS. All IBSS parameters are decided now.... */ + /* */ + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n")); + pAd->MlmeAux.BssType = BSS_ADHOC; NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); - pAd->MlmeAux.SsidLen = SsidLen; + pAd->MlmeAux.SsidLen = SsidLen; - // generate a radom number as BSSID + /* generate a radom number as BSSID */ MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid); - DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - generate a radom number as BSSID \n")); - - Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || - (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || - (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); - pAd->MlmeAux.CapabilityInfo = CAP_GENERATE(0,1,Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 1, 0); - pAd->MlmeAux.BeaconPeriod = pAd->CommonCfg.BeaconPeriod; - pAd->MlmeAux.AtimWin = pAd->StaCfg.AtimWin; - pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; - - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; - pAd->MlmeAux.CentralChannel = pAd->CommonCfg.CentralChannel; - - pAd->MlmeAux.SupRateLen= pAd->CommonCfg.SupRateLen; - NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); - RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); + DBGPRINT(RT_DEBUG_TRACE, + ("MlmeStartReqAction - generate a radom number as BSSID \n")); + + Privacy = + (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) + || (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) + || (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); + pAd->MlmeAux.CapabilityInfo = + CAP_GENERATE(0, 1, Privacy, + (pAd->CommonCfg.TxPreamble == + Rt802_11PreambleShort), 1, 0); + pAd->MlmeAux.BeaconPeriod = pAd->CommonCfg.BeaconPeriod; + pAd->MlmeAux.AtimWin = pAd->StaCfg.AtimWin; + pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; + + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + pAd->MlmeAux.CentralChannel = pAd->CommonCfg.CentralChannel; + + pAd->MlmeAux.SupRateLen = pAd->CommonCfg.SupRateLen; + NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, + MAX_LEN_OF_SUPPORTED_RATES); + RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, + &pAd->MlmeAux.SupRateLen); pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen; - NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES); - RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); - - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) - { - RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0], &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo); - pAd->MlmeAux.HtCapabilityLen = sizeof(HT_CAPABILITY_IE); - // Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here. - DBGPRINT(RT_DEBUG_TRACE, ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n")); - } - else - { + NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, + MAX_LEN_OF_SUPPORTED_RATES); + RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, + &pAd->MlmeAux.ExtRateLen); + + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) { + RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, + &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0], + &pAd->MlmeAux.HtCapability, + &pAd->MlmeAux.AddHtInfo); + pAd->MlmeAux.HtCapabilityLen = sizeof(struct rt_ht_capability_ie); + /* Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here. */ + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n")); + } else { pAd->MlmeAux.HtCapabilityLen = 0; pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo. + MCSSet[0], 16); } - // temporarily not support QOS in IBSS - NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM)); - NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); - NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); + /* temporarily not support QOS in IBSS */ + NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(struct rt_edca_parm)); + NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, + sizeof(struct rt_qbss_load_parm)); + NdisZeroMemory(&pAd->MlmeAux.APQosCapability, + sizeof(struct rt_qos_capability_parm)); AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); AsicLockChannel(pAd, pAd->MlmeAux.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n", - pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen)); + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n", + pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.ExtRateLen)); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_SUCCESS; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); - } - else - { + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, + &Status); + } else { DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n")); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_INVALID_FORMAT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, + &Status); } } @@ -572,126 +550,116 @@ VOID MlmeStartReqAction( peer sends beacon back when scanning ========================================================================== */ -VOID PeerBeaconAtScanAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void PeerBeaconAtScanAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; - UCHAR Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel, - SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe; - CF_PARM CfParm; - USHORT BeaconPeriod, AtimWin, CapabilityInfo; - PFRAME_802_11 pFrame; - LARGE_INTEGER TimeStamp; - UCHAR Erp; - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen, ExtRateLen; - USHORT LenVIE; - UCHAR CkipFlag; - UCHAR AironetCellPowerLimit; - EDCA_PARM EdcaParm; - QBSS_LOAD_PARM QbssLoad; - QOS_CAPABILITY_PARM QosCapability; - ULONG RalinkIe; - UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 - NDIS_802_11_VARIABLE_IEs *pVIE = NULL; - HT_CAPABILITY_IE HtCapability; - ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE - UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0; - UCHAR AddHtInfoLen; - UCHAR NewExtChannelOffset = 0xff; - - pFrame = (PFRAME_802_11) Elem->Msg; - // Init Variable IE structure - pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + u8 Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + u8 Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel, + SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe; + struct rt_cf_parm CfParm; + u16 BeaconPeriod, AtimWin, CapabilityInfo; + struct rt_frame_802_11 * pFrame; + LARGE_INTEGER TimeStamp; + u8 Erp; + u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES], + ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + u8 SupRateLen, ExtRateLen; + u16 LenVIE; + u8 CkipFlag; + u8 AironetCellPowerLimit; + struct rt_edca_parm EdcaParm; + struct rt_qbss_load_parm QbssLoad; + struct rt_qos_capability_parm QosCapability; + unsigned long RalinkIe; + u8 VarIE[MAX_VIE_LEN]; /* Total VIE length = MAX_VIE_LEN - -5 */ + struct rt_ndis_802_11_variable_ies *pVIE = NULL; + struct rt_ht_capability_ie HtCapability; + struct rt_add_ht_info_ie AddHtInfo; /* AP might use this additional ht info IE */ + u8 HtCapabilityLen = 0, PreNHtCapabilityLen = 0; + u8 AddHtInfoLen; + u8 NewExtChannelOffset = 0xff; + + /* NdisFillMemory(Ssid, MAX_LEN_OF_SSID, 0x00); */ + pFrame = (struct rt_frame_802_11 *) Elem->Msg; + /* Init Variable IE structure */ + pVIE = (struct rt_ndis_802_11_variable_ies *)VarIE; pVIE->Length = 0; - RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); - RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); + RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); + RTMPZeroMemory(&AddHtInfo, sizeof(struct rt_add_ht_info_ie)); if (PeerBeaconAndProbeRspSanity(pAd, - Elem->Msg, - Elem->MsgLen, - Elem->Channel, - Addr2, - Bssid, - Ssid, - &SsidLen, - &BssType, - &BeaconPeriod, - &Channel, - &NewChannel, - &TimeStamp, - &CfParm, - &AtimWin, - &CapabilityInfo, - &Erp, - &DtimCount, - &DtimPeriod, - &BcastFlag, - &MessageToMe, - SupRate, - &SupRateLen, - ExtRate, - &ExtRateLen, - &CkipFlag, - &AironetCellPowerLimit, - &EdcaParm, - &QbssLoad, - &QosCapability, - &RalinkIe, - &HtCapabilityLen, - &PreNHtCapabilityLen, - &HtCapability, - &AddHtInfoLen, - &AddHtInfo, - &NewExtChannelOffset, - &LenVIE, - pVIE)) - { - ULONG Idx; - CHAR Rssi = 0; + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + Addr2, + Bssid, + (char *)Ssid, + &SsidLen, + &BssType, + &BeaconPeriod, + &Channel, + &NewChannel, + &TimeStamp, + &CfParm, + &AtimWin, + &CapabilityInfo, + &Erp, + &DtimCount, + &DtimPeriod, + &BcastFlag, + &MessageToMe, + SupRate, + &SupRateLen, + ExtRate, + &ExtRateLen, + &CkipFlag, + &AironetCellPowerLimit, + &EdcaParm, + &QbssLoad, + &QosCapability, + &RalinkIe, + &HtCapabilityLen, + &PreNHtCapabilityLen, + &HtCapability, + &AddHtInfoLen, + &AddHtInfo, + &NewExtChannelOffset, &LenVIE, pVIE)) { + unsigned long Idx; + char Rssi = 0; Idx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); if (Idx != BSS_NOT_FOUND) Rssi = pAd->ScanTab.BssEntry[Idx].Rssi; - Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + Rssi = + RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) HtCapabilityLen = SIZE_HT_CAP_IE; - if ((pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) && (Channel == pAd->StaCfg.CCXScanChannel)) - { - Idx = BssTableSetEntry(pAd, &pAd->StaCfg.CCXBssTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, - &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen,ExtRate, ExtRateLen, &HtCapability, - &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag, - &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); - if (Idx != BSS_NOT_FOUND) - { - NdisMoveMemory(pAd->StaCfg.CCXBssTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4); - NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); - NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); - if (pAd->StaCfg.CCXReqType == MSRN_TYPE_BEACON_REQ) - AironetAddBeaconReport(pAd, Idx, Elem); - } - } - else - { - Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, - &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, - &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag, - &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); - - if (Idx != BSS_NOT_FOUND) - { - NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4); - NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); - NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); - } + Idx = + BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, (char *)Ssid, + SsidLen, BssType, BeaconPeriod, &CfParm, + AtimWin, CapabilityInfo, SupRate, + SupRateLen, ExtRate, ExtRateLen, + &HtCapability, &AddHtInfo, HtCapabilityLen, + AddHtInfoLen, NewExtChannelOffset, Channel, + Rssi, TimeStamp, CkipFlag, &EdcaParm, + &QosCapability, &QbssLoad, LenVIE, pVIE); + + if (Idx != BSS_NOT_FOUND) { + NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, + &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], + &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], + &Elem->TimeStamp.u.LowPart, 4); } + } - // sanity check fail, ignored + /* sanity check fail, ignored */ } /* @@ -700,134 +668,207 @@ VOID PeerBeaconAtScanAction( When waiting joining the (I)BSS, beacon received from external ========================================================================== */ -VOID PeerBeaconAtJoinAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void PeerBeaconAtJoinAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; - UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe, - DtimCount, DtimPeriod, BcastFlag, NewChannel; + u8 Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + u8 Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe, + DtimCount, DtimPeriod, BcastFlag, NewChannel; LARGE_INTEGER TimeStamp; - USHORT BeaconPeriod, AtimWin, CapabilityInfo; - CF_PARM Cf; - BOOLEAN TimerCancelled; - UCHAR Erp; - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen, ExtRateLen; - UCHAR CkipFlag; - USHORT LenVIE; - UCHAR AironetCellPowerLimit; - EDCA_PARM EdcaParm; - QBSS_LOAD_PARM QbssLoad; - QOS_CAPABILITY_PARM QosCapability; - USHORT Status; - UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 - NDIS_802_11_VARIABLE_IEs *pVIE = NULL; - ULONG RalinkIe; - ULONG Idx; - HT_CAPABILITY_IE HtCapability; - ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE - UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0; - UCHAR AddHtInfoLen; - UCHAR NewExtChannelOffset = 0xff; - UCHAR CentralChannel; - - // Init Variable IE structure - pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + u16 BeaconPeriod, AtimWin, CapabilityInfo; + struct rt_cf_parm Cf; + BOOLEAN TimerCancelled; + u8 Erp; + u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES], + ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + u8 SupRateLen, ExtRateLen; + u8 CkipFlag; + u16 LenVIE; + u8 AironetCellPowerLimit; + struct rt_edca_parm EdcaParm; + struct rt_qbss_load_parm QbssLoad; + struct rt_qos_capability_parm QosCapability; + u16 Status; + u8 VarIE[MAX_VIE_LEN]; /* Total VIE length = MAX_VIE_LEN - -5 */ + struct rt_ndis_802_11_variable_ies *pVIE = NULL; + unsigned long RalinkIe; + unsigned long Idx; + struct rt_ht_capability_ie HtCapability; + struct rt_add_ht_info_ie AddHtInfo; /* AP might use this additional ht info IE */ + u8 HtCapabilityLen = 0, PreNHtCapabilityLen = 0; + u8 AddHtInfoLen; + u8 NewExtChannelOffset = 0xff; + u8 CentralChannel; + BOOLEAN bAllowNrate = FALSE; + + /* Init Variable IE structure */ + pVIE = (struct rt_ndis_802_11_variable_ies *)VarIE; pVIE->Length = 0; - RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); - RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); - + RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); + RTMPZeroMemory(&AddHtInfo, sizeof(struct rt_add_ht_info_ie)); if (PeerBeaconAndProbeRspSanity(pAd, - Elem->Msg, - Elem->MsgLen, - Elem->Channel, - Addr2, - Bssid, - Ssid, - &SsidLen, - &BssType, - &BeaconPeriod, - &Channel, - &NewChannel, - &TimeStamp, - &Cf, - &AtimWin, - &CapabilityInfo, - &Erp, - &DtimCount, - &DtimPeriod, - &BcastFlag, - &MessageToMe, - SupRate, - &SupRateLen, - ExtRate, - &ExtRateLen, - &CkipFlag, - &AironetCellPowerLimit, - &EdcaParm, - &QbssLoad, - &QosCapability, - &RalinkIe, - &HtCapabilityLen, - &PreNHtCapabilityLen, - &HtCapability, - &AddHtInfoLen, - &AddHtInfo, - &NewExtChannelOffset, - &LenVIE, - pVIE)) - { - // Disqualify 11b only adhoc when we are in 11g only adhoc mode - if ((BssType == BSS_ADHOC) && (pAd->CommonCfg.PhyMode == PHY_11G) && ((SupRateLen+ExtRateLen)< 12)) + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + Addr2, + Bssid, + (char *)Ssid, + &SsidLen, + &BssType, + &BeaconPeriod, + &Channel, + &NewChannel, + &TimeStamp, + &Cf, + &AtimWin, + &CapabilityInfo, + &Erp, + &DtimCount, + &DtimPeriod, + &BcastFlag, + &MessageToMe, + SupRate, + &SupRateLen, + ExtRate, + &ExtRateLen, + &CkipFlag, + &AironetCellPowerLimit, + &EdcaParm, + &QbssLoad, + &QosCapability, + &RalinkIe, + &HtCapabilityLen, + &PreNHtCapabilityLen, + &HtCapability, + &AddHtInfoLen, + &AddHtInfo, + &NewExtChannelOffset, &LenVIE, pVIE)) { + /* Disqualify 11b only adhoc when we are in 11g only adhoc mode */ + if ((BssType == BSS_ADHOC) + && (pAd->CommonCfg.PhyMode == PHY_11G) + && ((SupRateLen + ExtRateLen) < 12)) return; - // BEACON from desired BSS/IBSS found. We should be able to decide most - // BSS parameters here. - // Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION? - // Do we need to receover back all parameters belonging to previous BSS? - // A. Should be not. There's no back-door recover to previous AP. It still need - // a new JOIN-AUTH-ASSOC sequence. - if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid)) - { - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", Channel)); - RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); - - // Update RSSI to prevent No signal display when cards first initialized - pAd->StaCfg.RssiSample.LastRssi0 = ConvertToRssi(pAd, Elem->Rssi0, RSSI_0); - pAd->StaCfg.RssiSample.LastRssi1 = ConvertToRssi(pAd, Elem->Rssi1, RSSI_1); - pAd->StaCfg.RssiSample.LastRssi2 = ConvertToRssi(pAd, Elem->Rssi2, RSSI_2); - pAd->StaCfg.RssiSample.AvgRssi0 = pAd->StaCfg.RssiSample.LastRssi0; - pAd->StaCfg.RssiSample.AvgRssi0X8 = pAd->StaCfg.RssiSample.AvgRssi0 << 3; - pAd->StaCfg.RssiSample.AvgRssi1 = pAd->StaCfg.RssiSample.LastRssi1; - pAd->StaCfg.RssiSample.AvgRssi1X8 = pAd->StaCfg.RssiSample.AvgRssi1 << 3; - pAd->StaCfg.RssiSample.AvgRssi2 = pAd->StaCfg.RssiSample.LastRssi2; - pAd->StaCfg.RssiSample.AvgRssi2X8 = pAd->StaCfg.RssiSample.AvgRssi2 << 3; - - // - // We need to check if SSID only set to any, then we can record the current SSID. - // Otherwise will cause hidden SSID association failed. - // - if (pAd->MlmeAux.SsidLen == 0) - { - NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); + /* BEACON from desired BSS/IBSS found. We should be able to decide most */ + /* BSS parameters here. */ + /* Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION? */ + /* Do we need to receover back all parameters belonging to previous BSS? */ + /* A. Should be not. There's no back-door recover to previous AP. It still need */ + /* a new JOIN-AUTH-ASSOC sequence. */ + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid)) { + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", + Channel)); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, + &TimerCancelled); + + /* Update RSSI to prevent No signal display when cards first initialized */ + pAd->StaCfg.RssiSample.LastRssi0 = + ConvertToRssi(pAd, Elem->Rssi0, RSSI_0); + pAd->StaCfg.RssiSample.LastRssi1 = + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1); + pAd->StaCfg.RssiSample.LastRssi2 = + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2); + pAd->StaCfg.RssiSample.AvgRssi0 = + pAd->StaCfg.RssiSample.LastRssi0; + pAd->StaCfg.RssiSample.AvgRssi0X8 = + pAd->StaCfg.RssiSample.AvgRssi0 << 3; + pAd->StaCfg.RssiSample.AvgRssi1 = + pAd->StaCfg.RssiSample.LastRssi1; + pAd->StaCfg.RssiSample.AvgRssi1X8 = + pAd->StaCfg.RssiSample.AvgRssi1 << 3; + pAd->StaCfg.RssiSample.AvgRssi2 = + pAd->StaCfg.RssiSample.LastRssi2; + pAd->StaCfg.RssiSample.AvgRssi2X8 = + pAd->StaCfg.RssiSample.AvgRssi2 << 3; + + /* */ + /* We need to check if SSID only set to any, then we can record the current SSID. */ + /* Otherwise will cause hidden SSID association failed. */ + /* */ + if (pAd->MlmeAux.SsidLen == 0) { + NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, + SsidLen); pAd->MlmeAux.SsidLen = SsidLen; - } - else - { - Idx = BssSsidTableSearch(&pAd->ScanTab, Bssid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Channel); - - if (Idx != BSS_NOT_FOUND) - { - // - // Multiple SSID case, used correct CapabilityInfo - // - CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo; + } else { + Idx = + BssSsidTableSearch(&pAd->ScanTab, Bssid, + pAd->MlmeAux.Ssid, + pAd->MlmeAux.SsidLen, + Channel); + + if (Idx == BSS_NOT_FOUND) { + char Rssi = 0; + Rssi = + RTMPMaxRssi(pAd, + ConvertToRssi(pAd, + Elem-> + Rssi0, + RSSI_0), + ConvertToRssi(pAd, + Elem-> + Rssi1, + RSSI_1), + ConvertToRssi(pAd, + Elem-> + Rssi2, + RSSI_2)); + Idx = + BssTableSetEntry(pAd, &pAd->ScanTab, + Bssid, + (char *) Ssid, + SsidLen, BssType, + BeaconPeriod, &Cf, + AtimWin, + CapabilityInfo, + SupRate, + SupRateLen, + ExtRate, + ExtRateLen, + &HtCapability, + &AddHtInfo, + HtCapabilityLen, + AddHtInfoLen, + NewExtChannelOffset, + Channel, Rssi, + TimeStamp, + CkipFlag, + &EdcaParm, + &QosCapability, + &QbssLoad, LenVIE, + pVIE); + if (Idx != BSS_NOT_FOUND) { + NdisMoveMemory(pAd->ScanTab. + BssEntry[Idx]. + PTSF, + &Elem->Msg[24], + 4); + NdisMoveMemory(&pAd->ScanTab. + BssEntry[Idx]. + TTSF[0], + &Elem->TimeStamp. + u.LowPart, 4); + NdisMoveMemory(&pAd->ScanTab. + BssEntry[Idx]. + TTSF[4], + &Elem->TimeStamp. + u.LowPart, 4); + CapabilityInfo = + pAd->ScanTab.BssEntry[Idx]. + CapabilityInfo; + } + } else { + /* */ + /* Multiple SSID case, used correct CapabilityInfo */ + /* */ + CapabilityInfo = + pAd->ScanTab.BssEntry[Idx]. + CapabilityInfo; } } NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN); - pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + pAd->MlmeAux.CapabilityInfo = + CapabilityInfo & SUPPORTED_CAPABILITY_INFO; pAd->MlmeAux.BssType = BssType; pAd->MlmeAux.BeaconPeriod = BeaconPeriod; pAd->MlmeAux.Channel = Channel; @@ -836,107 +877,159 @@ VOID PeerBeaconAtJoinAction( pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration; pAd->MlmeAux.APRalinkIe = RalinkIe; - // Copy AP's supported rate to MlmeAux for creating assoication request - // Also filter out not supported rate + /* Copy AP's supported rate to MlmeAux for creating assoication request */ + /* Also filter out not supported rate */ pAd->MlmeAux.SupRateLen = SupRateLen; - NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen); - RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); + NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, + SupRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, + &pAd->MlmeAux.SupRateLen); pAd->MlmeAux.ExtRateLen = ExtRateLen; - NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen); - RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); - - NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16); + NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, + ExtRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, + &pAd->MlmeAux.ExtRateLen); + + NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, + 16); + + if (((pAd->StaCfg.WepStatus != Ndis802_11WEPEnabled) + && (pAd->StaCfg.WepStatus != + Ndis802_11Encryption2Enabled)) + || (pAd->CommonCfg.HT_DisallowTKIP == FALSE)) { + bAllowNrate = TRUE; + } pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset; pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen; - // filter out un-supported ht rates - if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); - RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, SIZE_ADD_HT_INFO_IE); - - // StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability - NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16); - pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset; + RTMPZeroMemory(&pAd->MlmeAux.HtCapability, + SIZE_HT_CAP_IE); + /* filter out un-supported ht rates */ + if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) + && ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + && (bAllowNrate))) { + RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, + &AddHtInfo, SIZE_ADD_HT_INFO_IE); + + /* StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability */ + NdisMoveMemory(pAd->StaActive.SupportedPhyInfo. + MCSSet, HtCapability.MCSSet, 16); + pAd->MlmeAux.NewExtChannelOffset = + NewExtChannelOffset; pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE; - pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE; + pAd->StaActive.SupportedPhyInfo.bHtEnable = + TRUE; if (PreNHtCapabilityLen > 0) - pAd->StaActive.SupportedPhyInfo.bPreNHt = TRUE; - RTMPCheckHt(pAd, BSSID_WCID, &HtCapability, &AddHtInfo); - // Copy AP Parameter to StaActive. This is also in LinkUp. - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n", - pAd->StaActive.SupportedHtPhy.MpduDensity, pAd->StaActive.SupportedHtPhy.MaxRAmpduFactor, HtCapability.HtCapInfo.ChannelWidth)); - - if (AddHtInfoLen > 0) - { + pAd->StaActive.SupportedPhyInfo. + bPreNHt = TRUE; + RTMPCheckHt(pAd, BSSID_WCID, &HtCapability, + &AddHtInfo); + /* Copy AP Parameter to StaActive. This is also in LinkUp. */ + DBGPRINT(RT_DEBUG_TRACE, + ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n", + pAd->StaActive.SupportedHtPhy. + MpduDensity, + pAd->StaActive.SupportedHtPhy. + MaxRAmpduFactor, + HtCapability.HtCapInfo.ChannelWidth)); + + if (AddHtInfoLen > 0) { CentralChannel = AddHtInfo.ControlChan; - // Check again the Bandwidth capability of this AP. - if ((AddHtInfo.ControlChan > 2)&& (AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - CentralChannel = AddHtInfo.ControlChan - 2; - } - else if ((AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - CentralChannel = AddHtInfo.ControlChan + 2; - } - - // Check Error . - if (pAd->MlmeAux.CentralChannel != CentralChannel) - DBGPRINT(RT_DEBUG_ERROR, ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", CentralChannel, AddHtInfo.ControlChan, pAd->MlmeAux.CentralChannel)); - - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", CentralChannel, AddHtInfo.ControlChan)); + /* Check again the Bandwidth capability of this AP. */ + if ((AddHtInfo.ControlChan > 2) + && (AddHtInfo.AddHtInfo. + ExtChanOffset == EXTCHA_BELOW) + && (HtCapability.HtCapInfo. + ChannelWidth == BW_40)) { + CentralChannel = + AddHtInfo.ControlChan - 2; + } else + if ((AddHtInfo.AddHtInfo. + ExtChanOffset == EXTCHA_ABOVE) + && (HtCapability.HtCapInfo. + ChannelWidth == BW_40)) { + CentralChannel = + AddHtInfo.ControlChan + 2; + } + /* Check Error . */ + if (pAd->MlmeAux.CentralChannel != + CentralChannel) + DBGPRINT(RT_DEBUG_ERROR, + ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", + CentralChannel, + AddHtInfo.ControlChan, + pAd->MlmeAux. + CentralChannel)); + + DBGPRINT(RT_DEBUG_TRACE, + ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", + CentralChannel, + AddHtInfo.ControlChan)); } - } - else - { - // To prevent error, let legacy AP must have same CentralChannel and Channel. - if ((HtCapabilityLen == 0) && (PreNHtCapabilityLen == 0)) - pAd->MlmeAux.CentralChannel = pAd->MlmeAux.Channel; - - pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; - RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); - RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE); + } else { + /* To prevent error, let legacy AP must have same CentralChannel and Channel. */ + if ((HtCapabilityLen == 0) + && (PreNHtCapabilityLen == 0)) + pAd->MlmeAux.CentralChannel = + pAd->MlmeAux.Channel; + + pAd->StaActive.SupportedPhyInfo.bHtEnable = + FALSE; + pAd->MlmeAux.NewExtChannelOffset = 0xff; + RTMPZeroMemory(&pAd->MlmeAux.HtCapability, + SIZE_HT_CAP_IE); + pAd->MlmeAux.HtCapabilityLen = 0; + RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, + SIZE_ADD_HT_INFO_IE); } RTMPUpdateMlmeRate(pAd); - // copy QOS related information + /* copy QOS related information */ if ((pAd->CommonCfg.bWmmCapable) - || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) - ) - { - NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, &EdcaParm, sizeof(EDCA_PARM)); - NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM)); - NdisMoveMemory(&pAd->MlmeAux.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM)); - } - else - { - NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM)); - NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); - NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); + || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + ) { + NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, + &EdcaParm, sizeof(struct rt_edca_parm)); + NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, + &QbssLoad, + sizeof(struct rt_qbss_load_parm)); + NdisMoveMemory(&pAd->MlmeAux.APQosCapability, + &QosCapability, + sizeof(struct rt_qos_capability_parm)); + } else { + NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, + sizeof(struct rt_edca_parm)); + NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, + sizeof(struct rt_qbss_load_parm)); + NdisZeroMemory(&pAd->MlmeAux.APQosCapability, + sizeof(struct rt_qos_capability_parm)); } - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n", - pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen)); + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n", + pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.ExtRateLen)); - if (AironetCellPowerLimit != 0xFF) - { - //We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power - ChangeToCellPowerLimit(pAd, AironetCellPowerLimit); - } - else //Used the default TX Power Percentage. - pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + if (AironetCellPowerLimit != 0xFF) { + /*We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power */ + ChangeToCellPowerLimit(pAd, + AironetCellPowerLimit); + } else /*Used the default TX Power Percentage. */ + pAd->CommonCfg.TxPowerPercentage = + pAd->CommonCfg.TxPowerDefault; pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_SUCCESS; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, + 2, &Status); } - // not to me BEACON, ignored + /* not to me BEACON, ignored */ } - // sanity check fail, ignore this frame + /* sanity check fail, ignore this frame */ } /* @@ -948,662 +1041,660 @@ VOID PeerBeaconAtJoinAction( ========================================================================== */ -VOID PeerBeacon( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void PeerBeacon(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; - CHAR Ssid[MAX_LEN_OF_SSID]; - CF_PARM CfParm; - UCHAR SsidLen, MessageToMe=0, BssType, Channel, NewChannel, index=0; - UCHAR DtimCount=0, DtimPeriod=0, BcastFlag=0; - USHORT CapabilityInfo, AtimWin, BeaconPeriod; + u8 Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + char Ssid[MAX_LEN_OF_SSID]; + struct rt_cf_parm CfParm; + u8 SsidLen, MessageToMe = 0, BssType, Channel, NewChannel, index = 0; + u8 DtimCount = 0, DtimPeriod = 0, BcastFlag = 0; + u16 CapabilityInfo, AtimWin, BeaconPeriod; LARGE_INTEGER TimeStamp; - USHORT TbttNumToNextWakeUp; - UCHAR Erp; - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen, ExtRateLen; - UCHAR CkipFlag; - USHORT LenVIE; - UCHAR AironetCellPowerLimit; - EDCA_PARM EdcaParm; - QBSS_LOAD_PARM QbssLoad; - QOS_CAPABILITY_PARM QosCapability; - ULONG RalinkIe; - // New for WPA security suites - UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 - NDIS_802_11_VARIABLE_IEs *pVIE = NULL; - HT_CAPABILITY_IE HtCapability; - ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE - UCHAR HtCapabilityLen, PreNHtCapabilityLen; - UCHAR AddHtInfoLen; - UCHAR NewExtChannelOffset = 0xff; + u16 TbttNumToNextWakeUp; + u8 Erp; + u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES], + ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + u8 SupRateLen, ExtRateLen; + u8 CkipFlag; + u16 LenVIE; + u8 AironetCellPowerLimit; + struct rt_edca_parm EdcaParm; + struct rt_qbss_load_parm QbssLoad; + struct rt_qos_capability_parm QosCapability; + unsigned long RalinkIe; + /* New for WPA security suites */ + u8 VarIE[MAX_VIE_LEN]; /* Total VIE length = MAX_VIE_LEN - -5 */ + struct rt_ndis_802_11_variable_ies *pVIE = NULL; + struct rt_ht_capability_ie HtCapability; + struct rt_add_ht_info_ie AddHtInfo; /* AP might use this additional ht info IE */ + u8 HtCapabilityLen, PreNHtCapabilityLen; + u8 AddHtInfoLen; + u8 NewExtChannelOffset = 0xff; if (!(INFRA_ON(pAd) || ADHOC_ON(pAd) - )) + )) return; - // Init Variable IE structure - pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + /* Init Variable IE structure */ + pVIE = (struct rt_ndis_802_11_variable_ies *)VarIE; pVIE->Length = 0; - RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); - RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); + RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); + RTMPZeroMemory(&AddHtInfo, sizeof(struct rt_add_ht_info_ie)); if (PeerBeaconAndProbeRspSanity(pAd, - Elem->Msg, - Elem->MsgLen, - Elem->Channel, - Addr2, - Bssid, - Ssid, - &SsidLen, - &BssType, - &BeaconPeriod, - &Channel, - &NewChannel, - &TimeStamp, - &CfParm, - &AtimWin, - &CapabilityInfo, - &Erp, - &DtimCount, - &DtimPeriod, - &BcastFlag, - &MessageToMe, - SupRate, - &SupRateLen, - ExtRate, - &ExtRateLen, - &CkipFlag, - &AironetCellPowerLimit, - &EdcaParm, - &QbssLoad, - &QosCapability, - &RalinkIe, - &HtCapabilityLen, - &PreNHtCapabilityLen, - &HtCapability, - &AddHtInfoLen, - &AddHtInfo, - &NewExtChannelOffset, - &LenVIE, - pVIE)) - { + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + Addr2, + Bssid, + Ssid, + &SsidLen, + &BssType, + &BeaconPeriod, + &Channel, + &NewChannel, + &TimeStamp, + &CfParm, + &AtimWin, + &CapabilityInfo, + &Erp, + &DtimCount, + &DtimPeriod, + &BcastFlag, + &MessageToMe, + SupRate, + &SupRateLen, + ExtRate, + &ExtRateLen, + &CkipFlag, + &AironetCellPowerLimit, + &EdcaParm, + &QbssLoad, + &QosCapability, + &RalinkIe, + &HtCapabilityLen, + &PreNHtCapabilityLen, + &HtCapability, + &AddHtInfoLen, + &AddHtInfo, + &NewExtChannelOffset, &LenVIE, pVIE)) { BOOLEAN is_my_bssid, is_my_ssid; - ULONG Bssidx, Now; - BSS_ENTRY *pBss; - CHAR RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); - - is_my_bssid = MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid)? TRUE : FALSE; - is_my_ssid = SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)? TRUE:FALSE; - - - // ignore BEACON not for my SSID - if ((! is_my_ssid) && (! is_my_bssid)) + unsigned long Bssidx, Now; + struct rt_bss_entry *pBss; + char RealRssi = + RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + + is_my_bssid = + MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid) ? TRUE : FALSE; + is_my_ssid = + SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, + pAd->CommonCfg.SsidLen) ? TRUE : FALSE; + + /* ignore BEACON not for my SSID */ + if ((!is_my_ssid) && (!is_my_bssid)) return; - // It means STA waits disassoc completely from this AP, ignores this beacon. + /* It means STA waits disassoc completely from this AP, ignores this beacon. */ if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC) return; - // Copy Control channel for this BSSID. + /* Copy Control channel for this BSSID. */ if (AddHtInfoLen != 0) Channel = AddHtInfo.ControlChan; if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) HtCapabilityLen = SIZE_HT_CAP_IE; - // - // Housekeeping "SsidBssTab" table for later-on ROAMing usage. - // + /* */ + /* Housekeeping "SsidBssTab" table for later-on ROAMing usage. */ + /* */ Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); - if (Bssidx == BSS_NOT_FOUND) - { - // discover new AP of this network, create BSS entry - Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, - &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, - &HtCapability, &AddHtInfo,HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel, - RealRssi, TimeStamp, CkipFlag, &EdcaParm, &QosCapability, - &QbssLoad, LenVIE, pVIE); - if (Bssidx == BSS_NOT_FOUND) // return if BSS table full + if (Bssidx == BSS_NOT_FOUND) { + /* discover new AP of this network, create BSS entry */ + Bssidx = + BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, + SsidLen, BssType, BeaconPeriod, + &CfParm, AtimWin, CapabilityInfo, + SupRate, SupRateLen, ExtRate, + ExtRateLen, &HtCapability, + &AddHtInfo, HtCapabilityLen, + AddHtInfoLen, NewExtChannelOffset, + Channel, RealRssi, TimeStamp, + CkipFlag, &EdcaParm, + &QosCapability, &QbssLoad, LenVIE, + pVIE); + if (Bssidx == BSS_NOT_FOUND) /* return if BSS table full */ return; - NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4); - NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); - NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); - - + NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, + &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], + &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], + &Elem->TimeStamp.u.LowPart, 4); } - if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel)) - { - // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). - // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. + if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) + && (Channel != NewChannel)) { + /* Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). */ + /* In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. */ AsicSwitchChannel(pAd, 1, FALSE); AsicLockChannel(pAd, 1); - LinkDown(pAd, FALSE); + LinkDown(pAd, FALSE); MlmeQueueInit(&pAd->Mlme.Queue); BssTableInit(&pAd->ScanTab); - RTMPusecDelay(1000000); // use delay to prevent STA do reassoc - - // channel sanity check - for (index = 0 ; index < pAd->ChannelListNum; index++) - { - if (pAd->ChannelList[index].Channel == NewChannel) - { - pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel; + RTMPusecDelay(1000000); /* use delay to prevent STA do reassoc */ + + /* channel sanity check */ + for (index = 0; index < pAd->ChannelListNum; index++) { + if (pAd->ChannelList[index].Channel == + NewChannel) { + pAd->ScanTab.BssEntry[Bssidx].Channel = + NewChannel; pAd->CommonCfg.Channel = NewChannel; - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel)); + AsicSwitchChannel(pAd, + pAd->CommonCfg. + Channel, FALSE); + AsicLockChannel(pAd, + pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, + ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", + NewChannel)); break; } } - if (index >= pAd->ChannelListNum) - { + if (index >= pAd->ChannelListNum) { DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); } } - - // if the ssid matched & bssid unmatched, we should select the bssid with large value. - // This might happened when two STA start at the same time - if ((! is_my_bssid) && ADHOC_ON(pAd)) - { - INT i; - - // Add the safeguard against the mismatch of adhoc wep status - if (pAd->StaCfg.WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus) - { - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Not matched wep status %d %d\n", pAd->StaCfg.WepStatus, pAd->ScanTab.BssEntry[Bssidx].WepStatus)); - DBGPRINT(RT_DEBUG_TRACE, ("bssid=%s\n", pAd->ScanTab.BssEntry[Bssidx].Bssid)); + /* if the ssid matched & bssid unmatched, we should select the bssid with large value. */ + /* This might happened when two STA start at the same time */ + if ((!is_my_bssid) && ADHOC_ON(pAd)) { + int i; + + /* Add the safeguard against the mismatch of adhoc wep status */ + if (pAd->StaCfg.WepStatus != + pAd->ScanTab.BssEntry[Bssidx].WepStatus) { return; } - - // collapse into the ADHOC network which has bigger BSSID value. - for (i = 0; i < 6; i++) - { - if (Bssid[i] > pAd->CommonCfg.Bssid[i]) - { - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", - Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); + /* collapse into the ADHOC network which has bigger BSSID value. */ + for (i = 0; i < 6; i++) { + if (Bssid[i] > pAd->CommonCfg.Bssid[i]) { + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", + Bssid[0], Bssid[1], Bssid[2], + Bssid[3], Bssid[4], + Bssid[5])); AsicDisableSync(pAd); - COPY_MAC_ADDR(pAd->CommonCfg.Bssid, Bssid); + COPY_MAC_ADDR(pAd->CommonCfg.Bssid, + Bssid); AsicSetBssid(pAd, pAd->CommonCfg.Bssid); - MakeIbssBeacon(pAd); // re-build BEACON frame - AsicEnableIbssSync(pAd); // copy BEACON frame to on-chip memory + MakeIbssBeacon(pAd); /* re-build BEACON frame */ + AsicEnableIbssSync(pAd); /* copy BEACON frame to on-chip memory */ is_my_bssid = TRUE; break; - } - else if (Bssid[i] < pAd->CommonCfg.Bssid[i]) + } else if (Bssid[i] < pAd->CommonCfg.Bssid[i]) break; } } - NdisGetSystemUpTime(&Now); pBss = &pAd->ScanTab.BssEntry[Bssidx]; - pBss->Rssi = RealRssi; // lastest RSSI - pBss->LastBeaconRxTime = Now; // last RX timestamp + pBss->Rssi = RealRssi; /* lastest RSSI */ + pBss->LastBeaconRxTime = Now; /* last RX timestamp */ - // - // BEACON from my BSSID - either IBSS or INFRA network - // - if (is_my_bssid) - { - RXWI_STRUC RxWI; + /* */ + /* BEACON from my BSSID - either IBSS or INFRA network */ + /* */ + if (is_my_bssid) { + struct rt_rxwi RxWI; pAd->StaCfg.DtimCount = DtimCount; pAd->StaCfg.DtimPeriod = DtimPeriod; pAd->StaCfg.LastBeaconRxTime = Now; - RxWI.RSSI0 = Elem->Rssi0; RxWI.RSSI1 = Elem->Rssi1; RxWI.RSSI2 = Elem->Rssi2; Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI); - if (AironetCellPowerLimit != 0xFF) - { - // - // We get the Cisco (ccx) "TxPower Limit" required - // Changed to appropriate TxPower Limit for Ciso Compatible Extensions - // - ChangeToCellPowerLimit(pAd, AironetCellPowerLimit); + if (AironetCellPowerLimit != 0xFF) { + /* */ + /* We get the Cisco (ccx) "TxPower Limit" required */ + /* Changed to appropriate TxPower Limit for Ciso Compatible Extensions */ + /* */ + ChangeToCellPowerLimit(pAd, + AironetCellPowerLimit); + } else { + /* */ + /* AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist. */ + /* Used the default TX Power Percentage, that set from UI. */ + /* */ + pAd->CommonCfg.TxPowerPercentage = + pAd->CommonCfg.TxPowerDefault; } - else - { - // - // AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist. - // Used the default TX Power Percentage, that set from UI. - // - pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; - } - -#ifdef RT2860 - // at least one 11b peer joined. downgrade the MaxTxRate to 11Mbps - // after last 11b peer left for several seconds, we'll auto switch back to 11G rate - // in MlmePeriodicExec() -#endif - if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo))) - { -#ifdef RT2860 - BOOLEAN bRestart; - BOOLEAN bnRestart; - - bRestart = FALSE; - bnRestart = FALSE; - - do - { - if ((SupRateLen+ExtRateLen <= 4) && (pAd->CommonCfg.MaxTxRate > RATE_11)) - { - if (pAd->StaCfg.AdhocBOnlyJoined == FALSE) - { - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - 11b peer joined. down-grade to 11b TX rates \n")); - bRestart = TRUE; - NdisMoveMemory(pAd->StaActive.SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES); - pAd->StaActive.SupRateLen = SupRateLen; - NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, MAX_LEN_OF_SUPPORTED_RATES); - pAd->StaActive.ExtRateLen = ExtRateLen; - pAd->StaCfg.AdhocBOnlyJoined = TRUE; - pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; - AsicSetEdcaParm(pAd, NULL); - } - - // this timestamp is for MlmePeriodicExec() to check if all 11B peers have left - pAd->StaCfg.Last11bBeaconRxTime = Now; - break; - } - - // Update Ht Phy. - if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && - !pAd->StaCfg.AdhocBGJoined && - !pAd->StaCfg.AdhocBOnlyJoined) - AdhocTurnOnQos(pAd); - - // Handle rate switch issue when Adhoc mode - if ((SupRateLen+ExtRateLen >= 8) && (HtCapability.MCSSet[0] == 0) && (HtCapability.MCSSet[1] == 0)) - { - if (pAd->StaCfg.AdhocBGJoined == FALSE) - { - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - 11g peer joined. down-grade to 11g TX rates \n")); - bRestart = TRUE; - NdisMoveMemory(pAd->StaActive.SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES); - pAd->StaActive.SupRateLen = SupRateLen; - NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, MAX_LEN_OF_SUPPORTED_RATES); - pAd->StaActive.ExtRateLen = ExtRateLen; - pAd->StaCfg.AdhocBGJoined = TRUE; - pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; - AsicSetEdcaParm(pAd, NULL); - } - - // this timestamp is for MlmePeriodicExec() to check if all 11g peers have left - pAd->StaCfg.Last11gBeaconRxTime = Now; - break; - } - else if (!pAd->StaCfg.AdhocBGJoined && - !pAd->StaCfg.AdhocBOnlyJoined && - (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) && - (HtCapability.HtCapInfo.ChannelWidth == BW_20)) - { - if (pAd->StaCfg.Adhoc20NJoined == FALSE) - { - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; - - pAd->StaCfg.Adhoc20NJoined = TRUE; - NdisMoveMemory(&pAd->MlmeAux.HtCapability, &HtCapability, SIZE_HT_CAP_IE); - if (AddHtInfoLen != 0) - NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, AddHtInfoLen); - NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16); - - RTMPCheckHt(pAd, Elem->Wcid, &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo); - COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); - pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE; - bRestart = TRUE; - bnRestart = TRUE; - } - // this timestamp is for MlmePeriodicExec() to check if all 20MHz N peers have left - pAd->StaCfg.Last20NBeaconRxTime = Now; - } - } - else - { - RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); - RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE); - } - }while (FALSE); - - // If peer Adhoc is legacy mode, I don't need to call MlmeUpdateHtTxRates no matter I support HT or not - if ((bRestart == TRUE) && (bnRestart == FALSE)) - { - MlmeUpdateTxRates(pAd, FALSE, 0); - MakeIbssBeacon(pAd); // re-build BEACON frame - AsicEnableIbssSync(pAd); // copy to on-chip memory + if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo))) { + u8 MaxSupportedRateIn500Kbps = 0; + u8 idx; + struct rt_mac_table_entry *pEntry; + + /* supported rates array may not be sorted. sort it and find the maximum rate */ + for (idx = 0; idx < SupRateLen; idx++) { + if (MaxSupportedRateIn500Kbps < + (SupRate[idx] & 0x7f)) + MaxSupportedRateIn500Kbps = + SupRate[idx] & 0x7f; } - else if ((bRestart == TRUE) && (bnRestart == TRUE)) - { - MlmeUpdateTxRates(pAd, FALSE, BSS0); - MlmeUpdateHtTxRates(pAd, BSS0); - MakeIbssBeacon(pAd); // re-build BEACON frame - AsicEnableIbssSync(pAd); // copy to on-chip memory - } - - // At least another peer in this IBSS, declare MediaState as CONNECTED - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); - pAd->IndicateMediaState = NdisMediaStateConnected; - RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_UP; - AsicSetBssid(pAd, pAd->CommonCfg.Bssid); - - // 2003/03/12 - john - // Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that - // "site survey" result should always include the current connected network. - // - Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); - if (Bssidx == BSS_NOT_FOUND) - { - Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, - &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, - &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0, - &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); - } - DBGPRINT(RT_DEBUG_TRACE, ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n")); + for (idx = 0; idx < ExtRateLen; idx++) { + if (MaxSupportedRateIn500Kbps < + (ExtRate[idx] & 0x7f)) + MaxSupportedRateIn500Kbps = + ExtRate[idx] & 0x7f; } - // Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon. - // To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station. - if (ADHOC_ON(pAd) && (Elem->Wcid == RESERVED_WCID)) - { - UCHAR idx; - MAC_TABLE_ENTRY *pEntry; - - // look up the existing table - pEntry = MacTableLookup(pAd, Addr2); - if (pEntry == NULL) - { - // Another adhoc joining, add to our MAC table. - pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE); - if (pEntry) - { - pEntry->Sst = SST_ASSOC; - idx = pAd->StaCfg.DefaultKeyId; - // After InsertEntry, Write to ASIC on-chip table. - RT28XX_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry); - DBGPRINT(RT_DEBUG_TRACE, ("ADHOC %x:%x:%x:%x:%x:%x join in.Entry=%d\n", Addr2[0],Addr2[1],Addr2[2],Addr2[3],Addr2[4],Addr2[5], pEntry->Aid)); - - pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word; - if (HtCapabilityLen <= 0) - { - pEntry->HTPhyMode.field.STBC = 0; - pEntry->HTPhyMode.field.BW = 0; - pEntry->HTPhyMode.field.ShortGI = 0; - if ((SupRateLen+ExtRateLen <= 4) && (pAd->CommonCfg.Channel <= 14)) - { - pEntry->HTPhyMode.field.MODE = MODE_CCK; - } - else - { - pEntry->HTPhyMode.field.MODE = MODE_OFDM; - } - MlmeUpdateTxRates(pAd, FALSE, 0); - } - else - { - MlmeUpdateTxRates(pAd, FALSE, 0); - MlmeUpdateHtTxRates(pAd, BSS0); - } - - { - union iwreq_data wrqu; - wext_notify_event_assoc(pAd); - - memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); - memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); - wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); - - } - } - } - } -#endif /* RT2860 */ -#ifdef RT2870 - UCHAR MaxSupportedRateIn500Kbps = 0; - UCHAR idx; - MAC_TABLE_ENTRY *pEntry; - - // supported rates array may not be sorted. sort it and find the maximum rate - for (idx=0; idxWcid == RESERVED_WCID)) || - (pEntry && ((pEntry->LastBeaconRxTime + ADHOC_ENTRY_BEACON_LOST_TIME) < Now))) - { + /* Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon. */ + /* To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station. */ + if ((ADHOC_ON(pAd) + && (Elem->Wcid == RESERVED_WCID)) + || (pEntry + && + ((pEntry->LastBeaconRxTime + + ADHOC_ENTRY_BEACON_LOST_TIME) < + Now))) { if (pEntry == NULL) - // Another adhoc joining, add to our MAC table. - pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE); - - if (StaAddMacTableEntry(pAd, pEntry, MaxSupportedRateIn500Kbps, &HtCapability, HtCapabilityLen, CapabilityInfo) == FALSE) - { - DBGPRINT(RT_DEBUG_TRACE, ("ADHOC - Add Entry failed.\n")); + /* Another adhoc joining, add to our MAC table. */ + pEntry = + MacTableInsertEntry(pAd, + Addr2, + BSS0, + FALSE); + + if (StaAddMacTableEntry(pAd, + pEntry, + MaxSupportedRateIn500Kbps, + &HtCapability, + HtCapabilityLen, + &AddHtInfo, + AddHtInfoLen, + CapabilityInfo) + == FALSE) { + DBGPRINT(RT_DEBUG_TRACE, + ("ADHOC - Add Entry failed.\n")); return; } if (pEntry && - (Elem->Wcid == RESERVED_WCID)) - { + (Elem->Wcid == RESERVED_WCID)) { idx = pAd->StaCfg.DefaultKeyId; - RT28XX_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry); + RTMP_STA_SECURITY_INFO_ADD(pAd, + BSS0, + idx, + pEntry); } } if (pEntry && pEntry->ValidAsCLI) pEntry->LastBeaconRxTime = Now; - // At least another peer in this IBSS, declare MediaState as CONNECTED - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + /* At least another peer in this IBSS, declare MediaState as CONNECTED */ + if (!OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { + OPSTATUS_SET_FLAG(pAd, + fOP_STATUS_MEDIA_STATE_CONNECTED); - pAd->IndicateMediaState = NdisMediaStateConnected; + pAd->IndicateMediaState = + NdisMediaStateConnected; RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_UP; + pAd->ExtraInfo = GENERAL_LINK_UP; AsicSetBssid(pAd, pAd->CommonCfg.Bssid); - // 2003/03/12 - john - // Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that - // "site survey" result should always include the current connected network. - // - Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); - if (Bssidx == BSS_NOT_FOUND) - { - Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, - &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, - &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0, - &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); + /* 2003/03/12 - john */ + /* Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that */ + /* "site survey" result should always include the current connected network. */ + /* */ + Bssidx = + BssTableSearch(&pAd->ScanTab, Bssid, + Channel); + if (Bssidx == BSS_NOT_FOUND) { + Bssidx = + BssTableSetEntry(pAd, + &pAd-> + ScanTab, + Bssid, + Ssid, + SsidLen, + BssType, + BeaconPeriod, + &CfParm, + AtimWin, + CapabilityInfo, + SupRate, + SupRateLen, + ExtRate, + ExtRateLen, + &HtCapability, + &AddHtInfo, + HtCapabilityLen, + AddHtInfoLen, + NewExtChannelOffset, + Channel, + RealRssi, + TimeStamp, + 0, + &EdcaParm, + &QosCapability, + &QbssLoad, + LenVIE, + pVIE); } - DBGPRINT(RT_DEBUG_TRACE, ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n")); + DBGPRINT(RT_DEBUG_TRACE, + ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n")); } -#endif /* RT2870 */ } - if (INFRA_ON(pAd)) - { + if (INFRA_ON(pAd)) { BOOLEAN bUseShortSlot, bUseBGProtection; - // decide to use/change to - - // 1. long slot (20 us) or short slot (9 us) time - // 2. turn on/off RTS/CTS and/or CTS-to-self protection - // 3. short preamble - - //bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo); - bUseShortSlot = CAP_IS_SHORT_SLOT(CapabilityInfo); - if (bUseShortSlot != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED)) + /* decide to use/change to - */ + /* 1. long slot (20 us) or short slot (9 us) time */ + /* 2. turn on/off RTS/CTS and/or CTS-to-self protection */ + /* 3. short preamble */ + + /*bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo); */ + bUseShortSlot = + CAP_IS_SHORT_SLOT(CapabilityInfo); + if (bUseShortSlot != + OPSTATUS_TEST_FLAG(pAd, + fOP_STATUS_SHORT_SLOT_INUSED)) AsicSetSlotTime(pAd, bUseShortSlot); - bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || // always use - ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(Erp)); + bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || /* always use */ + ((pAd->CommonCfg.UseBGProtection == 0) + && ERP_IS_USE_PROTECTION(Erp)); - if (pAd->CommonCfg.Channel > 14) // always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP + if (pAd->CommonCfg.Channel > 14) /* always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP */ bUseBGProtection = FALSE; - if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + if (bUseBGProtection != + OPSTATUS_TEST_FLAG(pAd, + fOP_STATUS_BG_PROTECTION_INUSED)) { - if (bUseBGProtection) - { - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),FALSE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)); - } - else - { - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),TRUE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)); + if (bUseBGProtection) { + OPSTATUS_SET_FLAG(pAd, + fOP_STATUS_BG_PROTECTION_INUSED); + AsicUpdateProtect(pAd, + pAd->MlmeAux. + AddHtInfo. + AddHtInfo2. + OperaionMode, + (OFDMSETPROTECT + | + CCKSETPROTECT + | + ALLN_SETPROTECT), + FALSE, + (pAd->MlmeAux. + AddHtInfo. + AddHtInfo2. + NonGfPresent + == 1)); + } else { + OPSTATUS_CLEAR_FLAG(pAd, + fOP_STATUS_BG_PROTECTION_INUSED); + AsicUpdateProtect(pAd, + pAd->MlmeAux. + AddHtInfo. + AddHtInfo2. + OperaionMode, + (OFDMSETPROTECT + | + CCKSETPROTECT + | + ALLN_SETPROTECT), + TRUE, + (pAd->MlmeAux. + AddHtInfo. + AddHtInfo2. + NonGfPresent + == 1)); } - DBGPRINT(RT_DEBUG_WARN, ("SYNC - AP changed B/G protection to %d\n", bUseBGProtection)); + DBGPRINT(RT_DEBUG_WARN, + ("SYNC - AP changed B/G protection to %d\n", + bUseBGProtection)); } - - // check Ht protection mode. and adhere to the Non-GF device indication by AP. + /* check Ht protection mode. and adhere to the Non-GF device indication by AP. */ if ((AddHtInfoLen != 0) && - ((AddHtInfo.AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) || - (AddHtInfo.AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent))) - { - pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = AddHtInfo.AddHtInfo2.NonGfPresent; - pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = AddHtInfo.AddHtInfo2.OperaionMode; - if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1) - { - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE); - } - else - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); - - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP changed N OperaionMode to %d\n", pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode)); + ((AddHtInfo.AddHtInfo2.OperaionMode != + pAd->MlmeAux.AddHtInfo.AddHtInfo2. + OperaionMode) + || (AddHtInfo.AddHtInfo2.NonGfPresent != + pAd->MlmeAux.AddHtInfo.AddHtInfo2. + NonGfPresent))) { + pAd->MlmeAux.AddHtInfo.AddHtInfo2. + NonGfPresent = + AddHtInfo.AddHtInfo2.NonGfPresent; + pAd->MlmeAux.AddHtInfo.AddHtInfo2. + OperaionMode = + AddHtInfo.AddHtInfo2.OperaionMode; + if (pAd->MlmeAux.AddHtInfo.AddHtInfo2. + NonGfPresent == 1) { + AsicUpdateProtect(pAd, + pAd->MlmeAux. + AddHtInfo. + AddHtInfo2. + OperaionMode, + ALLN_SETPROTECT, + FALSE, TRUE); + } else + AsicUpdateProtect(pAd, + pAd->MlmeAux. + AddHtInfo. + AddHtInfo2. + OperaionMode, + ALLN_SETPROTECT, + FALSE, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - AP changed N OperaionMode to %d\n", + pAd->MlmeAux.AddHtInfo. + AddHtInfo2.OperaionMode)); } - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) && - ERP_IS_USE_BARKER_PREAMBLE(Erp)) - { - MlmeSetTxPreamble(pAd, Rt802_11PreambleLong); - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP forced to use LONG preamble\n")); + if (OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) + && ERP_IS_USE_BARKER_PREAMBLE(Erp)) { + MlmeSetTxPreamble(pAd, + Rt802_11PreambleLong); + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - AP forced to use long preamble\n")); } - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && - (EdcaParm.bValid == TRUE) && - (EdcaParm.EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount)) - { - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n", - pAd->CommonCfg.APEdcaParm.EdcaUpdateCount, - EdcaParm.EdcaUpdateCount)); + if (OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_WMM_INUSED) + && (EdcaParm.bValid == TRUE) + && (EdcaParm.EdcaUpdateCount != + pAd->CommonCfg.APEdcaParm. + EdcaUpdateCount)) { + DBGPRINT(RT_DEBUG_TRACE, + ("SYNC - AP change EDCA parameters(from %d to %d)\n", + pAd->CommonCfg.APEdcaParm. + EdcaUpdateCount, + EdcaParm.EdcaUpdateCount)); AsicSetEdcaParm(pAd, &EdcaParm); } - - // copy QOS related information - NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM)); - NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM)); + /* copy QOS related information */ + NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, + &QbssLoad, + sizeof(struct rt_qbss_load_parm)); + NdisMoveMemory(&pAd->CommonCfg.APQosCapability, + &QosCapability, + sizeof(struct rt_qos_capability_parm)); } - - // only INFRASTRUCTURE mode support power-saving feature - if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) || (pAd->CommonCfg.bAPSDForcePowerSave)) - { - UCHAR FreeNumber; - // 1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL - // 2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE - // 3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE - // 4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE - // 5. otherwise, put PHY back to sleep to save battery. - if (MessageToMe) - { -#ifdef RT2860 - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); + /* only INFRASTRUCTURE mode support power-saving feature */ + if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) + || (pAd->CommonCfg.bAPSDForcePowerSave)) { + u8 FreeNumber; + /* 1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL */ + /* 2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE */ + /* 3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE */ + /* 4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE */ + /* 5. otherwise, put PHY back to sleep to save battery. */ + if (MessageToMe) { +#ifdef RTMP_MAC_PCI + if (OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_PCIE_DEVICE)) { + /* Restore to correct BBP R3 value */ + if (pAd->Antenna.field.RxPath > + 1) + RTMP_BBP_IO_WRITE8_BY_REG_ID + (pAd, BBP_R3, + pAd->StaCfg.BBPR3); + /* Turn clk to 80Mhz. */ } -#endif - if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && - pAd->CommonCfg.bAPSDAC_BE && pAd->CommonCfg.bAPSDAC_BK && pAd->CommonCfg.bAPSDAC_VI && pAd->CommonCfg.bAPSDAC_VO) - { - pAd->CommonCfg.bNeedSendTriggerFrame = TRUE; - } - else - RT28XX_PS_POLL_ENQUEUE(pAd); - } - else if (BcastFlag && (DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM)) +#endif /* RTMP_MAC_PCI // */ + if (pAd->CommonCfg.bAPSDCapable + && pAd->CommonCfg.APEdcaParm. + bAPSDCapable + && pAd->CommonCfg.bAPSDAC_BE + && pAd->CommonCfg.bAPSDAC_BK + && pAd->CommonCfg.bAPSDAC_VI + && pAd->CommonCfg.bAPSDAC_VO) { + pAd->CommonCfg. + bNeedSendTriggerFrame = + TRUE; + } else + RTMP_PS_POLL_ENQUEUE(pAd); + } else if (BcastFlag && (DtimCount == 0) + && OPSTATUS_TEST_FLAG(pAd, + fOP_STATUS_RECEIVE_DTIM)) { -#ifdef RT2860 - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); +#ifdef RTMP_MAC_PCI + if (OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_PCIE_DEVICE)) { + if (pAd->Antenna.field.RxPath > + 1) + RTMP_BBP_IO_WRITE8_BY_REG_ID + (pAd, BBP_R3, + pAd->StaCfg.BBPR3); } -#endif - } - else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) || - (pAd->TxSwQueue[QID_AC_BE].Number != 0) || - (pAd->TxSwQueue[QID_AC_VI].Number != 0) || - (pAd->TxSwQueue[QID_AC_VO].Number != 0) || - (RTMPFreeTXDRequest(pAd, QID_AC_BK, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || - (RTMPFreeTXDRequest(pAd, QID_AC_BE, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || - (RTMPFreeTXDRequest(pAd, QID_AC_VI, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || - (RTMPFreeTXDRequest(pAd, QID_AC_VO, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || - (RTMPFreeTXDRequest(pAd, QID_MGMT, MGMT_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)) - { - // TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme - // can we cheat here (i.e. just check MGMT & AC_BE) for better performance? -#ifdef RT2860 - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); +#endif /* RTMP_MAC_PCI // */ + } else + if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) + || (pAd->TxSwQueue[QID_AC_BE].Number != + 0) + || (pAd->TxSwQueue[QID_AC_VI].Number != + 0) + || (pAd->TxSwQueue[QID_AC_VO].Number != + 0) + || + (RTMPFreeTXDRequest + (pAd, QID_AC_BK, TX_RING_SIZE - 1, + &FreeNumber) != NDIS_STATUS_SUCCESS) + || + (RTMPFreeTXDRequest + (pAd, QID_AC_BE, TX_RING_SIZE - 1, + &FreeNumber) != NDIS_STATUS_SUCCESS) + || + (RTMPFreeTXDRequest + (pAd, QID_AC_VI, TX_RING_SIZE - 1, + &FreeNumber) != NDIS_STATUS_SUCCESS) + || + (RTMPFreeTXDRequest + (pAd, QID_AC_VO, TX_RING_SIZE - 1, + &FreeNumber) != NDIS_STATUS_SUCCESS) + || + (RTMPFreeTXDRequest + (pAd, QID_MGMT, MGMT_RING_SIZE - 1, + &FreeNumber) != + NDIS_STATUS_SUCCESS)) { + /* TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme */ + /* can we cheat here (i.e. just check MGMT & AC_BE) for better performance? */ +#ifdef RTMP_MAC_PCI + if (OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_PCIE_DEVICE)) { + if (pAd->Antenna.field.RxPath > + 1) + RTMP_BBP_IO_WRITE8_BY_REG_ID + (pAd, BBP_R3, + pAd->StaCfg.BBPR3); } -#endif - } - else - { - USHORT NextDtim = DtimCount; - - if (NextDtim == 0) - NextDtim = DtimPeriod; - - TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) - TbttNumToNextWakeUp = NextDtim; - - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { -#ifdef RT2860 - // Set a flag to go to sleep . Then after parse this RxDoneInterrupt, will go to sleep mode. - RTMP_SET_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); - pAd->ThisTbttNumToNextWakeUp = TbttNumToNextWakeUp; -#endif -#ifdef RT2870 - AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); -#endif +#endif /* RTMP_MAC_PCI // */ + } else { + if ((pAd->CommonCfg. + bACMAPSDTr[QID_AC_VO]) + || (pAd->CommonCfg. + bACMAPSDTr[QID_AC_VI]) + || (pAd->CommonCfg. + bACMAPSDTr[QID_AC_BK]) + || (pAd->CommonCfg. + bACMAPSDTr[QID_AC_BE])) { + /* + WMM Spec v1.0 3.6.2.4, + The WMM STA shall remain awake until it receives a + QoS Data or Null frame addressed to it, with the + EOSP subfield in QoS Control field set to 1. + + So we can not sleep here or we will suffer a case: + + PS Management Frame --> + Trigger frame --> + Beacon (TIM=0) (Beacon is closer to Trig frame) --> + Station goes to sleep --> + AP delivery queued UAPSD packets --> + Station can NOT receive the reply + + Maybe we need a timeout timer to avoid that we do + NOT receive the EOSP frame. + + We can not use More Data to check if SP is ended + due to MaxSPLength. + */ + } else { + u16 NextDtim = DtimCount; + + if (NextDtim == 0) + NextDtim = DtimPeriod; + + TbttNumToNextWakeUp = + pAd->StaCfg. + DefaultListenCount; + if (OPSTATUS_TEST_FLAG + (pAd, + fOP_STATUS_RECEIVE_DTIM) + && (TbttNumToNextWakeUp > + NextDtim)) + TbttNumToNextWakeUp = + NextDtim; + + if (!OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_DOZE)) { + /* Set a flag to go to sleep . Then after parse this RxDoneInterrupt, will go to sleep mode. */ + pAd-> + ThisTbttNumToNextWakeUp + = + TbttNumToNextWakeUp; + AsicSleepThenAutoWakeup + (pAd, + pAd-> + ThisTbttNumToNextWakeUp); + } } } } } - // not my BSSID, ignore it + /* not my BSSID, ignore it */ } - // sanity check fail, ignore this frame + /* sanity check fail, ignore this frame */ } /* @@ -1612,116 +1703,126 @@ VOID PeerBeacon( Receive PROBE REQ from remote peer when operating in IBSS mode ========================================================================== */ -VOID PeerProbeReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void PeerProbeReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - UCHAR Addr2[MAC_ADDR_LEN]; - CHAR Ssid[MAX_LEN_OF_SSID]; - UCHAR SsidLen; - UCHAR HtLen, AddHtLen, NewExtLen; - HEADER_802_11 ProbeRspHdr; - NDIS_STATUS NStatus; - PUCHAR pOutBuffer = NULL; - ULONG FrameLen = 0; + u8 Addr2[MAC_ADDR_LEN]; + char Ssid[MAX_LEN_OF_SSID]; + u8 SsidLen; + u8 HtLen, AddHtLen, NewExtLen; + struct rt_header_802_11 ProbeRspHdr; + int NStatus; + u8 *pOutBuffer = NULL; + unsigned long FrameLen = 0; LARGE_INTEGER FakeTimestamp; - UCHAR DsLen = 1, IbssLen = 2; - UCHAR LocalErpIe[3] = {IE_ERP, 1, 0}; - BOOLEAN Privacy; - USHORT CapabilityInfo; - UCHAR RSNIe = IE_WPA; + u8 DsLen = 1, IbssLen = 2; + u8 LocalErpIe[3] = { IE_ERP, 1, 0 }; + BOOLEAN Privacy; + u16 CapabilityInfo; + u8 RSNIe = IE_WPA; - if (! ADHOC_ON(pAd)) + if (!ADHOC_ON(pAd)) return; - if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen)) - { - if ((SsidLen == 0) || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)) - { - // allocate and send out ProbeRsp frame - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (PeerProbeReqSanity + (pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen)) { + if ((SsidLen == 0) + || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, + pAd->CommonCfg.SsidLen)) { + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ if (NStatus != NDIS_STATUS_SUCCESS) return; - //pAd->StaCfg.AtimWin = 0; // ?????? - - Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || - (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || - (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); - CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0); - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &ProbeRspHdr, - TIMESTAMP_LEN, &FakeTimestamp, - 2, &pAd->CommonCfg.BeaconPeriod, - 2, &CapabilityInfo, - 1, &SsidIe, - 1, &pAd->CommonCfg.SsidLen, - pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, - 1, &SupRateIe, - 1, &pAd->StaActive.SupRateLen, - pAd->StaActive.SupRateLen, pAd->StaActive.SupRate, - 1, &DsIe, - 1, &DsLen, - 1, &pAd->CommonCfg.Channel, - 1, &IbssIe, - 1, &IbssLen, - 2, &pAd->StaActive.AtimWin, - END_OF_ARGS); - - if (pAd->StaActive.ExtRateLen) - { - ULONG tmp; - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 3, LocalErpIe, - 1, &ExtRateIe, - 1, &pAd->StaActive.ExtRateLen, - pAd->StaActive.ExtRateLen, &pAd->StaActive.ExtRate, - END_OF_ARGS); + /*pAd->StaCfg.AtimWin = 0; // ?????? */ + + Privacy = + (pAd->StaCfg.WepStatus == + Ndis802_11Encryption1Enabled) + || (pAd->StaCfg.WepStatus == + Ndis802_11Encryption2Enabled) + || (pAd->StaCfg.WepStatus == + Ndis802_11Encryption3Enabled); + CapabilityInfo = + CAP_GENERATE(0, 1, Privacy, + (pAd->CommonCfg.TxPreamble == + Rt802_11PreambleShort), 0, 0); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(struct rt_header_802_11), &ProbeRspHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &CapabilityInfo, + 1, &SsidIe, + 1, &pAd->CommonCfg.SsidLen, + pAd->CommonCfg.SsidLen, + pAd->CommonCfg.Ssid, 1, &SupRateIe, 1, + &pAd->StaActive.SupRateLen, + pAd->StaActive.SupRateLen, + pAd->StaActive.SupRate, 1, &DsIe, 1, + &DsLen, 1, &pAd->CommonCfg.Channel, 1, + &IbssIe, 1, &IbssLen, 2, + &pAd->StaActive.AtimWin, END_OF_ARGS); + + if (pAd->StaActive.ExtRateLen) { + unsigned long tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 3, LocalErpIe, + 1, &ExtRateIe, + 1, &pAd->StaActive.ExtRateLen, + pAd->StaActive.ExtRateLen, + &pAd->StaActive.ExtRate, + END_OF_ARGS); FrameLen += tmp; } - - // If adhoc secruity is set for WPA-None, append the cipher suite IE - if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - { - ULONG tmp; - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &RSNIe, - 1, &pAd->StaCfg.RSNIE_Len, - pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, - END_OF_ARGS); + /* If adhoc secruity is set for WPA-None, append the cipher suite IE */ + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) { + unsigned long tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &RSNIe, + 1, &pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSN_IE, + END_OF_ARGS); FrameLen += tmp; } - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) - { - ULONG TmpLen; - UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) { + unsigned long TmpLen; + u8 BROADCOM[4] = { 0x0, 0x90, 0x4c, 0x33 }; HtLen = sizeof(pAd->CommonCfg.HtCapability); AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); NewExtLen = 1; - //New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame - if (pAd->bBroadComHT == TRUE) - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, - 1, &WpaIe, - 4, &BROADCOM[0], - pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, - END_OF_ARGS); - } - else - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, - 1, &HtCapIe, - 1, &HtLen, - sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability, - 1, &AddHtInfoIe, - 1, &AddHtLen, - sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo, - 1, &NewExtChanIe, - 1, &NewExtLen, - sizeof(NEW_EXT_CHAN_IE), &pAd->CommonCfg.NewExtChanOffset, - END_OF_ARGS); + /*New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame */ + if (pAd->bBroadComHT == TRUE) { + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 1, &WpaIe, 4, + &BROADCOM[0], + pAd->MlmeAux. + HtCapabilityLen, + &pAd->MlmeAux. + HtCapability, + END_OF_ARGS); + } else { + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpLen, 1, &HtCapIe, + 1, &HtLen, + sizeof + (struct rt_ht_capability_ie), + &pAd->CommonCfg. + HtCapability, 1, + &AddHtInfoIe, 1, + &AddHtLen, + sizeof + (struct rt_add_ht_info_ie), + &pAd->CommonCfg. + AddHTInfo, 1, + &NewExtChanIe, 1, + &NewExtLen, + sizeof + (struct rt_new_ext_chan_ie), + &pAd->CommonCfg. + NewExtChanOffset, + END_OF_ARGS); } FrameLen += TmpLen; } @@ -1732,11 +1833,9 @@ VOID PeerProbeReqAction( } } -VOID BeaconTimeoutAtJoinAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void BeaconTimeoutAtJoinAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Status; + u16 Status; DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n")); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_REJ_TIMEOUT; @@ -1749,20 +1848,18 @@ VOID BeaconTimeoutAtJoinAction( Scan timeout procedure. basically add channel index by 1 and rescan ========================================================================== */ -VOID ScanTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void ScanTimeoutAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel); - // Only one channel scanned for CISCO beacon request + /* Only one channel scanned for CISCO beacon request */ if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) || - (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) || - (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) || - (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD)) + (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) || + (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) || + (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD)) pAd->MlmeAux.Channel = 0; - // this routine will stop if pAd->MlmeAux.Channel == 0 + /* this routine will stop if pAd->MlmeAux.Channel == 0 */ ScanNextChannel(pAd); } @@ -1771,12 +1868,12 @@ VOID ScanTimeoutAction( Description: ========================================================================== */ -VOID InvalidStateWhenScan( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void InvalidStateWhenScan(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); + u16 Status; + DBGPRINT(RT_DEBUG_TRACE, + ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", + pAd->Mlme.SyncMachine.CurrState)); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_STATE_MACHINE_REJECT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); @@ -1787,12 +1884,12 @@ VOID InvalidStateWhenScan( Description: ========================================================================== */ -VOID InvalidStateWhenJoin( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void InvalidStateWhenJoin(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); + u16 Status; + DBGPRINT(RT_DEBUG_TRACE, + ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", + pAd->Mlme.SyncMachine.CurrState)); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_STATE_MACHINE_REJECT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); @@ -1803,12 +1900,12 @@ VOID InvalidStateWhenJoin( Description: ========================================================================== */ -VOID InvalidStateWhenStart( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void InvalidStateWhenStart(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); + u16 Status; + DBGPRINT(RT_DEBUG_TRACE, + ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", + pAd->Mlme.SyncMachine.CurrState)); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_STATE_MACHINE_REJECT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); @@ -1822,54 +1919,51 @@ VOID InvalidStateWhenStart( ========================================================================== */ -VOID EnqueuePsPoll( - IN PRTMP_ADAPTER pAd) +void EnqueuePsPoll(struct rt_rtmp_adapter *pAd) { + if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP) - pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE; - MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->PsPollFrame, sizeof(PSPOLL_FRAME)); + pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE; + MiniportMMRequest(pAd, 0, (u8 *)& pAd->PsPollFrame, + sizeof(struct rt_pspoll_frame)); } - /* ========================================================================== Description: ========================================================================== */ -VOID EnqueueProbeRequest( - IN PRTMP_ADAPTER pAd) +void EnqueueProbeRequest(struct rt_rtmp_adapter *pAd) { - NDIS_STATUS NState; - PUCHAR pOutBuffer; - ULONG FrameLen = 0; - HEADER_802_11 Hdr80211; + int NState; + u8 *pOutBuffer; + unsigned long FrameLen = 0; + struct rt_header_802_11 Hdr80211; DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n")); - NState = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NState == NDIS_STATUS_SUCCESS) - { - MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); - - // this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &Hdr80211, - 1, &SsidIe, - 1, &pAd->CommonCfg.SsidLen, - pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, - 1, &SupRateIe, - 1, &pAd->StaActive.SupRateLen, - pAd->StaActive.SupRateLen, pAd->StaActive.SupRate, - END_OF_ARGS); + NState = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NState == NDIS_STATUS_SUCCESS) { + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, + BROADCAST_ADDR, BROADCAST_ADDR); + + /* this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(struct rt_header_802_11), &Hdr80211, + 1, &SsidIe, + 1, &pAd->CommonCfg.SsidLen, + pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, + 1, &SupRateIe, + 1, &pAd->StaActive.SupRateLen, + pAd->StaActive.SupRateLen, + pAd->StaActive.SupRate, END_OF_ARGS); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } } -BOOLEAN ScanRunning( - IN PRTMP_ADAPTER pAd) +BOOLEAN ScanRunning(struct rt_rtmp_adapter *pAd) { return (pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) ? TRUE : FALSE; } - diff --git a/drivers/staging/rt2860/sta/wpa.c b/drivers/staging/rt2860/sta/wpa.c index 8c34e39f38607e273ab13457224a8c9b58ddaea7..69b8a24daa21997aa3b3301b91dfd4f67613d223 100644 --- a/drivers/staging/rt2860/sta/wpa.c +++ b/drivers/staging/rt2860/sta/wpa.c @@ -37,1813 +37,7 @@ */ #include "../rt_config.h" -#define WPARSNIE 0xdd -#define WPA2RSNIE 0x30 - -//extern UCHAR BIT8[]; -UCHAR CipherWpaPskTkip[] = { - 0xDD, 0x16, // RSN IE - 0x00, 0x50, 0xf2, 0x01, // oui - 0x01, 0x00, // Version - 0x00, 0x50, 0xf2, 0x02, // Multicast - 0x01, 0x00, // Number of unicast - 0x00, 0x50, 0xf2, 0x02, // unicast - 0x01, 0x00, // number of authentication method - 0x00, 0x50, 0xf2, 0x02 // authentication - }; -UCHAR CipherWpaPskTkipLen = (sizeof(CipherWpaPskTkip) / sizeof(UCHAR)); - -UCHAR CipherWpaPskAes[] = { - 0xDD, 0x16, // RSN IE - 0x00, 0x50, 0xf2, 0x01, // oui - 0x01, 0x00, // Version - 0x00, 0x50, 0xf2, 0x04, // Multicast - 0x01, 0x00, // Number of unicast - 0x00, 0x50, 0xf2, 0x04, // unicast - 0x01, 0x00, // number of authentication method - 0x00, 0x50, 0xf2, 0x02 // authentication - }; -UCHAR CipherWpaPskAesLen = (sizeof(CipherWpaPskAes) / sizeof(UCHAR)); - -UCHAR CipherSuiteCiscoCCKM[] = { - 0xDD, 0x16, // RSN IE - 0x00, 0x50, 0xf2, 0x01, // oui - 0x01, 0x00, // Version - 0x00, 0x40, 0x96, 0x01, // Multicast - 0x01, 0x00, // Number of uicast - 0x00, 0x40, 0x96, 0x01, // unicast - 0x01, 0x00, // number of authentication method - 0x00, 0x40, 0x96, 0x00 // Authentication - }; -UCHAR CipherSuiteCiscoCCKMLen = (sizeof(CipherSuiteCiscoCCKM) / sizeof(UCHAR)); - -UCHAR CipherSuiteCiscoCCKM24[] = { - 0xDD, 0x18, // RSN IE - 0x00, 0x50, 0xf2, 0x01, // oui - 0x01, 0x00, // Version - 0x00, 0x40, 0x96, 0x01, // Multicast - 0x01, 0x00, // Number of uicast - 0x00, 0x40, 0x96, 0x01, // unicast - 0x01, 0x00, // number of authentication method - 0x00, 0x40, 0x96, 0x00, - 0x28, 0x00// Authentication - }; - -UCHAR CipherSuiteCiscoCCKM24Len = (sizeof(CipherSuiteCiscoCCKM24) / sizeof(UCHAR)); - -UCHAR CipherSuiteCCXTkip[] = { - 0xDD, 0x16, // RSN IE - 0x00, 0x50, 0xf2, 0x01, // oui - 0x01, 0x00, // Version - 0x00, 0x50, 0xf2, 0x02, // Multicast - 0x01, 0x00, // Number of unicast - 0x00, 0x50, 0xf2, 0x02, // unicast - 0x01, 0x00, // number of authentication method - 0x00, 0x50, 0xf2, 0x01 // authentication - }; -UCHAR CipherSuiteCCXTkipLen = (sizeof(CipherSuiteCCXTkip) / sizeof(UCHAR)); - -UCHAR CCX_LLC_HDR[] = {0xAA, 0xAA, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02}; -UCHAR LLC_NORMAL[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00}; - -UCHAR EAPOL_FRAME[] = {0x88, 0x8E}; - -BOOLEAN CheckRSNIE( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN UCHAR DataLen, - OUT UCHAR *Offset); - -void inc_byte_array(UCHAR *counter, int len); - -/* - ======================================================================== - - Routine Description: - Classify WPA EAP message type - - Arguments: - EAPType Value of EAP message type - MsgType Internal Message definition for MLME state machine - - Return Value: - TRUE Found appropriate message type - FALSE No appropriate message type - - IRQL = DISPATCH_LEVEL - - Note: - All these constants are defined in wpa.h - For supplicant, there is only EAPOL Key message avaliable - - ======================================================================== -*/ -BOOLEAN WpaMsgTypeSubst( - IN UCHAR EAPType, - OUT INT *MsgType) -{ - switch (EAPType) - { - case EAPPacket: - *MsgType = MT2_EAPPacket; - break; - case EAPOLStart: - *MsgType = MT2_EAPOLStart; - break; - case EAPOLLogoff: - *MsgType = MT2_EAPOLLogoff; - break; - case EAPOLKey: - *MsgType = MT2_EAPOLKey; - break; - case EAPOLASFAlert: - *MsgType = MT2_EAPOLASFAlert; - break; - default: - return FALSE; - } - return TRUE; -} - -/* - ========================================================================== - Description: - association state machine init, including state transition and timer init - Parameters: - S - pointer to the association state machine - ========================================================================== - */ -VOID WpaPskStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]) -{ - StateMachineInit(S, Trans, MAX_WPA_PSK_STATE, MAX_WPA_PSK_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PSK_IDLE, WPA_MACHINE_BASE); - StateMachineSetAction(S, WPA_PSK_IDLE, MT2_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction); -} - -/* - ========================================================================== - Description: - This is state machine function. - When receiving EAPOL packets which is for 802.1x key management. - Use both in WPA, and WPAPSK case. - In this function, further dispatch to different functions according to the received packet. 3 categories are : - 1. normal 4-way pairwisekey and 2-way groupkey handshake - 2. MIC error (Countermeasures attack) report packet from STA. - 3. Request for pairwise/group key update from STA - Return: - ========================================================================== -*/ -VOID WpaEAPOLKeyAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) - -{ - INT MsgType = EAPOL_MSG_INVALID; - PKEY_DESCRIPTER pKeyDesc; - PHEADER_802_11 pHeader; //red - UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY]; - UCHAR EapolVr; - KEY_INFO peerKeyInfo; - - DBGPRINT(RT_DEBUG_TRACE, ("-----> WpaEAPOLKeyAction\n")); - - // Get 802.11 header first - pHeader = (PHEADER_802_11) Elem->Msg; - - // Get EAPoL-Key Descriptor - pKeyDesc = (PKEY_DESCRIPTER) &Elem->Msg[(LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H)]; - - NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); - NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pKeyDesc->KeyInfo, sizeof(KEY_INFO)); - - *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo)); - - - // 1. Check EAPOL frame version and type - EapolVr = (UCHAR) Elem->Msg[LENGTH_802_11+LENGTH_802_1_H]; - - if (((EapolVr != EAPOL_VER) && (EapolVr != EAPOL_VER2)) || ((pKeyDesc->Type != WPA1_KEY_DESC) && (pKeyDesc->Type != WPA2_KEY_DESC))) - { - DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n")); - return; - } - - // First validate replay counter, only accept message with larger replay counter - // Let equal pass, some AP start with all zero replay counter - NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); - - if((RTMPCompareMemory(pKeyDesc->ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) && - (RTMPCompareMemory(pKeyDesc->ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0)) - { - DBGPRINT(RT_DEBUG_ERROR, (" ReplayCounter not match \n")); - return; - } - - // Process WPA2PSK frame - if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) - { - if((peerKeyInfo.KeyType == PAIRWISEKEY) && - (peerKeyInfo.EKD_DL == 0) && - (peerKeyInfo.KeyAck == 1) && - (peerKeyInfo.KeyMic == 0) && - (peerKeyInfo.Secure == 0) && - (peerKeyInfo.Error == 0) && - (peerKeyInfo.Request == 0)) - { - MsgType = EAPOL_PAIR_MSG_1; - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 1\n")); - } else if((peerKeyInfo.KeyType == PAIRWISEKEY) && - (peerKeyInfo.EKD_DL == 1) && - (peerKeyInfo.KeyAck == 1) && - (peerKeyInfo.KeyMic == 1) && - (peerKeyInfo.Secure == 1) && - (peerKeyInfo.Error == 0) && - (peerKeyInfo.Request == 0)) - { - MsgType = EAPOL_PAIR_MSG_3; - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 3\n")); - } else if((peerKeyInfo.KeyType == GROUPKEY) && - (peerKeyInfo.EKD_DL == 1) && - (peerKeyInfo.KeyAck == 1) && - (peerKeyInfo.KeyMic == 1) && - (peerKeyInfo.Secure == 1) && - (peerKeyInfo.Error == 0) && - (peerKeyInfo.Request == 0)) - { - MsgType = EAPOL_GROUP_MSG_1; - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Group Message 1\n")); - } - - // We will assume link is up (assoc suceess and port not secured). - // All state has to be able to process message from previous state - switch(pAd->StaCfg.WpaState) - { - case SS_START: - if(MsgType == EAPOL_PAIR_MSG_1) - { - Wpa2PairMsg1Action(pAd, Elem); - pAd->StaCfg.WpaState = SS_WAIT_MSG_3; - } - break; - - case SS_WAIT_MSG_3: - if(MsgType == EAPOL_PAIR_MSG_1) - { - Wpa2PairMsg1Action(pAd, Elem); - pAd->StaCfg.WpaState = SS_WAIT_MSG_3; - } - else if(MsgType == EAPOL_PAIR_MSG_3) - { - Wpa2PairMsg3Action(pAd, Elem); - pAd->StaCfg.WpaState = SS_WAIT_GROUP; - } - break; - - case SS_WAIT_GROUP: // When doing group key exchange - case SS_FINISH: // This happened when update group key - if(MsgType == EAPOL_PAIR_MSG_1) - { - // Reset port secured variable - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - Wpa2PairMsg1Action(pAd, Elem); - pAd->StaCfg.WpaState = SS_WAIT_MSG_3; - } - else if(MsgType == EAPOL_PAIR_MSG_3) - { - // Reset port secured variable - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - Wpa2PairMsg3Action(pAd, Elem); - pAd->StaCfg.WpaState = SS_WAIT_GROUP; - } - else if(MsgType == EAPOL_GROUP_MSG_1) - { - WpaGroupMsg1Action(pAd, Elem); - pAd->StaCfg.WpaState = SS_FINISH; - } - break; - - default: - break; - } - } - // Process WPAPSK Frame - // Classify message Type, either pairwise message 1, 3, or group message 1 for supplicant - else if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) - { - if((peerKeyInfo.KeyType == PAIRWISEKEY) && - (peerKeyInfo.KeyIndex == 0) && - (peerKeyInfo.KeyAck == 1) && - (peerKeyInfo.KeyMic == 0) && - (peerKeyInfo.Secure == 0) && - (peerKeyInfo.Error == 0) && - (peerKeyInfo.Request == 0)) - { - MsgType = EAPOL_PAIR_MSG_1; - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 1\n")); - } - else if((peerKeyInfo.KeyType == PAIRWISEKEY) && - (peerKeyInfo.KeyIndex == 0) && - (peerKeyInfo.KeyAck == 1) && - (peerKeyInfo.KeyMic == 1) && - (peerKeyInfo.Secure == 0) && - (peerKeyInfo.Error == 0) && - (peerKeyInfo.Request == 0)) - { - MsgType = EAPOL_PAIR_MSG_3; - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 3\n")); - } - else if((peerKeyInfo.KeyType == GROUPKEY) && - (peerKeyInfo.KeyIndex != 0) && - (peerKeyInfo.KeyAck == 1) && - (peerKeyInfo.KeyMic == 1) && - (peerKeyInfo.Secure == 1) && - (peerKeyInfo.Error == 0) && - (peerKeyInfo.Request == 0)) - { - MsgType = EAPOL_GROUP_MSG_1; - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Group Message 1\n")); - } - - // We will assume link is up (assoc suceess and port not secured). - // All state has to be able to process message from previous state - switch(pAd->StaCfg.WpaState) - { - case SS_START: - if(MsgType == EAPOL_PAIR_MSG_1) - { - WpaPairMsg1Action(pAd, Elem); - pAd->StaCfg.WpaState = SS_WAIT_MSG_3; - } - break; - - case SS_WAIT_MSG_3: - if(MsgType == EAPOL_PAIR_MSG_1) - { - WpaPairMsg1Action(pAd, Elem); - pAd->StaCfg.WpaState = SS_WAIT_MSG_3; - } - else if(MsgType == EAPOL_PAIR_MSG_3) - { - WpaPairMsg3Action(pAd, Elem); - pAd->StaCfg.WpaState = SS_WAIT_GROUP; - } - break; - - case SS_WAIT_GROUP: // When doing group key exchange - case SS_FINISH: // This happened when update group key - if(MsgType == EAPOL_PAIR_MSG_1) - { - WpaPairMsg1Action(pAd, Elem); - pAd->StaCfg.WpaState = SS_WAIT_MSG_3; - // Reset port secured variable - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - } - else if(MsgType == EAPOL_PAIR_MSG_3) - { - WpaPairMsg3Action(pAd, Elem); - pAd->StaCfg.WpaState = SS_WAIT_GROUP; - // Reset port secured variable - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - } - else if(MsgType == EAPOL_GROUP_MSG_1) - { - WpaGroupMsg1Action(pAd, Elem); - pAd->StaCfg.WpaState = SS_FINISH; - } - break; - - default: - break; - } - } - - DBGPRINT(RT_DEBUG_TRACE, ("<----- WpaEAPOLKeyAction\n")); -} - -/* - ======================================================================== - - Routine Description: - Process Pairwise key 4-way handshaking - - Arguments: - pAd Pointer to our adapter - Elem Message body - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID WpaPairMsg1Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - PHEADER_802_11 pHeader; - UCHAR *mpool, *PTK, *digest; - PUCHAR pOutBuffer = NULL; - UCHAR Header802_3[14]; - ULONG FrameLen = 0; - PEAPOL_PACKET pMsg1; - EAPOL_PACKET Packet; - UCHAR Mic[16]; - - DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg1Action ----->\n")); - - // allocate memory pool - os_alloc_mem(pAd, (PUCHAR *)&mpool, 256); - - if (mpool == NULL) - return; - - // PTK Len = 80. - PTK = (UCHAR *) ROUND_UP(mpool, 4); - // digest Len = 80. - digest = (UCHAR *) ROUND_UP(PTK + 80, 4); - - pHeader = (PHEADER_802_11) Elem->Msg; - - // Process message 1 from authenticator - pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; - - // 1. Save Replay counter, it will use to verify message 3 and construct message 2 - NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - - // 2. Save ANonce - NdisMoveMemory(pAd->StaCfg.ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); - - // Generate random SNonce - GenRandom(pAd, pAd->CurrentAddress, pAd->StaCfg.SNonce); - - // Calc PTK(ANonce, SNonce) - WpaCountPTK(pAd, - pAd->StaCfg.PMK, - pAd->StaCfg.ANonce, - pAd->CommonCfg.Bssid, - pAd->StaCfg.SNonce, - pAd->CurrentAddress, - PTK, - LEN_PTK); - - // Save key to PTK entry - NdisMoveMemory(pAd->StaCfg.PTK, PTK, LEN_PTK); - - // init 802.3 header and Fill Packet - MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); - - // Zero Message 2 body - NdisZeroMemory(&Packet, sizeof(Packet)); - Packet.ProVer = EAPOL_VER; - Packet.ProType = EAPOLKey; - // - // Message 2 as EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE) - // - Packet.KeyDesc.Type = WPA1_KEY_DESC; - // 1. Key descriptor version and appropriate RSN IE - if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - Packet.KeyDesc.KeyInfo.KeyDescVer = 2; - } - else // TKIP - { - Packet.KeyDesc.KeyInfo.KeyDescVer = 1; - } - - // fill in Data Material and its length - Packet.KeyDesc.KeyData[0] = IE_WPA; - Packet.KeyDesc.KeyData[1] = pAd->StaCfg.RSNIE_Len; - Packet.KeyDesc.KeyDataLen[1] = pAd->StaCfg.RSNIE_Len + 2; - NdisMoveMemory(&Packet.KeyDesc.KeyData[2], pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len); - - // Update packet length after decide Key data payload - Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + Packet.KeyDesc.KeyDataLen[1]; - - // Update Key length - Packet.KeyDesc.KeyLength[0] = pMsg1->KeyDesc.KeyLength[0]; - Packet.KeyDesc.KeyLength[1] = pMsg1->KeyDesc.KeyLength[1]; - // 2. Key Type PeerKey - Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; - - // 3. KeyMic field presented - Packet.KeyDesc.KeyInfo.KeyMic = 1; - - //Convert to little-endian format. - *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); - - - // 4. Fill SNonce - NdisMoveMemory(Packet.KeyDesc.KeyNonce, pAd->StaCfg.SNonce, LEN_KEY_DESC_NONCE); - - // 5. Key Replay Count - NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); - - // Send EAPOL(0, 1, 0, 0, 0, P, 0, SNonce, MIC, RSN_IE) - // Out buffer for transmitting message 2 - MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory - if(pOutBuffer == NULL) - { - os_free_mem(pAd, mpool); - return; - } - // Prepare EAPOL frame for MIC calculation - // Be careful, only EAPOL frame is counted for MIC calculation - MakeOutgoingFrame(pOutBuffer, &FrameLen, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - // 6. Prepare and Fill MIC value - NdisZeroMemory(Mic, sizeof(Mic)); - if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { // AES - - HMAC_SHA1(pOutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest); - NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); - } - else - { // TKIP - hmac_md5(PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); - } - NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); - - //hex_dump("MIC", Mic, LEN_KEY_DESC_MIC); - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - LENGTH_802_3, &Header802_3, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - - // 5. Copy frame to Tx ring and send Msg 2 to authenticator - RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE); - - MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); - os_free_mem(pAd, (PUCHAR)mpool); - - DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg1Action <-----\n")); -} - -VOID Wpa2PairMsg1Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - PHEADER_802_11 pHeader; - UCHAR *mpool, *PTK, *digest; - PUCHAR pOutBuffer = NULL; - UCHAR Header802_3[14]; - ULONG FrameLen = 0; - PEAPOL_PACKET pMsg1; - EAPOL_PACKET Packet; - UCHAR Mic[16]; - - DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg1Action ----->\n")); - - // allocate memory pool - os_alloc_mem(pAd, (PUCHAR *)&mpool, 256); - - if (mpool == NULL) - return; - - // PTK Len = 80. - PTK = (UCHAR *) ROUND_UP(mpool, 4); - // digest Len = 80. - digest = (UCHAR *) ROUND_UP(PTK + 80, 4); - - pHeader = (PHEADER_802_11) Elem->Msg; - - // Process message 1 from authenticator - pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; - - // 1. Save Replay counter, it will use to verify message 3 and construct message 2 - NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - - // 2. Save ANonce - NdisMoveMemory(pAd->StaCfg.ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); - - // Generate random SNonce - GenRandom(pAd, pAd->CurrentAddress, pAd->StaCfg.SNonce); - - if(pMsg1->KeyDesc.KeyDataLen[1] > 0 ) - { - // cached PMKID - } - - // Calc PTK(ANonce, SNonce) - WpaCountPTK(pAd, - pAd->StaCfg.PMK, - pAd->StaCfg.ANonce, - pAd->CommonCfg.Bssid, - pAd->StaCfg.SNonce, - pAd->CurrentAddress, - PTK, - LEN_PTK); - - // Save key to PTK entry - NdisMoveMemory(pAd->StaCfg.PTK, PTK, LEN_PTK); - - // init 802.3 header and Fill Packet - MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); - - // Zero message 2 body - NdisZeroMemory(&Packet, sizeof(Packet)); - Packet.ProVer = EAPOL_VER; - Packet.ProType = EAPOLKey; - // - // Message 2 as EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE) - // - Packet.KeyDesc.Type = WPA2_KEY_DESC; - - // 1. Key descriptor version and appropriate RSN IE - if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - Packet.KeyDesc.KeyInfo.KeyDescVer = 2; - } - else // TKIP - { - Packet.KeyDesc.KeyInfo.KeyDescVer = 1; - } - - // fill in Data Material and its length - Packet.KeyDesc.KeyData[0] = IE_WPA2; - Packet.KeyDesc.KeyData[1] = pAd->StaCfg.RSNIE_Len; - Packet.KeyDesc.KeyDataLen[1] = pAd->StaCfg.RSNIE_Len + 2; - NdisMoveMemory(&Packet.KeyDesc.KeyData[2], pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len); - - // Update packet length after decide Key data payload - Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + Packet.KeyDesc.KeyDataLen[1]; - - // 2. Key Type PeerKey - Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; - - // 3. KeyMic field presented - Packet.KeyDesc.KeyInfo.KeyMic = 1; - - // Update Key Length - Packet.KeyDesc.KeyLength[0] = 0; - Packet.KeyDesc.KeyLength[1] = pMsg1->KeyDesc.KeyLength[1]; - - // 4. Fill SNonce - NdisMoveMemory(Packet.KeyDesc.KeyNonce, pAd->StaCfg.SNonce, LEN_KEY_DESC_NONCE); - - // 5. Key Replay Count - NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); - - // Convert to little-endian format. - *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); - - // Send EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE) - // Out buffer for transmitting message 2 - MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory - if(pOutBuffer == NULL) - { - os_free_mem(pAd, mpool); - return; - } - - // Prepare EAPOL frame for MIC calculation - // Be careful, only EAPOL frame is counted for MIC calculation - MakeOutgoingFrame(pOutBuffer, &FrameLen, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - // 6. Prepare and Fill MIC value - NdisZeroMemory(Mic, sizeof(Mic)); - if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - // AES - HMAC_SHA1(pOutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest); - NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); - } - else - { - hmac_md5(PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); - } - NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); - - - // Make Transmitting frame - MakeOutgoingFrame(pOutBuffer, &FrameLen, - LENGTH_802_3, &Header802_3, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - - // 5. Copy frame to Tx ring - RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE); - - MlmeFreeMemory(pAd, pOutBuffer); - os_free_mem(pAd, mpool); - - DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg1Action <-----\n")); - -} - -/* - ======================================================================== - - Routine Description: - Process Pairwise key 4-way handshaking - - Arguments: - pAd Pointer to our adapter - Elem Message body - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID WpaPairMsg3Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) - -{ - PHEADER_802_11 pHeader; - PUCHAR pOutBuffer = NULL; - UCHAR Header802_3[14]; - ULONG FrameLen = 0; - EAPOL_PACKET Packet; - PEAPOL_PACKET pMsg3; - UCHAR Mic[16], OldMic[16]; - MAC_TABLE_ENTRY *pEntry = NULL; - UCHAR skip_offset; - KEY_INFO peerKeyInfo; - - DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg3Action ----->\n")); - - // Record 802.11 header & the received EAPOL packet Msg3 - pHeader = (PHEADER_802_11) Elem->Msg; - pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; - - NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); - NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pMsg3->KeyDesc.KeyInfo, sizeof(KEY_INFO)); - - *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo)); - - - // 1. Verify cipher type match - if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer != 2)) - { - return; - } - else if(pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1)) - { - return; - } - - // Verify RSN IE - //if (!RTMPEqualMemory(pMsg3->KeyDesc.KeyData, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) - if (!CheckRSNIE(pAd, pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1], &skip_offset)) - { - DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in Msg 3 of WPA1 4-way handshake!! \n")); - hex_dump("The original RSN_IE", pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len); - hex_dump("The received RSN_IE", pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1]); - return; - } - else - DBGPRINT(RT_DEBUG_TRACE, ("RSN_IE VALID in Msg 3 of WPA1 4-way handshake!! \n")); - - - // 2. Check MIC value - // Save the MIC and replace with zero - NdisMoveMemory(OldMic, pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); - NdisZeroMemory(pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); - if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - // AES - UCHAR digest[80]; - - HMAC_SHA1((PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); - NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); - } - else // TKIP - { - hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, Mic); - } - - if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC)) - { - DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in msg 3 of 4-way handshake!!!!!!!!!! \n")); - return; - } - else - DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in msg 3 of 4-way handshake!!!!!!!!!! \n")); - - // 3. Check Replay Counter, it has to be larger than last one. No need to be exact one larger - if(RTMPCompareMemory(pMsg3->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) - return; - - // Update new replay counter - NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - - // 4. Double check ANonce - if(!NdisEqualMemory(pAd->StaCfg.ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) - return; - - // init 802.3 header and Fill Packet - MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); - - // Zero Message 4 body - NdisZeroMemory(&Packet, sizeof(Packet)); - Packet.ProVer = EAPOL_VER; - Packet.ProType = EAPOLKey; - Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field - - // - // Message 4 as EAPOL-Key(0,1,0,0,0,P,0,0,MIC,0) - // - Packet.KeyDesc.Type = WPA1_KEY_DESC; - - // Key descriptor version and appropriate RSN IE - Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer; - - // Update Key Length - Packet.KeyDesc.KeyLength[0] = pMsg3->KeyDesc.KeyLength[0]; - Packet.KeyDesc.KeyLength[1] = pMsg3->KeyDesc.KeyLength[1]; - - // Key Type PeerKey - Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; - - // KeyMic field presented - Packet.KeyDesc.KeyInfo.KeyMic = 1; - - // In Msg3, KeyInfo.secure =0 if Group Key HS to come. 1 if no group key HS - // Station sends Msg4 KeyInfo.secure should be the same as that in Msg.3 - Packet.KeyDesc.KeyInfo.Secure= peerKeyInfo.Secure; - - // Convert to little-endian format. - *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); - - // Key Replay count - NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - - // Out buffer for transmitting message 4 - MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory - if(pOutBuffer == NULL) - return; - - // Prepare EAPOL frame for MIC calculation - // Be careful, only EAPOL frame is counted for MIC calculation - MakeOutgoingFrame(pOutBuffer, &FrameLen, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - // Prepare and Fill MIC value - NdisZeroMemory(Mic, sizeof(Mic)); - if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - // AES - UCHAR digest[80]; - - HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); - NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); - } - else - { - hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); - } - NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); - - // Update PTK - // Prepare pair-wise key information into shared key table - NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); - pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); - NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); - NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); - - // Decide its ChiperAlg - if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; - else - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE; - - // Update these related information to MAC_TABLE_ENTRY - pEntry = &pAd->MacTab.Content[BSSID_WCID]; - NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); - NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); - NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); - pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; - - // Update pairwise key information to ASIC Shared Key Table - AsicAddSharedKeyEntry(pAd, - BSS0, - 0, - pAd->SharedKey[BSS0][0].CipherAlg, - pAd->SharedKey[BSS0][0].Key, - pAd->SharedKey[BSS0][0].TxMic, - pAd->SharedKey[BSS0][0].RxMic); - - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAd, - BSS0, - 0, - pAd->SharedKey[BSS0][0].CipherAlg, - pEntry); - - // Make transmitting frame - MakeOutgoingFrame(pOutBuffer, &FrameLen, - LENGTH_802_3, &Header802_3, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - - // Copy frame to Tx ring and Send Message 4 to authenticator - RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE); - - MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); - - DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg3Action <-----\n")); -} - -VOID Wpa2PairMsg3Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) - -{ - PHEADER_802_11 pHeader; - PUCHAR pOutBuffer = NULL; - UCHAR Header802_3[14]; - ULONG FrameLen = 0; - EAPOL_PACKET Packet; - PEAPOL_PACKET pMsg3; - UCHAR Mic[16], OldMic[16]; - UCHAR *mpool, *KEYDATA, *digest; - UCHAR Key[32]; - MAC_TABLE_ENTRY *pEntry = NULL; - KEY_INFO peerKeyInfo; - - // allocate memory - os_alloc_mem(pAd, (PUCHAR *)&mpool, 1024); - - if(mpool == NULL) - return; - - // KEYDATA Len = 512. - KEYDATA = (UCHAR *) ROUND_UP(mpool, 4); - // digest Len = 80. - digest = (UCHAR *) ROUND_UP(KEYDATA + 512, 4); - - DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg3Action ----->\n")); - - pHeader = (PHEADER_802_11) Elem->Msg; - - // Process message 3 frame. - pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; - - NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); - NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pMsg3->KeyDesc.KeyInfo, sizeof(KEY_INFO)); - - *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo)); - - // 1. Verify cipher type match - if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer!= 2)) - { - os_free_mem(pAd, (PUCHAR)mpool); - return; - } - else if(pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1)) - { - os_free_mem(pAd, (PUCHAR)mpool); - return; - } - - // 2. Check MIC value - // Save the MIC and replace with zero - NdisMoveMemory(OldMic, pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); - NdisZeroMemory(pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); - if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - // AES - HMAC_SHA1((PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); - NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); - } - else - { - hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, Mic); - } - - if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC)) - { - DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in msg 3 of 4-way handshake!!!!!!!!!! \n")); - os_free_mem(pAd, (PUCHAR)mpool); - return; - } - else - DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in msg 3 of 4-way handshake!!!!!!!!!! \n")); - - // 3. Check Replay Counter, it has to be larger than last one. No need to be exact one larger - if(RTMPCompareMemory(pMsg3->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) - { - os_free_mem(pAd, (PUCHAR)mpool); - return; - } - - // Update new replay counter - NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - - // 4. Double check ANonce - if(!NdisEqualMemory(pAd->StaCfg.ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) - { - os_free_mem(pAd, (PUCHAR)mpool); - return; - } - - // Obtain GTK - // 5. Decrypt GTK from Key Data - DBGPRINT_RAW(RT_DEBUG_TRACE, ("EKD = %d\n", peerKeyInfo.EKD_DL)); - if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - // Decrypt AES GTK - AES_GTK_KEY_UNWRAP(&pAd->StaCfg.PTK[16], KEYDATA, pMsg3->KeyDesc.KeyDataLen[1],pMsg3->KeyDesc.KeyData); - } - else // TKIP - { - INT i; - // Decrypt TKIP GTK - // Construct 32 bytes RC4 Key - NdisMoveMemory(Key, pMsg3->KeyDesc.KeyIv, 16); - NdisMoveMemory(&Key[16], &pAd->StaCfg.PTK[16], 16); - ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32); - //discard first 256 bytes - for(i = 0; i < 256; i++) - ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT); - // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not - ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1]); - } - - if (!ParseKeyData(pAd, KEYDATA, pMsg3->KeyDesc.KeyDataLen[1], 1)) - { - os_free_mem(pAd, (PUCHAR)mpool); - return; - } - - // Update GTK to ASIC - // Update group key information to ASIC Shared Key Table - AsicAddSharedKeyEntry(pAd, - BSS0, - pAd->StaCfg.DefaultKeyId, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic); - - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAd, - BSS0, - pAd->StaCfg.DefaultKeyId, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, - NULL); - - // init 802.3 header and Fill Packet - MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); - - // Zero message 4 body - NdisZeroMemory(&Packet, sizeof(Packet)); - Packet.ProVer = EAPOL_VER; - Packet.ProType = EAPOLKey; - Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field - - // - // Message 4 as EAPOL-Key(0,1,0,0,0,P,0,0,MIC,0) - // - Packet.KeyDesc.Type = WPA2_KEY_DESC; - - // Key descriptor version and appropriate RSN IE - Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer; - - // Update Key Length - Packet.KeyDesc.KeyLength[0] = pMsg3->KeyDesc.KeyLength[0]; - Packet.KeyDesc.KeyLength[1] = pMsg3->KeyDesc.KeyLength[1]; - - // Key Type PeerKey - Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; - - // KeyMic field presented - Packet.KeyDesc.KeyInfo.KeyMic = 1; - Packet.KeyDesc.KeyInfo.Secure = 1; - - // Convert to little-endian format. - *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); - - // Key Replay count - NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - - // Out buffer for transmitting message 4 - MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory - if(pOutBuffer == NULL) - { - os_free_mem(pAd, (PUCHAR)mpool); - return; - } - - // Prepare EAPOL frame for MIC calculation - // Be careful, only EAPOL frame is counted for MIC calculation - MakeOutgoingFrame(pOutBuffer, &FrameLen, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - // Prepare and Fill MIC value - NdisZeroMemory(Mic, sizeof(Mic)); - if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - // AES - HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); - NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); - } - else - { - hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); - } - NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); - - // Update PTK - // Prepare pair-wise key information into shared key table - NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); - pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); - NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); - NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); - - // Decide its ChiperAlg - if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; - else - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE; - - // Update these related information to MAC_TABLE_ENTRY - pEntry = &pAd->MacTab.Content[BSSID_WCID]; - NdisMoveMemory(&pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); - NdisMoveMemory(&pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); - NdisMoveMemory(&pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); - pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; - - // Update pairwise key information to ASIC Shared Key Table - AsicAddSharedKeyEntry(pAd, - BSS0, - 0, - pAd->SharedKey[BSS0][0].CipherAlg, - pAd->SharedKey[BSS0][0].Key, - pAd->SharedKey[BSS0][0].TxMic, - pAd->SharedKey[BSS0][0].RxMic); - - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAd, - BSS0, - 0, - pAd->SharedKey[BSS0][0].CipherAlg, - pEntry); - - // Make Transmitting frame - MakeOutgoingFrame(pOutBuffer, &FrameLen, - LENGTH_802_3, &Header802_3, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - - // Copy frame to Tx ring and Send Message 4 to authenticator - RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE); - - // set 802.1x port control - STA_PORT_SECURED(pAd); - - // Indicate Connected for GUI - pAd->IndicateMediaState = NdisMediaStateConnected; - - MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); - os_free_mem(pAd, (PUCHAR)mpool); - - - // send wireless event - for set key done WPA2 - if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, BSS0, 0); - - DBGPRINT(RT_DEBUG_ERROR, ("Wpa2PairMsg3Action <-----\n")); - -} - -/* - ======================================================================== - - Routine Description: - Process Group key 2-way handshaking - - Arguments: - pAd Pointer to our adapter - Elem Message body - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID WpaGroupMsg1Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) - -{ - PUCHAR pOutBuffer = NULL; - UCHAR Header802_3[14]; - ULONG FrameLen = 0; - EAPOL_PACKET Packet; - PEAPOL_PACKET pGroup; - UCHAR *mpool, *digest, *KEYDATA; - UCHAR Mic[16], OldMic[16]; - UCHAR GTK[32], Key[32]; - KEY_INFO peerKeyInfo; - - // allocate memory - os_alloc_mem(pAd, (PUCHAR *)&mpool, 1024); - - if(mpool == NULL) - return; - - // digest Len = 80. - digest = (UCHAR *) ROUND_UP(mpool, 4); - // KEYDATA Len = 512. - KEYDATA = (UCHAR *) ROUND_UP(digest + 80, 4); - - DBGPRINT(RT_DEBUG_TRACE, ("WpaGroupMsg1Action ----->\n")); - - // Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8) - pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; - - NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); - NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pGroup->KeyDesc.KeyInfo, sizeof(KEY_INFO)); - - *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo)); - - // 0. Check cipher type match - if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer != 2)) - { - os_free_mem(pAd, (PUCHAR)mpool); - return; - } - else if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1)) - { - os_free_mem(pAd, (PUCHAR)mpool); - return; - } - - // 1. Verify Replay counter - // Check Replay Counter, it has to be larger than last one. No need to be exact one larger - if(RTMPCompareMemory(pGroup->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) - { - os_free_mem(pAd, (PUCHAR)mpool); - return; - } - - // Update new replay counter - NdisMoveMemory(pAd->StaCfg.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - - // 2. Verify MIC is valid - // Save the MIC and replace with zero - NdisMoveMemory(OldMic, pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); - NdisZeroMemory(pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); - - if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { // AES - HMAC_SHA1((PUCHAR) pGroup, pGroup->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); - NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); - } - else - { // TKIP - hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pGroup, pGroup->Body_Len[1] + 4, Mic); - } - - if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC)) - { - DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in group msg 1 of 2-way handshake!!!!!!!!!! \n")); - MlmeFreeMemory(pAd, (PUCHAR)mpool); - return; - } - else - DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in group msg 1 of 2-way handshake!!!!!!!!!! \n")); - - - // 3. Decrypt GTK from Key Data - if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - // Decrypt AES GTK - AES_GTK_KEY_UNWRAP(&pAd->StaCfg.PTK[16], KEYDATA, pGroup->KeyDesc.KeyDataLen[1], pGroup->KeyDesc.KeyData); - } - else // TKIP - { - INT i; - - // Decrypt TKIP GTK - // Construct 32 bytes RC4 Key - NdisMoveMemory(Key, pGroup->KeyDesc.KeyIv, 16); - NdisMoveMemory(&Key[16], &pAd->StaCfg.PTK[16], 16); - ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32); - //discard first 256 bytes - for(i = 0; i < 256; i++) - ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT); - // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not - ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pGroup->KeyDesc.KeyData, pGroup->KeyDesc.KeyDataLen[1]); - } - - // Process decrypted key data material - // Parse keyData to handle KDE format for WPA2PSK - if (peerKeyInfo.EKD_DL) - { - if (!ParseKeyData(pAd, KEYDATA, pGroup->KeyDesc.KeyDataLen[1], 0)) - { - os_free_mem(pAd, (PUCHAR)mpool); - return; - } - } - else // WPAPSK - { - // set key material, TxMic and RxMic for WPAPSK - NdisMoveMemory(GTK, KEYDATA, 32); - NdisMoveMemory(pAd->StaCfg.GTK, GTK, 32); - pAd->StaCfg.DefaultKeyId = peerKeyInfo.KeyIndex; - - // Prepare pair-wise key information into shared key table - NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY)); - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, GTK, LEN_TKIP_EK); - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, >K[16], LEN_TKIP_RXMICK); - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, >K[24], LEN_TKIP_TXMICK); - - // Update Shared Key CipherAlg - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE; - if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES; - else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled) - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP64; - else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled) - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP128; - - //hex_dump("Group Key :", pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, LEN_TKIP_EK); - } - - // Update group key information to ASIC Shared Key Table - AsicAddSharedKeyEntry(pAd, - BSS0, - pAd->StaCfg.DefaultKeyId, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic); - - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAd, - BSS0, - pAd->StaCfg.DefaultKeyId, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, - NULL); - - // set 802.1x port control - STA_PORT_SECURED(pAd); - - // Indicate Connected for GUI - pAd->IndicateMediaState = NdisMediaStateConnected; - - // init header and Fill Packet - MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); - - // Zero Group message 1 body - NdisZeroMemory(&Packet, sizeof(Packet)); - Packet.ProVer = EAPOL_VER; - Packet.ProType = EAPOLKey; - Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field - - // - // Group Message 2 as EAPOL-Key(1,0,0,0,G,0,0,MIC,0) - // - if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) - { - Packet.KeyDesc.Type = WPA2_KEY_DESC; - } - else - { - Packet.KeyDesc.Type = WPA1_KEY_DESC; - } - - // Key descriptor version and appropriate RSN IE - Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer; - - // Update Key Length - Packet.KeyDesc.KeyLength[0] = pGroup->KeyDesc.KeyLength[0]; - Packet.KeyDesc.KeyLength[1] = pGroup->KeyDesc.KeyLength[1]; - - // Key Index as G-Msg 1 - if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) - Packet.KeyDesc.KeyInfo.KeyIndex = peerKeyInfo.KeyIndex; - - // Key Type Group key - Packet.KeyDesc.KeyInfo.KeyType = GROUPKEY; - - // KeyMic field presented - Packet.KeyDesc.KeyInfo.KeyMic = 1; - - // Secure bit - Packet.KeyDesc.KeyInfo.Secure = 1; - - // Convert to little-endian format. - *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); - - // Key Replay count - NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - - // Out buffer for transmitting group message 2 - MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory - if(pOutBuffer == NULL) - { - MlmeFreeMemory(pAd, (PUCHAR)mpool); - return; - } - - // Prepare EAPOL frame for MIC calculation - // Be careful, only EAPOL frame is counted for MIC calculation - MakeOutgoingFrame(pOutBuffer, &FrameLen, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - // Prepare and Fill MIC value - NdisZeroMemory(Mic, sizeof(Mic)); - if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - // AES - HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); - NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); - } - else - { - hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); - } - NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); - - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - LENGTH_802_3, &Header802_3, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - - // 5. Copy frame to Tx ring and prepare for encryption - RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, FALSE); - - // 6 Free allocated memory - MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); - os_free_mem(pAd, (PUCHAR)mpool); - - // send wireless event - for set key done WPA2 - if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - - DBGPRINT(RT_DEBUG_TRACE, ("WpaGroupMsg1Action <-----\n")); -} - -/* - ======================================================================== - - Routine Description: - Init WPA MAC header - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID WpaMacHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PHEADER_802_11 pHdr80211, - IN UCHAR wep, - IN PUCHAR pAddr1) -{ - NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); - pHdr80211->FC.Type = BTYPE_DATA; - pHdr80211->FC.ToDs = 1; - if (wep == 1) - pHdr80211->FC.Wep = 1; - - // Addr1: BSSID, Addr2: SA, Addr3: DA - COPY_MAC_ADDR(pHdr80211->Addr1, pAddr1); - COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); - COPY_MAC_ADDR(pHdr80211->Addr3, pAd->CommonCfg.Bssid); - pHdr80211->Sequence = pAd->Sequence; -} - -/* - ======================================================================== - - Routine Description: - Copy frame from waiting queue into relative ring buffer and set - appropriate ASIC register to kick hardware encryption before really - sent out to air. - - Arguments: - pAd Pointer to our adapter - PNDIS_PACKET Pointer to outgoing Ndis frame - NumberOfFrag Number of fragment required - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID RTMPToWirelessSta( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pHeader802_3, - IN UINT HdrLen, - IN PUCHAR pData, - IN UINT DataLen, - IN BOOLEAN is4wayFrame) - -{ - NDIS_STATUS Status; - PNDIS_PACKET pPacket; - UCHAR Index; - - do - { - // 1. build a NDIS packet and call RTMPSendPacket(); - // be careful about how/when to release this internal allocated NDIS PACKET buffer - Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen); - if (Status != NDIS_STATUS_SUCCESS) - break; - - if (is4wayFrame) - RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1); - else - RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0); - - // 2. send out the packet - Status = STASendPacket(pAd, pPacket); - if(Status == NDIS_STATUS_SUCCESS) - { - // Dequeue one frame from TxSwQueue0..3 queue and process it - // There are three place calling dequeue for TX ring. - // 1. Here, right after queueing the frame. - // 2. At the end of TxRingTxDone service routine. - // 3. Upon NDIS call RTMPSendPackets - if((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) - { - for(Index = 0; Index < 5; Index ++) - if(pAd->TxSwQueue[Index].Number > 0) - RTMPDeQueuePacket(pAd, FALSE, Index, MAX_TX_PROCESS); - } - } - } while(FALSE); - -} - -/* - ======================================================================== - - Routine Description: - Check Sanity RSN IE form AP - - Arguments: - - Return Value: - - - ======================================================================== -*/ -BOOLEAN CheckRSNIE( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN UCHAR DataLen, - OUT UCHAR *Offset) -{ - PUCHAR pVIE; - UCHAR len; - PEID_STRUCT pEid; - BOOLEAN result = FALSE; - - pVIE = pData; - len = DataLen; - *Offset = 0; - - while (len > sizeof(RSNIE2)) - { - pEid = (PEID_STRUCT) pVIE; - // WPA RSN IE - if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) - { - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) && - (NdisEqualMemory(pVIE, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) && - (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == (pEid->Len + 2))) - { - DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> WPA/WPAPSK RSN IE matched in Msg 3, Length(%d) \n", (pEid->Len + 2))); - result = TRUE; - } - - *Offset += (pEid->Len + 2); - } - // WPA2 RSN IE - else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) - { - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) && - (NdisEqualMemory(pVIE, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) && - (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == (pEid->Len + 2))) - { - DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", (pEid->Len + 2))); - result = TRUE; - } - - *Offset += (pEid->Len + 2); - } - else - { - break; - } - - pVIE += (pEid->Len + 2); - len -= (pEid->Len + 2); - } - - DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> skip_offset(%d) \n", *Offset)); - - return result; - -} - - -/* - ======================================================================== - - Routine Description: - Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK. - GTK is encaptulated in KDE format at p.83 802.11i D10 - - Arguments: - - Return Value: - - Note: - 802.11i D10 - - ======================================================================== -*/ -BOOLEAN ParseKeyData( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKeyData, - IN UCHAR KeyDataLen, - IN UCHAR bPairewise) -{ - PKDE_ENCAP pKDE = NULL; - PUCHAR pMyKeyData = pKeyData; - UCHAR KeyDataLength = KeyDataLen; - UCHAR GTKLEN; - UCHAR skip_offset; - - // Verify The RSN IE contained in Pairewise-Msg 3 and skip it - if (bPairewise) - { - // Check RSN IE whether it is WPA2/WPA2PSK - if (!CheckRSNIE(pAd, pKeyData, KeyDataLen, &skip_offset)) - { - DBGPRINT(RT_DEBUG_ERROR, ("ParseKeyData ==> WPA2/WPA2PSK RSN IE mismatched \n")); - hex_dump("Get KEYDATA :", pKeyData, KeyDataLen); - return FALSE; - } - else - { - // skip RSN IE - pMyKeyData += skip_offset; - KeyDataLength -= skip_offset; - - //DBGPRINT(RT_DEBUG_TRACE, ("ParseKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset)); - } - } - - DBGPRINT(RT_DEBUG_TRACE,("ParseKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength)); - - // Parse EKD format - if (KeyDataLength >= 8) - { - pKDE = (PKDE_ENCAP) pMyKeyData; - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KeyDataLength is too short \n")); - return FALSE; - } - - - // Sanity check - shared key index should not be 0 - if (pKDE->GTKEncap.Kid == 0) - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index zero \n")); - return FALSE; - } - - // Sanity check - KED length - if (KeyDataLength < (pKDE->Len + 2)) - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n")); - return FALSE; - } - - // Get GTK length - refer to IEEE 802.11i-2004 p.82 - GTKLEN = pKDE->Len -6; - - if (GTKLEN < LEN_AES_KEY) - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN)); - return FALSE; - } - else - DBGPRINT(RT_DEBUG_TRACE, ("GTK Key with KDE formet got index=%d, len=%d \n", pKDE->GTKEncap.Kid, GTKLEN)); - - // Update GTK - // set key material, TxMic and RxMic for WPAPSK - NdisMoveMemory(pAd->StaCfg.GTK, pKDE->GTKEncap.GTK, 32); - pAd->StaCfg.DefaultKeyId = pKDE->GTKEncap.Kid; - - // Update shared key table - NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY)); - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKDE->GTKEncap.GTK, LEN_TKIP_EK); - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, &pKDE->GTKEncap.GTK[16], LEN_TKIP_RXMICK); - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, &pKDE->GTKEncap.GTK[24], LEN_TKIP_TXMICK); - - // Update Shared Key CipherAlg - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE; - if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES; - else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled) - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP64; - else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled) - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP128; - - return TRUE; - -} - -/* - ======================================================================== - - Routine Description: - Cisco CCKM PRF function - - Arguments: - key Cisco Base Transient Key (BTK) - key_len The key length of the BTK - data Ruquest Number(RN) + BSSID - data_len The length of the data - output Store for PTK(Pairwise transient keys) - len The length of the output - Return Value: - None - - Note: - 802.1i Annex F.9 - - ======================================================================== -*/ -VOID CCKMPRF( - IN UCHAR *key, - IN INT key_len, - IN UCHAR *data, - IN INT data_len, - OUT UCHAR *output, - IN INT len) -{ - INT i; - UCHAR input[1024]; - INT currentindex = 0; - INT total_len; - - NdisMoveMemory(input, data, data_len); - total_len = data_len; - input[total_len] = 0; - total_len++; - for (i = 0; i < (len + 19) / 20; i++) - { - HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]); - currentindex += 20; - input[total_len - 1]++; - } -} +void inc_byte_array(u8 * counter, int len); /* ======================================================================== @@ -1864,189 +58,178 @@ VOID CCKMPRF( ======================================================================== */ -VOID RTMPReportMicError( - IN PRTMP_ADAPTER pAd, - IN PCIPHER_KEY pWpaKey) +void RTMPReportMicError(struct rt_rtmp_adapter *pAd, struct rt_cipher_key *pWpaKey) { - ULONG Now; - UCHAR unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1:0); + unsigned long Now; + u8 unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1 : 0); - // Record Last MIC error time and count - Now = jiffies; - if (pAd->StaCfg.MicErrCnt == 0) - { + /* Record Last MIC error time and count */ + NdisGetSystemUpTime(&Now); + if (pAd->StaCfg.MicErrCnt == 0) { pAd->StaCfg.MicErrCnt++; pAd->StaCfg.LastMicErrorTime = Now; - NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); - } - else if (pAd->StaCfg.MicErrCnt == 1) - { - if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now) - { - // Update Last MIC error time, this did not violate two MIC errors within 60 seconds + NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); + } else if (pAd->StaCfg.MicErrCnt == 1) { + if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now) { + /* Update Last MIC error time, this did not violate two MIC errors within 60 seconds */ pAd->StaCfg.LastMicErrorTime = Now; - } - else - { + } else { if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + RTMPSendWirelessEvent(pAd, + IW_COUNTER_MEASURES_EVENT_FLAG, + pAd->MacTab. + Content[BSSID_WCID].Addr, + BSS0, 0); pAd->StaCfg.LastMicErrorTime = Now; - // Violate MIC error counts, MIC countermeasures kicks in + /* Violate MIC error counts, MIC countermeasures kicks in */ pAd->StaCfg.MicErrCnt++; + /* We shall block all reception */ + /* We shall clean all Tx ring and disassoicate from AP after next EAPOL frame */ + /* */ + /* No necessary to clean all Tx ring, on RTMPHardTransmit will stop sending non-802.1X EAPOL packets */ + /* if pAd->StaCfg.MicErrCnt greater than 2. */ + /* */ + /* RTMPRingCleanUp(pAd, QID_AC_BK); */ + /* RTMPRingCleanUp(pAd, QID_AC_BE); */ + /* RTMPRingCleanUp(pAd, QID_AC_VI); */ + /* RTMPRingCleanUp(pAd, QID_AC_VO); */ + /* RTMPRingCleanUp(pAd, QID_HCCA); */ } - } - else - { - // MIC error count >= 2 - // This should not happen + } else { + /* MIC error count >= 2 */ + /* This should not happen */ ; } - MlmeEnqueue(pAd, - MLME_CNTL_STATE_MACHINE, - OID_802_11_MIC_FAILURE_REPORT_FRAME, - 1, - &unicastKey); - - if (pAd->StaCfg.MicErrCnt == 2) - { - RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100); - } + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_MIC_FAILURE_REPORT_FRAME, 1, &unicastKey); + + if (pAd->StaCfg.MicErrCnt == 2) { + RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100); + } } #define LENGTH_EAP_H 4 -// If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)). -INT WpaCheckEapCode( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pFrame, - IN USHORT FrameLen, - IN USHORT OffSet) +/* If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)). */ +int WpaCheckEapCode(struct rt_rtmp_adapter *pAd, + u8 *pFrame, u16 FrameLen, u16 OffSet) { - PUCHAR pData; - INT result = 0; + u8 *pData; + int result = 0; - if( FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H ) + if (FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H) return result; - pData = pFrame + OffSet; // skip offset bytes + pData = pFrame + OffSet; /* skip offset bytes */ - if(*(pData+1) == EAPPacket) // 802.1x header - Packet Type + if (*(pData + 1) == EAPPacket) /* 802.1x header - Packet Type */ { - result = *(pData+4); // EAP header - Code + result = *(pData + 4); /* EAP header - Code */ } return result; } -VOID WpaSendMicFailureToWpaSupplicant( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bUnicast) +void WpaSendMicFailureToWpaSupplicant(struct rt_rtmp_adapter *pAd, IN BOOLEAN bUnicast) { - union iwreq_data wrqu; - char custom[IW_CUSTOM_MAX] = {0}; + char custom[IW_CUSTOM_MAX] = { 0 }; - sprintf(custom, "MLME-MICHAELMICFAILURE.indication"); - if (bUnicast) - sprintf(custom, "%s unicast", custom); - wrqu.data.length = strlen(custom); - wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom); + sprintf(custom, "MLME-MICHAELMICFAILURE.indication"); + if (bUnicast) + sprintf(custom, "%s unicast", custom); - return; + RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, -1, NULL, (u8 *)custom, + strlen(custom)); + + return; } -VOID WpaMicFailureReportFrame( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) +void WpaMicFailureReportFrame(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { - PUCHAR pOutBuffer = NULL; - UCHAR Header802_3[14]; - ULONG FrameLen = 0; - EAPOL_PACKET Packet; - UCHAR Mic[16]; - BOOLEAN bUnicast; + u8 *pOutBuffer = NULL; + u8 Header802_3[14]; + unsigned long FrameLen = 0; + struct rt_eapol_packet Packet; + u8 Mic[16]; + BOOLEAN bUnicast; DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n")); - bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE); + bUnicast = (Elem->Msg[0] == 1 ? TRUE : FALSE); pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER); - // init 802.3 header and Fill Packet - MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + /* init 802.3 header and Fill Packet */ + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, + pAd->CurrentAddress, EAPOL); NdisZeroMemory(&Packet, sizeof(Packet)); - Packet.ProVer = EAPOL_VER; - Packet.ProType = EAPOLKey; + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; Packet.KeyDesc.Type = WPA1_KEY_DESC; - // Request field presented - Packet.KeyDesc.KeyInfo.Request = 1; + /* Request field presented */ + Packet.KeyDesc.KeyInfo.Request = 1; - if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) { Packet.KeyDesc.KeyInfo.KeyDescVer = 2; - } - else // TKIP + } else /* TKIP */ { Packet.KeyDesc.KeyInfo.KeyDescVer = 1; } - Packet.KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY); - - // KeyMic field presented - Packet.KeyDesc.KeyInfo.KeyMic = 1; + Packet.KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY); - // Error field presented - Packet.KeyDesc.KeyInfo.Error = 1; + /* KeyMic field presented */ + Packet.KeyDesc.KeyInfo.KeyMic = 1; - // Update packet length after decide Key data payload - Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; + /* Error field presented */ + Packet.KeyDesc.KeyInfo.Error = 1; - // Key Replay Count - NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); - inc_byte_array(pAd->StaCfg.ReplayCounter, 8); + /* Update packet length after decide Key data payload */ + SET_u16_TO_ARRARY(Packet.Body_Len, LEN_EAPOL_KEY_MSG) + /* Key Replay Count */ + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, + pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); + inc_byte_array(pAd->StaCfg.ReplayCounter, 8); - // Convert to little-endian format. - *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); + /* Convert to little-endian format. */ + *((u16 *) & Packet.KeyDesc.KeyInfo) = + cpu2le16(*((u16 *) & Packet.KeyDesc.KeyInfo)); - - MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory - if(pOutBuffer == NULL) - { + MlmeAllocateMemory(pAd, (u8 **) & pOutBuffer); /* allocate memory */ + if (pOutBuffer == NULL) { return; } + /* Prepare EAPOL frame for MIC calculation */ + /* Be careful, only EAPOL frame is counted for MIC calculation */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + CONV_ARRARY_TO_u16(Packet.Body_Len) + 4, &Packet, + END_OF_ARGS); - // Prepare EAPOL frame for MIC calculation - // Be careful, only EAPOL frame is counted for MIC calculation - MakeOutgoingFrame(pOutBuffer, &FrameLen, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - // Prepare and Fill MIC value + /* Prepare and Fill MIC value */ NdisZeroMemory(Mic, sizeof(Mic)); - if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { // AES - UCHAR digest[20] = {0}; - HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) { /* AES */ + u8 digest[20] = { 0 }; + HMAC_SHA1(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, + digest, SHA1_DIGEST_SIZE); NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); - } - else - { // TKIP - hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + } else { /* TKIP */ + HMAC_MD5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, + Mic, MD5_DIGEST_SIZE); } NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - LENGTH_802_3, &Header802_3, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - // opy frame to Tx ring and send MIC failure report frame to authenticator - RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, FALSE); + /* copy frame to Tx ring and send MIC failure report frame to authenticator */ + RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], + Header802_3, LENGTH_802_3, + (u8 *)& Packet, + CONV_ARRARY_TO_u16(Packet.Body_Len) + 4, FALSE); - MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + MlmeFreeMemory(pAd, (u8 *)pOutBuffer); DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n")); } @@ -2060,7 +243,7 @@ VOID WpaMicFailureReportFrame( * rolling over to more significant bytes if the byte was incremented from * 0xff to 0x00. */ -void inc_byte_array(UCHAR *counter, int len) +void inc_byte_array(u8 * counter, int len) { int pos = len - 1; while (pos >= 0) { @@ -2071,21 +254,120 @@ void inc_byte_array(UCHAR *counter, int len) } } -VOID WpaDisassocApAndBlockAssoc( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) +void WpaDisassocApAndBlockAssoc(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, + void *SystemSpecific3) { - RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext; - MLME_DISASSOC_REQ_STRUCT DisassocReq; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; + struct rt_mlme_disassoc_req DisassocReq; - // disassoc from current AP first - DBGPRINT(RT_DEBUG_TRACE, ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n")); - DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_MIC_FAILURE); - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + /* disassoc from current AP first */ + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, + REASON_MIC_FAILURE); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof(struct rt_mlme_disassoc_req), &DisassocReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; pAd->StaCfg.bBlockAssoc = TRUE; } +void WpaStaPairwiseKeySetting(struct rt_rtmp_adapter *pAd) +{ + struct rt_cipher_key *pSharedKey; + struct rt_mac_table_entry *pEntry; + + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + + /* Pairwise key shall use key#0 */ + pSharedKey = &pAd->SharedKey[BSS0][0]; + + NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK); + + /* Prepare pair-wise key information into shared key table */ + NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key)); + pSharedKey->KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); + NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48], + LEN_TKIP_RXMICK); + NdisMoveMemory(pSharedKey->TxMic, + &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); + + /* Decide its ChiperAlg */ + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + pSharedKey->CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + pSharedKey->CipherAlg = CIPHER_AES; + else + pSharedKey->CipherAlg = CIPHER_NONE; + + /* Update these related information to struct rt_mac_table_entry */ + NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], + LEN_TKIP_EK); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], + LEN_TKIP_RXMICK); + NdisMoveMemory(pEntry->PairwiseKey.TxMic, + &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); + pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg; + + /* Update pairwise key information to ASIC Shared Key Table */ + AsicAddSharedKeyEntry(pAd, + BSS0, + 0, + pSharedKey->CipherAlg, + pSharedKey->Key, + pSharedKey->TxMic, pSharedKey->RxMic); + + /* Update ASIC WCID attribute table and IVEIV table */ + RTMPAddWcidAttributeEntry(pAd, BSS0, 0, pSharedKey->CipherAlg, pEntry); + STA_PORT_SECURED(pAd); + pAd->IndicateMediaState = NdisMediaStateConnected; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s : AID(%d) port secured\n", __func__, pEntry->Aid)); + +} + +void WpaStaGroupKeySetting(struct rt_rtmp_adapter *pAd) +{ + struct rt_cipher_key *pSharedKey; + + pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId]; + + /* Prepare pair-wise key information into shared key table */ + NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key)); + pSharedKey->KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK); + NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16], + LEN_TKIP_RXMICK); + NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24], + LEN_TKIP_TXMICK); + + /* Update Shared Key CipherAlg */ + pSharedKey->CipherAlg = CIPHER_NONE; + if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) + pSharedKey->CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) + pSharedKey->CipherAlg = CIPHER_AES; + else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled) + pSharedKey->CipherAlg = CIPHER_WEP64; + else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled) + pSharedKey->CipherAlg = CIPHER_WEP128; + + /* Update group key information to ASIC Shared Key Table */ + AsicAddSharedKeyEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pSharedKey->CipherAlg, + pSharedKey->Key, + pSharedKey->TxMic, pSharedKey->RxMic); + + /* Update ASIC WCID attribute table and IVEIV table */ + RTMPAddWcidAttributeEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pSharedKey->CipherAlg, NULL); + +} diff --git a/drivers/staging/rt2860/sta_ioctl.c b/drivers/staging/rt2860/sta_ioctl.c index c0e04251e126f27fedbbd8bad9fcd2acfdf8c036..d8fbe6cc6941af878ba3e5bce442ad93e90d8e53 100644 --- a/drivers/staging/rt2860/sta_ioctl.c +++ b/drivers/staging/rt2860/sta_ioctl.c @@ -40,7 +40,7 @@ #include "rt_config.h" #ifdef DBG -extern ULONG RTDebugLevel; +extern unsigned long RTDebugLevel; #endif #define NR_WEP_KEYS 4 @@ -49,424 +49,310 @@ extern ULONG RTDebugLevel; #define GROUP_KEY_NO 4 -extern UCHAR CipherWpa2Template[]; -extern UCHAR CipherWpaPskTkip[]; -extern UCHAR CipherWpaPskTkipLen; - -typedef struct PACKED _RT_VERSION_INFO{ - UCHAR DriverVersionW; - UCHAR DriverVersionX; - UCHAR DriverVersionY; - UCHAR DriverVersionZ; - UINT DriverBuildYear; - UINT DriverBuildMonth; - UINT DriverBuildDay; -} RT_VERSION_INFO, *PRT_VERSION_INFO; - -struct iw_priv_args privtab[] = { -{ RTPRIV_IOCTL_SET, - IW_PRIV_TYPE_CHAR | 1024, 0, - "set"}, - -{ RTPRIV_IOCTL_SHOW, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, - ""}, -{ RTPRIV_IOCTL_SHOW, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, - ""}, -/* --- sub-ioctls definitions --- */ - { SHOW_CONN_STATUS, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "connStatus" }, - { SHOW_DRVIER_VERION, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "driverVer" }, - { SHOW_BA_INFO, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "bainfo" }, - { SHOW_DESC_INFO, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "descinfo" }, - { RAIO_OFF, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_off" }, - { RAIO_ON, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_on" }, - { SHOW_CFG_VALUE, - IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "show" }, -/* --- sub-ioctls relations --- */ - -{ RTPRIV_IOCTL_STATISTICS, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, - "stat"}, -{ RTPRIV_IOCTL_GSITESURVEY, - 0, IW_PRIV_TYPE_CHAR | 1024, - "get_site_survey"}, -}; - -INT Set_SSID_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg); - -#ifdef WMM_SUPPORT -INT Set_WmmCapable_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); -#endif +extern u8 CipherWpa2Template[]; -INT Set_NetworkType_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg); - -INT Set_AuthMode_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg); - -INT Set_EncrypType_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg); - -INT Set_DefaultKeyID_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg); - -INT Set_Key1_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg); - -INT Set_Key2_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg); - -INT Set_Key3_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg); - -INT Set_Key4_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg); - -INT Set_WPAPSK_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg); - - -INT Set_PSMode_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg); - -INT Set_Wpa_Support( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -NDIS_STATUS RTMPWPANoneAddKeyProc( - IN PRTMP_ADAPTER pAd, - IN PVOID pBuf); - -INT Set_FragTest_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg); - -INT Set_TGnWifiTest_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -INT Set_LongRetryLimit_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg); - -INT Set_ShortRetryLimit_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg); - -static struct { - CHAR *name; - INT (*set_proc)(PRTMP_ADAPTER pAdapter, PUCHAR arg); -} *PRTMP_PRIVATE_SET_PROC, RTMP_PRIVATE_SUPPORT_PROC[] = { - {"DriverVersion", Set_DriverVersion_Proc}, - {"CountryRegion", Set_CountryRegion_Proc}, - {"CountryRegionABand", Set_CountryRegionABand_Proc}, - {"SSID", Set_SSID_Proc}, - {"WirelessMode", Set_WirelessMode_Proc}, - {"TxBurst", Set_TxBurst_Proc}, - {"TxPreamble", Set_TxPreamble_Proc}, - {"TxPower", Set_TxPower_Proc}, - {"Channel", Set_Channel_Proc}, - {"BGProtection", Set_BGProtection_Proc}, - {"RTSThreshold", Set_RTSThreshold_Proc}, - {"FragThreshold", Set_FragThreshold_Proc}, - {"HtBw", Set_HtBw_Proc}, - {"HtMcs", Set_HtMcs_Proc}, - {"HtGi", Set_HtGi_Proc}, - {"HtOpMode", Set_HtOpMode_Proc}, - {"HtExtcha", Set_HtExtcha_Proc}, - {"HtMpduDensity", Set_HtMpduDensity_Proc}, - {"HtBaWinSize", Set_HtBaWinSize_Proc}, - {"HtRdg", Set_HtRdg_Proc}, - {"HtAmsdu", Set_HtAmsdu_Proc}, - {"HtAutoBa", Set_HtAutoBa_Proc}, - {"HtBaDecline", Set_BADecline_Proc}, - {"HtProtect", Set_HtProtect_Proc}, - {"HtMimoPs", Set_HtMimoPs_Proc}, -#ifdef AGGREGATION_SUPPORT - {"PktAggregate", Set_PktAggregate_Proc}, -#endif +struct PACKED rt_version_info { + u8 DriverVersionW; + u8 DriverVersionX; + u8 DriverVersionY; + u8 DriverVersionZ; + u32 DriverBuildYear; + u32 DriverBuildMonth; + u32 DriverBuildDay; +}; -#ifdef WMM_SUPPORT - {"WmmCapable", Set_WmmCapable_Proc}, -#endif - {"IEEE80211H", Set_IEEE80211H_Proc}, - {"NetworkType", Set_NetworkType_Proc}, - {"AuthMode", Set_AuthMode_Proc}, - {"EncrypType", Set_EncrypType_Proc}, - {"DefaultKeyID", Set_DefaultKeyID_Proc}, - {"Key1", Set_Key1_Proc}, - {"Key2", Set_Key2_Proc}, - {"Key3", Set_Key3_Proc}, - {"Key4", Set_Key4_Proc}, - {"WPAPSK", Set_WPAPSK_Proc}, - {"ResetCounter", Set_ResetStatCounter_Proc}, - {"PSMode", Set_PSMode_Proc}, -#ifdef DBG - {"Debug", Set_Debug_Proc}, -#endif - {"WpaSupport", Set_Wpa_Support}, - {"FixedTxMode", Set_FixedTxMode_Proc}, - {"TGnWifiTest", Set_TGnWifiTest_Proc}, - {"ForceGF", Set_ForceGF_Proc}, - {"LongRetry", Set_LongRetryLimit_Proc}, - {"ShortRetry", Set_ShortRetryLimit_Proc}, -#ifdef RT2870 - {"efuseFreeNumber", set_eFuseGetFreeBlockCount_Proc}, - {"efuseDump", set_eFusedump_Proc}, - {"efuseLoadFromBin", set_eFuseLoadFromBin_Proc}, -#endif - {NULL,} +static __s32 ralinkrate[] = { 2, 4, 11, 22, /* CCK */ + 12, 18, 24, 36, 48, 72, 96, 108, /* OFDM */ + 13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, /* 20MHz, 800ns GI, MCS: 0 ~ 15 */ + 39, 78, 117, 156, 234, 312, 351, 390, /* 20MHz, 800ns GI, MCS: 16 ~ 23 */ + 27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, /* 40MHz, 800ns GI, MCS: 0 ~ 15 */ + 81, 162, 243, 324, 486, 648, 729, 810, /* 40MHz, 800ns GI, MCS: 16 ~ 23 */ + 14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, /* 20MHz, 400ns GI, MCS: 0 ~ 15 */ + 43, 87, 130, 173, 260, 317, 390, 433, /* 20MHz, 400ns GI, MCS: 16 ~ 23 */ + 30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, /* 40MHz, 400ns GI, MCS: 0 ~ 15 */ + 90, 180, 270, 360, 540, 720, 810, 900 }; +int Set_SSID_Proc(struct rt_rtmp_adapter *pAdapter, char *arg); -VOID RTMPAddKey( - IN PRTMP_ADAPTER pAd, - IN PNDIS_802_11_KEY pKey) -{ - ULONG KeyIdx; - MAC_TABLE_ENTRY *pEntry; +int Set_NetworkType_Proc(struct rt_rtmp_adapter *pAdapter, char *arg); - DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey ------>\n")); +void RTMPAddKey(struct rt_rtmp_adapter *pAd, struct rt_ndis_802_11_key *pKey) +{ + unsigned long KeyIdx; + struct rt_mac_table_entry *pEntry; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey ------>\n")); + + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) { + if (pKey->KeyIndex & 0x80000000) { + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) { + NdisZeroMemory(pAd->StaCfg.PMK, 32); + NdisMoveMemory(pAd->StaCfg.PMK, + pKey->KeyMaterial, + pKey->KeyLength); + goto end; + } + /* Update PTK */ + NdisZeroMemory(&pAd->SharedKey[BSS0][0], + sizeof(struct rt_cipher_key)); + pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, + pKey->KeyMaterial, LEN_TKIP_EK); + + if (pAd->StaCfg.PairCipher == + Ndis802_11Encryption2Enabled) { + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, + pKey->KeyMaterial + LEN_TKIP_EK, + LEN_TKIP_TXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, + pKey->KeyMaterial + LEN_TKIP_EK + + LEN_TKIP_TXMICK, + LEN_TKIP_RXMICK); + } else { + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, + pKey->KeyMaterial + LEN_TKIP_EK, + LEN_TKIP_TXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, + pKey->KeyMaterial + LEN_TKIP_EK + + LEN_TKIP_TXMICK, + LEN_TKIP_RXMICK); + } -#ifdef RT2860 - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); - if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)) - { - if (pAd->StaCfg.bRadio == FALSE) - { - RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); - return; - } - DBGPRINT(RT_DEBUG_TRACE,("RTMPWPAAddKeyProc1==>\n")); - RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT); - RTMPusecDelay(6000); - pAd->bPCIclkOff = FALSE; - } -#endif + /* Decide its ChiperAlg */ + if (pAd->StaCfg.PairCipher == + Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == + Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + else + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE; + + /* Update these related information to struct rt_mac_table_entry */ + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + NdisMoveMemory(pEntry->PairwiseKey.Key, + pAd->SharedKey[BSS0][0].Key, + LEN_TKIP_EK); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, + pAd->SharedKey[BSS0][0].RxMic, + LEN_TKIP_RXMICK); + NdisMoveMemory(pEntry->PairwiseKey.TxMic, + pAd->SharedKey[BSS0][0].TxMic, + LEN_TKIP_TXMICK); + pEntry->PairwiseKey.CipherAlg = + pAd->SharedKey[BSS0][0].CipherAlg; + + /* Update pairwise key information to ASIC Shared Key Table */ + AsicAddSharedKeyEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pAd->SharedKey[BSS0][0].Key, + pAd->SharedKey[BSS0][0].TxMic, + pAd->SharedKey[BSS0][0].RxMic); + + /* Update ASIC WCID attribute table and IVEIV table */ + RTMPAddWcidAttributeEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0]. + CipherAlg, pEntry); - if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - { - if (pKey->KeyIndex & 0x80000000) - { - if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - { - NdisZeroMemory(pAd->StaCfg.PMK, 32); - NdisMoveMemory(pAd->StaCfg.PMK, pKey->KeyMaterial, pKey->KeyLength); - goto end; - } - // Update PTK - NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); - pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pKey->KeyMaterial, LEN_TKIP_EK); - - if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) - { - NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); - NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); - } - else - { - NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); - NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); - } - - // Decide its ChiperAlg - if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; - else - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE; - - // Update these related information to MAC_TABLE_ENTRY - pEntry = &pAd->MacTab.Content[BSSID_WCID]; - NdisMoveMemory(pEntry->PairwiseKey.Key, pAd->SharedKey[BSS0][0].Key, LEN_TKIP_EK); - NdisMoveMemory(pEntry->PairwiseKey.RxMic, pAd->SharedKey[BSS0][0].RxMic, LEN_TKIP_RXMICK); - NdisMoveMemory(pEntry->PairwiseKey.TxMic, pAd->SharedKey[BSS0][0].TxMic, LEN_TKIP_TXMICK); - pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; - - // Update pairwise key information to ASIC Shared Key Table - AsicAddSharedKeyEntry(pAd, - BSS0, - 0, - pAd->SharedKey[BSS0][0].CipherAlg, - pAd->SharedKey[BSS0][0].Key, - pAd->SharedKey[BSS0][0].TxMic, - pAd->SharedKey[BSS0][0].RxMic); - - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAd, - BSS0, - 0, - pAd->SharedKey[BSS0][0].CipherAlg, - pEntry); - - if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2) - { - // set 802.1x port control + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2) { + /* set 802.1x port control */ + /*pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */ STA_PORT_SECURED(pAd); - // Indicate Connected for GUI - pAd->IndicateMediaState = NdisMediaStateConnected; - } - } - else - { - // Update GTK - pAd->StaCfg.DefaultKeyId = (pKey->KeyIndex & 0xFF); - NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY)); - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKey->KeyMaterial, LEN_TKIP_EK); - - if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) - { - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); - } - else - { - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); - } - - // Update Shared Key CipherAlg - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE; - if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES; - - // Update group key information to ASIC Shared Key Table - AsicAddSharedKeyEntry(pAd, - BSS0, - pAd->StaCfg.DefaultKeyId, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic); - - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAd, - BSS0, - pAd->StaCfg.DefaultKeyId, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, - NULL); - - // set 802.1x port control + /* Indicate Connected for GUI */ + pAd->IndicateMediaState = + NdisMediaStateConnected; + } + } else { + /* Update GTK */ + pAd->StaCfg.DefaultKeyId = (pKey->KeyIndex & 0xFF); + NdisZeroMemory(&pAd-> + SharedKey[BSS0][pAd->StaCfg. + DefaultKeyId], + sizeof(struct rt_cipher_key)); + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = + LEN_TKIP_EK; + NdisMoveMemory(pAd-> + SharedKey[BSS0][pAd->StaCfg. + DefaultKeyId].Key, + pKey->KeyMaterial, LEN_TKIP_EK); + + if (pAd->StaCfg.GroupCipher == + Ndis802_11Encryption2Enabled) { + NdisMoveMemory(pAd-> + SharedKey[BSS0][pAd->StaCfg. + DefaultKeyId]. + RxMic, + pKey->KeyMaterial + LEN_TKIP_EK, + LEN_TKIP_TXMICK); + NdisMoveMemory(pAd-> + SharedKey[BSS0][pAd->StaCfg. + DefaultKeyId]. + TxMic, + pKey->KeyMaterial + LEN_TKIP_EK + + LEN_TKIP_TXMICK, + LEN_TKIP_RXMICK); + } else { + NdisMoveMemory(pAd-> + SharedKey[BSS0][pAd->StaCfg. + DefaultKeyId]. + TxMic, + pKey->KeyMaterial + LEN_TKIP_EK, + LEN_TKIP_TXMICK); + NdisMoveMemory(pAd-> + SharedKey[BSS0][pAd->StaCfg. + DefaultKeyId]. + RxMic, + pKey->KeyMaterial + LEN_TKIP_EK + + LEN_TKIP_TXMICK, + LEN_TKIP_RXMICK); + } + + /* Update Shared Key CipherAlg */ + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId]. + CipherAlg = CIPHER_NONE; + if (pAd->StaCfg.GroupCipher == + Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId]. + CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.GroupCipher == + Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId]. + CipherAlg = CIPHER_AES; + + /* Update group key information to ASIC Shared Key Table */ + AsicAddSharedKeyEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg. + DefaultKeyId]. + CipherAlg, + pAd->SharedKey[BSS0][pAd->StaCfg. + DefaultKeyId]. + Key, + pAd->SharedKey[BSS0][pAd->StaCfg. + DefaultKeyId]. + TxMic, + pAd->SharedKey[BSS0][pAd->StaCfg. + DefaultKeyId]. + RxMic); + + /* Update ASIC WCID attribute table and IVEIV table */ + RTMPAddWcidAttributeEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd-> + StaCfg. + DefaultKeyId]. + CipherAlg, NULL); + + /* set 802.1x port control */ + /*pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */ STA_PORT_SECURED(pAd); - // Indicate Connected for GUI - pAd->IndicateMediaState = NdisMediaStateConnected; - } - } - else // dynamic WEP from wpa_supplicant + /* Indicate Connected for GUI */ + pAd->IndicateMediaState = NdisMediaStateConnected; + } + } else /* dynamic WEP from wpa_supplicant */ { - UCHAR CipherAlg; - PUCHAR Key; + u8 CipherAlg; + u8 *Key; - if(pKey->KeyLength == 32) + if (pKey->KeyLength == 32) goto end; KeyIdx = pKey->KeyIndex & 0x0fffffff; - if (KeyIdx < 4) - { - // it is a default shared key, for Pairwise key setting - if (pKey->KeyIndex & 0x80000000) - { + if (KeyIdx < 4) { + /* it is a default shared key, for Pairwise key setting */ + if (pKey->KeyIndex & 0x80000000) { pEntry = MacTableLookup(pAd, pKey->BSSID); - if (pEntry) - { - DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey: Set Pair-wise Key\n")); + if (pEntry) { + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPAddKey: Set Pair-wise Key\n")); - // set key material and key length - pEntry->PairwiseKey.KeyLen = (UCHAR)pKey->KeyLength; - NdisMoveMemory(pEntry->PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength); + /* set key material and key length */ + pEntry->PairwiseKey.KeyLen = + (u8)pKey->KeyLength; + NdisMoveMemory(pEntry->PairwiseKey.Key, + &pKey->KeyMaterial, + pKey->KeyLength); - // set Cipher type + /* set Cipher type */ if (pKey->KeyLength == 5) - pEntry->PairwiseKey.CipherAlg = CIPHER_WEP64; + pEntry->PairwiseKey.CipherAlg = + CIPHER_WEP64; else - pEntry->PairwiseKey.CipherAlg = CIPHER_WEP128; - - // Add Pair-wise key to Asic - AsicAddPairwiseKeyEntry( - pAd, - pEntry->Addr, - (UCHAR)pEntry->Aid, - &pEntry->PairwiseKey); - - // update WCID attribute table and IVEIV table for this entry - RTMPAddWcidAttributeEntry( - pAd, - BSS0, - KeyIdx, // The value may be not zero - pEntry->PairwiseKey.CipherAlg, - pEntry); + pEntry->PairwiseKey.CipherAlg = + CIPHER_WEP128; + + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry(pAd, + pEntry->Addr, + (u8)pEntry-> + Aid, + &pEntry-> + PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMPAddWcidAttributeEntry(pAd, BSS0, KeyIdx, /* The value may be not zero */ + pEntry-> + PairwiseKey. + CipherAlg, + pEntry); } - } - else - { - // Default key for tx (shared key) - pAd->StaCfg.DefaultKeyId = (UCHAR) KeyIdx; - - // set key material and key length - pAd->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pKey->KeyLength; - NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, &pKey->KeyMaterial, pKey->KeyLength); - - // Set Ciper type + } else { + /* Default key for tx (shared key) */ + pAd->StaCfg.DefaultKeyId = (u8)KeyIdx; + + /* set key material and key length */ + pAd->SharedKey[BSS0][KeyIdx].KeyLen = + (u8)pKey->KeyLength; + NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, + &pKey->KeyMaterial, + pKey->KeyLength); + + /* Set Ciper type */ if (pKey->KeyLength == 5) - pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP64; + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = + CIPHER_WEP64; else - pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP128; + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = + CIPHER_WEP128; - CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; - Key = pAd->SharedKey[BSS0][KeyIdx].Key; + CipherAlg = + pAd->SharedKey[BSS0][KeyIdx].CipherAlg; + Key = pAd->SharedKey[BSS0][KeyIdx].Key; - // Set Group key material to Asic - AsicAddSharedKeyEntry(pAd, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL); + /* Set Group key material to Asic */ + AsicAddSharedKeyEntry(pAd, BSS0, KeyIdx, + CipherAlg, Key, NULL, + NULL); - // Update WCID attribute table and IVEIV table for this group key table - RTMPAddWcidAttributeEntry(pAd, BSS0, KeyIdx, CipherAlg, NULL); + /* Update WCID attribute table and IVEIV table for this group key table */ + RTMPAddWcidAttributeEntry(pAd, BSS0, KeyIdx, + CipherAlg, NULL); } } } end: -#ifdef RT2860 - RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); - DBGPRINT(RT_DEBUG_INFO, ("<------ RTMPAddKey\n")); -#endif return; } -char * rtstrchr(const char * s, int c) +char *rtstrchr(const char *s, int c) { - for(; *s != (char) c; ++s) - if (*s == '\0') - return NULL; - return (char *) s; + for (; *s != (char)c; ++s) + if (*s == '\0') + return NULL; + return (char *)s; } /* @@ -475,159 +361,164 @@ This is required for LinEX2004/kernel2.6.7 to provide iwlist scanning function int rt_ioctl_giwname(struct net_device *dev, - struct iw_request_info *info, - char *name, char *extra) + struct iw_request_info *info, char *name, char *extra) { -// PRTMP_ADAPTER pAdapter = dev->ml_priv; - strncpy(name, RT28xx_CHIP_NAME " Wireless", IFNAMSIZ); + strncpy(name, "Ralink STA", IFNAMSIZ); + /* RT2870 2.1.0.0 uses "RT2870 Wireless" */ + /* RT3090 2.1.0.0 uses "RT2860 Wireless" */ return 0; } int rt_ioctl_siwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) + struct iw_request_info *info, + struct iw_freq *freq, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; - int chan = -1; + struct rt_rtmp_adapter *pAdapter = NULL; + int chan = -1; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } + GET_PAD_FROM_NET_DEV(pAdapter, dev); + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } if (freq->e > 1) return -EINVAL; - if((freq->e == 0) && (freq->m <= 1000)) - chan = freq->m; // Setting by channel number + if ((freq->e == 0) && (freq->m <= 1000)) + chan = freq->m; /* Setting by channel number */ else - MAP_KHZ_TO_CHANNEL_ID( (freq->m /100) , chan); // Setting by frequency - search the table , like 2.412G, 2.422G, - - if (ChannelSanity(pAdapter, chan) == TRUE) - { - pAdapter->CommonCfg.Channel = chan; - DBGPRINT(RT_DEBUG_ERROR, ("==>rt_ioctl_siwfreq::SIOCSIWFREQ[cmd=0x%x] (Channel=%d)\n", SIOCSIWFREQ, pAdapter->CommonCfg.Channel)); - } - else - return -EINVAL; + MAP_KHZ_TO_CHANNEL_ID((freq->m / 100), chan); /* Setting by frequency - search the table , like 2.412G, 2.422G, */ + + if (ChannelSanity(pAdapter, chan) == TRUE) { + pAdapter->CommonCfg.Channel = chan; + DBGPRINT(RT_DEBUG_ERROR, + ("==>rt_ioctl_siwfreq::SIOCSIWFREQ[cmd=0x%x] (Channel=%d)\n", + SIOCSIWFREQ, pAdapter->CommonCfg.Channel)); + } else + return -EINVAL; return 0; } + int rt_ioctl_giwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) + struct iw_request_info *info, + struct iw_freq *freq, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; - UCHAR ch = pAdapter->CommonCfg.Channel; - ULONG m; + struct rt_rtmp_adapter *pAdapter = NULL; + u8 ch; + unsigned long m = 2412000; + + GET_PAD_FROM_NET_DEV(pAdapter, dev); - DBGPRINT(RT_DEBUG_TRACE,("==>rt_ioctl_giwfreq %d\n", ch)); + ch = pAdapter->CommonCfg.Channel; - MAP_CHANNEL_ID_TO_KHZ(ch, m); + DBGPRINT(RT_DEBUG_TRACE, ("==>rt_ioctl_giwfreq %d\n", ch)); + + MAP_CHANNEL_ID_TO_KHZ(ch, m); freq->m = m * 100; freq->e = 1; return 0; } int rt_ioctl_siwmode(struct net_device *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) + struct iw_request_info *info, __u32 * mode, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } + GET_PAD_FROM_NET_DEV(pAdapter, dev); - switch (*mode) - { - case IW_MODE_ADHOC: - Set_NetworkType_Proc(pAdapter, "Adhoc"); - break; - case IW_MODE_INFRA: - Set_NetworkType_Proc(pAdapter, "Infra"); - break; - case IW_MODE_MONITOR: - Set_NetworkType_Proc(pAdapter, "Monitor"); - break; - default: - DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_siwmode::SIOCSIWMODE (unknown %d)\n", *mode)); - return -EINVAL; + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; } - // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key + switch (*mode) { + case IW_MODE_ADHOC: + Set_NetworkType_Proc(pAdapter, "Adhoc"); + break; + case IW_MODE_INFRA: + Set_NetworkType_Proc(pAdapter, "Infra"); + break; + case IW_MODE_MONITOR: + Set_NetworkType_Proc(pAdapter, "Monitor"); + break; + default: + DBGPRINT(RT_DEBUG_TRACE, + ("===>rt_ioctl_siwmode::SIOCSIWMODE (unknown %d)\n", + *mode)); + return -EINVAL; + } + + /* Reset Ralink supplicant to not use, it will be set to start when UI set PMK key */ pAdapter->StaCfg.WpaState = SS_NOTUSE; return 0; } int rt_ioctl_giwmode(struct net_device *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) + struct iw_request_info *info, __u32 * mode, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; + + GET_PAD_FROM_NET_DEV(pAdapter, dev); if (ADHOC_ON(pAdapter)) *mode = IW_MODE_ADHOC; - else if (INFRA_ON(pAdapter)) + else if (INFRA_ON(pAdapter)) *mode = IW_MODE_INFRA; - else if (MONITOR_ON(pAdapter)) - { - *mode = IW_MODE_MONITOR; - } - else - *mode = IW_MODE_AUTO; + else if (MONITOR_ON(pAdapter)) { + *mode = IW_MODE_MONITOR; + } else + *mode = IW_MODE_AUTO; DBGPRINT(RT_DEBUG_TRACE, ("==>rt_ioctl_giwmode(mode=%d)\n", *mode)); return 0; } int rt_ioctl_siwsens(struct net_device *dev, - struct iw_request_info *info, - char *name, char *extra) + struct iw_request_info *info, char *name, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } + GET_PAD_FROM_NET_DEV(pAdapter, dev); + + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } return 0; } int rt_ioctl_giwsens(struct net_device *dev, - struct iw_request_info *info, - char *name, char *extra) + struct iw_request_info *info, char *name, char *extra) { return 0; } int rt_ioctl_giwrange(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) + struct iw_request_info *info, + struct iw_point *data, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; - struct iw_range *range = (struct iw_range *) extra; + struct rt_rtmp_adapter *pAdapter = NULL; + struct iw_range *range = (struct iw_range *)extra; u16 val; int i; - DBGPRINT(RT_DEBUG_TRACE ,("===>rt_ioctl_giwrange\n")); + GET_PAD_FROM_NET_DEV(pAdapter, dev); + + DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_giwrange\n")); data->length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range)); range->txpower_capa = IW_TXPOW_DBM; - if (INFRA_ON(pAdapter)||ADHOC_ON(pAdapter)) - { + if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter)) { range->min_pmp = 1 * 1024; range->max_pmp = 65535 * 1024; range->min_pmt = 1 * 1024; @@ -635,7 +526,7 @@ int rt_ioctl_giwrange(struct net_device *dev, range->pmp_flags = IW_POWER_PERIOD; range->pmt_flags = IW_POWER_TIMEOUT; range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | - IW_POWER_UNICAST_R | IW_POWER_ALL_R; + IW_POWER_UNICAST_R | IW_POWER_ALL_R; } range->we_version_compiled = WIRELESS_EXT; @@ -646,15 +537,14 @@ int rt_ioctl_giwrange(struct net_device *dev, range->min_retry = 0; range->max_retry = 255; - range->num_channels = pAdapter->ChannelListNum; + range->num_channels = pAdapter->ChannelListNum; val = 0; - for (i = 1; i <= range->num_channels; i++) - { - u32 m; - range->freq[val].i = pAdapter->ChannelList[i-1].Channel; - MAP_CHANNEL_ID_TO_KHZ(pAdapter->ChannelList[i-1].Channel, m); - range->freq[val].m = m * 100; /* HZ */ + for (i = 1; i <= range->num_channels; i++) { + u32 m = 2412000; + range->freq[val].i = pAdapter->ChannelList[i - 1].Channel; + MAP_CHANNEL_ID_TO_KHZ(pAdapter->ChannelList[i - 1].Channel, m); + range->freq[val].m = m * 100; /* OS_HZ */ range->freq[val].e = 1; val++; @@ -663,11 +553,11 @@ int rt_ioctl_giwrange(struct net_device *dev, } range->num_frequency = val; - range->max_qual.qual = 100; /* what is correct max? This was not - * documented exactly. At least - * 69 has been observed. */ - range->max_qual.level = 0; /* dB */ - range->max_qual.noise = 0; /* dB */ + range->max_qual.qual = 100; /* what is correct max? This was not + * documented exactly. At least + * 69 has been observed. */ + range->max_qual.level = 0; /* dB */ + range->max_qual.noise = 0; /* dB */ /* What would be suitable values for "average/typical" qual? */ range->avg_qual.qual = 20; @@ -687,70 +577,68 @@ int rt_ioctl_giwrange(struct net_device *dev, /* IW_ENC_CAPA_* bit field */ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; + IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; return 0; } int rt_ioctl_siwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; - NDIS_802_11_MAC_ADDRESS Bssid; + struct rt_rtmp_adapter *pAdapter = NULL; + NDIS_802_11_MAC_ADDRESS Bssid; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) - { - RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); - DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); - } - - // tell CNTL state machine to call NdisMSetInformationComplete() after completing - // this request, because this request is initiated by NDIS. - pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE; - // Prevent to connect AP again in STAMlmePeriodicExec - pAdapter->MlmeAux.AutoReconnectSsidLen= 32; - - memset(Bssid, 0, MAC_ADDR_LEN); - memcpy(Bssid, ap_addr->sa_data, MAC_ADDR_LEN); - MlmeEnqueue(pAdapter, - MLME_CNTL_STATE_MACHINE, - OID_802_11_BSSID, - sizeof(NDIS_802_11_MAC_ADDRESS), - (VOID *)&Bssid); - - DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCSIWAP %02x:%02x:%02x:%02x:%02x:%02x\n", - Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); + GET_PAD_FROM_NET_DEV(pAdapter, dev); + + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) { + RTMP_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, + ("MLME busy, reset MLME state machine!\n")); + } + /* tell CNTL state machine to call NdisMSetInformationComplete() after completing */ + /* this request, because this request is initiated by NDIS. */ + pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE; + /* Prevent to connect AP again in STAMlmePeriodicExec */ + pAdapter->MlmeAux.AutoReconnectSsidLen = 32; + + memset(Bssid, 0, MAC_ADDR_LEN); + memcpy(Bssid, ap_addr->sa_data, MAC_ADDR_LEN); + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID, + sizeof(NDIS_802_11_MAC_ADDRESS), (void *) & Bssid); + + DBGPRINT(RT_DEBUG_TRACE, + ("IOCTL::SIOCSIWAP %02x:%02x:%02x:%02x:%02x:%02x\n", Bssid[0], + Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); return 0; } int rt_ioctl_giwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; - if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter)) - { + GET_PAD_FROM_NET_DEV(pAdapter, dev); + + if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter)) { ap_addr->sa_family = ARPHRD_ETHER; memcpy(ap_addr->sa_data, &pAdapter->CommonCfg.Bssid, ETH_ALEN); } - // Add for RT2870 - else if (pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) - { - ap_addr->sa_family = ARPHRD_ETHER; - memcpy(ap_addr->sa_data, &pAdapter->MlmeAux.Bssid, ETH_ALEN); - } - else - { + /* Add for RT2870 */ + else if (pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) { + ap_addr->sa_family = ARPHRD_ETHER; + memcpy(ap_addr->sa_data, &pAdapter->MlmeAux.Bssid, ETH_ALEN); + } else { DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWAP(=EMPTY)\n")); return -ENOTCONN; } @@ -774,316 +662,317 @@ int rt_ioctl_giwap(struct net_device *dev, * NB: various calculations are based on the orinoco/wavelan * drivers for compatibility */ -static void set_quality(PRTMP_ADAPTER pAdapter, - struct iw_quality *iq, - signed char rssi) +static void set_quality(struct rt_rtmp_adapter *pAdapter, + struct iw_quality *iq, signed char rssi) { __u8 ChannelQuality; - // Normalize Rssi + /* Normalize Rssi */ if (rssi >= -50) ChannelQuality = 100; - else if (rssi >= -80) // between -50 ~ -80dbm - ChannelQuality = (__u8)(24 + ((rssi + 80) * 26)/10); - else if (rssi >= -90) // between -80 ~ -90dbm - ChannelQuality = (__u8)((rssi + 90) * 26)/10; + else if (rssi >= -80) /* between -50 ~ -80dbm */ + ChannelQuality = (__u8) (24 + ((rssi + 80) * 26) / 10); + else if (rssi >= -90) /* between -80 ~ -90dbm */ + ChannelQuality = (__u8) ((rssi + 90) * 26) / 10; else ChannelQuality = 0; - iq->qual = (__u8)ChannelQuality; + iq->qual = (__u8) ChannelQuality; - iq->level = (__u8)(rssi); - iq->noise = (pAdapter->BbpWriteLatch[66] > pAdapter->BbpTuning.FalseCcaUpperThreshold) ? ((__u8)pAdapter->BbpTuning.FalseCcaUpperThreshold) : ((__u8) pAdapter->BbpWriteLatch[66]); // noise level (dBm) - iq->noise += 256 - 143; - iq->updated = pAdapter->iw_stats.qual.updated; + iq->level = (__u8) (rssi); + iq->noise = (pAdapter->BbpWriteLatch[66] > pAdapter->BbpTuning.FalseCcaUpperThreshold) ? ((__u8) pAdapter->BbpTuning.FalseCcaUpperThreshold) : ((__u8) pAdapter->BbpWriteLatch[66]); /* noise level (dBm) */ + iq->noise += 256 - 143; + iq->updated = pAdapter->iw_stats.qual.updated; } int rt_ioctl_iwaplist(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) + struct iw_request_info *info, + struct iw_point *data, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; struct sockaddr addr[IW_MAX_AP]; struct iw_quality qual[IW_MAX_AP]; int i; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + GET_PAD_FROM_NET_DEV(pAdapter, dev); + + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); data->length = 0; return 0; - //return -ENETDOWN; + /*return -ENETDOWN; */ } - for (i = 0; i = pAdapter->ScanTab.BssNr) + for (i = 0; i < IW_MAX_AP; i++) { + if (i >= pAdapter->ScanTab.BssNr) break; addr[i].sa_family = ARPHRD_ETHER; - memcpy(addr[i].sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN); - set_quality(pAdapter, &qual[i], pAdapter->ScanTab.BssEntry[i].Rssi); + memcpy(addr[i].sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, + MAC_ADDR_LEN); + set_quality(pAdapter, &qual[i], + pAdapter->ScanTab.BssEntry[i].Rssi); } data->length = i; - memcpy(extra, &addr, i*sizeof(addr[0])); - data->flags = 1; /* signal quality present (sort of) */ - memcpy(extra + i*sizeof(addr[0]), &qual, i*sizeof(qual[i])); + memcpy(extra, &addr, i * sizeof(addr[0])); + data->flags = 1; /* signal quality present (sort of) */ + memcpy(extra + i * sizeof(addr[0]), &qual, i * sizeof(qual[i])); return 0; } int rt_ioctl_siwscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) + struct iw_request_info *info, + struct iw_point *data, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; - ULONG Now; + unsigned long Now; int Status = NDIS_STATUS_SUCCESS; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { + GET_PAD_FROM_NET_DEV(pAdapter, dev); + + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); return -ENETDOWN; } - if (MONITOR_ON(pAdapter)) - { - DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n")); - return -EINVAL; - } -#ifdef RT2860 - if ((pAdapter->OpMode == OPMODE_STA) && (IDLE_ON(pAdapter)) - && (pAdapter->StaCfg.bRadio == TRUE) - && (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_IDLE_RADIO_OFF))) - { - RT28xxPciAsicRadioOn(pAdapter, GUI_IDLE_POWER_SAVE); + if (MONITOR_ON(pAdapter)) { + DBGPRINT(RT_DEBUG_TRACE, + ("Driver is in Monitor Mode now!\n")); + return -EINVAL; } - // Check if still radio off. - else if (pAdapter->bPCIclkOff == TRUE) - return 0; -#endif - if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) - { + + if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) { pAdapter->StaCfg.WpaSupplicantScanCount++; } - pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE; + pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE; if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - return 0; - do{ + return NDIS_STATUS_SUCCESS; + do { Now = jiffies; - if ((pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) && - (pAdapter->StaCfg.WpaSupplicantScanCount > 3)) - { - DBGPRINT(RT_DEBUG_TRACE, ("!!! WpaSupplicantScanCount > 3\n")); + if ((pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) + && (pAdapter->StaCfg.WpaSupplicantScanCount > 3)) { + DBGPRINT(RT_DEBUG_TRACE, + ("WpaSupplicantScanCount > 3\n")); Status = NDIS_STATUS_SUCCESS; break; } - if ((OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) && - ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || - (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) && - (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) - { - DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); + if ((OPSTATUS_TEST_FLAG + (pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) + && ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA) + || (pAdapter->StaCfg.AuthMode == + Ndis802_11AuthModeWPAPSK)) + && (pAdapter->StaCfg.PortSecured == + WPA_802_1X_PORT_NOT_SECURED)) { + DBGPRINT(RT_DEBUG_TRACE, + ("Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); Status = NDIS_STATUS_SUCCESS; break; } - if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) - { - RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); - DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) { + RTMP_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, + ("MLME busy, reset MLME state machine!\n")); } - - // tell CNTL state machine to call NdisMSetInformationComplete() after completing - // this request, because this request is initiated by NDIS. + /* tell CNTL state machine to call NdisMSetInformationComplete() after completing */ + /* this request, because this request is initiated by NDIS. */ pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE; - // Reset allowed scan retries + /* Reset allowed scan retries */ pAdapter->StaCfg.ScanCnt = 0; pAdapter->StaCfg.LastScanTime = Now; MlmeEnqueue(pAdapter, - MLME_CNTL_STATE_MACHINE, - OID_802_11_BSSID_LIST_SCAN, - 0, - NULL); + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID_LIST_SCAN, 0, NULL); Status = NDIS_STATUS_SUCCESS; - RT28XX_MLME_HANDLER(pAdapter); - }while(0); - return 0; + RTMP_MLME_HANDLER(pAdapter); + } while (0); + return NDIS_STATUS_SUCCESS; } int rt_ioctl_giwscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) + struct iw_request_info *info, + struct iw_point *data, char *extra) { - - PRTMP_ADAPTER pAdapter = dev->ml_priv; - int i=0; + struct rt_rtmp_adapter *pAdapter = NULL; + int i = 0; char *current_ev = extra, *previous_ev = extra; char *end_buf; - char *current_val, custom[MAX_CUSTOM_LEN] = {0}; + char *current_val; + char custom[MAX_CUSTOM_LEN] = { 0 }; struct iw_event iwe; - if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - { + GET_PAD_FROM_NET_DEV(pAdapter, dev); + + if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) { /* * Still scanning, indicate the caller should try again. */ return -EAGAIN; } - if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) - { + if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) { pAdapter->StaCfg.WpaSupplicantScanCount = 0; } - if (pAdapter->ScanTab.BssNr == 0) - { + if (pAdapter->ScanTab.BssNr == 0) { data->length = 0; return 0; } - if (data->length > 0) - end_buf = extra + data->length; - else - end_buf = extra + IW_SCAN_MAX_DATA; + if (data->length > 0) + end_buf = extra + data->length; + else + end_buf = extra + IW_SCAN_MAX_DATA; - for (i = 0; i < pAdapter->ScanTab.BssNr; i++) - { - if (current_ev >= end_buf) + for (i = 0; i < pAdapter->ScanTab.BssNr; i++) { + if (current_ev >= end_buf) { return -E2BIG; - - //MAC address - //================================ + } + /*MAC address */ + /*================================ */ memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, ETH_ALEN); + memcpy(iwe.u.ap_addr.sa_data, + &pAdapter->ScanTab.BssEntry[i].Bssid, ETH_ALEN); - previous_ev = current_ev; - current_ev = iwe_stream_add_event(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN); - if (current_ev == previous_ev) - return -E2BIG; + previous_ev = current_ev; + current_ev = + iwe_stream_add_event(info, current_ev, end_buf, &iwe, + IW_EV_ADDR_LEN); + if (current_ev == previous_ev) + return -E2BIG; /* - Protocol: - it will show scanned AP's WirelessMode . - it might be - 802.11a - 802.11a/n - 802.11g/n - 802.11b/g/n - 802.11g - 802.11b/g - */ + Protocol: + it will show scanned AP's WirelessMode . + it might be + 802.11a + 802.11a/n + 802.11g/n + 802.11b/g/n + 802.11g + 802.11b/g + */ memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWNAME; - - { - PBSS_ENTRY pBssEntry=&pAdapter->ScanTab.BssEntry[i]; - BOOLEAN isGonly=FALSE; - int rateCnt=0; - - if (pBssEntry->Channel>14) - { - if (pBssEntry->HtCapabilityLen!=0) - strcpy(iwe.u.name,"802.11a/n"); - else - strcpy(iwe.u.name,"802.11a"); - } - else { - /* - if one of non B mode rate is set supported rate . it mean G only. - */ - for (rateCnt=0;rateCntSupRateLen;rateCnt++) - { - /* - 6Mbps(140) 9Mbps(146) and >=12Mbps(152) are supported rate , it mean G only. - */ - if (pBssEntry->SupRate[rateCnt]==140 || pBssEntry->SupRate[rateCnt]==146 || pBssEntry->SupRate[rateCnt]>=152) - isGonly=TRUE; - } + struct rt_bss_entry *pBssEntry = &pAdapter->ScanTab.BssEntry[i]; + BOOLEAN isGonly = FALSE; + int rateCnt = 0; - for (rateCnt=0;rateCntExtRateLen;rateCnt++) - { - if (pBssEntry->ExtRate[rateCnt]==140 || pBssEntry->ExtRate[rateCnt]==146 || pBssEntry->ExtRate[rateCnt]>=152) - isGonly=TRUE; - } + if (pBssEntry->Channel > 14) { + if (pBssEntry->HtCapabilityLen != 0) + strcpy(iwe.u.name, "802.11a/n"); + else + strcpy(iwe.u.name, "802.11a"); + } else { + /* + if one of non B mode rate is set supported rate . it mean G only. + */ + for (rateCnt = 0; + rateCnt < pBssEntry->SupRateLen; + rateCnt++) { + /* + 6Mbps(140) 9Mbps(146) and >=12Mbps(152) are supported rate , it mean G only. + */ + if (pBssEntry->SupRate[rateCnt] == 140 + || pBssEntry->SupRate[rateCnt] == + 146 + || pBssEntry->SupRate[rateCnt] >= + 152) + isGonly = TRUE; + } + for (rateCnt = 0; + rateCnt < pBssEntry->ExtRateLen; + rateCnt++) { + if (pBssEntry->ExtRate[rateCnt] == 140 + || pBssEntry->ExtRate[rateCnt] == + 146 + || pBssEntry->ExtRate[rateCnt] >= + 152) + isGonly = TRUE; + } - if (pBssEntry->HtCapabilityLen!=0) - { - if (isGonly==TRUE) - strcpy(iwe.u.name,"802.11g/n"); - else - strcpy(iwe.u.name,"802.11b/g/n"); - } - else - { - if (isGonly==TRUE) - strcpy(iwe.u.name,"802.11g"); - else - { - if (pBssEntry->SupRateLen==4 && pBssEntry->ExtRateLen==0) - strcpy(iwe.u.name,"802.11b"); + if (pBssEntry->HtCapabilityLen != 0) { + if (isGonly == TRUE) + strcpy(iwe.u.name, "802.11g/n"); else - strcpy(iwe.u.name,"802.11b/g"); + strcpy(iwe.u.name, + "802.11b/g/n"); + } else { + if (isGonly == TRUE) + strcpy(iwe.u.name, "802.11g"); + else { + if (pBssEntry->SupRateLen == 4 + && pBssEntry->ExtRateLen == + 0) + strcpy(iwe.u.name, + "802.11b"); + else + strcpy(iwe.u.name, + "802.11b/g"); + } } } } - } previous_ev = current_ev; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); - if (current_ev == previous_ev) - return -E2BIG; + current_ev = + iwe_stream_add_event(info, current_ev, end_buf, &iwe, + IW_EV_ADDR_LEN); + if (current_ev == previous_ev) + return -E2BIG; - //ESSID - //================================ + /*ESSID */ + /*================================ */ memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWESSID; iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].SsidLen; iwe.u.data.flags = 1; - previous_ev = current_ev; - current_ev = iwe_stream_add_point(info, current_ev,end_buf, &iwe, pAdapter->ScanTab.BssEntry[i].Ssid); - if (current_ev == previous_ev) - return -E2BIG; + previous_ev = current_ev; + current_ev = + iwe_stream_add_point(info, current_ev, end_buf, &iwe, + (char *)pAdapter->ScanTab. + BssEntry[i].Ssid); + if (current_ev == previous_ev) + return -E2BIG; - //Network Type - //================================ + /*Network Type */ + /*================================ */ memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWMODE; - if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11IBSS) - { + if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11IBSS) { iwe.u.mode = IW_MODE_ADHOC; - } - else if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11Infrastructure) - { + } else if (pAdapter->ScanTab.BssEntry[i].BssType == + Ndis802_11Infrastructure) { iwe.u.mode = IW_MODE_INFRA; - } - else - { + } else { iwe.u.mode = IW_MODE_AUTO; } iwe.len = IW_EV_UINT_LEN; - previous_ev = current_ev; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN); - if (current_ev == previous_ev) - return -E2BIG; + previous_ev = current_ev; + current_ev = + iwe_stream_add_event(info, current_ev, end_buf, &iwe, + IW_EV_UINT_LEN); + if (current_ev == previous_ev) + return -E2BIG; - //Channel and Frequency - //================================ + /*Channel and Frequency */ + /*================================ */ memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWFREQ; if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter)) @@ -1094,172 +983,217 @@ int rt_ioctl_giwscan(struct net_device *dev, iwe.u.freq.i = 0; previous_ev = current_ev; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); - if (current_ev == previous_ev) - return -E2BIG; - - //Add quality statistics - //================================ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVQUAL; - iwe.u.qual.level = 0; - iwe.u.qual.noise = 0; - set_quality(pAdapter, &iwe.u.qual, pAdapter->ScanTab.BssEntry[i].Rssi); - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); - if (current_ev == previous_ev) - return -E2BIG; - - //Encyption key - //================================ + current_ev = + iwe_stream_add_event(info, current_ev, end_buf, &iwe, + IW_EV_FREQ_LEN); + if (current_ev == previous_ev) + return -E2BIG; + + /*Add quality statistics */ + /*================================ */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVQUAL; + iwe.u.qual.level = 0; + iwe.u.qual.noise = 0; + set_quality(pAdapter, &iwe.u.qual, + pAdapter->ScanTab.BssEntry[i].Rssi); + current_ev = + iwe_stream_add_event(info, current_ev, end_buf, &iwe, + IW_EV_QUAL_LEN); + if (current_ev == previous_ev) + return -E2BIG; + + /*Encyption key */ + /*================================ */ memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWENCODE; - if (CAP_IS_PRIVACY_ON (pAdapter->ScanTab.BssEntry[i].CapabilityInfo )) - iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + if (CAP_IS_PRIVACY_ON + (pAdapter->ScanTab.BssEntry[i].CapabilityInfo)) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; else iwe.u.data.flags = IW_ENCODE_DISABLED; - previous_ev = current_ev; - current_ev = iwe_stream_add_point(info, current_ev, end_buf,&iwe, (char *)pAdapter->SharedKey[BSS0][(iwe.u.data.flags & IW_ENCODE_INDEX)-1].Key); - if (current_ev == previous_ev) - return -E2BIG; + previous_ev = current_ev; + current_ev = + iwe_stream_add_point(info, current_ev, end_buf, &iwe, + (char *)pAdapter-> + SharedKey[BSS0][(iwe.u.data. + flags & + IW_ENCODE_INDEX) - + 1].Key); + if (current_ev == previous_ev) + return -E2BIG; - //Bit Rate - //================================ - if (pAdapter->ScanTab.BssEntry[i].SupRateLen) - { - UCHAR tmpRate = pAdapter->ScanTab.BssEntry[i].SupRate[pAdapter->ScanTab.BssEntry[i].SupRateLen-1]; + /*Bit Rate */ + /*================================ */ + if (pAdapter->ScanTab.BssEntry[i].SupRateLen) { + u8 tmpRate = + pAdapter->ScanTab.BssEntry[i].SupRate[pAdapter-> + ScanTab. + BssEntry[i]. + SupRateLen - + 1]; memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWRATE; - current_val = current_ev + IW_EV_LCP_LEN; - if (tmpRate == 0x82) - iwe.u.bitrate.value = 1 * 1000000; - else if (tmpRate == 0x84) - iwe.u.bitrate.value = 2 * 1000000; - else if (tmpRate == 0x8B) - iwe.u.bitrate.value = 5.5 * 1000000; - else if (tmpRate == 0x96) - iwe.u.bitrate.value = 11 * 1000000; - else - iwe.u.bitrate.value = (tmpRate/2) * 1000000; + current_val = current_ev + IW_EV_LCP_LEN; + if (tmpRate == 0x82) + iwe.u.bitrate.value = 1 * 1000000; + else if (tmpRate == 0x84) + iwe.u.bitrate.value = 2 * 1000000; + else if (tmpRate == 0x8B) + iwe.u.bitrate.value = 5.5 * 1000000; + else if (tmpRate == 0x96) + iwe.u.bitrate.value = 11 * 1000000; + else + iwe.u.bitrate.value = (tmpRate / 2) * 1000000; + + if (tmpRate == 0x6c + && pAdapter->ScanTab.BssEntry[i].HtCapabilityLen > + 0) { + int rate_count = + sizeof(ralinkrate) / sizeof(__s32); + struct rt_ht_cap_info capInfo = + pAdapter->ScanTab.BssEntry[i].HtCapability. + HtCapInfo; + int shortGI = + capInfo.ChannelWidth ? capInfo. + ShortGIfor40 : capInfo.ShortGIfor20; + int maxMCS = + pAdapter->ScanTab.BssEntry[i].HtCapability. + MCSSet[1] ? 15 : 7; + int rate_index = + 12 + ((u8)capInfo.ChannelWidth * 24) + + ((u8)shortGI * 48) + ((u8)maxMCS); + if (rate_index < 0) + rate_index = 0; + if (rate_index > rate_count) + rate_index = rate_count; + iwe.u.bitrate.value = + ralinkrate[rate_index] * 500000; + } iwe.u.bitrate.disabled = 0; current_val = iwe_stream_add_value(info, current_ev, - current_val, end_buf, &iwe, - IW_EV_PARAM_LEN); - - if((current_val-current_ev)>IW_EV_LCP_LEN) - current_ev = current_val; - else - return -E2BIG; - } + current_val, end_buf, + &iwe, + IW_EV_PARAM_LEN); - //WPA IE - if (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen > 0) - { + if ((current_val - current_ev) > IW_EV_LCP_LEN) + current_ev = current_val; + else + return -E2BIG; + } + /*WPA IE */ + if (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen > 0) { memset(&iwe, 0, sizeof(iwe)); memset(&custom[0], 0, MAX_CUSTOM_LEN); - memcpy(custom, &(pAdapter->ScanTab.BssEntry[i].WpaIE.IE[0]), - pAdapter->ScanTab.BssEntry[i].WpaIE.IELen); + memcpy(custom, + &(pAdapter->ScanTab.BssEntry[i].WpaIE.IE[0]), + pAdapter->ScanTab.BssEntry[i].WpaIE.IELen); iwe.cmd = IWEVGENIE; - iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].WpaIE.IELen; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, custom); + iwe.u.data.length = + pAdapter->ScanTab.BssEntry[i].WpaIE.IELen; + current_ev = + iwe_stream_add_point(info, current_ev, end_buf, + &iwe, custom); if (current_ev == previous_ev) return -E2BIG; } - - //WPA2 IE - if (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen > 0) - { - memset(&iwe, 0, sizeof(iwe)); + /*WPA2 IE */ + if (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen > 0) { + memset(&iwe, 0, sizeof(iwe)); memset(&custom[0], 0, MAX_CUSTOM_LEN); - memcpy(custom, &(pAdapter->ScanTab.BssEntry[i].RsnIE.IE[0]), - pAdapter->ScanTab.BssEntry[i].RsnIE.IELen); + memcpy(custom, + &(pAdapter->ScanTab.BssEntry[i].RsnIE.IE[0]), + pAdapter->ScanTab.BssEntry[i].RsnIE.IELen); iwe.cmd = IWEVGENIE; - iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].RsnIE.IELen; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, custom); + iwe.u.data.length = + pAdapter->ScanTab.BssEntry[i].RsnIE.IELen; + current_ev = + iwe_stream_add_point(info, current_ev, end_buf, + &iwe, custom); if (current_ev == previous_ev) return -E2BIG; - } + } } data->length = current_ev - extra; - pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; - DBGPRINT(RT_DEBUG_ERROR ,("===>rt_ioctl_giwscan. %d(%d) BSS returned, data->length = %d\n",i , pAdapter->ScanTab.BssNr, data->length)); + pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; + DBGPRINT(RT_DEBUG_ERROR, + ("===>rt_ioctl_giwscan. %d(%d) BSS returned, data->length = %d\n", + i, pAdapter->ScanTab.BssNr, data->length)); return 0; } int rt_ioctl_siwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *essid) + struct iw_request_info *info, + struct iw_point *data, char *essid) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } + GET_PAD_FROM_NET_DEV(pAdapter, dev); - if (data->flags) - { - PCHAR pSsidString = NULL; + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (data->flags) { + char *pSsidString = NULL; - // Includes null character. + /* Includes null character. */ if (data->length > (IW_ESSID_MAX_SIZE + 1)) return -E2BIG; - pSsidString = (CHAR *) kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG); - if (pSsidString) - { - NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1); + pSsidString = kmalloc(MAX_LEN_OF_SSID + 1, MEM_ALLOC_FLAG); + if (pSsidString) { + NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID + 1); NdisMoveMemory(pSsidString, essid, data->length); if (Set_SSID_Proc(pAdapter, pSsidString) == FALSE) return -EINVAL; - } - else + } else return -ENOMEM; - } - else - { - // ANY ssid + } else { + /* ANY ssid */ if (Set_SSID_Proc(pAdapter, "") == FALSE) return -EINVAL; - } + } return 0; } int rt_ioctl_giwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *essid) + struct iw_request_info *info, + struct iw_point *data, char *essid) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; + + GET_PAD_FROM_NET_DEV(pAdapter, dev); data->flags = 1; - if (MONITOR_ON(pAdapter)) - { - data->length = 0; - return 0; - } + if (MONITOR_ON(pAdapter)) { + data->length = 0; + return 0; + } - if (OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - DBGPRINT(RT_DEBUG_TRACE ,("MediaState is connected\n")); + if (OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) { + DBGPRINT(RT_DEBUG_TRACE, ("MediaState is connected\n")); data->length = pAdapter->CommonCfg.SsidLen; - memcpy(essid, pAdapter->CommonCfg.Ssid, pAdapter->CommonCfg.SsidLen); + memcpy(essid, pAdapter->CommonCfg.Ssid, + pAdapter->CommonCfg.SsidLen); } -#ifdef RT2870 - // Add for RT2870 - else if (pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) - { - data->length = pAdapter->CommonCfg.SsidLen; - memcpy(essid, pAdapter->CommonCfg.Ssid, pAdapter->CommonCfg.SsidLen); +#ifdef RTMP_MAC_USB + /* Add for RT2870 */ + else if (pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) { + data->length = pAdapter->CommonCfg.SsidLen; + memcpy(essid, pAdapter->CommonCfg.Ssid, + pAdapter->CommonCfg.SsidLen); } -#endif // RT2870 // - else - {//the ANY ssid was specified - data->length = 0; - DBGPRINT(RT_DEBUG_TRACE ,("MediaState is not connected, ess\n")); +#endif /* RTMP_MAC_USB // */ + else { /*the ANY ssid was specified */ + data->length = 0; + DBGPRINT(RT_DEBUG_TRACE, + ("MediaState is not connected, ess\n")); } return 0; @@ -1267,17 +1201,18 @@ int rt_ioctl_giwessid(struct net_device *dev, } int rt_ioctl_siwnickn(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *nickname) + struct iw_request_info *info, + struct iw_point *data, char *nickname) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; + + GET_PAD_FROM_NET_DEV(pAdapter, dev); - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE ,("INFO::Network is down!\n")); - return -ENETDOWN; - } + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } if (data->length > IW_ESSID_MAX_SIZE) return -EINVAL; @@ -1285,45 +1220,47 @@ int rt_ioctl_siwnickn(struct net_device *dev, memset(pAdapter->nickname, 0, IW_ESSID_MAX_SIZE + 1); memcpy(pAdapter->nickname, nickname, data->length); - return 0; } int rt_ioctl_giwnickn(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *nickname) + struct iw_request_info *info, + struct iw_point *data, char *nickname) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; + + GET_PAD_FROM_NET_DEV(pAdapter, dev); - if (data->length > strlen(pAdapter->nickname) + 1) - data->length = strlen(pAdapter->nickname) + 1; + if (data->length > strlen((char *)pAdapter->nickname) + 1) + data->length = strlen((char *)pAdapter->nickname) + 1; if (data->length > 0) { - memcpy(nickname, pAdapter->nickname, data->length-1); - nickname[data->length-1] = '\0'; + memcpy(nickname, pAdapter->nickname, data->length - 1); + nickname[data->length - 1] = '\0'; } return 0; } int rt_ioctl_siwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) + struct iw_request_info *info, + struct iw_param *rts, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; u16 val; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } + GET_PAD_FROM_NET_DEV(pAdapter, dev); + + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } if (rts->disabled) val = MAX_RTS_THRESHOLD; else if (rts->value < 0 || rts->value > MAX_RTS_THRESHOLD) return -EINVAL; else if (rts->value == 0) - val = MAX_RTS_THRESHOLD; + val = MAX_RTS_THRESHOLD; else val = rts->value; @@ -1334,17 +1271,18 @@ int rt_ioctl_siwrts(struct net_device *dev, } int rt_ioctl_giwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) + struct iw_request_info *info, + struct iw_param *rts, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; + + GET_PAD_FROM_NET_DEV(pAdapter, dev); - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } rts->value = pAdapter->CommonCfg.RtsThreshold; rts->disabled = (rts->value == MAX_RTS_THRESHOLD); @@ -1354,25 +1292,27 @@ int rt_ioctl_giwrts(struct net_device *dev, } int rt_ioctl_siwfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frag, char *extra) + struct iw_request_info *info, + struct iw_param *frag, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; u16 val; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } + GET_PAD_FROM_NET_DEV(pAdapter, dev); + + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } if (frag->disabled) val = MAX_FRAG_THRESHOLD; - else if (frag->value >= MIN_FRAG_THRESHOLD && frag->value <= MAX_FRAG_THRESHOLD) - val = __cpu_to_le16(frag->value & ~0x1); /* even numbers only */ + else if (frag->value >= MIN_FRAG_THRESHOLD + && frag->value <= MAX_FRAG_THRESHOLD) + val = __cpu_to_le16(frag->value & ~0x1); /* even numbers only */ else if (frag->value == 0) - val = MAX_FRAG_THRESHOLD; + val = MAX_FRAG_THRESHOLD; else return -EINVAL; @@ -1381,17 +1321,18 @@ int rt_ioctl_siwfrag(struct net_device *dev, } int rt_ioctl_giwfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frag, char *extra) + struct iw_request_info *info, + struct iw_param *frag, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } + GET_PAD_FROM_NET_DEV(pAdapter, dev); + + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } frag->value = pAdapter->CommonCfg.FragmentThreshold; frag->disabled = (frag->value == MAX_FRAG_THRESHOLD); @@ -1403,156 +1344,161 @@ int rt_ioctl_giwfrag(struct net_device *dev, #define MAX_WEP_KEY_SIZE 13 #define MIN_WEP_KEY_SIZE 5 int rt_ioctl_siwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *extra) + struct iw_request_info *info, + struct iw_point *erq, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } + GET_PAD_FROM_NET_DEV(pAdapter, dev); - if ((erq->length == 0) && - (erq->flags & IW_ENCODE_DISABLED)) - { + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if ((erq->length == 0) && (erq->flags & IW_ENCODE_DISABLED)) { pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; - goto done; - } else if ( - (erq->flags & IW_ENCODE_RESTRICTED || erq->flags & IW_ENCODE_OPEN)) { + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + goto done; + } else if (erq->flags & IW_ENCODE_RESTRICTED + || erq->flags & IW_ENCODE_OPEN) { + /*pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */ STA_PORT_SECURED(pAdapter); pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled; pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled; pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled; - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; if (erq->flags & IW_ENCODE_RESTRICTED) pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared; - else + else pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; } - if (erq->length > 0) - { + if (erq->length > 0) { int keyIdx = (erq->flags & IW_ENCODE_INDEX) - 1; /* Check the size of the key */ if (erq->length > MAX_WEP_KEY_SIZE) { return -EINVAL; } /* Check key index */ - if ((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS)) - { - DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::Wrong keyIdx=%d! Using default key instead (%d)\n", - keyIdx, pAdapter->StaCfg.DefaultKeyId)); + if ((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS)) { + DBGPRINT(RT_DEBUG_TRACE, + ("==>rt_ioctl_siwencode::Wrong keyIdx=%d! Using default key instead (%d)\n", + keyIdx, pAdapter->StaCfg.DefaultKeyId)); - //Using default key + /*Using default key */ keyIdx = pAdapter->StaCfg.DefaultKeyId; - } - else - pAdapter->StaCfg.DefaultKeyId=keyIdx; - - NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, 16); - - if (erq->length == MAX_WEP_KEY_SIZE) - { - pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE; - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128; - } - else if (erq->length == MIN_WEP_KEY_SIZE) - { - pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE; - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64; - } - else + } else + pAdapter->StaCfg.DefaultKeyId = keyIdx; + + NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, 16); + + if (erq->length == MAX_WEP_KEY_SIZE) { + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = + MAX_WEP_KEY_SIZE; + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = + CIPHER_WEP128; + } else if (erq->length == MIN_WEP_KEY_SIZE) { + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = + MIN_WEP_KEY_SIZE; + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = + CIPHER_WEP64; + } else /* Disable the key */ pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0; /* Check if the key is not marked as invalid */ - if(!(erq->flags & IW_ENCODE_NOKEY)) { + if (!(erq->flags & IW_ENCODE_NOKEY)) { /* Copy the key in the driver */ - NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, extra, erq->length); - } - } - else - { + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, + extra, erq->length); + } + } else { /* Do we want to just set the transmit key index ? */ int index = (erq->flags & IW_ENCODE_INDEX) - 1; - if ((index >= 0) && (index < 4)) - { + if ((index >= 0) && (index < 4)) { pAdapter->StaCfg.DefaultKeyId = index; - } - else + } else /* Don't complain if only change the mode */ - if (!(erq->flags & IW_ENCODE_MODE)) { - return -EINVAL; - } + if (!(erq->flags & IW_ENCODE_MODE)) + return -EINVAL; } done: - DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::erq->flags=%x\n",erq->flags)); - DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::AuthMode=%x\n",pAdapter->StaCfg.AuthMode)); - DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::DefaultKeyId=%x, KeyLen = %d\n",pAdapter->StaCfg.DefaultKeyId , pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen)); - DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::WepStatus=%x\n",pAdapter->StaCfg.WepStatus)); + DBGPRINT(RT_DEBUG_TRACE, + ("==>rt_ioctl_siwencode::erq->flags=%x\n", erq->flags)); + DBGPRINT(RT_DEBUG_TRACE, + ("==>rt_ioctl_siwencode::AuthMode=%x\n", + pAdapter->StaCfg.AuthMode)); + DBGPRINT(RT_DEBUG_TRACE, + ("==>rt_ioctl_siwencode::DefaultKeyId=%x, KeyLen = %d\n", + pAdapter->StaCfg.DefaultKeyId, + pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId]. + KeyLen)); + DBGPRINT(RT_DEBUG_TRACE, + ("==>rt_ioctl_siwencode::WepStatus=%x\n", + pAdapter->StaCfg.WepStatus)); return 0; } int rt_ioctl_giwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *key) + struct iw_request_info *info, + struct iw_point *erq, char *key) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; int kid; + struct rt_rtmp_adapter *pAdapter = NULL; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; + GET_PAD_FROM_NET_DEV(pAdapter, dev); + + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; } kid = erq->flags & IW_ENCODE_INDEX; - DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_giwencode %d\n", erq->flags & IW_ENCODE_INDEX)); + DBGPRINT(RT_DEBUG_TRACE, + ("===>rt_ioctl_giwencode %d\n", erq->flags & IW_ENCODE_INDEX)); - if (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled) - { + if (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled) { erq->length = 0; erq->flags = IW_ENCODE_DISABLED; - } - else if ((kid > 0) && (kid <=4)) - { - // copy wep key - erq->flags = kid ; /* NB: base 1 */ - if (erq->length > pAdapter->SharedKey[BSS0][kid-1].KeyLen) - erq->length = pAdapter->SharedKey[BSS0][kid-1].KeyLen; - memcpy(key, pAdapter->SharedKey[BSS0][kid-1].Key, erq->length); - //if ((kid == pAdapter->PortCfg.DefaultKeyId)) - //erq->flags |= IW_ENCODE_ENABLED; /* XXX */ + } else if ((kid > 0) && (kid <= 4)) { + /* copy wep key */ + erq->flags = kid; /* NB: base 1 */ + if (erq->length > pAdapter->SharedKey[BSS0][kid - 1].KeyLen) + erq->length = pAdapter->SharedKey[BSS0][kid - 1].KeyLen; + memcpy(key, pAdapter->SharedKey[BSS0][kid - 1].Key, + erq->length); + /*if ((kid == pAdapter->PortCfg.DefaultKeyId)) */ + /*erq->flags |= IW_ENCODE_ENABLED; */ /* XXX */ if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) - erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ + erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ else - erq->flags |= IW_ENCODE_OPEN; /* XXX */ + erq->flags |= IW_ENCODE_OPEN; /* XXX */ - } - else if (kid == 0) - { + } else if (kid == 0) { if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) - erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ + erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ else - erq->flags |= IW_ENCODE_OPEN; /* XXX */ - erq->length = pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen; - memcpy(key, pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key, erq->length); - // copy default key ID + erq->flags |= IW_ENCODE_OPEN; /* XXX */ + erq->length = + pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId]. + KeyLen; + memcpy(key, + pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId]. + Key, erq->length); + /* copy default key ID */ if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) - erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ + erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ else - erq->flags |= IW_ENCODE_OPEN; /* XXX */ - erq->flags = pAdapter->StaCfg.DefaultKeyId + 1; /* NB: base 1 */ + erq->flags |= IW_ENCODE_OPEN; /* XXX */ + erq->flags = pAdapter->StaCfg.DefaultKeyId + 1; /* NB: base 1 */ erq->flags |= IW_ENCODE_ENABLED; /* XXX */ } @@ -1560,770 +1506,585 @@ rt_ioctl_giwencode(struct net_device *dev, } -static int -rt_ioctl_setparam(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) +void getBaInfo(struct rt_rtmp_adapter *pAd, char *pOutBuf) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; - POS_COOKIE pObj = (POS_COOKIE)pAdapter->OS_Cookie; - char *this_char = extra; - char *value; - int Status=0; - - { - pObj->ioctl_if_type = INT_MAIN; - pObj->ioctl_if = MAIN_MBSSID; - } - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - if (!*this_char) - return -EINVAL; - - if ((value = rtstrchr(this_char, '=')) != NULL) - *value++ = 0; - - if (!value) - return -EINVAL; - - // reject setting nothing besides ANY ssid(ssidLen=0) - if (!*value && (strcmp(this_char, "SSID") != 0)) - return -EINVAL; - - for (PRTMP_PRIVATE_SET_PROC = RTMP_PRIVATE_SUPPORT_PROC; PRTMP_PRIVATE_SET_PROC->name; PRTMP_PRIVATE_SET_PROC++) - { - if (strcmp(this_char, PRTMP_PRIVATE_SET_PROC->name) == 0) - { - if(!PRTMP_PRIVATE_SET_PROC->set_proc(pAdapter, value)) - { //FALSE:Set private failed then return Invalid argument - Status = -EINVAL; - } - break; //Exit for loop. - } - } - - if(PRTMP_PRIVATE_SET_PROC->name == NULL) - { //Not found argument - Status = -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_setparam:: (iwpriv) Not Support Set Command [%s=%s]\n", this_char, value)); - } - - return Status; -} - - -static int -rt_private_get_statistics(struct net_device *dev, struct iw_request_info *info, - struct iw_point *wrq, char *extra) -{ - INT Status = 0; - PRTMP_ADAPTER pAd = dev->ml_priv; - - if (extra == NULL) - { - wrq->length = 0; - return -EIO; - } - - memset(extra, 0x00, IW_PRIV_SIZE_MASK); - sprintf(extra, "\n\n"); - - { - sprintf(extra+strlen(extra), "Tx success = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.QuadPart); - sprintf(extra+strlen(extra), "Tx success without retry = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.QuadPart - (ULONG)pAd->WlanCounters.RetryCount.QuadPart); - } - sprintf(extra+strlen(extra), "Tx success after retry = %ld\n", (ULONG)pAd->WlanCounters.RetryCount.QuadPart); - sprintf(extra+strlen(extra), "Tx fail to Rcv ACK after retry = %ld\n", (ULONG)pAd->WlanCounters.FailedCount.QuadPart); - sprintf(extra+strlen(extra), "RTS Success Rcv CTS = %ld\n", (ULONG)pAd->WlanCounters.RTSSuccessCount.QuadPart); - sprintf(extra+strlen(extra), "RTS Fail Rcv CTS = %ld\n", (ULONG)pAd->WlanCounters.RTSFailureCount.QuadPart); - - sprintf(extra+strlen(extra), "Rx success = %ld\n", (ULONG)pAd->WlanCounters.ReceivedFragmentCount.QuadPart); - sprintf(extra+strlen(extra), "Rx with CRC = %ld\n", (ULONG)pAd->WlanCounters.FCSErrorCount.QuadPart); - sprintf(extra+strlen(extra), "Rx drop due to out of resource = %ld\n", (ULONG)pAd->Counters8023.RxNoBuffer); - sprintf(extra+strlen(extra), "Rx duplicate frame = %ld\n", (ULONG)pAd->WlanCounters.FrameDuplicateCount.QuadPart); - - sprintf(extra+strlen(extra), "False CCA (one second) = %ld\n", (ULONG)pAd->RalinkCounters.OneSecFalseCCACnt); - { - sprintf(extra+strlen(extra), "RSSI-A = %ld\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi0 - pAd->BbpRssiToDbmDelta)); - sprintf(extra+strlen(extra), "RSSI-B (if available) = %ld\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi1 - pAd->BbpRssiToDbmDelta)); - sprintf(extra+strlen(extra), "RSSI-C (if available) = %ld\n\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi2 - pAd->BbpRssiToDbmDelta)); - } - sprintf(extra+strlen(extra), "WpaSupplicantUP = %d\n\n", pAd->StaCfg.WpaSupplicantUP); - - wrq->length = strlen(extra) + 1; // 1: size of '\0' - DBGPRINT(RT_DEBUG_TRACE, ("<== rt_private_get_statistics, wrq->length = %d\n", wrq->length)); - - return Status; -} - -void getBaInfo( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pOutBuf) -{ - INT i, j; - BA_ORI_ENTRY *pOriBAEntry; - BA_REC_ENTRY *pRecBAEntry; - - for (i=0; iMacTab.Content[i]; - if (((pEntry->ValidAsCLI || pEntry->ValidAsApCli) && (pEntry->Sst == SST_ASSOC)) - || (pEntry->ValidAsWDS) || (pEntry->ValidAsMesh)) - { - sprintf(pOutBuf + strlen(pOutBuf), "\n%02X:%02X:%02X:%02X:%02X:%02X (Aid = %d) (AP) -\n", - pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], - pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5], pEntry->Aid); + int i, j; + struct rt_ba_ori_entry *pOriBAEntry; + struct rt_ba_rec_entry *pRecBAEntry; + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) { + struct rt_mac_table_entry *pEntry = &pAd->MacTab.Content[i]; + if (((pEntry->ValidAsCLI || pEntry->ValidAsApCli) + && (pEntry->Sst == SST_ASSOC)) + || (pEntry->ValidAsWDS) || (pEntry->ValidAsMesh)) { + sprintf(pOutBuf + strlen(pOutBuf), + "\n%02X:%02X:%02X:%02X:%02X:%02X (Aid = %d) (AP) -\n", + pEntry->Addr[0], pEntry->Addr[1], + pEntry->Addr[2], pEntry->Addr[3], + pEntry->Addr[4], pEntry->Addr[5], pEntry->Aid); sprintf(pOutBuf, "%s[Recipient]\n", pOutBuf); - for (j=0; j < NUM_OF_TID; j++) - { - if (pEntry->BARecWcidArray[j] != 0) - { - pRecBAEntry =&pAd->BATable.BARecEntry[pEntry->BARecWcidArray[j]]; - sprintf(pOutBuf + strlen(pOutBuf), "TID=%d, BAWinSize=%d, LastIndSeq=%d, ReorderingPkts=%d\n", j, pRecBAEntry->BAWinSize, pRecBAEntry->LastIndSeq, pRecBAEntry->list.qlen); + for (j = 0; j < NUM_OF_TID; j++) { + if (pEntry->BARecWcidArray[j] != 0) { + pRecBAEntry = + &pAd->BATable.BARecEntry[pEntry-> + BARecWcidArray + [j]]; + sprintf(pOutBuf + strlen(pOutBuf), + "TID=%d, BAWinSize=%d, LastIndSeq=%d, ReorderingPkts=%d\n", + j, pRecBAEntry->BAWinSize, + pRecBAEntry->LastIndSeq, + pRecBAEntry->list.qlen); } } sprintf(pOutBuf, "%s\n", pOutBuf); sprintf(pOutBuf, "%s[Originator]\n", pOutBuf); - for (j=0; j < NUM_OF_TID; j++) - { - if (pEntry->BAOriWcidArray[j] != 0) - { - pOriBAEntry =&pAd->BATable.BAOriEntry[pEntry->BAOriWcidArray[j]]; - sprintf(pOutBuf + strlen(pOutBuf), "TID=%d, BAWinSize=%d, StartSeq=%d, CurTxSeq=%d\n", j, pOriBAEntry->BAWinSize, pOriBAEntry->Sequence, pEntry->TxSeq[j]); + for (j = 0; j < NUM_OF_TID; j++) { + if (pEntry->BAOriWcidArray[j] != 0) { + pOriBAEntry = + &pAd->BATable.BAOriEntry[pEntry-> + BAOriWcidArray + [j]]; + sprintf(pOutBuf + strlen(pOutBuf), + "TID=%d, BAWinSize=%d, StartSeq=%d, CurTxSeq=%d\n", + j, pOriBAEntry->BAWinSize, + pOriBAEntry->Sequence, + pEntry->TxSeq[j]); } } sprintf(pOutBuf, "%s\n\n", pOutBuf); } - if (strlen(pOutBuf) > (IW_PRIV_SIZE_MASK - 30)) - break; + if (strlen(pOutBuf) > (IW_PRIV_SIZE_MASK - 30)) + break; } return; } -static int -rt_private_show(struct net_device *dev, struct iw_request_info *info, - struct iw_point *wrq, char *extra) -{ - INT Status = 0; - PRTMP_ADAPTER pAd = dev->ml_priv; - POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; - u32 subcmd = wrq->flags; - - if (extra == NULL) - { - wrq->length = 0; - return -EIO; - } - memset(extra, 0x00, IW_PRIV_SIZE_MASK); - - { - pObj->ioctl_if_type = INT_MAIN; - pObj->ioctl_if = MAIN_MBSSID; - } - - switch(subcmd) - { - - case SHOW_CONN_STATUS: - if (MONITOR_ON(pAd)) - { - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && - pAd->CommonCfg.RegTransmitSetting.field.BW) - sprintf(extra, "Monitor Mode(CentralChannel %d)\n", pAd->CommonCfg.CentralChannel); - else - sprintf(extra, "Monitor Mode(Channel %d)\n", pAd->CommonCfg.Channel); - } - else - { - if (pAd->IndicateMediaState == NdisMediaStateConnected) - { - if (INFRA_ON(pAd)) - { - sprintf(extra, "Connected(AP: %s[%02X:%02X:%02X:%02X:%02X:%02X])\n", - pAd->CommonCfg.Ssid, - pAd->CommonCfg.Bssid[0], - pAd->CommonCfg.Bssid[1], - pAd->CommonCfg.Bssid[2], - pAd->CommonCfg.Bssid[3], - pAd->CommonCfg.Bssid[4], - pAd->CommonCfg.Bssid[5]); - DBGPRINT(RT_DEBUG_TRACE ,("Ssid=%s ,Ssidlen = %d\n",pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)); - } - else if (ADHOC_ON(pAd)) - sprintf(extra, "Connected\n"); - } - else - { - sprintf(extra, "Disconnected\n"); - DBGPRINT(RT_DEBUG_TRACE ,("ConnStatus is not connected\n")); - } - } - wrq->length = strlen(extra) + 1; // 1: size of '\0' - break; - case SHOW_DRVIER_VERION: - sprintf(extra, "Driver version-%s, %s %s\n", STA_DRIVER_VERSION, __DATE__, __TIME__ ); - wrq->length = strlen(extra) + 1; // 1: size of '\0' - break; - case SHOW_BA_INFO: - getBaInfo(pAd, extra); - wrq->length = strlen(extra) + 1; // 1: size of '\0' - break; - case SHOW_DESC_INFO: - { - Show_DescInfo_Proc(pAd, NULL); - wrq->length = 0; // 1: size of '\0' - } - break; - case RAIO_OFF: - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - { - sprintf(extra, "Scanning\n"); - wrq->length = strlen(extra) + 1; // 1: size of '\0' - break; - } - pAd->StaCfg.bSwRadio = FALSE; - if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) - { - pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); - if (pAd->StaCfg.bRadio == FALSE) - { - MlmeRadioOff(pAd); - // Update extra information - pAd->ExtraInfo = SW_RADIO_OFF; - } - } - sprintf(extra, "Radio Off\n"); - wrq->length = strlen(extra) + 1; // 1: size of '\0' - break; - case RAIO_ON: -#ifdef RT2870 - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - { - sprintf(extra, "Scanning\n"); - wrq->length = strlen(extra) + 1; // 1: size of '\0' - break; - } -#endif - pAd->StaCfg.bSwRadio = TRUE; - //if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) - { - pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); - if (pAd->StaCfg.bRadio == TRUE) - { - MlmeRadioOn(pAd); - // Update extra information - pAd->ExtraInfo = EXTRA_INFO_CLEAR; - } - } - sprintf(extra, "Radio On\n"); - wrq->length = strlen(extra) + 1; // 1: size of '\0' - break; - - case SHOW_CFG_VALUE: - { - Status = RTMPShowCfgValue(pAd, wrq->pointer, extra); - if (Status == 0) - wrq->length = strlen(extra) + 1; // 1: size of '\0' - } - break; - default: - DBGPRINT(RT_DEBUG_TRACE, ("%s - unknow subcmd = %d\n", __func__, subcmd)); - break; - } - - return Status; -} - int rt_ioctl_siwmlme(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { - PRTMP_ADAPTER pAd = dev->ml_priv; + struct rt_rtmp_adapter *pAd = NULL; struct iw_mlme *pMlme = (struct iw_mlme *)wrqu->data.pointer; - MLME_QUEUE_ELEM MsgElem; - MLME_DISASSOC_REQ_STRUCT DisAssocReq; - MLME_DEAUTH_REQ_STRUCT DeAuthReq; + struct rt_mlme_queue_elem MsgElem; + struct rt_mlme_disassoc_req DisAssocReq; + struct rt_mlme_deauth_req DeAuthReq; + + GET_PAD_FROM_NET_DEV(pAd, dev); DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __func__)); if (pMlme == NULL) return -EINVAL; - switch(pMlme->cmd) - { + switch (pMlme->cmd) { #ifdef IW_MLME_DEAUTH - case IW_MLME_DEAUTH: - DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DEAUTH\n", __func__)); - COPY_MAC_ADDR(DeAuthReq.Addr, pAd->CommonCfg.Bssid); - DeAuthReq.Reason = pMlme->reason_code; - MsgElem.MsgLen = sizeof(MLME_DEAUTH_REQ_STRUCT); - NdisMoveMemory(MsgElem.Msg, &DeAuthReq, sizeof(MLME_DEAUTH_REQ_STRUCT)); - MlmeDeauthReqAction(pAd, &MsgElem); - if (INFRA_ON(pAd)) - { - LinkDown(pAd, FALSE); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - } - break; -#endif // IW_MLME_DEAUTH // + case IW_MLME_DEAUTH: + DBGPRINT(RT_DEBUG_TRACE, + ("====> %s - IW_MLME_DEAUTH\n", __func__)); + COPY_MAC_ADDR(DeAuthReq.Addr, pAd->CommonCfg.Bssid); + DeAuthReq.Reason = pMlme->reason_code; + MsgElem.MsgLen = sizeof(struct rt_mlme_deauth_req); + NdisMoveMemory(MsgElem.Msg, &DeAuthReq, + sizeof(struct rt_mlme_deauth_req)); + MlmeDeauthReqAction(pAd, &MsgElem); + if (INFRA_ON(pAd)) { + LinkDown(pAd, FALSE); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + } + break; +#endif /* IW_MLME_DEAUTH // */ #ifdef IW_MLME_DISASSOC - case IW_MLME_DISASSOC: - DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DISASSOC\n", __func__)); - COPY_MAC_ADDR(DisAssocReq.Addr, pAd->CommonCfg.Bssid); - DisAssocReq.Reason = pMlme->reason_code; - - MsgElem.Machine = ASSOC_STATE_MACHINE; - MsgElem.MsgType = MT2_MLME_DISASSOC_REQ; - MsgElem.MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); - NdisMoveMemory(MsgElem.Msg, &DisAssocReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); - - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; - MlmeDisassocReqAction(pAd, &MsgElem); - break; -#endif // IW_MLME_DISASSOC // - default: - DBGPRINT(RT_DEBUG_TRACE, ("====> %s - Unknow Command\n", __func__)); - break; + case IW_MLME_DISASSOC: + DBGPRINT(RT_DEBUG_TRACE, + ("====> %s - IW_MLME_DISASSOC\n", __func__)); + COPY_MAC_ADDR(DisAssocReq.Addr, pAd->CommonCfg.Bssid); + DisAssocReq.Reason = pMlme->reason_code; + + MsgElem.Machine = ASSOC_STATE_MACHINE; + MsgElem.MsgType = MT2_MLME_DISASSOC_REQ; + MsgElem.MsgLen = sizeof(struct rt_mlme_disassoc_req); + NdisMoveMemory(MsgElem.Msg, &DisAssocReq, + sizeof(struct rt_mlme_disassoc_req)); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; + MlmeDisassocReqAction(pAd, &MsgElem); + break; +#endif /* IW_MLME_DISASSOC // */ + default: + DBGPRINT(RT_DEBUG_TRACE, + ("====> %s - Unknow Command\n", __func__)); + break; } return 0; } int rt_ioctl_siwauth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; struct iw_param *param = &wrqu->param; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; + GET_PAD_FROM_NET_DEV(pAdapter, dev); + + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; } switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - if (param->value == IW_AUTH_WPA_VERSION_WPA) - { - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; - if (pAdapter->StaCfg.BssType == BSS_ADHOC) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; - } - else if (param->value == IW_AUTH_WPA_VERSION_WPA2) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; - - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __func__, param->value)); - break; - case IW_AUTH_CIPHER_PAIRWISE: - if (param->value == IW_AUTH_CIPHER_NONE) - { - pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; - pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; - } - else if (param->value == IW_AUTH_CIPHER_WEP40 || - param->value == IW_AUTH_CIPHER_WEP104) - { - pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled; - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; - pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled; - pAdapter->StaCfg.IEEE8021X = FALSE; - } - else if (param->value == IW_AUTH_CIPHER_TKIP) - { - pAdapter->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; - pAdapter->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; - } - else if (param->value == IW_AUTH_CIPHER_CCMP) - { - pAdapter->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; - pAdapter->StaCfg.PairCipher = Ndis802_11Encryption3Enabled; - } - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_PAIRWISE - param->value = %d!\n", __func__, param->value)); - break; - case IW_AUTH_CIPHER_GROUP: - if (param->value == IW_AUTH_CIPHER_NONE) - { - pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; - } - else if (param->value == IW_AUTH_CIPHER_WEP40 || - param->value == IW_AUTH_CIPHER_WEP104) - { - pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled; - } - else if (param->value == IW_AUTH_CIPHER_TKIP) - { - pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption2Enabled; - } - else if (param->value == IW_AUTH_CIPHER_CCMP) - { - pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption3Enabled; - } - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_GROUP - param->value = %d!\n", __func__, param->value)); - break; - case IW_AUTH_KEY_MGMT: - if (param->value == IW_AUTH_KEY_MGMT_802_1X) - { - if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) - { - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA; - pAdapter->StaCfg.IEEE8021X = FALSE; - } - else if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) - { - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; - pAdapter->StaCfg.IEEE8021X = FALSE; - } - else - // WEP 1x - pAdapter->StaCfg.IEEE8021X = TRUE; - } - else if (param->value == 0) - { - STA_PORT_SECURED(pAdapter); - } - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_KEY_MGMT - param->value = %d!\n", __func__, param->value)); - break; - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - break; - case IW_AUTH_PRIVACY_INVOKED: - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_PRIVACY_INVOKED - param->value = %d!\n", __func__, param->value)); - break; - case IW_AUTH_DROP_UNENCRYPTED: - if (param->value != 0) - pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - else - { - STA_PORT_SECURED(pAdapter); - } - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __func__, param->value)); - break; - case IW_AUTH_80211_AUTH_ALG: - if (param->value & IW_AUTH_ALG_SHARED_KEY) - { - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared; - } - else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) - { - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; - } - else - return -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_80211_AUTH_ALG - param->value = %d!\n", __func__, param->value)); - break; - case IW_AUTH_WPA_ENABLED: - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_ENABLED - Driver supports WPA!(param->value = %d)\n", __func__, param->value)); - break; - default: - return -EOPNOTSUPP; -} + case IW_AUTH_WPA_VERSION: + if (param->value == IW_AUTH_WPA_VERSION_WPA) { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; + if (pAdapter->StaCfg.BssType == BSS_ADHOC) + pAdapter->StaCfg.AuthMode = + Ndis802_11AuthModeWPANone; + } else if (param->value == IW_AUTH_WPA_VERSION_WPA2) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", + __func__, param->value)); + break; + case IW_AUTH_CIPHER_PAIRWISE: + if (param->value == IW_AUTH_CIPHER_NONE) { + pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; + pAdapter->StaCfg.OrigWepStatus = + pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; + } else if (param->value == IW_AUTH_CIPHER_WEP40 || + param->value == IW_AUTH_CIPHER_WEP104) { + pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled; + pAdapter->StaCfg.OrigWepStatus = + pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled; + pAdapter->StaCfg.IEEE8021X = FALSE; + } else if (param->value == IW_AUTH_CIPHER_TKIP) { + pAdapter->StaCfg.WepStatus = + Ndis802_11Encryption2Enabled; + pAdapter->StaCfg.OrigWepStatus = + pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.PairCipher = + Ndis802_11Encryption2Enabled; + } else if (param->value == IW_AUTH_CIPHER_CCMP) { + pAdapter->StaCfg.WepStatus = + Ndis802_11Encryption3Enabled; + pAdapter->StaCfg.OrigWepStatus = + pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.PairCipher = + Ndis802_11Encryption3Enabled; + } + DBGPRINT(RT_DEBUG_TRACE, + ("%s::IW_AUTH_CIPHER_PAIRWISE - param->value = %d!\n", + __func__, param->value)); + break; + case IW_AUTH_CIPHER_GROUP: + if (param->value == IW_AUTH_CIPHER_NONE) { + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + } else if (param->value == IW_AUTH_CIPHER_WEP40 || + param->value == IW_AUTH_CIPHER_WEP104) { + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled; + } else if (param->value == IW_AUTH_CIPHER_TKIP) { + pAdapter->StaCfg.GroupCipher = + Ndis802_11Encryption2Enabled; + } else if (param->value == IW_AUTH_CIPHER_CCMP) { + pAdapter->StaCfg.GroupCipher = + Ndis802_11Encryption3Enabled; + } + DBGPRINT(RT_DEBUG_TRACE, + ("%s::IW_AUTH_CIPHER_GROUP - param->value = %d!\n", + __func__, param->value)); + break; + case IW_AUTH_KEY_MGMT: + if (param->value == IW_AUTH_KEY_MGMT_802_1X) { + if (pAdapter->StaCfg.AuthMode == + Ndis802_11AuthModeWPAPSK) { + pAdapter->StaCfg.AuthMode = + Ndis802_11AuthModeWPA; + pAdapter->StaCfg.IEEE8021X = FALSE; + } else if (pAdapter->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2PSK) { + pAdapter->StaCfg.AuthMode = + Ndis802_11AuthModeWPA2; + pAdapter->StaCfg.IEEE8021X = FALSE; + } else + /* WEP 1x */ + pAdapter->StaCfg.IEEE8021X = TRUE; + } else if (param->value == 0) { + /*pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */ + STA_PORT_SECURED(pAdapter); + } + DBGPRINT(RT_DEBUG_TRACE, + ("%s::IW_AUTH_KEY_MGMT - param->value = %d!\n", + __func__, param->value)); + break; + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + break; + case IW_AUTH_PRIVACY_INVOKED: + /*if (param->value == 0) + { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + } */ + DBGPRINT(RT_DEBUG_TRACE, + ("%s::IW_AUTH_PRIVACY_INVOKED - param->value = %d!\n", + __func__, param->value)); + break; + case IW_AUTH_DROP_UNENCRYPTED: + if (param->value != 0) + pAdapter->StaCfg.PortSecured = + WPA_802_1X_PORT_NOT_SECURED; + else { + /*pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */ + STA_PORT_SECURED(pAdapter); + } + DBGPRINT(RT_DEBUG_TRACE, + ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", + __func__, param->value)); + break; + case IW_AUTH_80211_AUTH_ALG: + if (param->value & IW_AUTH_ALG_SHARED_KEY) { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared; + } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + } else + return -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, + ("%s::IW_AUTH_80211_AUTH_ALG - param->value = %d!\n", + __func__, param->value)); + break; + case IW_AUTH_WPA_ENABLED: + DBGPRINT(RT_DEBUG_TRACE, + ("%s::IW_AUTH_WPA_ENABLED - Driver supports WPA!(param->value = %d)\n", + __func__, param->value)); + break; + default: + return -EOPNOTSUPP; + } return 0; } int rt_ioctl_giwauth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct rt_rtmp_adapter *pAdapter = NULL; struct iw_param *param = &wrqu->param; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } + GET_PAD_FROM_NET_DEV(pAdapter, dev); + + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } switch (param->flags & IW_AUTH_INDEX) { case IW_AUTH_DROP_UNENCRYPTED: - param->value = (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled) ? 0 : 1; + param->value = + (pAdapter->StaCfg.WepStatus == + Ndis802_11WEPDisabled) ? 0 : 1; break; case IW_AUTH_80211_AUTH_ALG: - param->value = (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) ? IW_AUTH_ALG_SHARED_KEY : IW_AUTH_ALG_OPEN_SYSTEM; + param->value = + (pAdapter->StaCfg.AuthMode == + Ndis802_11AuthModeShared) ? IW_AUTH_ALG_SHARED_KEY : + IW_AUTH_ALG_OPEN_SYSTEM; break; case IW_AUTH_WPA_ENABLED: - param->value = (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) ? 1 : 0; + param->value = + (pAdapter->StaCfg.AuthMode >= + Ndis802_11AuthModeWPA) ? 1 : 0; break; default: return -EOPNOTSUPP; } - DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_giwauth::param->value = %d!\n", param->value)); + DBGPRINT(RT_DEBUG_TRACE, + ("rt_ioctl_giwauth::param->value = %d!\n", param->value)); return 0; } -void fnSetCipherKey( - IN PRTMP_ADAPTER pAdapter, - IN INT keyIdx, - IN UCHAR CipherAlg, - IN BOOLEAN bGTK, - IN struct iw_encode_ext *ext) +void fnSetCipherKey(struct rt_rtmp_adapter *pAdapter, + int keyIdx, + u8 CipherAlg, + IN BOOLEAN bGTK, IN struct iw_encode_ext *ext) { -#ifdef RT2860 - RTMP_CLEAR_PSFLAG(pAdapter, fRTMP_PS_CAN_GO_SLEEP); - if (RTMP_TEST_PSFLAG(pAdapter, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)) - { - if (pAdapter->StaCfg.bRadio == FALSE) - { - RTMP_SET_PSFLAG(pAdapter, fRTMP_PS_CAN_GO_SLEEP); - return; - } - DBGPRINT(RT_DEBUG_TRACE,("RTMPWPAAddKeyProc1==>\n")); - RTMPPCIeLinkCtrlValueRestore(pAdapter, RESTORE_HALT); - RTMPusecDelay(6000); - pAdapter->bPCIclkOff = FALSE; - } -#endif - NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY)); - pAdapter->SharedKey[BSS0][keyIdx].KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, LEN_TKIP_EK); - NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].TxMic, ext->key + LEN_TKIP_EK, LEN_TKIP_TXMICK); - NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].RxMic, ext->key + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CipherAlg; - - // Update group key information to ASIC Shared Key Table + NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(struct rt_cipher_key)); + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, + LEN_TKIP_EK); + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].TxMic, + ext->key + LEN_TKIP_EK, LEN_TKIP_TXMICK); + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].RxMic, + ext->key + LEN_TKIP_EK + LEN_TKIP_TXMICK, + LEN_TKIP_RXMICK); + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CipherAlg; + + /* Update group key information to ASIC Shared Key Table */ AsicAddSharedKeyEntry(pAdapter, - BSS0, - keyIdx, - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, - pAdapter->SharedKey[BSS0][keyIdx].Key, - pAdapter->SharedKey[BSS0][keyIdx].TxMic, - pAdapter->SharedKey[BSS0][keyIdx].RxMic); - - if (bGTK) - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAdapter, - BSS0, - keyIdx, - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, - NULL); - else - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAdapter, - BSS0, - keyIdx, - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, - &pAdapter->MacTab.Content[BSSID_WCID]); -#ifdef RT2860 - RTMP_SET_PSFLAG(pAdapter, fRTMP_PS_CAN_GO_SLEEP); -#endif + BSS0, + keyIdx, + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, + pAdapter->SharedKey[BSS0][keyIdx].Key, + pAdapter->SharedKey[BSS0][keyIdx].TxMic, + pAdapter->SharedKey[BSS0][keyIdx].RxMic); + + if (bGTK) + /* Update ASIC WCID attribute table and IVEIV table */ + RTMPAddWcidAttributeEntry(pAdapter, + BSS0, + keyIdx, + pAdapter->SharedKey[BSS0][keyIdx]. + CipherAlg, NULL); + else + /* Update ASIC WCID attribute table and IVEIV table */ + RTMPAddWcidAttributeEntry(pAdapter, + BSS0, + keyIdx, + pAdapter->SharedKey[BSS0][keyIdx]. + CipherAlg, + &pAdapter->MacTab. + Content[BSSID_WCID]); } int rt_ioctl_siwencodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) - { - PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct rt_rtmp_adapter *pAdapter = NULL; struct iw_point *encoding = &wrqu->encoding; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int keyIdx, alg = ext->alg; + int keyIdx, alg = ext->alg; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; + GET_PAD_FROM_NET_DEV(pAdapter, dev); + + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; } - if (encoding->flags & IW_ENCODE_DISABLED) - { - keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1; - // set BSSID wcid entry of the Pair-wise Key table as no-security mode - AsicRemovePairwiseKeyEntry(pAdapter, BSS0, BSSID_WCID); - pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0; + if (encoding->flags & IW_ENCODE_DISABLED) { + keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1; + /* set BSSID wcid entry of the Pair-wise Key table as no-security mode */ + AsicRemovePairwiseKeyEntry(pAdapter, BSS0, BSSID_WCID); + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0; pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_NONE; - AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)keyIdx); - NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY)); - DBGPRINT(RT_DEBUG_TRACE, ("%s::Remove all keys!(encoding->flags = %x)\n", __func__, encoding->flags)); - } - else - { - // Get Key Index and convet to our own defined key index - keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1; - if((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS)) - return -EINVAL; - - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) - { - pAdapter->StaCfg.DefaultKeyId = keyIdx; - DBGPRINT(RT_DEBUG_TRACE, ("%s::DefaultKeyId = %d\n", __func__, pAdapter->StaCfg.DefaultKeyId)); - } - - switch (alg) { - case IW_ENCODE_ALG_NONE: - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_NONE\n", __func__)); - break; - case IW_ENCODE_ALG_WEP: - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_WEP - ext->key_len = %d, keyIdx = %d\n", __func__, ext->key_len, keyIdx)); - if (ext->key_len == MAX_WEP_KEY_SIZE) - { - pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE; - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128; - } - else if (ext->key_len == MIN_WEP_KEY_SIZE) - { - pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE; - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64; - } - else - return -EINVAL; + AsicRemoveSharedKeyEntry(pAdapter, 0, (u8)keyIdx); + NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], + sizeof(struct rt_cipher_key)); + DBGPRINT(RT_DEBUG_TRACE, + ("%s::Remove all keys!(encoding->flags = %x)\n", + __func__, encoding->flags)); + } else { + /* Get Key Index and convet to our own defined key index */ + keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1; + if ((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS)) + return -EINVAL; - NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, 16); - NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, ext->key_len); - if (pAdapter->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled || - pAdapter->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled) - { - // Set Group key material to Asic - AsicAddSharedKeyEntry(pAdapter, BSS0, keyIdx, pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, pAdapter->SharedKey[BSS0][keyIdx].Key, NULL, NULL); + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + pAdapter->StaCfg.DefaultKeyId = keyIdx; + DBGPRINT(RT_DEBUG_TRACE, + ("%s::DefaultKeyId = %d\n", __func__, + pAdapter->StaCfg.DefaultKeyId)); + } - // Update WCID attribute table and IVEIV table for this group key table - RTMPAddWcidAttributeEntry(pAdapter, BSS0, keyIdx, pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, NULL); + switch (alg) { + case IW_ENCODE_ALG_NONE: + DBGPRINT(RT_DEBUG_TRACE, + ("%s::IW_ENCODE_ALG_NONE\n", __func__)); + break; + case IW_ENCODE_ALG_WEP: + DBGPRINT(RT_DEBUG_TRACE, + ("%s::IW_ENCODE_ALG_WEP - ext->key_len = %d, keyIdx = %d\n", + __func__, ext->key_len, keyIdx)); + if (ext->key_len == MAX_WEP_KEY_SIZE) { + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = + MAX_WEP_KEY_SIZE; + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = + CIPHER_WEP128; + } else if (ext->key_len == MIN_WEP_KEY_SIZE) { + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = + MIN_WEP_KEY_SIZE; + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = + CIPHER_WEP64; + } else + return -EINVAL; - STA_PORT_SECURED(pAdapter); + NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, + 16); + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, + ext->key, ext->key_len); + if (pAdapter->StaCfg.GroupCipher == + Ndis802_11GroupWEP40Enabled + || pAdapter->StaCfg.GroupCipher == + Ndis802_11GroupWEP104Enabled) { + /* Set Group key material to Asic */ + AsicAddSharedKeyEntry(pAdapter, BSS0, keyIdx, + pAdapter-> + SharedKey[BSS0][keyIdx]. + CipherAlg, + pAdapter-> + SharedKey[BSS0][keyIdx]. + Key, NULL, NULL); + + /* Update WCID attribute table and IVEIV table for this group key table */ + RTMPAddWcidAttributeEntry(pAdapter, BSS0, + keyIdx, + pAdapter-> + SharedKey[BSS0] + [keyIdx].CipherAlg, + NULL); + + STA_PORT_SECURED(pAdapter); - // Indicate Connected for GUI - pAdapter->IndicateMediaState = NdisMediaStateConnected; + /* Indicate Connected for GUI */ + pAdapter->IndicateMediaState = + NdisMediaStateConnected; + } + break; + case IW_ENCODE_ALG_TKIP: + DBGPRINT(RT_DEBUG_TRACE, + ("%s::IW_ENCODE_ALG_TKIP - keyIdx = %d, ext->key_len = %d\n", + __func__, keyIdx, ext->key_len)); + if (ext->key_len == 32) { + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + fnSetCipherKey(pAdapter, keyIdx, + CIPHER_TKIP, FALSE, ext); + if (pAdapter->StaCfg.AuthMode >= + Ndis802_11AuthModeWPA2) { + /*pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */ + STA_PORT_SECURED(pAdapter); + pAdapter->IndicateMediaState = + NdisMediaStateConnected; + } + } else if (ext-> + ext_flags & IW_ENCODE_EXT_GROUP_KEY) + { + fnSetCipherKey(pAdapter, keyIdx, + CIPHER_TKIP, TRUE, ext); + + /* set 802.1x port control */ + /*pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */ + STA_PORT_SECURED(pAdapter); + pAdapter->IndicateMediaState = + NdisMediaStateConnected; } - break; - case IW_ENCODE_ALG_TKIP: - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_TKIP - keyIdx = %d, ext->key_len = %d\n", __func__, keyIdx, ext->key_len)); - if (ext->key_len == 32) - { - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) - { - fnSetCipherKey(pAdapter, keyIdx, CIPHER_TKIP, FALSE, ext); - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2) - { - STA_PORT_SECURED(pAdapter); - } - } - else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) - { - fnSetCipherKey(pAdapter, keyIdx, CIPHER_TKIP, TRUE, ext); - - // set 802.1x port control - STA_PORT_SECURED(pAdapter); - } - } - else - return -EINVAL; - break; - case IW_ENCODE_ALG_CCMP: - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) - { - fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, FALSE, ext); - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2) - STA_PORT_SECURED(pAdapter); - } - else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) - { - fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, TRUE, ext); - - // set 802.1x port control - STA_PORT_SECURED(pAdapter); - } - break; - default: - return -EINVAL; + } else + return -EINVAL; + break; + case IW_ENCODE_ALG_CCMP: + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, + FALSE, ext); + if (pAdapter->StaCfg.AuthMode >= + Ndis802_11AuthModeWPA2) + /*pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */ + STA_PORT_SECURED(pAdapter); + pAdapter->IndicateMediaState = + NdisMediaStateConnected; + } else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, + TRUE, ext); + + /* set 802.1x port control */ + /*pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */ + STA_PORT_SECURED(pAdapter); + pAdapter->IndicateMediaState = + NdisMediaStateConnected; + } + break; + default: + return -EINVAL; } - } + } - return 0; + return 0; } int rt_ioctl_giwencodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { - PRTMP_ADAPTER pAd = dev->ml_priv; - PCHAR pKey = NULL; + struct rt_rtmp_adapter *pAd = NULL; + char *pKey = NULL; struct iw_point *encoding = &wrqu->encoding; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; int idx, max_key_len; - DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_giwencodeext\n")); + GET_PAD_FROM_NET_DEV(pAd, dev); + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt_ioctl_giwencodeext\n")); max_key_len = encoding->length - sizeof(*ext); if (max_key_len < 0) return -EINVAL; idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) - { + if (idx) { if (idx < 1 || idx > 4) return -EINVAL; idx--; if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || - (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)) - { - if (idx != pAd->StaCfg.DefaultKeyId) - { + (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)) { + if (idx != pAd->StaCfg.DefaultKeyId) { ext->key_len = 0; return 0; } } - } - else + } else idx = pAd->StaCfg.DefaultKeyId; encoding->flags = idx + 1; memset(ext, 0, sizeof(*ext)); ext->key_len = 0; - switch(pAd->StaCfg.WepStatus) { - case Ndis802_11WEPDisabled: - ext->alg = IW_ENCODE_ALG_NONE; - encoding->flags |= IW_ENCODE_DISABLED; - break; - case Ndis802_11WEPEnabled: - ext->alg = IW_ENCODE_ALG_WEP; - if (pAd->SharedKey[BSS0][idx].KeyLen > max_key_len) - return -E2BIG; - else - { - ext->key_len = pAd->SharedKey[BSS0][idx].KeyLen; - pKey = &(pAd->SharedKey[BSS0][idx].Key[0]); - } - break; - case Ndis802_11Encryption2Enabled: - case Ndis802_11Encryption3Enabled: - if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) - ext->alg = IW_ENCODE_ALG_TKIP; - else - ext->alg = IW_ENCODE_ALG_CCMP; + switch (pAd->StaCfg.WepStatus) { + case Ndis802_11WEPDisabled: + ext->alg = IW_ENCODE_ALG_NONE; + encoding->flags |= IW_ENCODE_DISABLED; + break; + case Ndis802_11WEPEnabled: + ext->alg = IW_ENCODE_ALG_WEP; + if (pAd->SharedKey[BSS0][idx].KeyLen > max_key_len) + return -E2BIG; + else { + ext->key_len = pAd->SharedKey[BSS0][idx].KeyLen; + pKey = (char *)& (pAd->SharedKey[BSS0][idx].Key[0]); + } + break; + case Ndis802_11Encryption2Enabled: + case Ndis802_11Encryption3Enabled: + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) + ext->alg = IW_ENCODE_ALG_TKIP; + else + ext->alg = IW_ENCODE_ALG_CCMP; - if (max_key_len < 32) - return -E2BIG; - else - { - ext->key_len = 32; - pKey = &pAd->StaCfg.PMK[0]; - } - break; - default: - return -EINVAL; + if (max_key_len < 32) + return -E2BIG; + else { + ext->key_len = 32; + pKey = (char *)& pAd->StaCfg.PMK[0]; + } + break; + default: + return -EINVAL; } - if (ext->key_len && pKey) - { + if (ext->key_len && pKey) { encoding->flags |= IW_ENCODE_ENABLED; memcpy(ext->key, pKey, ext->key_len); } @@ -2332,22 +2093,25 @@ rt_ioctl_giwencodeext(struct net_device *dev, } int rt_ioctl_siwgenie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { - PRTMP_ADAPTER pAd = dev->ml_priv; + struct rt_rtmp_adapter *pAd = NULL; + + GET_PAD_FROM_NET_DEV(pAd, dev); + DBGPRINT(RT_DEBUG_TRACE, ("===> rt_ioctl_siwgenie\n")); + pAd->StaCfg.bRSN_IE_FromWpaSupplicant = FALSE; if (wrqu->data.length > MAX_LEN_OF_RSNIE || (wrqu->data.length && extra == NULL)) return -EINVAL; - if (wrqu->data.length) - { + if (wrqu->data.length) { pAd->StaCfg.RSNIE_Len = wrqu->data.length; - NdisMoveMemory(&pAd->StaCfg.RSN_IE[0], extra, pAd->StaCfg.RSNIE_Len); - } - else - { + NdisMoveMemory(&pAd->StaCfg.RSN_IE[0], extra, + pAd->StaCfg.RSNIE_Len); + pAd->StaCfg.bRSN_IE_FromWpaSupplicant = TRUE; + } else { pAd->StaCfg.RSNIE_Len = 0; NdisZeroMemory(&pAd->StaCfg.RSN_IE[0], MAX_LEN_OF_RSNIE); } @@ -2356,182 +2120,213 @@ int rt_ioctl_siwgenie(struct net_device *dev, } int rt_ioctl_giwgenie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { - PRTMP_ADAPTER pAd = dev->ml_priv; + struct rt_rtmp_adapter *pAd = NULL; + + GET_PAD_FROM_NET_DEV(pAd, dev); if ((pAd->StaCfg.RSNIE_Len == 0) || - (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA)) - { + (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA)) { wrqu->data.length = 0; return 0; } - if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) - { - if (wrqu->data.length < pAd->StaCfg.RSNIE_Len) - return -E2BIG; + if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) { + if (wrqu->data.length < pAd->StaCfg.RSNIE_Len) + return -E2BIG; - wrqu->data.length = pAd->StaCfg.RSNIE_Len; - memcpy(extra, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len); - } - else - { - UCHAR RSNIe = IE_WPA; + wrqu->data.length = pAd->StaCfg.RSNIE_Len; + memcpy(extra, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len); + } else { + u8 RSNIe = IE_WPA; - if (wrqu->data.length < (pAd->StaCfg.RSNIE_Len + 2)) // ID, Len + if (wrqu->data.length < (pAd->StaCfg.RSNIE_Len + 2)) /* ID, Len */ return -E2BIG; wrqu->data.length = pAd->StaCfg.RSNIE_Len + 2; if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)) + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)) RSNIe = IE_RSN; extra[0] = (char)RSNIe; extra[1] = pAd->StaCfg.RSNIE_Len; - memcpy(extra+2, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len); + memcpy(extra + 2, &pAd->StaCfg.RSN_IE[0], + pAd->StaCfg.RSNIE_Len); } return 0; } int rt_ioctl_siwpmksa(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { - PRTMP_ADAPTER pAd = dev->ml_priv; + struct rt_rtmp_adapter *pAd = NULL; struct iw_pmksa *pPmksa = (struct iw_pmksa *)wrqu->data.pointer; - INT CachedIdx = 0, idx = 0; + int CachedIdx = 0, idx = 0; + + GET_PAD_FROM_NET_DEV(pAd, dev); if (pPmksa == NULL) return -EINVAL; - DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_siwpmksa\n")); - switch(pPmksa->cmd) - { - case IW_PMKSA_FLUSH: - NdisZeroMemory(pAd->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO); - DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_FLUSH\n")); - break; - case IW_PMKSA_REMOVE: - for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++) - { - // compare the BSSID - if (NdisEqualMemory(pPmksa->bssid.sa_data, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN)) - { - NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN); - NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].PMKID, 16); - for (idx = CachedIdx; idx < (pAd->StaCfg.SavedPMKNum - 1); idx++) - { - NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].BSSID[0], &pAd->StaCfg.SavedPMK[idx+1].BSSID[0], MAC_ADDR_LEN); - NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].PMKID[0], &pAd->StaCfg.SavedPMK[idx+1].PMKID[0], 16); - } - pAd->StaCfg.SavedPMKNum--; - break; - } - } + DBGPRINT(RT_DEBUG_TRACE, ("===> rt_ioctl_siwpmksa\n")); + switch (pPmksa->cmd) { + case IW_PMKSA_FLUSH: + NdisZeroMemory(pAd->StaCfg.SavedPMK, + sizeof(struct rt_bssid_info) * PMKID_NO); + DBGPRINT(RT_DEBUG_TRACE, + ("rt_ioctl_siwpmksa - IW_PMKSA_FLUSH\n")); + break; + case IW_PMKSA_REMOVE: + for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; + CachedIdx++) { + /* compare the BSSID */ + if (NdisEqualMemory + (pPmksa->bssid.sa_data, + pAd->StaCfg.SavedPMK[CachedIdx].BSSID, + MAC_ADDR_LEN)) { + NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx]. + BSSID, MAC_ADDR_LEN); + NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx]. + PMKID, 16); + for (idx = CachedIdx; + idx < (pAd->StaCfg.SavedPMKNum - 1); + idx++) { + NdisMoveMemory(&pAd->StaCfg. + SavedPMK[idx].BSSID[0], + &pAd->StaCfg. + SavedPMK[idx + + 1].BSSID[0], + MAC_ADDR_LEN); + NdisMoveMemory(&pAd->StaCfg. + SavedPMK[idx].PMKID[0], + &pAd->StaCfg. + SavedPMK[idx + + 1].PMKID[0], + 16); + } + pAd->StaCfg.SavedPMKNum--; + break; + } + } - DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_REMOVE\n")); - break; - case IW_PMKSA_ADD: - for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++) - { - // compare the BSSID - if (NdisEqualMemory(pPmksa->bssid.sa_data, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN)) - break; - } - - // Found, replace it - if (CachedIdx < PMKID_NO) - { - DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx)); - NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pPmksa->bssid.sa_data, MAC_ADDR_LEN); - NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pPmksa->pmkid, 16); - pAd->StaCfg.SavedPMKNum++; - } - // Not found, replace the last one - else - { - // Randomly replace one - CachedIdx = (pPmksa->bssid.sa_data[5] % PMKID_NO); - DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx)); - NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pPmksa->bssid.sa_data, MAC_ADDR_LEN); - NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pPmksa->pmkid, 16); - } - - DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_ADD\n")); - break; - default: - DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - Unknow Command!!\n")); - break; + DBGPRINT(RT_DEBUG_TRACE, + ("rt_ioctl_siwpmksa - IW_PMKSA_REMOVE\n")); + break; + case IW_PMKSA_ADD: + for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; + CachedIdx++) { + /* compare the BSSID */ + if (NdisEqualMemory + (pPmksa->bssid.sa_data, + pAd->StaCfg.SavedPMK[CachedIdx].BSSID, + MAC_ADDR_LEN)) + break; + } + + /* Found, replace it */ + if (CachedIdx < PMKID_NO) { + DBGPRINT(RT_DEBUG_OFF, + ("Update PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx]. + BSSID[0], pPmksa->bssid.sa_data, + MAC_ADDR_LEN); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx]. + PMKID[0], pPmksa->pmkid, 16); + pAd->StaCfg.SavedPMKNum++; + } + /* Not found, replace the last one */ + else { + /* Randomly replace one */ + CachedIdx = (pPmksa->bssid.sa_data[5] % PMKID_NO); + DBGPRINT(RT_DEBUG_OFF, + ("Update PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx]. + BSSID[0], pPmksa->bssid.sa_data, + MAC_ADDR_LEN); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx]. + PMKID[0], pPmksa->pmkid, 16); + } + + DBGPRINT(RT_DEBUG_TRACE, + ("rt_ioctl_siwpmksa - IW_PMKSA_ADD\n")); + break; + default: + DBGPRINT(RT_DEBUG_TRACE, + ("rt_ioctl_siwpmksa - Unknown Command!\n")); + break; } return 0; } int rt_ioctl_siwrate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { - PRTMP_ADAPTER pAd = dev->ml_priv; - UINT32 rate = wrqu->bitrate.value, fixed = wrqu->bitrate.fixed; + struct rt_rtmp_adapter *pAd = NULL; + u32 rate = wrqu->bitrate.value, fixed = wrqu->bitrate.fixed; - //check if the interface is down - if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::Network is down!\n")); - return -ENETDOWN; + GET_PAD_FROM_NET_DEV(pAd, dev); + + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, + ("rt_ioctl_siwrate::Network is down!\n")); + return -ENETDOWN; } - DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(rate = %d, fixed = %d)\n", rate, fixed)); - /* rate = -1 => auto rate - rate = X, fixed = 1 => (fixed rate X) - */ - if (rate == -1) - { - //Auto Rate + DBGPRINT(RT_DEBUG_TRACE, + ("rt_ioctl_siwrate::(rate = %d, fixed = %d)\n", rate, fixed)); + /* rate = -1 => auto rate + rate = X, fixed = 1 => (fixed rate X) + */ + if (rate == -1) { + /*Auto Rate */ pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; pAd->StaCfg.bAutoTxRateSwitch = TRUE; if ((pAd->CommonCfg.PhyMode <= PHY_11G) || - (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)) + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= + MODE_OFDM)) RTMPSetDesiredRates(pAd, -1); SetCommonHT(pAd); - } - else - { - if (fixed) - { - pAd->StaCfg.bAutoTxRateSwitch = FALSE; - if ((pAd->CommonCfg.PhyMode <= PHY_11G) || - (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)) - RTMPSetDesiredRates(pAd, rate); - else - { - pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; - SetCommonHT(pAd); - } - DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(HtMcs=%d)\n",pAd->StaCfg.DesiredTransmitSetting.field.MCS)); - } - else - { - // TODO: rate = X, fixed = 0 => (rates <= X) - return -EOPNOTSUPP; - } - } - - return 0; + } else { + if (fixed) { + pAd->StaCfg.bAutoTxRateSwitch = FALSE; + if ((pAd->CommonCfg.PhyMode <= PHY_11G) || + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field. + MODE <= MODE_OFDM)) + RTMPSetDesiredRates(pAd, rate); + else { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = + MCS_AUTO; + SetCommonHT(pAd); + } + DBGPRINT(RT_DEBUG_TRACE, + ("rt_ioctl_siwrate::(HtMcs=%d)\n", + pAd->StaCfg.DesiredTransmitSetting.field. + MCS)); + } else { + /* TODO: rate = X, fixed = 0 => (rates <= X) */ + return -EOPNOTSUPP; + } + } + + return 0; } int rt_ioctl_giwrate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { - PRTMP_ADAPTER pAd = dev->ml_priv; - int rate_index = 0, rate_count = 0; - HTTRANSMIT_SETTING ht_setting; + struct rt_rtmp_adapter *pAd = NULL; + int rate_index = 0, rate_count = 0; + HTTRANSMIT_SETTING ht_setting; +/* Remove to global variable __s32 ralinkrate[] = {2, 4, 11, 22, // CCK 12, 18, 24, 36, 48, 72, 96, 108, // OFDM @@ -2543,329 +2338,295 @@ int rt_ioctl_giwrate(struct net_device *dev, 43, 87, 130, 173, 260, 317, 390, 433, // 20MHz, 400ns GI, MCS: 16 ~ 23 30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, // 40MHz, 400ns GI, MCS: 0 ~ 15 90, 180, 270, 360, 540, 720, 810, 900}; // 40MHz, 400ns GI, MCS: 16 ~ 23 +*/ + GET_PAD_FROM_NET_DEV(pAd, dev); - rate_count = sizeof(ralinkrate)/sizeof(__s32); - //check if the interface is down - if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; + rate_count = sizeof(ralinkrate) / sizeof(__s32); + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; } - if ((pAd->StaCfg.bAutoTxRateSwitch == FALSE) && - (INFRA_ON(pAd)) && - ((pAd->CommonCfg.PhyMode <= PHY_11G) || (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM))) - ht_setting.word = pAd->StaCfg.HTPhyMode.word; - else - ht_setting.word = pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word; - - if (ht_setting.field.MODE >= MODE_HTMIX) - { - rate_index = 12 + ((UCHAR)ht_setting.field.BW *24) + ((UCHAR)ht_setting.field.ShortGI *48) + ((UCHAR)ht_setting.field.MCS); - } - else - if (ht_setting.field.MODE == MODE_OFDM) - rate_index = (UCHAR)(ht_setting.field.MCS) + 4; - else if (ht_setting.field.MODE == MODE_CCK) - rate_index = (UCHAR)(ht_setting.field.MCS); - - if (rate_index < 0) - rate_index = 0; - - if (rate_index > rate_count) - rate_index = rate_count; - - wrqu->bitrate.value = ralinkrate[rate_index] * 500000; - wrqu->bitrate.disabled = 0; - - return 0; -} + if ((pAd->StaCfg.bAutoTxRateSwitch == FALSE) && + (INFRA_ON(pAd)) && + ((pAd->CommonCfg.PhyMode <= PHY_11G) + || (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= + MODE_OFDM))) + ht_setting.word = pAd->StaCfg.HTPhyMode.word; + else + ht_setting.word = + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word; -static const iw_handler rt_handler[] = -{ - (iw_handler) NULL, /* SIOCSIWCOMMIT */ - (iw_handler) rt_ioctl_giwname, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) rt_ioctl_siwfreq, /* SIOCSIWFREQ */ - (iw_handler) rt_ioctl_giwfreq, /* SIOCGIWFREQ */ - (iw_handler) rt_ioctl_siwmode, /* SIOCSIWMODE */ - (iw_handler) rt_ioctl_giwmode, /* SIOCGIWMODE */ - (iw_handler) NULL, /* SIOCSIWSENS */ - (iw_handler) NULL, /* SIOCGIWSENS */ - (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */ - (iw_handler) rt_ioctl_giwrange, /* SIOCGIWRANGE */ - (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ - (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ - (iw_handler) rt28xx_get_wireless_stats /* kernel code */, /* SIOCGIWSTATS */ - (iw_handler) NULL, /* SIOCSIWSPY */ - (iw_handler) NULL, /* SIOCGIWSPY */ - (iw_handler) NULL, /* SIOCSIWTHRSPY */ - (iw_handler) NULL, /* SIOCGIWTHRSPY */ - (iw_handler) rt_ioctl_siwap, /* SIOCSIWAP */ - (iw_handler) rt_ioctl_giwap, /* SIOCGIWAP */ - (iw_handler) rt_ioctl_siwmlme, /* SIOCSIWMLME */ - (iw_handler) rt_ioctl_iwaplist, /* SIOCGIWAPLIST */ - (iw_handler) rt_ioctl_siwscan, /* SIOCSIWSCAN */ - (iw_handler) rt_ioctl_giwscan, /* SIOCGIWSCAN */ - (iw_handler) rt_ioctl_siwessid, /* SIOCSIWESSID */ - (iw_handler) rt_ioctl_giwessid, /* SIOCGIWESSID */ - (iw_handler) rt_ioctl_siwnickn, /* SIOCSIWNICKN */ - (iw_handler) rt_ioctl_giwnickn, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) rt_ioctl_siwrate, /* SIOCSIWRATE */ - (iw_handler) rt_ioctl_giwrate, /* SIOCGIWRATE */ - (iw_handler) rt_ioctl_siwrts, /* SIOCSIWRTS */ - (iw_handler) rt_ioctl_giwrts, /* SIOCGIWRTS */ - (iw_handler) rt_ioctl_siwfrag, /* SIOCSIWFRAG */ - (iw_handler) rt_ioctl_giwfrag, /* SIOCGIWFRAG */ - (iw_handler) NULL, /* SIOCSIWTXPOW */ - (iw_handler) NULL, /* SIOCGIWTXPOW */ - (iw_handler) NULL, /* SIOCSIWRETRY */ - (iw_handler) NULL, /* SIOCGIWRETRY */ - (iw_handler) rt_ioctl_siwencode, /* SIOCSIWENCODE */ - (iw_handler) rt_ioctl_giwencode, /* SIOCGIWENCODE */ - (iw_handler) NULL, /* SIOCSIWPOWER */ - (iw_handler) NULL, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) rt_ioctl_siwgenie, /* SIOCSIWGENIE */ - (iw_handler) rt_ioctl_giwgenie, /* SIOCGIWGENIE */ - (iw_handler) rt_ioctl_siwauth, /* SIOCSIWAUTH */ - (iw_handler) rt_ioctl_giwauth, /* SIOCGIWAUTH */ - (iw_handler) rt_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */ - (iw_handler) rt_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */ - (iw_handler) rt_ioctl_siwpmksa, /* SIOCSIWPMKSA */ -}; + if (ht_setting.field.MODE >= MODE_HTMIX) { +/* rate_index = 12 + ((u8)ht_setting.field.BW *16) + ((u8)ht_setting.field.ShortGI *32) + ((u8)ht_setting.field.MCS); */ + rate_index = + 12 + ((u8)ht_setting.field.BW * 24) + + ((u8)ht_setting.field.ShortGI * 48) + + ((u8)ht_setting.field.MCS); + } else if (ht_setting.field.MODE == MODE_OFDM) + rate_index = (u8)(ht_setting.field.MCS) + 4; + else if (ht_setting.field.MODE == MODE_CCK) + rate_index = (u8)(ht_setting.field.MCS); -static const iw_handler rt_priv_handlers[] = { - (iw_handler) NULL, /* + 0x00 */ - (iw_handler) NULL, /* + 0x01 */ - (iw_handler) rt_ioctl_setparam, /* + 0x02 */ - (iw_handler) NULL, /* + 0x03 */ - (iw_handler) NULL, /* + 0x04 */ - (iw_handler) NULL, /* + 0x05 */ - (iw_handler) NULL, /* + 0x06 */ - (iw_handler) NULL, /* + 0x07 */ - (iw_handler) NULL, /* + 0x08 */ - (iw_handler) rt_private_get_statistics, /* + 0x09 */ - (iw_handler) NULL, /* + 0x0A */ - (iw_handler) NULL, /* + 0x0B */ - (iw_handler) NULL, /* + 0x0C */ - (iw_handler) NULL, /* + 0x0D */ - (iw_handler) NULL, /* + 0x0E */ - (iw_handler) NULL, /* + 0x0F */ - (iw_handler) NULL, /* + 0x10 */ - (iw_handler) rt_private_show, /* + 0x11 */ - (iw_handler) NULL, /* + 0x12 */ - (iw_handler) NULL, /* + 0x13 */ - (iw_handler) NULL, /* + 0x15 */ - (iw_handler) NULL, /* + 0x17 */ - (iw_handler) NULL, /* + 0x18 */ + if (rate_index < 0) + rate_index = 0; + + if (rate_index > rate_count) + rate_index = rate_count; + + wrqu->bitrate.value = ralinkrate[rate_index] * 500000; + wrqu->bitrate.disabled = 0; + + return 0; +} + +static const iw_handler rt_handler[] = { + (iw_handler) NULL, /* SIOCSIWCOMMIT */ + (iw_handler) rt_ioctl_giwname, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) rt_ioctl_siwfreq, /* SIOCSIWFREQ */ + (iw_handler) rt_ioctl_giwfreq, /* SIOCGIWFREQ */ + (iw_handler) rt_ioctl_siwmode, /* SIOCSIWMODE */ + (iw_handler) rt_ioctl_giwmode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCSIWSENS */ + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL /* not used */ , /* SIOCSIWRANGE */ + (iw_handler) rt_ioctl_giwrange, /* SIOCGIWRANGE */ + (iw_handler) NULL /* not used */ , /* SIOCSIWPRIV */ + (iw_handler) NULL /* kernel code */ , /* SIOCGIWPRIV */ + (iw_handler) NULL /* not used */ , /* SIOCSIWSTATS */ + (iw_handler) rt28xx_get_wireless_stats /* kernel code */ , /* SIOCGIWSTATS */ + (iw_handler) NULL, /* SIOCSIWSPY */ + (iw_handler) NULL, /* SIOCGIWSPY */ + (iw_handler) NULL, /* SIOCSIWTHRSPY */ + (iw_handler) NULL, /* SIOCGIWTHRSPY */ + (iw_handler) rt_ioctl_siwap, /* SIOCSIWAP */ + (iw_handler) rt_ioctl_giwap, /* SIOCGIWAP */ + (iw_handler) rt_ioctl_siwmlme, /* SIOCSIWMLME */ + (iw_handler) rt_ioctl_iwaplist, /* SIOCGIWAPLIST */ + (iw_handler) rt_ioctl_siwscan, /* SIOCSIWSCAN */ + (iw_handler) rt_ioctl_giwscan, /* SIOCGIWSCAN */ + (iw_handler) rt_ioctl_siwessid, /* SIOCSIWESSID */ + (iw_handler) rt_ioctl_giwessid, /* SIOCGIWESSID */ + (iw_handler) rt_ioctl_siwnickn, /* SIOCSIWNICKN */ + (iw_handler) rt_ioctl_giwnickn, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) rt_ioctl_siwrate, /* SIOCSIWRATE */ + (iw_handler) rt_ioctl_giwrate, /* SIOCGIWRATE */ + (iw_handler) rt_ioctl_siwrts, /* SIOCSIWRTS */ + (iw_handler) rt_ioctl_giwrts, /* SIOCGIWRTS */ + (iw_handler) rt_ioctl_siwfrag, /* SIOCSIWFRAG */ + (iw_handler) rt_ioctl_giwfrag, /* SIOCGIWFRAG */ + (iw_handler) NULL, /* SIOCSIWTXPOW */ + (iw_handler) NULL, /* SIOCGIWTXPOW */ + (iw_handler) NULL, /* SIOCSIWRETRY */ + (iw_handler) NULL, /* SIOCGIWRETRY */ + (iw_handler) rt_ioctl_siwencode, /* SIOCSIWENCODE */ + (iw_handler) rt_ioctl_giwencode, /* SIOCGIWENCODE */ + (iw_handler) NULL, /* SIOCSIWPOWER */ + (iw_handler) NULL, /* SIOCGIWPOWER */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) rt_ioctl_siwgenie, /* SIOCSIWGENIE */ + (iw_handler) rt_ioctl_giwgenie, /* SIOCGIWGENIE */ + (iw_handler) rt_ioctl_siwauth, /* SIOCSIWAUTH */ + (iw_handler) rt_ioctl_giwauth, /* SIOCGIWAUTH */ + (iw_handler) rt_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */ + (iw_handler) rt_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */ + (iw_handler) rt_ioctl_siwpmksa, /* SIOCSIWPMKSA */ }; -const struct iw_handler_def rt28xx_iw_handler_def = -{ -#define N(a) (sizeof (a) / sizeof (a[0])) - .standard = (iw_handler *) rt_handler, - .num_standard = sizeof(rt_handler) / sizeof(iw_handler), - .private = (iw_handler *) rt_priv_handlers, - .num_private = N(rt_priv_handlers), - .private_args = (struct iw_priv_args *) privtab, - .num_private_args = N(privtab), +const struct iw_handler_def rt28xx_iw_handler_def = { + .standard = (iw_handler *) rt_handler, + .num_standard = sizeof(rt_handler) / sizeof(iw_handler), #if IW_HANDLER_VERSION >= 7 - .get_wireless_stats = rt28xx_get_wireless_stats, + .get_wireless_stats = rt28xx_get_wireless_stats, #endif }; -INT rt28xx_sta_ioctl( - IN struct net_device *net_dev, - IN OUT struct ifreq *rq, - IN INT cmd) +int rt28xx_sta_ioctl(IN struct net_device *net_dev, + IN OUT struct ifreq *rq, int cmd) { - RTMP_ADAPTER *pAd = net_dev->ml_priv; - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - struct iwreq *wrq = (struct iwreq *) rq; - BOOLEAN StateMachineTouched = FALSE; - INT Status = NDIS_STATUS_SUCCESS; - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - } - - { // determine this ioctl command is comming from which interface. + struct os_cookie *pObj; + struct rt_rtmp_adapter *pAd = NULL; + struct iwreq *wrq = (struct iwreq *)rq; + BOOLEAN StateMachineTouched = FALSE; + int Status = NDIS_STATUS_SUCCESS; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + pObj = (struct os_cookie *)pAd->OS_Cookie; + + /*check if the interface is down */ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + } + + { /* determine this ioctl command is comming from which interface. */ pObj->ioctl_if_type = INT_MAIN; pObj->ioctl_if = MAIN_MBSSID; } - switch(cmd) - { - case SIOCGIFHWADDR: - DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIFHWADDR\n")); - memcpy(wrq->u.name, pAd->CurrentAddress, ETH_ALEN); - break; - case SIOCGIWNAME: - { - char *name=&wrq->u.name[0]; - rt_ioctl_giwname(net_dev, NULL, name, NULL); + switch (cmd) { + case SIOCGIFHWADDR: + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIFHWADDR\n")); + memcpy(wrq->u.name, pAd->CurrentAddress, ETH_ALEN); + break; + case SIOCGIWNAME: + { + char *name = &wrq->u.name[0]; + rt_ioctl_giwname(net_dev, NULL, name, NULL); break; } - case SIOCGIWESSID: //Get ESSID - { - struct iw_point *essid=&wrq->u.essid; - rt_ioctl_giwessid(net_dev, NULL, essid, essid->pointer); + case SIOCGIWESSID: /*Get ESSID */ + { + struct iw_point *essid = &wrq->u.essid; + rt_ioctl_giwessid(net_dev, NULL, essid, essid->pointer); break; } - case SIOCSIWESSID: //Set ESSID - { - struct iw_point *essid=&wrq->u.essid; - rt_ioctl_siwessid(net_dev, NULL, essid, essid->pointer); + case SIOCSIWESSID: /*Set ESSID */ + { + struct iw_point *essid = &wrq->u.essid; + rt_ioctl_siwessid(net_dev, NULL, essid, essid->pointer); break; } - case SIOCSIWNWID: // set network id (the cell) - case SIOCGIWNWID: // get network id - Status = -EOPNOTSUPP; - break; - case SIOCSIWFREQ: //set channel/frequency (Hz) - { - struct iw_freq *freq=&wrq->u.freq; - rt_ioctl_siwfreq(net_dev, NULL, freq, NULL); + case SIOCSIWNWID: /* set network id (the cell) */ + case SIOCGIWNWID: /* get network id */ + Status = -EOPNOTSUPP; + break; + case SIOCSIWFREQ: /*set channel/frequency (Hz) */ + { + struct iw_freq *freq = &wrq->u.freq; + rt_ioctl_siwfreq(net_dev, NULL, freq, NULL); break; } - case SIOCGIWFREQ: // get channel/frequency (Hz) - { - struct iw_freq *freq=&wrq->u.freq; - rt_ioctl_giwfreq(net_dev, NULL, freq, NULL); + case SIOCGIWFREQ: /* get channel/frequency (Hz) */ + { + struct iw_freq *freq = &wrq->u.freq; + rt_ioctl_giwfreq(net_dev, NULL, freq, NULL); break; } - case SIOCSIWNICKN: //set node name/nickname - { - struct iw_point *data=&wrq->u.data; - rt_ioctl_siwnickn(net_dev, NULL, data, NULL); + case SIOCSIWNICKN: /*set node name/nickname */ + { + /*struct iw_point *data=&wrq->u.data; */ + /*rt_ioctl_siwnickn(net_dev, NULL, data, NULL); */ break; } - case SIOCGIWNICKN: //get node name/nickname - { - struct iw_point *data=&wrq->u.data; - rt_ioctl_giwnickn(net_dev, NULL, data, NULL); + case SIOCGIWNICKN: /*get node name/nickname */ + { + struct iw_point *erq = NULL; + erq = &wrq->u.data; + erq->length = strlen((char *)pAd->nickname); + Status = + copy_to_user(erq->pointer, pAd->nickname, + erq->length); break; } - case SIOCGIWRATE: //get default bit rate (bps) - rt_ioctl_giwrate(net_dev, NULL, &wrq->u, NULL); - break; - case SIOCSIWRATE: //set default bit rate (bps) - rt_ioctl_siwrate(net_dev, NULL, &wrq->u, NULL); - break; - case SIOCGIWRTS: // get RTS/CTS threshold (bytes) - { - struct iw_param *rts=&wrq->u.rts; - rt_ioctl_giwrts(net_dev, NULL, rts, NULL); + case SIOCGIWRATE: /*get default bit rate (bps) */ + rt_ioctl_giwrate(net_dev, NULL, &wrq->u, NULL); + break; + case SIOCSIWRATE: /*set default bit rate (bps) */ + rt_ioctl_siwrate(net_dev, NULL, &wrq->u, NULL); + break; + case SIOCGIWRTS: /* get RTS/CTS threshold (bytes) */ + { + struct iw_param *rts = &wrq->u.rts; + rt_ioctl_giwrts(net_dev, NULL, rts, NULL); break; } - case SIOCSIWRTS: //set RTS/CTS threshold (bytes) - { - struct iw_param *rts=&wrq->u.rts; - rt_ioctl_siwrts(net_dev, NULL, rts, NULL); + case SIOCSIWRTS: /*set RTS/CTS threshold (bytes) */ + { + struct iw_param *rts = &wrq->u.rts; + rt_ioctl_siwrts(net_dev, NULL, rts, NULL); break; } - case SIOCGIWFRAG: //get fragmentation thr (bytes) - { - struct iw_param *frag=&wrq->u.frag; - rt_ioctl_giwfrag(net_dev, NULL, frag, NULL); + case SIOCGIWFRAG: /*get fragmentation thr (bytes) */ + { + struct iw_param *frag = &wrq->u.frag; + rt_ioctl_giwfrag(net_dev, NULL, frag, NULL); break; } - case SIOCSIWFRAG: //set fragmentation thr (bytes) - { - struct iw_param *frag=&wrq->u.frag; - rt_ioctl_siwfrag(net_dev, NULL, frag, NULL); + case SIOCSIWFRAG: /*set fragmentation thr (bytes) */ + { + struct iw_param *frag = &wrq->u.frag; + rt_ioctl_siwfrag(net_dev, NULL, frag, NULL); break; } - case SIOCGIWENCODE: //get encoding token & mode - { - struct iw_point *erq=&wrq->u.encoding; - if(erq->pointer) - rt_ioctl_giwencode(net_dev, NULL, erq, erq->pointer); + case SIOCGIWENCODE: /*get encoding token & mode */ + { + struct iw_point *erq = &wrq->u.encoding; + if (erq) + rt_ioctl_giwencode(net_dev, NULL, erq, + erq->pointer); break; } - case SIOCSIWENCODE: //set encoding token & mode - { - struct iw_point *erq=&wrq->u.encoding; - if(erq->pointer) - rt_ioctl_siwencode(net_dev, NULL, erq, erq->pointer); + case SIOCSIWENCODE: /*set encoding token & mode */ + { + struct iw_point *erq = &wrq->u.encoding; + if (erq) + rt_ioctl_siwencode(net_dev, NULL, erq, + erq->pointer); break; } - case SIOCGIWAP: //get access point MAC addresses - { - struct sockaddr *ap_addr=&wrq->u.ap_addr; - rt_ioctl_giwap(net_dev, NULL, ap_addr, ap_addr->sa_data); + case SIOCGIWAP: /*get access point MAC addresses */ + { + struct sockaddr *ap_addr = &wrq->u.ap_addr; + rt_ioctl_giwap(net_dev, NULL, ap_addr, + ap_addr->sa_data); break; } - case SIOCSIWAP: //set access point MAC addresses - { - struct sockaddr *ap_addr=&wrq->u.ap_addr; - rt_ioctl_siwap(net_dev, NULL, ap_addr, ap_addr->sa_data); + case SIOCSIWAP: /*set access point MAC addresses */ + { + struct sockaddr *ap_addr = &wrq->u.ap_addr; + rt_ioctl_siwap(net_dev, NULL, ap_addr, + ap_addr->sa_data); break; } - case SIOCGIWMODE: //get operation mode - { - __u32 *mode=&wrq->u.mode; - rt_ioctl_giwmode(net_dev, NULL, mode, NULL); + case SIOCGIWMODE: /*get operation mode */ + { + __u32 *mode = &wrq->u.mode; + rt_ioctl_giwmode(net_dev, NULL, mode, NULL); break; } - case SIOCSIWMODE: //set operation mode - { - __u32 *mode=&wrq->u.mode; - rt_ioctl_siwmode(net_dev, NULL, mode, NULL); + case SIOCSIWMODE: /*set operation mode */ + { + __u32 *mode = &wrq->u.mode; + rt_ioctl_siwmode(net_dev, NULL, mode, NULL); break; } - case SIOCGIWSENS: //get sensitivity (dBm) - case SIOCSIWSENS: //set sensitivity (dBm) - case SIOCGIWPOWER: //get Power Management settings - case SIOCSIWPOWER: //set Power Management settings - case SIOCGIWTXPOW: //get transmit power (dBm) - case SIOCSIWTXPOW: //set transmit power (dBm) - case SIOCGIWRANGE: //Get range of parameters - case SIOCGIWRETRY: //get retry limits and lifetime - case SIOCSIWRETRY: //set retry limits and lifetime - case RT_PRIV_IOCTL: - case RT_PRIV_IOCTL_EXT: - Status = -EOPNOTSUPP; - break; - case SIOCGIWPRIV: - if (wrq->u.data.pointer) - { - if ( access_ok(VERIFY_WRITE, wrq->u.data.pointer, sizeof(privtab)) != TRUE) - break; - wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]); - if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab))) - Status = -EFAULT; - } - break; - case RTPRIV_IOCTL_SET: - if(access_ok(VERIFY_READ, wrq->u.data.pointer, wrq->u.data.length) != TRUE) - break; - rt_ioctl_setparam(net_dev, NULL, NULL, wrq->u.data.pointer); - break; - case RTPRIV_IOCTL_GSITESURVEY: - RTMPIoctlGetSiteSurvey(pAd, wrq); - break; - case SIOCETHTOOL: - break; - default: - DBGPRINT(RT_DEBUG_ERROR, ("IOCTL::unknown IOCTL's cmd = 0x%08x\n", cmd)); - Status = -EOPNOTSUPP; - break; + case SIOCGIWSENS: /*get sensitivity (dBm) */ + case SIOCSIWSENS: /*set sensitivity (dBm) */ + case SIOCGIWPOWER: /*get Power Management settings */ + case SIOCSIWPOWER: /*set Power Management settings */ + case SIOCGIWTXPOW: /*get transmit power (dBm) */ + case SIOCSIWTXPOW: /*set transmit power (dBm) */ + case SIOCGIWRANGE: /*Get range of parameters */ + case SIOCGIWRETRY: /*get retry limits and lifetime */ + case SIOCSIWRETRY: /*set retry limits and lifetime */ + case RT_PRIV_IOCTL: + case RT_PRIV_IOCTL_EXT: + case RTPRIV_IOCTL_SET: + case RTPRIV_IOCTL_GSITESURVEY: + case SIOCGIWPRIV: + Status = -EOPNOTSUPP; + break; + case SIOCETHTOOL: + break; + default: + DBGPRINT(RT_DEBUG_ERROR, + ("IOCTL::unknown IOCTL's cmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; } - if(StateMachineTouched) // Upper layer sent a MLME-related operations - RT28XX_MLME_HANDLER(pAd); + if (StateMachineTouched) /* Upper layer sent a MLME-related operations */ + RTMP_MLME_HANDLER(pAd); return Status; } @@ -2878,94 +2639,76 @@ INT rt28xx_sta_ioctl( TRUE if all parameters are OK, FALSE otherwise ========================================================================== */ -INT Set_SSID_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg) +int Set_SSID_Proc(struct rt_rtmp_adapter *pAdapter, char *arg) { - NDIS_802_11_SSID Ssid, *pSsid=NULL; - BOOLEAN StateMachineTouched = FALSE; - int success = TRUE; - - if( strlen(arg) <= MAX_LEN_OF_SSID) - { - NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); - if (strlen(arg) != 0) - { - NdisMoveMemory(Ssid.Ssid, arg, strlen(arg)); - Ssid.SsidLength = strlen(arg); - } - else //ANY ssid - { - Ssid.SsidLength = 0; - memcpy(Ssid.Ssid, "", 0); + struct rt_ndis_802_11_ssid Ssid, *pSsid = NULL; + BOOLEAN StateMachineTouched = FALSE; + int success = TRUE; + + if (strlen(arg) <= MAX_LEN_OF_SSID) { + NdisZeroMemory(&Ssid, sizeof(struct rt_ndis_802_11_ssid)); + if (strlen(arg) != 0) { + NdisMoveMemory(Ssid.Ssid, arg, strlen(arg)); + Ssid.SsidLength = strlen(arg); + } else /*ANY ssid */ + { + Ssid.SsidLength = 0; + memcpy(Ssid.Ssid, "", 0); pAdapter->StaCfg.BssType = BSS_INFRA; pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; - pAdapter->StaCfg.WepStatus = Ndis802_11EncryptionDisabled; + pAdapter->StaCfg.WepStatus = + Ndis802_11EncryptionDisabled; } - pSsid = &Ssid; - - if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) - { - RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); - DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); - } + pSsid = &Ssid; - pAdapter->MlmeAux.CurrReqIsFromNdis = TRUE; - pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; - pAdapter->bConfigChanged = TRUE; - - MlmeEnqueue(pAdapter, - MLME_CNTL_STATE_MACHINE, - OID_802_11_SSID, - sizeof(NDIS_802_11_SSID), - (VOID *)pSsid); + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) { + RTMP_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, + ("MLME busy, reset MLME state machine!\n")); + } - StateMachineTouched = TRUE; - DBGPRINT(RT_DEBUG_TRACE, ("Set_SSID_Proc::(Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid)); - } - else - success = FALSE; + if ((pAdapter->StaCfg.WpaPassPhraseLen >= 8) && + (pAdapter->StaCfg.WpaPassPhraseLen <= 64)) { + char passphrase_str[65] = { 0 }; + u8 keyMaterial[40]; + + RTMPMoveMemory(passphrase_str, + pAdapter->StaCfg.WpaPassPhrase, + pAdapter->StaCfg.WpaPassPhraseLen); + RTMPZeroMemory(pAdapter->StaCfg.PMK, 32); + if (pAdapter->StaCfg.WpaPassPhraseLen == 64) { + AtoH((char *)pAdapter->StaCfg.WpaPassPhrase, + pAdapter->StaCfg.PMK, 32); + } else { + PasswordHash((char *)pAdapter->StaCfg. + WpaPassPhrase, Ssid.Ssid, + Ssid.SsidLength, keyMaterial); + NdisMoveMemory(pAdapter->StaCfg.PMK, + keyMaterial, 32); + } + } - if (StateMachineTouched) // Upper layer sent a MLME-related operations - RT28XX_MLME_HANDLER(pAdapter); + pAdapter->MlmeAux.CurrReqIsFromNdis = TRUE; + pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; + pAdapter->bConfigChanged = TRUE; - return success; -} + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof(struct rt_ndis_802_11_ssid), (void *) pSsid); -#ifdef WMM_SUPPORT -/* - ========================================================================== - Description: - Set WmmCapable Enable or Disable - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_WmmCapable_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - BOOLEAN bWmmCapable; - - bWmmCapable = simple_strtol(arg, 0, 10); - - if ((bWmmCapable == 1) -#ifdef RT2870 - && (pAd->NumberOfPipes >= 5) -#endif // RT2870 // - ) - pAd->CommonCfg.bWmmCapable = TRUE; - else if (bWmmCapable == 0) - pAd->CommonCfg.bWmmCapable = FALSE; - else - return FALSE; //Invalid argument + StateMachineTouched = TRUE; + DBGPRINT(RT_DEBUG_TRACE, + ("Set_SSID_Proc::(Len=%d,Ssid=%s)\n", Ssid.SsidLength, + Ssid.Ssid)); + } else + success = FALSE; - DBGPRINT(RT_DEBUG_TRACE, ("Set_WmmCapable_Proc::(bWmmCapable=%d)\n", - pAd->CommonCfg.bWmmCapable)); + if (StateMachineTouched) /* Upper layer sent a MLME-related operations */ + RTMP_MLME_HANDLER(pAdapter); - return TRUE; + return success; } -#endif // WMM_SUPPORT // /* ========================================================================== @@ -2975,166 +2718,184 @@ INT Set_WmmCapable_Proc( TRUE if all parameters are OK, FALSE otherwise ========================================================================== */ -INT Set_NetworkType_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg) +int Set_NetworkType_Proc(struct rt_rtmp_adapter *pAdapter, char *arg) { - UINT32 Value = 0; + u32 Value = 0; - if (strcmp(arg, "Adhoc") == 0) - { - if (pAdapter->StaCfg.BssType != BSS_ADHOC) - { - // Config has changed + if (strcmp(arg, "Adhoc") == 0) { + if (pAdapter->StaCfg.BssType != BSS_ADHOC) { + /* Config has changed */ pAdapter->bConfigChanged = TRUE; - if (MONITOR_ON(pAdapter)) - { - RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, STANORMAL); - RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); + if (MONITOR_ON(pAdapter)) { + RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, + STANORMAL); + RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); Value &= (~0x80); RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value); - OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED); - pAdapter->StaCfg.bAutoReconnect = TRUE; - LinkDown(pAdapter, FALSE); - } - if (INFRA_ON(pAdapter)) - { - //BOOLEAN Cancelled; - // Set the AutoReconnectSsid to prevent it reconnect to old SSID - // Since calling this indicate user don't want to connect to that SSID anymore. - pAdapter->MlmeAux.AutoReconnectSsidLen= 32; - NdisZeroMemory(pAdapter->MlmeAux.AutoReconnectSsid, pAdapter->MlmeAux.AutoReconnectSsidLen); + OPSTATUS_CLEAR_FLAG(pAdapter, + fOP_STATUS_MEDIA_STATE_CONNECTED); + pAdapter->StaCfg.bAutoReconnect = TRUE; + LinkDown(pAdapter, FALSE); + } + if (INFRA_ON(pAdapter)) { + /*BOOLEAN Cancelled; */ + /* Set the AutoReconnectSsid to prevent it reconnect to old SSID */ + /* Since calling this indicate user don't want to connect to that SSID anymore. */ + pAdapter->MlmeAux.AutoReconnectSsidLen = 32; + NdisZeroMemory(pAdapter->MlmeAux. + AutoReconnectSsid, + pAdapter->MlmeAux. + AutoReconnectSsidLen); LinkDown(pAdapter, FALSE); - DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event BB!\n")); + DBGPRINT(RT_DEBUG_TRACE, + ("NDIS_STATUS_MEDIA_DISCONNECT Event BB!\n")); } } pAdapter->StaCfg.BssType = BSS_ADHOC; - pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType; - DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(AD-HOC)\n")); - } - else if (strcmp(arg, "Infra") == 0) - { - if (pAdapter->StaCfg.BssType != BSS_INFRA) - { - // Config has changed + pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType; + DBGPRINT(RT_DEBUG_TRACE, + ("===>Set_NetworkType_Proc::(AD-HOC)\n")); + } else if (strcmp(arg, "Infra") == 0) { + if (pAdapter->StaCfg.BssType != BSS_INFRA) { + /* Config has changed */ pAdapter->bConfigChanged = TRUE; - if (MONITOR_ON(pAdapter)) - { - RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, STANORMAL); - RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); + if (MONITOR_ON(pAdapter)) { + RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, + STANORMAL); + RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); Value &= (~0x80); RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value); - OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED); - pAdapter->StaCfg.bAutoReconnect = TRUE; - LinkDown(pAdapter, FALSE); - } - if (ADHOC_ON(pAdapter)) - { - // Set the AutoReconnectSsid to prevent it reconnect to old SSID - // Since calling this indicate user don't want to connect to that SSID anymore. - pAdapter->MlmeAux.AutoReconnectSsidLen= 32; - NdisZeroMemory(pAdapter->MlmeAux.AutoReconnectSsid, pAdapter->MlmeAux.AutoReconnectSsidLen); + OPSTATUS_CLEAR_FLAG(pAdapter, + fOP_STATUS_MEDIA_STATE_CONNECTED); + pAdapter->StaCfg.bAutoReconnect = TRUE; + LinkDown(pAdapter, FALSE); + } + if (ADHOC_ON(pAdapter)) { + /* Set the AutoReconnectSsid to prevent it reconnect to old SSID */ + /* Since calling this indicate user don't want to connect to that SSID anymore. */ + pAdapter->MlmeAux.AutoReconnectSsidLen = 32; + NdisZeroMemory(pAdapter->MlmeAux. + AutoReconnectSsid, + pAdapter->MlmeAux. + AutoReconnectSsidLen); LinkDown(pAdapter, FALSE); } } pAdapter->StaCfg.BssType = BSS_INFRA; - pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType; - DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(INFRA)\n")); - - pAdapter->StaCfg.BssType = BSS_INFRA; - } - else if (strcmp(arg, "Monitor") == 0) - { - UCHAR bbpValue = 0; + pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType; + DBGPRINT(RT_DEBUG_TRACE, + ("===>Set_NetworkType_Proc::(INFRA)\n")); + } else if (strcmp(arg, "Monitor") == 0) { + u8 bbpValue = 0; BCN_TIME_CFG_STRUC csr; OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_INFRA_ON); - OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_ADHOC_ON); + OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_ADHOC_ON); OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED); - // disable all periodic state machine + /* disable all periodic state machine */ pAdapter->StaCfg.bAutoReconnect = FALSE; - // reset all mlme state machine - RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); - DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_MEDIA_STATE_CONNECTED \n")); - if (pAdapter->CommonCfg.CentralChannel == 0) - { - if (pAdapter->CommonCfg.PhyMode == PHY_11AN_MIXED) - pAdapter->CommonCfg.CentralChannel = 36; - else - pAdapter->CommonCfg.CentralChannel = 6; - } - else - N_ChannelCheck(pAdapter); - - if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && - pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 && - pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) - { - // 40MHz ,control channel at lower - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue); + /* reset all mlme state machine */ + RTMP_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, + ("fOP_STATUS_MEDIA_STATE_CONNECTED \n")); + if (pAdapter->CommonCfg.CentralChannel == 0) { + if (pAdapter->CommonCfg.PhyMode == PHY_11AN_MIXED) + pAdapter->CommonCfg.CentralChannel = 36; + else + pAdapter->CommonCfg.CentralChannel = 6; + } else + N_ChannelCheck(pAdapter); + + if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 && + pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == + EXTCHA_ABOVE) { + /* 40MHz ,control channel at lower */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, + &bbpValue); bbpValue &= (~0x18); bbpValue |= 0x10; - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, + bbpValue); pAdapter->CommonCfg.BBPCurrentBW = BW_40; - // RX : control channel at lower - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, &bbpValue); + /* RX : control channel at lower */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, + &bbpValue); bbpValue &= (~0x20); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, bbpValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, + bbpValue); RTMP_IO_READ32(pAdapter, TX_BAND_CFG, &Value); Value &= 0xfffffffe; RTMP_IO_WRITE32(pAdapter, TX_BAND_CFG, Value); - pAdapter->CommonCfg.CentralChannel = pAdapter->CommonCfg.Channel + 2; - AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAdapter, pAdapter->CommonCfg.CentralChannel); - DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n", - pAdapter->CommonCfg.Channel, - pAdapter->CommonCfg.CentralChannel)); - } - else if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && - pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 && - pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW) - { - // 40MHz ,control channel at upper - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue); + pAdapter->CommonCfg.CentralChannel = + pAdapter->CommonCfg.Channel + 2; + AsicSwitchChannel(pAdapter, + pAdapter->CommonCfg.CentralChannel, + FALSE); + AsicLockChannel(pAdapter, + pAdapter->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, + ("BW_40 ,control_channel(%d), CentralChannel(%d) \n", + pAdapter->CommonCfg.Channel, + pAdapter->CommonCfg.CentralChannel)); + } else if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED + && pAdapter->CommonCfg.RegTransmitSetting.field.BW == + BW_40 + && pAdapter->CommonCfg.RegTransmitSetting.field. + EXTCHA == EXTCHA_BELOW) { + /* 40MHz ,control channel at upper */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, + &bbpValue); bbpValue &= (~0x18); bbpValue |= 0x10; - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, + bbpValue); pAdapter->CommonCfg.BBPCurrentBW = BW_40; RTMP_IO_READ32(pAdapter, TX_BAND_CFG, &Value); Value |= 0x1; RTMP_IO_WRITE32(pAdapter, TX_BAND_CFG, Value); - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, &bbpValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, + &bbpValue); bbpValue |= (0x20); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, bbpValue); - pAdapter->CommonCfg.CentralChannel = pAdapter->CommonCfg.Channel - 2; - AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAdapter, pAdapter->CommonCfg.CentralChannel); - DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n", - pAdapter->CommonCfg.Channel, - pAdapter->CommonCfg.CentralChannel)); - } - else - { - // 20MHz - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, + bbpValue); + pAdapter->CommonCfg.CentralChannel = + pAdapter->CommonCfg.Channel - 2; + AsicSwitchChannel(pAdapter, + pAdapter->CommonCfg.CentralChannel, + FALSE); + AsicLockChannel(pAdapter, + pAdapter->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, + ("BW_40 ,control_channel(%d), CentralChannel(%d) \n", + pAdapter->CommonCfg.Channel, + pAdapter->CommonCfg.CentralChannel)); + } else { + /* 20MHz */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, + &bbpValue); bbpValue &= (~0x18); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, + bbpValue); pAdapter->CommonCfg.BBPCurrentBW = BW_20; - AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.Channel, FALSE); + AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.Channel, + FALSE); AsicLockChannel(pAdapter, pAdapter->CommonCfg.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAdapter->CommonCfg.Channel)); + DBGPRINT(RT_DEBUG_TRACE, + ("BW_20, Channel(%d)\n", + pAdapter->CommonCfg.Channel)); } - // Enable Rx with promiscuous reception + /* Enable Rx with promiscuous reception */ RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, 0x3); - // ASIC supporsts sniffer function with replacing RSSI with timestamp. - //RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); - //Value |= (0x80); - //RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value); - // disable sync + /* ASIC supporsts sniffer function with replacing RSSI with timestamp. */ + /*RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); */ + /*Value |= (0x80); */ + /*RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value); */ + /* disable sync */ RTMP_IO_READ32(pAdapter, BCN_TIME_CFG, &csr.word); csr.field.bBeaconGen = 0; csr.field.bTBTTEnable = 0; @@ -3142,655 +2903,16 @@ INT Set_NetworkType_Proc( RTMP_IO_WRITE32(pAdapter, BCN_TIME_CFG, csr.word); pAdapter->StaCfg.BssType = BSS_MONITOR; - pAdapter->net_dev->type = ARPHRD_IEEE80211_PRISM; //ARPHRD_IEEE80211; // IEEE80211 - DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(MONITOR)\n")); - } - - // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key - pAdapter->StaCfg.WpaState = SS_NOTUSE; - - DBGPRINT(RT_DEBUG_TRACE, ("Set_NetworkType_Proc::(NetworkType=%d)\n", pAdapter->StaCfg.BssType)); - - return TRUE; -} - -/* - ========================================================================== - Description: - Set Authentication mode - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_AuthMode_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg) -{ - if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch; - else if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; - else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared; - else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; - else if ((strcmp(arg, "WPANONE") == 0) || (strcmp(arg, "wpanone") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; - else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; - else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA; - else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; - else - return FALSE; - - pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - - DBGPRINT(RT_DEBUG_TRACE, ("Set_AuthMode_Proc::(AuthMode=%d)\n", pAdapter->StaCfg.AuthMode)); - - return TRUE; -} - -/* - ========================================================================== - Description: - Set Encryption Type - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_EncrypType_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg) -{ - if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0)) - { - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; - pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; - pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; - } - else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0)) - { - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled; - pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled; - pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled; - } - else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0)) - { - if (pAdapter->StaCfg.AuthMode < Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - pAdapter->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; - pAdapter->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; - pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption2Enabled; - } - else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0)) - { - if (pAdapter->StaCfg.AuthMode < Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - pAdapter->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; - pAdapter->StaCfg.PairCipher = Ndis802_11Encryption3Enabled; - pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption3Enabled; - } - else - return FALSE; - - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; - - DBGPRINT(RT_DEBUG_TRACE, ("Set_EncrypType_Proc::(EncrypType=%d)\n", pAdapter->StaCfg.WepStatus)); - - return TRUE; -} - -/* - ========================================================================== - Description: - Set Default Key ID - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_DefaultKeyID_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg) -{ - ULONG KeyIdx; - - KeyIdx = simple_strtol(arg, 0, 10); - if((KeyIdx >= 1 ) && (KeyIdx <= 4)) - pAdapter->StaCfg.DefaultKeyId = (UCHAR) (KeyIdx - 1 ); - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_DefaultKeyID_Proc::(DefaultKeyID=%d)\n", pAdapter->StaCfg.DefaultKeyId)); - - return TRUE; -} - -/* - ========================================================================== - Description: - Set WEP KEY1 - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_Key1_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg) -{ - int KeyLen; - int i; - UCHAR CipherAlg=CIPHER_WEP64; - - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - KeyLen = strlen(arg); - - switch (KeyLen) - { - case 5: //wep 40 Ascii type - pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii")); - break; - case 10: //wep 40 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex")); - break; - case 13: //wep 104 Ascii type - pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii")); - break; - case 26: //wep 104 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex")); - break; - default: //Invalid argument - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::Invalid argument (=%s)\n", arg)); - return FALSE; - } - - pAdapter->SharedKey[BSS0][0].CipherAlg = CipherAlg; - - // Set keys (into ASIC) - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - ; // not support - else // Old WEP stuff - { - AsicAddSharedKeyEntry(pAdapter, - 0, - 0, - pAdapter->SharedKey[BSS0][0].CipherAlg, - pAdapter->SharedKey[BSS0][0].Key, - NULL, - NULL); - } - - return TRUE; -} -/* - ========================================================================== - - Description: - Set WEP KEY2 - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_Key2_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg) -{ - int KeyLen; - int i; - UCHAR CipherAlg=CIPHER_WEP64; - - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - KeyLen = strlen(arg); - - switch (KeyLen) - { - case 5: //wep 40 Ascii type - pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii")); - break; - case 10: //wep 40 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex")); - break; - case 13: //wep 104 Ascii type - pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii")); - break; - case 26: //wep 104 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex")); - break; - default: //Invalid argument - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::Invalid argument (=%s)\n", arg)); - return FALSE; - } - pAdapter->SharedKey[BSS0][1].CipherAlg = CipherAlg; - - // Set keys (into ASIC) - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - ; // not support - else // Old WEP stuff - { - AsicAddSharedKeyEntry(pAdapter, - 0, - 1, - pAdapter->SharedKey[BSS0][1].CipherAlg, - pAdapter->SharedKey[BSS0][1].Key, - NULL, - NULL); - } - - return TRUE; -} -/* - ========================================================================== - Description: - Set WEP KEY3 - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_Key3_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg) -{ - int KeyLen; - int i; - UCHAR CipherAlg=CIPHER_WEP64; - - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - KeyLen = strlen(arg); - - switch (KeyLen) - { - case 5: //wep 40 Ascii type - pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg)); - break; - case 10: //wep 40 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg)); - break; - case 13: //wep 104 Ascii type - pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg)); - break; - case 26: //wep 104 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg)); - break; - default: //Invalid argument - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::Invalid argument (=%s)\n", arg)); - return FALSE; - } - pAdapter->SharedKey[BSS0][2].CipherAlg = CipherAlg; - - // Set keys (into ASIC) - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - ; // not support - else // Old WEP stuff - { - AsicAddSharedKeyEntry(pAdapter, - 0, - 2, - pAdapter->SharedKey[BSS0][2].CipherAlg, - pAdapter->SharedKey[BSS0][2].Key, - NULL, - NULL); - } - - return TRUE; -} -/* - ========================================================================== - Description: - Set WEP KEY4 - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_Key4_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg) -{ - int KeyLen; - int i; - UCHAR CipherAlg=CIPHER_WEP64; - - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - KeyLen = strlen(arg); - - switch (KeyLen) - { - case 5: //wep 40 Ascii type - pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii")); - break; - case 10: //wep 40 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex")); - break; - case 13: //wep 104 Ascii type - pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii")); - break; - case 26: //wep 104 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex")); - break; - default: //Invalid argument - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::Invalid argument (=%s)\n", arg)); - return FALSE; - } - pAdapter->SharedKey[BSS0][3].CipherAlg = CipherAlg; - - // Set keys (into ASIC) - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - ; // not support - else // Old WEP stuff - { - AsicAddSharedKeyEntry(pAdapter, - 0, - 3, - pAdapter->SharedKey[BSS0][3].CipherAlg, - pAdapter->SharedKey[BSS0][3].Key, - NULL, - NULL); - } - - return TRUE; -} - -/* - ========================================================================== - Description: - Set WPA PSK key - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_WPAPSK_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg) -{ - UCHAR keyMaterial[40]; - - if ((pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && - (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) && - (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) - ) - return TRUE; // do nothing - - DBGPRINT(RT_DEBUG_TRACE, ("Set_WPAPSK_Proc::(WPAPSK=%s)\n", arg)); - - NdisZeroMemory(keyMaterial, 40); - - if ((strlen(arg) < 8) || (strlen(arg) > 64)) - { - DBGPRINT(RT_DEBUG_TRACE, ("Set failed!!(WPAPSK=%s), WPAPSK key-string required 8 ~ 64 characters \n", arg)); - return FALSE; - } - - if (strlen(arg) == 64) - { - AtoH(arg, keyMaterial, 32); - NdisMoveMemory(pAdapter->StaCfg.PMK, keyMaterial, 32); - - } - else - { - PasswordHash((char *)arg, pAdapter->MlmeAux.Ssid, pAdapter->MlmeAux.SsidLen, keyMaterial); - NdisMoveMemory(pAdapter->StaCfg.PMK, keyMaterial, 32); - } - - - - if(pAdapter->StaCfg.BssType == BSS_ADHOC && - pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - { - pAdapter->StaCfg.WpaState = SS_NOTUSE; - } - else - { - // Start STA supplicant state machine - pAdapter->StaCfg.WpaState = SS_START; - } - - return TRUE; -} - -/* - ========================================================================== - Description: - Set Power Saving mode - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_PSMode_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg) -{ - if (pAdapter->StaCfg.BssType == BSS_INFRA) - { - if ((strcmp(arg, "Max_PSP") == 0) || - (strcmp(arg, "max_psp") == 0) || - (strcmp(arg, "MAX_PSP") == 0)) - { - // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() - // to exclude certain situations. - if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) - pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP; - pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP; - OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); - pAdapter->StaCfg.DefaultListenCount = 5; - - } - else if ((strcmp(arg, "Fast_PSP") == 0) || - (strcmp(arg, "fast_psp") == 0) || - (strcmp(arg, "FAST_PSP") == 0)) - { - // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() - // to exclude certain situations. - OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); - if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) - pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP; - pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP; - pAdapter->StaCfg.DefaultListenCount = 3; - } - else if ((strcmp(arg, "Legacy_PSP") == 0) || - (strcmp(arg, "legacy_psp") == 0) || - (strcmp(arg, "LEGACY_PSP") == 0)) - { - // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() - // to exclude certain situations. - OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); - if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) - pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP; - pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP; - pAdapter->StaCfg.DefaultListenCount = 3; - } - else - { - //Default Ndis802_11PowerModeCAM - // clear PSM bit immediately - MlmeSetPsmBit(pAdapter, PWR_ACTIVE); - OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); - if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) - pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; - pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; - } - - DBGPRINT(RT_DEBUG_TRACE, ("Set_PSMode_Proc::(PSMode=%ld)\n", pAdapter->StaCfg.WindowsPowerMode)); - } - else - return FALSE; - - - return TRUE; -} - -/* - ========================================================================== - Description: - Set WpaSupport flag. - Value: - 0: Driver ignore wpa_supplicant. - 1: wpa_supplicant initiates scanning and AP selection. - 2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters. - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_Wpa_Support( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - - if ( simple_strtol(arg, 0, 10) == 0) - pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; - else if ( simple_strtol(arg, 0, 10) == 1) - pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; - else if ( simple_strtol(arg, 0, 10) == 2) - pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE_WITH_WEB_UI; - else - pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; - - DBGPRINT(RT_DEBUG_TRACE, ("Set_Wpa_Support::(WpaSupplicantUP=%d)\n", pAd->StaCfg.WpaSupplicantUP)); - - return TRUE; -} - -INT Set_TGnWifiTest_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - if (simple_strtol(arg, 0, 10) == 0) - pAd->StaCfg.bTGnWifiTest = FALSE; - else - pAd->StaCfg.bTGnWifiTest = TRUE; - - DBGPRINT(RT_DEBUG_TRACE, ("IF Set_TGnWifiTest_Proc::(bTGnWifiTest=%d)\n", pAd->StaCfg.bTGnWifiTest)); - return TRUE; -} - -INT Set_LongRetryLimit_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg) -{ - TX_RTY_CFG_STRUC tx_rty_cfg; - UCHAR LongRetryLimit = (UCHAR)simple_strtol(arg, 0, 10); - - RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); - tx_rty_cfg.field.LongRtyLimit = LongRetryLimit; - RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word); - DBGPRINT(RT_DEBUG_TRACE, ("IF Set_LongRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word)); - return TRUE; -} + pAdapter->net_dev->type = ARPHRD_IEEE80211_PRISM; /*ARPHRD_IEEE80211; // IEEE80211 */ + DBGPRINT(RT_DEBUG_TRACE, + ("===>Set_NetworkType_Proc::(MONITOR)\n")); + } + /* Reset Ralink supplicant to not use, it will be set to start when UI set PMK key */ + pAdapter->StaCfg.WpaState = SS_NOTUSE; -INT Set_ShortRetryLimit_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR arg) -{ - TX_RTY_CFG_STRUC tx_rty_cfg; - UCHAR ShortRetryLimit = (UCHAR)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, + ("Set_NetworkType_Proc::(NetworkType=%d)\n", + pAdapter->StaCfg.BssType)); - RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); - tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit; - RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word); - DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ShortRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word)); return TRUE; } diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c new file mode 100644 index 0000000000000000000000000000000000000000..925a236e104421214ec53e31ec571fb5107c9ab9 --- /dev/null +++ b/drivers/staging/rt2860/usb_main_dev.c @@ -0,0 +1,887 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, 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 "rt_config.h" + +/* Following information will be show when you run 'modinfo' */ +/* *** If you have a solution for the bug in current version of driver, please mail to me. */ +/* Otherwise post to forum in ralinktech's web site(www.ralinktech.com) and let all users help you. *** */ +MODULE_AUTHOR("Paul Lin "); +MODULE_DESCRIPTION("RT2870/RT3070 Wireless Lan Linux Driver"); +MODULE_LICENSE("GPL"); +#ifdef MODULE_VERSION +MODULE_VERSION(STA_DRIVER_VERSION); +#endif + +/* module table */ +struct usb_device_id rtusb_usb_id[] = { +#ifdef RT2870 + {USB_DEVICE(0x148F, 0x2770)}, /* Ralink */ + {USB_DEVICE(0x148F, 0x2870)}, /* Ralink */ + {USB_DEVICE(0x07B8, 0x2870)}, /* AboCom */ + {USB_DEVICE(0x07B8, 0x2770)}, /* AboCom */ + {USB_DEVICE(0x0DF6, 0x0039)}, /* Sitecom 2770 */ + {USB_DEVICE(0x083A, 0x7512)}, /* Arcadyan 2770 */ + {USB_DEVICE(0x0789, 0x0162)}, /* Logitec 2870 */ + {USB_DEVICE(0x0789, 0x0163)}, /* Logitec 2870 */ + {USB_DEVICE(0x0789, 0x0164)}, /* Logitec 2870 */ + {USB_DEVICE(0x177f, 0x0302)}, /* lsusb */ + {USB_DEVICE(0x0B05, 0x1731)}, /* Asus */ + {USB_DEVICE(0x0B05, 0x1732)}, /* Asus */ + {USB_DEVICE(0x0B05, 0x1742)}, /* Asus */ + {USB_DEVICE(0x0DF6, 0x0017)}, /* Sitecom */ + {USB_DEVICE(0x0DF6, 0x002B)}, /* Sitecom */ + {USB_DEVICE(0x0DF6, 0x002C)}, /* Sitecom */ + {USB_DEVICE(0x0DF6, 0x002D)}, /* Sitecom */ + {USB_DEVICE(0x14B2, 0x3C06)}, /* Conceptronic */ + {USB_DEVICE(0x14B2, 0x3C28)}, /* Conceptronic */ + {USB_DEVICE(0x2019, 0xED06)}, /* Planex Communications, Inc. */ + {USB_DEVICE(0x07D1, 0x3C09)}, /* D-Link */ + {USB_DEVICE(0x07D1, 0x3C11)}, /* D-Link */ + {USB_DEVICE(0x14B2, 0x3C07)}, /* AL */ + {USB_DEVICE(0x050D, 0x8053)}, /* Belkin */ + {USB_DEVICE(0x14B2, 0x3C23)}, /* Airlink */ + {USB_DEVICE(0x14B2, 0x3C27)}, /* Airlink */ + {USB_DEVICE(0x07AA, 0x002F)}, /* Corega */ + {USB_DEVICE(0x07AA, 0x003C)}, /* Corega */ + {USB_DEVICE(0x07AA, 0x003F)}, /* Corega */ + {USB_DEVICE(0x1044, 0x800B)}, /* Gigabyte */ + {USB_DEVICE(0x15A9, 0x0006)}, /* Sparklan */ + {USB_DEVICE(0x083A, 0xB522)}, /* SMC */ + {USB_DEVICE(0x083A, 0xA618)}, /* SMC */ + {USB_DEVICE(0x083A, 0x8522)}, /* Arcadyan */ + {USB_DEVICE(0x083A, 0x7522)}, /* Arcadyan */ + {USB_DEVICE(0x0CDE, 0x0022)}, /* ZCOM */ + {USB_DEVICE(0x0586, 0x3416)}, /* Zyxel */ + {USB_DEVICE(0x0CDE, 0x0025)}, /* Zyxel */ + {USB_DEVICE(0x1740, 0x9701)}, /* EnGenius */ + {USB_DEVICE(0x1740, 0x9702)}, /* EnGenius */ + {USB_DEVICE(0x0471, 0x200f)}, /* Philips */ + {USB_DEVICE(0x14B2, 0x3C25)}, /* Draytek */ + {USB_DEVICE(0x13D3, 0x3247)}, /* AzureWave */ + {USB_DEVICE(0x083A, 0x6618)}, /* Accton */ + {USB_DEVICE(0x15c5, 0x0008)}, /* Amit */ + {USB_DEVICE(0x0E66, 0x0001)}, /* Hawking */ + {USB_DEVICE(0x0E66, 0x0003)}, /* Hawking */ + {USB_DEVICE(0x129B, 0x1828)}, /* Siemens */ + {USB_DEVICE(0x157E, 0x300E)}, /* U-Media */ + {USB_DEVICE(0x050d, 0x805c)}, + {USB_DEVICE(0x050d, 0x815c)}, + {USB_DEVICE(0x1482, 0x3C09)}, /* Abocom */ + {USB_DEVICE(0x14B2, 0x3C09)}, /* Alpha */ + {USB_DEVICE(0x04E8, 0x2018)}, /* samsung */ + {USB_DEVICE(0x5A57, 0x0280)}, /* Zinwell */ + {USB_DEVICE(0x5A57, 0x0282)}, /* Zinwell */ + {USB_DEVICE(0x7392, 0x7718)}, + {USB_DEVICE(0x7392, 0x7717)}, + {USB_DEVICE(0x1737, 0x0070)}, /* Linksys WUSB100 */ + {USB_DEVICE(0x1737, 0x0071)}, /* Linksys WUSB600N */ + {USB_DEVICE(0x0411, 0x00e8)}, /* Buffalo WLI-UC-G300N */ + {USB_DEVICE(0x050d, 0x815c)}, /* Belkin F5D8053 */ +#endif /* RT2870 // */ +#ifdef RT3070 + {USB_DEVICE(0x148F, 0x3070)}, /* Ralink 3070 */ + {USB_DEVICE(0x148F, 0x3071)}, /* Ralink 3071 */ + {USB_DEVICE(0x148F, 0x3072)}, /* Ralink 3072 */ + {USB_DEVICE(0x0DB0, 0x3820)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DF6, 0x003E)}, /* Sitecom 3070 */ + {USB_DEVICE(0x0DF6, 0x0042)}, /* Sitecom 3072 */ + {USB_DEVICE(0x14B2, 0x3C12)}, /* AL 3070 */ + {USB_DEVICE(0x18C5, 0x0012)}, /* Corega 3070 */ + {USB_DEVICE(0x083A, 0x7511)}, /* Arcadyan 3070 */ + {USB_DEVICE(0x1740, 0x9703)}, /* EnGenius 3070 */ + {USB_DEVICE(0x1740, 0x9705)}, /* EnGenius 3071 */ + {USB_DEVICE(0x1740, 0x9706)}, /* EnGenius 3072 */ + {USB_DEVICE(0x13D3, 0x3273)}, /* AzureWave 3070 */ + {USB_DEVICE(0x1044, 0x800D)}, /* Gigabyte GN-WB32L 3070 */ + {USB_DEVICE(0x2019, 0xAB25)}, /* Planex Communications, Inc. RT3070 */ + {USB_DEVICE(0x07B8, 0x3070)}, /* AboCom 3070 */ + {USB_DEVICE(0x07B8, 0x3071)}, /* AboCom 3071 */ + {USB_DEVICE(0x07B8, 0x3072)}, /* Abocom 3072 */ + {USB_DEVICE(0x7392, 0x7711)}, /* Edimax 3070 */ + {USB_DEVICE(0x1A32, 0x0304)}, /* Quanta 3070 */ + {USB_DEVICE(0x1EDA, 0x2310)}, /* AirTies 3070 */ + {USB_DEVICE(0x07D1, 0x3C0A)}, /* D-Link 3072 */ + {USB_DEVICE(0x07D1, 0x3C0D)}, /* D-Link 3070 */ + {USB_DEVICE(0x07D1, 0x3C0E)}, /* D-Link 3070 */ + {USB_DEVICE(0x07D1, 0x3C0F)}, /* D-Link 3070 */ + {USB_DEVICE(0x1D4D, 0x000C)}, /* Pegatron Corporation 3070 */ + {USB_DEVICE(0x1D4D, 0x000E)}, /* Pegatron Corporation 3070 */ + {USB_DEVICE(0x5A57, 0x5257)}, /* Zinwell 3070 */ + {USB_DEVICE(0x5A57, 0x0283)}, /* Zinwell 3072 */ + {USB_DEVICE(0x04BB, 0x0945)}, /* I-O DATA 3072 */ + {USB_DEVICE(0x203D, 0x1480)}, /* Encore 3070 */ +#endif /* RT3070 // */ + {USB_DEVICE(0x0DF6, 0x003F)}, /* Sitecom WL-608 */ + {USB_DEVICE(0x1737, 0x0077)}, /* Linksys WUSB54GC-EU v3 */ + {USB_DEVICE(0x2001, 0x3C09)}, /* D-Link */ + {USB_DEVICE(0x2001, 0x3C0A)}, /* D-Link 3072 */ + {USB_DEVICE(0x2019, 0xED14)}, /* Planex Communications, Inc. */ + {} /* Terminating entry */ +}; + +int const rtusb_usb_id_len = + sizeof(rtusb_usb_id) / sizeof(struct usb_device_id); + +MODULE_DEVICE_TABLE(usb, rtusb_usb_id); + +static void rt2870_disconnect(struct usb_device *dev, struct rt_rtmp_adapter *pAd); + +static int __devinit rt2870_probe(IN struct usb_interface *intf, + IN struct usb_device *usb_dev, + IN const struct usb_device_id *dev_id, + struct rt_rtmp_adapter ** ppAd); + +#ifndef PF_NOFREEZE +#define PF_NOFREEZE 0 +#endif + +extern int rt28xx_close(IN struct net_device *net_dev); +extern int rt28xx_open(struct net_device *net_dev); + +static BOOLEAN USBDevConfigInit(IN struct usb_device *dev, + IN struct usb_interface *intf, + struct rt_rtmp_adapter *pAd); + +/* +======================================================================== +Routine Description: + Check the chipset vendor/product ID. + +Arguments: + _dev_p Point to the PCI or USB device + +Return Value: + TRUE Check ok + FALSE Check fail + +Note: +======================================================================== +*/ +BOOLEAN RT28XXChipsetCheck(IN void *_dev_p) +{ + struct usb_interface *intf = (struct usb_interface *)_dev_p; + struct usb_device *dev_p = interface_to_usbdev(intf); + u32 i; + + for (i = 0; i < rtusb_usb_id_len; i++) { + if (dev_p->descriptor.idVendor == rtusb_usb_id[i].idVendor && + dev_p->descriptor.idProduct == rtusb_usb_id[i].idProduct) { + printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n", + dev_p->descriptor.idVendor, + dev_p->descriptor.idProduct); + break; + } + } + + if (i == rtusb_usb_id_len) { + printk("rt2870: Error! Device Descriptor not matching!\n"); + return FALSE; + } + + return TRUE; +} + +/**************************************************************************/ +/**************************************************************************/ +/*tested for kernel 2.6series */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef CONFIG_PM +static int rt2870_suspend(struct usb_interface *intf, pm_message_t state); +static int rt2870_resume(struct usb_interface *intf); +#endif /* CONFIG_PM // */ + +static int rtusb_probe(struct usb_interface *intf, + const struct usb_device_id *id); +static void rtusb_disconnect(struct usb_interface *intf); + +static BOOLEAN USBDevConfigInit(IN struct usb_device *dev, + IN struct usb_interface *intf, + struct rt_rtmp_adapter *pAd) +{ + struct usb_host_interface *iface_desc; + unsigned long BulkOutIdx; + u32 i; + + /* get the active interface descriptor */ + iface_desc = intf->cur_altsetting; + + /* get # of enpoints */ + pAd->NumberOfPipes = iface_desc->desc.bNumEndpoints; + DBGPRINT(RT_DEBUG_TRACE, + ("NumEndpoints=%d\n", iface_desc->desc.bNumEndpoints)); + + /* Configure Pipes */ + BulkOutIdx = 0; + + for (i = 0; i < pAd->NumberOfPipes; i++) { + if ((iface_desc->endpoint[i].desc.bmAttributes == + USB_ENDPOINT_XFER_BULK) && + ((iface_desc->endpoint[i].desc.bEndpointAddress & + USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)) { + pAd->BulkInEpAddr = + iface_desc->endpoint[i].desc.bEndpointAddress; + pAd->BulkInMaxPacketSize = + le2cpu16(iface_desc->endpoint[i].desc. + wMaxPacketSize); + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("BULK IN MaxPacketSize = %d\n", + pAd->BulkInMaxPacketSize)); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("EP address = 0x%2x\n", + iface_desc->endpoint[i].desc. + bEndpointAddress)); + } else + if ((iface_desc->endpoint[i].desc.bmAttributes == + USB_ENDPOINT_XFER_BULK) + && + ((iface_desc->endpoint[i].desc. + bEndpointAddress & USB_ENDPOINT_DIR_MASK) == + USB_DIR_OUT)) { + /* there are 6 bulk out EP. EP6 highest priority. */ + /* EP1-4 is EDCA. EP5 is HCCA. */ + pAd->BulkOutEpAddr[BulkOutIdx++] = + iface_desc->endpoint[i].desc.bEndpointAddress; + pAd->BulkOutMaxPacketSize = + le2cpu16(iface_desc->endpoint[i].desc. + wMaxPacketSize); + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("BULK OUT MaxPacketSize = %d\n", + pAd->BulkOutMaxPacketSize)); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("EP address = 0x%2x \n", + iface_desc->endpoint[i].desc. + bEndpointAddress)); + } + } + + if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0])) { + printk + ("%s: Could not find both bulk-in and bulk-out endpoints\n", + __FUNCTION__); + return FALSE; + } + + pAd->config = &dev->config->desc; + usb_set_intfdata(intf, pAd); + + return TRUE; + +} + +static int rtusb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct rt_rtmp_adapter *pAd; + struct usb_device *dev; + int rv; + + dev = interface_to_usbdev(intf); + dev = usb_get_dev(dev); + + rv = rt2870_probe(intf, dev, id, &pAd); + if (rv != 0) + usb_put_dev(dev); + + return rv; +} + +static void rtusb_disconnect(struct usb_interface *intf) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct rt_rtmp_adapter *pAd; + + pAd = usb_get_intfdata(intf); + usb_set_intfdata(intf, NULL); + + rt2870_disconnect(dev, pAd); +} + +struct usb_driver rtusb_driver = { + .name = "rt2870", + .probe = rtusb_probe, + .disconnect = rtusb_disconnect, + .id_table = rtusb_usb_id, + +#ifdef CONFIG_PM +suspend:rt2870_suspend, +resume:rt2870_resume, +#endif +}; + +#ifdef CONFIG_PM + +void RT2870RejectPendingPackets(struct rt_rtmp_adapter *pAd) +{ + /* clear PS packets */ + /* clear TxSw packets */ +} + +static int rt2870_suspend(struct usb_interface *intf, pm_message_t state) +{ + struct net_device *net_dev; + struct rt_rtmp_adapter *pAd = usb_get_intfdata(intf); + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_suspend()\n")); + net_dev = pAd->net_dev; + netif_device_detach(net_dev); + + pAd->PM_FlgSuspend = 1; + if (netif_running(net_dev)) { + RTUSBCancelPendingBulkInIRP(pAd); + RTUSBCancelPendingBulkOutIRP(pAd); + } + DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_suspend()\n")); + return 0; +} + +static int rt2870_resume(struct usb_interface *intf) +{ + struct net_device *net_dev; + struct rt_rtmp_adapter *pAd = usb_get_intfdata(intf); + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_resume()\n")); + + pAd->PM_FlgSuspend = 0; + net_dev = pAd->net_dev; + netif_device_attach(net_dev); + netif_start_queue(net_dev); + netif_carrier_on(net_dev); + netif_wake_queue(net_dev); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_resume()\n")); + return 0; +} +#endif /* CONFIG_PM // */ + +/* Init driver module */ +int __init rtusb_init(void) +{ + printk("rtusb init --->\n"); + return usb_register(&rtusb_driver); +} + +/* Deinit driver module */ +void __exit rtusb_exit(void) +{ + usb_deregister(&rtusb_driver); + printk("<--- rtusb exit\n"); +} + +module_init(rtusb_init); +module_exit(rtusb_exit); + +/*--------------------------------------------------------------------- */ +/* function declarations */ +/*--------------------------------------------------------------------- */ + +/* +======================================================================== +Routine Description: + MLME kernel thread. + +Arguments: + *Context the pAd, driver control block pointer + +Return Value: + 0 close the thread + +Note: +======================================================================== +*/ +int MlmeThread(IN void *Context) +{ + struct rt_rtmp_adapter *pAd; + struct rt_rtmp_os_task *pTask; + int status; + status = 0; + + pTask = (struct rt_rtmp_os_task *)Context; + pAd = (struct rt_rtmp_adapter *)pTask->priv; + + RtmpOSTaskCustomize(pTask); + + while (!pTask->task_killed) { +#ifdef KTHREAD_SUPPORT + RTMP_WAIT_EVENT_INTERRUPTIBLE(pAd, pTask); +#else + RTMP_SEM_EVENT_WAIT(&(pTask->taskSema), status); + + /* unlock the device pointers */ + if (status != 0) { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } +#endif + + /* lock the device pointers , need to check if required */ + /*down(&(pAd->usbdev_semaphore)); */ + + if (!pAd->PM_FlgSuspend) + MlmeHandler(pAd); + } + + /* notify the exit routine that we're actually exiting now + * + * complete()/wait_for_completion() is similar to up()/down(), + * except that complete() is safe in the case where the structure + * is getting deleted in a parallel mode of execution (i.e. just + * after the down() -- that's necessary for the thread-shutdown + * case. + * + * complete_and_exit() goes even further than this -- it is safe in + * the case that the thread of the caller is going away (not just + * the structure) -- this is necessary for the module-remove case. + * This is important in preemption kernels, which transfer the flow + * of execution immediately upon a complete(). + */ + DBGPRINT(RT_DEBUG_TRACE, ("<---%s\n", __FUNCTION__)); +#ifndef KTHREAD_SUPPORT + pTask->taskPID = THREAD_PID_INIT_VALUE; + complete_and_exit(&pTask->taskComplete, 0); +#endif + return 0; + +} + +/* +======================================================================== +Routine Description: + USB command kernel thread. + +Arguments: + *Context the pAd, driver control block pointer + +Return Value: + 0 close the thread + +Note: +======================================================================== +*/ +int RTUSBCmdThread(IN void *Context) +{ + struct rt_rtmp_adapter *pAd; + struct rt_rtmp_os_task *pTask; + int status; + status = 0; + + pTask = (struct rt_rtmp_os_task *)Context; + pAd = (struct rt_rtmp_adapter *)pTask->priv; + + RtmpOSTaskCustomize(pTask); + + NdisAcquireSpinLock(&pAd->CmdQLock); + pAd->CmdQ.CmdQState = RTMP_TASK_STAT_RUNNING; + NdisReleaseSpinLock(&pAd->CmdQLock); + + while (pAd && pAd->CmdQ.CmdQState == RTMP_TASK_STAT_RUNNING) { +#ifdef KTHREAD_SUPPORT + RTMP_WAIT_EVENT_INTERRUPTIBLE(pAd, pTask); +#else + /* lock the device pointers */ + RTMP_SEM_EVENT_WAIT(&(pTask->taskSema), status); + + if (status != 0) { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } +#endif + + if (pAd->CmdQ.CmdQState == RTMP_TASK_STAT_STOPED) + break; + + if (!pAd->PM_FlgSuspend) + CMDHandler(pAd); + } + + if (pAd && !pAd->PM_FlgSuspend) { /* Clear the CmdQElements. */ + struct rt_cmdqelmt *pCmdQElmt = NULL; + + NdisAcquireSpinLock(&pAd->CmdQLock); + pAd->CmdQ.CmdQState = RTMP_TASK_STAT_STOPED; + while (pAd->CmdQ.size) { + RTUSBDequeueCmd(&pAd->CmdQ, &pCmdQElmt); + if (pCmdQElmt) { + if (pCmdQElmt->CmdFromNdis == TRUE) { + if (pCmdQElmt->buffer != NULL) + os_free_mem(pAd, + pCmdQElmt->buffer); + os_free_mem(pAd, (u8 *)pCmdQElmt); + } else { + if ((pCmdQElmt->buffer != NULL) + && (pCmdQElmt->bufferlength != 0)) + os_free_mem(pAd, + pCmdQElmt->buffer); + os_free_mem(pAd, (u8 *)pCmdQElmt); + } + } + } + + NdisReleaseSpinLock(&pAd->CmdQLock); + } + /* notify the exit routine that we're actually exiting now + * + * complete()/wait_for_completion() is similar to up()/down(), + * except that complete() is safe in the case where the structure + * is getting deleted in a parallel mode of execution (i.e. just + * after the down() -- that's necessary for the thread-shutdown + * case. + * + * complete_and_exit() goes even further than this -- it is safe in + * the case that the thread of the caller is going away (not just + * the structure) -- this is necessary for the module-remove case. + * This is important in preemption kernels, which transfer the flow + * of execution immediately upon a complete(). + */ + DBGPRINT(RT_DEBUG_TRACE, ("<---RTUSBCmdThread\n")); + +#ifndef KTHREAD_SUPPORT + pTask->taskPID = THREAD_PID_INIT_VALUE; + complete_and_exit(&pTask->taskComplete, 0); +#endif + return 0; + +} + +void RTUSBWatchDog(struct rt_rtmp_adapter *pAd) +{ + struct rt_ht_tx_context *pHTTXContext; + int idx; + unsigned long irqFlags; + PURB pUrb; + BOOLEAN needDumpSeq = FALSE; + u32 MACValue; + u32 TxRxQ_Pcnt; + + idx = 0; + RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue); + if ((MACValue & 0xff) != 0) { + DBGPRINT(RT_DEBUG_TRACE, + ("TX QUEUE 0 Not EMPTY(Value=0x%0x)!\n", + MACValue)); + RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40012); + while ((MACValue & 0xff) != 0 && (idx++ < 10)) { + RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue); + RTMPusecDelay(1); + } + RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006); + } + + if (pAd->watchDogRxOverFlowCnt >= 2) { + DBGPRINT(RT_DEBUG_TRACE, + ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n")); + if ((!RTMP_TEST_FLAG + (pAd, + (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_BULKIN_RESET | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) { + DBGPRINT(RT_DEBUG_TRACE, + ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n")); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, + NULL, 0); + needDumpSeq = TRUE; + } + pAd->watchDogRxOverFlowCnt = 0; + } + + RTUSBReadMACRegister(pAd, 0x438, &TxRxQ_Pcnt); + + for (idx = 0; idx < NUM_OF_TX_RING; idx++) { + pUrb = NULL; + + RTMP_IRQ_LOCK(&pAd->BulkOutLock[idx], irqFlags); + if ((pAd->BulkOutPending[idx] == TRUE) + && pAd->watchDogTxPendingCnt) { + int actual_length = 0, transfer_buffer_length = 0; + BOOLEAN isDataPacket = FALSE; + pAd->watchDogTxPendingCnt[idx]++; + + if ((pAd->watchDogTxPendingCnt[idx] > 2) && + (!RTMP_TEST_FLAG + (pAd, + (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST | + fRTMP_ADAPTER_BULKOUT_RESET))) + ) { + /* FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it! */ + pHTTXContext = + (struct rt_ht_tx_context *)(&pAd->TxContext[idx]); + if (pHTTXContext->IRPPending) { /* Check TxContext. */ + pUrb = pHTTXContext->pUrb; + + actual_length = pUrb->actual_length; + transfer_buffer_length = + pUrb->transfer_buffer_length; + isDataPacket = TRUE; + } else if (idx == MGMTPIPEIDX) { + struct rt_tx_context *pMLMEContext, *pNULLContext, + *pPsPollContext; + + /*Check MgmtContext. */ + pMLMEContext = + (struct rt_tx_context *)(pAd->MgmtRing. + Cell[pAd->MgmtRing. + TxDmaIdx]. + AllocVa); + pPsPollContext = + (struct rt_tx_context *)(&pAd->PsPollContext); + pNULLContext = + (struct rt_tx_context *)(&pAd->NullContext); + + if (pMLMEContext->IRPPending) { + ASSERT(pMLMEContext-> + IRPPending); + pUrb = pMLMEContext->pUrb; + } else if (pNULLContext->IRPPending) { + ASSERT(pNULLContext-> + IRPPending); + pUrb = pNULLContext->pUrb; + } else if (pPsPollContext->IRPPending) { + ASSERT(pPsPollContext-> + IRPPending); + pUrb = pPsPollContext->pUrb; + } + } + + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], + irqFlags); + + printk(KERN_INFO "%d:%lu LTL=%d , TL=%d L:%d\n", + idx, pAd->watchDogTxPendingCnt[idx], + pAd->TransferedLength[idx], + actual_length, transfer_buffer_length); + + if (pUrb) { + if ((isDataPacket + && pAd->TransferedLength[idx] == + actual_length + && pAd->TransferedLength[idx] < + transfer_buffer_length + && actual_length != 0 +/* && TxRxQ_Pcnt==0 */ + && pAd->watchDogTxPendingCnt[idx] > + 3) + || isDataPacket == FALSE + || pAd->watchDogTxPendingCnt[idx] > + 6) { + DBGPRINT(RT_DEBUG_TRACE, + ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", + idx)); + DBGPRINT(RT_DEBUG_TRACE, + ("Unlink the pending URB!\n")); + /* unlink it now */ + RTUSB_UNLINK_URB(pUrb); + /* Sleep 200 microseconds to give cancellation time to work */ + /*RTMPusecDelay(200); */ + needDumpSeq = TRUE; + } + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("Unknown bulkOut URB maybe hanged!\n")); + } + } else { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], + irqFlags); + } + + if (isDataPacket == TRUE) + pAd->TransferedLength[idx] = actual_length; + } else { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags); + } + } + + /* For Sigma debug, dump the ba_reordering sequence. */ + if ((needDumpSeq == TRUE) && (pAd->CommonCfg.bDisableReordering == 0)) { + u16 Idx; + struct rt_ba_rec_entry *pBAEntry = NULL; + u8 count = 0; + struct reordering_mpdu *mpdu_blk; + + Idx = pAd->MacTab.Content[BSSID_WCID].BARecWcidArray[0]; + + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + if ((pBAEntry->list.qlen > 0) && (pBAEntry->list.next != NULL)) { + DBGPRINT(RT_DEBUG_TRACE, + ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n")); + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + mpdu_blk = pBAEntry->list.next; + while (mpdu_blk) { + DBGPRINT(RT_DEBUG_TRACE, + ("\t%d:Seq-%d, bAMSDU-%d!\n", count, + mpdu_blk->Sequence, + mpdu_blk->bAMSDU)); + mpdu_blk = mpdu_blk->next; + count++; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("\npBAEntry->LastIndSeq=%d!\n", + pBAEntry->LastIndSeq)); + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); + } + } +} + +/* +======================================================================== +Routine Description: + Release allocated resources. + +Arguments: + *dev Point to the PCI or USB device + pAd driver control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +static void rt2870_disconnect(struct usb_device *dev, struct rt_rtmp_adapter *pAd) +{ + DBGPRINT(RT_DEBUG_ERROR, + ("rtusb_disconnect: unregister usbnet usb-%s-%s\n", + dev->bus->bus_name, dev->devpath)); + if (!pAd) { + usb_put_dev(dev); + printk("rtusb_disconnect: pAd == NULL!\n"); + return; + } + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); + + /* for debug, wait to show some messages to /proc system */ + udelay(1); + + RtmpPhyNetDevExit(pAd, pAd->net_dev); + + /* FIXME: Shall we need following delay and flush the schedule?? */ + udelay(1); + flush_scheduled_work(); + udelay(1); + + /* free the root net_device */ + RtmpOSNetDevFree(pAd->net_dev); + + RtmpRaDevCtrlExit(pAd); + + /* release a use of the usb device structure */ + usb_put_dev(dev); + udelay(1); + + DBGPRINT(RT_DEBUG_ERROR, (" RTUSB disconnect successfully\n")); +} + +static int __devinit rt2870_probe(IN struct usb_interface *intf, + IN struct usb_device *usb_dev, + IN const struct usb_device_id *dev_id, + struct rt_rtmp_adapter ** ppAd) +{ + struct net_device *net_dev = NULL; + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)NULL; + int status, rv; + void *handle; + struct rt_rtmp_os_netdev_op_hook netDevHook; + + DBGPRINT(RT_DEBUG_TRACE, ("===>rt2870_probe()!\n")); + + /* Check chipset vendor/product ID */ + /*if (RT28XXChipsetCheck(_dev_p) == FALSE) */ + /* goto err_out; */ + +/*RtmpDevInit============================================= */ + /* Allocate struct rt_rtmp_adapter adapter structure */ + handle = kmalloc(sizeof(struct os_cookie), GFP_KERNEL); + if (handle == NULL) { + printk + ("rt2870_probe(): Allocate memory for os handle failed!\n"); + return -ENOMEM; + } + ((struct os_cookie *)handle)->pUsb_Dev = usb_dev; + + rv = RTMPAllocAdapterBlock(handle, &pAd); + if (rv != NDIS_STATUS_SUCCESS) { + kfree(handle); + goto err_out; + } +/*USBDevInit============================================== */ + if (USBDevConfigInit(usb_dev, intf, pAd) == FALSE) + goto err_out_free_radev; + + RtmpRaDevCtrlInit(pAd, RTMP_DEV_INF_USB); + +/*NetDevInit============================================== */ + net_dev = RtmpPhyNetDevInit(pAd, &netDevHook); + if (net_dev == NULL) + goto err_out_free_radev; + + /* Here are the net_device structure with usb specific parameters. */ + /* for supporting Network Manager. + * Set the sysfs physical device reference for the network logical device if set prior to registration will + * cause a symlink during initialization. + */ + SET_NETDEV_DEV(net_dev, &(usb_dev->dev)); + + pAd->StaCfg.OriDevType = net_dev->type; + +/*All done, it's time to register the net device to linux kernel. */ + /* Register this device */ + status = RtmpOSNetDevAttach(net_dev, &netDevHook); + if (status != 0) + goto err_out_free_netdev; + +#ifdef KTHREAD_SUPPORT + init_waitqueue_head(&pAd->mlmeTask.kthread_q); + init_waitqueue_head(&pAd->timerTask.kthread_q); + init_waitqueue_head(&pAd->cmdQTask.kthread_q); +#endif + + *ppAd = pAd; + + DBGPRINT(RT_DEBUG_TRACE, ("<===rt2870_probe()!\n")); + + return 0; + + /* --------------------------- ERROR HANDLE --------------------------- */ +err_out_free_netdev: + RtmpOSNetDevFree(net_dev); + +err_out_free_radev: + RTMPFreeAdapter(pAd); + +err_out: + *ppAd = NULL; + + return -1; + +} diff --git a/drivers/staging/rt2860/wpa.h b/drivers/staging/rt2860/wpa.h index 7006e389e3233afd52d0e3e6fbe019eebbb4b70a..6199ae6cdcd03febb9d342c1bba5f48a877cef6b 100644 --- a/drivers/staging/rt2860/wpa.h +++ b/drivers/staging/rt2860/wpa.h @@ -38,7 +38,7 @@ #ifndef __WPA_H__ #define __WPA_H__ -// EAPOL Key descripter frame format related length +/* EAPOL Key descripter frame format related length */ #define LEN_KEY_DESC_NONCE 32 #define LEN_KEY_DESC_IV 16 #define LEN_KEY_DESC_RSC 8 @@ -46,39 +46,38 @@ #define LEN_KEY_DESC_REPLAY 8 #define LEN_KEY_DESC_MIC 16 -// The length is the EAPoL-Key frame except key data field. -// Please refer to 802.11i-2004 ,Figure 43u in p.78 -#define LEN_EAPOL_KEY_MSG (sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE) +/* The length is the EAPoL-Key frame except key data field. */ +/* Please refer to 802.11i-2004 ,Figure 43u in p.78 */ +#define LEN_EAPOL_KEY_MSG (sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE) -// EAP Code Type. +/* EAP Code Type. */ #define EAP_CODE_REQUEST 1 #define EAP_CODE_RESPONSE 2 #define EAP_CODE_SUCCESS 3 #define EAP_CODE_FAILURE 4 -// EAPOL frame Protocol Version +/* EAPOL frame Protocol Version */ #define EAPOL_VER 1 #define EAPOL_VER2 2 -// EAPOL-KEY Descriptor Type +/* EAPOL-KEY Descriptor Type */ #define WPA1_KEY_DESC 0xfe #define WPA2_KEY_DESC 0x02 -// Key Descriptor Version of Key Information +/* Key Descriptor Version of Key Information */ #define DESC_TYPE_TKIP 1 #define DESC_TYPE_AES 2 -#define DESC_TYPE_MESH 3 #define LEN_MSG1_2WAY 0x7f #define MAX_LEN_OF_EAP_HS 256 #define LEN_MASTER_KEY 32 -// EAPOL EK, MK +/* EAPOL EK, MK */ #define LEN_EAP_EK 16 #define LEN_EAP_MICK 16 #define LEN_EAP_KEY ((LEN_EAP_EK)+(LEN_EAP_MICK)) -// TKIP key related +/* TKIP key related */ #define LEN_PMKID 16 #define LEN_TKIP_EK 16 #define LEN_TKIP_RXMICK 8 @@ -90,12 +89,18 @@ #define TKIP_AP_RXMICK_OFFSET (TKIP_AP_TXMICK_OFFSET+LEN_TKIP_TXMICK) #define TKIP_GTK_LENGTH ((LEN_TKIP_EK)+(LEN_TKIP_RXMICK)+(LEN_TKIP_TXMICK)) #define LEN_PTK ((LEN_EAP_KEY)+(LEN_TKIP_KEY)) +#define MIN_LEN_OF_GTK 5 +#define LEN_PMK 32 +#define LEN_PMK_NAME 16 +#define LEN_NONCE 32 -// RSN IE Length definition -#define MAX_LEN_OF_RSNIE 90 +/* RSN IE Length definition */ +#define MAX_LEN_OF_RSNIE 255 #define MIN_LEN_OF_RSNIE 8 -//EAP Packet Type +#define KEY_LIFETIME 3600 + +/*EAP Packet Type */ #define EAPPacket 0 #define EAPOLStart 1 #define EAPOLLogoff 2 @@ -114,11 +119,33 @@ #define PAIRWISEKEY 1 #define GROUPKEY 0 -// Retry timer counter initial value +/* Retry timer counter initial value */ #define PEER_MSG1_RETRY_TIMER_CTR 0 #define PEER_MSG3_RETRY_TIMER_CTR 10 #define GROUP_MSG1_RETRY_TIMER_CTR 20 +/*#ifdef CONFIG_AP_SUPPORT */ +/* WPA mechanism retry timer interval */ +#define PEER_MSG1_RETRY_EXEC_INTV 1000 /* 1 sec */ +#define PEER_MSG3_RETRY_EXEC_INTV 3000 /* 3 sec */ +#define GROUP_KEY_UPDATE_EXEC_INTV 1000 /* 1 sec */ +#define PEER_GROUP_KEY_UPDATE_INIV 2000 /* 2 sec */ + +#define ENQUEUE_EAPOL_START_TIMER 200 /* 200 ms */ + +/* group rekey interval */ +#define TIME_REKEY 0 +#define PKT_REKEY 1 +#define DISABLE_REKEY 2 +#define MAX_REKEY 2 + +#define MAX_REKEY_INTER 0x3ffffff +/*#endif // CONFIG_AP_SUPPORT // */ + +#define GROUP_SUITE 0 +#define PAIRWISE_SUITE 1 +#define AKM_SUITE 2 +#define PMKID_LIST 3 #define EAPOL_START_DISABLE 0 #define EAPOL_START_PSK 1 @@ -129,12 +156,33 @@ #define MIX_CIPHER_WPA2_TKIP_ON(x) (((x) & 0x02) != 0) #define MIX_CIPHER_WPA2_AES_ON(x) (((x) & 0x01) != 0) +#ifndef ROUND_UP #define ROUND_UP(__x, __y) \ - (((ULONG)((__x)+((__y)-1))) & ((ULONG)~((__y)-1))) + (((unsigned long)((__x)+((__y)-1))) & ((unsigned long)~((__y)-1))) +#endif + +#define SET_u16_TO_ARRARY(_V, _LEN) \ +{ \ + _V[0] = (_LEN & 0xFF00) >> 8; \ + _V[1] = (_LEN & 0xFF); \ +} + +#define INC_u16_TO_ARRARY(_V, _LEN) \ +{ \ + u16 var_len; \ + \ + var_len = (_V[0]<<8) | (_V[1]); \ + var_len += _LEN; \ + \ + _V[0] = (var_len & 0xFF00) >> 8; \ + _V[1] = (var_len & 0xFF); \ +} + +#define CONV_ARRARY_TO_u16(_V) ((_V[0]<<8) | (_V[1])) #define ADD_ONE_To_64BIT_VAR(_V) \ { \ - UCHAR cnt = LEN_KEY_DESC_REPLAY; \ + u8 cnt = LEN_KEY_DESC_REPLAY; \ do \ { \ cnt--; \ @@ -146,182 +194,200 @@ #define IS_WPA_CAPABILITY(a) (((a) >= Ndis802_11AuthModeWPA) && ((a) <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) -// EAPOL Key Information definition within Key descriptor format -typedef struct PACKED _KEY_INFO -{ - UCHAR KeyMic:1; - UCHAR Secure:1; - UCHAR Error:1; - UCHAR Request:1; - UCHAR EKD_DL:1; // EKD for AP; DL for STA - UCHAR Rsvd:3; - UCHAR KeyDescVer:3; - UCHAR KeyType:1; - UCHAR KeyIndex:2; - UCHAR Install:1; - UCHAR KeyAck:1; -} KEY_INFO, *PKEY_INFO; - -// EAPOL Key descriptor format -typedef struct PACKED _KEY_DESCRIPTER -{ - UCHAR Type; - KEY_INFO KeyInfo; - UCHAR KeyLength[2]; - UCHAR ReplayCounter[LEN_KEY_DESC_REPLAY]; - UCHAR KeyNonce[LEN_KEY_DESC_NONCE]; - UCHAR KeyIv[LEN_KEY_DESC_IV]; - UCHAR KeyRsc[LEN_KEY_DESC_RSC]; - UCHAR KeyId[LEN_KEY_DESC_ID]; - UCHAR KeyMic[LEN_KEY_DESC_MIC]; - UCHAR KeyDataLen[2]; - UCHAR KeyData[MAX_LEN_OF_RSNIE]; -} KEY_DESCRIPTER, *PKEY_DESCRIPTER; - -typedef struct PACKED _EAPOL_PACKET -{ - UCHAR ProVer; - UCHAR ProType; - UCHAR Body_Len[2]; - KEY_DESCRIPTER KeyDesc; -} EAPOL_PACKET, *PEAPOL_PACKET; - -//802.11i D10 page 83 -typedef struct PACKED _GTK_ENCAP -{ - UCHAR Kid:2; - UCHAR tx:1; - UCHAR rsv:5; - UCHAR rsv1; - UCHAR GTK[TKIP_GTK_LENGTH]; -} GTK_ENCAP, *PGTK_ENCAP; - -typedef struct PACKED _KDE_ENCAP -{ - UCHAR Type; - UCHAR Len; - UCHAR OUI[3]; - UCHAR DataType; - GTK_ENCAP GTKEncap; -} KDE_ENCAP, *PKDE_ENCAP; - -// For WPA1 -typedef struct PACKED _RSNIE { - UCHAR oui[4]; - USHORT version; - UCHAR mcast[4]; - USHORT ucount; - struct PACKED { - UCHAR oui[4]; - }ucast[1]; -} RSNIE, *PRSNIE; - -// For WPA2 -typedef struct PACKED _RSNIE2 { - USHORT version; - UCHAR mcast[4]; - USHORT ucount; - struct PACKED { - UCHAR oui[4]; - }ucast[1]; -} RSNIE2, *PRSNIE2; - -// AKM Suite -typedef struct PACKED _RSNIE_AUTH { - USHORT acount; - struct PACKED { - UCHAR oui[4]; - }auth[1]; -} RSNIE_AUTH,*PRSNIE_AUTH; - -typedef union PACKED _RSN_CAPABILITIES { - struct PACKED { - USHORT PreAuth:1; - USHORT No_Pairwise:1; - USHORT PTKSA_R_Counter:2; - USHORT GTKSA_R_Counter:2; - USHORT Rsvd:10; - } field; - USHORT word; -} RSN_CAPABILITIES, *PRSN_CAPABILITIES; - -typedef struct PACKED _EAP_HDR { - UCHAR ProVer; - UCHAR ProType; - UCHAR Body_Len[2]; - UCHAR code; - UCHAR identifier; - UCHAR length[2]; // including code and identifier, followed by length-2 octets of data -} EAP_HDR, *PEAP_HDR; - -// For supplicant state machine states. 802.11i Draft 4.1, p. 97 -// We simplified it -typedef enum _WpaState -{ - SS_NOTUSE, // 0 - SS_START, // 1 - SS_WAIT_MSG_3, // 2 - SS_WAIT_GROUP, // 3 - SS_FINISH, // 4 - SS_KEYUPDATE, // 5 -} WPA_STATE; - -// -// The definition of the cipher combination -// -// bit3 bit2 bit1 bit0 -// +------------+------------+ -// | WPA | WPA2 | -// +------+-----+------+-----+ -// | TKIP | AES | TKIP | AES | -// | 0 | 1 | 1 | 0 | -> 0x06 -// | 0 | 1 | 1 | 1 | -> 0x07 -// | 1 | 0 | 0 | 1 | -> 0x09 -// | 1 | 0 | 1 | 1 | -> 0x0B -// | 1 | 1 | 0 | 1 | -> 0x0D -// | 1 | 1 | 1 | 0 | -> 0x0E -// | 1 | 1 | 1 | 1 | -> 0x0F -// +------+-----+------+-----+ -// -typedef enum _WpaMixPairCipher -{ - MIX_CIPHER_NOTUSE = 0x00, - WPA_NONE_WPA2_TKIPAES = 0x03, // WPA2-TKIPAES - WPA_AES_WPA2_TKIP = 0x06, - WPA_AES_WPA2_TKIPAES = 0x07, - WPA_TKIP_WPA2_AES = 0x09, - WPA_TKIP_WPA2_TKIPAES = 0x0B, - WPA_TKIPAES_WPA2_NONE = 0x0C, // WPA-TKIPAES - WPA_TKIPAES_WPA2_AES = 0x0D, - WPA_TKIPAES_WPA2_TKIP = 0x0E, - WPA_TKIPAES_WPA2_TKIPAES = 0x0F, -} WPA_MIX_PAIR_CIPHER; - -typedef struct PACKED _RSN_IE_HEADER_STRUCT { - UCHAR Eid; - UCHAR Length; - USHORT Version; // Little endian format -} RSN_IE_HEADER_STRUCT, *PRSN_IE_HEADER_STRUCT; - -// Cipher suite selector types -typedef struct PACKED _CIPHER_SUITE_STRUCT { - UCHAR Oui[3]; - UCHAR Type; -} CIPHER_SUITE_STRUCT, *PCIPHER_SUITE_STRUCT; - -// Authentication and Key Management suite selector -typedef struct PACKED _AKM_SUITE_STRUCT { - UCHAR Oui[3]; - UCHAR Type; -} AKM_SUITE_STRUCT, *PAKM_SUITE_STRUCT; - -// RSN capability -typedef struct PACKED _RSN_CAPABILITY { - USHORT Rsv:10; - USHORT GTKSAReplayCnt:2; - USHORT PTKSAReplayCnt:2; - USHORT NoPairwise:1; - USHORT PreAuth:1; -} RSN_CAPABILITY, *PRSN_CAPABILITY; +/* EAPOL Key Information definition within Key descriptor format */ +struct PACKED rt_key_info { + u8 KeyMic:1; + u8 Secure:1; + u8 Error:1; + u8 Request:1; + u8 EKD_DL:1; /* EKD for AP; DL for STA */ + u8 Rsvd:3; + u8 KeyDescVer:3; + u8 KeyType:1; + u8 KeyIndex:2; + u8 Install:1; + u8 KeyAck:1; +}; + +/* EAPOL Key descriptor format */ +struct PACKED rt_key_descripter { + u8 Type; + struct rt_key_info KeyInfo; + u8 KeyLength[2]; + u8 ReplayCounter[LEN_KEY_DESC_REPLAY]; + u8 KeyNonce[LEN_KEY_DESC_NONCE]; + u8 KeyIv[LEN_KEY_DESC_IV]; + u8 KeyRsc[LEN_KEY_DESC_RSC]; + u8 KeyId[LEN_KEY_DESC_ID]; + u8 KeyMic[LEN_KEY_DESC_MIC]; + u8 KeyDataLen[2]; + u8 KeyData[MAX_LEN_OF_RSNIE]; +}; + +struct PACKED rt_eapol_packet { + u8 ProVer; + u8 ProType; + u8 Body_Len[2]; + struct rt_key_descripter KeyDesc; +}; + +/*802.11i D10 page 83 */ +struct PACKED rt_gtk_encap { + u8 Kid:2; + u8 tx:1; + u8 rsv:5; + u8 rsv1; + u8 GTK[TKIP_GTK_LENGTH]; +}; + +struct PACKED rt_kde_encap { + u8 Type; + u8 Len; + u8 OUI[3]; + u8 DataType; + struct rt_gtk_encap GTKEncap; +}; + +/* For WPA1 */ +struct PACKED rt_rsnie { + u8 oui[4]; + u16 version; + u8 mcast[4]; + u16 ucount; + struct PACKED { + u8 oui[4]; + } ucast[1]; +}; + +/* For WPA2 */ +struct PACKED rt_rsnie2 { + u16 version; + u8 mcast[4]; + u16 ucount; + struct PACKED { + u8 oui[4]; + } ucast[1]; +}; + +/* AKM Suite */ +struct PACKED rt_rsnie_auth { + u16 acount; + struct PACKED { + u8 oui[4]; + } auth[1]; +}; + +typedef union PACKED _RSN_CAPABILITIES { + struct PACKED { + u16 PreAuth:1; + u16 No_Pairwise:1; + u16 PTKSA_R_Counter:2; + u16 GTKSA_R_Counter:2; + u16 Rsvd:10; + } field; + u16 word; +} RSN_CAPABILITIES, *PRSN_CAPABILITIES; + +struct PACKED rt_eap_hdr { + u8 ProVer; + u8 ProType; + u8 Body_Len[2]; + u8 code; + u8 identifier; + u8 length[2]; /* including code and identifier, followed by length-2 octets of data */ +}; + +/* For supplicant state machine states. 802.11i Draft 4.1, p. 97 */ +/* We simplified it */ +typedef enum _WpaState { + SS_NOTUSE, /* 0 */ + SS_START, /* 1 */ + SS_WAIT_MSG_3, /* 2 */ + SS_WAIT_GROUP, /* 3 */ + SS_FINISH, /* 4 */ + SS_KEYUPDATE, /* 5 */ +} WPA_STATE; + +/* */ +/* The definition of the cipher combination */ +/* */ +/* bit3 bit2 bit1 bit0 */ +/* +------------+------------+ */ +/* | WPA | WPA2 | */ +/* +------+-----+------+-----+ */ +/* | TKIP | AES | TKIP | AES | */ +/* | 0 | 1 | 1 | 0 | -> 0x06 */ +/* | 0 | 1 | 1 | 1 | -> 0x07 */ +/* | 1 | 0 | 0 | 1 | -> 0x09 */ +/* | 1 | 0 | 1 | 1 | -> 0x0B */ +/* | 1 | 1 | 0 | 1 | -> 0x0D */ +/* | 1 | 1 | 1 | 0 | -> 0x0E */ +/* | 1 | 1 | 1 | 1 | -> 0x0F */ +/* +------+-----+------+-----+ */ +/* */ +typedef enum _WpaMixPairCipher { + MIX_CIPHER_NOTUSE = 0x00, + WPA_NONE_WPA2_TKIPAES = 0x03, /* WPA2-TKIPAES */ + WPA_AES_WPA2_TKIP = 0x06, + WPA_AES_WPA2_TKIPAES = 0x07, + WPA_TKIP_WPA2_AES = 0x09, + WPA_TKIP_WPA2_TKIPAES = 0x0B, + WPA_TKIPAES_WPA2_NONE = 0x0C, /* WPA-TKIPAES */ + WPA_TKIPAES_WPA2_AES = 0x0D, + WPA_TKIPAES_WPA2_TKIP = 0x0E, + WPA_TKIPAES_WPA2_TKIPAES = 0x0F, +} WPA_MIX_PAIR_CIPHER; + +struct PACKED rt_rsn_ie_header { + u8 Eid; + u8 Length; + u16 Version; /* Little endian format */ +}; + +/* Cipher suite selector types */ +struct PACKED rt_cipher_suite_struct { + u8 Oui[3]; + u8 Type; +}; + +/* Authentication and Key Management suite selector */ +struct PACKED rt_akm_suite { + u8 Oui[3]; + u8 Type; +}; + +/* RSN capability */ +struct PACKED rt_rsn_capability { + u16 Rsv:10; + u16 GTKSAReplayCnt:2; + u16 PTKSAReplayCnt:2; + u16 NoPairwise:1; + u16 PreAuth:1; +}; + +/*======================================== + The prototype is defined in cmm_wpa.c + ========================================*/ +BOOLEAN WpaMsgTypeSubst(u8 EAPType, int * MsgType); + +void PRF(u8 * key, + int key_len, + u8 * prefix, + int prefix_len, + u8 * data, int data_len, u8 * output, int len); + +int PasswordHash(char *password, + unsigned char *ssid, int ssidlength, unsigned char *output); + +u8 *GetSuiteFromRSNIE(u8 *rsnie, + u32 rsnie_len, u8 type, u8 * count); + +void WpaShowAllsuite(u8 *rsnie, u32 rsnie_len); + +void RTMPInsertRSNIE(u8 *pFrameBuf, + unsigned long *pFrameLen, + u8 *rsnie_ptr, + u8 rsnie_len, + u8 *pmkid_ptr, u8 pmkid_len); #endif diff --git a/drivers/staging/rt2870/2870_main_dev.c b/drivers/staging/rt2870/2870_main_dev.c deleted file mode 100644 index d0ed48bed2bb90f5e3a8e99f5fb0a5a6069b851d..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2870/2870_main_dev.c +++ /dev/null @@ -1,1530 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rtmp_main.c - - Abstract: - main initialization routines - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Name Date Modification logs - Jan Lee 01-10-2005 modified - Sample Jun/01/07 Merge RT2870 and RT2860 drivers. -*/ - -#include "rt_config.h" - - -// Following information will be show when you run 'modinfo' -// *** If you have a solution for the bug in current version of driver, please mail to me. -// Otherwise post to forum in ralinktech's web site(www.ralinktech.com) and let all users help you. *** -MODULE_AUTHOR("Paul Lin "); -MODULE_DESCRIPTION(RT28xx_CHIP_NAME " Wireless LAN Linux Driver"); -MODULE_LICENSE("GPL"); -#ifdef MODULE_VERSION -MODULE_VERSION(STA_DRIVER_VERSION); -#endif -MODULE_ALIAS("rt3070sta"); - -/* Kernel thread and vars, which handles packets that are completed. Only - * 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. */ - -extern INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p, - IN UINT argc, OUT PRTMP_ADAPTER *ppAd); - -struct usb_device_id rtusb_usb_id[] = { - { USB_DEVICE(0x148F, 0x2770) }, /* Ralink */ - { USB_DEVICE(0x1737, 0x0071) }, /* Linksys WUSB600N */ - { USB_DEVICE(0x1737, 0x0070) }, /* Linksys */ - { USB_DEVICE(0x148F, 0x2870) }, /* Ralink */ - { USB_DEVICE(0x148F, 0x3070) }, /* Ralink 3070 */ - { USB_DEVICE(0x148F, 0x3071) }, /* Ralink 3071 */ - { USB_DEVICE(0x148F, 0x3072) }, /* Ralink 3072 */ - { USB_DEVICE(0x0B05, 0x1731) }, /* Asus */ - { USB_DEVICE(0x0B05, 0x1732) }, /* Asus */ - { USB_DEVICE(0x0B05, 0x1742) }, /* Asus */ - { USB_DEVICE(0x0DF6, 0x0017) }, /* Sitecom */ - { USB_DEVICE(0x0DF6, 0x002B) }, /* Sitecom */ - { USB_DEVICE(0x0DF6, 0x002C) }, /* Sitecom */ - { USB_DEVICE(0x0DF6, 0x003E) }, /* Sitecom 3070 */ - { USB_DEVICE(0x0DF6, 0x002D) }, /* Sitecom */ - { USB_DEVICE(0x0DF6, 0x0039) }, /* Sitecom 2770 */ - { USB_DEVICE(0x0DF6, 0x003F) }, /* Sitecom WL-608 */ - { USB_DEVICE(0x14B2, 0x3C06) }, /* Conceptronic */ - { USB_DEVICE(0x14B2, 0x3C28) }, /* Conceptronic */ - { USB_DEVICE(0x2019, 0xED06) }, /* Planex Communications, Inc. */ - { USB_DEVICE(0x2019, 0xED14) }, /* Planex Communications, Inc. */ - { USB_DEVICE(0x2019, 0xAB25) }, /* Planex Communications, Inc. RT3070 */ - { USB_DEVICE(0x07D1, 0x3C09) }, /* D-Link */ - { USB_DEVICE(0x07D1, 0x3C11) }, /* D-Link */ - { USB_DEVICE(0x2001, 0x3C09) }, /* D-Link */ - { USB_DEVICE(0x2001, 0x3C0A) }, /* D-Link 3072*/ - { USB_DEVICE(0x14B2, 0x3C07) }, /* AL */ - { USB_DEVICE(0x14B2, 0x3C12) }, /* AL 3070 */ - { USB_DEVICE(0x050D, 0x8053) }, /* Belkin */ - { USB_DEVICE(0x050D, 0x815C) }, /* Belkin */ - { USB_DEVICE(0x050D, 0x825a) }, /* Belkin */ - { USB_DEVICE(0x14B2, 0x3C23) }, /* Airlink */ - { USB_DEVICE(0x14B2, 0x3C27) }, /* Airlink */ - { USB_DEVICE(0x07AA, 0x002F) }, /* Corega */ - { USB_DEVICE(0x07AA, 0x003C) }, /* Corega */ - { USB_DEVICE(0x07AA, 0x003F) }, /* Corega */ - { USB_DEVICE(0x18C5, 0x0012) }, /* Corega 3070 */ - { USB_DEVICE(0x1044, 0x800B) }, /* Gigabyte */ - { USB_DEVICE(0x1044, 0x800D) }, /* Gigabyte GN-WB32L 3070 */ - { USB_DEVICE(0x15A9, 0x0006) }, /* Sparklan */ - { USB_DEVICE(0x083A, 0xB522) }, /* SMC */ - { USB_DEVICE(0x083A, 0xA618) }, /* SMC */ - { USB_DEVICE(0x083A, 0x8522) }, /* Arcadyan */ - { USB_DEVICE(0x083A, 0x7512) }, /* Arcadyan 2770 */ - { USB_DEVICE(0x083A, 0x7522) }, /* Arcadyan */ - { USB_DEVICE(0x083A, 0x7511) }, /* Arcadyan 3070 */ - { USB_DEVICE(0x0CDE, 0x0022) }, /* ZCOM */ - { USB_DEVICE(0x0586, 0x3416) }, /* Zyxel */ - { USB_DEVICE(0x0CDE, 0x0025) }, /* Zyxel */ - { USB_DEVICE(0x1740, 0x9701) }, /* EnGenius */ - { USB_DEVICE(0x1740, 0x9702) }, /* EnGenius */ - { USB_DEVICE(0x1740, 0x9703) }, /* EnGenius 3070 */ - { USB_DEVICE(0x0471, 0x200f) }, /* Philips */ - { USB_DEVICE(0x14B2, 0x3C25) }, /* Draytek */ - { USB_DEVICE(0x13D3, 0x3247) }, /* AzureWave */ - { USB_DEVICE(0x13D3, 0x3273) }, /* AzureWave 3070*/ - { USB_DEVICE(0x083A, 0x6618) }, /* Accton */ - { USB_DEVICE(0x15c5, 0x0008) }, /* Amit */ - { USB_DEVICE(0x0E66, 0x0001) }, /* Hawking */ - { USB_DEVICE(0x0E66, 0x0003) }, /* Hawking */ - { USB_DEVICE(0x129B, 0x1828) }, /* Siemens */ - { USB_DEVICE(0x157E, 0x300E) }, /* U-Media */ - { USB_DEVICE(0x050d, 0x805c) }, - { USB_DEVICE(0x1482, 0x3C09) }, /* Abocom*/ - { USB_DEVICE(0x14B2, 0x3C09) }, /* Alpha */ - { USB_DEVICE(0x04E8, 0x2018) }, /* samsung */ - { USB_DEVICE(0x07B8, 0x3070) }, /* AboCom 3070 */ - { USB_DEVICE(0x07B8, 0x3071) }, /* AboCom 3071 */ - { USB_DEVICE(0x07B8, 0x2870) }, /* AboCom */ - { USB_DEVICE(0x07B8, 0x2770) }, /* AboCom */ - { USB_DEVICE(0x07B8, 0x3072) }, /* Abocom 3072 */ - { USB_DEVICE(0x7392, 0x7711) }, /* Edimax 3070 */ - { USB_DEVICE(0x5A57, 0x0280) }, /* Zinwell */ - { USB_DEVICE(0x5A57, 0x0282) }, /* Zinwell */ - { USB_DEVICE(0x1A32, 0x0304) }, /* Quanta 3070 */ - { USB_DEVICE(0x0789, 0x0162) }, /* Logitec 2870 */ - { USB_DEVICE(0x0789, 0x0163) }, /* Logitec 2870 */ - { USB_DEVICE(0x0789, 0x0164) }, /* Logitec 2870 */ - { USB_DEVICE(0x7392, 0x7717) }, /* Edimax */ - { USB_DEVICE(0x1EDA, 0x2310) }, /* AirTies 3070 */ - { USB_DEVICE(0x1737, 0x0077) }, /* Linksys WUSB54GC-EU v3 */ - { } /* Terminating entry */ -}; - -INT const rtusb_usb_id_len = sizeof(rtusb_usb_id) / sizeof(struct usb_device_id); -MODULE_DEVICE_TABLE(usb, rtusb_usb_id); - -#ifndef PF_NOFREEZE -#define PF_NOFREEZE 0 -#endif - - -#ifdef CONFIG_PM -static int rt2870_suspend(struct usb_interface *intf, pm_message_t state); -static int rt2870_resume(struct usb_interface *intf); -#endif // CONFIG_PM // - -/**************************************************************************/ -/**************************************************************************/ -//tested for kernel 2.6series -/**************************************************************************/ -/**************************************************************************/ -static int rtusb_probe (struct usb_interface *intf, - const struct usb_device_id *id); -static void rtusb_disconnect(struct usb_interface *intf); - -struct usb_driver rtusb_driver = { - .name="rt2870", - .probe=rtusb_probe, - .disconnect=rtusb_disconnect, - .id_table=rtusb_usb_id, - -#ifdef CONFIG_PM - suspend: rt2870_suspend, - resume: rt2870_resume, -#endif - }; - -#ifdef CONFIG_PM - -VOID RT2860RejectPendingPackets( - IN PRTMP_ADAPTER pAd) -{ - // clear PS packets - // clear TxSw packets -} - -static int rt2870_suspend( - struct usb_interface *intf, - pm_message_t state) -{ - struct net_device *net_dev; - PRTMP_ADAPTER pAd = usb_get_intfdata(intf); - - - DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_suspend()\n")); - net_dev = pAd->net_dev; - netif_device_detach (net_dev); - - pAd->PM_FlgSuspend = 1; - if (netif_running(net_dev)) { - RTUSBCancelPendingBulkInIRP(pAd); - RTUSBCancelPendingBulkOutIRP(pAd); - } - DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_suspend()\n")); - return 0; -} - -static int rt2870_resume( - struct usb_interface *intf) -{ - struct net_device *net_dev; - PRTMP_ADAPTER pAd = usb_get_intfdata(intf); - - - DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_resume()\n")); - - pAd->PM_FlgSuspend = 0; - net_dev = pAd->net_dev; - netif_device_attach (net_dev); - netif_start_queue(net_dev); - netif_carrier_on(net_dev); - netif_wake_queue(net_dev); - - DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_resume()\n")); - return 0; -} -#endif // CONFIG_PM // - - -// Init driver module -INT __init rtusb_init(void) -{ - printk("rtusb init --->\n"); - return usb_register(&rtusb_driver); -} - -// Deinit driver module -VOID __exit rtusb_exit(void) -{ - usb_deregister(&rtusb_driver); - printk("<--- rtusb exit\n"); -} - -module_init(rtusb_init); -module_exit(rtusb_exit); - - - - -/*--------------------------------------------------------------------- */ -/* function declarations */ -/*--------------------------------------------------------------------- */ - -/* -======================================================================== -Routine Description: - MLME kernel thread. - -Arguments: - *Context the pAd, driver control block pointer - -Return Value: - 0 close the thread - -Note: -======================================================================== -*/ -INT MlmeThread( - IN void *Context) -{ - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context; - POS_COOKIE pObj; - int status; - - pObj = (POS_COOKIE)pAd->OS_Cookie; - - rtmp_os_thread_init("rt2870MlmeThread", (PVOID)&(pAd->mlmeComplete)); - - while (pAd->mlme_kill == 0) - { - /* lock the device pointers */ - //down(&(pAd->mlme_semaphore)); - status = down_interruptible(&(pAd->mlme_semaphore)); - - /* lock the device pointers , need to check if required*/ - //down(&(pAd->usbdev_semaphore)); - - if (!pAd->PM_FlgSuspend) - MlmeHandler(pAd); - - /* unlock the device pointers */ - //up(&(pAd->usbdev_semaphore)); - if (status != 0) - { - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); - break; - } - } - - /* notify the exit routine that we're actually exiting now - * - * complete()/wait_for_completion() is similar to up()/down(), - * except that complete() is safe in the case where the structure - * is getting deleted in a parallel mode of execution (i.e. just - * after the down() -- that's necessary for the thread-shutdown - * case. - * - * complete_and_exit() goes even further than this -- it is safe in - * the case that the thread of the caller is going away (not just - * the structure) -- this is necessary for the module-remove case. - * This is important in preemption kernels, which transfer the flow - * of execution immediately upon a complete(). - */ - DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__)); - - pObj->MLMEThr_pid = NULL; - - complete_and_exit (&pAd->mlmeComplete, 0); - return 0; - -} - - -/* -======================================================================== -Routine Description: - USB command kernel thread. - -Arguments: - *Context the pAd, driver control block pointer - -Return Value: - 0 close the thread - -Note: -======================================================================== -*/ -INT RTUSBCmdThread( - IN void * Context) -{ - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context; - POS_COOKIE pObj; - int status; - - pObj = (POS_COOKIE)pAd->OS_Cookie; - - rtmp_os_thread_init("rt2870CmdThread", (PVOID)&(pAd->CmdQComplete)); - - NdisAcquireSpinLock(&pAd->CmdQLock); - pAd->CmdQ.CmdQState = RT2870_THREAD_RUNNING; - NdisReleaseSpinLock(&pAd->CmdQLock); - - while (pAd->CmdQ.CmdQState == RT2870_THREAD_RUNNING) - { - /* lock the device pointers */ - //down(&(pAd->RTUSBCmd_semaphore)); - status = down_interruptible(&(pAd->RTUSBCmd_semaphore)); - - if (pAd->CmdQ.CmdQState == RT2870_THREAD_STOPED) - break; - - if (status != 0) - { - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); - break; - } - /* lock the device pointers , need to check if required*/ - //down(&(pAd->usbdev_semaphore)); - - if (!pAd->PM_FlgSuspend) - CMDHandler(pAd); - - /* unlock the device pointers */ - //up(&(pAd->usbdev_semaphore)); - } - - if (!pAd->PM_FlgSuspend) - { // Clear the CmdQElements. - CmdQElmt *pCmdQElmt = NULL; - - NdisAcquireSpinLock(&pAd->CmdQLock); - pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED; - while(pAd->CmdQ.size) - { - RTUSBDequeueCmd(&pAd->CmdQ, &pCmdQElmt); - if (pCmdQElmt) - { - if (pCmdQElmt->CmdFromNdis == TRUE) - { - if (pCmdQElmt->buffer != NULL) - NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0); - - NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0); - } - else - { - if ((pCmdQElmt->buffer != NULL) && (pCmdQElmt->bufferlength != 0)) - NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0); - { - NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0); - } - } - } - } - - NdisReleaseSpinLock(&pAd->CmdQLock); - } - /* notify the exit routine that we're actually exiting now - * - * complete()/wait_for_completion() is similar to up()/down(), - * except that complete() is safe in the case where the structure - * is getting deleted in a parallel mode of execution (i.e. just - * after the down() -- that's necessary for the thread-shutdown - * case. - * - * complete_and_exit() goes even further than this -- it is safe in - * the case that the thread of the caller is going away (not just - * the structure) -- this is necessary for the module-remove case. - * This is important in preemption kernels, which transfer the flow - * of execution immediately upon a complete(). - */ - DBGPRINT(RT_DEBUG_TRACE,( "<---RTUSBCmdThread\n")); - - pObj->RTUSBCmdThr_pid = NULL; - - complete_and_exit (&pAd->CmdQComplete, 0); - return 0; - -} - - -static void RT2870_TimerQ_Handle(RTMP_ADAPTER *pAd) -{ - int status; - RALINK_TIMER_STRUCT *pTimer; - RT2870_TIMER_ENTRY *pEntry; - unsigned long irqFlag; - - while(!pAd->TimerFunc_kill) - { -// printk("waiting for event!\n"); - pTimer = NULL; - - status = down_interruptible(&(pAd->RTUSBTimer_semaphore)); - - if (pAd->TimerQ.status == RT2870_THREAD_STOPED) - break; - - // event happened. - while(pAd->TimerQ.pQHead) - { - RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlag); - pEntry = pAd->TimerQ.pQHead; - if (pEntry) - { - pTimer = pEntry->pRaTimer; - - // update pQHead - pAd->TimerQ.pQHead = pEntry->pNext; - if (pEntry == pAd->TimerQ.pQTail) - pAd->TimerQ.pQTail = NULL; - - // return this queue entry to timerQFreeList. - pEntry->pNext = pAd->TimerQ.pQPollFreeList; - pAd->TimerQ.pQPollFreeList = pEntry; - } - RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlag); - - if (pTimer) - { - if (pTimer->handle != NULL) - if (!pAd->PM_FlgSuspend) - pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer); - if ((pTimer->Repeat) && (pTimer->State == FALSE)) - RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue); - } - } - - if (status != 0) - { - pAd->TimerQ.status = RT2870_THREAD_STOPED; - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); - break; - } - } -} - - -INT TimerQThread( - IN OUT PVOID Context) -{ - PRTMP_ADAPTER pAd; - POS_COOKIE pObj; - - pAd = (PRTMP_ADAPTER)Context; - pObj = (POS_COOKIE) pAd->OS_Cookie; - - rtmp_os_thread_init("rt2870TimerQHandle", (PVOID)&(pAd->TimerQComplete)); - - RT2870_TimerQ_Handle(pAd); - - /* notify the exit routine that we're actually exiting now - * - * complete()/wait_for_completion() is similar to up()/down(), - * except that complete() is safe in the case where the structure - * is getting deleted in a parallel mode of execution (i.e. just - * after the down() -- that's necessary for the thread-shutdown - * case. - * - * complete_and_exit() goes even further than this -- it is safe in - * the case that the thread of the caller is going away (not just - * the structure) -- this is necessary for the module-remove case. - * This is important in preemption kernels, which transfer the flow - * of execution immediately upon a complete(). - */ - DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__)); - - pObj->TimerQThr_pid = NULL; - - complete_and_exit(&pAd->TimerQComplete, 0); - return 0; - -} - - -RT2870_TIMER_ENTRY *RT2870_TimerQ_Insert( - IN RTMP_ADAPTER *pAd, - IN RALINK_TIMER_STRUCT *pTimer) -{ - RT2870_TIMER_ENTRY *pQNode = NULL, *pQTail; - unsigned long irqFlags; - - - RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags); - if (pAd->TimerQ.status & RT2870_THREAD_CAN_DO_INSERT) - { - if(pAd->TimerQ.pQPollFreeList) - { - pQNode = pAd->TimerQ.pQPollFreeList; - pAd->TimerQ.pQPollFreeList = pQNode->pNext; - - pQNode->pRaTimer = pTimer; - pQNode->pNext = NULL; - - pQTail = pAd->TimerQ.pQTail; - if (pAd->TimerQ.pQTail != NULL) - pQTail->pNext = pQNode; - pAd->TimerQ.pQTail = pQNode; - if (pAd->TimerQ.pQHead == NULL) - pAd->TimerQ.pQHead = pQNode; - } - RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags); - - if (pQNode) - up(&pAd->RTUSBTimer_semaphore); - //wake_up(&timerWaitQ); - } - else - { - RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags); - } - return pQNode; -} - - -BOOLEAN RT2870_TimerQ_Remove( - IN RTMP_ADAPTER *pAd, - IN RALINK_TIMER_STRUCT *pTimer) -{ - RT2870_TIMER_ENTRY *pNode, *pPrev = NULL; - unsigned long irqFlags; - - RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags); - if (pAd->TimerQ.status >= RT2870_THREAD_INITED) - { - pNode = pAd->TimerQ.pQHead; - while (pNode) - { - if (pNode->pRaTimer == pTimer) - break; - pPrev = pNode; - pNode = pNode->pNext; - } - - // Now move it to freeList queue. - if (pNode) - { - if (pNode == pAd->TimerQ.pQHead) - pAd->TimerQ.pQHead = pNode->pNext; - if (pNode == pAd->TimerQ.pQTail) - pAd->TimerQ.pQTail = pPrev; - if (pPrev != NULL) - pPrev->pNext = pNode->pNext; - - // return this queue entry to timerQFreeList. - pNode->pNext = pAd->TimerQ.pQPollFreeList; - pAd->TimerQ.pQPollFreeList = pNode; - } - } - RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags); - - return TRUE; -} - - -void RT2870_TimerQ_Exit(RTMP_ADAPTER *pAd) -{ - RT2870_TIMER_ENTRY *pTimerQ; - unsigned long irqFlags; - - RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags); - while (pAd->TimerQ.pQHead) - { - pTimerQ = pAd->TimerQ.pQHead; - pAd->TimerQ.pQHead = pTimerQ->pNext; - // remove the timeQ - } - pAd->TimerQ.pQPollFreeList = NULL; - os_free_mem(pAd, pAd->TimerQ.pTimerQPoll); - pAd->TimerQ.pQTail = NULL; - pAd->TimerQ.pQHead = NULL; - pAd->TimerQ.status = RT2870_THREAD_STOPED; - RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags); - -} - - -void RT2870_TimerQ_Init(RTMP_ADAPTER *pAd) -{ - int i; - RT2870_TIMER_ENTRY *pQNode, *pEntry; - unsigned long irqFlags; - - NdisAllocateSpinLock(&pAd->TimerQLock); - - RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags); - NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ)); - //InterlockedExchange(&pAd->TimerQ.count, 0); - - /* Initialise the wait q head */ - //init_waitqueue_head(&timerWaitQ); - - os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RT2870_TIMER_ENTRY) * TIMER_QUEUE_SIZE_MAX); - if (pAd->TimerQ.pTimerQPoll) - { - pEntry = NULL; - pQNode = (RT2870_TIMER_ENTRY *)pAd->TimerQ.pTimerQPoll; - for (i = 0 ;i pNext = pEntry; - pEntry = pQNode; - pQNode++; - } - pAd->TimerQ.pQPollFreeList = pEntry; - pAd->TimerQ.pQHead = NULL; - pAd->TimerQ.pQTail = NULL; - pAd->TimerQ.status = RT2870_THREAD_INITED; - } - RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags); -} - - -VOID RT2870_WatchDog(IN RTMP_ADAPTER *pAd) -{ - PHT_TX_CONTEXT pHTTXContext; - int idx; - ULONG irqFlags; - PURB pUrb; - BOOLEAN needDumpSeq = FALSE; - UINT32 MACValue; - - - idx = 0; - RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue); - if ((MACValue & 0xff) !=0 ) - { - DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 0 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue)); - RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40012); - while((MACValue &0xff) != 0 && (idx++ < 10)) - { - RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue); - NdisMSleep(1); - } - RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006); - } - -//PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) - idx = 0; - if ((MACValue & 0xff00) !=0 ) - { - DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 1 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue)); - RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf4000a); - while((MACValue &0xff00) != 0 && (idx++ < 10)) - { - RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue); - NdisMSleep(1); - } - RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006); - } - - if (pAd->watchDogRxOverFlowCnt >= 2) - { - DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n")); - if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_BULKIN_RESET | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_NIC_NOT_EXIST)))) - { - DBGPRINT(RT_DEBUG_TRACE, ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n")); - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0); - needDumpSeq = TRUE; - } - pAd->watchDogRxOverFlowCnt = 0; - } - - - for (idx = 0; idx < NUM_OF_TX_RING; idx++) - { - pUrb = NULL; - - RTMP_IRQ_LOCK(&pAd->BulkOutLock[idx], irqFlags); - if ((pAd->BulkOutPending[idx] == TRUE) && pAd->watchDogTxPendingCnt) - { - pAd->watchDogTxPendingCnt[idx]++; - - if ((pAd->watchDogTxPendingCnt[idx] > 2) && - (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_BULKOUT_RESET))) - ) - { - // FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it! - pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[idx]); - if (pHTTXContext->IRPPending) - { // Check TxContext. - pUrb = pHTTXContext->pUrb; - } - else if (idx == MGMTPIPEIDX) - { - PTX_CONTEXT pMLMEContext, pNULLContext, pPsPollContext; - - //Check MgmtContext. - pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa); - pPsPollContext = (PTX_CONTEXT)(&pAd->PsPollContext); - pNULLContext = (PTX_CONTEXT)(&pAd->NullContext); - - if (pMLMEContext->IRPPending) - { - ASSERT(pMLMEContext->IRPPending); - pUrb = pMLMEContext->pUrb; - } - else if (pNULLContext->IRPPending) - { - ASSERT(pNULLContext->IRPPending); - pUrb = pNULLContext->pUrb; - } - else if (pPsPollContext->IRPPending) - { - ASSERT(pPsPollContext->IRPPending); - pUrb = pPsPollContext->pUrb; - } - } - - RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags); - - DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", idx)); - if (pUrb) - { - DBGPRINT(RT_DEBUG_TRACE, ("Unlink the pending URB!\n")); - // unlink it now - RTUSB_UNLINK_URB(pUrb); - // Sleep 200 microseconds to give cancellation time to work - RTMPusecDelay(200); - needDumpSeq = TRUE; - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n")); - } - } - else - { - RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags); - } - } - else - { - RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags); - } - } - - // For Sigma debug, dump the ba_reordering sequence. - if((needDumpSeq == TRUE) && (pAd->CommonCfg.bDisableReordering == 0)) - { - USHORT Idx; - PBA_REC_ENTRY pBAEntry = NULL; - UCHAR count = 0; - struct reordering_mpdu *mpdu_blk; - - Idx = pAd->MacTab.Content[BSSID_WCID].BARecWcidArray[0]; - - pBAEntry = &pAd->BATable.BARecEntry[Idx]; - if((pBAEntry->list.qlen > 0) && (pBAEntry->list.next != NULL)) - { - DBGPRINT(RT_DEBUG_TRACE, ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n")); - NdisAcquireSpinLock(&pBAEntry->RxReRingLock); - mpdu_blk = pBAEntry->list.next; - while (mpdu_blk) - { - DBGPRINT(RT_DEBUG_TRACE, ("\t%d:Seq-%d, bAMSDU-%d!\n", count, mpdu_blk->Sequence, mpdu_blk->bAMSDU)); - mpdu_blk = mpdu_blk->next; - count++; - } - - DBGPRINT(RT_DEBUG_TRACE, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry->LastIndSeq)); - NdisReleaseSpinLock(&pBAEntry->RxReRingLock); - } - } -} - -/* -======================================================================== -Routine Description: - Release allocated resources. - -Arguments: - *dev Point to the PCI or USB device - pAd driver control block pointer - -Return Value: - None - -Note: -======================================================================== -*/ -static void _rtusb_disconnect(struct usb_device *dev, PRTMP_ADAPTER pAd) -{ - struct net_device *net_dev = NULL; - - - DBGPRINT(RT_DEBUG_ERROR, ("rtusb_disconnect: unregister usbnet usb-%s-%s\n", - dev->bus->bus_name, dev->devpath)); - if (!pAd) - { - usb_put_dev(dev); - - printk("rtusb_disconnect: pAd == NULL!\n"); - return; - } - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); - - - - // for debug, wait to show some messages to /proc system - udelay(1); - - - - - net_dev = pAd->net_dev; - if (pAd->net_dev != NULL) - { - printk("rtusb_disconnect: unregister_netdev(), dev->name=%s!\n", net_dev->name); - unregister_netdev (pAd->net_dev); - } - udelay(1); - flush_scheduled_work(); - udelay(1); - - // free net_device memory - free_netdev(net_dev); - - // free adapter memory - RTMPFreeAdapter(pAd); - - // release a use of the usb device structure - usb_put_dev(dev); - udelay(1); - - DBGPRINT(RT_DEBUG_ERROR, (" RTUSB disconnect successfully\n")); -} - - -/* -======================================================================== -Routine Description: - Probe RT28XX chipset. - -Arguments: - *dev Point to the PCI or USB device - interface - *id_table Point to the PCI or USB device ID - -Return Value: - None - -Note: -======================================================================== -*/ -static int rtusb_probe (struct usb_interface *intf, - const struct usb_device_id *id) -{ - PRTMP_ADAPTER pAd; - return (int)rt28xx_probe((void *)intf, (void *)id, 0, &pAd); -} - - -static void rtusb_disconnect(struct usb_interface *intf) -{ - struct usb_device *dev = interface_to_usbdev(intf); - PRTMP_ADAPTER pAd; - - - pAd = usb_get_intfdata(intf); - usb_set_intfdata(intf, NULL); - - _rtusb_disconnect(dev, pAd); -} - - -/* -======================================================================== -Routine Description: - Close kernel threads. - -Arguments: - *pAd the raxx interface data pointer - -Return Value: - NONE - -Note: -======================================================================== -*/ -VOID RT28xxThreadTerminate( - IN RTMP_ADAPTER *pAd) -{ - POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; - INT ret; - - - // Sleep 50 milliseconds so pending io might finish normally - RTMPusecDelay(50000); - - // We want to wait until all pending receives and sends to the - // device object. We cancel any - // irps. Wait until sends and receives have stopped. - RTUSBCancelPendingIRPs(pAd); - - // Terminate Threads - - if (pid_nr(pObj->TimerQThr_pid) > 0) - { - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - - printk("Terminate the TimerQThr_pid=%d!\n", pid_nr(pObj->TimerQThr_pid)); - mb(); - pAd->TimerFunc_kill = 1; - mb(); - ret = kill_pid(pObj->TimerQThr_pid, SIGTERM, 1); - if (ret) - { - printk(KERN_WARNING "%s: unable to stop TimerQThread, pid=%d, ret=%d!\n", - pAd->net_dev->name, pid_nr(pObj->TimerQThr_pid), ret); - } - else - { - wait_for_completion(&pAd->TimerQComplete); - pObj->TimerQThr_pid = NULL; - } - } - - if (pid_nr(pObj->MLMEThr_pid) > 0) - { - printk("Terminate the MLMEThr_pid=%d!\n", pid_nr(pObj->MLMEThr_pid)); - mb(); - pAd->mlme_kill = 1; - //RT28XX_MLME_HANDLER(pAd); - mb(); - ret = kill_pid(pObj->MLMEThr_pid, SIGTERM, 1); - if (ret) - { - printk (KERN_WARNING "%s: unable to Mlme thread, pid=%d, ret=%d!\n", - pAd->net_dev->name, pid_nr(pObj->MLMEThr_pid), ret); - } - else - { - //wait_for_completion (&pAd->notify); - wait_for_completion (&pAd->mlmeComplete); - pObj->MLMEThr_pid = NULL; - } - } - - if (pid_nr(pObj->RTUSBCmdThr_pid) > 0) - { - printk("Terminate the RTUSBCmdThr_pid=%d!\n", pid_nr(pObj->RTUSBCmdThr_pid)); - mb(); - NdisAcquireSpinLock(&pAd->CmdQLock); - pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED; - NdisReleaseSpinLock(&pAd->CmdQLock); - mb(); - //RTUSBCMDUp(pAd); - ret = kill_pid(pObj->RTUSBCmdThr_pid, SIGTERM, 1); - if (ret) - { - printk(KERN_WARNING "%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n", - pAd->net_dev->name, pid_nr(pObj->RTUSBCmdThr_pid), ret); - } - else - { - //wait_for_completion (&pAd->notify); - wait_for_completion (&pAd->CmdQComplete); - pObj->RTUSBCmdThr_pid = NULL; - } - } - - // Kill tasklets - pAd->mlme_kill = 0; - pAd->CmdQ.CmdQState = RT2870_THREAD_UNKNOWN; - pAd->TimerFunc_kill = 0; -} - - -void kill_thread_task(IN PRTMP_ADAPTER pAd) -{ - POS_COOKIE pObj; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - tasklet_kill(&pObj->rx_done_task); - tasklet_kill(&pObj->mgmt_dma_done_task); - tasklet_kill(&pObj->ac0_dma_done_task); - tasklet_kill(&pObj->ac1_dma_done_task); - tasklet_kill(&pObj->ac2_dma_done_task); - tasklet_kill(&pObj->ac3_dma_done_task); - tasklet_kill(&pObj->hcca_dma_done_task); - tasklet_kill(&pObj->tbtt_task); - -} - - -/* -======================================================================== -Routine Description: - Check the chipset vendor/product ID. - -Arguments: - _dev_p Point to the PCI or USB device - -Return Value: - TRUE Check ok - FALSE Check fail - -Note: -======================================================================== -*/ -BOOLEAN RT28XXChipsetCheck( - IN void *_dev_p) -{ - struct usb_interface *intf = (struct usb_interface *)_dev_p; - struct usb_device *dev_p = interface_to_usbdev(intf); - UINT32 i; - - - for(i=0; idescriptor.idVendor == rtusb_usb_id[i].idVendor && - dev_p->descriptor.idProduct == rtusb_usb_id[i].idProduct) - { - printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n", - dev_p->descriptor.idVendor, dev_p->descriptor.idProduct); - break; - } - } - - if (i == rtusb_usb_id_len) - { - printk("rt2870: Error! Device Descriptor not matching!\n"); - return FALSE; - } - - return TRUE; -} - - -/* -======================================================================== -Routine Description: - Init net device structure. - -Arguments: - _dev_p Point to the PCI or USB device - *net_dev Point to the net device - *pAd the raxx interface data pointer - -Return Value: - TRUE Init ok - FALSE Init fail - -Note: -======================================================================== -*/ -BOOLEAN RT28XXNetDevInit( - IN void *_dev_p, - IN struct net_device *net_dev, - IN RTMP_ADAPTER *pAd) -{ - struct usb_interface *intf = (struct usb_interface *)_dev_p; - struct usb_device *dev_p = interface_to_usbdev(intf); - - - pAd->config = &dev_p->config->desc; - return TRUE; -} - - -/* -======================================================================== -Routine Description: - Init net device structure. - -Arguments: - _dev_p Point to the PCI or USB device - *pAd the raxx interface data pointer - -Return Value: - TRUE Config ok - FALSE Config fail - -Note: -======================================================================== -*/ -BOOLEAN RT28XXProbePostConfig( - IN void *_dev_p, - IN RTMP_ADAPTER *pAd, - IN INT32 interface) -{ - struct usb_interface *intf = (struct usb_interface *)_dev_p; - struct usb_host_interface *iface_desc; - ULONG BulkOutIdx; - UINT32 i; - - - /* get the active interface descriptor */ - iface_desc = intf->cur_altsetting; - - /* get # of enpoints */ - pAd->NumberOfPipes = iface_desc->desc.bNumEndpoints; - DBGPRINT(RT_DEBUG_TRACE, - ("NumEndpoints=%d\n", iface_desc->desc.bNumEndpoints)); - - /* Configure Pipes */ - BulkOutIdx = 0; - - for(i=0; iNumberOfPipes; i++) - { - if ((iface_desc->endpoint[i].desc.bmAttributes == - USB_ENDPOINT_XFER_BULK) && - ((iface_desc->endpoint[i].desc.bEndpointAddress & - USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)) - { - pAd->BulkInEpAddr = iface_desc->endpoint[i].desc.bEndpointAddress; - pAd->BulkInMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize; - - DBGPRINT_RAW(RT_DEBUG_TRACE, - ("BULK IN MaximumPacketSize = %d\n", pAd->BulkInMaxPacketSize)); - DBGPRINT_RAW(RT_DEBUG_TRACE, - ("EP address = 0x%2x\n", iface_desc->endpoint[i].desc.bEndpointAddress)); - } - else if ((iface_desc->endpoint[i].desc.bmAttributes == - USB_ENDPOINT_XFER_BULK) && - ((iface_desc->endpoint[i].desc.bEndpointAddress & - USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)) - { - // there are 6 bulk out EP. EP6 highest priority. - // EP1-4 is EDCA. EP5 is HCCA. - pAd->BulkOutEpAddr[BulkOutIdx++] = iface_desc->endpoint[i].desc.bEndpointAddress; - pAd->BulkOutMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize; - - DBGPRINT_RAW(RT_DEBUG_TRACE, - ("BULK OUT MaximumPacketSize = %d\n", pAd->BulkOutMaxPacketSize)); - DBGPRINT_RAW(RT_DEBUG_TRACE, - ("EP address = 0x%2x \n", iface_desc->endpoint[i].desc.bEndpointAddress)); - } - } - - if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0])) - { - printk("%s: Could not find both bulk-in and bulk-out endpoints\n", __func__); - return FALSE; - } - - return TRUE; -} - - -/* -======================================================================== -Routine Description: - Disable DMA. - -Arguments: - *pAd the raxx interface data pointer - -Return Value: - None - -Note: -======================================================================== -*/ -VOID RT28XXDMADisable( - IN RTMP_ADAPTER *pAd) -{ - // no use -} - - - -/* -======================================================================== -Routine Description: - Enable DMA. - -Arguments: - *pAd the raxx interface data pointer - -Return Value: - None - -Note: -======================================================================== -*/ -VOID RT28XXDMAEnable( - IN RTMP_ADAPTER *pAd) -{ - WPDMA_GLO_CFG_STRUC GloCfg; - USB_DMA_CFG_STRUC UsbCfg; - int i = 0; - - - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4); - do - { - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); - if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) - break; - - DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n")); - RTMPusecDelay(1000); - i++; - }while ( i <200); - - - RTMPusecDelay(50); - GloCfg.field.EnTXWriteBackDDONE = 1; - GloCfg.field.EnableRxDMA = 1; - GloCfg.field.EnableTxDMA = 1; - DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word)); - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); - - UsbCfg.word = 0; - UsbCfg.field.phyclear = 0; - /* usb version is 1.1,do not use bulk in aggregation */ - if (pAd->BulkInMaxPacketSize == 512) - UsbCfg.field.RxBulkAggEn = 1; - /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */ - UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE /1024)-3; - UsbCfg.field.RxBulkAggTOut = 0x80; /* 2006-10-18 */ - UsbCfg.field.RxBulkEn = 1; - UsbCfg.field.TxBulkEn = 1; - - RTUSBWriteMACRegister(pAd, USB_DMA_CFG, UsbCfg.word); - -} - -/* -======================================================================== -Routine Description: - Write Beacon buffer to Asic. - -Arguments: - *pAd the raxx interface data pointer - -Return Value: - None - -Note: -======================================================================== -*/ -VOID RT28xx_UpdateBeaconToAsic( - IN RTMP_ADAPTER *pAd, - IN INT apidx, - IN ULONG FrameLen, - IN ULONG UpdatePos) -{ - PUCHAR pBeaconFrame = NULL; - UCHAR *ptr; - UINT i, padding; - BEACON_SYNC_STRUCT *pBeaconSync = pAd->CommonCfg.pBeaconSync; - UINT32 longValue; - BOOLEAN bBcnReq = FALSE; - UCHAR bcn_idx = 0; - - - if (pBeaconFrame == NULL) - { - DBGPRINT(RT_DEBUG_ERROR,("pBeaconFrame is NULL!\n")); - return; - } - - if (pBeaconSync == NULL) - { - DBGPRINT(RT_DEBUG_ERROR,("pBeaconSync is NULL!\n")); - return; - } - - //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) || - // ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP)) - // ) - if (bBcnReq == FALSE) - { - /* when the ra interface is down, do not send its beacon frame */ - /* clear all zero */ - for(i=0; iBeaconOffset[bcn_idx] + i, 0x00); - } - pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx))); - NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWI_SIZE); - } - else - { - ptr = (PUCHAR)&pAd->BeaconTxWI; - - if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE) == FALSE) - { // If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames. - pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx))); - NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE); - } - - if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) != (1 << bcn_idx)) - { - for (i=0; iBeaconOffset[bcn_idx] + i, longValue); - ptr += 4; - } - } - - ptr = pBeaconSync->BeaconBuf[bcn_idx]; - padding = (FrameLen & 0x01); - NdisZeroMemory((PUCHAR)(pBeaconFrame + FrameLen), padding); - FrameLen += padding; - for (i = 0 ; i < FrameLen /*HW_BEACON_OFFSET*/; i += 2) - { - if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE) - { - NdisMoveMemory(ptr, pBeaconFrame, 2); - //shortValue = *ptr + (*(ptr+1)<<8); - //RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue); - RTUSBMultiWrite(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, ptr, 2); - } - ptr +=2; - pBeaconFrame += 2; - } - - pBeaconSync->BeaconBitMap |= (1 << bcn_idx); - - // For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame. - } - -} - - -VOID RT2870_BssBeaconStop( - IN RTMP_ADAPTER *pAd) -{ - BEACON_SYNC_STRUCT *pBeaconSync; - int i, offset; - BOOLEAN Cancelled = TRUE; - - pBeaconSync = pAd->CommonCfg.pBeaconSync; - if (pBeaconSync && pBeaconSync->EnableBeacon) - { - INT NumOfBcn; - - NumOfBcn = MAX_MESH_NUM; - - RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled); - - for(i=0; iBeaconBuf[i], HW_BEACON_OFFSET); - NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); - - for (offset=0; offsetBeaconOffset[i] + offset, 0x00); - - pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; - pBeaconSync->TimIELocationInBeacon[i] = 0; - } - pBeaconSync->BeaconBitMap = 0; - pBeaconSync->DtimBitOn = 0; - } -} - - -VOID RT2870_BssBeaconStart( - IN RTMP_ADAPTER *pAd) -{ - int apidx; - BEACON_SYNC_STRUCT *pBeaconSync; -// LARGE_INTEGER tsfTime, deltaTime; - - pBeaconSync = pAd->CommonCfg.pBeaconSync; - if (pBeaconSync && pBeaconSync->EnableBeacon) - { - INT NumOfBcn; - - NumOfBcn = MAX_MESH_NUM; - - for(apidx=0; apidxBeaconBuf[apidx], HW_BEACON_OFFSET); - pBeaconSync->CapabilityInfoLocationInBeacon[apidx] = CapabilityInfoLocationInBeacon; - pBeaconSync->TimIELocationInBeacon[apidx] = TimIELocationInBeacon; - NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx], TXWI_SIZE); - } - pBeaconSync->BeaconBitMap = 0; - pBeaconSync->DtimBitOn = 0; - pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE; - - pAd->CommonCfg.BeaconAdjust = 0; - pAd->CommonCfg.BeaconFactor = 0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10); - pAd->CommonCfg.BeaconRemain = (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1; - printk(RT28xx_CHIP_NAME "_BssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", pAd->CommonCfg.BeaconFactor, pAd->CommonCfg.BeaconRemain); - RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer, pAd->CommonCfg.BeaconPeriod); - - } -} - - -VOID RT2870_BssBeaconInit( - IN RTMP_ADAPTER *pAd) -{ - BEACON_SYNC_STRUCT *pBeaconSync; - int i; - - NdisAllocMemory(pAd->CommonCfg.pBeaconSync, sizeof(BEACON_SYNC_STRUCT), MEM_ALLOC_FLAG); - if (pAd->CommonCfg.pBeaconSync) - { - pBeaconSync = pAd->CommonCfg.pBeaconSync; - NdisZeroMemory(pBeaconSync, sizeof(BEACON_SYNC_STRUCT)); - for(i=0; i < HW_BEACON_MAX_COUNT; i++) - { - NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET); - pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; - pBeaconSync->TimIELocationInBeacon[i] = 0; - NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); - } - pBeaconSync->BeaconBitMap = 0; - - //RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE); - pBeaconSync->EnableBeacon = TRUE; - } -} - - -VOID RT2870_BssBeaconExit( - IN RTMP_ADAPTER *pAd) -{ - BEACON_SYNC_STRUCT *pBeaconSync; - BOOLEAN Cancelled = TRUE; - int i; - - if (pAd->CommonCfg.pBeaconSync) - { - pBeaconSync = pAd->CommonCfg.pBeaconSync; - pBeaconSync->EnableBeacon = FALSE; - RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled); - pBeaconSync->BeaconBitMap = 0; - - for(i=0; iBeaconBuf[i], HW_BEACON_OFFSET); - pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; - pBeaconSync->TimIELocationInBeacon[i] = 0; - NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); - } - - NdisFreeMemory(pAd->CommonCfg.pBeaconSync, HW_BEACON_OFFSET * HW_BEACON_MAX_COUNT, 0); - pAd->CommonCfg.pBeaconSync = NULL; - } -} - -VOID BeaconUpdateExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; - LARGE_INTEGER tsfTime_a;//, tsfTime_b, deltaTime_exp, deltaTime_ab; - UINT32 delta, remain, remain_low, remain_high; -// BOOLEAN positive; - - ReSyncBeaconTime(pAd); - - - - RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart); - RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart); - - - //positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp); - remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart; - remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10); - remain = (remain_high + remain_low)%(pAd->CommonCfg.BeaconPeriod << 10); - delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain; - - pAd->CommonCfg.BeaconUpdateTimer.TimerValue = (delta >> 10) + 10; - -} - diff --git a/drivers/staging/rt2870/Kconfig b/drivers/staging/rt2870/Kconfig index aea5c8221810c5dc22b25cb59a2860fcb30247b3..fd3ba3a3b127a66a4ee7fb90f9978c747c3b8ec9 100644 --- a/drivers/staging/rt2870/Kconfig +++ b/drivers/staging/rt2870/Kconfig @@ -1,5 +1,7 @@ config RT2870 tristate "Ralink 2870/3070 wireless support" depends on USB && X86 && WLAN + select WIRELESS_EXT + select WEXT_PRIV ---help--- This is an experimental driver for the Ralink xx70 wireless chips. diff --git a/drivers/staging/rt2870/Makefile b/drivers/staging/rt2870/Makefile index 306c33113c58778cc5ea899989adc50a8e47eb4c..523e7e738d009df3cd9ae626fcb6462d870a5963 100644 --- a/drivers/staging/rt2870/Makefile +++ b/drivers/staging/rt2870/Makefile @@ -1,27 +1,35 @@ +# obj-$(CONFIG_RT2870) += rt2870sta.o # TODO: all of these should be removed EXTRA_CFLAGS += -DLINUX -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -EXTRA_CFLAGS += -DRT2870 -DRT3070 +EXTRA_CFLAGS += -DRTMP_MAC_USB -DRTMP_USB_SUPPORT -DRT2870 -DRTMP_TIMER_TASK_SUPPORT +EXTRA_CFLAGS += -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DRT30xx -DRT3070 EXTRA_CFLAGS += -DDBG rt2870sta-objs := \ - common/md5.o \ + common/crypt_md5.o \ + common/crypt_sha2.o \ + common/crypt_hmac.o \ common/mlme.o \ - common/rtmp_wep.o \ + common/cmm_wep.o \ common/action.o \ common/cmm_data.o \ common/rtmp_init.o \ - common/rtmp_tkip.o \ + common/cmm_tkip.o \ + common/cmm_aes.o \ common/cmm_sync.o \ common/eeprom.o \ common/cmm_sanity.o \ common/cmm_info.o \ + common/cmm_cfg.o \ common/cmm_wpa.o \ common/dfs.o \ common/spectrum.o \ + common/rtmp_timer.o \ + common/rt_channel.o \ + common/cmm_asic.o \ sta/assoc.o \ - sta/aironet.o \ sta/auth.o \ sta/auth_rsp.o \ sta/sync.o \ @@ -30,14 +38,18 @@ rt2870sta-objs := \ sta/connect.o \ sta/wpa.o \ rt_linux.o \ - rt_profile.o \ rt_main_dev.o \ sta_ioctl.o \ common/ba_action.o \ - 2870_main_dev.o \ - common/2870_rtmp_init.o \ + usb_main_dev.o \ + rt_usb.o \ + common/cmm_mac_usb.o \ common/rtusb_io.o \ common/rtusb_bulk.o \ common/rtusb_data.o \ - common/cmm_data_2870.o - + common/cmm_data_usb.o \ + common/rtmp_mcu.o \ + common/ee_efuse.o \ + chips/rt30xx.o \ + common/rt_rf.o \ + chips/rt3070.o diff --git a/drivers/staging/rt2870/chips/rt3070.c b/drivers/staging/rt2870/chips/rt3070.c new file mode 100644 index 0000000000000000000000000000000000000000..3a6db5ea89ab75dea657232f701a8f5f5876eedc --- /dev/null +++ b/drivers/staging/rt2870/chips/rt3070.c @@ -0,0 +1 @@ +#include "../../rt2860/chips/rt3070.c" diff --git a/drivers/staging/rt2870/chips/rt30xx.c b/drivers/staging/rt2870/chips/rt30xx.c new file mode 100644 index 0000000000000000000000000000000000000000..6c56b84c75d9b8e9497229ece022209c1782e49b --- /dev/null +++ b/drivers/staging/rt2870/chips/rt30xx.c @@ -0,0 +1 @@ +#include "../../rt2860/chips/rt30xx.c" diff --git a/drivers/staging/rt2870/common/2870_rtmp_init.c b/drivers/staging/rt2870/common/2870_rtmp_init.c deleted file mode 100644 index f517d9e902711fae99a6f01a680dbff223bc3382..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2870/common/2870_rtmp_init.c +++ /dev/null @@ -1,1730 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - 2870_rtmp_init.c - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Paul Lin 2002-08-01 created - John Chang 2004-08-20 RT2561/2661 use scatter-gather scheme - Jan Lee 2006-09-15 RT2860. Change for 802.11n , EEPROM, Led, BA, HT. - Sample Lin 2007-05-31 Merge RT2860 and RT2870 drivers. -*/ - -#include "../rt_config.h" - - -static void rx_done_tasklet(unsigned long data); -static void rt2870_hcca_dma_done_tasklet(unsigned long data); -static void rt2870_ac3_dma_done_tasklet(unsigned long data); -static void rt2870_ac2_dma_done_tasklet(unsigned long data); -static void rt2870_ac1_dma_done_tasklet(unsigned long data); -static void rt2870_ac0_dma_done_tasklet(unsigned long data); -static void rt2870_mgmt_dma_done_tasklet(unsigned long data); -static void rt2870_null_frame_complete_tasklet(unsigned long data); -static void rt2870_rts_frame_complete_tasklet(unsigned long data); -static void rt2870_pspoll_frame_complete_tasklet(unsigned long data); -static void rt2870_dataout_complete_tasklet(unsigned long data); - - -/* -======================================================================== -Routine Description: - Initialize receive data structures. - -Arguments: - pAd Pointer to our adapter - -Return Value: - NDIS_STATUS_SUCCESS - NDIS_STATUS_RESOURCES - -Note: - Initialize all receive releated private buffer, include those define - in RTMP_ADAPTER structure and all private data structures. The mahor - work is to allocate buffer for each packet and chain buffer to - NDIS packet descriptor. -======================================================================== -*/ -NDIS_STATUS NICInitRecv( - IN PRTMP_ADAPTER pAd) -{ - UCHAR i; - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; - - - DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitRecv\n")); - pObj = pObj; - - //InterlockedExchange(&pAd->PendingRx, 0); - pAd->PendingRx = 0; - pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index - pAd->NextRxBulkInIndex = 0 ; //RX_RING_SIZE -1; // Rx Bulk pointer - pAd->NextRxBulkInPosition = 0; - - for (i = 0; i < (RX_RING_SIZE); i++) - { - PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); - - //Allocate URB - pRxContext->pUrb = RTUSB_ALLOC_URB(0); - if (pRxContext->pUrb == NULL) - { - Status = NDIS_STATUS_RESOURCES; - goto out1; - } - - // Allocate transfer buffer - pRxContext->TransferBuffer = RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE, &pRxContext->data_dma); - if (pRxContext->TransferBuffer == NULL) - { - Status = NDIS_STATUS_RESOURCES; - goto out1; - } - - NdisZeroMemory(pRxContext->TransferBuffer, MAX_RXBULK_SIZE); - - pRxContext->pAd = pAd; - pRxContext->pIrp = NULL; - pRxContext->InUse = FALSE; - pRxContext->IRPPending = FALSE; - pRxContext->Readable = FALSE; - //pRxContext->ReorderInUse = FALSE; - pRxContext->bRxHandling = FALSE; - pRxContext->BulkInOffset = 0; - } - - DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitRecv\n")); - return Status; - -out1: - for (i = 0; i < (RX_RING_SIZE); i++) - { - PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); - - if (NULL != pRxContext->TransferBuffer) - { - RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE, - pRxContext->TransferBuffer, pRxContext->data_dma); - pRxContext->TransferBuffer = NULL; - } - - if (NULL != pRxContext->pUrb) - { - RTUSB_UNLINK_URB(pRxContext->pUrb); - RTUSB_FREE_URB(pRxContext->pUrb); - pRxContext->pUrb = NULL; - } - } - - return Status; -} - - -/* -======================================================================== -Routine Description: - Initialize transmit data structures. - -Arguments: - pAd Pointer to our adapter - -Return Value: - NDIS_STATUS_SUCCESS - NDIS_STATUS_RESOURCES - -Note: -======================================================================== -*/ -NDIS_STATUS NICInitTransmit( - IN PRTMP_ADAPTER pAd) -{ -#define LM_USB_ALLOC(pObj, Context, TB_Type, BufferSize, Status, msg1, err1, msg2, err2) \ - Context->pUrb = RTUSB_ALLOC_URB(0); \ - if (Context->pUrb == NULL) { \ - DBGPRINT(RT_DEBUG_ERROR, msg1); \ - Status = NDIS_STATUS_RESOURCES; \ - goto err1; } \ - \ - Context->TransferBuffer = \ - (TB_Type)RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, BufferSize, &Context->data_dma); \ - if (Context->TransferBuffer == NULL) { \ - DBGPRINT(RT_DEBUG_ERROR, msg2); \ - Status = NDIS_STATUS_RESOURCES; \ - goto err2; } - -#define LM_URB_FREE(pObj, Context, BufferSize) \ - if (NULL != Context->pUrb) { \ - RTUSB_UNLINK_URB(Context->pUrb); \ - RTUSB_FREE_URB(Context->pUrb); \ - Context->pUrb = NULL; } \ - if (NULL != Context->TransferBuffer) { \ - RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, BufferSize, \ - Context->TransferBuffer, \ - Context->data_dma); \ - Context->TransferBuffer = NULL; } - - UCHAR i, acidx; - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - PTX_CONTEXT pNullContext = &(pAd->NullContext); - PTX_CONTEXT pPsPollContext = &(pAd->PsPollContext); - PTX_CONTEXT pRTSContext = &(pAd->RTSContext); - PTX_CONTEXT pMLMEContext = NULL; -// PHT_TX_CONTEXT pHTTXContext = NULL; - POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; - PVOID RingBaseVa; -// RTMP_TX_RING *pTxRing; - RTMP_MGMT_RING *pMgmtRing; - - DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTransmit\n")); - pObj = pObj; - - // Init 4 set of Tx parameters - for(acidx = 0; acidx < NUM_OF_TX_RING; acidx++) - { - // Initialize all Transmit releated queues - InitializeQueueHeader(&pAd->TxSwQueue[acidx]); - - // Next Local tx ring pointer waiting for buck out - pAd->NextBulkOutIndex[acidx] = acidx; - pAd->BulkOutPending[acidx] = FALSE; // Buck Out control flag - //pAd->DataBulkDoneIdx[acidx] = 0; - } - - //pAd->NextMLMEIndex = 0; - //pAd->PushMgmtIndex = 0; - //pAd->PopMgmtIndex = 0; - //InterlockedExchange(&pAd->MgmtQueueSize, 0); - //InterlockedExchange(&pAd->TxCount, 0); - - //pAd->PrioRingFirstIndex = 0; - //pAd->PrioRingTxCnt = 0; - - do - { - // - // TX_RING_SIZE, 4 ACs - // - for(acidx=0; acidx<4; acidx++) - { - PHT_TX_CONTEXT pHTTXContext = &(pAd->TxContext[acidx]); - - NdisZeroMemory(pHTTXContext, sizeof(HT_TX_CONTEXT)); - //Allocate URB - LM_USB_ALLOC(pObj, pHTTXContext, PHTTX_BUFFER, sizeof(HTTX_BUFFER), Status, - ("<-- ERROR in Alloc TX TxContext[%d] urb!! \n", acidx), - done, - ("<-- ERROR in Alloc TX TxContext[%d] HTTX_BUFFER !! \n", acidx), - out1); - - NdisZeroMemory(pHTTXContext->TransferBuffer->Aggregation, 4); - pHTTXContext->pAd = pAd; - pHTTXContext->pIrp = NULL; - pHTTXContext->IRPPending = FALSE; - pHTTXContext->NextBulkOutPosition = 0; - pHTTXContext->ENextBulkOutPosition = 0; - pHTTXContext->CurWritePosition = 0; - pHTTXContext->CurWriteRealPos = 0; - pHTTXContext->BulkOutSize = 0; - pHTTXContext->BulkOutPipeId = acidx; - pHTTXContext->bRingEmpty = TRUE; - pHTTXContext->bCopySavePad = FALSE; - - pAd->BulkOutPending[acidx] = FALSE; - } - - - // - // MGMT_RING_SIZE - // - // Allocate MGMT ring descriptor's memory - pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * sizeof(TX_CONTEXT); - RTMPAllocateMemory(&pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize); - if (pAd->MgmtDescRing.AllocVa == NULL) - { - DBGPRINT_ERR(("Failed to allocate a big buffer for MgmtDescRing!\n")); - Status = NDIS_STATUS_RESOURCES; - goto out1; - } - NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize); - RingBaseVa = pAd->MgmtDescRing.AllocVa; - - // Initialize MGMT Ring and associated buffer memory - pMgmtRing = &pAd->MgmtRing; - for (i = 0; i < MGMT_RING_SIZE; i++) - { - // link the pre-allocated Mgmt buffer to MgmtRing.Cell - pMgmtRing->Cell[i].AllocSize = sizeof(TX_CONTEXT); - pMgmtRing->Cell[i].AllocVa = RingBaseVa; - pMgmtRing->Cell[i].pNdisPacket = NULL; - pMgmtRing->Cell[i].pNextNdisPacket = NULL; - - //Allocate URB for MLMEContext - pMLMEContext = (PTX_CONTEXT) pAd->MgmtRing.Cell[i].AllocVa; - pMLMEContext->pUrb = RTUSB_ALLOC_URB(0); - if (pMLMEContext->pUrb == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("<-- ERROR in Alloc TX MLMEContext[%d] urb!! \n", i)); - Status = NDIS_STATUS_RESOURCES; - goto out2; - } - pMLMEContext->pAd = pAd; - pMLMEContext->pIrp = NULL; - pMLMEContext->TransferBuffer = NULL; - pMLMEContext->InUse = FALSE; - pMLMEContext->IRPPending = FALSE; - pMLMEContext->bWaitingBulkOut = FALSE; - pMLMEContext->BulkOutSize = 0; - pMLMEContext->SelfIdx = i; - - // Offset to next ring descriptor address - RingBaseVa = (PUCHAR) RingBaseVa + sizeof(TX_CONTEXT); - } - DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", i)); - - //pAd->MgmtRing.TxSwFreeIdx = (MGMT_RING_SIZE - 1); - pAd->MgmtRing.TxSwFreeIdx = MGMT_RING_SIZE; - pAd->MgmtRing.TxCpuIdx = 0; - pAd->MgmtRing.TxDmaIdx = 0; - - // - // BEACON_RING_SIZE - // - for(i=0; iBeaconContext[i]); - - - NdisZeroMemory(pBeaconContext, sizeof(TX_CONTEXT)); - - //Allocate URB - LM_USB_ALLOC(pObj, pBeaconContext, PTX_BUFFER, sizeof(TX_BUFFER), Status, - ("<-- ERROR in Alloc TX BeaconContext[%d] urb!! \n", i), - out2, - ("<-- ERROR in Alloc TX BeaconContext[%d] TX_BUFFER !! \n", i), - out3); - - pBeaconContext->pAd = pAd; - pBeaconContext->pIrp = NULL; - pBeaconContext->InUse = FALSE; - pBeaconContext->IRPPending = FALSE; - } - - // - // NullContext - // - NdisZeroMemory(pNullContext, sizeof(TX_CONTEXT)); - - //Allocate URB - LM_USB_ALLOC(pObj, pNullContext, PTX_BUFFER, sizeof(TX_BUFFER), Status, - ("<-- ERROR in Alloc TX NullContext urb!! \n"), - out3, - ("<-- ERROR in Alloc TX NullContext TX_BUFFER !! \n"), - out4); - - pNullContext->pAd = pAd; - pNullContext->pIrp = NULL; - pNullContext->InUse = FALSE; - pNullContext->IRPPending = FALSE; - - // - // RTSContext - // - NdisZeroMemory(pRTSContext, sizeof(TX_CONTEXT)); - - //Allocate URB - LM_USB_ALLOC(pObj, pRTSContext, PTX_BUFFER, sizeof(TX_BUFFER), Status, - ("<-- ERROR in Alloc TX RTSContext urb!! \n"), - out4, - ("<-- ERROR in Alloc TX RTSContext TX_BUFFER !! \n"), - out5); - - pRTSContext->pAd = pAd; - pRTSContext->pIrp = NULL; - pRTSContext->InUse = FALSE; - pRTSContext->IRPPending = FALSE; - - // - // PsPollContext - // - //NdisZeroMemory(pPsPollContext, sizeof(TX_CONTEXT)); - //Allocate URB - LM_USB_ALLOC(pObj, pPsPollContext, PTX_BUFFER, sizeof(TX_BUFFER), Status, - ("<-- ERROR in Alloc TX PsPollContext urb!! \n"), - out5, - ("<-- ERROR in Alloc TX PsPollContext TX_BUFFER !! \n"), - out6); - - pPsPollContext->pAd = pAd; - pPsPollContext->pIrp = NULL; - pPsPollContext->InUse = FALSE; - pPsPollContext->IRPPending = FALSE; - pPsPollContext->bAggregatible = FALSE; - pPsPollContext->LastOne = TRUE; - - } while (FALSE); - - -done: - DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTransmit\n")); - - return Status; - - /* --------------------------- ERROR HANDLE --------------------------- */ -out6: - LM_URB_FREE(pObj, pPsPollContext, sizeof(TX_BUFFER)); - -out5: - LM_URB_FREE(pObj, pRTSContext, sizeof(TX_BUFFER)); - -out4: - LM_URB_FREE(pObj, pNullContext, sizeof(TX_BUFFER)); - -out3: - for(i=0; iBeaconContext[i]); - if (pBeaconContext) - LM_URB_FREE(pObj, pBeaconContext, sizeof(TX_BUFFER)); - } - -out2: - if (pAd->MgmtDescRing.AllocVa) - { - pMgmtRing = &pAd->MgmtRing; - for(i=0; iMgmtRing.Cell[i].AllocVa; - if (pMLMEContext) - LM_URB_FREE(pObj, pMLMEContext, sizeof(TX_BUFFER)); - } - NdisFreeMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize, 0); - pAd->MgmtDescRing.AllocVa = NULL; - } - -out1: - for (acidx = 0; acidx < 4; acidx++) - { - PHT_TX_CONTEXT pTxContext = &(pAd->TxContext[acidx]); - if (pTxContext) - LM_URB_FREE(pObj, pTxContext, sizeof(HTTX_BUFFER)); - } - - // Here we didn't have any pre-allocated memory need to free. - - return Status; -} - - -/* -======================================================================== -Routine Description: - Allocate DMA memory blocks for send, receive. - -Arguments: - pAd Pointer to our adapter - -Return Value: - NDIS_STATUS_SUCCESS - NDIS_STATUS_FAILURE - NDIS_STATUS_RESOURCES - -Note: -======================================================================== -*/ -NDIS_STATUS RTMPAllocTxRxRingMemory( - IN PRTMP_ADAPTER pAd) -{ -// COUNTER_802_11 pCounter = &pAd->WlanCounters; - NDIS_STATUS Status; - INT num; - - - DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); - - - do - { - // Init the CmdQ and CmdQLock - NdisAllocateSpinLock(&pAd->CmdQLock); - NdisAcquireSpinLock(&pAd->CmdQLock); - RTUSBInitializeCmdQ(&pAd->CmdQ); - NdisReleaseSpinLock(&pAd->CmdQLock); - - - NdisAllocateSpinLock(&pAd->MLMEBulkOutLock); - //NdisAllocateSpinLock(&pAd->MLMEWaitQueueLock); - NdisAllocateSpinLock(&pAd->BulkOutLock[0]); - NdisAllocateSpinLock(&pAd->BulkOutLock[1]); - NdisAllocateSpinLock(&pAd->BulkOutLock[2]); - NdisAllocateSpinLock(&pAd->BulkOutLock[3]); - NdisAllocateSpinLock(&pAd->BulkOutLock[4]); - NdisAllocateSpinLock(&pAd->BulkOutLock[5]); - NdisAllocateSpinLock(&pAd->BulkInLock); - - for (num = 0; num < NUM_OF_TX_RING; num++) - { - NdisAllocateSpinLock(&pAd->TxContextQueueLock[num]); - } - -// NdisAllocateSpinLock(&pAd->MemLock); // Not used in RT28XX - -// NdisAllocateSpinLock(&pAd->MacTabLock); // init it in UserCfgInit() -// NdisAllocateSpinLock(&pAd->BATabLock); // init it in BATableInit() - -// for(num=0; numBATable.BARecEntry[num].RxReRingLock); -// } - - // - // Init Mac Table - // -// MacTableInitialize(pAd); - - // - // Init send data structures and related parameters - // - Status = NICInitTransmit(pAd); - if (Status != NDIS_STATUS_SUCCESS) - break; - - // - // Init receive data structures and related parameters - // - Status = NICInitRecv(pAd); - if (Status != NDIS_STATUS_SUCCESS) - break; - - pAd->PendingIoCount = 1; - - } while (FALSE); - - NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME)); - pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); - - if (pAd->FragFrame.pFragPacket == NULL) - { - Status = NDIS_STATUS_RESOURCES; - } - - DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); - return Status; -} - - -/* -======================================================================== -Routine Description: - Calls USB_InterfaceStop and frees memory allocated for the URBs - calls NdisMDeregisterDevice and frees the memory - allocated in VNetInitialize for the Adapter Object - -Arguments: - *pAd the raxx interface data pointer - -Return Value: - None - -Note: -======================================================================== -*/ -VOID RTMPFreeTxRxRingMemory( - IN PRTMP_ADAPTER pAd) -{ -#define LM_URB_FREE(pObj, Context, BufferSize) \ - if (NULL != Context->pUrb) { \ - RTUSB_UNLINK_URB(Context->pUrb); \ - RTUSB_FREE_URB(Context->pUrb); \ - Context->pUrb = NULL; } \ - if (NULL != Context->TransferBuffer) { \ - RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, BufferSize, \ - Context->TransferBuffer, \ - Context->data_dma); \ - Context->TransferBuffer = NULL; } - - - UINT i, acidx; - PTX_CONTEXT pNullContext = &pAd->NullContext; - PTX_CONTEXT pPsPollContext = &pAd->PsPollContext; - PTX_CONTEXT pRTSContext = &pAd->RTSContext; -// PHT_TX_CONTEXT pHTTXContext; - //PRTMP_REORDERBUF pReorderBuf; - POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; -// RTMP_TX_RING *pTxRing; - - DBGPRINT(RT_DEBUG_ERROR, ("---> RTMPFreeTxRxRingMemory\n")); - pObj = pObj; - - // Free all resources for the RECEIVE buffer queue. - for(i=0; i<(RX_RING_SIZE); i++) - { - PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); - if (pRxContext) - LM_URB_FREE(pObj, pRxContext, MAX_RXBULK_SIZE); - } - - // Free PsPoll frame resource - LM_URB_FREE(pObj, pPsPollContext, sizeof(TX_BUFFER)); - - // Free NULL frame resource - LM_URB_FREE(pObj, pNullContext, sizeof(TX_BUFFER)); - - // Free RTS frame resource - LM_URB_FREE(pObj, pRTSContext, sizeof(TX_BUFFER)); - - - // Free beacon frame resource - for(i=0; iBeaconContext[i]); - if (pBeaconContext) - LM_URB_FREE(pObj, pBeaconContext, sizeof(TX_BUFFER)); - } - - - // Free mgmt frame resource - for(i = 0; i < MGMT_RING_SIZE; i++) - { - PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[i].AllocVa; - //LM_URB_FREE(pObj, pMLMEContext, sizeof(TX_BUFFER)); - if (NULL != pAd->MgmtRing.Cell[i].pNdisPacket) - { - RTMPFreeNdisPacket(pAd, pAd->MgmtRing.Cell[i].pNdisPacket); - pAd->MgmtRing.Cell[i].pNdisPacket = NULL; - pMLMEContext->TransferBuffer = NULL; - } - - if (pMLMEContext) - { - if (NULL != pMLMEContext->pUrb) - { - RTUSB_UNLINK_URB(pMLMEContext->pUrb); - RTUSB_FREE_URB(pMLMEContext->pUrb); - pMLMEContext->pUrb = NULL; - } - } - } - if (pAd->MgmtDescRing.AllocVa) - NdisFreeMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize, 0); - - - // Free Tx frame resource - for(acidx=0; acidx<4; acidx++) - { - PHT_TX_CONTEXT pHTTXContext = &(pAd->TxContext[acidx]); - if (pHTTXContext) - LM_URB_FREE(pObj, pHTTXContext, sizeof(HTTX_BUFFER)); - } - - if (pAd->FragFrame.pFragPacket) - RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS); - - for(i=0; i<6; i++) - { - NdisFreeSpinLock(&pAd->BulkOutLock[i]); - } - - NdisFreeSpinLock(&pAd->BulkInLock); - NdisFreeSpinLock(&pAd->MLMEBulkOutLock); - - NdisFreeSpinLock(&pAd->CmdQLock); - - // Clear all pending bulk-out request flags. - RTUSB_CLEAR_BULK_FLAG(pAd, 0xffffffff); - -// NdisFreeSpinLock(&pAd->MacTabLock); - -// for(i=0; iBATable.BARecEntry[i].RxReRingLock); -// } - - DBGPRINT(RT_DEBUG_ERROR, ("<--- ReleaseAdapter\n")); -} - - -/* -======================================================================== -Routine Description: - Allocate memory for adapter control block. - -Arguments: - pAd Pointer to our adapter - -Return Value: - NDIS_STATUS_SUCCESS - NDIS_STATUS_FAILURE - NDIS_STATUS_RESOURCES - -Note: -======================================================================== -*/ -NDIS_STATUS AdapterBlockAllocateMemory( - IN PVOID handle, - OUT PVOID *ppAd) -{ - PUSB_DEV usb_dev; - POS_COOKIE pObj = (POS_COOKIE) handle; - - - usb_dev = pObj->pUsb_Dev; - - pObj->MLMEThr_pid = NULL; - pObj->RTUSBCmdThr_pid = NULL; - - *ppAd = (PVOID)vmalloc(sizeof(RTMP_ADAPTER)); - - if (*ppAd) - { - NdisZeroMemory(*ppAd, sizeof(RTMP_ADAPTER)); - ((PRTMP_ADAPTER)*ppAd)->OS_Cookie = handle; - return (NDIS_STATUS_SUCCESS); - } - else - { - return (NDIS_STATUS_FAILURE); - } -} - - -/* -======================================================================== -Routine Description: - Create kernel threads & tasklets. - -Arguments: - *net_dev Pointer to wireless net device interface - -Return Value: - NDIS_STATUS_SUCCESS - NDIS_STATUS_FAILURE - -Note: -======================================================================== -*/ -NDIS_STATUS CreateThreads( - IN struct net_device *net_dev) -{ - PRTMP_ADAPTER pAd = net_dev->ml_priv; - POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; - pid_t pid_number; - - //init_MUTEX(&(pAd->usbdev_semaphore)); - - init_MUTEX_LOCKED(&(pAd->mlme_semaphore)); - init_completion (&pAd->mlmeComplete); - - init_MUTEX_LOCKED(&(pAd->RTUSBCmd_semaphore)); - init_completion (&pAd->CmdQComplete); - - init_MUTEX_LOCKED(&(pAd->RTUSBTimer_semaphore)); - init_completion (&pAd->TimerQComplete); - - // Creat MLME Thread - pObj->MLMEThr_pid = NULL; - pid_number = kernel_thread(MlmeThread, pAd, CLONE_VM); - if (pid_number < 0) - { - printk (KERN_WARNING "%s: unable to start Mlme thread\n",pAd->net_dev->name); - return NDIS_STATUS_FAILURE; - } - - pObj->MLMEThr_pid = find_get_pid(pid_number); - - // Wait for the thread to start - wait_for_completion(&(pAd->mlmeComplete)); - - // Creat Command Thread - pObj->RTUSBCmdThr_pid = NULL; - pid_number = kernel_thread(RTUSBCmdThread, pAd, CLONE_VM); - if (pid_number < 0) - { - printk (KERN_WARNING "%s: unable to start RTUSBCmd thread\n",pAd->net_dev->name); - return NDIS_STATUS_FAILURE; - } - - pObj->RTUSBCmdThr_pid = find_get_pid(pid_number); - - wait_for_completion(&(pAd->CmdQComplete)); - - pObj->TimerQThr_pid = NULL; - pid_number = kernel_thread(TimerQThread, pAd, CLONE_VM); - if (pid_number < 0) - { - printk (KERN_WARNING "%s: unable to start TimerQThread\n",pAd->net_dev->name); - return NDIS_STATUS_FAILURE; - } - - pObj->TimerQThr_pid = find_get_pid(pid_number); - - // Wait for the thread to start - wait_for_completion(&(pAd->TimerQComplete)); - - // Create receive tasklet - tasklet_init(&pObj->rx_done_task, rx_done_tasklet, (ULONG)pAd); - tasklet_init(&pObj->mgmt_dma_done_task, rt2870_mgmt_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->ac0_dma_done_task, rt2870_ac0_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->ac1_dma_done_task, rt2870_ac1_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->ac2_dma_done_task, rt2870_ac2_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->ac3_dma_done_task, rt2870_ac3_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->hcca_dma_done_task, rt2870_hcca_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->tbtt_task, tbtt_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->null_frame_complete_task, rt2870_null_frame_complete_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->rts_frame_complete_task, rt2870_rts_frame_complete_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->pspoll_frame_complete_task, rt2870_pspoll_frame_complete_tasklet, (unsigned long)pAd); - - return NDIS_STATUS_SUCCESS; -} - -/* -======================================================================== -Routine Description: - As STA's BSSID is a WC too, it uses shared key table. - This function write correct unicast TX key to ASIC WCID. - And we still make a copy in our MacTab.Content[BSSID_WCID].PairwiseKey. - Caller guarantee TKIP/AES always has keyidx = 0. (pairwise key) - Caller guarantee WEP calls this function when set Txkey, default key index=0~3. - -Arguments: - pAd Pointer to our adapter - pKey Pointer to the where the key stored - -Return Value: - NDIS_SUCCESS Add key successfully - -Note: -======================================================================== -*/ -VOID RTMPAddBSSIDCipher( - IN PRTMP_ADAPTER pAd, - IN UCHAR Aid, - IN PNDIS_802_11_KEY pKey, - IN UCHAR CipherAlg) -{ - PUCHAR pTxMic, pRxMic; - BOOLEAN bKeyRSC, bAuthenticator; // indicate the receive SC set by KeyRSC value -// UCHAR CipherAlg; - UCHAR i; - ULONG WCIDAttri; - USHORT offset; - UCHAR KeyIdx, IVEIV[8]; - UINT32 Value; - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddBSSIDCipher==> Aid = %d\n",Aid)); - - // Bit 29 of Add-key KeyRSC - bKeyRSC = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE; - - // Bit 28 of Add-key Authenticator - bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE; - KeyIdx = (UCHAR)pKey->KeyIndex&0xff; - - if (KeyIdx > 4) - return; - - - if (pAd->MacTab.Content[Aid].PairwiseKey.CipherAlg == CIPHER_TKIP) - { if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - { - // for WPA-None Tx, Rx MIC is the same - pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 16; - pRxMic = pTxMic; - } - else if (bAuthenticator == TRUE) - { - pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 16; - pRxMic = (PUCHAR) (&pKey->KeyMaterial) + 24; - } - else - { - pRxMic = (PUCHAR) (&pKey->KeyMaterial) + 16; - pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 24; - } - - offset = PAIRWISE_KEY_TABLE_BASE + (Aid * HW_KEY_ENTRY_SIZE) + 0x10; - for (i=0; i<8; ) - { - Value = *(pTxMic+i); - Value += (*(pTxMic+i+1)<<8); - Value += (*(pTxMic+i+2)<<16); - Value += (*(pTxMic+i+3)<<24); - RTUSBWriteMACRegister(pAd, offset+i, Value); - i+=4; - } - - offset = PAIRWISE_KEY_TABLE_BASE + (Aid * HW_KEY_ENTRY_SIZE) + 0x18; - for (i=0; i<8; ) - { - Value = *(pRxMic+i); - Value += (*(pRxMic+i+1)<<8); - Value += (*(pRxMic+i+2)<<16); - Value += (*(pRxMic+i+3)<<24); - RTUSBWriteMACRegister(pAd, offset+i, Value); - i+=4; - } - - // Only Key lenth equal to TKIP key have these - NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.RxMic, pRxMic, 8); - NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.TxMic, pTxMic, 8); - - DBGPRINT(RT_DEBUG_TRACE, - (" TxMIC = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x \n", - pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3], - pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); - DBGPRINT(RT_DEBUG_TRACE, - (" RxMIC = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x \n", - pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3], - pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); - } - - // 2. Record Security Key. - pAd->MacTab.Content[BSSID_WCID].PairwiseKey.KeyLen= (UCHAR)pKey->KeyLength; - NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength); - - // 3. Check RxTsc. And used to init to ASIC IV. - if (bKeyRSC == TRUE) - NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.RxTsc, &pKey->KeyRSC, 6); - else - NdisZeroMemory(pAd->MacTab.Content[Aid].PairwiseKey.RxTsc, 6); - - // 4. Init TxTsc to one based on WiFi WPA specs - pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[0] = 1; - pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[1] = 0; - pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[2] = 0; - pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[3] = 0; - pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[4] = 0; - pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[5] = 0; - - CipherAlg = pAd->MacTab.Content[Aid].PairwiseKey.CipherAlg; - - offset = PAIRWISE_KEY_TABLE_BASE + (Aid * HW_KEY_ENTRY_SIZE); - RTUSBMultiWrite(pAd, (USHORT) offset, pKey->KeyMaterial, - ((pKey->KeyLength == LEN_TKIP_KEY) ? 16 : (USHORT)pKey->KeyLength)); - - offset = SHARED_KEY_TABLE_BASE + (KeyIdx * HW_KEY_ENTRY_SIZE); - RTUSBMultiWrite(pAd, (USHORT) offset, pKey->KeyMaterial, (USHORT)pKey->KeyLength); - - offset = PAIRWISE_IVEIV_TABLE_BASE + (Aid * HW_IVEIV_ENTRY_SIZE); - NdisZeroMemory(IVEIV, 8); - - // IV/EIV - if ((CipherAlg == CIPHER_TKIP) || - (CipherAlg == CIPHER_TKIP_NO_MIC) || - (CipherAlg == CIPHER_AES)) - { - IVEIV[3] = 0x20; // Eiv bit on. keyid always 0 for pairwise key - } - // default key idx needs to set. - // in TKIP/AES KeyIdx = 0 , WEP KeyIdx is default tx key. - else - { - IVEIV[3] |= (KeyIdx<< 6); - } - RTUSBMultiWrite(pAd, (USHORT) offset, IVEIV, 8); - - // WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:1=PAIRWISE KEY, BSSIdx is 0 - if ((CipherAlg == CIPHER_TKIP) || - (CipherAlg == CIPHER_TKIP_NO_MIC) || - (CipherAlg == CIPHER_AES)) - { - WCIDAttri = (CipherAlg<<1)|SHAREDKEYTABLE; - } - else - WCIDAttri = (CipherAlg<<1)|SHAREDKEYTABLE; - - offset = MAC_WCID_ATTRIBUTE_BASE + (Aid* HW_WCID_ATTRI_SIZE); - RTUSBWriteMACRegister(pAd, offset, WCIDAttri); - RTUSBReadMACRegister(pAd, offset, &Value); - - DBGPRINT(RT_DEBUG_TRACE, ("BSSID_WCID : offset = %x, WCIDAttri = %lx\n", - offset, WCIDAttri)); - - // pAddr - // Add Bssid mac address at linkup. not here. check! - /*offset = MAC_WCID_BASE + (BSSID_WCID * HW_WCID_ENTRY_SIZE); - *for (i=0; iBSSID[i]); - } - */ - - DBGPRINT(RT_DEBUG_ERROR, ("AddBSSIDasWCIDEntry: Alg=%s, KeyLength = %d\n", - CipherName[CipherAlg], pKey->KeyLength)); - DBGPRINT(RT_DEBUG_TRACE, ("Key [idx=%x] [KeyLen = %d]\n", - pKey->KeyIndex, pKey->KeyLength)); - for(i=0; iKeyLength; i++) - DBGPRINT_RAW(RT_DEBUG_TRACE,(" %x:", pKey->KeyMaterial[i])); - DBGPRINT(RT_DEBUG_TRACE,(" \n")); -} - -/* -======================================================================== -Routine Description: - Get a received packet. - -Arguments: - pAd device control block - pSaveRxD receive descriptor information - *pbReschedule need reschedule flag - *pRxPending pending received packet flag - -Return Value: - the recieved packet - -Note: -======================================================================== -*/ -#define RT2870_RXDMALEN_FIELD_SIZE 4 -PNDIS_PACKET GetPacketFromRxRing( - IN PRTMP_ADAPTER pAd, - OUT PRT28XX_RXD_STRUC pSaveRxD, - OUT BOOLEAN *pbReschedule, - IN OUT UINT32 *pRxPending) -{ - PRX_CONTEXT pRxContext; - PNDIS_PACKET pSkb; - PUCHAR pData; - ULONG ThisFrameLen; - ULONG RxBufferLength; - PRXWI_STRUC pRxWI; - - pRxContext = &pAd->RxContext[pAd->NextRxBulkInReadIndex]; - if ((pRxContext->Readable == FALSE) || (pRxContext->InUse == TRUE)) - return NULL; - - RxBufferLength = pRxContext->BulkInOffset - pAd->ReadPosition; - if (RxBufferLength < (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXWI_STRUC) + sizeof(RXINFO_STRUC))) - { - goto label_null; - } - - pData = &pRxContext->TransferBuffer[pAd->ReadPosition]; /* 4KB */ - // The RXDMA field is 4 bytes, now just use the first 2 bytes. The Length including the (RXWI + MSDU + Padding) - ThisFrameLen = *pData + (*(pData+1)<<8); - if (ThisFrameLen == 0) - { - DBGPRINT(RT_DEBUG_TRACE, ("BIRIdx(%d): RXDMALen is zero.[%ld], BulkInBufLen = %ld)\n", - pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset)); - goto label_null; - } - if ((ThisFrameLen&0x3) != 0) - { - DBGPRINT(RT_DEBUG_ERROR, ("BIRIdx(%d): RXDMALen not multiple of 4.[%ld], BulkInBufLen = %ld)\n", - pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset)); - goto label_null; - } - - if ((ThisFrameLen + 8)> RxBufferLength) // 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXINFO_STRUC)) - { - DBGPRINT(RT_DEBUG_TRACE,("BIRIdx(%d):FrameLen(0x%lx) outranges. BulkInLen=0x%lx, remaining RxBufLen=0x%lx, ReadPos=0x%lx\n", - pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset, RxBufferLength, pAd->ReadPosition)); - - // error frame. finish this loop - goto label_null; - } - - // skip USB frame length field - pData += RT2870_RXDMALEN_FIELD_SIZE; - pRxWI = (PRXWI_STRUC)pData; - - if (pRxWI->MPDUtotalByteCount > ThisFrameLen) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s():pRxWIMPDUtotalByteCount(%d) large than RxDMALen(%ld)\n", - __func__, pRxWI->MPDUtotalByteCount, ThisFrameLen)); - goto label_null; - } - - // allocate a rx packet - pSkb = dev_alloc_skb(ThisFrameLen); - if (pSkb == NULL) - { - DBGPRINT(RT_DEBUG_ERROR,("%s():Cannot Allocate sk buffer for this Bulk-In buffer!\n", __func__)); - goto label_null; - } - - // copy the rx packet - memcpy(skb_put(pSkb, ThisFrameLen), pData, ThisFrameLen); - RTPKT_TO_OSPKT(pSkb)->dev = get_netdev_from_bssid(pAd, BSS0); - RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pSkb), PKTSRC_NDIS); - - // copy RxD - *pSaveRxD = *(PRXINFO_STRUC)(pData + ThisFrameLen); - - // update next packet read position. - pAd->ReadPosition += (ThisFrameLen + RT2870_RXDMALEN_FIELD_SIZE + RXINFO_SIZE); // 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXINFO_STRUC)) - - return pSkb; - -label_null: - - return NULL; -} - - -/* -======================================================================== -Routine Description: - Handle received packets. - -Arguments: - data - URB information pointer - -Return Value: - None - -Note: -======================================================================== -*/ -static void rx_done_tasklet(unsigned long data) -{ - purbb_t pUrb; - PRX_CONTEXT pRxContext; - PRTMP_ADAPTER pAd; - NTSTATUS Status; - unsigned int IrqFlags; - - pUrb = (purbb_t)data; - pRxContext = (PRX_CONTEXT)pUrb->context; - pAd = pRxContext->pAd; - Status = pUrb->status; - - - RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); - pRxContext->InUse = FALSE; - pRxContext->IRPPending = FALSE; - pRxContext->BulkInOffset += pUrb->actual_length; - //NdisInterlockedDecrement(&pAd->PendingRx); - pAd->PendingRx--; - - if (Status == USB_ST_NOERROR) - { - pAd->BulkInComplete++; - pAd->NextRxBulkInPosition = 0; - if (pRxContext->BulkInOffset) // As jan's comment, it may bulk-in success but size is zero. - { - pRxContext->Readable = TRUE; - INC_RING_INDEX(pAd->NextRxBulkInIndex, RX_RING_SIZE); - } - RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); - } - else // STATUS_OTHER - { - pAd->BulkInCompleteFail++; - // Still read this packet although it may comtain wrong bytes. - pRxContext->Readable = FALSE; - RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); - - // Parsing all packets. because after reset, the index will reset to all zero. - if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_BULKIN_RESET | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_NIC_NOT_EXIST)))) - { - - DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk In Failed. Status=%d, BIIdx=0x%x, BIRIdx=0x%x, actual_length= 0x%x\n", - Status, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex, pRxContext->pUrb->actual_length)); - - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0); - } - } - - ASSERT((pRxContext->InUse == pRxContext->IRPPending)); - - RTUSBBulkReceive(pAd); - - return; - -} - - -static void rt2870_mgmt_dma_done_tasklet(unsigned long data) -{ - PRTMP_ADAPTER pAd; - PTX_CONTEXT pMLMEContext; - int index; - PNDIS_PACKET pPacket; - purbb_t pUrb; - NTSTATUS Status; - unsigned long IrqFlags; - - - pUrb = (purbb_t)data; - pMLMEContext = (PTX_CONTEXT)pUrb->context; - pAd = pMLMEContext->pAd; - Status = pUrb->status; - index = pMLMEContext->SelfIdx; - - ASSERT((pAd->MgmtRing.TxDmaIdx == index)); - - RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); - - - if (Status != USB_ST_NOERROR) - { - //Bulk-Out fail status handle - if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out MLME Failed, Status=%d!\n", Status)); - // TODO: How to handle about the MLMEBulkOut failed issue. Need to resend the mgmt pkt? - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); - pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); - } - } - - pAd->BulkOutPending[MGMTPIPEIDX] = FALSE; - RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); - - RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags); - // Reset MLME context flags - pMLMEContext->IRPPending = FALSE; - pMLMEContext->InUse = FALSE; - pMLMEContext->bWaitingBulkOut = FALSE; - pMLMEContext->BulkOutSize = 0; - - pPacket = pAd->MgmtRing.Cell[index].pNdisPacket; - pAd->MgmtRing.Cell[index].pNdisPacket = NULL; - - // Increase MgmtRing Index - INC_RING_INDEX(pAd->MgmtRing.TxDmaIdx, MGMT_RING_SIZE); - pAd->MgmtRing.TxSwFreeIdx++; - RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags); - - // No-matter success or fail, we free the mgmt packet. - if (pPacket) - RTMPFreeNdisPacket(pAd, pPacket); - - if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_NIC_NOT_EXIST)))) - { - // do nothing and return directly. - } - else - { - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET) && - ((pAd->bulkResetPipeid & BULKOUT_MGMT_RESET_FLAG) == BULKOUT_MGMT_RESET_FLAG)) - { // For Mgmt Bulk-Out failed, ignore it now. - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); - } - else - { - - // Always call Bulk routine, even reset bulk. - // The protectioon of rest bulk should be in BulkOut routine - if (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE /* pMLMEContext->bWaitingBulkOut == TRUE */) - { - RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); - } - RTUSBKickBulkOut(pAd); - } - } - -} - - -static void rt2870_hcca_dma_done_tasklet(unsigned long data) -{ - PRTMP_ADAPTER pAd; - PHT_TX_CONTEXT pHTTXContext; - UCHAR BulkOutPipeId = 4; - purbb_t pUrb; - - DBGPRINT_RAW(RT_DEBUG_ERROR, ("--->hcca_dma_done_tasklet\n")); - - pUrb = (purbb_t)data; - pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; - pAd = pHTTXContext->pAd; - - rt2870_dataout_complete_tasklet((unsigned long)pUrb); - - if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_NIC_NOT_EXIST)))) - { - // do nothing and return directly. - } - else - { - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) - { - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); - } - else - { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; - if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && - /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ - (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && - (pHTTXContext->bCurWriting == FALSE)) - { - RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); - } - - RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<4); - RTUSBKickBulkOut(pAd); - } - } - - DBGPRINT_RAW(RT_DEBUG_ERROR, ("<---hcca_dma_done_tasklet\n")); -} - - -static void rt2870_ac3_dma_done_tasklet(unsigned long data) -{ - PRTMP_ADAPTER pAd; - PHT_TX_CONTEXT pHTTXContext; - UCHAR BulkOutPipeId = 3; - purbb_t pUrb; - - - pUrb = (purbb_t)data; - pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; - pAd = pHTTXContext->pAd; - - rt2870_dataout_complete_tasklet((unsigned long)pUrb); - - if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_NIC_NOT_EXIST)))) - { - // do nothing and return directly. - } - else - { - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) - { - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); - } - else - { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; - if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && - /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ - (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && - (pHTTXContext->bCurWriting == FALSE)) - { - RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); - } - - RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<3); - RTUSBKickBulkOut(pAd); - } - } - - - return; -} - - -static void rt2870_ac2_dma_done_tasklet(unsigned long data) -{ - PRTMP_ADAPTER pAd; - PHT_TX_CONTEXT pHTTXContext; - UCHAR BulkOutPipeId = 2; - purbb_t pUrb; - - - pUrb = (purbb_t)data; - pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; - pAd = pHTTXContext->pAd; - - rt2870_dataout_complete_tasklet((unsigned long)pUrb); - - if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_NIC_NOT_EXIST)))) - { - // do nothing and return directly. - } - else - { - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) - { - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); - } - else - { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; - if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && - /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ - (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && - (pHTTXContext->bCurWriting == FALSE)) - { - RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); - } - - RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<2); - RTUSBKickBulkOut(pAd); - } - } - - return; -} - - -static void rt2870_ac1_dma_done_tasklet(unsigned long data) -{ - PRTMP_ADAPTER pAd; - PHT_TX_CONTEXT pHTTXContext; - UCHAR BulkOutPipeId = 1; - purbb_t pUrb; - - - pUrb = (purbb_t)data; - pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; - pAd = pHTTXContext->pAd; - - rt2870_dataout_complete_tasklet((unsigned long)pUrb); - - if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_NIC_NOT_EXIST)))) - { - // do nothing and return directly. - } - else - { - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) - { - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); - } - else - { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; - if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && - /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ - (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && - (pHTTXContext->bCurWriting == FALSE)) - { - RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); - } - - RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<1); - RTUSBKickBulkOut(pAd); - } - } - - - return; -} - - -static void rt2870_ac0_dma_done_tasklet(unsigned long data) -{ - PRTMP_ADAPTER pAd; - PHT_TX_CONTEXT pHTTXContext; - UCHAR BulkOutPipeId = 0; - purbb_t pUrb; - - - pUrb = (purbb_t)data; - pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; - pAd = pHTTXContext->pAd; - - rt2870_dataout_complete_tasklet((unsigned long)pUrb); - - if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_NIC_NOT_EXIST)))) - { - // do nothing and return directly. - } - else - { - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) - { - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); - } - else - { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; - if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && - /* ((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ - (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && - (pHTTXContext->bCurWriting == FALSE)) - { - RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); - } - - RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL); - RTUSBKickBulkOut(pAd); - } - } - - - return; - -} - - -static void rt2870_null_frame_complete_tasklet(unsigned long data) -{ - PRTMP_ADAPTER pAd; - PTX_CONTEXT pNullContext; - purbb_t pUrb; - NTSTATUS Status; - unsigned long irqFlag; - - - pUrb = (purbb_t)data; - pNullContext = (PTX_CONTEXT)pUrb->context; - pAd = pNullContext->pAd; - Status = pUrb->status; - - // Reset Null frame context flags - RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag); - pNullContext->IRPPending = FALSE; - pNullContext->InUse = FALSE; - pAd->BulkOutPending[0] = FALSE; - pAd->watchDogTxPendingCnt[0] = 0; - - if (Status == USB_ST_NOERROR) - { - RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); - - RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); - } - else // STATUS_OTHER - { - if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out Null Frame Failed, ReasonCode=%d!\n", Status)); - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); - pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); - RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); - } - else - { - RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); - } - } - - // Always call Bulk routine, even reset bulk. - // The protectioon of rest bulk should be in BulkOut routine - RTUSBKickBulkOut(pAd); - -} - - -static void rt2870_rts_frame_complete_tasklet(unsigned long data) -{ - PRTMP_ADAPTER pAd; - PTX_CONTEXT pRTSContext; - purbb_t pUrb; - NTSTATUS Status; - unsigned long irqFlag; - - - pUrb = (purbb_t)data; - pRTSContext = (PTX_CONTEXT)pUrb->context; - pAd = pRTSContext->pAd; - Status = pUrb->status; - - // Reset RTS frame context flags - RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag); - pRTSContext->IRPPending = FALSE; - pRTSContext->InUse = FALSE; - - if (Status == USB_ST_NOERROR) - { - RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); - RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); - } - else // STATUS_OTHER - { - if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out RTS Frame Failed\n")); - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); - pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); - RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); - } - else - { - RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); - } - } - - RTMP_SEM_LOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId]); - pAd->BulkOutPending[pRTSContext->BulkOutPipeId] = FALSE; - RTMP_SEM_UNLOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId]); - - // Always call Bulk routine, even reset bulk. - // The protectioon of rest bulk should be in BulkOut routine - RTUSBKickBulkOut(pAd); - -} - - -static void rt2870_pspoll_frame_complete_tasklet(unsigned long data) -{ - PRTMP_ADAPTER pAd; - PTX_CONTEXT pPsPollContext; - purbb_t pUrb; - NTSTATUS Status; - - - pUrb = (purbb_t)data; - pPsPollContext = (PTX_CONTEXT)pUrb->context; - pAd = pPsPollContext->pAd; - Status = pUrb->status; - - // Reset PsPoll context flags - pPsPollContext->IRPPending = FALSE; - pPsPollContext->InUse = FALSE; - pAd->watchDogTxPendingCnt[0] = 0; - - if (Status == USB_ST_NOERROR) - { - RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); - } - else // STATUS_OTHER - { - if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out PSPoll Failed\n")); - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); - pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); - } - } - - RTMP_SEM_LOCK(&pAd->BulkOutLock[0]); - pAd->BulkOutPending[0] = FALSE; - RTMP_SEM_UNLOCK(&pAd->BulkOutLock[0]); - - // Always call Bulk routine, even reset bulk. - // The protectioon of rest bulk should be in BulkOut routine - RTUSBKickBulkOut(pAd); - -} - - -static void rt2870_dataout_complete_tasklet(unsigned long data) -{ - PRTMP_ADAPTER pAd; - purbb_t pUrb; - POS_COOKIE pObj; - PHT_TX_CONTEXT pHTTXContext; - UCHAR BulkOutPipeId; - NTSTATUS Status; - unsigned long IrqFlags; - - - pUrb = (purbb_t)data; - pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; - pAd = pHTTXContext->pAd; - pObj = (POS_COOKIE) pAd->OS_Cookie; - Status = pUrb->status; - - // Store BulkOut PipeId - BulkOutPipeId = pHTTXContext->BulkOutPipeId; - pAd->BulkOutDataOneSecCount++; - - //DBGPRINT(RT_DEBUG_LOUD, ("Done-B(%d):I=0x%lx, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", BulkOutPipeId, in_interrupt(), pHTTXContext->CurWritePosition, - // pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); - - RTMP_IRQ_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); - pAd->BulkOutPending[BulkOutPipeId] = FALSE; - pHTTXContext->IRPPending = FALSE; - pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0; - - if (Status == USB_ST_NOERROR) - { - pAd->BulkOutComplete++; - - RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); - - pAd->Counters8023.GoodTransmits++; - //RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); - FREE_HTTX_RING(pAd, BulkOutPipeId, pHTTXContext); - //RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); - - - } - else // STATUS_OTHER - { - PUCHAR pBuf; - - pAd->BulkOutCompleteOther++; - - pBuf = &pHTTXContext->TransferBuffer->field.WirelessPacket[pHTTXContext->NextBulkOutPosition]; - - if (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_NIC_NOT_EXIST | - fRTMP_ADAPTER_BULKOUT_RESET))) - { - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); - pAd->bulkResetPipeid = BulkOutPipeId; - pAd->bulkResetReq[BulkOutPipeId] = pAd->BulkOutReq; - } - RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); - - DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkOutDataPacket failed: ReasonCode=%d!\n", Status)); - DBGPRINT_RAW(RT_DEBUG_ERROR, ("\t>>BulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther)); - DBGPRINT_RAW(RT_DEBUG_ERROR, ("\t>>BulkOut Header:%x %x %x %x %x %x %x %x\n", pBuf[0], pBuf[1], pBuf[2], pBuf[3], pBuf[4], pBuf[5], pBuf[6], pBuf[7])); - //DBGPRINT_RAW(RT_DEBUG_ERROR, (">>BulkOutCompleteCancel=0x%x, BulkOutCompleteOther=0x%x\n", pAd->BulkOutCompleteCancel, pAd->BulkOutCompleteOther)); - - } - - // - // bInUse = TRUE, means some process are filling TX data, after that must turn on bWaitingBulkOut - // bWaitingBulkOut = TRUE, means the TX data are waiting for bulk out. - // - //RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); - if ((pHTTXContext->ENextBulkOutPosition != pHTTXContext->CurWritePosition) && - (pHTTXContext->ENextBulkOutPosition != (pHTTXContext->CurWritePosition+8)) && - !RTUSB_TEST_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId))) - { - // Indicate There is data avaliable - RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); - } - //RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); - - // Always call Bulk routine, even reset bulk. - // The protection of rest bulk should be in BulkOut routine - RTUSBKickBulkOut(pAd); -} - -/* End of 2870_rtmp_init.c */ diff --git a/drivers/staging/rt2870/common/acction.c b/drivers/staging/rt2870/common/acction.c new file mode 100644 index 0000000000000000000000000000000000000000..fd806c3871aa6d5709a80af643f20e20d6637edf --- /dev/null +++ b/drivers/staging/rt2870/common/acction.c @@ -0,0 +1 @@ +#include "../../rt2860/common/action.c" diff --git a/drivers/staging/rt2870/common/cmm_aes.c b/drivers/staging/rt2870/common/cmm_aes.c new file mode 100644 index 0000000000000000000000000000000000000000..15d6a14d2d9cbfa7ea8b84253f6589291c46ea86 --- /dev/null +++ b/drivers/staging/rt2870/common/cmm_aes.c @@ -0,0 +1 @@ +#include "../../rt2860/common/cmm_aes.c" diff --git a/drivers/staging/rt2870/common/cmm_asic.c b/drivers/staging/rt2870/common/cmm_asic.c new file mode 100644 index 0000000000000000000000000000000000000000..38de817991ffaa2687475d5f0f06e7f939cd1fe6 --- /dev/null +++ b/drivers/staging/rt2870/common/cmm_asic.c @@ -0,0 +1 @@ +#include "../../rt2860/common/cmm_asic.c" diff --git a/drivers/staging/rt2870/common/cmm_cfg.c b/drivers/staging/rt2870/common/cmm_cfg.c new file mode 100644 index 0000000000000000000000000000000000000000..6b2bdd7d44ec945ce5e9bfa151cff70018a7f630 --- /dev/null +++ b/drivers/staging/rt2870/common/cmm_cfg.c @@ -0,0 +1 @@ +#include "../../rt2860/common/cmm_cfg.c" diff --git a/drivers/staging/rt2870/common/cmm_data_2870.c b/drivers/staging/rt2870/common/cmm_data_2870.c deleted file mode 100644 index 3b63a48310f054241c26bc23d604de76e767f1c3..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2870/common/cmm_data_2870.c +++ /dev/null @@ -1,936 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* -*/ -/* - All functions in this file must be USB-depended, or you should out your function - in other files. - -*/ -#include "../rt_config.h" - - -/* - We can do copy the frame into pTxContext when match following conditions. - => - => - => -*/ -static inline NDIS_STATUS RtmpUSBCanDoWrite( - IN RTMP_ADAPTER *pAd, - IN UCHAR QueIdx, - IN HT_TX_CONTEXT *pHTTXContext) -{ - NDIS_STATUS canWrite = NDIS_STATUS_RESOURCES; - - if (((pHTTXContext->CurWritePosition) < pHTTXContext->NextBulkOutPosition) && (pHTTXContext->CurWritePosition + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition) - { - DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c1!\n")); - RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx)); - } - else if ((pHTTXContext->CurWritePosition == 8) && (pHTTXContext->NextBulkOutPosition < LOCAL_TXBUF_SIZE)) - { - DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c2!\n")); - RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx)); - } - else if (pHTTXContext->bCurWriting == TRUE) - { - DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c3!\n")); - } - else - { - canWrite = NDIS_STATUS_SUCCESS; - } - - - return canWrite; -} - - -USHORT RtmpUSB_WriteSubTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN BOOLEAN bIsLast, - OUT USHORT *FreeNumber) -{ - - // Dummy function. Should be removed in the future. - return 0; - -} - -USHORT RtmpUSB_WriteFragTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR fragNum, - OUT USHORT *FreeNumber) -{ - HT_TX_CONTEXT *pHTTXContext; - USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length. - UINT32 fillOffset; - TXINFO_STRUC *pTxInfo; - TXWI_STRUC *pTxWI; - PUCHAR pWirelessPacket = NULL; - UCHAR QueIdx; - NDIS_STATUS Status; - unsigned long IrqFlags; - UINT32 USBDMApktLen = 0, DMAHdrLen, padding; - BOOLEAN TxQLastRound = FALSE; - - // - // get Tx Ring Resource & Dma Buffer address - // - QueIdx = pTxBlk->QueIdx; - pHTTXContext = &pAd->TxContext[QueIdx]; - - RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - - pHTTXContext = &pAd->TxContext[QueIdx]; - fillOffset = pHTTXContext->CurWritePosition; - - if(fragNum == 0) - { - // Check if we have enough space for this bulk-out batch. - Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); - if (Status == NDIS_STATUS_SUCCESS) - { - pHTTXContext->bCurWriting = TRUE; - - // Reserve space for 8 bytes padding. - if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) - { - pHTTXContext->ENextBulkOutPosition += 8; - pHTTXContext->CurWritePosition += 8; - fillOffset += 8; - } - pTxBlk->Priv = 0; - pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; - } - else - { - RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - - RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); - return(Status); - } - } - else - { - // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. - Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); - if (Status == NDIS_STATUS_SUCCESS) - { - fillOffset += pTxBlk->Priv; - } - else - { - RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - - RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); - return(Status); - } - } - - NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE); - pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); - pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); - - pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; - - // copy TXWI + WLAN Header + LLC into DMA Header Buffer - //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); - hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; - - // Build our URB for USBD - DMAHdrLen = TXWI_SIZE + hwHdrLen; - USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; - padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment - USBDMApktLen += padding; - - pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen); - - // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload - RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); - - if (fragNum == pTxBlk->TotalFragNum) - { - pTxInfo->USBDMATxburst = 0; - if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT) - { - pTxInfo->SwUseLastRound = 1; - TxQLastRound = TRUE; - } - } - else - { - pTxInfo->USBDMATxburst = 1; - } - - NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); - pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); - pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); - - RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - - NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); - - // Zero the last padding. - pWirelessPacket += pTxBlk->SrcBufLen; - NdisZeroMemory(pWirelessPacket, padding + 8); - - if (fragNum == pTxBlk->TotalFragNum) - { - RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - - // Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame. - pHTTXContext->CurWritePosition += pTxBlk->Priv; - if (TxQLastRound == TRUE) - pHTTXContext->CurWritePosition = 8; - pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; - - - // Finally, set bCurWriting as FALSE - pHTTXContext->bCurWriting = FALSE; - - RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - - // succeed and release the skb buffer - RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); - } - - - return(Status); - -} - - -USHORT RtmpUSB_WriteSingleTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN BOOLEAN bIsLast, - OUT USHORT *FreeNumber) -{ - HT_TX_CONTEXT *pHTTXContext; - USHORT hwHdrLen; - UINT32 fillOffset; - TXINFO_STRUC *pTxInfo; - TXWI_STRUC *pTxWI; - PUCHAR pWirelessPacket; - UCHAR QueIdx; - unsigned long IrqFlags; - NDIS_STATUS Status; - UINT32 USBDMApktLen = 0, DMAHdrLen, padding; - BOOLEAN bTxQLastRound = FALSE; - - // For USB, didn't need PCI_MAP_SINGLE() - //SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE); - - - // - // get Tx Ring Resource & Dma Buffer address - // - QueIdx = pTxBlk->QueIdx; - - RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - pHTTXContext = &pAd->TxContext[QueIdx]; - fillOffset = pHTTXContext->CurWritePosition; - - - - // Check ring full. - Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); - if(Status == NDIS_STATUS_SUCCESS) - { - pHTTXContext->bCurWriting = TRUE; - - pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); - pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); - - // Reserve space for 8 bytes padding. - if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) - { - pHTTXContext->ENextBulkOutPosition += 8; - pHTTXContext->CurWritePosition += 8; - fillOffset += 8; - } - pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; - - pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; - - // copy TXWI + WLAN Header + LLC into DMA Header Buffer - //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); - hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; - - // Build our URB for USBD - DMAHdrLen = TXWI_SIZE + hwHdrLen; - USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; - padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment - USBDMApktLen += padding; - - pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen); - - // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload - //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) - RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); - - if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT) - { - pTxInfo->SwUseLastRound = 1; - bTxQLastRound = TRUE; - } - NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); - pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); - - // We unlock it here to prevent the first 8 bytes maybe over-writed issue. - // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext. - // 2. An interrupt break our routine and handle bulk-out complete. - // 3. In the bulk-out compllete, it need to do another bulk-out, - // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, - // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. - // 4. Interrupt complete. - // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. - // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. - // and the packet will wrong. - pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); - RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - - NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); - pWirelessPacket += pTxBlk->SrcBufLen; - NdisZeroMemory(pWirelessPacket, padding + 8); - - RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - - pHTTXContext->CurWritePosition += pTxBlk->Priv; - if (bTxQLastRound) - pHTTXContext->CurWritePosition = 8; - pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; - - pHTTXContext->bCurWriting = FALSE; - } - - - RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - - - // succeed and release the skb buffer - RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); - - return(Status); - -} - - -USHORT RtmpUSB_WriteMultiTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR frameNum, - OUT USHORT *FreeNumber) -{ - HT_TX_CONTEXT *pHTTXContext; - USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length. - UINT32 fillOffset; - TXINFO_STRUC *pTxInfo; - TXWI_STRUC *pTxWI; - PUCHAR pWirelessPacket = NULL; - UCHAR QueIdx; - NDIS_STATUS Status; - unsigned long IrqFlags; - //UINT32 USBDMApktLen = 0, DMAHdrLen, padding; - - // - // get Tx Ring Resource & Dma Buffer address - // - QueIdx = pTxBlk->QueIdx; - pHTTXContext = &pAd->TxContext[QueIdx]; - - RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - - if(frameNum == 0) - { - // Check if we have enough space for this bulk-out batch. - Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); - if (Status == NDIS_STATUS_SUCCESS) - { - pHTTXContext->bCurWriting = TRUE; - - pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); - pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); - - - // Reserve space for 8 bytes padding. - if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) - { - - pHTTXContext->CurWritePosition += 8; - pHTTXContext->ENextBulkOutPosition += 8; - } - fillOffset = pHTTXContext->CurWritePosition; - pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; - - pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; - - // - // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer - // - if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) - //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; - hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; - else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) - //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; - hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; - else - //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); - hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; - - // Update the pTxBlk->Priv. - pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; - - // pTxInfo->USBDMApktLen now just a temp value and will to correct latter. - RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); - - // Copy it. - NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv); - pHTTXContext->CurWriteRealPos += pTxBlk->Priv; - pWirelessPacket += pTxBlk->Priv; - } - } - else - { // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. - - Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); - if (Status == NDIS_STATUS_SUCCESS) - { - fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv); - pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; - - //hwHdrLen = pTxBlk->MpduHeaderLen; - NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen); - pWirelessPacket += (pTxBlk->MpduHeaderLen); - pTxBlk->Priv += pTxBlk->MpduHeaderLen; - } - else - { // It should not happened now unless we are going to shutdown. - DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n")); - Status = NDIS_STATUS_FAILURE; - } - } - - - // We unlock it here to prevent the first 8 bytes maybe over-write issue. - // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext. - // 2. An interrupt break our routine and handle bulk-out complete. - // 3. In the bulk-out compllete, it need to do another bulk-out, - // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, - // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. - // 4. Interrupt complete. - // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. - // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. - // and the packet will wrong. - RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition)); - goto done; - } - - // Copy the frame content into DMA buffer and update the pTxBlk->Priv - NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); - pWirelessPacket += pTxBlk->SrcBufLen; - pTxBlk->Priv += pTxBlk->SrcBufLen; - -done: - // Release the skb buffer here - RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); - - return(Status); - -} - - -VOID RtmpUSB_FinalWriteTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN USHORT totalMPDUSize, - IN USHORT TxIdx) -{ - UCHAR QueIdx; - HT_TX_CONTEXT *pHTTXContext; - UINT32 fillOffset; - TXINFO_STRUC *pTxInfo; - TXWI_STRUC *pTxWI; - UINT32 USBDMApktLen, padding; - unsigned long IrqFlags; - PUCHAR pWirelessPacket; - - QueIdx = pTxBlk->QueIdx; - pHTTXContext = &pAd->TxContext[QueIdx]; - - RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - - if (pHTTXContext->bCurWriting == TRUE) - { - fillOffset = pHTTXContext->CurWritePosition; - if (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition)) - && (pHTTXContext->bCopySavePad == TRUE)) - pWirelessPacket = (PUCHAR)(&pHTTXContext->SavedPad[0]); - else - pWirelessPacket = (PUCHAR)(&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]); - - // - // Update TxInfo->USBDMApktLen , - // the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding - // - pTxInfo = (PTXINFO_STRUC)(pWirelessPacket); - - // Calculate the bulk-out padding - USBDMApktLen = pTxBlk->Priv - TXINFO_SIZE; - padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment - USBDMApktLen += padding; - - pTxInfo->USBDMATxPktLen = USBDMApktLen; - - // - // Update TXWI->MPDUtotalByteCount , - // the length = 802.11 header + payload_of_all_batch_frames - pTxWI= (PTXWI_STRUC)(pWirelessPacket + TXINFO_SIZE); - pTxWI->MPDUtotalByteCount = totalMPDUSize; - - // - // Update the pHTTXContext->CurWritePosition - // - pHTTXContext->CurWritePosition += (TXINFO_SIZE + USBDMApktLen); - if ((pHTTXContext->CurWritePosition + 3906)> MAX_TXBULK_LIMIT) - { // Add 3906 for prevent the NextBulkOut packet size is a A-RALINK/A-MSDU Frame. - pHTTXContext->CurWritePosition = 8; - pTxInfo->SwUseLastRound = 1; - } - pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; - - - // - // Zero the last padding. - // - pWirelessPacket = (&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset + pTxBlk->Priv]); - NdisZeroMemory(pWirelessPacket, padding + 8); - - // Finally, set bCurWriting as FALSE - pHTTXContext->bCurWriting = FALSE; - - } - else - { // It should not happened now unless we are going to shutdown. - DBGPRINT(RT_DEBUG_ERROR, ("FinalWriteTxResource():bCurWriting is FALSE when handle last frames.\n")); - } - - RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); - -} - - -VOID RtmpUSBDataLastTxIdx( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN USHORT TxIdx) -{ - // DO nothing for USB. -} - - -/* - When can do bulk-out: - 1. TxSwFreeIdx < TX_RING_SIZE; - It means has at least one Ring entity is ready for bulk-out, kick it out. - 2. If TxSwFreeIdx == TX_RING_SIZE - Check if the CurWriting flag is FALSE, if it's FALSE, we can do kick out. - -*/ -VOID RtmpUSBDataKickOut( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR QueIdx) -{ - RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx)); - RTUSBKickBulkOut(pAd); - -} - - -/* - Must be run in Interrupt context - This function handle RT2870 specific TxDesc and cpu index update and kick the packet out. - */ -int RtmpUSBMgmtKickOut( - IN RTMP_ADAPTER *pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket, - IN PUCHAR pSrcBufVA, - IN UINT SrcBufLen) -{ - PTXINFO_STRUC pTxInfo; - ULONG BulkOutSize; - UCHAR padLen; - PUCHAR pDest; - ULONG SwIdx = pAd->MgmtRing.TxCpuIdx; - PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[SwIdx].AllocVa; - unsigned long IrqFlags; - - - pTxInfo = (PTXINFO_STRUC)(pSrcBufVA); - - // Build our URB for USBD - BulkOutSize = SrcBufLen; - BulkOutSize = (BulkOutSize + 3) & (~3); - RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(BulkOutSize - TXINFO_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); - - BulkOutSize += 4; // Always add 4 extra bytes at every packet. - - // If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again. - if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0) - BulkOutSize += 4; - - padLen = BulkOutSize - SrcBufLen; - ASSERT((padLen <= RTMP_PKT_TAIL_PADDING)); - - // Now memzero all extra padding bytes. - pDest = (PUCHAR)(pSrcBufVA + SrcBufLen); - skb_put(GET_OS_PKT_TYPE(pPacket), padLen); - NdisZeroMemory(pDest, padLen); - - RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags); - - pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket; - pMLMEContext->TransferBuffer = (PTX_BUFFER)(GET_OS_PKT_DATAPTR(pPacket)); - - // Length in TxInfo should be 8 less than bulkout size. - pMLMEContext->BulkOutSize = BulkOutSize; - pMLMEContext->InUse = TRUE; - pMLMEContext->bWaitingBulkOut = TRUE; - - - //for debug - //hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize)); - - //pAd->RalinkCounters.KickTxCount++; - //pAd->RalinkCounters.OneSecTxDoneCount++; - - //if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE) - // needKickOut = TRUE; - - // Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX - pAd->MgmtRing.TxSwFreeIdx--; - INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); - - RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags); - - RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); - //if (needKickOut) - RTUSBKickBulkOut(pAd); - - return 0; -} - - -VOID RtmpUSBNullFrameKickOut( - IN RTMP_ADAPTER *pAd, - IN UCHAR QueIdx, - IN UCHAR *pNullFrame, - IN UINT32 frameLen) -{ - if (pAd->NullContext.InUse == FALSE) - { - PTX_CONTEXT pNullContext; - PTXINFO_STRUC pTxInfo; - PTXWI_STRUC pTxWI; - PUCHAR pWirelessPkt; - - pNullContext = &(pAd->NullContext); - - // Set the in use bit - pNullContext->InUse = TRUE; - pWirelessPkt = (PUCHAR)&pNullContext->TransferBuffer->field.WirelessPacket[0]; - - RTMPZeroMemory(&pWirelessPkt[0], 100); - pTxInfo = (PTXINFO_STRUC)&pWirelessPkt[0]; - RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(HEADER_802_11)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); - pTxInfo->QSEL = FIFO_EDCA; - pTxWI = (PTXWI_STRUC)&pWirelessPkt[TXINFO_SIZE]; - RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(HEADER_802_11)), - 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit); - RTMPMoveMemory(&pWirelessPkt[TXWI_SIZE+TXINFO_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11)); - pAd->NullContext.BulkOutSize = TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4; - - // Fill out frame length information for global Bulk out arbitor - //pNullContext->BulkOutSize = TransferBufferLength; - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - send NULL Frame @%d Mbps...\n", RateIdToMbps[pAd->CommonCfg.TxRate])); - RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL); - - // Kick bulk out - RTUSBKickBulkOut(pAd); - } - -} - -/* - ======================================================================== - - Routine Description: - Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound - - Arguments: - pRxD Pointer to the Rx descriptor - - Return Value: - NDIS_STATUS_SUCCESS No err - NDIS_STATUS_FAILURE Error - - Note: - - ======================================================================== -*/ -NDIS_STATUS RTMPCheckRxError( - IN PRTMP_ADAPTER pAd, - IN PHEADER_802_11 pHeader, - IN PRXWI_STRUC pRxWI, - IN PRT28XX_RXD_STRUC pRxINFO) -{ - PCIPHER_KEY pWpaKey; - INT dBm; - - if (pAd->bPromiscuous == TRUE) - return(NDIS_STATUS_SUCCESS); - if(pRxINFO == NULL) - return(NDIS_STATUS_FAILURE); - - // Phy errors & CRC errors - if (pRxINFO->Crc) - { - // Check RSSI for Noise Hist statistic collection. - dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta; - if (dBm <= -87) - pAd->StaCfg.RPIDensity[0] += 1; - else if (dBm <= -82) - pAd->StaCfg.RPIDensity[1] += 1; - else if (dBm <= -77) - pAd->StaCfg.RPIDensity[2] += 1; - else if (dBm <= -72) - pAd->StaCfg.RPIDensity[3] += 1; - else if (dBm <= -67) - pAd->StaCfg.RPIDensity[4] += 1; - else if (dBm <= -62) - pAd->StaCfg.RPIDensity[5] += 1; - else if (dBm <= -57) - pAd->StaCfg.RPIDensity[6] += 1; - else if (dBm > -57) - pAd->StaCfg.RPIDensity[7] += 1; - - return(NDIS_STATUS_FAILURE); - } - - // Add Rx size to channel load counter, we should ignore error counts - pAd->StaCfg.CLBusyBytes += (pRxWI->MPDUtotalByteCount+ 14); - - // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics - if (pHeader->FC.ToDs) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("Err;FC.ToDs\n")); - return NDIS_STATUS_FAILURE; - } - - // Paul 04-03 for OFDM Rx length issue - if (pRxWI->MPDUtotalByteCount > MAX_AGGREGATION_SIZE) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n")); - return NDIS_STATUS_FAILURE; - } - - // Drop not U2M frames, cant's drop here because we will drop beacon in this case - // I am kind of doubting the U2M bit operation - // if (pRxD->U2M == 0) - // return(NDIS_STATUS_FAILURE); - - // drop decyption fail frame - if (pRxINFO->Decrypted && pRxINFO->CipherErr) - { - - // - // MIC Error - // - if ((pRxINFO->CipherErr == 2) && pRxINFO->MyBss) - { - pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex]; - RTMPReportMicError(pAd, pWpaKey); - DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n")); - } - - if (pRxINFO->Decrypted && - (pAd->SharedKey[BSS0][pRxWI->KeyIndex].CipherAlg == CIPHER_AES) && - (pHeader->Sequence == pAd->FragFrame.Sequence)) - { - // - // Acceptable since the First FragFrame no CipherErr problem. - // - return(NDIS_STATUS_SUCCESS); - } - - return(NDIS_STATUS_FAILURE); - } - - return(NDIS_STATUS_SUCCESS); -} - -VOID RT28xxUsbStaAsicForceWakeup( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bFromTx) -{ - AUTO_WAKEUP_STRUC AutoWakeupCfg; - - AutoWakeupCfg.word = 0; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - - AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); - - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); -} - -VOID RT28xxUsbStaAsicSleepThenAutoWakeup( - IN PRTMP_ADAPTER pAd, - IN USHORT TbttNumToNextWakeUp) -{ - AUTO_WAKEUP_STRUC AutoWakeupCfg; - - // we have decided to SLEEP, so at least do it for a BEACON period. - if (TbttNumToNextWakeUp == 0) - TbttNumToNextWakeUp = 1; - - AutoWakeupCfg.word = 0; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - - AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; - AutoWakeupCfg.field.EnableAutoWakeup = 1; - AutoWakeupCfg.field.AutoLeadTime = 5; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - - AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); // send POWER-SAVE command to MCU. Timeout 40us. - - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); - -} - -VOID RT28xxUsbMlmeRadioOn( - IN PRTMP_ADAPTER pAd) -{ - DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOn()\n")); - - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) - return; - - AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); - RTMPusecDelay(10000); - - NICResetFromError(pAd); - - // Enable Tx/Rx - RTMPEnableRxTx(pAd); - -#ifdef RT3070 - if (IS_RT3071(pAd)) - { - RT30xxReverseRFSleepModeSetup(pAd); - } -#endif // RT3070 // - - // Clear Radio off flag - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - - RTUSBBulkReceive(pAd); - - // Set LED - RTMPSetLED(pAd, LED_RADIO_ON); -} - -VOID RT28xxUsbMlmeRadioOFF( - IN PRTMP_ADAPTER pAd) -{ - WPDMA_GLO_CFG_STRUC GloCfg; - UINT32 Value, i; - - DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOFF()\n")); - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) - return; - - // Set LED - RTMPSetLED(pAd, LED_RADIO_OFF); - // Set Radio off flag - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - - { - // Link down first if any association exists - if (INFRA_ON(pAd) || ADHOC_ON(pAd)) - LinkDown(pAd, FALSE); - RTMPusecDelay(10000); - - //========================================== - // Clean up old bss table - BssTableInit(&pAd->ScanTab); - } - - if (pAd->CommonCfg.BBPCurrentBW == BW_40) - { - // Must using 40MHz. - AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); - } - else - { - // Must using 20MHz. - AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); - } - - // Disable Tx/Rx DMA - RTUSBReadMACRegister(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA - GloCfg.field.EnableTxDMA = 0; - GloCfg.field.EnableRxDMA = 0; - RTUSBWriteMACRegister(pAd, WPDMA_GLO_CFG, GloCfg.word); // abort all TX rings - - // Waiting for DMA idle - i = 0; - do - { - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); - if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) - break; - - RTMPusecDelay(1000); - }while (i++ < 100); - - // Disable MAC Tx/Rx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value &= (0xfffffff3); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - - AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); -} - diff --git a/drivers/staging/rt2870/common/cmm_data_usb.c b/drivers/staging/rt2870/common/cmm_data_usb.c new file mode 100644 index 0000000000000000000000000000000000000000..704675fccb7d1fe99b8054f1b11e8912f6e595db --- /dev/null +++ b/drivers/staging/rt2870/common/cmm_data_usb.c @@ -0,0 +1 @@ +#include "../../rt2860/common/cmm_data_usb.c" diff --git a/drivers/staging/rt2870/common/cmm_mac_usb.c b/drivers/staging/rt2870/common/cmm_mac_usb.c new file mode 100644 index 0000000000000000000000000000000000000000..b26af4af890b9d8724b11220de10f2cc4c461578 --- /dev/null +++ b/drivers/staging/rt2870/common/cmm_mac_usb.c @@ -0,0 +1 @@ +#include "../../rt2860/common/cmm_mac_usb.c" diff --git a/drivers/staging/rt2870/common/cmm_profile.c b/drivers/staging/rt2870/common/cmm_profile.c new file mode 100644 index 0000000000000000000000000000000000000000..9926e45aba3c364000600002cb2cd307f46c7b9c --- /dev/null +++ b/drivers/staging/rt2870/common/cmm_profile.c @@ -0,0 +1 @@ +#include "../../rt2860/common/cmm_profile.c" diff --git a/drivers/staging/rt2870/common/cmm_tkip.c b/drivers/staging/rt2870/common/cmm_tkip.c new file mode 100644 index 0000000000000000000000000000000000000000..f73c71bafe86197657f74f58a41b4b6b6f5c00b3 --- /dev/null +++ b/drivers/staging/rt2870/common/cmm_tkip.c @@ -0,0 +1 @@ +#include "../../rt2860/common/cmm_tkip.c" diff --git a/drivers/staging/rt2870/common/cmm_wep.c b/drivers/staging/rt2870/common/cmm_wep.c new file mode 100644 index 0000000000000000000000000000000000000000..5f681078387fd7e8b4d197e674a8efdaa7a8d5ed --- /dev/null +++ b/drivers/staging/rt2870/common/cmm_wep.c @@ -0,0 +1 @@ +#include "../../rt2860/common/cmm_wep.c" diff --git a/drivers/staging/rt2870/common/crypt_hmac.c b/drivers/staging/rt2870/common/crypt_hmac.c new file mode 100644 index 0000000000000000000000000000000000000000..24d84e7724fb39261dceb1525f0bdb8f4bfa3553 --- /dev/null +++ b/drivers/staging/rt2870/common/crypt_hmac.c @@ -0,0 +1 @@ +#include "../../rt2860/common/crypt_hmac.c" diff --git a/drivers/staging/rt2870/common/crypt_md5.c b/drivers/staging/rt2870/common/crypt_md5.c new file mode 100644 index 0000000000000000000000000000000000000000..457a2caca1e3cbf4dd674eacc9a09dd54ebcaa43 --- /dev/null +++ b/drivers/staging/rt2870/common/crypt_md5.c @@ -0,0 +1 @@ +#include "../../rt2860/common/crypt_md5.c" diff --git a/drivers/staging/rt2870/common/crypt_sha2.c b/drivers/staging/rt2870/common/crypt_sha2.c new file mode 100644 index 0000000000000000000000000000000000000000..07ffb300c193a72e65db1bb2b9d4aea00d3580ec --- /dev/null +++ b/drivers/staging/rt2870/common/crypt_sha2.c @@ -0,0 +1 @@ +#include "../../rt2860/common/crypt_sha2.c" diff --git a/drivers/staging/rt2870/common/ee_efuse.c b/drivers/staging/rt2870/common/ee_efuse.c new file mode 100644 index 0000000000000000000000000000000000000000..0e34e65e5f288257624aff44090ae89f538f2888 --- /dev/null +++ b/drivers/staging/rt2870/common/ee_efuse.c @@ -0,0 +1 @@ +#include "../../rt2860/common/ee_efuse.c" diff --git a/drivers/staging/rt2870/common/rt_channel.c b/drivers/staging/rt2870/common/rt_channel.c new file mode 100644 index 0000000000000000000000000000000000000000..c8ceb4c177d927cad1c7b6aae3a29f853aac06ac --- /dev/null +++ b/drivers/staging/rt2870/common/rt_channel.c @@ -0,0 +1 @@ +#include "../../rt2860/common/rt_channel.c" diff --git a/drivers/staging/rt2870/common/rt_rf.c b/drivers/staging/rt2870/common/rt_rf.c new file mode 100644 index 0000000000000000000000000000000000000000..b81cff34969bda8b5c5fd60b5fd9c8fd4d15503e --- /dev/null +++ b/drivers/staging/rt2870/common/rt_rf.c @@ -0,0 +1 @@ +#include "../../rt2860/common/rt_rf.c" diff --git a/drivers/staging/rt2870/common/rtmp_mcu.c b/drivers/staging/rt2870/common/rtmp_mcu.c new file mode 100644 index 0000000000000000000000000000000000000000..20b7f13d60f860e925c9b7c795d6367822ac6d5c --- /dev/null +++ b/drivers/staging/rt2870/common/rtmp_mcu.c @@ -0,0 +1 @@ +#include "../../rt2860/common/rtmp_mcu.c" diff --git a/drivers/staging/rt2870/common/rtmp_timer.c b/drivers/staging/rt2870/common/rtmp_timer.c new file mode 100644 index 0000000000000000000000000000000000000000..fd4aedcd5e8bae0d38bf094f501e95eb7099fdf5 --- /dev/null +++ b/drivers/staging/rt2870/common/rtmp_timer.c @@ -0,0 +1 @@ +#include "../../rt2860/common/rtmp_timer.c" diff --git a/drivers/staging/rt2870/common/rtusb_bulk.c b/drivers/staging/rt2870/common/rtusb_bulk.c index a4244b516440f8461f1a85ebc006a2151a1b72ee..379780c72b3cd7a39b5b38843e35c89f075edd4d 100644 --- a/drivers/staging/rt2870/common/rtusb_bulk.c +++ b/drivers/staging/rt2870/common/rtusb_bulk.c @@ -1,4 +1,4 @@ - /* +/* ************************************************************************* * Ralink Tech Inc. * 5F., No.36, Taiyuan St., Jhubei City, @@ -37,133 +37,124 @@ */ +#ifdef RTMP_MAC_USB + #include "../rt_config.h" -// Match total 6 bulkout endpoint to corresponding queue. -UCHAR EpToQueue[6]={FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_MGMT}; - -//static BOOLEAN SingleBulkOut = FALSE; - -void RTUSB_FILL_BULK_URB (struct urb *pUrb, - struct usb_device *pUsb_Dev, - unsigned int bulkpipe, - void *pTransferBuf, - int BufSize, - usb_complete_t Complete, - void *pContext) +/* Match total 6 bulkout endpoint to corresponding queue. */ +u8 EpToQueue[6] = + { FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_MGMT }; + +/*static BOOLEAN SingleBulkOut = FALSE; */ + +void RTUSB_FILL_BULK_URB(struct urb *pUrb, + struct usb_device *pUsb_Dev, + unsigned int bulkpipe, + void *pTransferBuf, + int BufSize, usb_complete_t Complete, void *pContext) { - usb_fill_bulk_urb(pUrb, pUsb_Dev, bulkpipe, pTransferBuf, BufSize, (usb_complete_t)Complete, pContext); + usb_fill_bulk_urb(pUrb, pUsb_Dev, bulkpipe, pTransferBuf, BufSize, + (usb_complete_t) Complete, pContext); } -VOID RTUSBInitTxDesc( - IN PRTMP_ADAPTER pAd, - IN PTX_CONTEXT pTxContext, - IN UCHAR BulkOutPipeId, - IN usb_complete_t Func) +void RTUSBInitTxDesc(struct rt_rtmp_adapter *pAd, + struct rt_tx_context *pTxContext, + u8 BulkOutPipeId, IN usb_complete_t Func) { - PURB pUrb; - PUCHAR pSrc = NULL; - POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + PURB pUrb; + u8 *pSrc = NULL; + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; pUrb = pTxContext->pUrb; ASSERT(pUrb); - // Store BulkOut PipeId + /* Store BulkOut PipeId */ pTxContext->BulkOutPipeId = BulkOutPipeId; - if (pTxContext->bAggregatible) - { + if (pTxContext->bAggregatible) { pSrc = &pTxContext->TransferBuffer->Aggregation[2]; - } - else - { - pSrc = (PUCHAR) pTxContext->TransferBuffer->field.WirelessPacket; + } else { + pSrc = + (u8 *)pTxContext->TransferBuffer->field.WirelessPacket; } - - //Initialize a tx bulk urb + /*Initialize a tx bulk urb */ RTUSB_FILL_BULK_URB(pUrb, - pObj->pUsb_Dev, - usb_sndbulkpipe(pObj->pUsb_Dev, pAd->BulkOutEpAddr[BulkOutPipeId]), - pSrc, - pTxContext->BulkOutSize, - Func, - pTxContext); + pObj->pUsb_Dev, + usb_sndbulkpipe(pObj->pUsb_Dev, + pAd->BulkOutEpAddr[BulkOutPipeId]), + pSrc, pTxContext->BulkOutSize, Func, pTxContext); if (pTxContext->bAggregatible) - pUrb->transfer_dma = (pTxContext->data_dma + TX_BUFFER_NORMSIZE + 2); + pUrb->transfer_dma = + (pTxContext->data_dma + TX_BUFFER_NORMSIZE + 2); else - pUrb->transfer_dma = pTxContext->data_dma; + pUrb->transfer_dma = pTxContext->data_dma; pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; } -VOID RTUSBInitHTTxDesc( - IN PRTMP_ADAPTER pAd, - IN PHT_TX_CONTEXT pTxContext, - IN UCHAR BulkOutPipeId, - IN ULONG BulkOutSize, - IN usb_complete_t Func) +void RTUSBInitHTTxDesc(struct rt_rtmp_adapter *pAd, + struct rt_ht_tx_context *pTxContext, + u8 BulkOutPipeId, + unsigned long BulkOutSize, IN usb_complete_t Func) { - PURB pUrb; - PUCHAR pSrc = NULL; - POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + PURB pUrb; + u8 *pSrc = NULL; + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; pUrb = pTxContext->pUrb; ASSERT(pUrb); - // Store BulkOut PipeId + /* Store BulkOut PipeId */ pTxContext->BulkOutPipeId = BulkOutPipeId; - pSrc = &pTxContext->TransferBuffer->field.WirelessPacket[pTxContext->NextBulkOutPosition]; - + pSrc = + &pTxContext->TransferBuffer->field.WirelessPacket[pTxContext-> + NextBulkOutPosition]; - //Initialize a tx bulk urb + /*Initialize a tx bulk urb */ RTUSB_FILL_BULK_URB(pUrb, - pObj->pUsb_Dev, - usb_sndbulkpipe(pObj->pUsb_Dev, pAd->BulkOutEpAddr[BulkOutPipeId]), - pSrc, - BulkOutSize, - Func, - pTxContext); - - pUrb->transfer_dma = (pTxContext->data_dma + pTxContext->NextBulkOutPosition); + pObj->pUsb_Dev, + usb_sndbulkpipe(pObj->pUsb_Dev, + pAd->BulkOutEpAddr[BulkOutPipeId]), + pSrc, BulkOutSize, Func, pTxContext); + + pUrb->transfer_dma = + (pTxContext->data_dma + pTxContext->NextBulkOutPosition); pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; } -VOID RTUSBInitRxDesc( - IN PRTMP_ADAPTER pAd, - IN PRX_CONTEXT pRxContext) +void RTUSBInitRxDesc(struct rt_rtmp_adapter *pAd, struct rt_rx_context *pRxContext) { - PURB pUrb; - POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; - ULONG RX_bulk_size; - + PURB pUrb; + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; + unsigned long RX_bulk_size; pUrb = pRxContext->pUrb; ASSERT(pUrb); - if ( pAd->BulkInMaxPacketSize == 64) + if (pAd->BulkInMaxPacketSize == 64) RX_bulk_size = 4096; else RX_bulk_size = MAX_RXBULK_SIZE; - //Initialize a rx bulk urb + /*Initialize a rx bulk urb */ RTUSB_FILL_BULK_URB(pUrb, - pObj->pUsb_Dev, - usb_rcvbulkpipe(pObj->pUsb_Dev, pAd->BulkInEpAddr), - &(pRxContext->TransferBuffer[pAd->NextRxBulkInPosition]), - RX_bulk_size - (pAd->NextRxBulkInPosition), - (usb_complete_t)RTUSBBulkRxComplete, - (void *)pRxContext); - - pUrb->transfer_dma = pRxContext->data_dma + pAd->NextRxBulkInPosition; + pObj->pUsb_Dev, + usb_rcvbulkpipe(pObj->pUsb_Dev, pAd->BulkInEpAddr), + &(pRxContext-> + TransferBuffer[pAd->NextRxBulkInPosition]), + RX_bulk_size - (pAd->NextRxBulkInPosition), + (usb_complete_t) RTUSBBulkRxComplete, + (void *)pRxContext); + + pUrb->transfer_dma = pRxContext->data_dma + pAd->NextRxBulkInPosition; pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - } /* @@ -188,177 +179,215 @@ VOID RTUSBInitRxDesc( if(1 /*!(in_interrupt() & 0xffff0000)*/) \ RTMP_IRQ_UNLOCK((pLock), IrqFlags); - -VOID RTUSBBulkOutDataPacket( - IN PRTMP_ADAPTER pAd, - IN UCHAR BulkOutPipeId, - IN UCHAR Index) +void RTUSBBulkOutDataPacket(struct rt_rtmp_adapter *pAd, + u8 BulkOutPipeId, u8 Index) { - PHT_TX_CONTEXT pHTTXContext; - PURB pUrb; - int ret = 0; - PTXINFO_STRUC pTxInfo, pLastTxInfo = NULL; - PTXWI_STRUC pTxWI; - ULONG TmpBulkEndPos, ThisBulkSize; - unsigned long IrqFlags = 0, IrqFlags2 = 0; - PUCHAR pWirelessPkt, pAppendant; - BOOLEAN bTxQLastRound = FALSE; - UCHAR allzero[4]= {0x0,0x0,0x0,0x0}; + struct rt_ht_tx_context *pHTTXContext; + PURB pUrb; + int ret = 0; + struct rt_txinfo *pTxInfo, *pLastTxInfo = NULL; + struct rt_txwi * pTxWI; + unsigned long TmpBulkEndPos, ThisBulkSize; + unsigned long IrqFlags = 0, IrqFlags2 = 0; + u8 *pWirelessPkt, *pAppendant; + BOOLEAN bTxQLastRound = FALSE; + u8 allzero[4] = { 0x0, 0x0, 0x0, 0x0 }; BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); - if ((pAd->BulkOutPending[BulkOutPipeId] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) - { + if ((pAd->BulkOutPending[BulkOutPipeId] == TRUE) + || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) { BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); return; } pAd->BulkOutPending[BulkOutPipeId] = TRUE; if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) - ) - { + ) { pAd->BulkOutPending[BulkOutPipeId] = FALSE; BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); return; } BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); - pHTTXContext = &(pAd->TxContext[BulkOutPipeId]); BULK_OUT_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2); - if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) - || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition)) - { - BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2); + if ((pHTTXContext->ENextBulkOutPosition == + pHTTXContext->CurWritePosition) + || ((pHTTXContext->ENextBulkOutPosition - 8) == + pHTTXContext->CurWritePosition)) { + BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], + IrqFlags2); BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->BulkOutPending[BulkOutPipeId] = FALSE; - // Clear Data flag - RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId)); - RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); + /* Clear Data flag */ + RTUSB_CLEAR_BULK_FLAG(pAd, + (fRTUSB_BULK_OUT_DATA_FRAG << + BulkOutPipeId)); + RTUSB_CLEAR_BULK_FLAG(pAd, + (fRTUSB_BULK_OUT_DATA_NORMAL << + BulkOutPipeId)); BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); return; } - - // Clear Data flag - RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId)); - RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); - - //DBGPRINT(RT_DEBUG_TRACE,("BulkOut-B:I=0x%lx, CWPos=%ld, CWRPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", in_interrupt(), - // pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->NextBulkOutPosition, - // pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); + /* Clear Data flag */ + RTUSB_CLEAR_BULK_FLAG(pAd, + (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId)); + RTUSB_CLEAR_BULK_FLAG(pAd, + (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); + + /*DBGPRINT(RT_DEBUG_TRACE,("BulkOut-B:I=0x%lx, CWPos=%ld, CWRPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", in_interrupt(), */ + /* pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->NextBulkOutPosition, */ + /* pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); */ pHTTXContext->NextBulkOutPosition = pHTTXContext->ENextBulkOutPosition; ThisBulkSize = 0; TmpBulkEndPos = pHTTXContext->NextBulkOutPosition; pWirelessPkt = &pHTTXContext->TransferBuffer->field.WirelessPacket[0]; - if ((pHTTXContext->bCopySavePad == TRUE)) - { - if (RTMPEqualMemory(pHTTXContext->SavedPad, allzero,4)) - { - DBGPRINT_RAW(RT_DEBUG_ERROR,("e1, allzero : %x %x %x %x %x %x %x %x \n", - pHTTXContext->SavedPad[0], pHTTXContext->SavedPad[1], pHTTXContext->SavedPad[2],pHTTXContext->SavedPad[3] - ,pHTTXContext->SavedPad[4], pHTTXContext->SavedPad[5], pHTTXContext->SavedPad[6],pHTTXContext->SavedPad[7])); + if ((pHTTXContext->bCopySavePad == TRUE)) { + if (RTMPEqualMemory(pHTTXContext->SavedPad, allzero, 4)) { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("e1, allzero : %x %x %x %x %x %x %x %x \n", + pHTTXContext->SavedPad[0], + pHTTXContext->SavedPad[1], + pHTTXContext->SavedPad[2], + pHTTXContext->SavedPad[3] + , pHTTXContext->SavedPad[4], + pHTTXContext->SavedPad[5], + pHTTXContext->SavedPad[6], + pHTTXContext->SavedPad[7])); } - NdisMoveMemory(&pWirelessPkt[TmpBulkEndPos], pHTTXContext->SavedPad, 8); + NdisMoveMemory(&pWirelessPkt[TmpBulkEndPos], + pHTTXContext->SavedPad, 8); pHTTXContext->bCopySavePad = FALSE; if (pAd->bForcePrintTX == TRUE) - DBGPRINT(RT_DEBUG_TRACE,("RTUSBBulkOutDataPacket --> COPY PAD. CurWrite = %ld, NextBulk = %ld. ENextBulk = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition)); + DBGPRINT(RT_DEBUG_TRACE, + ("RTUSBBulkOutDataPacket --> COPY PAD. CurWrite = %ld, NextBulk = %ld. ENextBulk = %ld.\n", + pHTTXContext->CurWritePosition, + pHTTXContext->NextBulkOutPosition, + pHTTXContext->ENextBulkOutPosition)); } - do - { - pTxInfo = (PTXINFO_STRUC)&pWirelessPkt[TmpBulkEndPos]; - pTxWI = (PTXWI_STRUC)&pWirelessPkt[TmpBulkEndPos + TXINFO_SIZE]; + do { + pTxInfo = (struct rt_txinfo *)& pWirelessPkt[TmpBulkEndPos]; + pTxWI = + (struct rt_txwi *) & pWirelessPkt[TmpBulkEndPos + TXINFO_SIZE]; if (pAd->bForcePrintTX == TRUE) - DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBulkOutDataPacket AMPDU = %d.\n", pTxWI->AMPDU)); - - // add by Iverson, limit BulkOut size to 4k to pass WMM b mode 2T1R test items - //if ((ThisBulkSize != 0) && (pTxWI->AMPDU == 0)) - if ((ThisBulkSize != 0) && (pTxWI->PHYMODE == MODE_CCK)) - { - if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x1000) == 0x1000)) - { - // Limit BulkOut size to about 4k bytes. - pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + DBGPRINT(RT_DEBUG_TRACE, + ("RTUSBBulkOutDataPacket AMPDU = %d.\n", + pTxWI->AMPDU)); + + /* add by Iverson, limit BulkOut size to 4k to pass WMM b mode 2T1R test items */ + /*if ((ThisBulkSize != 0) && (pTxWI->AMPDU == 0)) */ + if ((ThisBulkSize != 0) && (pTxWI->PHYMODE == MODE_CCK)) { + if (((ThisBulkSize & 0xffff8000) != 0) + || ((ThisBulkSize & 0x1000) == 0x1000)) { + /* Limit BulkOut size to about 4k bytes. */ + pHTTXContext->ENextBulkOutPosition = + TmpBulkEndPos; break; - } - else if (((pAd->BulkOutMaxPacketSize < 512) && ((ThisBulkSize&0xfffff800) != 0) ) /*|| ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0))*/) - { - // For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size. - // For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04. - pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + } else + if (((pAd->BulkOutMaxPacketSize < 512) + && ((ThisBulkSize & 0xfffff800) != + 0)) + /*|| ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0)) */ + ) { + /* For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size. */ + /* For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04. */ + pHTTXContext->ENextBulkOutPosition = + TmpBulkEndPos; break; } } - // end Iverson - else - { - if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x6000) == 0x6000)) - { // Limit BulkOut size to about 24k bytes. - pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + /* end Iverson */ + else { + if (((ThisBulkSize & 0xffff8000) != 0) || ((ThisBulkSize & 0x6000) == 0x6000)) { /* Limit BulkOut size to about 24k bytes. */ + pHTTXContext->ENextBulkOutPosition = + TmpBulkEndPos; break; - } - else if (((pAd->BulkOutMaxPacketSize < 512) && ((ThisBulkSize&0xfffff800) != 0) ) /*|| ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0))*/) - { // For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size. - // For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04. - pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + } else if (((pAd->BulkOutMaxPacketSize < 512) && ((ThisBulkSize & 0xfffff800) != 0)) /*|| ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0)) */ ) { /* For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size. */ + /* For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04. */ + pHTTXContext->ENextBulkOutPosition = + TmpBulkEndPos; break; } } - if (TmpBulkEndPos == pHTTXContext->CurWritePosition) - { + if (TmpBulkEndPos == pHTTXContext->CurWritePosition) { pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; break; } - //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) - if (pTxInfo->QSEL != FIFO_EDCA) - { - printk("%s(): ====> pTxInfo->QueueSel(%d)!= FIFO_EDCA!!!!\n", __func__, pTxInfo->QSEL); - printk("\tCWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad); - hex_dump("Wrong QSel Pkt:", (PUCHAR)&pWirelessPkt[TmpBulkEndPos], (pHTTXContext->CurWritePosition - pHTTXContext->NextBulkOutPosition)); + if (pTxInfo->QSEL != FIFO_EDCA) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): ====> pTxInfo->QueueSel(%d)!= FIFO_EDCA!!!!\n", + __FUNCTION__, pTxInfo->QSEL)); + DBGPRINT(RT_DEBUG_ERROR, + ("\tCWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", + pHTTXContext->CurWritePosition, + pHTTXContext->NextBulkOutPosition, + pHTTXContext->ENextBulkOutPosition, + pHTTXContext->bCopySavePad)); + hex_dump("Wrong QSel Pkt:", + (u8 *)& pWirelessPkt[TmpBulkEndPos], + (pHTTXContext->CurWritePosition - + pHTTXContext->NextBulkOutPosition)); } - if (pTxInfo->USBDMATxPktLen <= 8) - { - BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2); - DBGPRINT(RT_DEBUG_ERROR /*RT_DEBUG_TRACE*/,("e2, USBDMATxPktLen==0, Size=%ld, bCSPad=%d, CWPos=%ld, NBPos=%ld, CWRPos=%ld!\n", - pHTTXContext->BulkOutSize, pHTTXContext->bCopySavePad, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->CurWriteRealPos)); + if (pTxInfo->USBDMATxPktLen <= 8) { + BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], + IrqFlags2); + DBGPRINT(RT_DEBUG_ERROR /*RT_DEBUG_TRACE */ , + ("e2, USBDMATxPktLen==0, Size=%ld, bCSPad=%d, CWPos=%ld, NBPos=%ld, CWRPos=%ld!\n", + pHTTXContext->BulkOutSize, + pHTTXContext->bCopySavePad, + pHTTXContext->CurWritePosition, + pHTTXContext->NextBulkOutPosition, + pHTTXContext->CurWriteRealPos)); { - DBGPRINT_RAW(RT_DEBUG_ERROR /*RT_DEBUG_TRACE*/,("%x %x %x %x %x %x %x %x \n", - pHTTXContext->SavedPad[0], pHTTXContext->SavedPad[1], pHTTXContext->SavedPad[2],pHTTXContext->SavedPad[3] - ,pHTTXContext->SavedPad[4], pHTTXContext->SavedPad[5], pHTTXContext->SavedPad[6],pHTTXContext->SavedPad[7])); + DBGPRINT_RAW(RT_DEBUG_ERROR /*RT_DEBUG_TRACE */ + , + ("%x %x %x %x %x %x %x %x \n", + pHTTXContext->SavedPad[0], + pHTTXContext->SavedPad[1], + pHTTXContext->SavedPad[2], + pHTTXContext->SavedPad[3] + , pHTTXContext->SavedPad[4], + pHTTXContext->SavedPad[5], + pHTTXContext->SavedPad[6], + pHTTXContext->SavedPad[7])); } pAd->bForcePrintTX = TRUE; - BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], + IrqFlags); pAd->BulkOutPending[BulkOutPipeId] = FALSE; - BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); - //DBGPRINT(RT_DEBUG_LOUD,("Out:pTxInfo->USBDMATxPktLen=%d!\n", pTxInfo->USBDMATxPktLen)); + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], + IrqFlags); + /*DBGPRINT(RT_DEBUG_LOUD,("Out:pTxInfo->USBDMATxPktLen=%d!\n", pTxInfo->USBDMATxPktLen)); */ return; } - - // Increase Total transmit byte counter - pAd->RalinkCounters.OneSecTransmittedByteCount += pTxWI->MPDUtotalByteCount; - pAd->RalinkCounters.TransmittedByteCount += pTxWI->MPDUtotalByteCount; + /* Increase Total transmit byte counter */ + pAd->RalinkCounters.OneSecTransmittedByteCount += + pTxWI->MPDUtotalByteCount; + pAd->RalinkCounters.TransmittedByteCount += + pTxWI->MPDUtotalByteCount; pLastTxInfo = pTxInfo; - // Make sure we use EDCA QUEUE. - pTxInfo->QSEL = FIFO_EDCA; //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) - ThisBulkSize += (pTxInfo->USBDMATxPktLen+4); - TmpBulkEndPos += (pTxInfo->USBDMATxPktLen+4); + /* Make sure we use EDCA QUEUE. */ + pTxInfo->QSEL = FIFO_EDCA; + ThisBulkSize += (pTxInfo->USBDMATxPktLen + 4); + TmpBulkEndPos += (pTxInfo->USBDMATxPktLen + 4); if (TmpBulkEndPos != pHTTXContext->CurWritePosition) pTxInfo->USBDMANextVLD = 1; - if (pTxInfo->SwUseLastRound == 1) - { + if (pTxInfo->SwUseLastRound == 1) { if (pHTTXContext->CurWritePosition == 8) pTxInfo->USBDMANextVLD = 0; pTxInfo->SwUseLastRound = 0; @@ -368,68 +397,88 @@ VOID RTUSBBulkOutDataPacket( break; } - }while (TRUE); - // adjust the pTxInfo->USBDMANextVLD value of last pTxInfo. - if (pLastTxInfo) - { + } while (TRUE); + + /* adjust the pTxInfo->USBDMANextVLD value of last pTxInfo. */ + if (pLastTxInfo) { pLastTxInfo->USBDMANextVLD = 0; } /* - We need to copy SavedPad when following condition matched! - 1. Not the last round of the TxQueue and - 2. any match of following cases: - (1). The End Position of this bulk out is reach to the Currenct Write position and - the TxInfo and related header already write to the CurWritePosition. - =>(ENextBulkOutPosition == CurWritePosition) && (CurWriteRealPos > CurWritePosition) - - (2). The EndPosition of the bulk out is not reach to the Current Write Position. - =>(ENextBulkOutPosition != CurWritePosition) - */ + We need to copy SavedPad when following condition matched! + 1. Not the last round of the TxQueue and + 2. any match of following cases: + (1). The End Position of this bulk out is reach to the Currenct Write position and + the TxInfo and related header already write to the CurWritePosition. + =>(ENextBulkOutPosition == CurWritePosition) && (CurWriteRealPos > CurWritePosition) + + (2). The EndPosition of the bulk out is not reach to the Current Write Position. + =>(ENextBulkOutPosition != CurWritePosition) + */ if ((bTxQLastRound == FALSE) && - (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) && (pHTTXContext->CurWriteRealPos > pHTTXContext->CurWritePosition)) || - (pHTTXContext->ENextBulkOutPosition != pHTTXContext->CurWritePosition)) - ) - { - NdisMoveMemory(pHTTXContext->SavedPad, &pWirelessPkt[pHTTXContext->ENextBulkOutPosition], 8); + (((pHTTXContext->ENextBulkOutPosition == + pHTTXContext->CurWritePosition) + && (pHTTXContext->CurWriteRealPos > + pHTTXContext->CurWritePosition)) + || (pHTTXContext->ENextBulkOutPosition != + pHTTXContext->CurWritePosition)) + ) { + NdisMoveMemory(pHTTXContext->SavedPad, + &pWirelessPkt[pHTTXContext-> + ENextBulkOutPosition], 8); pHTTXContext->bCopySavePad = TRUE; - if (RTMPEqualMemory(pHTTXContext->SavedPad, allzero,4)) - { - PUCHAR pBuf = &pHTTXContext->SavedPad[0]; - DBGPRINT_RAW(RT_DEBUG_ERROR,("WARNING-Zero-3:%02x%02x%02x%02x%02x%02x%02x%02x,CWPos=%ld, CWRPos=%ld, bCW=%d, NBPos=%ld, TBPos=%ld, TBSize=%ld\n", - pBuf[0], pBuf[1], pBuf[2],pBuf[3],pBuf[4], pBuf[5], pBuf[6],pBuf[7], pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, - pHTTXContext->bCurWriting, pHTTXContext->NextBulkOutPosition, TmpBulkEndPos, ThisBulkSize)); + if (RTMPEqualMemory(pHTTXContext->SavedPad, allzero, 4)) { + u8 *pBuf = &pHTTXContext->SavedPad[0]; + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("WARNING-Zero-3:%02x%02x%02x%02x%02x%02x%02x%02x,CWPos=%ld, CWRPos=%ld, bCW=%d, NBPos=%ld, TBPos=%ld, TBSize=%ld\n", + pBuf[0], pBuf[1], pBuf[2], pBuf[3], + pBuf[4], pBuf[5], pBuf[6], pBuf[7], + pHTTXContext->CurWritePosition, + pHTTXContext->CurWriteRealPos, + pHTTXContext->bCurWriting, + pHTTXContext->NextBulkOutPosition, + TmpBulkEndPos, ThisBulkSize)); pBuf = &pWirelessPkt[pHTTXContext->CurWritePosition]; - DBGPRINT_RAW(RT_DEBUG_ERROR,("\tCWPos=%02x%02x%02x%02x%02x%02x%02x%02x\n", pBuf[0], pBuf[1], pBuf[2],pBuf[3],pBuf[4], pBuf[5], pBuf[6],pBuf[7])); + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("\tCWPos=%02x%02x%02x%02x%02x%02x%02x%02x\n", + pBuf[0], pBuf[1], pBuf[2], pBuf[3], + pBuf[4], pBuf[5], pBuf[6], pBuf[7])); } - //DBGPRINT(RT_DEBUG_LOUD,("ENPos==CWPos=%ld, CWRPos=%ld, bCSPad=%d!\n", pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->bCopySavePad)); + /*DBGPRINT(RT_DEBUG_LOUD,("ENPos==CWPos=%ld, CWRPos=%ld, bCSPad=%d!\n", pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->bCopySavePad)); */ } if (pAd->bForcePrintTX == TRUE) - DBGPRINT(RT_DEBUG_TRACE,("BulkOut-A:Size=%ld, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", ThisBulkSize, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); - //DBGPRINT(RT_DEBUG_LOUD,("BulkOut-A:Size=%ld, CWPos=%ld, CWRPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, bLRound=%d!\n", ThisBulkSize, pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad, bTxQLastRound)); - - // USB DMA engine requires to pad extra 4 bytes. This pad doesn't count into real bulkoutsize. + DBGPRINT(RT_DEBUG_TRACE, + ("BulkOut-A:Size=%ld, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", + ThisBulkSize, pHTTXContext->CurWritePosition, + pHTTXContext->NextBulkOutPosition, + pHTTXContext->ENextBulkOutPosition, + pHTTXContext->bCopySavePad)); + /*DBGPRINT(RT_DEBUG_LOUD,("BulkOut-A:Size=%ld, CWPos=%ld, CWRPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, bLRound=%d!\n", ThisBulkSize, pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad, bTxQLastRound)); */ + + /* USB DMA engine requires to pad extra 4 bytes. This pad doesn't count into real bulkoutsize. */ pAppendant = &pWirelessPkt[TmpBulkEndPos]; NdisZeroMemory(pAppendant, 8); + ThisBulkSize += 4; + pHTTXContext->LastOne = TRUE; + if ((ThisBulkSize % pAd->BulkOutMaxPacketSize) == 0) ThisBulkSize += 4; - pHTTXContext->LastOne = TRUE; - if ((ThisBulkSize % pAd->BulkOutMaxPacketSize) == 0) - ThisBulkSize += 4; pHTTXContext->BulkOutSize = ThisBulkSize; pAd->watchDogTxPendingCnt[BulkOutPipeId] = 1; BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2); - // Init Tx context descriptor - RTUSBInitHTTxDesc(pAd, pHTTXContext, BulkOutPipeId, ThisBulkSize, (usb_complete_t)RTUSBBulkOutDataPacketComplete); + /* Init Tx context descriptor */ + RTUSBInitHTTxDesc(pAd, pHTTXContext, BulkOutPipeId, ThisBulkSize, + (usb_complete_t) RTUSBBulkOutDataPacketComplete); pUrb = pHTTXContext->pUrb; - if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) - { - DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutDataPacket: Submit Tx URB failed %d\n", ret)); + if ((ret = RTUSB_SUBMIT_URB(pUrb)) != 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("RTUSBBulkOutDataPacket: Submit Tx URB failed %d\n", + ret)); BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->BulkOutPending[BulkOutPipeId] = FALSE; @@ -446,48 +495,41 @@ VOID RTUSBBulkOutDataPacket( } - -VOID RTUSBBulkOutDataPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs) +void RTUSBBulkOutDataPacketComplete(struct urb *pUrb, struct pt_regs * pt_regs) { - PHT_TX_CONTEXT pHTTXContext; - PRTMP_ADAPTER pAd; - POS_COOKIE pObj; - UCHAR BulkOutPipeId; + struct rt_ht_tx_context *pHTTXContext; + struct rt_rtmp_adapter *pAd; + struct os_cookie *pObj; + u8 BulkOutPipeId; + pHTTXContext = (struct rt_ht_tx_context *)pUrb->context; + pAd = pHTTXContext->pAd; + pObj = (struct os_cookie *)pAd->OS_Cookie; - pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; - pAd = pHTTXContext->pAd; - pObj = (POS_COOKIE) pAd->OS_Cookie; - - // Store BulkOut PipeId - BulkOutPipeId = pHTTXContext->BulkOutPipeId; + /* Store BulkOut PipeId */ + BulkOutPipeId = pHTTXContext->BulkOutPipeId; pAd->BulkOutDataOneSecCount++; - switch (BulkOutPipeId) - { - case 0: - pObj->ac0_dma_done_task.data = (unsigned long)pUrb; - tasklet_hi_schedule(&pObj->ac0_dma_done_task); - break; - case 1: - pObj->ac1_dma_done_task.data = (unsigned long)pUrb; - tasklet_hi_schedule(&pObj->ac1_dma_done_task); - break; - case 2: - pObj->ac2_dma_done_task.data = (unsigned long)pUrb; - tasklet_hi_schedule(&pObj->ac2_dma_done_task); - break; - case 3: - pObj->ac3_dma_done_task.data = (unsigned long)pUrb; - tasklet_hi_schedule(&pObj->ac3_dma_done_task); - break; - case 4: - pObj->hcca_dma_done_task.data = (unsigned long)pUrb; - tasklet_hi_schedule(&pObj->hcca_dma_done_task); - break; + switch (BulkOutPipeId) { + case 0: + pObj->ac0_dma_done_task.data = (unsigned long)pUrb; + tasklet_hi_schedule(&pObj->ac0_dma_done_task); + break; + case 1: + pObj->ac1_dma_done_task.data = (unsigned long)pUrb; + tasklet_hi_schedule(&pObj->ac1_dma_done_task); + break; + case 2: + pObj->ac2_dma_done_task.data = (unsigned long)pUrb; + tasklet_hi_schedule(&pObj->ac2_dma_done_task); + break; + case 3: + pObj->ac3_dma_done_task.data = (unsigned long)pUrb; + tasklet_hi_schedule(&pObj->ac3_dma_done_task); + break; } -} +} /* ======================================================================== @@ -502,17 +544,16 @@ VOID RTUSBBulkOutDataPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs) ======================================================================== */ -VOID RTUSBBulkOutNullFrame( - IN PRTMP_ADAPTER pAd) +void RTUSBBulkOutNullFrame(struct rt_rtmp_adapter *pAd) { - PTX_CONTEXT pNullContext = &(pAd->NullContext); - PURB pUrb; - int ret = 0; - unsigned long IrqFlags; + struct rt_tx_context *pNullContext = &(pAd->NullContext); + PURB pUrb; + int ret = 0; + unsigned long IrqFlags; RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); - if ((pAd->BulkOutPending[0] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) - { + if ((pAd->BulkOutPending[0] == TRUE) + || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); return; } @@ -521,45 +562,45 @@ VOID RTUSBBulkOutNullFrame( pNullContext->IRPPending = TRUE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); - // Increase Total transmit byte counter - pAd->RalinkCounters.TransmittedByteCount += pNullContext->BulkOutSize; + /* Increase Total transmit byte counter */ + pAd->RalinkCounters.TransmittedByteCount += pNullContext->BulkOutSize; - - // Clear Null frame bulk flag + /* Clear Null frame bulk flag */ RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL); - // Init Tx context descriptor - RTUSBInitTxDesc(pAd, pNullContext, 0, (usb_complete_t)RTUSBBulkOutNullFrameComplete); + /* Init Tx context descriptor */ + RTUSBInitTxDesc(pAd, pNullContext, 0, + (usb_complete_t) RTUSBBulkOutNullFrameComplete); pUrb = pNullContext->pUrb; - if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) - { + if ((ret = RTUSB_SUBMIT_URB(pUrb)) != 0) { RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); pAd->BulkOutPending[0] = FALSE; pAd->watchDogTxPendingCnt[0] = 0; pNullContext->IRPPending = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); - DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutNullFrame: Submit Tx URB failed %d\n", ret)); + DBGPRINT(RT_DEBUG_ERROR, + ("RTUSBBulkOutNullFrame: Submit Tx URB failed %d\n", + ret)); return; } } -// NULL frame use BulkOutPipeId = 0 -VOID RTUSBBulkOutNullFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs) +/* NULL frame use BulkOutPipeId = 0 */ +void RTUSBBulkOutNullFrameComplete(struct urb *pUrb, struct pt_regs * pt_regs) { - PRTMP_ADAPTER pAd; - PTX_CONTEXT pNullContext; - NTSTATUS Status; - POS_COOKIE pObj; - + struct rt_rtmp_adapter *pAd; + struct rt_tx_context *pNullContext; + int Status; + struct os_cookie *pObj; - pNullContext = (PTX_CONTEXT)pUrb->context; - pAd = pNullContext->pAd; - Status = pUrb->status; + pNullContext = (struct rt_tx_context *)pUrb->context; + pAd = pNullContext->pAd; + Status = pUrb->status; - pObj = (POS_COOKIE) pAd->OS_Cookie; + pObj = (struct os_cookie *)pAd->OS_Cookie; pObj->null_frame_complete_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->null_frame_complete_task); } @@ -577,34 +618,30 @@ VOID RTUSBBulkOutNullFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs) ======================================================================== */ -VOID RTUSBBulkOutMLMEPacket( - IN PRTMP_ADAPTER pAd, - IN UCHAR Index) +void RTUSBBulkOutMLMEPacket(struct rt_rtmp_adapter *pAd, u8 Index) { - PTX_CONTEXT pMLMEContext; - PURB pUrb; - int ret = 0; - unsigned long IrqFlags; + struct rt_tx_context *pMLMEContext; + PURB pUrb; + int ret = 0; + unsigned long IrqFlags; - pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa; + pMLMEContext = + (struct rt_tx_context *)pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa; pUrb = pMLMEContext->pUrb; if ((pAd->MgmtRing.TxSwFreeIdx >= MGMT_RING_SIZE) || - (pMLMEContext->InUse == FALSE) || - (pMLMEContext->bWaitingBulkOut == FALSE)) - { - + (pMLMEContext->InUse == FALSE) || + (pMLMEContext->bWaitingBulkOut == FALSE)) { - // Clear MLME bulk flag + /* Clear MLME bulk flag */ RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); return; } - RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); - if ((pAd->BulkOutPending[MGMTPIPEIDX] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) - { + if ((pAd->BulkOutPending[MGMTPIPEIDX] == TRUE) + || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); return; } @@ -615,23 +652,25 @@ VOID RTUSBBulkOutMLMEPacket( pMLMEContext->bWaitingBulkOut = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); - // Increase Total transmit byte counter - pAd->RalinkCounters.TransmittedByteCount += pMLMEContext->BulkOutSize; + /* Increase Total transmit byte counter */ + pAd->RalinkCounters.TransmittedByteCount += pMLMEContext->BulkOutSize; - // Clear MLME bulk flag + /* Clear MLME bulk flag */ RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); - // Init Tx context descriptor - RTUSBInitTxDesc(pAd, pMLMEContext, MGMTPIPEIDX, (usb_complete_t)RTUSBBulkOutMLMEPacketComplete); + /* Init Tx context descriptor */ + RTUSBInitTxDesc(pAd, pMLMEContext, MGMTPIPEIDX, + (usb_complete_t) RTUSBBulkOutMLMEPacketComplete); - //For mgmt urb buffer, because we use sk_buff, so we need to notify the USB controller do dma mapping. - pUrb->transfer_dma = 0; + /*For mgmt urb buffer, because we use sk_buff, so we need to notify the USB controller do dma mapping. */ + pUrb->transfer_dma = 0; pUrb->transfer_flags &= (~URB_NO_TRANSFER_DMA_MAP); pUrb = pMLMEContext->pUrb; - if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) - { - DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutMLMEPacket: Submit MLME URB failed %d\n", ret)); + if ((ret = RTUSB_SUBMIT_URB(pUrb)) != 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("RTUSBBulkOutMLMEPacket: Submit MLME URB failed %d\n", + ret)); RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); pAd->BulkOutPending[MGMTPIPEIDX] = FALSE; pAd->watchDogTxPendingCnt[MGMTPIPEIDX] = 0; @@ -641,32 +680,29 @@ VOID RTUSBBulkOutMLMEPacket( return; } - - //DBGPRINT_RAW(RT_DEBUG_INFO, ("<---RTUSBBulkOutMLMEPacket \n")); -// printk("<---RTUSBBulkOutMLMEPacket,Cpu=%d!, Dma=%d, SwIdx=%d!\n", pAd->MgmtRing.TxCpuIdx, pAd->MgmtRing.TxDmaIdx, pAd->MgmtRing.TxSwFreeIdx); + /*DBGPRINT_RAW(RT_DEBUG_INFO, ("<---RTUSBBulkOutMLMEPacket \n")); */ +/* printk("<---RTUSBBulkOutMLMEPacket,Cpu=%d!, Dma=%d, SwIdx=%d!\n", pAd->MgmtRing.TxCpuIdx, pAd->MgmtRing.TxDmaIdx, pAd->MgmtRing.TxSwFreeIdx); */ } - -VOID RTUSBBulkOutMLMEPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs) +void RTUSBBulkOutMLMEPacketComplete(struct urb *pUrb, struct pt_regs * pt_regs) { - PTX_CONTEXT pMLMEContext; - PRTMP_ADAPTER pAd; - NTSTATUS Status; - POS_COOKIE pObj; - int index; - - //DBGPRINT_RAW(RT_DEBUG_INFO, ("--->RTUSBBulkOutMLMEPacketComplete\n")); - pMLMEContext = (PTX_CONTEXT)pUrb->context; - pAd = pMLMEContext->pAd; - pObj = (POS_COOKIE)pAd->OS_Cookie; - Status = pUrb->status; - index = pMLMEContext->SelfIdx; + struct rt_tx_context *pMLMEContext; + struct rt_rtmp_adapter *pAd; + int Status; + struct os_cookie *pObj; + int index; + + /*DBGPRINT_RAW(RT_DEBUG_INFO, ("--->RTUSBBulkOutMLMEPacketComplete\n")); */ + pMLMEContext = (struct rt_tx_context *)pUrb->context; + pAd = pMLMEContext->pAd; + pObj = (struct os_cookie *)pAd->OS_Cookie; + Status = pUrb->status; + index = pMLMEContext->SelfIdx; pObj->mgmt_dma_done_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->mgmt_dma_done_task); } - /* ======================================================================== @@ -680,17 +716,16 @@ VOID RTUSBBulkOutMLMEPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs) ======================================================================== */ -VOID RTUSBBulkOutPsPoll( - IN PRTMP_ADAPTER pAd) +void RTUSBBulkOutPsPoll(struct rt_rtmp_adapter *pAd) { - PTX_CONTEXT pPsPollContext = &(pAd->PsPollContext); - PURB pUrb; - int ret = 0; - unsigned long IrqFlags; + struct rt_tx_context *pPsPollContext = &(pAd->PsPollContext); + PURB pUrb; + int ret = 0; + unsigned long IrqFlags; RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); - if ((pAd->BulkOutPending[0] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) - { + if ((pAd->BulkOutPending[0] == TRUE) + || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); return; } @@ -699,57 +734,57 @@ VOID RTUSBBulkOutPsPoll( pPsPollContext->IRPPending = TRUE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); - - // Clear PS-Poll bulk flag + /* Clear PS-Poll bulk flag */ RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL); - // Init Tx context descriptor - RTUSBInitTxDesc(pAd, pPsPollContext, MGMTPIPEIDX, (usb_complete_t)RTUSBBulkOutPsPollComplete); + /* Init Tx context descriptor */ + RTUSBInitTxDesc(pAd, pPsPollContext, MGMTPIPEIDX, + (usb_complete_t) RTUSBBulkOutPsPollComplete); pUrb = pPsPollContext->pUrb; - if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) - { + if ((ret = RTUSB_SUBMIT_URB(pUrb)) != 0) { RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); pAd->BulkOutPending[0] = FALSE; pAd->watchDogTxPendingCnt[0] = 0; pPsPollContext->IRPPending = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); - DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutPsPoll: Submit Tx URB failed %d\n", ret)); + DBGPRINT(RT_DEBUG_ERROR, + ("RTUSBBulkOutPsPoll: Submit Tx URB failed %d\n", + ret)); return; } } -// PS-Poll frame use BulkOutPipeId = 0 -VOID RTUSBBulkOutPsPollComplete(purbb_t pUrb,struct pt_regs *pt_regs) +/* PS-Poll frame use BulkOutPipeId = 0 */ +void RTUSBBulkOutPsPollComplete(struct urb *pUrb, struct pt_regs * pt_regs) { - PRTMP_ADAPTER pAd; - PTX_CONTEXT pPsPollContext; - NTSTATUS Status; - POS_COOKIE pObj; - + struct rt_rtmp_adapter *pAd; + struct rt_tx_context *pPsPollContext; + int Status; + struct os_cookie *pObj; - pPsPollContext= (PTX_CONTEXT)pUrb->context; + pPsPollContext = (struct rt_tx_context *)pUrb->context; pAd = pPsPollContext->pAd; Status = pUrb->status; - pObj = (POS_COOKIE) pAd->OS_Cookie; + pObj = (struct os_cookie *)pAd->OS_Cookie; pObj->pspoll_frame_complete_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->pspoll_frame_complete_task); } -VOID DoBulkIn(IN RTMP_ADAPTER *pAd) +void DoBulkIn(struct rt_rtmp_adapter *pAd) { - PRX_CONTEXT pRxContext; - PURB pUrb; - int ret = 0; - unsigned long IrqFlags; + struct rt_rx_context *pRxContext; + PURB pUrb; + int ret = 0; + unsigned long IrqFlags; RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]); - if ((pAd->PendingRx > 0) || (pRxContext->Readable == TRUE) || (pRxContext->InUse == TRUE)) - { + if ((pAd->PendingRx > 0) || (pRxContext->Readable == TRUE) + || (pRxContext->InUse == TRUE)) { RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); return; } @@ -759,13 +794,12 @@ VOID DoBulkIn(IN RTMP_ADAPTER *pAd) pAd->BulkInReq++; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); - // Init Rx context descriptor + /* Init Rx context descriptor */ NdisZeroMemory(pRxContext->TransferBuffer, pRxContext->BulkInOffset); RTUSBInitRxDesc(pAd, pRxContext); pUrb = pRxContext->pUrb; - if ((ret = RTUSB_SUBMIT_URB(pUrb))!=0) - { // fail + if ((ret = RTUSB_SUBMIT_URB(pUrb)) != 0) { /* fail */ RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext->InUse = FALSE; @@ -773,16 +807,14 @@ VOID DoBulkIn(IN RTMP_ADAPTER *pAd) pAd->PendingRx--; pAd->BulkInReq--; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); - DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkReceive: Submit Rx URB failed %d\n", ret)); - } - else - { // success + DBGPRINT(RT_DEBUG_ERROR, + ("RTUSBBulkReceive: Submit Rx URB failed %d\n", ret)); + } else { /* success */ ASSERT((pRxContext->InUse == pRxContext->IRPPending)); - //printk("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex); + /*printk("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex); */ } } - /* ======================================================================== @@ -813,44 +845,40 @@ VOID DoBulkIn(IN RTMP_ADAPTER *pAd) fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_RESET_IN_PROGRESS | \ fRTMP_ADAPTER_REMOVE_IN_PROGRESS) -VOID RTUSBBulkReceive( - IN PRTMP_ADAPTER pAd) +void RTUSBBulkReceive(struct rt_rtmp_adapter *pAd) { - PRX_CONTEXT pRxContext; - unsigned long IrqFlags; - + struct rt_rx_context *pRxContext; + unsigned long IrqFlags; /* sanity check */ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_HANDLE_RX)) return; - while(1) - { + while (1) { RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext = &(pAd->RxContext[pAd->NextRxBulkInReadIndex]); - if (((pRxContext->InUse == FALSE) && (pRxContext->Readable == TRUE)) && - (pRxContext->bRxHandling == FALSE)) - { + if (((pRxContext->InUse == FALSE) + && (pRxContext->Readable == TRUE)) + && (pRxContext->bRxHandling == FALSE)) { pRxContext->bRxHandling = TRUE; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); - // read RxContext, Since not + /* read RxContext, Since not */ STARxDoneInterruptHandle(pAd, TRUE); - // Finish to handle this bulkIn buffer. + /* Finish to handle this bulkIn buffer. */ RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext->BulkInOffset = 0; pRxContext->Readable = FALSE; pRxContext->bRxHandling = FALSE; pAd->ReadPosition = 0; pAd->TransferBufferLength = 0; - INC_RING_INDEX(pAd->NextRxBulkInReadIndex, RX_RING_SIZE); + INC_RING_INDEX(pAd->NextRxBulkInReadIndex, + RX_RING_SIZE); RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); - } - else - { + } else { RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); break; } @@ -861,7 +889,6 @@ VOID RTUSBBulkReceive( } - /* ======================================================================== @@ -885,27 +912,24 @@ VOID RTUSBBulkReceive( Always returns STATUS_MORE_PROCESSING_REQUIRED ======================================================================== */ -VOID RTUSBBulkRxComplete(purbb_t pUrb, struct pt_regs *pt_regs) +void RTUSBBulkRxComplete(struct urb *pUrb, struct pt_regs *pt_regs) { - // use a receive tasklet to handle received packets; - // or sometimes hardware IRQ will be disabled here, so we can not - // use spin_lock_bh()/spin_unlock_bh() after IRQ is disabled. :< - PRX_CONTEXT pRxContext; - PRTMP_ADAPTER pAd; - POS_COOKIE pObj; - + /* use a receive tasklet to handle received packets; */ + /* or sometimes hardware IRQ will be disabled here, so we can not */ + /* use spin_lock_bh()/spin_unlock_bh() after IRQ is disabled. :< */ + struct rt_rx_context *pRxContext; + struct rt_rtmp_adapter *pAd; + struct os_cookie *pObj; - pRxContext = (PRX_CONTEXT)pUrb->context; - pAd = pRxContext->pAd; - pObj = (POS_COOKIE) pAd->OS_Cookie; + pRxContext = (struct rt_rx_context *)pUrb->context; + pAd = pRxContext->pAd; + pObj = (struct os_cookie *)pAd->OS_Cookie; pObj->rx_done_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->rx_done_task); } - - /* ======================================================================== @@ -919,86 +943,78 @@ VOID RTUSBBulkRxComplete(purbb_t pUrb, struct pt_regs *pt_regs) ======================================================================== */ -VOID RTUSBKickBulkOut( - IN PRTMP_ADAPTER pAd) +void RTUSBKickBulkOut(struct rt_rtmp_adapter *pAd) { - // BulkIn Reset will reset whole USB PHY. So we need to make sure fRTMP_ADAPTER_BULKIN_RESET not flaged. - if (!RTMP_TEST_FLAG(pAd ,fRTMP_ADAPTER_NEED_STOP_TX) - ) - { - // 2. PS-Poll frame is next - if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL)) - { + /* BulkIn Reset will reset whole USB PHY. So we need to make sure fRTMP_ADAPTER_BULKIN_RESET not flaged. */ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX) + ) { + /* 2. PS-Poll frame is next */ + if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL)) { RTUSBBulkOutPsPoll(pAd); } - - // 5. Mlme frame is next - else if ((RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME)) && - (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE)) - { + /* 5. Mlme frame is next */ + else if ((RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME)) || + (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE)) { RTUSBBulkOutMLMEPacket(pAd, pAd->MgmtRing.TxDmaIdx); } - - // 6. Data frame normal is next - if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL)) - { - if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || - (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - )) - { - RTUSBBulkOutDataPacket(pAd, 0, pAd->NextBulkOutIndex[0]); + /* 6. Data frame normal is next */ + if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL)) { + if (((!RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + || + (!OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + )) { + RTUSBBulkOutDataPacket(pAd, 0, + pAd-> + NextBulkOutIndex[0]); } } - if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_2)) - { - if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || - (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - )) - { - RTUSBBulkOutDataPacket(pAd, 1, pAd->NextBulkOutIndex[1]); + if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_2)) { + if (((!RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + || + (!OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + )) { + RTUSBBulkOutDataPacket(pAd, 1, + pAd-> + NextBulkOutIndex[1]); } } - if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_3)) - { - if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || - (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - )) - { - RTUSBBulkOutDataPacket(pAd, 2, pAd->NextBulkOutIndex[2]); + if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_3)) { + if (((!RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + || + (!OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + )) { + RTUSBBulkOutDataPacket(pAd, 2, + pAd-> + NextBulkOutIndex[2]); } } - if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_4)) - { - if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || - (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - )) - { - RTUSBBulkOutDataPacket(pAd, 3, pAd->NextBulkOutIndex[3]); + if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_4)) { + if (((!RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + || + (!OPSTATUS_TEST_FLAG + (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + )) { + RTUSBBulkOutDataPacket(pAd, 3, + pAd-> + NextBulkOutIndex[3]); } } - - //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) - if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_5)) - { - if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || - (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - )) - { - } - } - - // 7. Null frame is the last - else if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL)) - { - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - { + /* 7. Null frame is the last */ + else if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL)) { + if (!RTMP_TEST_FLAG + (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) { RTUSBBulkOutNullFrame(pAd); } } - - // 8. No data avaliable - else - { + /* 8. No data avaliable */ + else { } } @@ -1017,16 +1033,14 @@ VOID RTUSBKickBulkOut( ======================================================================== */ -VOID RTUSBCleanUpDataBulkOutQueue( - IN PRTMP_ADAPTER pAd) +void RTUSBCleanUpDataBulkOutQueue(struct rt_rtmp_adapter *pAd) { - UCHAR Idx; - PHT_TX_CONTEXT pTxContext; + u8 Idx; + struct rt_ht_tx_context *pTxContext; DBGPRINT(RT_DEBUG_TRACE, ("--->CleanUpDataBulkOutQueue\n")); - for (Idx = 0; Idx < 4; Idx++) - { + for (Idx = 0; Idx < 4; Idx++) { pTxContext = &pAd->TxContext[Idx]; pTxContext->CurWritePosition = pTxContext->NextBulkOutPosition; @@ -1052,14 +1066,12 @@ VOID RTUSBCleanUpDataBulkOutQueue( ======================================================================== */ -VOID RTUSBCleanUpMLMEBulkOutQueue( - IN PRTMP_ADAPTER pAd) +void RTUSBCleanUpMLMEBulkOutQueue(struct rt_rtmp_adapter *pAd) { DBGPRINT(RT_DEBUG_TRACE, ("--->CleanUpMLMEBulkOutQueue\n")); DBGPRINT(RT_DEBUG_TRACE, ("<---CleanUpMLMEBulkOutQueue\n")); } - /* ======================================================================== @@ -1069,13 +1081,11 @@ VOID RTUSBCleanUpMLMEBulkOutQueue( Return Value: - Note: ======================================================================== */ -VOID RTUSBCancelPendingIRPs( - IN PRTMP_ADAPTER pAd) +void RTUSBCancelPendingIRPs(struct rt_rtmp_adapter *pAd) { RTUSBCancelPendingBulkInIRP(pAd); RTUSBCancelPendingBulkOutIRP(pAd); @@ -1094,29 +1104,25 @@ VOID RTUSBCancelPendingIRPs( ======================================================================== */ -VOID RTUSBCancelPendingBulkInIRP( - IN PRTMP_ADAPTER pAd) +void RTUSBCancelPendingBulkInIRP(struct rt_rtmp_adapter *pAd) { - PRX_CONTEXT pRxContext; - UINT i; + struct rt_rx_context *pRxContext; + u32 i; DBGPRINT_RAW(RT_DEBUG_TRACE, ("--->RTUSBCancelPendingBulkInIRP\n")); - for ( i = 0; i < (RX_RING_SIZE); i++) - { + for (i = 0; i < (RX_RING_SIZE); i++) { pRxContext = &(pAd->RxContext[i]); - if(pRxContext->IRPPending == TRUE) - { + if (pRxContext->IRPPending == TRUE) { RTUSB_UNLINK_URB(pRxContext->pUrb); pRxContext->IRPPending = FALSE; pRxContext->InUse = FALSE; - //NdisInterlockedDecrement(&pAd->PendingRx); - //pAd->PendingRx--; + /*NdisInterlockedDecrement(&pAd->PendingRx); */ + /*pAd->PendingRx--; */ } } DBGPRINT_RAW(RT_DEBUG_TRACE, ("<---RTUSBCancelPendingBulkInIRP\n")); } - /* ======================================================================== @@ -1130,83 +1136,74 @@ VOID RTUSBCancelPendingBulkInIRP( ======================================================================== */ -VOID RTUSBCancelPendingBulkOutIRP( - IN PRTMP_ADAPTER pAd) +void RTUSBCancelPendingBulkOutIRP(struct rt_rtmp_adapter *pAd) { - PHT_TX_CONTEXT pHTTXContext; - PTX_CONTEXT pMLMEContext; - PTX_CONTEXT pBeaconContext; - PTX_CONTEXT pNullContext; - PTX_CONTEXT pPsPollContext; - PTX_CONTEXT pRTSContext; - UINT i, Idx; -// unsigned int IrqFlags; -// NDIS_SPIN_LOCK *pLock; -// BOOLEAN *pPending; - - -// pLock = &pAd->BulkOutLock[MGMTPIPEIDX]; -// pPending = &pAd->BulkOutPending[MGMTPIPEIDX]; - - for (Idx = 0; Idx < 4; Idx++) - { + struct rt_ht_tx_context *pHTTXContext; + struct rt_tx_context *pMLMEContext; + struct rt_tx_context *pBeaconContext; + struct rt_tx_context *pNullContext; + struct rt_tx_context *pPsPollContext; + struct rt_tx_context *pRTSContext; + u32 i, Idx; +/* unsigned int IrqFlags; */ +/* spinlock_t *pLock; */ +/* BOOLEAN *pPending; */ + +/* pLock = &pAd->BulkOutLock[MGMTPIPEIDX]; */ +/* pPending = &pAd->BulkOutPending[MGMTPIPEIDX]; */ + + for (Idx = 0; Idx < 4; Idx++) { pHTTXContext = &(pAd->TxContext[Idx]); - if (pHTTXContext->IRPPending == TRUE) - { + if (pHTTXContext->IRPPending == TRUE) { - // Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself - // remove it from the HeadPendingSendList and NULL out HeadPendingSendList - // when the last IRP on the list has been cancelled; that's how we exit this loop - // + /* Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself */ + /* remove it from the HeadPendingSendList and NULL out HeadPendingSendList */ + /* when the last IRP on the list has been cancelled; that's how we exit this loop */ + /* */ RTUSB_UNLINK_URB(pHTTXContext->pUrb); - // Sleep 200 microseconds to give cancellation time to work + /* Sleep 200 microseconds to give cancellation time to work */ RTMPusecDelay(200); } pAd->BulkOutPending[Idx] = FALSE; } - //RTMP_IRQ_LOCK(pLock, IrqFlags); - for (i = 0; i < MGMT_RING_SIZE; i++) - { - pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[i].AllocVa; - if(pMLMEContext && (pMLMEContext->IRPPending == TRUE)) - { + /*RTMP_IRQ_LOCK(pLock, IrqFlags); */ + for (i = 0; i < MGMT_RING_SIZE; i++) { + pMLMEContext = (struct rt_tx_context *)pAd->MgmtRing.Cell[i].AllocVa; + if (pMLMEContext && (pMLMEContext->IRPPending == TRUE)) { - // Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself - // remove it from the HeadPendingSendList and NULL out HeadPendingSendList - // when the last IRP on the list has been cancelled; that's how we exit this loop - // + /* Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself */ + /* remove it from the HeadPendingSendList and NULL out HeadPendingSendList */ + /* when the last IRP on the list has been cancelled; that's how we exit this loop */ + /* */ RTUSB_UNLINK_URB(pMLMEContext->pUrb); pMLMEContext->IRPPending = FALSE; - // Sleep 200 microsecs to give cancellation time to work + /* Sleep 200 microsecs to give cancellation time to work */ RTMPusecDelay(200); } } pAd->BulkOutPending[MGMTPIPEIDX] = FALSE; - //RTMP_IRQ_UNLOCK(pLock, IrqFlags); - + /*RTMP_IRQ_UNLOCK(pLock, IrqFlags); */ - for (i = 0; i < BEACON_RING_SIZE; i++) - { + for (i = 0; i < BEACON_RING_SIZE; i++) { pBeaconContext = &(pAd->BeaconContext[i]); - if(pBeaconContext->IRPPending == TRUE) - { + if (pBeaconContext->IRPPending == TRUE) { - // Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself - // remove it from the HeadPendingSendList and NULL out HeadPendingSendList - // when the last IRP on the list has been cancelled; that's how we exit this loop - // + /* Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself */ + /* remove it from the HeadPendingSendList and NULL out HeadPendingSendList */ + /* when the last IRP on the list has been cancelled; that's how we exit this loop */ + /* */ RTUSB_UNLINK_URB(pBeaconContext->pUrb); - // Sleep 200 microsecs to give cancellation time to work + /* Sleep 200 microsecs to give cancellation time to work */ RTMPusecDelay(200); } } @@ -1223,11 +1220,11 @@ VOID RTUSBCancelPendingBulkOutIRP( if (pPsPollContext->IRPPending == TRUE) RTUSB_UNLINK_URB(pPsPollContext->pUrb); - for (Idx = 0; Idx < 4; Idx++) - { + for (Idx = 0; Idx < 4; Idx++) { NdisAcquireSpinLock(&pAd->BulkOutLock[Idx]); pAd->BulkOutPending[Idx] = FALSE; NdisReleaseSpinLock(&pAd->BulkOutLock[Idx]); } } +#endif /* RTMP_MAC_USB // */ diff --git a/drivers/staging/rt2870/common/rtusb_data.c b/drivers/staging/rt2870/common/rtusb_data.c index 6b003f63372e090273e8f4f46c25a87d4a43cf17..4583764c78d2e7bf02afd3377977f09b3183ec09 100644 --- a/drivers/staging/rt2870/common/rtusb_data.c +++ b/drivers/staging/rt2870/common/rtusb_data.c @@ -36,82 +36,102 @@ Jan 03-25-2006 created */ + +#ifdef RTMP_MAC_USB + #include "../rt_config.h" -extern UCHAR Phy11BGNextRateUpward[]; // defined in mlme.c -extern UCHAR EpToQueue[]; +extern u8 Phy11BGNextRateUpward[]; /* defined in mlme.c */ +extern u8 EpToQueue[]; -VOID REPORT_AMSDU_FRAMES_TO_LLC( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG DataSize) +void REPORT_AMSDU_FRAMES_TO_LLC(struct rt_rtmp_adapter *pAd, + u8 *pData, unsigned long DataSize) { - PNDIS_PACKET pPacket; - UINT nMSDU; - struct sk_buff *pSkb; + void *pPacket; + u32 nMSDU; + struct sk_buff *pSkb; nMSDU = 0; /* allocate a rx packet */ pSkb = dev_alloc_skb(RX_BUFFER_AGGRESIZE); - pPacket = (PNDIS_PACKET)OSPKT_TO_RTPKT(pSkb); - if (pSkb) - { + pPacket = (void *)OSPKT_TO_RTPKT(pSkb); + if (pSkb) { /* convert 802.11 to 802.3 packet */ pSkb->dev = get_netdev_from_bssid(pAd, BSS0); RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize); - } - else - { - DBGPRINT(RT_DEBUG_ERROR,("Can't allocate skb\n")); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("Can't allocate skb\n")); } } -NDIS_STATUS RTUSBFreeDescriptorRequest( - IN PRTMP_ADAPTER pAd, - IN UCHAR BulkOutPipeId, - IN UINT32 NumberRequired) -{ -// UCHAR FreeNumber = 0; -// UINT Index; - NDIS_STATUS Status = NDIS_STATUS_FAILURE; - unsigned long IrqFlags; - HT_TX_CONTEXT *pHTTXContext; +/* + ======================================================================== + + Routine Description: + This subroutine will scan through releative ring descriptor to find + out avaliable free ring descriptor and compare with request size. + Arguments: + pAd Pointer to our adapter + RingType Selected Ring + + Return Value: + NDIS_STATUS_FAILURE Not enough free descriptor + NDIS_STATUS_SUCCESS Enough free descriptor + + Note: + + ======================================================================== +*/ +int RTUSBFreeDescriptorRequest(struct rt_rtmp_adapter *pAd, + u8 BulkOutPipeId, + u32 NumberRequired) +{ +/* u8 FreeNumber = 0; */ +/* u32 Index; */ + int Status = NDIS_STATUS_FAILURE; + unsigned long IrqFlags; + struct rt_ht_tx_context *pHTTXContext; pHTTXContext = &pAd->TxContext[BulkOutPipeId]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); - if ((pHTTXContext->CurWritePosition < pHTTXContext->NextBulkOutPosition) && ((pHTTXContext->CurWritePosition + NumberRequired + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition)) - { - - RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); - } - else if ((pHTTXContext->CurWritePosition == 8) && (pHTTXContext->NextBulkOutPosition < (NumberRequired + LOCAL_TXBUF_SIZE))) - { - RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); - } - else if (pHTTXContext->bCurWriting == TRUE) - { - DBGPRINT(RT_DEBUG_TRACE,("RTUSBFreeD c3 --> QueIdx=%d, CWPos=%ld, NBOutPos=%ld!\n", BulkOutPipeId, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition)); - RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); - } - else - { + if ((pHTTXContext->CurWritePosition < pHTTXContext->NextBulkOutPosition) + && + ((pHTTXContext->CurWritePosition + NumberRequired + + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition)) { + + RTUSB_SET_BULK_FLAG(pAd, + (fRTUSB_BULK_OUT_DATA_NORMAL << + BulkOutPipeId)); + } else if ((pHTTXContext->CurWritePosition == 8) + && (pHTTXContext->NextBulkOutPosition < + (NumberRequired + LOCAL_TXBUF_SIZE))) { + RTUSB_SET_BULK_FLAG(pAd, + (fRTUSB_BULK_OUT_DATA_NORMAL << + BulkOutPipeId)); + } else if (pHTTXContext->bCurWriting == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, + ("RTUSBFreeD c3 --> QueIdx=%d, CWPos=%ld, NBOutPos=%ld!\n", + BulkOutPipeId, pHTTXContext->CurWritePosition, + pHTTXContext->NextBulkOutPosition)); + RTUSB_SET_BULK_FLAG(pAd, + (fRTUSB_BULK_OUT_DATA_NORMAL << + BulkOutPipeId)); + } else { Status = NDIS_STATUS_SUCCESS; } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); - return (Status); } -NDIS_STATUS RTUSBFreeDescriptorRelease( - IN RTMP_ADAPTER *pAd, - IN UCHAR BulkOutPipeId) +int RTUSBFreeDescriptorRelease(struct rt_rtmp_adapter *pAd, + u8 BulkOutPipeId) { - unsigned long IrqFlags; - HT_TX_CONTEXT *pHTTXContext; + unsigned long IrqFlags; + struct rt_ht_tx_context *pHTTXContext; pHTTXContext = &pAd->TxContext[BulkOutPipeId]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); @@ -121,28 +141,32 @@ NDIS_STATUS RTUSBFreeDescriptorRelease( return (NDIS_STATUS_SUCCESS); } - -BOOLEAN RTUSBNeedQueueBackForAgg( - IN RTMP_ADAPTER *pAd, - IN UCHAR BulkOutPipeId) +BOOLEAN RTUSBNeedQueueBackForAgg(struct rt_rtmp_adapter *pAd, u8 BulkOutPipeId) { - unsigned long IrqFlags; - HT_TX_CONTEXT *pHTTXContext; - BOOLEAN needQueBack = FALSE; + unsigned long IrqFlags; + struct rt_ht_tx_context *pHTTXContext; + BOOLEAN needQueBack = FALSE; pHTTXContext = &pAd->TxContext[BulkOutPipeId]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); - if ((pHTTXContext->IRPPending == TRUE) /*&& (pAd->TxSwQueue[BulkOutPipeId].Number == 0) */) - { - if ((pHTTXContext->CurWritePosition < pHTTXContext->ENextBulkOutPosition) && - (((pHTTXContext->ENextBulkOutPosition+MAX_AGGREGATION_SIZE) < MAX_TXBULK_LIMIT) || (pHTTXContext->CurWritePosition > MAX_AGGREGATION_SIZE))) - { + if ((pHTTXContext->IRPPending == + TRUE) /*&& (pAd->TxSwQueue[BulkOutPipeId].Number == 0) */ ) { + if ((pHTTXContext->CurWritePosition < + pHTTXContext->ENextBulkOutPosition) + && + (((pHTTXContext->ENextBulkOutPosition + + MAX_AGGREGATION_SIZE) < MAX_TXBULK_LIMIT) + || (pHTTXContext->CurWritePosition > + MAX_AGGREGATION_SIZE))) { needQueBack = TRUE; - } - else if ((pHTTXContext->CurWritePosition > pHTTXContext->ENextBulkOutPosition) && - ((pHTTXContext->ENextBulkOutPosition + MAX_AGGREGATION_SIZE) < pHTTXContext->CurWritePosition)) - { + } else + if ((pHTTXContext->CurWritePosition > + pHTTXContext->ENextBulkOutPosition) + && + ((pHTTXContext->ENextBulkOutPosition + + MAX_AGGREGATION_SIZE) < + pHTTXContext->CurWritePosition)) { needQueBack = TRUE; } } @@ -152,7 +176,6 @@ BOOLEAN RTUSBNeedQueueBackForAgg( } - /* ======================================================================== @@ -168,21 +191,17 @@ BOOLEAN RTUSBNeedQueueBackForAgg( ======================================================================== */ -VOID RTUSBRejectPendingPackets( - IN PRTMP_ADAPTER pAd) +void RTUSBRejectPendingPackets(struct rt_rtmp_adapter *pAd) { - UCHAR Index; - PQUEUE_ENTRY pEntry; - PNDIS_PACKET pPacket; - PQUEUE_HEADER pQueue; + u8 Index; + struct rt_queue_entry *pEntry; + void *pPacket; + struct rt_queue_header *pQueue; - - for (Index = 0; Index < 4; Index++) - { + for (Index = 0; Index < 4; Index++) { NdisAcquireSpinLock(&pAd->TxSwQueueLock[Index]); - while (pAd->TxSwQueue[Index].Head != NULL) - { - pQueue = (PQUEUE_HEADER) &(pAd->TxSwQueue[Index]); + while (pAd->TxSwQueue[Index].Head != NULL) { + pQueue = (struct rt_queue_header *)& (pAd->TxSwQueue[Index]); pEntry = RemoveHeadQueue(pQueue); pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); @@ -193,20 +212,46 @@ VOID RTUSBRejectPendingPackets( } -VOID RTMPWriteTxInfo( - IN PRTMP_ADAPTER pAd, - IN PTXINFO_STRUC pTxInfo, - IN USHORT USBDMApktLen, - IN BOOLEAN bWiv, - IN UCHAR QueueSel, - IN UCHAR NextValid, - IN UCHAR TxBurst) +/* + ======================================================================== + + Routine Description: + Calculates the duration which is required to transmit out frames + with given size and specified rate. + + Arguments: + pTxD Pointer to transmit descriptor + Ack Setting for Ack requirement bit + Fragment Setting for Fragment bit + RetryMode Setting for retry mode + Ifs Setting for IFS gap + Rate Setting for transmit rate + Service Setting for service + Length Frame length + TxPreamble Short or Long preamble when using CCK rates + QueIdx - 0-3, according to 802.11e/d4.4 June/2003 + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ + +void RTMPWriteTxInfo(struct rt_rtmp_adapter *pAd, + struct rt_txinfo *pTxInfo, + u16 USBDMApktLen, + IN BOOLEAN bWiv, + u8 QueueSel, u8 NextValid, u8 TxBurst) { pTxInfo->USBDMATxPktLen = USBDMApktLen; pTxInfo->QSEL = QueueSel; if (QueueSel != FIFO_EDCA) - DBGPRINT(RT_DEBUG_TRACE, ("====> QueueSel != FIFO_EDCA<============\n")); - pTxInfo->USBDMANextVLD = FALSE; //NextValid; // Need to check with Jan about this. + DBGPRINT(RT_DEBUG_TRACE, + ("====> QueueSel != FIFO_EDCA<============\n")); + pTxInfo->USBDMANextVLD = FALSE; /*NextValid; // Need to check with Jan about this. */ pTxInfo->USBDMATxburst = TxBurst; pTxInfo->WIV = bWiv; pTxInfo->SwUseLastRound = 0; @@ -214,3 +259,4 @@ VOID RTMPWriteTxInfo( pTxInfo->rsv2 = 0; } +#endif /* RTMP_MAC_USB // */ diff --git a/drivers/staging/rt2870/common/rtusb_io.c b/drivers/staging/rt2870/common/rtusb_io.c index 1d69590421a3494019e3ef85443a9f9f2f2dd559..34443f2243f11c395fb81274e8d7111bf2f75931 100644 --- a/drivers/staging/rt2870/common/rtusb_io.c +++ b/drivers/staging/rt2870/common/rtusb_io.c @@ -36,8 +36,9 @@ Paul Lin 06-25-2004 created */ -#include "../rt_config.h" +#ifdef RTMP_MAC_USB +#include "../rt_config.h" /* ======================================================================== @@ -55,26 +56,18 @@ ======================================================================== */ -NTSTATUS RTUSBFirmwareRun( - IN PRTMP_ADAPTER pAd) +static int RTUSBFirmwareRun(struct rt_rtmp_adapter *pAd) { - NTSTATUS Status; - - Status = RTUSB_VendorRequest( - pAd, - USBD_TRANSFER_DIRECTION_OUT, - DEVICE_VENDOR_REQUEST_OUT, - 0x01, - 0x8, - 0, - NULL, - 0); + int Status; + + Status = RTUSB_VendorRequest(pAd, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x01, 0x8, 0, NULL, 0); return Status; } - - /* ======================================================================== @@ -90,19 +83,16 @@ NTSTATUS RTUSBFirmwareRun( ======================================================================== */ -NTSTATUS RTUSBFirmwareWrite( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pFwImage, - IN ULONG FwLen) +int RTUSBFirmwareWrite(struct rt_rtmp_adapter *pAd, + u8 *pFwImage, unsigned long FwLen) { - UINT32 MacReg; - NTSTATUS Status; -// ULONG i; - USHORT writeLen; + u32 MacReg; + int Status; +/* unsigned long i; */ + u16 writeLen; Status = RTUSBReadMACRegister(pAd, MAC_CSR0, &MacReg); - writeLen = FwLen; RTUSBMultiWrite(pAd, FIRMWARE_IMAGE_BASE, pFwImage, writeLen); @@ -110,66 +100,28 @@ NTSTATUS RTUSBFirmwareWrite( Status = RTUSBWriteMACRegister(pAd, 0x701c, 0xffffffff); Status = RTUSBFirmwareRun(pAd); + /*2008/11/28:KH add to fix the dead rf frequency offset bug<-- */ RTMPusecDelay(10000); - RTUSBWriteMACRegister(pAd,H2M_MAILBOX_CSR,0); - AsicSendCommandToMcu(pAd, 0x72, 0x00, 0x00, 0x00);//reset rf by MCU supported by new firmware + RTUSBWriteMACRegister(pAd, H2M_MAILBOX_CSR, 0); + AsicSendCommandToMcu(pAd, 0x72, 0x00, 0x00, 0x00); /*reset rf by MCU supported by new firmware */ + /*2008/11/28:KH add to fix the dead rf frequency offset bug--> */ return Status; } - -/* - ======================================================================== - - Routine Description: Get current firmware operation mode (Return Value) - - Arguments: - - Return Value: - 0 or 1 = Downloaded by host driver - others = Driver doesn't download firmware - - IRQL = - - Note: - - ======================================================================== -*/ -NTSTATUS RTUSBFirmwareOpmode( - IN PRTMP_ADAPTER pAd, - OUT PUINT32 pValue) +int RTUSBVenderReset(struct rt_rtmp_adapter *pAd) { - NTSTATUS Status; - - Status = RTUSB_VendorRequest( - pAd, - (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK), - DEVICE_VENDOR_REQUEST_IN, - 0x1, - 0x11, - 0, - pValue, - 4); - return Status; -} -NTSTATUS RTUSBVenderReset( - IN PRTMP_ADAPTER pAd) -{ - NTSTATUS Status; + int Status; DBGPRINT_RAW(RT_DEBUG_ERROR, ("-->RTUSBVenderReset\n")); - Status = RTUSB_VendorRequest( - pAd, - USBD_TRANSFER_DIRECTION_OUT, - DEVICE_VENDOR_REQUEST_OUT, - 0x01, - 0x1, - 0, - NULL, - 0); + Status = RTUSB_VendorRequest(pAd, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x01, 0x1, 0, NULL, 0); DBGPRINT_RAW(RT_DEBUG_ERROR, ("<--RTUSBVenderReset\n")); return Status; } + /* ======================================================================== @@ -185,23 +137,16 @@ NTSTATUS RTUSBVenderReset( ======================================================================== */ -NTSTATUS RTUSBMultiRead( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - OUT PUCHAR pData, - IN USHORT length) +int RTUSBMultiRead(struct rt_rtmp_adapter *pAd, + u16 Offset, u8 *pData, u16 length) { - NTSTATUS Status; - - Status = RTUSB_VendorRequest( - pAd, - (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK), - DEVICE_VENDOR_REQUEST_IN, - 0x7, - 0, - Offset, - pData, - length); + int Status; + + Status = RTUSB_VendorRequest(pAd, + (USBD_TRANSFER_DIRECTION_IN | + USBD_SHORT_TRANSFER_OK), + DEVICE_VENDOR_REQUEST_IN, 0x7, 0, Offset, + pData, length); return Status; } @@ -221,77 +166,56 @@ NTSTATUS RTUSBMultiRead( ======================================================================== */ -NTSTATUS RTUSBMultiWrite_OneByte( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN PUCHAR pData) +int RTUSBMultiWrite_OneByte(struct rt_rtmp_adapter *pAd, + u16 Offset, u8 *pData) { - NTSTATUS Status; - - // TODO: In 2870, use this funciton carefully cause it's not stable. - Status = RTUSB_VendorRequest( - pAd, - USBD_TRANSFER_DIRECTION_OUT, - DEVICE_VENDOR_REQUEST_OUT, - 0x6, - 0, - Offset, - pData, - 1); + int Status; + + /* TODO: In 2870, use this funciton carefully cause it's not stable. */ + Status = RTUSB_VendorRequest(pAd, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x6, 0, Offset, pData, 1); return Status; } -NTSTATUS RTUSBMultiWrite( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN PUCHAR pData, - IN USHORT length) +int RTUSBMultiWrite(struct rt_rtmp_adapter *pAd, + u16 Offset, u8 *pData, u16 length) { - NTSTATUS Status; - - - USHORT index = 0,Value; - PUCHAR pSrc = pData; - USHORT resude = 0; - - resude = length % 2; - length += resude; - do - { - Value =(USHORT)( *pSrc | (*(pSrc + 1) << 8)); - Status = RTUSBSingleWrite(pAd,Offset + index,Value); - index +=2; - length -= 2; - pSrc = pSrc + 2; - }while(length > 0); + int Status; + + u16 index = 0, Value; + u8 *pSrc = pData; + u16 resude = 0; + + resude = length % 2; + length += resude; + do { + Value = (u16)(*pSrc | (*(pSrc + 1) << 8)); + Status = RTUSBSingleWrite(pAd, Offset + index, Value); + index += 2; + length -= 2; + pSrc = pSrc + 2; + } while (length > 0); return Status; } - -NTSTATUS RTUSBSingleWrite( - IN RTMP_ADAPTER *pAd, - IN USHORT Offset, - IN USHORT Value) +int RTUSBSingleWrite(struct rt_rtmp_adapter *pAd, + u16 Offset, u16 Value) { - NTSTATUS Status; - - Status = RTUSB_VendorRequest( - pAd, - USBD_TRANSFER_DIRECTION_OUT, - DEVICE_VENDOR_REQUEST_OUT, - 0x2, - Value, - Offset, - NULL, - 0); + int Status; + + Status = RTUSB_VendorRequest(pAd, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x2, Value, Offset, NULL, 0); return Status; } - /* ======================================================================== @@ -307,26 +231,19 @@ NTSTATUS RTUSBSingleWrite( ======================================================================== */ -NTSTATUS RTUSBReadMACRegister( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - OUT PUINT32 pValue) +int RTUSBReadMACRegister(struct rt_rtmp_adapter *pAd, + u16 Offset, u32 *pValue) { - NTSTATUS Status; - UINT32 localVal; - - Status = RTUSB_VendorRequest( - pAd, - (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK), - DEVICE_VENDOR_REQUEST_IN, - 0x7, - 0, - Offset, - &localVal, - 4); + int Status = 0; + u32 localVal; - *pValue = le2cpu32(localVal); + Status = RTUSB_VendorRequest(pAd, + (USBD_TRANSFER_DIRECTION_IN | + USBD_SHORT_TRANSFER_OK), + DEVICE_VENDOR_REQUEST_IN, 0x7, 0, Offset, + &localVal, 4); + *pValue = le2cpu32(localVal); if (Status < 0) *pValue = 0xffffffff; @@ -334,7 +251,6 @@ NTSTATUS RTUSBReadMACRegister( return Status; } - /* ======================================================================== @@ -350,25 +266,22 @@ NTSTATUS RTUSBReadMACRegister( ======================================================================== */ -NTSTATUS RTUSBWriteMACRegister( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN UINT32 Value) +int RTUSBWriteMACRegister(struct rt_rtmp_adapter *pAd, + u16 Offset, u32 Value) { - NTSTATUS Status; - UINT32 localVal; + int Status; + u32 localVal; localVal = Value; - Status = RTUSBSingleWrite(pAd, Offset, (USHORT)(localVal & 0xffff)); - Status = RTUSBSingleWrite(pAd, Offset + 2, (USHORT)((localVal & 0xffff0000) >> 16)); + Status = RTUSBSingleWrite(pAd, Offset, (u16)(localVal & 0xffff)); + Status = + RTUSBSingleWrite(pAd, Offset + 2, + (u16)((localVal & 0xffff0000) >> 16)); return Status; } - - -#if 1 /* ======================================================================== @@ -384,139 +297,77 @@ NTSTATUS RTUSBWriteMACRegister( ======================================================================== */ -NTSTATUS RTUSBReadBBPRegister( - IN PRTMP_ADAPTER pAd, - IN UCHAR Id, - IN PUCHAR pValue) +int RTUSBReadBBPRegister(struct rt_rtmp_adapter *pAd, + u8 Id, u8 *pValue) { - BBP_CSR_CFG_STRUC BbpCsr; - UINT i = 0; - NTSTATUS status; + BBP_CSR_CFG_STRUC BbpCsr; + u32 i = 0; + int status; - // Verify the busy condition - do - { + /* Verify the busy condition */ + do { status = RTUSBReadMACRegister(pAd, BBP_CSR_CFG, &BbpCsr.word); - if(status >= 0) - { - if (!(BbpCsr.field.Busy == BUSY)) - break; + if (status >= 0) { + if (!(BbpCsr.field.Busy == BUSY)) + break; } - printk("RTUSBReadBBPRegister(BBP_CSR_CFG_1):retry count=%d!\n", i); + DBGPRINT(RT_DEBUG_TRACE, + ("RTUSBReadBBPRegister(BBP_CSR_CFG_1):retry count=%d!\n", + i)); i++; - } - while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); - - if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) - { - // - // Read failed then Return Default value. - // + } while ((i < RETRY_LIMIT) + && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); + + if ((i == RETRY_LIMIT) + || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { + /* */ + /* Read failed then Return Default value. */ + /* */ *pValue = pAd->BbpWriteLatch[Id]; - DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("Retry count exhausted or device removed!!!\n")); return STATUS_UNSUCCESSFUL; } - - // Prepare for write material - BbpCsr.word = 0; - BbpCsr.field.fRead = 1; - BbpCsr.field.Busy = 1; - BbpCsr.field.RegNum = Id; + /* Prepare for write material */ + BbpCsr.word = 0; + BbpCsr.field.fRead = 1; + BbpCsr.field.Busy = 1; + BbpCsr.field.RegNum = Id; RTUSBWriteMACRegister(pAd, BBP_CSR_CFG, BbpCsr.word); i = 0; - // Verify the busy condition - do - { + /* Verify the busy condition */ + do { status = RTUSBReadMACRegister(pAd, BBP_CSR_CFG, &BbpCsr.word); - if (status >= 0) - { - if (!(BbpCsr.field.Busy == BUSY)) - { - *pValue = (UCHAR)BbpCsr.field.Value; - break; - } + if (status >= 0) { + if (!(BbpCsr.field.Busy == BUSY)) { + *pValue = (u8)BbpCsr.field.Value; + break; + } } - printk("RTUSBReadBBPRegister(BBP_CSR_CFG_2):retry count=%d!\n", i); + DBGPRINT(RT_DEBUG_TRACE, + ("RTUSBReadBBPRegister(BBP_CSR_CFG_2):retry count=%d!\n", + i)); i++; - } - while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); - - if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) - { - // - // Read failed then Return Default value. - // + } while ((i < RETRY_LIMIT) + && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); + + if ((i == RETRY_LIMIT) + || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { + /* */ + /* Read failed then Return Default value. */ + /* */ *pValue = pAd->BbpWriteLatch[Id]; - DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("Retry count exhausted or device removed!!!\n")); return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; } -#else -/* - ======================================================================== - - Routine Description: Read 8-bit BBP register via firmware - Arguments: - - Return Value: - - IRQL = - - Note: - - ======================================================================== -*/ -NTSTATUS RTUSBReadBBPRegister( - IN PRTMP_ADAPTER pAd, - IN UCHAR Id, - IN PUCHAR pValue) -{ - BBP_CSR_CFG_STRUC BbpCsr; - int i, k; - for (i=0; iBbpWriteLatch[Id]; - return STATUS_UNSUCCESSFUL; - } - return STATUS_SUCCESS; -} -#endif - -#if 1 /* ======================================================================== @@ -532,95 +383,46 @@ NTSTATUS RTUSBReadBBPRegister( ======================================================================== */ -NTSTATUS RTUSBWriteBBPRegister( - IN PRTMP_ADAPTER pAd, - IN UCHAR Id, - IN UCHAR Value) +int RTUSBWriteBBPRegister(struct rt_rtmp_adapter *pAd, + u8 Id, u8 Value) { - BBP_CSR_CFG_STRUC BbpCsr; - UINT i = 0; - NTSTATUS status; - // Verify the busy condition - do - { + BBP_CSR_CFG_STRUC BbpCsr; + u32 i = 0; + int status; + /* Verify the busy condition */ + do { status = RTUSBReadMACRegister(pAd, BBP_CSR_CFG, &BbpCsr.word); - if (status >= 0) - { - if (!(BbpCsr.field.Busy == BUSY)) - break; + if (status >= 0) { + if (!(BbpCsr.field.Busy == BUSY)) + break; } - printk("RTUSBWriteBBPRegister(BBP_CSR_CFG):retry count=%d!\n", i); + DBGPRINT(RT_DEBUG_TRACE, + ("RTUSBWriteBBPRegister(BBP_CSR_CFG):retry count=%d!\n", + i)); i++; } - while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); + while ((i < RETRY_LIMIT) + && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); - if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); + if ((i == RETRY_LIMIT) + || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("Retry count exhausted or device removed!!!\n")); return STATUS_UNSUCCESSFUL; } - - // Prepare for write material - BbpCsr.word = 0; - BbpCsr.field.fRead = 0; - BbpCsr.field.Value = Value; - BbpCsr.field.Busy = 1; - BbpCsr.field.RegNum = Id; + /* Prepare for write material */ + BbpCsr.word = 0; + BbpCsr.field.fRead = 0; + BbpCsr.field.Value = Value; + BbpCsr.field.Busy = 1; + BbpCsr.field.RegNum = Id; RTUSBWriteMACRegister(pAd, BBP_CSR_CFG, BbpCsr.word); pAd->BbpWriteLatch[Id] = Value; return STATUS_SUCCESS; } -#else -/* - ======================================================================== - Routine Description: Write 8-bit BBP register via firmware - - Arguments: - - Return Value: - - IRQL = - - Note: - - ======================================================================== -*/ - -NTSTATUS RTUSBWriteBBPRegister( - IN PRTMP_ADAPTER pAd, - IN UCHAR Id, - IN UCHAR Value) - -{ - BBP_CSR_CFG_STRUC BbpCsr; - int BusyCnt; - for (BusyCnt=0; BusyCntBbpWriteLatch[Id] = Value; - break; - } - if (BusyCnt == MAX_BUSY_COUNT) - { - DBGPRINT_ERR(("BBP write R%d=0x%x fail\n", Id, BbpCsr.word)); - return STATUS_UNSUCCESSFUL; - } - return STATUS_SUCCESS; -} -#endif /* ======================================================================== @@ -636,31 +438,31 @@ NTSTATUS RTUSBWriteBBPRegister( ======================================================================== */ -NTSTATUS RTUSBWriteRFRegister( - IN PRTMP_ADAPTER pAd, - IN UINT32 Value) +int RTUSBWriteRFRegister(struct rt_rtmp_adapter *pAd, u32 Value) { - PHY_CSR4_STRUC PhyCsr4; - UINT i = 0; - NTSTATUS status; + PHY_CSR4_STRUC PhyCsr4; + u32 i = 0; + int status; NdisZeroMemory(&PhyCsr4, sizeof(PHY_CSR4_STRUC)); - do - { + do { status = RTUSBReadMACRegister(pAd, RF_CSR_CFG0, &PhyCsr4.word); - if (status >= 0) - { - if (!(PhyCsr4.field.Busy)) - break; + if (status >= 0) { + if (!(PhyCsr4.field.Busy)) + break; } - printk("RTUSBWriteRFRegister(RF_CSR_CFG0):retry count=%d!\n", i); + DBGPRINT(RT_DEBUG_TRACE, + ("RTUSBWriteRFRegister(RF_CSR_CFG0):retry count=%d!\n", + i)); i++; } - while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); + while ((i < RETRY_LIMIT) + && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); - if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); + if ((i == RETRY_LIMIT) + || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("Retry count exhausted or device removed!!!\n")); return STATUS_UNSUCCESSFUL; } @@ -672,57 +474,7 @@ NTSTATUS RTUSBWriteRFRegister( /* ======================================================================== - Routine Description: Write RT30xx RF register through MAC - - Arguments: - - Return Value: - - IRQL = - - Note: - - ======================================================================== -*/ -NTSTATUS RT30xxWriteRFRegister( - IN PRTMP_ADAPTER pAd, - IN UCHAR RegID, - IN UCHAR Value) -{ - RF_CSR_CFG_STRUC rfcsr; - UINT i = 0; - - do - { - RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word); - - if (!rfcsr.field.RF_CSR_KICK) - break; - i++; - } - while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); - - if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); - return STATUS_UNSUCCESSFUL; - } - - rfcsr.field.RF_CSR_WR = 1; - rfcsr.field.RF_CSR_KICK = 1; - rfcsr.field.TESTCSR_RFACC_REGNUM = RegID; - rfcsr.field.RF_CSR_DATA = Value; - - RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word); - - return STATUS_SUCCESS; -} - - -/* - ======================================================================== - - Routine Description: Read RT30xx RF register through MAC + Routine Description: Arguments: @@ -734,48 +486,18 @@ NTSTATUS RT30xxWriteRFRegister( ======================================================================== */ -NTSTATUS RT30xxReadRFRegister( - IN PRTMP_ADAPTER pAd, - IN UCHAR RegID, - IN PUCHAR pValue) +int RTUSBReadEEPROM(struct rt_rtmp_adapter *pAd, + u16 Offset, u8 *pData, u16 length) { - RF_CSR_CFG_STRUC rfcsr; - UINT i=0, k=0; - - for (i=0; ibUseEfuse) - Status =eFuseRead(pAd, Offset, pData, length); - else - { - Status = RTUSB_VendorRequest( - pAd, - (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK), - DEVICE_VENDOR_REQUEST_IN, - 0x9, - 0, - Offset, - pData, - length); - } + Status = RTUSB_VendorRequest(pAd, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x8, 0, Offset, pData, length); return Status; } -/* - ======================================================================== - - Routine Description: - - Arguments: - - Return Value: - - IRQL = - - Note: - - ======================================================================== -*/ -NTSTATUS RTUSBWriteEEPROM( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN PUCHAR pData, - IN USHORT length) +int RTUSBReadEEPROM16(struct rt_rtmp_adapter *pAd, + u16 offset, u16 *pData) { - NTSTATUS Status = STATUS_SUCCESS; + int status; + u16 localData; - if(pAd->bUseEfuse) - Status = eFuseWrite(pAd, Offset, pData, length); - else - { - Status = RTUSB_VendorRequest( - pAd, - USBD_TRANSFER_DIRECTION_OUT, - DEVICE_VENDOR_REQUEST_OUT, - 0x8, - 0, - Offset, - pData, - length); - } + status = RTUSBReadEEPROM(pAd, offset, (u8 *)(&localData), 2); + if (status == STATUS_SUCCESS) + *pData = le2cpu16(localData); + + return status; - return Status; } /* @@ -875,16 +557,15 @@ NTSTATUS RTUSBWriteEEPROM( ======================================================================== */ -VOID RTUSBPutToSleep( - IN PRTMP_ADAPTER pAd) +void RTUSBPutToSleep(struct rt_rtmp_adapter *pAd) { - UINT32 value; + u32 value; - // Timeout 0x40 x 50us - value = (SLEEPCID<<16)+(OWNERMCU<<24)+ (0x40<<8)+1; + /* Timeout 0x40 x 50us */ + value = (SLEEPCID << 16) + (OWNERMCU << 24) + (0x40 << 8) + 1; RTUSBWriteMACRegister(pAd, 0x7010, value); RTUSBWriteMACRegister(pAd, 0x404, 0x30); - //RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + /*RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); */ DBGPRINT_RAW(RT_DEBUG_ERROR, ("Sleep Mailbox testvalue %x\n", value)); } @@ -904,20 +585,14 @@ VOID RTUSBPutToSleep( ======================================================================== */ -NTSTATUS RTUSBWakeUp( - IN PRTMP_ADAPTER pAd) +int RTUSBWakeUp(struct rt_rtmp_adapter *pAd) { - NTSTATUS Status; - - Status = RTUSB_VendorRequest( - pAd, - USBD_TRANSFER_DIRECTION_OUT, - DEVICE_VENDOR_REQUEST_OUT, - 0x01, - 0x09, - 0, - NULL, - 0); + int Status; + + Status = RTUSB_VendorRequest(pAd, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x01, 0x09, 0, NULL, 0); return Status; } @@ -937,13 +612,12 @@ NTSTATUS RTUSBWakeUp( ======================================================================== */ -VOID RTUSBInitializeCmdQ( - IN PCmdQ cmdq) +void RTUSBInitializeCmdQ(struct rt_cmdq *cmdq) { cmdq->head = NULL; cmdq->tail = NULL; cmdq->size = 0; - cmdq->CmdQState = RT2870_THREAD_INITED; + cmdq->CmdQState = RTMP_TASK_STAT_INITED; } /* @@ -961,41 +635,45 @@ VOID RTUSBInitializeCmdQ( ======================================================================== */ -NDIS_STATUS RTUSBEnqueueCmdFromNdis( - IN PRTMP_ADAPTER pAd, - IN NDIS_OID Oid, - IN BOOLEAN SetInformation, - IN PVOID pInformationBuffer, - IN UINT32 InformationBufferLength) +int RTUSBEnqueueCmdFromNdis(struct rt_rtmp_adapter *pAd, + IN NDIS_OID Oid, + IN BOOLEAN SetInformation, + void *pInformationBuffer, + u32 InformationBufferLength) { - NDIS_STATUS status; - PCmdQElmt cmdqelmt = NULL; - POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + int status; + struct rt_cmdqelmt *cmdqelmt = NULL; + struct rt_rtmp_os_task *pTask = &pAd->cmdQTask; - if (pid_nr(pObj->RTUSBCmdThr_pid) > 0) - return (NDIS_STATUS_RESOURCES); +#ifdef KTHREAD_SUPPORT + if (pTask->kthread_task == NULL) +#else + CHECK_PID_LEGALITY(pTask->taskPID) { + } + else +#endif + return (NDIS_STATUS_RESOURCES); - status = RTMPAllocateMemory((PVOID *)&cmdqelmt, sizeof(CmdQElmt)); + status = os_alloc_mem(pAd, (u8 **) (&cmdqelmt), sizeof(struct rt_cmdqelmt)); if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt == NULL)) return (NDIS_STATUS_RESOURCES); - cmdqelmt->buffer = NULL; - if (pInformationBuffer != NULL) - { - status = RTMPAllocateMemory((PVOID *)&cmdqelmt->buffer, InformationBufferLength); - if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt->buffer == NULL)) - { - kfree(cmdqelmt); - return (NDIS_STATUS_RESOURCES); - } - else - { - NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, InformationBufferLength); - cmdqelmt->bufferlength = InformationBufferLength; - } + cmdqelmt->buffer = NULL; + if (pInformationBuffer != NULL) { + status = + os_alloc_mem(pAd, (u8 **) & cmdqelmt->buffer, + InformationBufferLength); + if ((status != NDIS_STATUS_SUCCESS) + || (cmdqelmt->buffer == NULL)) { + kfree(cmdqelmt); + return (NDIS_STATUS_RESOURCES); + } else { + NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, + InformationBufferLength); + cmdqelmt->bufferlength = InformationBufferLength; } - else - cmdqelmt->bufferlength = 0; + } else + cmdqelmt->bufferlength = 0; cmdqelmt->command = Oid; cmdqelmt->CmdFromNdis = TRUE; @@ -1005,28 +683,22 @@ NDIS_STATUS RTUSBEnqueueCmdFromNdis( cmdqelmt->SetOperation = FALSE; NdisAcquireSpinLock(&pAd->CmdQLock); - if (pAd->CmdQ.CmdQState & RT2870_THREAD_CAN_DO_INSERT) - { + if (pAd->CmdQ.CmdQState & RTMP_TASK_CAN_DO_INSERT) { EnqueueCmd((&pAd->CmdQ), cmdqelmt); status = NDIS_STATUS_SUCCESS; - } - else - { + } else { status = NDIS_STATUS_FAILURE; } NdisReleaseSpinLock(&pAd->CmdQLock); - if (status == NDIS_STATUS_FAILURE) - { + if (status == NDIS_STATUS_FAILURE) { if (cmdqelmt->buffer) - NdisFreeMemory(cmdqelmt->buffer, cmdqelmt->bufferlength, 0); - NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0); - } - else - RTUSBCMDUp(pAd); - + os_free_mem(pAd, cmdqelmt->buffer); + os_free_mem(pAd, cmdqelmt); + } else + RTUSBCMDUp(pAd); - return(NDIS_STATUS_SUCCESS); + return (NDIS_STATUS_SUCCESS); } /* @@ -1044,37 +716,33 @@ NDIS_STATUS RTUSBEnqueueCmdFromNdis( ======================================================================== */ -NDIS_STATUS RTUSBEnqueueInternalCmd( - IN PRTMP_ADAPTER pAd, - IN NDIS_OID Oid, - IN PVOID pInformationBuffer, - IN UINT32 InformationBufferLength) +int RTUSBEnqueueInternalCmd(struct rt_rtmp_adapter *pAd, + IN NDIS_OID Oid, + void *pInformationBuffer, + u32 InformationBufferLength) { - NDIS_STATUS status; - PCmdQElmt cmdqelmt = NULL; + int status; + struct rt_cmdqelmt *cmdqelmt = NULL; - - status = RTMPAllocateMemory((PVOID *)&cmdqelmt, sizeof(CmdQElmt)); + status = os_alloc_mem(pAd, (u8 **) & cmdqelmt, sizeof(struct rt_cmdqelmt)); if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt == NULL)) return (NDIS_STATUS_RESOURCES); - NdisZeroMemory(cmdqelmt, sizeof(CmdQElmt)); - - if(InformationBufferLength > 0) - { - status = RTMPAllocateMemory((PVOID *)&cmdqelmt->buffer, InformationBufferLength); - if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt->buffer == NULL)) - { - NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0); + NdisZeroMemory(cmdqelmt, sizeof(struct rt_cmdqelmt)); + + if (InformationBufferLength > 0) { + status = + os_alloc_mem(pAd, (u8 **) & cmdqelmt->buffer, + InformationBufferLength); + if ((status != NDIS_STATUS_SUCCESS) + || (cmdqelmt->buffer == NULL)) { + os_free_mem(pAd, cmdqelmt); return (NDIS_STATUS_RESOURCES); - } - else - { - NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, InformationBufferLength); + } else { + NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, + InformationBufferLength); cmdqelmt->bufferlength = InformationBufferLength; } - } - else - { + } else { cmdqelmt->buffer = NULL; cmdqelmt->bufferlength = 0; } @@ -1082,30 +750,24 @@ NDIS_STATUS RTUSBEnqueueInternalCmd( cmdqelmt->command = Oid; cmdqelmt->CmdFromNdis = FALSE; - if (cmdqelmt != NULL) - { + if (cmdqelmt != NULL) { NdisAcquireSpinLock(&pAd->CmdQLock); - if (pAd->CmdQ.CmdQState & RT2870_THREAD_CAN_DO_INSERT) - { + if (pAd->CmdQ.CmdQState & RTMP_TASK_CAN_DO_INSERT) { EnqueueCmd((&pAd->CmdQ), cmdqelmt); status = NDIS_STATUS_SUCCESS; - } - else - { + } else { status = NDIS_STATUS_FAILURE; } NdisReleaseSpinLock(&pAd->CmdQLock); - if (status == NDIS_STATUS_FAILURE) - { + if (status == NDIS_STATUS_FAILURE) { if (cmdqelmt->buffer) - NdisFreeMemory(cmdqelmt->buffer, cmdqelmt->bufferlength, 0); - NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0); - } - else - RTUSBCMDUp(pAd); + os_free_mem(pAd, cmdqelmt->buffer); + os_free_mem(pAd, cmdqelmt); + } else + RTUSBCMDUp(pAd); } - return(NDIS_STATUS_SUCCESS); + return (NDIS_STATUS_SUCCESS); } /* @@ -1123,14 +785,11 @@ NDIS_STATUS RTUSBEnqueueInternalCmd( ======================================================================== */ -VOID RTUSBDequeueCmd( - IN PCmdQ cmdq, - OUT PCmdQElmt *pcmdqelmt) +void RTUSBDequeueCmd(struct rt_cmdq *cmdq, struct rt_cmdqelmt * * pcmdqelmt) { *pcmdqelmt = cmdq->head; - if (*pcmdqelmt != NULL) - { + if (*pcmdqelmt != NULL) { cmdq->head = cmdq->head->next; cmdq->size--; if (cmdq->size == 0) @@ -1164,7 +823,6 @@ VOID RTUSBDequeueCmd( method can wait for it to complete. Since you don't have a handle on the URB used, you can't cancel the request. - Routine Description: Arguments: @@ -1175,68 +833,109 @@ VOID RTUSBDequeueCmd( ======================================================================== */ -NTSTATUS RTUSB_VendorRequest( - IN PRTMP_ADAPTER pAd, - IN UINT32 TransferFlags, - IN UCHAR RequestType, - IN UCHAR Request, - IN USHORT Value, - IN USHORT Index, - IN PVOID TransferBuffer, - IN UINT32 TransferBufferLength) +int RTUSB_VendorRequest(struct rt_rtmp_adapter *pAd, + u32 TransferFlags, + u8 RequestType, + u8 Request, + u16 Value, + u16 Index, + void *TransferBuffer, + u32 TransferBufferLength) { - int ret; - POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + int ret = 0; + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) - { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { DBGPRINT(RT_DEBUG_ERROR, ("device disconnected\n")); return -1; - } - else if (in_interrupt()) - { - DBGPRINT(RT_DEBUG_ERROR, ("in_interrupt, RTUSB_VendorRequest Request%02x Value%04x Offset%04x\n",Request,Value,Index)); + } else if (in_interrupt()) { + DBGPRINT(RT_DEBUG_ERROR, + ("in_interrupt, RTUSB_VendorRequest Request%02x Value%04x Offset%04x\n", + Request, Value, Index)); return -1; - } - else - { + } else { #define MAX_RETRY_COUNT 10 int retryCount = 0; - void *tmpBuf = TransferBuffer; + void *tmpBuf = TransferBuffer; - // Acquire Control token - do { - if( RequestType == DEVICE_VENDOR_REQUEST_OUT) - ret=usb_control_msg(pObj->pUsb_Dev, usb_sndctrlpipe( pObj->pUsb_Dev, 0 ), Request, RequestType, Value,Index, tmpBuf, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES); - else if(RequestType == DEVICE_VENDOR_REQUEST_IN) - ret=usb_control_msg(pObj->pUsb_Dev, usb_rcvctrlpipe( pObj->pUsb_Dev, 0 ), Request, RequestType, Value,Index, tmpBuf, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES); - else - { - DBGPRINT(RT_DEBUG_ERROR, ("vendor request direction is failed\n")); - ret = -1; + ret = down_interruptible(&(pAd->UsbVendorReq_semaphore)); + if (pAd->UsbVendorReqBuf) { + ASSERT(TransferBufferLength < MAX_PARAM_BUFFER_SIZE); + + tmpBuf = (void *)pAd->UsbVendorReqBuf; + NdisZeroMemory(pAd->UsbVendorReqBuf, + TransferBufferLength); + + if (RequestType == DEVICE_VENDOR_REQUEST_OUT) + NdisMoveMemory(tmpBuf, TransferBuffer, + TransferBufferLength); } + do { + if (RequestType == DEVICE_VENDOR_REQUEST_OUT) + ret = + usb_control_msg(pObj->pUsb_Dev, + usb_sndctrlpipe(pObj-> + pUsb_Dev, + 0), Request, + RequestType, Value, Index, + tmpBuf, + TransferBufferLength, + CONTROL_TIMEOUT_JIFFIES); + else if (RequestType == DEVICE_VENDOR_REQUEST_IN) + ret = + usb_control_msg(pObj->pUsb_Dev, + usb_rcvctrlpipe(pObj-> + pUsb_Dev, + 0), Request, + RequestType, Value, Index, + tmpBuf, + TransferBufferLength, + CONTROL_TIMEOUT_JIFFIES); + else { + DBGPRINT(RT_DEBUG_ERROR, + ("vendor request direction is failed\n")); + ret = -1; + } + retryCount++; if (ret < 0) { - printk("#\n"); + DBGPRINT(RT_DEBUG_OFF, ("#\n")); RTMPusecDelay(5000); } - } while((ret < 0) && (retryCount < MAX_RETRY_COUNT)); - - if (ret < 0) { -// DBGPRINT(RT_DEBUG_ERROR, ("USBVendorRequest failed ret=%d \n",ret)); - DBGPRINT(RT_DEBUG_ERROR, ("RTUSB_VendorRequest failed(%d),TxFlags=0x%x, ReqType=%s, Req=0x%x, Index=0x%x\n", - ret, TransferFlags, (RequestType == DEVICE_VENDOR_REQUEST_OUT ? "OUT" : "IN"), Request, Index)); + } while ((ret < 0) && (retryCount < MAX_RETRY_COUNT)); + + if ((pAd->UsbVendorReqBuf) + && (RequestType == DEVICE_VENDOR_REQUEST_IN)) + NdisMoveMemory(TransferBuffer, tmpBuf, + TransferBufferLength); + up(&(pAd->UsbVendorReq_semaphore)); + + if (ret < 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("RTUSB_VendorRequest failed(%d),TxFlags=0x%x, ReqType=%s, Req=0x%x, Index=0x%x\n", + ret, TransferFlags, + (RequestType == + DEVICE_VENDOR_REQUEST_OUT ? "OUT" : "IN"), + Request, Index)); if (Request == 0x2) - DBGPRINT(RT_DEBUG_ERROR, ("\tRequest Value=0x%04x!\n", Value)); + DBGPRINT(RT_DEBUG_ERROR, + ("\tRequest Value=0x%04x!\n", Value)); + + if ((TransferBuffer != NULL) + && (TransferBufferLength > 0)) + hex_dump("Failed TransferBuffer value", + TransferBuffer, TransferBufferLength); + } - if ((TransferBuffer!= NULL) && (TransferBufferLength > 0)) - hex_dump("Failed TransferBuffer value", TransferBuffer, TransferBufferLength); - } } - return ret; + + if (ret != -1) + return STATUS_SUCCESS; + else + return STATUS_UNSUCCESSFUL; } /* @@ -1255,28 +954,25 @@ NTSTATUS RTUSB_VendorRequest( ======================================================================== */ -NTSTATUS RTUSB_ResetDevice( - IN PRTMP_ADAPTER pAd) +int RTUSB_ResetDevice(struct rt_rtmp_adapter *pAd) { - NTSTATUS Status = TRUE; + int Status = TRUE; DBGPRINT_RAW(RT_DEBUG_TRACE, ("--->USB_ResetDevice\n")); - //RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS); + /*RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS); */ return Status; } -VOID CMDHandler( - IN PRTMP_ADAPTER pAd) +void CMDHandler(struct rt_rtmp_adapter *pAd) { - PCmdQElmt cmdqelmt; - PUCHAR pData; - NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; -// ULONG Now = 0; - NTSTATUS ntStatus; -// unsigned long IrqFlags; - - while (pAd->CmdQ.size > 0) - { + struct rt_cmdqelmt *cmdqelmt; + u8 *pData; + int NdisStatus = NDIS_STATUS_SUCCESS; +/* unsigned long Now = 0; */ + int ntStatus; +/* unsigned long IrqFlags; */ + + while (pAd && pAd->CmdQ.size > 0) { NdisStatus = NDIS_STATUS_SUCCESS; NdisAcquireSpinLock(&pAd->CmdQLock); @@ -1288,591 +984,1129 @@ VOID CMDHandler( pData = cmdqelmt->buffer; - if(!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) - { - switch (cmdqelmt->command) - { - case CMDTHREAD_CHECK_GPIO: - { - UINT32 data; - - { - // Read GPIO pin2 as Hardware controlled radio state - - RTUSBReadMACRegister( pAd, GPIO_CTRL_CFG, &data); - - if (data & 0x04) - { - pAd->StaCfg.bHwRadio = TRUE; - } - else - { - pAd->StaCfg.bHwRadio = FALSE; - } + if (! + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) + || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { + switch (cmdqelmt->command) { + case CMDTHREAD_CHECK_GPIO: + { + u32 data; - if(pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) - { - pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); - if(pAd->StaCfg.bRadio == TRUE) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("!!! Radio On !!!\n")); - - MlmeRadioOn(pAd); - // Update extra information - pAd->ExtraInfo = EXTRA_INFO_CLEAR; - } - else - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("!!! Radio Off !!!\n")); + { + /* Read GPIO pin2 as Hardware controlled radio state */ + + RTUSBReadMACRegister(pAd, + GPIO_CTRL_CFG, + &data); + + if (data & 0x04) { + pAd->StaCfg.bHwRadio = + TRUE; + } else { + pAd->StaCfg.bHwRadio = + FALSE; + } - MlmeRadioOff(pAd); - // Update extra information - pAd->ExtraInfo = HW_RADIO_OFF; - } + if (pAd->StaCfg.bRadio != + (pAd->StaCfg.bHwRadio + && pAd->StaCfg.bSwRadio)) { + pAd->StaCfg.bRadio = + (pAd->StaCfg. + bHwRadio + && pAd->StaCfg. + bSwRadio); + if (pAd->StaCfg. + bRadio == TRUE) { + DBGPRINT_RAW + (RT_DEBUG_ERROR, + ("!!! Radio On !!!\n")); + + MlmeRadioOn + (pAd); + /* Update extra information */ + pAd->ExtraInfo = + EXTRA_INFO_CLEAR; + } else { + DBGPRINT_RAW + (RT_DEBUG_ERROR, + ("!!! Radio Off !!!\n")); + + MlmeRadioOff + (pAd); + /* Update extra information */ + pAd->ExtraInfo = + HW_RADIO_OFF; } } } - break; - - case CMDTHREAD_QKERIODIC_EXECUT: - { - StaQuickResponeForRateUpExec(NULL, pAd, NULL, NULL); - } - break; + } + break; - case CMDTHREAD_RESET_BULK_OUT: - { - UINT32 MACValue; - UCHAR Index; - int ret=0; - PHT_TX_CONTEXT pHTTXContext; -// RTMP_TX_RING *pTxRing; - unsigned long IrqFlags; - - DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_OUT(ResetPipeid=0x%0x)===>\n", pAd->bulkResetPipeid)); - // All transfers must be aborted or cancelled before attempting to reset the pipe. - //RTUSBCancelPendingBulkOutIRP(pAd); - // Wait 10ms to let previous packet that are already in HW FIFO to clear. by MAXLEE 12-25-2007 - Index = 0; - do - { - RTUSBReadMACRegister(pAd, TXRXQ_PCNT, &MACValue); - if ((MACValue & 0xf00000/*0x800000*/) == 0) - break; - Index++; - RTMPusecDelay(10000); - }while(Index < 100); - MACValue = 0; - RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); - // To prevent Read Register error, we 2nd check the validity. - if ((MACValue & 0xc00000) == 0) - RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); - // To prevent Read Register error, we 3rd check the validity. - if ((MACValue & 0xc00000) == 0) - RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); - MACValue |= 0x80000; - RTUSBWriteMACRegister(pAd, USB_DMA_CFG, MACValue); - - // Wait 1ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007 - RTMPusecDelay(1000); - - MACValue &= (~0x80000); - RTUSBWriteMACRegister(pAd, USB_DMA_CFG, MACValue); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("\tSet 0x2a0 bit19. Clear USB DMA TX path\n")); - - // Wait 5ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007 - //RTMPusecDelay(5000); - - if ((pAd->bulkResetPipeid & BULKOUT_MGMT_RESET_FLAG) == BULKOUT_MGMT_RESET_FLAG) - { - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); - if (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE /* pMLMEContext->bWaitingBulkOut == TRUE */) - { - RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); - } - RTUSBKickBulkOut(pAd); + case CMDTHREAD_QKERIODIC_EXECUT: + { + StaQuickResponeForRateUpExec(NULL, pAd, + NULL, + NULL); + } + break; - DBGPRINT_RAW(RT_DEBUG_TRACE, ("\tTX MGMT RECOVER Done!\n")); + case CMDTHREAD_RESET_BULK_OUT: + { + u32 MACValue; + u8 Index; + int ret = 0; + struct rt_ht_tx_context *pHTTXContext; +/* struct rt_rtmp_tx_ring *pTxRing; */ + unsigned long IrqFlags; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("CmdThread : CMDTHREAD_RESET_BULK_OUT(ResetPipeid=0x%0x)===>\n", + pAd->bulkResetPipeid)); + /* All transfers must be aborted or cancelled before attempting to reset the pipe. */ + /*RTUSBCancelPendingBulkOutIRP(pAd); */ + /* Wait 10ms to let previous packet that are already in HW FIFO to clear. by MAXLEE 12-25-2007 */ + Index = 0; + do { + RTUSBReadMACRegister(pAd, + TXRXQ_PCNT, + &MACValue); + if ((MACValue & 0xf00000 + /*0x800000 */ ) == 0) + break; + Index++; + RTMPusecDelay(10000); + } while (Index < 100); + MACValue = 0; + RTUSBReadMACRegister(pAd, USB_DMA_CFG, + &MACValue); + /* To prevent Read Register error, we 2nd check the validity. */ + if ((MACValue & 0xc00000) == 0) + RTUSBReadMACRegister(pAd, + USB_DMA_CFG, + &MACValue); + /* To prevent Read Register error, we 3rd check the validity. */ + if ((MACValue & 0xc00000) == 0) + RTUSBReadMACRegister(pAd, + USB_DMA_CFG, + &MACValue); + MACValue |= 0x80000; + RTUSBWriteMACRegister(pAd, USB_DMA_CFG, + MACValue); + + /* Wait 1ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007 */ + RTMPusecDelay(1000); + + MACValue &= (~0x80000); + RTUSBWriteMACRegister(pAd, USB_DMA_CFG, + MACValue); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("\tSet 0x2a0 bit19. Clear USB DMA TX path\n")); + + /* Wait 5ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007 */ + /*RTMPusecDelay(5000); */ + + if ((pAd-> + bulkResetPipeid & + BULKOUT_MGMT_RESET_FLAG) == + BULKOUT_MGMT_RESET_FLAG) { + RTMP_CLEAR_FLAG(pAd, + fRTMP_ADAPTER_BULKOUT_RESET); + if (pAd->MgmtRing.TxSwFreeIdx < + MGMT_RING_SIZE + /* pMLMEContext->bWaitingBulkOut == TRUE */ + ) { + RTUSB_SET_BULK_FLAG(pAd, + fRTUSB_BULK_OUT_MLME); } - else - { - pHTTXContext = &(pAd->TxContext[pAd->bulkResetPipeid]); - //NdisAcquireSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); - RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); - if ( pAd->BulkOutPending[pAd->bulkResetPipeid] == FALSE) + RTUSBKickBulkOut(pAd); + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("\tTX MGMT RECOVER Done!\n")); + } else { + pHTTXContext = + &(pAd-> + TxContext[pAd-> + bulkResetPipeid]); + /*NdisAcquireSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); */ + RTMP_INT_LOCK(&pAd-> + BulkOutLock[pAd-> + bulkResetPipeid], + IrqFlags); + if (pAd-> + BulkOutPending[pAd-> + bulkResetPipeid] + == FALSE) { + pAd-> + BulkOutPending[pAd-> + bulkResetPipeid] + = TRUE; + pHTTXContext-> + IRPPending = TRUE; + pAd-> + watchDogTxPendingCnt + [pAd-> + bulkResetPipeid] = + 1; + + /* no matter what, clean the flag */ + RTMP_CLEAR_FLAG(pAd, + fRTMP_ADAPTER_BULKOUT_RESET); + + /*NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); */ + RTMP_INT_UNLOCK(&pAd-> + BulkOutLock + [pAd-> + bulkResetPipeid], + IrqFlags); { - pAd->BulkOutPending[pAd->bulkResetPipeid] = TRUE; - pHTTXContext->IRPPending = TRUE; - pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 1; - - // no matter what, clean the flag - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); - - //NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); - RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); -/*-----------------------------------------------------------------------------------------------*/ -/*-----------------------------------------------------------------------------------------------*/ - { - RTUSBInitHTTxDesc(pAd, pHTTXContext, pAd->bulkResetPipeid, pHTTXContext->BulkOutSize, (usb_complete_t)RTUSBBulkOutDataPacketComplete); - - if((ret = RTUSB_SUBMIT_URB(pHTTXContext->pUrb))!=0) - { - RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); - pAd->BulkOutPending[pAd->bulkResetPipeid] = FALSE; - pHTTXContext->IRPPending = FALSE; - pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 0; - RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); - - DBGPRINT(RT_DEBUG_ERROR, ("CmdThread : CMDTHREAD_RESET_BULK_OUT: Submit Tx URB failed %d\n", ret)); - } - else - { - RTMP_IRQ_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); - DBGPRINT_RAW(RT_DEBUG_TRACE,("\tCMDTHREAD_RESET_BULK_OUT: TxContext[%d]:CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, pending=%d!\n", - pAd->bulkResetPipeid, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, - pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad, pAd->BulkOutPending[pAd->bulkResetPipeid])); - DBGPRINT_RAW(RT_DEBUG_TRACE,("\t\tBulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", - pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther)); - RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("\tCMDTHREAD_RESET_BULK_OUT: Submit Tx DATA URB for failed BulkReq(0x%lx) Done, status=%d!\n", pAd->bulkResetReq[pAd->bulkResetPipeid], pHTTXContext->pUrb->status)); - - } + RTUSBInitHTTxDesc + (pAd, + pHTTXContext, + pAd-> + bulkResetPipeid, + pHTTXContext-> + BulkOutSize, + (usb_complete_t) + RTUSBBulkOutDataPacketComplete); + + if ((ret = + RTUSB_SUBMIT_URB + (pHTTXContext-> + pUrb)) != + 0) { + RTMP_INT_LOCK + (&pAd-> + BulkOutLock + [pAd-> + bulkResetPipeid], + IrqFlags); + pAd-> + BulkOutPending + [pAd-> + bulkResetPipeid] + = + FALSE; + pHTTXContext-> + IRPPending + = + FALSE; + pAd-> + watchDogTxPendingCnt + [pAd-> + bulkResetPipeid] + = 0; + RTMP_INT_UNLOCK + (&pAd-> + BulkOutLock + [pAd-> + bulkResetPipeid], + IrqFlags); + + DBGPRINT + (RT_DEBUG_ERROR, + ("CmdThread : CMDTHREAD_RESET_BULK_OUT: Submit Tx URB failed %d\n", + ret)); + } else { + RTMP_IRQ_LOCK + (&pAd-> + BulkOutLock + [pAd-> + bulkResetPipeid], + IrqFlags); + DBGPRINT_RAW + (RT_DEBUG_TRACE, + ("\tCMDTHREAD_RESET_BULK_OUT: TxContext[%d]:CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, pending=%d!\n", + pAd-> + bulkResetPipeid, + pHTTXContext-> + CurWritePosition, + pHTTXContext-> + NextBulkOutPosition, + pHTTXContext-> + ENextBulkOutPosition, + pHTTXContext-> + bCopySavePad, + pAd-> + BulkOutPending + [pAd-> + bulkResetPipeid])); + DBGPRINT_RAW + (RT_DEBUG_TRACE, + ("\t\tBulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", + pAd-> + BulkOutReq, + pAd-> + BulkOutComplete, + pAd-> + BulkOutCompleteOther)); + RTMP_IRQ_UNLOCK + (&pAd-> + BulkOutLock + [pAd-> + bulkResetPipeid], + IrqFlags); + DBGPRINT_RAW + (RT_DEBUG_TRACE, + ("\tCMDTHREAD_RESET_BULK_OUT: Submit Tx DATA URB for failed BulkReq(0x%lx) Done, status=%d!\n", + pAd-> + bulkResetReq + [pAd-> + bulkResetPipeid], + pHTTXContext-> + pUrb-> + status)); + } } - else - { - //NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); - //RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); - - DBGPRINT_RAW(RT_DEBUG_ERROR, ("CmdThread : TX DATA RECOVER FAIL for BulkReq(0x%lx) because BulkOutPending[%d] is TRUE!\n", pAd->bulkResetReq[pAd->bulkResetPipeid], pAd->bulkResetPipeid)); - if (pAd->bulkResetPipeid == 0) - { - UCHAR pendingContext = 0; - PHT_TX_CONTEXT pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[pAd->bulkResetPipeid ]); - PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa); - PTX_CONTEXT pNULLContext = (PTX_CONTEXT)(&pAd->PsPollContext); - PTX_CONTEXT pPsPollContext = (PTX_CONTEXT)(&pAd->NullContext); - - if (pHTTXContext->IRPPending) - pendingContext |= 1; - else if (pMLMEContext->IRPPending) - pendingContext |= 2; - else if (pNULLContext->IRPPending) - pendingContext |= 4; - else if (pPsPollContext->IRPPending) - pendingContext |= 8; - else - pendingContext = 0; - - DBGPRINT_RAW(RT_DEBUG_ERROR, ("\tTX Occupied by %d!\n", pendingContext)); - } - - // no matter what, clean the flag - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); - - RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + } else { + /*NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); */ + /*RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); */ + + DBGPRINT_RAW + (RT_DEBUG_ERROR, + ("CmdThread : TX DATA RECOVER FAIL for BulkReq(0x%lx) because BulkOutPending[%d] is TRUE!\n", + pAd-> + bulkResetReq[pAd-> + bulkResetPipeid], + pAd-> + bulkResetPipeid)); + if (pAd-> + bulkResetPipeid == + 0) { + u8 + pendingContext + = 0; + struct rt_ht_tx_context * + pHTTXContext + = + (struct rt_ht_tx_context *) + (&pAd-> + TxContext + [pAd-> + bulkResetPipeid]); + struct rt_tx_context * + pMLMEContext + = + (struct rt_tx_context *) + (pAd-> + MgmtRing. + Cell[pAd-> + MgmtRing. + TxDmaIdx]. + AllocVa); + struct rt_tx_context * + pNULLContext + = + (struct rt_tx_context *) + (&pAd-> + PsPollContext); + struct rt_tx_context * + pPsPollContext + = + (struct rt_tx_context *) + (&pAd-> + NullContext); + + if (pHTTXContext->IRPPending) + pendingContext + |= + 1; + else if + (pMLMEContext-> + IRPPending) + pendingContext + |= + 2; + else if + (pNULLContext-> + IRPPending) + pendingContext + |= + 4; + else if + (pPsPollContext-> + IRPPending) + pendingContext + |= + 8; + else + pendingContext + = 0; - RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << pAd->bulkResetPipeid)); + DBGPRINT_RAW + (RT_DEBUG_ERROR, + ("\tTX Occupied by %d!\n", + pendingContext)); } - - RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); - //RTUSBKickBulkOut(pAd); + /* no matter what, clean the flag */ + RTMP_CLEAR_FLAG(pAd, + fRTMP_ADAPTER_BULKOUT_RESET); + + RTMP_INT_UNLOCK(&pAd-> + BulkOutLock + [pAd-> + bulkResetPipeid], + IrqFlags); + + RTUSB_SET_BULK_FLAG(pAd, + (fRTUSB_BULK_OUT_DATA_NORMAL + << + pAd-> + bulkResetPipeid)); } + RTMPDeQueuePacket(pAd, FALSE, + NUM_OF_TX_RING, + MAX_TX_PROCESS); + /*RTUSBKickBulkOut(pAd); */ } - /* - // Don't cancel BULKIN. - while ((atomic_read(&pAd->PendingRx) > 0) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) - { - if (atomic_read(&pAd->PendingRx) > 0) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkIn IRP Pending!!cancel it!\n")); - RTUSBCancelPendingBulkInIRP(pAd); - } - RTMPusecDelay(100000); - } - if ((atomic_read(&pAd->PendingRx) == 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) - { - UCHAR i; - RTUSBRxPacket(pAd); - pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index - pAd->NextRxBulkInIndex = 0; // Rx Bulk pointer - for (i = 0; i < (RX_RING_SIZE); i++) - { - PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); + } + /* + // Don't cancel BULKIN. + while ((atomic_read(&pAd->PendingRx) > 0) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + if (atomic_read(&pAd->PendingRx) > 0) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkIn IRP Pending!!cancel it!\n")); + RTUSBCancelPendingBulkInIRP(pAd); + } + RTMPusecDelay(100000); + } + + if ((atomic_read(&pAd->PendingRx) == 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) + { + u8 i; + RTUSBRxPacket(pAd); + pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index + pAd->NextRxBulkInIndex = 0; // Rx Bulk pointer + for (i = 0; i < (RX_RING_SIZE); i++) + { + struct rt_rx_context *pRxContext = &(pAd->RxContext[i]); + + pRxContext->pAd = pAd; + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pRxContext->Readable = FALSE; + pRxContext->ReorderInUse = FALSE; + + } + RTUSBBulkReceive(pAd); + DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTUSBBulkReceive\n")); + } */ + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("CmdThread : CMDTHREAD_RESET_BULK_OUT<===\n")); + break; - pRxContext->pAd = pAd; - pRxContext->InUse = FALSE; - pRxContext->IRPPending = FALSE; - pRxContext->Readable = FALSE; - pRxContext->ReorderInUse = FALSE; + case CMDTHREAD_RESET_BULK_IN: + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("CmdThread : CMDTHREAD_RESET_BULK_IN === >\n")); - } - RTUSBBulkReceive(pAd); - DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTUSBBulkReceive\n")); - }*/ - DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_OUT<===\n")); - break; + /* All transfers must be aborted or cancelled before attempting to reset the pipe. */ + { + u32 MACValue; - case CMDTHREAD_RESET_BULK_IN: - DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN === >\n")); - - // All transfers must be aborted or cancelled before attempting to reset the pipe. { - UINT32 MACValue; -/*-----------------------------------------------------------------------------------------------*/ -/*-----------------------------------------------------------------------------------------------*/ - { - //while ((atomic_read(&pAd->PendingRx) > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) - if((pAd->PendingRx > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + /*while ((atomic_read(&pAd->PendingRx) > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) */ + if ((pAd->PendingRx > 0) + && + (!RTMP_TEST_FLAG + (pAd, + fRTMP_ADAPTER_NIC_NOT_EXIST))) { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkIn IRP Pending!!!\n")); - RTUSBCancelPendingBulkInIRP(pAd); + DBGPRINT_RAW + (RT_DEBUG_ERROR, + ("BulkIn IRP Pending!!!\n")); + RTUSBCancelPendingBulkInIRP + (pAd); RTMPusecDelay(100000); pAd->PendingRx = 0; } - } - - // Wait 10ms before reading register. - RTMPusecDelay(10000); - ntStatus = RTUSBReadMACRegister(pAd, MAC_CSR0, &MACValue); - - if ((NT_SUCCESS(ntStatus) == TRUE) && - (!(RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF | - fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))))) - { - UCHAR i; + } - if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF | - fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))) + /* Wait 10ms before reading register. */ + RTMPusecDelay(10000); + ntStatus = + RTUSBReadMACRegister(pAd, MAC_CSR0, + &MACValue); + + if ((NT_SUCCESS(ntStatus) == TRUE) && + (!(RTMP_TEST_FLAG + (pAd, + (fRTMP_ADAPTER_RESET_IN_PROGRESS + | fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_HALT_IN_PROGRESS + | + fRTMP_ADAPTER_NIC_NOT_EXIST))))) + { + u8 i; + + if (RTMP_TEST_FLAG + (pAd, + (fRTMP_ADAPTER_RESET_IN_PROGRESS + | fRTMP_ADAPTER_RADIO_OFF + | + fRTMP_ADAPTER_HALT_IN_PROGRESS + | + fRTMP_ADAPTER_NIC_NOT_EXIST))) + break; + pAd->NextRxBulkInPosition = + pAd->RxContext[pAd-> + NextRxBulkInIndex]. + BulkInOffset; + DBGPRINT(RT_DEBUG_TRACE, + ("BULK_IN_RESET: NBIIdx=0x%x,NBIRIdx=0x%x, BIRPos=0x%lx. BIReq=x%lx, BIComplete=0x%lx, BICFail0x%lx\n", + pAd-> + NextRxBulkInIndex, + pAd-> + NextRxBulkInReadIndex, + pAd-> + NextRxBulkInPosition, + pAd->BulkInReq, + pAd->BulkInComplete, + pAd-> + BulkInCompleteFail)); + for (i = 0; i < RX_RING_SIZE; + i++) { + DBGPRINT(RT_DEBUG_TRACE, + ("\tRxContext[%d]: IRPPending=%d, InUse=%d, Readable=%d!\n", + i, + pAd-> + RxContext[i]. + IRPPending, + pAd-> + RxContext[i]. + InUse, + pAd-> + RxContext[i]. + Readable)); + } + /* + + DBGPRINT_RAW(RT_DEBUG_ERROR, ("==========================================\n")); + + pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index + pAd->NextRxBulkInIndex = 0; // Rx Bulk pointer + for (i = 0; i < (RX_RING_SIZE); i++) + { + struct rt_rx_context *pRxContext = &(pAd->RxContext[i]); + + pRxContext->pAd = pAd; + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pRxContext->Readable = FALSE; + pRxContext->ReorderInUse = FALSE; + + } */ + RTMP_CLEAR_FLAG(pAd, + fRTMP_ADAPTER_BULKIN_RESET); + for (i = 0; + i < + pAd->CommonCfg. + NumOfBulkInIRP; i++) { + /*RTUSBBulkReceive(pAd); */ + struct rt_rx_context *pRxContext; + PURB pUrb; + int ret = 0; + unsigned long IrqFlags; + + RTMP_IRQ_LOCK(&pAd-> + BulkInLock, + IrqFlags); + pRxContext = + &(pAd-> + RxContext[pAd-> + NextRxBulkInIndex]); + if ((pAd->PendingRx > 0) + || (pRxContext-> + Readable == + TRUE) + || (pRxContext-> + InUse == + TRUE)) { + RTMP_IRQ_UNLOCK + (&pAd-> + BulkInLock, + IrqFlags); break; - pAd->NextRxBulkInPosition = pAd->RxContext[pAd->NextRxBulkInIndex].BulkInOffset; - DBGPRINT(RT_DEBUG_TRACE, ("BULK_IN_RESET: NBIIdx=0x%x,NBIRIdx=0x%x, BIRPos=0x%lx. BIReq=x%lx, BIComplete=0x%lx, BICFail0x%lx\n", - pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex, pAd->NextRxBulkInPosition, pAd->BulkInReq, pAd->BulkInComplete, pAd->BulkInCompleteFail)); - for (i = 0; i < RX_RING_SIZE; i++) - { - DBGPRINT(RT_DEBUG_TRACE, ("\tRxContext[%d]: IRPPending=%d, InUse=%d, Readable=%d!\n" - , i, pAd->RxContext[i].IRPPending, pAd->RxContext[i].InUse, pAd->RxContext[i].Readable)); } - /* - - DBGPRINT_RAW(RT_DEBUG_ERROR, ("==========================================\n")); - - pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index - pAd->NextRxBulkInIndex = 0; // Rx Bulk pointer - for (i = 0; i < (RX_RING_SIZE); i++) - { - PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); - - pRxContext->pAd = pAd; - pRxContext->InUse = FALSE; - pRxContext->IRPPending = FALSE; - pRxContext->Readable = FALSE; - pRxContext->ReorderInUse = FALSE; - - }*/ - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); - for (i = 0; i < pAd->CommonCfg.NumOfBulkInIRP; i++) - { - //RTUSBBulkReceive(pAd); - PRX_CONTEXT pRxContext; - PURB pUrb; - int ret = 0; - unsigned long IrqFlags; - - - RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); - pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]); - if ((pAd->PendingRx > 0) || (pRxContext->Readable == TRUE) || (pRxContext->InUse == TRUE)) - { - RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); - break; - } - pRxContext->InUse = TRUE; - pRxContext->IRPPending = TRUE; - pAd->PendingRx++; - pAd->BulkInReq++; - RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); - - // Init Rx context descriptor - RTUSBInitRxDesc(pAd, pRxContext); - pUrb = pRxContext->pUrb; - if ((ret = RTUSB_SUBMIT_URB(pUrb))!=0) - { // fail - - RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); - pRxContext->InUse = FALSE; - pRxContext->IRPPending = FALSE; - pAd->PendingRx--; - pAd->BulkInReq--; - RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); - DBGPRINT(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB failed(%d), status=%d\n", ret, pUrb->status)); - } - else - { // success - DBGPRINT_RAW(RT_DEBUG_TRACE, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB Done, status=%d!\n", pUrb->status)); - ASSERT((pRxContext->InUse == pRxContext->IRPPending)); - } - } - - } - else - { - // Card must be removed - if (NT_SUCCESS(ntStatus) != TRUE) - { - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); - DBGPRINT_RAW(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Read Register Failed!Card must be removed!!\n\n")); + pRxContext->InUse = + TRUE; + pRxContext->IRPPending = + TRUE; + pAd->PendingRx++; + pAd->BulkInReq++; + RTMP_IRQ_UNLOCK(&pAd-> + BulkInLock, + IrqFlags); + + /* Init Rx context descriptor */ + RTUSBInitRxDesc(pAd, + pRxContext); + pUrb = pRxContext->pUrb; + if ((ret = RTUSB_SUBMIT_URB(pUrb)) != 0) { /* fail */ + + RTMP_IRQ_LOCK + (&pAd-> + BulkInLock, + IrqFlags); + pRxContext-> + InUse = + FALSE; + pRxContext-> + IRPPending = + FALSE; + pAd-> + PendingRx--; + pAd-> + BulkInReq--; + RTMP_IRQ_UNLOCK + (&pAd-> + BulkInLock, + IrqFlags); + DBGPRINT + (RT_DEBUG_ERROR, + ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB failed(%d), status=%d\n", + ret, + pUrb-> + status)); + } else { /* success */ + /*DBGPRINT(RT_DEBUG_TRACE, ("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", */ + /* pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex)); */ + DBGPRINT_RAW + (RT_DEBUG_TRACE, + ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB Done, status=%d!\n", + pUrb-> + status)); + ASSERT((pRxContext->InUse == pRxContext->IRPPending)); } - else - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Cannot do bulk in because flags(0x%lx) on !\n", pAd->Flags)); } - } - } - DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN <===\n")); - break; - case CMDTHREAD_SET_ASIC_WCID: - { - RT_SET_ASIC_WCID SetAsicWcid; - USHORT offset; - UINT32 MACValue, MACRValue = 0; - SetAsicWcid = *((PRT_SET_ASIC_WCID)(pData)); - - if (SetAsicWcid.WCID >= MAX_LEN_OF_MAC_TABLE) - return; - - offset = MAC_WCID_BASE + ((UCHAR)SetAsicWcid.WCID)*HW_WCID_ENTRY_SIZE; - - DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_SET_ASIC_WCID : WCID = %ld, SetTid = %lx, DeleteTid = %lx.\n", SetAsicWcid.WCID, SetAsicWcid.SetTid, SetAsicWcid.DeleteTid)); - MACValue = (pAd->MacTab.Content[SetAsicWcid.WCID].Addr[3]<<24)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[2]<<16)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[1]<<8)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[0]); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("1-MACValue= %x,\n", MACValue)); - RTUSBWriteMACRegister(pAd, offset, MACValue); - // Read bitmask - RTUSBReadMACRegister(pAd, offset+4, &MACRValue); - if ( SetAsicWcid.DeleteTid != 0xffffffff) - MACRValue &= (~SetAsicWcid.DeleteTid); - if (SetAsicWcid.SetTid != 0xffffffff) - MACRValue |= (SetAsicWcid.SetTid); - MACRValue &= 0xffff0000; - - MACValue = (pAd->MacTab.Content[SetAsicWcid.WCID].Addr[5]<<8)+pAd->MacTab.Content[SetAsicWcid.WCID].Addr[4]; - MACValue |= MACRValue; - RTUSBWriteMACRegister(pAd, offset+4, MACValue); - - DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-MACValue= %x,\n", MACValue)); + } else { + /* Card must be removed */ + if (NT_SUCCESS(ntStatus) != + TRUE) { + RTMP_SET_FLAG(pAd, + fRTMP_ADAPTER_NIC_NOT_EXIST); + DBGPRINT_RAW + (RT_DEBUG_ERROR, + ("CMDTHREAD_RESET_BULK_IN: Read Register Failed!Card must be removed!!\n\n")); + } else { + DBGPRINT_RAW + (RT_DEBUG_ERROR, + ("CMDTHREAD_RESET_BULK_IN: Cannot do bulk in because flags(0x%lx) on !\n", + pAd->Flags)); + } } - break; + } + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("CmdThread : CMDTHREAD_RESET_BULK_IN <===\n")); + break; - case CMDTHREAD_SET_ASIC_WCID_CIPHER: - { - RT_SET_ASIC_WCID_ATTRI SetAsicWcidAttri; - USHORT offset; - UINT32 MACRValue = 0; - SHAREDKEY_MODE_STRUC csr1; - SetAsicWcidAttri = *((PRT_SET_ASIC_WCID_ATTRI)(pData)); - - if (SetAsicWcidAttri.WCID >= MAX_LEN_OF_MAC_TABLE) - return; - - offset = MAC_WCID_ATTRIBUTE_BASE + ((UCHAR)SetAsicWcidAttri.WCID)*HW_WCID_ATTRI_SIZE; - - DBGPRINT_RAW(RT_DEBUG_TRACE, ("Cmd : CMDTHREAD_SET_ASIC_WCID_CIPHER : WCID = %ld, Cipher = %lx.\n", SetAsicWcidAttri.WCID, SetAsicWcidAttri.Cipher)); - // Read bitmask - RTUSBReadMACRegister(pAd, offset, &MACRValue); - MACRValue = 0; - MACRValue |= (((UCHAR)SetAsicWcidAttri.Cipher) << 1); - - RTUSBWriteMACRegister(pAd, offset, MACRValue); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-offset = %x , MACValue= %x,\n", offset, MACRValue)); - - offset = PAIRWISE_IVEIV_TABLE_BASE + ((UCHAR)SetAsicWcidAttri.WCID)*HW_IVEIV_ENTRY_SIZE; - MACRValue = 0; - if ( (SetAsicWcidAttri.Cipher <= CIPHER_WEP128)) - MACRValue |= ( pAd->StaCfg.DefaultKeyId << 30); - else - MACRValue |= (0x20000000); - RTUSBWriteMACRegister(pAd, offset, MACRValue); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-offset = %x , MACValue= %x,\n", offset, MACRValue)); - - // - // Update cipher algorithm. WSTA always use BSS0 - // - // for adhoc mode only ,because wep status slow than add key, when use zero config - if (pAd->StaCfg.BssType == BSS_ADHOC ) - { - offset = MAC_WCID_ATTRIBUTE_BASE; + case CMDTHREAD_SET_ASIC_WCID: + { + struct rt_set_asic_wcid SetAsicWcid; + u16 offset; + u32 MACValue, MACRValue = 0; + SetAsicWcid = + *((struct rt_set_asic_wcid *)(pData)); + + if (SetAsicWcid.WCID >= + MAX_LEN_OF_MAC_TABLE) + return; + + offset = + MAC_WCID_BASE + + ((u8)SetAsicWcid.WCID) * + HW_WCID_ENTRY_SIZE; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("CmdThread : CMDTHREAD_SET_ASIC_WCID : WCID = %ld, SetTid = %lx, DeleteTid = %lx.\n", + SetAsicWcid.WCID, + SetAsicWcid.SetTid, + SetAsicWcid.DeleteTid)); + MACValue = + (pAd->MacTab. + Content[SetAsicWcid.WCID]. + Addr[3] << 24) + + (pAd->MacTab. + Content[SetAsicWcid.WCID]. + Addr[2] << 16) + + (pAd->MacTab. + Content[SetAsicWcid.WCID]. + Addr[1] << 8) + + (pAd->MacTab. + Content[SetAsicWcid.WCID].Addr[0]); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("1-MACValue= %x,\n", + MACValue)); + RTUSBWriteMACRegister(pAd, offset, + MACValue); + /* Read bitmask */ + RTUSBReadMACRegister(pAd, offset + 4, + &MACRValue); + if (SetAsicWcid.DeleteTid != 0xffffffff) + MACRValue &= + (~SetAsicWcid.DeleteTid); + if (SetAsicWcid.SetTid != 0xffffffff) + MACRValue |= + (SetAsicWcid.SetTid); + MACRValue &= 0xffff0000; + + MACValue = + (pAd->MacTab. + Content[SetAsicWcid.WCID]. + Addr[5] << 8) + + pAd->MacTab.Content[SetAsicWcid. + WCID].Addr[4]; + MACValue |= MACRValue; + RTUSBWriteMACRegister(pAd, offset + 4, + MACValue); + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("2-MACValue= %x,\n", + MACValue)); + } + break; - RTUSBReadMACRegister(pAd, offset, &MACRValue); - MACRValue &= (~0xe); - MACRValue |= (((UCHAR)SetAsicWcidAttri.Cipher) << 1); + case CMDTHREAD_SET_ASIC_WCID_CIPHER: + { + struct rt_set_asic_wcid_attri SetAsicWcidAttri; + u16 offset; + u32 MACRValue = 0; + SHAREDKEY_MODE_STRUC csr1; + SetAsicWcidAttri = + *((struct rt_set_asic_wcid_attri *) + (pData)); + + if (SetAsicWcidAttri.WCID >= + MAX_LEN_OF_MAC_TABLE) + return; + + offset = + MAC_WCID_ATTRIBUTE_BASE + + ((u8)SetAsicWcidAttri.WCID) * + HW_WCID_ATTRI_SIZE; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("Cmd : CMDTHREAD_SET_ASIC_WCID_CIPHER : WCID = %ld, Cipher = %lx.\n", + SetAsicWcidAttri.WCID, + SetAsicWcidAttri.Cipher)); + /* Read bitmask */ + RTUSBReadMACRegister(pAd, offset, + &MACRValue); + MACRValue = 0; + MACRValue |= + (((u8)SetAsicWcidAttri. + Cipher) << 1); + + RTUSBWriteMACRegister(pAd, offset, + MACRValue); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("2-offset = %x , MACValue= %x,\n", + offset, MACRValue)); + + offset = + PAIRWISE_IVEIV_TABLE_BASE + + ((u8)SetAsicWcidAttri.WCID) * + HW_IVEIV_ENTRY_SIZE; + MACRValue = 0; + if ((SetAsicWcidAttri.Cipher <= + CIPHER_WEP128)) + MACRValue |= + (pAd->StaCfg. + DefaultKeyId << 30); + else + MACRValue |= (0x20000000); + RTUSBWriteMACRegister(pAd, offset, + MACRValue); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("2-offset = %x , MACValue= %x,\n", + offset, MACRValue)); + + /* */ + /* Update cipher algorithm. WSTA always use BSS0 */ + /* */ + /* for adhoc mode only ,because wep status slow than add key, when use zero config */ + if (pAd->StaCfg.BssType == BSS_ADHOC) { + offset = + MAC_WCID_ATTRIBUTE_BASE; + + RTUSBReadMACRegister(pAd, + offset, + &MACRValue); + MACRValue &= (~0xe); + MACRValue |= + (((u8)SetAsicWcidAttri. + Cipher) << 1); + + RTUSBWriteMACRegister(pAd, + offset, + MACRValue); + + /*Update group key cipher,,because wep status slow than add key, when use zero config */ + RTUSBReadMACRegister(pAd, + SHARED_KEY_MODE_BASE + + + 4 * (0 / + 2), + &csr1. + word); + + csr1.field.Bss0Key0CipherAlg = + SetAsicWcidAttri.Cipher; + csr1.field.Bss0Key1CipherAlg = + SetAsicWcidAttri.Cipher; + + RTUSBWriteMACRegister(pAd, + SHARED_KEY_MODE_BASE + + + 4 * (0 / + 2), + csr1. + word); + } + } + break; - RTUSBWriteMACRegister(pAd, offset, MACRValue); +/*Benson modified for USB interface, avoid in interrupt when write key, 20080724 --> */ + case RT_CMD_SET_KEY_TABLE: /*General call for AsicAddPairwiseKeyEntry() */ + { + struct rt_add_pairwise_key_entry KeyInfo; + KeyInfo = + *((struct rt_add_pairwise_key_entry *) + (pData)); + AsicAddPairwiseKeyEntry(pAd, + KeyInfo.MacAddr, + (u8)KeyInfo. + MacTabMatchWCID, + &KeyInfo. + CipherKey); + } + break; - //Update group key cipher,,because wep status slow than add key, when use zero config - RTUSBReadMACRegister(pAd, SHARED_KEY_MODE_BASE+4*(0/2), &csr1.word); + case RT_CMD_SET_RX_WCID_TABLE: /*General call for RTMPAddWcidAttributeEntry() */ + { + struct rt_mac_table_entry *pEntry; + u8 KeyIdx = 0; + u8 CipherAlg = CIPHER_NONE; + u8 ApIdx = BSS0; + + pEntry = (struct rt_mac_table_entry *)(pData); + + RTMPAddWcidAttributeEntry(pAd, + ApIdx, + KeyIdx, + CipherAlg, + pEntry); + } + break; +/*Benson modified for USB interface, avoid in interrupt when write key, 20080724 <-- */ - csr1.field.Bss0Key0CipherAlg = SetAsicWcidAttri.Cipher; - csr1.field.Bss0Key1CipherAlg = SetAsicWcidAttri.Cipher; + case CMDTHREAD_SET_CLIENT_MAC_ENTRY: + { + struct rt_mac_table_entry *pEntry; + pEntry = (struct rt_mac_table_entry *)pData; - RTUSBWriteMACRegister(pAd, SHARED_KEY_MODE_BASE+4*(0/2), csr1.word); + { + AsicRemovePairwiseKeyEntry(pAd, + pEntry-> + apidx, + (u8) + pEntry-> + Aid); + if ((pEntry->AuthMode <= + Ndis802_11AuthModeAutoSwitch) + && (pEntry->WepStatus == + Ndis802_11Encryption1Enabled)) + { + u32 uIV = 1; + u8 *ptr; + + ptr = (u8 *)& uIV; + *(ptr + 3) = + (pAd->StaCfg. + DefaultKeyId << 6); + AsicUpdateWCIDIVEIV(pAd, + pEntry-> + Aid, + uIV, + 0); + AsicUpdateWCIDAttribute + (pAd, pEntry->Aid, + BSS0, + pAd-> + SharedKey[BSS0] + [pAd->StaCfg. + DefaultKeyId]. + CipherAlg, FALSE); + } else if (pEntry->AuthMode == + Ndis802_11AuthModeWPANone) + { + u32 uIV = 1; + u8 *ptr; + + ptr = (u8 *)& uIV; + *(ptr + 3) = + (pAd->StaCfg. + DefaultKeyId << 6); + AsicUpdateWCIDIVEIV(pAd, + pEntry-> + Aid, + uIV, + 0); + AsicUpdateWCIDAttribute + (pAd, pEntry->Aid, + BSS0, + pAd-> + SharedKey[BSS0] + [pAd->StaCfg. + DefaultKeyId]. + CipherAlg, FALSE); + } else { + /* */ + /* Other case, disable engine. */ + /* Don't worry WPA key, we will add WPA Key after 4-Way handshaking. */ + /* */ + u16 offset; + offset = + MAC_WCID_ATTRIBUTE_BASE + + + (pEntry->Aid * + HW_WCID_ATTRI_SIZE); + /* RX_PKEY_MODE:0 for no security; RX_KEY_TAB:0 for shared key table; BSS_IDX:0 */ + RTUSBWriteMACRegister + (pAd, offset, 0); } } - break; - case CMDTHREAD_SET_CLIENT_MAC_ENTRY: - { - MAC_TABLE_ENTRY *pEntry; - pEntry = (MAC_TABLE_ENTRY *)pData; - { - AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)pEntry->Aid); - if ((pEntry->AuthMode <= Ndis802_11AuthModeAutoSwitch) && (pEntry->WepStatus == Ndis802_11Encryption1Enabled)) - { - UINT32 uIV = 0; - PUCHAR ptr; + AsicUpdateRxWCIDTable(pAd, pEntry->Aid, + pEntry->Addr); + DBGPRINT(RT_DEBUG_TRACE, + ("UpdateRxWCIDTable(): Aid=%d, Addr=%02x:%02x:%02x:%02x:%02x:%02x!\n", + pEntry->Aid, pEntry->Addr[0], + pEntry->Addr[1], + pEntry->Addr[2], + pEntry->Addr[3], + pEntry->Addr[4], + pEntry->Addr[5])); + } + break; - ptr = (PUCHAR) &uIV; - *(ptr + 3) = (pAd->StaCfg.DefaultKeyId << 6); - AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, uIV, 0); - AsicUpdateWCIDAttribute(pAd, pEntry->Aid, BSS0, pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, FALSE); +/* add by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet */ + case CMDTHREAD_UPDATE_PROTECT: + { + AsicUpdateProtect(pAd, 0, + (ALLN_SETPROTECT), + TRUE, 0); + } + break; +/* end johnli */ + + case OID_802_11_ADD_WEP: + { + u32 i; + u32 KeyIdx; + struct rt_ndis_802_11_wep *pWepKey; + + DBGPRINT(RT_DEBUG_TRACE, + ("CmdThread::OID_802_11_ADD_WEP \n")); + + pWepKey = (struct rt_ndis_802_11_wep *)pData; + KeyIdx = pWepKey->KeyIndex & 0x0fffffff; + + /* it is a shared key */ + if ((KeyIdx >= 4) + || ((pWepKey->KeyLength != 5) + && (pWepKey->KeyLength != + 13))) { + NdisStatus = + NDIS_STATUS_INVALID_DATA; + DBGPRINT(RT_DEBUG_ERROR, + ("CmdThread::OID_802_11_ADD_WEP, INVALID_DATA!!\n")); + } else { + u8 CipherAlg; + pAd->SharedKey[BSS0][KeyIdx]. + KeyLen = + (u8)pWepKey->KeyLength; + NdisMoveMemory(pAd-> + SharedKey[BSS0] + [KeyIdx].Key, + &pWepKey-> + KeyMaterial, + pWepKey-> + KeyLength); + CipherAlg = + (pAd-> + SharedKey[BSS0][KeyIdx]. + KeyLen == + 5) ? CIPHER_WEP64 : + CIPHER_WEP128; + + /* */ + /* Change the WEP cipher to CKIP cipher if CKIP KP on. */ + /* Funk UI or Meetinghouse UI will add ckip key from this path. */ + /* */ + + if (pAd->OpMode == OPMODE_STA) { + pAd->MacTab. + Content[BSSID_WCID]. + PairwiseKey. + CipherAlg = + pAd-> + SharedKey[BSS0] + [KeyIdx].CipherAlg; + pAd->MacTab. + Content[BSSID_WCID]. + PairwiseKey.KeyLen = + pAd-> + SharedKey[BSS0] + [KeyIdx].KeyLen; + } + pAd->SharedKey[BSS0][KeyIdx]. + CipherAlg = CipherAlg; + if (pWepKey-> + KeyIndex & 0x80000000) { + /* Default key for tx (shared key) */ + u8 IVEIV[8]; + u32 WCIDAttri, Value; + u16 offset, offset2; + NdisZeroMemory(IVEIV, + 8); + pAd->StaCfg. + DefaultKeyId = + (u8)KeyIdx; + /* Add BSSID to WCTable. because this is Tx wep key. */ + /* WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:1=PAIRWISE KEY, BSSIdx is 0 */ + WCIDAttri = + (CipherAlg << 1) | + SHAREDKEYTABLE; + + offset = + MAC_WCID_ATTRIBUTE_BASE + + + (BSSID_WCID * + HW_WCID_ATTRI_SIZE); + RTUSBWriteMACRegister + (pAd, offset, + WCIDAttri); + /* 1. IV/EIV */ + /* Specify key index to find shared key. */ + IVEIV[3] = (u8)(KeyIdx << 6); /*WEP Eiv bit off. groupkey index is not 0 */ + offset = + PAIRWISE_IVEIV_TABLE_BASE + + + (BSS0Mcast_WCID * + HW_IVEIV_ENTRY_SIZE); + offset2 = + PAIRWISE_IVEIV_TABLE_BASE + + + (BSSID_WCID * + HW_IVEIV_ENTRY_SIZE); + for (i = 0; i < 8;) { + Value = + IVEIV[i]; + Value += + (IVEIV + [i + + 1] << 8); + Value += + (IVEIV + [i + + 2] << 16); + Value += + (IVEIV + [i + + 3] << 24); + RTUSBWriteMACRegister + (pAd, + offset + i, + Value); + RTUSBWriteMACRegister + (pAd, + offset2 + + i, Value); + i += 4; } - else if (pEntry->AuthMode == Ndis802_11AuthModeWPANone) - { - UINT32 uIV = 0; - PUCHAR ptr; - ptr = (PUCHAR) &uIV; - *(ptr + 3) = (pAd->StaCfg.DefaultKeyId << 6); - AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, uIV, 0); - AsicUpdateWCIDAttribute(pAd, pEntry->Aid, BSS0, pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, FALSE); - } - else - { - // - // Other case, disable engine. - // Don't worry WPA key, we will add WPA Key after 4-Way handshaking. - // - USHORT offset; - offset = MAC_WCID_ATTRIBUTE_BASE + (pEntry->Aid * HW_WCID_ATTRI_SIZE); - // RX_PKEY_MODE:0 for no security; RX_KEY_TAB:0 for shared key table; BSS_IDX:0 - RTUSBWriteMACRegister(pAd, offset, 0); - } - } + /* 2. WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:use share key, BSSIdx is 0 */ + WCIDAttri = + (pAd-> + SharedKey[BSS0] + [KeyIdx]. + CipherAlg << 1) | + SHAREDKEYTABLE; + offset = + MAC_WCID_ATTRIBUTE_BASE + + + (BSS0Mcast_WCID * + HW_WCID_ATTRI_SIZE); + DBGPRINT(RT_DEBUG_TRACE, + ("BSS0Mcast_WCID : offset = %x, WCIDAttri = %x\n", + offset, + WCIDAttri)); + RTUSBWriteMACRegister + (pAd, offset, + WCIDAttri); - AsicUpdateRxWCIDTable(pAd, pEntry->Aid, pEntry->Addr); - printk("UpdateRxWCIDTable(): Aid=%d, Addr=%02x:%02x:%02x:%02x:%02x:%02x!\n", pEntry->Aid, - pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); - } - break; - case CMDTHREAD_UPDATE_PROTECT: - { - AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT), TRUE, 0); + } + AsicAddSharedKeyEntry(pAd, BSS0, + (u8) + KeyIdx, + CipherAlg, + pWepKey-> + KeyMaterial, + NULL, + NULL); + DBGPRINT(RT_DEBUG_TRACE, + ("CmdThread::OID_802_11_ADD_WEP (KeyIdx=%d, Len=%d-byte)\n", + KeyIdx, + pWepKey->KeyLength)); } - break; - case OID_802_11_ADD_WEP: - { - UINT i; - UINT32 KeyIdx; - PNDIS_802_11_WEP pWepKey; - - DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::OID_802_11_ADD_WEP \n")); + } + break; - pWepKey = (PNDIS_802_11_WEP)pData; - KeyIdx = pWepKey->KeyIndex & 0x0fffffff; + case CMDTHREAD_802_11_COUNTER_MEASURE: + break; - // it is a shared key - if ((KeyIdx >= 4) || ((pWepKey->KeyLength != 5) && (pWepKey->KeyLength != 13))) - { - NdisStatus = NDIS_STATUS_INVALID_DATA; - DBGPRINT(RT_DEBUG_ERROR, ("CmdThread::OID_802_11_ADD_WEP, INVALID_DATA!!\n")); - } - else - { - UCHAR CipherAlg; - pAd->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength; - NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength); - CipherAlg = (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 5)? CIPHER_WEP64 : CIPHER_WEP128; - - // - // Change the WEP cipher to CKIP cipher if CKIP KP on. - // Funk UI or Meetinghouse UI will add ckip key from this path. - // - - if (pAd->OpMode == OPMODE_STA) - { - pAd->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; - pAd->MacTab.Content[BSSID_WCID].PairwiseKey.KeyLen = pAd->SharedKey[BSS0][KeyIdx].KeyLen; - } - pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CipherAlg; - if (pWepKey->KeyIndex & 0x80000000) - { - // Default key for tx (shared key) - UCHAR IVEIV[8]; - UINT32 WCIDAttri, Value; - USHORT offset, offset2; - NdisZeroMemory(IVEIV, 8); - pAd->StaCfg.DefaultKeyId = (UCHAR) KeyIdx; - // Add BSSID to WCTable. because this is Tx wep key. - // WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:1=PAIRWISE KEY, BSSIdx is 0 - WCIDAttri = (CipherAlg<<1)|SHAREDKEYTABLE; - - offset = MAC_WCID_ATTRIBUTE_BASE + (BSSID_WCID* HW_WCID_ATTRI_SIZE); - RTUSBWriteMACRegister(pAd, offset, WCIDAttri); - // 1. IV/EIV - // Specify key index to find shared key. - IVEIV[3] = (UCHAR)(KeyIdx<< 6); //WEP Eiv bit off. groupkey index is not 0 - offset = PAIRWISE_IVEIV_TABLE_BASE + (BSS0Mcast_WCID * HW_IVEIV_ENTRY_SIZE); - offset2 = PAIRWISE_IVEIV_TABLE_BASE + (BSSID_WCID* HW_IVEIV_ENTRY_SIZE); - for (i=0; i<8;) - { - Value = IVEIV[i]; - Value += (IVEIV[i+1]<<8); - Value += (IVEIV[i+2]<<16); - Value += (IVEIV[i+3]<<24); - RTUSBWriteMACRegister(pAd, offset+i, Value); - RTUSBWriteMACRegister(pAd, offset2+i, Value); - i+=4; - } + case CMDTHREAD_SET_GROUP_KEY: + WpaStaGroupKeySetting(pAd); + break; - // 2. WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:use share key, BSSIdx is 0 - WCIDAttri = (pAd->SharedKey[BSS0][KeyIdx].CipherAlg<<1)|SHAREDKEYTABLE; - offset = MAC_WCID_ATTRIBUTE_BASE + (BSS0Mcast_WCID* HW_WCID_ATTRI_SIZE); - DBGPRINT(RT_DEBUG_TRACE, ("BSS0Mcast_WCID : offset = %x, WCIDAttri = %x\n", offset, WCIDAttri)); - RTUSBWriteMACRegister(pAd, offset, WCIDAttri); + case CMDTHREAD_SET_PAIRWISE_KEY: + WpaStaPairwiseKeySetting(pAd); + break; - } - AsicAddSharedKeyEntry(pAd, BSS0, (UCHAR)KeyIdx, CipherAlg, pWepKey->KeyMaterial, NULL, NULL); - DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::OID_802_11_ADD_WEP (KeyIdx=%d, Len=%d-byte)\n", KeyIdx, pWepKey->KeyLength)); - } - } - break; + case CMDTHREAD_SET_PSM_BIT: + { + u16 *pPsm = (u16 *) pData; + MlmeSetPsmBit(pAd, *pPsm); + } + break; + case CMDTHREAD_FORCE_WAKE_UP: + AsicForceWakeup(pAd, TRUE); + break; - case CMDTHREAD_802_11_COUNTER_MEASURE: - break; - default: - DBGPRINT(RT_DEBUG_ERROR, ("--> Control Thread !! ERROR !! Unknown(cmdqelmt->command=0x%x) !! \n", cmdqelmt->command)); - break; + default: + DBGPRINT(RT_DEBUG_ERROR, + ("--> Control Thread !! ERROR !! Unknown(cmdqelmt->command=0x%x) !! \n", + cmdqelmt->command)); + break; } } - if (cmdqelmt->CmdFromNdis == TRUE) - { - if (cmdqelmt->buffer != NULL) - NdisFreeMemory(cmdqelmt->buffer, cmdqelmt->bufferlength, 0); - - NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0); - } - else - { - if ((cmdqelmt->buffer != NULL) && (cmdqelmt->bufferlength != 0)) - NdisFreeMemory(cmdqelmt->buffer, cmdqelmt->bufferlength, 0); - { - NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0); - } + if (cmdqelmt->CmdFromNdis == TRUE) { + if (cmdqelmt->buffer != NULL) + os_free_mem(pAd, cmdqelmt->buffer); + os_free_mem(pAd, cmdqelmt); + } else { + if ((cmdqelmt->buffer != NULL) + && (cmdqelmt->bufferlength != 0)) + os_free_mem(pAd, cmdqelmt->buffer); + os_free_mem(pAd, cmdqelmt); } - } /* end of while */ + } /* end of while */ } +#endif /* RTMP_MAC_USB // */ diff --git a/drivers/staging/rt2870/rt2870.h b/drivers/staging/rt2870/rt2870.h deleted file mode 100644 index 4c67bafad4e6f76f8b560f19c2c6e1517cfa0641..0000000000000000000000000000000000000000 --- a/drivers/staging/rt2870/rt2870.h +++ /dev/null @@ -1,583 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - */ - -#ifndef __RT2870_H__ -#define __RT2870_H__ - -//usb header files -#include - -/* rtmp_def.h */ -// -#define BULKAGGRE_ZISE 100 -#define RT28XX_DRVDATA_SET(_a) usb_set_intfdata(_a, pAd); -#define RT28XX_PUT_DEVICE usb_put_dev -#define RTUSB_ALLOC_URB(iso) usb_alloc_urb(iso, GFP_ATOMIC) -#define RTUSB_SUBMIT_URB(pUrb) usb_submit_urb(pUrb, GFP_ATOMIC) -#define RTUSB_URB_ALLOC_BUFFER(pUsb_Dev, BufSize, pDma_addr) usb_buffer_alloc(pUsb_Dev, BufSize, GFP_ATOMIC, pDma_addr) -#define RTUSB_URB_FREE_BUFFER(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) usb_buffer_free(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) - -#define RXBULKAGGRE_ZISE 12 -#define MAX_TXBULK_LIMIT (LOCAL_TXBUF_SIZE*(BULKAGGRE_ZISE-1)) -#define MAX_TXBULK_SIZE (LOCAL_TXBUF_SIZE*BULKAGGRE_ZISE) -#define MAX_RXBULK_SIZE (LOCAL_TXBUF_SIZE*RXBULKAGGRE_ZISE) -#define MAX_MLME_HANDLER_MEMORY 20 -#define RETRY_LIMIT 10 -#define BUFFER_SIZE 2400 //2048 -#define TX_RING 0xa -#define PRIO_RING 0xc - - -// Flags for Bulkflags control for bulk out data -// -#define fRTUSB_BULK_OUT_DATA_NULL 0x00000001 -#define fRTUSB_BULK_OUT_RTS 0x00000002 -#define fRTUSB_BULK_OUT_MLME 0x00000004 - -#define fRTUSB_BULK_OUT_DATA_NORMAL 0x00010000 -#define fRTUSB_BULK_OUT_DATA_NORMAL_2 0x00020000 -#define fRTUSB_BULK_OUT_DATA_NORMAL_3 0x00040000 -#define fRTUSB_BULK_OUT_DATA_NORMAL_4 0x00080000 -#define fRTUSB_BULK_OUT_DATA_NORMAL_5 0x00100000 - -#define fRTUSB_BULK_OUT_PSPOLL 0x00000020 -#define fRTUSB_BULK_OUT_DATA_FRAG 0x00000040 -#define fRTUSB_BULK_OUT_DATA_FRAG_2 0x00000080 -#define fRTUSB_BULK_OUT_DATA_FRAG_3 0x00000100 -#define fRTUSB_BULK_OUT_DATA_FRAG_4 0x00000200 - -#define FREE_HTTX_RING(_p, _b, _t) \ -{ \ - if ((_t)->ENextBulkOutPosition == (_t)->CurWritePosition) \ - { \ - (_t)->bRingEmpty = TRUE; \ - } \ - /*NdisInterlockedDecrement(&(_p)->TxCount); */\ -} - -// -// RXINFO appends at the end of each rx packet. -// -typedef struct PACKED _RXINFO_STRUC { - UINT32 BA:1; - UINT32 DATA:1; - UINT32 NULLDATA:1; - UINT32 FRAG:1; - UINT32 U2M:1; // 1: this RX frame is unicast to me - UINT32 Mcast:1; // 1: this is a multicast frame - UINT32 Bcast:1; // 1: this is a broadcast frame - UINT32 MyBss:1; // 1: this frame belongs to the same BSSID - UINT32 Crc:1; // 1: CRC error - UINT32 CipherErr:2; // 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid - UINT32 AMSDU:1; // rx with 802.3 header, not 802.11 header. - UINT32 HTC:1; - UINT32 RSSI:1; - UINT32 L2PAD:1; - UINT32 AMPDU:1; // To be moved - UINT32 Decrypted:1; - UINT32 PlcpRssil:1; - UINT32 CipherAlg:1; - UINT32 LastAMSDU:1; - UINT32 PlcpSignal:12; -} RXINFO_STRUC, *PRXINFO_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC; - -// -// TXINFO -// -typedef struct _TXINFO_STRUC { - // Word 0 - UINT32 USBDMATxPktLen:16; //used ONLY in USB bulk Aggregation, Total byte counts of all sub-frame. - UINT32 rsv:8; - UINT32 WIV:1; // Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition - UINT32 QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA - UINT32 SwUseLastRound:1; // Software use. - UINT32 rsv2:2; // Software use. - UINT32 USBDMANextVLD:1; //used ONLY in USB bulk Aggregation, NextValid - UINT32 USBDMATxburst:1;//used ONLY in USB bulk Aggre. Force USB DMA transmit frame from current selected endpoint -} TXINFO_STRUC, *PTXINFO_STRUC; - -#define TXINFO_SIZE 4 -#define RXINFO_SIZE 4 -#define TXPADDING_SIZE 11 - -// -// Management ring buffer format -// -typedef struct _MGMT_STRUC { - BOOLEAN Valid; - PUCHAR pBuffer; - ULONG Length; -} MGMT_STRUC, *PMGMT_STRUC; - - -/* ----------------- EEPROM Related MACRO ----------------- */ -#define RT28xx_EEPROM_READ16(pAd, offset, var) \ - do { \ - RTUSBReadEEPROM(pAd, offset, (PUCHAR)&(var), 2); \ - if(!pAd->bUseEfuse) \ - var = le2cpu16(var); \ - }while(0) - -#define RT28xx_EEPROM_WRITE16(pAd, offset, var) \ - do{ \ - USHORT _tmpVar=var; \ - if(!pAd->bUseEfuse) \ - _tmpVar = cpu2le16(var); \ - RTUSBWriteEEPROM(pAd, offset, (PUCHAR)&(_tmpVar), 2); \ - }while(0) - -/* ----------------- TASK/THREAD Related MACRO ----------------- */ -#define RT28XX_TASK_THREAD_INIT(pAd, Status) \ - Status = CreateThreads(net_dev); - - -/* ----------------- Frimware Related MACRO ----------------- */ -#define RT28XX_WRITE_FIRMWARE(_pAd, _pFwImage, _FwLen) \ - RTUSBFirmwareWrite(_pAd, _pFwImage, _FwLen) - -/* ----------------- TX Related MACRO ----------------- */ -#define RT28XX_START_DEQUEUE(pAd, QueIdx, irqFlags) \ - { \ - RTMP_IRQ_LOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ - if (pAd->DeQueueRunning[QueIdx]) \ - { \ - RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);\ - printk("DeQueueRunning[%d]= TRUE!\n", QueIdx); \ - continue; \ - } \ - else \ - { \ - pAd->DeQueueRunning[QueIdx] = TRUE; \ - RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);\ - } \ - } -#define RT28XX_STOP_DEQUEUE(pAd, QueIdx, irqFlags) \ - do{ \ - RTMP_IRQ_LOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ - pAd->DeQueueRunning[QueIdx] = FALSE; \ - RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ - }while(0) - - -#define RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, freeNum, pPacket) \ - (RTUSBFreeDescriptorRequest(pAd, pTxBlk->QueIdx, (pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))) == NDIS_STATUS_SUCCESS) - -#define RT28XX_RELEASE_DESC_RESOURCE(pAd, QueIdx) \ - do{}while(0) - -#define NEED_QUEUE_BACK_FOR_AGG(_pAd, _QueIdx, _freeNum, _TxFrameType) \ - ((_TxFrameType == TX_RALINK_FRAME) && (RTUSBNeedQueueBackForAgg(_pAd, _QueIdx))) - - - -#define fRTMP_ADAPTER_NEED_STOP_TX \ - (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \ - fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_BULKOUT_RESET | \ - fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_REMOVE_IN_PROGRESS) - - -#define HAL_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) \ - RtmpUSB_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) - -#define HAL_WriteTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) \ - RtmpUSB_WriteSingleTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) - -#define HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) \ - RtmpUSB_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) - -#define HAL_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) \ - RtmpUSB_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) - -#define HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, TxIdx) \ - RtmpUSB_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, TxIdx) - -#define HAL_LastTxIdx(pAd, QueIdx,TxIdx) \ - /*RtmpUSBDataLastTxIdx(pAd, QueIdx,TxIdx)*/ - -#define HAL_KickOutTx(pAd, pTxBlk, QueIdx) \ - RtmpUSBDataKickOut(pAd, pTxBlk, QueIdx) - - -#define HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen) \ - RtmpUSBMgmtKickOut(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen) - -#define HAL_KickOutNullFrameTx(_pAd, _QueIdx, _pNullFrame, _frameLen) \ - RtmpUSBNullFrameKickOut(_pAd, _QueIdx, _pNullFrame, _frameLen) - -#define RTMP_PKT_TAIL_PADDING 11 // 3(max 4 byte padding) + 4 (last packet padding) + 4 (MaxBulkOutsize align padding) - -extern UCHAR EpToQueue[6]; - - -#ifdef RT2870 -#define GET_TXRING_FREENO(_pAd, _QueIdx) (_QueIdx) //(_pAd->TxRing[_QueIdx].TxSwFreeIdx) -#define GET_MGMTRING_FREENO(_pAd) (_pAd->MgmtRing.TxSwFreeIdx) -#endif // RT2870 // - - -/* ----------------- RX Related MACRO ----------------- */ -//#define RT28XX_RX_ERROR_CHECK RTMPCheckRxWI - -#define RT28XX_RV_ALL_BUF_END(bBulkReceive) \ - /* We return STATUS_MORE_PROCESSING_REQUIRED so that the completion */ \ - /* routine (IofCompleteRequest) will stop working on the irp. */ \ - if (bBulkReceive == TRUE) RTUSBBulkReceive(pAd); - - -/* ----------------- ASIC Related MACRO ----------------- */ - -// reset MAC of a station entry to 0xFFFFFFFFFFFF -#define RT28XX_STA_ENTRY_MAC_RESET(pAd, Wcid) \ - { RT_SET_ASIC_WCID SetAsicWcid; \ - SetAsicWcid.WCID = Wcid; \ - SetAsicWcid.SetTid = 0xffffffff; \ - SetAsicWcid.DeleteTid = 0xffffffff; \ - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_SET_ASIC_WCID, \ - &SetAsicWcid, sizeof(RT_SET_ASIC_WCID)); } - -// add this entry into ASIC RX WCID search table -#define RT28XX_STA_ENTRY_ADD(pAd, pEntry) \ - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_SET_CLIENT_MAC_ENTRY, \ - pEntry, sizeof(MAC_TABLE_ENTRY)); - -// remove Pair-wise key material from ASIC -// yet implement -#define RT28XX_STA_ENTRY_KEY_DEL(pAd, BssIdx, Wcid) - -// add Client security information into ASIC WCID table and IVEIV table -#define RT28XX_STA_SECURITY_INFO_ADD(pAd, apidx, KeyID, pEntry) \ - { RT28XX_STA_ENTRY_MAC_RESET(pAd, pEntry->Aid); \ - if (pEntry->Aid >= 1) { \ - RT_SET_ASIC_WCID_ATTRI SetAsicWcidAttri; \ - SetAsicWcidAttri.WCID = pEntry->Aid; \ - if ((pEntry->AuthMode <= Ndis802_11AuthModeAutoSwitch) && \ - (pEntry->WepStatus == Ndis802_11Encryption1Enabled)) \ - { \ - SetAsicWcidAttri.Cipher = pAd->SharedKey[apidx][KeyID].CipherAlg; \ - } \ - else if (pEntry->AuthMode == Ndis802_11AuthModeWPANone) \ - { \ - SetAsicWcidAttri.Cipher = pAd->SharedKey[apidx][KeyID].CipherAlg; \ - } \ - else SetAsicWcidAttri.Cipher = 0; \ - DBGPRINT(RT_DEBUG_TRACE, ("aid cipher = %ld\n",SetAsicWcidAttri.Cipher)); \ - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_SET_ASIC_WCID_CIPHER, \ - &SetAsicWcidAttri, sizeof(RT_SET_ASIC_WCID_ATTRI)); } } - -// Insert the BA bitmap to ASIC for the Wcid entry -#define RT28XX_ADD_BA_SESSION_TO_ASIC(_pAd, _Aid, _TID) \ - do{ \ - RT_SET_ASIC_WCID SetAsicWcid; \ - SetAsicWcid.WCID = (_Aid); \ - SetAsicWcid.SetTid = (0x10000<<(_TID)); \ - SetAsicWcid.DeleteTid = 0xffffffff; \ - RTUSBEnqueueInternalCmd((_pAd), CMDTHREAD_SET_ASIC_WCID, &SetAsicWcid, sizeof(RT_SET_ASIC_WCID)); \ - }while(0) - -// Remove the BA bitmap from ASIC for the Wcid entry -#define RT28XX_DEL_BA_SESSION_FROM_ASIC(_pAd, _Wcid, _TID) \ - do{ \ - RT_SET_ASIC_WCID SetAsicWcid; \ - SetAsicWcid.WCID = (_Wcid); \ - SetAsicWcid.SetTid = (0xffffffff); \ - SetAsicWcid.DeleteTid = (0x10000<<(_TID) ); \ - RTUSBEnqueueInternalCmd((_pAd), CMDTHREAD_SET_ASIC_WCID, &SetAsicWcid, sizeof(RT_SET_ASIC_WCID)); \ - }while(0) - - -/* ----------------- PCI/USB Related MACRO ----------------- */ -#define RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p) \ - ((POS_COOKIE)handle)->pUsb_Dev = dev_p; - -// no use -#define RT28XX_UNMAP() -#define RT28XX_IRQ_REQUEST(net_dev) -#define RT28XX_IRQ_RELEASE(net_dev) -#define RT28XX_IRQ_INIT(pAd) -#define RT28XX_IRQ_ENABLE(pAd) - - -/* ----------------- MLME Related MACRO ----------------- */ -#define RT28XX_MLME_HANDLER(pAd) RTUSBMlmeUp(pAd) - -#define RT28XX_MLME_PRE_SANITY_CHECK(pAd) \ - { if ((pAd->CommonCfg.bHardwareRadio == TRUE) && \ - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && \ - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { \ - RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_CHECK_GPIO, NULL, 0); } } - -#define RT28XX_MLME_STA_QUICK_RSP_WAKE_UP(pAd) \ - { RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_QKERIODIC_EXECUT, NULL, 0); \ - RTUSBMlmeUp(pAd); } - -#define RT28XX_MLME_RESET_STATE_MACHINE(pAd) \ - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_RESET_CONF, 0, NULL); \ - RTUSBMlmeUp(pAd); - -#define RT28XX_HANDLE_COUNTER_MEASURE(_pAd, _pEntry) \ - { RTUSBEnqueueInternalCmd(_pAd, CMDTHREAD_802_11_COUNTER_MEASURE, _pEntry, sizeof(MAC_TABLE_ENTRY)); \ - RTUSBMlmeUp(_pAd); \ - } - - -/* ----------------- Power Save Related MACRO ----------------- */ -#define RT28XX_PS_POLL_ENQUEUE(pAd) \ - { RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL); \ - RTUSBKickBulkOut(pAd); } - -#define RT28xx_CHIP_NAME "RTxx70" - -#define USB_CYC_CFG 0x02a4 -#define STATUS_SUCCESS 0x00 -#define STATUS_UNSUCCESSFUL 0x01 -#define NT_SUCCESS(status) (((status) > 0) ? (1):(0)) -#define InterlockedIncrement atomic_inc -#define NdisInterlockedIncrement atomic_inc -#define InterlockedDecrement atomic_dec -#define NdisInterlockedDecrement atomic_dec -#define InterlockedExchange atomic_set -//#define NdisMSendComplete RTMP_SendComplete -#define NdisMCancelTimer RTMPCancelTimer -#define NdisAllocMemory(_ptr, _size, _flag) \ - do{_ptr = kmalloc((_size),(_flag));}while(0) -#define NdisFreeMemory(a, b, c) kfree((a)) -#define NdisMSleep RTMPusecDelay /* unit: microsecond */ - - -#define USBD_TRANSFER_DIRECTION_OUT 0 -#define USBD_TRANSFER_DIRECTION_IN 0 -#define USBD_SHORT_TRANSFER_OK 0 -#define PURB purbb_t - -#define RTUSB_FREE_URB(pUrb) usb_free_urb(pUrb) - -//#undef MlmeAllocateMemory -//#undef MlmeFreeMemory - -typedef struct usb_device * PUSB_DEV; - -/* MACRO for linux usb */ -typedef struct urb *purbb_t; -typedef struct usb_ctrlrequest devctrlrequest; -#define PIRP PVOID -#define PMDL PVOID -#define NDIS_OID UINT -#ifndef USB_ST_NOERROR -#define USB_ST_NOERROR 0 -#endif - -// vendor-specific control operations -#define CONTROL_TIMEOUT_JIFFIES ( (100 * HZ) / 1000) -#define UNLINK_TIMEOUT_MS 3 - -/* unlink urb */ -#define RTUSB_UNLINK_URB(pUrb) usb_kill_urb(pUrb) - -// Prototypes of completion funuc. -VOID RTUSBBulkOutDataPacketComplete(purbb_t purb, struct pt_regs *pt_regs); -VOID RTUSBBulkOutMLMEPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs); -VOID RTUSBBulkOutNullFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs); -VOID RTUSBBulkOutRTSFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs); -VOID RTUSBBulkOutPsPollComplete(purbb_t pUrb, struct pt_regs *pt_regs); -VOID RTUSBBulkRxComplete(purbb_t pUrb, struct pt_regs *pt_regs); - -#define RTUSBMlmeUp(pAd) \ -{ \ - POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; \ - if (pid_nr(pObj->MLMEThr_pid) > 0) \ - up(&(pAd->mlme_semaphore)); \ -} - -#define RTUSBCMDUp(pAd) \ -{ \ - POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; \ - if (pid_nr(pObj->RTUSBCmdThr_pid) > 0) \ - up(&(pAd->RTUSBCmd_semaphore)); \ -} - -static inline NDIS_STATUS RTMPAllocateMemory( - OUT PVOID *ptr, - IN size_t size) -{ - *ptr = kmalloc(size, GFP_ATOMIC); - if(*ptr) - return NDIS_STATUS_SUCCESS; - else - return NDIS_STATUS_RESOURCES; -} - -/* rtmp.h */ -#define BEACON_RING_SIZE 2 -#define DEVICE_VENDOR_REQUEST_OUT 0x40 -#define DEVICE_VENDOR_REQUEST_IN 0xc0 -#define INTERFACE_VENDOR_REQUEST_OUT 0x41 -#define INTERFACE_VENDOR_REQUEST_IN 0xc1 -#define MGMTPIPEIDX 0 // EP6 is highest priority - -#define BULKOUT_MGMT_RESET_FLAG 0x80 - -#define RTUSB_SET_BULK_FLAG(_M, _F) ((_M)->BulkFlags |= (_F)) -#define RTUSB_CLEAR_BULK_FLAG(_M, _F) ((_M)->BulkFlags &= ~(_F)) -#define RTUSB_TEST_BULK_FLAG(_M, _F) (((_M)->BulkFlags & (_F)) != 0) - -#define EnqueueCmd(cmdq, cmdqelmt) \ -{ \ - if (cmdq->size == 0) \ - cmdq->head = cmdqelmt; \ - else \ - cmdq->tail->next = cmdqelmt; \ - cmdq->tail = cmdqelmt; \ - cmdqelmt->next = NULL; \ - cmdq->size++; \ -} - -typedef struct _RT_SET_ASIC_WCID { - ULONG WCID; // mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based - ULONG SetTid; // time-based: seconds, packet-based: kilo-packets - ULONG DeleteTid; // time-based: seconds, packet-based: kilo-packets - UCHAR Addr[MAC_ADDR_LEN]; // avoid in interrupt when write key -} RT_SET_ASIC_WCID,*PRT_SET_ASIC_WCID; - -typedef struct _RT_SET_ASIC_WCID_ATTRI { - ULONG WCID; // mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based - ULONG Cipher; // ASIC Cipher definition - UCHAR Addr[ETH_LENGTH_OF_ADDRESS]; -} RT_SET_ASIC_WCID_ATTRI,*PRT_SET_ASIC_WCID_ATTRI; - -typedef struct _MLME_MEMORY_STRUCT { - PVOID AllocVa; //Pointer to the base virtual address of the allocated memory - struct _MLME_MEMORY_STRUCT *Next; //Pointer to the next virtual address of the allocated memory -} MLME_MEMORY_STRUCT, *PMLME_MEMORY_STRUCT; - -typedef struct _MLME_MEMORY_HANDLER { - BOOLEAN MemRunning; //The flag of the Mlme memory handler's status - UINT MemoryCount; //Total nonpaged system-space memory not size - UINT InUseCount; //Nonpaged system-space memory in used counts - UINT UnUseCount; //Nonpaged system-space memory available counts - INT PendingCount; //Nonpaged system-space memory for free counts - PMLME_MEMORY_STRUCT pInUseHead; //Pointer to the first nonpaed memory not used - PMLME_MEMORY_STRUCT pInUseTail; //Pointer to the last nonpaged memory not used - PMLME_MEMORY_STRUCT pUnUseHead; //Pointer to the first nonpaged memory in used - PMLME_MEMORY_STRUCT pUnUseTail; //Pointer to the last nonpaged memory in used - PULONG MemFreePending[MAX_MLME_HANDLER_MEMORY]; //an array to keep pending free-memory's pointer (32bits) -} MLME_MEMORY_HANDLER, *PMLME_MEMORY_HANDLER; - -typedef struct _CmdQElmt { - UINT command; - PVOID buffer; - ULONG bufferlength; - BOOLEAN CmdFromNdis; - BOOLEAN SetOperation; - struct _CmdQElmt *next; -} CmdQElmt, *PCmdQElmt; - -typedef struct _CmdQ { - UINT size; - CmdQElmt *head; - CmdQElmt *tail; - UINT32 CmdQState; -}CmdQ, *PCmdQ; - -/* oid.h */ -// Cipher suite type for mixed mode group cipher, P802.11i-2004 -typedef enum _RT_802_11_CIPHER_SUITE_TYPE { - Cipher_Type_NONE, - Cipher_Type_WEP40, - Cipher_Type_TKIP, - Cipher_Type_RSVD, - Cipher_Type_CCMP, - Cipher_Type_WEP104 -} RT_802_11_CIPHER_SUITE_TYPE, *PRT_802_11_CIPHER_SUITE_TYPE; - -//CMDTHREAD_MULTI_READ_MAC -//CMDTHREAD_MULTI_WRITE_MAC -//CMDTHREAD_VENDOR_EEPROM_READ -//CMDTHREAD_VENDOR_EEPROM_WRITE -typedef struct _CMDHandler_TLV { - USHORT Offset; - USHORT Length; - UCHAR DataFirst; -} CMDHandler_TLV, *PCMDHandler_TLV; - -// New for MeetingHouse Api support -#define CMDTHREAD_VENDOR_RESET 0x0D730101 // cmd -#define CMDTHREAD_VENDOR_UNPLUG 0x0D730102 // cmd -#define CMDTHREAD_VENDOR_SWITCH_FUNCTION 0x0D730103 // cmd -#define CMDTHREAD_MULTI_WRITE_MAC 0x0D730107 // cmd -#define CMDTHREAD_MULTI_READ_MAC 0x0D730108 // cmd -#define CMDTHREAD_VENDOR_EEPROM_WRITE 0x0D73010A // cmd -#define CMDTHREAD_VENDOR_EEPROM_READ 0x0D73010B // cmd -#define CMDTHREAD_VENDOR_ENTER_TESTMODE 0x0D73010C // cmd -#define CMDTHREAD_VENDOR_EXIT_TESTMODE 0x0D73010D // cmd -#define CMDTHREAD_VENDOR_WRITE_BBP 0x0D730119 // cmd -#define CMDTHREAD_VENDOR_READ_BBP 0x0D730118 // cmd -#define CMDTHREAD_VENDOR_WRITE_RF 0x0D73011A // cmd -#define CMDTHREAD_VENDOR_FLIP_IQ 0x0D73011D // cmd -#define CMDTHREAD_RESET_BULK_OUT 0x0D730210 // cmd -#define CMDTHREAD_RESET_BULK_IN 0x0D730211 // cmd -#define CMDTHREAD_SET_PSM_BIT_SAVE 0x0D730212 // cmd -#define CMDTHREAD_SET_RADIO 0x0D730214 // cmd -#define CMDTHREAD_UPDATE_TX_RATE 0x0D730216 // cmd -#define CMDTHREAD_802_11_ADD_KEY_WEP 0x0D730218 // cmd -#define CMDTHREAD_RESET_FROM_ERROR 0x0D73021A // cmd -#define CMDTHREAD_LINK_DOWN 0x0D73021B // cmd -#define CMDTHREAD_RESET_FROM_NDIS 0x0D73021C // cmd -#define CMDTHREAD_CHECK_GPIO 0x0D730215 // cmd -#define CMDTHREAD_FORCE_WAKE_UP 0x0D730222 // cmd -#define CMDTHREAD_SET_BW 0x0D730225 // cmd -#define CMDTHREAD_SET_ASIC_WCID 0x0D730226 // cmd -#define CMDTHREAD_SET_ASIC_WCID_CIPHER 0x0D730227 // cmd -#define CMDTHREAD_QKERIODIC_EXECUT 0x0D73023D // cmd -#define CMDTHREAD_SET_CLIENT_MAC_ENTRY 0x0D73023E // cmd -#define CMDTHREAD_802_11_QUERY_HARDWARE_REGISTER 0x0D710105 // cmd -#define CMDTHREAD_802_11_SET_PHY_MODE 0x0D79010C // cmd -#define CMDTHREAD_802_11_SET_STA_CONFIG 0x0D790111 // cmd -#define CMDTHREAD_802_11_SET_PREAMBLE 0x0D790101 // cmd -#define CMDTHREAD_802_11_COUNTER_MEASURE 0x0D790102 // cmd -#define CMDTHREAD_UPDATE_PROTECT 0x0D790103 // cmd - -#define WPA1AKMBIT 0x01 -#define WPA2AKMBIT 0x02 -#define WPA1PSKAKMBIT 0x04 -#define WPA2PSKAKMBIT 0x08 -#define TKIPBIT 0x01 -#define CCMPBIT 0x02 - - -#define RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx) \ - RT28xxUsbStaAsicForceWakeup(pAd, bFromTx); - -#define RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp) \ - RT28xxUsbStaAsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); - -#define RT28XX_MLME_RADIO_ON(pAd) \ - RT28xxUsbMlmeRadioOn(pAd); - -#define RT28XX_MLME_RADIO_OFF(pAd) \ - RT28xxUsbMlmeRadioOFF(pAd); - -#endif //__RT2870_H__ diff --git a/drivers/staging/rt2870/rt_usb.c b/drivers/staging/rt2870/rt_usb.c new file mode 100644 index 0000000000000000000000000000000000000000..5e02d4c88d7375e66e4544e22ac89d7258f7d797 --- /dev/null +++ b/drivers/staging/rt2870/rt_usb.c @@ -0,0 +1 @@ +#include "../rt2860/rt_usb.c" diff --git a/drivers/staging/rt2870/usb_main_dev.c b/drivers/staging/rt2870/usb_main_dev.c new file mode 100644 index 0000000000000000000000000000000000000000..6e63bc50047afe8ddc04a5a15bee2403254e1c50 --- /dev/null +++ b/drivers/staging/rt2870/usb_main_dev.c @@ -0,0 +1 @@ +#include "../rt2860/usb_main_dev.c" diff --git a/drivers/staging/rt3070/firmware.h b/drivers/staging/rt3070/firmware.h index b07783ed8dd051be9aaeb5118beff9bf712a74fa..5cf9cbcf4ab6a063a2792e0c2327c374e9763e94 100644 --- a/drivers/staging/rt3070/firmware.h +++ b/drivers/staging/rt3070/firmware.h @@ -43,7 +43,7 @@ /* AUTO GEN PLEASE DO NOT MODIFY IT */ -UCHAR FirmwareImage [] = { +u8 FirmwareImage_2870 [] = { 0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x12, 0x67, 0x02, 0x12, 0x68, 0x02, 0x12, 0x87, 0x02, 0x12, 0x8c, 0x12, 0x12, 0x88, 0x22, 0x02, 0x16, 0x49, 0x02, 0x17, 0x1f, 0x02, 0x13, 0x77, 0x02, 0x12, 0x8d, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x17, diff --git a/drivers/staging/rt3070/md4.h b/drivers/staging/rt3070/md4.h index f1e5b526350a745aa9fd4d83a39e7ebc75ba293e..a9cc7b0f3ee3afac33f8a5afa09392b06a2ea053 100644 --- a/drivers/staging/rt3070/md4.h +++ b/drivers/staging/rt3070/md4.h @@ -30,13 +30,13 @@ /* MD4 context. */ typedef struct _MD4_CTX_ { - ULONG state[4]; /* state (ABCD) */ - ULONG count[2]; /* number of bits, modulo 2^64 (lsb first) */ - UCHAR buffer[64]; /* input buffer */ + unsigned long state[4]; /* state (ABCD) */ + unsigned long count[2]; /* number of bits, modulo 2^64 (lsb first) */ + u8 buffer[64]; /* input buffer */ } MD4_CTX; -VOID MD4Init (MD4_CTX *); -VOID MD4Update (MD4_CTX *, PUCHAR, UINT); -VOID MD4Final (UCHAR [16], MD4_CTX *); +void MD4Init (MD4_CTX *); +void MD4Update (MD4_CTX *, u8 *, UINT); +void MD4Final (u8 [16], MD4_CTX *); #endif //__MD4_H__ \ No newline at end of file diff --git a/drivers/staging/rt3090/Kconfig b/drivers/staging/rt3090/Kconfig deleted file mode 100644 index 2b3f745d72b7cfb4dcf2f12e50d8c5955c5afc13..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/Kconfig +++ /dev/null @@ -1,5 +0,0 @@ -config RT3090 - tristate "Ralink 3090 wireless support" - depends on PCI && X86 && WLAN - ---help--- - This is an experimental driver for the Ralink 3090 wireless chip. diff --git a/drivers/staging/rt3090/Makefile b/drivers/staging/rt3090/Makefile deleted file mode 100644 index 995491c91fce18d7d5e21f6d049c94b4d141e91b..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/Makefile +++ /dev/null @@ -1,80 +0,0 @@ -obj-$(CONFIG_RT3090) += rt3090sta.o - -include drivers/staging/rt3090/config.mk - -rt3090sta-objs := \ - common/crypt_md5.o \ - common/crypt_sha2.o \ - common/crypt_hmac.o \ - common/mlme.o \ - common/cmm_wep.o \ - common/action.o \ - common/cmm_data.o \ - common/rtmp_init.o \ - common/cmm_tkip.o \ - common/cmm_aes.o \ - common/cmm_sync.o \ - common/eeprom.o \ - common/cmm_sanity.o \ - common/cmm_info.o \ - common/cmm_cfg.o \ - common/cmm_wpa.o \ - common/dfs.o \ - common/spectrum.o \ - common/rtmp_timer.o \ - common/rt_channel.o \ - common/cmm_profile.o \ - common/cmm_asic.o \ - sta/assoc.o \ - sta/auth.o \ - sta/auth_rsp.o \ - sta/sync.o \ - sta/sanity.o \ - sta/rtmp_data.o \ - sta/connect.o \ - sta/wpa.o \ - rt_linux.o \ - rt_profile.o \ - rt_main_dev.o \ - sta_ioctl.o - -#ifdef DOT11_N_SUPPORT -ifeq ($(HAS_DOT11_N_SUPPORT),y) -rt3090sta-objs += \ - common/ba_action.o -endif -#endif // DOT11_N_SUPPORT // - -#ifdef ETH_CONVERT -ifeq ($(HAS_ETH_CONVERT_SUPPORT), y) -rt3090sta-objs += \ - common/cmm_mat.o \ - common/cmm_mat_iparp.o \ - common/cmm_mat_pppoe.o \ - common/cmm_mat_ipv6.o -endif -#endif // ETH_CONVERT // - -ifeq ($(HAS_BLOCK_NET_IF),y) -rt3090sta-objs += common/netif_block.o -endif - -ifeq ($(HAS_QOS_DLS_SUPPORT),y) -rt3090sta-objs += sta/dls.o -endif - -rt3090sta-objs += \ - pci_main_dev.o \ - rt_pci_rbus.o \ - common/cmm_mac_pci.o \ - common/cmm_data_pci.o \ - common/ee_prom.o \ - common/ee_efuse.o \ - common/rtmp_mcu.o \ - chips/rt30xx.o \ - common/rt_rf.o \ - chips/rt3090.o - -ifeq ($(HAS_ATE),y) -rt3090sta-objs += rt_ate.o -endif diff --git a/drivers/staging/rt3090/action.h b/drivers/staging/rt3090/action.h deleted file mode 100644 index ac0a0a3c5ce42f8a73e1db334d5101ee5a4d2889..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/action.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - aironet.h - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Name Date Modification logs - Paul Lin 04-06-15 Initial -*/ - -#ifndef __ACTION_H__ -#define __ACTION_H__ - -typedef struct PACKED __HT_INFO_OCTET -{ -#ifdef RT_BIG_ENDIAN - UCHAR Reserved:5; - UCHAR STA_Channel_Width:1; - UCHAR Forty_MHz_Intolerant:1; - UCHAR Request:1; -#else - UCHAR Request:1; - UCHAR Forty_MHz_Intolerant:1; - UCHAR STA_Channel_Width:1; - UCHAR Reserved:5; -#endif -} HT_INFORMATION_OCTET; - - -typedef struct PACKED __FRAME_HT_INFO -{ - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; - HT_INFORMATION_OCTET HT_Info; -} FRAME_HT_INFO, *PFRAME_HT_INFO; - -#endif /* __ACTION_H__ */ diff --git a/drivers/staging/rt3090/ap.h b/drivers/staging/rt3090/ap.h deleted file mode 100644 index e89430381071a7335968d42a9d538ee1c582b049..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/ap.h +++ /dev/null @@ -1,512 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - ap.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Paul Lin 08-01-2002 created - James Tan 09-06-2002 modified (Revise NTCRegTable) - John Chang 12-22-2004 modified for RT2561/2661. merge with STA driver -*/ -#ifndef __AP_H__ -#define __AP_H__ - - -// ============================================================= -// Function Prototypes -// ============================================================= - -// ap_data.c - -BOOLEAN APBridgeToWirelessSta( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pHeader, - IN UINT HdrLen, - IN PUCHAR pData, - IN UINT DataLen, - IN ULONG fromwdsidx); - - -VOID APSendPackets( - IN NDIS_HANDLE MiniportAdapterContext, - IN PPNDIS_PACKET ppPacketArray, - IN UINT NumberOfPackets); - -NDIS_STATUS APSendPacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket); - - -NDIS_STATUS APHardTransmit( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR QueIdx); - -VOID APRxEAPOLFrameIndicate( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); - -NDIS_STATUS APCheckRxError( - IN PRTMP_ADAPTER pAd, - IN PRT28XX_RXD_STRUC pRxD, - IN UCHAR Wcid); - -BOOLEAN APCheckClass2Class3Error( - IN PRTMP_ADAPTER pAd, - IN ULONG Wcid, - IN PHEADER_802_11 pHeader); - -VOID APHandleRxPsPoll( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN USHORT Aid, - IN BOOLEAN isActive); - -VOID RTMPDescriptorEndianChange( - IN PUCHAR pData, - IN ULONG DescriptorType); - -VOID RTMPFrameEndianChange( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG Dir, - IN BOOLEAN FromRxDoneInt); - -// ap_assoc.c - -VOID APAssocStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID APPeerAssocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID APPeerReassocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID APPeerDisassocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MbssKickOutStas( - IN PRTMP_ADAPTER pAd, - IN INT apidx, - IN USHORT Reason); - -VOID APMlmeKickOutSta( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pStaAddr, - IN UCHAR Wcid, - IN USHORT Reason); - -VOID APMlmeDisassocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID APCls3errAction( - IN PRTMP_ADAPTER pAd, - IN ULONG Wcid, - IN PHEADER_802_11 pHeader); - - -USHORT APBuildAssociation( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN USHORT CapabilityInfo, - IN UCHAR MaxSupportedRateIn500Kbps, - IN UCHAR *RSN, - IN UCHAR *pRSNLen, - IN BOOLEAN bWmmCapable, - IN ULONG RalinkIe, -#ifdef DOT11N_DRAFT3 - IN EXT_CAP_INFO_ELEMENT ExtCapInfo, -#endif // DOT11N_DRAFT3 // - IN HT_CAPABILITY_IE *pHtCapability, - IN UCHAR HtCapabilityLen, - OUT USHORT *pAid); - -/* -VOID RTMPAddClientSec( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIdx, - IN UCHAR KeyIdx, - IN UCHAR CipherAlg, - IN PUCHAR pKey, - IN PUCHAR pTxMic, - IN PUCHAR pRxMic, - IN MAC_TABLE_ENTRY *pEntry); -*/ - -// ap_auth.c - -void APAuthStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *Sm, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID APCls2errAction( - IN PRTMP_ADAPTER pAd, - IN ULONG Wcid, - IN PHEADER_802_11 pHeader); - -// ap_connect.c - - -VOID APMakeBssBeacon( - IN PRTMP_ADAPTER pAd, - IN INT apidx); - -VOID APUpdateBeaconFrame( - IN PRTMP_ADAPTER pAd, - IN INT apidx); - -VOID APMakeAllBssBeacon( - IN PRTMP_ADAPTER pAd); - -VOID APUpdateAllBeaconFrame( - IN PRTMP_ADAPTER pAd); - - -// ap_sync.c - -VOID APSyncStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *Sm, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID APScanTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID APInvalidStateWhenScan( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID APScanTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID APPeerProbeReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID APPeerBeaconAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID APMlmeScanReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID APPeerBeaconAtScanAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID APScanCnclAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID ApSiteSurvey( - IN PRTMP_ADAPTER pAd, - IN PNDIS_802_11_SSID pSsid, - IN UCHAR ScanType); - -VOID SupportRate( - IN PUCHAR SupRate, - IN UCHAR SupRateLen, - IN PUCHAR ExtRate, - IN UCHAR ExtRateLen, - OUT PUCHAR *Rates, - OUT PUCHAR RatesLen, - OUT PUCHAR pMaxSupportRate); - - -BOOLEAN ApScanRunning( - IN PRTMP_ADAPTER pAd); - -#ifdef DOT11N_DRAFT3 -VOID APOverlappingBSSScan( - IN RTMP_ADAPTER *pAd); -#endif // DOT11N_DRAFT3 // - -// ap_wpa.c -VOID WpaStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *Sm, - OUT STATE_MACHINE_FUNC Trans[]); - -// ap_mlme.c -VOID APMlmePeriodicExec( - IN PRTMP_ADAPTER pAd); - -VOID APMlmeSelectTxRateTable( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PUCHAR *ppTable, - IN PUCHAR pTableSize, - IN PUCHAR pInitTxRateIdx); - -VOID APMlmeSetTxRate( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PRTMP_TX_RATE_SWITCH pTxRate); - -VOID APMlmeDynamicTxRateSwitching( - IN PRTMP_ADAPTER pAd); - -VOID APQuickResponeForRateUpExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -BOOLEAN APMsgTypeSubst( - IN PRTMP_ADAPTER pAd, - IN PFRAME_802_11 pFrame, - OUT INT *Machine, - OUT INT *MsgType); - -VOID APQuickResponeForRateUpExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - - -VOID RTMPSetPiggyBack( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bPiggyBack); - -VOID APAsicEvaluateRxAnt( - IN PRTMP_ADAPTER pAd); - -VOID APAsicRxAntEvalTimeout( - IN PRTMP_ADAPTER pAd); - -// ap.c - -VOID APSwitchChannel( - IN PRTMP_ADAPTER pAd, - IN INT Channel); - -NDIS_STATUS APInitialize( - IN PRTMP_ADAPTER pAd); - -VOID APShutdown( - IN PRTMP_ADAPTER pAd); - -VOID APStartUp( - IN PRTMP_ADAPTER pAd); - -VOID APStop( - IN PRTMP_ADAPTER pAd); - -VOID APCleanupPsQueue( - IN PRTMP_ADAPTER pAd, - IN PQUEUE_HEADER pQueue); - -VOID MacTableReset( - IN PRTMP_ADAPTER pAd); - -MAC_TABLE_ENTRY *MacTableInsertEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN UCHAR apidx, - IN BOOLEAN CleanAll); - -BOOLEAN MacTableDeleteEntry( - IN PRTMP_ADAPTER pAd, - IN USHORT wcid, - IN PUCHAR pAddr); - -MAC_TABLE_ENTRY *MacTableLookup( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr); - -VOID MacTableMaintenance( - IN PRTMP_ADAPTER pAd); - -UINT32 MacTableAssocStaNumGet( - IN PRTMP_ADAPTER pAd); - -MAC_TABLE_ENTRY *APSsPsInquiry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - OUT SST *Sst, - OUT USHORT *Aid, - OUT UCHAR *PsMode, - OUT UCHAR *Rate); - -BOOLEAN APPsIndicate( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN ULONG Wcid, - IN UCHAR Psm); - -VOID ApLogEvent( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN USHORT Event); - -#ifdef DOT11_N_SUPPORT -VOID APUpdateOperationMode( - IN PRTMP_ADAPTER pAd); -#endif // DOT11_N_SUPPORT // - -VOID APUpdateCapabilityAndErpIe( - IN PRTMP_ADAPTER pAd); - -BOOLEAN ApCheckAccessControlList( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN UCHAR Apidx); - -VOID ApUpdateAccessControlList( - IN PRTMP_ADAPTER pAd, - IN UCHAR Apidx); - -VOID ApEnqueueNullFrame( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN UCHAR TxRate, - IN UCHAR PID, - IN UCHAR apidx, - IN BOOLEAN bQosNull, - IN BOOLEAN bEOSP, - IN UCHAR OldUP); - -VOID ApSendFrame( - IN PRTMP_ADAPTER pAd, - IN PVOID pBuffer, - IN ULONG Length, - IN UCHAR TxRate, - IN UCHAR PID); - -VOID ApEnqueueAckFrame( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN UCHAR TxRate, - IN UCHAR apidx); - -// ap_sanity.c - - -BOOLEAN PeerAssocReqCmmSanity( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN isRessoc, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *pCapabilityInfo, - OUT USHORT *pListenInterval, - OUT PUCHAR pApAddr, - OUT UCHAR *pSsidLen, - OUT char *Ssid, - OUT UCHAR *pRatesLen, - OUT UCHAR Rates[], - OUT UCHAR *RSN, - OUT UCHAR *pRSNLen, - OUT BOOLEAN *pbWmmCapable, - OUT ULONG *pRalinkIe, -#ifdef DOT11N_DRAFT3 - OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, -#endif // DOT11N_DRAFT3 // - OUT UCHAR *pHtCapabilityLen, - OUT HT_CAPABILITY_IE *pHtCapability); - - -BOOLEAN PeerDisassocReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *Reason); - -BOOLEAN PeerDeauthReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *Reason); - -BOOLEAN APPeerAuthSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr1, - OUT PUCHAR pAddr2, - OUT USHORT *Alg, - OUT USHORT *Seq, - OUT USHORT *Status, - OUT CHAR *ChlgText - ); - -BOOLEAN APPeerProbeReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT CHAR Ssid[], - OUT UCHAR *SsidLen); - -BOOLEAN APPeerBeaconAndProbeRspSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT PUCHAR pBssid, - OUT CHAR Ssid[], - OUT UCHAR *SsidLen, - OUT UCHAR *BssType, - OUT USHORT *BeaconPeriod, - OUT UCHAR *Channel, - OUT LARGE_INTEGER *Timestamp, - OUT USHORT *CapabilityInfo, - OUT UCHAR Rate[], - OUT UCHAR *RateLen, - OUT BOOLEAN *ExtendedRateIeExist, - OUT UCHAR *Erp); -#if defined(RT30xx) || defined(RT305x) -VOID EnableAPMIMOPS( - IN PRTMP_ADAPTER pAd); - -VOID DisableAPMIMOPS( - IN PRTMP_ADAPTER pAd); -#endif -#endif // __AP_H__ diff --git a/drivers/staging/rt3090/ap_apcli.h b/drivers/staging/rt3090/ap_apcli.h deleted file mode 100644 index d363c36b82872e74338fd4628f6a5f287f1e91b5..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/ap_apcli.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - ap_apcli.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Shiang, Fonchi 02-13-2007 created -*/ - -#ifndef _AP_APCLI_H_ -#define _AP_APCLI_H_ - -#ifdef APCLI_SUPPORT - -#include "rtmp.h" - -#define AUTH_TIMEOUT 300 // unit: msec -#define ASSOC_TIMEOUT 300 // unit: msec -//#define JOIN_TIMEOUT 2000 // unit: msec // not used in Ap-client mode, remove it -#define PROBE_TIMEOUT 1000 // unit: msec - -#define APCLI_ROOT_BSSID_GET(pAd, wcid) ((pAd)->MacTab.Content[(wcid)].Addr) -#define APCLI_IF_UP_CHECK(pAd, ifidx) ((pAd)->ApCfg.ApCliTab[(ifidx)].dev->flags & IFF_UP) - -/* sanity check for apidx */ -#define APCLI_MR_APIDX_SANITY_CHECK(idx) \ -{ \ - if ((idx) >= MAX_APCLI_NUM) \ - { \ - (idx) = 0; \ - DBGPRINT(RT_DEBUG_ERROR, ("%s> Error! apcli-idx > MAX_APCLI_NUM!\n", __FUNCTION__)); \ - } \ -} - -typedef struct _APCLI_MLME_JOIN_REQ_STRUCT { - UCHAR Bssid[MAC_ADDR_LEN]; - UCHAR SsidLen; - UCHAR Ssid[MAX_LEN_OF_SSID]; -} APCLI_MLME_JOIN_REQ_STRUCT; - -typedef struct _STA_CTRL_JOIN_REQ_STRUCT { - USHORT Status; -} APCLI_CTRL_MSG_STRUCT, *PSTA_CTRL_MSG_STRUCT; - -BOOLEAN isValidApCliIf( - SHORT ifIndex); - -// -// Private routines in apcli_ctrl.c -// -VOID ApCliCtrlStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE_EX *Sm, - OUT STATE_MACHINE_FUNC_EX Trans[]); - -// -// Private routines in apcli_sync.c -// -VOID ApCliSyncStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE_EX *Sm, - OUT STATE_MACHINE_FUNC_EX Trans[]); - -// -// Private routines in apcli_auth.c -// -VOID ApCliAuthStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE_EX *Sm, - OUT STATE_MACHINE_FUNC_EX Trans[]); - -// -// Private routines in apcli_assoc.c -// -VOID ApCliAssocStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE_EX *Sm, - OUT STATE_MACHINE_FUNC_EX Trans[]); - -MAC_TABLE_ENTRY *ApCliTableLookUpByWcid( - IN PRTMP_ADAPTER pAd, - IN UCHAR wcid, - IN PUCHAR pAddrs); - - -BOOLEAN ApCliAllowToSendPacket( - IN RTMP_ADAPTER *pAd, - IN PNDIS_PACKET pPacket, - OUT UCHAR *pWcid); - -BOOLEAN ApCliValidateRSNIE( - IN PRTMP_ADAPTER pAd, - IN PEID_STRUCT pEid_ptr, - IN USHORT eid_len, - IN USHORT idx); - -VOID RT28xx_ApCli_Init( - IN PRTMP_ADAPTER pAd, - IN PNET_DEV pPhyNetDev); - -VOID RT28xx_ApCli_Close( - IN PRTMP_ADAPTER pAd); - -VOID RT28xx_ApCli_Remove( - IN PRTMP_ADAPTER pAd); - - -VOID RT28xx_ApCli_Remove( - IN PRTMP_ADAPTER ad_p); - -INT ApCliIfLookUp( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr); - -INT ApCli_VirtualIF_Open( - IN PNET_DEV dev_p); - -INT ApCli_VirtualIF_Close( - IN PNET_DEV dev_p); - -INT ApCli_VirtualIF_PacketSend( - IN PNDIS_PACKET skb_p, - IN PNET_DEV dev_p); - -INT ApCli_VirtualIF_Ioctl( - IN PNET_DEV dev_p, - IN OUT struct ifreq *rq_p, - IN INT cmd); - - -VOID ApCliMgtMacHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PHEADER_802_11 pHdr80211, - IN UCHAR SubType, - IN UCHAR ToDs, - IN PUCHAR pDA, - IN PUCHAR pBssid, - IN USHORT ifIndex); - -#ifdef DOT11_N_SUPPORT -BOOLEAN ApCliCheckHt( - IN PRTMP_ADAPTER pAd, - IN USHORT IfIndex, - IN OUT HT_CAPABILITY_IE *pHtCapability, - IN OUT ADD_HT_INFO_IE *pAddHtInfo); -#endif // DOT11_N_SUPPORT // - -BOOLEAN ApCliLinkUp( - IN PRTMP_ADAPTER pAd, - IN UCHAR ifIndex); - -VOID ApCliLinkDown( - IN PRTMP_ADAPTER pAd, - IN UCHAR ifIndex); - -VOID ApCliIfUp( - IN PRTMP_ADAPTER pAd); - -VOID ApCliIfDown( - IN PRTMP_ADAPTER pAd); - -VOID ApCliIfMonitor( - IN PRTMP_ADAPTER pAd); - -BOOLEAN ApCliMsgTypeSubst( - IN PRTMP_ADAPTER pAd, - IN PFRAME_802_11 pFrame, - OUT INT *Machine, - OUT INT *MsgType); - -BOOLEAN preCheckMsgTypeSubset( - IN PRTMP_ADAPTER pAd, - IN PFRAME_802_11 pFrame, - OUT INT *Machine, - OUT INT *MsgType); - -BOOLEAN ApCliPeerAssocRspSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *pCapabilityInfo, - OUT USHORT *pStatus, - OUT USHORT *pAid, - OUT UCHAR SupRate[], - OUT UCHAR *pSupRateLen, - OUT UCHAR ExtRate[], - OUT UCHAR *pExtRateLen, - OUT HT_CAPABILITY_IE *pHtCapability, - OUT ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE - OUT UCHAR *pHtCapabilityLen, - OUT UCHAR *pAddHtInfoLen, - OUT UCHAR *pNewExtChannelOffset, - OUT PEDCA_PARM pEdcaParm, - OUT UCHAR *pCkipFlag); - -VOID ApCliPeerPairMsg1Action( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN MLME_QUEUE_ELEM *Elem); - -VOID ApCliPeerPairMsg3Action( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN MLME_QUEUE_ELEM *Elem); - -VOID ApCliPeerGroupMsg1Action( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN MLME_QUEUE_ELEM *Elem); - -BOOLEAN ApCliCheckRSNIE( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN UCHAR DataLen, - IN MAC_TABLE_ENTRY *pEntry, - OUT UCHAR *Offset); - -BOOLEAN ApCliParseKeyData( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKeyData, - IN UCHAR KeyDataLen, - IN MAC_TABLE_ENTRY *pEntry, - IN UCHAR IfIdx, - IN UCHAR bPairewise); - -BOOLEAN ApCliHandleRxBroadcastFrame( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN MAC_TABLE_ENTRY *pEntry, - IN UCHAR FromWhichBSSID); - -VOID APCliUpdatePairwiseKeyTable( - IN PRTMP_ADAPTER pAd, - IN UCHAR *KeyRsc, - IN MAC_TABLE_ENTRY *pEntry); - -BOOLEAN APCliUpdateSharedKeyTable( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKey, - IN UCHAR KeyLen, - IN UCHAR DefaultKeyIdx, - IN MAC_TABLE_ENTRY *pEntry); - -#endif // APCLI_SUPPORT // - -#endif /* _AP_APCLI_H_ */ diff --git a/drivers/staging/rt3090/ap_autoChSel.h b/drivers/staging/rt3090/ap_autoChSel.h deleted file mode 100644 index 46881ff857ac843b11ed4c1cefbac497cb10c76d..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/ap_autoChSel.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - ap_autoChSel.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#include "ap_autoChSel_cmm.h" - -#ifndef __AUTOCHSELECT_H__ -#define __AUTOCHSELECT_H__ - -#ifdef AUTO_CH_SELECT_ENHANCE -#define AP_AUTO_CH_SEL(__P, __O) New_APAutoSelectChannel((__P), (__O)) -#else -#define AP_AUTO_CH_SEL(__P, __O) APAutoSelectChannel((__P), (__O)) -#endif - - -ULONG AutoChBssInsertEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pBssid, - IN CHAR Ssid[], - IN UCHAR SsidLen, - IN UCHAR ChannelNo, - IN UCHAR ExtChOffset, - IN CHAR Rssi); - -void AutoChBssTableInit( - IN PRTMP_ADAPTER pAd); - -void ChannelInfoInit( - IN PRTMP_ADAPTER pAd); - -void AutoChBssTableDestroy( - IN PRTMP_ADAPTER pAd); - -void ChannelInfoDestroy( - IN PRTMP_ADAPTER pAd); - -UCHAR New_APAutoSelectChannel( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN Optimal); - -UCHAR APAutoSelectChannel( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN Optimal); - -#endif // __AUTOCHSELECT_H__ // diff --git a/drivers/staging/rt3090/ap_autoChSel_cmm.h b/drivers/staging/rt3090/ap_autoChSel_cmm.h deleted file mode 100644 index ad77ec125625b25e96dd2048be781caef618f461..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/ap_autoChSel_cmm.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - ap_autoChSel_cmm.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - - -#ifndef __AUTOCHSELECT_CMM_H__ -#define __AUTOCHSELECT_CMM_H__ - -#define RSSI_TO_DBM_OFFSET 120 // RSSI-115 = dBm - - -typedef struct { - ULONG dirtyness[MAX_NUM_OF_CHANNELS+1]; - ULONG max_rssi[MAX_NUM_OF_CHANNELS+1]; - ULONG total_rssi[MAX_NUM_OF_CHANNELS+1]; - UINT32 FalseCCA[MAX_NUM_OF_CHANNELS+1]; -} CHANNELINFO, *PCHANNELINFO; - -typedef struct { - UCHAR Bssid[MAC_ADDR_LEN]; - UCHAR SsidLen; - CHAR Ssid[MAX_LEN_OF_SSID]; - UCHAR Channel; - UCHAR ExtChOffset; - UCHAR Rssi; -} BSSENTRY, *PBSSENTRY; - -typedef struct { - UCHAR BssNr; - BSSENTRY BssEntry[MAX_LEN_OF_BSS_TABLE]; -} BSSINFO, *PBSSINFO; - -#endif // __AUTOCHSELECT_CMM_H__ // diff --git a/drivers/staging/rt3090/ap_cfg.h b/drivers/staging/rt3090/ap_cfg.h deleted file mode 100644 index 7c99423900ad3f7964f675a878c3dbfb3f47573f..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/ap_cfg.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - ap_cfg.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ -#ifndef __AP_CFG_H__ -#define __AP_CFG_H__ - - -#include "rt_config.h" - -INT RTMPAPPrivIoctlSet( - IN RTMP_ADAPTER *pAd, - IN struct iwreq *pIoctlCmdStr); - -INT RTMPAPPrivIoctlShow( - IN RTMP_ADAPTER *pAd, - IN struct iwreq *pIoctlCmdStr); - -INT RTMPAPSetInformation( - IN PRTMP_ADAPTER pAd, - IN OUT struct iwreq *rq, - IN INT cmd); - -INT RTMPAPQueryInformation( - IN PRTMP_ADAPTER pAd, - IN OUT struct iwreq *rq, - IN INT cmd); - -VOID RTMPIoctlStatistics( - IN PRTMP_ADAPTER pAd, - IN struct iwreq *wrq); - -VOID RTMPIoctlGetMacTable( - IN PRTMP_ADAPTER pAd, - IN struct iwreq *wrq); - -#ifdef DBG -VOID RTMPAPIoctlBBP( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq); - -VOID RTMPAPIoctlMAC( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq); - -VOID RTMPAPIoctlE2PROM( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq); - -#ifdef RTMP_RF_RW_SUPPORT -VOID RTMPAPIoctlRF( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq); -#endif // RTMP_RF_RW_SUPPORT // - -#endif // DBG // - -VOID RT28XX_IOCTL_MaxRateGet( - IN RTMP_ADAPTER *pAd, - IN PHTTRANSMIT_SETTING pHtPhyMode, - OUT UINT32 *pRate); - - -#ifdef DOT11_N_SUPPORT -VOID RTMPIoctlQueryBaTable( - IN PRTMP_ADAPTER pAd, - IN struct iwreq *wrq); -#endif // DOT11_N_SUPPORT // - -VOID RTMPIoctlStaticWepCopy( - IN PRTMP_ADAPTER pAd, - IN struct iwreq *wrq); - -VOID RTMPIoctlRadiusData( - IN PRTMP_ADAPTER pAd, - IN struct iwreq *wrq); - -VOID RTMPIoctlAddWPAKey( - IN PRTMP_ADAPTER pAd, - IN struct iwreq *wrq); - -VOID RTMPIoctlAddPMKIDCache( - IN PRTMP_ADAPTER pAd, - IN struct iwreq *wrq); - -#endif // __AP_CFG_H__ // diff --git a/drivers/staging/rt3090/ap_ids.h b/drivers/staging/rt3090/ap_ids.h deleted file mode 100644 index cf8797f7f580985ae78fd4a7c69b9c1989e5ec67..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/ap_ids.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - ap_ids.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -VOID RTMPIdsPeriodicExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -BOOLEAN RTMPSpoofedMgmtDetection( - IN PRTMP_ADAPTER pAd, - IN PHEADER_802_11 pHeader, - IN CHAR Rssi0, - IN CHAR Rssi1, - IN CHAR Rssi2); - -VOID RTMPConflictSsidDetection( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pSsid, - IN UCHAR SsidLen, - IN CHAR Rssi0, - IN CHAR Rssi1, - IN CHAR Rssi2); - -BOOLEAN RTMPReplayAttackDetection( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr2, - IN CHAR Rssi0, - IN CHAR Rssi1, - IN CHAR Rssi2); - -VOID RTMPUpdateStaMgmtCounter( - IN PRTMP_ADAPTER pAd, - IN USHORT type); - -VOID RTMPClearAllIdsCounter( - IN PRTMP_ADAPTER pAd); - -VOID RTMPIdsStart( - IN PRTMP_ADAPTER pAd); - -VOID RTMPIdsStop( - IN PRTMP_ADAPTER pAd); - -VOID rtmp_read_ids_from_file( - IN PRTMP_ADAPTER pAd, - char *tmpbuf, - char *buffer); diff --git a/drivers/staging/rt3090/ap_mbss.h b/drivers/staging/rt3090/ap_mbss.h deleted file mode 100644 index f78556c529a8b89549d6f6ce94f20b189c60183f..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/ap_mbss.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - ap_mbss.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#ifndef MODULE_MBSS - -#define MBSS_EXTERN extern - -#else - -#define MBSS_EXTERN - -#endif // MODULE_MBSS // - - -/* Public function list */ -MBSS_EXTERN VOID RT28xx_MBSS_Init( - IN PRTMP_ADAPTER ad_p, - IN PNET_DEV main_dev_p); - -MBSS_EXTERN VOID RT28xx_MBSS_Close( - IN PRTMP_ADAPTER ad_p); - -MBSS_EXTERN VOID RT28xx_MBSS_Remove( - IN PRTMP_ADAPTER ad_p); - -INT MBSS_VirtualIF_Open( - IN PNET_DEV dev_p); -INT MBSS_VirtualIF_Close( - IN PNET_DEV dev_p); -INT MBSS_VirtualIF_PacketSend( - IN PNDIS_PACKET skb_p, - IN PNET_DEV dev_p); -INT MBSS_VirtualIF_Ioctl( - IN PNET_DEV dev_p, - IN OUT struct ifreq *rq_p, - IN INT cmd); - -/* End of ap_mbss.h */ diff --git a/drivers/staging/rt3090/ap_uapsd.h b/drivers/staging/rt3090/ap_uapsd.h deleted file mode 100644 index d49a9e7500b4fd812005396c6f9a3ff878b55c77..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/ap_uapsd.h +++ /dev/null @@ -1,636 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - ap_uapsd.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -/* only for UAPSD_TIMING_RECORD */ - -//#define UAPSD_TIMING_RECORD_FUNC - -#define UAPSD_TIMING_RECORD_MAX 1000 -#define UAPSD_TIMING_RECORD_DISPLAY_TIMES 10 - -#define UAPSD_TIMING_RECORD_ISR 1 -#define UAPSD_TIMING_RECORD_TASKLET 2 -#define UAPSD_TIMING_RECORD_TRG_RCV 3 -#define UAPSD_TIMING_RECORD_MOVE2TX 4 -#define UAPSD_TIMING_RECORD_TX2AIR 5 - -#define UAPSD_TIMING_CTRL_STOP 0 -#define UAPSD_TIMING_CTRL_START 1 -#define UAPSD_TIMING_CTRL_SUSPEND 2 - -#define UAPSD_TIMESTAMP_GET(__pAd, __TimeStamp) \ - { \ - UINT32 __CSR=0; UINT64 __Value64; \ - RTMP_IO_READ32((__pAd), TSF_TIMER_DW0, &__CSR); \ - __TimeStamp = (UINT64)__CSR; \ - RTMP_IO_READ32((__pAd), TSF_TIMER_DW1, &__CSR); \ - __Value64 = (UINT64)__CSR; \ - __TimeStamp |= (__Value64 << 32); \ - } - -#ifdef LINUX -#define UAPSD_TIME_GET(__pAd, __Time) \ - __Time = jiffies -#endif // LINUX // - - -#ifdef UAPSD_TIMING_RECORD_FUNC -#define UAPSD_TIMING_RECORD_START() \ - UAPSD_TimingRecordCtrl(UAPSD_TIMING_CTRL_START); -#define UAPSD_TIMING_RECORD_STOP() \ - UAPSD_TimingRecordCtrl(UAPSD_TIMING_CTRL_STOP); -#define UAPSD_TIMING_RECORD(__pAd, __Type) \ - UAPSD_TimingRecord(__pAd, __Type); -#define UAPSD_TIMING_RECORD_INDEX(__LoopIndex) \ - UAPSD_TimeingRecordLoopIndex(__LoopIndex); -#else - -#define UAPSD_TIMING_RECORD_START() -#define UAPSD_TIMING_RECORD_STOP() -#define UAPSD_TIMING_RECORD(__pAd, __type) -#define UAPSD_TIMING_RECORD_INDEX(__LoopIndex) -#endif // UAPSD_TIMING_RECORD_FUNC // - - -#ifndef MODULE_WMM_UAPSD - -#define UAPSD_EXTERN extern - -/* Public Marco list */ - -/* - Init some parameters in packet structure for QoS Null frame; - purpose: is for management frame tx done use -*/ -#define UAPSD_MR_QOS_NULL_HANDLE(__pAd, __pData, __pPacket) \ - { \ - PHEADER_802_11 __pHeader = (PHEADER_802_11)(__pData); \ - MAC_TABLE_ENTRY *__pEntry; \ - if (__pHeader->FC.SubType == SUBTYPE_QOS_NULL) \ - { \ - RTMP_SET_PACKET_QOS_NULL((__pPacket)); \ - __pEntry = MacTableLookup((__pAd), __pHeader->Addr1); \ - if (__pEntry != NULL) \ - { \ - RTMP_SET_PACKET_WCID((__pPacket), __pEntry->Aid); \ - } \ - } \ - else \ - { \ - RTMP_SET_PACKET_NON_QOS_NULL((__pPacket)); \ - } \ - } - -/* - Init MAC entry UAPSD parameters; - purpose: initialize UAPSD PS queue and control parameters -*/ -#define UAPSD_MR_ENTRY_INIT(__pEntry) \ - { \ - UINT16 __IdAc; \ - for(__IdAc=0; __IdAcUAPSDQueue[__IdAc]); \ - (__pEntry)->UAPSDTxNum = 0; \ - (__pEntry)->pUAPSDEOSPFrame = NULL; \ - (__pEntry)->bAPSDFlagSPStart = 0; \ - (__pEntry)->bAPSDFlagEOSPOK = 0; \ - (__pEntry)->MaxSPLength = 0; \ - } - -/* - Reset MAC entry UAPSD parameters; - purpose: clean all UAPSD PS queue; release the EOSP frame if exists; - reset control parameters -*/ -#define UAPSD_MR_ENTRY_RESET(__pAd, __pEntry) \ - { \ - MAC_TABLE_ENTRY *__pSta; \ - UINT32 __IdAc; \ - __pSta = (__pEntry); \ - /* clear all U-APSD queues */ \ - for(__IdAc=0; __IdAcUAPSDQueue[__IdAc]); \ - /* clear EOSP frame */ \ - __pSta->UAPSDTxNum = 0; \ - if (__pSta->pUAPSDEOSPFrame != NULL) { \ - RELEASE_NDIS_PACKET((__pAd), \ - QUEUE_ENTRY_TO_PACKET(__pSta->pUAPSDEOSPFrame), \ - NDIS_STATUS_FAILURE); \ - __pSta->pUAPSDEOSPFrame = NULL; } \ - __pSta->bAPSDFlagSPStart = 0; \ - __pSta->bAPSDFlagEOSPOK = 0; } - -/* - Enable or disable UAPSD flag in WMM element in beacon frame; - purpose: set UAPSD enable/disable bit -*/ -#define UAPSD_MR_IE_FILL(__QosCtrlField, __pAd) \ - (__QosCtrlField) |= ((__pAd)->CommonCfg.bAPSDCapable) ? 0x80 : 0x00; - -/* - Check if we do NOT need to control TIM bit for the station; - note: we control TIM bit only when all AC are UAPSD AC -*/ -#define UAPSD_MR_IS_NOT_TIM_BIT_NEEDED_HANDLED(__pMacEntry, __QueIdx) \ - (CLIENT_STATUS_TEST_FLAG((__pMacEntry), fCLIENT_STATUS_APSD_CAPABLE) && \ - (!(__pMacEntry)->bAPSDDeliverEnabledPerAC[QID_AC_VO] || \ - !(__pMacEntry)->bAPSDDeliverEnabledPerAC[QID_AC_VI] || \ - !(__pMacEntry)->bAPSDDeliverEnabledPerAC[QID_AC_BE] || \ - !(__pMacEntry)->bAPSDDeliverEnabledPerAC[QID_AC_BK]) && \ - (__pMacEntry)->bAPSDDeliverEnabledPerAC[__QueIdx]) - -/* check if the AC is UAPSD delivery-enabled AC */ -#define UAPSD_MR_IS_UAPSD_AC(__pMacEntry, __AcId) \ - (CLIENT_STATUS_TEST_FLAG((__pMacEntry), fCLIENT_STATUS_APSD_CAPABLE) && \ - ((0 <= (__AcId)) && ((__AcId) < WMM_NUM_OF_AC)) && /* 0 ~ 3 */ \ - (__pMacEntry)->bAPSDDeliverEnabledPerAC[(__AcId)]) - -/* check if all AC are UAPSD delivery-enabled AC */ -#define UAPSD_MR_IS_ALL_AC_UAPSD(__FlgIsActive, __pMacEntry) \ - (((__FlgIsActive) == FALSE) && ((__pMacEntry)->bAPSDAllAC == 1)) - -/* suspend SP */ -#define UAPSD_MR_SP_SUSPEND(__pAd) \ - (__pAd)->bAPSDFlagSPSuspend = 1; - -/* resume SP */ -#define UAPSD_MR_SP_RESUME(__pAd) \ - (__pAd)->bAPSDFlagSPSuspend = 0; - -/* mark PS poll frame sent in mix mode */ -#ifdef RTMP_MAC_PCI -/* - Note: - (1) When SP is not started, try to mark a flag to record if the legacy ps - packet is handled in statistics handler; - (2) When SP is started, increase the UAPSD count number for the legacy PS. -*/ -#define UAPSD_MR_MIX_PS_POLL_RCV(__pAd, __pMacEntry) \ - if ((__pMacEntry)->bAPSDFlagSpRoughUse == 0) \ - { \ - if ((__pMacEntry)->bAPSDFlagSPStart == 0) \ - { \ - if ((__pMacEntry)->bAPSDFlagLegacySent == 1) \ - NICUpdateFifoStaCounters((__pAd)); \ - (__pMacEntry)->bAPSDFlagLegacySent = 1; \ - } \ - else \ - { \ - (__pMacEntry)->UAPSDTxNum ++; \ - } \ - } -#endif // RTMP_MAC_PCI // - - -#else - -#define UAPSD_EXTERN -#define UAPSD_QOS_NULL_QUE_ID 0x7f - -#ifdef RTMP_MAC_PCI -/* - In RT2870, FIFO counter is for all stations, not for per-entry, - so we can not use accurate method in RT2870 -*/ - -/* - Note for SP ACCURATE Mechanism: - 1. When traffic is busy for the PS station - Statistics FIFO counter maybe overflow before we read it, so UAPSD - counting mechanism will not accurately. - - Solution: - We need to avoid the worse case so we suggest a maximum interval for - a SP that the interval between last frame from QAP and data frame from - QSTA is larger than UAPSD_EPT_SP_INT. - - 2. When traffic use CCK/1Mbps from QAP - Statistics FIFO will not count the packet. There are 2 cases: - (1) We force to downgrage ARP response & DHCP packet to 1Mbps; - (2) After rate switch mechanism, tx rate is fixed to 1Mbps. - - Solution: - Use old DMA UAPSD mechanism. - - 3. When part of AC uses legacy PS mode - Statistics count will inclue packet statistics for legacy PS packets - so we can not know which one is UAPSD, which one is legacy. - - Solution: - Cound the legacy PS packet. - - 4. Check FIFO statistics count in Rx Done function - We can not to check TX FIFO statistics count in Rx Done function or - the real packet tx/rx sequence will be disarranged. - - Solution: - Suspend SP handle before rx done and resume SP handle after rx done. -*/ -#define UAPSD_SP_ACCURATE /* use more accurate method to send EOSP */ -#endif // RTMP_MAC_PCI // - -#define UAPSD_EPT_SP_INT (100000/(1000000/OS_HZ)) /* 100ms */ - -#endif // MODULE_WMM_UAPSD // - - -/* max UAPSD buffer queue size */ -#define MAX_PACKETS_IN_UAPSD_QUEUE 16 /* for each AC = 16*4 = 64 */ - - -/* Public function list */ -/* -======================================================================== -Routine Description: - UAPSD Module Init. - -Arguments: - pAd Pointer to our adapter - -Return Value: - None - -Note: -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_Init( - IN PRTMP_ADAPTER pAd); - - -/* -======================================================================== -Routine Description: - UAPSD Module Release. - -Arguments: - pAd Pointer to our adapter - -Return Value: - None - -Note: -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_Release( - IN PRTMP_ADAPTER pAd); - - -/* -======================================================================== -Routine Description: - Free all EOSP frames and close all SP. - -Arguments: - pAd Pointer to our adapter - -Return Value: - None - -Note: -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_FreeAll( - IN PRTMP_ADAPTER pAd); - - -/* -======================================================================== -Routine Description: - Close current Service Period. - -Arguments: - pAd Pointer to our adapter - pEntry Close the SP of the entry - -Return Value: - None - -Note: -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_SP_Close( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry); - - -/* -======================================================================== -Routine Description: - Deliver all queued packets. - -Arguments: - pAd Pointer to our adapter - *pEntry STATION - -Return Value: - None - -Note: - SMP protection by caller for packet enqueue. -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_AllPacketDeliver( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry); - - -/* -======================================================================== -Routine Description: - Parse the UAPSD field in WMM element in (re)association request frame. - -Arguments: - pAd Pointer to our adapter - *pEntry STATION - *pElm QoS information field - -Return Value: - None - -Note: - No protection is needed. - - 1. Association -> TSPEC: - use static UAPSD settings in Association - update UAPSD settings in TSPEC - - 2. Association -> TSPEC(11r) -> Reassociation: - update UAPSD settings in TSPEC - backup static UAPSD settings in Reassociation - - 3. Association -> Reassociation: - update UAPSD settings in TSPEC - backup static UAPSD settings in Reassociation -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_AssocParse( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN UCHAR *pElm); - - -/* -======================================================================== -Routine Description: - Enqueue a UAPSD packet. - -Arguments: - pAd Pointer to our adapter - *pEntry STATION - pPacket UAPSD dnlink packet - IdAc UAPSD AC ID (0 ~ 3) - -Return Value: - None - -Note: -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_PacketEnqueue( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN PNDIS_PACKET pPacket, - IN UINT32 IdAc); - - -/* -======================================================================== -Routine Description: - Handle QoS Null Frame Tx Done or Management Tx Done interrupt. - -Arguments: - pAd Pointer to our adapter - pPacket Completed TX packet - pDstMac Destinated MAC address - -Return Value: - None - -Note: -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_QoSNullTxMgmtTxDoneHandle( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR *pDstMac); - - -/* -======================================================================== -Routine Description: - Maintenance our UAPSD PS queue. Release all queued packet if timeout. - -Arguments: - pAd Pointer to our adapter - *pEntry STATION - -Return Value: - None - -Note: - If in RT2870, pEntry can not be removed during UAPSD_QueueMaintenance() -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_QueueMaintenance( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry); - - -/* -======================================================================== -Routine Description: - Close SP in Tx Done, not Tx DMA Done. - -Arguments: - pAd Pointer to our adapter - pEntry destination entry - FlgSuccess 0:tx success, 1:tx fail - -Return Value: - None - -Note: - For RT28xx series, for packetID=0 or multicast frame, no statistics - count can be got, ex: ARP response or DHCP packets, we will use - low rate to set (CCK, MCS=0=packetID). - So SP will not be close until UAPSD_EPT_SP_INT timeout. - - So if the tx rate is 1Mbps for a entry, we will use DMA done, not - use UAPSD_SP_AUE_Handle(). -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_SP_AUE_Handle( - IN RTMP_ADAPTER *pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN UCHAR FlgSuccess); - - -/* -======================================================================== -Routine Description: - Close current Service Period. - -Arguments: - pAd Pointer to our adapter - -Return Value: - None - -Note: - When we receive EOSP frame tx done interrupt and a uplink packet - from the station simultaneously, we will regard it as a new trigger - frame because the packet is received when EOSP frame tx done interrupt. - - We can not sure the uplink packet is sent after old SP or in the old SP. - So we must close the old SP in receive done ISR to avoid the problem. -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_SP_CloseInRVDone( - IN PRTMP_ADAPTER pAd); - - -/* -======================================================================== -Routine Description: - Check if we need to close current SP. - -Arguments: - pAd Pointer to our adapter - pPacket Completed TX packet - pDstMac Destinated MAC address - -Return Value: - None - -Note: - 1. We need to call the function in TxDone ISR. - 2. SMP protection by caller for packet enqueue. -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_SP_PacketCheck( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR *pDstMac); - - -#ifdef UAPSD_TIMING_RECORD_FUNC -/* -======================================================================== -Routine Description: - Enable/Disable Timing Record Function. - -Arguments: - pAd Pointer to our adapter - Flag 1 (Enable) or 0 (Disable) - -Return Value: - None - -Note: -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_TimingRecordCtrl( - IN UINT32 Flag); - -/* -======================================================================== -Routine Description: - Record some timings. - -Arguments: - pAd Pointer to our adapter - Type The timing is for what type - -Return Value: - None - -Note: - UAPSD_TIMING_RECORD_ISR - UAPSD_TIMING_RECORD_TASKLET - UAPSD_TIMING_RECORD_TRG_RCV - UAPSD_TIMING_RECORD_MOVE2TX - UAPSD_TIMING_RECORD_TX2AIR -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_TimingRecord( - IN PRTMP_ADAPTER pAd, - IN UINT32 Type); - -/* -======================================================================== -Routine Description: - Record the loop index for received packet handle. - -Arguments: - pAd Pointer to our adapter - LoopIndex The RxProcessed in APRxDoneInterruptHandle() - -Return Value: - None - -Note: -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_TimeingRecordLoopIndex( - IN UINT32 LoopIndex); -#endif // UAPSD_TIMING_RECORD_FUNC // - - -/* -======================================================================== -Routine Description: - Handle UAPSD Trigger Frame. - -Arguments: - pAd Pointer to our adapter - *pEntry the source STATION - UpOfFrame the UP of the trigger frame - -Return Value: - None - -Note: -======================================================================== -*/ -UAPSD_EXTERN VOID UAPSD_TriggerFrameHandle( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN UCHAR UpOfFrame); - - - -/* End of ap_uapsd.h */ diff --git a/drivers/staging/rt3090/ap_wds.h b/drivers/staging/rt3090/ap_wds.h deleted file mode 100644 index efcb107db4ffe8e6365a06373f6382017c8b9231..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/ap_wds.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - ap_cfg.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Fonchi 02-13-2007 created -*/ - -#ifndef _AP_WDS_H_ -#define _AP_WDS_H_ - -#define WDS_ENTRY_RETRY_INTERVAL (100 * OS_HZ / 1000) - - -static inline BOOLEAN WDS_IF_UP_CHECK( - IN PRTMP_ADAPTER pAd, - IN ULONG ifidx) -{ - if ((pAd->flg_wds_init != TRUE) || - (ifidx >= MAX_WDS_ENTRY)) - return FALSE; - -// if (pAd->WdsTab.WdsEntry[ifidx].dev->flags & IFF_UP) -// Patch for wds ,when dirver call apmlmeperiod => APMlmeDynamicTxRateSwitching check if wds device ready -if ((pAd->WdsTab.WdsEntry[ifidx].dev != NULL) && (pAd->WdsTab.WdsEntry[ifidx].dev->flags & IFF_UP)) - return TRUE; - - return FALSE; -} - -LONG WdsEntryAlloc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr); - -VOID WdsEntryDel( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr); - -MAC_TABLE_ENTRY *MacTableInsertWDSEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - UINT WdsTabIdx); - -BOOLEAN MacTableDeleteWDSEntry( - IN PRTMP_ADAPTER pAd, - IN USHORT wcid, - IN PUCHAR pAddr); - - -BOOLEAN ApWdsAllowToSendPacket( - IN RTMP_ADAPTER *pAd, - IN PNDIS_PACKET pPacket, - OUT UCHAR *pWcid); - -MAC_TABLE_ENTRY *WdsTableLookupByWcid( - IN PRTMP_ADAPTER pAd, - IN UCHAR wcid, - IN PUCHAR pAddr, - IN BOOLEAN bResetIdelCount); - -MAC_TABLE_ENTRY *WdsTableLookup( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN BOOLEAN bResetIdelCount); - -MAC_TABLE_ENTRY *FindWdsEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN PUCHAR pAddr, - IN UINT32 PhyMode); - -VOID WdsTableMaintenance( - IN PRTMP_ADAPTER pAd); - -VOID RT28xx_WDS_Init( - IN PRTMP_ADAPTER pAd, - IN PNET_DEV net_dev); - -VOID RT28xx_WDS_Close( - IN PRTMP_ADAPTER pAd); - -VOID RT28xx_WDS_Remove( - IN PRTMP_ADAPTER pAd); - -VOID WdsDown( - IN PRTMP_ADAPTER pAd); - -VOID AsicUpdateWdsRxWCIDTable( - IN PRTMP_ADAPTER pAd); - -VOID AsicUpdateWdsEncryption( - IN PRTMP_ADAPTER pAd, - IN UCHAR wcid); - -VOID WdsPeerBeaconProc( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN USHORT CapabilityInfo, - IN UCHAR MaxSupportedRateIn500Kbps, - IN UCHAR MaxSupportedRateLen, - IN BOOLEAN bWmmCapable, - IN ULONG ClientRalinkIe, - IN HT_CAPABILITY_IE *pHtCapability, - IN UCHAR HtCapabilityLen); - -VOID APWdsInitialize( - IN PRTMP_ADAPTER pAd); - -INT Show_WdsTable_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -VOID rtmp_read_wds_from_file( - IN PRTMP_ADAPTER pAd, - PSTRING tmpbuf, - PSTRING buffer); - -VOID WdsPrepareWepKeyFromMainBss( - IN PRTMP_ADAPTER pAd); - -INT WdsVirtualIFSendPackets( - IN PNDIS_PACKET pSkb, - IN PNET_DEV dev); - -INT WdsVirtualIF_open( - IN PNET_DEV dev); - -INT WdsVirtualIF_close( - IN PNET_DEV dev); - -INT WdsVirtualIF_ioctl( - IN PNET_DEV net_dev, - IN OUT struct ifreq *rq, - IN INT cmd); - -/* - ========================================================================== - Description: - Check the WDS Entry is valid or not. - ========================================================================== - */ -static inline BOOLEAN ValidWdsEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR WdsIndex) -{ - BOOLEAN result; - PMAC_TABLE_ENTRY pMacEntry; - - do - { - if (WdsIndex >= MAX_WDS_ENTRY) - { - result = FALSE; - break; - } - - if (pAd->WdsTab.WdsEntry[WdsIndex].Valid != TRUE) - { - result = FALSE; - break; - } - - if ((pAd->WdsTab.WdsEntry[WdsIndex].MacTabMatchWCID==0) - || (pAd->WdsTab.WdsEntry[WdsIndex].MacTabMatchWCID >= MAX_LEN_OF_MAC_TABLE)) - { - result = FALSE; - break; - } - - pMacEntry = &pAd->MacTab.Content[pAd->WdsTab.WdsEntry[WdsIndex].MacTabMatchWCID]; - if (pMacEntry->ValidAsWDS != TRUE) - { - result = FALSE; - break; - } - - result = TRUE; - } while(FALSE); - - return result; -} -#endif // _AP_WDS_H_ // diff --git a/drivers/staging/rt3090/chips/rt3370.c b/drivers/staging/rt3090/chips/rt3370.c deleted file mode 100644 index 38ecb0623424e3856b8fdd4311aaebd59c2a9ed3..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/chips/rt3370.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rt3370.c - - Abstract: - Specific funcitons and variables for RT30xx. - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#ifdef RT3370 - -#include "../rt_config.h" - - -#ifndef RTMP_RF_RW_SUPPORT -#error "You Should Enable compile flag RTMP_RF_RW_SUPPORT for this chip" -#endif // RTMP_RF_RW_SUPPORT // - - -VOID NICInitRT3370RFRegisters(IN PRTMP_ADAPTER pAd) -{ - INT i; - // Driver must read EEPROM to get RfIcType before initial RF registers - // Initialize RF register to default value - if (IS_RT3090(pAd)||IS_RT3390(pAd)||IS_RT3572(pAd)) - { - // Init RF calibration - // Driver should toggle RF R30 bit7 before init RF registers - UINT32 RfReg = 0, data; - - RT30xxReadRFRegister(pAd, RF_R30, (PUCHAR)&RfReg); - RfReg |= 0x80; - RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg); - RTMPusecDelay(1000); - RfReg &= 0x7F; - RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg); - - // init R24, R31 - RT30xxWriteRFRegister(pAd, RF_R24, 0x0F); - RT30xxWriteRFRegister(pAd, RF_R31, 0x0F); - - if (IS_RT3390(pAd)) - { - // patch LNA_PE_G1 failed issue - RTMP_IO_READ32(pAd, GPIO_SWITCH, &data); - data &= ~(0x20); - RTMP_IO_WRITE32(pAd, GPIO_SWITCH, data); - - // RF registers initialization - for (i = 0; i < NUM_RF_REG_PARMS_OVER_RT3390; i++) - { - RT30xxWriteRFRegister(pAd, RFRegTableOverRT3390[i].Register, RFRegTableOverRT3390[i].Value); - } - } - - // patch LNA_PE_G1 failed issue - RTMP_IO_READ32(pAd, GPIO_SWITCH, &data); - data &= ~(0x20); - RTMP_IO_WRITE32(pAd, GPIO_SWITCH, data); - - // Initialize RF register to default value - for (i = 0; i < NUM_RF_REG_PARMS_OVER_RT3390; i++) - { - RT30xxWriteRFRegister(pAd, RT30xx_RFRegTable[i].Register, RT30xx_RFRegTable[i].Value); - } - - // Driver should set RF R6 bit6 on before calibration - RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RfReg); - RfReg |= 0x40; - RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RfReg); - - //For RF filter Calibration - RTMPFilterCalibration(pAd); - - // Initialize RF R27 register, set RF R27 must be behind RTMPFilterCalibration() - if ((pAd->MACVersion & 0xffff) < 0x0211) - RT30xxWriteRFRegister(pAd, RF_R27, 0x3); - - // set led open drain enable - RTMP_IO_READ32(pAd, OPT_14, &data); - data |= 0x01; - RTMP_IO_WRITE32(pAd, OPT_14, data); - - // set default antenna as main - if (pAd->RfIcType == RFIC_3020) - AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); - - // add by johnli, RF power sequence setup, load RF normal operation-mode setup - RT30xxLoadRFNormalModeSetup(pAd); - } - -} -#endif // RT3070 // diff --git a/drivers/staging/rt3090/chips/rt3390.c b/drivers/staging/rt3090/chips/rt3390.c deleted file mode 100644 index afed9e705e8d99715a89ab33c08e7ad10e3a5e53..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/chips/rt3390.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rt3390.c - - Abstract: - Specific funcitons and variables for RT30xx. - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#ifdef RT3390 - -#include "../rt_config.h" - - -#ifndef RTMP_RF_RW_SUPPORT -#error "You Should Enable compile flag RTMP_RF_RW_SUPPORT for this chip" -#endif // RTMP_RF_RW_SUPPORT // - - -VOID NICInitRT3390RFRegisters(IN PRTMP_ADAPTER pAd) -{ - INT i; - // Driver must read EEPROM to get RfIcType before initial RF registers - // Initialize RF register to default value - if (IS_RT3090(pAd)||IS_RT3390(pAd)||IS_RT3572(pAd)) - { - // Init RF calibration - // Driver should toggle RF R30 bit7 before init RF registers - UINT32 RfReg = 0, data; - - RT30xxReadRFRegister(pAd, RF_R30, (PUCHAR)&RfReg); - RfReg |= 0x80; - RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg); - RTMPusecDelay(1000); - RfReg &= 0x7F; - RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg); - - // init R24, R31 - RT30xxWriteRFRegister(pAd, RF_R24, 0x0F); - RT30xxWriteRFRegister(pAd, RF_R31, 0x0F); - - if (IS_RT3390(pAd)) - { - // patch LNA_PE_G1 failed issue - RTMP_IO_READ32(pAd, GPIO_SWITCH, &data); - data &= ~(0x20); - RTMP_IO_WRITE32(pAd, GPIO_SWITCH, data); - - // RF registers initialization - for (i = 0; i < NUM_RF_REG_PARMS_OVER_RT3390; i++) - { - RT30xxWriteRFRegister(pAd, RFRegTableOverRT3390[i].Register, RFRegTableOverRT3390[i].Value); - } - } - - // patch LNA_PE_G1 failed issue - RTMP_IO_READ32(pAd, GPIO_SWITCH, &data); - data &= ~(0x20); - RTMP_IO_WRITE32(pAd, GPIO_SWITCH, data); - - // Initialize RF register to default value - for (i = 0; i < NUM_RF_REG_PARMS_OVER_RT3390; i++) - { - RT30xxWriteRFRegister(pAd, RFRegTableOverRT3390[i].Register, RFRegTableOverRT3390[i].Value); - } - - // Driver should set RF R6 bit6 on before calibration - RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RfReg); - RfReg |= 0x40; - RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RfReg); - - //For RF filter Calibration - RTMPFilterCalibration(pAd); - - // Initialize RF R27 register, set RF R27 must be behind RTMPFilterCalibration() - if ((pAd->MACVersion & 0xffff) < 0x0211) - RT30xxWriteRFRegister(pAd, RF_R27, 0x3); - - // set led open drain enable - RTMP_IO_READ32(pAd, OPT_14, &data); - data |= 0x01; - RTMP_IO_WRITE32(pAd, OPT_14, data); - - // set default antenna as main - if (pAd->RfIcType == RFIC_3020) - AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); - - // add by johnli, RF power sequence setup, load RF normal operation-mode setup - RT33xxLoadRFNormalModeSetup(pAd); - } - -} - -#endif // RT3390 // diff --git a/drivers/staging/rt3090/chips/rt33xx.c b/drivers/staging/rt3090/chips/rt33xx.c deleted file mode 100644 index 56f376c88bda6b68f22bdf815374e2b0bee36e01..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/chips/rt33xx.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rt33xx.c - - Abstract: - Specific funcitons and variables for RT30xx. - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - - -#ifdef RT33xx - - -#ifndef RTMP_RF_RW_SUPPORT -#error "You Should Enable compile flag RTMP_RF_RW_SUPPORT for this chip" -#endif // RTMP_RF_RW_SUPPORT // - -#include "../rt_config.h" - - -// -// RF register initialization set -// -REG_PAIR RFRegTableOverRT3390[] = { - {RF_R00, 0xA0}, - {RF_R01, 0xE1}, - {RF_R02, 0xF1}, - {RF_R03, 0x62}, - {RF_R04, 0x40}, - {RF_R05, 0x8B}, - {RF_R06, 0x42}, - {RF_R07, 0x34}, - {RF_R08, 0x00}, // Read only - {RF_R09, 0xC0}, - - {RF_R10, 0x61}, - {RF_R11, 0x21}, - {RF_R12, 0x3B}, - {RF_R13, 0xE0}, - {RF_R14, 0x90}, - {RF_R15, 0x53}, - {RF_R16, 0x0E}, - {RF_R17, 0x94}, - {RF_R18, 0x5C}, - {RF_R19, 0x4A}, - - {RF_R20, 0xB2}, - {RF_R21, 0xF6}, - {RF_R22, 0x00}, - {RF_R23, 0x14}, - {RF_R24, 0x08}, - {RF_R25, 0x3D}, - {RF_R26, 0x85}, - {RF_R27, 0x00}, - {RF_R28, 0x41}, - {RF_R29, 0x8F}, - {RF_R30, 0x20}, - {RF_R31, 0x0F}, -}; - -UCHAR NUM_RF_REG_PARMS_OVER_RT3390=(sizeof(RFRegTableOverRT3390) / sizeof(REG_PAIR)); - - - -// Antenna divesity use GPIO3 and EESK pin for control -// Antenna and EEPROM access are both using EESK pin, -// Therefor we should avoid accessing EESK at the same time -// Then restore antenna after EEPROM access -// The original name of this function is AsicSetRxAnt(), now change to -//VOID AsicSetRxAnt( - -VOID RT33xxSetRxAnt( - IN PRTMP_ADAPTER pAd, - IN UCHAR Ant) -{ - UINT32 Value; - UINT32 x; - - if ((pAd->EepromAccess) || - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) || - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) || - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) || - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) - { - return; - } - - // the antenna selection is through firmware and MAC register(GPIO3) - if (Ant == 0) - { - // Main antenna - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - x |= (EESK); - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value); - Value &= ~(0x0808); - RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n")); - } - else - { - // Aux antenna - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - x &= ~(EESK); - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value); - Value &= ~(0x0808); - Value |= 0x08; - RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n")); - } -} - - -/* - ======================================================================== - - Routine Description: - For RF filter calibration purpose - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - ======================================================================== -*/ -VOID RTMPFilterCalibration( - IN PRTMP_ADAPTER pAd) -{ - UCHAR R55x = 0, value, FilterTarget = 0x1E, BBPValue=0; - UINT loop = 0, count = 0, loopcnt = 0, ReTry = 0; - UCHAR RF_R24_Value = 0; - - // Give bbp filter initial value - pAd->Mlme.CaliBW20RfR24 = 0x1F; - pAd->Mlme.CaliBW40RfR24 = 0x2F; //Bit[5] must be 1 for BW 40 - - do - { - if (loop == 1) //BandWidth = 40 MHz - { - // Write 0x27 to RF_R24 to program filter - RF_R24_Value = 0x27; - RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); - if (IS_RT3090(pAd) || IS_RT3572(pAd)|| IS_RT3390(pAd)) - FilterTarget = 0x15; - else - FilterTarget = 0x19; - - // when calibrate BW40, BBP mask must set to BW40. - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue&= (~0x18); - BBPValue|= (0x10); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - - // set to BW40 - RT30xxReadRFRegister(pAd, RF_R31, &value); - value |= 0x20; - RT30xxWriteRFRegister(pAd, RF_R31, value); - } - else //BandWidth = 20 MHz - { - // Write 0x07 to RF_R24 to program filter - RF_R24_Value = 0x07; - RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); - if (IS_RT3090(pAd) || IS_RT3572(pAd)|| IS_RT3390(pAd)) - FilterTarget = 0x13; - else - FilterTarget = 0x16; - - // set to BW20 - RT30xxReadRFRegister(pAd, RF_R31, &value); - value &= (~0x20); - RT30xxWriteRFRegister(pAd, RF_R31, value); - } - - // Write 0x01 to RF_R22 to enable baseband loopback mode - RT30xxReadRFRegister(pAd, RF_R22, &value); - value |= 0x01; - RT30xxWriteRFRegister(pAd, RF_R22, value); - - // Write 0x00 to BBP_R24 to set power & frequency of passband test tone - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0); - - do - { - // Write 0x90 to BBP_R25 to transmit test tone - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R25, 0x90); - - RTMPusecDelay(1000); - // Read BBP_R55[6:0] for received power, set R55x = BBP_R55[6:0] - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R55, &value); - R55x = value & 0xFF; - - } while ((ReTry++ < 100) && (R55x == 0)); - - // Write 0x06 to BBP_R24 to set power & frequency of stopband test tone - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x06); - - while(TRUE) - { - // Write 0x90 to BBP_R25 to transmit test tone - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R25, 0x90); - - //We need to wait for calibration - RTMPusecDelay(1000); - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R55, &value); - value &= 0xFF; - if ((R55x - value) < FilterTarget) - { - RF_R24_Value ++; - } - else if ((R55x - value) == FilterTarget) - { - RF_R24_Value ++; - count ++; - } - else - { - break; - } - - // prevent infinite loop cause driver hang. - if (loopcnt++ > 100) - { - DBGPRINT(RT_DEBUG_ERROR, ("RTMPFilterCalibration - can't find a valid value, loopcnt=%d stop calibrating", loopcnt)); - break; - } - - // Write RF_R24 to program filter - RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); - } - - if (count > 0) - { - RF_R24_Value = RF_R24_Value - ((count) ? (1) : (0)); - } - - // Store for future usage - if (loopcnt < 100) - { - if (loop++ == 0) - { - //BandWidth = 20 MHz - pAd->Mlme.CaliBW20RfR24 = (UCHAR)RF_R24_Value; - } - else - { - //BandWidth = 40 MHz - pAd->Mlme.CaliBW40RfR24 = (UCHAR)RF_R24_Value; - break; - } - } - else - break; - - RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); - - // reset count - count = 0; - } while(TRUE); - - // - // Set back to initial state - // - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0); - - RT30xxReadRFRegister(pAd, RF_R22, &value); - value &= ~(0x01); - RT30xxWriteRFRegister(pAd, RF_R22, value); - - // set BBP back to BW20 - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue&= (~0x18); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPFilterCalibration - CaliBW20RfR24=0x%x, CaliBW40RfR24=0x%x\n", pAd->Mlme.CaliBW20RfR24, pAd->Mlme.CaliBW40RfR24)); -} - - -// add by johnli, RF power sequence setup -/* - ========================================================================== - Description: - - Load RF normal operation-mode setup - - ========================================================================== - */ -VOID RT33xxLoadRFNormalModeSetup( - IN PRTMP_ADAPTER pAd) -{ - UCHAR RFValue; - - // RX0_PD & TX0_PD, RF R1 register Bit 2 & Bit 3 to 0 and RF_BLOCK_en,RX1_PD & TX1_PD, Bit0, Bit 4 & Bit5 to 1 - RT30xxReadRFRegister(pAd, RF_R01, &RFValue); - RFValue = (RFValue & (~0x0C)) | 0x31; - RT30xxWriteRFRegister(pAd, RF_R01, RFValue); - - // TX_LO2_en, RF R15 register Bit 3 to 0 - RT30xxReadRFRegister(pAd, RF_R15, &RFValue); - RFValue &= (~0x08); - RT30xxWriteRFRegister(pAd, RF_R15, RFValue); - - /* move to NICInitRT30xxRFRegisters - // TX_LO1_en, RF R17 register Bit 3 to 0 - RT30xxReadRFRegister(pAd, RF_R17, &RFValue); - RFValue &= (~0x08); - // to fix rx long range issue - if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0)) - { - RFValue |= 0x20; - } - // set RF_R17_bit[2:0] equal to EEPROM setting at 0x48h - if (pAd->TxMixerGain24G >= 2) - { - RFValue &= (~0x7); // clean bit [2:0] - RFValue |= pAd->TxMixerGain24G; - } - RT30xxWriteRFRegister(pAd, RF_R17, RFValue); - */ - - // RX_LO1_en, RF R20 register Bit 3 to 0 - RT30xxReadRFRegister(pAd, RF_R20, &RFValue); - RFValue &= (~0x08); - RT30xxWriteRFRegister(pAd, RF_R20, RFValue); - - // RX_LO2_en, RF R21 register Bit 3 to 0 - RT30xxReadRFRegister(pAd, RF_R21, &RFValue); - RFValue &= (~0x08); - RT30xxWriteRFRegister(pAd, RF_R21, RFValue); - - /* add by johnli, reset RF_R27 when interface down & up to fix throughput problem*/ - // LDORF_VC, RF R27 register Bit 2 to 0 - RT30xxReadRFRegister(pAd, RF_R27, &RFValue); - // TX to RX IQ glitch(RF_R27) has been fixed in RT3070(F). - // Raising RF voltage is no longer needed for RT3070(F) - if (IS_RT3090(pAd)) // RT309x and RT3071/72 - { - if ((pAd->MACVersion & 0xffff) < 0x0211) - RFValue = (RFValue & (~0x77)) | 0x3; - else - RFValue = (RFValue & (~0x77)); - RT30xxWriteRFRegister(pAd, RF_R27, RFValue); - } - /* end johnli */ -} - -/* - ========================================================================== - Description: - - Load RF sleep-mode setup - - ========================================================================== - */ -VOID RT33xxLoadRFSleepModeSetup( - IN PRTMP_ADAPTER pAd) -{ - UCHAR RFValue; - UINT32 MACValue; - - - { - // RF_BLOCK_en. RF R1 register Bit 0 to 0 - RT30xxReadRFRegister(pAd, RF_R01, &RFValue); - RFValue &= (~0x01); - RT30xxWriteRFRegister(pAd, RF_R01, RFValue); - - // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0 - RT30xxReadRFRegister(pAd, RF_R07, &RFValue); - RFValue &= (~0x30); - RT30xxWriteRFRegister(pAd, RF_R07, RFValue); - - // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0 - RT30xxReadRFRegister(pAd, RF_R09, &RFValue); - RFValue &= (~0x0E); - RT30xxWriteRFRegister(pAd, RF_R09, RFValue); - - // RX_CTB_en, RF R21 register Bit 7 to 0 - RT30xxReadRFRegister(pAd, RF_R21, &RFValue); - RFValue &= (~0x80); - RT30xxWriteRFRegister(pAd, RF_R21, RFValue); - } - - if (IS_RT3090(pAd) || // IS_RT3090 including RT309x and RT3071/72 - IS_RT3572(pAd) || - IS_RT3390(pAd) || - (IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201))) - { - { - RT30xxReadRFRegister(pAd, RF_R27, &RFValue); - RFValue |= 0x77; - RT30xxWriteRFRegister(pAd, RF_R27, RFValue); - } - - RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue); - MACValue |= 0x1D000000; - RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue); - } -} - -/* - ========================================================================== - Description: - - Reverse RF sleep-mode setup - - ========================================================================== - */ -VOID RT33xxReverseRFSleepModeSetup( - IN PRTMP_ADAPTER pAd) -{ - UCHAR RFValue; - UINT32 MACValue; - - { - // RF_BLOCK_en, RF R1 register Bit 0 to 1 - RT30xxReadRFRegister(pAd, RF_R01, &RFValue); - RFValue |= 0x01; - RT30xxWriteRFRegister(pAd, RF_R01, RFValue); - - // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1 - RT30xxReadRFRegister(pAd, RF_R07, &RFValue); - RFValue |= 0x30; - RT30xxWriteRFRegister(pAd, RF_R07, RFValue); - - // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1 - RT30xxReadRFRegister(pAd, RF_R09, &RFValue); - RFValue |= 0x0E; - RT30xxWriteRFRegister(pAd, RF_R09, RFValue); - - // RX_CTB_en, RF R21 register Bit 7 to 1 - RT30xxReadRFRegister(pAd, RF_R21, &RFValue); - RFValue |= 0x80; - RT30xxWriteRFRegister(pAd, RF_R21, RFValue); - } - - if (IS_RT3090(pAd) || // IS_RT3090 including RT309x and RT3071/72 - IS_RT3572(pAd) || - IS_RT3390(pAd) || - (IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201))) - { - { - RT30xxReadRFRegister(pAd, RF_R27, &RFValue); - if ((pAd->MACVersion & 0xffff) < 0x0211) - RFValue = (RFValue & (~0x77)) | 0x3; - else - RFValue = (RFValue & (~0x77)); - RT30xxWriteRFRegister(pAd, RF_R27, RFValue); - } - - // RT3071 version E has fixed this issue - if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211)) - { - // patch tx EVM issue temporarily - RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue); - MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000); - RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue); - } - else - { - RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue); - MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000); - RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue); - } - } - - if(IS_RT3572(pAd)) - RT30xxWriteRFRegister(pAd, RF_R08, 0x80); -} -// end johnli - -VOID RT33xxHaltAction( - IN PRTMP_ADAPTER pAd) -{ - UINT32 TxPinCfg = 0x00050F0F; - - // - // Turn off LNA_PE or TRSW_POL - // - if (IS_RT3070(pAd) || IS_RT3071(pAd) || IS_RT3390(pAd)||IS_RT3572(pAd)) - { - //KH? Both support 3390 usb and PCI - if ((IS_RT3071(pAd) || IS_RT3572(pAd)||IS_RT3390(pAd)) -#ifdef RTMP_EFUSE_SUPPORT - && (pAd->bUseEfuse) -#endif // RTMP_EFUSE_SUPPORT // - ) - { - TxPinCfg &= 0xFFFBF0F0; // bit18 off - } - else - { - TxPinCfg &= 0xFFFFF0F0; - } - - RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); - } -} - -#endif // RT30xx // diff --git a/drivers/staging/rt3090/chlist.h b/drivers/staging/rt3090/chlist.h deleted file mode 100644 index d03cb475439422d4e4305561c3b01ba557153d1a..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/chlist.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - chlist.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Fonchi Wu 2007-12-19 created -*/ - -#ifndef __CHLIST_H__ -#define __CHLIST_H__ - -#include "rtmp_type.h" -#include "rtmp_def.h" - - -#define ODOR 0 -#define IDOR 1 -#define BOTH 2 - -#define BAND_5G 0 -#define BAND_24G 1 -#define BAND_BOTH 2 - -typedef struct _CH_DESP { - UCHAR FirstChannel; - UCHAR NumOfCh; - CHAR MaxTxPwr; // dBm - UCHAR Geography; // 0:out door, 1:in door, 2:both - BOOLEAN DfsReq; // Dfs require, 0: No, 1: yes. -} CH_DESP, *PCH_DESP; - -typedef struct _CH_REGION { - UCHAR CountReg[3]; - UCHAR DfsType; // 0: CE, 1: FCC, 2: JAP, 3:JAP_W53, JAP_W56 - CH_DESP ChDesp[10]; -} CH_REGION, *PCH_REGION; - -extern CH_REGION ChRegion[]; - -typedef struct _CH_FREQ_MAP_{ - UINT16 channel; - UINT16 freqKHz; -}CH_FREQ_MAP; - -extern CH_FREQ_MAP CH_HZ_ID_MAP[]; -extern int CH_HZ_ID_MAP_NUM; - - -#define MAP_CHANNEL_ID_TO_KHZ(_ch, _khz) \ - do{ \ - int _chIdx; \ - for (_chIdx = 0; _chIdx < CH_HZ_ID_MAP_NUM; _chIdx++)\ - { \ - if ((_ch) == CH_HZ_ID_MAP[_chIdx].channel) \ - { \ - (_khz) = CH_HZ_ID_MAP[_chIdx].freqKHz * 1000; \ - break; \ - } \ - } \ - if (_chIdx == CH_HZ_ID_MAP_NUM) \ - (_khz) = 2412000; \ - }while(0) - -#define MAP_KHZ_TO_CHANNEL_ID(_khz, _ch) \ - do{ \ - int _chIdx; \ - for (_chIdx = 0; _chIdx < CH_HZ_ID_MAP_NUM; _chIdx++)\ - { \ - if ((_khz) == CH_HZ_ID_MAP[_chIdx].freqKHz) \ - { \ - (_ch) = CH_HZ_ID_MAP[_chIdx].channel; \ - break; \ - } \ - } \ - if (_chIdx == CH_HZ_ID_MAP_NUM) \ - (_ch) = 1; \ - }while(0) - - -VOID BuildChannelListEx( - IN PRTMP_ADAPTER pAd); - -VOID BuildBeaconChList( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf, - OUT PULONG pBufLen); - -#ifdef DOT11_N_SUPPORT -VOID N_ChannelCheck( - IN PRTMP_ADAPTER pAd); - -VOID N_SetCenCh( - IN PRTMP_ADAPTER pAd); -#endif // DOT11_N_SUPPORT // - -UINT8 GetCuntryMaxTxPwr( - IN PRTMP_ADAPTER pAd, - IN UINT8 channel); - -#endif // __CHLIST_H__ diff --git a/drivers/staging/rt3090/common/action.c b/drivers/staging/rt3090/common/action.c deleted file mode 100644 index 8e3b0a0c2d642d5819d20265ca861839ac19b337..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/action.c +++ /dev/null @@ -1,1057 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - action.c - - Abstract: - Handle association related requests either from WSTA or from local MLME - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Jan Lee 2006 created for rt2860 - */ - -#include "../rt_config.h" -#include "../action.h" - - -static VOID ReservedAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - - -/* - ========================================================================== - Description: - association state machine init, including state transition and timer init - Parameters: - S - pointer to the association state machine - Note: - The state machine looks like the following - - ASSOC_IDLE - MT2_MLME_DISASSOC_REQ mlme_disassoc_req_action - MT2_PEER_DISASSOC_REQ peer_disassoc_action - MT2_PEER_ASSOC_REQ drop - MT2_PEER_REASSOC_REQ drop - MT2_CLS3ERR cls3err_action - ========================================================================== - */ -VOID ActionStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]) -{ - StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_ACT_STATE, MAX_ACT_MSG, (STATE_MACHINE_FUNC)Drop, ACT_IDLE, ACT_MACHINE_BASE); - - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE, (STATE_MACHINE_FUNC)PeerSpectrumAction); - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE, (STATE_MACHINE_FUNC)PeerQOSAction); - - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)ReservedAction); -#ifdef QOS_DLS_SUPPORT - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)PeerDLSAction); -#endif // QOS_DLS_SUPPORT // - -#ifdef DOT11_N_SUPPORT - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE, (STATE_MACHINE_FUNC)PeerBAAction); - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE, (STATE_MACHINE_FUNC)PeerHTAction); - StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE, (STATE_MACHINE_FUNC)MlmeADDBAAction); - StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction); - StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction); -#endif // DOT11_N_SUPPORT // - - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE, (STATE_MACHINE_FUNC)PeerPublicAction); - StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE, (STATE_MACHINE_FUNC)PeerRMAction); - - StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE, (STATE_MACHINE_FUNC)MlmeQOSAction); - StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE, (STATE_MACHINE_FUNC)MlmeDLSAction); - StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID, (STATE_MACHINE_FUNC)MlmeInvalidAction); - - -} - -#ifdef DOT11_N_SUPPORT -VOID MlmeADDBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) - -{ - MLME_ADDBA_REQ_STRUCT *pInfo; - UCHAR Addr[6]; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG Idx; - FRAME_ADDBA_REQ Frame; - ULONG FrameLen; - BA_ORI_ENTRY *pBAEntry = NULL; - - pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg; - NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ)); - - if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr)) - { - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n")); - return; - } - // 1. find entry - Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; - if (Idx == 0) - { - MlmeFreeMemory(pAd, pOutBuffer); - DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n")); - return; - } - else - { - pBAEntry =&pAd->BATable.BAOriEntry[Idx]; - } - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (ADHOC_ON(pAd)) - ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); - else -#ifdef QOS_DLS_SUPPORT - if (pAd->MacTab.Content[pInfo->Wcid].ValidAsDls) - ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); - else -#endif // QOS_DLS_SUPPORT // - ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pInfo->pAddr); - - } -#endif // CONFIG_STA_SUPPORT // - - Frame.Category = CATEGORY_BA; - Frame.Action = ADDBA_REQ; - Frame.BaParm.AMSDUSupported = 0; - Frame.BaParm.BAPolicy = IMMED_BA; - Frame.BaParm.TID = pInfo->TID; - Frame.BaParm.BufSize = pInfo->BaBufSize; - Frame.Token = pInfo->Token; - Frame.TimeOutValue = pInfo->TimeOutValue; - Frame.BaStartSeq.field.FragNum = 0; - Frame.BaStartSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; - - *(USHORT *)(&Frame.BaParm) = cpu2le16(*(USHORT *)(&Frame.BaParm)); - Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue); - Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word); - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(FRAME_ADDBA_REQ), &Frame, - END_OF_ARGS); - - MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | MapUserPriorityToAccessCategory[pInfo->TID]), pOutBuffer, FrameLen); - - MlmeFreeMemory(pAd, pOutBuffer); - - DBGPRINT(RT_DEBUG_TRACE, ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize)); - } -} - -/* - ========================================================================== - Description: - send DELBA and delete BaEntry if any - Parametrs: - Elem - MLME message MLME_DELBA_REQ_STRUCT - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID MlmeDELBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - MLME_DELBA_REQ_STRUCT *pInfo; - PUCHAR pOutBuffer = NULL; - PUCHAR pOutBuffer2 = NULL; - NDIS_STATUS NStatus; - ULONG Idx; - FRAME_DELBA_REQ Frame; - ULONG FrameLen; - FRAME_BAR FrameBar; - - pInfo = (MLME_DELBA_REQ_STRUCT *)Elem->Msg; - // must send back DELBA - NdisZeroMemory(&Frame, sizeof(FRAME_DELBA_REQ)); - DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator)); - - if(MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen)) - { - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeDELBAAction() allocate memory failed 1. \n")); - return; - } - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - MlmeFreeMemory(pAd, pOutBuffer); - DBGPRINT(RT_DEBUG_ERROR, ("BA - MlmeDELBAAction() allocate memory failed 2. \n")); - return; - } - - // SEND BAR (Send BAR to refresh peer reordering buffer.) - Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress); -#endif // CONFIG_STA_SUPPORT // - - FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL funciton. - FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; // make sure sequence not clear in DEL funciton. - FrameBar.BarControl.TID = pInfo->TID; // make sure sequence not clear in DEL funciton. - FrameBar.BarControl.ACKPolicy = IMMED_BA; // make sure sequence not clear in DEL funciton. - FrameBar.BarControl.Compressed = 1; // make sure sequence not clear in DEL funciton. - FrameBar.BarControl.MTID = 0; // make sure sequence not clear in DEL funciton. - - MakeOutgoingFrame(pOutBuffer2, &FrameLen, - sizeof(FRAME_BAR), &FrameBar, - END_OF_ARGS); - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer2); - DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n")); - - // SEND DELBA FRAME - FrameLen = 0; -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (ADHOC_ON(pAd)) - ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); - else -#ifdef QOS_DLS_SUPPORT - if (pAd->MacTab.Content[pInfo->Wcid].ValidAsDls) - ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); - else -#endif // QOS_DLS_SUPPORT // - ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr); - } -#endif // CONFIG_STA_SUPPORT // - Frame.Category = CATEGORY_BA; - Frame.Action = DELBA; - Frame.DelbaParm.Initiator = pInfo->Initiator; - Frame.DelbaParm.TID = pInfo->TID; - Frame.ReasonCode = 39; // Time Out - *(USHORT *)(&Frame.DelbaParm) = cpu2le16(*(USHORT *)(&Frame.DelbaParm)); - Frame.ReasonCode = cpu2le16(Frame.ReasonCode); - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(FRAME_DELBA_REQ), &Frame, - END_OF_ARGS); - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - DBGPRINT(RT_DEBUG_TRACE, ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", pInfo->Initiator)); - } -} -#endif // DOT11_N_SUPPORT // - -VOID MlmeQOSAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ -} - -VOID MlmeDLSAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ -} - -VOID MlmeInvalidAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - //PUCHAR pOutBuffer = NULL; - //Return the receiving frame except the MSB of category filed set to 1. 7.3.1.11 -} - -VOID PeerQOSAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ -} - -#ifdef QOS_DLS_SUPPORT -VOID PeerDLSAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR Action = Elem->Msg[LENGTH_802_11+1]; - - switch(Action) - { - case ACTION_DLS_REQUEST: -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - PeerDlsReqAction(pAd, Elem); -#endif // CONFIG_STA_SUPPORT // - break; - - case ACTION_DLS_RESPONSE: -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - PeerDlsRspAction(pAd, Elem); -#endif // CONFIG_STA_SUPPORT // - break; - - case ACTION_DLS_TEARDOWN: -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - PeerDlsTearDownAction(pAd, Elem); -#endif // CONFIG_STA_SUPPORT // - break; - } -} -#endif // QOS_DLS_SUPPORT // - - - -#ifdef DOT11_N_SUPPORT -VOID PeerBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR Action = Elem->Msg[LENGTH_802_11+1]; - - switch(Action) - { - case ADDBA_REQ: - PeerAddBAReqAction(pAd,Elem); - break; - case ADDBA_RESP: - PeerAddBARspAction(pAd,Elem); - break; - case DELBA: - PeerDelBAAction(pAd,Elem); - break; - } -} - - -#ifdef DOT11N_DRAFT3 - -#ifdef CONFIG_STA_SUPPORT -VOID StaPublicAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Bss2040Coexist) -{ - BSS_2040_COEXIST_IE BssCoexist; - MLME_SCAN_REQ_STRUCT ScanReq; - - BssCoexist.word = Bss2040Coexist; - // AP asks Station to return a 20/40 BSS Coexistence mgmt frame. So we first starts a scan, then send back 20/40 BSS Coexistence mgmt frame - if ((BssCoexist.field.InfoReq == 1) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))) - { - // Clear record first. After scan , will update those bit and send back to transmiter. - pAd->CommonCfg.BSSCoexist2040.field.InfoReq = 1; - pAd->CommonCfg.BSSCoexist2040.field.Intolerant40 = 0; - pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 0; - // Fill out stuff for scan request - ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_2040_BSS_COEXIST); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; - } -} - - -/* -Description : Build Intolerant Channel Rerpot from Trigger event table. -return : how many bytes copied. -*/ -ULONG BuildIntolerantChannelRep( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDest) -{ - ULONG FrameLen = 0; - ULONG ReadOffset = 0; - UCHAR i; - UCHAR LastRegClass = 0xff; - PUCHAR pLen; - - for ( i = 0;i < MAX_TRIGGER_EVENT;i++) - { - if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid == TRUE) - { - if (pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass == LastRegClass) - { - *(pDest + ReadOffset) = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel; - *pLen++; - ReadOffset++; - FrameLen++; - } - else - { - *(pDest + ReadOffset) = IE_2040_BSS_INTOLERANT_REPORT; // IE - *(pDest + ReadOffset + 1) = 2; // Len = RegClass byte + channel byte. - pLen = pDest + ReadOffset + 1; - LastRegClass = pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass; - *(pDest + ReadOffset + 2) = LastRegClass; // Len = RegClass byte + channel byte. - *(pDest + ReadOffset + 3) = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel; - FrameLen += 4; - ReadOffset += 4; - } - - } - } - return FrameLen; -} - - -/* -Description : Send 20/40 BSS Coexistence Action frame If one trigger event is triggered. -*/ -VOID Send2040CoexistAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN BOOLEAN bAddIntolerantCha) -{ - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - FRAME_ACTION_HDR Frame; - ULONG FrameLen; - ULONG IntolerantChaRepLen; - - IntolerantChaRepLen = 0; - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction() allocate memory failed \n")); - return; - } - ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->CommonCfg.Bssid); - Frame.Category = CATEGORY_PUBLIC; - Frame.Action = ACTION_BSS_2040_COEXIST; - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(FRAME_ACTION_HDR), &Frame, - END_OF_ARGS); - - *(pOutBuffer + FrameLen) = pAd->CommonCfg.BSSCoexist2040.word; - FrameLen++; - - if (bAddIntolerantCha == TRUE) - IntolerantChaRepLen = BuildIntolerantChannelRep(pAd, pOutBuffer + FrameLen); - - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen + IntolerantChaRepLen); - DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction( BSSCoexist2040 = 0x%x ) \n", pAd->CommonCfg.BSSCoexist2040.word)); - -} - - -/* - ========================================================================== - Description: - After scan, Update 20/40 BSS Coexistence IE and send out. - According to 802.11n D3.03 11.14.10 - - Parameters: - ========================================================================== - */ -VOID Update2040CoexistFrameAndNotify( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN BOOLEAN bAddIntolerantCha) -{ - BSS_2040_COEXIST_IE OldValue; - - OldValue.word = pAd->CommonCfg.BSSCoexist2040.word; - if ((pAd->CommonCfg.TriggerEventTab.EventANo > 0) || (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)) - pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 1; - - // Need to check !!!! - // How STA will set Intolerant40 if implementation dependent. Now we don't set this bit first.!!!!! - // So Only check BSS20WidthReq change. - if (OldValue.field.BSS20WidthReq != pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq) - { - Send2040CoexistAction(pAd, Wcid, bAddIntolerantCha); - } -} -#endif // CONFIG_STA_SUPPORT // - - -BOOLEAN ChannelSwitchSanityCheck( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR NewChannel, - IN UCHAR Secondary) -{ - UCHAR i; - - if (Wcid >= MAX_LEN_OF_MAC_TABLE) - return FALSE; - - if ((NewChannel > 7) && (Secondary == 1)) - return FALSE; - - if ((NewChannel < 5) && (Secondary == 3)) - return FALSE; - - // 0. Check if new channel is in the channellist. - for (i = 0;i < pAd->ChannelListNum;i++) - { - if (pAd->ChannelList[i].Channel == NewChannel) - { - break; - } - } - - if (i == pAd->ChannelListNum) - return FALSE; - - return TRUE; -} - - -VOID ChannelSwitchAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR NewChannel, - IN UCHAR Secondary) -{ - UCHAR BBPValue = 0; - ULONG MACValue; - - DBGPRINT(RT_DEBUG_TRACE,("SPECTRUM - ChannelSwitchAction(NewChannel = %d , Secondary = %d) \n", NewChannel, Secondary)); - - if (ChannelSwitchSanityCheck(pAd, Wcid, NewChannel, Secondary) == FALSE) - return; - - // 1. Switches to BW = 20. - if (Secondary == 0) - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue&= (~0x18); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - if (pAd->MACVersion == 0x28600100) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11); - DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); - } - pAd->CommonCfg.BBPCurrentBW = BW_20; - pAd->CommonCfg.Channel = NewChannel; - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel,FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 0; - DBGPRINT(RT_DEBUG_TRACE, ("!!!20MHz !!! \n" )); - } - // 1. Switches to BW = 40 And Station supports BW = 40. - else if (((Secondary == 1) || (Secondary == 3)) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1)) - { - pAd->CommonCfg.Channel = NewChannel; - - if (Secondary == 1) - { - // Secondary above. - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; - RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue); - MACValue &= 0xfe; - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue); - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue&= (~0x18); - BBPValue|= (0x10); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue); - BBPValue&= (~0x20); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue); - DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel )); - } - else - { - // Secondary below. - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; - RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue); - MACValue &= 0xfe; - MACValue |= 0x1; - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue); - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue&= (~0x18); - BBPValue|= (0x10); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue); - BBPValue&= (~0x20); - BBPValue|= (0x20); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue); - DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel )); - } - pAd->CommonCfg.BBPCurrentBW = BW_40; - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 1; - } -} -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // - -VOID PeerPublicAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ -#ifdef DOT11_N_SUPPORT -#ifdef DOT11N_DRAFT3 - UCHAR Action = Elem->Msg[LENGTH_802_11+1]; -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // - if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) - return; - -#ifdef DOT11_N_SUPPORT -#ifdef DOT11N_DRAFT3 - switch(Action) - { - case ACTION_BSS_2040_COEXIST: // Format defined in IEEE 7.4.7a.1 in 11n Draf3.03 - { - //UCHAR BssCoexist; - BSS_2040_COEXIST_ELEMENT *pCoexistInfo; - BSS_2040_COEXIST_IE *pBssCoexistIe; - BSS_2040_INTOLERANT_CH_REPORT *pIntolerantReport = NULL; - - if (Elem->MsgLen <= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT)) ) - { - DBGPRINT(RT_DEBUG_ERROR, ("ACTION - 20/40 BSS Coexistence Management Frame length too short! len = %ld!\n", Elem->MsgLen)); - break; - } - DBGPRINT(RT_DEBUG_TRACE, ("ACTION - 20/40 BSS Coexistence Management action----> \n")); - hex_dump("CoexistenceMgmtFrame", Elem->Msg, Elem->MsgLen); - - - pCoexistInfo = (BSS_2040_COEXIST_ELEMENT *) &Elem->Msg[LENGTH_802_11+2]; - //hex_dump("CoexistInfo", (PUCHAR)pCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT)); - if (Elem->MsgLen >= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT) + sizeof(BSS_2040_INTOLERANT_CH_REPORT))) - { - pIntolerantReport = (BSS_2040_INTOLERANT_CH_REPORT *)((PUCHAR)pCoexistInfo + sizeof(BSS_2040_COEXIST_ELEMENT)); - } - //hex_dump("IntolerantReport ", (PUCHAR)pIntolerantReport, sizeof(BSS_2040_INTOLERANT_CH_REPORT)); - - pBssCoexistIe = (BSS_2040_COEXIST_IE *)(&pCoexistInfo->BssCoexistIe); - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (INFRA_ON(pAd)) - { - StaPublicAction(pAd, pCoexistInfo); - } - } -#endif // CONFIG_STA_SUPPORT // - - } - break; - } - -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // - -} - - -static VOID ReservedAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR Category; - - if (Elem->MsgLen <= LENGTH_802_11) - { - return; - } - - Category = Elem->Msg[LENGTH_802_11]; - DBGPRINT(RT_DEBUG_TRACE,("Rcv reserved category(%d) Action Frame\n", Category)); - hex_dump("Reserved Action Frame", &Elem->Msg[0], Elem->MsgLen); -} - -VOID PeerRMAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) - -{ - return; -} - -#ifdef DOT11_N_SUPPORT -static VOID respond_ht_information_exchange_action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen; - FRAME_HT_INFO HTINFOframe, *pFrame; - UCHAR *pAddr; - - - // 2. Always send back ADDBA Response - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE,("ACTION - respond_ht_information_exchange_action() allocate memory failed \n")); - return; - } - - // get RA - pFrame = (FRAME_HT_INFO *) &Elem->Msg[0]; - pAddr = pFrame->Hdr.Addr2; - - NdisZeroMemory(&HTINFOframe, sizeof(FRAME_HT_INFO)); - // 2-1. Prepare ADDBA Response frame. -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (ADHOC_ON(pAd)) - ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); - else - ActHeaderInit(pAd, &HTINFOframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr); - } -#endif // CONFIG_STA_SUPPORT // - - HTINFOframe.Category = CATEGORY_HT; - HTINFOframe.Action = HT_INFO_EXCHANGE; - HTINFOframe.HT_Info.Request = 0; - HTINFOframe.HT_Info.Forty_MHz_Intolerant = pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant; - HTINFOframe.HT_Info.STA_Channel_Width = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(FRAME_HT_INFO), &HTINFOframe, - END_OF_ARGS); - - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); -} - - -#ifdef DOT11N_DRAFT3 -VOID SendNotifyBWActionFrame( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR apidx) -{ - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - FRAME_ACTION_HDR Frame; - ULONG FrameLen; - PUCHAR pAddr1; - - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_ERROR,("ACT - SendNotifyBWAction() allocate memory failed \n")); - return; - } - - if (Wcid == MCAST_WCID) - pAddr1 = &BROADCAST_ADDR[0]; - else - pAddr1 = pAd->MacTab.Content[Wcid].Addr; - ActHeaderInit(pAd, &Frame.Hdr, pAddr1, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid); - - Frame.Category = CATEGORY_HT; - Frame.Action = NOTIFY_BW_ACTION; - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(FRAME_ACTION_HDR), &Frame, - END_OF_ARGS); - - *(pOutBuffer + FrameLen) = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; - FrameLen++; - - - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); - DBGPRINT(RT_DEBUG_TRACE,("ACT - SendNotifyBWAction(NotifyBW= %d)!\n", pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth)); - -} -#endif // DOT11N_DRAFT3 // - - -VOID PeerHTAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR Action = Elem->Msg[LENGTH_802_11+1]; - - if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) - return; - - switch(Action) - { - case NOTIFY_BW_ACTION: - DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Notify Channel bandwidth action----> \n")); -#ifdef CONFIG_STA_SUPPORT - if(pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) - { - // Note, this is to patch DIR-1353 AP. When the AP set to Wep, it will use legacy mode. But AP still keeps - // sending BW_Notify Action frame, and cause us to linkup and linkdown. - // In legacy mode, don't need to parse HT action frame. - DBGPRINT(RT_DEBUG_TRACE,("ACTION -Ignore HT Notify Channel BW when link as legacy mode. BW = %d---> \n", - Elem->Msg[LENGTH_802_11+2] )); - break; - } -#endif // CONFIG_STA_SUPPORT // - - if (Elem->Msg[LENGTH_802_11+2] == 0) // 7.4.8.2. if value is 1, keep the same as supported channel bandwidth. - pAd->MacTab.Content[Elem->Wcid].HTPhyMode.field.BW = 0; - - break; - - case SMPS_ACTION: - // 7.3.1.25 - DBGPRINT(RT_DEBUG_TRACE,("ACTION - SMPS action----> \n")); - if (((Elem->Msg[LENGTH_802_11+2]&0x1) == 0)) - { - pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_ENABLE; - } - else if (((Elem->Msg[LENGTH_802_11+2]&0x2) == 0)) - { - pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_STATIC; - } - else - { - pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_DYNAMIC; - } - - DBGPRINT(RT_DEBUG_TRACE,("Aid(%d) MIMO PS = %d\n", Elem->Wcid, pAd->MacTab.Content[Elem->Wcid].MmpsMode)); - // rt2860c : add something for smps change. - break; - - case SETPCO_ACTION: - break; - - case MIMO_CHA_MEASURE_ACTION: - break; - - case HT_INFO_EXCHANGE: - { - HT_INFORMATION_OCTET *pHT_info; - - pHT_info = (HT_INFORMATION_OCTET *) &Elem->Msg[LENGTH_802_11+2]; - // 7.4.8.10 - DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Information Exchange action----> \n")); - if (pHT_info->Request) - { - respond_ht_information_exchange_action(pAd, Elem); - } - } - break; - } -} - - -/* - ========================================================================== - Description: - Retry sending ADDBA Reqest. - - IRQL = DISPATCH_LEVEL - - Parametrs: - p8023Header: if this is already 802.3 format, p8023Header is NULL - - Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. - FALSE , then continue indicaterx at this moment. - ========================================================================== - */ -VOID ORIBATimerTimeout( - IN PRTMP_ADAPTER pAd) -{ - MAC_TABLE_ENTRY *pEntry; - INT i, total; -// FRAME_BAR FrameBar; -// ULONG FrameLen; -// NDIS_STATUS NStatus; -// PUCHAR pOutBuffer = NULL; -// USHORT Sequence; - UCHAR TID; - -#ifdef RALINK_ATE - if (ATE_ON(pAd)) - return; -#endif // RALINK_ATE // - - total = pAd->MacTab.Size * NUM_OF_TID; - - for (i = 1; ((i 0)) ; i++) - { - if (pAd->BATable.BAOriEntry[i].ORI_BA_Status == Originator_Done) - { - pEntry = &pAd->MacTab.Content[pAd->BATable.BAOriEntry[i].Wcid]; - TID = pAd->BATable.BAOriEntry[i].TID; - - ASSERT(pAd->BATable.BAOriEntry[i].Wcid < MAX_LEN_OF_MAC_TABLE); - } - total --; - } -} - - -VOID SendRefreshBAR( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry) -{ - FRAME_BAR FrameBar; - ULONG FrameLen; - NDIS_STATUS NStatus; - PUCHAR pOutBuffer = NULL; - USHORT Sequence; - UCHAR i, TID; - USHORT idx; - BA_ORI_ENTRY *pBAEntry; - - for (i = 0; i BAOriWcidArray[i]; - if (idx == 0) - { - continue; - } - pBAEntry = &pAd->BATable.BAOriEntry[idx]; - - if (pBAEntry->ORI_BA_Status == Originator_Done) - { - TID = pBAEntry->TID; - - ASSERT(pBAEntry->Wcid < MAX_LEN_OF_MAC_TABLE); - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); - return; - } - - Sequence = pEntry->TxSeq[TID]; - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->CurrentAddress); -#endif // CONFIG_STA_SUPPORT // - - FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function. - FrameBar.StartingSeq.field.StartSeq = Sequence; // make sure sequence not clear in DEL funciton. - FrameBar.BarControl.TID = TID; // make sure sequence not clear in DEL funciton. - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(FRAME_BAR), &FrameBar, - END_OF_ARGS); - //if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET))) - if (1) // Now we always send BAR. - { - //MiniportMMRequestUnlock(pAd, 0, pOutBuffer, FrameLen); - MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | MapUserPriorityToAccessCategory[TID]), pOutBuffer, FrameLen); - - } - MlmeFreeMemory(pAd, pOutBuffer); - } - } -} -#endif // DOT11_N_SUPPORT // - -VOID ActHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PHEADER_802_11 pHdr80211, - IN PUCHAR Addr1, - IN PUCHAR Addr2, - IN PUCHAR Addr3) -{ - NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); - pHdr80211->FC.Type = BTYPE_MGMT; - pHdr80211->FC.SubType = SUBTYPE_ACTION; - - COPY_MAC_ADDR(pHdr80211->Addr1, Addr1); - COPY_MAC_ADDR(pHdr80211->Addr2, Addr2); - COPY_MAC_ADDR(pHdr80211->Addr3, Addr3); -} - -VOID BarHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PFRAME_BAR pCntlBar, - IN PUCHAR pDA, - IN PUCHAR pSA) -{ -// USHORT Duration; - - NdisZeroMemory(pCntlBar, sizeof(FRAME_BAR)); - pCntlBar->FC.Type = BTYPE_CNTL; - pCntlBar->FC.SubType = SUBTYPE_BLOCK_ACK_REQ; - pCntlBar->BarControl.MTID = 0; - pCntlBar->BarControl.Compressed = 1; - pCntlBar->BarControl.ACKPolicy = 0; - - - pCntlBar->Duration = 16 + RTMPCalcDuration(pAd, RATE_1, sizeof(FRAME_BA)); - - COPY_MAC_ADDR(pCntlBar->Addr1, pDA); - COPY_MAC_ADDR(pCntlBar->Addr2, pSA); -} - - -/* - ========================================================================== - Description: - Insert Category and action code into the action frame. - - Parametrs: - 1. frame buffer pointer. - 2. frame length. - 3. category code of the frame. - 4. action code of the frame. - - Return : None. - ========================================================================== - */ -VOID InsertActField( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN UINT8 Category, - IN UINT8 ActCode) -{ - ULONG TempLen; - - MakeOutgoingFrame( pFrameBuf, &TempLen, - 1, &Category, - 1, &ActCode, - END_OF_ARGS); - - *pFrameLen = *pFrameLen + TempLen; - - return; -} diff --git a/drivers/staging/rt3090/common/ba_action.c b/drivers/staging/rt3090/common/ba_action.c deleted file mode 100644 index c73248980690d18f06b9b6e23f070d1875d6df21..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/ba_action.c +++ /dev/null @@ -1,1779 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - */ - - -#ifdef DOT11_N_SUPPORT - -#include "../rt_config.h" - - -#define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) //1 // inital sequence number of BA session - -#define ORI_SESSION_MAX_RETRY 8 -#define ORI_BA_SESSION_TIMEOUT (2000) // ms -#define REC_BA_SESSION_IDLE_TIMEOUT (1000) // ms - -#define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) // system ticks -- 100 ms -#define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_HZ)/1000) // system ticks -- 100 ms - -#define RESET_RCV_SEQ (0xFFFF) - -static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk); - - -BA_ORI_ENTRY *BATableAllocOriEntry( - IN PRTMP_ADAPTER pAd, - OUT USHORT *Idx); - -BA_REC_ENTRY *BATableAllocRecEntry( - IN PRTMP_ADAPTER pAd, - OUT USHORT *Idx); - -VOID BAOriSessionSetupTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID BARecSessionIdleTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - - -BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout); -BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout); - -#define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \ - Announce_Reordering_Packet(_pAd, _mpdu_blk); - -VOID BA_MaxWinSizeReasign( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntryPeer, - OUT UCHAR *pWinSize) -{ - UCHAR MaxSize; - - - if (pAd->MACVersion >= RALINK_2883_VERSION) // 3*3 - { - if (pAd->MACVersion >= RALINK_3070_VERSION) - { - if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled) - MaxSize = 7; // for non-open mode - else - MaxSize = 13; - } - else - MaxSize = 31; - } - else if (pAd->MACVersion >= RALINK_2880E_VERSION) // 2880 e - { - if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled) - MaxSize = 7; // for non-open mode - else - MaxSize = 13; - } - else - MaxSize = 7; - - DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n", - *pWinSize, MaxSize)); - - if ((*pWinSize) > MaxSize) - { - DBGPRINT(RT_DEBUG_TRACE, ("ba> reassign max win size from %d to %d\n", - *pWinSize, MaxSize)); - - *pWinSize = MaxSize; - } -} - -void Announce_Reordering_Packet(IN PRTMP_ADAPTER pAd, - IN struct reordering_mpdu *mpdu) -{ - PNDIS_PACKET pPacket; - - pPacket = mpdu->pPacket; - - if (mpdu->bAMSDU) - { - ASSERT(0); - BA_Reorder_AMSDU_Annnounce(pAd, pPacket); - } - else - { - // - // pass this 802.3 packet to upper layer or forward this packet to WM directly - // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket)); -#endif // CONFIG_STA_SUPPORT // - } -} - -/* - * Insert a reordering mpdu into sorted linked list by sequence no. - */ -BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu) -{ - - struct reordering_mpdu **ppScan = &list->next; - - while (*ppScan != NULL) - { - if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ)) - { - ppScan = &(*ppScan)->next; - } - else if ((*ppScan)->Sequence == mpdu->Sequence) - { - /* give up this duplicated frame */ - return(FALSE); - } - else - { - /* find position */ - break; - } - } - - mpdu->next = *ppScan; - *ppScan = mpdu; - list->qlen++; - return TRUE; -} - - -/* - * caller lock critical section if necessary - */ -static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk) -{ - list->qlen++; - mpdu_blk->next = list->next; - list->next = mpdu_blk; -} - -/* - * caller lock critical section if necessary - */ -static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list) -{ - struct reordering_mpdu *mpdu_blk = NULL; - - ASSERT(list); - - if (list->qlen) - { - list->qlen--; - mpdu_blk = list->next; - if (mpdu_blk) - { - list->next = mpdu_blk->next; - mpdu_blk->next = NULL; - } - } - return mpdu_blk; -} - - -static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct reordering_list *list) -{ - return(ba_dequeue(list)); -} - - -static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct reordering_list *list) - { - ASSERT(list); - - return(list->next); - } - - -/* - * free all resource for reordering mechanism - */ -void ba_reordering_resource_release(PRTMP_ADAPTER pAd) -{ - BA_TABLE *Tab; - PBA_REC_ENTRY pBAEntry; - struct reordering_mpdu *mpdu_blk; - int i; - - Tab = &pAd->BATable; - - /* I. release all pending reordering packet */ - NdisAcquireSpinLock(&pAd->BATabLock); - for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) - { - pBAEntry = &Tab->BARecEntry[i]; - if (pBAEntry->REC_BA_Status != Recipient_NONE) - { - while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) - { - ASSERT(mpdu_blk->pPacket); - RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE); - ba_mpdu_blk_free(pAd, mpdu_blk); - } - } - } - NdisReleaseSpinLock(&pAd->BATabLock); - - ASSERT(pBAEntry->list.qlen == 0); - /* II. free memory of reordering mpdu table */ - NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); - os_free_mem(pAd, pAd->mpdu_blk_pool.mem); - NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); -} - - - -/* - * Allocate all resource for reordering mechanism - */ -BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num) -{ - int i; - PUCHAR mem; - struct reordering_mpdu *mpdu_blk; - struct reordering_list *freelist; - - /* allocate spinlock */ - NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock); - - /* initialize freelist */ - freelist = &pAd->mpdu_blk_pool.freelist; - freelist->next = NULL; - freelist->qlen = 0; - - DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu)))); - - /* allocate number of mpdu_blk memory */ - os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu))); - - pAd->mpdu_blk_pool.mem = mem; - - if (mem == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n")); - return(FALSE); - } - - /* build mpdu_blk free list */ - for (i=0; impdu_blk_pool.lock); - mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist); - if (mpdu_blk) - { -// blk_count++; - /* reset mpdu_blk */ - NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu)); - } - NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); - return mpdu_blk; -} - -static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk) -{ - ASSERT(mpdu_blk); - - NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); -// blk_count--; - ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk); - NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); -} - - -static USHORT ba_indicate_reordering_mpdus_in_order( - IN PRTMP_ADAPTER pAd, - IN PBA_REC_ENTRY pBAEntry, - IN USHORT StartSeq) -{ - struct reordering_mpdu *mpdu_blk; - USHORT LastIndSeq = RESET_RCV_SEQ; - - NdisAcquireSpinLock(&pBAEntry->RxReRingLock); - - while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) - { - /* find in-order frame */ - if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ)) - { - break; - } - /* dequeue in-order frame from reodering list */ - mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); - /* pass this frame up */ - ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); - /* move to next sequence */ - StartSeq = mpdu_blk->Sequence; - LastIndSeq = StartSeq; - /* free mpdu_blk */ - ba_mpdu_blk_free(pAd, mpdu_blk); - } - - NdisReleaseSpinLock(&pBAEntry->RxReRingLock); - - /* update last indicated sequence */ - return LastIndSeq; -} - -static void ba_indicate_reordering_mpdus_le_seq( - IN PRTMP_ADAPTER pAd, - IN PBA_REC_ENTRY pBAEntry, - IN USHORT Sequence) -{ - struct reordering_mpdu *mpdu_blk; - - NdisAcquireSpinLock(&pBAEntry->RxReRingLock); - while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) - { - /* find in-order frame */ - if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ)) - { - /* dequeue in-order frame from reodering list */ - mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); - /* pass this frame up */ - ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); - /* free mpdu_blk */ - ba_mpdu_blk_free(pAd, mpdu_blk); - } - else - { - break; - } - } - NdisReleaseSpinLock(&pBAEntry->RxReRingLock); -} - - -static void ba_refresh_reordering_mpdus( - IN PRTMP_ADAPTER pAd, - PBA_REC_ENTRY pBAEntry) -{ - struct reordering_mpdu *mpdu_blk; - - NdisAcquireSpinLock(&pBAEntry->RxReRingLock); - - /* dequeue in-order frame from reodering list */ - while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) - { - /* pass this frame up */ - ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); - - pBAEntry->LastIndSeq = mpdu_blk->Sequence; - ba_mpdu_blk_free(pAd, mpdu_blk); - - /* update last indicated sequence */ - } - ASSERT(pBAEntry->list.qlen == 0); - pBAEntry->LastIndSeq = RESET_RCV_SEQ; - NdisReleaseSpinLock(&pBAEntry->RxReRingLock); -} - - -//static -void ba_flush_reordering_timeout_mpdus( - IN PRTMP_ADAPTER pAd, - IN PBA_REC_ENTRY pBAEntry, - IN ULONG Now32) - -{ - USHORT Sequence; - -// if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) && -// (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //|| -// (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) && -// (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8))) - if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT/6))) - &&(pBAEntry->list.qlen > 1) - ) - { - DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer), - (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT, - pBAEntry->LastIndSeq)); - ba_refresh_reordering_mpdus(pAd, pBAEntry); - pBAEntry->LastIndSeqAtTimer = Now32; - } - else - if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT))) - && (pBAEntry->list.qlen > 0) - ) - { -// DBGPRINT(RT_DEBUG_OFF, ("timeout[%d] (%lx-%lx = %d > %d): %x, ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer), -// (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), REORDERING_PACKET_TIMEOUT, -// pBAEntry->LastIndSeq)); - // - // force LastIndSeq to shift to LastIndSeq+1 - // - Sequence = (pBAEntry->LastIndSeq+1) & MAXSEQ; - ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); - pBAEntry->LastIndSeqAtTimer = Now32; - pBAEntry->LastIndSeq = Sequence; - // - // indicate in-order mpdus - // - Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence); - if (Sequence != RESET_RCV_SEQ) - { - pBAEntry->LastIndSeq = Sequence; - } - - DBGPRINT(RT_DEBUG_OFF, ("%x, flush one!\n", pBAEntry->LastIndSeq)); - - } -} - - -/* - * generate ADDBA request to - * set up BA agreement - */ -VOID BAOriSessionSetUp( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN UCHAR TID, - IN USHORT TimeOut, - IN ULONG DelayTime, - IN BOOLEAN isForced) - -{ - //MLME_ADDBA_REQ_STRUCT AddbaReq; - BA_ORI_ENTRY *pBAEntry = NULL; - USHORT Idx; - BOOLEAN Cancelled; - - if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE)) - return; - - // if this entry is limited to use legacy tx mode, it doesn't generate BA. - if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT) - return; - - if ((pEntry->BADeclineBitmap & (1<BAOriWcidArray[TID]; - if (Idx == 0) - { - // allocate a BA session - pBAEntry = BATableAllocOriEntry(pAd, &Idx); - if (pBAEntry == NULL) - { - DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n")); - return; - } - } - else - { - pBAEntry =&pAd->BATable.BAOriEntry[Idx]; - } - - if (pBAEntry->ORI_BA_Status >= Originator_WaitRes) - { - return; - } - - pEntry->BAOriWcidArray[TID] = Idx; - - // Initialize BA session - pBAEntry->ORI_BA_Status = Originator_WaitRes; - pBAEntry->Wcid = pEntry->Aid; - pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; - pBAEntry->Sequence = BA_ORI_INIT_SEQ; - pBAEntry->Token = 1; // (2008-01-21) Jan Lee recommends it - this token can't be 0 - pBAEntry->TID = TID; - pBAEntry->TimeOutValue = TimeOut; - pBAEntry->pAdapter = pAd; - - if (!(pEntry->TXBAbitmap & (1<ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE); - } - else - RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); - - // set timer to send ADDBA request - RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime); -} - -VOID BAOriSessionAdd( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN PFRAME_ADDBA_RSP pFrame) -{ - BA_ORI_ENTRY *pBAEntry = NULL; - BOOLEAN Cancelled; - UCHAR TID; - USHORT Idx; - PUCHAR pOutBuffer2 = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen; - FRAME_BAR FrameBar; - - TID = pFrame->BaParm.TID; - Idx = pEntry->BAOriWcidArray[TID]; - pBAEntry =&pAd->BATable.BAOriEntry[Idx]; - - // Start fill in parameters. - if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes)) - { - pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, ((UCHAR)pFrame->BaParm.BufSize)); - BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize); - - pBAEntry->TimeOutValue = pFrame->TimeOutValue; - pBAEntry->ORI_BA_Status = Originator_Done; - pAd->BATable.numDoneOriginator ++; - - // reset sequence number - pBAEntry->Sequence = BA_ORI_INIT_SEQ; - // Set Bitmap flag. - pEntry->TXBAbitmap |= (1<ORIBATimer, &Cancelled); - - pBAEntry->ORIBATimer.TimerValue = 0; //pFrame->TimeOutValue; - - DBGPRINT(RT_DEBUG_TRACE,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __FUNCTION__, pEntry->TXBAbitmap, - pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue)); - - // SEND BAR ; - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n")); - return; - } - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress); -#endif // CONFIG_STA_SUPPORT // - - FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function. - FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; // make sure sequence not clear in DEL funciton. - FrameBar.BarControl.TID = pBAEntry->TID; // make sure sequence not clear in DEL funciton. - MakeOutgoingFrame(pOutBuffer2, &FrameLen, - sizeof(FRAME_BAR), &FrameBar, - END_OF_ARGS); - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer2); - - - if (pBAEntry->ORIBATimer.TimerValue) - RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); // in mSec - } -} - -BOOLEAN BARecSessionAdd( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN PFRAME_ADDBA_REQ pFrame) -{ - BA_REC_ENTRY *pBAEntry = NULL; - BOOLEAN Status = TRUE; - BOOLEAN Cancelled; - USHORT Idx; - UCHAR TID; - UCHAR BAWinSize; - //UINT32 Value; - //UINT offset; - - - ASSERT(pEntry); - - // find TID - TID = pFrame->BaParm.TID; - - BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); - - // Intel patch - if (BAWinSize == 0) - { - BAWinSize = 64; - } - - Idx = pEntry->BARecWcidArray[TID]; - - - if (Idx == 0) - { - pBAEntry = BATableAllocRecEntry(pAd, &Idx); - } - else - { - pBAEntry = &pAd->BATable.BARecEntry[Idx]; - // flush all pending reordering mpdus - ba_refresh_reordering_mpdus(pAd, pBAEntry); - } - - DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __FUNCTION__, pAd->BATable.numAsRecipient, Idx, - pFrame->BaParm.BufSize, BAWinSize)); - - // Start fill in parameters. - if (pBAEntry != NULL) - { - ASSERT(pBAEntry->list.qlen == 0); - - pBAEntry->REC_BA_Status = Recipient_HandleRes; - pBAEntry->BAWinSize = BAWinSize; - pBAEntry->Wcid = pEntry->Aid; - pBAEntry->TID = TID; - pBAEntry->TimeOutValue = pFrame->TimeOutValue; - pBAEntry->REC_BA_Status = Recipient_Accept; - // initial sequence number - pBAEntry->LastIndSeq = RESET_RCV_SEQ; //pFrame->BaStartSeq.field.StartSeq; - - DBGPRINT(RT_DEBUG_OFF, ("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq)); - - if (pEntry->RXBAbitmap & (1<RECBATimer, &Cancelled); - } - else - { - RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE); - } - - - // Set Bitmap flag. - pEntry->RXBAbitmap |= (1<BARecWcidArray[TID] = Idx; - - pEntry->BADeclineBitmap &= ~(1<Aid, TID); - - DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n", - pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID])); - } - else - { - Status = FALSE; - DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n", - PRINT_MAC(pEntry->Addr), TID)); - } - return(Status); -} - - -BA_REC_ENTRY *BATableAllocRecEntry( - IN PRTMP_ADAPTER pAd, - OUT USHORT *Idx) -{ - int i; - BA_REC_ENTRY *pBAEntry = NULL; - - - NdisAcquireSpinLock(&pAd->BATabLock); - - if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION) - { - DBGPRINT(RT_DEBUG_OFF, ("BA Recipeint Session (%ld) > %d\n", - pAd->BATable.numAsRecipient, MAX_BARECI_SESSION)); - goto done; - } - - // reserve idx 0 to identify BAWcidArray[TID] as empty - for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++) - { - pBAEntry =&pAd->BATable.BARecEntry[i]; - if ((pBAEntry->REC_BA_Status == Recipient_NONE)) - { - // get one - pAd->BATable.numAsRecipient++; - pBAEntry->REC_BA_Status = Recipient_USED; - *Idx = i; - break; - } - } - -done: - NdisReleaseSpinLock(&pAd->BATabLock); - return pBAEntry; -} - -BA_ORI_ENTRY *BATableAllocOriEntry( - IN PRTMP_ADAPTER pAd, - OUT USHORT *Idx) -{ - int i; - BA_ORI_ENTRY *pBAEntry = NULL; - - NdisAcquireSpinLock(&pAd->BATabLock); - - if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE)) - { - goto done; - } - - // reserve idx 0 to identify BAWcidArray[TID] as empty - for (i=1; iBATable.BAOriEntry[i]; - if ((pBAEntry->ORI_BA_Status == Originator_NONE)) - { - // get one - pAd->BATable.numAsOriginator++; - pBAEntry->ORI_BA_Status = Originator_USED; - pBAEntry->pAdapter = pAd; - *Idx = i; - break; - } - } - -done: - NdisReleaseSpinLock(&pAd->BATabLock); - return pBAEntry; -} - - -VOID BATableFreeOriEntry( - IN PRTMP_ADAPTER pAd, - IN ULONG Idx) -{ - BA_ORI_ENTRY *pBAEntry = NULL; - MAC_TABLE_ENTRY *pEntry; - - - if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) - return; - - pBAEntry =&pAd->BATable.BAOriEntry[Idx]; - - if (pBAEntry->ORI_BA_Status != Originator_NONE) - { - pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; - pEntry->BAOriWcidArray[pBAEntry->TID] = 0; - - - NdisAcquireSpinLock(&pAd->BATabLock); - if (pBAEntry->ORI_BA_Status == Originator_Done) - { - pAd->BATable.numDoneOriginator -= 1; - pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) )); - DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient)); - // Erase Bitmap flag. - } - - ASSERT(pAd->BATable.numAsOriginator != 0); - - pAd->BATable.numAsOriginator -= 1; - - pBAEntry->ORI_BA_Status = Originator_NONE; - pBAEntry->Token = 0; - NdisReleaseSpinLock(&pAd->BATabLock); - } -} - - -VOID BATableFreeRecEntry( - IN PRTMP_ADAPTER pAd, - IN ULONG Idx) -{ - BA_REC_ENTRY *pBAEntry = NULL; - MAC_TABLE_ENTRY *pEntry; - - - if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE)) - return; - - pBAEntry =&pAd->BATable.BARecEntry[Idx]; - - if (pBAEntry->REC_BA_Status != Recipient_NONE) - { - pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; - pEntry->BARecWcidArray[pBAEntry->TID] = 0; - - NdisAcquireSpinLock(&pAd->BATabLock); - - ASSERT(pAd->BATable.numAsRecipient != 0); - - pAd->BATable.numAsRecipient -= 1; - - pBAEntry->REC_BA_Status = Recipient_NONE; - NdisReleaseSpinLock(&pAd->BATabLock); - } -} - - -VOID BAOriSessionTearDown( - IN OUT PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR TID, - IN BOOLEAN bPassive, - IN BOOLEAN bForceSend) -{ - ULONG Idx = 0; - BA_ORI_ENTRY *pBAEntry; - BOOLEAN Cancelled; - - if (Wcid >= MAX_LEN_OF_MAC_TABLE) - { - return; - } - - // - // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). - // - Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID]; - if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) - { - if (bForceSend == TRUE) - { - // force send specified TID DelBA - MLME_DELBA_REQ_STRUCT DelbaReq; - MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); - if (Elem != NULL) - { - NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); - NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); - - COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); - DelbaReq.Wcid = Wcid; - DelbaReq.TID = TID; - DelbaReq.Initiator = ORIGINATOR; - Elem->MsgLen = sizeof(DelbaReq); - NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); - MlmeDELBAAction(pAd, Elem); - kfree(Elem); - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("%s(bForceSend):alloc memory failed!\n", __FUNCTION__)); - } - } - - return; - } - - DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID)); - - pBAEntry = &pAd->BATable.BAOriEntry[Idx]; - DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status)); - // - // Prepare DelBA action frame and send to the peer. - // - if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done)) - { - MLME_DELBA_REQ_STRUCT DelbaReq; - MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); - if (Elem != NULL) - { - NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); - NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); - - COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); - DelbaReq.Wcid = Wcid; - DelbaReq.TID = pBAEntry->TID; - DelbaReq.Initiator = ORIGINATOR; - Elem->MsgLen = sizeof(DelbaReq); - NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); - MlmeDELBAAction(pAd, Elem); - kfree(Elem); - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__)); - return; - } - } - RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); - BATableFreeOriEntry(pAd, Idx); - - if (bPassive) - { - //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE); - } -} - -VOID BARecSessionTearDown( - IN OUT PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR TID, - IN BOOLEAN bPassive) -{ - ULONG Idx = 0; - BA_REC_ENTRY *pBAEntry; - - if (Wcid >= MAX_LEN_OF_MAC_TABLE) - { - return; - } - - // - // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). - // - Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; - if (Idx == 0) - return; - - DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID)); - - - pBAEntry = &pAd->BATable.BARecEntry[Idx]; - DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status)); - // - // Prepare DelBA action frame and send to the peer. - // - if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept)) - { - MLME_DELBA_REQ_STRUCT DelbaReq; - BOOLEAN Cancelled; - //ULONG offset; - //UINT32 VALUE; - - RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); - - // - // 1. Send DELBA Action Frame - // - if (bPassive == FALSE) - { - MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); - if (Elem != NULL) - { - NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); - NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); - - COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); - DelbaReq.Wcid = Wcid; - DelbaReq.TID = TID; - DelbaReq.Initiator = RECIPIENT; - Elem->MsgLen = sizeof(DelbaReq); - NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); - MlmeDELBAAction(pAd, Elem); - kfree(Elem); - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__)); - return; - } - } - - - // - // 2. Free resource of BA session - // - // flush all pending reordering mpdus - ba_refresh_reordering_mpdus(pAd, pBAEntry); - - NdisAcquireSpinLock(&pAd->BATabLock); - - // Erase Bitmap flag. - pBAEntry->LastIndSeq = RESET_RCV_SEQ; - pBAEntry->BAWinSize = 0; - // Erase Bitmap flag at software mactable - pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID))); - pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0; - - RTMP_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID); - - NdisReleaseSpinLock(&pAd->BATabLock); - - } - - BATableFreeRecEntry(pAd, Idx); -} - -VOID BASessionTearDownALL( - IN OUT PRTMP_ADAPTER pAd, - IN UCHAR Wcid) -{ - int i; - - for (i=0; ipAdapter; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // Do nothing if monitor mode is on - if (MONITOR_ON(pAd)) - return; - } -#endif // CONFIG_STA_SUPPORT // - -#ifdef RALINK_ATE - // Nothing to do in ATE mode. - if (ATE_ON(pAd)) - return; -#endif // RALINK_ATE // - - pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; - - if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY)) - { - MLME_ADDBA_REQ_STRUCT AddbaReq; - - NdisZeroMemory(&AddbaReq, sizeof(AddbaReq)); - COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr); - AddbaReq.Wcid = (UCHAR)(pEntry->Aid); - AddbaReq.TID = pBAEntry->TID; - AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; - AddbaReq.TimeOutValue = 0; - AddbaReq.Token = pBAEntry->Token; - MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq); - RTMP_MLME_HANDLER(pAd); - DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token)); - - pBAEntry->Token++; - RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT); - } - else - { - BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]); - } -} - -/* - ========================================================================== - Description: - Retry sending ADDBA Reqest. - - IRQL = DISPATCH_LEVEL - - Parametrs: - p8023Header: if this is already 802.3 format, p8023Header is NULL - - Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. - FALSE , then continue indicaterx at this moment. - ========================================================================== - */ -VOID BARecSessionIdleTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - - BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext; - PRTMP_ADAPTER pAd; - ULONG Now32; - - if (pBAEntry == NULL) - return; - - if ((pBAEntry->REC_BA_Status == Recipient_Accept)) - { - NdisGetSystemUpTime(&Now32); - - if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT))) - { - pAd = pBAEntry->pAdapter; - // flush all pending reordering mpdus - ba_refresh_reordering_mpdus(pAd, pBAEntry); - DBGPRINT(RT_DEBUG_OFF, ("%ld: REC BA session Timeout\n", Now32)); - } - } -} - - -VOID PeerAddBAReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) - -{ - // 7.4.4.1 - //ULONG Idx; - UCHAR Status = 1; - UCHAR pAddr[6]; - FRAME_ADDBA_RSP ADDframe; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - PFRAME_ADDBA_REQ pAddreqFrame = NULL; - //UCHAR BufSize; - ULONG FrameLen; - PULONG ptemp; - PMAC_TABLE_ENTRY pMacEntry; - - DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __FUNCTION__, Elem->Wcid)); - - //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen); - - //ADDBA Request from unknown peer, ignore this. - if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) - return; - - pMacEntry = &pAd->MacTab.Content[Elem->Wcid]; - DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n")); - ptemp = (PULONG)Elem->Msg; - //DBGPRINT_RAW(RT_DEBUG_EMU, ("%08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x\n", *(ptemp), *(ptemp+1), *(ptemp+2), *(ptemp+3), *(ptemp+4), *(ptemp+5), *(ptemp+6), *(ptemp+7), *(ptemp+8))); - - if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr)) - { - - if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry)) - { - pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); - DBGPRINT(RT_DEBUG_OFF, ("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid)); - if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame)) - Status = 0; - else - Status = 38; // more parameters have invalid values - } - else - { - Status = 37; // the request has been declined. - } - } - - if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI) - ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC); - - pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); - // 2. Always send back ADDBA Response - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n")); - return; - } - - NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP)); - // 2-1. Prepare ADDBA Response frame. -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (ADHOC_ON(pAd)) - ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); - else -#ifdef QOS_DLS_SUPPORT - if (pAd->MacTab.Content[Elem->Wcid].ValidAsDls) - ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); - else -#endif // QOS_DLS_SUPPORT // - ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr); - } -#endif // CONFIG_STA_SUPPORT // - ADDframe.Category = CATEGORY_BA; - ADDframe.Action = ADDBA_RESP; - ADDframe.Token = pAddreqFrame->Token; - // What is the Status code?? need to check. - ADDframe.StatusCode = Status; - ADDframe.BaParm.BAPolicy = IMMED_BA; - ADDframe.BaParm.AMSDUSupported = 0; - ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID; - ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); - if (ADDframe.BaParm.BufSize == 0) - { - ADDframe.BaParm.BufSize = 64; - } - ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue; - - *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm)); - ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode); - ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue); - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(FRAME_ADDBA_RSP), &ADDframe, - END_OF_ARGS); - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __FUNCTION__, Elem->Wcid, ADDframe.BaParm.TID, - ADDframe.BaParm.BufSize)); -} - - -VOID PeerAddBARspAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) - -{ - //UCHAR Idx, i; - //PUCHAR pOutBuffer = NULL; - PFRAME_ADDBA_RSP pFrame = NULL; - //PBA_ORI_ENTRY pBAEntry; - - //ADDBA Response from unknown peer, ignore this. - if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) - return; - - DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __FUNCTION__, Elem->Wcid)); - - //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen); - - if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen)) - { - pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]); - - DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode)); - switch (pFrame->StatusCode) - { - case 0: - // I want a BAsession with this peer as an originator. - BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame); - break; - default: - // check status == USED ??? - BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE); - break; - } - // Rcv Decline StatusCode - if ((pFrame->StatusCode == 37) -#ifdef CONFIG_STA_SUPPORT - || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0)) -#endif // CONFIG_STA_SUPPORT // - ) - { - pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<BaParm.TID; - } - } -} - -VOID PeerDelBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) - -{ - //UCHAR Idx; - //PUCHAR pOutBuffer = NULL; - PFRAME_DELBA_REQ pDelFrame = NULL; - - DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __FUNCTION__)); - //DELBA Request from unknown peer, ignore this. - if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen)) - { - pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]); - if (pDelFrame->DelbaParm.Initiator == ORIGINATOR) - { - DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n")); - BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE); - } - else - { - DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode)); - //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen); - BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE); - } - } -} - - -BOOLEAN CntlEnqueueForRecv( - IN PRTMP_ADAPTER pAd, - IN ULONG Wcid, - IN ULONG MsgLen, - IN PFRAME_BA_REQ pMsg) -{ - PFRAME_BA_REQ pFrame = pMsg; - //PRTMP_REORDERBUF pBuffer; - //PRTMP_REORDERBUF pDmaBuf; - PBA_REC_ENTRY pBAEntry; - //BOOLEAN Result; - ULONG Idx; - //UCHAR NumRxPkt; - UCHAR TID;//, i; - - TID = (UCHAR)pFrame->BARControl.TID; - - DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __FUNCTION__, Wcid, TID)); - //hex_dump("BAR", (PCHAR) pFrame, MsgLen); - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return FALSE; - - // First check the size, it MUST not exceed the mlme queue size - if (MsgLen > MGMT_DMA_BUFFER_SIZE) - { - DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); - return FALSE; - } - else if (MsgLen != sizeof(FRAME_BA_REQ)) - { - DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); - return FALSE; - } - else if (MsgLen != sizeof(FRAME_BA_REQ)) - { - DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); - return FALSE; - } - - if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8)) - { - // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search. - Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; - pBAEntry = &pAd->BATable.BARecEntry[Idx]; - } - else - { - return FALSE; - } - - DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq )); - - if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ)) - { - //DBGPRINT(RT_DEBUG_TRACE, ("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq)); - ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq); - pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1); - } - //ba_refresh_reordering_mpdus(pAd, pBAEntry); - return TRUE; -} - -/* -Description : Send PSMP Action frame If PSMP mode switches. -*/ -VOID SendPSMPAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR Psmp) -{ - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - //ULONG Idx; - FRAME_PSMP_ACTION Frame; - ULONG FrameLen; - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); - return; - } -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr); -#endif // CONFIG_STA_SUPPORT // - - Frame.Category = CATEGORY_HT; - Frame.Action = SMPS_ACTION; - switch (Psmp) - { - case MMPS_ENABLE: -#ifdef RT30xx - if (IS_RT30xx(pAd) - &&(pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1)) - { - RTMP_ASIC_MMPS_DISABLE(pAd); - } -#endif // RT30xx // - Frame.Psmp = 0; - break; - case MMPS_DYNAMIC: - Frame.Psmp = 3; - break; - case MMPS_STATIC: -#ifdef RT30xx - if (IS_RT30xx(pAd) - &&(pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1)) - { - RTMP_ASIC_MMPS_ENABLE(pAd); - } -#endif // RT30xx // - Frame.Psmp = 1; - break; - } - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(FRAME_PSMP_ACTION), &Frame, - END_OF_ARGS); - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp)); -} - - -#define RADIO_MEASUREMENT_REQUEST_ACTION 0 - -typedef struct PACKED -{ - UCHAR RegulatoryClass; - UCHAR ChannelNumber; - USHORT RandomInterval; - USHORT MeasurementDuration; - UCHAR MeasurementMode; - UCHAR BSSID[MAC_ADDR_LEN]; - UCHAR ReportingCondition; - UCHAR Threshold; - UCHAR SSIDIE[2]; // 2 byte -} BEACON_REQUEST; - -typedef struct PACKED -{ - UCHAR ID; - UCHAR Length; - UCHAR Token; - UCHAR RequestMode; - UCHAR Type; -} MEASUREMENT_REQ; - - - - -void convert_reordering_packet_to_preAMSDU_or_802_3_packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) -{ - PNDIS_PACKET pRxPkt; - UCHAR Header802_3[LENGTH_802_3]; - - // 1. get 802.3 Header - // 2. remove LLC - // a. pointer pRxBlk->pData to payload - // b. modify pRxBlk->DataSize - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); -#endif // CONFIG_STA_SUPPORT // - - ASSERT(pRxBlk->pRxPacket); - pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); - - SET_OS_PKT_NETDEV(pRxPkt, get_netdev_from_bssid(pAd, FromWhichBSSID)); - SET_OS_PKT_DATAPTR(pRxPkt, pRxBlk->pData); - SET_OS_PKT_LEN(pRxPkt, pRxBlk->DataSize); - SET_OS_PKT_DATATAIL(pRxPkt, pRxBlk->pData, pRxBlk->DataSize); - - // - // copy 802.3 header, if necessary - // - if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) - { - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { -#ifdef LINUX - NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3); -#endif - } -#endif // CONFIG_STA_SUPPORT // - } -} - - -#define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \ - do \ - { \ - if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \ - { \ - Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ - } \ - else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \ - { \ - Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ - } \ - else \ - { \ - Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ - } \ - } while (0); - - - -static VOID ba_enqueue_reordering_packet( - IN PRTMP_ADAPTER pAd, - IN PBA_REC_ENTRY pBAEntry, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) -{ - struct reordering_mpdu *mpdu_blk; - UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence; - - mpdu_blk = ba_mpdu_blk_alloc(pAd); - if ((mpdu_blk != NULL) && - (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP))) - { - // Write RxD buffer address & allocated buffer length - NdisAcquireSpinLock(&pBAEntry->RxReRingLock); - - mpdu_blk->Sequence = Sequence; - - mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU); - - convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID); - - STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); - - // - // it is necessary for reordering packet to record - // which BSS it come from - // - RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); - - mpdu_blk->pPacket = pRxBlk->pRxPacket; - - if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE) - { - // had been already within reordering list - // don't indicate - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS); - ba_mpdu_blk_free(pAd, mpdu_blk); - } - - ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize)); - NdisReleaseSpinLock(&pBAEntry->RxReRingLock); - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n", - pBAEntry->list.qlen)); - /* - * flush all pending reordering mpdus - * and receving mpdu to upper layer - * make tcp/ip to take care reordering mechanism - */ - //ba_refresh_reordering_mpdus(pAd, pBAEntry); - ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); - - pBAEntry->LastIndSeq = Sequence; - INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); - } -} - - -/* - ========================================================================== - Description: - Indicate this packet to upper layer or put it into reordering buffer - - Parametrs: - pRxBlk : carry necessary packet info 802.11 format - FromWhichBSSID : the packet received from which BSS - - Return : - none - - Note : - the packet queued into reordering buffer need to cover to 802.3 format - or pre_AMSDU format - ========================================================================== - */ - -VOID Indicate_AMPDU_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) -{ - USHORT Idx; - PBA_REC_ENTRY pBAEntry = NULL; - UINT16 Sequence = pRxBlk->pHeader->Sequence; - ULONG Now32; - UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID; - UCHAR TID = pRxBlk->pRxWI->TID; - - - if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > MAX_RX_PKT_LEN)) - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); - return; - } - - - - if (Wcid < MAX_LEN_OF_MAC_TABLE) - { - Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; - if (Idx == 0) - { - /* Rec BA Session had been torn down */ - INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); - return; - } - pBAEntry = &pAd->BATable.BARecEntry[Idx]; - } - else - { - // impossible !!! - ASSERT(0); - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); - return; - } - - ASSERT(pBAEntry); - - // update last rx time - NdisGetSystemUpTime(&Now32); - - pBAEntry->rcvSeq = Sequence; - - - ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); - pBAEntry->LastIndSeqAtTimer = Now32; - - // - // Reset Last Indicate Sequence - // - if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) - { - ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL)); - - // reset rcv sequence of BA session - pBAEntry->LastIndSeq = Sequence; - pBAEntry->LastIndSeqAtTimer = Now32; - INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); - return; - } - - // - // I. Check if in order. - // - if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) - { - USHORT LastIndSeq; - - pBAEntry->LastIndSeq = Sequence; - INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); - LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); - if (LastIndSeq != RESET_RCV_SEQ) - { - pBAEntry->LastIndSeq = LastIndSeq; - } - pBAEntry->LastIndSeqAtTimer = Now32; - } - // - // II. Drop Duplicated Packet - // - else if (Sequence == pBAEntry->LastIndSeq) - { - - // drop and release packet - pBAEntry->nDropPacket++; - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); - } - // - // III. Drop Old Received Packet - // - else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) - { - - // drop and release packet - pBAEntry->nDropPacket++; - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); - } - // - // IV. Receive Sequence within Window Size - // - else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ)) - { - ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID); - } - // - // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer - // - else - { - LONG WinStartSeq, TmpSeq; - - - TmpSeq = Sequence - (pBAEntry->BAWinSize) -1; - if (TmpSeq < 0) - { - TmpSeq = (MAXSEQ+1) + TmpSeq; - } - WinStartSeq = (TmpSeq+1) & MAXSEQ; - ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq); - pBAEntry->LastIndSeq = WinStartSeq; //TmpSeq; - - pBAEntry->LastIndSeqAtTimer = Now32; - - ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID); - - TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); - if (TmpSeq != RESET_RCV_SEQ) - { - pBAEntry->LastIndSeq = TmpSeq; - } - } -} - -#endif // DOT11_N_SUPPORT // diff --git a/drivers/staging/rt3090/common/cmm_asic.c b/drivers/staging/rt3090/common/cmm_asic.c deleted file mode 100644 index 3d1c808496f39e1b1327e1cc97b96a45dd4f4e11..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/cmm_asic.c +++ /dev/null @@ -1,2753 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - cmm_asic.c - - Abstract: - Functions used to communicate with ASIC - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#include "../rt_config.h" - - -// Reset the RFIC setting to new series -RTMP_RF_REGS RF2850RegTable[] = { -// ch R1 R2 R3(TX0~4=0) R4 - {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b}, - {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f}, - {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b}, - {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f}, - {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b}, - {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f}, - {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b}, - {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f}, - {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b}, - {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f}, - {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b}, - {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f}, - {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b}, - {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193}, - - // 802.11 UNI / HyperLan 2 - {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3}, - {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193}, - {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183}, - {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3}, - {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b}, - {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b}, - {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193}, - {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3}, - {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b}, - {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183}, - {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193}, - {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5. - - // 802.11 HyperLan 2 - {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783}, - - // 2008.04.30 modified - // The system team has AN to improve the EVM value - // for channel 102 to 108 for the RT2850/RT2750 dual band solution. - {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793}, - {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3}, - {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193}, - - {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183}, - {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b}, - {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3}, - {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193}, - {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183}, - {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193}, - {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927 - {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3}, - {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b}, - {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193}, - {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b}, - {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183}, - - // 802.11 UNII - {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7}, - {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187}, - {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f}, - {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f}, - {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7}, - {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187}, - {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197}, - {167, 0x98402ec4, 0x984c03d2, 0x98179855, 0x9815531f}, - {169, 0x98402ec4, 0x984c03d2, 0x98179855, 0x98155327}, - {171, 0x98402ec4, 0x984c03d6, 0x98179855, 0x98155307}, - {173, 0x98402ec4, 0x984c03d6, 0x98179855, 0x9815530f}, - - // Japan - {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b}, - {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13}, - {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b}, - {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23}, - {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13}, - {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b}, - {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23}, - - // still lack of MMAC(Japan) ch 34,38,42,46 -}; -UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS)); - -FREQUENCY_ITEM FreqItems3020[] = -{ - /**************************************************/ - // ISM : 2.4 to 2.483 GHz // - /**************************************************/ - // 11g - /**************************************************/ - //-CH---N-------R---K----------- - {1, 241, 2, 2}, - {2, 241, 2, 7}, - {3, 242, 2, 2}, - {4, 242, 2, 7}, - {5, 243, 2, 2}, - {6, 243, 2, 7}, - {7, 244, 2, 2}, - {8, 244, 2, 7}, - {9, 245, 2, 2}, - {10, 245, 2, 7}, - {11, 246, 2, 2}, - {12, 246, 2, 7}, - {13, 247, 2, 2}, - {14, 248, 2, 4}, -}; -UCHAR NUM_OF_3020_CHNL = (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM)); - - -VOID AsicUpdateAutoFallBackTable( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pRateTable) -{ - UCHAR i; - HT_FBK_CFG0_STRUC HtCfg0; - HT_FBK_CFG1_STRUC HtCfg1; - LG_FBK_CFG0_STRUC LgCfg0; - LG_FBK_CFG1_STRUC LgCfg1; - PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate; - - // set to initial value - HtCfg0.word = 0x65432100; - HtCfg1.word = 0xedcba988; - LgCfg0.word = 0xedcba988; - LgCfg1.word = 0x00002100; - - pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1; - for (i = 1; i < *((PUCHAR) pRateTable); i++) - { - pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i; - switch (pCurrTxRate->Mode) - { - case 0: //CCK - break; - case 1: //OFDM - { - switch(pCurrTxRate->CurrMCS) - { - case 0: - LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - case 1: - LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - case 2: - LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - case 3: - LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - case 4: - LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - case 5: - LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - case 6: - LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - case 7: - LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; - break; - } - } - break; -#ifdef DOT11_N_SUPPORT - case 2: //HT-MIX - case 3: //HT-GF - { - if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS)) - { - switch(pCurrTxRate->CurrMCS) - { - case 0: - HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS; - break; - case 1: - HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS; - break; - case 2: - HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS; - break; - case 3: - HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS; - break; - case 4: - HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS; - break; - case 5: - HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS; - break; - case 6: - HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS; - break; - case 7: - HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS; - break; - case 8: - HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS; - break; - case 9: - HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS; - break; - case 10: - HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS; - break; - case 11: - HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS; - break; - case 12: - HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS; - break; - case 13: - HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS; - break; - case 14: - HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS; - break; - case 15: - HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS; - break; - default: - DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS)); - } - } - } - break; -#endif // DOT11_N_SUPPORT // - } - - pNextTxRate = pCurrTxRate; - } - - RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word); - RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word); - RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word); - RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word); -} - -/* - ======================================================================== - - Routine Description: - Set MAC register value according operation mode. - OperationMode AND bNonGFExist are for MM and GF Proteciton. - If MM or GF mask is not set, those passing argument doesn't not take effect. - - Operation mode meaning: - = 0 : Pure HT, no preotection. - = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS. - = 0x10: No Transmission in 40M is protected. - = 0x11: Transmission in both 40M and 20M shall be protected - if (bNonGFExist) - we should choose not to use GF. But still set correct ASIC registers. - ======================================================================== -*/ -VOID AsicUpdateProtect( - IN PRTMP_ADAPTER pAd, - IN USHORT OperationMode, - IN UCHAR SetMask, - IN BOOLEAN bDisableBGProtect, - IN BOOLEAN bNonGFExist) -{ - PROT_CFG_STRUC ProtCfg, ProtCfg4; - UINT32 Protect[6]; - USHORT offset; - UCHAR i; - UINT32 MacReg = 0; - -#ifdef RALINK_ATE - if (ATE_ON(pAd)) - return; -#endif // RALINK_ATE // - -#ifdef DOT11_N_SUPPORT - if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8)) - { - return; - } - - if (pAd->BATable.numDoneOriginator) - { - // - // enable the RTS/CTS to avoid channel collision - // - SetMask = ALLN_SETPROTECT; - OperationMode = 8; - } -#endif // DOT11_N_SUPPORT // - - // Config ASIC RTS threshold register - RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); - MacReg &= 0xFF0000FF; - // If the user want disable RtsThreshold and enbale Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096 - if (( -#ifdef DOT11_N_SUPPORT - (pAd->CommonCfg.BACapability.field.AmsduEnable) || -#endif // DOT11_N_SUPPORT // - (pAd->CommonCfg.bAggregationCapable == TRUE)) - && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD) - { - MacReg |= (0x1000 << 8); - } - else - { - MacReg |= (pAd->CommonCfg.RtsThreshold << 8); - } - - RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); - - // Initial common protection settings - RTMPZeroMemory(Protect, sizeof(Protect)); - ProtCfg4.word = 0; - ProtCfg.word = 0; - ProtCfg.field.TxopAllowGF40 = 1; - ProtCfg.field.TxopAllowGF20 = 1; - ProtCfg.field.TxopAllowMM40 = 1; - ProtCfg.field.TxopAllowMM20 = 1; - ProtCfg.field.TxopAllowOfdm = 1; - ProtCfg.field.TxopAllowCck = 1; - ProtCfg.field.RTSThEn = 1; - ProtCfg.field.ProtectNav = ASIC_SHORTNAV; - - // update PHY mode and rate - if (pAd->CommonCfg.Channel > 14) - ProtCfg.field.ProtectRate = 0x4000; - ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate; - - // Handle legacy(B/G) protection - if (bDisableBGProtect) - { - //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; - ProtCfg.field.ProtectCtrl = 0; - Protect[0] = ProtCfg.word; - Protect[1] = ProtCfg.word; - pAd->FlgCtsEnabled = 0; /* CTS-self is not used */ - } - else - { - //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; - ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected - Protect[0] = ProtCfg.word; - ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect - Protect[1] = ProtCfg.word; - pAd->FlgCtsEnabled = 1; /* CTS-self is used */ - } - -#ifdef DOT11_N_SUPPORT - // Decide HT frame protection. - if ((SetMask & ALLN_SETPROTECT) != 0) - { - switch(OperationMode) - { - case 0x0: - // NO PROTECT - // 1.All STAs in the BSS are 20/40 MHz HT - // 2. in ai 20/40MHz BSS - // 3. all STAs are 20MHz in a 20MHz BSS - // Pure HT. no protection. - - // MM20_PROT_CFG - // Reserved (31:27) - // PROT_TXOP(25:20) -- 010111 - // PROT_NAV(19:18) -- 01 (Short NAV protection) - // PROT_CTRL(17:16) -- 00 (None) - // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) - Protect[2] = 0x01744004; - - // MM40_PROT_CFG - // Reserved (31:27) - // PROT_TXOP(25:20) -- 111111 - // PROT_NAV(19:18) -- 01 (Short NAV protection) - // PROT_CTRL(17:16) -- 00 (None) - // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) - Protect[3] = 0x03f44084; - - // CF20_PROT_CFG - // Reserved (31:27) - // PROT_TXOP(25:20) -- 010111 - // PROT_NAV(19:18) -- 01 (Short NAV protection) - // PROT_CTRL(17:16) -- 00 (None) - // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) - Protect[4] = 0x01744004; - - // CF40_PROT_CFG - // Reserved (31:27) - // PROT_TXOP(25:20) -- 111111 - // PROT_NAV(19:18) -- 01 (Short NAV protection) - // PROT_CTRL(17:16) -- 00 (None) - // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) - Protect[5] = 0x03f44084; - - if (bNonGFExist) - { - // PROT_NAV(19:18) -- 01 (Short NAV protectiion) - // PROT_CTRL(17:16) -- 01 (RTS/CTS) - Protect[4] = 0x01754004; - Protect[5] = 0x03f54084; - } - pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; - break; - - case 1: - // This is "HT non-member protection mode." - // If there may be non-HT STAs my BSS - ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None) - ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1. - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) - { - ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18.. - ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083; - } - //Assign Protection method for 20&40 MHz packets - ProtCfg.field.ProtectCtrl = ASIC_RTS; - ProtCfg.field.ProtectNav = ASIC_SHORTNAV; - ProtCfg4.field.ProtectCtrl = ASIC_RTS; - ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; - Protect[2] = ProtCfg.word; - Protect[3] = ProtCfg4.word; - Protect[4] = ProtCfg.word; - Protect[5] = ProtCfg4.word; - pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; - break; - - case 2: - // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets - ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None) - ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1. - - //Assign Protection method for 40MHz packets - ProtCfg4.field.ProtectCtrl = ASIC_RTS; - ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; - Protect[2] = ProtCfg.word; - Protect[3] = ProtCfg4.word; - if (bNonGFExist) - { - ProtCfg.field.ProtectCtrl = ASIC_RTS; - ProtCfg.field.ProtectNav = ASIC_SHORTNAV; - } - Protect[4] = ProtCfg.word; - Protect[5] = ProtCfg4.word; - - pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; - break; - - case 3: - // HT mixed mode. PROTECT ALL! - // Assign Rate - ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1. - ProtCfg4.word = 0x03f44084; - // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) - { - ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18.. - ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083 - } - //Assign Protection method for 20&40 MHz packets - ProtCfg.field.ProtectCtrl = ASIC_RTS; - ProtCfg.field.ProtectNav = ASIC_SHORTNAV; - ProtCfg4.field.ProtectCtrl = ASIC_RTS; - ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; - Protect[2] = ProtCfg.word; - Protect[3] = ProtCfg4.word; - Protect[4] = ProtCfg.word; - Protect[5] = ProtCfg4.word; - pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; - break; - - case 8: - // Special on for Atheros problem n chip. - Protect[2] = 0x01754004; - Protect[3] = 0x03f54084; - Protect[4] = 0x01754004; - Protect[5] = 0x03f54084; - pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; - break; - } - } -#endif // DOT11_N_SUPPORT // - - offset = CCK_PROT_CFG; - for (i = 0;i < 6;i++) - { - if ((SetMask & (1<< i))) - { - RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]); - } -} -} - - -/* - ========================================================================== - Description: - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AsicSwitchChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel, - IN BOOLEAN bScan) -{ - ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0; - CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER; - UCHAR index; - UINT32 Value = 0; //BbpReg, Value; - RTMP_RF_REGS *RFRegTable; - UCHAR RFValue; - - RFValue = 0; - // Search Tx power value - // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list - // in ChannelList, so use TxPower array instead. - // - for (index = 0; index < MAX_NUM_OF_CHANNELS; index++) - { - if (Channel == pAd->TxPower[index].Channel) - { - TxPwer = pAd->TxPower[index].Power; - TxPwer2 = pAd->TxPower[index].Power2; - break; - } - } - - if (index == MAX_NUM_OF_CHANNELS) - { - DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel)); - } - -#ifdef RT30xx - // The RF programming sequence is difference between 3xxx and 2xxx - if ((IS_RT3070(pAd) || IS_RT3090(pAd)||IS_RT3390(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) || - (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022))) - { - /* modify by WY for Read RF Reg. error */ - - for (index = 0; index < NUM_OF_3020_CHNL; index++) - { - if (Channel == FreqItems3020[index].Channel) - { - // Programming channel parameters - RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N); - RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K); - RT30xxReadRFRegister(pAd, RF_R06, &RFValue); - RFValue = (RFValue & 0xFC) | FreqItems3020[index].R; - RT30xxWriteRFRegister(pAd, RF_R06, RFValue); - - // Set Tx0 Power - RT30xxReadRFRegister(pAd, RF_R12, &RFValue); - RFValue = (RFValue & 0xE0) | TxPwer; - RT30xxWriteRFRegister(pAd, RF_R12, RFValue); - - // Set Tx1 Power - RT30xxReadRFRegister(pAd, RF_R13, &RFValue); - RFValue = (RFValue & 0xE0) | TxPwer2; - RT30xxWriteRFRegister(pAd, RF_R13, RFValue); - - // Tx/Rx Stream setting - RT30xxReadRFRegister(pAd, RF_R01, &RFValue); - //if (IS_RT3090(pAd)) - // RFValue |= 0x01; // Enable RF block. - RFValue &= 0x03; //clear bit[7~2] - if (pAd->Antenna.field.TxPath == 1) - RFValue |= 0xA0; - else if (pAd->Antenna.field.TxPath == 2) - RFValue |= 0x80; - if (pAd->Antenna.field.RxPath == 1) - RFValue |= 0x50; - else if (pAd->Antenna.field.RxPath == 2) - RFValue |= 0x40; - RT30xxWriteRFRegister(pAd, RF_R01, RFValue); - - // Set RF offset - RT30xxReadRFRegister(pAd, RF_R23, &RFValue); - RFValue = (RFValue & 0x80) | pAd->RfFreqOffset; - RT30xxWriteRFRegister(pAd, RF_R23, RFValue); - - // Set BW - if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40)) - { - RFValue = pAd->Mlme.CaliBW40RfR24; - //DISABLE_11N_CHECK(pAd); - } - else - { - RFValue = pAd->Mlme.CaliBW20RfR24; - } - RT30xxWriteRFRegister(pAd, RF_R24, RFValue); - RT30xxWriteRFRegister(pAd, RF_R31, RFValue); - - // Enable RF tuning - RT30xxReadRFRegister(pAd, RF_R07, &RFValue); - RFValue = RFValue | 0x1; - RT30xxWriteRFRegister(pAd, RF_R07, RFValue); - - // latch channel for future usage. - pAd->LatchRfRegs.Channel = Channel; - - DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", - Channel, - pAd->RfIcType, - TxPwer, - TxPwer2, - pAd->Antenna.field.TxPath, - FreqItems3020[index].N, - FreqItems3020[index].K, - FreqItems3020[index].R)); - - break; - } - } - } - else -#endif // RT30xx // - { - RFRegTable = RF2850RegTable; - switch (pAd->RfIcType) - { - case RFIC_2820: - case RFIC_2850: - case RFIC_2720: - case RFIC_2750: - - for (index = 0; index < NUM_OF_2850_CHNL; index++) - { - if (Channel == RFRegTable[index].Channel) - { - R2 = RFRegTable[index].R2; - if (pAd->Antenna.field.TxPath == 1) - { - R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; - } - - if (pAd->Antenna.field.RxPath == 2) - { - R2 |= 0x40; // write 1 to off Rxpath. - } - else if (pAd->Antenna.field.RxPath == 1) - { - R2 |= 0x20040; // write 1 to off RxPath - } - - if (Channel > 14) - { - // initialize R3, R4 - R3 = (RFRegTable[index].R3 & 0xffffc1ff); - R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15); - - // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB - // R3 - if ((TxPwer >= -7) && (TxPwer < 0)) - { - TxPwer = (7+TxPwer); - TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); - R3 |= (TxPwer << 10); - DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer)); - } - else - { - TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); - R3 |= (TxPwer << 10) | (1 << 9); - } - - // R4 - if ((TxPwer2 >= -7) && (TxPwer2 < 0)) - { - TxPwer2 = (7+TxPwer2); - TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); - R4 |= (TxPwer2 << 7); - DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2)); - } - else - { - TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); - R4 |= (TxPwer2 << 7) | (1 << 6); - } - } - else - { - R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0 - R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1 - } - - // Based on BBP current mode before changing RF channel. - if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40)) - { - R4 |=0x200000; - } - - // Update variables - pAd->LatchRfRegs.Channel = Channel; - pAd->LatchRfRegs.R1 = RFRegTable[index].R1; - pAd->LatchRfRegs.R2 = R2; - pAd->LatchRfRegs.R3 = R3; - pAd->LatchRfRegs.R4 = R4; - -#ifdef DFS_DEBUG -#ifdef DFS_FCC_BW40_FIX - if (pAd->infType == RTMP_DEV_INF_PCI) // RT2880 PCI - { - /* only for RT2880 */ - // FCC DFS test - pAd->LatchRfRegs.R1 |= 0x100; - pAd->LatchRfRegs.R4 |= 0x00400000; - } -#endif // DFS_FCC_BW40_FIX // -#endif // DFS_DEBUG // - - // Set RF value 1's set R3[bit2] = [0] - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); - RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); - - RTMPusecDelay(200); - - // Set RF value 2's set R3[bit2] = [1] - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); - RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04)); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); - - RTMPusecDelay(200); - - // Set RF value 3's set R3[bit2] = [0] - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); - RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); - - break; - } - } - break; - - default: - break; - } - - DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", - Channel, - pAd->RfIcType, - (R3 & 0x00003e00) >> 9, - (R4 & 0x000007c0) >> 6, - pAd->Antenna.field.TxPath, - pAd->LatchRfRegs.R1, - pAd->LatchRfRegs.R2, - pAd->LatchRfRegs.R3, - pAd->LatchRfRegs.R4)); - } - - // Change BBP setting during siwtch from a->g, g->a - if (Channel <= 14) - { - ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A - - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. - //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); - - // Rx High power VGA offset for LNA select - if (pAd->NicConfig2.field.ExternalLNAForG) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); - } - else - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); - } - - // 5G band selection PIN, bit1 and bit2 are complement - RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); - Value &= (~0x6); - Value |= (0x04); - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); - - // Turn off unused PA or LNA when only 1T or 1R - if (pAd->Antenna.field.TxPath == 1) - { - TxPinCfg &= 0xFFFFFFF3; - } - if (pAd->Antenna.field.RxPath == 1) - { - TxPinCfg &= 0xFFFFF3FF; - } - - - RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); - -#if defined(RT3090) || defined(RT3390) - // PCIe PHY Transmit attenuation adjustment - if (IS_RT3090A(pAd) || IS_RT3390(pAd)) - { - TX_ATTENUATION_CTRL_STRUC TxAttenuationCtrl = {0}; - - RTMP_IO_READ32(pAd, PCIE_PHY_TX_ATTENUATION_CTRL, &TxAttenuationCtrl.word); - - if (Channel == 14) // Channel #14 - { - TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_EN = 1; // Enable PCIe PHY Tx attenuation - TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_VALUE = 4; // 9/16 full drive level - } - else // Channel #1~#13 - { - TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_EN = 0; // Disable PCIe PHY Tx attenuation - TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_VALUE = 0; // n/a - } - - RTMP_IO_WRITE32(pAd, PCIE_PHY_TX_ATTENUATION_CTRL, TxAttenuationCtrl.word); - } -#endif - } - else - { - ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505 - - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); - - // Rx High power VGA offset for LNA select - if (pAd->NicConfig2.field.ExternalLNAForA) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); - } - else - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); - } - - // 5G band selection PIN, bit1 and bit2 are complement - RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); - Value &= (~0x6); - Value |= (0x02); - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); - - // Turn off unused PA or LNA when only 1T or 1R - if (pAd->Antenna.field.TxPath == 1) - { - TxPinCfg &= 0xFFFFFFF3; - } - if (pAd->Antenna.field.RxPath == 1) - { - TxPinCfg &= 0xFFFFF3FF; - } - - - RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); - - } - - // R66 should be set according to Channel and use 20MHz when scanning - //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd))); - if (bScan) - RTMPSetAGCInitValue(pAd, BW_20); - else - RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); - - // - // On 11A, We should delay and wait RF/BBP to be stable - // and the appropriate time should be 1000 micro seconds - // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL. - // - RTMPusecDelay(1000); -} - -/* - ========================================================================== - Description: - This function is required for 2421 only, and should not be used during - site survey. It's only required after NIC decided to stay at a channel - for a longer period. - When this function is called, it's always after AsicSwitchChannel(). - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AsicLockChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel) -{ -} - -/* - ========================================================================== - Description: - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -#ifdef ANT_DIVERSITY_SUPPORT -VOID AsicAntennaSelect( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel) -{ -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - if (pAd->Mlme.OneSecPeriodicRound % 2 == 1) -#endif // CONFIG_STA_SUPPORT // - { - // patch for AsicSetRxAnt failed - pAd->RxAnt.EvaluatePeriod = 0; - - // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a - // valid indication of the distance between this AP and its clients. - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - SHORT realavgrssi1; - - // if no traffic then reset average rssi to trigger evaluation -#ifdef CONFIG_STA_SUPPORT - if (pAd->StaCfg.NumOfAvgRssiSample < 5) - { - pAd->RxAnt.Pair1LastAvgRssi = (-99); - pAd->RxAnt.Pair2LastAvgRssi = (-99); - DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n")); - } - - pAd->StaCfg.NumOfAvgRssiSample = 0; - realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3); -#endif // CONFIG_STA_SUPPORT // - - DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt)); - - // if the difference between two rssi is larger or less than 5, then evaluate the other antenna - if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5))) - AsicEvaluateRxAnt(pAd); - - pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1; - } - else - { - // if not connected, always switch antenna to try to connect - UCHAR temp; - - temp = pAd->RxAnt.Pair1PrimaryRxAnt; - pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt; - pAd->RxAnt.Pair1SecondaryRxAnt = temp; - - DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n")); - - AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); - } - } -} -#endif // ANT_DIVERSITY_SUPPORT // - -/* - ======================================================================== - - Routine Description: - Antenna miscellaneous setting. - - Arguments: - pAd Pointer to our adapter - BandState Indicate current Band State. - - Return Value: - None - - IRQL <= DISPATCH_LEVEL - - Note: - 1.) Frame End type control - only valid for G only (RF_2527 & RF_2529) - 0: means DPDT, set BBP R4 bit 5 to 1 - 1: means SPDT, set BBP R4 bit 5 to 0 - - - ======================================================================== -*/ -VOID AsicAntennaSetting( - IN PRTMP_ADAPTER pAd, - IN ABGBAND_STATE BandState) -{ -} - -VOID AsicRfTuningExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ -} - -/* - ========================================================================== - Description: - Gives CCK TX rate 2 more dB TX power. - This routine works only in LINK UP in INFRASTRUCTURE mode. - - calculate desired Tx power in RF R3.Tx0~5, should consider - - 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) - 1. TxPowerPercentage - 2. auto calibration based on TSSI feedback - 3. extra 2 db for CCK - 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP - - NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), - it should be called AFTER MlmeDynamicTxRatSwitching() - ========================================================================== - */ -VOID AsicAdjustTxPower( - IN PRTMP_ADAPTER pAd) -{ - INT i, j; - CHAR DeltaPwr = 0; - BOOLEAN bAutoTxAgc = FALSE; - UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; - UCHAR BbpR1 = 0, BbpR49 = 0, idx; - PCHAR pTxAgcCompensate; - ULONG TxPwr[5]; - CHAR Value; -#ifdef CONFIG_STA_SUPPORT - CHAR Rssi = -127; -#endif // CONFIG_STA_SUPPORT // -#ifdef CARRIER_SENSE_NEW_ALGO - unsigned long flags; //KH Add to Fix PCIe Power-Saving bug -#endif // CARRIER_SENSE_NEW_ALGO // - - -#ifdef CARRIER_SENSE_NEW_ALGO - //KH Add to Fix PCIe Power-Saving bug<-- - RTMP_INT_LOCK(&pAd->irq_lock, flags); - //KH Add to Fix PCIe Power-Saving bug--> -#endif // CARRIER_SENSE_NEW_ALGO // - -#ifdef CONFIG_STA_SUPPORT - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) || -#ifdef RTMP_MAC_PCI - (pAd->bPCIclkOff == TRUE) || -#endif // RTMP_MAC_PCI // - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) -{ - -#ifdef CARRIER_SENSE_NEW_ALGO - //KH Add to Fix PCIe Power-Saving bug<-- - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - //KH add to fix PCIe-Power Saving --> -#endif // CARRIER_SENSE_NEW_ALGO // - return; -} - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - Rssi = RTMPMaxRssi(pAd, - pAd->StaCfg.RssiSample.AvgRssi0, - pAd->StaCfg.RssiSample.AvgRssi1, - pAd->StaCfg.RssiSample.AvgRssi2); -#endif // CONFIG_STA_SUPPORT // - - if (pAd->CommonCfg.BBPCurrentBW == BW_40) - { - if (pAd->CommonCfg.CentralChannel > 14) - { - TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; - TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; - TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; - TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; - TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; - } - else - { - TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; - TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; - TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; - TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; - TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; - } - } - else - { - if (pAd->CommonCfg.Channel > 14) - { - TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; - TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; - TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; - TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; - TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; - } - else - { - TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; - TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; - TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; - TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; - TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; - } - } - - // TX power compensation for temperature variation based on TSSI. try every 4 second - if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) - { - if (pAd->CommonCfg.Channel <= 14) - { - /* bg channel */ - bAutoTxAgc = pAd->bAutoTxAgcG; - TssiRef = pAd->TssiRefG; - pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; - pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; - TxAgcStep = pAd->TxAgcStepG; - pTxAgcCompensate = &pAd->TxAgcCompensateG; - } - else - { - /* a channel */ - bAutoTxAgc = pAd->bAutoTxAgcA; - TssiRef = pAd->TssiRefA; - pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; - pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; - TxAgcStep = pAd->TxAgcStepA; - pTxAgcCompensate = &pAd->TxAgcCompensateA; - } - - if (bAutoTxAgc) - { - /* BbpR1 is unsigned char */ - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); - - /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ - /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ - /* step value is defined in pAd->TxAgcStepG for tx power value */ - - /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ - /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 - above value are examined in mass factory production */ - /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ - - /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */ - /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ - /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */ - - if (BbpR49 > pTssiMinusBoundary[1]) - { - // Reading is larger than the reference value - // check for how large we need to decrease the Tx power - for (idx = 1; idx < 5; idx++) - { - if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range - break; - } - // The index is the step we should decrease, idx = 0 means there is nothing to compensate -// if (R3 > (ULONG) (TxAgcStep * (idx-1))) - *pTxAgcCompensate = -(TxAgcStep * (idx-1)); -// else -// *pTxAgcCompensate = -((UCHAR)R3); - - DeltaPwr += (*pTxAgcCompensate); - DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", - BbpR49, TssiRef, TxAgcStep, idx-1)); - } - else if (BbpR49 < pTssiPlusBoundary[1]) - { - // Reading is smaller than the reference value - // check for how large we need to increase the Tx power - for (idx = 1; idx < 5; idx++) - { - if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range - break; - } - // The index is the step we should increase, idx = 0 means there is nothing to compensate - *pTxAgcCompensate = TxAgcStep * (idx-1); - DeltaPwr += (*pTxAgcCompensate); - DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", - BbpR49, TssiRef, TxAgcStep, idx-1)); - } - else - { - *pTxAgcCompensate = 0; - DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", - BbpR49, TssiRef, TxAgcStep, 0)); - } - } - } - else - { - if (pAd->CommonCfg.Channel <= 14) - { - bAutoTxAgc = pAd->bAutoTxAgcG; - pTxAgcCompensate = &pAd->TxAgcCompensateG; - } - else - { - bAutoTxAgc = pAd->bAutoTxAgcA; - pTxAgcCompensate = &pAd->TxAgcCompensateA; - } - - if (bAutoTxAgc) - DeltaPwr += (*pTxAgcCompensate); - } - - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); - BbpR1 &= 0xFC; - -#ifdef SINGLE_SKU - // Handle regulatory max tx power constrain - do - { - UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion; - UCHAR AdjustMaxTxPwr[40]; - - if (pAd->CommonCfg.Channel > 14) // 5G band - TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8); - else // 2.4G band - TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF); - CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); - - // error handling, range check - if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50)) - { - DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr)); - break; - } - - criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion - - DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr)); - - // Adjust max tx power according to the relationship of tx power in E2PROM - for (i=0; i<5; i++) - { - // CCK will have 4dBm larger than OFDM - // Therefore, we should separate to parse the tx power field - if (i == 0) - { - for (j=0; j<8; j++) - { - Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); - - if (j < 4) - { - // CCK will have 4dBm larger than OFDM - AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4; - } - else - { - AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion); - } - DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); - } - } - else - { - for (j=0; j<8; j++) - { - Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); - - AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion); - DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); - } - } - } - - // Adjust tx power according to the relationship - for (i=0; i<5; i++) - { - if (TxPwr[i] != 0xffffffff) - { - for (j=0; j<8; j++) - { - Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); - - // The system tx power is larger than the regulatory, the power should be restrain - if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr) - { - // decrease to zero and don't need to take care BBPR1 - if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0) - Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr); - else - Value = 0; - - DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); - } - else - DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); - - TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); - } - } - } - } while (FALSE); -#endif // SINGLE_SKU // - - /* calculate delta power based on the percentage specified from UI */ - // E2PROM setting is calibrated for maximum TX power (i.e. 100%) - // We lower TX power here according to the percentage specified from UI - if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control - { -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // to patch high power issue with some APs, like Belkin N1. - if (Rssi > -35) - { - BbpR1 |= 0x02; // DeltaPwr -= 12; - } - else if (Rssi > -40) - { - BbpR1 |= 0x01; // DeltaPwr -= 6; - } - else - ; - } -#endif // CONFIG_STA_SUPPORT // - } - else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW - ; - else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1; - { - DeltaPwr -= 1; - } - else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3; - { - DeltaPwr -= 3; - } - else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6; - { - BbpR1 |= 0x01; - } - else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9; - { - BbpR1 |= 0x01; - DeltaPwr -= 3; - } - else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12; - { - BbpR1 |= 0x02; - } - - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); - - /* reset different new tx power for different TX rate */ - for(i=0; i<5; i++) - { - if (TxPwr[i] != 0xffffffff) - { - for (j=0; j<8; j++) - { - Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */ - - if ((Value + DeltaPwr) < 0) - { - Value = 0; /* min */ - } - else if ((Value + DeltaPwr) > 0xF) - { - Value = 0xF; /* max */ - } - else - { - Value += DeltaPwr; /* temperature compensation */ - } - - /* fill new value to CSR offset */ - TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); - } - - /* write tx power value to CSR */ - /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M - TX power for OFDM 6M/9M - TX power for CCK5.5M/11M - TX power for CCK1M/2M */ - /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ - RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]); - } - } - -#ifdef CARRIER_SENSE_NEW_ALGO - //KH Add to Fix PCIe Power-Saving bug<-- - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - //KH add to fix PCIe-Power Saving --> -#endif // CARRIER_SENSE_NEW_ALGO // - -} - - -#ifdef CONFIG_STA_SUPPORT -VOID AsicResetBBPAgent( -IN PRTMP_ADAPTER pAd) -{ - BBP_CSR_CFG_STRUC BbpCsr; - DBGPRINT(RT_DEBUG_ERROR, ("Reset BBP Agent busy bit.!! \n")); - // Still need to find why BBP agent keeps busy, but in fact, hardware still function ok. Now clear busy first. - RTMP_IO_READ32(pAd, H2M_BBP_AGENT, &BbpCsr.word); - BbpCsr.field.Busy = 0; - RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, BbpCsr.word); -} -/* - ========================================================================== - Description: - put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup - automatically. Instead, MCU will issue a TwakeUpInterrupt to host after - the wakeup timer timeout. Driver has to issue a separate command to wake - PHY up. - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AsicSleepThenAutoWakeup( - IN PRTMP_ADAPTER pAd, - IN USHORT TbttNumToNextWakeUp) -{ - RTMP_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp); -} - -/* - ========================================================================== - Description: - AsicForceWakeup() is used whenever manual wakeup is required - AsicForceSleep() should only be used when not in INFRA BSS. When - in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead. - ========================================================================== - */ -VOID AsicForceSleep( - IN PRTMP_ADAPTER pAd) -{ - -} - -/* - ========================================================================== - Description: - AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup) - expired. - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - ========================================================================== - */ -VOID AsicForceWakeup( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bFromTx) -{ - DBGPRINT(RT_DEBUG_INFO, ("--> AsicForceWakeup \n")); - RTMP_STA_FORCE_WAKEUP(pAd, bFromTx); -} -#endif // CONFIG_STA_SUPPORT // - - -/* - ========================================================================== - Description: - Set My BSSID - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AsicSetBssid( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pBssid) -{ - ULONG Addr4; - DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n", - pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5])); - - Addr4 = (ULONG)(pBssid[0]) | - (ULONG)(pBssid[1] << 8) | - (ULONG)(pBssid[2] << 16) | - (ULONG)(pBssid[3] << 24); - RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); - - Addr4 = 0; - // always one BSSID in STA mode - Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8); - - RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); -} - -VOID AsicSetMcastWC( - IN PRTMP_ADAPTER pAd) -{ - MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID]; - USHORT offset; - - pEntry->Sst = SST_ASSOC; - pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index - pEntry->PsMode = PWR_ACTIVE; - pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate; - offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE; -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AsicDelWcidTab( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid) -{ - ULONG Addr0 = 0x0, Addr1 = 0x0; - ULONG offset; - - DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid)); - offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE; - RTMP_IO_WRITE32(pAd, offset, Addr0); - offset += 4; - RTMP_IO_WRITE32(pAd, offset, Addr1); -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AsicEnableRDG( - IN PRTMP_ADAPTER pAd) -{ - TX_LINK_CFG_STRUC TxLinkCfg; - UINT32 Data = 0; - - RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); - TxLinkCfg.field.TxRDGEn = 1; - RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); - - RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); - Data &= 0xFFFFFF00; - Data |= 0x80; - RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); - - //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AsicDisableRDG( - IN PRTMP_ADAPTER pAd) -{ - TX_LINK_CFG_STRUC TxLinkCfg; - UINT32 Data = 0; - - - RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); - TxLinkCfg.field.TxRDGEn = 0; - RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); - - RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); - - Data &= 0xFFFFFF00; - //Data |= 0x20; -#ifndef WIFI_TEST - //if ( pAd->CommonCfg.bEnableTxBurst ) - // Data |= 0x60; // for performance issue not set the TXOP to 0 -#endif - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE) -#ifdef DOT11_N_SUPPORT - && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE) -#endif // DOT11_N_SUPPORT // - ) - { - // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode - if (pAd->CommonCfg.bEnableTxBurst) - Data |= 0x20; - } - RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); -} - -/* - ========================================================================== - Description: - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AsicDisableSync( - IN PRTMP_ADAPTER pAd) -{ - BCN_TIME_CFG_STRUC csr; - - DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n")); - - // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect - // that NIC will never wakes up because TSF stops and no more - // TBTT interrupts - pAd->TbttTickCount = 0; - RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); - csr.field.bBeaconGen = 0; - csr.field.bTBTTEnable = 0; - csr.field.TsfSyncMode = 0; - csr.field.bTsfTicking = 0; - RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); - -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AsicEnableBssSync( - IN PRTMP_ADAPTER pAd) -{ - BCN_TIME_CFG_STRUC csr; - - DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n")); - - RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); -// RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000); -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU - csr.field.bTsfTicking = 1; - csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode - csr.field.bBeaconGen = 0; // do NOT generate BEACON - csr.field.bTBTTEnable = 1; - } -#endif // CONFIG_STA_SUPPORT // - RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); -} - -/* - ========================================================================== - Description: - Note: - BEACON frame in shared memory should be built ok before this routine - can be called. Otherwise, a garbage frame maybe transmitted out every - Beacon period. - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AsicEnableIbssSync( - IN PRTMP_ADAPTER pAd) -{ - BCN_TIME_CFG_STRUC csr9; - PUCHAR ptr; - UINT i; - - DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount)); - - RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word); - csr9.field.bBeaconGen = 0; - csr9.field.bTBTTEnable = 0; - csr9.field.bTsfTicking = 0; - RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); - -#ifdef RTMP_MAC_PCI - // move BEACON TXD and frame content to on-chip memory - ptr = (PUCHAR)&pAd->BeaconTxWI; - for (i=0; iBeaconBuf; - for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4) - { - UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); - RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr); - ptr +=4; - } -#endif // RTMP_MAC_PCI // - - - // - // For Wi-Fi faily generated beacons between participating stations. - // Set TBTT phase adaptive adjustment step to 8us (default 16us) - // don't change settings 2006-5- by Jerry - //RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010); - - // start sending BEACON - csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU - csr9.field.bTsfTicking = 1; - csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode - csr9.field.bTBTTEnable = 1; - csr9.field.bBeaconGen = 1; - RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); -} - -/* - ========================================================================== - Description: - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AsicSetEdcaParm( - IN PRTMP_ADAPTER pAd, - IN PEDCA_PARM pEdcaParm) -{ - EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg; - AC_TXOP_CSR0_STRUC csr0; - AC_TXOP_CSR1_STRUC csr1; - AIFSN_CSR_STRUC AifsnCsr; - CWMIN_CSR_STRUC CwminCsr; - CWMAX_CSR_STRUC CwmaxCsr; - int i; - - Ac0Cfg.word = 0; - Ac1Cfg.word = 0; - Ac2Cfg.word = 0; - Ac3Cfg.word = 0; - if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE)) - { - DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n")); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED); - for (i=0; iMacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli) - CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE); - } - - //======================================================== - // MAC Register has a copy . - //======================================================== -//#ifndef WIFI_TEST - if( pAd->CommonCfg.bEnableTxBurst ) - { - // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode - Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode - } - else - Ac0Cfg.field.AcTxop = 0; // QID_AC_BE -//#else -// Ac0Cfg.field.AcTxop = 0; // QID_AC_BE -//#endif - Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS; - Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS; - Ac0Cfg.field.Aifsn = 2; - RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); - - Ac1Cfg.field.AcTxop = 0; // QID_AC_BK - Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS; - Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS; - Ac1Cfg.field.Aifsn = 2; - RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); - - if (pAd->CommonCfg.PhyMode == PHY_11B) - { - Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms - Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms - } - else - { - Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms - Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms - } - Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS; - Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS; - Ac2Cfg.field.Aifsn = 2; - RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); - Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS; - Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS; - Ac3Cfg.field.Aifsn = 2; - RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); - - //======================================================== - // DMA Register has a copy too. - //======================================================== - csr0.field.Ac0Txop = 0; // QID_AC_BE - csr0.field.Ac1Txop = 0; // QID_AC_BK - RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); - if (pAd->CommonCfg.PhyMode == PHY_11B) - { - csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms - csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms - } - else - { - csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms - csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms - } - RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); - - CwminCsr.word = 0; - CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS; - CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS; - CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS; - CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS; - RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); - - CwmaxCsr.word = 0; - CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS; - CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS; - CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS; - CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS; - RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); - - RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222); - - NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM)); - } - else - { - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED); - //======================================================== - // MAC Register has a copy. - //======================================================== - // - // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27 - // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue. - // - //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this - - Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE]; - Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE]; - Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE]; - Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1; - - Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; - Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2; - Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK]; - Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1; - - Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10; - if(pAd->Antenna.field.TxPath == 1) - { - Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI] + 1; - Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI] + 1; - } - else - { - Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI]; - Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI]; - } - Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI] + 1; -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - -#ifdef INF_AMAZON_SE -#endif // INF_AMAZON_SE // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // Tuning for Wi-Fi WMM S06 - if (pAd->CommonCfg.bWiFiTest && - pEdcaParm->Aifsn[QID_AC_VI] == 10) - Ac2Cfg.field.Aifsn -= 1; - - // Tuning for TGn Wi-Fi 5.2.32 - // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta - if (STA_TGN_WIFI_ON(pAd) && - pEdcaParm->Aifsn[QID_AC_VI] == 10) - { - Ac0Cfg.field.Aifsn = 3; - Ac2Cfg.field.AcTxop = 5; - } - -#ifdef RT30xx - if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020) - { - // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta. - Ac2Cfg.field.Aifsn = 5; - } -#endif // RT30xx // - } -#endif // CONFIG_STA_SUPPORT // - - Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO]; - Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO]; - Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO]; - Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO]; - -//#ifdef WIFI_TEST - if (pAd->CommonCfg.bWiFiTest) - { - if (Ac3Cfg.field.AcTxop == 102) - { - Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10; - Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */ - Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; - Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; - Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI]; - } /* End of if */ - } -//#endif // WIFI_TEST // - - RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); - RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); - RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); - RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); - - - //======================================================== - // DMA Register has a copy too. - //======================================================== - csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop; - csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop; - RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); - - csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop; - csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop; - RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); - - CwminCsr.word = 0; - CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE]; - CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK]; - CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI]; -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test -#endif // CONFIG_STA_SUPPORT // - RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); - - CwmaxCsr.word = 0; - CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE]; - CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK]; - CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI]; - CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO]; - RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); - - AifsnCsr.word = 0; - AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE]; - AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK]; - AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI]; -#ifdef INF_AMAZON_SE -#endif // INF_AMAZON_SE // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // Tuning for Wi-Fi WMM S06 - if (pAd->CommonCfg.bWiFiTest && - pEdcaParm->Aifsn[QID_AC_VI] == 10) - AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4; - - // Tuning for TGn Wi-Fi 5.2.32 - // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta - if (STA_TGN_WIFI_ON(pAd) && - pEdcaParm->Aifsn[QID_AC_VI] == 10) - { - AifsnCsr.field.Aifsn0 = 3; - AifsnCsr.field.Aifsn2 = 7; - } - - if (INFRA_ON(pAd)) - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE); - } -#endif // CONFIG_STA_SUPPORT // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test -#ifdef RT30xx - // TODO: Shiang, this modification also suitable for RT3052/RT3050 ??? - if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020) - { - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04. - } -#endif // RT30xx // - } -#endif // CONFIG_STA_SUPPORT // - RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word); - - NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM)); - if (!ADHOC_ON(pAd)) - { - DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount)); - DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n", - pEdcaParm->Aifsn[0], - pEdcaParm->Cwmin[0], - pEdcaParm->Cwmax[0], - pEdcaParm->Txop[0]<<5, - pEdcaParm->bACM[0])); - DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n", - pEdcaParm->Aifsn[1], - pEdcaParm->Cwmin[1], - pEdcaParm->Cwmax[1], - pEdcaParm->Txop[1]<<5, - pEdcaParm->bACM[1])); - DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n", - pEdcaParm->Aifsn[2], - pEdcaParm->Cwmin[2], - pEdcaParm->Cwmax[2], - pEdcaParm->Txop[2]<<5, - pEdcaParm->bACM[2])); - DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n", - pEdcaParm->Aifsn[3], - pEdcaParm->Cwmin[3], - pEdcaParm->Cwmax[3], - pEdcaParm->Txop[3]<<5, - pEdcaParm->bACM[3])); - } - } - -} - -/* - ========================================================================== - Description: - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AsicSetSlotTime( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bUseShortSlotTime) -{ - ULONG SlotTime; - UINT32 RegValue = 0; - -#ifdef CONFIG_STA_SUPPORT - if (pAd->CommonCfg.Channel > 14) - bUseShortSlotTime = TRUE; -#endif // CONFIG_STA_SUPPORT // - - if (bUseShortSlotTime && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED)) - return; - else if ((!bUseShortSlotTime) && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED))) - return; - - if (bUseShortSlotTime) - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); - else - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); - - SlotTime = (bUseShortSlotTime)? 9 : 20; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // force using short SLOT time for FAE to demo performance when TxBurst is ON - if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))) -#ifdef DOT11_N_SUPPORT - || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE)) -#endif // DOT11_N_SUPPORT // - ) - { - // In this case, we will think it is doing Wi-Fi test - // And we will not set to short slot when bEnableTxBurst is TRUE. - } - else if (pAd->CommonCfg.bEnableTxBurst) - { - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); - SlotTime = 9; - } - } -#endif // CONFIG_STA_SUPPORT // - - // - // For some reasons, always set it to short slot time. - // - // ToDo: Should consider capability with 11B - // -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (pAd->StaCfg.BssType == BSS_ADHOC) - { - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); - SlotTime = 20; - } - } -#endif // CONFIG_STA_SUPPORT // - - RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); - RegValue = RegValue & 0xFFFFFF00; - - RegValue |= SlotTime; - - RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue); -} - -/* - ======================================================================== - Description: - Add Shared key information into ASIC. - Update shared key, TxMic and RxMic to Asic Shared key table - Update its cipherAlg to Asic Shared key Mode. - - Return: - ======================================================================== -*/ -VOID AsicAddSharedKeyEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIndex, - IN UCHAR KeyIdx, - IN UCHAR CipherAlg, - IN PUCHAR pKey, - IN PUCHAR pTxMic, - IN PUCHAR pRxMic) -{ - ULONG offset; //, csr0; - SHAREDKEY_MODE_STRUC csr1; -#ifdef RTMP_MAC_PCI - INT i; -#endif // RTMP_MAC_PCI // - - DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx)); -//============================================================================================ - - DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx)); - DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15])); - if (pRxMic) - { - DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); - } - if (pTxMic) - { - DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); - } -//============================================================================================ - // - // fill key material - key + TX MIC + RX MIC - // -#ifdef RTMP_MAC_PCI - offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE; - for (i=0; iKey; -// ULONG KeyLen = pCipherKey->KeyLen; - PUCHAR pTxMic = pCipherKey->TxMic; - PUCHAR pRxMic = pCipherKey->RxMic; - PUCHAR pTxtsc = pCipherKey->TxTsc; - UCHAR CipherAlg = pCipherKey->CipherAlg; - SHAREDKEY_MODE_STRUC csr1; -#ifdef RTMP_MAC_PCI - UCHAR i; -#endif // RTMP_MAC_PCI // - -// ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY); - - DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n")); - // - // 1.) decide key table offset - // - if (bUsePairewiseKeyTable) - offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); - else - offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE; - - // - // 2.) Set Key to Asic - // - //for (i = 0; i < KeyLen; i++) -#ifdef RTMP_MAC_PCI - for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++) - { - RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); - } - offset += MAX_LEN_OF_PEER_KEY; - - // - // 3.) Set MIC key if available - // - if (pTxMic) - { - for (i = 0; i < 8; i++) - { - RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); - } - } - offset += LEN_TKIP_TXMICK; - - if (pRxMic) - { - for (i = 0; i < 8; i++) - { - RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); - } - } -#endif // RTMP_MAC_PCI // - - - // - // 4.) Modify IV/EIV if needs - // This will force Asic to use this key ID by setting IV. - // - if (bTxKey) - { -#ifdef RTMP_MAC_PCI - offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); - // - // Write IV - // - RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]); - RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f)); - RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]); - - IV4 = (KeyIdx << 6); - if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES)) - IV4 |= 0x20; // turn on extension bit means EIV existence - - RTMP_IO_WRITE8(pAd, offset + 3, IV4); - - // - // Write EIV - // - offset += 4; - for (i = 0; i < 4; i++) - { - RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]); - } -#endif // RTMP_MAC_PCI // - - AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable); - } - - if (!bUsePairewiseKeyTable) - { - // - // Only update the shared key security mode - // - RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word); - if ((BssIndex % 2) == 0) - { - if (KeyIdx == 0) - csr1.field.Bss0Key0CipherAlg = CipherAlg; - else if (KeyIdx == 1) - csr1.field.Bss0Key1CipherAlg = CipherAlg; - else if (KeyIdx == 2) - csr1.field.Bss0Key2CipherAlg = CipherAlg; - else - csr1.field.Bss0Key3CipherAlg = CipherAlg; - } - else - { - if (KeyIdx == 0) - csr1.field.Bss1Key0CipherAlg = CipherAlg; - else if (KeyIdx == 1) - csr1.field.Bss1Key1CipherAlg = CipherAlg; - else if (KeyIdx == 2) - csr1.field.Bss1Key2CipherAlg = CipherAlg; - else - csr1.field.Bss1Key3CipherAlg = CipherAlg; - } - RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word); - } - - DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n")); -} - - -/* - ======================================================================== - Description: - Add Pair-wise key material into ASIC. - Update pairwise key, TxMic and RxMic to Asic Pair-wise key table - - Return: - ======================================================================== -*/ -VOID AsicAddPairwiseKeyEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN UCHAR WCID, - IN CIPHER_KEY *pCipherKey) -{ - INT i; - ULONG offset; - PUCHAR pKey = pCipherKey->Key; - PUCHAR pTxMic = pCipherKey->TxMic; - PUCHAR pRxMic = pCipherKey->RxMic; -#ifdef DBG - UCHAR CipherAlg = pCipherKey->CipherAlg; -#endif // DBG // - - // EKEY - offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); -#ifdef RTMP_MAC_PCI - for (i=0; ichipOps.sendCommandToMcu) - pAd->chipOps.sendCommandToMcu(pAd, Command, Token, Arg0, Arg1); - - return TRUE; -} - - -VOID AsicSetRxAnt( - IN PRTMP_ADAPTER pAd, - IN UCHAR Ant) -{ -#ifdef RT33xx - RT33xxSetRxAnt(pAd, Ant); -#else -#ifdef RT30xx - /* RT3572 ATE need not to do this. */ - RT30xxSetRxAnt(pAd, Ant); -#endif // RT30xx // -#endif // RT33xx // -} - - -VOID AsicTurnOffRFClk( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel) -{ - if (pAd->chipOps.AsicRfTurnOff) - { - pAd->chipOps.AsicRfTurnOff(pAd); - } - else - { - // RF R2 bit 18 = 0 - UINT32 R1 = 0, R2 = 0, R3 = 0; - UCHAR index; - RTMP_RF_REGS *RFRegTable; - - RFRegTable = RF2850RegTable; - - switch (pAd->RfIcType) - { - case RFIC_2820: - case RFIC_2850: - case RFIC_2720: - case RFIC_2750: - - for (index = 0; index < NUM_OF_2850_CHNL; index++) - { - if (Channel == RFRegTable[index].Channel) - { - R1 = RFRegTable[index].R1 & 0xffffdfff; - R2 = RFRegTable[index].R2 & 0xfffbffff; - R3 = RFRegTable[index].R3 & 0xfff3ffff; - - RTMP_RF_IO_WRITE32(pAd, R1); - RTMP_RF_IO_WRITE32(pAd, R2); - - // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0. - // Set RF R2 bit18=0, R3 bit[18:19]=0 - //if (pAd->StaCfg.bRadio == FALSE) - if (1) - { - RTMP_RF_IO_WRITE32(pAd, R3); - - DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n", - Channel, pAd->RfIcType, R2, R3)); - } - else - DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n", - Channel, pAd->RfIcType, R2)); - break; - } - } - break; - - default: - break; - } - } -} - - -VOID AsicTurnOnRFClk( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel) -{ - // RF R2 bit 18 = 0 - UINT32 R1 = 0, R2 = 0, R3 = 0; - UCHAR index; - RTMP_RF_REGS *RFRegTable; - -#ifdef PCIE_PS_SUPPORT - // The RF programming sequence is difference between 3xxx and 2xxx - if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) - { - return; - } -#endif // PCIE_PS_SUPPORT // - - RFRegTable = RF2850RegTable; - - switch (pAd->RfIcType) - { - case RFIC_2820: - case RFIC_2850: - case RFIC_2720: - case RFIC_2750: - - for (index = 0; index < NUM_OF_2850_CHNL; index++) - { - if (Channel == RFRegTable[index].Channel) - { - R3 = pAd->LatchRfRegs.R3; - R3 &= 0xfff3ffff; - R3 |= 0x00080000; - RTMP_RF_IO_WRITE32(pAd, R3); - - R1 = RFRegTable[index].R1; - RTMP_RF_IO_WRITE32(pAd, R1); - - R2 = RFRegTable[index].R2; - if (pAd->Antenna.field.TxPath == 1) - { - R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; - } - - if (pAd->Antenna.field.RxPath == 2) - { - R2 |= 0x40; // write 1 to off Rxpath. - } - else if (pAd->Antenna.field.RxPath == 1) - { - R2 |= 0x20040; // write 1 to off RxPath - } - RTMP_RF_IO_WRITE32(pAd, R2); - - break; - } - } - break; - - default: - break; - } - - DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n", - Channel, - pAd->RfIcType, - R2)); -} diff --git a/drivers/staging/rt3090/common/cmm_data.c b/drivers/staging/rt3090/common/cmm_data.c deleted file mode 100644 index 634007163160a62d819a6a588f7b3a21a6c54f1d..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/cmm_data.c +++ /dev/null @@ -1,2763 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - cmm_data.c - - Abstract: - - Revision History: - Who When What - --------- ---------- ---------------------------------------------- - */ - -#include "../rt_config.h" - - -UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; -UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8}; -// Add Cisco Aironet SNAP heade for CCX2 support -UCHAR SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00}; -UCHAR CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02}; -UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e}; -UCHAR EAPOL[] = {0x88, 0x8e}; -UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */ - -UCHAR IPX[] = {0x81, 0x37}; -UCHAR APPLE_TALK[] = {0x80, 0xf3}; -UCHAR RateIdToPlcpSignal[12] = { - 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec - 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14 - 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14 - -UCHAR OfdmSignalToRateId[16] = { - RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 0, 1, 2, 3 respectively - RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 4, 5, 6, 7 respectively - RATE_48, RATE_24, RATE_12, RATE_6, // OFDM PLCP Signal = 8, 9, 10, 11 respectively - RATE_54, RATE_36, RATE_18, RATE_9, // OFDM PLCP Signal = 12, 13, 14, 15 respectively -}; - -UCHAR OfdmRateToRxwiMCS[12] = { - 0, 0, 0, 0, - 0, 1, 2, 3, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 - 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 -}; -UCHAR RxwiMCSToOfdmRate[12] = { - RATE_6, RATE_9, RATE_12, RATE_18, - RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 - 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 -}; - -char* MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"}; - -UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2}; -//UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1}; -UCHAR default_sta_aifsn[]={3,7,2,2}; - -UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO}; - - -/* - ======================================================================== - - Routine Description: - API for MLME to transmit management frame to AP (BSS Mode) - or station (IBSS Mode) - - Arguments: - pAd Pointer to our adapter - pData Pointer to the outgoing 802.11 frame - Length Size of outgoing management frame - - Return Value: - NDIS_STATUS_FAILURE - NDIS_STATUS_PENDING - NDIS_STATUS_SUCCESS - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -NDIS_STATUS MiniportMMRequest( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PUCHAR pData, - IN UINT Length) -{ - PNDIS_PACKET pPacket; - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - ULONG FreeNum; - UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN]; -#ifdef RTMP_MAC_PCI - unsigned long IrqFlags = 0; - UCHAR IrqState; -#endif // RTMP_MAC_PCI // - BOOLEAN bUseDataQ = FALSE; - int retryCnt = 0; - - ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); - - if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) - { - bUseDataQ = TRUE; - QueIdx &= (~MGMT_USE_QUEUE_FLAG); - } - -#ifdef RTMP_MAC_PCI - // 2860C use Tx Ring - IrqState = pAd->irq_disabled; - if (pAd->MACVersion == 0x28600100) - { - QueIdx = (bUseDataQ ==TRUE ? QueIdx : 3); - bUseDataQ = TRUE; - } - if (bUseDataQ && (!IrqState)) - RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); -#endif // RTMP_MAC_PCI // - - do - { - // Reset is in progress, stop immediately - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)|| - !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) - { - Status = NDIS_STATUS_FAILURE; - break; - } - - // Check Free priority queue - // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. -#ifdef RTMP_MAC_PCI - if (bUseDataQ) - { - retryCnt = MAX_DATAMM_RETRY; - // free Tx(QueIdx) resources - RTMPFreeTXDUponTxDmaDone(pAd, QueIdx); - FreeNum = GET_TXRING_FREENO(pAd, QueIdx); - } - else -#endif // RTMP_MAC_PCI // - { - FreeNum = GET_MGMTRING_FREENO(pAd); - } - - if ((FreeNum > 0)) - { - // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 - NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE)); - Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); - break; - } - - //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; - //pAd->CommonCfg.MlmeRate = RATE_2; - - -#ifdef RTMP_MAC_PCI - if (bUseDataQ) - { - Status = MlmeDataHardTransmit(pAd, QueIdx, pPacket); - retryCnt--; - } - else -#endif // RTMP_MAC_PCI // - Status = MlmeHardTransmit(pAd, QueIdx, pPacket); - if (Status == NDIS_STATUS_SUCCESS) - retryCnt = 0; - else - RTMPFreeNdisPacket(pAd, pPacket); - } - else - { - pAd->RalinkCounters.MgmtRingFullCount++; -#ifdef RTMP_MAC_PCI - if (bUseDataQ) - { - retryCnt--; - DBGPRINT(RT_DEBUG_TRACE, ("retryCnt %d\n", retryCnt)); - if (retryCnt == 0) - { - DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n", - QueIdx, pAd->RalinkCounters.MgmtRingFullCount)); - } - } -#endif // RTMP_MAC_PCI // - DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n", - QueIdx, pAd->RalinkCounters.MgmtRingFullCount)); - - - - } - } while (retryCnt > 0); - - -#ifdef RTMP_MAC_PCI - if (bUseDataQ && (!IrqState)) - RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); -#endif // RTMP_MAC_PCI // - - return Status; -} - - - - -/* - ======================================================================== - - Routine Description: - Copy frame from waiting queue into relative ring buffer and set - appropriate ASIC register to kick hardware transmit function - - Arguments: - pAd Pointer to our adapter - pBuffer Pointer to memory of outgoing frame - Length Size of outgoing management frame - - Return Value: - NDIS_STATUS_FAILURE - NDIS_STATUS_PENDING - NDIS_STATUS_SUCCESS - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -NDIS_STATUS MlmeHardTransmit( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket) -{ - PACKET_INFO PacketInfo; - PUCHAR pSrcBufVA; - UINT SrcBufLen; - PHEADER_802_11 pHeader_802_11; - - if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) -#ifdef CARRIER_DETECTION_SUPPORT -#endif // CARRIER_DETECTION_SUPPORT // - ) - { - return NDIS_STATUS_FAILURE; - } - - RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); - if (pSrcBufVA == NULL) - return NDIS_STATUS_FAILURE; - - pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); - - -#ifdef RTMP_MAC_PCI - if ( pAd->MACVersion == 0x28600100 ) - return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket); - else -#endif // RTMP_MAC_PCI // - return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket); - -} - - -NDIS_STATUS MlmeHardTransmitMgmtRing( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket) -{ - PACKET_INFO PacketInfo; - PUCHAR pSrcBufVA; - UINT SrcBufLen; - PHEADER_802_11 pHeader_802_11; - BOOLEAN bAckRequired, bInsertTimestamp; - UCHAR MlmeRate; - PTXWI_STRUC pFirstTxWI; - MAC_TABLE_ENTRY *pMacEntry = NULL; - UCHAR PID; - - RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); - - // Make sure MGMT ring resource won't be used by other threads - RTMP_SEM_LOCK(&pAd->MgmtRingLock); - if (pSrcBufVA == NULL) - { - // The buffer shouldn't be NULL - RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); - return NDIS_STATUS_FAILURE; - } - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // outgoing frame always wakeup PHY to prevent frame lost - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - AsicForceWakeup(pAd, TRUE); - } -#endif // CONFIG_STA_SUPPORT // - - pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE); - pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE); - - if (pHeader_802_11->Addr1[0] & 0x01) - { - MlmeRate = pAd->CommonCfg.BasicMlmeRate; - } - else - { - MlmeRate = pAd->CommonCfg.MlmeRate; - } - - // Verify Mlme rate for a / g bands. - if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band - MlmeRate = RATE_6; - - if ((pHeader_802_11->FC.Type == BTYPE_DATA) && - (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) - { - pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); - } - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode. - if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED -#ifdef DOT11_N_SUPPORT - || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED -#endif // DOT11_N_SUPPORT // - ) - { - if (pAd->LatchRfRegs.Channel > 14) - pAd->CommonCfg.MlmeTransmit.field.MODE = 1; - else - pAd->CommonCfg.MlmeTransmit.field.MODE = 0; - } - } -#endif // CONFIG_STA_SUPPORT // - - // - // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) - // Snice it's been set to 0 while on MgtMacHeaderInit - // By the way this will cause frame to be send on PWR_SAVE failed. - // - pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; // (pAd->StaCfg.Psm == PWR_SAVE); - -#ifdef CONFIG_STA_SUPPORT - // - // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame - // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD -// if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL)) - { - if ((pHeader_802_11->FC.SubType == SUBTYPE_ACTION) || - ((pHeader_802_11->FC.Type == BTYPE_DATA) && - ((pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL) || - (pHeader_802_11->FC.SubType == SUBTYPE_NULL_FUNC)))) - { - if (pAd->StaCfg.Psm == PWR_SAVE) - pHeader_802_11->FC.PwrMgmt = PWR_SAVE; - else - pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave; - } - } -#endif // CONFIG_STA_SUPPORT // - - - - - - bInsertTimestamp = FALSE; - if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL - { -#ifdef CONFIG_STA_SUPPORT - //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue. - if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) - { - pHeader_802_11->FC.PwrMgmt = PWR_SAVE; - } -#endif // CONFIG_STA_SUPPORT // - bAckRequired = FALSE; - } - else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame) - { - //pAd->Sequence++; - //pHeader_802_11->Sequence = pAd->Sequence; - - if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST - { - bAckRequired = FALSE; - pHeader_802_11->Duration = 0; - } - else - { - bAckRequired = TRUE; - pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14); - if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) && (pHeader_802_11->FC.Type == BTYPE_MGMT)) - { - bInsertTimestamp = TRUE; - bAckRequired = FALSE; // Disable ACK to prevent retry 0x1f for Probe Response - } - else if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) && (pHeader_802_11->FC.Type == BTYPE_MGMT)) - { - bAckRequired = FALSE; // Disable ACK to prevent retry 0x1f for Probe Request - } - } - } - - pHeader_802_11->Sequence = pAd->Sequence++; - if (pAd->Sequence >0xfff) - pAd->Sequence = 0; - - // Before radar detection done, mgmt frame can not be sent but probe req - // Because we need to use probe req to trigger driver to send probe req in passive scan - if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) - && (pAd->CommonCfg.bIEEE80211H == 1) - && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) - { - DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n")); -// if (!IrqState) - RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); - return (NDIS_STATUS_FAILURE); - } - -#ifdef RT_BIG_ENDIAN - RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE); -#endif - - // - // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET - // should always has only one physical buffer, and the whole frame size equals - // to the first scatter buffer size - // - - // Initialize TX Descriptor - // For inter-frame gap, the number is for this frame and next frame - // For MLME rate, we will fix as 2Mb to match other vendor's implement -// pAd->CommonCfg.MlmeTransmit.field.MODE = 1; - -// management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. - PID = PID_MGMT; - - - if (pMacEntry == NULL) - { - RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, - 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); - } - else - { - /* dont use low rate to send QoS Null data frame */ - RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, - bInsertTimestamp, FALSE, bAckRequired, FALSE, - 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), - pMacEntry->MaxHTPhyMode.field.MCS, 0, - (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS, - IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); - } - -#ifdef RT_BIG_ENDIAN - RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI); -#endif - - // Now do hardware-depened kick out. - HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen); - - // Make sure to release MGMT ring resource -// if (!IrqState) - RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); - return NDIS_STATUS_SUCCESS; -} - - -/******************************************************************************** - - New DeQueue Procedures. - - ********************************************************************************/ - -#define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \ - do{ \ - if (bIntContext == FALSE) \ - RTMP_IRQ_LOCK((lock), IrqFlags); \ - }while(0) - -#define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \ - do{ \ - if (bIntContext == FALSE) \ - RTMP_IRQ_UNLOCK((lock), IrqFlags); \ - }while(0) - - - - -/* - ======================================================================== - Tx Path design algorithm: - Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal), - Specific Packet Type. Following show the classification rule and policy for each kinds of packets. - Classification Rule=> - Multicast: (*addr1 & 0x01) == 0x01 - Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc. - 11N Rate : If peer support HT - (1).AMPDU -- If TXBA is negotiated. - (2).AMSDU -- If AMSDU is capable for both peer and ourself. - *). AMSDU can embedded in a AMPDU, but now we didn't support it. - (3).Normal -- Other packets which send as 11n rate. - - B/G Rate : If peer is b/g only. - (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6 - (2).Normal -- Other packets which send as b/g rate. - Fragment: - The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment. - - Classified Packet Handle Rule=> - Multicast: - No ACK, //pTxBlk->bAckRequired = FALSE; - No WMM, //pTxBlk->bWMM = FALSE; - No piggyback, //pTxBlk->bPiggyBack = FALSE; - Force LowRate, //pTxBlk->bForceLowRate = TRUE; - Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use - the same policy to handle it. - Force LowRate, //pTxBlk->bForceLowRate = TRUE; - - 11N Rate : - No piggyback, //pTxBlk->bPiggyBack = FALSE; - - (1).AMSDU - pTxBlk->bWMM = TRUE; - (2).AMPDU - pTxBlk->bWMM = TRUE; - (3).Normal - - B/G Rate : - (1).ARALINK - - (2).Normal - ======================================================================== -*/ -static UCHAR TxPktClassification( - IN RTMP_ADAPTER *pAd, - IN PNDIS_PACKET pPacket) -{ - UCHAR TxFrameType = TX_UNKOWN_FRAME; - UCHAR Wcid; - MAC_TABLE_ENTRY *pMacEntry = NULL; -#ifdef DOT11_N_SUPPORT - BOOLEAN bHTRate = FALSE; -#endif // DOT11_N_SUPPORT // - - Wcid = RTMP_GET_PACKET_WCID(pPacket); - if (Wcid == MCAST_WCID) - { // Handle for RA is Broadcast/Multicast Address. - return TX_MCAST_FRAME; - } - - // Handle for unicast packets - pMacEntry = &pAd->MacTab.Content[Wcid]; - if (RTMP_GET_PACKET_LOWRATE(pPacket)) - { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame - TxFrameType = TX_LEGACY_FRAME; - } -#ifdef DOT11_N_SUPPORT - else if (IS_HT_RATE(pMacEntry)) - { // it's a 11n capable packet - - // Depends on HTPhyMode to check if the peer support the HTRate transmission. - // Currently didn't support A-MSDU embedded in A-MPDU - bHTRate = TRUE; - if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE)) - TxFrameType = TX_LEGACY_FRAME; -#ifdef UAPSD_AP_SUPPORT - else if (RTMP_GET_PACKET_EOSP(pPacket)) - TxFrameType = TX_LEGACY_FRAME; -#endif // UAPSD_AP_SUPPORT // - else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0) - return TX_AMPDU_FRAME; - else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED)) - return TX_AMSDU_FRAME; - else - TxFrameType = TX_LEGACY_FRAME; - } -#endif // DOT11_N_SUPPORT // - else - { // it's a legacy b/g packet. - if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) && - (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) && - (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) - { // if peer support Ralink Aggregation, we use it. - TxFrameType = TX_RALINK_FRAME; - } - else - { - TxFrameType = TX_LEGACY_FRAME; - } - } - - // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU. - if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME)) - TxFrameType = TX_FRAG_FRAME; - - return TxFrameType; -} - - -BOOLEAN RTMP_FillTxBlkInfo( - IN RTMP_ADAPTER *pAd, - IN TX_BLK *pTxBlk) -{ - PACKET_INFO PacketInfo; - PNDIS_PACKET pPacket; - PMAC_TABLE_ENTRY pMacEntry = NULL; - - pPacket = pTxBlk->pPacket; - RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); - - pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket); - pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket); - pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket); - pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap - - if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket)) - TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame); - else - TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame); - - // Default to clear this flag - TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS); - - - if (pTxBlk->Wcid == MCAST_WCID) - { - pTxBlk->pMacEntry = NULL; - { -#ifdef MCAST_RATE_SPECIFIC - PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket); - if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff)) - pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode; - else -#endif // MCAST_RATE_SPECIFIC // - pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; - } - - TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode. - //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate); - TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag); - TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); - if (RTMP_GET_PACKET_MOREDATA(pPacket)) - { - TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); - } - - } - else - { - pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid]; - pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode; - - pMacEntry = pTxBlk->pMacEntry; - - - // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK. - if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK) - TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); - else - TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired); - -#ifdef CONFIG_STA_SUPPORT - if ((pAd->OpMode == OPMODE_STA) && - (ADHOC_ON(pAd)) && - (RX_FILTER_TEST_FLAG(pAd, fRX_FILTER_ACCEPT_PROMISCUOUS))) - { - if(pAd->CommonCfg.PSPXlink) - TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); - } -#endif // CONFIG_STA_SUPPORT // - - { - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - - // If support WMM, enable it. - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && - CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) - TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM); - -// if (pAd->StaCfg.bAutoTxRateSwitch) -// TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch); - } -#endif // CONFIG_STA_SUPPORT // - } - - if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) - { - if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) || - ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1))) - { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate. - pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; -#ifdef DOT11_N_SUPPORT - // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it??? - if (IS_HT_STA(pTxBlk->pMacEntry) && - (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) && - ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))) - { - TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); - TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS); - } -#endif // DOT11_N_SUPPORT // - } - -#ifdef DOT11_N_SUPPORT - if ( (IS_HT_RATE(pMacEntry) == FALSE) && - (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE))) - { // Currently piggy-back only support when peer is operate in b/g mode. - TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack); - } -#endif // DOT11_N_SUPPORT // - - if (RTMP_GET_PACKET_MOREDATA(pPacket)) - { - TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); - } -#ifdef UAPSD_AP_SUPPORT - if (RTMP_GET_PACKET_EOSP(pPacket)) - { - TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP); - } -#endif // UAPSD_AP_SUPPORT // - } - else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) - { - TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag); - } - - pMacEntry->DebugTxCount++; - } - - return TRUE; -} - - -BOOLEAN CanDoAggregateTransmit( - IN RTMP_ADAPTER *pAd, - IN NDIS_PACKET *pPacket, - IN TX_BLK *pTxBlk) -{ - - //DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType)); - - if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID) - return FALSE; - - if (RTMP_GET_PACKET_DHCP(pPacket) || - RTMP_GET_PACKET_EAPOL(pPacket) || - RTMP_GET_PACKET_WAI(pPacket)) - return FALSE; - - if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) && - ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100))) - { // For AMSDU, allow the packets with total length < max-amsdu size - return FALSE; - } - - if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && - (pTxBlk->TxPacketList.Number == 2)) - { // For RALINK-Aggregation, allow two frames in one batch. - return FALSE; - } - -#ifdef CONFIG_STA_SUPPORT - if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP - return TRUE; - else -#endif // CONFIG_STA_SUPPORT // - return FALSE; - -} - - -/* - ======================================================================== - - Routine Description: - To do the enqueue operation and extract the first item of waiting - list. If a number of available shared memory segments could meet - the request of extracted item, the extracted item will be fragmented - into shared memory segments. - - Arguments: - pAd Pointer to our adapter - pQueue Pointer to Waiting Queue - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPDeQueuePacket( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bIntContext, - IN UCHAR QIdx, /* BulkOutPipeId */ - IN UCHAR Max_Tx_Packets) -{ - PQUEUE_ENTRY pEntry = NULL; - PNDIS_PACKET pPacket; - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - UCHAR Count=0; - PQUEUE_HEADER pQueue; - ULONG FreeNumber[NUM_OF_TX_RING]; - UCHAR QueIdx, sQIdx, eQIdx; - unsigned long IrqFlags = 0; - BOOLEAN hasTxDesc = FALSE; - TX_BLK TxBlk; - TX_BLK *pTxBlk; - -#ifdef DBG_DIAGNOSE - BOOLEAN firstRound; - RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct; -#endif - - - if (QIdx == NUM_OF_TX_RING) - { - sQIdx = 0; - eQIdx = 3; // 4 ACs, start from 0. - } - else - { - sQIdx = eQIdx = QIdx; - } - - for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++) - { - Count=0; - - RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags); - -#ifdef DBG_DIAGNOSE - firstRound = ((QueIdx == 0) ? TRUE : FALSE); -#endif // DBG_DIAGNOSE // - - while (1) - { - if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS | - fRTMP_ADAPTER_RADIO_OFF | - fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_NIC_NOT_EXIST)))) - { - RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); - return; - } - - if (Count >= Max_Tx_Packets) - break; - - DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags); - if (&pAd->TxSwQueue[QueIdx] == NULL) - { -#ifdef DBG_DIAGNOSE - if (firstRound == TRUE) - pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++; -#endif // DBG_DIAGNOSE // - DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); - break; - } - -#ifdef RTMP_MAC_PCI - FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); - -#ifdef DBG_DIAGNOSE - if (firstRound == TRUE) - { - UCHAR txDescNumLevel, txSwQNumLevel; - - txDescNumLevel = (TX_RING_SIZE - FreeNumber[QueIdx]); // Number of occupied hw desc. - txDescNumLevel = ((txDescNumLevel <=15) ? txDescNumLevel : 15); - pDiagStruct->TxDescCnt[pDiagStruct->ArrayCurIdx][txDescNumLevel]++; - - txSwQNumLevel = ((pAd->TxSwQueue[QueIdx].Number <=7) ? pAd->TxSwQueue[QueIdx].Number : 8); - pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][txSwQNumLevel]++; - - firstRound = FALSE; - } -#endif // DBG_DIAGNOSE // - - if (FreeNumber[QueIdx] <= 5) - { - // free Tx(QueIdx) resources - RTMPFreeTXDUponTxDmaDone(pAd, QueIdx); - FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); - } -#endif // RTMP_MAC_PCI // - - // probe the Queue Head - pQueue = &pAd->TxSwQueue[QueIdx]; - if ((pEntry = pQueue->Head) == NULL) - { - DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); - break; - } - - pTxBlk = &TxBlk; - NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK)); - //InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it. - pTxBlk->QueIdx = QueIdx; - - pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); - - - // Early check to make sure we have enoguh Tx Resource. - hasTxDesc = RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); - if (!hasTxDesc) - { - pAd->PrivateInfo.TxRingFullCnt++; - - DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); - - break; - } - - pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket); - pEntry = RemoveHeadQueue(pQueue); - pTxBlk->TotalFrameNum++; - pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary - pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); - pTxBlk->pPacket = pPacket; - InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); - - if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME) - { - // Enhance SW Aggregation Mechanism - if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType)) - { - InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); - DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); - break; - } - - do{ - if((pEntry = pQueue->Head) == NULL) - break; - - // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. - pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); - FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); - hasTxDesc = RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); - if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE)) - break; - - //Remove the packet from the TxSwQueue and insert into pTxBlk - pEntry = RemoveHeadQueue(pQueue); - ASSERT(pEntry); - pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); - pTxBlk->TotalFrameNum++; - pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary - pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); - InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); - }while(1); - - if (pTxBlk->TxPacketList.Number == 1) - pTxBlk->TxFrameType = TX_LEGACY_FRAME; - } - - - Count += pTxBlk->TxPacketList.Number; - - - // Do HardTransmit now. -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - Status = STAHardTransmit(pAd, pTxBlk, QueIdx); -#endif // CONFIG_STA_SUPPORT // - -#ifdef RTMP_MAC_PCI - DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); - // static rate also need NICUpdateFifoStaCounters() function. - //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) - NICUpdateFifoStaCounters(pAd); -#endif // RTMP_MAC_PCI // - - } - - RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); - - -#ifdef BLOCK_NET_IF - if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE) - && (pAd->TxSwQueue[QueIdx].Number < 1)) - { - releaseNetIf(&pAd->blockQueueTab[QueIdx]); - } -#endif // BLOCK_NET_IF // - - } - -} - - -/* - ======================================================================== - - Routine Description: - Calculates the duration which is required to transmit out frames - with given size and specified rate. - - Arguments: - pAd Pointer to our adapter - Rate Transmit rate - Size Frame size in units of byte - - Return Value: - Duration number in units of usec - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -USHORT RTMPCalcDuration( - IN PRTMP_ADAPTER pAd, - IN UCHAR Rate, - IN ULONG Size) -{ - ULONG Duration = 0; - - if (Rate < RATE_FIRST_OFDM_RATE) // CCK - { - if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)) - Duration = 96; // 72+24 preamble+plcp - else - Duration = 192; // 144+48 preamble+plcp - - Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]); - if ((Size << 4) % RateIdTo500Kbps[Rate]) - Duration ++; - } - else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates - { - Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension - Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]); - if ((11 + Size * 4) % RateIdTo500Kbps[Rate]) - Duration += 4; - } - else //mimo rate - { - Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension - } - - return (USHORT)Duration; -} - - -/* - ======================================================================== - - Routine Description: - Calculates the duration which is required to transmit out frames - with given size and specified rate. - - Arguments: - pTxWI Pointer to head of each MPDU to HW. - Ack Setting for Ack requirement bit - Fragment Setting for Fragment bit - RetryMode Setting for retry mode - Ifs Setting for IFS gap - Rate Setting for transmit rate - Service Setting for service - Length Frame length - TxPreamble Short or Long preamble when using CCK rates - QueIdx - 0-3, according to 802.11e/d4.4 June/2003 - - Return Value: - None - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - See also : BASmartHardTransmit() !!! - - ======================================================================== -*/ -VOID RTMPWriteTxWI( - IN PRTMP_ADAPTER pAd, - IN PTXWI_STRUC pOutTxWI, - IN BOOLEAN FRAG, - IN BOOLEAN CFACK, - IN BOOLEAN InsTimestamp, - IN BOOLEAN AMPDU, - IN BOOLEAN Ack, - IN BOOLEAN NSeq, // HW new a sequence. - IN UCHAR BASize, - IN UCHAR WCID, - IN ULONG Length, - IN UCHAR PID, - IN UCHAR TID, - IN UCHAR TxRate, - IN UCHAR Txopmode, - IN BOOLEAN CfAck, - IN HTTRANSMIT_SETTING *pTransmit) -{ - PMAC_TABLE_ENTRY pMac = NULL; - TXWI_STRUC TxWI; - PTXWI_STRUC pTxWI; - - if (WCID < MAX_LEN_OF_MAC_TABLE) - pMac = &pAd->MacTab.Content[WCID]; - - // - // Always use Long preamble before verifiation short preamble functionality works well. - // Todo: remove the following line if short preamble functionality works - // - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); - NdisZeroMemory(&TxWI, TXWI_SIZE); - pTxWI = &TxWI; - - pTxWI->FRAG= FRAG; - - pTxWI->CFACK = CFACK; - pTxWI->TS= InsTimestamp; - pTxWI->AMPDU = AMPDU; - pTxWI->ACK = Ack; - pTxWI->txop= Txopmode; - - pTxWI->NSEQ = NSeq; - // John tune the performace with Intel Client in 20 MHz performance -#ifdef DOT11_N_SUPPORT - BASize = pAd->CommonCfg.TxBASize; - if (pAd->MACVersion == 0x28720200) - { - if( BASize >13 ) - BASize =13; - } - else - { - if( BASize >7 ) - BASize =7; - } - pTxWI->BAWinSize = BASize; - pTxWI->ShortGI = pTransmit->field.ShortGI; - pTxWI->STBC = pTransmit->field.STBC; -#endif // DOT11_N_SUPPORT // - - pTxWI->WirelessCliID = WCID; - pTxWI->MPDUtotalByteCount = Length; - pTxWI->PacketId = PID; - - // If CCK or OFDM, BW must be 20 - pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); -#ifdef DOT11_N_SUPPORT -#ifdef DOT11N_DRAFT3 - if (pTxWI->BW) - pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // - - pTxWI->MCS = pTransmit->field.MCS; - pTxWI->PHYMODE = pTransmit->field.MODE; - pTxWI->CFACK = CfAck; - -#ifdef DOT11_N_SUPPORT - if (pMac) - { - if (pAd->CommonCfg.bMIMOPSEnable) - { - if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) - { - // Dynamic MIMO Power Save Mode - pTxWI->MIMOps = 1; - } - else if (pMac->MmpsMode == MMPS_STATIC) - { - // Static MIMO Power Save Mode - if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) - { - pTxWI->MCS = 7; - pTxWI->MIMOps = 0; - } - } - } - //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; - if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled)) - { - pTxWI->MpduDensity = 7; - } - else - { - pTxWI->MpduDensity = pMac->MpduDensity; - } - } -#endif // DOT11_N_SUPPORT // - - pTxWI->PacketId = pTxWI->MCS; - NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC)); -} - - -VOID RTMPWriteTxWI_Data( - IN PRTMP_ADAPTER pAd, - IN OUT PTXWI_STRUC pTxWI, - IN TX_BLK *pTxBlk) -{ - HTTRANSMIT_SETTING *pTransmit; - PMAC_TABLE_ENTRY pMacEntry; -#ifdef DOT11_N_SUPPORT - UCHAR BASize; -#endif // DOT11_N_SUPPORT // - - - ASSERT(pTxWI); - - pTransmit = pTxBlk->pTransmit; - pMacEntry = pTxBlk->pMacEntry; - - - // - // Always use Long preamble before verifiation short preamble functionality works well. - // Todo: remove the following line if short preamble functionality works - // - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); - NdisZeroMemory(pTxWI, TXWI_SIZE); - - pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); - pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); - pTxWI->txop = pTxBlk->FrameGap; - -#ifdef CONFIG_STA_SUPPORT -#ifdef QOS_DLS_SUPPORT - if (pMacEntry && - (pAd->StaCfg.BssType == BSS_INFRA) && - (pMacEntry->ValidAsDls == TRUE)) - pTxWI->WirelessCliID = BSSID_WCID; - else -#endif // QOS_DLS_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - pTxWI->WirelessCliID = pTxBlk->Wcid; - - pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; - pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); - - // If CCK or OFDM, BW must be 20 - pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); -#ifdef DOT11_N_SUPPORT -#ifdef DOT11N_DRAFT3 - if (pTxWI->BW) - pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); -#endif // DOT11N_DRAFT3 // - pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE); - - // John tune the performace with Intel Client in 20 MHz performance - BASize = pAd->CommonCfg.TxBASize; - if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) - { - UCHAR RABAOriIdx = 0; //The RA's BA Originator table index. - - RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; - BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize; - } - - - pTxWI->TxBF = pTransmit->field.TxBF; - pTxWI->BAWinSize = BASize; - pTxWI->ShortGI = pTransmit->field.ShortGI; - pTxWI->STBC = pTransmit->field.STBC; -#endif // DOT11_N_SUPPORT // - - pTxWI->MCS = pTransmit->field.MCS; - pTxWI->PHYMODE = pTransmit->field.MODE; - - -#ifdef DOT11_N_SUPPORT - if (pMacEntry) - { - if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) - { - // Dynamic MIMO Power Save Mode - pTxWI->MIMOps = 1; - } - else if (pMacEntry->MmpsMode == MMPS_STATIC) - { - // Static MIMO Power Save Mode - if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) - { - pTxWI->MCS = 7; - pTxWI->MIMOps = 0; - } - } - - if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) - { - pTxWI->MpduDensity = 7; - } - else - { - pTxWI->MpduDensity = pMacEntry->MpduDensity; - } - } -#endif // DOT11_N_SUPPORT // - -#ifdef DBG_DIAGNOSE - if (pTxBlk->QueIdx== 0) - { - pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++; - pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++; - } -#endif // DBG_DIAGNOSE // - - // for rate adapation - pTxWI->PacketId = pTxWI->MCS; -#ifdef INF_AMAZON_SE -/*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */ - if( RTMP_GET_PACKET_NOBULKOUT(pTxBlk->pPacket)) - { - if(pTxWI->PHYMODE == MODE_CCK) - { - pTxWI->PacketId = 6; - } - } -#endif // INF_AMAZON_SE // -} - - -VOID RTMPWriteTxWI_Cache( - IN PRTMP_ADAPTER pAd, - IN OUT PTXWI_STRUC pTxWI, - IN TX_BLK *pTxBlk) -{ - PHTTRANSMIT_SETTING /*pTxHTPhyMode,*/ pTransmit; - PMAC_TABLE_ENTRY pMacEntry; - - // - // update TXWI - // - pMacEntry = pTxBlk->pMacEntry; - pTransmit = pTxBlk->pTransmit; - - //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) - //if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry)) - //if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch)) - if (pMacEntry->bAutoTxRateSwitch) - { - pTxWI->txop = IFS_HTTXOP; - - // If CCK or OFDM, BW must be 20 - pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); - pTxWI->ShortGI = pTransmit->field.ShortGI; - pTxWI->STBC = pTransmit->field.STBC; - - pTxWI->MCS = pTransmit->field.MCS; - pTxWI->PHYMODE = pTransmit->field.MODE; - - // set PID for TxRateSwitching - pTxWI->PacketId = pTransmit->field.MCS; - } - -#ifdef DOT11_N_SUPPORT - pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE); - pTxWI->MIMOps = 0; - -#ifdef DOT11N_DRAFT3 - if (pTxWI->BW) - pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); -#endif // DOT11N_DRAFT3 // - - if (pAd->CommonCfg.bMIMOPSEnable) - { - // MIMO Power Save Mode - if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) - { - // Dynamic MIMO Power Save Mode - pTxWI->MIMOps = 1; - } - else if (pMacEntry->MmpsMode == MMPS_STATIC) - { - // Static MIMO Power Save Mode - if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7)) - { - pTxWI->MCS = 7; - pTxWI->MIMOps = 0; - } - } - } -#endif // DOT11_N_SUPPORT // - -#ifdef DBG_DIAGNOSE - if (pTxBlk->QueIdx== 0) - { - pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++; - pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++; - } -#endif // DBG_DIAGNOSE // - - pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; - -} - - -// should be called only when - -// 1. MEADIA_CONNECTED -// 2. AGGREGATION_IN_USED -// 3. Fragmentation not in used -// 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible -BOOLEAN TxFrameIsAggregatible( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pPrevAddr1, - IN PUCHAR p8023hdr) -{ - - // can't aggregate EAPOL (802.1x) frame - if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e)) - return FALSE; - - // can't aggregate multicast/broadcast frame - if (p8023hdr[0] & 0x01) - return FALSE; - - if (INFRA_ON(pAd)) // must be unicast to AP - return TRUE; - else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA - return TRUE; - else - return FALSE; -} - - -/* - ======================================================================== - - Routine Description: - Check the MSDU Aggregation policy - 1.HT aggregation is A-MSDU - 2.legaacy rate aggregation is software aggregation by Ralink. - - Arguments: - - Return Value: - - Note: - - ======================================================================== -*/ -BOOLEAN PeerIsAggreOn( - IN PRTMP_ADAPTER pAd, - IN ULONG TxRate, - IN PMAC_TABLE_ENTRY pMacEntry) -{ - ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE); - - if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) - { -#ifdef DOT11_N_SUPPORT - if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) - { - return TRUE; - } -#endif // DOT11_N_SUPPORT // - -#ifdef AGGREGATION_SUPPORT - if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) - { // legacy Ralink Aggregation support - return TRUE; - } -#endif // AGGREGATION_SUPPORT // - } - - return FALSE; - -} - - -/* - ======================================================================== - - Routine Description: - Check and fine the packet waiting in SW queue with highest priority - - Arguments: - pAd Pointer to our adapter - - Return Value: - pQueue Pointer to Waiting Queue - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -PQUEUE_HEADER RTMPCheckTxSwQueue( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pQueIdx) -{ - - ULONG Number; - // 2004-11-15 to be removed. test aggregation only -// if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2)) -// return NULL; - - Number = pAd->TxSwQueue[QID_AC_BK].Number - + pAd->TxSwQueue[QID_AC_BE].Number - + pAd->TxSwQueue[QID_AC_VI].Number - + pAd->TxSwQueue[QID_AC_VO].Number; - /*+ pAd->TxSwQueue[QID_HCCA].Number;*/ - - if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) - { - *pQueIdx = QID_AC_VO; - return (&pAd->TxSwQueue[QID_AC_VO]); - } - else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) - { - *pQueIdx = QID_AC_VI; - return (&pAd->TxSwQueue[QID_AC_VI]); - } - else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) - { - *pQueIdx = QID_AC_BE; - return (&pAd->TxSwQueue[QID_AC_BE]); - } - else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) - { - *pQueIdx = QID_AC_BK; - return (&pAd->TxSwQueue[QID_AC_BK]); - } - /* - else if (pAd->TxSwQueue[QID_HCCA].Head != NULL) - { - *pQueIdx = QID_HCCA; - return (&pAd->TxSwQueue[QID_HCCA]); - } - */ - - // No packet pending in Tx Sw queue - *pQueIdx = QID_AC_BK; - - return (NULL); -} - - -/* - ======================================================================== - - Routine Description: - Suspend MSDU transmission - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID RTMPSuspendMsduTransmission( - IN PRTMP_ADAPTER pAd) -{ - DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n")); - - - // - // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and - // use Lowbound as R66 value on ScanNextChannel(...) - // - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue); - - // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning) - //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); - RTMPSetAGCInitValue(pAd, BW_20); - - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); - //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings -} - - -/* - ======================================================================== - - Routine Description: - Resume MSDU transmission - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPResumeMsduTransmission( - IN PRTMP_ADAPTER pAd) -{ -// UCHAR IrqState; - - DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n")); - - - // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value - // R66 should not be 0 - if (pAd->BbpTuning.R66CurrentValue == 0) - { - pAd->BbpTuning.R66CurrentValue = 0x38; - DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n")); - } - - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue); - - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); -// sample, for IRQ LOCK to SEM LOCK -// IrqState = pAd->irq_disabled; -// if (IrqState) -// RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); -// else - RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); -} - - -UINT deaggregate_AMSDU_announce( - IN PRTMP_ADAPTER pAd, - PNDIS_PACKET pPacket, - IN PUCHAR pData, - IN ULONG DataSize) -{ - USHORT PayloadSize; - USHORT SubFrameSize; - PHEADER_802_3 pAMSDUsubheader; - UINT nMSDU; - UCHAR Header802_3[14]; - - PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP; - PNDIS_PACKET pClonePacket; - - - - nMSDU = 0; - - while (DataSize > LENGTH_802_3) - { - - nMSDU++; - - //hex_dump("subheader", pData, 64); - pAMSDUsubheader = (PHEADER_802_3)pData; - //pData += LENGTH_802_3; - PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8); - SubFrameSize = PayloadSize + LENGTH_802_3; - - - if ((DataSize < SubFrameSize) || (PayloadSize > 1518 )) - { - break; - } - - //DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n", nMSDU, PayloadSize)); - - pPayload = pData + LENGTH_802_3; - pDA = pData; - pSA = pData + MAC_ADDR_LEN; - - // convert to 802.3 header - CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP); - -#ifdef CONFIG_STA_SUPPORT - if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) ) - { - /* avoid local heap overflow, use dyanamic allocation */ - MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); - if (Elem != NULL) - { - memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize); - Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize; - //WpaEAPOLKeyAction(pAd, Elem); - REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID, Elem->Msg, Elem->MsgLen, 0, 0, 0, 0); - kfree(Elem); - } - } -#endif // CONFIG_STA_SUPPORT // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (pRemovedLLCSNAP) - { - pPayload -= LENGTH_802_3; - PayloadSize += LENGTH_802_3; - NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3); - } - } -#endif // CONFIG_STA_SUPPORT // - - pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize); - if (pClonePacket) - { -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket)); -#endif // CONFIG_STA_SUPPORT // - } - - - // A-MSDU has padding to multiple of 4 including subframe header. - // align SubFrameSize up to multiple of 4 - SubFrameSize = (SubFrameSize+3)&(~0x3); - - - if (SubFrameSize > 1528 || SubFrameSize < 32) - { - break; - } - - if (DataSize > SubFrameSize) - { - pData += SubFrameSize; - DataSize -= SubFrameSize; - } - else - { - // end of A-MSDU - DataSize = 0; - } - } - - // finally release original rx packet - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - - return nMSDU; -} - - -UINT BA_Reorder_AMSDU_Annnounce( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket) -{ - PUCHAR pData; - USHORT DataSize; - UINT nMSDU = 0; - - pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); - DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); - - nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize); - - return nMSDU; -} - - -/* - ========================================================================== - Description: - Look up the MAC address in the MAC table. Return NULL if not found. - Return: - pEntry - pointer to the MAC entry; NULL is not found - ========================================================================== -*/ -MAC_TABLE_ENTRY *MacTableLookup( - IN PRTMP_ADAPTER pAd, - PUCHAR pAddr) -{ - ULONG HashIdx; - MAC_TABLE_ENTRY *pEntry = NULL; - - HashIdx = MAC_ADDR_HASH_INDEX(pAddr); - pEntry = pAd->MacTab.Hash[HashIdx]; - - while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) - { - if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) - { - break; - } - else - pEntry = pEntry->pNext; - } - - return pEntry; -} - -MAC_TABLE_ENTRY *MacTableInsertEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN UCHAR apidx, - IN BOOLEAN CleanAll) -{ - UCHAR HashIdx; - int i, FirstWcid; - MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; -// USHORT offset; -// ULONG addr; - - // if FULL, return - if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) - return NULL; - - FirstWcid = 1; -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - if (pAd->StaCfg.BssType == BSS_INFRA) - FirstWcid = 2; -#endif // CONFIG_STA_SUPPORT // - - // allocate one MAC entry - NdisAcquireSpinLock(&pAd->MacTabLock); - for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup - { - // pick up the first available vacancy - if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) && - (pAd->MacTab.Content[i].ValidAsWDS == FALSE) && - (pAd->MacTab.Content[i].ValidAsApCli== FALSE) && - (pAd->MacTab.Content[i].ValidAsMesh == FALSE) -#ifdef CONFIG_STA_SUPPORT -#ifdef QOS_DLS_SUPPORT - && (pAd->MacTab.Content[i].ValidAsDls == FALSE) -#endif // QOS_DLS_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - ) - { - pEntry = &pAd->MacTab.Content[i]; - if (CleanAll == TRUE) - { - pEntry->MaxSupportedRate = RATE_11; - pEntry->CurrTxRate = RATE_11; - NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); - pEntry->PairwiseKey.KeyLen = 0; - pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; - } -#ifdef CONFIG_STA_SUPPORT -#ifdef QOS_DLS_SUPPORT - if (apidx >= MIN_NET_DEVICE_FOR_DLS) - { - pEntry->ValidAsCLI = FALSE; - pEntry->ValidAsWDS = FALSE; - pEntry->ValidAsApCli = FALSE; - pEntry->ValidAsMesh = FALSE; - pEntry->ValidAsDls = TRUE; - pEntry->isCached = FALSE; - } - else -#endif // QOS_DLS_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - { - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - pEntry->ValidAsCLI = TRUE; - pEntry->ValidAsWDS = FALSE; - pEntry->ValidAsApCli = FALSE; - pEntry->ValidAsMesh = FALSE; - pEntry->ValidAsDls = FALSE; - } -#endif // CONFIG_STA_SUPPORT // - } - - pEntry->bIAmBadAtheros = FALSE; - pEntry->pAd = pAd; - pEntry->CMTimerRunning = FALSE; - pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; - pEntry->RSNIE_Len = 0; - NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter)); - pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; - - if (pEntry->ValidAsMesh) - pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH); - else if (pEntry->ValidAsApCli) - pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI); - else if (pEntry->ValidAsWDS) - pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS); -#ifdef CONFIG_STA_SUPPORT -#ifdef QOS_DLS_SUPPORT - else if (pEntry->ValidAsDls) - pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS); -#endif // QOS_DLS_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - else - pEntry->apidx = apidx; - - - { - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - pEntry->AuthMode = pAd->StaCfg.AuthMode; - pEntry->WepStatus = pAd->StaCfg.WepStatus; - pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; -#ifdef RTMP_MAC_PCI - AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i); -#endif // RTMP_MAC_PCI // - } -#endif // CONFIG_STA_SUPPORT // - } - - pEntry->GTKState = REKEY_NEGOTIATING; - pEntry->PairwiseKey.KeyLen = 0; - pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; -#ifdef CONFIG_STA_SUPPORT -#ifdef QOS_DLS_SUPPORT - if (pEntry->ValidAsDls == TRUE) - pEntry->PortSecured = WPA_802_1X_PORT_SECURED; - else -#endif //QOS_DLS_SUPPORT -#endif // CONFIG_STA_SUPPORT // - pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; - - pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; - COPY_MAC_ADDR(pEntry->Addr, pAddr); - pEntry->Sst = SST_NOT_AUTH; - pEntry->AuthState = AS_NOT_AUTH; - pEntry->Aid = (USHORT)i; //0; - pEntry->CapabilityInfo = 0; - pEntry->PsMode = PWR_ACTIVE; - pEntry->PsQIdleCount = 0; - pEntry->NoDataIdleCount = 0; - pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT; - pEntry->ContinueTxFailCnt = 0; -#ifdef WDS_SUPPORT - pEntry->LockEntryTx = FALSE; - pEntry->TimeStamp_toTxRing = 0; -#endif // WDS_SUPPORT // - InitializeQueueHeader(&pEntry->PsQueue); - - - pAd->MacTab.Size ++; - // Add this entry into ASIC RX WCID search table - RTMP_STA_ENTRY_ADD(pAd, pEntry); - - - - DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size)); - break; - } - } - - // add this MAC entry into HASH table - if (pEntry) - { - HashIdx = MAC_ADDR_HASH_INDEX(pAddr); - if (pAd->MacTab.Hash[HashIdx] == NULL) - { - pAd->MacTab.Hash[HashIdx] = pEntry; - } - else - { - pCurrEntry = pAd->MacTab.Hash[HashIdx]; - while (pCurrEntry->pNext != NULL) - pCurrEntry = pCurrEntry->pNext; - pCurrEntry->pNext = pEntry; - } - } - - NdisReleaseSpinLock(&pAd->MacTabLock); - return pEntry; -} - -/* - ========================================================================== - Description: - Delete a specified client from MAC table - ========================================================================== - */ -BOOLEAN MacTableDeleteEntry( - IN PRTMP_ADAPTER pAd, - IN USHORT wcid, - IN PUCHAR pAddr) -{ - USHORT HashIdx; - MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry; - BOOLEAN Cancelled; - //USHORT offset; // unused variable - //UCHAR j; // unused variable - - if (wcid >= MAX_LEN_OF_MAC_TABLE) - return FALSE; - - NdisAcquireSpinLock(&pAd->MacTabLock); - - HashIdx = MAC_ADDR_HASH_INDEX(pAddr); - //pEntry = pAd->MacTab.Hash[HashIdx]; - pEntry = &pAd->MacTab.Content[wcid]; - - if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh -#ifdef CONFIG_STA_SUPPORT -#ifdef QOS_DLS_SUPPORT - || pEntry->ValidAsDls -#endif // QOS_DLS_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - )) - { - if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) - { - - // Delete this entry from ASIC on-chip WCID Table - RTMP_STA_ENTRY_MAC_RESET(pAd, wcid); - -#ifdef DOT11_N_SUPPORT - // free resources of BA - BASessionTearDownALL(pAd, pEntry->Aid); -#endif // DOT11_N_SUPPORT // - - - pPrevEntry = NULL; - pProbeEntry = pAd->MacTab.Hash[HashIdx]; - ASSERT(pProbeEntry); - - // update Hash list - do - { - if (pProbeEntry == pEntry) - { - if (pPrevEntry == NULL) - { - pAd->MacTab.Hash[HashIdx] = pEntry->pNext; - } - else - { - pPrevEntry->pNext = pEntry->pNext; - } - break; - } - - pPrevEntry = pProbeEntry; - pProbeEntry = pProbeEntry->pNext; - } while (pProbeEntry); - - // not found !!! - ASSERT(pProbeEntry != NULL); - - RTMP_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid); - - - if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE) - { - RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); - pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; - } - - - NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); - pAd->MacTab.Size --; - DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size)); - } - else - { - DBGPRINT(RT_DEBUG_OFF, ("\n%s: Impossible Wcid = %d !!!!!\n", __FUNCTION__, wcid)); - } - } - - NdisReleaseSpinLock(&pAd->MacTabLock); - - //Reset operating mode when no Sta. - if (pAd->MacTab.Size == 0) - { -#ifdef DOT11_N_SUPPORT - pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0; -#endif // DOT11_N_SUPPORT // - //AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/); - RTMP_UPDATE_PROTECT(pAd); // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet - } - - return TRUE; -} - - -/* - ========================================================================== - Description: - This routine reset the entire MAC table. All packets pending in - the power-saving queues are freed here. - ========================================================================== - */ -VOID MacTableReset( - IN PRTMP_ADAPTER pAd) -{ - int i; - - DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n")); - //NdisAcquireSpinLock(&pAd->MacTabLock); - - - for (i=1; iMacTab.Content[i].ValidAsCLI == TRUE) - { - - -#ifdef DOT11_N_SUPPORT - // free resources of BA - BASessionTearDownALL(pAd, i); -#endif // DOT11_N_SUPPORT // - - pAd->MacTab.Content[i].ValidAsCLI = FALSE; - - - - - //AsicDelWcidTab(pAd, i); - } - } - - return; -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID AssocParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq, - IN PUCHAR pAddr, - IN USHORT CapabilityInfo, - IN ULONG Timeout, - IN USHORT ListenIntv) -{ - COPY_MAC_ADDR(AssocReq->Addr, pAddr); - // Add mask to support 802.11b mode only - AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request - AssocReq->Timeout = Timeout; - AssocReq->ListenIntv = ListenIntv; -} - - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID DisassocParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq, - IN PUCHAR pAddr, - IN USHORT Reason) -{ - COPY_MAC_ADDR(DisassocReq->Addr, pAddr); - DisassocReq->Reason = Reason; -} - - -/* - ======================================================================== - - Routine Description: - Check the out going frame, if this is an DHCP or ARP datagram - will be duplicate another frame at low data rate transmit. - - Arguments: - pAd Pointer to our adapter - pPacket Pointer to outgoing Ndis frame - - Return Value: - TRUE To be duplicate at Low data rate transmit. (1mb) - FALSE Do nothing. - - IRQL = DISPATCH_LEVEL - - Note: - - MAC header + IP Header + UDP Header - 14 Bytes 20 Bytes - - UDP Header - 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15| - Source Port - 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31| - Destination Port - - port 0x43 means Bootstrap Protocol, server. - Port 0x44 means Bootstrap Protocol, client. - - ======================================================================== -*/ - -BOOLEAN RTMPCheckDHCPFrame( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket) -{ - PACKET_INFO PacketInfo; - ULONG NumberOfBytesRead = 0; - ULONG CurrentOffset = 0; - PVOID pVirtualAddress = NULL; - UINT NdisBufferLength; - PUCHAR pSrc; - USHORT Protocol; - UCHAR ByteOffset36 = 0; - UCHAR ByteOffset38 = 0; - BOOLEAN ReadFirstParm = TRUE; - - RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength); - - NumberOfBytesRead += NdisBufferLength; - pSrc = (PUCHAR) pVirtualAddress; - Protocol = *(pSrc + 12) * 256 + *(pSrc + 13); - - // - // Check DHCP & BOOTP protocol - // - while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) - { - if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) - { - CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength); - ByteOffset36 = *(pSrc + CurrentOffset); - ReadFirstParm = FALSE; - } - - if (NumberOfBytesRead >= 37) - { - CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength); - ByteOffset38 = *(pSrc + CurrentOffset); - //End of Read - break; - } - return FALSE; - } - - // Check for DHCP & BOOTP protocol - if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) - { - // - // 2054 (hex 0806) for ARP datagrams - // if this packet is not ARP datagrams, then do nothing - // ARP datagrams will also be duplicate at 1mb broadcast frames - // - if (Protocol != 0x0806 ) - return FALSE; - } - - return TRUE; -} - - -BOOLEAN RTMPCheckEtherType( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket) -{ - USHORT TypeLen; - UCHAR Byte0, Byte1; - PUCHAR pSrcBuf; - UINT32 pktLen; - UINT16 srcPort, dstPort; - BOOLEAN status = TRUE; - - - pSrcBuf = GET_OS_PKT_DATAPTR(pPacket); - pktLen = GET_OS_PKT_LEN(pPacket); - - ASSERT(pSrcBuf); - - RTMP_SET_PACKET_SPECIFIC(pPacket, 0); - - // get Ethernet protocol field - TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13]; - - pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header. - - if (TypeLen <= 1500) - { // 802.3, 802.3 LLC - /* - DestMAC(6) + SrcMAC(6) + Lenght(2) + - DSAP(1) + SSAP(1) + Control(1) + - if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header. - => + SNAP (5, OriginationID(3) + etherType(2)) - */ - if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03) - { - Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 6, &Byte0, &Byte1); - RTMP_SET_PACKET_LLCSNAP(pPacket, 1); - TypeLen = (USHORT)((Byte0 << 8) + Byte1); - pSrcBuf += 8; // Skip this LLC/SNAP header - } - else - { - //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. - } - } - - // If it's a VLAN packet, get the real Type/Length field. - if (TypeLen == 0x8100) - { - /* 0x8100 means VLAN packets */ - - /* Dest. MAC Address (6-bytes) + - Source MAC Address (6-bytes) + - Length/Type = 802.1Q Tag Type (2-byte) + - Tag Control Information (2-bytes) + - Length / Type (2-bytes) + - data payload (0-n bytes) + - Pad (0-p bytes) + - Frame Check Sequence (4-bytes) */ - - RTMP_SET_PACKET_VLAN(pPacket, 1); - Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 2, &Byte0, &Byte1); - TypeLen = (USHORT)((Byte0 << 8) + Byte1); - - pSrcBuf += 4; // Skip the VLAN Header. - } - - switch (TypeLen) - { - case 0x0800: - { - ASSERT((pktLen > 34)); - if (*(pSrcBuf + 9) == 0x11) - { // udp packet - ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header - - pSrcBuf += 20; // Skip the IP header - srcPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf))); - dstPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf+2))); - - if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44)) - { //It's a BOOTP/DHCP packet - RTMP_SET_PACKET_DHCP(pPacket, 1); - } - } - } - break; - case 0x0806: - { - //ARP Packet. - RTMP_SET_PACKET_DHCP(pPacket, 1); - } - break; - case 0x888e: - { - // EAPOL Packet. - RTMP_SET_PACKET_EAPOL(pPacket, 1); - } - break; - default: - status = FALSE; - break; - } - - return status; - -} - - - -VOID Update_Rssi_Sample( - IN PRTMP_ADAPTER pAd, - IN RSSI_SAMPLE *pRssi, - IN PRXWI_STRUC pRxWI) - { - CHAR rssi0 = pRxWI->RSSI0; - CHAR rssi1 = pRxWI->RSSI1; - CHAR rssi2 = pRxWI->RSSI2; - - if (rssi0 != 0) - { - pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0); - pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0; - pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3; - } - - if (rssi1 != 0) - { - pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1); - pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1; - pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3; - } - - if (rssi2 != 0) - { - pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2); - pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2; - pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3; - } -} - - - -// Normal legacy Rx packet indication -VOID Indicate_Legacy_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) -{ - PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; - UCHAR Header802_3[LENGTH_802_3]; - - // 1. get 802.3 Header - // 2. remove LLC - // a. pointer pRxBlk->pData to payload - // b. modify pRxBlk->DataSize -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); -#endif // CONFIG_STA_SUPPORT // - - if (pRxBlk->DataSize > MAX_RX_PKT_LEN) - { - - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); - return; - } - - - STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); - - - wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); - - // - // pass this 802.3 packet to upper layer or forward this packet to WM directly - // -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); -#endif // CONFIG_STA_SUPPORT // - -} - - -// Normal, AMPDU or AMSDU -VOID CmmRxnonRalinkFrameIndicate( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) -{ -#ifdef DOT11_N_SUPPORT - if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) - { - Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); - } - else -#endif // DOT11_N_SUPPORT // - { -#ifdef DOT11_N_SUPPORT - if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) - { - // handle A-MSDU - Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID); - } - else -#endif // DOT11_N_SUPPORT // - { - Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); - } - } -} - - -VOID CmmRxRalinkFrameIndicate( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) -{ - UCHAR Header802_3[LENGTH_802_3]; - UINT16 Msdu2Size; - UINT16 Payload1Size, Payload2Size; - PUCHAR pData2; - PNDIS_PACKET pPacket2 = NULL; - - - - Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8); - - if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) - { - /* skip two byte MSDU2 len */ - pRxBlk->pData += 2; - pRxBlk->DataSize -= 2; - } - else - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); - return; - } - - // get 802.3 Header and remove LLC -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); -#endif // CONFIG_STA_SUPPORT // - - - ASSERT(pRxBlk->pRxPacket); - - // Ralink Aggregation frame - pAd->RalinkCounters.OneSecRxAggregationCount ++; - Payload1Size = pRxBlk->DataSize - Msdu2Size; - Payload2Size = Msdu2Size - LENGTH_802_3; - - pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3; -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID); -#endif // CONFIG_STA_SUPPORT // - - if (!pPacket2) - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); - return; - } - - // update payload size of 1st packet - pRxBlk->DataSize = Payload1Size; - wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID); -#endif // CONFIG_STA_SUPPORT // - - if (pPacket2) - { -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID); -#endif // CONFIG_STA_SUPPORT // - } -} - - -#define RESET_FRAGFRAME(_fragFrame) \ - { \ - _fragFrame.RxSize = 0; \ - _fragFrame.Sequence = 0; \ - _fragFrame.LastFrag = 0; \ - _fragFrame.Flags = 0; \ - } - - -PNDIS_PACKET RTMPDeFragmentDataFrame( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk) -{ - PHEADER_802_11 pHeader = pRxBlk->pHeader; - PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; - UCHAR *pData = pRxBlk->pData; - USHORT DataSize = pRxBlk->DataSize; - PNDIS_PACKET pRetPacket = NULL; - UCHAR *pFragBuffer = NULL; - BOOLEAN bReassDone = FALSE; - UCHAR HeaderRoom = 0; - - - ASSERT(pHeader); - - HeaderRoom = pData - (UCHAR *)pHeader; - - // Re-assemble the fragmented packets - if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt - { - // the first pkt of fragment, record it. - if (pHeader->FC.MoreFrag) - { - ASSERT(pAd->FragFrame.pFragPacket); - pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); - pAd->FragFrame.RxSize = DataSize + HeaderRoom; - NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize); - pAd->FragFrame.Sequence = pHeader->Sequence; - pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0 - ASSERT(pAd->FragFrame.LastFrag == 0); - goto done; // end of processing this frame - } - } - else //Middle & End of fragment - { - if ((pHeader->Sequence != pAd->FragFrame.Sequence) || - (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) - { - // Fragment is not the same sequence or out of fragment number order - // Reset Fragment control blk - RESET_FRAGFRAME(pAd->FragFrame); - DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n")); - goto done; // give up this frame - } - else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) - { - // Fragment frame is too large, it exeeds the maximum frame size. - // Reset Fragment control blk - RESET_FRAGFRAME(pAd->FragFrame); - DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n")); - goto done; // give up this frame - } - - // - // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment. - // In this case, we will dropt it. - // - if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) - { - DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag)); - goto done; // give up this frame - } - - pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); - - // concatenate this fragment into the re-assembly buffer - NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize); - pAd->FragFrame.RxSize += DataSize; - pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number - - // Last fragment - if (pHeader->FC.MoreFrag == FALSE) - { - bReassDone = TRUE; - } - } - -done: - // always release rx fragmented packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); - - // return defragmented packet if packet is reassembled completely - // otherwise return NULL - if (bReassDone) - { - PNDIS_PACKET pNewFragPacket; - - // allocate a new packet buffer for fragment - pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); - if (pNewFragPacket) - { - // update RxBlk - pRetPacket = pAd->FragFrame.pFragPacket; - pAd->FragFrame.pFragPacket = pNewFragPacket; - pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket); - pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom; - pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom; - pRxBlk->pRxPacket = pRetPacket; - } - else - { - RESET_FRAGFRAME(pAd->FragFrame); - } - } - - return pRetPacket; -} - - -VOID Indicate_AMSDU_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) -{ - UINT nMSDU; - - update_os_packet_info(pAd, pRxBlk, FromWhichBSSID); - RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); - nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize); -} - -VOID Indicate_EAPOL_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) -{ - MAC_TABLE_ENTRY *pEntry = NULL; - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - pEntry = &pAd->MacTab.Content[BSSID_WCID]; - STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); - return; - } -#endif // CONFIG_STA_SUPPORT // - - if (pEntry == NULL) - { - DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n")); - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); - return; - } -} - -#define BCN_TBTT_OFFSET 64 //defer 64 us -VOID ReSyncBeaconTime( - IN PRTMP_ADAPTER pAd) -{ - - UINT32 Offset; - - - Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET); - - pAd->TbttTickCount++; - - // - // The updated BeaconInterval Value will affect Beacon Interval after two TBTT - // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER - // - if (Offset == (BCN_TBTT_OFFSET-2)) - { - BCN_TIME_CFG_STRUC csr; - RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); - csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us - RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); - } - else - { - if (Offset == (BCN_TBTT_OFFSET-1)) - { - BCN_TIME_CFG_STRUC csr; - - RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); - csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU - RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); - } - } -} diff --git a/drivers/staging/rt3090/common/cmm_data_pci.c b/drivers/staging/rt3090/common/cmm_data_pci.c deleted file mode 100644 index 084f81927158756eac028a440b275be91e0ae093..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/cmm_data_pci.c +++ /dev/null @@ -1,1576 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* -*/ - -/* - All functions in this file must be PCI-depended, or you should out your function - in other files. - -*/ -#include "../rt_config.h" - - -USHORT RtmpPCI_WriteTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN BOOLEAN bIsLast, - OUT USHORT *FreeNumber) -{ - - UCHAR *pDMAHeaderBufVA; - USHORT TxIdx, RetTxIdx; - PTXD_STRUC pTxD; - UINT32 BufBasePaLow; - PRTMP_TX_RING pTxRing; - USHORT hwHeaderLen; - - // - // get Tx Ring Resource - // - pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; - TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; - pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; - BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); - - // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer - if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) - { - //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; - hwHeaderLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; - } - else - { - //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); - hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; - } - NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen); - - pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; - pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; - - // - // build Tx Descriptor - // - - pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; - NdisZeroMemory(pTxD, TXD_SIZE); - - pTxD->SDPtr0 = BufBasePaLow; - pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding - pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE); - pTxD->SDLen1 = pTxBlk->SrcBufLen; - pTxD->LastSec0 = 0; - pTxD->LastSec1 = (bIsLast) ? 1 : 0; - - RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); - - RetTxIdx = TxIdx; - // - // Update Tx index - // - INC_RING_INDEX(TxIdx, TX_RING_SIZE); - pTxRing->TxCpuIdx = TxIdx; - - *FreeNumber -= 1; - - return RetTxIdx; -} - - -USHORT RtmpPCI_WriteSingleTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN BOOLEAN bIsLast, - OUT USHORT *FreeNumber) -{ - - UCHAR *pDMAHeaderBufVA; - USHORT TxIdx, RetTxIdx; - PTXD_STRUC pTxD; -#ifdef RT_BIG_ENDIAN - PTXD_STRUC pDestTxD; - TXD_STRUC TxD; -#endif - UINT32 BufBasePaLow; - PRTMP_TX_RING pTxRing; - USHORT hwHeaderLen; - - // - // get Tx Ring Resource - // - pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; - TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; - pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; - BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); - - // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer - //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); - hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; - - NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen); - - pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; - pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; - - // - // build Tx Descriptor - // -#ifndef RT_BIG_ENDIAN - pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; -#else - pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; - TxD = *pDestTxD; - pTxD = &TxD; -#endif - NdisZeroMemory(pTxD, TXD_SIZE); - - pTxD->SDPtr0 = BufBasePaLow; - pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding - pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);; - pTxD->SDLen1 = pTxBlk->SrcBufLen; - pTxD->LastSec0 = 0; - pTxD->LastSec1 = (bIsLast) ? 1 : 0; - - RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); -#ifdef RT_BIG_ENDIAN - RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI); - RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); -#endif // RT_BIG_ENDIAN // - - RetTxIdx = TxIdx; - // - // Update Tx index - // - INC_RING_INDEX(TxIdx, TX_RING_SIZE); - pTxRing->TxCpuIdx = TxIdx; - - *FreeNumber -= 1; - - return RetTxIdx; -} - - -USHORT RtmpPCI_WriteMultiTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR frameNum, - OUT USHORT *FreeNumber) -{ - BOOLEAN bIsLast; - UCHAR *pDMAHeaderBufVA; - USHORT TxIdx, RetTxIdx; - PTXD_STRUC pTxD; -#ifdef RT_BIG_ENDIAN - PTXD_STRUC pDestTxD; - TXD_STRUC TxD; -#endif - UINT32 BufBasePaLow; - PRTMP_TX_RING pTxRing; - USHORT hwHdrLen; - UINT32 firstDMALen; - - bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0); - - // - // get Tx Ring Resource - // - pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; - TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; - pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; - BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); - - if (frameNum == 0) - { - // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer - if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) - //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; - hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; - else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) - //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; - hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; - else - //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); - hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; - - firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; - } - else - { - firstDMALen = pTxBlk->MpduHeaderLen; - } - - NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); - - pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; - pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; - - // - // build Tx Descriptor - // -#ifndef RT_BIG_ENDIAN - pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; -#else - pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; - TxD = *pDestTxD; - pTxD = &TxD; -#endif - NdisZeroMemory(pTxD, TXD_SIZE); - - pTxD->SDPtr0 = BufBasePaLow; - pTxD->SDLen0 = firstDMALen; // include padding - pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);; - pTxD->SDLen1 = pTxBlk->SrcBufLen; - pTxD->LastSec0 = 0; - pTxD->LastSec1 = (bIsLast) ? 1 : 0; - - RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); - -#ifdef RT_BIG_ENDIAN - if (frameNum == 0) - RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA+ TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); - - if (frameNum != 0) - RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI); - - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); -#endif // RT_BIG_ENDIAN // - - RetTxIdx = TxIdx; - // - // Update Tx index - // - INC_RING_INDEX(TxIdx, TX_RING_SIZE); - pTxRing->TxCpuIdx = TxIdx; - - *FreeNumber -= 1; - - return RetTxIdx; - -} - - -VOID RtmpPCI_FinalWriteTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN USHORT totalMPDUSize, - IN USHORT FirstTxIdx) -{ - - PTXWI_STRUC pTxWI; - PRTMP_TX_RING pTxRing; - - // - // get Tx Ring Resource - // - pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; - pTxWI = (PTXWI_STRUC) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa; - pTxWI->MPDUtotalByteCount = totalMPDUSize; -#ifdef RT_BIG_ENDIAN - RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); -#endif // RT_BIG_ENDIAN // - -} - - -VOID RtmpPCIDataLastTxIdx( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN USHORT LastTxIdx) -{ - PTXD_STRUC pTxD; -#ifdef RT_BIG_ENDIAN - PTXD_STRUC pDestTxD; - TXD_STRUC TxD; -#endif - PRTMP_TX_RING pTxRing; - - // - // get Tx Ring Resource - // - pTxRing = &pAd->TxRing[QueIdx]; - - // - // build Tx Descriptor - // -#ifndef RT_BIG_ENDIAN - pTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa; -#else - pDestTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa; - TxD = *pDestTxD; - pTxD = &TxD; -#endif - - pTxD->LastSec1 = 1; - -#ifdef RT_BIG_ENDIAN - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); -#endif // RT_BIG_ENDIAN // - -} - - -USHORT RtmpPCI_WriteFragTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR fragNum, - OUT USHORT *FreeNumber) -{ - UCHAR *pDMAHeaderBufVA; - USHORT TxIdx, RetTxIdx; - PTXD_STRUC pTxD; -#ifdef RT_BIG_ENDIAN - PTXD_STRUC pDestTxD; - TXD_STRUC TxD; -#endif - UINT32 BufBasePaLow; - PRTMP_TX_RING pTxRing; - USHORT hwHeaderLen; - UINT32 firstDMALen; - - // - // Get Tx Ring Resource - // - pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; - TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; - pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; - BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); - - // - // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer - // - //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); - hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; - - firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; - NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); - - - // - // Build Tx Descriptor - // -#ifndef RT_BIG_ENDIAN - pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; -#else - pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; - TxD = *pDestTxD; - pTxD = &TxD; -#endif - NdisZeroMemory(pTxD, TXD_SIZE); - - if (fragNum == pTxBlk->TotalFragNum) - { - pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; - pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; - } - - pTxD->SDPtr0 = BufBasePaLow; - pTxD->SDLen0 = firstDMALen; // include padding - pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE); - pTxD->SDLen1 = pTxBlk->SrcBufLen; - pTxD->LastSec0 = 0; - pTxD->LastSec1 = 1; - - RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); - -#ifdef RT_BIG_ENDIAN - RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI); - RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); -#endif // RT_BIG_ENDIAN // - - RetTxIdx = TxIdx; - pTxBlk->Priv += pTxBlk->SrcBufLen; - - // - // Update Tx index - // - INC_RING_INDEX(TxIdx, TX_RING_SIZE); - pTxRing->TxCpuIdx = TxIdx; - - *FreeNumber -= 1; - - return RetTxIdx; - -} - - -/* - Must be run in Interrupt context - This function handle PCI specific TxDesc and cpu index update and kick the packet out. - */ -int RtmpPCIMgmtKickOut( - IN RTMP_ADAPTER *pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket, - IN PUCHAR pSrcBufVA, - IN UINT SrcBufLen) -{ - PTXD_STRUC pTxD; -#ifdef RT_BIG_ENDIAN - PTXD_STRUC pDestTxD; - TXD_STRUC TxD; -#endif - ULONG SwIdx = pAd->MgmtRing.TxCpuIdx; - -#ifdef RT_BIG_ENDIAN - pDestTxD = (PTXD_STRUC)pAd->MgmtRing.Cell[SwIdx].AllocVa; - TxD = *pDestTxD; - pTxD = &TxD; - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); -#else - pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa; -#endif - - pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket; - pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL; - - RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT); - pTxD->LastSec0 = 1; - pTxD->LastSec1 = 1; - pTxD->DMADONE = 0; - pTxD->SDLen1 = 0; - pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE); - pTxD->SDLen0 = SrcBufLen; - -#ifdef RT_BIG_ENDIAN - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); -#endif - -//================================================================== -/* DBGPRINT_RAW(RT_DEBUG_TRACE, ("MLMEHardTransmit\n")); - for (i = 0; i < (TXWI_SIZE+24); i++) - { - - DBGPRINT_RAW(RT_DEBUG_TRACE, ("%x:", *(pSrcBufVA+i))); - if ( i%4 == 3) - DBGPRINT_RAW(RT_DEBUG_TRACE, (" :: ")); - if ( i%16 == 15) - DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n ")); - } - DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n "));*/ -//======================================================================= - - pAd->RalinkCounters.KickTxCount++; - pAd->RalinkCounters.OneSecTxDoneCount++; - - // Increase TX_CTX_IDX, but write to register later. - INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); - - RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); - - return 0; -} - - -#ifdef CONFIG_STA_SUPPORT -/* - ======================================================================== - - Routine Description: - Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound - - Arguments: - pRxD Pointer to the Rx descriptor - - Return Value: - NDIS_STATUS_SUCCESS No err - NDIS_STATUS_FAILURE Error - - Note: - - ======================================================================== -*/ -NDIS_STATUS RTMPCheckRxError( - IN PRTMP_ADAPTER pAd, - IN PHEADER_802_11 pHeader, - IN PRXWI_STRUC pRxWI, - IN PRT28XX_RXD_STRUC pRxD) -{ - PCIPHER_KEY pWpaKey; - INT dBm; - - // Phy errors & CRC errors - if (/*(pRxD->PhyErr) ||*/ (pRxD->Crc)) - { - // Check RSSI for Noise Hist statistic collection. - dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta; - if (dBm <= -87) - pAd->StaCfg.RPIDensity[0] += 1; - else if (dBm <= -82) - pAd->StaCfg.RPIDensity[1] += 1; - else if (dBm <= -77) - pAd->StaCfg.RPIDensity[2] += 1; - else if (dBm <= -72) - pAd->StaCfg.RPIDensity[3] += 1; - else if (dBm <= -67) - pAd->StaCfg.RPIDensity[4] += 1; - else if (dBm <= -62) - pAd->StaCfg.RPIDensity[5] += 1; - else if (dBm <= -57) - pAd->StaCfg.RPIDensity[6] += 1; - else if (dBm > -57) - pAd->StaCfg.RPIDensity[7] += 1; - - return(NDIS_STATUS_FAILURE); - } - - // Add Rx size to channel load counter, we should ignore error counts - pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14); - - // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics - if (pHeader != NULL) - { - if (pHeader->FC.ToDs) - { - return(NDIS_STATUS_FAILURE); - } - } - - // Drop not U2M frames, cant's drop here because we will drop beacon in this case - // I am kind of doubting the U2M bit operation - // if (pRxD->U2M == 0) - // return(NDIS_STATUS_FAILURE); - - // drop decyption fail frame - if (pRxD->CipherErr) - { - if (pRxD->CipherErr == 2) - {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV ok but MICErr "));} - else if (pRxD->CipherErr == 1) - {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV Err "));} - else if (pRxD->CipherErr == 3) - DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: Key not valid ")); - - if (((pRxD->CipherErr & 1) == 1) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd)) - RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - - DBGPRINT_RAW(RT_DEBUG_TRACE,(" %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n", - pRxD->CipherErr, - pRxD->SDL0, - pRxD->Mcast | pRxD->Bcast, - pRxD->MyBss, - pRxWI->WirelessCliID, -// CipherName[pRxD->CipherAlg], - pRxWI->KeyIndex)); - - // - // MIC Error - // - if (pRxD->CipherErr == 2) - { - pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex]; -#ifdef WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.WpaSupplicantUP) - WpaSendMicFailureToWpaSupplicant(pAd, - (pWpaKey->Type == PAIRWISEKEY) ? TRUE:FALSE); - else -#endif // WPA_SUPPLICANT_SUPPORT // - RTMPReportMicError(pAd, pWpaKey); - - if (((pRxD->CipherErr & 2) == 2) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd)) - RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - - DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n")); - } - - if (pHeader == NULL) - return(NDIS_STATUS_SUCCESS); - /*if ((pRxD->CipherAlg == CIPHER_AES) && - (pHeader->Sequence == pAd->FragFrame.Sequence)) - { - // - // Acceptable since the First FragFrame no CipherErr problem. - // - return(NDIS_STATUS_SUCCESS); - }*/ - - return(NDIS_STATUS_FAILURE); - } - - return(NDIS_STATUS_SUCCESS); -} -#endif // CONFIG_STA_SUPPORT // - - -BOOLEAN RTMPFreeTXDUponTxDmaDone( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx) -{ - PRTMP_TX_RING pTxRing; - PTXD_STRUC pTxD; -#ifdef RT_BIG_ENDIAN - PTXD_STRUC pDestTxD; -#endif - PNDIS_PACKET pPacket; - UCHAR FREE = 0; - TXD_STRUC TxD, *pOriTxD; - //ULONG IrqFlags; - BOOLEAN bReschedule = FALSE; - - - ASSERT(QueIdx < NUM_OF_TX_RING); - pTxRing = &pAd->TxRing[QueIdx]; - - RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx); - while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx) - { -// RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); -#ifdef RALINK_ATE -#ifdef RALINK_28xx_QA - PHEADER_802_11 pHeader80211; - - if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE)) - { - if (pAd->ate.QID == QueIdx) - { - pAd->ate.TxDoneCount++; - pAd->RalinkCounters.KickTxCount++; - - /* always use QID_AC_BE and FIFO_EDCA */ - ASSERT(pAd->ate.QID == 0); - pAd->ate.TxAc0++; - - FREE++; -#ifndef RT_BIG_ENDIAN - pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); - pOriTxD = pTxD; - NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); - pTxD = &TxD; -#else - pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); - pOriTxD = pDestTxD ; - TxD = *pDestTxD; - pTxD = &TxD; - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); -#endif - pTxD->DMADONE = 0; - - pHeader80211 = pTxRing->Cell[pTxRing->TxSwFreeIdx].DmaBuf.AllocVa + sizeof(TXWI_STRUC); -#ifdef RT_BIG_ENDIAN - RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_READ, FALSE); -#endif - pHeader80211->Sequence = ++pAd->ate.seq; -#ifdef RT_BIG_ENDIAN - RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE); -#endif - - if ((pAd->ate.bQATxStart == TRUE) && (pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.TxDoneCount < pAd->ate.TxCount)) - { - pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); - pAd->RalinkCounters.OneSecTransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); - pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; - INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); - - /* get TX_DTX_IDX again */ - RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx); - goto kick_out; - } - else if ((pAd->ate.TxStatus == 1)/* or (pAd->ate.bQATxStart == TRUE) ??? */ && (pAd->ate.TxDoneCount == pAd->ate.TxCount)) - { - DBGPRINT(RT_DEBUG_TRACE,("all Tx is done\n")); - - // Tx status enters idle mode. - pAd->ate.TxStatus = 0; - } - else if (!(pAd->ate.Mode & ATE_TXFRAME)) - { - /* not complete sending yet, but someone press the Stop TX botton */ - DBGPRINT(RT_DEBUG_ERROR,("not complete sending yet, but someone pressed the Stop TX bottom\n")); - DBGPRINT(RT_DEBUG_ERROR,("pAd->ate.Mode = 0x%02x\n", pAd->ate.Mode)); - } - else - { - DBGPRINT(RT_DEBUG_OFF,("pTxRing->TxSwFreeIdx = %d\n", pTxRing->TxSwFreeIdx)); - } - -#ifndef RT_BIG_ENDIAN - NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); -#else - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - *pDestTxD = TxD; -#endif // RT_BIG_ENDIAN // - - INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); - continue; - } - } -#endif // RALINK_28xx_QA // -#endif // RALINK_ATE // - - // static rate also need NICUpdateFifoStaCounters() function. - //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) - NICUpdateFifoStaCounters(pAd); - - /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */ - FREE++; -#ifndef RT_BIG_ENDIAN - pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); - pOriTxD = pTxD; - NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); - pTxD = &TxD; -#else - pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); - pOriTxD = pDestTxD ; - TxD = *pDestTxD; - pTxD = &TxD; - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); -#endif - - pTxD->DMADONE = 0; - - -#ifdef RALINK_ATE - /* Execution of this block is not allowed when ATE is running. */ - if (!(ATE_ON(pAd))) -#endif // RALINK_ATE // - { - pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket; - if (pPacket) - { -#ifdef CONFIG_5VT_ENHANCE - if (RTMP_GET_PACKET_5VT(pPacket)) - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE); - else -#endif // CONFIG_5VT_ENHANCE // - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - //Always assign pNdisPacket as NULL after clear - pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL; - - pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket; - - ASSERT(pPacket == NULL); - if (pPacket) - { -#ifdef CONFIG_5VT_ENHANCE - if (RTMP_GET_PACKET_5VT(pPacket)) - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE); - else -#endif // CONFIG_5VT_ENHANCE // - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - //Always assign pNextNdisPacket as NULL after clear - pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; - } - - pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); - pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; - INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); - /* get tx_tdx_idx again */ - RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx); -#ifdef RT_BIG_ENDIAN - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - *pDestTxD = TxD; -#else - NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); -#endif - -#ifdef RALINK_ATE -#ifdef RALINK_28xx_QA -kick_out: -#endif // RALINK_28xx_QA // - - /* - ATE_TXCONT mode also need to send some normal frames, so let it in. - ATE_STOP must be changed not to be 0xff - to prevent it from running into this block. - */ - if ((pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.QID == QueIdx)) - { - // TxDoneCount++ has been done if QA is used. - if (pAd->ate.bQATxStart == FALSE) - { - pAd->ate.TxDoneCount++; - } - if (((pAd->ate.TxCount - pAd->ate.TxDoneCount + 1) >= TX_RING_SIZE)) - { - /* Note : We increase TxCpuIdx here, not TxSwFreeIdx ! */ - INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); -#ifndef RT_BIG_ENDIAN - pTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); - pOriTxD = pTxD; - NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); - pTxD = &TxD; -#else - pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); - pOriTxD = pDestTxD ; - TxD = *pDestTxD; - pTxD = &TxD; - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); -#endif - pTxD->DMADONE = 0; -#ifndef RT_BIG_ENDIAN - NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); -#else - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - *pDestTxD = TxD; -#endif - // kick Tx-Ring - RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * RINGREG_DIFF, pAd->TxRing[QueIdx].TxCpuIdx); - pAd->RalinkCounters.KickTxCount++; - } - } -#endif // RALINK_ATE // -// RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); - } - - - return bReschedule; - -} - - -/* - ======================================================================== - - Routine Description: - Process TX Rings DMA Done interrupt, running in DPC level - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - ======================================================================== -*/ -BOOLEAN RTMPHandleTxRingDmaDoneInterrupt( - IN PRTMP_ADAPTER pAd, - IN INT_SOURCE_CSR_STRUC TxRingBitmap) -{ -// UCHAR Count = 0; - unsigned long IrqFlags; - BOOLEAN bReschedule = FALSE; - - // Make sure Tx ring resource won't be used by other threads - //NdisAcquireSpinLock(&pAd->TxRingLock); - - RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); - - if (TxRingBitmap.field.Ac0DmaDone) - bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE); -/* - if (TxRingBitmap.field.HccaDmaDone) - bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA); -*/ - - if (TxRingBitmap.field.Ac3DmaDone) - bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO); - - if (TxRingBitmap.field.Ac2DmaDone) - bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI); - - if (TxRingBitmap.field.Ac1DmaDone) - bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK); - - // Make sure to release Tx ring resource - //NdisReleaseSpinLock(&pAd->TxRingLock); - RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); - - // Dequeue outgoing frames from TxSwQueue[] and process it - RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); - - return bReschedule; -} - - -/* - ======================================================================== - - Routine Description: - Process MGMT ring DMA done interrupt, running in DPC level - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPHandleMgmtRingDmaDoneInterrupt( - IN PRTMP_ADAPTER pAd) -{ - PTXD_STRUC pTxD; -#ifdef RT_BIG_ENDIAN - PTXD_STRUC pDestTxD; - TXD_STRUC TxD; -#endif - PNDIS_PACKET pPacket; -// int i; - UCHAR FREE = 0; - PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; - - NdisAcquireSpinLock(&pAd->MgmtRingLock); - - RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx); - while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx) - { - FREE++; -#ifdef RT_BIG_ENDIAN - pDestTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa); - TxD = *pDestTxD; - pTxD = &TxD; - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); -#else - pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa); -#endif - pTxD->DMADONE = 0; - pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket; - - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL; - - pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket; - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL; - INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE); - -#ifdef RT_BIG_ENDIAN - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); -#endif - } - NdisReleaseSpinLock(&pAd->MgmtRingLock); - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // -} - - -/* - ======================================================================== - - Routine Description: - Arguments: - Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon. - - IRQL = DISPATCH_LEVEL - - ======================================================================== -*/ -VOID RTMPHandleTBTTInterrupt( - IN PRTMP_ADAPTER pAd) -{ - { - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - } - } -} - - -/* - ======================================================================== - - Routine Description: - Arguments: - pAd Pointer to our adapter. Rewrite beacon content before next send-out. - - IRQL = DISPATCH_LEVEL - - ======================================================================== -*/ -VOID RTMPHandlePreTBTTInterrupt( - IN PRTMP_ADAPTER pAd) -{ - { - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n")); - } - } - - -} - -VOID RTMPHandleRxCoherentInterrupt( - IN PRTMP_ADAPTER pAd) -{ - WPDMA_GLO_CFG_STRUC GloCfg; - - if (pAd == NULL) - { - DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n")); - return; - } - - DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n")); - - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word); - - GloCfg.field.EnTXWriteBackDDONE = 0; - GloCfg.field.EnableRxDMA = 0; - GloCfg.field.EnableTxDMA = 0; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); - - RTMPRingCleanUp(pAd, QID_AC_BE); - RTMPRingCleanUp(pAd, QID_AC_BK); - RTMPRingCleanUp(pAd, QID_AC_VI); - RTMPRingCleanUp(pAd, QID_AC_VO); - /*RTMPRingCleanUp(pAd, QID_HCCA);*/ - RTMPRingCleanUp(pAd, QID_MGMT); - RTMPRingCleanUp(pAd, QID_RX); - - RTMPEnableRxTx(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n")); -} - - - - -VOID DBGPRINT_TX_RING( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx) -{ - UINT32 Ac0Base; - UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx; - int i; -// PULONG pTxD; - PULONG ptemp; - - DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " )); - switch (QueIdx) - { - case QID_AC_BE: - RTMP_IO_READ32(pAd, TX_BASE_PTR0, &Ac0Base); - RTMP_IO_READ32(pAd, TX_CTX_IDX0, &Ac0SwIdx); - RTMP_IO_READ32(pAd, TX_DTX_IDX0, &Ac0HwIdx); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BE DESCRIPTOR \n " )); - for (i=0;iTxRing[QID_AC_BE].Cell[i].AllocVa; - DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3))); - } - DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " )); - break; - case QID_AC_BK: - RTMP_IO_READ32(pAd, TX_BASE_PTR1, &Ac0Base); - RTMP_IO_READ32(pAd, TX_CTX_IDX1, &Ac0SwIdx); - RTMP_IO_READ32(pAd, TX_DTX_IDX1, &Ac0HwIdx); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BK DESCRIPTOR \n " )); - for (i=0;iTxRing[QID_AC_BK].Cell[i].AllocVa; - DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3))); - } - DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " )); - break; - case QID_AC_VI: - RTMP_IO_READ32(pAd, TX_BASE_PTR2, &Ac0Base); - RTMP_IO_READ32(pAd, TX_CTX_IDX2, &Ac0SwIdx); - RTMP_IO_READ32(pAd, TX_DTX_IDX2, &Ac0HwIdx); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VI DESCRIPTOR \n " )); - for (i=0;iTxRing[QID_AC_VI].Cell[i].AllocVa; - DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3))); - } - DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " )); - break; - case QID_AC_VO: - RTMP_IO_READ32(pAd, TX_BASE_PTR3, &Ac0Base); - RTMP_IO_READ32(pAd, TX_CTX_IDX3, &Ac0SwIdx); - RTMP_IO_READ32(pAd, TX_DTX_IDX3, &Ac0HwIdx); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VO DESCRIPTOR \n " )); - for (i=0;iTxRing[QID_AC_VO].Cell[i].AllocVa; - DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3))); - } - DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " )); - break; - case QID_MGMT: - RTMP_IO_READ32(pAd, TX_BASE_PTR5, &Ac0Base); - RTMP_IO_READ32(pAd, TX_CTX_IDX5, &Ac0SwIdx); - RTMP_IO_READ32(pAd, TX_DTX_IDX5, &Ac0HwIdx); - DBGPRINT_RAW(RT_DEBUG_TRACE, (" All QID_MGMT DESCRIPTOR \n " )); - for (i=0;iMgmtRing.Cell[i].AllocVa; - DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3))); - } - DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " )); - break; - - default: - DBGPRINT_ERR(("DBGPRINT_TX_RING(Ring %d) not supported\n", QueIdx)); - break; - } - AC0freeIdx = pAd->TxRing[QueIdx].TxSwFreeIdx; - - DBGPRINT(RT_DEBUG_TRACE,("TxRing%d, TX_DTX_IDX=%d, TX_CTX_IDX=%d\n", QueIdx, Ac0HwIdx, Ac0SwIdx)); - DBGPRINT_RAW(RT_DEBUG_TRACE,(" TxSwFreeIdx[%d]", AC0freeIdx)); - DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount)); - - -} - - -VOID DBGPRINT_RX_RING( - IN PRTMP_ADAPTER pAd) -{ - UINT32 Ac0Base; - UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx; -// PULONG pTxD; - int i; - UINT32 *ptemp; -// PRXD_STRUC pRxD; - - DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " )); - RTMP_IO_READ32(pAd, RX_BASE_PTR, &Ac0Base); - RTMP_IO_READ32(pAd, RX_CRX_IDX, &Ac0SwIdx); - RTMP_IO_READ32(pAd, RX_DRX_IDX, &Ac0HwIdx); - AC0freeIdx = pAd->RxRing.RxSwReadIdx; - - DBGPRINT_RAW(RT_DEBUG_TRACE, ("All RX DSP \n " )); - for (i=0;iRxRing.Cell[i].AllocVa; - DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08x: %08x: %08x: %08x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3))); - } - DBGPRINT(RT_DEBUG_TRACE,("RxRing, RX_DRX_IDX=%d, RX_CRX_IDX=%d \n", Ac0HwIdx, Ac0SwIdx)); - DBGPRINT_RAW(RT_DEBUG_TRACE,(" RxSwReadIdx [%d]=", AC0freeIdx)); - DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount)); -} - - -PNDIS_PACKET GetPacketFromRxRing( - IN PRTMP_ADAPTER pAd, - OUT PRT28XX_RXD_STRUC pSaveRxD, - OUT BOOLEAN *pbReschedule, - IN OUT UINT32 *pRxPending) -{ - PRXD_STRUC pRxD; -#ifdef RT_BIG_ENDIAN - PRXD_STRUC pDestRxD; - RXD_STRUC RxD; -#endif - PNDIS_PACKET pRxPacket = NULL; - PNDIS_PACKET pNewPacket; - PVOID AllocVa; - NDIS_PHYSICAL_ADDRESS AllocPa; - BOOLEAN bReschedule = FALSE; - - RTMP_SEM_LOCK(&pAd->RxRingLock); - - if (*pRxPending == 0) - { - // Get how may packets had been received - RTMP_IO_READ32(pAd, RX_DRX_IDX , &pAd->RxRing.RxDmaIdx); - - if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx) - { - // no more rx packets - bReschedule = FALSE; - goto done; - } - - // get rx pending count - if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx) - *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx; - else - *pRxPending = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx; - - } - -#ifdef RT_BIG_ENDIAN - pDestRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa; - RxD = *pDestRxD; - pRxD = &RxD; - RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); -#else - // Point to Rx indexed rx ring descriptor - pRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa; -#endif - - if (pRxD->DDONE == 0) - { - *pRxPending = 0; - // DMAIndx had done but DDONE bit not ready - bReschedule = TRUE; - goto done; - } - - - // return rx descriptor - NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE); - - pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa); - - if (pNewPacket) - { - // unmap the rx buffer - PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa, - pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE); - pRxPacket = pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket; - - pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE; - pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket = (PNDIS_PACKET) pNewPacket; - pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocVa = AllocVa; - pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa = AllocPa; - /* update SDP0 to new buffer of rx packet */ - pRxD->SDP0 = AllocPa; - } - else - { - //DBGPRINT(RT_DEBUG_TRACE,("No Rx Buffer\n")); - pRxPacket = NULL; - bReschedule = TRUE; - } - - pRxD->DDONE = 0; - - // had handled one rx packet - *pRxPending = *pRxPending - 1; - - // update rx descriptor and kick rx -#ifdef RT_BIG_ENDIAN - RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); - WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD); -#endif - INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); - - pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1); - RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); - -done: - RTMP_SEM_UNLOCK(&pAd->RxRingLock); - *pbReschedule = bReschedule; - return pRxPacket; -} - - -NDIS_STATUS MlmeHardTransmitTxRing( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket) -{ - PACKET_INFO PacketInfo; - PUCHAR pSrcBufVA; - UINT SrcBufLen; - PTXD_STRUC pTxD; -#ifdef RT_BIG_ENDIAN - PTXD_STRUC pDestTxD; - TXD_STRUC TxD; -#endif - PHEADER_802_11 pHeader_802_11; - BOOLEAN bAckRequired, bInsertTimestamp; - ULONG SrcBufPA; - //UCHAR TxBufIdx; - UCHAR MlmeRate; - ULONG SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; - PTXWI_STRUC pFirstTxWI; - //ULONG i; - //HTTRANSMIT_SETTING MlmeTransmit; //Rate for this MGMT frame. - ULONG FreeNum; - MAC_TABLE_ENTRY *pMacEntry = NULL; - - - RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); - - - if (pSrcBufVA == NULL) - { - // The buffer shouldn't be NULL - return NDIS_STATUS_FAILURE; - } - - // Make sure MGMT ring resource won't be used by other threads - //NdisAcquireSpinLock(&pAd->TxRingLock); - - FreeNum = GET_TXRING_FREENO(pAd, QueIdx); - - if (FreeNum == 0) - { - //NdisReleaseSpinLock(&pAd->TxRingLock); - return NDIS_STATUS_FAILURE; - } - - SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; - -#ifndef RT_BIG_ENDIAN - pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; -#else - pDestTxD = (PTXD_STRUC)pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; - TxD = *pDestTxD; - pTxD = &TxD; - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); -#endif - - if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket) - { - DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n")); - //NdisReleaseSpinLock(&pAd->TxRingLock); - return NDIS_STATUS_FAILURE; - } - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // outgoing frame always wakeup PHY to prevent frame lost - // if (pAd->StaCfg.Psm == PWR_SAVE) - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - AsicForceWakeup(pAd, TRUE); - } -#endif // CONFIG_STA_SUPPORT // - pFirstTxWI =(PTXWI_STRUC)pSrcBufVA; - - pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXWI_SIZE); - if (pHeader_802_11->Addr1[0] & 0x01) - { - MlmeRate = pAd->CommonCfg.BasicMlmeRate; - } - else - { - MlmeRate = pAd->CommonCfg.MlmeRate; - } - - if ((pHeader_802_11->FC.Type == BTYPE_DATA) && - (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) - { - pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); - } - - // Verify Mlme rate for a / g bands. - if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band - MlmeRate = RATE_6; - - // - // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) - // Snice it's been set to 0 while on MgtMacHeaderInit - // By the way this will cause frame to be send on PWR_SAVE failed. - // - // - // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame -#ifdef CONFIG_STA_SUPPORT - // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD - if (pHeader_802_11->FC.Type != BTYPE_DATA) - { - if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) - { - pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; - } - else - { - pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave; - } - } -#endif // CONFIG_STA_SUPPORT // - - bInsertTimestamp = FALSE; - if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL - { - bAckRequired = FALSE; - } - else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame) - { - if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST - { - bAckRequired = FALSE; - pHeader_802_11->Duration = 0; - } - else - { - bAckRequired = TRUE; - pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14); - if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) - { - bInsertTimestamp = TRUE; - } - } - } - pHeader_802_11->Sequence = pAd->Sequence++; - if (pAd->Sequence > 0xfff) - pAd->Sequence = 0; - // Before radar detection done, mgmt frame can not be sent but probe req - // Because we need to use probe req to trigger driver to send probe req in passive scan - if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) - && (pAd->CommonCfg.bIEEE80211H == 1) - && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) - { - DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n")); - //NdisReleaseSpinLock(&pAd->TxRingLock); - return (NDIS_STATUS_FAILURE); - } - -#ifdef RT_BIG_ENDIAN - RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE); -#endif - // - // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET - // should always has only one ohysical buffer, and the whole frame size equals - // to the first scatter buffer size - // - - // Initialize TX Descriptor - // For inter-frame gap, the number is for this frame and next frame - // For MLME rate, we will fix as 2Mb to match other vendor's implement -// pAd->CommonCfg.MlmeTransmit.field.MODE = 1; - -// management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. - // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE. - if (pMacEntry == NULL) - { - RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, - 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); - } - else - { - RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, - bInsertTimestamp, FALSE, bAckRequired, FALSE, - 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE), - pMacEntry->MaxHTPhyMode.field.MCS, 0, - (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS, - IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); - } - - pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket; - pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL; -// pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE; -#ifdef RT_BIG_ENDIAN - RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI); -#endif - SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE); - - - RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA); - pTxD->LastSec0 = 1; - pTxD->LastSec1 = 1; - pTxD->SDLen0 = SrcBufLen; - pTxD->SDLen1 = 0; - pTxD->SDPtr0 = SrcBufPA; - pTxD->DMADONE = 0; - -#ifdef RT_BIG_ENDIAN - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); -#endif - - pAd->RalinkCounters.KickTxCount++; - pAd->RalinkCounters.OneSecTxDoneCount++; - - // Increase TX_CTX_IDX, but write to register later. - INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); - - RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx); - - // Make sure to release MGMT ring resource -// NdisReleaseSpinLock(&pAd->TxRingLock); - - return NDIS_STATUS_SUCCESS; -} - - -NDIS_STATUS MlmeDataHardTransmit( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket) -{ - if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) - ) - { - return NDIS_STATUS_FAILURE; - } - - return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket); -} - - -/* - ======================================================================== - - Routine Description: - Calculates the duration which is required to transmit out frames - with given size and specified rate. - - Arguments: - pTxD Pointer to transmit descriptor - Ack Setting for Ack requirement bit - Fragment Setting for Fragment bit - RetryMode Setting for retry mode - Ifs Setting for IFS gap - Rate Setting for transmit rate - Service Setting for service - Length Frame length - TxPreamble Short or Long preamble when using CCK rates - QueIdx - 0-3, according to 802.11e/d4.4 June/2003 - - Return Value: - None - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - ======================================================================== -*/ -VOID RTMPWriteTxDescriptor( - IN PRTMP_ADAPTER pAd, - IN PTXD_STRUC pTxD, - IN BOOLEAN bWIV, - IN UCHAR QueueSEL) -{ - // - // Always use Long preamble before verifiation short preamble functionality works well. - // Todo: remove the following line if short preamble functionality works - // - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); - - pTxD->WIV = (bWIV) ? 1: 0; - pTxD->QSEL= (QueueSEL); - //RT2860c?? fixed using EDCA queue for test... We doubt Queue1 has problem. 2006-09-26 Jan - //pTxD->QSEL= FIFO_EDCA; - /* - if (pAd->bGenOneHCCA == TRUE) - pTxD->QSEL= FIFO_HCCA; - */ - pTxD->DMADONE = 0; -} diff --git a/drivers/staging/rt3090/common/cmm_info.c b/drivers/staging/rt3090/common/cmm_info.c deleted file mode 100644 index 3e51e98b474c95ae6f6ceda764ac9bd5ea1a594a..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/cmm_info.c +++ /dev/null @@ -1,3718 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - cmm_info.c - - Abstract: - - Revision History: - Who When What - --------- ---------- ---------------------------------------------- - */ - -#include -#include "../rt_config.h" - - -INT Show_SSID_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_WirelessMode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_TxBurst_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_TxPreamble_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_TxPower_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_Channel_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_BGProtection_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_RTSThreshold_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_FragThreshold_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -#ifdef DOT11_N_SUPPORT -INT Show_HtBw_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_HtMcs_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_HtGi_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_HtOpMode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_HtExtcha_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_HtMpduDensity_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_HtBaWinSize_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_HtRdg_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_HtAmsdu_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_HtAutoBa_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); -#endif // DOT11_N_SUPPORT // - -INT Show_CountryRegion_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_CountryRegionABand_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_CountryCode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -#ifdef AGGREGATION_SUPPORT -INT Show_PktAggregate_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); -#endif // AGGREGATION_SUPPORT // - -#ifdef WMM_SUPPORT -INT Show_WmmCapable_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); -#endif // WMM_SUPPORT // - -INT Show_IEEE80211H_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -#ifdef CONFIG_STA_SUPPORT -INT Show_NetworkType_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -#endif // CONFIG_STA_SUPPORT // - -INT Show_AuthMode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_EncrypType_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_DefaultKeyID_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_Key1_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_Key2_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_Key3_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_Key4_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -INT Show_WPAPSK_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf); - -static struct { - PSTRING name; - INT (*show_proc)(PRTMP_ADAPTER pAdapter, PSTRING arg); -} *PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC, RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC[] = { - {"SSID", Show_SSID_Proc}, - {"WirelessMode", Show_WirelessMode_Proc}, - {"TxBurst", Show_TxBurst_Proc}, - {"TxPreamble", Show_TxPreamble_Proc}, - {"TxPower", Show_TxPower_Proc}, - {"Channel", Show_Channel_Proc}, - {"BGProtection", Show_BGProtection_Proc}, - {"RTSThreshold", Show_RTSThreshold_Proc}, - {"FragThreshold", Show_FragThreshold_Proc}, -#ifdef DOT11_N_SUPPORT - {"HtBw", Show_HtBw_Proc}, - {"HtMcs", Show_HtMcs_Proc}, - {"HtGi", Show_HtGi_Proc}, - {"HtOpMode", Show_HtOpMode_Proc}, - {"HtExtcha", Show_HtExtcha_Proc}, - {"HtMpduDensity", Show_HtMpduDensity_Proc}, - {"HtBaWinSize", Show_HtBaWinSize_Proc}, - {"HtRdg", Show_HtRdg_Proc}, - {"HtAmsdu", Show_HtAmsdu_Proc}, - {"HtAutoBa", Show_HtAutoBa_Proc}, -#endif // DOT11_N_SUPPORT // - {"CountryRegion", Show_CountryRegion_Proc}, - {"CountryRegionABand", Show_CountryRegionABand_Proc}, - {"CountryCode", Show_CountryCode_Proc}, -#ifdef AGGREGATION_SUPPORT - {"PktAggregate", Show_PktAggregate_Proc}, -#endif - -#ifdef WMM_SUPPORT - {"WmmCapable", Show_WmmCapable_Proc}, -#endif - {"IEEE80211H", Show_IEEE80211H_Proc}, -#ifdef CONFIG_STA_SUPPORT - {"NetworkType", Show_NetworkType_Proc}, -#endif // CONFIG_STA_SUPPORT // - {"AuthMode", Show_AuthMode_Proc}, - {"EncrypType", Show_EncrypType_Proc}, - {"DefaultKeyID", Show_DefaultKeyID_Proc}, - {"Key1", Show_Key1_Proc}, - {"Key2", Show_Key2_Proc}, - {"Key3", Show_Key3_Proc}, - {"Key4", Show_Key4_Proc}, - {"WPAPSK", Show_WPAPSK_Proc}, - {NULL, NULL} -}; - -/* - ========================================================================== - Description: - Get Driver version. - - Return: - ========================================================================== -*/ -INT Set_DriverVersion_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - DBGPRINT(RT_DEBUG_TRACE, ("Driver version-%s\n", STA_DRIVER_VERSION)); -#endif // CONFIG_STA_SUPPORT // - - - return TRUE; -} - -/* - ========================================================================== - Description: - Set Country Region. - This command will not work, if the field of CountryRegion in eeprom is programmed. - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_CountryRegion_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - int retval; - -#ifdef EXT_BUILD_CHANNEL_LIST - return -EOPNOTSUPP; -#endif // EXT_BUILD_CHANNEL_LIST // - - retval = RT_CfgSetCountryRegion(pAd, arg, BAND_24G); - if (retval == FALSE) - return FALSE; - - // if set country region, driver needs to be reset - BuildChannelList(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegion_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegion)); - - return TRUE; -} - - -/* - ========================================================================== - Description: - Set Country Region for A band. - This command will not work, if the field of CountryRegion in eeprom is programmed. - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_CountryRegionABand_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - int retval; - -#ifdef EXT_BUILD_CHANNEL_LIST - return -EOPNOTSUPP; -#endif // EXT_BUILD_CHANNEL_LIST // - - retval = RT_CfgSetCountryRegion(pAd, arg, BAND_5G); - if (retval == FALSE) - return FALSE; - - // if set country region, driver needs to be reset - BuildChannelList(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegionABand_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegionForABand)); - - return TRUE; -} - - -/* - ========================================================================== - Description: - Set Wireless Mode - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_WirelessMode_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - INT success = TRUE; - - success = RT_CfgSetWirelessMode(pAd, arg); - if (success) - { - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - LONG WirelessMode = pAd->CommonCfg.PhyMode; - - RTMPSetPhyMode(pAd, WirelessMode); -#ifdef DOT11_N_SUPPORT - if (WirelessMode >= PHY_11ABGN_MIXED) - { - pAd->CommonCfg.BACapability.field.AutoBA = TRUE; - pAd->CommonCfg.REGBACapability.field.AutoBA = TRUE; - } - else - { - pAd->CommonCfg.BACapability.field.AutoBA = FALSE; - pAd->CommonCfg.REGBACapability.field.AutoBA = FALSE; - } -#endif // DOT11_N_SUPPORT // - // Set AdhocMode rates - if (pAd->StaCfg.BssType == BSS_ADHOC) - { - MlmeUpdateTxRates(pAd, FALSE, 0); - MakeIbssBeacon(pAd); // re-build BEACON frame - AsicEnableIbssSync(pAd); // copy to on-chip memory - } - } -#endif // CONFIG_STA_SUPPORT // - - // it is needed to set SSID to take effect -#ifdef DOT11_N_SUPPORT - SetCommonHT(pAd); -#endif // DOT11_N_SUPPORT // - DBGPRINT(RT_DEBUG_TRACE, ("Set_WirelessMode_Proc::(=%d)\n", pAd->CommonCfg.PhyMode)); - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("Set_WirelessMode_Proc::parameters out of range\n")); - } - - return success; -} - -/* - ========================================================================== - Description: - Set Channel - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_Channel_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - INT success = TRUE; - UCHAR Channel; - - Channel = (UCHAR) simple_strtol(arg, 0, 10); - - // check if this channel is valid - if (ChannelSanity(pAd, Channel) == TRUE) - { -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - pAd->CommonCfg.Channel = Channel; - - if (MONITOR_ON(pAd)) - { -#ifdef DOT11_N_SUPPORT - N_ChannelCheck(pAd); - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && - pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) - { - N_SetCenCh(pAd); - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - DBGPRINT(RT_DEBUG_TRACE, ("BW_40, control_channel(%d), CentralChannel(%d) \n", - pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); - } - else -#endif // DOT11_N_SUPPORT // - { - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAd->CommonCfg.Channel)); - } - } - } -#endif // CONFIG_STA_SUPPORT // - success = TRUE; - } - else - { - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - success = FALSE; -#endif // CONFIG_STA_SUPPORT // - } - - - if (success == TRUE) - DBGPRINT(RT_DEBUG_TRACE, ("Set_Channel_Proc::(Channel=%d)\n", pAd->CommonCfg.Channel)); - - return success; -} - - -/* - ========================================================================== - Description: - Set Short Slot Time Enable or Disable - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_ShortSlot_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - int retval; - - retval = RT_CfgSetShortSlot(pAd, arg); - if (retval == TRUE) - DBGPRINT(RT_DEBUG_TRACE, ("Set_ShortSlot_Proc::(ShortSlot=%d)\n", pAd->CommonCfg.bUseShortSlotTime)); - - return retval; -} - - -/* - ========================================================================== - Description: - Set Tx power - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_TxPower_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - LONG TxPower; - INT success = FALSE; - - TxPower = simple_strtol(arg, 0, 10); - if (TxPower <= 100) - { - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - pAd->CommonCfg.TxPowerDefault = TxPower; - pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; - } -#endif // CONFIG_STA_SUPPORT // - success = TRUE; - } - else - success = FALSE; - - DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPower_Proc::(TxPowerPercentage=%ld)\n", pAd->CommonCfg.TxPowerPercentage)); - - return success; -} - -/* - ========================================================================== - Description: - Set 11B/11G Protection - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_BGProtection_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - switch (simple_strtol(arg, 0, 10)) - { - case 0: //AUTO - pAd->CommonCfg.UseBGProtection = 0; - break; - case 1: //Always On - pAd->CommonCfg.UseBGProtection = 1; - break; - case 2: //Always OFF - pAd->CommonCfg.UseBGProtection = 2; - break; - default: //Invalid argument - return FALSE; - } - - - DBGPRINT(RT_DEBUG_TRACE, ("Set_BGProtection_Proc::(BGProtection=%ld)\n", pAd->CommonCfg.UseBGProtection)); - - return TRUE; -} - -/* - ========================================================================== - Description: - Set TxPreamble - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_TxPreamble_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - RT_802_11_PREAMBLE Preamble; - - Preamble = simple_strtol(arg, 0, 10); - - - switch (Preamble) - { - case Rt802_11PreambleShort: - pAd->CommonCfg.TxPreamble = Preamble; -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - MlmeSetTxPreamble(pAd, Rt802_11PreambleShort); -#endif // CONFIG_STA_SUPPORT // - break; - case Rt802_11PreambleLong: -#ifdef CONFIG_STA_SUPPORT - case Rt802_11PreambleAuto: - // if user wants AUTO, initialize to LONG here, then change according to AP's - // capability upon association. -#endif // CONFIG_STA_SUPPORT // - pAd->CommonCfg.TxPreamble = Preamble; -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - MlmeSetTxPreamble(pAd, Rt802_11PreambleLong); -#endif // CONFIG_STA_SUPPORT // - break; - default: //Invalid argument - return FALSE; - } - - DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPreamble_Proc::(TxPreamble=%ld)\n", pAd->CommonCfg.TxPreamble)); - - return TRUE; -} - -/* - ========================================================================== - Description: - Set RTS Threshold - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_RTSThreshold_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - NDIS_802_11_RTS_THRESHOLD RtsThresh; - - RtsThresh = simple_strtol(arg, 0, 10); - - if((RtsThresh > 0) && (RtsThresh <= MAX_RTS_THRESHOLD)) - pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh; -#ifdef CONFIG_STA_SUPPORT - else if (RtsThresh == 0) - pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD; -#endif // CONFIG_STA_SUPPORT // - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_RTSThreshold_Proc::(RTSThreshold=%d)\n", pAd->CommonCfg.RtsThreshold)); - - return TRUE; -} - -/* - ========================================================================== - Description: - Set Fragment Threshold - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_FragThreshold_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh; - - FragThresh = simple_strtol(arg, 0, 10); - - if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD) - { - //Illegal FragThresh so we set it to default - pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; - } - else if (FragThresh % 2 == 1) - { - // The length of each fragment shall always be an even number of octets, except for the last fragment - // of an MSDU or MMPDU, which may be either an even or an odd number of octets. - pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1); - } - else - { - pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh; - } - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (pAd->CommonCfg.FragmentThreshold == MAX_FRAG_THRESHOLD) - pAd->CommonCfg.bUseZeroToDisableFragment = TRUE; - else - pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; - } -#endif // CONFIG_STA_SUPPORT // - - DBGPRINT(RT_DEBUG_TRACE, ("Set_FragThreshold_Proc::(FragThreshold=%d)\n", pAd->CommonCfg.FragmentThreshold)); - - return TRUE; -} - -/* - ========================================================================== - Description: - Set TxBurst - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_TxBurst_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - LONG TxBurst; - - TxBurst = simple_strtol(arg, 0, 10); - if (TxBurst == 1) - pAd->CommonCfg.bEnableTxBurst = TRUE; - else if (TxBurst == 0) - pAd->CommonCfg.bEnableTxBurst = FALSE; - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_TxBurst_Proc::(TxBurst=%d)\n", pAd->CommonCfg.bEnableTxBurst)); - - return TRUE; -} - -#ifdef AGGREGATION_SUPPORT -/* - ========================================================================== - Description: - Set TxBurst - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_PktAggregate_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - LONG aggre; - - aggre = simple_strtol(arg, 0, 10); - - if (aggre == 1) - pAd->CommonCfg.bAggregationCapable = TRUE; - else if (aggre == 0) - pAd->CommonCfg.bAggregationCapable = FALSE; - else - return FALSE; //Invalid argument - - - DBGPRINT(RT_DEBUG_TRACE, ("Set_PktAggregate_Proc::(AGGRE=%d)\n", pAd->CommonCfg.bAggregationCapable)); - - return TRUE; -} -#endif - - -#ifdef INF_AMAZON_PPA -INT Set_INF_AMAZON_SE_PPA_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - ULONG aggre; - UINT status; - - aggre = simple_strtol(arg, 0, 10); - - if (aggre == 1) - { - if(pAd->PPAEnable==TRUE) - { - printk("INF_AMAZON_SE_PPA already enabled \n"); - } - else - { - if (ppa_hook_directpath_register_dev_fn) - { - UINT32 g_if_id; - - if (pAd->pDirectpathCb == NULL) - { - pAd->pDirectpathCb = (PPA_DIRECTPATH_CB *) kmalloc (sizeof(PPA_DIRECTPATH_CB), GFP_ATOMIC); - printk("Realloc memory for pDirectpathCb ??\n"); - } - - /* register callback */ - pAd->pDirectpathCb->rx_fn = NULL; - pAd->pDirectpathCb->stop_tx_fn = NULL; - pAd->pDirectpathCb->start_tx_fn = NULL; - - status = ppa_hook_directpath_register_dev_fn(&g_if_id, pAd->net_dev, pAd->pDirectpathCb, PPA_F_DIRECTPATH_ETH_IF); - - if(status==1) - { - pAd->g_if_id=g_if_id; - printk("register INF_AMAZON_SE_PPA success :ret:%d id:%d:%d\n",status,pAd->g_if_id,g_if_id); - pAd->PPAEnable=TRUE; - } - else - { - printk("register INF_AMAZON_SE_PPA fail :ret:%d\n",status); - } - - } - else - { - printk("INF_AMAZON_SE_PPA enable fail : there is no INF_AMAZON_SE_PPA module . \n"); - } - } - - - } - else if (aggre == 0) - { - if(pAd->PPAEnable==FALSE) - { - -printk("INF_AMAZON_SE_PPA already disable \n"); - } - else - { - if (ppa_hook_directpath_register_dev_fn) - { - UINT32 g_if_id; - g_if_id=pAd->g_if_id; - printk("g_if_id=%d \n",pAd->g_if_id); - status=ppa_hook_directpath_register_dev_fn(&g_if_id, pAd->net_dev, NULL, PPA_F_DIRECTPATH_DEREGISTER); - - if(status==1) - { - pAd->g_if_id=0; - printk("unregister INF_AMAZON_SE_PPA success :ret:%d\n",status); - pAd->PPAEnable=FALSE; - } - else - { - printk("unregister INF_AMAZON_SE_PPA fail :ret:%d\n",status); - } - - } - else - { - printk("INF_AMAZON_SE_PPA enable fail : there is no INF_AMAZON_SE_PPA module . \n"); - } - } - - } - else - { - printk("Invalid argument %d \n",aggre); - return FALSE; //Invalid argument - } - - return TRUE; - -} -#endif // INF_AMAZON_PPA // - - -/* - ========================================================================== - Description: - Set IEEE80211H. - This parameter is 1 when needs radar detection, otherwise 0 - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_IEEE80211H_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - LONG ieee80211h; - - ieee80211h = simple_strtol(arg, 0, 10); - - if (ieee80211h == 1) - pAd->CommonCfg.bIEEE80211H = TRUE; - else if (ieee80211h == 0) - pAd->CommonCfg.bIEEE80211H = FALSE; - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_IEEE80211H_Proc::(IEEE80211H=%d)\n", pAd->CommonCfg.bIEEE80211H)); - - return TRUE; -} - - -#ifdef DBG -/* - ========================================================================== - Description: - For Debug information - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_Debug_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - DBGPRINT(RT_DEBUG_TRACE, ("==> Set_Debug_Proc *******************\n")); - - if(simple_strtol(arg, 0, 10) <= RT_DEBUG_LOUD) - RTDebugLevel = simple_strtol(arg, 0, 10); - - DBGPRINT(RT_DEBUG_TRACE, ("<== Set_Debug_Proc(RTDebugLevel = %ld)\n", RTDebugLevel)); - - return TRUE; -} -#endif - -INT Show_DescInfo_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ -#ifdef RTMP_MAC_PCI - INT i, QueIdx=0; -// ULONG RegValue; - PRT28XX_RXD_STRUC pRxD; - PTXD_STRUC pTxD; - PRTMP_TX_RING pTxRing = &pAd->TxRing[QueIdx]; - PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; - PRTMP_RX_RING pRxRing = &pAd->RxRing; - - for(i=0;iCell[i].AllocVa; - DBGPRINT(RT_DEBUG_OFF, ("Desc #%d\n",i)); - hex_dump("Tx Descriptor", (PUCHAR)pTxD, 16); - DBGPRINT(RT_DEBUG_OFF, ("pTxD->DMADONE = %x\n", pTxD->DMADONE)); - } - DBGPRINT(RT_DEBUG_OFF, ("---------------------------------------------------\n")); - for(i=0;iCell[i].AllocVa; - DBGPRINT(RT_DEBUG_OFF, ("Desc #%d\n",i)); - hex_dump("Mgmt Descriptor", (PUCHAR)pTxD, 16); - DBGPRINT(RT_DEBUG_OFF, ("pMgmt->DMADONE = %x\n", pTxD->DMADONE)); - } - DBGPRINT(RT_DEBUG_OFF, ("---------------------------------------------------\n")); - for(i=0;iCell[i].AllocVa; - DBGPRINT(RT_DEBUG_OFF, ("Desc #%d\n",i)); - hex_dump("Rx Descriptor", (PUCHAR)pRxD, 16); - DBGPRINT(RT_DEBUG_OFF, ("pRxD->DDONE = %x\n", pRxD->DDONE)); - } -#endif // RTMP_MAC_PCI // - - return TRUE; -} - -/* - ========================================================================== - Description: - Reset statistics counter - - Arguments: - pAdapter Pointer to our adapter - arg - - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_ResetStatCounter_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - //UCHAR i; - //MAC_TABLE_ENTRY *pEntry; - - DBGPRINT(RT_DEBUG_TRACE, ("==>Set_ResetStatCounter_Proc\n")); - - // add the most up-to-date h/w raw counters into software counters - NICUpdateRawCounters(pAd); - - NdisZeroMemory(&pAd->WlanCounters, sizeof(COUNTER_802_11)); - NdisZeroMemory(&pAd->Counters8023, sizeof(COUNTER_802_3)); - NdisZeroMemory(&pAd->RalinkCounters, sizeof(COUNTER_RALINK)); - - // Reset HotSpot counter - - - return TRUE; -} - -/* - ======================================================================== - - Routine Description: - Add WPA key process. - In Adhoc WPANONE, bPairwise = 0; KeyIdx = 0; - - Arguments: - pAd Pointer to our adapter - pBuf Pointer to the where the key stored - - Return Value: - NDIS_SUCCESS Add key successfully - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ - -BOOLEAN RTMPCheckStrPrintAble( - IN CHAR *pInPutStr, - IN UCHAR strLen) -{ - UCHAR i=0; - - for (i=0; i 0x7E)) - return FALSE; - } - - return TRUE; -} - -/* - ======================================================================== - - Routine Description: - Remove WPA Key process - - Arguments: - pAd Pointer to our adapter - pBuf Pointer to the where the key stored - - Return Value: - NDIS_SUCCESS Add key successfully - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -#ifdef CONFIG_STA_SUPPORT -VOID RTMPSetDesiredRates( - IN PRTMP_ADAPTER pAdapter, - IN LONG Rates) -{ - NDIS_802_11_RATES aryRates; - - memset(&aryRates, 0x00, sizeof(NDIS_802_11_RATES)); - switch (pAdapter->CommonCfg.PhyMode) - { - case PHY_11A: // A only - switch (Rates) - { - case 6000000: //6M - aryRates[0] = 0x0c; // 6M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; - break; - case 9000000: //9M - aryRates[0] = 0x12; // 9M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; - break; - case 12000000: //12M - aryRates[0] = 0x18; // 12M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; - break; - case 18000000: //18M - aryRates[0] = 0x24; // 18M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; - break; - case 24000000: //24M - aryRates[0] = 0x30; // 24M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_4; - break; - case 36000000: //36M - aryRates[0] = 0x48; // 36M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_5; - break; - case 48000000: //48M - aryRates[0] = 0x60; // 48M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_6; - break; - case 54000000: //54M - aryRates[0] = 0x6c; // 54M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_7; - break; - case -1: //Auto - default: - aryRates[0] = 0x6c; // 54Mbps - aryRates[1] = 0x60; // 48Mbps - aryRates[2] = 0x48; // 36Mbps - aryRates[3] = 0x30; // 24Mbps - aryRates[4] = 0x24; // 18M - aryRates[5] = 0x18; // 12M - aryRates[6] = 0x12; // 9M - aryRates[7] = 0x0c; // 6M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; - break; - } - break; - case PHY_11BG_MIXED: // B/G Mixed - case PHY_11B: // B only - case PHY_11ABG_MIXED: // A/B/G Mixed - default: - switch (Rates) - { - case 1000000: //1M - aryRates[0] = 0x02; - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; - break; - case 2000000: //2M - aryRates[0] = 0x04; - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; - break; - case 5000000: //5.5M - aryRates[0] = 0x0b; // 5.5M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; - break; - case 11000000: //11M - aryRates[0] = 0x16; // 11M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; - break; - case 6000000: //6M - aryRates[0] = 0x0c; // 6M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; - break; - case 9000000: //9M - aryRates[0] = 0x12; // 9M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; - break; - case 12000000: //12M - aryRates[0] = 0x18; // 12M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; - break; - case 18000000: //18M - aryRates[0] = 0x24; // 18M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; - break; - case 24000000: //24M - aryRates[0] = 0x30; // 24M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_4; - break; - case 36000000: //36M - aryRates[0] = 0x48; // 36M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_5; - break; - case 48000000: //48M - aryRates[0] = 0x60; // 48M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_6; - break; - case 54000000: //54M - aryRates[0] = 0x6c; // 54M - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_7; - break; - case -1: //Auto - default: - if (pAdapter->CommonCfg.PhyMode == PHY_11B) - { //B Only - aryRates[0] = 0x16; // 11Mbps - aryRates[1] = 0x0b; // 5.5Mbps - aryRates[2] = 0x04; // 2Mbps - aryRates[3] = 0x02; // 1Mbps - } - else - { //(B/G) Mixed or (A/B/G) Mixed - aryRates[0] = 0x6c; // 54Mbps - aryRates[1] = 0x60; // 48Mbps - aryRates[2] = 0x48; // 36Mbps - aryRates[3] = 0x30; // 24Mbps - aryRates[4] = 0x16; // 11Mbps - aryRates[5] = 0x0b; // 5.5Mbps - aryRates[6] = 0x04; // 2Mbps - aryRates[7] = 0x02; // 1Mbps - } - pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; - break; - } - break; - } - - NdisZeroMemory(pAdapter->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); - NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES)); - DBGPRINT(RT_DEBUG_TRACE, (" RTMPSetDesiredRates (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n", - pAdapter->CommonCfg.DesireRate[0],pAdapter->CommonCfg.DesireRate[1], - pAdapter->CommonCfg.DesireRate[2],pAdapter->CommonCfg.DesireRate[3], - pAdapter->CommonCfg.DesireRate[4],pAdapter->CommonCfg.DesireRate[5], - pAdapter->CommonCfg.DesireRate[6],pAdapter->CommonCfg.DesireRate[7] )); - // Changing DesiredRate may affect the MAX TX rate we used to TX frames out - MlmeUpdateTxRates(pAdapter, FALSE, 0); -} - -NDIS_STATUS RTMPWPARemoveKeyProc( - IN PRTMP_ADAPTER pAd, - IN PVOID pBuf) -{ - PNDIS_802_11_REMOVE_KEY pKey; - ULONG KeyIdx; - NDIS_STATUS Status = NDIS_STATUS_FAILURE; - BOOLEAN bTxKey; // Set the key as transmit key - BOOLEAN bPairwise; // Indicate the key is pairwise key - BOOLEAN bKeyRSC; // indicate the receive SC set by KeyRSC value. - // Otherwise, it will set by the NIC. - BOOLEAN bAuthenticator; // indicate key is set by authenticator. - INT i; - - DBGPRINT(RT_DEBUG_TRACE,("---> RTMPWPARemoveKeyProc\n")); - - pKey = (PNDIS_802_11_REMOVE_KEY) pBuf; - KeyIdx = pKey->KeyIndex & 0xff; - // Bit 31 of Add-key, Tx Key - bTxKey = (pKey->KeyIndex & 0x80000000) ? TRUE : FALSE; - // Bit 30 of Add-key PairwiseKey - bPairwise = (pKey->KeyIndex & 0x40000000) ? TRUE : FALSE; - // Bit 29 of Add-key KeyRSC - bKeyRSC = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE; - // Bit 28 of Add-key Authenticator - bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE; - - // 1. If bTx is TRUE, return failure information - if (bTxKey == TRUE) - return(NDIS_STATUS_INVALID_DATA); - - // 2. Check Pairwise Key - if (bPairwise) - { - // a. If BSSID is broadcast, remove all pairwise keys. - // b. If not broadcast, remove the pairwise specified by BSSID - for (i = 0; i < SHARE_KEY_NUM; i++) - { - if (MAC_ADDR_EQUAL(pAd->SharedKey[BSS0][i].BssId, pKey->BSSID)) - { - DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%d)\n", i)); - pAd->SharedKey[BSS0][i].KeyLen = 0; - pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_NONE; - AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)i); - Status = NDIS_STATUS_SUCCESS; - break; - } - } - } - // 3. Group Key - else - { - // a. If BSSID is broadcast, remove all group keys indexed - // b. If BSSID matched, delete the group key indexed. - DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%ld)\n", KeyIdx)); - pAd->SharedKey[BSS0][KeyIdx].KeyLen = 0; - pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE; - AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)KeyIdx); - Status = NDIS_STATUS_SUCCESS; - } - - return (Status); -} -#endif // CONFIG_STA_SUPPORT // - - -#ifdef CONFIG_STA_SUPPORT -/* - ======================================================================== - - Routine Description: - Remove All WPA Keys - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPWPARemoveAllKeys( - IN PRTMP_ADAPTER pAd) -{ - - UCHAR i; - - DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveAllKeys(AuthMode=%d, WepStatus=%d)\n", pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus)); - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); - // For WEP/CKIP, there is no need to remove it, since WinXP won't set it again after - // Link up. And it will be replaced if user changed it. - if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) - return; - - // For WPA-None, there is no need to remove it, since WinXP won't set it again after - // Link up. And it will be replaced if user changed it. - if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - return; - - // set BSSID wcid entry of the Pair-wise Key table as no-security mode - AsicRemovePairwiseKeyEntry(pAd, BSS0, BSSID_WCID); - - // set all shared key mode as no-security. - for (i = 0; i < SHARE_KEY_NUM; i++) - { - DBGPRINT(RT_DEBUG_TRACE,("remove %s key #%d\n", CipherName[pAd->SharedKey[BSS0][i].CipherAlg], i)); - NdisZeroMemory(&pAd->SharedKey[BSS0][i], sizeof(CIPHER_KEY)); - - AsicRemoveSharedKeyEntry(pAd, BSS0, i); - } - RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); - -} -#endif // CONFIG_STA_SUPPORT // - - -/* - ======================================================================== - - Routine Description: - As STA's BSSID is a WC too, it uses shared key table. - This function write correct unicast TX key to ASIC WCID. - And we still make a copy in our MacTab.Content[BSSID_WCID].PairwiseKey. - Caller guarantee TKIP/AES always has keyidx = 0. (pairwise key) - Caller guarantee WEP calls this function when set Txkey, default key index=0~3. - - Arguments: - pAd Pointer to our adapter - pKey Pointer to the where the key stored - - Return Value: - NDIS_SUCCESS Add key successfully - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -/* - ======================================================================== - Routine Description: - Change NIC PHY mode. Re-association may be necessary. possible settings - include - PHY_11B, PHY_11BG_MIXED, PHY_11A, and PHY_11ABG_MIXED - - Arguments: - pAd - Pointer to our adapter - phymode - - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - ======================================================================== -*/ -VOID RTMPSetPhyMode( - IN PRTMP_ADAPTER pAd, - IN ULONG phymode) -{ - INT i; - // the selected phymode must be supported by the RF IC encoded in E2PROM - - // if no change, do nothing - /* bug fix - if (pAd->CommonCfg.PhyMode == phymode) - return; - */ - pAd->CommonCfg.PhyMode = (UCHAR)phymode; - - DBGPRINT(RT_DEBUG_TRACE,("RTMPSetPhyMode : PhyMode=%d, channel=%d \n", pAd->CommonCfg.PhyMode, pAd->CommonCfg.Channel)); -#ifdef EXT_BUILD_CHANNEL_LIST - BuildChannelListEx(pAd); -#else - BuildChannelList(pAd); -#endif // EXT_BUILD_CHANNEL_LIST // - - // sanity check user setting - for (i = 0; i < pAd->ChannelListNum; i++) - { - if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel) - break; - } - - if (i == pAd->ChannelListNum) - { -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - pAd->CommonCfg.Channel = FirstChannel(pAd); -#endif // CONFIG_STA_SUPPORT // - DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetPhyMode: channel is out of range, use first channel=%d \n", pAd->CommonCfg.Channel)); - } - - NdisZeroMemory(pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); - NdisZeroMemory(pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES); - NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); - switch (phymode) { - case PHY_11B: - pAd->CommonCfg.SupRate[0] = 0x82; // 1 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[1] = 0x84; // 2 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[2] = 0x8B; // 5.5 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[3] = 0x96; // 11 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRateLen = 4; - pAd->CommonCfg.ExtRateLen = 0; - pAd->CommonCfg.DesireRate[0] = 2; // 1 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[1] = 4; // 2 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[2] = 11; // 5.5 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[3] = 22; // 11 mbps, in units of 0.5 Mbps - //pAd->CommonCfg.HTPhyMode.field.MODE = MODE_CCK; // This MODE is only FYI. not use - break; - - case PHY_11G: - case PHY_11BG_MIXED: - case PHY_11ABG_MIXED: -#ifdef DOT11_N_SUPPORT - case PHY_11N_2_4G: - case PHY_11ABGN_MIXED: - case PHY_11BGN_MIXED: - case PHY_11GN_MIXED: -#endif // DOT11_N_SUPPORT // - pAd->CommonCfg.SupRate[0] = 0x82; // 1 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[1] = 0x84; // 2 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[2] = 0x8B; // 5.5 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[3] = 0x96; // 11 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[4] = 0x12; // 9 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRate[5] = 0x24; // 18 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRate[6] = 0x48; // 36 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRateLen = 8; - pAd->CommonCfg.ExtRate[0] = 0x0C; // 6 mbps, in units of 0.5 Mbps - pAd->CommonCfg.ExtRate[1] = 0x18; // 12 mbps, in units of 0.5 Mbps - pAd->CommonCfg.ExtRate[2] = 0x30; // 24 mbps, in units of 0.5 Mbps - pAd->CommonCfg.ExtRate[3] = 0x60; // 48 mbps, in units of 0.5 Mbps - pAd->CommonCfg.ExtRateLen = 4; - pAd->CommonCfg.DesireRate[0] = 2; // 1 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[1] = 4; // 2 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[2] = 11; // 5.5 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[3] = 22; // 11 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[4] = 12; // 6 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[5] = 18; // 9 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[6] = 24; // 12 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[7] = 36; // 18 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[8] = 48; // 24 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[9] = 72; // 36 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[10] = 96; // 48 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[11] = 108; // 54 mbps, in units of 0.5 Mbps - break; - - case PHY_11A: -#ifdef DOT11_N_SUPPORT - case PHY_11AN_MIXED: - case PHY_11AGN_MIXED: - case PHY_11N_5G: -#endif // DOT11_N_SUPPORT // - pAd->CommonCfg.SupRate[0] = 0x8C; // 6 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRate[2] = 0x98; // 12 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRate[4] = 0xb0; // 24 mbps, in units of 0.5 Mbps, basic rate - pAd->CommonCfg.SupRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps - pAd->CommonCfg.SupRateLen = 8; - pAd->CommonCfg.ExtRateLen = 0; - pAd->CommonCfg.DesireRate[0] = 12; // 6 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[1] = 18; // 9 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[2] = 24; // 12 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[3] = 36; // 18 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[4] = 48; // 24 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[5] = 72; // 36 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[6] = 96; // 48 mbps, in units of 0.5 Mbps - pAd->CommonCfg.DesireRate[7] = 108; // 54 mbps, in units of 0.5 Mbps - //pAd->CommonCfg.HTPhyMode.field.MODE = MODE_OFDM; // This MODE is only FYI. not use - break; - - default: - break; - } - - - pAd->CommonCfg.BandState = UNKNOWN_BAND; -} - - -#ifdef DOT11_N_SUPPORT -/* - ======================================================================== - Routine Description: - Caller ensures we has 802.11n support. - Calls at setting HT from AP/STASetinformation - - Arguments: - pAd - Pointer to our adapter - phymode - - - ======================================================================== -*/ -VOID RTMPSetHT( - IN PRTMP_ADAPTER pAd, - IN OID_SET_HT_PHYMODE *pHTPhyMode) -{ - //ULONG *pmcs; - UINT32 Value = 0; - UCHAR BBPValue = 0; - UCHAR BBP3Value = 0; - UCHAR RxStream = pAd->CommonCfg.RxStream; - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : HT_mode(%d), ExtOffset(%d), MCS(%d), BW(%d), STBC(%d), SHORTGI(%d)\n", - pHTPhyMode->HtMode, pHTPhyMode->ExtOffset, - pHTPhyMode->MCS, pHTPhyMode->BW, - pHTPhyMode->STBC, pHTPhyMode->SHORTGI)); - - // Don't zero supportedHyPhy structure. - RTMPZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability)); - RTMPZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo)); - RTMPZeroMemory(&pAd->CommonCfg.NewExtChanOffset, sizeof(pAd->CommonCfg.NewExtChanOffset)); - RTMPZeroMemory(&pAd->CommonCfg.DesiredHtPhy, sizeof(pAd->CommonCfg.DesiredHtPhy)); - - if (pAd->CommonCfg.bRdg) - { - pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 1; - pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 1; - } - else - { - pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 0; - pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 0; - } - - pAd->CommonCfg.HtCapability.HtCapParm.MaxRAmpduFactor = 3; - pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor = 3; - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : RxBAWinLimit = %d\n", pAd->CommonCfg.BACapability.field.RxBAWinLimit)); - - // Mimo power save, A-MSDU size, - pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable; - pAd->CommonCfg.DesiredHtPhy.AmsduSize = (UCHAR)pAd->CommonCfg.BACapability.field.AmsduSize; - pAd->CommonCfg.DesiredHtPhy.MimoPs = (UCHAR)pAd->CommonCfg.BACapability.field.MMPSmode; - pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; - - pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; - pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; - pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : AMsduSize = %d, MimoPs = %d, MpduDensity = %d, MaxRAmpduFactor = %d\n", - pAd->CommonCfg.DesiredHtPhy.AmsduSize, - pAd->CommonCfg.DesiredHtPhy.MimoPs, - pAd->CommonCfg.DesiredHtPhy.MpduDensity, - pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor)); - - if(pHTPhyMode->HtMode == HTMODE_GF) - { - pAd->CommonCfg.HtCapability.HtCapInfo.GF = 1; - pAd->CommonCfg.DesiredHtPhy.GF = 1; - } - else - pAd->CommonCfg.DesiredHtPhy.GF = 0; - - // Decide Rx MCSSet - switch (RxStream) - { - case 1: - pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; - pAd->CommonCfg.HtCapability.MCSSet[1] = 0x00; - break; - - case 2: - pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; - pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff; - break; - - case 3: // 3*3 - pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; - pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff; - pAd->CommonCfg.HtCapability.MCSSet[2] = 0xff; - break; - } - - if (pAd->CommonCfg.bForty_Mhz_Intolerant && (pAd->CommonCfg.Channel <= 14) && (pHTPhyMode->BW == BW_40) ) - { - pHTPhyMode->BW = BW_20; - pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant = 1; - } - - if(pHTPhyMode->BW == BW_40) - { - pAd->CommonCfg.HtCapability.MCSSet[4] = 0x1; // MCS 32 - pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 1; - if (pAd->CommonCfg.Channel <= 14) - pAd->CommonCfg.HtCapability.HtCapInfo.CCKmodein40 = 1; - - pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 1; - pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 1; - pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = (pHTPhyMode->ExtOffset == EXTCHA_BELOW)? (EXTCHA_BELOW): EXTCHA_ABOVE; - // Set Regsiter for extension channel position. - RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBP3Value); - if ((pHTPhyMode->ExtOffset == EXTCHA_BELOW)) - { - Value |= 0x1; - BBP3Value |= (0x20); - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); - } - else if ((pHTPhyMode->ExtOffset == EXTCHA_ABOVE)) - { - Value &= 0xfe; - BBP3Value &= (~0x20); - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); - } - - // Turn on BBP 40MHz mode now only as AP . - // Sta can turn on BBP 40MHz after connection with 40MHz AP. Sta only broadcast 40MHz capability before connection. - if ((pAd->OpMode == OPMODE_AP) || INFRA_ON(pAd) || ADHOC_ON(pAd) - ) - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue &= (~0x18); - BBPValue |= 0x10; - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBP3Value); - pAd->CommonCfg.BBPCurrentBW = BW_40; - } - } - else - { - pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 0; - pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 0; - pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; - pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = EXTCHA_NONE; - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; - // Turn on BBP 20MHz mode by request here. - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue &= (~0x18); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - pAd->CommonCfg.BBPCurrentBW = BW_20; - } - } - - if(pHTPhyMode->STBC == STBC_USE) - { - pAd->CommonCfg.HtCapability.HtCapInfo.TxSTBC = 1; - pAd->CommonCfg.DesiredHtPhy.TxSTBC = 1; - pAd->CommonCfg.HtCapability.HtCapInfo.RxSTBC = 1; - pAd->CommonCfg.DesiredHtPhy.RxSTBC = 1; - } - else - { - pAd->CommonCfg.DesiredHtPhy.TxSTBC = 0; - pAd->CommonCfg.DesiredHtPhy.RxSTBC = 0; - } - - if(pHTPhyMode->SHORTGI == GI_400) - { - pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 1; - pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 1; - pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 1; - pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 1; - } - else - { - pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 0; - pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 0; - pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 0; - pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 0; - } - - // We support link adaptation for unsolicit MCS feedback, set to 2. - pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_NONE; //MCSFBK_UNSOLICIT; - pAd->CommonCfg.AddHTInfo.ControlChan = pAd->CommonCfg.Channel; - // 1, the extension channel above the control channel. - - // EDCA parameters used for AP's own transmission - if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) - { - pAd->CommonCfg.APEdcaParm.bValid = TRUE; - pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; - pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; - pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; - pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; - - pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; - pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; - pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; - pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; - - pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6; - pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10; - pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; - pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; - - pAd->CommonCfg.APEdcaParm.Txop[0] = 0; - pAd->CommonCfg.APEdcaParm.Txop[1] = 0; - pAd->CommonCfg.APEdcaParm.Txop[2] = 94; - pAd->CommonCfg.APEdcaParm.Txop[3] = 47; - } - AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - RTMPSetIndividualHT(pAd, 0); - } -#endif // CONFIG_STA_SUPPORT // - -} - -/* - ======================================================================== - Routine Description: - Caller ensures we has 802.11n support. - Calls at setting HT from AP/STASetinformation - - Arguments: - pAd - Pointer to our adapter - phymode - - - ======================================================================== -*/ -VOID RTMPSetIndividualHT( - IN PRTMP_ADAPTER pAd, - IN UCHAR apidx) -{ - PRT_HT_PHY_INFO pDesired_ht_phy = NULL; - UCHAR TxStream = pAd->CommonCfg.TxStream; - UCHAR DesiredMcs = MCS_AUTO; - - do - { - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - pDesired_ht_phy = &pAd->StaCfg.DesiredHtPhyInfo; - DesiredMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS; - //pAd->StaCfg.bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; - break; - } -#endif // CONFIG_STA_SUPPORT // - } while (FALSE); - - if (pDesired_ht_phy == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx)); - return; - } - RTMPZeroMemory(pDesired_ht_phy, sizeof(RT_HT_PHY_INFO)); - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetIndividualHT : Desired MCS = %d\n", DesiredMcs)); - // Check the validity of MCS - if ((TxStream == 1) && ((DesiredMcs >= MCS_8) && (DesiredMcs <= MCS_15))) - { - DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS(%d) is invalid in 1S, reset it as MCS_7\n", DesiredMcs)); - DesiredMcs = MCS_7; - } - - if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_20) && (DesiredMcs == MCS_32)) - { - DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS_32 is only supported in 40-MHz, reset it as MCS_0\n")); - DesiredMcs = MCS_0; - } - - pDesired_ht_phy->bHtEnable = TRUE; - - // Decide desired Tx MCS - switch (TxStream) - { - case 1: - if (DesiredMcs == MCS_AUTO) - { - pDesired_ht_phy->MCSSet[0]= 0xff; - pDesired_ht_phy->MCSSet[1]= 0x00; - } - else if (DesiredMcs <= MCS_7) - { - pDesired_ht_phy->MCSSet[0]= 1<MCSSet[1]= 0x00; - } - break; - - case 2: - if (DesiredMcs == MCS_AUTO) - { - pDesired_ht_phy->MCSSet[0]= 0xff; - pDesired_ht_phy->MCSSet[1]= 0xff; - } - else if (DesiredMcs <= MCS_15) - { - ULONG mode; - - mode = DesiredMcs / 8; - if (mode < 2) - pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8)); - } - break; - - case 3: // 3*3 - if (DesiredMcs == MCS_AUTO) - { - /* MCS0 ~ MCS23, 3 bytes */ - pDesired_ht_phy->MCSSet[0]= 0xff; - pDesired_ht_phy->MCSSet[1]= 0xff; - pDesired_ht_phy->MCSSet[2]= 0xff; - } - else if (DesiredMcs <= MCS_23) - { - ULONG mode; - - mode = DesiredMcs / 8; - if (mode < 3) - pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8)); - } - break; - } - - if(pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_40) - { - if (DesiredMcs == MCS_AUTO || DesiredMcs == MCS_32) - pDesired_ht_phy->MCSSet[4] = 0x1; - } - - // update HT Rate setting - if (pAd->OpMode == OPMODE_STA) - MlmeUpdateHtTxRates(pAd, BSS0); - else - MlmeUpdateHtTxRates(pAd, apidx); -} - - -/* - ======================================================================== - Routine Description: - Update HT IE from our capability. - - Arguments: - Send all HT IE in beacon/probe rsp/assoc rsp/action frame. - - - ======================================================================== -*/ -VOID RTMPUpdateHTIE( - IN RT_HT_CAPABILITY *pRtHt, - IN UCHAR *pMcsSet, - OUT HT_CAPABILITY_IE *pHtCapability, - OUT ADD_HT_INFO_IE *pAddHtInfo) -{ - RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE)); - RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE)); - - pHtCapability->HtCapInfo.ChannelWidth = pRtHt->ChannelWidth; - pHtCapability->HtCapInfo.MimoPs = pRtHt->MimoPs; - pHtCapability->HtCapInfo.GF = pRtHt->GF; - pHtCapability->HtCapInfo.ShortGIfor20 = pRtHt->ShortGIfor20; - pHtCapability->HtCapInfo.ShortGIfor40 = pRtHt->ShortGIfor40; - pHtCapability->HtCapInfo.TxSTBC = pRtHt->TxSTBC; - pHtCapability->HtCapInfo.RxSTBC = pRtHt->RxSTBC; - pHtCapability->HtCapInfo.AMsduSize = pRtHt->AmsduSize; - pHtCapability->HtCapParm.MaxRAmpduFactor = pRtHt->MaxRAmpduFactor; - pHtCapability->HtCapParm.MpduDensity = pRtHt->MpduDensity; - - pAddHtInfo->AddHtInfo.ExtChanOffset = pRtHt->ExtChanOffset ; - pAddHtInfo->AddHtInfo.RecomWidth = pRtHt->RecomWidth; - pAddHtInfo->AddHtInfo2.OperaionMode = pRtHt->OperaionMode; - pAddHtInfo->AddHtInfo2.NonGfPresent = pRtHt->NonGfPresent; - RTMPMoveMemory(pAddHtInfo->MCSSet, /*pRtHt->MCSSet*/pMcsSet, 4); // rt2860 only support MCS max=32, no need to copy all 16 uchar. - - DBGPRINT(RT_DEBUG_TRACE,("RTMPUpdateHTIE <== \n")); -} -#endif // DOT11_N_SUPPORT // - -/* - ======================================================================== - Description: - Add Client security information into ASIC WCID table and IVEIV table. - Return: - ======================================================================== -*/ -VOID RTMPAddWcidAttributeEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIdx, - IN UCHAR KeyIdx, - IN UCHAR CipherAlg, - IN MAC_TABLE_ENTRY *pEntry) -{ - UINT32 WCIDAttri = 0; - USHORT offset; - UCHAR IVEIV = 0; - USHORT Wcid = 0; - - { -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (BssIdx > BSS0) - { - DBGPRINT(RT_DEBUG_ERROR, ("RTMPAddWcidAttributeEntry: The BSS-index(%d) is out of range for Infra link. \n", BssIdx)); - return; - } - - // 1. In ADHOC mode, the AID is wcid number. And NO mesh link exists. - // 2. In Infra mode, the AID:1 MUST be wcid of infra STA. - // the AID:2~ assign to mesh link entry. - if (pEntry) - Wcid = pEntry->Aid; - else - Wcid = MCAST_WCID; - } -#endif // CONFIG_STA_SUPPORT // - } - - // Update WCID attribute table - offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE); - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (pEntry && pEntry->ValidAsMesh) - WCIDAttri = (CipherAlg<<1) | PAIRWISEKEYTABLE; -#ifdef QOS_DLS_SUPPORT - else if ((pEntry) && (pEntry->ValidAsDls) && - ((CipherAlg == CIPHER_TKIP) || - (CipherAlg == CIPHER_TKIP_NO_MIC) || - (CipherAlg == CIPHER_AES) || - (CipherAlg == CIPHER_NONE))) - WCIDAttri = (CipherAlg<<1) | PAIRWISEKEYTABLE; -#endif // QOS_DLS_SUPPORT // - else - WCIDAttri = (CipherAlg<<1) | SHAREDKEYTABLE; - } -#endif // CONFIG_STA_SUPPORT // - - RTMP_IO_WRITE32(pAd, offset, WCIDAttri); - - - // Update IV/EIV table - offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_SIZE); - - // WPA mode - if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) || (CipherAlg == CIPHER_AES)) - { - // Eiv bit on. keyid always is 0 for pairwise key - IVEIV = (KeyIdx <<6) | 0x20; - } - else - { - // WEP KeyIdx is default tx key. - IVEIV = (KeyIdx << 6); - } - - // For key index and ext IV bit, so only need to update the position(offset+3). -#ifdef RTMP_MAC_PCI - RTMP_IO_WRITE8(pAd, offset+3, IVEIV); -#endif // RTMP_MAC_PCI // - - DBGPRINT(RT_DEBUG_TRACE,("RTMPAddWcidAttributeEntry: WCID #%d, KeyIndex #%d, Alg=%s\n",Wcid, KeyIdx, CipherName[CipherAlg])); - DBGPRINT(RT_DEBUG_TRACE,(" WCIDAttri = 0x%x \n", WCIDAttri)); - -} - -/* - ========================================================================== - Description: - Parse encryption type -Arguments: - pAdapter Pointer to our adapter - wrq Pointer to the ioctl argument - - Return Value: - None - - Note: - ========================================================================== -*/ -PSTRING GetEncryptType(CHAR enc) -{ - if(enc == Ndis802_11WEPDisabled) - return "NONE"; - if(enc == Ndis802_11WEPEnabled) - return "WEP"; - if(enc == Ndis802_11Encryption2Enabled) - return "TKIP"; - if(enc == Ndis802_11Encryption3Enabled) - return "AES"; - if(enc == Ndis802_11Encryption4Enabled) - return "TKIPAES"; - else - return "UNKNOW"; -} - -PSTRING GetAuthMode(CHAR auth) -{ - if(auth == Ndis802_11AuthModeOpen) - return "OPEN"; - if(auth == Ndis802_11AuthModeShared) - return "SHARED"; - if(auth == Ndis802_11AuthModeAutoSwitch) - return "AUTOWEP"; - if(auth == Ndis802_11AuthModeWPA) - return "WPA"; - if(auth == Ndis802_11AuthModeWPAPSK) - return "WPAPSK"; - if(auth == Ndis802_11AuthModeWPANone) - return "WPANONE"; - if(auth == Ndis802_11AuthModeWPA2) - return "WPA2"; - if(auth == Ndis802_11AuthModeWPA2PSK) - return "WPA2PSK"; - if(auth == Ndis802_11AuthModeWPA1WPA2) - return "WPA1WPA2"; - if(auth == Ndis802_11AuthModeWPA1PSKWPA2PSK) - return "WPA1PSKWPA2PSK"; - - return "UNKNOW"; -} - - -/* - ========================================================================== - Description: - Get site survey results - Arguments: - pAdapter Pointer to our adapter - wrq Pointer to the ioctl argument - - Return Value: - None - - Note: - Usage: - 1.) UI needs to wait 4 seconds after issue a site survey command - 2.) iwpriv ra0 get_site_survey - 3.) UI needs to prepare at least 4096bytes to get the results - ========================================================================== -*/ -#define LINE_LEN (4+33+20+23+9+7+3) // Channel+SSID+Bssid+Security+Signal+WiressMode+NetworkType -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // -VOID RTMPCommSiteSurveyData( - IN PSTRING msg, - IN PBSS_ENTRY pBss) -{ - INT Rssi = 0; - UINT Rssi_Quality = 0; - NDIS_802_11_NETWORK_TYPE wireless_mode; - CHAR Ssid[MAX_LEN_OF_SSID +1]; - STRING SecurityStr[32] = {0}; - NDIS_802_11_ENCRYPTION_STATUS ap_cipher = Ndis802_11EncryptionDisabled; - NDIS_802_11_AUTHENTICATION_MODE ap_auth_mode = Ndis802_11AuthModeOpen; - - memset(Ssid, 0 ,(MAX_LEN_OF_SSID +1)); - - //Channel - sprintf(msg+strlen(msg),"%-4d", pBss->Channel); - //SSID - memcpy(Ssid, pBss->Ssid, pBss->SsidLen); - Ssid[pBss->SsidLen] = '\0'; - sprintf(msg+strlen(msg),"%-33s", Ssid); - //BSSID - sprintf(msg+strlen(msg),"%02x:%02x:%02x:%02x:%02x:%02x ", - pBss->Bssid[0], - pBss->Bssid[1], - pBss->Bssid[2], - pBss->Bssid[3], - pBss->Bssid[4], - pBss->Bssid[5]); - - //Security - if ((Ndis802_11AuthModeWPA <= pBss->AuthMode) && - (pBss->AuthMode <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) - { - if (pBss->AuthModeAux == Ndis802_11AuthModeWPANone) - { - ap_auth_mode = pBss->AuthMode; - if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) - ap_cipher = pBss->WPA.PairCipher; - else - ap_cipher = Ndis802_11Encryption4Enabled; - } - else if (pBss->AuthModeAux == Ndis802_11AuthModeOpen) - { - ap_auth_mode = pBss->AuthMode; - if ((ap_auth_mode == Ndis802_11AuthModeWPA) || - (ap_auth_mode == Ndis802_11AuthModeWPAPSK)) - { - if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) - ap_cipher = pBss->WPA.PairCipher; - else - ap_cipher = Ndis802_11Encryption4Enabled; - } - else if ((ap_auth_mode == Ndis802_11AuthModeWPA2) || - (ap_auth_mode == Ndis802_11AuthModeWPA2PSK)) - { - if (pBss->WPA2.PairCipherAux == Ndis802_11WEPDisabled) - ap_cipher = pBss->WPA2.PairCipher; - else - ap_cipher = Ndis802_11Encryption4Enabled; - } - } - else if ((pBss->AuthMode == Ndis802_11AuthModeWPAPSK) || - (pBss->AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - if ((pBss->AuthModeAux == Ndis802_11AuthModeWPAPSK) || - (pBss->AuthModeAux == Ndis802_11AuthModeWPA2PSK)) - ap_auth_mode = Ndis802_11AuthModeWPA1PSKWPA2PSK; - else - ap_auth_mode = pBss->AuthMode; - - if (pBss->WPA.PairCipher != pBss->WPA2.PairCipher) - ap_cipher = Ndis802_11Encryption4Enabled; - else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && - (pBss->WPA.PairCipherAux != pBss->WPA2.PairCipherAux)) - ap_cipher = Ndis802_11Encryption4Enabled; - else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && - (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) && - (pBss->WPA.PairCipherAux != Ndis802_11WEPDisabled)) - ap_cipher = Ndis802_11Encryption4Enabled; - else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && - (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) && - (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)) - ap_cipher = pBss->WPA.PairCipher; - } - else if ((pBss->AuthMode == Ndis802_11AuthModeWPA) || - (pBss->AuthMode == Ndis802_11AuthModeWPA2)) - { - if ((pBss->AuthModeAux == Ndis802_11AuthModeWPA) || - (pBss->AuthMode == Ndis802_11AuthModeWPA2)) - ap_auth_mode = Ndis802_11AuthModeWPA1WPA2; - else - ap_auth_mode = pBss->AuthMode; - - if (pBss->WPA.PairCipher != pBss->WPA2.PairCipher) - ap_cipher = Ndis802_11Encryption4Enabled; - else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && - (pBss->WPA.PairCipherAux != pBss->WPA2.PairCipherAux)) - ap_cipher = Ndis802_11Encryption4Enabled; - else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && - (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) && - (pBss->WPA.PairCipherAux != Ndis802_11WEPDisabled)) - ap_cipher = Ndis802_11Encryption4Enabled; - else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && - (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) && - (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)) - ap_cipher = pBss->WPA.PairCipher; - } - - sprintf(SecurityStr, "%s/%s", GetAuthMode((CHAR)ap_auth_mode), GetEncryptType((CHAR)ap_cipher)); - } - else - { - ap_auth_mode = pBss->AuthMode; - ap_cipher = pBss->WepStatus; - if (ap_cipher == Ndis802_11WEPDisabled) - sprintf(SecurityStr, "NONE"); - else if (ap_cipher == Ndis802_11WEPEnabled) - sprintf(SecurityStr, "WEP"); - else - sprintf(SecurityStr, "%s/%s", GetAuthMode((CHAR)ap_auth_mode), GetEncryptType((CHAR)ap_cipher)); - } - - sprintf(msg+strlen(msg), "%-23s", SecurityStr); - - // Rssi - Rssi = (INT)pBss->Rssi; - if (Rssi >= -50) - Rssi_Quality = 100; - else if (Rssi >= -80) // between -50 ~ -80dbm - Rssi_Quality = (UINT)(24 + ((Rssi + 80) * 26)/10); - else if (Rssi >= -90) // between -80 ~ -90dbm - Rssi_Quality = (UINT)(((Rssi + 90) * 26)/10); - else // < -84 dbm - Rssi_Quality = 0; - sprintf(msg+strlen(msg),"%-9d", Rssi_Quality); - // Wireless Mode - wireless_mode = NetworkTypeInUseSanity(pBss); - if (wireless_mode == Ndis802_11FH || - wireless_mode == Ndis802_11DS) - sprintf(msg+strlen(msg),"%-7s", "11b"); - else if (wireless_mode == Ndis802_11OFDM5) - sprintf(msg+strlen(msg),"%-7s", "11a"); - else if (wireless_mode == Ndis802_11OFDM5_N) - sprintf(msg+strlen(msg),"%-7s", "11a/n"); - else if (wireless_mode == Ndis802_11OFDM24) - sprintf(msg+strlen(msg),"%-7s", "11b/g"); - else if (wireless_mode == Ndis802_11OFDM24_N) - sprintf(msg+strlen(msg),"%-7s", "11b/g/n"); - else - sprintf(msg+strlen(msg),"%-7s", "unknow"); - //Network Type - if (pBss->BssType == BSS_ADHOC) - sprintf(msg+strlen(msg),"%-3s", " Ad"); - else - sprintf(msg+strlen(msg),"%-3s", " In"); - - sprintf(msg+strlen(msg),"\n"); - - return; -} - -VOID RTMPIoctlGetSiteSurvey( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq) -{ - PSTRING msg; - INT i=0; - INT WaitCnt; - INT Status=0; - INT max_len = LINE_LEN; - PBSS_ENTRY pBss; - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - - os_alloc_mem(NULL, (PUCHAR *)&msg, sizeof(CHAR)*((MAX_LEN_OF_BSS_TABLE)*max_len)); - - if (msg == NULL) - { - DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - msg memory alloc fail.\n")); - return; - } - - memset(msg, 0 ,(MAX_LEN_OF_BSS_TABLE)*max_len ); - sprintf(msg,"%s","\n"); - sprintf(msg+strlen(msg),"%-4s%-33s%-20s%-23s%-9s%-7s%-3s\n", - "Ch", "SSID", "BSSID", "Security", "Siganl(%)", "W-Mode", " NT"); - -#ifdef CONFIG_STA_SUPPORT - -#endif // CONFIG_STA_SUPPORT // - - WaitCnt = 0; -#ifdef CONFIG_STA_SUPPORT - pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE; - while ((ScanRunning(pAdapter) == TRUE) && (WaitCnt++ < 200)) - OS_WAIT(500); -#endif // CONFIG_STA_SUPPORT // - - for(i=0; iScanTab.BssNr ;i++) - { - pBss = &pAdapter->ScanTab.BssEntry[i]; - - if( pBss->Channel==0) - break; - - if((strlen(msg)+max_len ) >= IW_SCAN_MAX_DATA) - break; - - - RTMPCommSiteSurveyData(msg, pBss); - -#ifdef CONFIG_STA_SUPPORT - -#endif // CONFIG_STA_SUPPORT // - } - -#ifdef CONFIG_STA_SUPPORT - pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; -#endif // CONFIG_STA_SUPPORT // - wrq->u.data.length = strlen(msg); - Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - wrq->u.data.length = %d\n", wrq->u.data.length)); - os_free_mem(NULL, (PUCHAR)msg); -} - -#define MAC_LINE_LEN (14+4+4+10+10+10+6+6) // Addr+aid+psm+datatime+rxbyte+txbyte+current tx rate+last tx rate -VOID RTMPIoctlGetMacTable( - IN PRTMP_ADAPTER pAd, - IN struct iwreq *wrq) -{ - INT i; - RT_802_11_MAC_TABLE MacTab; - char *msg; - - MacTab.Num = 0; - for (i=0; iMacTab.Content[i].ValidAsCLI && (pAd->MacTab.Content[i].Sst == SST_ASSOC)) - { - COPY_MAC_ADDR(MacTab.Entry[MacTab.Num].Addr, &pAd->MacTab.Content[i].Addr); - MacTab.Entry[MacTab.Num].Aid = (UCHAR)pAd->MacTab.Content[i].Aid; - MacTab.Entry[MacTab.Num].Psm = pAd->MacTab.Content[i].PsMode; -#ifdef DOT11_N_SUPPORT - MacTab.Entry[MacTab.Num].MimoPs = pAd->MacTab.Content[i].MmpsMode; -#endif // DOT11_N_SUPPORT // - - // Fill in RSSI per entry - MacTab.Entry[MacTab.Num].AvgRssi0 = pAd->MacTab.Content[i].RssiSample.AvgRssi0; - MacTab.Entry[MacTab.Num].AvgRssi1 = pAd->MacTab.Content[i].RssiSample.AvgRssi1; - MacTab.Entry[MacTab.Num].AvgRssi2 = pAd->MacTab.Content[i].RssiSample.AvgRssi2; - - // the connected time per entry - MacTab.Entry[MacTab.Num].ConnectedTime = pAd->MacTab.Content[i].StaConnectTime; - MacTab.Entry[MacTab.Num].TxRate.field.MCS = pAd->MacTab.Content[i].HTPhyMode.field.MCS; - MacTab.Entry[MacTab.Num].TxRate.field.BW = pAd->MacTab.Content[i].HTPhyMode.field.BW; - MacTab.Entry[MacTab.Num].TxRate.field.ShortGI = pAd->MacTab.Content[i].HTPhyMode.field.ShortGI; - MacTab.Entry[MacTab.Num].TxRate.field.STBC = pAd->MacTab.Content[i].HTPhyMode.field.STBC; - MacTab.Entry[MacTab.Num].TxRate.field.rsv = pAd->MacTab.Content[i].HTPhyMode.field.rsv; - MacTab.Entry[MacTab.Num].TxRate.field.MODE = pAd->MacTab.Content[i].HTPhyMode.field.MODE; - MacTab.Entry[MacTab.Num].TxRate.word = pAd->MacTab.Content[i].HTPhyMode.word; - - MacTab.Num += 1; - } - } - wrq->u.data.length = sizeof(RT_802_11_MAC_TABLE); - if (copy_to_user(wrq->u.data.pointer, &MacTab, wrq->u.data.length)) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); - } - - msg = kmalloc(sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN), MEM_ALLOC_FLAG); - if (msg == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); - return; - } - memset(msg, 0 ,MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN ); - sprintf(msg,"%s","\n"); - sprintf(msg+strlen(msg),"%-14s%-4s%-4s%-10s%-10s%-10s%-6s%-6s\n", - "MAC", "AID", "PSM", "LDT", "RxB", "TxB","CTxR", "LTxR"); - - for (i=0; iMacTab.Content[i]; - if (pEntry->ValidAsCLI && (pEntry->Sst == SST_ASSOC)) - { - if((strlen(msg)+MAC_LINE_LEN ) >= (MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN) ) - break; - sprintf(msg+strlen(msg),"%02x%02x%02x%02x%02x%02x ", - pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], - pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); - sprintf(msg+strlen(msg),"%-4d", (int)pEntry->Aid); - sprintf(msg+strlen(msg),"%-4d", (int)pEntry->PsMode); - sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.LastDataPacketTime*/); // ToDo - sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalRxByteCount*/); // ToDo - sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalTxByteCount*/); // ToDo - sprintf(msg+strlen(msg),"%-6d",RateIdToMbps[pAd->MacTab.Content[i].CurrTxRate]); - sprintf(msg+strlen(msg),"%-6d\n",0/*RateIdToMbps[pAd->MacTab.Content[i].LastTxRate]*/); // ToDo - } - } - // for compatible with old API just do the printk to console - //wrq->u.data.length = strlen(msg); - //if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s", msg)); - } - - kfree(msg); -} - - -#ifdef DOT11_N_SUPPORT -INT Set_BASetup_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UCHAR mac[6], tid; - PSTRING token; - STRING sepValue[] = ":", DASH = '-'; - INT i; - MAC_TABLE_ENTRY *pEntry; - -/* - The BASetup inupt string format should be xx:xx:xx:xx:xx:xx-d, - =>The six 2 digit hex-decimal number previous are the Mac address, - =>The seventh decimal number is the tid value. -*/ - //DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg)); - - if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format. - return FALSE; - - token = strchr(arg, DASH); - if ((token != NULL) && (strlen(token)>1)) - { - tid = (UCHAR) simple_strtol((token+1), 0, 10); - if (tid > 15) - return FALSE; - - *token = '\0'; - for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) - { - if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) - return FALSE; - AtoH(token, (&mac[i]), 1); - } - if(i != 6) - return FALSE; - - DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], tid)); - - pEntry = MacTableLookup(pAd, (PUCHAR) mac); - - if (pEntry) { - DBGPRINT(RT_DEBUG_OFF, ("\nSetup BA Session: Tid = %d\n", tid)); - BAOriSessionSetUp(pAd, pEntry, tid, 0, 100, TRUE); - } - - return TRUE; - } - - return FALSE; - -} - -INT Set_BADecline_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG bBADecline; - - bBADecline = simple_strtol(arg, 0, 10); - - if (bBADecline == 0) - { - pAd->CommonCfg.bBADecline = FALSE; - } - else if (bBADecline == 1) - { - pAd->CommonCfg.bBADecline = TRUE; - } - else - { - return FALSE; //Invalid argument - } - - DBGPRINT(RT_DEBUG_TRACE, ("Set_BADecline_Proc::(BADecline=%d)\n", pAd->CommonCfg.bBADecline)); - - return TRUE; -} - -INT Set_BAOriTearDown_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UCHAR mac[6], tid; - PSTRING token; - STRING sepValue[] = ":", DASH = '-'; - INT i; - MAC_TABLE_ENTRY *pEntry; - - //DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg)); -/* - The BAOriTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, - =>The six 2 digit hex-decimal number previous are the Mac address, - =>The seventh decimal number is the tid value. -*/ - if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format. - return FALSE; - - token = strchr(arg, DASH); - if ((token != NULL) && (strlen(token)>1)) - { - tid = simple_strtol((token+1), 0, 10); - if (tid > NUM_OF_TID) - return FALSE; - - *token = '\0'; - for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) - { - if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) - return FALSE; - AtoH(token, (&mac[i]), 1); - } - if(i != 6) - return FALSE; - - DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], tid)); - - pEntry = MacTableLookup(pAd, (PUCHAR) mac); - - if (pEntry) { - DBGPRINT(RT_DEBUG_OFF, ("\nTear down Ori BA Session: Tid = %d\n", tid)); - BAOriSessionTearDown(pAd, pEntry->Aid, tid, FALSE, TRUE); - } - - return TRUE; - } - - return FALSE; - -} - -INT Set_BARecTearDown_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UCHAR mac[6], tid; - PSTRING token; - STRING sepValue[] = ":", DASH = '-'; - INT i; - MAC_TABLE_ENTRY *pEntry; - - //DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg)); -/* - The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, - =>The six 2 digit hex-decimal number previous are the Mac address, - =>The seventh decimal number is the tid value. -*/ - if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format. - return FALSE; - - token = strchr(arg, DASH); - if ((token != NULL) && (strlen(token)>1)) - { - tid = simple_strtol((token+1), 0, 10); - if (tid > NUM_OF_TID) - return FALSE; - - *token = '\0'; - for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) - { - if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) - return FALSE; - AtoH(token, (&mac[i]), 1); - } - if(i != 6) - return FALSE; - - DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], tid)); - - pEntry = MacTableLookup(pAd, (PUCHAR) mac); - - if (pEntry) { - DBGPRINT(RT_DEBUG_OFF, ("\nTear down Rec BA Session: Tid = %d\n", tid)); - BARecSessionTearDown(pAd, pEntry->Aid, tid, FALSE); - } - - return TRUE; - } - - return FALSE; - -} - -INT Set_HtBw_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG HtBw; - - HtBw = simple_strtol(arg, 0, 10); - if (HtBw == BW_40) - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; - else if (HtBw == BW_20) - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBw_Proc::(HtBw=%d)\n", pAd->CommonCfg.RegTransmitSetting.field.BW)); - - return TRUE; -} - -INT Set_HtMcs_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG HtMcs, Mcs_tmp; -#ifdef CONFIG_STA_SUPPORT - BOOLEAN bAutoRate = FALSE; -#endif // CONFIG_STA_SUPPORT // - - Mcs_tmp = simple_strtol(arg, 0, 10); - - if (Mcs_tmp <= 15 || Mcs_tmp == 32) - HtMcs = Mcs_tmp; - else - HtMcs = MCS_AUTO; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - pAd->StaCfg.DesiredTransmitSetting.field.MCS = HtMcs; - pAd->StaCfg.bAutoTxRateSwitch = (HtMcs == MCS_AUTO) ? TRUE:FALSE; - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(HtMcs=%d, bAutoTxRateSwitch = %d)\n", - pAd->StaCfg.DesiredTransmitSetting.field.MCS, pAd->StaCfg.bAutoTxRateSwitch)); - - if ((pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) || - (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE < MODE_HTMIX)) - { - if ((pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) && - (HtMcs >= 0 && HtMcs <= 3) && - (pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_CCK)) - { - RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs] * 1000000)); - } - else if ((pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) && - (HtMcs >= 0 && HtMcs <= 7) && - (pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_OFDM)) - { - RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs+4] * 1000000)); - } - else - bAutoRate = TRUE; - - if (bAutoRate) - { - pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; - RTMPSetDesiredRates(pAd, -1); - } - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(FixedTxMode=%d)\n",pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode)); - } - if (ADHOC_ON(pAd)) - return TRUE; - } -#endif // CONFIG_STA_SUPPORT // - - SetCommonHT(pAd); - - return TRUE; -} - -INT Set_HtGi_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG HtGi; - - HtGi = simple_strtol(arg, 0, 10); - - if ( HtGi == GI_400) - pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400; - else if ( HtGi == GI_800 ) - pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtGi_Proc::(ShortGI=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.ShortGI)); - - return TRUE; -} - - -INT Set_HtTxBASize_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UCHAR Size; - - Size = simple_strtol(arg, 0, 10); - - if (Size <=0 || Size >=64) - { - Size = 8; - } - pAd->CommonCfg.TxBASize = Size-1; - DBGPRINT(RT_DEBUG_ERROR, ("Set_HtTxBASize ::(TxBASize= %d)\n", Size)); - - return TRUE; -} - -INT Set_HtDisallowTKIP_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - if (Value == 1) - { - pAd->CommonCfg.HT_DisallowTKIP = TRUE; - } - else - { - pAd->CommonCfg.HT_DisallowTKIP = FALSE; - } - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtDisallowTKIP_Proc ::%s\n", - (pAd->CommonCfg.HT_DisallowTKIP == TRUE) ? "enabled" : "disabled")); - - return TRUE; -} - -INT Set_HtOpMode_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - if (Value == HTMODE_GF) - pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF; - else if ( Value == HTMODE_MM ) - pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtOpMode_Proc::(HtOpMode=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.HTMODE)); - - return TRUE; - -} - -INT Set_HtStbc_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - if (Value == STBC_USE) - pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE; - else if ( Value == STBC_NONE ) - pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_Stbc_Proc::(HtStbc=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.STBC)); - - return TRUE; -} - -INT Set_HtHtc_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - pAd->HTCEnable = FALSE; - else if ( Value ==1 ) - pAd->HTCEnable = TRUE; - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtHtc_Proc::(HtHtc=%d)\n",pAd->HTCEnable)); - - return TRUE; -} - -INT Set_HtExtcha_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - if (Value == 0) - pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; - else if ( Value ==1 ) - pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtExtcha_Proc::(HtExtcha=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.EXTCHA)); - - return TRUE; -} - -INT Set_HtMpduDensity_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - if (Value <=7 && Value >= 0) - pAd->CommonCfg.BACapability.field.MpduDensity = Value; - else - pAd->CommonCfg.BACapability.field.MpduDensity = 4; - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMpduDensity_Proc::(HtMpduDensity=%d)\n",pAd->CommonCfg.BACapability.field.MpduDensity)); - - return TRUE; -} - -INT Set_HtBaWinSize_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - - if (Value >=1 && Value <= 64) - { - pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value; - pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value; - } - else - { - pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64; - pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; - } - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBaWinSize_Proc::(HtBaWinSize=%d)\n",pAd->CommonCfg.BACapability.field.RxBAWinLimit)); - - return TRUE; -} - -INT Set_HtRdg_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - if (Value == 0) - pAd->CommonCfg.bRdg = FALSE; - else if ( Value ==1 ) - { - pAd->HTCEnable = TRUE; - pAd->CommonCfg.bRdg = TRUE; - } - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtRdg_Proc::(HtRdg=%d)\n",pAd->CommonCfg.bRdg)); - - return TRUE; -} - -INT Set_HtLinkAdapt_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - pAd->bLinkAdapt = FALSE; - else if ( Value ==1 ) - { - pAd->HTCEnable = TRUE; - pAd->bLinkAdapt = TRUE; - } - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtLinkAdapt_Proc::(HtLinkAdapt=%d)\n",pAd->bLinkAdapt)); - - return TRUE; -} - -INT Set_HtAmsdu_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE; - else if ( Value == 1 ) - pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAmsdu_Proc::(HtAmsdu=%d)\n",pAd->CommonCfg.BACapability.field.AmsduEnable)); - - return TRUE; -} - -INT Set_HtAutoBa_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.BACapability.field.AutoBA = FALSE; - pAd->CommonCfg.BACapability.field.Policy = BA_NOTUSE; - } - else if (Value == 1) - { - pAd->CommonCfg.BACapability.field.AutoBA = TRUE; - pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; - } - else - return FALSE; //Invalid argument - - pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA; - pAd->CommonCfg.REGBACapability.field.Policy = pAd->CommonCfg.BACapability.field.Policy; - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAutoBa_Proc::(HtAutoBa=%d)\n",pAd->CommonCfg.BACapability.field.AutoBA)); - - return TRUE; - -} - -INT Set_HtProtect_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - pAd->CommonCfg.bHTProtect = FALSE; - else if (Value == 1) - pAd->CommonCfg.bHTProtect = TRUE; - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtProtect_Proc::(HtProtect=%d)\n",pAd->CommonCfg.bHTProtect)); - - return TRUE; -} - -INT Set_SendPSMPAction_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UCHAR mac[6], mode; - PSTRING token; - STRING sepValue[] = ":", DASH = '-'; - INT i; - MAC_TABLE_ENTRY *pEntry; - - //DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg)); -/* - The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, - =>The six 2 digit hex-decimal number previous are the Mac address, - =>The seventh decimal number is the mode value. -*/ - if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and mode value in decimal format. - return FALSE; - - token = strchr(arg, DASH); - if ((token != NULL) && (strlen(token)>1)) - { - mode = simple_strtol((token+1), 0, 10); - if (mode > MMPS_ENABLE) - return FALSE; - - *token = '\0'; - for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) - { - if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) - return FALSE; - AtoH(token, (&mac[i]), 1); - } - if(i != 6) - return FALSE; - - DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], mode)); - - pEntry = MacTableLookup(pAd, mac); - - if (pEntry) { - DBGPRINT(RT_DEBUG_OFF, ("\nSendPSMPAction MIPS mode = %d\n", mode)); - SendPSMPAction(pAd, pEntry->Aid, mode); - } - - return TRUE; - } - - return FALSE; - - -} - -INT Set_HtMIMOPSmode_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - - if (Value <=3 && Value >= 0) - pAd->CommonCfg.BACapability.field.MMPSmode = Value; - else - pAd->CommonCfg.BACapability.field.MMPSmode = 3; - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMIMOPSmode_Proc::(MIMOPS mode=%d)\n",pAd->CommonCfg.BACapability.field.MMPSmode)); - - return TRUE; -} - - -INT Set_ForceShortGI_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - pAd->WIFItestbed.bShortGI = FALSE; - else if (Value == 1) - pAd->WIFItestbed.bShortGI = TRUE; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceShortGI_Proc::(ForceShortGI=%d)\n", pAd->WIFItestbed.bShortGI)); - - return TRUE; -} - - - -INT Set_ForceGF_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - pAd->WIFItestbed.bGreenField = FALSE; - else if (Value == 1) - pAd->WIFItestbed.bGreenField = TRUE; - else - return FALSE; //Invalid argument - - SetCommonHT(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceGF_Proc::(ForceGF=%d)\n", pAd->WIFItestbed.bGreenField)); - - return TRUE; -} - -INT Set_HtMimoPs_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - if (Value == 0) - pAd->CommonCfg.bMIMOPSEnable = FALSE; - else if (Value == 1) - pAd->CommonCfg.bMIMOPSEnable = TRUE; - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMimoPs_Proc::(HtMimoPs=%d)\n",pAd->CommonCfg.bMIMOPSEnable)); - - return TRUE; -} -#endif // DOT11_N_SUPPORT // - - -#ifdef DOT11_N_SUPPORT -INT SetCommonHT( - IN PRTMP_ADAPTER pAd) -{ - OID_SET_HT_PHYMODE SetHT; - - if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) - return FALSE; - - SetHT.PhyMode = pAd->CommonCfg.PhyMode; - SetHT.TransmitNo = ((UCHAR)pAd->Antenna.field.TxPath); - SetHT.HtMode = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.HTMODE; - SetHT.ExtOffset = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; - SetHT.MCS = MCS_AUTO; - SetHT.BW = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.BW; - SetHT.STBC = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.STBC; - SetHT.SHORTGI = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.ShortGI; - - RTMPSetHT(pAd, &SetHT); - - return TRUE; -} -#endif // DOT11_N_SUPPORT // - -INT Set_FixedTxMode_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UCHAR fix_tx_mode = FIXED_TXMODE_HT; - - if (strcmp(arg, "OFDM") == 0 || strcmp(arg, "ofdm") == 0) - { - fix_tx_mode = FIXED_TXMODE_OFDM; - } - else if (strcmp(arg, "CCK") == 0 || strcmp(arg, "cck") == 0) - { - fix_tx_mode = FIXED_TXMODE_CCK; - } - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode; -#endif // CONFIG_STA_SUPPORT // - - DBGPRINT(RT_DEBUG_TRACE, ("Set_FixedTxMode_Proc::(FixedTxMode=%d)\n", fix_tx_mode)); - - return TRUE; -} - -#ifdef CONFIG_APSTA_MIXED_SUPPORT -INT Set_OpMode_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG Value; - - Value = simple_strtol(arg, 0, 10); - -#ifdef RTMP_MAC_PCI - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) -#endif // RTMP_MAC_PCI // - { - DBGPRINT(RT_DEBUG_ERROR, ("Can not switch operate mode on interface up !! \n")); - return FALSE; - } - - if (Value == 0) - pAd->OpMode = OPMODE_STA; - else if (Value == 1) - pAd->OpMode = OPMODE_AP; - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_OpMode_Proc::(OpMode=%s)\n", pAd->OpMode == 1 ? "AP Mode" : "STA Mode")); - - return TRUE; -} -#endif // CONFIG_APSTA_MIXED_SUPPORT // - - - -INT Set_LongRetryLimit_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg) -{ - TX_RTY_CFG_STRUC tx_rty_cfg; - UCHAR LongRetryLimit = (UCHAR)simple_strtol(arg, 0, 10); - - RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); - tx_rty_cfg.field.LongRtyLimit = LongRetryLimit; - RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word); - DBGPRINT(RT_DEBUG_TRACE, ("IF Set_LongRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word)); - return TRUE; -} - -INT Set_ShortRetryLimit_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg) -{ - TX_RTY_CFG_STRUC tx_rty_cfg; - UCHAR ShortRetryLimit = (UCHAR)simple_strtol(arg, 0, 10); - - RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); - tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit; - RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word); - DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ShortRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word)); - return TRUE; -} - - -///////////////////////////////////////////////////////////////////////// -PSTRING RTMPGetRalinkAuthModeStr( - IN NDIS_802_11_AUTHENTICATION_MODE authMode) -{ - switch(authMode) - { - case Ndis802_11AuthModeOpen: - return "OPEN"; - case Ndis802_11AuthModeWPAPSK: - return "WPAPSK"; - case Ndis802_11AuthModeShared: - return "SHARED"; - case Ndis802_11AuthModeWPA: - return "WPA"; - case Ndis802_11AuthModeWPA2: - return "WPA2"; - case Ndis802_11AuthModeWPA2PSK: - return "WPA2PSK"; - case Ndis802_11AuthModeWPA1PSKWPA2PSK: - return "WPAPSKWPA2PSK"; - case Ndis802_11AuthModeWPA1WPA2: - return "WPA1WPA2"; - case Ndis802_11AuthModeWPANone: - return "WPANONE"; - default: - return "UNKNOW"; - } -} - -PSTRING RTMPGetRalinkEncryModeStr( - IN USHORT encryMode) -{ - switch(encryMode) - { - case Ndis802_11WEPDisabled: - return "NONE"; - case Ndis802_11WEPEnabled: - return "WEP"; - case Ndis802_11Encryption2Enabled: - return "TKIP"; - case Ndis802_11Encryption3Enabled: - return "AES"; - case Ndis802_11Encryption4Enabled: - return "TKIPAES"; - default: - return "UNKNOW"; - } -} - -INT RTMPShowCfgValue( - IN PRTMP_ADAPTER pAd, - IN PSTRING pName, - IN PSTRING pBuf) -{ - INT Status = 0; - - for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++) - { - if (!strcmp(pName, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name)) - { - if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->show_proc(pAd, pBuf)) - Status = -EINVAL; - break; //Exit for loop. - } - } - - if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name == NULL) - { - sprintf(pBuf, "\n"); - for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++) - sprintf(pBuf, "%s%s\n", pBuf, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name); - } - - return Status; -} - -INT Show_SSID_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - sprintf(pBuf, "\t%s", pAd->CommonCfg.Ssid); -#endif // CONFIG_STA_SUPPORT // - return 0; -} - -INT Show_WirelessMode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - switch(pAd->CommonCfg.PhyMode) - { - case PHY_11BG_MIXED: - sprintf(pBuf, "\t11B/G"); - break; - case PHY_11B: - sprintf(pBuf, "\t11B"); - break; - case PHY_11A: - sprintf(pBuf, "\t11A"); - break; - case PHY_11ABG_MIXED: - sprintf(pBuf, "\t11A/B/G"); - break; - case PHY_11G: - sprintf(pBuf, "\t11G"); - break; -#ifdef DOT11_N_SUPPORT - case PHY_11ABGN_MIXED: - sprintf(pBuf, "\t11A/B/G/N"); - break; - case PHY_11N_2_4G: - sprintf(pBuf, "\t11N only with 2.4G"); - break; - case PHY_11GN_MIXED: - sprintf(pBuf, "\t11G/N"); - break; - case PHY_11AN_MIXED: - sprintf(pBuf, "\t11A/N"); - break; - case PHY_11BGN_MIXED: - sprintf(pBuf, "\t11B/G/N"); - break; - case PHY_11AGN_MIXED: - sprintf(pBuf, "\t11A/G/N"); - break; - case PHY_11N_5G: - sprintf(pBuf, "\t11N only with 5G"); - break; -#endif // DOT11_N_SUPPORT // - default: - sprintf(pBuf, "\tUnknow Value(%d)", pAd->CommonCfg.PhyMode); - break; - } - return 0; -} - - -INT Show_TxBurst_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.bEnableTxBurst ? "TRUE":"FALSE"); - return 0; -} - -INT Show_TxPreamble_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - switch(pAd->CommonCfg.TxPreamble) - { - case Rt802_11PreambleShort: - sprintf(pBuf, "\tShort"); - break; - case Rt802_11PreambleLong: - sprintf(pBuf, "\tLong"); - break; - case Rt802_11PreambleAuto: - sprintf(pBuf, "\tAuto"); - break; - default: - sprintf(pBuf, "\tUnknow Value(%lu)", pAd->CommonCfg.TxPreamble); - break; - } - - return 0; -} - -INT Show_TxPower_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%lu", pAd->CommonCfg.TxPowerPercentage); - return 0; -} - -INT Show_Channel_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%d", pAd->CommonCfg.Channel); - return 0; -} - -INT Show_BGProtection_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - switch(pAd->CommonCfg.UseBGProtection) - { - case 1: //Always On - sprintf(pBuf, "\tON"); - break; - case 2: //Always OFF - sprintf(pBuf, "\tOFF"); - break; - case 0: //AUTO - sprintf(pBuf, "\tAuto"); - break; - default: - sprintf(pBuf, "\tUnknow Value(%lu)", pAd->CommonCfg.UseBGProtection); - break; - } - return 0; -} - -INT Show_RTSThreshold_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%u", pAd->CommonCfg.RtsThreshold); - return 0; -} - -INT Show_FragThreshold_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%u", pAd->CommonCfg.FragmentThreshold); - return 0; -} - -#ifdef DOT11_N_SUPPORT -INT Show_HtBw_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) - { - sprintf(pBuf, "\t40 MHz"); - } - else - { - sprintf(pBuf, "\t20 MHz"); - } - return 0; -} - -INT Show_HtMcs_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - sprintf(pBuf, "\t%u", pAd->StaCfg.DesiredTransmitSetting.field.MCS); -#endif // CONFIG_STA_SUPPORT // - return 0; -} - -INT Show_HtGi_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - switch(pAd->CommonCfg.RegTransmitSetting.field.ShortGI) - { - case GI_400: - sprintf(pBuf, "\tGI_400"); - break; - case GI_800: - sprintf(pBuf, "\tGI_800"); - break; - default: - sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.ShortGI); - break; - } - return 0; -} - -INT Show_HtOpMode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - switch(pAd->CommonCfg.RegTransmitSetting.field.HTMODE) - { - case HTMODE_GF: - sprintf(pBuf, "\tGF"); - break; - case HTMODE_MM: - sprintf(pBuf, "\tMM"); - break; - default: - sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.HTMODE); - break; - } - return 0; -} - -INT Show_HtExtcha_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - switch(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA) - { - case EXTCHA_BELOW: - sprintf(pBuf, "\tBelow"); - break; - case EXTCHA_ABOVE: - sprintf(pBuf, "\tAbove"); - break; - default: - sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.EXTCHA); - break; - } - return 0; -} - - -INT Show_HtMpduDensity_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%u", pAd->CommonCfg.BACapability.field.MpduDensity); - return 0; -} - -INT Show_HtBaWinSize_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%u", pAd->CommonCfg.BACapability.field.RxBAWinLimit); - return 0; -} - -INT Show_HtRdg_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.bRdg ? "TRUE":"FALSE"); - return 0; -} - -INT Show_HtAmsdu_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.BACapability.field.AmsduEnable ? "TRUE":"FALSE"); - return 0; -} - -INT Show_HtAutoBa_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.BACapability.field.AutoBA ? "TRUE":"FALSE"); - return 0; -} -#endif // DOT11_N_SUPPORT // - -INT Show_CountryRegion_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%d", pAd->CommonCfg.CountryRegion); - return 0; -} - -INT Show_CountryRegionABand_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%d", pAd->CommonCfg.CountryRegionForABand); - return 0; -} - -INT Show_CountryCode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.CountryCode); - return 0; -} - -#ifdef AGGREGATION_SUPPORT -INT Show_PktAggregate_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.bAggregationCapable ? "TRUE":"FALSE"); - return 0; -} -#endif // AGGREGATION_SUPPORT // - -#ifdef WMM_SUPPORT -INT Show_WmmCapable_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - sprintf(pBuf, "\t%s", pAd->CommonCfg.bWmmCapable ? "TRUE":"FALSE"); -#endif // CONFIG_STA_SUPPORT // - - return 0; -} -#endif // WMM_SUPPORT // - -INT Show_IEEE80211H_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - sprintf(pBuf, "\t%s", pAd->CommonCfg.bIEEE80211H ? "TRUE":"FALSE"); - return 0; -} - -#ifdef CONFIG_STA_SUPPORT -INT Show_NetworkType_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - switch(pAd->StaCfg.BssType) - { - case BSS_ADHOC: - sprintf(pBuf, "\tAdhoc"); - break; - case BSS_INFRA: - sprintf(pBuf, "\tInfra"); - break; - case BSS_ANY: - sprintf(pBuf, "\tAny"); - break; - case BSS_MONITOR: - sprintf(pBuf, "\tMonitor"); - break; - default: - sprintf(pBuf, "\tUnknow Value(%d)", pAd->StaCfg.BssType); - break; - } - return 0; -} - - -#endif // CONFIG_STA_SUPPORT // - -INT Show_AuthMode_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeOpen; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - AuthMode = pAd->StaCfg.AuthMode; -#endif // CONFIG_STA_SUPPORT // - - if ((AuthMode >= Ndis802_11AuthModeOpen) && - (AuthMode <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) - sprintf(pBuf, "\t%s", RTMPGetRalinkAuthModeStr(AuthMode)); - else - sprintf(pBuf, "\tUnknow Value(%d)", AuthMode); - - return 0; -} - -INT Show_EncrypType_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - NDIS_802_11_WEP_STATUS WepStatus = Ndis802_11WEPDisabled; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - WepStatus = pAd->StaCfg.WepStatus; -#endif // CONFIG_STA_SUPPORT // - - if ((WepStatus >= Ndis802_11WEPEnabled) && - (WepStatus <= Ndis802_11Encryption4KeyAbsent)) - sprintf(pBuf, "\t%s", RTMPGetRalinkEncryModeStr(WepStatus)); - else - sprintf(pBuf, "\tUnknow Value(%d)", WepStatus); - - return 0; -} - -INT Show_DefaultKeyID_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - UCHAR DefaultKeyId = 0; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - DefaultKeyId = pAd->StaCfg.DefaultKeyId; -#endif // CONFIG_STA_SUPPORT // - - sprintf(pBuf, "\t%d", DefaultKeyId); - - return 0; -} - -INT Show_WepKey_Proc( - IN PRTMP_ADAPTER pAd, - IN INT KeyIdx, - OUT PSTRING pBuf) -{ - UCHAR Key[16] = {0}, KeyLength = 0; - INT index = BSS0; - - KeyLength = pAd->SharedKey[index][KeyIdx].KeyLen; - NdisMoveMemory(Key, pAd->SharedKey[index][KeyIdx].Key, KeyLength); - - //check key string is ASCII or not - if (RTMPCheckStrPrintAble((PCHAR)Key, KeyLength)) - sprintf(pBuf, "\t%s", Key); - else - { - int idx; - sprintf(pBuf, "\t"); - for (idx = 0; idx < KeyLength; idx++) - sprintf(pBuf+strlen(pBuf), "%02X", Key[idx]); - } - return 0; -} - -INT Show_Key1_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - Show_WepKey_Proc(pAd, 0, pBuf); - return 0; -} - -INT Show_Key2_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - Show_WepKey_Proc(pAd, 1, pBuf); - return 0; -} - -INT Show_Key3_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - Show_WepKey_Proc(pAd, 2, pBuf); - return 0; -} - -INT Show_Key4_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - Show_WepKey_Proc(pAd, 3, pBuf); - return 0; -} - -INT Show_WPAPSK_Proc( - IN PRTMP_ADAPTER pAd, - OUT PSTRING pBuf) -{ - INT idx; - UCHAR PMK[32] = {0}; - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - NdisMoveMemory(PMK, pAd->StaCfg.PMK, 32); -#endif // CONFIG_STA_SUPPORT // - - sprintf(pBuf, "\tPMK = "); - for (idx = 0; idx < 32; idx++) - sprintf(pBuf+strlen(pBuf), "%02X", PMK[idx]); - - return 0; -} diff --git a/drivers/staging/rt3090/common/cmm_mac_pci.c b/drivers/staging/rt3090/common/cmm_mac_pci.c deleted file mode 100644 index 8e1636315a8b332edc8522a77a4c66d03bf92fb1..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/cmm_mac_pci.c +++ /dev/null @@ -1,1757 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* -*/ - -#ifdef RTMP_MAC_PCI - -#include "../rt_config.h" - - -/* - ======================================================================== - - Routine Description: - Allocate DMA memory blocks for send, receive - - Arguments: - Adapter Pointer to our adapter - - Return Value: - NDIS_STATUS_SUCCESS - NDIS_STATUS_FAILURE - NDIS_STATUS_RESOURCES - - IRQL = PASSIVE_LEVEL - - Note: - - ======================================================================== -*/ -NDIS_STATUS RTMPAllocTxRxRingMemory( - IN PRTMP_ADAPTER pAd) -{ - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - ULONG RingBasePaHigh; - ULONG RingBasePaLow; - PVOID RingBaseVa; - INT index, num; - PTXD_STRUC pTxD; - PRXD_STRUC pRxD; - ULONG ErrorValue = 0; - PRTMP_TX_RING pTxRing; - PRTMP_DMABUF pDmaBuf; - PNDIS_PACKET pPacket; -// PRTMP_REORDERBUF pReorderBuf; - - DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); - do - { - // - // Allocate all ring descriptors, include TxD, RxD, MgmtD. - // Although each size is different, to prevent cacheline and alignment - // issue, I intentional set them all to 64 bytes. - // - for (num=0; numTxDescRing[num].AllocSize = TX_RING_SIZE * TXD_SIZE; - RTMP_AllocateTxDescMemory( - pAd, - num, - pAd->TxDescRing[num].AllocSize, - FALSE, - &pAd->TxDescRing[num].AllocVa, - &pAd->TxDescRing[num].AllocPa); - - if (pAd->TxDescRing[num].AllocVa == NULL) - { - ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; - DBGPRINT_ERR(("Failed to allocate a big buffer\n")); - Status = NDIS_STATUS_RESOURCES; - break; - } - - // Zero init this memory block - NdisZeroMemory(pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocSize); - - // Save PA & VA for further operation - RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num].AllocPa); - RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxDescRing[num].AllocPa); - RingBaseVa = pAd->TxDescRing[num].AllocVa; - - // - // Allocate all 1st TXBuf's memory for this TxRing - // - pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE; - RTMP_AllocateFirstTxBuffer( - pAd, - num, - pAd->TxBufSpace[num].AllocSize, - FALSE, - &pAd->TxBufSpace[num].AllocVa, - &pAd->TxBufSpace[num].AllocPa); - - if (pAd->TxBufSpace[num].AllocVa == NULL) - { - ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; - DBGPRINT_ERR(("Failed to allocate a big buffer\n")); - Status = NDIS_STATUS_RESOURCES; - break; - } - - // Zero init this memory block - NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocSize); - - // Save PA & VA for further operation - BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num].AllocPa); - BufBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxBufSpace[num].AllocPa); - BufBaseVa = pAd->TxBufSpace[num].AllocVa; - - // - // Initialize Tx Ring Descriptor and associated buffer memory - // - pTxRing = &pAd->TxRing[num]; - for (index = 0; index < TX_RING_SIZE; index++) - { - pTxRing->Cell[index].pNdisPacket = NULL; - pTxRing->Cell[index].pNextNdisPacket = NULL; - // Init Tx Ring Size, Va, Pa variables - pTxRing->Cell[index].AllocSize = TXD_SIZE; - pTxRing->Cell[index].AllocVa = RingBaseVa; - RTMP_SetPhysicalAddressHigh(pTxRing->Cell[index].AllocPa, RingBasePaHigh); - RTMP_SetPhysicalAddressLow (pTxRing->Cell[index].AllocPa, RingBasePaLow); - - // Setup Tx Buffer size & address. only 802.11 header will store in this space - pDmaBuf = &pTxRing->Cell[index].DmaBuf; - pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; - pDmaBuf->AllocVa = BufBaseVa; - RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, BufBasePaHigh); - RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow); - - // link the pre-allocated TxBuf to TXD - pTxD = (PTXD_STRUC) pTxRing->Cell[index].AllocVa; - pTxD->SDPtr0 = BufBasePaLow; - // advance to next ring descriptor address - pTxD->DMADONE = 1; -#ifdef RT_BIG_ENDIAN - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); -#endif - RingBasePaLow += TXD_SIZE; - RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; - - // advance to next TxBuf address - BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE; - BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; - } - DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry allocated\n", num, index)); - } - if (Status == NDIS_STATUS_RESOURCES) - break; - - // - // Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler - // - pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE; - RTMP_AllocateMgmtDescMemory( - pAd, - pAd->MgmtDescRing.AllocSize, - FALSE, - &pAd->MgmtDescRing.AllocVa, - &pAd->MgmtDescRing.AllocPa); - - if (pAd->MgmtDescRing.AllocVa == NULL) - { - ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; - DBGPRINT_ERR(("Failed to allocate a big buffer\n")); - Status = NDIS_STATUS_RESOURCES; - break; - } - - // Zero init this memory block - NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize); - - // Save PA & VA for further operation - RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa); - RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->MgmtDescRing.AllocPa); - RingBaseVa = pAd->MgmtDescRing.AllocVa; - - // - // Initialize MGMT Ring and associated buffer memory - // - for (index = 0; index < MGMT_RING_SIZE; index++) - { - pAd->MgmtRing.Cell[index].pNdisPacket = NULL; - pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL; - // Init MGMT Ring Size, Va, Pa variables - pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE; - pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa; - RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index].AllocPa, RingBasePaHigh); - RTMP_SetPhysicalAddressLow (pAd->MgmtRing.Cell[index].AllocPa, RingBasePaLow); - - // Offset to next ring descriptor address - RingBasePaLow += TXD_SIZE; - RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; - - // link the pre-allocated TxBuf to TXD - pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[index].AllocVa; - pTxD->DMADONE = 1; - -#ifdef RT_BIG_ENDIAN - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); -#endif - // no pre-allocated buffer required in MgmtRing for scatter-gather case - } - DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index)); - - // - // Allocate RX ring descriptor's memory except Tx ring which allocated eariler - // - pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE; - RTMP_AllocateRxDescMemory( - pAd, - pAd->RxDescRing.AllocSize, - FALSE, - &pAd->RxDescRing.AllocVa, - &pAd->RxDescRing.AllocPa); - - if (pAd->RxDescRing.AllocVa == NULL) - { - ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; - DBGPRINT_ERR(("Failed to allocate a big buffer\n")); - Status = NDIS_STATUS_RESOURCES; - break; - } - - // Zero init this memory block - NdisZeroMemory(pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize); - - - DBGPRINT(RT_DEBUG_OFF, - ("RX DESC %p size = %ld\n", pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize)); - - // Save PA & VA for further operation - RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa); - RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->RxDescRing.AllocPa); - RingBaseVa = pAd->RxDescRing.AllocVa; - - // - // Initialize Rx Ring and associated buffer memory - // - for (index = 0; index < RX_RING_SIZE; index++) - { - // Init RX Ring Size, Va, Pa variables - pAd->RxRing.Cell[index].AllocSize = RXD_SIZE; - pAd->RxRing.Cell[index].AllocVa = RingBaseVa; - RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index].AllocPa, RingBasePaHigh); - RTMP_SetPhysicalAddressLow (pAd->RxRing.Cell[index].AllocPa, RingBasePaLow); - - //NdisZeroMemory(RingBaseVa, RXD_SIZE); - - // Offset to next ring descriptor address - RingBasePaLow += RXD_SIZE; - RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE; - - // Setup Rx associated Buffer size & allocate share memory - pDmaBuf = &pAd->RxRing.Cell[index].DmaBuf; - pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE; - pPacket = RTMP_AllocateRxPacketBuffer( - pAd, - pDmaBuf->AllocSize, - FALSE, - &pDmaBuf->AllocVa, - &pDmaBuf->AllocPa); - - /* keep allocated rx packet */ - pAd->RxRing.Cell[index].pNdisPacket = pPacket; - - // Error handling - if (pDmaBuf->AllocVa == NULL) - { - ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; - DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n")); - Status = NDIS_STATUS_RESOURCES; - break; - } - - // Zero init this memory block - NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize); - - // Write RxD buffer address & allocated buffer length - pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa; - pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); - pRxD->DDONE = 0; - -#ifdef RT_BIG_ENDIAN - RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); -#endif - } - - DBGPRINT(RT_DEBUG_TRACE, ("Rx Ring: total %d entry allocated\n", index)); - - } while (FALSE); - - - NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME)); - pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); - - if (pAd->FragFrame.pFragPacket == NULL) - { - Status = NDIS_STATUS_RESOURCES; - } - - if (Status != NDIS_STATUS_SUCCESS) - { - // Log error inforamtion - NdisWriteErrorLogEntry( - pAd->AdapterHandle, - NDIS_ERROR_CODE_OUT_OF_RESOURCES, - 1, - ErrorValue); - } - - // Following code segment get from original func:NICInitTxRxRingAndBacklogQueue(), now should integrate it to here. - { - DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTxRxRingAndBacklogQueue\n")); - -/* - // Disable DMA. - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); - GloCfg.word &= 0xff0; - GloCfg.field.EnTXWriteBackDDONE =1; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); -*/ - - // Initialize all transmit related software queues - for(index = 0; index < NUM_OF_TX_RING; index++) - { - InitializeQueueHeader(&pAd->TxSwQueue[index]); - // Init TX rings index pointer - pAd->TxRing[index].TxSwFreeIdx = 0; - pAd->TxRing[index].TxCpuIdx = 0; - //RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10) , pAd->TxRing[i].TX_CTX_IDX); - } - - // Init RX Ring index pointer - pAd->RxRing.RxSwReadIdx = 0; - pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1; - //RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RX_CRX_IDX0); - - - // init MGMT ring index pointer - pAd->MgmtRing.TxSwFreeIdx = 0; - pAd->MgmtRing.TxCpuIdx = 0; - - pAd->PrivateInfo.TxRingFullCnt = 0; - - DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTxRxRingAndBacklogQueue\n")); - } - - DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); - return Status; -} - - - - -/* - ======================================================================== - - Routine Description: - Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero. - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - Note: - Reset NIC to initial state AS IS system boot up time. - - ======================================================================== -*/ -VOID RTMPRingCleanUp( - IN PRTMP_ADAPTER pAd, - IN UCHAR RingType) -{ - PTXD_STRUC pTxD; - PRXD_STRUC pRxD; - PQUEUE_ENTRY pEntry; - PNDIS_PACKET pPacket; - int i; - PRTMP_TX_RING pTxRing; - unsigned long IrqFlags; - //UINT32 RxSwReadIdx; - - - DBGPRINT(RT_DEBUG_TRACE,("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, pAd->RalinkCounters.PendingNdisPacketCount)); - switch (RingType) - { - case QID_AC_BK: - case QID_AC_BE: - case QID_AC_VI: - case QID_AC_VO: - /*case QID_HCCA:*/ - - pTxRing = &pAd->TxRing[RingType]; - - RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); - // We have to clean all descriptors in case some error happened with reset - for (i=0; iCell[i].AllocVa; - - pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNdisPacket; - // release scatter-and-gather NDIS_PACKET - if (pPacket) - { - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - pTxRing->Cell[i].pNdisPacket = NULL; - } - - pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNextNdisPacket; - // release scatter-and-gather NDIS_PACKET - if (pPacket) - { - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - pTxRing->Cell[i].pNextNdisPacket = NULL; - } - } - - RTMP_IO_READ32(pAd, TX_DTX_IDX0 + RingType * 0x10, &pTxRing->TxDmaIdx); - pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; - pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; - RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + RingType * 0x10, pTxRing->TxCpuIdx); - - RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); - - RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); - while (pAd->TxSwQueue[RingType].Head != NULL) - { - pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]); - pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - DBGPRINT(RT_DEBUG_TRACE,("Release 1 NDIS packet from s/w backlog queue\n")); - } - RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); - break; - - case QID_MGMT: - // We have to clean all descriptors in case some error happened with reset - NdisAcquireSpinLock(&pAd->MgmtRingLock); - - for (i=0; iMgmtRing.Cell[i].AllocVa; - - pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNdisPacket; - // rlease scatter-and-gather NDIS_PACKET - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - } - pAd->MgmtRing.Cell[i].pNdisPacket = NULL; - - pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNextNdisPacket; - // release scatter-and-gather NDIS_PACKET - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - } - pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL; - - } - - RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pAd->MgmtRing.TxDmaIdx); - pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx; - pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx; - RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); - - NdisReleaseSpinLock(&pAd->MgmtRingLock); - pAd->RalinkCounters.MgmtRingFullCount = 0; - break; - - case QID_RX: - // We have to clean all descriptors in case some error happened with reset - NdisAcquireSpinLock(&pAd->RxRingLock); - - for (i=0; iRxRing.Cell[i].AllocVa; - pRxD->DDONE = 0 ; - } - - RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx); - pAd->RxRing.RxSwReadIdx = pAd->RxRing.RxDmaIdx; - pAd->RxRing.RxCpuIdx = ((pAd->RxRing.RxDmaIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxDmaIdx-1)); - RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); - - NdisReleaseSpinLock(&pAd->RxRingLock); - break; - - default: - break; - } -} - - -VOID RTMPFreeTxRxRingMemory( - IN PRTMP_ADAPTER pAd) -{ - int index, num , j; - PRTMP_TX_RING pTxRing; - PTXD_STRUC pTxD; - PNDIS_PACKET pPacket; - unsigned int IrqFlags; - - //POS_COOKIE pObj =(POS_COOKIE) pAd->OS_Cookie; - - DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n")); - - // Free TxSwQueue Packet - for (index=0; index irq_lock, IrqFlags); - pQueue = &pAd->TxSwQueue[index]; - while (pQueue->Head) - { - pEntry = RemoveHeadQueue(pQueue); - pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - } - RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); - } - - // Free Tx Ring Packet - for (index=0;index< NUM_OF_TX_RING;index++) - { - pTxRing = &pAd->TxRing[index]; - - for (j=0; j< TX_RING_SIZE; j++) - { - pTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa); - pPacket = pTxRing->Cell[j].pNdisPacket; - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - //Always assign pNdisPacket as NULL after clear - pTxRing->Cell[j].pNdisPacket = NULL; - - pPacket = pTxRing->Cell[j].pNextNdisPacket; - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - //Always assign pNextNdisPacket as NULL after clear - pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; - - } - } - - for (index = RX_RING_SIZE - 1 ; index >= 0; index--) - { - if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) && (pAd->RxRing.Cell[index].pNdisPacket)) - { - PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[index].DmaBuf.AllocPa, pAd->RxRing.Cell[index].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE); - RELEASE_NDIS_PACKET(pAd, pAd->RxRing.Cell[index].pNdisPacket, NDIS_STATUS_SUCCESS); - } - } - NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(RTMP_DMACB)); - - if (pAd->RxDescRing.AllocVa) - { - RTMP_FreeDescMemory(pAd, pAd->RxDescRing.AllocSize, pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocPa); - } - NdisZeroMemory(&pAd->RxDescRing, sizeof(RTMP_DMABUF)); - - if (pAd->MgmtDescRing.AllocVa) - { - RTMP_FreeDescMemory(pAd, pAd->MgmtDescRing.AllocSize, pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocPa); - } - NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF)); - - for (num = 0; num < NUM_OF_TX_RING; num++) - { - if (pAd->TxBufSpace[num].AllocVa) - { - RTMP_FreeFirstTxBuffer(pAd, pAd->TxBufSpace[num].AllocSize, FALSE, pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocPa); - } - NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF)); - - if (pAd->TxDescRing[num].AllocVa) - { - RTMP_FreeDescMemory(pAd, pAd->TxDescRing[num].AllocSize, pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocPa); - } - NdisZeroMemory(&pAd->TxDescRing[num], sizeof(RTMP_DMABUF)); - } - - if (pAd->FragFrame.pFragPacket) - RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS); - - DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n")); -} - - -/*************************************************************************** - * - * register related procedures. - * - **************************************************************************/ -/* -======================================================================== -Routine Description: - Disable DMA. - -Arguments: - *pAd the raxx interface data pointer - -Return Value: - None - -Note: -======================================================================== -*/ -VOID RT28XXDMADisable( - IN RTMP_ADAPTER *pAd) -{ - WPDMA_GLO_CFG_STRUC GloCfg; - - - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); - GloCfg.word &= 0xff0; - GloCfg.field.EnTXWriteBackDDONE =1; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); -} - - -/* -======================================================================== -Routine Description: - Enable DMA. - -Arguments: - *pAd the raxx interface data pointer - -Return Value: - None - -Note: -======================================================================== -*/ -VOID RT28XXDMAEnable( - IN RTMP_ADAPTER *pAd) -{ - WPDMA_GLO_CFG_STRUC GloCfg; - int i = 0; - - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4); - do - { - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); - if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) - break; - - DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n")); - RTMPusecDelay(1000); - i++; - }while ( i <200); - - RTMPusecDelay(50); - - GloCfg.field.EnTXWriteBackDDONE = 1; - GloCfg.field.WPDMABurstSIZE = 2; - GloCfg.field.EnableRxDMA = 1; - GloCfg.field.EnableTxDMA = 1; - - DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word)); - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); - -} - - -BOOLEAN AsicCheckCommanOk( - IN PRTMP_ADAPTER pAd, - IN UCHAR Command) -{ - UINT32 CmdStatus = 0, CID = 0, i; - UINT32 ThisCIDMask = 0; - - i = 0; - do - { - RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID); - // Find where the command is. Because this is randomly specified by firmware. - if ((CID & CID0MASK) == Command) - { - ThisCIDMask = CID0MASK; - break; - } - else if ((((CID & CID1MASK)>>8) & 0xff) == Command) - { - ThisCIDMask = CID1MASK; - break; - } - else if ((((CID & CID2MASK)>>16) & 0xff) == Command) - { - ThisCIDMask = CID2MASK; - break; - } - else if ((((CID & CID3MASK)>>24) & 0xff) == Command) - { - ThisCIDMask = CID3MASK; - break; - } - - RTMPusecDelay(100); - i++; - }while (i < 200); - - // Get CommandStatus Value - RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus); - - // This command's status is at the same position as command. So AND command position's bitmask to read status. - if (i < 200) - { - // If Status is 1, the comamnd is success. - if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100) - || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000)) - { - DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus)); - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); - return TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus)); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus)); - } - // Clear Command and Status. - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); - - return FALSE; -} - - -/* -======================================================================== -Routine Description: - Write Beacon buffer to Asic. - -Arguments: - *pAd the raxx interface data pointer - -Return Value: - None - -Note: -======================================================================== -*/ -VOID RT28xx_UpdateBeaconToAsic( - IN RTMP_ADAPTER *pAd, - IN INT apidx, - IN ULONG FrameLen, - IN ULONG UpdatePos) -{ - ULONG CapInfoPos = 0; - UCHAR *ptr, *ptr_update, *ptr_capinfo; - UINT i; - BOOLEAN bBcnReq = FALSE; - UCHAR bcn_idx = 0; - - - { - DBGPRINT(RT_DEBUG_ERROR, ("%s() : No valid Interface be found.\n", __FUNCTION__)); - return; - } - - //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) - // || ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) - // || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP)) - // ) - if (bBcnReq == FALSE) - { - /* when the ra interface is down, do not send its beacon frame */ - /* clear all zero */ - for(i=0; iBeaconOffset[bcn_idx] + i, 0x00); - } - else - { - ptr = (PUCHAR)&pAd->BeaconTxWI; -#ifdef RT_BIG_ENDIAN - RTMPWIEndianChange(ptr, TYPE_TXWI); -#endif - for (i=0; iBeaconOffset[bcn_idx] + i, longptr); - ptr += 4; - } - - // Update CapabilityInfo in Beacon - for (i = CapInfoPos; i < (CapInfoPos+2); i++) - { - RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, *ptr_capinfo); - ptr_capinfo ++; - } - - if (FrameLen > UpdatePos) - { - for (i= UpdatePos; i< (FrameLen); i++) - { - RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, *ptr_update); - ptr_update ++; - } - } - - } - -} - - -#ifdef CONFIG_STA_SUPPORT -VOID RT28xxPciStaAsicForceWakeup( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bFromTx) -{ - AUTO_WAKEUP_STRUC AutoWakeupCfg; - - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - return; - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) - { - DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); - return; - } - - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); - - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) - &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) - { - // Support PCIe Advance Power Save - if (bFromTx == TRUE - &&(pAd->Mlme.bPsPollTimerRunning == TRUE)) - { - pAd->Mlme.bPsPollTimerRunning = FALSE; - RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); - RTMPusecDelay(3000); - DBGPRINT(RT_DEBUG_TRACE, ("=======AsicForceWakeup===bFromTx\n")); - } - - AutoWakeupCfg.word = 0; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - - if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE)) - { -#ifdef PCIE_PS_SUPPORT - // add by johnli, RF power sequence setup, load RF normal operation-mode setup - if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)) - { - RTMP_CHIP_OP *pChipOps = &pAd->chipOps; - - if (pChipOps->AsicReverseRfFromSleepMode) - pChipOps->AsicReverseRfFromSleepMode(pAd); - } - else -#endif // PCIE_PS_SUPPORT // - { - // end johnli - // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. - if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) - && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - } - else - { - // Must using 20MHz. - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - } - } - } -#ifdef PCIE_PS_SUPPORT - // 3090 MCU Wakeup command needs more time to be stable. - // Before stable, don't issue other MCU command to prevent from firmware error. - if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd) - && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) - && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("<==RT28xxPciStaAsicForceWakeup::Release the MCU Lock(3090)\n")); - RTMP_SEM_LOCK(&pAd->McuCmdLock); - pAd->brt30xxBanMcuCmd = FALSE; - RTMP_SEM_UNLOCK(&pAd->McuCmdLock); - } -#endif // PCIE_PS_SUPPORT // - } - else - { - // PCI, 2860-PCIe - DBGPRINT(RT_DEBUG_TRACE, ("<==RT28xxPciStaAsicForceWakeup::Original PCI Power Saving\n")); - AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); - AutoWakeupCfg.word = 0; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - } - - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); - DBGPRINT(RT_DEBUG_TRACE, ("<=======RT28xxPciStaAsicForceWakeup\n")); -} - - -VOID RT28xxPciStaAsicSleepThenAutoWakeup( - IN PRTMP_ADAPTER pAd, - IN USHORT TbttNumToNextWakeUp) -{ - BOOLEAN brc; - - if (pAd->StaCfg.bRadio == FALSE) - { - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); - return; - } - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) - &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) - { - ULONG Now = 0; - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) - { - DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); - return; - } - - NdisGetSystemUpTime(&Now); - // If last send NULL fram time is too close to this receiving beacon (within 8ms), don't go to sleep for this DTM. - // Because Some AP can't queuing outgoing frames immediately. - if (((pAd->Mlme.LastSendNULLpsmTime + 8) >= Now) && (pAd->Mlme.LastSendNULLpsmTime <= Now)) - { - DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu : RxCountSinceLastNULL = %lu. \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL)); - return; - } - else if ((pAd->RalinkCounters.RxCountSinceLastNULL > 0) && ((pAd->Mlme.LastSendNULLpsmTime + pAd->CommonCfg.BeaconPeriod) >= Now)) - { - DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu: RxCountSinceLastNULL = %lu > 0 \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL)); - return; - } - - brc = RT28xxPciAsicRadioOff(pAd, DOT11POWERSAVE, TbttNumToNextWakeUp); - if (brc==TRUE) - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); - } - else - { - AUTO_WAKEUP_STRUC AutoWakeupCfg; - // we have decided to SLEEP, so at least do it for a BEACON period. - if (TbttNumToNextWakeUp == 0) - TbttNumToNextWakeUp = 1; - - //RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt); - - AutoWakeupCfg.word = 0; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; - AutoWakeupCfg.field.EnableAutoWakeup = 1; - AutoWakeupCfg.field.AutoLeadTime = 5; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout 40us. - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); - DBGPRINT(RT_DEBUG_TRACE, ("<-- %s, TbttNumToNextWakeUp=%d \n", __FUNCTION__, TbttNumToNextWakeUp)); - } - -} - - -VOID PsPollWakeExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; - unsigned long flags; - - DBGPRINT(RT_DEBUG_TRACE,("-->PsPollWakeExec \n")); - - RTMP_INT_LOCK(&pAd->irq_lock, flags); - if (pAd->Mlme.bPsPollTimerRunning) - { - RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); - } - pAd->Mlme.bPsPollTimerRunning = FALSE; - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); -#ifdef PCIE_PS_SUPPORT - // For rt30xx power solution 3, Use software timer to wake up in psm. So call - // AsicForceWakeup here instead of handling twakeup interrupt. - if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)) - && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) - && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) - { - DBGPRINT(RT_DEBUG_TRACE,("<--PsPollWakeExec::3090 calls AsicForceWakeup(pAd, DOT11POWERSAVE) in advance \n")); - AsicForceWakeup(pAd, DOT11POWERSAVE); - } - -#endif // PCIE_PS_SUPPORT // -} - -VOID RadioOnExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; - RTMP_CHIP_OP *pChipOps = &pAd->chipOps; - WPDMA_GLO_CFG_STRUC DmaCfg; - BOOLEAN Cancelled; - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on fOP_STATUS_DOZE == TRUE; \n")); -//KH Debug: Add the compile flag "RT2860 and condition -#ifdef RTMP_PCI_SUPPORT - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) - &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) - RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); -#endif // RTMP_PCI_SUPPORT // - return; - } - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - { - DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on SCAN_IN_PROGRESS; \n")); - - -#ifdef RTMP_PCI_SUPPORT -if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) - &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) - RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); -#endif // RTMP_PCI_SUPPORT // - return; - } -//KH Debug: need to check. I add the compile flag "CONFIG_STA_SUPPORT" to enclose the following codes. -#ifdef RTMP_PCI_SUPPORT -if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) - &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) - { - pAd->Mlme.bPsPollTimerRunning = FALSE; - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - } -#endif // RTMP_PCI_SUPPORT // - if (pAd->StaCfg.bRadio == TRUE) - { - pAd->bPCIclkOff = FALSE; - RTMPRingCleanUp(pAd, QID_AC_BK); - RTMPRingCleanUp(pAd, QID_AC_BE); - RTMPRingCleanUp(pAd, QID_AC_VI); - RTMPRingCleanUp(pAd, QID_AC_VO); - /*RTMPRingCleanUp(pAd, QID_HCCA);*/ - RTMPRingCleanUp(pAd, QID_MGMT); - RTMPRingCleanUp(pAd, QID_RX); - - // 2. Send wake up command. - AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02); - // 2-1. wait command ok. - AsicCheckCommanOk(pAd, PowerWakeCID); - - // When PCI clock is off, don't want to service interrupt. So when back to clock on, enable interrupt. - //RTMP_IO_WRITE32(pAd, INT_MASK_CSR, (DELAYINTMASK|RxINT)); - RTMP_ASIC_INTERRUPT_ENABLE(pAd); - - // 3. Enable Tx DMA. - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); - DmaCfg.field.EnableTxDMA = 1; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); - - // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. - if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) - && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - } - else - { - // Must using 20MHz. - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - } -//KH Debug:The following codes should be enclosed by RT3090 compile flag - if (pChipOps->AsicReverseRfFromSleepMode) - pChipOps->AsicReverseRfFromSleepMode(pAd); -#ifdef PCIE_PS_SUPPORT -#ifdef CONFIG_STA_SUPPORT -// 3090 MCU Wakeup command needs more time to be stable. -// Before stable, don't issue other MCU command to prevent from firmware error. -if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd) - && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) - && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) - { - RTMP_SEM_LOCK(&pAd->McuCmdLock); - pAd->brt30xxBanMcuCmd = FALSE; - RTMP_SEM_UNLOCK(&pAd->McuCmdLock); - } -#endif // CONFIG_STA_SUPPORT // -#endif // PCIE_PS_SUPPORT // - // Clear Radio off flag - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - - // Set LED - RTMPSetLED(pAd, LED_RADIO_ON); - - if (pAd->StaCfg.Psm == PWR_ACTIVE) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); - } - } - else - { - RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0); - } -} -#endif // CONFIG_STA_SUPPORT // - - -/* - ========================================================================== - Description: - This routine sends command to firmware and turn our chip to wake up mode from power save mode. - Both RadioOn and .11 power save function needs to call this routine. - Input: - Level = GUIRADIO_OFF : call this function is from Radio Off to Radio On. Need to restore PCI host value. - Level = other value : normal wake up function. - - ========================================================================== - */ -BOOLEAN RT28xxPciAsicRadioOn( - IN PRTMP_ADAPTER pAd, - IN UCHAR Level) -{ - //WPDMA_GLO_CFG_STRUC DmaCfg; -#ifdef CONFIG_STA_SUPPORT - BOOLEAN Cancelled; -#endif // CONFIG_STA_SUPPORT // - //UINT32 MACValue; - - if (pAd->OpMode == OPMODE_AP && Level==DOT11POWERSAVE) - return FALSE; - -#ifdef CONFIG_STA_SUPPORT - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - { - if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) - { - pAd->Mlme.bPsPollTimerRunning = FALSE; - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - } - if ((pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)&& - ((Level == GUIRADIO_OFF) || (Level == GUI_IDLE_POWER_SAVE)) - ||(RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))) - { - // Some chips don't need to delay 6ms, so copy RTMPPCIePowerLinkCtrlRestore - // return condition here. - /* - if (((pAd->MACVersion&0xffff0000) != 0x28600000) - && ((pAd->DeviceID == NIC2860_PCIe_DEVICE_ID) - ||(pAd->DeviceID == NIC2790_PCIe_DEVICE_ID))) - */ - { - DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOn ()\n")); - // 1. Set PCI Link Control in Configuration Space. - RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); - RTMPusecDelay(6000); - } - } - } - -#ifdef PCIE_PS_SUPPORT -if (!(((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd) - && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) - && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)))) -#endif // PCIE_PS_SUPPORT // - { - pAd->bPCIclkOff = FALSE; - DBGPRINT(RT_DEBUG_TRACE, ("PSM :309xbPCIclkOff == %d\n", pAd->bPCIclkOff)); - - } -#endif // CONFIG_STA_SUPPORT // - // 2. Send wake up command. - AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02); - pAd->bPCIclkOff = FALSE; - // 2-1. wait command ok. - AsicCheckCommanOk(pAd, PowerWakeCID); - RTMP_ASIC_INTERRUPT_ENABLE(pAd); - - - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); - if (Level == GUI_IDLE_POWER_SAVE) - { -#ifdef PCIE_PS_SUPPORT - - // add by johnli, RF power sequence setup, load RF normal operation-mode setup - if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) - { - RTMP_CHIP_OP *pChipOps = &pAd->chipOps; - - if (pChipOps->AsicReverseRfFromSleepMode) - pChipOps->AsicReverseRfFromSleepMode(pAd); -#ifdef CONFIG_STA_SUPPORT - // 3090 MCU Wakeup command needs more time to be stable. - // Before stable, don't issue other MCU command to prevent from firmware error. - if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd) - && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) - && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) - { - RTMP_SEM_LOCK(&pAd->McuCmdLock); - pAd->brt30xxBanMcuCmd = FALSE; - RTMP_SEM_UNLOCK(&pAd->McuCmdLock); - } -#endif // CONFIG_STA_SUPPORT // - } - else - // end johnli -#endif // PCIE_PS_SUPPORT // - { - // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) - && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - } - else - { - // Must using 20MHz. - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - } - } -#endif // CONFIG_STA_SUPPORT // - } - } - return TRUE; - -} - - -/* - ========================================================================== - Description: - This routine sends command to firmware and turn our chip to power save mode. - Both RadioOff and .11 power save function needs to call this routine. - Input: - Level = GUIRADIO_OFF : GUI Radio Off mode - Level = DOT11POWERSAVE : 802.11 power save mode - Level = RTMP_HALT : When Disable device. - - ========================================================================== - */ -BOOLEAN RT28xxPciAsicRadioOff( - IN PRTMP_ADAPTER pAd, - IN UCHAR Level, - IN USHORT TbttNumToNextWakeUp) -{ -#ifdef CONFIG_STA_SUPPORT - WPDMA_GLO_CFG_STRUC DmaCfg; - UCHAR i, tempBBP_R3 = 0; -#endif // CONFIG_STA_SUPPORT // - BOOLEAN brc = FALSE, Cancelled; - UINT32 TbTTTime = 0; - UINT32 PsPollTime = 0/*, MACValue*/; - ULONG BeaconPeriodTime; - UINT32 RxDmaIdx, RxCpuIdx; - DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> Lv= %d, TxCpuIdx = %d, TxDmaIdx = %d. RxCpuIdx = %d, RxDmaIdx = %d.\n", Level,pAd->TxRing[0].TxCpuIdx, pAd->TxRing[0].TxDmaIdx, pAd->RxRing.RxCpuIdx, pAd->RxRing.RxDmaIdx)); - - if (pAd->OpMode == OPMODE_AP && Level==DOT11POWERSAVE) - return FALSE; - - // Check Rx DMA busy status, if more than half is occupied, give up this radio off. - RTMP_IO_READ32(pAd, RX_DRX_IDX , &RxDmaIdx); - RTMP_IO_READ32(pAd, RX_CRX_IDX , &RxCpuIdx); - if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE/3)) - { - DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return1. RxDmaIdx = %d , RxCpuIdx = %d. \n", RxDmaIdx, RxCpuIdx)); - return FALSE; - } - else if ((RxCpuIdx >= RxDmaIdx) && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE/3)) - { - DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return2. RxCpuIdx = %d. RxDmaIdx = %d , \n", RxCpuIdx, RxDmaIdx)); - return FALSE; - } - - // Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops. - //pAd->bPCIclkOffDisableTx = TRUE; - RTMP_SET_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) - && pAd->OpMode == OPMODE_STA -#ifdef CONFIG_STA_SUPPORT - &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE -#endif // CONFIG_STA_SUPPORT // - ) - { - - RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - - if (Level == DOT11POWERSAVE) - { - RTMP_IO_READ32(pAd, TBTT_TIMER, &TbTTTime); - TbTTTime &= 0x1ffff; - // 00. check if need to do sleep in this DTIM period. If next beacon will arrive within 30ms , ...doesn't necessarily sleep. - // TbTTTime uint = 64us, LEAD_TIME unit = 1024us, PsPollTime unit = 1ms - if (((64*TbTTTime) <((LEAD_TIME*1024) + 40000)) && (TbttNumToNextWakeUp == 0)) - { - DBGPRINT(RT_DEBUG_TRACE, ("TbTTTime = 0x%x , give up this sleep. \n", TbTTTime)); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); - //pAd->bPCIclkOffDisableTx = FALSE; - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); - return FALSE; - } - else - { - PsPollTime = (64*TbTTTime- LEAD_TIME*1024)/1000; -#ifdef PCIE_PS_SUPPORT -#ifdef CONFIG_STA_SUPPORT - if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd) - && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) - && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) - { - PsPollTime -= 5; - } - else -#endif // CONFIG_STA_SUPPORT // -#endif // PCIE_PS_SUPPORT // - PsPollTime -= 3; - - BeaconPeriodTime = pAd->CommonCfg.BeaconPeriod*102/100; - if (TbttNumToNextWakeUp > 0) - PsPollTime += ((TbttNumToNextWakeUp -1) * BeaconPeriodTime); - - pAd->Mlme.bPsPollTimerRunning = TRUE; - RTMPSetTimer(&pAd->Mlme.PsPollTimer, PsPollTime); - } - } - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOff::Level!=DOT11POWERSAVE \n")); - } - - pAd->bPCIclkOffDisableTx = FALSE; - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); - -#ifdef CONFIG_STA_SUPPORT - // Set to 1R. - if (pAd->Antenna.field.RxPath > 1 && pAd->OpMode == OPMODE_STA) - { - tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3); - } -#endif // CONFIG_STA_SUPPORT // - - // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. - if ((INFRA_ON(pAd) || pAd->OpMode == OPMODE_AP) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) - && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. - AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); - } - else - { - // Must using 20MHz. - AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); - } - - if (Level != RTMP_HALT) - { - // Change Interrupt bitmask. - // When PCI clock is off, don't want to service interrupt. - RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt); - } - else - { - RTMP_ASIC_INTERRUPT_DISABLE(pAd); - } - - - RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); - // 2. Send Sleep command - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); - // send POWER-SAVE command to MCU. high-byte = 1 save power as much as possible. high byte = 0 save less power - AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x1); - // 2-1. Wait command success - // Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task. - brc = AsicCheckCommanOk(pAd, PowerSafeCID); - - // 3. After 0x30 command is ok, send radio off command. lowbyte = 0 for power safe. - // If 0x30 command is not ok this time, we can ignore 0x35 command. It will make sure not cause firmware'r problem. - if ((Level == DOT11POWERSAVE) && (brc == TRUE)) - { - AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 0, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio. - // 3-1. Wait command success - AsicCheckCommanOk(pAd, PowerRadioOffCID); - } - else if (brc == TRUE) - { - AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 1, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio. - // 3-1. Wait command success - AsicCheckCommanOk(pAd, PowerRadioOffCID); - } - -#ifdef CONFIG_STA_SUPPORT - // 1. Wait DMA not busy - i = 0; - do - { - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); - if ((DmaCfg.field.RxDMABusy == 0) && (DmaCfg.field.TxDMABusy == 0)) - break; - RTMPusecDelay(20); - i++; - }while(i < 50); - - /* - if (i >= 50) - { - pAd->CheckDmaBusyCount++; - DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy. return on AsicRadioOff () CheckDmaBusyCount = %d \n", pAd->CheckDmaBusyCount)); - } - else - { - pAd->CheckDmaBusyCount = 0; - } - */ -#endif // CONFIG_STA_SUPPORT // -//KH Debug:My original codes have the follwoing codes, but currecnt codes do not have it. -// Disable for stability. If PCIE Link Control is modified for advance power save, re-covery this code segment. -RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x1280); -//OPSTATUS_SET_FLAG(pAd, fOP_STATUS_CLKSELECT_40MHZ); - -#ifdef PCIE_PS_SUPPORT -#ifdef CONFIG_STA_SUPPORT -if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd) - && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) - && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOff::3090 return to skip the following TbttNumToNextWakeUp setting for 279x\n")); - pAd->bPCIclkOff = TRUE; - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); - // For this case, doesn't need to below actions, so return here. - return brc; - } -#endif // CONFIG_STA_SUPPORT // -#endif // PCIE_PS_SUPPORT // - if (Level == DOT11POWERSAVE) - { - AUTO_WAKEUP_STRUC AutoWakeupCfg; - //RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90); - - // we have decided to SLEEP, so at least do it for a BEACON period. - if (TbttNumToNextWakeUp == 0) - TbttNumToNextWakeUp = 1; - - AutoWakeupCfg.word = 0; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - - // 1. Set auto wake up timer. - AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; - AutoWakeupCfg.field.EnableAutoWakeup = 1; - AutoWakeupCfg.field.AutoLeadTime = LEAD_TIME; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - } - -#ifdef CONFIG_STA_SUPPORT - // 4-1. If it's to disable our device. Need to restore PCI Configuration Space to its original value. - if (Level == RTMP_HALT && pAd->OpMode == OPMODE_STA) - { - if ((brc == TRUE) && (i < 50)) - RTMPPCIeLinkCtrlSetting(pAd, 1); - } - // 4. Set PCI configuration Space Link Comtrol fields. Only Radio Off needs to call this function - else if (pAd->OpMode == OPMODE_STA) - { - if ((brc == TRUE) && (i < 50)) - RTMPPCIeLinkCtrlSetting(pAd, 3); - } -#endif // CONFIG_STA_SUPPORT // - - //pAd->bPCIclkOffDisableTx = FALSE; - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); - return TRUE; -} - - - - -VOID RT28xxPciMlmeRadioOn( - IN PRTMP_ADAPTER pAd) -{ - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) - return; - - DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__)); - - if ((pAd->OpMode == OPMODE_AP) || - ((pAd->OpMode == OPMODE_STA) - && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) -#ifdef CONFIG_STA_SUPPORT - ||pAd->StaCfg.PSControl.field.EnableNewPS == FALSE -#endif // CONFIG_STA_SUPPORT // - ))) - { - RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); - //NICResetFromError(pAd); - - RTMPRingCleanUp(pAd, QID_AC_BK); - RTMPRingCleanUp(pAd, QID_AC_BE); - RTMPRingCleanUp(pAd, QID_AC_VI); - RTMPRingCleanUp(pAd, QID_AC_VO); - /*RTMPRingCleanUp(pAd, QID_HCCA);*/ - RTMPRingCleanUp(pAd, QID_MGMT); - RTMPRingCleanUp(pAd, QID_RX); - - // Enable Tx/Rx - RTMPEnableRxTx(pAd); - - // Clear Radio off flag - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); - // Set LED - RTMPSetLED(pAd, LED_RADIO_ON); - } - -#ifdef CONFIG_STA_SUPPORT - if ((pAd->OpMode == OPMODE_STA) && - (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - &&(pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) - { - BOOLEAN Cancelled; - - RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); - - pAd->Mlme.bPsPollTimerRunning = FALSE; - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); - RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 40); - } -#endif // CONFIG_STA_SUPPORT // -} - - -VOID RT28xxPciMlmeRadioOFF( - IN PRTMP_ADAPTER pAd) -{ - BOOLEAN brc=TRUE; - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) - return; - -#ifdef CONFIG_STA_SUPPORT - // Link down first if any association exists - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) - { - if (INFRA_ON(pAd) || ADHOC_ON(pAd)) - { - MLME_DISASSOC_REQ_STRUCT DisReq; - MLME_QUEUE_ELEM *pMsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); - - if (pMsgElem) - { - COPY_MAC_ADDR(&DisReq.Addr, pAd->CommonCfg.Bssid); - DisReq.Reason = REASON_DISASSOC_STA_LEAVING; - - pMsgElem->Machine = ASSOC_STATE_MACHINE; - pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ; - pMsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); - NdisMoveMemory(pMsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); - - MlmeDisassocReqAction(pAd, pMsgElem); - kfree(pMsgElem); - - RTMPusecDelay(1000); - } - } - } -#endif // CONFIG_STA_SUPPORT // - - DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__)); - - // Set LED - //RTMPSetLED(pAd, LED_RADIO_OFF); - // Set Radio off flag - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - BOOLEAN Cancelled; - if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) - { - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - { - RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); - } - // If during power safe mode. - if (pAd->StaCfg.bRadio == TRUE) - { - DBGPRINT(RT_DEBUG_TRACE,("-->MlmeRadioOff() return on bRadio == TRUE; \n")); - return; - } - // Always radio on since the NIC needs to set the MCU command (LED_RADIO_OFF). - if (IDLE_ON(pAd) && - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) - { - RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); - } - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - { - BOOLEAN Cancelled; - pAd->Mlme.bPsPollTimerRunning = FALSE; - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); - } - } - - // Link down first if any association exists - if (INFRA_ON(pAd) || ADHOC_ON(pAd)) - LinkDown(pAd, FALSE); - RTMPusecDelay(10000); - //========================================== - // Clean up old bss table - BssTableInit(&pAd->ScanTab); - - /* - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - { - RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); - return; - } - */ - } -#endif // CONFIG_STA_SUPPORT // - // Set LED.Move to here for fixing LED bug. This flag must be called after LinkDown - RTMPSetLED(pAd, LED_RADIO_OFF); - -#ifdef CONFIG_STA_SUPPORT -//KH Debug:All PCIe devices need to use timer to execute radio off function, or the PCIe&&EnableNewPS needs. -//KH Ans:It is right, because only when the PCIe and EnableNewPs is true, we need to delay the RadioOffTimer -//to avoid the deadlock with PCIe Power saving function. -if (pAd->OpMode == OPMODE_STA&& - OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)&& - pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) - { - RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); - } -else -#endif // CONFIG_STA_SUPPORT // -{ - - - brc=RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0); - - if (brc==FALSE) - { - DBGPRINT(RT_DEBUG_ERROR,("%s call RT28xxPciAsicRadioOff fail !!\n", __FUNCTION__)); - } -} -/* - // Disable Tx/Rx DMA - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA - GloCfg.field.EnableTxDMA = 0; - GloCfg.field.EnableRxDMA = 0; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); // abort all TX rings - - - // MAC_SYS_CTRL => value = 0x0 => 40mA - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0); - - // PWR_PIN_CFG => value = 0x0 => 40mA - RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0); - - // TX_PIN_CFG => value = 0x0 => 20mA - RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0); - - if (pAd->CommonCfg.BBPCurrentBW == BW_40) - { - // Must using 40MHz. - AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); - } - else - { - // Must using 20MHz. - AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); - } - - // Waiting for DMA idle - i = 0; - do - { - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); - if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) - break; - - RTMPusecDelay(1000); - }while (i++ < 100); -*/ -} - -#endif // RTMP_MAC_PCI // diff --git a/drivers/staging/rt3090/common/cmm_profile.c b/drivers/staging/rt3090/common/cmm_profile.c deleted file mode 100644 index 5803f422ae0960fbba420c63a9444e458fe97eec..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/cmm_profile.c +++ /dev/null @@ -1,2321 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - cmm_profile.c - - Abstract: - - Revision History: - Who When What - --------- ---------- ---------------------------------------------- - */ - -#include "../rt_config.h" - - -#define ETH_MAC_ADDR_STR_LEN 17 // in format of xx:xx:xx:xx:xx:xx - -// We assume the s1 is a sting, s2 is a memory space with 6 bytes. and content of s1 will be changed. -BOOLEAN rtstrmactohex(PSTRING s1, PSTRING s2) -{ - int i = 0; - PSTRING ptokS = s1, ptokE = s1; - - if (strlen(s1) != ETH_MAC_ADDR_STR_LEN) - return FALSE; - - while((*ptokS) != '\0') - { - if((ptokE = strchr(ptokS, ':')) != NULL) - *ptokE++ = '\0'; - if ((strlen(ptokS) != 2) || (!isxdigit(*ptokS)) || (!isxdigit(*(ptokS+1)))) - break; // fail - AtoH(ptokS, (PUCHAR)&s2[i++], 1); - ptokS = ptokE; - if (i == 6) - break; // parsing finished - } - - return ( i == 6 ? TRUE : FALSE); - -} - - -// we assume the s1 and s2 both are strings. -BOOLEAN rtstrcasecmp(PSTRING s1, PSTRING s2) -{ - PSTRING p1 = s1, p2 = s2; - - if (strlen(s1) != strlen(s2)) - return FALSE; - - while(*p1 != '\0') - { - if((*p1 != *p2) && ((*p1 ^ *p2) != 0x20)) - return FALSE; - p1++; - p2++; - } - - return TRUE; -} - -// we assume the s1 (buffer) and s2 (key) both are strings. -PSTRING rtstrstruncasecmp(PSTRING s1, PSTRING s2) -{ - INT l1, l2, i; - char temp1, temp2; - - l2 = strlen(s2); - if (!l2) - return (char *) s1; - - l1 = strlen(s1); - - while (l1 >= l2) - { - l1--; - - for(i=0; i= l2) - { - l1--; - if (!memcmp(s1,s2,l2)) - return s1; - s1++; - } - - return NULL; -} - -/** - * rstrtok - Split a string into tokens - * @s: The string to be searched - * @ct: The characters to search for - * * WARNING: strtok is deprecated, use strsep instead. However strsep is not compatible with old architecture. - */ -PSTRING __rstrtok; -PSTRING rstrtok(PSTRING s,const PSTRING ct) -{ - PSTRING sbegin, send; - - sbegin = s ? s : __rstrtok; - if (!sbegin) - { - return NULL; - } - - sbegin += strspn(sbegin,ct); - if (*sbegin == '\0') - { - __rstrtok = NULL; - return( NULL ); - } - - send = strpbrk( sbegin, ct); - if (send && *send != '\0') - *send++ = '\0'; - - __rstrtok = send; - - return (sbegin); -} - -/** - * delimitcnt - return the count of a given delimiter in a given string. - * @s: The string to be searched. - * @ct: The delimiter to search for. - * Notice : We suppose the delimiter is a single-char string(for example : ";"). - */ -INT delimitcnt(PSTRING s,PSTRING ct) -{ - INT count = 0; - /* point to the beginning of the line */ - PSTRING token = s; - - for ( ;; ) - { - token = strpbrk(token, ct); /* search for delimiters */ - - if ( token == NULL ) - { - /* advanced to the terminating null character */ - break; - } - /* skip the delimiter */ - ++token; - - /* - * Print the found text: use len with %.*s to specify field width. - */ - - /* accumulate delimiter count */ - ++count; - } - return count; -} - -/* - * converts the Internet host address from the standard numbers-and-dots notation - * into binary data. - * returns nonzero if the address is valid, zero if not. - */ -int rtinet_aton(PSTRING cp, unsigned int *addr) -{ - unsigned int val; - int base, n; - STRING c; - unsigned int parts[4]; - unsigned int *pp = parts; - - for (;;) - { - /* - * Collect number up to ``.''. - * Values are specified as for C: - * 0x=hex, 0=octal, other=decimal. - */ - val = 0; - base = 10; - if (*cp == '0') - { - if (*++cp == 'x' || *cp == 'X') - base = 16, cp++; - else - base = 8; - } - while ((c = *cp) != '\0') - { - if (isdigit((unsigned char) c)) - { - val = (val * base) + (c - '0'); - cp++; - continue; - } - if (base == 16 && isxdigit((unsigned char) c)) - { - val = (val << 4) + - (c + 10 - (islower((unsigned char) c) ? 'a' : 'A')); - cp++; - continue; - } - break; - } - if (*cp == '.') - { - /* - * Internet format: a.b.c.d a.b.c (with c treated as 16-bits) - * a.b (with b treated as 24 bits) - */ - if (pp >= parts + 3 || val > 0xff) - return 0; - *pp++ = val, cp++; - } - else - break; - } - - /* - * Check for trailing junk. - */ - while (*cp) - if (!isspace((unsigned char) *cp++)) - return 0; - - /* - * Concoct the address according to the number of parts specified. - */ - n = pp - parts + 1; - switch (n) - { - - case 1: /* a -- 32 bits */ - break; - - case 2: /* a.b -- 8.24 bits */ - if (val > 0xffffff) - return 0; - val |= parts[0] << 24; - break; - - case 3: /* a.b.c -- 8.8.16 bits */ - if (val > 0xffff) - return 0; - val |= (parts[0] << 24) | (parts[1] << 16); - break; - - case 4: /* a.b.c.d -- 8.8.8.8 bits */ - if (val > 0xff) - return 0; - val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); - break; - } - - *addr = htonl(val); - return 1; - -} - -/* - ======================================================================== - - Routine Description: - Find key section for Get key parameter. - - Arguments: - buffer Pointer to the buffer to start find the key section - section the key of the secion to be find - - Return Value: - NULL Fail - Others Success - ======================================================================== -*/ -PSTRING RTMPFindSection( - IN PSTRING buffer) -{ - STRING temp_buf[32]; - PSTRING ptr; - - strcpy(temp_buf, "Default"); - - if((ptr = rtstrstr(buffer, temp_buf)) != NULL) - return (ptr+strlen("\n")); - else - return NULL; -} - -/* - ======================================================================== - - Routine Description: - Get key parameter. - - Arguments: - key Pointer to key string - dest Pointer to destination - destsize The datasize of the destination - buffer Pointer to the buffer to start find the key - bTrimSpace Set true if you want to strip the space character of the result pattern - - Return Value: - TRUE Success - FALSE Fail - - Note: - This routine get the value with the matched key (case case-sensitive) - For SSID and security key related parameters, we SHALL NOT trim the space(' ') character. - ======================================================================== -*/ -INT RTMPGetKeyParameter( - IN PSTRING key, - OUT PSTRING dest, - IN INT destsize, - IN PSTRING buffer, - IN BOOLEAN bTrimSpace) -{ - PSTRING pMemBuf, temp_buf1 = NULL, temp_buf2 = NULL; - PSTRING start_ptr, end_ptr; - PSTRING ptr; - PSTRING offset = NULL; - INT len, keyLen; - - - keyLen = strlen(key); - os_alloc_mem(NULL, (PUCHAR *)&pMemBuf, MAX_PARAM_BUFFER_SIZE * 2); - if (pMemBuf == NULL) - return (FALSE); - - memset(pMemBuf, 0, MAX_PARAM_BUFFER_SIZE * 2); - temp_buf1 = pMemBuf; - temp_buf2 = (PSTRING)(pMemBuf + MAX_PARAM_BUFFER_SIZE); - - - //find section - if((offset = RTMPFindSection(buffer)) == NULL) - { - os_free_mem(NULL, (PUCHAR)pMemBuf); - return (FALSE); - } - - strcpy(temp_buf1, "\n"); - strcat(temp_buf1, key); - strcat(temp_buf1, "="); - - //search key - if((start_ptr=rtstrstr(offset, temp_buf1)) == NULL) - { - os_free_mem(NULL, (PUCHAR)pMemBuf); - return (FALSE); - } - - start_ptr += strlen("\n"); - if((end_ptr = rtstrstr(start_ptr, "\n"))==NULL) - end_ptr = start_ptr+strlen(start_ptr); - - if (end_ptr= 1 ) && (KeyIdx <= 4)) - pAd->StaCfg.DefaultKeyId = (UCHAR) (KeyIdx - 1); - else - pAd->StaCfg.DefaultKeyId = 0; - - DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyID(0~3)=%d\n", pAd->StaCfg.DefaultKeyId)); - } -#endif // CONFIG_STA_SUPPORT // - } - - - for (idx = 0; idx < 4; idx++) - { - sprintf(tok_str, "Key%dType", idx + 1); - //Key1Type - if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, TRUE)) - { - for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) - { - /* - do sanity check for KeyType length; - or in station mode, the KeyType length > 1, - the code will overwrite the stack of caller - (RTMPSetProfileParameters) and cause srcbuf = NULL - */ - if (i < MAX_MBSSID_NUM) - KeyType[i] = simple_strtol(macptr, 0, 10); - } - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - sprintf(tok_str, "Key%dStr", idx + 1); - if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE)) - { - rtmp_parse_key_buffer_from_file(pAd, tmpbuf, KeyType[BSS0], BSS0, idx); - } - } -#endif // CONFIG_STA_SUPPORT // - } - } -} - - - -#ifdef CONFIG_STA_SUPPORT -static void rtmp_read_sta_wmm_parms_from_file(IN PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer) -{ - PSTRING macptr; - INT i=0; - BOOLEAN bWmmEnable = FALSE; - - //WmmCapable - if(RTMPGetKeyParameter("WmmCapable", tmpbuf, 32, buffer, TRUE)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable - { - pAd->CommonCfg.bWmmCapable = TRUE; - bWmmEnable = TRUE; - } - else //Disable - { - pAd->CommonCfg.bWmmCapable = FALSE; - } - - DBGPRINT(RT_DEBUG_TRACE, ("WmmCapable=%d\n", pAd->CommonCfg.bWmmCapable)); - } - -#ifdef QOS_DLS_SUPPORT - //DLSCapable - if(RTMPGetKeyParameter("DLSCapable", tmpbuf, 32, buffer, TRUE)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable - { - pAd->CommonCfg.bDLSCapable = TRUE; - } - else //Disable - { - pAd->CommonCfg.bDLSCapable = FALSE; - } - - DBGPRINT(RT_DEBUG_TRACE, ("bDLSCapable=%d\n", pAd->CommonCfg.bDLSCapable)); - } -#endif // QOS_DLS_SUPPORT // - - //AckPolicy for AC_BK, AC_BE, AC_VI, AC_VO - if(RTMPGetKeyParameter("AckPolicy", tmpbuf, 32, buffer, TRUE)) - { - for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) - { - pAd->CommonCfg.AckPolicy[i] = (UCHAR)simple_strtol(macptr, 0, 10); - - DBGPRINT(RT_DEBUG_TRACE, ("AckPolicy[%d]=%d\n", i, pAd->CommonCfg.AckPolicy[i])); - } - } - - if (bWmmEnable) - { - //APSDCapable - if(RTMPGetKeyParameter("APSDCapable", tmpbuf, 10, buffer, TRUE)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable - pAd->CommonCfg.bAPSDCapable = TRUE; - else - pAd->CommonCfg.bAPSDCapable = FALSE; - - DBGPRINT(RT_DEBUG_TRACE, ("APSDCapable=%d\n", pAd->CommonCfg.bAPSDCapable)); - } - - //MaxSPLength - if(RTMPGetKeyParameter("MaxSPLength", tmpbuf, 10, buffer, TRUE)) - { - pAd->CommonCfg.MaxSPLength = simple_strtol(tmpbuf, 0, 10); - - DBGPRINT(RT_DEBUG_TRACE, ("MaxSPLength=%d\n", pAd->CommonCfg.MaxSPLength)); - } - - //APSDAC for AC_BE, AC_BK, AC_VI, AC_VO - if(RTMPGetKeyParameter("APSDAC", tmpbuf, 32, buffer, TRUE)) - { - BOOLEAN apsd_ac[4]; - - for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) - { - apsd_ac[i] = (BOOLEAN)simple_strtol(macptr, 0, 10); - - DBGPRINT(RT_DEBUG_TRACE, ("APSDAC%d %d\n", i, apsd_ac[i])); - } - - pAd->CommonCfg.bAPSDAC_BE = apsd_ac[0]; - pAd->CommonCfg.bAPSDAC_BK = apsd_ac[1]; - pAd->CommonCfg.bAPSDAC_VI = apsd_ac[2]; - pAd->CommonCfg.bAPSDAC_VO = apsd_ac[3]; - - pAd->CommonCfg.bACMAPSDTr[0] = apsd_ac[0]; - pAd->CommonCfg.bACMAPSDTr[1] = apsd_ac[1]; - pAd->CommonCfg.bACMAPSDTr[2] = apsd_ac[2]; - pAd->CommonCfg.bACMAPSDTr[3] = apsd_ac[3]; - } - } - -} -#endif // CONFIG_STA_SUPPORT // - - -#ifdef DOT11_N_SUPPORT -static void HTParametersHook( - IN PRTMP_ADAPTER pAd, - IN PSTRING pValueStr, - IN PSTRING pInput) -{ - - long Value; - - if (RTMPGetKeyParameter("HT_PROTECT", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.bHTProtect = FALSE; - } - else - { - pAd->CommonCfg.bHTProtect = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: Protection = %s\n", (Value==0) ? "Disable" : "Enable")); - } - - if (RTMPGetKeyParameter("HT_MIMOPSEnable", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.bMIMOPSEnable = FALSE; - } - else - { - pAd->CommonCfg.bMIMOPSEnable = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPSEnable = %s\n", (Value==0) ? "Disable" : "Enable")); - } - - - if (RTMPGetKeyParameter("HT_MIMOPSMode", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value > MMPS_ENABLE) - { - pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; - } - else - { - //TODO: add mimo power saving mechanism - pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; - //pAd->CommonCfg.BACapability.field.MMPSmode = Value; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPS Mode = %d\n", (INT) Value)); - } - - if (RTMPGetKeyParameter("HT_BADecline", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.bBADecline = FALSE; - } - else - { - pAd->CommonCfg.bBADecline = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Decline = %s\n", (Value==0) ? "Disable" : "Enable")); - } - - - if (RTMPGetKeyParameter("HT_DisableReordering", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.bDisableReordering = FALSE; - } - else - { - pAd->CommonCfg.bDisableReordering = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: DisableReordering = %s\n", (Value==0) ? "Disable" : "Enable")); - } - - if (RTMPGetKeyParameter("HT_AutoBA", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.BACapability.field.AutoBA = FALSE; - pAd->CommonCfg.BACapability.field.Policy = BA_NOTUSE; - } - else - { - pAd->CommonCfg.BACapability.field.AutoBA = TRUE; - pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; - } - pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA; - DBGPRINT(RT_DEBUG_TRACE, ("HT: Auto BA = %s\n", (Value==0) ? "Disable" : "Enable")); - } - - // Tx_+HTC frame - if (RTMPGetKeyParameter("HT_HTC", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->HTCEnable = FALSE; - } - else - { - pAd->HTCEnable = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx +HTC frame = %s\n", (Value==0) ? "Disable" : "Enable")); - } - - // Enable HT Link Adaptation Control - if (RTMPGetKeyParameter("HT_LinkAdapt", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->bLinkAdapt = FALSE; - } - else - { - pAd->HTCEnable = TRUE; - pAd->bLinkAdapt = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: Link Adaptation Control = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)")); - } - - // Reverse Direction Mechanism - if (RTMPGetKeyParameter("HT_RDG", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.bRdg = FALSE; - } - else - { - pAd->HTCEnable = TRUE; - pAd->CommonCfg.bRdg = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: RDG = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)")); - } - - - - - // Tx A-MSUD ? - if (RTMPGetKeyParameter("HT_AMSDU", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE; - } - else - { - pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx A-MSDU = %s\n", (Value==0) ? "Disable" : "Enable")); - } - - // MPDU Density - if (RTMPGetKeyParameter("HT_MpduDensity", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value <=7 && Value >= 0) - { - pAd->CommonCfg.BACapability.field.MpduDensity = Value; - DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d\n", (INT) Value)); - } - else - { - pAd->CommonCfg.BACapability.field.MpduDensity = 4; - DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d (Default)\n", 4)); - } - } - - // Max Rx BA Window Size - if (RTMPGetKeyParameter("HT_BAWinSize", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - - if (Value >=1 && Value <= 64) - { - pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value; - pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value; - DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = %d\n", (INT) Value)); - } - else - { - pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64; - pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; - DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = 64 (Defualt)\n")); - } - - } - - // Guard Interval - if (RTMPGetKeyParameter("HT_GI", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - - if (Value == GI_400) - { - pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400; - } - else - { - pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800; - } - - DBGPRINT(RT_DEBUG_TRACE, ("HT: Guard Interval = %s\n", (Value==GI_400) ? "400" : "800" )); - } - - // HT Operation Mode : Mixed Mode , Green Field - if (RTMPGetKeyParameter("HT_OpMode", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - - if (Value == HTMODE_GF) - { - - pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF; - } - else - { - pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM; - } - - DBGPRINT(RT_DEBUG_TRACE, ("HT: Operate Mode = %s\n", (Value==HTMODE_GF) ? "Green Field" : "Mixed Mode" )); - } - - // Fixed Tx mode : CCK, OFDM - if (RTMPGetKeyParameter("FixedTxMode", pValueStr, 25, pInput, TRUE)) - { - UCHAR fix_tx_mode; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - fix_tx_mode = FIXED_TXMODE_HT; - - if (strcmp(pValueStr, "OFDM") == 0 || strcmp(pValueStr, "ofdm") == 0) - { - fix_tx_mode = FIXED_TXMODE_OFDM; - } - else if (strcmp(pValueStr, "CCK") == 0 || strcmp(pValueStr, "cck") == 0) - { - fix_tx_mode = FIXED_TXMODE_CCK; - } - else if (strcmp(pValueStr, "HT") == 0 || strcmp(pValueStr, "ht") == 0) - { - fix_tx_mode = FIXED_TXMODE_HT; - } - else - { - Value = simple_strtol(pValueStr, 0, 10); - // 1 : CCK - // 2 : OFDM - // otherwise : HT - if (Value == FIXED_TXMODE_CCK || Value == FIXED_TXMODE_OFDM) - fix_tx_mode = Value; - else - fix_tx_mode = FIXED_TXMODE_HT; - } - - pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode; - DBGPRINT(RT_DEBUG_TRACE, ("Fixed Tx Mode = %d\n", fix_tx_mode)); - - } -#endif // CONFIG_STA_SUPPORT // - } - - - // Channel Width - if (RTMPGetKeyParameter("HT_BW", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - - if (Value == BW_40) - { - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; - } - else - { - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; - } - -#ifdef MCAST_RATE_SPECIFIC - pAd->CommonCfg.MCastPhyMode.field.BW = pAd->CommonCfg.RegTransmitSetting.field.BW; -#endif // MCAST_RATE_SPECIFIC // - - DBGPRINT(RT_DEBUG_TRACE, ("HT: Channel Width = %s\n", (Value==BW_40) ? "40 MHz" : "20 MHz" )); - } - - if (RTMPGetKeyParameter("HT_EXTCHA", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - - if (Value == 0) - { - - pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; - } - else - { - pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; - } - - DBGPRINT(RT_DEBUG_TRACE, ("HT: Ext Channel = %s\n", (Value==0) ? "BELOW" : "ABOVE" )); - } - - // MSC - if (RTMPGetKeyParameter("HT_MCS", pValueStr, 50, pInput, TRUE)) - { - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - Value = simple_strtol(pValueStr, 0, 10); - -// if ((Value >= 0 && Value <= 15) || (Value == 32)) - if ((Value >= 0 && Value <= 23) || (Value == 32)) // 3*3 - { - pAd->StaCfg.DesiredTransmitSetting.field.MCS = Value; - pAd->StaCfg.bAutoTxRateSwitch = FALSE; - DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = %d\n", pAd->StaCfg.DesiredTransmitSetting.field.MCS)); - } - else - { - pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; - pAd->StaCfg.bAutoTxRateSwitch = TRUE; - DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = AUTO\n")); - } - } -#endif // CONFIG_STA_SUPPORT // - } - - // STBC - if (RTMPGetKeyParameter("HT_STBC", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == STBC_USE) - { - pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE; - } - else - { - pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: STBC = %d\n", pAd->CommonCfg.RegTransmitSetting.field.STBC)); - } - - // 40_Mhz_Intolerant - if (RTMPGetKeyParameter("HT_40MHZ_INTOLERANT", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.bForty_Mhz_Intolerant = FALSE; - } - else - { - pAd->CommonCfg.bForty_Mhz_Intolerant = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: 40MHZ INTOLERANT = %d\n", pAd->CommonCfg.bForty_Mhz_Intolerant)); - } - //HT_TxStream - if(RTMPGetKeyParameter("HT_TxStream", pValueStr, 10, pInput, TRUE)) - { - switch (simple_strtol(pValueStr, 0, 10)) - { - case 1: - pAd->CommonCfg.TxStream = 1; - break; - case 2: - pAd->CommonCfg.TxStream = 2; - break; - case 3: // 3*3 - default: - pAd->CommonCfg.TxStream = 3; - - if (pAd->MACVersion < RALINK_2883_VERSION) - pAd->CommonCfg.TxStream = 2; // only 2 tx streams for RT2860 series - break; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx Stream = %d\n", pAd->CommonCfg.TxStream)); - } - //HT_RxStream - if(RTMPGetKeyParameter("HT_RxStream", pValueStr, 10, pInput, TRUE)) - { - switch (simple_strtol(pValueStr, 0, 10)) - { - case 1: - pAd->CommonCfg.RxStream = 1; - break; - case 2: - pAd->CommonCfg.RxStream = 2; - break; - case 3: - default: - pAd->CommonCfg.RxStream = 3; - - if (pAd->MACVersion < RALINK_2883_VERSION) - pAd->CommonCfg.RxStream = 2; // only 2 rx streams for RT2860 series - break; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: Rx Stream = %d\n", pAd->CommonCfg.RxStream)); - } - //2008/11/05: KH add to support Antenna power-saving of AP<-- - //Green AP - if(RTMPGetKeyParameter("GreenAP", pValueStr, 10, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - if (Value == 0) - { - pAd->CommonCfg.bGreenAPEnable = FALSE; - } - else - { - pAd->CommonCfg.bGreenAPEnable = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("HT: Green AP= %d\n", pAd->CommonCfg.bGreenAPEnable)); - } - - // HT_DisallowTKIP - if (RTMPGetKeyParameter("HT_DisallowTKIP", pValueStr, 25, pInput, TRUE)) - { - Value = simple_strtol(pValueStr, 0, 10); - - if (Value == 1) - { - pAd->CommonCfg.HT_DisallowTKIP = TRUE; - } - else - { - pAd->CommonCfg.HT_DisallowTKIP = FALSE; - } - - DBGPRINT(RT_DEBUG_TRACE, ("HT: Disallow TKIP mode = %s\n", (pAd->CommonCfg.HT_DisallowTKIP == TRUE) ? "ON" : "OFF" )); - } - - - //2008/11/05:KH add to support Antenna power-saving of AP--> -} -#endif // DOT11_N_SUPPORT // - - -NDIS_STATUS RTMPSetProfileParameters( - IN RTMP_ADAPTER *pAd, - IN PSTRING pBuffer) -{ - PSTRING tmpbuf; - ULONG RtsThresh; - ULONG FragThresh; - PSTRING macptr; - INT i = 0, retval; - tmpbuf = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG); - if(tmpbuf == NULL) - return NDIS_STATUS_FAILURE; - - do - { - // set file parameter to portcfg - //CountryRegion - if(RTMPGetKeyParameter("CountryRegion", tmpbuf, 25, pBuffer, TRUE)) - { - retval = RT_CfgSetCountryRegion(pAd, tmpbuf, BAND_24G); - DBGPRINT(RT_DEBUG_TRACE, ("CountryRegion=%d\n", pAd->CommonCfg.CountryRegion)); - } - //CountryRegionABand - if(RTMPGetKeyParameter("CountryRegionABand", tmpbuf, 25, pBuffer, TRUE)) - { - retval = RT_CfgSetCountryRegion(pAd, tmpbuf, BAND_5G); - DBGPRINT(RT_DEBUG_TRACE, ("CountryRegionABand=%d\n", pAd->CommonCfg.CountryRegionForABand)); - } -#ifdef RTMP_EFUSE_SUPPORT -#ifdef RT30xx - //EfuseBufferMode - if(RTMPGetKeyParameter("EfuseBufferMode", tmpbuf, 25, pBuffer, TRUE)) - { - pAd->bEEPROMFile = (UCHAR) simple_strtol(tmpbuf, 0, 10); - DBGPRINT(RT_DEBUG_TRACE, ("EfuseBufferMode=%d\n", pAd->bUseEfuse)); - } -#endif // RT30xx // -#endif // RTMP_EFUSE_SUPPORT // - //CountryCode - if(RTMPGetKeyParameter("CountryCode", tmpbuf, 25, pBuffer, TRUE)) - { - NdisMoveMemory(pAd->CommonCfg.CountryCode, tmpbuf , 2); -#ifdef CONFIG_STA_SUPPORT -#ifdef EXT_BUILD_CHANNEL_LIST - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - NdisMoveMemory(pAd->StaCfg.StaOriCountryCode, tmpbuf , 2); -#endif // EXT_BUILD_CHANNEL_LIST // -#endif // CONFIG_STA_SUPPORT // - if (strlen((PSTRING) pAd->CommonCfg.CountryCode) != 0) - { - pAd->CommonCfg.bCountryFlag = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("CountryCode=%s\n", pAd->CommonCfg.CountryCode)); - } - //ChannelGeography - if(RTMPGetKeyParameter("ChannelGeography", tmpbuf, 25, pBuffer, TRUE)) - { - UCHAR Geography = (UCHAR) simple_strtol(tmpbuf, 0, 10); - if (Geography <= BOTH) - { - pAd->CommonCfg.Geography = Geography; - pAd->CommonCfg.CountryCode[2] = - (pAd->CommonCfg.Geography == BOTH) ? ' ' : ((pAd->CommonCfg.Geography == IDOR) ? 'I' : 'O'); -#ifdef CONFIG_STA_SUPPORT -#ifdef EXT_BUILD_CHANNEL_LIST - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - pAd->StaCfg.StaOriGeography = pAd->CommonCfg.Geography; -#endif // EXT_BUILD_CHANNEL_LIST // -#endif // CONFIG_STA_SUPPORT // - DBGPRINT(RT_DEBUG_TRACE, ("ChannelGeography=%d\n", pAd->CommonCfg.Geography)); - } - } - else - { - pAd->CommonCfg.Geography = BOTH; - pAd->CommonCfg.CountryCode[2] = ' '; - } - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - //SSID - if (RTMPGetKeyParameter("SSID", tmpbuf, 256, pBuffer, FALSE)) - { - if (strlen(tmpbuf) <= 32) - { - pAd->CommonCfg.SsidLen = (UCHAR) strlen(tmpbuf); - NdisZeroMemory(pAd->CommonCfg.Ssid, NDIS_802_11_LENGTH_SSID); - NdisMoveMemory(pAd->CommonCfg.Ssid, tmpbuf, pAd->CommonCfg.SsidLen); - pAd->MlmeAux.AutoReconnectSsidLen = pAd->CommonCfg.SsidLen; - NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, NDIS_802_11_LENGTH_SSID); - NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, tmpbuf, pAd->MlmeAux.AutoReconnectSsidLen); - pAd->MlmeAux.SsidLen = pAd->CommonCfg.SsidLen; - NdisZeroMemory(pAd->MlmeAux.Ssid, NDIS_802_11_LENGTH_SSID); - NdisMoveMemory(pAd->MlmeAux.Ssid, tmpbuf, pAd->MlmeAux.SsidLen); - DBGPRINT(RT_DEBUG_TRACE, ("%s::(SSID=%s)\n", __FUNCTION__, tmpbuf)); - } - } - } -#endif // CONFIG_STA_SUPPORT // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - //NetworkType - if (RTMPGetKeyParameter("NetworkType", tmpbuf, 25, pBuffer, TRUE)) - { - pAd->bConfigChanged = TRUE; - if (strcmp(tmpbuf, "Adhoc") == 0) - pAd->StaCfg.BssType = BSS_ADHOC; - else //Default Infrastructure mode - pAd->StaCfg.BssType = BSS_INFRA; - // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key - pAd->StaCfg.WpaState = SS_NOTUSE; - DBGPRINT(RT_DEBUG_TRACE, ("%s::(NetworkType=%d)\n", __FUNCTION__, pAd->StaCfg.BssType)); - } - } -#ifdef RTMP_MAC_PCI - //NewPCIePS - if(RTMPGetKeyParameter("NewPCIePS", tmpbuf, 10, pBuffer, TRUE)) - { - UCHAR temp_buffer = (UCHAR) simple_strtol(tmpbuf, 0, 10); - if(temp_buffer>0) - pAd->StaCfg.PSControl.field.EnableNewPS=TRUE; - else - pAd->StaCfg.PSControl.field.EnableNewPS=FALSE; - DBGPRINT(RT_DEBUG_TRACE, ("NewPCIePS=%d\n", pAd->StaCfg.PSControl.field.EnableNewPS)); - } -#endif // RTMP_MAC_PCI // -#ifdef RT3090 - //PCIePowerLevel - - if(RTMPGetKeyParameter("PCIePowerLevel", tmpbuf, 10, pBuffer, TRUE)) - { - pAd->StaCfg.PSControl.field.rt30xxPowerMode = (UCHAR) simple_strtol(tmpbuf, 0, 10); - DBGPRINT(RT_DEBUG_TRACE, ("PCIePowerLevel=%d\n", pAd->StaCfg.PSControl.field.rt30xxPowerMode)); - } - //FollowHostASPM - if(RTMPGetKeyParameter("FollowHostASPM", tmpbuf, 10, pBuffer, TRUE)) - { - UCHAR temp_buffer = (UCHAR) simple_strtol(tmpbuf, 0, 10); - - if(temp_buffer>0) - pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM=TRUE; - else - pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM=FALSE; - DBGPRINT(RT_DEBUG_TRACE, ("rt30xxFollowHostASPM=%d\n", pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM)); - } - //ForceTestASPM - if(RTMPGetKeyParameter("ForceTestASPM", tmpbuf, 10, pBuffer, TRUE)) - { - UCHAR temp_buffer = (UCHAR) simple_strtol(tmpbuf, 0, 10); - - if(temp_buffer>0) - pAd->StaCfg.PSControl.field.rt30xxForceASPMTest=TRUE; - else - pAd->StaCfg.PSControl.field.rt30xxForceASPMTest=FALSE; - DBGPRINT(RT_DEBUG_TRACE, ("rt30xxForceASPM=%d\n", pAd->StaCfg.PSControl.field.rt30xxForceASPMTest)); - } -#endif // RT3090 // -#endif // CONFIG_STA_SUPPORT // - //Channel - if(RTMPGetKeyParameter("Channel", tmpbuf, 10, pBuffer, TRUE)) - { - pAd->CommonCfg.Channel = (UCHAR) simple_strtol(tmpbuf, 0, 10); - DBGPRINT(RT_DEBUG_TRACE, ("Channel=%d\n", pAd->CommonCfg.Channel)); - } - //WirelessMode - if(RTMPGetKeyParameter("WirelessMode", tmpbuf, 10, pBuffer, TRUE)) - { - RT_CfgSetWirelessMode(pAd, tmpbuf); - DBGPRINT(RT_DEBUG_TRACE, ("PhyMode=%d\n", pAd->CommonCfg.PhyMode)); - } - //BasicRate - if(RTMPGetKeyParameter("BasicRate", tmpbuf, 10, pBuffer, TRUE)) - { - pAd->CommonCfg.BasicRateBitmap = (ULONG) simple_strtol(tmpbuf, 0, 10); - DBGPRINT(RT_DEBUG_TRACE, ("BasicRate=%ld\n", pAd->CommonCfg.BasicRateBitmap)); - } - //BeaconPeriod - if(RTMPGetKeyParameter("BeaconPeriod", tmpbuf, 10, pBuffer, TRUE)) - { - pAd->CommonCfg.BeaconPeriod = (USHORT) simple_strtol(tmpbuf, 0, 10); - DBGPRINT(RT_DEBUG_TRACE, ("BeaconPeriod=%d\n", pAd->CommonCfg.BeaconPeriod)); - } - //TxPower - if(RTMPGetKeyParameter("TxPower", tmpbuf, 10, pBuffer, TRUE)) - { - pAd->CommonCfg.TxPowerPercentage = (ULONG) simple_strtol(tmpbuf, 0, 10); -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - pAd->CommonCfg.TxPowerDefault = pAd->CommonCfg.TxPowerPercentage; -#endif // CONFIG_STA_SUPPORT // - DBGPRINT(RT_DEBUG_TRACE, ("TxPower=%ld\n", pAd->CommonCfg.TxPowerPercentage)); - } - //BGProtection - if(RTMPGetKeyParameter("BGProtection", tmpbuf, 10, pBuffer, TRUE)) - { - //#if 0 //#ifndef WIFI_TEST - // pAd->CommonCfg.UseBGProtection = 2;// disable b/g protection for throughput test - //#else - switch (simple_strtol(tmpbuf, 0, 10)) - { - case 1: //Always On - pAd->CommonCfg.UseBGProtection = 1; - break; - case 2: //Always OFF - pAd->CommonCfg.UseBGProtection = 2; - break; - case 0: //AUTO - default: - pAd->CommonCfg.UseBGProtection = 0; - break; - } - //#endif - DBGPRINT(RT_DEBUG_TRACE, ("BGProtection=%ld\n", pAd->CommonCfg.UseBGProtection)); - } - //OLBCDetection - if(RTMPGetKeyParameter("DisableOLBC", tmpbuf, 10, pBuffer, TRUE)) - { - switch (simple_strtol(tmpbuf, 0, 10)) - { - case 1: //disable OLBC Detection - pAd->CommonCfg.DisableOLBCDetect = 1; - break; - case 0: //enable OLBC Detection - pAd->CommonCfg.DisableOLBCDetect = 0; - break; - default: - pAd->CommonCfg.DisableOLBCDetect= 0; - break; - } - DBGPRINT(RT_DEBUG_TRACE, ("OLBCDetection=%ld\n", pAd->CommonCfg.DisableOLBCDetect)); - } - //TxPreamble - if(RTMPGetKeyParameter("TxPreamble", tmpbuf, 10, pBuffer, TRUE)) - { - switch (simple_strtol(tmpbuf, 0, 10)) - { - case Rt802_11PreambleShort: - pAd->CommonCfg.TxPreamble = Rt802_11PreambleShort; - break; - case Rt802_11PreambleLong: - default: - pAd->CommonCfg.TxPreamble = Rt802_11PreambleLong; - break; - } - DBGPRINT(RT_DEBUG_TRACE, ("TxPreamble=%ld\n", pAd->CommonCfg.TxPreamble)); - } - //RTSThreshold - if(RTMPGetKeyParameter("RTSThreshold", tmpbuf, 10, pBuffer, TRUE)) - { - RtsThresh = simple_strtol(tmpbuf, 0, 10); - if( (RtsThresh >= 1) && (RtsThresh <= MAX_RTS_THRESHOLD) ) - pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh; - else - pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD; - - DBGPRINT(RT_DEBUG_TRACE, ("RTSThreshold=%d\n", pAd->CommonCfg.RtsThreshold)); - } - //FragThreshold - if(RTMPGetKeyParameter("FragThreshold", tmpbuf, 10, pBuffer, TRUE)) - { - FragThresh = simple_strtol(tmpbuf, 0, 10); - pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; - - if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD) - { //illegal FragThresh so we set it to default - pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; - pAd->CommonCfg.bUseZeroToDisableFragment = TRUE; - } - else if (FragThresh % 2 == 1) - { - // The length of each fragment shall always be an even number of octets, except for the last fragment - // of an MSDU or MMPDU, which may be either an even or an odd number of octets. - pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1); - } - else - { - pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh; - } - //pAd->CommonCfg.AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; - DBGPRINT(RT_DEBUG_TRACE, ("FragThreshold=%d\n", pAd->CommonCfg.FragmentThreshold)); - } - //TxBurst - if(RTMPGetKeyParameter("TxBurst", tmpbuf, 10, pBuffer, TRUE)) - { - //#ifdef WIFI_TEST - // pAd->CommonCfg.bEnableTxBurst = FALSE; - //#else - if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable - pAd->CommonCfg.bEnableTxBurst = TRUE; - else //Disable - pAd->CommonCfg.bEnableTxBurst = FALSE; - //#endif - DBGPRINT(RT_DEBUG_TRACE, ("TxBurst=%d\n", pAd->CommonCfg.bEnableTxBurst)); - } - -#ifdef AGGREGATION_SUPPORT - //PktAggregate - if(RTMPGetKeyParameter("PktAggregate", tmpbuf, 10, pBuffer, TRUE)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable - pAd->CommonCfg.bAggregationCapable = TRUE; - else //Disable - pAd->CommonCfg.bAggregationCapable = FALSE; -#ifdef PIGGYBACK_SUPPORT - pAd->CommonCfg.bPiggyBackCapable = pAd->CommonCfg.bAggregationCapable; -#endif // PIGGYBACK_SUPPORT // - DBGPRINT(RT_DEBUG_TRACE, ("PktAggregate=%d\n", pAd->CommonCfg.bAggregationCapable)); - } -#else - pAd->CommonCfg.bAggregationCapable = FALSE; - pAd->CommonCfg.bPiggyBackCapable = FALSE; -#endif // AGGREGATION_SUPPORT // - - // WmmCapable - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - rtmp_read_sta_wmm_parms_from_file(pAd, tmpbuf, pBuffer); -#endif // CONFIG_STA_SUPPORT // - - //ShortSlot - if(RTMPGetKeyParameter("ShortSlot", tmpbuf, 10, pBuffer, TRUE)) - { - RT_CfgSetShortSlot(pAd, tmpbuf); - DBGPRINT(RT_DEBUG_TRACE, ("ShortSlot=%d\n", pAd->CommonCfg.bUseShortSlotTime)); - } - //IEEE80211H - if(RTMPGetKeyParameter("IEEE80211H", tmpbuf, 10, pBuffer, TRUE)) - { - for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) - { - if(simple_strtol(macptr, 0, 10) != 0) //Enable - pAd->CommonCfg.bIEEE80211H = TRUE; - else //Disable - pAd->CommonCfg.bIEEE80211H = FALSE; - - DBGPRINT(RT_DEBUG_TRACE, ("IEEE80211H=%d\n", pAd->CommonCfg.bIEEE80211H)); - } - } - //CSPeriod - if(RTMPGetKeyParameter("CSPeriod", tmpbuf, 10, pBuffer, TRUE)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) - pAd->CommonCfg.RadarDetect.CSPeriod = simple_strtol(tmpbuf, 0, 10); - else - pAd->CommonCfg.RadarDetect.CSPeriod = 0; - - DBGPRINT(RT_DEBUG_TRACE, ("CSPeriod=%d\n", pAd->CommonCfg.RadarDetect.CSPeriod)); - } - -#ifdef MERGE_ARCH_TEAM - // DfsLowerLimit - if(RTMPGetKeyParameter("DfsLowerLimit", tmpbuf, 10, pBuffer, TRUE)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) - pAd->CommonCfg.RadarDetect.DfsLowerLimit = simple_strtol(tmpbuf, 0, 10); - - DBGPRINT(RT_DEBUG_TRACE, ("DfsLowerLimit=%ld\n", pAd->CommonCfg.RadarDetect.DfsLowerLimit)); - } - - // DfsUpperLimit - if(RTMPGetKeyParameter("DfsUpperLimit", tmpbuf, 10, pBuffer, TRUE)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) - pAd->CommonCfg.RadarDetect.DfsUpperLimit = simple_strtol(tmpbuf, 0, 10); - - DBGPRINT(RT_DEBUG_TRACE, ("DfsUpperLimit=%ld\n", pAd->CommonCfg.RadarDetect.DfsUpperLimit)); - } - - // FixDfsLimit - if(RTMPGetKeyParameter("FixDfsLimit", tmpbuf, 10, pBuffer, TRUE)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) - pAd->CommonCfg.RadarDetect.FixDfsLimit = TRUE; - else - pAd->CommonCfg.RadarDetect.FixDfsLimit = FALSE; - - DBGPRINT(RT_DEBUG_TRACE, ("FixDfsLimit=%d\n", pAd->CommonCfg.RadarDetect.FixDfsLimit)); - } - - // LongPulseRadarTh - if(RTMPGetKeyParameter("LongPulseRadarTh", tmpbuf, 10, pBuffer, TRUE)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) - pAd->CommonCfg.RadarDetect.LongPulseRadarTh = simple_strtol(tmpbuf, 0, 10); - - DBGPRINT(RT_DEBUG_TRACE, ("LongPulseRadarTh=%d\n", pAd->CommonCfg.RadarDetect.LongPulseRadarTh)); - } - - // AvgRssiReq - if(RTMPGetKeyParameter("AvgRssiReq", tmpbuf, 10, pBuffer, TRUE)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) - pAd->CommonCfg.RadarDetect.AvgRssiReq = simple_strtol(tmpbuf, 0, 10); - - DBGPRINT(RT_DEBUG_TRACE, ("AvgRssiReq=%d\n", pAd->CommonCfg.RadarDetect.AvgRssiReq)); - } - -#endif // MERGE_ARCH_TEAM // - - //RDRegion - if(RTMPGetKeyParameter("RDRegion", tmpbuf, 128, pBuffer, TRUE)) - { - RADAR_DETECT_STRUCT *pRadarDetect = &pAd->CommonCfg.RadarDetect; - if ((strncmp(tmpbuf, "JAP_W53", 7) == 0) || (strncmp(tmpbuf, "jap_w53", 7) == 0)) - { - pRadarDetect->RDDurRegion = JAP_W53; - pRadarDetect->DfsSessionTime = 15; - } - else if ((strncmp(tmpbuf, "JAP_W56", 7) == 0) || (strncmp(tmpbuf, "jap_w56", 7) == 0)) - { - pRadarDetect->RDDurRegion = JAP_W56; - pRadarDetect->DfsSessionTime = 13; - } - else if ((strncmp(tmpbuf, "JAP", 3) == 0) || (strncmp(tmpbuf, "jap", 3) == 0)) - { - pRadarDetect->RDDurRegion = JAP; - pRadarDetect->DfsSessionTime = 5; - } - else if ((strncmp(tmpbuf, "FCC", 3) == 0) || (strncmp(tmpbuf, "fcc", 3) == 0)) - { - pRadarDetect->RDDurRegion = FCC; - pRadarDetect->DfsSessionTime = 5; -#ifdef DFS_FCC_BW40_FIX - pRadarDetect->DfsSessionFccOff = 0; -#endif // DFS_FCC_BW40_FIX // - } - else if ((strncmp(tmpbuf, "CE", 2) == 0) || (strncmp(tmpbuf, "ce", 2) == 0)) - { - pRadarDetect->RDDurRegion = CE; - pRadarDetect->DfsSessionTime = 13; - } - else - { - pRadarDetect->RDDurRegion = CE; - pRadarDetect->DfsSessionTime = 13; - } - - DBGPRINT(RT_DEBUG_TRACE, ("RDRegion=%d\n", pRadarDetect->RDDurRegion)); - } - else - { - pAd->CommonCfg.RadarDetect.RDDurRegion = CE; - pAd->CommonCfg.RadarDetect.DfsSessionTime = 13; - } - - //WirelessEvent - if(RTMPGetKeyParameter("WirelessEvent", tmpbuf, 10, pBuffer, TRUE)) - { -#if WIRELESS_EXT >= 15 - if(simple_strtol(tmpbuf, 0, 10) != 0) - pAd->CommonCfg.bWirelessEvent = simple_strtol(tmpbuf, 0, 10); - else - pAd->CommonCfg.bWirelessEvent = 0; // disable -#else - pAd->CommonCfg.bWirelessEvent = 0; // disable -#endif - DBGPRINT(RT_DEBUG_TRACE, ("WirelessEvent=%d\n", pAd->CommonCfg.bWirelessEvent)); - } - if(RTMPGetKeyParameter("WiFiTest", tmpbuf, 10, pBuffer, TRUE)) - { - if(simple_strtol(tmpbuf, 0, 10) != 0) - pAd->CommonCfg.bWiFiTest= simple_strtol(tmpbuf, 0, 10); - else - pAd->CommonCfg.bWiFiTest = 0; // disable - - DBGPRINT(RT_DEBUG_TRACE, ("WiFiTest=%d\n", pAd->CommonCfg.bWiFiTest)); - } - //AuthMode - if(RTMPGetKeyParameter("AuthMode", tmpbuf, 128, pBuffer, TRUE)) - { -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if ((strcmp(tmpbuf, "WEPAUTO") == 0) || (strcmp(tmpbuf, "wepauto") == 0)) - pAd->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch; - else if ((strcmp(tmpbuf, "SHARED") == 0) || (strcmp(tmpbuf, "shared") == 0)) - pAd->StaCfg.AuthMode = Ndis802_11AuthModeShared; - else if ((strcmp(tmpbuf, "WPAPSK") == 0) || (strcmp(tmpbuf, "wpapsk") == 0)) - pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; - else if ((strcmp(tmpbuf, "WPANONE") == 0) || (strcmp(tmpbuf, "wpanone") == 0)) - pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; - else if ((strcmp(tmpbuf, "WPA2PSK") == 0) || (strcmp(tmpbuf, "wpa2psk") == 0)) - pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; -#ifdef WPA_SUPPLICANT_SUPPORT - else if ((strcmp(tmpbuf, "WPA") == 0) || (strcmp(tmpbuf, "wpa") == 0)) - pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA; - else if ((strcmp(tmpbuf, "WPA2") == 0) || (strcmp(tmpbuf, "wpa2") == 0)) - pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; -#endif // WPA_SUPPLICANT_SUPPORT // - else - pAd->StaCfg.AuthMode = Ndis802_11AuthModeOpen; - - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - - DBGPRINT(RT_DEBUG_TRACE, ("%s::(EncrypType=%d)\n", __FUNCTION__, pAd->StaCfg.WepStatus)); - } -#endif // CONFIG_STA_SUPPORT // - } - //EncrypType - if(RTMPGetKeyParameter("EncrypType", tmpbuf, 128, pBuffer, TRUE)) - { - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if ((strcmp(tmpbuf, "WEP") == 0) || (strcmp(tmpbuf, "wep") == 0)) - pAd->StaCfg.WepStatus = Ndis802_11WEPEnabled; - else if ((strcmp(tmpbuf, "TKIP") == 0) || (strcmp(tmpbuf, "tkip") == 0)) - pAd->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; - else if ((strcmp(tmpbuf, "AES") == 0) || (strcmp(tmpbuf, "aes") == 0)) - pAd->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; - else - pAd->StaCfg.WepStatus = Ndis802_11WEPDisabled; - - // Update all wepstatus related - pAd->StaCfg.PairCipher = pAd->StaCfg.WepStatus; - pAd->StaCfg.GroupCipher = pAd->StaCfg.WepStatus; - pAd->StaCfg.OrigWepStatus = pAd->StaCfg.WepStatus; - pAd->StaCfg.bMixCipher = FALSE; - - //RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0); - DBGPRINT(RT_DEBUG_TRACE, ("%s::(EncrypType=%d)\n", __FUNCTION__, pAd->StaCfg.WepStatus)); - } -#endif // CONFIG_STA_SUPPORT // - } - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if(RTMPGetKeyParameter("WPAPSK", tmpbuf, 512, pBuffer, FALSE)) - { - int ret = TRUE; - - tmpbuf[strlen(tmpbuf)] = '\0'; // make STA can process .$^& for WPAPSK input - - if ((pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && - (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) && - (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) - ) - { - ret = FALSE; - } - else - { - ret = RT_CfgSetWPAPSKKey(pAd, tmpbuf, (PUCHAR)pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->StaCfg.PMK); - } - - if (ret == TRUE) - { - RTMPZeroMemory(pAd->StaCfg.WpaPassPhrase, 64); - RTMPMoveMemory(pAd->StaCfg.WpaPassPhrase, tmpbuf, strlen(tmpbuf)); - pAd->StaCfg.WpaPassPhraseLen= strlen(tmpbuf); - - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - // Start STA supplicant state machine - pAd->StaCfg.WpaState = SS_START; - } - else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - { - pAd->StaCfg.WpaState = SS_NOTUSE; - } - DBGPRINT(RT_DEBUG_TRACE, ("%s::(WPAPSK=%s)\n", __FUNCTION__, tmpbuf)); - } - } - } -#endif // CONFIG_STA_SUPPORT // - - //DefaultKeyID, KeyType, KeyStr - rtmp_read_key_parms_from_file(pAd, tmpbuf, pBuffer); - - - //HSCounter - /*if(RTMPGetKeyParameter("HSCounter", tmpbuf, 10, pBuffer, TRUE)) - { - switch (simple_strtol(tmpbuf, 0, 10)) - { - case 1: //Enable - pAd->CommonCfg.bEnableHSCounter = TRUE; - break; - case 0: //Disable - default: - pAd->CommonCfg.bEnableHSCounter = FALSE; - break; - } - DBGPRINT(RT_DEBUG_TRACE, "HSCounter=%d\n", pAd->CommonCfg.bEnableHSCounter); - }*/ - -#ifdef DOT11_N_SUPPORT - HTParametersHook(pAd, tmpbuf, pBuffer); -#endif // DOT11_N_SUPPORT // - - -#ifdef CARRIER_DETECTION_SUPPORT - //CarrierDetect - if(RTMPGetKeyParameter("CarrierDetect", tmpbuf, 128, pBuffer, TRUE)) - { - if ((strncmp(tmpbuf, "0", 1) == 0)) - pAd->CommonCfg.CarrierDetect.Enable = FALSE; - else if ((strncmp(tmpbuf, "1", 1) == 0)) - pAd->CommonCfg.CarrierDetect.Enable = TRUE; - else - pAd->CommonCfg.CarrierDetect.Enable = FALSE; - - DBGPRINT(RT_DEBUG_TRACE, ("CarrierDetect.Enable=%d\n", pAd->CommonCfg.CarrierDetect.Enable)); - } - else - pAd->CommonCfg.CarrierDetect.Enable = FALSE; -#endif // CARRIER_DETECTION_SUPPORT // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - //PSMode - if (RTMPGetKeyParameter("PSMode", tmpbuf, 10, pBuffer, TRUE)) - { - if (pAd->StaCfg.BssType == BSS_INFRA) - { - if ((strcmp(tmpbuf, "MAX_PSP") == 0) || (strcmp(tmpbuf, "max_psp") == 0)) - { - // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() - // to exclude certain situations. - // MlmeSetPsm(pAd, PWR_SAVE); - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); - if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) - pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP; - pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP; - pAd->StaCfg.DefaultListenCount = 5; - } - else if ((strcmp(tmpbuf, "Fast_PSP") == 0) || (strcmp(tmpbuf, "fast_psp") == 0) - || (strcmp(tmpbuf, "FAST_PSP") == 0)) - { - // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() - // to exclude certain situations. - // MlmeSetPsmBit(pAd, PWR_SAVE); - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); - if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) - pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP; - pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP; - pAd->StaCfg.DefaultListenCount = 3; - } - else if ((strcmp(tmpbuf, "Legacy_PSP") == 0) || (strcmp(tmpbuf, "legacy_psp") == 0) - || (strcmp(tmpbuf, "LEGACY_PSP") == 0)) - { - // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() - // to exclude certain situations. - // MlmeSetPsmBit(pAd, PWR_SAVE); - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); - if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) - pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP; - pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP; - pAd->StaCfg.DefaultListenCount = 3; - } - else - { //Default Ndis802_11PowerModeCAM - // clear PSM bit immediately - RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE); - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); - if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) - pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; - pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; - } - DBGPRINT(RT_DEBUG_TRACE, ("PSMode=%ld\n", pAd->StaCfg.WindowsPowerMode)); - } - } - // AutoRoaming by RSSI - if (RTMPGetKeyParameter("AutoRoaming", tmpbuf, 32, pBuffer, TRUE)) - { - if (simple_strtol(tmpbuf, 0, 10) == 0) - pAd->StaCfg.bAutoRoaming = FALSE; - else - pAd->StaCfg.bAutoRoaming = TRUE; - - DBGPRINT(RT_DEBUG_TRACE, ("AutoRoaming=%d\n", pAd->StaCfg.bAutoRoaming)); - } - // RoamThreshold - if (RTMPGetKeyParameter("RoamThreshold", tmpbuf, 32, pBuffer, TRUE)) - { - long lInfo = simple_strtol(tmpbuf, 0, 10); - - if (lInfo > 90 || lInfo < 60) - pAd->StaCfg.dBmToRoam = -70; - else - pAd->StaCfg.dBmToRoam = (CHAR)(-1)*lInfo; - - DBGPRINT(RT_DEBUG_TRACE, ("RoamThreshold=%d dBm\n", pAd->StaCfg.dBmToRoam)); - } - - if(RTMPGetKeyParameter("TGnWifiTest", tmpbuf, 10, pBuffer, TRUE)) - { - if(simple_strtol(tmpbuf, 0, 10) == 0) - pAd->StaCfg.bTGnWifiTest = FALSE; - else - pAd->StaCfg.bTGnWifiTest = TRUE; - DBGPRINT(RT_DEBUG_TRACE, ("TGnWifiTest=%d\n", pAd->StaCfg.bTGnWifiTest)); - } - - // Beacon Lost Time - if (RTMPGetKeyParameter("BeaconLostTime", tmpbuf, 32, pBuffer, TRUE)) - { - ULONG lInfo = (ULONG)simple_strtol(tmpbuf, 0, 10); - - if ((lInfo != 0) && (lInfo <= 60)) - pAd->StaCfg.BeaconLostTime = (lInfo * OS_HZ); - DBGPRINT(RT_DEBUG_TRACE, ("BeaconLostTime=%ld \n", pAd->StaCfg.BeaconLostTime)); - } - - - } -#endif // CONFIG_STA_SUPPORT // - - - -#ifdef RT30xx -#ifdef ANT_DIVERSITY_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if(RTMPGetKeyParameter("AntDiversity", tmpbuf, 10, pBuffer, TRUE)) - { - for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) - { - UCHAR Ant = simple_strtol(tmpbuf, 0, 10); - if(Ant < 3) - pAd->CommonCfg.bRxAntDiversity = Ant; - else - pAd->CommonCfg.bRxAntDiversity = ANT_DIVERSITY_DISABLE; - - DBGPRINT(RT_DEBUG_ERROR, ("AntDiversity=%d\n", pAd->CommonCfg.bRxAntDiversity)); - } - } - } -#endif // ANT_DIVERSITY_SUPPORT // -#endif // RT30xx // - - }while(0); - - - kfree(tmpbuf); - - return NDIS_STATUS_SUCCESS; - -} - - -#ifdef MULTIPLE_CARD_SUPPORT -// record whether the card in the card list is used in the card file -UINT8 MC_CardUsed[MAX_NUM_OF_MULTIPLE_CARD]; -// record used card mac address in the card list -static UINT8 MC_CardMac[MAX_NUM_OF_MULTIPLE_CARD][6]; - -/* -======================================================================== -Routine Description: - Get card profile path. - -Arguments: - pAd - -Return Value: - TRUE - Find a card profile - FALSE - use default profile - -Note: -======================================================================== -*/ -BOOLEAN RTMP_CardInfoRead( - IN PRTMP_ADAPTER pAd) -{ -#define MC_SELECT_CARDID 0 /* use CARD ID (0 ~ 31) to identify different cards */ -#define MC_SELECT_MAC 1 /* use CARD MAC to identify different cards */ -#define MC_SELECT_CARDTYPE 2 /* use CARD type (abgn or bgn) to identify different cards */ - -#define LETTER_CASE_TRANSLATE(txt_p, card_id) \ - { UINT32 _len; char _char; \ - for(_len=0; _lenEEPROMAddressNum = 6; // 93C46 - else if ((data & 0x30) == 0x10) - pAd->EEPROMAddressNum = 8; // 93C66 - else - pAd->EEPROMAddressNum = 8; // 93C86 - - RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, antenna.word); - - if ((antenna.field.RfIcType == RFIC_2850) || - (antenna.field.RfIcType == RFIC_2750)) - { - /* ABGN card */ - strcpy(RFIC_word, "abgn"); - } - else - { - /* BGN card */ - strcpy(RFIC_word, "bgn"); - } - - // get MAC address - RT28xx_EEPROM_READ16(pAd, 0x04, addr01); - RT28xx_EEPROM_READ16(pAd, 0x06, addr23); - RT28xx_EEPROM_READ16(pAd, 0x08, addr45); - - mac[0] = (UCHAR)(addr01 & 0xff); - mac[1] = (UCHAR)(addr01 >> 8); - mac[2] = (UCHAR)(addr23 & 0xff); - mac[3] = (UCHAR)(addr23 >> 8); - mac[4] = (UCHAR)(addr45 & 0xff); - mac[5] = (UCHAR)(addr45 >> 8); - - DBGPRINT(RT_DEBUG_TRACE, ("mac addr=%02x:%02x:%02x:%02x:%02x:%02x!\n", PRINT_MAC(mac))); - - RtmpOSFSInfoChange(&osFSInfo, TRUE); - // open card information file - srcf = RtmpOSFileOpen(CARD_INFO_PATH, O_RDONLY, 0); - if (IS_FILE_OPEN_ERR(srcf)) - { - /* card information file does not exist */ - DBGPRINT(RT_DEBUG_TRACE, - ("--> Error opening %s\n", CARD_INFO_PATH)); - goto free_resource; - } - - /* card information file exists so reading the card information */ - memset(buffer, 0x00, MAX_INI_BUFFER_SIZE); - retval = RtmpOSFileRead(srcf, buffer, MAX_INI_BUFFER_SIZE); - if (retval < 0) - { - /* read fail */ - DBGPRINT(RT_DEBUG_TRACE, - ("--> Read %s error %d\n", CARD_INFO_PATH, -retval)); - } - else - { - /* get card selection method */ - memset(tmpbuf, 0x00, MAX_PARAM_BUFFER_SIZE); - card_select_method = MC_SELECT_CARDTYPE; // default - - if (RTMPGetKeyParameter("SELECT", tmpbuf, 256, buffer, TRUE)) - { - if (strcmp(tmpbuf, "CARDID") == 0) - card_select_method = MC_SELECT_CARDID; - else if (strcmp(tmpbuf, "MAC") == 0) - card_select_method = MC_SELECT_MAC; - else if (strcmp(tmpbuf, "CARDTYPE") == 0) - card_select_method = MC_SELECT_CARDTYPE; - } - - DBGPRINT(RT_DEBUG_TRACE, - ("MC> Card Selection = %d\n", card_select_method)); - - // init - card_free_id = -1; - card_nouse_id = -1; - card_same_mac_id = -1; - card_match_id = -1; - - // search current card information records - for(card_index=0; - card_index Free = %d, Same = %d, NOUSE = %d\n", - card_free_id, card_same_mac_id, card_nouse_id)); - - if ((card_same_mac_id >= 0) && - ((card_select_method == MC_SELECT_CARDID) || - (card_select_method == MC_SELECT_CARDTYPE))) - { - // same MAC entry is found - card_match_id = card_same_mac_id; - - if (card_select_method == MC_SELECT_CARDTYPE) - { - // for CARDTYPE - sprintf(card_id_buf, "%02dCARDTYPE%s", - card_match_id, RFIC_word); - - if ((start_ptr = (PUCHAR)rtstrstruncasecmp(buffer, card_id_buf)) != NULL) - { - // we found the card ID - LETTER_CASE_TRANSLATE(start_ptr, card_id_buf); - } - } - } - else - { - // the card is 1st plug-in, try to find the match card profile - switch(card_select_method) - { - case MC_SELECT_CARDID: // CARDID - default: - if (card_free_id >= 0) - card_match_id = card_free_id; - else - card_match_id = card_nouse_id; - break; - - case MC_SELECT_MAC: // MAC - sprintf(card_id_buf, "MAC%02x:%02x:%02x:%02x:%02x:%02x", - mac[0], mac[1], mac[2], - mac[3], mac[4], mac[5]); - - /* try to find the key word in the card file */ - if ((start_ptr = (PUCHAR)rtstrstruncasecmp(buffer, card_id_buf)) != NULL) - { - LETTER_CASE_TRANSLATE(start_ptr, card_id_buf); - - /* get the row ID (2 ASCII characters) */ - start_ptr -= 2; - card_id_buf[0] = *(start_ptr); - card_id_buf[1] = *(start_ptr+1); - card_id_buf[2] = 0x00; - - card_match_id = simple_strtol(card_id_buf, 0, 10); - } - break; - - case MC_SELECT_CARDTYPE: // CARDTYPE - card_nouse_id = -1; - - for(card_index=0; - card_index= 0) - { - // make up search keyword - switch(card_select_method) - { - case MC_SELECT_CARDID: // CARDID - sprintf(card_id_buf, "%02dCARDID", card_match_id); - break; - - case MC_SELECT_MAC: // MAC - sprintf(card_id_buf, - "%02dmac%02x:%02x:%02x:%02x:%02x:%02x", - card_match_id, - mac[0], mac[1], mac[2], - mac[3], mac[4], mac[5]); - break; - - case MC_SELECT_CARDTYPE: // CARDTYPE - default: - sprintf(card_id_buf, "%02dcardtype%s", - card_match_id, RFIC_word); - break; - } - - DBGPRINT(RT_DEBUG_TRACE, ("Search Keyword = %s\n", card_id_buf)); - - // read card file path - if (RTMPGetKeyParameter(card_id_buf, tmpbuf, 256, buffer, TRUE)) - { - if (strlen(tmpbuf) < sizeof(pAd->MC_FileName)) - { - // backup card information - pAd->MC_RowID = card_match_id; /* base 0 */ - MC_CardUsed[card_match_id] = 1; - memcpy(MC_CardMac[card_match_id], mac, sizeof(mac)); - - // backup card file path - NdisMoveMemory(pAd->MC_FileName, tmpbuf , strlen(tmpbuf)); - pAd->MC_FileName[strlen(tmpbuf)] = '\0'; - flg_match_ok = TRUE; - - DBGPRINT(RT_DEBUG_TRACE, - ("Card Profile Name = %s\n", pAd->MC_FileName)); - } - else - { - DBGPRINT(RT_DEBUG_ERROR, - ("Card Profile Name length too large!\n")); - } - } - else - { - DBGPRINT(RT_DEBUG_ERROR, - ("Can not find search key word in card.dat!\n")); - } - - if ((flg_match_ok != TRUE) && - (card_match_id < MAX_NUM_OF_MULTIPLE_CARD)) - { - MC_CardUsed[card_match_id] = 0; - memset(MC_CardMac[card_match_id], 0, sizeof(mac)); - } - } // if (card_match_id >= 0) - } - - - // close file - retval = RtmpOSFileClose(srcf); - -free_resource: - RtmpOSFSInfoChange(&osFSInfo, FALSE); - kfree(buffer); - kfree(tmpbuf); - - return flg_match_ok; -} -#endif // MULTIPLE_CARD_SUPPORT // diff --git a/drivers/staging/rt3090/common/cmm_sanity.c b/drivers/staging/rt3090/common/cmm_sanity.c deleted file mode 100644 index de631c38a44e46c61926b3955c6cce06b4e68304..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/cmm_sanity.c +++ /dev/null @@ -1,1718 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - sanity.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - John Chang 2004-09-01 add WMM support -*/ - -#include "../rt_config.h" - - -extern UCHAR CISCO_OUI[]; - -extern UCHAR WPA_OUI[]; -extern UCHAR RSN_OUI[]; -extern UCHAR WME_INFO_ELEM[]; -extern UCHAR WME_PARM_ELEM[]; -extern UCHAR Ccx2QosInfo[]; -extern UCHAR RALINK_OUI[]; -extern UCHAR BROADCOM_OUI[]; -extern UCHAR WPS_OUI[]; - -/* - ========================================================================== - Description: - MLME message sanity check - Return: - TRUE if all parameters are OK, FALSE otherwise - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -BOOLEAN MlmeAddBAReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2) -{ - PMLME_ADDBA_REQ_STRUCT pInfo; - - pInfo = (MLME_ADDBA_REQ_STRUCT *)Msg; - - if ((MsgLen != sizeof(MLME_ADDBA_REQ_STRUCT))) - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - message lenght not correct.\n")); - return FALSE; - } - - if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - The peer Mac is not associated yet.\n")); - return FALSE; - } - - /* - if ((pInfo->BaBufSize > MAX_RX_REORDERBUF) || (pInfo->BaBufSize < 2)) - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - Rx Reordering buffer too big or too small\n")); - return FALSE; - } - */ - - if ((pInfo->pAddr[0]&0x01) == 0x01) - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - broadcast address not support BA\n")); - return FALSE; - } - - return TRUE; -} - -/* - ========================================================================== - Description: - MLME message sanity check - Return: - TRUE if all parameters are OK, FALSE otherwise - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -BOOLEAN MlmeDelBAReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen) -{ - MLME_DELBA_REQ_STRUCT *pInfo; - pInfo = (MLME_DELBA_REQ_STRUCT *)Msg; - - if ((MsgLen != sizeof(MLME_DELBA_REQ_STRUCT))) - { - DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - message lenght not correct.\n")); - return FALSE; - } - - if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) - { - DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer Mac is not associated yet.\n")); - return FALSE; - } - - if ((pInfo->TID & 0xf0)) - { - DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer TID is incorrect.\n")); - return FALSE; - } - - if (NdisEqualMemory(pAd->MacTab.Content[pInfo->Wcid].Addr, pInfo->Addr, MAC_ADDR_LEN) == 0) - { - DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - the peer addr dosen't exist.\n")); - return FALSE; - } - - return TRUE; -} - -BOOLEAN PeerAddBAReqActionSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2) -{ - PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; - PFRAME_ADDBA_REQ pAddFrame; - pAddFrame = (PFRAME_ADDBA_REQ)(pMsg); - if (MsgLen < (sizeof(FRAME_ADDBA_REQ))) - { - DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request frame length size = %ld incorrect\n", MsgLen)); - return FALSE; - } - // we support immediate BA. -#ifdef UNALIGNMENT_SUPPORT - { - BA_PARM tmpBaParm; - - NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&pAddFrame->BaParm), sizeof(BA_PARM)); - *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm)); - NdisMoveMemory((PUCHAR)(&pAddFrame->BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM)); - } -#else - *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm)); -#endif - pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); - pAddFrame->BaStartSeq.word = cpu2le16(pAddFrame->BaStartSeq.word); - - if (pAddFrame->BaParm.BAPolicy != IMMED_BA) - { - DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy)); - DBGPRINT(RT_DEBUG_ERROR,("ADDBA Request. tid=%x, Bufsize=%x, AMSDUSupported=%x \n", pAddFrame->BaParm.TID, pAddFrame->BaParm.BufSize, pAddFrame->BaParm.AMSDUSupported)); - return FALSE; - } - - // we support immediate BA. - if (pAddFrame->BaParm.TID &0xfff0) - { - DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request incorrect TID = %d\n", pAddFrame->BaParm.TID)); - return FALSE; - } - COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); - return TRUE; -} - -BOOLEAN PeerAddBARspActionSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen) -{ - //PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; - PFRAME_ADDBA_RSP pAddFrame; - - pAddFrame = (PFRAME_ADDBA_RSP)(pMsg); - if (MsgLen < (sizeof(FRAME_ADDBA_RSP))) - { - DBGPRINT(RT_DEBUG_ERROR,("PeerAddBARspActionSanity: ADDBA Response frame length size = %ld incorrect\n", MsgLen)); - return FALSE; - } - // we support immediate BA. -#ifdef UNALIGNMENT_SUPPORT - { - BA_PARM tmpBaParm; - - NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&pAddFrame->BaParm), sizeof(BA_PARM)); - *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm)); - NdisMoveMemory((PUCHAR)(&pAddFrame->BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM)); - } -#else - *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm)); -#endif - pAddFrame->StatusCode = cpu2le16(pAddFrame->StatusCode); - pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); - - if (pAddFrame->BaParm.BAPolicy != IMMED_BA) - { - DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Response Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy)); - return FALSE; - } - - // we support immediate BA. - if (pAddFrame->BaParm.TID &0xfff0) - { - DBGPRINT(RT_DEBUG_ERROR,("PeerAddBARspActionSanity: ADDBA Response incorrect TID = %d\n", pAddFrame->BaParm.TID)); - return FALSE; - } - return TRUE; - -} - -BOOLEAN PeerDelBAActionSanity( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN VOID *pMsg, - IN ULONG MsgLen ) -{ - //PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; - PFRAME_DELBA_REQ pDelFrame; - if (MsgLen != (sizeof(FRAME_DELBA_REQ))) - return FALSE; - - if (Wcid >= MAX_LEN_OF_MAC_TABLE) - return FALSE; - - pDelFrame = (PFRAME_DELBA_REQ)(pMsg); - - *(USHORT *)(&pDelFrame->DelbaParm) = cpu2le16(*(USHORT *)(&pDelFrame->DelbaParm)); - pDelFrame->ReasonCode = cpu2le16(pDelFrame->ReasonCode); - - if (pDelFrame->DelbaParm.TID &0xfff0) - return FALSE; - - return TRUE; -} - -/* - ========================================================================== - Description: - MLME message sanity check - Return: - TRUE if all parameters are OK, FALSE otherwise - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -BOOLEAN PeerBeaconAndProbeRspSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - IN UCHAR MsgChannel, - OUT PUCHAR pAddr2, - OUT PUCHAR pBssid, - OUT CHAR Ssid[], - OUT UCHAR *pSsidLen, - OUT UCHAR *pBssType, - OUT USHORT *pBeaconPeriod, - OUT UCHAR *pChannel, - OUT UCHAR *pNewChannel, - OUT LARGE_INTEGER *pTimestamp, - OUT CF_PARM *pCfParm, - OUT USHORT *pAtimWin, - OUT USHORT *pCapabilityInfo, - OUT UCHAR *pErp, - OUT UCHAR *pDtimCount, - OUT UCHAR *pDtimPeriod, - OUT UCHAR *pBcastFlag, - OUT UCHAR *pMessageToMe, - OUT UCHAR SupRate[], - OUT UCHAR *pSupRateLen, - OUT UCHAR ExtRate[], - OUT UCHAR *pExtRateLen, - OUT UCHAR *pCkipFlag, - OUT UCHAR *pAironetCellPowerLimit, - OUT PEDCA_PARM pEdcaParm, - OUT PQBSS_LOAD_PARM pQbssLoad, - OUT PQOS_CAPABILITY_PARM pQosCapability, - OUT ULONG *pRalinkIe, - OUT UCHAR *pHtCapabilityLen, -#ifdef CONFIG_STA_SUPPORT - OUT UCHAR *pPreNHtCapabilityLen, -#endif // CONFIG_STA_SUPPORT // - OUT HT_CAPABILITY_IE *pHtCapability, - OUT UCHAR *AddHtInfoLen, - OUT ADD_HT_INFO_IE *AddHtInfo, - OUT UCHAR *NewExtChannelOffset, // Ht extension channel offset(above or below) - OUT USHORT *LengthVIE, - OUT PNDIS_802_11_VARIABLE_IEs pVIE) -{ - UCHAR *Ptr; -#ifdef CONFIG_STA_SUPPORT - UCHAR TimLen; -#endif // CONFIG_STA_SUPPORT // - PFRAME_802_11 pFrame; - PEID_STRUCT pEid; - UCHAR SubType; - UCHAR Sanity; - //UCHAR ECWMin, ECWMax; - //MAC_CSR9_STRUC Csr9; - ULONG Length = 0; - - // For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel - // 1. If the AP is 11n enabled, then check the control channel. - // 2. If the AP didn't have any info about channel, use the channel we received this frame as the channel. (May inaccuracy!!) - UCHAR CtrlChannel = 0; - - // Add for 3 necessary EID field check - Sanity = 0; - - *pAtimWin = 0; - *pErp = 0; - *pDtimCount = 0; - *pDtimPeriod = 0; - *pBcastFlag = 0; - *pMessageToMe = 0; - *pExtRateLen = 0; - *pCkipFlag = 0; // Default of CkipFlag is 0 - *pAironetCellPowerLimit = 0xFF; // Default of AironetCellPowerLimit is 0xFF - *LengthVIE = 0; // Set the length of VIE to init value 0 - *pHtCapabilityLen = 0; // Set the length of VIE to init value 0 -#ifdef CONFIG_STA_SUPPORT - if (pAd->OpMode == OPMODE_STA) - *pPreNHtCapabilityLen = 0; // Set the length of VIE to init value 0 -#endif // CONFIG_STA_SUPPORT // - *AddHtInfoLen = 0; // Set the length of VIE to init value 0 - *pRalinkIe = 0; - *pNewChannel = 0; - *NewExtChannelOffset = 0xff; //Default 0xff means no such IE - pCfParm->bValid = FALSE; // default: no IE_CF found - pQbssLoad->bValid = FALSE; // default: no IE_QBSS_LOAD found - pEdcaParm->bValid = FALSE; // default: no IE_EDCA_PARAMETER found - pQosCapability->bValid = FALSE; // default: no IE_QOS_CAPABILITY found - - pFrame = (PFRAME_802_11)Msg; - - // get subtype from header - SubType = (UCHAR)pFrame->Hdr.FC.SubType; - - // get Addr2 and BSSID from header - COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); - COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3); - -// hex_dump("Beacon", Msg, MsgLen); - - Ptr = pFrame->Octet; - Length += LENGTH_802_11; - - // get timestamp from payload and advance the pointer - NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN); - - pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart); - pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart); - - Ptr += TIMESTAMP_LEN; - Length += TIMESTAMP_LEN; - - // get beacon interval from payload and advance the pointer - NdisMoveMemory(pBeaconPeriod, Ptr, 2); - Ptr += 2; - Length += 2; - - // get capability info from payload and advance the pointer - NdisMoveMemory(pCapabilityInfo, Ptr, 2); - Ptr += 2; - Length += 2; - - if (CAP_IS_ESS_ON(*pCapabilityInfo)) - *pBssType = BSS_INFRA; - else - *pBssType = BSS_ADHOC; - - pEid = (PEID_STRUCT) Ptr; - - // get variable fields from payload and advance the pointer - while ((Length + 2 + pEid->Len) <= MsgLen) - { - // - // Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow. - // - if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN) - { - DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", - (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN)); - break; - } - - switch(pEid->Eid) - { - case IE_SSID: - // Already has one SSID EID in this beacon, ignore the second one - if (Sanity & 0x1) - break; - if(pEid->Len <= MAX_LEN_OF_SSID) - { - NdisMoveMemory(Ssid, pEid->Octet, pEid->Len); - *pSsidLen = pEid->Len; - Sanity |= 0x1; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len)); - return FALSE; - } - break; - - case IE_SUPP_RATES: - if(pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) - { - Sanity |= 0x2; - NdisMoveMemory(SupRate, pEid->Octet, pEid->Len); - *pSupRateLen = pEid->Len; - - // TODO: 2004-09-14 not a good design here, cause it exclude extra rates - // from ScanTab. We should report as is. And filter out unsupported - // rates in MlmeAux. - // Check against the supported rates - // RTMPCheckRates(pAd, SupRate, pSupRateLen); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_RATES (len=%d)\n",pEid->Len)); - return FALSE; - } - break; - - case IE_HT_CAP: - if (pEid->Len >= SIZE_HT_CAP_IE) //Note: allow extension.!! - { - NdisMoveMemory(pHtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE)); - *pHtCapabilityLen = SIZE_HT_CAP_IE; // Nnow we only support 26 bytes. - - *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); -#ifdef UNALIGNMENT_SUPPORT - { - EXT_HT_CAP_INFO extHtCapInfo; - NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); - *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); - NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); - } -#else - *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); -#endif // UNALIGNMENT_SUPPORT // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - *pPreNHtCapabilityLen = 0; // Now we only support 26 bytes. - - Ptr = (PUCHAR) pVIE; - NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); - *LengthVIE += (pEid->Len + 2); - } -#endif // CONFIG_STA_SUPPORT // - } - else - { - DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_HT_CAP. pEid->Len = %d\n", pEid->Len)); - } - - break; - case IE_ADD_HT: - if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) - { - // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only - // copy first sizeof(ADD_HT_INFO_IE) - NdisMoveMemory(AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); - *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; - - CtrlChannel = AddHtInfo->ControlChan; - - *(USHORT *)(&AddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo2)); - *(USHORT *)(&AddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo3)); - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - Ptr = (PUCHAR) pVIE; - NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); - *LengthVIE += (pEid->Len + 2); - } -#endif // CONFIG_STA_SUPPORT // - } - else - { - DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_ADD_HT. \n")); - } - - break; - case IE_SECONDARY_CH_OFFSET: - if (pEid->Len == 1) - { - *NewExtChannelOffset = pEid->Octet[0]; - } - else - { - DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); - } - - break; - case IE_FH_PARM: - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity(IE_FH_PARM) \n")); - break; - - case IE_DS_PARM: - if(pEid->Len == 1) - { - *pChannel = *pEid->Octet; -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (ChannelSanity(pAd, *pChannel) == 0) - { - - return FALSE; - } - } -#endif // CONFIG_STA_SUPPORT // - Sanity |= 0x4; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_DS_PARM (len=%d)\n",pEid->Len)); - return FALSE; - } - break; - - case IE_CF_PARM: - if(pEid->Len == 6) - { - pCfParm->bValid = TRUE; - pCfParm->CfpCount = pEid->Octet[0]; - pCfParm->CfpPeriod = pEid->Octet[1]; - pCfParm->CfpMaxDuration = pEid->Octet[2] + 256 * pEid->Octet[3]; - pCfParm->CfpDurRemaining = pEid->Octet[4] + 256 * pEid->Octet[5]; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_CF_PARM\n")); - return FALSE; - } - break; - - case IE_IBSS_PARM: - if(pEid->Len == 2) - { - NdisMoveMemory(pAtimWin, pEid->Octet, pEid->Len); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_IBSS_PARM\n")); - return FALSE; - } - break; - -#ifdef CONFIG_STA_SUPPORT - case IE_TIM: - if(INFRA_ON(pAd) && SubType == SUBTYPE_BEACON) - { - GetTimBit((PCHAR)pEid, pAd->StaActive.Aid, &TimLen, pBcastFlag, pDtimCount, pDtimPeriod, pMessageToMe); - } - break; -#endif // CONFIG_STA_SUPPORT // - case IE_CHANNEL_SWITCH_ANNOUNCEMENT: - if(pEid->Len == 3) - { - *pNewChannel = pEid->Octet[1]; //extract new channel number - } - break; - - // New for WPA - // CCX v2 has the same IE, we need to parse that too - // Wifi WMM use the same IE vale, need to parse that too - // case IE_WPA: - case IE_VENDOR_SPECIFIC: - // Check Broadcom/Atheros 802.11n OUI version, for HT Capability IE. - // This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan. - /*if (NdisEqualMemory(pEid->Octet, BROADCOM_OUI, 3) && (pEid->Len >= 4)) - { - if ((pEid->Octet[3] == OUI_BROADCOM_HT) && (pEid->Len >= 30)) - { - { - NdisMoveMemory(pHtCapability, &pEid->Octet[4], sizeof(HT_CAPABILITY_IE)); - *pHtCapabilityLen = SIZE_HT_CAP_IE; // Nnow we only support 26 bytes. - } - } - if ((pEid->Octet[3] == OUI_BROADCOM_HT) && (pEid->Len >= 26)) - { - { - NdisMoveMemory(AddHtInfo, &pEid->Octet[4], sizeof(ADD_HT_INFO_IE)); - *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; // Nnow we only support 26 bytes. - } - } - } - */ - // Check the OUI version, filter out non-standard usage - if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 7)) - { - //*pRalinkIe = pEid->Octet[3]; - if (pEid->Octet[3] != 0) - *pRalinkIe = pEid->Octet[3]; - else - *pRalinkIe = 0xf0000000; // Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag. - } -#ifdef CONFIG_STA_SUPPORT -#ifdef DOT11_N_SUPPORT - // This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan. - - // Other vendors had production before IE_HT_CAP value is assigned. To backward support those old-firmware AP, - // Check broadcom-defiend pre-802.11nD1.0 OUI for HT related IE, including HT Capatilities IE and HT Information IE - else if ((*pHtCapabilityLen == 0) && NdisEqualMemory(pEid->Octet, PRE_N_HT_OUI, 3) && (pEid->Len >= 4) && (pAd->OpMode == OPMODE_STA)) - { - if ((pEid->Octet[3] == OUI_PREN_HT_CAP) && (pEid->Len >= 30) && (*pHtCapabilityLen == 0)) - { - NdisMoveMemory(pHtCapability, &pEid->Octet[4], sizeof(HT_CAPABILITY_IE)); - *pPreNHtCapabilityLen = SIZE_HT_CAP_IE; - } - - if ((pEid->Octet[3] == OUI_PREN_ADD_HT) && (pEid->Len >= 26)) - { - NdisMoveMemory(AddHtInfo, &pEid->Octet[4], sizeof(ADD_HT_INFO_IE)); - *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; - } - } -#endif // DOT11_N_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) - { - // Copy to pVIE which will report to microsoft bssid list. - Ptr = (PUCHAR) pVIE; - NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); - *LengthVIE += (pEid->Len + 2); - } - else if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) - { - PUCHAR ptr; - int i; - - // parsing EDCA parameters - pEdcaParm->bValid = TRUE; - pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10; - pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20; - pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40; - pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; - pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; - ptr = &pEid->Octet[8]; - for (i=0; i<4; i++) - { - UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX - pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); // b5 is ACM - pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; // b0~3 is AIFSN - pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; // b0~4 is Cwmin - pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; // b5~8 is Cwmax - pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us - ptr += 4; // point to next AC - } - } - else if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7)) - { - // parsing EDCA parameters - pEdcaParm->bValid = TRUE; - pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10; - pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20; - pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40; - pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; - pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; - - // use default EDCA parameter - pEdcaParm->bACM[QID_AC_BE] = 0; - pEdcaParm->Aifsn[QID_AC_BE] = 3; - pEdcaParm->Cwmin[QID_AC_BE] = CW_MIN_IN_BITS; - pEdcaParm->Cwmax[QID_AC_BE] = CW_MAX_IN_BITS; - pEdcaParm->Txop[QID_AC_BE] = 0; - - pEdcaParm->bACM[QID_AC_BK] = 0; - pEdcaParm->Aifsn[QID_AC_BK] = 7; - pEdcaParm->Cwmin[QID_AC_BK] = CW_MIN_IN_BITS; - pEdcaParm->Cwmax[QID_AC_BK] = CW_MAX_IN_BITS; - pEdcaParm->Txop[QID_AC_BK] = 0; - - pEdcaParm->bACM[QID_AC_VI] = 0; - pEdcaParm->Aifsn[QID_AC_VI] = 2; - pEdcaParm->Cwmin[QID_AC_VI] = CW_MIN_IN_BITS-1; - pEdcaParm->Cwmax[QID_AC_VI] = CW_MAX_IN_BITS; - pEdcaParm->Txop[QID_AC_VI] = 96; // AC_VI: 96*32us ~= 3ms - - pEdcaParm->bACM[QID_AC_VO] = 0; - pEdcaParm->Aifsn[QID_AC_VO] = 2; - pEdcaParm->Cwmin[QID_AC_VO] = CW_MIN_IN_BITS-2; - pEdcaParm->Cwmax[QID_AC_VO] = CW_MAX_IN_BITS-1; - pEdcaParm->Txop[QID_AC_VO] = 48; // AC_VO: 48*32us ~= 1.5ms - } -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - - - break; - - case IE_EXT_SUPP_RATES: - if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) - { - NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); - *pExtRateLen = pEid->Len; - - // TODO: 2004-09-14 not a good design here, cause it exclude extra rates - // from ScanTab. We should report as is. And filter out unsupported - // rates in MlmeAux. - // Check against the supported rates - // RTMPCheckRates(pAd, ExtRate, pExtRateLen); - } - break; - - case IE_ERP: - if (pEid->Len == 1) - { - *pErp = (UCHAR)pEid->Octet[0]; - } - break; - - case IE_AIRONET_CKIP: - // 0. Check Aironet IE length, it must be larger or equal to 28 - // Cisco AP350 used length as 28 - // Cisco AP12XX used length as 30 - if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) - break; - - // 1. Copy CKIP flag byte to buffer for process - *pCkipFlag = *(pEid->Octet + 8); - break; - - case IE_AP_TX_POWER: - // AP Control of Client Transmit Power - //0. Check Aironet IE length, it must be 6 - if (pEid->Len != 0x06) - break; - - // Get cell power limit in dBm - if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) - *pAironetCellPowerLimit = *(pEid->Octet + 4); - break; - - // WPA2 & 802.11i RSN - case IE_RSN: - // There is no OUI for version anymore, check the group cipher OUI before copying - if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) - { - // Copy to pVIE which will report to microsoft bssid list. - Ptr = (PUCHAR) pVIE; - NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); - *LengthVIE += (pEid->Len + 2); - } - break; -#ifdef CONFIG_STA_SUPPORT -#ifdef EXT_BUILD_CHANNEL_LIST - case IE_COUNTRY: - Ptr = (PUCHAR) pVIE; - NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); - *LengthVIE += (pEid->Len + 2); - break; -#endif // EXT_BUILD_CHANNEL_LIST // -#endif // CONFIG_STA_SUPPORT // - - - default: - break; - } - - Length = Length + 2 + pEid->Len; // Eid[1] + Len[1]+ content[Len] - pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); - } - - // For some 11a AP. it did not have the channel EID, patch here -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - UCHAR LatchRfChannel = MsgChannel; - if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0)) - { - if (CtrlChannel != 0) - *pChannel = CtrlChannel; - else - *pChannel = LatchRfChannel; - Sanity |= 0x4; - } - } -#endif // CONFIG_STA_SUPPORT // - - if (Sanity != 0x7) - { - DBGPRINT(RT_DEBUG_LOUD, ("PeerBeaconAndProbeRspSanity - missing field, Sanity=0x%02x\n", Sanity)); - return FALSE; - } - else - { - return TRUE; - } - -} - -#ifdef DOT11N_DRAFT3 -/* - ========================================================================== - Description: - MLME message sanity check for some IE addressed in 802.11n d3.03. - Return: - TRUE if all parameters are OK, FALSE otherwise - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -BOOLEAN PeerBeaconAndProbeRspSanity2( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT UCHAR *RegClass) -{ - CHAR *Ptr; - PFRAME_802_11 pFrame; - PEID_STRUCT pEid; - ULONG Length = 0; - - pFrame = (PFRAME_802_11)Msg; - - *RegClass = 0; - Ptr = (PCHAR) pFrame->Octet; - Length += LENGTH_802_11; - - // get timestamp from payload and advance the pointer - Ptr += TIMESTAMP_LEN; - Length += TIMESTAMP_LEN; - - // get beacon interval from payload and advance the pointer - Ptr += 2; - Length += 2; - - // get capability info from payload and advance the pointer - Ptr += 2; - Length += 2; - - pEid = (PEID_STRUCT) Ptr; - - // get variable fields from payload and advance the pointer - while ((Length + 2 + pEid->Len) <= MsgLen) - { - switch(pEid->Eid) - { - case IE_SUPP_REG_CLASS: - if(pEid->Len > 0) - { - *RegClass = *pEid->Octet; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len)); - return FALSE; - } - break; - } - - Length = Length + 2 + pEid->Len; // Eid[1] + Len[1]+ content[Len] - pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); - } - - return TRUE; - -} -#endif // DOT11N_DRAFT3 // - -/* - ========================================================================== - Description: - MLME message sanity check - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== - */ -BOOLEAN MlmeScanReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT UCHAR *pBssType, - OUT CHAR Ssid[], - OUT UCHAR *pSsidLen, - OUT UCHAR *pScanType) -{ - MLME_SCAN_REQ_STRUCT *Info; - - Info = (MLME_SCAN_REQ_STRUCT *)(Msg); - *pBssType = Info->BssType; - *pSsidLen = Info->SsidLen; - NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen); - *pScanType = Info->ScanType; - - if ((*pBssType == BSS_INFRA || *pBssType == BSS_ADHOC || *pBssType == BSS_ANY) - && (*pScanType == SCAN_ACTIVE || *pScanType == SCAN_PASSIVE -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - )) - { - return TRUE; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqSanity fail - wrong BssType or ScanType\n")); - return FALSE; - } -} - -// IRQL = DISPATCH_LEVEL -UCHAR ChannelSanity( - IN PRTMP_ADAPTER pAd, - IN UCHAR channel) -{ - int i; - - for (i = 0; i < pAd->ChannelListNum; i ++) - { - if (channel == pAd->ChannelList[i].Channel) - return 1; - } - return 0; -} - -/* - ========================================================================== - Description: - MLME message sanity check - Return: - TRUE if all parameters are OK, FALSE otherwise - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -BOOLEAN PeerDeauthSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *pReason) -{ - PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; - - COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); - NdisMoveMemory(pReason, &pFrame->Octet[0], 2); - - return TRUE; -} - -/* - ========================================================================== - Description: - MLME message sanity check - Return: - TRUE if all parameters are OK, FALSE otherwise - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -BOOLEAN PeerAuthSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr, - OUT USHORT *pAlg, - OUT USHORT *pSeq, - OUT USHORT *pStatus, - CHAR *pChlgText) -{ - PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; - - COPY_MAC_ADDR(pAddr, pFrame->Hdr.Addr2); - NdisMoveMemory(pAlg, &pFrame->Octet[0], 2); - NdisMoveMemory(pSeq, &pFrame->Octet[2], 2); - NdisMoveMemory(pStatus, &pFrame->Octet[4], 2); - - if (*pAlg == AUTH_MODE_OPEN) - { - if (*pSeq == 1 || *pSeq == 2) - { - return TRUE; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n")); - return FALSE; - } - } - else if (*pAlg == AUTH_MODE_KEY) - { - if (*pSeq == 1 || *pSeq == 4) - { - return TRUE; - } - else if (*pSeq == 2 || *pSeq == 3) - { - NdisMoveMemory(pChlgText, &pFrame->Octet[8], CIPHER_TEXT_LEN); - return TRUE; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n")); - return FALSE; - } - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong algorithm\n")); - return FALSE; - } -} - -/* - ========================================================================== - Description: - MLME message sanity check - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== - */ -BOOLEAN MlmeAuthReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr, - OUT ULONG *pTimeout, - OUT USHORT *pAlg) -{ - MLME_AUTH_REQ_STRUCT *pInfo; - - pInfo = (MLME_AUTH_REQ_STRUCT *)Msg; - COPY_MAC_ADDR(pAddr, pInfo->Addr); - *pTimeout = pInfo->Timeout; - *pAlg = pInfo->Alg; - - if (((*pAlg == AUTH_MODE_KEY) ||(*pAlg == AUTH_MODE_OPEN) - ) && - ((*pAddr & 0x01) == 0)) - { - return TRUE; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeAuthReqSanity fail - wrong algorithm\n")); - return FALSE; - } -} - -/* - ========================================================================== - Description: - MLME message sanity check - Return: - TRUE if all parameters are OK, FALSE otherwise - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -BOOLEAN MlmeAssocReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pApAddr, - OUT USHORT *pCapabilityInfo, - OUT ULONG *pTimeout, - OUT USHORT *pListenIntv) -{ - MLME_ASSOC_REQ_STRUCT *pInfo; - - pInfo = (MLME_ASSOC_REQ_STRUCT *)Msg; - *pTimeout = pInfo->Timeout; // timeout - COPY_MAC_ADDR(pApAddr, pInfo->Addr); // AP address - *pCapabilityInfo = pInfo->CapabilityInfo; // capability info - *pListenIntv = pInfo->ListenIntv; - - return TRUE; -} - -/* - ========================================================================== - Description: - MLME message sanity check - Return: - TRUE if all parameters are OK, FALSE otherwise - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -BOOLEAN PeerDisassocSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *pReason) -{ - PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; - - COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); - NdisMoveMemory(pReason, &pFrame->Octet[0], 2); - - return TRUE; -} - -/* - ======================================================================== - Routine Description: - Sanity check NetworkType (11b, 11g or 11a) - - Arguments: - pBss - Pointer to BSS table. - - Return Value: - Ndis802_11DS .......(11b) - Ndis802_11OFDM24....(11g) - Ndis802_11OFDM5.....(11a) - - IRQL = DISPATCH_LEVEL - - ======================================================================== -*/ -NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity( - IN PBSS_ENTRY pBss) -{ - NDIS_802_11_NETWORK_TYPE NetWorkType; - UCHAR rate, i; - - NetWorkType = Ndis802_11DS; - - if (pBss->Channel <= 14) - { - // - // First check support Rate. - // - for (i = 0; i < pBss->SupRateLen; i++) - { - rate = pBss->SupRate[i] & 0x7f; // Mask out basic rate set bit - if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22)) - { - continue; - } - else - { - // - // Otherwise (even rate > 108) means Ndis802_11OFDM24 - // - NetWorkType = Ndis802_11OFDM24; - break; - } - } - - // - // Second check Extend Rate. - // - if (NetWorkType != Ndis802_11OFDM24) - { - for (i = 0; i < pBss->ExtRateLen; i++) - { - rate = pBss->SupRate[i] & 0x7f; // Mask out basic rate set bit - if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22)) - { - continue; - } - else - { - // - // Otherwise (even rate > 108) means Ndis802_11OFDM24 - // - NetWorkType = Ndis802_11OFDM24; - break; - } - } - } - } - else - { - NetWorkType = Ndis802_11OFDM5; - } - - if (pBss->HtCapabilityLen != 0) - { - if (NetWorkType == Ndis802_11OFDM5) - NetWorkType = Ndis802_11OFDM5_N; - else - NetWorkType = Ndis802_11OFDM24_N; - } - - return NetWorkType; -} - -/* - ========================================================================== - Description: - Check the validity of the received EAPoL frame - Return: - TRUE if all parameters are OK, - FALSE otherwise - ========================================================================== - */ -BOOLEAN PeerWpaMessageSanity( - IN PRTMP_ADAPTER pAd, - IN PEAPOL_PACKET pMsg, - IN ULONG MsgLen, - IN UCHAR MsgType, - IN MAC_TABLE_ENTRY *pEntry) -{ - UCHAR mic[LEN_KEY_DESC_MIC], digest[80], KEYDATA[MAX_LEN_OF_RSNIE]; - BOOLEAN bReplayDiff = FALSE; - BOOLEAN bWPA2 = FALSE; - KEY_INFO EapolKeyInfo; - UCHAR GroupKeyIndex = 0; - - - NdisZeroMemory(mic, sizeof(mic)); - NdisZeroMemory(digest, sizeof(digest)); - NdisZeroMemory(KEYDATA, sizeof(KEYDATA)); - NdisZeroMemory((PUCHAR)&EapolKeyInfo, sizeof(EapolKeyInfo)); - - NdisMoveMemory((PUCHAR)&EapolKeyInfo, (PUCHAR)&pMsg->KeyDesc.KeyInfo, sizeof(KEY_INFO)); - - *((USHORT *)&EapolKeyInfo) = cpu2le16(*((USHORT *)&EapolKeyInfo)); - - // Choose WPA2 or not - if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) - bWPA2 = TRUE; - - // 0. Check MsgType - if ((MsgType > EAPOL_GROUP_MSG_2) || (MsgType < EAPOL_PAIR_MSG_1)) - { - DBGPRINT(RT_DEBUG_ERROR, ("The message type is invalid(%d)! \n", MsgType)); - return FALSE; - } - - // 1. Replay counter check - if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1) // For supplicant - { - // First validate replay counter, only accept message with larger replay counter. - // Let equal pass, some AP start with all zero replay counter - UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY]; - - NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); - if ((RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY) != 1) && - (RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0)) - { - bReplayDiff = TRUE; - } - } - else if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) // For authenticator - { - // check Replay Counter coresponds to MSG from authenticator, otherwise discard - if (!NdisEqualMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY)) - { - bReplayDiff = TRUE; - } - } - - // Replay Counter different condition - if (bReplayDiff) - { - // send wireless event - for replay counter different - if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_REPLAY_COUNTER_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); - - if (MsgType < EAPOL_GROUP_MSG_1) - { - DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in pairwise msg %d of 4-way handshake!\n", MsgType)); - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4))); - } - - hex_dump("Receive replay counter ", pMsg->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - hex_dump("Current replay counter ", pEntry->R_Counter, LEN_KEY_DESC_REPLAY); - return FALSE; - } - - // 2. Verify MIC except Pairwise Msg1 - if (MsgType != EAPOL_PAIR_MSG_1) - { - UCHAR rcvd_mic[LEN_KEY_DESC_MIC]; - - // Record the received MIC for check later - NdisMoveMemory(rcvd_mic, pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); - NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); - - if (EapolKeyInfo.KeyDescVer == DESC_TYPE_TKIP) // TKIP - { - HMAC_MD5(pEntry->PTK, LEN_EAP_MICK, (PUCHAR)pMsg, MsgLen, mic, MD5_DIGEST_SIZE); - } - else if (EapolKeyInfo.KeyDescVer == DESC_TYPE_AES) // AES - { - HMAC_SHA1(pEntry->PTK, LEN_EAP_MICK, (PUCHAR)pMsg, MsgLen, digest, SHA1_DIGEST_SIZE); - NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); - } - - if (!NdisEqualMemory(rcvd_mic, mic, LEN_KEY_DESC_MIC)) - { - // send wireless event - for MIC different - if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_MIC_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); - - if (MsgType < EAPOL_GROUP_MSG_1) - { - DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in pairwise msg %d of 4-way handshake!\n", MsgType)); - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4))); - } - - hex_dump("Received MIC", rcvd_mic, LEN_KEY_DESC_MIC); - hex_dump("Desired MIC", mic, LEN_KEY_DESC_MIC); - - return FALSE; - } - } - - // 1. Decrypt the Key Data field if GTK is included. - // 2. Extract the context of the Key Data field if it exist. - // The field in pairwise_msg_2_WPA1(WPA2) & pairwise_msg_3_WPA1 is clear. - // The field in group_msg_1_WPA1(WPA2) & pairwise_msg_3_WPA2 is encrypted. - if (CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen) > 0) - { - // Decrypt this field - if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1)) - { - if( - (EapolKeyInfo.KeyDescVer == DESC_TYPE_AES)) - { - // AES - AES_GTK_KEY_UNWRAP(&pEntry->PTK[16], KEYDATA, - CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen), - pMsg->KeyDesc.KeyData); - } - else - { - INT i; - UCHAR Key[32]; - // Decrypt TKIP GTK - // Construct 32 bytes RC4 Key - NdisMoveMemory(Key, pMsg->KeyDesc.KeyIv, 16); - NdisMoveMemory(&Key[16], &pEntry->PTK[16], 16); - ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32); - //discard first 256 bytes - for(i = 0; i < 256; i++) - ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT); - // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not - ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, - pMsg->KeyDesc.KeyData, - CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen)); - } - - if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) - GroupKeyIndex = EapolKeyInfo.KeyIndex; - - } - else if ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3 && !bWPA2)) - { - NdisMoveMemory(KEYDATA, pMsg->KeyDesc.KeyData, CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen)); - } - else - { - - return TRUE; - } - - // Parse Key Data field to - // 1. verify RSN IE for pairwise_msg_2_WPA1(WPA2) ,pairwise_msg_3_WPA1(WPA2) - // 2. verify KDE format for pairwise_msg_3_WPA2, group_msg_1_WPA2 - // 3. update shared key for pairwise_msg_3_WPA2, group_msg_1_WPA1(WPA2) - if (!RTMPParseEapolKeyData(pAd, KEYDATA, - CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen), - GroupKeyIndex, MsgType, bWPA2, pEntry)) - { - return FALSE; - } - } - - return TRUE; - -} - -#ifdef CONFIG_STA_SUPPORT -#ifdef QOS_DLS_SUPPORT -BOOLEAN MlmeDlsReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PRT_802_11_DLS *pDLS, - OUT PUSHORT pReason) -{ - MLME_DLS_REQ_STRUCT *pInfo; - - pInfo = (MLME_DLS_REQ_STRUCT *)Msg; - - *pDLS = pInfo->pDLS; - *pReason = pInfo->Reason; - - return TRUE; -} -#endif // QOS_DLS_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - -#ifdef QOS_DLS_SUPPORT -BOOLEAN PeerDlsReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pDA, - OUT PUCHAR pSA, - OUT USHORT *pCapabilityInfo, - OUT USHORT *pDlsTimeout, - OUT UCHAR *pRatesLen, - OUT UCHAR Rates[], - OUT UCHAR *pHtCapabilityLen, - OUT HT_CAPABILITY_IE *pHtCapability) -{ - CHAR *Ptr; - PFRAME_802_11 Fr = (PFRAME_802_11)Msg; - PEID_STRUCT eid_ptr; - - // to prevent caller from using garbage output value - *pCapabilityInfo = 0; - *pDlsTimeout = 0; - *pHtCapabilityLen = 0; - - Ptr = (PCHAR)Fr->Octet; - - // offset to destination MAC address (Category and Action field) - Ptr += 2; - - // get DA from payload and advance the pointer - NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN); - Ptr += MAC_ADDR_LEN; - - // get SA from payload and advance the pointer - NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN); - Ptr += MAC_ADDR_LEN; - - // get capability info from payload and advance the pointer - NdisMoveMemory(pCapabilityInfo, Ptr, 2); - Ptr += 2; - - // get capability info from payload and advance the pointer - NdisMoveMemory(pDlsTimeout, Ptr, 2); - Ptr += 2; - - // Category and Action field + DA + SA + capability + Timeout - eid_ptr = (PEID_STRUCT) &Fr->Octet[18]; - - while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen)) - { - switch(eid_ptr->Eid) - { - case IE_SUPP_RATES: - if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0)) - { - NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len); - DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n",eid_ptr->Len, Rates[0])); - DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7])); - *pRatesLen = eid_ptr->Len; - } - else - { - *pRatesLen = 8; - Rates[0] = 0x82; - Rates[1] = 0x84; - Rates[2] = 0x8b; - Rates[3] = 0x96; - Rates[4] = 0x12; - Rates[5] = 0x24; - Rates[6] = 0x48; - Rates[7] = 0x6c; - DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len)); - } - break; - - case IE_EXT_SUPP_RATES: - if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES) - { - NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len); - *pRatesLen = (*pRatesLen) + eid_ptr->Len; - } - else - { - NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen)); - *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES; - } - break; - - case IE_HT_CAP: - if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE)) - { - NdisMoveMemory(pHtCapability, eid_ptr->Octet, sizeof(HT_CAPABILITY_IE)); - - *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); -#ifdef UNALIGNMENT_SUPPORT - { - EXT_HT_CAP_INFO extHtCapInfo; - - NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); - *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); - NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); - } -#else - *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); -#endif // UNALIGNMENT_SUPPORT // - *pHtCapabilityLen = sizeof(HT_CAPABILITY_IE); - - DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - IE_HT_CAP\n")); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len)); - } - break; - - default: - break; - } - - eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); - } - - return TRUE; -} - -BOOLEAN PeerDlsRspSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pDA, - OUT PUCHAR pSA, - OUT USHORT *pCapabilityInfo, - OUT USHORT *pStatus, - OUT UCHAR *pRatesLen, - OUT UCHAR Rates[], - OUT UCHAR *pHtCapabilityLen, - OUT HT_CAPABILITY_IE *pHtCapability) -{ - CHAR *Ptr; - PFRAME_802_11 Fr = (PFRAME_802_11)Msg; - PEID_STRUCT eid_ptr; - - // to prevent caller from using garbage output value - *pStatus = 0; - *pCapabilityInfo = 0; - *pHtCapabilityLen = 0; - - Ptr = (PCHAR)Fr->Octet; - - // offset to destination MAC address (Category and Action field) - Ptr += 2; - - // get status code from payload and advance the pointer - NdisMoveMemory(pStatus, Ptr, 2); - Ptr += 2; - - // get DA from payload and advance the pointer - NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN); - Ptr += MAC_ADDR_LEN; - - // get SA from payload and advance the pointer - NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN); - Ptr += MAC_ADDR_LEN; - - if (pStatus == 0) - { - // get capability info from payload and advance the pointer - NdisMoveMemory(pCapabilityInfo, Ptr, 2); - Ptr += 2; - } - - // Category and Action field + status code + DA + SA + capability - eid_ptr = (PEID_STRUCT) &Fr->Octet[18]; - - while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen)) - { - switch(eid_ptr->Eid) - { - case IE_SUPP_RATES: - if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0)) - { - NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len); - DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n",eid_ptr->Len, Rates[0])); - DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7])); - *pRatesLen = eid_ptr->Len; - } - else - { - *pRatesLen = 8; - Rates[0] = 0x82; - Rates[1] = 0x84; - Rates[2] = 0x8b; - Rates[3] = 0x96; - Rates[4] = 0x12; - Rates[5] = 0x24; - Rates[6] = 0x48; - Rates[7] = 0x6c; - DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len)); - } - break; - - case IE_EXT_SUPP_RATES: - if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES) - { - NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len); - *pRatesLen = (*pRatesLen) + eid_ptr->Len; - } - else - { - NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen)); - *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES; - } - break; - - case IE_HT_CAP: - if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE)) - { - NdisMoveMemory(pHtCapability, eid_ptr->Octet, sizeof(HT_CAPABILITY_IE)); - - *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); -#ifdef UNALIGNMENT_SUPPORT - { - EXT_HT_CAP_INFO extHtCapInfo; - - NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); - *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); - NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); - } -#else - *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); -#endif // UNALIGNMENT_SUPPORT // - *pHtCapabilityLen = sizeof(HT_CAPABILITY_IE); - - DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - IE_HT_CAP\n")); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len)); - } - break; - - default: - break; - } - - eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); - } - - return TRUE; -} - -BOOLEAN PeerDlsTearDownSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pDA, - OUT PUCHAR pSA, - OUT USHORT *pReason) -{ - CHAR *Ptr; - PFRAME_802_11 Fr = (PFRAME_802_11)Msg; - - // to prevent caller from using garbage output value - *pReason = 0; - - Ptr = (PCHAR)Fr->Octet; - - // offset to destination MAC address (Category and Action field) - Ptr += 2; - - // get DA from payload and advance the pointer - NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN); - Ptr += MAC_ADDR_LEN; - - // get SA from payload and advance the pointer - NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN); - Ptr += MAC_ADDR_LEN; - - // get reason code from payload and advance the pointer - NdisMoveMemory(pReason, Ptr, 2); - Ptr += 2; - - return TRUE; -} -#endif // QOS_DLS_SUPPORT // diff --git a/drivers/staging/rt3090/common/cmm_sync.c b/drivers/staging/rt3090/common/cmm_sync.c deleted file mode 100644 index 6d7b974d7e1564047d35d63f750ddcd5784c1764..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/cmm_sync.c +++ /dev/null @@ -1,734 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - cmm_sync.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - John Chang 2004-09-01 modified for rt2561/2661 -*/ - -#include "../rt_config.h" - - -// 2.4 Ghz channel plan index in the TxPower arrays. -#define BG_BAND_REGION_0_START 0 // 1,2,3,4,5,6,7,8,9,10,11 -#define BG_BAND_REGION_0_SIZE 11 -#define BG_BAND_REGION_1_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13 -#define BG_BAND_REGION_1_SIZE 13 -#define BG_BAND_REGION_2_START 9 // 10,11 -#define BG_BAND_REGION_2_SIZE 2 -#define BG_BAND_REGION_3_START 9 // 10,11,12,13 -#define BG_BAND_REGION_3_SIZE 4 -#define BG_BAND_REGION_4_START 13 // 14 -#define BG_BAND_REGION_4_SIZE 1 -#define BG_BAND_REGION_5_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13,14 -#define BG_BAND_REGION_5_SIZE 14 -#define BG_BAND_REGION_6_START 2 // 3,4,5,6,7,8,9 -#define BG_BAND_REGION_6_SIZE 7 -#define BG_BAND_REGION_7_START 4 // 5,6,7,8,9,10,11,12,13 -#define BG_BAND_REGION_7_SIZE 9 -#define BG_BAND_REGION_31_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13,14 -#define BG_BAND_REGION_31_SIZE 14 - -// 5 Ghz channel plan index in the TxPower arrays. -UCHAR A_BAND_REGION_0_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}; -UCHAR A_BAND_REGION_1_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; -UCHAR A_BAND_REGION_2_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64}; -UCHAR A_BAND_REGION_3_CHANNEL_LIST[]={52, 56, 60, 64, 149, 153, 157, 161}; -UCHAR A_BAND_REGION_4_CHANNEL_LIST[]={149, 153, 157, 161, 165}; -UCHAR A_BAND_REGION_5_CHANNEL_LIST[]={149, 153, 157, 161}; -UCHAR A_BAND_REGION_6_CHANNEL_LIST[]={36, 40, 44, 48}; -UCHAR A_BAND_REGION_7_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 169, 173}; -UCHAR A_BAND_REGION_8_CHANNEL_LIST[]={52, 56, 60, 64}; -UCHAR A_BAND_REGION_9_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}; -UCHAR A_BAND_REGION_10_CHANNEL_LIST[]={36, 40, 44, 48, 149, 153, 157, 161, 165}; -UCHAR A_BAND_REGION_11_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161}; -UCHAR A_BAND_REGION_12_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; -UCHAR A_BAND_REGION_13_CHANNEL_LIST[]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161}; -UCHAR A_BAND_REGION_14_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}; -UCHAR A_BAND_REGION_15_CHANNEL_LIST[]={149, 153, 157, 161, 165, 169, 173}; - - -//BaSizeArray follows the 802.11n definition as MaxRxFactor. 2^(13+factor) bytes. When factor =0, it's about Ba buffer size =8. -UCHAR BaSizeArray[4] = {8,16,32,64}; - -/* - ========================================================================== - Description: - Update StaCfg->ChannelList[] according to 1) Country Region 2) RF IC type, - and 3) PHY-mode user selected. - The outcome is used by driver when doing site survey. - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID BuildChannelList( - IN PRTMP_ADAPTER pAd) -{ - UCHAR i, j, index=0, num=0; - PUCHAR pChannelList = NULL; - - NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER)); - - // if not 11a-only mode, channel list starts from 2.4Ghz band - if ((pAd->CommonCfg.PhyMode != PHY_11A) -#ifdef DOT11_N_SUPPORT - && (pAd->CommonCfg.PhyMode != PHY_11AN_MIXED) && (pAd->CommonCfg.PhyMode != PHY_11N_5G) -#endif // DOT11_N_SUPPORT // - ) - { - switch (pAd->CommonCfg.CountryRegion & 0x7f) - { - case REGION_0_BG_BAND: // 1 -11 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_0_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_0_SIZE); - index += BG_BAND_REGION_0_SIZE; - break; - case REGION_1_BG_BAND: // 1 - 13 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_1_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_1_SIZE); - index += BG_BAND_REGION_1_SIZE; - break; - case REGION_2_BG_BAND: // 10 - 11 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_2_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_2_SIZE); - index += BG_BAND_REGION_2_SIZE; - break; - case REGION_3_BG_BAND: // 10 - 13 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_3_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_3_SIZE); - index += BG_BAND_REGION_3_SIZE; - break; - case REGION_4_BG_BAND: // 14 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_4_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_4_SIZE); - index += BG_BAND_REGION_4_SIZE; - break; - case REGION_5_BG_BAND: // 1 - 14 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_5_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_5_SIZE); - index += BG_BAND_REGION_5_SIZE; - break; - case REGION_6_BG_BAND: // 3 - 9 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_6_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_6_SIZE); - index += BG_BAND_REGION_6_SIZE; - break; - case REGION_7_BG_BAND: // 5 - 13 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_7_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_7_SIZE); - index += BG_BAND_REGION_7_SIZE; - break; - case REGION_31_BG_BAND: // 1 - 14 - NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_31_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_31_SIZE); - index += BG_BAND_REGION_31_SIZE; - break; - default: // Error. should never happen - break; - } - for (i=0; iChannelList[i].MaxTxPwr = 20; - } - - if ((pAd->CommonCfg.PhyMode == PHY_11A) || (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) -#ifdef DOT11_N_SUPPORT - || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) - || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11N_5G) -#endif // DOT11_N_SUPPORT // - ) - { - switch (pAd->CommonCfg.CountryRegionForABand & 0x7f) - { - case REGION_0_A_BAND: - num = sizeof(A_BAND_REGION_0_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_0_CHANNEL_LIST; - break; - case REGION_1_A_BAND: - num = sizeof(A_BAND_REGION_1_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_1_CHANNEL_LIST; - break; - case REGION_2_A_BAND: - num = sizeof(A_BAND_REGION_2_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_2_CHANNEL_LIST; - break; - case REGION_3_A_BAND: - num = sizeof(A_BAND_REGION_3_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_3_CHANNEL_LIST; - break; - case REGION_4_A_BAND: - num = sizeof(A_BAND_REGION_4_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_4_CHANNEL_LIST; - break; - case REGION_5_A_BAND: - num = sizeof(A_BAND_REGION_5_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_5_CHANNEL_LIST; - break; - case REGION_6_A_BAND: - num = sizeof(A_BAND_REGION_6_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_6_CHANNEL_LIST; - break; - case REGION_7_A_BAND: - num = sizeof(A_BAND_REGION_7_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_7_CHANNEL_LIST; - break; - case REGION_8_A_BAND: - num = sizeof(A_BAND_REGION_8_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_8_CHANNEL_LIST; - break; - case REGION_9_A_BAND: - num = sizeof(A_BAND_REGION_9_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_9_CHANNEL_LIST; - break; - case REGION_10_A_BAND: - num = sizeof(A_BAND_REGION_10_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_10_CHANNEL_LIST; - break; - case REGION_11_A_BAND: - num = sizeof(A_BAND_REGION_11_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_11_CHANNEL_LIST; - break; - case REGION_12_A_BAND: - num = sizeof(A_BAND_REGION_12_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_12_CHANNEL_LIST; - break; - case REGION_13_A_BAND: - num = sizeof(A_BAND_REGION_13_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_13_CHANNEL_LIST; - break; - case REGION_14_A_BAND: - num = sizeof(A_BAND_REGION_14_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_14_CHANNEL_LIST; - break; - case REGION_15_A_BAND: - num = sizeof(A_BAND_REGION_15_CHANNEL_LIST)/sizeof(UCHAR); - pChannelList = A_BAND_REGION_15_CHANNEL_LIST; - break; - default: // Error. should never happen - DBGPRINT(RT_DEBUG_WARN,("countryregion=%d not support", pAd->CommonCfg.CountryRegionForABand)); - break; - } - - if (num != 0) - { - UCHAR RadarCh[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; - for (i=0; iTxPower[j].Channel) - NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER)); - } - for (j=0; j<15; j++) - { - if (pChannelList[i] == RadarCh[j]) - pAd->ChannelList[index+i].DfsReq = TRUE; - } - pAd->ChannelList[index+i].MaxTxPwr = 20; - } - index += num; - } - } - - pAd->ChannelListNum = index; - DBGPRINT(RT_DEBUG_TRACE,("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n", - pAd->CommonCfg.CountryRegion, pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType, pAd->CommonCfg.PhyMode, pAd->ChannelListNum)); -#ifdef DBG - for (i=0;iChannelListNum;i++) - { - DBGPRINT_RAW(RT_DEBUG_TRACE,("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, \n ", pAd->ChannelList[i].Channel, pAd->ChannelList[i].Power, pAd->ChannelList[i].Power2)); - } -#endif -} - -/* - ========================================================================== - Description: - This routine return the first channel number according to the country - code selection and RF IC selection (signal band or dual band). It is called - whenever driver need to start a site survey of all supported channels. - Return: - ch - the first channel number of current country code setting - - IRQL = PASSIVE_LEVEL - - ========================================================================== - */ -UCHAR FirstChannel( - IN PRTMP_ADAPTER pAd) -{ - return pAd->ChannelList[0].Channel; -} - -/* - ========================================================================== - Description: - This routine returns the next channel number. This routine is called - during driver need to start a site survey of all supported channels. - Return: - next_channel - the next channel number valid in current country code setting. - Note: - return 0 if no more next channel - ========================================================================== - */ -UCHAR NextChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR channel) -{ - int i; - UCHAR next_channel = 0; - - for (i = 0; i < (pAd->ChannelListNum - 1); i++) - if (channel == pAd->ChannelList[i].Channel) - { - next_channel = pAd->ChannelList[i+1].Channel; - break; - } - return next_channel; -} - -/* - ========================================================================== - Description: - This routine is for Cisco Compatible Extensions 2.X - Spec31. AP Control of Client Transmit Power - Return: - None - Note: - Required by Aironet dBm(mW) - 0dBm(1mW), 1dBm(5mW), 13dBm(20mW), 15dBm(30mW), - 17dBm(50mw), 20dBm(100mW) - - We supported - 3dBm(Lowest), 6dBm(10%), 9dBm(25%), 12dBm(50%), - 14dBm(75%), 15dBm(100%) - - The client station's actual transmit power shall be within +/- 5dB of - the minimum value or next lower value. - ========================================================================== - */ -VOID ChangeToCellPowerLimit( - IN PRTMP_ADAPTER pAd, - IN UCHAR AironetCellPowerLimit) -{ - //valud 0xFF means that hasn't found power limit information - //from the AP's Beacon/Probe response. - if (AironetCellPowerLimit == 0xFF) - return; - - if (AironetCellPowerLimit < 6) //Used Lowest Power Percentage. - pAd->CommonCfg.TxPowerPercentage = 6; - else if (AironetCellPowerLimit < 9) - pAd->CommonCfg.TxPowerPercentage = 10; - else if (AironetCellPowerLimit < 12) - pAd->CommonCfg.TxPowerPercentage = 25; - else if (AironetCellPowerLimit < 14) - pAd->CommonCfg.TxPowerPercentage = 50; - else if (AironetCellPowerLimit < 15) - pAd->CommonCfg.TxPowerPercentage = 75; - else - pAd->CommonCfg.TxPowerPercentage = 100; //else used maximum - - if (pAd->CommonCfg.TxPowerPercentage > pAd->CommonCfg.TxPowerDefault) - pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; - -} - -CHAR ConvertToRssi( - IN PRTMP_ADAPTER pAd, - IN CHAR Rssi, - IN UCHAR RssiNumber) -{ - UCHAR RssiOffset, LNAGain; - - // Rssi equals to zero should be an invalid value - if (Rssi == 0) - return -99; - - LNAGain = GET_LNA_GAIN(pAd); - if (pAd->LatchRfRegs.Channel > 14) - { - if (RssiNumber == 0) - RssiOffset = pAd->ARssiOffset0; - else if (RssiNumber == 1) - RssiOffset = pAd->ARssiOffset1; - else - RssiOffset = pAd->ARssiOffset2; - } - else - { - if (RssiNumber == 0) - RssiOffset = pAd->BGRssiOffset0; - else if (RssiNumber == 1) - RssiOffset = pAd->BGRssiOffset1; - else - RssiOffset = pAd->BGRssiOffset2; - } - - return (-12 - RssiOffset - LNAGain - Rssi); -} - -/* - ========================================================================== - Description: - Scan next channel - ========================================================================== - */ -VOID ScanNextChannel( - IN PRTMP_ADAPTER pAd) -{ - HEADER_802_11 Hdr80211; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - UCHAR SsidLen = 0, ScanType = pAd->MlmeAux.ScanType, BBPValue = 0; -#ifdef CONFIG_STA_SUPPORT - USHORT Status; - PHEADER_802_11 pHdr80211; -#endif // CONFIG_STA_SUPPORT // - UINT ScanTimeIn5gChannel = SHORT_CHANNEL_TIME; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (MONITOR_ON(pAd)) - return; - } -#endif // CONFIG_STA_SUPPORT // - -#ifdef RALINK_ATE - // Nothing to do in ATE mode. - if (ATE_ON(pAd)) - return; -#endif // RALINK_ATE // - - if (pAd->MlmeAux.Channel == 0) - { - if ((pAd->CommonCfg.BBPCurrentBW == BW_40) -#ifdef CONFIG_STA_SUPPORT - && (INFRA_ON(pAd) - || (pAd->OpMode == OPMODE_AP)) -#endif // CONFIG_STA_SUPPORT // - ) - { - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue &= (~0x18); - BBPValue |= 0x10; - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); - } - else - { - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to channel %d, Total BSS[%02d]\n",pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); - } - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // - // To prevent data lost. - // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. - // Now, we need to send an NULL data with turned PSM bit off to AP, when scan progress done - // - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) - { - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); - if (NStatus == NDIS_STATUS_SUCCESS) - { - pHdr80211 = (PHEADER_802_11) pOutBuffer; - MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); - pHdr80211->Duration = 0; - pHdr80211->FC.Type = BTYPE_DATA; - pHdr80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); - - // Send using priority queue - MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); - DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame\n")); - MlmeFreeMemory(pAd, pOutBuffer); - RTMPusecDelay(5000); - } - } - - pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; - Status = MLME_SUCCESS; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); - } -#endif // CONFIG_STA_SUPPORT // - - - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); - } - else - { -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // BBP and RF are not accessible in PS mode, we has to wake them up first - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - AsicForceWakeup(pAd, TRUE); - - // leave PSM during scanning. otherwise we may lost ProbeRsp & BEACON - if (pAd->StaCfg.Psm == PWR_SAVE) - RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE); - } -#endif // CONFIG_STA_SUPPORT // - - AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, TRUE); - AsicLockChannel(pAd, pAd->MlmeAux.Channel); - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (pAd->MlmeAux.Channel > 14) - { - if ((pAd->CommonCfg.bIEEE80211H == 1) && RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) - { - ScanType = SCAN_PASSIVE; - ScanTimeIn5gChannel = MIN_CHANNEL_TIME; - } - } - -#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier - // carrier detection - if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) - { - ScanType = SCAN_PASSIVE; - ScanTimeIn5gChannel = MIN_CHANNEL_TIME; - } -#endif // CARRIER_DETECTION_SUPPORT // - } - -#endif // CONFIG_STA_SUPPORT // - - //Global country domain(ch1-11:active scan, ch12-14 passive scan) - if ((pAd->MlmeAux.Channel <= 14) && (pAd->MlmeAux.Channel >= 12) && ((pAd->CommonCfg.CountryRegion & 0x7f) == REGION_31_BG_BAND)) - { - ScanType = SCAN_PASSIVE; - } - - // We need to shorten active scan time in order for WZC connect issue - // Chnage the channel scan time for CISCO stuff based on its IAPP announcement - if (ScanType == FAST_SCAN_ACTIVE) - RTMPSetTimer(&pAd->MlmeAux.ScanTimer, FAST_ACTIVE_SCAN_TIME); - else // must be SCAN_PASSIVE or SCAN_ACTIVE - { - if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) -#ifdef DOT11_N_SUPPORT - || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) -#endif // DOT11_N_SUPPORT // - ) - { - if (pAd->MlmeAux.Channel > 14) - RTMPSetTimer(&pAd->MlmeAux.ScanTimer, ScanTimeIn5gChannel); - else - RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MIN_CHANNEL_TIME); - } - else - RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MAX_CHANNEL_TIME); - } - - if ((ScanType == SCAN_ACTIVE) - || (ScanType == FAST_SCAN_ACTIVE) - ) - { - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - ScanNextChannel() allocate memory fail\n")); -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; - Status = MLME_FAIL_NO_RESOURCE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); - } -#endif // CONFIG_STA_SUPPORT // - - return; - } - - // There is no need to send broadcast probe request if active scan is in effect. - if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) - ) - SsidLen = pAd->MlmeAux.SsidLen; - else - SsidLen = 0; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); -#endif // CONFIG_STA_SUPPORT // - - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &Hdr80211, - 1, &SsidIe, - 1, &SsidLen, - SsidLen, pAd->MlmeAux.Ssid, - 1, &SupRateIe, - 1, &pAd->CommonCfg.SupRateLen, - pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, - END_OF_ARGS); - - if (pAd->CommonCfg.ExtRateLen) - { - ULONG Tmp; - MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, - 1, &ExtRateIe, - 1, &pAd->CommonCfg.ExtRateLen, - pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, - END_OF_ARGS); - FrameLen += Tmp; - } - -#ifdef DOT11_N_SUPPORT - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) - { - ULONG Tmp; - UCHAR HtLen; - UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; -#ifdef RT_BIG_ENDIAN - HT_CAPABILITY_IE HtCapabilityTmp; -#endif - if (pAd->bBroadComHT == TRUE) - { - HtLen = pAd->MlmeAux.HtCapabilityLen + 4; -#ifdef RT_BIG_ENDIAN - NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); - *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); -#ifdef UNALIGNMENT_SUPPORT - { - EXT_HT_CAP_INFO extHtCapInfo; - - NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); - *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); - NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); - } -#else - *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); -#endif // UNALIGNMENT_SUPPORT // - - MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, - 1, &WpaIe, - 1, &HtLen, - 4, &BROADCOM[0], - pAd->MlmeAux.HtCapabilityLen, &HtCapabilityTmp, - END_OF_ARGS); -#else - MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, - 1, &WpaIe, - 1, &HtLen, - 4, &BROADCOM[0], - pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, - END_OF_ARGS); -#endif // RT_BIG_ENDIAN // - } - else - { - HtLen = pAd->MlmeAux.HtCapabilityLen; -#ifdef RT_BIG_ENDIAN - NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE); - *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); -#ifdef UNALIGNMENT_SUPPORT - { - EXT_HT_CAP_INFO extHtCapInfo; - - NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); - *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); - NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); - } -#else - *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); -#endif // UNALIGNMENT_SUPPORT // - - MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, - 1, &HtCapIe, - 1, &HtLen, - HtLen, &HtCapabilityTmp, - END_OF_ARGS); -#else - MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, - 1, &HtCapIe, - 1, &HtLen, - HtLen, &pAd->CommonCfg.HtCapability, - END_OF_ARGS); -#endif // RT_BIG_ENDIAN // - } - FrameLen += Tmp; - -#ifdef DOT11N_DRAFT3 - if (pAd->CommonCfg.BACapability.field.b2040CoexistScanSup == 1) - { - ULONG Tmp; - HtLen = 1; - MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, - 1, &ExtHtCapIe, - 1, &HtLen, - 1, &pAd->CommonCfg.BSSCoexist2040.word, - END_OF_ARGS); - - FrameLen += Tmp; - } -#endif // DOT11N_DRAFT3 // - } -#endif // DOT11_N_SUPPORT // - - - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - } - - // For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe reponse - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - pAd->Mlme.SyncMachine.CurrState = SCAN_LISTEN; -#endif // CONFIG_STA_SUPPORT // - - } -} - -VOID MgtProbReqMacHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PHEADER_802_11 pHdr80211, - IN UCHAR SubType, - IN UCHAR ToDs, - IN PUCHAR pDA, - IN PUCHAR pBssid) -{ - NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); - - pHdr80211->FC.Type = BTYPE_MGMT; - pHdr80211->FC.SubType = SubType; - if (SubType == SUBTYPE_ACK) - pHdr80211->FC.Type = BTYPE_CNTL; - pHdr80211->FC.ToDs = ToDs; - COPY_MAC_ADDR(pHdr80211->Addr1, pDA); - COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); - COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); -} diff --git a/drivers/staging/rt3090/common/cmm_tkip.c b/drivers/staging/rt3090/common/cmm_tkip.c deleted file mode 100644 index 0b474f20859bde5b08ceda190b8650672bb3b43e..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/cmm_tkip.c +++ /dev/null @@ -1,966 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - cmm_tkip.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Paul Wu 02-25-02 Initial -*/ - -#include "../rt_config.h" - - -// Rotation functions on 32 bit values -#define ROL32( A, n ) \ - ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) ) -#define ROR32( A, n ) ROL32( (A), 32-(n) ) - -UINT Tkip_Sbox_Lower[256] = -{ - 0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54, - 0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A, - 0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B, - 0xEC,0x67,0xFD,0xEA,0xBF,0xF7,0x96,0x5B, - 0xC2,0x1C,0xAE,0x6A,0x5A,0x41,0x02,0x4F, - 0x5C,0xF4,0x34,0x08,0x93,0x73,0x53,0x3F, - 0x0C,0x52,0x65,0x5E,0x28,0xA1,0x0F,0xB5, - 0x09,0x36,0x9B,0x3D,0x26,0x69,0xCD,0x9F, - 0x1B,0x9E,0x74,0x2E,0x2D,0xB2,0xEE,0xFB, - 0xF6,0x4D,0x61,0xCE,0x7B,0x3E,0x71,0x97, - 0xF5,0x68,0x00,0x2C,0x60,0x1F,0xC8,0xED, - 0xBE,0x46,0xD9,0x4B,0xDE,0xD4,0xE8,0x4A, - 0x6B,0x2A,0xE5,0x16,0xC5,0xD7,0x55,0x94, - 0xCF,0x10,0x06,0x81,0xF0,0x44,0xBA,0xE3, - 0xF3,0xFE,0xC0,0x8A,0xAD,0xBC,0x48,0x04, - 0xDF,0xC1,0x75,0x63,0x30,0x1A,0x0E,0x6D, - 0x4C,0x14,0x35,0x2F,0xE1,0xA2,0xCC,0x39, - 0x57,0xF2,0x82,0x47,0xAC,0xE7,0x2B,0x95, - 0xA0,0x98,0xD1,0x7F,0x66,0x7E,0xAB,0x83, - 0xCA,0x29,0xD3,0x3C,0x79,0xE2,0x1D,0x76, - 0x3B,0x56,0x4E,0x1E,0xDB,0x0A,0x6C,0xE4, - 0x5D,0x6E,0xEF,0xA6,0xA8,0xA4,0x37,0x8B, - 0x32,0x43,0x59,0xB7,0x8C,0x64,0xD2,0xE0, - 0xB4,0xFA,0x07,0x25,0xAF,0x8E,0xE9,0x18, - 0xD5,0x88,0x6F,0x72,0x24,0xF1,0xC7,0x51, - 0x23,0x7C,0x9C,0x21,0xDD,0xDC,0x86,0x85, - 0x90,0x42,0xC4,0xAA,0xD8,0x05,0x01,0x12, - 0xA3,0x5F,0xF9,0xD0,0x91,0x58,0x27,0xB9, - 0x38,0x13,0xB3,0x33,0xBB,0x70,0x89,0xA7, - 0xB6,0x22,0x92,0x20,0x49,0xFF,0x78,0x7A, - 0x8F,0xF8,0x80,0x17,0xDA,0x31,0xC6,0xB8, - 0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A -}; - -UINT Tkip_Sbox_Upper[256] = -{ - 0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91, - 0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC, - 0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB, - 0x41,0xB3,0x5F,0x45,0x23,0x53,0xE4,0x9B, - 0x75,0xE1,0x3D,0x4C,0x6C,0x7E,0xF5,0x83, - 0x68,0x51,0xD1,0xF9,0xE2,0xAB,0x62,0x2A, - 0x08,0x95,0x46,0x9D,0x30,0x37,0x0A,0x2F, - 0x0E,0x24,0x1B,0xDF,0xCD,0x4E,0x7F,0xEA, - 0x12,0x1D,0x58,0x34,0x36,0xDC,0xB4,0x5B, - 0xA4,0x76,0xB7,0x7D,0x52,0xDD,0x5E,0x13, - 0xA6,0xB9,0x00,0xC1,0x40,0xE3,0x79,0xB6, - 0xD4,0x8D,0x67,0x72,0x94,0x98,0xB0,0x85, - 0xBB,0xC5,0x4F,0xED,0x86,0x9A,0x66,0x11, - 0x8A,0xE9,0x04,0xFE,0xA0,0x78,0x25,0x4B, - 0xA2,0x5D,0x80,0x05,0x3F,0x21,0x70,0xF1, - 0x63,0x77,0xAF,0x42,0x20,0xE5,0xFD,0xBF, - 0x81,0x18,0x26,0xC3,0xBE,0x35,0x88,0x2E, - 0x93,0x55,0xFC,0x7A,0xC8,0xBA,0x32,0xE6, - 0xC0,0x19,0x9E,0xA3,0x44,0x54,0x3B,0x0B, - 0x8C,0xC7,0x6B,0x28,0xA7,0xBC,0x16,0xAD, - 0xDB,0x64,0x74,0x14,0x92,0x0C,0x48,0xB8, - 0x9F,0xBD,0x43,0xC4,0x39,0x31,0xD3,0xF2, - 0xD5,0x8B,0x6E,0xDA,0x01,0xB1,0x9C,0x49, - 0xD8,0xAC,0xF3,0xCF,0xCA,0xF4,0x47,0x10, - 0x6F,0xF0,0x4A,0x5C,0x38,0x57,0x73,0x97, - 0xCB,0xA1,0xE8,0x3E,0x96,0x61,0x0D,0x0F, - 0xE0,0x7C,0x71,0xCC,0x90,0x06,0xF7,0x1C, - 0xC2,0x6A,0xAE,0x69,0x17,0x99,0x3A,0x27, - 0xD9,0xEB,0x2B,0x22,0xD2,0xA9,0x07,0x33, - 0x2D,0x3C,0x15,0xC9,0x87,0xAA,0x50,0xA5, - 0x03,0x59,0x09,0x1A,0x65,0xD7,0x84,0xD0, - 0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C -}; - -// -// Expanded IV for TKIP function. -// -typedef struct PACKED _IV_CONTROL_ -{ - union PACKED - { - struct PACKED - { - UCHAR rc0; - UCHAR rc1; - UCHAR rc2; - - union PACKED - { - struct PACKED - { -#ifdef RT_BIG_ENDIAN - UCHAR KeyID:2; - UCHAR ExtIV:1; - UCHAR Rsvd:5; -#else - UCHAR Rsvd:5; - UCHAR ExtIV:1; - UCHAR KeyID:2; -#endif - } field; - UCHAR Byte; - } CONTROL; - } field; - - ULONG word; - } IV16; - - ULONG IV32; -} TKIP_IV, *PTKIP_IV; - - -/* - ======================================================================== - - Routine Description: - Convert from UCHAR[] to ULONG in a portable way - - Arguments: - pMICKey pointer to MIC Key - - Return Value: - None - - Note: - - ======================================================================== -*/ -ULONG RTMPTkipGetUInt32( - IN PUCHAR pMICKey) -{ - ULONG res = 0; - INT i; - - for (i = 0; i < 4; i++) - { - res |= (*pMICKey++) << (8 * i); - } - - return res; -} - -/* - ======================================================================== - - Routine Description: - Convert from ULONG to UCHAR[] in a portable way - - Arguments: - pDst pointer to destination for convert ULONG to UCHAR[] - val the value for convert - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPTkipPutUInt32( - IN OUT PUCHAR pDst, - IN ULONG val) -{ - INT i; - - for(i = 0; i < 4; i++) - { - *pDst++ = (UCHAR) (val & 0xff); - val >>= 8; - } -} - -/* - ======================================================================== - - Routine Description: - Set the MIC Key. - - Arguments: - pAd Pointer to our adapter - pMICKey pointer to MIC Key - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPTkipSetMICKey( - IN PTKIP_KEY_INFO pTkip, - IN PUCHAR pMICKey) -{ - // Set the key - pTkip->K0 = RTMPTkipGetUInt32(pMICKey); - pTkip->K1 = RTMPTkipGetUInt32(pMICKey + 4); - // and reset the message - pTkip->L = pTkip->K0; - pTkip->R = pTkip->K1; - pTkip->nBytesInM = 0; - pTkip->M = 0; -} - -/* - ======================================================================== - - Routine Description: - Calculate the MIC Value. - - Arguments: - pAd Pointer to our adapter - uChar Append this uChar - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPTkipAppendByte( - IN PTKIP_KEY_INFO pTkip, - IN UCHAR uChar) -{ - // Append the byte to our word-sized buffer - pTkip->M |= (uChar << (8* pTkip->nBytesInM)); - pTkip->nBytesInM++; - // Process the word if it is full. - if( pTkip->nBytesInM >= 4 ) - { - pTkip->L ^= pTkip->M; - pTkip->R ^= ROL32( pTkip->L, 17 ); - pTkip->L += pTkip->R; - pTkip->R ^= ((pTkip->L & 0xff00ff00) >> 8) | ((pTkip->L & 0x00ff00ff) << 8); - pTkip->L += pTkip->R; - pTkip->R ^= ROL32( pTkip->L, 3 ); - pTkip->L += pTkip->R; - pTkip->R ^= ROR32( pTkip->L, 2 ); - pTkip->L += pTkip->R; - // Clear the buffer - pTkip->M = 0; - pTkip->nBytesInM = 0; - } -} - -/* - ======================================================================== - - Routine Description: - Calculate the MIC Value. - - Arguments: - pAd Pointer to our adapter - pSrc Pointer to source data for Calculate MIC Value - Len Indicate the length of the source data - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPTkipAppend( - IN PTKIP_KEY_INFO pTkip, - IN PUCHAR pSrc, - IN UINT nBytes) -{ - // This is simple - while(nBytes > 0) - { - RTMPTkipAppendByte(pTkip, *pSrc++); - nBytes--; - } -} - -/* - ======================================================================== - - Routine Description: - Get the MIC Value. - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - the MIC Value is store in pAd->PrivateInfo.MIC - ======================================================================== -*/ -VOID RTMPTkipGetMIC( - IN PTKIP_KEY_INFO pTkip) -{ - // Append the minimum padding - RTMPTkipAppendByte(pTkip, 0x5a ); - RTMPTkipAppendByte(pTkip, 0 ); - RTMPTkipAppendByte(pTkip, 0 ); - RTMPTkipAppendByte(pTkip, 0 ); - RTMPTkipAppendByte(pTkip, 0 ); - // and then zeroes until the length is a multiple of 4 - while( pTkip->nBytesInM != 0 ) - { - RTMPTkipAppendByte(pTkip, 0 ); - } - // The appendByte function has already computed the result. - RTMPTkipPutUInt32(pTkip->MIC, pTkip->L); - RTMPTkipPutUInt32(pTkip->MIC + 4, pTkip->R); -} - -/* - ======================================================================== - - Routine Description: - Init Tkip function. - - Arguments: - pAd Pointer to our adapter - pTKey Pointer to the Temporal Key (TK), TK shall be 128bits. - KeyId TK Key ID - pTA Pointer to transmitter address - pMICKey pointer to MIC Key - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPInitTkipEngine( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKey, - IN UCHAR KeyId, - IN PUCHAR pTA, - IN PUCHAR pMICKey, - IN PUCHAR pTSC, - OUT PULONG pIV16, - OUT PULONG pIV32) -{ - TKIP_IV tkipIv; - - // Prepare 8 bytes TKIP encapsulation for MPDU - NdisZeroMemory(&tkipIv, sizeof(TKIP_IV)); - tkipIv.IV16.field.rc0 = *(pTSC + 1); - tkipIv.IV16.field.rc1 = (tkipIv.IV16.field.rc0 | 0x20) & 0x7f; - tkipIv.IV16.field.rc2 = *pTSC; - tkipIv.IV16.field.CONTROL.field.ExtIV = 1; // 0: non-extended IV, 1: an extended IV - tkipIv.IV16.field.CONTROL.field.KeyID = KeyId; -// tkipIv.IV32 = *(PULONG)(pTSC + 2); - NdisMoveMemory(&tkipIv.IV32, (pTSC + 2), 4); // Copy IV - - *pIV16 = tkipIv.IV16.word; - *pIV32 = tkipIv.IV32; -} - -/* - ======================================================================== - - Routine Description: - Init MIC Value calculation function which include set MIC key & - calculate first 16 bytes (DA + SA + priority + 0) - - Arguments: - pAd Pointer to our adapter - pTKey Pointer to the Temporal Key (TK), TK shall be 128bits. - pDA Pointer to DA address - pSA Pointer to SA address - pMICKey pointer to MIC Key - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID RTMPInitMICEngine( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKey, - IN PUCHAR pDA, - IN PUCHAR pSA, - IN UCHAR UserPriority, - IN PUCHAR pMICKey) -{ - ULONG Priority = UserPriority; - - // Init MIC value calculation - RTMPTkipSetMICKey(&pAd->PrivateInfo.Tx, pMICKey); - // DA - RTMPTkipAppend(&pAd->PrivateInfo.Tx, pDA, MAC_ADDR_LEN); - // SA - RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSA, MAC_ADDR_LEN); - // Priority + 3 bytes of 0 - RTMPTkipAppend(&pAd->PrivateInfo.Tx, (PUCHAR)&Priority, 4); -} - -/* - ======================================================================== - - Routine Description: - Compare MIC value of received MSDU - - Arguments: - pAd Pointer to our adapter - pSrc Pointer to the received Plain text data - pDA Pointer to DA address - pSA Pointer to SA address - pMICKey pointer to MIC Key - Len the length of the received plain text data exclude MIC value - - Return Value: - TRUE MIC value matched - FALSE MIC value mismatched - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -BOOLEAN RTMPTkipCompareMICValue( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pSrc, - IN PUCHAR pDA, - IN PUCHAR pSA, - IN PUCHAR pMICKey, - IN UCHAR UserPriority, - IN UINT Len) -{ - UCHAR OldMic[8]; - ULONG Priority = UserPriority; - - // Init MIC value calculation - RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey); - // DA - RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN); - // SA - RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN); - // Priority + 3 bytes of 0 - RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4); - - // Calculate MIC value from plain text data - RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len); - - // Get MIC valude from received frame - NdisMoveMemory(OldMic, pSrc + Len, 8); - - // Get MIC value from decrypted plain data - RTMPTkipGetMIC(&pAd->PrivateInfo.Rx); - - // Move MIC value from MSDU, this steps should move to data path. - // Since the MIC value might cross MPDUs. - if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8)) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValue(): TKIP MIC Error !\n")); //MIC error. - - - return (FALSE); - } - return (TRUE); -} - -/* - ======================================================================== - - Routine Description: - Compare MIC value of received MSDU - - Arguments: - pAd Pointer to our adapter - pLLC LLC header - pSrc Pointer to the received Plain text data - pDA Pointer to DA address - pSA Pointer to SA address - pMICKey pointer to MIC Key - Len the length of the received plain text data exclude MIC value - - Return Value: - TRUE MIC value matched - FALSE MIC value mismatched - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -BOOLEAN RTMPTkipCompareMICValueWithLLC( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pLLC, - IN PUCHAR pSrc, - IN PUCHAR pDA, - IN PUCHAR pSA, - IN PUCHAR pMICKey, - IN UINT Len) -{ - UCHAR OldMic[8]; - ULONG Priority = 0; - - // Init MIC value calculation - RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey); - // DA - RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN); - // SA - RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN); - // Priority + 3 bytes of 0 - RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4); - - // Start with LLC header - RTMPTkipAppend(&pAd->PrivateInfo.Rx, pLLC, 8); - - // Calculate MIC value from plain text data - RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len); - - // Get MIC valude from received frame - NdisMoveMemory(OldMic, pSrc + Len, 8); - - // Get MIC value from decrypted plain data - RTMPTkipGetMIC(&pAd->PrivateInfo.Rx); - - // Move MIC value from MSDU, this steps should move to data path. - // Since the MIC value might cross MPDUs. - if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8)) - { - DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValueWithLLC(): TKIP MIC Error !\n")); //MIC error. - - - return (FALSE); - } - return (TRUE); -} -/* - ======================================================================== - - Routine Description: - Copy frame from waiting queue into relative ring buffer and set - appropriate ASIC register to kick hardware transmit function - - Arguments: - pAd Pointer to our adapter - PNDIS_PACKET Pointer to Ndis Packet for MIC calculation - pEncap Pointer to LLC encap data - LenEncap Total encap length, might be 0 which indicates no encap - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPCalculateMICValue( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN PUCHAR pEncap, - IN PCIPHER_KEY pKey, - IN UCHAR apidx) -{ - PACKET_INFO PacketInfo; - PUCHAR pSrcBufVA; - UINT SrcBufLen; - PUCHAR pSrc; - UCHAR UserPriority; - UCHAR vlan_offset = 0; - - RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); - - UserPriority = RTMP_GET_PACKET_UP(pPacket); - pSrc = pSrcBufVA; - - // determine if this is a vlan packet - if (((*(pSrc + 12) << 8) + *(pSrc + 13)) == 0x8100) - vlan_offset = 4; - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - { - RTMPInitMICEngine( - pAd, - pKey->Key, - pSrc, - pSrc + 6, - UserPriority, - pKey->TxMic); - } - - - if (pEncap != NULL) - { - // LLC encapsulation - RTMPTkipAppend(&pAd->PrivateInfo.Tx, pEncap, 6); - // Protocol Type - RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc + 12 + vlan_offset, 2); - } - SrcBufLen -= (14 + vlan_offset); - pSrc += (14 + vlan_offset); - do - { - if (SrcBufLen > 0) - { - RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc, SrcBufLen); - } - - break; // No need handle next packet - - } while (TRUE); // End of copying payload - - // Compute the final MIC Value - RTMPTkipGetMIC(&pAd->PrivateInfo.Tx); -} - - -/************************************************************/ -/* tkip_sbox() */ -/* Returns a 16 bit value from a 64K entry table. The Table */ -/* is synthesized from two 256 entry byte wide tables. */ -/************************************************************/ - -UINT tkip_sbox(UINT index) -{ - UINT index_low; - UINT index_high; - UINT left, right; - - index_low = (index % 256); - index_high = ((index >> 8) % 256); - - left = Tkip_Sbox_Lower[index_low] + (Tkip_Sbox_Upper[index_low] * 256); - right = Tkip_Sbox_Upper[index_high] + (Tkip_Sbox_Lower[index_high] * 256); - - return (left ^ right); -} - -UINT rotr1(UINT a) -{ - unsigned int b; - - if ((a & 0x01) == 0x01) - { - b = (a >> 1) | 0x8000; - } - else - { - b = (a >> 1) & 0x7fff; - } - b = b % 65536; - return b; -} - -VOID RTMPTkipMixKey( - UCHAR *key, - UCHAR *ta, - ULONG pnl, /* Least significant 16 bits of PN */ - ULONG pnh, /* Most significant 32 bits of PN */ - UCHAR *rc4key, - UINT *p1k) -{ - - UINT tsc0; - UINT tsc1; - UINT tsc2; - - UINT ppk0; - UINT ppk1; - UINT ppk2; - UINT ppk3; - UINT ppk4; - UINT ppk5; - - INT i; - INT j; - - tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ - tsc1 = (unsigned int)(pnh % 65536); - tsc2 = (unsigned int)(pnl % 65536); /* lsb */ - - /* Phase 1, step 1 */ - p1k[0] = tsc1; - p1k[1] = tsc0; - p1k[2] = (UINT)(ta[0] + (ta[1]*256)); - p1k[3] = (UINT)(ta[2] + (ta[3]*256)); - p1k[4] = (UINT)(ta[4] + (ta[5]*256)); - - /* Phase 1, step 2 */ - for (i=0; i<8; i++) - { - j = 2*(i & 1); - p1k[0] = (p1k[0] + tkip_sbox( (p1k[4] ^ ((256*key[1+j]) + key[j])) % 65536 )) % 65536; - p1k[1] = (p1k[1] + tkip_sbox( (p1k[0] ^ ((256*key[5+j]) + key[4+j])) % 65536 )) % 65536; - p1k[2] = (p1k[2] + tkip_sbox( (p1k[1] ^ ((256*key[9+j]) + key[8+j])) % 65536 )) % 65536; - p1k[3] = (p1k[3] + tkip_sbox( (p1k[2] ^ ((256*key[13+j]) + key[12+j])) % 65536 )) % 65536; - p1k[4] = (p1k[4] + tkip_sbox( (p1k[3] ^ (((256*key[1+j]) + key[j]))) % 65536 )) % 65536; - p1k[4] = (p1k[4] + i) % 65536; - } - - /* Phase 2, Step 1 */ - ppk0 = p1k[0]; - ppk1 = p1k[1]; - ppk2 = p1k[2]; - ppk3 = p1k[3]; - ppk4 = p1k[4]; - ppk5 = (p1k[4] + tsc2) % 65536; - - /* Phase2, Step 2 */ - ppk0 = ppk0 + tkip_sbox( (ppk5 ^ ((256*key[1]) + key[0])) % 65536); - ppk1 = ppk1 + tkip_sbox( (ppk0 ^ ((256*key[3]) + key[2])) % 65536); - ppk2 = ppk2 + tkip_sbox( (ppk1 ^ ((256*key[5]) + key[4])) % 65536); - ppk3 = ppk3 + tkip_sbox( (ppk2 ^ ((256*key[7]) + key[6])) % 65536); - ppk4 = ppk4 + tkip_sbox( (ppk3 ^ ((256*key[9]) + key[8])) % 65536); - ppk5 = ppk5 + tkip_sbox( (ppk4 ^ ((256*key[11]) + key[10])) % 65536); - - ppk0 = ppk0 + rotr1(ppk5 ^ ((256*key[13]) + key[12])); - ppk1 = ppk1 + rotr1(ppk0 ^ ((256*key[15]) + key[14])); - ppk2 = ppk2 + rotr1(ppk1); - ppk3 = ppk3 + rotr1(ppk2); - ppk4 = ppk4 + rotr1(ppk3); - ppk5 = ppk5 + rotr1(ppk4); - - /* Phase 2, Step 3 */ - /* Phase 2, Step 3 */ - - tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ - tsc1 = (unsigned int)(pnh % 65536); - tsc2 = (unsigned int)(pnl % 65536); /* lsb */ - - rc4key[0] = (tsc2 >> 8) % 256; - rc4key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f; - rc4key[2] = tsc2 % 256; - rc4key[3] = ((ppk5 ^ ((256*key[1]) + key[0])) >> 1) % 256; - - rc4key[4] = ppk0 % 256; - rc4key[5] = (ppk0 >> 8) % 256; - - rc4key[6] = ppk1 % 256; - rc4key[7] = (ppk1 >> 8) % 256; - - rc4key[8] = ppk2 % 256; - rc4key[9] = (ppk2 >> 8) % 256; - - rc4key[10] = ppk3 % 256; - rc4key[11] = (ppk3 >> 8) % 256; - - rc4key[12] = ppk4 % 256; - rc4key[13] = (ppk4 >> 8) % 256; - - rc4key[14] = ppk5 % 256; - rc4key[15] = (ppk5 >> 8) % 256; -} - - -// -// TRUE: Success! -// FALSE: Decrypt Error! -// -BOOLEAN RTMPSoftDecryptTKIP( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG DataByteCnt, - IN UCHAR UserPriority, - IN PCIPHER_KEY pWpaKey) -{ - UCHAR KeyID; - UINT HeaderLen; - UCHAR fc0; - UCHAR fc1; - USHORT fc; - UINT frame_type; - UINT frame_subtype; - UINT from_ds; - UINT to_ds; - INT a4_exists; - INT qc_exists; - USHORT duration; - USHORT seq_control; - USHORT qos_control; - UCHAR TA[MAC_ADDR_LEN]; - UCHAR DA[MAC_ADDR_LEN]; - UCHAR SA[MAC_ADDR_LEN]; - UCHAR RC4Key[16]; - UINT p1k[5]; //for mix_key; - ULONG pnl;/* Least significant 16 bits of PN */ - ULONG pnh;/* Most significant 32 bits of PN */ - UINT num_blocks; - UINT payload_remainder; - ARCFOURCONTEXT ArcFourContext; - UINT crc32 = 0; - UINT trailfcs = 0; - UCHAR MIC[8]; - UCHAR TrailMIC[8]; - -#ifdef RT_BIG_ENDIAN - RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE); -#endif - - fc0 = *pData; - fc1 = *(pData + 1); - - fc = *((PUSHORT)pData); - - frame_type = ((fc0 >> 2) & 0x03); - frame_subtype = ((fc0 >> 4) & 0x0f); - - from_ds = (fc1 & 0x2) >> 1; - to_ds = (fc1 & 0x1); - - a4_exists = (from_ds & to_ds); - qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */ - (frame_subtype == 0x09) || /* Likely to change. */ - (frame_subtype == 0x0a) || - (frame_subtype == 0x0b) - ); - - HeaderLen = 24; - if (a4_exists) - HeaderLen += 6; - - KeyID = *((PUCHAR)(pData+ HeaderLen + 3)); - KeyID = KeyID >> 6; - - if (pWpaKey[KeyID].KeyLen == 0) - { - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptTKIP failed!(KeyID[%d] Length can not be 0)\n", KeyID)); - return FALSE; - } - - duration = *((PUSHORT)(pData+2)); - - seq_control = *((PUSHORT)(pData+22)); - - if (qc_exists) - { - if (a4_exists) - { - qos_control = *((PUSHORT)(pData+30)); - } - else - { - qos_control = *((PUSHORT)(pData+24)); - } - } - - if (to_ds == 0 && from_ds == 1) - { - NdisMoveMemory(DA, pData+4, MAC_ADDR_LEN); - NdisMoveMemory(SA, pData+16, MAC_ADDR_LEN); - NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); //BSSID - } - else if (to_ds == 0 && from_ds == 0 ) - { - NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); - NdisMoveMemory(DA, pData+4, MAC_ADDR_LEN); - NdisMoveMemory(SA, pData+10, MAC_ADDR_LEN); - } - else if (to_ds == 1 && from_ds == 0) - { - NdisMoveMemory(SA, pData+10, MAC_ADDR_LEN); - NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); - NdisMoveMemory(DA, pData+16, MAC_ADDR_LEN); - } - else if (to_ds == 1 && from_ds == 1) - { - NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); - NdisMoveMemory(DA, pData+16, MAC_ADDR_LEN); - NdisMoveMemory(SA, pData+22, MAC_ADDR_LEN); - } - - num_blocks = (DataByteCnt - 16) / 16; - payload_remainder = (DataByteCnt - 16) % 16; - - pnl = (*(pData + HeaderLen)) * 256 + *(pData + HeaderLen + 2); - pnh = *((PULONG)(pData + HeaderLen + 4)); - pnh = cpu2le32(pnh); - RTMPTkipMixKey(pWpaKey[KeyID].Key, TA, pnl, pnh, RC4Key, p1k); - - ARCFOUR_INIT(&ArcFourContext, RC4Key, 16); - - ARCFOUR_DECRYPT(&ArcFourContext, pData + HeaderLen, pData + HeaderLen + 8, DataByteCnt - HeaderLen - 8); - NdisMoveMemory(&trailfcs, pData + DataByteCnt - 8 - 4, 4); - crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pData + HeaderLen, DataByteCnt - HeaderLen - 8 - 4); //Skip IV+EIV 8 bytes & Skip last 4 bytes(FCS). - crc32 ^= 0xffffffff; /* complement */ - - if(crc32 != cpu2le32(trailfcs)) - { - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptTKIP, WEP Data ICV Error !\n")); //ICV error. - - return (FALSE); - } - - NdisMoveMemory(TrailMIC, pData + DataByteCnt - 8 - 8 - 4, 8); - RTMPInitMICEngine(pAd, pWpaKey[KeyID].Key, DA, SA, UserPriority, pWpaKey[KeyID].RxMic); - RTMPTkipAppend(&pAd->PrivateInfo.Tx, pData + HeaderLen, DataByteCnt - HeaderLen - 8 - 12); - RTMPTkipGetMIC(&pAd->PrivateInfo.Tx); - NdisMoveMemory(MIC, pAd->PrivateInfo.Tx.MIC, 8); - - if (!NdisEqualMemory(MIC, TrailMIC, 8)) - { - DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptTKIP, WEP Data MIC Error !\n")); //MIC error. - //RTMPReportMicError(pAd, &pWpaKey[KeyID]); // marked by AlbertY @ 20060630 - return (FALSE); - } - -#ifdef RT_BIG_ENDIAN - RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE); -#endif - //DBGPRINT(RT_DEBUG_TRACE, "RTMPSoftDecryptTKIP Decript done!!\n"); - return TRUE; -} diff --git a/drivers/staging/rt3090/common/cmm_wpa.c b/drivers/staging/rt3090/common/cmm_wpa.c deleted file mode 100644 index bf68ad8747ac7bb7a0039b74a3bcd167900baa22..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/cmm_wpa.c +++ /dev/null @@ -1,3149 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - wpa.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Jan Lee 03-07-22 Initial - Paul Lin 03-11-28 Modify for supplicant -*/ - -#include "../rt_config.h" - - -// WPA OUI -UCHAR OUI_WPA_NONE_AKM[4] = {0x00, 0x50, 0xF2, 0x00}; -UCHAR OUI_WPA_VERSION[4] = {0x00, 0x50, 0xF2, 0x01}; -UCHAR OUI_WPA_WEP40[4] = {0x00, 0x50, 0xF2, 0x01}; -UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02}; -UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04}; -UCHAR OUI_WPA_WEP104[4] = {0x00, 0x50, 0xF2, 0x05}; -UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01}; -UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02}; -// WPA2 OUI -UCHAR OUI_WPA2_WEP40[4] = {0x00, 0x0F, 0xAC, 0x01}; -UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02}; -UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04}; -UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01}; -UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02}; -UCHAR OUI_WPA2_WEP104[4] = {0x00, 0x0F, 0xAC, 0x05}; - - - -static VOID ConstructEapolKeyData( - IN PMAC_TABLE_ENTRY pEntry, - IN UCHAR GroupKeyWepStatus, - IN UCHAR keyDescVer, - IN UCHAR MsgType, - IN UCHAR DefaultKeyIdx, - IN UCHAR *GTK, - IN UCHAR *RSNIE, - IN UCHAR RSNIE_LEN, - OUT PEAPOL_PACKET pMsg); - -static VOID CalculateMIC( - IN UCHAR KeyDescVer, - IN UCHAR *PTK, - OUT PEAPOL_PACKET pMsg); - -static VOID WpaEAPPacketAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -static VOID WpaEAPOLASFAlertAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -static VOID WpaEAPOLLogoffAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -static VOID WpaEAPOLStartAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -static VOID WpaEAPOLKeyAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -/* - ========================================================================== - Description: - association state machine init, including state transition and timer init - Parameters: - S - pointer to the association state machine - ========================================================================== - */ -VOID WpaStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]) -{ - StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_WPA_PTK_STATE, MAX_WPA_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PTK, WPA_MACHINE_BASE); - - StateMachineSetAction(S, WPA_PTK, MT2_EAPPacket, (STATE_MACHINE_FUNC)WpaEAPPacketAction); - StateMachineSetAction(S, WPA_PTK, MT2_EAPOLStart, (STATE_MACHINE_FUNC)WpaEAPOLStartAction); - StateMachineSetAction(S, WPA_PTK, MT2_EAPOLLogoff, (STATE_MACHINE_FUNC)WpaEAPOLLogoffAction); - StateMachineSetAction(S, WPA_PTK, MT2_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction); - StateMachineSetAction(S, WPA_PTK, MT2_EAPOLASFAlert, (STATE_MACHINE_FUNC)WpaEAPOLASFAlertAction); -} - -/* - ========================================================================== - Description: - this is state machine function. - When receiving EAP packets which is for 802.1x authentication use. - Not use in PSK case - Return: - ========================================================================== -*/ -VOID WpaEAPPacketAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ -} - -VOID WpaEAPOLASFAlertAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ -} - -VOID WpaEAPOLLogoffAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ -} - -/* - ========================================================================== - Description: - Start 4-way HS when rcv EAPOL_START which may create by our driver in assoc.c - Return: - ========================================================================== -*/ -VOID WpaEAPOLStartAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - MAC_TABLE_ENTRY *pEntry; - PHEADER_802_11 pHeader; - - DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLStartAction ===> \n")); - - pHeader = (PHEADER_802_11)Elem->Msg; - - //For normaol PSK, we enqueue an EAPOL-Start command to trigger the process. - if (Elem->MsgLen == 6) - pEntry = MacTableLookup(pAd, Elem->Msg); - else - { - pEntry = MacTableLookup(pAd, pHeader->Addr2); - } - - if (pEntry) - { - DBGPRINT(RT_DEBUG_TRACE, (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n", pEntry->PortSecured, pEntry->WpaState, pEntry->AuthMode, pEntry->PMKID_CacheIdx)); - - if ((pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED) - && (pEntry->WpaState < AS_PTKSTART) - && ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) || ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND)))) - { - pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; - pEntry->WpaState = AS_INITPSK; - pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; - NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter)); - pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; - - WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV); - } - } -} - -/* - ========================================================================== - Description: - This is state machine function. - When receiving EAPOL packets which is for 802.1x key management. - Use both in WPA, and WPAPSK case. - In this function, further dispatch to different functions according to the received packet. 3 categories are : - 1. normal 4-way pairwisekey and 2-way groupkey handshake - 2. MIC error (Countermeasures attack) report packet from STA. - 3. Request for pairwise/group key update from STA - Return: - ========================================================================== -*/ -VOID WpaEAPOLKeyAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - MAC_TABLE_ENTRY *pEntry; - PHEADER_802_11 pHeader; - PEAPOL_PACKET pEapol_packet; - KEY_INFO peerKeyInfo; - - DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLKeyAction ===>\n")); - - pHeader = (PHEADER_802_11)Elem->Msg; - pEapol_packet = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; - - NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); - NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pEapol_packet->KeyDesc.KeyInfo, sizeof(KEY_INFO)); - - hex_dump("Received Eapol frame", (unsigned char *)pEapol_packet, (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H)); - - *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo)); - - do - { - pEntry = MacTableLookup(pAd, pHeader->Addr2); - - if (!pEntry || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) - break; - - if (pEntry->AuthMode < Ndis802_11AuthModeWPA) - break; - - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPoL-Key frame from STA %02X-%02X-%02X-%02X-%02X-%02X\n", PRINT_MAC(pEntry->Addr))); - - if (((pEapol_packet->ProVer != EAPOL_VER) && (pEapol_packet->ProVer != EAPOL_VER2)) || - ((pEapol_packet->KeyDesc.Type != WPA1_KEY_DESC) && (pEapol_packet->KeyDesc.Type != WPA2_KEY_DESC))) - { - DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n")); - break; - } - - // The value 1 shall be used for all EAPOL-Key frames to and from a STA when - // neither the group nor pairwise ciphers are CCMP for Key Descriptor 1. - if ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) && (peerKeyInfo.KeyDescVer != DESC_TYPE_TKIP)) - { - DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(TKIP) \n")); - break; - } - // The value 2 shall be used for all EAPOL-Key frames to and from a STA when - // either the pairwise or the group cipher is AES-CCMP for Key Descriptor 2. - else if ((pEntry->WepStatus == Ndis802_11Encryption3Enabled) && (peerKeyInfo.KeyDescVer != DESC_TYPE_AES)) - { - DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(AES) \n")); - break; - } - - // Check if this STA is in class 3 state and the WPA state is started - if ((pEntry->Sst == SST_ASSOC) && (pEntry->WpaState >= AS_INITPSK)) - { - // Check the Key Ack (bit 7) of the Key Information to determine the Authenticator - // or not. - // An EAPOL-Key frame that is sent by the Supplicant in response to an EAPOL- - // Key frame from the Authenticator must not have the Ack bit set. - if (peerKeyInfo.KeyAck == 1) - { - // The frame is snet by Authenticator. - // So the Supplicant side shall handle this. - - if ((peerKeyInfo.Secure == 0) && (peerKeyInfo.Request == 0) && - (peerKeyInfo.Error == 0) && (peerKeyInfo.KeyType == PAIRWISEKEY)) - { - // Process 1. the message 1 of 4-way HS in WPA or WPA2 - // EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) - // 2. the message 3 of 4-way HS in WPA - // EAPOL-Key(0,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) - if (peerKeyInfo.KeyMic == 0) - PeerPairMsg1Action(pAd, pEntry, Elem); - else - PeerPairMsg3Action(pAd, pEntry, Elem); - } - else if ((peerKeyInfo.Secure == 1) && - (peerKeyInfo.KeyMic == 1) && - (peerKeyInfo.Request == 0) && - (peerKeyInfo.Error == 0)) - { - // Process 1. the message 3 of 4-way HS in WPA2 - // EAPOL-Key(1,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) - // 2. the message 1 of group KS in WPA or WPA2 - // EAPOL-Key(1,1,1,0,G,0,Key RSC,0, MIC,GTK[N]) - if (peerKeyInfo.KeyType == PAIRWISEKEY) - PeerPairMsg3Action(pAd, pEntry, Elem); - else - PeerGroupMsg1Action(pAd, pEntry, Elem); - } - } - else - { - // The frame is snet by Supplicant. - // So the Authenticator side shall handle this. - if ((peerKeyInfo.Request == 0) && - (peerKeyInfo.Error == 0) && - (peerKeyInfo.KeyMic == 1)) - { - if (peerKeyInfo.Secure == 0 && peerKeyInfo.KeyType == PAIRWISEKEY) - { - // EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,Data) - // Process 1. message 2 of 4-way HS in WPA or WPA2 - // 2. message 4 of 4-way HS in WPA - if (CONV_ARRARY_TO_UINT16(pEapol_packet->KeyDesc.KeyDataLen) == 0) - { - PeerPairMsg4Action(pAd, pEntry, Elem); - } - else - { - PeerPairMsg2Action(pAd, pEntry, Elem); - } - } - else if (peerKeyInfo.Secure == 1 && peerKeyInfo.KeyType == PAIRWISEKEY) - { - // EAPOL-Key(1,1,0,0,P,0,0,0,MIC,0) - // Process message 4 of 4-way HS in WPA2 - PeerPairMsg4Action(pAd, pEntry, Elem); - } - else if (peerKeyInfo.Secure == 1 && peerKeyInfo.KeyType == GROUPKEY) - { - // EAPOL-Key(1,1,0,0,G,0,0,0,MIC,0) - // Process message 2 of Group key HS in WPA or WPA2 - PeerGroupMsg2Action(pAd, pEntry, &Elem->Msg[LENGTH_802_11], (Elem->MsgLen - LENGTH_802_11)); - } - } - } - } - }while(FALSE); -} - -/* - ======================================================================== - - Routine Description: - Copy frame from waiting queue into relative ring buffer and set - appropriate ASIC register to kick hardware encryption before really - sent out to air. - - Arguments: - pAd Pointer to our adapter - PNDIS_PACKET Pointer to outgoing Ndis frame - NumberOfFrag Number of fragment required - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID RTMPToWirelessSta( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PUCHAR pHeader802_3, - IN UINT HdrLen, - IN PUCHAR pData, - IN UINT DataLen, - IN BOOLEAN bClearFrame) -{ - PNDIS_PACKET pPacket; - NDIS_STATUS Status; - - if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) - return; - - do { - // build a NDIS packet - Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen); - if (Status != NDIS_STATUS_SUCCESS) - break; - - - if (bClearFrame) - RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1); - else - RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0); - { - RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); - - RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID); // set a default value - if(pEntry->apidx != 0) - RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, pEntry->apidx); - - RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid); - RTMP_SET_PACKET_MOREDATA(pPacket, FALSE); - } - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // send out the packet - Status = STASendPacket(pAd, pPacket); - if (Status == NDIS_STATUS_SUCCESS) - { - UCHAR Index; - - // Dequeue one frame from TxSwQueue0..3 queue and process it - // There are three place calling dequeue for TX ring. - // 1. Here, right after queueing the frame. - // 2. At the end of TxRingTxDone service routine. - // 3. Upon NDIS call RTMPSendPackets - if((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) - { - for(Index = 0; Index < 5; Index ++) - if(pAd->TxSwQueue[Index].Number > 0) - RTMPDeQueuePacket(pAd, FALSE, Index, MAX_TX_PROCESS); - } - } - } -#endif // CONFIG_STA_SUPPORT // - - } while (FALSE); -} - -/* - ========================================================================== - Description: - This is a function to initilize 4-way handshake - - Return: - - ========================================================================== -*/ -VOID WPAStart4WayHS( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN ULONG TimeInterval) -{ - UCHAR Header802_3[14]; - EAPOL_PACKET EAPOLPKT; - PUINT8 pBssid = NULL; - UCHAR group_cipher = Ndis802_11WEPDisabled; - - DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n")); - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS)) - { - DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The interface is closed...\n")); - return; - } - - - if (pBssid == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n")); - return; - } - - // Check the status - if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK)) - { - DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : Not expect calling\n")); - return; - } - - - // Increment replay counter by 1 - ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); - - // Randomly generate ANonce - GenRandom(pAd, (UCHAR *)pBssid, pEntry->ANonce); - - // Construct EAPoL message - Pairwise Msg 1 - // EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) - NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET)); - ConstructEapolMsg(pEntry, - group_cipher, - EAPOL_PAIR_MSG_1, - 0, // Default key index - pEntry->ANonce, - NULL, // TxRSC - NULL, // GTK - NULL, // RSNIE - 0, // RSNIE length - &EAPOLPKT); - - - // Make outgoing frame - MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); - RTMPToWirelessSta(pAd, pEntry, Header802_3, - LENGTH_802_3, (PUCHAR)&EAPOLPKT, - CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, - (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); - - // Trigger Retry Timer - RTMPModTimer(&pEntry->RetryTimer, TimeInterval); - - // Update State - pEntry->WpaState = AS_PTKSTART; - - DBGPRINT(RT_DEBUG_TRACE, ("<=== WPAStart4WayHS: send Msg1 of 4-way \n")); - -} - -/* - ======================================================================== - - Routine Description: - Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2 - - Arguments: - pAd Pointer to our adapter - Elem Message body - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID PeerPairMsg1Action( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR PTK[80]; - UCHAR Header802_3[14]; - PEAPOL_PACKET pMsg1; - UINT MsgLen; - EAPOL_PACKET EAPOLPKT; - PUINT8 pCurrentAddr = NULL; - PUINT8 pmk_ptr = NULL; - UCHAR group_cipher = Ndis802_11WEPDisabled; - PUINT8 rsnie_ptr = NULL; - UCHAR rsnie_len = 0; - - DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n")); - - if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) - return; - - if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2)) - return; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - pCurrentAddr = pAd->CurrentAddress; - pmk_ptr = pAd->StaCfg.PMK; - group_cipher = pAd->StaCfg.GroupCipher; - rsnie_ptr = pAd->StaCfg.RSN_IE; - rsnie_len = pAd->StaCfg.RSNIE_Len; - } -#endif // CONFIG_STA_SUPPORT // - - // Store the received frame - pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; - MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; - - // Sanity Check peer Pairwise message 1 - Replay Counter - if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry) == FALSE) - return; - - // Store Replay counter, it will use to verify message 3 and construct message 2 - NdisMoveMemory(pEntry->R_Counter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - - // Store ANonce - NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); - - // Generate random SNonce - GenRandom(pAd, (UCHAR *)pCurrentAddr, pEntry->SNonce); - - { - // Calculate PTK(ANonce, SNonce) - WpaDerivePTK(pAd, - pmk_ptr, - pEntry->ANonce, - pEntry->Addr, - pEntry->SNonce, - pCurrentAddr, - PTK, - LEN_PTK); - - // Save key to PTK entry - NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK); - } - - // Update WpaState - pEntry->WpaState = AS_PTKINIT_NEGOTIATING; - - // Construct EAPoL message - Pairwise Msg 2 - // EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2) - NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET)); - ConstructEapolMsg(pEntry, - group_cipher, - EAPOL_PAIR_MSG_2, - 0, // DefaultKeyIdx - pEntry->SNonce, - NULL, // TxRsc - NULL, // GTK - (UCHAR *)rsnie_ptr, - rsnie_len, - &EAPOLPKT); - - // Make outgoing frame - MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); - - RTMPToWirelessSta(pAd, pEntry, - Header802_3, sizeof(Header802_3), (PUCHAR)&EAPOLPKT, - CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, TRUE); - - DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n")); -} - - -/* - ========================================================================== - Description: - When receiving the second packet of 4-way pairwisekey handshake. - Return: - ========================================================================== -*/ -VOID PeerPairMsg2Action( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR PTK[80]; - BOOLEAN Cancelled; - PHEADER_802_11 pHeader; - EAPOL_PACKET EAPOLPKT; - PEAPOL_PACKET pMsg2; - UINT MsgLen; - UCHAR Header802_3[LENGTH_802_3]; - UCHAR TxTsc[6]; - PUINT8 pBssid = NULL; - PUINT8 pmk_ptr = NULL; - PUINT8 gtk_ptr = NULL; - UCHAR default_key = 0; - UCHAR group_cipher = Ndis802_11WEPDisabled; - PUINT8 rsnie_ptr = NULL; - UCHAR rsnie_len = 0; - - DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n")); - - if ((!pEntry) || (!pEntry->ValidAsCLI)) - return; - - if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2)) - return; - - // check Entry in valid State - if (pEntry->WpaState < AS_PTKSTART) - return; - - - - // pointer to 802.11 header - pHeader = (PHEADER_802_11)Elem->Msg; - - // skip 802.11_header(24-byte) and LLC_header(8) - pMsg2 = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; - MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; - - // Store SNonce - NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); - - { - // Derive PTK - WpaDerivePTK(pAd, - (UCHAR *)pmk_ptr, - pEntry->ANonce, // ANONCE - (UCHAR *)pBssid, - pEntry->SNonce, // SNONCE - pEntry->Addr, - PTK, - LEN_PTK); - - NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK); - } - - // Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE - if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry) == FALSE) - return; - - do - { - // delete retry timer - RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); - - // Change state - pEntry->WpaState = AS_PTKINIT_NEGOTIATING; - - // Increment replay counter by 1 - ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); - - // Construct EAPoL message - Pairwise Msg 3 - NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET)); - ConstructEapolMsg(pEntry, - group_cipher, - EAPOL_PAIR_MSG_3, - default_key, - pEntry->ANonce, - TxTsc, - (UCHAR *)gtk_ptr, - (UCHAR *)rsnie_ptr, - rsnie_len, - &EAPOLPKT); - - // Make outgoing frame - MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); - RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3, - (PUCHAR)&EAPOLPKT, - CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, - (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); - - pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR; - RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV); - - // Update State - pEntry->WpaState = AS_PTKINIT_NEGOTIATING; - }while(FALSE); - - DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n")); -} - -/* - ======================================================================== - - Routine Description: - Process Pairwise key Msg 3 of 4-way handshaking and send Msg 4 - - Arguments: - pAd Pointer to our adapter - Elem Message body - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID PeerPairMsg3Action( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN MLME_QUEUE_ELEM *Elem) -{ - PHEADER_802_11 pHeader; - UCHAR Header802_3[14]; - EAPOL_PACKET EAPOLPKT; - PEAPOL_PACKET pMsg3; - UINT MsgLen; - PUINT8 pCurrentAddr = NULL; - UCHAR group_cipher = Ndis802_11WEPDisabled; - - DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n")); - - if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) - return; - - if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2)) - return; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - pCurrentAddr = pAd->CurrentAddress; - group_cipher = pAd->StaCfg.GroupCipher; - - } -#endif // CONFIG_STA_SUPPORT // - - // Record 802.11 header & the received EAPOL packet Msg3 - pHeader = (PHEADER_802_11) Elem->Msg; - pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; - MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; - - // Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE - if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry) == FALSE) - return; - - // Save Replay counter, it will use construct message 4 - NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - - // Double check ANonce - if (!NdisEqualMemory(pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) - { - return; - } - - // Construct EAPoL message - Pairwise Msg 4 - NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET)); - ConstructEapolMsg(pEntry, - group_cipher, - EAPOL_PAIR_MSG_4, - 0, // group key index not used in message 4 - NULL, // Nonce not used in message 4 - NULL, // TxRSC not used in message 4 - NULL, // GTK not used in message 4 - NULL, // RSN IE not used in message 4 - 0, - &EAPOLPKT); - - // Update WpaState - pEntry->WpaState = AS_PTKINITDONE; - - // Update pairwise key -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - PCIPHER_KEY pSharedKey; - - pSharedKey = &pAd->SharedKey[BSS0][0]; - - NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK); - - // Prepare pair-wise key information into shared key table - NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY)); - pSharedKey->KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); - NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); - NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); - - // Decide its ChiperAlg - if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) - pSharedKey->CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) - pSharedKey->CipherAlg = CIPHER_AES; - else - pSharedKey->CipherAlg = CIPHER_NONE; - - // Update these related information to MAC_TABLE_ENTRY - pEntry = &pAd->MacTab.Content[BSSID_WCID]; - NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); - NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); - NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); - pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg; - - // Update pairwise key information to ASIC Shared Key Table - AsicAddSharedKeyEntry(pAd, - BSS0, - 0, - pSharedKey->CipherAlg, - pSharedKey->Key, - pSharedKey->TxMic, - pSharedKey->RxMic); - - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAd, - BSS0, - 0, - pSharedKey->CipherAlg, - pEntry); - - } -#endif // CONFIG_STA_SUPPORT // - - // open 802.1x port control and privacy filter - if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK || - pEntry->AuthMode == Ndis802_11AuthModeWPA2) - { - pEntry->PortSecured = WPA_802_1X_PORT_SECURED; - pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; - -#ifdef CONFIG_STA_SUPPORT - STA_PORT_SECURED(pAd); - // Indicate Connected for GUI - pAd->IndicateMediaState = NdisMediaStateConnected; -#endif // CONFIG_STA_SUPPORT // - DBGPRINT(RT_DEBUG_TRACE, ("PeerPairMsg3Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n", - GetAuthMode(pEntry->AuthMode), - GetEncryptType(pEntry->WepStatus), - GetEncryptType(group_cipher))); - } - else - { - } - - // Init 802.3 header and send out - MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); - RTMPToWirelessSta(pAd, pEntry, - Header802_3, sizeof(Header802_3), - (PUCHAR)&EAPOLPKT, - CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, TRUE); - - DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n")); -} - -/* - ========================================================================== - Description: - When receiving the last packet of 4-way pairwisekey handshake. - Initilize 2-way groupkey handshake following. - Return: - ========================================================================== -*/ -VOID PeerPairMsg4Action( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN MLME_QUEUE_ELEM *Elem) -{ - PEAPOL_PACKET pMsg4; - PHEADER_802_11 pHeader; - UINT MsgLen; - BOOLEAN Cancelled; - UCHAR group_cipher = Ndis802_11WEPDisabled; - - DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n")); - - do - { - if ((!pEntry) || (!pEntry->ValidAsCLI)) - break; - - if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2 ) ) - break; - - if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING) - break; - - - // pointer to 802.11 header - pHeader = (PHEADER_802_11)Elem->Msg; - - // skip 802.11_header(24-byte) and LLC_header(8) - pMsg4 = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; - MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; - - // Sanity Check peer Pairwise message 4 - Replay Counter, MIC - if (PeerWpaMessageSanity(pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE) - break; - - // 3. uses the MLME.SETKEYS.request to configure PTK into MAC - NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY)); - - // reset IVEIV in Asic - AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, 1, 0); - - pEntry->PairwiseKey.KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[32], LEN_TKIP_EK); - NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pEntry->PTK[TKIP_AP_RXMICK_OFFSET], LEN_TKIP_RXMICK); - NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pEntry->PTK[TKIP_AP_TXMICK_OFFSET], LEN_TKIP_TXMICK); - - // Set pairwise key to Asic - { - pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; - if (pEntry->WepStatus == Ndis802_11Encryption2Enabled) - pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP; - else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled) - pEntry->PairwiseKey.CipherAlg = CIPHER_AES; - - // Add Pair-wise key to Asic - AsicAddPairwiseKeyEntry( - pAd, - pEntry->Addr, - (UCHAR)pEntry->Aid, - &pEntry->PairwiseKey); - - // update WCID attribute table and IVEIV table for this entry - RTMPAddWcidAttributeEntry( - pAd, - pEntry->apidx, - 0, - pEntry->PairwiseKey.CipherAlg, - pEntry); - } - - // 4. upgrade state - pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; - pEntry->WpaState = AS_PTKINITDONE; - pEntry->PortSecured = WPA_802_1X_PORT_SECURED; - - - if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 || - pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) - { - pEntry->GTKState = REKEY_ESTABLISHED; - RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); - - - // send wireless event - for set key done WPA2 - if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); - - DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n", - pEntry->AuthMode, GetAuthMode(pEntry->AuthMode), - pEntry->WepStatus, GetEncryptType(pEntry->WepStatus), - group_cipher, - GetEncryptType(group_cipher))); - } - else - { - // 5. init Group 2-way handshake if necessary. - WPAStart2WayGroupHS(pAd, pEntry); - - pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR; - RTMPModTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV); - } - }while(FALSE); - -} - -/* - ========================================================================== - Description: - This is a function to send the first packet of 2-way groupkey handshake - Return: - - ========================================================================== -*/ -VOID WPAStart2WayGroupHS( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry) -{ - UCHAR Header802_3[14]; - UCHAR TxTsc[6]; - EAPOL_PACKET EAPOLPKT; - UCHAR group_cipher = Ndis802_11WEPDisabled; - UCHAR default_key = 0; - PUINT8 gnonce_ptr = NULL; - PUINT8 gtk_ptr = NULL; - PUINT8 pBssid = NULL; - - DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n")); - - if ((!pEntry) || (!pEntry->ValidAsCLI)) - return; - - - do - { - // Increment replay counter by 1 - ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); - - // Construct EAPoL message - Group Msg 1 - NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET)); - ConstructEapolMsg(pEntry, - group_cipher, - EAPOL_GROUP_MSG_1, - default_key, - (UCHAR *)gnonce_ptr, - TxTsc, - (UCHAR *)gtk_ptr, - NULL, - 0, - &EAPOLPKT); - - // Make outgoing frame - MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); - RTMPToWirelessSta(pAd, pEntry, - Header802_3, LENGTH_802_3, - (PUCHAR)&EAPOLPKT, - CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, FALSE); - - - - }while (FALSE); - - DBGPRINT(RT_DEBUG_TRACE, ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n")); - - return; -} - -/* - ======================================================================== - - Routine Description: - Process Group key 2-way handshaking - - Arguments: - pAd Pointer to our adapter - Elem Message body - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID PeerGroupMsg1Action( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR Header802_3[14]; - EAPOL_PACKET EAPOLPKT; - PEAPOL_PACKET pGroup; - UINT MsgLen; - BOOLEAN Cancelled; - UCHAR default_key = 0; - UCHAR group_cipher = Ndis802_11WEPDisabled; - PUINT8 pCurrentAddr = NULL; - - DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n")); - - if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) - return; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - pCurrentAddr = pAd->CurrentAddress; - group_cipher = pAd->StaCfg.GroupCipher; - default_key = pAd->StaCfg.DefaultKeyId; - } -#endif // CONFIG_STA_SUPPORT // - - // Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8) - pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; - MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; - - // Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE - if (PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pEntry) == FALSE) - return; - - // delete retry timer - RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); - - // Save Replay counter, it will use to construct message 2 - NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - - // Construct EAPoL message - Group Msg 2 - NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET)); - ConstructEapolMsg(pEntry, - group_cipher, - EAPOL_GROUP_MSG_2, - default_key, - NULL, // Nonce not used - NULL, // TxRSC not used - NULL, // GTK not used - NULL, // RSN IE not used - 0, - &EAPOLPKT); - - // open 802.1x port control and privacy filter - pEntry->PortSecured = WPA_802_1X_PORT_SECURED; - pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; - -#ifdef CONFIG_STA_SUPPORT - STA_PORT_SECURED(pAd); - // Indicate Connected for GUI - pAd->IndicateMediaState = NdisMediaStateConnected; -#endif // CONFIG_STA_SUPPORT // - - DBGPRINT(RT_DEBUG_TRACE, ("PeerGroupMsg1Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n", - GetAuthMode(pEntry->AuthMode), - GetEncryptType(pEntry->WepStatus), - GetEncryptType(group_cipher))); - - // init header and Fill Packet and send Msg 2 to authenticator - MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); - RTMPToWirelessSta(pAd, pEntry, - Header802_3, sizeof(Header802_3), - (PUCHAR)&EAPOLPKT, - CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, FALSE); - - DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerGroupMsg1Action: sned group message 2\n")); -} - -/* - ========================================================================== - Description: - When receiving the last packet of 2-way groupkey handshake. - Return: - ========================================================================== -*/ -VOID PeerGroupMsg2Action( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN VOID *Msg, - IN UINT MsgLen) -{ - UINT Len; - PUCHAR pData; - BOOLEAN Cancelled; - PEAPOL_PACKET pMsg2; - UCHAR group_cipher = Ndis802_11WEPDisabled; - - DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n")); - - do - { - if ((!pEntry) || (!pEntry->ValidAsCLI)) - break; - - if (MsgLen < (LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2)) - break; - - if (pEntry->WpaState != AS_PTKINITDONE) - break; - - - pData = (PUCHAR)Msg; - pMsg2 = (PEAPOL_PACKET) (pData + LENGTH_802_1_H); - Len = MsgLen - LENGTH_802_1_H; - - // Sanity Check peer group message 2 - Replay Counter, MIC - if (PeerWpaMessageSanity(pAd, pMsg2, Len, EAPOL_GROUP_MSG_2, pEntry) == FALSE) - break; - - // 3. upgrade state - - RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); - pEntry->GTKState = REKEY_ESTABLISHED; - - if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - // send wireless event - for set key done WPA2 - if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); - - DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n", - pEntry->AuthMode, GetAuthMode(pEntry->AuthMode), - pEntry->WepStatus, GetEncryptType(pEntry->WepStatus), - group_cipher, GetEncryptType(group_cipher))); - } - else - { - // send wireless event - for set key done WPA - if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA1_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); - - DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA1, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n", - pEntry->AuthMode, GetAuthMode(pEntry->AuthMode), - pEntry->WepStatus, GetEncryptType(pEntry->WepStatus), - group_cipher, GetEncryptType(group_cipher))); - } - }while(FALSE); -} - -/* - ======================================================================== - - Routine Description: - Classify WPA EAP message type - - Arguments: - EAPType Value of EAP message type - MsgType Internal Message definition for MLME state machine - - Return Value: - TRUE Found appropriate message type - FALSE No appropriate message type - - IRQL = DISPATCH_LEVEL - - Note: - All these constants are defined in wpa.h - For supplicant, there is only EAPOL Key message avaliable - - ======================================================================== -*/ -BOOLEAN WpaMsgTypeSubst( - IN UCHAR EAPType, - OUT INT *MsgType) -{ - switch (EAPType) - { - case EAPPacket: - *MsgType = MT2_EAPPacket; - break; - case EAPOLStart: - *MsgType = MT2_EAPOLStart; - break; - case EAPOLLogoff: - *MsgType = MT2_EAPOLLogoff; - break; - case EAPOLKey: - *MsgType = MT2_EAPOLKey; - break; - case EAPOLASFAlert: - *MsgType = MT2_EAPOLASFAlert; - break; - default: - return FALSE; - } - return TRUE; -} - -/* - ======================================================================== - - Routine Description: - The pseudo-random function(PRF) that hashes various inputs to - derive a pseudo-random value. To add liveness to the pseudo-random - value, a nonce should be one of the inputs. - - It is used to generate PTK, GTK or some specific random value. - - Arguments: - UCHAR *key, - the key material for HMAC_SHA1 use - INT key_len - the length of key - UCHAR *prefix - a prefix label - INT prefix_len - the length of the label - UCHAR *data - a specific data with variable length - INT data_len - the length of a specific data - INT len - the output lenght - - Return Value: - UCHAR *output - the calculated result - - Note: - 802.11i-2004 Annex H.3 - - ======================================================================== -*/ -VOID PRF( - IN UCHAR *key, - IN INT key_len, - IN UCHAR *prefix, - IN INT prefix_len, - IN UCHAR *data, - IN INT data_len, - OUT UCHAR *output, - IN INT len) -{ - INT i; - UCHAR *input; - INT currentindex = 0; - INT total_len; - - // Allocate memory for input - os_alloc_mem(NULL, (PUCHAR *)&input, 1024); - - if (input == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n")); - return; - } - - // Generate concatenation input - NdisMoveMemory(input, prefix, prefix_len); - - // Concatenate a single octet containing 0 - input[prefix_len] = 0; - - // Concatenate specific data - NdisMoveMemory(&input[prefix_len + 1], data, data_len); - total_len = prefix_len + 1 + data_len; - - // Concatenate a single octet containing 0 - // This octet shall be update later - input[total_len] = 0; - total_len++; - - // Iterate to calculate the result by hmac-sha-1 - // Then concatenate to last result - for (i = 0; i < (len + 19) / 20; i++) - { - HMAC_SHA1(key, key_len, input, total_len, &output[currentindex], SHA1_DIGEST_SIZE); - currentindex += 20; - - // update the last octet - input[total_len - 1]++; - } - os_free_mem(NULL, input); -} - -/* -* F(P, S, c, i) = U1 xor U2 xor ... Uc -* U1 = PRF(P, S || Int(i)) -* U2 = PRF(P, U1) -* Uc = PRF(P, Uc-1) -*/ - -static void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output) -{ - unsigned char digest[36], digest1[SHA1_DIGEST_SIZE]; - int i, j; - - /* U1 = PRF(P, S || int(i)) */ - memcpy(digest, ssid, ssidlength); - digest[ssidlength] = (unsigned char)((count>>24) & 0xff); - digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff); - digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff); - digest[ssidlength+3] = (unsigned char)(count & 0xff); - HMAC_SHA1((unsigned char*) password, (int) strlen(password), digest, ssidlength+4, digest1, SHA1_DIGEST_SIZE); // for WPA update - - /* output = U1 */ - memcpy(output, digest1, SHA1_DIGEST_SIZE); - - for (i = 1; i < iterations; i++) - { - /* Un = PRF(P, Un-1) */ - HMAC_SHA1((unsigned char*) password, (int) strlen(password), digest1, SHA1_DIGEST_SIZE, digest, SHA1_DIGEST_SIZE); // for WPA update - memcpy(digest1, digest, SHA1_DIGEST_SIZE); - - /* output = output xor Un */ - for (j = 0; j < SHA1_DIGEST_SIZE; j++) - { - output[j] ^= digest[j]; - } - } -} - -/* -* password - ascii string up to 63 characters in length -* ssid - octet string up to 32 octets -* ssidlength - length of ssid in octets -* output must be 40 octets in length and outputs 256 bits of key -*/ -int PasswordHash(PSTRING password, PUCHAR ssid, INT ssidlength, PUCHAR output) -{ - if ((strlen(password) > 63) || (ssidlength > 32)) - return 0; - - F(password, ssid, ssidlength, 4096, 1, output); - F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]); - return 1; -} - - - -/* - ======================================================================== - - Routine Description: - It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK. - It shall be called by 4-way handshake processing. - - Arguments: - pAd - pointer to our pAdapter context - PMK - pointer to PMK - ANonce - pointer to ANonce - AA - pointer to Authenticator Address - SNonce - pointer to SNonce - SA - pointer to Supplicant Address - len - indicate the length of PTK (octet) - - Return Value: - Output pointer to the PTK - - Note: - Refer to IEEE 802.11i-2004 8.5.1.2 - - ======================================================================== -*/ -VOID WpaDerivePTK( - IN PRTMP_ADAPTER pAd, - IN UCHAR *PMK, - IN UCHAR *ANonce, - IN UCHAR *AA, - IN UCHAR *SNonce, - IN UCHAR *SA, - OUT UCHAR *output, - IN UINT len) -{ - UCHAR concatenation[76]; - UINT CurrPos = 0; - UCHAR temp[32]; - UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ', - 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'}; - - // initiate the concatenation input - NdisZeroMemory(temp, sizeof(temp)); - NdisZeroMemory(concatenation, 76); - - // Get smaller address - if (RTMPCompareMemory(SA, AA, 6) == 1) - NdisMoveMemory(concatenation, AA, 6); - else - NdisMoveMemory(concatenation, SA, 6); - CurrPos += 6; - - // Get larger address - if (RTMPCompareMemory(SA, AA, 6) == 1) - NdisMoveMemory(&concatenation[CurrPos], SA, 6); - else - NdisMoveMemory(&concatenation[CurrPos], AA, 6); - - // store the larger mac address for backward compatible of - // ralink proprietary STA-key issue - NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN); - CurrPos += 6; - - // Get smaller Nonce - if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) - NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue - else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) - NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); - else - NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); - CurrPos += 32; - - // Get larger Nonce - if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) - NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue - else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) - NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); - else - NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); - CurrPos += 32; - - hex_dump("concatenation=", concatenation, 76); - - // Use PRF to generate PTK - PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len); - -} - -/* - ======================================================================== - - Routine Description: - Generate random number by software. - - Arguments: - pAd - pointer to our pAdapter context - macAddr - pointer to local MAC address - - Return Value: - - Note: - 802.1ii-2004 Annex H.5 - - ======================================================================== -*/ -VOID GenRandom( - IN PRTMP_ADAPTER pAd, - IN UCHAR *macAddr, - OUT UCHAR *random) -{ - INT i, curr; - UCHAR local[80], KeyCounter[32]; - UCHAR result[80]; - ULONG CurrentTime; - UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'}; - - // Zero the related information - NdisZeroMemory(result, 80); - NdisZeroMemory(local, 80); - NdisZeroMemory(KeyCounter, 32); - - for (i = 0; i < 32; i++) - { - // copy the local MAC address - COPY_MAC_ADDR(local, macAddr); - curr = MAC_ADDR_LEN; - - // concatenate the current time - NdisGetSystemUpTime(&CurrentTime); - NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime)); - curr += sizeof(CurrentTime); - - // concatenate the last result - NdisMoveMemory(&local[curr], result, 32); - curr += 32; - - // concatenate a variable - NdisMoveMemory(&local[curr], &i, 2); - curr += 2; - - // calculate the result - PRF(KeyCounter, 32, prefix,12, local, curr, result, 32); - } - - NdisMoveMemory(random, result, 32); -} - -/* - ======================================================================== - - Routine Description: - Build cipher suite in RSN-IE. - It only shall be called by RTMPMakeRSNIE. - - Arguments: - pAd - pointer to our pAdapter context - ElementID - indicate the WPA1 or WPA2 - WepStatus - indicate the encryption type - bMixCipher - a boolean to indicate the pairwise cipher and group - cipher are the same or not - - Return Value: - - Note: - - ======================================================================== -*/ -static VOID RTMPMakeRsnIeCipher( - IN PRTMP_ADAPTER pAd, - IN UCHAR ElementID, - IN UINT WepStatus, - IN BOOLEAN bMixCipher, - IN UCHAR FlexibleCipher, - OUT PUCHAR pRsnIe, - OUT UCHAR *rsn_len) -{ - UCHAR PairwiseCnt; - - *rsn_len = 0; - - // decide WPA2 or WPA1 - if (ElementID == Wpa2Ie) - { - RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe; - - // Assign the verson as 1 - pRsnie_cipher->version = 1; - - switch (WepStatus) - { - // TKIP mode - case Ndis802_11Encryption2Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); - pRsnie_cipher->ucount = 1; - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); - *rsn_len = sizeof(RSNIE2); - break; - - // AES mode - case Ndis802_11Encryption3Enabled: - if (bMixCipher) - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); - else - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4); - pRsnie_cipher->ucount = 1; - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); - *rsn_len = sizeof(RSNIE2); - break; - - // TKIP-AES mix mode - case Ndis802_11Encryption4Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); - - PairwiseCnt = 1; - // Insert WPA2 TKIP as the first pairwise cipher - if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) - { - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); - // Insert WPA2 AES as the secondary pairwise cipher - if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) - { - NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4); - PairwiseCnt = 2; - } - } - else - { - // Insert WPA2 AES as the first pairwise cipher - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); - } - - pRsnie_cipher->ucount = PairwiseCnt; - *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1)); - break; - } - -#ifdef CONFIG_STA_SUPPORT - if ((pAd->OpMode == OPMODE_STA) && - (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) && - (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) - { - UINT GroupCipher = pAd->StaCfg.GroupCipher; - switch(GroupCipher) - { - case Ndis802_11GroupWEP40Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP40, 4); - break; - case Ndis802_11GroupWEP104Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP104, 4); - break; - } - } -#endif // CONFIG_STA_SUPPORT // - - // swap for big-endian platform - pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); - pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); - } - else - { - RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe; - - // Assign OUI and version - NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4); - pRsnie_cipher->version = 1; - - switch (WepStatus) - { - // TKIP mode - case Ndis802_11Encryption2Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); - pRsnie_cipher->ucount = 1; - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); - *rsn_len = sizeof(RSNIE); - break; - - // AES mode - case Ndis802_11Encryption3Enabled: - if (bMixCipher) - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); - else - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4); - pRsnie_cipher->ucount = 1; - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); - *rsn_len = sizeof(RSNIE); - break; - - // TKIP-AES mix mode - case Ndis802_11Encryption4Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); - - PairwiseCnt = 1; - // Insert WPA TKIP as the first pairwise cipher - if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) - { - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); - // Insert WPA AES as the secondary pairwise cipher - if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) - { - NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4); - PairwiseCnt = 2; - } - } - else - { - // Insert WPA AES as the first pairwise cipher - NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); - } - - pRsnie_cipher->ucount = PairwiseCnt; - *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1)); - break; - } - -#ifdef CONFIG_STA_SUPPORT - if ((pAd->OpMode == OPMODE_STA) && - (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) && - (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) - { - UINT GroupCipher = pAd->StaCfg.GroupCipher; - switch(GroupCipher) - { - case Ndis802_11GroupWEP40Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP40, 4); - break; - case Ndis802_11GroupWEP104Enabled: - NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP104, 4); - break; - } - } -#endif // CONFIG_STA_SUPPORT // - - // swap for big-endian platform - pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); - pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); - } -} - -/* - ======================================================================== - - Routine Description: - Build AKM suite in RSN-IE. - It only shall be called by RTMPMakeRSNIE. - - Arguments: - pAd - pointer to our pAdapter context - ElementID - indicate the WPA1 or WPA2 - AuthMode - indicate the authentication mode - apidx - indicate the interface index - - Return Value: - - Note: - - ======================================================================== -*/ -static VOID RTMPMakeRsnIeAKM( - IN PRTMP_ADAPTER pAd, - IN UCHAR ElementID, - IN UINT AuthMode, - IN UCHAR apidx, - OUT PUCHAR pRsnIe, - OUT UCHAR *rsn_len) -{ - RSNIE_AUTH *pRsnie_auth; - UCHAR AkmCnt = 1; // default as 1 - - pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len)); - - // decide WPA2 or WPA1 - if (ElementID == Wpa2Ie) - { - - switch (AuthMode) - { - case Ndis802_11AuthModeWPA2: - case Ndis802_11AuthModeWPA1WPA2: - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4); - break; - - case Ndis802_11AuthModeWPA2PSK: - case Ndis802_11AuthModeWPA1PSKWPA2PSK: - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4); - break; - default: - AkmCnt = 0; - break; - - } - } - else - { - switch (AuthMode) - { - case Ndis802_11AuthModeWPA: - case Ndis802_11AuthModeWPA1WPA2: - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4); - break; - - case Ndis802_11AuthModeWPAPSK: - case Ndis802_11AuthModeWPA1PSKWPA2PSK: - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4); - break; - - case Ndis802_11AuthModeWPANone: - NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4); - break; - default: - AkmCnt = 0; - break; - } - } - - pRsnie_auth->acount = AkmCnt; - pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount); - - // update current RSNIE length - (*rsn_len) += (sizeof(RSNIE_AUTH) + (4 * (AkmCnt - 1))); - -} - -/* - ======================================================================== - - Routine Description: - Build capability in RSN-IE. - It only shall be called by RTMPMakeRSNIE. - - Arguments: - pAd - pointer to our pAdapter context - ElementID - indicate the WPA1 or WPA2 - apidx - indicate the interface index - - Return Value: - - Note: - - ======================================================================== -*/ -static VOID RTMPMakeRsnIeCap( - IN PRTMP_ADAPTER pAd, - IN UCHAR ElementID, - IN UCHAR apidx, - OUT PUCHAR pRsnIe, - OUT UCHAR *rsn_len) -{ - RSN_CAPABILITIES *pRSN_Cap; - - // it could be ignored in WPA1 mode - if (ElementID == WpaIe) - return; - - pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len)); - - - pRSN_Cap->word = cpu2le16(pRSN_Cap->word); - - (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length - -} - - -/* - ======================================================================== - - Routine Description: - Build RSN IE context. It is not included element-ID and length. - - Arguments: - pAd - pointer to our pAdapter context - AuthMode - indicate the authentication mode - WepStatus - indicate the encryption type - apidx - indicate the interface index - - Return Value: - - Note: - - ======================================================================== -*/ -VOID RTMPMakeRSNIE( - IN PRTMP_ADAPTER pAd, - IN UINT AuthMode, - IN UINT WepStatus, - IN UCHAR apidx) -{ - PUCHAR pRsnIe = NULL; // primary RSNIE - UCHAR *rsnielen_cur_p = 0; // the length of the primary RSNIE - UCHAR *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE - UCHAR PrimaryRsnie; - BOOLEAN bMixCipher = FALSE; // indicate the pairwise and group cipher are different - UCHAR p_offset; - WPA_MIX_PAIR_CIPHER FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES; // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode - - rsnielen_cur_p = NULL; - rsnielen_ex_cur_p = NULL; - - { -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { -#ifdef WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) - { - if (AuthMode < Ndis802_11AuthModeWPA) - return; - } - else -#endif // WPA_SUPPLICANT_SUPPORT // - { - // Support WPAPSK or WPA2PSK in STA-Infra mode - // Support WPANone in STA-Adhoc mode - if ((AuthMode != Ndis802_11AuthModeWPAPSK) && - (AuthMode != Ndis802_11AuthModeWPA2PSK) && - (AuthMode != Ndis802_11AuthModeWPANone) - ) - return; - } - - DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n")); - - // Zero RSNIE context - pAd->StaCfg.RSNIE_Len = 0; - NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE); - - // Pointer to RSNIE - rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len; - pRsnIe = pAd->StaCfg.RSN_IE; - - bMixCipher = pAd->StaCfg.bMixCipher; - } -#endif // CONFIG_STA_SUPPORT // - } - - // indicate primary RSNIE as WPA or WPA2 - if ((AuthMode == Ndis802_11AuthModeWPA) || - (AuthMode == Ndis802_11AuthModeWPAPSK) || - (AuthMode == Ndis802_11AuthModeWPANone) || - (AuthMode == Ndis802_11AuthModeWPA1WPA2) || - (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) - PrimaryRsnie = WpaIe; - else - PrimaryRsnie = Wpa2Ie; - - { - // Build the primary RSNIE - // 1. insert cipher suite - RTMPMakeRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset); - - // 2. insert AKM - RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset); - - // 3. insert capability - RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); - } - - // 4. update the RSNIE length - *rsnielen_cur_p = p_offset; - - hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p)); - - -} - -/* - ========================================================================== - Description: - Check whether the received frame is EAP frame. - - Arguments: - pAd - pointer to our pAdapter context - pEntry - pointer to active entry - pData - the received frame - DataByteCount - the received frame's length - FromWhichBSSID - indicate the interface index - - Return: - TRUE - This frame is EAP frame - FALSE - otherwise - ========================================================================== -*/ -BOOLEAN RTMPCheckWPAframe( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PUCHAR pData, - IN ULONG DataByteCount, - IN UCHAR FromWhichBSSID) -{ - ULONG Body_len; - BOOLEAN Cancelled; - - - if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H)) - return FALSE; - - - // Skip LLC header - if (NdisEqualMemory(SNAP_802_1H, pData, 6) || - // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL - NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) - { - pData += 6; - } - // Skip 2-bytes EAPoL type - if (NdisEqualMemory(EAPOL, pData, 2)) -// if (*(UINT16 *)EAPOL == *(UINT16 *)pData) - { - pData += 2; - } - else - return FALSE; - - switch (*(pData+1)) - { - case EAPPacket: - Body_len = (*(pData+2)<<8) | (*(pData+3)); - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len)); - break; - case EAPOLStart: - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n")); - if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE) - { - DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n")); - RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); - pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; - } - break; - case EAPOLLogoff: - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n")); - break; - case EAPOLKey: - Body_len = (*(pData+2)<<8) | (*(pData+3)); - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len)); - break; - case EAPOLASFAlert: - DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n")); - break; - default: - return FALSE; - - } - return TRUE; -} - -/* - ========================================================================== - Description: - Report the EAP message type - - Arguments: - msg - EAPOL_PAIR_MSG_1 - EAPOL_PAIR_MSG_2 - EAPOL_PAIR_MSG_3 - EAPOL_PAIR_MSG_4 - EAPOL_GROUP_MSG_1 - EAPOL_GROUP_MSG_2 - - Return: - message type string - - ========================================================================== -*/ -PSTRING GetEapolMsgType(CHAR msg) -{ - if(msg == EAPOL_PAIR_MSG_1) - return "Pairwise Message 1"; - else if(msg == EAPOL_PAIR_MSG_2) - return "Pairwise Message 2"; - else if(msg == EAPOL_PAIR_MSG_3) - return "Pairwise Message 3"; - else if(msg == EAPOL_PAIR_MSG_4) - return "Pairwise Message 4"; - else if(msg == EAPOL_GROUP_MSG_1) - return "Group Message 1"; - else if(msg == EAPOL_GROUP_MSG_2) - return "Group Message 2"; - else - return "Invalid Message"; -} - - -/* - ======================================================================== - - Routine Description: - Check Sanity RSN IE of EAPoL message - - Arguments: - - Return Value: - - - ======================================================================== -*/ -BOOLEAN RTMPCheckRSNIE( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN UCHAR DataLen, - IN MAC_TABLE_ENTRY *pEntry, - OUT UCHAR *Offset) -{ - PUCHAR pVIE; - UCHAR len; - PEID_STRUCT pEid; - BOOLEAN result = FALSE; - - pVIE = pData; - len = DataLen; - *Offset = 0; - - while (len > sizeof(RSNIE2)) - { - pEid = (PEID_STRUCT) pVIE; - // WPA RSN IE - if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) - { - if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) && - (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) && - (pEntry->RSNIE_Len == (pEid->Len + 2))) - { - result = TRUE; - } - - *Offset += (pEid->Len + 2); - } - // WPA2 RSN IE - else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) - { - if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) && - (pEid->Eid == pEntry->RSN_IE[0]) && - ((pEid->Len + 2) >= pEntry->RSNIE_Len) && - (NdisEqualMemory(pEid->Octet, &pEntry->RSN_IE[2], pEntry->RSNIE_Len - 2))) - { - - result = TRUE; - } - - *Offset += (pEid->Len + 2); - } - else - { - break; - } - - pVIE += (pEid->Len + 2); - len -= (pEid->Len + 2); - } - - - return result; - -} - - -/* - ======================================================================== - - Routine Description: - Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK. - GTK is encaptulated in KDE format at p.83 802.11i D10 - - Arguments: - - Return Value: - - Note: - 802.11i D10 - - ======================================================================== -*/ -BOOLEAN RTMPParseEapolKeyData( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKeyData, - IN UCHAR KeyDataLen, - IN UCHAR GroupKeyIndex, - IN UCHAR MsgType, - IN BOOLEAN bWPA2, - IN MAC_TABLE_ENTRY *pEntry) -{ - PKDE_ENCAP pKDE = NULL; - PUCHAR pMyKeyData = pKeyData; - UCHAR KeyDataLength = KeyDataLen; - UCHAR GTKLEN = 0; - UCHAR DefaultIdx = 0; - UCHAR skip_offset; - - // Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it - if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3) - { - // Check RSN IE whether it is WPA2/WPA2PSK - if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset)) - { - // send wireless event - for RSN IE different - if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_RSNIE_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); - - DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in msg %d of 4-way handshake!\n", MsgType)); - hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen); - hex_dump("Desired RSN_IE ", pEntry->RSN_IE, pEntry->RSNIE_Len); - - return FALSE; - } - else - { - if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3) - { - WpaShowAllsuite(pMyKeyData, skip_offset); - - // skip RSN IE - pMyKeyData += skip_offset; - KeyDataLength -= skip_offset; - DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset)); - } - else - return TRUE; - } - } - - DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength)); - //hex_dump("remain data", pMyKeyData, KeyDataLength); - - - // Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2 - if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1)) - { - if (KeyDataLength >= 8) // KDE format exclude GTK length - { - pKDE = (PKDE_ENCAP) pMyKeyData; - - - DefaultIdx = pKDE->GTKEncap.Kid; - - // Sanity check - KED length - if (KeyDataLength < (pKDE->Len + 2)) - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n")); - return FALSE; - } - - // Get GTK length - refer to IEEE 802.11i-2004 p.82 - GTKLEN = pKDE->Len -6; - if (GTKLEN < LEN_AES_KEY) - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN)); - return FALSE; - } - - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KDE format length is too short \n")); - return FALSE; - } - - DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN)); - // skip it - pMyKeyData += 8; - KeyDataLength -= 8; - - } - else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1) - { - DefaultIdx = GroupKeyIndex; - DBGPRINT(RT_DEBUG_TRACE, ("GTK DefaultKeyID=%d \n", DefaultIdx)); - } - - // Sanity check - shared key index must be 1 ~ 3 - if (DefaultIdx < 1 || DefaultIdx > 3) - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); - return FALSE; - } - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - PCIPHER_KEY pSharedKey; - - // set key material, TxMic and RxMic - NdisMoveMemory(pAd->StaCfg.GTK, pMyKeyData, 32); - pAd->StaCfg.DefaultKeyId = DefaultIdx; - - pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId]; - - // Prepare pair-wise key information into shared key table - NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY)); - pSharedKey->KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK); - NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16], LEN_TKIP_RXMICK); - NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24], LEN_TKIP_TXMICK); - - // Update Shared Key CipherAlg - pSharedKey->CipherAlg = CIPHER_NONE; - if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) - pSharedKey->CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) - pSharedKey->CipherAlg = CIPHER_AES; - else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled) - pSharedKey->CipherAlg = CIPHER_WEP64; - else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled) - pSharedKey->CipherAlg = CIPHER_WEP128; - - - // Update group key information to ASIC Shared Key Table - AsicAddSharedKeyEntry(pAd, - BSS0, - pAd->StaCfg.DefaultKeyId, - pSharedKey->CipherAlg, - pSharedKey->Key, - pSharedKey->TxMic, - pSharedKey->RxMic); - - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAd, - BSS0, - pAd->StaCfg.DefaultKeyId, - pSharedKey->CipherAlg, - NULL); - } -#endif // CONFIG_STA_SUPPORT // - - return TRUE; - -} - - -/* - ======================================================================== - - Routine Description: - Construct EAPoL message for WPA handshaking - Its format is below, - - +--------------------+ - | Protocol Version | 1 octet - +--------------------+ - | Protocol Type | 1 octet - +--------------------+ - | Body Length | 2 octets - +--------------------+ - | Descriptor Type | 1 octet - +--------------------+ - | Key Information | 2 octets - +--------------------+ - | Key Length | 1 octet - +--------------------+ - | Key Repaly Counter | 8 octets - +--------------------+ - | Key Nonce | 32 octets - +--------------------+ - | Key IV | 16 octets - +--------------------+ - | Key RSC | 8 octets - +--------------------+ - | Key ID or Reserved | 8 octets - +--------------------+ - | Key MIC | 16 octets - +--------------------+ - | Key Data Length | 2 octets - +--------------------+ - | Key Data | n octets - +--------------------+ - - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID ConstructEapolMsg( - IN PMAC_TABLE_ENTRY pEntry, - IN UCHAR GroupKeyWepStatus, - IN UCHAR MsgType, - IN UCHAR DefaultKeyIdx, - IN UCHAR *KeyNonce, - IN UCHAR *TxRSC, - IN UCHAR *GTK, - IN UCHAR *RSNIE, - IN UCHAR RSNIE_Len, - OUT PEAPOL_PACKET pMsg) -{ - BOOLEAN bWPA2 = FALSE; - UCHAR KeyDescVer; - - // Choose WPA2 or not - if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || - (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) - bWPA2 = TRUE; - - // Init Packet and Fill header - pMsg->ProVer = EAPOL_VER; - pMsg->ProType = EAPOLKey; - - // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field - SET_UINT16_TO_ARRARY(pMsg->Body_Len, LEN_EAPOL_KEY_MSG); - - // Fill in EAPoL descriptor - if (bWPA2) - pMsg->KeyDesc.Type = WPA2_KEY_DESC; - else - pMsg->KeyDesc.Type = WPA1_KEY_DESC; - - // Key Descriptor Version (bits 0-2) specifies the key descriptor version type - { - // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 - // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used. - KeyDescVer = (((pEntry->WepStatus == Ndis802_11Encryption3Enabled) || - (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP)); - } - - pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer; - - // Specify Key Type as Group(0) or Pairwise(1) - if (MsgType >= EAPOL_GROUP_MSG_1) - pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY; - else - pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; - - // Specify Key Index, only group_msg1_WPA1 - if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)) - pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx; - - if (MsgType == EAPOL_PAIR_MSG_3) - pMsg->KeyDesc.KeyInfo.Install = 1; - - if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)) - pMsg->KeyDesc.KeyInfo.KeyAck = 1; - - if (MsgType != EAPOL_PAIR_MSG_1) - pMsg->KeyDesc.KeyInfo.KeyMic = 1; - - if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || - (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) - { - pMsg->KeyDesc.KeyInfo.Secure = 1; - } - - if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || - (MsgType == EAPOL_GROUP_MSG_1))) - { - pMsg->KeyDesc.KeyInfo.EKD_DL = 1; - } - - // key Information element has done. - *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo)); - - // Fill in Key Length - { - if (MsgType >= EAPOL_GROUP_MSG_1) - { - // the length of group key cipher - pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY); - } - else - { - // the length of pairwise key cipher - pMsg->KeyDesc.KeyLength[1] = ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY); - } - } - - // Fill in replay counter - NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY); - - // Fill Key Nonce field - // ANonce : pairwise_msg1 & pairwise_msg3 - // SNonce : pairwise_msg2 - // GNonce : group_msg1_wpa1 - if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)))) - NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE); - - // Fill key IV - WPA2 as 0, WPA1 as random - if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) - { - // Suggest IV be random number plus some number, - NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV); - pMsg->KeyDesc.KeyIv[15] += 2; - } - - // Fill Key RSC field - // It contains the RSC for the GTK being installed. - if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1)) - { - NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6); - } - - // Clear Key MIC field for MIC calculation later - NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); - - ConstructEapolKeyData(pEntry, - GroupKeyWepStatus, - KeyDescVer, - MsgType, - DefaultKeyIdx, - GTK, - RSNIE, - RSNIE_Len, - pMsg); - - // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. - if (MsgType != EAPOL_PAIR_MSG_1) - { - CalculateMIC(KeyDescVer, pEntry->PTK, pMsg); - } - - DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); - DBGPRINT(RT_DEBUG_TRACE, (" Body length = %d \n", CONV_ARRARY_TO_UINT16(pMsg->Body_Len))); - DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyLength))); - - -} - -/* - ======================================================================== - - Routine Description: - Construct the Key Data field of EAPoL message - - Arguments: - pAd Pointer to our adapter - Elem Message body - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID ConstructEapolKeyData( - IN PMAC_TABLE_ENTRY pEntry, - IN UCHAR GroupKeyWepStatus, - IN UCHAR keyDescVer, - IN UCHAR MsgType, - IN UCHAR DefaultKeyIdx, - IN UCHAR *GTK, - IN UCHAR *RSNIE, - IN UCHAR RSNIE_LEN, - OUT PEAPOL_PACKET pMsg) -{ - UCHAR *mpool, *Key_Data, *Rc4GTK; - UCHAR ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)]; - ULONG data_offset; - BOOLEAN bWPA2Capable = FALSE; - PRTMP_ADAPTER pAd = pEntry->pAd; - BOOLEAN GTK_Included = FALSE; - - // Choose WPA2 or not - if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || - (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) - bWPA2Capable = TRUE; - - if (MsgType == EAPOL_PAIR_MSG_1 || - MsgType == EAPOL_PAIR_MSG_4 || - MsgType == EAPOL_GROUP_MSG_2) - return; - - // allocate memory pool - os_alloc_mem(NULL, (PUCHAR *)&mpool, 1500); - - if (mpool == NULL) - return; - - /* Rc4GTK Len = 512 */ - Rc4GTK = (UCHAR *) ROUND_UP(mpool, 4); - /* Key_Data Len = 512 */ - Key_Data = (UCHAR *) ROUND_UP(Rc4GTK + 512, 4); - - NdisZeroMemory(Key_Data, 512); - SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0); - data_offset = 0; - - // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 - if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3))) - { - PUINT8 pmkid_ptr = NULL; - UINT8 pmkid_len = 0; - - - RTMPInsertRSNIE(&Key_Data[data_offset], - (PULONG)&data_offset, - RSNIE, - RSNIE_LEN, - pmkid_ptr, - pmkid_len); - } - - - // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2 - if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))) - { - // Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h - Key_Data[data_offset + 0] = 0xDD; - - if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) - { - Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField) - } - else - { - Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField) - } - - Key_Data[data_offset + 2] = 0x00; - Key_Data[data_offset + 3] = 0x0F; - Key_Data[data_offset + 4] = 0xAC; - Key_Data[data_offset + 5] = 0x01; - - // GTK KDE format - 802.11i-2004 Figure-43x - Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03); - Key_Data[data_offset + 7] = 0x00; // Reserved Byte - - data_offset += 8; - } - - - // Encapsulate GTK - // Only for pairwise_msg3_WPA2 and group_msg1 - if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1)) - { - // Fill in GTK - if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) - { - NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY); - data_offset += LEN_AES_KEY; - } - else - { - NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH); - data_offset += TKIP_GTK_LENGTH; - } - - GTK_Included = TRUE; - } - - - // This whole key-data field shall be encrypted if a GTK is included. - // Encrypt the data material in key data field with KEK - if (GTK_Included) - { - //hex_dump("GTK_Included", Key_Data, data_offset); - - if ( - (keyDescVer == DESC_TYPE_AES)) - { - UCHAR remainder = 0; - UCHAR pad_len = 0; - - // Key Descriptor Version 2 or 3: AES key wrap, defined in IETF RFC 3394, - // shall be used to encrypt the Key Data field using the KEK field from - // the derived PTK. - - // If the Key Data field uses the NIST AES key wrap, then the Key Data field - // shall be padded before encrypting if the key data length is less than 16 - // octets or if it is not a multiple of 8. The padding consists of appending - // a single octet 0xdd followed by zero or more 0x00 octets. - if ((remainder = data_offset & 0x07) != 0) - { - INT i; - - pad_len = (8 - remainder); - Key_Data[data_offset] = 0xDD; - for (i = 1; i < pad_len; i++) - Key_Data[data_offset + i] = 0; - - data_offset += pad_len; - } - - AES_GTK_KEY_WRAP(&pEntry->PTK[16], Key_Data, data_offset, Rc4GTK); - // AES wrap function will grow 8 bytes in length - data_offset += 8; - } - else - { - /* Key Descriptor Version 1: ARC4 is used to encrypt the Key Data field - using the KEK field from the derived PTK. */ - - // PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV) - // put TxTsc in Key RSC field - pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32. - - // ekey is the contanetion of IV-field, and PTK[16]->PTK[31] - NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, LEN_KEY_DESC_IV); - NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &pEntry->PTK[16], LEN_EAP_EK); - ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); //INIT SBOX, KEYLEN+3(IV) - pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, data_offset); - WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, Key_Data, data_offset); - } - - NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset); - } - else - { - NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset); - } - - // Update key data length field and total body length - SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, data_offset); - INC_UINT16_TO_ARRARY(pMsg->Body_Len, data_offset); - - os_free_mem(NULL, mpool); - -} - -/* - ======================================================================== - - Routine Description: - Calcaulate MIC. It is used during 4-ways handsharking. - - Arguments: - pAd - pointer to our pAdapter context - PeerWepStatus - indicate the encryption type - - Return Value: - - Note: - - ======================================================================== -*/ -static VOID CalculateMIC( - IN UCHAR KeyDescVer, - IN UCHAR *PTK, - OUT PEAPOL_PACKET pMsg) -{ - UCHAR *OutBuffer; - ULONG FrameLen = 0; - UCHAR mic[LEN_KEY_DESC_MIC]; - UCHAR digest[80]; - - // allocate memory for MIC calculation - os_alloc_mem(NULL, (PUCHAR *)&OutBuffer, 512); - - if (OutBuffer == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n")); - return; - } - - // make a frame for calculating MIC. - MakeOutgoingFrame(OutBuffer, &FrameLen, - CONV_ARRARY_TO_UINT16(pMsg->Body_Len) + 4, pMsg, - END_OF_ARGS); - - NdisZeroMemory(mic, sizeof(mic)); - - // Calculate MIC - if (KeyDescVer == DESC_TYPE_AES) - { - HMAC_SHA1(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE); - NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); - } - else - { - HMAC_MD5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic, MD5_DIGEST_SIZE); - } - - // store the calculated MIC - NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC); - - os_free_mem(NULL, OutBuffer); -} - -/* - ======================================================================== - - Routine Description: - Some received frames can't decrypt by Asic, so decrypt them by software. - - Arguments: - pAd - pointer to our pAdapter context - PeerWepStatus - indicate the encryption type - - Return Value: - NDIS_STATUS_SUCCESS - decryption successful - NDIS_STATUS_FAILURE - decryption failure - - ======================================================================== -*/ -NDIS_STATUS RTMPSoftDecryptBroadCastData( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN NDIS_802_11_ENCRYPTION_STATUS GroupCipher, - IN PCIPHER_KEY pShard_key) -{ - PRXWI_STRUC pRxWI = pRxBlk->pRxWI; - - - - // handle WEP decryption - if (GroupCipher == Ndis802_11Encryption1Enabled) - { - if (RTMPSoftDecryptWEP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, pShard_key)) - { - - //Minus IV[4] & ICV[4] - pRxWI->MPDUtotalByteCount -= 8; - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR : Software decrypt WEP data fails.\n")); - // give up this frame - return NDIS_STATUS_FAILURE; - } - } - // handle TKIP decryption - else if (GroupCipher == Ndis802_11Encryption2Enabled) - { - if (RTMPSoftDecryptTKIP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, pShard_key)) - { - - //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV - pRxWI->MPDUtotalByteCount -= 20; - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptTKIP Failed\n")); - // give up this frame - return NDIS_STATUS_FAILURE; - } - } - // handle AES decryption - else if (GroupCipher == Ndis802_11Encryption3Enabled) - { - if (RTMPSoftDecryptAES(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount , pShard_key)) - { - - //8 bytes MIC, 8 bytes IV/EIV (CCMP Header) - pRxWI->MPDUtotalByteCount -= 16; - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptAES Failed\n")); - // give up this frame - return NDIS_STATUS_FAILURE; - } - } - else - { - // give up this frame - return NDIS_STATUS_FAILURE; - } - - return NDIS_STATUS_SUCCESS; - -} - - -PUINT8 GetSuiteFromRSNIE( - IN PUINT8 rsnie, - IN UINT rsnie_len, - IN UINT8 type, - OUT UINT8 *count) -{ - PEID_STRUCT pEid; - INT len; - PUINT8 pBuf; - INT offset = 0; - PRSNIE_AUTH pAkm; - UINT16 acount; - BOOLEAN isWPA2 = FALSE; - - pEid = (PEID_STRUCT)rsnie; - len = rsnie_len - 2; // exclude IE and length - pBuf = (PUINT8)&pEid->Octet[0]; - - - - // set default value - *count = 0; - - // Check length - if ((len <= 0) || (pEid->Len != len)) - { - DBGPRINT_ERR(("%s : The length is invalid\n", __FUNCTION__)); - return NULL; - } - - // Check WPA or WPA2 - if (pEid->Eid == IE_WPA) - { - PRSNIE pRsnie = (PRSNIE)pBuf; - UINT16 ucount; - - if (len < sizeof(RSNIE)) - { - DBGPRINT_ERR(("%s : The length is too short for WPA\n", __FUNCTION__)); - return NULL; - } - - // Get the count of pairwise cipher - ucount = cpu2le16(pRsnie->ucount); - if (ucount > 2) - { - DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n", - __FUNCTION__, ucount)); - return NULL; - } - - // Get the group cipher - if (type == GROUP_SUITE) - { - *count = 1; - return pRsnie->mcast; - } - // Get the pairwise cipher suite - else if (type == PAIRWISE_SUITE) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of pairwise cipher is %d\n", - __FUNCTION__, ucount)); - *count = ucount; - return pRsnie->ucast[0].oui; - } - - offset = sizeof(RSNIE) + (4 * (ucount - 1)); - - } - else if (pEid->Eid == IE_RSN) - { - PRSNIE2 pRsnie = (PRSNIE2)pBuf; - UINT16 ucount; - - isWPA2 = TRUE; - - if (len < sizeof(RSNIE2)) - { - DBGPRINT_ERR(("%s : The length is too short for WPA2\n", __FUNCTION__)); - return NULL; - } - - // Get the count of pairwise cipher - ucount = cpu2le16(pRsnie->ucount); - if (ucount > 2) - { - DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n", - __FUNCTION__, ucount)); - return NULL; - } - - // Get the group cipher - if (type == GROUP_SUITE) - { - *count = 1; - return pRsnie->mcast; - } - // Get the pairwise cipher suite - else if (type == PAIRWISE_SUITE) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of pairwise cipher is %d\n", - __FUNCTION__, ucount)); - *count = ucount; - return pRsnie->ucast[0].oui; - } - - offset = sizeof(RSNIE2) + (4 * (ucount - 1)); - - } - else - { - DBGPRINT_ERR(("%s : Unknown IE (%d)\n", __FUNCTION__, pEid->Eid)); - return NULL; - } - - // skip group cipher and pairwise cipher suite - pBuf += offset; - len -= offset; - - if (len < sizeof(RSNIE_AUTH)) - { - DBGPRINT_ERR(("%s : The length of RSNIE is too short\n", __FUNCTION__)); - return NULL; - } - - // pointer to AKM count - pAkm = (PRSNIE_AUTH)pBuf; - - // Get the count of pairwise cipher - acount = cpu2le16(pAkm->acount); - if (acount > 2) - { - DBGPRINT_ERR(("%s : The count(%d) of AKM is invlaid\n", - __FUNCTION__, acount)); - return NULL; - } - - // Get the AKM suite - if (type == AKM_SUITE) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of AKM is %d\n", - __FUNCTION__, acount)); - *count = acount; - return pAkm->auth[0].oui; - } - offset = sizeof(RSNIE_AUTH) + (4 * (acount - 1)); - - pBuf += offset; - len -= offset; - - // The remaining length must larger than (RSN-Capability(2) + PMKID-Count(2) + PMKID(16~)) - if (len >= (sizeof(RSN_CAPABILITIES) + 2 + LEN_PMKID)) - { - // Skip RSN capability and PMKID-Count - pBuf += (sizeof(RSN_CAPABILITIES) + 2); - len -= (sizeof(RSN_CAPABILITIES) + 2); - - // Get PMKID - if (type == PMKID_LIST) - { - *count = 1; - return pBuf; - } - } - else - { - DBGPRINT_ERR(("%s : it can't get any more information beyond AKM \n", __FUNCTION__)); - return NULL; - } - - *count = 0; - //DBGPRINT_ERR(("%s : The type(%d) doesn't support \n", __FUNCTION__, type)); - return NULL; - -} - -VOID WpaShowAllsuite( - IN PUINT8 rsnie, - IN UINT rsnie_len) -{ - PUINT8 pSuite = NULL; - UINT8 count; - - hex_dump("RSNIE", rsnie, rsnie_len); - - // group cipher - if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE, &count)) != NULL) - { - hex_dump("group cipher", pSuite, 4*count); - } - - // pairwise cipher - if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE, &count)) != NULL) - { - hex_dump("pairwise cipher", pSuite, 4*count); - } - - // AKM - if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count)) != NULL) - { - hex_dump("AKM suite", pSuite, 4*count); - } - - // PMKID - if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count)) != NULL) - { - hex_dump("PMKID", pSuite, LEN_PMKID); - } - -} - -VOID RTMPInsertRSNIE( - IN PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN PUINT8 rsnie_ptr, - IN UINT8 rsnie_len, - IN PUINT8 pmkid_ptr, - IN UINT8 pmkid_len) -{ - PUCHAR pTmpBuf; - ULONG TempLen = 0; - UINT8 extra_len = 0; - UINT16 pmk_count = 0; - UCHAR ie_num; - UINT8 total_len = 0; - UCHAR WPA2_OUI[3]={0x00,0x0F,0xAC}; - - pTmpBuf = pFrameBuf; - - /* PMKID-List Must larger than 0 and the multiple of 16. */ - if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0)) - { - extra_len = sizeof(UINT16) + pmkid_len; - - pmk_count = (pmkid_len >> 4); - pmk_count = cpu2le16(pmk_count); - } - else - { - DBGPRINT(RT_DEBUG_WARN, ("%s : The length is PMKID-List is invalid (%d), so don't insert it.\n", - __FUNCTION__, pmkid_len)); - } - - if (rsnie_len != 0) - { - ie_num = IE_WPA; - total_len = rsnie_len; - - if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI))) - { - ie_num = IE_RSN; - total_len += extra_len; - } - - /* construct RSNIE body */ - MakeOutgoingFrame(pTmpBuf, &TempLen, - 1, &ie_num, - 1, &total_len, - rsnie_len, rsnie_ptr, - END_OF_ARGS); - - pTmpBuf += TempLen; - *pFrameLen = *pFrameLen + TempLen; - - if (ie_num == IE_RSN) - { - /* Insert PMKID-List field */ - if (extra_len > 0) - { - MakeOutgoingFrame(pTmpBuf, &TempLen, - 2, &pmk_count, - pmkid_len, pmkid_ptr, - END_OF_ARGS); - - pTmpBuf += TempLen; - *pFrameLen = *pFrameLen + TempLen; - } - } - } - - return; -} diff --git a/drivers/staging/rt3090/common/crypt_aes.c b/drivers/staging/rt3090/common/crypt_aes.c deleted file mode 100644 index f400f1eab516a68ce57bd7038f06e04cd84659ea..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/crypt_aes.c +++ /dev/null @@ -1,1007 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - crypt_aes.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Eddy 2009/01/19 Create AES-128, AES-192, AES-256, AES-CBC -*/ - -#include "crypt_aes.h" - -/* The value given by [x^(i-1),{00},{00},{00}], with x^(i-1) being powers of x in the field GF(2^8). */ -static const UINT32 aes_rcon[] = { - 0x00000000, 0x01000000, 0x02000000, 0x04000000, - 0x08000000, 0x10000000, 0x20000000, 0x40000000, - 0x80000000, 0x1B000000, 0x36000000}; - -static const UINT8 aes_sbox_enc[] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7 ,0xab, 0x76, /* 0 */ - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4 ,0x72, 0xc0, /* 1 */ - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8 ,0x31, 0x15, /* 2 */ - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27 ,0xb2, 0x75, /* 3 */ - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3 ,0x2f, 0x84, /* 4 */ - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c ,0x58, 0xcf, /* 5 */ - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c ,0x9f, 0xa8, /* 6 */ - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff ,0xf3, 0xd2, /* 7 */ - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d ,0x19, 0x73, /* 8 */ - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e ,0x0b, 0xdb, /* 9 */ - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95 ,0xe4, 0x79, /* a */ - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a ,0xae, 0x08, /* b */ - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd ,0x8b, 0x8a, /* c */ - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1 ,0x1d, 0x9e, /* d */ - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55 ,0x28, 0xdf, /* e */ - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54 ,0xbb, 0x16, /* f */ -}; - -static const UINT8 aes_sbox_dec[] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, /* 0 */ - 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, /* 1 */ - 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, /* 2 */ - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, /* 3 */ - 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, /* 4 */ - 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, /* 5 */ - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, /* 6 */ - 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, /* 7 */ - 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, /* 8 */ - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, /* 9 */ - 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, /* a */ - 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, /* b */ - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, /* c */ - 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, /* d */ - 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, /* e */ - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, /* f */ -}; - -/* ArrayIndex*{02} */ -static const UINT8 aes_mul_2[] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, /* 0 */ - 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, /* 1 */ - 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, /* 2 */ - 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, /* 3 */ - 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, /* 4 */ - 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, /* 5 */ - 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, /* 6 */ - 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, /* 7 */ - 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, /* 8 */ - 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, /* 9 */ - 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, /* a */ - 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, /* b */ - 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, /* c */ - 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, /* d */ - 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, /* e */ - 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5, /* f */ -}; - -/* ArrayIndex*{03} */ -static const UINT8 aes_mul_3[] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, /* 0 */ - 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, /* 1 */ - 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, /* 2 */ - 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41, /* 3 */ - 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, /* 4 */ - 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, /* 5 */ - 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, /* 6 */ - 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, /* 7 */ - 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a, /* 8 */ - 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba, /* 9 */ - 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, /* a */ - 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda, /* b */ - 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a, /* c */ - 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, /* d */ - 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a, /* e */ - 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a, /* f */ -}; - -/* ArrayIndex*{09} */ -static const UINT8 aes_mul_9[] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, /* 0 */ - 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, /* 1 */ - 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, /* 2 */ - 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, /* 3 */ - 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, /* 4 */ - 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, /* 5 */ - 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, /* 6 */ - 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, /* 7 */ - 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, /* 8 */ - 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, /* 9 */ - 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, /* a */ - 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, /* b */ - 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, /* c */ - 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, /* d */ - 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, /* e */ - 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46, /* f */ -}; - -/* ArrayIndex*{0b} */ -static const UINT8 aes_mul_b[] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, /* 0 */ - 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, /* 1 */ - 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, /* 2 */ - 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, /* 3 */ - 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, /* 4 */ - 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, /* 5 */ - 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, /* 6 */ - 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, /* 7 */ - 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, /* 8 */ - 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, /* 9 */ - 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, /* a */ - 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, /* b */ - 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, /* c */ - 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, /* d */ - 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, /* e */ - 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3, /* f */ -}; - -/* ArrayIndex*{0d} */ -static const UINT8 aes_mul_d[] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, /* 0 */ - 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, /* 1 */ - 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, /* 2 */ - 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, /* 3 */ - 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, /* 4 */ - 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, /* 5 */ - 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, /* 6 */ - 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, /* 7 */ - 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, /* 8 */ - 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, /* 9 */ - 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, /* a */ - 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, /* b */ - 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, /* c */ - 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, /* d */ - 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, /* e */ - 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97, /* f */ -}; - -/* ArrayIndex*{0e} */ -static const UINT8 aes_mul_e[] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, /* 0 */ - 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, /* 1 */ - 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, /* 2 */ - 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, /* 3 */ - 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, /* 4 */ - 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, /* 5 */ - 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, /* 6 */ - 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, /* 7 */ - 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, /* 8 */ - 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, /* 9 */ - 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, /* a */ - 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, /* b */ - 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, /* c */ - 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, /* d */ - 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, /* e */ - 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d, /* f */ -}; - - -/* For AES_CMAC */ -#define AES_MAC_LENGTH 16 /* 128-bit string */ -static UINT8 Const_Zero[16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -static UINT8 Const_Rb[16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87}; - - -/* -======================================================================== -Routine Description: - AES key expansion (key schedule) - -Arguments: - Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) - KeyLength The length of cipher key in bytes - paes_ctx Pointer to AES_CTX_STRUC - -Return Value: - paes_ctx Retrun the KeyWordExpansion of AES_CTX_STRUC - -Note: - Pseudo code for key expansion - ------------------------------------------ - Nk = (key length/4); - - while (i < Nk) - KeyWordExpansion[i] = word(key[4*i], key[4*i + 1], key[4*i + 2], key[4*i + 3]); - i++; - end while - - while (i < ((key length/4 + 6 + 1)*4) ) - temp = KeyWordExpansion[i - 1]; - if (i % Nk ==0) - temp = SubWord(RotWord(temp)) ^ Rcon[i/Nk]; - else if ((Nk > 6) && (i % 4 == 4)) - temp = SubWord(temp); - end if - - KeyWordExpansion[i] = KeyWordExpansion[i - Nk]^ temp; - i++; - end while -======================================================================== -*/ -VOID AES_KeyExpansion ( - IN UINT8 Key[], - IN UINT KeyLength, - INOUT AES_CTX_STRUC *paes_ctx) -{ - UINT KeyIndex = 0; - UINT NumberOfWordOfKey, NumberOfWordOfKeyExpansion; - UINT8 TempWord[AES_KEY_ROWS], Temp; - UINT32 Temprcon; - - NumberOfWordOfKey = KeyLength >> 2; - while (KeyIndex < NumberOfWordOfKey) - { - paes_ctx->KeyWordExpansion[0][KeyIndex] = Key[4*KeyIndex]; - paes_ctx->KeyWordExpansion[1][KeyIndex] = Key[4*KeyIndex + 1]; - paes_ctx->KeyWordExpansion[2][KeyIndex] = Key[4*KeyIndex + 2]; - paes_ctx->KeyWordExpansion[3][KeyIndex] = Key[4*KeyIndex + 3]; - KeyIndex++; - } /* End of while */ - - NumberOfWordOfKeyExpansion = ((UINT) AES_KEY_ROWS) * ((KeyLength >> 2) + 6 + 1); - while (KeyIndex < NumberOfWordOfKeyExpansion) - { - TempWord[0] = paes_ctx->KeyWordExpansion[0][KeyIndex - 1]; - TempWord[1] = paes_ctx->KeyWordExpansion[1][KeyIndex - 1]; - TempWord[2] = paes_ctx->KeyWordExpansion[2][KeyIndex - 1]; - TempWord[3] = paes_ctx->KeyWordExpansion[3][KeyIndex - 1]; - if ((KeyIndex % NumberOfWordOfKey) == 0) { - Temprcon = aes_rcon[KeyIndex/NumberOfWordOfKey]; - Temp = aes_sbox_enc[TempWord[1]]^((Temprcon >> 24) & 0xff); - TempWord[1] = aes_sbox_enc[TempWord[2]]^((Temprcon >> 16) & 0xff); - TempWord[2] = aes_sbox_enc[TempWord[3]]^((Temprcon >> 8) & 0xff); - TempWord[3] = aes_sbox_enc[TempWord[0]]^((Temprcon ) & 0xff); - TempWord[0] = Temp; - } else if ((NumberOfWordOfKey > 6) && ((KeyIndex % NumberOfWordOfKey) == 4)) { - Temp = aes_sbox_enc[TempWord[0]]; - TempWord[1] = aes_sbox_enc[TempWord[1]]; - TempWord[2] = aes_sbox_enc[TempWord[2]]; - TempWord[3] = aes_sbox_enc[TempWord[3]]; - TempWord[0] = Temp; - } - paes_ctx->KeyWordExpansion[0][KeyIndex] = paes_ctx->KeyWordExpansion[0][KeyIndex - NumberOfWordOfKey]^TempWord[0]; - paes_ctx->KeyWordExpansion[1][KeyIndex] = paes_ctx->KeyWordExpansion[1][KeyIndex - NumberOfWordOfKey]^TempWord[1]; - paes_ctx->KeyWordExpansion[2][KeyIndex] = paes_ctx->KeyWordExpansion[2][KeyIndex - NumberOfWordOfKey]^TempWord[2]; - paes_ctx->KeyWordExpansion[3][KeyIndex] = paes_ctx->KeyWordExpansion[3][KeyIndex - NumberOfWordOfKey]^TempWord[3]; - KeyIndex++; - } /* End of while */ -} /* End of AES_KeyExpansion */ - - -/* -======================================================================== -Routine Description: - AES encryption - -Arguments: - PlainBlock The block of plain text, 16 bytes(128 bits) each block - PlainBlockSize The length of block of plain text in bytes - Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) - KeyLength The length of cipher key in bytes - CipherBlockSize The length of allocated cipher block in bytes - -Return Value: - CipherBlock Return cipher text - CipherBlockSize Return the length of real used cipher block in bytes - -Note: - Reference to FIPS-PUB 197 - 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits) - 2. Transfer the plain block to state block - 3. Main encryption rounds - 4. Transfer the state block to cipher block - ------------------------------------------ - NumberOfRound = (key length / 4) + 6; - state block = plain block; - - AddRoundKey(state block, key); - for round = 1 to NumberOfRound - SubBytes(state block) - ShiftRows(state block) - MixColumns(state block) - AddRoundKey(state block, key); - end for - - SubBytes(state block) - ShiftRows(state block) - AddRoundKey(state block, key); - - cipher block = state block; -======================================================================== -*/ -VOID AES_Encrypt ( - IN UINT8 PlainBlock[], - IN UINT PlainBlockSize, - IN UINT8 Key[], - IN UINT KeyLength, - OUT UINT8 CipherBlock[], - INOUT UINT *CipherBlockSize) -{ - AES_CTX_STRUC aes_ctx; - UINT RowIndex, ColumnIndex; - UINT RoundIndex, NumberOfRound = 0; - UINT8 Temp, Row0, Row1, Row2, Row3; - - /* - * 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits) - */ - if (PlainBlockSize != AES_BLOCK_SIZES) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_Encrypt: plain block size is %d bytes, it must be %d bytes(128 bits).\n", - PlainBlockSize, AES_BLOCK_SIZES)); - return; - } /* End of if */ - if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_Encrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", - KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); - return; - } /* End of if */ - if (*CipherBlockSize < AES_BLOCK_SIZES) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_Encrypt: cipher block size is %d bytes, it must be %d bytes(128 bits).\n", - *CipherBlockSize, AES_BLOCK_SIZES)); - return; - } /* End of if */ - - /* - * 2. Transfer the plain block to state block - */ - for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - aes_ctx.State[RowIndex][ColumnIndex] = PlainBlock[RowIndex + 4*ColumnIndex]; - - /* - * 3. Main encryption rounds - */ - AES_KeyExpansion(Key, KeyLength, &aes_ctx); - NumberOfRound = (KeyLength >> 2) + 6; - - /* AES_AddRoundKey */ - RoundIndex = 0; - for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - aes_ctx.State[RowIndex][ColumnIndex] ^= aes_ctx.KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; - - for (RoundIndex = 1; RoundIndex < NumberOfRound;RoundIndex++) - { - /* AES_SubBytes */ - for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - aes_ctx.State[RowIndex][ColumnIndex] = aes_sbox_enc[aes_ctx.State[RowIndex][ColumnIndex]]; - - /* AES_ShiftRows */ - Temp = aes_ctx.State[1][0]; - aes_ctx.State[1][0] = aes_ctx.State[1][1]; - aes_ctx.State[1][1] = aes_ctx.State[1][2]; - aes_ctx.State[1][2] = aes_ctx.State[1][3]; - aes_ctx.State[1][3] = Temp; - Temp = aes_ctx.State[2][0]; - aes_ctx.State[2][0] = aes_ctx.State[2][2]; - aes_ctx.State[2][2] = Temp; - Temp = aes_ctx.State[2][1]; - aes_ctx.State[2][1] = aes_ctx.State[2][3]; - aes_ctx.State[2][3] = Temp; - Temp = aes_ctx.State[3][3]; - aes_ctx.State[3][3] = aes_ctx.State[3][2]; - aes_ctx.State[3][2] = aes_ctx.State[3][1]; - aes_ctx.State[3][1] = aes_ctx.State[3][0]; - aes_ctx.State[3][0] = Temp; - - /* AES_MixColumns */ - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - { - Row0 = aes_ctx.State[0][ColumnIndex]; - Row1 = aes_ctx.State[1][ColumnIndex]; - Row2 = aes_ctx.State[2][ColumnIndex]; - Row3 = aes_ctx.State[3][ColumnIndex]; - aes_ctx.State[0][ColumnIndex] = aes_mul_2[Row0]^aes_mul_3[Row1]^Row2^Row3; - aes_ctx.State[1][ColumnIndex] = Row0^aes_mul_2[Row1]^aes_mul_3[Row2]^Row3; - aes_ctx.State[2][ColumnIndex] = Row0^Row1^aes_mul_2[Row2]^aes_mul_3[Row3]; - aes_ctx.State[3][ColumnIndex] = aes_mul_3[Row0]^Row1^Row2^aes_mul_2[Row3]; - } - - /* AES_AddRoundKey */ - for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - aes_ctx.State[RowIndex][ColumnIndex] ^= aes_ctx.KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; - } /* End of for */ - - /* AES_SubBytes */ - for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - aes_ctx.State[RowIndex][ColumnIndex] = aes_sbox_enc[aes_ctx.State[RowIndex][ColumnIndex]]; - /* AES_ShiftRows */ - Temp = aes_ctx.State[1][0]; - aes_ctx.State[1][0] = aes_ctx.State[1][1]; - aes_ctx.State[1][1] = aes_ctx.State[1][2]; - aes_ctx.State[1][2] = aes_ctx.State[1][3]; - aes_ctx.State[1][3] = Temp; - Temp = aes_ctx.State[2][0]; - aes_ctx.State[2][0] = aes_ctx.State[2][2]; - aes_ctx.State[2][2] = Temp; - Temp = aes_ctx.State[2][1]; - aes_ctx.State[2][1] = aes_ctx.State[2][3]; - aes_ctx.State[2][3] = Temp; - Temp = aes_ctx.State[3][3]; - aes_ctx.State[3][3] = aes_ctx.State[3][2]; - aes_ctx.State[3][2] = aes_ctx.State[3][1]; - aes_ctx.State[3][1] = aes_ctx.State[3][0]; - aes_ctx.State[3][0] = Temp; - /* AES_AddRoundKey */ - for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - aes_ctx.State[RowIndex][ColumnIndex] ^= aes_ctx.KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; - - /* - * 4. Transfer the state block to cipher block - */ - for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - CipherBlock[RowIndex + 4*ColumnIndex] = aes_ctx.State[RowIndex][ColumnIndex]; - - *CipherBlockSize = ((UINT) AES_STATE_ROWS)*((UINT) AES_STATE_COLUMNS); -} /* End of AES_Encrypt */ - - -/* -======================================================================== -Routine Description: - AES decryption - -Arguments: - CipherBlock The block of cipher text, 16 bytes(128 bits) each block - CipherBlockSize The length of block of cipher text in bytes - Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) - KeyLength The length of cipher key in bytes - PlainBlockSize The length of allocated plain block in bytes - -Return Value: - PlainBlock Return plain text - PlainBlockSize Return the length of real used plain block in bytes - -Note: - Reference to FIPS-PUB 197 - 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits) - 2. Transfer the cipher block to state block - 3. Main decryption rounds - 4. Transfer the state block to plain block - ------------------------------------------ - NumberOfRound = (key length / 4) + 6; - state block = cipher block; - - AddRoundKey(state block, key); - for round = NumberOfRound to 1 - InvSubBytes(state block) - InvShiftRows(state block) - InvMixColumns(state block) - AddRoundKey(state block, key); - end for - - InvSubBytes(state block) - InvShiftRows(state block) - AddRoundKey(state block, key); - - plain block = state block; -======================================================================== -*/ -VOID AES_Decrypt ( - IN UINT8 CipherBlock[], - IN UINT CipherBlockSize, - IN UINT8 Key[], - IN UINT KeyLength, - OUT UINT8 PlainBlock[], - INOUT UINT *PlainBlockSize) -{ - AES_CTX_STRUC aes_ctx; - UINT RowIndex, ColumnIndex; - UINT RoundIndex, NumberOfRound = 0; - UINT8 Temp, Row0, Row1, Row2, Row3; - - /* - * 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits) - */ - if (*PlainBlockSize < AES_BLOCK_SIZES) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_Decrypt: plain block size is %d bytes, it must be %d bytes(128 bits).\n", - *PlainBlockSize, AES_BLOCK_SIZES)); - return; - } /* End of if */ - if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_Decrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", - KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); - return; - } /* End of if */ - if (CipherBlockSize != AES_BLOCK_SIZES) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_Decrypt: cipher block size is %d bytes, it must be %d bytes(128 bits).\n", - CipherBlockSize, AES_BLOCK_SIZES)); - return; - } /* End of if */ - - /* - * 2. Transfer the cipher block to state block - */ - for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - aes_ctx.State[RowIndex][ColumnIndex] = CipherBlock[RowIndex + 4*ColumnIndex]; - - /* - * 3. Main decryption rounds - */ - AES_KeyExpansion(Key, KeyLength, &aes_ctx); - NumberOfRound = (KeyLength >> 2) + 6; - - /* AES_AddRoundKey */ - RoundIndex = NumberOfRound; - for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - aes_ctx.State[RowIndex][ColumnIndex] ^= aes_ctx.KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; - - for (RoundIndex = (NumberOfRound - 1); RoundIndex > 0 ;RoundIndex--) - { - /* AES_InvShiftRows */ - Temp = aes_ctx.State[1][3]; - aes_ctx.State[1][3] = aes_ctx.State[1][2]; - aes_ctx.State[1][2] = aes_ctx.State[1][1]; - aes_ctx.State[1][1] = aes_ctx.State[1][0]; - aes_ctx.State[1][0] = Temp; - Temp = aes_ctx.State[2][0]; - aes_ctx.State[2][0] = aes_ctx.State[2][2]; - aes_ctx.State[2][2] = Temp; - Temp = aes_ctx.State[2][1]; - aes_ctx.State[2][1] = aes_ctx.State[2][3]; - aes_ctx.State[2][3] = Temp; - Temp = aes_ctx.State[3][0]; - aes_ctx.State[3][0] = aes_ctx.State[3][1]; - aes_ctx.State[3][1] = aes_ctx.State[3][2]; - aes_ctx.State[3][2] = aes_ctx.State[3][3]; - aes_ctx.State[3][3] = Temp; - - /* AES_InvSubBytes */ - for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - aes_ctx.State[RowIndex][ColumnIndex] = aes_sbox_dec[aes_ctx.State[RowIndex][ColumnIndex]]; - - /* AES_AddRoundKey */ - for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - aes_ctx.State[RowIndex][ColumnIndex] ^= aes_ctx.KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; - - /* AES_InvMixColumns */ - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - { - Row0 = aes_ctx.State[0][ColumnIndex]; - Row1 = aes_ctx.State[1][ColumnIndex]; - Row2 = aes_ctx.State[2][ColumnIndex]; - Row3 = aes_ctx.State[3][ColumnIndex]; - aes_ctx.State[0][ColumnIndex] = aes_mul_e[Row0]^aes_mul_b[Row1]^aes_mul_d[Row2]^aes_mul_9[Row3]; - aes_ctx.State[1][ColumnIndex] = aes_mul_9[Row0]^aes_mul_e[Row1]^aes_mul_b[Row2]^aes_mul_d[Row3]; - aes_ctx.State[2][ColumnIndex] = aes_mul_d[Row0]^aes_mul_9[Row1]^aes_mul_e[Row2]^aes_mul_b[Row3]; - aes_ctx.State[3][ColumnIndex] = aes_mul_b[Row0]^aes_mul_d[Row1]^aes_mul_9[Row2]^aes_mul_e[Row3]; - } - } /* End of for */ - - /* AES_InvShiftRows */ - Temp = aes_ctx.State[1][3]; - aes_ctx.State[1][3] = aes_ctx.State[1][2]; - aes_ctx.State[1][2] = aes_ctx.State[1][1]; - aes_ctx.State[1][1] = aes_ctx.State[1][0]; - aes_ctx.State[1][0] = Temp; - Temp = aes_ctx.State[2][0]; - aes_ctx.State[2][0] = aes_ctx.State[2][2]; - aes_ctx.State[2][2] = Temp; - Temp = aes_ctx.State[2][1]; - aes_ctx.State[2][1] = aes_ctx.State[2][3]; - aes_ctx.State[2][3] = Temp; - Temp = aes_ctx.State[3][0]; - aes_ctx.State[3][0] = aes_ctx.State[3][1]; - aes_ctx.State[3][1] = aes_ctx.State[3][2]; - aes_ctx.State[3][2] = aes_ctx.State[3][3]; - aes_ctx.State[3][3] = Temp; - /* AES_InvSubBytes */ - for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - aes_ctx.State[RowIndex][ColumnIndex] = aes_sbox_dec[aes_ctx.State[RowIndex][ColumnIndex]]; - /* AES_AddRoundKey */ - for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - aes_ctx.State[RowIndex][ColumnIndex] ^= aes_ctx.KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; - - /* - * 4. Transfer the state block to plain block - */ - for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) - for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) - PlainBlock[RowIndex + 4*ColumnIndex] = aes_ctx.State[RowIndex][ColumnIndex]; - - *PlainBlockSize = ((UINT) AES_STATE_ROWS)*((UINT) AES_STATE_COLUMNS); -} /* End of AES_Decrypt */ - - -/* -======================================================================== -Routine Description: - AES-CBC encryption - -Arguments: - PlainText Plain text - PlainTextLength The length of plain text in bytes - Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) - KeyLength The length of cipher key in bytes - IV Initialization vector, it may be 16 bytes (128 bits) - IVLength The length of initialization vector in bytes - CipherTextLength The length of allocated cipher text in bytes - -Return Value: - CipherText Return cipher text - CipherTextLength Return the length of real used cipher text in bytes - -Note: - Reference to RFC 3602 and NIST 800-38A -======================================================================== -*/ -VOID AES_CBC_Encrypt ( - IN UINT8 PlainText[], - IN UINT PlainTextLength, - IN UINT8 Key[], - IN UINT KeyLength, - IN UINT8 IV[], - IN UINT IVLength, - OUT UINT8 CipherText[], - INOUT UINT *CipherTextLength) -{ - UINT PaddingSize, PlainBlockStart, CipherBlockStart, CipherBlockSize; - UINT Index; - UINT8 Block[AES_BLOCK_SIZES]; - - /* - * 1. Check the input parameters - * - CipherTextLength > (PlainTextLength + Padding size), Padding size = block size - (PlainTextLength % block size) - * - Key length must be 16, 24, or 32 bytes(128, 192, or 256 bits) - * - IV length must be 16 bytes(128 bits) - */ - PaddingSize = ((UINT) AES_BLOCK_SIZES) - (PlainTextLength % ((UINT)AES_BLOCK_SIZES)); - if (*CipherTextLength < (PlainTextLength + PaddingSize)) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Encrypt: cipher text length is %d bytes < (plain text length %d bytes + padding size %d bytes).\n", - *CipherTextLength, PlainTextLength, PaddingSize)); - return; - } /* End of if */ - if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Encrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", - KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); - return; - } /* End of if */ - if (IVLength != AES_CBC_IV_LENGTH) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Encrypt: IV length is %d bytes, it must be %d bytes(128bits).\n", - IVLength, AES_CBC_IV_LENGTH)); - return; - } /* End of if */ - - - /* - * 2. Main algorithm - * - Plain text divide into serveral blocks (16 bytes/block) - * - If plain text is divided with no remainder by block, add a new block and padding size = block(16 bytes) - * - If plain text is not divided with no remainder by block, padding size = (block - remainder plain text) - * - Execute AES_Encrypt procedure. - * - * - Padding method: The remainder bytes will be filled with padding size (1 byte) - */ - PlainBlockStart = 0; - CipherBlockStart = 0; - while ((PlainTextLength - PlainBlockStart) >= AES_BLOCK_SIZES) - { - if (CipherBlockStart == 0) { - for (Index = 0; Index < AES_BLOCK_SIZES; Index++) - Block[Index] = PlainText[PlainBlockStart + Index]^IV[Index]; - } else { - for (Index = 0; Index < AES_BLOCK_SIZES; Index++) - Block[Index] = PlainText[PlainBlockStart + Index]^CipherText[CipherBlockStart - ((UINT) AES_BLOCK_SIZES) + Index]; - } /* End of if */ - - CipherBlockSize = *CipherTextLength - CipherBlockStart; - AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, CipherText + CipherBlockStart, &CipherBlockSize); - - PlainBlockStart += ((UINT) AES_BLOCK_SIZES); - CipherBlockStart += CipherBlockSize; - } /* End of while */ - - NdisMoveMemory(Block, (&PlainText[0] + PlainBlockStart), (PlainTextLength - PlainBlockStart)); - NdisFillMemory((Block + (((UINT) AES_BLOCK_SIZES) -PaddingSize)), PaddingSize, (UINT8) PaddingSize); - if (CipherBlockStart == 0) { - for (Index = 0; Index < AES_BLOCK_SIZES; Index++) - Block[Index] ^= IV[Index]; - } else { - for (Index = 0; Index < AES_BLOCK_SIZES; Index++) - Block[Index] ^= CipherText[CipherBlockStart - ((UINT) AES_BLOCK_SIZES) + Index]; - } /* End of if */ - CipherBlockSize = *CipherTextLength - CipherBlockStart; - AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, CipherText + CipherBlockStart, &CipherBlockSize); - CipherBlockStart += CipherBlockSize; - *CipherTextLength = CipherBlockStart; -} /* End of AES_CBC_Encrypt */ - - -/* -======================================================================== -Routine Description: - AES-CBC decryption - -Arguments: - CipherText Cipher text - CipherTextLength The length of cipher text in bytes - Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) - KeyLength The length of cipher key in bytes - IV Initialization vector, it may be 16 bytes (128 bits) - IVLength The length of initialization vector in bytes - PlainTextLength The length of allocated plain text in bytes - -Return Value: - PlainText Return plain text - PlainTextLength Return the length of real used plain text in bytes - -Note: - Reference to RFC 3602 and NIST 800-38A -======================================================================== -*/ -VOID AES_CBC_Decrypt ( - IN UINT8 CipherText[], - IN UINT CipherTextLength, - IN UINT8 Key[], - IN UINT KeyLength, - IN UINT8 IV[], - IN UINT IVLength, - OUT UINT8 PlainText[], - INOUT UINT *PlainTextLength) -{ - UINT PaddingSize, PlainBlockStart, CipherBlockStart, PlainBlockSize; - UINT Index; - - /* - * 1. Check the input parameters - * - CipherTextLength must be divided with no remainder by block - * - Key length must be 16, 24, or 32 bytes(128, 192, or 256 bits) - * - IV length must be 16 bytes(128 bits) - */ - if ((CipherTextLength % AES_BLOCK_SIZES) != 0) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Decrypt: cipher text length is %d bytes, it can't be divided with no remainder by block size(%d).\n", - CipherTextLength, AES_BLOCK_SIZES)); - return; - } /* End of if */ - if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Decrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", - KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); - return; - } /* End of if */ - if (IVLength != AES_CBC_IV_LENGTH) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Decrypt: IV length is %d bytes, it must be %d bytes(128bits).\n", - IVLength, AES_CBC_IV_LENGTH)); - return; - } /* End of if */ - - - /* - * 2. Main algorithm - * - Cypher text divide into serveral blocks (16 bytes/block) - * - Execute AES_Decrypt procedure. - * - Remove padding bytes, padding size is the last byte of plain text - */ - CipherBlockStart = 0; - PlainBlockStart = 0; - while ((CipherTextLength - CipherBlockStart) >= AES_BLOCK_SIZES) - { - PlainBlockSize = *PlainTextLength - PlainBlockStart; - AES_Decrypt(CipherText + CipherBlockStart, AES_BLOCK_SIZES , Key, KeyLength, PlainText + PlainBlockStart, &PlainBlockSize); - - if (PlainBlockStart == 0) { - for (Index = 0; Index < AES_BLOCK_SIZES; Index++) - PlainText[PlainBlockStart + Index] ^= IV[Index]; - } else { - for (Index = 0; Index < AES_BLOCK_SIZES; Index++) - PlainText[PlainBlockStart + Index] ^= CipherText[CipherBlockStart + Index - ((UINT) AES_BLOCK_SIZES)]; - } /* End of if */ - - CipherBlockStart += AES_BLOCK_SIZES; - PlainBlockStart += PlainBlockSize; - } /* End of while */ - - PaddingSize = (UINT8) PlainText[PlainBlockStart -1]; - *PlainTextLength = PlainBlockStart - PaddingSize; - -} /* End of AES_CBC_Encrypt */ - - - -/* -======================================================================== -Routine Description: - AES-CMAC generate subkey - -Arguments: - Key Cipher key 128 bits - KeyLength The length of Cipher key in bytes - -Return Value: - SubKey1 SubKey 1 128 bits - SubKey2 SubKey 2 128 bits - -Note: - Reference to RFC 4493 - - Step 1. L := AES-128(K, const_Zero); - Step 2. if MSB(L) is equal to 0 - then K1 := L << 1; - else K1 := (L << 1) XOR const_Rb; - Step 3. if MSB(K1) is equal to 0 - then K2 := K1 << 1; - else K2 := (K1 << 1) XOR const_Rb; - Step 4. return K1, K2; -======================================================================== -*/ -VOID AES_CMAC_GenerateSubKey ( - IN UINT8 Key[], - IN UINT KeyLength, - OUT UINT8 SubKey1[], - OUT UINT8 SubKey2[]) -{ - UINT8 MSB_L = 0, MSB_K1 = 0, Top_Bit = 0; - UINT SubKey1_Length = 0; - INT Index = 0; - - if (KeyLength != AES_KEY128_LENGTH) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_CMAC_GenerateSubKey: key length is %d bytes, it must be %d bytes(128 bits).\n", - KeyLength, AES_KEY128_LENGTH)); - return; - } /* End of if */ - - /* Step 1: L := AES-128(K, const_Zero); */ - SubKey1_Length = 16; - AES_Encrypt(Const_Zero, sizeof(Const_Zero), Key, KeyLength, SubKey1, &SubKey1_Length); - - /* - * Step 2. if MSB(L) is equal to 0 - * then K1 := L << 1; - * else K1 := (L << 1) XOR const_Rb; - */ - MSB_L = SubKey1[0] & 0x80; - for(Index = 0; Index < 15; Index++) { - Top_Bit = (SubKey1[Index + 1] & 0x80)?1:0; - SubKey1[Index] <<= 1; - SubKey1[Index] |= Top_Bit; - } - SubKey1[15] <<= 1; - if (MSB_L > 0) { - for(Index = 0; Index < 16; Index++) - SubKey1[Index] ^= Const_Rb[Index]; - } /* End of if */ - - /* - * Step 3. if MSB(K1) is equal to 0 - * then K2 := K1 << 1; - * else K2 := (K1 << 1) XOR const_Rb; - */ - MSB_K1 = SubKey1[0] & 0x80; - for(Index = 0; Index < 15; Index++) { - Top_Bit = (SubKey1[Index + 1] & 0x80)?1:0; - SubKey2[Index] = SubKey1[Index] << 1; - SubKey2[Index] |= Top_Bit; - } - SubKey2[15] = SubKey1[15] << 1; - if (MSB_K1 > 0) { - for(Index = 0; Index < 16; Index++) - SubKey2[Index] ^= Const_Rb[Index]; - } /* End of if */ -} /* End of AES_CMAC_GenerateSubKey */ - - -/* -======================================================================== -Routine Description: - AES-CMAC - -Arguments: - PlainText Plain text - PlainTextLength The length of plain text in bytes - Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) - KeyLength The length of cipher key in bytes - MACTextLength The length of allocated memory spaces in bytes - -Return Value: - MACText Message authentication code (128-bit string) - MACTextLength Return the length of Message authentication code in bytes - -Note: - Reference to RFC 4493 -======================================================================== -*/ -VOID AES_CMAC ( - IN UINT8 PlainText[], - IN UINT PlainTextLength, - IN UINT8 Key[], - IN UINT KeyLength, - OUT UINT8 MACText[], - INOUT UINT *MACTextLength) -{ - UINT PlainBlockStart; - UINT8 X[AES_BLOCK_SIZES], Y[AES_BLOCK_SIZES]; - UINT8 SubKey1[16]; - UINT8 SubKey2[16]; - INT X_Length, Index; - - if (*MACTextLength < AES_MAC_LENGTH) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_CMAC: MAC text length is less than %d bytes).\n", - AES_MAC_LENGTH)); - return; - } /* End of if */ - if (KeyLength != AES_KEY128_LENGTH) { - DBGPRINT(RT_DEBUG_ERROR, ("AES_CMAC: key length is %d bytes, it must be %d bytes(128 bits).\n", - KeyLength, AES_KEY128_LENGTH)); - return; - } /* End of if */ - - /* Step 1. (K1,K2) := Generate_Subkey(K); */ - NdisZeroMemory(SubKey1, 16); - NdisZeroMemory(SubKey2, 16); - AES_CMAC_GenerateSubKey(Key, KeyLength, SubKey1, SubKey2); - - /* - * 2. Main algorithm - * - Plain text divide into serveral blocks (16 bytes/block) - * - If plain text is not divided with no remainder by block, padding size = (block - remainder plain text) - * - Execute AES_Encrypt procedure. - */ - PlainBlockStart = 0; - NdisMoveMemory(X, Const_Zero, AES_BLOCK_SIZES); - while ((PlainTextLength - PlainBlockStart) > AES_BLOCK_SIZES) - { - for (Index = 0; Index < AES_BLOCK_SIZES; Index++) - Y[Index] = PlainText[PlainBlockStart + Index]^X[Index]; - - X_Length = sizeof(X); - AES_Encrypt(Y, sizeof(Y) , Key, KeyLength, X, &X_Length); - PlainBlockStart += ((UINT) AES_BLOCK_SIZES); - } /* End of while */ - if ((PlainTextLength - PlainBlockStart) == AES_BLOCK_SIZES) { - for (Index = 0; Index < AES_BLOCK_SIZES; Index++) - Y[Index] = PlainText[PlainBlockStart + Index]^X[Index]^SubKey1[Index]; - } else { - NdisZeroMemory(Y, AES_BLOCK_SIZES); - NdisMoveMemory(Y, &PlainText[PlainBlockStart], (PlainTextLength - PlainBlockStart)); - Y[(PlainTextLength - PlainBlockStart)] = 0x80; - for (Index = 0; Index < AES_BLOCK_SIZES; Index++) - Y[Index] = Y[Index]^X[Index]^SubKey2[Index]; - } /* End of if */ - AES_Encrypt(Y, sizeof(Y) , Key, KeyLength, MACText, MACTextLength); -} /* End of AES_CMAC */ diff --git a/drivers/staging/rt3090/common/crypt_biginteger.c b/drivers/staging/rt3090/common/crypt_biginteger.c deleted file mode 100644 index b346c5f7fbd0f6cb5f065dbfcf4960f1aaf91806..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/crypt_biginteger.c +++ /dev/null @@ -1,1119 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - cmm_profile.c - - Abstract: - - Revision History: - Who When What - --------- ---------- ---------------------------------------------- - */ - -#include "crypt_biginteger.h" - -#ifdef __KERNEL__ -#define DEBUGPRINT(fmt, args...) printk(KERN_ERR fmt, ## args) -#else -#define DEBUGPRINT(fmt, args...) printf(fmt, ## args) -#endif /* __KERNEL__ */ - -#define UINT32_HBITS(value) (((value) >> 0x10) & 0xffff) -#define UINT32_LBITS(value) ((value) & 0xffff) -#define UINT32_GETBYTE(value, index) (((value) >> ((index)*8)) & 0xff) -#define UINT64_HBITS(value) (((value) >> 0x20) & 0xffffffff) -#define UINT64_LBITS(value) ((value) & 0xffffffff) - -static UINT8 WPS_DH_P_VALUE[192] = -{ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -}; - -static UINT8 WPS_DH_R_VALUE[193] = -{ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, -}; - -static UINT8 WPS_DH_X_VALUE[184] = -{ - 0x36, 0xf0, 0x25, 0x5d, 0xde, 0x97, 0x3d, 0xcb, - 0x3b, 0x39, 0x9d, 0x74, 0x7f, 0x23, 0xe3, 0x2e, - 0xd6, 0xfd, 0xb1, 0xf7, 0x75, 0x98, 0x33, 0x8b, - 0xfd, 0xf4, 0x41, 0x59, 0xc4, 0xec, 0x64, 0xdd, - 0xae, 0xb5, 0xf7, 0x86, 0x71, 0xcb, 0xfb, 0x22, - 0x10, 0x6a, 0xe6, 0x4c, 0x32, 0xc5, 0xbc, 0xe4, - 0xcf, 0xd4, 0xf5, 0x92, 0x0d, 0xa0, 0xeb, 0xc8, - 0xb0, 0x1e, 0xca, 0x92, 0x92, 0xae, 0x3d, 0xba, - 0x1b, 0x7a, 0x4a, 0x89, 0x9d, 0xa1, 0x81, 0x39, - 0x0b, 0xb3, 0xbd, 0x16, 0x59, 0xc8, 0x12, 0x94, - 0xf4, 0x00, 0xa3, 0x49, 0x0b, 0xf9, 0x48, 0x12, - 0x11, 0xc7, 0x94, 0x04, 0xa5, 0x76, 0x60, 0x5a, - 0x51, 0x60, 0xdb, 0xee, 0x83, 0xb4, 0xe0, 0x19, - 0xb6, 0xd7, 0x99, 0xae, 0x13, 0x1b, 0xa4, 0xc2, - 0x3d, 0xff, 0x83, 0x47, 0x5e, 0x9c, 0x40, 0xfa, - 0x67, 0x25, 0xb7, 0xc9, 0xe3, 0xaa, 0x2c, 0x65, - 0x96, 0xe9, 0xc0, 0x57, 0x02, 0xdb, 0x30, 0xa0, - 0x7c, 0x9a, 0xa2, 0xdc, 0x23, 0x5c, 0x52, 0x69, - 0xe3, 0x9d, 0x0c, 0xa9, 0xdf, 0x7a, 0xad, 0x44, - 0x61, 0x2a, 0xd6, 0xf8, 0x8f, 0x69, 0x69, 0x92, - 0x98, 0xf3, 0xca, 0xb1, 0xb5, 0x43, 0x67, 0xfb, - 0x0e, 0x8b, 0x93, 0xf7, 0x35, 0xdc, 0x8c, 0xd8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -}; - -static UINT8 WPS_DH_RRModP_VALUE[192] = -{ - 0xe3, 0xb3, 0x3c, 0x72, 0x59, 0x54, 0x1c, 0x01, - 0xee, 0x9c, 0x9a, 0x21, 0x6c, 0xc1, 0xeb, 0xd2, - 0xae, 0x59, 0x41, 0x04, 0x79, 0x29, 0xa1, 0xc7, - 0xe9, 0xc3, 0xfa, 0x02, 0xcc, 0x24, 0x56, 0xef, - 0x10, 0x26, 0x30, 0xfa, 0x9a, 0x36, 0xa5, 0x1f, - 0x57, 0xb5, 0x93, 0x48, 0x67, 0x98, 0x44, 0x60, - 0x0b, 0xe4, 0x96, 0x47, 0xa8, 0x7c, 0x7b, 0x37, - 0xf8, 0x05, 0x65, 0x64, 0x96, 0x9b, 0x7f, 0x02, - 0xdc, 0x54, 0x1a, 0x4e, 0xd4, 0x05, 0x3f, 0x54, - 0xd6, 0x2a, 0x0e, 0xea, 0xb2, 0x70, 0x52, 0x1b, - 0x22, 0xc2, 0x96, 0xe9, 0xd4, 0x6f, 0xec, 0x23, - 0x8e, 0x1a, 0xbd, 0x78, 0x02, 0x23, 0xb7, 0x6b, - 0xb8, 0xfe, 0x61, 0x21, 0x19, 0x6b, 0x7e, 0x88, - 0x1c, 0x72, 0x9c, 0x7e, 0x04, 0xb9, 0xf7, 0x96, - 0x07, 0xcd, 0x0a, 0x62, 0x8e, 0x43, 0x41, 0x30, - 0x04, 0xa5, 0x41, 0xff, 0x93, 0xae, 0x1c, 0xeb, - 0xb0, 0x04, 0xa7, 0x50, 0xdb, 0x10, 0x2d, 0x39, - 0xb9, 0x05, 0x2b, 0xb4, 0x7a, 0x58, 0xf1, 0x70, - 0x7e, 0x8c, 0xd2, 0xac, 0x98, 0xb5, 0xfb, 0x62, - 0x8f, 0x23, 0x31, 0xb1, 0x3b, 0x01, 0xe0, 0x18, - 0xf4, 0x66, 0xee, 0x5f, 0xbc, 0xd4, 0x9d, 0x68, - 0xd0, 0xab, 0x92, 0xe1, 0x83, 0x97, 0xf2, 0x45, - 0x8e, 0x0e, 0x3e, 0x21, 0x67, 0x47, 0x8c, 0x73, - 0xf1, 0x15, 0xd2, 0x7d, 0x32, 0xc6, 0x95, 0xe0, -}; - -static UINT8 Value_0[1] = {0x00}; -static UINT8 Value_1[1] = {0x01}; -static PBIG_INTEGER pBI_U = NULL, pBI_S = NULL, pBI_O = NULL; -static UINT Bits_Of_R = 0; - - -VOID BigInteger_Print ( - IN PBIG_INTEGER pBI) -{ - int i = 0, j = 0; - - if ((pBI == NULL) || (pBI->pIntegerArray == NULL)) - return; - - if (strlen(pBI->Name) != 0) - DEBUGPRINT("Name=%s\n", pBI->Name); - DEBUGPRINT("AllocSize=%d, ArrayLength=%d, IntegerLength=%d, Signed=%d\n", pBI->AllocSize, pBI->ArrayLength, pBI->IntegerLength, pBI->Signed); - for (i = (pBI->ArrayLength - 1), j = 0;i >=0;i--,j++) { - DEBUGPRINT("%08x, ", pBI->pIntegerArray[i]); - if ((j%8) == 7) - DEBUGPRINT("\n"); - } /* End od for */ - DEBUGPRINT("\n\n"); -} /* End of BigInteger_Print */ - - -VOID BigInteger_Init ( - INOUT PBIG_INTEGER *pBI) -{ - if (*pBI != NULL) - BigInteger_Free(pBI); - - if ((*pBI = (PBIG_INTEGER) kmalloc(sizeof(BIG_INTEGER), GFP_ATOMIC)) == NULL) { - DEBUGPRINT("BigInteger_Init: allocate %d bytes memory failure.\n", (sizeof(BIG_INTEGER))); - return; - } /* End of if */ - - NdisZeroMemory(*pBI, sizeof(BIG_INTEGER)); - (*pBI)->pIntegerArray = NULL; - (*pBI)->Signed = 1; -} /* End of BigInteger_Init */ - - -VOID BigInteger_Free_AllocSize ( - IN PBIG_INTEGER *pBI) -{ - if ((*pBI != NULL) && ((*pBI)->pIntegerArray != NULL)) { - kfree((*pBI)->pIntegerArray); - NdisZeroMemory(*pBI, sizeof(BIG_INTEGER)); - (*pBI)->pIntegerArray = NULL; - (*pBI)->Signed = 1; - } /* End of if */ -} /* End of BigInteger_Free_AllocSize */ - - -VOID BigInteger_Free ( - IN PBIG_INTEGER *pBI) -{ - if (*pBI != NULL) { - BigInteger_Free_AllocSize(pBI); - kfree(*pBI); - } /* End of if */ - - *pBI = NULL; -} /* End of BigInteger_Free */ - - -VOID BigInteger_AllocSize ( - IN PBIG_INTEGER *pBI, - IN UINT Length) -{ - UINT ArrayLength = 0; - - if (Length == 0) - return; - - if (*pBI == NULL) - BigInteger_Init(pBI); - - /* Caculate array size */ - ArrayLength = Length >> 0x2; - if ((Length & 0x3) != 0) - ArrayLength++; - - if (((*pBI)->pIntegerArray != NULL) && ((*pBI)->AllocSize < (sizeof(UINT32)*ArrayLength))) - BigInteger_Free_AllocSize(pBI); - - if ((*pBI)->pIntegerArray == NULL) { - if (((*pBI)->pIntegerArray = (UINT32 *) kmalloc(sizeof(UINT32)*ArrayLength, GFP_ATOMIC)) == NULL) { - DEBUGPRINT("BigInteger_AllocSize: allocate %d bytes memory failure.\n", (sizeof(UINT32)*ArrayLength)); - return; - } /* End of if */ - (*pBI)->AllocSize = sizeof(UINT32)*ArrayLength; - } /* End of if */ - - NdisZeroMemory((*pBI)->pIntegerArray, (*pBI)->AllocSize); - (*pBI)->ArrayLength = ArrayLength; - (*pBI)->IntegerLength = Length; -} /* End of BigInteger_AllocSize */ - - -VOID BigInteger_ClearHighBits ( - IN PBIG_INTEGER pBI) -{ - INT BIArrayIndex, ShiftIndex = 0; - UINT8 value; - - if ((pBI == NULL) || (pBI->pIntegerArray == NULL)) - return; - - BIArrayIndex = pBI->ArrayLength - 1; - while ((BIArrayIndex >= 0) && (pBI->pIntegerArray[BIArrayIndex] == 0)) - BIArrayIndex--; - - if (BIArrayIndex >= 0) { - value = 0; - ShiftIndex = 4; - while (value == 0) { - ShiftIndex--; - value = UINT32_GETBYTE(pBI->pIntegerArray[BIArrayIndex], ShiftIndex); - } /* End of while */ - } /* End of if */ - - if ((BIArrayIndex == -1) && (ShiftIndex == -1)) { - pBI->IntegerLength = 1; - pBI->ArrayLength = 1; - pBI->Signed = 1; - } else { - pBI->IntegerLength = (BIArrayIndex*4) + ShiftIndex + 1; - pBI->ArrayLength = BIArrayIndex + 1; - } /* End of if */ -} /* End of BigInteger_ClearHighBits */ - - -VOID BigInteger_BI2Bin ( - IN PBIG_INTEGER pBI, - OUT UINT8 *pValue, - OUT UINT *Length) -{ - INT ValueIndex, BIArrayIndex, ShiftIndex; - UINT32 Number; - - if (pBI == NULL) { - DEBUGPRINT("BigInteger_BI2Bin: pBI is NUll\n"); - *Length = 0; - return; - } /* End of if */ - - if (*Length < (sizeof(UINT8) * pBI->IntegerLength)) { - DEBUGPRINT("BigInteger_BI2Bin: length(%d) is not enough.\n", *Length); - *Length = 0; - return; - } /* End of if */ - - if (pBI->pIntegerArray == NULL) { - *Length = 0; - return; - } /* End of if */ - - BigInteger_ClearHighBits(pBI); - if ((ShiftIndex = pBI->IntegerLength & 0x3) == 0) - ShiftIndex = 4; - BIArrayIndex = pBI->ArrayLength - 1; - ValueIndex = 0; - - Number = pBI->pIntegerArray[BIArrayIndex]; - while (ValueIndex < pBI->IntegerLength) - { - pValue[ValueIndex++] = (UINT8) UINT32_GETBYTE(Number, ShiftIndex - 1); - if ((--ShiftIndex) == 0) { - ShiftIndex = 4; - BIArrayIndex--; - Number = pBI->pIntegerArray[BIArrayIndex]; - } /* End of if */ - } /* End of while */ - *Length = pBI->IntegerLength; -} /* End of BigInteger_BI2Bin */ - - -VOID BigInteger_Bin2BI ( - IN UINT8 *pValue, - IN UINT Length, - OUT PBIG_INTEGER *pBI) -{ - INT ValueIndex, BIArrayIndex, ShiftIndex; - UINT32 Number; - - BigInteger_AllocSize(pBI, Length); - - if ((*pBI)->pIntegerArray != NULL) { - Number = 0; - if ((ShiftIndex = Length & 0x3) == 0) - ShiftIndex = 4; - BIArrayIndex = (*pBI)->ArrayLength - 1; - ValueIndex = 0; - while (ValueIndex < Length) - { - Number = (Number << 8) | (UINT8) pValue[ValueIndex++]; - if ((--ShiftIndex) == 0) { - (*pBI)->pIntegerArray[BIArrayIndex] = Number; - ShiftIndex = 4; - BIArrayIndex--; - Number = 0; - } /* End of if */ - } /* End of while */ - } /* End of if */ -} /* End of BigInteger_Bin2BI */ - - -/* Calculate the bits of BigInteger, the highest bit is 1 */ -VOID BigInteger_BitsOfBI ( - IN PBIG_INTEGER pBI, - OUT UINT *Bits_Of_P) -{ - UINT32 Number, Index; - - Number = pBI->pIntegerArray[pBI->ArrayLength - 1]; - Index = 0; - while ((!(Number & 0x80000000)) && (Index < 32)) { - Number <<= 1; - Index++; - } /* End of while */ - *Bits_Of_P = (pBI->ArrayLength*sizeof(UINT32)) - Index; -} /* End of BigInteger_BitsOfBN */ - - -INT BigInteger_GetBitValue ( - IN PBIG_INTEGER pBI, - IN UINT Index) -{ - UINT Array = 0; - UINT Shift = 0; - - if (Index > 0) { - Array = (Index - 1) >> 0x5; - Shift = (Index - 1) & 0x1F; - } - if (Array > pBI->ArrayLength) - return 0; - - return ((pBI->pIntegerArray[Array] >> Shift) & 0x1); -} /* End of BigInteger_GetBitValue */ - - -UINT8 BigInteger_GetByteValue ( - IN PBIG_INTEGER pBI, - IN UINT Index) -{ - UINT Array = 0; - UINT Shift = 0; - - if (Index > 0) { - Array = (Index - 1) >> 0x2; - Shift = (Index - 1) & 0x3; - } - if ((Array > pBI->ArrayLength) || (Index > pBI->IntegerLength)) - return 0; - - - return (UINT8) UINT32_GETBYTE(pBI->pIntegerArray[Array], Shift - 1); -} /* End of BigInteger_GetByteValue */ - - -VOID BigInteger_Copy ( - IN PBIG_INTEGER pBI_Copied, - OUT PBIG_INTEGER *pBI_Result) -{ - BigInteger_AllocSize(pBI_Result, pBI_Copied->IntegerLength); - NdisCopyMemory((*pBI_Result)->pIntegerArray, pBI_Copied->pIntegerArray, (sizeof(UINT32)*(*pBI_Result)->ArrayLength)); - (*pBI_Result)->ArrayLength = pBI_Copied->ArrayLength; - (*pBI_Result)->IntegerLength = pBI_Copied->IntegerLength; - (*pBI_Result)->Signed = pBI_Copied->Signed; -} /* End of BigInteger_Copy */ - - -INT BigInteger_UnsignedCompare ( - IN PBIG_INTEGER pFirstOperand, - IN PBIG_INTEGER pSecondOperand) -{ - INT BIArrayIndex; - - if (pFirstOperand->IntegerLength > pSecondOperand->IntegerLength) - return 1; - - if (pFirstOperand->IntegerLength < pSecondOperand->IntegerLength) - return -1; - - if (pFirstOperand->IntegerLength == pSecondOperand->IntegerLength) { - for(BIArrayIndex = (pFirstOperand->ArrayLength - 1);BIArrayIndex >= 0 ; BIArrayIndex--) - { - if (pFirstOperand->pIntegerArray[BIArrayIndex] > pSecondOperand->pIntegerArray[BIArrayIndex]) - return 1; - else if (pFirstOperand->pIntegerArray[BIArrayIndex] < pSecondOperand->pIntegerArray[BIArrayIndex]) - return -1; - } /* End of for */ - } /* End of if */ - - return 0; -} /* End of BigInteger_Compare */ - - -VOID BigInteger_Add ( - IN PBIG_INTEGER pFirstOperand, - IN PBIG_INTEGER pSecondOperand, - OUT PBIG_INTEGER *pBI_Result) -{ - INT CompareResult; - UINT32 BIArrayIndex; - UINT64 Sum, Carry; - PBIG_INTEGER pTempBI = NULL; - - if ((pFirstOperand == NULL) || (pFirstOperand->pIntegerArray == NULL) - || (pSecondOperand == NULL) || (pSecondOperand->pIntegerArray == NULL)) { - DEBUGPRINT("BigInteger_Add: first or second operand is NULL.\n"); - return; - } /* End of if */ - - if (*pBI_Result == NULL) - BigInteger_Init(pBI_Result); - - CompareResult = BigInteger_UnsignedCompare(pFirstOperand, pSecondOperand); - if ((CompareResult == 0) & ((pFirstOperand->Signed * pSecondOperand->Signed) < 0)) { - BigInteger_AllocSize(pBI_Result, 1); - return ; - } /* End of if */ - - /* - * Singed table - * A + B || A > B || A < B - * ------------------------ - * + + || + || + - * + - || + || - - * - + || - || + - * - - || - || - - */ - if ((pFirstOperand->Signed * pSecondOperand->Signed) > 0) { - if (pFirstOperand->IntegerLength > pSecondOperand->IntegerLength) { - BigInteger_AllocSize(pBI_Result, pFirstOperand->IntegerLength + 1); - } else { - BigInteger_AllocSize(pBI_Result, pSecondOperand->IntegerLength + 1); - } /* End of if */ - - Carry = 0; - for (BIArrayIndex=0; BIArrayIndex < (*pBI_Result)->ArrayLength; BIArrayIndex++) - { - - Sum = 0; - if (BIArrayIndex < pFirstOperand->ArrayLength) - Sum += (UINT64) pFirstOperand->pIntegerArray[BIArrayIndex]; - - if (BIArrayIndex < pSecondOperand->ArrayLength) - Sum += (UINT64) pSecondOperand->pIntegerArray[BIArrayIndex]; - - Sum += Carry; - Carry = Sum >> 32; - (*pBI_Result)->pIntegerArray[BIArrayIndex] = (UINT32) (Sum & 0xffffffffUL); - } /* End of for */ - (*pBI_Result)->Signed = pFirstOperand->Signed; - BigInteger_ClearHighBits(*pBI_Result); - } else { - if ((pFirstOperand->Signed == 1) & (pSecondOperand->Signed == -1)) { - BigInteger_Copy(pSecondOperand, &pTempBI); - pTempBI->Signed = 1; - BigInteger_Sub(pFirstOperand, pTempBI, pBI_Result); - } else if ((pFirstOperand->Signed == -1) & (pSecondOperand->Signed == 1)) { - BigInteger_Copy(pFirstOperand, &pTempBI); - pTempBI->Signed = 1; - BigInteger_Sub(pSecondOperand, pTempBI, pBI_Result); - } /* End of if */ - } /* End of if */ - - BigInteger_Free(&pTempBI); -} /* End of BigInteger_Add */ - - -VOID BigInteger_Sub ( - IN PBIG_INTEGER pFirstOperand, - IN PBIG_INTEGER pSecondOperand, - OUT PBIG_INTEGER *pBI_Result) -{ - INT CompareResult; - UINT32 BIArrayIndex, Carry; - PBIG_INTEGER pTempBI = NULL, pTempBI2 = NULL; - - if ((pFirstOperand == NULL) || (pFirstOperand->pIntegerArray == NULL) - || (pSecondOperand == NULL) || (pSecondOperand->pIntegerArray == NULL)) { - DEBUGPRINT("BigInteger_Sub: first or second operand is NULL.\n"); - return; - } /* End of if */ - - if (*pBI_Result == NULL) - BigInteger_Init(pBI_Result); - - CompareResult = BigInteger_UnsignedCompare(pFirstOperand, pSecondOperand); - if ((CompareResult == 0) & ((pFirstOperand->Signed * pSecondOperand->Signed) > 0)) { - BigInteger_AllocSize(pBI_Result, 1); - return ; - } /* End of if */ - - BigInteger_Init(&pTempBI); - BigInteger_Init(&pTempBI2); - - /* - * Singed table - * A - B || A > B || A < B - * ------------------------ - * + + || + || - - * + - || + || + - * - + || - || - - * - - || - || + - */ - if ((pFirstOperand->Signed * pSecondOperand->Signed) > 0) { - if (CompareResult == 1) { - BigInteger_Copy(pFirstOperand, &pTempBI); - BigInteger_Copy(pSecondOperand, &pTempBI2); - } else if (CompareResult == -1) { - BigInteger_Copy(pSecondOperand, &pTempBI); - BigInteger_Copy(pFirstOperand, &pTempBI2); - } /* End of if */ - - BigInteger_Copy(pTempBI, pBI_Result); - Carry = 0; - for (BIArrayIndex=0; BIArrayIndex < (*pBI_Result)->ArrayLength; BIArrayIndex++) - { - if (BIArrayIndex < pTempBI2->ArrayLength) { - if ((*pBI_Result)->pIntegerArray[BIArrayIndex] >= (pTempBI2->pIntegerArray[BIArrayIndex] - Carry)) { - (*pBI_Result)->pIntegerArray[BIArrayIndex] = (*pBI_Result)->pIntegerArray[BIArrayIndex] - pTempBI2->pIntegerArray[BIArrayIndex] - Carry; - Carry = 0; - } else { - (*pBI_Result)->pIntegerArray[BIArrayIndex] = 0xffffffffUL - pTempBI2->pIntegerArray[BIArrayIndex] - Carry + (*pBI_Result)->pIntegerArray[BIArrayIndex] + 1; - Carry = 1; - } /* End of if */ - } else { - if ((*pBI_Result)->pIntegerArray[BIArrayIndex] >= Carry) { - (*pBI_Result)->pIntegerArray[BIArrayIndex] -= Carry; - Carry = 0; - } else { - (*pBI_Result)->pIntegerArray[BIArrayIndex] = 0xffffffffUL - Carry; - Carry = 1; - } /* End of if */ - } /* End of if */ - } /* End of for */ - - if (((pFirstOperand->Signed == 1) & (pSecondOperand->Signed == 1) & (CompareResult == -1)) - || ((pFirstOperand->Signed == -1) & (pSecondOperand->Signed == -1) & (CompareResult == 1))) - (*pBI_Result)->Signed = -1; - - BigInteger_ClearHighBits(*pBI_Result); - } else { - if ((pFirstOperand->Signed == 1) & (pSecondOperand->Signed == -1)) { - BigInteger_Copy(pSecondOperand, &pTempBI); - pTempBI->Signed = 1; - BigInteger_Add(pFirstOperand, pTempBI, pBI_Result); - } else if ((pFirstOperand->Signed == -1) & (pSecondOperand->Signed == 1)) { - BigInteger_Copy(pFirstOperand, &pTempBI); - pTempBI->Signed = 1; - BigInteger_Add(pTempBI, pSecondOperand, pBI_Result); - (*pBI_Result)->Signed = -1; - } /* End of if */ - } /* End of if */ - - BigInteger_Free(&pTempBI); - BigInteger_Free(&pTempBI2); -} /* End of BigInteger_Sub */ - - -VOID BigInteger_Mul ( - IN PBIG_INTEGER pFirstOperand, - IN PBIG_INTEGER pSecondOperand, - OUT PBIG_INTEGER *pBI_Result) -{ - - UINT32 BIFirstIndex, BISecondIndex; - UINT64 FirstValue, SecondValue, Sum, Carry; - - if ((pFirstOperand == NULL) || (pFirstOperand->pIntegerArray == NULL) - || (pSecondOperand == NULL) || (pSecondOperand->pIntegerArray == NULL)) { - DEBUGPRINT("BigInteger_Mul: first or second operand is NULL.\n"); - return; - } /* End of if */ - - /* The first or second operand is zero */ - if (((pFirstOperand->IntegerLength == 1) && (pFirstOperand->pIntegerArray[0] == 0)) - ||((pSecondOperand->IntegerLength == 1) && (pSecondOperand->pIntegerArray[0] == 0))) { - BigInteger_AllocSize(pBI_Result, 1); - goto output; - } /* End of if */ - - /* The first or second operand is one */ - if ((pFirstOperand->IntegerLength == 1) && (pFirstOperand->pIntegerArray[0] == 1)) { - BigInteger_Copy(pSecondOperand, pBI_Result); - goto output; - } /* End of if */ - if ((pSecondOperand->IntegerLength == 1) && (pSecondOperand->pIntegerArray[0] == 1)) { - BigInteger_Copy(pFirstOperand, pBI_Result); - goto output; - } /* End of if */ - - BigInteger_AllocSize(pBI_Result, pFirstOperand->IntegerLength + pSecondOperand->IntegerLength); - - for (BIFirstIndex=0; BIFirstIndex < pFirstOperand->ArrayLength; BIFirstIndex++) - { - Carry = 0; - FirstValue = (UINT64) pFirstOperand->pIntegerArray[BIFirstIndex]; - if (FirstValue == 0) { - continue; - } else { - for (BISecondIndex=0; BISecondIndex < pSecondOperand->ArrayLength; BISecondIndex++) - { - SecondValue = ((UINT64) pSecondOperand->pIntegerArray[BISecondIndex])*FirstValue; - Sum = (UINT64) ((*pBI_Result)->pIntegerArray[BIFirstIndex + BISecondIndex] + SecondValue + Carry); - Carry = Sum >> 32; - (*pBI_Result)->pIntegerArray[BIFirstIndex + BISecondIndex] = (UINT32) (Sum & 0xffffffffUL); - } /* End of for */ - while (Carry != 0) { - Sum = (UINT64) (*pBI_Result)->pIntegerArray[BIFirstIndex + BISecondIndex]; - Sum += Carry; - - Carry = Sum >> 32; - (*pBI_Result)->pIntegerArray[BIFirstIndex + BISecondIndex] = (UINT32) (Sum & 0xffffffffUL); - BISecondIndex++; - } /* End of while */ - } /* End of if */ - } /* End of for */ - -output: - (*pBI_Result)->Signed = pFirstOperand->Signed * pSecondOperand->Signed; - BigInteger_ClearHighBits(*pBI_Result); -} /* End of BigInteger_Mul */ - - -VOID BigInteger_Square ( - IN PBIG_INTEGER pBI, - OUT PBIG_INTEGER *pBI_Result) -{ - INT BIFirstIndex, BISecondIndex; - UINT32 HBITS_Value, LBITS_Value, Temp1_Value, Temp2_Value, Carry32; - UINT32 *Point_Of_S, *Point_Of_Result, *Point_Of_BI; - UINT64 Result64_1, Result64_2, Carry64, TempValue64; - - if ((pBI == NULL) || (pBI->pIntegerArray == NULL)) { - DEBUGPRINT("\tBigInteger_Square: the operand is NULL.\n"); - return; - } /* End of if */ - - /* The operand is zero */ - if ((pBI->IntegerLength == 1) && (pBI->pIntegerArray[0] == 0)) { - BigInteger_AllocSize(pBI_Result, 1); - goto output; - } /* End of if */ - - BigInteger_AllocSize(pBI_Result, (pBI->IntegerLength*2) + 20); - BigInteger_AllocSize(&pBI_S, (pBI->IntegerLength*2) + 20); - BigInteger_AllocSize(&pBI_O, (pBI->IntegerLength*2) + 20); - - /* - * Input: pBI = {a_0, a_1, a_2, a_3, ..., a_n} - * Step1. calculate a_0^2, a_1^2, a_2^2, a_3^2 ... a_n^2 - */ - Point_Of_S = pBI_S->pIntegerArray; - for (BIFirstIndex=0; BIFirstIndex < pBI->ArrayLength; BIFirstIndex++) - { - HBITS_Value = UINT32_HBITS(pBI->pIntegerArray[BIFirstIndex]); - LBITS_Value = UINT32_LBITS(pBI->pIntegerArray[BIFirstIndex]); - Temp1_Value = HBITS_Value*LBITS_Value; - Temp2_Value = (Temp1_Value & 0x7fff) << 0x11; - Point_Of_S[0] = (LBITS_Value*LBITS_Value) + Temp2_Value; - Point_Of_S[1] = (HBITS_Value*HBITS_Value) + ((Temp1_Value >> 0xf) & 0x1ffff); - if (Point_Of_S[0] < Temp2_Value) - Point_Of_S[1] += 1; - - Point_Of_S += 2; - } /* End of for */ - - /* - * Step2. calculate a_0*{a_1, a_2, a_3, a_4, ..., a_n} - */ - Point_Of_BI = pBI->pIntegerArray; - Point_Of_Result = (*pBI_Result)->pIntegerArray; - Point_Of_Result[0] = 0; - TempValue64 = (UINT64) Point_Of_BI[0]; - Point_Of_Result++; - Carry64 = 0; - for (BIFirstIndex=1; BIFirstIndex < pBI->ArrayLength; BIFirstIndex++) - { - Result64_1 = (UINT64) Point_Of_BI[BIFirstIndex]*TempValue64; - Result64_1 += Carry64; - Carry64 = (Result64_1 >> 32); - Point_Of_Result[0] = (UINT32) (Result64_1 & 0xffffffffUL); - Point_Of_Result++; - } /* End of for */ - if (Carry64 > 0) - Point_Of_Result[0] = (UINT32) (Carry64 & 0xffffffffUL); - - /* - * Step3. calculate - * a_1*{a_2, a_3, a_4, ..., a_n} - * a_2*{a_3, a_4, a_5, ..., a_n} - * a_3*{a_4, a_5, a_6, ..., a_n} - * a_4*{a_5, a_6, a_7, ..., a_n} - * ... - * a_n-1*{a_n} - */ - Point_Of_BI = pBI->pIntegerArray; - for (BIFirstIndex=1; BIFirstIndex < (pBI->ArrayLength - 1); BIFirstIndex++) - { - Point_Of_Result = (*pBI_Result)->pIntegerArray; - Point_Of_Result += (BIFirstIndex*2) + 1; - TempValue64 = (UINT64) Point_Of_BI[BIFirstIndex]; - Carry64 = 0; - for (BISecondIndex=(BIFirstIndex + 1); BISecondIndex < pBI->ArrayLength; BISecondIndex++) - { - Result64_1 = ((UINT64) Point_Of_Result[0]) + Carry64; - Result64_2 = (UINT64) Point_Of_BI[BISecondIndex]*TempValue64; - Carry64 = (Result64_1 >> 32); - Result64_1 = (Result64_1 & 0xffffffffUL); - Result64_1 = Result64_1 + Result64_2; - Carry64 += (Result64_1 >> 32); - Point_Of_Result[0] = (UINT32) (Result64_1 & 0xffffffffUL); - Point_Of_Result++; - } /* End of for */ - if (Carry64 > 0) - Point_Of_Result[0] += (UINT32) (Carry64 & 0xffffffffUL); - } /* End of for */ - - BigInteger_ClearHighBits(*pBI_Result); - BigInteger_Copy(*pBI_Result, &pBI_O); - - Carry32 = 0; - for (BIFirstIndex=0; BIFirstIndex < pBI_O->ArrayLength; BIFirstIndex++) { - pBI_O->pIntegerArray[BIFirstIndex] = (pBI_O->pIntegerArray[BIFirstIndex] << 1) | Carry32; - if (pBI_O->pIntegerArray[BIFirstIndex] < (*pBI_Result)->pIntegerArray[BIFirstIndex]) - Carry32 = 1; - else - Carry32 = 0; - } /* End of for */ - pBI_O->pIntegerArray[BIFirstIndex] = Carry32; - pBI_O->IntegerLength++; - pBI_O->ArrayLength++; - BigInteger_ClearHighBits(pBI_O); - - BigInteger_Add(pBI_O, pBI_S, pBI_Result); -output: - (*pBI_Result)->Signed = 1; - BigInteger_ClearHighBits(*pBI_Result); -} /* End of BigInteger_Square */ - - -VOID BigInteger_Div ( - IN PBIG_INTEGER pFirstOperand, - IN PBIG_INTEGER pSecondOperand, - OUT PBIG_INTEGER *pBI_Result, - OUT PBIG_INTEGER *pBI_Remainder) -{ - INT CompareResult; - INT Index, MulIndex, ComputeSize; - UINT32 MulStart; - UINT AllocLength, ArrayIndex, ShiftIndex; - PBIG_INTEGER pTempBI = NULL, pTempBI2 = NULL, pMulBI = NULL; - UINT8 SecondHighByte; - - if ((pFirstOperand == NULL) || (pFirstOperand->pIntegerArray == NULL) - || (pSecondOperand == NULL) || (pSecondOperand->pIntegerArray == NULL)) { - DEBUGPRINT("BigInteger_Div: first or second operand is NULL.\n"); - return; - } /* End of if */ - - /* The second operand is zero */ - if ((pSecondOperand->IntegerLength == 1) && (pSecondOperand->pIntegerArray[0] == 0)) { - DEBUGPRINT("BigInteger_Div: second operand is zero.\n"); - return; - } /* End of if */ - - if (*pBI_Result == NULL) - BigInteger_Init(pBI_Result); - if (*pBI_Remainder == NULL) - BigInteger_Init(pBI_Remainder); - - /* The second operand is one */ - if ((pSecondOperand->IntegerLength == 1) && (pSecondOperand->pIntegerArray[0] == 1)) { - BigInteger_Copy(pFirstOperand, pBI_Result); - BigInteger_Bin2BI(Value_0, 1, pBI_Remainder); - goto output; - } /* End of if */ - - CompareResult = BigInteger_UnsignedCompare(pFirstOperand, pSecondOperand); - if (CompareResult == 0) { - BigInteger_Bin2BI(Value_1, 1, pBI_Result); - BigInteger_Bin2BI(Value_0, 1, pBI_Remainder); - goto output; - } else if (CompareResult == -1) { - BigInteger_Bin2BI(Value_0, 1, pBI_Result); - BigInteger_Copy(pFirstOperand, pBI_Remainder); - goto output; - } /* End of if */ - BigInteger_AllocSize(pBI_Result, pFirstOperand->IntegerLength - pSecondOperand->IntegerLength + 1); - BigInteger_AllocSize(pBI_Remainder, pSecondOperand->IntegerLength); - - AllocLength = (UINT) (pFirstOperand->IntegerLength << 1); - BigInteger_AllocSize(&pTempBI, AllocLength); - BigInteger_AllocSize(&pTempBI2, AllocLength); - BigInteger_AllocSize(&pMulBI, AllocLength); - - BigInteger_Copy(pFirstOperand, pBI_Remainder); - SecondHighByte = BigInteger_GetByteValue(pSecondOperand, pSecondOperand->IntegerLength); - ComputeSize = (INT) pFirstOperand->IntegerLength - pSecondOperand->IntegerLength + 1; - for (Index = (INT) ComputeSize;Index >= 0;Index--) { - if (BigInteger_UnsignedCompare(*pBI_Remainder, pSecondOperand) == -1) - break; - - if (((pSecondOperand->IntegerLength + Index) - (*pBI_Remainder)->IntegerLength) <= 1) { - BigInteger_AllocSize(&pMulBI, Index + 1); - ArrayIndex = 0; - if (Index > 0) - ArrayIndex = (UINT) (Index - 1) >> 2 ; - ShiftIndex = (Index & 0x03); - if (ShiftIndex == 0) - ShiftIndex = 4; - ShiftIndex--; - MulStart = 0; - MulStart = (BigInteger_GetByteValue((*pBI_Remainder), pFirstOperand->IntegerLength + Index - ComputeSize + 1) & 0xFF) << 8; - MulStart = MulStart | (BigInteger_GetByteValue((*pBI_Remainder), pFirstOperand->IntegerLength + Index - ComputeSize) & 0xFF); - if (MulStart < (UINT32) SecondHighByte) - continue; - - MulStart = MulStart / (UINT32) SecondHighByte; - - if (MulStart > 0xFF) - MulStart = 0x100; - - for (MulIndex = (INT) MulStart;MulIndex <= 0x101;MulIndex++) { /* 0xFFFF / 0xFF = 0x101 */ - if ((MulIndex > 0xFF) && (ShiftIndex == 3)) - pMulBI->pIntegerArray[ArrayIndex + 1] = 0x01; - pMulBI->pIntegerArray[ArrayIndex] = ((UINT) MulIndex << (8*ShiftIndex)); - BigInteger_Mul(pSecondOperand, pMulBI , &pTempBI); - CompareResult = BigInteger_UnsignedCompare(*pBI_Remainder, pTempBI); - if (CompareResult < 1) { - if (MulIndex > 1) { - if (CompareResult != 0) { - if ((MulIndex == 0x100) && (ShiftIndex == 3)) - pMulBI->pIntegerArray[ArrayIndex + 1] = 0; - pMulBI->pIntegerArray[ArrayIndex] = ((UINT) (MulIndex - 1) << (8*ShiftIndex)); - } /* End of if */ - - BigInteger_Mul(pSecondOperand, pMulBI, &pTempBI); - BigInteger_Sub(*pBI_Remainder, pTempBI, &pTempBI2); - BigInteger_Copy(pTempBI2, pBI_Remainder); - BigInteger_Add(*pBI_Result, pMulBI, &pTempBI2); - BigInteger_Copy(pTempBI2, pBI_Result); - } /* End of if */ - break; - } /* End of if */ - - if ((MulIndex >= 0x100) && (ShiftIndex == 3)) - pMulBI->pIntegerArray[ArrayIndex++] = 0; - pMulBI->pIntegerArray[ArrayIndex] = 0; - } /* End of for */ - } /* End of if */ - } /* End of for */ - - BigInteger_Free(&pTempBI); - BigInteger_Free(&pTempBI2); - BigInteger_Free(&pMulBI); -output: - (*pBI_Result)->Signed = pFirstOperand->Signed * pSecondOperand->Signed; - (*pBI_Remainder)->Signed = pFirstOperand->Signed * pSecondOperand->Signed; - BigInteger_ClearHighBits(*pBI_Result); - BigInteger_ClearHighBits(*pBI_Remainder); -} /* End of BigInteger_Div */ - - -VOID BigInteger_Montgomery_Reduction ( - IN PBIG_INTEGER pBI_A, - IN PBIG_INTEGER pBI_P, - IN PBIG_INTEGER pBI_R, - OUT PBIG_INTEGER *pBI_Result) -{ - UINT32 *Point_P, *Point_Result; - UINT32 LoopCount; - UINT64 Result64_1, Result64_2, Carry64, TempValue64; - INT FirstLoop, SecondLoop; - - BigInteger_AllocSize(pBI_Result, pBI_A->IntegerLength+ pBI_P->IntegerLength + 20); - BigInteger_Copy(pBI_A, pBI_Result); - - Point_P = pBI_P->pIntegerArray; - Point_Result = (*pBI_Result)->pIntegerArray; - - LoopCount = Bits_Of_R >> 0x5; - for (FirstLoop = 0;FirstLoop < LoopCount;FirstLoop++) { - Carry64 = 0; - TempValue64 = (UINT64) Point_Result[0]; - for (SecondLoop = 0;SecondLoop < pBI_P->ArrayLength;SecondLoop++) { - Result64_1 = ((UINT64) Point_Result[SecondLoop]) + Carry64; - Result64_2 = (UINT64) Point_P[SecondLoop]*TempValue64; - Carry64 = (Result64_1 >> 32); - Result64_1 = (Result64_1 & 0xffffffffUL); - Result64_1 = Result64_1 + Result64_2; - Carry64 += (Result64_1 >> 32); - Point_Result[SecondLoop] = (UINT32) (Result64_1 & 0xffffffffUL); - } /* End of for */ - while (Carry64 != 0) { - Result64_1 = ((UINT64) Point_Result[SecondLoop]) + Carry64; - Carry64 = Result64_1 >> 32; - Point_Result[SecondLoop] = (UINT32) (Result64_1 & 0xffffffffUL); - SecondLoop++; - } /* End of while */ - Point_Result++; - } /* End of for */ - - for (FirstLoop = 0;FirstLoop <= LoopCount;FirstLoop++) { - (*pBI_Result)->pIntegerArray[FirstLoop] = (*pBI_Result)->pIntegerArray[FirstLoop + LoopCount]; - } /* End of for */ - if ((*pBI_Result)->pIntegerArray[LoopCount] != 0) - (*pBI_Result)->ArrayLength = LoopCount + 1; - else - (*pBI_Result)->ArrayLength = LoopCount; - - (*pBI_Result)->IntegerLength = (*pBI_Result)->ArrayLength*4; - BigInteger_ClearHighBits(*pBI_Result); - - if (BigInteger_UnsignedCompare(*pBI_Result, pBI_P) >= 0) { - BigInteger_Sub(*pBI_Result, pBI_P, &pBI_U); - BigInteger_Copy(pBI_U, pBI_Result); - } /* End of if */ - BigInteger_ClearHighBits(*pBI_Result); -} /* End of BigInteger_Montgomery_Reduction */ - - -VOID BigInteger_Montgomery_ExpMod ( - IN PBIG_INTEGER pBI_G, - IN PBIG_INTEGER pBI_E, - IN PBIG_INTEGER pBI_P, - OUT PBIG_INTEGER *pBI_Result) -{ - UINT Bits_Of_P; - UINT32 Index, Index2, AllocLength; - UINT32 Sliding_Value , Sliding_HighValue, Sliding_LowValue; - PBIG_INTEGER pBI_Temp1 = NULL, pBI_Temp2 = NULL; - PBIG_INTEGER pBI_X = NULL, pBI_R = NULL, pBI_RR = NULL, pBI_1 = NULL; - BIG_INTEGER *pBI_A[SLIDING_WINDOW]; - UINT8 *pRValue = NULL; - - AllocLength = (pBI_G->IntegerLength + pBI_E->IntegerLength + pBI_P->IntegerLength + 300); - BigInteger_AllocSize(&pBI_Temp1, AllocLength); - BigInteger_AllocSize(&pBI_Temp2, AllocLength); - - /* Calculate the bits of P and E, the highest bit is 1 */ - BigInteger_BitsOfBI(pBI_P, &Bits_Of_P); - - if ((pBI_E->IntegerLength == 1) && (pBI_E->pIntegerArray[0] == 1)) { - BigInteger_Div(pBI_G, pBI_P, &pBI_Temp1, pBI_Result); - goto memory_free; - } /* End of if */ - - if ((pBI_E->IntegerLength == 1) && (pBI_E->pIntegerArray[0] == 2)) { - BigInteger_Mul(pBI_G, pBI_G, &pBI_Temp1); - BigInteger_Div(pBI_Temp1, pBI_P, &pBI_Temp2, pBI_Result); - goto memory_free; - } /* End of if */ - - /* - * Main algorithm - */ - BigInteger_Init(&pBI_R); - BigInteger_Init(&pBI_RR); - BigInteger_Bin2BI(Value_1, 1, &pBI_1); - BigInteger_AllocSize(&pBI_X, AllocLength); - BigInteger_AllocSize(&pBI_U, AllocLength); // for BigInteger_Montgomery_Reduction - BigInteger_AllocSize(&pBI_S, AllocLength); // for BigInteger_Square - BigInteger_AllocSize(&pBI_O, AllocLength); // for BigInteger_Square - - for (Index = 0; Index < SLIDING_WINDOW; Index++) { - pBI_A[Index] = NULL; - BigInteger_AllocSize(&pBI_A[Index], 193); - } /* End of for */ - BigInteger_Bin2BI(WPS_DH_P_VALUE, 192, &pBI_Temp1); - if (NdisCmpMemory(pBI_P->pIntegerArray, pBI_Temp1->pIntegerArray, pBI_P->IntegerLength) == 0) { - BigInteger_Bin2BI(WPS_DH_X_VALUE, 184, &pBI_X); - BigInteger_Bin2BI(WPS_DH_R_VALUE, 193, &pBI_R); - BigInteger_Bin2BI(WPS_DH_RRModP_VALUE, 192, &pBI_RR); - Bits_Of_R = 1537; - } else { - if ((Bits_Of_P % 8) == 0) { - AllocLength = pBI_P->IntegerLength + 1; - } else { - AllocLength = pBI_P->IntegerLength; - } /* End of if */ - pRValue = (UINT8 *) kmalloc(sizeof(UINT8)*AllocLength, GFP_ATOMIC); - if (pRValue == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); - goto memory_free; - } - NdisZeroMemory(pRValue, sizeof(UINT8)*AllocLength); - pRValue[0] = (UINT8) (1 << (Bits_Of_P & 0x7)); - BigInteger_Bin2BI(pRValue, AllocLength , &pBI_R); - - BigInteger_Mul(pBI_R, pBI_R, &pBI_Temp1); - BigInteger_Div(pBI_Temp1, pBI_P, &pBI_A[1], &pBI_RR); - - /* X = 1*R (mod P) */ - BigInteger_Div(pBI_R, pBI_P, &pBI_Temp2, &pBI_X); - } /* End of if */ - - /* A = G*R (mod P) => A = MonMod(G, R^2 mod P) */ - BigInteger_Mul(pBI_G, pBI_RR, &pBI_Temp1); - BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P , pBI_R, &pBI_A[1]); - for (Index = 2; Index < SLIDING_WINDOW; Index++) { - BigInteger_Mul(pBI_A[Index - 1], pBI_A[1], &pBI_Temp1); - BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_A[Index]); - } /* End of for */ - - for (Index = pBI_E->IntegerLength ; Index > 0 ; Index--) { - for (Index2 = 0; Index2 < 4 ; Index2++) { - BigInteger_Square(pBI_X, &pBI_Temp1); - BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_X); - } /* End of for */ - - Sliding_Value = BigInteger_GetByteValue(pBI_E, Index); - Sliding_HighValue = (Sliding_Value >> 4); - if (Sliding_HighValue != 0) { - BigInteger_Mul(pBI_A[Sliding_HighValue], pBI_X, &pBI_Temp1); - BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_X); - } /* End of if */ - - for (Index2 = 0; Index2 < 4 ; Index2++) { - BigInteger_Square(pBI_X, &pBI_Temp1); - BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_X); - } /* End of for */ - - Sliding_LowValue = Sliding_Value & 0x0f; - if (Sliding_LowValue != 0) { - BigInteger_Mul(pBI_A[Sliding_LowValue], pBI_X, &pBI_Temp1); - BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_X); - } /* End of if */ - } /* End of for */ - BigInteger_Montgomery_Reduction(pBI_X, pBI_P , pBI_R, pBI_Result); - - BigInteger_Free(&pBI_X); - BigInteger_Free(&pBI_R); - BigInteger_Free(&pBI_RR); - BigInteger_Free(&pBI_1); - BigInteger_Free(&pBI_U); - BigInteger_Free(&pBI_S); - BigInteger_Free(&pBI_O); - for(Index = 0; Index < SLIDING_WINDOW; Index++) - BigInteger_Free(&pBI_A[Index]); - if (pRValue != NULL) - kfree(pRValue); - -memory_free: - BigInteger_Free(&pBI_Temp1); - BigInteger_Free(&pBI_Temp2); -} /* End of BigInteger_Montgomery_ExpMod */ - -/* End of crypt_biginteger.c */ diff --git a/drivers/staging/rt3090/common/crypt_dh.c b/drivers/staging/rt3090/common/crypt_dh.c deleted file mode 100644 index 0f69f2af903874745dcc39c9f5223339b21d091e..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/crypt_dh.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - crypt_dh.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Eddy 2009/01/19 Create AES-128, AES-192, AES-256, AES-CBC -*/ - -#include "crypt_dh.h" -#include "crypt_biginteger.h" - -/* -======================================================================== -Routine Description: - Diffie-Hellman public key generation - -Arguments: - GValue Array in UINT8 - GValueLength The length of G in bytes - PValue Array in UINT8 - PValueLength The length of P in bytes - PrivateKey Private key - PrivateKeyLength The length of Private key in bytes - -Return Value: - PublicKey Public key - PublicKeyLength The length of public key in bytes - -Note: - Reference to RFC2631 - PublicKey = G^PrivateKey (mod P) -======================================================================== -*/ -void DH_PublicKey_Generate ( - IN UINT8 GValue[], - IN UINT GValueLength, - IN UINT8 PValue[], - IN UINT PValueLength, - IN UINT8 PrivateKey[], - IN UINT PrivateKeyLength, - OUT UINT8 PublicKey[], - INOUT UINT *PublicKeyLength) -{ - PBIG_INTEGER pBI_G = NULL; - PBIG_INTEGER pBI_P = NULL; - PBIG_INTEGER pBI_PrivateKey = NULL; - PBIG_INTEGER pBI_PublicKey = NULL; - - /* - * 1. Check the input parameters - * - GValueLength, PValueLength and PrivateLength must be large than zero - * - PublicKeyLength must be large or equal than PValueLength - * - PValue must be odd - * - * - PValue must be prime number (no implement) - * - GValue must be greater than 0 but less than the PValue (no implement) - */ - if (GValueLength == 0) { - DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: G length is (%d)\n", GValueLength)); - return; - } /* End of if */ - if (PValueLength == 0) { - DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: P length is (%d)\n", PValueLength)); - return; - } /* End of if */ - if (PrivateKeyLength == 0) { - DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: private key length is (%d)\n", PrivateKeyLength)); - return; - } /* End of if */ - if (*PublicKeyLength < PValueLength) { - DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: public key length(%d) must be large or equal than P length(%d)\n", - *PublicKeyLength, PValueLength)); - return; - } /* End of if */ - if (!(PValue[PValueLength - 1] & 0x1)) { - DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: P value must be odd\n")); - return; - } /* End of if */ - - /* - * 2. Transfer parameters to BigInteger structure - */ - BigInteger_Init(&pBI_G); - BigInteger_Init(&pBI_P); - BigInteger_Init(&pBI_PrivateKey); - BigInteger_Init(&pBI_PublicKey); - BigInteger_Bin2BI(GValue, GValueLength, &pBI_G); - BigInteger_Bin2BI(PValue, PValueLength, &pBI_P); - BigInteger_Bin2BI(PrivateKey, PrivateKeyLength, &pBI_PrivateKey); - - /* - * 3. Calculate PublicKey = G^PrivateKey (mod P) - * - BigInteger Operation - * - Montgomery reduction - */ - BigInteger_Montgomery_ExpMod(pBI_G, pBI_PrivateKey, pBI_P, &pBI_PublicKey); - - /* - * 4. Transfer BigInteger structure to char array - */ - BigInteger_BI2Bin(pBI_PublicKey, PublicKey, PublicKeyLength); - - BigInteger_Free(&pBI_G); - BigInteger_Free(&pBI_P); - BigInteger_Free(&pBI_PrivateKey); - BigInteger_Free(&pBI_PublicKey); -} /* End of DH_PublicKey_Generate */ - - -/* -======================================================================== -Routine Description: - Diffie-Hellman secret key generation - -Arguments: - PublicKey Public key - PublicKeyLength The length of Public key in bytes - PValue Array in UINT8 - PValueLength The length of P in bytes - PrivateKey Private key - PrivateKeyLength The length of Private key in bytes - -Return Value: - SecretKey Secret key - SecretKeyLength The length of secret key in bytes - -Note: - Reference to RFC2631 - SecretKey = PublicKey^PrivateKey (mod P) -======================================================================== -*/ -void DH_SecretKey_Generate ( - IN UINT8 PublicKey[], - IN UINT PublicKeyLength, - IN UINT8 PValue[], - IN UINT PValueLength, - IN UINT8 PrivateKey[], - IN UINT PrivateKeyLength, - OUT UINT8 SecretKey[], - INOUT UINT *SecretKeyLength) -{ - PBIG_INTEGER pBI_P = NULL; - PBIG_INTEGER pBI_SecretKey = NULL; - PBIG_INTEGER pBI_PrivateKey = NULL; - PBIG_INTEGER pBI_PublicKey = NULL; - - /* - * 1. Check the input parameters - * - PublicKeyLength, PValueLength and PrivateLength must be large than zero - * - SecretKeyLength must be large or equal than PValueLength - * - PValue must be odd - * - * - PValue must be prime number (no implement) - */ - if (PublicKeyLength == 0) { - DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: public key length is (%d)\n", PublicKeyLength)); - return; - } /* End of if */ - if (PValueLength == 0) { - DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: P length is (%d)\n", PValueLength)); - return; - } /* End of if */ - if (PrivateKeyLength == 0) { - DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: private key length is (%d)\n", PrivateKeyLength)); - return; - } /* End of if */ - if (*SecretKeyLength < PValueLength) { - DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: secret key length(%d) must be large or equal than P length(%d)\n", - *SecretKeyLength, PValueLength)); - return; - } /* End of if */ - if (!(PValue[PValueLength - 1] & 0x1)) { - DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: P value must be odd\n")); - return; - } /* End of if */ - - /* - * 2. Transfer parameters to BigInteger structure - */ - BigInteger_Init(&pBI_P); - BigInteger_Init(&pBI_PrivateKey); - BigInteger_Init(&pBI_PublicKey); - BigInteger_Init(&pBI_SecretKey); - - BigInteger_Bin2BI(PublicKey, PublicKeyLength, &pBI_PublicKey); - BigInteger_Bin2BI(PValue, PValueLength, &pBI_P); - BigInteger_Bin2BI(PrivateKey, PrivateKeyLength, &pBI_PrivateKey); - - /* - * 3. Calculate SecretKey = PublicKey^PrivateKey (mod P) - * - BigInteger Operation - * - Montgomery reduction - */ - BigInteger_Montgomery_ExpMod(pBI_PublicKey, pBI_PrivateKey, pBI_P, &pBI_SecretKey); - - /* - * 4. Transfer BigInteger structure to char array - */ - BigInteger_BI2Bin(pBI_SecretKey, SecretKey, SecretKeyLength); - - BigInteger_Free(&pBI_P); - BigInteger_Free(&pBI_PrivateKey); - BigInteger_Free(&pBI_PublicKey); - BigInteger_Free(&pBI_SecretKey); -} /* End of DH_SecretKey_Generate */ diff --git a/drivers/staging/rt3090/common/crypt_hmac.c b/drivers/staging/rt3090/common/crypt_hmac.c deleted file mode 100644 index e2854082f1d9774df7edc333338495b47452382f..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/crypt_hmac.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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 "../crypt_hmac.h" - - -#ifdef HMAC_SHA1_SUPPORT -/* -======================================================================== -Routine Description: - HMAC using SHA1 hash function - -Arguments: - key Secret key - key_len The length of the key in bytes - message Message context - message_len The length of message in bytes - macLen Request the length of message authentication code - -Return Value: - mac Message authentication code - -Note: - None -======================================================================== -*/ -VOID HMAC_SHA1 ( - IN const UINT8 Key[], - IN UINT KeyLen, - IN const UINT8 Message[], - IN UINT MessageLen, - OUT UINT8 MAC[], - IN UINT MACLen) -{ - SHA1_CTX_STRUC sha_ctx1; - SHA1_CTX_STRUC sha_ctx2; - UINT8 K0[SHA1_BLOCK_SIZE]; - UINT8 Digest[SHA1_DIGEST_SIZE]; - UINT index; - - NdisZeroMemory(&sha_ctx1, sizeof(SHA1_CTX_STRUC)); - NdisZeroMemory(&sha_ctx2, sizeof(SHA1_CTX_STRUC)); - /* - * If the length of K = B(Block size): K0 = K. - * If the length of K > B: hash K to obtain an L byte string, - * then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00). - * If the length of K < B: append zeros to the end of K to create a B-byte string K0 - */ - NdisZeroMemory(K0, SHA1_BLOCK_SIZE); - if (KeyLen <= SHA1_BLOCK_SIZE) - NdisMoveMemory(K0, Key, KeyLen); - else - RT_SHA1(Key, KeyLen, K0); - /* End of if */ - - /* Exclusive-Or K0 with ipad */ - /* ipad: Inner pad; the byte x��36�� repeated B times. */ - for (index = 0; index < SHA1_BLOCK_SIZE; index++) - K0[index] ^= 0x36; - /* End of for */ - - SHA1_Init(&sha_ctx1); - /* H(K0^ipad) */ - SHA1_Append(&sha_ctx1, K0, sizeof(K0)); - /* H((K0^ipad)||text) */ - SHA1_Append(&sha_ctx1, Message, MessageLen); - SHA1_End(&sha_ctx1, Digest); - - /* Exclusive-Or K0 with opad and remove ipad */ - /* opad: Outer pad; the byte x��5c�� repeated B times. */ - for (index = 0; index < SHA1_BLOCK_SIZE; index++) - K0[index] ^= 0x36^0x5c; - /* End of for */ - - SHA1_Init(&sha_ctx2); - /* H(K0^opad) */ - SHA1_Append(&sha_ctx2, K0, sizeof(K0)); - /* H( (K0^opad) || H((K0^ipad)||text) ) */ - SHA1_Append(&sha_ctx2, Digest, SHA1_DIGEST_SIZE); - SHA1_End(&sha_ctx2, Digest); - - if (MACLen > SHA1_DIGEST_SIZE) - NdisMoveMemory(MAC, Digest, SHA1_DIGEST_SIZE); - else - NdisMoveMemory(MAC, Digest, MACLen); -} /* End of HMAC_SHA1 */ -#endif /* HMAC_SHA1_SUPPORT */ - - -#ifdef HMAC_SHA256_SUPPORT -/* -======================================================================== -Routine Description: - HMAC using SHA256 hash function - -Arguments: - key Secret key - key_len The length of the key in bytes - message Message context - message_len The length of message in bytes - macLen Request the length of message authentication code - -Return Value: - mac Message authentication code - -Note: - None -======================================================================== -*/ -VOID HMAC_SHA256 ( - IN const UINT8 Key[], - IN UINT KeyLen, - IN const UINT8 Message[], - IN UINT MessageLen, - OUT UINT8 MAC[], - IN UINT MACLen) -{ - SHA256_CTX_STRUC sha_ctx1; - SHA256_CTX_STRUC sha_ctx2; - UINT8 K0[SHA256_BLOCK_SIZE]; - UINT8 Digest[SHA256_DIGEST_SIZE]; - UINT index; - - NdisZeroMemory(&sha_ctx1, sizeof(SHA256_CTX_STRUC)); - NdisZeroMemory(&sha_ctx2, sizeof(SHA256_CTX_STRUC)); - /* - * If the length of K = B(Block size): K0 = K. - * If the length of K > B: hash K to obtain an L byte string, - * then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00). - * If the length of K < B: append zeros to the end of K to create a B-byte string K0 - */ - NdisZeroMemory(K0, SHA256_BLOCK_SIZE); - if (KeyLen <= SHA256_BLOCK_SIZE) { - NdisMoveMemory(K0, Key, KeyLen); - } else { - RT_SHA256(Key, KeyLen, K0); - } - - /* Exclusive-Or K0 with ipad */ - /* ipad: Inner pad; the byte x��36�� repeated B times. */ - for (index = 0; index < SHA256_BLOCK_SIZE; index++) - K0[index] ^= 0x36; - /* End of for */ - - SHA256_Init(&sha_ctx1); - /* H(K0^ipad) */ - SHA256_Append(&sha_ctx1, K0, sizeof(K0)); - /* H((K0^ipad)||text) */ - SHA256_Append(&sha_ctx1, Message, MessageLen); - SHA256_End(&sha_ctx1, Digest); - - /* Exclusive-Or K0 with opad and remove ipad */ - /* opad: Outer pad; the byte x��5c�� repeated B times. */ - for (index = 0; index < SHA256_BLOCK_SIZE; index++) - K0[index] ^= 0x36^0x5c; - /* End of for */ - - SHA256_Init(&sha_ctx2); - /* H(K0^opad) */ - SHA256_Append(&sha_ctx2, K0, sizeof(K0)); - /* H( (K0^opad) || H((K0^ipad)||text) ) */ - SHA256_Append(&sha_ctx2, Digest, SHA256_DIGEST_SIZE); - SHA256_End(&sha_ctx2, Digest); - - if (MACLen > SHA256_DIGEST_SIZE) - NdisMoveMemory(MAC, Digest,SHA256_DIGEST_SIZE); - else - NdisMoveMemory(MAC, Digest, MACLen); - -} /* End of HMAC_SHA256 */ -#endif /* HMAC_SHA256_SUPPORT */ - - -#ifdef HMAC_MD5_SUPPORT -/* -======================================================================== -Routine Description: - HMAC using MD5 hash function - -Arguments: - key Secret key - key_len The length of the key in bytes - message Message context - message_len The length of message in bytes - macLen Request the length of message authentication code - -Return Value: - mac Message authentication code - -Note: - None -======================================================================== -*/ -VOID HMAC_MD5( - IN const UINT8 Key[], - IN UINT KeyLen, - IN const UINT8 Message[], - IN UINT MessageLen, - OUT UINT8 MAC[], - IN UINT MACLen) -{ - MD5_CTX_STRUC md5_ctx1; - MD5_CTX_STRUC md5_ctx2; - UINT8 K0[MD5_BLOCK_SIZE]; - UINT8 Digest[MD5_DIGEST_SIZE]; - UINT index; - - NdisZeroMemory(&md5_ctx1, sizeof(MD5_CTX_STRUC)); - NdisZeroMemory(&md5_ctx2, sizeof(MD5_CTX_STRUC)); - /* - * If the length of K = B(Block size): K0 = K. - * If the length of K > B: hash K to obtain an L byte string, - * then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00). - * If the length of K < B: append zeros to the end of K to create a B-byte string K0 - */ - NdisZeroMemory(K0, MD5_BLOCK_SIZE); - if (KeyLen <= MD5_BLOCK_SIZE) { - NdisMoveMemory(K0, Key, KeyLen); - } else { - RT_MD5(Key, KeyLen, K0); - } - - /* Exclusive-Or K0 with ipad */ - /* ipad: Inner pad; the byte x��36�� repeated B times. */ - for (index = 0; index < MD5_BLOCK_SIZE; index++) - K0[index] ^= 0x36; - /* End of for */ - - MD5_Init(&md5_ctx1); - /* H(K0^ipad) */ - MD5_Append(&md5_ctx1, K0, sizeof(K0)); - /* H((K0^ipad)||text) */ - MD5_Append(&md5_ctx1, Message, MessageLen); - MD5_End(&md5_ctx1, Digest); - - /* Exclusive-Or K0 with opad and remove ipad */ - /* opad: Outer pad; the byte x��5c�� repeated B times. */ - for (index = 0; index < MD5_BLOCK_SIZE; index++) - K0[index] ^= 0x36^0x5c; - /* End of for */ - - MD5_Init(&md5_ctx2); - /* H(K0^opad) */ - MD5_Append(&md5_ctx2, K0, sizeof(K0)); - /* H( (K0^opad) || H((K0^ipad)||text) ) */ - MD5_Append(&md5_ctx2, Digest, MD5_DIGEST_SIZE); - MD5_End(&md5_ctx2, Digest); - - if (MACLen > MD5_DIGEST_SIZE) - NdisMoveMemory(MAC, Digest, MD5_DIGEST_SIZE); - else - NdisMoveMemory(MAC, Digest, MACLen); -} /* End of HMAC_SHA256 */ -#endif /* HMAC_MD5_SUPPORT */ - -/* End of crypt_hmac.c */ diff --git a/drivers/staging/rt3090/common/crypt_md5.c b/drivers/staging/rt3090/common/crypt_md5.c deleted file mode 100644 index b09326540f5e1c405ace9ee7cc9e500f1a932043..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/crypt_md5.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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 "../crypt_md5.h" - - -#ifdef MD5_SUPPORT -/* - * F, G, H and I are basic MD5 functions. - */ -#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define I(x, y, z) ((y) ^ ((x) | (~z))) - -#define ROTL(x,n,w) ((x << n) | (x >> (w - n))) -#define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */ - -#define ROUND1(a, b, c, d, x, s, ac) { \ - (a) += F((b),(c),(d)) + (x) + (UINT32)(ac); \ - (a) = ROTL32((a),(s)); \ - (a) += (b); \ -} -#define ROUND2(a, b, c, d, x, s, ac) { \ - (a) += G((b),(c),(d)) + (x) + (UINT32)(ac); \ - (a) = ROTL32((a),(s)); \ - (a) += (b); \ -} -#define ROUND3(a, b, c, d, x, s, ac) { \ - (a) += H((b),(c),(d)) + (x) + (UINT32)(ac); \ - (a) = ROTL32((a),(s)); \ - (a) += (b); \ -} -#define ROUND4(a, b, c, d, x, s, ac) { \ - (a) += I((b),(c),(d)) + (x) + (UINT32)(ac); \ - (a) = ROTL32((a),(s)); \ - (a) += (b); \ -} -static const UINT32 MD5_DefaultHashValue[4] = { - 0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL -}; -#endif /* MD5_SUPPORT */ - - -#ifdef MD5_SUPPORT -/* -======================================================================== -Routine Description: - Initial Md5_CTX_STRUC - -Arguments: - pMD5_CTX Pointer to Md5_CTX_STRUC - -Return Value: - None - -Note: - None -======================================================================== -*/ -VOID MD5_Init ( - IN MD5_CTX_STRUC *pMD5_CTX) -{ - NdisMoveMemory(pMD5_CTX->HashValue, MD5_DefaultHashValue, - sizeof(MD5_DefaultHashValue)); - NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE); - pMD5_CTX->BlockLen = 0; - pMD5_CTX->MessageLen = 0; -} /* End of MD5_Init */ - - -/* -======================================================================== -Routine Description: - MD5 computation for one block (512 bits) - -Arguments: - pMD5_CTX Pointer to Md5_CTX_STRUC - -Return Value: - None - -Note: - T[i] := floor(abs(sin(i + 1)) * (2 pow 32)), i is number of round -======================================================================== -*/ -VOID MD5_Hash ( - IN MD5_CTX_STRUC *pMD5_CTX) -{ - UINT32 X_i; - UINT32 X[16]; - UINT32 a,b,c,d; - - /* Prepare the message schedule, {X_i} */ - NdisMoveMemory(X, pMD5_CTX->Block, MD5_BLOCK_SIZE); - for (X_i = 0; X_i < 16; X_i++) - X[X_i] = cpu2le32(X[X_i]); /* Endian Swap */ - /* End of for */ - - /* MD5 hash computation */ - /* Initialize the working variables */ - a = pMD5_CTX->HashValue[0]; - b = pMD5_CTX->HashValue[1]; - c = pMD5_CTX->HashValue[2]; - d = pMD5_CTX->HashValue[3]; - - /* - * Round 1 - * Let [abcd k s i] denote the operation - * a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s) - */ - ROUND1(a, b, c, d, X[ 0], 7, 0xd76aa478); /* 1 */ - ROUND1(d, a, b, c, X[ 1], 12, 0xe8c7b756); /* 2 */ - ROUND1(c, d, a, b, X[ 2], 17, 0x242070db); /* 3 */ - ROUND1(b, c, d, a, X[ 3], 22, 0xc1bdceee); /* 4 */ - ROUND1(a, b, c, d, X[ 4], 7, 0xf57c0faf); /* 5 */ - ROUND1(d, a, b, c, X[ 5], 12, 0x4787c62a); /* 6 */ - ROUND1(c, d, a, b, X[ 6], 17, 0xa8304613); /* 7 */ - ROUND1(b, c, d, a, X[ 7], 22, 0xfd469501); /* 8 */ - ROUND1(a, b, c, d, X[ 8], 7, 0x698098d8); /* 9 */ - ROUND1(d, a, b, c, X[ 9], 12, 0x8b44f7af); /* 10 */ - ROUND1(c, d, a, b, X[10], 17, 0xffff5bb1); /* 11 */ - ROUND1(b, c, d, a, X[11], 22, 0x895cd7be); /* 12 */ - ROUND1(a, b, c, d, X[12], 7, 0x6b901122); /* 13 */ - ROUND1(d, a, b, c, X[13], 12, 0xfd987193); /* 14 */ - ROUND1(c, d, a, b, X[14], 17, 0xa679438e); /* 15 */ - ROUND1(b, c, d, a, X[15], 22, 0x49b40821); /* 16 */ - - /* - * Round 2 - * Let [abcd k s i] denote the operation - * a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s) - */ - ROUND2(a, b, c, d, X[ 1], 5, 0xf61e2562); /* 17 */ - ROUND2(d, a, b, c, X[ 6], 9, 0xc040b340); /* 18 */ - ROUND2(c, d, a, b, X[11], 14, 0x265e5a51); /* 19 */ - ROUND2(b, c, d, a, X[ 0], 20, 0xe9b6c7aa); /* 20 */ - ROUND2(a, b, c, d, X[ 5], 5, 0xd62f105d); /* 21 */ - ROUND2(d, a, b, c, X[10], 9, 0x2441453); /* 22 */ - ROUND2(c, d, a, b, X[15], 14, 0xd8a1e681); /* 23 */ - ROUND2(b, c, d, a, X[ 4], 20, 0xe7d3fbc8); /* 24 */ - ROUND2(a, b, c, d, X[ 9], 5, 0x21e1cde6); /* 25 */ - ROUND2(d, a, b, c, X[14], 9, 0xc33707d6); /* 26 */ - ROUND2(c, d, a, b, X[ 3], 14, 0xf4d50d87); /* 27 */ - ROUND2(b, c, d, a, X[ 8], 20, 0x455a14ed); /* 28 */ - ROUND2(a, b, c, d, X[13], 5, 0xa9e3e905); /* 29 */ - ROUND2(d, a, b, c, X[ 2], 9, 0xfcefa3f8); /* 30 */ - ROUND2(c, d, a, b, X[ 7], 14, 0x676f02d9); /* 31 */ - ROUND2(b, c, d, a, X[12], 20, 0x8d2a4c8a); /* 32 */ - - /* - * Round 3 - * Let [abcd k s t] denote the operation - * a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s) - */ - ROUND3(a, b, c, d, X[ 5], 4, 0xfffa3942); /* 33 */ - ROUND3(d, a, b, c, X[ 8], 11, 0x8771f681); /* 34 */ - ROUND3(c, d, a, b, X[11], 16, 0x6d9d6122); /* 35 */ - ROUND3(b, c, d, a, X[14], 23, 0xfde5380c); /* 36 */ - ROUND3(a, b, c, d, X[ 1], 4, 0xa4beea44); /* 37 */ - ROUND3(d, a, b, c, X[ 4], 11, 0x4bdecfa9); /* 38 */ - ROUND3(c, d, a, b, X[ 7], 16, 0xf6bb4b60); /* 39 */ - ROUND3(b, c, d, a, X[10], 23, 0xbebfbc70); /* 40 */ - ROUND3(a, b, c, d, X[13], 4, 0x289b7ec6); /* 41 */ - ROUND3(d, a, b, c, X[ 0], 11, 0xeaa127fa); /* 42 */ - ROUND3(c, d, a, b, X[ 3], 16, 0xd4ef3085); /* 43 */ - ROUND3(b, c, d, a, X[ 6], 23, 0x4881d05); /* 44 */ - ROUND3(a, b, c, d, X[ 9], 4, 0xd9d4d039); /* 45 */ - ROUND3(d, a, b, c, X[12], 11, 0xe6db99e5); /* 46 */ - ROUND3(c, d, a, b, X[15], 16, 0x1fa27cf8); /* 47 */ - ROUND3(b, c, d, a, X[ 2], 23, 0xc4ac5665); /* 48 */ - - /* - * Round 4 - * Let [abcd k s t] denote the operation - * a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s) - */ - ROUND4(a, b, c, d, X[ 0], 6, 0xf4292244); /* 49 */ - ROUND4(d, a, b, c, X[ 7], 10, 0x432aff97); /* 50 */ - ROUND4(c, d, a, b, X[14], 15, 0xab9423a7); /* 51 */ - ROUND4(b, c, d, a, X[ 5], 21, 0xfc93a039); /* 52 */ - ROUND4(a, b, c, d, X[12], 6, 0x655b59c3); /* 53 */ - ROUND4(d, a, b, c, X[ 3], 10, 0x8f0ccc92); /* 54 */ - ROUND4(c, d, a, b, X[10], 15, 0xffeff47d); /* 55 */ - ROUND4(b, c, d, a, X[ 1], 21, 0x85845dd1); /* 56 */ - ROUND4(a, b, c, d, X[ 8], 6, 0x6fa87e4f); /* 57 */ - ROUND4(d, a, b, c, X[15], 10, 0xfe2ce6e0); /* 58 */ - ROUND4(c, d, a, b, X[ 6], 15, 0xa3014314); /* 59 */ - ROUND4(b, c, d, a, X[13], 21, 0x4e0811a1); /* 60 */ - ROUND4(a, b, c, d, X[ 4], 6, 0xf7537e82); /* 61 */ - ROUND4(d, a, b, c, X[11], 10, 0xbd3af235); /* 62 */ - ROUND4(c, d, a, b, X[ 2], 15, 0x2ad7d2bb); /* 63 */ - ROUND4(b, c, d, a, X[ 9], 21, 0xeb86d391); /* 64 */ - - /* Compute the i^th intermediate hash value H^(i) */ - pMD5_CTX->HashValue[0] += a; - pMD5_CTX->HashValue[1] += b; - pMD5_CTX->HashValue[2] += c; - pMD5_CTX->HashValue[3] += d; - - NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE); - pMD5_CTX->BlockLen = 0; -} /* End of MD5_Hash */ - - -/* -======================================================================== -Routine Description: - The message is appended to block. If block size > 64 bytes, the MD5_Hash -will be called. - -Arguments: - pMD5_CTX Pointer to MD5_CTX_STRUC - message Message context - messageLen The length of message in bytes - -Return Value: - None - -Note: - None -======================================================================== -*/ -VOID MD5_Append ( - IN MD5_CTX_STRUC *pMD5_CTX, - IN const UINT8 Message[], - IN UINT MessageLen) -{ - UINT appendLen = 0; - UINT diffLen = 0; - - while (appendLen != MessageLen) { - diffLen = MessageLen - appendLen; - if ((pMD5_CTX->BlockLen + diffLen) < MD5_BLOCK_SIZE) { - NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, - Message + appendLen, diffLen); - pMD5_CTX->BlockLen += diffLen; - appendLen += diffLen; - } - else - { - NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, - Message + appendLen, MD5_BLOCK_SIZE - pMD5_CTX->BlockLen); - appendLen += (MD5_BLOCK_SIZE - pMD5_CTX->BlockLen); - pMD5_CTX->BlockLen = MD5_BLOCK_SIZE; - MD5_Hash(pMD5_CTX); - } /* End of if */ - } /* End of while */ - pMD5_CTX->MessageLen += MessageLen; -} /* End of MD5_Append */ - - -/* -======================================================================== -Routine Description: - 1. Append bit 1 to end of the message - 2. Append the length of message in rightmost 64 bits - 3. Transform the Hash Value to digest message - -Arguments: - pMD5_CTX Pointer to MD5_CTX_STRUC - -Return Value: - digestMessage Digest message - -Note: - None -======================================================================== -*/ -VOID MD5_End ( - IN MD5_CTX_STRUC *pMD5_CTX, - OUT UINT8 DigestMessage[]) -{ - UINT index; - UINT64 message_length_bits; - - /* append 1 bits to end of the message */ - NdisFillMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, 1, 0x80); - - /* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */ - if (pMD5_CTX->BlockLen > 55) - MD5_Hash(pMD5_CTX); - /* End of if */ - - /* Append the length of message in rightmost 64 bits */ - message_length_bits = pMD5_CTX->MessageLen*8; - message_length_bits = cpu2le64(message_length_bits); - NdisMoveMemory(&pMD5_CTX->Block[56], &message_length_bits, 8); - MD5_Hash(pMD5_CTX); - - /* Return message digest, transform the UINT32 hash value to bytes */ - for (index = 0; index < 4;index++) - pMD5_CTX->HashValue[index] = cpu2le32(pMD5_CTX->HashValue[index]); - /* End of for */ - NdisMoveMemory(DigestMessage, pMD5_CTX->HashValue, MD5_DIGEST_SIZE); -} /* End of MD5_End */ - - -/* -======================================================================== -Routine Description: - MD5 algorithm - -Arguments: - message Message context - messageLen The length of message in bytes - -Return Value: - digestMessage Digest message - -Note: - None -======================================================================== -*/ -VOID RT_MD5 ( - IN const UINT8 Message[], - IN UINT MessageLen, - OUT UINT8 DigestMessage[]) -{ - MD5_CTX_STRUC md5_ctx; - - NdisZeroMemory(&md5_ctx, sizeof(MD5_CTX_STRUC)); - MD5_Init(&md5_ctx); - MD5_Append(&md5_ctx, Message, MessageLen); - MD5_End(&md5_ctx, DigestMessage); -} /* End of RT_MD5 */ - -#endif /* MD5_SUPPORT */ - -/* End of crypt_md5.c */ diff --git a/drivers/staging/rt3090/common/crypt_sha2.c b/drivers/staging/rt3090/common/crypt_sha2.c deleted file mode 100644 index c7490d0d3c445920b99601c2ae4af122aa01bddd..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/crypt_sha2.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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 "../crypt_sha2.h" - - -/* Basic operations */ -#define SHR(x,n) (x >> n) /* SHR(x)^n, right shift n bits , x is w-bit word, 0 <= n <= w */ -#define ROTR(x,n,w) ((x >> n) | (x << (w - n))) /* ROTR(x)^n, circular right shift n bits , x is w-bit word, 0 <= n <= w */ -#define ROTL(x,n,w) ((x << n) | (x >> (w - n))) /* ROTL(x)^n, circular left shift n bits , x is w-bit word, 0 <= n <= w */ -#define ROTR32(x,n) ROTR(x,n,32) /* 32 bits word */ -#define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */ - -/* Basic functions */ -#define Ch(x,y,z) ((x & y) ^ ((~x) & z)) -#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) -#define Parity(x,y,z) (x ^ y ^ z) - -#ifdef SHA1_SUPPORT -/* SHA1 constants */ -#define SHA1_MASK 0x0000000f -static const UINT32 SHA1_K[4] = { - 0x5a827999UL, 0x6ed9eba1UL, 0x8f1bbcdcUL, 0xca62c1d6UL -}; -static const UINT32 SHA1_DefaultHashValue[5] = { - 0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL, 0xc3d2e1f0UL -}; -#endif /* SHA1_SUPPORT */ - - -#ifdef SHA256_SUPPORT -/* SHA256 functions */ -#define Zsigma_256_0(x) (ROTR32(x,2) ^ ROTR32(x,13) ^ ROTR32(x,22)) -#define Zsigma_256_1(x) (ROTR32(x,6) ^ ROTR32(x,11) ^ ROTR32(x,25)) -#define Sigma_256_0(x) (ROTR32(x,7) ^ ROTR32(x,18) ^ SHR(x,3)) -#define Sigma_256_1(x) (ROTR32(x,17) ^ ROTR32(x,19) ^ SHR(x,10)) -/* SHA256 constants */ -static const UINT32 SHA256_K[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, - 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, - 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, - 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, - 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, - 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, - 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, - 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, - 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, - 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, - 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, - 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, - 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, - 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, - 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL -}; -static const UINT32 SHA256_DefaultHashValue[8] = { - 0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL, - 0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL -}; -#endif /* SHA256_SUPPORT */ - - -#ifdef SHA1_SUPPORT -/* -======================================================================== -Routine Description: - Initial SHA1_CTX_STRUC - -Arguments: - pSHA_CTX Pointer to SHA1_CTX_STRUC - -Return Value: - None - -Note: - None -======================================================================== -*/ -VOID SHA1_Init ( - IN SHA1_CTX_STRUC *pSHA_CTX) -{ - NdisMoveMemory(pSHA_CTX->HashValue, SHA1_DefaultHashValue, - sizeof(SHA1_DefaultHashValue)); - NdisZeroMemory(pSHA_CTX->Block, SHA1_BLOCK_SIZE); - pSHA_CTX->MessageLen = 0; - pSHA_CTX->BlockLen = 0; -} /* End of SHA1_Init */ - - -/* -======================================================================== -Routine Description: - SHA1 computation for one block (512 bits) - -Arguments: - pSHA_CTX Pointer to SHA1_CTX_STRUC - -Return Value: - None - -Note: - None -======================================================================== -*/ -VOID SHA1_Hash ( - IN SHA1_CTX_STRUC *pSHA_CTX) -{ - UINT32 W_i,t,s; - UINT32 W[16]; - UINT32 a,b,c,d,e,T,f_t = 0; - - /* Prepare the message schedule, {W_i}, 0 < t < 15 */ - NdisMoveMemory(W, pSHA_CTX->Block, SHA1_BLOCK_SIZE); - for (W_i = 0; W_i < 16; W_i++) - W[W_i] = cpu2be32(W[W_i]); /* Endian Swap */ - /* End of for */ - - /* SHA256 hash computation */ - /* Initialize the working variables */ - a = pSHA_CTX->HashValue[0]; - b = pSHA_CTX->HashValue[1]; - c = pSHA_CTX->HashValue[2]; - d = pSHA_CTX->HashValue[3]; - e = pSHA_CTX->HashValue[4]; - - /* 80 rounds */ - for (t = 0;t < 80;t++) { - s = t & SHA1_MASK; - if (t > 15) { /* Prepare the message schedule, {W_i}, 16 < t < 79 */ - W[s] = (W[(s+13) & SHA1_MASK]) ^ (W[(s+8) & SHA1_MASK]) ^ (W[(s+2) & SHA1_MASK]) ^ W[s]; - W[s] = ROTL32(W[s],1); - } /* End of if */ - switch (t / 20) { - case 0: - f_t = Ch(b,c,d); - break; - case 1: - f_t = Parity(b,c,d); - break; - case 2: - f_t = Maj(b,c,d); - break; - case 3: - f_t = Parity(b,c,d); - break; - } /* End of switch */ - T = ROTL32(a,5) + f_t + e + SHA1_K[t / 20] + W[s]; - e = d; - d = c; - c = ROTL32(b,30); - b = a; - a = T; - } /* End of for */ - - /* Compute the i^th intermediate hash value H^(i) */ - pSHA_CTX->HashValue[0] += a; - pSHA_CTX->HashValue[1] += b; - pSHA_CTX->HashValue[2] += c; - pSHA_CTX->HashValue[3] += d; - pSHA_CTX->HashValue[4] += e; - - NdisZeroMemory(pSHA_CTX->Block, SHA1_BLOCK_SIZE); - pSHA_CTX->BlockLen = 0; -} /* End of SHA1_Hash */ - - -/* -======================================================================== -Routine Description: - The message is appended to block. If block size > 64 bytes, the SHA1_Hash -will be called. - -Arguments: - pSHA_CTX Pointer to SHA1_CTX_STRUC - message Message context - messageLen The length of message in bytes - -Return Value: - None - -Note: - None -======================================================================== -*/ -VOID SHA1_Append ( - IN SHA1_CTX_STRUC *pSHA_CTX, - IN const UINT8 Message[], - IN UINT MessageLen) -{ - UINT appendLen = 0; - UINT diffLen = 0; - - while (appendLen != MessageLen) { - diffLen = MessageLen - appendLen; - if ((pSHA_CTX->BlockLen + diffLen) < SHA1_BLOCK_SIZE) { - NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, - Message + appendLen, diffLen); - pSHA_CTX->BlockLen += diffLen; - appendLen += diffLen; - } - else - { - NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, - Message + appendLen, SHA1_BLOCK_SIZE - pSHA_CTX->BlockLen); - appendLen += (SHA1_BLOCK_SIZE - pSHA_CTX->BlockLen); - pSHA_CTX->BlockLen = SHA1_BLOCK_SIZE; - SHA1_Hash(pSHA_CTX); - } /* End of if */ - } /* End of while */ - pSHA_CTX->MessageLen += MessageLen; -} /* End of SHA1_Append */ - - -/* -======================================================================== -Routine Description: - 1. Append bit 1 to end of the message - 2. Append the length of message in rightmost 64 bits - 3. Transform the Hash Value to digest message - -Arguments: - pSHA_CTX Pointer to SHA1_CTX_STRUC - -Return Value: - digestMessage Digest message - -Note: - None -======================================================================== -*/ -VOID SHA1_End ( - IN SHA1_CTX_STRUC *pSHA_CTX, - OUT UINT8 DigestMessage[]) -{ - UINT index; - UINT64 message_length_bits; - - /* Append bit 1 to end of the message */ - NdisFillMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, 1, 0x80); - - /* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */ - if (pSHA_CTX->BlockLen > 55) - SHA1_Hash(pSHA_CTX); - /* End of if */ - - /* Append the length of message in rightmost 64 bits */ - message_length_bits = pSHA_CTX->MessageLen*8; - message_length_bits = cpu2be64(message_length_bits); - NdisMoveMemory(&pSHA_CTX->Block[56], &message_length_bits, 8); - SHA1_Hash(pSHA_CTX); - - /* Return message digest, transform the UINT32 hash value to bytes */ - for (index = 0; index < 5;index++) - pSHA_CTX->HashValue[index] = cpu2be32(pSHA_CTX->HashValue[index]); - /* End of for */ - NdisMoveMemory(DigestMessage, pSHA_CTX->HashValue, SHA1_DIGEST_SIZE); -} /* End of SHA1_End */ - - -/* -======================================================================== -Routine Description: - SHA1 algorithm - -Arguments: - message Message context - messageLen The length of message in bytes - -Return Value: - digestMessage Digest message - -Note: - None -======================================================================== -*/ -VOID RT_SHA1 ( - IN const UINT8 Message[], - IN UINT MessageLen, - OUT UINT8 DigestMessage[]) -{ - - SHA1_CTX_STRUC sha_ctx; - - NdisZeroMemory(&sha_ctx, sizeof(SHA1_CTX_STRUC)); - SHA1_Init(&sha_ctx); - SHA1_Append(&sha_ctx, Message, MessageLen); - SHA1_End(&sha_ctx, DigestMessage); -} /* End of RT_SHA1 */ -#endif /* SHA1_SUPPORT */ - - -#ifdef SHA256_SUPPORT -/* -======================================================================== -Routine Description: - Initial SHA256_CTX_STRUC - -Arguments: - pSHA_CTX Pointer to SHA256_CTX_STRUC - -Return Value: - None - -Note: - None -======================================================================== -*/ -VOID SHA256_Init ( - IN SHA256_CTX_STRUC *pSHA_CTX) -{ - NdisMoveMemory(pSHA_CTX->HashValue, SHA256_DefaultHashValue, - sizeof(SHA256_DefaultHashValue)); - NdisZeroMemory(pSHA_CTX->Block, SHA256_BLOCK_SIZE); - pSHA_CTX->MessageLen = 0; - pSHA_CTX->BlockLen = 0; -} /* End of SHA256_Init */ - - -/* -======================================================================== -Routine Description: - SHA256 computation for one block (512 bits) - -Arguments: - pSHA_CTX Pointer to SHA256_CTX_STRUC - -Return Value: - None - -Note: - None -======================================================================== -*/ -VOID SHA256_Hash ( - IN SHA256_CTX_STRUC *pSHA_CTX) -{ - UINT32 W_i,t; - UINT32 W[64]; - UINT32 a,b,c,d,e,f,g,h,T1,T2; - - /* Prepare the message schedule, {W_i}, 0 < t < 15 */ - NdisMoveMemory(W, pSHA_CTX->Block, SHA256_BLOCK_SIZE); - for (W_i = 0; W_i < 16; W_i++) - W[W_i] = cpu2be32(W[W_i]); /* Endian Swap */ - /* End of for */ - - /* SHA256 hash computation */ - /* Initialize the working variables */ - a = pSHA_CTX->HashValue[0]; - b = pSHA_CTX->HashValue[1]; - c = pSHA_CTX->HashValue[2]; - d = pSHA_CTX->HashValue[3]; - e = pSHA_CTX->HashValue[4]; - f = pSHA_CTX->HashValue[5]; - g = pSHA_CTX->HashValue[6]; - h = pSHA_CTX->HashValue[7]; - - /* 64 rounds */ - for (t = 0;t < 64;t++) { - if (t > 15) /* Prepare the message schedule, {W_i}, 16 < t < 63 */ - W[t] = Sigma_256_1(W[t-2]) + W[t-7] + Sigma_256_0(W[t-15]) + W[t-16]; - /* End of if */ - T1 = h + Zsigma_256_1(e) + Ch(e,f,g) + SHA256_K[t] + W[t]; - T2 = Zsigma_256_0(a) + Maj(a,b,c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - } /* End of for */ - - /* Compute the i^th intermediate hash value H^(i) */ - pSHA_CTX->HashValue[0] += a; - pSHA_CTX->HashValue[1] += b; - pSHA_CTX->HashValue[2] += c; - pSHA_CTX->HashValue[3] += d; - pSHA_CTX->HashValue[4] += e; - pSHA_CTX->HashValue[5] += f; - pSHA_CTX->HashValue[6] += g; - pSHA_CTX->HashValue[7] += h; - - NdisZeroMemory(pSHA_CTX->Block, SHA256_BLOCK_SIZE); - pSHA_CTX->BlockLen = 0; -} /* End of SHA256_Hash */ - - -/* -======================================================================== -Routine Description: - The message is appended to block. If block size > 64 bytes, the SHA256_Hash -will be called. - -Arguments: - pSHA_CTX Pointer to SHA256_CTX_STRUC - message Message context - messageLen The length of message in bytes - -Return Value: - None - -Note: - None -======================================================================== -*/ -VOID SHA256_Append ( - IN SHA256_CTX_STRUC *pSHA_CTX, - IN const UINT8 Message[], - IN UINT MessageLen) -{ - UINT appendLen = 0; - UINT diffLen = 0; - - while (appendLen != MessageLen) { - diffLen = MessageLen - appendLen; - if ((pSHA_CTX->BlockLen + diffLen) < SHA256_BLOCK_SIZE) { - NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, - Message + appendLen, diffLen); - pSHA_CTX->BlockLen += diffLen; - appendLen += diffLen; - } - else - { - NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, - Message + appendLen, SHA256_BLOCK_SIZE - pSHA_CTX->BlockLen); - appendLen += (SHA256_BLOCK_SIZE - pSHA_CTX->BlockLen); - pSHA_CTX->BlockLen = SHA256_BLOCK_SIZE; - SHA256_Hash(pSHA_CTX); - } /* End of if */ - } /* End of while */ - pSHA_CTX->MessageLen += MessageLen; -} /* End of SHA256_Append */ - - -/* -======================================================================== -Routine Description: - 1. Append bit 1 to end of the message - 2. Append the length of message in rightmost 64 bits - 3. Transform the Hash Value to digest message - -Arguments: - pSHA_CTX Pointer to SHA256_CTX_STRUC - -Return Value: - digestMessage Digest message - -Note: - None -======================================================================== -*/ -VOID SHA256_End ( - IN SHA256_CTX_STRUC *pSHA_CTX, - OUT UINT8 DigestMessage[]) -{ - UINT index; - UINT64 message_length_bits; - - /* Append bit 1 to end of the message */ - NdisFillMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, 1, 0x80); - - /* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */ - if (pSHA_CTX->BlockLen > 55) - SHA256_Hash(pSHA_CTX); - /* End of if */ - - /* Append the length of message in rightmost 64 bits */ - message_length_bits = pSHA_CTX->MessageLen*8; - message_length_bits = cpu2be64(message_length_bits); - NdisMoveMemory(&pSHA_CTX->Block[56], &message_length_bits, 8); - SHA256_Hash(pSHA_CTX); - - /* Return message digest, transform the UINT32 hash value to bytes */ - for (index = 0; index < 8;index++) - pSHA_CTX->HashValue[index] = cpu2be32(pSHA_CTX->HashValue[index]); - /* End of for */ - NdisMoveMemory(DigestMessage, pSHA_CTX->HashValue, SHA256_DIGEST_SIZE); -} /* End of SHA256_End */ - - -/* -======================================================================== -Routine Description: - SHA256 algorithm - -Arguments: - message Message context - messageLen The length of message in bytes - -Return Value: - digestMessage Digest message - -Note: - None -======================================================================== -*/ -VOID RT_SHA256 ( - IN const UINT8 Message[], - IN UINT MessageLen, - OUT UINT8 DigestMessage[]) -{ - SHA256_CTX_STRUC sha_ctx; - - NdisZeroMemory(&sha_ctx, sizeof(SHA256_CTX_STRUC)); - SHA256_Init(&sha_ctx); - SHA256_Append(&sha_ctx, Message, MessageLen); - SHA256_End(&sha_ctx, DigestMessage); -} /* End of RT_SHA256 */ -#endif /* SHA256_SUPPORT */ - -/* End of crypt_sha2.c */ diff --git a/drivers/staging/rt3090/common/dfs.c b/drivers/staging/rt3090/common/dfs.c deleted file mode 100644 index c15704ae2f24c55cddc90a590c25974627668466..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/dfs.c +++ /dev/null @@ -1,481 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - ap_dfs.c - - Abstract: - Support DFS function. - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#include "../rt_config.h" - - -typedef struct _RADAR_DURATION_TABLE -{ - ULONG RDDurRegion; - ULONG RadarSignalDuration; - ULONG Tolerance; -} RADAR_DURATION_TABLE, *PRADAR_DURATION_TABLE; - - - -UCHAR RdIdleTimeTable[MAX_RD_REGION][4] = -{ - {9, 250, 250, 250}, // CE -#ifdef DFS_FCC_BW40_FIX - {1, 250, 250, 250}, // FCC -#else - {4, 250, 250, 250}, // FCC -#endif - {4, 250, 250, 250}, // JAP - {15, 250, 250, 250}, // JAP_W53 - {4, 250, 250, 250} // JAP_W56 -}; - -#ifdef TONE_RADAR_DETECT_SUPPORT -static void ToneRadarProgram(PRTMP_ADAPTER pAd); -static void ToneRadarEnable(PRTMP_ADAPTER pAd); -#endif // TONE_RADAR_DETECT_SUPPORT // - -#ifdef DFS_SUPPORT -/* - ======================================================================== - - Routine Description: - Bbp Radar detection routine - - Arguments: - pAd Pointer to our adapter - - Return Value: - - ======================================================================== -*/ -VOID BbpRadarDetectionStart( - IN PRTMP_ADAPTER pAd) -{ - UINT8 RadarPeriod; - - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 114, 0x02); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 121, 0x20); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 122, 0x00); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 123, 0x08/*0x80*/); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 124, 0x28); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 125, 0xff); - -#ifdef MERGE_ARCH_TEAM - if ((pAd->CommonCfg.RadarDetect.RDDurRegion == JAP) || (pAd->CommonCfg.RadarDetect.RDDurRegion == JAP_W53) || (pAd->CommonCfg.RadarDetect.RDDurRegion == JAP_W56)) - { - pAd->CommonCfg.RadarDetect.RDDurRegion = JAP; - pAd->CommonCfg.RadarDetect.RDDurRegion = JapRadarType(pAd); - if (pAd->CommonCfg.RadarDetect.RDDurRegion == JAP_W56) - { - pAd->CommonCfg.RadarDetect.DfsSessionTime = 13; - } - else if (pAd->CommonCfg.RadarDetect.RDDurRegion == JAP_W53) - { - pAd->CommonCfg.RadarDetect.DfsSessionTime = 15; - } -#ifdef CARRIER_DETECTION_SUPPORT - pAd->CommonCfg.CarrierDetect.Enable = 1; -#endif // CARRIER_DETECTION_SUPPORT // - } -#endif // MERGE_ARCH_TEAM // - - RadarPeriod = ((UINT)RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + (UINT)pAd->CommonCfg.RadarDetect.DfsSessionTime) < 250 ? - (RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + pAd->CommonCfg.RadarDetect.DfsSessionTime) : 250; - -#ifdef MERGE_ARCH_TEAM - - -#else // Original RT28xx source code. - RTMP_IO_WRITE8(pAd, 0x7020, 0x1d); - RTMP_IO_WRITE8(pAd, 0x7021, 0x40); -#endif // MERGE_ARCH_TEAM // - - RadarDetectionStart(pAd, 0, RadarPeriod); - return; -} - -/* - ======================================================================== - - Routine Description: - Bbp Radar detection routine - - Arguments: - pAd Pointer to our adapter - - Return Value: - - ======================================================================== -*/ -VOID BbpRadarDetectionStop( - IN PRTMP_ADAPTER pAd) -{ - RTMP_IO_WRITE8(pAd, 0x7020, 0x1d); - RTMP_IO_WRITE8(pAd, 0x7021, 0x60); - - RadarDetectionStop(pAd); - return; -} - -/* - ======================================================================== - - Routine Description: - Radar detection routine - - Arguments: - pAd Pointer to our adapter - - Return Value: - - ======================================================================== -*/ -VOID RadarDetectionStart( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN CTSProtect, - IN UINT8 CTSPeriod) -{ - UINT8 DfsActiveTime = (pAd->CommonCfg.RadarDetect.DfsSessionTime & 0x1f); - UINT8 CtsProtect = (CTSProtect == 1) ? 0x02 : 0x01; // CTS protect. - - if (CTSProtect != 0) - { - switch(pAd->CommonCfg.RadarDetect.RDDurRegion) - { - case FCC: - case JAP_W56: - CtsProtect = 0x03; - break; - - case JAP: - { - UCHAR RDDurRegion; - RDDurRegion = JapRadarType(pAd); - if (RDDurRegion == JAP_W56) - CtsProtect = 0x03; - else - CtsProtect = 0x02; - break; - } - - case CE: - case JAP_W53: - default: - CtsProtect = 0x02; - break; - } - } - else - CtsProtect = 0x01; - - - // send start-RD with CTS protection command to MCU - // highbyte [7] reserve - // highbyte [6:5] 0x: stop Carrier/Radar detection - // highbyte [10]: Start Carrier/Radar detection without CTS protection, 11: Start Carrier/Radar detection with CTS protection - // highbyte [4:0] Radar/carrier detection duration. In 1ms. - - // lowbyte [7:0] Radar/carrier detection period, in 1ms. - AsicSendCommandToMcu(pAd, 0x60, 0xff, CTSPeriod, DfsActiveTime | (CtsProtect << 5)); - //AsicSendCommandToMcu(pAd, 0x63, 0xff, 10, 0); - - return; -} - -/* - ======================================================================== - - Routine Description: - Radar detection routine - - Arguments: - pAd Pointer to our adapter - - Return Value: - TRUE Found radar signal - FALSE Not found radar signal - - ======================================================================== -*/ -VOID RadarDetectionStop( - IN PRTMP_ADAPTER pAd) -{ - DBGPRINT(RT_DEBUG_TRACE,("RadarDetectionStop.\n")); - AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x00, 0x00); // send start-RD with CTS protection command to MCU - - return; -} -#endif // DFS_SUPPORT // - - -/* - ======================================================================== - - Routine Description: - Radar channel check routine - - Arguments: - pAd Pointer to our adapter - - Return Value: - TRUE need to do radar detect - FALSE need not to do radar detect - - ======================================================================== -*/ -BOOLEAN RadarChannelCheck( - IN PRTMP_ADAPTER pAd, - IN UCHAR Ch) -{ - INT i; - BOOLEAN result = FALSE; - - for (i=0; iChannelListNum; i++) - { - if (Ch == pAd->ChannelList[i].Channel) - { - result = pAd->ChannelList[i].DfsReq; - break; - } - } - - return result; -} - -#ifdef DFS_SUPPORT - -ULONG JapRadarType( - IN PRTMP_ADAPTER pAd) -{ - ULONG i; - const UCHAR Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; - - if (pAd->CommonCfg.RadarDetect.RDDurRegion != JAP) - { - return pAd->CommonCfg.RadarDetect.RDDurRegion; - } - - for (i=0; i<15; i++) - { - if (pAd->CommonCfg.Channel == Channel[i]) - { - break; - } - } - - if (i < 4) - return JAP_W53; - else if (i < 15) - return JAP_W56; - else - return JAP; // W52 - -} - -ULONG RTMPBbpReadRadarDuration( - IN PRTMP_ADAPTER pAd) -{ - UINT8 byteValue = 0; - ULONG result; - - BBP_IO_READ8_BY_REG_ID(pAd, BBP_R115, &byteValue); - - result = 0; - switch (byteValue) - { - case 1: // radar signal detected by pulse mode. - case 2: // radar signal detected by width mode. - result = RTMPReadRadarDuration(pAd); - break; - - case 0: // No radar signal. - default: - - result = 0; - break; - } - - return result; -} - -ULONG RTMPReadRadarDuration( - IN PRTMP_ADAPTER pAd) -{ - ULONG result = 0; - -#ifdef DFS_SUPPORT - UINT8 duration1 = 0, duration2 = 0, duration3 = 0; - - - BBP_IO_READ8_BY_REG_ID(pAd, BBP_R116, &duration1); - BBP_IO_READ8_BY_REG_ID(pAd, BBP_R117, &duration2); - BBP_IO_READ8_BY_REG_ID(pAd, BBP_R118, &duration3); - result = (duration1 << 16) + (duration2 << 8) + duration3; -#endif // DFS_SUPPORT // - - return result; - -} - -VOID RTMPCleanRadarDuration( - IN PRTMP_ADAPTER pAd) -{ - return; -} - -/* - ======================================================================== - Routine Description: - Radar wave detection. The API should be invoke each second. - - Arguments: - pAd - Adapter pointer - - Return Value: - None - - ======================================================================== -*/ -VOID ApRadarDetectPeriodic( - IN PRTMP_ADAPTER pAd) -{ - INT i; - - pAd->CommonCfg.RadarDetect.InServiceMonitorCount++; - - for (i=0; iChannelListNum; i++) - { - - if (pAd->ChannelList[i].RemainingTimeForUse > 0) - { - pAd->ChannelList[i].RemainingTimeForUse --; - if ((pAd->Mlme.PeriodicRound%5) == 0) - { - DBGPRINT(RT_DEBUG_TRACE, ("RadarDetectPeriodic - ch=%d, RemainingTimeForUse=%d\n", pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse)); - } - } - } - - //radar detect - if ((pAd->CommonCfg.Channel > 14) - && (pAd->CommonCfg.bIEEE80211H == 1) - && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) - { - RadarDetectPeriodic(pAd); - } - - return; -} - -// Periodic Radar detection, switch channel will occur in RTMPHandleTBTTInterrupt() -// Before switch channel, driver needs doing channel switch announcement. -VOID RadarDetectPeriodic( - IN PRTMP_ADAPTER pAd) -{ - - // need to check channel availability, after switch channel - if (pAd->CommonCfg.RadarDetect.RDMode != RD_SILENCE_MODE) - return; - - - - // channel availability check time is 60sec, use 65 for assurance - if (pAd->CommonCfg.RadarDetect.RDCount++ > pAd->CommonCfg.RadarDetect.ChMovingTime) - { - DBGPRINT(RT_DEBUG_TRACE, ("Not found radar signal, start send beacon and radar detection in service monitor\n\n")); - BbpRadarDetectionStop(pAd); - - - AsicEnableBssSync(pAd); - pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE; - - - - return; - } - - return; -} -#endif // DFS_SUPPORT // - -#ifdef DFS_SUPPORT -/* - ========================================================================== - Description: - change channel moving time for DFS testing. - - Arguments: - pAdapter Pointer to our adapter - wrq Pointer to the ioctl argument - - Return Value: - None - - Note: - Usage: - 1.) iwpriv ra0 set ChMovTime=[value] - ========================================================================== -*/ -INT Set_ChMovingTime_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UINT8 Value; - - Value = (UINT8) simple_strtol(arg, 0, 10); - - pAd->CommonCfg.RadarDetect.ChMovingTime = Value; - - DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __FUNCTION__, - pAd->CommonCfg.RadarDetect.ChMovingTime)); - - return TRUE; -} - -INT Set_LongPulseRadarTh_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UINT8 Value; - - Value = (UINT8) simple_strtol(arg, 0, 10) > 10 ? 10 : simple_strtol(arg, 0, 10); - - pAd->CommonCfg.RadarDetect.LongPulseRadarTh = Value; - - DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __FUNCTION__, - pAd->CommonCfg.RadarDetect.LongPulseRadarTh)); - - return TRUE; -} -#endif // DFS_SUPPORT // diff --git a/drivers/staging/rt3090/common/ee_efuse.c b/drivers/staging/rt3090/common/ee_efuse.c deleted file mode 100644 index c51e3059bf4cd725d0ae08742f7620707e61f6d3..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/ee_efuse.c +++ /dev/null @@ -1,1548 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - ee_efuse.c - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#include "../rt_config.h" - - -#define EFUSE_USAGE_MAP_START 0x2d0 -#define EFUSE_USAGE_MAP_END 0x2fc -#define EFUSE_USAGE_MAP_SIZE 45 - - - -#define EFUSE_EEPROM_DEFULT_FILE "RT30xxEEPROM.bin" -#define MAX_EEPROM_BIN_FILE_SIZE 1024 - - - -#define EFUSE_TAG 0x2fe - - -#ifdef RT_BIG_ENDIAN -typedef union _EFUSE_CTRL_STRUC { - struct { - UINT32 SEL_EFUSE:1; - UINT32 EFSROM_KICK:1; - UINT32 RESERVED:4; - UINT32 EFSROM_AIN:10; - UINT32 EFSROM_LDO_ON_TIME:2; - UINT32 EFSROM_LDO_OFF_TIME:6; - UINT32 EFSROM_MODE:2; - UINT32 EFSROM_AOUT:6; - } field; - UINT32 word; -} EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC; -#else -typedef union _EFUSE_CTRL_STRUC { - struct { - UINT32 EFSROM_AOUT:6; - UINT32 EFSROM_MODE:2; - UINT32 EFSROM_LDO_OFF_TIME:6; - UINT32 EFSROM_LDO_ON_TIME:2; - UINT32 EFSROM_AIN:10; - UINT32 RESERVED:4; - UINT32 EFSROM_KICK:1; - UINT32 SEL_EFUSE:1; - } field; - UINT32 word; -} EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC; -#endif // RT_BIG_ENDIAN // - -static UCHAR eFuseReadRegisters( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - OUT USHORT* pData); - -static VOID eFuseReadPhysical( - IN PRTMP_ADAPTER pAd, - IN PUSHORT lpInBuffer, - IN ULONG nInBufferSize, - OUT PUSHORT lpOutBuffer, - IN ULONG nOutBufferSize); - -static VOID eFusePhysicalWriteRegisters( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - OUT USHORT* pData); - -static NTSTATUS eFuseWriteRegisters( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - IN USHORT* pData); - -static VOID eFuseWritePhysical( - IN PRTMP_ADAPTER pAd, - PUSHORT lpInBuffer, - ULONG nInBufferSize, - PUCHAR lpOutBuffer, - ULONG nOutBufferSize); - - -static NTSTATUS eFuseWriteRegistersFromBin( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - IN USHORT* pData); - - -/* -======================================================================== - - Routine Description: - - Arguments: - - Return Value: - - Note: - -======================================================================== -*/ -UCHAR eFuseReadRegisters( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - OUT USHORT* pData) -{ - EFUSE_CTRL_STRUC eFuseCtrlStruc; - int i; - USHORT efuseDataOffset; - UINT32 data; - - RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); - - //Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. - //Use the eeprom logical address and covert to address to block number - eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; - - //Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 0. - eFuseCtrlStruc.field.EFSROM_MODE = 0; - - //Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. - eFuseCtrlStruc.field.EFSROM_KICK = 1; - - NdisMoveMemory(&data, &eFuseCtrlStruc, 4); - RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); - - //Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. - i = 0; - while(i < 500) - { - //rtmp.HwMemoryReadDword(EFUSE_CTRL, (DWORD *) &eFuseCtrlStruc, 4); - RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); - if(eFuseCtrlStruc.field.EFSROM_KICK == 0) - { - break; - } - RTMPusecDelay(2); - i++; - } - - //if EFSROM_AOUT is not found in physical address, write 0xffff - if (eFuseCtrlStruc.field.EFSROM_AOUT == 0x3f) - { - for(i=0; i> (8*(Offset & 0x3)); -#endif // RT_BIG_ENDIAN // - - NdisMoveMemory(pData, &data, Length); - } - - return (UCHAR) eFuseCtrlStruc.field.EFSROM_AOUT; - -} - -/* -======================================================================== - - Routine Description: - - Arguments: - - Return Value: - - Note: - -======================================================================== -*/ -VOID eFusePhysicalReadRegisters( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - OUT USHORT* pData) -{ - EFUSE_CTRL_STRUC eFuseCtrlStruc; - int i; - USHORT efuseDataOffset; - UINT32 data; - - RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); - - //Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. - eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; - - //Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1. - //Read in physical view - eFuseCtrlStruc.field.EFSROM_MODE = 1; - - //Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. - eFuseCtrlStruc.field.EFSROM_KICK = 1; - - NdisMoveMemory(&data, &eFuseCtrlStruc, 4); - RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); - - //Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. - i = 0; - while(i < 500) - { - RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); - if(eFuseCtrlStruc.field.EFSROM_KICK == 0) - break; - RTMPusecDelay(2); - i++; - } - - //Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590) - //Because the size of each EFUSE_DATA is 4 Bytes, the size of address of each is 2 bits. - //The previous 2 bits is the EFUSE_DATA number, the last 2 bits is used to decide which bytes - //Decide which EFUSE_DATA to read - //590:F E D C - //594:B A 9 8 - //598:7 6 5 4 - //59C:3 2 1 0 - efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC) ; - - RTMP_IO_READ32(pAd, efuseDataOffset, &data); - -#ifdef RT_BIG_ENDIAN - data = data << (8*((Offset & 0x3)^0x2)); -#else - data = data >> (8*(Offset & 0x3)); -#endif // RT_BIG_ENDIAN // - - NdisMoveMemory(pData, &data, Length); - -} - -/* -======================================================================== - - Routine Description: - - Arguments: - - Return Value: - - Note: - -======================================================================== -*/ -static VOID eFuseReadPhysical( - IN PRTMP_ADAPTER pAd, - IN PUSHORT lpInBuffer, - IN ULONG nInBufferSize, - OUT PUSHORT lpOutBuffer, - IN ULONG nOutBufferSize -) -{ - USHORT* pInBuf = (USHORT*)lpInBuffer; - USHORT* pOutBuf = (USHORT*)lpOutBuffer; - - USHORT Offset = pInBuf[0]; //addr - USHORT Length = pInBuf[1]; //length - int i; - - for(i=0; i> 2; - data = pData[0] & 0xffff; - //The offset should be 0x***10 or 0x***00 - if((Offset % 4) != 0) - { - eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff) | (data << 16); - } - else - { - eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff0000) | data; - } - - efuseDataOffset = EFUSE_DATA3; - for(i=0; i< 4; i++) - { - RTMP_IO_WRITE32(pAd, efuseDataOffset, eFuseDataBuffer[i]); - efuseDataOffset -= 4; - } - ///////////////////////////////////////////////////////////////// - - //Step1. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. - - RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); - - eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; - - //Step2. Write EFSROM_MODE (0x580, bit7:bit6) to 3. - eFuseCtrlStruc.field.EFSROM_MODE = 3; - - //Step3. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical write procedure. - eFuseCtrlStruc.field.EFSROM_KICK = 1; - - NdisMoveMemory(&data, &eFuseCtrlStruc, 4); - RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); - - //Step4. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. It��s done. - i = 0; - - while(i < 500) - { - RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); - - if(eFuseCtrlStruc.field.EFSROM_KICK == 0) - break; - - RTMPusecDelay(2); - i++; - } -} - -/* -======================================================================== - - Routine Description: - - Arguments: - - Return Value: - - Note: - -======================================================================== -*/ -static NTSTATUS eFuseWriteRegisters( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - IN USHORT* pData) -{ - USHORT i,Loop=0; - USHORT eFuseData; - USHORT LogicalAddress, BlkNum = 0xffff; - UCHAR EFSROM_AOUT; - - USHORT addr,tmpaddr, InBuf[3], tmpOffset; - USHORT buffer[8]; - BOOLEAN bWriteSuccess = TRUE; - - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters Offset=%x, pData=%x\n", Offset, *pData)); - - //Step 0. find the entry in the mapping table - //The address of EEPROM is 2-bytes alignment. - //The last bit is used for alignment, so it must be 0. - tmpOffset = Offset & 0xfffe; - EFSROM_AOUT = eFuseReadRegisters(pAd, tmpOffset, 2, &eFuseData); - - if( EFSROM_AOUT == 0x3f) - { //find available logical address pointer - //the logical address does not exist, find an empty one - //from the first address of block 45=16*45=0x2d0 to the last address of block 47 - //==>48*16-3(reserved)=2FC - for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2) - { - //Retrive the logical block nubmer form each logical address pointer - //It will access two logical address pointer each time. - eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); - if( (LogicalAddress & 0xff) == 0) - {//Not used logical address pointer - BlkNum = i-EFUSE_USAGE_MAP_START; - break; - } - else if(( (LogicalAddress >> 8) & 0xff) == 0) - {//Not used logical address pointer - if (i != EFUSE_USAGE_MAP_END) - { - BlkNum = i-EFUSE_USAGE_MAP_START+1; - } - break; - } - } - } - else - { - BlkNum = EFSROM_AOUT; - } - - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters BlkNum = %d \n", BlkNum)); - - if(BlkNum == 0xffff) - { - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); - return FALSE; - } - - //Step 1. Save data of this block which is pointed by the avaible logical address pointer - // read and save the original block data - for(i =0; i<8; i++) - { - addr = BlkNum * 0x10 ; - - InBuf[0] = addr+2*i; - InBuf[1] = 2; - InBuf[2] = 0x0; - - eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); - - buffer[i] = InBuf[2]; - } - - //Step 2. Update the data in buffer, and write the data to Efuse - buffer[ (Offset >> 1) % 8] = pData[0]; - - do - { Loop++; - //Step 3. Write the data to Efuse - if(!bWriteSuccess) - { - for(i =0; i<8; i++) - { - addr = BlkNum * 0x10 ; - - InBuf[0] = addr+2*i; - InBuf[1] = 2; - InBuf[2] = buffer[i]; - - eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); - } - } - else - { - addr = BlkNum * 0x10 ; - - InBuf[0] = addr+(Offset % 16); - InBuf[1] = 2; - InBuf[2] = pData[0]; - - eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); - } - - //Step 4. Write mapping table - addr = EFUSE_USAGE_MAP_START+BlkNum; - - tmpaddr = addr; - - if(addr % 2 != 0) - addr = addr -1; - InBuf[0] = addr; - InBuf[1] = 2; - - //convert the address from 10 to 8 bit ( bit7, 6 = parity and bit5 ~ 0 = bit9~4), and write to logical map entry - tmpOffset = Offset; - tmpOffset >>= 4; - tmpOffset |= ((~((tmpOffset & 0x01) ^ ( tmpOffset >> 1 & 0x01) ^ (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01))) << 6) & 0x40; - tmpOffset |= ((~( (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01) ^ (tmpOffset >> 4 & 0x01) ^ ( tmpOffset >> 5 & 0x01))) << 7) & 0x80; - - // write the logical address - if(tmpaddr%2 != 0) - InBuf[2] = tmpOffset<<8; - else - InBuf[2] = tmpOffset; - - eFuseWritePhysical(pAd,&InBuf[0], 6, NULL, 0); - - //Step 5. Compare data if not the same, invalidate the mapping entry, then re-write the data until E-fuse is exhausted - bWriteSuccess = TRUE; - for(i =0; i<8; i++) - { - addr = BlkNum * 0x10 ; - - InBuf[0] = addr+2*i; - InBuf[1] = 2; - InBuf[2] = 0x0; - - eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); - - if(buffer[i] != InBuf[2]) - { - bWriteSuccess = FALSE; - break; - } - } - - //Step 6. invlidate mapping entry and find a free mapping entry if not succeed - if (!bWriteSuccess) - { - DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess BlkNum = %d\n", BlkNum)); - - // the offset of current mapping entry - addr = EFUSE_USAGE_MAP_START+BlkNum; - - //find a new mapping entry - BlkNum = 0xffff; - for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2) - { - eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); - if( (LogicalAddress & 0xff) == 0) - { - BlkNum = i-EFUSE_USAGE_MAP_START; - break; - } - else if(( (LogicalAddress >> 8) & 0xff) == 0) - { - if (i != EFUSE_USAGE_MAP_END) - { - BlkNum = i+1-EFUSE_USAGE_MAP_START; - } - break; - } - } - DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess new BlkNum = %d\n", BlkNum)); - if(BlkNum == 0xffff) - { - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); - return FALSE; - } - - //invalidate the original mapping entry if new entry is not found - tmpaddr = addr; - - if(addr % 2 != 0) - addr = addr -1; - InBuf[0] = addr; - InBuf[1] = 2; - - eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); - - // write the logical address - if(tmpaddr%2 != 0) - { - // Invalidate the high byte - for (i=8; i<15; i++) - { - if( ( (InBuf[2] >> i) & 0x01) == 0) - { - InBuf[2] |= (0x1 <> i) & 0x01) == 0) - { - InBuf[2] |= (0x1 <bUseEfuse) - return FALSE; - for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i+=2) - { - eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); - if( (LogicalAddress & 0xff) == 0) - { - efusefreenum= (UCHAR) (EFUSE_USAGE_MAP_END-i+1); - break; - } - else if(( (LogicalAddress >> 8) & 0xff) == 0) - { - efusefreenum = (UCHAR) (EFUSE_USAGE_MAP_END-i); - break; - } - - if(i == EFUSE_USAGE_MAP_END) - efusefreenum = 0; - } - printk("efuseFreeNumber is %d\n",efusefreenum); - return TRUE; -} - - -INT set_eFusedump_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ -USHORT InBuf[3]; - INT i=0; - if(!pAd->bUseEfuse) - return FALSE; - for(i =0; i0) - NdisMoveMemory(src, arg, strlen(arg)); - else - NdisMoveMemory(src, EFUSE_EEPROM_DEFULT_FILE, strlen(EFUSE_EEPROM_DEFULT_FILE)); - DBGPRINT(RT_DEBUG_TRACE, ("FileName=%s\n",src)); - - RtmpOSFSInfoChange(&osfsInfo, TRUE); - - srcf = RtmpOSFileOpen(src, O_RDONLY, 0); - if (IS_FILE_OPEN_ERR(srcf)) - { - DBGPRINT(RT_DEBUG_ERROR, ("--> Error opening file %s\n", src)); - retval = FALSE; - goto recoverFS; - } - else - { - // The object must have a read method - while(RtmpOSFileRead(srcf, &buffer[i], 1)==1) - { - i++; - if(i>MAX_EEPROM_BIN_FILE_SIZE) - { - DBGPRINT(RT_DEBUG_ERROR, ("--> Error reading file %s, file size too large[>%d]\n", src, MAX_EEPROM_BIN_FILE_SIZE)); - retval = FALSE; - goto closeFile; - } - } - - retval = RtmpOSFileClose(srcf); - if (retval) - DBGPRINT(RT_DEBUG_TRACE, ("--> Error closing file %s\n", src)); - } - - - RtmpOSFSInfoChange(&osfsInfo, FALSE); - - for(j=0;j48*16-3(reserved)=2FC - bAllocateNewBlk=TRUE; - for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2) - { - //Retrive the logical block nubmer form each logical address pointer - //It will access two logical address pointer each time. - eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); - if( (LogicalAddress & 0xff) == 0) - {//Not used logical address pointer - BlkNum = i-EFUSE_USAGE_MAP_START; - break; - } - else if(( (LogicalAddress >> 8) & 0xff) == 0) - {//Not used logical address pointer - if (i != EFUSE_USAGE_MAP_END) - { - BlkNum = i-EFUSE_USAGE_MAP_START+1; - } - break; - } - } - } - else - { - bAllocateNewBlk=FALSE; - BlkNum = EFSROM_AOUT; - } - - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters BlkNum = %d \n", BlkNum)); - - if(BlkNum == 0xffff) - { - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); - return FALSE; - } - //Step 1.1.0 - //If the block is not existing in mapping table, create one - //and write down the 16-bytes data to the new block - if(bAllocateNewBlk) - { - DBGPRINT(RT_DEBUG_TRACE, ("Allocate New Blk\n")); - efuseDataOffset = EFUSE_DATA3; - for(i=0; i< 4; i++) - { - DBGPRINT(RT_DEBUG_TRACE, ("Allocate New Blk, Data%d=%04x%04x\n",3-i,pData[2*i+1],pData[2*i])); - tempbuffer=((pData[2*i+1]<<16)&0xffff0000)|pData[2*i]; - - - RTMP_IO_WRITE32(pAd, efuseDataOffset,tempbuffer); - efuseDataOffset -= 4; - - } - ///////////////////////////////////////////////////////////////// - - //Step1.1.1. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. - RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); - eFuseCtrlStruc.field.EFSROM_AIN = BlkNum* 0x10 ; - - //Step1.1.2. Write EFSROM_MODE (0x580, bit7:bit6) to 3. - eFuseCtrlStruc.field.EFSROM_MODE = 3; - - //Step1.1.3. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical write procedure. - eFuseCtrlStruc.field.EFSROM_KICK = 1; - - NdisMoveMemory(&data, &eFuseCtrlStruc, 4); - - RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); - - //Step1.1.4. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. It��s done. - i = 0; - while(i < 100) - { - RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); - - if(eFuseCtrlStruc.field.EFSROM_KICK == 0) - break; - - RTMPusecDelay(2); - i++; - } - - } - else - { //Step1.2. - //If the same logical number is existing, check if the writting data and the data - //saving in this block are the same. - ///////////////////////////////////////////////////////////////// - //read current values of 16-byte block - RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); - - //Step1.2.0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. - eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; - - //Step1.2.1. Write EFSROM_MODE (0x580, bit7:bit6) to 1. - eFuseCtrlStruc.field.EFSROM_MODE = 0; - - //Step1.2.2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. - eFuseCtrlStruc.field.EFSROM_KICK = 1; - - NdisMoveMemory(&data, &eFuseCtrlStruc, 4); - RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); - - //Step1.2.3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. - i = 0; - while(i < 500) - { - RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); - - if(eFuseCtrlStruc.field.EFSROM_KICK == 0) - break; - RTMPusecDelay(2); - i++; - } - - //Step1.2.4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590) - efuseDataOffset = EFUSE_DATA3; - for(i=0; i< 4; i++) - { - RTMP_IO_READ32(pAd, efuseDataOffset, (PUINT32) &buffer[i]); - efuseDataOffset -= 4; - } - //Step1.2.5. Check if the data of efuse and the writing data are the same. - for(i =0; i<4; i++) - { - tempbuffer=((pData[2*i+1]<<16)&0xffff0000)|pData[2*i]; - DBGPRINT(RT_DEBUG_TRACE, ("buffer[%d]=%x,pData[%d]=%x,pData[%d]=%x,tempbuffer=%x\n",i,buffer[i],2*i,pData[2*i],2*i+1,pData[2*i+1],tempbuffer)); - - if(((buffer[i]&0xffff0000)==(pData[2*i+1]<<16))&&((buffer[i]&0xffff)==pData[2*i])) - bNotWrite&=TRUE; - else - { - bNotWrite&=FALSE; - break; - } - } - if(!bNotWrite) - { - printk("The data is not the same\n"); - - for(i =0; i<8; i++) - { - addr = BlkNum * 0x10 ; - - InBuf[0] = addr+2*i; - InBuf[1] = 2; - InBuf[2] = pData[i]; - - eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); - } - - } - else - return TRUE; - } - - - - //Step 2. Write mapping table - addr = EFUSE_USAGE_MAP_START+BlkNum; - - tmpaddr = addr; - - if(addr % 2 != 0) - addr = addr -1; - InBuf[0] = addr; - InBuf[1] = 2; - - //convert the address from 10 to 8 bit ( bit7, 6 = parity and bit5 ~ 0 = bit9~4), and write to logical map entry - tmpOffset = Offset; - tmpOffset >>= 4; - tmpOffset |= ((~((tmpOffset & 0x01) ^ ( tmpOffset >> 1 & 0x01) ^ (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01))) << 6) & 0x40; - tmpOffset |= ((~( (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01) ^ (tmpOffset >> 4 & 0x01) ^ ( tmpOffset >> 5 & 0x01))) << 7) & 0x80; - - // write the logical address - if(tmpaddr%2 != 0) - InBuf[2] = tmpOffset<<8; - else - InBuf[2] = tmpOffset; - - eFuseWritePhysical(pAd,&InBuf[0], 6, NULL, 0); - - //Step 3. Compare data if not the same, invalidate the mapping entry, then re-write the data until E-fuse is exhausted - bWriteSuccess = TRUE; - for(i =0; i<8; i++) - { - addr = BlkNum * 0x10 ; - - InBuf[0] = addr+2*i; - InBuf[1] = 2; - InBuf[2] = 0x0; - - eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); - DBGPRINT(RT_DEBUG_TRACE, ("addr=%x, buffer[i]=%x,InBuf[2]=%x\n",InBuf[0],pData[i],InBuf[2])); - if(pData[i] != InBuf[2]) - { - bWriteSuccess = FALSE; - break; - } - } - - //Step 4. invlidate mapping entry and find a free mapping entry if not succeed - - if (!bWriteSuccess&&Loop<2) - { - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin::Not bWriteSuccess BlkNum = %d\n", BlkNum)); - - // the offset of current mapping entry - addr = EFUSE_USAGE_MAP_START+BlkNum; - - //find a new mapping entry - BlkNum = 0xffff; - for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2) - { - eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); - if( (LogicalAddress & 0xff) == 0) - { - BlkNum = i-EFUSE_USAGE_MAP_START; - break; - } - else if(( (LogicalAddress >> 8) & 0xff) == 0) - { - if (i != EFUSE_USAGE_MAP_END) - { - BlkNum = i+1-EFUSE_USAGE_MAP_START; - } - break; - } - } - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin::Not bWriteSuccess new BlkNum = %d\n", BlkNum)); - if(BlkNum == 0xffff) - { - DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin: out of free E-fuse space!!!\n")); - return FALSE; - } - - //invalidate the original mapping entry if new entry is not found - tmpaddr = addr; - - if(addr % 2 != 0) - addr = addr -1; - InBuf[0] = addr; - InBuf[1] = 2; - - eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); - - // write the logical address - if(tmpaddr%2 != 0) - { - // Invalidate the high byte - for (i=8; i<15; i++) - { - if( ( (InBuf[2] >> i) & 0x01) == 0) - { - InBuf[2] |= (0x1 <> i) & 0x01) == 0) - { - InBuf[2] |= (0x1 <bFroceEEPROMBuffer || pAd->bEEPROMFile) - { - DBGPRINT(RT_DEBUG_TRACE, ("Read from EEPROM Buffer\n")); - NdisMoveMemory(pValue, &(pAd->EEPROMImage[Offset]), 2); - } - else - eFuseReadRegisters(pAd, Offset, 2, pValue); - return (*pValue); -} - - -int rtmp_ee_efuse_write16( - IN RTMP_ADAPTER *pAd, - IN USHORT Offset, - IN USHORT data) -{ - if(pAd->bFroceEEPROMBuffer||pAd->bEEPROMFile) - { - DBGPRINT(RT_DEBUG_TRACE, ("Write to EEPROM Buffer\n")); - NdisMoveMemory(&(pAd->EEPROMImage[Offset]), &data, 2); - } - else - eFuseWriteRegisters(pAd, Offset, 2, &data); - return 0; -} - - -int RtmpEfuseSupportCheck( - IN RTMP_ADAPTER *pAd) -{ - USHORT value; - - if (IS_RT30xx(pAd)) - { - eFusePhysicalReadRegisters(pAd, EFUSE_TAG, 2, &value); - pAd->EFuseTag = (value & 0xff); - } - return 0; -} - -INT set_eFuseBufferModeWriteBack_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UINT Enable; - - - if(strlen(arg)>0) - { - Enable= simple_strtol(arg, 0, 16); - } - else - return FALSE; - if(Enable==1) - { - DBGPRINT(RT_DEBUG_TRACE, ("set_eFuseBufferMode_Proc:: Call WRITEEEPROMBUF")); - eFuseWriteEeeppromBuf(pAd); - } - else - return FALSE; - return TRUE; -} - - -/* - ======================================================================== - - Routine Description: - Load EEPROM from bin file for eFuse mode - - Arguments: - Adapter Pointer to our adapter - - Return Value: - NDIS_STATUS_SUCCESS firmware image load ok - NDIS_STATUS_FAILURE image not found - - IRQL = PASSIVE_LEVEL - - ======================================================================== -*/ -INT eFuseLoadEEPROM( - IN PRTMP_ADAPTER pAd) -{ - PSTRING src = NULL; - INT retval; - RTMP_OS_FD srcf; - RTMP_OS_FS_INFO osFSInfo; - - - src=EFUSE_BUFFER_PATH; - DBGPRINT(RT_DEBUG_TRACE, ("FileName=%s\n",src)); - - - RtmpOSFSInfoChange(&osFSInfo, TRUE); - - if (src && *src) - { - srcf = RtmpOSFileOpen(src, O_RDONLY, 0); - if (IS_FILE_OPEN_ERR(srcf)) - { - DBGPRINT(RT_DEBUG_ERROR, ("--> Error %ld opening %s\n", -PTR_ERR(srcf),src)); - return FALSE; - } - else - { - - memset(pAd->EEPROMImage, 0x00, MAX_EEPROM_BIN_FILE_SIZE); - - - retval =RtmpOSFileRead(srcf, (PSTRING)pAd->EEPROMImage, MAX_EEPROM_BIN_FILE_SIZE); - if (retval > 0) - { - RTMPSetProfileParameters(pAd, (PSTRING)pAd->EEPROMImage); - retval = NDIS_STATUS_SUCCESS; - } - else - DBGPRINT(RT_DEBUG_ERROR, ("Read file \"%s\" failed(errCode=%d)!\n", src, retval)); - - } - - - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("--> Error src or srcf is null\n")); - return FALSE; - - } - - retval=RtmpOSFileClose(srcf); - - if (retval) - { - DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src)); - } - - - RtmpOSFSInfoChange(&osFSInfo, FALSE); - - return TRUE; -} - -INT eFuseWriteEeeppromBuf( - IN PRTMP_ADAPTER pAd) -{ - - PSTRING src = NULL; - INT retval; - RTMP_OS_FD srcf; - RTMP_OS_FS_INFO osFSInfo; - - - src=EFUSE_BUFFER_PATH; - DBGPRINT(RT_DEBUG_TRACE, ("FileName=%s\n",src)); - - RtmpOSFSInfoChange(&osFSInfo, TRUE); - - - - if (src && *src) - { - srcf = RtmpOSFileOpen(src, O_WRONLY|O_CREAT, 0); - - if (IS_FILE_OPEN_ERR(srcf)) - { - DBGPRINT(RT_DEBUG_ERROR, ("--> Error %ld opening %s\n", -PTR_ERR(srcf),src)); - return FALSE; - } - else - { -/* - // The object must have a read method - if (srcf->f_op && srcf->f_op->write) - { - // The object must have a read method - srcf->f_op->write(srcf, pAd->EEPROMImage, 1024, &srcf->f_pos); - - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("--> Error!! System doest not support read function\n")); - return FALSE; - } -*/ - - RtmpOSFileWrite(srcf, (PSTRING)pAd->EEPROMImage,MAX_EEPROM_BIN_FILE_SIZE); - - } - - - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("--> Error src or srcf is null\n")); - return FALSE; - - } - - retval=RtmpOSFileClose(srcf); - - if (retval) - { - DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src)); - } - - RtmpOSFSInfoChange(&osFSInfo, FALSE); - return TRUE; -} - - -VOID eFuseGetFreeBlockCount(IN PRTMP_ADAPTER pAd, - PUINT EfuseFreeBlock) -{ - USHORT i; - USHORT LogicalAddress; - if(!pAd->bUseEfuse) - { - DBGPRINT(RT_DEBUG_TRACE,("eFuseGetFreeBlockCount Only supports efuse Mode\n")); - return ; - } - for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i+=2) - { - eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); - if( (LogicalAddress & 0xff) == 0) - { - *EfuseFreeBlock= (UCHAR) (EFUSE_USAGE_MAP_END-i+1); - break; - } - else if(( (LogicalAddress >> 8) & 0xff) == 0) - { - *EfuseFreeBlock = (UCHAR) (EFUSE_USAGE_MAP_END-i); - break; - } - - if(i == EFUSE_USAGE_MAP_END) - *EfuseFreeBlock = 0; - } - DBGPRINT(RT_DEBUG_TRACE,("eFuseGetFreeBlockCount is 0x%x\n",*EfuseFreeBlock)); -} - -INT eFuse_init( - IN PRTMP_ADAPTER pAd) -{ - UINT EfuseFreeBlock=0; - DBGPRINT(RT_DEBUG_ERROR, ("NVM is Efuse and its size =%x[%x-%x] \n",EFUSE_USAGE_MAP_SIZE,EFUSE_USAGE_MAP_START,EFUSE_USAGE_MAP_END)); - eFuseGetFreeBlockCount(pAd, &EfuseFreeBlock); - //If the used block of efuse is less than 5. We assume the default value - // of this efuse is empty and change to the buffer mode in odrder to - //bring up interfaces successfully. - if(EfuseFreeBlock > (EFUSE_USAGE_MAP_END-5)) - { - DBGPRINT(RT_DEBUG_ERROR, ("NVM is Efuse and the information is too less to bring up interface. Force to use EEPROM Buffer Mode\n")); - pAd->bFroceEEPROMBuffer = TRUE; - eFuseLoadEEPROM(pAd); - } - else - pAd->bFroceEEPROMBuffer = FALSE; - DBGPRINT(RT_DEBUG_TRACE, ("NVM is Efuse and force to use EEPROM Buffer Mode=%x\n",pAd->bFroceEEPROMBuffer)); - - return 0; -} diff --git a/drivers/staging/rt3090/common/ee_prom.c b/drivers/staging/rt3090/common/ee_prom.c deleted file mode 100644 index 051cfdee2a157961a4540b4ea75b86512d7a5367..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/ee_prom.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - ee_prom.c - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#include "../rt_config.h" - - -// IRQL = PASSIVE_LEVEL -static inline VOID RaiseClock( - IN PRTMP_ADAPTER pAd, - IN UINT32 *x) -{ - *x = *x | EESK; - RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); - RTMPusecDelay(1); // Max frequency = 1MHz in Spec. definition -} - -// IRQL = PASSIVE_LEVEL -static inline VOID LowerClock( - IN PRTMP_ADAPTER pAd, - IN UINT32 *x) -{ - *x = *x & ~EESK; - RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); - RTMPusecDelay(1); -} - -// IRQL = PASSIVE_LEVEL -static inline USHORT ShiftInBits( - IN PRTMP_ADAPTER pAd) -{ - UINT32 x,i; - USHORT data=0; - - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - - x &= ~( EEDO | EEDI); - - for(i=0; i<16; i++) - { - data = data << 1; - RaiseClock(pAd, &x); - - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - LowerClock(pAd, &x); //prevent read failed - - x &= ~(EEDI); - if(x & EEDO) - data |= 1; - } - - return data; -} - - -// IRQL = PASSIVE_LEVEL -static inline VOID ShiftOutBits( - IN PRTMP_ADAPTER pAd, - IN USHORT data, - IN USHORT count) -{ - UINT32 x,mask; - - mask = 0x01 << (count - 1); - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - - x &= ~(EEDO | EEDI); - - do - { - x &= ~EEDI; - if(data & mask) x |= EEDI; - - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - RaiseClock(pAd, &x); - LowerClock(pAd, &x); - - mask = mask >> 1; - } while(mask); - - x &= ~EEDI; - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); -} - - -// IRQL = PASSIVE_LEVEL -static inline VOID EEpromCleanup( - IN PRTMP_ADAPTER pAd) -{ - UINT32 x; - - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - - x &= ~(EECS | EEDI); - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - RaiseClock(pAd, &x); - LowerClock(pAd, &x); -} - - -static inline VOID EWEN( - IN PRTMP_ADAPTER pAd) -{ - UINT32 x; - - // reset bits and set EECS - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - x &= ~(EEDI | EEDO | EESK); - x |= EECS; - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - // kick a pulse - RaiseClock(pAd, &x); - LowerClock(pAd, &x); - - // output the read_opcode and six pulse in that order - ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5); - ShiftOutBits(pAd, 0, 6); - - EEpromCleanup(pAd); -} - - -static inline VOID EWDS( - IN PRTMP_ADAPTER pAd) -{ - UINT32 x; - - // reset bits and set EECS - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - x &= ~(EEDI | EEDO | EESK); - x |= EECS; - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - // kick a pulse - RaiseClock(pAd, &x); - LowerClock(pAd, &x); - - // output the read_opcode and six pulse in that order - ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5); - ShiftOutBits(pAd, 0, 6); - - EEpromCleanup(pAd); -} - - -// IRQL = PASSIVE_LEVEL -int rtmp_ee_prom_read16( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - OUT USHORT *pValue) -{ - UINT32 x; - USHORT data; - -#ifdef RT30xx -#ifdef ANT_DIVERSITY_SUPPORT - if (pAd->NicConfig2.field.AntDiversity) - { - pAd->EepromAccess = TRUE; - } -#endif // ANT_DIVERSITY_SUPPORT // -#endif // RT30xx // - - Offset /= 2; - // reset bits and set EECS - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - x &= ~(EEDI | EEDO | EESK); - x |= EECS; - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - // patch can not access e-Fuse issue - if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) - { - // kick a pulse - RaiseClock(pAd, &x); - LowerClock(pAd, &x); - } - - // output the read_opcode and register number in that order - ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3); - ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum); - - // Now read the data (16 bits) in from the selected EEPROM word - data = ShiftInBits(pAd); - - EEpromCleanup(pAd); - -#ifdef RT30xx -#ifdef ANT_DIVERSITY_SUPPORT - // Antenna and EEPROM access are both using EESK pin, - // Therefor we should avoid accessing EESK at the same time - // Then restore antenna after EEPROM access - if ((pAd->NicConfig2.field.AntDiversity)/* || (pAd->RfIcType == RFIC_3020)*/) - { - pAd->EepromAccess = FALSE; - AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); - } -#endif // ANT_DIVERSITY_SUPPORT // -#endif // RT30xx // - - *pValue = data; - - return NDIS_STATUS_SUCCESS; -} - - -int rtmp_ee_prom_write16( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Data) -{ - UINT32 x; - -#ifdef RT30xx -#ifdef ANT_DIVERSITY_SUPPORT - if (pAd->NicConfig2.field.AntDiversity) - { - pAd->EepromAccess = TRUE; - } -#endif // ANT_DIVERSITY_SUPPORT // -#endif // RT30xx // - - Offset /= 2; - - EWEN(pAd); - - // reset bits and set EECS - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - x &= ~(EEDI | EEDO | EESK); - x |= EECS; - RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); - - // patch can not access e-Fuse issue - if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) - { - // kick a pulse - RaiseClock(pAd, &x); - LowerClock(pAd, &x); - } - - // output the read_opcode ,register number and data in that order - ShiftOutBits(pAd, EEPROM_WRITE_OPCODE, 3); - ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum); - ShiftOutBits(pAd, Data, 16); // 16-bit access - - // read DO status - RTMP_IO_READ32(pAd, E2PROM_CSR, &x); - - EEpromCleanup(pAd); - - RTMPusecDelay(10000); //delay for twp(MAX)=10ms - - EWDS(pAd); - - EEpromCleanup(pAd); - -#ifdef RT30xx -#ifdef ANT_DIVERSITY_SUPPORT - // Antenna and EEPROM access are both using EESK pin, - // Therefor we should avoid accessing EESK at the same time - // Then restore antenna after EEPROM access - if ((pAd->NicConfig2.field.AntDiversity) /*|| (pAd->RfIcType == RFIC_3020)*/) - { - pAd->EepromAccess = FALSE; - AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); - } -#endif // ANT_DIVERSITY_SUPPORT // -#endif // RT30xx // - - return NDIS_STATUS_SUCCESS; - -} diff --git a/drivers/staging/rt3090/common/eeprom.c b/drivers/staging/rt3090/common/eeprom.c deleted file mode 100644 index 2e837499e5e4c172e2137344d5c992988a434a73..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/eeprom.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - eeprom.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Name Date Modification logs -*/ - -#include "../rt_config.h" - - -INT RtmpChipOpsEepromHook( - IN RTMP_ADAPTER *pAd, - IN INT infType) -{ - RTMP_CHIP_OP *pChipOps = &pAd->chipOps; -#ifdef RT30xx -#ifdef RTMP_EFUSE_SUPPORT - UINT32 eFuseCtrl, MacCsr0; - int index; - - index = 0; - do - { - RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); - pAd->MACVersion = MacCsr0; - - if ((pAd->MACVersion != 0x00) && (pAd->MACVersion != 0xFFFFFFFF)) - break; - - RTMPusecDelay(10); - } while (index++ < 100); - - pAd->bUseEfuse=FALSE; - RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrl); - pAd->bUseEfuse = ( (eFuseCtrl & 0x80000000) == 0x80000000) ? 1 : 0; - if(pAd->bUseEfuse) - { - pChipOps->eeinit = eFuse_init; - pChipOps->eeread = rtmp_ee_efuse_read16; - pChipOps->eewrite = rtmp_ee_efuse_write16; - return 0 ; - } - else - { - pAd->bFroceEEPROMBuffer = FALSE; - DBGPRINT(RT_DEBUG_TRACE, ("NVM is EEPROM\n")); - } -#endif // RTMP_EFUSE_SUPPORT // -#endif // RT30xx // - - switch(infType) - { -#ifdef RTMP_PCI_SUPPORT - case RTMP_DEV_INF_PCI: - pChipOps->eeinit = NULL; - pChipOps->eeread = rtmp_ee_prom_read16; - pChipOps->eewrite = rtmp_ee_prom_write16; - break; -#endif // RTMP_PCI_SUPPORT // - - - default: - DBGPRINT(RT_DEBUG_ERROR, ("RtmpChipOpsEepromHook() failed!\n")); - break; - } - - return 0; -} diff --git a/drivers/staging/rt3090/common/igmp_snoop.c b/drivers/staging/rt3090/common/igmp_snoop.c deleted file mode 100644 index 680658f97f0a20b5433d3409951dc4c7604f241d..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/igmp_snoop.c +++ /dev/null @@ -1,1365 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - */ - - -#ifdef IGMP_SNOOP_SUPPORT - -#include "../rt_config.h" -#include "../ipv6.h" -#include "../igmp_snoop.h" - - -static inline void initFreeEntryList( - IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, - IN PLIST_HEADER pList) -{ - int i; - - for (i = 0; i < FREE_MEMBER_POOL_SIZE; i++) - insertTailList(pList, (PLIST_ENTRY)&(pMulticastFilterTable->freeMemberPool[i])); - - return; -} - -static inline PMEMBER_ENTRY AllocaGrpMemberEntry( - IN PMULTICAST_FILTER_TABLE pMulticastFilterTable) -{ - PMEMBER_ENTRY pMemberEntry; - - RTMP_SEM_LOCK(&pMulticastFilterTable->FreeMemberPoolTabLock); - - pMemberEntry = (PMEMBER_ENTRY)removeHeadList(&pMulticastFilterTable->freeEntryList); - - RTMP_SEM_UNLOCK(&pMulticastFilterTable->FreeMemberPoolTabLock); - - return (PMEMBER_ENTRY)pMemberEntry; -} - -static inline VOID FreeGrpMemberEntry( - IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, - IN PMEMBER_ENTRY pEntry) -{ - RTMP_SEM_LOCK(&pMulticastFilterTable->FreeMemberPoolTabLock); - - insertTailList(&pMulticastFilterTable->freeEntryList, (PLIST_ENTRY)pEntry); - - RTMP_SEM_UNLOCK(&pMulticastFilterTable->FreeMemberPoolTabLock); -} - -static VOID IGMPTableDisplay( - IN PRTMP_ADAPTER pAd); - -static BOOLEAN isIgmpMacAddr( - IN PUCHAR pMacAddr); - -static VOID InsertIgmpMember( - IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, - IN PLIST_HEADER pList, - IN PUCHAR pMemberAddr); - -static VOID DeleteIgmpMember( - IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, - IN PLIST_HEADER pList, - IN PUCHAR pMemberAddr); - -static VOID DeleteIgmpMemberList( - IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, - IN PLIST_HEADER pList); - - -/* - ========================================================================== - Description: - This routine init the entire IGMP table. - ========================================================================== - */ -VOID MulticastFilterTableInit( - IN PMULTICAST_FILTER_TABLE *ppMulticastFilterTable) -{ - // Initialize MAC table and allocate spin lock - *ppMulticastFilterTable = kmalloc(sizeof(MULTICAST_FILTER_TABLE), MEM_ALLOC_FLAG); - if (*ppMulticastFilterTable == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for Multicase filter table, size=%d\n", - __FUNCTION__, sizeof(MULTICAST_FILTER_TABLE))); - return; - } - - NdisZeroMemory(*ppMulticastFilterTable, sizeof(MULTICAST_FILTER_TABLE)); - NdisAllocateSpinLock(&((*ppMulticastFilterTable)->MulticastFilterTabLock)); - - NdisAllocateSpinLock(&((*ppMulticastFilterTable)->FreeMemberPoolTabLock)); - initList(&((*ppMulticastFilterTable)->freeEntryList)); - initFreeEntryList(*ppMulticastFilterTable, &((*ppMulticastFilterTable)->freeEntryList)); - return; -} - -/* - ========================================================================== - Description: - This routine reset the entire IGMP table. - ========================================================================== - */ -VOID MultiCastFilterTableReset( - IN PMULTICAST_FILTER_TABLE *ppMulticastFilterTable) -{ - if(*ppMulticastFilterTable == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__)); - return; - } - - NdisFreeSpinLock(&((*ppMulticastFilterTable)->FreeMemberPoolTabLock)); - NdisFreeSpinLock(&((*ppMulticastFilterTable)->MulticastFilterTabLock)); - kfree(*ppMulticastFilterTable); - *ppMulticastFilterTable = NULL; -} - -/* - ========================================================================== - Description: - Display all entrys in IGMP table - ========================================================================== - */ -static VOID IGMPTableDisplay( - IN PRTMP_ADAPTER pAd) -{ - int i; - MULTICAST_FILTER_TABLE_ENTRY *pEntry = NULL; - PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable; - - if (pMulticastFilterTable == NULL) - { - DBGPRINT(RT_DEBUG_OFF, ("%s Multicase filter table is not ready.\n", __FUNCTION__)); - return; - } - - // if FULL, return - if (pMulticastFilterTable->Size == 0) - { - DBGPRINT(RT_DEBUG_ERROR, ("Table empty.\n")); - return; - } - - // allocate one MAC entry - RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock); - - for (i = 0; i< MAX_LEN_OF_MULTICAST_FILTER_TABLE; i++) - { - // pick up the first available vacancy - if (pMulticastFilterTable->Content[i].Valid == TRUE) - { - PMEMBER_ENTRY pMemberEntry = NULL; - pEntry = &pMulticastFilterTable->Content[i]; - - DBGPRINT(RT_DEBUG_OFF, ("IF(%s) entry #%d, type=%s, GrpId=(%02x:%02x:%02x:%02x:%02x:%02x) memberCnt=%d\n", - RTMP_OS_NETDEV_GET_DEVNAME(pEntry->net_dev), i, (pEntry->type==0 ? "static":"dynamic"), - PRINT_MAC(pEntry->Addr), IgmpMemberCnt(&pEntry->MemberList))); - - pMemberEntry = (PMEMBER_ENTRY)pEntry->MemberList.pHead; - while (pMemberEntry) - { - DBGPRINT(RT_DEBUG_OFF, ("member mac=(%02x:%02x:%02x:%02x:%02x:%02x)\n", - PRINT_MAC(pMemberEntry->Addr))); - - pMemberEntry = pMemberEntry->pNext; - } - } - } - - RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock); - - return; -} - -/* - ========================================================================== - Description: - Add and new entry into MAC table - ========================================================================== - */ -BOOLEAN MulticastFilterTableInsertEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pGrpId, - IN PUCHAR pMemberAddr, - IN PNET_DEV dev, - IN MulticastFilterEntryType type) -{ - UCHAR HashIdx; - int i; - MULTICAST_FILTER_TABLE_ENTRY *pEntry = NULL, *pCurrEntry, *pPrevEntry; - PMEMBER_ENTRY pMemberEntry; - PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable; - - if (pMulticastFilterTable == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__)); - return FALSE; - } - - // if FULL, return - if (pMulticastFilterTable->Size >= MAX_LEN_OF_MULTICAST_FILTER_TABLE) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table full. max-entries = %d\n", - __FUNCTION__, MAX_LEN_OF_MULTICAST_FILTER_TABLE)); - return FALSE; - } - - // check the rule is in table already or not. - if ((pEntry = MulticastFilterTableLookup(pMulticastFilterTable, pGrpId, dev))) - { - // doesn't indicate member mac address. - if(pMemberAddr == NULL) - { - return FALSE; - } - - pMemberEntry = (PMEMBER_ENTRY)pEntry->MemberList.pHead; - - while (pMemberEntry) - { - if (MAC_ADDR_EQUAL(pMemberAddr, pMemberEntry->Addr)) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: already in Members list.\n", __FUNCTION__)); - return FALSE; - } - - pMemberEntry = pMemberEntry->pNext; - } - } - - RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock); - do - { - ULONG Now; - // the multicast entry already exist but doesn't include the member yet. - if (pEntry != NULL && pMemberAddr != NULL) - { - InsertIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr); - break; - } - - // allocate one MAC entry - for (i = 0; i < MAX_LEN_OF_MULTICAST_FILTER_TABLE; i++) - { - // pick up the first available vacancy - pEntry = &pMulticastFilterTable->Content[i]; - NdisGetSystemUpTime(&Now); - if ((pEntry->Valid == TRUE) && (pEntry->type == MCAT_FILTER_DYNAMIC) - && ((Now - pEntry->lastTime) > IGMPMAC_TB_ENTRY_AGEOUT_TIME)) - { - PMULTICAST_FILTER_TABLE_ENTRY pHashEntry; - - HashIdx = MULTICAST_ADDR_HASH_INDEX(pEntry->Addr); - pHashEntry = pMulticastFilterTable->Hash[HashIdx]; - - if ((pEntry->net_dev == pHashEntry->net_dev) - && MAC_ADDR_EQUAL(pEntry->Addr, pHashEntry->Addr)) - { - pMulticastFilterTable->Hash[HashIdx] = pHashEntry->pNext; - pMulticastFilterTable->Size --; - DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 1 - Total= %d\n", pMulticastFilterTable->Size)); - } else - { - while (pHashEntry->pNext) - { - pPrevEntry = pHashEntry; - pHashEntry = pHashEntry->pNext; - if ((pEntry->net_dev == pHashEntry->net_dev) - && MAC_ADDR_EQUAL(pEntry->Addr, pHashEntry->Addr)) - { - pPrevEntry->pNext = pHashEntry->pNext; - pMulticastFilterTable->Size --; - DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size)); - break; - } - } - } - pEntry->Valid = FALSE; - DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList); - } - - if (pEntry->Valid == FALSE) - { - NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY)); - pEntry->Valid = TRUE; - - COPY_MAC_ADDR(pEntry->Addr, pGrpId); - pEntry->net_dev = dev; - NdisGetSystemUpTime(&Now); - pEntry->lastTime = Now; - pEntry->type = type; - initList(&pEntry->MemberList); - if (pMemberAddr != NULL) - InsertIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr); - - pMulticastFilterTable->Size ++; - - DBGPRINT(RT_DEBUG_TRACE, ("MulticastFilterTableInsertEntry -IF(%s) allocate entry #%d, Total= %d\n", RTMP_OS_NETDEV_GET_DEVNAME(dev), i, pMulticastFilterTable->Size)); - break; - } - } - - // add this MAC entry into HASH table - if (pEntry) - { - HashIdx = MULTICAST_ADDR_HASH_INDEX(pGrpId); - if (pMulticastFilterTable->Hash[HashIdx] == NULL) - { - pMulticastFilterTable->Hash[HashIdx] = pEntry; - } else - { - pCurrEntry = pMulticastFilterTable->Hash[HashIdx]; - while (pCurrEntry->pNext != NULL) - pCurrEntry = pCurrEntry->pNext; - pCurrEntry->pNext = pEntry; - } - } - }while(FALSE); - - RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock); - - return TRUE; -} - -/* - ========================================================================== - Description: - Delete a specified client from MAC table - ========================================================================== - */ -BOOLEAN MulticastFilterTableDeleteEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pGrpId, - IN PUCHAR pMemberAddr, - IN PNET_DEV dev) -{ - USHORT HashIdx; - MULTICAST_FILTER_TABLE_ENTRY *pEntry, *pPrevEntry; - PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable; - USHORT Aid = MCAST_WCID; - SST Sst = SST_ASSOC; - UCHAR PsMode = PWR_ACTIVE, Rate; - - if (pMulticastFilterTable == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__)); - return FALSE; - } - - RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock); - - do - { - HashIdx = MULTICAST_ADDR_HASH_INDEX(pGrpId); - pPrevEntry = pEntry = pMulticastFilterTable->Hash[HashIdx]; - - while (pEntry && pEntry->Valid) - { - if ((pEntry->net_dev == dev) - && MAC_ADDR_EQUAL(pEntry->Addr, pGrpId)) - break; - else - { - pPrevEntry = pEntry; - pEntry = pEntry->pNext; - } - } - - // check the rule is in table already or not. - if (pEntry && (pMemberAddr != NULL)) - { - if(APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate)) - DeleteIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr); - if (IgmpMemberCnt(&pEntry->MemberList) > 0) - break; - } - - if (pEntry) - { - if (pEntry == pMulticastFilterTable->Hash[HashIdx]) - { - pMulticastFilterTable->Hash[HashIdx] = pEntry->pNext; - DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList); - NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY)); - pMulticastFilterTable->Size --; - DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 1 - Total= %d\n", pMulticastFilterTable->Size)); - } - else - { - pPrevEntry->pNext = pEntry->pNext; - DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList); - NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY)); - pMulticastFilterTable->Size --; - DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size)); - } - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: the Group doesn't exist.\n", __FUNCTION__)); - } - } while(FALSE); - - RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock); - - return TRUE; -} - -/* - ========================================================================== - Description: - Look up the MAC address in the IGMP table. Return NULL if not found. - Return: - pEntry - pointer to the MAC entry; NULL is not found - ========================================================================== -*/ -PMULTICAST_FILTER_TABLE_ENTRY MulticastFilterTableLookup( - IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, - IN PUCHAR pAddr, - IN PNET_DEV dev) -{ - ULONG HashIdx, Now; - PMULTICAST_FILTER_TABLE_ENTRY pEntry = NULL, pPrev = NULL; - - if (pMulticastFilterTable == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__)); - return NULL; - } - - RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock); - - HashIdx = MULTICAST_ADDR_HASH_INDEX(pAddr); - pEntry = pPrev = pMulticastFilterTable->Hash[HashIdx]; - - while (pEntry && pEntry->Valid) - { - if ((pEntry->net_dev == dev) - && MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) - { - NdisGetSystemUpTime(&Now); - pEntry->lastTime = Now; - break; - } - else - { - NdisGetSystemUpTime(&Now); - if ((pEntry->Valid == TRUE) && (pEntry->type == MCAT_FILTER_DYNAMIC) - && RTMP_TIME_AFTER(Now, pEntry->lastTime+IGMPMAC_TB_ENTRY_AGEOUT_TIME)) - { - // Remove the aged entry - if (pEntry == pMulticastFilterTable->Hash[HashIdx]) - { - pMulticastFilterTable->Hash[HashIdx] = pEntry->pNext; - pPrev = pMulticastFilterTable->Hash[HashIdx]; - DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList); - NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY)); - pMulticastFilterTable->Size --; - pEntry = pPrev; - DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size)); - } - else - { - pPrev->pNext = pEntry->pNext; - DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList); - NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY)); - pMulticastFilterTable->Size --; - pEntry = (pPrev == NULL ? NULL: pPrev->pNext); - DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size)); - } - } - else - { - pPrev = pEntry; - pEntry = pEntry->pNext; - } - } - } - - RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock); - - return pEntry; -} - -VOID IGMPSnooping( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDstMacAddr, - IN PUCHAR pSrcMacAddr, - IN PUCHAR pIpHeader, - IN PNET_DEV pDev) -{ - INT i; - INT IpHeaderLen; - UCHAR GroupType; - UINT16 numOfGroup; - UCHAR IgmpVerType; - PUCHAR pIgmpHeader; - PUCHAR pGroup; - UCHAR AuxDataLen; - UINT16 numOfSources; - PUCHAR pGroupIpAddr; - UCHAR GroupMacAddr[6]; - PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr; - - if(isIgmpPkt(pDstMacAddr, pIpHeader)) - { - IpHeaderLen = (*(pIpHeader + 2) & 0x0f) * 4; - pIgmpHeader = pIpHeader + 2 + IpHeaderLen; - IgmpVerType = (UCHAR)(*(pIgmpHeader)); - - DBGPRINT(RT_DEBUG_TRACE, ("IGMP type=%0x\n", IgmpVerType)); - - switch(IgmpVerType) - { - case IGMP_V1_MEMBERSHIP_REPORT: // IGMP version 1 membership report. - case IGMP_V2_MEMBERSHIP_REPORT: // IGMP version 2 membership report. - pGroupIpAddr = (PUCHAR)(pIgmpHeader + 4); - ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP); - DBGPRINT(RT_DEBUG_TRACE, ("IGMP Group=%02x:%02x:%02x:%02x:%02x:%02x\n", - GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5])); - MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); - break; - - case IGMP_LEAVE_GROUP: // IGMP version 1 and version 2 leave group. - pGroupIpAddr = (PUCHAR)(pIgmpHeader + 4); - ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP); - DBGPRINT(RT_DEBUG_TRACE, ("IGMP Group=%02x:%02x:%02x:%02x:%02x:%02x\n", - GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5])); - MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev); - break; - - case IGMP_V3_MEMBERSHIP_REPORT: // IGMP version 3 membership report. - numOfGroup = ntohs(*((UINT16 *)(pIgmpHeader + 6))); - pGroup = (PUCHAR)(pIgmpHeader + 8); - for (i=0; i < numOfGroup; i++) - { - GroupType = (UCHAR)(*pGroup); - AuxDataLen = (UCHAR)(*(pGroup + 1)); - numOfSources = ntohs(*((UINT16 *)(pGroup + 2))); - pGroupIpAddr = (PUCHAR)(pGroup + 4); - DBGPRINT(RT_DEBUG_TRACE, ("IGMPv3 Type=%d, ADL=%d, numOfSource=%d\n", GroupType, AuxDataLen, numOfSources)); - ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP); - DBGPRINT(RT_DEBUG_TRACE, ("IGMP Group=%02x:%02x:%02x:%02x:%02x:%02x\n", - GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5])); - - do - { - if((GroupType == MODE_IS_EXCLUDE) || (GroupType == CHANGE_TO_EXCLUDE_MODE) || (GroupType == ALLOW_NEW_SOURCES)) - { - MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); - break; - } - - if((GroupType == MODE_IS_INCLUDE) || (GroupType == BLOCK_OLD_SOURCES)) - { - MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev); - break; - } - - if((GroupType == CHANGE_TO_INCLUDE_MODE)) - { - if(numOfSources == 0) - MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev); - else - MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); - break; - } - } while(FALSE); - pGroup += (8 + (numOfSources * 4) + AuxDataLen); - } - break; - - default: - DBGPRINT(RT_DEBUG_TRACE, ("unknow IGMP Type=%d\n", IgmpVerType)); - break; - } - } - - return; -} - - -static BOOLEAN isIgmpMacAddr( - IN PUCHAR pMacAddr) -{ - if((pMacAddr[0] == 0x01) - && (pMacAddr[1] == 0x00) - && (pMacAddr[2] == 0x5e)) - return TRUE; - return FALSE; -} - -BOOLEAN isIgmpPkt( - IN PUCHAR pDstMacAddr, - IN PUCHAR pIpHeader) -{ - UINT16 IpProtocol = ntohs(*((UINT16 *)(pIpHeader))); - UCHAR IgmpProtocol; - - if(!isIgmpMacAddr(pDstMacAddr)) - return FALSE; - - if(IpProtocol == ETH_P_IP) - { - IgmpProtocol = (UCHAR)*(pIpHeader + 11); - if(IgmpProtocol == IGMP_PROTOCOL_DESCRIPTOR) - return TRUE; - } - - return FALSE; -} - -static VOID InsertIgmpMember( - IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, - IN PLIST_HEADER pList, - IN PUCHAR pMemberAddr) -{ - PMEMBER_ENTRY pMemberEntry; - - if(pList == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__)); - return; - } - - if (pMemberAddr == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: invalid member.\n", __FUNCTION__)); - return; - } - - if((pMemberEntry = (PMEMBER_ENTRY)AllocaGrpMemberEntry(pMulticastFilterTable)) != NULL) - { - NdisZeroMemory(pMemberEntry, sizeof(MEMBER_ENTRY)); - COPY_MAC_ADDR(pMemberEntry->Addr, pMemberAddr); - insertTailList(pList, (PLIST_ENTRY)pMemberEntry); - - DBGPRINT(RT_DEBUG_TRACE, ("%s Member Mac=%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, - pMemberEntry->Addr[0], pMemberEntry->Addr[1], pMemberEntry->Addr[2], - pMemberEntry->Addr[3], pMemberEntry->Addr[4], pMemberEntry->Addr[5])); - } - return; -} - -static VOID DeleteIgmpMember( - IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, - IN PLIST_HEADER pList, - IN PUCHAR pMemberAddr) -{ - PMEMBER_ENTRY pCurEntry; - - if((pList == NULL) || (pList->pHead == NULL)) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__)); - return; - } - - if (pMemberAddr == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: invalid member.\n", __FUNCTION__)); - return; - } - - pCurEntry = (PMEMBER_ENTRY)pList->pHead; - while (pCurEntry) - { - if(MAC_ADDR_EQUAL(pMemberAddr, pCurEntry->Addr)) - { - delEntryList(pList, (PLIST_ENTRY)pCurEntry); - FreeGrpMemberEntry(pMulticastFilterTable, pCurEntry); - break; - } - pCurEntry = pCurEntry->pNext; - } - - return; -} - -static VOID DeleteIgmpMemberList( - IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, - IN PLIST_HEADER pList) -{ - PMEMBER_ENTRY pCurEntry, pPrvEntry; - - if((pList == NULL) || (pList->pHead == NULL)) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__)); - return; - } - - pPrvEntry = pCurEntry = (PMEMBER_ENTRY)pList->pHead; - while (pCurEntry) - { - delEntryList(pList, (PLIST_ENTRY)pCurEntry); - pPrvEntry = pCurEntry; - pCurEntry = pCurEntry->pNext; - FreeGrpMemberEntry(pMulticastFilterTable, pPrvEntry); - } - - initList(pList); - return; -} - - -UCHAR IgmpMemberCnt( - IN PLIST_HEADER pList) -{ - if(pList == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__)); - return 0; - } - - return getListSize(pList); -} - -VOID IgmpGroupDelMembers( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pMemberAddr, - IN PNET_DEV pDev) -{ - INT i; - MULTICAST_FILTER_TABLE_ENTRY *pEntry = NULL; - PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable; - - for (i = 0; i < MAX_LEN_OF_MULTICAST_FILTER_TABLE; i++) - { - // pick up the first available vacancy - pEntry = &pMulticastFilterTable->Content[i]; - if (pEntry->Valid == TRUE) - { - if(pMemberAddr != NULL) - { - RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock); - DeleteIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr); - RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock); - } - - if((pEntry->type == MCAT_FILTER_DYNAMIC) - && (IgmpMemberCnt(&pEntry->MemberList) == 0)) - MulticastFilterTableDeleteEntry(pAd, pEntry->Addr, pMemberAddr, pDev); - } - } -} - -INT Set_IgmpSn_Enable_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UINT Enable; - POS_COOKIE pObj; - UCHAR ifIndex; - PNET_DEV pDev; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - ifIndex = pObj->ioctl_if; - - pDev = (ifIndex == MAIN_MBSSID) ? (pAd->net_dev) : (pAd->ApCfg.MBSSID[ifIndex].MSSIDDev); - Enable = (UINT) simple_strtol(arg, 0, 10); - - pAd->ApCfg.MBSSID[ifIndex].IgmpSnoopEnable = (BOOLEAN)(Enable == 0 ? 0 : 1); - DBGPRINT(RT_DEBUG_TRACE, ("%s::(%s) %s\n", __FUNCTION__, RTMP_OS_NETDEV_GET_DEVNAME(pDev), Enable == TRUE ? "Enable IGMP Snooping":"Disable IGMP Snooping")); - - return TRUE; -} - -INT Set_IgmpSn_AddEntry_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - INT i; - BOOLEAN bGroupId = 1; - PSTRING value; - PSTRING thisChar; - UCHAR IpAddr[4]; - UCHAR Addr[ETH_LENGTH_OF_ADDRESS]; - UCHAR GroupId[ETH_LENGTH_OF_ADDRESS]; - PUCHAR *pAddr = (PUCHAR *)&Addr; - PNET_DEV pDev; - POS_COOKIE pObj; - UCHAR ifIndex; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - ifIndex = pObj->ioctl_if; - - pDev = (ifIndex == MAIN_MBSSID) ? (pAd->net_dev) : (pAd->ApCfg.MBSSID[ifIndex].MSSIDDev); - - while ((thisChar = strsep((char **)&arg, "-")) != NULL) - { - // refuse the Member if it's not a MAC address. - if((bGroupId == 0) && (strlen(thisChar) != 17)) - continue; - - if(strlen(thisChar) == 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 - { - for (i=0, value = rstrtok(thisChar,":"); value; value = rstrtok(NULL,":")) - { - if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) - return FALSE; //Invalid - - AtoH(value, &Addr[i++], 1); - } - - if(i != 6) - return FALSE; //Invalid - } - else - { - for (i=0, value = rstrtok(thisChar,"."); value; value = rstrtok(NULL,".")) - { - if((strlen(value) > 0) && (strlen(value) <= 3)) - { - int ii; - for(ii=0; iiOS_Cookie; - ifIndex = pObj->ioctl_if; - - pDev = (ifIndex == MAIN_MBSSID) ? (pAd->net_dev) : (pAd->ApCfg.MBSSID[ifIndex].MSSIDDev); - - while ((thisChar = strsep((char **)&arg, "-")) != NULL) - { - // refuse the Member if it's not a MAC address. - if((bGroupId == 0) && (strlen(thisChar) != 17)) - continue; - - if(strlen(thisChar) == 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 - { - for (i=0, value = rstrtok(thisChar,":"); value; value = rstrtok(NULL,":")) - { - if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) - return FALSE; //Invalid - - AtoH(value, &Addr[i++], 1); - } - - if(i != 6) - return FALSE; //Invalid - } - else - { - for (i=0, value = rstrtok(thisChar,"."); value; value = rstrtok(NULL,".")) - { - if((strlen(value) > 0) && (strlen(value) <= 3)) - { - int ii; - for(ii=0; ii 0 ) - MulticastFilterTableDeleteEntry(pAd, (PUCHAR)GroupId, Addr, pDev); - - bGroupId = 0; - } - - if(memberCnt == 0) - MulticastFilterTableDeleteEntry(pAd, (PUCHAR)GroupId, NULL, pDev); - - DBGPRINT(RT_DEBUG_TRACE, ("%s (%2X:%2X:%2X:%2X:%2X:%2X)\n", - __FUNCTION__, Addr[0], Addr[1], Addr[2], Addr[3], Addr[4], Addr[5])); - - return TRUE; -} - -INT Set_IgmpSn_TabDisplay_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - IGMPTableDisplay(pAd); - return TRUE; -} - -void rtmp_read_igmp_snoop_from_file( - IN PRTMP_ADAPTER pAd, - PSTRING tmpbuf, - PSTRING buffer) -{ - PSTRING macptr; - INT i=0; - - //IgmpSnEnable - if(RTMPGetKeyParameter("IgmpSnEnable", tmpbuf, 128, buffer, TRUE)) - { - for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < pAd->ApCfg.BssidNum); macptr = rstrtok(NULL,";"), i++) - { - if ((strncmp(macptr, "0", 1) == 0)) - pAd->ApCfg.MBSSID[i].IgmpSnoopEnable = FALSE; - else if ((strncmp(macptr, "1", 1) == 0)) - pAd->ApCfg.MBSSID[i].IgmpSnoopEnable = TRUE; - else - pAd->ApCfg.MBSSID[i].IgmpSnoopEnable = FALSE; - - DBGPRINT(RT_DEBUG_TRACE, ("MBSSID[%d].Enable=%d\n", i, pAd->ApCfg.MBSSID[i].IgmpSnoopEnable)); - } - } -} - -NDIS_STATUS IgmpPktInfoQuery( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pSrcBufVA, - IN PNDIS_PACKET pPacket, - IN UCHAR apidx, - OUT BOOLEAN *pInIgmpGroup, - OUT PMULTICAST_FILTER_TABLE_ENTRY *ppGroupEntry) -{ - if(IS_MULTICAST_MAC_ADDR(pSrcBufVA)) - { - BOOLEAN IgmpMldPkt = FALSE; - PUCHAR pIpHeader = pSrcBufVA + 12; - - if(ntohs(*((UINT16 *)(pIpHeader))) == ETH_P_IPV6) - IgmpMldPkt = isMldPkt(pSrcBufVA, pIpHeader, NULL, NULL); - else - IgmpMldPkt = isIgmpPkt(pSrcBufVA, pIpHeader); - - if (IgmpMldPkt) - { - *ppGroupEntry = NULL; - } - else if ((*ppGroupEntry = MulticastFilterTableLookup(pAd->pMulticastFilterTable, pSrcBufVA, - pAd->ApCfg.MBSSID[apidx].MSSIDDev)) == NULL) - { - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - return NDIS_STATUS_FAILURE; - } - *pInIgmpGroup = TRUE; - } - else if (IS_BROADCAST_MAC_ADDR(pSrcBufVA)) - { - PUCHAR pDstIpAddr = pSrcBufVA + 30; // point to Destination of Ip address of IP header. - UCHAR GroupMacAddr[6]; - PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr; - - ConvertMulticastIP2MAC(pDstIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP); - if ((*ppGroupEntry = MulticastFilterTableLookup(pAd->pMulticastFilterTable, pGroupMacAddr, - pAd->ApCfg.MBSSID[apidx].MSSIDDev)) != NULL) - { - *pInIgmpGroup = TRUE; - } - } - return NDIS_STATUS_SUCCESS; -} - -NDIS_STATUS IgmpPktClone( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR QueIdx, - IN PMULTICAST_FILTER_TABLE_ENTRY pGroupEntry) -{ - PNDIS_PACKET pSkbClone = NULL; - PMEMBER_ENTRY pMemberEntry = (PMEMBER_ENTRY)pGroupEntry->MemberList.pHead; - MAC_TABLE_ENTRY *pMacEntry = NULL; - USHORT Aid; - SST Sst = SST_ASSOC; - UCHAR PsMode = PWR_ACTIVE; - UCHAR Rate; - unsigned long IrqFlags; - - // check all members of the IGMP group. - while(pMemberEntry != NULL) - { - pMacEntry = APSsPsInquiry(pAd, pMemberEntry->Addr, &Sst, &Aid, &PsMode, &Rate); - - if (pMacEntry && (Sst == SST_ASSOC) && (PsMode != PWR_SAVE)) - { - pSkbClone = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG); - if(pSkbClone) - { - RTMP_SET_PACKET_WCID(pSkbClone, (UCHAR)Aid); - // Pkt type must set to PKTSRC_NDIS. - // It cause of the deason that APHardTransmit() - // doesn't handle PKTSRC_DRIVER pkt type in version 1.3.0.0. - RTMP_SET_PACKET_SOURCE(pSkbClone, PKTSRC_NDIS); - } - else - { - pMemberEntry = pMemberEntry->pNext; - continue; - } - - // insert the pkt to TxSwQueue. - if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE) - { -#ifdef BLOCK_NET_IF - StopNetIfQueue(pAd, QueIdx, pSkbClone); -#endif // BLOCK_NET_IF // - RELEASE_NDIS_PACKET(pAd, pSkbClone, NDIS_STATUS_FAILURE); - return NDIS_STATUS_FAILURE; - } - else - { - RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); - InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pSkbClone)); - RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); - } - } - pMemberEntry = pMemberEntry->pNext; - } - return NDIS_STATUS_SUCCESS; -} - -static inline BOOLEAN isMldMacAddr( - IN PUCHAR pMacAddr) -{ - return ((pMacAddr[0] == 0x33) && (pMacAddr[1] == 0x33)) ? TRUE : FALSE; -} - -static inline BOOLEAN IsSupportedMldMsg( - IN UINT8 MsgType) -{ - BOOLEAN result = FALSE; - switch(MsgType) - { - case MLD_V1_LISTENER_REPORT: - case MLD_V1_LISTENER_DONE: - case MLD_V2_LISTERNER_REPORT: - result = TRUE; - break; - default: - result = FALSE; - break; - } - - return result; -} - -BOOLEAN isMldPkt( - IN PUCHAR pDstMacAddr, - IN PUCHAR pIpHeader, - OUT UINT8 *pProtoType, - OUT PUCHAR *pMldHeader) -{ - BOOLEAN result = FALSE; - UINT16 IpProtocol = ntohs(*((UINT16 *)(pIpHeader))); - - if(!isMldMacAddr(pDstMacAddr)) - return FALSE; - - if(IpProtocol != ETH_P_IPV6) - return FALSE; - - // skip protocol (2 Bytes). - pIpHeader += 2; - do - { - PRT_IPV6_HDR pIpv6Hdr = (PRT_IPV6_HDR)(pIpHeader); - UINT8 nextProtocol = pIpv6Hdr->nextHdr; - UINT32 offset = IPV6_HDR_LEN; - - while(nextProtocol != IPV6_NEXT_HEADER_ICMPV6) - { - if(IPv6ExtHdrHandle((RT_IPV6_EXT_HDR *)(pIpHeader + offset), &nextProtocol, &offset) == FALSE) - break; - } - - if(nextProtocol == IPV6_NEXT_HEADER_ICMPV6) - { - PRT_ICMPV6_HDR pICMPv6Hdr = (PRT_ICMPV6_HDR)(pIpHeader + offset); - if (IsSupportedMldMsg(pICMPv6Hdr->type) == TRUE) - { - if (pProtoType != NULL) - *pProtoType = pICMPv6Hdr->type; - if (pMldHeader != NULL) - *pMldHeader = (PUCHAR)pICMPv6Hdr; - result = TRUE; - } - } - }while(FALSE); - - return result; -} - -/* MLD v1 messages have the following format: - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Code | Checksum | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Maximum Response Delay | Reserved | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - + + - | | - + Multicast Address + - | | - + + - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/* Version 3 Membership Report Message - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type = 143 | Reserved | Checksum | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Reserved | Number of Group Records (M) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - . . - . Multicast Address Record [1] . - . . - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - . . - . Multicast Address Record [2] . - . . - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | . | - . . . - | . | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - . . - . Multicast Address Record [M] . - . . - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - - where each Group Record has the following internal format: - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Record Type | Aux Data Len | Number of Sources (N) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - * * - | | - * Multicast Address * - | | - * * - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - * * - | | - * Source Address [1] * - | | - * * - | | - +- -+ - | | - * * - | | - * Source Address [2] * - | | - * * - | | - +- -+ - . . . - . . . - . . . - +- -+ - | | - * * - | | - * Source Address [N] * - | | - * * - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - . . - . Auxiliary Data . - . . - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -VOID MLDSnooping( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDstMacAddr, - IN PUCHAR pSrcMacAddr, - IN PUCHAR pIpHeader, - IN PNET_DEV pDev) -{ - INT i; - UCHAR GroupType; - UINT16 numOfGroup; - PUCHAR pGroup; - UCHAR AuxDataLen; - UINT16 numOfSources; - PUCHAR pGroupIpAddr; - UCHAR GroupMacAddr[6]; - PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr; - - UINT8 MldType; - PUCHAR pMldHeader; - - if(isMldPkt(pDstMacAddr, pIpHeader, &MldType, &pMldHeader) == TRUE) - { - DBGPRINT(RT_DEBUG_TRACE, ("MLD type=%0x\n", MldType)); - - switch(MldType) - { - case MLD_V1_LISTENER_REPORT: - // skip Type(1 Byte), code(1 Byte), checksum(2 Bytes), Maximum Rsp Delay(2 Bytes), Reserve(2 Bytes). - pGroupIpAddr = (PUCHAR)(pMldHeader + 8); - ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IPV6); - DBGPRINT(RT_DEBUG_TRACE, ("Group Id=%02x:%02x:%02x:%02x:%02x:%02x\n", - GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5])); - MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); - break; - - case MLD_V1_LISTENER_DONE: - // skip Type(1 Byte), code(1 Byte), checksum(2 Bytes), Maximum Rsp Delay(2 Bytes), Reserve(2 Bytes). - pGroupIpAddr = (PUCHAR)(pMldHeader + 8); - ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IPV6); - DBGPRINT(RT_DEBUG_TRACE, ("Group Id=%02x:%02x:%02x:%02x:%02x:%02x\n", - GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5])); - MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev); - break; - - case MLD_V2_LISTERNER_REPORT: // IGMP version 3 membership report. - numOfGroup = ntohs(*((UINT16 *)(pMldHeader + 6))); - pGroup = (PUCHAR)(pMldHeader + 8); - for (i=0; i < numOfGroup; i++) - { - GroupType = (UCHAR)(*pGroup); - AuxDataLen = (UCHAR)(*(pGroup + 1)); - numOfSources = ntohs(*((UINT16 *)(pGroup + 2))); - pGroupIpAddr = (PUCHAR)(pGroup + 4); - DBGPRINT(RT_DEBUG_TRACE, ("MLDv2 Type=%d, ADL=%d, numOfSource=%d\n", GroupType, AuxDataLen, numOfSources)); - ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IPV6); - DBGPRINT(RT_DEBUG_TRACE, ("MLD Group=%02x:%02x:%02x:%02x:%02x:%02x\n", - GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5])); - - do - { - if((GroupType == MODE_IS_EXCLUDE) || (GroupType == CHANGE_TO_EXCLUDE_MODE) || (GroupType == ALLOW_NEW_SOURCES)) - { - MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); - break; - } - - if((GroupType == MODE_IS_INCLUDE) || (GroupType == BLOCK_OLD_SOURCES)) - { - MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev); - break; - } - - if((GroupType == CHANGE_TO_INCLUDE_MODE)) - { - if(numOfSources == 0) - MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev); - else - MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC); - break; - } - } while(FALSE); - // skip 4 Bytes (Record Type, Aux Data Len, Number of Sources) + a IPv6 address. - pGroup += (4 + IPV6_ADDR_LEN + (numOfSources * 16) + AuxDataLen); - } - break; - - default: - DBGPRINT(RT_DEBUG_TRACE, ("unknow MLD Type=%d\n", MldType)); - break; - } - } - - return; -} - - -#endif // IGMP_SNOOP_SUPPORT // diff --git a/drivers/staging/rt3090/common/mlme.c b/drivers/staging/rt3090/common/mlme.c deleted file mode 100644 index 1613c04c59325b63e91af3486de2439f4f5063d8..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/mlme.c +++ /dev/null @@ -1,6550 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - mlme.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - John Chang 2004-08-25 Modify from RT2500 code base - John Chang 2004-09-06 modified for RT2600 -*/ - -#include "../rt_config.h" -#include - -UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96}; - -UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01}; -UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac}; -UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72}; -UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; -UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; -UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04}; -UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43}; -UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c}; -UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04}; -#ifdef CONFIG_STA_SUPPORT -#ifdef DOT11_N_SUPPORT -UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c}; -#endif // DOT11_N_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - -UCHAR RateSwitchTable[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x11, 0x00, 0, 0, 0, // Initial used item after association - 0x00, 0x00, 0, 40, 101, - 0x01, 0x00, 1, 40, 50, - 0x02, 0x00, 2, 35, 45, - 0x03, 0x00, 3, 20, 45, - 0x04, 0x21, 0, 30, 50, - 0x05, 0x21, 1, 20, 50, - 0x06, 0x21, 2, 20, 50, - 0x07, 0x21, 3, 15, 50, - 0x08, 0x21, 4, 15, 30, - 0x09, 0x21, 5, 10, 25, - 0x0a, 0x21, 6, 8, 25, - 0x0b, 0x21, 7, 8, 25, - 0x0c, 0x20, 12, 15, 30, - 0x0d, 0x20, 13, 8, 20, - 0x0e, 0x20, 14, 8, 20, - 0x0f, 0x20, 15, 8, 25, - 0x10, 0x22, 15, 8, 25, - 0x11, 0x00, 0, 0, 0, - 0x12, 0x00, 0, 0, 0, - 0x13, 0x00, 0, 0, 0, - 0x14, 0x00, 0, 0, 0, - 0x15, 0x00, 0, 0, 0, - 0x16, 0x00, 0, 0, 0, - 0x17, 0x00, 0, 0, 0, - 0x18, 0x00, 0, 0, 0, - 0x19, 0x00, 0, 0, 0, - 0x1a, 0x00, 0, 0, 0, - 0x1b, 0x00, 0, 0, 0, - 0x1c, 0x00, 0, 0, 0, - 0x1d, 0x00, 0, 0, 0, - 0x1e, 0x00, 0, 0, 0, - 0x1f, 0x00, 0, 0, 0, -}; - -UCHAR RateSwitchTable11B[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x04, 0x03, 0, 0, 0, // Initial used item after association - 0x00, 0x00, 0, 40, 101, - 0x01, 0x00, 1, 40, 50, - 0x02, 0x00, 2, 35, 45, - 0x03, 0x00, 3, 20, 45, -}; - -UCHAR RateSwitchTable11BG[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0a, 0x00, 0, 0, 0, // Initial used item after association - 0x00, 0x00, 0, 40, 101, - 0x01, 0x00, 1, 40, 50, - 0x02, 0x00, 2, 35, 45, - 0x03, 0x00, 3, 20, 45, - 0x04, 0x10, 2, 20, 35, - 0x05, 0x10, 3, 16, 35, - 0x06, 0x10, 4, 10, 25, - 0x07, 0x10, 5, 16, 25, - 0x08, 0x10, 6, 10, 25, - 0x09, 0x10, 7, 10, 13, -}; - -UCHAR RateSwitchTable11G[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x08, 0x00, 0, 0, 0, // Initial used item after association - 0x00, 0x10, 0, 20, 101, - 0x01, 0x10, 1, 20, 35, - 0x02, 0x10, 2, 20, 35, - 0x03, 0x10, 3, 16, 35, - 0x04, 0x10, 4, 10, 25, - 0x05, 0x10, 5, 16, 25, - 0x06, 0x10, 6, 10, 25, - 0x07, 0x10, 7, 10, 13, -}; - -#ifdef DOT11_N_SUPPORT -UCHAR RateSwitchTable11N1S[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0c, 0x0a, 0, 0, 0, // Initial used item after association - 0x00, 0x00, 0, 40, 101, - 0x01, 0x00, 1, 40, 50, - 0x02, 0x00, 2, 25, 45, - 0x03, 0x21, 0, 20, 35, - 0x04, 0x21, 1, 20, 35, - 0x05, 0x21, 2, 20, 35, - 0x06, 0x21, 3, 15, 35, - 0x07, 0x21, 4, 15, 30, - 0x08, 0x21, 5, 10, 25, - 0x09, 0x21, 6, 8, 14, - 0x0a, 0x21, 7, 8, 14, - 0x0b, 0x23, 7, 8, 14, -}; - -UCHAR RateSwitchTable11N2S[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0e, 0x0c, 0, 0, 0, // Initial used item after association - 0x00, 0x00, 0, 40, 101, - 0x01, 0x00, 1, 40, 50, - 0x02, 0x00, 2, 25, 45, - 0x03, 0x21, 0, 20, 35, - 0x04, 0x21, 1, 20, 35, - 0x05, 0x21, 2, 20, 35, - 0x06, 0x21, 3, 15, 35, - 0x07, 0x21, 4, 15, 30, - 0x08, 0x20, 11, 15, 30, - 0x09, 0x20, 12, 15, 30, - 0x0a, 0x20, 13, 8, 20, - 0x0b, 0x20, 14, 8, 20, - 0x0c, 0x20, 15, 8, 25, - 0x0d, 0x22, 15, 8, 15, -}; - -UCHAR RateSwitchTable11N3S[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0b, 0x00, 0, 0, 0, // 0x0a, 0x00, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30, 101, - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 15, 50, - 0x04, 0x21, 4, 15, 30, - 0x05, 0x20, 11, 15, 30, // Required by System-Alan @ 20080812 - 0x06, 0x20, 12, 15, 30, // 0x05, 0x20, 12, 15, 30, - 0x07, 0x20, 13, 8, 20, // 0x06, 0x20, 13, 8, 20, - 0x08, 0x20, 14, 8, 20, // 0x07, 0x20, 14, 8, 20, - 0x09, 0x20, 15, 8, 25, // 0x08, 0x20, 15, 8, 25, - 0x0a, 0x22, 15, 8, 25, // 0x09, 0x22, 15, 8, 25, -}; - -UCHAR RateSwitchTable11N2SForABand[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0b, 0x09, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30, 101, - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 15, 50, - 0x04, 0x21, 4, 15, 30, - 0x05, 0x21, 5, 15, 30, - 0x06, 0x20, 12, 15, 30, - 0x07, 0x20, 13, 8, 20, - 0x08, 0x20, 14, 8, 20, - 0x09, 0x20, 15, 8, 25, - 0x0a, 0x22, 15, 8, 25, -}; - -UCHAR RateSwitchTable11N3SForABand[] = { // 3*3 -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0b, 0x09, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30, 101, - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 15, 50, - 0x04, 0x21, 4, 15, 30, - 0x05, 0x21, 5, 15, 30, - 0x06, 0x20, 12, 15, 30, - 0x07, 0x20, 13, 8, 20, - 0x08, 0x20, 14, 8, 20, - 0x09, 0x20, 15, 8, 25, - 0x0a, 0x22, 15, 8, 25, -}; - -UCHAR RateSwitchTable11BGN1S[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0c, 0x0a, 0, 0, 0, // Initial used item after association - 0x00, 0x00, 0, 40, 101, - 0x01, 0x00, 1, 40, 50, - 0x02, 0x00, 2, 25, 45, - 0x03, 0x21, 0, 20, 35, - 0x04, 0x21, 1, 20, 35, - 0x05, 0x21, 2, 20, 35, - 0x06, 0x21, 3, 15, 35, - 0x07, 0x21, 4, 15, 30, - 0x08, 0x21, 5, 10, 25, - 0x09, 0x21, 6, 8, 14, - 0x0a, 0x21, 7, 8, 14, - 0x0b, 0x23, 7, 8, 14, -}; - -UCHAR RateSwitchTable11BGN2S[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0e, 0x0c, 0, 0, 0, // Initial used item after association - 0x00, 0x00, 0, 40, 101, - 0x01, 0x00, 1, 40, 50, - 0x02, 0x00, 2, 25, 45, - 0x03, 0x21, 0, 20, 35, - 0x04, 0x21, 1, 20, 35, - 0x05, 0x21, 2, 20, 35, - 0x06, 0x21, 3, 15, 35, - 0x07, 0x21, 4, 15, 30, - 0x08, 0x20, 11, 15, 30, - 0x09, 0x20, 12, 15, 30, - 0x0a, 0x20, 13, 8, 20, - 0x0b, 0x20, 14, 8, 20, - 0x0c, 0x20, 15, 8, 25, - 0x0d, 0x22, 15, 8, 15, -}; - -UCHAR RateSwitchTable11BGN3S[] = { // 3*3 -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0a, 0x00, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30,101, //50 - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 20, 50, - 0x04, 0x21, 4, 15, 50, - 0x05, 0x20, 20, 15, 30, - 0x06, 0x20, 21, 8, 20, - 0x07, 0x20, 22, 8, 20, - 0x08, 0x20, 23, 8, 25, - 0x09, 0x22, 23, 8, 25, -}; - -UCHAR RateSwitchTable11BGN2SForABand[] = { -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0b, 0x09, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30,101, //50 - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 15, 50, - 0x04, 0x21, 4, 15, 30, - 0x05, 0x21, 5, 15, 30, - 0x06, 0x20, 12, 15, 30, - 0x07, 0x20, 13, 8, 20, - 0x08, 0x20, 14, 8, 20, - 0x09, 0x20, 15, 8, 25, - 0x0a, 0x22, 15, 8, 25, -}; - -UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3 -// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) - 0x0c, 0x09, 0, 0, 0, // Initial used item after association - 0x00, 0x21, 0, 30,101, //50 - 0x01, 0x21, 1, 20, 50, - 0x02, 0x21, 2, 20, 50, - 0x03, 0x21, 3, 15, 50, - 0x04, 0x21, 4, 15, 30, - 0x05, 0x21, 5, 15, 30, - 0x06, 0x21, 12, 15, 30, - 0x07, 0x20, 20, 15, 30, - 0x08, 0x20, 21, 8, 20, - 0x09, 0x20, 22, 8, 20, - 0x0a, 0x20, 23, 8, 25, - 0x0b, 0x22, 23, 8, 25, -}; -#endif // DOT11_N_SUPPORT // - - -extern UCHAR OfdmRateToRxwiMCS[]; -// since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate. -// otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate -ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */, - 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */, - 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */}; - -UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -// e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than -// this value, then it's quaranteed capable of operating in 36 mbps TX rate in -// clean environment. -// TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100 -CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 }; - -UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100}; -USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200}; - -UCHAR SsidIe = IE_SSID; -UCHAR SupRateIe = IE_SUPP_RATES; -UCHAR ExtRateIe = IE_EXT_SUPP_RATES; -#ifdef DOT11_N_SUPPORT -UCHAR HtCapIe = IE_HT_CAP; -UCHAR AddHtInfoIe = IE_ADD_HT; -UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET; -#ifdef DOT11N_DRAFT3 -UCHAR ExtHtCapIe = IE_EXT_CAPABILITY; -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // -UCHAR ErpIe = IE_ERP; -UCHAR DsIe = IE_DS_PARM; -UCHAR TimIe = IE_TIM; -UCHAR WpaIe = IE_WPA; -UCHAR Wpa2Ie = IE_WPA2; -UCHAR IbssIe = IE_IBSS_PARM; -UCHAR Ccx2Ie = IE_CCX_V2; -UCHAR WapiIe = IE_WAPI; - -extern UCHAR WPA_OUI[]; - -UCHAR SES_OUI[] = {0x00, 0x90, 0x4c}; - -UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - - -/* - ========================================================================== - Description: - initialize the MLME task and its data structure (queue, spinlock, - timer, state machines). - - IRQL = PASSIVE_LEVEL - - Return: - always return NDIS_STATUS_SUCCESS - - ========================================================================== -*/ -NDIS_STATUS MlmeInit( - IN PRTMP_ADAPTER pAd) -{ - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - - DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n")); - - do - { - Status = MlmeQueueInit(&pAd->Mlme.Queue); - if(Status != NDIS_STATUS_SUCCESS) - break; - - pAd->Mlme.bRunning = FALSE; - NdisAllocateSpinLock(&pAd->Mlme.TaskLock); - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - BssTableInit(&pAd->ScanTab); - - // init STA state machines - AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc); - AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc); - AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc); - SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc); - -#ifdef QOS_DLS_SUPPORT - DlsStateMachineInit(pAd, &pAd->Mlme.DlsMachine, pAd->Mlme.DlsFunc); -#endif // QOS_DLS_SUPPORT // - - - - // Since we are using switch/case to implement it, the init is different from the above - // state machine init - MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL); - } -#endif // CONFIG_STA_SUPPORT // - - - WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine, pAd->Mlme.WpaFunc); - - - ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc); - - // Init mlme periodic timer - RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE); - - // Set mlme periodic timer - RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV); - - // software-based RX Antenna diversity - RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE); - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { -#ifdef RTMP_PCI_SUPPORT - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - { - // only PCIe cards need these two timers - RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE); - RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE); - } -#endif // RTMP_PCI_SUPPORT // - - RTMPInitTimer(pAd, &pAd->Mlme.LinkDownTimer, GET_TIMER_FUNCTION(LinkDownExec), pAd, FALSE); - - } -#endif // CONFIG_STA_SUPPORT // - - } while (FALSE); - - DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n")); - - return Status; -} - -/* - ========================================================================== - Description: - main loop of the MLME - Pre: - Mlme has to be initialized, and there are something inside the queue - Note: - This function is invoked from MPSetInformation and MPReceive; - This task guarantee only one MlmeHandler will run. - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID MlmeHandler( - IN PRTMP_ADAPTER pAd) -{ - MLME_QUEUE_ELEM *Elem = NULL; -#ifdef APCLI_SUPPORT - SHORT apcliIfIndex; -#endif // APCLI_SUPPORT // - - // Only accept MLME and Frame from peer side, no other (control/data) frame should - // get into this state machine - - NdisAcquireSpinLock(&pAd->Mlme.TaskLock); - if(pAd->Mlme.bRunning) - { - NdisReleaseSpinLock(&pAd->Mlme.TaskLock); - return; - } - else - { - pAd->Mlme.bRunning = TRUE; - } - NdisReleaseSpinLock(&pAd->Mlme.TaskLock); - - while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) - { - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) - { - DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num)); - break; - } - -#ifdef RALINK_ATE - if(ATE_ON(pAd)) - { - DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now in MlmeHandler\n")); - break; - } -#endif // RALINK_ATE // - - //From message type, determine which state machine I should drive - if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) - { - - // if dequeue success - switch (Elem->Machine) - { - // STA state machines -#ifdef CONFIG_STA_SUPPORT - case ASSOC_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem); - break; - case AUTH_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem); - break; - case AUTH_RSP_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem); - break; - case SYNC_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem); - break; - case MLME_CNTL_STATE_MACHINE: - MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem); - break; - case WPA_PSK_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem); - break; - -#ifdef QOS_DLS_SUPPORT - case DLS_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine, Elem); - break; -#endif // QOS_DLS_SUPPORT // - -#endif // CONFIG_STA_SUPPORT // - - case ACTION_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem); - break; - - case WPA_STATE_MACHINE: - StateMachinePerformAction(pAd, &pAd->Mlme.WpaMachine, Elem); - break; - - - default: - DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine)); - break; - } // end of switch - - // free MLME element - Elem->Occupied = FALSE; - Elem->MsgLen = 0; - - } - else { - DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n")); - } - } - - NdisAcquireSpinLock(&pAd->Mlme.TaskLock); - pAd->Mlme.bRunning = FALSE; - NdisReleaseSpinLock(&pAd->Mlme.TaskLock); -} - -/* - ========================================================================== - Description: - Destructor of MLME (Destroy queue, state machine, spin lock and timer) - Parameters: - Adapter - NIC Adapter pointer - Post: - The MLME task will no longer work properly - - IRQL = PASSIVE_LEVEL - - ========================================================================== - */ -VOID MlmeHalt( - IN PRTMP_ADAPTER pAd) -{ - BOOLEAN Cancelled; - - DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n")); - - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) - { - // disable BEACON generation and other BEACON related hardware timers - AsicDisableSync(pAd); - } - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { -#ifdef QOS_DLS_SUPPORT - UCHAR i; -#endif // QOS_DLS_SUPPORT // - // Cancel pending timers - RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); - - -#ifdef RTMP_MAC_PCI - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) - &&(pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) - { - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); - } -#endif // RTMP_MAC_PCI // - -#ifdef QOS_DLS_SUPPORT - for (i=0; iStaCfg.DLSEntry[i].Timer, &Cancelled); - } -#endif // QOS_DLS_SUPPORT // - RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled); - - } -#endif // CONFIG_STA_SUPPORT // - - RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); - RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled); - - - - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) - { - RTMP_CHIP_OP *pChipOps = &pAd->chipOps; - - // Set LED - RTMPSetLED(pAd, LED_HALT); - RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it. - - if (pChipOps->AsicHaltAction) - pChipOps->AsicHaltAction(pAd); - } - - RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled - - MlmeQueueDestroy(&pAd->Mlme.Queue); - NdisFreeSpinLock(&pAd->Mlme.TaskLock); - - DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n")); -} - -VOID MlmeResetRalinkCounters( - IN PRTMP_ADAPTER pAd) -{ - pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt; - // clear all OneSecxxx counters. - pAd->RalinkCounters.OneSecBeaconSentCnt = 0; - pAd->RalinkCounters.OneSecFalseCCACnt = 0; - pAd->RalinkCounters.OneSecRxFcsErrCnt = 0; - pAd->RalinkCounters.OneSecRxOkCnt = 0; - pAd->RalinkCounters.OneSecTxFailCount = 0; - pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0; - pAd->RalinkCounters.OneSecTxRetryOkCount = 0; - pAd->RalinkCounters.OneSecRxOkDataCnt = 0; - pAd->RalinkCounters.OneSecReceivedByteCount = 0; - pAd->RalinkCounters.OneSecTransmittedByteCount = 0; - - // TODO: for debug only. to be removed - pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0; - pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0; - pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0; - pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0; - pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0; - pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0; - pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0; - pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0; - pAd->RalinkCounters.OneSecTxDoneCount = 0; - pAd->RalinkCounters.OneSecRxCount = 0; - pAd->RalinkCounters.OneSecTxAggregationCount = 0; - pAd->RalinkCounters.OneSecRxAggregationCount = 0; - - return; -} - - -/* - ========================================================================== - Description: - This routine is executed periodically to - - 1. Decide if it's a right time to turn on PwrMgmt bit of all - outgoiing frames - 2. Calculate ChannelQuality based on statistics of the last - period, so that TX rate won't toggling very frequently between a - successful TX and a failed TX. - 3. If the calculated ChannelQuality indicated current connection not - healthy, then a ROAMing attempt is tried here. - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -#define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec -VOID MlmePeriodicExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - ULONG TxTotalCnt; - PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; - SHORT realavgrssi; - -#ifdef CONFIG_STA_SUPPORT -#ifdef RTMP_MAC_PCI - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second. - // Move code to here, because following code will return when radio is off - if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) && (pAd->StaCfg.bHardwareRadio == TRUE) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) - /*&&(pAd->bPCIclkOff == FALSE)*/) - { - UINT32 data = 0; - - // Read GPIO pin2 as Hardware controlled radio state -#ifndef RT3090 - RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data); -#endif // RT3090 // -//KH(PCIE PS):Added based on Jane<-- -#ifdef RT3090 -// Read GPIO pin2 as Hardware controlled radio state -// We need to Read GPIO if HW said so no mater what advance power saving -if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) - && (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) - && (pAd->StaCfg.PSControl.field.EnablePSinIdle == TRUE)) - { - // Want to make sure device goes to L0 state before reading register. - RTMPPCIeLinkCtrlValueRestore(pAd, 0); - RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data); - RTMPPCIeLinkCtrlSetting(pAd, 3); - } -else - RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data); -#endif // RT3090 // -//KH(PCIE PS):Added based on Jane--> - - if (data & 0x04) - { - pAd->StaCfg.bHwRadio = TRUE; - } - else - { - pAd->StaCfg.bHwRadio = FALSE; - } - if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) - { - pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); - if (pAd->StaCfg.bRadio == TRUE) - { - MlmeRadioOn(pAd); - // Update extra information - pAd->ExtraInfo = EXTRA_INFO_CLEAR; - } - else - { - MlmeRadioOff(pAd); - // Update extra information - pAd->ExtraInfo = HW_RADIO_OFF; - } - } - } - } -#endif // RTMP_MAC_PCI // -#endif // CONFIG_STA_SUPPORT // - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_RADIO_OFF | - fRTMP_ADAPTER_RADIO_MEASUREMENT | - fRTMP_ADAPTER_RESET_IN_PROGRESS)))) - return; - - RTMP_MLME_PRE_SANITY_CHECK(pAd); - -#ifdef RALINK_ATE - /* Do not show RSSI until "Normal 1 second Mlme PeriodicExec". */ - if (ATE_ON(pAd)) - { - if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE != (MLME_TASK_EXEC_MULTIPLE - 1)) - { - pAd->Mlme.PeriodicRound ++; - return; - } - } -#endif // RALINK_ATE // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // Do nothing if monitor mode is on - if (MONITOR_ON(pAd)) - return; - - if (pAd->Mlme.PeriodicRound & 0x1) - { - // This is the fix for wifi 11n extension channel overlapping test case. for 2860D - if (((pAd->MACVersion & 0xffff) == 0x0101) && - (STA_TGN_WIFI_ON(pAd)) && - (pAd->CommonCfg.IOTestParm.bToggle == FALSE)) - - { - RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf); - pAd->CommonCfg.IOTestParm.bToggle = TRUE; - } - else if ((STA_TGN_WIFI_ON(pAd)) && - ((pAd->MACVersion & 0xffff) == 0x0101)) - { - RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f); - pAd->CommonCfg.IOTestParm.bToggle = FALSE; - } - } - } -#endif // CONFIG_STA_SUPPORT // - - pAd->bUpdateBcnCntDone = FALSE; - -// RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3); - pAd->Mlme.PeriodicRound ++; - - - // execute every 500ms - if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/) - { -#ifdef CONFIG_STA_SUPPORT - // perform dynamic tx rate switching based on past TX history - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) - ) - && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))) - MlmeDynamicTxRateSwitching(pAd); - } -#endif // CONFIG_STA_SUPPORT // - } - - // Normal 1 second Mlme PeriodicExec. - if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0) - { - pAd->Mlme.OneSecPeriodicRound ++; - -#ifdef RALINK_ATE - if (ATE_ON(pAd)) - { - /* request from Baron : move this routine from later to here */ - /* for showing Rx error count in ATE RXFRAME */ - NICUpdateRawCounters(pAd); - if (pAd->ate.bRxFER == 1) - { - pAd->ate.RxTotalCnt += pAd->ate.RxCntPerSec; - ate_print(KERN_EMERG "MlmePeriodicExec: Rx packet cnt = %d/%d\n", pAd->ate.RxCntPerSec, pAd->ate.RxTotalCnt); - pAd->ate.RxCntPerSec = 0; - - if (pAd->ate.RxAntennaSel == 0) - ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi0=%d, AvgRssi1=%d, AvgRssi2=%d\n\n", - pAd->ate.AvgRssi0, pAd->ate.AvgRssi1, pAd->ate.AvgRssi2); - else - ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi=%d\n\n", pAd->ate.AvgRssi0); - } - MlmeResetRalinkCounters(pAd); - - - - return; - } -#endif // RALINK_ATE // - - - - //ORIBATimerTimeout(pAd); - - // Media status changed, report to NDIS - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE)) - { - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE); - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - pAd->IndicateMediaState = NdisMediaStateConnected; - RTMP_IndicateMediaState(pAd); - } - else - { - pAd->IndicateMediaState = NdisMediaStateDisconnected; - RTMP_IndicateMediaState(pAd); - } - } - - NdisGetSystemUpTime(&pAd->Mlme.Now32); - - // add the most up-to-date h/w raw counters into software variable, so that - // the dynamic tuning mechanism below are based on most up-to-date information - NICUpdateRawCounters(pAd); - - -#ifdef DOT11_N_SUPPORT - // Need statistics after read counter. So put after NICUpdateRawCounters - ORIBATimerTimeout(pAd); -#endif // DOT11_N_SUPPORT // - - // if MGMT RING is full more than twice within 1 second, we consider there's - // a hardware problem stucking the TX path. In this case, try a hardware reset - // to recover the system - // if (pAd->RalinkCounters.MgmtRingFullCount >= 2) - // RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR); - // else - // pAd->RalinkCounters.MgmtRingFullCount = 0; - - // The time period for checking antenna is according to traffic -#ifdef ANT_DIVERSITY_SUPPORT - if ((pAd->NicConfig2.field.AntDiversity) && - (pAd->CommonCfg.bRxAntDiversity == ANT_DIVERSITY_ENABLE) && - (!pAd->EepromAccess)) - AsicAntennaSelect(pAd, pAd->MlmeAux.Channel); - else if(pAd->CommonCfg.bRxAntDiversity == ANT_FIX_ANT1 || pAd->CommonCfg.bRxAntDiversity == ANT_FIX_ANT2) - { -#ifdef CONFIG_STA_SUPPORT - realavgrssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3); -#endif // CONFIG_STA_SUPPORT // - DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt)); - } - else -#endif // ANT_DIVERSITY_SUPPORT // - { - if (pAd->Mlme.bEnableAutoAntennaCheck) - { - TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + - pAd->RalinkCounters.OneSecTxRetryOkCount + - pAd->RalinkCounters.OneSecTxFailCount; - - // dynamic adjust antenna evaluation period according to the traffic - if (TxTotalCnt > 50) - { - if (pAd->Mlme.OneSecPeriodicRound % 10 == 0) - { - AsicEvaluateRxAnt(pAd); - } - } - else - { - if (pAd->Mlme.OneSecPeriodicRound % 3 == 0) - { - AsicEvaluateRxAnt(pAd); - } - } - } - } - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - STAMlmePeriodicExec(pAd); -#endif // CONFIG_STA_SUPPORT // - - MlmeResetRalinkCounters(pAd); - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { -#ifdef RTMP_MAC_PCI - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE)) -#endif // RTMP_MAC_PCI // - { - // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock - // and sending CTS-to-self over and over. - // Software Patch Solution: - // 1. Polling debug state register 0x10F4 every one second. - // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred. - // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again. - - UINT32 MacReg = 0; - - RTMP_IO_READ32(pAd, 0x10F4, &MacReg); - if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20))) - { - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); - RTMPusecDelay(1); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC); - - DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n")); - } - } - } -#endif // CONFIG_STA_SUPPORT // - - RTMP_MLME_HANDLER(pAd); - } - - - pAd->bUpdateBcnCntDone = FALSE; -} - - -/* - ========================================================================== - Validate SSID for connection try and rescan purpose - Valid SSID will have visible chars only. - The valid length is from 0 to 32. - IRQL = DISPATCH_LEVEL - ========================================================================== - */ -BOOLEAN MlmeValidateSSID( - IN PUCHAR pSsid, - IN UCHAR SsidLen) -{ - int index; - - if (SsidLen > MAX_LEN_OF_SSID) - return (FALSE); - - // Check each character value - for (index = 0; index < SsidLen; index++) - { - if (pSsid[index] < 0x20) - return (FALSE); - } - - // All checked - return (TRUE); -} - -VOID MlmeSelectTxRateTable( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PUCHAR *ppTable, - IN PUCHAR pTableSize, - IN PUCHAR pInitTxRateIdx) -{ - do - { - // decide the rate table for tuning - if (pAd->CommonCfg.TxRateTableSize > 0) - { - *ppTable = RateSwitchTable; - *pTableSize = RateSwitchTable[0]; - *pInitTxRateIdx = RateSwitchTable[1]; - - break; - } - -#ifdef CONFIG_STA_SUPPORT - if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd)) - { -#ifdef DOT11_N_SUPPORT - if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && - (pEntry->HTCapability.MCSSet[0] == 0xff) && - ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) - {// 11N 1S Adhoc - *ppTable = RateSwitchTable11N1S; - *pTableSize = RateSwitchTable11N1S[0]; - *pInitTxRateIdx = RateSwitchTable11N1S[1]; - - } - else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && - (pEntry->HTCapability.MCSSet[0] == 0xff) && - (pEntry->HTCapability.MCSSet[1] == 0xff) && - (pAd->Antenna.field.TxPath == 2)) - {// 11N 2S Adhoc - if (pAd->LatchRfRegs.Channel <= 14) - { - *ppTable = RateSwitchTable11N2S; - *pTableSize = RateSwitchTable11N2S[0]; - *pInitTxRateIdx = RateSwitchTable11N2S[1]; - } - else - { - *ppTable = RateSwitchTable11N2SForABand; - *pTableSize = RateSwitchTable11N2SForABand[0]; - *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; - } - - } - else -#endif // DOT11_N_SUPPORT // - if ((pEntry->RateLen == 4) -#ifdef DOT11_N_SUPPORT - && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) -#endif // DOT11_N_SUPPORT // - ) - { - *ppTable = RateSwitchTable11B; - *pTableSize = RateSwitchTable11B[0]; - *pInitTxRateIdx = RateSwitchTable11B[1]; - - } - else if (pAd->LatchRfRegs.Channel <= 14) - { - *ppTable = RateSwitchTable11BG; - *pTableSize = RateSwitchTable11BG[0]; - *pInitTxRateIdx = RateSwitchTable11BG[1]; - - } - else - { - *ppTable = RateSwitchTable11G; - *pTableSize = RateSwitchTable11G[0]; - *pInitTxRateIdx = RateSwitchTable11G[1]; - - } - break; - } -#endif // CONFIG_STA_SUPPORT // - -#ifdef DOT11_N_SUPPORT - //if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && - // ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) - if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) && - ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) - {// 11BGN 1S AP - *ppTable = RateSwitchTable11BGN1S; - *pTableSize = RateSwitchTable11BGN1S[0]; - *pInitTxRateIdx = RateSwitchTable11BGN1S[1]; - - break; - } - - //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && - // (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) - if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) && - (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) - {// 11BGN 2S AP - if (pAd->LatchRfRegs.Channel <= 14) - { - *ppTable = RateSwitchTable11BGN2S; - *pTableSize = RateSwitchTable11BGN2S[0]; - *pInitTxRateIdx = RateSwitchTable11BGN2S[1]; - - } - else - { - *ppTable = RateSwitchTable11BGN2SForABand; - *pTableSize = RateSwitchTable11BGN2SForABand[0]; - *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1]; - - } - break; - } - - //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) - if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) - {// 11N 1S AP - *ppTable = RateSwitchTable11N1S; - *pTableSize = RateSwitchTable11N1S[0]; - *pInitTxRateIdx = RateSwitchTable11N1S[1]; - - break; - } - - //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) - if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) - {// 11N 2S AP - if (pAd->LatchRfRegs.Channel <= 14) - { - *ppTable = RateSwitchTable11N2S; - *pTableSize = RateSwitchTable11N2S[0]; - *pInitTxRateIdx = RateSwitchTable11N2S[1]; - } - else - { - *ppTable = RateSwitchTable11N2SForABand; - *pTableSize = RateSwitchTable11N2SForABand[0]; - *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; - } - - break; - } -#endif // DOT11_N_SUPPORT // - //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) - if ((pEntry->RateLen == 4 || pAd->CommonCfg.PhyMode==PHY_11B) -#ifdef DOT11_N_SUPPORT - //Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode - /* && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)*/ -#endif // DOT11_N_SUPPORT // - ) - {// B only AP - *ppTable = RateSwitchTable11B; - *pTableSize = RateSwitchTable11B[0]; - *pInitTxRateIdx = RateSwitchTable11B[1]; - - break; - } - - //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) - if ((pEntry->RateLen > 8) -#ifdef DOT11_N_SUPPORT - && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) -#endif // DOT11_N_SUPPORT // - ) - {// B/G mixed AP - *ppTable = RateSwitchTable11BG; - *pTableSize = RateSwitchTable11BG[0]; - *pInitTxRateIdx = RateSwitchTable11BG[1]; - - break; - } - - //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) - if ((pEntry->RateLen == 8) -#ifdef DOT11_N_SUPPORT - && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) -#endif // DOT11_N_SUPPORT // - ) - {// G only AP - *ppTable = RateSwitchTable11G; - *pTableSize = RateSwitchTable11G[0]; - *pInitTxRateIdx = RateSwitchTable11G[1]; - - break; - } -#ifdef DOT11_N_SUPPORT -#endif // DOT11_N_SUPPORT // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { -#ifdef DOT11_N_SUPPORT - //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) - if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)) -#endif // DOT11_N_SUPPORT // - { // Legacy mode - if (pAd->CommonCfg.MaxTxRate <= RATE_11) - { - *ppTable = RateSwitchTable11B; - *pTableSize = RateSwitchTable11B[0]; - *pInitTxRateIdx = RateSwitchTable11B[1]; - } - else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11)) - { - *ppTable = RateSwitchTable11G; - *pTableSize = RateSwitchTable11G[0]; - *pInitTxRateIdx = RateSwitchTable11G[1]; - - } - else - { - *ppTable = RateSwitchTable11BG; - *pTableSize = RateSwitchTable11BG[0]; - *pInitTxRateIdx = RateSwitchTable11BG[1]; - } - break; - } -#ifdef DOT11_N_SUPPORT - if (pAd->LatchRfRegs.Channel <= 14) - { - if (pAd->CommonCfg.TxStream == 1) - { - *ppTable = RateSwitchTable11N1S; - *pTableSize = RateSwitchTable11N1S[0]; - *pInitTxRateIdx = RateSwitchTable11N1S[1]; - DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n")); - } - else - { - *ppTable = RateSwitchTable11N2S; - *pTableSize = RateSwitchTable11N2S[0]; - *pInitTxRateIdx = RateSwitchTable11N2S[1]; - DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n")); - } - } - else - { - if (pAd->CommonCfg.TxStream == 1) - { - *ppTable = RateSwitchTable11N1S; - *pTableSize = RateSwitchTable11N1S[0]; - *pInitTxRateIdx = RateSwitchTable11N1S[1]; - DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n")); - } - else - { - *ppTable = RateSwitchTable11N2SForABand; - *pTableSize = RateSwitchTable11N2SForABand[0]; - *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; - DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n")); - } - } -#endif // DOT11_N_SUPPORT // - DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n", - pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1])); - } -#endif // CONFIG_STA_SUPPORT // - } while(FALSE); -} - - -#ifdef CONFIG_STA_SUPPORT -VOID STAMlmePeriodicExec( - PRTMP_ADAPTER pAd) -{ - ULONG TxTotalCnt; - int i; - - - - - /* - We return here in ATE mode, because the statistics - that ATE need are not collected via this routine. - */ -#ifdef RALINK_ATE - if (ATE_ON(pAd)) - return; -#endif // RALINK_ATE // - -#ifdef RALINK_ATE - // It is supposed that we will never reach here in ATE mode. - ASSERT(!(ATE_ON(pAd))); - if (ATE_ON(pAd)) - return; -#endif // RALINK_ATE // - -#ifdef PCIE_PS_SUPPORT -// don't perform idle-power-save mechanism within 3 min after driver initialization. -// This can make rebooter test more robust -if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - { - if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) - && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) - && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) - && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) - { - if (IS_RT3090(pAd)|| IS_RT3572(pAd) || IS_RT3390(pAd)) - { - if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s::%d\n",__FUNCTION__,__LINE__)); - - RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("%s::%d\n",__FUNCTION__,__LINE__)); - AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x2); - // Wait command success - AsicCheckCommanOk(pAd, PowerSafeCID); - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); - DBGPRINT(RT_DEBUG_TRACE, ("PSM - rt30xx Issue Sleep command)\n")); - } - } - else if (pAd->Mlme.OneSecPeriodicRound > 180) - { - if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s::%d\n",__FUNCTION__,__LINE__)); - RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("%s::%d\n",__FUNCTION__,__LINE__)); - AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x02); - // Wait command success - AsicCheckCommanOk(pAd, PowerSafeCID); - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); - DBGPRINT(RT_DEBUG_TRACE, ("PSM - rt28xx Issue Sleep command)\n")); - } - } - } - else - { - DBGPRINT(RT_DEBUG_TRACE,("STAMlmePeriodicExec MMCHK - CommonCfg.Ssid[%d]=%c%c%c%c... MlmeAux.Ssid[%d]=%c%c%c%c...\n", - pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid[0], pAd->CommonCfg.Ssid[1], pAd->CommonCfg.Ssid[2], pAd->CommonCfg.Ssid[3], - pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid[0], pAd->MlmeAux.Ssid[1], pAd->MlmeAux.Ssid[2], pAd->MlmeAux.Ssid[3])); - } - } -#endif // PCIE_PS_SUPPORT // - - -#ifdef WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) -#endif // WPA_SUPPLICANT_SUPPORT // - { - // WPA MIC error should block association attempt for 60 seconds - if (pAd->StaCfg.bBlockAssoc && - RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastMicErrorTime + (60*OS_HZ))) - pAd->StaCfg.bBlockAssoc = FALSE; - } - - if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent)) - { - if (pAd->IndicateMediaState == NdisMediaStateConnected) - { - RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - } - pAd->PreMediaState = pAd->IndicateMediaState; - } - - - - - if (pAd->CommonCfg.PSPXlink && ADHOC_ON(pAd)) - { - } - else - { - AsicStaBbpTuning(pAd); - } - - TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + - pAd->RalinkCounters.OneSecTxRetryOkCount + - pAd->RalinkCounters.OneSecTxFailCount; - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - // update channel quality for Roaming and UI LinkQuality display - MlmeCalculateChannelQuality(pAd, NULL, pAd->Mlme.Now32); - } - - // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if - // Radio is currently in noisy environment - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - AsicAdjustTxPower(pAd); - - if (INFRA_ON(pAd)) - { -#ifdef QOS_DLS_SUPPORT - // Check DLS time out, then tear down those session - RTMPCheckDLSTimeOut(pAd); -#endif // QOS_DLS_SUPPORT // - - // Is PSM bit consistent with user power management policy? - // This is the only place that will set PSM bit ON. - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - MlmeCheckPsmChange(pAd, pAd->Mlme.Now32); - - pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt; - - if ((RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastBeaconRxTime + (1*OS_HZ))) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && - (((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt) < 600))) - { - RTMPSetAGCInitValue(pAd, BW_20); - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd)))); - } - - //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && - // (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)) - { - if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) - { - // When APSD is enabled, the period changes as 20 sec - if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8) - RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); - } - else - { - // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out) - if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) - { - if (pAd->CommonCfg.bWmmCapable) - RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); - else - RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE); - } - } - } - - if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality)) - { - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount)); - - // Lost AP, send disconnect & link down event - LinkDown(pAd, FALSE); - -#ifdef WPA_SUPPLICANT_SUPPORT -#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT - //send disassociate event to wpa_supplicant - if (pAd->StaCfg.WpaSupplicantUP) { - RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, RT_DISASSOC_EVENT_FLAG, NULL, NULL, 0); - } -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // -#endif // WPA_SUPPLICANT_SUPPORT // - -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT - RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, 0); -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - - // RTMPPatchMacBbpBug(pAd); - MlmeAutoReconnectLastSSID(pAd); - } - else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality)) - { - pAd->RalinkCounters.BadCQIAutoRecoveryCount ++; - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount)); - MlmeAutoReconnectLastSSID(pAd); - } - - if (pAd->StaCfg.bAutoRoaming) - { - BOOLEAN rv = FALSE; - CHAR dBmToRoam = pAd->StaCfg.dBmToRoam; - CHAR MaxRssi = RTMPMaxRssi(pAd, - pAd->StaCfg.RssiSample.LastRssi0, - pAd->StaCfg.RssiSample.LastRssi1, - pAd->StaCfg.RssiSample.LastRssi2); - - // Scanning, ignore Roaming - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) && - (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) && - (MaxRssi <= dBmToRoam)) - { - DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", MaxRssi, (CHAR)dBmToRoam)); - - - // Add auto seamless roaming - if (rv == FALSE) - rv = MlmeCheckForFastRoaming(pAd); - - if (rv == FALSE) - { - if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32) - { - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n")); - pAd->StaCfg.ScanCnt = 2; - pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; - MlmeAutoScan(pAd); - } - } - } - } - } - else if (ADHOC_ON(pAd)) - { - - // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState - // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can - // join later. - if (RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME) && - OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - MLME_START_REQ_STRUCT StartReq; - - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n")); - LinkDown(pAd, FALSE); - - StartParmFill(pAd, &StartReq, (CHAR *)pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; - } - - for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) - { - MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i]; - - if (pEntry->ValidAsCLI == FALSE) - continue; - - if (RTMP_TIME_AFTER(pAd->Mlme.Now32, pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME)) - MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); - } - } - else // no INFRA nor ADHOC connection - { - - if (pAd->StaCfg.bScanReqIsFromWebUI && - RTMP_TIME_BEFORE(pAd->Mlme.Now32, pAd->StaCfg.LastScanTime + (30 * OS_HZ))) - goto SKIP_AUTO_SCAN_CONN; - else - pAd->StaCfg.bScanReqIsFromWebUI = FALSE; - - if ((pAd->StaCfg.bAutoReconnect == TRUE) - && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP) - && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) - { - if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) - { - MLME_SCAN_REQ_STRUCT ScanReq; - - if (RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastScanTime + (10 * OS_HZ))) - { - DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid)); - ScanParmFill(pAd, &ScanReq, (PSTRING) pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; - // Reset Missed scan number - pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; - } - else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room - MlmeAutoReconnectLastSSID(pAd); - } - else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) - { - if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0) - { - MlmeAutoScan(pAd); - pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; - } - else - { -#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier - if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) - { - if ((pAd->Mlme.OneSecPeriodicRound % 5) == 1) - MlmeAutoReconnectLastSSID(pAd); - } - else -#endif // CARRIER_DETECTION_SUPPORT // - MlmeAutoReconnectLastSSID(pAd); - } - } - } - } - -SKIP_AUTO_SCAN_CONN: - -#ifdef DOT11_N_SUPPORT - if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE)) - { - pAd->MacTab.fAnyBASession = TRUE; - AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE); - } - else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE)) - { - pAd->MacTab.fAnyBASession = FALSE; - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); - } -#endif // DOT11_N_SUPPORT // - - -#ifdef DOT11_N_SUPPORT -#ifdef DOT11N_DRAFT3 - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040)) - TriEventCounterMaintenance(pAd); -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // - - return; -} - -// Link down report -VOID LinkDownExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; - - if (pAd != NULL) - { - MLME_DISASSOC_REQ_STRUCT DisassocReq; - - if ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) && - (INFRA_ON(pAd))) - { - DBGPRINT(RT_DEBUG_TRACE, ("LinkDownExec(): disassociate with current AP...\n")); - DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, - sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; - - pAd->IndicateMediaState = NdisMediaStateDisconnected; - RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_DOWN; - } - } -} - -// IRQL = DISPATCH_LEVEL -VOID MlmeAutoScan( - IN PRTMP_ADAPTER pAd) -{ - // check CntlMachine.CurrState to avoid collision with NDIS SetOID request - if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) - { - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n")); - MlmeEnqueue(pAd, - MLME_CNTL_STATE_MACHINE, - OID_802_11_BSSID_LIST_SCAN, - pAd->MlmeAux.AutoReconnectSsidLen, - pAd->MlmeAux.AutoReconnectSsid); - RTMP_MLME_HANDLER(pAd); - } -} - -// IRQL = DISPATCH_LEVEL -VOID MlmeAutoReconnectLastSSID( - IN PRTMP_ADAPTER pAd) -{ - if (pAd->StaCfg.bAutoConnectByBssid) - { - DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_BSSID setting - %02X:%02X:%02X:%02X:%02X:%02X\n", - pAd->MlmeAux.Bssid[0], - pAd->MlmeAux.Bssid[1], - pAd->MlmeAux.Bssid[2], - pAd->MlmeAux.Bssid[3], - pAd->MlmeAux.Bssid[4], - pAd->MlmeAux.Bssid[5])); - - pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; - MlmeEnqueue(pAd, - MLME_CNTL_STATE_MACHINE, - OID_802_11_BSSID, - MAC_ADDR_LEN, - pAd->MlmeAux.Bssid); - - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - - RTMP_MLME_HANDLER(pAd); - } - // check CntlMachine.CurrState to avoid collision with NDIS SetOID request - else if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && - (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) - { - NDIS_802_11_SSID OidSsid; - OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen; - NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); - - DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen)); - MlmeEnqueue(pAd, - MLME_CNTL_STATE_MACHINE, - OID_802_11_SSID, - sizeof(NDIS_802_11_SSID), - &OidSsid); - RTMP_MLME_HANDLER(pAd); - } -} - - -/* - ========================================================================== - Description: - This routine checks if there're other APs out there capable for - roaming. Caller should call this routine only when Link up in INFRA mode - and channel quality is below CQI_GOOD_THRESHOLD. - - IRQL = DISPATCH_LEVEL - - Output: - ========================================================================== - */ -VOID MlmeCheckForRoaming( - IN PRTMP_ADAPTER pAd, - IN ULONG Now32) -{ - USHORT i; - BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; - BSS_ENTRY *pBss; - - DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n")); - // put all roaming candidates into RoamTab, and sort in RSSI order - BssTableInit(pRoamTab); - for (i = 0; i < pAd->ScanTab.BssNr; i++) - { - pBss = &pAd->ScanTab.BssEntry[i]; - - if ((pBss->LastBeaconRxTime + pAd->StaCfg.BeaconLostTime) < Now32) - continue; // AP disappear - if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING) - continue; // RSSI too weak. forget it. - if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) - continue; // skip current AP - if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA)) - continue; // only AP with stronger RSSI is eligible for roaming - - // AP passing all above rules is put into roaming candidate table - NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); - pRoamTab->BssNr += 1; - } - - if (pRoamTab->BssNr > 0) - { - // check CntlMachine.CurrState to avoid collision with NDIS SetOID request - if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) - { - pAd->RalinkCounters.PoorCQIRoamingCount ++; - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount)); - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); - RTMP_MLME_HANDLER(pAd); - } - } - DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr)); -} - -/* - ========================================================================== - Description: - This routine checks if there're other APs out there capable for - roaming. Caller should call this routine only when link up in INFRA mode - and channel quality is below CQI_GOOD_THRESHOLD. - - IRQL = DISPATCH_LEVEL - - Output: - ========================================================================== - */ -BOOLEAN MlmeCheckForFastRoaming( - IN PRTMP_ADAPTER pAd) -{ - USHORT i; - BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; - BSS_ENTRY *pBss; - - DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n")); - // put all roaming candidates into RoamTab, and sort in RSSI order - BssTableInit(pRoamTab); - for (i = 0; i < pAd->ScanTab.BssNr; i++) - { - pBss = &pAd->ScanTab.BssEntry[i]; - - if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel)) - continue; // RSSI too weak. forget it. - if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) - continue; // skip current AP - if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)) - continue; // skip different SSID - if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA)) - continue; // skip AP without better RSSI - - DBGPRINT(RT_DEBUG_TRACE, ("LastRssi0 = %d, pBss->Rssi = %d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), pBss->Rssi)); - // AP passing all above rules is put into roaming candidate table - NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); - pRoamTab->BssNr += 1; - } - - DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr)); - if (pRoamTab->BssNr > 0) - { - // check CntlMachine.CurrState to avoid collision with NDIS SetOID request - if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) - { - pAd->RalinkCounters.PoorCQIRoamingCount ++; - DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount)); - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); - RTMP_MLME_HANDLER(pAd); - return TRUE; - } - } - - return FALSE; -} - -VOID MlmeSetTxRate( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PRTMP_TX_RATE_SWITCH pTxRate) -{ - UCHAR MaxMode = MODE_OFDM; - -#ifdef DOT11_N_SUPPORT - MaxMode = MODE_HTGREENFIELD; - - if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2)) - pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE; - else -#endif // DOT11_N_SUPPORT // - pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; - - if (pTxRate->CurrMCS < MCS_AUTO) - pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS; - - if (pAd->StaCfg.HTPhyMode.field.MCS > 7) - pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; - - if (ADHOC_ON(pAd)) - { - // If peer adhoc is b-only mode, we can't send 11g rate. - pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; - pEntry->HTPhyMode.field.STBC = STBC_NONE; - - // - // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary - // - pEntry->HTPhyMode.field.MODE = pTxRate->Mode; - pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI; - pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - - // Patch speed error in status page - pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE; - } - else - { - if (pTxRate->Mode <= MaxMode) - pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode; - -#ifdef DOT11_N_SUPPORT - if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI)) - pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400; - else -#endif // DOT11_N_SUPPORT // - pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; - -#ifdef DOT11_N_SUPPORT - // Reexam each bandwidth's SGI support. - if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400) - { - if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE))) - pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; - if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE))) - pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; - } - - // Turn RTS/CTS rate to 6Mbps. - if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0)) - { - pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - if (pAd->MacTab.fAnyBASession) - { - AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); - } - else - { - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); - } - } - else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8)) - { - pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - if (pAd->MacTab.fAnyBASession) - { - AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); - } - else - { - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); - } - } - else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0)) - { - AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); - - } - else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8)) - { - AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); - } -#endif // DOT11_N_SUPPORT // - - pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC; - pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI; - pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; -#ifdef DOT11_N_SUPPORT - if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) && - pAd->WIFItestbed.bGreenField) - pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD; -#endif // DOT11_N_SUPPORT // - } - - pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word); -} - -/* - ========================================================================== - Description: - This routine calculates the acumulated TxPER of eaxh TxRate. And - according to the calculation result, change CommonCfg.TxRate which - is the stable TX Rate we expect the Radio situation could sustained. - - CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate} - Output: - CommonCfg.TxRate - - - IRQL = DISPATCH_LEVEL - - NOTE: - call this routine every second - ========================================================================== - */ -VOID MlmeDynamicTxRateSwitching( - IN PRTMP_ADAPTER pAd) -{ - UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx; - ULONG i, AccuTxTotalCnt = 0, TxTotalCnt; - ULONG TxErrorRatio = 0; - BOOLEAN bTxRateChanged = FALSE, bUpgradeQuality = FALSE; - PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL; - PUCHAR pTable; - UCHAR TableSize = 0; - UCHAR InitTxRateIdx = 0, TrainUp, TrainDown; - CHAR Rssi, RssiOffset = 0; - TX_STA_CNT1_STRUC StaTx1; - TX_STA_CNT0_STRUC TxStaCnt0; - ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; - MAC_TABLE_ENTRY *pEntry; - RSSI_SAMPLE *pRssi = &pAd->StaCfg.RssiSample; - -#ifdef RALINK_ATE - if (ATE_ON(pAd)) - { - return; - } -#endif // RALINK_ATE // - - // - // walk through MAC table, see if need to change AP's TX rate toward each entry - // - for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) - { - pEntry = &pAd->MacTab.Content[i]; - - // check if this entry need to switch rate automatically - if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) - continue; - - if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls)) - { - Rssi = RTMPMaxRssi(pAd, - pRssi->AvgRssi0, - pRssi->AvgRssi1, - pRssi->AvgRssi2); - - // Update statistic counter - RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); - RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); - pAd->bUpdateBcnCntDone = TRUE; - TxRetransmit = StaTx1.field.TxRetransmit; - TxSuccess = StaTx1.field.TxSuccess; - TxFailCount = TxStaCnt0.field.TxFailCount; - TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; - - pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; - pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; - pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount; - pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; - pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; - pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; - - // if no traffic in the past 1-sec period, don't change TX rate, - // but clear all bad history. because the bad history may affect the next - // Chariot throughput test - AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + - pAd->RalinkCounters.OneSecTxRetryOkCount + - pAd->RalinkCounters.OneSecTxFailCount; - - if (TxTotalCnt) - TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; - } - else - { - if (INFRA_ON(pAd) && (i == 1)) - Rssi = RTMPMaxRssi(pAd, - pRssi->AvgRssi0, - pRssi->AvgRssi1, - pRssi->AvgRssi2); - else - Rssi = RTMPMaxRssi(pAd, - pEntry->RssiSample.AvgRssi0, - pEntry->RssiSample.AvgRssi1, - pEntry->RssiSample.AvgRssi2); - - TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + - pEntry->OneSecTxRetryOkCount + - pEntry->OneSecTxFailCount; - - if (TxTotalCnt) - TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt; - } - - if (TxTotalCnt) - { - /* - Three AdHoc connections can not work normally if one AdHoc connection is disappeared from a heavy traffic environment generated by ping tool - We force to set LongRtyLimit and ShortRtyLimit to 0 to stop retransmitting packet, after a while, resoring original settings - */ - if (TxErrorRatio == 100) - { - TX_RTY_CFG_STRUC TxRtyCfg,TxRtyCfgtmp; - ULONG Index; - ULONG MACValue; - - RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word); - TxRtyCfgtmp.word = TxRtyCfg.word; - TxRtyCfg.field.LongRtyLimit = 0x0; - TxRtyCfg.field.ShortRtyLimit = 0x0; - RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word); - - RTMPusecDelay(1); - - Index = 0; - MACValue = 0; - do - { - RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue); - if ((MACValue & 0xffffff) == 0) - break; - Index++; - RTMPusecDelay(1000); - }while((Index < 330)&&(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))); - - RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word); - TxRtyCfg.field.LongRtyLimit = TxRtyCfgtmp.field.LongRtyLimit; - TxRtyCfg.field.ShortRtyLimit = TxRtyCfgtmp.field.ShortRtyLimit; - RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word); - } - } - - CurrRateIdx = pEntry->CurrTxRateIndex; - - MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); - - if (CurrRateIdx >= TableSize) - { - CurrRateIdx = TableSize - 1; - } - - // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex. - // So need to sync here. - pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; - if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS) - //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE) - ) - { - - // Need to sync Real Tx rate and our record. - // Then return for next DRS. - pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5]; - pEntry->CurrTxRateIndex = InitTxRateIdx; - MlmeSetTxRate(pAd, pEntry, pCurrTxRate); - - // reset all OneSecTx counters - RESET_ONE_SEC_TX_CNT(pEntry); - continue; - } - - // decide the next upgrade rate and downgrade rate, if any - if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) - { - UpRateIdx = CurrRateIdx + 1; - DownRateIdx = CurrRateIdx -1; - } - else if (CurrRateIdx == 0) - { - UpRateIdx = CurrRateIdx + 1; - DownRateIdx = CurrRateIdx; - } - else if (CurrRateIdx == (TableSize - 1)) - { - UpRateIdx = CurrRateIdx; - DownRateIdx = CurrRateIdx - 1; - } - - pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; - -#ifdef DOT11_N_SUPPORT - if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) - { - TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); - TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); - } - else -#endif // DOT11_N_SUPPORT // - { - TrainUp = pCurrTxRate->TrainUp; - TrainDown = pCurrTxRate->TrainDown; - } - - //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction; - - // - // Keep the last time TxRateChangeAction status. - // - pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction; - - - - // - // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI - // (criteria copied from RT2500 for Netopia case) - // - if (TxTotalCnt <= 15) - { - CHAR idx = 0; - UCHAR TxRateIdx; - UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0; - UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0; - UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3 - - // check the existence and index of each needed MCS - while (idx < pTable[0]) - { - pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5]; - - if (pCurrTxRate->CurrMCS == MCS_0) - { - MCS0 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_1) - { - MCS1 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_2) - { - MCS2 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_3) - { - MCS3 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_4) - { - MCS4 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_5) - { - MCS5 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_6) - { - MCS6 = idx; - } - //else if (pCurrTxRate->CurrMCS == MCS_7) - else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput - { - MCS7 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_12) - { - MCS12 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_13) - { - MCS13 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_14) - { - MCS14 = idx; - } - //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate - else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) //we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI - { - MCS15 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3 - { - MCS20 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_21) - { - MCS21 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_22) - { - MCS22 = idx; - } - else if (pCurrTxRate->CurrMCS == MCS_23) - { - MCS23 = idx; - } - idx ++; - } - - if (pAd->LatchRfRegs.Channel <= 14) - { - if (pAd->NicConfig2.field.ExternalLNAForG) - { - RssiOffset = 2; - } - else - { - RssiOffset = 5; - } - } - else - { - if (pAd->NicConfig2.field.ExternalLNAForA) - { - RssiOffset = 5; - } - else - { - RssiOffset = 8; - } - } -#ifdef DOT11_N_SUPPORT - /*if (MCS15)*/ - if ((pTable == RateSwitchTable11BGN3S) || - (pTable == RateSwitchTable11N3S) || - (pTable == RateSwitchTable)) - {// N mode with 3 stream // 3*3 - if (MCS23 && (Rssi >= -70)) - TxRateIdx = MCS23; - else if (MCS22 && (Rssi >= -72)) - TxRateIdx = MCS22; - else if (MCS21 && (Rssi >= -76)) - TxRateIdx = MCS21; - else if (MCS20 && (Rssi >= -78)) - TxRateIdx = MCS20; - else if (MCS4 && (Rssi >= -82)) - TxRateIdx = MCS4; - else if (MCS3 && (Rssi >= -84)) - TxRateIdx = MCS3; - else if (MCS2 && (Rssi >= -86)) - TxRateIdx = MCS2; - else if (MCS1 && (Rssi >= -88)) - TxRateIdx = MCS1; - else - TxRateIdx = MCS0; - } -// else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable)) - else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3 - {// N mode with 2 stream - if (MCS15 && (Rssi >= (-70+RssiOffset))) - TxRateIdx = MCS15; - else if (MCS14 && (Rssi >= (-72+RssiOffset))) - TxRateIdx = MCS14; - else if (MCS13 && (Rssi >= (-76+RssiOffset))) - TxRateIdx = MCS13; - else if (MCS12 && (Rssi >= (-78+RssiOffset))) - TxRateIdx = MCS12; - else if (MCS4 && (Rssi >= (-82+RssiOffset))) - TxRateIdx = MCS4; - else if (MCS3 && (Rssi >= (-84+RssiOffset))) - TxRateIdx = MCS3; - else if (MCS2 && (Rssi >= (-86+RssiOffset))) - TxRateIdx = MCS2; - else if (MCS1 && (Rssi >= (-88+RssiOffset))) - TxRateIdx = MCS1; - else - TxRateIdx = MCS0; - } - else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S)) - {// N mode with 1 stream - if (MCS7 && (Rssi > (-72+RssiOffset))) - TxRateIdx = MCS7; - else if (MCS6 && (Rssi > (-74+RssiOffset))) - TxRateIdx = MCS6; - else if (MCS5 && (Rssi > (-77+RssiOffset))) - TxRateIdx = MCS5; - else if (MCS4 && (Rssi > (-79+RssiOffset))) - TxRateIdx = MCS4; - else if (MCS3 && (Rssi > (-81+RssiOffset))) - TxRateIdx = MCS3; - else if (MCS2 && (Rssi > (-83+RssiOffset))) - TxRateIdx = MCS2; - else if (MCS1 && (Rssi > (-86+RssiOffset))) - TxRateIdx = MCS1; - else - TxRateIdx = MCS0; - } - else -#endif // DOT11_N_SUPPORT // - {// Legacy mode - if (MCS7 && (Rssi > -70)) - TxRateIdx = MCS7; - else if (MCS6 && (Rssi > -74)) - TxRateIdx = MCS6; - else if (MCS5 && (Rssi > -78)) - TxRateIdx = MCS5; - else if (MCS4 && (Rssi > -82)) - TxRateIdx = MCS4; - else if (MCS4 == 0) // for B-only mode - TxRateIdx = MCS3; - else if (MCS3 && (Rssi > -85)) - TxRateIdx = MCS3; - else if (MCS2 && (Rssi > -87)) - TxRateIdx = MCS2; - else if (MCS1 && (Rssi > -90)) - TxRateIdx = MCS1; - else - TxRateIdx = MCS0; - } - - // if (TxRateIdx != pAd->CommonCfg.TxRateIndex) - { - pEntry->CurrTxRateIndex = TxRateIdx; - pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5]; - MlmeSetTxRate(pAd, pEntry, pNextTxRate); - } - - NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); - NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); - pEntry->fLastSecAccordingRSSI = TRUE; - // reset all OneSecTx counters - RESET_ONE_SEC_TX_CNT(pEntry); - - continue; - } - - if (pEntry->fLastSecAccordingRSSI == TRUE) - { - pEntry->fLastSecAccordingRSSI = FALSE; - pEntry->LastSecTxRateChangeAction = 0; - // reset all OneSecTx counters - RESET_ONE_SEC_TX_CNT(pEntry); - - continue; - } - - do - { - BOOLEAN bTrainUpDown = FALSE; - - pEntry->CurrTxRateStableTime ++; - - // downgrade TX quality if PER >= Rate-Down threshold - if (TxErrorRatio >= TrainDown) - { - bTrainUpDown = TRUE; - pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; - } - // upgrade TX quality if PER <= Rate-Up threshold - else if (TxErrorRatio <= TrainUp) - { - bTrainUpDown = TRUE; - bUpgradeQuality = TRUE; - if (pEntry->TxQuality[CurrRateIdx]) - pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate - - if (pEntry->TxRateUpPenalty) - pEntry->TxRateUpPenalty --; - else if (pEntry->TxQuality[UpRateIdx]) - pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality - } - - pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio; - - if (bTrainUpDown) - { - // perform DRS - consider TxRate Down first, then rate up. - if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND)) - { - pEntry->CurrTxRateIndex = DownRateIdx; - } - else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0)) - { - pEntry->CurrTxRateIndex = UpRateIdx; - } - } - } while (FALSE); - - // if rate-up happen, clear all bad history of all TX rates - if (pEntry->CurrTxRateIndex > CurrRateIdx) - { - pEntry->CurrTxRateStableTime = 0; - pEntry->TxRateUpPenalty = 0; - pEntry->LastSecTxRateChangeAction = 1; // rate UP - NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); - NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); - - // - // For TxRate fast train up - // - if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) - { - RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100); - - pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; - } - bTxRateChanged = TRUE; - } - // if rate-down happen, only clear DownRate's bad history - else if (pEntry->CurrTxRateIndex < CurrRateIdx) - { - pEntry->CurrTxRateStableTime = 0; - pEntry->TxRateUpPenalty = 0; // no penalty - pEntry->LastSecTxRateChangeAction = 2; // rate DOWN - pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; - pEntry->PER[pEntry->CurrTxRateIndex] = 0; - - // - // For TxRate fast train down - // - if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) - { - RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100); - - pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; - } - bTxRateChanged = TRUE; - } - else - { - pEntry->LastSecTxRateChangeAction = 0; // rate no change - bTxRateChanged = FALSE; - } - - pEntry->LastTxOkCount = TxSuccess; - - { - UCHAR tmpTxRate; - - // to fix tcp ack issue - if (!bTxRateChanged && (pAd->RalinkCounters.OneSecReceivedByteCount > (pAd->RalinkCounters.OneSecTransmittedByteCount * 5))) - { - tmpTxRate = DownRateIdx; - DBGPRINT_RAW(RT_DEBUG_TRACE,("DRS: Rx(%d) is 5 times larger than Tx(%d), use low rate (curr=%d, tmp=%d)\n", - pAd->RalinkCounters.OneSecReceivedByteCount, pAd->RalinkCounters.OneSecTransmittedByteCount, pEntry->CurrTxRateIndex, tmpTxRate)); - } - else - { - tmpTxRate = pEntry->CurrTxRateIndex; - } - - pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(tmpTxRate+1)*5]; - if (bTxRateChanged && pNextTxRate) - { - MlmeSetTxRate(pAd, pEntry, pNextTxRate); - } - } - // reset all OneSecTx counters - RESET_ONE_SEC_TX_CNT(pEntry); - } -} - -/* - ======================================================================== - Routine Description: - Station side, Auto TxRate faster train up timer call back function. - - Arguments: - SystemSpecific1 - Not used. - FunctionContext - Pointer to our Adapter context. - SystemSpecific2 - Not used. - SystemSpecific3 - Not used. - - Return Value: - None - - ======================================================================== -*/ -VOID StaQuickResponeForRateUpExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; - UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0; - ULONG TxTotalCnt; - ULONG TxErrorRatio = 0; - BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE; - PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL; - PUCHAR pTable; - UCHAR TableSize = 0; - UCHAR InitTxRateIdx = 0, TrainUp, TrainDown; - TX_STA_CNT1_STRUC StaTx1; - TX_STA_CNT0_STRUC TxStaCnt0; - CHAR Rssi, ratio; - ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; - MAC_TABLE_ENTRY *pEntry; - ULONG i; - - pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; - - // - // walk through MAC table, see if need to change AP's TX rate toward each entry - // - for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) - { - pEntry = &pAd->MacTab.Content[i]; - - // check if this entry need to switch rate automatically - if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) - continue; - - if (INFRA_ON(pAd) && (i == 1)) - Rssi = RTMPMaxRssi(pAd, - pAd->StaCfg.RssiSample.AvgRssi0, - pAd->StaCfg.RssiSample.AvgRssi1, - pAd->StaCfg.RssiSample.AvgRssi2); - else - Rssi = RTMPMaxRssi(pAd, - pEntry->RssiSample.AvgRssi0, - pEntry->RssiSample.AvgRssi1, - pEntry->RssiSample.AvgRssi2); - - CurrRateIdx = pAd->CommonCfg.TxRateIndex; - - MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); - - // decide the next upgrade rate and downgrade rate, if any - if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) - { - UpRateIdx = CurrRateIdx + 1; - DownRateIdx = CurrRateIdx -1; - } - else if (CurrRateIdx == 0) - { - UpRateIdx = CurrRateIdx + 1; - DownRateIdx = CurrRateIdx; - } - else if (CurrRateIdx == (TableSize - 1)) - { - UpRateIdx = CurrRateIdx; - DownRateIdx = CurrRateIdx - 1; - } - - pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; - -#ifdef DOT11_N_SUPPORT - if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) - { - TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); - TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); - } - else -#endif // DOT11_N_SUPPORT // - { - TrainUp = pCurrTxRate->TrainUp; - TrainDown = pCurrTxRate->TrainDown; - } - - if (pAd->MacTab.Size == 1) - { - // Update statistic counter - RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); - RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); - - TxRetransmit = StaTx1.field.TxRetransmit; - TxSuccess = StaTx1.field.TxSuccess; - TxFailCount = TxStaCnt0.field.TxFailCount; - TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; - - pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; - pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; - pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount; - pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; - pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; - pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; - - if (TxTotalCnt) - TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; - } - else - { - TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + - pEntry->OneSecTxRetryOkCount + - pEntry->OneSecTxFailCount; - - if (TxTotalCnt) - TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt; - } - - - // - // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI - // (criteria copied from RT2500 for Netopia case) - // - if (TxTotalCnt <= 12) - { - NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); - NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); - - if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx)) - { - pAd->CommonCfg.TxRateIndex = DownRateIdx; - pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; - } - else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) - { - pAd->CommonCfg.TxRateIndex = UpRateIdx; - } - - DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n")); - return; - } - - do - { - ULONG OneSecTxNoRetryOKRationCount; - - if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0) - ratio = 5; - else - ratio = 4; - - // downgrade TX quality if PER >= Rate-Down threshold - if (TxErrorRatio >= TrainDown) - { - pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; - } - - pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio; - - OneSecTxNoRetryOKRationCount = (TxSuccess * ratio); - - // perform DRS - consider TxRate Down first, then rate up. - if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx)) - { - if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) - { - pAd->CommonCfg.TxRateIndex = DownRateIdx; - pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; - - } - - } - else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) - { - if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown)) - { - - } - else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) - { - pAd->CommonCfg.TxRateIndex = UpRateIdx; - } - } - }while (FALSE); - - // if rate-up happen, clear all bad history of all TX rates - if (pAd->CommonCfg.TxRateIndex > CurrRateIdx) - { - pAd->DrsCounters.TxRateUpPenalty = 0; - NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); - NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); - bTxRateChanged = TRUE; - } - // if rate-down happen, only clear DownRate's bad history - else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx) - { - DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex)); - - pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty - pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0; - pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0; - bTxRateChanged = TRUE; - } - else - { - bTxRateChanged = FALSE; - } - - pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5]; - if (bTxRateChanged && pNextTxRate) - { - MlmeSetTxRate(pAd, pEntry, pNextTxRate); - } - } -} - -/* - ========================================================================== - Description: - This routine is executed periodically inside MlmePeriodicExec() after - association with an AP. - It checks if StaCfg.Psm is consistent with user policy (recorded in - StaCfg.WindowsPowerMode). If not, enforce user policy. However, - there're some conditions to consider: - 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all - the time when Mibss==TRUE - 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE - if outgoing traffic available in TxRing or MgmtRing. - Output: - 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID MlmeCheckPsmChange( - IN PRTMP_ADAPTER pAd, - IN ULONG Now32) -{ - ULONG PowerMode; - - // condition - - // 1. Psm maybe ON only happen in INFRASTRUCTURE mode - // 2. user wants either MAX_PSP or FAST_PSP - // 3. but current psm is not in PWR_SAVE - // 4. CNTL state machine is not doing SCANning - // 5. no TX SUCCESS event for the past 1-sec period - PowerMode = pAd->StaCfg.WindowsPowerMode; - - if (INFRA_ON(pAd) && - (PowerMode != Ndis802_11PowerModeCAM) && - (pAd->StaCfg.Psm == PWR_ACTIVE) && -// (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)&& - RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP) - /*&& - (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && - (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/) - { - NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime); - pAd->RalinkCounters.RxCountSinceLastNULL = 0; - RTMP_SET_PSM_BIT(pAd, PWR_SAVE); - if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) - { - RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE); - } - else - { - RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); - } - } -} - -// IRQL = PASSIVE_LEVEL -// IRQL = DISPATCH_LEVEL -VOID MlmeSetPsmBit( - IN PRTMP_ADAPTER pAd, - IN USHORT psm) -{ - AUTO_RSP_CFG_STRUC csr4; - - pAd->StaCfg.Psm = psm; - RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); - csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0; - RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); - DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm)); -} -#endif // CONFIG_STA_SUPPORT // - -/* - ========================================================================== - Description: - This routine calculates TxPER, RxPER of the past N-sec period. And - according to the calculation result, ChannelQuality is calculated here - to decide if current AP is still doing the job. - - If ChannelQuality is not good, a ROAMing attempt may be tried later. - Output: - StaCfg.ChannelQuality - 0..100 - - IRQL = DISPATCH_LEVEL - - NOTE: This routine decide channle quality based on RX CRC error ratio. - Caller should make sure a function call to NICUpdateRawCounters(pAd) - is performed right before this routine, so that this routine can decide - channel quality based on the most up-to-date information - ========================================================================== - */ -VOID MlmeCalculateChannelQuality( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pMacEntry, - IN ULONG Now32) -{ - ULONG TxOkCnt, TxCnt, TxPER, TxPRR; - ULONG RxCnt, RxPER; - UCHAR NorRssi; - CHAR MaxRssi; - RSSI_SAMPLE *pRssiSample = NULL; - UINT32 OneSecTxNoRetryOkCount = 0; - UINT32 OneSecTxRetryOkCount = 0; - UINT32 OneSecTxFailCount = 0; - UINT32 OneSecRxOkCnt = 0; - UINT32 OneSecRxFcsErrCnt = 0; - ULONG ChannelQuality = 0; // 0..100, Channel Quality Indication for Roaming -#ifdef CONFIG_STA_SUPPORT - ULONG BeaconLostTime = pAd->StaCfg.BeaconLostTime; -#endif // CONFIG_STA_SUPPORT // - -#ifdef CONFIG_STA_SUPPORT -#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier - // longer beacon lost time when carrier detection enabled - if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) - { - BeaconLostTime = pAd->StaCfg.BeaconLostTime + (pAd->StaCfg.BeaconLostTime/2); - } -#endif // CARRIER_DETECTION_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - -#ifdef CONFIG_STA_SUPPORT - if (pAd->OpMode == OPMODE_STA) - { - pRssiSample = &pAd->StaCfg.RssiSample; - OneSecTxNoRetryOkCount = pAd->RalinkCounters.OneSecTxNoRetryOkCount; - OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount; - OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount; - OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt; - OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt; - } -#endif // CONFIG_STA_SUPPORT // - - MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi0, - pRssiSample->LastRssi1, - pRssiSample->LastRssi2); - - // - // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics - // - TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount; - TxCnt = TxOkCnt + OneSecTxFailCount; - if (TxCnt < 5) - { - TxPER = 0; - TxPRR = 0; - } - else - { - TxPER = (OneSecTxFailCount * 100) / TxCnt; - TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt; - } - - // - // calculate RX PER - don't take RxPER into consideration if too few sample - // - RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt; - if (RxCnt < 5) - RxPER = 0; - else - RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt; - - // - // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER - // -#ifdef CONFIG_STA_SUPPORT - if ((pAd->OpMode == OPMODE_STA) && - INFRA_ON(pAd) && - (OneSecTxNoRetryOkCount < 2) && // no heavy traffic - ((pAd->StaCfg.LastBeaconRxTime + BeaconLostTime) < Now32)) - { - DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt)); - ChannelQuality = 0; - } - else -#endif // CONFIG_STA_SUPPORT // - { - // Normalize Rssi - if (MaxRssi > -40) - NorRssi = 100; - else if (MaxRssi < -90) - NorRssi = 0; - else - NorRssi = (MaxRssi + 90) * 2; - - // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) - ChannelQuality = (RSSI_WEIGHTING * NorRssi + - TX_WEIGHTING * (100 - TxPRR) + - RX_WEIGHTING* (100 - RxPER)) / 100; - } - - -#ifdef CONFIG_STA_SUPPORT - if (pAd->OpMode == OPMODE_STA) - pAd->Mlme.ChannelQuality = (ChannelQuality > 100) ? 100 : ChannelQuality; -#endif // CONFIG_STA_SUPPORT // - - -} - - -// IRQL = DISPATCH_LEVEL -VOID MlmeSetTxPreamble( - IN PRTMP_ADAPTER pAd, - IN USHORT TxPreamble) -{ - AUTO_RSP_CFG_STRUC csr4; - - // - // Always use Long preamble before verifiation short preamble functionality works well. - // Todo: remove the following line if short preamble functionality works - // - //TxPreamble = Rt802_11PreambleLong; - - RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); - if (TxPreamble == Rt802_11PreambleLong) - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n")); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); - csr4.field.AutoResponderPreamble = 0; - } - else - { - // NOTE: 1Mbps should always use long preamble - DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n")); - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); - csr4.field.AutoResponderPreamble = 1; - } - - RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); -} - -/* - ========================================================================== - Description: - Update basic rate bitmap - ========================================================================== - */ - -VOID UpdateBasicRateBitmap( - IN PRTMP_ADAPTER pAdapter) -{ - INT i, j; - /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ - UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; - UCHAR *sup_p = pAdapter->CommonCfg.SupRate; - UCHAR *ext_p = pAdapter->CommonCfg.ExtRate; - ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap; - - - /* if A mode, always use fix BasicRateBitMap */ - //if (pAdapter->CommonCfg.Channel == PHY_11A) - if (pAdapter->CommonCfg.Channel > 14) - pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */ - /* End of if */ - - if (pAdapter->CommonCfg.BasicRateBitmap > 4095) - { - /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */ - return; - } /* End of if */ - - for(i=0; iCommonCfg.DesireRate[i] & 0x7f) - { - case 2: Rate = RATE_1; num++; break; - case 4: Rate = RATE_2; num++; break; - case 11: Rate = RATE_5_5; num++; break; - case 22: Rate = RATE_11; num++; break; - case 12: Rate = RATE_6; num++; break; - case 18: Rate = RATE_9; num++; break; - case 24: Rate = RATE_12; num++; break; - case 36: Rate = RATE_18; num++; break; - case 48: Rate = RATE_24; num++; break; - case 72: Rate = RATE_36; num++; break; - case 96: Rate = RATE_48; num++; break; - case 108: Rate = RATE_54; num++; break; - //default: Rate = RATE_1; break; - } - if (MaxDesire < Rate) MaxDesire = Rate; - } - -//=========================================================================== -//=========================================================================== - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - pHtPhy = &pAd->StaCfg.HTPhyMode; - pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; - pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; - - auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; - HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS; - - if ((pAd->StaCfg.BssType == BSS_ADHOC) && - (pAd->CommonCfg.PhyMode == PHY_11B) && - (MaxDesire > RATE_11)) - { - MaxDesire = RATE_11; - } - } -#endif // CONFIG_STA_SUPPORT // - - pAd->CommonCfg.MaxDesiredRate = MaxDesire; - pMinHtPhy->word = 0; - pMaxHtPhy->word = 0; - pHtPhy->word = 0; - - // Auto rate switching is enabled only if more than one DESIRED RATES are - // specified; otherwise disabled - if (num <= 1) - { - //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); - //pAd->CommonCfg.bAutoTxRateSwitch = FALSE; - *auto_rate_cur_p = FALSE; - } - else - { - //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); - //pAd->CommonCfg.bAutoTxRateSwitch = TRUE; - *auto_rate_cur_p = TRUE; - } - - if (HtMcs != MCS_AUTO) - { - //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); - //pAd->CommonCfg.bAutoTxRateSwitch = FALSE; - *auto_rate_cur_p = FALSE; - } - else - { - //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); - //pAd->CommonCfg.bAutoTxRateSwitch = TRUE; - *auto_rate_cur_p = TRUE; - } - -#ifdef CONFIG_STA_SUPPORT - if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) - { - pSupRate = &pAd->StaActive.SupRate[0]; - pExtRate = &pAd->StaActive.ExtRate[0]; - SupRateLen = pAd->StaActive.SupRateLen; - ExtRateLen = pAd->StaActive.ExtRateLen; - } - else -#endif // CONFIG_STA_SUPPORT // - { - pSupRate = &pAd->CommonCfg.SupRate[0]; - pExtRate = &pAd->CommonCfg.ExtRate[0]; - SupRateLen = pAd->CommonCfg.SupRateLen; - ExtRateLen = pAd->CommonCfg.ExtRateLen; - } - - // find max supported rate - for (i=0; i Rate) MinSupport = Rate; - } - - for (i=0; i Rate) MinSupport = Rate; - } - - RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap); - - // bug fix - // pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap; - - // calculate the exptected ACK rate for each TX rate. This info is used to caculate - // the DURATION field of outgoing uniicast DATA/MGMT frame - for (i=0; iCommonCfg.ExpectedACKRate[i] = CurrBasicRate; - } - - DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire])); - // max tx rate = min {max desire rate, max supported rate} - if (MaxSupport < MaxDesire) - pAd->CommonCfg.MaxTxRate = MaxSupport; - else - pAd->CommonCfg.MaxTxRate = MaxDesire; - - pAd->CommonCfg.MinTxRate = MinSupport; - // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success - // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending - // on average RSSI - // 1. RSSI >= -70db, start at 54 Mbps (short distance) - // 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance) - // 3. -75 > RSSI, start at 11 Mbps (long distance) - //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* && - // OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/) - if (*auto_rate_cur_p) - { - short dbm = 0; -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta; -#endif // CONFIG_STA_SUPPORT // - if (bLinkUp == TRUE) - pAd->CommonCfg.TxRate = RATE_24; - else - pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; - - if (dbm < -75) - pAd->CommonCfg.TxRate = RATE_11; - else if (dbm < -70) - pAd->CommonCfg.TxRate = RATE_24; - - // should never exceed MaxTxRate (consider 11B-only mode) - if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate) - pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; - - pAd->CommonCfg.TxRateIndex = 0; - } - else - { - pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; - pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate; - pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK; - - pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC; - pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI; - pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS; - pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE; - } - - if (pAd->CommonCfg.TxRate <= RATE_11) - { - pMaxHtPhy->field.MODE = MODE_CCK; - pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate; - pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate; - } - else - { - pMaxHtPhy->field.MODE = MODE_OFDM; - pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate]; - if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54)) - {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];} - else - {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;} - } - - pHtPhy->word = (pMaxHtPhy->word); - if (bLinkUp && (pAd->OpMode == OPMODE_STA)) - { - pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word; - pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word; - pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word; - } - else - { - switch (pAd->CommonCfg.PhyMode) - { - case PHY_11BG_MIXED: - case PHY_11B: -#ifdef DOT11_N_SUPPORT - case PHY_11BGN_MIXED: -#endif // DOT11_N_SUPPORT // - pAd->CommonCfg.MlmeRate = RATE_1; - pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; - pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; - -//#ifdef WIFI_TEST - pAd->CommonCfg.RtsRate = RATE_11; -//#else -// pAd->CommonCfg.RtsRate = RATE_1; -//#endif - break; - case PHY_11G: - case PHY_11A: -#ifdef DOT11_N_SUPPORT - case PHY_11AGN_MIXED: - case PHY_11GN_MIXED: - case PHY_11N_2_4G: - case PHY_11AN_MIXED: - case PHY_11N_5G: -#endif // DOT11_N_SUPPORT // - pAd->CommonCfg.MlmeRate = RATE_6; - pAd->CommonCfg.RtsRate = RATE_6; - pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; - pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; - break; - case PHY_11ABG_MIXED: -#ifdef DOT11_N_SUPPORT - case PHY_11ABGN_MIXED: -#endif // DOT11_N_SUPPORT // - if (pAd->CommonCfg.Channel <= 14) - { - pAd->CommonCfg.MlmeRate = RATE_1; - pAd->CommonCfg.RtsRate = RATE_1; - pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; - pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; - } - else - { - pAd->CommonCfg.MlmeRate = RATE_6; - pAd->CommonCfg.RtsRate = RATE_6; - pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; - pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; - } - break; - default: // error - pAd->CommonCfg.MlmeRate = RATE_6; - pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; - pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; - pAd->CommonCfg.RtsRate = RATE_1; - break; - } - // - // Keep Basic Mlme Rate. - // - pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word; - if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM) - pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24]; - else - pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1; - pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate; - } - - DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n", - RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate], - /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p)); - DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n", - RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap)); - DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n", - pAd->CommonCfg.MlmeTransmit.word, pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word )); -} - -#ifdef DOT11_N_SUPPORT -/* - ========================================================================== - Description: - This function update HT Rate setting. - Input Wcid value is valid for 2 case : - 1. it's used for Station in infra mode that copy AP rate to Mactable. - 2. OR Station in adhoc mode to copy peer's HT rate to Mactable. - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID MlmeUpdateHtTxRates( - IN PRTMP_ADAPTER pAd, - IN UCHAR apidx) -{ - UCHAR StbcMcs; //j, StbcMcs, bitmask; - CHAR i; // 3*3 - RT_HT_CAPABILITY *pRtHtCap = NULL; - RT_HT_PHY_INFO *pActiveHtPhy = NULL; - ULONG BasicMCS; - UCHAR j, bitmask; - PRT_HT_PHY_INFO pDesireHtPhy = NULL; - PHTTRANSMIT_SETTING pHtPhy = NULL; - PHTTRANSMIT_SETTING pMaxHtPhy = NULL; - PHTTRANSMIT_SETTING pMinHtPhy = NULL; - BOOLEAN *auto_rate_cur_p; - - DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n")); - - auto_rate_cur_p = NULL; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; - pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; - pHtPhy = &pAd->StaCfg.HTPhyMode; - pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; - pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; - - auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; - } -#endif // CONFIG_STA_SUPPORT // - -#ifdef CONFIG_STA_SUPPORT - if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) - { - if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) - return; - - pRtHtCap = &pAd->StaActive.SupportedHtPhy; - pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo; - StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs; - BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16); - if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2)) - pMaxHtPhy->field.STBC = STBC_USE; - else - pMaxHtPhy->field.STBC = STBC_NONE; - } - else -#endif // CONFIG_STA_SUPPORT // - { - if (pDesireHtPhy->bHtEnable == FALSE) - return; - - pRtHtCap = &pAd->CommonCfg.DesiredHtPhy; - StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs; - BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16); - if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2)) - pMaxHtPhy->field.STBC = STBC_USE; - else - pMaxHtPhy->field.STBC = STBC_NONE; - } - - // Decide MAX ht rate. - if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) - pMaxHtPhy->field.MODE = MODE_HTGREENFIELD; - else - pMaxHtPhy->field.MODE = MODE_HTMIX; - - if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth)) - pMaxHtPhy->field.BW = BW_40; - else - pMaxHtPhy->field.BW = BW_20; - - if (pMaxHtPhy->field.BW == BW_20) - pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20); - else - pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40); - - if (pDesireHtPhy->MCSSet[4] != 0) - { - pMaxHtPhy->field.MCS = 32; - } - - for (i=23; i>=0; i--) // 3*3 - { - j = i/8; - bitmask = (1<<(i-(j*8))); - - if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask)) - { - pMaxHtPhy->field.MCS = i; - break; - } - - if (i==0) - break; - } - - // Copy MIN ht rate. rt2860??? - pMinHtPhy->field.BW = BW_20; - pMinHtPhy->field.MCS = 0; - pMinHtPhy->field.STBC = 0; - pMinHtPhy->field.ShortGI = 0; - //If STA assigns fixed rate. update to fixed here. -#ifdef CONFIG_STA_SUPPORT - if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)) - { - if (pDesireHtPhy->MCSSet[4] != 0) - { - pMaxHtPhy->field.MCS = 32; - pMinHtPhy->field.MCS = 32; - DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS)); - } - - for (i=23; (CHAR)i >= 0; i--) // 3*3 - { - j = i/8; - bitmask = (1<<(i-(j*8))); - if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask)) - { - pMaxHtPhy->field.MCS = i; - pMinHtPhy->field.MCS = i; - break; - } - if (i==0) - break; - } - } -#endif // CONFIG_STA_SUPPORT // - - - // Decide ht rate - pHtPhy->field.STBC = pMaxHtPhy->field.STBC; - pHtPhy->field.BW = pMaxHtPhy->field.BW; - pHtPhy->field.MODE = pMaxHtPhy->field.MODE; - pHtPhy->field.MCS = pMaxHtPhy->field.MCS; - pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI; - - // use default now. rt2860 - if (pDesireHtPhy->MCSSet[0] != 0xff) - *auto_rate_cur_p = FALSE; - else - *auto_rate_cur_p = TRUE; - - DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize )); - DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS, - pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE)); - DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n")); -} - - -VOID BATableInit( - IN PRTMP_ADAPTER pAd, - IN BA_TABLE *Tab) -{ - int i; - - Tab->numAsOriginator = 0; - Tab->numAsRecipient = 0; - Tab->numDoneOriginator = 0; - NdisAllocateSpinLock(&pAd->BATabLock); - for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) - { - Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE; - NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock)); - } - for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) - { - Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE; - } -} -#endif // DOT11_N_SUPPORT // - -// IRQL = DISPATCH_LEVEL -VOID MlmeRadioOff( - IN PRTMP_ADAPTER pAd) -{ - RTMP_MLME_RADIO_OFF(pAd); -} - -// IRQL = DISPATCH_LEVEL -VOID MlmeRadioOn( - IN PRTMP_ADAPTER pAd) -{ - RTMP_MLME_RADIO_ON(pAd); -} - -// =========================================================================================== -// bss_table.c -// =========================================================================================== - - -/*! \brief initialize BSS table - * \param p_tab pointer to the table - * \return none - * \pre - * \post - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - */ -VOID BssTableInit( - IN BSS_TABLE *Tab) -{ - int i; - - Tab->BssNr = 0; - Tab->BssOverlapNr = 0; - for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) - { - NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY)); - Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value - } -} - - -/*! \brief search the BSS table by SSID - * \param p_tab pointer to the bss table - * \param ssid SSID string - * \return index of the table, BSS_NOT_FOUND if not in the table - * \pre - * \post - * \note search by sequential search - - IRQL = DISPATCH_LEVEL - - */ -ULONG BssTableSearch( - IN BSS_TABLE *Tab, - IN PUCHAR pBssid, - IN UCHAR Channel) -{ - UCHAR i; - - for (i = 0; i < Tab->BssNr; i++) - { - // - // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. - // We should distinguish this case. - // - if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || - ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && - MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) - { - return i; - } - } - return (ULONG)BSS_NOT_FOUND; -} - -ULONG BssSsidTableSearch( - IN BSS_TABLE *Tab, - IN PUCHAR pBssid, - IN PUCHAR pSsid, - IN UCHAR SsidLen, - IN UCHAR Channel) -{ - UCHAR i; - - for (i = 0; i < Tab->BssNr; i++) - { - // - // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. - // We should distinguish this case. - // - if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || - ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && - MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) && - SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen)) - { - return i; - } - } - return (ULONG)BSS_NOT_FOUND; -} - -ULONG BssTableSearchWithSSID( - IN BSS_TABLE *Tab, - IN PUCHAR Bssid, - IN PUCHAR pSsid, - IN UCHAR SsidLen, - IN UCHAR Channel) -{ - UCHAR i; - - for (i = 0; i < Tab->BssNr; i++) - { - if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || - ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && - MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) && - (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) || - (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) || - (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen)))) - { - return i; - } - } - return (ULONG)BSS_NOT_FOUND; -} - - -ULONG BssSsidTableSearchBySSID( - IN BSS_TABLE *Tab, - IN PUCHAR pSsid, - IN UCHAR SsidLen) -{ - UCHAR i; - - for (i = 0; i < Tab->BssNr; i++) - { - if (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen)) - { - return i; - } - } - return (ULONG)BSS_NOT_FOUND; -} - - -// IRQL = DISPATCH_LEVEL -VOID BssTableDeleteEntry( - IN OUT BSS_TABLE *Tab, - IN PUCHAR pBssid, - IN UCHAR Channel) -{ - UCHAR i, j; - - for (i = 0; i < Tab->BssNr; i++) - { - if ((Tab->BssEntry[i].Channel == Channel) && - (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) - { - for (j = i; j < Tab->BssNr - 1; j++) - { - NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY)); - } - NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY)); - Tab->BssNr -= 1; - return; - } - } -} - -#ifdef DOT11_N_SUPPORT -/* - ======================================================================== - Routine Description: - Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed. - - Arguments: - // IRQL = DISPATCH_LEVEL - ======================================================================== -*/ -VOID BATableDeleteORIEntry( - IN OUT PRTMP_ADAPTER pAd, - IN BA_ORI_ENTRY *pBAORIEntry) -{ - - if (pBAORIEntry->ORI_BA_Status != Originator_NONE) - { - NdisAcquireSpinLock(&pAd->BATabLock); - if (pBAORIEntry->ORI_BA_Status == Originator_Done) - { - pAd->BATable.numAsOriginator -= 1; - DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient)); - // Erase Bitmap flag. - } - pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here - pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here - pBAORIEntry->ORI_BA_Status = Originator_NONE; - pBAORIEntry->Token = 1; - // Not clear Sequence here. - NdisReleaseSpinLock(&pAd->BATabLock); - } -} -#endif // DOT11_N_SUPPORT // - -/*! \brief - * \param - * \return - * \pre - * \post - - IRQL = DISPATCH_LEVEL - - */ -VOID BssEntrySet( - IN PRTMP_ADAPTER pAd, - OUT BSS_ENTRY *pBss, - IN PUCHAR pBssid, - IN CHAR Ssid[], - IN UCHAR SsidLen, - IN UCHAR BssType, - IN USHORT BeaconPeriod, - IN PCF_PARM pCfParm, - IN USHORT AtimWin, - IN USHORT CapabilityInfo, - IN UCHAR SupRate[], - IN UCHAR SupRateLen, - IN UCHAR ExtRate[], - IN UCHAR ExtRateLen, - IN HT_CAPABILITY_IE *pHtCapability, - IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE - IN UCHAR HtCapabilityLen, - IN UCHAR AddHtInfoLen, - IN UCHAR NewExtChanOffset, - IN UCHAR Channel, - IN CHAR Rssi, - IN LARGE_INTEGER TimeStamp, - IN UCHAR CkipFlag, - IN PEDCA_PARM pEdcaParm, - IN PQOS_CAPABILITY_PARM pQosCapability, - IN PQBSS_LOAD_PARM pQbssLoad, - IN USHORT LengthVIE, - IN PNDIS_802_11_VARIABLE_IEs pVIE) -{ - COPY_MAC_ADDR(pBss->Bssid, pBssid); - // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID - pBss->Hidden = 1; - if (SsidLen > 0) - { - // For hidden SSID AP, it might send beacon with SSID len equal to 0 - // Or send beacon /probe response with SSID len matching real SSID length, - // but SSID is all zero. such as "00-00-00-00" with length 4. - // We have to prevent this case overwrite correct table - if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) - { - NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID); - NdisMoveMemory(pBss->Ssid, Ssid, SsidLen); - pBss->SsidLen = SsidLen; - pBss->Hidden = 0; - } - } - else - pBss->SsidLen = 0; - pBss->BssType = BssType; - pBss->BeaconPeriod = BeaconPeriod; - if (BssType == BSS_INFRA) - { - if (pCfParm->bValid) - { - pBss->CfpCount = pCfParm->CfpCount; - pBss->CfpPeriod = pCfParm->CfpPeriod; - pBss->CfpMaxDuration = pCfParm->CfpMaxDuration; - pBss->CfpDurRemaining = pCfParm->CfpDurRemaining; - } - } - else - { - pBss->AtimWin = AtimWin; - } - - pBss->CapabilityInfo = CapabilityInfo; - // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES - // Combine with AuthMode, they will decide the connection methods. - pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo); - ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES); - if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) - NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen); - else - NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES); - pBss->SupRateLen = SupRateLen; - ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES); - NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen); - pBss->NewExtChanOffset = NewExtChanOffset; - pBss->ExtRateLen = ExtRateLen; - pBss->Channel = Channel; - pBss->CentralChannel = Channel; - pBss->Rssi = Rssi; - // Update CkipFlag. if not exists, the value is 0x0 - pBss->CkipFlag = CkipFlag; - - // New for microsoft Fixed IEs - NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8); - pBss->FixIEs.BeaconInterval = BeaconPeriod; - pBss->FixIEs.Capabilities = CapabilityInfo; - - // New for microsoft Variable IEs - if (LengthVIE != 0) - { - pBss->VarIELen = LengthVIE; - NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen); - } - else - { - pBss->VarIELen = 0; - } - - pBss->AddHtInfoLen = 0; - pBss->HtCapabilityLen = 0; -#ifdef DOT11_N_SUPPORT - if (HtCapabilityLen> 0) - { - pBss->HtCapabilityLen = HtCapabilityLen; - NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen); - if (AddHtInfoLen > 0) - { - pBss->AddHtInfoLen = AddHtInfoLen; - NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen); - - if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) - { - pBss->CentralChannel = pAddHtInfo->ControlChan - 2; - } - else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) - { - pBss->CentralChannel = pAddHtInfo->ControlChan + 2; - } - } - } -#endif // DOT11_N_SUPPORT // - - BssCipherParse(pBss); - - // new for QOS - if (pEdcaParm) - NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM)); - else - pBss->EdcaParm.bValid = FALSE; - if (pQosCapability) - NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM)); - else - pBss->QosCapability.bValid = FALSE; - if (pQbssLoad) - NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM)); - else - pBss->QbssLoad.bValid = FALSE; - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - PEID_STRUCT pEid; - USHORT Length = 0; - - - NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN); - NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN); -#ifdef EXT_BUILD_CHANNEL_LIST - NdisZeroMemory(&pBss->CountryString[0], 3); - pBss->bHasCountryIE = FALSE; -#endif // EXT_BUILD_CHANNEL_LIST // - pEid = (PEID_STRUCT) pVIE; - while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE) - { - switch(pEid->Eid) - { - case IE_WPA: - if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) - { - if ((pEid->Len + 2) > MAX_CUSTOM_LEN) - { - pBss->WpaIE.IELen = 0; - break; - } - pBss->WpaIE.IELen = pEid->Len + 2; - NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen); - } - break; - case IE_RSN: - if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) - { - if ((pEid->Len + 2) > MAX_CUSTOM_LEN) - { - pBss->RsnIE.IELen = 0; - break; - } - pBss->RsnIE.IELen = pEid->Len + 2; - NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen); - } - break; -#ifdef EXT_BUILD_CHANNEL_LIST - case IE_COUNTRY: - NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3); - pBss->bHasCountryIE = TRUE; - break; -#endif // EXT_BUILD_CHANNEL_LIST // - } - Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len] - pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); - } - } -#endif // CONFIG_STA_SUPPORT // -} - -/*! - * \brief insert an entry into the bss table - * \param p_tab The BSS table - * \param Bssid BSSID - * \param ssid SSID - * \param ssid_len Length of SSID - * \param bss_type - * \param beacon_period - * \param timestamp - * \param p_cf - * \param atim_win - * \param cap - * \param rates - * \param rates_len - * \param channel_idx - * \return none - * \pre - * \post - * \note If SSID is identical, the old entry will be replaced by the new one - - IRQL = DISPATCH_LEVEL - - */ -ULONG BssTableSetEntry( - IN PRTMP_ADAPTER pAd, - OUT BSS_TABLE *Tab, - IN PUCHAR pBssid, - IN CHAR Ssid[], - IN UCHAR SsidLen, - IN UCHAR BssType, - IN USHORT BeaconPeriod, - IN CF_PARM *CfParm, - IN USHORT AtimWin, - IN USHORT CapabilityInfo, - IN UCHAR SupRate[], - IN UCHAR SupRateLen, - IN UCHAR ExtRate[], - IN UCHAR ExtRateLen, - IN HT_CAPABILITY_IE *pHtCapability, - IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE - IN UCHAR HtCapabilityLen, - IN UCHAR AddHtInfoLen, - IN UCHAR NewExtChanOffset, - IN UCHAR ChannelNo, - IN CHAR Rssi, - IN LARGE_INTEGER TimeStamp, - IN UCHAR CkipFlag, - IN PEDCA_PARM pEdcaParm, - IN PQOS_CAPABILITY_PARM pQosCapability, - IN PQBSS_LOAD_PARM pQbssLoad, - IN USHORT LengthVIE, - IN PNDIS_802_11_VARIABLE_IEs pVIE) -{ - ULONG Idx; - - Idx = BssTableSearchWithSSID(Tab, pBssid, (UCHAR *)Ssid, SsidLen, ChannelNo); - if (Idx == BSS_NOT_FOUND) - { - if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) - { - // - // It may happen when BSS Table was full. - // The desired AP will not be added into BSS Table - // In this case, if we found the desired AP then overwrite BSS Table. - // - if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) || - SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen)) - { - Idx = Tab->BssOverlapNr; - BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin, - CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, - NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); - Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE; - } - return Idx; - } - else - { - return BSS_NOT_FOUND; - } - } - Idx = Tab->BssNr; - BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin, - CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, - NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); - Tab->BssNr++; - } - else - { - /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */ - if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) || - (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen))) - { - BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin, - CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, - NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); - } - } - - return Idx; -} - -#ifdef CONFIG_STA_SUPPORT -#ifdef DOT11_N_SUPPORT -#ifdef DOT11N_DRAFT3 -VOID TriEventInit( - IN PRTMP_ADAPTER pAd) -{ - UCHAR i; - - for (i = 0;i < MAX_TRIGGER_EVENT;i++) - pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE; - - pAd->CommonCfg.TriggerEventTab.EventANo = 0; - pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0; -} - -ULONG TriEventTableSetEntry( - IN PRTMP_ADAPTER pAd, - OUT TRIGGER_EVENT_TAB *Tab, - IN PUCHAR pBssid, - IN HT_CAPABILITY_IE *pHtCapability, - IN UCHAR HtCapabilityLen, - IN UCHAR RegClass, - IN UCHAR ChannelNo) -{ - // Event A - if (HtCapabilityLen == 0) - { - if (Tab->EventANo < MAX_TRIGGER_EVENT) - { - RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6); - Tab->EventA[Tab->EventANo].bValid = TRUE; - Tab->EventA[Tab->EventANo].Channel = ChannelNo; - Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay; - if (RegClass != 0) - { - // Beacon has Regulatory class IE. So use beacon's - Tab->EventA[Tab->EventANo].RegClass = RegClass; - } - else - { - // Use Station's Regulatory class instead. - if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE) - { - if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) - { - Tab->EventA[Tab->EventANo].RegClass = 32; - } - else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) - Tab->EventA[Tab->EventANo].RegClass = 33; - } - else - Tab->EventA[Tab->EventANo].RegClass = ??; - - } - - Tab->EventANo ++; - } - } - else if (pHtCapability->HtCapInfo.Intolerant40) - { - Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay; - } - -} - -/* - ======================================================================== - Routine Description: - Trigger Event table Maintainence called once every second. - - Arguments: - // IRQL = DISPATCH_LEVEL - ======================================================================== -*/ -VOID TriEventCounterMaintenance( - IN PRTMP_ADAPTER pAd) -{ - UCHAR i; - BOOLEAN bNotify = FALSE; - for (i = 0;i < MAX_TRIGGER_EVENT;i++) - { - if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0)) - { - pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--; - if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0) - { - pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE; - pAd->CommonCfg.TriggerEventTab.EventANo --; - // Need to send 20/40 Coexistence Notify frame if has status change. - bNotify = TRUE; - } - } - } - if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0) - { - pAd->CommonCfg.TriggerEventTab.EventBCountDown--; - if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0) - bNotify = TRUE; - } - - if (bNotify == TRUE) - Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE); -} -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // - -// IRQL = DISPATCH_LEVEL -VOID BssTableSsidSort( - IN PRTMP_ADAPTER pAd, - OUT BSS_TABLE *OutTab, - IN CHAR Ssid[], - IN UCHAR SsidLen) -{ - INT i; - BssTableInit(OutTab); - - for (i = 0; i < pAd->ScanTab.BssNr; i++) - { - BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i]; - BOOLEAN bIsHiddenApIncluded = FALSE; - - if (((pAd->CommonCfg.bIEEE80211H == 1) && - (pAd->MlmeAux.Channel > 14) && - RadarChannelCheck(pAd, pInBss->Channel)) -#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier - || (pAd->CommonCfg.CarrierDetect.Enable == TRUE) -#endif // CARRIER_DETECTION_SUPPORT // - ) -{ - if (pInBss->Hidden) - bIsHiddenApIncluded = TRUE; -} - - if ((pInBss->BssType == pAd->StaCfg.BssType) && - (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded)) - { - BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; - - -#ifdef EXT_BUILD_CHANNEL_LIST - // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict. - if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) && - (pInBss->bHasCountryIE == FALSE)) - { - DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n")); - continue; - } -#endif // EXT_BUILD_CHANNEL_LIST // - -#ifdef DOT11_N_SUPPORT - // 2.4G/5G N only mode - if ((pInBss->HtCapabilityLen == 0) && - ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) - { - DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); - continue; - } -#endif // DOT11_N_SUPPORT // - - // New for WPA2 - // Check the Authmode first - if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - { - // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode - if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux)) - // None matched - continue; - - // Check cipher suite, AP must have more secured cipher than station setting - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) - { - // If it's not mixed mode, we should only let BSS pass with the same encryption - if (pInBss->WPA.bMixMode == FALSE) - if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher) - continue; - - // check group cipher - if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) && - (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) && - (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled)) - continue; - - // check pairwise cipher, skip if none matched - // If profile set to AES, let it pass without question. - // If profile set to TKIP, we must find one mateched - if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && - (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) && - (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux)) - continue; - } - else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - // If it's not mixed mode, we should only let BSS pass with the same encryption - if (pInBss->WPA2.bMixMode == FALSE) - if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher) - continue; - - // check group cipher - if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) && - (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) && - (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled)) - continue; - - // check pairwise cipher, skip if none matched - // If profile set to AES, let it pass without question. - // If profile set to TKIP, we must find one mateched - if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && - (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) && - (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux)) - continue; - } - } - // Bss Type matched, SSID matched. - // We will check wepstatus for qualification Bss - else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) - { - DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus)); - // - // For the SESv2 case, we will not qualify WepStatus. - // - if (!pInBss->bSES) - continue; - } - - // Since the AP is using hidden SSID, and we are trying to connect to ANY - // It definitely will fail. So, skip it. - // CCX also require not even try to connect it!! - if (SsidLen == 0) - continue; - -#ifdef DOT11_N_SUPPORT - // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region - // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, - if ((pInBss->CentralChannel != pInBss->Channel) && - (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) - { - if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE) - { - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; - SetCommonHT(pAd); - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; - } - else - { - if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20) - { - SetCommonHT(pAd); - } - } - } -#endif // DOT11_N_SUPPORT // - - // copy matching BSS from InTab to OutTab - NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); - - OutTab->BssNr++; - } - else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0)) - { - BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; - - -#ifdef DOT11_N_SUPPORT - // 2.4G/5G N only mode - if ((pInBss->HtCapabilityLen == 0) && - ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) - { - DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); - continue; - } -#endif // DOT11_N_SUPPORT // - - // New for WPA2 - // Check the Authmode first - if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - { - // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode - if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux)) - // None matched - continue; - - // Check cipher suite, AP must have more secured cipher than station setting - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) - { - // If it's not mixed mode, we should only let BSS pass with the same encryption - if (pInBss->WPA.bMixMode == FALSE) - if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher) - continue; - - // check group cipher - if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) - continue; - - // check pairwise cipher, skip if none matched - // If profile set to AES, let it pass without question. - // If profile set to TKIP, we must find one mateched - if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && - (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) && - (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux)) - continue; - } - else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - // If it's not mixed mode, we should only let BSS pass with the same encryption - if (pInBss->WPA2.bMixMode == FALSE) - if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher) - continue; - - // check group cipher - if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher) - continue; - - // check pairwise cipher, skip if none matched - // If profile set to AES, let it pass without question. - // If profile set to TKIP, we must find one mateched - if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && - (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) && - (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux)) - continue; - } - } - // Bss Type matched, SSID matched. - // We will check wepstatus for qualification Bss - else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) - continue; - -#ifdef DOT11_N_SUPPORT - // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region - // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, - if ((pInBss->CentralChannel != pInBss->Channel) && - (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) - { - if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE) - { - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; - SetCommonHT(pAd); - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; - } - } -#endif // DOT11_N_SUPPORT // - - // copy matching BSS from InTab to OutTab - NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); - - OutTab->BssNr++; - } - - if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE) - break; - } - - BssTableSortByRssi(OutTab); -} - - -// IRQL = DISPATCH_LEVEL -VOID BssTableSortByRssi( - IN OUT BSS_TABLE *OutTab) -{ - INT i, j; - BSS_ENTRY TmpBss; - - for (i = 0; i < OutTab->BssNr - 1; i++) - { - for (j = i+1; j < OutTab->BssNr; j++) - { - if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi) - { - NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY)); - NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY)); - NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY)); - } - } - } -} -#endif // CONFIG_STA_SUPPORT // - - -VOID BssCipherParse( - IN OUT PBSS_ENTRY pBss) -{ - PEID_STRUCT pEid; - PUCHAR pTmp; - PRSN_IE_HEADER_STRUCT pRsnHeader; - PCIPHER_SUITE_STRUCT pCipher; - PAKM_SUITE_STRUCT pAKM; - USHORT Count; - INT Length; - NDIS_802_11_ENCRYPTION_STATUS TmpCipher; - - // - // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame. - // - if (pBss->Privacy) - { - pBss->WepStatus = Ndis802_11WEPEnabled; - } - else - { - pBss->WepStatus = Ndis802_11WEPDisabled; - } - // Set default to disable & open authentication before parsing variable IE - pBss->AuthMode = Ndis802_11AuthModeOpen; - pBss->AuthModeAux = Ndis802_11AuthModeOpen; - - // Init WPA setting - pBss->WPA.PairCipher = Ndis802_11WEPDisabled; - pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled; - pBss->WPA.GroupCipher = Ndis802_11WEPDisabled; - pBss->WPA.RsnCapability = 0; - pBss->WPA.bMixMode = FALSE; - - // Init WPA2 setting - pBss->WPA2.PairCipher = Ndis802_11WEPDisabled; - pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled; - pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled; - pBss->WPA2.RsnCapability = 0; - pBss->WPA2.bMixMode = FALSE; - - - Length = (INT) pBss->VarIELen; - - while (Length > 0) - { - // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently - pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length; - pEid = (PEID_STRUCT) pTmp; - switch (pEid->Eid) - { - case IE_WPA: - if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7)) - { - pBss->bSES = TRUE; - break; - } - else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1) - { - // if unsupported vendor specific IE - break; - } - // Skip OUI, version, and multicast suite - // This part should be improved in the future when AP supported multiple cipher suite. - // For now, it's OK since almost all APs have fixed cipher suite supported. - // pTmp = (PUCHAR) pEid->Octet; - pTmp += 11; - - // Cipher Suite Selectors from Spec P802.11i/D3.2 P26. - // Value Meaning - // 0 None - // 1 WEP-40 - // 2 Tkip - // 3 WRAP - // 4 AES - // 5 WEP-104 - // Parse group cipher - switch (*pTmp) - { - case 1: - pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled; - break; - case 5: - pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled; - break; - case 2: - pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled; - break; - case 4: - pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled; - break; - default: - break; - } - // number of unicast suite - pTmp += 1; - - // skip all unicast cipher suites - //Count = *(PUSHORT) pTmp; - Count = (pTmp[1]<<8) + pTmp[0]; - pTmp += sizeof(USHORT); - - // Parsing all unicast cipher suite - while (Count > 0) - { - // Skip OUI - pTmp += 3; - TmpCipher = Ndis802_11WEPDisabled; - switch (*pTmp) - { - case 1: - case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway - TmpCipher = Ndis802_11Encryption1Enabled; - break; - case 2: - TmpCipher = Ndis802_11Encryption2Enabled; - break; - case 4: - TmpCipher = Ndis802_11Encryption3Enabled; - break; - default: - break; - } - if (TmpCipher > pBss->WPA.PairCipher) - { - // Move the lower cipher suite to PairCipherAux - pBss->WPA.PairCipherAux = pBss->WPA.PairCipher; - pBss->WPA.PairCipher = TmpCipher; - } - else - { - pBss->WPA.PairCipherAux = TmpCipher; - } - pTmp++; - Count--; - } - - // 4. get AKM suite counts - //Count = *(PUSHORT) pTmp; - Count = (pTmp[1]<<8) + pTmp[0]; - pTmp += sizeof(USHORT); - pTmp += 3; - - switch (*pTmp) - { - case 1: - // Set AP support WPA-enterprise mode - if (pBss->AuthMode == Ndis802_11AuthModeOpen) - pBss->AuthMode = Ndis802_11AuthModeWPA; - else - pBss->AuthModeAux = Ndis802_11AuthModeWPA; - break; - case 2: - // Set AP support WPA-PSK mode - if (pBss->AuthMode == Ndis802_11AuthModeOpen) - pBss->AuthMode = Ndis802_11AuthModeWPAPSK; - else - pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK; - break; - default: - break; - } - pTmp += 1; - - // Fixed for WPA-None - if (pBss->BssType == BSS_ADHOC) - { - pBss->AuthMode = Ndis802_11AuthModeWPANone; - pBss->AuthModeAux = Ndis802_11AuthModeWPANone; - pBss->WepStatus = pBss->WPA.GroupCipher; - // Patched bugs for old driver - if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) - pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher; - } - else - pBss->WepStatus = pBss->WPA.PairCipher; - - // Check the Pair & Group, if different, turn on mixed mode flag - if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher) - pBss->WPA.bMixMode = TRUE; - - break; - - case IE_RSN: - pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp; - - // 0. Version must be 1 - if (le2cpu16(pRsnHeader->Version) != 1) - break; - pTmp += sizeof(RSN_IE_HEADER_STRUCT); - - // 1. Check group cipher - pCipher = (PCIPHER_SUITE_STRUCT) pTmp; - if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) - break; - - // Parse group cipher - switch (pCipher->Type) - { - case 1: - pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled; - break; - case 5: - pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled; - break; - case 2: - pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled; - break; - case 4: - pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled; - break; - default: - break; - } - // set to correct offset for next parsing - pTmp += sizeof(CIPHER_SUITE_STRUCT); - - // 2. Get pairwise cipher counts - //Count = *(PUSHORT) pTmp; - Count = (pTmp[1]<<8) + pTmp[0]; - pTmp += sizeof(USHORT); - - // 3. Get pairwise cipher - // Parsing all unicast cipher suite - while (Count > 0) - { - // Skip OUI - pCipher = (PCIPHER_SUITE_STRUCT) pTmp; - TmpCipher = Ndis802_11WEPDisabled; - switch (pCipher->Type) - { - case 1: - case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway - TmpCipher = Ndis802_11Encryption1Enabled; - break; - case 2: - TmpCipher = Ndis802_11Encryption2Enabled; - break; - case 4: - TmpCipher = Ndis802_11Encryption3Enabled; - break; - default: - break; - } - if (TmpCipher > pBss->WPA2.PairCipher) - { - // Move the lower cipher suite to PairCipherAux - pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher; - pBss->WPA2.PairCipher = TmpCipher; - } - else - { - pBss->WPA2.PairCipherAux = TmpCipher; - } - pTmp += sizeof(CIPHER_SUITE_STRUCT); - Count--; - } - - // 4. get AKM suite counts - //Count = *(PUSHORT) pTmp; - Count = (pTmp[1]<<8) + pTmp[0]; - pTmp += sizeof(USHORT); - - // 5. Get AKM ciphers - // Parsing all AKM ciphers - while (Count > 0) - { - pAKM = (PAKM_SUITE_STRUCT) pTmp; - if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) - break; - - switch (pAKM->Type) - { - case 1: - // Set AP support WPA-enterprise mode - if (pBss->AuthMode == Ndis802_11AuthModeOpen) - pBss->AuthMode = Ndis802_11AuthModeWPA2; - else - pBss->AuthModeAux = Ndis802_11AuthModeWPA2; - break; - case 2: - // Set AP support WPA-PSK mode - if (pBss->AuthMode == Ndis802_11AuthModeOpen) - pBss->AuthMode = Ndis802_11AuthModeWPA2PSK; - else - pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK; - break; - default: - if (pBss->AuthMode == Ndis802_11AuthModeOpen) - pBss->AuthMode = Ndis802_11AuthModeMax; - else - pBss->AuthModeAux = Ndis802_11AuthModeMax; - break; - } - pTmp += (Count * sizeof(AKM_SUITE_STRUCT)); - Count--; - } - - // Fixed for WPA-None - if (pBss->BssType == BSS_ADHOC) - { - pBss->AuthMode = Ndis802_11AuthModeWPANone; - pBss->AuthModeAux = Ndis802_11AuthModeWPANone; - pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux; - pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher; - pBss->WepStatus = pBss->WPA.GroupCipher; - // Patched bugs for old driver - if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) - pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher; - } - pBss->WepStatus = pBss->WPA2.PairCipher; - - // 6. Get RSN capability - //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp; - pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0]; - pTmp += sizeof(USHORT); - - // Check the Pair & Group, if different, turn on mixed mode flag - if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher) - pBss->WPA2.bMixMode = TRUE; - - break; - default: - break; - } - Length -= (pEid->Len + 2); - } -} - -// =========================================================================================== -// mac_table.c -// =========================================================================================== - -/*! \brief generates a random mac address value for IBSS BSSID - * \param Addr the bssid location - * \return none - * \pre - * \post - */ -VOID MacAddrRandomBssid( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pAddr) -{ - INT i; - - for (i = 0; i < MAC_ADDR_LEN; i++) - { - pAddr[i] = RandomByte(pAd); - } - - pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx -} - -/*! \brief init the management mac frame header - * \param p_hdr mac header - * \param subtype subtype of the frame - * \param p_ds destination address, don't care if it is a broadcast address - * \return none - * \pre the station has the following information in the pAd->StaCfg - * - bssid - * - station address - * \post - * \note this function initializes the following field - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - */ -VOID MgtMacHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PHEADER_802_11 pHdr80211, - IN UCHAR SubType, - IN UCHAR ToDs, - IN PUCHAR pDA, - IN PUCHAR pBssid) -{ - NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); - - pHdr80211->FC.Type = BTYPE_MGMT; - pHdr80211->FC.SubType = SubType; -// if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type -// pHdr80211->FC.Type = BTYPE_CNTL; - pHdr80211->FC.ToDs = ToDs; - COPY_MAC_ADDR(pHdr80211->Addr1, pDA); -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); -#endif // CONFIG_STA_SUPPORT // - COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); -} - -// =========================================================================================== -// mem_mgmt.c -// =========================================================================================== - -/*!*************************************************************************** - * This routine build an outgoing frame, and fill all information specified - * in argument list to the frame body. The actual frame size is the summation - * of all arguments. - * input params: - * Buffer - pointer to a pre-allocated memory segment - * args - a list of pairs. - * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this - * function will FAIL!!! - * return: - * Size of the buffer - * usage: - * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS); - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - ****************************************************************************/ -ULONG MakeOutgoingFrame( - OUT UCHAR *Buffer, - OUT ULONG *FrameLen, ...) -{ - UCHAR *p; - int leng; - ULONG TotLeng; - va_list Args; - - // calculates the total length - TotLeng = 0; - va_start(Args, FrameLen); - do - { - leng = va_arg(Args, int); - if (leng == END_OF_ARGS) - { - break; - } - p = va_arg(Args, PVOID); - NdisMoveMemory(&Buffer[TotLeng], p, leng); - TotLeng = TotLeng + leng; - } while(TRUE); - - va_end(Args); /* clean up */ - *FrameLen = TotLeng; - return TotLeng; -} - -// =========================================================================================== -// mlme_queue.c -// =========================================================================================== - -/*! \brief Initialize The MLME Queue, used by MLME Functions - * \param *Queue The MLME Queue - * \return Always Return NDIS_STATE_SUCCESS in this implementation - * \pre - * \post - * \note Because this is done only once (at the init stage), no need to be locked - - IRQL = PASSIVE_LEVEL - - */ -NDIS_STATUS MlmeQueueInit( - IN MLME_QUEUE *Queue) -{ - INT i; - - NdisAllocateSpinLock(&Queue->Lock); - - Queue->Num = 0; - Queue->Head = 0; - Queue->Tail = 0; - - for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) - { - Queue->Entry[i].Occupied = FALSE; - Queue->Entry[i].MsgLen = 0; - NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE); - } - - return NDIS_STATUS_SUCCESS; -} - -/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread - * \param *Queue The MLME Queue - * \param Machine The State Machine Id - * \param MsgType The Message Type - * \param MsgLen The Message length - * \param *Msg The message pointer - * \return TRUE if enqueue is successful, FALSE if the queue is full - * \pre - * \post - * \note The message has to be initialized - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - */ -BOOLEAN MlmeEnqueue( - IN PRTMP_ADAPTER pAd, - IN ULONG Machine, - IN ULONG MsgType, - IN ULONG MsgLen, - IN VOID *Msg) -{ - INT Tail; - MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return FALSE; - - // First check the size, it MUST not exceed the mlme queue size - if (MsgLen > MGMT_DMA_BUFFER_SIZE) - { - DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen)); - return FALSE; - } - - if (MlmeQueueFull(Queue)) - { - return FALSE; - } - - NdisAcquireSpinLock(&(Queue->Lock)); - Tail = Queue->Tail; - Queue->Tail++; - Queue->Num++; - if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) - { - Queue->Tail = 0; - } - - Queue->Entry[Tail].Wcid = RESERVED_WCID; - Queue->Entry[Tail].Occupied = TRUE; - Queue->Entry[Tail].Machine = Machine; - Queue->Entry[Tail].MsgType = MsgType; - Queue->Entry[Tail].MsgLen = MsgLen; - - if (Msg != NULL) - { - NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); - } - - NdisReleaseSpinLock(&(Queue->Lock)); - return TRUE; -} - -/*! \brief This function is used when Recv gets a MLME message - * \param *Queue The MLME Queue - * \param TimeStampHigh The upper 32 bit of timestamp - * \param TimeStampLow The lower 32 bit of timestamp - * \param Rssi The receiving RSSI strength - * \param MsgLen The length of the message - * \param *Msg The message pointer - * \return TRUE if everything ok, FALSE otherwise (like Queue Full) - * \pre - * \post - - IRQL = DISPATCH_LEVEL - - */ -BOOLEAN MlmeEnqueueForRecv( - IN PRTMP_ADAPTER pAd, - IN ULONG Wcid, - IN ULONG TimeStampHigh, - IN ULONG TimeStampLow, - IN UCHAR Rssi0, - IN UCHAR Rssi1, - IN UCHAR Rssi2, - IN ULONG MsgLen, - IN VOID *Msg, - IN UCHAR Signal) -{ - INT Tail, Machine; - PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; - INT MsgType; - MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; - -#ifdef RALINK_ATE - /* Nothing to do in ATE mode */ - if(ATE_ON(pAd)) - return FALSE; -#endif // RALINK_ATE // - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - { - DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n")); - return FALSE; - } - - // First check the size, it MUST not exceed the mlme queue size - if (MsgLen > MGMT_DMA_BUFFER_SIZE) - { - DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); - return FALSE; - } - - if (MlmeQueueFull(Queue)) - { - return FALSE; - } - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) - { - DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType)); - return FALSE; - } - } -#endif // CONFIG_STA_SUPPORT // - - // OK, we got all the informations, it is time to put things into queue - NdisAcquireSpinLock(&(Queue->Lock)); - Tail = Queue->Tail; - Queue->Tail++; - Queue->Num++; - if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) - { - Queue->Tail = 0; - } - Queue->Entry[Tail].Occupied = TRUE; - Queue->Entry[Tail].Machine = Machine; - Queue->Entry[Tail].MsgType = MsgType; - Queue->Entry[Tail].MsgLen = MsgLen; - Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow; - Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh; - Queue->Entry[Tail].Rssi0 = Rssi0; - Queue->Entry[Tail].Rssi1 = Rssi1; - Queue->Entry[Tail].Rssi2 = Rssi2; - Queue->Entry[Tail].Signal = Signal; - Queue->Entry[Tail].Wcid = (UCHAR)Wcid; - - Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel; - - if (Msg != NULL) - { - NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); - } - - NdisReleaseSpinLock(&(Queue->Lock)); - - RTMP_MLME_HANDLER(pAd); - - return TRUE; -} - - -/*! \brief Dequeue a message from the MLME Queue - * \param *Queue The MLME Queue - * \param *Elem The message dequeued from MLME Queue - * \return TRUE if the Elem contains something, FALSE otherwise - * \pre - * \post - - IRQL = DISPATCH_LEVEL - - */ -BOOLEAN MlmeDequeue( - IN MLME_QUEUE *Queue, - OUT MLME_QUEUE_ELEM **Elem) -{ - NdisAcquireSpinLock(&(Queue->Lock)); - *Elem = &(Queue->Entry[Queue->Head]); - Queue->Num--; - Queue->Head++; - if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) - { - Queue->Head = 0; - } - NdisReleaseSpinLock(&(Queue->Lock)); - return TRUE; -} - -// IRQL = DISPATCH_LEVEL -VOID MlmeRestartStateMachine( - IN PRTMP_ADAPTER pAd) -{ -#ifdef RTMP_MAC_PCI - MLME_QUEUE_ELEM *Elem = NULL; -#endif // RTMP_MAC_PCI // -#ifdef CONFIG_STA_SUPPORT - BOOLEAN Cancelled; -#endif // CONFIG_STA_SUPPORT // - - DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n")); - -#ifdef RTMP_MAC_PCI - NdisAcquireSpinLock(&pAd->Mlme.TaskLock); - if(pAd->Mlme.bRunning) - { - NdisReleaseSpinLock(&pAd->Mlme.TaskLock); - return; - } - else - { - pAd->Mlme.bRunning = TRUE; - } - NdisReleaseSpinLock(&pAd->Mlme.TaskLock); - - // Remove all Mlme queues elements - while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) - { - //From message type, determine which state machine I should drive - if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) - { - // free MLME element - Elem->Occupied = FALSE; - Elem->MsgLen = 0; - - } - else { - DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n")); - } - } -#endif // RTMP_MAC_PCI // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { -#ifdef QOS_DLS_SUPPORT - UCHAR i; -#endif // QOS_DLS_SUPPORT // - // Cancel all timer events - // Be careful to cancel new added timer - RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); - RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); - -#ifdef QOS_DLS_SUPPORT - for (i=0; iStaCfg.DLSEntry[i].Timer, &Cancelled); - } -#endif // QOS_DLS_SUPPORT // - } -#endif // CONFIG_STA_SUPPORT // - - // Change back to original channel in case of doing scan - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - - // Resume MSDU which is turned off durning scan - RTMPResumeMsduTransmission(pAd); - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // Set all state machines back IDLE - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE; - pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; - pAd->Mlme.ActMachine.CurrState = ACT_IDLE; -#ifdef QOS_DLS_SUPPORT - pAd->Mlme.DlsMachine.CurrState = DLS_IDLE; -#endif // QOS_DLS_SUPPORT // - } -#endif // CONFIG_STA_SUPPORT // - -#ifdef RTMP_MAC_PCI - // Remove running state - NdisAcquireSpinLock(&pAd->Mlme.TaskLock); - pAd->Mlme.bRunning = FALSE; - NdisReleaseSpinLock(&pAd->Mlme.TaskLock); -#endif // RTMP_MAC_PCI // -} - -/*! \brief test if the MLME Queue is empty - * \param *Queue The MLME Queue - * \return TRUE if the Queue is empty, FALSE otherwise - * \pre - * \post - - IRQL = DISPATCH_LEVEL - - */ -BOOLEAN MlmeQueueEmpty( - IN MLME_QUEUE *Queue) -{ - BOOLEAN Ans; - - NdisAcquireSpinLock(&(Queue->Lock)); - Ans = (Queue->Num == 0); - NdisReleaseSpinLock(&(Queue->Lock)); - - return Ans; -} - -/*! \brief test if the MLME Queue is full - * \param *Queue The MLME Queue - * \return TRUE if the Queue is empty, FALSE otherwise - * \pre - * \post - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - */ -BOOLEAN MlmeQueueFull( - IN MLME_QUEUE *Queue) -{ - BOOLEAN Ans; - - NdisAcquireSpinLock(&(Queue->Lock)); - Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied); - NdisReleaseSpinLock(&(Queue->Lock)); - - return Ans; -} - -/*! \brief The destructor of MLME Queue - * \param - * \return - * \pre - * \post - * \note Clear Mlme Queue, Set Queue->Num to Zero. - - IRQL = PASSIVE_LEVEL - - */ -VOID MlmeQueueDestroy( - IN MLME_QUEUE *pQueue) -{ - NdisAcquireSpinLock(&(pQueue->Lock)); - pQueue->Num = 0; - pQueue->Head = 0; - pQueue->Tail = 0; - NdisReleaseSpinLock(&(pQueue->Lock)); - NdisFreeSpinLock(&(pQueue->Lock)); -} - - -/*! \brief To substitute the message type if the message is coming from external - * \param pFrame The frame received - * \param *Machine The state machine - * \param *MsgType the message type for the state machine - * \return TRUE if the substitution is successful, FALSE otherwise - * \pre - * \post - - IRQL = DISPATCH_LEVEL - - */ -#ifdef CONFIG_STA_SUPPORT -BOOLEAN MsgTypeSubst( - IN PRTMP_ADAPTER pAd, - IN PFRAME_802_11 pFrame, - OUT INT *Machine, - OUT INT *MsgType) -{ - USHORT Seq, Alg; - UCHAR EAPType; - PUCHAR pData; - - // Pointer to start of data frames including SNAP header - pData = (PUCHAR) pFrame + LENGTH_802_11; - - // The only data type will pass to this function is EAPOL frame - if (pFrame->Hdr.FC.Type == BTYPE_DATA) - { - { - *Machine = WPA_STATE_MACHINE; - EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1); - return (WpaMsgTypeSubst(EAPType, (INT *) MsgType)); - } - } - - switch (pFrame->Hdr.FC.SubType) - { - case SUBTYPE_ASSOC_REQ: - *Machine = ASSOC_STATE_MACHINE; - *MsgType = MT2_PEER_ASSOC_REQ; - break; - case SUBTYPE_ASSOC_RSP: - *Machine = ASSOC_STATE_MACHINE; - *MsgType = MT2_PEER_ASSOC_RSP; - break; - case SUBTYPE_REASSOC_REQ: - *Machine = ASSOC_STATE_MACHINE; - *MsgType = MT2_PEER_REASSOC_REQ; - break; - case SUBTYPE_REASSOC_RSP: - *Machine = ASSOC_STATE_MACHINE; - *MsgType = MT2_PEER_REASSOC_RSP; - break; - case SUBTYPE_PROBE_REQ: - *Machine = SYNC_STATE_MACHINE; - *MsgType = MT2_PEER_PROBE_REQ; - break; - case SUBTYPE_PROBE_RSP: - *Machine = SYNC_STATE_MACHINE; - *MsgType = MT2_PEER_PROBE_RSP; - break; - case SUBTYPE_BEACON: - *Machine = SYNC_STATE_MACHINE; - *MsgType = MT2_PEER_BEACON; - break; - case SUBTYPE_ATIM: - *Machine = SYNC_STATE_MACHINE; - *MsgType = MT2_PEER_ATIM; - break; - case SUBTYPE_DISASSOC: - *Machine = ASSOC_STATE_MACHINE; - *MsgType = MT2_PEER_DISASSOC_REQ; - break; - case SUBTYPE_AUTH: - // get the sequence number from payload 24 Mac Header + 2 bytes algorithm - NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT)); - NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(USHORT)); - if (Seq == 1 || Seq == 3) - { - *Machine = AUTH_RSP_STATE_MACHINE; - *MsgType = MT2_PEER_AUTH_ODD; - } - else if (Seq == 2 || Seq == 4) - { - if (Alg == AUTH_MODE_OPEN || Alg == AUTH_MODE_KEY) - { - *Machine = AUTH_STATE_MACHINE; - *MsgType = MT2_PEER_AUTH_EVEN; - } - } - else - { - return FALSE; - } - break; - case SUBTYPE_DEAUTH: - *Machine = AUTH_RSP_STATE_MACHINE; - *MsgType = MT2_PEER_DEAUTH; - break; - case SUBTYPE_ACTION: - *Machine = ACTION_STATE_MACHINE; - // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support - if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG) - { - *MsgType = MT2_ACT_INVALID; - } - else - { - *MsgType = (pFrame->Octet[0]&0x7F); - } - break; - default: - return FALSE; - break; - } - - return TRUE; -} -#endif // CONFIG_STA_SUPPORT // - -// =========================================================================================== -// state_machine.c -// =========================================================================================== - -/*! \brief Initialize the state machine. - * \param *S pointer to the state machine - * \param Trans State machine transition function - * \param StNr number of states - * \param MsgNr number of messages - * \param DefFunc default function, when there is invalid state/message combination - * \param InitState initial state of the state machine - * \param Base StateMachine base, internal use only - * \pre p_sm should be a legal pointer - * \post - - IRQL = PASSIVE_LEVEL - - */ -VOID StateMachineInit( - IN STATE_MACHINE *S, - IN STATE_MACHINE_FUNC Trans[], - IN ULONG StNr, - IN ULONG MsgNr, - IN STATE_MACHINE_FUNC DefFunc, - IN ULONG InitState, - IN ULONG Base) -{ - ULONG i, j; - - // set number of states and messages - S->NrState = StNr; - S->NrMsg = MsgNr; - S->Base = Base; - - S->TransFunc = Trans; - - // init all state transition to default function - for (i = 0; i < StNr; i++) - { - for (j = 0; j < MsgNr; j++) - { - S->TransFunc[i * MsgNr + j] = DefFunc; - } - } - - // set the starting state - S->CurrState = InitState; -} - -/*! \brief This function fills in the function pointer into the cell in the state machine - * \param *S pointer to the state machine - * \param St state - * \param Msg incoming message - * \param f the function to be executed when (state, message) combination occurs at the state machine - * \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state - * \post - - IRQL = PASSIVE_LEVEL - - */ -VOID StateMachineSetAction( - IN STATE_MACHINE *S, - IN ULONG St, - IN ULONG Msg, - IN STATE_MACHINE_FUNC Func) -{ - ULONG MsgIdx; - - MsgIdx = Msg - S->Base; - - if (St < S->NrState && MsgIdx < S->NrMsg) - { - // boundary checking before setting the action - S->TransFunc[St * S->NrMsg + MsgIdx] = Func; - } -} - -/*! \brief This function does the state transition - * \param *Adapter the NIC adapter pointer - * \param *S the state machine - * \param *Elem the message to be executed - * \return None - - IRQL = DISPATCH_LEVEL - - */ -VOID StateMachinePerformAction( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - IN MLME_QUEUE_ELEM *Elem) -{ - (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem); -} - -/* - ========================================================================== - Description: - The drop function, when machine executes this, the message is simply - ignored. This function does nothing, the message is freed in - StateMachinePerformAction() - ========================================================================== - */ -VOID Drop( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ -} - -// =========================================================================================== -// lfsr.c -// =========================================================================================== - -/* - ========================================================================== - Description: - - IRQL = PASSIVE_LEVEL - - ========================================================================== - */ -VOID LfsrInit( - IN PRTMP_ADAPTER pAd, - IN ULONG Seed) -{ - if (Seed == 0) - pAd->Mlme.ShiftReg = 1; - else - pAd->Mlme.ShiftReg = Seed; -} - -/* - ========================================================================== - Description: - ========================================================================== - */ -UCHAR RandomByte( - IN PRTMP_ADAPTER pAd) -{ - ULONG i; - UCHAR R, Result; - - R = 0; - - if (pAd->Mlme.ShiftReg == 0) - NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg); - - for (i = 0; i < 8; i++) - { - if (pAd->Mlme.ShiftReg & 0x00000001) - { - pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000; - Result = 1; - } - else - { - pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1; - Result = 0; - } - R = (R << 1) | Result; - } - - return R; -} - - -/* - ======================================================================== - - Routine Description: - Verify the support rate for different PHY type - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - ======================================================================== -*/ -VOID RTMPCheckRates( - IN PRTMP_ADAPTER pAd, - IN OUT UCHAR SupRate[], - IN OUT UCHAR *SupRateLen) -{ - UCHAR RateIdx, i, j; - UCHAR NewRate[12], NewRateLen; - - NewRateLen = 0; - - if (pAd->CommonCfg.PhyMode == PHY_11B) - RateIdx = 4; - else - RateIdx = 12; - - // Check for support rates exclude basic rate bit - for (i = 0; i < *SupRateLen; i++) - for (j = 0; j < RateIdx; j++) - if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) - NewRate[NewRateLen++] = SupRate[i]; - - *SupRateLen = NewRateLen; - NdisMoveMemory(SupRate, NewRate, NewRateLen); -} - -#ifdef CONFIG_STA_SUPPORT -#ifdef DOT11_N_SUPPORT -BOOLEAN RTMPCheckChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR CentralChannel, - IN UCHAR Channel) -{ - UCHAR k; - UCHAR UpperChannel = 0, LowerChannel = 0; - UCHAR NoEffectChannelinList = 0; - - // Find upper and lower channel according to 40MHz current operation. - if (CentralChannel < Channel) - { - UpperChannel = Channel; - if (CentralChannel > 2) - LowerChannel = CentralChannel - 2; - else - return FALSE; - } - else if (CentralChannel > Channel) - { - UpperChannel = CentralChannel + 2; - LowerChannel = Channel; - } - - for (k = 0;k < pAd->ChannelListNum;k++) - { - if (pAd->ChannelList[k].Channel == UpperChannel) - { - NoEffectChannelinList ++; - } - if (pAd->ChannelList[k].Channel == LowerChannel) - { - NoEffectChannelinList ++; - } - } - - DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList)); - if (NoEffectChannelinList == 2) - return TRUE; - else - return FALSE; -} - -/* - ======================================================================== - - Routine Description: - Verify the support rate for HT phy type - - Arguments: - pAd Pointer to our adapter - - Return Value: - FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode) - - IRQL = PASSIVE_LEVEL - - ======================================================================== -*/ -BOOLEAN RTMPCheckHt( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN HT_CAPABILITY_IE *pHtCapability, - IN ADD_HT_INFO_IE *pAddHtInfo) -{ - if (Wcid >= MAX_LEN_OF_MAC_TABLE) - return FALSE; - - // If use AMSDU, set flag. - if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable) - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED); - // Save Peer Capability - if (pHtCapability->HtCapInfo.ShortGIfor20) - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE); - if (pHtCapability->HtCapInfo.ShortGIfor40) - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE); - if (pHtCapability->HtCapInfo.TxSTBC) - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE); - if (pHtCapability->HtCapInfo.RxSTBC) - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE); - if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) - { - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE); - } - - if (Wcid < MAX_LEN_OF_MAC_TABLE) - { - pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity; - } - - // Will check ChannelWidth for MCSSet[4] below - pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1; - switch (pAd->CommonCfg.RxStream) - { - case 1: - pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; - pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00; - pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; - pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; - break; - case 2: - pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; - pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; - pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; - pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; - break; - case 3: - pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; - pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; - pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff; - pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; - break; - } - - pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth; - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n", - pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth, - pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode)); - - pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF; - - // Send Assoc Req with my HT capability. - pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize; - pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs; - pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20); - pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40); - pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC); - pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC); - pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor; - pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity; - pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; - pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; - if (pAd->CommonCfg.bRdg) - { - pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport; - pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1; - } - - if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20) - pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32 - - COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability); - return TRUE; -} -#endif // DOT11_N_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - -/* - ======================================================================== - - Routine Description: - Verify the support rate for different PHY type - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - ======================================================================== -*/ -VOID RTMPUpdateMlmeRate( - IN PRTMP_ADAPTER pAd) -{ - UCHAR MinimumRate; - UCHAR ProperMlmeRate; //= RATE_54; - UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 - BOOLEAN bMatch = FALSE; - - switch (pAd->CommonCfg.PhyMode) - { - case PHY_11B: - ProperMlmeRate = RATE_11; - MinimumRate = RATE_1; - break; - case PHY_11BG_MIXED: -#ifdef DOT11_N_SUPPORT - case PHY_11ABGN_MIXED: - case PHY_11BGN_MIXED: -#endif // DOT11_N_SUPPORT // - if ((pAd->MlmeAux.SupRateLen == 4) && - (pAd->MlmeAux.ExtRateLen == 0)) - // B only AP - ProperMlmeRate = RATE_11; - else - ProperMlmeRate = RATE_24; - - if (pAd->MlmeAux.Channel <= 14) - MinimumRate = RATE_1; - else - MinimumRate = RATE_6; - break; - case PHY_11A: -#ifdef DOT11_N_SUPPORT - case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n - case PHY_11GN_MIXED: - case PHY_11AGN_MIXED: - case PHY_11AN_MIXED: - case PHY_11N_5G: -#endif // DOT11_N_SUPPORT // - ProperMlmeRate = RATE_24; - MinimumRate = RATE_6; - break; - case PHY_11ABG_MIXED: - ProperMlmeRate = RATE_24; - if (pAd->MlmeAux.Channel <= 14) - MinimumRate = RATE_1; - else - MinimumRate = RATE_6; - break; - default: // error - ProperMlmeRate = RATE_1; - MinimumRate = RATE_1; - break; - } - - for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) - { - for (j = 0; j < RateIdx; j++) - { - if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) - { - if (j == ProperMlmeRate) - { - bMatch = TRUE; - break; - } - } - } - - if (bMatch) - break; - } - - if (bMatch == FALSE) - { - for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) - { - for (j = 0; j < RateIdx; j++) - { - if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j]) - { - if (j == ProperMlmeRate) - { - bMatch = TRUE; - break; - } - } - } - - if (bMatch) - break; - } - } - - if (bMatch == FALSE) - { - ProperMlmeRate = MinimumRate; - } - - pAd->CommonCfg.MlmeRate = MinimumRate; - pAd->CommonCfg.RtsRate = ProperMlmeRate; - if (pAd->CommonCfg.MlmeRate >= RATE_6) - { - pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; - pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; - pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM; - pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; - } - else - { - pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; - pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate; - pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK; - pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate; - } - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word)); -} - -CHAR RTMPMaxRssi( - IN PRTMP_ADAPTER pAd, - IN CHAR Rssi0, - IN CHAR Rssi1, - IN CHAR Rssi2) -{ - CHAR larger = -127; - - if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) - { - larger = Rssi0; - } - - if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) - { - larger = max(Rssi0, Rssi1); - } - - if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) - { - larger = max(larger, Rssi2); - } - - if (larger == -127) - larger = 0; - - return larger; -} - - -/* - ======================================================================== - Routine Description: - Periodic evaluate antenna link status - - Arguments: - pAd - Adapter pointer - - Return Value: - None - - ======================================================================== -*/ -VOID AsicEvaluateRxAnt( - IN PRTMP_ADAPTER pAd) -{ -#ifdef CONFIG_STA_SUPPORT - UCHAR BBPR3 = 0; -#endif // CONFIG_STA_SUPPORT // - -#ifdef RALINK_ATE - if (ATE_ON(pAd)) - return; -#endif // RALINK_ATE // - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_RADIO_OFF | - fRTMP_ADAPTER_NIC_NOT_EXIST | - fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) || - OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) -#ifdef RT3090 - || (pAd->bPCIclkOff == TRUE) -#endif // RT3090 // -#ifdef ANT_DIVERSITY_SUPPORT - || (pAd->EepromAccess) -#endif // ANT_DIVERSITY_SUPPORT // - ) - return; - -#ifdef ANT_DIVERSITY_SUPPORT - if ((pAd->NicConfig2.field.AntDiversity) && (pAd->CommonCfg.bRxAntDiversity == ANT_DIVERSITY_ENABLE)) - { - // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove - // one is antenna diversity:there is only one antenna can rx and tx - // the other is failed antenna remove:two physical antenna can rx and tx - DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n", - pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt)); - - AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt); - - pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt - pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE; - pAd->RxAnt.RcvPktNumWhenEvaluate = 0; - - // a one-shot timer to end the evalution - // dynamic adjust antenna evaluation period according to the traffic - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100); - else - RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300); - } - else -#endif // ANT_DIVERSITY_SUPPORT // - { -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - - if (pAd->StaCfg.Psm == PWR_SAVE) - return; - - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); - BBPR3 &= (~0x18); - if(pAd->Antenna.field.RxPath == 3) - { - BBPR3 |= (0x10); - } - else if(pAd->Antenna.field.RxPath == 2) - { - BBPR3 |= (0x8); - } - else if(pAd->Antenna.field.RxPath == 1) - { - BBPR3 |= (0x0); - } - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); -#ifdef RTMP_MAC_PCI - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - pAd->StaCfg.BBPR3 = BBPR3; -#endif // RTMP_MAC_PCI // - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) - ) - { - ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + - pAd->RalinkCounters.OneSecTxRetryOkCount + - pAd->RalinkCounters.OneSecTxFailCount; - - // dynamic adjust antenna evaluation period according to the traffic - if (TxTotalCnt > 50) - { - RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20); - pAd->Mlme.bLowThroughput = FALSE; - } - else - { - RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300); - pAd->Mlme.bLowThroughput = TRUE; - } - } - } -#endif // CONFIG_STA_SUPPORT // - } -} - -/* - ======================================================================== - Routine Description: - After evaluation, check antenna link status - - Arguments: - pAd - Adapter pointer - - Return Value: - None - - ======================================================================== -*/ -VOID AsicRxAntEvalTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; - BOOLEAN bSwapAnt = FALSE; -#ifdef CONFIG_STA_SUPPORT - UCHAR BBPR3 = 0; - CHAR larger = -127, rssi0, rssi1, rssi2; -#endif // CONFIG_STA_SUPPORT // - -#ifdef RALINK_ATE - if (ATE_ON(pAd)) - return; -#endif // RALINK_ATE // - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_RADIO_OFF | - fRTMP_ADAPTER_NIC_NOT_EXIST) || - OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) -#ifdef RT3090 - || (pAd->bPCIclkOff == TRUE) -#endif // RT3090 // -#ifdef ANT_DIVERSITY_SUPPORT - || (pAd->EepromAccess) -#endif // ANT_DIVERSITY_SUPPORT // - ) - return; - -#ifdef ANT_DIVERSITY_SUPPORT - if ((pAd->NicConfig2.field.AntDiversity) && (pAd->CommonCfg.bRxAntDiversity == ANT_DIVERSITY_ENABLE)) - { -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt])) - bSwapAnt = TRUE; -#endif // CONFIG_STA_SUPPORT // - if (bSwapAnt == TRUE) - { - UCHAR temp; - - // - // select PrimaryRxAntPair - // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair. - // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt - // - temp = pAd->RxAnt.Pair1PrimaryRxAnt; - pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt; - pAd->RxAnt.Pair1SecondaryRxAnt = temp; - -#ifdef CONFIG_STA_SUPPORT - pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3); -#endif // CONFIG_STA_SUPPORT // -// pAd->RxAnt.EvaluateStableCnt = 0; - } - else - { - // if the evaluated antenna is not better than original, switch back to original antenna - AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); - pAd->RxAnt.EvaluateStableCnt ++; - } - - pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt - -#ifdef CONFIG_STA_SUPPORT - DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n", - pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate)); -#endif // CONFIG_STA_SUPPORT // - } - else -#endif // ANT_DIVERSITY_SUPPORT // - { -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (pAd->StaCfg.Psm == PWR_SAVE) - return; - - - // if the traffic is low, use average rssi as the criteria - if (pAd->Mlme.bLowThroughput == TRUE) - { - rssi0 = pAd->StaCfg.RssiSample.LastRssi0; - rssi1 = pAd->StaCfg.RssiSample.LastRssi1; - rssi2 = pAd->StaCfg.RssiSample.LastRssi2; - } - else - { - rssi0 = pAd->StaCfg.RssiSample.AvgRssi0; - rssi1 = pAd->StaCfg.RssiSample.AvgRssi1; - rssi2 = pAd->StaCfg.RssiSample.AvgRssi2; - } - - if(pAd->Antenna.field.RxPath == 3) - { - larger = max(rssi0, rssi1); - - if (larger > (rssi2 + 20)) - pAd->Mlme.RealRxPath = 2; - else - pAd->Mlme.RealRxPath = 3; - } - else if(pAd->Antenna.field.RxPath == 2) - { - if (rssi0 > (rssi1 + 20)) - pAd->Mlme.RealRxPath = 1; - else - pAd->Mlme.RealRxPath = 2; - } - - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); - BBPR3 &= (~0x18); - if(pAd->Mlme.RealRxPath == 3) - { - BBPR3 |= (0x10); - } - else if(pAd->Mlme.RealRxPath == 2) - { - BBPR3 |= (0x8); - } - else if(pAd->Mlme.RealRxPath == 1) - { - BBPR3 |= (0x0); - } - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); -#ifdef RTMP_MAC_PCI - pAd->StaCfg.BBPR3 = BBPR3; -#endif // RTMP_MAC_PCI // - } -#endif // CONFIG_STA_SUPPORT // - } -} - - -VOID APSDPeriodicExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; - - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - return; - - pAd->CommonCfg.TriggerTimerCount++; - -// Driver should not send trigger frame, it should be send by application layer -/* - if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable - && (pAd->CommonCfg.bNeedSendTriggerFrame || - (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO)))) - { - DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n")); - RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); - pAd->CommonCfg.bNeedSendTriggerFrame = FALSE; - pAd->CommonCfg.TriggerTimerCount = 0; - pAd->CommonCfg.bInServicePeriod = TRUE; - }*/ -} - -/* - ======================================================================== - Routine Description: - Set/reset MAC registers according to bPiggyBack parameter - - Arguments: - pAd - Adapter pointer - bPiggyBack - Enable / Disable Piggy-Back - - Return Value: - None - - ======================================================================== -*/ -VOID RTMPSetPiggyBack( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bPiggyBack) -{ - TX_LINK_CFG_STRUC TxLinkCfg; - - RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); - - TxLinkCfg.field.TxCFAckEn = bPiggyBack; - RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); -} - -/* - ======================================================================== - Routine Description: - check if this entry need to switch rate automatically - - Arguments: - pAd - pEntry - - Return Value: - TURE - FALSE - - ======================================================================== -*/ -BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry) -{ - BOOLEAN result = TRUE; - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // only associated STA counts - if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC)) - { - result = pAd->StaCfg.bAutoTxRateSwitch; - } - else - result = FALSE; - -#ifdef QOS_DLS_SUPPORT - if (pEntry && (pEntry->ValidAsDls)) - result = pAd->StaCfg.bAutoTxRateSwitch; -#endif // QOS_DLS_SUPPORT // - } -#endif // CONFIG_STA_SUPPORT // - - - - return result; -} - - -BOOLEAN RTMPAutoRateSwitchCheck( - IN PRTMP_ADAPTER pAd) -{ - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (pAd->StaCfg.bAutoTxRateSwitch) - return TRUE; - } -#endif // CONFIG_STA_SUPPORT // - return FALSE; -} - - -/* - ======================================================================== - Routine Description: - check if this entry need to fix tx legacy rate - - Arguments: - pAd - pEntry - - Return Value: - TURE - FALSE - - ======================================================================== -*/ -UCHAR RTMPStaFixedTxMode( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry) -{ - UCHAR tx_mode = FIXED_TXMODE_HT; - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode; - } -#endif // CONFIG_STA_SUPPORT // - - return tx_mode; -} - -/* - ======================================================================== - Routine Description: - Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified. - - Arguments: - pAd - pEntry - - Return Value: - TURE - FALSE - - ======================================================================== -*/ -VOID RTMPUpdateLegacyTxSetting( - UCHAR fixed_tx_mode, - PMAC_TABLE_ENTRY pEntry) -{ - HTTRANSMIT_SETTING TransmitSetting; - - if (fixed_tx_mode == FIXED_TXMODE_HT) - return; - - TransmitSetting.word = 0; - - TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE; - TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS; - - if (fixed_tx_mode == FIXED_TXMODE_CCK) - { - TransmitSetting.field.MODE = MODE_CCK; - // CCK mode allow MCS 0~3 - if (TransmitSetting.field.MCS > MCS_3) - TransmitSetting.field.MCS = MCS_3; - } - else - { - TransmitSetting.field.MODE = MODE_OFDM; - // OFDM mode allow MCS 0~7 - if (TransmitSetting.field.MCS > MCS_7) - TransmitSetting.field.MCS = MCS_7; - } - - if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) - { - pEntry->HTPhyMode.word = TransmitSetting.word; - DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n", - pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS)); - } -} - -#ifdef CONFIG_STA_SUPPORT -/* - ========================================================================== - Description: - dynamic tune BBP R66 to find a balance between sensibility and - noise isolation - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AsicStaBbpTuning( - IN PRTMP_ADAPTER pAd) -{ - UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30; - CHAR Rssi; - - // 2860C did not support Fase CCA, therefore can't tune - if (pAd->MACVersion == 0x28600100) - return; - - // - // work as a STA - // - if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING - return; - - if ((pAd->OpMode == OPMODE_STA) - && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) - ) - && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) -#ifdef RTMP_MAC_PCI - && (pAd->bPCIclkOff == FALSE) -#endif // RTMP_MAC_PCI // - ) - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value); - R66 = OrigR66Value; - - if (pAd->Antenna.field.RxPath > 1) - Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1; - else - Rssi = pAd->StaCfg.RssiSample.AvgRssi0; - - if (pAd->LatchRfRegs.Channel <= 14) - { //BG band -#ifdef RT30xx - // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control - // Otherwise, it will have some throughput side effect when low RSSI - - if (IS_RT3070(pAd)||IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) - { - if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) - { - R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20; - if (OrigR66Value != R66) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - } - else - { - R66 = 0x1C + 2*GET_LNA_GAIN(pAd); - if (OrigR66Value != R66) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - } - } - else -#endif // RT30xx // - { - if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) - { - R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10; - if (OrigR66Value != R66) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - } - else - { - R66 = 0x2E + GET_LNA_GAIN(pAd); - if (OrigR66Value != R66) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - } - } - } - else - { //A band - if (pAd->CommonCfg.BBPCurrentBW == BW_20) - { - if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) - { - R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10; - if (OrigR66Value != R66) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - } - else - { - R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3; - if (OrigR66Value != R66) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - } - } - else - { - if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) - { - R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10; - if (OrigR66Value != R66) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - } - else - { - R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3; - if (OrigR66Value != R66) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - } - } - } - - - } -} -#endif // CONFIG_STA_SUPPORT // - -VOID RTMPSetAGCInitValue( - IN PRTMP_ADAPTER pAd, - IN UCHAR BandWidth) -{ - UCHAR R66 = 0x30; - - if (pAd->LatchRfRegs.Channel <= 14) - { // BG band -#ifdef RT30xx - /* Gary was verified Amazon AP and find that RT307x has BBP_R66 invalid default value */ - - if (IS_RT3070(pAd)||IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) - { - R66 = 0x1C + 2*GET_LNA_GAIN(pAd); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - else -#endif // RT30xx // - { - R66 = 0x2E + GET_LNA_GAIN(pAd); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - } - else - { //A band - { - if (BandWidth == BW_20) - { - R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } -#ifdef DOT11_N_SUPPORT - else - { - R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } -#endif // DOT11_N_SUPPORT // - } - } - -} diff --git a/drivers/staging/rt3090/common/mlme_ex.c b/drivers/staging/rt3090/common/mlme_ex.c deleted file mode 100644 index d7fb7f58daeef4aaf11c2e937682d8c439e12722..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/mlme_ex.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - mlme_ex.c - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Fonchi 2007-06-25 Extend original mlme APIs to support multi-entries -*/ - -#include "../rt_config.h" -#include "../mlme_ex_def.h" -//#include - - -// =========================================================================================== -// state_machine -// =========================================================================================== - -/*! \brief Initialize the state machine. - * \param *S pointer to the state machine - * \param Trans State machine transition function - * \param StNr number of states - * \param MsgNr number of messages - * \param DefFunc default function, when there is invalid state/message combination - * \param InitState initial state of the state machine - * \param Base StateMachine base, internal use only - * \pre p_sm should be a legal pointer - * \post - */ -VOID StateMachineInitEx( - IN STATE_MACHINE_EX *S, - IN STATE_MACHINE_FUNC_EX Trans[], - IN ULONG StNr, - IN ULONG MsgNr, - IN STATE_MACHINE_FUNC_EX DefFunc, - IN ULONG InitState, - IN ULONG Base) -{ - ULONG i, j; - - // set number of states and messages - S->NrState = StNr; - S->NrMsg = MsgNr; - S->Base = Base; - - S->TransFunc = Trans; - - // init all state transition to default function - for (i = 0; i < StNr; i++) - { - for (j = 0; j < MsgNr; j++) - { - S->TransFunc[i * MsgNr + j] = DefFunc; - } - } - - // set the starting state - S->CurrState = InitState; - - return; -} - -/*! \brief This function fills in the function pointer into the cell in the state machine - * \param *S pointer to the state machine - * \param St state - * \param Msg incoming message - * \param f the function to be executed when (state, message) combination occurs at the state machine - * \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state - * \post - */ -VOID StateMachineSetActionEx( - IN STATE_MACHINE_EX *S, - IN ULONG St, - IN ULONG Msg, - IN STATE_MACHINE_FUNC_EX Func) -{ - ULONG MsgIdx; - - MsgIdx = Msg - S->Base; - - if (St < S->NrState && MsgIdx < S->NrMsg) - { - // boundary checking before setting the action - S->TransFunc[St * S->NrMsg + MsgIdx] = Func; - } - - return; -} - -/*! \brief This function does the state transition - * \param *Adapter the NIC adapter pointer - * \param *S the state machine - * \param *Elem the message to be executed - * \return None - */ -VOID StateMachinePerformActionEx( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE_EX *S, - IN MLME_QUEUE_ELEM *Elem, - USHORT Idx, - PULONG pCurrState) -{ - if (S->TransFunc[(*pCurrState) * S->NrMsg + Elem->MsgType - S->Base]) - (*(S->TransFunc[(*pCurrState) * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem, pCurrState, Idx); - - return; -} - -/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread - * \param *Queue The MLME Queue - * \param Machine The State Machine Id - * \param MsgType The Message Type - * \param MsgLen The Message length - * \param *Msg The message pointer - * \return TRUE if enqueue is successful, FALSE if the queue is full - * \pre - * \post - * \note The message has to be initialized - */ -BOOLEAN MlmeEnqueueEx( - IN PRTMP_ADAPTER pAd, - IN ULONG Machine, - IN ULONG MsgType, - IN ULONG MsgLen, - IN VOID *Msg, - IN USHORT Idx) -{ - INT Tail; - MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) - return FALSE; - - - // First check the size, it MUST not exceed the mlme queue size - if (MsgLen > MAX_LEN_OF_MLME_BUFFER) - { - DBGPRINT_ERR(("MlmeEnqueueEx: msg too large, size = %ld \n", MsgLen)); - return FALSE; - } - - if (MlmeQueueFull(Queue)) - { - - return FALSE; - } - - RTMP_SEM_LOCK(&Queue->Lock); - Tail = Queue->Tail; - Queue->Tail++; - Queue->Num++; - if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) - { - Queue->Tail = 0; - } - Queue->Entry[Tail].Occupied = TRUE; - Queue->Entry[Tail].Machine = Machine; - Queue->Entry[Tail].MsgType = MsgType; - Queue->Entry[Tail].MsgLen = MsgLen; - Queue->Entry[Tail].Idx = Idx; - if (Msg != NULL) - NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); - - RTMP_SEM_UNLOCK(&Queue->Lock); - - return TRUE; -} - -/* - ========================================================================== - Description: - The drop function, when machine executes this, the message is simply - ignored. This function does nothing, the message is freed in - StateMachinePerformAction() - ========================================================================== - */ -VOID DropEx( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem, - PULONG pCurrState, - USHORT Idx) -{ - return; -} diff --git a/drivers/staging/rt3090/common/netif_block.c b/drivers/staging/rt3090/common/netif_block.c deleted file mode 100644 index 2172957f4e412aa216c76d17445209b9b1062dfc..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/netif_block.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - */ -#ifdef BLOCK_NET_IF - -#include "../rt_config.h" -#include "../netif_block.h" - - -static NETIF_ENTRY freeNetIfEntryPool[FREE_NETIF_POOL_SIZE]; -static LIST_HEADER freeNetIfEntryList; - -void initblockQueueTab( - IN PRTMP_ADAPTER pAd) -{ - int i; - - initList(&freeNetIfEntryList); - for (i = 0; i < FREE_NETIF_POOL_SIZE; i++) - insertTailList(&freeNetIfEntryList, (PLIST_ENTRY)&freeNetIfEntryPool[i]); - - for (i=0; i < NUM_OF_TX_RING; i++) - initList(&pAd->blockQueueTab[i].NetIfList); - - return; -} - -BOOLEAN blockNetIf( - IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry, - IN PNET_DEV pNetDev) -{ - PNETIF_ENTRY pNetIfEntry = NULL; - - if ((pNetIfEntry = (PNETIF_ENTRY)removeHeadList(&freeNetIfEntryList)) != NULL) - { - RTMP_OS_NETDEV_STOP_QUEUE(pNetDev); - pNetIfEntry->pNetDev = pNetDev; - insertTailList(&pBlockQueueEntry->NetIfList, (PLIST_ENTRY)pNetIfEntry); - - pBlockQueueEntry->SwTxQueueBlockFlag = TRUE; - DBGPRINT(RT_DEBUG_TRACE, ("RTMP_OS_NETDEV_STOP_QUEUE(%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(pNetDev))); - } - else - return FALSE; - - return TRUE; -} - -VOID releaseNetIf( - IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry) -{ - PNETIF_ENTRY pNetIfEntry = NULL; - PLIST_HEADER pNetIfList = &pBlockQueueEntry->NetIfList; - - while((pNetIfEntry = (PNETIF_ENTRY)removeHeadList(pNetIfList)) != NULL) - { - PNET_DEV pNetDev = pNetIfEntry->pNetDev; - RTMP_OS_NETDEV_WAKE_QUEUE(pNetDev); - insertTailList(&freeNetIfEntryList, (PLIST_ENTRY)pNetIfEntry); - - DBGPRINT(RT_DEBUG_TRACE, ("RTMP_OS_NETDEV_WAKE_QUEUE(%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(pNetDev))); - } - pBlockQueueEntry->SwTxQueueBlockFlag = FALSE; - return; -} - - -VOID StopNetIfQueue( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket) -{ - PNET_DEV NetDev = NULL; - UCHAR IfIdx = 0; - BOOLEAN valid = FALSE; - -#ifdef APCLI_SUPPORT - if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_APCLI) - { - IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_APCLI) % MAX_APCLI_NUM; - NetDev = pAd->ApCfg.ApCliTab[IfIdx].dev; - } - else -#endif // APCLI_SUPPORT // -#ifdef WDS_SUPPORT - if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_WDS) - { - IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_WDS) % MAX_WDS_ENTRY; - NetDev = pAd->WdsTab.WdsEntry[IfIdx].dev; - } - else -#endif // WDS_SUPPORT // - { -#ifdef MBSS_SUPPORT - if (pAd->OpMode == OPMODE_AP) - { - IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_MBSSID) % MAX_MBSSID_NUM; - NetDev = pAd->ApCfg.MBSSID[IfIdx].MSSIDDev; - } - else - { - IfIdx = MAIN_MBSSID; - NetDev = pAd->net_dev; - } -#else - IfIdx = MAIN_MBSSID; - NetDev = pAd->net_dev; -#endif - } - - // WMM support 4 software queues. - // One software queue full doesn't mean device have no capbility to transmit packet. - // So disable block Net-If queue function while WMM enable. -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - valid = (pAd->CommonCfg.bWmmCapable == TRUE) ? FALSE : TRUE; -#endif // CONFIG_STA_SUPPORT // - - if (valid) - blockNetIf(&pAd->blockQueueTab[QueIdx], NetDev); - return; -} - -#endif // BLOCK_NET_IF // diff --git a/drivers/staging/rt3090/common/rt_channel.c b/drivers/staging/rt3090/common/rt_channel.c deleted file mode 100644 index da2391e8b74bedf8854a83b621ed5489b39abac3..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/rt_channel.c +++ /dev/null @@ -1,1287 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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 "../rt_config.h" - - -CH_FREQ_MAP CH_HZ_ID_MAP[]= - { - {1, 2412}, - {2, 2417}, - {3, 2422}, - {4, 2427}, - {5, 2432}, - {6, 2437}, - {7, 2442}, - {8, 2447}, - {9, 2452}, - {10, 2457}, - {11, 2462}, - {12, 2467}, - {13, 2472}, - {14, 2484}, - - /* UNII */ - {36, 5180}, - {40, 5200}, - {44, 5220}, - {48, 5240}, - {52, 5260}, - {56, 5280}, - {60, 5300}, - {64, 5320}, - {149, 5745}, - {153, 5765}, - {157, 5785}, - {161, 5805}, - {165, 5825}, - {167, 5835}, - {169, 5845}, - {171, 5855}, - {173, 5865}, - - /* HiperLAN2 */ - {100, 5500}, - {104, 5520}, - {108, 5540}, - {112, 5560}, - {116, 5580}, - {120, 5600}, - {124, 5620}, - {128, 5640}, - {132, 5660}, - {136, 5680}, - {140, 5700}, - - /* Japan MMAC */ - {34, 5170}, - {38, 5190}, - {42, 5210}, - {46, 5230}, - - /* Japan */ - {184, 4920}, - {188, 4940}, - {192, 4960}, - {196, 4980}, - - {208, 5040}, /* Japan, means J08 */ - {212, 5060}, /* Japan, means J12 */ - {216, 5080}, /* Japan, means J16 */ -}; - -INT CH_HZ_ID_MAP_NUM = (sizeof(CH_HZ_ID_MAP)/sizeof(CH_FREQ_MAP)); - -CH_REGION ChRegion[] = -{ - { // Antigua and Berbuda - "AG", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Argentina - "AR", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Aruba - "AW", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Australia - "AU", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Austria - "AT", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, TRUE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Bahamas - "BS", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Barbados - "BB", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Bermuda - "BM", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Brazil - "BR", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 24, BOTH, FALSE}, // 5G, ch 100~140 - { 149, 5, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Belgium - "BE", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 18, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 18, IDOR, FALSE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // Bulgaria - "BG", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Canada - "CA", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Cayman IsLands - "KY", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Chile - "CL", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 20, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // China - "CN", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Colombia - "CO", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Costa Rica - "CR", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Cyprus - "CY", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Czech_Republic - "CZ", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // Denmark - "DK", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Dominican Republic - "DO", - CE, - { - { 1, 0, 20, BOTH, FALSE}, // 2.4 G, ch 0 - { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Equador - "EC", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 100, 11, 27, BOTH, FALSE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // El Salvador - "SV", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 30, BOTH, TRUE}, // 5G, ch 52~64 - { 149, 4, 36, BOTH, TRUE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Finland - "FI", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // France - "FR", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // Germany - "DE", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Greece - "GR", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Guam - "GU", - CE, - { - { 1, 11, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 - { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Guatemala - "GT", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Haiti - "HT", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Honduras - "HN", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Hong Kong - "HK", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 - { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Hungary - "HU", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // Iceland - "IS", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // India - "IN", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 149, 4, 24, IDOR, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Indonesia - "ID", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Ireland - "IE", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Israel - "IL", - CE, - { - { 1, 3, 20, IDOR, FALSE}, // 2.4 G, ch 1~3 - { 4, 6, 20, BOTH, FALSE}, // 2.4 G, ch 4~9 - { 10, 4, 20, IDOR, FALSE}, // 2.4 G, ch 10~13 - { 0}, // end - } - }, - - { // Italy - "IT", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Japan - "JP", - JAP, - { - { 1, 14, 20, BOTH, FALSE}, // 2.4 G, ch 1~14 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 0}, // end - } - }, - - { // Jordan - "JO", - CE, - { - { 1, 13, 20, IDOR, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 149, 4, 23, IDOR, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Latvia - "LV", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Liechtenstein - "LI", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Lithuania - "LT", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Luxemburg - "LU", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Malaysia - "MY", - CE, - { - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Malta - "MT", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Marocco - "MA", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 24, IDOR, FALSE}, // 5G, ch 36~48 - { 0}, // end - } - }, - - { // Mexico - "MX", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 5, 30, IDOR, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Netherlands - "NL", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // New Zealand - "NZ", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 24, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Norway - "NO", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 24, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Peru - "PE", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Portugal - "PT", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Poland - "PL", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Romania - "RO", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Russia - "RU", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 149, 4, 20, IDOR, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Saudi Arabia - "SA", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 4, 23, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Serbia_and_Montenegro - "CS", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 0}, // end - } - }, - - { // Singapore - "SG", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 - { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Slovakia - "SK", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Slovenia - "SI", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // South Africa - "ZA", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // South Korea - "KR", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 20, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 8, 20, BOTH, FALSE}, // 5G, ch 100~128 - { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Spain - "ES", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 17, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Sweden - "SE", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Switzerland - "CH", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 - { 36, 4, 23, IDOR, TRUE}, // 5G, ch 36~48 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // Taiwan - "TW", - CE, - { - { 1, 11, 30, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // Turkey - "TR", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 - { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 - { 0}, // end - } - }, - - { // UK - "GB", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 36, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 - { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 0}, // end - } - }, - - { // Ukraine - "UA", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 0}, // end - } - }, - - { // United_Arab_Emirates - "AE", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 0}, // end - } - }, - - { // United_States - "US", - CE, - { - { 1, 11, 30, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 36, 4, 17, IDOR, FALSE}, // 5G, ch 52~64 - { 52, 4, 24, BOTH, TRUE}, // 5G, ch 52~64 - { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 - { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, - - { // Venezuela - "VE", - CE, - { - { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 - { 0}, // end - } - }, - - { // Default - "", - CE, - { - { 1, 11, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 - { 36, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 - { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 - { 100, 11, 20, BOTH, FALSE}, // 5G, ch 100~140 - { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165 - { 0}, // end - } - }, -}; - - -static PCH_REGION GetChRegion( - IN PUCHAR CntryCode) -{ - INT loop = 0; - PCH_REGION pChRegion = NULL; - - while (strcmp((PSTRING) ChRegion[loop].CountReg, "") != 0) - { - if (strncmp((PSTRING) ChRegion[loop].CountReg, (PSTRING) CntryCode, 2) == 0) - { - pChRegion = &ChRegion[loop]; - break; - } - loop++; - } - - if (pChRegion == NULL) - pChRegion = &ChRegion[loop]; - return pChRegion; -} - -static VOID ChBandCheck( - IN UCHAR PhyMode, - OUT PUCHAR pChType) -{ - switch(PhyMode) - { - case PHY_11A: -#ifdef DOT11_N_SUPPORT - case PHY_11AN_MIXED: -#endif // DOT11_N_SUPPORT // - *pChType = BAND_5G; - break; - case PHY_11ABG_MIXED: -#ifdef DOT11_N_SUPPORT - case PHY_11AGN_MIXED: - case PHY_11ABGN_MIXED: -#endif // DOT11_N_SUPPORT // - *pChType = BAND_BOTH; - break; - - default: - *pChType = BAND_24G; - break; - } -} - -static UCHAR FillChList( - IN PRTMP_ADAPTER pAd, - IN PCH_DESP pChDesp, - IN UCHAR Offset, - IN UCHAR increment) -{ - INT i, j, l; - UCHAR channel; - - j = Offset; - for (i = 0; i < pChDesp->NumOfCh; i++) - { - channel = pChDesp->FirstChannel + i * increment; - for (l=0; lTxPower[l].Channel) - { - pAd->ChannelList[j].Power = pAd->TxPower[l].Power; - pAd->ChannelList[j].Power2 = pAd->TxPower[l].Power2; - break; - } - } - if (l == MAX_NUM_OF_CHANNELS) - continue; - - pAd->ChannelList[j].Channel = pChDesp->FirstChannel + i * increment; - pAd->ChannelList[j].MaxTxPwr = pChDesp->MaxTxPwr; - pAd->ChannelList[j].DfsReq = pChDesp->DfsReq; - j++; - } - pAd->ChannelListNum = j; - - return j; -} - - -static inline VOID CreateChList( - IN PRTMP_ADAPTER pAd, - IN PCH_REGION pChRegion, - IN UCHAR Geography) -{ - INT i; - UCHAR offset = 0; - PCH_DESP pChDesp; - UCHAR ChType; - UCHAR increment; - - if (pChRegion == NULL) - return; - - ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); - - for (i=0; i<10; i++) - { - pChDesp = &pChRegion->ChDesp[i]; - if (pChDesp->FirstChannel == 0) - break; - - if (ChType == BAND_5G) - { - if (pChDesp->FirstChannel <= 14) - continue; - } - else if (ChType == BAND_24G) - { - if (pChDesp->FirstChannel > 14) - continue; - } - - if ((pChDesp->Geography == BOTH) - || (pChDesp->Geography == Geography)) - { - if (pChDesp->FirstChannel > 14) - increment = 4; - else - increment = 1; - offset = FillChList(pAd, pChDesp, offset, increment); - } - } -} - - -VOID BuildChannelListEx( - IN PRTMP_ADAPTER pAd) -{ - PCH_REGION pChReg; - - pChReg = GetChRegion(pAd->CommonCfg.CountryCode); - CreateChList(pAd, pChReg, pAd->CommonCfg.Geography); -} - - -VOID BuildBeaconChList( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf, - OUT PULONG pBufLen) -{ - INT i; - ULONG TmpLen; - PCH_REGION pChRegion; - PCH_DESP pChDesp; - UCHAR ChType; - - pChRegion = GetChRegion(pAd->CommonCfg.CountryCode); - - if (pChRegion == NULL) - return; - - ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); - *pBufLen = 0; - - for (i=0; i<10; i++) - { - pChDesp = &pChRegion->ChDesp[i]; - if (pChDesp->FirstChannel == 0) - break; - - if (ChType == BAND_5G) - { - if (pChDesp->FirstChannel <= 14) - continue; - } - else if (ChType == BAND_24G) - { - if (pChDesp->FirstChannel > 14) - continue; - } - - if ((pChDesp->Geography == BOTH) - || (pChDesp->Geography == pAd->CommonCfg.Geography)) - { - MakeOutgoingFrame(pBuf + *pBufLen, &TmpLen, - 1, &pChDesp->FirstChannel, - 1, &pChDesp->NumOfCh, - 1, &pChDesp->MaxTxPwr, - END_OF_ARGS); - *pBufLen += TmpLen; - } - } -} - - -#ifdef DOT11_N_SUPPORT -static BOOLEAN IsValidChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR channel) - -{ - INT i; - - for (i = 0; i < pAd->ChannelListNum; i++) - { - if (pAd->ChannelList[i].Channel == channel) - break; - } - - if (i == pAd->ChannelListNum) - return FALSE; - else - return TRUE; -} - - -static UCHAR GetExtCh( - IN UCHAR Channel, - IN UCHAR Direction) -{ - CHAR ExtCh; - - if (Direction == EXTCHA_ABOVE) - ExtCh = Channel + 4; - else - ExtCh = (Channel - 4) > 0 ? (Channel - 4) : 0; - - return ExtCh; -} - - -VOID N_ChannelCheck( - IN PRTMP_ADAPTER pAd) -{ - //UCHAR ChannelNum = pAd->ChannelListNum; - UCHAR Channel = pAd->CommonCfg.Channel; - - if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) - { - if (Channel > 14) - { - if ((Channel == 36) || (Channel == 44) || (Channel == 52) || (Channel == 60) || (Channel == 100) || (Channel == 108) || - (Channel == 116) || (Channel == 124) || (Channel == 132) || (Channel == 149) || (Channel == 157)) - { - pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; - } - else if ((Channel == 40) || (Channel == 48) || (Channel == 56) || (Channel == 64) || (Channel == 104) || (Channel == 112) || - (Channel == 120) || (Channel == 128) || (Channel == 136) || (Channel == 153) || (Channel == 161)) - { - pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; - } - else - { - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; - } - } - else - { - do - { - UCHAR ExtCh; - UCHAR Dir = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; - ExtCh = GetExtCh(Channel, Dir); - if (IsValidChannel(pAd, ExtCh)) - break; - - Dir = (Dir == EXTCHA_ABOVE) ? EXTCHA_BELOW : EXTCHA_ABOVE; - ExtCh = GetExtCh(Channel, Dir); - if (IsValidChannel(pAd, ExtCh)) - { - pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = Dir; - break; - } - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; - } while(FALSE); - - if (Channel == 14) - { - pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; - //pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; // We didn't set the ExtCh as NONE due to it'll set in RTMPSetHT() - } - } - } - - -} - - -VOID N_SetCenCh( - IN PRTMP_ADAPTER pAd) -{ - if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) - { - if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) - { - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; - } - else - { - if (pAd->CommonCfg.Channel == 14) - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 1; - else - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; - } - } - else - { - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; - } -} -#endif // DOT11_N_SUPPORT // - - -UINT8 GetCuntryMaxTxPwr( - IN PRTMP_ADAPTER pAd, - IN UINT8 channel) -{ - int i; - for (i = 0; i < pAd->ChannelListNum; i++) - { - if (pAd->ChannelList[i].Channel == channel) - break; - } - - if (i == pAd->ChannelListNum) - return 0xff; - else - return pAd->ChannelList[i].MaxTxPwr; -} diff --git a/drivers/staging/rt3090/common/rtmp_init.c b/drivers/staging/rt3090/common/rtmp_init.c deleted file mode 100644 index 48b95b75b0d5dc99e5c336d8d0f7ab7346906a9c..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/rtmp_init.c +++ /dev/null @@ -1,3882 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rtmp_init.c - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#include "../rt_config.h" - - -UCHAR BIT8[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; -char* CipherName[] = {"none","wep64","wep128","TKIP","AES","CKIP64","CKIP128"}; - -// -// BBP register initialization set -// -REG_PAIR BBPRegTable[] = { - {BBP_R65, 0x2C}, // fix rssi issue - {BBP_R66, 0x38}, // Also set this default value to pAd->BbpTuning.R66CurrentValue at initial - {BBP_R69, 0x12}, - {BBP_R70, 0xa}, // BBP_R70 will change to 0x8 in ApStartUp and LinkUp for rt2860C, otherwise value is 0xa - {BBP_R73, 0x10}, - {BBP_R81, 0x37}, - {BBP_R82, 0x62}, - {BBP_R83, 0x6A}, - {BBP_R84, 0x99}, // 0x19 is for rt2860E and after. This is for extension channel overlapping IOT. 0x99 is for rt2860D and before - {BBP_R86, 0x00}, // middle range issue, Rory @2008-01-28 - {BBP_R91, 0x04}, // middle range issue, Rory @2008-01-28 - {BBP_R92, 0x00}, // middle range issue, Rory @2008-01-28 - {BBP_R103, 0x00}, // near range high-power issue, requested from Gary @2008-0528 - {BBP_R105, 0x05}, // 0x05 is for rt2860E to turn on FEQ control. It is safe for rt2860D and before, because Bit 7:2 are reserved in rt2860D and before. - {BBP_R106, 0x35}, // for ShortGI throughput -}; -#define NUM_BBP_REG_PARMS (sizeof(BBPRegTable) / sizeof(REG_PAIR)) - - -// -// ASIC register initialization sets -// - -RTMP_REG_PAIR MACRegTable[] = { -#if defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x200) - {BCN_OFFSET0, 0xf8f0e8e0}, /* 0x3800(e0), 0x3A00(e8), 0x3C00(f0), 0x3E00(f8), 512B for each beacon */ - {BCN_OFFSET1, 0x6f77d0c8}, /* 0x3200(c8), 0x3400(d0), 0x1DC0(77), 0x1BC0(6f), 512B for each beacon */ -#elif defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x100) - {BCN_OFFSET0, 0xece8e4e0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ - {BCN_OFFSET1, 0xfcf8f4f0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ -#else - #error You must re-calculate new value for BCN_OFFSET0 & BCN_OFFSET1 in MACRegTable[]!!! -#endif // HW_BEACON_OFFSET // - - {LEGACY_BASIC_RATE, 0x0000013f}, // Basic rate set bitmap - {HT_BASIC_RATE, 0x00008003}, // Basic HT rate set , 20M, MCS=3, MM. Format is the same as in TXWI. - {MAC_SYS_CTRL, 0x00}, // 0x1004, , default Disable RX - {RX_FILTR_CFG, 0x17f97}, //0x1400 , RX filter control, - {BKOFF_SLOT_CFG, 0x209}, // default set short slot time, CC_DELAY_TIME should be 2 - //{TX_SW_CFG0, 0x40a06}, // Gary,2006-08-23 - {TX_SW_CFG0, 0x0}, // Gary,2008-05-21 for CWC test - {TX_SW_CFG1, 0x80606}, // Gary,2006-08-23 - {TX_LINK_CFG, 0x1020}, // Gary,2006-08-23 - //{TX_TIMEOUT_CFG, 0x00182090}, // CCK has some problem. So increase timieout value. 2006-10-09// MArvek RT - {TX_TIMEOUT_CFG, 0x000a2090}, // CCK has some problem. So increase timieout value. 2006-10-09// MArvek RT , Modify for 2860E ,2007-08-01 - {MAX_LEN_CFG, MAX_AGGREGATION_SIZE | 0x00001000}, // 0x3018, MAX frame length. Max PSDU = 16kbytes. - {LED_CFG, 0x7f031e46}, // Gary, 2006-08-23 - -//#ifdef CONFIG_AP_SUPPORT -// {WMM_AIFSN_CFG, 0x00001173}, -// {WMM_CWMIN_CFG, 0x00002344}, -// {WMM_CWMAX_CFG, 0x000034a6}, -// {WMM_TXOP0_CFG, 0x00100020}, -// {WMM_TXOP1_CFG, 0x002F0038}, -//#endif // CONFIG_AP_SUPPORT // - -//#ifdef CONFIG_STA_SUPPORT -// {WMM_AIFSN_CFG, 0x00002273}, -// {WMM_CWMIN_CFG, 0x00002344}, -// {WMM_CWMAX_CFG, 0x000034aa}, -//#endif // CONFIG_STA_SUPPORT // -#ifdef INF_AMAZON_SE - {PBF_MAX_PCNT, 0x1F3F6F6F}, //iverson modify for usb issue, 2008/09/19 - // 6F + 6F < total page count FE - // so that RX doesn't occupy TX's buffer space when WMM congestion. -#else - {PBF_MAX_PCNT, 0x1F3FBF9F}, //0x1F3f7f9f}, //Jan, 2006/04/20 -#endif // INF_AMAZON_SE // - //{TX_RTY_CFG, 0x6bb80408}, // Jan, 2006/11/16 -// WMM_ACM_SUPPORT -// {TX_RTY_CFG, 0x6bb80101}, // sample - {TX_RTY_CFG, 0x47d01f0f}, // Jan, 2006/11/16, Set TxWI->ACK =0 in Probe Rsp Modify for 2860E ,2007-08-03 - - {AUTO_RSP_CFG, 0x00000013}, // Initial Auto_Responder, because QA will turn off Auto-Responder - {CCK_PROT_CFG, 0x05740003 /*0x01740003*/}, // Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. - {OFDM_PROT_CFG, 0x05740003 /*0x01740003*/}, // Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. - {GF20_PROT_CFG, 0x01744004}, // set 19:18 --> Short NAV for MIMO PS - {GF40_PROT_CFG, 0x03F44084}, - {MM20_PROT_CFG, 0x01744004}, -#ifdef RTMP_MAC_PCI - {MM40_PROT_CFG, 0x03F54084}, -#endif // RTMP_MAC_PCI // - {TXOP_CTRL_CFG, 0x0000583f, /*0x0000243f*/ /*0x000024bf*/}, //Extension channel backoff. - {TX_RTS_CFG, 0x00092b20}, -//#ifdef WIFI_TEST - {EXP_ACK_TIME, 0x002400ca}, // default value -//#else -// {EXP_ACK_TIME, 0x005400ca}, // suggested by Gray @ 20070323 for 11n intel-sta throughput -//#endif // end - WIFI_TEST // -//#ifdef CONFIG_AP_SUPPORT -// {TBTT_SYNC_CFG, 0x00422000}, // TBTT_ADJUST(7:0) == 0 -// {TBTT_SYNC_CFG, 0x00012000}, // TBTT_ADJUST(7:0) == 0 -//#endif // CONFIG_AP_SUPPORT // - {TXOP_HLDR_ET, 0x00000002}, - - /* Jerry comments 2008/01/16: we use SIFS = 10us in CCK defaultly, but it seems that 10us - is too small for INTEL 2200bg card, so in MBSS mode, the delta time between beacon0 - and beacon1 is SIFS (10us), so if INTEL 2200bg card connects to BSS0, the ping - will always lost. So we change the SIFS of CCK from 10us to 16us. */ - {XIFS_TIME_CFG, 0x33a41010}, - {PWR_PIN_CFG, 0x00000003}, // patch for 2880-E -}; - - -#ifdef CONFIG_STA_SUPPORT -RTMP_REG_PAIR STAMACRegTable[] = { - {WMM_AIFSN_CFG, 0x00002273}, - {WMM_CWMIN_CFG, 0x00002344}, - {WMM_CWMAX_CFG, 0x000034aa}, -}; -#endif // CONFIG_STA_SUPPORT // - -#define NUM_MAC_REG_PARMS (sizeof(MACRegTable) / sizeof(RTMP_REG_PAIR)) -#ifdef CONFIG_STA_SUPPORT -#define NUM_STA_MAC_REG_PARMS (sizeof(STAMACRegTable) / sizeof(RTMP_REG_PAIR)) -#endif // CONFIG_STA_SUPPORT // - - -/* - ======================================================================== - - Routine Description: - Allocate RTMP_ADAPTER data block and do some initialization - - Arguments: - Adapter Pointer to our adapter - - Return Value: - NDIS_STATUS_SUCCESS - NDIS_STATUS_FAILURE - - IRQL = PASSIVE_LEVEL - - Note: - - ======================================================================== -*/ -NDIS_STATUS RTMPAllocAdapterBlock( - IN PVOID handle, - OUT PRTMP_ADAPTER *ppAdapter) -{ - PRTMP_ADAPTER pAd; - NDIS_STATUS Status; - INT index; - UCHAR *pBeaconBuf = NULL; - - DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocAdapterBlock\n")); - - *ppAdapter = NULL; - - do - { - // Allocate RTMP_ADAPTER memory block - pBeaconBuf = kmalloc(MAX_BEACON_SIZE, MEM_ALLOC_FLAG); - if (pBeaconBuf == NULL) - { - Status = NDIS_STATUS_FAILURE; - DBGPRINT_ERR(("Failed to allocate memory - BeaconBuf!\n")); - break; - } - NdisZeroMemory(pBeaconBuf, MAX_BEACON_SIZE); - - Status = AdapterBlockAllocateMemory(handle, (PVOID *)&pAd); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT_ERR(("Failed to allocate memory - ADAPTER\n")); - break; - } - pAd->BeaconBuf = pBeaconBuf; - DBGPRINT(RT_DEBUG_OFF, ("\n\n=== pAd = %p, size = %d ===\n\n", pAd, (UINT32)sizeof(RTMP_ADAPTER))); - - - // Init spin locks - NdisAllocateSpinLock(&pAd->MgmtRingLock); -#ifdef RTMP_MAC_PCI - NdisAllocateSpinLock(&pAd->RxRingLock); -#ifdef RT3090 -#ifdef CONFIG_STA_SUPPORT - NdisAllocateSpinLock(&pAd->McuCmdLock); -#endif // CONFIG_STA_SUPPORT // -#endif // RT3090 // -#endif // RTMP_MAC_PCI // - - for (index =0 ; index < NUM_OF_TX_RING; index++) - { - NdisAllocateSpinLock(&pAd->TxSwQueueLock[index]); - NdisAllocateSpinLock(&pAd->DeQueueLock[index]); - pAd->DeQueueRunning[index] = FALSE; - } - - NdisAllocateSpinLock(&pAd->irq_lock); - - - } while (FALSE); - - if ((Status != NDIS_STATUS_SUCCESS) && (pBeaconBuf)) - kfree(pBeaconBuf); - - *ppAdapter = pAd; - - DBGPRINT_S(Status, ("<-- RTMPAllocAdapterBlock, Status=%x\n", Status)); - return Status; -} - - -/* - ======================================================================== - - Routine Description: - Read initial Tx power per MCS and BW from EEPROM - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPReadTxPwrPerRate( - IN PRTMP_ADAPTER pAd) -{ - ULONG data, Adata, Gdata; - USHORT i, value, value2; - INT Apwrdelta, Gpwrdelta; - UCHAR t1,t2,t3,t4; - BOOLEAN bApwrdeltaMinus = TRUE, bGpwrdeltaMinus = TRUE; - - // - // Get power delta for 20MHz and 40MHz. - // - DBGPRINT(RT_DEBUG_TRACE, ("Txpower per Rate\n")); - RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, value2); - Apwrdelta = 0; - Gpwrdelta = 0; - - if ((value2 & 0xff) != 0xff) - { - if ((value2 & 0x80)) - Gpwrdelta = (value2&0xf); - - if ((value2 & 0x40)) - bGpwrdeltaMinus = FALSE; - else - bGpwrdeltaMinus = TRUE; - } - if ((value2 & 0xff00) != 0xff00) - { - if ((value2 & 0x8000)) - Apwrdelta = ((value2&0xf00)>>8); - - if ((value2 & 0x4000)) - bApwrdeltaMinus = FALSE; - else - bApwrdeltaMinus = TRUE; - } - DBGPRINT(RT_DEBUG_TRACE, ("Gpwrdelta = %x, Apwrdelta = %x .\n", Gpwrdelta, Apwrdelta)); - - // - // Get Txpower per MCS for 20MHz in 2.4G. - // - for (i=0; i<5; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4, value); - data = value; - if (bApwrdeltaMinus == FALSE) - { - t1 = (value&0xf)+(Apwrdelta); - if (t1 > 0xf) - t1 = 0xf; - t2 = ((value&0xf0)>>4)+(Apwrdelta); - if (t2 > 0xf) - t2 = 0xf; - t3 = ((value&0xf00)>>8)+(Apwrdelta); - if (t3 > 0xf) - t3 = 0xf; - t4 = ((value&0xf000)>>12)+(Apwrdelta); - if (t4 > 0xf) - t4 = 0xf; - } - else - { - if ((value&0xf) > Apwrdelta) - t1 = (value&0xf)-(Apwrdelta); - else - t1 = 0; - if (((value&0xf0)>>4) > Apwrdelta) - t2 = ((value&0xf0)>>4)-(Apwrdelta); - else - t2 = 0; - if (((value&0xf00)>>8) > Apwrdelta) - t3 = ((value&0xf00)>>8)-(Apwrdelta); - else - t3 = 0; - if (((value&0xf000)>>12) > Apwrdelta) - t4 = ((value&0xf000)>>12)-(Apwrdelta); - else - t4 = 0; - } - Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12); - if (bGpwrdeltaMinus == FALSE) - { - t1 = (value&0xf)+(Gpwrdelta); - if (t1 > 0xf) - t1 = 0xf; - t2 = ((value&0xf0)>>4)+(Gpwrdelta); - if (t2 > 0xf) - t2 = 0xf; - t3 = ((value&0xf00)>>8)+(Gpwrdelta); - if (t3 > 0xf) - t3 = 0xf; - t4 = ((value&0xf000)>>12)+(Gpwrdelta); - if (t4 > 0xf) - t4 = 0xf; - } - else - { - if ((value&0xf) > Gpwrdelta) - t1 = (value&0xf)-(Gpwrdelta); - else - t1 = 0; - if (((value&0xf0)>>4) > Gpwrdelta) - t2 = ((value&0xf0)>>4)-(Gpwrdelta); - else - t2 = 0; - if (((value&0xf00)>>8) > Gpwrdelta) - t3 = ((value&0xf00)>>8)-(Gpwrdelta); - else - t3 = 0; - if (((value&0xf000)>>12) > Gpwrdelta) - t4 = ((value&0xf000)>>12)-(Gpwrdelta); - else - t4 = 0; - } - Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12); - - RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4 + 2, value); - if (bApwrdeltaMinus == FALSE) - { - t1 = (value&0xf)+(Apwrdelta); - if (t1 > 0xf) - t1 = 0xf; - t2 = ((value&0xf0)>>4)+(Apwrdelta); - if (t2 > 0xf) - t2 = 0xf; - t3 = ((value&0xf00)>>8)+(Apwrdelta); - if (t3 > 0xf) - t3 = 0xf; - t4 = ((value&0xf000)>>12)+(Apwrdelta); - if (t4 > 0xf) - t4 = 0xf; - } - else - { - if ((value&0xf) > Apwrdelta) - t1 = (value&0xf)-(Apwrdelta); - else - t1 = 0; - if (((value&0xf0)>>4) > Apwrdelta) - t2 = ((value&0xf0)>>4)-(Apwrdelta); - else - t2 = 0; - if (((value&0xf00)>>8) > Apwrdelta) - t3 = ((value&0xf00)>>8)-(Apwrdelta); - else - t3 = 0; - if (((value&0xf000)>>12) > Apwrdelta) - t4 = ((value&0xf000)>>12)-(Apwrdelta); - else - t4 = 0; - } - Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); - if (bGpwrdeltaMinus == FALSE) - { - t1 = (value&0xf)+(Gpwrdelta); - if (t1 > 0xf) - t1 = 0xf; - t2 = ((value&0xf0)>>4)+(Gpwrdelta); - if (t2 > 0xf) - t2 = 0xf; - t3 = ((value&0xf00)>>8)+(Gpwrdelta); - if (t3 > 0xf) - t3 = 0xf; - t4 = ((value&0xf000)>>12)+(Gpwrdelta); - if (t4 > 0xf) - t4 = 0xf; - } - else - { - if ((value&0xf) > Gpwrdelta) - t1 = (value&0xf)-(Gpwrdelta); - else - t1 = 0; - if (((value&0xf0)>>4) > Gpwrdelta) - t2 = ((value&0xf0)>>4)-(Gpwrdelta); - else - t2 = 0; - if (((value&0xf00)>>8) > Gpwrdelta) - t3 = ((value&0xf00)>>8)-(Gpwrdelta); - else - t3 = 0; - if (((value&0xf000)>>12) > Gpwrdelta) - t4 = ((value&0xf000)>>12)-(Gpwrdelta); - else - t4 = 0; - } - Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); - data |= (value<<16); - - /* For 20M/40M Power Delta issue */ - pAd->Tx20MPwrCfgABand[i] = data; - pAd->Tx20MPwrCfgGBand[i] = data; - pAd->Tx40MPwrCfgABand[i] = Adata; - pAd->Tx40MPwrCfgGBand[i] = Gdata; - - if (data != 0xffffffff) - RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, data); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band-%lx, Adata = %lx, Gdata = %lx \n", data, Adata, Gdata)); - } -} - - -/* - ======================================================================== - - Routine Description: - Read initial channel power parameters from EEPROM - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPReadChannelPwr( - IN PRTMP_ADAPTER pAd) -{ - UCHAR i, choffset; - EEPROM_TX_PWR_STRUC Power; - EEPROM_TX_PWR_STRUC Power2; - - // Read Tx power value for all channels - // Value from 1 - 0x7f. Default value is 24. - // Power value : 2.4G 0x00 (0) ~ 0x1F (31) - // : 5.5G 0xF9 (-7) ~ 0x0F (15) - - // 0. 11b/g, ch1 - ch 14 - for (i = 0; i < 7; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2, Power.word); - RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2, Power2.word); - pAd->TxPower[i * 2].Channel = i * 2 + 1; - pAd->TxPower[i * 2 + 1].Channel = i * 2 + 2; - - if ((Power.field.Byte0 > 31) || (Power.field.Byte0 < 0)) - pAd->TxPower[i * 2].Power = DEFAULT_RF_TX_POWER; - else - pAd->TxPower[i * 2].Power = Power.field.Byte0; - - if ((Power.field.Byte1 > 31) || (Power.field.Byte1 < 0)) - pAd->TxPower[i * 2 + 1].Power = DEFAULT_RF_TX_POWER; - else - pAd->TxPower[i * 2 + 1].Power = Power.field.Byte1; - - if ((Power2.field.Byte0 > 31) || (Power2.field.Byte0 < 0)) - pAd->TxPower[i * 2].Power2 = DEFAULT_RF_TX_POWER; - else - pAd->TxPower[i * 2].Power2 = Power2.field.Byte0; - - if ((Power2.field.Byte1 > 31) || (Power2.field.Byte1 < 0)) - pAd->TxPower[i * 2 + 1].Power2 = DEFAULT_RF_TX_POWER; - else - pAd->TxPower[i * 2 + 1].Power2 = Power2.field.Byte1; - } - - // 1. U-NII lower/middle band: 36, 38, 40; 44, 46, 48; 52, 54, 56; 60, 62, 64 (including central frequency in BW 40MHz) - // 1.1 Fill up channel - choffset = 14; - for (i = 0; i < 4; i++) - { - pAd->TxPower[3 * i + choffset + 0].Channel = 36 + i * 8 + 0; - pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; - - pAd->TxPower[3 * i + choffset + 1].Channel = 36 + i * 8 + 2; - pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; - - pAd->TxPower[3 * i + choffset + 2].Channel = 36 + i * 8 + 4; - pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; - } - - // 1.2 Fill up power - for (i = 0; i < 6; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + i * 2, Power.word); - RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + i * 2, Power2.word); - - if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) - pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; - - if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) - pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; - - if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) - pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; - - if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) - pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; - } - - // 2. HipperLAN 2 100, 102 ,104; 108, 110, 112; 116, 118, 120; 124, 126, 128; 132, 134, 136; 140 (including central frequency in BW 40MHz) - // 2.1 Fill up channel - choffset = 14 + 12; - for (i = 0; i < 5; i++) - { - pAd->TxPower[3 * i + choffset + 0].Channel = 100 + i * 8 + 0; - pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; - - pAd->TxPower[3 * i + choffset + 1].Channel = 100 + i * 8 + 2; - pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; - - pAd->TxPower[3 * i + choffset + 2].Channel = 100 + i * 8 + 4; - pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; - } - pAd->TxPower[3 * 5 + choffset + 0].Channel = 140; - pAd->TxPower[3 * 5 + choffset + 0].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * 5 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; - - // 2.2 Fill up power - for (i = 0; i < 8; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word); - RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word); - - if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) - pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; - - if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) - pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; - - if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) - pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; - - if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) - pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; - } - - // 3. U-NII upper band: 149, 151, 153; 157, 159, 161; 165, 167, 169; 171, 173 (including central frequency in BW 40MHz) - // 3.1 Fill up channel - choffset = 14 + 12 + 16; - /*for (i = 0; i < 2; i++)*/ - for (i = 0; i < 3; i++) - { - pAd->TxPower[3 * i + choffset + 0].Channel = 149 + i * 8 + 0; - pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; - - pAd->TxPower[3 * i + choffset + 1].Channel = 149 + i * 8 + 2; - pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; - - pAd->TxPower[3 * i + choffset + 2].Channel = 149 + i * 8 + 4; - pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; - } - pAd->TxPower[3 * 3 + choffset + 0].Channel = 171; - pAd->TxPower[3 * 3 + choffset + 0].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * 3 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; - - pAd->TxPower[3 * 3 + choffset + 1].Channel = 173; - pAd->TxPower[3 * 3 + choffset + 1].Power = DEFAULT_RF_TX_POWER; - pAd->TxPower[3 * 3 + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; - - // 3.2 Fill up power - /*for (i = 0; i < 4; i++)*/ - for (i = 0; i < 6; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word); - RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word); - - if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) - pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; - - if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) - pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; - - if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) - pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; - - if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) - pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; - } - - // 4. Print and Debug - /*choffset = 14 + 12 + 16 + 7;*/ - choffset = 14 + 12 + 16 + 11; - - -} - -/* - ======================================================================== - - Routine Description: - Read the following from the registry - 1. All the parameters - 2. NetworkAddres - - Arguments: - Adapter Pointer to our adapter - WrapperConfigurationContext For use by NdisOpenConfiguration - - Return Value: - NDIS_STATUS_SUCCESS - NDIS_STATUS_FAILURE - NDIS_STATUS_RESOURCES - - IRQL = PASSIVE_LEVEL - - Note: - - ======================================================================== -*/ -NDIS_STATUS NICReadRegParameters( - IN PRTMP_ADAPTER pAd, - IN NDIS_HANDLE WrapperConfigurationContext - ) -{ - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - DBGPRINT_S(Status, ("<-- NICReadRegParameters, Status=%x\n", Status)); - return Status; -} - - -/* - ======================================================================== - - Routine Description: - Read initial parameters from EEPROM - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - Note: - - ======================================================================== -*/ -VOID NICReadEEPROMParameters( - IN PRTMP_ADAPTER pAd, - IN PUCHAR mac_addr) -{ - UINT32 data = 0; - USHORT i, value, value2; - UCHAR TmpPhy; - EEPROM_TX_PWR_STRUC Power; - EEPROM_VERSION_STRUC Version; - EEPROM_ANTENNA_STRUC Antenna; - EEPROM_NIC_CONFIG2_STRUC NicConfig2; - - DBGPRINT(RT_DEBUG_TRACE, ("--> NICReadEEPROMParameters\n")); - - if (pAd->chipOps.eeinit) - pAd->chipOps.eeinit(pAd); -#ifdef RTMP_EFUSE_SUPPORT -#ifdef RT30xx - if(!pAd->bFroceEEPROMBuffer && pAd->bEEPROMFile) - { - DBGPRINT(RT_DEBUG_TRACE, ("--> NICReadEEPROMParameters::(Efuse)Load to EEPROM Buffer Mode\n")); - eFuseLoadEEPROM(pAd); - } -#endif // RT30xx // -#endif // RTMP_EFUSE_SUPPORT // - - // Init EEPROM Address Number, before access EEPROM; if 93c46, EEPROMAddressNum=6, else if 93c66, EEPROMAddressNum=8 - RTMP_IO_READ32(pAd, E2PROM_CSR, &data); - DBGPRINT(RT_DEBUG_TRACE, ("--> E2PROM_CSR = 0x%x\n", data)); - - if((data & 0x30) == 0) - pAd->EEPROMAddressNum = 6; // 93C46 - else if((data & 0x30) == 0x10) - pAd->EEPROMAddressNum = 8; // 93C66 - else - pAd->EEPROMAddressNum = 8; // 93C86 - DBGPRINT(RT_DEBUG_TRACE, ("--> EEPROMAddressNum = %d\n", pAd->EEPROMAddressNum )); - - // RT2860 MAC no longer auto load MAC address from E2PROM. Driver has to intialize - // MAC address registers according to E2PROM setting - if (mac_addr == NULL || - strlen((PSTRING) mac_addr) != 17 || - mac_addr[2] != ':' || mac_addr[5] != ':' || mac_addr[8] != ':' || - mac_addr[11] != ':' || mac_addr[14] != ':') - { - USHORT Addr01,Addr23,Addr45 ; - - RT28xx_EEPROM_READ16(pAd, 0x04, Addr01); - RT28xx_EEPROM_READ16(pAd, 0x06, Addr23); - RT28xx_EEPROM_READ16(pAd, 0x08, Addr45); - - pAd->PermanentAddress[0] = (UCHAR)(Addr01 & 0xff); - pAd->PermanentAddress[1] = (UCHAR)(Addr01 >> 8); - pAd->PermanentAddress[2] = (UCHAR)(Addr23 & 0xff); - pAd->PermanentAddress[3] = (UCHAR)(Addr23 >> 8); - pAd->PermanentAddress[4] = (UCHAR)(Addr45 & 0xff); - pAd->PermanentAddress[5] = (UCHAR)(Addr45 >> 8); - - DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from E2PROM \n")); - } - else - { - INT j; - PSTRING macptr; - - macptr = (PSTRING) mac_addr; - - for (j=0; jPermanentAddress[j], 1); - macptr=macptr+3; - } - - DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from module parameter \n")); - } - - - { - //more conveninet to test mbssid, so ap's bssid &0xf1 - if (pAd->PermanentAddress[0] == 0xff) - pAd->PermanentAddress[0] = RandomByte(pAd)&0xf8; - - //if (pAd->PermanentAddress[5] == 0xff) - // pAd->PermanentAddress[5] = RandomByte(pAd)&0xf8; - - DBGPRINT_RAW(RT_DEBUG_TRACE,("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n", - pAd->PermanentAddress[0], pAd->PermanentAddress[1], - pAd->PermanentAddress[2], pAd->PermanentAddress[3], - pAd->PermanentAddress[4], pAd->PermanentAddress[5])); - if (pAd->bLocalAdminMAC == FALSE) - { - MAC_DW0_STRUC csr2; - MAC_DW1_STRUC csr3; - COPY_MAC_ADDR(pAd->CurrentAddress, pAd->PermanentAddress); - csr2.field.Byte0 = pAd->CurrentAddress[0]; - csr2.field.Byte1 = pAd->CurrentAddress[1]; - csr2.field.Byte2 = pAd->CurrentAddress[2]; - csr2.field.Byte3 = pAd->CurrentAddress[3]; - RTMP_IO_WRITE32(pAd, MAC_ADDR_DW0, csr2.word); - csr3.word = 0; - csr3.field.Byte4 = pAd->CurrentAddress[4]; - csr3.field.Byte5 = pAd->CurrentAddress[5]; - csr3.field.U2MeMask = 0xff; - RTMP_IO_WRITE32(pAd, MAC_ADDR_DW1, csr3.word); - DBGPRINT_RAW(RT_DEBUG_TRACE,("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n", - PRINT_MAC(pAd->PermanentAddress))); - } - } - - // if not return early. cause fail at emulation. - // Init the channel number for TX channel power - RTMPReadChannelPwr(pAd); - - // if E2PROM version mismatch with driver's expectation, then skip - // all subsequent E2RPOM retieval and set a system error bit to notify GUI - RT28xx_EEPROM_READ16(pAd, EEPROM_VERSION_OFFSET, Version.word); - pAd->EepromVersion = Version.field.Version + Version.field.FaeReleaseNumber * 256; - DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: Version = %d, FAE release #%d\n", Version.field.Version, Version.field.FaeReleaseNumber)); - - if (Version.field.Version > VALID_EEPROM_VERSION) - { - DBGPRINT_ERR(("E2PROM: WRONG VERSION 0x%x, should be %d\n",Version.field.Version, VALID_EEPROM_VERSION)); - /*pAd->SystemErrorBitmap |= 0x00000001; - - // hard-code default value when no proper E2PROM installed - pAd->bAutoTxAgcA = FALSE; - pAd->bAutoTxAgcG = FALSE; - - // Default the channel power - for (i = 0; i < MAX_NUM_OF_CHANNELS; i++) - pAd->TxPower[i].Power = DEFAULT_RF_TX_POWER; - - // Default the channel power - for (i = 0; i < MAX_NUM_OF_11JCHANNELS; i++) - pAd->TxPower11J[i].Power = DEFAULT_RF_TX_POWER; - - for(i = 0; i < NUM_EEPROM_BBP_PARMS; i++) - pAd->EEPROMDefaultValue[i] = 0xffff; - return; */ - } - - // Read BBP default value from EEPROM and store to array(EEPROMDefaultValue) in pAd - RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, value); - pAd->EEPROMDefaultValue[0] = value; - - RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value); - pAd->EEPROMDefaultValue[1] = value; - - RT28xx_EEPROM_READ16(pAd, 0x38, value); // Country Region - pAd->EEPROMDefaultValue[2] = value; - - for(i = 0; i < 8; i++) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_BBP_BASE_OFFSET + i*2, value); - pAd->EEPROMDefaultValue[i+3] = value; - } - - // We have to parse NIC configuration 0 at here. - // If TSSI did not have preloaded value, it should reset the TxAutoAgc to false - // Therefore, we have to read TxAutoAgc control beforehand. - // Read Tx AGC control bit - Antenna.word = pAd->EEPROMDefaultValue[0]; - if (Antenna.word == 0xFFFF) - { -#ifdef RT30xx - if(IS_RT3090(pAd)|| IS_RT3390(pAd)) - { - Antenna.word = 0; - Antenna.field.RfIcType = RFIC_3020; - Antenna.field.TxPath = 1; - Antenna.field.RxPath = 1; - } - else -#endif // RT30xx // - { - - Antenna.word = 0; - Antenna.field.RfIcType = RFIC_2820; - Antenna.field.TxPath = 1; - Antenna.field.RxPath = 2; - DBGPRINT(RT_DEBUG_WARN, ("E2PROM error, hard code as 0x%04x\n", Antenna.word)); - } - } - - // Choose the desired Tx&Rx stream. - if ((pAd->CommonCfg.TxStream == 0) || (pAd->CommonCfg.TxStream > Antenna.field.TxPath)) - pAd->CommonCfg.TxStream = Antenna.field.TxPath; - - if ((pAd->CommonCfg.RxStream == 0) || (pAd->CommonCfg.RxStream > Antenna.field.RxPath)) - { - pAd->CommonCfg.RxStream = Antenna.field.RxPath; - - if ((pAd->MACVersion < RALINK_2883_VERSION) && - (pAd->CommonCfg.RxStream > 2)) - { - // only 2 Rx streams for RT2860 series - pAd->CommonCfg.RxStream = 2; - } - } - - // 3*3 - // read value from EEPROM and set them to CSR174 ~ 177 in chain0 ~ chain2 - // yet implement - for(i=0; i<3; i++) - { - } - - NicConfig2.word = pAd->EEPROMDefaultValue[1]; - - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if ((NicConfig2.word & 0x00ff) == 0xff) - { - NicConfig2.word &= 0xff00; - } - - if ((NicConfig2.word >> 8) == 0xff) - { - NicConfig2.word &= 0x00ff; - } - } -#endif // CONFIG_STA_SUPPORT // - - if (NicConfig2.field.DynamicTxAgcControl == 1) - pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE; - else - pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE; - - DBGPRINT_RAW(RT_DEBUG_TRACE, ("NICReadEEPROMParameters: RxPath = %d, TxPath = %d\n", Antenna.field.RxPath, Antenna.field.TxPath)); - - // Save the antenna for future use - pAd->Antenna.word = Antenna.word; - - // Set the RfICType here, then we can initialize RFIC related operation callbacks - pAd->Mlme.RealRxPath = (UCHAR) Antenna.field.RxPath; - pAd->RfIcType = (UCHAR) Antenna.field.RfIcType; - -#ifdef RTMP_RF_RW_SUPPORT - RtmpChipOpsRFHook(pAd); -#endif // RTMP_RF_RW_SUPPORT // - - // - // Reset PhyMode if we don't support 802.11a - // Only RFIC_2850 & RFIC_2750 support 802.11a - // - if ((Antenna.field.RfIcType != RFIC_2850) - && (Antenna.field.RfIcType != RFIC_2750) - && (Antenna.field.RfIcType != RFIC_3052)) - { - if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) || - (pAd->CommonCfg.PhyMode == PHY_11A)) - pAd->CommonCfg.PhyMode = PHY_11BG_MIXED; -#ifdef DOT11_N_SUPPORT - else if ((pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || - (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) || - (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || - (pAd->CommonCfg.PhyMode == PHY_11N_5G)) - pAd->CommonCfg.PhyMode = PHY_11BGN_MIXED; -#endif // DOT11_N_SUPPORT // - } - - // Read TSSI reference and TSSI boundary for temperature compensation. This is ugly - // 0. 11b/g - { - /* these are tempature reference value (0x00 ~ 0xFE) - ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 - TssiPlusBoundaryG [4] [3] [2] [1] [0] (smaller) + - TssiMinusBoundaryG[0] [1] [2] [3] [4] (larger) */ - RT28xx_EEPROM_READ16(pAd, 0x6E, Power.word); - pAd->TssiMinusBoundaryG[4] = Power.field.Byte0; - pAd->TssiMinusBoundaryG[3] = Power.field.Byte1; - RT28xx_EEPROM_READ16(pAd, 0x70, Power.word); - pAd->TssiMinusBoundaryG[2] = Power.field.Byte0; - pAd->TssiMinusBoundaryG[1] = Power.field.Byte1; - RT28xx_EEPROM_READ16(pAd, 0x72, Power.word); - pAd->TssiRefG = Power.field.Byte0; /* reference value [0] */ - pAd->TssiPlusBoundaryG[1] = Power.field.Byte1; - RT28xx_EEPROM_READ16(pAd, 0x74, Power.word); - pAd->TssiPlusBoundaryG[2] = Power.field.Byte0; - pAd->TssiPlusBoundaryG[3] = Power.field.Byte1; - RT28xx_EEPROM_READ16(pAd, 0x76, Power.word); - pAd->TssiPlusBoundaryG[4] = Power.field.Byte0; - pAd->TxAgcStepG = Power.field.Byte1; - pAd->TxAgcCompensateG = 0; - pAd->TssiMinusBoundaryG[0] = pAd->TssiRefG; - pAd->TssiPlusBoundaryG[0] = pAd->TssiRefG; - - // Disable TxAgc if the based value is not right - if (pAd->TssiRefG == 0xff) - pAd->bAutoTxAgcG = FALSE; - - DBGPRINT(RT_DEBUG_TRACE,("E2PROM: G Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", - pAd->TssiMinusBoundaryG[4], pAd->TssiMinusBoundaryG[3], pAd->TssiMinusBoundaryG[2], pAd->TssiMinusBoundaryG[1], - pAd->TssiRefG, - pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4], - pAd->TxAgcStepG, pAd->bAutoTxAgcG)); - } - // 1. 11a - { - RT28xx_EEPROM_READ16(pAd, 0xD4, Power.word); - pAd->TssiMinusBoundaryA[4] = Power.field.Byte0; - pAd->TssiMinusBoundaryA[3] = Power.field.Byte1; - RT28xx_EEPROM_READ16(pAd, 0xD6, Power.word); - pAd->TssiMinusBoundaryA[2] = Power.field.Byte0; - pAd->TssiMinusBoundaryA[1] = Power.field.Byte1; - RT28xx_EEPROM_READ16(pAd, 0xD8, Power.word); - pAd->TssiRefA = Power.field.Byte0; - pAd->TssiPlusBoundaryA[1] = Power.field.Byte1; - RT28xx_EEPROM_READ16(pAd, 0xDA, Power.word); - pAd->TssiPlusBoundaryA[2] = Power.field.Byte0; - pAd->TssiPlusBoundaryA[3] = Power.field.Byte1; - RT28xx_EEPROM_READ16(pAd, 0xDC, Power.word); - pAd->TssiPlusBoundaryA[4] = Power.field.Byte0; - pAd->TxAgcStepA = Power.field.Byte1; - pAd->TxAgcCompensateA = 0; - pAd->TssiMinusBoundaryA[0] = pAd->TssiRefA; - pAd->TssiPlusBoundaryA[0] = pAd->TssiRefA; - - // Disable TxAgc if the based value is not right - if (pAd->TssiRefA == 0xff) - pAd->bAutoTxAgcA = FALSE; - - DBGPRINT(RT_DEBUG_TRACE,("E2PROM: A Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", - pAd->TssiMinusBoundaryA[4], pAd->TssiMinusBoundaryA[3], pAd->TssiMinusBoundaryA[2], pAd->TssiMinusBoundaryA[1], - pAd->TssiRefA, - pAd->TssiPlusBoundaryA[1], pAd->TssiPlusBoundaryA[2], pAd->TssiPlusBoundaryA[3], pAd->TssiPlusBoundaryA[4], - pAd->TxAgcStepA, pAd->bAutoTxAgcA)); - } - pAd->BbpRssiToDbmDelta = 0x0; - - // Read frequency offset setting for RF - RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, value); - if ((value & 0x00FF) != 0x00FF) - pAd->RfFreqOffset = (ULONG) (value & 0x00FF); - else - pAd->RfFreqOffset = 0; - DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: RF FreqOffset=0x%lx \n", pAd->RfFreqOffset)); - - //CountryRegion byte offset (38h) - value = pAd->EEPROMDefaultValue[2] >> 8; // 2.4G band - value2 = pAd->EEPROMDefaultValue[2] & 0x00FF; // 5G band - - if ((value <= REGION_MAXIMUM_BG_BAND) && (value2 <= REGION_MAXIMUM_A_BAND)) - { - pAd->CommonCfg.CountryRegion = ((UCHAR) value) | 0x80; - pAd->CommonCfg.CountryRegionForABand = ((UCHAR) value2) | 0x80; - TmpPhy = pAd->CommonCfg.PhyMode; - pAd->CommonCfg.PhyMode = 0xff; - RTMPSetPhyMode(pAd, TmpPhy); -#ifdef DOT11_N_SUPPORT - SetCommonHT(pAd); -#endif // DOT11_N_SUPPORT // - } - - // - // Get RSSI Offset on EEPROM 0x9Ah & 0x9Ch. - // The valid value are (-10 ~ 10) - // - RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, value); - pAd->BGRssiOffset0 = value & 0x00ff; - pAd->BGRssiOffset1 = (value >> 8); - RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET+2, value); - pAd->BGRssiOffset2 = value & 0x00ff; - pAd->ALNAGain1 = (value >> 8); - RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, value); - pAd->BLNAGain = value & 0x00ff; - pAd->ALNAGain0 = (value >> 8); - - // Validate 11b/g RSSI_0 offset. - if ((pAd->BGRssiOffset0 < -10) || (pAd->BGRssiOffset0 > 10)) - pAd->BGRssiOffset0 = 0; - - // Validate 11b/g RSSI_1 offset. - if ((pAd->BGRssiOffset1 < -10) || (pAd->BGRssiOffset1 > 10)) - pAd->BGRssiOffset1 = 0; - - // Validate 11b/g RSSI_2 offset. - if ((pAd->BGRssiOffset2 < -10) || (pAd->BGRssiOffset2 > 10)) - pAd->BGRssiOffset2 = 0; - - RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, value); - pAd->ARssiOffset0 = value & 0x00ff; - pAd->ARssiOffset1 = (value >> 8); - RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET+2), value); - pAd->ARssiOffset2 = value & 0x00ff; - pAd->ALNAGain2 = (value >> 8); - - if (((UCHAR)pAd->ALNAGain1 == 0xFF) || (pAd->ALNAGain1 == 0x00)) - pAd->ALNAGain1 = pAd->ALNAGain0; - if (((UCHAR)pAd->ALNAGain2 == 0xFF) || (pAd->ALNAGain2 == 0x00)) - pAd->ALNAGain2 = pAd->ALNAGain0; - - // Validate 11a RSSI_0 offset. - if ((pAd->ARssiOffset0 < -10) || (pAd->ARssiOffset0 > 10)) - pAd->ARssiOffset0 = 0; - - // Validate 11a RSSI_1 offset. - if ((pAd->ARssiOffset1 < -10) || (pAd->ARssiOffset1 > 10)) - pAd->ARssiOffset1 = 0; - - //Validate 11a RSSI_2 offset. - if ((pAd->ARssiOffset2 < -10) || (pAd->ARssiOffset2 > 10)) - pAd->ARssiOffset2 = 0; - -#ifdef RT30xx - // - // Get TX mixer gain setting - // 0xff are invalid value - // Note: RT30xX default value is 0x00 and will program to RF_R17 only when this value is not zero. - // RT359X default value is 0x02 - // - if (IS_RT30xx(pAd) || IS_RT3572(pAd)) - { - RT28xx_EEPROM_READ16(pAd, EEPROM_TXMIXER_GAIN_2_4G, value); - pAd->TxMixerGain24G = 0; - value &= 0x00ff; - if (value != 0xff) - { - value &= 0x07; - pAd->TxMixerGain24G = (UCHAR)value; - } - } -#endif // RT30xx // - - // - // Get LED Setting. - // - RT28xx_EEPROM_READ16(pAd, 0x3a, value); - pAd->LedCntl.word = (value>>8); - RT28xx_EEPROM_READ16(pAd, EEPROM_LED1_OFFSET, value); - pAd->Led1 = value; - RT28xx_EEPROM_READ16(pAd, EEPROM_LED2_OFFSET, value); - pAd->Led2 = value; - RT28xx_EEPROM_READ16(pAd, EEPROM_LED3_OFFSET, value); - pAd->Led3 = value; - - RTMPReadTxPwrPerRate(pAd); - -#ifdef SINGLE_SKU - RT28xx_EEPROM_READ16(pAd, EEPROM_DEFINE_MAX_TXPWR, pAd->CommonCfg.DefineMaxTxPwr); -#endif // SINGLE_SKU // - -#ifdef RT30xx -#ifdef RTMP_EFUSE_SUPPORT - RtmpEfuseSupportCheck(pAd); -#endif // RTMP_EFUSE_SUPPORT // -#endif // RT30xx // - - DBGPRINT(RT_DEBUG_TRACE, ("<-- NICReadEEPROMParameters\n")); -} - - -/* - ======================================================================== - - Routine Description: - Set default value from EEPROM - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - Note: - - ======================================================================== -*/ -VOID NICInitAsicFromEEPROM( - IN PRTMP_ADAPTER pAd) -{ -#ifdef CONFIG_STA_SUPPORT - UINT32 data = 0; - UCHAR BBPR1 = 0; -#endif // CONFIG_STA_SUPPORT // - USHORT i; -// EEPROM_ANTENNA_STRUC Antenna; - EEPROM_NIC_CONFIG2_STRUC NicConfig2; - UCHAR BBPR3 = 0; - - DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitAsicFromEEPROM\n")); - for(i = 3; i < NUM_EEPROM_BBP_PARMS; i++) - { - UCHAR BbpRegIdx, BbpValue; - - if ((pAd->EEPROMDefaultValue[i] != 0xFFFF) && (pAd->EEPROMDefaultValue[i] != 0)) - { - BbpRegIdx = (UCHAR)(pAd->EEPROMDefaultValue[i] >> 8); - BbpValue = (UCHAR)(pAd->EEPROMDefaultValue[i] & 0xff); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BbpRegIdx, BbpValue); - } - } - - - NicConfig2.word = pAd->EEPROMDefaultValue[1]; - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if ((NicConfig2.word & 0x00ff) == 0xff) - { - NicConfig2.word &= 0xff00; - } - - if ((NicConfig2.word >> 8) == 0xff) - { - NicConfig2.word &= 0x00ff; - } - } -#endif // CONFIG_STA_SUPPORT // - - // Save the antenna for future use - pAd->NicConfig2.word = NicConfig2.word; - -#ifdef RT30xx - // set default antenna as main - if (pAd->RfIcType == RFIC_3020) - AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); -#endif // RT30xx // - - // - // Send LED Setting to MCU. - // - if (pAd->LedCntl.word == 0xFF) - { - pAd->LedCntl.word = 0x01; - pAd->Led1 = 0x5555; - pAd->Led2 = 0x2221; - -#ifdef RTMP_MAC_PCI - pAd->Led3 = 0xA9F8; -#endif // RTMP_MAC_PCI // - } - - AsicSendCommandToMcu(pAd, 0x52, 0xff, (UCHAR)pAd->Led1, (UCHAR)(pAd->Led1 >> 8)); - AsicSendCommandToMcu(pAd, 0x53, 0xff, (UCHAR)pAd->Led2, (UCHAR)(pAd->Led2 >> 8)); - AsicSendCommandToMcu(pAd, 0x54, 0xff, (UCHAR)pAd->Led3, (UCHAR)(pAd->Led3 >> 8)); - AsicSendCommandToMcu(pAd, 0x51, 0xff, 0, pAd->LedCntl.field.Polarity); - - pAd->LedIndicatorStrength = 0xFF; - RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, before link up - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // Read Hardware controlled Radio state enable bit - if (NicConfig2.field.HardwareRadioControl == 1) - { - pAd->StaCfg.bHardwareRadio = TRUE; - - // Read GPIO pin2 as Hardware controlled radio state - RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data); - if ((data & 0x04) == 0) - { - pAd->StaCfg.bHwRadio = FALSE; - pAd->StaCfg.bRadio = FALSE; -// RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818); - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - } - } - else - pAd->StaCfg.bHardwareRadio = FALSE; - - if (pAd->StaCfg.bRadio == FALSE) - { - RTMPSetLED(pAd, LED_RADIO_OFF); - } - else - { - RTMPSetLED(pAd, LED_RADIO_ON); -#ifdef RTMP_MAC_PCI -#ifdef RT3090 - AsicSendCommandToMcu(pAd, 0x30, PowerRadioOffCID, 0xff, 0x02); - AsicCheckCommanOk(pAd, PowerRadioOffCID); -#endif // RT3090 // -#ifndef RT3090 - AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); -#endif // RT3090 // - AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x00); - // 2-1. wait command ok. - AsicCheckCommanOk(pAd, PowerWakeCID); -#endif // RTMP_MAC_PCI // - } - } -#ifdef RTMP_MAC_PCI -#ifdef RT30xx - if (IS_RT3090(pAd)|| IS_RT3572(pAd) || IS_RT3390(pAd)) - { - RTMP_CHIP_OP *pChipOps = &pAd->chipOps; - if (pChipOps->AsicReverseRfFromSleepMode) - pChipOps->AsicReverseRfFromSleepMode(pAd); - } - // 3090 MCU Wakeup command needs more time to be stable. - // Before stable, don't issue other MCU command to prevent from firmware error. - - if ((IS_RT3090(pAd)|| IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd) - && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) - && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) - { - DBGPRINT(RT_DEBUG_TRACE,("%s::%d,release Mcu Lock\n",__FUNCTION__,__LINE__)); - RTMP_SEM_LOCK(&pAd->McuCmdLock); - pAd->brt30xxBanMcuCmd = FALSE; - RTMP_SEM_UNLOCK(&pAd->McuCmdLock); - } -#endif // RT30xx // -#endif // RTMP_MAC_PCI // -#endif // CONFIG_STA_SUPPORT // - - // Turn off patching for cardbus controller - if (NicConfig2.field.CardbusAcceleration == 1) - { -// pAd->bTest1 = TRUE; - } - - if (NicConfig2.field.DynamicTxAgcControl == 1) - pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE; - else - pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE; - // - // Since BBP has been progamed, to make sure BBP setting will be - // upate inside of AsicAntennaSelect, so reset to UNKNOWN_BAND!! - // - pAd->CommonCfg.BandState = UNKNOWN_BAND; - - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); - BBPR3 &= (~0x18); - if(pAd->Antenna.field.RxPath == 3) - { - BBPR3 |= (0x10); - } - else if(pAd->Antenna.field.RxPath == 2) - { - BBPR3 |= (0x8); - } - else if(pAd->Antenna.field.RxPath == 1) - { - BBPR3 |= (0x0); - } - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // Handle the difference when 1T - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); - if(pAd->Antenna.field.TxPath == 1) - { - BBPR1 &= (~0x18); - } - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); - - DBGPRINT(RT_DEBUG_TRACE, ("Use Hw Radio Control Pin=%d; if used Pin=%d;\n", - pAd->CommonCfg.bHardwareRadio, pAd->CommonCfg.bHardwareRadio)); - } -#endif // CONFIG_STA_SUPPORT // - - - DBGPRINT(RT_DEBUG_TRACE, ("TxPath = %d, RxPath = %d, RFIC=%d, Polar+LED mode=%x\n", - pAd->Antenna.field.TxPath, pAd->Antenna.field.RxPath, - pAd->RfIcType, pAd->LedCntl.word)); - DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitAsicFromEEPROM\n")); -} - -/* - ======================================================================== - - Routine Description: - Initialize NIC hardware - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - Note: - - ======================================================================== -*/ -NDIS_STATUS NICInitializeAdapter( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bHardReset) -{ - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - WPDMA_GLO_CFG_STRUC GloCfg; -#ifdef RTMP_MAC_PCI - UINT32 Value; - DELAY_INT_CFG_STRUC IntCfg; -#endif // RTMP_MAC_PCI // -// INT_MASK_CSR_STRUC IntMask; - ULONG i =0, j=0; - AC_TXOP_CSR0_STRUC csr0; - - DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAdapter\n")); - - // 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits: -retry: - i = 0; - do - { - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); - if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) - break; - - RTMPusecDelay(1000); - i++; - }while ( i<100); - DBGPRINT(RT_DEBUG_TRACE, ("<== DMA offset 0x208 = 0x%x\n", GloCfg.word)); - GloCfg.word &= 0xff0; - GloCfg.field.EnTXWriteBackDDONE =1; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); - - // Record HW Beacon offset - pAd->BeaconOffset[0] = HW_BEACON_BASE0; - pAd->BeaconOffset[1] = HW_BEACON_BASE1; - pAd->BeaconOffset[2] = HW_BEACON_BASE2; - pAd->BeaconOffset[3] = HW_BEACON_BASE3; - pAd->BeaconOffset[4] = HW_BEACON_BASE4; - pAd->BeaconOffset[5] = HW_BEACON_BASE5; - pAd->BeaconOffset[6] = HW_BEACON_BASE6; - pAd->BeaconOffset[7] = HW_BEACON_BASE7; - - // - // write all shared Ring's base address into ASIC - // - - // asic simulation sequence put this ahead before loading firmware. - // pbf hardware reset -#ifdef RTMP_MAC_PCI - RTMP_IO_WRITE32(pAd, WPDMA_RST_IDX, 0x1003f); // 0x10000 for reset rx, 0x3f resets all 6 tx rings. - RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe1f); - RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe00); -#endif // RTMP_MAC_PCI // - - // Initialze ASIC for TX & Rx operation - if (NICInitializeAsic(pAd , bHardReset) != NDIS_STATUS_SUCCESS) - { - if (j++ == 0) - { - NICLoadFirmware(pAd); - goto retry; - } - return NDIS_STATUS_FAILURE; - } - - -#ifdef RTMP_MAC_PCI - // Write AC_BK base address register - Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BK].Cell[0].AllocPa); - RTMP_IO_WRITE32(pAd, TX_BASE_PTR1, Value); - DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR1 : 0x%x\n", Value)); - - // Write AC_BE base address register - Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BE].Cell[0].AllocPa); - RTMP_IO_WRITE32(pAd, TX_BASE_PTR0, Value); - DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR0 : 0x%x\n", Value)); - - // Write AC_VI base address register - Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VI].Cell[0].AllocPa); - RTMP_IO_WRITE32(pAd, TX_BASE_PTR2, Value); - DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR2 : 0x%x\n", Value)); - - // Write AC_VO base address register - Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VO].Cell[0].AllocPa); - RTMP_IO_WRITE32(pAd, TX_BASE_PTR3, Value); - DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR3 : 0x%x\n", Value)); - - // Write HCCA base address register - /* - Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_HCCA].Cell[0].AllocPa); - RTMP_IO_WRITE32(pAd, TX_BASE_PTR4, Value); - DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR4 : 0x%x\n", Value)); - */ - - // Write MGMT_BASE_CSR register - Value = RTMP_GetPhysicalAddressLow(pAd->MgmtRing.Cell[0].AllocPa); - RTMP_IO_WRITE32(pAd, TX_BASE_PTR5, Value); - DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR5 : 0x%x\n", Value)); - - // Write RX_BASE_CSR register - Value = RTMP_GetPhysicalAddressLow(pAd->RxRing.Cell[0].AllocPa); - RTMP_IO_WRITE32(pAd, RX_BASE_PTR, Value); - DBGPRINT(RT_DEBUG_TRACE, ("--> RX_BASE_PTR : 0x%x\n", Value)); - - // Init RX Ring index pointer - pAd->RxRing.RxSwReadIdx = 0; - pAd->RxRing.RxCpuIdx = RX_RING_SIZE-1; - RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); - - // Init TX rings index pointer - { - for (i=0; iTxRing[i].TxSwFreeIdx = 0; - pAd->TxRing[i].TxCpuIdx = 0; - RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10) , pAd->TxRing[i].TxCpuIdx); - } - } - - // init MGMT ring index pointer - pAd->MgmtRing.TxSwFreeIdx = 0; - pAd->MgmtRing.TxCpuIdx = 0; - RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); - - // - // set each Ring's SIZE into ASIC. Descriptor Size is fixed by design. - // - - // Write TX_RING_CSR0 register - Value = TX_RING_SIZE; - RTMP_IO_WRITE32(pAd, TX_MAX_CNT0, Value); - RTMP_IO_WRITE32(pAd, TX_MAX_CNT1, Value); - RTMP_IO_WRITE32(pAd, TX_MAX_CNT2, Value); - RTMP_IO_WRITE32(pAd, TX_MAX_CNT3, Value); - RTMP_IO_WRITE32(pAd, TX_MAX_CNT4, Value); - Value = MGMT_RING_SIZE; - RTMP_IO_WRITE32(pAd, TX_MGMTMAX_CNT, Value); - - // Write RX_RING_CSR register - Value = RX_RING_SIZE; - RTMP_IO_WRITE32(pAd, RX_MAX_CNT, Value); -#endif // RTMP_MAC_PCI // - - - // WMM parameter - csr0.word = 0; - RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); - if (pAd->CommonCfg.PhyMode == PHY_11B) - { - csr0.field.Ac0Txop = 192; // AC_VI: 192*32us ~= 6ms - csr0.field.Ac1Txop = 96; // AC_VO: 96*32us ~= 3ms - } - else - { - csr0.field.Ac0Txop = 96; // AC_VI: 96*32us ~= 3ms - csr0.field.Ac1Txop = 48; // AC_VO: 48*32us ~= 1.5ms - } - RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr0.word); - - -#ifdef RTMP_MAC_PCI - // 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits: - i = 0; - do - { - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); - if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) - break; - - RTMPusecDelay(1000); - i++; - }while ( i < 100); - - GloCfg.word &= 0xff0; - GloCfg.field.EnTXWriteBackDDONE =1; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); - - IntCfg.word = 0; - RTMP_IO_WRITE32(pAd, DELAY_INT_CFG, IntCfg.word); -#endif // RTMP_MAC_PCI // - - - // reset action - // Load firmware - // Status = NICLoadFirmware(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAdapter\n")); - return Status; -} - -/* - ======================================================================== - - Routine Description: - Initialize ASIC - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - Note: - - ======================================================================== -*/ -NDIS_STATUS NICInitializeAsic( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bHardReset) -{ - ULONG Index = 0; - UCHAR R0 = 0xff; - UINT32 MacCsr12 = 0, Counter = 0; -#ifdef RT30xx - UCHAR bbpreg=0; - UCHAR RFValue=0; -#endif // RT30xx // - USHORT KeyIdx; - INT i,apidx; - - DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAsic\n")); - -#ifdef RTMP_MAC_PCI - RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x3); // To fix driver disable/enable hang issue when radio off - if (bHardReset == TRUE) - { - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3); - } - else - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); - - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); - // Initialize MAC register to default value - for (Index = 0; Index < NUM_MAC_REG_PARMS; Index++) - { -#ifdef RT30xx - if ((MACRegTable[Index].Register == TX_SW_CFG0) && ( IS_RT3090(pAd) || IS_RT3390(pAd))) - { - MACRegTable[Index].Value = 0x00000400; - } -#endif // RT30xx // - RTMP_IO_WRITE32(pAd, MACRegTable[Index].Register, MACRegTable[Index].Value); - } - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - for (Index = 0; Index < NUM_STA_MAC_REG_PARMS; Index++) - { - RTMP_IO_WRITE32(pAd, STAMACRegTable[Index].Register, STAMACRegTable[Index].Value); - } - } -#endif // CONFIG_STA_SUPPORT // -#endif // RTMP_MAC_PCI // - - -#ifdef RT30xx - // Initialize RT3070 serial MAC registers which is different from RT2870 serial - if (IS_RT3090(pAd) || IS_RT3572(pAd)||IS_RT3390(pAd)) - { - RTMP_IO_WRITE32(pAd, TX_SW_CFG1, 0); - - // RT3071 version E has fixed this issue - if ((pAd->MACVersion & 0xffff) < 0x0211) - { - if (pAd->NicConfig2.field.DACTestBit == 1) - { - RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x2C); // To fix throughput drop drastically - } - else - { - RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x0F); // To fix throughput drop drastically - } - } - else - { - RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x0); - } - } - else if (IS_RT3070(pAd)) - { - if (((pAd->MACVersion & 0xffff) < 0x0201)) - { - RTMP_IO_WRITE32(pAd, TX_SW_CFG1, 0); - RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x2C); // To fix throughput drop drastically - } - else - { - RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0); - } - } -#endif // RT30xx // - - // - // Before program BBP, we need to wait BBP/RF get wake up. - // - Index = 0; - do - { - RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacCsr12); - - if ((MacCsr12 & 0x03) == 0) // if BB.RF is stable - break; - - DBGPRINT(RT_DEBUG_TRACE, ("Check MAC_STATUS_CFG = Busy = %x\n", MacCsr12)); - RTMPusecDelay(1000); - } while (Index++ < 100); - - // The commands to firmware should be after these commands, these commands will init firmware - // PCI and USB are not the same because PCI driver needs to wait for PCI bus ready - RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, 0); // initialize BBP R/W access agent - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, 0); -#ifdef RT3090 - //2008/11/28:KH add to fix the dead rf frequency offset bug<-- - AsicSendCommandToMcu(pAd, 0x72, 0, 0, 0); - //2008/11/28:KH add to fix the dead rf frequency offset bug--> -#endif // RT3090 // - RTMPusecDelay(1000); - - // Read BBP register, make sure BBP is up and running before write new data - Index = 0; - do - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R0, &R0); - DBGPRINT(RT_DEBUG_TRACE, ("BBP version = %x\n", R0)); - } while ((++Index < 20) && ((R0 == 0xff) || (R0 == 0x00))); - //ASSERT(Index < 20); //this will cause BSOD on Check-build driver - - if ((R0 == 0xff) || (R0 == 0x00)) - return NDIS_STATUS_FAILURE; - - // Initialize BBP register to default value - for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, BBPRegTable[Index].Value); - } - -#ifdef RTMP_MAC_PCI - // TODO: shiang, check MACVersion, currently, rbus-based chip use this. - if (pAd->MACVersion == 0x28720200) - { - //UCHAR value; - ULONG value2; - - //disable MLD by Bruce 20080704 - //BBP_IO_READ8_BY_REG_ID(pAd, BBP_R105, &value); - //BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R105, value | 4); - - //Maximum PSDU length from 16K to 32K bytes - RTMP_IO_READ32(pAd, MAX_LEN_CFG, &value2); - value2 &= ~(0x3<<12); - value2 |= (0x2<<12); - RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, value2); - } -#endif // RTMP_MAC_PCI // - - // for rt2860E and after, init BBP_R84 with 0x19. This is for extension channel overlapping IOT. - // RT3090 should not program BBP R84 to 0x19, otherwise TX will block. - //3070/71/72,3090,3090A( are included in RT30xx),3572,3390 - if (((pAd->MACVersion & 0xffff) != 0x0101) && !(IS_RT30xx(pAd)|| IS_RT3572(pAd) || IS_RT3390(pAd))) - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R84, 0x19); - -#ifdef RT30xx -// add by johnli, RF power sequence setup - if (IS_RT30xx(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) - { //update for RT3070/71/72/90/91/92,3572,3390. - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R79, 0x13); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R80, 0x05); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R81, 0x33); - } - - if (IS_RT3090(pAd)||IS_RT3390(pAd)) // RT309x, RT3071/72 - { - // enable DC filter - if ((pAd->MACVersion & 0xffff) >= 0x0211) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R103, 0xc0); - } - - // improve power consumption - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R138, &bbpreg); - if (pAd->Antenna.field.TxPath == 1) - { - // turn off tx DAC_1 - bbpreg = (bbpreg | 0x20); - } - - if (pAd->Antenna.field.RxPath == 1) - { - // turn off tx ADC_1 - bbpreg &= (~0x2); - } - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R138, bbpreg); - - // improve power consumption in RT3071 Ver.E - if ((pAd->MACVersion & 0xffff) >= 0x0211) - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R31, &bbpreg); - bbpreg &= (~0x3); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R31, bbpreg); - } - } - else if (IS_RT3070(pAd)) - { - if ((pAd->MACVersion & 0xffff) >= 0x0201) - { - // enable DC filter - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R103, 0xc0); - - // improve power consumption in RT3070 Ver.F - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R31, &bbpreg); - bbpreg &= (~0x3); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R31, bbpreg); - } - - // TX_LO1_en, RF R17 register Bit 3 to 0 - RT30xxReadRFRegister(pAd, RF_R17, &RFValue); - RFValue &= (~0x08); - // to fix rx long range issue - if (pAd->NicConfig2.field.ExternalLNAForG == 0) - { - RFValue |= 0x20; - } - // set RF_R17_bit[2:0] equal to EEPROM setting at 0x48h - if (pAd->TxMixerGain24G >= 1) - { - RFValue &= (~0x7); // clean bit [2:0] - RFValue |= pAd->TxMixerGain24G; - } - RT30xxWriteRFRegister(pAd, RF_R17, RFValue); - } -// end johnli -#endif // RT30xx // - - if (pAd->MACVersion == 0x28600100) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x12); - } - - if (pAd->MACVersion >= RALINK_2880E_VERSION && pAd->MACVersion < RALINK_3070_VERSION) // 3*3 - { - // enlarge MAX_LEN_CFG - UINT32 csr; - RTMP_IO_READ32(pAd, MAX_LEN_CFG, &csr); - csr &= 0xFFF; - csr |= 0x2000; - RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, csr); - } - - -#ifdef CONFIG_STA_SUPPORT - // Add radio off control - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (pAd->StaCfg.bRadio == FALSE) - { -// RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818); - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - DBGPRINT(RT_DEBUG_TRACE, ("Set Radio Off\n")); - } - } -#endif // CONFIG_STA_SUPPORT // - - // Clear raw counters - RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter); - RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter); - RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter); - RTMP_IO_READ32(pAd, TX_STA_CNT0, &Counter); - RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter); - RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter); - - // ASIC will keep garbage value after boot - // Clear all shared key table when initial - // This routine can be ignored in radio-ON/OFF operation. - if (bHardReset) - { - for (KeyIdx = 0; KeyIdx < 4; KeyIdx++) - { - RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4*KeyIdx, 0); - } - - // Clear all pairwise key table when initial - for (KeyIdx = 0; KeyIdx < 256; KeyIdx++) - { - RTMP_IO_WRITE32(pAd, MAC_WCID_ATTRIBUTE_BASE + (KeyIdx * HW_WCID_ATTRI_SIZE), 1); - } - } - - // assert HOST ready bit -// RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x0); // 2004-09-14 asked by Mark -// RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x4); - - // It isn't necessary to clear this space when not hard reset. - if (bHardReset == TRUE) - { - // clear all on-chip BEACON frame space - for (apidx = 0; apidx < HW_BEACON_MAX_COUNT; apidx++) - { - for (i = 0; i < HW_BEACON_OFFSET>>2; i+=4) - RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[apidx] + i, 0x00); - } - } - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // for rt2860E and after, init TXOP_CTRL_CFG with 0x583f. This is for extension channel overlapping IOT. - if ((pAd->MACVersion&0xffff) != 0x0101) - RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x583f); - } -#endif // CONFIG_STA_SUPPORT // - -#ifdef RT30xx -#ifdef NEW_FW - if (IS_RT3070(pAd) || IS_RT3572(pAd)||IS_RT3390(pAd)||IS_RT3090(pAd)) - { - // send 0x36 mcu command after 0x72 for RT3xxx to fix Radio-Off current leakage issue - RTMPusecDelay(200); - if (pAd->buseEfuse) - AsicSendCommandToMcu(pAd, 0x36, 0xff, 0xff, 0); - else - AsicSendCommandToMcu(pAd, 0x36, 0xff, 0xff, 0x04); - RTMPusecDelay(10); - } -#endif // NEW_FW // -#endif // RT30xx // - - DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAsic\n")); - return NDIS_STATUS_SUCCESS; -} - -/* - ======================================================================== - - Routine Description: - Reset NIC Asics - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - Note: - Reset NIC to initial state AS IS system boot up time. - - ======================================================================== -*/ -VOID NICIssueReset( - IN PRTMP_ADAPTER pAd) -{ - UINT32 Value = 0; - DBGPRINT(RT_DEBUG_TRACE, ("--> NICIssueReset\n")); - - // Abort Tx, prevent ASIC from writing to Host memory - //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x001f0000); - - // Disable Rx, register value supposed will remain after reset - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value &= (0xfffffff3); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - - // Issue reset and clear from reset state - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x03); // 2004-09-17 change from 0x01 - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); - - DBGPRINT(RT_DEBUG_TRACE, ("<-- NICIssueReset\n")); -} - -/* - ======================================================================== - - Routine Description: - Check ASIC registers and find any reason the system might hang - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - ======================================================================== -*/ -BOOLEAN NICCheckForHang( - IN PRTMP_ADAPTER pAd) -{ - return (FALSE); -} - -VOID NICUpdateFifoStaCounters( - IN PRTMP_ADAPTER pAd) -{ - TX_STA_FIFO_STRUC StaFifo; - MAC_TABLE_ENTRY *pEntry; - UCHAR i = 0; - UCHAR pid = 0, wcid = 0; - CHAR reTry; - UCHAR succMCS; - -#ifdef RALINK_ATE - /* Nothing to do in ATE mode */ - if (ATE_ON(pAd)) - return; -#endif // RALINK_ATE // - - do - { - RTMP_IO_READ32(pAd, TX_STA_FIFO, &StaFifo.word); - - if (StaFifo.field.bValid == 0) - break; - - wcid = (UCHAR)StaFifo.field.wcid; - - - /* ignore NoACK and MGMT frame use 0xFF as WCID */ - if ((StaFifo.field.TxAckRequired == 0) || (wcid >= MAX_LEN_OF_MAC_TABLE)) - { - i++; - continue; - } - - /* PID store Tx MCS Rate */ - pid = (UCHAR)StaFifo.field.PidType; - - pEntry = &pAd->MacTab.Content[wcid]; - - pEntry->DebugFIFOCount++; - -#ifdef DOT11_N_SUPPORT - if (StaFifo.field.TxBF) // 3*3 - pEntry->TxBFCount++; -#endif // DOT11_N_SUPPORT // - -#ifdef UAPSD_AP_SUPPORT - UAPSD_SP_AUE_Handle(pAd, pEntry, StaFifo.field.TxSuccess); -#endif // UAPSD_AP_SUPPORT // - - if (!StaFifo.field.TxSuccess) - { - pEntry->FIFOCount++; - pEntry->OneSecTxFailCount++; - - if (pEntry->FIFOCount >= 1) - { - DBGPRINT(RT_DEBUG_TRACE, ("#")); -#ifdef DOT11_N_SUPPORT - pEntry->NoBADataCountDown = 64; -#endif // DOT11_N_SUPPORT // - - if(pEntry->PsMode == PWR_ACTIVE) - { -#ifdef DOT11_N_SUPPORT - int tid; - for (tid=0; tidAid, tid, FALSE, FALSE); - } -#endif // DOT11_N_SUPPORT // - - // Update the continuous transmission counter except PS mode - pEntry->ContinueTxFailCnt++; - -#ifdef WDS_SUPPORT - // fix WDS Jam issue - if((pEntry->ValidAsWDS == TRUE) - && (pEntry->LockEntryTx == FALSE) - && (pEntry->ContinueTxFailCnt >= pAd->ApCfg.EntryLifeCheck)) - { - DBGPRINT(RT_DEBUG_TRACE, ("Entry %02x:%02x:%02x:%02x:%02x:%02x Blocked!! (Fail Cnt = %d)\n", - pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2],pEntry->Addr[3], - pEntry->Addr[4],pEntry->Addr[5],pEntry->ContinueTxFailCnt )); - - pEntry->LockEntryTx = TRUE; - } -#endif // WDS_SUPPORT // - } - else - { - // Clear the FIFOCount when sta in Power Save mode. Basically we assume - // this tx error happened due to sta just go to sleep. - pEntry->FIFOCount = 0; - pEntry->ContinueTxFailCnt = 0; - } - //pEntry->FIFOCount = 0; - } - //pEntry->bSendBAR = TRUE; - } - else - { -#ifdef DOT11_N_SUPPORT - if ((pEntry->PsMode != PWR_SAVE) && (pEntry->NoBADataCountDown > 0)) - { - pEntry->NoBADataCountDown--; - if (pEntry->NoBADataCountDown==0) - { - DBGPRINT(RT_DEBUG_TRACE, ("@\n")); - } - } -#endif // DOT11_N_SUPPORT // - pEntry->FIFOCount = 0; - pEntry->OneSecTxNoRetryOkCount++; - // update NoDataIdleCount when sucessful send packet to STA. - pEntry->NoDataIdleCount = 0; - pEntry->ContinueTxFailCnt = 0; -#ifdef WDS_SUPPORT - pEntry->LockEntryTx = FALSE; -#endif // WDS_SUPPORT // - } - - succMCS = StaFifo.field.SuccessRate & 0x7F; - - reTry = pid - succMCS; - - if (StaFifo.field.TxSuccess) - { - pEntry->TXMCSExpected[pid]++; - if (pid == succMCS) - { - pEntry->TXMCSSuccessful[pid]++; - } - else - { - pEntry->TXMCSAutoFallBack[pid][succMCS]++; - } - } - else - { - pEntry->TXMCSFailed[pid]++; - } - - if (reTry > 0) - { - if ((pid >= 12) && succMCS <=7) - { - reTry -= 4; - } - pEntry->OneSecTxRetryOkCount += reTry; - } - - i++; - // ASIC store 16 stack - } while ( i < (TX_RING_SIZE<<1) ); - -} - -/* - ======================================================================== - - Routine Description: - Read statistical counters from hardware registers and record them - in software variables for later on query - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - ======================================================================== -*/ -VOID NICUpdateRawCounters( - IN PRTMP_ADAPTER pAd) -{ - UINT32 OldValue;//, Value2; - //ULONG PageSum, OneSecTransmitCount; - //ULONG TxErrorRatio, Retry, Fail; - RX_STA_CNT0_STRUC RxStaCnt0; - RX_STA_CNT1_STRUC RxStaCnt1; - RX_STA_CNT2_STRUC RxStaCnt2; - TX_STA_CNT0_STRUC TxStaCnt0; - TX_STA_CNT1_STRUC StaTx1; - TX_STA_CNT2_STRUC StaTx2; - TX_AGG_CNT_STRUC TxAggCnt; - TX_AGG_CNT0_STRUC TxAggCnt0; - TX_AGG_CNT1_STRUC TxAggCnt1; - TX_AGG_CNT2_STRUC TxAggCnt2; - TX_AGG_CNT3_STRUC TxAggCnt3; - TX_AGG_CNT4_STRUC TxAggCnt4; - TX_AGG_CNT5_STRUC TxAggCnt5; - TX_AGG_CNT6_STRUC TxAggCnt6; - TX_AGG_CNT7_STRUC TxAggCnt7; - COUNTER_RALINK *pRalinkCounters; - - - pRalinkCounters = &pAd->RalinkCounters; - - RTMP_IO_READ32(pAd, RX_STA_CNT0, &RxStaCnt0.word); - RTMP_IO_READ32(pAd, RX_STA_CNT2, &RxStaCnt2.word); - - { - RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word); - // Update RX PLCP error counter - pAd->PrivateInfo.PhyRxErrCnt += RxStaCnt1.field.PlcpErr; - // Update False CCA counter - pAd->RalinkCounters.OneSecFalseCCACnt += RxStaCnt1.field.FalseCca; - } - - // Update FCS counters - OldValue= pAd->WlanCounters.FCSErrorCount.u.LowPart; - pAd->WlanCounters.FCSErrorCount.u.LowPart += (RxStaCnt0.field.CrcErr); // >> 7); - if (pAd->WlanCounters.FCSErrorCount.u.LowPart < OldValue) - pAd->WlanCounters.FCSErrorCount.u.HighPart++; - - // Add FCS error count to private counters - pRalinkCounters->OneSecRxFcsErrCnt += RxStaCnt0.field.CrcErr; - OldValue = pRalinkCounters->RealFcsErrCount.u.LowPart; - pRalinkCounters->RealFcsErrCount.u.LowPart += RxStaCnt0.field.CrcErr; - if (pRalinkCounters->RealFcsErrCount.u.LowPart < OldValue) - pRalinkCounters->RealFcsErrCount.u.HighPart++; - - // Update Duplicate Rcv check - pRalinkCounters->DuplicateRcv += RxStaCnt2.field.RxDupliCount; - pAd->WlanCounters.FrameDuplicateCount.u.LowPart += RxStaCnt2.field.RxDupliCount; - // Update RX Overflow counter - pAd->Counters8023.RxNoBuffer += (RxStaCnt2.field.RxFifoOverflowCount); - - //pAd->RalinkCounters.RxCount = 0; - - - //if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) || - // (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) && (pAd->MacTab.Size != 1))) - if (!pAd->bUpdateBcnCntDone) - { - // Update BEACON sent count - RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); - RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); - RTMP_IO_READ32(pAd, TX_STA_CNT2, &StaTx2.word); - pRalinkCounters->OneSecBeaconSentCnt += TxStaCnt0.field.TxBeaconCount; - pRalinkCounters->OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; - pRalinkCounters->OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; - pRalinkCounters->OneSecTxFailCount += TxStaCnt0.field.TxFailCount; - pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; - pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; - pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; - } - - - //if (pAd->bStaFifoTest == TRUE) - { - RTMP_IO_READ32(pAd, TX_AGG_CNT, &TxAggCnt.word); - RTMP_IO_READ32(pAd, TX_AGG_CNT0, &TxAggCnt0.word); - RTMP_IO_READ32(pAd, TX_AGG_CNT1, &TxAggCnt1.word); - RTMP_IO_READ32(pAd, TX_AGG_CNT2, &TxAggCnt2.word); - RTMP_IO_READ32(pAd, TX_AGG_CNT3, &TxAggCnt3.word); - RTMP_IO_READ32(pAd, TX_AGG_CNT4, &TxAggCnt4.word); - RTMP_IO_READ32(pAd, TX_AGG_CNT5, &TxAggCnt5.word); - RTMP_IO_READ32(pAd, TX_AGG_CNT6, &TxAggCnt6.word); - RTMP_IO_READ32(pAd, TX_AGG_CNT7, &TxAggCnt7.word); - pRalinkCounters->TxAggCount += TxAggCnt.field.AggTxCount; - pRalinkCounters->TxNonAggCount += TxAggCnt.field.NonAggTxCount; - pRalinkCounters->TxAgg1MPDUCount += TxAggCnt0.field.AggSize1Count; - pRalinkCounters->TxAgg2MPDUCount += TxAggCnt0.field.AggSize2Count; - - pRalinkCounters->TxAgg3MPDUCount += TxAggCnt1.field.AggSize3Count; - pRalinkCounters->TxAgg4MPDUCount += TxAggCnt1.field.AggSize4Count; - pRalinkCounters->TxAgg5MPDUCount += TxAggCnt2.field.AggSize5Count; - pRalinkCounters->TxAgg6MPDUCount += TxAggCnt2.field.AggSize6Count; - - pRalinkCounters->TxAgg7MPDUCount += TxAggCnt3.field.AggSize7Count; - pRalinkCounters->TxAgg8MPDUCount += TxAggCnt3.field.AggSize8Count; - pRalinkCounters->TxAgg9MPDUCount += TxAggCnt4.field.AggSize9Count; - pRalinkCounters->TxAgg10MPDUCount += TxAggCnt4.field.AggSize10Count; - - pRalinkCounters->TxAgg11MPDUCount += TxAggCnt5.field.AggSize11Count; - pRalinkCounters->TxAgg12MPDUCount += TxAggCnt5.field.AggSize12Count; - pRalinkCounters->TxAgg13MPDUCount += TxAggCnt6.field.AggSize13Count; - pRalinkCounters->TxAgg14MPDUCount += TxAggCnt6.field.AggSize14Count; - - pRalinkCounters->TxAgg15MPDUCount += TxAggCnt7.field.AggSize15Count; - pRalinkCounters->TxAgg16MPDUCount += TxAggCnt7.field.AggSize16Count; - - // Calculate the transmitted A-MPDU count - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += TxAggCnt0.field.AggSize1Count; - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt0.field.AggSize2Count / 2); - - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize3Count / 3); - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize4Count / 4); - - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize5Count / 5); - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize6Count / 6); - - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize7Count / 7); - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize8Count / 8); - - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize9Count / 9); - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize10Count / 10); - - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize11Count / 11); - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize12Count / 12); - - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize13Count / 13); - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize14Count / 14); - - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize15Count / 15); - pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize16Count / 16); - } - -#ifdef DBG_DIAGNOSE - { - RtmpDiagStruct *pDiag; - UCHAR ArrayCurIdx, i; - - pDiag = &pAd->DiagStruct; - ArrayCurIdx = pDiag->ArrayCurIdx; - - if (pDiag->inited == 0) - { - NdisZeroMemory(pDiag, sizeof(struct _RtmpDiagStrcut_)); - pDiag->ArrayStartIdx = pDiag->ArrayCurIdx = 0; - pDiag->inited = 1; - } - else - { - // Tx - pDiag->TxFailCnt[ArrayCurIdx] = TxStaCnt0.field.TxFailCount; - pDiag->TxAggCnt[ArrayCurIdx] = TxAggCnt.field.AggTxCount; - pDiag->TxNonAggCnt[ArrayCurIdx] = TxAggCnt.field.NonAggTxCount; - pDiag->TxAMPDUCnt[ArrayCurIdx][0] = TxAggCnt0.field.AggSize1Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][1] = TxAggCnt0.field.AggSize2Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][2] = TxAggCnt1.field.AggSize3Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][3] = TxAggCnt1.field.AggSize4Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][4] = TxAggCnt2.field.AggSize5Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][5] = TxAggCnt2.field.AggSize6Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][6] = TxAggCnt3.field.AggSize7Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][7] = TxAggCnt3.field.AggSize8Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][8] = TxAggCnt4.field.AggSize9Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][9] = TxAggCnt4.field.AggSize10Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][10] = TxAggCnt5.field.AggSize11Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][11] = TxAggCnt5.field.AggSize12Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][12] = TxAggCnt6.field.AggSize13Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][13] = TxAggCnt6.field.AggSize14Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][14] = TxAggCnt7.field.AggSize15Count; - pDiag->TxAMPDUCnt[ArrayCurIdx][15] = TxAggCnt7.field.AggSize16Count; - - pDiag->RxCrcErrCnt[ArrayCurIdx] = RxStaCnt0.field.CrcErr; - - INC_RING_INDEX(pDiag->ArrayCurIdx, DIAGNOSE_TIME); - ArrayCurIdx = pDiag->ArrayCurIdx; - for (i =0; i < 9; i++) - { - pDiag->TxDescCnt[ArrayCurIdx][i]= 0; - pDiag->TxSWQueCnt[ArrayCurIdx][i] =0; - pDiag->TxMcsCnt[ArrayCurIdx][i] = 0; - pDiag->RxMcsCnt[ArrayCurIdx][i] = 0; - } - pDiag->TxDataCnt[ArrayCurIdx] = 0; - pDiag->TxFailCnt[ArrayCurIdx] = 0; - pDiag->RxDataCnt[ArrayCurIdx] = 0; - pDiag->RxCrcErrCnt[ArrayCurIdx] = 0; -// for (i = 9; i < 16; i++) - for (i = 9; i < 24; i++) // 3*3 - { - pDiag->TxDescCnt[ArrayCurIdx][i] = 0; - pDiag->TxMcsCnt[ArrayCurIdx][i] = 0; - pDiag->RxMcsCnt[ArrayCurIdx][i] = 0; -} - - if (pDiag->ArrayCurIdx == pDiag->ArrayStartIdx) - INC_RING_INDEX(pDiag->ArrayStartIdx, DIAGNOSE_TIME); - } - - } -#endif // DBG_DIAGNOSE // - - -} - - -/* - ======================================================================== - - Routine Description: - Reset NIC from error - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - Note: - Reset NIC from error state - - ======================================================================== -*/ -VOID NICResetFromError( - IN PRTMP_ADAPTER pAd) -{ - // Reset BBP (according to alex, reset ASIC will force reset BBP - // Therefore, skip the reset BBP - // RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x2); - - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); - // Remove ASIC from reset state - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); - - NICInitializeAdapter(pAd, FALSE); - NICInitAsicFromEEPROM(pAd); - - // Switch to current channel, since during reset process, the connection should remains on. - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); -} - - -NDIS_STATUS NICLoadFirmware( - IN PRTMP_ADAPTER pAd) -{ - NDIS_STATUS status = NDIS_STATUS_SUCCESS; - if (pAd->chipOps.loadFirmware) - status = pAd->chipOps.loadFirmware(pAd); - - return status; -} - - -/* - ======================================================================== - - Routine Description: - erase 8051 firmware image in MAC ASIC - - Arguments: - Adapter Pointer to our adapter - - IRQL = PASSIVE_LEVEL - - ======================================================================== -*/ -VOID NICEraseFirmware( - IN PRTMP_ADAPTER pAd) -{ - if (pAd->chipOps.eraseFirmware) - pAd->chipOps.eraseFirmware(pAd); - -}/* End of NICEraseFirmware */ - - -/* - ======================================================================== - - Routine Description: - Load Tx rate switching parameters - - Arguments: - Adapter Pointer to our adapter - - Return Value: - NDIS_STATUS_SUCCESS firmware image load ok - NDIS_STATUS_FAILURE image not found - - IRQL = PASSIVE_LEVEL - - Rate Table Format: - 1. (B0: Valid Item number) (B1:Initial item from zero) - 2. Item Number(Dec) Mode(Hex) Current MCS(Dec) TrainUp(Dec) TrainDown(Dec) - - ======================================================================== -*/ -NDIS_STATUS NICLoadRateSwitchingParams( - IN PRTMP_ADAPTER pAd) -{ - return NDIS_STATUS_SUCCESS; -} - - -/* - ======================================================================== - - Routine Description: - Compare two memory block - - Arguments: - pSrc1 Pointer to first memory address - pSrc2 Pointer to second memory address - - Return Value: - 0: memory is equal - 1: pSrc1 memory is larger - 2: pSrc2 memory is larger - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -ULONG RTMPCompareMemory( - IN PVOID pSrc1, - IN PVOID pSrc2, - IN ULONG Length) -{ - PUCHAR pMem1; - PUCHAR pMem2; - ULONG Index = 0; - - pMem1 = (PUCHAR) pSrc1; - pMem2 = (PUCHAR) pSrc2; - - for (Index = 0; Index < Length; Index++) - { - if (pMem1[Index] > pMem2[Index]) - return (1); - else if (pMem1[Index] < pMem2[Index]) - return (2); - } - - // Equal - return (0); -} - - -/* - ======================================================================== - - Routine Description: - Zero out memory block - - Arguments: - pSrc1 Pointer to memory address - Length Size - - Return Value: - None - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPZeroMemory( - IN PVOID pSrc, - IN ULONG Length) -{ - PUCHAR pMem; - ULONG Index = 0; - - pMem = (PUCHAR) pSrc; - - for (Index = 0; Index < Length; Index++) - { - pMem[Index] = 0x00; - } -} - - -/* - ======================================================================== - - Routine Description: - Copy data from memory block 1 to memory block 2 - - Arguments: - pDest Pointer to destination memory address - pSrc Pointer to source memory address - Length Copy size - - Return Value: - None - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPMoveMemory( - OUT PVOID pDest, - IN PVOID pSrc, - IN ULONG Length) -{ - PUCHAR pMem1; - PUCHAR pMem2; - UINT Index; - - ASSERT((Length==0) || (pDest && pSrc)); - - pMem1 = (PUCHAR) pDest; - pMem2 = (PUCHAR) pSrc; - - for (Index = 0; Index < Length; Index++) - { - pMem1[Index] = pMem2[Index]; - } -} - - -/* - ======================================================================== - - Routine Description: - Initialize port configuration structure - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - Note: - - ======================================================================== -*/ -VOID UserCfgInit( - IN PRTMP_ADAPTER pAd) -{ -// EDCA_PARM DefaultEdcaParm; - UINT key_index, bss_index; - - DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit\n")); - - // - // part I. intialize common configuration - // - - for(key_index=0; key_indexSharedKey[bss_index][key_index].KeyLen = 0; - pAd->SharedKey[bss_index][key_index].CipherAlg = CIPHER_NONE; - } - } - - pAd->EepromAccess = FALSE; - - pAd->Antenna.word = 0; - pAd->CommonCfg.BBPCurrentBW = BW_20; - - pAd->LedCntl.word = 0; -#ifdef RTMP_MAC_PCI - pAd->LedIndicatorStrength = 0; - pAd->RLnkCtrlOffset = 0; - pAd->HostLnkCtrlOffset = 0; -#ifdef CONFIG_STA_SUPPORT - pAd->StaCfg.PSControl.field.EnableNewPS=TRUE; - pAd->CheckDmaBusyCount = 0; -#endif // CONFIG_STA_SUPPORT // -#endif // RTMP_MAC_PCI // - - pAd->bAutoTxAgcA = FALSE; // Default is OFF - pAd->bAutoTxAgcG = FALSE; // Default is OFF - pAd->RfIcType = RFIC_2820; - - // Init timer for reset complete event - pAd->CommonCfg.CentralChannel = 1; - pAd->bForcePrintTX = FALSE; - pAd->bForcePrintRX = FALSE; - pAd->bStaFifoTest = FALSE; - pAd->bProtectionTest = FALSE; - /* - pAd->bHCCATest = FALSE; - pAd->bGenOneHCCA = FALSE; - */ - pAd->CommonCfg.Dsifs = 10; // in units of usec - pAd->CommonCfg.TxPower = 100; //mW - pAd->CommonCfg.TxPowerPercentage = 0xffffffff; // AUTO - pAd->CommonCfg.TxPowerDefault = 0xffffffff; // AUTO - pAd->CommonCfg.TxPreamble = Rt802_11PreambleAuto; // use Long preamble on TX by defaut - pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; - pAd->CommonCfg.RtsThreshold = 2347; - pAd->CommonCfg.FragmentThreshold = 2346; - pAd->CommonCfg.UseBGProtection = 0; // 0: AUTO - pAd->CommonCfg.bEnableTxBurst = TRUE; //0; - pAd->CommonCfg.PhyMode = 0xff; // unknown - pAd->CommonCfg.BandState = UNKNOWN_BAND; - pAd->CommonCfg.RadarDetect.CSPeriod = 10; - pAd->CommonCfg.RadarDetect.CSCount = 0; - pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE; - - - -#ifdef TONE_RADAR_DETECT_SUPPORT -#ifdef CARRIER_DETECTION_SUPPORT - pAd->CommonCfg.CarrierDetect.delta = CARRIER_DETECT_DELTA; - pAd->CommonCfg.CarrierDetect.div_flag = CARRIER_DETECT_DIV_FLAG; - pAd->CommonCfg.CarrierDetect.criteria = CARRIER_DETECT_CRITIRIA; -#ifdef RT3090 - if(IS_RT3090A(pAd)) - pAd->CommonCfg.CarrierDetect.threshold = CARRIER_DETECT_THRESHOLD_3090A; - else -#endif // RT3090 // - pAd->CommonCfg.CarrierDetect.threshold = CARRIER_DETECT_THRESHOLD; -#endif // CARRIER_DETECTION_SUPPORT // -#endif // TONE_RADAR_DETECT_SUPPORT // - - pAd->CommonCfg.RadarDetect.ChMovingTime = 65; -#ifdef MERGE_ARCH_TEAM - pAd->CommonCfg.RadarDetect.LongPulseRadarTh = 2; - pAd->CommonCfg.RadarDetect.AvgRssiReq = -75; -#else // original rt28xx source code - pAd->CommonCfg.RadarDetect.LongPulseRadarTh = 3; -#endif // MERGE_ARCH_TEAM // - pAd->CommonCfg.bAPSDCapable = FALSE; - pAd->CommonCfg.bNeedSendTriggerFrame = FALSE; - pAd->CommonCfg.TriggerTimerCount = 0; - pAd->CommonCfg.bAPSDForcePowerSave = FALSE; - pAd->CommonCfg.bCountryFlag = FALSE; - pAd->CommonCfg.TxStream = 0; - pAd->CommonCfg.RxStream = 0; - - NdisZeroMemory(&pAd->BeaconTxWI, sizeof(pAd->BeaconTxWI)); - -#ifdef DOT11_N_SUPPORT - NdisZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability)); - pAd->HTCEnable = FALSE; - pAd->bBroadComHT = FALSE; - pAd->CommonCfg.bRdg = FALSE; - -#ifdef DOT11N_DRAFT3 - pAd->CommonCfg.Dot11OBssScanPassiveDwell = dot11OBSSScanPassiveDwell; // Unit : TU. 5~1000 - pAd->CommonCfg.Dot11OBssScanActiveDwell = dot11OBSSScanActiveDwell; // Unit : TU. 10~1000 - pAd->CommonCfg.Dot11BssWidthTriggerScanInt = dot11BSSWidthTriggerScanInterval; // Unit : Second - pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = dot11OBSSScanPassiveTotalPerChannel; // Unit : TU. 200~10000 - pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = dot11OBSSScanActiveTotalPerChannel; // Unit : TU. 20~10000 - pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = dot11BSSWidthChannelTransactionDelayFactor; - pAd->CommonCfg.Dot11OBssScanActivityThre = dot11BSSScanActivityThreshold; // Unit : percentage - pAd->CommonCfg.Dot11BssWidthChanTranDelay = (pAd->CommonCfg.Dot11BssWidthTriggerScanInt * pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); -#endif // DOT11N_DRAFT3 // - - NdisZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo)); - pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; - pAd->CommonCfg.BACapability.field.MpduDensity = 0; - pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; - pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; //32; - pAd->CommonCfg.BACapability.field.TxBAWinLimit = 64; //32; - DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit. BACapability = 0x%x\n", pAd->CommonCfg.BACapability.word)); - - pAd->CommonCfg.BACapability.field.AutoBA = FALSE; - BATableInit(pAd, &pAd->BATable); - - pAd->CommonCfg.bExtChannelSwitchAnnouncement = 1; - pAd->CommonCfg.bHTProtect = 1; - pAd->CommonCfg.bMIMOPSEnable = TRUE; - //2008/11/05:KH add to support Antenna power-saving of AP<-- - pAd->CommonCfg.bGreenAPEnable=FALSE; - pAd->CommonCfg.bBlockAntDivforGreenAP=FALSE; - //2008/11/05:KH add to support Antenna power-saving of AP--> - pAd->CommonCfg.bBADecline = FALSE; - pAd->CommonCfg.bDisableReordering = FALSE; - - if (pAd->MACVersion == 0x28720200) - { - pAd->CommonCfg.TxBASize = 13; //by Jerry recommend - }else{ - pAd->CommonCfg.TxBASize = 7; - } - - pAd->CommonCfg.REGBACapability.word = pAd->CommonCfg.BACapability.word; -#endif // DOT11_N_SUPPORT // - - //pAd->CommonCfg.HTPhyMode.field.BW = BW_20; - //pAd->CommonCfg.HTPhyMode.field.MCS = MCS_AUTO; - //pAd->CommonCfg.HTPhyMode.field.ShortGI = GI_800; - //pAd->CommonCfg.HTPhyMode.field.STBC = STBC_NONE; - pAd->CommonCfg.TxRate = RATE_6; - - pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_RATE_6; - pAd->CommonCfg.MlmeTransmit.field.BW = BW_20; - pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; - - pAd->CommonCfg.BeaconPeriod = 100; // in mSec - - - // - // part II. intialize STA specific configuration - // -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_DIRECT); - RX_FILTER_CLEAR_FLAG(pAd, fRX_FILTER_ACCEPT_MULTICAST); - RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_BROADCAST); - RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_ALL_MULTICAST); - - pAd->StaCfg.Psm = PWR_ACTIVE; - - pAd->StaCfg.OrigWepStatus = Ndis802_11EncryptionDisabled; - pAd->StaCfg.PairCipher = Ndis802_11EncryptionDisabled; - pAd->StaCfg.GroupCipher = Ndis802_11EncryptionDisabled; - pAd->StaCfg.bMixCipher = FALSE; - pAd->StaCfg.DefaultKeyId = 0; - - // 802.1x port control - pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - pAd->StaCfg.LastMicErrorTime = 0; - pAd->StaCfg.MicErrCnt = 0; - pAd->StaCfg.bBlockAssoc = FALSE; - pAd->StaCfg.WpaState = SS_NOTUSE; - - pAd->CommonCfg.NdisRadioStateOff = FALSE; // New to support microsoft disable radio with OID command - - pAd->StaCfg.RssiTrigger = 0; - NdisZeroMemory(&pAd->StaCfg.RssiSample, sizeof(RSSI_SAMPLE)); - pAd->StaCfg.RssiTriggerMode = RSSI_TRIGGERED_UPON_BELOW_THRESHOLD; - pAd->StaCfg.AtimWin = 0; - pAd->StaCfg.DefaultListenCount = 3;//default listen count; - pAd->StaCfg.BssType = BSS_INFRA; // BSS_INFRA or BSS_ADHOC or BSS_MONITOR - pAd->StaCfg.bScanReqIsFromWebUI = FALSE; - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); - - pAd->StaCfg.bAutoTxRateSwitch = TRUE; - pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; - } - -#ifdef EXT_BUILD_CHANNEL_LIST - pAd->StaCfg.IEEE80211dClientMode = Rt802_11_D_None; -#endif // EXT_BUILD_CHANNEL_LIST // -#ifdef PCIE_PS_SUPPORT -pAd->brt30xxBanMcuCmd = FALSE; -pAd->b3090ESpecialChip = FALSE; -//KH Debug:the following must be removed -pAd->StaCfg.PSControl.field.rt30xxPowerMode=3; -pAd->StaCfg.PSControl.field.rt30xxForceASPMTest=0; -pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM=1; -#endif // PCIE_PS_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - - // global variables mXXXX used in MAC protocol state machines - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); - - // PHY specification - pAd->CommonCfg.PhyMode = PHY_11BG_MIXED; // default PHY mode - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); // CCK use LONG preamble - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // user desired power mode - pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; - pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; - pAd->StaCfg.bWindowsACCAMEnable = FALSE; - - RTMPInitTimer(pAd, &pAd->StaCfg.StaQuickResponeForRateUpTimer, GET_TIMER_FUNCTION(StaQuickResponeForRateUpExec), pAd, FALSE); - pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; - - // Patch for Ndtest - pAd->StaCfg.ScanCnt = 0; - - pAd->StaCfg.bHwRadio = TRUE; // Default Hardware Radio status is On - pAd->StaCfg.bSwRadio = TRUE; // Default Software Radio status is On - pAd->StaCfg.bRadio = TRUE; // bHwRadio && bSwRadio - pAd->StaCfg.bHardwareRadio = FALSE; // Default is OFF - pAd->StaCfg.bShowHiddenSSID = FALSE; // Default no show - - // Nitro mode control - pAd->StaCfg.bAutoReconnect = TRUE; - - // Save the init time as last scan time, the system should do scan after 2 seconds. - // This patch is for driver wake up from standby mode, system will do scan right away. - NdisGetSystemUpTime(&pAd->StaCfg.LastScanTime); - if (pAd->StaCfg.LastScanTime > 10 * OS_HZ) - pAd->StaCfg.LastScanTime -= (10 * OS_HZ); - - NdisZeroMemory(pAd->nickname, IW_ESSID_MAX_SIZE+1); -#ifdef RTMP_MAC_PCI - sprintf((PSTRING) pAd->nickname, "RT2860STA"); -#endif // RTMP_MAC_PCI // - RTMPInitTimer(pAd, &pAd->StaCfg.WpaDisassocAndBlockAssocTimer, GET_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc), pAd, FALSE); -#ifdef WPA_SUPPLICANT_SUPPORT - pAd->StaCfg.IEEE8021X = FALSE; - pAd->StaCfg.IEEE8021x_required_keys = FALSE; - pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; - pAd->StaCfg.bRSN_IE_FromWpaSupplicant = FALSE; -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT - pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // -#endif // WPA_SUPPLICANT_SUPPORT // - - NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); - - - pAd->StaCfg.bAutoConnectByBssid = FALSE; - pAd->StaCfg.BeaconLostTime = BEACON_LOST_TIME; - NdisZeroMemory(pAd->StaCfg.WpaPassPhrase, 64); - pAd->StaCfg.WpaPassPhraseLen = 0; - pAd->StaCfg.bAutoRoaming = FALSE; - pAd->StaCfg.bForceTxBurst = FALSE; - } -#endif // CONFIG_STA_SUPPORT // - - // Default for extra information is not valid - pAd->ExtraInfo = EXTRA_INFO_CLEAR; - - // Default Config change flag - pAd->bConfigChanged = FALSE; - - // - // part III. AP configurations - // - - - // - // part IV. others - // - // dynamic BBP R66:sensibity tuning to overcome background noise - pAd->BbpTuning.bEnable = TRUE; - pAd->BbpTuning.FalseCcaLowerThreshold = 100; - pAd->BbpTuning.FalseCcaUpperThreshold = 512; - pAd->BbpTuning.R66Delta = 4; - pAd->Mlme.bEnableAutoAntennaCheck = TRUE; - - // - // Also initial R66CurrentValue, RTUSBResumeMsduTransmission might use this value. - // if not initial this value, the default value will be 0. - // - pAd->BbpTuning.R66CurrentValue = 0x38; - - pAd->Bbp94 = BBPR94_DEFAULT; - pAd->BbpForCCK = FALSE; - - // Default is FALSE for test bit 1 - //pAd->bTest1 = FALSE; - - // initialize MAC table and allocate spin lock - NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE)); - InitializeQueueHeader(&pAd->MacTab.McastPsQueue); - NdisAllocateSpinLock(&pAd->MacTabLock); - - //RTMPInitTimer(pAd, &pAd->RECBATimer, RECBATimerTimeout, pAd, TRUE); - //RTMPSetTimer(&pAd->RECBATimer, REORDER_EXEC_INTV); - -#ifdef RALINK_ATE - NdisZeroMemory(&pAd->ate, sizeof(ATE_INFO)); - pAd->ate.Mode = ATE_STOP; - pAd->ate.TxCount = 200;/* to exceed TX_RING_SIZE ... */ - pAd->ate.TxDoneCount = 0; - pAd->ate.RFFreqOffset = 0; - pAd->ate.TxLength = 1024; - pAd->ate.TxWI.ShortGI = 0;// LONG GI : 800 ns - pAd->ate.TxWI.PHYMODE = MODE_CCK; - pAd->ate.TxWI.MCS = 3; - pAd->ate.TxWI.BW = BW_20; - pAd->ate.Channel = 1; - pAd->ate.QID = QID_AC_BE; - pAd->ate.Addr1[0] = 0x00; - pAd->ate.Addr1[1] = 0x11; - pAd->ate.Addr1[2] = 0x22; - pAd->ate.Addr1[3] = 0xAA; - pAd->ate.Addr1[4] = 0xBB; - pAd->ate.Addr1[5] = 0xCC; - NdisMoveMemory(pAd->ate.Addr2, pAd->ate.Addr1, ETH_LENGTH_OF_ADDRESS); - NdisMoveMemory(pAd->ate.Addr3, pAd->ate.Addr1, ETH_LENGTH_OF_ADDRESS); - pAd->ate.bRxFER = 0; - pAd->ate.bQATxStart = FALSE; - pAd->ate.bQARxStart = FALSE; - -#ifdef RTMP_MAC_PCI - pAd->ate.bFWLoading = FALSE; -#endif // RTMP_MAC_PCI // - - -#ifdef RALINK_28xx_QA - pAd->ate.TxStatus = 0; - pAd->ate.AtePid = THREAD_PID_INIT_VALUE; -#endif // RALINK_28xx_QA // -#endif // RALINK_ATE // - - - pAd->CommonCfg.bWiFiTest = FALSE; -#ifdef RTMP_MAC_PCI - pAd->bPCIclkOff = FALSE; -#endif // RTMP_MAC_PCI // - -#ifdef CONFIG_STA_SUPPORT -RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); -#endif // CONFIG_STA_SUPPORT // -#ifdef ANT_DIVERSITY_SUPPORT - if ( pAd->CommonCfg.bRxAntDiversity == ANT_FIX_ANT2) - { - pAd->RxAnt.Pair1PrimaryRxAnt = 1; - pAd->RxAnt.Pair1SecondaryRxAnt = 0; - } - else // Default - { - pAd->RxAnt.Pair1PrimaryRxAnt = 0; - pAd->RxAnt.Pair1SecondaryRxAnt = 1; - } - pAd->RxAnt.EvaluatePeriod = 0; - pAd->RxAnt.RcvPktNumWhenEvaluate = 0; -#ifdef CONFIG_STA_SUPPORT - pAd->RxAnt.Pair1AvgRssi[0] = pAd->RxAnt.Pair1AvgRssi[1] = 0; -#endif // CONFIG_STA_SUPPORT // -#endif // AP_ANTENNA_DIVERSITY_SUPPORT // - - DBGPRINT(RT_DEBUG_TRACE, ("<-- UserCfgInit\n")); -} - -// IRQL = PASSIVE_LEVEL -UCHAR BtoH(STRING ch) -{ - if (ch >= '0' && ch <= '9') return (ch - '0'); // Handle numerals - if (ch >= 'A' && ch <= 'F') return (ch - 'A' + 0xA); // Handle capitol hex digits - if (ch >= 'a' && ch <= 'f') return (ch - 'a' + 0xA); // Handle small hex digits - return(255); -} - -// -// FUNCTION: AtoH(char *, UCHAR *, int) -// -// PURPOSE: Converts ascii string to network order hex -// -// PARAMETERS: -// src - pointer to input ascii string -// dest - pointer to output hex -// destlen - size of dest -// -// COMMENTS: -// -// 2 ascii bytes make a hex byte so must put 1st ascii byte of pair -// into upper nibble and 2nd ascii byte of pair into lower nibble. -// -// IRQL = PASSIVE_LEVEL - -void AtoH(PSTRING src, PUCHAR dest, int destlen) -{ - PSTRING srcptr; - PUCHAR destTemp; - - srcptr = src; - destTemp = (PUCHAR) dest; - - while(destlen--) - { - *destTemp = BtoH(*srcptr++) << 4; // Put 1st ascii byte in upper nibble. - *destTemp += BtoH(*srcptr++); // Add 2nd ascii byte to above. - destTemp++; - } -} - - -//+++Mark by shiang, not use now, need to remove after confirm -//---Mark by shiang, not use now, need to remove after confirm - - -/* - ======================================================================== - - Routine Description: - Init timer objects - - Arguments: - pAd Pointer to our adapter - pTimer Timer structure - pTimerFunc Function to execute when timer expired - Repeat Ture for period timer - - Return Value: - None - - Note: - - ======================================================================== -*/ -VOID RTMPInitTimer( - IN PRTMP_ADAPTER pAd, - IN PRALINK_TIMER_STRUCT pTimer, - IN PVOID pTimerFunc, - IN PVOID pData, - IN BOOLEAN Repeat) -{ - // - // Set Valid to TRUE for later used. - // It will crash if we cancel a timer or set a timer - // that we haven't initialize before. - // - pTimer->Valid = TRUE; - - pTimer->PeriodicType = Repeat; - pTimer->State = FALSE; - pTimer->cookie = (ULONG) pData; - -#ifdef RTMP_TIMER_TASK_SUPPORT - pTimer->pAd = pAd; -#endif // RTMP_TIMER_TASK_SUPPORT // - - RTMP_OS_Init_Timer(pAd, &pTimer->TimerObj, pTimerFunc, (PVOID) pTimer); -} - - -/* - ======================================================================== - - Routine Description: - Init timer objects - - Arguments: - pTimer Timer structure - Value Timer value in milliseconds - - Return Value: - None - - Note: - To use this routine, must call RTMPInitTimer before. - - ======================================================================== -*/ -VOID RTMPSetTimer( - IN PRALINK_TIMER_STRUCT pTimer, - IN ULONG Value) -{ - if (pTimer->Valid) - { - pTimer->TimerValue = Value; - pTimer->State = FALSE; - if (pTimer->PeriodicType == TRUE) - { - pTimer->Repeat = TRUE; - RTMP_SetPeriodicTimer(&pTimer->TimerObj, Value); - } - else - { - pTimer->Repeat = FALSE; - RTMP_OS_Add_Timer(&pTimer->TimerObj, Value); - } - } - else - { - DBGPRINT_ERR(("RTMPSetTimer failed, Timer hasn't been initialize!\n")); - } -} - - -/* - ======================================================================== - - Routine Description: - Init timer objects - - Arguments: - pTimer Timer structure - Value Timer value in milliseconds - - Return Value: - None - - Note: - To use this routine, must call RTMPInitTimer before. - - ======================================================================== -*/ -VOID RTMPModTimer( - IN PRALINK_TIMER_STRUCT pTimer, - IN ULONG Value) -{ - BOOLEAN Cancel; - - if (pTimer->Valid) - { - pTimer->TimerValue = Value; - pTimer->State = FALSE; - if (pTimer->PeriodicType == TRUE) - { - RTMPCancelTimer(pTimer, &Cancel); - RTMPSetTimer(pTimer, Value); - } - else - { - RTMP_OS_Mod_Timer(&pTimer->TimerObj, Value); - } - } - else - { - DBGPRINT_ERR(("RTMPModTimer failed, Timer hasn't been initialize!\n")); - } -} - - -/* - ======================================================================== - - Routine Description: - Cancel timer objects - - Arguments: - Adapter Pointer to our adapter - - Return Value: - None - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - Note: - 1.) To use this routine, must call RTMPInitTimer before. - 2.) Reset NIC to initial state AS IS system boot up time. - - ======================================================================== -*/ -VOID RTMPCancelTimer( - IN PRALINK_TIMER_STRUCT pTimer, - OUT BOOLEAN *pCancelled) -{ - if (pTimer->Valid) - { - if (pTimer->State == FALSE) - pTimer->Repeat = FALSE; - - RTMP_OS_Del_Timer(&pTimer->TimerObj, pCancelled); - - if (*pCancelled == TRUE) - pTimer->State = TRUE; - -#ifdef RTMP_TIMER_TASK_SUPPORT - // We need to go-through the TimerQ to findout this timer handler and remove it if - // it's still waiting for execution. - RtmpTimerQRemove(pTimer->pAd, pTimer); -#endif // RTMP_TIMER_TASK_SUPPORT // - } - else - { - DBGPRINT_ERR(("RTMPCancelTimer failed, Timer hasn't been initialize!\n")); - } -} - - -/* - ======================================================================== - - Routine Description: - Set LED Status - - Arguments: - pAd Pointer to our adapter - Status LED Status - - Return Value: - None - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPSetLED( - IN PRTMP_ADAPTER pAd, - IN UCHAR Status) -{ - //ULONG data; - UCHAR HighByte = 0; - UCHAR LowByte; - BOOLEAN bIgnored = FALSE; - -#ifdef RALINK_ATE - /* - In ATE mode of RT2860 AP/STA, we have erased 8051 firmware. - So LED mode is not supported when ATE is running. - */ - if (!IS_RT3572(pAd)) - { - if (ATE_ON(pAd)) - return; - } -#endif // RALINK_ATE // - - LowByte = pAd->LedCntl.field.LedMode&0x7f; - switch (Status) - { - case LED_LINK_DOWN: - HighByte = 0x20; - AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); - pAd->LedIndicatorStrength = 0; - break; - case LED_LINK_UP: - if (pAd->CommonCfg.Channel > 14) - HighByte = 0xa0; - else - HighByte = 0x60; - AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); - break; - case LED_RADIO_ON: - HighByte = 0x20; - AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); - break; - case LED_HALT: - LowByte = 0; // Driver sets MAC register and MAC controls LED - case LED_RADIO_OFF: - HighByte = 0; - AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); - break; - case LED_WPS: - HighByte = 0x10; - AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); - break; - case LED_ON_SITE_SURVEY: - HighByte = 0x08; - AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); - break; - case LED_POWER_UP: - HighByte = 0x04; - AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); - break; -#ifdef RALINK_ATE -#endif // RALINK_ATE // - default: - DBGPRINT(RT_DEBUG_WARN, ("RTMPSetLED::Unknown Status %d\n", Status)); - break; - } - - // - // Keep LED status for LED SiteSurvey mode. - // After SiteSurvey, we will set the LED mode to previous status. - // - if ((Status != LED_ON_SITE_SURVEY) && (Status != LED_POWER_UP) && (bIgnored == FALSE)) - pAd->LedStatus = Status; - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetLED::Mode=%d,HighByte=0x%02x,LowByte=0x%02x\n", pAd->LedCntl.field.LedMode, HighByte, LowByte)); -} - -/* - ======================================================================== - - Routine Description: - Set LED Signal Stregth - - Arguments: - pAd Pointer to our adapter - Dbm Signal Stregth - - Return Value: - None - - IRQL = PASSIVE_LEVEL - - Note: - Can be run on any IRQL level. - - According to Microsoft Zero Config Wireless Signal Stregth definition as belows. - <= -90 No Signal - <= -81 Very Low - <= -71 Low - <= -67 Good - <= -57 Very Good - > -57 Excellent - ======================================================================== -*/ -VOID RTMPSetSignalLED( - IN PRTMP_ADAPTER pAd, - IN NDIS_802_11_RSSI Dbm) -{ - UCHAR nLed = 0; - - if (pAd->LedCntl.field.LedMode == LED_MODE_SIGNAL_STREGTH) - { - if (Dbm <= -90) - nLed = 0; - else if (Dbm <= -81) - nLed = 1; - else if (Dbm <= -71) - nLed = 3; - else if (Dbm <= -67) - nLed = 7; - else if (Dbm <= -57) - nLed = 15; - else - nLed = 31; - - // - // Update Signal Stregth to firmware if changed. - // - if (pAd->LedIndicatorStrength != nLed) - { - AsicSendCommandToMcu(pAd, 0x51, 0xff, nLed, pAd->LedCntl.field.Polarity); - pAd->LedIndicatorStrength = nLed; - } - } -} - - - -/* - ======================================================================== - - Routine Description: - Enable RX - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - IRQL <= DISPATCH_LEVEL - - Note: - Before Enable RX, make sure you have enabled Interrupt. - ======================================================================== -*/ -VOID RTMPEnableRxTx( - IN PRTMP_ADAPTER pAd) -{ -// WPDMA_GLO_CFG_STRUC GloCfg; -// ULONG i = 0; - UINT32 rx_filter_flag; - - DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPEnableRxTx\n")); - - // Enable Rx DMA. - RT28XXDMAEnable(pAd); - - // enable RX of MAC block - if (pAd->OpMode == OPMODE_AP) - { - rx_filter_flag = APNORMAL; - - - RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); // enable RX of DMA block - } - else - { - if (pAd->CommonCfg.PSPXlink) - rx_filter_flag = PSPXLINK; - else - rx_filter_flag = STANORMAL; // Staion not drop control frame will fail WiFi Certification. - RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); - } - - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc); - DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPEnableRxTx\n")); -} - - -//+++Add by shiang, move from os/linux/rt_main_dev.c -void CfgInitHook(PRTMP_ADAPTER pAd) -{ - pAd->bBroadComHT = TRUE; -} - - -int rt28xx_init( - IN PRTMP_ADAPTER pAd, - IN PSTRING pDefaultMac, - IN PSTRING pHostName) -{ - UINT index; - UCHAR TmpPhy; - NDIS_STATUS Status; - UINT32 MacCsr0 = 0; - -#ifdef CONFIG_STA_SUPPORT -#ifdef RTMP_MAC_PCI - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // If dirver doesn't wake up firmware here, - // NICLoadFirmware will hang forever when interface is up again. - // RT2860 PCI - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) && - OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - { - AUTO_WAKEUP_STRUC AutoWakeupCfg; - AsicForceWakeup(pAd, TRUE); - AutoWakeupCfg.word = 0; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); - } - } -#endif // RTMP_MAC_PCI // -#endif // CONFIG_STA_SUPPORT // - - - // reset Adapter flags - RTMP_CLEAR_FLAGS(pAd); - - // Init BssTab & ChannelInfo tabbles for auto channel select. - -#ifdef DOT11_N_SUPPORT - // Allocate BA Reordering memory - ba_reordering_resource_init(pAd, MAX_REORDERING_MPDU_NUM); -#endif // DOT11_N_SUPPORT // - - // Make sure MAC gets ready. - index = 0; - do - { - RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); - pAd->MACVersion = MacCsr0; - - if ((pAd->MACVersion != 0x00) && (pAd->MACVersion != 0xFFFFFFFF)) - break; - - RTMPusecDelay(10); - } while (index++ < 100); - DBGPRINT(RT_DEBUG_TRACE, ("MAC_CSR0 [ Ver:Rev=0x%08x]\n", pAd->MACVersion)); - -#ifdef RTMP_MAC_PCI -#ifdef PCIE_PS_SUPPORT - /*Iverson patch PCIE L1 issue to make sure that driver can be read,write ,BBP and RF register at pcie L.1 level */ - if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))&&OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - { - RTMP_IO_READ32(pAd, AUX_CTRL, &MacCsr0); - MacCsr0 |= 0x402; - RTMP_IO_WRITE32(pAd, AUX_CTRL, MacCsr0); - DBGPRINT(RT_DEBUG_TRACE, ("AUX_CTRL = 0x%x\n", MacCsr0)); - } -#endif // PCIE_PS_SUPPORT // - - // To fix driver disable/enable hang issue when radio off - RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x2); -#endif // RTMP_MAC_PCI // - - // Disable DMA - RT28XXDMADisable(pAd); - - - // Load 8051 firmware - Status = NICLoadFirmware(pAd); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT_ERR(("NICLoadFirmware failed, Status[=0x%08x]\n", Status)); - goto err1; - } - - NICLoadRateSwitchingParams(pAd); - - // Disable interrupts here which is as soon as possible - // This statement should never be true. We might consider to remove it later -#ifdef RTMP_MAC_PCI - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) - { - RTMP_ASIC_INTERRUPT_DISABLE(pAd); - } -#endif // RTMP_MAC_PCI // - - Status = RTMPAllocTxRxRingMemory(pAd); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT_ERR(("RTMPAllocDMAMemory failed, Status[=0x%08x]\n", Status)); - goto err1; - } - - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); - - // initialize MLME - // - - Status = RtmpMgmtTaskInit(pAd); - if (Status != NDIS_STATUS_SUCCESS) - goto err2; - - Status = MlmeInit(pAd); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT_ERR(("MlmeInit failed, Status[=0x%08x]\n", Status)); - goto err2; - } - - // Initialize pAd->StaCfg, pAd->ApCfg, pAd->CommonCfg to manufacture default - // - UserCfgInit(pAd); - Status = RtmpNetTaskInit(pAd); - if (Status != NDIS_STATUS_SUCCESS) - goto err3; - -// COPY_MAC_ADDR(pAd->ApCfg.MBSSID[apidx].Bssid, netif->hwaddr); -// pAd->bForcePrintTX = TRUE; - - CfgInitHook(pAd); - - -#ifdef BLOCK_NET_IF - initblockQueueTab(pAd); -#endif // BLOCK_NET_IF // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - NdisAllocateSpinLock(&pAd->MacTabLock); -#endif // CONFIG_STA_SUPPORT // - - MeasureReqTabInit(pAd); - TpcReqTabInit(pAd); - - // - // Init the hardware, we need to init asic before read registry, otherwise mac register will be reset - // - Status = NICInitializeAdapter(pAd, TRUE); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT_ERR(("NICInitializeAdapter failed, Status[=0x%08x]\n", Status)); - if (Status != NDIS_STATUS_SUCCESS) - goto err3; - } - - // Read parameters from Config File - Status = RTMPReadParametersHook(pAd); - - DBGPRINT(RT_DEBUG_OFF, ("1. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT_ERR(("NICReadRegParameters failed, Status[=0x%08x]\n",Status)); - goto err4; - } - - - -#ifdef DOT11_N_SUPPORT - //Init Ba Capability parameters. -// RT28XX_BA_INIT(pAd); - pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; - pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable; - pAd->CommonCfg.DesiredHtPhy.AmsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; - pAd->CommonCfg.DesiredHtPhy.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; - // UPdata to HT IE - pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; - pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; - pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; -#endif // DOT11_N_SUPPORT // - - // after reading Registry, we now know if in AP mode or STA mode - - // Load 8051 firmware; crash when FW image not existent - // Status = NICLoadFirmware(pAd); - // if (Status != NDIS_STATUS_SUCCESS) - // break; - - DBGPRINT(RT_DEBUG_OFF, ("2. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); - - // We should read EEPROM for all cases. rt2860b - NICReadEEPROMParameters(pAd, (PUCHAR)pDefaultMac); -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - - DBGPRINT(RT_DEBUG_OFF, ("3. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); - - NICInitAsicFromEEPROM(pAd); //rt2860b - - // Set PHY to appropriate mode - TmpPhy = pAd->CommonCfg.PhyMode; - pAd->CommonCfg.PhyMode = 0xff; - RTMPSetPhyMode(pAd, TmpPhy); -#ifdef DOT11_N_SUPPORT - SetCommonHT(pAd); -#endif // DOT11_N_SUPPORT // - - // No valid channels. - if (pAd->ChannelListNum == 0) - { - DBGPRINT(RT_DEBUG_ERROR, ("Wrong configuration. No valid channel found. Check \"ContryCode\" and \"ChannelGeography\" setting.\n")); - goto err4; - } - -#ifdef DOT11_N_SUPPORT - DBGPRINT(RT_DEBUG_OFF, ("MCS Set = %02x %02x %02x %02x %02x\n", pAd->CommonCfg.HtCapability.MCSSet[0], - pAd->CommonCfg.HtCapability.MCSSet[1], pAd->CommonCfg.HtCapability.MCSSet[2], - pAd->CommonCfg.HtCapability.MCSSet[3], pAd->CommonCfg.HtCapability.MCSSet[4])); -#endif // DOT11_N_SUPPORT // - -#ifdef RTMP_RF_RW_SUPPORT - //Init RT30xx RFRegisters after read RFIC type from EEPROM - NICInitRFRegisters(pAd); -#endif // RTMP_RF_RW_SUPPORT // - - - -// APInitialize(pAd); - -#ifdef IKANOS_VX_1X0 - VR_IKANOS_FP_Init(pAd->ApCfg.BssidNum, pAd->PermanentAddress); -#endif // IKANOS_VX_1X0 // - - // - // Initialize RF register to default value - // - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - - // 8051 firmware require the signal during booting time. - //2008/11/28:KH marked the following codes to patch Frequency offset bug - //AsicSendCommandToMcu(pAd, 0x72, 0xFF, 0x00, 0x00); - - if (pAd && (Status != NDIS_STATUS_SUCCESS)) - { - // - // Undo everything if it failed - // - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { -// NdisMDeregisterInterrupt(&pAd->Interrupt); - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); - } -// RTMPFreeAdapter(pAd); // we will free it in disconnect() - } - else if (pAd) - { - // Microsoft HCT require driver send a disconnect event after driver initialization. - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); -// pAd->IndicateMediaState = NdisMediaStateDisconnected; - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE); - - DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event B!\n")); - - - }// end of else - - - // Set up the Mac address - RtmpOSNetDevAddrSet(pAd->net_dev, &pAd->CurrentAddress[0]); - - // Various AP function init - - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { -#ifdef WPA_SUPPLICANT_SUPPORT -#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT - // send wireless event to wpa_supplicant for infroming interface up. - RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, RT_INTERFACE_UP, NULL, NULL, 0); -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // -#endif // WPA_SUPPLICANT_SUPPORT // - - } -#endif // CONFIG_STA_SUPPORT // - - - - DBGPRINT_S(Status, ("<==== rt28xx_init, Status=%x\n", Status)); - - return TRUE; - - -err4: -err3: - MlmeHalt(pAd); -err2: - RTMPFreeTxRxRingMemory(pAd); -err1: - -#ifdef DOT11_N_SUPPORT - os_free_mem(pAd, pAd->mpdu_blk_pool.mem); // free BA pool -#endif // DOT11_N_SUPPORT // - - // shall not set priv to NULL here because the priv didn't been free yet. - //net_dev->priv = 0; -#ifdef INF_AMAZON_SE -err0: -#endif // INF_AMAZON_SE // -#ifdef ST -err0: -#endif // ST // - - DBGPRINT(RT_DEBUG_ERROR, ("!!! rt28xx Initialized fail !!!\n")); - return FALSE; -} -//---Add by shiang, move from os/linux/rt_main_dev.c - - -static INT RtmpChipOpsRegister( - IN RTMP_ADAPTER *pAd, - IN INT infType) -{ - RTMP_CHIP_OP *pChipOps = &pAd->chipOps; - int status; - - memset(pChipOps, 0, sizeof(RTMP_CHIP_OP)); - - /* set eeprom related hook functions */ - status = RtmpChipOpsEepromHook(pAd, infType); - - /* set mcu related hook functions */ - switch(infType) - { -#ifdef RTMP_PCI_SUPPORT - case RTMP_DEV_INF_PCI: - pChipOps->loadFirmware = RtmpAsicLoadFirmware; - pChipOps->eraseFirmware = RtmpAsicEraseFirmware; - pChipOps->sendCommandToMcu = RtmpAsicSendCommandToMcu; - break; -#endif // RTMP_PCI_SUPPORT // - - - default: - break; - } - - return status; -} - - -INT RtmpRaDevCtrlInit( - IN RTMP_ADAPTER *pAd, - IN RTMP_INF_TYPE infType) -{ - //VOID *handle; - - // Assign the interface type. We need use it when do register/EEPROM access. - pAd->infType = infType; - - -#ifdef CONFIG_STA_SUPPORT - pAd->OpMode = OPMODE_STA; - DBGPRINT(RT_DEBUG_TRACE, ("STA Driver version-%s\n", STA_DRIVER_VERSION)); -#endif // CONFIG_STA_SUPPORT // - - - - RtmpChipOpsRegister(pAd, infType); - -#ifdef MULTIPLE_CARD_SUPPORT -{ - extern BOOLEAN RTMP_CardInfoRead(PRTMP_ADAPTER pAd); - - // find its profile path - pAd->MC_RowID = -1; // use default profile path - RTMP_CardInfoRead(pAd); - - if (pAd->MC_RowID == -1) -#ifdef CONFIG_STA_SUPPORT - strcpy(pAd->MC_FileName, STA_PROFILE_PATH); -#endif // CONFIG_STA_SUPPORT // - - DBGPRINT(RT_DEBUG_TRACE, ("MC> ROW = %d, PATH = %s\n", pAd->MC_RowID, pAd->MC_FileName)); -} -#endif // MULTIPLE_CARD_SUPPORT // - - return 0; -} - - -BOOLEAN RtmpRaDevCtrlExit(IN RTMP_ADAPTER *pAd) -{ -#ifdef MULTIPLE_CARD_SUPPORT -extern UINT8 MC_CardUsed[MAX_NUM_OF_MULTIPLE_CARD]; - - if ((pAd->MC_RowID >= 0) && (pAd->MC_RowID <= MAX_NUM_OF_MULTIPLE_CARD)) - MC_CardUsed[pAd->MC_RowID] = 0; // not clear MAC address -#endif // MULTIPLE_CARD_SUPPORT // - - - RTMPFreeAdapter(pAd); - - return TRUE; -} - - -// not yet support MBSS -PNET_DEV get_netdev_from_bssid( - IN PRTMP_ADAPTER pAd, - IN UCHAR FromWhichBSSID) -{ - PNET_DEV dev_p = NULL; - - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - dev_p = pAd->net_dev; - } -#endif // CONFIG_STA_SUPPORT // - - ASSERT(dev_p); - return dev_p; /* return one of MBSS */ -} diff --git a/drivers/staging/rt3090/common/rtmp_mcu.c b/drivers/staging/rt3090/common/rtmp_mcu.c deleted file mode 100644 index 23f785a90e06bfa48eb37a070c91f2f493d8e216..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/rtmp_mcu.c +++ /dev/null @@ -1,560 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rtmp_mcu.c - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#include "../rt_config.h" -#include "../firmware.h" - -//#define BIN_IN_FILE /* use *.bin firmware */ - - -// New 8k byte firmware size for RT3071/RT3072 -#define FIRMWAREIMAGE_MAX_LENGTH 0x2000 -#define FIRMWAREIMAGE_LENGTH (sizeof (FirmwareImage) / sizeof(UCHAR)) -#define FIRMWARE_MAJOR_VERSION 0 - -#define FIRMWAREIMAGEV1_LENGTH 0x1000 -#define FIRMWAREIMAGEV2_LENGTH 0x1000 - -#ifdef RTMP_MAC_PCI -#define FIRMWARE_MINOR_VERSION 2 -#endif // RTMP_MAC_PCI // - -const unsigned short ccitt_16Table[] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 -}; -#define ByteCRC16(v, crc) \ - (unsigned short)((crc << 8) ^ ccitt_16Table[((crc >> 8) ^ (v)) & 255]) - -unsigned char BitReverse(unsigned char x) -{ - int i; - unsigned char Temp=0; - for(i=0; ; i++) - { - if(x & 0x80) Temp |= 0x80; - if(i==7) break; - x <<= 1; - Temp >>= 1; - } - return Temp; -} - - -/* - ======================================================================== - - Routine Description: - erase 8051 firmware image in MAC ASIC - - Arguments: - Adapter Pointer to our adapter - - IRQL = PASSIVE_LEVEL - - ======================================================================== -*/ -INT RtmpAsicEraseFirmware( - IN PRTMP_ADAPTER pAd) -{ - ULONG i; - - for(i=0; i %s\n", __FUNCTION__)); - - /* init */ - pFirmwareImage = NULL; - src = RTMP_FIRMWARE_FILE_NAME; - - RtmpOSFSInfoChange(&osFSInfo, TRUE); - - pAd->FirmwareVersion = (FIRMWARE_MAJOR_VERSION << 8) + \ - FIRMWARE_MINOR_VERSION; - - - /* allocate firmware buffer */ - pFirmwareImage = kmalloc(MAX_FIRMWARE_IMAGE_SIZE, MEM_ALLOC_FLAG); - if (pFirmwareImage == NULL) - { - /* allocate fail, use default firmware array in firmware.h */ - DBGPRINT(RT_DEBUG_ERROR, ("%s - Allocate memory fail!\n", __FUNCTION__)); - NICLF_DEFAULT_USE(); - } - else - { - /* allocate ok! zero the firmware buffer */ - memset(pFirmwareImage, 0x00, MAX_FIRMWARE_IMAGE_SIZE); - } /* End of if */ - - - /* if ok, read firmware file from *.bin file */ - if (flg_default_firm_use == FALSE) - { - do - { - /* open the bin file */ - srcf = RtmpOSFileOpen(src, O_RDONLY, 0); - - if (IS_FILE_OPEN_ERR(srcf)) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s - Error opening file %s\n", __FUNCTION__, src)); - NICLF_DEFAULT_USE(); - break; - } - - - /* read the firmware from the file *.bin */ - FileLength = RtmpOSFileRead(srcf, pFirmwareImage, MAX_FIRMWARE_IMAGE_SIZE); - if (FileLength != MAX_FIRMWARE_IMAGE_SIZE) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: error file length (=%d) in RT2860AP.BIN\n", - __FUNCTION__, FileLength)); - NICLF_DEFAULT_USE(); - break; - } - else - { - PUCHAR ptr = pFirmwareImage; - USHORT crc = 0xffff; - - - /* calculate firmware CRC */ - for(i=0; i<(MAX_FIRMWARE_IMAGE_SIZE-2); i++, ptr++) - crc = ByteCRC16(BitReverse(*ptr), crc); - /* End of for */ - - if ((pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-2] != \ - (UCHAR)BitReverse((UCHAR)(crc>>8))) || - (pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-1] != \ - (UCHAR)BitReverse((UCHAR)crc))) - { - /* CRC fail */ - DBGPRINT(RT_DEBUG_ERROR, ("%s: CRC = 0x%02x 0x%02x " - "error, should be 0x%02x 0x%02x\n", - __FUNCTION__, - pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-2], - pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-1], - (UCHAR)(crc>>8), (UCHAR)(crc))); - NICLF_DEFAULT_USE(); - break; - } - else - { - /* firmware is ok */ - pAd->FirmwareVersion = \ - (pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-4] << 8) + - pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-3]; - - /* check if firmware version of the file is too old */ - if ((pAd->FirmwareVersion) < \ - ((FIRMWARE_MAJOR_VERSION << 8) + - FIRMWARE_MINOR_VERSION)) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: firmware version too old!\n", __FUNCTION__)); - NICLF_DEFAULT_USE(); - break; - } /* End of if */ - } /* End of if */ - - DBGPRINT(RT_DEBUG_TRACE, - ("NICLoadFirmware: CRC ok, ver=%d.%d\n", - pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-4], - pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-3])); - } /* End of if (FileLength == MAX_FIRMWARE_IMAGE_SIZE) */ - break; - } while(TRUE); - - /* close firmware file */ - if (IS_FILE_OPEN_ERR(srcf)) - ; - else - { - retval = RtmpOSFileClose(srcf); - if (retval) - { - DBGPRINT(RT_DEBUG_ERROR, ("--> Error %d closing %s\n", -retval, src)); - } - } - } - - - /* write firmware to ASIC */ - if (flg_default_firm_use == TRUE) - { - /* use default fimeware, free allocated buffer */ - if (pFirmwareImage != NULL) - kfree(pFirmwareImage); - /* End of if */ - - /* use default *.bin array */ - pFirmwareImage = FirmwareImage; - FileLength = sizeof(FirmwareImage); - } /* End of if */ - - /* enable Host program ram write selection */ - RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x10000); - - for(i=0; iMACVersion >> 16); - - pFirmwareImage = FirmwareImage; - FileLength = sizeof(FirmwareImage); - - // New 8k byte firmware size for RT3071/RT3072 - //DBGPRINT(RT_DEBUG_TRACE, ("Usb Chip\n")); - if (FIRMWAREIMAGE_LENGTH == FIRMWAREIMAGE_MAX_LENGTH) - //The firmware image consists of two parts. One is the origianl and the other is the new. - //Use Second Part - { -#ifdef RTMP_MAC_PCI - if ((Version == 0x2860) || IS_RT3090(pAd)||IS_RT3390(pAd)) - { - pFirmwareImage = FirmwareImage; - FileLength = FIRMWAREIMAGE_LENGTH; - } -#endif // RTMP_MAC_PCI // - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("KH: bin file should be 8KB.\n")); - Status = NDIS_STATUS_FAILURE; - } - - - RTMP_WRITE_FIRMWARE(pAd, pFirmwareImage, FileLength); - -#endif - - /* check if MCU is ready */ - Index = 0; - do - { - RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacReg); - - if (MacReg & 0x80) - break; - - RTMPusecDelay(1000); - } while (Index++ < 1000); - - if (Index >= 1000) - { - DBGPRINT(RT_DEBUG_ERROR, ("NICLoadFirmware: MCU is not ready\n\n\n")); - Status = NDIS_STATUS_FAILURE; - } - - DBGPRINT(RT_DEBUG_TRACE, ("<=== %s (status=%d)\n", __FUNCTION__, Status)); - - return Status; -} - - -INT RtmpAsicSendCommandToMcu( - IN PRTMP_ADAPTER pAd, - IN UCHAR Command, - IN UCHAR Token, - IN UCHAR Arg0, - IN UCHAR Arg1) -{ - HOST_CMD_CSR_STRUC H2MCmd; - H2M_MAILBOX_STRUC H2MMailbox; - ULONG i = 0; -#ifdef RTMP_MAC_PCI -#ifdef RALINK_ATE - static UINT32 j = 0; -#endif // RALINK_ATE // -#endif // RTMP_MAC_PCI // -#ifdef PCIE_PS_SUPPORT -#ifdef CONFIG_STA_SUPPORT - // 3090F power solution 3 has hw limitation that needs to ban all mcu command - // when firmware is in radio state. For other chip doesn't have this limitation. - if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd) - && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) - && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) - { - RTMP_SEM_LOCK(&pAd->McuCmdLock); - if ((pAd->brt30xxBanMcuCmd == TRUE) - && (Command != WAKE_MCU_CMD) && (Command != RFOFF_MCU_CMD)) - { - RTMP_SEM_UNLOCK(&pAd->McuCmdLock); - DBGPRINT(RT_DEBUG_TRACE, (" Ban Mcu Cmd %x in sleep mode\n", Command)); - return FALSE; - } - else if ((Command == SLEEP_MCU_CMD) - ||(Command == RFOFF_MCU_CMD)) - { - pAd->brt30xxBanMcuCmd = TRUE; - } - else if (Command != WAKE_MCU_CMD) - { - pAd->brt30xxBanMcuCmd = FALSE; - } - - RTMP_SEM_UNLOCK(&pAd->McuCmdLock); - - } - if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd) - && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) - && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) - && (Command == WAKE_MCU_CMD)) - { - - do - { - RTMP_IO_FORCE_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word); - if (H2MMailbox.field.Owner == 0) - break; - - RTMPusecDelay(2); - DBGPRINT(RT_DEBUG_INFO, ("AsicSendCommanToMcu::Mail box is busy\n")); - } while(i++ < 100); - - if (i >= 100) - { - DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n")); - return FALSE; - } - - H2MMailbox.field.Owner = 1; // pass ownership to MCU - H2MMailbox.field.CmdToken = Token; - H2MMailbox.field.HighByte = Arg1; - H2MMailbox.field.LowByte = Arg0; - RTMP_IO_FORCE_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word); - - H2MCmd.word = 0; - H2MCmd.field.HostCommand = Command; - RTMP_IO_FORCE_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word); - - - } - else -#endif // CONFIG_STA_SUPPORT // -#endif // PCIE_PS_SUPPORT // - { - do - { - RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word); - if (H2MMailbox.field.Owner == 0) - break; - - RTMPusecDelay(2); - } while(i++ < 100); - - if (i >= 100) - { -#ifdef RTMP_MAC_PCI -#ifdef RALINK_ATE - if (pAd->ate.bFWLoading == TRUE) - { - /* reloading firmware when received iwpriv cmd "ATE=ATESTOP" */ - if (j > 0) - { - if (j % 64 != 0) - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("#")); - } - else - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("\n")); - } - ++j; - } - else if (j == 0) - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("Loading firmware. Please wait for a moment...\n")); - ++j; - } - } - else -#endif // RALINK_ATE // -#endif // RTMP_MAC_PCI // - { - DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n")); - } - return FALSE; - } - -#ifdef RTMP_MAC_PCI -#ifdef RALINK_ATE - else if (pAd->ate.bFWLoading == TRUE) - { - /* reloading of firmware is completed */ - pAd->ate.bFWLoading = FALSE; - ATEDBGPRINT(RT_DEBUG_ERROR, ("\n")); - j = 0; - } -#endif // RALINK_ATE // -#endif // RTMP_MAC_PCI // - - H2MMailbox.field.Owner = 1; // pass ownership to MCU - H2MMailbox.field.CmdToken = Token; - H2MMailbox.field.HighByte = Arg1; - H2MMailbox.field.LowByte = Arg0; - RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word); - - H2MCmd.word = 0; - H2MCmd.field.HostCommand = Command; - RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word); - - if (Command != 0x80) - { - } -} -#ifdef PCIE_PS_SUPPORT -#ifdef CONFIG_STA_SUPPORT - // 3090 MCU Wakeup command needs more time to be stable. - // Before stable, don't issue other MCU command to prevent from firmware error. - if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd) - && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) - && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) - && (Command == WAKE_MCU_CMD)) - { - RTMPusecDelay(2000); - //Put this is after RF programming. - //NdisAcquireSpinLock(&pAd->McuCmdLock); - //pAd->brt30xxBanMcuCmd = FALSE; - //NdisReleaseSpinLock(&pAd->McuCmdLock); - } -#endif // CONFIG_STA_SUPPORT // -#endif // PCIE_PS_SUPPORT // - - return TRUE; -} diff --git a/drivers/staging/rt3090/common/spectrum.c b/drivers/staging/rt3090/common/spectrum.c deleted file mode 100644 index 12d2125148ba0a2d4d2522977be9e996be600a74..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/common/spectrum.c +++ /dev/null @@ -1,2221 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - action.c - - Abstract: - Handle association related requests either from WSTA or from local MLME - - Revision History: - Who When What - --------- ---------- ---------------------------------------------- - Fonchi Wu 2008 created for 802.11h - */ - -#include "../rt_config.h" -#include "../action.h" - - -/* The regulatory information in the USA (US) */ -DOT11_REGULATORY_INFORMATION USARegulatoryInfo[] = -{ -/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ - {0, {0, 0, {0}}}, // Invlid entry - {1, {4, 16, {36, 40, 44, 48}}}, - {2, {4, 23, {52, 56, 60, 64}}}, - {3, {4, 29, {149, 153, 157, 161}}}, - {4, {11, 23, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}}, - {5, {5, 30, {149, 153, 157, 161, 165}}}, - {6, {10, 14, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}}, - {7, {10, 27, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}}, - {8, {5, 17, {11, 13, 15, 17, 19}}}, - {9, {5, 30, {11, 13, 15, 17, 19}}}, - {10, {2, 20, {21, 25}}}, - {11, {2, 33, {21, 25}}}, - {12, {11, 30, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}} -}; -#define USA_REGULATORY_INFO_SIZE (sizeof(USARegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION)) - - -/* The regulatory information in Europe */ -DOT11_REGULATORY_INFORMATION EuropeRegulatoryInfo[] = -{ -/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ - {0, {0, 0, {0}}}, // Invalid entry - {1, {4, 20, {36, 40, 44, 48}}}, - {2, {4, 20, {52, 56, 60, 64}}}, - {3, {11, 30, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}}, - {4, {13, 20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}} -}; -#define EU_REGULATORY_INFO_SIZE (sizeof(EuropeRegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION)) - - -/* The regulatory information in Japan */ -DOT11_REGULATORY_INFORMATION JapanRegulatoryInfo[] = -{ -/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ - {0, {0, 0, {0}}}, // Invalid entry - {1, {4, 22, {34, 38, 42, 46}}}, - {2, {3, 24, {8, 12, 16}}}, - {3, {3, 24, {8, 12, 16}}}, - {4, {3, 24, {8, 12, 16}}}, - {5, {3, 24, {8, 12, 16}}}, - {6, {3, 22, {8, 12, 16}}}, - {7, {4, 24, {184, 188, 192, 196}}}, - {8, {4, 24, {184, 188, 192, 196}}}, - {9, {4, 24, {184, 188, 192, 196}}}, - {10, {4, 24, {184, 188, 192, 196}}}, - {11, {4, 22, {184, 188, 192, 196}}}, - {12, {4, 24, {7, 8, 9, 11}}}, - {13, {4, 24, {7, 8, 9, 11}}}, - {14, {4, 24, {7, 8, 9, 11}}}, - {15, {4, 24, {7, 8, 9, 11}}}, - {16, {6, 24, {183, 184, 185, 187, 188, 189}}}, - {17, {6, 24, {183, 184, 185, 187, 188, 189}}}, - {18, {6, 24, {183, 184, 185, 187, 188, 189}}}, - {19, {6, 24, {183, 184, 185, 187, 188, 189}}}, - {20, {6, 17, {183, 184, 185, 187, 188, 189}}}, - {21, {6, 24, {6, 7, 8, 9, 10, 11}}}, - {22, {6, 24, {6, 7, 8, 9, 10, 11}}}, - {23, {6, 24, {6, 7, 8, 9, 10, 11}}}, - {24, {6, 24, {6, 7, 8, 9, 10, 11}}}, - {25, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}}, - {26, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}}, - {27, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}}, - {28, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}}, - {29, {8, 17, {182, 183, 184, 185, 186, 187, 188, 189}}}, - {30, {13, 23, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}}, - {31, {1, 23, {14}}}, - {32, {4, 22, {52, 56, 60, 64}}} -}; -#define JP_REGULATORY_INFO_SIZE (sizeof(JapanRegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION)) - - -CHAR RTMP_GetTxPwr( - IN PRTMP_ADAPTER pAd, - IN HTTRANSMIT_SETTING HTTxMode) -{ -typedef struct __TX_PWR_CFG -{ - UINT8 Mode; - UINT8 MCS; - UINT16 req; - UINT8 shift; - UINT32 BitMask; -} TX_PWR_CFG; - - UINT32 Value; - INT Idx; - UINT8 PhyMode; - CHAR CurTxPwr; - UINT8 TxPwrRef = 0; - CHAR DaltaPwr; - ULONG TxPwr[5]; - - - TX_PWR_CFG TxPwrCfg[] = { - {MODE_CCK, 0, 0, 4, 0x000000f0}, - {MODE_CCK, 1, 0, 0, 0x0000000f}, - {MODE_CCK, 2, 0, 12, 0x0000f000}, - {MODE_CCK, 3, 0, 8, 0x00000f00}, - - {MODE_OFDM, 0, 0, 20, 0x00f00000}, - {MODE_OFDM, 1, 0, 16, 0x000f0000}, - {MODE_OFDM, 2, 0, 28, 0xf0000000}, - {MODE_OFDM, 3, 0, 24, 0x0f000000}, - {MODE_OFDM, 4, 1, 4, 0x000000f0}, - {MODE_OFDM, 5, 1, 0, 0x0000000f}, - {MODE_OFDM, 6, 1, 12, 0x0000f000}, - {MODE_OFDM, 7, 1, 8, 0x00000f00} -#ifdef DOT11_N_SUPPORT - ,{MODE_HTMIX, 0, 1, 20, 0x00f00000}, - {MODE_HTMIX, 1, 1, 16, 0x000f0000}, - {MODE_HTMIX, 2, 1, 28, 0xf0000000}, - {MODE_HTMIX, 3, 1, 24, 0x0f000000}, - {MODE_HTMIX, 4, 2, 4, 0x000000f0}, - {MODE_HTMIX, 5, 2, 0, 0x0000000f}, - {MODE_HTMIX, 6, 2, 12, 0x0000f000}, - {MODE_HTMIX, 7, 2, 8, 0x00000f00}, - {MODE_HTMIX, 8, 2, 20, 0x00f00000}, - {MODE_HTMIX, 9, 2, 16, 0x000f0000}, - {MODE_HTMIX, 10, 2, 28, 0xf0000000}, - {MODE_HTMIX, 11, 2, 24, 0x0f000000}, - {MODE_HTMIX, 12, 3, 4, 0x000000f0}, - {MODE_HTMIX, 13, 3, 0, 0x0000000f}, - {MODE_HTMIX, 14, 3, 12, 0x0000f000}, - {MODE_HTMIX, 15, 3, 8, 0x00000f00} -#endif // DOT11_N_SUPPORT // - }; -#define MAX_TXPWR_TAB_SIZE (sizeof(TxPwrCfg) / sizeof(TX_PWR_CFG)) - -#ifdef SINGLE_SKU - CurTxPwr = pAd->CommonCfg.DefineMaxTxPwr; -#else - CurTxPwr = 19; -#endif - - /* check Tx Power setting from UI. */ - if (pAd->CommonCfg.TxPowerPercentage > 90) - ; - else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */ - CurTxPwr -= 1; - else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */ - CurTxPwr -= 3; - else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */ - CurTxPwr -= 6; - else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */ - CurTxPwr -= 9; - else /* reduce Pwr for 12 dB. */ - CurTxPwr -= 12; - - if (pAd->CommonCfg.BBPCurrentBW == BW_40) - { - if (pAd->CommonCfg.CentralChannel > 14) - { - TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; - TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; - TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; - TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; - TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; - } - else - { - TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; - TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; - TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; - TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; - TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; - } - } - else - { - if (pAd->CommonCfg.Channel > 14) - { - TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; - TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; - TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; - TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; - TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; - } - else - { - TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; - TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; - TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; - TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; - TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; - } - } - - - switch(HTTxMode.field.MODE) - { - case MODE_CCK: - case MODE_OFDM: - Value = TxPwr[1]; - TxPwrRef = (Value & 0x00000f00) >> 8; - - break; - -#ifdef DOT11_N_SUPPORT - case MODE_HTMIX: - case MODE_HTGREENFIELD: - if (pAd->CommonCfg.TxStream == 1) - { - Value = TxPwr[2]; - TxPwrRef = (Value & 0x00000f00) >> 8; - } - else if (pAd->CommonCfg.TxStream == 2) - { - Value = TxPwr[3]; - TxPwrRef = (Value & 0x00000f00) >> 8; - } - break; -#endif // DOT11_N_SUPPORT // - } - - PhyMode = -#ifdef DOT11_N_SUPPORT - (HTTxMode.field.MODE == MODE_HTGREENFIELD) - ? MODE_HTMIX : -#endif // DOT11_N_SUPPORT // - HTTxMode.field.MODE; - - for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++) - { - if ((TxPwrCfg[Idx].Mode == PhyMode) - && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS)) - { - Value = TxPwr[TxPwrCfg[Idx].req]; - DaltaPwr = TxPwrRef - (CHAR)((Value & TxPwrCfg[Idx].BitMask) - >> TxPwrCfg[Idx].shift); - CurTxPwr -= DaltaPwr; - break; - } - } - - return CurTxPwr; -} - - -VOID MeasureReqTabInit( - IN PRTMP_ADAPTER pAd) -{ - NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock); - - pAd->CommonCfg.pMeasureReqTab = kmalloc(sizeof(MEASURE_REQ_TAB), GFP_ATOMIC); - if (pAd->CommonCfg.pMeasureReqTab) - NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, sizeof(MEASURE_REQ_TAB)); - else - DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __FUNCTION__)); - - return; -} - -VOID MeasureReqTabExit( - IN PRTMP_ADAPTER pAd) -{ - NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock); - - if (pAd->CommonCfg.pMeasureReqTab) - kfree(pAd->CommonCfg.pMeasureReqTab); - pAd->CommonCfg.pMeasureReqTab = NULL; - - return; -} - -PMEASURE_REQ_ENTRY MeasureReqLookUp( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken) -{ - UINT HashIdx; - PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; - PMEASURE_REQ_ENTRY pEntry = NULL; - PMEASURE_REQ_ENTRY pPrevEntry = NULL; - - if (pTab == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__)); - return NULL; - } - - RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); - - HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken); - pEntry = pTab->Hash[HashIdx]; - - while (pEntry) - { - if (pEntry->DialogToken == DialogToken) - break; - else - { - pPrevEntry = pEntry; - pEntry = pEntry->pNext; - } - } - - RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); - - return pEntry; -} - -PMEASURE_REQ_ENTRY MeasureReqInsert( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken) -{ - INT i; - ULONG HashIdx; - PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; - PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry; - ULONG Now; - - if(pTab == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__)); - return NULL; - } - - pEntry = MeasureReqLookUp(pAd, DialogToken); - if (pEntry == NULL) - { - RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); - for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++) - { - NdisGetSystemUpTime(&Now); - pEntry = &pTab->Content[i]; - - if ((pEntry->Valid == TRUE) - && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + MQ_REQ_AGE_OUT))) - { - PMEASURE_REQ_ENTRY pPrevEntry = NULL; - ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); - PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; - - // update Hash list - do - { - if (pProbeEntry == pEntry) - { - if (pPrevEntry == NULL) - { - pTab->Hash[HashIdx] = pEntry->pNext; - } - else - { - pPrevEntry->pNext = pEntry->pNext; - } - break; - } - - pPrevEntry = pProbeEntry; - pProbeEntry = pProbeEntry->pNext; - } while (pProbeEntry); - - NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY)); - pTab->Size--; - - break; - } - - if (pEntry->Valid == FALSE) - break; - } - - if (i < MAX_MEASURE_REQ_TAB_SIZE) - { - NdisGetSystemUpTime(&Now); - pEntry->lastTime = Now; - pEntry->Valid = TRUE; - pEntry->DialogToken = DialogToken; - pTab->Size++; - } - else - { - pEntry = NULL; - DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab tab full.\n", __FUNCTION__)); - } - - // add this Neighbor entry into HASH table - if (pEntry) - { - HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken); - if (pTab->Hash[HashIdx] == NULL) - { - pTab->Hash[HashIdx] = pEntry; - } - else - { - pCurrEntry = pTab->Hash[HashIdx]; - while (pCurrEntry->pNext != NULL) - pCurrEntry = pCurrEntry->pNext; - pCurrEntry->pNext = pEntry; - } - } - - RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); - } - - return pEntry; -} - -VOID MeasureReqDelete( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken) -{ - PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; - PMEASURE_REQ_ENTRY pEntry = NULL; - - if(pTab == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__)); - return; - } - - // if empty, return - if (pTab->Size == 0) - { - DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n")); - return; - } - - pEntry = MeasureReqLookUp(pAd, DialogToken); - if (pEntry != NULL) - { - PMEASURE_REQ_ENTRY pPrevEntry = NULL; - ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); - PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; - - RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); - // update Hash list - do - { - if (pProbeEntry == pEntry) - { - if (pPrevEntry == NULL) - { - pTab->Hash[HashIdx] = pEntry->pNext; - } - else - { - pPrevEntry->pNext = pEntry->pNext; - } - break; - } - - pPrevEntry = pProbeEntry; - pProbeEntry = pProbeEntry->pNext; - } while (pProbeEntry); - - NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY)); - pTab->Size--; - - RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); - } - - return; -} - -VOID TpcReqTabInit( - IN PRTMP_ADAPTER pAd) -{ - NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock); - - pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(TPC_REQ_TAB), GFP_ATOMIC); - if (pAd->CommonCfg.pTpcReqTab) - NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(TPC_REQ_TAB)); - else - DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __FUNCTION__)); - - return; -} - -VOID TpcReqTabExit( - IN PRTMP_ADAPTER pAd) -{ - NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock); - - if (pAd->CommonCfg.pTpcReqTab) - kfree(pAd->CommonCfg.pTpcReqTab); - pAd->CommonCfg.pTpcReqTab = NULL; - - return; -} - -static PTPC_REQ_ENTRY TpcReqLookUp( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken) -{ - UINT HashIdx; - PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; - PTPC_REQ_ENTRY pEntry = NULL; - PTPC_REQ_ENTRY pPrevEntry = NULL; - - if (pTab == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__)); - return NULL; - } - - RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); - - HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken); - pEntry = pTab->Hash[HashIdx]; - - while (pEntry) - { - if (pEntry->DialogToken == DialogToken) - break; - else - { - pPrevEntry = pEntry; - pEntry = pEntry->pNext; - } - } - - RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); - - return pEntry; -} - - -static PTPC_REQ_ENTRY TpcReqInsert( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken) -{ - INT i; - ULONG HashIdx; - PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; - PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry; - ULONG Now; - - if(pTab == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__)); - return NULL; - } - - pEntry = TpcReqLookUp(pAd, DialogToken); - if (pEntry == NULL) - { - RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); - for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++) - { - NdisGetSystemUpTime(&Now); - pEntry = &pTab->Content[i]; - - if ((pEntry->Valid == TRUE) - && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + TPC_REQ_AGE_OUT))) - { - PTPC_REQ_ENTRY pPrevEntry = NULL; - ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); - PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; - - // update Hash list - do - { - if (pProbeEntry == pEntry) - { - if (pPrevEntry == NULL) - { - pTab->Hash[HashIdx] = pEntry->pNext; - } - else - { - pPrevEntry->pNext = pEntry->pNext; - } - break; - } - - pPrevEntry = pProbeEntry; - pProbeEntry = pProbeEntry->pNext; - } while (pProbeEntry); - - NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY)); - pTab->Size--; - - break; - } - - if (pEntry->Valid == FALSE) - break; - } - - if (i < MAX_TPC_REQ_TAB_SIZE) - { - NdisGetSystemUpTime(&Now); - pEntry->lastTime = Now; - pEntry->Valid = TRUE; - pEntry->DialogToken = DialogToken; - pTab->Size++; - } - else - { - pEntry = NULL; - DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab tab full.\n", __FUNCTION__)); - } - - // add this Neighbor entry into HASH table - if (pEntry) - { - HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken); - if (pTab->Hash[HashIdx] == NULL) - { - pTab->Hash[HashIdx] = pEntry; - } - else - { - pCurrEntry = pTab->Hash[HashIdx]; - while (pCurrEntry->pNext != NULL) - pCurrEntry = pCurrEntry->pNext; - pCurrEntry->pNext = pEntry; - } - } - - RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); - } - - return pEntry; -} - -static VOID TpcReqDelete( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken) -{ - PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; - PTPC_REQ_ENTRY pEntry = NULL; - - if(pTab == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__)); - return; - } - - // if empty, return - if (pTab->Size == 0) - { - DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n")); - return; - } - - pEntry = TpcReqLookUp(pAd, DialogToken); - if (pEntry != NULL) - { - PTPC_REQ_ENTRY pPrevEntry = NULL; - ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); - PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; - - RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); - // update Hash list - do - { - if (pProbeEntry == pEntry) - { - if (pPrevEntry == NULL) - { - pTab->Hash[HashIdx] = pEntry->pNext; - } - else - { - pPrevEntry->pNext = pEntry->pNext; - } - break; - } - - pPrevEntry = pProbeEntry; - pProbeEntry = pProbeEntry->pNext; - } while (pProbeEntry); - - NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY)); - pTab->Size--; - - RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); - } - - return; -} - -/* - ========================================================================== - Description: - Get Current TimeS tamp. - - Parametrs: - - Return : Current Time Stamp. - ========================================================================== - */ -static UINT64 GetCurrentTimeStamp( - IN PRTMP_ADAPTER pAd) -{ - // get current time stamp. - return 0; -} - -/* - ========================================================================== - Description: - Get Current Transmit Power. - - Parametrs: - - Return : Current Time Stamp. - ========================================================================== - */ -static UINT8 GetCurTxPwr( - IN PRTMP_ADAPTER pAd, - IN UINT8 Wcid) -{ - return 16; /* 16 dBm */ -} - -/* - ========================================================================== - Description: - Get Current Transmit Power. - - Parametrs: - - Return : Current Time Stamp. - ========================================================================== - */ -VOID InsertChannelRepIE( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN PSTRING pCountry, - IN UINT8 RegulatoryClass) -{ - ULONG TempLen; - UINT8 Len; - UINT8 IEId = IE_AP_CHANNEL_REPORT; - PUCHAR pChListPtr = NULL; - - Len = 1; - if (strncmp(pCountry, "US", 2) == 0) - { - if (RegulatoryClass >= USA_REGULATORY_INFO_SIZE) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: USA Unknow Requlatory class (%d)\n", - __FUNCTION__, RegulatoryClass)); - return; - } - - Len += USARegulatoryInfo[RegulatoryClass].ChannelSet.NumberOfChannels; - pChListPtr = USARegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList; - } - else if (strncmp(pCountry, "JP", 2) == 0) - { - if (RegulatoryClass >= JP_REGULATORY_INFO_SIZE) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: JP Unknow Requlatory class (%d)\n", - __FUNCTION__, RegulatoryClass)); - return; - } - - Len += JapanRegulatoryInfo[RegulatoryClass].ChannelSet.NumberOfChannels; - pChListPtr = JapanRegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList; - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n", - __FUNCTION__, pCountry)); - return; - } - - MakeOutgoingFrame(pFrameBuf, &TempLen, - 1, &IEId, - 1, &Len, - 1, &RegulatoryClass, - Len -1, pChListPtr, - END_OF_ARGS); - - *pFrameLen = *pFrameLen + TempLen; - - return; -} - -/* - ========================================================================== - Description: - Insert Dialog Token into frame. - - Parametrs: - 1. frame buffer pointer. - 2. frame length. - 3. Dialog token. - - Return : None. - ========================================================================== - */ -VOID InsertDialogToken( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN UINT8 DialogToken) -{ - ULONG TempLen; - MakeOutgoingFrame(pFrameBuf, &TempLen, - 1, &DialogToken, - END_OF_ARGS); - - *pFrameLen = *pFrameLen + TempLen; - - return; -} - -/* - ========================================================================== - Description: - Insert TPC Request IE into frame. - - Parametrs: - 1. frame buffer pointer. - 2. frame length. - - Return : None. - ========================================================================== - */ - static VOID InsertTpcReqIE( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen) -{ - ULONG TempLen; - ULONG Len = 0; - UINT8 ElementID = IE_TPC_REQUEST; - - MakeOutgoingFrame(pFrameBuf, &TempLen, - 1, &ElementID, - 1, &Len, - END_OF_ARGS); - - *pFrameLen = *pFrameLen + TempLen; - - return; -} - -/* - ========================================================================== - Description: - Insert TPC Report IE into frame. - - Parametrs: - 1. frame buffer pointer. - 2. frame length. - 3. Transmit Power. - 4. Link Margin. - - Return : None. - ========================================================================== - */ -VOID InsertTpcReportIE( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN UINT8 TxPwr, - IN UINT8 LinkMargin) -{ - ULONG TempLen; - ULONG Len = sizeof(TPC_REPORT_INFO); - UINT8 ElementID = IE_TPC_REPORT; - TPC_REPORT_INFO TpcReportIE; - - TpcReportIE.TxPwr = TxPwr; - TpcReportIE.LinkMargin = LinkMargin; - - MakeOutgoingFrame(pFrameBuf, &TempLen, - 1, &ElementID, - 1, &Len, - Len, &TpcReportIE, - END_OF_ARGS); - - *pFrameLen = *pFrameLen + TempLen; - - - return; -} - -/* - ========================================================================== - Description: - Insert Channel Switch Announcement IE into frame. - - Parametrs: - 1. frame buffer pointer. - 2. frame length. - 3. channel switch announcement mode. - 4. new selected channel. - 5. channel switch announcement count. - - Return : None. - ========================================================================== - */ -static VOID InsertChSwAnnIE( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN UINT8 ChSwMode, - IN UINT8 NewChannel, - IN UINT8 ChSwCnt) -{ - ULONG TempLen; - ULONG Len = sizeof(CH_SW_ANN_INFO); - UINT8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT; - CH_SW_ANN_INFO ChSwAnnIE; - - ChSwAnnIE.ChSwMode = ChSwMode; - ChSwAnnIE.Channel = NewChannel; - ChSwAnnIE.ChSwCnt = ChSwCnt; - - MakeOutgoingFrame(pFrameBuf, &TempLen, - 1, &ElementID, - 1, &Len, - Len, &ChSwAnnIE, - END_OF_ARGS); - - *pFrameLen = *pFrameLen + TempLen; - - - return; -} - -/* - ========================================================================== - Description: - Insert Measure Request IE into frame. - - Parametrs: - 1. frame buffer pointer. - 2. frame length. - 3. Measure Token. - 4. Measure Request Mode. - 5. Measure Request Type. - 6. Measure Channel. - 7. Measure Start time. - 8. Measure Duration. - - - Return : None. - ========================================================================== - */ -static VOID InsertMeasureReqIE( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN UINT8 Len, - IN PMEASURE_REQ_INFO pMeasureReqIE) -{ - ULONG TempLen; - UINT8 ElementID = IE_MEASUREMENT_REQUEST; - - MakeOutgoingFrame(pFrameBuf, &TempLen, - 1, &ElementID, - 1, &Len, - sizeof(MEASURE_REQ_INFO), pMeasureReqIE, - END_OF_ARGS); - - *pFrameLen = *pFrameLen + TempLen; - - return; -} - -/* - ========================================================================== - Description: - Insert Measure Report IE into frame. - - Parametrs: - 1. frame buffer pointer. - 2. frame length. - 3. Measure Token. - 4. Measure Request Mode. - 5. Measure Request Type. - 6. Length of Report Infomation - 7. Pointer of Report Infomation Buffer. - - Return : None. - ========================================================================== - */ -static VOID InsertMeasureReportIE( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN PMEASURE_REPORT_INFO pMeasureReportIE, - IN UINT8 ReportLnfoLen, - IN PUINT8 pReportInfo) -{ - ULONG TempLen; - ULONG Len; - UINT8 ElementID = IE_MEASUREMENT_REPORT; - - Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen; - - MakeOutgoingFrame(pFrameBuf, &TempLen, - 1, &ElementID, - 1, &Len, - Len, pMeasureReportIE, - END_OF_ARGS); - - *pFrameLen = *pFrameLen + TempLen; - - if ((ReportLnfoLen > 0) && (pReportInfo != NULL)) - { - MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen, - ReportLnfoLen, pReportInfo, - END_OF_ARGS); - - *pFrameLen = *pFrameLen + TempLen; - } - return; -} - -/* - ========================================================================== - Description: - Prepare Measurement request action frame and enqueue it into - management queue waiting for transmition. - - Parametrs: - 1. the destination mac address of the frame. - - Return : None. - ========================================================================== - */ -VOID MakeMeasurementReqFrame( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pOutBuffer, - OUT PULONG pFrameLen, - IN UINT8 TotalLen, - IN UINT8 Category, - IN UINT8 Action, - IN UINT8 MeasureToken, - IN UINT8 MeasureReqMode, - IN UINT8 MeasureReqType, - IN UINT8 NumOfRepetitions) -{ - ULONG TempLen; - MEASURE_REQ_INFO MeasureReqIE; - - InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category, Action); - - // fill Dialog Token - InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen, MeasureToken); - - /* fill Number of repetitions. */ - if (Category == CATEGORY_RM) - { - MakeOutgoingFrame((pOutBuffer+*pFrameLen), &TempLen, - 2, &NumOfRepetitions, - END_OF_ARGS); - - *pFrameLen += TempLen; - } - - // prepare Measurement IE. - NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO)); - MeasureReqIE.Token = MeasureToken; - MeasureReqIE.ReqMode.word = MeasureReqMode; - MeasureReqIE.ReqType = MeasureReqType; - InsertMeasureReqIE(pAd, (pOutBuffer+*pFrameLen), pFrameLen, - TotalLen, &MeasureReqIE); - - return; -} - -/* - ========================================================================== - Description: - Prepare Measurement report action frame and enqueue it into - management queue waiting for transmition. - - Parametrs: - 1. the destination mac address of the frame. - - Return : None. - ========================================================================== - */ -VOID EnqueueMeasurementRep( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UINT8 DialogToken, - IN UINT8 MeasureToken, - IN UINT8 MeasureReqMode, - IN UINT8 MeasureReqType, - IN UINT8 ReportInfoLen, - IN PUINT8 pReportInfo) -{ - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen; - HEADER_802_11 ActHdr; - MEASURE_REPORT_INFO MeasureRepIE; - - // build action frame header. - MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, - pAd->CurrentAddress); - - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); - return; - } - NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); - FrameLen = sizeof(HEADER_802_11); - - InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRP); - - // fill Dialog Token - InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); - - // prepare Measurement IE. - NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO)); - MeasureRepIE.Token = MeasureToken; - MeasureRepIE.ReportMode = MeasureReqMode; - MeasureRepIE.ReportType = MeasureReqType; - InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureRepIE, ReportInfoLen, pReportInfo); - - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - return; -} - -/* - ========================================================================== - Description: - Prepare TPC Request action frame and enqueue it into - management queue waiting for transmition. - - Parametrs: - 1. the destination mac address of the frame. - - Return : None. - ========================================================================== - */ -VOID EnqueueTPCReq( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UCHAR DialogToken) -{ - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen; - - HEADER_802_11 ActHdr; - - // build action frame header. - MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, - pAd->CurrentAddress); - - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); - return; - } - NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); - FrameLen = sizeof(HEADER_802_11); - - InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRQ); - - // fill Dialog Token - InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); - - // Insert TPC Request IE. - InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen); - - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - return; -} - -/* - ========================================================================== - Description: - Prepare TPC Report action frame and enqueue it into - management queue waiting for transmition. - - Parametrs: - 1. the destination mac address of the frame. - - Return : None. - ========================================================================== - */ -VOID EnqueueTPCRep( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UINT8 DialogToken, - IN UINT8 TxPwr, - IN UINT8 LinkMargin) -{ - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen; - - HEADER_802_11 ActHdr; - - // build action frame header. - MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, - pAd->CurrentAddress); - - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); - return; - } - NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); - FrameLen = sizeof(HEADER_802_11); - - InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRP); - - // fill Dialog Token - InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); - - // Insert TPC Request IE. - InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, LinkMargin); - - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - return; -} - -/* - ========================================================================== - Description: - Prepare Channel Switch Announcement action frame and enqueue it into - management queue waiting for transmition. - - Parametrs: - 1. the destination mac address of the frame. - 2. Channel switch announcement mode. - 2. a New selected channel. - - Return : None. - ========================================================================== - */ -VOID EnqueueChSwAnn( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UINT8 ChSwMode, - IN UINT8 NewCh) -{ - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen; - - HEADER_802_11 ActHdr; - - // build action frame header. - MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, - pAd->CurrentAddress); - - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); - return; - } - NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); - FrameLen = sizeof(HEADER_802_11); - - InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH); - - InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, 0); - - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - return; -} - -static BOOLEAN DfsRequirementCheck( - IN PRTMP_ADAPTER pAd, - IN UINT8 Channel) -{ - BOOLEAN Result = FALSE; - INT i; - - do - { - // check DFS procedure is running. - // make sure DFS procedure won't start twice. - if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) - { - Result = FALSE; - break; - } - - // check the new channel carried from Channel Switch Announcemnet is valid. - for (i=0; iChannelListNum; i++) - { - if ((Channel == pAd->ChannelList[i].Channel) - &&(pAd->ChannelList[i].RemainingTimeForUse == 0)) - { - // found radar signal in the channel. the channel can't use at least for 30 minutes. - pAd->ChannelList[i].RemainingTimeForUse = 1800;//30 min = 1800 sec - Result = TRUE; - break; - } - } - } while(FALSE); - - return Result; -} - -VOID NotifyChSwAnnToPeerAPs( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pRA, - IN PUCHAR pTA, - IN UINT8 ChSwMode, - IN UINT8 Channel) -{ -#ifdef WDS_SUPPORT - if (!((pRA[0] & 0xff) == 0xff)) // is pRA a broadcase address. - { - INT i; - // info neighbor APs that Radar signal found throgh WDS link. - for (i = 0; i < MAX_WDS_ENTRY; i++) - { - if (ValidWdsEntry(pAd, i)) - { - PUCHAR pDA = pAd->WdsTab.WdsEntry[i].PeerWdsAddr; - - // DA equal to SA. have no necessary orignal AP which found Radar signal. - if (MAC_ADDR_EQUAL(pTA, pDA)) - continue; - - // send Channel Switch Action frame to info Neighbro APs. - EnqueueChSwAnn(pAd, pDA, ChSwMode, Channel); - } - } - } -#endif // WDS_SUPPORT // -} - -static VOID StartDFSProcedure( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel, - IN UINT8 ChSwMode) -{ - // start DFS procedure - pAd->CommonCfg.Channel = Channel; -#ifdef DOT11_N_SUPPORT - N_ChannelCheck(pAd); -#endif // DOT11_N_SUPPORT // - pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE; - pAd->CommonCfg.RadarDetect.CSCount = 0; -} - -/* - ========================================================================== - Description: - Channel Switch Announcement action frame sanity check. - - Parametrs: - 1. MLME message containing the received frame - 2. message length. - 3. Channel switch announcement infomation buffer. - - - Return : None. - ========================================================================== - */ - -/* - Channel Switch Announcement IE. - +----+-----+-----------+------------+-----------+ - | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt | - +----+-----+-----------+------------+-----------+ - 1 1 1 1 1 -*/ -static BOOLEAN PeerChSwAnnSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PCH_SW_ANN_INFO pChSwAnnInfo) -{ - PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; - PUCHAR pFramePtr = Fr->Octet; - BOOLEAN result = FALSE; - PEID_STRUCT eid_ptr; - - // skip 802.11 header. - MsgLen -= sizeof(HEADER_802_11); - - // skip category and action code. - pFramePtr += 2; - MsgLen -= 2; - - if (pChSwAnnInfo == NULL) - return result; - - eid_ptr = (PEID_STRUCT)pFramePtr; - while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) - { - switch(eid_ptr->Eid) - { - case IE_CHANNEL_SWITCH_ANNOUNCEMENT: - NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, 1); - NdisMoveMemory(&pChSwAnnInfo->Channel, eid_ptr->Octet + 1, 1); - NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, eid_ptr->Octet + 2, 1); - - result = TRUE; - break; - - default: - break; - } - eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); - } - - return result; -} - -/* - ========================================================================== - Description: - Measurement request action frame sanity check. - - Parametrs: - 1. MLME message containing the received frame - 2. message length. - 3. Measurement request infomation buffer. - - Return : None. - ========================================================================== - */ -static BOOLEAN PeerMeasureReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUINT8 pDialogToken, - OUT PMEASURE_REQ_INFO pMeasureReqInfo, - OUT PMEASURE_REQ pMeasureReq) -{ - PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; - PUCHAR pFramePtr = Fr->Octet; - BOOLEAN result = FALSE; - PEID_STRUCT eid_ptr; - PUCHAR ptr; - UINT64 MeasureStartTime; - UINT16 MeasureDuration; - - // skip 802.11 header. - MsgLen -= sizeof(HEADER_802_11); - - // skip category and action code. - pFramePtr += 2; - MsgLen -= 2; - - if (pMeasureReqInfo == NULL) - return result; - - NdisMoveMemory(pDialogToken, pFramePtr, 1); - pFramePtr += 1; - MsgLen -= 1; - - eid_ptr = (PEID_STRUCT)pFramePtr; - while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) - { - switch(eid_ptr->Eid) - { - case IE_MEASUREMENT_REQUEST: - NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, 1); - NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, eid_ptr->Octet + 1, 1); - NdisMoveMemory(&pMeasureReqInfo->ReqType, eid_ptr->Octet + 2, 1); - ptr = (PUCHAR)(eid_ptr->Octet + 3); - NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1); - NdisMoveMemory(&MeasureStartTime, ptr + 1, 8); - pMeasureReq->MeasureStartTime = SWAP64(MeasureStartTime); - NdisMoveMemory(&MeasureDuration, ptr + 9, 2); - pMeasureReq->MeasureDuration = SWAP16(MeasureDuration); - - result = TRUE; - break; - - default: - break; - } - eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); - } - - return result; -} - -/* - ========================================================================== - Description: - Measurement report action frame sanity check. - - Parametrs: - 1. MLME message containing the received frame - 2. message length. - 3. Measurement report infomation buffer. - 4. basic report infomation buffer. - - Return : None. - ========================================================================== - */ - -/* - Measurement Report IE. - +----+-----+-------+-------------+--------------+----------------+ - | ID | Len | Token | Report Mode | Measure Type | Measure Report | - +----+-----+-------+-------------+--------------+----------------+ - 1 1 1 1 1 variable - - Basic Report. - +--------+------------+----------+-----+ - | Ch Num | Start Time | Duration | Map | - +--------+------------+----------+-----+ - 1 8 2 1 - - Map Field Bit Format. - +-----+---------------+---------------------+-------+------------+----------+ - | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved | - +-----+---------------+---------------------+-------+------------+----------+ - 0 1 2 3 4 5-7 -*/ -static BOOLEAN PeerMeasureReportSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUINT8 pDialogToken, - OUT PMEASURE_REPORT_INFO pMeasureReportInfo, - OUT PUINT8 pReportBuf) -{ - PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; - PUCHAR pFramePtr = Fr->Octet; - BOOLEAN result = FALSE; - PEID_STRUCT eid_ptr; - PUCHAR ptr; - - // skip 802.11 header. - MsgLen -= sizeof(HEADER_802_11); - - // skip category and action code. - pFramePtr += 2; - MsgLen -= 2; - - if (pMeasureReportInfo == NULL) - return result; - - NdisMoveMemory(pDialogToken, pFramePtr, 1); - pFramePtr += 1; - MsgLen -= 1; - - eid_ptr = (PEID_STRUCT)pFramePtr; - while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) - { - switch(eid_ptr->Eid) - { - case IE_MEASUREMENT_REPORT: - NdisMoveMemory(&pMeasureReportInfo->Token, eid_ptr->Octet, 1); - NdisMoveMemory(&pMeasureReportInfo->ReportMode, eid_ptr->Octet + 1, 1); - NdisMoveMemory(&pMeasureReportInfo->ReportType, eid_ptr->Octet + 2, 1); - if (pMeasureReportInfo->ReportType == RM_BASIC) - { - PMEASURE_BASIC_REPORT pReport = (PMEASURE_BASIC_REPORT)pReportBuf; - ptr = (PUCHAR)(eid_ptr->Octet + 3); - NdisMoveMemory(&pReport->ChNum, ptr, 1); - NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); - NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); - NdisMoveMemory(&pReport->Map, ptr + 11, 1); - - } - else if (pMeasureReportInfo->ReportType == RM_CCA) - { - PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf; - ptr = (PUCHAR)(eid_ptr->Octet + 3); - NdisMoveMemory(&pReport->ChNum, ptr, 1); - NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); - NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); - NdisMoveMemory(&pReport->CCA_Busy_Fraction, ptr + 11, 1); - - } - else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM) - { - PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf; - ptr = (PUCHAR)(eid_ptr->Octet + 3); - NdisMoveMemory(&pReport->ChNum, ptr, 1); - NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); - NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); - NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 8); - } - result = TRUE; - break; - - default: - break; - } - eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); - } - - return result; -} - -/* - ========================================================================== - Description: - TPC Request action frame sanity check. - - Parametrs: - 1. MLME message containing the received frame - 2. message length. - 3. Dialog Token. - - Return : None. - ========================================================================== - */ -static BOOLEAN PeerTpcReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUINT8 pDialogToken) -{ - PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; - PUCHAR pFramePtr = Fr->Octet; - BOOLEAN result = FALSE; - PEID_STRUCT eid_ptr; - - MsgLen -= sizeof(HEADER_802_11); - - // skip category and action code. - pFramePtr += 2; - MsgLen -= 2; - - if (pDialogToken == NULL) - return result; - - NdisMoveMemory(pDialogToken, pFramePtr, 1); - pFramePtr += 1; - MsgLen -= 1; - - eid_ptr = (PEID_STRUCT)pFramePtr; - while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) - { - switch(eid_ptr->Eid) - { - case IE_TPC_REQUEST: - result = TRUE; - break; - - default: - break; - } - eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); - } - - return result; -} - -/* - ========================================================================== - Description: - TPC Report action frame sanity check. - - Parametrs: - 1. MLME message containing the received frame - 2. message length. - 3. Dialog Token. - 4. TPC Report IE. - - Return : None. - ========================================================================== - */ -static BOOLEAN PeerTpcRepSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUINT8 pDialogToken, - OUT PTPC_REPORT_INFO pTpcRepInfo) -{ - PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; - PUCHAR pFramePtr = Fr->Octet; - BOOLEAN result = FALSE; - PEID_STRUCT eid_ptr; - - MsgLen -= sizeof(HEADER_802_11); - - // skip category and action code. - pFramePtr += 2; - MsgLen -= 2; - - if (pDialogToken == NULL) - return result; - - NdisMoveMemory(pDialogToken, pFramePtr, 1); - pFramePtr += 1; - MsgLen -= 1; - - eid_ptr = (PEID_STRUCT)pFramePtr; - while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) - { - switch(eid_ptr->Eid) - { - case IE_TPC_REPORT: - NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1); - NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1); - result = TRUE; - break; - - default: - break; - } - eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); - } - - return result; -} - -/* - ========================================================================== - Description: - Channel Switch Announcement action frame handler. - - Parametrs: - Elme - MLME message containing the received frame - - Return : None. - ========================================================================== - */ -static VOID PeerChSwAnnAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - CH_SW_ANN_INFO ChSwAnnInfo; - PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; -#ifdef CONFIG_STA_SUPPORT - UCHAR index = 0, Channel = 0, NewChannel = 0; - ULONG Bssidx = 0; -#endif // CONFIG_STA_SUPPORT // - - NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO)); - if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) - { - DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n")); - return; - } - - -#ifdef CONFIG_STA_SUPPORT - if (pAd->OpMode == OPMODE_STA) - { - Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel); - if (Bssidx == BSS_NOT_FOUND) - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n")); - return; - } - - DBGPRINT(RT_DEBUG_TRACE, ("\n****Bssidx is %d, Channel = %d\n", index, pAd->ScanTab.BssEntry[Bssidx].Channel)); - hex_dump("SSID",pAd->ScanTab.BssEntry[Bssidx].Bssid ,6); - - Channel = pAd->CommonCfg.Channel; - NewChannel = ChSwAnnInfo.Channel; - - if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel)) - { - // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). - // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. - AsicSwitchChannel(pAd, 1, FALSE); - AsicLockChannel(pAd, 1); - LinkDown(pAd, FALSE); - MlmeQueueInit(&pAd->Mlme.Queue); - BssTableInit(&pAd->ScanTab); - RTMPusecDelay(1000000); // use delay to prevent STA do reassoc - - // channel sanity check - for (index = 0 ; index < pAd->ChannelListNum; index++) - { - if (pAd->ChannelList[index].Channel == NewChannel) - { - pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel; - pAd->CommonCfg.Channel = NewChannel; - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel)); - break; - } - } - - if (index >= pAd->ChannelListNum) - { - DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); - } - } - } -#endif // CONFIG_STA_SUPPORT // - - return; -} - - -/* - ========================================================================== - Description: - Measurement Request action frame handler. - - Parametrs: - Elme - MLME message containing the received frame - - Return : None. - ========================================================================== - */ -static VOID PeerMeasureReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; - UINT8 DialogToken; - MEASURE_REQ_INFO MeasureReqInfo; - MEASURE_REQ MeasureReq; - MEASURE_REPORT_MODE ReportMode; - - if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo, &MeasureReq)) - { - ReportMode.word = 0; - ReportMode.field.Incapable = 1; - EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL); - } - - return; -} - -/* - ========================================================================== - Description: - Measurement Report action frame handler. - - Parametrs: - Elme - MLME message containing the received frame - - Return : None. - ========================================================================== - */ -static VOID PeerMeasureReportAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - MEASURE_REPORT_INFO MeasureReportInfo; - PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; - UINT8 DialogToken; - PUINT8 pMeasureReportInfo; - -// if (pAd->CommonCfg.bIEEE80211H != TRUE) -// return; - - if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __FUNCTION__, sizeof(MEASURE_RPI_REPORT))); - return; - } - - NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO)); - NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT)); - if (PeerMeasureReportSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, pMeasureReportInfo)) - { - do { - PMEASURE_REQ_ENTRY pEntry = NULL; - - // Not a autonomous measure report. - // check the dialog token field. drop it if the dialog token doesn't match. - if ((DialogToken != 0) - && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL)) - break; - - if (pEntry != NULL) - MeasureReqDelete(pAd, pEntry->DialogToken); - - if (MeasureReportInfo.ReportType == RM_BASIC) - { - PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo; - if ((pBasicReport->Map.field.Radar) - && (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE)) - { - NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum); - StartDFSProcedure(pAd, pBasicReport->ChNum, 1); - } - } - } while (FALSE); - } - else - DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n")); - - kfree(pMeasureReportInfo); - - return; -} - -/* - ========================================================================== - Description: - TPC Request action frame handler. - - Parametrs: - Elme - MLME message containing the received frame - - Return : None. - ========================================================================== - */ -static VOID PeerTpcReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; - PUCHAR pFramePtr = pFr->Octet; - UINT8 DialogToken; - UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid); - UINT8 LinkMargin = 0; - CHAR RealRssi; - - // link margin: Ratio of the received signal power to the minimum desired by the station (STA). The - // STA may incorporate rate information and channel conditions, including interference, into its computation - // of link margin. - - RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), - ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), - ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); - - // skip Category and action code. - pFramePtr += 2; - - // Dialog token. - NdisMoveMemory(&DialogToken, pFramePtr, 1); - - LinkMargin = (RealRssi / MIN_RCV_PWR); - if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken)) - EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin); - - return; -} - -/* - ========================================================================== - Description: - TPC Report action frame handler. - - Parametrs: - Elme - MLME message containing the received frame - - Return : None. - ========================================================================== - */ -static VOID PeerTpcRepAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UINT8 DialogToken; - TPC_REPORT_INFO TpcRepInfo; - PTPC_REQ_ENTRY pEntry = NULL; - - NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO)); - if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) - { - if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL) - { - TpcReqDelete(pAd, pEntry->DialogToken); - DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n", - __FUNCTION__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin)); - } - } - - return; -} - -/* - ========================================================================== - Description: - Spectrun action frames Handler such as channel switch annoucement, - measurement report, measurement request actions frames. - - Parametrs: - Elme - MLME message containing the received frame - - Return : None. - ========================================================================== - */ -VOID PeerSpectrumAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - - UCHAR Action = Elem->Msg[LENGTH_802_11+1]; - - if (pAd->CommonCfg.bIEEE80211H != TRUE) - return; - - switch(Action) - { - case SPEC_MRQ: - // current rt2860 unable do such measure specified in Measurement Request. - // reject all measurement request. - PeerMeasureReqAction(pAd, Elem); - break; - - case SPEC_MRP: - PeerMeasureReportAction(pAd, Elem); - break; - - case SPEC_TPCRQ: - PeerTpcReqAction(pAd, Elem); - break; - - case SPEC_TPCRP: - PeerTpcRepAction(pAd, Elem); - break; - - case SPEC_CHANNEL_SWITCH: - -#ifdef DOT11N_DRAFT3 - { - SEC_CHA_OFFSET_IE Secondary; - CHA_SWITCH_ANNOUNCE_IE ChannelSwitch; - - // 802.11h only has Channel Switch Announcement IE. - RTMPMoveMemory(&ChannelSwitch, &Elem->Msg[LENGTH_802_11+4], sizeof (CHA_SWITCH_ANNOUNCE_IE)); - - // 802.11n D3.03 adds secondary channel offset element in the end. - if (Elem->MsgLen == (LENGTH_802_11 + 2 + sizeof (CHA_SWITCH_ANNOUNCE_IE) + sizeof (SEC_CHA_OFFSET_IE))) - { - RTMPMoveMemory(&Secondary, &Elem->Msg[LENGTH_802_11+9], sizeof (SEC_CHA_OFFSET_IE)); - } - else - { - Secondary.SecondaryChannelOffset = 0; - } - - if ((Elem->Msg[LENGTH_802_11+2] == IE_CHANNEL_SWITCH_ANNOUNCEMENT) && (Elem->Msg[LENGTH_802_11+3] == 3)) - { - ChannelSwitchAction(pAd, Elem->Wcid, ChannelSwitch.NewChannel, Secondary.SecondaryChannelOffset); - } - } -#endif // DOT11N_DRAFT3 // - - PeerChSwAnnAction(pAd, Elem); - break; - } - - return; -} - -/* - ========================================================================== - Description: - - Parametrs: - - Return : None. - ========================================================================== - */ -INT Set_MeasureReq_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UINT Aid = 1; - UINT ArgIdx; - PSTRING thisChar; - - MEASURE_REQ_MODE MeasureReqMode; - UINT8 MeasureReqToken = RandomByte(pAd); - UINT8 MeasureReqType = RM_BASIC; - UINT8 MeasureCh = 1; - UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd); - MEASURE_REQ MeasureReq; - UINT8 TotalLen; - - HEADER_802_11 ActHdr; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen; - - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); - goto END_OF_MEASURE_REQ; - } - - ArgIdx = 1; - while ((thisChar = strsep((char **)&arg, "-")) != NULL) - { - switch(ArgIdx) - { - case 1: // Aid. - Aid = (UINT8) simple_strtol(thisChar, 0, 16); - break; - - case 2: // Measurement Request Type. - MeasureReqType = simple_strtol(thisChar, 0, 16); - if (MeasureReqType > 3) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __FUNCTION__, MeasureReqType)); - goto END_OF_MEASURE_REQ; - } - break; - - case 3: // Measurement channel. - MeasureCh = (UINT8) simple_strtol(thisChar, 0, 16); - break; - } - ArgIdx++; - } - - DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __FUNCTION__, Aid, MeasureReqType, MeasureCh)); - if (!VALID_WCID(Aid)) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid)); - goto END_OF_MEASURE_REQ; - } - - MeasureReqMode.word = 0; - MeasureReqMode.field.Enable = 1; - - MeasureReqInsert(pAd, MeasureReqToken); - - // build action frame header. - MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pAd->MacTab.Content[Aid].Addr, - pAd->CurrentAddress); - - NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); - FrameLen = sizeof(HEADER_802_11); - - TotalLen = sizeof(MEASURE_REQ_INFO) + sizeof(MEASURE_REQ); - - MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen, - sizeof(MEASURE_REQ_INFO), CATEGORY_RM, RM_BASIC, - MeasureReqToken, MeasureReqMode.word, - MeasureReqType, 0); - - MeasureReq.ChNum = MeasureCh; - MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime); - MeasureReq.MeasureDuration = cpu2le16(2000); - - { - ULONG TempLen; - MakeOutgoingFrame( pOutBuffer+FrameLen, &TempLen, - sizeof(MEASURE_REQ), &MeasureReq, - END_OF_ARGS); - FrameLen += TempLen; - } - - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (UINT)FrameLen); - -END_OF_MEASURE_REQ: - MlmeFreeMemory(pAd, pOutBuffer); - - return TRUE; -} - -INT Set_TpcReq_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UINT Aid; - - UINT8 TpcReqToken = RandomByte(pAd); - - Aid = (UINT) simple_strtol(arg, 0, 16); - - DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __FUNCTION__, Aid)); - if (!VALID_WCID(Aid)) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid)); - return TRUE; - } - - TpcReqInsert(pAd, TpcReqToken); - - EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken); - - return TRUE; -} diff --git a/drivers/staging/rt3090/config.mk b/drivers/staging/rt3090/config.mk deleted file mode 100644 index 4c90c4060d1059018dd03ee27a767c052611d23d..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/config.mk +++ /dev/null @@ -1,187 +0,0 @@ -# Support ATE function -HAS_ATE=y - -# Support 28xx QA ATE function -HAS_28xx_QA=n - - -HAS_NINTENDO=n - -# Support LLTD function -HAS_LLTD=n - -# Support WDS function -HAS_WDS=n - -# Support AP-Client function -HAS_APCLI=n - -# Support Wpa_Supplicant -HAS_WPA_SUPPLICANT=y - -# Support Native WpaSupplicant for Network Maganger -HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y - -#Support Net interface block while Tx-Sw queue full -HAS_BLOCK_NET_IF=n - -#Support IGMP-Snooping function. -HAS_IGMP_SNOOP_SUPPORT=n - -#Support DFS function -HAS_DFS_SUPPORT=n - -#Support Carrier-Sense function -HAS_CS_SUPPORT=n - -# Support for STA Ethernet Converter -HAS_ETH_CONVERT_SUPPORT=n - -# Support user specific transmit rate of Multicast packet. -HAS_MCAST_RATE_SPECIFIC_SUPPORT=n - -# Support for Multiple Cards -HAS_MC_SUPPORT=n - -#Support for PCI-MSI -HAS_MSI_SUPPORT=n - - -#Support for IEEE802.11e DLS -HAS_QOS_DLS_SUPPORT=n - -#Support for EXT_CHANNEL -HAS_EXT_BUILD_CHANNEL_LIST=n - -#Support for IDS -HAS_IDS_SUPPORT=n - - -#Support for Net-SNMP -HAS_SNMP_SUPPORT=n - -#Support features of 802.11n Draft3 -HAS_DOT11N_DRAFT3_SUPPORT=n - -#Support features of Single SKU. -HAS_SINGLE_SKU_SUPPORT=n - -#Support features of 802.11n -HAS_DOT11_N_SUPPORT=y - - - -#Support for 2860/2880 co-exist -HAS_RT2880_RT2860_COEXIST=n - -HAS_KTHREAD_SUPPORT=n - - -#Support for Auto channel select enhance -HAS_AUTO_CH_SELECT_ENHANCE=n - -#Support bypass bridge -HAS_BG_FT_SUPPORT=n - -#Support Antenna Diversity -HAS_ANTENNA_DIVERSITY_SUPPORT=y -################################################# - -WFLAGS := -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -DLINUX -Wall -Wstrict-prototypes -Wno-trigraphs -Wpointer-sign - -ifeq ($(HAS_KTHREAD_SUPPORT),y) -WFLAGS += -DKTHREAD_SUPPORT -endif - - -################################################# - -# config for STA mode - -WFLAGS += -DCONFIG_STA_SUPPORT -DDBG - -ifeq ($(HAS_WPA_SUPPLICANT),y) -WFLAGS += -DWPA_SUPPLICANT_SUPPORT -ifeq ($(HAS_NATIVE_WPA_SUPPLICANT_SUPPORT),y) -WFLAGS += -DNATIVE_WPA_SUPPLICANT_SUPPORT -endif -endif - - -ifeq ($(HAS_ETH_CONVERT_SUPPORT), y) -WFLAGS += -DETH_CONVERT_SUPPORT -DMAT_SUPPORT -endif - -ifeq ($(HAS_ATE),y) -WFLAGS += -DRALINK_ATE -ifeq ($(HAS_28xx_QA),y) -WFLAGS += -DRALINK_28xx_QA -endif -endif - - -ifeq ($(HAS_SNMP_SUPPORT),y) -WFLAGS += -DSNMP_SUPPORT -endif - -ifeq ($(HAS_QOS_DLS_SUPPORT),y) -WFLAGS += -DQOS_DLS_SUPPORT -endif - -ifeq ($(HAS_DOT11_N_SUPPORT),y) -WFLAGS += -DDOT11_N_SUPPORT -endif - -ifeq ($(HAS_CS_SUPPORT),y) -WFLAGS += -DCARRIER_DETECTION_SUPPORT -endif - -ifeq ($(HAS_ANTENNA_DIVERSITY_SUPPORT),y) -WFLAGS += -DANT_DIVERSITY_SUPPORT -endif - -################################################# - -################################################# - -# -# Common compiler flag -# - - - - - -ifeq ($(HAS_EXT_BUILD_CHANNEL_LIST),y) -WFLAGS += -DEXT_BUILD_CHANNEL_LIST -endif - -ifeq ($(HAS_IDS_SUPPORT),y) -WFLAGS += -DIDS_SUPPORT -endif - - -################################################# -# ChipSet specific definitions. -# -WFLAGS +=-DRTMP_MAC_PCI -DRT30xx -DRT3090 -DRTMP_PCI_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -################################################# - - -ifeq ($(HAS_BLOCK_NET_IF),y) -WFLAGS += -DBLOCK_NET_IF -endif - -ifeq ($(HAS_DFS_SUPPORT),y) -WFLAGS += -DDFS_SUPPORT -endif - -ifeq ($(HAS_MC_SUPPORT),y) -WFLAGS += -DMULTIPLE_CARD_SUPPORT -endif - -ifeq ($(HAS_LLTD),y) -WFLAGS += -DLLTD_SUPPORT -endif - -EXTRA_CFLAGS := $(WFLAGS) diff --git a/drivers/staging/rt3090/crypt_sha2.h b/drivers/staging/rt3090/crypt_sha2.h deleted file mode 100644 index 85c0403d725a3ff803e8113f13259585199a85cd..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/crypt_sha2.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - crypt_sha2.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Eddy 2008/11/24 Create SHA1 - Eddy 2008/07/23 Create SHA256 -*/ - -#ifndef __CRYPT_SHA2_H__ -#define __CRYPT_SHA2_H__ - -#ifdef CRYPT_TESTPLAN -#include "crypt_testplan.h" -#else -#include "rt_config.h" -#endif /* CRYPT_TESTPLAN */ - -/* Algorithm options */ -#define SHA1_SUPPORT -#define SHA256_SUPPORT - -#ifdef SHA1_SUPPORT -#define SHA1_BLOCK_SIZE 64 /* 512 bits = 64 bytes */ -#define SHA1_DIGEST_SIZE 20 /* 160 bits = 20 bytes */ -typedef struct _SHA1_CTX_STRUC { - UINT32 HashValue[5]; /* 5 = (SHA1_DIGEST_SIZE / 32) */ - UINT64 MessageLen; /* total size */ - UINT8 Block[SHA1_BLOCK_SIZE]; - UINT BlockLen; -} SHA1_CTX_STRUC, *PSHA1_CTX_STRUC; - -VOID SHA1_Init ( - IN SHA1_CTX_STRUC *pSHA_CTX); -VOID SHA1_Hash ( - IN SHA1_CTX_STRUC *pSHA_CTX); -VOID SHA1_Append ( - IN SHA1_CTX_STRUC *pSHA_CTX, - IN const UINT8 Message[], - IN UINT MessageLen); -VOID SHA1_End ( - IN SHA1_CTX_STRUC *pSHA_CTX, - OUT UINT8 DigestMessage[]); -VOID RT_SHA1 ( - IN const UINT8 Message[], - IN UINT MessageLen, - OUT UINT8 DigestMessage[]); -#endif /* SHA1_SUPPORT */ - -#ifdef SHA256_SUPPORT -#define SHA256_BLOCK_SIZE 64 /* 512 bits = 64 bytes */ -#define SHA256_DIGEST_SIZE 32 /* 256 bits = 32 bytes */ -typedef struct _SHA256_CTX_STRUC { - UINT32 HashValue[8]; /* 8 = (SHA256_DIGEST_SIZE / 32) */ - UINT64 MessageLen; /* total size */ - UINT8 Block[SHA256_BLOCK_SIZE]; - UINT BlockLen; -} SHA256_CTX_STRUC, *PSHA256_CTX_STRUC; - -VOID SHA256_Init ( - IN SHA256_CTX_STRUC *pSHA_CTX); -VOID SHA256_Hash ( - IN SHA256_CTX_STRUC *pSHA_CTX); -VOID SHA256_Append ( - IN SHA256_CTX_STRUC *pSHA_CTX, - IN const UINT8 Message[], - IN UINT MessageLen); -VOID SHA256_End ( - IN SHA256_CTX_STRUC *pSHA_CTX, - OUT UINT8 DigestMessage[]); -VOID RT_SHA256 ( - IN const UINT8 Message[], - IN UINT MessageLen, - OUT UINT8 DigestMessage[]); -#endif /* SHA256_SUPPORT */ - -#endif /* __CRYPT_SHA2_H__ */ diff --git a/drivers/staging/rt3090/dfs.h b/drivers/staging/rt3090/dfs.h deleted file mode 100644 index 506468ea952f0359665ed0337288f14ea60d2d74..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/dfs.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - dfs.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Fonchi 03-12-2007 created -*/ - -#define RADAR_PULSE 1 -#define RADAR_WIDTH 2 - -#define WIDTH_RD_IDLE 0 -#define WIDTH_RD_CHECK 1 - - - -/************************************************************************* - * - * DFS Radar related definitions. - * - ************************************************************************/ -//#define CARRIER_DETECT_TASK_NUM 6 -//#define RADAR_DETECT_TASK_NUM 7 - -// McuRadarState && McuCarrierState for 2880-SW-MCU -#define FREE_FOR_TX 0 -#define WAIT_CTS_BEING_SENT 1 -#define DO_DETECTION 2 - -// McuRadarEvent -#define RADAR_EVENT_CTS_SENT 0x01 // Host signal MCU that CTS has been sent -#define RADAR_EVENT_CTS_CARRIER_SENT 0x02 // Host signal MCU that CTS has been sent (Carrier) -#define RADAR_EVENT_RADAR_DETECTING 0x04 // Radar detection is on going, carrier detection hold back -#define RADAR_EVENT_CARRIER_DETECTING 0x08 // Carrier detection is on going, radar detection hold back -#define RADAR_EVENT_WIDTH_RADAR 0x10 // BBP == 2 radar detected -#define RADAR_EVENT_CTS_KICKED 0x20 // Radar detection need to sent double CTS, first CTS sent - -// McuRadarCmd -#define DETECTION_STOP 0 -#define RADAR_DETECTION 1 -#define CARRIER_DETECTION 2 - - - -#ifdef TONE_RADAR_DETECT_SUPPORT -INT Set_CarrierCriteria_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); -int Set_CarrierReCheck_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); -INT Set_CarrierStopCheck_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); -void NewCarrierDetectionStart(PRTMP_ADAPTER pAd); -void RTMPHandleRadarInterrupt(PRTMP_ADAPTER pAd); -VOID CSAsicDisableSync(IN PRTMP_ADAPTER pAd); -#endif // TONE_RADAR_DETECT_SUPPORT // - - -VOID BbpRadarDetectionStart( - IN PRTMP_ADAPTER pAd); - -VOID BbpRadarDetectionStop( - IN PRTMP_ADAPTER pAd); - -VOID RadarDetectionStart( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN CTS_Protect, - IN UINT8 CTSPeriod); - -VOID RadarDetectionStop( - IN PRTMP_ADAPTER pAd); - -VOID RadarDetectPeriodic( - IN PRTMP_ADAPTER pAd); - - -BOOLEAN RadarChannelCheck( - IN PRTMP_ADAPTER pAd, - IN UCHAR Ch); - -ULONG JapRadarType( - IN PRTMP_ADAPTER pAd); - -ULONG RTMPBbpReadRadarDuration( - IN PRTMP_ADAPTER pAd); - -ULONG RTMPReadRadarDuration( - IN PRTMP_ADAPTER pAd); - -VOID RTMPCleanRadarDuration( - IN PRTMP_ADAPTER pAd); - -VOID RTMPPrepareRDCTSFrame( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN ULONG Duration, - IN UCHAR RTSRate, - IN ULONG CTSBaseAddr, - IN UCHAR FrameGap); - -VOID RTMPPrepareRadarDetectParams( - IN PRTMP_ADAPTER pAd); - - -INT Set_ChMovingTime_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_LongPulseRadarTh_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); diff --git a/drivers/staging/rt3090/firmware.h b/drivers/staging/rt3090/firmware.h index f2836a22cb8e761860ce63994ec2f244fd8e6af2..17056e26795b34989f2e2a25b5772fd14e8930b0 100644 --- a/drivers/staging/rt3090/firmware.h +++ b/drivers/staging/rt3090/firmware.h @@ -2,7 +2,7 @@ /* AUTO GEN PLEASE DO NOT MODIFY IT */ -UCHAR FirmwareImage [] = { +u8 FirmwareImage_3090 [] = { 0x02, 0x02, 0xf3, 0x02, 0x02, 0xa1, 0x22, 0x22, 0xff, 0xff, 0xff, 0x02, 0x01, 0x27, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0xd8, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18, 0xc2, 0xaf, 0x30, 0x45, 0x03, diff --git a/drivers/staging/rt3090/igmp_snoop.h b/drivers/staging/rt3090/igmp_snoop.h deleted file mode 100644 index 63f9692e0b35ac12fa9b523e0c9e7d21b2f16edd..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/igmp_snoop.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - igmp_snoop.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - - -#ifndef __RTMP_IGMP_SNOOP_H__ -#define __RTMP_IGMP_SNOOP_H__ - -#include "link_list.h" - -#define IGMP_PROTOCOL_DESCRIPTOR 0x02 -#define IGMP_V1_MEMBERSHIP_REPORT 0x12 -#define IGMP_V2_MEMBERSHIP_REPORT 0x16 -#define IGMP_LEAVE_GROUP 0x17 -#define IGMP_V3_MEMBERSHIP_REPORT 0x22 - -#define MLD_V1_LISTENER_REPORT 131 -#define MLD_V1_LISTENER_DONE 132 -#define MLD_V2_LISTERNER_REPORT 143 - -#define IGMPMAC_TB_ENTRY_AGEOUT_TIME 120 * OS_HZ - -#define MULTICAST_ADDR_HASH_INDEX(Addr) (MAC_ADDR_HASH(Addr) % (MAX_LEN_OF_MULTICAST_FILTER_HASH_TABLE)) - -#define IS_MULTICAST_MAC_ADDR(Addr) ((((Addr[0]) & 0x01) == 0x01) && ((Addr[0]) != 0xff)) -#define IS_BROADCAST_MAC_ADDR(Addr) ((((Addr[0]) & 0xff) == 0xff)) - -VOID MulticastFilterTableInit( - IN PMULTICAST_FILTER_TABLE *ppMulticastFilterTable); - -VOID MultiCastFilterTableReset( - IN PMULTICAST_FILTER_TABLE *ppMulticastFilterTable); - -BOOLEAN MulticastFilterTableInsertEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pGrpId, - IN PUCHAR pMemberAddr, - IN PNET_DEV dev, - IN MulticastFilterEntryType type); - -BOOLEAN MulticastFilterTableDeleteEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pGrpId, - IN PUCHAR pMemberAddr, - IN PNET_DEV dev); - -PMULTICAST_FILTER_TABLE_ENTRY MulticastFilterTableLookup( - IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, - IN PUCHAR pAddr, - IN PNET_DEV dev); - -BOOLEAN isIgmpPkt( - IN PUCHAR pDstMacAddr, - IN PUCHAR pIpHeader); - -VOID IGMPSnooping( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDstMacAddr, - IN PUCHAR pSrcMacAddr, - IN PUCHAR pIpHeader, - IN PNET_DEV pDev); - -BOOLEAN isMldPkt( - IN PUCHAR pDstMacAddr, - IN PUCHAR pIpHeader, - OUT UINT8 *pProtoType, - OUT PUCHAR *pMldHeader); - -VOID MLDSnooping( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDstMacAddr, - IN PUCHAR pSrcMacAddr, - IN PUCHAR pIpHeader, - IN PNET_DEV pDev); - -UCHAR IgmpMemberCnt( - IN PLIST_HEADER pList); - -VOID IgmpGroupDelMembers( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pMemberAddr, - IN PNET_DEV pDev); - -INT Set_IgmpSn_Enable_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_IgmpSn_AddEntry_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_IgmpSn_DelEntry_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_IgmpSn_TabDisplay_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -void rtmp_read_igmp_snoop_from_file( - IN PRTMP_ADAPTER pAd, - PSTRING tmpbuf, - PSTRING buffer); - -NDIS_STATUS IgmpPktInfoQuery( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pSrcBufVA, - IN PNDIS_PACKET pPacket, - IN UCHAR apidx, - OUT BOOLEAN *pInIgmpGroup, - OUT PMULTICAST_FILTER_TABLE_ENTRY *ppGroupEntry); - -NDIS_STATUS IgmpPktClone( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR QueIdx, - IN PMULTICAST_FILTER_TABLE_ENTRY pGroupEntry); - -#endif /* __RTMP_IGMP_SNOOP_H__ */ diff --git a/drivers/staging/rt3090/ipv6.h b/drivers/staging/rt3090/ipv6.h deleted file mode 100644 index c34a5f2569dd9d28fb4cf2026ad3968eee2dde68..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/ipv6.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - ipv6.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#ifndef __IPV6_HDR_H_ -#define __IPV6_HDR_H_ - -#define IPV6_ADDR_LEN 16 -#define IPV6_HDR_LEN 40 - -// IPv6 address definition -#define IPV6_LINK_LOCAL_ADDR_PREFIX 0xFE8 -#define IPV6_SITE_LOCAL_ADDR_PREFIX 0xFEC -#define IPV6_LOCAL_ADDR_PREFIX 0xFE8 -#define IPV6_MULTICAST_ADDR_PREFIX 0xFF -#define IPV6_LOOPBACK_ADDR 0x1 -#define IPV6_UNSPECIFIED_ADDR 0x0 - -// defined as sequence in IPv6 header -#define IPV6_NEXT_HEADER_HOP_BY_HOP 0x00 // 0 -#define IPV6_NEXT_HEADER_DESTINATION 0x3c // 60 -#define IPV6_NEXT_HEADER_ROUTING 0x2b // 43 -#define IPV6_NEXT_HEADER_FRAGMENT 0x2c // 44 -#define IPV6_NEXT_HEADER_AUTHENTICATION 0x33 // 51 -#define IPV6_NEXT_HEADER_ENCAPSULATION 0x32 // 50, RFC-2406 -#define IPV6_NEXT_HEADER_NONE 0x3b // 59 - -#define IPV6_NEXT_HEADER_TCP 0x06 -#define IPV6_NEXT_HEADER_UDP 0x11 -#define IPV6_NEXT_HEADER_ICMPV6 0x3a - -// ICMPv6 msg type definition -#define ICMPV6_MSG_TYPE_ROUTER_SOLICITATION 0x85 // 133 -#define ROUTER_SOLICITATION_FIXED_LEN 8 - -#define ICMPV6_MSG_TYPE_ROUTER_ADVERTISEMENT 0x86 // 134 -#define ROUTER_ADVERTISEMENT_FIXED_LEN 16 - -#define ICMPV6_MSG_TYPE_NEIGHBOR_SOLICITATION 0x87 // 135 -#define NEIGHBOR_SOLICITATION_FIXED_LEN 24 - -#define ICMPV6_MSG_TYPE_NEIGHBOR_ADVERTISEMENT 0x88 // 136 -#define NEIGHBOR_ADVERTISEMENT_FIXED_LEN 24 - -#define ICMPV6_MSG_TYPE_REDIRECT 0x89 // 137 -#define REDIRECT_FIXED_LEN 40 - -/* IPv6 Address related structures */ -typedef struct rt_ipv6_addr_ -{ - union - { - UCHAR ipv6Addr8[16]; - USHORT ipv6Addr16[8]; - UINT32 ipv6Addr32[4]; - }addr; -#define ipv6_addr addr.ipv6Addr8 -#define ipv6_addr16 addr.ipv6Addr16 -#define ipv6_addr32 addr.ipv6Addr32 -}RT_IPV6_ADDR, *PRT_IPV6_ADDR; - - -#define PRINT_IPV6_ADDR(ipv6Addr) \ - OS_NTOHS((ipv6Addr).ipv6_addr16[0]), \ - OS_NTOHS((ipv6Addr).ipv6_addr16[1]), \ - OS_NTOHS((ipv6Addr).ipv6_addr16[2]), \ - OS_NTOHS((ipv6Addr).ipv6_addr16[3]), \ - OS_NTOHS((ipv6Addr).ipv6_addr16[4]), \ - OS_NTOHS((ipv6Addr).ipv6_addr16[5]), \ - OS_NTOHS((ipv6Addr).ipv6_addr16[6]), \ - OS_NTOHS((ipv6Addr).ipv6_addr16[7]) - - -/*IPv6 Header related structures */ -typedef struct PACKED _rt_ipv6_hdr_ -{ - UINT32 ver:4, - trafficClass:8, - flowLabel:20; - USHORT payload_len; - UCHAR nextHdr; - UCHAR hopLimit; - RT_IPV6_ADDR srcAddr; - RT_IPV6_ADDR dstAddr; -}RT_IPV6_HDR, *PRT_IPV6_HDR; - - -typedef struct PACKED _rt_ipv6_ext_hdr_ -{ - UCHAR nextProto; // Indicate the protocol type of next extension header. - UCHAR extHdrLen; // optional field for msg length of this extension header which didn't include the first "nextProto" field. - UCHAR octets[1]; // hook to extend header message body. -}RT_IPV6_EXT_HDR, *PRT_IPV6_EXT_HDR; - - -/* ICMPv6 related structures */ -typedef struct PACKED _rt_ipv6_icmpv6_hdr_ -{ - UCHAR type; - UCHAR code; - USHORT chksum; - UCHAR octets[1]; //hook to extend header message body. -}RT_ICMPV6_HDR, *PRT_ICMPV6_HDR; - - -typedef struct PACKED _rt_icmp6_option_hdr_ -{ - UCHAR type; - UCHAR len; - UCHAR octet[1]; -}RT_ICMPV6_OPTION_HDR, *PRT_ICMPV6_OPTION_HDR; - -typedef enum{ -// Defined ICMPv6 Option Types. - TYPE_SRC_LL_ADDR = 1, - TYPE_TGT_LL_ADDR = 2, - TYPE_PREFIX_INFO = 3, - TYPE_REDIRECTED_HDR = 4, - TYPE_MTU = 5, -}ICMPV6_OPTIONS_TYPE_DEF; - - -static inline BOOLEAN IPv6ExtHdrHandle( - RT_IPV6_EXT_HDR *pExtHdr, - UCHAR *pProto, - UINT32 *pOffset) -{ - UCHAR nextProto = 0xff; - UINT32 extLen = 0; - BOOLEAN status = TRUE; - - //printk("%s(): parsing the Extension Header with Protocol(0x%x):\n", __FUNCTION__, *pProto); - switch (*pProto) - { - case IPV6_NEXT_HEADER_HOP_BY_HOP: - // IPv6ExtHopByHopHandle(); - nextProto = pExtHdr->nextProto; - extLen = (pExtHdr->extHdrLen + 1) * 8; - break; - - case IPV6_NEXT_HEADER_DESTINATION: - // IPv6ExtDestHandle(); - nextProto = pExtHdr->nextProto; - extLen = (pExtHdr->extHdrLen + 1) * 8; - break; - - case IPV6_NEXT_HEADER_ROUTING: - // IPv6ExtRoutingHandle(); - nextProto = pExtHdr->nextProto; - extLen = (pExtHdr->extHdrLen + 1) * 8; - break; - - case IPV6_NEXT_HEADER_FRAGMENT: - // IPv6ExtFragmentHandle(); - nextProto = pExtHdr->nextProto; - extLen = 8; // The Fragment header length is fixed to 8 bytes. - break; - - case IPV6_NEXT_HEADER_AUTHENTICATION: - // IPV6_NEXT_HEADER_ENCAPSULATION: - /* - TODO: Not support. For encryption issue. - */ - nextProto = 0xFF; - status = FALSE; - break; - - default: - nextProto = 0xFF; - status = FALSE; - break; - } - - *pProto = nextProto; - *pOffset += extLen; - //printk("%s(): nextProto = 0x%x!, offset=0x%x!\n", __FUNCTION__, nextProto, offset); - - return status; - -} - -#endif // __IPV6_HDR_H_ // diff --git a/drivers/staging/rt3090/link_list.h b/drivers/staging/rt3090/link_list.h deleted file mode 100644 index 205b610bfb905b34324e3f1879aa625c5fd20741..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/link_list.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - */ - -#ifndef __LINK_LIST_H__ -#define __LINK_LIST_H__ - -typedef struct _LIST_ENTRY -{ - struct _LIST_ENTRY *pNext; -} LIST_ENTRY, *PLIST_ENTRY; - -typedef struct _LIST_HEADR -{ - PLIST_ENTRY pHead; - PLIST_ENTRY pTail; - UCHAR size; -} LIST_HEADER, *PLIST_HEADER; - -static inline VOID initList( - IN PLIST_HEADER pList) -{ - pList->pHead = pList->pTail = NULL; - pList->size = 0; - return; -} - -static inline VOID insertTailList( - IN PLIST_HEADER pList, - IN PLIST_ENTRY pEntry) -{ - pEntry->pNext = NULL; - if (pList->pTail) - pList->pTail->pNext = pEntry; - else - pList->pHead = pEntry; - pList->pTail = pEntry; - pList->size++; - - return; -} - -static inline PLIST_ENTRY removeHeadList( - IN PLIST_HEADER pList) -{ - PLIST_ENTRY pNext; - PLIST_ENTRY pEntry; - - pEntry = pList->pHead; - if (pList->pHead != NULL) - { - pNext = pList->pHead->pNext; - pList->pHead = pNext; - if (pNext == NULL) - pList->pTail = NULL; - pList->size--; - } - return pEntry; -} - -static inline int getListSize( - IN PLIST_HEADER pList) -{ - return pList->size; -} - -static inline PLIST_ENTRY delEntryList( - IN PLIST_HEADER pList, - IN PLIST_ENTRY pEntry) -{ - PLIST_ENTRY pCurEntry; - PLIST_ENTRY pPrvEntry; - - if(pList->pHead == NULL) - return NULL; - - if(pEntry == pList->pHead) - { - pCurEntry = pList->pHead; - pList->pHead = pCurEntry->pNext; - - if(pList->pHead == NULL) - pList->pTail = NULL; - - pList->size--; - return pCurEntry; - } - - pPrvEntry = pList->pHead; - pCurEntry = pPrvEntry->pNext; - while(pCurEntry != NULL) - { - if (pEntry == pCurEntry) - { - pPrvEntry->pNext = pCurEntry->pNext; - - if(pEntry == pList->pTail) - pList->pTail = pPrvEntry; - - pList->size--; - break; - } - pPrvEntry = pCurEntry; - pCurEntry = pPrvEntry->pNext; - } - - return pCurEntry; -} - -#endif // ___LINK_LIST_H__ // diff --git a/drivers/staging/rt3090/mlme.h b/drivers/staging/rt3090/mlme.h deleted file mode 100644 index 233674397a73b22493d7a87b901866d999fac11d..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/mlme.h +++ /dev/null @@ -1,1360 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - mlme.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - John Chang 2003-08-28 Created - John Chang 2004-09-06 modified for RT2600 -*/ -#ifndef __MLME_H__ -#define __MLME_H__ - -#include "rtmp_dot11.h" - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - - -// maximum supported capability information - -// ESS, IBSS, Privacy, Short Preamble, Spectrum mgmt, Short Slot -#define SUPPORTED_CAPABILITY_INFO 0x0533 - -#define END_OF_ARGS -1 -#define LFSR_MASK 0x80000057 -#define MLME_TASK_EXEC_INTV 100/*200*/ // -#define LEAD_TIME 5 -#define MLME_TASK_EXEC_MULTIPLE 10 /*5*/ // MLME_TASK_EXEC_MULTIPLE * MLME_TASK_EXEC_INTV = 1 sec -#define REORDER_EXEC_INTV 100 // 0.1 sec -//#define TBTT_PRELOAD_TIME 384 // usec. LomgPreamble + 24-byte at 1Mbps - -// The definition of Radar detection duration region -#define CE 0 -#define FCC 1 -#define JAP 2 -#define JAP_W53 3 -#define JAP_W56 4 -#define MAX_RD_REGION 5 - -#define BEACON_LOST_TIME 4 * OS_HZ // 2048 msec = 2 sec - -#define DLS_TIMEOUT 1200 // unit: msec -#define AUTH_TIMEOUT 300 // unit: msec -#define ASSOC_TIMEOUT 300 // unit: msec -#define JOIN_TIMEOUT 2000 // unit: msec -#define SHORT_CHANNEL_TIME 90 // unit: msec -#define MIN_CHANNEL_TIME 110 // unit: msec, for dual band scan -#define MAX_CHANNEL_TIME 140 // unit: msec, for single band scan -#define FAST_ACTIVE_SCAN_TIME 30 // Active scan waiting for probe response time -#define CW_MIN_IN_BITS 4 // actual CwMin = 2^CW_MIN_IN_BITS - 1 -#define LINK_DOWN_TIMEOUT 20000 // unit: msec -#define AUTO_WAKEUP_TIMEOUT 70 //unit: msec - - -#ifdef CONFIG_STA_SUPPORT -#define CW_MAX_IN_BITS 10 // actual CwMax = 2^CW_MAX_IN_BITS - 1 -#endif // CONFIG_STA_SUPPORT // - -#ifdef CONFIG_APSTA_MIXED_SUPPORT -extern UINT32 CW_MAX_IN_BITS; -#endif // CONFIG_APSTA_MIXED_SUPPORT // - -// Note: RSSI_TO_DBM_OFFSET has been changed to variable for new RF (2004-0720). -// SHould not refer to this constant anymore -//#define RSSI_TO_DBM_OFFSET 120 // for RT2530 RSSI-115 = dBm -#define RSSI_FOR_MID_TX_POWER -55 // -55 db is considered mid-distance -#define RSSI_FOR_LOW_TX_POWER -45 // -45 db is considered very short distance and - // eligible to use a lower TX power -#define RSSI_FOR_LOWEST_TX_POWER -30 -//#define MID_TX_POWER_DELTA 0 // 0 db from full TX power upon mid-distance to AP -#define LOW_TX_POWER_DELTA 6 // -3 db from full TX power upon very short distance. 1 grade is 0.5 db -#define LOWEST_TX_POWER_DELTA 16 // -8 db from full TX power upon shortest distance. 1 grade is 0.5 db - -#define RSSI_TRIGGERED_UPON_BELOW_THRESHOLD 0 -#define RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD 1 -#define RSSI_THRESHOLD_FOR_ROAMING 25 -#define RSSI_DELTA 5 - -// Channel Quality Indication -#define CQI_IS_GOOD(cqi) ((cqi) >= 50) -//#define CQI_IS_FAIR(cqi) (((cqi) >= 20) && ((cqi) < 50)) -#define CQI_IS_POOR(cqi) (cqi < 50) //(((cqi) >= 5) && ((cqi) < 20)) -#define CQI_IS_BAD(cqi) (cqi < 5) -#define CQI_IS_DEAD(cqi) (cqi == 0) - -// weighting factor to calculate Channel quality, total should be 100% -#define RSSI_WEIGHTING 50 -#define TX_WEIGHTING 30 -#define RX_WEIGHTING 20 - -//#define PEER_KEY_NOT_USED 0 -//#define PEER_KEY_64_BIT 64 -//#define PEER_KEY_128_BIT 128 - -//#define PEER_KEY_64BIT_LEN 8 -//#define PEER_KEY_128BIT_LEN 16 - -#define BSS_NOT_FOUND 0xFFFFFFFF - - -#ifdef CONFIG_STA_SUPPORT -#define MAX_LEN_OF_MLME_QUEUE 40 //10 -#endif // CONFIG_STA_SUPPORT // - -#define SCAN_PASSIVE 18 // scan with no probe request, only wait beacon and probe response -#define SCAN_ACTIVE 19 // scan with probe request, and wait beacon and probe response -#define SCAN_CISCO_PASSIVE 20 // Single channel passive scan -#define SCAN_CISCO_ACTIVE 21 // Single channel active scan -#define SCAN_CISCO_NOISE 22 // Single channel passive scan for noise histogram collection -#define SCAN_CISCO_CHANNEL_LOAD 23 // Single channel passive scan for channel load collection -#define FAST_SCAN_ACTIVE 24 // scan with probe request, and wait beacon and probe response - -#ifdef DOT11N_DRAFT3 -#define SCAN_2040_BSS_COEXIST 26 -#endif // DOT11N_DRAFT3 // - -//#define BSS_TABLE_EMPTY(x) ((x).BssNr == 0) -#define MAC_ADDR_IS_GROUP(Addr) (((Addr[0]) & 0x01)) -#define MAC_ADDR_HASH(Addr) (Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5]) -#define MAC_ADDR_HASH_INDEX(Addr) (MAC_ADDR_HASH(Addr) % HASH_TABLE_SIZE) -#define TID_MAC_HASH(Addr,TID) (TID^Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5]) -#define TID_MAC_HASH_INDEX(Addr,TID) (TID_MAC_HASH(Addr,TID) % HASH_TABLE_SIZE) - -// LED Control -// assoiation ON. one LED ON. another blinking when TX, OFF when idle -// no association, both LED off -#define ASIC_LED_ACT_ON(pAd) RTMP_IO_WRITE32(pAd, MAC_CSR14, 0x00031e46) -#define ASIC_LED_ACT_OFF(pAd) RTMP_IO_WRITE32(pAd, MAC_CSR14, 0x00001e46) - -// bit definition of the 2-byte pBEACON->Capability field -#define CAP_IS_ESS_ON(x) (((x) & 0x0001) != 0) -#define CAP_IS_IBSS_ON(x) (((x) & 0x0002) != 0) -#define CAP_IS_CF_POLLABLE_ON(x) (((x) & 0x0004) != 0) -#define CAP_IS_CF_POLL_REQ_ON(x) (((x) & 0x0008) != 0) -#define CAP_IS_PRIVACY_ON(x) (((x) & 0x0010) != 0) -#define CAP_IS_SHORT_PREAMBLE_ON(x) (((x) & 0x0020) != 0) -#define CAP_IS_PBCC_ON(x) (((x) & 0x0040) != 0) -#define CAP_IS_AGILITY_ON(x) (((x) & 0x0080) != 0) -#define CAP_IS_SPECTRUM_MGMT(x) (((x) & 0x0100) != 0) // 802.11e d9 -#define CAP_IS_QOS(x) (((x) & 0x0200) != 0) // 802.11e d9 -#define CAP_IS_SHORT_SLOT(x) (((x) & 0x0400) != 0) -#define CAP_IS_APSD(x) (((x) & 0x0800) != 0) // 802.11e d9 -#define CAP_IS_IMMED_BA(x) (((x) & 0x1000) != 0) // 802.11e d9 -#define CAP_IS_DSSS_OFDM(x) (((x) & 0x2000) != 0) -#define CAP_IS_DELAY_BA(x) (((x) & 0x4000) != 0) // 802.11e d9 - -#define CAP_GENERATE(ess,ibss,priv,s_pre,s_slot,spectrum) (((ess) ? 0x0001 : 0x0000) | ((ibss) ? 0x0002 : 0x0000) | ((priv) ? 0x0010 : 0x0000) | ((s_pre) ? 0x0020 : 0x0000) | ((s_slot) ? 0x0400 : 0x0000) | ((spectrum) ? 0x0100 : 0x0000)) - -//#define STA_QOS_CAPABILITY 0 // 1-byte. see 802.11e d9.0 for bit definition - -#define ERP_IS_NON_ERP_PRESENT(x) (((x) & 0x01) != 0) // 802.11g -#define ERP_IS_USE_PROTECTION(x) (((x) & 0x02) != 0) // 802.11g -#define ERP_IS_USE_BARKER_PREAMBLE(x) (((x) & 0x04) != 0) // 802.11g - -#define DRS_TX_QUALITY_WORST_BOUND 8// 3 // just test by gary -#define DRS_PENALTY 8 - -#define BA_NOTUSE 2 -//BA Policy subfiled value in ADDBA frame -#define IMMED_BA 1 -#define DELAY_BA 0 - -// BA Initiator subfield in DELBA frame -#define ORIGINATOR 1 -#define RECIPIENT 0 - -// ADDBA Status Code -#define ADDBA_RESULTCODE_SUCCESS 0 -#define ADDBA_RESULTCODE_REFUSED 37 -#define ADDBA_RESULTCODE_INVALID_PARAMETERS 38 - -// DELBA Reason Code -#define DELBA_REASONCODE_QSTA_LEAVING 36 -#define DELBA_REASONCODE_END_BA 37 -#define DELBA_REASONCODE_UNKNOWN_BA 38 -#define DELBA_REASONCODE_TIMEOUT 39 - -// reset all OneSecTx counters -#define RESET_ONE_SEC_TX_CNT(__pEntry) \ -if (((__pEntry)) != NULL) \ -{ \ - (__pEntry)->OneSecTxRetryOkCount = 0; \ - (__pEntry)->OneSecTxFailCount = 0; \ - (__pEntry)->OneSecTxNoRetryOkCount = 0; \ -} - -// -// 802.11 frame formats -// -// HT Capability INFO field in HT Cap IE . -typedef struct PACKED { -#ifdef RT_BIG_ENDIAN - USHORT LSIGTxopProSup:1; - USHORT Forty_Mhz_Intolerant:1; - USHORT PSMP:1; - USHORT CCKmodein40:1; - USHORT AMsduSize:1; - USHORT DelayedBA:1; //rt2860c not support - USHORT RxSTBC:2; - USHORT TxSTBC:1; - USHORT ShortGIfor40:1; //for40MHz - USHORT ShortGIfor20:1; - USHORT GF:1; //green field - USHORT MimoPs:2;//momi power safe - USHORT ChannelWidth:1; - USHORT AdvCoding:1; -#else - USHORT AdvCoding:1; - USHORT ChannelWidth:1; - USHORT MimoPs:2;//momi power safe - USHORT GF:1; //green field - USHORT ShortGIfor20:1; - USHORT ShortGIfor40:1; //for40MHz - USHORT TxSTBC:1; - USHORT RxSTBC:2; - USHORT DelayedBA:1; //rt2860c not support - USHORT AMsduSize:1; // only support as zero - USHORT CCKmodein40:1; - USHORT PSMP:1; - USHORT Forty_Mhz_Intolerant:1; - USHORT LSIGTxopProSup:1; -#endif /* !RT_BIG_ENDIAN */ -} HT_CAP_INFO, *PHT_CAP_INFO; - -// HT Capability INFO field in HT Cap IE . -typedef struct PACKED { -#ifdef RT_BIG_ENDIAN - UCHAR rsv:3;//momi power safe - UCHAR MpduDensity:3; - UCHAR MaxRAmpduFactor:2; -#else - UCHAR MaxRAmpduFactor:2; - UCHAR MpduDensity:3; - UCHAR rsv:3;//momi power safe -#endif /* !RT_BIG_ENDIAN */ -} HT_CAP_PARM, *PHT_CAP_PARM; - -// HT Capability INFO field in HT Cap IE . -typedef struct PACKED { - UCHAR MCSSet[10]; - UCHAR SupRate[2]; // unit : 1Mbps -#ifdef RT_BIG_ENDIAN - UCHAR rsv:3; - UCHAR MpduDensity:1; - UCHAR TxStream:2; - UCHAR TxRxNotEqual:1; - UCHAR TxMCSSetDefined:1; -#else - UCHAR TxMCSSetDefined:1; - UCHAR TxRxNotEqual:1; - UCHAR TxStream:2; - UCHAR MpduDensity:1; - UCHAR rsv:3; -#endif // RT_BIG_ENDIAN // - UCHAR rsv3[3]; -} HT_MCS_SET, *PHT_MCS_SET; - -// HT Capability INFO field in HT Cap IE . -typedef struct PACKED { -#ifdef RT_BIG_ENDIAN - USHORT rsv2:4; - USHORT RDGSupport:1; //reverse Direction Grant support - USHORT PlusHTC:1; //+HTC control field support - USHORT MCSFeedback:2; //0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv. - USHORT rsv:5;//momi power safe - USHORT TranTime:2; - USHORT Pco:1; -#else - USHORT Pco:1; - USHORT TranTime:2; - USHORT rsv:5;//momi power safe - USHORT MCSFeedback:2; //0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv. - USHORT PlusHTC:1; //+HTC control field support - USHORT RDGSupport:1; //reverse Direction Grant support - USHORT rsv2:4; -#endif /* RT_BIG_ENDIAN */ -} EXT_HT_CAP_INFO, *PEXT_HT_CAP_INFO; - -// HT Beamforming field in HT Cap IE . -typedef struct PACKED _HT_BF_CAP{ -#ifdef RT_BIG_ENDIAN - ULONG rsv:3; - ULONG ChanEstimation:2; - ULONG CSIRowBFSup:2; - ULONG ComSteerBFAntSup:2; - ULONG NoComSteerBFAntSup:2; - ULONG CSIBFAntSup:2; - ULONG MinGrouping:2; - ULONG ExpComBF:2; - ULONG ExpNoComBF:2; - ULONG ExpCSIFbk:2; - ULONG ExpComSteerCapable:1; - ULONG ExpNoComSteerCapable:1; - ULONG ExpCSICapable:1; - ULONG Calibration:2; - ULONG ImpTxBFCapable:1; - ULONG TxNDPCapable:1; - ULONG RxNDPCapable:1; - ULONG TxSoundCapable:1; - ULONG RxSoundCapable:1; - ULONG TxBFRecCapable:1; -#else - ULONG TxBFRecCapable:1; - ULONG RxSoundCapable:1; - ULONG TxSoundCapable:1; - ULONG RxNDPCapable:1; - ULONG TxNDPCapable:1; - ULONG ImpTxBFCapable:1; - ULONG Calibration:2; - ULONG ExpCSICapable:1; - ULONG ExpNoComSteerCapable:1; - ULONG ExpComSteerCapable:1; - ULONG ExpCSIFbk:2; - ULONG ExpNoComBF:2; - ULONG ExpComBF:2; - ULONG MinGrouping:2; - ULONG CSIBFAntSup:2; - ULONG NoComSteerBFAntSup:2; - ULONG ComSteerBFAntSup:2; - ULONG CSIRowBFSup:2; - ULONG ChanEstimation:2; - ULONG rsv:3; -#endif // RT_BIG_ENDIAN // -} HT_BF_CAP, *PHT_BF_CAP; - -// HT antenna selection field in HT Cap IE . -typedef struct PACKED _HT_AS_CAP{ -#ifdef RT_BIG_ENDIAN - UCHAR rsv:1; - UCHAR TxSoundPPDU:1; - UCHAR RxASel:1; - UCHAR AntIndFbk:1; - UCHAR ExpCSIFbk:1; - UCHAR AntIndFbkTxASEL:1; - UCHAR ExpCSIFbkTxASEL:1; - UCHAR AntSelect:1; -#else - UCHAR AntSelect:1; - UCHAR ExpCSIFbkTxASEL:1; - UCHAR AntIndFbkTxASEL:1; - UCHAR ExpCSIFbk:1; - UCHAR AntIndFbk:1; - UCHAR RxASel:1; - UCHAR TxSoundPPDU:1; - UCHAR rsv:1; -#endif // RT_BIG_ENDIAN // -} HT_AS_CAP, *PHT_AS_CAP; - -// Draft 1.0 set IE length 26, but is extensible.. -#define SIZE_HT_CAP_IE 26 -// The structure for HT Capability IE. -typedef struct PACKED _HT_CAPABILITY_IE{ - HT_CAP_INFO HtCapInfo; - HT_CAP_PARM HtCapParm; -// HT_MCS_SET HtMCSSet; - UCHAR MCSSet[16]; - EXT_HT_CAP_INFO ExtHtCapInfo; - HT_BF_CAP TxBFCap; // beamforming cap. rt2860c not support beamforming. - HT_AS_CAP ASCap; //antenna selection. -} HT_CAPABILITY_IE, *PHT_CAPABILITY_IE; - - -// 802.11n draft3 related structure definitions. -// 7.3.2.60 -#define dot11OBSSScanPassiveDwell 20 // in TU. min amount of time that the STA continously scans each channel when performing an active OBSS scan. -#define dot11OBSSScanActiveDwell 10 // in TU.min amount of time that the STA continously scans each channel when performing an passive OBSS scan. -#define dot11BSSWidthTriggerScanInterval 300 // in sec. max interval between scan operations to be performed to detect BSS channel width trigger events. -#define dot11OBSSScanPassiveTotalPerChannel 200 // in TU. min total amount of time that the STA scans each channel when performing a passive OBSS scan. -#define dot11OBSSScanActiveTotalPerChannel 20 //in TU. min total amount of time that the STA scans each channel when performing a active OBSS scan -#define dot11BSSWidthChannelTransactionDelayFactor 5 // min ratio between the delay time in performing a switch from 20MHz BSS to 20/40 BSS operation and the maximum - // interval between overlapping BSS scan operations. -#define dot11BSSScanActivityThreshold 25 // in %%, max total time that a STA may be active on the medium during a period of - // (dot11BSSWidthChannelTransactionDelayFactor * dot11BSSWidthTriggerScanInterval) seconds without - // being obligated to perform OBSS Scan operations. default is 25(== 0.25%) - -typedef struct PACKED _OVERLAP_BSS_SCAN_IE{ - USHORT ScanPassiveDwell; - USHORT ScanActiveDwell; - USHORT TriggerScanInt; // Trigger scan interval - USHORT PassiveTalPerChannel; // passive total per channel - USHORT ActiveTalPerChannel; // active total per channel - USHORT DelayFactor; // BSS width channel transition delay factor - USHORT ScanActThre; // Scan Activity threshold -}OVERLAP_BSS_SCAN_IE, *POVERLAP_BSS_SCAN_IE; - - -// 7.3.2.56. 20/40 Coexistence element used in Element ID = 72 = IE_2040_BSS_COEXIST -typedef union PACKED _BSS_2040_COEXIST_IE{ - struct PACKED { - #ifdef RT_BIG_ENDIAN - UCHAR rsv:5; - UCHAR BSS20WidthReq:1; - UCHAR Intolerant40:1; - UCHAR InfoReq:1; - #else - UCHAR InfoReq:1; - UCHAR Intolerant40:1; // Inter-BSS. set 1 when prohibits a receiving BSS from operating as a 20/40 Mhz BSS. - UCHAR BSS20WidthReq:1; // Intra-BSS set 1 when prohibits a receiving AP from operating its BSS as a 20/40MHz BSS. - UCHAR rsv:5; -#endif // RT_BIG_ENDIAN // - } field; - UCHAR word; -} BSS_2040_COEXIST_IE, *PBSS_2040_COEXIST_IE; - - -typedef struct _TRIGGER_EVENTA{ - BOOLEAN bValid; - UCHAR BSSID[6]; - UCHAR RegClass; // Regulatory Class - USHORT Channel; - ULONG CDCounter; // Maintain a seperate count down counter for each Event A. -} TRIGGER_EVENTA, *PTRIGGER_EVENTA; - -// 20/40 trigger event table -// If one Event A delete or created, or if Event B is detected or not detected, STA should send 2040BSSCoexistence to AP. -#define MAX_TRIGGER_EVENT 64 -typedef struct _TRIGGER_EVENT_TAB{ - UCHAR EventANo; - TRIGGER_EVENTA EventA[MAX_TRIGGER_EVENT]; - ULONG EventBCountDown; // Count down counter for Event B. -} TRIGGER_EVENT_TAB, *PTRIGGER_EVENT_TAB; - -// 7.3.27 20/40 Bss Coexistence Mgmt capability used in extended capabilities information IE( ID = 127 = IE_EXT_CAPABILITY). -// This is the first octet and was defined in 802.11n D3.03 and 802.11yD9.0 -typedef struct PACKED _EXT_CAP_INFO_ELEMENT{ -#ifdef RT_BIG_ENDIAN - UCHAR rsv2:5; - UCHAR ExtendChannelSwitch:1; - UCHAR rsv:1; - UCHAR BssCoexistMgmtSupport:1; -#else - UCHAR BssCoexistMgmtSupport:1; - UCHAR rsv:1; - UCHAR ExtendChannelSwitch:1; - UCHAR rsv2:5; -#endif // RT_BIG_ENDIAN // -}EXT_CAP_INFO_ELEMENT, *PEXT_CAP_INFO_ELEMENT; - - -// 802.11n 7.3.2.61 -typedef struct PACKED _BSS_2040_COEXIST_ELEMENT{ - UCHAR ElementID; // ID = IE_2040_BSS_COEXIST = 72 - UCHAR Len; - BSS_2040_COEXIST_IE BssCoexistIe; -}BSS_2040_COEXIST_ELEMENT, *PBSS_2040_COEXIST_ELEMENT; - - -//802.11n 7.3.2.59 -typedef struct PACKED _BSS_2040_INTOLERANT_CH_REPORT{ - UCHAR ElementID; // ID = IE_2040_BSS_INTOLERANT_REPORT = 73 - UCHAR Len; - UCHAR RegulatoryClass; - UCHAR ChList[0]; -}BSS_2040_INTOLERANT_CH_REPORT, *PBSS_2040_INTOLERANT_CH_REPORT; - - -// The structure for channel switch annoucement IE. This is in 802.11n D3.03 -typedef struct PACKED _CHA_SWITCH_ANNOUNCE_IE{ - UCHAR SwitchMode; //channel switch mode - UCHAR NewChannel; // - UCHAR SwitchCount; // -} CHA_SWITCH_ANNOUNCE_IE, *PCHA_SWITCH_ANNOUNCE_IE; - - -// The structure for channel switch annoucement IE. This is in 802.11n D3.03 -typedef struct PACKED _SEC_CHA_OFFSET_IE{ - UCHAR SecondaryChannelOffset; // 1: Secondary above, 3: Secondary below, 0: no Secondary -} SEC_CHA_OFFSET_IE, *PSEC_CHA_OFFSET_IE; - - -// This structure is extracted from struct RT_HT_CAPABILITY -typedef struct { - BOOLEAN bHtEnable; // If we should use ht rate. - BOOLEAN bPreNHt; // If we should use ht rate. - //Substract from HT Capability IE - UCHAR MCSSet[16]; -} RT_HT_PHY_INFO, *PRT_HT_PHY_INFO; - -//This structure substracts ralink supports from all 802.11n-related features. -//Features not listed here but contained in 802.11n spec are not supported in rt2860. -typedef struct { -#ifdef RT_BIG_ENDIAN - USHORT rsv:5; - USHORT AmsduSize:1; // Max receiving A-MSDU size - USHORT AmsduEnable:1; // Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n - USHORT RxSTBC:2; // 2 bits - USHORT TxSTBC:1; - USHORT ShortGIfor40:1; //for40MHz - USHORT ShortGIfor20:1; - USHORT GF:1; //green field - USHORT MimoPs:2;//mimo power safe MMPS_ - USHORT ChannelWidth:1; -#else - USHORT ChannelWidth:1; - USHORT MimoPs:2;//mimo power safe MMPS_ - USHORT GF:1; //green field - USHORT ShortGIfor20:1; - USHORT ShortGIfor40:1; //for40MHz - USHORT TxSTBC:1; - USHORT RxSTBC:2; // 2 bits - USHORT AmsduEnable:1; // Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n - USHORT AmsduSize:1; // Max receiving A-MSDU size - USHORT rsv:5; -#endif - - //Substract from Addiont HT INFO IE -#ifdef RT_BIG_ENDIAN - UCHAR RecomWidth:1; - UCHAR ExtChanOffset:2; // Please not the difference with following UCHAR NewExtChannelOffset; from 802.11n - UCHAR MpduDensity:3; - UCHAR MaxRAmpduFactor:2; -#else - UCHAR MaxRAmpduFactor:2; - UCHAR MpduDensity:3; - UCHAR ExtChanOffset:2; // Please not the difference with following UCHAR NewExtChannelOffset; from 802.11n - UCHAR RecomWidth:1; -#endif - -#ifdef RT_BIG_ENDIAN - USHORT rsv2:11; - USHORT OBSS_NonHTExist:1; - USHORT rsv3:1; - USHORT NonGfPresent:1; - USHORT OperaionMode:2; -#else - USHORT OperaionMode:2; - USHORT NonGfPresent:1; - USHORT rsv3:1; - USHORT OBSS_NonHTExist:1; - USHORT rsv2:11; -#endif - - // New Extension Channel Offset IE - UCHAR NewExtChannelOffset; - // Extension Capability IE = 127 - UCHAR BSSCoexist2040; -} RT_HT_CAPABILITY, *PRT_HT_CAPABILITY; - -// field in Addtional HT Information IE . -typedef struct PACKED { -#ifdef RT_BIG_ENDIAN - UCHAR SerInterGranu:3; - UCHAR S_PSMPSup:1; - UCHAR RifsMode:1; - UCHAR RecomWidth:1; - UCHAR ExtChanOffset:2; -#else - UCHAR ExtChanOffset:2; - UCHAR RecomWidth:1; - UCHAR RifsMode:1; - UCHAR S_PSMPSup:1; //Indicate support for scheduled PSMP - UCHAR SerInterGranu:3; //service interval granularity -#endif -} ADD_HTINFO, *PADD_HTINFO; - -typedef struct PACKED{ -#ifdef RT_BIG_ENDIAN - USHORT rsv2:11; - USHORT OBSS_NonHTExist:1; - USHORT rsv:1; - USHORT NonGfPresent:1; - USHORT OperaionMode:2; -#else - USHORT OperaionMode:2; - USHORT NonGfPresent:1; - USHORT rsv:1; - USHORT OBSS_NonHTExist:1; - USHORT rsv2:11; -#endif -} ADD_HTINFO2, *PADD_HTINFO2; - - -// TODO: Need sync with spec about the definition of StbcMcs. In Draft 3.03, it's reserved. -typedef struct PACKED{ -#ifdef RT_BIG_ENDIAN - USHORT rsv:4; - USHORT PcoPhase:1; - USHORT PcoActive:1; - USHORT LsigTxopProt:1; - USHORT STBCBeacon:1; - USHORT DualCTSProtect:1; - USHORT DualBeacon:1; - USHORT StbcMcs:6; -#else - USHORT StbcMcs:6; - USHORT DualBeacon:1; - USHORT DualCTSProtect:1; - USHORT STBCBeacon:1; - USHORT LsigTxopProt:1; // L-SIG TXOP protection full support - USHORT PcoActive:1; - USHORT PcoPhase:1; - USHORT rsv:4; -#endif // RT_BIG_ENDIAN // -} ADD_HTINFO3, *PADD_HTINFO3; - -#define SIZE_ADD_HT_INFO_IE 22 -typedef struct PACKED{ - UCHAR ControlChan; - ADD_HTINFO AddHtInfo; - ADD_HTINFO2 AddHtInfo2; - ADD_HTINFO3 AddHtInfo3; - UCHAR MCSSet[16]; // Basic MCS set -} ADD_HT_INFO_IE, *PADD_HT_INFO_IE; - -typedef struct PACKED{ - UCHAR NewExtChanOffset; -} NEW_EXT_CHAN_IE, *PNEW_EXT_CHAN_IE; - -typedef struct PACKED _FRAME_802_11 { - HEADER_802_11 Hdr; - UCHAR Octet[1]; -} FRAME_802_11, *PFRAME_802_11; - -// QoSNull embedding of management action. When HT Control MA field set to 1. -typedef struct PACKED _MA_BODY { - UCHAR Category; - UCHAR Action; - UCHAR Octet[1]; -} MA_BODY, *PMA_BODY; - -typedef struct PACKED _HEADER_802_3 { - UCHAR DAAddr1[MAC_ADDR_LEN]; - UCHAR SAAddr2[MAC_ADDR_LEN]; - UCHAR Octet[2]; -} HEADER_802_3, *PHEADER_802_3; -////Block ACK related format -// 2-byte BA Parameter field in DELBA frames to terminate an already set up bA -typedef struct PACKED{ -#ifdef RT_BIG_ENDIAN - USHORT TID:4; // value of TC os TS - USHORT Initiator:1; // 1: originator 0:recipient - USHORT Rsv:11; // always set to 0 -#else - USHORT Rsv:11; // always set to 0 - USHORT Initiator:1; // 1: originator 0:recipient - USHORT TID:4; // value of TC os TS -#endif /* !RT_BIG_ENDIAN */ -} DELBA_PARM, *PDELBA_PARM; - -// 2-byte BA Parameter Set field in ADDBA frames to signal parm for setting up a BA -typedef struct PACKED { -#ifdef RT_BIG_ENDIAN - USHORT BufSize:10; // number of buffe of size 2304 octetsr - USHORT TID:4; // value of TC os TS - USHORT BAPolicy:1; // 1: immediately BA 0:delayed BA - USHORT AMSDUSupported:1; // 0: not permitted 1: permitted -#else - USHORT AMSDUSupported:1; // 0: not permitted 1: permitted - USHORT BAPolicy:1; // 1: immediately BA 0:delayed BA - USHORT TID:4; // value of TC os TS - USHORT BufSize:10; // number of buffe of size 2304 octetsr -#endif /* !RT_BIG_ENDIAN */ -} BA_PARM, *PBA_PARM; - -// 2-byte BA Starting Seq CONTROL field -typedef union PACKED { - struct PACKED { -#ifdef RT_BIG_ENDIAN - USHORT StartSeq:12; // sequence number of the 1st MSDU for which this BAR is sent - USHORT FragNum:4; // always set to 0 -#else - USHORT FragNum:4; // always set to 0 - USHORT StartSeq:12; // sequence number of the 1st MSDU for which this BAR is sent -#endif /* RT_BIG_ENDIAN */ - } field; - USHORT word; -} BASEQ_CONTROL, *PBASEQ_CONTROL; - -//BAControl and BARControl are the same -// 2-byte BA CONTROL field in BA frame -typedef struct PACKED { -#ifdef RT_BIG_ENDIAN - USHORT TID:4; - USHORT Rsv:9; - USHORT Compressed:1; - USHORT MTID:1; //EWC V1.24 - USHORT ACKPolicy:1; // only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK 1:No ACK -#else - USHORT ACKPolicy:1; // only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK 1:No ACK - USHORT MTID:1; //EWC V1.24 - USHORT Compressed:1; - USHORT Rsv:9; - USHORT TID:4; -#endif /* !RT_BIG_ENDIAN */ -} BA_CONTROL, *PBA_CONTROL; - -// 2-byte BAR CONTROL field in BAR frame -typedef struct PACKED { -#ifdef RT_BIG_ENDIAN - USHORT TID:4; - USHORT Rsv1:9; - USHORT Compressed:1; - USHORT MTID:1; //if this bit1, use FRAME_MTBA_REQ, if 0, use FRAME_BA_REQ - USHORT ACKPolicy:1; -#else - USHORT ACKPolicy:1; // 0:normal ack, 1:no ack. - USHORT MTID:1; //if this bit1, use FRAME_MTBA_REQ, if 0, use FRAME_BA_REQ - USHORT Compressed:1; - USHORT Rsv1:9; - USHORT TID:4; -#endif /* !RT_BIG_ENDIAN */ -} BAR_CONTROL, *PBAR_CONTROL; - -// BARControl in MTBAR frame -typedef struct PACKED { -#ifdef RT_BIG_ENDIAN - USHORT NumTID:4; - USHORT Rsv1:9; - USHORT Compressed:1; - USHORT MTID:1; - USHORT ACKPolicy:1; -#else - USHORT ACKPolicy:1; - USHORT MTID:1; - USHORT Compressed:1; - USHORT Rsv1:9; - USHORT NumTID:4; -#endif /* !RT_BIG_ENDIAN */ -} MTBAR_CONTROL, *PMTBAR_CONTROL; - -typedef struct PACKED { -#ifdef RT_BIG_ENDIAN - USHORT TID:4; - USHORT Rsv1:12; -#else - USHORT Rsv1:12; - USHORT TID:4; -#endif /* !RT_BIG_ENDIAN */ -} PER_TID_INFO, *PPER_TID_INFO; - -typedef struct { - PER_TID_INFO PerTID; - BASEQ_CONTROL BAStartingSeq; -} EACH_TID, *PEACH_TID; - - -// BAREQ AND MTBAREQ have the same subtype BAR, 802.11n BAR use compressed bitmap. -typedef struct PACKED _FRAME_BA_REQ { - FRAME_CONTROL FC; - USHORT Duration; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; - BAR_CONTROL BARControl; - BASEQ_CONTROL BAStartingSeq; -} FRAME_BA_REQ, *PFRAME_BA_REQ; - -typedef struct PACKED _FRAME_MTBA_REQ { - FRAME_CONTROL FC; - USHORT Duration; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; - MTBAR_CONTROL MTBARControl; - PER_TID_INFO PerTIDInfo; - BASEQ_CONTROL BAStartingSeq; -} FRAME_MTBA_REQ, *PFRAME_MTBA_REQ; - -// Compressed format is mandantory in HT STA -typedef struct PACKED _FRAME_MTBA { - FRAME_CONTROL FC; - USHORT Duration; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; - BA_CONTROL BAControl; - BASEQ_CONTROL BAStartingSeq; - UCHAR BitMap[8]; -} FRAME_MTBA, *PFRAME_MTBA; - -typedef struct PACKED _FRAME_PSMP_ACTION { - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; - UCHAR Psmp; // 7.3.1.25 -} FRAME_PSMP_ACTION, *PFRAME_PSMP_ACTION; - -typedef struct PACKED _FRAME_ACTION_HDR { - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; -} FRAME_ACTION_HDR, *PFRAME_ACTION_HDR; - -//Action Frame -//Action Frame Category:Spectrum, Action:Channel Switch. 7.3.2.20 -typedef struct PACKED _CHAN_SWITCH_ANNOUNCE { - UCHAR ElementID; // ID = IE_CHANNEL_SWITCH_ANNOUNCEMENT = 37 - UCHAR Len; - CHA_SWITCH_ANNOUNCE_IE CSAnnounceIe; -} CHAN_SWITCH_ANNOUNCE, *PCHAN_SWITCH_ANNOUNCE; - - -//802.11n : 7.3.2.20a -typedef struct PACKED _SECOND_CHAN_OFFSET { - UCHAR ElementID; // ID = IE_SECONDARY_CH_OFFSET = 62 - UCHAR Len; - SEC_CHA_OFFSET_IE SecChOffsetIe; -} SECOND_CHAN_OFFSET, *PSECOND_CHAN_OFFSET; - - -typedef struct PACKED _FRAME_SPETRUM_CS { - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; - CHAN_SWITCH_ANNOUNCE CSAnnounce; - SECOND_CHAN_OFFSET SecondChannel; -} FRAME_SPETRUM_CS, *PFRAME_SPETRUM_CS; - - -typedef struct PACKED _FRAME_ADDBA_REQ { - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; - UCHAR Token; // 1 - BA_PARM BaParm; // 2 - 10 - USHORT TimeOutValue; // 0 - 0 - BASEQ_CONTROL BaStartSeq; // 0-0 -} FRAME_ADDBA_REQ, *PFRAME_ADDBA_REQ; - -typedef struct PACKED _FRAME_ADDBA_RSP { - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; - UCHAR Token; - USHORT StatusCode; - BA_PARM BaParm; //0 - 2 - USHORT TimeOutValue; -} FRAME_ADDBA_RSP, *PFRAME_ADDBA_RSP; - -typedef struct PACKED _FRAME_DELBA_REQ { - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; - DELBA_PARM DelbaParm; - USHORT ReasonCode; -} FRAME_DELBA_REQ, *PFRAME_DELBA_REQ; - - -//7.2.1.7 -typedef struct PACKED _FRAME_BAR { - FRAME_CONTROL FC; - USHORT Duration; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; - BAR_CONTROL BarControl; - BASEQ_CONTROL StartingSeq; -} FRAME_BAR, *PFRAME_BAR; - -//7.2.1.7 -typedef struct PACKED _FRAME_BA { - FRAME_CONTROL FC; - USHORT Duration; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; - BAR_CONTROL BarControl; - BASEQ_CONTROL StartingSeq; - UCHAR bitmask[8]; -} FRAME_BA, *PFRAME_BA; - - -// Radio Measuement Request Frame Format -typedef struct PACKED _FRAME_RM_REQ_ACTION { - HEADER_802_11 Hdr; - UCHAR Category; - UCHAR Action; - UCHAR Token; - USHORT Repetition; - UCHAR data[0]; -} FRAME_RM_REQ_ACTION, *PFRAME_RM_REQ_ACTION; - -typedef struct PACKED { - UCHAR ID; - UCHAR Length; - UCHAR ChannelSwitchMode; - UCHAR NewRegClass; - UCHAR NewChannelNum; - UCHAR ChannelSwitchCount; -} HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE, *PHT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE; - - -// -// _Limit must be the 2**n - 1 -// _SEQ1 , _SEQ2 must be within 0 ~ _Limit -// -#define SEQ_STEPONE(_SEQ1, _SEQ2, _Limit) ((_SEQ1 == ((_SEQ2+1) & _Limit))) -#define SEQ_SMALLER(_SEQ1, _SEQ2, _Limit) (((_SEQ1-_SEQ2) & ((_Limit+1)>>1))) -#define SEQ_LARGER(_SEQ1, _SEQ2, _Limit) ((_SEQ1 != _SEQ2) && !(((_SEQ1-_SEQ2) & ((_Limit+1)>>1)))) -#define SEQ_WITHIN_WIN(_SEQ1, _SEQ2, _WIN, _Limit) (SEQ_LARGER(_SEQ1, _SEQ2, _Limit) && \ - SEQ_SMALLER(_SEQ1, ((_SEQ2+_WIN+1)&_Limit), _Limit)) - -// -// Contention-free parameter (without ID and Length) -// -typedef struct PACKED { - BOOLEAN bValid; // 1: variable contains valid value - UCHAR CfpCount; - UCHAR CfpPeriod; - USHORT CfpMaxDuration; - USHORT CfpDurRemaining; -} CF_PARM, *PCF_PARM; - -typedef struct _CIPHER_SUITE { - NDIS_802_11_ENCRYPTION_STATUS PairCipher; // Unicast cipher 1, this one has more secured cipher suite - NDIS_802_11_ENCRYPTION_STATUS PairCipherAux; // Unicast cipher 2 if AP announce two unicast cipher suite - NDIS_802_11_ENCRYPTION_STATUS GroupCipher; // Group cipher - USHORT RsnCapability; // RSN capability from beacon - BOOLEAN bMixMode; // Indicate Pair & Group cipher might be different -} CIPHER_SUITE, *PCIPHER_SUITE; - -// EDCA configuration from AP's BEACON/ProbeRsp -typedef struct { - BOOLEAN bValid; // 1: variable contains valid value - BOOLEAN bAdd; // 1: variable contains valid value - BOOLEAN bQAck; - BOOLEAN bQueueRequest; - BOOLEAN bTxopRequest; - BOOLEAN bAPSDCapable; -// BOOLEAN bMoreDataAck; - UCHAR EdcaUpdateCount; - UCHAR Aifsn[4]; // 0:AC_BK, 1:AC_BE, 2:AC_VI, 3:AC_VO - UCHAR Cwmin[4]; - UCHAR Cwmax[4]; - USHORT Txop[4]; // in unit of 32-us - BOOLEAN bACM[4]; // 1: Admission Control of AC_BK is mandattory -} EDCA_PARM, *PEDCA_PARM; - -// QBSS LOAD information from QAP's BEACON/ProbeRsp -typedef struct { - BOOLEAN bValid; // 1: variable contains valid value - USHORT StaNum; - UCHAR ChannelUtilization; - USHORT RemainingAdmissionControl; // in unit of 32-us -} QBSS_LOAD_PARM, *PQBSS_LOAD_PARM; - -// QBSS Info field in QSTA's assoc req -typedef struct PACKED { -#ifdef RT_BIG_ENDIAN - UCHAR Rsv2:1; - UCHAR MaxSPLength:2; - UCHAR Rsv1:1; - UCHAR UAPSD_AC_BE:1; - UCHAR UAPSD_AC_BK:1; - UCHAR UAPSD_AC_VI:1; - UCHAR UAPSD_AC_VO:1; -#else - UCHAR UAPSD_AC_VO:1; - UCHAR UAPSD_AC_VI:1; - UCHAR UAPSD_AC_BK:1; - UCHAR UAPSD_AC_BE:1; - UCHAR Rsv1:1; - UCHAR MaxSPLength:2; - UCHAR Rsv2:1; -#endif /* !RT_BIG_ENDIAN */ -} QBSS_STA_INFO_PARM, *PQBSS_STA_INFO_PARM; - -// QBSS Info field in QAP's Beacon/ProbeRsp -typedef struct PACKED { -#ifdef RT_BIG_ENDIAN - UCHAR UAPSD:1; - UCHAR Rsv:3; - UCHAR ParamSetCount:4; -#else - UCHAR ParamSetCount:4; - UCHAR Rsv:3; - UCHAR UAPSD:1; -#endif /* !RT_BIG_ENDIAN */ -} QBSS_AP_INFO_PARM, *PQBSS_AP_INFO_PARM; - -// QOS Capability reported in QAP's BEACON/ProbeRsp -// QOS Capability sent out in QSTA's AssociateReq/ReAssociateReq -typedef struct { - BOOLEAN bValid; // 1: variable contains valid value - BOOLEAN bQAck; - BOOLEAN bQueueRequest; - BOOLEAN bTxopRequest; -// BOOLEAN bMoreDataAck; - UCHAR EdcaUpdateCount; -} QOS_CAPABILITY_PARM, *PQOS_CAPABILITY_PARM; - -#ifdef CONFIG_STA_SUPPORT -typedef struct { - UCHAR IELen; - UCHAR IE[MAX_CUSTOM_LEN]; -} WPA_IE_; -#endif // CONFIG_STA_SUPPORT // - - -typedef struct { - UCHAR Bssid[MAC_ADDR_LEN]; - UCHAR Channel; - UCHAR CentralChannel; //Store the wide-band central channel for 40MHz. .used in 40MHz AP. Or this is the same as Channel. - UCHAR BssType; - USHORT AtimWin; - USHORT BeaconPeriod; - - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen; - UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR ExtRateLen; - HT_CAPABILITY_IE HtCapability; - UCHAR HtCapabilityLen; - ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE - UCHAR AddHtInfoLen; - UCHAR NewExtChanOffset; - CHAR Rssi; - UCHAR Privacy; // Indicate security function ON/OFF. Don't mess up with auth mode. - UCHAR Hidden; - - USHORT DtimPeriod; - USHORT CapabilityInfo; - - USHORT CfpCount; - USHORT CfpPeriod; - USHORT CfpMaxDuration; - USHORT CfpDurRemaining; - UCHAR SsidLen; - CHAR Ssid[MAX_LEN_OF_SSID]; - - ULONG LastBeaconRxTime; // OS's timestamp - - BOOLEAN bSES; - - // New for WPA2 - CIPHER_SUITE WPA; // AP announced WPA cipher suite - CIPHER_SUITE WPA2; // AP announced WPA2 cipher suite - - // New for microsoft WPA support - NDIS_802_11_FIXED_IEs FixIEs; - NDIS_802_11_AUTHENTICATION_MODE AuthModeAux; // Addition mode for WPA2 / WPA capable AP - NDIS_802_11_AUTHENTICATION_MODE AuthMode; - NDIS_802_11_WEP_STATUS WepStatus; // Unicast Encryption Algorithm extract from VAR_IE - USHORT VarIELen; // Length of next VIE include EID & Length - UCHAR VarIEs[MAX_VIE_LEN]; - - // CCX Ckip information - UCHAR CkipFlag; - - // CCX 2 TSF - UCHAR PTSF[4]; // Parent TSF - UCHAR TTSF[8]; // Target TSF - - // 802.11e d9, and WMM - EDCA_PARM EdcaParm; - QOS_CAPABILITY_PARM QosCapability; - QBSS_LOAD_PARM QbssLoad; -#ifdef CONFIG_STA_SUPPORT - WPA_IE_ WpaIE; - WPA_IE_ RsnIE; -#ifdef EXT_BUILD_CHANNEL_LIST - UCHAR CountryString[3]; - BOOLEAN bHasCountryIE; -#endif // EXT_BUILD_CHANNEL_LIST // -#endif // CONFIG_STA_SUPPORT // - -} BSS_ENTRY, *PBSS_ENTRY; - -typedef struct { - UCHAR BssNr; - UCHAR BssOverlapNr; - BSS_ENTRY BssEntry[MAX_LEN_OF_BSS_TABLE]; -} BSS_TABLE, *PBSS_TABLE; - - -typedef struct _MLME_QUEUE_ELEM { - ULONG Machine; - ULONG MsgType; - ULONG MsgLen; - UCHAR Msg[MGMT_DMA_BUFFER_SIZE]; - LARGE_INTEGER TimeStamp; - UCHAR Rssi0; - UCHAR Rssi1; - UCHAR Rssi2; - UCHAR Signal; - UCHAR Channel; - UCHAR Wcid; - BOOLEAN Occupied; -#ifdef MLME_EX - USHORT Idx; -#endif // MLME_EX // -} MLME_QUEUE_ELEM, *PMLME_QUEUE_ELEM; - -typedef struct _MLME_QUEUE { - ULONG Num; - ULONG Head; - ULONG Tail; - NDIS_SPIN_LOCK Lock; - MLME_QUEUE_ELEM Entry[MAX_LEN_OF_MLME_QUEUE]; -} MLME_QUEUE, *PMLME_QUEUE; - -typedef VOID (*STATE_MACHINE_FUNC)(VOID *Adaptor, MLME_QUEUE_ELEM *Elem); - -typedef struct _STATE_MACHINE { - ULONG Base; - ULONG NrState; - ULONG NrMsg; - ULONG CurrState; - STATE_MACHINE_FUNC *TransFunc; -} STATE_MACHINE, *PSTATE_MACHINE; - - -// MLME AUX data structure that hold temporarliy settings during a connection attempt. -// Once this attemp succeeds, all settings will be copy to pAd->StaActive. -// A connection attempt (user set OID, roaming, CCX fast roaming,..) consists of -// several steps (JOIN, AUTH, ASSOC or REASSOC) and may fail at any step. We purposely -// separate this under-trial settings away from pAd->StaActive so that once -// this new attempt failed, driver can auto-recover back to the active settings. -typedef struct _MLME_AUX { - UCHAR BssType; - UCHAR Ssid[MAX_LEN_OF_SSID]; - UCHAR SsidLen; - UCHAR Bssid[MAC_ADDR_LEN]; - UCHAR AutoReconnectSsid[MAX_LEN_OF_SSID]; - UCHAR AutoReconnectSsidLen; - USHORT Alg; - UCHAR ScanType; - UCHAR Channel; - UCHAR CentralChannel; - USHORT Aid; - USHORT CapabilityInfo; - USHORT BeaconPeriod; - USHORT CfpMaxDuration; - USHORT CfpPeriod; - USHORT AtimWin; - - // Copy supported rate from desired AP's beacon. We are trying to match - // AP's supported and extended rate settings. - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen; - UCHAR ExtRateLen; - HT_CAPABILITY_IE HtCapability; - UCHAR HtCapabilityLen; - ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE - UCHAR NewExtChannelOffset; - //RT_HT_CAPABILITY SupportedHtPhy; - - // new for QOS - QOS_CAPABILITY_PARM APQosCapability; // QOS capability of the current associated AP - EDCA_PARM APEdcaParm; // EDCA parameters of the current associated AP - QBSS_LOAD_PARM APQbssLoad; // QBSS load of the current associated AP - - // new to keep Ralink specific feature - ULONG APRalinkIe; - - BSS_TABLE SsidBssTab; // AP list for the same SSID - BSS_TABLE RoamTab; // AP list eligible for roaming - ULONG BssIdx; - ULONG RoamIdx; - - BOOLEAN CurrReqIsFromNdis; - - RALINK_TIMER_STRUCT BeaconTimer, ScanTimer; - RALINK_TIMER_STRUCT AuthTimer; - RALINK_TIMER_STRUCT AssocTimer, ReassocTimer, DisassocTimer; - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // -} MLME_AUX, *PMLME_AUX; - -typedef struct _MLME_ADDBA_REQ_STRUCT{ - UCHAR Wcid; // - UCHAR pAddr[MAC_ADDR_LEN]; - UCHAR BaBufSize; - USHORT TimeOutValue; - UCHAR TID; - UCHAR Token; - USHORT BaStartSeq; -} MLME_ADDBA_REQ_STRUCT, *PMLME_ADDBA_REQ_STRUCT; - - -typedef struct _MLME_DELBA_REQ_STRUCT{ - UCHAR Wcid; // - UCHAR Addr[MAC_ADDR_LEN]; - UCHAR TID; - UCHAR Initiator; -} MLME_DELBA_REQ_STRUCT, *PMLME_DELBA_REQ_STRUCT; - -// assoc struct is equal to reassoc -typedef struct _MLME_ASSOC_REQ_STRUCT{ - UCHAR Addr[MAC_ADDR_LEN]; - USHORT CapabilityInfo; - USHORT ListenIntv; - ULONG Timeout; -} MLME_ASSOC_REQ_STRUCT, *PMLME_ASSOC_REQ_STRUCT, MLME_REASSOC_REQ_STRUCT, *PMLME_REASSOC_REQ_STRUCT; - -typedef struct _MLME_DISASSOC_REQ_STRUCT{ - UCHAR Addr[MAC_ADDR_LEN]; - USHORT Reason; -} MLME_DISASSOC_REQ_STRUCT, *PMLME_DISASSOC_REQ_STRUCT; - -typedef struct _MLME_AUTH_REQ_STRUCT { - UCHAR Addr[MAC_ADDR_LEN]; - USHORT Alg; - ULONG Timeout; -} MLME_AUTH_REQ_STRUCT, *PMLME_AUTH_REQ_STRUCT; - -typedef struct _MLME_DEAUTH_REQ_STRUCT { - UCHAR Addr[MAC_ADDR_LEN]; - USHORT Reason; -} MLME_DEAUTH_REQ_STRUCT, *PMLME_DEAUTH_REQ_STRUCT; - -typedef struct { - ULONG BssIdx; -} MLME_JOIN_REQ_STRUCT; - -typedef struct _MLME_SCAN_REQ_STRUCT { - UCHAR Bssid[MAC_ADDR_LEN]; - UCHAR BssType; - UCHAR ScanType; - UCHAR SsidLen; - CHAR Ssid[MAX_LEN_OF_SSID]; -} MLME_SCAN_REQ_STRUCT, *PMLME_SCAN_REQ_STRUCT; - -typedef struct _MLME_START_REQ_STRUCT { - CHAR Ssid[MAX_LEN_OF_SSID]; - UCHAR SsidLen; -} MLME_START_REQ_STRUCT, *PMLME_START_REQ_STRUCT; - -#ifdef CONFIG_STA_SUPPORT -#ifdef QOS_DLS_SUPPORT -// structure for DLS -typedef struct _RT_802_11_DLS { - USHORT TimeOut; // Use to time out while slience, unit: second , set by UI - USHORT CountDownTimer; // Use to time out while slience,unit: second , used by driver only - NDIS_802_11_MAC_ADDRESS MacAddr; // set by UI - UCHAR Status; // 0: none , 1: wait STAkey, 2: finish DLS setup , set by driver only - BOOLEAN Valid; // 1: valid , 0: invalid , set by UI, use to setup or tear down DLS link - RALINK_TIMER_STRUCT Timer; // Use to time out while handshake - USHORT Sequence; - USHORT MacTabMatchWCID; // ASIC - BOOLEAN bHTCap; - PVOID pAd; -} RT_802_11_DLS, *PRT_802_11_DLS; - -typedef struct _MLME_DLS_REQ_STRUCT { - PRT_802_11_DLS pDLS; - USHORT Reason; -} MLME_DLS_REQ_STRUCT, *PMLME_DLS_REQ_STRUCT; -#endif // QOS_DLS_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - -typedef struct PACKED { - UCHAR Eid; - UCHAR Len; - UCHAR Octet[1]; -} EID_STRUCT,*PEID_STRUCT, BEACON_EID_STRUCT, *PBEACON_EID_STRUCT; - -typedef struct PACKED _RTMP_TX_RATE_SWITCH -{ - UCHAR ItemNo; -#ifdef RT_BIG_ENDIAN - UCHAR Rsv2:2; - UCHAR Mode:2; - UCHAR Rsv1:1; - UCHAR BW:1; - UCHAR ShortGI:1; - UCHAR STBC:1; -#else - UCHAR STBC:1; - UCHAR ShortGI:1; - UCHAR BW:1; - UCHAR Rsv1:1; - UCHAR Mode:2; - UCHAR Rsv2:2; -#endif - UCHAR CurrMCS; - UCHAR TrainUp; - UCHAR TrainDown; -} RRTMP_TX_RATE_SWITCH, *PRTMP_TX_RATE_SWITCH; - -// ========================== AP mlme.h =============================== -#define TBTT_PRELOAD_TIME 384 // usec. LomgPreamble + 24-byte at 1Mbps -#define DEFAULT_DTIM_PERIOD 1 - -// weighting factor to calculate Channel quality, total should be 100% -//#define RSSI_WEIGHTING 0 -//#define TX_WEIGHTING 40 -//#define RX_WEIGHTING 60 - -#define MAC_TABLE_AGEOUT_TIME 300 // unit: sec -#define MAC_TABLE_ASSOC_TIMEOUT 5 // unit: sec -#define MAC_TABLE_FULL(Tab) ((Tab).size == MAX_LEN_OF_MAC_TABLE) - -// AP shall drop the sta if contine Tx fail count reach it. -#define MAC_ENTRY_LIFE_CHECK_CNT 20 // packet cnt. - -// Value domain of pMacEntry->Sst -typedef enum _Sst { - SST_NOT_AUTH, // 0: equivalent to IEEE 802.11/1999 state 1 - SST_AUTH, // 1: equivalent to IEEE 802.11/1999 state 2 - SST_ASSOC // 2: equivalent to IEEE 802.11/1999 state 3 -} SST; - -// value domain of pMacEntry->AuthState -typedef enum _AuthState { - AS_NOT_AUTH, - AS_AUTH_OPEN, // STA has been authenticated using OPEN SYSTEM - AS_AUTH_KEY, // STA has been authenticated using SHARED KEY - AS_AUTHENTICATING // STA is waiting for AUTH seq#3 using SHARED KEY -} AUTH_STATE; - -//for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 -typedef enum _ApWpaState { - AS_NOTUSE, // 0 - AS_DISCONNECT, // 1 - AS_DISCONNECTED, // 2 - AS_INITIALIZE, // 3 - AS_AUTHENTICATION, // 4 - AS_AUTHENTICATION2, // 5 - AS_INITPMK, // 6 - AS_INITPSK, // 7 - AS_PTKSTART, // 8 - AS_PTKINIT_NEGOTIATING, // 9 - AS_PTKINITDONE, // 10 - AS_UPDATEKEYS, // 11 - AS_INTEGRITY_FAILURE, // 12 - AS_KEYUPDATE, // 13 -} AP_WPA_STATE; - -// for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 -typedef enum _GTKState { - REKEY_NEGOTIATING, - REKEY_ESTABLISHED, - KEYERROR, -} GTK_STATE; - -// for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 -typedef enum _WpaGTKState { - SETKEYS, - SETKEYS_DONE, -} WPA_GTK_STATE; -// ====================== end of AP mlme.h ============================ - - -#endif // MLME_H__ diff --git a/drivers/staging/rt3090/mlme_ex.h b/drivers/staging/rt3090/mlme_ex.h deleted file mode 100644 index b3e94dc8837568caca64f4556315bf6b3ae91069..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/mlme_ex.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - mlme_ex.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Fonchi 2007-06-25 Extend original mlme APIs to support multi-entries -*/ -#ifndef __MLME_EX_H__ -#define __MLME_EX_H__ - -#include "mlme_ex_def.h" - - -VOID StateMachineInitEx( - IN STATE_MACHINE_EX *S, - IN STATE_MACHINE_FUNC_EX Trans[], - IN ULONG StNr, - IN ULONG MsgNr, - IN STATE_MACHINE_FUNC_EX DefFunc, - IN ULONG InitState, - IN ULONG Base); - -VOID StateMachineSetActionEx( - IN STATE_MACHINE_EX *S, - IN ULONG St, - IN ULONG Msg, - IN STATE_MACHINE_FUNC_EX Func); - -BOOLEAN isValidApCliIf( - SHORT Idx); - -VOID StateMachinePerformActionEx( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE_EX *S, - IN MLME_QUEUE_ELEM *Elem, - USHORT Idx, - PULONG pCurrState); - -BOOLEAN MlmeEnqueueEx( - IN PRTMP_ADAPTER pAd, - IN ULONG Machine, - IN ULONG MsgType, - IN ULONG MsgLen, - IN VOID *Msg, - IN USHORT Idx); - -VOID DropEx( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem, - PULONG pCurrState, - USHORT Idx); - -#endif /* __MLME_EX_H__ */ diff --git a/drivers/staging/rt3090/mlme_ex_def.h b/drivers/staging/rt3090/mlme_ex_def.h deleted file mode 100644 index ccd60b41614a07785d83da7e554378f71d00050b..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/mlme_ex_def.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - mlme_ex_def.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Fonchi 2007-06-25 Extend original mlme APIs to support multi-entries -*/ -#ifndef __MLME_EX_DEF_H__ -#define __MLME_EX_DEF_H__ - - -typedef VOID (*STATE_MACHINE_FUNC_EX)(VOID *Adaptor, MLME_QUEUE_ELEM *Elem, PULONG pCurrState, USHORT Idx); - -typedef struct _STA_STATE_MACHINE_EX -{ - ULONG Base; - ULONG NrState; - ULONG NrMsg; - ULONG CurrState; - STATE_MACHINE_FUNC_EX *TransFunc; -} STATE_MACHINE_EX, *PSTA_STATE_MACHINE_EX; - -#endif // __MLME_EX_DEF_H__ // diff --git a/drivers/staging/rt3090/oid.h b/drivers/staging/rt3090/oid.h deleted file mode 100644 index 29a43401095e8d465df122e355ca8be56858d97a..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/oid.h +++ /dev/null @@ -1,1144 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - oid.h - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Name Date Modification logs -*/ -#ifndef _OID_H_ -#define _OID_H_ - -//#include - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif -// -// IEEE 802.11 Structures and definitions -// -#define MAX_TX_POWER_LEVEL 100 /* mW */ -#define MAX_RSSI_TRIGGER -10 /* dBm */ -#define MIN_RSSI_TRIGGER -200 /* dBm */ -#define MAX_FRAG_THRESHOLD 2346 /* byte count */ -#define MIN_FRAG_THRESHOLD 256 /* byte count */ -#define MAX_RTS_THRESHOLD 2347 /* byte count */ - -// new types for Media Specific Indications -// Extension channel offset -#define EXTCHA_NONE 0 -#define EXTCHA_ABOVE 0x1 -#define EXTCHA_BELOW 0x3 - -// BW -#define BAND_WIDTH_20 0 -#define BAND_WIDTH_40 1 -#define BAND_WIDTH_BOTH 2 -#define BAND_WIDTH_10 3 // 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. -// SHORTGI -#define GAP_INTERVAL_400 1 // only support in HT mode -#define GAP_INTERVAL_800 0 -#define GAP_INTERVAL_BOTH 2 - -#define NdisMediaStateConnected 1 -#define NdisMediaStateDisconnected 0 - -#define NDIS_802_11_LENGTH_SSID 32 -#define NDIS_802_11_LENGTH_RATES 8 -#define NDIS_802_11_LENGTH_RATES_EX 16 -#define MAC_ADDR_LENGTH 6 -//#define MAX_NUM_OF_CHS 49 // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL terminationc -#define MAX_NUM_OF_CHS 54 // 14 channels @2.4G + 12@UNII(lower/middle) + 16@HiperLAN2 + 11@UNII(upper) + 0 @Japan + 1 as NULL termination -#define MAX_NUMBER_OF_EVENT 10 // entry # in EVENT table -#define MAX_NUMBER_OF_MAC 32 // if MAX_MBSSID_NUM is 8, this value can't be larger than 211 -#define MAX_NUMBER_OF_ACL 64 -#define MAX_LENGTH_OF_SUPPORT_RATES 12 // 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 -#define MAX_NUMBER_OF_DLS_ENTRY 4 - - -#define RT_QUERY_SIGNAL_CONTEXT 0x0402 -#define RT_SET_IAPP_PID 0x0404 -#define RT_SET_APD_PID 0x0405 -#define RT_SET_DEL_MAC_ENTRY 0x0406 -#define RT_QUERY_EVENT_TABLE 0x0407 -// -// IEEE 802.11 OIDs -// -#define OID_GET_SET_TOGGLE 0x8000 -#define OID_GET_SET_FROM_UI 0x4000 - -#define OID_802_11_NETWORK_TYPES_SUPPORTED 0x0103 -#define OID_802_11_NETWORK_TYPE_IN_USE 0x0104 -#define OID_802_11_RSSI_TRIGGER 0x0107 -#define RT_OID_802_11_RSSI 0x0108 //rt2860 only , kathy -#define RT_OID_802_11_RSSI_1 0x0109 //rt2860 only , kathy -#define RT_OID_802_11_RSSI_2 0x010A //rt2860 only , kathy -#define OID_802_11_NUMBER_OF_ANTENNAS 0x010B -#define OID_802_11_RX_ANTENNA_SELECTED 0x010C -#define OID_802_11_TX_ANTENNA_SELECTED 0x010D -#define OID_802_11_SUPPORTED_RATES 0x010E -#define OID_802_11_ADD_WEP 0x0112 -#define OID_802_11_REMOVE_WEP 0x0113 -#define OID_802_11_DISASSOCIATE 0x0114 -#define OID_802_11_PRIVACY_FILTER 0x0118 -#define OID_802_11_ASSOCIATION_INFORMATION 0x011E -#define OID_802_11_TEST 0x011F - - -#define RT_OID_802_11_COUNTRY_REGION 0x0507 -#define OID_802_11_BSSID_LIST_SCAN 0x0508 -#define OID_802_11_SSID 0x0509 -#define OID_802_11_BSSID 0x050A -#define RT_OID_802_11_RADIO 0x050B -#define RT_OID_802_11_PHY_MODE 0x050C -#define RT_OID_802_11_STA_CONFIG 0x050D -#define OID_802_11_DESIRED_RATES 0x050E -#define RT_OID_802_11_PREAMBLE 0x050F -#define OID_802_11_WEP_STATUS 0x0510 -#define OID_802_11_AUTHENTICATION_MODE 0x0511 -#define OID_802_11_INFRASTRUCTURE_MODE 0x0512 -#define RT_OID_802_11_RESET_COUNTERS 0x0513 -#define OID_802_11_RTS_THRESHOLD 0x0514 -#define OID_802_11_FRAGMENTATION_THRESHOLD 0x0515 -#define OID_802_11_POWER_MODE 0x0516 -#define OID_802_11_TX_POWER_LEVEL 0x0517 -#define RT_OID_802_11_ADD_WPA 0x0518 -#define OID_802_11_REMOVE_KEY 0x0519 -#define OID_802_11_ADD_KEY 0x0520 -#define OID_802_11_CONFIGURATION 0x0521 -#define OID_802_11_TX_PACKET_BURST 0x0522 -#define RT_OID_802_11_QUERY_NOISE_LEVEL 0x0523 -#define RT_OID_802_11_EXTRA_INFO 0x0524 -#ifdef DBG -#define RT_OID_802_11_HARDWARE_REGISTER 0x0525 -#endif -#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS -#define OID_802_11_DEAUTHENTICATION 0x0526 -#define OID_802_11_DROP_UNENCRYPTED 0x0527 -#define OID_802_11_MIC_FAILURE_REPORT_FRAME 0x0528 -#define OID_802_11_EAP_METHOD 0x0529 - -// For 802.1x daemin using to require current driver configuration -#define OID_802_11_RADIUS_QUERY_SETTING 0x0540 - -#define RT_OID_DEVICE_NAME 0x0607 -#define RT_OID_VERSION_INFO 0x0608 -#define OID_802_11_BSSID_LIST 0x0609 -#define OID_802_3_CURRENT_ADDRESS 0x060A -#define OID_GEN_MEDIA_CONNECT_STATUS 0x060B -#define RT_OID_802_11_QUERY_LINK_STATUS 0x060C -#define OID_802_11_RSSI 0x060D -#define OID_802_11_STATISTICS 0x060E -#define OID_GEN_RCV_OK 0x060F -#define OID_GEN_RCV_NO_BUFFER 0x0610 -#define RT_OID_802_11_QUERY_EEPROM_VERSION 0x0611 -#define RT_OID_802_11_QUERY_FIRMWARE_VERSION 0x0612 -#define RT_OID_802_11_QUERY_LAST_RX_RATE 0x0613 -#define RT_OID_802_11_TX_POWER_LEVEL_1 0x0614 -#define RT_OID_802_11_QUERY_PIDVID 0x0615 -//for WPA_SUPPLICANT_SUPPORT -#define OID_SET_COUNTERMEASURES 0x0616 -#define OID_802_11_SET_IEEE8021X 0x0617 -#define OID_802_11_SET_IEEE8021X_REQUIRE_KEY 0x0618 -#define OID_802_11_PMKID 0x0620 -#define RT_OID_WPA_SUPPLICANT_SUPPORT 0x0621 -#define RT_OID_WE_VERSION_COMPILED 0x0622 -#define RT_OID_NEW_DRIVER 0x0623 - -#define RT_OID_802_11_SNR_0 0x0630 -#define RT_OID_802_11_SNR_1 0x0631 -#define RT_OID_802_11_QUERY_LAST_TX_RATE 0x0632 -#define RT_OID_802_11_QUERY_HT_PHYMODE 0x0633 -#define RT_OID_802_11_SET_HT_PHYMODE 0x0634 -#define OID_802_11_RELOAD_DEFAULTS 0x0635 -#define RT_OID_802_11_QUERY_APSD_SETTING 0x0636 -#define RT_OID_802_11_SET_APSD_SETTING 0x0637 -#define RT_OID_802_11_QUERY_APSD_PSM 0x0638 -#define RT_OID_802_11_SET_APSD_PSM 0x0639 -#define RT_OID_802_11_QUERY_DLS 0x063A -#define RT_OID_802_11_SET_DLS 0x063B -#define RT_OID_802_11_QUERY_DLS_PARAM 0x063C -#define RT_OID_802_11_SET_DLS_PARAM 0x063D -#define RT_OID_802_11_QUERY_WMM 0x063E -#define RT_OID_802_11_SET_WMM 0x063F -#define RT_OID_802_11_QUERY_IMME_BA_CAP 0x0640 -#define RT_OID_802_11_SET_IMME_BA_CAP 0x0641 -#define RT_OID_802_11_QUERY_BATABLE 0x0642 -#define RT_OID_802_11_ADD_IMME_BA 0x0643 -#define RT_OID_802_11_TEAR_IMME_BA 0x0644 -#define RT_OID_DRIVER_DEVICE_NAME 0x0645 -#define RT_OID_802_11_QUERY_DAT_HT_PHYMODE 0x0646 -#define RT_OID_QUERY_MULTIPLE_CARD_SUPPORT 0x0647 -#define OID_802_11_SET_PSPXLINK_MODE 0x0648 -/*+++ add by woody +++*/ -#define OID_802_11_SET_PASSPHRASE 0x0649 -// Ralink defined OIDs -// Dennis Lee move to platform specific - -#define RT_OID_802_11_BSSID (OID_GET_SET_TOGGLE | OID_802_11_BSSID) -#define RT_OID_802_11_SSID (OID_GET_SET_TOGGLE | OID_802_11_SSID) -#define RT_OID_802_11_INFRASTRUCTURE_MODE (OID_GET_SET_TOGGLE | OID_802_11_INFRASTRUCTURE_MODE) -#define RT_OID_802_11_ADD_WEP (OID_GET_SET_TOGGLE | OID_802_11_ADD_WEP) -#define RT_OID_802_11_ADD_KEY (OID_GET_SET_TOGGLE | OID_802_11_ADD_KEY) -#define RT_OID_802_11_REMOVE_WEP (OID_GET_SET_TOGGLE | OID_802_11_REMOVE_WEP) -#define RT_OID_802_11_REMOVE_KEY (OID_GET_SET_TOGGLE | OID_802_11_REMOVE_KEY) -#define RT_OID_802_11_DISASSOCIATE (OID_GET_SET_TOGGLE | OID_802_11_DISASSOCIATE) -#define RT_OID_802_11_AUTHENTICATION_MODE (OID_GET_SET_TOGGLE | OID_802_11_AUTHENTICATION_MODE) -#define RT_OID_802_11_PRIVACY_FILTER (OID_GET_SET_TOGGLE | OID_802_11_PRIVACY_FILTER) -#define RT_OID_802_11_BSSID_LIST_SCAN (OID_GET_SET_TOGGLE | OID_802_11_BSSID_LIST_SCAN) -#define RT_OID_802_11_WEP_STATUS (OID_GET_SET_TOGGLE | OID_802_11_WEP_STATUS) -#define RT_OID_802_11_RELOAD_DEFAULTS (OID_GET_SET_TOGGLE | OID_802_11_RELOAD_DEFAULTS) -#define RT_OID_802_11_NETWORK_TYPE_IN_USE (OID_GET_SET_TOGGLE | OID_802_11_NETWORK_TYPE_IN_USE) -#define RT_OID_802_11_TX_POWER_LEVEL (OID_GET_SET_TOGGLE | OID_802_11_TX_POWER_LEVEL) -#define RT_OID_802_11_RSSI_TRIGGER (OID_GET_SET_TOGGLE | OID_802_11_RSSI_TRIGGER) -#define RT_OID_802_11_FRAGMENTATION_THRESHOLD (OID_GET_SET_TOGGLE | OID_802_11_FRAGMENTATION_THRESHOLD) -#define RT_OID_802_11_RTS_THRESHOLD (OID_GET_SET_TOGGLE | OID_802_11_RTS_THRESHOLD) -#define RT_OID_802_11_RX_ANTENNA_SELECTED (OID_GET_SET_TOGGLE | OID_802_11_RX_ANTENNA_SELECTED) -#define RT_OID_802_11_TX_ANTENNA_SELECTED (OID_GET_SET_TOGGLE | OID_802_11_TX_ANTENNA_SELECTED) -#define RT_OID_802_11_SUPPORTED_RATES (OID_GET_SET_TOGGLE | OID_802_11_SUPPORTED_RATES) -#define RT_OID_802_11_DESIRED_RATES (OID_GET_SET_TOGGLE | OID_802_11_DESIRED_RATES) -#define RT_OID_802_11_CONFIGURATION (OID_GET_SET_TOGGLE | OID_802_11_CONFIGURATION) -#define RT_OID_802_11_POWER_MODE (OID_GET_SET_TOGGLE | OID_802_11_POWER_MODE) -#define RT_OID_802_11_SET_PSPXLINK_MODE (OID_GET_SET_TOGGLE | OID_802_11_SET_PSPXLINK_MODE) -#define RT_OID_802_11_EAP_METHOD (OID_GET_SET_TOGGLE | OID_802_11_EAP_METHOD) -#define RT_OID_802_11_SET_PASSPHRASE (OID_GET_SET_TOGGLE | OID_802_11_SET_PASSPHRASE) - - - -typedef enum _NDIS_802_11_STATUS_TYPE -{ - Ndis802_11StatusType_Authentication, - Ndis802_11StatusType_MediaStreamMode, - Ndis802_11StatusType_PMKID_CandidateList, - Ndis802_11StatusTypeMax // not a real type, defined as an upper bound -} NDIS_802_11_STATUS_TYPE, *PNDIS_802_11_STATUS_TYPE; - -typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; - -typedef struct _NDIS_802_11_STATUS_INDICATION -{ - NDIS_802_11_STATUS_TYPE StatusType; -} NDIS_802_11_STATUS_INDICATION, *PNDIS_802_11_STATUS_INDICATION; - -// mask for authentication/integrity fields -#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f - -#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 -#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 -#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 -#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E - -typedef struct _NDIS_802_11_AUTHENTICATION_REQUEST -{ - ULONG Length; // Length of structure - NDIS_802_11_MAC_ADDRESS Bssid; - ULONG Flags; -} NDIS_802_11_AUTHENTICATION_REQUEST, *PNDIS_802_11_AUTHENTICATION_REQUEST; - -//Added new types for PMKID Candidate lists. -typedef struct _PMKID_CANDIDATE { - NDIS_802_11_MAC_ADDRESS BSSID; - ULONG Flags; -} PMKID_CANDIDATE, *PPMKID_CANDIDATE; - -typedef struct _NDIS_802_11_PMKID_CANDIDATE_LIST -{ - ULONG Version; // Version of the structure - ULONG NumCandidates; // No. of pmkid candidates - PMKID_CANDIDATE CandidateList[1]; -} NDIS_802_11_PMKID_CANDIDATE_LIST, *PNDIS_802_11_PMKID_CANDIDATE_LIST; - -//Flags for PMKID Candidate list structure -#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 - -// Added new types for OFDM 5G and 2.4G -typedef enum _NDIS_802_11_NETWORK_TYPE -{ - Ndis802_11FH, - Ndis802_11DS, - Ndis802_11OFDM5, - Ndis802_11OFDM24, - Ndis802_11Automode, - Ndis802_11OFDM5_N, - Ndis802_11OFDM24_N, - Ndis802_11NetworkTypeMax // not a real type, defined as an upper bound -} NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE; - -typedef struct _NDIS_802_11_NETWORK_TYPE_LIST -{ - UINT NumberOfItems; // in list below, at least 1 - NDIS_802_11_NETWORK_TYPE NetworkType [1]; -} NDIS_802_11_NETWORK_TYPE_LIST, *PNDIS_802_11_NETWORK_TYPE_LIST; - -typedef enum _NDIS_802_11_POWER_MODE -{ - Ndis802_11PowerModeCAM, - Ndis802_11PowerModeMAX_PSP, - Ndis802_11PowerModeFast_PSP, - Ndis802_11PowerModeLegacy_PSP, - Ndis802_11PowerModeMax // not a real mode, defined as an upper bound -} NDIS_802_11_POWER_MODE, *PNDIS_802_11_POWER_MODE; - -typedef ULONG NDIS_802_11_TX_POWER_LEVEL; // in milliwatts - -// -// Received Signal Strength Indication -// -typedef LONG NDIS_802_11_RSSI; // in dBm - -typedef struct _NDIS_802_11_CONFIGURATION_FH -{ - ULONG Length; // Length of structure - ULONG HopPattern; // As defined by 802.11, MSB set - ULONG HopSet; // to one if non-802.11 - ULONG DwellTime; // units are Kusec -} NDIS_802_11_CONFIGURATION_FH, *PNDIS_802_11_CONFIGURATION_FH; - -typedef struct _NDIS_802_11_CONFIGURATION -{ - ULONG Length; // Length of structure - ULONG BeaconPeriod; // units are Kusec - ULONG ATIMWindow; // units are Kusec - ULONG DSConfig; // Frequency, units are kHz - NDIS_802_11_CONFIGURATION_FH FHConfig; -} NDIS_802_11_CONFIGURATION, *PNDIS_802_11_CONFIGURATION; - -typedef struct _NDIS_802_11_STATISTICS -{ - ULONG Length; // Length of structure - LARGE_INTEGER TransmittedFragmentCount; - LARGE_INTEGER MulticastTransmittedFrameCount; - LARGE_INTEGER FailedCount; - LARGE_INTEGER RetryCount; - LARGE_INTEGER MultipleRetryCount; - LARGE_INTEGER RTSSuccessCount; - LARGE_INTEGER RTSFailureCount; - LARGE_INTEGER ACKFailureCount; - LARGE_INTEGER FrameDuplicateCount; - LARGE_INTEGER ReceivedFragmentCount; - LARGE_INTEGER MulticastReceivedFrameCount; - LARGE_INTEGER FCSErrorCount; - LARGE_INTEGER TKIPLocalMICFailures; - LARGE_INTEGER TKIPRemoteMICErrors; - LARGE_INTEGER TKIPICVErrors; - LARGE_INTEGER TKIPCounterMeasuresInvoked; - LARGE_INTEGER TKIPReplays; - LARGE_INTEGER CCMPFormatErrors; - LARGE_INTEGER CCMPReplays; - LARGE_INTEGER CCMPDecryptErrors; - LARGE_INTEGER FourWayHandshakeFailures; -} NDIS_802_11_STATISTICS, *PNDIS_802_11_STATISTICS; - -typedef ULONG NDIS_802_11_KEY_INDEX; -typedef ULONGLONG NDIS_802_11_KEY_RSC; - -#define MAX_RADIUS_SRV_NUM 2 // 802.1x failover number - -typedef struct PACKED _RADIUS_SRV_INFO { - UINT32 radius_ip; - UINT32 radius_port; - UCHAR radius_key[64]; - UCHAR radius_key_len; -} RADIUS_SRV_INFO, *PRADIUS_SRV_INFO; - -typedef struct PACKED _RADIUS_KEY_INFO -{ - UCHAR radius_srv_num; - RADIUS_SRV_INFO radius_srv_info[MAX_RADIUS_SRV_NUM]; - UCHAR ieee8021xWEP; // dynamic WEP - UCHAR key_index; - UCHAR key_length; // length of key in bytes - UCHAR key_material[13]; -} RADIUS_KEY_INFO, *PRADIUS_KEY_INFO; - -// It's used by 802.1x daemon to require relative configuration -typedef struct PACKED _RADIUS_CONF -{ - UINT32 Length; // Length of this structure - UCHAR mbss_num; // indicate multiple BSS number - UINT32 own_ip_addr; - UINT32 retry_interval; - UINT32 session_timeout_interval; - UCHAR EAPifname[8][IFNAMSIZ]; - UCHAR EAPifname_len[8]; - UCHAR PreAuthifname[8][IFNAMSIZ]; - UCHAR PreAuthifname_len[8]; - RADIUS_KEY_INFO RadiusInfo[8]; -} RADIUS_CONF, *PRADIUS_CONF; - - - -#ifdef CONFIG_STA_SUPPORT -// Key mapping keys require a BSSID -typedef struct _NDIS_802_11_KEY -{ - UINT Length; // Length of this structure - UINT KeyIndex; - UINT KeyLength; // length of key in bytes - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_KEY_RSC KeyRSC; - UCHAR KeyMaterial[1]; // variable length depending on above field -} NDIS_802_11_KEY, *PNDIS_802_11_KEY; - -typedef struct _NDIS_802_11_PASSPHRASE -{ - UINT KeyLength; // length of key in bytes - NDIS_802_11_MAC_ADDRESS BSSID; - UCHAR KeyMaterial[1]; // variable length depending on above field -} NDIS_802_11_PASSPHRASE, *PNDIS_802_11_PASSPHRASE; -#endif // CONFIG_STA_SUPPORT // - -typedef struct _NDIS_802_11_REMOVE_KEY -{ - UINT Length; // Length of this structure - UINT KeyIndex; - NDIS_802_11_MAC_ADDRESS BSSID; -} NDIS_802_11_REMOVE_KEY, *PNDIS_802_11_REMOVE_KEY; - -typedef struct _NDIS_802_11_WEP -{ - UINT Length; // Length of this structure - UINT KeyIndex; // 0 is the per-client key, 1-N are the - // global keys - UINT KeyLength; // length of key in bytes - UCHAR KeyMaterial[1];// variable length depending on above field -} NDIS_802_11_WEP, *PNDIS_802_11_WEP; - - -typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE -{ - Ndis802_11IBSS, - Ndis802_11Infrastructure, - Ndis802_11AutoUnknown, - Ndis802_11Monitor, - Ndis802_11InfrastructureMax // Not a real value, defined as upper bound -} NDIS_802_11_NETWORK_INFRASTRUCTURE, *PNDIS_802_11_NETWORK_INFRASTRUCTURE; - -// Add new authentication modes -typedef enum _NDIS_802_11_AUTHENTICATION_MODE -{ - Ndis802_11AuthModeOpen, - Ndis802_11AuthModeShared, - Ndis802_11AuthModeAutoSwitch, - Ndis802_11AuthModeWPA, - Ndis802_11AuthModeWPAPSK, - Ndis802_11AuthModeWPANone, - Ndis802_11AuthModeWPA2, - Ndis802_11AuthModeWPA2PSK, - Ndis802_11AuthModeWPA1WPA2, - Ndis802_11AuthModeWPA1PSKWPA2PSK, - Ndis802_11AuthModeMax // Not a real mode, defined as upper bound -} NDIS_802_11_AUTHENTICATION_MODE, *PNDIS_802_11_AUTHENTICATION_MODE; - -typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; // Set of 8 data rates -typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; // Set of 16 data rates - -typedef struct PACKED _NDIS_802_11_SSID -{ - UINT SsidLength; // length of SSID field below, in bytes; - // this can be zero. - UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; // SSID information field -} NDIS_802_11_SSID, *PNDIS_802_11_SSID; - - -typedef struct PACKED _NDIS_WLAN_BSSID -{ - ULONG Length; // Length of this structure - NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID - UCHAR Reserved[2]; - NDIS_802_11_SSID Ssid; // SSID - ULONG Privacy; // WEP encryption requirement - NDIS_802_11_RSSI Rssi; // receive signal strength in dBm - NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; - NDIS_802_11_CONFIGURATION Configuration; - NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; - NDIS_802_11_RATES SupportedRates; -} NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID; - -typedef struct PACKED _NDIS_802_11_BSSID_LIST -{ - UINT NumberOfItems; // in list below, at least 1 - NDIS_WLAN_BSSID Bssid[1]; -} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST; - -// Added Capabilities, IELength and IEs for each BSSID -typedef struct PACKED _NDIS_WLAN_BSSID_EX -{ - ULONG Length; // Length of this structure - NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID - UCHAR Reserved[2]; - NDIS_802_11_SSID Ssid; // SSID - UINT Privacy; // WEP encryption requirement - NDIS_802_11_RSSI Rssi; // receive signal - // strength in dBm - NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; - NDIS_802_11_CONFIGURATION Configuration; - NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; - NDIS_802_11_RATES_EX SupportedRates; - ULONG IELength; - UCHAR IEs[1]; -} NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX; - -typedef struct PACKED _NDIS_802_11_BSSID_LIST_EX -{ - UINT NumberOfItems; // in list below, at least 1 - NDIS_WLAN_BSSID_EX Bssid[1]; -} NDIS_802_11_BSSID_LIST_EX, *PNDIS_802_11_BSSID_LIST_EX; - -typedef struct PACKED _NDIS_802_11_FIXED_IEs -{ - UCHAR Timestamp[8]; - USHORT BeaconInterval; - USHORT Capabilities; -} NDIS_802_11_FIXED_IEs, *PNDIS_802_11_FIXED_IEs; - -typedef struct _NDIS_802_11_VARIABLE_IEs -{ - UCHAR ElementID; - UCHAR Length; // Number of bytes in data field - UCHAR data[1]; -} NDIS_802_11_VARIABLE_IEs, *PNDIS_802_11_VARIABLE_IEs; - -typedef ULONG NDIS_802_11_FRAGMENTATION_THRESHOLD; - -typedef ULONG NDIS_802_11_RTS_THRESHOLD; - -typedef ULONG NDIS_802_11_ANTENNA; - -typedef enum _NDIS_802_11_PRIVACY_FILTER -{ - Ndis802_11PrivFilterAcceptAll, - Ndis802_11PrivFilter8021xWEP -} NDIS_802_11_PRIVACY_FILTER, *PNDIS_802_11_PRIVACY_FILTER; - -// Added new encryption types -// Also aliased typedef to new name -typedef enum _NDIS_802_11_WEP_STATUS -{ - Ndis802_11WEPEnabled, - Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, - Ndis802_11WEPDisabled, - Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, - Ndis802_11WEPKeyAbsent, - Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, - Ndis802_11WEPNotSupported, - Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, - Ndis802_11Encryption2Enabled, - Ndis802_11Encryption2KeyAbsent, - Ndis802_11Encryption3Enabled, - Ndis802_11Encryption3KeyAbsent, - Ndis802_11Encryption4Enabled, // TKIP or AES mix - Ndis802_11Encryption4KeyAbsent, - Ndis802_11GroupWEP40Enabled, - Ndis802_11GroupWEP104Enabled, -} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS, - NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS; - -typedef enum _NDIS_802_11_RELOAD_DEFAULTS -{ - Ndis802_11ReloadWEPKeys -} NDIS_802_11_RELOAD_DEFAULTS, *PNDIS_802_11_RELOAD_DEFAULTS; - -#define NDIS_802_11_AI_REQFI_CAPABILITIES 1 -#define NDIS_802_11_AI_REQFI_LISTENINTERVAL 2 -#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS 4 - -#define NDIS_802_11_AI_RESFI_CAPABILITIES 1 -#define NDIS_802_11_AI_RESFI_STATUSCODE 2 -#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4 - -typedef struct _NDIS_802_11_AI_REQFI -{ - USHORT Capabilities; - USHORT ListenInterval; - NDIS_802_11_MAC_ADDRESS CurrentAPAddress; -} NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI; - -typedef struct _NDIS_802_11_AI_RESFI -{ - USHORT Capabilities; - USHORT StatusCode; - USHORT AssociationId; -} NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI; - -typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION -{ - ULONG Length; - USHORT AvailableRequestFixedIEs; - NDIS_802_11_AI_REQFI RequestFixedIEs; - ULONG RequestIELength; - ULONG OffsetRequestIEs; - USHORT AvailableResponseFixedIEs; - NDIS_802_11_AI_RESFI ResponseFixedIEs; - ULONG ResponseIELength; - ULONG OffsetResponseIEs; -} NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION; - -typedef struct _NDIS_802_11_AUTHENTICATION_EVENT -{ - NDIS_802_11_STATUS_INDICATION Status; - NDIS_802_11_AUTHENTICATION_REQUEST Request[1]; -} NDIS_802_11_AUTHENTICATION_EVENT, *PNDIS_802_11_AUTHENTICATION_EVENT; - -/* -typedef struct _NDIS_802_11_TEST -{ - ULONG Length; - ULONG Type; - union - { - NDIS_802_11_AUTHENTICATION_EVENT AuthenticationEvent; - NDIS_802_11_RSSI RssiTrigger; - }; -} NDIS_802_11_TEST, *PNDIS_802_11_TEST; - */ - -// 802.11 Media stream constraints, associated with OID_802_11_MEDIA_STREAM_MODE -typedef enum _NDIS_802_11_MEDIA_STREAM_MODE -{ - Ndis802_11MediaStreamOff, - Ndis802_11MediaStreamOn, -} NDIS_802_11_MEDIA_STREAM_MODE, *PNDIS_802_11_MEDIA_STREAM_MODE; - -// PMKID Structures -typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; - -#ifdef CONFIG_STA_SUPPORT -typedef struct _BSSID_INFO -{ - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_PMKID_VALUE PMKID; -} BSSID_INFO, *PBSSID_INFO; - -typedef struct _NDIS_802_11_PMKID -{ - UINT Length; - UINT BSSIDInfoCount; - BSSID_INFO BSSIDInfo[1]; -} NDIS_802_11_PMKID, *PNDIS_802_11_PMKID; -#endif // CONFIG_STA_SUPPORT // - - -typedef struct _NDIS_802_11_AUTHENTICATION_ENCRYPTION -{ - NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; - NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; -} NDIS_802_11_AUTHENTICATION_ENCRYPTION, *PNDIS_802_11_AUTHENTICATION_ENCRYPTION; - -typedef struct _NDIS_802_11_CAPABILITY -{ - ULONG Length; - ULONG Version; - ULONG NoOfPMKIDs; - ULONG NoOfAuthEncryptPairsSupported; - NDIS_802_11_AUTHENTICATION_ENCRYPTION AuthenticationEncryptionSupported[1]; -} NDIS_802_11_CAPABILITY, *PNDIS_802_11_CAPABILITY; - -#ifdef LINUX -#if WIRELESS_EXT <= 11 -#ifndef SIOCDEVPRIVATE -#define SIOCDEVPRIVATE 0x8BE0 -#endif -#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE -#endif -#endif // LINUX // - - -#ifdef CONFIG_STA_SUPPORT -#define RT_PRIV_IOCTL (SIOCIWFIRSTPRIV + 0x01) // Sync. with AP for wsc upnp daemon -#define RTPRIV_IOCTL_SET (SIOCIWFIRSTPRIV + 0x02) - -#ifdef DBG -#define RTPRIV_IOCTL_BBP (SIOCIWFIRSTPRIV + 0x03) -#define RTPRIV_IOCTL_MAC (SIOCIWFIRSTPRIV + 0x05) - -#ifdef RTMP_RF_RW_SUPPORT -// TODO: shiang, Need to reassign the oid number. ArchTeam use (SIOCIWFIRSTPRIV + 0x19) for this oid -#define RTPRIV_IOCTL_RF (SIOCIWFIRSTPRIV + 0x13) // edit by johnli, fix read rf register problem -#endif // RTMP_RF_RW_SUPPORT // - -#define RTPRIV_IOCTL_E2P (SIOCIWFIRSTPRIV + 0x07) -#endif // DBG // - -#ifdef RALINK_ATE -#ifdef RALINK_28xx_QA -#define RTPRIV_IOCTL_ATE (SIOCIWFIRSTPRIV + 0x08) -#endif // RALINK_28xx_QA // -#endif // RALINK_ATE // - -#define RTPRIV_IOCTL_STATISTICS (SIOCIWFIRSTPRIV + 0x09) -#define RTPRIV_IOCTL_ADD_PMKID_CACHE (SIOCIWFIRSTPRIV + 0x0A) -#define RTPRIV_IOCTL_RADIUS_DATA (SIOCIWFIRSTPRIV + 0x0C) -#define RTPRIV_IOCTL_GSITESURVEY (SIOCIWFIRSTPRIV + 0x0D) -#define RT_PRIV_IOCTL_EXT (SIOCIWFIRSTPRIV + 0x0E) // Sync. with RT61 (for wpa_supplicant) -#define RTPRIV_IOCTL_GET_MAC_TABLE (SIOCIWFIRSTPRIV + 0x0F) - -#define RTPRIV_IOCTL_SHOW (SIOCIWFIRSTPRIV + 0x11) -enum { - SHOW_CONN_STATUS = 4, - SHOW_DRVIER_VERION = 5, - SHOW_BA_INFO = 6, - SHOW_DESC_INFO = 7, - RAIO_OFF = 10, - RAIO_ON = 11, -#ifdef QOS_DLS_SUPPORT - SHOW_DLS_ENTRY_INFO = 19, -#endif // QOS_DLS_SUPPORT // - SHOW_CFG_VALUE = 20, - SHOW_ADHOC_ENTRY_INFO = 21, -}; - - -#endif // CONFIG_STA_SUPPORT // - - - -#ifdef SNMP_SUPPORT -//SNMP ieee 802dot11, kathy , 2008_0220 -// dot11res(3) -#define RT_OID_802_11_MANUFACTUREROUI 0x0700 -#define RT_OID_802_11_MANUFACTURERNAME 0x0701 -#define RT_OID_802_11_RESOURCETYPEIDNAME 0x0702 - -// dot11smt(1) -#define RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED 0x0703 -#define RT_OID_802_11_POWERMANAGEMENTMODE 0x0704 -#define OID_802_11_WEPDEFAULTKEYVALUE 0x0705 // read , write -#define OID_802_11_WEPDEFAULTKEYID 0x0706 -#define RT_OID_802_11_WEPKEYMAPPINGLENGTH 0x0707 -#define OID_802_11_SHORTRETRYLIMIT 0x0708 -#define OID_802_11_LONGRETRYLIMIT 0x0709 -#define RT_OID_802_11_PRODUCTID 0x0710 -#define RT_OID_802_11_MANUFACTUREID 0x0711 - -// //dot11Phy(4) -#define OID_802_11_CURRENTCHANNEL 0x0712 - -//dot11mac -#define RT_OID_802_11_MAC_ADDRESS 0x0713 -#endif // SNMP_SUPPORT // - -#define OID_802_11_BUILD_CHANNEL_EX 0x0714 -#define OID_802_11_GET_CH_LIST 0x0715 -#define OID_802_11_GET_COUNTRY_CODE 0x0716 -#define OID_802_11_GET_CHANNEL_GEOGRAPHY 0x0717 - -//#define RT_OID_802_11_STATISTICS (OID_GET_SET_TOGGLE | OID_802_11_STATISTICS) - -#ifdef CONFIG_STA_SUPPORT -#define RT_OID_WSC_SET_PASSPHRASE 0x0740 // passphrase for wpa(2)-psk -#define RT_OID_WSC_DRIVER_AUTO_CONNECT 0x0741 -#define RT_OID_WSC_QUERY_DEFAULT_PROFILE 0x0742 -#define RT_OID_WSC_SET_CONN_BY_PROFILE_INDEX 0x0743 -#define RT_OID_WSC_SET_ACTION 0x0744 -#define RT_OID_WSC_SET_SSID 0x0745 -#define RT_OID_WSC_SET_PIN_CODE 0x0746 -#define RT_OID_WSC_SET_MODE 0x0747 // PIN or PBC -#define RT_OID_WSC_SET_CONF_MODE 0x0748 // Enrollee or Registrar -#define RT_OID_WSC_SET_PROFILE 0x0749 -#endif // CONFIG_STA_SUPPORT // -#define RT_OID_WSC_CONFIG_STATUS 0x074F -#define RT_OID_802_11_WSC_QUERY_PROFILE 0x0750 -// for consistency with RT61 -#define RT_OID_WSC_QUERY_STATUS 0x0751 -#define RT_OID_WSC_PIN_CODE 0x0752 -#define RT_OID_WSC_UUID 0x0753 -#define RT_OID_WSC_SET_SELECTED_REGISTRAR 0x0754 -#define RT_OID_WSC_EAPMSG 0x0755 -#define RT_OID_WSC_MANUFACTURER 0x0756 -#define RT_OID_WSC_MODEL_NAME 0x0757 -#define RT_OID_WSC_MODEL_NO 0x0758 -#define RT_OID_WSC_SERIAL_NO 0x0759 -#define RT_OID_WSC_MAC_ADDRESS 0x0760 - -#ifdef LLTD_SUPPORT -// for consistency with RT61 -#define RT_OID_GET_PHY_MODE 0x761 -#endif // LLTD_SUPPORT // - -#ifdef NINTENDO_AP -//#define RT_OID_NINTENDO 0x0D010770 -#define RT_OID_802_11_NINTENDO_GET_TABLE 0x0771 //((RT_OID_NINTENDO + 0x01) & 0xffff) -#define RT_OID_802_11_NINTENDO_SET_TABLE 0x0772 //((RT_OID_NINTENDO + 0x02) & 0xffff) -#define RT_OID_802_11_NINTENDO_CAPABLE 0x0773 //((RT_OID_NINTENDO + 0x03) & 0xffff) -#endif // NINTENDO_AP // - - -// New for MeetingHouse Api support -#define OID_MH_802_1X_SUPPORTED 0xFFEDC100 - -// MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition!!! -typedef union _HTTRANSMIT_SETTING { -#ifdef RT_BIG_ENDIAN - struct { - USHORT MODE:2; // Use definition MODE_xxx. -// USHORT rsv:3; - USHORT TxBF:1; - USHORT rsv:2; - USHORT STBC:2; //SPACE - USHORT ShortGI:1; - USHORT BW:1; //channel bandwidth 20MHz or 40 MHz - USHORT MCS:7; // MCS - } field; -#else - struct { - USHORT MCS:7; // MCS - USHORT BW:1; //channel bandwidth 20MHz or 40 MHz - USHORT ShortGI:1; - USHORT STBC:2; //SPACE -// USHORT rsv:3; - USHORT rsv:2; - USHORT TxBF:1; - USHORT MODE:2; // Use definition MODE_xxx. - } field; -#endif - USHORT word; - } HTTRANSMIT_SETTING, *PHTTRANSMIT_SETTING; - -typedef enum _RT_802_11_PREAMBLE { - Rt802_11PreambleLong, - Rt802_11PreambleShort, - Rt802_11PreambleAuto -} RT_802_11_PREAMBLE, *PRT_802_11_PREAMBLE; - -typedef enum _RT_802_11_PHY_MODE { - PHY_11BG_MIXED = 0, - PHY_11B, - PHY_11A, - PHY_11ABG_MIXED, - PHY_11G, -#ifdef DOT11_N_SUPPORT - PHY_11ABGN_MIXED, // both band 5 - PHY_11N_2_4G, // 11n-only with 2.4G band 6 - PHY_11GN_MIXED, // 2.4G band 7 - PHY_11AN_MIXED, // 5G band 8 - PHY_11BGN_MIXED, // if check 802.11b. 9 - PHY_11AGN_MIXED, // if check 802.11b. 10 - PHY_11N_5G, // 11n-only with 5G band 11 -#endif // DOT11_N_SUPPORT // -} RT_802_11_PHY_MODE; - - -// put all proprietery for-query objects here to reduce # of Query_OID -typedef struct _RT_802_11_LINK_STATUS { - ULONG CurrTxRate; // in units of 0.5Mbps - ULONG ChannelQuality; // 0..100 % - ULONG TxByteCount; // both ok and fail - ULONG RxByteCount; // both ok and fail - ULONG CentralChannel; // 40MHz central channel number -} RT_802_11_LINK_STATUS, *PRT_802_11_LINK_STATUS; - -typedef struct _RT_802_11_EVENT_LOG { - LARGE_INTEGER SystemTime; // timestammp via NdisGetCurrentSystemTime() - UCHAR Addr[MAC_ADDR_LENGTH]; - USHORT Event; // EVENT_xxx -} RT_802_11_EVENT_LOG, *PRT_802_11_EVENT_LOG; - -typedef struct _RT_802_11_EVENT_TABLE { - ULONG Num; - ULONG Rsv; // to align Log[] at LARGE_INEGER boundary - RT_802_11_EVENT_LOG Log[MAX_NUMBER_OF_EVENT]; -} RT_802_11_EVENT_TABLE, PRT_802_11_EVENT_TABLE; - -// MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition!!! -typedef union _MACHTTRANSMIT_SETTING { - struct { - USHORT MCS:7; // MCS - USHORT BW:1; //channel bandwidth 20MHz or 40 MHz - USHORT ShortGI:1; - USHORT STBC:2; //SPACE - USHORT rsv:3; - USHORT MODE:2; // Use definition MODE_xxx. - } field; - USHORT word; - } MACHTTRANSMIT_SETTING, *PMACHTTRANSMIT_SETTING; - -typedef struct _RT_802_11_MAC_ENTRY { - UCHAR Addr[MAC_ADDR_LENGTH]; - UCHAR Aid; - UCHAR Psm; // 0:PWR_ACTIVE, 1:PWR_SAVE - UCHAR MimoPs; // 0:MMPS_STATIC, 1:MMPS_DYNAMIC, 3:MMPS_Enabled - CHAR AvgRssi0; - CHAR AvgRssi1; - CHAR AvgRssi2; - UINT32 ConnectedTime; - MACHTTRANSMIT_SETTING TxRate; -} RT_802_11_MAC_ENTRY, *PRT_802_11_MAC_ENTRY; - -typedef struct _RT_802_11_MAC_TABLE { - ULONG Num; - RT_802_11_MAC_ENTRY Entry[MAX_NUMBER_OF_MAC]; -} RT_802_11_MAC_TABLE, *PRT_802_11_MAC_TABLE; - -// structure for query/set hardware register - MAC, BBP, RF register -typedef struct _RT_802_11_HARDWARE_REGISTER { - ULONG HardwareType; // 0:MAC, 1:BBP, 2:RF register, 3:EEPROM - ULONG Offset; // Q/S register offset addr - ULONG Data; // R/W data buffer -} RT_802_11_HARDWARE_REGISTER, *PRT_802_11_HARDWARE_REGISTER; - -typedef struct _RT_802_11_AP_CONFIG { - ULONG EnableTxBurst; // 0-disable, 1-enable - ULONG EnableTurboRate; // 0-disable, 1-enable 72/100mbps turbo rate - ULONG IsolateInterStaTraffic; // 0-disable, 1-enable isolation - ULONG HideSsid; // 0-disable, 1-enable hiding - ULONG UseBGProtection; // 0-AUTO, 1-always ON, 2-always OFF - ULONG UseShortSlotTime; // 0-no use, 1-use 9-us short slot time - ULONG Rsv1; // must be 0 - ULONG SystemErrorBitmap; // ignore upon SET, return system error upon QUERY -} RT_802_11_AP_CONFIG, *PRT_802_11_AP_CONFIG; - -// structure to query/set STA_CONFIG -typedef struct _RT_802_11_STA_CONFIG { - ULONG EnableTxBurst; // 0-disable, 1-enable - ULONG EnableTurboRate; // 0-disable, 1-enable 72/100mbps turbo rate - ULONG UseBGProtection; // 0-AUTO, 1-always ON, 2-always OFF - ULONG UseShortSlotTime; // 0-no use, 1-use 9-us short slot time when applicable - ULONG AdhocMode; // 0-11b rates only (WIFI spec), 1 - b/g mixed, 2 - g only - ULONG HwRadioStatus; // 0-OFF, 1-ON, default is 1, Read-Only - ULONG Rsv1; // must be 0 - ULONG SystemErrorBitmap; // ignore upon SET, return system error upon QUERY -} RT_802_11_STA_CONFIG, *PRT_802_11_STA_CONFIG; - -// -// For OID Query or Set about BA structure -// -typedef struct _OID_BACAP_STRUC { - UCHAR RxBAWinLimit; - UCHAR TxBAWinLimit; - UCHAR Policy; // 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid - UCHAR MpduDensity; // 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid - UCHAR AmsduEnable; //Enable AMSDU transmisstion - UCHAR AmsduSize; // 0:3839, 1:7935 bytes. UINT MSDUSizeToBytes[] = { 3839, 7935}; - UCHAR MMPSmode; // MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable - BOOLEAN AutoBA; // Auto BA will automatically -} OID_BACAP_STRUC, *POID_BACAP_STRUC; - -typedef struct _RT_802_11_ACL_ENTRY { - UCHAR Addr[MAC_ADDR_LENGTH]; - USHORT Rsv; -} RT_802_11_ACL_ENTRY, *PRT_802_11_ACL_ENTRY; - -typedef struct PACKED _RT_802_11_ACL { - ULONG Policy; // 0-disable, 1-positive list, 2-negative list - ULONG Num; - RT_802_11_ACL_ENTRY Entry[MAX_NUMBER_OF_ACL]; -} RT_802_11_ACL, *PRT_802_11_ACL; - -typedef struct _RT_802_11_WDS { - ULONG Num; - NDIS_802_11_MAC_ADDRESS Entry[24/*MAX_NUM_OF_WDS_LINK*/]; - ULONG KeyLength; - UCHAR KeyMaterial[32]; -} RT_802_11_WDS, *PRT_802_11_WDS; - -typedef struct _RT_802_11_TX_RATES_ { - UCHAR SupRateLen; - UCHAR SupRate[MAX_LENGTH_OF_SUPPORT_RATES]; - UCHAR ExtRateLen; - UCHAR ExtRate[MAX_LENGTH_OF_SUPPORT_RATES]; -} RT_802_11_TX_RATES, *PRT_802_11_TX_RATES; - - -// Definition of extra information code -#define GENERAL_LINK_UP 0x0 // Link is Up -#define GENERAL_LINK_DOWN 0x1 // Link is Down -#define HW_RADIO_OFF 0x2 // Hardware radio off -#define SW_RADIO_OFF 0x3 // Software radio off -#define AUTH_FAIL 0x4 // Open authentication fail -#define AUTH_FAIL_KEYS 0x5 // Shared authentication fail -#define ASSOC_FAIL 0x6 // Association failed -#define EAP_MIC_FAILURE 0x7 // Deauthencation because MIC failure -#define EAP_4WAY_TIMEOUT 0x8 // Deauthencation on 4-way handshake timeout -#define EAP_GROUP_KEY_TIMEOUT 0x9 // Deauthencation on group key handshake timeout -#define EAP_SUCCESS 0xa // EAP succeed -#define DETECT_RADAR_SIGNAL 0xb // Radar signal occur in current channel -#define EXTRA_INFO_MAX 0xb // Indicate Last OID - -#define EXTRA_INFO_CLEAR 0xffffffff - -// This is OID setting structure. So only GF or MM as Mode. This is valid when our wirelss mode has 802.11n in use. -typedef struct { - RT_802_11_PHY_MODE PhyMode; // - UCHAR TransmitNo; - UCHAR HtMode; //HTMODE_GF or HTMODE_MM - UCHAR ExtOffset; //extension channel above or below - UCHAR MCS; - UCHAR BW; - UCHAR STBC; - UCHAR SHORTGI; - UCHAR rsv; -} OID_SET_HT_PHYMODE, *POID_SET_HT_PHYMODE; - -#ifdef NINTENDO_AP -#define NINTENDO_MAX_ENTRY 16 -#define NINTENDO_SSID_NAME_LN 8 -#define NINTENDO_SSID_NAME "NWCUSBAP" -#define NINTENDO_PROBE_REQ_FLAG_MASK 0x03 -#define NINTENDO_PROBE_REQ_ON 0x01 -#define NINTENDO_PROBE_REQ_SIGNAL 0x02 -#define NINTENDO_PROBE_RSP_ON 0x01 -#define NINTENDO_SSID_NICKNAME_LN 20 - -#define NINTENDO_WEPKEY_LN 13 - -typedef struct _NINTENDO_SSID -{ - UCHAR NINTENDOFixChar[NINTENDO_SSID_NAME_LN]; - UCHAR zero1; - UCHAR registe; - UCHAR ID; - UCHAR zero2; - UCHAR NICKname[NINTENDO_SSID_NICKNAME_LN]; -} RT_NINTENDO_SSID, *PRT_NINTENDO_SSID; - -typedef struct _NINTENDO_ENTRY -{ - UCHAR NICKname[NINTENDO_SSID_NICKNAME_LN]; - UCHAR DS_Addr[ETH_LENGTH_OF_ADDRESS]; - UCHAR registe; - UCHAR UserSpaceAck; -} RT_NINTENDO_ENTRY, *PRT_NINTENDO_ENTRY; - -//RTPRIV_IOCTL_NINTENDO_GET_TABLE -//RTPRIV_IOCTL_NINTENDO_SET_TABLE -typedef struct _NINTENDO_TABLE -{ - UINT number; - RT_NINTENDO_ENTRY entry[NINTENDO_MAX_ENTRY]; -} RT_NINTENDO_TABLE, *PRT_NINTENDO_TABLE; - -//RTPRIV_IOCTL_NINTENDO_SEED_WEPKEY -typedef struct _NINTENDO_SEED_WEPKEY -{ - UCHAR seed[NINTENDO_SSID_NICKNAME_LN]; - UCHAR wepkey[16];//use 13 for 104 bits wep key -} RT_NINTENDO_SEED_WEPKEY, *PRT_NINTENDO_SEED_WEPKEY; -#endif // NINTENDO_AP // - -#ifdef LLTD_SUPPORT -typedef struct _RT_LLTD_ASSOICATION_ENTRY { - UCHAR Addr[ETH_LENGTH_OF_ADDRESS]; - unsigned short MOR; // maximum operational rate - UCHAR phyMode; -} RT_LLTD_ASSOICATION_ENTRY, *PRT_LLTD_ASSOICATION_ENTRY; - -typedef struct _RT_LLTD_ASSOICATION_TABLE { - unsigned int Num; - RT_LLTD_ASSOICATION_ENTRY Entry[MAX_NUMBER_OF_MAC]; -} RT_LLTD_ASSOICATION_TABLE, *PRT_LLTD_ASSOICATION_TABLE; -#endif // LLTD_SUPPORT // - -#ifdef CONFIG_STA_SUPPORT -#ifdef QOS_DLS_SUPPORT -//rt2860, kathy 2007-0118 -// structure for DLS -typedef struct _RT_802_11_DLS_UI { - USHORT TimeOut; // unit: second , set by UI - USHORT CountDownTimer; // unit: second , used by driver only - NDIS_802_11_MAC_ADDRESS MacAddr; // set by UI - UCHAR Status; // 0: none , 1: wait STAkey, 2: finish DLS setup , set by driver only - BOOLEAN Valid; // 1: valid , 0: invalid , set by UI, use to setup or tear down DLS link -} RT_802_11_DLS_UI, *PRT_802_11_DLS_UI; - -typedef struct _RT_802_11_DLS_INFO { - RT_802_11_DLS_UI Entry[MAX_NUMBER_OF_DLS_ENTRY]; - UCHAR num; -} RT_802_11_DLS_INFO, *PRT_802_11_DLS_INFO; - -typedef enum _RT_802_11_DLS_MODE { - DLS_NONE, - DLS_WAIT_KEY, - DLS_FINISH -} RT_802_11_DLS_MODE; -#endif // QOS_DLS_SUPPORT // - -#ifdef WPA_SUPPLICANT_SUPPORT -#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT -#define RT_ASSOC_EVENT_FLAG 0x0101 -#define RT_DISASSOC_EVENT_FLAG 0x0102 -#define RT_REQIE_EVENT_FLAG 0x0103 -#define RT_RESPIE_EVENT_FLAG 0x0104 -#define RT_ASSOCINFO_EVENT_FLAG 0x0105 -#define RT_PMKIDCAND_FLAG 0x0106 -#define RT_INTERFACE_DOWN 0x0107 -#define RT_INTERFACE_UP 0x0108 -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // -#endif // WPA_SUPPLICANT_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - - - - -#define MAX_CUSTOM_LEN 128 - -#ifdef CONFIG_STA_SUPPORT -typedef enum _RT_802_11_D_CLIENT_MODE -{ - Rt802_11_D_None, - Rt802_11_D_Flexible, - Rt802_11_D_Strict, -} RT_802_11_D_CLIENT_MODE, *PRT_802_11_D_CLIENT_MODE; -#endif // CONFIG_STA_SUPPORT // - -typedef struct _RT_CHANNEL_LIST_INFO -{ - UCHAR ChannelList[MAX_NUM_OF_CHS]; // list all supported channels for site survey - UCHAR ChannelListNum; // number of channel in ChannelList[] -} RT_CHANNEL_LIST_INFO, *PRT_CHANNEL_LIST_INFO; - -// WSC configured credential -typedef struct _WSC_CREDENTIAL -{ - NDIS_802_11_SSID SSID; // mandatory - USHORT AuthType; // mandatory, 1: open, 2: wpa-psk, 4: shared, 8:wpa, 0x10: wpa2, 0x20: wpa2-psk - USHORT EncrType; // mandatory, 1: none, 2: wep, 4: tkip, 8: aes - UCHAR Key[64]; // mandatory, Maximum 64 byte - USHORT KeyLength; - UCHAR MacAddr[6]; // mandatory, AP MAC address - UCHAR KeyIndex; // optional, default is 1 - UCHAR Rsvd[3]; // Make alignment -} WSC_CREDENTIAL, *PWSC_CREDENTIAL; - -// WSC configured profiles -typedef struct _WSC_PROFILE -{ - UINT ProfileCnt; - UINT ApplyProfileIdx; // add by johnli, fix WPS test plan 5.1.1 - WSC_CREDENTIAL Profile[8]; // Support up to 8 profiles -} WSC_PROFILE, *PWSC_PROFILE; - - - -#endif // _OID_H_ diff --git a/drivers/staging/rt3090/pci_main_dev.c b/drivers/staging/rt3090/pci_main_dev.c deleted file mode 100644 index 1410156b90c6a85f831ba3d54b8f987f268304f8..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/pci_main_dev.c +++ /dev/null @@ -1,1195 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - pci_main_dev.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Name Date Modification logs -*/ - - -#include "rt_config.h" -#include - -// Following information will be show when you run 'modinfo' -// *** If you have a solution for the bug in current version of driver, please mail to me. -// Otherwise post to forum in ralinktech's web site(www.ralinktech.com) and let all users help you. *** -MODULE_AUTHOR("Jett Chen "); -MODULE_DESCRIPTION("RT3090 Wireless Lan Linux Driver"); -MODULE_LICENSE("GPL"); - -// -// Function declarations -// -extern int rt28xx_close(IN struct net_device *net_dev); -extern int rt28xx_open(struct net_device *net_dev); - -static VOID __devexit rt2860_remove_one(struct pci_dev *pci_dev); -static INT __devinit rt2860_probe(struct pci_dev *pci_dev, const struct pci_device_id *ent); -static void __exit rt2860_cleanup_module(void); -static int __init rt2860_init_module(void); - - - static VOID RTMPInitPCIeDevice( - IN struct pci_dev *pci_dev, - IN PRTMP_ADAPTER pAd); - - -#ifdef CONFIG_PM -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) -#define pm_message_t u32 -#endif - -static int rt2860_suspend(struct pci_dev *pci_dev, pm_message_t state); -static int rt2860_resume(struct pci_dev *pci_dev); -#endif -#endif // CONFIG_PM // - -// -// Ralink PCI device table, include all supported chipsets -// -static struct pci_device_id rt2860_pci_tbl[] __devinitdata = -{ -#ifdef RT3090 - {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3090_PCIe_DEVICE_ID)}, - {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3091_PCIe_DEVICE_ID)}, - {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3092_PCIe_DEVICE_ID)}, - {PCI_DEVICE(0x1462, 0x891A)}, -#endif // RT3090 // -#ifdef RT3390 - {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3390_PCIe_DEVICE_ID)}, - {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3391_PCIe_DEVICE_ID)}, - {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3392_PCIe_DEVICE_ID)}, -#endif // RT3390 // - {0,} // terminate list -}; - -MODULE_DEVICE_TABLE(pci, rt2860_pci_tbl); -#ifdef CONFIG_STA_SUPPORT -#ifdef MODULE_VERSION -MODULE_VERSION(STA_DRIVER_VERSION); -#endif -#endif // CONFIG_STA_SUPPORT // - - -// -// Our PCI driver structure -// -static struct pci_driver rt2860_driver = -{ - name: "rt3090", - id_table: rt2860_pci_tbl, - probe: rt2860_probe, -#if LINUX_VERSION_CODE >= 0x20412 - remove: __devexit_p(rt2860_remove_one), -#else - remove: __devexit(rt2860_remove_one), -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#ifdef CONFIG_PM - suspend: rt2860_suspend, - resume: rt2860_resume, -#endif -#endif -}; - - -/*************************************************************************** - * - * PCI device initialization related procedures. - * - ***************************************************************************/ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#ifdef CONFIG_PM - -VOID RT2860RejectPendingPackets( - IN PRTMP_ADAPTER pAd) -{ - // clear PS packets - // clear TxSw packets -} - -static int rt2860_suspend( - struct pci_dev *pci_dev, - pm_message_t state) -{ - struct net_device *net_dev = pci_get_drvdata(pci_dev); - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)NULL; - INT32 retval = 0; - - - DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_suspend()\n")); - - if (net_dev == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n")); - } - else - { - pAd = (PRTMP_ADAPTER)RTMP_OS_NETDEV_GET_PRIV(net_dev); - - /* we can not use IFF_UP because ra0 down but ra1 up */ - /* and 1 suspend/resume function for 1 module, not for each interface */ - /* so Linux will call suspend/resume function once */ - if (VIRTUAL_IF_NUM(pAd) > 0) - { - // avoid users do suspend after interface is down - - // stop interface - netif_carrier_off(net_dev); - netif_stop_queue(net_dev); - - // mark device as removed from system and therefore no longer available - netif_device_detach(net_dev); - - // mark halt flag - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - - // take down the device - rt28xx_close((PNET_DEV)net_dev); - - RT_MOD_DEC_USE_COUNT(); - } - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) - // reference to http://vovo2000.com/type-lab/linux/kernel-api/linux-kernel-api.html - // enable device to generate PME# when suspended - // pci_choose_state(): Choose the power state of a PCI device to be suspended - retval = pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1); - // save the PCI configuration space of a device before suspending - pci_save_state(pci_dev); - // disable PCI device after use - pci_disable_device(pci_dev); - - retval = pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); -#endif - - DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_suspend()\n")); - return retval; -} - -static int rt2860_resume( - struct pci_dev *pci_dev) -{ - struct net_device *net_dev = pci_get_drvdata(pci_dev); - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)NULL; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) - INT32 retval; - - - // set the power state of a PCI device - // PCI has 4 power states, DO (normal) ~ D3(less power) - // in include/linux/pci.h, you can find that - // #define PCI_D0 ((pci_power_t __force) 0) - // #define PCI_D1 ((pci_power_t __force) 1) - // #define PCI_D2 ((pci_power_t __force) 2) - // #define PCI_D3hot ((pci_power_t __force) 3) - // #define PCI_D3cold ((pci_power_t __force) 4) - // #define PCI_UNKNOWN ((pci_power_t __force) 5) - // #define PCI_POWER_ERROR ((pci_power_t __force) -1) - retval = pci_set_power_state(pci_dev, PCI_D0); - - // restore the saved state of a PCI device - pci_restore_state(pci_dev); - - // initialize device before it's used by a driver - if (pci_enable_device(pci_dev)) - { - printk("pci enable fail!\n"); - return 0; - } -#endif - - DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_resume()\n")); - - if (net_dev == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n")); - } - else - pAd = (PRTMP_ADAPTER)RTMP_OS_NETDEV_GET_PRIV(net_dev); - - if (pAd != NULL) - { - /* we can not use IFF_UP because ra0 down but ra1 up */ - /* and 1 suspend/resume function for 1 module, not for each interface */ - /* so Linux will call suspend/resume function once */ - if (VIRTUAL_IF_NUM(pAd) > 0) - { - // mark device as attached from system and restart if needed - netif_device_attach(net_dev); - - if (rt28xx_open((PNET_DEV)net_dev) != 0) - { - // open fail - DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_resume()\n")); - return 0; - } - - // increase MODULE use count - RT_MOD_INC_USE_COUNT(); - - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); - - netif_start_queue(net_dev); - netif_carrier_on(net_dev); - netif_wake_queue(net_dev); - } - } - - DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_resume()\n")); - return 0; -} -#endif // CONFIG_PM // -#endif - - -static INT __init rt2860_init_module(VOID) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - return pci_register_driver(&rt2860_driver); -#else - return pci_module_init(&rt2860_driver); -#endif -} - - -// -// Driver module unload function -// -static VOID __exit rt2860_cleanup_module(VOID) -{ - pci_unregister_driver(&rt2860_driver); -} - -module_init(rt2860_init_module); -module_exit(rt2860_cleanup_module); - - -// -// PCI device probe & initialization function -// -static INT __devinit rt2860_probe( - IN struct pci_dev *pci_dev, - IN const struct pci_device_id *pci_id) -{ - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)NULL; - struct net_device *net_dev; - PVOID handle; - PSTRING print_name; - ULONG csr_addr; - INT rv = 0; - RTMP_OS_NETDEV_OP_HOOK netDevHook; - - DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_probe\n")); - -//PCIDevInit============================================== - // wake up and enable device - if ((rv = pci_enable_device(pci_dev))!= 0) - { - DBGPRINT(RT_DEBUG_ERROR, ("Enable PCI device failed, errno=%d!\n", rv)); - return rv; - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - print_name = pci_dev ? pci_name(pci_dev) : "rt3090"; -#else - print_name = pci_dev ? pci_dev->slot_name : "rt3090"; -#endif // LINUX_VERSION_CODE // - - if ((rv = pci_request_regions(pci_dev, print_name)) != 0) - { - DBGPRINT(RT_DEBUG_ERROR, ("Request PCI resource failed, errno=%d!\n", rv)); - goto err_out; - } - - // map physical address to virtual address for accessing register - csr_addr = (unsigned long) ioremap(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); - if (!csr_addr) - { - DBGPRINT(RT_DEBUG_ERROR, ("ioremap failed for device %s, region 0x%lX @ 0x%lX\n", - print_name, (ULONG)pci_resource_len(pci_dev, 0), (ULONG)pci_resource_start(pci_dev, 0))); - goto err_out_free_res; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("%s: at 0x%lx, VA 0x%lx, IRQ %d. \n", print_name, - (ULONG)pci_resource_start(pci_dev, 0), (ULONG)csr_addr, pci_dev->irq)); - } - - // Set DMA master - pci_set_master(pci_dev); - - -//RtmpDevInit============================================== - // Allocate RTMP_ADAPTER adapter structure - handle = kmalloc(sizeof(struct os_cookie), GFP_KERNEL); - if (handle == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s(): Allocate memory for os handle failed!\n", __FUNCTION__)); - goto err_out_iounmap; - } - - ((POS_COOKIE)handle)->pci_dev = pci_dev; - - rv = RTMPAllocAdapterBlock(handle, &pAd); //shiang: we may need the pci_dev for allocate structure of "RTMP_ADAPTER" - if (rv != NDIS_STATUS_SUCCESS) - goto err_out_iounmap; - // Here are the RTMP_ADAPTER structure with pci-bus specific parameters. - pAd->CSRBaseAddress = (PUCHAR)csr_addr; - DBGPRINT(RT_DEBUG_ERROR, ("pAd->CSRBaseAddress =0x%lx, csr_addr=0x%lx!\n", (ULONG)pAd->CSRBaseAddress, csr_addr)); - RtmpRaDevCtrlInit(pAd, RTMP_DEV_INF_PCI); - - -//NetDevInit============================================== - net_dev = RtmpPhyNetDevInit(pAd, &netDevHook); - if (net_dev == NULL) - goto err_out_free_radev; - - // Here are the net_device structure with pci-bus specific parameters. - net_dev->irq = pci_dev->irq; // Interrupt IRQ number - net_dev->base_addr = csr_addr; // Save CSR virtual address and irq to device structure - pci_set_drvdata(pci_dev, net_dev); // Set driver data - -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT -/* for supporting Network Manager */ - /* Set the sysfs physical device reference for the network logical device - * if set prior to registration will cause a symlink during initialization. - */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) - SET_NETDEV_DEV(net_dev, &(pci_dev->dev)); -#endif -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - - -//All done, it's time to register the net device to linux kernel. - // Register this device - rv = RtmpOSNetDevAttach(net_dev, &netDevHook); - if (rv) - goto err_out_free_netdev; - -#ifdef CONFIG_STA_SUPPORT - pAd->StaCfg.OriDevType = net_dev->type; -#endif // CONFIG_STA_SUPPORT // -RTMPInitPCIeDevice(pci_dev, pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_probe\n")); - - return 0; // probe ok - - - /* --------------------------- ERROR HANDLE --------------------------- */ -err_out_free_netdev: - RtmpOSNetDevFree(net_dev); - -err_out_free_radev: - /* free RTMP_ADAPTER strcuture and os_cookie*/ - RTMPFreeAdapter(pAd); - -err_out_iounmap: - iounmap((void *)(csr_addr)); - release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); - -err_out_free_res: - pci_release_regions(pci_dev); - -err_out: - pci_disable_device(pci_dev); - - DBGPRINT(RT_DEBUG_ERROR, ("<=== rt2860_probe failed with rv = %d!\n", rv)); - - return -ENODEV; /* probe fail */ -} - - -static VOID __devexit rt2860_remove_one( - IN struct pci_dev *pci_dev) -{ - PNET_DEV net_dev = pci_get_drvdata(pci_dev); - RTMP_ADAPTER *pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev); - ULONG csr_addr = net_dev->base_addr; // pAd->CSRBaseAddress; - - DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_remove_one\n")); - - if (pAd != NULL) - { - // Unregister/Free all allocated net_device. - RtmpPhyNetDevExit(pAd, net_dev); - - // Unmap CSR base address - iounmap((char *)(csr_addr)); - - // release memory region - release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); - - // Free RTMP_ADAPTER related structures. - RtmpRaDevCtrlExit(pAd); - - } - else - { - // Unregister network device - RtmpOSNetDevDetach(net_dev); - - // Unmap CSR base address - iounmap((char *)(net_dev->base_addr)); - - // release memory region - release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); - } - - // Free the root net_device - RtmpOSNetDevFree(net_dev); - -} - - -/* -======================================================================== -Routine Description: - Check the chipset vendor/product ID. - -Arguments: - _dev_p Point to the PCI or USB device - -Return Value: - TRUE Check ok - FALSE Check fail - -Note: -======================================================================== -*/ -BOOLEAN RT28XXChipsetCheck( - IN void *_dev_p) -{ - /* always TRUE */ - return TRUE; -} - - - -/*************************************************************************** - * - * PCIe device initialization related procedures. - * - ***************************************************************************/ - static VOID RTMPInitPCIeDevice( - IN struct pci_dev *pci_dev, - IN PRTMP_ADAPTER pAd) -{ - USHORT device_id; - POS_COOKIE pObj; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - pci_read_config_word(pci_dev, PCI_DEVICE_ID, &device_id); - device_id = le2cpu16(device_id); - pObj->DeviceID = device_id; - if ( -#ifdef RT3090 - (device_id == NIC3090_PCIe_DEVICE_ID) || - (device_id == NIC3091_PCIe_DEVICE_ID) || - (device_id == NIC3092_PCIe_DEVICE_ID) || -#endif // RT3090 // - 0) - { - UINT32 MacCsr0 = 0, Index= 0; - do - { - RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); - - if ((MacCsr0 != 0x00) && (MacCsr0 != 0xFFFFFFFF)) - break; - - RTMPusecDelay(10); - } while (Index++ < 100); - - // Support advanced power save after 2892/2790. - // MAC version at offset 0x1000 is 0x2872XXXX/0x2870XXXX(PCIe, USB, SDIO). - if ((MacCsr0&0xffff0000) != 0x28600000) - { - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_PCIE_DEVICE); - } - } -} - -#ifdef CONFIG_STA_SUPPORT -VOID RTMPInitPCIeLinkCtrlValue( - IN PRTMP_ADAPTER pAd) -{ - INT pos; - USHORT reg16, data2, PCIePowerSaveLevel, Configuration; - UINT32 MacValue; - BOOLEAN bFindIntel = FALSE; - POS_COOKIE pObj; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - return; - - DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __FUNCTION__)); - // Init EEPROM, and save settings - if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) - { - RT28xx_EEPROM_READ16(pAd, 0x22, PCIePowerSaveLevel); - pAd->PCIePowerSaveLevel = PCIePowerSaveLevel & 0xff; - pAd->LnkCtrlBitMask = 0; - if ((PCIePowerSaveLevel&0xff) == 0xff) - { - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_PCIE_DEVICE); - DBGPRINT(RT_DEBUG_TRACE, ("====> PCIePowerSaveLevel = 0x%x.\n", PCIePowerSaveLevel)); - return; - } - else - { - PCIePowerSaveLevel &= 0x3; - RT28xx_EEPROM_READ16(pAd, 0x24, data2); - - if( !(((data2&0xff00) == 0x9200) && ((data2&0x80) !=0)) ) - { - if (PCIePowerSaveLevel > 1 ) - PCIePowerSaveLevel = 1; - } - - DBGPRINT(RT_DEBUG_TRACE, ("====> Write 0x83 = 0x%x.\n", PCIePowerSaveLevel)); - AsicSendCommandToMcu(pAd, 0x83, 0xff, (UCHAR)PCIePowerSaveLevel, 0x00); - RT28xx_EEPROM_READ16(pAd, 0x22, PCIePowerSaveLevel); - PCIePowerSaveLevel &= 0xff; - PCIePowerSaveLevel = PCIePowerSaveLevel >> 6; - switch(PCIePowerSaveLevel) - { - case 0: // Only support L0 - pAd->LnkCtrlBitMask = 0; - break; - case 1: // Only enable L0s - pAd->LnkCtrlBitMask = 1; - break; - case 2: // enable L1, L0s - pAd->LnkCtrlBitMask = 3; - break; - case 3: // sync with host clk and enable L1, L0s - pAd->LnkCtrlBitMask = 0x103; - break; - } - RT28xx_EEPROM_READ16(pAd, 0x24, data2); - if ((PCIePowerSaveLevel&0xff) != 0xff) - { - PCIePowerSaveLevel &= 0x3; - - if( !(((data2&0xff00) == 0x9200) && ((data2&0x80) !=0)) ) - { - if (PCIePowerSaveLevel > 1 ) - PCIePowerSaveLevel = 1; - } - - DBGPRINT(RT_DEBUG_TRACE, ("====> rt28xx Write 0x83 Command = 0x%x.\n", PCIePowerSaveLevel)); - printk("\n\n\n%s:%d\n",__FUNCTION__,__LINE__); - - AsicSendCommandToMcu(pAd, 0x83, 0xff, (UCHAR)PCIePowerSaveLevel, 0x00); - } - DBGPRINT(RT_DEBUG_TRACE, ("====> LnkCtrlBitMask = 0x%x.\n", pAd->LnkCtrlBitMask)); - } - } - else if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) - { - UCHAR LinkCtrlSetting = 0; - - // Check 3090E special setting chip. - RT28xx_EEPROM_READ16(pAd, 0x24, data2); - if ((data2 == 0x9280) && ((pAd->MACVersion&0xffff) == 0x0211)) - { - pAd->b3090ESpecialChip = TRUE; - DBGPRINT_RAW(RT_DEBUG_ERROR,("Special 3090E chip \n")); - } - - RTMP_IO_READ32(pAd, AUX_CTRL, &MacValue); - //enable WAKE_PCIE function, which forces to enable PCIE clock when mpu interrupt asserting. - //Force PCIE 125MHz CLK to toggle - MacValue |= 0x402; - RTMP_IO_WRITE32(pAd, AUX_CTRL, MacValue); - DBGPRINT_RAW(RT_DEBUG_ERROR,(" AUX_CTRL = 0x%32x\n", MacValue)); - - - - // for RT30xx F and after, PCIe infterface, and for power solution 3 - if ((IS_VERSION_AFTER_F(pAd)) - && (pAd->StaCfg.PSControl.field.rt30xxPowerMode >= 2) - && (pAd->StaCfg.PSControl.field.rt30xxPowerMode <= 3)) - { - RTMP_IO_READ32(pAd, AUX_CTRL, &MacValue); - DBGPRINT_RAW(RT_DEBUG_ERROR,(" Read AUX_CTRL = 0x%x\n", MacValue)); - // turn on bit 12. - //enable 32KHz clock mode for power saving - MacValue |= 0x1000; - if (MacValue != 0xffffffff) - { - RTMP_IO_WRITE32(pAd, AUX_CTRL, MacValue); - DBGPRINT_RAW(RT_DEBUG_ERROR,(" Write AUX_CTRL = 0x%x\n", MacValue)); - // 1. if use PCIePowerSetting is 2 or 3, need to program OSC_CTRL to 0x3ff11. - MacValue = 0x3ff11; - RTMP_IO_WRITE32(pAd, OSC_CTRL, MacValue); - DBGPRINT_RAW(RT_DEBUG_ERROR,(" OSC_CTRL = 0x%x\n", MacValue)); - // 2. Write PCI register Clk ref bit - RTMPrt3xSetPCIePowerLinkCtrl(pAd); - } - else - { - // Error read Aux_Ctrl value. Force to use solution 1 - DBGPRINT(RT_DEBUG_ERROR,(" Error Value in AUX_CTRL = 0x%x\n", MacValue)); - pAd->StaCfg.PSControl.field.rt30xxPowerMode = 1; - DBGPRINT(RT_DEBUG_ERROR,(" Force to use power solution1 \n")); - } - } - // 1. read setting from inf file. - - PCIePowerSaveLevel = (USHORT)pAd->StaCfg.PSControl.field.rt30xxPowerMode; - DBGPRINT(RT_DEBUG_ERROR, ("====> rt30xx Read PowerLevelMode = 0x%x.\n", PCIePowerSaveLevel)); - // 2. Check EnableNewPS. - if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) - PCIePowerSaveLevel = 1; - - if (IS_VERSION_BEFORE_F(pAd) && (pAd->b3090ESpecialChip == FALSE)) - { - // Chip Version E only allow 1, So force set 1. - PCIePowerSaveLevel &= 0x1; - pAd->PCIePowerSaveLevel = (USHORT)PCIePowerSaveLevel; - DBGPRINT(RT_DEBUG_TRACE, ("====> rt30xx E Write 0x83 Command = 0x%x.\n", PCIePowerSaveLevel)); - - AsicSendCommandToMcu(pAd, 0x83, 0xff, (UCHAR)PCIePowerSaveLevel, 0x00); - } - else - { - // Chip Version F and after only allow 1 or 2 or 3. This might be modified after new chip version come out. - if (!((PCIePowerSaveLevel == 1) || (PCIePowerSaveLevel == 3))) - PCIePowerSaveLevel = 1; - DBGPRINT(RT_DEBUG_ERROR, ("====> rt30xx F Write 0x83 Command = 0x%x.\n", PCIePowerSaveLevel)); - pAd->PCIePowerSaveLevel = (USHORT)PCIePowerSaveLevel; - // for 3090F , we need to add high-byte arg for 0x83 command to indicate the link control setting in - // PCI Configuration Space. Because firmware can't read PCI Configuration Space - if ((pAd->Rt3xxRalinkLinkCtrl & 0x2) && (pAd->Rt3xxHostLinkCtrl & 0x2)) - { - LinkCtrlSetting = 1; - } - DBGPRINT(RT_DEBUG_TRACE, ("====> rt30xxF LinkCtrlSetting = 0x%x.\n", LinkCtrlSetting)); - AsicSendCommandToMcu(pAd, 0x83, 0xff, (UCHAR)PCIePowerSaveLevel, LinkCtrlSetting); - } - - } - - // Find Ralink PCIe Device's Express Capability Offset - pos = pci_find_capability(pObj->pci_dev, PCI_CAP_ID_EXP); - - if (pos != 0) - { - // Ralink PCIe Device's Link Control Register Offset - pAd->RLnkCtrlOffset = pos + PCI_EXP_LNKCTL; - pci_read_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset, ®16); - Configuration = le2cpu16(reg16); - DBGPRINT(RT_DEBUG_TRACE, ("Read (Ralink PCIe Link Control Register) offset 0x%x = 0x%x\n", - pAd->RLnkCtrlOffset, Configuration)); - pAd->RLnkCtrlConfiguration = (Configuration & 0x103); - Configuration &= 0xfefc; - Configuration |= (0x0); - - RTMPFindHostPCIDev(pAd); - if (pObj->parent_pci_dev) - { - USHORT vendor_id; - - pci_read_config_word(pObj->parent_pci_dev, PCI_VENDOR_ID, &vendor_id); - vendor_id = le2cpu16(vendor_id); - if (vendor_id == PCIBUS_INTEL_VENDOR) - { - bFindIntel = TRUE; - RTMP_SET_PSFLAG(pAd, fRTMP_PS_TOGGLE_L1); - } - /* - else if ((vendor_id == PCIBUS_AMD_VENDOR1) - && (DeviceID == 0x96000000)) - { - //Verified 2792 Aspire 8530 AMD NB (S3/S4/CBoot/WBoot/Chariot) by customer and ourselves. - // So use L1 Toggle method in this NB. - bFindIntel = TRUE; - RTMP_SET_PSFLAG(pAd, fRTMP_PS_TOGGLE_L1); - DBGPRINT(RT_DEBUG_TRACE, ("PSM : Aspire 8530 AMD NB. Use L1 Toggle. \n")); - } - */ - // Find PCI-to-PCI Bridge Express Capability Offset - pos = pci_find_capability(pObj->parent_pci_dev, PCI_CAP_ID_EXP); - - if (pos != 0) - { - BOOLEAN bChange = FALSE; - // PCI-to-PCI Bridge Link Control Register Offset - pAd->HostLnkCtrlOffset = pos + PCI_EXP_LNKCTL; - pci_read_config_word(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, ®16); - Configuration = le2cpu16(reg16); - DBGPRINT(RT_DEBUG_TRACE, ("Read (Host PCI-to-PCI Bridge Link Control Register) offset 0x%x = 0x%x\n", - pAd->HostLnkCtrlOffset, Configuration)); - pAd->HostLnkCtrlConfiguration = (Configuration & 0x103); - Configuration &= 0xfefc; - Configuration |= (0x0); - - switch (pObj->DeviceID) - { -#ifdef RT3090 - case NIC3090_PCIe_DEVICE_ID: - case NIC3091_PCIe_DEVICE_ID: - case NIC3092_PCIe_DEVICE_ID: - if (bFindIntel == FALSE) - bChange = TRUE; - break; -#endif // RT3090 // - default: - break; - } - - if (bChange) - { - reg16 = cpu2le16(Configuration); - pci_write_config_word(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, reg16); - DBGPRINT(RT_DEBUG_TRACE, ("Write (Host PCI-to-PCI Bridge Link Control Register) offset 0x%x = 0x%x\n", - pAd->HostLnkCtrlOffset, Configuration)); - } - } - else - { - pAd->HostLnkCtrlOffset = 0; - DBGPRINT(RT_DEBUG_ERROR, ("%s: cannot find PCI-to-PCI Bridge PCI Express Capability!\n", __FUNCTION__)); - } - } - } - else - { - pAd->RLnkCtrlOffset = 0; - pAd->HostLnkCtrlOffset = 0; - DBGPRINT(RT_DEBUG_ERROR, ("%s: cannot find Ralink PCIe Device's PCI Express Capability!\n", __FUNCTION__)); - } - - if (bFindIntel == FALSE) - { - DBGPRINT(RT_DEBUG_TRACE, ("Doesn't find Intel PCI host controller. \n")); - // Doesn't switch L0, L1, So set PCIePowerSaveLevel to 0xff - pAd->PCIePowerSaveLevel = 0xff; - if ((pAd->RLnkCtrlOffset != 0) -#ifdef RT3090 - && ((pObj->DeviceID == NIC3090_PCIe_DEVICE_ID) - ||(pObj->DeviceID == NIC3091_PCIe_DEVICE_ID) - ||(pObj->DeviceID == NIC3092_PCIe_DEVICE_ID)) -#endif // RT3090 // - ) - { - pci_read_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset, ®16); - Configuration = le2cpu16(reg16); - DBGPRINT(RT_DEBUG_TRACE, ("Read (Ralink 30xx PCIe Link Control Register) offset 0x%x = 0x%x\n", - pAd->RLnkCtrlOffset, Configuration)); - pAd->RLnkCtrlConfiguration = (Configuration & 0x103); - Configuration &= 0xfefc; - Configuration |= (0x0); - reg16 = cpu2le16(Configuration); - pci_write_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset, reg16); - DBGPRINT(RT_DEBUG_TRACE, ("Write (Ralink PCIe Link Control Register) offset 0x%x = 0x%x\n", - pos + PCI_EXP_LNKCTL, Configuration)); - } - } -} - -VOID RTMPFindHostPCIDev( - IN PRTMP_ADAPTER pAd) -{ - USHORT reg16; - UCHAR reg8; - UINT DevFn; - PPCI_DEV pPci_dev; - POS_COOKIE pObj; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - return; - - DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __FUNCTION__)); - - pObj->parent_pci_dev = NULL; - if (pObj->pci_dev->bus->parent) - { - for (DevFn = 0; DevFn < 255; DevFn++) - { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - pPci_dev = pci_get_slot(pObj->pci_dev->bus->parent, DevFn); -#else - pPci_dev = pci_find_slot(pObj->pci_dev->bus->parent->number, DevFn); -#endif - if (pPci_dev) - { - pci_read_config_word(pPci_dev, PCI_CLASS_DEVICE, ®16); - reg16 = le2cpu16(reg16); - pci_read_config_byte(pPci_dev, PCI_CB_CARD_BUS, ®8); - if ((reg16 == PCI_CLASS_BRIDGE_PCI) && - (reg8 == pObj->pci_dev->bus->number)) - { - pObj->parent_pci_dev = pPci_dev; - } - } - } - } -} - -/* - ======================================================================== - - Routine Description: - - Arguments: - Level = RESTORE_HALT : Restore PCI host and Ralink PCIe Link Control field to its default value. - Level = Other Value : Restore from dot11 power save or radio off status. And force PCI host Link Control fields to 0x1 - - ======================================================================== -*/ -VOID RTMPPCIeLinkCtrlValueRestore( - IN PRTMP_ADAPTER pAd, - IN UCHAR Level) -{ - USHORT PCIePowerSaveLevel, reg16; - USHORT Configuration; - POS_COOKIE pObj; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - return; - - // Check PSControl Configuration - if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) - return TRUE; - - //3090 will not execute the following codes. - // Check interface : If not PCIe interface, return. - -#ifdef RT3090 - if ((pObj->DeviceID == NIC3090_PCIe_DEVICE_ID) - ||(pObj->DeviceID == NIC3091_PCIe_DEVICE_ID) - ||(pObj->DeviceID == NIC3092_PCIe_DEVICE_ID)) - return; -#endif // RT3090 // - DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __FUNCTION__)); - PCIePowerSaveLevel = pAd->PCIePowerSaveLevel; - if ((PCIePowerSaveLevel&0xff) == 0xff) - { - DBGPRINT(RT_DEBUG_TRACE,("return \n")); - return; - } - - if (pObj->parent_pci_dev && (pAd->HostLnkCtrlOffset != 0)) - { - PCI_REG_READ_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, Configuration); - if ((Configuration != 0) && - (Configuration != 0xFFFF)) - { - Configuration &= 0xfefc; - // If call from interface down, restore to orginial setting. - if (Level == RESTORE_CLOSE) - { - Configuration |= pAd->HostLnkCtrlConfiguration; - } - else - Configuration |= 0x0; - PCI_REG_WIRTE_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, Configuration); - DBGPRINT(RT_DEBUG_TRACE, ("Restore PCI host : offset 0x%x = 0x%x\n", pAd->HostLnkCtrlOffset, Configuration)); - } - else - DBGPRINT(RT_DEBUG_ERROR, ("Restore PCI host : PCI_REG_READ_WORD failed (Configuration = 0x%x)\n", Configuration)); - } - - if (pObj->pci_dev && (pAd->RLnkCtrlOffset != 0)) - { - PCI_REG_READ_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset, Configuration); - if ((Configuration != 0) && - (Configuration != 0xFFFF)) - { - Configuration &= 0xfefc; - // If call from interface down, restore to orginial setting. - if (Level == RESTORE_CLOSE) - Configuration |= pAd->RLnkCtrlConfiguration; - else - Configuration |= 0x0; - PCI_REG_WIRTE_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset, Configuration); - DBGPRINT(RT_DEBUG_TRACE, ("Restore Ralink : offset 0x%x = 0x%x\n", pAd->RLnkCtrlOffset, Configuration)); - } - else - DBGPRINT(RT_DEBUG_ERROR, ("Restore Ralink : PCI_REG_READ_WORD failed (Configuration = 0x%x)\n", Configuration)); - } - - DBGPRINT(RT_DEBUG_TRACE,("%s <===\n", __FUNCTION__)); -} - -/* - ======================================================================== - - Routine Description: - - Arguments: - Max : limit Host PCI and Ralink PCIe device's LINK CONTROL field's value. - Because now frequently set our device to mode 1 or mode 3 will cause problem. - - ======================================================================== -*/ -VOID RTMPPCIeLinkCtrlSetting( - IN PRTMP_ADAPTER pAd, - IN USHORT Max) -{ - USHORT PCIePowerSaveLevel, reg16; - USHORT Configuration; - POS_COOKIE pObj; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - return; - - // Check PSControl Configuration - if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) - return TRUE; - - // Check interface : If not PCIe interface, return. - //Block 3090 to enter the following function - -#ifdef RT3090 - if ((pObj->DeviceID == NIC3090_PCIe_DEVICE_ID) - ||(pObj->DeviceID == NIC3091_PCIe_DEVICE_ID) - ||(pObj->DeviceID == NIC3092_PCIe_DEVICE_ID)) - return; -#endif // RT3090 // - if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)) - { - DBGPRINT(RT_DEBUG_INFO, ("RTMPPCIePowerLinkCtrl return on fRTMP_PS_CAN_GO_SLEEP flag\n")); - return; - } - DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__)); - PCIePowerSaveLevel = pAd->PCIePowerSaveLevel; - if ((PCIePowerSaveLevel&0xff) == 0xff) - { - DBGPRINT(RT_DEBUG_TRACE,("return \n")); - return; - } - PCIePowerSaveLevel = PCIePowerSaveLevel>>6; - - // Skip non-exist deice right away - if (pObj->parent_pci_dev && (pAd->HostLnkCtrlOffset != 0)) - { - PCI_REG_READ_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, Configuration); - switch (PCIePowerSaveLevel) - { - case 0: - // Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 00 - Configuration &= 0xfefc; - break; - case 1: - // Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 01 - Configuration &= 0xfefc; - Configuration |= 0x1; - break; - case 2: - // Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 - Configuration &= 0xfefc; - Configuration |= 0x3; - break; - case 3: - // Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 and bit 8 of LinkControl of 2892 to 1 - Configuration &= 0xfefc; - Configuration |= 0x103; - break; - } - PCI_REG_WIRTE_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, Configuration); - DBGPRINT(RT_DEBUG_TRACE, ("Write PCI host offset 0x%x = 0x%x\n", pAd->HostLnkCtrlOffset, Configuration)); - } - - if (pObj->pci_dev && (pAd->RLnkCtrlOffset != 0)) - { - // first 2892 chip not allow to frequently set mode 3. will cause hang problem. - if (PCIePowerSaveLevel > Max) - PCIePowerSaveLevel = Max; - - PCI_REG_READ_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset, Configuration); - switch (PCIePowerSaveLevel) - { - case 0: - // No PCI power safe - // Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 00 . - Configuration &= 0xfefc; - break; - case 1: - // L0 - // Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 01 . - Configuration &= 0xfefc; - Configuration |= 0x1; - break; - case 2: - // L0 and L1 - // Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 - Configuration &= 0xfefc; - Configuration |= 0x3; - break; - case 3: - // L0 , L1 and clock management. - // Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 and bit 8 of LinkControl of 2892 to 1 - Configuration &= 0xfefc; - Configuration |= 0x103; - pAd->bPCIclkOff = TRUE; - break; - } - PCI_REG_WIRTE_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset, Configuration); - DBGPRINT(RT_DEBUG_TRACE, ("Write Ralink device : offset 0x%x = 0x%x\n", pAd->RLnkCtrlOffset, Configuration)); - } - - DBGPRINT(RT_DEBUG_TRACE,("RTMPPCIePowerLinkCtrl <==============\n")); -} -/* - ======================================================================== - - Routine Description: - 1. Write a PCI register for rt30xx power solution 3 - - ======================================================================== -*/ -VOID RTMPrt3xSetPCIePowerLinkCtrl( - IN PRTMP_ADAPTER pAd) -{ - - ULONG HostConfiguration; - ULONG Configuration; - ULONG Vendor; - ULONG offset; - POS_COOKIE pObj; - INT pos; - USHORT reg16; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - DBGPRINT(RT_DEBUG_INFO, ("RTMPrt3xSetPCIePowerLinkCtrl.===> %x\n", pAd->StaCfg.PSControl.word)); - - // Check PSControl Configuration - if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) - return; - RTMPFindHostPCIDev(pAd); - if (pObj->parent_pci_dev) - { - USHORT vendor_id; - // Find PCI-to-PCI Bridge Express Capability Offset - pos = pci_find_capability(pObj->parent_pci_dev, PCI_CAP_ID_EXP); - - if (pos != 0) - { - pAd->HostLnkCtrlOffset = pos + PCI_EXP_LNKCTL; - } - // If configurared to turn on L1. - HostConfiguration = 0; - if (pAd->StaCfg.PSControl.field.rt30xxForceASPMTest == 1) - { - DBGPRINT(RT_DEBUG_TRACE, ("Enter,PSM : Force ASPM \n")); - - // Skip non-exist deice right away - if ((pAd->HostLnkCtrlOffset != 0)) - { - PCI_REG_READ_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, HostConfiguration); - // Prepare Configuration to write to Host - HostConfiguration |= 0x3; - PCI_REG_WIRTE_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, HostConfiguration); - pAd->Rt3xxHostLinkCtrl = HostConfiguration; - // Because in rt30xxForceASPMTest Mode, Force turn on L0s, L1. - // Fix HostConfiguration bit0:1 = 0x3 for later use. - HostConfiguration = 0x3; - DBGPRINT(RT_DEBUG_TRACE, ("PSM : Force ASPM : Host device L1/L0s Value = 0x%x\n", HostConfiguration)); - } - } - else if (pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM == 1) - { - - // Skip non-exist deice right away - if ((pAd->HostLnkCtrlOffset != 0)) - { - PCI_REG_READ_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset, HostConfiguration); - pAd->Rt3xxHostLinkCtrl = HostConfiguration; - HostConfiguration &= 0x3; - DBGPRINT(RT_DEBUG_TRACE, ("PSM : Follow Host ASPM : Host device L1/L0s Value = 0x%x\n", HostConfiguration)); - } - } - } - // Prepare to write Ralink setting. - // Find Ralink PCIe Device's Express Capability Offset - pos = pci_find_capability(pObj->pci_dev, PCI_CAP_ID_EXP); - - if (pos != 0) - { - // Ralink PCIe Device's Link Control Register Offset - pAd->RLnkCtrlOffset = pos + PCI_EXP_LNKCTL; - pci_read_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset, ®16); - Configuration = le2cpu16(reg16); - DBGPRINT(RT_DEBUG_TRACE, ("Read (Ralink PCIe Link Control Register) offset 0x%x = 0x%x\n", - pAd->RLnkCtrlOffset, Configuration)); - Configuration |= 0x100; - if ((pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM == 1) - || (pAd->StaCfg.PSControl.field.rt30xxForceASPMTest == 1)) - { - switch(HostConfiguration) - { - case 0: - Configuration &= 0xffffffc; - break; - case 1: - Configuration &= 0xffffffc; - Configuration |= 0x1; - break; - case 2: - Configuration &= 0xffffffc; - Configuration |= 0x2; - break; - case 3: - Configuration |= 0x3; - break; - } - } - reg16 = cpu2le16(Configuration); - pci_write_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset, reg16); - pAd->Rt3xxRalinkLinkCtrl = Configuration; - DBGPRINT(RT_DEBUG_TRACE, ("PSM :Write Ralink device L1/L0s Value = 0x%x\n", Configuration)); - } - DBGPRINT(RT_DEBUG_INFO,("PSM :RTMPrt3xSetPCIePowerLinkCtrl <==============\n")); - -} - -#endif // CONFIG_STA_SUPPORT // diff --git a/drivers/staging/rt3090/rt3390.h b/drivers/staging/rt3090/rt3390.h deleted file mode 100644 index 412ab3d32ab597c30c9c0384f461ee903a56d3e6..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rt3390.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rt3390.h - - Abstract: - - Revision History: - Who When What - --------- ---------- ---------------------------------------------- - */ - -#ifndef __RT3390_H__ -#define __RT3390_H__ - -#ifdef RT3390 - -#ifndef RTMP_PCI_SUPPORT -#error "For RT3390, you should define the compile flag -DRTMP_PCI_SUPPORT" -#endif - -#ifndef RTMP_MAC_PCI -#error "For RT3390, you should define the compile flag -DRTMP_MAC_PCI" -#endif - -#ifndef RTMP_RF_RW_SUPPORT -#error "For RT3390, you should define the compile flag -DRTMP_RF_RW_SUPPORT" -#endif - -#ifndef RT30xx -#error "For RT3390, you should define the compile flag -DRT30xx" -#endif - -#ifdef CARRIER_DETECTION_SUPPORT -#define TONE_RADAR_DETECT_SUPPORT -#define CARRIER_SENSE_NEW_ALGO -#endif // CARRIER_DETECTION_SUPPORT // - -#define PCIE_PS_SUPPORT - -#include "mac_pci.h" -#include "rt33xx.h" - -// -// Device ID & Vendor ID, these values should match EEPROM value -// -#define NIC3390_PCIe_DEVICE_ID 0x3090 // 1T/1R miniCard -#define NIC3391_PCIe_DEVICE_ID 0x3091 // 1T/2R miniCard -#define NIC3392_PCIe_DEVICE_ID 0x3092 // 2T/2R miniCard - -#endif // RT3390 // - -#endif //__RT3390_H__ // diff --git a/drivers/staging/rt3090/rt_ate.c b/drivers/staging/rt3090/rt_ate.c deleted file mode 100644 index 259aae4116284915b470c0a22fd3632979108d99..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rt_ate.c +++ /dev/null @@ -1,6089 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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 "rt_config.h" - -#ifdef RALINK_ATE - -#ifdef RT30xx -#define ATE_BBP_REG_NUM 168 -UCHAR restore_BBP[ATE_BBP_REG_NUM]={0}; -#endif // RT30xx // - -// 802.11 MAC Header, Type:Data, Length:24bytes -UCHAR TemplateFrame[24] = {0x08,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0x00,0xAA,0xBB,0x12,0x34,0x56,0x00,0x11,0x22,0xAA,0xBB,0xCC,0x00,0x00}; - -extern RTMP_RF_REGS RF2850RegTable[]; -extern UCHAR NUM_OF_2850_CHNL; - -extern FREQUENCY_ITEM FreqItems3020[]; -extern UCHAR NUM_OF_3020_CHNL; - - - - -static CHAR CCKRateTable[] = {0, 1, 2, 3, 8, 9, 10, 11, -1}; /* CCK Mode. */ -static CHAR OFDMRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, -1}; /* OFDM Mode. */ -static CHAR HTMIXRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}; /* HT Mix Mode. */ - -static INT TxDmaBusy( - IN PRTMP_ADAPTER pAd); - -static INT RxDmaBusy( - IN PRTMP_ADAPTER pAd); - -static VOID RtmpDmaEnable( - IN PRTMP_ADAPTER pAd, - IN INT Enable); - -static VOID BbpSoftReset( - IN PRTMP_ADAPTER pAd); - -static VOID RtmpRfIoWrite( - IN PRTMP_ADAPTER pAd); - -static INT ATESetUpFrame( - IN PRTMP_ADAPTER pAd, - IN UINT32 TxIdx); - -static INT ATETxPwrHandler( - IN PRTMP_ADAPTER pAd, - IN char index); - -static INT ATECmdHandler( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -#ifndef RT30xx -static int CheckMCSValid( - IN UCHAR Mode, - IN UCHAR Mcs); -#endif // RT30xx // - -#ifdef RT30xx -static int CheckMCSValid( - IN UCHAR Mode, - IN UCHAR Mcs, - IN BOOLEAN bRT2070); -#endif // RT30xx // - -#ifdef RTMP_MAC_PCI -static VOID ATEWriteTxWI( - IN PRTMP_ADAPTER pAd, - IN PTXWI_STRUC pOutTxWI, - IN BOOLEAN FRAG, - IN BOOLEAN CFACK, - IN BOOLEAN InsTimestamp, - IN BOOLEAN AMPDU, - IN BOOLEAN Ack, - IN BOOLEAN NSeq, // HW new a sequence. - IN UCHAR BASize, - IN UCHAR WCID, - IN ULONG Length, - IN UCHAR PID, - IN UCHAR TID, - IN UCHAR TxRate, - IN UCHAR Txopmode, - IN BOOLEAN CfAck, - IN HTTRANSMIT_SETTING *pTransmit); -#endif // RTMP_MAC_PCI // - - -static VOID SetJapanFilter( - IN PRTMP_ADAPTER pAd); - - -#ifdef RALINK_28xx_QA -static inline INT DO_RACFG_CMD_ATE_START( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_STOP( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_RF_WRITE_ALL( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_E2PROM_READ16( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_E2PROM_WRITE16( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_E2PROM_READ_ALL -( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_E2PROM_WRITE_ALL( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_IO_READ( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_IO_WRITE( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_IO_READ_BULK( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_BBP_READ8( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_BBP_WRITE8( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_BBP_READ_ALL( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_GET_NOISE_LEVEL( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_GET_COUNTER( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_CLEAR_COUNTER( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_TX_START( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_GET_TX_STATUS( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_TX_STOP( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_RX_START( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_RX_STOP( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_RX_STOP( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_START_TX_CARRIER( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_START_TX_CONT( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_START_TX_FRAME( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_SET_BW( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_SET_TX_POWER0( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_SET_TX_POWER1( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_SET_FREQ_OFFSET( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_GET_STATISTICS( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_RESET_COUNTER( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_SEL_TX_ANTENNA( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_SEL_RX_ANTENNA( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_SET_PREAMBLE( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_SET_CHANNEL( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_SET_ADDR1( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_SET_ADDR2( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_SET_ADDR3( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_SET_RATE( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_SET_TX_FRAME_LEN( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_SET_TX_FRAME_COUNT( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_START_RX_FRAME( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_E2PROM_READ_BULK( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_E2PROM_WRITE_BULK( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_IO_WRITE_BULK( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_BBP_READ_BULK( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -static inline INT DO_RACFG_CMD_ATE_BBP_WRITE_BULK( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg -); - -#endif // RALINK_28xx_QA // - - -#ifdef RTMP_MAC_PCI -static INT TxDmaBusy( - IN PRTMP_ADAPTER pAd) -{ - INT result; - WPDMA_GLO_CFG_STRUC GloCfg; - - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA - if (GloCfg.field.TxDMABusy) - result = 1; - else - result = 0; - - return result; -} - - -static INT RxDmaBusy( - IN PRTMP_ADAPTER pAd) -{ - INT result; - WPDMA_GLO_CFG_STRUC GloCfg; - - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA - if (GloCfg.field.RxDMABusy) - result = 1; - else - result = 0; - - return result; -} - - -static VOID RtmpDmaEnable( - IN PRTMP_ADAPTER pAd, - IN INT Enable) -{ - BOOLEAN value; - ULONG WaitCnt; - WPDMA_GLO_CFG_STRUC GloCfg; - - value = Enable > 0 ? 1 : 0; - - // check DMA is in busy mode. - WaitCnt = 0; - - while (TxDmaBusy(pAd) || RxDmaBusy(pAd)) - { - RTMPusecDelay(10); - if (WaitCnt++ > 100) - break; - } - - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA - GloCfg.field.EnableTxDMA = value; - GloCfg.field.EnableRxDMA = value; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); // abort all TX rings - RTMPusecDelay(5000); - - return; -} -#endif // RTMP_MAC_PCI // - - - - -static VOID BbpSoftReset( - IN PRTMP_ADAPTER pAd) -{ - UCHAR BbpData = 0; - - // Soft reset, set BBP R21 bit0=1->0 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpData); - BbpData |= 0x00000001; //set bit0=1 - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData); - - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpData); - BbpData &= ~(0x00000001); //set bit0=0 - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData); - - return; -} - - -static VOID RtmpRfIoWrite( - IN PRTMP_ADAPTER pAd) -{ - // Set RF value 1's set R3[bit2] = [0] - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); - RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); - - RTMPusecDelay(200); - - // Set RF value 2's set R3[bit2] = [1] - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); - RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04)); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); - - RTMPusecDelay(200); - - // Set RF value 3's set R3[bit2] = [0] - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); - RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); - RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); - - return; -} - - -#ifdef RT30xx -static int CheckMCSValid( - UCHAR Mode, - UCHAR Mcs, - BOOLEAN bRT2070) -#endif // RT30xx // -#ifndef RT30xx -static int CheckMCSValid( - IN UCHAR Mode, - IN UCHAR Mcs) -#endif // RT30xx // -{ - INT i; - PCHAR pRateTab; - - switch (Mode) - { - case 0: - pRateTab = CCKRateTable; - break; - case 1: - pRateTab = OFDMRateTable; - break; - case 2: - case 3: -#ifdef RT30xx - if (bRT2070) - pRateTab = OFDMRateTable; - else -#endif // RT30xx // - pRateTab = HTMIXRateTable; - break; - default: - ATEDBGPRINT(RT_DEBUG_ERROR, ("unrecognizable Tx Mode %d\n", Mode)); - return -1; - break; - } - - i = 0; - while (pRateTab[i] != -1) - { - if (pRateTab[i] == Mcs) - return 0; - i++; - } - - return -1; -} - - -static INT ATETxPwrHandler( - IN PRTMP_ADAPTER pAd, - IN char index) -{ - ULONG R; - CHAR TxPower; - UCHAR Bbp94 = 0; - BOOLEAN bPowerReduce = FALSE; -#ifdef RTMP_RF_RW_SUPPORT - UCHAR RFValue; -#endif // RTMP_RF_RW_SUPPORT // -#ifdef RALINK_28xx_QA - if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE)) - { - /* - When QA is used for Tx, pAd->ate.TxPower0/1 and real tx power - are not synchronized. - */ - return 0; - } - else -#endif // RALINK_28xx_QA // - { - TxPower = index == 0 ? pAd->ate.TxPower0 : pAd->ate.TxPower1; - - if (pAd->ate.Channel <= 14) - { - if (TxPower > 31) - { - - // R3, R4 can't large than 31 (0x24), 31 ~ 36 used by BBP 94 - R = 31; - if (TxPower <= 36) - Bbp94 = BBPR94_DEFAULT + (UCHAR)(TxPower - 31); - } - else if (TxPower < 0) - { - - // R3, R4 can't less than 0, -1 ~ -6 used by BBP 94 - R = 0; - if (TxPower >= -6) - Bbp94 = BBPR94_DEFAULT + TxPower; - } - else - { - // 0 ~ 31 - R = (ULONG) TxPower; - Bbp94 = BBPR94_DEFAULT; - } - - ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R=%ld, BBP_R94=%d)\n", __FUNCTION__, TxPower, R, Bbp94)); - } - else /* 5.5 GHz */ - { - if (TxPower > 15) - { - - // R3, R4 can't large than 15 (0x0F) - R = 15; - } - else if (TxPower < 0) - { - - // R3, R4 can't less than 0 - // -1 ~ -7 - ASSERT((TxPower >= -7)); - R = (ULONG)(TxPower + 7); - bPowerReduce = TRUE; - } - else - { - // 0 ~ 15 - R = (ULONG) TxPower; - } - - ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R=%lu)\n", __FUNCTION__, TxPower, R)); - } -//2008/09/10:KH adds to support 3070 ATE TX Power tunning real time<-- -#ifdef RTMP_RF_RW_SUPPORT - if (IS_RT30xx(pAd)) - { - // Set Tx Power - ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R12, (PUCHAR)&RFValue); - RFValue = (RFValue & 0xE0) | TxPower; - ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R12, (UCHAR)RFValue); - ATEDBGPRINT(RT_DEBUG_TRACE, ("3070 or 2070:%s (TxPower=%d, RFValue=%x)\n", __FUNCTION__, TxPower, RFValue)); - } - else -#endif // RTMP_RF_RW_SUPPORT // - { - if (pAd->ate.Channel <= 14) - { - if (index == 0) - { - // shift TX power control to correct RF(R3) register bit position - R = R << 9; - R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); - pAd->LatchRfRegs.R3 = R; - } - else - { - // shift TX power control to correct RF(R4) register bit position - R = R << 6; - R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); - pAd->LatchRfRegs.R4 = R; - } - } - else /* 5.5GHz */ - { - if (bPowerReduce == FALSE) - { - if (index == 0) - { - // shift TX power control to correct RF(R3) register bit position - R = (R << 10) | (1 << 9); - R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); - pAd->LatchRfRegs.R3 = R; - } - else - { - // shift TX power control to correct RF(R4) register bit position - R = (R << 7) | (1 << 6); - R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); - pAd->LatchRfRegs.R4 = R; - } - } - else - { - if (index == 0) - { - // shift TX power control to correct RF(R3) register bit position - R = (R << 10); - R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); - - /* Clear bit 9 of R3 to reduce 7dB. */ - pAd->LatchRfRegs.R3 = (R & (~(1 << 9))); - } - else - { - // shift TX power control to correct RF(R4) register bit position - R = (R << 7); - R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); - - /* Clear bit 6 of R4 to reduce 7dB. */ - pAd->LatchRfRegs.R4 = (R & (~(1 << 6))); - } - } - } - RtmpRfIoWrite(pAd); - } -//2008/09/10:KH adds to support 3070 ATE TX Power tunning real time--> - - return 0; - } -} - - -/* -========================================================================== - Description: - Set ATE operation mode to - 0. ATESTART = Start ATE Mode - 1. ATESTOP = Stop ATE Mode - 2. TXCONT = Continuous Transmit - 3. TXCARR = Transmit Carrier - 4. TXFRAME = Transmit Frames - 5. RXFRAME = Receive Frames -#ifdef RALINK_28xx_QA - 6. TXSTOP = Stop Any Type of Transmition - 7. RXSTOP = Stop Receiving Frames -#endif // RALINK_28xx_QA // - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -#ifdef RTMP_MAC_PCI -static INT ATECmdHandler( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UINT32 Value = 0; - UCHAR BbpData; - UINT32 MacData = 0; - PTXD_STRUC pTxD; - INT index; - UINT i = 0, atemode = 0; - PRXD_STRUC pRxD; - PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; -#ifdef RT_BIG_ENDIAN - PTXD_STRUC pDestTxD; - TXD_STRUC TxD; -#endif - - ATEDBGPRINT(RT_DEBUG_TRACE, ("===> ATECmdHandler()\n")); - - ATEAsicSwitchChannel(pAd); - - /* empty function */ - AsicLockChannel(pAd, pAd->ate.Channel); - - RTMPusecDelay(5000); - - // read MAC_SYS_CTRL and backup MAC_SYS_CTRL value. - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); - - // Default value in BBP R22 is 0x0. - BbpData = 0; - - // clean bit4 to stop continuous Tx production test. - MacData &= 0xFFFFFFEF; - - // Enter ATE mode and set Tx/Rx Idle - if (!strcmp(arg, "ATESTART")) - { - ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: ATESTART\n")); - -#if defined(LINUX) || defined(VXWORKS) - // check if we have removed the firmware - if (!(ATE_ON(pAd))) - { - NICEraseFirmware(pAd); - } -#endif // defined(LINUX) || defined(VXWORKS) // - - atemode = pAd->ate.Mode; - pAd->ate.Mode = ATE_START; - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); - - if (atemode == ATE_TXCARR) - { - // No Carrier Test set BBP R22 bit7=0, bit6=0, bit[5~0]=0x0 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); - BbpData &= 0xFFFFFF00; // clear bit7, bit6, bit[5~0] - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); - } - else if (atemode == ATE_TXCARRSUPP) - { - // No Cont. TX set BBP R22 bit7=0 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); - BbpData &= ~(1 << 7); // set bit7=0 - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); - - // No Carrier Suppression set BBP R24 bit0=0 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R24, &BbpData); - BbpData &= 0xFFFFFFFE; // clear bit0 - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, BbpData); - } - - /* - We should free some resource which was allocated - when ATE_TXFRAME , ATE_STOP, and ATE_TXCONT. - */ - else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP)) - { - PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; - - if (atemode == ATE_TXCONT) - { - // No Cont. TX set BBP R22 bit7=0 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); - BbpData &= ~(1 << 7); // set bit7=0 - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); - } - - // Abort Tx, Rx DMA. - RtmpDmaEnable(pAd, 0); - for (i=0; iTxRing[QID_AC_BE].Cell[i].AllocVa; -#else - pDestTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa; - TxD = *pDestTxD; - pTxD = &TxD; - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); -#endif - pTxD->DMADONE = 0; - pPacket = pTxRing->Cell[i].pNdisPacket; - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - - // Always assign pNdisPacket as NULL after clear - pTxRing->Cell[i].pNdisPacket = NULL; - - pPacket = pTxRing->Cell[i].pNextNdisPacket; - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - - // Always assign pNextNdisPacket as NULL after clear - pTxRing->Cell[i].pNextNdisPacket = NULL; -#ifdef RT_BIG_ENDIAN - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); -#endif - } - - // Start Tx, RX DMA - RtmpDmaEnable(pAd, 1); - } - - // reset Rx statistics. - pAd->ate.LastSNR0 = 0; - pAd->ate.LastSNR1 = 0; - pAd->ate.LastRssi0 = 0; - pAd->ate.LastRssi1 = 0; - pAd->ate.LastRssi2 = 0; - pAd->ate.AvgRssi0 = 0; - pAd->ate.AvgRssi1 = 0; - pAd->ate.AvgRssi2 = 0; - pAd->ate.AvgRssi0X8 = 0; - pAd->ate.AvgRssi1X8 = 0; - pAd->ate.AvgRssi2X8 = 0; - pAd->ate.NumOfAvgRssiSample = 0; - -#ifdef RALINK_28xx_QA - // Tx frame - pAd->ate.bQATxStart = FALSE; - pAd->ate.bQARxStart = FALSE; - pAd->ate.seq = 0; - - // counters - pAd->ate.U2M = 0; - pAd->ate.OtherData = 0; - pAd->ate.Beacon = 0; - pAd->ate.OtherCount = 0; - pAd->ate.TxAc0 = 0; - pAd->ate.TxAc1 = 0; - pAd->ate.TxAc2 = 0; - pAd->ate.TxAc3 = 0; - /*pAd->ate.TxHCCA = 0;*/ - pAd->ate.TxMgmt = 0; - pAd->ate.RSSI0 = 0; - pAd->ate.RSSI1 = 0; - pAd->ate.RSSI2 = 0; - pAd->ate.SNR0 = 0; - pAd->ate.SNR1 = 0; - - // control - pAd->ate.TxDoneCount = 0; - // TxStatus : 0 --> task is idle, 1 --> task is running - pAd->ate.TxStatus = 0; -#endif // RALINK_28xx_QA // - - // Soft reset BBP. - BbpSoftReset(pAd); - - -#ifdef CONFIG_STA_SUPPORT - /* LinkDown() has "AsicDisableSync();" and "RTMP_BBP_IO_R/W8_BY_REG_ID();" inside. */ -// LinkDown(pAd, FALSE); -// AsicEnableBssSync(pAd); - -#if defined(LINUX) || defined(VXWORKS) - RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); -#endif // defined(LINUX) || defined(VXWORKS) // - - /* - If we skip "LinkDown()", we should disable protection - to prevent from sending out RTS or CTS-to-self. - */ - ATEDisableAsicProtect(pAd); - RTMPStationStop(pAd); -#endif // CONFIG_STA_SUPPORT // - - /* Disable Tx */ - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value &= ~(1 << 2); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - - /* Disable Rx */ - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value &= ~(1 << 3); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - } - else if (!strcmp(arg, "ATESTOP")) - { - ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: ATESTOP\n")); - - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); - - // recover the MAC_SYS_CTRL register back - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); - - // disable Tx, Rx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value &= (0xfffffff3); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - - // abort Tx, RX DMA - RtmpDmaEnable(pAd, 0); - -#ifdef LINUX - pAd->ate.bFWLoading = TRUE; - - Status = NICLoadFirmware(pAd); - - if (Status != NDIS_STATUS_SUCCESS) - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("NICLoadFirmware failed, Status[=0x%08x]\n", Status)); - return FALSE; - } -#endif // LINUX // - pAd->ate.Mode = ATE_STOP; - - /* - Even the firmware has been loaded, - we still could use ATE_BBP_IO_READ8_BY_REG_ID(). - But this is not suggested. - */ - BbpSoftReset(pAd); - - RTMP_ASIC_INTERRUPT_DISABLE(pAd); - - NICInitializeAdapter(pAd, TRUE); - - /* - Reinitialize Rx Ring before Rx DMA is enabled. - >>>RxCoherent<<< was gone ! - */ - for (index = 0; index < RX_RING_SIZE; index++) - { - pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa; - pRxD->DDONE = 0; - } - - // We should read EEPROM for all cases. - NICReadEEPROMParameters(pAd, NULL); - NICInitAsicFromEEPROM(pAd); - - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - - /* empty function */ - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - - /* clear garbage interrupts */ - RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, 0xffffffff); - /* Enable Interrupt */ - RTMP_ASIC_INTERRUPT_ENABLE(pAd); - - /* restore RX_FILTR_CFG */ - -#ifdef CONFIG_STA_SUPPORT - /* restore RX_FILTR_CFG due to that QA maybe set it to 0x3 */ - RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); -#endif // CONFIG_STA_SUPPORT // - - // Enable Tx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value |= (1 << 2); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - - // Enable Tx, Rx DMA. - RtmpDmaEnable(pAd, 1); - - // Enable Rx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value |= (1 << 3); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - - -#ifdef CONFIG_STA_SUPPORT - RTMPStationStart(pAd); -#endif // CONFIG_STA_SUPPORT // - -#if defined(LINUX) || defined(VXWORKS) - RTMP_OS_NETDEV_START_QUEUE(pAd->net_dev); -#endif // defined(LINUX) || defined(VXWORKS) // - } - else if (!strcmp(arg, "TXCARR")) - { - ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXCARR\n")); - pAd->ate.Mode = ATE_TXCARR; - - // QA has done the following steps if it is used. - if (pAd->ate.bQATxStart == FALSE) - { - // Soft reset BBP. - BbpSoftReset(pAd); - - // Carrier Test set BBP R22 bit7=1, bit6=1, bit[5~0]=0x01 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); - BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0] - BbpData |= 0x000000C1; //set bit7=1, bit6=1, bit[5~0]=0x01 - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); - - // set MAC_SYS_CTRL(0x1004) Continuous Tx Production Test (bit4) = 1 - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value = Value | 0x00000010; - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - } - } - else if (!strcmp(arg, "TXCONT")) - { - if (pAd->ate.bQATxStart == TRUE) - { - /* - set MAC_SYS_CTRL(0x1004) bit4(Continuous Tx Production Test) - and bit2(MAC TX enable) back to zero. - */ - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); - MacData &= 0xFFFFFFEB; - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); - - // set BBP R22 bit7=0 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); - BbpData &= 0xFFFFFF7F; //set bit7=0 - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); - } - - /* - for TxCont mode. - Step 1: Send 50 packets first then wait for a moment. - Step 2: Send more 50 packet then start continue mode. - */ - ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXCONT\n")); - - // Step 1: send 50 packets first. - pAd->ate.Mode = ATE_TXCONT; - pAd->ate.TxCount = 50; - - /* Do it after Tx/Rx DMA is aborted. */ -// pAd->ate.TxDoneCount = 0; - - // Soft reset BBP. - BbpSoftReset(pAd); - - // Abort Tx, RX DMA. - RtmpDmaEnable(pAd, 0); - - // Fix can't smooth kick - { - RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * 0x10, &pTxRing->TxDmaIdx); - pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; - pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; - RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * 0x10, pTxRing->TxCpuIdx); - } - - pAd->ate.TxDoneCount = 0; - - /* Only needed if we have to send some normal frames. */ - SetJapanFilter(pAd); - - for (i = 0; (i < TX_RING_SIZE-1) && (i < pAd->ate.TxCount); i++) - { - PNDIS_PACKET pPacket; - UINT32 TxIdx = pTxRing->TxCpuIdx; - -#ifndef RT_BIG_ENDIAN - pTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; -#else - pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; - TxD = *pDestTxD; - pTxD = &TxD; - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); -#endif - // Clean current cell. - pPacket = pTxRing->Cell[TxIdx].pNdisPacket; - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - - // Always assign pNdisPacket as NULL after clear - pTxRing->Cell[TxIdx].pNdisPacket = NULL; - - pPacket = pTxRing->Cell[TxIdx].pNextNdisPacket; - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - - // Always assign pNextNdisPacket as NULL after clear - pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; - -#ifdef RT_BIG_ENDIAN - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); -#endif - - if (ATESetUpFrame(pAd, TxIdx) != 0) - break; - - INC_RING_INDEX(pTxRing->TxCpuIdx, TX_RING_SIZE); - } - - // Setup frame format. - ATESetUpFrame(pAd, pTxRing->TxCpuIdx); - - // Start Tx, RX DMA. - RtmpDmaEnable(pAd, 1); - - // Enable Tx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value |= (1 << 2); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - - // Disable Rx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value &= ~(1 << 3); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - -#ifdef RALINK_28xx_QA - if (pAd->ate.bQATxStart == TRUE) - { - pAd->ate.TxStatus = 1; - } -#endif // RALINK_28xx_QA // - - // kick Tx-Ring - RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * RINGREG_DIFF, pAd->TxRing[QID_AC_BE].TxCpuIdx); - - RTMPusecDelay(5000); - - - // Step 2: send more 50 packets then start continue mode. - // Abort Tx, RX DMA. - RtmpDmaEnable(pAd, 0); - - // Cont. TX set BBP R22 bit7=1 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); - BbpData |= 0x00000080; //set bit7=1 - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); - - pAd->ate.TxCount = 50; - - // Fix can't smooth kick - { - RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * 0x10, &pTxRing->TxDmaIdx); - pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; - pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; - RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * 0x10, pTxRing->TxCpuIdx); - } - - pAd->ate.TxDoneCount = 0; - - SetJapanFilter(pAd); - - for (i = 0; (i < TX_RING_SIZE-1) && (i < pAd->ate.TxCount); i++) - { - PNDIS_PACKET pPacket; - UINT32 TxIdx = pTxRing->TxCpuIdx; - -#ifndef RT_BIG_ENDIAN - pTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; -#else - pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; - TxD = *pDestTxD; - pTxD = &TxD; - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); -#endif - // clean current cell. - pPacket = pTxRing->Cell[TxIdx].pNdisPacket; - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - - // Always assign pNdisPacket as NULL after clear - pTxRing->Cell[TxIdx].pNdisPacket = NULL; - - pPacket = pTxRing->Cell[TxIdx].pNextNdisPacket; - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - - // Always assign pNextNdisPacket as NULL after clear - pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; - -#ifdef RT_BIG_ENDIAN - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); -#endif - - if (ATESetUpFrame(pAd, TxIdx) != 0) - break; - - INC_RING_INDEX(pTxRing->TxCpuIdx, TX_RING_SIZE); - } - - ATESetUpFrame(pAd, pTxRing->TxCpuIdx); - - // Start Tx, RX DMA. - RtmpDmaEnable(pAd, 1); - - // Enable Tx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value |= (1 << 2); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - - // Disable Rx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value &= ~(1 << 3); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - -#ifdef RALINK_28xx_QA - if (pAd->ate.bQATxStart == TRUE) - { - pAd->ate.TxStatus = 1; - } -#endif // RALINK_28xx_QA // - - // kick Tx-Ring. - RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * RINGREG_DIFF, pAd->TxRing[QID_AC_BE].TxCpuIdx); - - RTMPusecDelay(500); - - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); - MacData |= 0x00000010; - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); - } - else if (!strcmp(arg, "TXFRAME")) - { - ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXFRAME(Count=%d)\n", pAd->ate.TxCount)); - pAd->ate.Mode |= ATE_TXFRAME; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); - - // Soft reset BBP. - BbpSoftReset(pAd); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); - - // Abort Tx, RX DMA. - RtmpDmaEnable(pAd, 0); - - // Fix can't smooth kick - { - RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * 0x10, &pTxRing->TxDmaIdx); - pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; - pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; - RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * 0x10, pTxRing->TxCpuIdx); - } - - pAd->ate.TxDoneCount = 0; - - SetJapanFilter(pAd); - - for (i = 0; (i < TX_RING_SIZE-1) && (i < pAd->ate.TxCount); i++) - { - PNDIS_PACKET pPacket; - UINT32 TxIdx = pTxRing->TxCpuIdx; - -#ifndef RT_BIG_ENDIAN - pTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; -#else - pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; - TxD = *pDestTxD; - pTxD = &TxD; - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); -#endif - // Clean current cell. - pPacket = pTxRing->Cell[TxIdx].pNdisPacket; - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - - // Always assign pNdisPacket as NULL after clear - pTxRing->Cell[TxIdx].pNdisPacket = NULL; - - pPacket = pTxRing->Cell[TxIdx].pNextNdisPacket; - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - - // Always assign pNextNdisPacket as NULL after clear - pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; - -#ifdef RT_BIG_ENDIAN - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); -#endif - - if (ATESetUpFrame(pAd, TxIdx) != 0) - break; - - INC_RING_INDEX(pTxRing->TxCpuIdx, TX_RING_SIZE); - - } - - ATESetUpFrame(pAd, pTxRing->TxCpuIdx); - - // Start Tx, Rx DMA. - RtmpDmaEnable(pAd, 1); - - // Enable Tx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value |= (1 << 2); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - -#ifdef RALINK_28xx_QA - // add this for LoopBack mode - if (pAd->ate.bQARxStart == FALSE) - { - // Disable Rx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value &= ~(1 << 3); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - } - - if (pAd->ate.bQATxStart == TRUE) - { - pAd->ate.TxStatus = 1; - } -#else - // Disable Rx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value &= ~(1 << 3); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); -#endif // RALINK_28xx_QA // - - RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * RINGREG_DIFF, &pAd->TxRing[QID_AC_BE].TxDmaIdx); - // kick Tx-Ring. - RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * RINGREG_DIFF, pAd->TxRing[QID_AC_BE].TxCpuIdx); - - pAd->RalinkCounters.KickTxCount++; - } -#ifdef RALINK_28xx_QA - else if (!strcmp(arg, "TXSTOP")) - { - ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXSTOP\n")); - atemode = pAd->ate.Mode; - pAd->ate.Mode &= ATE_TXSTOP; - pAd->ate.bQATxStart = FALSE; -// pAd->ate.TxDoneCount = pAd->ate.TxCount; - - if (atemode == ATE_TXCARR) - { - // No Carrier Test set BBP R22 bit7=0, bit6=0, bit[5~0]=0x0 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); - BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0] - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); - } - else if (atemode == ATE_TXCARRSUPP) - { - // No Cont. TX set BBP R22 bit7=0 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); - BbpData &= ~(1 << 7); //set bit7=0 - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); - - // No Carrier Suppression set BBP R24 bit0=0 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R24, &BbpData); - BbpData &= 0xFFFFFFFE; //clear bit0 - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, BbpData); - } - - /* - We should free some resource which was allocated - when ATE_TXFRAME, ATE_STOP, and ATE_TXCONT. - */ - else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP)) - { - PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; - - if (atemode == ATE_TXCONT) - { - // No Cont. TX set BBP R22 bit7=0 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); - BbpData &= ~(1 << 7); //set bit7=0 - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); - } - - // Abort Tx, Rx DMA. - RtmpDmaEnable(pAd, 0); - - for (i=0; iTxRing[QID_AC_BE].Cell[i].AllocVa; -#else - pDestTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa; - TxD = *pDestTxD; - pTxD = &TxD; - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); -#endif - pTxD->DMADONE = 0; - pPacket = pTxRing->Cell[i].pNdisPacket; - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - - // Always assign pNdisPacket as NULL after clear - pTxRing->Cell[i].pNdisPacket = NULL; - - pPacket = pTxRing->Cell[i].pNextNdisPacket; - - if (pPacket) - { - PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); - } - - // Always assign pNextNdisPacket as NULL after clear - pTxRing->Cell[i].pNextNdisPacket = NULL; -#ifdef RT_BIG_ENDIAN - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); -#endif - } - // Enable Tx, Rx DMA - RtmpDmaEnable(pAd, 1); - - } - - // TxStatus : 0 --> task is idle, 1 --> task is running - pAd->ate.TxStatus = 0; - - // Soft reset BBP. - BbpSoftReset(pAd); - - // Disable Tx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value &= ~(1 << 2); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - } - else if (!strcmp(arg, "RXSTOP")) - { - ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: RXSTOP\n")); - atemode = pAd->ate.Mode; - pAd->ate.Mode &= ATE_RXSTOP; - pAd->ate.bQARxStart = FALSE; -// pAd->ate.TxDoneCount = pAd->ate.TxCount; - - if (atemode == ATE_TXCARR) - { - ; - } - else if (atemode == ATE_TXCARRSUPP) - { - ; - } - - /* - We should free some resource which was allocated - when ATE_TXFRAME, ATE_STOP, and ATE_TXCONT. - */ - else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP)) - { - if (atemode == ATE_TXCONT) - { - ; - } - } - - // Soft reset BBP. - BbpSoftReset(pAd); - - // Disable Rx - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value &= ~(1 << 3); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - } -#endif // RALINK_28xx_QA // - else if (!strcmp(arg, "RXFRAME")) - { - ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: RXFRAME\n")); - - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); - - pAd->ate.Mode |= ATE_RXFRAME; - - // Disable Tx of MAC block. - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value &= ~(1 << 2); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - - // Enable Rx of MAC block. - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value |= (1 << 3); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - } - else - { - ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: Invalid arg!\n")); - return FALSE; - } - RTMPusecDelay(5000); - - ATEDBGPRINT(RT_DEBUG_TRACE, ("<=== ATECmdHandler()\n")); - - return TRUE; -} -/*=======================End of RTMP_MAC_PCI =======================*/ -#endif // RTMP_MAC_PCI // - - - - -INT Set_ATE_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - if (ATECmdHandler(pAd, arg)) - { - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_Proc Success\n")); - - - return TRUE; - } - else - { - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_Proc Failed\n")); - return FALSE; - } -} - - -/* -========================================================================== - Description: - Set ATE ADDR1=DA for TxFrame(AP : To DS = 0 ; From DS = 1) - or - Set ATE ADDR3=DA for TxFrame(STA : To DS = 1 ; From DS = 0) - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_DA_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - PSTRING value; - INT i; - - // Mac address acceptable format 01:02:03:04:05:06 length 17 - if (strlen(arg) != 17) - return FALSE; - - for (i = 0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) - { - /* sanity check */ - if ((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1)))) - { - return FALSE; - } - -#ifdef CONFIG_STA_SUPPORT - AtoH(value, &pAd->ate.Addr3[i++], 1); -#endif // CONFIG_STA_SUPPORT // - } - - /* sanity check */ - if (i != 6) - { - return FALSE; - } - -#ifdef CONFIG_STA_SUPPORT - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_DA_Proc (DA = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr3[0], - pAd->ate.Addr3[1], pAd->ate.Addr3[2], pAd->ate.Addr3[3], pAd->ate.Addr3[4], pAd->ate.Addr3[5])); -#endif // CONFIG_STA_SUPPORT // - - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_DA_Proc Success\n")); - - return TRUE; -} - - -/* -========================================================================== - Description: - Set ATE ADDR3=SA for TxFrame(AP : To DS = 0 ; From DS = 1) - or - Set ATE ADDR2=SA for TxFrame(STA : To DS = 1 ; From DS = 0) - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_SA_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - PSTRING value; - INT i; - - // Mac address acceptable format 01:02:03:04:05:06 length 17 - if (strlen(arg) != 17) - return FALSE; - - for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) - { - /* sanity check */ - if ((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1)))) - { - return FALSE; - } - -#ifdef CONFIG_STA_SUPPORT - AtoH(value, &pAd->ate.Addr2[i++], 1); -#endif // CONFIG_STA_SUPPORT // - } - - /* sanity check */ - if (i != 6) - { - return FALSE; - } - -#ifdef CONFIG_STA_SUPPORT - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_SA_Proc (SA = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr2[0], - pAd->ate.Addr2[1], pAd->ate.Addr2[2], pAd->ate.Addr2[3], pAd->ate.Addr2[4], pAd->ate.Addr2[5])); -#endif // CONFIG_STA_SUPPORT // - - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_SA_Proc Success\n")); - - return TRUE; -} - - -/* -========================================================================== - Description: - Set ATE ADDR2=BSSID for TxFrame(AP : To DS = 0 ; From DS = 1) - or - Set ATE ADDR1=BSSID for TxFrame(STA : To DS = 1 ; From DS = 0) - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_BSSID_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - PSTRING value; - INT i; - - // Mac address acceptable format 01:02:03:04:05:06 length 17 - if (strlen(arg) != 17) - return FALSE; - - for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) - { - /* sanity check */ - if ((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1)))) - { - return FALSE; - } - -#ifdef CONFIG_STA_SUPPORT - AtoH(value, &pAd->ate.Addr1[i++], 1); -#endif // CONFIG_STA_SUPPORT // - } - - /* sanity check */ - if(i != 6) - { - return FALSE; - } - -#ifdef CONFIG_STA_SUPPORT - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_BSSID_Proc (BSSID = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr1[0], - pAd->ate.Addr1[1], pAd->ate.Addr1[2], pAd->ate.Addr1[3], pAd->ate.Addr1[4], pAd->ate.Addr1[5])); -#endif // CONFIG_STA_SUPPORT // - - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_BSSID_Proc Success\n")); - - return TRUE; -} - - -/* -========================================================================== - Description: - Set ATE Tx Channel - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_CHANNEL_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UCHAR channel; - - channel = simple_strtol(arg, 0, 10); - - // to allow A band channel : ((channel < 1) || (channel > 14)) - if ((channel < 1) || (channel > 216)) - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_CHANNEL_Proc::Out of range, it should be in range of 1~14.\n")); - return FALSE; - } - pAd->ate.Channel = channel; - - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_CHANNEL_Proc (ATE Channel = %d)\n", pAd->ate.Channel)); - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_CHANNEL_Proc Success\n")); - - - return TRUE; -} - - -/* -========================================================================== - Description: - Set ATE Tx Power0 - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_TX_POWER0_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - CHAR TxPower; - - TxPower = simple_strtol(arg, 0, 10); - - if (pAd->ate.Channel <= 14) - { - if ((TxPower > 31) || (TxPower < 0)) - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER0_Proc::Out of range (Value=%d)\n", TxPower)); - return FALSE; - } - } - else/* 5.5 GHz */ - { - if ((TxPower > 15) || (TxPower < -7)) - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER0_Proc::Out of range (Value=%d)\n", TxPower)); - return FALSE; - } - } - - pAd->ate.TxPower0 = TxPower; - ATETxPwrHandler(pAd, 0); - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_POWER0_Proc Success\n")); - - - return TRUE; -} - - -/* -========================================================================== - Description: - Set ATE Tx Power1 - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_TX_POWER1_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - CHAR TxPower; - - TxPower = simple_strtol(arg, 0, 10); - - if (pAd->ate.Channel <= 14) - { - if ((TxPower > 31) || (TxPower < 0)) - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER1_Proc::Out of range (Value=%d)\n", TxPower)); - return FALSE; - } - } - else - { - if ((TxPower > 15) || (TxPower < -7)) - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER1_Proc::Out of range (Value=%d)\n", TxPower)); - return FALSE; - } - } - - pAd->ate.TxPower1 = TxPower; - ATETxPwrHandler(pAd, 1); - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_POWER1_Proc Success\n")); - - - return TRUE; -} - - -/* -========================================================================== - Description: - Set ATE Tx Antenna - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_TX_Antenna_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - CHAR value; - - value = simple_strtol(arg, 0, 10); - - if ((value > 2) || (value < 0)) - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_Antenna_Proc::Out of range (Value=%d)\n", value)); - return FALSE; - } - - pAd->ate.TxAntennaSel = value; - - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_Antenna_Proc (Antenna = %d)\n", pAd->ate.TxAntennaSel)); - ATEDBGPRINT(RT_DEBUG_TRACE,("Ralink: Set_ATE_TX_Antenna_Proc Success\n")); - - // calibration power unbalance issues, merged from Arch Team - ATEAsicSwitchChannel(pAd); - - - return TRUE; -} - - -/* -========================================================================== - Description: - Set ATE Rx Antenna - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_RX_Antenna_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - CHAR value; - - value = simple_strtol(arg, 0, 10); - - if ((value > 3) || (value < 0)) - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_RX_Antenna_Proc::Out of range (Value=%d)\n", value)); - return FALSE; - } - - pAd->ate.RxAntennaSel = value; - - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_RX_Antenna_Proc (Antenna = %d)\n", pAd->ate.RxAntennaSel)); - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_RX_Antenna_Proc Success\n")); - - // calibration power unbalance issues, merged from Arch Team - ATEAsicSwitchChannel(pAd); - - - return TRUE; -} - - -/* -========================================================================== - Description: - Set ATE RF frequence offset - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_TX_FREQOFFSET_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UCHAR RFFreqOffset = 0; - ULONG R4 = 0; - - RFFreqOffset = simple_strtol(arg, 0, 10); -#ifndef RTMP_RF_RW_SUPPORT - if (RFFreqOffset >= 64) -#endif // RTMP_RF_RW_SUPPORT // - /* RT35xx ATE will reuse this code segment. */ -#ifdef RTMP_RF_RW_SUPPORT -//2008/08/06: KH modified the limit of offset value from 65 to 95(0x5F) - if (RFFreqOffset >= 95) -#endif // RTMP_RF_RW_SUPPORT // - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_FREQOFFSET_Proc::Out of range, it should be in range of 0~63.\n")); - return FALSE; - } - - pAd->ate.RFFreqOffset = RFFreqOffset; -#ifdef RTMP_RF_RW_SUPPORT - if (IS_RT30xx(pAd) || IS_RT3572(pAd)) - { - // Set RF offset - UCHAR RFValue; - ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R23, (PUCHAR)&RFValue); -//2008/08/06: KH modified "pAd->RFFreqOffset" to "pAd->ate.RFFreqOffset" - RFValue = ((RFValue & 0x80) | pAd->ate.RFFreqOffset); - ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R23, (UCHAR)RFValue); - } - else -#endif // RTMP_RF_RW_SUPPORT // - { - // RT28xx - // shift TX power control to correct RF register bit position - R4 = pAd->ate.RFFreqOffset << 15; - R4 |= (pAd->LatchRfRegs.R4 & ((~0x001f8000))); - pAd->LatchRfRegs.R4 = R4; - - RtmpRfIoWrite(pAd); - } - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_FREQOFFSET_Proc (RFFreqOffset = %d)\n", pAd->ate.RFFreqOffset)); - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_FREQOFFSET_Proc Success\n")); - - - return TRUE; -} - - -/* -========================================================================== - Description: - Set ATE RF BW - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_TX_BW_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - INT i; - UCHAR value = 0; - UCHAR BBPCurrentBW; - - BBPCurrentBW = simple_strtol(arg, 0, 10); - - if ((BBPCurrentBW == 0) -#ifdef RT30xx - || IS_RT2070(pAd) -#endif // RT30xx // - ) - { - pAd->ate.TxWI.BW = BW_20; - } - else - { - pAd->ate.TxWI.BW = BW_40; - } - - /* RT35xx ATE will reuse this code segment. */ - // Fix the error spectrum of CCK-40MHZ - // Turn on BBP 20MHz mode by request here. - if ((pAd->ate.TxWI.PHYMODE == MODE_CCK) && (pAd->ate.TxWI.BW == BW_40)) - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_BW_Proc!! Warning!! CCK only supports 20MHZ!!\nBandwidth switch to 20\n")); - pAd->ate.TxWI.BW = BW_20; - } - - if (pAd->ate.TxWI.BW == BW_20) - { - if (pAd->ate.Channel <= 14) - { - for (i=0; i<5; i++) - { - if (pAd->Tx20MPwrCfgGBand[i] != 0xffffffff) - { - RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx20MPwrCfgGBand[i]); - RTMPusecDelay(5000); - } - } - } - else - { - for (i=0; i<5; i++) - { - if (pAd->Tx20MPwrCfgABand[i] != 0xffffffff) - { - RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx20MPwrCfgABand[i]); - RTMPusecDelay(5000); - } - } - } - - // Set BBP R4 bit[4:3]=0:0 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); - value &= (~0x18); - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); - - - // Set BBP R66=0x3C - value = 0x3C; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); - - // Set BBP R68=0x0B - // to improve Rx sensitivity. - value = 0x0B; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); - // Set BBP R69=0x16 - value = 0x16; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); - // Set BBP R70=0x08 - value = 0x08; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); - // Set BBP R73=0x11 - value = 0x11; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); - - /* - If Channel=14, Bandwidth=20M and Mode=CCK, Set BBP R4 bit5=1 - (to set Japan filter coefficients). - This segment of code will only works when ATETXMODE and ATECHANNEL - were set to MODE_CCK and 14 respectively before ATETXBW is set to 0. - */ - if (pAd->ate.Channel == 14) - { - INT TxMode = pAd->ate.TxWI.PHYMODE; - - if (TxMode == MODE_CCK) - { - // when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); - value |= 0x20; //set bit5=1 - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); - } - } - -#ifdef RT30xx - // set BW = 20 MHz - if (IS_RT30xx(pAd)) - ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR) pAd->Mlme.CaliBW20RfR24); - else -#endif // RT30xx // - // set BW = 20 MHz - { - pAd->LatchRfRegs.R4 &= ~0x00200000; - RtmpRfIoWrite(pAd); - } - - } - // If bandwidth = 40M, set RF Reg4 bit 21 = 0. - else if (pAd->ate.TxWI.BW == BW_40) - { - if (pAd->ate.Channel <= 14) - { - for (i=0; i<5; i++) - { - if (pAd->Tx40MPwrCfgGBand[i] != 0xffffffff) - { - RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx40MPwrCfgGBand[i]); - RTMPusecDelay(5000); - } - } - } - else - { - for (i=0; i<5; i++) - { - if (pAd->Tx40MPwrCfgABand[i] != 0xffffffff) - { - RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx40MPwrCfgABand[i]); - RTMPusecDelay(5000); - } - } -#ifdef DOT11_N_SUPPORT - if ((pAd->ate.TxWI.PHYMODE >= MODE_HTMIX) && (pAd->ate.TxWI.MCS == 7)) - { - value = 0x28; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, value); - } -#endif // DOT11_N_SUPPORT // - } - - // Set BBP R4 bit[4:3]=1:0 - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); - value &= (~0x18); - value |= 0x10; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); - - - // Set BBP R66=0x3C - value = 0x3C; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); - - // Set BBP R68=0x0C - // to improve Rx sensitivity - value = 0x0C; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); - // Set BBP R69=0x1A - value = 0x1A; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); - // Set BBP R70=0x0A - value = 0x0A; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); - // Set BBP R73=0x16 - value = 0x16; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); - - // If bandwidth = 40M, set RF Reg4 bit 21 = 1. -#ifdef RT30xx - // set BW = 40 MHz - if(IS_RT30xx(pAd)) - ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR) pAd->Mlme.CaliBW40RfR24); - else -#endif // RT30xx // - // set BW = 40 MHz - { - pAd->LatchRfRegs.R4 |= 0x00200000; - RtmpRfIoWrite(pAd); - } - } - - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_BW_Proc (BBPCurrentBW = %d)\n", pAd->ate.TxWI.BW)); - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_BW_Proc Success\n")); - - - return TRUE; -} - - -/* -========================================================================== - Description: - Set ATE Tx frame length - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_TX_LENGTH_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - pAd->ate.TxLength = simple_strtol(arg, 0, 10); - - if ((pAd->ate.TxLength < 24) || (pAd->ate.TxLength > (MAX_FRAME_SIZE - 34/* == 2312 */))) - { - pAd->ate.TxLength = (MAX_FRAME_SIZE - 34/* == 2312 */); - ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_LENGTH_Proc::Out of range, it should be in range of 24~%d.\n", (MAX_FRAME_SIZE - 34/* == 2312 */))); - return FALSE; - } - - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_LENGTH_Proc (TxLength = %d)\n", pAd->ate.TxLength)); - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_LENGTH_Proc Success\n")); - - - return TRUE; -} - - -/* -========================================================================== - Description: - Set ATE Tx frame count - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_TX_COUNT_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - pAd->ate.TxCount = simple_strtol(arg, 0, 10); - - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_COUNT_Proc (TxCount = %d)\n", pAd->ate.TxCount)); - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_COUNT_Proc Success\n")); - - - return TRUE; -} - - -/* -========================================================================== - Description: - Set ATE Tx frame MCS - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_TX_MCS_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UCHAR MCS; - INT result; - - MCS = simple_strtol(arg, 0, 10); -#ifndef RT30xx - result = CheckMCSValid(pAd->ate.TxWI.PHYMODE, MCS); -#endif // RT30xx // - - /* RT35xx ATE will reuse this code segment. */ -#ifdef RT30xx - result = CheckMCSValid(pAd->ate.TxWI.PHYMODE, MCS, IS_RT2070(pAd)); -#endif // RT30xx // - - - if (result != -1) - { - pAd->ate.TxWI.MCS = (UCHAR)MCS; - } - else - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_MCS_Proc::Out of range, refer to rate table.\n")); - return FALSE; - } - - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_MCS_Proc (MCS = %d)\n", pAd->ate.TxWI.MCS)); - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_MCS_Proc Success\n")); - - - return TRUE; -} - - -/* -========================================================================== - Description: - Set ATE Tx frame Mode - 0: MODE_CCK - 1: MODE_OFDM - 2: MODE_HTMIX - 3: MODE_HTGREENFIELD - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_TX_MODE_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UCHAR BbpData = 0; - - pAd->ate.TxWI.PHYMODE = simple_strtol(arg, 0, 10); - - if (pAd->ate.TxWI.PHYMODE > 3) - { - pAd->ate.TxWI.PHYMODE = 0; - ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_MODE_Proc::Out of range.\nIt should be in range of 0~3\n")); - ATEDBGPRINT(RT_DEBUG_ERROR, ("0: CCK, 1: OFDM, 2: HT_MIX, 3: HT_GREEN_FIELD.\n")); - return FALSE; - } - - // Turn on BBP 20MHz mode by request here. - if (pAd->ate.TxWI.PHYMODE == MODE_CCK) - { - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BbpData); - BbpData &= (~0x18); - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpData); - pAd->ate.TxWI.BW = BW_20; - ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_MODE_Proc::CCK Only support 20MHZ. Switch to 20MHZ.\n")); - } - - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_MODE_Proc (TxMode = %d)\n", pAd->ate.TxWI.PHYMODE)); - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_MODE_Proc Success\n")); - - - return TRUE; -} - - -/* -========================================================================== - Description: - Set ATE Tx frame GI - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -INT Set_ATE_TX_GI_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - pAd->ate.TxWI.ShortGI = simple_strtol(arg, 0, 10); - - if (pAd->ate.TxWI.ShortGI > 1) - { - pAd->ate.TxWI.ShortGI = 0; - ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_GI_Proc::Out of range\n")); - return FALSE; - } - - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_GI_Proc (GI = %d)\n", pAd->ate.TxWI.ShortGI)); - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_GI_Proc Success\n")); - - - return TRUE; -} - - -INT Set_ATE_RX_FER_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - pAd->ate.bRxFER = simple_strtol(arg, 0, 10); - - if (pAd->ate.bRxFER == 1) - { - pAd->ate.RxCntPerSec = 0; - pAd->ate.RxTotalCnt = 0; - } - - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_RX_FER_Proc (bRxFER = %d)\n", pAd->ate.bRxFER)); - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_RX_FER_Proc Success\n")); - - - return TRUE; -} - - -INT Set_ATE_Read_RF_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ -#ifdef RTMP_RF_RW_SUPPORT -//2008/07/10:KH add to support RT30xx ATE<-- - if (IS_RT30xx(pAd) || IS_RT3572(pAd)) - { - /* modify by WY for Read RF Reg. error */ - UCHAR RFValue; - INT index=0; - - for (index = 0; index < 32; index++) - { - ATE_RF_IO_READ8_BY_REG_ID(pAd, index, (PUCHAR)&RFValue); - ate_print("R%d=%d\n",index,RFValue); - } - } - else -//2008/07/10:KH add to support RT30xx ATE--> -#endif // RTMP_RF_RW_SUPPORT // - { - ate_print(KERN_EMERG "R1 = %lx\n", pAd->LatchRfRegs.R1); - ate_print(KERN_EMERG "R2 = %lx\n", pAd->LatchRfRegs.R2); - ate_print(KERN_EMERG "R3 = %lx\n", pAd->LatchRfRegs.R3); - ate_print(KERN_EMERG "R4 = %lx\n", pAd->LatchRfRegs.R4); - } - return TRUE; -} - - -INT Set_ATE_Write_RF1_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UINT32 value = (UINT32) simple_strtol(arg, 0, 16); - -#ifdef RTMP_RF_RW_SUPPORT -//2008/07/10:KH add to support 3070 ATE<-- - if (IS_RT30xx(pAd) || IS_RT3572(pAd)) - { - ate_print("Warning!! RT3xxx Don't Support !\n"); - return FALSE; - - } - else -//2008/07/10:KH add to support 3070 ATE--> -#endif // RTMP_RF_RW_SUPPORT // - { - pAd->LatchRfRegs.R1 = value; - RtmpRfIoWrite(pAd); - } - return TRUE; -} - - -INT Set_ATE_Write_RF2_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UINT32 value = (UINT32) simple_strtol(arg, 0, 16); - -#ifdef RTMP_RF_RW_SUPPORT -//2008/07/10:KH add to support 3070 ATE<-- - if (IS_RT30xx(pAd) || IS_RT3572(pAd)) - { - ate_print("Warning!! RT3xxx Don't Support !\n"); - return FALSE; - - } - else -//2008/07/10:KH add to support 3070 ATE--> -#endif // RTMP_RF_RW_SUPPORT // - { - pAd->LatchRfRegs.R2 = value; - RtmpRfIoWrite(pAd); - } - return TRUE; -} - - -INT Set_ATE_Write_RF3_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UINT32 value = simple_strtol(arg, 0, 16); - -#ifdef RTMP_RF_RW_SUPPORT -//2008/07/10:KH add to support 3070 ATE<-- - if (IS_RT30xx(pAd) || IS_RT3572(pAd)) - { - ate_print("Warning!! RT3xxx Don't Support !\n"); - return FALSE; - - } - else -//2008/07/10:KH add to support 3070 ATE--> -#endif // RTMP_RF_RW_SUPPORT // - { - pAd->LatchRfRegs.R3 = value; - RtmpRfIoWrite(pAd); - } - return TRUE; -} - - -INT Set_ATE_Write_RF4_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UINT32 value = (UINT32) simple_strtol(arg, 0, 16); - -#ifdef RTMP_RF_RW_SUPPORT -//2008/07/10:KH add to support 3070 ATE<-- - if (IS_RT30xx(pAd) || IS_RT3572(pAd)) - { - ate_print("Warning!! RT3xxx Don't Support !\n"); - return FALSE; - - } - else -//2008/07/10:KH add to support 3070 ATE--> -#endif // RTMP_RF_RW_SUPPORT // - { - pAd->LatchRfRegs.R4 = value; - RtmpRfIoWrite(pAd); - } - return TRUE; -} - - -/* -========================================================================== - Description: - Load and Write EEPROM from a binary file prepared in advance. - - Return: - TRUE if all parameters are OK, FALSE otherwise -========================================================================== -*/ -#if defined(LINUX) || defined(VXWORKS) -INT Set_ATE_Load_E2P_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - BOOLEAN ret = FALSE; - PSTRING src = EEPROM_BIN_FILE_NAME; - RTMP_OS_FD srcf; - INT32 retval; - USHORT WriteEEPROM[(EEPROM_SIZE/2)]; - INT FileLength = 0; - UINT32 value = (UINT32) simple_strtol(arg, 0, 10); - RTMP_OS_FS_INFO osFSInfo; - - ATEDBGPRINT(RT_DEBUG_ERROR, ("===> %s (value=%d)\n\n", __FUNCTION__, value)); - - if (value > 0) - { - /* zero the e2p buffer */ - NdisZeroMemory((PUCHAR)WriteEEPROM, EEPROM_SIZE); - - RtmpOSFSInfoChange(&osFSInfo, TRUE); - - do - { - /* open the bin file */ - srcf = RtmpOSFileOpen(src, O_RDONLY, 0); - - if (IS_FILE_OPEN_ERR(srcf)) - { - ate_print("%s - Error opening file %s\n", __FUNCTION__, src); - break; - } - - /* read the firmware from the file *.bin */ - FileLength = RtmpOSFileRead(srcf, (PSTRING)WriteEEPROM, EEPROM_SIZE); - - if (FileLength != EEPROM_SIZE) - { - ate_print("%s: error file length (=%d) in e2p.bin\n", - __FUNCTION__, FileLength); - break; - } - else - { - /* write the content of .bin file to EEPROM */ - rt_ee_write_all(pAd, WriteEEPROM); - ret = TRUE; - } - break; - } while(TRUE); - - /* close firmware file */ - if (IS_FILE_OPEN_ERR(srcf)) - { - ; - } - else - { - retval = RtmpOSFileClose(srcf); - - if (retval) - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("--> Error %d closing %s\n", -retval, src)); - - } - } - - /* restore */ - RtmpOSFSInfoChange(&osFSInfo, FALSE); - } - - ATEDBGPRINT(RT_DEBUG_ERROR, ("<=== %s (ret=%d)\n", __FUNCTION__, ret)); - - return ret; - -} -#endif // defined(LINUX) || defined(VXWORKS) // - - - - -INT Set_ATE_Read_E2P_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - USHORT buffer[EEPROM_SIZE/2]; - USHORT *p; - int i; - - rt_ee_read_all(pAd, (USHORT *)buffer); - p = buffer; - for (i = 0; i < (EEPROM_SIZE/2); i++) - { - ate_print("%4.4x ", *p); - if (((i+1) % 16) == 0) - ate_print("\n"); - p++; - } - return TRUE; -} - - - - -INT Set_ATE_Show_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ate_print("Mode=%d\n", pAd->ate.Mode); - ate_print("TxPower0=%d\n", pAd->ate.TxPower0); - ate_print("TxPower1=%d\n", pAd->ate.TxPower1); - ate_print("TxAntennaSel=%d\n", pAd->ate.TxAntennaSel); - ate_print("RxAntennaSel=%d\n", pAd->ate.RxAntennaSel); - ate_print("BBPCurrentBW=%d\n", pAd->ate.TxWI.BW); - ate_print("GI=%d\n", pAd->ate.TxWI.ShortGI); - ate_print("MCS=%d\n", pAd->ate.TxWI.MCS); - ate_print("TxMode=%d\n", pAd->ate.TxWI.PHYMODE); - ate_print("Addr1=%02x:%02x:%02x:%02x:%02x:%02x\n", - pAd->ate.Addr1[0], pAd->ate.Addr1[1], pAd->ate.Addr1[2], pAd->ate.Addr1[3], pAd->ate.Addr1[4], pAd->ate.Addr1[5]); - ate_print("Addr2=%02x:%02x:%02x:%02x:%02x:%02x\n", - pAd->ate.Addr2[0], pAd->ate.Addr2[1], pAd->ate.Addr2[2], pAd->ate.Addr2[3], pAd->ate.Addr2[4], pAd->ate.Addr2[5]); - ate_print("Addr3=%02x:%02x:%02x:%02x:%02x:%02x\n", - pAd->ate.Addr3[0], pAd->ate.Addr3[1], pAd->ate.Addr3[2], pAd->ate.Addr3[3], pAd->ate.Addr3[4], pAd->ate.Addr3[5]); - ate_print("Channel=%d\n", pAd->ate.Channel); - ate_print("TxLength=%d\n", pAd->ate.TxLength); - ate_print("TxCount=%u\n", pAd->ate.TxCount); - ate_print("RFFreqOffset=%d\n", pAd->ate.RFFreqOffset); - ate_print(KERN_EMERG "Set_ATE_Show_Proc Success\n"); - return TRUE; -} - - -INT Set_ATE_Help_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ate_print("ATE=ATESTART, ATESTOP, TXCONT, TXCARR, TXFRAME, RXFRAME\n"); - ate_print("ATEDA\n"); - ate_print("ATESA\n"); - ate_print("ATEBSSID\n"); - ate_print("ATECHANNEL, range:0~14(unless A band !)\n"); - ate_print("ATETXPOW0, set power level of antenna 1.\n"); - ate_print("ATETXPOW1, set power level of antenna 2.\n"); - ate_print("ATETXANT, set TX antenna. 0:all, 1:antenna one, 2:antenna two.\n"); - ate_print("ATERXANT, set RX antenna.0:all, 1:antenna one, 2:antenna two, 3:antenna three.\n"); - ate_print("ATETXFREQOFFSET, set frequency offset, range 0~63\n"); - ate_print("ATETXBW, set BandWidth, 0:20MHz, 1:40MHz.\n"); - ate_print("ATETXLEN, set Frame length, range 24~%d\n", (MAX_FRAME_SIZE - 34/* == 2312 */)); - ate_print("ATETXCNT, set how many frame going to transmit.\n"); - ate_print("ATETXMCS, set MCS, reference to rate table.\n"); - ate_print("ATETXMODE, set Mode 0:CCK, 1:OFDM, 2:HT-Mix, 3:GreenField, reference to rate table.\n"); - ate_print("ATETXGI, set GI interval, 0:Long, 1:Short\n"); - ate_print("ATERXFER, 0:disable Rx Frame error rate. 1:enable Rx Frame error rate.\n"); - ate_print("ATERRF, show all RF registers.\n"); - ate_print("ATEWRF1, set RF1 register.\n"); - ate_print("ATEWRF2, set RF2 register.\n"); - ate_print("ATEWRF3, set RF3 register.\n"); - ate_print("ATEWRF4, set RF4 register.\n"); - ate_print("ATELDE2P, load EEPROM from .bin file.\n"); - ate_print("ATERE2P, display all EEPROM content.\n"); - ate_print("ATESHOW, display all parameters of ATE.\n"); - ate_print("ATEHELP, online help.\n"); - - return TRUE; -} - - - - -/* -========================================================================== - Description: - - AsicSwitchChannel() dedicated for ATE. - -========================================================================== -*/ -VOID ATEAsicSwitchChannel( - IN PRTMP_ADAPTER pAd) -{ - UINT32 R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0, Value = 0; - CHAR TxPwer = 0, TxPwer2 = 0; - UCHAR index = 0, BbpValue = 0, R66 = 0x30; - RTMP_RF_REGS *RFRegTable; - UCHAR Channel = 0; - - RFRegTable = NULL; - -#ifdef RALINK_28xx_QA - // for QA mode, TX power values are passed from UI - if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE)) - { - if (pAd->ate.Channel != pAd->LatchRfRegs.Channel) - { - pAd->ate.Channel = pAd->LatchRfRegs.Channel; - } - return; - } - else -#endif // RALINK_28xx_QA // - Channel = pAd->ate.Channel; - - // select antenna for RT3090 - AsicAntennaSelect(pAd, Channel); - - // fill Tx power value - TxPwer = pAd->ate.TxPower0; - TxPwer2 = pAd->ate.TxPower1; -#ifdef RT30xx -//2008/07/10:KH add to support 3070 ATE<-- - - /* - The RF programming sequence is difference between 3xxx and 2xxx. - The 3070 is 1T1R. Therefore, we don't need to set the number of Tx/Rx path - and the only job is to set the parameters of channels. - */ - if (IS_RT30xx(pAd) && ((pAd->RfIcType == RFIC_3020) || - (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022) || - (pAd->RfIcType == RFIC_2020))) - { - /* modify by WY for Read RF Reg. error */ - UCHAR RFValue = 0; - - for (index = 0; index < NUM_OF_3020_CHNL; index++) - { - if (Channel == FreqItems3020[index].Channel) - { - // Programming channel parameters. - ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R02, FreqItems3020[index].N); - ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R03, FreqItems3020[index].K); - - ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R06, (PUCHAR)&RFValue); - RFValue = (RFValue & 0xFC) | FreqItems3020[index].R; - ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R06, (UCHAR)RFValue); - - // Set Tx Power. - ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R12, (PUCHAR)&RFValue); - RFValue = (RFValue & 0xE0) | TxPwer; - ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R12, (UCHAR)RFValue); - - // Set RF offset. - ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R23, (PUCHAR)&RFValue); - //2008/08/06: KH modified "pAd->RFFreqOffset" to "pAd->ate.RFFreqOffset" - RFValue = (RFValue & 0x80) | pAd->ate.RFFreqOffset; - ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R23, (UCHAR)RFValue); - - // Set BW. - if (pAd->ate.TxWI.BW == BW_40) - { - RFValue = pAd->Mlme.CaliBW40RfR24; -// DISABLE_11N_CHECK(pAd); - } - else - { - RFValue = pAd->Mlme.CaliBW20RfR24; - } - ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)RFValue); - - // Enable RF tuning - ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R07, (PUCHAR)&RFValue); - RFValue = RFValue | 0x1; - ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R07, (UCHAR)RFValue); - - // latch channel for future usage - pAd->LatchRfRegs.Channel = Channel; - - break; - } - } - - ATEDBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", - Channel, - pAd->RfIcType, - TxPwer, - TxPwer2, - pAd->Antenna.field.TxPath, - FreqItems3020[index].N, - FreqItems3020[index].K, - FreqItems3020[index].R)); - } - else -//2008/07/10:KH add to support 3070 ATE--> -#endif // RT30xx // - { - /* RT28xx */ - RFRegTable = RF2850RegTable; - - switch (pAd->RfIcType) - { - /* But only 2850 and 2750 support 5.5GHz band... */ - case RFIC_2820: - case RFIC_2850: - case RFIC_2720: - case RFIC_2750: - - for (index = 0; index < NUM_OF_2850_CHNL; index++) - { - if (Channel == RFRegTable[index].Channel) - { - R2 = RFRegTable[index].R2; - - // If TX path is 1, bit 14 = 1; - if (pAd->Antenna.field.TxPath == 1) - { - R2 |= 0x4000; - } - - if (pAd->Antenna.field.RxPath == 2) - { - switch (pAd->ate.RxAntennaSel) - { - case 1: - R2 |= 0x20040; - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); - BbpValue &= 0xE4; - BbpValue |= 0x00; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); - break; - case 2: - R2 |= 0x10040; - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); - BbpValue &= 0xE4; - BbpValue |= 0x01; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); - break; - default: - R2 |= 0x40; - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); - BbpValue &= 0xE4; - /* Only enable two Antenna to receive. */ - BbpValue |= 0x08; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); - break; - } - } - else if (pAd->Antenna.field.RxPath == 1) - { - // write 1 to off RxPath - R2 |= 0x20040; - } - - if (pAd->Antenna.field.TxPath == 2) - { - if (pAd->ate.TxAntennaSel == 1) - { - // If TX Antenna select is 1 , bit 14 = 1; Disable Ant 2 - R2 |= 0x4000; - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); - BbpValue &= 0xE7; // 11100111B - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); - } - else if (pAd->ate.TxAntennaSel == 2) - { - // If TX Antenna select is 2 , bit 15 = 1; Disable Ant 1 - R2 |= 0x8000; - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); - BbpValue &= 0xE7; - BbpValue |= 0x08; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); - } - else - { - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); - BbpValue &= 0xE7; - BbpValue |= 0x10; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); - } - } - if (pAd->Antenna.field.RxPath == 3) - { - switch (pAd->ate.RxAntennaSel) - { - case 1: - R2 |= 0x20040; - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); - BbpValue &= 0xE4; - BbpValue |= 0x00; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); - break; - case 2: - R2 |= 0x10040; - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); - BbpValue &= 0xE4; - BbpValue |= 0x01; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); - break; - case 3: - R2 |= 0x30000; - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); - BbpValue &= 0xE4; - BbpValue |= 0x02; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); - break; - default: - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); - BbpValue &= 0xE4; - BbpValue |= 0x10; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); - break; - } - } - - if (Channel > 14) - { - // initialize R3, R4 - R3 = (RFRegTable[index].R3 & 0xffffc1ff); - R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->ate.RFFreqOffset << 15); - - /* - According the Rory's suggestion to solve the middle range issue. - - 5.5G band power range : 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" - means the TX power reduce 7dB. - */ - // R3 - if ((TxPwer >= -7) && (TxPwer < 0)) - { - TxPwer = (7+TxPwer); - TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); - R3 |= (TxPwer << 10); - ATEDBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer=%d \n", TxPwer)); - } - else - { - TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); - R3 |= (TxPwer << 10) | (1 << 9); - } - - // R4 - if ((TxPwer2 >= -7) && (TxPwer2 < 0)) - { - TxPwer2 = (7+TxPwer2); - TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); - R4 |= (TxPwer2 << 7); - ATEDBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer2=%d \n", TxPwer2)); - } - else - { - TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); - R4 |= (TxPwer2 << 7) | (1 << 6); - } - } - else - { - // Set TX power0. - R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); - // Set frequency offset and TX power1. - R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->ate.RFFreqOffset << 15) | (TxPwer2 <<6); - } - - // based on BBP current mode before changing RF channel - if (pAd->ate.TxWI.BW == BW_40) - { - R4 |=0x200000; - } - - // Update variables. - pAd->LatchRfRegs.Channel = Channel; - pAd->LatchRfRegs.R1 = RFRegTable[index].R1; - pAd->LatchRfRegs.R2 = R2; - pAd->LatchRfRegs.R3 = R3; - pAd->LatchRfRegs.R4 = R4; - - RtmpRfIoWrite(pAd); - - break; - } - } - break; - - default: - break; - } - } - - // Change BBP setting during switch from a->g, g->a - if (Channel <= 14) - { - UINT32 TxPinCfg = 0x00050F0A;// 2007.10.09 by Brian : 0x0005050A ==> 0x00050F0A - - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); - - /* For 1T/2R chip only... */ - if (pAd->NicConfig2.field.ExternalLNAForG) - { - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); - } - else - { - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); - } - - // According the Rory's suggestion to solve the middle range issue. - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R86, &BbpValue);// may be removed for RT35xx ++ - - ASSERT((BbpValue == 0x00)); - if ((BbpValue != 0x00)) - { - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x00); - }// may be removed for RT35xx -- - - // 5.5 GHz band selection PIN, bit1 and bit2 are complement - RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); - Value &= (~0x6); - Value |= (0x04); - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); - - // Turn off unused PA or LNA when only 1T or 1R. - if (pAd->Antenna.field.TxPath == 1) - { - TxPinCfg &= 0xFFFFFFF3; - } - if (pAd->Antenna.field.RxPath == 1) - { - TxPinCfg &= 0xFFFFF3FF; - } - - // calibration power unbalance issues - if (pAd->Antenna.field.TxPath == 2) - { - if (pAd->ate.TxAntennaSel == 1) - { - TxPinCfg &= 0xFFFFFFF7; - } - else if (pAd->ate.TxAntennaSel == 2) - { - TxPinCfg &= 0xFFFFFFFD; - } - } - - RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); - } - else - { - UINT32 TxPinCfg = 0x00050F05;// 2007.10.09 by Brian : 0x00050505 ==> 0x00050F05 - - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); - - // According the Rory's suggestion to solve the middle range issue. - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R86, &BbpValue);// may be removed for RT35xx ++ - - ASSERT((BbpValue == 0x00)); - if ((BbpValue != 0x00)) - { - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x00); - } - - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R91, &BbpValue); - ASSERT((BbpValue == 0x04)); - - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R92, &BbpValue); - ASSERT((BbpValue == 0x00));// may be removed for RT35xx -- - - // 5.5 GHz band selection PIN, bit1 and bit2 are complement - RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); - Value &= (~0x6); - Value |= (0x02); - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); - - // Turn off unused PA or LNA when only 1T or 1R. - if (pAd->Antenna.field.TxPath == 1) - { - TxPinCfg &= 0xFFFFFFF3; - } - if (pAd->Antenna.field.RxPath == 1) - { - TxPinCfg &= 0xFFFFF3FF; - } - - RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); - } - - - // R66 should be set according to Channel and use 20MHz when scanning - if (Channel <= 14) - { - // BG band - R66 = 0x2E + GET_LNA_GAIN(pAd); - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - else - { - // 5.5 GHz band - if (pAd->ate.TxWI.BW == BW_20) - { - R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3); - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - else - { - R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3); - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); - } - } - - /* - On 11A, We should delay and wait RF/BBP to be stable - and the appropriate time should be 1000 micro seconds. - - 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL. - */ - RTMPusecDelay(1000); - -#ifndef RTMP_RF_RW_SUPPORT - if (Channel > 14) - { - // When 5.5GHz band the LSB of TxPwr will be used to reduced 7dB or not. - ATEDBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", - Channel, - pAd->RfIcType, - pAd->Antenna.field.TxPath, - pAd->LatchRfRegs.R1, - pAd->LatchRfRegs.R2, - pAd->LatchRfRegs.R3, - pAd->LatchRfRegs.R4)); - } - else - { - ATEDBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%u, Pwr1=%u, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", - Channel, - pAd->RfIcType, - (R3 & 0x00003e00) >> 9, - (R4 & 0x000007c0) >> 6, - pAd->Antenna.field.TxPath, - pAd->LatchRfRegs.R1, - pAd->LatchRfRegs.R2, - pAd->LatchRfRegs.R3, - pAd->LatchRfRegs.R4)); - } -#endif // RTMP_RF_RW_SUPPORT // -} - - - -/* In fact, no one will call this routine so far ! */ - -/* -========================================================================== - Description: - Gives CCK TX rate 2 more dB TX power. - This routine works only in ATE mode. - - calculate desired Tx power in RF R3.Tx0~5, should consider - - 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) - 1. TxPowerPercentage - 2. auto calibration based on TSSI feedback - 3. extra 2 db for CCK - 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP - - NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), - it should be called AFTER MlmeDynamicTxRateSwitching() -========================================================================== -*/ -VOID ATEAsicAdjustTxPower( - IN PRTMP_ADAPTER pAd) -{ - INT i, j; - CHAR DeltaPwr = 0; - BOOLEAN bAutoTxAgc = FALSE; - UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; - UCHAR BbpR49 = 0, idx; - PCHAR pTxAgcCompensate; - ULONG TxPwr[5]; - CHAR Value; - - /* no one calls this procedure so far */ - if (pAd->ate.TxWI.BW == BW_40) - { - if (pAd->ate.Channel > 14) - { - TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; - TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; - TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; - TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; - TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; - } - else - { - TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; - TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; - TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; - TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; - TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; - } - } - else - { - if (pAd->ate.Channel > 14) - { - TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; - TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; - TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; - TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; - TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; - } - else - { - TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; - TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; - TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; - TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; - TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; - } - } - - // TX power compensation for temperature variation based on TSSI. - // Do it per 4 seconds. - if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) - { - if (pAd->ate.Channel <= 14) - { - /* bg channel */ - bAutoTxAgc = pAd->bAutoTxAgcG; - TssiRef = pAd->TssiRefG; - pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; - pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; - TxAgcStep = pAd->TxAgcStepG; - pTxAgcCompensate = &pAd->TxAgcCompensateG; - } - else - { - /* a channel */ - bAutoTxAgc = pAd->bAutoTxAgcA; - TssiRef = pAd->TssiRefA; - pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; - pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; - TxAgcStep = pAd->TxAgcStepA; - pTxAgcCompensate = &pAd->TxAgcCompensateA; - } - - if (bAutoTxAgc) - { - /* BbpR49 is unsigned char. */ - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); - - /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ - /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ - /* step value is defined in pAd->TxAgcStepG for tx power value */ - - /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ - /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 - above value are examined in mass factory production */ - /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ - - /* plus is 0x10 ~ 0x40, minus is 0x60 ~ 0x90 */ - /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ - /* if value is 0x65, tx power will be -= TxAgcStep*(2-1) */ - - if (BbpR49 > pTssiMinusBoundary[1]) - { - // Reading is larger than the reference value. - // Check for how large we need to decrease the Tx power. - for (idx = 1; idx < 5; idx++) - { - // Found the range. - if (BbpR49 <= pTssiMinusBoundary[idx]) - break; - } - - // The index is the step we should decrease, idx = 0 means there is nothing to compensate. -// if (R3 > (ULONG) (TxAgcStep * (idx-1))) - *pTxAgcCompensate = -(TxAgcStep * (idx-1)); -// else -// *pTxAgcCompensate = -((UCHAR)R3); - - DeltaPwr += (*pTxAgcCompensate); - ATEDBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", - BbpR49, TssiRef, TxAgcStep, idx-1)); - } - else if (BbpR49 < pTssiPlusBoundary[1]) - { - // Reading is smaller than the reference value. - // Check for how large we need to increase the Tx power. - for (idx = 1; idx < 5; idx++) - { - // Found the range. - if (BbpR49 >= pTssiPlusBoundary[idx]) - break; - } - - // The index is the step we should increase, idx = 0 means there is nothing to compensate. - *pTxAgcCompensate = TxAgcStep * (idx-1); - DeltaPwr += (*pTxAgcCompensate); - ATEDBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", - BbpR49, TssiRef, TxAgcStep, idx-1)); - } - else - { - *pTxAgcCompensate = 0; - ATEDBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", - BbpR49, TssiRef, TxAgcStep, 0)); - } - } - } - else - { - if (pAd->ate.Channel <= 14) - { - bAutoTxAgc = pAd->bAutoTxAgcG; - pTxAgcCompensate = &pAd->TxAgcCompensateG; - } - else - { - bAutoTxAgc = pAd->bAutoTxAgcA; - pTxAgcCompensate = &pAd->TxAgcCompensateA; - } - - if (bAutoTxAgc) - DeltaPwr += (*pTxAgcCompensate); - } - - /* Calculate delta power based on the percentage specified from UI. */ - // E2PROM setting is calibrated for maximum TX power (i.e. 100%) - // We lower TX power here according to the percentage specified from UI. - if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control - ; - else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW - ; - else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW - { - DeltaPwr -= 1; - } - else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW - { - DeltaPwr -= 3; - } - else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW - { - DeltaPwr -= 6; - } - else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW - { - DeltaPwr -= 9; - } - else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW - { - DeltaPwr -= 12; - } - - /* Reset different new tx power for different TX rate. */ - for (i=0; i<5; i++) - { - if (TxPwr[i] != 0xffffffff) - { - for (j=0; j<8; j++) - { - Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */ - - if ((Value + DeltaPwr) < 0) - { - Value = 0; /* min */ - } - else if ((Value + DeltaPwr) > 0xF) - { - Value = 0xF; /* max */ - } - else - { - Value += DeltaPwr; /* temperature compensation */ - } - - /* fill new value to CSR offset */ - TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); - } - - /* write tx power value to CSR */ - /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M - TX power for OFDM 6M/9M - TX power for CCK5.5M/11M - TX power for CCK1M/2M */ - /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ - RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]); - - - } - } - -} - - -/* -======================================================================== - Routine Description: - Write TxWI for ATE mode. - - Return Value: - None -======================================================================== -*/ -#ifdef RTMP_MAC_PCI -static VOID ATEWriteTxWI( - IN PRTMP_ADAPTER pAd, - IN PTXWI_STRUC pOutTxWI, - IN BOOLEAN FRAG, - IN BOOLEAN CFACK, - IN BOOLEAN InsTimestamp, - IN BOOLEAN AMPDU, - IN BOOLEAN Ack, - IN BOOLEAN NSeq, // HW new a sequence. - IN UCHAR BASize, - IN UCHAR WCID, - IN ULONG Length, - IN UCHAR PID, - IN UCHAR TID, - IN UCHAR TxRate, - IN UCHAR Txopmode, - IN BOOLEAN CfAck, - IN HTTRANSMIT_SETTING *pTransmit) -{ - TXWI_STRUC TxWI; - PTXWI_STRUC pTxWI; - - // - // Always use Long preamble before verifiation short preamble functionality works well. - // Todo: remove the following line if short preamble functionality works - // - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); - NdisZeroMemory(&TxWI, TXWI_SIZE); - pTxWI = &TxWI; - - pTxWI->FRAG= FRAG; - - pTxWI->CFACK = CFACK; - pTxWI->TS= InsTimestamp; - pTxWI->AMPDU = AMPDU; - pTxWI->ACK = Ack; - pTxWI->txop= Txopmode; - - pTxWI->NSEQ = NSeq; - - // John tune the performace with Intel Client in 20 MHz performance - if ( BASize >7 ) - BASize =7; - - pTxWI->BAWinSize = BASize; - pTxWI->WirelessCliID = WCID; - pTxWI->MPDUtotalByteCount = Length; - pTxWI->PacketId = PID; - - // If CCK or OFDM, BW must be 20 - pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); - pTxWI->ShortGI = pTransmit->field.ShortGI; - pTxWI->STBC = pTransmit->field.STBC; - - pTxWI->MCS = pTransmit->field.MCS; - pTxWI->PHYMODE = pTransmit->field.MODE; - pTxWI->CFACK = CfAck; - pTxWI->MIMOps = 0; - pTxWI->MpduDensity = 0; - - pTxWI->PacketId = pTxWI->MCS; - NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC)); - - return; -} -#endif // RTMP_MAC_PCI // - - - - -/* -======================================================================== - - Routine Description: - Disable protection for ATE. -======================================================================== -*/ -VOID ATEDisableAsicProtect( - IN PRTMP_ADAPTER pAd) -{ - PROT_CFG_STRUC ProtCfg, ProtCfg4; - UINT32 Protect[6]; - USHORT offset; - UCHAR i; - UINT32 MacReg = 0; - - // Config ASIC RTS threshold register - RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); - MacReg &= 0xFF0000FF; - MacReg |= (pAd->CommonCfg.RtsThreshold << 8); - RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); - - // Initial common protection settings - RTMPZeroMemory(Protect, sizeof(Protect)); - ProtCfg4.word = 0; - ProtCfg.word = 0; - ProtCfg.field.TxopAllowGF40 = 1; - ProtCfg.field.TxopAllowGF20 = 1; - ProtCfg.field.TxopAllowMM40 = 1; - ProtCfg.field.TxopAllowMM20 = 1; - ProtCfg.field.TxopAllowOfdm = 1; - ProtCfg.field.TxopAllowCck = 1; - ProtCfg.field.RTSThEn = 1; - ProtCfg.field.ProtectNav = ASIC_SHORTNAV; - - // Handle legacy(B/G) protection - ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; - ProtCfg.field.ProtectCtrl = 0; - Protect[0] = ProtCfg.word; - Protect[1] = ProtCfg.word; - - // NO PROTECT - // 1.All STAs in the BSS are 20/40 MHz HT - // 2. in ai 20/40MHz BSS - // 3. all STAs are 20MHz in a 20MHz BSS - // Pure HT. no protection. - - // MM20_PROT_CFG - // Reserved (31:27) - // PROT_TXOP(25:20) -- 010111 - // PROT_NAV(19:18) -- 01 (Short NAV protection) - // PROT_CTRL(17:16) -- 00 (None) - // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) - Protect[2] = 0x01744004; - - // MM40_PROT_CFG - // Reserved (31:27) - // PROT_TXOP(25:20) -- 111111 - // PROT_NAV(19:18) -- 01 (Short NAV protection) - // PROT_CTRL(17:16) -- 00 (None) - // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) - Protect[3] = 0x03f44084; - - // CF20_PROT_CFG - // Reserved (31:27) - // PROT_TXOP(25:20) -- 010111 - // PROT_NAV(19:18) -- 01 (Short NAV protection) - // PROT_CTRL(17:16) -- 00 (None) - // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) - Protect[4] = 0x01744004; - - // CF40_PROT_CFG - // Reserved (31:27) - // PROT_TXOP(25:20) -- 111111 - // PROT_NAV(19:18) -- 01 (Short NAV protection) - // PROT_CTRL(17:16) -- 00 (None) - // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) - Protect[5] = 0x03f44084; - - pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; - - offset = CCK_PROT_CFG; - for (i = 0;i < 6;i++) - RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]); - -} - - - - -/* There are two ways to convert Rssi */ -/* the way used with GET_LNA_GAIN() */ -CHAR ATEConvertToRssi( - IN PRTMP_ADAPTER pAd, - IN CHAR Rssi, - IN UCHAR RssiNumber) -{ - UCHAR RssiOffset, LNAGain; - - // Rssi equals to zero should be an invalid value - if (Rssi == 0) - return -99; - - LNAGain = GET_LNA_GAIN(pAd); - if (pAd->LatchRfRegs.Channel > 14) - { - if (RssiNumber == 0) - RssiOffset = pAd->ARssiOffset0; - else if (RssiNumber == 1) - RssiOffset = pAd->ARssiOffset1; - else - RssiOffset = pAd->ARssiOffset2; - } - else - { - if (RssiNumber == 0) - RssiOffset = pAd->BGRssiOffset0; - else if (RssiNumber == 1) - RssiOffset = pAd->BGRssiOffset1; - else - RssiOffset = pAd->BGRssiOffset2; - } - - return (-12 - RssiOffset - LNAGain - Rssi); -} - - -/* -======================================================================== - - Routine Description: - Set Japan filter coefficients if needed. - Note: - This routine should only be called when - entering TXFRAME mode or TXCONT mode. - -======================================================================== -*/ -static VOID SetJapanFilter( - IN PRTMP_ADAPTER pAd) -{ - UCHAR BbpData = 0; - - // - // If Channel=14 and Bandwidth=20M and Mode=CCK, set BBP R4 bit5=1 - // (Japan Tx filter coefficients)when (TXFRAME or TXCONT). - // - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BbpData); - - if ((pAd->ate.TxWI.PHYMODE == MODE_CCK) && (pAd->ate.Channel == 14) && (pAd->ate.TxWI.BW == BW_20)) - { - BbpData |= 0x20; // turn on - ATEDBGPRINT(RT_DEBUG_TRACE, ("SetJapanFilter!!!\n")); - } - else - { - BbpData &= 0xdf; // turn off - ATEDBGPRINT(RT_DEBUG_TRACE, ("ClearJapanFilter!!!\n")); - } - - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpData); -} - - -VOID ATESampleRssi( - IN PRTMP_ADAPTER pAd, - IN PRXWI_STRUC pRxWI) -{ - /* There are two ways to collect RSSI. */ -// pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ; - if (pRxWI->RSSI0 != 0) - { - pAd->ate.LastRssi0 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI0, RSSI_0); - pAd->ate.AvgRssi0X8 = (pAd->ate.AvgRssi0X8 - pAd->ate.AvgRssi0) + pAd->ate.LastRssi0; - pAd->ate.AvgRssi0 = pAd->ate.AvgRssi0X8 >> 3; - } - if (pRxWI->RSSI1 != 0) - { - pAd->ate.LastRssi1 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI1, RSSI_1); - pAd->ate.AvgRssi1X8 = (pAd->ate.AvgRssi1X8 - pAd->ate.AvgRssi1) + pAd->ate.LastRssi1; - pAd->ate.AvgRssi1 = pAd->ate.AvgRssi1X8 >> 3; - } - if (pRxWI->RSSI2 != 0) - { - pAd->ate.LastRssi2 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI2, RSSI_2); - pAd->ate.AvgRssi2X8 = (pAd->ate.AvgRssi2X8 - pAd->ate.AvgRssi2) + pAd->ate.LastRssi2; - pAd->ate.AvgRssi2 = pAd->ate.AvgRssi2X8 >> 3; - } - - pAd->ate.LastSNR0 = (CHAR)(pRxWI->SNR0);// CHAR ==> UCHAR ? - pAd->ate.LastSNR1 = (CHAR)(pRxWI->SNR1);// CHAR ==> UCHAR ? - - pAd->ate.NumOfAvgRssiSample ++; -} - - -#ifdef CONFIG_STA_SUPPORT -VOID RTMPStationStop( - IN PRTMP_ADAPTER pAd) -{ -// BOOLEAN Cancelled; - - ATEDBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStop\n")); - - // For rx statistics, we need to keep this timer running. -// RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); - - ATEDBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStop\n")); -} - - -VOID RTMPStationStart( - IN PRTMP_ADAPTER pAd) -{ - ATEDBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStart\n")); - -#ifdef RTMP_MAC_PCI - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - - /* We did not cancel this timer when entering ATE mode. */ -// RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV); -#endif // RTMP_MAC_PCI // - - ATEDBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStart\n")); -} -#endif // CONFIG_STA_SUPPORT // - - -/* -========================================================================== - Description: - Setup Frame format. - NOTE: - This routine should only be used in ATE mode. -========================================================================== -*/ -#ifdef RTMP_MAC_PCI -static INT ATESetUpFrame( - IN PRTMP_ADAPTER pAd, - IN UINT32 TxIdx) -{ - UINT j; - PTXD_STRUC pTxD; -#ifdef RT_BIG_ENDIAN - PTXD_STRUC pDestTxD; - TXD_STRUC TxD; -#endif - PNDIS_PACKET pPacket; - PUCHAR pDest; - PVOID AllocVa; - NDIS_PHYSICAL_ADDRESS AllocPa; - HTTRANSMIT_SETTING TxHTPhyMode; - - PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; - PTXWI_STRUC pTxWI = (PTXWI_STRUC) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; - PUCHAR pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; - -#ifdef RALINK_28xx_QA - PHEADER_802_11 pHeader80211; -#endif // RALINK_28xx_QA // - - if (pAd->ate.bQATxStart == TRUE) - { - // always use QID_AC_BE and FIFO_EDCA - - // fill TxWI - TxHTPhyMode.field.BW = pAd->ate.TxWI.BW; - TxHTPhyMode.field.ShortGI = pAd->ate.TxWI.ShortGI; - TxHTPhyMode.field.STBC = 0; - TxHTPhyMode.field.MCS = pAd->ate.TxWI.MCS; - TxHTPhyMode.field.MODE = pAd->ate.TxWI.PHYMODE; - - ATEWriteTxWI(pAd, pTxWI, pAd->ate.TxWI.FRAG, pAd->ate.TxWI.CFACK, - pAd->ate.TxWI.TS, pAd->ate.TxWI.AMPDU, pAd->ate.TxWI.ACK, pAd->ate.TxWI.NSEQ, - pAd->ate.TxWI.BAWinSize, 0, pAd->ate.TxWI.MPDUtotalByteCount, pAd->ate.TxWI.PacketId, 0, 0, - pAd->ate.TxWI.txop/*IFS_HTTXOP*/, pAd->ate.TxWI.CFACK/*FALSE*/, &TxHTPhyMode); - } - else - { - TxHTPhyMode.field.BW = pAd->ate.TxWI.BW; - TxHTPhyMode.field.ShortGI = pAd->ate.TxWI.ShortGI; - TxHTPhyMode.field.STBC = 0; - TxHTPhyMode.field.MCS = pAd->ate.TxWI.MCS; - TxHTPhyMode.field.MODE = pAd->ate.TxWI.PHYMODE; - ATEWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, - 4, 0, pAd->ate.TxLength, 0, 0, 0, IFS_HTTXOP, FALSE, &TxHTPhyMode); - } - - // fill 802.11 header -#ifdef RALINK_28xx_QA - if (pAd->ate.bQATxStart == TRUE) - { - NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE, pAd->ate.Header, pAd->ate.HLen); - } - else -#endif // RALINK_28xx_QA // - { - NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE, TemplateFrame, LENGTH_802_11); - NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE+4, pAd->ate.Addr1, ETH_LENGTH_OF_ADDRESS); - NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE+10, pAd->ate.Addr2, ETH_LENGTH_OF_ADDRESS); - NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE+16, pAd->ate.Addr3, ETH_LENGTH_OF_ADDRESS); - } - -#ifdef RT_BIG_ENDIAN - RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA)+TXWI_SIZE), DIR_READ, FALSE); -#endif // RT_BIG_ENDIAN // - - /* alloc buffer for payload */ -#ifdef RALINK_28xx_QA - if (pAd->ate.bQATxStart == TRUE) - { - pPacket = RTMP_AllocateRxPacketBuffer(pAd, pAd->ate.DLen + 0x100, FALSE, &AllocVa, &AllocPa); - } - else -#endif // RALINK_28xx_QA // - { - pPacket = RTMP_AllocateRxPacketBuffer(pAd, pAd->ate.TxLength, FALSE, &AllocVa, &AllocPa); - } - - if (pPacket == NULL) - { - pAd->ate.TxCount = 0; - ATEDBGPRINT(RT_DEBUG_TRACE, ("%s fail to alloc packet space.\n", __FUNCTION__)); - return -1; - } - pTxRing->Cell[TxIdx].pNextNdisPacket = pPacket; - - pDest = (PUCHAR) AllocVa; - -#ifdef RALINK_28xx_QA - if (pAd->ate.bQATxStart == TRUE) - { - RTPKT_TO_OSPKT(pPacket)->len = pAd->ate.DLen; - } - else -#endif // RALINK_28xx_QA // - { - RTPKT_TO_OSPKT(pPacket)->len = pAd->ate.TxLength - LENGTH_802_11; - } - - // prepare frame payload -#ifdef RALINK_28xx_QA - if (pAd->ate.bQATxStart == TRUE) - { - // copy pattern - if ((pAd->ate.PLen != 0)) - { - int j; - - for (j = 0; j < pAd->ate.DLen; j+=pAd->ate.PLen) - { - memcpy(RTPKT_TO_OSPKT(pPacket)->data + j, pAd->ate.Pattern, pAd->ate.PLen); - } - } - } - else -#endif // RALINK_28xx_QA // - { - for (j = 0; j < RTPKT_TO_OSPKT(pPacket)->len; j++) - { - pDest[j] = 0xA5; - } - } - - /* build Tx Descriptor */ -#ifndef RT_BIG_ENDIAN - pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; -#else - pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; - TxD = *pDestTxD; - pTxD = &TxD; -#endif // !RT_BIG_ENDIAN // - -#ifdef RALINK_28xx_QA - if (pAd->ate.bQATxStart == TRUE) - { - // prepare TxD - NdisZeroMemory(pTxD, TXD_SIZE); - RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); - // build TX DESC - pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); - pTxD->SDLen0 = TXWI_SIZE + pAd->ate.HLen; - pTxD->LastSec0 = 0; - pTxD->SDPtr1 = AllocPa; - pTxD->SDLen1 = RTPKT_TO_OSPKT(pPacket)->len; - pTxD->LastSec1 = 1; - - pDest = (PUCHAR)pTxWI; - pDest += TXWI_SIZE; - pHeader80211 = (PHEADER_802_11)pDest; - - // modify sequence number... - if (pAd->ate.TxDoneCount == 0) - { - pAd->ate.seq = pHeader80211->Sequence; - } - else - pHeader80211->Sequence = ++pAd->ate.seq; - } - else -#endif // RALINK_28xx_QA // - { - NdisZeroMemory(pTxD, TXD_SIZE); - RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); - // build TX DESC - pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow (pTxRing->Cell[TxIdx].DmaBuf.AllocPa); - pTxD->SDLen0 = TXWI_SIZE + LENGTH_802_11; - pTxD->LastSec0 = 0; - pTxD->SDPtr1 = AllocPa; - pTxD->SDLen1 = RTPKT_TO_OSPKT(pPacket)->len; - pTxD->LastSec1 = 1; - } - -#ifdef RT_BIG_ENDIAN - RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); - RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA)+TXWI_SIZE), DIR_WRITE, FALSE); - RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); - WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); -#endif // RT_BIG_ENDIAN // - - return 0; -} -/*=======================End of RTMP_MAC_PCI =======================*/ -#endif // RTMP_MAC_PCI // - - - - -VOID rt_ee_read_all(PRTMP_ADAPTER pAd, USHORT *Data) -{ - USHORT i; - USHORT value; - - - for (i = 0 ; i < EEPROM_SIZE/2 ; ) - { - /* "value" is especially for some compilers... */ - RT28xx_EEPROM_READ16(pAd, i*2, value); - Data[i] = value; - i++; - } -} - - -VOID rt_ee_write_all(PRTMP_ADAPTER pAd, USHORT *Data) -{ - USHORT i; - USHORT value; - - - for (i = 0 ; i < EEPROM_SIZE/2 ; ) - { - /* "value" is especially for some compilers... */ - value = Data[i]; - RT28xx_EEPROM_WRITE16(pAd, i*2, value); - i++; - } -} - - -#ifdef RALINK_28xx_QA -VOID ATE_QA_Statistics( - IN PRTMP_ADAPTER pAd, - IN PRXWI_STRUC pRxWI, - IN PRT28XX_RXD_STRUC pRxD, - IN PHEADER_802_11 pHeader) -{ - // update counter first - if (pHeader != NULL) - { - if (pHeader->FC.Type == BTYPE_DATA) - { - if (pRxD->U2M) - pAd->ate.U2M++; - else - pAd->ate.OtherData++; - } - else if (pHeader->FC.Type == BTYPE_MGMT) - { - if (pHeader->FC.SubType == SUBTYPE_BEACON) - pAd->ate.Beacon++; - else - pAd->ate.OtherCount++; - } - else if (pHeader->FC.Type == BTYPE_CNTL) - { - pAd->ate.OtherCount++; - } - } - pAd->ate.RSSI0 = pRxWI->RSSI0; - pAd->ate.RSSI1 = pRxWI->RSSI1; - pAd->ate.RSSI2 = pRxWI->RSSI2; - pAd->ate.SNR0 = pRxWI->SNR0; - pAd->ate.SNR1 = pRxWI->SNR1; -} - - -/* command id with Cmd Type == 0x0008(for 28xx)/0x0005(for iNIC) */ -#define RACFG_CMD_RF_WRITE_ALL 0x0000 -#define RACFG_CMD_E2PROM_READ16 0x0001 -#define RACFG_CMD_E2PROM_WRITE16 0x0002 -#define RACFG_CMD_E2PROM_READ_ALL 0x0003 -#define RACFG_CMD_E2PROM_WRITE_ALL 0x0004 -#define RACFG_CMD_IO_READ 0x0005 -#define RACFG_CMD_IO_WRITE 0x0006 -#define RACFG_CMD_IO_READ_BULK 0x0007 -#define RACFG_CMD_BBP_READ8 0x0008 -#define RACFG_CMD_BBP_WRITE8 0x0009 -#define RACFG_CMD_BBP_READ_ALL 0x000a -#define RACFG_CMD_GET_COUNTER 0x000b -#define RACFG_CMD_CLEAR_COUNTER 0x000c - -#define RACFG_CMD_RSV1 0x000d -#define RACFG_CMD_RSV2 0x000e -#define RACFG_CMD_RSV3 0x000f - -#define RACFG_CMD_TX_START 0x0010 -#define RACFG_CMD_GET_TX_STATUS 0x0011 -#define RACFG_CMD_TX_STOP 0x0012 -#define RACFG_CMD_RX_START 0x0013 -#define RACFG_CMD_RX_STOP 0x0014 -#define RACFG_CMD_GET_NOISE_LEVEL 0x0015 - -#define RACFG_CMD_ATE_START 0x0080 -#define RACFG_CMD_ATE_STOP 0x0081 - -#define RACFG_CMD_ATE_START_TX_CARRIER 0x0100 -#define RACFG_CMD_ATE_START_TX_CONT 0x0101 -#define RACFG_CMD_ATE_START_TX_FRAME 0x0102 -#define RACFG_CMD_ATE_SET_BW 0x0103 -#define RACFG_CMD_ATE_SET_TX_POWER0 0x0104 -#define RACFG_CMD_ATE_SET_TX_POWER1 0x0105 -#define RACFG_CMD_ATE_SET_FREQ_OFFSET 0x0106 -#define RACFG_CMD_ATE_GET_STATISTICS 0x0107 -#define RACFG_CMD_ATE_RESET_COUNTER 0x0108 -#define RACFG_CMD_ATE_SEL_TX_ANTENNA 0x0109 -#define RACFG_CMD_ATE_SEL_RX_ANTENNA 0x010a -#define RACFG_CMD_ATE_SET_PREAMBLE 0x010b -#define RACFG_CMD_ATE_SET_CHANNEL 0x010c -#define RACFG_CMD_ATE_SET_ADDR1 0x010d -#define RACFG_CMD_ATE_SET_ADDR2 0x010e -#define RACFG_CMD_ATE_SET_ADDR3 0x010f -#define RACFG_CMD_ATE_SET_RATE 0x0110 -#define RACFG_CMD_ATE_SET_TX_FRAME_LEN 0x0111 -#define RACFG_CMD_ATE_SET_TX_FRAME_COUNT 0x0112 -#define RACFG_CMD_ATE_START_RX_FRAME 0x0113 -#define RACFG_CMD_ATE_E2PROM_READ_BULK 0x0114 -#define RACFG_CMD_ATE_E2PROM_WRITE_BULK 0x0115 -#define RACFG_CMD_ATE_IO_WRITE_BULK 0x0116 -#define RACFG_CMD_ATE_BBP_READ_BULK 0x0117 -#define RACFG_CMD_ATE_BBP_WRITE_BULK 0x0118 -#define RACFG_CMD_ATE_RF_READ_BULK 0x0119 -#define RACFG_CMD_ATE_RF_WRITE_BULK 0x011a - - -static VOID memcpy_exl(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len); -static VOID memcpy_exs(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len); -static VOID RTMP_IO_READ_BULK(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, UINT32 len); - - - -VOID RtmpDoAte( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq) -{ - USHORT Command_Id; - INT Status = NDIS_STATUS_SUCCESS; - struct ate_racfghdr *pRaCfg; - - - if ((pRaCfg = kmalloc(sizeof(struct ate_racfghdr), GFP_KERNEL)) == NULL) - { - Status = -EINVAL; - return; - } - - NdisZeroMemory(pRaCfg, sizeof(struct ate_racfghdr)); - - if (copy_from_user((PUCHAR)pRaCfg, wrq->u.data.pointer, wrq->u.data.length)) - { - Status = -EFAULT; - kfree(pRaCfg); - return; - } - - Command_Id = ntohs(pRaCfg->command_id); - - ATEDBGPRINT(RT_DEBUG_TRACE,("\n%s: Command_Id = 0x%04x !\n", __FUNCTION__, Command_Id)); - - switch (Command_Id) - { - /* We will get this command when QA starts. */ - case RACFG_CMD_ATE_START: - Status=DO_RACFG_CMD_ATE_START(pAdapter,wrq,pRaCfg); - break; - - /* We will get this command either QA is closed or ated is killed by user. */ - case RACFG_CMD_ATE_STOP: - Status=DO_RACFG_CMD_ATE_STOP(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_RF_WRITE_ALL: - Status=DO_RACFG_CMD_RF_WRITE_ALL(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_E2PROM_READ16: - Status=DO_RACFG_CMD_E2PROM_READ16(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_E2PROM_WRITE16: - Status=DO_RACFG_CMD_E2PROM_WRITE16(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_E2PROM_READ_ALL: - Status=DO_RACFG_CMD_E2PROM_READ_ALL(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_E2PROM_WRITE_ALL: - Status=DO_RACFG_CMD_E2PROM_WRITE_ALL(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_IO_READ: - Status=DO_RACFG_CMD_IO_READ(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_IO_WRITE: - Status=DO_RACFG_CMD_IO_WRITE(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_IO_READ_BULK: - Status=DO_RACFG_CMD_IO_READ_BULK(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_BBP_READ8: - Status=DO_RACFG_CMD_BBP_READ8(pAdapter,wrq,pRaCfg); - break; - case RACFG_CMD_BBP_WRITE8: - Status=DO_RACFG_CMD_BBP_WRITE8(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_BBP_READ_ALL: - Status=DO_RACFG_CMD_BBP_READ_ALL(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_E2PROM_READ_BULK: - Status=DO_RACFG_CMD_ATE_E2PROM_READ_BULK(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_E2PROM_WRITE_BULK: - Status=DO_RACFG_CMD_ATE_E2PROM_WRITE_BULK(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_IO_WRITE_BULK: - Status=DO_RACFG_CMD_ATE_IO_WRITE_BULK(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_BBP_READ_BULK: - Status=DO_RACFG_CMD_ATE_BBP_READ_BULK(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_BBP_WRITE_BULK: - Status=DO_RACFG_CMD_ATE_BBP_WRITE_BULK(pAdapter,wrq,pRaCfg); - break; - - - case RACFG_CMD_GET_NOISE_LEVEL: - Status=DO_RACFG_CMD_GET_NOISE_LEVEL(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_GET_COUNTER: - Status=DO_RACFG_CMD_GET_COUNTER(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_CLEAR_COUNTER: - Status=DO_RACFG_CMD_CLEAR_COUNTER(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_TX_START: - Status=DO_RACFG_CMD_TX_START(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_GET_TX_STATUS: - Status=DO_RACFG_CMD_GET_TX_STATUS(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_TX_STOP: - Status=DO_RACFG_CMD_TX_STOP(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_RX_START: - Status=DO_RACFG_CMD_RX_START(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_RX_STOP: - Status=DO_RACFG_CMD_RX_STOP(pAdapter,wrq,pRaCfg); - break; - - /* The following cases are for new ATE GUI(not QA). */ - /*==================================================*/ - case RACFG_CMD_ATE_START_TX_CARRIER: - Status=DO_RACFG_CMD_ATE_START_TX_CARRIER(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_START_TX_CONT: - Status=DO_RACFG_CMD_ATE_START_TX_CONT(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_START_TX_FRAME: - Status=DO_RACFG_CMD_ATE_START_TX_FRAME(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_SET_BW: - Status=DO_RACFG_CMD_ATE_SET_BW(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_SET_TX_POWER0: - Status=DO_RACFG_CMD_ATE_SET_TX_POWER0(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_SET_TX_POWER1: - Status=DO_RACFG_CMD_ATE_SET_TX_POWER1(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_SET_FREQ_OFFSET: - Status=DO_RACFG_CMD_ATE_SET_TX_POWER1(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_GET_STATISTICS: - Status=DO_RACFG_CMD_ATE_GET_STATISTICS(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_RESET_COUNTER: - Status=DO_RACFG_CMD_ATE_RESET_COUNTER(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_SEL_TX_ANTENNA: - Status=DO_RACFG_CMD_ATE_SEL_TX_ANTENNA(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_SEL_RX_ANTENNA: - Status=DO_RACFG_CMD_ATE_SEL_TX_ANTENNA(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_SET_PREAMBLE: - Status=DO_RACFG_CMD_ATE_SET_PREAMBLE(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_SET_CHANNEL: - Status=DO_RACFG_CMD_ATE_SET_CHANNEL(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_SET_ADDR1: - Status=DO_RACFG_CMD_ATE_SET_ADDR1(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_SET_ADDR2: - Status=DO_RACFG_CMD_ATE_SET_ADDR2(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_SET_ADDR3: - Status=DO_RACFG_CMD_ATE_SET_ADDR3(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_SET_RATE: - Status=DO_RACFG_CMD_ATE_SET_RATE(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_SET_TX_FRAME_LEN: - Status=DO_RACFG_CMD_ATE_SET_TX_FRAME_LEN(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_SET_TX_FRAME_COUNT: - Status=DO_RACFG_CMD_ATE_SET_TX_FRAME_COUNT(pAdapter,wrq,pRaCfg); - break; - - case RACFG_CMD_ATE_START_RX_FRAME: - Status=DO_RACFG_CMD_ATE_START_RX_FRAME(pAdapter,wrq,pRaCfg); - break; - default: - break; - } - - ASSERT(pRaCfg != NULL); - - if (pRaCfg != NULL) - kfree(pRaCfg); - - return; -} - - -VOID BubbleSort(INT32 n, INT32 a[]) -{ - INT32 k, j, temp; - - for (k = n-1; k>0; k--) - { - for (j = 0; j a[j+1]) - { - temp = a[j]; - a[j]=a[j+1]; - a[j+1]=temp; - } - } - } -} - - -VOID CalNoiseLevel(PRTMP_ADAPTER pAd, UCHAR channel, INT32 RSSI[3][10]) -{ - INT32 RSSI0, RSSI1, RSSI2; - CHAR Rssi0Offset, Rssi1Offset, Rssi2Offset; - UCHAR BbpR50Rssi0 = 0, BbpR51Rssi1 = 0, BbpR52Rssi2 = 0; - UCHAR Org_BBP66value = 0, Org_BBP69value = 0, Org_BBP70value = 0, data = 0; - USHORT LNA_Gain = 0; - INT32 j = 0; - UCHAR Org_Channel = pAd->ate.Channel; - USHORT GainValue = 0, OffsetValue = 0; - - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &Org_BBP66value); - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R69, &Org_BBP69value); - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R70, &Org_BBP70value); - - //********************************************************************** - // Read the value of LNA gain and Rssi offset - //********************************************************************** - RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, GainValue); - - // for Noise Level - if (channel <= 14) - { - LNA_Gain = GainValue & 0x00FF; - - RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, OffsetValue); - Rssi0Offset = OffsetValue & 0x00FF; - Rssi1Offset = (OffsetValue & 0xFF00) >> 8; - RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_BG_OFFSET + 2)/* 0x48 */, OffsetValue); - Rssi2Offset = OffsetValue & 0x00FF; - } - else - { - LNA_Gain = (GainValue & 0xFF00) >> 8; - - RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, OffsetValue); - Rssi0Offset = OffsetValue & 0x00FF; - Rssi1Offset = (OffsetValue & 0xFF00) >> 8; - RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET + 2)/* 0x4C */, OffsetValue); - Rssi2Offset = OffsetValue & 0x00FF; - } - //********************************************************************** - { - pAd->ate.Channel = channel; - ATEAsicSwitchChannel(pAd); - mdelay(5); - - data = 0x10; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, data); - data = 0x40; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, data); - data = 0x40; - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, data); - mdelay(5); - - // start Rx - pAd->ate.bQARxStart = TRUE; - Set_ATE_Proc(pAd, "RXFRAME"); - - mdelay(5); - - for (j = 0; j < 10; j++) - { - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R50, &BbpR50Rssi0); - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R51, &BbpR51Rssi1); - ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R52, &BbpR52Rssi2); - - mdelay(10); - - // calculate RSSI 0 - if (BbpR50Rssi0 == 0) - { - RSSI0 = -100; - } - else - { - RSSI0 = (INT32)(-12 - BbpR50Rssi0 - LNA_Gain - Rssi0Offset); - } - RSSI[0][j] = RSSI0; - - if ( pAd->Antenna.field.RxPath >= 2 ) // 2R - { - // calculate RSSI 1 - if (BbpR51Rssi1 == 0) - { - RSSI1 = -100; - } - else - { - RSSI1 = (INT32)(-12 - BbpR51Rssi1 - LNA_Gain - Rssi1Offset); - } - RSSI[1][j] = RSSI1; - } - - if ( pAd->Antenna.field.RxPath >= 3 ) // 3R - { - // calculate RSSI 2 - if (BbpR52Rssi2 == 0) - RSSI2 = -100; - else - RSSI2 = (INT32)(-12 - BbpR52Rssi2 - LNA_Gain - Rssi2Offset); - - RSSI[2][j] = RSSI2; - } - } - - // stop Rx - Set_ATE_Proc(pAd, "RXSTOP"); - - mdelay(5); - - BubbleSort(10, RSSI[0]); // 1R - - if ( pAd->Antenna.field.RxPath >= 2 ) // 2R - { - BubbleSort(10, RSSI[1]); - } - - if ( pAd->Antenna.field.RxPath >= 3 ) // 3R - { - BubbleSort(10, RSSI[2]); - } - } - - pAd->ate.Channel = Org_Channel; - ATEAsicSwitchChannel(pAd); - - // restore original value - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, Org_BBP66value); - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, Org_BBP69value); - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, Org_BBP70value); - - return; -} - - -BOOLEAN SyncTxRxConfig(PRTMP_ADAPTER pAd, USHORT offset, UCHAR value) -{ - UCHAR tmp = 0, bbp_data = 0; - - if (ATE_ON(pAd)) - { - ATE_BBP_IO_READ8_BY_REG_ID(pAd, offset, &bbp_data); - } - else - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, offset, &bbp_data); - } - - /* confirm again */ - ASSERT(bbp_data == value); - - switch (offset) - { - case BBP_R1: - /* Need to synchronize tx configuration with legacy ATE. */ - tmp = (bbp_data & ((1 << 4) | (1 << 3))/* 0x18 */) >> 3; - switch (tmp) - { - /* The BBP R1 bit[4:3] = 2 :: Both DACs will be used by QA. */ - case 2: - /* All */ - pAd->ate.TxAntennaSel = 0; - break; - /* The BBP R1 bit[4:3] = 0 :: DAC 0 will be used by QA. */ - case 0: - /* Antenna one */ - pAd->ate.TxAntennaSel = 1; - break; - /* The BBP R1 bit[4:3] = 1 :: DAC 1 will be used by QA. */ - case 1: - /* Antenna two */ - pAd->ate.TxAntennaSel = 2; - break; - default: - DBGPRINT(RT_DEBUG_TRACE, ("%s -- Sth. wrong! : return FALSE; \n", __FUNCTION__)); - return FALSE; - } - break;/* case BBP_R1 */ - - case BBP_R3: - /* Need to synchronize rx configuration with legacy ATE. */ - tmp = (bbp_data & ((1 << 1) | (1 << 0))/* 0x03 */); - switch(tmp) - { - /* The BBP R3 bit[1:0] = 3 :: All ADCs will be used by QA. */ - case 3: - /* All */ - pAd->ate.RxAntennaSel = 0; - break; - /* - The BBP R3 bit[1:0] = 0 :: ADC 0 will be used by QA, - unless the BBP R3 bit[4:3] = 2 - */ - case 0: - /* Antenna one */ - pAd->ate.RxAntennaSel = 1; - tmp = ((bbp_data & ((1 << 4) | (1 << 3))/* 0x03 */) >> 3); - if (tmp == 2)// 3R - { - /* Default : All ADCs will be used by QA */ - pAd->ate.RxAntennaSel = 0; - } - break; - /* The BBP R3 bit[1:0] = 1 :: ADC 1 will be used by QA. */ - case 1: - /* Antenna two */ - pAd->ate.RxAntennaSel = 2; - break; - /* The BBP R3 bit[1:0] = 2 :: ADC 2 will be used by QA. */ - case 2: - /* Antenna three */ - pAd->ate.RxAntennaSel = 3; - break; - default: - DBGPRINT(RT_DEBUG_ERROR, ("%s -- Impossible! : return FALSE; \n", __FUNCTION__)); - return FALSE; - } - break;/* case BBP_R3 */ - - default: - DBGPRINT(RT_DEBUG_ERROR, ("%s -- Sth. wrong! : return FALSE; \n", __FUNCTION__)); - return FALSE; - - } - return TRUE; -} - - -static VOID memcpy_exl(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len) -{ - ULONG i, Value = 0; - ULONG *pDst, *pSrc; - UCHAR *p8; - - p8 = src; - pDst = (ULONG *) dst; - pSrc = (ULONG *) src; - - for (i = 0 ; i < (len/4); i++) - { - /* For alignment issue, we need a variable "Value". */ - memmove(&Value, pSrc, 4); - Value = htonl(Value); - memmove(pDst, &Value, 4); - pDst++; - pSrc++; - } - if ((len % 4) != 0) - { - /* wish that it will never reach here */ - memmove(&Value, pSrc, (len % 4)); - Value = htonl(Value); - memmove(pDst, &Value, (len % 4)); - } -} - - -static VOID memcpy_exs(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len) -{ - ULONG i; - UCHAR *pDst, *pSrc; - - pDst = dst; - pSrc = src; - - for (i = 0; i < (len/2); i++) - { - memmove(pDst, pSrc, 2); - *((USHORT *)pDst) = htons(*((USHORT *)pDst)); - pDst+=2; - pSrc+=2; - } - - if ((len % 2) != 0) - { - memmove(pDst, pSrc, 1); - } -} - - -static VOID RTMP_IO_READ_BULK(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, UINT32 len) -{ - UINT32 i, Value; - UINT32 *pDst, *pSrc; - - pDst = (UINT32 *) dst; - pSrc = (UINT32 *) src; - - for (i = 0 ; i < (len/4); i++) - { - RTMP_IO_READ32(pAd, (ULONG)pSrc, &Value); - Value = htonl(Value); - memmove(pDst, &Value, 4); - pDst++; - pSrc++; - } - return; -} - - -INT Set_TxStop_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ATEDBGPRINT(RT_DEBUG_TRACE,("Set_TxStop_Proc\n")); - - if (Set_ATE_Proc(pAd, "TXSTOP")) - { - return TRUE; - } - else - { - return FALSE; - } -} - - -INT Set_RxStop_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ATEDBGPRINT(RT_DEBUG_TRACE,("Set_RxStop_Proc\n")); - - if (Set_ATE_Proc(pAd, "RXSTOP")) - { - return TRUE; - } - else - { - return FALSE; - } -} - - -#ifdef DBG -INT Set_EERead_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - USHORT buffer[EEPROM_SIZE/2]; - USHORT *p; - INT i; - - rt_ee_read_all(pAd, (USHORT *)buffer); - p = buffer; - - for (i = 0; i < (EEPROM_SIZE/2); i++) - { - ate_print(KERN_EMERG "%4.4x ", *p); - if (((i+1) % 16) == 0) - ate_print(KERN_EMERG "\n"); - p++; - } - - return TRUE; -} - - -INT Set_EEWrite_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - USHORT offset = 0, value; - PSTRING p2 = arg; - - while ((*p2 != ':') && (*p2 != '\0')) - { - p2++; - } - - if (*p2 == ':') - { - A2Hex(offset, arg); - A2Hex(value, p2 + 1); - } - else - { - A2Hex(value, arg); - } - - if (offset >= EEPROM_SIZE) - { - ate_print(KERN_EMERG "Offset can not exceed EEPROM_SIZE( == 0x%04x)\n", EEPROM_SIZE); - return FALSE; - } - - RT28xx_EEPROM_WRITE16(pAd, offset, value); - - return TRUE; -} - - -INT Set_BBPRead_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UCHAR value = 0, offset; - - A2Hex(offset, arg); - - if (ATE_ON(pAd)) - { - ATE_BBP_IO_READ8_BY_REG_ID(pAd, offset, &value); - } - else - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, offset, &value); - } - - ate_print(KERN_EMERG "%x\n", value); - - return TRUE; -} - - -INT Set_BBPWrite_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - USHORT offset = 0; - PSTRING p2 = arg; - UCHAR value; - - while ((*p2 != ':') && (*p2 != '\0')) - { - p2++; - } - - if (*p2 == ':') - { - A2Hex(offset, arg); - A2Hex(value, p2 + 1); - } - else - { - A2Hex(value, arg); - } - - if (ATE_ON(pAd)) - { - ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, offset, value); - } - else - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, offset, value); - } - - return TRUE; -} - - -INT Set_RFWrite_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - PSTRING p2, p3, p4; - UINT32 R1, R2, R3, R4; - - p2 = arg; - - while ((*p2 != ':') && (*p2 != '\0')) - { - p2++; - } - - if (*p2 != ':') - return FALSE; - - p3 = p2 + 1; - - while((*p3 != ':') && (*p3 != '\0')) - { - p3++; - } - - if (*p3 != ':') - return FALSE; - - p4 = p3 + 1; - - while ((*p4 != ':') && (*p4 != '\0')) - { - p4++; - } - - if (*p4 != ':') - return FALSE; - - - A2Hex(R1, arg); - A2Hex(R2, p2 + 1); - A2Hex(R3, p3 + 1); - A2Hex(R4, p4 + 1); - - RTMP_RF_IO_WRITE32(pAd, R1); - RTMP_RF_IO_WRITE32(pAd, R2); - RTMP_RF_IO_WRITE32(pAd, R3); - RTMP_RF_IO_WRITE32(pAd, R4); - - return TRUE; -} -#endif // DBG // -#endif // RALINK_28xx_QA // - - - - -#ifdef RALINK_28xx_QA -#define LEN_OF_ARG 16 - -#define RESPONSE_TO_GUI(__pRaCfg, __pwrq, __Length, __Status) \ - (__pRaCfg)->length = htons((__Length)); \ - (__pRaCfg)->status = htons((__Status)); \ - (__pwrq)->u.data.length = sizeof((__pRaCfg)->magic_no) + sizeof((__pRaCfg)->command_type) \ - + sizeof((__pRaCfg)->command_id) + sizeof((__pRaCfg)->length) \ - + sizeof((__pRaCfg)->sequence) + ntohs((__pRaCfg)->length); \ - ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", (__pwrq)->u.data.length)); \ - if (copy_to_user((__pwrq)->u.data.pointer, (UCHAR *)(__pRaCfg), (__pwrq)->u.data.length)) \ - { \ - ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in %s\n", __FUNCTION__)); \ - return (-EFAULT); \ - } \ - else \ - { \ - ATEDBGPRINT(RT_DEBUG_TRACE, ("%s is done !\n", __FUNCTION__)); \ - } - -static inline INT DO_RACFG_CMD_ATE_START( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START\n")); - - /* Prepare feedback as soon as we can to avoid QA timeout. */ - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - Set_ATE_Proc(pAdapter, "ATESTART"); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_STOP( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - INT32 ret; - - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_STOP\n")); - - /* - Distinguish this command came from QA(via ate agent) - or ate agent according to the existence of pid in payload. - - No need to prepare feedback if this cmd came directly from ate agent, - not from QA. - */ - pRaCfg->length = ntohs(pRaCfg->length); - - if (pRaCfg->length == sizeof(pAdapter->ate.AtePid)) - { - /* - This command came from QA. - Get the pid of ATE agent. - */ - memcpy((UCHAR *)&pAdapter->ate.AtePid, - (&pRaCfg->data[0]) - 2/* == sizeof(pRaCfg->status) */, - sizeof(pAdapter->ate.AtePid)); - - /* Prepare feedback as soon as we can to avoid QA timeout. */ - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - /* - Kill ATE agent when leaving ATE mode. - - We must kill ATE agent first before setting ATESTOP, - or Microsoft will report sth. wrong. - */ - ret = KILL_THREAD_PID(pAdapter->ate.AtePid, SIGTERM, 1); - - if (ret) - { - ATEDBGPRINT(RT_DEBUG_ERROR, ("%s: unable to kill ate thread\n", pAdapter->net_dev->name)); - } - } - - - /* AP/STA might have in ATE_STOP mode due to cmd from QA. */ - if (ATE_ON(pAdapter)) - { - /* Someone has killed ate agent while QA GUI is still open. */ - Set_ATE_Proc(pAdapter, "ATESTOP"); - ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_AP_START is done !\n")); - } - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_RF_WRITE_ALL( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - UINT32 R1, R2, R3, R4; - USHORT channel; - - memcpy(&R1, pRaCfg->data-2, 4); - memcpy(&R2, pRaCfg->data+2, 4); - memcpy(&R3, pRaCfg->data+6, 4); - memcpy(&R4, pRaCfg->data+10, 4); - memcpy(&channel, pRaCfg->data+14, 2); - - pAdapter->LatchRfRegs.R1 = ntohl(R1); - pAdapter->LatchRfRegs.R2 = ntohl(R2); - pAdapter->LatchRfRegs.R3 = ntohl(R3); - pAdapter->LatchRfRegs.R4 = ntohl(R4); - pAdapter->LatchRfRegs.Channel = ntohs(channel); - - RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R1); - RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R2); - RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R3); - RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R4); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_E2PROM_READ16( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - UINT16 offset=0, value=0; - USHORT tmp=0; - - offset = ntohs(pRaCfg->status); - - /* "tmp" is especially for some compilers... */ - RT28xx_EEPROM_READ16(pAdapter, offset, tmp); - value = tmp; - value = htons(value); - - ATEDBGPRINT(RT_DEBUG_TRACE,("EEPROM Read offset = 0x%04x, value = 0x%04x\n", offset, value)); - memcpy(pRaCfg->data, &value, 2); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status)+2, NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_E2PROM_WRITE16( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - USHORT offset, value; - - offset = ntohs(pRaCfg->status); - memcpy(&value, pRaCfg->data, 2); - value = ntohs(value); - RT28xx_EEPROM_WRITE16(pAdapter, offset, value); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_E2PROM_READ_ALL( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - USHORT buffer[EEPROM_SIZE/2]; - - rt_ee_read_all(pAdapter,(USHORT *)buffer); - memcpy_exs(pAdapter, pRaCfg->data, (UCHAR *)buffer, EEPROM_SIZE); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status)+EEPROM_SIZE, NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_E2PROM_WRITE_ALL( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - USHORT buffer[EEPROM_SIZE/2]; - - NdisZeroMemory((UCHAR *)buffer, EEPROM_SIZE); - memcpy_exs(pAdapter, (UCHAR *)buffer, (UCHAR *)&pRaCfg->status, EEPROM_SIZE); - rt_ee_write_all(pAdapter,(USHORT *)buffer); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_IO_READ( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - UINT32 offset; - UINT32 value; - - memcpy(&offset, &pRaCfg->status, 4); - offset = ntohl(offset); - - /* - We do not need the base address. - So just extract the offset out. - */ - offset &= 0x0000FFFF; - RTMP_IO_READ32(pAdapter, offset, &value); - value = htonl(value); - memcpy(pRaCfg->data, &value, 4); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status)+4, NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_IO_WRITE( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - UINT32 offset, value; - - memcpy(&offset, pRaCfg->data-2, 4); - memcpy(&value, pRaCfg->data+2, 4); - - offset = ntohl(offset); - - /* - We do not need the base address. - So just extract the offset out. - */ - offset &= 0x0000FFFF; - value = ntohl(value); - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_IO_WRITE: offset = %x, value = %x\n", offset, value)); - RTMP_IO_WRITE32(pAdapter, offset, value); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_IO_READ_BULK( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - UINT32 offset; - USHORT len; - - memcpy(&offset, &pRaCfg->status, 4); - offset = ntohl(offset); - - /* - We do not need the base address. - So just extract the offset out. - */ - offset &= 0x0000FFFF; - memcpy(&len, pRaCfg->data+2, 2); - len = ntohs(len); - - if (len > 371) - { - ATEDBGPRINT(RT_DEBUG_TRACE,("length requested is too large, make it smaller\n")); - pRaCfg->length = htons(2); - pRaCfg->status = htons(1); - return -EFAULT; - } - - RTMP_IO_READ_BULK(pAdapter, pRaCfg->data, (UCHAR *)offset, len*4);// unit in four bytes - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status)+(len*4), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_BBP_READ8( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - USHORT offset; - UCHAR value; - - value = 0; - offset = ntohs(pRaCfg->status); - - if (ATE_ON(pAdapter)) - { - ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, offset, &value); - } - else - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, offset, &value); - } - - pRaCfg->data[0] = value; - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status)+1, NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_BBP_WRITE8( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - USHORT offset; - UCHAR value; - - offset = ntohs(pRaCfg->status); - memcpy(&value, pRaCfg->data, 1); - - if (ATE_ON(pAdapter)) - { - ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, offset, value); - } - else - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, offset, value); - } - - if ((offset == BBP_R1) || (offset == BBP_R3)) - { - SyncTxRxConfig(pAdapter, offset, value); - } - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_BBP_READ_ALL( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - USHORT bbp_reg_index; - - for (bbp_reg_index = 0; bbp_reg_index < MAX_BBP_ID+1; bbp_reg_index++) - { - pRaCfg->data[bbp_reg_index] = 0; - - if (ATE_ON(pAdapter)) - { - ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbp_reg_index, &pRaCfg->data[bbp_reg_index]); - } - else - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbp_reg_index, &pRaCfg->data[bbp_reg_index]); - } - } - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status)+MAX_BBP_ID+1, NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_GET_NOISE_LEVEL( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - UCHAR channel; - INT32 buffer[3][10];/* 3 : RxPath ; 10 : no. of per rssi samples */ - - channel = (ntohs(pRaCfg->status) & 0x00FF); - CalNoiseLevel(pAdapter, channel, buffer); - memcpy_exl(pAdapter, (UCHAR *)pRaCfg->data, (UCHAR *)&(buffer[0][0]), (sizeof(INT32)*3*10)); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status)+(sizeof(INT32)*3*10), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_GET_COUNTER( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - memcpy_exl(pAdapter, &pRaCfg->data[0], (UCHAR *)&pAdapter->ate.U2M, 4); - memcpy_exl(pAdapter, &pRaCfg->data[4], (UCHAR *)&pAdapter->ate.OtherData, 4); - memcpy_exl(pAdapter, &pRaCfg->data[8], (UCHAR *)&pAdapter->ate.Beacon, 4); - memcpy_exl(pAdapter, &pRaCfg->data[12], (UCHAR *)&pAdapter->ate.OtherCount, 4); - memcpy_exl(pAdapter, &pRaCfg->data[16], (UCHAR *)&pAdapter->ate.TxAc0, 4); - memcpy_exl(pAdapter, &pRaCfg->data[20], (UCHAR *)&pAdapter->ate.TxAc1, 4); - memcpy_exl(pAdapter, &pRaCfg->data[24], (UCHAR *)&pAdapter->ate.TxAc2, 4); - memcpy_exl(pAdapter, &pRaCfg->data[28], (UCHAR *)&pAdapter->ate.TxAc3, 4); - /*memcpy_exl(pAdapter, &pRaCfg->data[32], (UCHAR *)&pAdapter->ate.TxHCCA, 4);*/ - memcpy_exl(pAdapter, &pRaCfg->data[36], (UCHAR *)&pAdapter->ate.TxMgmt, 4); - memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&pAdapter->ate.RSSI0, 4); - memcpy_exl(pAdapter, &pRaCfg->data[44], (UCHAR *)&pAdapter->ate.RSSI1, 4); - memcpy_exl(pAdapter, &pRaCfg->data[48], (UCHAR *)&pAdapter->ate.RSSI2, 4); - memcpy_exl(pAdapter, &pRaCfg->data[52], (UCHAR *)&pAdapter->ate.SNR0, 4); - memcpy_exl(pAdapter, &pRaCfg->data[56], (UCHAR *)&pAdapter->ate.SNR1, 4); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status)+60, NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_CLEAR_COUNTER( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - pAdapter->ate.U2M = 0; - pAdapter->ate.OtherData = 0; - pAdapter->ate.Beacon = 0; - pAdapter->ate.OtherCount = 0; - pAdapter->ate.TxAc0 = 0; - pAdapter->ate.TxAc1 = 0; - pAdapter->ate.TxAc2 = 0; - pAdapter->ate.TxAc3 = 0; - /*pAdapter->ate.TxHCCA = 0;*/ - pAdapter->ate.TxMgmt = 0; - pAdapter->ate.TxDoneCount = 0; - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_TX_START( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - USHORT *p; - USHORT err = 1; - UCHAR Bbp22Value = 0, Bbp24Value = 0; - - if ((pAdapter->ate.TxStatus != 0) && (pAdapter->ate.Mode & ATE_TXFRAME)) - { - ATEDBGPRINT(RT_DEBUG_TRACE,("Ate Tx is already running, to run next Tx, you must stop it first\n")); - err = 2; - goto TX_START_ERROR; - } - else if ((pAdapter->ate.TxStatus != 0) && !(pAdapter->ate.Mode & ATE_TXFRAME)) - { - int i = 0; - - while ((i++ < 10) && (pAdapter->ate.TxStatus != 0)) - { - RTMPusecDelay(5000); - } - - /* force it to stop */ - pAdapter->ate.TxStatus = 0; - pAdapter->ate.TxDoneCount = 0; - pAdapter->ate.bQATxStart = FALSE; - } - - /* - If pRaCfg->length == 0, this "RACFG_CMD_TX_START" - is for Carrier test or Carrier Suppression. - */ - if (ntohs(pRaCfg->length) != 0) - { - /* get frame info */ - - NdisMoveMemory(&pAdapter->ate.TxWI, pRaCfg->data + 2, 16); -#ifdef RT_BIG_ENDIAN - RTMPWIEndianChange((PUCHAR)&pAdapter->ate.TxWI, TYPE_TXWI); -#endif // RT_BIG_ENDIAN // - - NdisMoveMemory(&pAdapter->ate.TxCount, pRaCfg->data + 18, 4); - pAdapter->ate.TxCount = ntohl(pAdapter->ate.TxCount); - - p = (USHORT *)(&pRaCfg->data[22]); - - /* always use QID_AC_BE */ - pAdapter->ate.QID = 0; - - p = (USHORT *)(&pRaCfg->data[24]); - pAdapter->ate.HLen = ntohs(*p); - - if (pAdapter->ate.HLen > 32) - { - ATEDBGPRINT(RT_DEBUG_ERROR,("pAdapter->ate.HLen > 32\n")); - err = 3; - goto TX_START_ERROR; - } - - NdisMoveMemory(&pAdapter->ate.Header, pRaCfg->data + 26, pAdapter->ate.HLen); - - pAdapter->ate.PLen = ntohs(pRaCfg->length) - (pAdapter->ate.HLen + 28); - - if (pAdapter->ate.PLen > 32) - { - ATEDBGPRINT(RT_DEBUG_ERROR,("pAdapter->ate.PLen > 32\n")); - err = 4; - goto TX_START_ERROR; - } - - NdisMoveMemory(&pAdapter->ate.Pattern, pRaCfg->data + 26 + pAdapter->ate.HLen, pAdapter->ate.PLen); - pAdapter->ate.DLen = pAdapter->ate.TxWI.MPDUtotalByteCount - pAdapter->ate.HLen; - } - - ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R22, &Bbp22Value); - - switch (Bbp22Value) - { - case BBP22_TXFRAME: - { - if (pAdapter->ate.TxCount == 0) - { -#ifdef RTMP_MAC_PCI - pAdapter->ate.TxCount = 0xFFFFFFFF; -#endif // RTMP_MAC_PCI // - } - ATEDBGPRINT(RT_DEBUG_TRACE,("START TXFRAME\n")); - pAdapter->ate.bQATxStart = TRUE; - Set_ATE_Proc(pAdapter, "TXFRAME"); - } - break; - - case BBP22_TXCONT_OR_CARRSUPP: - { - ATEDBGPRINT(RT_DEBUG_TRACE,("BBP22_TXCONT_OR_CARRSUPP\n")); - ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R24, &Bbp24Value); - - switch (Bbp24Value) - { - case BBP24_TXCONT: - { - ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCONT\n")); - pAdapter->ate.bQATxStart = TRUE; - Set_ATE_Proc(pAdapter, "TXCONT"); - } - break; - - case BBP24_CARRSUPP: - { - ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCARRSUPP\n")); - pAdapter->ate.bQATxStart = TRUE; - pAdapter->ate.Mode |= ATE_TXCARRSUPP; - } - break; - - default: - { - ATEDBGPRINT(RT_DEBUG_ERROR,("Unknown TX subtype !")); - } - break; - } - } - break; - - case BBP22_TXCARR: - { - ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCARR\n")); - pAdapter->ate.bQATxStart = TRUE; - Set_ATE_Proc(pAdapter, "TXCARR"); - } - break; - - default: - { - ATEDBGPRINT(RT_DEBUG_ERROR,("Unknown Start TX subtype !")); - } - break; - } - - if (pAdapter->ate.bQATxStart == TRUE) - { - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - return NDIS_STATUS_SUCCESS; - } - -TX_START_ERROR: - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), err); - - return err; -} - - -static inline INT DO_RACFG_CMD_GET_TX_STATUS( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - UINT32 count=0; - - count = htonl(pAdapter->ate.TxDoneCount); - NdisMoveMemory(pRaCfg->data, &count, 4); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status)+4, NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_TX_STOP( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_TX_STOP\n")); - - Set_ATE_Proc(pAdapter, "TXSTOP"); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_RX_START( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_START\n")); - - pAdapter->ate.bQARxStart = TRUE; - Set_ATE_Proc(pAdapter, "RXFRAME"); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_RX_STOP( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_STOP\n")); - - Set_ATE_Proc(pAdapter, "RXSTOP"); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_START_TX_CARRIER( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_CARRIER\n")); - - Set_ATE_Proc(pAdapter, "TXCARR"); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_START_TX_CONT( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_CONT\n")); - - Set_ATE_Proc(pAdapter, "TXCONT"); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_START_TX_FRAME( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_FRAME\n")); - - Set_ATE_Proc(pAdapter, "TXFRAME"); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_SET_BW( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - SHORT value = 0; - STRING str[LEN_OF_ARG]; - - NdisZeroMemory(str, LEN_OF_ARG); - - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_BW\n")); - - memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); - value = ntohs(value); - sprintf((char *)str, "%d", value); - - Set_ATE_TX_BW_Proc(pAdapter, str); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_SET_TX_POWER0( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - SHORT value = 0; - STRING str[LEN_OF_ARG]; - - NdisZeroMemory(str, LEN_OF_ARG); - - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER0\n")); - - memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); - value = ntohs(value); - sprintf((char *)str, "%d", value); - Set_ATE_TX_POWER0_Proc(pAdapter, str); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_SET_TX_POWER1( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - SHORT value = 0; - STRING str[LEN_OF_ARG]; - - NdisZeroMemory(str, LEN_OF_ARG); - - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER1\n")); - - memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); - value = ntohs(value); - sprintf((char *)str, "%d", value); - Set_ATE_TX_POWER1_Proc(pAdapter, str); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_SET_FREQ_OFFSET( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - SHORT value = 0; - STRING str[LEN_OF_ARG]; - - NdisZeroMemory(str, LEN_OF_ARG); - - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_FREQ_OFFSET\n")); - - memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); - value = ntohs(value); - sprintf((char *)str, "%d", value); - Set_ATE_TX_FREQOFFSET_Proc(pAdapter, str); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_GET_STATISTICS( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_GET_STATISTICS\n")); - - memcpy_exl(pAdapter, &pRaCfg->data[0], (UCHAR *)&pAdapter->ate.TxDoneCount, 4); - memcpy_exl(pAdapter, &pRaCfg->data[4], (UCHAR *)&pAdapter->WlanCounters.RetryCount.u.LowPart, 4); - memcpy_exl(pAdapter, &pRaCfg->data[8], (UCHAR *)&pAdapter->WlanCounters.FailedCount.u.LowPart, 4); - memcpy_exl(pAdapter, &pRaCfg->data[12], (UCHAR *)&pAdapter->WlanCounters.RTSSuccessCount.u.LowPart, 4); - memcpy_exl(pAdapter, &pRaCfg->data[16], (UCHAR *)&pAdapter->WlanCounters.RTSFailureCount.u.LowPart, 4); - memcpy_exl(pAdapter, &pRaCfg->data[20], (UCHAR *)&pAdapter->WlanCounters.ReceivedFragmentCount.QuadPart, 4); - memcpy_exl(pAdapter, &pRaCfg->data[24], (UCHAR *)&pAdapter->WlanCounters.FCSErrorCount.u.LowPart, 4); - memcpy_exl(pAdapter, &pRaCfg->data[28], (UCHAR *)&pAdapter->Counters8023.RxNoBuffer, 4); - memcpy_exl(pAdapter, &pRaCfg->data[32], (UCHAR *)&pAdapter->WlanCounters.FrameDuplicateCount.u.LowPart, 4); - memcpy_exl(pAdapter, &pRaCfg->data[36], (UCHAR *)&pAdapter->RalinkCounters.OneSecFalseCCACnt, 4); - - if (pAdapter->ate.RxAntennaSel == 0) - { - INT32 RSSI0 = 0; - INT32 RSSI1 = 0; - INT32 RSSI2 = 0; - - RSSI0 = (INT32)(pAdapter->ate.LastRssi0 - pAdapter->BbpRssiToDbmDelta); - RSSI1 = (INT32)(pAdapter->ate.LastRssi1 - pAdapter->BbpRssiToDbmDelta); - RSSI2 = (INT32)(pAdapter->ate.LastRssi2 - pAdapter->BbpRssiToDbmDelta); - memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&RSSI0, 4); - memcpy_exl(pAdapter, &pRaCfg->data[44], (UCHAR *)&RSSI1, 4); - memcpy_exl(pAdapter, &pRaCfg->data[48], (UCHAR *)&RSSI2, 4); - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status)+52, NDIS_STATUS_SUCCESS); - } - else - { - INT32 RSSI0 = 0; - - RSSI0 = (INT32)(pAdapter->ate.LastRssi0 - pAdapter->BbpRssiToDbmDelta); - memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&RSSI0, 4); - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status)+44, NDIS_STATUS_SUCCESS); - } - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_RESET_COUNTER( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - SHORT value = 1; - STRING str[LEN_OF_ARG]; - - NdisZeroMemory(str, LEN_OF_ARG); - - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_RESET_COUNTER\n")); - - sprintf((char *)str, "%d", value); - Set_ResetStatCounter_Proc(pAdapter, str); - - pAdapter->ate.TxDoneCount = 0; - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_SEL_TX_ANTENNA( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - SHORT value = 0; - STRING str[LEN_OF_ARG]; - - NdisZeroMemory(str, LEN_OF_ARG); - - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SEL_TX_ANTENNA\n")); - - memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); - value = ntohs(value); - sprintf((char *)str, "%d", value); - Set_ATE_TX_Antenna_Proc(pAdapter, str); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_SEL_RX_ANTENNA( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - SHORT value = 0; - STRING str[LEN_OF_ARG]; - - NdisZeroMemory(str, LEN_OF_ARG); - - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SEL_RX_ANTENNA\n")); - - memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); - value = ntohs(value); - sprintf((char *)str, "%d", value); - Set_ATE_RX_Antenna_Proc(pAdapter, str); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_SET_PREAMBLE( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - SHORT value = 0; - STRING str[LEN_OF_ARG]; - - NdisZeroMemory(str, LEN_OF_ARG); - - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_PREAMBLE\n")); - - memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); - value = ntohs(value); - sprintf((char *)str, "%d", value); - Set_ATE_TX_MODE_Proc(pAdapter, str); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_SET_CHANNEL( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - SHORT value = 0; - STRING str[LEN_OF_ARG]; - - NdisZeroMemory(str, LEN_OF_ARG); - - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_CHANNEL\n")); - - memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); - value = ntohs(value); - sprintf((char *)str, "%d", value); - Set_ATE_CHANNEL_Proc(pAdapter, str); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_SET_ADDR1( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR1\n")); - - /* - Addr is an array of UCHAR, - so no need to perform endian swap. - */ - memcpy(pAdapter->ate.Addr1, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_SET_ADDR2( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR2\n")); - - /* - Addr is an array of UCHAR, - so no need to perform endian swap. - */ - memcpy(pAdapter->ate.Addr2, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_SET_ADDR3( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR3\n")); - - /* - Addr is an array of UCHAR, - so no need to perform endian swap. - */ - memcpy(pAdapter->ate.Addr3, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_SET_RATE( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - SHORT value = 0; - STRING str[LEN_OF_ARG]; - - NdisZeroMemory(str, LEN_OF_ARG); - - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_RATE\n")); - - memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); - value = ntohs(value); - sprintf((char *)str, "%d", value); - Set_ATE_TX_MCS_Proc(pAdapter, str); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_SET_TX_FRAME_LEN( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - SHORT value = 0; - STRING str[LEN_OF_ARG]; - - NdisZeroMemory(str, LEN_OF_ARG); - - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_FRAME_LEN\n")); - - memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); - value = ntohs(value); - sprintf((char *)str, "%d", value); - Set_ATE_TX_LENGTH_Proc(pAdapter, str); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_SET_TX_FRAME_COUNT( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - USHORT value = 0; - STRING str[LEN_OF_ARG]; - - NdisZeroMemory(str, LEN_OF_ARG); - - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_FRAME_COUNT\n")); - - memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); - value = ntohs(value); - -#ifdef RTMP_MAC_PCI - /* TX_FRAME_COUNT == 0 means tx infinitely */ - if (value == 0) - { - /* Use TxCount = 0xFFFFFFFF to approximate the infinity. */ - pAdapter->ate.TxCount = 0xFFFFFFFF; - ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_COUNT_Proc (TxCount = %d)\n", pAdapter->ate.TxCount)); - ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_COUNT_Proc Success\n")); - - - } - else -#endif // RTMP_MAC_PCI // - { - sprintf((char *)str, "%d", value); - Set_ATE_TX_COUNT_Proc(pAdapter, str); - } - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_START_RX_FRAME( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_START\n")); - - Set_ATE_Proc(pAdapter, "RXFRAME"); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_E2PROM_READ_BULK( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - USHORT offset; - USHORT len; - USHORT buffer[EEPROM_SIZE/2]; - - offset = ntohs(pRaCfg->status); - memcpy(&len, pRaCfg->data, 2); - len = ntohs(len); - - rt_ee_read_all(pAdapter, (USHORT *)buffer); - - if (offset + len <= EEPROM_SIZE) - memcpy_exs(pAdapter, pRaCfg->data, (UCHAR *)buffer+offset, len); - else - ATEDBGPRINT(RT_DEBUG_ERROR, ("exceed EEPROM size\n")); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status)+len, NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_E2PROM_WRITE_BULK( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - USHORT offset; - USHORT len; - USHORT buffer[EEPROM_SIZE/2]; - - offset = ntohs(pRaCfg->status); - memcpy(&len, pRaCfg->data, 2); - len = ntohs(len); - - rt_ee_read_all(pAdapter,(USHORT *)buffer); - memcpy_exs(pAdapter, (UCHAR *)buffer + offset, (UCHAR *)pRaCfg->data + 2, len); - rt_ee_write_all(pAdapter,(USHORT *)buffer); - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_IO_WRITE_BULK( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - UINT32 offset, i, value; - USHORT len; - - memcpy(&offset, &pRaCfg->status, 4); - offset = ntohl(offset); - memcpy(&len, pRaCfg->data+2, 2); - len = ntohs(len); - - for (i = 0; i < len; i += 4) - { - memcpy_exl(pAdapter, (UCHAR *)&value, pRaCfg->data+4+i, 4); - ATEDBGPRINT(RT_DEBUG_TRACE,("Write %x %x\n", offset + i, value)); - RTMP_IO_WRITE32(pAdapter, ((offset+i) & (0xffff)), value); - } - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_BBP_READ_BULK( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - USHORT offset; - USHORT len; - USHORT j; - - offset = ntohs(pRaCfg->status); - memcpy(&len, pRaCfg->data, 2); - len = ntohs(len); - - for (j = offset; j < (offset+len); j++) - { - pRaCfg->data[j - offset] = 0; - - if (pAdapter->ate.Mode == ATE_STOP) - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j - offset]); - } - else - { - ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j - offset]); - } - } - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status)+len, NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -static inline INT DO_RACFG_CMD_ATE_BBP_WRITE_BULK( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq, - IN struct ate_racfghdr *pRaCfg) -{ - USHORT offset; - USHORT len; - USHORT j; - UCHAR *value; - - offset = ntohs(pRaCfg->status); - memcpy(&len, pRaCfg->data, 2); - len = ntohs(len); - - for (j = offset; j < (offset+len); j++) - { - value = pRaCfg->data + 2 + (j - offset); - if (pAdapter->ate.Mode == ATE_STOP) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, j, *value); - } - else - { - ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, j, *value); - } - } - - RESPONSE_TO_GUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); - - return NDIS_STATUS_SUCCESS; -} - - -#endif // RALINK_28xx_QA // -#endif // RALINK_ATE // diff --git a/drivers/staging/rt3090/rt_ate.h b/drivers/staging/rt3090/rt_ate.h deleted file mode 100644 index 38d596162e7467dcc39116c2a24945f5fc8ac9e4..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rt_ate.h +++ /dev/null @@ -1,314 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - */ - -#ifndef __ATE_H__ -#define __ATE_H__ - - -#ifdef LINUX -#define ate_print printk -#define ATEDBGPRINT DBGPRINT -#ifdef RTMP_MAC_PCI -#define EEPROM_SIZE 0x200 -#ifdef CONFIG_STA_SUPPORT -#define EEPROM_BIN_FILE_NAME "/etc/Wireless/RT2860STA/e2p.bin" -#endif // CONFIG_STA_SUPPORT // -#endif // RTMP_MAC_PCI // -#endif // LINUX // - - -#define ATE_ON(_p) (((_p)->ate.Mode) != ATE_STOP) - -#ifdef RTMP_MAC_PCI -#define ATE_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \ -{ \ - BBP_CSR_CFG_STRUC BbpCsr; \ - int j, k; \ - for (j=0; jBbpWriteLatch[_I]; \ - } \ -} - -#define ATE_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) \ -{ \ - BBP_CSR_CFG_STRUC BbpCsr; \ - int BusyCnt; \ - for (BusyCnt=0; BusyCntBbpWriteLatch[_I] = _V; \ - break; \ - } \ - if (BusyCnt == MAX_BUSY_COUNT) \ - { \ - ATEDBGPRINT(RT_DEBUG_ERROR, ("BBP write R%d fail\n", _I)); \ - } \ -} -#endif // RTMP_MAC_PCI // - - -#ifdef RT30xx -#define ATE_RF_IO_READ8_BY_REG_ID(_A, _I, _pV) RTMP_RF_IO_READ8_BY_REG_ID(_A, _I, _pV) -#define ATE_RF_IO_WRITE8_BY_REG_ID(_A, _I, _V) RTMP_RF_IO_WRITE8_BY_REG_ID(_A, _I, _V) -#endif // RT30xx // - - -VOID rt_ee_read_all( - IN PRTMP_ADAPTER pAd, - OUT USHORT *Data); - -VOID rt_ee_write_all( - IN PRTMP_ADAPTER pAd, - IN USHORT *Data); - -INT Set_ATE_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_DA_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_SA_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_BSSID_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_CHANNEL_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_TX_POWER0_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_TX_POWER1_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_TX_Antenna_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_RX_Antenna_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_TX_FREQOFFSET_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_TX_BW_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_TX_LENGTH_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_TX_COUNT_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_TX_MCS_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_TX_MODE_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_TX_GI_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - - -INT Set_ATE_RX_FER_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_Read_RF_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_Write_RF1_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_Write_RF2_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_Write_RF3_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_Write_RF4_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_Load_E2P_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_Read_E2P_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - - -INT Set_ATE_Show_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ATE_Help_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -#ifdef RALINK_28xx_QA -VOID ATE_QA_Statistics( - IN PRTMP_ADAPTER pAd, - IN PRXWI_STRUC pRxWI, - IN PRT28XX_RXD_STRUC p28xxRxD, - IN PHEADER_802_11 pHeader); - -VOID RtmpDoAte( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq); - -VOID BubbleSort( - IN INT32 n, - IN INT32 a[]); - -VOID CalNoiseLevel( - IN PRTMP_ADAPTER pAdapter, - IN UCHAR channel, - OUT INT32 buffer[3][10]); - -BOOLEAN SyncTxRxConfig( - IN PRTMP_ADAPTER pAdapter, - IN USHORT offset, - IN UCHAR value); - -INT Set_TxStop_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_RxStop_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -#ifdef DBG -INT Set_EERead_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_EEWrite_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_BBPRead_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_BBPWrite_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_RFWrite_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); -#endif // DBG // -#endif // RALINK_28xx_QA // - - -VOID ATEAsicSwitchChannel( - IN PRTMP_ADAPTER pAd); - -VOID ATEAsicAdjustTxPower( - IN PRTMP_ADAPTER pAd); - -VOID ATEDisableAsicProtect( - IN PRTMP_ADAPTER pAd); - -CHAR ATEConvertToRssi( - IN PRTMP_ADAPTER pAd, - IN CHAR Rssi, - IN UCHAR RssiNumber); - -VOID ATESampleRssi( - IN PRTMP_ADAPTER pAd, - IN PRXWI_STRUC pRxWI); - - -#ifdef CONFIG_STA_SUPPORT -VOID RTMPStationStop( - IN PRTMP_ADAPTER pAd); - -VOID RTMPStationStart( - IN PRTMP_ADAPTER pAd); -#endif // CONFIG_STA_SUPPORT // -#endif // __ATE_H__ // diff --git a/drivers/staging/rt3090/rt_config.h b/drivers/staging/rt3090/rt_config.h deleted file mode 100644 index 005142dfa25760632f353bb7189fe7d03117abfb..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rt_config.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rt_config.h - - Abstract: - Central header file to maintain all include files for all NDIS - miniport driver routines. - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Paul Lin 08-01-2002 created - -*/ -#ifndef __RT_CONFIG_H__ -#define __RT_CONFIG_H__ - -#include "rtmp_type.h" -#include "rtmp_os.h" - -#include "rtmp_def.h" -#include "rtmp_chip.h" -#include "rtmp_timer.h" - -#include "oid.h" -#include "mlme.h" -#include "wpa.h" -#include "crypt_md5.h" -#include "crypt_sha2.h" -#include "crypt_hmac.h" -#include "rtmp.h" -#include "ap.h" -#include "dfs.h" -#include "chlist.h" -#include "spectrum.h" - -#ifdef MLME_EX -#include "mlme_ex_def.h" -#include "mlme_ex.h" -#endif // MLME_EX // - -#include "eeprom.h" -#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) -#include "rtmp_mcu.h" -#endif - - - -#undef AP_WSC_INCLUDED -#undef STA_WSC_INCLUDED -#undef WSC_INCLUDED - - - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - -#ifdef BLOCK_NET_IF -#include "netif_block.h" -#endif // BLOCK_NET_IF // - -#ifdef IGMP_SNOOP_SUPPORT -#include "igmp_snoop.h" -#endif // IGMP_SNOOP_SUPPORT // - -#ifdef RALINK_ATE -#include "rt_ate.h" -#endif // RALINK_ATE // - -#ifdef RALINK_28xx_QA -#ifndef RALINK_ATE -#error "For supporting QA GUI, please set HAS_ATE=y and HAS_28xx_QA=y." -#endif // RALINK_ATE // -#endif // RALINK_28xx_QA // - - - - -#if defined(AP_WSC_INCLUDED) || defined(STA_WSC_INCLUDED) -#define WSC_INCLUDED -#endif - - -#ifdef CONFIG_STA_SUPPORT -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT -#ifndef WPA_SUPPLICANT_SUPPORT -#error "Build for being controlled by NetworkManager or wext, please set HAS_WPA_SUPPLICANT=y and HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y" -#endif // WPA_SUPPLICANT_SUPPORT // -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - -#endif // CONFIG_STA_SUPPORT // - - - -#ifdef IKANOS_VX_1X0 -#include "vr_ikans.h" -#endif // IKANOS_VX_1X0 // - - - -#endif // __RT_CONFIG_H__ diff --git a/drivers/staging/rt3090/rt_linux.c b/drivers/staging/rt3090/rt_linux.c deleted file mode 100644 index 9b94aa6eb904043d71591a3507049fabd06fab3b..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rt_linux.c +++ /dev/null @@ -1,1624 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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 "rt_config.h" - -ULONG RTDebugLevel = RT_DEBUG_ERROR; - - -// for wireless system event message -char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = { - // system status event - "had associated successfully", /* IW_ASSOC_EVENT_FLAG */ - "had disassociated", /* IW_DISASSOC_EVENT_FLAG */ - "had deauthenticated", /* IW_DEAUTH_EVENT_FLAG */ - "had been aged-out and disassociated", /* IW_AGEOUT_EVENT_FLAG */ - "occurred CounterMeasures attack", /* IW_COUNTER_MEASURES_EVENT_FLAG */ - "occurred replay counter different in Key Handshaking", /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */ - "occurred RSNIE different in Key Handshaking", /* IW_RSNIE_DIFF_EVENT_FLAG */ - "occurred MIC different in Key Handshaking", /* IW_MIC_DIFF_EVENT_FLAG */ - "occurred ICV error in RX", /* IW_ICV_ERROR_EVENT_FLAG */ - "occurred MIC error in RX", /* IW_MIC_ERROR_EVENT_FLAG */ - "Group Key Handshaking timeout", /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */ - "Pairwise Key Handshaking timeout", /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */ - "RSN IE sanity check failure", /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */ - "set key done in WPA/WPAPSK", /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */ - "set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */ - "connects with our wireless client", /* IW_STA_LINKUP_EVENT_FLAG */ - "disconnects with our wireless client", /* IW_STA_LINKDOWN_EVENT_FLAG */ - "scan completed" /* IW_SCAN_COMPLETED_EVENT_FLAG */ - "scan terminate!! Busy!! Enqueue fail!!" /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */ - }; - -// for wireless IDS_spoof_attack event message -char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = { - "detected conflict SSID", /* IW_CONFLICT_SSID_EVENT_FLAG */ - "detected spoofed association response", /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */ - "detected spoofed reassociation responses", /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */ - "detected spoofed probe response", /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */ - "detected spoofed beacon", /* IW_SPOOF_BEACON_EVENT_FLAG */ - "detected spoofed disassociation", /* IW_SPOOF_DISASSOC_EVENT_FLAG */ - "detected spoofed authentication", /* IW_SPOOF_AUTH_EVENT_FLAG */ - "detected spoofed deauthentication", /* IW_SPOOF_DEAUTH_EVENT_FLAG */ - "detected spoofed unknown management frame", /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */ - "detected replay attack" /* IW_REPLAY_ATTACK_EVENT_FLAG */ - }; - -// for wireless IDS_flooding_attack event message -char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = { - "detected authentication flooding", /* IW_FLOOD_AUTH_EVENT_FLAG */ - "detected association request flooding", /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */ - "detected reassociation request flooding", /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */ - "detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */ - "detected disassociation flooding", /* IW_FLOOD_DISASSOC_EVENT_FLAG */ - "detected deauthentication flooding", /* IW_FLOOD_DEAUTH_EVENT_FLAG */ - "detected 802.1x eap-request flooding" /* IW_FLOOD_EAP_REQ_EVENT_FLAG */ - }; - - -/* timeout -- ms */ -VOID RTMP_SetPeriodicTimer( - IN NDIS_MINIPORT_TIMER *pTimer, - IN unsigned long timeout) -{ - timeout = ((timeout*OS_HZ) / 1000); - pTimer->expires = jiffies + timeout; - add_timer(pTimer); -} - -/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */ -VOID RTMP_OS_Init_Timer( - IN PRTMP_ADAPTER pAd, - IN NDIS_MINIPORT_TIMER *pTimer, - IN TIMER_FUNCTION function, - IN PVOID data) -{ - init_timer(pTimer); - pTimer->data = (unsigned long)data; - pTimer->function = function; -} - - -VOID RTMP_OS_Add_Timer( - IN NDIS_MINIPORT_TIMER *pTimer, - IN unsigned long timeout) -{ - if (timer_pending(pTimer)) - return; - - timeout = ((timeout*OS_HZ) / 1000); - pTimer->expires = jiffies + timeout; - add_timer(pTimer); -} - -VOID RTMP_OS_Mod_Timer( - IN NDIS_MINIPORT_TIMER *pTimer, - IN unsigned long timeout) -{ - timeout = ((timeout*OS_HZ) / 1000); - mod_timer(pTimer, jiffies + timeout); -} - -VOID RTMP_OS_Del_Timer( - IN NDIS_MINIPORT_TIMER *pTimer, - OUT BOOLEAN *pCancelled) -{ - if (timer_pending(pTimer)) - { - *pCancelled = del_timer_sync(pTimer); - } - else - { - *pCancelled = TRUE; - } - -} - -VOID RTMP_OS_Release_Packet( - IN PRTMP_ADAPTER pAd, - IN PQUEUE_ENTRY pEntry) -{ - //RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry); -} - -// Unify all delay routine by using udelay -VOID RTMPusecDelay( - IN ULONG usec) -{ - ULONG i; - - for (i = 0; i < (usec / 50); i++) - udelay(50); - - if (usec % 50) - udelay(usec % 50); -} - -void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time) -{ - time->u.LowPart = jiffies; -} - -// pAd MUST allow to be NULL -NDIS_STATUS os_alloc_mem( - IN RTMP_ADAPTER *pAd, - OUT UCHAR **mem, - IN ULONG size) -{ - *mem = (PUCHAR) kmalloc(size, GFP_ATOMIC); - if (*mem) - return (NDIS_STATUS_SUCCESS); - else - return (NDIS_STATUS_FAILURE); -} - -// pAd MUST allow to be NULL -NDIS_STATUS os_free_mem( - IN PRTMP_ADAPTER pAd, - IN PVOID mem) -{ - - ASSERT(mem); - kfree(mem); - return (NDIS_STATUS_SUCCESS); -} - - - - -PNDIS_PACKET RtmpOSNetPktAlloc( - IN RTMP_ADAPTER *pAd, - IN int size) -{ - struct sk_buff *skb; - /* Add 2 more bytes for ip header alignment*/ - skb = dev_alloc_skb(size+2); - - return ((PNDIS_PACKET)skb); -} - - -PNDIS_PACKET RTMP_AllocateFragPacketBuffer( - IN PRTMP_ADAPTER pAd, - IN ULONG Length) -{ - struct sk_buff *pkt; - - pkt = dev_alloc_skb(Length); - - if (pkt == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("can't allocate frag rx %ld size packet\n",Length)); - } - - if (pkt) - { - RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); - } - - return (PNDIS_PACKET) pkt; -} - - -PNDIS_PACKET RTMP_AllocateTxPacketBuffer( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress) -{ - struct sk_buff *pkt; - - pkt = dev_alloc_skb(Length); - - if (pkt == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("can't allocate tx %ld size packet\n",Length)); - } - - if (pkt) - { - RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); - *VirtualAddress = (PVOID) pkt->data; - } - else - { - *VirtualAddress = (PVOID) NULL; - } - - return (PNDIS_PACKET) pkt; -} - - -VOID build_tx_packet( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN PUCHAR pFrame, - IN ULONG FrameLen) -{ - - struct sk_buff *pTxPkt; - - ASSERT(pPacket); - pTxPkt = RTPKT_TO_OSPKT(pPacket); - - NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen); -} - -VOID RTMPFreeAdapter( - IN PRTMP_ADAPTER pAd) -{ - POS_COOKIE os_cookie; - int index; - - os_cookie=(POS_COOKIE)pAd->OS_Cookie; - - if (pAd->BeaconBuf) - kfree(pAd->BeaconBuf); - - - NdisFreeSpinLock(&pAd->MgmtRingLock); - -#ifdef RTMP_MAC_PCI - NdisFreeSpinLock(&pAd->RxRingLock); -#ifdef RT3090 -NdisFreeSpinLock(&pAd->McuCmdLock); -#endif // RT3090 // -#endif // RTMP_MAC_PCI // - - for (index =0 ; index < NUM_OF_TX_RING; index++) - { - NdisFreeSpinLock(&pAd->TxSwQueueLock[index]); - NdisFreeSpinLock(&pAd->DeQueueLock[index]); - pAd->DeQueueRunning[index] = FALSE; - } - - NdisFreeSpinLock(&pAd->irq_lock); - - - vfree(pAd); // pci_free_consistent(os_cookie->pci_dev,sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa); - if (os_cookie) - kfree(os_cookie); -} - -BOOLEAN OS_Need_Clone_Packet(void) -{ - return (FALSE); -} - - - -/* - ======================================================================== - - Routine Description: - clone an input NDIS PACKET to another one. The new internally created NDIS PACKET - must have only one NDIS BUFFER - return - byte copied. 0 means can't create NDIS PACKET - NOTE: internally created NDIS_PACKET should be destroyed by RTMPFreeNdisPacket - - Arguments: - pAd Pointer to our adapter - pInsAMSDUHdr EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU. - *pSrcTotalLen return total packet length. This lenght is calculated with 802.3 format packet. - - Return Value: - NDIS_STATUS_SUCCESS - NDIS_STATUS_FAILURE - - Note: - - ======================================================================== -*/ -NDIS_STATUS RTMPCloneNdisPacket( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN pInsAMSDUHdr, - IN PNDIS_PACKET pInPacket, - OUT PNDIS_PACKET *ppOutPacket) -{ - - struct sk_buff *pkt; - - ASSERT(pInPacket); - ASSERT(ppOutPacket); - - // 1. Allocate a packet - pkt = dev_alloc_skb(2048); - - if (pkt == NULL) - { - return NDIS_STATUS_FAILURE; - } - - skb_put(pkt, GET_OS_PKT_LEN(pInPacket)); - NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket), GET_OS_PKT_LEN(pInPacket)); - *ppOutPacket = OSPKT_TO_RTPKT(pkt); - - - RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); - - printk("###Clone###\n"); - - return NDIS_STATUS_SUCCESS; -} - - -// the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket() -NDIS_STATUS RTMPAllocateNdisPacket( - IN PRTMP_ADAPTER pAd, - OUT PNDIS_PACKET *ppPacket, - IN PUCHAR pHeader, - IN UINT HeaderLen, - IN PUCHAR pData, - IN UINT DataLen) -{ - PNDIS_PACKET pPacket; - ASSERT(pData); - ASSERT(DataLen); - - // 1. Allocate a packet - pPacket = (PNDIS_PACKET *) dev_alloc_skb(HeaderLen + DataLen + RTMP_PKT_TAIL_PADDING); - if (pPacket == NULL) - { - *ppPacket = NULL; -#ifdef DEBUG - printk("RTMPAllocateNdisPacket Fail\n\n"); -#endif - return NDIS_STATUS_FAILURE; - } - - // 2. clone the frame content - if (HeaderLen > 0) - NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen); - if (DataLen > 0) - NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData, DataLen); - - // 3. update length of packet - skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen+DataLen); - - RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); -// printk("%s : pPacket = %p, len = %d\n", __FUNCTION__, pPacket, GET_OS_PKT_LEN(pPacket)); - *ppPacket = pPacket; - return NDIS_STATUS_SUCCESS; -} - -/* - ======================================================================== - Description: - This routine frees a miniport internally allocated NDIS_PACKET and its - corresponding NDIS_BUFFER and allocated memory. - ======================================================================== -*/ -VOID RTMPFreeNdisPacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket) -{ - dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket)); -} - - -// IRQL = DISPATCH_LEVEL -// NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same -// scatter gather buffer -NDIS_STATUS Sniff2BytesFromNdisBuffer( - IN PNDIS_BUFFER pFirstBuffer, - IN UCHAR DesiredOffset, - OUT PUCHAR pByte0, - OUT PUCHAR pByte1) -{ - *pByte0 = *(PUCHAR)(pFirstBuffer + DesiredOffset); - *pByte1 = *(PUCHAR)(pFirstBuffer + DesiredOffset + 1); - - return NDIS_STATUS_SUCCESS; -} - - -void RTMP_QueryPacketInfo( - IN PNDIS_PACKET pPacket, - OUT PACKET_INFO *pPacketInfo, - OUT PUCHAR *pSrcBufVA, - OUT UINT *pSrcBufLen) -{ - pPacketInfo->BufferCount = 1; - pPacketInfo->pFirstBuffer = (PNDIS_BUFFER)GET_OS_PKT_DATAPTR(pPacket); - pPacketInfo->PhysicalBufferCount = 1; - pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket); - - *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); - *pSrcBufLen = GET_OS_PKT_LEN(pPacket); -} - -void RTMP_QueryNextPacketInfo( - IN PNDIS_PACKET *ppPacket, - OUT PACKET_INFO *pPacketInfo, - OUT PUCHAR *pSrcBufVA, - OUT UINT *pSrcBufLen) -{ - PNDIS_PACKET pPacket = NULL; - - if (*ppPacket) - pPacket = GET_OS_PKT_NEXT(*ppPacket); - - if (pPacket) - { - pPacketInfo->BufferCount = 1; - pPacketInfo->pFirstBuffer = (PNDIS_BUFFER)GET_OS_PKT_DATAPTR(pPacket); - pPacketInfo->PhysicalBufferCount = 1; - pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket); - - *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); - *pSrcBufLen = GET_OS_PKT_LEN(pPacket); - *ppPacket = GET_OS_PKT_NEXT(pPacket); - } - else - { - pPacketInfo->BufferCount = 0; - pPacketInfo->pFirstBuffer = NULL; - pPacketInfo->PhysicalBufferCount = 0; - pPacketInfo->TotalPacketLength = 0; - - *pSrcBufVA = NULL; - *pSrcBufLen = 0; - *ppPacket = NULL; - } -} - - -PNDIS_PACKET DuplicatePacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR FromWhichBSSID) -{ - struct sk_buff *skb; - PNDIS_PACKET pRetPacket = NULL; - USHORT DataSize; - UCHAR *pData; - - DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); - pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); - - - skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG); - if (skb) - { - skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); - pRetPacket = OSPKT_TO_RTPKT(skb); - } - - - return pRetPacket; - -} - -PNDIS_PACKET duplicate_pkt( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pHeader802_3, - IN UINT HdrLen, - IN PUCHAR pData, - IN ULONG DataSize, - IN UCHAR FromWhichBSSID) -{ - struct sk_buff *skb; - PNDIS_PACKET pPacket = NULL; - - - if ((skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL) - { - skb_reserve(skb, 2); - NdisMoveMemory(skb_tail_pointer(skb), pHeader802_3, HdrLen); - skb_put(skb, HdrLen); - NdisMoveMemory(skb_tail_pointer(skb), pData, DataSize); - skb_put(skb, DataSize); - skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); - pPacket = OSPKT_TO_RTPKT(skb); - } - - return pPacket; -} - - -#define TKIP_TX_MIC_SIZE 8 -PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket) -{ - struct sk_buff *skb, *newskb; - - - skb = RTPKT_TO_OSPKT(pPacket); - if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE) - { - // alloc a new skb and copy the packet - newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC); - dev_kfree_skb_any(skb); - if (newskb == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n")); - return NULL; - } - skb = newskb; - } - - return OSPKT_TO_RTPKT(skb); - - -} - - - - -PNDIS_PACKET ClonePacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN PUCHAR pData, - IN ULONG DataSize) -{ - struct sk_buff *pRxPkt; - struct sk_buff *pClonedPkt; - - ASSERT(pPacket); - pRxPkt = RTPKT_TO_OSPKT(pPacket); - - // clone the packet - pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG); - - if (pClonedPkt) - { - // set the correct dataptr and data len - pClonedPkt->dev = pRxPkt->dev; - pClonedPkt->data = pData; - pClonedPkt->len = DataSize; - pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len; - ASSERT(DataSize < 1530); - } - return pClonedPkt; -} - -// -// change OS packet DataPtr and DataLen -// -void update_os_packet_info( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) -{ - struct sk_buff *pOSPkt; - - ASSERT(pRxBlk->pRxPacket); - pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); - - pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); - pOSPkt->data = pRxBlk->pData; - pOSPkt->len = pRxBlk->DataSize; - pOSPkt->tail = pOSPkt->data + pOSPkt->len; -} - - -void wlan_802_11_to_802_3_packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN PUCHAR pHeader802_3, - IN UCHAR FromWhichBSSID) -{ - struct sk_buff *pOSPkt; - - ASSERT(pRxBlk->pRxPacket); - ASSERT(pHeader802_3); - - pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); - - pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); - pOSPkt->data = pRxBlk->pData; - pOSPkt->len = pRxBlk->DataSize; - pOSPkt->tail = pOSPkt->data + pOSPkt->len; - - // - // copy 802.3 header - // - // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3); -#endif // CONFIG_STA_SUPPORT // - } - - - -void announce_802_3_packet( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket) -{ - - struct sk_buff *pRxPkt; -#ifdef INF_AMAZON_PPA - int ret = 0; - unsigned int ppa_flags = 0; /* reserved for now */ -#endif // INF_AMAZON_PPA // - - ASSERT(pPacket); - - pRxPkt = RTPKT_TO_OSPKT(pPacket); - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - - /* Push up the protocol stack */ -#ifdef IKANOS_VX_1X0 - IKANOS_DataFrameRx(pAd, pRxPkt->dev, pRxPkt, pRxPkt->len); -#else -#ifdef INF_AMAZON_SE -#ifdef BG_FT_SUPPORT - BG_FTPH_PacketFromApHandle(pRxPkt); - return; -#endif // BG_FT_SUPPORT // -#endif // INF_AMAZON_SE // - pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); - -#ifdef INF_AMAZON_PPA - if (ppa_hook_directpath_send_fn && pAd->PPAEnable==TRUE ) - { - memset(pRxPkt->head,0,pRxPkt->data-pRxPkt->head-14); - DBGPRINT(RT_DEBUG_TRACE, ("ppa_hook_directpath_send_fn rx :ret:%d headroom:%d dev:%s pktlen:%d<===\n",ret,skb_headroom(pRxPkt) - ,pRxPkt->dev->name,pRxPkt->len)); - hex_dump("rx packet", pRxPkt->data, 32); - ret = ppa_hook_directpath_send_fn(pAd->g_if_id, pRxPkt, pRxPkt->len, ppa_flags); - pRxPkt=NULL; - return; - - } -#endif // INF_AMAZON_PPA // - -//#ifdef CONFIG_5VT_ENHANCE -// *(int*)(pRxPkt->cb) = BRIDGE_TAG; -//#endif - - { - netif_rx(pRxPkt); - } - -#endif // IKANOS_VX_1X0 // -} - - -PRTMP_SCATTER_GATHER_LIST -rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg) -{ - sg->NumberOfElements = 1; - sg->Elements[0].Address = GET_OS_PKT_DATAPTR(pPacket); - sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket); - return (sg); -} - -void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen) -{ - unsigned char *pt; - int x; - - if (RTDebugLevel < RT_DEBUG_TRACE) - return; - - pt = pSrcBufVA; - printk("%s: %p, len = %d\n",str, pSrcBufVA, SrcBufLen); - for (x=0; x= 15 - - //union iwreq_data wrqu; - PSTRING pBuf = NULL, pBufPtr = NULL; - USHORT event, type, BufLen; - UCHAR event_table_len = 0; - - type = Event_flag & 0xFF00; - event = Event_flag & 0x00FF; - - switch (type) - { - case IW_SYS_EVENT_FLAG_START: - event_table_len = IW_SYS_EVENT_TYPE_NUM; - break; - - case IW_SPOOF_EVENT_FLAG_START: - event_table_len = IW_SPOOF_EVENT_TYPE_NUM; - break; - - case IW_FLOOD_EVENT_FLAG_START: - event_table_len = IW_FLOOD_EVENT_TYPE_NUM; - break; - } - - if (event_table_len == 0) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s : The type(%0x02x) is not valid.\n", __FUNCTION__, type)); - return; - } - - if (event >= event_table_len) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s : The event(%0x02x) is not valid.\n", __FUNCTION__, event)); - return; - } - - //Allocate memory and copy the msg. - if((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL) - { - //Prepare the payload - memset(pBuf, 0, IW_CUSTOM_MAX_LEN); - - pBufPtr = pBuf; - - if (pAddr) - pBufPtr += sprintf(pBufPtr, "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", PRINT_MAC(pAddr)); - else if (BssIdx < MAX_MBSSID_NUM) - pBufPtr += sprintf(pBufPtr, "(RT2860) BSS(ra%d) ", BssIdx); - else - pBufPtr += sprintf(pBufPtr, "(RT2860) "); - - if (type == IW_SYS_EVENT_FLAG_START) - pBufPtr += sprintf(pBufPtr, "%s", pWirelessSysEventText[event]); - else if (type == IW_SPOOF_EVENT_FLAG_START) - pBufPtr += sprintf(pBufPtr, "%s (RSSI=%d)", pWirelessSpoofEventText[event], Rssi); - else if (type == IW_FLOOD_EVENT_FLAG_START) - pBufPtr += sprintf(pBufPtr, "%s", pWirelessFloodEventText[event]); - else - pBufPtr += sprintf(pBufPtr, "%s", "unknown event"); - - pBufPtr[pBufPtr - pBuf] = '\0'; - BufLen = pBufPtr - pBuf; - - RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, Event_flag, NULL, (PUCHAR)pBuf, BufLen); - //DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __FUNCTION__, pBuf)); - - kfree(pBuf); - } - else - DBGPRINT(RT_DEBUG_ERROR, ("%s : Can't allocate memory for wireless event.\n", __FUNCTION__)); -#else - DBGPRINT(RT_DEBUG_ERROR, ("%s : The Wireless Extension MUST be v15 or newer.\n", __FUNCTION__)); -#endif /* WIRELESS_EXT >= 15 */ -} - - - - -#ifdef CONFIG_STA_SUPPORT -void send_monitor_packets( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk) -{ - struct sk_buff *pOSPkt; - wlan_ng_prism2_header *ph; - int rate_index = 0; - USHORT header_len = 0; - UCHAR temp_header[40] = {0}; - - u_int32_t ralinkrate[256] = {2,4,11,22, 12,18,24,36,48,72,96, 108, 109, 110, 111, 112, 13, 26, 39, 52,78,104, 117, 130, 26, 52, 78,104, 156, 208, 234, 260, 27, 54,81,108,162, 216, 243, 270, // Last 38 - 54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115, 130, 144, 29, 59,87,115, 173, 230,260, 288, 30, 60,90,120,180,240,270,300,60,120,180,240,360,480,540,600, 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,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80}; - - - ASSERT(pRxBlk->pRxPacket); - if (pRxBlk->DataSize < 10) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too small! (%d)\n", __FUNCTION__, pRxBlk->DataSize)); - goto err_free_sk_buff; - } - - if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%d)\n", __FUNCTION__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header))); - goto err_free_sk_buff; - } - - pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); - pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0); - if (pRxBlk->pHeader->FC.Type == BTYPE_DATA) - { - pRxBlk->DataSize -= LENGTH_802_11; - if ((pRxBlk->pHeader->FC.ToDs == 1) && - (pRxBlk->pHeader->FC.FrDs == 1)) - header_len = LENGTH_802_11_WITH_ADDR4; - else - header_len = LENGTH_802_11; - - // QOS - if (pRxBlk->pHeader->FC.SubType & 0x08) - { - header_len += 2; - // Data skip QOS contorl field - pRxBlk->DataSize -=2; - } - - // Order bit: A-Ralink or HTC+ - if (pRxBlk->pHeader->FC.Order) - { - header_len += 4; - // Data skip HTC contorl field - pRxBlk->DataSize -= 4; - } - - // Copy Header - if (header_len <= 40) - NdisMoveMemory(temp_header, pRxBlk->pData, header_len); - - // skip HW padding - if (pRxBlk->RxD.L2PAD) - pRxBlk->pData += (header_len + 2); - else - pRxBlk->pData += header_len; - } //end if - - - if (pRxBlk->DataSize < pOSPkt->len) { - skb_trim(pOSPkt,pRxBlk->DataSize); - } else { - skb_put(pOSPkt,(pRxBlk->DataSize - pOSPkt->len)); - } //end if - - if ((pRxBlk->pData - pOSPkt->data) > 0) { - skb_put(pOSPkt,(pRxBlk->pData - pOSPkt->data)); - skb_pull(pOSPkt,(pRxBlk->pData - pOSPkt->data)); - } //end if - - if (skb_headroom(pOSPkt) < (sizeof(wlan_ng_prism2_header)+ header_len)) { - if (pskb_expand_head(pOSPkt, (sizeof(wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) { - DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __FUNCTION__)); - goto err_free_sk_buff; - } //end if - } //end if - - if (header_len > 0) - NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len); - - ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, sizeof(wlan_ng_prism2_header)); - NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header)); - - ph->msgcode = DIDmsg_lnxind_wlansniffrm; - ph->msglen = sizeof(wlan_ng_prism2_header); - strcpy((PSTRING) ph->devname, (PSTRING) pAd->net_dev->name); - - ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; - ph->hosttime.status = 0; - ph->hosttime.len = 4; - ph->hosttime.data = jiffies; - - ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; - ph->mactime.status = 0; - ph->mactime.len = 0; - ph->mactime.data = 0; - - ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; - ph->istx.status = 0; - ph->istx.len = 0; - ph->istx.data = 0; - - ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; - ph->channel.status = 0; - ph->channel.len = 4; - - ph->channel.data = (u_int32_t)pAd->CommonCfg.Channel; - - ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; - ph->rssi.status = 0; - ph->rssi.len = 4; - ph->rssi.data = (u_int32_t)RTMPMaxRssi(pAd, ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0, RSSI_0), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI1, RSSI_1), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2, RSSI_2));; - - ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal; - ph->signal.status = 0; - ph->signal.len = 4; - ph->signal.data = 0; //rssi + noise; - - ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise; - ph->noise.status = 0; - ph->noise.len = 4; - ph->noise.data = 0; - -#ifdef DOT11_N_SUPPORT - if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX) - { - rate_index = 16 + ((UCHAR)pRxBlk->pRxWI->BW *16) + ((UCHAR)pRxBlk->pRxWI->ShortGI *32) + ((UCHAR)pRxBlk->pRxWI->MCS); - } - else -#endif // DOT11_N_SUPPORT // - if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM) - rate_index = (UCHAR)(pRxBlk->pRxWI->MCS) + 4; - else - rate_index = (UCHAR)(pRxBlk->pRxWI->MCS); - if (rate_index < 0) - rate_index = 0; - if (rate_index > 255) - rate_index = 255; - - ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; - ph->rate.status = 0; - ph->rate.len = 4; - ph->rate.data = ralinkrate[rate_index]; - - ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; - ph->frmlen.status = 0; - ph->frmlen.len = 4; - ph->frmlen.data = (u_int32_t)pRxBlk->DataSize; - - - pOSPkt->pkt_type = PACKET_OTHERHOST; - pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev); - pOSPkt->ip_summed = CHECKSUM_NONE; - netif_rx(pOSPkt); - - return; - -err_free_sk_buff: - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); - return; - -} -#endif // CONFIG_STA_SUPPORT // - - - -/******************************************************************************* - - File open/close related functions. - - *******************************************************************************/ -RTMP_OS_FD RtmpOSFileOpen(char *pPath, int flag, int mode) -{ - struct file *filePtr; - - filePtr = filp_open(pPath, flag, 0); - if (IS_ERR(filePtr)) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s(): Error %ld opening %s\n", __FUNCTION__, -PTR_ERR(filePtr), pPath)); - } - - return (RTMP_OS_FD)filePtr; -} - -int RtmpOSFileClose(RTMP_OS_FD osfd) -{ - filp_close(osfd, NULL); - return 0; -} - - -void RtmpOSFileSeek(RTMP_OS_FD osfd, int offset) -{ - osfd->f_pos = offset; -} - - -int RtmpOSFileRead(RTMP_OS_FD osfd, char *pDataPtr, int readLen) -{ - // The object must have a read method - if (osfd->f_op && osfd->f_op->read) - { - return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos); - } - else - { - DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n")); - return -1; - } -} - - -int RtmpOSFileWrite(RTMP_OS_FD osfd, char *pDataPtr, int writeLen) -{ - return osfd->f_op->write(osfd, pDataPtr, (size_t)writeLen, &osfd->f_pos); -} - - -void RtmpOSFSInfoChange(RTMP_OS_FS_INFO *pOSFSInfo, BOOLEAN bSet) -{ - if (bSet) - { - // Save uid and gid used for filesystem access. - // Set user and group to 0 (root) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - pOSFSInfo->fsuid= current->fsuid; - pOSFSInfo->fsgid = current->fsgid; - current->fsuid = current->fsgid = 0; -#else - pOSFSInfo->fsuid = current_fsuid(); - pOSFSInfo->fsgid = current_fsgid(); -#endif - pOSFSInfo->fs = get_fs(); - set_fs(KERNEL_DS); - } - else - { - set_fs(pOSFSInfo->fs); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - current->fsuid = pOSFSInfo->fsuid; - current->fsgid = pOSFSInfo->fsgid; -#endif - } -} - - - -/******************************************************************************* - - Task create/management/kill related functions. - - *******************************************************************************/ -NDIS_STATUS RtmpOSTaskKill( - IN RTMP_OS_TASK *pTask) -{ - RTMP_ADAPTER *pAd; - int ret = NDIS_STATUS_FAILURE; - - pAd = (RTMP_ADAPTER *)pTask->priv; - -#ifdef KTHREAD_SUPPORT - if (pTask->kthread_task) - { - kthread_stop(pTask->kthread_task); - ret = NDIS_STATUS_SUCCESS; - } -#else - CHECK_PID_LEGALITY(pTask->taskPID) - { - printk("Terminate the task(%s) with pid(%d)!\n", pTask->taskName, GET_PID_NUMBER(pTask->taskPID)); - mb(); - pTask->task_killed = 1; - mb(); - ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1); - if (ret) - { - printk(KERN_WARNING "kill task(%s) with pid(%d) failed(retVal=%d)!\n", - pTask->taskName, GET_PID_NUMBER(pTask->taskPID), ret); - } - else - { - wait_for_completion(&pTask->taskComplete); - pTask->taskPID = THREAD_PID_INIT_VALUE; - pTask->task_killed = 0; - ret = NDIS_STATUS_SUCCESS; - } - } -#endif - - return ret; - -} - - -INT RtmpOSTaskNotifyToExit( - IN RTMP_OS_TASK *pTask) -{ - -#ifndef KTHREAD_SUPPORT - complete_and_exit(&pTask->taskComplete, 0); -#endif - - return 0; -} - - -void RtmpOSTaskCustomize( - IN RTMP_OS_TASK *pTask) -{ - -#ifndef KTHREAD_SUPPORT - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - daemonize((PSTRING)&pTask->taskName[0]/*"%s",pAd->net_dev->name*/); - - allow_signal(SIGTERM); - allow_signal(SIGKILL); - current->flags |= PF_NOFREEZE; -#else - unsigned long flags; - - daemonize(); - reparent_to_init(); - strcpy(current->comm, &pTask->taskName[0]); - - siginitsetinv(¤t->blocked, sigmask(SIGTERM) | sigmask(SIGKILL)); - - /* Allow interception of SIGKILL only - * Don't allow other signals to interrupt the transmission */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - spin_lock_irqsave(¤t->sigmask_lock, flags); - flush_signals(current); - recalc_sigpending(current); - spin_unlock_irqrestore(¤t->sigmask_lock, flags); -#endif -#endif - - /* signal that we've started the thread */ - complete(&pTask->taskComplete); - -#endif -} - - -NDIS_STATUS RtmpOSTaskAttach( - IN RTMP_OS_TASK *pTask, - IN int (*fn)(void *), - IN void *arg) -{ - NDIS_STATUS status = NDIS_STATUS_SUCCESS; - pid_t pid_number = -1; - -#ifdef KTHREAD_SUPPORT - pTask->task_killed = 0; - pTask->kthread_task = NULL; - pTask->kthread_task = kthread_run(fn, arg, pTask->taskName); - if (IS_ERR(pTask->kthread_task)) - status = NDIS_STATUS_FAILURE; -#else - pid_number = kernel_thread(fn, arg, RTMP_OS_MGMT_TASK_FLAGS); - if (pid_number < 0) - { - DBGPRINT (RT_DEBUG_ERROR, ("Attach task(%s) failed!\n", pTask->taskName)); - status = NDIS_STATUS_FAILURE; - } - else - { - pTask->taskPID = GET_PID(pid_number); - - // Wait for the thread to start - wait_for_completion(&pTask->taskComplete); - status = NDIS_STATUS_SUCCESS; - } -#endif - return status; -} - - -NDIS_STATUS RtmpOSTaskInit( - IN RTMP_OS_TASK *pTask, - IN PSTRING pTaskName, - IN VOID *pPriv) -{ - int len; - - ASSERT(pTask); - -#ifndef KTHREAD_SUPPORT - NdisZeroMemory((PUCHAR)(pTask), sizeof(RTMP_OS_TASK)); -#endif - - len = strlen(pTaskName); - len = len > (RTMP_OS_TASK_NAME_LEN -1) ? (RTMP_OS_TASK_NAME_LEN-1) : len; - NdisMoveMemory(&pTask->taskName[0], pTaskName, len); - pTask->priv = pPriv; - -#ifndef KTHREAD_SUPPORT - RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema)); - pTask->taskPID = THREAD_PID_INIT_VALUE; - - init_completion (&pTask->taskComplete); -#endif - - return NDIS_STATUS_SUCCESS; -} - - -void RTMP_IndicateMediaState( - IN PRTMP_ADAPTER pAd) -{ - if (pAd->CommonCfg.bWirelessEvent) - { - if (pAd->IndicateMediaState == NdisMediaStateConnected) - { - RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - } - else - { - RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - } - } -} - - -#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1 -//static struct net_device *alloc_netdev(int sizeof_priv, const char *mask, void (*setup)(struct net_device *)) //sample -struct net_device *alloc_netdev( - int sizeof_priv, - const char *mask, - void (*setup)(struct net_device *)) -{ - struct net_device *dev; - INT alloc_size; - - - /* ensure 32-byte alignment of the private area */ - alloc_size = sizeof (*dev) + sizeof_priv + 31; - - dev = (struct net_device *) kmalloc(alloc_size, GFP_KERNEL); - if (dev == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, - ("alloc_netdev: Unable to allocate device memory.\n")); - return NULL; - } - - memset(dev, 0, alloc_size); - - if (sizeof_priv) - dev->priv = (void *) (((long)(dev + 1) + 31) & ~31); - - setup(dev); - strcpy(dev->name, mask); - - return dev; -} -#endif // LINUX_VERSION_CODE // - - -int RtmpOSWrielessEventSend( - IN RTMP_ADAPTER *pAd, - IN UINT32 eventType, - IN INT flags, - IN PUCHAR pSrcMac, - IN PUCHAR pData, - IN UINT32 dataLen) -{ - union iwreq_data wrqu; - - memset(&wrqu, 0, sizeof(wrqu)); - - if (flags>-1) - wrqu.data.flags = flags; - - if (pSrcMac) - memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN); - - if ((pData!= NULL) && (dataLen > 0)) - wrqu.data.length = dataLen; - - wireless_send_event(pAd->net_dev, eventType, &wrqu, (char *)pData); - return 0; -} - - -int RtmpOSNetDevAddrSet( - IN PNET_DEV pNetDev, - IN PUCHAR pMacAddr) -{ - struct net_device *net_dev; - RTMP_ADAPTER *pAd; - - net_dev = pNetDev; - //pAd = (RTMP_ADAPTER *)net_dev->priv; - pAd=RTMP_OS_NETDEV_GET_PRIV(pNetDev); - -#ifdef CONFIG_STA_SUPPORT - // work-around for the SuSE due to it has it's own interface name management system. - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - NdisZeroMemory(pAd->StaCfg.dev_name, 16); - NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, strlen(net_dev->name)); - } -#endif // CONFIG_STA_SUPPORT // - - NdisMoveMemory(net_dev->dev_addr, pMacAddr, 6); - - return 0; -} - - - -/* - * Assign the network dev name for created Ralink WiFi interface. - */ -static int RtmpOSNetDevRequestName( - IN RTMP_ADAPTER *pAd, - IN PNET_DEV dev, - IN PSTRING pPrefixStr, - IN INT devIdx) -{ - PNET_DEV existNetDev; - STRING suffixName[IFNAMSIZ]; - STRING desiredName[IFNAMSIZ]; - int ifNameIdx, prefixLen, slotNameLen; - int Status; - - - prefixLen = strlen(pPrefixStr); - ASSERT((prefixLen < IFNAMSIZ)); - - for (ifNameIdx = devIdx; ifNameIdx < 32; ifNameIdx++) - { - memset(suffixName, 0, IFNAMSIZ); - memset(desiredName, 0, IFNAMSIZ); - strncpy(&desiredName[0], pPrefixStr, prefixLen); - -#ifdef MULTIPLE_CARD_SUPPORT - if (pAd->MC_RowID >= 0) - sprintf(suffixName, "%02d_%d", pAd->MC_RowID, ifNameIdx); - else -#endif // MULTIPLE_CARD_SUPPORT // - sprintf(suffixName, "%d", ifNameIdx); - - slotNameLen = strlen(suffixName); - ASSERT(((slotNameLen + prefixLen) < IFNAMSIZ)); - strcat(desiredName, suffixName); - - existNetDev = RtmpOSNetDevGetByName(dev, &desiredName[0]); - if (existNetDev == NULL) - break; - else - RtmpOSNetDeviceRefPut(existNetDev); - } - - if(ifNameIdx < 32) - { - strcpy(&dev->name[0], &desiredName[0]); - Status = NDIS_STATUS_SUCCESS; - } - else - { - DBGPRINT(RT_DEBUG_ERROR, - ("Cannot request DevName with preifx(%s) and in range(0~32) as suffix from OS!\n", pPrefixStr)); - Status = NDIS_STATUS_FAILURE; - } - - return Status; -} - - -void RtmpOSNetDevClose( - IN PNET_DEV pNetDev) -{ - dev_close(pNetDev); -} - - -void RtmpOSNetDevFree(PNET_DEV pNetDev) -{ - ASSERT(pNetDev); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - free_netdev(pNetDev); -#else - kfree(pNetDev); -#endif -} - - -INT RtmpOSNetDevAlloc( - IN PNET_DEV *new_dev_p, - IN UINT32 privDataSize) -{ - // assign it as null first. - *new_dev_p = NULL; - - DBGPRINT(RT_DEBUG_TRACE, ("Allocate a net device with private data size=%d!\n", privDataSize)); -#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1 - *new_dev_p = alloc_netdev(privDataSize, "eth%d", ether_setup); -#else - *new_dev_p = alloc_etherdev(privDataSize); -#endif // LINUX_VERSION_CODE // - - if (*new_dev_p) - return NDIS_STATUS_SUCCESS; - else - return NDIS_STATUS_FAILURE; -} - - -PNET_DEV RtmpOSNetDevGetByName(PNET_DEV pNetDev, PSTRING pDevName) -{ - PNET_DEV pTargetNetDev = NULL; - - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName); -#else - ASSERT(pNetDev); - pTargetNetDev = dev_get_by_name(pNetDev->nd_net, pDevName); -#endif -#else - pTargetNetDev = dev_get_by_name(pDevName); -#endif // KERNEL_VERSION(2,6,24) // - -#else - int devNameLen; - - devNameLen = strlen(pDevName); - ASSERT((devNameLen <= IFNAMSIZ)); - - for(pTargetNetDev=dev_base; pTargetNetDev!=NULL; pTargetNetDev=pTargetNetDev->next) - { - if (strncmp(pTargetNetDev->name, pDevName, devNameLen) == 0) - break; - } -#endif // KERNEL_VERSION(2,5,0) // - - return pTargetNetDev; -} - - -void RtmpOSNetDeviceRefPut(PNET_DEV pNetDev) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - /* - every time dev_get_by_name is called, and it has returned a valid struct - net_device*, dev_put should be called afterwards, because otherwise the - machine hangs when the device is unregistered (since dev->refcnt > 1). - */ - if(pNetDev) - dev_put(pNetDev); -#endif // LINUX_VERSION_CODE // -} - - -INT RtmpOSNetDevDestory( - IN RTMP_ADAPTER *pAd, - IN PNET_DEV pNetDev) -{ - - // TODO: Need to fix this - printk("WARNING: This function(%s) not implement yet!!!\n", __FUNCTION__); - return 0; -} - - -void RtmpOSNetDevDetach(PNET_DEV pNetDev) -{ - unregister_netdev(pNetDev); -} - - -int RtmpOSNetDevAttach( - IN PNET_DEV pNetDev, - IN RTMP_OS_NETDEV_OP_HOOK *pDevOpHook) -{ - int ret, rtnl_locked = FALSE; - - DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n")); - // If we need hook some callback function to the net device structrue, now do it. - if (pDevOpHook) - { - PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(pNetDev); - - pNetDev->netdev_ops = pDevOpHook->netdev_ops; - - /* OS specific flags, here we used to indicate if we are virtual interface */ - pNetDev->priv_flags = pDevOpHook->priv_flags; - -#if (WIRELESS_EXT < 21) && (WIRELESS_EXT >= 12) - pNetDev->get_wireless_stats = rt28xx_get_wireless_stats; -#endif - -#ifdef CONFIG_STA_SUPPORT -#if WIRELESS_EXT >= 12 - if (pAd->OpMode == OPMODE_STA) - { - pNetDev->wireless_handlers = &rt28xx_iw_handler_def; - } -#endif //WIRELESS_EXT >= 12 -#endif // CONFIG_STA_SUPPORT // - -#ifdef CONFIG_APSTA_MIXED_SUPPORT -#if WIRELESS_EXT >= 12 - if (pAd->OpMode == OPMODE_AP) - { - pNetDev->wireless_handlers = &rt28xx_ap_iw_handler_def; - } -#endif //WIRELESS_EXT >= 12 -#endif // CONFIG_APSTA_MIXED_SUPPORT // - - // copy the net device mac address to the net_device structure. - NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0], MAC_ADDR_LEN); - - rtnl_locked = pDevOpHook->needProtcted; - } - - if (rtnl_locked) - ret = register_netdevice(pNetDev); - else - ret = register_netdev(pNetDev); - - DBGPRINT(RT_DEBUG_TRACE, ("<---RtmpOSNetDevAttach(), ret=%d\n", ret)); - if (ret == 0) - return NDIS_STATUS_SUCCESS; - else - return NDIS_STATUS_FAILURE; -} - - -PNET_DEV RtmpOSNetDevCreate( - IN RTMP_ADAPTER *pAd, - IN INT devType, - IN INT devNum, - IN INT privMemSize, - IN PSTRING pNamePrefix) -{ - struct net_device *pNetDev = NULL; - int status; - - - /* allocate a new network device */ - status = RtmpOSNetDevAlloc(&pNetDev, 0 /*privMemSize*/); - if (status != NDIS_STATUS_SUCCESS) - { - /* allocation fail, exit */ - DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (%s)...\n", pNamePrefix)); - return NULL; - } - - - /* find a available interface name, max 32 interfaces */ - status = RtmpOSNetDevRequestName(pAd, pNetDev, pNamePrefix, devNum); - if (status != NDIS_STATUS_SUCCESS) - { - /* error! no any available ra name can be used! */ - DBGPRINT(RT_DEBUG_ERROR, ("Assign interface name (%s with suffix 0~32) failed...\n", pNamePrefix)); - RtmpOSNetDevFree(pNetDev); - - return NULL; - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("The name of the new %s interface is %s...\n", pNamePrefix, pNetDev->name)); - } - - return pNetDev; -} diff --git a/drivers/staging/rt3090/rt_linux.h b/drivers/staging/rt3090/rt_linux.h deleted file mode 100644 index a970e780ef274c128082175fbfd3ee48a94310c2..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rt_linux.h +++ /dev/null @@ -1,1034 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rt_linux.h - - Abstract: - - Revision History: - Who When What - --------- ---------- ---------------------------------------------- -*/ - -#ifndef __RT_LINUX_H__ -#define __RT_LINUX_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef INF_AMAZON_PPA -#include -#include -#endif // INF_AMAZON_PPA // - -// load firmware -#define __KERNEL_SYSCALLS__ -#include -#include -#include -#include // for get_unaligned() - -#ifdef KTHREAD_SUPPORT -#include -#include -#endif // KTHREAD_SUPPORT // - -#undef AP_WSC_INCLUDED -#undef STA_WSC_INCLUDED -#undef WSC_INCLUDED - - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - - -#ifdef KTHREAD_SUPPORT -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) -#error "This kerne version doesn't support kthread!!" -#endif -#endif // KTHREAD_SUPPORT // - -/*********************************************************************************** - * Profile related sections - ***********************************************************************************/ - - -#ifdef CONFIG_STA_SUPPORT -#ifdef RTMP_MAC_PCI -#define STA_PROFILE_PATH "/etc/Wireless/RT2860STA/RT2860STA.dat" -#define STA_DRIVER_VERSION "2.1.0.0" -#ifdef MULTIPLE_CARD_SUPPORT -#define CARD_INFO_PATH "/etc/Wireless/RT2860STA/RT2860STACard.dat" -#endif // MULTIPLE_CARD_SUPPORT // -#endif // RTMP_MAC_PCI // - - - -extern const struct iw_handler_def rt28xx_iw_handler_def; -#endif // CONFIG_STA_SUPPORT // - -#ifdef CONFIG_APSTA_MIXED_SUPPORT -extern const struct iw_handler_def rt28xx_ap_iw_handler_def; -#endif // CONFIG_APSTA_MIXED_SUPPORT // - -/*********************************************************************************** - * Compiler related definitions - ***********************************************************************************/ -#undef __inline -#define __inline static inline -#define IN -#define OUT -#define INOUT -#define NDIS_STATUS INT - - -/*********************************************************************************** - * OS Specific definitions and data structures - ***********************************************************************************/ -typedef struct pci_dev * PPCI_DEV; -typedef struct net_device * PNET_DEV; -typedef void * PNDIS_PACKET; -typedef char NDIS_PACKET; -typedef PNDIS_PACKET * PPNDIS_PACKET; -typedef dma_addr_t NDIS_PHYSICAL_ADDRESS; -typedef dma_addr_t * PNDIS_PHYSICAL_ADDRESS; -typedef void * NDIS_HANDLE; -typedef char * PNDIS_BUFFER; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) -typedef struct pid * RTMP_OS_PID; -#else -typedef pid_t RTMP_OS_PID; -#endif - -typedef struct semaphore RTMP_OS_SEM; - -#ifdef RTMP_MAC_PCI -#ifndef PCI_DEVICE -#define PCI_DEVICE(vend,dev) \ - .vendor = (vend), .device = (dev), \ - .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID -#endif // PCI_DEVICE // -#endif // RTMP_MAC_PCI // - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#define RT_MOD_INC_USE_COUNT() \ - if (!try_module_get(THIS_MODULE)) \ - { \ - DBGPRINT(RT_DEBUG_ERROR, ("%s: cannot reserve module\n", __FUNCTION__)); \ - return -1; \ - } - -#define RT_MOD_DEC_USE_COUNT() module_put(THIS_MODULE); -#else -#define RT_MOD_INC_USE_COUNT() MOD_INC_USE_COUNT; -#define RT_MOD_DEC_USE_COUNT() MOD_DEC_USE_COUNT; -#endif - -#define RTMP_INC_REF(_A) 0 -#define RTMP_DEC_REF(_A) 0 -#define RTMP_GET_REF(_A) 0 - - -#if WIRELESS_EXT >= 12 -// This function will be called when query /proc -struct iw_statistics *rt28xx_get_wireless_stats( - IN struct net_device *net_dev); -#endif - - -/*********************************************************************************** - * Network related constant definitions - ***********************************************************************************/ -#ifndef IFNAMSIZ -#define IFNAMSIZ 16 -#endif - -#define ETH_LENGTH_OF_ADDRESS 6 - -#define NDIS_STATUS_SUCCESS 0x00 -#define NDIS_STATUS_FAILURE 0x01 -#define NDIS_STATUS_INVALID_DATA 0x02 -#define NDIS_STATUS_RESOURCES 0x03 - -#define NDIS_SET_PACKET_STATUS(_p, _status) do{} while(0) -#define NdisWriteErrorLogEntry(_a, _b, _c, _d) do{} while(0) - -/* statistics counter */ -#define STATS_INC_RX_PACKETS(_pAd, _dev) -#define STATS_INC_TX_PACKETS(_pAd, _dev) - -#define STATS_INC_RX_BYTESS(_pAd, _dev, len) -#define STATS_INC_TX_BYTESS(_pAd, _dev, len) - -#define STATS_INC_RX_ERRORS(_pAd, _dev) -#define STATS_INC_TX_ERRORS(_pAd, _dev) - -#define STATS_INC_RX_DROPPED(_pAd, _dev) -#define STATS_INC_TX_DROPPED(_pAd, _dev) - - -/*********************************************************************************** - * Ralink Specific network related constant definitions - ***********************************************************************************/ -#define MIN_NET_DEVICE_FOR_AID 0x00 //0x00~0x3f -#define MIN_NET_DEVICE_FOR_MBSSID 0x00 //0x00,0x10,0x20,0x30 -#define MIN_NET_DEVICE_FOR_WDS 0x10 //0x40,0x50,0x60,0x70 -#define MIN_NET_DEVICE_FOR_APCLI 0x20 -#define MIN_NET_DEVICE_FOR_MESH 0x30 -#ifdef CONFIG_STA_SUPPORT -#define MIN_NET_DEVICE_FOR_DLS 0x40 -#endif // CONFIG_STA_SUPPORT // -#define NET_DEVICE_REAL_IDX_MASK 0x0f // for each operation mode, we maximum support 15 entities. - - -#ifdef CONFIG_STA_SUPPORT -#define NDIS_PACKET_TYPE_DIRECTED 0 -#define NDIS_PACKET_TYPE_MULTICAST 1 -#define NDIS_PACKET_TYPE_BROADCAST 2 -#define NDIS_PACKET_TYPE_ALL_MULTICAST 3 -#define NDIS_PACKET_TYPE_PROMISCUOUS 4 -#endif // CONFIG_STA_SUPPORT // - - -/*********************************************************************************** - * OS signaling related constant definitions - ***********************************************************************************/ - - -/*********************************************************************************** - * OS file operation related data structure definitions - ***********************************************************************************/ -typedef struct file* RTMP_OS_FD; - -typedef struct _RTMP_OS_FS_INFO_ -{ - int fsuid; - int fsgid; - mm_segment_t fs; -}RTMP_OS_FS_INFO; - -#define IS_FILE_OPEN_ERR(_fd) IS_ERR((_fd)) - - -/*********************************************************************************** - * OS semaphore related data structure and definitions - ***********************************************************************************/ -struct os_lock { - spinlock_t lock; - unsigned long flags; -}; - -typedef spinlock_t NDIS_SPIN_LOCK; - -// -// spin_lock enhanced for Nested spin lock -// -#define NdisAllocateSpinLock(__lock) \ -{ \ - spin_lock_init((spinlock_t *)(__lock)); \ -} - -#define NdisFreeSpinLock(lock) \ - do{}while(0) - - -#define RTMP_SEM_LOCK(__lock) \ -{ \ - spin_lock_bh((spinlock_t *)(__lock)); \ -} - -#define RTMP_SEM_UNLOCK(__lock) \ -{ \ - spin_unlock_bh((spinlock_t *)(__lock)); \ -} - - -// sample, use semaphore lock to replace IRQ lock, 2007/11/15 -#define RTMP_IRQ_LOCK(__lock, __irqflags) \ -{ \ - __irqflags = 0; \ - spin_lock_bh((spinlock_t *)(__lock)); \ - pAd->irq_disabled |= 1; \ -} - -#define RTMP_IRQ_UNLOCK(__lock, __irqflag) \ -{ \ - pAd->irq_disabled &= 0; \ - spin_unlock_bh((spinlock_t *)(__lock)); \ -} - -#define RTMP_INT_LOCK(__lock, __irqflags) \ -{ \ - spin_lock_irqsave((spinlock_t *)__lock, __irqflags); \ -} - -#define RTMP_INT_UNLOCK(__lock, __irqflag) \ -{ \ - spin_unlock_irqrestore((spinlock_t *)(__lock), ((unsigned long)__irqflag)); \ -} - -#define NdisAcquireSpinLock RTMP_SEM_LOCK -#define NdisReleaseSpinLock RTMP_SEM_UNLOCK - -#ifndef wait_event_interruptible_timeout -#define __wait_event_interruptible_timeout(wq, condition, 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)) { \ - ret = schedule_timeout(ret); \ - if (!ret) \ - break; \ - continue; \ - } \ - ret = -ERESTARTSYS; \ - break; \ - } \ - current->state = TASK_RUNNING; \ - remove_wait_queue(&wq, &__wait); \ -} while (0) - -#define wait_event_interruptible_timeout(wq, condition, timeout) \ -({ \ - long __ret = timeout; \ - if (!(condition)) \ - __wait_event_interruptible_timeout(wq, condition, __ret); \ - __ret; \ -}) -#endif - -#define RTMP_SEM_EVENT_INIT_LOCKED(_pSema) sema_init((_pSema), 0) -#define RTMP_SEM_EVENT_INIT(_pSema) sema_init((_pSema), 1) -#define RTMP_SEM_EVENT_WAIT(_pSema, _status) ((_status) = down_interruptible((_pSema))) -#define RTMP_SEM_EVENT_UP(_pSema) up(_pSema) - -#ifdef KTHREAD_SUPPORT -#define RTMP_WAIT_EVENT_INTERRUPTIBLE(_pAd, _pTask) \ -{ \ - wait_event_interruptible(_pTask->kthread_q, \ - _pTask->kthread_running || kthread_should_stop()); \ - _pTask->kthread_running = FALSE; \ - if (kthread_should_stop()) \ - { \ - RTMP_SET_FLAG(_pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); \ - break; \ - } \ -} -#endif - -#ifdef KTHREAD_SUPPORT -#define WAKE_UP(_pTask) \ - do{ \ - if ((_pTask)->kthread_task) \ - { \ - (_pTask)->kthread_running = TRUE; \ - wake_up(&(_pTask)->kthread_q); \ - } \ - }while(0) -#endif - -/*********************************************************************************** - * OS Memory Access related data structure and definitions - ***********************************************************************************/ -#define MEM_ALLOC_FLAG (GFP_ATOMIC) //(GFP_DMA | GFP_ATOMIC) - -#define NdisMoveMemory(Destination, Source, Length) memmove(Destination, Source, Length) -#define NdisCopyMemory(Destination, Source, Length) memcpy(Destination, Source, Length) -#define NdisZeroMemory(Destination, Length) memset(Destination, 0, Length) -#define NdisFillMemory(Destination, Length, Fill) memset(Destination, Fill, Length) -#define NdisCmpMemory(Destination, Source, Length) memcmp(Destination, Source, Length) -#define NdisEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) -#define RTMPEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) - -#define MlmeAllocateMemory(_pAd, _ppVA) os_alloc_mem(_pAd, _ppVA, MGMT_DMA_BUFFER_SIZE) -#define MlmeFreeMemory(_pAd, _pVA) os_free_mem(_pAd, _pVA) - -#define COPY_MAC_ADDR(Addr1, Addr2) memcpy((Addr1), (Addr2), MAC_ADDR_LEN) - - -/*********************************************************************************** - * OS task related data structure and definitions - ***********************************************************************************/ -#define RTMP_OS_MGMT_TASK_FLAGS CLONE_VM - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) -typedef struct pid * THREAD_PID; -#define THREAD_PID_INIT_VALUE NULL -#define GET_PID(_v) find_get_pid((_v)) -#define GET_PID_NUMBER(_v) pid_nr((_v)) -#define CHECK_PID_LEGALITY(_pid) if (pid_nr((_pid)) >= 0) -#define KILL_THREAD_PID(_A, _B, _C) kill_pid((_A), (_B), (_C)) -#else -typedef pid_t THREAD_PID; -#define THREAD_PID_INIT_VALUE -1 -#define GET_PID(_v) (_v) -#define GET_PID_NUMBER(_v) (_v) -#define CHECK_PID_LEGALITY(_pid) if ((_pid) >= 0) -#define KILL_THREAD_PID(_A, _B, _C) kill_proc((_A), (_B), (_C)) -#endif - -typedef struct tasklet_struct RTMP_NET_TASK_STRUCT; -typedef struct tasklet_struct *PRTMP_NET_TASK_STRUCT; - - -/*********************************************************************************** - * Timer related definitions and data structures. - **********************************************************************************/ -#define OS_HZ HZ - -typedef struct timer_list NDIS_MINIPORT_TIMER; -typedef struct timer_list RTMP_OS_TIMER; -typedef void (*TIMER_FUNCTION)(unsigned long); - - -#define OS_WAIT(_time) \ -{ int _i; \ - long _loop = ((_time)/(1000/OS_HZ)) > 0 ? ((_time)/(1000/OS_HZ)) : 1;\ - wait_queue_head_t _wait; \ - init_waitqueue_head(&_wait); \ - for (_i=0; _i<(_loop); _i++) \ - wait_event_interruptible_timeout(_wait, 0, ONE_TICK); } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#define RTMP_TIME_AFTER(a,b) \ - (typecheck(unsigned long, (unsigned long)a) && \ - typecheck(unsigned long, (unsigned long)b) && \ - ((long)(b) - (long)(a) < 0)) - -#define RTMP_TIME_AFTER_EQ(a,b) \ - (typecheck(unsigned long, (unsigned long)a) && \ - typecheck(unsigned long, (unsigned long)b) && \ - ((long)(a) - (long)(b) >= 0)) -#define RTMP_TIME_BEFORE(a,b) RTMP_TIME_AFTER_EQ(b,a) -#else -#define typecheck(type,x) \ -({ type __dummy; \ - typeof(x) __dummy2; \ - (void)(&__dummy == &__dummy2); \ - 1; \ -}) -#define RTMP_TIME_AFTER_EQ(a,b) \ - (typecheck(unsigned long, (unsigned long)a) && \ - typecheck(unsigned long, (unsigned long)b) && \ - ((long)(a) - (long)(b) >= 0)) -#define RTMP_TIME_BEFORE(a,b) RTMP_TIME_AFTER_EQ(b,a) -#define RTMP_TIME_AFTER(a,b) time_after(a, b) -#endif - -#define ONE_TICK 1 - -static inline void NdisGetSystemUpTime(ULONG *time) -{ - *time = jiffies; -} - - -/*********************************************************************************** - * OS specific cookie data structure binding to RTMP_ADAPTER - ***********************************************************************************/ - -struct os_cookie { -#ifdef RTMP_MAC_PCI - struct pci_dev *pci_dev; - struct pci_dev *parent_pci_dev; - USHORT DeviceID; - dma_addr_t pAd_pa; -#endif // RTMP_MAC_PCI // - - - RTMP_NET_TASK_STRUCT rx_done_task; - RTMP_NET_TASK_STRUCT mgmt_dma_done_task; - RTMP_NET_TASK_STRUCT ac0_dma_done_task; - RTMP_NET_TASK_STRUCT ac1_dma_done_task; - RTMP_NET_TASK_STRUCT ac2_dma_done_task; - RTMP_NET_TASK_STRUCT ac3_dma_done_task; - /*RTMP_NET_TASK_STRUCT hcca_dma_done_task;*/ - RTMP_NET_TASK_STRUCT tbtt_task; -#ifdef RTMP_MAC_PCI - RTMP_NET_TASK_STRUCT fifo_statistic_full_task; -#endif // RTMP_MAC_PCI // - - - - unsigned long apd_pid; //802.1x daemon pid - INT ioctl_if_type; - INT ioctl_if; -}; - -typedef struct os_cookie * POS_COOKIE; - - - -/*********************************************************************************** - * OS debugging and printing related definitions and data structure - ***********************************************************************************/ -#define PRINT_MAC(addr) \ - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] - -#ifdef DBG -extern ULONG RTDebugLevel; - -#define DBGPRINT_RAW(Level, Fmt) \ -do{ \ - if (Level <= RTDebugLevel) \ - { \ - printk Fmt; \ - } \ -}while(0) - -#define DBGPRINT(Level, Fmt) DBGPRINT_RAW(Level, Fmt) - - -#define DBGPRINT_ERR(Fmt) \ -{ \ - printk("ERROR!!! "); \ - printk Fmt; \ -} - -#define DBGPRINT_S(Status, Fmt) \ -{ \ - printk Fmt; \ -} -#else -#define DBGPRINT(Level, Fmt) -#define DBGPRINT_RAW(Level, Fmt) -#define DBGPRINT_S(Status, Fmt) -#define DBGPRINT_ERR(Fmt) -#endif - -#undef ASSERT -#define ASSERT(x) \ -{ \ - if (!(x)) \ - { \ - printk(KERN_WARNING __FILE__ ":%d assert " #x "failed\n", __LINE__); \ - } \ -} - -void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen); - - -/********************************************************************************************************* - The following code are not revised, temporary put it here. - *********************************************************************************************************/ - - -/*********************************************************************************** - * Device DMA Access related definitions and data structures. - **********************************************************************************/ -#ifdef RTMP_MAC_PCI -dma_addr_t linux_pci_map_single(void *handle, void *ptr, size_t size, int sd_idx, int direction); -void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size, int direction); - -#define PCI_MAP_SINGLE(_handle, _ptr, _size, _sd_idx, _dir) \ - linux_pci_map_single(_handle, _ptr, _size, _sd_idx, _dir) - -#define PCI_UNMAP_SINGLE(_handle, _ptr, _size, _dir) \ - linux_pci_unmap_single(_handle, _ptr, _size, _dir) - -#define PCI_ALLOC_CONSISTENT(_pci_dev, _size, _ptr) \ - pci_alloc_consistent(_pci_dev, _size, _ptr) - -#define PCI_FREE_CONSISTENT(_pci_dev, _size, _virtual_addr, _physical_addr) \ - pci_free_consistent(_pci_dev, _size, _virtual_addr, _physical_addr) - -#define DEV_ALLOC_SKB(_length) \ - dev_alloc_skb(_length) -#endif // RTMP_MAC_PCI // - - - -/* - * ULONG - * RTMP_GetPhysicalAddressLow( - * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); - */ -#define RTMP_GetPhysicalAddressLow(PhysicalAddress) (PhysicalAddress) - -/* - * ULONG - * RTMP_GetPhysicalAddressHigh( - * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); - */ -#define RTMP_GetPhysicalAddressHigh(PhysicalAddress) (0) - -/* - * VOID - * RTMP_SetPhysicalAddressLow( - * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, - * IN ULONG Value); - */ -#define RTMP_SetPhysicalAddressLow(PhysicalAddress, Value) \ - PhysicalAddress = Value; - -/* - * VOID - * RTMP_SetPhysicalAddressHigh( - * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, - * IN ULONG Value); - */ -#define RTMP_SetPhysicalAddressHigh(PhysicalAddress, Value) - -#define NdisMIndicateStatus(_w, _x, _y, _z) - - - -/*********************************************************************************** - * Device Register I/O Access related definitions and data structures. - **********************************************************************************/ -#ifdef RTMP_MAC_PCI -#if defined(INF_TWINPASS) || defined(INF_DANUBE) || defined(IKANOS_VX_1X0) -//Patch for ASIC turst read/write bug, needs to remove after metel fix -#define RTMP_IO_READ32(_A, _R, _pV) \ -{ \ - if ((_A)->bPCIclkOff == FALSE) \ - { \ - (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ - (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ - (*_pV = SWAP32(*((UINT32 *)(_pV)))); \ - } \ -} - -#define RTMP_IO_READ8(_A, _R, _pV) \ -{ \ - (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ - (*_pV = readb((void *)((_A)->CSRBaseAddress + (_R)))); \ -} - -#define RTMP_IO_WRITE32(_A, _R, _V) \ -{ \ - if ((_A)->bPCIclkOff == FALSE) \ - { \ - UINT32 _Val; \ - _Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ - _Val = SWAP32(_V); \ - writel(_Val, (void *)((_A)->CSRBaseAddress + (_R))); \ - } \ -} - -#define RTMP_IO_WRITE8(_A, _R, _V) \ -{ \ - UINT Val; \ - Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ - writeb((_V), (PUCHAR)((_A)->CSRBaseAddress + (_R))); \ -} - -#define RTMP_IO_WRITE16(_A, _R, _V) \ -{ \ - UINT Val; \ - Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ - writew(SWAP16((_V)), (PUSHORT)((_A)->CSRBaseAddress + (_R))); \ -} -#else -//Patch for ASIC turst read/write bug, needs to remove after metel fix -#define RTMP_IO_READ32(_A, _R, _pV) \ -{ \ - if ((_A)->bPCIclkOff == FALSE) \ - { \ - (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ - (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ - } \ - else \ - *_pV = 0; \ -} - -#define RTMP_IO_FORCE_READ32(_A, _R, _pV) \ -{ \ - (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ - (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ -} - -#define RTMP_IO_READ8(_A, _R, _pV) \ -{ \ - (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ - (*_pV = readb((void *)((_A)->CSRBaseAddress + (_R)))); \ -} - -#define RTMP_IO_WRITE32(_A, _R, _V) \ -{ \ - if ((_A)->bPCIclkOff == FALSE) \ - { \ - UINT Val; \ - Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ - writel((_V), (void *)((_A)->CSRBaseAddress + (_R))); \ - } \ -} - -#define RTMP_IO_FORCE_WRITE32(_A, _R, _V) \ -{ \ - UINT Val; \ - Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ - writel(_V, (void *)((_A)->CSRBaseAddress + (_R))); \ -} - - - -#if defined(BRCM_6358) || defined(RALINK_2880) || defined(RALINK_3052) -#define RTMP_IO_WRITE8(_A, _R, _V) \ -{ \ - ULONG Val; \ - UCHAR _i; \ - _i = ((_R) & 0x3); \ - Val = readl((void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ - Val = Val & (~(0x000000ff << ((_i)*8))); \ - Val = Val | ((ULONG)(_V) << ((_i)*8)); \ - writel((Val), (void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ -} -#else -#define RTMP_IO_WRITE8(_A, _R, _V) \ -{ \ - UINT Val; \ - Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ - writeb((_V), (PUCHAR)((_A)->CSRBaseAddress + (_R))); \ -} -#endif // #if defined(BRCM_6358) || defined(RALINK_2880) // - -#define RTMP_IO_WRITE16(_A, _R, _V) \ -{ \ - UINT Val; \ - Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \ - writew((_V), (PUSHORT)((_A)->CSRBaseAddress + (_R))); \ -} -#endif // #if defined(INF_TWINPASS) || defined(INF_DANUBE) || defined(IKANOS_VX_1X0) // -#endif // RTMP_MAC_PCI // - - - -/*********************************************************************************** - * Network Related data structure and marco definitions - ***********************************************************************************/ -#define PKTSRC_NDIS 0x7f -#define PKTSRC_DRIVER 0x0f - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -#define RTMP_OS_NETDEV_SET_PRIV(_pNetDev, _pPriv) ((_pNetDev)->priv = (_pPriv)) -#define RTMP_OS_NETDEV_GET_PRIV(_pNetDev) ((_pNetDev)->priv) -#else -#define RTMP_OS_NETDEV_SET_PRIV(_pNetDev, _pPriv) ((_pNetDev)->ml_priv = (_pPriv)) -#define RTMP_OS_NETDEV_GET_PRIV(_pNetDev) ((_pNetDev)->ml_priv) -#endif -#define RTMP_OS_NETDEV_GET_DEVNAME(_pNetDev) ((_pNetDev)->name) -#define RTMP_OS_NETDEV_GET_PHYADDR(_PNETDEV) ((_PNETDEV)->dev_addr) - -#define RTMP_OS_NETDEV_START_QUEUE(_pNetDev) netif_start_queue((_pNetDev)) -#define RTMP_OS_NETDEV_STOP_QUEUE(_pNetDev) netif_stop_queue((_pNetDev)) -#define RTMP_OS_NETDEV_WAKE_QUEUE(_pNetDev) netif_wake_queue((_pNetDev)) -#define RTMP_OS_NETDEV_CARRIER_OFF(_pNetDev) netif_carrier_off((_pNetDev)) - -#define QUEUE_ENTRY_TO_PACKET(pEntry) \ - (PNDIS_PACKET)(pEntry) - -#define PACKET_TO_QUEUE_ENTRY(pPacket) \ - (PQUEUE_ENTRY)(pPacket) - -#ifdef CONFIG_5VT_ENHANCE -#define BRIDGE_TAG 0x35564252 // depends on 5VT define in br_input.c -#endif - -#define GET_SG_LIST_FROM_PACKET(_p, _sc) \ - rt_get_sg_list_from_packet(_p, _sc) - -#define RELEASE_NDIS_PACKET(_pAd, _pPacket, _Status) \ -{ \ - RTMPFreeNdisPacket(_pAd, _pPacket); \ -} - -/* - * packet helper - * - convert internal rt packet to os packet or - * os packet to rt packet - */ -#define RTPKT_TO_OSPKT(_p) ((struct sk_buff *)(_p)) -#define OSPKT_TO_RTPKT(_p) ((PNDIS_PACKET)(_p)) - -#define GET_OS_PKT_DATAPTR(_pkt) \ - (RTPKT_TO_OSPKT(_pkt)->data) -#define SET_OS_PKT_DATAPTR(_pkt, _dataPtr) \ - (RTPKT_TO_OSPKT(_pkt)->data) = (_dataPtr) - -#define GET_OS_PKT_LEN(_pkt) \ - (RTPKT_TO_OSPKT(_pkt)->len) -#define SET_OS_PKT_LEN(_pkt, _len) \ - (RTPKT_TO_OSPKT(_pkt)->len) = (_len) - -#define GET_OS_PKT_DATATAIL(_pkt) \ - (RTPKT_TO_OSPKT(_pkt)->tail) -#define SET_OS_PKT_DATATAIL(_pkt, _start, _len) \ - ((RTPKT_TO_OSPKT(_pkt))->tail) = (PUCHAR)((_start) + (_len)) - -#define GET_OS_PKT_HEAD(_pkt) \ - (RTPKT_TO_OSPKT(_pkt)->head) - -#define GET_OS_PKT_END(_pkt) \ - (RTPKT_TO_OSPKT(_pkt)->end) - -#define GET_OS_PKT_NETDEV(_pkt) \ - (RTPKT_TO_OSPKT(_pkt)->dev) -#define SET_OS_PKT_NETDEV(_pkt, _pNetDev) \ - (RTPKT_TO_OSPKT(_pkt)->dev) = (_pNetDev) - -#define GET_OS_PKT_TYPE(_pkt) \ - (RTPKT_TO_OSPKT(_pkt)) - -#define GET_OS_PKT_NEXT(_pkt) \ - (RTPKT_TO_OSPKT(_pkt)->next) - - -#define OS_PKT_CLONED(_pkt) skb_cloned(RTPKT_TO_OSPKT(_pkt)) - -#define OS_NTOHS(_Val) \ - (ntohs(_Val)) -#define OS_HTONS(_Val) \ - (htons(_Val)) -#define OS_NTOHL(_Val) \ - (ntohl(_Val)) -#define OS_HTONL(_Val) \ - (htonl(_Val)) - -#define CB_OFF 10 - -// User Priority -#define RTMP_SET_PACKET_UP(_p, _prio) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+0] = _prio) -#define RTMP_GET_PACKET_UP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+0]) - -// Fragment # -#define RTMP_SET_PACKET_FRAGMENTS(_p, _num) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+1] = _num) -#define RTMP_GET_PACKET_FRAGMENTS(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+1]) - -// 0x0 ~0x7f: TX to AP's own BSS which has the specified AID. if AID>127, set bit 7 in RTMP_SET_PACKET_EMACTAB too. -//(this value also as MAC(on-chip WCID) table index) -// 0x80~0xff: TX to a WDS link. b0~6: WDS index -#define RTMP_SET_PACKET_WCID(_p, _wdsidx) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2] = _wdsidx) -#define RTMP_GET_PACKET_WCID(_p) ((UCHAR)(RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2])) - -// 0xff: PKTSRC_NDIS, others: local TX buffer index. This value affects how to a packet -#define RTMP_SET_PACKET_SOURCE(_p, _pktsrc) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+3] = _pktsrc) -#define RTMP_GET_PACKET_SOURCE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+3]) - -// RTS/CTS-to-self protection method -#define RTMP_SET_PACKET_RTS(_p, _num) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+4] = _num) -#define RTMP_GET_PACKET_RTS(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+4]) -// see RTMP_S(G)ET_PACKET_EMACTAB - -// TX rate index -#define RTMP_SET_PACKET_TXRATE(_p, _rate) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+5] = _rate) -#define RTMP_GET_PACKET_TXRATE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+5]) - -// From which Interface -#define RTMP_SET_PACKET_IF(_p, _ifdx) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+6] = _ifdx) -#define RTMP_GET_PACKET_IF(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+6]) -#define RTMP_SET_PACKET_NET_DEVICE_MBSSID(_p, _bss) RTMP_SET_PACKET_IF((_p), (_bss)) -#define RTMP_SET_PACKET_NET_DEVICE_WDS(_p, _bss) RTMP_SET_PACKET_IF((_p), ((_bss) + MIN_NET_DEVICE_FOR_WDS)) -#define RTMP_SET_PACKET_NET_DEVICE_APCLI(_p, _idx) RTMP_SET_PACKET_IF((_p), ((_idx) + MIN_NET_DEVICE_FOR_APCLI)) -#define RTMP_SET_PACKET_NET_DEVICE_MESH(_p, _idx) RTMP_SET_PACKET_IF((_p), ((_idx) + MIN_NET_DEVICE_FOR_MESH)) -#define RTMP_GET_PACKET_NET_DEVICE_MBSSID(_p) RTMP_GET_PACKET_IF((_p)) -#define RTMP_GET_PACKET_NET_DEVICE(_p) RTMP_GET_PACKET_IF((_p)) - -#define RTMP_SET_PACKET_MOREDATA(_p, _morebit) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+7] = _morebit) -#define RTMP_GET_PACKET_MOREDATA(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+7]) - - - - - -// -// Sepcific Pakcet Type definition -// -#define RTMP_PACKET_SPECIFIC_CB_OFFSET 11 - -#define RTMP_PACKET_SPECIFIC_DHCP 0x01 -#define RTMP_PACKET_SPECIFIC_EAPOL 0x02 -#define RTMP_PACKET_SPECIFIC_IPV4 0x04 -#define RTMP_PACKET_SPECIFIC_WAI 0x08 -#define RTMP_PACKET_SPECIFIC_VLAN 0x10 -#define RTMP_PACKET_SPECIFIC_LLCSNAP 0x20 - -//Specific -#define RTMP_SET_PACKET_SPECIFIC(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] = _flg) - -//DHCP -#define RTMP_SET_PACKET_DHCP(_p, _flg) \ - do{ \ - if (_flg) \ - (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_DHCP); \ - else \ - (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_DHCP); \ - }while(0) -#define RTMP_GET_PACKET_DHCP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_DHCP) - -//EAPOL -#define RTMP_SET_PACKET_EAPOL(_p, _flg) \ - do{ \ - if (_flg) \ - (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_EAPOL); \ - else \ - (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_EAPOL); \ - }while(0) -#define RTMP_GET_PACKET_EAPOL(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_EAPOL) - -//WAI -#define RTMP_SET_PACKET_WAI(_p, _flg) \ - do{ \ - if (_flg) \ - (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_WAI); \ - else \ - (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_WAI); \ - }while(0) -#define RTMP_GET_PACKET_WAI(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_WAI) - -#define RTMP_GET_PACKET_LOWRATE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & (RTMP_PACKET_SPECIFIC_EAPOL | RTMP_PACKET_SPECIFIC_DHCP | RTMP_PACKET_SPECIFIC_WAI)) - -//VLAN -#define RTMP_SET_PACKET_VLAN(_p, _flg) \ - do{ \ - if (_flg) \ - (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_VLAN); \ - else \ - (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_VLAN); \ - }while(0) -#define RTMP_GET_PACKET_VLAN(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_VLAN) - -//LLC/SNAP -#define RTMP_SET_PACKET_LLCSNAP(_p, _flg) \ - do{ \ - if (_flg) \ - (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_LLCSNAP); \ - else \ - (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_LLCSNAP); \ - }while(0) - -#define RTMP_GET_PACKET_LLCSNAP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_LLCSNAP) - -// IP -#define RTMP_SET_PACKET_IPV4(_p, _flg) \ - do{ \ - if (_flg) \ - (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_IPV4); \ - else \ - (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_IPV4); \ - }while(0) - -#define RTMP_GET_PACKET_IPV4(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_IPV4) - - -// If this flag is set, it indicates that this EAPoL frame MUST be clear. -#define RTMP_SET_PACKET_CLEAR_EAP_FRAME(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+12] = _flg) -#define RTMP_GET_PACKET_CLEAR_EAP_FRAME(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+12]) - - - -/* use bit3 of cb[CB_OFF+16] */ - -#define RTMP_SET_PACKET_5VT(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+22] = _flg) -#define RTMP_GET_PACKET_5VT(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+22]) - -#ifdef INF_AMAZON_SE -/* [CB_OFF+28], 1B, Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */ -#define RTMP_SET_PACKET_NOBULKOUT(_p, _morebit) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+28] = _morebit) -#define RTMP_GET_PACKET_NOBULKOUT(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+28]) -#endif // INF_AMAZON_SE // -/* Max skb->cb = 48B = [CB_OFF+38] */ - - - -/*********************************************************************************** - * Other function prototypes definitions - ***********************************************************************************/ -void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); -int rt28xx_packet_xmit(struct sk_buff *skb); - - -void FlashWrite(UCHAR * p, ULONG a, ULONG b); -void FlashRead(UCHAR * p, ULONG a, ULONG b); - -#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1 -struct net_device *alloc_netdev(int sizeof_priv, const char *mask, void (*setup)(struct net_device *)); -#endif // LINUX_VERSION_CODE // - - -#ifdef RTMP_MAC_PCI -/* function declarations */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#define IRQ_HANDLE_TYPE irqreturn_t -#else -#define IRQ_HANDLE_TYPE void -#endif - -IRQ_HANDLE_TYPE -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) -rt2860_interrupt(int irq, void *dev_instance); -#else -rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -#endif - -#endif // RTMP_MAC_PCI // - -INT rt28xx_ioctl( - IN PNET_DEV net_dev, - IN OUT struct ifreq *rq, - IN INT cmd); - - -#ifdef CONFIG_STA_SUPPORT -INT rt28xx_sta_ioctl( - IN PNET_DEV net_dev, - IN OUT struct ifreq *rq, - IN INT cmd); -#endif // CONFIG_STA_SUPPORT // - -extern int ra_mtd_write(int num, loff_t to, size_t len, const u_char *buf); -extern int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf); - -#endif // __RT_LINUX_H__ // diff --git a/drivers/staging/rt3090/rt_main_dev.c b/drivers/staging/rt3090/rt_main_dev.c deleted file mode 100644 index 3307a5f368479e68f510746d8dbb0670955e56f4..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rt_main_dev.c +++ /dev/null @@ -1,897 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rt_main_dev.c - - Abstract: - Create and register network interface. - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#include "rt_config.h" - - -#ifdef CONFIG_APSTA_MIXED_SUPPORT -UINT32 CW_MAX_IN_BITS; -#endif // CONFIG_APSTA_MIXED_SUPPORT // - -/*---------------------------------------------------------------------*/ -/* Private Variables Used */ -/*---------------------------------------------------------------------*/ - -PSTRING mac = ""; // default 00:00:00:00:00:00 -PSTRING hostname = ""; // default CMPC -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12) -MODULE_PARM (mac, "s"); -#else -module_param (mac, charp, 0); -#endif -MODULE_PARM_DESC (mac, "rt28xx: wireless mac addr"); - - -/*---------------------------------------------------------------------*/ -/* Prototypes of Functions Used */ -/*---------------------------------------------------------------------*/ - -// public function prototype -int rt28xx_close(IN struct net_device *net_dev); -int rt28xx_open(struct net_device *net_dev); - -// private function prototype -static INT rt28xx_send_packets(IN struct sk_buff *skb_p, IN struct net_device *net_dev); - - -static struct net_device_stats *RT28xx_get_ether_stats( - IN struct net_device *net_dev); - -/* -======================================================================== -Routine Description: - Close raxx interface. - -Arguments: - *net_dev the raxx interface pointer - -Return Value: - 0 Open OK - otherwise Open Fail - -Note: - 1. if open fail, kernel will not call the close function. - 2. Free memory for - (1) Mlme Memory Handler: MlmeHalt() - (2) TX & RX: RTMPFreeTxRxRingMemory() - (3) BA Reordering: ba_reordering_resource_release() -======================================================================== -*/ -int MainVirtualIF_close(IN struct net_device *net_dev) -{ - RTMP_ADAPTER *pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev); - - // Sanity check for pAd - if (pAd == NULL) - return 0; // close ok - - netif_carrier_off(pAd->net_dev); - netif_stop_queue(pAd->net_dev); - - - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - BOOLEAN Cancelled; -#ifdef QOS_DLS_SUPPORT - // send DLS-TEAR_DOWN message, - if (pAd->CommonCfg.bDLSCapable) - { - UCHAR i; - - // tear down local dls table entry - for (i=0; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) - { - RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - } - } - - // tear down peer dls table entry - for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) - { - RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - } - } - RTMP_MLME_HANDLER(pAd); - } -#endif // QOS_DLS_SUPPORT // - - if (INFRA_ON(pAd) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) - { - MLME_DISASSOC_REQ_STRUCT DisReq; - MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); - - if (MsgElem) - { - COPY_MAC_ADDR(DisReq.Addr, pAd->CommonCfg.Bssid); - DisReq.Reason = REASON_DEAUTH_STA_LEAVING; - - MsgElem->Machine = ASSOC_STATE_MACHINE; - MsgElem->MsgType = MT2_MLME_DISASSOC_REQ; - MsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); - NdisMoveMemory(MsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); - - // Prevent to connect AP again in STAMlmePeriodicExec - pAd->MlmeAux.AutoReconnectSsidLen= 32; - NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); - - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; - MlmeDisassocReqAction(pAd, MsgElem); - kfree(MsgElem); - } - - RTMPusecDelay(1000); - } - - RTMPCancelTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, &Cancelled); - RTMPCancelTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, &Cancelled); - -#ifdef WPA_SUPPLICANT_SUPPORT -#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT - // send wireless event to wpa_supplicant for infroming interface down. - RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, RT_INTERFACE_DOWN, NULL, NULL, 0); -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // -#endif // WPA_SUPPLICANT_SUPPORT // - - - } -#endif // CONFIG_STA_SUPPORT // - - VIRTUAL_IF_DOWN(pAd); - - RT_MOD_DEC_USE_COUNT(); - - return 0; // close ok -} - -/* -======================================================================== -Routine Description: - Open raxx interface. - -Arguments: - *net_dev the raxx interface pointer - -Return Value: - 0 Open OK - otherwise Open Fail - -Note: - 1. if open fail, kernel will not call the close function. - 2. Free memory for - (1) Mlme Memory Handler: MlmeHalt() - (2) TX & RX: RTMPFreeTxRxRingMemory() - (3) BA Reordering: ba_reordering_resource_release() -======================================================================== -*/ -int MainVirtualIF_open(IN struct net_device *net_dev) -{ - RTMP_ADAPTER *pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev); - - // Sanity check for pAd - if (pAd == NULL) - return 0; // close ok - - if (VIRTUAL_IF_UP(pAd) != 0) - return -1; - - // increase MODULE use count - RT_MOD_INC_USE_COUNT(); - - netif_start_queue(net_dev); - netif_carrier_on(net_dev); - netif_wake_queue(net_dev); - - return 0; -} - -/* -======================================================================== -Routine Description: - Close raxx interface. - -Arguments: - *net_dev the raxx interface pointer - -Return Value: - 0 Open OK - otherwise Open Fail - -Note: - 1. if open fail, kernel will not call the close function. - 2. Free memory for - (1) Mlme Memory Handler: MlmeHalt() - (2) TX & RX: RTMPFreeTxRxRingMemory() - (3) BA Reordering: ba_reordering_resource_release() -======================================================================== -*/ -int rt28xx_close(IN PNET_DEV dev) -{ - struct net_device * net_dev = (struct net_device *)dev; - RTMP_ADAPTER *pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev); - BOOLEAN Cancelled; - UINT32 i = 0; - - - DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n")); - - Cancelled = FALSE; - // Sanity check for pAd - if (pAd == NULL) - return 0; // close ok - - - -#ifdef WDS_SUPPORT - WdsDown(pAd); -#endif // WDS_SUPPORT // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { -#ifdef RTMP_MAC_PCI - RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_CLOSE); -#endif // RTMP_MAC_PCI // - - // If dirver doesn't wake up firmware here, - // NICLoadFirmware will hang forever when interface is up again. - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - AsicForceWakeup(pAd, TRUE); - } - - - MlmeRadioOff(pAd); -#ifdef RTMP_MAC_PCI - pAd->bPCIclkOff = FALSE; -#endif // RTMP_MAC_PCI // - } -#endif // CONFIG_STA_SUPPORT // - - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); - - for (i = 0 ; i < NUM_OF_TX_RING; i++) - { - while (pAd->DeQueueRunning[i] == TRUE) - { - DBGPRINT(RT_DEBUG_TRACE, ("Waiting for TxQueue[%d] done..........\n", i)); - RTMPusecDelay(1000); - } - } - - - - // Stop Mlme state machine - MlmeHalt(pAd); - - // Close net tasklets - RtmpNetTaskExit(pAd); - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - MacTableReset(pAd); - } -#endif // CONFIG_STA_SUPPORT // - - - MeasureReqTabExit(pAd); - TpcReqTabExit(pAd); - - - // Close kernel threads - RtmpMgmtTaskExit(pAd); - -#ifdef RTMP_MAC_PCI - { - BOOLEAN brc; - // ULONG Value; - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) - { - RTMP_ASIC_INTERRUPT_DISABLE(pAd); - } - - // Receive packets to clear DMA index after disable interrupt. - //RTMPHandleRxDoneInterrupt(pAd); - // put to radio off to save power when driver unload. After radiooff, can't write /read register. So need to finish all - // register access before Radio off. - - - brc=RT28xxPciAsicRadioOff(pAd, RTMP_HALT, 0); - -//In solution 3 of 3090F, the bPCIclkOff will be set to TRUE after calling RT28xxPciAsicRadioOff - pAd->bPCIclkOff = FALSE; - - if (brc==FALSE) - { - DBGPRINT(RT_DEBUG_ERROR,("%s call RT28xxPciAsicRadioOff fail !!\n", __FUNCTION__)); - } - } - - -/* - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) - { - RTMP_ASIC_INTERRUPT_DISABLE(pAd); - } - - // Disable Rx, register value supposed will remain after reset - NICIssueReset(pAd); -*/ -#endif // RTMP_MAC_PCI // - - // Free IRQ - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { -#ifdef RTMP_MAC_PCI - // Deregister interrupt function - RTMP_IRQ_RELEASE(net_dev) -#endif // RTMP_MAC_PCI // - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); - } - - // Free Ring or USB buffers - RTMPFreeTxRxRingMemory(pAd); - - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); - -#ifdef DOT11_N_SUPPORT - // Free BA reorder resource - ba_reordering_resource_release(pAd); -#endif // DOT11_N_SUPPORT // - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP); - -/*+++Modify by woody to solve the bulk fail+++*/ -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - } -#endif // CONFIG_STA_SUPPORT // - - DBGPRINT(RT_DEBUG_TRACE, ("<=== rt28xx_close\n")); - return 0; // close ok -} /* End of rt28xx_close */ - - -/* -======================================================================== -Routine Description: - Open raxx interface. - -Arguments: - *net_dev the raxx interface pointer - -Return Value: - 0 Open OK - otherwise Open Fail - -Note: -======================================================================== -*/ -int rt28xx_open(IN PNET_DEV dev) -{ - struct net_device * net_dev = (struct net_device *)dev; - PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev); - int retval = 0; - //POS_COOKIE pObj; - - - // Sanity check for pAd - if (pAd == NULL) - { - /* if 1st open fail, pAd will be free; - So the net_dev->priv will be NULL in 2rd open */ - return -1; - } - -#ifdef CONFIG_APSTA_MIXED_SUPPORT - if (pAd->OpMode == OPMODE_AP) - { - CW_MAX_IN_BITS = 6; - } - else if (pAd->OpMode == OPMODE_STA) - { - CW_MAX_IN_BITS = 10; - } -#endif // CONFIG_APSTA_MIXED_SUPPORT // - -#if WIRELESS_EXT >= 12 - if (net_dev->priv_flags == INT_MAIN) - { -#ifdef CONFIG_APSTA_MIXED_SUPPORT - if (pAd->OpMode == OPMODE_AP) - net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_ap_iw_handler_def; -#endif // CONFIG_APSTA_MIXED_SUPPORT // -#ifdef CONFIG_STA_SUPPORT - if (pAd->OpMode == OPMODE_STA) - net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_iw_handler_def; -#endif // CONFIG_STA_SUPPORT // - } -#endif // WIRELESS_EXT >= 12 // - - // Request interrupt service routine for PCI device - // register the interrupt routine with the os - RTMP_IRQ_REQUEST(net_dev); - - // Init IRQ parameters stored in pAd - RTMP_IRQ_INIT(pAd); - - // Chip & other init - if (rt28xx_init(pAd, mac, hostname) == FALSE) - goto err; - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - - // Enable Interrupt - RTMP_IRQ_ENABLE(pAd); - - // Now Enable RxTx - RTMPEnableRxTx(pAd); - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); - - { - UINT32 reg = 0; - RTMP_IO_READ32(pAd, 0x1300, ®); // clear garbage interrupts - printk("0x1300 = %08x\n", reg); - } - - { -// u32 reg; -// UINT8 byte; -// u16 tmp; - -// RTMP_IO_READ32(pAd, XIFS_TIME_CFG, ®); - -// tmp = 0x0805; -// reg = (reg & 0xffff0000) | tmp; -// RTMP_IO_WRITE32(pAd, XIFS_TIME_CFG, reg); - - } - - -#ifdef CONFIG_STA_SUPPORT -#ifdef RTMP_MAC_PCI - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - RTMPInitPCIeLinkCtrlValue(pAd); -#endif // RTMP_MAC_PCI // -#endif // CONFIG_STA_SUPPORT // - - return (retval); - -err: -//+++Add by shiang, move from rt28xx_init() to here. - RTMP_IRQ_RELEASE(net_dev); -//---Add by shiang, move from rt28xx_init() to here. - return (-1); -} /* End of rt28xx_open */ - -static const struct net_device_ops rt3090_netdev_ops = { - .ndo_open = MainVirtualIF_open, - .ndo_stop = MainVirtualIF_close, - .ndo_do_ioctl = rt28xx_ioctl, - .ndo_get_stats = RT28xx_get_ether_stats, - .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, -#ifdef IKANOS_VX_1X0 - .ndo_start_xmit = IKANOS_DataFramesTx, -#else - .ndo_start_xmit = rt28xx_send_packets, -#endif -}; - -PNET_DEV RtmpPhyNetDevInit( - IN RTMP_ADAPTER *pAd, - IN RTMP_OS_NETDEV_OP_HOOK *pNetDevHook) -{ - struct net_device *net_dev = NULL; -// NDIS_STATUS Status; - - net_dev = RtmpOSNetDevCreate(pAd, INT_MAIN, 0, sizeof(PRTMP_ADAPTER), INF_MAIN_DEV_NAME); - if (net_dev == NULL) - { - printk("RtmpPhyNetDevInit(): creation failed for main physical net device!\n"); - return NULL; - } - - NdisZeroMemory((unsigned char *)pNetDevHook, sizeof(RTMP_OS_NETDEV_OP_HOOK)); - pNetDevHook->netdev_ops = &rt3090_netdev_ops; - pNetDevHook->priv_flags = INT_MAIN; - pNetDevHook->needProtcted = FALSE; - - RTMP_OS_NETDEV_SET_PRIV(net_dev, pAd); - //net_dev->priv = (PVOID)pAd; - pAd->net_dev = net_dev; - - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - SET_MODULE_OWNER(net_dev); -#endif - - netif_stop_queue(net_dev); - - return net_dev; - -} - - -/* -======================================================================== -Routine Description: - The entry point for Linux kernel sent packet to our driver. - -Arguments: - sk_buff *skb the pointer refer to a sk_buffer. - -Return Value: - 0 - -Note: - This function is the entry point of Tx Path for Os delivery packet to - our driver. You only can put OS-depened & STA/AP common handle procedures - in here. -======================================================================== -*/ -int rt28xx_packet_xmit(struct sk_buff *skb) -{ - struct net_device *net_dev = skb->dev; - PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev); - int status = 0; - PNDIS_PACKET pPacket = (PNDIS_PACKET) skb; - - /* RT2870STA does this in RTMPSendPackets() */ -#ifdef RALINK_ATE - if (ATE_ON(pAd)) - { - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_RESOURCES); - return 0; - } -#endif // RALINK_ATE // - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // Drop send request since we are in monitor mode - if (MONITOR_ON(pAd)) - { - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - goto done; - } - } -#endif // CONFIG_STA_SUPPORT // - - // EapolStart size is 18 - if (skb->len < 14) - { - //printk("bad packet size: %d\n", pkt->len); - hex_dump("bad packet", skb->data, skb->len); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - goto done; - } - - - - RTMP_SET_PACKET_5VT(pPacket, 0); -// MiniportMMRequest(pAd, pkt->data, pkt->len); -#ifdef CONFIG_5VT_ENHANCE - if (*(int*)(skb->cb) == BRIDGE_TAG) { - RTMP_SET_PACKET_5VT(pPacket, 1); - } -#endif - - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - - STASendPackets((NDIS_HANDLE)pAd, (PPNDIS_PACKET) &pPacket, 1); - } - -#endif // CONFIG_STA_SUPPORT // - - status = 0; -done: - - return status; -} - - -/* -======================================================================== -Routine Description: - Send a packet to WLAN. - -Arguments: - skb_p points to our adapter - dev_p which WLAN network interface - -Return Value: - 0: transmit successfully - otherwise: transmit fail - -Note: -======================================================================== -*/ -static int rt28xx_send_packets( - IN struct sk_buff *skb_p, - IN struct net_device *net_dev) -{ - RTMP_ADAPTER *pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev); - - if (!(net_dev->flags & IFF_UP)) - { - RELEASE_NDIS_PACKET(pAd, (PNDIS_PACKET)skb_p, NDIS_STATUS_FAILURE); - return 0; - } - - NdisZeroMemory((PUCHAR)&skb_p->cb[CB_OFF], 15); - RTMP_SET_PACKET_NET_DEVICE_MBSSID(skb_p, MAIN_MBSSID); - - return rt28xx_packet_xmit(skb_p); -} - - -#if WIRELESS_EXT >= 12 -// This function will be called when query /proc -struct iw_statistics *rt28xx_get_wireless_stats( - IN struct net_device *net_dev) -{ - PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev); - - - - DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_get_wireless_stats --->\n")); - - pAd->iw_stats.status = 0; // Status - device dependent for now - - // link quality -#ifdef CONFIG_STA_SUPPORT - if (pAd->OpMode == OPMODE_STA) - pAd->iw_stats.qual.qual = ((pAd->Mlme.ChannelQuality * 12)/10 + 10); -#endif // CONFIG_STA_SUPPORT // - - if(pAd->iw_stats.qual.qual > 100) - pAd->iw_stats.qual.qual = 100; - -#ifdef CONFIG_STA_SUPPORT - if (pAd->OpMode == OPMODE_STA) - { - pAd->iw_stats.qual.level = - RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, - pAd->StaCfg.RssiSample.LastRssi1, - pAd->StaCfg.RssiSample.LastRssi2); - } -#endif // CONFIG_STA_SUPPORT // - - pAd->iw_stats.qual.noise = pAd->BbpWriteLatch[66]; // noise level (dBm) - - pAd->iw_stats.qual.noise += 256 - 143; - pAd->iw_stats.qual.updated = 1; // Flags to know if updated -#ifdef IW_QUAL_DBM - pAd->iw_stats.qual.updated |= IW_QUAL_DBM; // Level + Noise are dBm -#endif // IW_QUAL_DBM // - - pAd->iw_stats.discard.nwid = 0; // Rx : Wrong nwid/essid - pAd->iw_stats.miss.beacon = 0; // Missed beacons/superframe - - DBGPRINT(RT_DEBUG_TRACE, ("<--- rt28xx_get_wireless_stats\n")); - return &pAd->iw_stats; -} -#endif // WIRELESS_EXT // - - -void tbtt_tasklet(unsigned long data) -{ -//#define MAX_TX_IN_TBTT (16) - -} - -INT rt28xx_ioctl( - IN PNET_DEV net_dev, - IN OUT struct ifreq *rq, - IN INT cmd) -{ - RTMP_ADAPTER *pAd = NULL; - INT ret = 0; - - pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev); - if (pAd == NULL) - { - /* if 1st open fail, pAd will be free; - So the net_dev->priv will be NULL in 2rd open */ - return -ENETDOWN; - } - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - ret = rt28xx_sta_ioctl(net_dev, rq, cmd); - } -#endif // CONFIG_STA_SUPPORT // - - return ret; -} - - -/* - ======================================================================== - - Routine Description: - return ethernet statistics counter - - Arguments: - net_dev Pointer to net_device - - Return Value: - net_device_stats* - - Note: - - ======================================================================== -*/ -static struct net_device_stats *RT28xx_get_ether_stats( - IN struct net_device *net_dev) -{ - RTMP_ADAPTER *pAd = NULL; - - if (net_dev) - pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev); - - if (pAd) - { - - pAd->stats.rx_packets = pAd->WlanCounters.ReceivedFragmentCount.QuadPart; - pAd->stats.tx_packets = pAd->WlanCounters.TransmittedFragmentCount.QuadPart; - - pAd->stats.rx_bytes = pAd->RalinkCounters.ReceivedByteCount; - pAd->stats.tx_bytes = pAd->RalinkCounters.TransmittedByteCount; - - pAd->stats.rx_errors = pAd->Counters8023.RxErrors; - pAd->stats.tx_errors = pAd->Counters8023.TxErrors; - - pAd->stats.rx_dropped = 0; - pAd->stats.tx_dropped = 0; - - pAd->stats.multicast = pAd->WlanCounters.MulticastReceivedFrameCount.QuadPart; // multicast packets received - pAd->stats.collisions = pAd->Counters8023.OneCollision + pAd->Counters8023.MoreCollisions; // Collision packets - - pAd->stats.rx_length_errors = 0; - pAd->stats.rx_over_errors = pAd->Counters8023.RxNoBuffer; // receiver ring buff overflow - pAd->stats.rx_crc_errors = 0;//pAd->WlanCounters.FCSErrorCount; // recved pkt with crc error - pAd->stats.rx_frame_errors = pAd->Counters8023.RcvAlignmentErrors; // recv'd frame alignment error - pAd->stats.rx_fifo_errors = pAd->Counters8023.RxNoBuffer; // recv'r fifo overrun - pAd->stats.rx_missed_errors = 0; // receiver missed packet - - // detailed tx_errors - pAd->stats.tx_aborted_errors = 0; - pAd->stats.tx_carrier_errors = 0; - pAd->stats.tx_fifo_errors = 0; - pAd->stats.tx_heartbeat_errors = 0; - pAd->stats.tx_window_errors = 0; - - // for cslip etc - pAd->stats.rx_compressed = 0; - pAd->stats.tx_compressed = 0; - - return &pAd->stats; - } - else - return NULL; -} - - -BOOLEAN RtmpPhyNetDevExit( - IN RTMP_ADAPTER *pAd, - IN PNET_DEV net_dev) -{ - - - -#ifdef INF_AMAZON_PPA - if (ppa_hook_directpath_register_dev_fn && pAd->PPAEnable==TRUE) - { - UINT status; - status=ppa_hook_directpath_register_dev_fn(&pAd->g_if_id, pAd->net_dev, NULL, PPA_F_DIRECTPATH_DEREGISTER); - printk("unregister PPA:g_if_id=%d status=%d\n",pAd->g_if_id,status); - } - kfree(pAd->pDirectpathCb); -#endif // INF_AMAZON_PPA // - - // Unregister network device - if (net_dev != NULL) - { - printk("RtmpOSNetDevDetach(): RtmpOSNetDeviceDetach(), dev->name=%s!\n", net_dev->name); - RtmpOSNetDevDetach(net_dev); - } - - return TRUE; - -} - - -/* -======================================================================== -Routine Description: - Allocate memory for adapter control block. - -Arguments: - pAd Pointer to our adapter - -Return Value: - NDIS_STATUS_SUCCESS - NDIS_STATUS_FAILURE - NDIS_STATUS_RESOURCES - -Note: -======================================================================== -*/ -NDIS_STATUS AdapterBlockAllocateMemory( - IN PVOID handle, - OUT PVOID *ppAd) -{ - - *ppAd = (PVOID)vmalloc(sizeof(RTMP_ADAPTER)); //pci_alloc_consistent(pci_dev, sizeof(RTMP_ADAPTER), phy_addr); - - if (*ppAd) - { - NdisZeroMemory(*ppAd, sizeof(RTMP_ADAPTER)); - ((PRTMP_ADAPTER)*ppAd)->OS_Cookie = handle; - return (NDIS_STATUS_SUCCESS); - } else { - return (NDIS_STATUS_FAILURE); - } -} diff --git a/drivers/staging/rt3090/rt_pci_rbus.c b/drivers/staging/rt3090/rt_pci_rbus.c deleted file mode 100644 index 29913191273beada86d008e8a412ec810287b999..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rt_pci_rbus.c +++ /dev/null @@ -1,989 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rt_pci_rbus.c - - Abstract: - Create and register network interface. - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#include "rt_config.h" -#include - - -IRQ_HANDLE_TYPE -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) -rt2860_interrupt(int irq, void *dev_instance); -#else -rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -#endif - - -static void rx_done_tasklet(unsigned long data); -static void mgmt_dma_done_tasklet(unsigned long data); -static void ac0_dma_done_tasklet(unsigned long data); -static void ac1_dma_done_tasklet(unsigned long data); -static void ac2_dma_done_tasklet(unsigned long data); -static void ac3_dma_done_tasklet(unsigned long data); -/*static void hcca_dma_done_tasklet(unsigned long data);*/ -static void fifo_statistic_full_tasklet(unsigned long data); - - - -/*---------------------------------------------------------------------*/ -/* Symbol & Macro Definitions */ -/*---------------------------------------------------------------------*/ -#define RT2860_INT_RX_DLY (1<<0) // bit 0 -#define RT2860_INT_TX_DLY (1<<1) // bit 1 -#define RT2860_INT_RX_DONE (1<<2) // bit 2 -#define RT2860_INT_AC0_DMA_DONE (1<<3) // bit 3 -#define RT2860_INT_AC1_DMA_DONE (1<<4) // bit 4 -#define RT2860_INT_AC2_DMA_DONE (1<<5) // bit 5 -#define RT2860_INT_AC3_DMA_DONE (1<<6) // bit 6 -#define RT2860_INT_HCCA_DMA_DONE (1<<7) // bit 7 -#define RT2860_INT_MGMT_DONE (1<<8) // bit 8 -#ifdef TONE_RADAR_DETECT_SUPPORT -#define RT2860_INT_TONE_RADAR (1<<20) // bit 20 -#endif // TONE_RADAR_DETECT_SUPPORT // - -#define INT_RX RT2860_INT_RX_DONE - -#define INT_AC0_DLY (RT2860_INT_AC0_DMA_DONE) //| RT2860_INT_TX_DLY) -#define INT_AC1_DLY (RT2860_INT_AC1_DMA_DONE) //| RT2860_INT_TX_DLY) -#define INT_AC2_DLY (RT2860_INT_AC2_DMA_DONE) //| RT2860_INT_TX_DLY) -#define INT_AC3_DLY (RT2860_INT_AC3_DMA_DONE) //| RT2860_INT_TX_DLY) -#define INT_HCCA_DLY (RT2860_INT_HCCA_DMA_DONE) //| RT2860_INT_TX_DLY) -#define INT_MGMT_DLY RT2860_INT_MGMT_DONE -#ifdef TONE_RADAR_DETECT_SUPPORT -#define INT_TONE_RADAR (RT2860_INT_TONE_RADAR) -#endif // TONE_RADAR_DETECT_SUPPORT // - - -/*************************************************************************** - * - * Interface-depended memory allocation/Free related procedures. - * Mainly for Hardware TxDesc/RxDesc/MgmtDesc, DMA Memory for TxData/RxData, etc., - * - **************************************************************************/ -// Function for TxDesc Memory allocation. -void RTMP_AllocateTxDescMemory( - IN PRTMP_ADAPTER pAd, - IN UINT Index, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - - *VirtualAddress = (PVOID)pci_alloc_consistent(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); - -} - - -// Function for MgmtDesc Memory allocation. -void RTMP_AllocateMgmtDescMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - - *VirtualAddress = (PVOID)pci_alloc_consistent(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); - -} - - -// Function for RxDesc Memory allocation. -void RTMP_AllocateRxDescMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - - *VirtualAddress = (PVOID)pci_alloc_consistent(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); - -} - - -// Function for free allocated Desc Memory. -void RTMP_FreeDescMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN PVOID VirtualAddress, - IN NDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - - pci_free_consistent(pObj->pci_dev, Length, VirtualAddress, PhysicalAddress); -} - - -// Function for TxData DMA Memory allocation. -void RTMP_AllocateFirstTxBuffer( - IN PRTMP_ADAPTER pAd, - IN UINT Index, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - - *VirtualAddress = (PVOID)pci_alloc_consistent(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); -} - - -void RTMP_FreeFirstTxBuffer( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - IN PVOID VirtualAddress, - IN NDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - - pci_free_consistent(pObj->pci_dev, Length, VirtualAddress, PhysicalAddress); -} - - -/* - * FUNCTION: Allocate a common buffer for DMA - * ARGUMENTS: - * AdapterHandle: AdapterHandle - * Length: Number of bytes to allocate - * Cached: Whether or not the memory can be cached - * VirtualAddress: Pointer to memory is returned here - * PhysicalAddress: Physical address corresponding to virtual address - */ -void RTMP_AllocateSharedMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - - *VirtualAddress = (PVOID)pci_alloc_consistent(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress); -} - - -/* - * FUNCTION: Allocate a packet buffer for DMA - * ARGUMENTS: - * AdapterHandle: AdapterHandle - * Length: Number of bytes to allocate - * Cached: Whether or not the memory can be cached - * VirtualAddress: Pointer to memory is returned here - * PhysicalAddress: Physical address corresponding to virtual address - * Notes: - * Cached is ignored: always cached memory - */ -PNDIS_PACKET RTMP_AllocateRxPacketBuffer( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) -{ - struct sk_buff *pkt; - - pkt = dev_alloc_skb(Length); - - if (pkt == NULL) { - DBGPRINT(RT_DEBUG_ERROR, ("can't allocate rx %ld size packet\n",Length)); - } - - if (pkt) { - RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); - *VirtualAddress = (PVOID) pkt->data; -//#ifdef CONFIG_5VT_ENHANCE -// *PhysicalAddress = PCI_MAP_SINGLE(pAd, *VirtualAddress, 1600, PCI_DMA_FROMDEVICE); -//#else - *PhysicalAddress = PCI_MAP_SINGLE(pAd, *VirtualAddress, Length, -1, PCI_DMA_FROMDEVICE); -//#endif - } else { - *VirtualAddress = (PVOID) NULL; - *PhysicalAddress = (NDIS_PHYSICAL_ADDRESS) NULL; - } - - return (PNDIS_PACKET) pkt; -} - - -VOID Invalid_Remaining_Packet( - IN PRTMP_ADAPTER pAd, - IN ULONG VirtualAddress) -{ - NDIS_PHYSICAL_ADDRESS PhysicalAddress; - - PhysicalAddress = PCI_MAP_SINGLE(pAd, (void *)(VirtualAddress+1600), RX_BUFFER_NORMSIZE-1600, -1, PCI_DMA_FROMDEVICE); -} - - -int RtmpOSIRQRequest(IN struct net_device *net_dev) -{ - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)(RTMP_OS_NETDEV_GET_PRIV(net_dev)); - int retval = 0; - - ASSERT(pAd); - - if (pAd->infType != RTMP_DEV_INF_RBUS) - { - POS_COOKIE _pObj = (POS_COOKIE)(pAd->OS_Cookie); - RTMP_MSI_ENABLE(pAd); - retval = request_irq(_pObj->pci_dev->irq, rt2860_interrupt, SA_SHIRQ, (net_dev)->name, (net_dev)); - if (retval != 0) - printk("RT2860: request_irq ERROR(%d)\n", retval); - } - else - { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - if ((retval = request_irq(net_dev->irq, rt2860_interrupt, IRQF_SHARED, net_dev->name ,net_dev))) -#else - if ((retval = request_irq(net_dev->irq,rt2860_interrupt, SA_INTERRUPT, net_dev->name ,net_dev))) -#endif - { - printk("RT2860: request_irq ERROR(%d)\n", retval); - } - } - - return retval; - -} - - -int RtmpOSIRQRelease(IN struct net_device *net_dev) -{ - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)(RTMP_OS_NETDEV_GET_PRIV(net_dev)); - - ASSERT(pAd); - if (pAd->infType != RTMP_DEV_INF_RBUS) - { - POS_COOKIE pObj = (POS_COOKIE)(pAd->OS_Cookie); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - synchronize_irq(pObj->pci_dev->irq); -#endif - free_irq(pObj->pci_dev->irq, (net_dev)); - RTMP_MSI_DISABLE(pAd); - } - else - { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - synchronize_irq(net_dev->irq); -#endif - free_irq(net_dev->irq, (net_dev)); - } - - return 0; -} - - -NDIS_STATUS RtmpNetTaskInit(IN RTMP_ADAPTER *pAd) -{ - POS_COOKIE pObj; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - tasklet_init(&pObj->rx_done_task, rx_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->mgmt_dma_done_task, mgmt_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->ac0_dma_done_task, ac0_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->ac1_dma_done_task, ac1_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->ac2_dma_done_task, ac2_dma_done_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->ac3_dma_done_task, ac3_dma_done_tasklet, (unsigned long)pAd); - /*tasklet_init(&pObj->hcca_dma_done_task, hcca_dma_done_tasklet, (unsigned long)pAd);*/ - tasklet_init(&pObj->tbtt_task, tbtt_tasklet, (unsigned long)pAd); - tasklet_init(&pObj->fifo_statistic_full_task, fifo_statistic_full_tasklet, (unsigned long)pAd); - - return NDIS_STATUS_SUCCESS; -} - - -void RtmpNetTaskExit(IN RTMP_ADAPTER *pAd) -{ - POS_COOKIE pObj; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - tasklet_kill(&pObj->rx_done_task); - tasklet_kill(&pObj->mgmt_dma_done_task); - tasklet_kill(&pObj->ac0_dma_done_task); - tasklet_kill(&pObj->ac1_dma_done_task); - tasklet_kill(&pObj->ac2_dma_done_task); - tasklet_kill(&pObj->ac3_dma_done_task); - /*tasklet_kill(&pObj->hcca_dma_done_task);*/ - tasklet_kill(&pObj->tbtt_task); - tasklet_kill(&pObj->fifo_statistic_full_task); -} - - -NDIS_STATUS RtmpMgmtTaskInit(IN RTMP_ADAPTER *pAd) -{ - - - return NDIS_STATUS_SUCCESS; -} - - -/* -======================================================================== -Routine Description: - Close kernel threads. - -Arguments: - *pAd the raxx interface data pointer - -Return Value: - NONE - -Note: -======================================================================== -*/ -VOID RtmpMgmtTaskExit( - IN RTMP_ADAPTER *pAd) -{ - - - return; -} - - -static inline void rt2860_int_enable(PRTMP_ADAPTER pAd, unsigned int mode) -{ - u32 regValue; - - pAd->int_disable_mask &= ~(mode); - regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask); - //if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); // 1:enable - } - //else - // DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_DOZE !\n")); - - if (regValue != 0) - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE); -} - - -static inline void rt2860_int_disable(PRTMP_ADAPTER pAd, unsigned int mode) -{ - u32 regValue; - - pAd->int_disable_mask |= mode; - regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask); - RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); // 0: disable - - if (regValue == 0) - { - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE); - } -} - - -/*************************************************************************** - * - * tasklet related procedures. - * - **************************************************************************/ -static void mgmt_dma_done_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - INT_SOURCE_CSR_STRUC IntSource; - POS_COOKIE pObj; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - -// printk("mgmt_dma_done_process\n"); - IntSource.word = 0; - IntSource.field.MgmtDmaDone = 1; - pAd->int_pending &= ~INT_MGMT_DLY; - - RTMPHandleMgmtRingDmaDoneInterrupt(pAd); - - // if you use RTMP_SEM_LOCK, sometimes kernel will hang up, no any - // bug report output - RTMP_INT_LOCK(&pAd->irq_lock, flags); - /* - * double check to avoid lose of interrupts - */ - if (pAd->int_pending & INT_MGMT_DLY) - { - tasklet_hi_schedule(&pObj->mgmt_dma_done_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable TxDataInt again */ - rt2860_int_enable(pAd, INT_MGMT_DLY); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); -} - - -static void rx_done_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - BOOLEAN bReschedule = 0; - POS_COOKIE pObj; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - -#ifdef UAPSD_AP_SUPPORT - UAPSD_TIMING_RECORD(pAd, UAPSD_TIMING_RECORD_TASKLET); -#endif // UAPSD_AP_SUPPORT // - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - pAd->int_pending &= ~(INT_RX); -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - bReschedule = STARxDoneInterruptHandle(pAd, 0); -#endif // CONFIG_STA_SUPPORT // - -#ifdef UAPSD_AP_SUPPORT - UAPSD_TIMING_RECORD_STOP(); -#endif // UAPSD_AP_SUPPORT // - - RTMP_INT_LOCK(&pAd->irq_lock, flags); - /* - * double check to avoid rotting packet - */ - if (pAd->int_pending & INT_RX || bReschedule) - { - tasklet_hi_schedule(&pObj->rx_done_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable RxINT again */ - rt2860_int_enable(pAd, INT_RX); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - -} - - -void fifo_statistic_full_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - POS_COOKIE pObj; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - pAd->int_pending &= ~(FifoStaFullInt); - NICUpdateFifoStaCounters(pAd); - - RTMP_INT_LOCK(&pAd->irq_lock, flags); - /* - * double check to avoid rotting packet - */ - if (pAd->int_pending & FifoStaFullInt) - { - tasklet_hi_schedule(&pObj->fifo_statistic_full_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable RxINT again */ - - rt2860_int_enable(pAd, FifoStaFullInt); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - -} - - - - -static void ac3_dma_done_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - INT_SOURCE_CSR_STRUC IntSource; - POS_COOKIE pObj; - BOOLEAN bReschedule = 0; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - -// printk("ac0_dma_done_process\n"); - IntSource.word = 0; - IntSource.field.Ac3DmaDone = 1; - pAd->int_pending &= ~INT_AC3_DLY; - - bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); - - RTMP_INT_LOCK(&pAd->irq_lock, flags); - /* - * double check to avoid lose of interrupts - */ - if ((pAd->int_pending & INT_AC3_DLY) || bReschedule) - { - tasklet_hi_schedule(&pObj->ac3_dma_done_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable TxDataInt again */ - rt2860_int_enable(pAd, INT_AC3_DLY); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); -} - - -static void ac2_dma_done_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - INT_SOURCE_CSR_STRUC IntSource; - POS_COOKIE pObj; - BOOLEAN bReschedule = 0; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - IntSource.word = 0; - IntSource.field.Ac2DmaDone = 1; - pAd->int_pending &= ~INT_AC2_DLY; - - bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); - - RTMP_INT_LOCK(&pAd->irq_lock, flags); - - /* - * double check to avoid lose of interrupts - */ - if ((pAd->int_pending & INT_AC2_DLY) || bReschedule) - { - tasklet_hi_schedule(&pObj->ac2_dma_done_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable TxDataInt again */ - rt2860_int_enable(pAd, INT_AC2_DLY); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); -} - - -static void ac1_dma_done_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - INT_SOURCE_CSR_STRUC IntSource; - POS_COOKIE pObj; - BOOLEAN bReschedule = 0; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - -// printk("ac0_dma_done_process\n"); - IntSource.word = 0; - IntSource.field.Ac1DmaDone = 1; - pAd->int_pending &= ~INT_AC1_DLY; - - bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); - - RTMP_INT_LOCK(&pAd->irq_lock, flags); - /* - * double check to avoid lose of interrupts - */ - if ((pAd->int_pending & INT_AC1_DLY) || bReschedule) - { - tasklet_hi_schedule(&pObj->ac1_dma_done_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable TxDataInt again */ - rt2860_int_enable(pAd, INT_AC1_DLY); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); -} - - -static void ac0_dma_done_tasklet(unsigned long data) -{ - unsigned long flags; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; - INT_SOURCE_CSR_STRUC IntSource; - POS_COOKIE pObj; - BOOLEAN bReschedule = 0; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - -// printk("ac0_dma_done_process\n"); - IntSource.word = 0; - IntSource.field.Ac0DmaDone = 1; - pAd->int_pending &= ~INT_AC0_DLY; - -// RTMPHandleMgmtRingDmaDoneInterrupt(pAd); - bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); - - RTMP_INT_LOCK(&pAd->irq_lock, flags); - /* - * double check to avoid lose of interrupts - */ - if ((pAd->int_pending & INT_AC0_DLY) || bReschedule) - { - tasklet_hi_schedule(&pObj->ac0_dma_done_task); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); - return; - } - - /* enable TxDataInt again */ - rt2860_int_enable(pAd, INT_AC0_DLY); - RTMP_INT_UNLOCK(&pAd->irq_lock, flags); -} - - - - -/*************************************************************************** - * - * interrupt handler related procedures. - * - **************************************************************************/ -int print_int_count; - -IRQ_HANDLE_TYPE -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) -rt2860_interrupt(int irq, void *dev_instance) -#else -rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -#endif -{ - struct net_device *net_dev = (struct net_device *) dev_instance; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) RTMP_OS_NETDEV_GET_PRIV(net_dev); - INT_SOURCE_CSR_STRUC IntSource; - POS_COOKIE pObj; - - pObj = (POS_COOKIE) pAd->OS_Cookie; - - - /* Note 03312008: we can not return here before - RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word); - RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word); - Or kernel will panic after ifconfig ra0 down sometimes */ - - - // - // Inital the Interrupt source. - // - IntSource.word = 0x00000000L; -// McuIntSource.word = 0x00000000L; - - // - // Get the interrupt sources & saved to local variable - // - //RTMP_IO_READ32(pAd, where, &McuIntSource.word); - //RTMP_IO_WRITE32(pAd, , McuIntSource.word); - - // - // Flag fOP_STATUS_DOZE On, means ASIC put to sleep, elase means ASICK WakeUp - // And at the same time, clock maybe turned off that say there is no DMA service. - // when ASIC get to sleep. - // To prevent system hang on power saving. - // We need to check it before handle the INT_SOURCE_CSR, ASIC must be wake up. - // - // RT2661 => when ASIC is sleeping, MAC register cannot be read and written. - // RT2860 => when ASIC is sleeping, MAC register can be read and written. -// if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word); - RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word); // write 1 to clear - } -// else -// DBGPRINT(RT_DEBUG_TRACE, (">>>fOP_STATUS_DOZE<<<\n")); - -// RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IsrAfterClear); -// RTMP_IO_READ32(pAd, MCU_INT_SOURCE_CSR, &McuIsrAfterClear); -// DBGPRINT(RT_DEBUG_INFO, ("====> RTMPHandleInterrupt(ISR=%08x,Mcu ISR=%08x, After clear ISR=%08x, MCU ISR=%08x)\n", -// IntSource.word, McuIntSource.word, IsrAfterClear, McuIsrAfterClear)); - - // Do nothing if Reset in progress - if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |fRTMP_ADAPTER_HALT_IN_PROGRESS))) - { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - return IRQ_HANDLED; -#else - return; -#endif - } - - // - // Handle interrupt, walk through all bits - // Should start from highest priority interrupt - // The priority can be adjust by altering processing if statement - // - -#ifdef DBG - -#endif - - - pAd->bPCIclkOff = FALSE; - - // If required spinlock, each interrupt service routine has to acquire - // and release itself. - // - - // Do nothing if NIC doesn't exist - if (IntSource.word == 0xffffffff) - { - RTMP_SET_FLAG(pAd, (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - return IRQ_HANDLED; -#else - return; -#endif - } - - if (IntSource.word & TxCoherent) - { - DBGPRINT(RT_DEBUG_ERROR, (">>>TxCoherent<<<\n")); - RTMPHandleRxCoherentInterrupt(pAd); - } - - if (IntSource.word & RxCoherent) - { - DBGPRINT(RT_DEBUG_ERROR, (">>>RxCoherent<<<\n")); - RTMPHandleRxCoherentInterrupt(pAd); - } - - if (IntSource.word & FifoStaFullInt) - { - if ((pAd->int_disable_mask & FifoStaFullInt) == 0) - { - /* mask FifoStaFullInt */ - rt2860_int_disable(pAd, FifoStaFullInt); - tasklet_hi_schedule(&pObj->fifo_statistic_full_task); - } - pAd->int_pending |= FifoStaFullInt; - } - - if (IntSource.word & INT_MGMT_DLY) - { - if ((pAd->int_disable_mask & INT_MGMT_DLY) ==0 ) - { - rt2860_int_disable(pAd, INT_MGMT_DLY); - tasklet_hi_schedule(&pObj->mgmt_dma_done_task); - } - pAd->int_pending |= INT_MGMT_DLY ; - } - - if (IntSource.word & INT_RX) - { - if ((pAd->int_disable_mask & INT_RX) == 0) - { - - /* mask RxINT */ - rt2860_int_disable(pAd, INT_RX); - tasklet_hi_schedule(&pObj->rx_done_task); - } - pAd->int_pending |= INT_RX; - } - - - if (IntSource.word & INT_AC3_DLY) - { - - if ((pAd->int_disable_mask & INT_AC3_DLY) == 0) - { - /* mask TxDataInt */ - rt2860_int_disable(pAd, INT_AC3_DLY); - tasklet_hi_schedule(&pObj->ac3_dma_done_task); - } - pAd->int_pending |= INT_AC3_DLY; - } - - if (IntSource.word & INT_AC2_DLY) - { - - if ((pAd->int_disable_mask & INT_AC2_DLY) == 0) - { - /* mask TxDataInt */ - rt2860_int_disable(pAd, INT_AC2_DLY); - tasklet_hi_schedule(&pObj->ac2_dma_done_task); - } - pAd->int_pending |= INT_AC2_DLY; - } - - if (IntSource.word & INT_AC1_DLY) - { - - pAd->int_pending |= INT_AC1_DLY; - - if ((pAd->int_disable_mask & INT_AC1_DLY) == 0) - { - /* mask TxDataInt */ - rt2860_int_disable(pAd, INT_AC1_DLY); - tasklet_hi_schedule(&pObj->ac1_dma_done_task); - } - - } - - if (IntSource.word & INT_AC0_DLY) - { - -/* - if (IntSource.word & 0x2) { - u32 reg; - RTMP_IO_READ32(pAd, DELAY_INT_CFG, ®); - printk("IntSource.word = %08x, DELAY_REG = %08x\n", IntSource.word, reg); - } -*/ - pAd->int_pending |= INT_AC0_DLY; - - if ((pAd->int_disable_mask & INT_AC0_DLY) == 0) - { - /* mask TxDataInt */ - rt2860_int_disable(pAd, INT_AC0_DLY); - tasklet_hi_schedule(&pObj->ac0_dma_done_task); - } - - } - - - if (IntSource.word & PreTBTTInt) - { - RTMPHandlePreTBTTInterrupt(pAd); - } - - if (IntSource.word & TBTTInt) - { - RTMPHandleTBTTInterrupt(pAd); - } - - - - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - if (IntSource.word & AutoWakeupInt) - RTMPHandleTwakeupInterrupt(pAd); - } -#endif // CONFIG_STA_SUPPORT // - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - return IRQ_HANDLED; -#endif - -} - -/* - * invaild or writeback cache - * and convert virtual address to physical address - */ -dma_addr_t linux_pci_map_single(void *handle, void *ptr, size_t size, int sd_idx, int direction) -{ - PRTMP_ADAPTER pAd; - POS_COOKIE pObj; - - /* - ------ Porting Information ------ - > For Tx Alloc: - mgmt packets => sd_idx = 0 - SwIdx: pAd->MgmtRing.TxCpuIdx - pTxD : pAd->MgmtRing.Cell[SwIdx].AllocVa; - - data packets => sd_idx = 1 - TxIdx : pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx - QueIdx: pTxBlk->QueIdx - pTxD : pAd->TxRing[pTxBlk->QueIdx].Cell[TxIdx].AllocVa; - - > For Rx Alloc: - sd_idx = -1 - */ - - pAd = (PRTMP_ADAPTER)handle; - pObj = (POS_COOKIE)pAd->OS_Cookie; - - if (sd_idx == 1) - { - PTX_BLK pTxBlk; - pTxBlk = (PTX_BLK)ptr; - return pci_map_single(pObj->pci_dev, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, direction); - } - else - { - return pci_map_single(pObj->pci_dev, ptr, size, direction); - } - -} - -void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size, int direction) -{ - PRTMP_ADAPTER pAd; - POS_COOKIE pObj; - - pAd=(PRTMP_ADAPTER)handle; - pObj = (POS_COOKIE)pAd->OS_Cookie; - - pci_unmap_single(pObj->pci_dev, dma_addr, size, direction); - -} diff --git a/drivers/staging/rt3090/rt_profile.c b/drivers/staging/rt3090/rt_profile.c deleted file mode 100644 index 49a05901bad4b53442307a954d47a1951763ff72..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rt_profile.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rt_profile.c - - Abstract: - - Revision History: - Who When What - --------- ---------- ---------------------------------------------- - */ - -#include "rt_config.h" - - -NDIS_STATUS RTMPReadParametersHook( - IN PRTMP_ADAPTER pAd) -{ - PSTRING src = NULL; - RTMP_OS_FD srcf; - RTMP_OS_FS_INFO osFSInfo; - INT retval = NDIS_STATUS_FAILURE; - PSTRING buffer; - - buffer = kmalloc(MAX_INI_BUFFER_SIZE, MEM_ALLOC_FLAG); - if(buffer == NULL) - return NDIS_STATUS_FAILURE; - memset(buffer, 0x00, MAX_INI_BUFFER_SIZE); - - { - -#ifdef CONFIG_STA_SUPPORT - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - src = STA_PROFILE_PATH; - } -#endif // CONFIG_STA_SUPPORT // -#ifdef MULTIPLE_CARD_SUPPORT - src = (PSTRING)pAd->MC_FileName; -#endif // MULTIPLE_CARD_SUPPORT // - } - - if (src && *src) - { - RtmpOSFSInfoChange(&osFSInfo, TRUE); - srcf = RtmpOSFileOpen(src, O_RDONLY, 0); - if (IS_FILE_OPEN_ERR(srcf)) - { - DBGPRINT(RT_DEBUG_ERROR, ("Open file \"%s\" failed!\n", src)); - } - else - { - retval =RtmpOSFileRead(srcf, buffer, MAX_INI_BUFFER_SIZE); - if (retval > 0) - { - RTMPSetProfileParameters(pAd, buffer); - retval = NDIS_STATUS_SUCCESS; - } - else - DBGPRINT(RT_DEBUG_ERROR, ("Read file \"%s\" failed(errCode=%d)!\n", src, retval)); - - retval = RtmpOSFileClose(srcf); - if ( retval != 0) - { - retval = NDIS_STATUS_FAILURE; - DBGPRINT(RT_DEBUG_ERROR, ("Close file \"%s\" failed(errCode=%d)!\n", src, retval)); - } - } - - RtmpOSFSInfoChange(&osFSInfo, FALSE); - } - - kfree(buffer); - - return (retval); - -} diff --git a/drivers/staging/rt3090/rtmp.h b/drivers/staging/rt3090/rtmp.h deleted file mode 100644 index 8ef6d0bfdee68bef15d372c6c499e30d6c7ce5f1..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rtmp.h +++ /dev/null @@ -1,6873 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rtmp.h - - Abstract: - Miniport generic portion header file - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Paul Lin 2002-08-01 created - James Tan 2002-09-06 modified (Revise NTCRegTable) - John Chang 2004-09-06 modified for RT2600 -*/ -#ifndef __RTMP_H__ -#define __RTMP_H__ - -#include "link_list.h" -#include "spectrum_def.h" - -#include "rtmp_dot11.h" - -#ifdef MLME_EX -#include "mlme_ex_def.h" -#endif // MLME_EX // - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - -#undef AP_WSC_INCLUDED -#undef STA_WSC_INCLUDED -#undef WSC_INCLUDED - - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - -#if defined(AP_WSC_INCLUDED) || defined(STA_WSC_INCLUDED) -#define WSC_INCLUDED -#endif - - - - - -#include "rtmp_chip.h" - - - -typedef struct _RTMP_ADAPTER RTMP_ADAPTER; -typedef struct _RTMP_ADAPTER *PRTMP_ADAPTER; - -typedef struct _RTMP_CHIP_OP_ RTMP_CHIP_OP; - - -//#define DBG 1 - -//#define DBG_DIAGNOSE 1 - - -//+++Add by shiang for merge MiniportMMRequest() and MiniportDataMMRequest() into one function -#define MAX_DATAMM_RETRY 3 -#define MGMT_USE_QUEUE_FLAG 0x80 -//---Add by shiang for merge MiniportMMRequest() and MiniportDataMMRequest() into one function - -#define MAXSEQ (0xFFF) - - -#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_STA_SUPPORT) -#define IF_DEV_CONFIG_OPMODE_ON_AP(_pAd) if(_pAd->OpMode == OPMODE_AP) -#define IF_DEV_CONFIG_OPMODE_ON_STA(_pAd) if(_pAd->OpMode == OPMODE_STA) -#else -#define IF_DEV_CONFIG_OPMODE_ON_AP(_pAd) -#define IF_DEV_CONFIG_OPMODE_ON_STA(_pAd) -#endif - -extern unsigned char SNAP_AIRONET[]; -extern unsigned char CISCO_OUI[]; -extern UCHAR BaSizeArray[4]; - -extern UCHAR BROADCAST_ADDR[MAC_ADDR_LEN]; -extern UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN]; -extern ULONG BIT32[32]; -extern UCHAR BIT8[8]; -extern char* CipherName[]; -extern char* MCSToMbps[]; -extern UCHAR RxwiMCSToOfdmRate[12]; -extern UCHAR SNAP_802_1H[6]; -extern UCHAR SNAP_BRIDGE_TUNNEL[6]; -extern UCHAR SNAP_AIRONET[8]; -extern UCHAR CKIP_LLC_SNAP[8]; -extern UCHAR EAPOL_LLC_SNAP[8]; -extern UCHAR EAPOL[2]; -extern UCHAR IPX[2]; -extern UCHAR APPLE_TALK[2]; -extern UCHAR RateIdToPlcpSignal[12]; // see IEEE802.11a-1999 p.14 -extern UCHAR OfdmRateToRxwiMCS[]; -extern UCHAR OfdmSignalToRateId[16] ; -extern UCHAR default_cwmin[4]; -extern UCHAR default_cwmax[4]; -extern UCHAR default_sta_aifsn[4]; -extern UCHAR MapUserPriorityToAccessCategory[8]; - -extern USHORT RateUpPER[]; -extern USHORT RateDownPER[]; -extern UCHAR Phy11BNextRateDownward[]; -extern UCHAR Phy11BNextRateUpward[]; -extern UCHAR Phy11BGNextRateDownward[]; -extern UCHAR Phy11BGNextRateUpward[]; -extern UCHAR Phy11ANextRateDownward[]; -extern UCHAR Phy11ANextRateUpward[]; -extern CHAR RssiSafeLevelForTxRate[]; -extern UCHAR RateIdToMbps[]; -extern USHORT RateIdTo500Kbps[]; - -extern UCHAR CipherSuiteWpaNoneTkip[]; -extern UCHAR CipherSuiteWpaNoneTkipLen; - -extern UCHAR CipherSuiteWpaNoneAes[]; -extern UCHAR CipherSuiteWpaNoneAesLen; - -extern UCHAR SsidIe; -extern UCHAR SupRateIe; -extern UCHAR ExtRateIe; - -#ifdef DOT11_N_SUPPORT -extern UCHAR HtCapIe; -extern UCHAR AddHtInfoIe; -extern UCHAR NewExtChanIe; -#ifdef DOT11N_DRAFT3 -extern UCHAR ExtHtCapIe; -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // - -extern UCHAR ErpIe; -extern UCHAR DsIe; -extern UCHAR TimIe; -extern UCHAR WpaIe; -extern UCHAR Wpa2Ie; -extern UCHAR IbssIe; -extern UCHAR Ccx2Ie; -extern UCHAR WapiIe; - -extern UCHAR WPA_OUI[]; -extern UCHAR RSN_OUI[]; -extern UCHAR WAPI_OUI[]; -extern UCHAR WME_INFO_ELEM[]; -extern UCHAR WME_PARM_ELEM[]; -extern UCHAR Ccx2QosInfo[]; -extern UCHAR Ccx2IeInfo[]; -extern UCHAR RALINK_OUI[]; -extern UCHAR PowerConstraintIE[]; - - -extern UCHAR RateSwitchTable[]; -extern UCHAR RateSwitchTable11B[]; -extern UCHAR RateSwitchTable11G[]; -extern UCHAR RateSwitchTable11BG[]; - -#ifdef DOT11_N_SUPPORT -extern UCHAR RateSwitchTable11BGN1S[]; -extern UCHAR RateSwitchTable11BGN2S[]; -extern UCHAR RateSwitchTable11BGN2SForABand[]; -extern UCHAR RateSwitchTable11N1S[]; -extern UCHAR RateSwitchTable11N2S[]; -extern UCHAR RateSwitchTable11N2SForABand[]; - -#ifdef CONFIG_STA_SUPPORT -extern UCHAR PRE_N_HT_OUI[]; -#endif // CONFIG_STA_SUPPORT // -#endif // DOT11_N_SUPPORT // - - -#ifdef RALINK_ATE -typedef struct _ATE_INFO { - UCHAR Mode; - CHAR TxPower0; - CHAR TxPower1; - CHAR TxAntennaSel; - CHAR RxAntennaSel; - TXWI_STRUC TxWI; // TXWI - USHORT QID; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; - UCHAR Addr3[MAC_ADDR_LEN]; - UCHAR Channel; - UINT32 TxLength; - UINT32 TxCount; - UINT32 TxDoneCount; // Tx DMA Done - UINT32 RFFreqOffset; - BOOLEAN bRxFER; // Show Rx Frame Error Rate - BOOLEAN bQATxStart; // Have compiled QA in and use it to ATE tx. - BOOLEAN bQARxStart; // Have compiled QA in and use it to ATE rx. -#ifdef RTMP_MAC_PCI - BOOLEAN bFWLoading; // Reload firmware when ATE is done. -#endif // RTMP_MAC_PCI // - UINT32 RxTotalCnt; - UINT32 RxCntPerSec; - - CHAR LastSNR0; // last received SNR - CHAR LastSNR1; // last received SNR for 2nd antenna - CHAR LastRssi0; // last received RSSI - CHAR LastRssi1; // last received RSSI for 2nd antenna - CHAR LastRssi2; // last received RSSI for 3rd antenna - CHAR AvgRssi0; // last 8 frames' average RSSI - CHAR AvgRssi1; // last 8 frames' average RSSI - CHAR AvgRssi2; // last 8 frames' average RSSI - SHORT AvgRssi0X8; // sum of last 8 frames' RSSI - SHORT AvgRssi1X8; // sum of last 8 frames' RSSI - SHORT AvgRssi2X8; // sum of last 8 frames' RSSI - - UINT32 NumOfAvgRssiSample; - - -#ifdef RALINK_28xx_QA - // Tx frame - USHORT HLen; // Header Length - USHORT PLen; // Pattern Length - UCHAR Header[32]; // Header buffer - UCHAR Pattern[32]; // Pattern buffer - USHORT DLen; // Data Length - USHORT seq; - UINT32 CID; - RTMP_OS_PID AtePid; - // counters - UINT32 U2M; - UINT32 OtherData; - UINT32 Beacon; - UINT32 OtherCount; - UINT32 TxAc0; - UINT32 TxAc1; - UINT32 TxAc2; - UINT32 TxAc3; - /*UINT32 TxHCCA;*/ - UINT32 TxMgmt; - UINT32 RSSI0; - UINT32 RSSI1; - UINT32 RSSI2; - UINT32 SNR0; - UINT32 SNR1; - // TxStatus : 0 --> task is idle, 1 --> task is running - UCHAR TxStatus; -#endif // RALINK_28xx_QA // -} ATE_INFO, *PATE_INFO; - -#ifdef RALINK_28xx_QA -struct ate_racfghdr { - UINT32 magic_no; - USHORT command_type; - USHORT command_id; - USHORT length; - USHORT sequence; - USHORT status; - UCHAR data[2046]; -} __attribute__((packed)); -#endif // RALINK_28xx_QA // -#endif // RALINK_ATE // - - -typedef struct _RSSI_SAMPLE { - CHAR LastRssi0; // last received RSSI - CHAR LastRssi1; // last received RSSI - CHAR LastRssi2; // last received RSSI - CHAR AvgRssi0; - CHAR AvgRssi1; - CHAR AvgRssi2; - SHORT AvgRssi0X8; - SHORT AvgRssi1X8; - SHORT AvgRssi2X8; -} RSSI_SAMPLE; - -// -// Queue structure and macros -// -typedef struct _QUEUE_ENTRY { - struct _QUEUE_ENTRY *Next; -} QUEUE_ENTRY, *PQUEUE_ENTRY; - -// Queue structure -typedef struct _QUEUE_HEADER { - PQUEUE_ENTRY Head; - PQUEUE_ENTRY Tail; - ULONG Number; -} QUEUE_HEADER, *PQUEUE_HEADER; - -#define InitializeQueueHeader(QueueHeader) \ -{ \ - (QueueHeader)->Head = (QueueHeader)->Tail = NULL; \ - (QueueHeader)->Number = 0; \ -} - -#define RemoveHeadQueue(QueueHeader) \ -(QueueHeader)->Head; \ -{ \ - PQUEUE_ENTRY pNext; \ - if ((QueueHeader)->Head != NULL) \ - { \ - pNext = (QueueHeader)->Head->Next; \ - (QueueHeader)->Head->Next = NULL; \ - (QueueHeader)->Head = pNext; \ - if (pNext == NULL) \ - (QueueHeader)->Tail = NULL; \ - (QueueHeader)->Number--; \ - } \ -} - -#define InsertHeadQueue(QueueHeader, QueueEntry) \ -{ \ - ((PQUEUE_ENTRY)QueueEntry)->Next = (QueueHeader)->Head; \ - (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ - if ((QueueHeader)->Tail == NULL) \ - (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ - (QueueHeader)->Number++; \ -} - -#define InsertTailQueue(QueueHeader, QueueEntry) \ -{ \ - ((PQUEUE_ENTRY)QueueEntry)->Next = NULL; \ - if ((QueueHeader)->Tail) \ - (QueueHeader)->Tail->Next = (PQUEUE_ENTRY)(QueueEntry); \ - else \ - (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ - (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ - (QueueHeader)->Number++; \ -} - -#define InsertTailQueueAc(pAd, pEntry, QueueHeader, QueueEntry) \ -{ \ - ((PQUEUE_ENTRY)QueueEntry)->Next = NULL; \ - if ((QueueHeader)->Tail) \ - (QueueHeader)->Tail->Next = (PQUEUE_ENTRY)(QueueEntry); \ - else \ - (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ - (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ - (QueueHeader)->Number++; \ -} - - - -// -// Macros for flag and ref count operations -// -#define RTMP_SET_FLAG(_M, _F) ((_M)->Flags |= (_F)) -#define RTMP_CLEAR_FLAG(_M, _F) ((_M)->Flags &= ~(_F)) -#define RTMP_CLEAR_FLAGS(_M) ((_M)->Flags = 0) -#define RTMP_TEST_FLAG(_M, _F) (((_M)->Flags & (_F)) != 0) -#define RTMP_TEST_FLAGS(_M, _F) (((_M)->Flags & (_F)) == (_F)) -// Macro for power save flag. -#define RTMP_SET_PSFLAG(_M, _F) ((_M)->PSFlags |= (_F)) -#define RTMP_CLEAR_PSFLAG(_M, _F) ((_M)->PSFlags &= ~(_F)) -#define RTMP_CLEAR_PSFLAGS(_M) ((_M)->PSFlags = 0) -#define RTMP_TEST_PSFLAG(_M, _F) (((_M)->PSFlags & (_F)) != 0) -#define RTMP_TEST_PSFLAGS(_M, _F) (((_M)->PSFlags & (_F)) == (_F)) - -#define OPSTATUS_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags |= (_F)) -#define OPSTATUS_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags &= ~(_F)) -#define OPSTATUS_TEST_FLAG(_pAd, _F) (((_pAd)->CommonCfg.OpStatusFlags & (_F)) != 0) - -#define CLIENT_STATUS_SET_FLAG(_pEntry,_F) ((_pEntry)->ClientStatusFlags |= (_F)) -#define CLIENT_STATUS_CLEAR_FLAG(_pEntry,_F) ((_pEntry)->ClientStatusFlags &= ~(_F)) -#define CLIENT_STATUS_TEST_FLAG(_pEntry,_F) (((_pEntry)->ClientStatusFlags & (_F)) != 0) - -#define RX_FILTER_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.PacketFilter |= (_F)) -#define RX_FILTER_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.PacketFilter &= ~(_F)) -#define RX_FILTER_TEST_FLAG(_pAd, _F) (((_pAd)->CommonCfg.PacketFilter & (_F)) != 0) - -#ifdef CONFIG_STA_SUPPORT -#define STA_NO_SECURITY_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11EncryptionDisabled) -#define STA_WEP_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) -#define STA_TKIP_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) -#define STA_AES_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - -#define STA_TGN_WIFI_ON(_p) (_p->StaCfg.bTGnWifiTest == TRUE) -#endif // CONFIG_STA_SUPPORT // - -#define CKIP_KP_ON(_p) ((((_p)->StaCfg.CkipFlag) & 0x10) && ((_p)->StaCfg.bCkipCmicOn == TRUE)) -#define CKIP_CMIC_ON(_p) ((((_p)->StaCfg.CkipFlag) & 0x08) && ((_p)->StaCfg.bCkipCmicOn == TRUE)) - - -#define INC_RING_INDEX(_idx, _RingSize) \ -{ \ - (_idx) = (_idx+1) % (_RingSize); \ -} - - -#ifdef DOT11_N_SUPPORT -// StaActive.SupportedHtPhy.MCSSet is copied from AP beacon. Don't need to update here. -#define COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \ -{ \ - _pAd->StaActive.SupportedHtPhy.ChannelWidth = _pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth; \ - _pAd->StaActive.SupportedHtPhy.MimoPs = _pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs; \ - _pAd->StaActive.SupportedHtPhy.GF = _pAd->MlmeAux.HtCapability.HtCapInfo.GF; \ - _pAd->StaActive.SupportedHtPhy.ShortGIfor20 = _pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20; \ - _pAd->StaActive.SupportedHtPhy.ShortGIfor40 = _pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40; \ - _pAd->StaActive.SupportedHtPhy.TxSTBC = _pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC; \ - _pAd->StaActive.SupportedHtPhy.RxSTBC = _pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC; \ - _pAd->StaActive.SupportedHtPhy.ExtChanOffset = _pAd->MlmeAux.AddHtInfo.AddHtInfo.ExtChanOffset; \ - _pAd->StaActive.SupportedHtPhy.RecomWidth = _pAd->MlmeAux.AddHtInfo.AddHtInfo.RecomWidth; \ - _pAd->StaActive.SupportedHtPhy.OperaionMode = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode; \ - _pAd->StaActive.SupportedHtPhy.NonGfPresent = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent; \ - NdisMoveMemory((_pAd)->MacTab.Content[BSSID_WCID].HTCapability.MCSSet, (_pAd)->StaActive.SupportedPhyInfo.MCSSet, sizeof(UCHAR) * 16);\ -} - -#define COPY_AP_HTSETTINGS_FROM_BEACON(_pAd, _pHtCapability) \ -{ \ - _pAd->MacTab.Content[BSSID_WCID].AMsduSize = (UCHAR)(_pHtCapability->HtCapInfo.AMsduSize); \ - _pAd->MacTab.Content[BSSID_WCID].MmpsMode= (UCHAR)(_pHtCapability->HtCapInfo.MimoPs); \ - _pAd->MacTab.Content[BSSID_WCID].MaxRAmpduFactor = (UCHAR)(_pHtCapability->HtCapParm.MaxRAmpduFactor); \ -} -#endif // DOT11_N_SUPPORT // - -// -// MACRO for 32-bit PCI register read / write -// -// Usage : RTMP_IO_READ32( -// PRTMP_ADAPTER pAd, -// ULONG Register_Offset, -// PULONG pValue) -// -// RTMP_IO_WRITE32( -// PRTMP_ADAPTER pAd, -// ULONG Register_Offset, -// ULONG Value) -// - - -// -// Common fragment list structure - Identical to the scatter gather frag list structure -// -//#define RTMP_SCATTER_GATHER_ELEMENT SCATTER_GATHER_ELEMENT -//#define PRTMP_SCATTER_GATHER_ELEMENT PSCATTER_GATHER_ELEMENT -#define NIC_MAX_PHYS_BUF_COUNT 8 - -typedef struct _RTMP_SCATTER_GATHER_ELEMENT { - PVOID Address; - ULONG Length; - PULONG Reserved; -} RTMP_SCATTER_GATHER_ELEMENT, *PRTMP_SCATTER_GATHER_ELEMENT; - - -typedef struct _RTMP_SCATTER_GATHER_LIST { - ULONG NumberOfElements; - PULONG Reserved; - RTMP_SCATTER_GATHER_ELEMENT Elements[NIC_MAX_PHYS_BUF_COUNT]; -} RTMP_SCATTER_GATHER_LIST, *PRTMP_SCATTER_GATHER_LIST; - - -// -// Some utility macros -// -#ifndef min -#define min(_a, _b) (((_a) < (_b)) ? (_a) : (_b)) -#endif - -#ifndef max -#define max(_a, _b) (((_a) > (_b)) ? (_a) : (_b)) -#endif - -#define GET_LNA_GAIN(_pAd) ((_pAd->LatchRfRegs.Channel <= 14) ? (_pAd->BLNAGain) : ((_pAd->LatchRfRegs.Channel <= 64) ? (_pAd->ALNAGain0) : ((_pAd->LatchRfRegs.Channel <= 128) ? (_pAd->ALNAGain1) : (_pAd->ALNAGain2)))) - -#define INC_COUNTER64(Val) (Val.QuadPart++) - -#define INFRA_ON(_p) (OPSTATUS_TEST_FLAG(_p, fOP_STATUS_INFRA_ON)) -#define ADHOC_ON(_p) (OPSTATUS_TEST_FLAG(_p, fOP_STATUS_ADHOC_ON)) -#define MONITOR_ON(_p) (((_p)->StaCfg.BssType) == BSS_MONITOR) -#define IDLE_ON(_p) (!INFRA_ON(_p) && !ADHOC_ON(_p)) - -// Check LEAP & CCKM flags -#define LEAP_ON(_p) (((_p)->StaCfg.LeapAuthMode) == CISCO_AuthModeLEAP) -#define LEAP_CCKM_ON(_p) ((((_p)->StaCfg.LeapAuthMode) == CISCO_AuthModeLEAP) && ((_p)->StaCfg.LeapAuthInfo.CCKM == TRUE)) - -// if orginal Ethernet frame contains no LLC/SNAP, then an extra LLC/SNAP encap is required -#define EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(_pBufVA, _pExtraLlcSnapEncap) \ -{ \ - if (((*(_pBufVA + 12) << 8) + *(_pBufVA + 13)) > 1500) \ - { \ - _pExtraLlcSnapEncap = SNAP_802_1H; \ - if (NdisEqualMemory(IPX, _pBufVA + 12, 2) || \ - NdisEqualMemory(APPLE_TALK, _pBufVA + 12, 2)) \ - { \ - _pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL; \ - } \ - } \ - else \ - { \ - _pExtraLlcSnapEncap = NULL; \ - } \ -} - -// New Define for new Tx Path. -#define EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(_pBufVA, _pExtraLlcSnapEncap) \ -{ \ - if (((*(_pBufVA) << 8) + *(_pBufVA + 1)) > 1500) \ - { \ - _pExtraLlcSnapEncap = SNAP_802_1H; \ - if (NdisEqualMemory(IPX, _pBufVA, 2) || \ - NdisEqualMemory(APPLE_TALK, _pBufVA, 2)) \ - { \ - _pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL; \ - } \ - } \ - else \ - { \ - _pExtraLlcSnapEncap = NULL; \ - } \ -} - - -#define MAKE_802_3_HEADER(_p, _pMac1, _pMac2, _pType) \ -{ \ - NdisMoveMemory(_p, _pMac1, MAC_ADDR_LEN); \ - NdisMoveMemory((_p + MAC_ADDR_LEN), _pMac2, MAC_ADDR_LEN); \ - NdisMoveMemory((_p + MAC_ADDR_LEN * 2), _pType, LENGTH_802_3_TYPE); \ -} - -// if pData has no LLC/SNAP (neither RFC1042 nor Bridge tunnel), keep it that way. -// else if the received frame is LLC/SNAP-encaped IPX or APPLETALK, preserve the LLC/SNAP field -// else remove the LLC/SNAP field from the result Ethernet frame -// Patch for WHQL only, which did not turn on Netbios but use IPX within its payload -// Note: -// _pData & _DataSize may be altered (remove 8-byte LLC/SNAP) by this MACRO -// _pRemovedLLCSNAP: pointer to removed LLC/SNAP; NULL is not removed -#define CONVERT_TO_802_3(_p8023hdr, _pDA, _pSA, _pData, _DataSize, _pRemovedLLCSNAP) \ -{ \ - char LLC_Len[2]; \ - \ - _pRemovedLLCSNAP = NULL; \ - if (NdisEqualMemory(SNAP_802_1H, _pData, 6) || \ - NdisEqualMemory(SNAP_BRIDGE_TUNNEL, _pData, 6)) \ - { \ - PUCHAR pProto = _pData + 6; \ - \ - if ((NdisEqualMemory(IPX, pProto, 2) || NdisEqualMemory(APPLE_TALK, pProto, 2)) && \ - NdisEqualMemory(SNAP_802_1H, _pData, 6)) \ - { \ - LLC_Len[0] = (UCHAR)(_DataSize / 256); \ - LLC_Len[1] = (UCHAR)(_DataSize % 256); \ - MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len); \ - } \ - else \ - { \ - MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, pProto); \ - _pRemovedLLCSNAP = _pData; \ - _DataSize -= LENGTH_802_1_H; \ - _pData += LENGTH_802_1_H; \ - } \ - } \ - else \ - { \ - LLC_Len[0] = (UCHAR)(_DataSize / 256); \ - LLC_Len[1] = (UCHAR)(_DataSize % 256); \ - MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len); \ - } \ -} - - -// Enqueue this frame to MLME engine -// We need to enqueue the whole frame because MLME need to pass data type -// information from 802.11 header -#ifdef RTMP_MAC_PCI -#define REPORT_MGMT_FRAME_TO_MLME(_pAd, Wcid, _pFrame, _FrameSize, _Rssi0, _Rssi1, _Rssi2, _PlcpSignal) \ -{ \ - UINT32 High32TSF, Low32TSF; \ - RTMP_IO_READ32(_pAd, TSF_TIMER_DW1, &High32TSF); \ - RTMP_IO_READ32(_pAd, TSF_TIMER_DW0, &Low32TSF); \ - MlmeEnqueueForRecv(_pAd, Wcid, High32TSF, Low32TSF, (UCHAR)_Rssi0, (UCHAR)_Rssi1,(UCHAR)_Rssi2,_FrameSize, _pFrame, (UCHAR)_PlcpSignal); \ -} -#endif // RTMP_MAC_PCI // - -#define MAC_ADDR_EQUAL(pAddr1,pAddr2) RTMPEqualMemory((PVOID)(pAddr1), (PVOID)(pAddr2), MAC_ADDR_LEN) -#define SSID_EQUAL(ssid1, len1, ssid2, len2) ((len1==len2) && (RTMPEqualMemory(ssid1, ssid2, len1))) - -// -// Check if it is Japan W53(ch52,56,60,64) channel. -// -#define JapanChannelCheck(channel) ((channel == 52) || (channel == 56) || (channel == 60) || (channel == 64)) - -#ifdef CONFIG_STA_SUPPORT -#define STA_EXTRA_SETTING(_pAd) - -#define STA_PORT_SECURED(_pAd) \ -{ \ - BOOLEAN Cancelled; \ - (_pAd)->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; \ - NdisAcquireSpinLock(&((_pAd)->MacTabLock)); \ - (_pAd)->MacTab.Content[BSSID_WCID].PortSecured = (_pAd)->StaCfg.PortSecured; \ - (_pAd)->MacTab.Content[BSSID_WCID].PrivacyFilter = Ndis802_11PrivFilterAcceptAll;\ - NdisReleaseSpinLock(&(_pAd)->MacTabLock); \ - RTMPCancelTimer(&((_pAd)->Mlme.LinkDownTimer), &Cancelled);\ - STA_EXTRA_SETTING(_pAd); \ -} -#endif // CONFIG_STA_SUPPORT // - - - -// -// Data buffer for DMA operation, the buffer must be contiguous physical memory -// Both DMA to / from CPU use the same structure. -// -typedef struct _RTMP_DMABUF -{ - ULONG AllocSize; - PVOID AllocVa; // TxBuf virtual address - NDIS_PHYSICAL_ADDRESS AllocPa; // TxBuf physical address -} RTMP_DMABUF, *PRTMP_DMABUF; - - -// -// Control block (Descriptor) for all ring descriptor DMA operation, buffer must be -// contiguous physical memory. NDIS_PACKET stored the binding Rx packet descriptor -// which won't be released, driver has to wait until upper layer return the packet -// before giveing up this rx ring descriptor to ASIC. NDIS_BUFFER is assocaited pair -// to describe the packet buffer. For Tx, NDIS_PACKET stored the tx packet descriptor -// which driver should ACK upper layer when the tx is physically done or failed. -// -typedef struct _RTMP_DMACB -{ - ULONG AllocSize; // Control block size - PVOID AllocVa; // Control block virtual address - NDIS_PHYSICAL_ADDRESS AllocPa; // Control block physical address - PNDIS_PACKET pNdisPacket; - PNDIS_PACKET pNextNdisPacket; - - RTMP_DMABUF DmaBuf; // Associated DMA buffer structure -} RTMP_DMACB, *PRTMP_DMACB; - - -typedef struct _RTMP_TX_RING -{ - RTMP_DMACB Cell[TX_RING_SIZE]; - UINT32 TxCpuIdx; - UINT32 TxDmaIdx; - UINT32 TxSwFreeIdx; // software next free tx index -} RTMP_TX_RING, *PRTMP_TX_RING; - -typedef struct _RTMP_RX_RING -{ - RTMP_DMACB Cell[RX_RING_SIZE]; - UINT32 RxCpuIdx; - UINT32 RxDmaIdx; - INT32 RxSwReadIdx; // software next read index -} RTMP_RX_RING, *PRTMP_RX_RING; - -typedef struct _RTMP_MGMT_RING -{ - RTMP_DMACB Cell[MGMT_RING_SIZE]; - UINT32 TxCpuIdx; - UINT32 TxDmaIdx; - UINT32 TxSwFreeIdx; // software next free tx index -} RTMP_MGMT_RING, *PRTMP_MGMT_RING; - - -// -// Statistic counter structure -// -typedef struct _COUNTER_802_3 -{ - // General Stats - ULONG GoodTransmits; - ULONG GoodReceives; - ULONG TxErrors; - ULONG RxErrors; - ULONG RxNoBuffer; - - // Ethernet Stats - ULONG RcvAlignmentErrors; - ULONG OneCollision; - ULONG MoreCollisions; - -} COUNTER_802_3, *PCOUNTER_802_3; - -typedef struct _COUNTER_802_11 { - ULONG Length; - LARGE_INTEGER LastTransmittedFragmentCount; - LARGE_INTEGER TransmittedFragmentCount; - LARGE_INTEGER MulticastTransmittedFrameCount; - LARGE_INTEGER FailedCount; - LARGE_INTEGER RetryCount; - LARGE_INTEGER MultipleRetryCount; - LARGE_INTEGER RTSSuccessCount; - LARGE_INTEGER RTSFailureCount; - LARGE_INTEGER ACKFailureCount; - LARGE_INTEGER FrameDuplicateCount; - LARGE_INTEGER ReceivedFragmentCount; - LARGE_INTEGER MulticastReceivedFrameCount; - LARGE_INTEGER FCSErrorCount; -} COUNTER_802_11, *PCOUNTER_802_11; - -typedef struct _COUNTER_RALINK { - ULONG TransmittedByteCount; // both successful and failure, used to calculate TX throughput - ULONG ReceivedByteCount; // both CRC okay and CRC error, used to calculate RX throughput - ULONG BeenDisassociatedCount; - ULONG BadCQIAutoRecoveryCount; - ULONG PoorCQIRoamingCount; - ULONG MgmtRingFullCount; - ULONG RxCountSinceLastNULL; - ULONG RxCount; - ULONG RxRingErrCount; - ULONG KickTxCount; - ULONG TxRingErrCount; - LARGE_INTEGER RealFcsErrCount; - ULONG PendingNdisPacketCount; - - ULONG OneSecOsTxCount[NUM_OF_TX_RING]; - ULONG OneSecDmaDoneCount[NUM_OF_TX_RING]; - UINT32 OneSecTxDoneCount; - ULONG OneSecRxCount; - UINT32 OneSecTxAggregationCount; - UINT32 OneSecRxAggregationCount; - UINT32 OneSecReceivedByteCount; - UINT32 OneSecFrameDuplicateCount; - - UINT32 OneSecTransmittedByteCount; // both successful and failure, used to calculate TX throughput - UINT32 OneSecTxNoRetryOkCount; - UINT32 OneSecTxRetryOkCount; - UINT32 OneSecTxFailCount; - UINT32 OneSecFalseCCACnt; // CCA error count, for debug purpose, might move to global counter - UINT32 OneSecRxOkCnt; // RX without error - UINT32 OneSecRxOkDataCnt; // unicast-to-me DATA frame count - UINT32 OneSecRxFcsErrCnt; // CRC error - UINT32 OneSecBeaconSentCnt; - UINT32 LastOneSecTotalTxCount; // OneSecTxNoRetryOkCount + OneSecTxRetryOkCount + OneSecTxFailCount - UINT32 LastOneSecRxOkDataCnt; // OneSecRxOkDataCnt - ULONG DuplicateRcv; - ULONG TxAggCount; - ULONG TxNonAggCount; - ULONG TxAgg1MPDUCount; - ULONG TxAgg2MPDUCount; - ULONG TxAgg3MPDUCount; - ULONG TxAgg4MPDUCount; - ULONG TxAgg5MPDUCount; - ULONG TxAgg6MPDUCount; - ULONG TxAgg7MPDUCount; - ULONG TxAgg8MPDUCount; - ULONG TxAgg9MPDUCount; - ULONG TxAgg10MPDUCount; - ULONG TxAgg11MPDUCount; - ULONG TxAgg12MPDUCount; - ULONG TxAgg13MPDUCount; - ULONG TxAgg14MPDUCount; - ULONG TxAgg15MPDUCount; - ULONG TxAgg16MPDUCount; - - LARGE_INTEGER TransmittedOctetsInAMSDU; - LARGE_INTEGER TransmittedAMSDUCount; - LARGE_INTEGER ReceivedOctesInAMSDUCount; - LARGE_INTEGER ReceivedAMSDUCount; - LARGE_INTEGER TransmittedAMPDUCount; - LARGE_INTEGER TransmittedMPDUsInAMPDUCount; - LARGE_INTEGER TransmittedOctetsInAMPDUCount; - LARGE_INTEGER MPDUInReceivedAMPDUCount; -} COUNTER_RALINK, *PCOUNTER_RALINK; - - -typedef struct _COUNTER_DRS { - // to record the each TX rate's quality. 0 is best, the bigger the worse. - USHORT TxQuality[MAX_STEP_OF_TX_RATE_SWITCH]; - UCHAR PER[MAX_STEP_OF_TX_RATE_SWITCH]; - UCHAR TxRateUpPenalty; // extra # of second penalty due to last unstable condition - ULONG CurrTxRateStableTime; // # of second in current TX rate - BOOLEAN fNoisyEnvironment; - BOOLEAN fLastSecAccordingRSSI; - UCHAR LastSecTxRateChangeAction; // 0: no change, 1:rate UP, 2:rate down - UCHAR LastTimeTxRateChangeAction; //Keep last time value of LastSecTxRateChangeAction - ULONG LastTxOkCount; -} COUNTER_DRS, *PCOUNTER_DRS; - - - - -/*************************************************************************** - * security key related data structure - **************************************************************************/ -typedef struct _CIPHER_KEY { - UCHAR Key[16]; // right now we implement 4 keys, 128 bits max - UCHAR RxMic[8]; // make alignment - UCHAR TxMic[8]; - UCHAR TxTsc[6]; // 48bit TSC value - UCHAR RxTsc[6]; // 48bit TSC value - UCHAR CipherAlg; // 0-none, 1:WEP64, 2:WEP128, 3:TKIP, 4:AES, 5:CKIP64, 6:CKIP128 - UCHAR KeyLen; -#ifdef CONFIG_STA_SUPPORT - UCHAR BssId[6]; -#endif // CONFIG_STA_SUPPORT // - // Key length for each key, 0: entry is invalid - UCHAR Type; // Indicate Pairwise/Group when reporting MIC error -} CIPHER_KEY, *PCIPHER_KEY; - - -// structure to define WPA Group Key Rekey Interval -typedef struct PACKED _RT_802_11_WPA_REKEY { - ULONG ReKeyMethod; // mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based - ULONG ReKeyInterval; // time-based: seconds, packet-based: kilo-packets -} RT_WPA_REKEY,*PRT_WPA_REKEY, RT_802_11_WPA_REKEY, *PRT_802_11_WPA_REKEY; - - - -typedef struct { - UCHAR Addr[MAC_ADDR_LEN]; - UCHAR ErrorCode[2]; //00 01-Invalid authentication type - //00 02-Authentication timeout - //00 03-Challenge from AP failed - //00 04-Challenge to AP failed - BOOLEAN Reported; -} ROGUEAP_ENTRY, *PROGUEAP_ENTRY; - -typedef struct { - UCHAR RogueApNr; - ROGUEAP_ENTRY RogueApEntry[MAX_LEN_OF_BSS_TABLE]; -} ROGUEAP_TABLE, *PROGUEAP_TABLE; - -// -// Cisco IAPP format -// -typedef struct _CISCO_IAPP_CONTENT_ -{ - USHORT Length; //IAPP Length - UCHAR MessageType; //IAPP type - UCHAR FunctionCode; //IAPP function type - UCHAR DestinaionMAC[MAC_ADDR_LEN]; - UCHAR SourceMAC[MAC_ADDR_LEN]; - USHORT Tag; //Tag(element IE) - Adjacent AP report - USHORT TagLength; //Length of element not including 4 byte header - UCHAR OUI[4]; //0x00, 0x40, 0x96, 0x00 - UCHAR PreviousAP[MAC_ADDR_LEN]; //MAC Address of access point - USHORT Channel; - USHORT SsidLen; - UCHAR Ssid[MAX_LEN_OF_SSID]; - USHORT Seconds; //Seconds that the client has been disassociated. -} CISCO_IAPP_CONTENT, *PCISCO_IAPP_CONTENT; - - -/* - * Fragment Frame structure - */ -typedef struct _FRAGMENT_FRAME { - PNDIS_PACKET pFragPacket; - ULONG RxSize; - USHORT Sequence; - USHORT LastFrag; - ULONG Flags; // Some extra frame information. bit 0: LLC presented -} FRAGMENT_FRAME, *PFRAGMENT_FRAME; - - -// -// Packet information for NdisQueryPacket -// -typedef struct _PACKET_INFO { - UINT PhysicalBufferCount; // Physical breaks of buffer descripor chained - UINT BufferCount ; // Number of Buffer descriptor chained - UINT TotalPacketLength ; // Self explained - PNDIS_BUFFER pFirstBuffer; // Pointer to first buffer descriptor -} PACKET_INFO, *PPACKET_INFO; - - -// -// Arcfour Structure Added by PaulWu -// -typedef struct _ARCFOUR -{ - UINT X; - UINT Y; - UCHAR STATE[256]; -} ARCFOURCONTEXT, *PARCFOURCONTEXT; - - -// -// Tkip Key structure which RC4 key & MIC calculation -// -typedef struct _TKIP_KEY_INFO { - UINT nBytesInM; // # bytes in M for MICKEY - ULONG IV16; - ULONG IV32; - ULONG K0; // for MICKEY Low - ULONG K1; // for MICKEY Hig - ULONG L; // Current state for MICKEY - ULONG R; // Current state for MICKEY - ULONG M; // Message accumulator for MICKEY - UCHAR RC4KEY[16]; - UCHAR MIC[8]; -} TKIP_KEY_INFO, *PTKIP_KEY_INFO; - - -// -// Private / Misc data, counters for driver internal use -// -typedef struct __PRIVATE_STRUC { - UINT SystemResetCnt; // System reset counter - UINT TxRingFullCnt; // Tx ring full occurrance number - UINT PhyRxErrCnt; // PHY Rx error count, for debug purpose, might move to global counter - // Variables for WEP encryption / decryption in rtmp_wep.c - UINT FCSCRC32; - ARCFOURCONTEXT WEPCONTEXT; - // Tkip stuff - TKIP_KEY_INFO Tx; - TKIP_KEY_INFO Rx; -} PRIVATE_STRUC, *PPRIVATE_STRUC; - - -/*************************************************************************** - * Channel and BBP related data structures - **************************************************************************/ -// structure to tune BBP R66 (BBP TUNING) -typedef struct _BBP_R66_TUNING { - BOOLEAN bEnable; - USHORT FalseCcaLowerThreshold; // default 100 - USHORT FalseCcaUpperThreshold; // default 512 - UCHAR R66Delta; - UCHAR R66CurrentValue; - BOOLEAN R66LowerUpperSelect; //Before LinkUp, Used LowerBound or UpperBound as R66 value. -} BBP_R66_TUNING, *PBBP_R66_TUNING; - -// structure to store channel TX power -typedef struct _CHANNEL_TX_POWER { - USHORT RemainingTimeForUse; //unit: sec - UCHAR Channel; -#ifdef DOT11N_DRAFT3 - BOOLEAN bEffectedChannel; // For BW 40 operating in 2.4GHz , the "effected channel" is the channel that is covered in 40Mhz. -#endif // DOT11N_DRAFT3 // - CHAR Power; - CHAR Power2; - UCHAR MaxTxPwr; - UCHAR DfsReq; -} CHANNEL_TX_POWER, *PCHANNEL_TX_POWER; - -// structure to store 802.11j channel TX power -typedef struct _CHANNEL_11J_TX_POWER { - UCHAR Channel; - UCHAR BW; // BW_10 or BW_20 - CHAR Power; - CHAR Power2; - USHORT RemainingTimeForUse; //unit: sec -} CHANNEL_11J_TX_POWER, *PCHANNEL_11J_TX_POWER; - -typedef struct _SOFT_RX_ANT_DIVERSITY_STRUCT { - UCHAR EvaluatePeriod; // 0:not evalute status, 1: evaluate status, 2: switching status - UCHAR EvaluateStableCnt; - UCHAR Pair1PrimaryRxAnt; // 0:Ant-E1, 1:Ant-E2 - UCHAR Pair1SecondaryRxAnt; // 0:Ant-E1, 1:Ant-E2 - UCHAR Pair2PrimaryRxAnt; // 0:Ant-E3, 1:Ant-E4 - UCHAR Pair2SecondaryRxAnt; // 0:Ant-E3, 1:Ant-E4 -#ifdef CONFIG_STA_SUPPORT - SHORT Pair1AvgRssi[2]; // AvgRssi[0]:E1, AvgRssi[1]:E2 - SHORT Pair2AvgRssi[2]; // AvgRssi[0]:E3, AvgRssi[1]:E4 -#endif // CONFIG_STA_SUPPORT // - SHORT Pair1LastAvgRssi; // - SHORT Pair2LastAvgRssi; // - ULONG RcvPktNumWhenEvaluate; - BOOLEAN FirstPktArrivedWhenEvaluate; - RALINK_TIMER_STRUCT RxAntDiversityTimer; -} SOFT_RX_ANT_DIVERSITY, *PSOFT_RX_ANT_DIVERSITY; - - -/*************************************************************************** - * structure for radar detection and channel switch - **************************************************************************/ -typedef struct _RADAR_DETECT_STRUCT { - //BOOLEAN IEEE80211H; // 0: disable, 1: enable IEEE802.11h - UCHAR CSCount; //Channel switch counter - UCHAR CSPeriod; //Channel switch period (beacon count) - UCHAR RDCount; //Radar detection counter - UCHAR RDMode; //Radar Detection mode - UCHAR RDDurRegion; //Radar detection duration region - UCHAR BBPR16; - UCHAR BBPR17; - UCHAR BBPR18; - UCHAR BBPR21; - UCHAR BBPR22; - UCHAR BBPR64; - ULONG InServiceMonitorCount; // unit: sec - UINT8 DfsSessionTime; -#ifdef DFS_FCC_BW40_FIX - CHAR DfsSessionFccOff; -#endif - BOOLEAN bFastDfs; - UINT8 ChMovingTime; - UINT8 LongPulseRadarTh; -#ifdef MERGE_ARCH_TEAM - CHAR AvgRssiReq; - ULONG DfsLowerLimit; - ULONG DfsUpperLimit; - UINT8 FixDfsLimit; - ULONG upperlimit; - ULONG lowerlimit; -#endif // MERGE_ARCH_TEAM // -} RADAR_DETECT_STRUCT, *PRADAR_DETECT_STRUCT; - -#ifdef CARRIER_DETECTION_SUPPORT -typedef enum CD_STATE_n -{ - CD_NORMAL, - CD_SILENCE, - CD_MAX_STATE -} CD_STATE; - -#ifdef TONE_RADAR_DETECT_SUPPORT -#define CARRIER_DETECT_RECHECK_TIME 3 - - -#ifdef CARRIER_SENSE_NEW_ALGO -#define CARRIER_DETECT_CRITIRIA 400 -#define CARRIER_DETECT_STOP_RATIO 0x11 -#define CARRIER_DETECT_STOP_RATIO_OLD_3090 2 -#endif // CARRIER_SENSE_NEW_ALGO // - - -#define CARRIER_DETECT_STOP_RECHECK_TIME 4 -#define CARRIER_DETECT_CRITIRIA_A 230 -#define CARRIER_DETECT_DELTA 7 -#define CARRIER_DETECT_DIV_FLAG 0 -#ifdef RT3090 -#define CARRIER_DETECT_THRESHOLD_3090A 0x1fffffff -#endif // RT3090 // -#ifdef RT3390 -#define CARRIER_DETECT_THRESHOLD 0x0fffffff -#endif // RT3390 // -#ifndef RT3390 -#define CARRIER_DETECT_THRESHOLD 0x0fffffff -#endif // RT3390 // -#endif // TONE_RADAR_DETECT_SUPPORT // - -typedef struct CARRIER_DETECTION_s -{ - BOOLEAN Enable; - UINT8 CDSessionTime; - UINT8 CDPeriod; - CD_STATE CD_State; -#ifdef TONE_RADAR_DETECT_SUPPORT - UINT8 delta; - UINT8 div_flag; - UINT32 threshold; - UINT8 recheck; - UINT8 recheck1; - UINT8 recheck2; - UINT32 TimeStamp; - UINT32 criteria; - UINT32 CarrierDebug; - ULONG idle_time; - ULONG busy_time; - ULONG Debug; -#endif // TONE_RADAR_DETECT_SUPPORT // -}CARRIER_DETECTION_STRUCT, *PCARRIER_DETECTION_STRUCT; -#endif // CARRIER_DETECTION_SUPPORT // - - -#ifdef NEW_DFS -typedef struct _NewDFSDebug -{ - UCHAR channel; - ULONG wait_time; - UCHAR delta_delay_range; - UCHAR delta_delay_step; - UCHAR EL_range; - UCHAR EL_step; - UCHAR EH_range; - UCHAR EH_step; - UCHAR WL_range; - UCHAR WL_step; - UCHAR WH_range; - UCHAR WH_step; - ULONG T_expected; - ULONG T_margin; - UCHAR start; - ULONG count; - ULONG idx; - -}NewDFSDebug, *pNewDFSDebug; - -#define NEW_DFS_FCC_5_ENT_NUM 5 -#define NEW_DFS_DBG_PORT_ENT_NUM_POWER 8 -#define NEW_DFS_DBG_PORT_ENT_NUM (1 << NEW_DFS_DBG_PORT_ENT_NUM_POWER) // CE Debug Port entry number, 256 -#define NEW_DFS_DBG_PORT_MASK 0xff - -// Matched Period definition -#define NEW_DFS_MPERIOD_ENT_NUM_POWER 8 -#define NEW_DFS_MPERIOD_ENT_NUM (1 << NEW_DFS_MPERIOD_ENT_NUM_POWER) // CE Period Table entry number, 512 -#define NEW_DFS_MAX_CHANNEL 4 - -typedef struct _NewDFSDebugPort{ - ULONG counter; - ULONG timestamp; - USHORT width; - USHORT start_idx; // start index to period table - USHORT end_idx; // end index to period table -}NewDFSDebugPort, *pNewDFSDebugPort; - -// Matched Period Table -typedef struct _NewDFSMPeriod{ - USHORT idx; - USHORT width; - USHORT idx2; - USHORT width2; - ULONG period; -}NewDFSMPeriod, *pNewDFSMPeriod; - -#endif // NEW_DFS // - - -typedef enum _ABGBAND_STATE_ { - UNKNOWN_BAND, - BG_BAND, - A_BAND, -} ABGBAND_STATE; - -#ifdef RTMP_MAC_PCI -#ifdef CONFIG_STA_SUPPORT -// Power save method control -typedef union _PS_CONTROL { - struct { - ULONG EnablePSinIdle:1; // Enable radio off when not connect to AP. radio on only when sitesurvey, - ULONG EnableNewPS:1; // Enable new Chip power save fucntion . New method can only be applied in chip version after 2872. and PCIe. - ULONG rt30xxPowerMode:2; // Power Level Mode for rt30xx chip - ULONG rt30xxFollowHostASPM:1; // Card Follows Host's setting for rt30xx chip. - ULONG rt30xxForceASPMTest:1; // Force enable L1 for rt30xx chip. This has higher priority than rt30xxFollowHostASPM Mode. - ULONG rsv:26; // Radio Measurement Enable - } field; - ULONG word; -} PS_CONTROL, *PPS_CONTROL; -#endif // CONFIG_STA_SUPPORT // -#endif // RTMP_MAC_PCI // -/*************************************************************************** - * structure for MLME state machine - **************************************************************************/ -typedef struct _MLME_STRUCT { -#ifdef CONFIG_STA_SUPPORT - // STA state machines - STATE_MACHINE CntlMachine; - STATE_MACHINE AssocMachine; - STATE_MACHINE AuthMachine; - STATE_MACHINE AuthRspMachine; - STATE_MACHINE SyncMachine; - STATE_MACHINE WpaPskMachine; - STATE_MACHINE LeapMachine; - STATE_MACHINE_FUNC AssocFunc[ASSOC_FUNC_SIZE]; - STATE_MACHINE_FUNC AuthFunc[AUTH_FUNC_SIZE]; - STATE_MACHINE_FUNC AuthRspFunc[AUTH_RSP_FUNC_SIZE]; - STATE_MACHINE_FUNC SyncFunc[SYNC_FUNC_SIZE]; -#endif // CONFIG_STA_SUPPORT // - STATE_MACHINE_FUNC ActFunc[ACT_FUNC_SIZE]; - // Action - STATE_MACHINE ActMachine; - - -#ifdef QOS_DLS_SUPPORT - STATE_MACHINE DlsMachine; - STATE_MACHINE_FUNC DlsFunc[DLS_FUNC_SIZE]; -#endif // QOS_DLS_SUPPORT // - - - // common WPA state machine - STATE_MACHINE WpaMachine; - STATE_MACHINE_FUNC WpaFunc[WPA_FUNC_SIZE]; - - - - ULONG ChannelQuality; // 0..100, Channel Quality Indication for Roaming - ULONG Now32; // latch the value of NdisGetSystemUpTime() - ULONG LastSendNULLpsmTime; - - BOOLEAN bRunning; - NDIS_SPIN_LOCK TaskLock; - MLME_QUEUE Queue; - - UINT ShiftReg; - - RALINK_TIMER_STRUCT PeriodicTimer; - RALINK_TIMER_STRUCT APSDPeriodicTimer; - RALINK_TIMER_STRUCT LinkDownTimer; - RALINK_TIMER_STRUCT LinkUpTimer; -#ifdef RTMP_MAC_PCI - UCHAR bPsPollTimerRunning; - RALINK_TIMER_STRUCT PsPollTimer; - RALINK_TIMER_STRUCT RadioOnOffTimer; -#endif // RTMP_MAC_PCI // - ULONG PeriodicRound; - ULONG OneSecPeriodicRound; - - UCHAR RealRxPath; - BOOLEAN bLowThroughput; - BOOLEAN bEnableAutoAntennaCheck; - RALINK_TIMER_STRUCT RxAntEvalTimer; - -#ifdef RT30xx - UCHAR CaliBW40RfR24; - UCHAR CaliBW20RfR24; -#endif // RT30xx // - -} MLME_STRUCT, *PMLME_STRUCT; - - -#ifdef DOT11_N_SUPPORT -/*************************************************************************** - * 802.11 N related data structures - **************************************************************************/ -struct reordering_mpdu -{ - struct reordering_mpdu *next; - PNDIS_PACKET pPacket; /* coverted to 802.3 frame */ - int Sequence; /* sequence number of MPDU */ - BOOLEAN bAMSDU; -}; - -struct reordering_list -{ - struct reordering_mpdu *next; - int qlen; -}; - -struct reordering_mpdu_pool -{ - PVOID mem; - NDIS_SPIN_LOCK lock; - struct reordering_list freelist; -}; - -typedef enum _REC_BLOCKACK_STATUS -{ - Recipient_NONE=0, - Recipient_USED, - Recipient_HandleRes, - Recipient_Accept -} REC_BLOCKACK_STATUS, *PREC_BLOCKACK_STATUS; - -typedef enum _ORI_BLOCKACK_STATUS -{ - Originator_NONE=0, - Originator_USED, - Originator_WaitRes, - Originator_Done -} ORI_BLOCKACK_STATUS, *PORI_BLOCKACK_STATUS; - -typedef struct _BA_ORI_ENTRY{ - UCHAR Wcid; - UCHAR TID; - UCHAR BAWinSize; - UCHAR Token; -// Sequence is to fill every outgoing QoS DATA frame's sequence field in 802.11 header. - USHORT Sequence; - USHORT TimeOutValue; - ORI_BLOCKACK_STATUS ORI_BA_Status; - RALINK_TIMER_STRUCT ORIBATimer; - PVOID pAdapter; -} BA_ORI_ENTRY, *PBA_ORI_ENTRY; - -typedef struct _BA_REC_ENTRY { - UCHAR Wcid; - UCHAR TID; - UCHAR BAWinSize; // 7.3.1.14. each buffer is capable of holding a max AMSDU or MSDU. - //UCHAR NumOfRxPkt; - //UCHAR Curindidx; // the head in the RX reordering buffer - USHORT LastIndSeq; -// USHORT LastIndSeqAtTimer; - USHORT TimeOutValue; - RALINK_TIMER_STRUCT RECBATimer; - ULONG LastIndSeqAtTimer; - ULONG nDropPacket; - ULONG rcvSeq; - REC_BLOCKACK_STATUS REC_BA_Status; -// UCHAR RxBufIdxUsed; - // corresponding virtual address for RX reordering packet storage. - //RTMP_REORDERDMABUF MAP_RXBuf[MAX_RX_REORDERBUF]; - NDIS_SPIN_LOCK RxReRingLock; // Rx Ring spinlock -// struct _BA_REC_ENTRY *pNext; - PVOID pAdapter; - struct reordering_list list; -} BA_REC_ENTRY, *PBA_REC_ENTRY; - - -typedef struct { - ULONG numAsRecipient; // I am recipient of numAsRecipient clients. These client are in the BARecEntry[] - ULONG numAsOriginator; // I am originator of numAsOriginator clients. These clients are in the BAOriEntry[] - ULONG numDoneOriginator; // count Done Originator sessions - BA_ORI_ENTRY BAOriEntry[MAX_LEN_OF_BA_ORI_TABLE]; - BA_REC_ENTRY BARecEntry[MAX_LEN_OF_BA_REC_TABLE]; -} BA_TABLE, *PBA_TABLE; - -//For QureyBATableOID use; -typedef struct PACKED _OID_BA_REC_ENTRY{ - UCHAR MACAddr[MAC_ADDR_LEN]; - UCHAR BaBitmap; // if (BaBitmap&(1<MaxHTPhyMode.field.MODE >= MODE_HTMIX) - -#define IS_HT_RATE(_pMacEntry) \ - (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) - -#define PEER_IS_HT_RATE(_pMacEntry) \ - (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) - -#endif // DOT11_N_SUPPORT // - - -//This structure is for all 802.11n card InterOptibilityTest action. Reset all Num every n second. (Details see MLMEPeriodic) -typedef struct _IOT_STRUC { - UCHAR Threshold[2]; - UCHAR ReorderTimeOutNum[MAX_LEN_OF_BA_REC_TABLE]; // compare with threshold[0] - UCHAR RefreshNum[MAX_LEN_OF_BA_REC_TABLE]; // compare with threshold[1] - ULONG OneSecInWindowCount; - ULONG OneSecFrameDuplicateCount; - ULONG OneSecOutWindowCount; - UCHAR DelOriAct; - UCHAR DelRecAct; - UCHAR RTSShortProt; - UCHAR RTSLongProt; - BOOLEAN bRTSLongProtOn; -#ifdef CONFIG_STA_SUPPORT - BOOLEAN bLastAtheros; - BOOLEAN bCurrentAtheros; - BOOLEAN bNowAtherosBurstOn; - BOOLEAN bNextDisableRxBA; - BOOLEAN bToggle; -#endif // CONFIG_STA_SUPPORT // -} IOT_STRUC, *PIOT_STRUC; - - -// This is the registry setting for 802.11n transmit setting. Used in advanced page. -typedef union _REG_TRANSMIT_SETTING { -#ifdef RT_BIG_ENDIAN - struct { - UINT32 rsv:13; - UINT32 EXTCHA:2; - UINT32 HTMODE:1; - UINT32 TRANSNO:2; - UINT32 STBC:1; //SPACE - UINT32 ShortGI:1; - UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz - UINT32 TxBF:1; // 3*3 - UINT32 rsv0:10; - //UINT32 MCS:7; // MCS - //UINT32 PhyMode:4; - } field; -#else - struct { - //UINT32 PhyMode:4; - //UINT32 MCS:7; // MCS - UINT32 rsv0:10; - UINT32 TxBF:1; - UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz - UINT32 ShortGI:1; - UINT32 STBC:1; //SPACE - UINT32 TRANSNO:2; - UINT32 HTMODE:1; - UINT32 EXTCHA:2; - UINT32 rsv:13; - } field; -#endif - UINT32 word; -} REG_TRANSMIT_SETTING, *PREG_TRANSMIT_SETTING; - - -typedef union _DESIRED_TRANSMIT_SETTING { -#ifdef RT_BIG_ENDIAN - struct { - USHORT rsv:3; - USHORT FixedTxMode:2; // If MCS isn't AUTO, fix rate in CCK, OFDM or HT mode. - USHORT PhyMode:4; - USHORT MCS:7; // MCS - } field; -#else - struct { - USHORT MCS:7; // MCS - USHORT PhyMode:4; - USHORT FixedTxMode:2; // If MCS isn't AUTO, fix rate in CCK, OFDM or HT mode. - USHORT rsv:3; - } field; -#endif - USHORT word; - } DESIRED_TRANSMIT_SETTING, *PDESIRED_TRANSMIT_SETTING; - - - - -/*************************************************************************** - * Multiple SSID related data structures - **************************************************************************/ -#define WLAN_MAX_NUM_OF_TIM ((MAX_LEN_OF_MAC_TABLE >> 3) + 1) /* /8 + 1 */ -#define WLAN_CT_TIM_BCMC_OFFSET 0 /* unit: 32B */ - -/* clear bcmc TIM bit */ -#define WLAN_MR_TIM_BCMC_CLEAR(apidx) \ - pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] &= ~BIT8[0]; - -/* set bcmc TIM bit */ -#define WLAN_MR_TIM_BCMC_SET(apidx) \ - pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] |= BIT8[0]; - -/* clear a station PS TIM bit */ -#define WLAN_MR_TIM_BIT_CLEAR(ad_p, apidx, wcid) \ - { UCHAR tim_offset = wcid >> 3; \ - UCHAR bit_offset = wcid & 0x7; \ - ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] &= (~BIT8[bit_offset]); } - -/* set a station PS TIM bit */ -#define WLAN_MR_TIM_BIT_SET(ad_p, apidx, wcid) \ - { UCHAR tim_offset = wcid >> 3; \ - UCHAR bit_offset = wcid & 0x7; \ - ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] |= BIT8[bit_offset]; } - - -// configuration common to OPMODE_AP as well as OPMODE_STA -typedef struct _COMMON_CONFIG { - - BOOLEAN bCountryFlag; - UCHAR CountryCode[3]; - UCHAR Geography; - UCHAR CountryRegion; // Enum of country region, 0:FCC, 1:IC, 2:ETSI, 3:SPAIN, 4:France, 5:MKK, 6:MKK1, 7:Israel - UCHAR CountryRegionForABand; // Enum of country region for A band - UCHAR PhyMode; // PHY_11A, PHY_11B, PHY_11BG_MIXED, PHY_ABG_MIXED - UCHAR DesiredPhyMode; // PHY_11A, PHY_11B, PHY_11BG_MIXED, PHY_ABG_MIXED - USHORT Dsifs; // in units of usec - ULONG PacketFilter; // Packet filter for receiving - UINT8 RegulatoryClass[MAX_NUM_OF_REGULATORY_CLASS]; - - CHAR Ssid[MAX_LEN_OF_SSID]; // NOT NULL-terminated - UCHAR SsidLen; // the actual ssid length in used - UCHAR LastSsidLen; // the actual ssid length in used - CHAR LastSsid[MAX_LEN_OF_SSID]; // NOT NULL-terminated - UCHAR LastBssid[MAC_ADDR_LEN]; - - UCHAR Bssid[MAC_ADDR_LEN]; - USHORT BeaconPeriod; - UCHAR Channel; - UCHAR CentralChannel; // Central Channel when using 40MHz is indicating. not real channel. - - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen; - UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR ExtRateLen; - UCHAR DesireRate[MAX_LEN_OF_SUPPORTED_RATES]; // OID_802_11_DESIRED_RATES - UCHAR MaxDesiredRate; - UCHAR ExpectedACKRate[MAX_LEN_OF_SUPPORTED_RATES]; - - ULONG BasicRateBitmap; // backup basic ratebitmap - - BOOLEAN bAPSDCapable; - BOOLEAN bInServicePeriod; - BOOLEAN bAPSDAC_BE; - BOOLEAN bAPSDAC_BK; - BOOLEAN bAPSDAC_VI; - BOOLEAN bAPSDAC_VO; - - /* because TSPEC can modify the APSD flag, we need to keep the APSD flag - requested in association stage from the station; - we need to recover the APSD flag after the TSPEC is deleted. */ - BOOLEAN bACMAPSDBackup[4]; /* for delivery-enabled & trigger-enabled both */ - BOOLEAN bACMAPSDTr[4]; /* no use */ - - BOOLEAN bNeedSendTriggerFrame; - BOOLEAN bAPSDForcePowerSave; // Force power save mode, should only use in APSD-STAUT - ULONG TriggerTimerCount; - UCHAR MaxSPLength; - UCHAR BBPCurrentBW; // BW_10, BW_20, BW_40 - // move to MULTISSID_STRUCT for MBSS - //HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. - REG_TRANSMIT_SETTING RegTransmitSetting; //registry transmit setting. this is for reading registry setting only. not useful. - //UCHAR FixedTxMode; // Fixed Tx Mode (CCK, OFDM), for HT fixed tx mode (GF, MIX) , refer to RegTransmitSetting.field.HTMode - UCHAR TxRate; // Same value to fill in TXD. TxRate is 6-bit - UCHAR MaxTxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11 - UCHAR TxRateIndex; // Tx rate index in RateSwitchTable - UCHAR TxRateTableSize; // Valid Tx rate table size in RateSwitchTable - //BOOLEAN bAutoTxRateSwitch; - UCHAR MinTxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11 - UCHAR RtsRate; // RATE_xxx - HTTRANSMIT_SETTING MlmeTransmit; // MGMT frame PHY rate setting when operatin at Ht rate. - UCHAR MlmeRate; // RATE_xxx, used to send MLME frames - UCHAR BasicMlmeRate; // Default Rate for sending MLME frames - - USHORT RtsThreshold; // in unit of BYTE - USHORT FragmentThreshold; // in unit of BYTE - - UCHAR TxPower; // in unit of mW - ULONG TxPowerPercentage; // 0~100 % - ULONG TxPowerDefault; // keep for TxPowerPercentage - UINT8 PwrConstraint; - -#ifdef DOT11_N_SUPPORT - BACAP_STRUC BACapability; // NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0 - BACAP_STRUC REGBACapability; // NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0 -#endif // DOT11_N_SUPPORT // - IOT_STRUC IOTestParm; // 802.11n InterOpbility Test Parameter; - ULONG TxPreamble; // Rt802_11PreambleLong, Rt802_11PreambleShort, Rt802_11PreambleAuto - BOOLEAN bUseZeroToDisableFragment; // Microsoft use 0 as disable - ULONG UseBGProtection; // 0: auto, 1: always use, 2: always not use - BOOLEAN bUseShortSlotTime; // 0: disable, 1 - use short slot (9us) - BOOLEAN bEnableTxBurst; // 1: enble TX PACKET BURST (when BA is established or AP is not a legacy WMM AP), 0: disable TX PACKET BURST - BOOLEAN bAggregationCapable; // 1: enable TX aggregation when the peer supports it - BOOLEAN bPiggyBackCapable; // 1: enable TX piggy-back according MAC's version - BOOLEAN bIEEE80211H; // 1: enable IEEE802.11h spec. - ULONG DisableOLBCDetect; // 0: enable OLBC detect; 1 disable OLBC detect - -#ifdef DOT11_N_SUPPORT - BOOLEAN bRdg; -#endif // DOT11_N_SUPPORT // - BOOLEAN bWmmCapable; // 0:disable WMM, 1:enable WMM - QOS_CAPABILITY_PARM APQosCapability; // QOS capability of the current associated AP - EDCA_PARM APEdcaParm; // EDCA parameters of the current associated AP - QBSS_LOAD_PARM APQbssLoad; // QBSS load of the current associated AP - UCHAR AckPolicy[4]; // ACK policy of the specified AC. see ACK_xxx -#ifdef CONFIG_STA_SUPPORT - BOOLEAN bDLSCapable; // 0:disable DLS, 1:enable DLS -#endif // CONFIG_STA_SUPPORT // - // a bitmap of BOOLEAN flags. each bit represent an operation status of a particular - // BOOLEAN control, either ON or OFF. These flags should always be accessed via - // OPSTATUS_TEST_FLAG(), OPSTATUS_SET_FLAG(), OP_STATUS_CLEAR_FLAG() macros. - // see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition - ULONG OpStatusFlags; - - BOOLEAN NdisRadioStateOff; //For HCT 12.0, set this flag to TRUE instead of called MlmeRadioOff. - ABGBAND_STATE BandState; // For setting BBP used on B/G or A mode. -#ifdef ANT_DIVERSITY_SUPPORT - UCHAR bRxAntDiversity; // 0:disable, 1:enable Software Rx Antenna Diversity. -#endif // ANT_DIVERSITY_SUPPORT // - - // IEEE802.11H--DFS. - RADAR_DETECT_STRUCT RadarDetect; - -#ifdef CARRIER_DETECTION_SUPPORT - CARRIER_DETECTION_STRUCT CarrierDetect; -#endif // CARRIER_DETECTION_SUPPORT // - -#ifdef DOT11_N_SUPPORT - // HT - UCHAR BASize; // USer desired BAWindowSize. Should not exceed our max capability - //RT_HT_CAPABILITY SupportedHtPhy; - RT_HT_CAPABILITY DesiredHtPhy; - HT_CAPABILITY_IE HtCapability; - ADD_HT_INFO_IE AddHTInfo; // Useful as AP. - //This IE is used with channel switch announcement element when changing to a new 40MHz. - //This IE is included in channel switch ammouncement frames 7.4.1.5, beacons, probe Rsp. - NEW_EXT_CHAN_IE NewExtChanOffset; //7.3.2.20A, 1 if extension channel is above the control channel, 3 if below, 0 if not present - -#ifdef DOT11N_DRAFT3 - UCHAR Bss2040CoexistFlag; // bit 0: bBssCoexistTimerRunning, bit 1: NeedSyncAddHtInfo. - RALINK_TIMER_STRUCT Bss2040CoexistTimer; - - //This IE is used for 20/40 BSS Coexistence. - BSS_2040_COEXIST_IE BSS2040CoexistInfo; - // ====== 11n D3.0 =======================> - USHORT Dot11OBssScanPassiveDwell; // Unit : TU. 5~1000 - USHORT Dot11OBssScanActiveDwell; // Unit : TU. 10~1000 - USHORT Dot11BssWidthTriggerScanInt; // Unit : Second - USHORT Dot11OBssScanPassiveTotalPerChannel; // Unit : TU. 200~10000 - USHORT Dot11OBssScanActiveTotalPerChannel; // Unit : TU. 20~10000 - USHORT Dot11BssWidthChanTranDelayFactor; - USHORT Dot11OBssScanActivityThre; // Unit : percentage - - ULONG Dot11BssWidthChanTranDelay; // multiple of (Dot11BssWidthTriggerScanInt * Dot11BssWidthChanTranDelayFactor) - ULONG CountDownCtr; // CountDown Counter from (Dot11BssWidthTriggerScanInt * Dot11BssWidthChanTranDelayFactor) - - NDIS_SPIN_LOCK TriggerEventTabLock; - BSS_2040_COEXIST_IE LastBSSCoexist2040; - BSS_2040_COEXIST_IE BSSCoexist2040; - TRIGGER_EVENT_TAB TriggerEventTab; - UCHAR ChannelListIdx; - // <====== 11n D3.0 ======================= - BOOLEAN bOverlapScanning; -#endif // DOT11N_DRAFT3 // - - BOOLEAN bHTProtect; - BOOLEAN bMIMOPSEnable; - BOOLEAN bBADecline; -//2008/11/05: KH add to support Antenna power-saving of AP<-- - BOOLEAN bGreenAPEnable; - BOOLEAN bBlockAntDivforGreenAP; -//2008/11/05: KH add to support Antenna power-saving of AP--> - BOOLEAN bDisableReordering; - BOOLEAN bForty_Mhz_Intolerant; - BOOLEAN bExtChannelSwitchAnnouncement; - BOOLEAN bRcvBSSWidthTriggerEvents; - ULONG LastRcvBSSWidthTriggerEventsTime; - - UCHAR TxBASize; -#endif // DOT11_N_SUPPORT // - - // Enable wireless event - BOOLEAN bWirelessEvent; - BOOLEAN bWiFiTest; // Enable this parameter for WiFi test - - // Tx & Rx Stream number selection - UCHAR TxStream; - UCHAR RxStream; - - // transmit phy mode, trasmit rate for Multicast. -#ifdef MCAST_RATE_SPECIFIC - UCHAR McastTransmitMcs; - UCHAR McastTransmitPhyMode; -#endif // MCAST_RATE_SPECIFIC // - - BOOLEAN bHardwareRadio; // Hardware controlled Radio enabled - - - - NDIS_SPIN_LOCK MeasureReqTabLock; - PMEASURE_REQ_TAB pMeasureReqTab; - - NDIS_SPIN_LOCK TpcReqTabLock; - PTPC_REQ_TAB pTpcReqTab; - - // transmit phy mode, trasmit rate for Multicast. -#ifdef MCAST_RATE_SPECIFIC - HTTRANSMIT_SETTING MCastPhyMode; -#endif // MCAST_RATE_SPECIFIC // - -#ifdef SINGLE_SKU - UINT16 DefineMaxTxPwr; -#endif // SINGLE_SKU // - - - BOOLEAN PSPXlink; // 0: Disable. 1: Enable - - -#if defined(RT305x)||defined(RT30xx) - // request by Gary, for High Power issue - UCHAR HighPowerPatchDisabled; -#endif - - BOOLEAN HT_DisallowTKIP; /* Restrict the encryption type in 11n HT mode */ -} COMMON_CONFIG, *PCOMMON_CONFIG; - - -#ifdef CONFIG_STA_SUPPORT -/* Modified by Wu Xi-Kun 4/21/2006 */ -// STA configuration and status -typedef struct _STA_ADMIN_CONFIG { - // GROUP 1 - - // User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe - // the user intended configuration, but not necessary fully equal to the final - // settings in ACTIVE BSS after negotiation/compromize with the BSS holder (either - // AP or IBSS holder). - // Once initialized, user configuration can only be changed via OID_xxx - UCHAR BssType; // BSS_INFRA or BSS_ADHOC - USHORT AtimWin; // used when starting a new IBSS - - // GROUP 2 - - // User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe - // the user intended configuration, and should be always applied to the final - // settings in ACTIVE BSS without compromising with the BSS holder. - // Once initialized, user configuration can only be changed via OID_xxx - UCHAR RssiTrigger; - UCHAR RssiTriggerMode; // RSSI_TRIGGERED_UPON_BELOW_THRESHOLD or RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD - USHORT DefaultListenCount; // default listen count; - ULONG WindowsPowerMode; // Power mode for AC power - ULONG WindowsBatteryPowerMode; // Power mode for battery if exists - BOOLEAN bWindowsACCAMEnable; // Enable CAM power mode when AC on - BOOLEAN bAutoReconnect; // Set to TRUE when setting OID_802_11_SSID with no matching BSSID - ULONG WindowsPowerProfile; // Windows power profile, for NDIS5.1 PnP - - // MIB:ieee802dot11.dot11smt(1).dot11StationConfigTable(1) - USHORT Psm; // power management mode (PWR_ACTIVE|PWR_SAVE) - USHORT DisassocReason; - UCHAR DisassocSta[MAC_ADDR_LEN]; - USHORT DeauthReason; - UCHAR DeauthSta[MAC_ADDR_LEN]; - USHORT AuthFailReason; - UCHAR AuthFailSta[MAC_ADDR_LEN]; - - NDIS_802_11_PRIVACY_FILTER PrivacyFilter; // PrivacyFilter enum for 802.1X - NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined - NDIS_802_11_WEP_STATUS WepStatus; - NDIS_802_11_WEP_STATUS OrigWepStatus; // Original wep status set from OID - - // Add to support different cipher suite for WPA2/WPA mode - NDIS_802_11_ENCRYPTION_STATUS GroupCipher; // Multicast cipher suite - NDIS_802_11_ENCRYPTION_STATUS PairCipher; // Unicast cipher suite - BOOLEAN bMixCipher; // Indicate current Pair & Group use different cipher suites - USHORT RsnCapability; - - NDIS_802_11_WEP_STATUS GroupKeyWepStatus; - - UCHAR WpaPassPhrase[64]; // WPA PSK pass phrase - UINT WpaPassPhraseLen; // the length of WPA PSK pass phrase - UCHAR PMK[32]; // WPA PSK mode PMK - UCHAR PTK[64]; // WPA PSK mode PTK - UCHAR GTK[32]; // GTK from authenticator - BSSID_INFO SavedPMK[PMKID_NO]; - UINT SavedPMKNum; // Saved PMKID number - - UCHAR DefaultKeyId; - - - // WPA 802.1x port control, WPA_802_1X_PORT_SECURED, WPA_802_1X_PORT_NOT_SECURED - UCHAR PortSecured; - - // For WPA countermeasures - ULONG LastMicErrorTime; // record last MIC error time - ULONG MicErrCnt; // Should be 0, 1, 2, then reset to zero (after disassoiciation). - BOOLEAN bBlockAssoc; // Block associate attempt for 60 seconds after counter measure occurred. - // For WPA-PSK supplicant state - WPA_STATE WpaState; // Default is SS_NOTUSE and handled by microsoft 802.1x - UCHAR ReplayCounter[8]; - UCHAR ANonce[32]; // ANonce for WPA-PSK from aurhenticator - UCHAR SNonce[32]; // SNonce for WPA-PSK - - UCHAR LastSNR0; // last received BEACON's SNR - UCHAR LastSNR1; // last received BEACON's SNR for 2nd antenna - RSSI_SAMPLE RssiSample; - ULONG NumOfAvgRssiSample; - - ULONG LastBeaconRxTime; // OS's timestamp of the last BEACON RX time - ULONG Last11bBeaconRxTime; // OS's timestamp of the last 11B BEACON RX time - ULONG Last11gBeaconRxTime; // OS's timestamp of the last 11G BEACON RX time - ULONG Last20NBeaconRxTime; // OS's timestamp of the last 20MHz N BEACON RX time - - ULONG LastScanTime; // Record last scan time for issue BSSID_SCAN_LIST - ULONG ScanCnt; // Scan counts since most recent SSID, BSSID, SCAN OID request - BOOLEAN bSwRadio; // Software controlled Radio On/Off, TRUE: On - BOOLEAN bHwRadio; // Hardware controlled Radio On/Off, TRUE: On - BOOLEAN bRadio; // Radio state, And of Sw & Hw radio state - BOOLEAN bHardwareRadio; // Hardware controlled Radio enabled - BOOLEAN bShowHiddenSSID; // Show all known SSID in SSID list get operation - - // New for WPA, windows want us to to keep association information and - // Fixed IEs from last association response - NDIS_802_11_ASSOCIATION_INFORMATION AssocInfo; - USHORT ReqVarIELen; // Length of next VIE include EID & Length - UCHAR ReqVarIEs[MAX_VIE_LEN]; // The content saved here should be little-endian format. - USHORT ResVarIELen; // Length of next VIE include EID & Length - UCHAR ResVarIEs[MAX_VIE_LEN]; - - UCHAR RSNIE_Len; - UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; // The content saved here should be little-endian format. - - ULONG CLBusyBytes; // Save the total bytes received durning channel load scan time - USHORT RPIDensity[8]; // Array for RPI density collection - - UCHAR RMReqCnt; // Number of measurement request saved. - UCHAR CurrentRMReqIdx; // Number of measurement request saved. - BOOLEAN ParallelReq; // Parallel measurement, only one request performed, - // It must be the same channel with maximum duration - USHORT ParallelDuration; // Maximum duration for parallel measurement - UCHAR ParallelChannel; // Only one channel with parallel measurement - USHORT IAPPToken; // IAPP dialog token - // Hack for channel load and noise histogram parameters - UCHAR NHFactor; // Parameter for Noise histogram - UCHAR CLFactor; // Parameter for channel load - - RALINK_TIMER_STRUCT StaQuickResponeForRateUpTimer; - BOOLEAN StaQuickResponeForRateUpTimerRunning; - - UCHAR DtimCount; // 0.. DtimPeriod-1 - UCHAR DtimPeriod; // default = 3 - -#ifdef QOS_DLS_SUPPORT - RT_802_11_DLS DLSEntry[MAX_NUM_OF_DLS_ENTRY]; - UCHAR DlsReplayCounter[8]; -#endif // QOS_DLS_SUPPORT // - //////////////////////////////////////////////////////////////////////////////////////// - // This is only for WHQL test. - BOOLEAN WhqlTest; - //////////////////////////////////////////////////////////////////////////////////////// - - RALINK_TIMER_STRUCT WpaDisassocAndBlockAssocTimer; - // Fast Roaming - BOOLEAN bAutoRoaming; // 0:disable auto roaming by RSSI, 1:enable auto roaming by RSSI - CHAR dBmToRoam; // the condition to roam when receiving Rssi less than this value. It's negative value. - -#ifdef WPA_SUPPLICANT_SUPPORT - BOOLEAN IEEE8021X; - BOOLEAN IEEE8021x_required_keys; - CIPHER_KEY DesireSharedKey[4]; // Record user desired WEP keys - UCHAR DesireSharedKeyId; - - // 0: driver ignores wpa_supplicant - // 1: wpa_supplicant initiates scanning and AP selection - // 2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters - UCHAR WpaSupplicantUP; - UCHAR WpaSupplicantScanCount; - BOOLEAN bRSN_IE_FromWpaSupplicant; -#endif // WPA_SUPPLICANT_SUPPORT // - - CHAR dev_name[16]; - USHORT OriDevType; - - BOOLEAN bTGnWifiTest; - BOOLEAN bScanReqIsFromWebUI; - - HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. - DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; - RT_HT_PHY_INFO DesiredHtPhyInfo; - BOOLEAN bAutoTxRateSwitch; - -#ifdef RTMP_MAC_PCI - UCHAR BBPR3; - // PS Control has 2 meanings for advanced power save function. - // 1. EnablePSinIdle : When no connection, always radio off except need to do site survey. - // 2. EnableNewPS : will save more current in sleep or radio off mode. - PS_CONTROL PSControl; -#endif // RTMP_MAC_PCI // - -#ifdef EXT_BUILD_CHANNEL_LIST - UCHAR IEEE80211dClientMode; - UCHAR StaOriCountryCode[3]; - UCHAR StaOriGeography; -#endif // EXT_BUILD_CHANNEL_LIST // - - - - BOOLEAN bAutoConnectByBssid; - ULONG BeaconLostTime; // seconds - BOOLEAN bForceTxBurst; // 1: force enble TX PACKET BURST, 0: disable -} STA_ADMIN_CONFIG, *PSTA_ADMIN_CONFIG; - -// This data structure keep the current active BSS/IBSS's configuration that this STA -// had agreed upon joining the network. Which means these parameters are usually decided -// by the BSS/IBSS creator instead of user configuration. Data in this data structurre -// is valid only when either ADHOC_ON(pAd) or INFRA_ON(pAd) is TRUE. -// Normally, after SCAN or failed roaming attempts, we need to recover back to -// the current active settings. -typedef struct _STA_ACTIVE_CONFIG { - USHORT Aid; - USHORT AtimWin; // in kusec; IBSS parameter set element - USHORT CapabilityInfo; - USHORT CfpMaxDuration; - USHORT CfpPeriod; - - // Copy supported rate from desired AP's beacon. We are trying to match - // AP's supported and extended rate settings. - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen; - UCHAR ExtRateLen; - // Copy supported ht from desired AP's beacon. We are trying to match - RT_HT_PHY_INFO SupportedPhyInfo; - RT_HT_CAPABILITY SupportedHtPhy; -} STA_ACTIVE_CONFIG, *PSTA_ACTIVE_CONFIG; - - - -#endif // CONFIG_STA_SUPPORT // - - - -typedef struct _MAC_TABLE_ENTRY { - //Choose 1 from ValidAsWDS and ValidAsCLI to validize. - BOOLEAN ValidAsCLI; // Sta mode, set this TRUE after Linkup,too. - BOOLEAN ValidAsWDS; // This is WDS Entry. only for AP mode. - BOOLEAN ValidAsApCli; //This is a AP-Client entry, only for AP mode which enable AP-Client functions. - BOOLEAN ValidAsMesh; - BOOLEAN ValidAsDls; // This is DLS Entry. only for STA mode. - BOOLEAN isCached; - BOOLEAN bIAmBadAtheros; // Flag if this is Atheros chip that has IOT problem. We need to turn on RTS/CTS protection. - - UCHAR EnqueueEapolStartTimerRunning; // Enqueue EAPoL-Start for triggering EAP SM - //jan for wpa - // record which entry revoke MIC Failure , if it leaves the BSS itself, AP won't update aMICFailTime MIB - UCHAR CMTimerRunning; - UCHAR apidx; // MBSS number - UCHAR RSNIE_Len; - UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; - UCHAR ANonce[LEN_KEY_DESC_NONCE]; - UCHAR SNonce[LEN_KEY_DESC_NONCE]; - UCHAR R_Counter[LEN_KEY_DESC_REPLAY]; - UCHAR PTK[64]; - UCHAR ReTryCounter; - RALINK_TIMER_STRUCT RetryTimer; - RALINK_TIMER_STRUCT EnqueueStartForPSKTimer; // A timer which enqueue EAPoL-Start for triggering PSK SM - NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined - NDIS_802_11_WEP_STATUS WepStatus; - NDIS_802_11_WEP_STATUS GroupKeyWepStatus; - AP_WPA_STATE WpaState; - GTK_STATE GTKState; - USHORT PortSecured; - NDIS_802_11_PRIVACY_FILTER PrivacyFilter; // PrivacyFilter enum for 802.1X - CIPHER_KEY PairwiseKey; - PVOID pAd; - INT PMKID_CacheIdx; - UCHAR PMKID[LEN_PMKID]; - - - UCHAR Addr[MAC_ADDR_LEN]; - UCHAR PsMode; - SST Sst; - AUTH_STATE AuthState; // for SHARED KEY authentication state machine used only - BOOLEAN IsReassocSta; // Indicate whether this is a reassociation procedure - USHORT Aid; - USHORT CapabilityInfo; - UCHAR LastRssi; - ULONG NoDataIdleCount; - UINT16 StationKeepAliveCount; // unit: second - ULONG PsQIdleCount; - QUEUE_HEADER PsQueue; - - UINT32 StaConnectTime; // the live time of this station since associated with AP - - -#ifdef DOT11_N_SUPPORT - BOOLEAN bSendBAR; - USHORT NoBADataCountDown; - - UINT32 CachedBuf[16]; // UINT (4 bytes) for alignment - UINT TxBFCount; // 3*3 -#endif // DOT11_N_SUPPORT // - UINT FIFOCount; - UINT DebugFIFOCount; - UINT DebugTxCount; - BOOLEAN bDlsInit; - - -//==================================================== -//WDS entry needs these -// if ValidAsWDS==TRUE, MatchWDSTabIdx is the index in WdsTab.MacTab - UINT MatchWDSTabIdx; - UCHAR MaxSupportedRate; - UCHAR CurrTxRate; - UCHAR CurrTxRateIndex; - // to record the each TX rate's quality. 0 is best, the bigger the worse. - USHORT TxQuality[MAX_STEP_OF_TX_RATE_SWITCH]; -// USHORT OneSecTxOkCount; - UINT32 OneSecTxNoRetryOkCount; - UINT32 OneSecTxRetryOkCount; - UINT32 OneSecTxFailCount; - UINT32 ContinueTxFailCnt; - UINT32 CurrTxRateStableTime; // # of second in current TX rate - UCHAR TxRateUpPenalty; // extra # of second penalty due to last unstable condition -#ifdef WDS_SUPPORT - BOOLEAN LockEntryTx; // TRUE = block to WDS Entry traffic, FALSE = not. - UINT32 TimeStamp_toTxRing; -#endif // WDS_SUPPORT // - -//==================================================== - - - -#ifdef CONFIG_STA_SUPPORT -#ifdef QOS_DLS_SUPPORT - UINT MatchDlsEntryIdx; // indicate the index in pAd->StaCfg.DLSEntry -#endif // QOS_DLS_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - - BOOLEAN fNoisyEnvironment; - BOOLEAN fLastSecAccordingRSSI; - UCHAR LastSecTxRateChangeAction; // 0: no change, 1:rate UP, 2:rate down - CHAR LastTimeTxRateChangeAction; //Keep last time value of LastSecTxRateChangeAction - ULONG LastTxOkCount; - UCHAR PER[MAX_STEP_OF_TX_RATE_SWITCH]; - - // a bitmap of BOOLEAN flags. each bit represent an operation status of a particular - // BOOLEAN control, either ON or OFF. These flags should always be accessed via - // CLIENT_STATUS_TEST_FLAG(), CLIENT_STATUS_SET_FLAG(), CLIENT_STATUS_CLEAR_FLAG() macros. - // see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition. fCLIENT_STATUS_AMSDU_INUSED - ULONG ClientStatusFlags; - - HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. - -#ifdef DOT11_N_SUPPORT - // HT EWC MIMO-N used parameters - USHORT RXBAbitmap; // fill to on-chip RXWI_BA_BITMASK in 8.1.3RX attribute entry format - USHORT TXBAbitmap; // This bitmap as originator, only keep in software used to mark AMPDU bit in TXWI - USHORT TXAutoBAbitmap; - USHORT BADeclineBitmap; - USHORT BARecWcidArray[NUM_OF_TID]; // The mapping wcid of recipient session. if RXBAbitmap bit is masked - USHORT BAOriWcidArray[NUM_OF_TID]; // The mapping wcid of originator session. if TXBAbitmap bit is masked - USHORT BAOriSequence[NUM_OF_TID]; // The mapping wcid of originator session. if TXBAbitmap bit is masked - - // 802.11n features. - UCHAR MpduDensity; - UCHAR MaxRAmpduFactor; - UCHAR AMsduSize; - UCHAR MmpsMode; // MIMO power save more. - - HT_CAPABILITY_IE HTCapability; - -#ifdef DOT11N_DRAFT3 - UCHAR BSS2040CoexistenceMgmtSupport; -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // - - BOOLEAN bAutoTxRateSwitch; - - UCHAR RateLen; - struct _MAC_TABLE_ENTRY *pNext; - USHORT TxSeq[NUM_OF_TID]; - USHORT NonQosDataSeq; - - RSSI_SAMPLE RssiSample; - - UINT32 TXMCSExpected[16]; - UINT32 TXMCSSuccessful[16]; - UINT32 TXMCSFailed[16]; - UINT32 TXMCSAutoFallBack[16][16]; - -#ifdef CONFIG_STA_SUPPORT - ULONG LastBeaconRxTime; -#endif // CONFIG_STA_SUPPORT // - - - - ULONG AssocDeadLine; - - - - ULONG ChannelQuality; // 0..100, Channel Quality Indication for Roaming - -} MAC_TABLE_ENTRY, *PMAC_TABLE_ENTRY; - -typedef struct _MAC_TABLE { - USHORT Size; - MAC_TABLE_ENTRY *Hash[HASH_TABLE_SIZE]; - MAC_TABLE_ENTRY Content[MAX_LEN_OF_MAC_TABLE]; - QUEUE_HEADER McastPsQueue; - ULONG PsQIdleCount; - BOOLEAN fAnyStationInPsm; - BOOLEAN fAnyStationBadAtheros; // Check if any Station is atheros 802.11n Chip. We need to use RTS/CTS with Atheros 802,.11n chip. - BOOLEAN fAnyTxOPForceDisable; // Check if it is necessary to disable BE TxOP - BOOLEAN fAllStationAsRalink; // Check if all stations are ralink-chipset -#ifdef DOT11_N_SUPPORT - BOOLEAN fAnyStationIsLegacy; // Check if I use legacy rate to transmit to my BSS Station/ - BOOLEAN fAnyStationNonGF; // Check if any Station can't support GF. - BOOLEAN fAnyStation20Only; // Check if any Station can't support GF. - BOOLEAN fAnyStationMIMOPSDynamic; // Check if any Station is MIMO Dynamic - BOOLEAN fAnyBASession; // Check if there is BA session. Force turn on RTS/CTS -//2008/10/28: KH add to support Antenna power-saving of AP<-- -//2008/10/28: KH add to support Antenna power-saving of AP--> -#endif // DOT11_N_SUPPORT // -} MAC_TABLE, *PMAC_TABLE; - - - - -#ifdef BLOCK_NET_IF -typedef struct _BLOCK_QUEUE_ENTRY -{ - BOOLEAN SwTxQueueBlockFlag; - LIST_HEADER NetIfList; -} BLOCK_QUEUE_ENTRY, *PBLOCK_QUEUE_ENTRY; -#endif // BLOCK_NET_IF // - - -struct wificonf -{ - BOOLEAN bShortGI; - BOOLEAN bGreenField; -}; - - -typedef struct _RTMP_DEV_INFO_ -{ - UCHAR chipName[16]; - RTMP_INF_TYPE infType; -}RTMP_DEV_INFO; - - -#ifdef DBG_DIAGNOSE -#define DIAGNOSE_TIME 10 // 10 sec -typedef struct _RtmpDiagStrcut_ -{ // Diagnosis Related element - unsigned char inited; - unsigned char qIdx; - unsigned char ArrayStartIdx; - unsigned char ArrayCurIdx; - // Tx Related Count - USHORT TxDataCnt[DIAGNOSE_TIME]; - USHORT TxFailCnt[DIAGNOSE_TIME]; -// USHORT TxDescCnt[DIAGNOSE_TIME][16]; // TxDesc queue length in scale of 0~14, >=15 - USHORT TxDescCnt[DIAGNOSE_TIME][24]; // 3*3 // TxDesc queue length in scale of 0~14, >=15 -// USHORT TxMcsCnt[DIAGNOSE_TIME][16]; // TxDate MCS Count in range from 0 to 15, step in 1. - USHORT TxMcsCnt[DIAGNOSE_TIME][24]; // 3*3 - USHORT TxSWQueCnt[DIAGNOSE_TIME][9]; // TxSwQueue length in scale of 0, 1, 2, 3, 4, 5, 6, 7, >=8 - - USHORT TxAggCnt[DIAGNOSE_TIME]; - USHORT TxNonAggCnt[DIAGNOSE_TIME]; -// USHORT TxAMPDUCnt[DIAGNOSE_TIME][16]; // 10 sec, TxDMA APMDU Aggregation count in range from 0 to 15, in setp of 1. - USHORT TxAMPDUCnt[DIAGNOSE_TIME][24]; // 3*3 // 10 sec, TxDMA APMDU Aggregation count in range from 0 to 15, in setp of 1. - USHORT TxRalinkCnt[DIAGNOSE_TIME]; // TxRalink Aggregation Count in 1 sec scale. - USHORT TxAMSDUCnt[DIAGNOSE_TIME]; // TxAMSUD Aggregation Count in 1 sec scale. - - // Rx Related Count - USHORT RxDataCnt[DIAGNOSE_TIME]; // Rx Total Data count. - USHORT RxCrcErrCnt[DIAGNOSE_TIME]; -// USHORT RxMcsCnt[DIAGNOSE_TIME][16]; // Rx MCS Count in range from 0 to 15, step in 1. - USHORT RxMcsCnt[DIAGNOSE_TIME][24]; // 3*3 -}RtmpDiagStruct; -#endif // DBG_DIAGNOSE // - - -struct _RTMP_CHIP_OP_ -{ - /* Calibration access related callback functions */ - int (*eeinit)(RTMP_ADAPTER *pAd); /* int (*eeinit)(RTMP_ADAPTER *pAd); */ - int (*eeread)(RTMP_ADAPTER *pAd, USHORT offset, PUSHORT pValue); /* int (*eeread)(RTMP_ADAPTER *pAd, int offset, PUSHORT pValue); */ - int (*eewrite)(RTMP_ADAPTER *pAd, USHORT offset, USHORT value);; /* int (*eewrite)(RTMP_ADAPTER *pAd, int offset, USHORT value); */ - - /* MCU related callback functions */ - int (*loadFirmware)(RTMP_ADAPTER *pAd); /* int (*loadFirmware)(RTMP_ADAPTER *pAd); */ - int (*eraseFirmware)(RTMP_ADAPTER *pAd); /* int (*eraseFirmware)(RTMP_ADAPTER *pAd); */ - int (*sendCommandToMcu)(RTMP_ADAPTER *pAd, UCHAR cmd, UCHAR token, UCHAR arg0, UCHAR arg1);; /* int (*sendCommandToMcu)(RTMP_ADAPTER *pAd, UCHAR cmd, UCHAR token, UCHAR arg0, UCHAR arg1); */ - - /* RF access related callback functions */ - REG_PAIR *pRFRegTable; - void (*AsicRfInit)(RTMP_ADAPTER *pAd); - void (*AsicRfTurnOn)(RTMP_ADAPTER *pAd); - void (*AsicRfTurnOff)(RTMP_ADAPTER *pAd); - void (*AsicReverseRfFromSleepMode)(RTMP_ADAPTER *pAd); - void (*AsicHaltAction)(RTMP_ADAPTER *pAd); -}; - - -// -// The miniport adapter structure -// -struct _RTMP_ADAPTER -{ - PVOID OS_Cookie; // save specific structure relative to OS - PNET_DEV net_dev; - ULONG VirtualIfCnt; - - RTMP_CHIP_OP chipOps; - USHORT ThisTbttNumToNextWakeUp; - -#ifdef INF_AMAZON_PPA - UINT32 g_if_id; - BOOLEAN PPAEnable; - PPA_DIRECTPATH_CB *pDirectpathCb; -#endif // INF_AMAZON_PPA // - -#ifdef RTMP_MAC_PCI -/*****************************************************************************************/ -/* PCI related parameters */ -/*****************************************************************************************/ - PUCHAR CSRBaseAddress; // PCI MMIO Base Address, all access will use - unsigned int irq_num; - - USHORT LnkCtrlBitMask; - USHORT RLnkCtrlConfiguration; - USHORT RLnkCtrlOffset; - USHORT HostLnkCtrlConfiguration; - USHORT HostLnkCtrlOffset; - USHORT PCIePowerSaveLevel; - ULONG Rt3xxHostLinkCtrl; // USed for 3090F chip - ULONG Rt3xxRalinkLinkCtrl; // USed for 3090F chip - USHORT DeviceID; // Read from PCI config - ULONG AccessBBPFailCount; - BOOLEAN bPCIclkOff; // flag that indicate if the PICE power status in Configuration SPace.. - BOOLEAN bPCIclkOffDisableTx; // - - BOOLEAN brt30xxBanMcuCmd; //when = 0xff means all commands are ok to set . - BOOLEAN b3090ESpecialChip; //3090E special chip that write EEPROM 0x24=0x9280. - ULONG CheckDmaBusyCount; // Check Interrupt Status Register Count. - - UINT int_enable_reg; - UINT int_disable_mask; - UINT int_pending; - - - RTMP_DMABUF TxBufSpace[NUM_OF_TX_RING]; // Shared memory of all 1st pre-allocated TxBuf associated with each TXD - RTMP_DMABUF RxDescRing; // Shared memory for RX descriptors - RTMP_DMABUF TxDescRing[NUM_OF_TX_RING]; // Shared memory for Tx descriptors - RTMP_TX_RING TxRing[NUM_OF_TX_RING]; // AC0~4 + HCCA -#endif // RTMP_MAC_PCI // - - - NDIS_SPIN_LOCK irq_lock; - UCHAR irq_disabled; - - -/*****************************************************************************************/ -/* RBUS related parameters */ -/*****************************************************************************************/ - - -/*****************************************************************************************/ -/* Both PCI/USB related parameters */ -/*****************************************************************************************/ - //RTMP_DEV_INFO chipInfo; - RTMP_INF_TYPE infType; - -/*****************************************************************************************/ -/* Driver Mgmt related parameters */ -/*****************************************************************************************/ - RTMP_OS_TASK mlmeTask; -#ifdef RTMP_TIMER_TASK_SUPPORT - // If you want use timer task to handle the timer related jobs, enable this. - RTMP_TIMER_TASK_QUEUE TimerQ; - NDIS_SPIN_LOCK TimerQLock; - RTMP_OS_TASK timerTask; -#endif // RTMP_TIMER_TASK_SUPPORT // - - -/*****************************************************************************************/ -/* Tx related parameters */ -/*****************************************************************************************/ - BOOLEAN DeQueueRunning[NUM_OF_TX_RING]; // for ensuring RTUSBDeQueuePacket get call once - NDIS_SPIN_LOCK DeQueueLock[NUM_OF_TX_RING]; - - - // resource for software backlog queues - QUEUE_HEADER TxSwQueue[NUM_OF_TX_RING]; // 4 AC + 1 HCCA - NDIS_SPIN_LOCK TxSwQueueLock[NUM_OF_TX_RING]; // TxSwQueue spinlock - - RTMP_DMABUF MgmtDescRing; // Shared memory for MGMT descriptors - RTMP_MGMT_RING MgmtRing; - NDIS_SPIN_LOCK MgmtRingLock; // Prio Ring spinlock - - -/*****************************************************************************************/ -/* Rx related parameters */ -/*****************************************************************************************/ - -#ifdef RTMP_MAC_PCI - RTMP_RX_RING RxRing; - NDIS_SPIN_LOCK RxRingLock; // Rx Ring spinlock -#ifdef RT3090 - NDIS_SPIN_LOCK McuCmdLock; //MCU Command Queue spinlock -#endif // RT3090 // -#endif // RTMP_MAC_PCI // - - - -/*****************************************************************************************/ -/* ASIC related parameters */ -/*****************************************************************************************/ - UINT32 MACVersion; // MAC version. Record rt2860C(0x28600100) or rt2860D (0x28600101).. - - // --------------------------- - // E2PROM - // --------------------------- - ULONG EepromVersion; // byte 0: version, byte 1: revision, byte 2~3: unused - ULONG FirmwareVersion; // byte 0: Minor version, byte 1: Major version, otherwise unused. - USHORT EEPROMDefaultValue[NUM_EEPROM_BBP_PARMS]; - UCHAR EEPROMAddressNum; // 93c46=6 93c66=8 - BOOLEAN EepromAccess; - UCHAR EFuseTag; - - - // --------------------------- - // BBP Control - // --------------------------- -#ifdef MERGE_ARCH_TEAM - UCHAR BbpWriteLatch[256]; // record last BBP register value written via BBP_IO_WRITE/BBP_IO_WRITE_VY_REG_ID -#else - UCHAR BbpWriteLatch[140]; // record last BBP register value written via BBP_IO_WRITE/BBP_IO_WRITE_VY_REG_ID -#endif // MERGE_ARCH_TEAM // - CHAR BbpRssiToDbmDelta; // change from UCHAR to CHAR for high power - BBP_R66_TUNING BbpTuning; - - // ---------------------------- - // RFIC control - // ---------------------------- - UCHAR RfIcType; // RFIC_xxx - ULONG RfFreqOffset; // Frequency offset for channel switching - RTMP_RF_REGS LatchRfRegs; // latch th latest RF programming value since RF IC doesn't support READ - - EEPROM_ANTENNA_STRUC Antenna; // Since ANtenna definition is different for a & g. We need to save it for future reference. - EEPROM_NIC_CONFIG2_STRUC NicConfig2; - - // This soft Rx Antenna Diversity mechanism is used only when user set - // RX Antenna = DIVERSITY ON - SOFT_RX_ANT_DIVERSITY RxAnt; - - UCHAR RFProgSeq; - CHANNEL_TX_POWER TxPower[MAX_NUM_OF_CHANNELS]; // Store Tx power value for all channels. - CHANNEL_TX_POWER ChannelList[MAX_NUM_OF_CHANNELS]; // list all supported channels for site survey - CHANNEL_11J_TX_POWER TxPower11J[MAX_NUM_OF_11JCHANNELS]; // 802.11j channel and bw - CHANNEL_11J_TX_POWER ChannelList11J[MAX_NUM_OF_11JCHANNELS]; // list all supported channels for site survey - - UCHAR ChannelListNum; // number of channel in ChannelList[] - UCHAR Bbp94; - BOOLEAN BbpForCCK; - ULONG Tx20MPwrCfgABand[5]; - ULONG Tx20MPwrCfgGBand[5]; - ULONG Tx40MPwrCfgABand[5]; - ULONG Tx40MPwrCfgGBand[5]; - - BOOLEAN bAutoTxAgcA; // Enable driver auto Tx Agc control - UCHAR TssiRefA; // Store Tssi reference value as 25 temperature. - UCHAR TssiPlusBoundaryA[5]; // Tssi boundary for increase Tx power to compensate. - UCHAR TssiMinusBoundaryA[5]; // Tssi boundary for decrease Tx power to compensate. - UCHAR TxAgcStepA; // Store Tx TSSI delta increment / decrement value - CHAR TxAgcCompensateA; // Store the compensation (TxAgcStep * (idx-1)) - - BOOLEAN bAutoTxAgcG; // Enable driver auto Tx Agc control - UCHAR TssiRefG; // Store Tssi reference value as 25 temperature. - UCHAR TssiPlusBoundaryG[5]; // Tssi boundary for increase Tx power to compensate. - UCHAR TssiMinusBoundaryG[5]; // Tssi boundary for decrease Tx power to compensate. - UCHAR TxAgcStepG; // Store Tx TSSI delta increment / decrement value - CHAR TxAgcCompensateG; // Store the compensation (TxAgcStep * (idx-1)) - - CHAR BGRssiOffset0; // Store B/G RSSI#0 Offset value on EEPROM 0x46h - CHAR BGRssiOffset1; // Store B/G RSSI#1 Offset value - CHAR BGRssiOffset2; // Store B/G RSSI#2 Offset value - - CHAR ARssiOffset0; // Store A RSSI#0 Offset value on EEPROM 0x4Ah - CHAR ARssiOffset1; // Store A RSSI#1 Offset value - CHAR ARssiOffset2; // Store A RSSI#2 Offset value - - CHAR BLNAGain; // Store B/G external LNA#0 value on EEPROM 0x44h - CHAR ALNAGain0; // Store A external LNA#0 value for ch36~64 - CHAR ALNAGain1; // Store A external LNA#1 value for ch100~128 - CHAR ALNAGain2; // Store A external LNA#2 value for ch132~165 -#ifdef RT30xx - // for 3572 - UCHAR Bbp25; - UCHAR Bbp26; - - UCHAR TxMixerGain24G; // Tx mixer gain value from EEPROM to improve Tx EVM / Tx DAC, 2.4G - UCHAR TxMixerGain5G; -#endif // RT30xx // - // ---------------------------- - // LED control - // ---------------------------- - MCU_LEDCS_STRUC LedCntl; - USHORT Led1; // read from EEPROM 0x3c - USHORT Led2; // EEPROM 0x3e - USHORT Led3; // EEPROM 0x40 - UCHAR LedIndicatorStrength; - UCHAR RssiSingalstrengthOffet; - BOOLEAN bLedOnScanning; - UCHAR LedStatus; - -/*****************************************************************************************/ -/* 802.11 related parameters */ -/*****************************************************************************************/ - // outgoing BEACON frame buffer and corresponding TXD - TXWI_STRUC BeaconTxWI; - PUCHAR BeaconBuf; - USHORT BeaconOffset[HW_BEACON_MAX_COUNT]; - - // pre-build PS-POLL and NULL frame upon link up. for efficiency purpose. - PSPOLL_FRAME PsPollFrame; - HEADER_802_11 NullFrame; - - - - -//=========AP=========== - - -//=======STA=========== -#ifdef CONFIG_STA_SUPPORT - // ----------------------------------------------- - // STA specific configuration & operation status - // used only when pAd->OpMode == OPMODE_STA - // ----------------------------------------------- - STA_ADMIN_CONFIG StaCfg; // user desired settings - STA_ACTIVE_CONFIG StaActive; // valid only when ADHOC_ON(pAd) || INFRA_ON(pAd) - CHAR nickname[IW_ESSID_MAX_SIZE+1]; // nickname, only used in the iwconfig i/f - NDIS_MEDIA_STATE PreMediaState; -#endif // CONFIG_STA_SUPPORT // - -//=======Common=========== - // OP mode: either AP or STA - UCHAR OpMode; // OPMODE_STA, OPMODE_AP - - NDIS_MEDIA_STATE IndicateMediaState; // Base on Indication state, default is NdisMediaStateDisConnected - - - /* MAT related parameters */ - - // configuration: read from Registry & E2PROM - BOOLEAN bLocalAdminMAC; // Use user changed MAC - UCHAR PermanentAddress[MAC_ADDR_LEN]; // Factory default MAC address - UCHAR CurrentAddress[MAC_ADDR_LEN]; // User changed MAC address - - // ------------------------------------------------------ - // common configuration to both OPMODE_STA and OPMODE_AP - // ------------------------------------------------------ - COMMON_CONFIG CommonCfg; - MLME_STRUCT Mlme; - - // AP needs those vaiables for site survey feature. - MLME_AUX MlmeAux; // temporary settings used during MLME state machine - BSS_TABLE ScanTab; // store the latest SCAN result - - //About MacTab, the sta driver will use #0 and #1 for multicast and AP. - MAC_TABLE MacTab; // ASIC on-chip WCID entry table. At TX, ASIC always use key according to this on-chip table. - NDIS_SPIN_LOCK MacTabLock; - -#ifdef DOT11_N_SUPPORT - BA_TABLE BATable; - NDIS_SPIN_LOCK BATabLock; - RALINK_TIMER_STRUCT RECBATimer; -#endif // DOT11_N_SUPPORT // - - // encryption/decryption KEY tables - CIPHER_KEY SharedKey[MAX_MBSSID_NUM][4]; // STA always use SharedKey[BSS0][0..3] - - // RX re-assembly buffer for fragmentation - FRAGMENT_FRAME FragFrame; // Frame storage for fragment frame - - // various Counters - COUNTER_802_3 Counters8023; // 802.3 counters - COUNTER_802_11 WlanCounters; // 802.11 MIB counters - COUNTER_RALINK RalinkCounters; // Ralink propriety counters - COUNTER_DRS DrsCounters; // counters for Dynamic TX Rate Switching - PRIVATE_STRUC PrivateInfo; // Private information & counters - - // flags, see fRTMP_ADAPTER_xxx flags - ULONG Flags; // Represent current device status - ULONG PSFlags; // Power Save operation flag. - - // current TX sequence # - USHORT Sequence; - - // Control disconnect / connect event generation - //+++Didn't used anymore - ULONG LinkDownTime; - //--- - ULONG LastRxRate; - ULONG LastTxRate; - //+++Used only for Station - BOOLEAN bConfigChanged; // Config Change flag for the same SSID setting - //--- - - ULONG ExtraInfo; // Extra information for displaying status - ULONG SystemErrorBitmap; // b0: E2PROM version error - - //+++Didn't used anymore - ULONG MacIcVersion; // MAC/BBP serial interface issue solved after ver.D - //--- - - // --------------------------- - // System event log - // --------------------------- - RT_802_11_EVENT_TABLE EventTab; - - - BOOLEAN HTCEnable; - - /*****************************************************************************************/ - /* Statistic related parameters */ - /*****************************************************************************************/ - - BOOLEAN bUpdateBcnCntDone; - ULONG watchDogMacDeadlock; // prevent MAC/BBP into deadlock condition - // ---------------------------- - // DEBUG paramerts - // ---------------------------- - //ULONG DebugSetting[4]; - BOOLEAN bBanAllBaSetup; - BOOLEAN bPromiscuous; - - // ---------------------------- - // rt2860c emulation-use Parameters - // ---------------------------- - //ULONG rtsaccu[30]; - //ULONG ctsaccu[30]; - //ULONG cfendaccu[30]; - //ULONG bacontent[16]; - //ULONG rxint[RX_RING_SIZE+1]; - //UCHAR rcvba[60]; - BOOLEAN bLinkAdapt; - BOOLEAN bForcePrintTX; - BOOLEAN bForcePrintRX; - //BOOLEAN bDisablescanning; //defined in RT2870 USB - BOOLEAN bStaFifoTest; - BOOLEAN bProtectionTest; - /* - BOOLEAN bHCCATest; - BOOLEAN bGenOneHCCA; - */ - BOOLEAN bBroadComHT; - //+++Following add from RT2870 USB. - ULONG BulkOutReq; - ULONG BulkOutComplete; - ULONG BulkOutCompleteOther; - ULONG BulkOutCompleteCancel; // seems not use now? - ULONG BulkInReq; - ULONG BulkInComplete; - ULONG BulkInCompleteFail; - //--- - - struct wificonf WIFItestbed; - -#ifdef RALINK_ATE - ATE_INFO ate; -#endif // RALINK_ATE // - -#ifdef DOT11_N_SUPPORT - struct reordering_mpdu_pool mpdu_blk_pool; -#endif // DOT11_N_SUPPORT // - - ULONG OneSecondnonBEpackets; // record non BE packets per second - -#ifdef LINUX -#if WIRELESS_EXT >= 12 - struct iw_statistics iw_stats; -#endif - - struct net_device_stats stats; -#endif // LINUX // - -#ifdef BLOCK_NET_IF - BLOCK_QUEUE_ENTRY blockQueueTab[NUM_OF_TX_RING]; -#endif // BLOCK_NET_IF // - - - -#ifdef MULTIPLE_CARD_SUPPORT - INT32 MC_RowID; - STRING MC_FileName[256]; -#endif // MULTIPLE_CARD_SUPPORT // - - ULONG TbttTickCount; -#ifdef PCI_MSI_SUPPORT - BOOLEAN HaveMsi; -#endif // PCI_MSI_SUPPORT // - - - UCHAR is_on; - -#define TIME_BASE (1000000/OS_HZ) -#define TIME_ONE_SECOND (1000000/TIME_BASE) - UCHAR flg_be_adjust; - ULONG be_adjust_last_time; - -#ifdef NINTENDO_AP - NINDO_CTRL_BLOCK nindo_ctrl_block; -#endif // NINTENDO_AP // - - -#ifdef IKANOS_VX_1X0 - struct IKANOS_TX_INFO IkanosTxInfo; - struct IKANOS_TX_INFO IkanosRxInfo[MAX_MBSSID_NUM + MAX_WDS_ENTRY + MAX_APCLI_NUM + MAX_MESH_NUM]; -#endif // IKANOS_VX_1X0 // - - -#ifdef DBG_DIAGNOSE - RtmpDiagStruct DiagStruct; -#endif // DBG_DIAGNOSE // - - - UINT8 FlgCtsEnabled; - UINT8 PM_FlgSuspend; - -#ifdef RT30xx -#ifdef RTMP_EFUSE_SUPPORT - BOOLEAN bUseEfuse; - BOOLEAN bEEPROMFile; - BOOLEAN bFroceEEPROMBuffer; - UCHAR EEPROMImage[1024]; -#endif // RTMP_EFUSE_SUPPORT // -#endif // RT30xx // - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - -}; - - - -#ifdef TONE_RADAR_DETECT_SUPPORT -#define DELAYINTMASK 0x0013fffb -#define INTMASK 0x0013fffb -#define IndMask 0x0013fffc -#define RadarInt 0x00100000 -#else -#define DELAYINTMASK 0x0003fffb -#define INTMASK 0x0003fffb -#define IndMask 0x0003fffc -#endif // TONE_RADAR_DETECT_SUPPORT // - -#define RxINT 0x00000005 // Delayed Rx or indivi rx -#define TxDataInt 0x000000fa // Delayed Tx or indivi tx -#define TxMgmtInt 0x00000102 // Delayed Tx or indivi tx -#define TxCoherent 0x00020000 // tx coherent -#define RxCoherent 0x00010000 // rx coherent -#define McuCommand 0x00000200 // mcu -#define PreTBTTInt 0x00001000 // Pre-TBTT interrupt -#define TBTTInt 0x00000800 // TBTT interrupt -#define GPTimeOutInt 0x00008000 // GPtimeout interrupt -#define AutoWakeupInt 0x00004000 // AutoWakeupInt interrupt -#define FifoStaFullInt 0x00002000 // fifo statistics full interrupt - - -/*************************************************************************** - * Rx Path software control block related data structures - **************************************************************************/ -typedef struct _RX_BLK_ -{ -// RXD_STRUC RxD; // sample - RT28XX_RXD_STRUC RxD; - PRXWI_STRUC pRxWI; - PHEADER_802_11 pHeader; - PNDIS_PACKET pRxPacket; - UCHAR *pData; - USHORT DataSize; - USHORT Flags; - UCHAR UserPriority; // for calculate TKIP MIC using -} RX_BLK; - - -#define RX_BLK_SET_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags |= _flag) -#define RX_BLK_TEST_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags & _flag) -#define RX_BLK_CLEAR_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags &= ~(_flag)) - - -#define fRX_WDS 0x0001 -#define fRX_AMSDU 0x0002 -#define fRX_ARALINK 0x0004 -#define fRX_HTC 0x0008 -#define fRX_PAD 0x0010 -#define fRX_AMPDU 0x0020 -#define fRX_QOS 0x0040 -#define fRX_INFRA 0x0080 -#define fRX_EAP 0x0100 -#define fRX_MESH 0x0200 -#define fRX_APCLI 0x0400 -#define fRX_DLS 0x0800 -#define fRX_WPI 0x1000 - -#define LENGTH_AMSDU_SUBFRAMEHEAD 14 -#define LENGTH_ARALINK_SUBFRAMEHEAD 14 -#define LENGTH_ARALINK_HEADER_FIELD 2 - - -/*************************************************************************** - * Tx Path software control block related data structures - **************************************************************************/ -#define TX_UNKOWN_FRAME 0x00 -#define TX_MCAST_FRAME 0x01 -#define TX_LEGACY_FRAME 0x02 -#define TX_AMPDU_FRAME 0x04 -#define TX_AMSDU_FRAME 0x08 -#define TX_RALINK_FRAME 0x10 -#define TX_FRAG_FRAME 0x20 - - -// Currently the sizeof(TX_BLK) is 148 bytes. -typedef struct _TX_BLK_ -{ - UCHAR QueIdx; - UCHAR TxFrameType; // Indicate the Transmission type of the all frames in one batch - UCHAR TotalFrameNum; // Total frame number want to send-out in one batch - USHORT TotalFragNum; // Total frame fragments required in one batch - USHORT TotalFrameLen; // Total length of all frames want to send-out in one batch - - QUEUE_HEADER TxPacketList; - MAC_TABLE_ENTRY *pMacEntry; // NULL: packet with 802.11 RA field is multicast/broadcast address - HTTRANSMIT_SETTING *pTransmit; - - // Following structure used for the characteristics of a specific packet. - PNDIS_PACKET pPacket; - PUCHAR pSrcBufHeader; // Reference to the head of sk_buff->data - PUCHAR pSrcBufData; // Reference to the sk_buff->data, will changed depends on hanlding progresss - UINT SrcBufLen; // Length of packet payload which not including Layer 2 header - PUCHAR pExtraLlcSnapEncap; // NULL means no extra LLC/SNAP is required - UCHAR HeaderBuf[96]; // TempBuffer for TX_INFO + TX_WI + 802.11 Header + padding + AMSDU SubHeader + LLC/SNAP - UCHAR MpduHeaderLen; // 802.11 header length NOT including the padding - UCHAR HdrPadLen; // recording Header Padding Length; - UCHAR apidx; // The interface associated to this packet - UCHAR Wcid; // The MAC entry associated to this packet - UCHAR UserPriority; // priority class of packet - UCHAR FrameGap; // what kind of IFS this packet use - UCHAR MpduReqNum; // number of fragments of this frame - UCHAR TxRate; // TODO: Obsoleted? Should change to MCS? - UCHAR CipherAlg; // cipher alogrithm - PCIPHER_KEY pKey; - - - - USHORT Flags; //See following definitions for detail. - - //YOU SHOULD NOT TOUCH IT! Following parameters are used for hardware-depended layer. - ULONG Priv; // Hardware specific value saved in here. - -} TX_BLK, *PTX_BLK; - - -#define fTX_bRtsRequired 0x0001 // Indicate if need send RTS frame for protection. Not used in RT2860/RT2870. -#define fTX_bAckRequired 0x0002 // the packet need ack response -#define fTX_bPiggyBack 0x0004 // Legacy device use Piggback or not -#define fTX_bHTRate 0x0008 // allow to use HT rate -#define fTX_bForceNonQoS 0x0010 // force to transmit frame without WMM-QoS in HT mode -#define fTX_bAllowFrag 0x0020 // allow to fragment the packet, A-MPDU, A-MSDU, A-Ralink is not allowed to fragment -#define fTX_bMoreData 0x0040 // there are more data packets in PowerSave Queue -#define fTX_bWMM 0x0080 // QOS Data -#define fTX_bClearEAPFrame 0x0100 - - - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - - - - -#define TX_BLK_SET_FLAG(_pTxBlk, _flag) (_pTxBlk->Flags |= _flag) -#define TX_BLK_TEST_FLAG(_pTxBlk, _flag) (((_pTxBlk->Flags & _flag) == _flag) ? 1 : 0) -#define TX_BLK_CLEAR_FLAG(_pTxBlk, _flag) (_pTxBlk->Flags &= ~(_flag)) - - - - -#ifdef RT_BIG_ENDIAN -/*************************************************************************** - * Endian conversion related functions - **************************************************************************/ -/* - ======================================================================== - - Routine Description: - Endian conversion of Tx/Rx descriptor . - - Arguments: - pAd Pointer to our adapter - pData Pointer to Tx/Rx descriptor - DescriptorType Direction of the frame - - Return Value: - None - - Note: - Call this function when read or update descriptor - ======================================================================== -*/ -static inline VOID RTMPWIEndianChange( - IN PUCHAR pData, - IN ULONG DescriptorType) -{ - int size; - int i; - - size = ((DescriptorType == TYPE_TXWI) ? TXWI_SIZE : RXWI_SIZE); - - if(DescriptorType == TYPE_TXWI) - { - *((UINT32 *)(pData)) = SWAP32(*((UINT32 *)(pData))); // Byte 0~3 - *((UINT32 *)(pData + 4)) = SWAP32(*((UINT32 *)(pData+4))); // Byte 4~7 - } - else - { - for(i=0; i < size/4 ; i++) - *(((UINT32 *)pData) +i) = SWAP32(*(((UINT32 *)pData)+i)); - } -} - - -#ifdef RTMP_MAC_PCI -static inline VOID WriteBackToDescriptor( - IN PUCHAR Dest, - IN PUCHAR Src, - IN BOOLEAN DoEncrypt, - IN ULONG DescriptorType) -{ - UINT32 *p1, *p2; - - p1 = ((UINT32 *)Dest); - p2 = ((UINT32 *)Src); - - *p1 = *p2; - *(p1+2) = *(p2+2); - *(p1+3) = *(p2+3); - *(p1+1) = *(p2+1); // Word 1; this must be written back last -} -#endif // RTMP_MAC_PCI // - - -/* - ======================================================================== - - Routine Description: - Endian conversion of Tx/Rx descriptor . - - Arguments: - pAd Pointer to our adapter - pData Pointer to Tx/Rx descriptor - DescriptorType Direction of the frame - - Return Value: - None - - Note: - Call this function when read or update descriptor - ======================================================================== -*/ -#ifdef RTMP_MAC_PCI -static inline VOID RTMPDescriptorEndianChange( - IN PUCHAR pData, - IN ULONG DescriptorType) -{ - *((UINT32 *)(pData)) = SWAP32(*((UINT32 *)(pData))); // Byte 0~3 - *((UINT32 *)(pData + 8)) = SWAP32(*((UINT32 *)(pData+8))); // Byte 8~11 - *((UINT32 *)(pData +12)) = SWAP32(*((UINT32 *)(pData + 12))); // Byte 12~15 - *((UINT32 *)(pData + 4)) = SWAP32(*((UINT32 *)(pData + 4))); // Byte 4~7, this must be swapped last -} -#endif // RTMP_MAC_PCI // - -/* - ======================================================================== - - Routine Description: - Endian conversion of all kinds of 802.11 frames . - - Arguments: - pAd Pointer to our adapter - pData Pointer to the 802.11 frame structure - Dir Direction of the frame - FromRxDoneInt Caller is from RxDone interrupt - - Return Value: - None - - Note: - Call this function when read or update buffer data - ======================================================================== -*/ -static inline VOID RTMPFrameEndianChange( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG Dir, - IN BOOLEAN FromRxDoneInt) -{ - PHEADER_802_11 pFrame; - PUCHAR pMacHdr; - - // swab 16 bit fields - Frame Control field - if(Dir == DIR_READ) - { - *(USHORT *)pData = SWAP16(*(USHORT *)pData); - } - - pFrame = (PHEADER_802_11) pData; - pMacHdr = (PUCHAR) pFrame; - - // swab 16 bit fields - Duration/ID field - *(USHORT *)(pMacHdr + 2) = SWAP16(*(USHORT *)(pMacHdr + 2)); - - // swab 16 bit fields - Sequence Control field - *(USHORT *)(pMacHdr + 22) = SWAP16(*(USHORT *)(pMacHdr + 22)); - - if(pFrame->FC.Type == BTYPE_MGMT) - { - switch(pFrame->FC.SubType) - { - case SUBTYPE_ASSOC_REQ: - case SUBTYPE_REASSOC_REQ: - // swab 16 bit fields - CapabilityInfo field - pMacHdr += sizeof(HEADER_802_11); - *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); - - // swab 16 bit fields - Listen Interval field - pMacHdr += 2; - *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); - break; - - case SUBTYPE_ASSOC_RSP: - case SUBTYPE_REASSOC_RSP: - // swab 16 bit fields - CapabilityInfo field - pMacHdr += sizeof(HEADER_802_11); - *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); - - // swab 16 bit fields - Status Code field - pMacHdr += 2; - *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); - - // swab 16 bit fields - AID field - pMacHdr += 2; - *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); - break; - - case SUBTYPE_AUTH: - // If from APHandleRxDoneInterrupt routine, it is still a encrypt format. - // The convertion is delayed to RTMPHandleDecryptionDoneInterrupt. - if(!FromRxDoneInt && pFrame->FC.Wep == 1) - break; - else - { - // swab 16 bit fields - Auth Alg No. field - pMacHdr += sizeof(HEADER_802_11); - *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); - - // swab 16 bit fields - Auth Seq No. field - pMacHdr += 2; - *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); - - // swab 16 bit fields - Status Code field - pMacHdr += 2; - *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); - } - break; - - case SUBTYPE_BEACON: - case SUBTYPE_PROBE_RSP: - // swab 16 bit fields - BeaconInterval field - pMacHdr += (sizeof(HEADER_802_11) + TIMESTAMP_LEN); - *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); - - // swab 16 bit fields - CapabilityInfo field - pMacHdr += sizeof(USHORT); - *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); - break; - - case SUBTYPE_DEAUTH: - case SUBTYPE_DISASSOC: - // swab 16 bit fields - Reason code field - pMacHdr += sizeof(HEADER_802_11); - *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); - break; - } - } - else if( pFrame->FC.Type == BTYPE_DATA ) - { - } - else if(pFrame->FC.Type == BTYPE_CNTL) - { - switch(pFrame->FC.SubType) - { - case SUBTYPE_BLOCK_ACK_REQ: - { - PFRAME_BA_REQ pBAReq = (PFRAME_BA_REQ)pFrame; - *(USHORT *)(&pBAReq->BARControl) = SWAP16(*(USHORT *)(&pBAReq->BARControl)); - pBAReq->BAStartingSeq.word = SWAP16(pBAReq->BAStartingSeq.word); - } - break; - case SUBTYPE_BLOCK_ACK: - // For Block Ack packet, the HT_CONTROL field is in the same offset with Addr3 - *(UINT32 *)(&pFrame->Addr3[0]) = SWAP32(*(UINT32 *)(&pFrame->Addr3[0])); - break; - - case SUBTYPE_ACK: - //For ACK packet, the HT_CONTROL field is in the same offset with Addr2 - *(UINT32 *)(&pFrame->Addr2[0])= SWAP32(*(UINT32 *)(&pFrame->Addr2[0])); - break; - } - } - else - { - DBGPRINT(RT_DEBUG_ERROR,("Invalid Frame Type!!!\n")); - } - - // swab 16 bit fields - Frame Control - if(Dir == DIR_WRITE) - { - *(USHORT *)pData = SWAP16(*(USHORT *)pData); - } -} -#endif // RT_BIG_ENDIAN // - - -/*************************************************************************** - * Other static inline function definitions - **************************************************************************/ -static inline VOID ConvertMulticastIP2MAC( - IN PUCHAR pIpAddr, - IN PUCHAR *ppMacAddr, - IN UINT16 ProtoType) -{ - if (pIpAddr == NULL) - return; - - if (ppMacAddr == NULL || *ppMacAddr == NULL) - return; - - switch (ProtoType) - { - case ETH_P_IPV6: -// memset(*ppMacAddr, 0, ETH_LENGTH_OF_ADDRESS); - *(*ppMacAddr) = 0x33; - *(*ppMacAddr + 1) = 0x33; - *(*ppMacAddr + 2) = pIpAddr[12]; - *(*ppMacAddr + 3) = pIpAddr[13]; - *(*ppMacAddr + 4) = pIpAddr[14]; - *(*ppMacAddr + 5) = pIpAddr[15]; - break; - - case ETH_P_IP: - default: -// memset(*ppMacAddr, 0, ETH_LENGTH_OF_ADDRESS); - *(*ppMacAddr) = 0x01; - *(*ppMacAddr + 1) = 0x00; - *(*ppMacAddr + 2) = 0x5e; - *(*ppMacAddr + 3) = pIpAddr[1] & 0x7f; - *(*ppMacAddr + 4) = pIpAddr[2]; - *(*ppMacAddr + 5) = pIpAddr[3]; - break; - } - - return; -} - - -char *GetPhyMode(int Mode); -char* GetBW(int BW); - - - -BOOLEAN RTMPCheckForHang( - IN NDIS_HANDLE MiniportAdapterContext); - -VOID RTMPHalt( - IN NDIS_HANDLE MiniportAdapterContext); - -// -// Private routines in rtmp_init.c -// -NDIS_STATUS RTMPAllocAdapterBlock( - IN PVOID handle, - OUT PRTMP_ADAPTER *ppAdapter); - -NDIS_STATUS RTMPAllocTxRxRingMemory( - IN PRTMP_ADAPTER pAd); - -NDIS_STATUS RTMPFindAdapter( - IN PRTMP_ADAPTER pAd, - IN NDIS_HANDLE WrapperConfigurationContext); - -NDIS_STATUS RTMPReadParametersHook( - IN PRTMP_ADAPTER pAd); - -NDIS_STATUS RTMPSetProfileParameters( - IN RTMP_ADAPTER *pAd, - IN PSTRING pBuffer); - -INT RTMPGetKeyParameter( - IN PSTRING key, - OUT PSTRING dest, - IN INT destsize, - IN PSTRING buffer, - IN BOOLEAN bTrimSpace); - -VOID RTMPFreeAdapter( - IN PRTMP_ADAPTER pAd); - -NDIS_STATUS NICReadRegParameters( - IN PRTMP_ADAPTER pAd, - IN NDIS_HANDLE WrapperConfigurationContext); - -#ifdef RTMP_RF_RW_SUPPORT -VOID NICInitRFRegisters( - IN PRTMP_ADAPTER pAd); - -VOID RtmpChipOpsRFHook( - IN RTMP_ADAPTER *pAd); - -NDIS_STATUS RT30xxWriteRFRegister( - IN PRTMP_ADAPTER pAd, - IN UCHAR regID, - IN UCHAR value); - -NDIS_STATUS RT30xxReadRFRegister( - IN PRTMP_ADAPTER pAd, - IN UCHAR regID, - IN PUCHAR pValue); -#endif // RTMP_RF_RW_SUPPORT // - -VOID NICReadEEPROMParameters( - IN PRTMP_ADAPTER pAd, - IN PUCHAR mac_addr); - -VOID NICInitAsicFromEEPROM( - IN PRTMP_ADAPTER pAd); - - -NDIS_STATUS NICInitializeAdapter( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bHardReset); - -NDIS_STATUS NICInitializeAsic( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bHardReset); - -VOID NICIssueReset( - IN PRTMP_ADAPTER pAd); - -VOID RTMPRingCleanUp( - IN PRTMP_ADAPTER pAd, - IN UCHAR RingType); - -VOID RxTest( - IN PRTMP_ADAPTER pAd); - -NDIS_STATUS DbgSendPacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket); - -VOID UserCfgInit( - IN PRTMP_ADAPTER pAd); - -VOID NICResetFromError( - IN PRTMP_ADAPTER pAd); - -NDIS_STATUS NICLoadFirmware( - IN PRTMP_ADAPTER pAd); - -VOID NICEraseFirmware( - IN PRTMP_ADAPTER pAd); - -NDIS_STATUS NICLoadRateSwitchingParams( - IN PRTMP_ADAPTER pAd); - -BOOLEAN NICCheckForHang( - IN PRTMP_ADAPTER pAd); - -VOID NICUpdateFifoStaCounters( - IN PRTMP_ADAPTER pAd); - -VOID NICUpdateRawCounters( - IN PRTMP_ADAPTER pAd); - -VOID RTMPZeroMemory( - IN PVOID pSrc, - IN ULONG Length); - -ULONG RTMPCompareMemory( - IN PVOID pSrc1, - IN PVOID pSrc2, - IN ULONG Length); - -VOID RTMPMoveMemory( - OUT PVOID pDest, - IN PVOID pSrc, - IN ULONG Length); - -VOID AtoH( - PSTRING src, - PUCHAR dest, - int destlen); - -UCHAR BtoH( - char ch); - -VOID RTMPPatchMacBbpBug( - IN PRTMP_ADAPTER pAd); - -VOID RTMPPatchCardBus( - IN PRTMP_ADAPTER pAdapter); - -VOID RTMPPatchRalinkCardBus( - IN PRTMP_ADAPTER pAdapter, - IN ULONG Bus); - -ULONG RTMPReadCBConfig( - IN ULONG Bus, - IN ULONG Slot, - IN ULONG Func, - IN ULONG Offset); - -VOID RTMPWriteCBConfig( - IN ULONG Bus, - IN ULONG Slot, - IN ULONG Func, - IN ULONG Offset, - IN ULONG Value); - -VOID RTMPInitTimer( - IN PRTMP_ADAPTER pAd, - IN PRALINK_TIMER_STRUCT pTimer, - IN PVOID pTimerFunc, - IN PVOID pData, - IN BOOLEAN Repeat); - -VOID RTMPSetTimer( - IN PRALINK_TIMER_STRUCT pTimer, - IN ULONG Value); - - -VOID RTMPModTimer( - IN PRALINK_TIMER_STRUCT pTimer, - IN ULONG Value); - -VOID RTMPCancelTimer( - IN PRALINK_TIMER_STRUCT pTimer, - OUT BOOLEAN *pCancelled); - -VOID RTMPSetLED( - IN PRTMP_ADAPTER pAd, - IN UCHAR Status); - -VOID RTMPSetSignalLED( - IN PRTMP_ADAPTER pAd, - IN NDIS_802_11_RSSI Dbm); - - -VOID RTMPEnableRxTx( - IN PRTMP_ADAPTER pAd); - -// -// prototype in action.c -// -VOID ActionStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID MlmeADDBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeDELBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeDLSAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeInvalidAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeQOSAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -#ifdef DOT11_N_SUPPORT -VOID PeerAddBAReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerAddBARspAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerDelBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerBAAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); -#endif // DOT11_N_SUPPORT // - -VOID SendPSMPAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR Psmp); - - -VOID PeerRMAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerPublicAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -#ifdef CONFIG_STA_SUPPORT -VOID StaPublicAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Bss2040Coexist); -#endif // CONFIG_STA_SUPPORT // - - -VOID PeerBSSTranAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -#ifdef DOT11_N_SUPPORT -VOID PeerHTAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); -#endif // DOT11_N_SUPPORT // - -VOID PeerQOSAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -#ifdef QOS_DLS_SUPPORT -VOID PeerDLSAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); -#endif // QOS_DLS_SUPPORT // - -#ifdef CONFIG_STA_SUPPORT -#ifdef QOS_DLS_SUPPORT -VOID DlsParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_DLS_REQ_STRUCT *pDlsReq, - IN PRT_802_11_DLS pDls, - IN USHORT reason); -#endif // QOS_DLS_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - -#ifdef DOT11_N_SUPPORT -VOID RECBATimerTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID ORIBATimerTimeout( - IN PRTMP_ADAPTER pAd); - -VOID SendRefreshBAR( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry); - -#ifdef DOT11N_DRAFT3 -VOID SendBSS2040CoexistMgmtAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR apidx, - IN UCHAR InfoReq); - -VOID SendNotifyBWActionFrame( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR apidx); - -BOOLEAN ChannelSwitchSanityCheck( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR NewChannel, - IN UCHAR Secondary); - -VOID ChannelSwitchAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR Channel, - IN UCHAR Secondary); - -ULONG BuildIntolerantChannelRep( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDest); - -VOID Update2040CoexistFrameAndNotify( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN BOOLEAN bAddIntolerantCha); - -VOID Send2040CoexistAction( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN BOOLEAN bAddIntolerantCha); -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // - -VOID ActHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PHEADER_802_11 pHdr80211, - IN PUCHAR Addr1, - IN PUCHAR Addr2, - IN PUCHAR Addr3); - -VOID BarHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PFRAME_BAR pCntlBar, - IN PUCHAR pDA, - IN PUCHAR pSA); - -VOID InsertActField( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN UINT8 Category, - IN UINT8 ActCode); - -BOOLEAN QosBADataParse( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bAMSDU, - IN PUCHAR p8023Header, - IN UCHAR WCID, - IN UCHAR TID, - IN USHORT Sequence, - IN UCHAR DataOffset, - IN USHORT Datasize, - IN UINT CurRxIndex); - -#ifdef DOT11_N_SUPPORT -BOOLEAN CntlEnqueueForRecv( - IN PRTMP_ADAPTER pAd, - IN ULONG Wcid, - IN ULONG MsgLen, - IN PFRAME_BA_REQ pMsg); - -VOID BaAutoManSwitch( - IN PRTMP_ADAPTER pAd); -#endif // DOT11_N_SUPPORT // - -VOID HTIOTCheck( - IN PRTMP_ADAPTER pAd, - IN UCHAR BatRecIdx); - -// -// Private routines in rtmp_data.c -// -BOOLEAN RTMPHandleRxDoneInterrupt( - IN PRTMP_ADAPTER pAd); - -VOID RTMPHandleTxDoneInterrupt( - IN PRTMP_ADAPTER pAd); - -BOOLEAN RTMPHandleTxRingDmaDoneInterrupt( - IN PRTMP_ADAPTER pAd, - IN INT_SOURCE_CSR_STRUC TxRingBitmap); - -VOID RTMPHandleMgmtRingDmaDoneInterrupt( - IN PRTMP_ADAPTER pAd); - -VOID RTMPHandleTBTTInterrupt( - IN PRTMP_ADAPTER pAd); - -VOID RTMPHandlePreTBTTInterrupt( - IN PRTMP_ADAPTER pAd); - -void RTMPHandleTwakeupInterrupt( - IN PRTMP_ADAPTER pAd); - -VOID RTMPHandleRxCoherentInterrupt( - IN PRTMP_ADAPTER pAd); - - -BOOLEAN TxFrameIsAggregatible( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pPrevAddr1, - IN PUCHAR p8023hdr); - -BOOLEAN PeerIsAggreOn( - IN PRTMP_ADAPTER pAd, - IN ULONG TxRate, - IN PMAC_TABLE_ENTRY pMacEntry); - - -NDIS_STATUS Sniff2BytesFromNdisBuffer( - IN PNDIS_BUFFER pFirstBuffer, - IN UCHAR DesiredOffset, - OUT PUCHAR pByte0, - OUT PUCHAR pByte1); - -NDIS_STATUS STASendPacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket); - -VOID STASendPackets( - IN NDIS_HANDLE MiniportAdapterContext, - IN PPNDIS_PACKET ppPacketArray, - IN UINT NumberOfPackets); - -VOID RTMPDeQueuePacket( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bIntContext, - IN UCHAR QueIdx, - IN UCHAR Max_Tx_Packets); - -NDIS_STATUS RTMPHardTransmit( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR QueIdx, - OUT PULONG pFreeTXDLeft); - -NDIS_STATUS STAHardTransmit( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR QueIdx); - -VOID STARxEAPOLFrameIndicate( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); - -NDIS_STATUS RTMPFreeTXDRequest( - IN PRTMP_ADAPTER pAd, - IN UCHAR RingType, - IN UCHAR NumberRequired, - IN PUCHAR FreeNumberIs); - -NDIS_STATUS MlmeHardTransmit( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket); - -NDIS_STATUS MlmeHardTransmitMgmtRing( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket); - -#ifdef RTMP_MAC_PCI -NDIS_STATUS MlmeHardTransmitTxRing( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket); - -NDIS_STATUS MlmeDataHardTransmit( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket); - -VOID RTMPWriteTxDescriptor( - IN PRTMP_ADAPTER pAd, - IN PTXD_STRUC pTxD, - IN BOOLEAN bWIV, - IN UCHAR QSEL); -#endif // RTMP_MAC_PCI // - -USHORT RTMPCalcDuration( - IN PRTMP_ADAPTER pAd, - IN UCHAR Rate, - IN ULONG Size); - -VOID RTMPWriteTxWI( - IN PRTMP_ADAPTER pAd, - IN PTXWI_STRUC pTxWI, - IN BOOLEAN FRAG, - IN BOOLEAN CFACK, - IN BOOLEAN InsTimestamp, - IN BOOLEAN AMPDU, - IN BOOLEAN Ack, - IN BOOLEAN NSeq, // HW new a sequence. - IN UCHAR BASize, - IN UCHAR WCID, - IN ULONG Length, - IN UCHAR PID, - IN UCHAR TID, - IN UCHAR TxRate, - IN UCHAR Txopmode, - IN BOOLEAN CfAck, - IN HTTRANSMIT_SETTING *pTransmit); - - -VOID RTMPWriteTxWI_Data( - IN PRTMP_ADAPTER pAd, - IN OUT PTXWI_STRUC pTxWI, - IN TX_BLK *pTxBlk); - - -VOID RTMPWriteTxWI_Cache( - IN PRTMP_ADAPTER pAd, - IN OUT PTXWI_STRUC pTxWI, - IN TX_BLK *pTxBlk); - -VOID RTMPSuspendMsduTransmission( - IN PRTMP_ADAPTER pAd); - -VOID RTMPResumeMsduTransmission( - IN PRTMP_ADAPTER pAd); - -NDIS_STATUS MiniportMMRequest( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN PUCHAR pData, - IN UINT Length); - -//+++mark by shiang, now this function merge to MiniportMMRequest() -//---mark by shiang, now this function merge to MiniportMMRequest() - -VOID RTMPSendNullFrame( - IN PRTMP_ADAPTER pAd, - IN UCHAR TxRate, - IN BOOLEAN bQosNull); - -VOID RTMPSendDisassociationFrame( - IN PRTMP_ADAPTER pAd); - -VOID RTMPSendRTSFrame( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN unsigned int NextMpduSize, - IN UCHAR TxRate, - IN UCHAR RTSRate, - IN USHORT AckDuration, - IN UCHAR QueIdx, - IN UCHAR FrameGap); - - -NDIS_STATUS RTMPApplyPacketFilter( - IN PRTMP_ADAPTER pAd, - IN PRT28XX_RXD_STRUC pRxD, - IN PHEADER_802_11 pHeader); - -PQUEUE_HEADER RTMPCheckTxSwQueue( - IN PRTMP_ADAPTER pAd, - OUT UCHAR *QueIdx); - -#ifdef CONFIG_STA_SUPPORT -VOID RTMPReportMicError( - IN PRTMP_ADAPTER pAd, - IN PCIPHER_KEY pWpaKey); - -VOID WpaMicFailureReportFrame( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID WpaDisassocApAndBlockAssoc( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID WpaStaPairwiseKeySetting( - IN PRTMP_ADAPTER pAd); - -VOID WpaStaGroupKeySetting( - IN PRTMP_ADAPTER pAd); - -#endif // CONFIG_STA_SUPPORT // - -NDIS_STATUS RTMPCloneNdisPacket( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN pInsAMSDUHdr, - IN PNDIS_PACKET pInPacket, - OUT PNDIS_PACKET *ppOutPacket); - -NDIS_STATUS RTMPAllocateNdisPacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET *pPacket, - IN PUCHAR pHeader, - IN UINT HeaderLen, - IN PUCHAR pData, - IN UINT DataLen); - -VOID RTMPFreeNdisPacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket); - -BOOLEAN RTMPFreeTXDUponTxDmaDone( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx); - -BOOLEAN RTMPCheckDHCPFrame( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket); - - -BOOLEAN RTMPCheckEtherType( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket); - - -VOID RTMPCckBbpTuning( - IN PRTMP_ADAPTER pAd, - IN UINT TxRate); - -// -// Private routines in rtmp_wep.c -// -VOID RTMPInitWepEngine( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKey, - IN UCHAR KeyId, - IN UCHAR KeyLen, - IN PUCHAR pDest); - -VOID RTMPEncryptData( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pSrc, - IN PUCHAR pDest, - IN UINT Len); - -BOOLEAN RTMPDecryptData( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR pSrc, - IN UINT Len, - IN UINT idx); - -BOOLEAN RTMPSoftDecryptWEP( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG DataByteCnt, - IN PCIPHER_KEY pGroupKey); - -VOID RTMPSetICV( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDest); - -VOID ARCFOUR_INIT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pKey, - IN UINT KeyLen); - -UCHAR ARCFOUR_BYTE( - IN PARCFOURCONTEXT Ctx); - -VOID ARCFOUR_DECRYPT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pDest, - IN PUCHAR pSrc, - IN UINT Len); - -VOID ARCFOUR_ENCRYPT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pDest, - IN PUCHAR pSrc, - IN UINT Len); - -VOID WPAARCFOUR_ENCRYPT( - IN PARCFOURCONTEXT Ctx, - IN PUCHAR pDest, - IN PUCHAR pSrc, - IN UINT Len); - -UINT RTMP_CALC_FCS32( - IN UINT Fcs, - IN PUCHAR Cp, - IN INT Len); - -// -// MLME routines -// - -// Asic/RF/BBP related functions - -VOID AsicAdjustTxPower( - IN PRTMP_ADAPTER pAd); - -VOID AsicUpdateProtect( - IN PRTMP_ADAPTER pAd, - IN USHORT OperaionMode, - IN UCHAR SetMask, - IN BOOLEAN bDisableBGProtect, - IN BOOLEAN bNonGFExist); - -VOID AsicSwitchChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel, - IN BOOLEAN bScan); - -VOID AsicLockChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel) ; - -VOID AsicAntennaSelect( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel); - -VOID AsicAntennaSetting( - IN PRTMP_ADAPTER pAd, - IN ABGBAND_STATE BandState); - -VOID AsicRfTuningExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -#ifdef CONFIG_STA_SUPPORT - -VOID AsicResetBBPAgent( - IN PRTMP_ADAPTER pAd); - -VOID AsicSleepThenAutoWakeup( - IN PRTMP_ADAPTER pAd, - IN USHORT TbttNumToNextWakeUp); - -VOID AsicForceSleep( - IN PRTMP_ADAPTER pAd); - -VOID AsicForceWakeup( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bFromTx); -#endif // CONFIG_STA_SUPPORT // - -VOID AsicSetBssid( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pBssid); - -VOID AsicSetMcastWC( - IN PRTMP_ADAPTER pAd); - - -VOID AsicDelWcidTab( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid); - -VOID AsicEnableRDG( - IN PRTMP_ADAPTER pAd); - -VOID AsicDisableRDG( - IN PRTMP_ADAPTER pAd); - -VOID AsicDisableSync( - IN PRTMP_ADAPTER pAd); - -VOID AsicEnableBssSync( - IN PRTMP_ADAPTER pAd); - -VOID AsicEnableIbssSync( - IN PRTMP_ADAPTER pAd); - -VOID AsicSetEdcaParm( - IN PRTMP_ADAPTER pAd, - IN PEDCA_PARM pEdcaParm); - -VOID AsicSetSlotTime( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bUseShortSlotTime); - - -VOID AsicAddSharedKeyEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIndex, - IN UCHAR KeyIdx, - IN UCHAR CipherAlg, - IN PUCHAR pKey, - IN PUCHAR pTxMic, - IN PUCHAR pRxMic); - -VOID AsicRemoveSharedKeyEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIndex, - IN UCHAR KeyIdx); - -VOID AsicUpdateWCIDAttribute( - IN PRTMP_ADAPTER pAd, - IN USHORT WCID, - IN UCHAR BssIndex, - IN UCHAR CipherAlg, - IN BOOLEAN bUsePairewiseKeyTable); - -VOID AsicUpdateWCIDIVEIV( - IN PRTMP_ADAPTER pAd, - IN USHORT WCID, - IN ULONG uIV, - IN ULONG uEIV); - -VOID AsicUpdateRxWCIDTable( - IN PRTMP_ADAPTER pAd, - IN USHORT WCID, - IN PUCHAR pAddr); - -VOID AsicAddKeyEntry( - IN PRTMP_ADAPTER pAd, - IN USHORT WCID, - IN UCHAR BssIndex, - IN UCHAR KeyIdx, - IN PCIPHER_KEY pCipherKey, - IN BOOLEAN bUsePairewiseKeyTable, - IN BOOLEAN bTxKey); - -VOID AsicAddPairwiseKeyEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN UCHAR WCID, - IN CIPHER_KEY *pCipherKey); - -VOID AsicRemovePairwiseKeyEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIdx, - IN UCHAR Wcid); - -BOOLEAN AsicSendCommandToMcu( - IN PRTMP_ADAPTER pAd, - IN UCHAR Command, - IN UCHAR Token, - IN UCHAR Arg0, - IN UCHAR Arg1); - - -#ifdef RTMP_MAC_PCI -BOOLEAN AsicCheckCommanOk( - IN PRTMP_ADAPTER pAd, - IN UCHAR Command); -#endif // RTMP_MAC_PCI // - -VOID MacAddrRandomBssid( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pAddr); - -VOID MgtMacHeaderInit( - IN PRTMP_ADAPTER pAd, - IN OUT PHEADER_802_11 pHdr80211, - IN UCHAR SubType, - IN UCHAR ToDs, - IN PUCHAR pDA, - IN PUCHAR pBssid); - -VOID MlmeRadioOff( - IN PRTMP_ADAPTER pAd); - -VOID MlmeRadioOn( - IN PRTMP_ADAPTER pAd); - - -VOID BssTableInit( - IN BSS_TABLE *Tab); - -#ifdef DOT11_N_SUPPORT -VOID BATableInit( - IN PRTMP_ADAPTER pAd, - IN BA_TABLE *Tab); -#endif // DOT11_N_SUPPORT // - -ULONG BssTableSearch( - IN BSS_TABLE *Tab, - IN PUCHAR pBssid, - IN UCHAR Channel); - -ULONG BssSsidTableSearch( - IN BSS_TABLE *Tab, - IN PUCHAR pBssid, - IN PUCHAR pSsid, - IN UCHAR SsidLen, - IN UCHAR Channel); - -ULONG BssTableSearchWithSSID( - IN BSS_TABLE *Tab, - IN PUCHAR Bssid, - IN PUCHAR pSsid, - IN UCHAR SsidLen, - IN UCHAR Channel); - -ULONG BssSsidTableSearchBySSID( - IN BSS_TABLE *Tab, - IN PUCHAR pSsid, - IN UCHAR SsidLen); - -VOID BssTableDeleteEntry( - IN OUT PBSS_TABLE pTab, - IN PUCHAR pBssid, - IN UCHAR Channel); - -#ifdef DOT11_N_SUPPORT -VOID BATableDeleteORIEntry( - IN OUT PRTMP_ADAPTER pAd, - IN BA_ORI_ENTRY *pBAORIEntry); - -VOID BATableDeleteRECEntry( - IN OUT PRTMP_ADAPTER pAd, - IN BA_REC_ENTRY *pBARECEntry); - -VOID BATableTearORIEntry( - IN OUT PRTMP_ADAPTER pAd, - IN UCHAR TID, - IN UCHAR Wcid, - IN BOOLEAN bForceDelete, - IN BOOLEAN ALL); - -VOID BATableTearRECEntry( - IN OUT PRTMP_ADAPTER pAd, - IN UCHAR TID, - IN UCHAR WCID, - IN BOOLEAN ALL); -#endif // DOT11_N_SUPPORT // - -VOID BssEntrySet( - IN PRTMP_ADAPTER pAd, - OUT PBSS_ENTRY pBss, - IN PUCHAR pBssid, - IN CHAR Ssid[], - IN UCHAR SsidLen, - IN UCHAR BssType, - IN USHORT BeaconPeriod, - IN PCF_PARM CfParm, - IN USHORT AtimWin, - IN USHORT CapabilityInfo, - IN UCHAR SupRate[], - IN UCHAR SupRateLen, - IN UCHAR ExtRate[], - IN UCHAR ExtRateLen, - IN HT_CAPABILITY_IE *pHtCapability, - IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE - IN UCHAR HtCapabilityLen, - IN UCHAR AddHtInfoLen, - IN UCHAR NewExtChanOffset, - IN UCHAR Channel, - IN CHAR Rssi, - IN LARGE_INTEGER TimeStamp, - IN UCHAR CkipFlag, - IN PEDCA_PARM pEdcaParm, - IN PQOS_CAPABILITY_PARM pQosCapability, - IN PQBSS_LOAD_PARM pQbssLoad, - IN USHORT LengthVIE, - IN PNDIS_802_11_VARIABLE_IEs pVIE); - -ULONG BssTableSetEntry( - IN PRTMP_ADAPTER pAd, - OUT PBSS_TABLE pTab, - IN PUCHAR pBssid, - IN CHAR Ssid[], - IN UCHAR SsidLen, - IN UCHAR BssType, - IN USHORT BeaconPeriod, - IN CF_PARM *CfParm, - IN USHORT AtimWin, - IN USHORT CapabilityInfo, - IN UCHAR SupRate[], - IN UCHAR SupRateLen, - IN UCHAR ExtRate[], - IN UCHAR ExtRateLen, - IN HT_CAPABILITY_IE *pHtCapability, - IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE - IN UCHAR HtCapabilityLen, - IN UCHAR AddHtInfoLen, - IN UCHAR NewExtChanOffset, - IN UCHAR Channel, - IN CHAR Rssi, - IN LARGE_INTEGER TimeStamp, - IN UCHAR CkipFlag, - IN PEDCA_PARM pEdcaParm, - IN PQOS_CAPABILITY_PARM pQosCapability, - IN PQBSS_LOAD_PARM pQbssLoad, - IN USHORT LengthVIE, - IN PNDIS_802_11_VARIABLE_IEs pVIE); - -#ifdef DOT11_N_SUPPORT -VOID BATableInsertEntry( - IN PRTMP_ADAPTER pAd, - IN USHORT Aid, - IN USHORT TimeOutValue, - IN USHORT StartingSeq, - IN UCHAR TID, - IN UCHAR BAWinSize, - IN UCHAR OriginatorStatus, - IN BOOLEAN IsRecipient); - -#ifdef DOT11N_DRAFT3 -VOID Bss2040CoexistTimeOut( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - - -VOID TriEventInit( - IN PRTMP_ADAPTER pAd); - -ULONG TriEventTableSetEntry( - IN PRTMP_ADAPTER pAd, - OUT TRIGGER_EVENT_TAB *Tab, - IN PUCHAR pBssid, - IN HT_CAPABILITY_IE *pHtCapability, - IN UCHAR HtCapabilityLen, - IN UCHAR RegClass, - IN UCHAR ChannelNo); - -VOID TriEventCounterMaintenance( - IN PRTMP_ADAPTER pAd); -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // - -VOID BssTableSsidSort( - IN PRTMP_ADAPTER pAd, - OUT BSS_TABLE *OutTab, - IN CHAR Ssid[], - IN UCHAR SsidLen); - -VOID BssTableSortByRssi( - IN OUT BSS_TABLE *OutTab); - -VOID BssCipherParse( - IN OUT PBSS_ENTRY pBss); - -NDIS_STATUS MlmeQueueInit( - IN MLME_QUEUE *Queue); - -VOID MlmeQueueDestroy( - IN MLME_QUEUE *Queue); - -BOOLEAN MlmeEnqueue( - IN PRTMP_ADAPTER pAd, - IN ULONG Machine, - IN ULONG MsgType, - IN ULONG MsgLen, - IN VOID *Msg); - -BOOLEAN MlmeEnqueueForRecv( - IN PRTMP_ADAPTER pAd, - IN ULONG Wcid, - IN ULONG TimeStampHigh, - IN ULONG TimeStampLow, - IN UCHAR Rssi0, - IN UCHAR Rssi1, - IN UCHAR Rssi2, - IN ULONG MsgLen, - IN PVOID Msg, - IN UCHAR Signal); - - -BOOLEAN MlmeDequeue( - IN MLME_QUEUE *Queue, - OUT MLME_QUEUE_ELEM **Elem); - -VOID MlmeRestartStateMachine( - IN PRTMP_ADAPTER pAd); - -BOOLEAN MlmeQueueEmpty( - IN MLME_QUEUE *Queue); - -BOOLEAN MlmeQueueFull( - IN MLME_QUEUE *Queue); - -BOOLEAN MsgTypeSubst( - IN PRTMP_ADAPTER pAd, - IN PFRAME_802_11 pFrame, - OUT INT *Machine, - OUT INT *MsgType); - -VOID StateMachineInit( - IN STATE_MACHINE *Sm, - IN STATE_MACHINE_FUNC Trans[], - IN ULONG StNr, - IN ULONG MsgNr, - IN STATE_MACHINE_FUNC DefFunc, - IN ULONG InitState, - IN ULONG Base); - -VOID StateMachineSetAction( - IN STATE_MACHINE *S, - IN ULONG St, - ULONG Msg, - IN STATE_MACHINE_FUNC F); - -VOID StateMachinePerformAction( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - IN MLME_QUEUE_ELEM *Elem); - -VOID Drop( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID AssocStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *Sm, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID ReassocTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID AssocTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID DisassocTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -//---------------------------------------------- -VOID MlmeDisassocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeAssocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeReassocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeDisassocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerAssocRspAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerReassocRspAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerDisassocAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID DisassocTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID AssocTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID ReassocTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID Cls3errAction( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr); - -VOID InvalidStateWhenAssoc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID InvalidStateWhenReassoc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID InvalidStateWhenDisassociate( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - - -VOID ComposePsPoll( - IN PRTMP_ADAPTER pAd); - -VOID ComposeNullFrame( - IN PRTMP_ADAPTER pAd); - -VOID AssocPostProc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr2, - IN USHORT CapabilityInfo, - IN USHORT Aid, - IN UCHAR SupRate[], - IN UCHAR SupRateLen, - IN UCHAR ExtRate[], - IN UCHAR ExtRateLen, - IN PEDCA_PARM pEdcaParm, - IN HT_CAPABILITY_IE *pHtCapability, - IN UCHAR HtCapabilityLen, - IN ADD_HT_INFO_IE *pAddHtInfo); - -VOID AuthStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN PSTATE_MACHINE sm, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID AuthTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID MlmeAuthReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerAuthRspAtSeq2Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerAuthRspAtSeq4Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID AuthTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID Cls2errAction( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr); - -VOID MlmeDeauthReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID InvalidStateWhenAuth( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -//============================================= - -VOID AuthRspStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN PSTATE_MACHINE Sm, - IN STATE_MACHINE_FUNC Trans[]); - -VOID PeerDeauthAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerAuthSimpleRspGenAndSend( - IN PRTMP_ADAPTER pAd, - IN PHEADER_802_11 pHdr80211, - IN USHORT Alg, - IN USHORT Seq, - IN USHORT Reason, - IN USHORT Status); - -// -// Private routines in dls.c -// - -#ifdef CONFIG_STA_SUPPORT -#ifdef QOS_DLS_SUPPORT -void DlsStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *Sm, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID MlmeDlsReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerDlsReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerDlsRspAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeDlsTearDownAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerDlsTearDownAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID RTMPCheckDLSTimeOut( - IN PRTMP_ADAPTER pAd); - -BOOLEAN RTMPRcvFrameDLSCheck( - IN PRTMP_ADAPTER pAd, - IN PHEADER_802_11 pHeader, - IN ULONG Len, - IN PRT28XX_RXD_STRUC pRxD); - -INT RTMPCheckDLSFrame( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA); - -VOID RTMPSendDLSTearDownFrame( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA); - -NDIS_STATUS RTMPSendSTAKeyRequest( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA); - -NDIS_STATUS RTMPSendSTAKeyHandShake( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA); - -VOID DlsTimeoutAction( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -BOOLEAN MlmeDlsReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PRT_802_11_DLS *pDLS, - OUT PUSHORT pReason); - -INT Set_DlsEntryInfo_Display_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -MAC_TABLE_ENTRY *MacTableInsertDlsEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN UINT DlsEntryIdx); - -BOOLEAN MacTableDeleteDlsEntry( - IN PRTMP_ADAPTER pAd, - IN USHORT wcid, - IN PUCHAR pAddr); - -MAC_TABLE_ENTRY *DlsEntryTableLookup( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN BOOLEAN bResetIdelCount); - -MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid( - IN PRTMP_ADAPTER pAd, - IN UCHAR wcid, - IN PUCHAR pAddr, - IN BOOLEAN bResetIdelCount); - -INT Set_DlsAddEntry_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_DlsTearDownEntry_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); -#endif // QOS_DLS_SUPPORT // -#endif // CONFIG_STA_SUPPORT // - -#ifdef QOS_DLS_SUPPORT -BOOLEAN PeerDlsReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pDA, - OUT PUCHAR pSA, - OUT USHORT *pCapabilityInfo, - OUT USHORT *pDlsTimeout, - OUT UCHAR *pRatesLen, - OUT UCHAR Rates[], - OUT UCHAR *pHtCapabilityLen, - OUT HT_CAPABILITY_IE *pHtCapability); - -BOOLEAN PeerDlsRspSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pDA, - OUT PUCHAR pSA, - OUT USHORT *pCapabilityInfo, - OUT USHORT *pStatus, - OUT UCHAR *pRatesLen, - OUT UCHAR Rates[], - OUT UCHAR *pHtCapabilityLen, - OUT HT_CAPABILITY_IE *pHtCapability); - -BOOLEAN PeerDlsTearDownSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pDA, - OUT PUCHAR pSA, - OUT USHORT *pReason); -#endif // QOS_DLS_SUPPORT // - -//======================================== - -VOID SyncStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *Sm, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID BeaconTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID ScanTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID MlmeScanReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID InvalidStateWhenScan( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID InvalidStateWhenJoin( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID InvalidStateWhenStart( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerBeacon( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID EnqueueProbeRequest( - IN PRTMP_ADAPTER pAd); - -BOOLEAN ScanRunning( - IN PRTMP_ADAPTER pAd); -//========================================= - -VOID MlmeCntlInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]); - -VOID MlmeCntlMachinePerformAction( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlIdleProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlOidScanProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlOidSsidProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM * Elem); - -VOID CntlOidRTBssidProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM * Elem); - -VOID CntlMlmeRoamingProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM * Elem); - -VOID CntlWaitDisassocProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlWaitJoinProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlWaitReassocProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlWaitStartProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlWaitAuthProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlWaitAuthProc2( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID CntlWaitAssocProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -#ifdef QOS_DLS_SUPPORT -VOID CntlOidDLSSetupProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); -#endif // QOS_DLS_SUPPORT // - -VOID LinkUp( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssType); - -VOID LinkDown( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN IsReqFromAP); - -VOID IterateOnBssTab( - IN PRTMP_ADAPTER pAd); - -VOID IterateOnBssTab2( - IN PRTMP_ADAPTER pAd);; - -VOID JoinParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_JOIN_REQ_STRUCT *JoinReq, - IN ULONG BssIdx); - -VOID AssocParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq, - IN PUCHAR pAddr, - IN USHORT CapabilityInfo, - IN ULONG Timeout, - IN USHORT ListenIntv); - -VOID ScanParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_SCAN_REQ_STRUCT *ScanReq, - IN STRING Ssid[], - IN UCHAR SsidLen, - IN UCHAR BssType, - IN UCHAR ScanType); - -VOID DisassocParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq, - IN PUCHAR pAddr, - IN USHORT Reason); - -VOID StartParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_START_REQ_STRUCT *StartReq, - IN CHAR Ssid[], - IN UCHAR SsidLen); - -VOID AuthParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_AUTH_REQ_STRUCT *AuthReq, - IN PUCHAR pAddr, - IN USHORT Alg); - -VOID EnqueuePsPoll( - IN PRTMP_ADAPTER pAd); - -VOID EnqueueBeaconFrame( - IN PRTMP_ADAPTER pAd); - -VOID MlmeJoinReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeScanReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID MlmeStartReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID ScanTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID BeaconTimeoutAtJoinAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerBeaconAtScanAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerBeaconAtJoinAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerBeacon( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerProbeReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -VOID ScanNextChannel( - IN PRTMP_ADAPTER pAd); - -ULONG MakeIbssBeacon( - IN PRTMP_ADAPTER pAd); - -VOID CCXAdjacentAPReport( - IN PRTMP_ADAPTER pAd); - -BOOLEAN MlmeScanReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT UCHAR *BssType, - OUT CHAR ssid[], - OUT UCHAR *SsidLen, - OUT UCHAR *ScanType); - -BOOLEAN PeerBeaconAndProbeRspSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - IN UCHAR MsgChannel, - OUT PUCHAR pAddr2, - OUT PUCHAR pBssid, - OUT CHAR Ssid[], - OUT UCHAR *pSsidLen, - OUT UCHAR *pBssType, - OUT USHORT *pBeaconPeriod, - OUT UCHAR *pChannel, - OUT UCHAR *pNewChannel, - OUT LARGE_INTEGER *pTimestamp, - OUT CF_PARM *pCfParm, - OUT USHORT *pAtimWin, - OUT USHORT *pCapabilityInfo, - OUT UCHAR *pErp, - OUT UCHAR *pDtimCount, - OUT UCHAR *pDtimPeriod, - OUT UCHAR *pBcastFlag, - OUT UCHAR *pMessageToMe, - OUT UCHAR SupRate[], - OUT UCHAR *pSupRateLen, - OUT UCHAR ExtRate[], - OUT UCHAR *pExtRateLen, - OUT UCHAR *pCkipFlag, - OUT UCHAR *pAironetCellPowerLimit, - OUT PEDCA_PARM pEdcaParm, - OUT PQBSS_LOAD_PARM pQbssLoad, - OUT PQOS_CAPABILITY_PARM pQosCapability, - OUT ULONG *pRalinkIe, - OUT UCHAR *pHtCapabilityLen, -#ifdef CONFIG_STA_SUPPORT - OUT UCHAR *pPreNHtCapabilityLen, -#endif // CONFIG_STA_SUPPORT // - OUT HT_CAPABILITY_IE *pHtCapability, - OUT UCHAR *AddHtInfoLen, - OUT ADD_HT_INFO_IE *AddHtInfo, - OUT UCHAR *NewExtChannel, - OUT USHORT *LengthVIE, - OUT PNDIS_802_11_VARIABLE_IEs pVIE); - -BOOLEAN PeerAddBAReqActionSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2); - -BOOLEAN PeerAddBARspActionSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen); - -BOOLEAN PeerDelBAActionSanity( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN VOID *pMsg, - IN ULONG MsgLen); - -BOOLEAN MlmeAssocReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pApAddr, - OUT USHORT *CapabilityInfo, - OUT ULONG *Timeout, - OUT USHORT *ListenIntv); - -BOOLEAN MlmeAuthReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr, - OUT ULONG *Timeout, - OUT USHORT *Alg); - -BOOLEAN MlmeStartReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT CHAR Ssid[], - OUT UCHAR *Ssidlen); - -BOOLEAN PeerAuthSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr, - OUT USHORT *Alg, - OUT USHORT *Seq, - OUT USHORT *Status, - OUT CHAR ChlgText[]); - -BOOLEAN PeerAssocRspSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *pCapabilityInfo, - OUT USHORT *pStatus, - OUT USHORT *pAid, - OUT UCHAR SupRate[], - OUT UCHAR *pSupRateLen, - OUT UCHAR ExtRate[], - OUT UCHAR *pExtRateLen, - OUT HT_CAPABILITY_IE *pHtCapability, - OUT ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE - OUT UCHAR *pHtCapabilityLen, - OUT UCHAR *pAddHtInfoLen, - OUT UCHAR *pNewExtChannelOffset, - OUT PEDCA_PARM pEdcaParm, - OUT UCHAR *pCkipFlag); - -BOOLEAN PeerDisassocSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *Reason); - -BOOLEAN PeerWpaMessageSanity( - IN PRTMP_ADAPTER pAd, - IN PEAPOL_PACKET pMsg, - IN ULONG MsgLen, - IN UCHAR MsgType, - IN MAC_TABLE_ENTRY *pEntry); - -BOOLEAN PeerDeauthSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *Reason); - -BOOLEAN PeerProbeReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT CHAR Ssid[], - OUT UCHAR *pSsidLen); - -BOOLEAN GetTimBit( - IN CHAR *Ptr, - IN USHORT Aid, - OUT UCHAR *TimLen, - OUT UCHAR *BcastFlag, - OUT UCHAR *DtimCount, - OUT UCHAR *DtimPeriod, - OUT UCHAR *MessageToMe); - -UCHAR ChannelSanity( - IN PRTMP_ADAPTER pAd, - IN UCHAR channel); - -NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity( - IN PBSS_ENTRY pBss); - - -BOOLEAN MlmeDelBAReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen); - -BOOLEAN MlmeAddBAReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2); - -ULONG MakeOutgoingFrame( - OUT UCHAR *Buffer, - OUT ULONG *Length, ...); - -VOID LfsrInit( - IN PRTMP_ADAPTER pAd, - IN ULONG Seed); - -UCHAR RandomByte( - IN PRTMP_ADAPTER pAd); - -VOID AsicUpdateAutoFallBackTable( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pTxRate); - -VOID MlmePeriodicExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID LinkDownExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID LinkUpExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID STAMlmePeriodicExec( - PRTMP_ADAPTER pAd); - -VOID MlmeAutoScan( - IN PRTMP_ADAPTER pAd); - -VOID MlmeAutoReconnectLastSSID( - IN PRTMP_ADAPTER pAd); - -BOOLEAN MlmeValidateSSID( - IN PUCHAR pSsid, - IN UCHAR SsidLen); - -VOID MlmeCheckForRoaming( - IN PRTMP_ADAPTER pAd, - IN ULONG Now32); - -BOOLEAN MlmeCheckForFastRoaming( - IN PRTMP_ADAPTER pAd); - -VOID MlmeDynamicTxRateSwitching( - IN PRTMP_ADAPTER pAd); - -VOID MlmeSetTxRate( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PRTMP_TX_RATE_SWITCH pTxRate); - -VOID MlmeSelectTxRateTable( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PUCHAR *ppTable, - IN PUCHAR pTableSize, - IN PUCHAR pInitTxRateIdx); - -VOID MlmeCalculateChannelQuality( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pMacEntry, - IN ULONG Now); - -VOID MlmeCheckPsmChange( - IN PRTMP_ADAPTER pAd, - IN ULONG Now32); - -VOID MlmeSetPsmBit( - IN PRTMP_ADAPTER pAd, - IN USHORT psm); - -VOID MlmeSetTxPreamble( - IN PRTMP_ADAPTER pAd, - IN USHORT TxPreamble); - -VOID UpdateBasicRateBitmap( - IN PRTMP_ADAPTER pAd); - -VOID MlmeUpdateTxRates( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bLinkUp, - IN UCHAR apidx); - -#ifdef DOT11_N_SUPPORT -VOID MlmeUpdateHtTxRates( - IN PRTMP_ADAPTER pAd, - IN UCHAR apidx); -#endif // DOT11_N_SUPPORT // - -VOID RTMPCheckRates( - IN PRTMP_ADAPTER pAd, - IN OUT UCHAR SupRate[], - IN OUT UCHAR *SupRateLen); - -#ifdef CONFIG_STA_SUPPORT -BOOLEAN RTMPCheckChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR CentralChannel, - IN UCHAR Channel); -#endif // CONFIG_STA_SUPPORT // - -BOOLEAN RTMPCheckHt( - IN PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN OUT HT_CAPABILITY_IE *pHtCapability, - IN OUT ADD_HT_INFO_IE *pAddHtInfo); - -VOID StaQuickResponeForRateUpExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID AsicBbpTuning1( - IN PRTMP_ADAPTER pAd); - -VOID AsicBbpTuning2( - IN PRTMP_ADAPTER pAd); - -VOID RTMPUpdateMlmeRate( - IN PRTMP_ADAPTER pAd); - -CHAR RTMPMaxRssi( - IN PRTMP_ADAPTER pAd, - IN CHAR Rssi0, - IN CHAR Rssi1, - IN CHAR Rssi2); - -#ifdef RT30xx -VOID AsicSetRxAnt( - IN PRTMP_ADAPTER pAd, - IN UCHAR Ant); - -VOID RTMPFilterCalibration( - IN PRTMP_ADAPTER pAd); - -#ifdef RTMP_EFUSE_SUPPORT -//2008/09/11:KH add to support efuse<-- -INT set_eFuseGetFreeBlockCount_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT set_eFusedump_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT set_eFuseLoadFromBin_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -VOID eFusePhysicalReadRegisters( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN USHORT Length, - OUT USHORT* pData); - -int RtmpEfuseSupportCheck( - IN RTMP_ADAPTER *pAd); - -INT set_eFuseBufferModeWriteBack_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT eFuseLoadEEPROM( - IN PRTMP_ADAPTER pAd); - -INT eFuseWriteEeeppromBuf( - IN PRTMP_ADAPTER pAd); - -VOID eFuseGetFreeBlockCount(IN PRTMP_ADAPTER pAd, - PUINT EfuseFreeBlock); - -INT eFuse_init( - IN PRTMP_ADAPTER pAd); - -NTSTATUS eFuseRead( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - OUT PUCHAR pData, - IN USHORT Length); - -NTSTATUS eFuseWrite( - IN PRTMP_ADAPTER pAd, - IN USHORT Offset, - IN PUCHAR pData, - IN USHORT length); -//2008/09/11:KH add to support efuse--> -#endif // RTMP_EFUSE_SUPPORT // - -// add by johnli, RF power sequence setup -VOID RT30xxLoadRFNormalModeSetup( - IN PRTMP_ADAPTER pAd); - -VOID RT30xxLoadRFSleepModeSetup( - IN PRTMP_ADAPTER pAd); - -VOID RT30xxReverseRFSleepModeSetup( - IN PRTMP_ADAPTER pAd); -// end johnli - - -#ifdef RT3090 -VOID NICInitRT3090RFRegisters( - IN RTMP_ADAPTER *pAd); -#endif // RT3090 // - -VOID RT30xxHaltAction( - IN PRTMP_ADAPTER pAd); - -VOID RT30xxSetRxAnt( - IN PRTMP_ADAPTER pAd, - IN UCHAR Ant); -#endif // RT30xx // -#ifdef RT33xx -VOID RT33xxLoadRFNormalModeSetup( - IN PRTMP_ADAPTER pAd); - -VOID RT33xxLoadRFSleepModeSetup( - IN PRTMP_ADAPTER pAd); - -VOID RT33xxReverseRFSleepModeSetup( - IN PRTMP_ADAPTER pAd); - -#ifdef RT3370 -VOID NICInitRT3370RFRegisters( - IN RTMP_ADAPTER *pAd); -#endif // RT3070 // - -#ifdef RT3390 -VOID NICInitRT3390RFRegisters( - IN RTMP_ADAPTER *pAd); -#endif // RT3090 // - -VOID RT33xxHaltAction( - IN PRTMP_ADAPTER pAd); - -VOID RT33xxSetRxAnt( - IN PRTMP_ADAPTER pAd, - IN UCHAR Ant); - -#endif // RT33xx // - - - -VOID AsicEvaluateRxAnt( - IN PRTMP_ADAPTER pAd); - -VOID AsicRxAntEvalTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID APSDPeriodicExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry); - -UCHAR RTMPStaFixedTxMode( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry); - -VOID RTMPUpdateLegacyTxSetting( - UCHAR fixed_tx_mode, - PMAC_TABLE_ENTRY pEntry); - -BOOLEAN RTMPAutoRateSwitchCheck( - IN PRTMP_ADAPTER pAd); - -NDIS_STATUS MlmeInit( - IN PRTMP_ADAPTER pAd); - -VOID MlmeHandler( - IN PRTMP_ADAPTER pAd); - -VOID MlmeHalt( - IN PRTMP_ADAPTER pAd); - -VOID MlmeResetRalinkCounters( - IN PRTMP_ADAPTER pAd); - -VOID BuildChannelList( - IN PRTMP_ADAPTER pAd); - -UCHAR FirstChannel( - IN PRTMP_ADAPTER pAd); - -UCHAR NextChannel( - IN PRTMP_ADAPTER pAd, - IN UCHAR channel); - -VOID ChangeToCellPowerLimit( - IN PRTMP_ADAPTER pAd, - IN UCHAR AironetCellPowerLimit); - -// -// Prototypes of function definition in rtmp_tkip.c -// -VOID RTMPInitTkipEngine( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pTKey, - IN UCHAR KeyId, - IN PUCHAR pTA, - IN PUCHAR pMICKey, - IN PUCHAR pTSC, - OUT PULONG pIV16, - OUT PULONG pIV32); - -VOID RTMPInitMICEngine( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKey, - IN PUCHAR pDA, - IN PUCHAR pSA, - IN UCHAR UserPriority, - IN PUCHAR pMICKey); - -BOOLEAN RTMPTkipCompareMICValue( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pSrc, - IN PUCHAR pDA, - IN PUCHAR pSA, - IN PUCHAR pMICKey, - IN UCHAR UserPriority, - IN UINT Len); - -VOID RTMPCalculateMICValue( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN PUCHAR pEncap, - IN PCIPHER_KEY pKey, - IN UCHAR apidx); - -BOOLEAN RTMPTkipCompareMICValueWithLLC( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pLLC, - IN PUCHAR pSrc, - IN PUCHAR pDA, - IN PUCHAR pSA, - IN PUCHAR pMICKey, - IN UINT Len); - -VOID RTMPTkipAppendByte( - IN PTKIP_KEY_INFO pTkip, - IN UCHAR uChar); - -VOID RTMPTkipAppend( - IN PTKIP_KEY_INFO pTkip, - IN PUCHAR pSrc, - IN UINT nBytes); - -VOID RTMPTkipGetMIC( - IN PTKIP_KEY_INFO pTkip); - -BOOLEAN RTMPSoftDecryptTKIP( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG DataByteCnt, - IN UCHAR UserPriority, - IN PCIPHER_KEY pWpaKey); - -BOOLEAN RTMPSoftDecryptAES( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG DataByteCnt, - IN PCIPHER_KEY pWpaKey); - - - -// -// Prototypes of function definition in cmm_info.c -// -INT RT_CfgSetCountryRegion( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg, - IN INT band); - -INT RT_CfgSetWirelessMode( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT RT_CfgSetShortSlot( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT RT_CfgSetWepKey( - IN PRTMP_ADAPTER pAd, - IN PSTRING keyString, - IN CIPHER_KEY *pSharedKey, - IN INT keyIdx); - -INT RT_CfgSetWPAPSKKey( - IN RTMP_ADAPTER *pAd, - IN PSTRING keyString, - IN UCHAR *pHashStr, - IN INT hashStrLen, - OUT PUCHAR pPMKBuf); - - - -// -// Prototypes of function definition in cmm_info.c -// -NDIS_STATUS RTMPWPARemoveKeyProc( - IN PRTMP_ADAPTER pAd, - IN PVOID pBuf); - -VOID RTMPWPARemoveAllKeys( - IN PRTMP_ADAPTER pAd); - -BOOLEAN RTMPCheckStrPrintAble( - IN CHAR *pInPutStr, - IN UCHAR strLen); - -VOID RTMPSetPhyMode( - IN PRTMP_ADAPTER pAd, - IN ULONG phymode); - -VOID RTMPUpdateHTIE( - IN RT_HT_CAPABILITY *pRtHt, - IN UCHAR *pMcsSet, - OUT HT_CAPABILITY_IE *pHtCapability, - OUT ADD_HT_INFO_IE *pAddHtInfo); - -VOID RTMPAddWcidAttributeEntry( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssIdx, - IN UCHAR KeyIdx, - IN UCHAR CipherAlg, - IN MAC_TABLE_ENTRY *pEntry); - -PSTRING GetEncryptType( - CHAR enc); - -PSTRING GetAuthMode( - CHAR auth); - - -VOID RTMPIndicateWPA2Status( - IN PRTMP_ADAPTER pAdapter); - -VOID RTMPOPModeSwitching( - IN PRTMP_ADAPTER pAd); - - -#ifdef DOT11_N_SUPPORT -VOID RTMPSetHT( - IN PRTMP_ADAPTER pAd, - IN OID_SET_HT_PHYMODE *pHTPhyMode); - -VOID RTMPSetIndividualHT( - IN PRTMP_ADAPTER pAd, - IN UCHAR apidx); -#endif // DOT11_N_SUPPORT // - -VOID RTMPSendWirelessEvent( - IN PRTMP_ADAPTER pAd, - IN USHORT Event_flag, - IN PUCHAR pAddr, - IN UCHAR BssIdx, - IN CHAR Rssi); - -VOID NICUpdateCntlCounters( - IN PRTMP_ADAPTER pAd, - IN PHEADER_802_11 pHeader, - IN UCHAR SubType, - IN PRXWI_STRUC pRxWI); - -VOID DBGPRINT_TX_RING( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx); - -VOID DBGPRINT_RX_RING( - IN PRTMP_ADAPTER pAd); - -CHAR ConvertToRssi( - IN PRTMP_ADAPTER pAd, - IN CHAR Rssi, - IN UCHAR RssiNumber); - - -#ifdef DOT11N_DRAFT3 -VOID BuildEffectedChannelList( - IN PRTMP_ADAPTER pAd); -#endif // DOT11N_DRAFT3 // - - -VOID APAsicEvaluateRxAnt( - IN PRTMP_ADAPTER pAd); - -#ifdef ANT_DIVERSITY_SUPPORT -VOID APAsicAntennaAvg( - IN PRTMP_ADAPTER pAd, - IN UCHAR AntSelect, - IN SHORT *RssiAvg); -#endif // ANT_DIVERSITY_SUPPORT // - -VOID APAsicRxAntEvalTimeout( - IN PRTMP_ADAPTER pAd); - -/*=================================== - Function prototype in cmm_wpa.c - =================================== */ -VOID RTMPToWirelessSta( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PUCHAR pHeader802_3, - IN UINT HdrLen, - IN PUCHAR pData, - IN UINT DataLen, - IN BOOLEAN bClearFrame); - -VOID WpaDerivePTK( - IN PRTMP_ADAPTER pAd, - IN UCHAR *PMK, - IN UCHAR *ANonce, - IN UCHAR *AA, - IN UCHAR *SNonce, - IN UCHAR *SA, - OUT UCHAR *output, - IN UINT len); - -VOID GenRandom( - IN PRTMP_ADAPTER pAd, - IN UCHAR *macAddr, - OUT UCHAR *random); - -BOOLEAN RTMPCheckWPAframe( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PUCHAR pData, - IN ULONG DataByteCount, - IN UCHAR FromWhichBSSID); - -VOID AES_GTK_KEY_UNWRAP( - IN UCHAR *key, - OUT UCHAR *plaintext, - IN UINT32 c_len, - IN UCHAR *ciphertext); - -BOOLEAN RTMPParseEapolKeyData( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pKeyData, - IN UCHAR KeyDataLen, - IN UCHAR GroupKeyIndex, - IN UCHAR MsgType, - IN BOOLEAN bWPA2, - IN MAC_TABLE_ENTRY *pEntry); - -VOID ConstructEapolMsg( - IN PMAC_TABLE_ENTRY pEntry, - IN UCHAR GroupKeyWepStatus, - IN UCHAR MsgType, - IN UCHAR DefaultKeyIdx, - IN UCHAR *KeyNonce, - IN UCHAR *TxRSC, - IN UCHAR *GTK, - IN UCHAR *RSNIE, - IN UCHAR RSNIE_Len, - OUT PEAPOL_PACKET pMsg); - -NDIS_STATUS RTMPSoftDecryptBroadCastData( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN NDIS_802_11_ENCRYPTION_STATUS GroupCipher, - IN PCIPHER_KEY pShard_key); - -VOID RTMPMakeRSNIE( - IN PRTMP_ADAPTER pAd, - IN UINT AuthMode, - IN UINT WepStatus, - IN UCHAR apidx); - -// -// function prototype in ap_wpa.c -// -VOID RTMPGetTxTscFromAsic( - IN PRTMP_ADAPTER pAd, - IN UCHAR apidx, - OUT PUCHAR pTxTsc); - -VOID APInstallPairwiseKey( - PRTMP_ADAPTER pAd, - PMAC_TABLE_ENTRY pEntry); - -MAC_TABLE_ENTRY *PACInquiry( - IN PRTMP_ADAPTER pAd, - IN ULONG Wcid); - -UINT APValidateRSNIE( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN PUCHAR pRsnIe, - IN UCHAR rsnie_len); - -VOID HandleCounterMeasure( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry); - -VOID WPAStart4WayHS( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN ULONG TimeInterval); - -VOID WPAStart2WayGroupHS( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry); - -VOID PeerPairMsg1Action( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerPairMsg2Action( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerPairMsg3Action( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerPairMsg4Action( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerGroupMsg1Action( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN MLME_QUEUE_ELEM *Elem); - -VOID PeerGroupMsg2Action( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN VOID *Msg, - IN UINT MsgLen); - -VOID CMTimerExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID WPARetryExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID EnqueueStartForPSKExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID RTMPHandleSTAKey( - IN PRTMP_ADAPTER pAdapter, - IN MAC_TABLE_ENTRY *pEntry, - IN MLME_QUEUE_ELEM *Elem); - -VOID PairDisAssocAction( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN USHORT Reason); - -VOID MlmeDeAuthAction( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN USHORT Reason); - -VOID GREKEYPeriodicExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID WpaDeriveGTK( - IN UCHAR *PMK, - IN UCHAR *GNonce, - IN UCHAR *AA, - OUT UCHAR *output, - IN UINT len); - -VOID AES_GTK_KEY_WRAP( - IN UCHAR *key, - IN UCHAR *plaintext, - IN UINT32 p_len, - OUT UCHAR *ciphertext); - -VOID AES_128_CMAC( - IN PUCHAR key, - IN PUCHAR input, - IN INT len, - OUT PUCHAR mac); - -VOID WpaSend( - IN PRTMP_ADAPTER pAdapter, - IN PUCHAR pPacket, - IN ULONG Len); - -VOID RTMPAddPMKIDCache( - IN PRTMP_ADAPTER pAd, - IN INT apidx, - IN PUCHAR pAddr, - IN UCHAR *PMKID, - IN UCHAR *PMK); - -INT RTMPSearchPMKIDCache( - IN PRTMP_ADAPTER pAd, - IN INT apidx, - IN PUCHAR pAddr); - -VOID RTMPDeletePMKIDCache( - IN PRTMP_ADAPTER pAd, - IN INT apidx, - IN INT idx); - -VOID RTMPMaintainPMKIDCache( - IN PRTMP_ADAPTER pAd); - -VOID RTMPSendTriggerFrame( - IN PRTMP_ADAPTER pAd, - IN PVOID pBuffer, - IN ULONG Length, - IN UCHAR TxRate, - IN BOOLEAN bQosNull); - -//typedef void (*TIMER_FUNCTION)(unsigned long); - - -/* timeout -- ms */ -VOID RTMP_SetPeriodicTimer( - IN NDIS_MINIPORT_TIMER *pTimer, - IN unsigned long timeout); - -VOID RTMP_OS_Init_Timer( - IN PRTMP_ADAPTER pAd, - IN NDIS_MINIPORT_TIMER *pTimer, - IN TIMER_FUNCTION function, - IN PVOID data); - -VOID RTMP_OS_Add_Timer( - IN NDIS_MINIPORT_TIMER *pTimer, - IN unsigned long timeout); - -VOID RTMP_OS_Mod_Timer( - IN NDIS_MINIPORT_TIMER *pTimer, - IN unsigned long timeout); - - -VOID RTMP_OS_Del_Timer( - IN NDIS_MINIPORT_TIMER *pTimer, - OUT BOOLEAN *pCancelled); - - -VOID RTMP_OS_Release_Packet( - IN PRTMP_ADAPTER pAd, - IN PQUEUE_ENTRY pEntry); - -VOID RTMPusecDelay( - IN ULONG usec); - -NDIS_STATUS os_alloc_mem( - IN RTMP_ADAPTER *pAd, - OUT UCHAR **mem, - IN ULONG size); - -NDIS_STATUS os_free_mem( - IN PRTMP_ADAPTER pAd, - IN PVOID mem); - - -void RTMP_AllocateSharedMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); - -VOID RTMPFreeTxRxRingMemory( - IN PRTMP_ADAPTER pAd); - -NDIS_STATUS AdapterBlockAllocateMemory( - IN PVOID handle, - OUT PVOID *ppAd); - -void RTMP_AllocateTxDescMemory( - IN PRTMP_ADAPTER pAd, - IN UINT Index, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); - -void RTMP_AllocateFirstTxBuffer( - IN PRTMP_ADAPTER pAd, - IN UINT Index, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); - -void RTMP_FreeFirstTxBuffer( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - IN PVOID VirtualAddress, - IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); - -void RTMP_AllocateMgmtDescMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); - -void RTMP_AllocateRxDescMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); - -void RTMP_FreeDescMemory( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN PVOID VirtualAddress, - IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); - -PNDIS_PACKET RtmpOSNetPktAlloc( - IN RTMP_ADAPTER *pAd, - IN int size); - -PNDIS_PACKET RTMP_AllocateRxPacketBuffer( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress, - OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); - -PNDIS_PACKET RTMP_AllocateTxPacketBuffer( - IN PRTMP_ADAPTER pAd, - IN ULONG Length, - IN BOOLEAN Cached, - OUT PVOID *VirtualAddress); - -PNDIS_PACKET RTMP_AllocateFragPacketBuffer( - IN PRTMP_ADAPTER pAd, - IN ULONG Length); - -void RTMP_QueryPacketInfo( - IN PNDIS_PACKET pPacket, - OUT PACKET_INFO *pPacketInfo, - OUT PUCHAR *pSrcBufVA, - OUT UINT *pSrcBufLen); - -void RTMP_QueryNextPacketInfo( - IN PNDIS_PACKET *ppPacket, - OUT PACKET_INFO *pPacketInfo, - OUT PUCHAR *pSrcBufVA, - OUT UINT *pSrcBufLen); - - -BOOLEAN RTMP_FillTxBlkInfo( - IN RTMP_ADAPTER *pAd, - IN TX_BLK *pTxBlk); - - -PRTMP_SCATTER_GATHER_LIST -rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg); - - - void announce_802_3_packet( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket); - - -UINT BA_Reorder_AMSDU_Annnounce( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket); - - -UINT Handle_AMSDU_Packet( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pData, - IN ULONG DataSize, - IN UCHAR FromWhichBSSID); - - -void convert_802_11_to_802_3_packet( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN PUCHAR p8023hdr, - IN PUCHAR pData, - IN ULONG DataSize, - IN UCHAR FromWhichBSSID); - - -PNET_DEV get_netdev_from_bssid( - IN PRTMP_ADAPTER pAd, - IN UCHAR FromWhichBSSID); - - -PNDIS_PACKET duplicate_pkt( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pHeader802_3, - IN UINT HdrLen, - IN PUCHAR pData, - IN ULONG DataSize, - IN UCHAR FromWhichBSSID); - - -PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pOldPkt); - -PNDIS_PACKET duplicate_pkt_with_VLAN( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pHeader802_3, - IN UINT HdrLen, - IN PUCHAR pData, - IN ULONG DataSize, - IN UCHAR FromWhichBSSID); - - -UCHAR VLAN_8023_Header_Copy( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pHeader802_3, - IN UINT HdrLen, - OUT PUCHAR pData, - IN UCHAR FromWhichBSSID); - -#ifdef DOT11_N_SUPPORT -void ba_flush_reordering_timeout_mpdus( - IN PRTMP_ADAPTER pAd, - IN PBA_REC_ENTRY pBAEntry, - IN ULONG Now32); - - -VOID BAOriSessionSetUp( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN UCHAR TID, - IN USHORT TimeOut, - IN ULONG DelayTime, - IN BOOLEAN isForced); - -VOID BASessionTearDownALL( - IN OUT PRTMP_ADAPTER pAd, - IN UCHAR Wcid); -#endif // DOT11_N_SUPPORT // - -BOOLEAN OS_Need_Clone_Packet(void); - - -VOID build_tx_packet( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN PUCHAR pFrame, - IN ULONG FrameLen); - - -VOID BAOriSessionTearDown( - IN OUT PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR TID, - IN BOOLEAN bPassive, - IN BOOLEAN bForceSend); - -VOID BARecSessionTearDown( - IN OUT PRTMP_ADAPTER pAd, - IN UCHAR Wcid, - IN UCHAR TID, - IN BOOLEAN bPassive); - -BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num); -void ba_reordering_resource_release(PRTMP_ADAPTER pAd); - - - -#ifdef NINTENDO_AP -VOID InitNINTENDO_TABLE( - IN PRTMP_ADAPTER pAd); - -UCHAR CheckNINTENDO_TABLE( - IN PRTMP_ADAPTER pAd, - PCHAR pDS_Ssid, - UCHAR DS_SsidLen, - PUCHAR pDS_Addr); - -UCHAR DelNINTENDO_ENTRY( - IN PRTMP_ADAPTER pAd, - UCHAR * pDS_Addr); - -VOID RTMPIoctlNintendoCapable( - IN PRTMP_ADAPTER pAd, - IN struct iwreq *wrq); - -VOID RTMPIoctlNintendoGetTable( - IN PRTMP_ADAPTER pAd, - IN struct iwreq *wrq); - -VOID RTMPIoctlNintendoSetTable( - IN PRTMP_ADAPTER pAd, - IN struct iwreq *wrq); - -#endif // NINTENDO_AP // - -BOOLEAN rtstrmactohex( - IN PSTRING s1, - IN PSTRING s2); - -BOOLEAN rtstrcasecmp( - IN PSTRING s1, - IN PSTRING s2); - -PSTRING rtstrstruncasecmp( - IN PSTRING s1, - IN PSTRING s2); - -PSTRING rtstrstr( - IN const PSTRING s1, - IN const PSTRING s2); - -PSTRING rstrtok( - IN PSTRING s, - IN const PSTRING ct); - -int rtinet_aton( - const PSTRING cp, - unsigned int *addr); - -////////// common ioctl functions ////////// -INT Set_DriverVersion_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_CountryRegion_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_CountryRegionABand_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_WirelessMode_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_Channel_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ShortSlot_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_TxPower_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_BGProtection_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_TxPreamble_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_RTSThreshold_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_FragThreshold_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_TxBurst_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -#ifdef AGGREGATION_SUPPORT -INT Set_PktAggregate_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); -#endif // AGGREGATION_SUPPORT // - -#ifdef INF_AMAZON_PPA -INT Set_INF_AMAZON_SE_PPA_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); - -#endif // INF_AMAZON_PPA // - -INT Set_IEEE80211H_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -#ifdef DBG -INT Set_Debug_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); -#endif - -INT Show_DescInfo_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ResetStatCounter_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -#ifdef DOT11_N_SUPPORT -INT Set_BASetup_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_BADecline_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_BAOriTearDown_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_BARecTearDown_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtBw_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtMcs_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtGi_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtOpMode_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtStbc_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtHtc_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtExtcha_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtMpduDensity_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtBaWinSize_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtRdg_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtLinkAdapt_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtAmsdu_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtAutoBa_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtProtect_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtMimoPs_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - - -INT Set_ForceShortGI_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ForceGF_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT SetCommonHT( - IN PRTMP_ADAPTER pAd); - -INT Set_SendPSMPAction_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtMIMOPSmode_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - - -INT Set_HtTxBASize_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_HtDisallowTKIP_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -#endif // DOT11_N_SUPPORT // - - - -#ifdef CONFIG_STA_SUPPORT -//Dls , kathy -VOID RTMPSendDLSTearDownFrame( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA); - -#ifdef DOT11_N_SUPPORT -//Block ACK -VOID QueryBATABLE( - IN PRTMP_ADAPTER pAd, - OUT PQUERYBA_TABLE pBAT); -#endif // DOT11_N_SUPPORT // - -#ifdef WPA_SUPPLICANT_SUPPORT -INT WpaCheckEapCode( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pFrame, - IN USHORT FrameLen, - IN USHORT OffSet); - -VOID WpaSendMicFailureToWpaSupplicant( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bUnicast); - -VOID SendAssocIEsToWpaSupplicant( - IN PRTMP_ADAPTER pAd); -#endif // WPA_SUPPLICANT_SUPPORT // - -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT -int wext_notify_event_assoc( - IN RTMP_ADAPTER *pAd); -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - -#endif // CONFIG_STA_SUPPORT // - - - -#ifdef DOT11_N_SUPPORT -VOID Handle_BSS_Width_Trigger_Events( - IN PRTMP_ADAPTER pAd); - -void build_ext_channel_switch_ie( - IN PRTMP_ADAPTER pAd, - IN HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE *pIE); -#endif // DOT11_N_SUPPORT // - - -BOOLEAN APRxDoneInterruptHandle( - IN PRTMP_ADAPTER pAd); - -BOOLEAN STARxDoneInterruptHandle( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN argc); - -#ifdef DOT11_N_SUPPORT -// AMPDU packet indication -VOID Indicate_AMPDU_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); - -// AMSDU packet indication -VOID Indicate_AMSDU_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); -#endif // DOT11_N_SUPPORT // - -// Normal legacy Rx packet indication -VOID Indicate_Legacy_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); - -VOID Indicate_EAPOL_Packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); - -void update_os_packet_info( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); - -void wlan_802_11_to_802_3_packet( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN PUCHAR pHeader802_3, - IN UCHAR FromWhichBSSID); - -UINT deaggregate_AMSDU_announce( - IN PRTMP_ADAPTER pAd, - PNDIS_PACKET pPacket, - IN PUCHAR pData, - IN ULONG DataSize); - - -#ifdef CONFIG_STA_SUPPORT -// remove LLC and get 802_3 Header -#define RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(_pRxBlk, _pHeader802_3) \ -{ \ - PUCHAR _pRemovedLLCSNAP = NULL, _pDA, _pSA; \ - \ - if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_MESH)) \ - { \ - _pDA = _pRxBlk->pHeader->Addr3; \ - _pSA = (PUCHAR)_pRxBlk->pHeader + sizeof(HEADER_802_11); \ - } \ - else \ - { \ - if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_INFRA)) \ - { \ - _pDA = _pRxBlk->pHeader->Addr1; \ - if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_DLS)) \ - _pSA = _pRxBlk->pHeader->Addr2; \ - else \ - _pSA = _pRxBlk->pHeader->Addr3; \ - } \ - else \ - { \ - _pDA = _pRxBlk->pHeader->Addr1; \ - _pSA = _pRxBlk->pHeader->Addr2; \ - } \ - } \ - \ - CONVERT_TO_802_3(_pHeader802_3, _pDA, _pSA, _pRxBlk->pData, \ - _pRxBlk->DataSize, _pRemovedLLCSNAP); \ -} -#endif // CONFIG_STA_SUPPORT // - - -BOOLEAN APFowardWirelessStaToWirelessSta( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN ULONG FromWhichBSSID); - -VOID Announce_or_Forward_802_3_Packet( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR FromWhichBSSID); - -VOID Sta_Announce_or_Forward_802_3_Packet( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR FromWhichBSSID); - - -#ifdef CONFIG_STA_SUPPORT -#define ANNOUNCE_OR_FORWARD_802_3_PACKET(_pAd, _pPacket, _FromWhichBSS)\ - Sta_Announce_or_Forward_802_3_Packet(_pAd, _pPacket, _FromWhichBSS); - //announce_802_3_packet(_pAd, _pPacket); -#endif // CONFIG_STA_SUPPORT // - - -PNDIS_PACKET DuplicatePacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR FromWhichBSSID); - - -PNDIS_PACKET ClonePacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN PUCHAR pData, - IN ULONG DataSize); - - -// Normal, AMPDU or AMSDU -VOID CmmRxnonRalinkFrameIndicate( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); - -VOID CmmRxRalinkFrameIndicate( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID); - -VOID Update_Rssi_Sample( - IN PRTMP_ADAPTER pAd, - IN RSSI_SAMPLE *pRssi, - IN PRXWI_STRUC pRxWI); - -PNDIS_PACKET GetPacketFromRxRing( - IN PRTMP_ADAPTER pAd, - OUT PRT28XX_RXD_STRUC pSaveRxD, - OUT BOOLEAN *pbReschedule, - IN OUT UINT32 *pRxPending); - -PNDIS_PACKET RTMPDeFragmentDataFrame( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk); - -//////////////////////////////////////// - -VOID RTMPIoctlGetSiteSurvey( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq); - - - - - -#ifdef SNMP_SUPPORT -//for snmp , kathy -typedef struct _DefaultKeyIdxValue -{ - UCHAR KeyIdx; - UCHAR Value[16]; -} DefaultKeyIdxValue, *PDefaultKeyIdxValue; -#endif - - -#ifdef CONFIG_STA_SUPPORT -enum { - DIDmsg_lnxind_wlansniffrm = 0x00000044, - DIDmsg_lnxind_wlansniffrm_hosttime = 0x00010044, - DIDmsg_lnxind_wlansniffrm_mactime = 0x00020044, - DIDmsg_lnxind_wlansniffrm_channel = 0x00030044, - DIDmsg_lnxind_wlansniffrm_rssi = 0x00040044, - DIDmsg_lnxind_wlansniffrm_sq = 0x00050044, - DIDmsg_lnxind_wlansniffrm_signal = 0x00060044, - DIDmsg_lnxind_wlansniffrm_noise = 0x00070044, - DIDmsg_lnxind_wlansniffrm_rate = 0x00080044, - DIDmsg_lnxind_wlansniffrm_istx = 0x00090044, - DIDmsg_lnxind_wlansniffrm_frmlen = 0x000A0044 -}; -enum { - P80211ENUM_msgitem_status_no_value = 0x00 -}; -enum { - P80211ENUM_truth_false = 0x00, - P80211ENUM_truth_true = 0x01 -}; - -/* Definition from madwifi */ -typedef struct { - UINT32 did; - UINT16 status; - UINT16 len; - UINT32 data; -} p80211item_uint32_t; - -typedef struct { - UINT32 msgcode; - UINT32 msglen; -#define WLAN_DEVNAMELEN_MAX 16 - UINT8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t hosttime; - p80211item_uint32_t mactime; - p80211item_uint32_t channel; - p80211item_uint32_t rssi; - p80211item_uint32_t sq; - p80211item_uint32_t signal; - p80211item_uint32_t noise; - p80211item_uint32_t rate; - p80211item_uint32_t istx; - p80211item_uint32_t frmlen; -} wlan_ng_prism2_header; - -/* The radio capture header precedes the 802.11 header. */ -typedef struct PACKED _ieee80211_radiotap_header { - UINT8 it_version; /* Version 0. Only increases - * for drastic changes, - * introduction of compatible - * new fields does not count. - */ - UINT8 it_pad; - UINT16 it_len; /* length of the whole - * header in bytes, including - * it_version, it_pad, - * it_len, and data fields. - */ - UINT32 it_present; /* A bitmap telling which - * fields are present. Set bit 31 - * (0x80000000) to extend the - * bitmap by another 32 bits. - * Additional extensions are made - * by setting bit 31. - */ -}ieee80211_radiotap_header ; - -enum ieee80211_radiotap_type { - IEEE80211_RADIOTAP_TSFT = 0, - IEEE80211_RADIOTAP_FLAGS = 1, - IEEE80211_RADIOTAP_RATE = 2, - IEEE80211_RADIOTAP_CHANNEL = 3, - IEEE80211_RADIOTAP_FHSS = 4, - IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, - IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, - IEEE80211_RADIOTAP_LOCK_QUALITY = 7, - IEEE80211_RADIOTAP_TX_ATTENUATION = 8, - IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, - IEEE80211_RADIOTAP_DBM_TX_POWER = 10, - IEEE80211_RADIOTAP_ANTENNA = 11, - IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, - IEEE80211_RADIOTAP_DB_ANTNOISE = 13 -}; - -#define WLAN_RADIOTAP_PRESENT ( \ - (1 << IEEE80211_RADIOTAP_TSFT) | \ - (1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - 0) - -typedef struct _wlan_radiotap_header { - ieee80211_radiotap_header wt_ihdr; - INT64 wt_tsft; - UINT8 wt_flags; - UINT8 wt_rate; -} wlan_radiotap_header; -/* Definition from madwifi */ - -void send_monitor_packets( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk); - - -VOID RTMPSetDesiredRates( - IN PRTMP_ADAPTER pAdapter, - IN LONG Rates); -#endif // CONFIG_STA_SUPPORT // - -INT Set_FixedTxMode_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -#ifdef CONFIG_APSTA_MIXED_SUPPORT -INT Set_OpMode_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); -#endif // CONFIG_APSTA_MIXED_SUPPORT // - -INT Set_LongRetryLimit_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -INT Set_ShortRetryLimit_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -BOOLEAN RT28XXChipsetCheck( - IN void *_dev_p); - - -VOID RT28XXDMADisable( - IN RTMP_ADAPTER *pAd); - -VOID RT28XXDMAEnable( - IN RTMP_ADAPTER *pAd); - -VOID RT28xx_UpdateBeaconToAsic( - IN RTMP_ADAPTER * pAd, - IN INT apidx, - IN ULONG BeaconLen, - IN ULONG UpdatePos); - -int rt28xx_init( - IN PRTMP_ADAPTER pAd, - IN PSTRING pDefaultMac, - IN PSTRING pHostName); - -BOOLEAN RT28XXSecurityKeyAdd( - IN PRTMP_ADAPTER pAd, - IN ULONG apidx, - IN ULONG KeyIdx, - IN MAC_TABLE_ENTRY *pEntry); - -NDIS_STATUS RtmpNetTaskInit( - IN RTMP_ADAPTER *pAd); - -VOID RtmpNetTaskExit( - IN PRTMP_ADAPTER pAd); - -NDIS_STATUS RtmpMgmtTaskInit( - IN RTMP_ADAPTER *pAd); - -VOID RtmpMgmtTaskExit( - IN RTMP_ADAPTER *pAd); - -void tbtt_tasklet(unsigned long data); - - -PNET_DEV RtmpPhyNetDevInit( - IN RTMP_ADAPTER *pAd, - IN RTMP_OS_NETDEV_OP_HOOK *pNetHook); - -BOOLEAN RtmpPhyNetDevExit( - IN RTMP_ADAPTER *pAd, - IN PNET_DEV net_dev); - -INT RtmpRaDevCtrlInit( - IN RTMP_ADAPTER *pAd, - IN RTMP_INF_TYPE infType); - -BOOLEAN RtmpRaDevCtrlExit( - IN RTMP_ADAPTER *pAd); - - -#ifdef RTMP_MAC_PCI -// -// Function Prototype in cmm_data_pci.c -// -USHORT RtmpPCI_WriteTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN BOOLEAN bIsLast, - OUT USHORT *FreeNumber); - -USHORT RtmpPCI_WriteSingleTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN BOOLEAN bIsLast, - OUT USHORT *FreeNumber); - -USHORT RtmpPCI_WriteMultiTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR frameNum, - OUT USHORT *FreeNumber); - -USHORT RtmpPCI_WriteFragTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR fragNum, - OUT USHORT *FreeNumber); - -USHORT RtmpPCI_WriteSubTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN BOOLEAN bIsLast, - OUT USHORT *FreeNumber); - -VOID RtmpPCI_FinalWriteTxResource( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN USHORT totalMPDUSize, - IN USHORT FirstTxIdx); - -VOID RtmpPCIDataLastTxIdx( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN USHORT LastTxIdx); - -VOID RtmpPCIDataKickOut( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR QueIdx); - - -int RtmpPCIMgmtKickOut( - IN RTMP_ADAPTER *pAd, - IN UCHAR QueIdx, - IN PNDIS_PACKET pPacket, - IN PUCHAR pSrcBufVA, - IN UINT SrcBufLen); - - -NDIS_STATUS RTMPCheckRxError( - IN PRTMP_ADAPTER pAd, - IN PHEADER_802_11 pHeader, - IN PRXWI_STRUC pRxWI, - IN PRT28XX_RXD_STRUC pRxD); - -BOOLEAN RT28xxPciAsicRadioOff( - IN PRTMP_ADAPTER pAd, - IN UCHAR Level, - IN USHORT TbttNumToNextWakeUp); - -BOOLEAN RT28xxPciAsicRadioOn( - IN PRTMP_ADAPTER pAd, - IN UCHAR Level); - -#ifdef CONFIG_STA_SUPPORT -VOID RTMPInitPCIeLinkCtrlValue( - IN PRTMP_ADAPTER pAd); - -VOID RTMPFindHostPCIDev( - IN PRTMP_ADAPTER pAd); - -VOID RTMPPCIeLinkCtrlValueRestore( - IN PRTMP_ADAPTER pAd, - IN UCHAR Level); - -VOID RTMPPCIeLinkCtrlSetting( - IN PRTMP_ADAPTER pAd, - IN USHORT Max); - -VOID RTMPrt3xSetPCIePowerLinkCtrl( - IN PRTMP_ADAPTER pAd); - - -VOID RT28xxPciStaAsicForceWakeup( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bFromTx); - -VOID RT28xxPciStaAsicSleepThenAutoWakeup( - IN PRTMP_ADAPTER pAd, - IN USHORT TbttNumToNextWakeUp); - -VOID PsPollWakeExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); - -VOID RadioOnExec( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3); -#endif // CONFIG_STA_SUPPORT // - -VOID RT28xxPciMlmeRadioOn( - IN PRTMP_ADAPTER pAd); - -VOID RT28xxPciMlmeRadioOFF( - IN PRTMP_ADAPTER pAd); -#endif // RTMP_MAC_PCI // - -VOID AsicTurnOffRFClk( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel); - -VOID AsicTurnOnRFClk( - IN PRTMP_ADAPTER pAd, - IN UCHAR Channel); - - - -#ifdef RTMP_TIMER_TASK_SUPPORT -INT RtmpTimerQThread( - IN OUT PVOID Context); - -RTMP_TIMER_TASK_ENTRY *RtmpTimerQInsert( - IN RTMP_ADAPTER *pAd, - IN RALINK_TIMER_STRUCT *pTimer); - -BOOLEAN RtmpTimerQRemove( - IN RTMP_ADAPTER *pAd, - IN RALINK_TIMER_STRUCT *pTimer); - -void RtmpTimerQExit( - IN RTMP_ADAPTER *pAd); - -void RtmpTimerQInit( - IN RTMP_ADAPTER *pAd); -#endif // RTMP_TIMER_TASK_SUPPORT // - - - -//////////////////////////////////////// - -VOID QBSS_LoadInit( - IN RTMP_ADAPTER *pAd); - -UINT32 QBSS_LoadElementAppend( - IN RTMP_ADAPTER *pAd, - OUT UINT8 *buf_p); - -VOID QBSS_LoadUpdate( - IN RTMP_ADAPTER *pAd); - -/////////////////////////////////////// -INT RTMPShowCfgValue( - IN PRTMP_ADAPTER pAd, - IN PSTRING pName, - IN PSTRING pBuf); - -PSTRING RTMPGetRalinkAuthModeStr( - IN NDIS_802_11_AUTHENTICATION_MODE authMode); - -PSTRING RTMPGetRalinkEncryModeStr( - IN USHORT encryMode); -////////////////////////////////////// - -#ifdef CONFIG_STA_SUPPORT -VOID AsicStaBbpTuning( - IN PRTMP_ADAPTER pAd); - -BOOLEAN StaAddMacTableEntry( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN UCHAR MaxSupportedRateIn500Kbps, - IN HT_CAPABILITY_IE *pHtCapability, - IN UCHAR HtCapabilityLen, - IN ADD_HT_INFO_IE *pAddHtInfo, - IN UCHAR AddHtInfoLen, - IN USHORT CapabilityInfo); - - -BOOLEAN AUTH_ReqSend( - IN PRTMP_ADAPTER pAd, - IN PMLME_QUEUE_ELEM pElem, - IN PRALINK_TIMER_STRUCT pAuthTimer, - IN PSTRING pSMName, - IN USHORT SeqNo, - IN PUCHAR pNewElement, - IN ULONG ElementLen); -#endif // CONFIG_STA_SUPPORT // - -void RTMP_IndicateMediaState( - IN PRTMP_ADAPTER pAd); - -VOID ReSyncBeaconTime( - IN PRTMP_ADAPTER pAd); - -VOID RTMPSetAGCInitValue( - IN PRTMP_ADAPTER pAd, - IN UCHAR BandWidth); - -int rt28xx_close(IN PNET_DEV dev); -int rt28xx_open(IN PNET_DEV dev); - - -#define VIRTUAL_IF_INC(__pAd) ((__pAd)->VirtualIfCnt++) -#define VIRTUAL_IF_DEC(__pAd) ((__pAd)->VirtualIfCnt--) -#define VIRTUAL_IF_NUM(__pAd) ((__pAd)->VirtualIfCnt) - - -#ifdef LINUX -__inline INT VIRTUAL_IF_UP(PRTMP_ADAPTER pAd) -{ - if (VIRTUAL_IF_NUM(pAd) == 0) - { - if (rt28xx_open(pAd->net_dev) != 0) - { - DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_open return fail!\n")); - return -1; - } - } - else - { - } - VIRTUAL_IF_INC(pAd); - return 0; -} - -__inline VOID VIRTUAL_IF_DOWN(PRTMP_ADAPTER pAd) -{ - VIRTUAL_IF_DEC(pAd); - if (VIRTUAL_IF_NUM(pAd) == 0) - rt28xx_close(pAd->net_dev); - return; -} -#endif // LINUX // - - - - -/* - OS Related funciton prototype definitions. - TODO: Maybe we need to move these function prototypes to other proper place. -*/ -int RtmpOSWrielessEventSend( - IN RTMP_ADAPTER *pAd, - IN UINT32 eventType, - IN INT flags, - IN PUCHAR pSrcMac, - IN PUCHAR pData, - IN UINT32 dataLen); - -int RtmpOSNetDevAddrSet( - IN PNET_DEV pNetDev, - IN PUCHAR pMacAddr); - -int RtmpOSNetDevAttach( - IN PNET_DEV pNetDev, - IN RTMP_OS_NETDEV_OP_HOOK *pDevOpHook); - -void RtmpOSNetDevClose( - IN PNET_DEV pNetDev); - -void RtmpOSNetDevDetach( - IN PNET_DEV pNetDev); - -INT RtmpOSNetDevAlloc( - IN PNET_DEV *pNewNetDev, - IN UINT32 privDataSize); - -void RtmpOSNetDevFree( - IN PNET_DEV pNetDev); - -PNET_DEV RtmpOSNetDevGetByName( - IN PNET_DEV pNetDev, - IN PSTRING pDevName); - -void RtmpOSNetDeviceRefPut( - IN PNET_DEV pNetDev); - -PNET_DEV RtmpOSNetDevCreate( - IN RTMP_ADAPTER *pAd, - IN INT devType, - IN INT devNum, - IN INT privMemSize, - IN PSTRING pNamePrefix); - -/* - Task operation related function prototypes -*/ -void RtmpOSTaskCustomize( - IN RTMP_OS_TASK *pTask); - -INT RtmpOSTaskNotifyToExit( - IN RTMP_OS_TASK *pTask); - -NDIS_STATUS RtmpOSTaskKill( - IN RTMP_OS_TASK *pTask); - -NDIS_STATUS RtmpOSTaskInit( - IN RTMP_OS_TASK *pTask, - PSTRING pTaskName, - VOID *pPriv); - -NDIS_STATUS RtmpOSTaskAttach( - IN RTMP_OS_TASK *pTask, - IN int (*fn)(void *), - IN void *arg); - - -/* - File operation related function prototypes -*/ -RTMP_OS_FD RtmpOSFileOpen( - IN char *pPath, - IN int flag, - IN int mode); - -int RtmpOSFileClose( - IN RTMP_OS_FD osfd); - -void RtmpOSFileSeek( - IN RTMP_OS_FD osfd, - IN int offset); - -int RtmpOSFileRead( - IN RTMP_OS_FD osfd, - IN char *pDataPtr, - IN int readLen); - -int RtmpOSFileWrite( - IN RTMP_OS_FD osfd, - IN char *pDataPtr, - IN int writeLen); - -void RtmpOSFSInfoChange( - IN RTMP_OS_FS_INFO *pOSFSInfo, - IN BOOLEAN bSet); - - -#endif // __RTMP_H__ diff --git a/drivers/staging/rt3090/rtmp_chip.h b/drivers/staging/rt3090/rtmp_chip.h deleted file mode 100644 index a0b4bf06cca08b4c93d7aa53b61cb343919a0fd3..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rtmp_chip.h +++ /dev/null @@ -1,355 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rtmp_chip.h - - Abstract: - Ralink Wireless Chip related definition & structures - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#ifndef __RTMP_CHIP_H__ -#define __RTMP_CHIP_H__ - -#include "rtmp_type.h" - -#ifdef RT3090 -#include "rt3090.h" -#endif // RT3090 // - -#ifdef RT3370 -#include "rt3370.h" -#endif // RT3370 // - -#ifdef RT3390 -#include "rt3390.h" -#endif // RT3390 // - -// We will have a cost down version which mac version is 0x3090xxxx -// -// RT3090A facts -// -// a) 2.4 GHz -// b) Replacement for RT3090 -// c) Internal LNA -// d) Interference over channel #14 -// e) New BBP features (e.g., SIG re-modulation) -// -#define IS_RT3090A(_pAd) ((((_pAd)->MACVersion & 0xffff0000) == 0x30900000)) - -// We will have a cost down version which mac version is 0x3090xxxx -#define IS_RT3090(_pAd) ((((_pAd)->MACVersion & 0xffff0000) == 0x30710000) || (IS_RT3090A(_pAd))) - -#define IS_RT3070(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x30700000) -#define IS_RT3071(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x30710000) -#define IS_RT2070(_pAd) (((_pAd)->RfIcType == RFIC_2020) || ((_pAd)->EFuseTag == 0x27)) - -#define IS_RT30xx(_pAd) (((_pAd)->MACVersion & 0xfff00000) == 0x30700000||IS_RT3090A(_pAd)) -//#define IS_RT305X(_pAd) ((_pAd)->MACVersion == 0x28720200) - -/* RT3572, 3592, 3562, 3062 share the same MAC version */ -#define IS_RT3572(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x35720000) -#define IS_VERSION_BEFORE_F(_pAd) (((_pAd)->MACVersion&0xffff) <= 0x0211) -// F version is 0x0212, E version is 0x0211. 309x can save more power after F version. -#define IS_VERSION_AFTER_F(_pAd) ((((_pAd)->MACVersion&0xffff) >= 0x0212) || (((_pAd)->b3090ESpecialChip == TRUE))) -// -// RT3390 facts -// -// a) Base on RT3090 (RF IC: RT3020) -// b) 2.4 GHz -// c) 1x1 -// d) Single chip -// e) Internal components: PA and LNA -// -//RT3390,RT3370 -#define IS_RT3390(_pAd) (((_pAd)->MACVersion & 0xFFFF0000) == 0x33900000) - -// ------------------------------------------------------ -// PCI registers - base address 0x0000 -// ------------------------------------------------------ -#define CHIP_PCI_CFG 0x0000 -#define CHIP_PCI_EECTRL 0x0004 -#define CHIP_PCI_MCUCTRL 0x0008 - -#define OPT_14 0x114 - -#define RETRY_LIMIT 10 - - - -// ------------------------------------------------------ -// BBP & RF definition -// ------------------------------------------------------ -#define BUSY 1 -#define IDLE 0 - - -//------------------------------------------------------------------------- -// EEPROM definition -//------------------------------------------------------------------------- -#define EEDO 0x08 -#define EEDI 0x04 -#define EECS 0x02 -#define EESK 0x01 -#define EERL 0x80 - -#define EEPROM_WRITE_OPCODE 0x05 -#define EEPROM_READ_OPCODE 0x06 -#define EEPROM_EWDS_OPCODE 0x10 -#define EEPROM_EWEN_OPCODE 0x13 - -#define NUM_EEPROM_BBP_PARMS 19 // Include NIC Config 0, 1, CR, TX ALC step, BBPs -#define NUM_EEPROM_TX_G_PARMS 7 -#define EEPROM_NIC1_OFFSET 0x34 // The address is from NIC config 0, not BBP register ID -#define EEPROM_NIC2_OFFSET 0x36 // The address is from NIC config 0, not BBP register ID -#define EEPROM_BBP_BASE_OFFSET 0xf0 // The address is from NIC config 0, not BBP register ID -#define EEPROM_G_TX_PWR_OFFSET 0x52 -#define EEPROM_G_TX2_PWR_OFFSET 0x60 -#define EEPROM_LED1_OFFSET 0x3c -#define EEPROM_LED2_OFFSET 0x3e -#define EEPROM_LED3_OFFSET 0x40 -#define EEPROM_LNA_OFFSET 0x44 -#define EEPROM_RSSI_BG_OFFSET 0x46 -#define EEPROM_TXMIXER_GAIN_2_4G 0x48 -#define EEPROM_RSSI_A_OFFSET 0x4a -#define EEPROM_TXMIXER_GAIN_5G 0x4c -#define EEPROM_DEFINE_MAX_TXPWR 0x4e -#define EEPROM_TXPOWER_BYRATE_20MHZ_2_4G 0xde // 20MHZ 2.4G tx power. -#define EEPROM_TXPOWER_BYRATE_40MHZ_2_4G 0xee // 40MHZ 2.4G tx power. -#define EEPROM_TXPOWER_BYRATE_20MHZ_5G 0xfa // 20MHZ 5G tx power. -#define EEPROM_TXPOWER_BYRATE_40MHZ_5G 0x10a // 40MHZ 5G tx power. -#define EEPROM_A_TX_PWR_OFFSET 0x78 -#define EEPROM_A_TX2_PWR_OFFSET 0xa6 -//#define EEPROM_Japan_TX_PWR_OFFSET 0x90 // 802.11j -//#define EEPROM_Japan_TX2_PWR_OFFSET 0xbe -//#define EEPROM_TSSI_REF_OFFSET 0x54 -//#define EEPROM_TSSI_DELTA_OFFSET 0x24 -//#define EEPROM_CCK_TX_PWR_OFFSET 0x62 -//#define EEPROM_CALIBRATE_OFFSET 0x7c -#define EEPROM_VERSION_OFFSET 0x02 -#define EEPROM_FREQ_OFFSET 0x3a -#define EEPROM_TXPOWER_BYRATE 0xde // 20MHZ power. -#define EEPROM_TXPOWER_DELTA 0x50 // 20MHZ AND 40 MHZ use different power. This is delta in 40MHZ. -#define VALID_EEPROM_VERSION 1 - - -/* - * EEPROM operation related marcos - */ -#define RT28xx_EEPROM_READ16(_pAd, _offset, _value) \ - (_pAd)->chipOps.eeread((RTMP_ADAPTER *)(_pAd), (USHORT)(_offset), (PUSHORT)&(_value)) - -#define RT28xx_EEPROM_WRITE16(_pAd, _offset, _value) \ - (_pAd)->chipOps.eewrite((RTMP_ADAPTER *)(_pAd), (USHORT)(_offset), (USHORT)(_value)) - - - -// ------------------------------------------------------------------- -// E2PROM data layout -// ------------------------------------------------------------------- - -// -// MCU_LEDCS: MCU LED Control Setting. -// -typedef union _MCU_LEDCS_STRUC { - struct { -#ifdef RT_BIG_ENDIAN - UCHAR Polarity:1; - UCHAR LedMode:7; -#else - UCHAR LedMode:7; - UCHAR Polarity:1; -#endif // RT_BIG_ENDIAN // - } field; - UCHAR word; -} MCU_LEDCS_STRUC, *PMCU_LEDCS_STRUC; - - -// -// EEPROM antenna select format -// -#ifdef RT_BIG_ENDIAN -typedef union _EEPROM_ANTENNA_STRUC { - struct { - USHORT Rsv:4; - USHORT RfIcType:4; // see E2PROM document - USHORT TxPath:4; // 1: 1T, 2: 2T - USHORT RxPath:4; // 1: 1R, 2: 2R, 3: 3R - } field; - USHORT word; -} EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC; -#else -typedef union _EEPROM_ANTENNA_STRUC { - struct { - USHORT RxPath:4; // 1: 1R, 2: 2R, 3: 3R - USHORT TxPath:4; // 1: 1T, 2: 2T - USHORT RfIcType:4; // see E2PROM document - USHORT Rsv:4; - } field; - USHORT word; -} EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC; -#endif - -#ifdef RT_BIG_ENDIAN -typedef union _EEPROM_NIC_CINFIG2_STRUC { - struct { - USHORT DACTestBit:1; // control if driver should patch the DAC issue - USHORT Rsv2:3; // must be 0 - USHORT AntDiversity:1; // Antenna diversity - USHORT Rsv1:1; // must be 0 - USHORT BW40MAvailForA:1; // 0:enable, 1:disable - USHORT BW40MAvailForG:1; // 0:enable, 1:disable - USHORT EnableWPSPBC:1; // WPS PBC Control bit - USHORT BW40MSidebandForA:1; - USHORT BW40MSidebandForG:1; - USHORT CardbusAcceleration:1; // !!! NOTE: 0 - enable, 1 - disable - USHORT ExternalLNAForA:1; // external LNA enable for 5G - USHORT ExternalLNAForG:1; // external LNA enable for 2.4G - USHORT DynamicTxAgcControl:1; // - USHORT HardwareRadioControl:1; // Whether RF is controlled by driver or HW. 1:enable hw control, 0:disable - } field; - USHORT word; -} EEPROM_NIC_CONFIG2_STRUC, *PEEPROM_NIC_CONFIG2_STRUC; -#else -typedef union _EEPROM_NIC_CINFIG2_STRUC { - struct { - USHORT HardwareRadioControl:1; // 1:enable, 0:disable - USHORT DynamicTxAgcControl:1; // - USHORT ExternalLNAForG:1; // - USHORT ExternalLNAForA:1; // external LNA enable for 2.4G - USHORT CardbusAcceleration:1; // !!! NOTE: 0 - enable, 1 - disable - USHORT BW40MSidebandForG:1; - USHORT BW40MSidebandForA:1; - USHORT EnableWPSPBC:1; // WPS PBC Control bit - USHORT BW40MAvailForG:1; // 0:enable, 1:disable - USHORT BW40MAvailForA:1; // 0:enable, 1:disable - USHORT Rsv1:1; // must be 0 - USHORT AntDiversity:1; // Antenna diversity - USHORT Rsv2:3; // must be 0 - USHORT DACTestBit:1; // control if driver should patch the DAC issue - } field; - USHORT word; -} EEPROM_NIC_CONFIG2_STRUC, *PEEPROM_NIC_CONFIG2_STRUC; -#endif - -// -// TX_PWR Value valid range 0xFA(-6) ~ 0x24(36) -// -#ifdef RT_BIG_ENDIAN -typedef union _EEPROM_TX_PWR_STRUC { - struct { - CHAR Byte1; // High Byte - CHAR Byte0; // Low Byte - } field; - USHORT word; -} EEPROM_TX_PWR_STRUC, *PEEPROM_TX_PWR_STRUC; -#else -typedef union _EEPROM_TX_PWR_STRUC { - struct { - CHAR Byte0; // Low Byte - CHAR Byte1; // High Byte - } field; - USHORT word; -} EEPROM_TX_PWR_STRUC, *PEEPROM_TX_PWR_STRUC; -#endif - -#ifdef RT_BIG_ENDIAN -typedef union _EEPROM_VERSION_STRUC { - struct { - UCHAR Version; // High Byte - UCHAR FaeReleaseNumber; // Low Byte - } field; - USHORT word; -} EEPROM_VERSION_STRUC, *PEEPROM_VERSION_STRUC; -#else -typedef union _EEPROM_VERSION_STRUC { - struct { - UCHAR FaeReleaseNumber; // Low Byte - UCHAR Version; // High Byte - } field; - USHORT word; -} EEPROM_VERSION_STRUC, *PEEPROM_VERSION_STRUC; -#endif - -#ifdef RT_BIG_ENDIAN -typedef union _EEPROM_LED_STRUC { - struct { - USHORT Rsvd:3; // Reserved - USHORT LedMode:5; // Led mode. - USHORT PolarityGPIO_4:1; // Polarity GPIO#4 setting. - USHORT PolarityGPIO_3:1; // Polarity GPIO#3 setting. - USHORT PolarityGPIO_2:1; // Polarity GPIO#2 setting. - USHORT PolarityGPIO_1:1; // Polarity GPIO#1 setting. - USHORT PolarityGPIO_0:1; // Polarity GPIO#0 setting. - USHORT PolarityACT:1; // Polarity ACT setting. - USHORT PolarityRDY_A:1; // Polarity RDY_A setting. - USHORT PolarityRDY_G:1; // Polarity RDY_G setting. - } field; - USHORT word; -} EEPROM_LED_STRUC, *PEEPROM_LED_STRUC; -#else -typedef union _EEPROM_LED_STRUC { - struct { - USHORT PolarityRDY_G:1; // Polarity RDY_G setting. - USHORT PolarityRDY_A:1; // Polarity RDY_A setting. - USHORT PolarityACT:1; // Polarity ACT setting. - USHORT PolarityGPIO_0:1; // Polarity GPIO#0 setting. - USHORT PolarityGPIO_1:1; // Polarity GPIO#1 setting. - USHORT PolarityGPIO_2:1; // Polarity GPIO#2 setting. - USHORT PolarityGPIO_3:1; // Polarity GPIO#3 setting. - USHORT PolarityGPIO_4:1; // Polarity GPIO#4 setting. - USHORT LedMode:5; // Led mode. - USHORT Rsvd:3; // Reserved - } field; - USHORT word; -} EEPROM_LED_STRUC, *PEEPROM_LED_STRUC; -#endif - -#ifdef RT_BIG_ENDIAN -typedef union _EEPROM_TXPOWER_DELTA_STRUC { - struct { - UCHAR TxPowerEnable:1;// Enable - UCHAR Type:1; // 1: plus the delta value, 0: minus the delta value - UCHAR DeltaValue:6; // Tx Power dalta value (MAX=4) - } field; - UCHAR value; -} EEPROM_TXPOWER_DELTA_STRUC, *PEEPROM_TXPOWER_DELTA_STRUC; -#else -typedef union _EEPROM_TXPOWER_DELTA_STRUC { - struct { - UCHAR DeltaValue:6; // Tx Power dalta value (MAX=4) - UCHAR Type:1; // 1: plus the delta value, 0: minus the delta value - UCHAR TxPowerEnable:1;// Enable - } field; - UCHAR value; -} EEPROM_TXPOWER_DELTA_STRUC, *PEEPROM_TXPOWER_DELTA_STRUC; -#endif - -#endif // __RTMP_CHIP_H__ // diff --git a/drivers/staging/rt3090/rtmp_def.h b/drivers/staging/rt3090/rtmp_def.h deleted file mode 100644 index aeb739d0935caa623ee2604bce68484b93b2c573..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rtmp_def.h +++ /dev/null @@ -1,1650 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rtmp_def.h - - Abstract: - Miniport related definition header - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Paul Lin 08-01-2002 created - John Chang 08-05-2003 add definition for 11g & other drafts -*/ -#ifndef __RTMP_DEF_H__ -#define __RTMP_DEF_H__ - -#include "oid.h" - -#undef AP_WSC_INCLUDED -#undef STA_WSC_INCLUDED -#undef WSC_INCLUDED - - -#ifdef CONFIG_STA_SUPPORT -#endif // CONFIG_STA_SUPPORT // - -#if defined(AP_WSC_INCLUDED) || defined(STA_WSC_INCLUDED) -#define WSC_INCLUDED -#endif -// -// Debug information verbosity: lower values indicate higher urgency -// -#define RT_DEBUG_OFF 0 -#define RT_DEBUG_ERROR 1 -#define RT_DEBUG_WARN 2 -#define RT_DEBUG_TRACE 3 -#define RT_DEBUG_INFO 4 -#define RT_DEBUG_LOUD 5 - -#define NIC_TAG ((ULONG)'0682') -#define NIC_DBG_STRING ("**RT28xx**") - -#ifdef SNMP_SUPPORT -// for snmp -// to get manufacturer OUI, kathy, 2008_0220 -#define ManufacturerOUI_LEN 3 -#define ManufacturerNAME ("Ralink Technology Company.") -#define ResourceTypeIdName ("Ralink_ID") -#endif - - -//#define PACKED - -#define RALINK_2883_VERSION ((UINT32)0x28830300) -#define RALINK_2880E_VERSION ((UINT32)0x28720200) -#define RALINK_3070_VERSION ((UINT32)0x30700200) - -#define MAX_RX_PKT_LEN 1520 - -// -// Entry number for each DMA descriptor ring -// - -#ifdef RTMP_MAC_PCI -#define TX_RING_SIZE 64 //64 -#define MGMT_RING_SIZE 128 -#define RX_RING_SIZE 128 //64 -#define MAX_TX_PROCESS TX_RING_SIZE //8 -#define MAX_DMA_DONE_PROCESS TX_RING_SIZE -#define MAX_TX_DONE_PROCESS TX_RING_SIZE //8 -#define LOCAL_TXBUF_SIZE 2 -#endif // RTMP_MAC_PCI // - -#define PCI_VIRT_TO_PHYS(__Addr) (((UINT32)(__Addr)) & 0x0FFFFFFF) - - -#ifdef MULTIPLE_CARD_SUPPORT -// MC: Multple Cards -#define MAX_NUM_OF_MULTIPLE_CARD 32 -#endif // MULTIPLE_CARD_SUPPORT // - -#define MAX_RX_PROCESS 128 //64 //32 -#define NUM_OF_LOCAL_TXBUF 2 -#define TXD_SIZE 16 -#define TXWI_SIZE 16 -#define RXD_SIZE 16 -#define RXWI_SIZE 16 -// TXINFO_SIZE + TXWI_SIZE + 802.11 Header Size + AMSDU sub frame header -#define TX_DMA_1ST_BUFFER_SIZE 96 // only the 1st physical buffer is pre-allocated -#define MGMT_DMA_BUFFER_SIZE 1536 //2048 -#define RX_BUFFER_AGGRESIZE 3840 //3904 //3968 //4096 //2048 //4096 -#define RX_BUFFER_NORMSIZE 3840 //3904 //3968 //4096 //2048 //4096 -#define TX_BUFFER_NORMSIZE RX_BUFFER_NORMSIZE -#define MAX_FRAME_SIZE 2346 // Maximum 802.11 frame size -#define MAX_AGGREGATION_SIZE 3840 //3904 //3968 //4096 -#define MAX_NUM_OF_TUPLE_CACHE 2 -#define MAX_MCAST_LIST_SIZE 32 -#define MAX_LEN_OF_VENDOR_DESC 64 -//#define MAX_SIZE_OF_MCAST_PSQ (NUM_OF_LOCAL_TXBUF >> 2) // AP won't spend more than 1/4 of total buffers on M/BCAST PSQ -#define MAX_SIZE_OF_MCAST_PSQ 32 - -#define MAX_RX_PROCESS_CNT (RX_RING_SIZE) - - -/* - WMM Note: If memory of your system is not much, please reduce the definition; - or when you do WMM test, the queue for low priority AC will be full, i.e. - TX_RING_SIZE + MAX_PACKETS_IN_QUEUE packets for the AC will be buffered in - WLAN, maybe no any packet buffer can be got in Ethernet driver. - - Sometimes no packet buffer can be got in Ethernet driver, the system will - send flow control packet to the sender to slow down its sending rate. - So no WMM can be saw in the air. -*/ - -/* - Need to use 64 in vxworks for test case WMM A5-T07 - Two dnlink (10Mbps) from a WMM station to a non-WMM station. - If use 256, queue is not enough. - And in rt_main_end.c, clConfig.clNum = RX_RING_SIZE * 3; is changed to - clConfig.clNum = RX_RING_SIZE * 4; -*/ -// TODO: For VxWorks the size is 256. Shall we cahnge the value as 256 for all OS????? -#define MAX_PACKETS_IN_QUEUE (512) //(512) // to pass WMM A5-WPAPSK - -#define MAX_PACKETS_IN_MCAST_PS_QUEUE 32 -#define MAX_PACKETS_IN_PS_QUEUE 128 //32 -#define WMM_NUM_OF_AC 4 /* AC0, AC1, AC2, and AC3 */ - - -#ifdef RTMP_EFUSE_SUPPORT -//2008/09/11:KH add to support efuse<-- -#define MAX_EEPROM_BIN_FILE_SIZE 1024 -#define EFUSE_BUFFER_PATH "/tmp/RT30xxEEPROM.bin" -//2008/09/11:KH add to support efuse--> -#endif // RTMP_EFUSE_SUPPORT // - -// RxFilter -#define STANORMAL 0x17f97 -#define APNORMAL 0x15f97 -#define PSPXLINK 0x17f93 -// -// RTMP_ADAPTER flags -// -#define fRTMP_ADAPTER_MAP_REGISTER 0x00000001 -#define fRTMP_ADAPTER_INTERRUPT_IN_USE 0x00000002 -#define fRTMP_ADAPTER_HARDWARE_ERROR 0x00000004 -#define fRTMP_ADAPTER_SCATTER_GATHER 0x00000008 -#define fRTMP_ADAPTER_SEND_PACKET_ERROR 0x00000010 -#define fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS 0x00000020 -#define fRTMP_ADAPTER_HALT_IN_PROGRESS 0x00000040 -#define fRTMP_ADAPTER_RESET_IN_PROGRESS 0x00000080 -#define fRTMP_ADAPTER_NIC_NOT_EXIST 0x00000100 -#define fRTMP_ADAPTER_TX_RING_ALLOCATED 0x00000200 -#define fRTMP_ADAPTER_REMOVE_IN_PROGRESS 0x00000400 -#define fRTMP_ADAPTER_MIMORATE_INUSED 0x00000800 -#define fRTMP_ADAPTER_RX_RING_ALLOCATED 0x00001000 -#define fRTMP_ADAPTER_INTERRUPT_ACTIVE 0x00002000 -#define fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS 0x00004000 -#define fRTMP_ADAPTER_REASSOC_IN_PROGRESS 0x00008000 -#define fRTMP_ADAPTER_MEDIA_STATE_PENDING 0x00010000 -#define fRTMP_ADAPTER_RADIO_OFF 0x00020000 -#define fRTMP_ADAPTER_BULKOUT_RESET 0x00040000 -#define fRTMP_ADAPTER_BULKIN_RESET 0x00080000 -#define fRTMP_ADAPTER_RDG_ACTIVE 0x00100000 -#define fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE 0x00200000 -#define fRTMP_ADAPTER_SCAN_2040 0x04000000 -#define fRTMP_ADAPTER_RADIO_MEASUREMENT 0x08000000 - -#define fRTMP_ADAPTER_START_UP 0x10000000 //Devive already initialized and enabled Tx/Rx. -#define fRTMP_ADAPTER_MEDIA_STATE_CHANGE 0x20000000 -#define fRTMP_ADAPTER_IDLE_RADIO_OFF 0x40000000 - -// Lock bit for accessing different ring buffers -//#define fRTMP_ADAPTER_TX_RING_BUSY 0x80000000 -//#define fRTMP_ADAPTER_MGMT_RING_BUSY 0x40000000 -//#define fRTMP_ADAPTER_ATIM_RING_BUSY 0x20000000 -//#define fRTMP_ADAPTER_RX_RING_BUSY 0x10000000 - -// Lock bit for accessing different queue -//#define fRTMP_ADAPTER_TX_QUEUE_BUSY 0x08000000 -//#define fRTMP_ADAPTER_MGMT_QUEUE_BUSY 0x04000000 - -// -// STA operation status flags -// -#define fOP_STATUS_INFRA_ON 0x00000001 -#define fOP_STATUS_ADHOC_ON 0x00000002 -#define fOP_STATUS_BG_PROTECTION_INUSED 0x00000004 -#define fOP_STATUS_SHORT_SLOT_INUSED 0x00000008 -#define fOP_STATUS_SHORT_PREAMBLE_INUSED 0x00000010 -#define fOP_STATUS_RECEIVE_DTIM 0x00000020 -//#define fOP_STATUS_TX_RATE_SWITCH_ENABLED 0x00000040 -#define fOP_STATUS_MEDIA_STATE_CONNECTED 0x00000080 -#define fOP_STATUS_WMM_INUSED 0x00000100 -#define fOP_STATUS_AGGREGATION_INUSED 0x00000200 -#define fOP_STATUS_DOZE 0x00000400 // debug purpose -#define fOP_STATUS_PIGGYBACK_INUSED 0x00000800 // piggy-back, and aggregation -#define fOP_STATUS_APSD_INUSED 0x00001000 -#define fOP_STATUS_TX_AMSDU_INUSED 0x00002000 -#define fOP_STATUS_MAX_RETRY_ENABLED 0x00004000 -#define fOP_STATUS_WAKEUP_NOW 0x00008000 -#define fOP_STATUS_PCIE_DEVICE 0x00020000 - -// -// RTMP_ADAPTER PSFlags : related to advanced power save. -// -// Indicate whether driver can go to sleep mode from now. This flag is useful AFTER link up -#define fRTMP_PS_CAN_GO_SLEEP 0x00000001 -// Indicate whether driver has issue a LinkControl command to PCIe L1 -#define fRTMP_PS_SET_PCI_CLK_OFF_COMMAND 0x00000002 -// Indicate driver should disable kick off hardware to send packets from now. -#define fRTMP_PS_DISABLE_TX 0x00000004 -// Indicate driver should IMMEDIATELY fo to sleep after receiving AP's beacon in which doesn't indicate unicate nor multicast packets for me -//. This flag is used ONLY in RTMPHandleRxDoneInterrupt routine. -#define fRTMP_PS_GO_TO_SLEEP_NOW 0x00000008 -#define fRTMP_PS_TOGGLE_L1 0x00000010 // Use Toggle L1 mechanism for rt28xx PCIe -#ifdef RT3090 -#define WAKE_MCU_CMD 0x31 -#define SLEEP_MCU_CMD 0x30 -#define RFOFF_MCU_CMD 0x35 -#endif // RT3090 // -#ifdef DOT11N_DRAFT3 -#define fOP_STATUS_SCAN_2040 0x00040000 -#endif // DOT11N_DRAFT3 // - -#define CCKSETPROTECT 0x1 -#define OFDMSETPROTECT 0x2 -#define MM20SETPROTECT 0x4 -#define MM40SETPROTECT 0x8 -#define GF20SETPROTECT 0x10 -#define GR40SETPROTECT 0x20 -#define ALLN_SETPROTECT (GR40SETPROTECT | GF20SETPROTECT | MM40SETPROTECT | MM20SETPROTECT) - -// -// AP's client table operation status flags -// -#define fCLIENT_STATUS_WMM_CAPABLE 0x00000001 // CLIENT can parse QOS DATA frame -#define fCLIENT_STATUS_AGGREGATION_CAPABLE 0x00000002 // CLIENT can receive Ralink's proprietary TX aggregation frame -#define fCLIENT_STATUS_PIGGYBACK_CAPABLE 0x00000004 // CLIENT support piggy-back -#define fCLIENT_STATUS_AMSDU_INUSED 0x00000008 -#define fCLIENT_STATUS_SGI20_CAPABLE 0x00000010 -#define fCLIENT_STATUS_SGI40_CAPABLE 0x00000020 -#define fCLIENT_STATUS_TxSTBC_CAPABLE 0x00000040 -#define fCLIENT_STATUS_RxSTBC_CAPABLE 0x00000080 -#define fCLIENT_STATUS_HTC_CAPABLE 0x00000100 -#define fCLIENT_STATUS_RDG_CAPABLE 0x00000200 -#define fCLIENT_STATUS_MCSFEEDBACK_CAPABLE 0x00000400 -#define fCLIENT_STATUS_APSD_CAPABLE 0x00000800 /* UAPSD STATION */ - -#ifdef DOT11N_DRAFT3 -#define fCLIENT_STATUS_BSSCOEXIST_CAPABLE 0x00001000 -#endif // DOT11N_DRAFT3 // - -#define fCLIENT_STATUS_RALINK_CHIPSET 0x00100000 -// -// STA configuration flags -// -//#define fSTA_CFG_ENABLE_TX_BURST 0x00000001 - -// 802.11n Operating Mode Definition. 0-3 also used in ASICUPdateProtect switch case -#define HT_NO_PROTECT 0 -#define HT_LEGACY_PROTECT 1 -#define HT_40_PROTECT 2 -#define HT_2040_PROTECT 3 -#define HT_RTSCTS_6M 7 -//following is our own definition in order to turn on our ASIC protection register in INFRASTRUCTURE. -#define HT_ATHEROS 8 // rt2860c has problem with atheros chip. we need to turn on RTS/CTS . -#define HT_FORCERTSCTS 9 // Force turn on RTS/CTS first. then go to evaluate if this force RTS is necessary. - -// -// RX Packet Filter control flags. Apply on pAd->PacketFilter -// -#define fRX_FILTER_ACCEPT_DIRECT NDIS_PACKET_TYPE_DIRECTED -#define fRX_FILTER_ACCEPT_MULTICAST NDIS_PACKET_TYPE_MULTICAST -#define fRX_FILTER_ACCEPT_BROADCAST NDIS_PACKET_TYPE_BROADCAST -#define fRX_FILTER_ACCEPT_ALL_MULTICAST NDIS_PACKET_TYPE_ALL_MULTICAST -#define fRX_FILTER_ACCEPT_PROMISCUOUS NDIS_PACKET_TYPE_PROMISCUOUS - -// -// Error code section -// -// NDIS_ERROR_CODE_ADAPTER_NOT_FOUND -#define ERRLOG_READ_PCI_SLOT_FAILED 0x00000101L -#define ERRLOG_WRITE_PCI_SLOT_FAILED 0x00000102L -#define ERRLOG_VENDOR_DEVICE_NOMATCH 0x00000103L - -// NDIS_ERROR_CODE_ADAPTER_DISABLED -#define ERRLOG_BUS_MASTER_DISABLED 0x00000201L - -// NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION -#define ERRLOG_INVALID_SPEED_DUPLEX 0x00000301L -#define ERRLOG_SET_SECONDARY_FAILED 0x00000302L - -// NDIS_ERROR_CODE_OUT_OF_RESOURCES -#define ERRLOG_OUT_OF_MEMORY 0x00000401L -#define ERRLOG_OUT_OF_SHARED_MEMORY 0x00000402L -#define ERRLOG_OUT_OF_MAP_REGISTERS 0x00000403L -#define ERRLOG_OUT_OF_BUFFER_POOL 0x00000404L -#define ERRLOG_OUT_OF_NDIS_BUFFER 0x00000405L -#define ERRLOG_OUT_OF_PACKET_POOL 0x00000406L -#define ERRLOG_OUT_OF_NDIS_PACKET 0x00000407L -#define ERRLOG_OUT_OF_LOOKASIDE_MEMORY 0x00000408L - -// NDIS_ERROR_CODE_HARDWARE_FAILURE -#define ERRLOG_SELFTEST_FAILED 0x00000501L -#define ERRLOG_INITIALIZE_ADAPTER 0x00000502L -#define ERRLOG_REMOVE_MINIPORT 0x00000503L - -// NDIS_ERROR_CODE_RESOURCE_CONFLICT -#define ERRLOG_MAP_IO_SPACE 0x00000601L -#define ERRLOG_QUERY_ADAPTER_RESOURCES 0x00000602L -#define ERRLOG_NO_IO_RESOURCE 0x00000603L -#define ERRLOG_NO_INTERRUPT_RESOURCE 0x00000604L -#define ERRLOG_NO_MEMORY_RESOURCE 0x00000605L - - -// WDS definition -#define MAX_WDS_ENTRY 4 -#define WDS_PAIRWISE_KEY_OFFSET 60 // WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table - -#define WDS_DISABLE_MODE 0 -#define WDS_RESTRICT_MODE 1 -#define WDS_BRIDGE_MODE 2 -#define WDS_REPEATER_MODE 3 -#define WDS_LAZY_MODE 4 - - -#define MAX_MESH_NUM 0 - -#define MAX_APCLI_NUM 0 -#ifdef APCLI_SUPPORT -#undef MAX_APCLI_NUM -#define MAX_APCLI_NUM 1 -#endif // APCLI_SUPPORT // - -#define MAX_MBSSID_NUM 1 -#ifdef MBSS_SUPPORT -#undef MAX_MBSSID_NUM -#define MAX_MBSSID_NUM (8 - MAX_MESH_NUM - MAX_APCLI_NUM) -#endif // MBSS_SUPPORT // - -/* sanity check for apidx */ -#define MBSS_MR_APIDX_SANITY_CHECK(apidx) \ - { if (apidx > MAX_MBSSID_NUM) { \ - DBGPRINT(RT_DEBUG_ERROR, ("%s> Error! apidx = %d > MAX_MBSSID_NUM!\n", __FUNCTION__, apidx)); \ - apidx = MAIN_MBSSID; } } - -#define VALID_WCID(_wcid) ((_wcid) > 0 && (_wcid) < MAX_LEN_OF_MAC_TABLE ) - -#define MAIN_MBSSID 0 -#define FIRST_MBSSID 1 - - -#define MAX_BEACON_SIZE 512 -// If the MAX_MBSSID_NUM is larger than 6, -// it shall reserve some WCID space(wcid 222~253) for beacon frames. -// - these wcid 238~253 are reserved for beacon#6(ra6). -// - these wcid 222~237 are reserved for beacon#7(ra7). -#if defined(MAX_MBSSID_NUM) && (MAX_MBSSID_NUM == 8) -#define HW_RESERVED_WCID 222 -#elif defined(MAX_MBSSID_NUM) && (MAX_MBSSID_NUM == 7) -#define HW_RESERVED_WCID 238 -#else -#define HW_RESERVED_WCID 255 -#endif - -// Then dedicate wcid of DFS and Carrier-Sense. -#define DFS_CTS_WCID (HW_RESERVED_WCID - 1) -#define CS_CTS_WCID (HW_RESERVED_WCID - 2) -#define LAST_SPECIFIC_WCID (HW_RESERVED_WCID - 2) - -// If MAX_MBSSID_NUM is 8, the maximum available wcid for the associated STA is 211. -// If MAX_MBSSID_NUM is 7, the maximum available wcid for the associated STA is 228. -#define MAX_AVAILABLE_CLIENT_WCID (LAST_SPECIFIC_WCID - MAX_MBSSID_NUM - 1) - -// TX need WCID to find Cipher Key -// these wcid 212 ~ 219 are reserved for bc/mc packets if MAX_MBSSID_NUM is 8. -#define GET_GroupKey_WCID(__wcid, __bssidx) \ - { \ - __wcid = LAST_SPECIFIC_WCID - (MAX_MBSSID_NUM) + __bssidx; \ - } - -#define IsGroupKeyWCID(__wcid) (((__wcid) < LAST_SPECIFIC_WCID) && ((__wcid) >= (LAST_SPECIFIC_WCID - (MAX_MBSSID_NUM)))) - - -// definition to support multiple BSSID -#define BSS0 0 -#define BSS1 1 -#define BSS2 2 -#define BSS3 3 -#define BSS4 4 -#define BSS5 5 -#define BSS6 6 -#define BSS7 7 - - -//============================================================ -// Length definitions -#define PEER_KEY_NO 2 -#define MAC_ADDR_LEN 6 -#define TIMESTAMP_LEN 8 -#define MAX_LEN_OF_SUPPORTED_RATES MAX_LENGTH_OF_SUPPORT_RATES // 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 -#define MAX_NUM_OF_REGULATORY_CLASS 16 -#define MAX_LEN_OF_KEY 32 // 32 octets == 256 bits, Redefine for WPA -#define MAX_NUM_OF_CHANNELS MAX_NUM_OF_CHS // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination -#define MAX_NUM_OF_11JCHANNELS 20 // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination -#define MAX_LEN_OF_SSID 32 -#define CIPHER_TEXT_LEN 128 -#define HASH_TABLE_SIZE 256 -#define MAX_VIE_LEN 1024 // New for WPA cipher suite variable IE sizes. -#define MAX_SUPPORT_MCS 32 -#define MAX_NUM_OF_BBP_LATCH 140 -//============================================================ -// ASIC WCID Table definition. -//============================================================ -#define BSSID_WCID 1 // in infra mode, always put bssid with this WCID -#define MCAST_WCID 0x0 -#define BSS0Mcast_WCID 0x0 -#define BSS1Mcast_WCID 0xf8 -#define BSS2Mcast_WCID 0xf9 -#define BSS3Mcast_WCID 0xfa -#define BSS4Mcast_WCID 0xfb -#define BSS5Mcast_WCID 0xfc -#define BSS6Mcast_WCID 0xfd -#define BSS7Mcast_WCID 0xfe -#define RESERVED_WCID 0xff - -#define MAX_NUM_OF_ACL_LIST MAX_NUMBER_OF_ACL - -#define MAX_LEN_OF_MAC_TABLE MAX_NUMBER_OF_MAC // if MAX_MBSSID_NUM is 8, this value can't be larger than 211 - -#if MAX_LEN_OF_MAC_TABLE>MAX_AVAILABLE_CLIENT_WCID -#error MAX_LEN_OF_MAC_TABLE can not be larger than MAX_AVAILABLE_CLIENT_WCID!!!! -#endif - -#define MAX_NUM_OF_WDS_LINK_PERBSSID 3 -#define MAX_NUM_OF_WDS_LINK (MAX_NUM_OF_WDS_LINK_PERBSSID*MAX_MBSSID_NUM) -#define MAX_NUM_OF_EVENT MAX_NUMBER_OF_EVENT -#define WDS_LINK_START_WCID (MAX_LEN_OF_MAC_TABLE-1) - -#define NUM_OF_TID 8 -#define MAX_AID_BA 4 -#define MAX_LEN_OF_BA_REC_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2)// (NUM_OF_TID*MAX_AID_BA + 32) //Block ACK recipient -#define MAX_LEN_OF_BA_ORI_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2)// (NUM_OF_TID*MAX_AID_BA + 32) // Block ACK originator -#define MAX_LEN_OF_BSS_TABLE 64 -#define MAX_REORDERING_MPDU_NUM 512 - -// key related definitions -#define SHARE_KEY_NUM 4 -#define MAX_LEN_OF_SHARE_KEY 16 // byte count -#define MAX_LEN_OF_PEER_KEY 16 // byte count -#define PAIRWISE_KEY_NUM 64 // in MAC ASIC pairwise key table -#define GROUP_KEY_NUM 4 -#define PMK_LEN 32 -#define WDS_PAIRWISE_KEY_OFFSET 60 // WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table -#define PMKID_NO 4 // Number of PMKID saved supported -#define MAX_LEN_OF_MLME_BUFFER 2048 - -// power status related definitions -#define PWR_ACTIVE 0 -#define PWR_SAVE 1 -#define PWR_MMPS 2 //MIMO power save -//#define PWR_UNKNOWN 2 - -// Auth and Assoc mode related definitions -#define AUTH_MODE_OPEN 0x00 -#define AUTH_MODE_KEY 0x01 -//#define AUTH_MODE_AUTO_SWITCH 0x03 -//#define AUTH_MODE_DEAUTH 0x04 -//#define AUTH_MODE_UPLAYER 0x05 // reserved for 802.11i use - -// BSS Type definitions -#define BSS_ADHOC 0 // = Ndis802_11IBSS -#define BSS_INFRA 1 // = Ndis802_11Infrastructure -#define BSS_ANY 2 // = Ndis802_11AutoUnknown -#define BSS_MONITOR 3 // = Ndis802_11Monitor - - -// Reason code definitions -#define REASON_RESERVED 0 -#define REASON_UNSPECIFY 1 -#define REASON_NO_LONGER_VALID 2 -#define REASON_DEAUTH_STA_LEAVING 3 -#define REASON_DISASSOC_INACTIVE 4 -#define REASON_DISASSPC_AP_UNABLE 5 -#define REASON_CLS2ERR 6 -#define REASON_CLS3ERR 7 -#define REASON_DISASSOC_STA_LEAVING 8 -#define REASON_STA_REQ_ASSOC_NOT_AUTH 9 -#define REASON_INVALID_IE 13 -#define REASON_MIC_FAILURE 14 -#define REASON_4_WAY_TIMEOUT 15 -#define REASON_GROUP_KEY_HS_TIMEOUT 16 -#define REASON_IE_DIFFERENT 17 -#define REASON_MCIPHER_NOT_VALID 18 -#define REASON_UCIPHER_NOT_VALID 19 -#define REASON_AKMP_NOT_VALID 20 -#define REASON_UNSUPPORT_RSNE_VER 21 -#define REASON_INVALID_RSNE_CAP 22 -#define REASON_8021X_AUTH_FAIL 23 -#define REASON_CIPHER_SUITE_REJECTED 24 -#define REASON_DECLINED 37 - -#define REASON_QOS_UNSPECIFY 32 -#define REASON_QOS_LACK_BANDWIDTH 33 -#define REASON_POOR_CHANNEL_CONDITION 34 -#define REASON_QOS_OUTSIDE_TXOP_LIMITION 35 -#define REASON_QOS_QSTA_LEAVING_QBSS 36 -#define REASON_QOS_UNWANTED_MECHANISM 37 -#define REASON_QOS_MECH_SETUP_REQUIRED 38 -#define REASON_QOS_REQUEST_TIMEOUT 39 -#define REASON_QOS_CIPHER_NOT_SUPPORT 45 - -// Status code definitions -#define MLME_SUCCESS 0 -#define MLME_UNSPECIFY_FAIL 1 -#define MLME_CANNOT_SUPPORT_CAP 10 -#define MLME_REASSOC_DENY_ASSOC_EXIST 11 -#define MLME_ASSOC_DENY_OUT_SCOPE 12 -#define MLME_ALG_NOT_SUPPORT 13 -#define MLME_SEQ_NR_OUT_OF_SEQUENCE 14 -#define MLME_REJ_CHALLENGE_FAILURE 15 -#define MLME_REJ_TIMEOUT 16 -#define MLME_ASSOC_REJ_UNABLE_HANDLE_STA 17 -#define MLME_ASSOC_REJ_DATA_RATE 18 - -#define MLME_ASSOC_REJ_NO_EXT_RATE 22 -#define MLME_ASSOC_REJ_NO_EXT_RATE_PBCC 23 -#define MLME_ASSOC_REJ_NO_CCK_OFDM 24 - -#define MLME_QOS_UNSPECIFY 32 -#define MLME_REQUEST_DECLINED 37 -#define MLME_REQUEST_WITH_INVALID_PARAM 38 -#define MLME_INVALID_GROUP_CIPHER 41 -#define MLME_INVALID_PAIRWISE_CIPHER 42 -#define MLME_INVALID_AKMP 43 -#define MLME_DLS_NOT_ALLOW_IN_QBSS 48 -#define MLME_DEST_STA_NOT_IN_QBSS 49 -#define MLME_DEST_STA_IS_NOT_A_QSTA 50 - -#define MLME_INVALID_FORMAT 0x51 -#define MLME_FAIL_NO_RESOURCE 0x52 -#define MLME_STATE_MACHINE_REJECT 0x53 -#define MLME_MAC_TABLE_FAIL 0x54 - -// IE code -#define IE_SSID 0 -#define IE_SUPP_RATES 1 -#define IE_FH_PARM 2 -#define IE_DS_PARM 3 -#define IE_CF_PARM 4 -#define IE_TIM 5 -#define IE_IBSS_PARM 6 -#define IE_COUNTRY 7 // 802.11d -#define IE_802_11D_REQUEST 10 // 802.11d -#define IE_QBSS_LOAD 11 // 802.11e d9 -#define IE_EDCA_PARAMETER 12 // 802.11e d9 -#define IE_TSPEC 13 // 802.11e d9 -#define IE_TCLAS 14 // 802.11e d9 -#define IE_SCHEDULE 15 // 802.11e d9 -#define IE_CHALLENGE_TEXT 16 -#define IE_POWER_CONSTRAINT 32 // 802.11h d3.3 -#define IE_POWER_CAPABILITY 33 // 802.11h d3.3 -#define IE_TPC_REQUEST 34 // 802.11h d3.3 -#define IE_TPC_REPORT 35 // 802.11h d3.3 -#define IE_SUPP_CHANNELS 36 // 802.11h d3.3 -#define IE_CHANNEL_SWITCH_ANNOUNCEMENT 37 // 802.11h d3.3 -#define IE_MEASUREMENT_REQUEST 38 // 802.11h d3.3 -#define IE_MEASUREMENT_REPORT 39 // 802.11h d3.3 -#define IE_QUIET 40 // 802.11h d3.3 -#define IE_IBSS_DFS 41 // 802.11h d3.3 -#define IE_ERP 42 // 802.11g -#define IE_TS_DELAY 43 // 802.11e d9 -#define IE_TCLAS_PROCESSING 44 // 802.11e d9 -#define IE_QOS_CAPABILITY 46 // 802.11e d6 -#define IE_HT_CAP 45 // 802.11n d1. HT CAPABILITY. ELEMENT ID TBD -#define IE_AP_CHANNEL_REPORT 51 // 802.11k d6 -#define IE_HT_CAP2 52 // 802.11n d1. HT CAPABILITY. ELEMENT ID TBD -#define IE_RSN 48 // 802.11i d3.0 -#define IE_WPA2 48 // WPA2 -#define IE_EXT_SUPP_RATES 50 // 802.11g -#define IE_SUPP_REG_CLASS 59 // 802.11y. Supported regulatory classes. -#define IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT 60 // 802.11n -#define IE_ADD_HT 61 // 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD -#define IE_ADD_HT2 53 // 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD - - -// For 802.11n D3.03 -//#define IE_NEW_EXT_CHA_OFFSET 62 // 802.11n d1. New extension channel offset elemet -#define IE_SECONDARY_CH_OFFSET 62 // 802.11n D3.03 Secondary Channel Offset element -#define IE_WAPI 68 // WAPI information element -#define IE_2040_BSS_COEXIST 72 // 802.11n D3.0.3 -#define IE_2040_BSS_INTOLERANT_REPORT 73 // 802.11n D3.03 -#define IE_OVERLAPBSS_SCAN_PARM 74 // 802.11n D3.03 -#define IE_EXT_CAPABILITY 127 // 802.11n D3.03 - - -#define IE_WPA 221 // WPA -#define IE_VENDOR_SPECIFIC 221 // Wifi WMM (WME) - -#define OUI_BROADCOM_HT 51 // -#define OUI_BROADCOM_HTADD 52 // -#define OUI_PREN_HT_CAP 51 // -#define OUI_PREN_ADD_HT 52 // - -// CCX information -#define IE_AIRONET_CKIP 133 // CCX1.0 ID 85H for CKIP -#define IE_AP_TX_POWER 150 // CCX 2.0 for AP transmit power -#define IE_MEASUREMENT_CAPABILITY 221 // CCX 2.0 -#define IE_CCX_V2 221 -#define IE_AIRONET_IPADDRESS 149 // CCX ID 95H for IP Address -#define IE_AIRONET_CCKMREASSOC 156 // CCX ID 9CH for CCKM Reassociation Request element -#define CKIP_NEGOTIATION_LENGTH 30 -#define AIRONET_IPADDRESS_LENGTH 10 -#define AIRONET_CCKMREASSOC_LENGTH 24 - -// ======================================================== -// MLME state machine definition -// ======================================================== - -// STA MLME state mahcines -#define ASSOC_STATE_MACHINE 1 -#define AUTH_STATE_MACHINE 2 -#define AUTH_RSP_STATE_MACHINE 3 -#define SYNC_STATE_MACHINE 4 -#define MLME_CNTL_STATE_MACHINE 5 -#define WPA_PSK_STATE_MACHINE 6 -//#define LEAP_STATE_MACHINE 7 -#define AIRONET_STATE_MACHINE 8 -#define ACTION_STATE_MACHINE 9 - -// AP MLME state machines -#define AP_ASSOC_STATE_MACHINE 11 -#define AP_AUTH_STATE_MACHINE 12 -#define AP_SYNC_STATE_MACHINE 14 -#define AP_CNTL_STATE_MACHINE 15 -#define WSC_STATE_MACHINE 17 -#define WSC_UPNP_STATE_MACHINE 18 - - -#define WPA_STATE_MACHINE 23 - - -#ifdef QOS_DLS_SUPPORT -#define DLS_STATE_MACHINE 26 -#endif // QOS_DLS_SUPPORT // - -// -// STA's CONTROL/CONNECT state machine: states, events, total function # -// -#define CNTL_IDLE 0 -#define CNTL_WAIT_DISASSOC 1 -#define CNTL_WAIT_JOIN 2 -#define CNTL_WAIT_REASSOC 3 -#define CNTL_WAIT_START 4 -#define CNTL_WAIT_AUTH 5 -#define CNTL_WAIT_ASSOC 6 -#define CNTL_WAIT_AUTH2 7 -#define CNTL_WAIT_OID_LIST_SCAN 8 -#define CNTL_WAIT_OID_DISASSOC 9 - -#define MT2_ASSOC_CONF 34 -#define MT2_AUTH_CONF 35 -#define MT2_DEAUTH_CONF 36 -#define MT2_DISASSOC_CONF 37 -#define MT2_REASSOC_CONF 38 -#define MT2_PWR_MGMT_CONF 39 -#define MT2_JOIN_CONF 40 -#define MT2_SCAN_CONF 41 -#define MT2_START_CONF 42 -#define MT2_GET_CONF 43 -#define MT2_SET_CONF 44 -#define MT2_RESET_CONF 45 -#define MT2_FT_OTD_CONF 46 -#define MT2_MLME_ROAMING_REQ 52 - -#define CNTL_FUNC_SIZE 1 - -// -// STA's ASSOC state machine: states, events, total function # -// -#define ASSOC_IDLE 0 -#define ASSOC_WAIT_RSP 1 -#define REASSOC_WAIT_RSP 2 -#define DISASSOC_WAIT_RSP 3 -#define MAX_ASSOC_STATE 4 - -#define ASSOC_MACHINE_BASE 0 -#define MT2_MLME_ASSOC_REQ 0 -#define MT2_MLME_REASSOC_REQ 1 -#define MT2_MLME_DISASSOC_REQ 2 -#define MT2_PEER_DISASSOC_REQ 3 -#define MT2_PEER_ASSOC_REQ 4 -#define MT2_PEER_ASSOC_RSP 5 -#define MT2_PEER_REASSOC_REQ 6 -#define MT2_PEER_REASSOC_RSP 7 -#define MT2_DISASSOC_TIMEOUT 8 -#define MT2_ASSOC_TIMEOUT 9 -#define MT2_REASSOC_TIMEOUT 10 -#define MAX_ASSOC_MSG 11 - -#define ASSOC_FUNC_SIZE (MAX_ASSOC_STATE * MAX_ASSOC_MSG) - -// -// ACT state machine: states, events, total function # -// -#define ACT_IDLE 0 -#define MAX_ACT_STATE 1 - -#define ACT_MACHINE_BASE 0 - -//Those PEER_xx_CATE number is based on real Categary value in IEEE spec. Please don'es modify it by your self. -//Category -#define MT2_PEER_SPECTRUM_CATE 0 -#define MT2_PEER_QOS_CATE 1 -#define MT2_PEER_DLS_CATE 2 -#define MT2_PEER_BA_CATE 3 -#define MT2_PEER_PUBLIC_CATE 4 -#define MT2_PEER_RM_CATE 5 -/* "FT_CATEGORY_BSS_TRANSITION equal to 6" is defined file of "dot11r_ft.h" */ -#define MT2_PEER_HT_CATE 7 // 7.4.7 -#define MAX_PEER_CATE_MSG 7 - - -#define MT2_MLME_ADD_BA_CATE 8 -#define MT2_MLME_ORI_DELBA_CATE 9 -#define MT2_MLME_REC_DELBA_CATE 10 -#define MT2_MLME_QOS_CATE 11 -#define MT2_MLME_DLS_CATE 12 -#define MT2_ACT_INVALID 13 - -#define MAX_ACT_MSG 14 - - -//Category field -#define CATEGORY_SPECTRUM 0 -#define CATEGORY_QOS 1 -#define CATEGORY_DLS 2 -#define CATEGORY_BA 3 -#define CATEGORY_PUBLIC 4 -#define CATEGORY_RM 5 -#define CATEGORY_HT 7 - - -// DLS Action frame definition -#define ACTION_DLS_REQUEST 0 -#define ACTION_DLS_RESPONSE 1 -#define ACTION_DLS_TEARDOWN 2 - -//Spectrum Action field value 802.11h 7.4.1 -#define SPEC_MRQ 0 // Request -#define SPEC_MRP 1 //Report -#define SPEC_TPCRQ 2 -#define SPEC_TPCRP 3 -#define SPEC_CHANNEL_SWITCH 4 - - -//BA Action field value -#define ADDBA_REQ 0 -#define ADDBA_RESP 1 -#define DELBA 2 - -//Public's Action field value in Public Category. Some in 802.11y and some in 11n -#define ACTION_BSS_2040_COEXIST 0 // 11n -#define ACTION_DSE_ENABLEMENT 1 // 11y D9.0 -#define ACTION_DSE_DEENABLEMENT 2 // 11y D9.0 -#define ACTION_DSE_REG_LOCATION_ANNOUNCE 3 // 11y D9.0 -#define ACTION_EXT_CH_SWITCH_ANNOUNCE 4 // 11y D9.0 -#define ACTION_DSE_MEASUREMENT_REQ 5 // 11y D9.0 -#define ACTION_DSE_MEASUREMENT_REPORT 6 // 11y D9.0 -#define ACTION_MEASUREMENT_PILOT_ACTION 7 // 11y D9.0 -#define ACTION_DSE_POWER_CONSTRAINT 8 // 11y D9.0 - - -//HT Action field value -#define NOTIFY_BW_ACTION 0 -#define SMPS_ACTION 1 -#define PSMP_ACTION 2 -#define SETPCO_ACTION 3 -#define MIMO_CHA_MEASURE_ACTION 4 -#define MIMO_N_BEACONFORM 5 -#define MIMO_BEACONFORM 6 -#define ANTENNA_SELECT 7 -#define HT_INFO_EXCHANGE 8 - -#define ACT_FUNC_SIZE (MAX_ACT_STATE * MAX_ACT_MSG) -// -// STA's AUTHENTICATION state machine: states, evvents, total function # -// -#define AUTH_REQ_IDLE 0 -#define AUTH_WAIT_SEQ2 1 -#define AUTH_WAIT_SEQ4 2 -#define MAX_AUTH_STATE 3 - -#define AUTH_MACHINE_BASE 0 -#define MT2_MLME_AUTH_REQ 0 -#define MT2_PEER_AUTH_EVEN 1 -#define MT2_AUTH_TIMEOUT 2 -#define MAX_AUTH_MSG 3 - -#define AUTH_FUNC_SIZE (MAX_AUTH_STATE * MAX_AUTH_MSG) - -// -// STA's AUTH_RSP state machine: states, events, total function # -// -#define AUTH_RSP_IDLE 0 -#define AUTH_RSP_WAIT_CHAL 1 -#define MAX_AUTH_RSP_STATE 2 - -#define AUTH_RSP_MACHINE_BASE 0 -#define MT2_AUTH_CHALLENGE_TIMEOUT 0 -#define MT2_PEER_AUTH_ODD 1 -#define MT2_PEER_DEAUTH 2 -#define MAX_AUTH_RSP_MSG 3 - -#define AUTH_RSP_FUNC_SIZE (MAX_AUTH_RSP_STATE * MAX_AUTH_RSP_MSG) - -// -// STA's SYNC state machine: states, events, total function # -// -#define SYNC_IDLE 0 // merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state -#define JOIN_WAIT_BEACON 1 -#define SCAN_LISTEN 2 -#define MAX_SYNC_STATE 3 - -#define SYNC_MACHINE_BASE 0 -#define MT2_MLME_SCAN_REQ 0 -#define MT2_MLME_JOIN_REQ 1 -#define MT2_MLME_START_REQ 2 -#define MT2_PEER_BEACON 3 -#define MT2_PEER_PROBE_RSP 4 -#define MT2_PEER_ATIM 5 -#define MT2_SCAN_TIMEOUT 6 -#define MT2_BEACON_TIMEOUT 7 -#define MT2_ATIM_TIMEOUT 8 -#define MT2_PEER_PROBE_REQ 9 -#define MAX_SYNC_MSG 10 - -#define SYNC_FUNC_SIZE (MAX_SYNC_STATE * MAX_SYNC_MSG) - -//Messages for the DLS state machine -#define DLS_IDLE 0 -#define MAX_DLS_STATE 1 - -#define DLS_MACHINE_BASE 0 -#define MT2_MLME_DLS_REQ 0 -#define MT2_PEER_DLS_REQ 1 -#define MT2_PEER_DLS_RSP 2 -#define MT2_MLME_DLS_TEAR_DOWN 3 -#define MT2_PEER_DLS_TEAR_DOWN 4 -#define MAX_DLS_MSG 5 - -#define DLS_FUNC_SIZE (MAX_DLS_STATE * MAX_DLS_MSG) - -// -// WSC State machine: states, events, total function # -// - -// -// AP's CONTROL/CONNECT state machine: states, events, total function # -// -#define AP_CNTL_FUNC_SIZE 1 - -// -// AP's ASSOC state machine: states, events, total function # -// -#define AP_ASSOC_IDLE 0 -#define AP_MAX_ASSOC_STATE 1 - -#define AP_ASSOC_MACHINE_BASE 0 -#define APMT2_MLME_DISASSOC_REQ 0 -#define APMT2_PEER_DISASSOC_REQ 1 -#define APMT2_PEER_ASSOC_REQ 2 -#define APMT2_PEER_REASSOC_REQ 3 -#define APMT2_CLS3ERR 4 -#define AP_MAX_ASSOC_MSG 5 - -#define AP_ASSOC_FUNC_SIZE (AP_MAX_ASSOC_STATE * AP_MAX_ASSOC_MSG) - -// -// AP's AUTHENTICATION state machine: states, events, total function # -// -#define AP_AUTH_REQ_IDLE 0 -#define AP_MAX_AUTH_STATE 1 - -#define AP_AUTH_MACHINE_BASE 0 -#define APMT2_MLME_DEAUTH_REQ 0 -#define APMT2_CLS2ERR 1 -#define APMT2_PEER_DEAUTH 2 -#define APMT2_PEER_AUTH_REQ 3 -#define APMT2_PEER_AUTH_CONFIRM 4 -#define AP_MAX_AUTH_MSG 5 - -#define AP_AUTH_FUNC_SIZE (AP_MAX_AUTH_STATE * AP_MAX_AUTH_MSG) - -// -// AP's SYNC state machine: states, events, total function # -// -#define AP_SYNC_IDLE 0 -#define AP_SCAN_LISTEN 1 -#define AP_MAX_SYNC_STATE 2 - -#define AP_SYNC_MACHINE_BASE 0 -#define APMT2_PEER_PROBE_REQ 0 -#define APMT2_PEER_BEACON 1 -#define APMT2_MLME_SCAN_REQ 2 -#define APMT2_PEER_PROBE_RSP 3 -#define APMT2_SCAN_TIMEOUT 4 -#define APMT2_MLME_SCAN_CNCL 5 -#define AP_MAX_SYNC_MSG 6 - -#define AP_SYNC_FUNC_SIZE (AP_MAX_SYNC_STATE * AP_MAX_SYNC_MSG) - -// -// Common WPA state machine: states, events, total function # -// -#define WPA_PTK 0 -#define MAX_WPA_PTK_STATE 1 - -#define WPA_MACHINE_BASE 0 -#define MT2_EAPPacket 0 -#define MT2_EAPOLStart 1 -#define MT2_EAPOLLogoff 2 -#define MT2_EAPOLKey 3 -#define MT2_EAPOLASFAlert 4 -#define MAX_WPA_MSG 5 - -#define WPA_FUNC_SIZE (MAX_WPA_PTK_STATE * MAX_WPA_MSG) - -#ifdef APCLI_SUPPORT -//ApCli authentication state machine -#define APCLI_AUTH_REQ_IDLE 0 -#define APCLI_AUTH_WAIT_SEQ2 1 -#define APCLI_AUTH_WAIT_SEQ4 2 -#define APCLI_MAX_AUTH_STATE 3 - -#define APCLI_AUTH_MACHINE_BASE 0 -#define APCLI_MT2_MLME_AUTH_REQ 0 -#define APCLI_MT2_MLME_DEAUTH_REQ 1 -#define APCLI_MT2_PEER_AUTH_EVEN 2 -#define APCLI_MT2_PEER_DEAUTH 3 -#define APCLI_MT2_AUTH_TIMEOUT 4 -#define APCLI_MAX_AUTH_MSG 5 - -#define APCLI_AUTH_FUNC_SIZE (APCLI_MAX_AUTH_STATE * APCLI_MAX_AUTH_MSG) - -//ApCli association state machine -#define APCLI_ASSOC_IDLE 0 -#define APCLI_ASSOC_WAIT_RSP 1 -#define APCLI_MAX_ASSOC_STATE 2 - -#define APCLI_ASSOC_MACHINE_BASE 0 -#define APCLI_MT2_MLME_ASSOC_REQ 0 -#define APCLI_MT2_MLME_DISASSOC_REQ 1 -#define APCLI_MT2_PEER_DISASSOC_REQ 2 -#define APCLI_MT2_PEER_ASSOC_RSP 3 -#define APCLI_MT2_ASSOC_TIMEOUT 4 -#define APCLI_MAX_ASSOC_MSG 5 - -#define APCLI_ASSOC_FUNC_SIZE (APCLI_MAX_ASSOC_STATE * APCLI_MAX_ASSOC_MSG) - -//ApCli sync state machine -#define APCLI_SYNC_IDLE 0 // merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state -#define APCLI_JOIN_WAIT_PROBE_RSP 1 -#define APCLI_MAX_SYNC_STATE 2 - -#define APCLI_SYNC_MACHINE_BASE 0 -#define APCLI_MT2_MLME_PROBE_REQ 0 -#define APCLI_MT2_PEER_PROBE_RSP 1 -#define APCLI_MT2_PROBE_TIMEOUT 2 -#define APCLI_MAX_SYNC_MSG 3 - -#define APCLI_SYNC_FUNC_SIZE (APCLI_MAX_SYNC_STATE * APCLI_MAX_SYNC_MSG) - -//ApCli ctrl state machine -#define APCLI_CTRL_DISCONNECTED 0 // merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state -#define APCLI_CTRL_PROBE 1 -#define APCLI_CTRL_AUTH 2 -#define APCLI_CTRL_AUTH_2 3 -#define APCLI_CTRL_ASSOC 4 -#define APCLI_CTRL_DEASSOC 5 -#define APCLI_CTRL_CONNECTED 6 -#define APCLI_MAX_CTRL_STATE 7 - -#define APCLI_CTRL_MACHINE_BASE 0 -#define APCLI_CTRL_JOIN_REQ 0 -#define APCLI_CTRL_PROBE_RSP 1 -#define APCLI_CTRL_AUTH_RSP 2 -#define APCLI_CTRL_DISCONNECT_REQ 3 -#define APCLI_CTRL_PEER_DISCONNECT_REQ 4 -#define APCLI_CTRL_ASSOC_RSP 5 -#define APCLI_CTRL_DEASSOC_RSP 6 -#define APCLI_CTRL_JOIN_REQ_TIMEOUT 7 -#define APCLI_CTRL_AUTH_REQ_TIMEOUT 8 -#define APCLI_CTRL_ASSOC_REQ_TIMEOUT 9 -#define APCLI_MAX_CTRL_MSG 10 - -#define APCLI_CTRL_FUNC_SIZE (APCLI_MAX_CTRL_STATE * APCLI_MAX_CTRL_MSG) - - -#endif // APCLI_SUPPORT // - - -// ============================================================================= - -// value domain of 802.11 header FC.Tyte, which is b3..b2 of the 1st-byte of MAC header -#define BTYPE_MGMT 0 -#define BTYPE_CNTL 1 -#define BTYPE_DATA 2 - -// value domain of 802.11 MGMT frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header -#define SUBTYPE_ASSOC_REQ 0 -#define SUBTYPE_ASSOC_RSP 1 -#define SUBTYPE_REASSOC_REQ 2 -#define SUBTYPE_REASSOC_RSP 3 -#define SUBTYPE_PROBE_REQ 4 -#define SUBTYPE_PROBE_RSP 5 -#define SUBTYPE_BEACON 8 -#define SUBTYPE_ATIM 9 -#define SUBTYPE_DISASSOC 10 -#define SUBTYPE_AUTH 11 -#define SUBTYPE_DEAUTH 12 -#define SUBTYPE_ACTION 13 -#define SUBTYPE_ACTION_NO_ACK 14 - -// value domain of 802.11 CNTL frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header -#define SUBTYPE_WRAPPER 7 -#define SUBTYPE_BLOCK_ACK_REQ 8 -#define SUBTYPE_BLOCK_ACK 9 -#define SUBTYPE_PS_POLL 10 -#define SUBTYPE_RTS 11 -#define SUBTYPE_CTS 12 -#define SUBTYPE_ACK 13 -#define SUBTYPE_CFEND 14 -#define SUBTYPE_CFEND_CFACK 15 - -// value domain of 802.11 DATA frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header -#define SUBTYPE_DATA 0 -#define SUBTYPE_DATA_CFACK 1 -#define SUBTYPE_DATA_CFPOLL 2 -#define SUBTYPE_DATA_CFACK_CFPOLL 3 -#define SUBTYPE_NULL_FUNC 4 -#define SUBTYPE_CFACK 5 -#define SUBTYPE_CFPOLL 6 -#define SUBTYPE_CFACK_CFPOLL 7 -#define SUBTYPE_QDATA 8 -#define SUBTYPE_QDATA_CFACK 9 -#define SUBTYPE_QDATA_CFPOLL 10 -#define SUBTYPE_QDATA_CFACK_CFPOLL 11 -#define SUBTYPE_QOS_NULL 12 -#define SUBTYPE_QOS_CFACK 13 -#define SUBTYPE_QOS_CFPOLL 14 -#define SUBTYPE_QOS_CFACK_CFPOLL 15 - -// ACK policy of QOS Control field bit 6:5 -#define NORMAL_ACK 0x00 // b6:5 = 00 -#define NO_ACK 0x20 // b6:5 = 01 -#define NO_EXPLICIT_ACK 0x40 // b6:5 = 10 -#define BLOCK_ACK 0x60 // b6:5 = 11 - -// -// rtmp_data.c use these definition -// -#define LENGTH_802_11 24 -#define LENGTH_802_11_AND_H 30 -#define LENGTH_802_11_CRC_H 34 -#define LENGTH_802_11_CRC 28 -#define LENGTH_802_11_WITH_ADDR4 30 -#define LENGTH_802_3 14 -#define LENGTH_802_3_TYPE 2 -#define LENGTH_802_1_H 8 -#define LENGTH_EAPOL_H 4 -#define LENGTH_WMMQOS_H 2 -#define LENGTH_CRC 4 -#define MAX_SEQ_NUMBER 0x0fff -#define LENGTH_802_3_NO_TYPE 12 -#define LENGTH_802_1Q 4 /* VLAN related */ - -// STA_CSR4.field.TxResult -#define TX_RESULT_SUCCESS 0 -#define TX_RESULT_ZERO_LENGTH 1 -#define TX_RESULT_UNDER_RUN 2 -#define TX_RESULT_OHY_ERROR 4 -#define TX_RESULT_RETRY_FAIL 6 - -// All PHY rate summary in TXD -// Preamble MODE in TxD -#define MODE_CCK 0 -#define MODE_OFDM 1 -#ifdef DOT11_N_SUPPORT -#define MODE_HTMIX 2 -#define MODE_HTGREENFIELD 3 -#endif // DOT11_N_SUPPORT // -// MCS for CCK. BW.SGI.STBC are reserved -#define MCS_LONGP_RATE_1 0 // long preamble CCK 1Mbps -#define MCS_LONGP_RATE_2 1 // long preamble CCK 1Mbps -#define MCS_LONGP_RATE_5_5 2 -#define MCS_LONGP_RATE_11 3 -#define MCS_SHORTP_RATE_1 4 // long preamble CCK 1Mbps. short is forbidden in 1Mbps -#define MCS_SHORTP_RATE_2 5 // short preamble CCK 2Mbps -#define MCS_SHORTP_RATE_5_5 6 -#define MCS_SHORTP_RATE_11 7 -// To send duplicate legacy OFDM. set BW=BW_40. SGI.STBC are reserved -#define MCS_RATE_6 0 // legacy OFDM -#define MCS_RATE_9 1 // OFDM -#define MCS_RATE_12 2 // OFDM -#define MCS_RATE_18 3 // OFDM -#define MCS_RATE_24 4 // OFDM -#define MCS_RATE_36 5 // OFDM -#define MCS_RATE_48 6 // OFDM -#define MCS_RATE_54 7 // OFDM -// HT -#define MCS_0 0 // 1S -#define MCS_1 1 -#define MCS_2 2 -#define MCS_3 3 -#define MCS_4 4 -#define MCS_5 5 -#define MCS_6 6 -#define MCS_7 7 -#define MCS_8 8 // 2S -#define MCS_9 9 -#define MCS_10 10 -#define MCS_11 11 -#define MCS_12 12 -#define MCS_13 13 -#define MCS_14 14 -#define MCS_15 15 -#define MCS_16 16 // 3*3 -#define MCS_17 17 -#define MCS_18 18 -#define MCS_19 19 -#define MCS_20 20 -#define MCS_21 21 -#define MCS_22 22 -#define MCS_23 23 -#define MCS_32 32 -#define MCS_AUTO 33 - -#ifdef DOT11_N_SUPPORT -// OID_HTPHYMODE -// MODE -#define HTMODE_MM 0 -#define HTMODE_GF 1 -#endif // DOT11_N_SUPPORT // - -// Fixed Tx MODE - HT, CCK or OFDM -#define FIXED_TXMODE_HT 0 -#define FIXED_TXMODE_CCK 1 -#define FIXED_TXMODE_OFDM 2 -// BW -#define BW_20 BAND_WIDTH_20 -#define BW_40 BAND_WIDTH_40 -#define BW_BOTH BAND_WIDTH_BOTH -#define BW_10 BAND_WIDTH_10 // 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. - -#ifdef DOT11_N_SUPPORT -// SHORTGI -#define GI_400 GAP_INTERVAL_400 // only support in HT mode -#define GI_BOTH GAP_INTERVAL_BOTH -#endif // DOT11_N_SUPPORT // -#define GI_800 GAP_INTERVAL_800 -// STBC -#define STBC_NONE 0 -#ifdef DOT11_N_SUPPORT -#define STBC_USE 1 // limited use in rt2860b phy -#define RXSTBC_ONE 1 // rx support of one spatial stream -#define RXSTBC_TWO 2 // rx support of 1 and 2 spatial stream -#define RXSTBC_THR 3 // rx support of 1~3 spatial stream -// MCS FEEDBACK -#define MCSFBK_NONE 0 // not support mcs feedback / -#define MCSFBK_RSV 1 // reserved -#define MCSFBK_UNSOLICIT 2 // only support unsolict mcs feedback -#define MCSFBK_MRQ 3 // response to both MRQ and unsolict mcs feedback - -// MIMO power safe -#define MMPS_STATIC 0 -#define MMPS_DYNAMIC 1 -#define MMPS_RSV 2 -#define MMPS_ENABLE 3 - - -// A-MSDU size -#define AMSDU_0 0 -#define AMSDU_1 1 - -#endif // DOT11_N_SUPPORT // - -// MCS use 7 bits -#define TXRATEMIMO 0x80 -#define TXRATEMCS 0x7F -#define TXRATEOFDM 0x7F -#define RATE_1 0 -#define RATE_2 1 -#define RATE_5_5 2 -#define RATE_11 3 -#define RATE_6 4 // OFDM -#define RATE_9 5 // OFDM -#define RATE_12 6 // OFDM -#define RATE_18 7 // OFDM -#define RATE_24 8 // OFDM -#define RATE_36 9 // OFDM -#define RATE_48 10 // OFDM -#define RATE_54 11 // OFDM -#define RATE_FIRST_OFDM_RATE RATE_6 -#define RATE_LAST_OFDM_RATE RATE_54 -#define RATE_6_5 12 // HT mix -#define RATE_13 13 // HT mix -#define RATE_19_5 14 // HT mix -#define RATE_26 15 // HT mix -#define RATE_39 16 // HT mix -#define RATE_52 17 // HT mix -#define RATE_58_5 18 // HT mix -#define RATE_65 19 // HT mix -#define RATE_78 20 // HT mix -#define RATE_104 21 // HT mix -#define RATE_117 22 // HT mix -#define RATE_130 23 // HT mix -//#define RATE_AUTO_SWITCH 255 // for StaCfg.FixedTxRate only -#define HTRATE_0 12 -#define RATE_FIRST_MM_RATE HTRATE_0 -#define RATE_FIRST_HT_RATE HTRATE_0 -#define RATE_LAST_HT_RATE HTRATE_0 - -// pTxWI->txop -#define IFS_HTTXOP 0 // The txop will be handles by ASIC. -#define IFS_PIFS 1 -#define IFS_SIFS 2 -#define IFS_BACKOFF 3 - -// pTxD->RetryMode -#define LONG_RETRY 1 -#define SHORT_RETRY 0 - -// Country Region definition -#define REGION_MINIMUM_BG_BAND 0 -#define REGION_0_BG_BAND 0 // 1-11 -#define REGION_1_BG_BAND 1 // 1-13 -#define REGION_2_BG_BAND 2 // 10-11 -#define REGION_3_BG_BAND 3 // 10-13 -#define REGION_4_BG_BAND 4 // 14 -#define REGION_5_BG_BAND 5 // 1-14 -#define REGION_6_BG_BAND 6 // 3-9 -#define REGION_7_BG_BAND 7 // 5-13 -#define REGION_31_BG_BAND 31 // 5-13 -#define REGION_MAXIMUM_BG_BAND 7 - -#define REGION_MINIMUM_A_BAND 0 -#define REGION_0_A_BAND 0 // 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 -#define REGION_1_A_BAND 1 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 -#define REGION_2_A_BAND 2 // 36, 40, 44, 48, 52, 56, 60, 64 -#define REGION_3_A_BAND 3 // 52, 56, 60, 64, 149, 153, 157, 161 -#define REGION_4_A_BAND 4 // 149, 153, 157, 161, 165 -#define REGION_5_A_BAND 5 // 149, 153, 157, 161 -#define REGION_6_A_BAND 6 // 36, 40, 44, 48 -#define REGION_7_A_BAND 7 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 169, 173 -#define REGION_8_A_BAND 8 // 52, 56, 60, 64 -#define REGION_9_A_BAND 9 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165 -#define REGION_10_A_BAND 10 // 36, 40, 44, 48, 149, 153, 157, 161, 165 -#define REGION_11_A_BAND 11 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161 -#define REGION_12_A_BAND 12 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 -#define REGION_13_A_BAND 13 // 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161 -#define REGION_14_A_BAND 14 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165 -#define REGION_15_A_BAND 15 // 149, 153, 157, 161, 165, 169, 173 -#define REGION_MAXIMUM_A_BAND 15 - -// pTxD->CipherAlg -#define CIPHER_NONE 0 -#define CIPHER_WEP64 1 -#define CIPHER_WEP128 2 -#define CIPHER_TKIP 3 -#define CIPHER_AES 4 -#define CIPHER_CKIP64 5 -#define CIPHER_CKIP128 6 -#define CIPHER_TKIP_NO_MIC 7 // MIC appended by driver: not a valid value in hardware key table -#define CIPHER_SMS4 8 - - -// LED Status. -#define LED_LINK_DOWN 0 -#define LED_LINK_UP 1 -#define LED_RADIO_OFF 2 -#define LED_RADIO_ON 3 -#define LED_HALT 4 -#define LED_WPS 5 -#define LED_ON_SITE_SURVEY 6 -#define LED_POWER_UP 7 - - -// value domain of pAd->LedCntl.LedMode and E2PROM -#define LED_MODE_DEFAULT 0 -#define LED_MODE_TWO_LED 1 -//#define LED_MODE_SIGNAL_STREGTH 8 // EEPROM define =8 -#define LED_MODE_SIGNAL_STREGTH 0x40 // EEPROM define = 64 - -// RC4 init value, used fro WEP & TKIP -#define PPPINITFCS32 0xffffffff /* Initial FCS value */ - -// value domain of pAd->StaCfg.PortSecured. 802.1X controlled port definition -#define WPA_802_1X_PORT_SECURED 1 -#define WPA_802_1X_PORT_NOT_SECURED 2 - -#define PAIRWISE_KEY 1 -#define GROUP_KEY 2 - -//definition of DRS -#define MAX_STEP_OF_TX_RATE_SWITCH 32 - - -// pre-allocated free NDIS PACKET/BUFFER poll for internal usage -#define MAX_NUM_OF_FREE_NDIS_PACKET 128 - -//Block ACK -#define MAX_TX_REORDERBUF 64 -#define MAX_RX_REORDERBUF 64 -#define DEFAULT_TX_TIMEOUT 30 -#define DEFAULT_RX_TIMEOUT 30 - -// definition of Recipient or Originator -#define I_RECIPIENT TRUE -#define I_ORIGINATOR FALSE - -#define DEFAULT_BBP_TX_POWER 0 -#define DEFAULT_RF_TX_POWER 5 - -#define MAX_INI_BUFFER_SIZE 4096 -#define MAX_PARAM_BUFFER_SIZE (2048) // enough for ACL (18*64) - //18 : the length of Mac address acceptable format "01:02:03:04:05:06;") - //64 : MAX_NUM_OF_ACL_LIST -// definition of pAd->OpMode -#define OPMODE_STA 0 -#define OPMODE_AP 1 -//#define OPMODE_L3_BRG 2 // as AP and STA at the same time - -#ifdef RT_BIG_ENDIAN -#define DIR_READ 0 -#define DIR_WRITE 1 -#define TYPE_TXD 0 -#define TYPE_RXD 1 -#define TYPE_TXINFO 0 -#define TYPE_RXINFO 1 -#define TYPE_TXWI 0 -#define TYPE_RXWI 1 -#endif - -// ========================= AP rtmp_def.h =========================== -// value domain for pAd->EventTab.Log[].Event -#define EVENT_RESET_ACCESS_POINT 0 // Log = "hh:mm:ss Restart Access Point" -#define EVENT_ASSOCIATED 1 // Log = "hh:mm:ss STA 00:01:02:03:04:05 associated" -#define EVENT_DISASSOCIATED 2 // Log = "hh:mm:ss STA 00:01:02:03:04:05 left this BSS" -#define EVENT_AGED_OUT 3 // Log = "hh:mm:ss STA 00:01:02:03:04:05 was aged-out and removed from this BSS" -#define EVENT_COUNTER_M 4 -#define EVENT_INVALID_PSK 5 -#define EVENT_MAX_EVENT_TYPE 6 -// ==== end of AP rtmp_def.h ============ - -// definition RSSI Number -#define RSSI_0 0 -#define RSSI_1 1 -#define RSSI_2 2 - -// definition of radar detection -#define RD_NORMAL_MODE 0 // Not found radar signal -#define RD_SWITCHING_MODE 1 // Found radar signal, and doing channel switch -#define RD_SILENCE_MODE 2 // After channel switch, need to be silence a while to ensure radar not found - -//Driver defined cid for mapping status and command. -#define SLEEPCID 0x11 -#define WAKECID 0x22 -#define QUERYPOWERCID 0x33 -#define OWNERMCU 0x1 -#define OWNERCPU 0x0 - -// MBSSID definition -#define ENTRY_NOT_FOUND 0xFF - - -/* After Linux 2.6.9, - * VLAN module use Private (from user) interface flags (netdevice->priv_flags). - * #define IFF_802_1Q_VLAN 0x1 -- 802.1Q VLAN device. in if.h - * ref to ip_sabotage_out() [ out->priv_flags & IFF_802_1Q_VLAN ] in br_netfilter.c - * - * For this reason, we MUST use EVEN value in priv_flags - */ -#define INT_MAIN 0x0100 -#define INT_MBSSID 0x0200 -#define INT_WDS 0x0300 -#define INT_APCLI 0x0400 -#define INT_MESH 0x0500 - -#define INF_MAIN_DEV_NAME "wlan" -#define INF_MBSSID_DEV_NAME "wlan" -#define INF_WDS_DEV_NAME "wds" -#define INF_APCLI_DEV_NAME "apcli" -#define INF_MESH_DEV_NAME "mesh" - -// Use bitmap to allow coexist of ATE_TXFRAME and ATE_RXFRAME(i.e.,to support LoopBack mode). -#ifdef RALINK_ATE -#define ATE_START 0x00 // Start ATE -#define ATE_STOP 0x80 // Stop ATE -#define ATE_TXCONT 0x05 // Continuous Transmit -#define ATE_TXCARR 0x09 // Transmit Carrier -#define ATE_TXCARRSUPP 0x11 // Transmit Carrier Suppression -#define ATE_TXFRAME 0x01 // Transmit Frames -#define ATE_RXFRAME 0x02 // Receive Frames -#ifdef RALINK_28xx_QA -#define ATE_TXSTOP 0xe2 // Stop Transmition(i.e., TXCONT, TXCARR, TXCARRSUPP, and TXFRAME) -#define ATE_RXSTOP 0xfd // Stop receiving Frames -#define BBP22_TXFRAME 0x00 // Transmit Frames -#define BBP22_TXCONT_OR_CARRSUPP 0x80 // Continuous Transmit or Carrier Suppression -#define BBP22_TXCARR 0xc1 // Transmit Carrier -#define BBP24_TXCONT 0x00 // Continuous Transmit -#define BBP24_CARRSUPP 0x01 // Carrier Suppression -#endif // RALINK_28xx_QA // -#endif // RALINK_ATE // - -// WEP Key TYPE -#define WEP_HEXADECIMAL_TYPE 0 -#define WEP_ASCII_TYPE 1 - - - -// WIRELESS EVENTS definition -/* Max number of char in custom event, refer to wireless_tools.28/wireless.20.h */ -#define IW_CUSTOM_MAX_LEN 255 /* In bytes */ - -// For system event - start -#define IW_SYS_EVENT_FLAG_START 0x0200 -#define IW_ASSOC_EVENT_FLAG 0x0200 -#define IW_DISASSOC_EVENT_FLAG 0x0201 -#define IW_DEAUTH_EVENT_FLAG 0x0202 -#define IW_AGEOUT_EVENT_FLAG 0x0203 -#define IW_COUNTER_MEASURES_EVENT_FLAG 0x0204 -#define IW_REPLAY_COUNTER_DIFF_EVENT_FLAG 0x0205 -#define IW_RSNIE_DIFF_EVENT_FLAG 0x0206 -#define IW_MIC_DIFF_EVENT_FLAG 0x0207 -#define IW_ICV_ERROR_EVENT_FLAG 0x0208 -#define IW_MIC_ERROR_EVENT_FLAG 0x0209 -#define IW_GROUP_HS_TIMEOUT_EVENT_FLAG 0x020A -#define IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG 0x020B -#define IW_RSNIE_SANITY_FAIL_EVENT_FLAG 0x020C -#define IW_SET_KEY_DONE_WPA1_EVENT_FLAG 0x020D -#define IW_SET_KEY_DONE_WPA2_EVENT_FLAG 0x020E -#define IW_STA_LINKUP_EVENT_FLAG 0x020F -#define IW_STA_LINKDOWN_EVENT_FLAG 0x0210 -#define IW_SCAN_COMPLETED_EVENT_FLAG 0x0211 -#define IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG 0x0212 -// if add new system event flag, please upadte the IW_SYS_EVENT_FLAG_END -#define IW_SYS_EVENT_FLAG_END 0x0212 -#define IW_SYS_EVENT_TYPE_NUM (IW_SYS_EVENT_FLAG_END - IW_SYS_EVENT_FLAG_START + 1) -// For system event - end - -// For spoof attack event - start -#define IW_SPOOF_EVENT_FLAG_START 0x0300 -#define IW_CONFLICT_SSID_EVENT_FLAG 0x0300 -#define IW_SPOOF_ASSOC_RESP_EVENT_FLAG 0x0301 -#define IW_SPOOF_REASSOC_RESP_EVENT_FLAG 0x0302 -#define IW_SPOOF_PROBE_RESP_EVENT_FLAG 0x0303 -#define IW_SPOOF_BEACON_EVENT_FLAG 0x0304 -#define IW_SPOOF_DISASSOC_EVENT_FLAG 0x0305 -#define IW_SPOOF_AUTH_EVENT_FLAG 0x0306 -#define IW_SPOOF_DEAUTH_EVENT_FLAG 0x0307 -#define IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG 0x0308 -#define IW_REPLAY_ATTACK_EVENT_FLAG 0x0309 -// if add new spoof attack event flag, please upadte the IW_SPOOF_EVENT_FLAG_END -#define IW_SPOOF_EVENT_FLAG_END 0x0309 -#define IW_SPOOF_EVENT_TYPE_NUM (IW_SPOOF_EVENT_FLAG_END - IW_SPOOF_EVENT_FLAG_START + 1) -// For spoof attack event - end - -// For flooding attack event - start -#define IW_FLOOD_EVENT_FLAG_START 0x0400 -#define IW_FLOOD_AUTH_EVENT_FLAG 0x0400 -#define IW_FLOOD_ASSOC_REQ_EVENT_FLAG 0x0401 -#define IW_FLOOD_REASSOC_REQ_EVENT_FLAG 0x0402 -#define IW_FLOOD_PROBE_REQ_EVENT_FLAG 0x0403 -#define IW_FLOOD_DISASSOC_EVENT_FLAG 0x0404 -#define IW_FLOOD_DEAUTH_EVENT_FLAG 0x0405 -#define IW_FLOOD_EAP_REQ_EVENT_FLAG 0x0406 -// if add new flooding attack event flag, please upadte the IW_FLOOD_EVENT_FLAG_END -#define IW_FLOOD_EVENT_FLAG_END 0x0406 -#define IW_FLOOD_EVENT_TYPE_NUM (IW_FLOOD_EVENT_FLAG_END - IW_FLOOD_EVENT_FLAG_START + 1) -// For flooding attack - end - -// End - WIRELESS EVENTS definition - -#ifdef CONFIG_STA_SUPPORT -// definition for DLS, kathy -#define MAX_NUM_OF_INIT_DLS_ENTRY 1 -#define MAX_NUM_OF_DLS_ENTRY MAX_NUMBER_OF_DLS_ENTRY - -//Block ACK, kathy -#define MAX_TX_REORDERBUF 64 -#define MAX_RX_REORDERBUF 64 -#define DEFAULT_TX_TIMEOUT 30 -#define DEFAULT_RX_TIMEOUT 30 -#define MAX_BARECI_SESSION 8 - -#ifndef IW_ESSID_MAX_SIZE -/* Maximum size of the ESSID and pAd->nickname strings */ -#define IW_ESSID_MAX_SIZE 32 -#endif -#endif // CONFIG_STA_SUPPORT // - -#ifdef MCAST_RATE_SPECIFIC -#define MCAST_DISABLE 0 -#define MCAST_CCK 1 -#define MCAST_OFDM 2 -#define MCAST_HTMIX 3 -#endif // MCAST_RATE_SPECIFIC // - -// For AsicRadioOff/AsicRadioOn function -#define DOT11POWERSAVE 0 -#define GUIRADIO_OFF 1 -#define RTMP_HALT 2 -#define GUI_IDLE_POWER_SAVE 3 -// -- - - -// definition for WpaSupport flag -#define WPA_SUPPLICANT_DISABLE 0 -#define WPA_SUPPLICANT_ENABLE 1 -#define WPA_SUPPLICANT_ENABLE_WITH_WEB_UI 2 - -// definition for Antenna Diversity flag -#ifdef ANT_DIVERSITY_SUPPORT -enum ANT_DIVERSITY_TYPE { - ANT_DIVERSITY_DISABLE = 0, - ANT_DIVERSITY_ENABLE = 1, - ANT_FIX_ANT1 = 2, - ANT_FIX_ANT2 = 3 -}; -#endif // ANT_DIVERSITY_SUPPORT // - -// Endian byte swapping codes -#define SWAP16(x) \ - ((UINT16)( \ - (((UINT16)(x) & (UINT16) 0x00ffU) << 8) | \ - (((UINT16)(x) & (UINT16) 0xff00U) >> 8) )) - -#define SWAP32(x) \ - ((UINT32)( \ - (((UINT32)(x) & (UINT32) 0x000000ffUL) << 24) | \ - (((UINT32)(x) & (UINT32) 0x0000ff00UL) << 8) | \ - (((UINT32)(x) & (UINT32) 0x00ff0000UL) >> 8) | \ - (((UINT32)(x) & (UINT32) 0xff000000UL) >> 24) )) - -#define SWAP64(x) \ - ((UINT64)( \ - (UINT64)(((UINT64)(x) & (UINT64) 0x00000000000000ffULL) << 56) | \ - (UINT64)(((UINT64)(x) & (UINT64) 0x000000000000ff00ULL) << 40) | \ - (UINT64)(((UINT64)(x) & (UINT64) 0x0000000000ff0000ULL) << 24) | \ - (UINT64)(((UINT64)(x) & (UINT64) 0x00000000ff000000ULL) << 8) | \ - (UINT64)(((UINT64)(x) & (UINT64) 0x000000ff00000000ULL) >> 8) | \ - (UINT64)(((UINT64)(x) & (UINT64) 0x0000ff0000000000ULL) >> 24) | \ - (UINT64)(((UINT64)(x) & (UINT64) 0x00ff000000000000ULL) >> 40) | \ - (UINT64)(((UINT64)(x) & (UINT64) 0xff00000000000000ULL) >> 56) )) - -#ifdef RT_BIG_ENDIAN - -#define cpu2le64(x) SWAP64((x)) -#define le2cpu64(x) SWAP64((x)) -#define cpu2le32(x) SWAP32((x)) -#define le2cpu32(x) SWAP32((x)) -#define cpu2le16(x) SWAP16((x)) -#define le2cpu16(x) SWAP16((x)) -#define cpu2be64(x) ((UINT64)(x)) -#define be2cpu64(x) ((UINT64)(x)) -#define cpu2be32(x) ((UINT32)(x)) -#define be2cpu32(x) ((UINT32)(x)) -#define cpu2be16(x) ((UINT16)(x)) -#define be2cpu16(x) ((UINT16)(x)) - -#else // Little_Endian - -#define cpu2le64(x) ((UINT64)(x)) -#define le2cpu64(x) ((UINT64)(x)) -#define cpu2le32(x) ((UINT32)(x)) -#define le2cpu32(x) ((UINT32)(x)) -#define cpu2le16(x) ((UINT16)(x)) -#define le2cpu16(x) ((UINT16)(x)) -#define cpu2be64(x) SWAP64((x)) -#define be2cpu64(x) SWAP64((x)) -#define cpu2be32(x) SWAP32((x)) -#define be2cpu32(x) SWAP32((x)) -#define cpu2be16(x) SWAP16((x)) -#define be2cpu16(x) SWAP16((x)) - -#endif // RT_BIG_ENDIAN - -#define ABS(_x, _y) ((_x) > (_y)) ? ((_x) -(_y)) : ((_y) -(_x)) - - -#define A2Dec(_X, _p) \ -{ \ - UCHAR *p; \ - _X = 0; \ - p = _p; \ - while (((*p >= '0') && (*p <= '9'))) \ - { \ - if ((*p >= '0') && (*p <= '9')) \ - _X = _X * 10 + *p - 48; \ - p++; \ - } \ -} - - -#define A2Hex(_X, _p) \ -do{ \ - char *__p; \ - (_X) = 0; \ - __p = (char *)(_p); \ - while (((*__p >= 'a') && (*__p <= 'f')) || ((*__p >= 'A') && (*__p <= 'F')) || ((*__p >= '0') && (*__p <= '9'))) \ - { \ - if ((*__p >= 'a') && (*__p <= 'f')) \ - (_X) = (_X) * 16 + *__p - 87; \ - else if ((*__p >= 'A') && (*__p <= 'F')) \ - (_X) = (_X) * 16 + *__p - 55; \ - else if ((*__p >= '0') && (*__p <= '9')) \ - (_X) = (_X) * 16 + *__p - 48; \ - __p++; \ - } \ -}while(0) - -#endif // __RTMP_DEF_H__ diff --git a/drivers/staging/rt3090/rtmp_dot11.h b/drivers/staging/rt3090/rtmp_dot11.h deleted file mode 100644 index a637825afe9c40bf4470371a004505d19835bb2e..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rtmp_dot11.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* -*/ - -#ifndef __DOT11_BASE_H__ -#define __DOT11_BASE_H__ - -#include "rtmp_type.h" - - -// 4-byte HTC field. maybe included in any frame except non-QOS data frame. The Order bit must set 1. -typedef struct PACKED { -#ifdef RT_BIG_ENDIAN - UINT32 RDG:1; //RDG / More PPDU - UINT32 ACConstraint:1; //feedback request - UINT32 rsv:5; //calibration sequence - UINT32 ZLFAnnouce:1; // ZLF announcement - UINT32 CSISTEERING:2; //CSI/ STEERING - UINT32 FBKReq:2; //feedback request - UINT32 CalSeq:2; //calibration sequence - UINT32 CalPos:2; // calibration position - UINT32 MFBorASC:7; //Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available - UINT32 MFS:3; //SET to the received value of MRS. 0x111 for unsolicited MFB. - UINT32 MRSorASI:3; // MRQ Sequence identifier. unchanged during entire procedure. 0x000-0x110. - UINT32 MRQ:1; //MCS feedback. Request for a MCS feedback - UINT32 TRQ:1; //sounding request - UINT32 MA:1; //management action payload exist in (QoS Null+HTC) -#else - UINT32 MA:1; //management action payload exist in (QoS Null+HTC) - UINT32 TRQ:1; //sounding request - UINT32 MRQ:1; //MCS feedback. Request for a MCS feedback - UINT32 MRSorASI:3; // MRQ Sequence identifier. unchanged during entire procedure. 0x000-0x110. - UINT32 MFS:3; //SET to the received value of MRS. 0x111 for unsolicited MFB. - UINT32 MFBorASC:7; //Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available - UINT32 CalPos:2; // calibration position - UINT32 CalSeq:2; //calibration sequence - UINT32 FBKReq:2; //feedback request - UINT32 CSISTEERING:2; //CSI/ STEERING - UINT32 ZLFAnnouce:1; // ZLF announcement - UINT32 rsv:5; //calibration sequence - UINT32 ACConstraint:1; //feedback request - UINT32 RDG:1; //RDG / More PPDU -#endif /* !RT_BIG_ENDIAN */ -} HT_CONTROL, *PHT_CONTROL; - -// 2-byte QOS CONTROL field -typedef struct PACKED { -#ifdef RT_BIG_ENDIAN - USHORT Txop_QueueSize:8; - USHORT AMsduPresent:1; - USHORT AckPolicy:2; //0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP 3: BA - USHORT EOSP:1; - USHORT TID:4; -#else - USHORT TID:4; - USHORT EOSP:1; - USHORT AckPolicy:2; //0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP 3: BA - USHORT AMsduPresent:1; - USHORT Txop_QueueSize:8; -#endif /* !RT_BIG_ENDIAN */ -} QOS_CONTROL, *PQOS_CONTROL; - - -// 2-byte Frame control field -typedef struct PACKED { -#ifdef RT_BIG_ENDIAN - USHORT Order:1; // Strict order expected - USHORT Wep:1; // Wep data - USHORT MoreData:1; // More data bit - USHORT PwrMgmt:1; // Power management bit - USHORT Retry:1; // Retry status bit - USHORT MoreFrag:1; // More fragment bit - USHORT FrDs:1; // From DS indication - USHORT ToDs:1; // To DS indication - USHORT SubType:4; // MSDU subtype - USHORT Type:2; // MSDU type - USHORT Ver:2; // Protocol version -#else - USHORT Ver:2; // Protocol version - USHORT Type:2; // MSDU type - USHORT SubType:4; // MSDU subtype - USHORT ToDs:1; // To DS indication - USHORT FrDs:1; // From DS indication - USHORT MoreFrag:1; // More fragment bit - USHORT Retry:1; // Retry status bit - USHORT PwrMgmt:1; // Power management bit - USHORT MoreData:1; // More data bit - USHORT Wep:1; // Wep data - USHORT Order:1; // Strict order expected -#endif /* !RT_BIG_ENDIAN */ -} FRAME_CONTROL, *PFRAME_CONTROL; - -typedef struct PACKED _HEADER_802_11 { - FRAME_CONTROL FC; - USHORT Duration; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; - UCHAR Addr3[MAC_ADDR_LEN]; -#ifdef RT_BIG_ENDIAN - USHORT Sequence:12; - USHORT Frag:4; -#else - USHORT Frag:4; - USHORT Sequence:12; -#endif /* !RT_BIG_ENDIAN */ - UCHAR Octet[0]; -} HEADER_802_11, *PHEADER_802_11; - -typedef struct PACKED _PSPOLL_FRAME { - FRAME_CONTROL FC; - USHORT Aid; - UCHAR Bssid[MAC_ADDR_LEN]; - UCHAR Ta[MAC_ADDR_LEN]; -} PSPOLL_FRAME, *PPSPOLL_FRAME; - -typedef struct PACKED _RTS_FRAME { - FRAME_CONTROL FC; - USHORT Duration; - UCHAR Addr1[MAC_ADDR_LEN]; - UCHAR Addr2[MAC_ADDR_LEN]; -}RTS_FRAME, *PRTS_FRAME; - -#endif // __DOT11_BASE_H__ // diff --git a/drivers/staging/rt3090/rtmp_mac.h b/drivers/staging/rt3090/rtmp_mac.h deleted file mode 100644 index c57b2959777e0e938e9b457c6dea3305157db141..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rtmp_mac.h +++ /dev/null @@ -1,2304 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rtmp_mac.h - - Abstract: - Ralink Wireless Chip MAC related definition & structures - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#ifndef __RTMP_MAC_H__ -#define __RTMP_MAC_H__ - - - -// ================================================================================= -// TX / RX ring descriptor format -// ================================================================================= - -// the first 24-byte in TXD is called TXINFO and will be DMAed to MAC block through TXFIFO. -// MAC block use this TXINFO to control the transmission behavior of this frame. -#define FIFO_MGMT 0 -#define FIFO_HCCA 1 -#define FIFO_EDCA 2 - - -// -// TXD Wireless Information format for Tx ring and Mgmt Ring -// -//txop : for txop mode -// 0:txop for the MPDU frame will be handles by ASIC by register -// 1/2/3:the MPDU frame is send after PIFS/backoff/SIFS -#ifdef RT_BIG_ENDIAN -typedef struct PACKED _TXWI_STRUC { - // Word 0 - UINT32 PHYMODE:2; - UINT32 TxBF:1; // 3*3 - UINT32 rsv2:1; -// UINT32 rsv2:2; - UINT32 Ifs:1; // - UINT32 STBC:2; //channel bandwidth 20MHz or 40 MHz - UINT32 ShortGI:1; - UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz - UINT32 MCS:7; - - UINT32 rsv:6; - UINT32 txop:2; //tx back off mode 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful. - UINT32 MpduDensity:3; - UINT32 AMPDU:1; - - UINT32 TS:1; - UINT32 CFACK:1; - UINT32 MIMOps:1; // the remote peer is in dynamic MIMO-PS mode - UINT32 FRAG:1; // 1 to inform TKIP engine this is a fragment. - // Word 1 - UINT32 PacketId:4; - UINT32 MPDUtotalByteCount:12; - UINT32 WirelessCliID:8; - UINT32 BAWinSize:6; - UINT32 NSEQ:1; - UINT32 ACK:1; - // Word 2 - UINT32 IV; - // Word 3 - UINT32 EIV; -} TXWI_STRUC, *PTXWI_STRUC; -#else -typedef struct PACKED _TXWI_STRUC { - // Word 0 - // ex: 00 03 00 40 means txop = 3, PHYMODE = 1 - UINT32 FRAG:1; // 1 to inform TKIP engine this is a fragment. - UINT32 MIMOps:1; // the remote peer is in dynamic MIMO-PS mode - UINT32 CFACK:1; - UINT32 TS:1; - - UINT32 AMPDU:1; - UINT32 MpduDensity:3; - UINT32 txop:2; //FOR "THIS" frame. 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful. - UINT32 rsv:6; - - UINT32 MCS:7; - UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz - UINT32 ShortGI:1; - UINT32 STBC:2; // 1: STBC support MCS =0-7, 2,3 : RESERVE - UINT32 Ifs:1; // -// UINT32 rsv2:2; //channel bandwidth 20MHz or 40 MHz - UINT32 rsv2:1; - UINT32 TxBF:1; // 3*3 - UINT32 PHYMODE:2; - // Word1 - // ex: 1c ff 38 00 means ACK=0, BAWinSize=7, MPDUtotalByteCount = 0x38 - UINT32 ACK:1; - UINT32 NSEQ:1; - UINT32 BAWinSize:6; - UINT32 WirelessCliID:8; - UINT32 MPDUtotalByteCount:12; - UINT32 PacketId:4; - //Word2 - UINT32 IV; - //Word3 - UINT32 EIV; -} TXWI_STRUC, *PTXWI_STRUC; -#endif - - -// -// RXWI wireless information format, in PBF. invisible in driver. -// -#ifdef RT_BIG_ENDIAN -typedef struct PACKED _RXWI_STRUC { - // Word 0 - UINT32 TID:4; - UINT32 MPDUtotalByteCount:12; - UINT32 UDF:3; - UINT32 BSSID:3; - UINT32 KeyIndex:2; - UINT32 WirelessCliID:8; - // Word 1 - UINT32 PHYMODE:2; // 1: this RX frame is unicast to me - UINT32 rsv:3; - UINT32 STBC:2; - UINT32 ShortGI:1; - UINT32 BW:1; - UINT32 MCS:7; - UINT32 SEQUENCE:12; - UINT32 FRAG:4; - // Word 2 - UINT32 rsv1:8; - UINT32 RSSI2:8; - UINT32 RSSI1:8; - UINT32 RSSI0:8; - // Word 3 - /*UINT32 rsv2:16;*/ - UINT32 rsv2:8; - UINT32 FOFFSET:8; // RT35xx - UINT32 SNR1:8; - UINT32 SNR0:8; -} RXWI_STRUC, *PRXWI_STRUC; -#else -typedef struct PACKED _RXWI_STRUC { - // Word 0 - UINT32 WirelessCliID:8; - UINT32 KeyIndex:2; - UINT32 BSSID:3; - UINT32 UDF:3; - UINT32 MPDUtotalByteCount:12; - UINT32 TID:4; - // Word 1 - UINT32 FRAG:4; - UINT32 SEQUENCE:12; - UINT32 MCS:7; - UINT32 BW:1; - UINT32 ShortGI:1; - UINT32 STBC:2; - UINT32 rsv:3; - UINT32 PHYMODE:2; // 1: this RX frame is unicast to me - //Word2 - UINT32 RSSI0:8; - UINT32 RSSI1:8; - UINT32 RSSI2:8; - UINT32 rsv1:8; - //Word3 - UINT32 SNR0:8; - UINT32 SNR1:8; - UINT32 FOFFSET:8; // RT35xx - UINT32 rsv2:8; - /*UINT32 rsv2:16;*/ -} RXWI_STRUC, *PRXWI_STRUC; -#endif - - -// ================================================================================= -// Register format -// ================================================================================= - - -// -// SCH/DMA registers - base address 0x0200 -// -// INT_SOURCE_CSR: Interrupt source register. Write one to clear corresponding bit -// -#define DMA_CSR0 0x200 -#define INT_SOURCE_CSR 0x200 -#ifdef RT_BIG_ENDIAN -typedef union _INT_SOURCE_CSR_STRUC { - struct { -#ifdef TONE_RADAR_DETECT_SUPPORT - UINT32 :11; - UINT32 RadarINT:1; - UINT32 rsv:2; -#else // original source code - UINT32 :14; -#endif // TONE_RADAR_DETECT_SUPPORT // - UINT32 TxCoherent:1; - UINT32 RxCoherent:1; - UINT32 GPTimer:1; - UINT32 AutoWakeup:1;//bit14 - UINT32 TXFifoStatusInt:1;//FIFO Statistics is full, sw should read 0x171c - UINT32 PreTBTT:1; - UINT32 TBTTInt:1; - UINT32 RxTxCoherent:1; - UINT32 MCUCommandINT:1; - UINT32 MgmtDmaDone:1; - UINT32 HccaDmaDone:1; - UINT32 Ac3DmaDone:1; - UINT32 Ac2DmaDone:1; - UINT32 Ac1DmaDone:1; - UINT32 Ac0DmaDone:1; - UINT32 RxDone:1; - UINT32 TxDelayINT:1; //delayed interrupt, not interrupt until several int or time limit hit - UINT32 RxDelayINT:1; //dealyed interrupt - } field; - UINT32 word; -} INT_SOURCE_CSR_STRUC, *PINT_SOURCE_CSR_STRUC; -#else -typedef union _INT_SOURCE_CSR_STRUC { - struct { - UINT32 RxDelayINT:1; - UINT32 TxDelayINT:1; - UINT32 RxDone:1; - UINT32 Ac0DmaDone:1;//4 - UINT32 Ac1DmaDone:1; - UINT32 Ac2DmaDone:1; - UINT32 Ac3DmaDone:1; - UINT32 HccaDmaDone:1; // bit7 - UINT32 MgmtDmaDone:1; - UINT32 MCUCommandINT:1;//bit 9 - UINT32 RxTxCoherent:1; - UINT32 TBTTInt:1; - UINT32 PreTBTT:1; - UINT32 TXFifoStatusInt:1;//FIFO Statistics is full, sw should read 0x171c - UINT32 AutoWakeup:1;//bit14 - UINT32 GPTimer:1; - UINT32 RxCoherent:1;//bit16 - UINT32 TxCoherent:1; -#ifdef TONE_RADAR_DETECT_SUPPORT - UINT32 rsv:2; - UINT32 RadarINT:1; - UINT32 :11; -#else - UINT32 :14; -#endif // TONE_RADAR_DETECT_SUPPORT // - } field; - UINT32 word; -} INT_SOURCE_CSR_STRUC, *PINT_SOURCE_CSR_STRUC; -#endif - -// -// INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF -// -#define INT_MASK_CSR 0x204 -#ifdef RT_BIG_ENDIAN -typedef union _INT_MASK_CSR_STRUC { - struct { - UINT32 TxCoherent:1; - UINT32 RxCoherent:1; -#ifdef TONE_RADAR_DETECT_SUPPORT - UINT32 :9; - UINT32 RadarINT:1; - UINT32 rsv:10; -#else - UINT32 :20; -#endif // TONE_RADAR_DETECT_SUPPORT // - UINT32 MCUCommandINT:1; - UINT32 MgmtDmaDone:1; - UINT32 HccaDmaDone:1; - UINT32 Ac3DmaDone:1; - UINT32 Ac2DmaDone:1; - UINT32 Ac1DmaDone:1; - UINT32 Ac0DmaDone:1; - UINT32 RxDone:1; - UINT32 TxDelay:1; - UINT32 RXDelay_INT_MSK:1; - } field; - UINT32 word; -}INT_MASK_CSR_STRUC, *PINT_MASK_CSR_STRUC; -#else -typedef union _INT_MASK_CSR_STRUC { - struct { - UINT32 RXDelay_INT_MSK:1; - UINT32 TxDelay:1; - UINT32 RxDone:1; - UINT32 Ac0DmaDone:1; - UINT32 Ac1DmaDone:1; - UINT32 Ac2DmaDone:1; - UINT32 Ac3DmaDone:1; - UINT32 HccaDmaDone:1; - UINT32 MgmtDmaDone:1; - UINT32 MCUCommandINT:1; -#ifdef TONE_RADAR_DETECT_SUPPORT - UINT32 rsv:10; - UINT32 RadarINT:1; - UINT32 :9; -#else - UINT32 :20; -#endif // TONE_RADAR_DETECT_SUPPORT // - UINT32 RxCoherent:1; - UINT32 TxCoherent:1; - } field; - UINT32 word; -} INT_MASK_CSR_STRUC, *PINT_MASK_CSR_STRUC; -#endif - -#define WPDMA_GLO_CFG 0x208 -#ifdef RT_BIG_ENDIAN -typedef union _WPDMA_GLO_CFG_STRUC { - struct { - UINT32 HDR_SEG_LEN:16; - UINT32 RXHdrScater:8; - UINT32 BigEndian:1; - UINT32 EnTXWriteBackDDONE:1; - UINT32 WPDMABurstSIZE:2; - UINT32 RxDMABusy:1; - UINT32 EnableRxDMA:1; - UINT32 TxDMABusy:1; - UINT32 EnableTxDMA:1; - } field; - UINT32 word; -}WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC; -#else -typedef union _WPDMA_GLO_CFG_STRUC { - struct { - UINT32 EnableTxDMA:1; - UINT32 TxDMABusy:1; - UINT32 EnableRxDMA:1; - UINT32 RxDMABusy:1; - UINT32 WPDMABurstSIZE:2; - UINT32 EnTXWriteBackDDONE:1; - UINT32 BigEndian:1; - UINT32 RXHdrScater:8; - UINT32 HDR_SEG_LEN:16; - } field; - UINT32 word; -} WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC; -#endif - -#define WPDMA_RST_IDX 0x20c -#ifdef RT_BIG_ENDIAN -typedef union _WPDMA_RST_IDX_STRUC { - struct { - UINT32 :15; - UINT32 RST_DRX_IDX0:1; - UINT32 rsv:10; - UINT32 RST_DTX_IDX5:1; - UINT32 RST_DTX_IDX4:1; - UINT32 RST_DTX_IDX3:1; - UINT32 RST_DTX_IDX2:1; - UINT32 RST_DTX_IDX1:1; - UINT32 RST_DTX_IDX0:1; - } field; - UINT32 word; -}WPDMA_RST_IDX_STRUC, *PWPDMA_RST_IDX_STRUC; -#else -typedef union _WPDMA_RST_IDX_STRUC { - struct { - UINT32 RST_DTX_IDX0:1; - UINT32 RST_DTX_IDX1:1; - UINT32 RST_DTX_IDX2:1; - UINT32 RST_DTX_IDX3:1; - UINT32 RST_DTX_IDX4:1; - UINT32 RST_DTX_IDX5:1; - UINT32 rsv:10; - UINT32 RST_DRX_IDX0:1; - UINT32 :15; - } field; - UINT32 word; -} WPDMA_RST_IDX_STRUC, *PWPDMA_RST_IDX_STRUC; -#endif -#define DELAY_INT_CFG 0x0210 -#ifdef RT_BIG_ENDIAN -typedef union _DELAY_INT_CFG_STRUC { - struct { - UINT32 TXDLY_INT_EN:1; - UINT32 TXMAX_PINT:7; - UINT32 TXMAX_PTIME:8; - UINT32 RXDLY_INT_EN:1; - UINT32 RXMAX_PINT:7; - UINT32 RXMAX_PTIME:8; - } field; - UINT32 word; -}DELAY_INT_CFG_STRUC, *PDELAY_INT_CFG_STRUC; -#else -typedef union _DELAY_INT_CFG_STRUC { - struct { - UINT32 RXMAX_PTIME:8; - UINT32 RXMAX_PINT:7; - UINT32 RXDLY_INT_EN:1; - UINT32 TXMAX_PTIME:8; - UINT32 TXMAX_PINT:7; - UINT32 TXDLY_INT_EN:1; - } field; - UINT32 word; -} DELAY_INT_CFG_STRUC, *PDELAY_INT_CFG_STRUC; -#endif -#define WMM_AIFSN_CFG 0x0214 -#ifdef RT_BIG_ENDIAN -typedef union _AIFSN_CSR_STRUC { - struct { - UINT32 Rsv:16; - UINT32 Aifsn3:4; // for AC_VO - UINT32 Aifsn2:4; // for AC_VI - UINT32 Aifsn1:4; // for AC_BK - UINT32 Aifsn0:4; // for AC_BE - } field; - UINT32 word; -} AIFSN_CSR_STRUC, *PAIFSN_CSR_STRUC; -#else -typedef union _AIFSN_CSR_STRUC { - struct { - UINT32 Aifsn0:4; // for AC_BE - UINT32 Aifsn1:4; // for AC_BK - UINT32 Aifsn2:4; // for AC_VI - UINT32 Aifsn3:4; // for AC_VO - UINT32 Rsv:16; - } field; - UINT32 word; -} AIFSN_CSR_STRUC, *PAIFSN_CSR_STRUC; -#endif -// -// CWMIN_CSR: CWmin for each EDCA AC -// -#define WMM_CWMIN_CFG 0x0218 -#ifdef RT_BIG_ENDIAN -typedef union _CWMIN_CSR_STRUC { - struct { - UINT32 Rsv:16; - UINT32 Cwmin3:4; // for AC_VO - UINT32 Cwmin2:4; // for AC_VI - UINT32 Cwmin1:4; // for AC_BK - UINT32 Cwmin0:4; // for AC_BE - } field; - UINT32 word; -} CWMIN_CSR_STRUC, *PCWMIN_CSR_STRUC; -#else -typedef union _CWMIN_CSR_STRUC { - struct { - UINT32 Cwmin0:4; // for AC_BE - UINT32 Cwmin1:4; // for AC_BK - UINT32 Cwmin2:4; // for AC_VI - UINT32 Cwmin3:4; // for AC_VO - UINT32 Rsv:16; - } field; - UINT32 word; -} CWMIN_CSR_STRUC, *PCWMIN_CSR_STRUC; -#endif - -// -// CWMAX_CSR: CWmin for each EDCA AC -// -#define WMM_CWMAX_CFG 0x021c -#ifdef RT_BIG_ENDIAN -typedef union _CWMAX_CSR_STRUC { - struct { - UINT32 Rsv:16; - UINT32 Cwmax3:4; // for AC_VO - UINT32 Cwmax2:4; // for AC_VI - UINT32 Cwmax1:4; // for AC_BK - UINT32 Cwmax0:4; // for AC_BE - } field; - UINT32 word; -} CWMAX_CSR_STRUC, *PCWMAX_CSR_STRUC; -#else -typedef union _CWMAX_CSR_STRUC { - struct { - UINT32 Cwmax0:4; // for AC_BE - UINT32 Cwmax1:4; // for AC_BK - UINT32 Cwmax2:4; // for AC_VI - UINT32 Cwmax3:4; // for AC_VO - UINT32 Rsv:16; - } field; - UINT32 word; -} CWMAX_CSR_STRUC, *PCWMAX_CSR_STRUC; -#endif - - -// -// AC_TXOP_CSR0: AC_BK/AC_BE TXOP register -// -#define WMM_TXOP0_CFG 0x0220 -#ifdef RT_BIG_ENDIAN -typedef union _AC_TXOP_CSR0_STRUC { - struct { - USHORT Ac1Txop; // for AC_BE, in unit of 32us - USHORT Ac0Txop; // for AC_BK, in unit of 32us - } field; - UINT32 word; -} AC_TXOP_CSR0_STRUC, *PAC_TXOP_CSR0_STRUC; -#else -typedef union _AC_TXOP_CSR0_STRUC { - struct { - USHORT Ac0Txop; // for AC_BK, in unit of 32us - USHORT Ac1Txop; // for AC_BE, in unit of 32us - } field; - UINT32 word; -} AC_TXOP_CSR0_STRUC, *PAC_TXOP_CSR0_STRUC; -#endif - -// -// AC_TXOP_CSR1: AC_VO/AC_VI TXOP register -// -#define WMM_TXOP1_CFG 0x0224 -#ifdef RT_BIG_ENDIAN -typedef union _AC_TXOP_CSR1_STRUC { - struct { - USHORT Ac3Txop; // for AC_VO, in unit of 32us - USHORT Ac2Txop; // for AC_VI, in unit of 32us - } field; - UINT32 word; -} AC_TXOP_CSR1_STRUC, *PAC_TXOP_CSR1_STRUC; -#else -typedef union _AC_TXOP_CSR1_STRUC { - struct { - USHORT Ac2Txop; // for AC_VI, in unit of 32us - USHORT Ac3Txop; // for AC_VO, in unit of 32us - } field; - UINT32 word; -} AC_TXOP_CSR1_STRUC, *PAC_TXOP_CSR1_STRUC; -#endif - - -#define RINGREG_DIFF 0x10 -#define GPIO_CTRL_CFG 0x0228 //MAC_CSR13 -#define MCU_CMD_CFG 0x022c -#define TX_BASE_PTR0 0x0230 //AC_BK base address -#define TX_MAX_CNT0 0x0234 -#define TX_CTX_IDX0 0x0238 -#define TX_DTX_IDX0 0x023c -#define TX_BASE_PTR1 0x0240 //AC_BE base address -#define TX_MAX_CNT1 0x0244 -#define TX_CTX_IDX1 0x0248 -#define TX_DTX_IDX1 0x024c -#define TX_BASE_PTR2 0x0250 //AC_VI base address -#define TX_MAX_CNT2 0x0254 -#define TX_CTX_IDX2 0x0258 -#define TX_DTX_IDX2 0x025c -#define TX_BASE_PTR3 0x0260 //AC_VO base address -#define TX_MAX_CNT3 0x0264 -#define TX_CTX_IDX3 0x0268 -#define TX_DTX_IDX3 0x026c -#define TX_BASE_PTR4 0x0270 //HCCA base address -#define TX_MAX_CNT4 0x0274 -#define TX_CTX_IDX4 0x0278 -#define TX_DTX_IDX4 0x027c -#define TX_BASE_PTR5 0x0280 //MGMT base address -#define TX_MAX_CNT5 0x0284 -#define TX_CTX_IDX5 0x0288 -#define TX_DTX_IDX5 0x028c -#define TX_MGMTMAX_CNT TX_MAX_CNT5 -#define TX_MGMTCTX_IDX TX_CTX_IDX5 -#define TX_MGMTDTX_IDX TX_DTX_IDX5 -#define RX_BASE_PTR 0x0290 //RX base address -#define RX_MAX_CNT 0x0294 -#define RX_CRX_IDX 0x0298 -#define RX_DRX_IDX 0x029c - - -#define USB_DMA_CFG 0x02a0 -#ifdef RT_BIG_ENDIAN -typedef union _USB_DMA_CFG_STRUC { - struct { - UINT32 TxBusy:1; //USB DMA TX FSM busy . debug only - UINT32 RxBusy:1; //USB DMA RX FSM busy . debug only - UINT32 EpoutValid:6; //OUT endpoint data valid. debug only - UINT32 TxBulkEn:1; //Enable USB DMA Tx - UINT32 RxBulkEn:1; //Enable USB DMA Rx - UINT32 RxBulkAggEn:1; //Enable Rx Bulk Aggregation - UINT32 TxopHalt:1; //Halt TXOP count down when TX buffer is full. - UINT32 TxClear:1; //Clear USB DMA TX path - UINT32 rsv:2; - UINT32 phyclear:1; //phy watch dog enable. write 1 - UINT32 RxBulkAggLmt:8; //Rx Bulk Aggregation Limit in unit of 1024 bytes - UINT32 RxBulkAggTOut:8; //Rx Bulk Aggregation TimeOut in unit of 33ns - } field; - UINT32 word; -} USB_DMA_CFG_STRUC, *PUSB_DMA_CFG_STRUC; -#else -typedef union _USB_DMA_CFG_STRUC { - struct { - UINT32 RxBulkAggTOut:8; //Rx Bulk Aggregation TimeOut in unit of 33ns - UINT32 RxBulkAggLmt:8; //Rx Bulk Aggregation Limit in unit of 256 bytes - UINT32 phyclear:1; //phy watch dog enable. write 1 - UINT32 rsv:2; - UINT32 TxClear:1; //Clear USB DMA TX path - UINT32 TxopHalt:1; //Halt TXOP count down when TX buffer is full. - UINT32 RxBulkAggEn:1; //Enable Rx Bulk Aggregation - UINT32 RxBulkEn:1; //Enable USB DMA Rx - UINT32 TxBulkEn:1; //Enable USB DMA Tx - UINT32 EpoutValid:6; //OUT endpoint data valid - UINT32 RxBusy:1; //USB DMA RX FSM busy - UINT32 TxBusy:1; //USB DMA TX FSM busy - } field; - UINT32 word; -} USB_DMA_CFG_STRUC, *PUSB_DMA_CFG_STRUC; -#endif - - -// -// 3 PBF registers -// -// -// Most are for debug. Driver doesn't touch PBF register. -#define PBF_SYS_CTRL 0x0400 -#define PBF_CFG 0x0408 -#define PBF_MAX_PCNT 0x040C -#define PBF_CTRL 0x0410 -#define PBF_INT_STA 0x0414 -#define PBF_INT_ENA 0x0418 -#define TXRXQ_PCNT 0x0438 -#define PBF_DBG 0x043c -#define PBF_CAP_CTRL 0x0440 - -#ifdef RT30xx -#ifdef RTMP_EFUSE_SUPPORT -// eFuse registers -#define EFUSE_CTRL 0x0580 -#define EFUSE_DATA0 0x0590 -#define EFUSE_DATA1 0x0594 -#define EFUSE_DATA2 0x0598 -#define EFUSE_DATA3 0x059c -#endif // RTMP_EFUSE_SUPPORT // -#endif // RT30xx // - -#define OSC_CTRL 0x5a4 -#define PCIE_PHY_TX_ATTENUATION_CTRL 0x05C8 -#define LDO_CFG0 0x05d4 -#define GPIO_SWITCH 0x05dc - - -// -// 4 MAC registers -// -// -// 4.1 MAC SYSTEM configuration registers (offset:0x1000) -// -#define MAC_CSR0 0x1000 -#ifdef RT_BIG_ENDIAN -typedef union _ASIC_VER_ID_STRUC { - struct { - USHORT ASICVer; // version : 2860 - USHORT ASICRev; // reversion : 0 - } field; - UINT32 word; -} ASIC_VER_ID_STRUC, *PASIC_VER_ID_STRUC; -#else -typedef union _ASIC_VER_ID_STRUC { - struct { - USHORT ASICRev; // reversion : 0 - USHORT ASICVer; // version : 2860 - } field; - UINT32 word; -} ASIC_VER_ID_STRUC, *PASIC_VER_ID_STRUC; -#endif -#define MAC_SYS_CTRL 0x1004 //MAC_CSR1 -#define MAC_ADDR_DW0 0x1008 // MAC ADDR DW0 -#define MAC_ADDR_DW1 0x100c // MAC ADDR DW1 -// -// MAC_CSR2: STA MAC register 0 -// -#ifdef RT_BIG_ENDIAN -typedef union _MAC_DW0_STRUC { - struct { - UCHAR Byte3; // MAC address byte 3 - UCHAR Byte2; // MAC address byte 2 - UCHAR Byte1; // MAC address byte 1 - UCHAR Byte0; // MAC address byte 0 - } field; - UINT32 word; -} MAC_DW0_STRUC, *PMAC_DW0_STRUC; -#else -typedef union _MAC_DW0_STRUC { - struct { - UCHAR Byte0; // MAC address byte 0 - UCHAR Byte1; // MAC address byte 1 - UCHAR Byte2; // MAC address byte 2 - UCHAR Byte3; // MAC address byte 3 - } field; - UINT32 word; -} MAC_DW0_STRUC, *PMAC_DW0_STRUC; -#endif - -// -// MAC_CSR3: STA MAC register 1 -// -#ifdef RT_BIG_ENDIAN -typedef union _MAC_DW1_STRUC { - struct { - UCHAR Rsvd1; - UCHAR U2MeMask; - UCHAR Byte5; // MAC address byte 5 - UCHAR Byte4; // MAC address byte 4 - } field; - UINT32 word; -} MAC_DW1_STRUC, *PMAC_DW1_STRUC; -#else -typedef union _MAC_DW1_STRUC { - struct { - UCHAR Byte4; // MAC address byte 4 - UCHAR Byte5; // MAC address byte 5 - UCHAR U2MeMask; - UCHAR Rsvd1; - } field; - UINT32 word; -} MAC_DW1_STRUC, *PMAC_DW1_STRUC; -#endif - -#define MAC_BSSID_DW0 0x1010 // MAC BSSID DW0 -#define MAC_BSSID_DW1 0x1014 // MAC BSSID DW1 - -// -// MAC_CSR5: BSSID register 1 -// -#ifdef RT_BIG_ENDIAN -typedef union _MAC_CSR5_STRUC { - struct { - USHORT Rsvd:11; - USHORT MBssBcnNum:3; - USHORT BssIdMode:2; // 0: one BSSID, 10: 4 BSSID, 01: 2 BSSID , 11: 8BSSID - UCHAR Byte5; // BSSID byte 5 - UCHAR Byte4; // BSSID byte 4 - } field; - UINT32 word; -} MAC_CSR5_STRUC, *PMAC_CSR5_STRUC; -#else -typedef union _MAC_CSR5_STRUC { - struct { - UCHAR Byte4; // BSSID byte 4 - UCHAR Byte5; // BSSID byte 5 - USHORT BssIdMask:2; // 0: one BSSID, 10: 4 BSSID, 01: 2 BSSID , 11: 8BSSID - USHORT MBssBcnNum:3; - USHORT Rsvd:11; - } field; - UINT32 word; -} MAC_CSR5_STRUC, *PMAC_CSR5_STRUC; -#endif - -#define MAX_LEN_CFG 0x1018 // rt2860b max 16k bytes. bit12:13 Maximum PSDU length (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 -#define BBP_CSR_CFG 0x101c // -// -// BBP_CSR_CFG: BBP serial control register -// -#ifdef RT_BIG_ENDIAN -typedef union _BBP_CSR_CFG_STRUC { - struct { - UINT32 :12; - UINT32 BBP_RW_MODE:1; // 0: use serial mode 1:parallel - UINT32 BBP_PAR_DUR:1; // 0: 4 MAC clock cycles 1: 8 MAC clock cycles - UINT32 Busy:1; // 1: ASIC is busy execute BBP programming. - UINT32 fRead:1; // 0: Write BBP, 1: Read BBP - UINT32 RegNum:8; // Selected BBP register - UINT32 Value:8; // Register value to program into BBP - } field; - UINT32 word; -} BBP_CSR_CFG_STRUC, *PBBP_CSR_CFG_STRUC; -#else -typedef union _BBP_CSR_CFG_STRUC { - struct { - UINT32 Value:8; // Register value to program into BBP - UINT32 RegNum:8; // Selected BBP register - UINT32 fRead:1; // 0: Write BBP, 1: Read BBP - UINT32 Busy:1; // 1: ASIC is busy execute BBP programming. - UINT32 BBP_PAR_DUR:1; // 0: 4 MAC clock cycles 1: 8 MAC clock cycles - UINT32 BBP_RW_MODE:1; // 0: use serial mode 1:parallel - UINT32 :12; - } field; - UINT32 word; -} BBP_CSR_CFG_STRUC, *PBBP_CSR_CFG_STRUC; -#endif -#define RF_CSR_CFG0 0x1020 -// -// RF_CSR_CFG: RF control register -// -#ifdef RT_BIG_ENDIAN -typedef union _RF_CSR_CFG0_STRUC { - struct { - UINT32 Busy:1; // 0: idle 1: 8busy - UINT32 Sel:1; // 0:RF_LE0 activate 1:RF_LE1 activate - UINT32 StandbyMode:1; // 0: high when stand by 1: low when standby - UINT32 bitwidth:5; // Selected BBP register - UINT32 RegIdAndContent:24; // Register value to program into BBP - } field; - UINT32 word; -} RF_CSR_CFG0_STRUC, *PRF_CSR_CFG0_STRUC; -#else -typedef union _RF_CSR_CFG0_STRUC { - struct { - UINT32 RegIdAndContent:24; // Register value to program into BBP - UINT32 bitwidth:5; // Selected BBP register - UINT32 StandbyMode:1; // 0: high when stand by 1: low when standby - UINT32 Sel:1; // 0:RF_LE0 activate 1:RF_LE1 activate - UINT32 Busy:1; // 0: idle 1: 8busy - } field; - UINT32 word; -} RF_CSR_CFG0_STRUC, *PRF_CSR_CFG0_STRUC; -#endif -#define RF_CSR_CFG1 0x1024 -#ifdef RT_BIG_ENDIAN -typedef union _RF_CSR_CFG1_STRUC { - struct { - UINT32 rsv:7; // 0: idle 1: 8busy - UINT32 RFGap:5; // Gap between BB_CONTROL_RF and RF_LE. 0: 3 system clock cycle (37.5usec) 1: 5 system clock cycle (62.5usec) - UINT32 RegIdAndContent:24; // Register value to program into BBP - } field; - UINT32 word; -} RF_CSR_CFG1_STRUC, *PRF_CSR_CFG1_STRUC; -#else -typedef union _RF_CSR_CFG1_STRUC { - struct { - UINT32 RegIdAndContent:24; // Register value to program into BBP - UINT32 RFGap:5; // Gap between BB_CONTROL_RF and RF_LE. 0: 3 system clock cycle (37.5usec) 1: 5 system clock cycle (62.5usec) - UINT32 rsv:7; // 0: idle 1: 8busy - } field; - UINT32 word; -} RF_CSR_CFG1_STRUC, *PRF_CSR_CFG1_STRUC; -#endif -#define RF_CSR_CFG2 0x1028 // -#ifdef RT_BIG_ENDIAN -typedef union _RF_CSR_CFG2_STRUC { - struct { - UINT32 rsv:8; // 0: idle 1: 8busy - UINT32 RegIdAndContent:24; // Register value to program into BBP - } field; - UINT32 word; -} RF_CSR_CFG2_STRUC, *PRF_CSR_CFG2_STRUC; -#else -typedef union _RF_CSR_CFG2_STRUC { - struct { - UINT32 RegIdAndContent:24; // Register value to program into BBP - UINT32 rsv:8; // 0: idle 1: 8busy - } field; - UINT32 word; -} RF_CSR_CFG2_STRUC, *PRF_CSR_CFG2_STRUC; -#endif -#define LED_CFG 0x102c // MAC_CSR14 -#ifdef RT_BIG_ENDIAN -typedef union _LED_CFG_STRUC { - struct { - UINT32 :1; - UINT32 LedPolar:1; // Led Polarity. 0: active low1: active high - UINT32 YLedMode:2; // yellow Led Mode - UINT32 GLedMode:2; // green Led Mode - UINT32 RLedMode:2; // red Led Mode 0: off1: blinking upon TX2: periodic slow blinking3: always on - UINT32 rsv:2; - UINT32 SlowBlinkPeriod:6; // slow blinking period. unit:1ms - UINT32 OffPeriod:8; // blinking off period unit 1ms - UINT32 OnPeriod:8; // blinking on period unit 1ms - } field; - UINT32 word; -} LED_CFG_STRUC, *PLED_CFG_STRUC; -#else -typedef union _LED_CFG_STRUC { - struct { - UINT32 OnPeriod:8; // blinking on period unit 1ms - UINT32 OffPeriod:8; // blinking off period unit 1ms - UINT32 SlowBlinkPeriod:6; // slow blinking period. unit:1ms - UINT32 rsv:2; - UINT32 RLedMode:2; // red Led Mode 0: off1: blinking upon TX2: periodic slow blinking3: always on - UINT32 GLedMode:2; // green Led Mode - UINT32 YLedMode:2; // yellow Led Mode - UINT32 LedPolar:1; // Led Polarity. 0: active low1: active high - UINT32 :1; - } field; - UINT32 word; -} LED_CFG_STRUC, *PLED_CFG_STRUC; -#endif -// -// 4.2 MAC TIMING configuration registers (offset:0x1100) -// -#define XIFS_TIME_CFG 0x1100 // MAC_CSR8 MAC_CSR9 -#ifdef RT_BIG_ENDIAN -typedef union _IFS_SLOT_CFG_STRUC { - struct { - UINT32 rsv:2; - UINT32 BBRxendEnable:1; // reference RXEND signal to begin XIFS defer - UINT32 EIFS:9; // unit 1us - UINT32 OfdmXifsTime:4; //OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND - UINT32 OfdmSifsTime:8; // unit 1us. Applied after OFDM RX/TX - UINT32 CckmSifsTime:8; // unit 1us. Applied after CCK RX/TX - } field; - UINT32 word; -} IFS_SLOT_CFG_STRUC, *PIFS_SLOT_CFG_STRUC; -#else -typedef union _IFS_SLOT_CFG_STRUC { - struct { - UINT32 CckmSifsTime:8; // unit 1us. Applied after CCK RX/TX - UINT32 OfdmSifsTime:8; // unit 1us. Applied after OFDM RX/TX - UINT32 OfdmXifsTime:4; //OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND - UINT32 EIFS:9; // unit 1us - UINT32 BBRxendEnable:1; // reference RXEND signal to begin XIFS defer - UINT32 rsv:2; - } field; - UINT32 word; -} IFS_SLOT_CFG_STRUC, *PIFS_SLOT_CFG_STRUC; -#endif - -#define BKOFF_SLOT_CFG 0x1104 // mac_csr9 last 8 bits -#define NAV_TIME_CFG 0x1108 // NAV (MAC_CSR15) -#define CH_TIME_CFG 0x110C // Count as channel busy -#define PBF_LIFE_TIMER 0x1110 //TX/RX MPDU timestamp timer (free run)Unit: 1us -#define BCN_TIME_CFG 0x1114 // TXRX_CSR9 - -#define BCN_OFFSET0 0x042C -#define BCN_OFFSET1 0x0430 - -// -// BCN_TIME_CFG : Synchronization control register -// -#ifdef RT_BIG_ENDIAN -typedef union _BCN_TIME_CFG_STRUC { - struct { - UINT32 TxTimestampCompensate:8; - UINT32 :3; - UINT32 bBeaconGen:1; // Enable beacon generator - UINT32 bTBTTEnable:1; - UINT32 TsfSyncMode:2; // Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode - UINT32 bTsfTicking:1; // Enable TSF auto counting - UINT32 BeaconInterval:16; // in unit of 1/16 TU - } field; - UINT32 word; -} BCN_TIME_CFG_STRUC, *PBCN_TIME_CFG_STRUC; -#else -typedef union _BCN_TIME_CFG_STRUC { - struct { - UINT32 BeaconInterval:16; // in unit of 1/16 TU - UINT32 bTsfTicking:1; // Enable TSF auto counting - UINT32 TsfSyncMode:2; // Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode - UINT32 bTBTTEnable:1; - UINT32 bBeaconGen:1; // Enable beacon generator - UINT32 :3; - UINT32 TxTimestampCompensate:8; - } field; - UINT32 word; -} BCN_TIME_CFG_STRUC, *PBCN_TIME_CFG_STRUC; -#endif -#define TBTT_SYNC_CFG 0x1118 // txrx_csr10 -#define TSF_TIMER_DW0 0x111C // Local TSF timer lsb 32 bits. Read-only -#define TSF_TIMER_DW1 0x1120 // msb 32 bits. Read-only. -#define TBTT_TIMER 0x1124 // TImer remains till next TBTT. Read-only. TXRX_CSR14 -#define INT_TIMER_CFG 0x1128 // -#define INT_TIMER_EN 0x112c // GP-timer and pre-tbtt Int enable -#define CH_IDLE_STA 0x1130 // channel idle time -#define CH_BUSY_STA 0x1134 // channle busy time -// -// 4.2 MAC POWER configuration registers (offset:0x1200) -// -#define MAC_STATUS_CFG 0x1200 // old MAC_CSR12 -#define PWR_PIN_CFG 0x1204 // old MAC_CSR12 -#define AUTO_WAKEUP_CFG 0x1208 // old MAC_CSR10 -// -// AUTO_WAKEUP_CFG: Manual power control / status register -// -#ifdef RT_BIG_ENDIAN -typedef union _AUTO_WAKEUP_STRUC { - struct { - UINT32 :16; - UINT32 EnableAutoWakeup:1; // 0:sleep, 1:awake - UINT32 NumofSleepingTbtt:7; // ForceWake has high privilege than PutToSleep when both set - UINT32 AutoLeadTime:8; - } field; - UINT32 word; -} AUTO_WAKEUP_STRUC, *PAUTO_WAKEUP_STRUC; -#else -typedef union _AUTO_WAKEUP_STRUC { - struct { - UINT32 AutoLeadTime:8; - UINT32 NumofSleepingTbtt:7; // ForceWake has high privilege than PutToSleep when both set - UINT32 EnableAutoWakeup:1; // 0:sleep, 1:awake - UINT32 :16; - } field; - UINT32 word; -} AUTO_WAKEUP_STRUC, *PAUTO_WAKEUP_STRUC; -#endif -// -// 4.3 MAC TX configuration registers (offset:0x1300) -// - -#define EDCA_AC0_CFG 0x1300 //AC_TXOP_CSR0 0x3474 -#define EDCA_AC1_CFG 0x1304 -#define EDCA_AC2_CFG 0x1308 -#define EDCA_AC3_CFG 0x130c -#ifdef RT_BIG_ENDIAN -typedef union _EDCA_AC_CFG_STRUC { - struct { - UINT32 :12; // - UINT32 Cwmax:4; //unit power of 2 - UINT32 Cwmin:4; // - UINT32 Aifsn:4; // # of slot time - UINT32 AcTxop:8; // in unit of 32us - } field; - UINT32 word; -} EDCA_AC_CFG_STRUC, *PEDCA_AC_CFG_STRUC; -#else -typedef union _EDCA_AC_CFG_STRUC { - struct { - UINT32 AcTxop:8; // in unit of 32us - UINT32 Aifsn:4; // # of slot time - UINT32 Cwmin:4; // - UINT32 Cwmax:4; //unit power of 2 - UINT32 :12; // - } field; - UINT32 word; -} EDCA_AC_CFG_STRUC, *PEDCA_AC_CFG_STRUC; -#endif - -#define EDCA_TID_AC_MAP 0x1310 -#define TX_PWR_CFG_0 0x1314 -#define TX_PWR_CFG_1 0x1318 -#define TX_PWR_CFG_2 0x131C -#define TX_PWR_CFG_3 0x1320 -#define TX_PWR_CFG_4 0x1324 -#define TX_PIN_CFG 0x1328 -#define TX_BAND_CFG 0x132c // 0x1 use upper 20MHz. 0 juse lower 20MHz -#define TX_SW_CFG0 0x1330 -#define TX_SW_CFG1 0x1334 -#define TX_SW_CFG2 0x1338 -#define TXOP_THRES_CFG 0x133c -#define TXOP_CTRL_CFG 0x1340 -#define TX_RTS_CFG 0x1344 - -#ifdef RT_BIG_ENDIAN -typedef union _TX_RTS_CFG_STRUC { - struct { - UINT32 rsv:7; - UINT32 RtsFbkEn:1; // enable rts rate fallback - UINT32 RtsThres:16; // unit:byte - UINT32 AutoRtsRetryLimit:8; - } field; - UINT32 word; -} TX_RTS_CFG_STRUC, *PTX_RTS_CFG_STRUC; -#else -typedef union _TX_RTS_CFG_STRUC { - struct { - UINT32 AutoRtsRetryLimit:8; - UINT32 RtsThres:16; // unit:byte - UINT32 RtsFbkEn:1; // enable rts rate fallback - UINT32 rsv:7; // 1: HT non-STBC control frame enable - } field; - UINT32 word; -} TX_RTS_CFG_STRUC, *PTX_RTS_CFG_STRUC; -#endif -#define TX_TIMEOUT_CFG 0x1348 -#ifdef RT_BIG_ENDIAN -typedef union _TX_TIMEOUT_CFG_STRUC { - struct { - UINT32 rsv2:8; - UINT32 TxopTimeout:8; //TXOP timeout value for TXOP truncation. It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) - UINT32 RxAckTimeout:8; // unit:slot. Used for TX precedure - UINT32 MpduLifeTime:4; // expiration time = 2^(9+MPDU LIFE TIME) us - UINT32 rsv:4; - } field; - UINT32 word; -} TX_TIMEOUT_CFG_STRUC, *PTX_TIMEOUT_CFG_STRUC; -#else -typedef union _TX_TIMEOUT_CFG_STRUC { - struct { - UINT32 rsv:4; - UINT32 MpduLifeTime:4; // expiration time = 2^(9+MPDU LIFE TIME) us - UINT32 RxAckTimeout:8; // unit:slot. Used for TX precedure - UINT32 TxopTimeout:8; //TXOP timeout value for TXOP truncation. It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) - UINT32 rsv2:8; // 1: HT non-STBC control frame enable - } field; - UINT32 word; -} TX_TIMEOUT_CFG_STRUC, *PTX_TIMEOUT_CFG_STRUC; -#endif -#define TX_RTY_CFG 0x134c -#ifdef RT_BIG_ENDIAN -typedef union PACKED _TX_RTY_CFG_STRUC { - struct { - UINT32 rsv:1; - UINT32 TxautoFBEnable:1; // Tx retry PHY rate auto fallback enable - UINT32 AggRtyMode:1; // Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer - UINT32 NonAggRtyMode:1; // Non-Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer - UINT32 LongRtyThre:12; // Long retry threshoold - UINT32 LongRtyLimit:8; //long retry limit - UINT32 ShortRtyLimit:8; // short retry limit - - } field; - UINT32 word; -} TX_RTY_CFG_STRUC, *PTX_RTY_CFG_STRUC; -#else -typedef union PACKED _TX_RTY_CFG_STRUC { - struct { - UINT32 ShortRtyLimit:8; // short retry limit - UINT32 LongRtyLimit:8; //long retry limit - UINT32 LongRtyThre:12; // Long retry threshoold - UINT32 NonAggRtyMode:1; // Non-Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer - UINT32 AggRtyMode:1; // Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer - UINT32 TxautoFBEnable:1; // Tx retry PHY rate auto fallback enable - UINT32 rsv:1; // 1: HT non-STBC control frame enable - } field; - UINT32 word; -} TX_RTY_CFG_STRUC, *PTX_RTY_CFG_STRUC; -#endif -#define TX_LINK_CFG 0x1350 -#ifdef RT_BIG_ENDIAN -typedef union PACKED _TX_LINK_CFG_STRUC { - struct PACKED { - UINT32 RemotMFS:8; //remote MCS feedback sequence number - UINT32 RemotMFB:8; // remote MCS feedback - UINT32 rsv:3; // - UINT32 TxCFAckEn:1; // Piggyback CF-ACK enable - UINT32 TxRDGEn:1; // RDG TX enable - UINT32 TxMRQEn:1; // MCS request TX enable - UINT32 RemoteUMFSEnable:1; // remote unsolicit MFB enable. 0: not apply remote remote unsolicit (MFS=7) - UINT32 MFBEnable:1; // TX apply remote MFB 1:enable - UINT32 RemoteMFBLifeTime:8; //remote MFB life time. unit : 32us - } field; - UINT32 word; -} TX_LINK_CFG_STRUC, *PTX_LINK_CFG_STRUC; -#else -typedef union PACKED _TX_LINK_CFG_STRUC { - struct PACKED { - UINT32 RemoteMFBLifeTime:8; //remote MFB life time. unit : 32us - UINT32 MFBEnable:1; // TX apply remote MFB 1:enable - UINT32 RemoteUMFSEnable:1; // remote unsolicit MFB enable. 0: not apply remote remote unsolicit (MFS=7) - UINT32 TxMRQEn:1; // MCS request TX enable - UINT32 TxRDGEn:1; // RDG TX enable - UINT32 TxCFAckEn:1; // Piggyback CF-ACK enable - UINT32 rsv:3; // - UINT32 RemotMFB:8; // remote MCS feedback - UINT32 RemotMFS:8; //remote MCS feedback sequence number - } field; - UINT32 word; -} TX_LINK_CFG_STRUC, *PTX_LINK_CFG_STRUC; -#endif -#define HT_FBK_CFG0 0x1354 -#ifdef RT_BIG_ENDIAN -typedef union PACKED _HT_FBK_CFG0_STRUC { - struct { - UINT32 HTMCS7FBK:4; - UINT32 HTMCS6FBK:4; - UINT32 HTMCS5FBK:4; - UINT32 HTMCS4FBK:4; - UINT32 HTMCS3FBK:4; - UINT32 HTMCS2FBK:4; - UINT32 HTMCS1FBK:4; - UINT32 HTMCS0FBK:4; - } field; - UINT32 word; -} HT_FBK_CFG0_STRUC, *PHT_FBK_CFG0_STRUC; -#else -typedef union PACKED _HT_FBK_CFG0_STRUC { - struct { - UINT32 HTMCS0FBK:4; - UINT32 HTMCS1FBK:4; - UINT32 HTMCS2FBK:4; - UINT32 HTMCS3FBK:4; - UINT32 HTMCS4FBK:4; - UINT32 HTMCS5FBK:4; - UINT32 HTMCS6FBK:4; - UINT32 HTMCS7FBK:4; - } field; - UINT32 word; -} HT_FBK_CFG0_STRUC, *PHT_FBK_CFG0_STRUC; -#endif -#define HT_FBK_CFG1 0x1358 -#ifdef RT_BIG_ENDIAN -typedef union _HT_FBK_CFG1_STRUC { - struct { - UINT32 HTMCS15FBK:4; - UINT32 HTMCS14FBK:4; - UINT32 HTMCS13FBK:4; - UINT32 HTMCS12FBK:4; - UINT32 HTMCS11FBK:4; - UINT32 HTMCS10FBK:4; - UINT32 HTMCS9FBK:4; - UINT32 HTMCS8FBK:4; - } field; - UINT32 word; -} HT_FBK_CFG1_STRUC, *PHT_FBK_CFG1_STRUC; -#else -typedef union _HT_FBK_CFG1_STRUC { - struct { - UINT32 HTMCS8FBK:4; - UINT32 HTMCS9FBK:4; - UINT32 HTMCS10FBK:4; - UINT32 HTMCS11FBK:4; - UINT32 HTMCS12FBK:4; - UINT32 HTMCS13FBK:4; - UINT32 HTMCS14FBK:4; - UINT32 HTMCS15FBK:4; - } field; - UINT32 word; -} HT_FBK_CFG1_STRUC, *PHT_FBK_CFG1_STRUC; -#endif -#define LG_FBK_CFG0 0x135c -#ifdef RT_BIG_ENDIAN -typedef union _LG_FBK_CFG0_STRUC { - struct { - UINT32 OFDMMCS7FBK:4; //initial value is 6 - UINT32 OFDMMCS6FBK:4; //initial value is 5 - UINT32 OFDMMCS5FBK:4; //initial value is 4 - UINT32 OFDMMCS4FBK:4; //initial value is 3 - UINT32 OFDMMCS3FBK:4; //initial value is 2 - UINT32 OFDMMCS2FBK:4; //initial value is 1 - UINT32 OFDMMCS1FBK:4; //initial value is 0 - UINT32 OFDMMCS0FBK:4; //initial value is 0 - } field; - UINT32 word; -} LG_FBK_CFG0_STRUC, *PLG_FBK_CFG0_STRUC; -#else -typedef union _LG_FBK_CFG0_STRUC { - struct { - UINT32 OFDMMCS0FBK:4; //initial value is 0 - UINT32 OFDMMCS1FBK:4; //initial value is 0 - UINT32 OFDMMCS2FBK:4; //initial value is 1 - UINT32 OFDMMCS3FBK:4; //initial value is 2 - UINT32 OFDMMCS4FBK:4; //initial value is 3 - UINT32 OFDMMCS5FBK:4; //initial value is 4 - UINT32 OFDMMCS6FBK:4; //initial value is 5 - UINT32 OFDMMCS7FBK:4; //initial value is 6 - } field; - UINT32 word; -} LG_FBK_CFG0_STRUC, *PLG_FBK_CFG0_STRUC; -#endif -#define LG_FBK_CFG1 0x1360 -#ifdef RT_BIG_ENDIAN -typedef union _LG_FBK_CFG1_STRUC { - struct { - UINT32 rsv:16; - UINT32 CCKMCS3FBK:4; //initial value is 2 - UINT32 CCKMCS2FBK:4; //initial value is 1 - UINT32 CCKMCS1FBK:4; //initial value is 0 - UINT32 CCKMCS0FBK:4; //initial value is 0 - } field; - UINT32 word; -} LG_FBK_CFG1_STRUC, *PLG_FBK_CFG1_STRUC; -#else -typedef union _LG_FBK_CFG1_STRUC { - struct { - UINT32 CCKMCS0FBK:4; //initial value is 0 - UINT32 CCKMCS1FBK:4; //initial value is 0 - UINT32 CCKMCS2FBK:4; //initial value is 1 - UINT32 CCKMCS3FBK:4; //initial value is 2 - UINT32 rsv:16; - } field; - UINT32 word; -} LG_FBK_CFG1_STRUC, *PLG_FBK_CFG1_STRUC; -#endif - - -//======================================================= -//================ Protection Paramater================================ -//======================================================= -#define CCK_PROT_CFG 0x1364 //CCK Protection -#define ASIC_SHORTNAV 1 -#define ASIC_LONGNAV 2 -#define ASIC_RTS 1 -#define ASIC_CTS 2 -#ifdef RT_BIG_ENDIAN -typedef union _PROT_CFG_STRUC { - struct { - UINT32 rsv:5; - UINT32 RTSThEn:1; //RTS threshold enable on CCK TX - UINT32 TxopAllowGF40:1; //CCK TXOP allowance.0:disallow. - UINT32 TxopAllowGF20:1; //CCK TXOP allowance.0:disallow. - UINT32 TxopAllowMM40:1; //CCK TXOP allowance.0:disallow. - UINT32 TxopAllowMM20:1; //CCK TXOP allowance. 0:disallow. - UINT32 TxopAllowOfdm:1; //CCK TXOP allowance.0:disallow. - UINT32 TxopAllowCck:1; //CCK TXOP allowance.0:disallow. - UINT32 ProtectNav:2; //TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect, 2:LongNAVProtect, 3:rsv - UINT32 ProtectCtrl:2; //Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv - UINT32 ProtectRate:16; //Protection control frame rate for CCK TX(RTS/CTS/CFEnd). - } field; - UINT32 word; -} PROT_CFG_STRUC, *PPROT_CFG_STRUC; -#else -typedef union _PROT_CFG_STRUC { - struct { - UINT32 ProtectRate:16; //Protection control frame rate for CCK TX(RTS/CTS/CFEnd). - UINT32 ProtectCtrl:2; //Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv - UINT32 ProtectNav:2; //TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect, 2:LongNAVProtect, 3:rsv - UINT32 TxopAllowCck:1; //CCK TXOP allowance.0:disallow. - UINT32 TxopAllowOfdm:1; //CCK TXOP allowance.0:disallow. - UINT32 TxopAllowMM20:1; //CCK TXOP allowance. 0:disallow. - UINT32 TxopAllowMM40:1; //CCK TXOP allowance.0:disallow. - UINT32 TxopAllowGF20:1; //CCK TXOP allowance.0:disallow. - UINT32 TxopAllowGF40:1; //CCK TXOP allowance.0:disallow. - UINT32 RTSThEn:1; //RTS threshold enable on CCK TX - UINT32 rsv:5; - } field; - UINT32 word; -} PROT_CFG_STRUC, *PPROT_CFG_STRUC; -#endif - -#define OFDM_PROT_CFG 0x1368 //OFDM Protection -#define MM20_PROT_CFG 0x136C //MM20 Protection -#define MM40_PROT_CFG 0x1370 //MM40 Protection -#define GF20_PROT_CFG 0x1374 //GF20 Protection -#define GF40_PROT_CFG 0x1378 //GR40 Protection -#define EXP_CTS_TIME 0x137C // -#define EXP_ACK_TIME 0x1380 // - -// -// 4.4 MAC RX configuration registers (offset:0x1400) -// -#define RX_FILTR_CFG 0x1400 //TXRX_CSR0 -#define AUTO_RSP_CFG 0x1404 //TXRX_CSR4 -// -// TXRX_CSR4: Auto-Responder/ -// -#ifdef RT_BIG_ENDIAN -typedef union _AUTO_RSP_CFG_STRUC { - struct { - UINT32 :24; - UINT32 AckCtsPsmBit:1; // Power bit value in conrtrol frame - UINT32 DualCTSEn:1; // Power bit value in conrtrol frame - UINT32 rsv:1; // Power bit value in conrtrol frame - UINT32 AutoResponderPreamble:1; // 0:long, 1:short preamble - UINT32 CTS40MRef:1; // Response CTS 40MHz duplicate mode - UINT32 CTS40MMode:1; // Response CTS 40MHz duplicate mode - UINT32 BACAckPolicyEnable:1; // 0:long, 1:short preamble - UINT32 AutoResponderEnable:1; - } field; - UINT32 word; -} AUTO_RSP_CFG_STRUC, *PAUTO_RSP_CFG_STRUC; -#else -typedef union _AUTO_RSP_CFG_STRUC { - struct { - UINT32 AutoResponderEnable:1; - UINT32 BACAckPolicyEnable:1; // 0:long, 1:short preamble - UINT32 CTS40MMode:1; // Response CTS 40MHz duplicate mode - UINT32 CTS40MRef:1; // Response CTS 40MHz duplicate mode - UINT32 AutoResponderPreamble:1; // 0:long, 1:short preamble - UINT32 rsv:1; // Power bit value in conrtrol frame - UINT32 DualCTSEn:1; // Power bit value in conrtrol frame - UINT32 AckCtsPsmBit:1; // Power bit value in conrtrol frame - UINT32 :24; - } field; - UINT32 word; -} AUTO_RSP_CFG_STRUC, *PAUTO_RSP_CFG_STRUC; -#endif - -#define LEGACY_BASIC_RATE 0x1408 // TXRX_CSR5 0x3054 -#define HT_BASIC_RATE 0x140c -#define HT_CTRL_CFG 0x1410 -#define SIFS_COST_CFG 0x1414 -#define RX_PARSER_CFG 0x1418 //Set NAV for all received frames - -// -// 4.5 MAC Security configuration (offset:0x1500) -// -#define TX_SEC_CNT0 0x1500 // -#define RX_SEC_CNT0 0x1504 // -#define CCMP_FC_MUTE 0x1508 // -// -// 4.6 HCCA/PSMP (offset:0x1600) -// -#define TXOP_HLDR_ADDR0 0x1600 -#define TXOP_HLDR_ADDR1 0x1604 -#define TXOP_HLDR_ET 0x1608 -#define QOS_CFPOLL_RA_DW0 0x160c -#define QOS_CFPOLL_A1_DW1 0x1610 -#define QOS_CFPOLL_QC 0x1614 -// -// 4.7 MAC Statistis registers (offset:0x1700) -// -#define RX_STA_CNT0 0x1700 // -#define RX_STA_CNT1 0x1704 // -#define RX_STA_CNT2 0x1708 // - -// -// RX_STA_CNT0_STRUC: RX PLCP error count & RX CRC error count -// -#ifdef RT_BIG_ENDIAN -typedef union _RX_STA_CNT0_STRUC { - struct { - USHORT PhyErr; - USHORT CrcErr; - } field; - UINT32 word; -} RX_STA_CNT0_STRUC, *PRX_STA_CNT0_STRUC; -#else -typedef union _RX_STA_CNT0_STRUC { - struct { - USHORT CrcErr; - USHORT PhyErr; - } field; - UINT32 word; -} RX_STA_CNT0_STRUC, *PRX_STA_CNT0_STRUC; -#endif - -// -// RX_STA_CNT1_STRUC: RX False CCA count & RX LONG frame count -// -#ifdef RT_BIG_ENDIAN -typedef union _RX_STA_CNT1_STRUC { - struct { - USHORT PlcpErr; - USHORT FalseCca; - } field; - UINT32 word; -} RX_STA_CNT1_STRUC, *PRX_STA_CNT1_STRUC; -#else -typedef union _RX_STA_CNT1_STRUC { - struct { - USHORT FalseCca; - USHORT PlcpErr; - } field; - UINT32 word; -} RX_STA_CNT1_STRUC, *PRX_STA_CNT1_STRUC; -#endif - -// -// RX_STA_CNT2_STRUC: -// -#ifdef RT_BIG_ENDIAN -typedef union _RX_STA_CNT2_STRUC { - struct { - USHORT RxFifoOverflowCount; - USHORT RxDupliCount; - } field; - UINT32 word; -} RX_STA_CNT2_STRUC, *PRX_STA_CNT2_STRUC; -#else -typedef union _RX_STA_CNT2_STRUC { - struct { - USHORT RxDupliCount; - USHORT RxFifoOverflowCount; - } field; - UINT32 word; -} RX_STA_CNT2_STRUC, *PRX_STA_CNT2_STRUC; -#endif -#define TX_STA_CNT0 0x170C // -// -// STA_CSR3: TX Beacon count -// -#ifdef RT_BIG_ENDIAN -typedef union _TX_STA_CNT0_STRUC { - struct { - USHORT TxBeaconCount; - USHORT TxFailCount; - } field; - UINT32 word; -} TX_STA_CNT0_STRUC, *PTX_STA_CNT0_STRUC; -#else -typedef union _TX_STA_CNT0_STRUC { - struct { - USHORT TxFailCount; - USHORT TxBeaconCount; - } field; - UINT32 word; -} TX_STA_CNT0_STRUC, *PTX_STA_CNT0_STRUC; -#endif -#define TX_STA_CNT1 0x1710 // -// -// TX_STA_CNT1: TX tx count -// -#ifdef RT_BIG_ENDIAN -typedef union _TX_STA_CNT1_STRUC { - struct { - USHORT TxRetransmit; - USHORT TxSuccess; - } field; - UINT32 word; -} TX_STA_CNT1_STRUC, *PTX_STA_CNT1_STRUC; -#else -typedef union _TX_STA_CNT1_STRUC { - struct { - USHORT TxSuccess; - USHORT TxRetransmit; - } field; - UINT32 word; -} TX_STA_CNT1_STRUC, *PTX_STA_CNT1_STRUC; -#endif -#define TX_STA_CNT2 0x1714 // -// -// TX_STA_CNT2: TX tx count -// -#ifdef RT_BIG_ENDIAN -typedef union _TX_STA_CNT2_STRUC { - struct { - USHORT TxUnderFlowCount; - USHORT TxZeroLenCount; - } field; - UINT32 word; -} TX_STA_CNT2_STRUC, *PTX_STA_CNT2_STRUC; -#else -typedef union _TX_STA_CNT2_STRUC { - struct { - USHORT TxZeroLenCount; - USHORT TxUnderFlowCount; - } field; - UINT32 word; -} TX_STA_CNT2_STRUC, *PTX_STA_CNT2_STRUC; -#endif -#define TX_STA_FIFO 0x1718 // -// -// TX_STA_FIFO_STRUC: TX Result for specific PID status fifo register -// -#ifdef RT_BIG_ENDIAN -typedef union PACKED _TX_STA_FIFO_STRUC { - struct { - UINT32 Reserve:2; - UINT32 TxBF:1; // 3*3 - UINT32 SuccessRate:13; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. -// UINT32 SuccessRate:16; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. - UINT32 wcid:8; //wireless client index - UINT32 TxAckRequired:1; // ack required - UINT32 TxAggre:1; // Tx is aggregated - UINT32 TxSuccess:1; // Tx success. whether success or not - UINT32 PidType:4; - UINT32 bValid:1; // 1:This register contains a valid TX result - } field; - UINT32 word; -} TX_STA_FIFO_STRUC, *PTX_STA_FIFO_STRUC; -#else -typedef union PACKED _TX_STA_FIFO_STRUC { - struct { - UINT32 bValid:1; // 1:This register contains a valid TX result - UINT32 PidType:4; - UINT32 TxSuccess:1; // Tx No retry success - UINT32 TxAggre:1; // Tx Retry Success - UINT32 TxAckRequired:1; // Tx fail - UINT32 wcid:8; //wireless client index -// UINT32 SuccessRate:16; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. - UINT32 SuccessRate:13; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. - UINT32 TxBF:1; - UINT32 Reserve:2; - } field; - UINT32 word; -} TX_STA_FIFO_STRUC, *PTX_STA_FIFO_STRUC; -#endif -// Debug counter -#define TX_AGG_CNT 0x171c -#ifdef RT_BIG_ENDIAN -typedef union _TX_AGG_CNT_STRUC { - struct { - USHORT AggTxCount; - USHORT NonAggTxCount; - } field; - UINT32 word; -} TX_AGG_CNT_STRUC, *PTX_AGG_CNT_STRUC; -#else -typedef union _TX_AGG_CNT_STRUC { - struct { - USHORT NonAggTxCount; - USHORT AggTxCount; - } field; - UINT32 word; -} TX_AGG_CNT_STRUC, *PTX_AGG_CNT_STRUC; -#endif -// Debug counter -#define TX_AGG_CNT0 0x1720 -#ifdef RT_BIG_ENDIAN -typedef union _TX_AGG_CNT0_STRUC { - struct { - USHORT AggSize2Count; - USHORT AggSize1Count; - } field; - UINT32 word; -} TX_AGG_CNT0_STRUC, *PTX_AGG_CNT0_STRUC; -#else -typedef union _TX_AGG_CNT0_STRUC { - struct { - USHORT AggSize1Count; - USHORT AggSize2Count; - } field; - UINT32 word; -} TX_AGG_CNT0_STRUC, *PTX_AGG_CNT0_STRUC; -#endif -// Debug counter -#define TX_AGG_CNT1 0x1724 -#ifdef RT_BIG_ENDIAN -typedef union _TX_AGG_CNT1_STRUC { - struct { - USHORT AggSize4Count; - USHORT AggSize3Count; - } field; - UINT32 word; -} TX_AGG_CNT1_STRUC, *PTX_AGG_CNT1_STRUC; -#else -typedef union _TX_AGG_CNT1_STRUC { - struct { - USHORT AggSize3Count; - USHORT AggSize4Count; - } field; - UINT32 word; -} TX_AGG_CNT1_STRUC, *PTX_AGG_CNT1_STRUC; -#endif -#define TX_AGG_CNT2 0x1728 -#ifdef RT_BIG_ENDIAN -typedef union _TX_AGG_CNT2_STRUC { - struct { - USHORT AggSize6Count; - USHORT AggSize5Count; - } field; - UINT32 word; -} TX_AGG_CNT2_STRUC, *PTX_AGG_CNT2_STRUC; -#else -typedef union _TX_AGG_CNT2_STRUC { - struct { - USHORT AggSize5Count; - USHORT AggSize6Count; - } field; - UINT32 word; -} TX_AGG_CNT2_STRUC, *PTX_AGG_CNT2_STRUC; -#endif -// Debug counter -#define TX_AGG_CNT3 0x172c -#ifdef RT_BIG_ENDIAN -typedef union _TX_AGG_CNT3_STRUC { - struct { - USHORT AggSize8Count; - USHORT AggSize7Count; - } field; - UINT32 word; -} TX_AGG_CNT3_STRUC, *PTX_AGG_CNT3_STRUC; -#else -typedef union _TX_AGG_CNT3_STRUC { - struct { - USHORT AggSize7Count; - USHORT AggSize8Count; - } field; - UINT32 word; -} TX_AGG_CNT3_STRUC, *PTX_AGG_CNT3_STRUC; -#endif -// Debug counter -#define TX_AGG_CNT4 0x1730 -#ifdef RT_BIG_ENDIAN -typedef union _TX_AGG_CNT4_STRUC { - struct { - USHORT AggSize10Count; - USHORT AggSize9Count; - } field; - UINT32 word; -} TX_AGG_CNT4_STRUC, *PTX_AGG_CNT4_STRUC; -#else -typedef union _TX_AGG_CNT4_STRUC { - struct { - USHORT AggSize9Count; - USHORT AggSize10Count; - } field; - UINT32 word; -} TX_AGG_CNT4_STRUC, *PTX_AGG_CNT4_STRUC; -#endif -#define TX_AGG_CNT5 0x1734 -#ifdef RT_BIG_ENDIAN -typedef union _TX_AGG_CNT5_STRUC { - struct { - USHORT AggSize12Count; - USHORT AggSize11Count; - } field; - UINT32 word; -} TX_AGG_CNT5_STRUC, *PTX_AGG_CNT5_STRUC; -#else -typedef union _TX_AGG_CNT5_STRUC { - struct { - USHORT AggSize11Count; - USHORT AggSize12Count; - } field; - UINT32 word; -} TX_AGG_CNT5_STRUC, *PTX_AGG_CNT5_STRUC; -#endif -#define TX_AGG_CNT6 0x1738 -#ifdef RT_BIG_ENDIAN -typedef union _TX_AGG_CNT6_STRUC { - struct { - USHORT AggSize14Count; - USHORT AggSize13Count; - } field; - UINT32 word; -} TX_AGG_CNT6_STRUC, *PTX_AGG_CNT6_STRUC; -#else -typedef union _TX_AGG_CNT6_STRUC { - struct { - USHORT AggSize13Count; - USHORT AggSize14Count; - } field; - UINT32 word; -} TX_AGG_CNT6_STRUC, *PTX_AGG_CNT6_STRUC; -#endif -#define TX_AGG_CNT7 0x173c -#ifdef RT_BIG_ENDIAN -typedef union _TX_AGG_CNT7_STRUC { - struct { - USHORT AggSize16Count; - USHORT AggSize15Count; - } field; - UINT32 word; -} TX_AGG_CNT7_STRUC, *PTX_AGG_CNT7_STRUC; -#else -typedef union _TX_AGG_CNT7_STRUC { - struct { - USHORT AggSize15Count; - USHORT AggSize16Count; - } field; - UINT32 word; -} TX_AGG_CNT7_STRUC, *PTX_AGG_CNT7_STRUC; -#endif -#define MPDU_DENSITY_CNT 0x1740 -#ifdef RT_BIG_ENDIAN -typedef union _MPDU_DEN_CNT_STRUC { - struct { - USHORT RXZeroDelCount; //RX zero length delimiter count - USHORT TXZeroDelCount; //TX zero length delimiter count - } field; - UINT32 word; -} MPDU_DEN_CNT_STRUC, *PMPDU_DEN_CNT_STRUC; -#else -typedef union _MPDU_DEN_CNT_STRUC { - struct { - USHORT TXZeroDelCount; //TX zero length delimiter count - USHORT RXZeroDelCount; //RX zero length delimiter count - } field; - UINT32 word; -} MPDU_DEN_CNT_STRUC, *PMPDU_DEN_CNT_STRUC; -#endif -// -// TXRX control registers - base address 0x3000 -// -// rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. -#define TXRX_CSR1 0x77d0 - -// -// Security key table memory, base address = 0x1000 -// -#define MAC_WCID_BASE 0x1800 //8-bytes(use only 6-bytes) * 256 entry = -#define HW_WCID_ENTRY_SIZE 8 -#define PAIRWISE_KEY_TABLE_BASE 0x4000 // 32-byte * 256-entry = -byte -#define HW_KEY_ENTRY_SIZE 0x20 -#define PAIRWISE_IVEIV_TABLE_BASE 0x6000 // 8-byte * 256-entry = -byte -#define MAC_IVEIV_TABLE_BASE 0x6000 // 8-byte * 256-entry = -byte -#define HW_IVEIV_ENTRY_SIZE 8 -#define MAC_WCID_ATTRIBUTE_BASE 0x6800 // 4-byte * 256-entry = -byte -#define HW_WCID_ATTRI_SIZE 4 -#define WCID_RESERVED 0x6bfc -#define SHARED_KEY_TABLE_BASE 0x6c00 // 32-byte * 16-entry = 512-byte -#define SHARED_KEY_MODE_BASE 0x7000 // 32-byte * 16-entry = 512-byte -#define HW_SHARED_KEY_MODE_SIZE 4 -#define SHAREDKEYTABLE 0 -#define PAIRWISEKEYTABLE 1 - - -#ifdef RT_BIG_ENDIAN -typedef union _SHAREDKEY_MODE_STRUC { - struct { - UINT32 :1; - UINT32 Bss1Key3CipherAlg:3; - UINT32 :1; - UINT32 Bss1Key2CipherAlg:3; - UINT32 :1; - UINT32 Bss1Key1CipherAlg:3; - UINT32 :1; - UINT32 Bss1Key0CipherAlg:3; - UINT32 :1; - UINT32 Bss0Key3CipherAlg:3; - UINT32 :1; - UINT32 Bss0Key2CipherAlg:3; - UINT32 :1; - UINT32 Bss0Key1CipherAlg:3; - UINT32 :1; - UINT32 Bss0Key0CipherAlg:3; - } field; - UINT32 word; -} SHAREDKEY_MODE_STRUC, *PSHAREDKEY_MODE_STRUC; -#else -typedef union _SHAREDKEY_MODE_STRUC { - struct { - UINT32 Bss0Key0CipherAlg:3; - UINT32 :1; - UINT32 Bss0Key1CipherAlg:3; - UINT32 :1; - UINT32 Bss0Key2CipherAlg:3; - UINT32 :1; - UINT32 Bss0Key3CipherAlg:3; - UINT32 :1; - UINT32 Bss1Key0CipherAlg:3; - UINT32 :1; - UINT32 Bss1Key1CipherAlg:3; - UINT32 :1; - UINT32 Bss1Key2CipherAlg:3; - UINT32 :1; - UINT32 Bss1Key3CipherAlg:3; - UINT32 :1; - } field; - UINT32 word; -} SHAREDKEY_MODE_STRUC, *PSHAREDKEY_MODE_STRUC; -#endif -// 64-entry for pairwise key table -typedef struct _HW_WCID_ENTRY { // 8-byte per entry - UCHAR Address[6]; - UCHAR Rsv[2]; -} HW_WCID_ENTRY, PHW_WCID_ENTRY; - - -// ================================================================================= -// WCID format -// ================================================================================= -//7.1 WCID ENTRY format : 8bytes -typedef struct _WCID_ENTRY_STRUC { - UCHAR RXBABitmap7; // bit0 for TID8, bit7 for TID 15 - UCHAR RXBABitmap0; // bit0 for TID0, bit7 for TID 7 - UCHAR MAC[6]; // 0 for shared key table. 1 for pairwise key table -} WCID_ENTRY_STRUC, *PWCID_ENTRY_STRUC; - -//8.1.1 SECURITY KEY format : 8DW -// 32-byte per entry, total 16-entry for shared key table, 64-entry for pairwise key table -typedef struct _HW_KEY_ENTRY { // 32-byte per entry - UCHAR Key[16]; - UCHAR TxMic[8]; - UCHAR RxMic[8]; -} HW_KEY_ENTRY, *PHW_KEY_ENTRY; - -//8.1.2 IV/EIV format : 2DW - -//8.1.3 RX attribute entry format : 1DW -#ifdef RT_BIG_ENDIAN -typedef struct _MAC_ATTRIBUTE_STRUC { - UINT32 rsv:22; - UINT32 RXWIUDF:3; - UINT32 BSSIDIdx:3; //multipleBSS index for the WCID - UINT32 PairKeyMode:3; - UINT32 KeyTab:1; // 0 for shared key table. 1 for pairwise key table -} MAC_ATTRIBUTE_STRUC, *PMAC_ATTRIBUTE_STRUC; -#else -typedef struct _MAC_ATTRIBUTE_STRUC { - UINT32 KeyTab:1; // 0 for shared key table. 1 for pairwise key table - UINT32 PairKeyMode:3; - UINT32 BSSIDIdx:3; //multipleBSS index for the WCID - UINT32 RXWIUDF:3; - UINT32 rsv:22; -} MAC_ATTRIBUTE_STRUC, *PMAC_ATTRIBUTE_STRUC; -#endif - - -// ================================================================================= -// HOST-MCU communication data structure -// ================================================================================= - -// -// H2M_MAILBOX_CSR: Host-to-MCU Mailbox -// -#ifdef RT_BIG_ENDIAN -typedef union _H2M_MAILBOX_STRUC { - struct { - UINT32 Owner:8; - UINT32 CmdToken:8; // 0xff tells MCU not to report CmdDoneInt after excuting the command - UINT32 HighByte:8; - UINT32 LowByte:8; - } field; - UINT32 word; -} H2M_MAILBOX_STRUC, *PH2M_MAILBOX_STRUC; -#else -typedef union _H2M_MAILBOX_STRUC { - struct { - UINT32 LowByte:8; - UINT32 HighByte:8; - UINT32 CmdToken:8; - UINT32 Owner:8; - } field; - UINT32 word; -} H2M_MAILBOX_STRUC, *PH2M_MAILBOX_STRUC; -#endif - -// -// M2H_CMD_DONE_CSR: MCU-to-Host command complete indication -// -#ifdef RT_BIG_ENDIAN -typedef union _M2H_CMD_DONE_STRUC { - struct { - UINT32 CmdToken3; - UINT32 CmdToken2; - UINT32 CmdToken1; - UINT32 CmdToken0; - } field; - UINT32 word; -} M2H_CMD_DONE_STRUC, *PM2H_CMD_DONE_STRUC; -#else -typedef union _M2H_CMD_DONE_STRUC { - struct { - UINT32 CmdToken0; - UINT32 CmdToken1; - UINT32 CmdToken2; - UINT32 CmdToken3; - } field; - UINT32 word; -} M2H_CMD_DONE_STRUC, *PM2H_CMD_DONE_STRUC; -#endif - - -//NAV_TIME_CFG :NAV -#ifdef RT_BIG_ENDIAN -typedef union _NAV_TIME_CFG_STRUC { - struct { - USHORT rsv:6; - USHORT ZeroSifs:1; // Applied zero SIFS timer after OFDM RX 0: disable - USHORT Eifs:9; // in unit of 1-us - UCHAR SlotTime; // in unit of 1-us - UCHAR Sifs; // in unit of 1-us - } field; - UINT32 word; -} NAV_TIME_CFG_STRUC, *PNAV_TIME_CFG_STRUC; -#else -typedef union _NAV_TIME_CFG_STRUC { - struct { - UCHAR Sifs; // in unit of 1-us - UCHAR SlotTime; // in unit of 1-us - USHORT Eifs:9; // in unit of 1-us - USHORT ZeroSifs:1; // Applied zero SIFS timer after OFDM RX 0: disable - USHORT rsv:6; - } field; - UINT32 word; -} NAV_TIME_CFG_STRUC, *PNAV_TIME_CFG_STRUC; -#endif - - -// -// RX_FILTR_CFG: /RX configuration register -// -#ifdef RT_BIG_ENDIAN -typedef union RX_FILTR_CFG_STRUC { - struct { - UINT32 :15; - UINT32 DropRsvCntlType:1; - - UINT32 DropBAR:1; // - UINT32 DropBA:1; // - UINT32 DropPsPoll:1; // Drop Ps-Poll - UINT32 DropRts:1; // Drop Ps-Poll - - UINT32 DropCts:1; // Drop Ps-Poll - UINT32 DropAck:1; // Drop Ps-Poll - UINT32 DropCFEnd:1; // Drop Ps-Poll - UINT32 DropCFEndAck:1; // Drop Ps-Poll - - UINT32 DropDuplicate:1; // Drop duplicate frame - UINT32 DropBcast:1; // Drop broadcast frames - UINT32 DropMcast:1; // Drop multicast frames - UINT32 DropVerErr:1; // Drop version error frame - - UINT32 DropNotMyBSSID:1; // Drop fram ToDs bit is true - UINT32 DropNotToMe:1; // Drop not to me unicast frame - UINT32 DropPhyErr:1; // Drop physical error - UINT32 DropCRCErr:1; // Drop CRC error - } field; - UINT32 word; -} RX_FILTR_CFG_STRUC, *PRX_FILTR_CFG_STRUC; -#else -typedef union _RX_FILTR_CFG_STRUC { - struct { - UINT32 DropCRCErr:1; // Drop CRC error - UINT32 DropPhyErr:1; // Drop physical error - UINT32 DropNotToMe:1; // Drop not to me unicast frame - UINT32 DropNotMyBSSID:1; // Drop fram ToDs bit is true - - UINT32 DropVerErr:1; // Drop version error frame - UINT32 DropMcast:1; // Drop multicast frames - UINT32 DropBcast:1; // Drop broadcast frames - UINT32 DropDuplicate:1; // Drop duplicate frame - - UINT32 DropCFEndAck:1; // Drop Ps-Poll - UINT32 DropCFEnd:1; // Drop Ps-Poll - UINT32 DropAck:1; // Drop Ps-Poll - UINT32 DropCts:1; // Drop Ps-Poll - - UINT32 DropRts:1; // Drop Ps-Poll - UINT32 DropPsPoll:1; // Drop Ps-Poll - UINT32 DropBA:1; // - UINT32 DropBAR:1; // - - UINT32 DropRsvCntlType:1; - UINT32 :15; - } field; - UINT32 word; -} RX_FILTR_CFG_STRUC, *PRX_FILTR_CFG_STRUC; -#endif - - - - -// -// PHY_CSR4: RF serial control register -// -#ifdef RT_BIG_ENDIAN -typedef union _PHY_CSR4_STRUC { - struct { - UINT32 Busy:1; // 1: ASIC is busy execute RF programming. - UINT32 PLL_LD:1; // RF PLL_LD status - UINT32 IFSelect:1; // 1: select IF to program, 0: select RF to program - UINT32 NumberOfBits:5; // Number of bits used in RFRegValue (I:20, RFMD:22) - UINT32 RFRegValue:24; // Register value (include register id) serial out to RF/IF chip. - } field; - UINT32 word; -} PHY_CSR4_STRUC, *PPHY_CSR4_STRUC; -#else -typedef union _PHY_CSR4_STRUC { - struct { - UINT32 RFRegValue:24; // Register value (include register id) serial out to RF/IF chip. - UINT32 NumberOfBits:5; // Number of bits used in RFRegValue (I:20, RFMD:22) - UINT32 IFSelect:1; // 1: select IF to program, 0: select RF to program - UINT32 PLL_LD:1; // RF PLL_LD status - UINT32 Busy:1; // 1: ASIC is busy execute RF programming. - } field; - UINT32 word; -} PHY_CSR4_STRUC, *PPHY_CSR4_STRUC; -#endif - - -// -// SEC_CSR5: shared key table security mode register -// -#ifdef RT_BIG_ENDIAN -typedef union _SEC_CSR5_STRUC { - struct { - UINT32 :1; - UINT32 Bss3Key3CipherAlg:3; - UINT32 :1; - UINT32 Bss3Key2CipherAlg:3; - UINT32 :1; - UINT32 Bss3Key1CipherAlg:3; - UINT32 :1; - UINT32 Bss3Key0CipherAlg:3; - UINT32 :1; - UINT32 Bss2Key3CipherAlg:3; - UINT32 :1; - UINT32 Bss2Key2CipherAlg:3; - UINT32 :1; - UINT32 Bss2Key1CipherAlg:3; - UINT32 :1; - UINT32 Bss2Key0CipherAlg:3; - } field; - UINT32 word; -} SEC_CSR5_STRUC, *PSEC_CSR5_STRUC; -#else -typedef union _SEC_CSR5_STRUC { - struct { - UINT32 Bss2Key0CipherAlg:3; - UINT32 :1; - UINT32 Bss2Key1CipherAlg:3; - UINT32 :1; - UINT32 Bss2Key2CipherAlg:3; - UINT32 :1; - UINT32 Bss2Key3CipherAlg:3; - UINT32 :1; - UINT32 Bss3Key0CipherAlg:3; - UINT32 :1; - UINT32 Bss3Key1CipherAlg:3; - UINT32 :1; - UINT32 Bss3Key2CipherAlg:3; - UINT32 :1; - UINT32 Bss3Key3CipherAlg:3; - UINT32 :1; - } field; - UINT32 word; -} SEC_CSR5_STRUC, *PSEC_CSR5_STRUC; -#endif - - -// -// HOST_CMD_CSR: For HOST to interrupt embedded processor -// -#ifdef RT_BIG_ENDIAN -typedef union _HOST_CMD_CSR_STRUC { - struct { - UINT32 Rsv:24; - UINT32 HostCommand:8; - } field; - UINT32 word; -} HOST_CMD_CSR_STRUC, *PHOST_CMD_CSR_STRUC; -#else -typedef union _HOST_CMD_CSR_STRUC { - struct { - UINT32 HostCommand:8; - UINT32 Rsv:24; - } field; - UINT32 word; -} HOST_CMD_CSR_STRUC, *PHOST_CMD_CSR_STRUC; -#endif - - -// -// AIFSN_CSR: AIFSN for each EDCA AC -// - - - -// -// E2PROM_CSR: EEPROM control register -// -#ifdef RT_BIG_ENDIAN -typedef union _E2PROM_CSR_STRUC { - struct { - UINT32 Rsvd:25; - UINT32 LoadStatus:1; // 1:loading, 0:done - UINT32 Type:1; // 1: 93C46, 0:93C66 - UINT32 EepromDO:1; - UINT32 EepromDI:1; - UINT32 EepromCS:1; - UINT32 EepromSK:1; - UINT32 Reload:1; // Reload EEPROM content, write one to reload, self-cleared. - } field; - UINT32 word; -} E2PROM_CSR_STRUC, *PE2PROM_CSR_STRUC; -#else -typedef union _E2PROM_CSR_STRUC { - struct { - UINT32 Reload:1; // Reload EEPROM content, write one to reload, self-cleared. - UINT32 EepromSK:1; - UINT32 EepromCS:1; - UINT32 EepromDI:1; - UINT32 EepromDO:1; - UINT32 Type:1; // 1: 93C46, 0:93C66 - UINT32 LoadStatus:1; // 1:loading, 0:done - UINT32 Rsvd:25; - } field; - UINT32 word; -} E2PROM_CSR_STRUC, *PE2PROM_CSR_STRUC; -#endif - -// -// QOS_CSR0: TXOP holder address0 register -// -#ifdef RT_BIG_ENDIAN -typedef union _QOS_CSR0_STRUC { - struct { - UCHAR Byte3; // MAC address byte 3 - UCHAR Byte2; // MAC address byte 2 - UCHAR Byte1; // MAC address byte 1 - UCHAR Byte0; // MAC address byte 0 - } field; - UINT32 word; -} QOS_CSR0_STRUC, *PQOS_CSR0_STRUC; -#else -typedef union _QOS_CSR0_STRUC { - struct { - UCHAR Byte0; // MAC address byte 0 - UCHAR Byte1; // MAC address byte 1 - UCHAR Byte2; // MAC address byte 2 - UCHAR Byte3; // MAC address byte 3 - } field; - UINT32 word; -} QOS_CSR0_STRUC, *PQOS_CSR0_STRUC; -#endif - -// -// QOS_CSR1: TXOP holder address1 register -// -#ifdef RT_BIG_ENDIAN -typedef union _QOS_CSR1_STRUC { - struct { - UCHAR Rsvd1; - UCHAR Rsvd0; - UCHAR Byte5; // MAC address byte 5 - UCHAR Byte4; // MAC address byte 4 - } field; - UINT32 word; -} QOS_CSR1_STRUC, *PQOS_CSR1_STRUC; -#else -typedef union _QOS_CSR1_STRUC { - struct { - UCHAR Byte4; // MAC address byte 4 - UCHAR Byte5; // MAC address byte 5 - UCHAR Rsvd0; - UCHAR Rsvd1; - } field; - UINT32 word; -} QOS_CSR1_STRUC, *PQOS_CSR1_STRUC; -#endif - -#define RF_CSR_CFG 0x500 -#ifdef RT_BIG_ENDIAN -typedef union _RF_CSR_CFG_STRUC { - struct { - UINT Rsvd1:14; // Reserved - UINT RF_CSR_KICK:1; // kick RF register read/write - UINT RF_CSR_WR:1; // 0: read 1: write - UINT Rsvd2:3; // Reserved - UINT TESTCSR_RFACC_REGNUM:5; // RF register ID - UINT RF_CSR_DATA:8; // DATA - } field; - UINT word; -} RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC; -#else -typedef union _RF_CSR_CFG_STRUC { - struct { - UINT RF_CSR_DATA:8; // DATA - UINT TESTCSR_RFACC_REGNUM:5; // RF register ID - UINT Rsvd2:3; // Reserved - UINT RF_CSR_WR:1; // 0: read 1: write - UINT RF_CSR_KICK:1; // kick RF register read/write - UINT Rsvd1:14; // Reserved - } field; - UINT word; -} RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC; -#endif - - -// -// Other on-chip shared memory space, base = 0x2000 -// - -// CIS space - base address = 0x2000 -#define HW_CIS_BASE 0x2000 - -// Carrier-sense CTS frame base address. It's where mac stores carrier-sense frame for carrier-sense function. -#define HW_CS_CTS_BASE 0x7700 -// DFS CTS frame base address. It's where mac stores CTS frame for DFS. -#define HW_DFS_CTS_BASE 0x7780 -#define HW_CTS_FRAME_SIZE 0x80 - -// 2004-11-08 john - since NULL frame won't be that long (256 byte). We steal 16 tail bytes -// to save debugging settings -#define HW_DEBUG_SETTING_BASE 0x77f0 // 0x77f0~0x77ff total 16 bytes -#define HW_DEBUG_SETTING_BASE2 0x7770 // 0x77f0~0x77ff total 16 bytes - -// In order to support maximum 8 MBSS and its maximum length is 512 for each beacon -// Three section discontinue memory segments will be used. -// 1. The original region for BCN 0~3 -// 2. Extract memory from FCE table for BCN 4~5 -// 3. Extract memory from Pair-wise key table for BCN 6~7 -// It occupied those memory of wcid 238~253 for BCN 6 -// and wcid 222~237 for BCN 7 -#define HW_BEACON_MAX_SIZE 0x1000 /* unit: byte */ -#define HW_BEACON_BASE0 0x7800 -#define HW_BEACON_BASE1 0x7A00 -#define HW_BEACON_BASE2 0x7C00 -#define HW_BEACON_BASE3 0x7E00 -#define HW_BEACON_BASE4 0x7200 -#define HW_BEACON_BASE5 0x7400 -#define HW_BEACON_BASE6 0x5DC0 -#define HW_BEACON_BASE7 0x5BC0 - -#define HW_BEACON_MAX_COUNT 8 -#define HW_BEACON_OFFSET 0x0200 -#define HW_BEACON_CONTENT_LEN (HW_BEACON_OFFSET - TXWI_SIZE) - -// HOST-MCU shared memory - base address = 0x2100 -#define HOST_CMD_CSR 0x404 -#define H2M_MAILBOX_CSR 0x7010 -#define H2M_MAILBOX_CID 0x7014 -#define H2M_MAILBOX_STATUS 0x701c -#define H2M_INT_SRC 0x7024 -#define H2M_BBP_AGENT 0x7028 -#define M2H_CMD_DONE_CSR 0x000c -#define MCU_TXOP_ARRAY_BASE 0x000c // TODO: to be provided by Albert -#define MCU_TXOP_ENTRY_SIZE 32 // TODO: to be provided by Albert -#define MAX_NUM_OF_TXOP_ENTRY 16 // TODO: must be same with 8051 firmware -#define MCU_MBOX_VERSION 0x01 // TODO: to be confirmed by Albert -#define MCU_MBOX_VERSION_OFFSET 5 // TODO: to be provided by Albert - -// -// Host DMA registers - base address 0x200 . TX0-3=EDCAQid0-3, TX4=HCCA, TX5=MGMT, -// -// -// DMA RING DESCRIPTOR -// -#define E2PROM_CSR 0x0004 -#define IO_CNTL_CSR 0x77d0 - - - -// ================================================================ -// Tx / Rx / Mgmt ring descriptor definition -// ================================================================ - -// the following PID values are used to mark outgoing frame type in TXD->PID so that -// proper TX statistics can be collected based on these categories -// b3-2 of PID field - -#define PID_MGMT 0x05 -#define PID_BEACON 0x0c -#define PID_DATA_NORMALUCAST 0x02 -#define PID_DATA_AMPDU 0x04 -#define PID_DATA_NO_ACK 0x08 -#define PID_DATA_NOT_NORM_ACK 0x03 -// value domain of pTxD->HostQId (4-bit: 0~15) -#define QID_AC_BK 1 // meet ACI definition in 802.11e -#define QID_AC_BE 0 // meet ACI definition in 802.11e -#define QID_AC_VI 2 -#define QID_AC_VO 3 -#define QID_HCCA 4 -//#define NUM_OF_TX_RING 5 -#define NUM_OF_TX_RING 4 -#define QID_MGMT 13 -#define QID_RX 14 -#define QID_OTHER 15 - -#endif // __RTMP_MAC_H__ // diff --git a/drivers/staging/rt3090/rtmp_type.h b/drivers/staging/rt3090/rtmp_type.h deleted file mode 100644 index d8b571e6f8012f7337ec6c3e726962a763782ad0..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/rtmp_type.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rtmp_type.h - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Name Date Modification logs - Paul Lin 1-2-2004 -*/ - -#ifndef __RTMP_TYPE_H__ -#define __RTMP_TYPE_H__ - - -#define PACKED __attribute__ ((packed)) - -#ifdef LINUX -// Put platform dependent declaration here -// For example, linux type definition -typedef unsigned char UINT8; -typedef unsigned short UINT16; -typedef unsigned int UINT32; -typedef unsigned long long UINT64; -typedef int INT32; -typedef long long INT64; -#endif // LINUX // - -typedef unsigned char * PUINT8; -typedef unsigned short * PUINT16; -typedef unsigned int * PUINT32; -typedef unsigned long long * PUINT64; -typedef int * PINT32; -typedef long long * PINT64; - -// modified for fixing compile warning on Sigma 8634 platform -typedef char STRING; -typedef signed char CHAR; - -typedef signed short SHORT; -typedef signed int INT; -typedef signed long LONG; -typedef signed long long LONGLONG; - - -#ifdef LINUX -typedef unsigned char UCHAR; -typedef unsigned short USHORT; -typedef unsigned int UINT; -typedef unsigned long ULONG; -#endif // LINUX // -typedef unsigned long long ULONGLONG; - -typedef unsigned char BOOLEAN; -#ifdef LINUX -typedef void VOID; -#endif // LINUX // - -typedef char * PSTRING; -typedef VOID * PVOID; -typedef CHAR * PCHAR; -typedef UCHAR * PUCHAR; -typedef USHORT * PUSHORT; -typedef LONG * PLONG; -typedef ULONG * PULONG; -typedef UINT * PUINT; - -typedef unsigned int NDIS_MEDIA_STATE; - -typedef union _LARGE_INTEGER { - struct { - UINT LowPart; - INT32 HighPart; - } u; - INT64 QuadPart; -} LARGE_INTEGER; - - -// -// Register set pair for initialzation register set definition -// -typedef struct _RTMP_REG_PAIR -{ - ULONG Register; - ULONG Value; -} RTMP_REG_PAIR, *PRTMP_REG_PAIR; - -typedef struct _REG_PAIR -{ - UCHAR Register; - UCHAR Value; -} REG_PAIR, *PREG_PAIR; - -// -// Register set pair for initialzation register set definition -// -typedef struct _RTMP_RF_REGS -{ - UCHAR Channel; - ULONG R1; - ULONG R2; - ULONG R3; - ULONG R4; -} RTMP_RF_REGS, *PRTMP_RF_REGS; - -typedef struct _FREQUENCY_ITEM { - UCHAR Channel; - UCHAR N; - UCHAR R; - UCHAR K; -} FREQUENCY_ITEM, *PFREQUENCY_ITEM; - - -typedef int NTSTATUS; - - -#define STATUS_SUCCESS 0x00 -#define STATUS_UNSUCCESSFUL 0x01 - -#endif // __RTMP_TYPE_H__ // diff --git a/drivers/staging/rt3090/spectrum.h b/drivers/staging/rt3090/spectrum.h deleted file mode 100644 index be9bae5b88c2e9d724f7c6a29683d0e8c8ed87fd..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/spectrum.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - */ - -#ifndef __SPECTRUM_H__ -#define __SPECTRUM_H__ - -#include "rtmp_type.h" -#include "spectrum_def.h" - - -CHAR RTMP_GetTxPwr( - IN PRTMP_ADAPTER pAd, - IN HTTRANSMIT_SETTING HTTxMode); - -/* - ========================================================================== - Description: - Prepare Measurement request action frame and enqueue it into - management queue waiting for transmition. - - Parametrs: - 1. the destination mac address of the frame. - - Return : None. - ========================================================================== - */ -VOID MakeMeasurementReqFrame( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pOutBuffer, - OUT PULONG pFrameLen, - IN UINT8 TotalLen, - IN UINT8 Category, - IN UINT8 Action, - IN UINT8 MeasureToken, - IN UINT8 MeasureReqMode, - IN UINT8 MeasureReqType, - IN UINT8 NumOfRepetitions); - -/* - ========================================================================== - Description: - Prepare Measurement report action frame and enqueue it into - management queue waiting for transmition. - - Parametrs: - 1. the destination mac address of the frame. - - Return : None. - ========================================================================== - */ -VOID EnqueueMeasurementRep( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UINT8 DialogToken, - IN UINT8 MeasureToken, - IN UINT8 MeasureReqMode, - IN UINT8 MeasureReqType, - IN UINT8 ReportInfoLen, - IN PUINT8 pReportInfo); - -/* - ========================================================================== - Description: - Prepare TPC Request action frame and enqueue it into - management queue waiting for transmition. - - Parametrs: - 1. the destination mac address of the frame. - - Return : None. - ========================================================================== - */ -VOID EnqueueTPCReq( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UCHAR DialogToken); - -/* - ========================================================================== - Description: - Prepare TPC Report action frame and enqueue it into - management queue waiting for transmition. - - Parametrs: - 1. the destination mac address of the frame. - - Return : None. - ========================================================================== - */ -VOID EnqueueTPCRep( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UINT8 DialogToken, - IN UINT8 TxPwr, - IN UINT8 LinkMargin); - -/* - ========================================================================== - Description: - Prepare Channel Switch Announcement action frame and enqueue it into - management queue waiting for transmition. - - Parametrs: - 1. the destination mac address of the frame. - 2. Channel switch announcement mode. - 2. a New selected channel. - - Return : None. - ========================================================================== - */ -VOID EnqueueChSwAnn( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN UINT8 ChSwMode, - IN UINT8 NewCh); - -/* - ========================================================================== - Description: - Spectrun action frames Handler such as channel switch annoucement, - measurement report, measurement request actions frames. - - Parametrs: - Elme - MLME message containing the received frame - - Return : None. - ========================================================================== - */ -VOID PeerSpectrumAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem); - -/* - ========================================================================== - Description: - - Parametrs: - - Return : None. - ========================================================================== - */ -INT Set_MeasureReq_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_TpcReq_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_PwrConstraint( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - - -VOID MeasureReqTabInit( - IN PRTMP_ADAPTER pAd); - -VOID MeasureReqTabExit( - IN PRTMP_ADAPTER pAd); - -PMEASURE_REQ_ENTRY MeasureReqLookUp( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken); - -PMEASURE_REQ_ENTRY MeasureReqInsert( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken); - -VOID MeasureReqDelete( - IN PRTMP_ADAPTER pAd, - IN UINT8 DialogToken); - -VOID InsertChannelRepIE( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN PSTRING pCountry, - IN UINT8 RegulatoryClass); - -VOID InsertTpcReportIE( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN UINT8 TxPwr, - IN UINT8 LinkMargin); - -VOID InsertDialogToken( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN UINT8 DialogToken); - -VOID TpcReqTabInit( - IN PRTMP_ADAPTER pAd); - -VOID TpcReqTabExit( - IN PRTMP_ADAPTER pAd); - -VOID NotifyChSwAnnToPeerAPs( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pRA, - IN PUCHAR pTA, - IN UINT8 ChSwMode, - IN UINT8 Channel); - -VOID RguClass_BuildBcnChList( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pBuf, - OUT PULONG pBufLen); -#endif // __SPECTRUM_H__ // diff --git a/drivers/staging/rt3090/spectrum_def.h b/drivers/staging/rt3090/spectrum_def.h deleted file mode 100644 index 0389b0921486493b149e0330f73bd343c8ca2828..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/spectrum_def.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - spectrum_def.h - - Abstract: - Handle association related requests either from WSTA or from local MLME - - Revision History: - Who When What - --------- ---------- ---------------------------------------------- - Fonchi Wu 2008 created for 802.11h - */ - -#ifndef __SPECTRUM_DEF_H__ -#define __SPECTRUM_DEF_H__ - - -#define MAX_MEASURE_REQ_TAB_SIZE 32 -#define MAX_HASH_MEASURE_REQ_TAB_SIZE MAX_MEASURE_REQ_TAB_SIZE - -#define MAX_TPC_REQ_TAB_SIZE 32 -#define MAX_HASH_TPC_REQ_TAB_SIZE MAX_TPC_REQ_TAB_SIZE - -#define MIN_RCV_PWR 100 /* Negative value ((dBm) */ - -#define TPC_REQ_AGE_OUT 500 /* ms */ -#define MQ_REQ_AGE_OUT 500 /* ms */ - -#define TPC_DIALOGTOKEN_HASH_INDEX(_DialogToken) ((_DialogToken) % MAX_HASH_TPC_REQ_TAB_SIZE) -#define MQ_DIALOGTOKEN_HASH_INDEX(_DialogToken) ((_DialogToken) % MAX_MEASURE_REQ_TAB_SIZE) - -typedef struct _MEASURE_REQ_ENTRY -{ - struct _MEASURE_REQ_ENTRY *pNext; - ULONG lastTime; - BOOLEAN Valid; - UINT8 DialogToken; - UINT8 MeasureDialogToken[3]; // 0:basic measure, 1: CCA measure, 2: RPI_Histogram measure. -} MEASURE_REQ_ENTRY, *PMEASURE_REQ_ENTRY; - -typedef struct _MEASURE_REQ_TAB -{ - UCHAR Size; - PMEASURE_REQ_ENTRY Hash[MAX_HASH_MEASURE_REQ_TAB_SIZE]; - MEASURE_REQ_ENTRY Content[MAX_MEASURE_REQ_TAB_SIZE]; -} MEASURE_REQ_TAB, *PMEASURE_REQ_TAB; - -typedef struct _TPC_REQ_ENTRY -{ - struct _TPC_REQ_ENTRY *pNext; - ULONG lastTime; - BOOLEAN Valid; - UINT8 DialogToken; -} TPC_REQ_ENTRY, *PTPC_REQ_ENTRY; - -typedef struct _TPC_REQ_TAB -{ - UCHAR Size; - PTPC_REQ_ENTRY Hash[MAX_HASH_TPC_REQ_TAB_SIZE]; - TPC_REQ_ENTRY Content[MAX_TPC_REQ_TAB_SIZE]; -} TPC_REQ_TAB, *PTPC_REQ_TAB; - - -/* The regulatory information */ -typedef struct _DOT11_CHANNEL_SET -{ - UCHAR NumberOfChannels; - UINT8 MaxTxPwr; - UCHAR ChannelList[16]; -} DOT11_CHANNEL_SET, *PDOT11_CHANNEL_SET; - -typedef struct _DOT11_REGULATORY_INFORMATION -{ - UCHAR RegulatoryClass; - DOT11_CHANNEL_SET ChannelSet; -} DOT11_REGULATORY_INFORMATION, *PDOT11_REGULATORY_INFORMATION; - - - -#define RM_TPC_REQ 0 -#define RM_MEASURE_REQ 1 - -#define RM_BASIC 0 -#define RM_CCA 1 -#define RM_RPI_HISTOGRAM 2 -#define RM_CH_LOAD 3 -#define RM_NOISE_HISTOGRAM 4 - - -typedef struct PACKED _TPC_REPORT_INFO -{ - UINT8 TxPwr; - UINT8 LinkMargin; -} TPC_REPORT_INFO, *PTPC_REPORT_INFO; - -typedef struct PACKED _CH_SW_ANN_INFO -{ - UINT8 ChSwMode; - UINT8 Channel; - UINT8 ChSwCnt; -} CH_SW_ANN_INFO, *PCH_SW_ANN_INFO; - -typedef union PACKED _MEASURE_REQ_MODE -{ -#ifdef RT_BIG_ENDIAN - struct PACKED - { - - UINT8 :3; - UINT8 DurationMandatory:1; - UINT8 Report:1; - UINT8 Request:1; - UINT8 Enable:1; - UINT8 Parallel:1; - } field; -#else - struct PACKED - { - UINT8 Parallel:1; - UINT8 Enable:1; - UINT8 Request:1; - UINT8 Report:1; - UINT8 DurationMandatory:1; - UINT8 :3; - } field; -#endif // RT_BIG_ENDIAN // - UINT8 word; -} MEASURE_REQ_MODE, *PMEASURE_REQ_MODE; - -typedef struct PACKED _MEASURE_REQ -{ - UINT8 ChNum; - UINT64 MeasureStartTime; - UINT16 MeasureDuration; -} MEASURE_REQ, *PMEASURE_REQ; - -typedef struct PACKED _MEASURE_REQ_INFO -{ - UINT8 Token; - MEASURE_REQ_MODE ReqMode; - UINT8 ReqType; - UINT8 Oct[0]; -} MEASURE_REQ_INFO, *PMEASURE_REQ_INFO; - -typedef union PACKED _MEASURE_BASIC_REPORT_MAP -{ -#ifdef RT_BIG_ENDIAN - struct PACKED - { - UINT8 Rev:3; - - UINT8 Unmeasure:1; - UINT8 Radar:1; - UINT8 UnidentifiedSignal:1; - UINT8 OfdmPreamble:1; - UINT8 BSS:1; - } field; -#else - struct PACKED - { - UINT8 BSS:1; - - UINT8 OfdmPreamble:1; - UINT8 UnidentifiedSignal:1; - UINT8 Radar:1; - UINT8 Unmeasure:1; - UINT8 Rev:3; - } field; -#endif // RT_BIG_ENDIAN // - UINT8 word; -} MEASURE_BASIC_REPORT_MAP, *PMEASURE_BASIC_REPORT_MAP; - -typedef struct PACKED _MEASURE_BASIC_REPORT -{ - UINT8 ChNum; - UINT64 MeasureStartTime; - UINT16 MeasureDuration; - MEASURE_BASIC_REPORT_MAP Map; -} MEASURE_BASIC_REPORT, *PMEASURE_BASIC_REPORT; - -typedef struct PACKED _MEASURE_CCA_REPORT -{ - UINT8 ChNum; - UINT64 MeasureStartTime; - UINT16 MeasureDuration; - UINT8 CCA_Busy_Fraction; -} MEASURE_CCA_REPORT, *PMEASURE_CCA_REPORT; - -typedef struct PACKED _MEASURE_RPI_REPORT -{ - UINT8 ChNum; - UINT64 MeasureStartTime; - UINT16 MeasureDuration; - UINT8 RPI_Density[8]; -} MEASURE_RPI_REPORT, *PMEASURE_RPI_REPORT; - -typedef union PACKED _MEASURE_REPORT_MODE -{ - struct PACKED - { -#ifdef RT_BIG_ENDIAN - UINT8 Rev:5; - UINT8 Refused:1; - UINT8 Incapable:1; - UINT8 Late:1; -#else - UINT8 Late:1; - UINT8 Incapable:1; - UINT8 Refused:1; - UINT8 Rev:5; -#endif // RT_BIG_ENDIAN // - } field; - UINT8 word; -} MEASURE_REPORT_MODE, *PMEASURE_REPORT_MODE; - -typedef struct PACKED _MEASURE_REPORT_INFO -{ - UINT8 Token; - UINT8 ReportMode; - UINT8 ReportType; - UINT8 Octect[0]; -} MEASURE_REPORT_INFO, *PMEASURE_REPORT_INFO; - -typedef struct PACKED _QUIET_INFO -{ - UINT8 QuietCnt; - UINT8 QuietPeriod; - UINT16 QuietDuration; - UINT16 QuietOffset; -} QUIET_INFO, *PQUIET_INFO; - -#endif // __SPECTRUM_DEF_H__ // diff --git a/drivers/staging/rt3090/sta/assoc.c b/drivers/staging/rt3090/sta/assoc.c deleted file mode 100644 index 012ed2b060832d3869cb33df67a094e3cbcc3141..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/sta/assoc.c +++ /dev/null @@ -1,1673 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - assoc.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - John 2004-9-3 porting from RT2500 -*/ - -#include "../rt_config.h" - - -UCHAR CipherWpaTemplate[] = { - 0xdd, // WPA IE - 0x16, // Length - 0x00, 0x50, 0xf2, 0x01, // oui - 0x01, 0x00, // Version - 0x00, 0x50, 0xf2, 0x02, // Multicast - 0x01, 0x00, // Number of unicast - 0x00, 0x50, 0xf2, 0x02, // unicast - 0x01, 0x00, // number of authentication method - 0x00, 0x50, 0xf2, 0x01 // authentication - }; - -UCHAR CipherWpa2Template[] = { - 0x30, // RSN IE - 0x14, // Length - 0x01, 0x00, // Version - 0x00, 0x0f, 0xac, 0x02, // group cipher, TKIP - 0x01, 0x00, // number of pairwise - 0x00, 0x0f, 0xac, 0x02, // unicast - 0x01, 0x00, // number of authentication method - 0x00, 0x0f, 0xac, 0x02, // authentication - 0x00, 0x00, // RSN capability - }; - -UCHAR Ccx2IeInfo[] = { 0x00, 0x40, 0x96, 0x03, 0x02}; - -/* - ========================================================================== - Description: - association state machine init, including state transition and timer init - Parameters: - S - pointer to the association state machine - - IRQL = PASSIVE_LEVEL - - ========================================================================== - */ -VOID AssocStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]) -{ - StateMachineInit(S, Trans, MAX_ASSOC_STATE, MAX_ASSOC_MSG, (STATE_MACHINE_FUNC)Drop, ASSOC_IDLE, ASSOC_MACHINE_BASE); - - // first column - StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)MlmeAssocReqAction); - StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)MlmeReassocReqAction); - StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)MlmeDisassocReqAction); - StateMachineSetAction(S, ASSOC_IDLE, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); - - // second column - StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc); - StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc); - StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate); - StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); - StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction); - // - // Patch 3Com AP MOde:3CRWE454G72 - // We send Assoc request frame to this AP, it always send Reassoc Rsp not Associate Rsp. - // - StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction); - StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_ASSOC_TIMEOUT, (STATE_MACHINE_FUNC)AssocTimeoutAction); - - // third column - StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc); - StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc); - StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate); - StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); - StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction); - // - // Patch, AP doesn't send Reassociate Rsp frame to Station. - // - StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction); - StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_REASSOC_TIMEOUT, (STATE_MACHINE_FUNC)ReassocTimeoutAction); - - // fourth column - StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc); - StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc); - StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate); - StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); - StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_DISASSOC_TIMEOUT, (STATE_MACHINE_FUNC)DisassocTimeoutAction); - - // initialize the timer - RTMPInitTimer(pAd, &pAd->MlmeAux.AssocTimer, GET_TIMER_FUNCTION(AssocTimeout), pAd, FALSE); - RTMPInitTimer(pAd, &pAd->MlmeAux.ReassocTimer, GET_TIMER_FUNCTION(ReassocTimeout), pAd, FALSE); - RTMPInitTimer(pAd, &pAd->MlmeAux.DisassocTimer, GET_TIMER_FUNCTION(DisassocTimeout), pAd, FALSE); -} - -/* - ========================================================================== - Description: - Association timeout procedure. After association timeout, this function - will be called and it will put a message into the MLME queue - Parameters: - Standard timer parameters - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AssocTimeout(IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_ASSOC_TIMEOUT, 0, NULL); - RTMP_MLME_HANDLER(pAd); -} - -/* - ========================================================================== - Description: - Reassociation timeout procedure. After reassociation timeout, this - function will be called and put a message into the MLME queue - Parameters: - Standard timer parameters - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID ReassocTimeout(IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_REASSOC_TIMEOUT, 0, NULL); - RTMP_MLME_HANDLER(pAd); -} - -/* - ========================================================================== - Description: - Disassociation timeout procedure. After disassociation timeout, this - function will be called and put a message into the MLME queue - Parameters: - Standard timer parameters - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID DisassocTimeout(IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_DISASSOC_TIMEOUT, 0, NULL); - RTMP_MLME_HANDLER(pAd); -} - -/* - ========================================================================== - Description: - mlme assoc req handling procedure - Parameters: - Adapter - Adapter pointer - Elem - MLME Queue Element - Pre: - the station has been authenticated and the following information is stored in the config - -# SSID - -# supported rates and their length - -# listen interval (Adapter->StaCfg.default_listen_count) - -# Transmit power (Adapter->StaCfg.tx_power) - Post : - -# An association request frame is generated and sent to the air - -# Association timer starts - -# Association state -> ASSOC_WAIT_RSP - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID MlmeAssocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR ApAddr[6]; - HEADER_802_11 AssocHdr; - UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; - USHORT ListenIntv; - ULONG Timeout; - USHORT CapabilityInfo; - BOOLEAN TimerCancelled; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - ULONG tmp; - USHORT VarIesOffset; - USHORT Status; - - // Block all authentication request durning WPA block period - if (pAd->StaCfg.bBlockAssoc == TRUE) - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block Assoc request durning WPA block period!\n")); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); - } - // check sanity first - else if (MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) - { - RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled); - COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr); - - // Get an unused nonpaged memory - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() allocate memory failed \n")); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - Status = MLME_FAIL_NO_RESOURCE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); - return; - } - - // Add by James 03/06/27 - pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); - // Association don't need to report MAC address - pAd->StaCfg.AssocInfo.AvailableRequestFixedIEs = - NDIS_802_11_AI_REQFI_CAPABILITIES | NDIS_802_11_AI_REQFI_LISTENINTERVAL; - pAd->StaCfg.AssocInfo.RequestFixedIEs.Capabilities = CapabilityInfo; - pAd->StaCfg.AssocInfo.RequestFixedIEs.ListenInterval = ListenIntv; - // Only reassociate need this - //COPY_MAC_ADDR(pAd->StaCfg.AssocInfo.RequestFixedIEs.CurrentAPAddress, ApAddr); - pAd->StaCfg.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); - - NdisZeroMemory(pAd->StaCfg.ReqVarIEs, MAX_VIE_LEN); - // First add SSID - VarIesOffset = 0; - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SsidIe, 1); - VarIesOffset += 1; - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SsidLen, 1); - VarIesOffset += 1; - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); - VarIesOffset += pAd->MlmeAux.SsidLen; - - // Second add Supported rates - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SupRateIe, 1); - VarIesOffset += 1; - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SupRateLen, 1); - VarIesOffset += 1; - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.SupRate, pAd->MlmeAux.SupRateLen); - VarIesOffset += pAd->MlmeAux.SupRateLen; - // End Add by James - - if ((pAd->CommonCfg.Channel > 14) && - (pAd->CommonCfg.bIEEE80211H == TRUE)) - CapabilityInfo |= 0x0100; - - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send ASSOC request...\n")); - MgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, ApAddr); - - // Build basic frame first - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &AssocHdr, - 2, &CapabilityInfo, - 2, &ListenIntv, - 1, &SsidIe, - 1, &pAd->MlmeAux.SsidLen, - pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, - 1, &SupRateIe, - 1, &pAd->MlmeAux.SupRateLen, - pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, - END_OF_ARGS); - - if (pAd->MlmeAux.ExtRateLen != 0) - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &ExtRateIe, - 1, &pAd->MlmeAux.ExtRateLen, - pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, - END_OF_ARGS); - FrameLen += tmp; - } - - -#ifdef DOT11_N_SUPPORT - // HT - if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - ULONG TmpLen; - UCHAR HtLen; - UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; - if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE) - { - HtLen = SIZE_HT_CAP_IE + 4; - MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, - 1, &WpaIe, - 1, &HtLen, - 4, &BROADCOM[0], - pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, - END_OF_ARGS); - } - else - { -#ifdef RT_BIG_ENDIAN - HT_CAPABILITY_IE HtCapabilityTmp; -#endif - -#ifndef RT_BIG_ENDIAN - MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, - 1, &HtCapIe, - 1, &pAd->MlmeAux.HtCapabilityLen, - pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, - END_OF_ARGS); -#else - NdisZeroMemory(&HtCapabilityTmp, sizeof(HT_CAPABILITY_IE)); - NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, pAd->MlmeAux.HtCapabilityLen); - *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); - *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); - - MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, - 1, &HtCapIe, - 1, &pAd->MlmeAux.HtCapabilityLen, - pAd->MlmeAux.HtCapabilityLen,&HtCapabilityTmp, - END_OF_ARGS); -#endif - } - FrameLen += TmpLen; - } -#endif // DOT11_N_SUPPORT // - - // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION - // Case I: (Aggregation + Piggy-Back) - // 1. user enable aggregation, AND - // 2. Mac support piggy-back - // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON - // Case II: (Aggregation) - // 1. user enable aggregation, AND - // 2. AP annouces it's AGGREGATION-capable in BEACON - if (pAd->CommonCfg.bAggregationCapable) - { - if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)) - { - ULONG TmpLen; - UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00}; - MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, - 9, RalinkIe, - END_OF_ARGS); - FrameLen += TmpLen; - } - else if (pAd->MlmeAux.APRalinkIe & 0x00000001) - { - ULONG TmpLen; - UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00}; - MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, - 9, RalinkIe, - END_OF_ARGS); - FrameLen += TmpLen; - } - } - else - { - ULONG TmpLen; - UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06, 0x00, 0x00, 0x00}; - MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, - 9, RalinkIe, - END_OF_ARGS); - FrameLen += TmpLen; - } - - if (pAd->MlmeAux.APEdcaParm.bValid) - { - if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable) - { - QBSS_STA_INFO_PARM QosInfo; - - NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); - QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE; - QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK; - QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI; - QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO; - QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength; - WmeIe[8] |= *(PUCHAR)&QosInfo; - } - else - { - // The Parameter Set Count is set to ��0�� in the association request frames - // WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f); - } - - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 9, &WmeIe[0], - END_OF_ARGS); - FrameLen += tmp; - } - - // - // Let WPA(#221) Element ID on the end of this association frame. - // Otherwise some AP will fail on parsing Element ID and set status fail on Assoc Rsp. - // For example: Put Vendor Specific IE on the front of WPA IE. - // This happens on AP (Model No:Linksys WRK54G) - // - if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) - ) - ) - { - UCHAR RSNIe = IE_WPA; - - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)) - { - RSNIe = IE_WPA2; - } - -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT -#ifdef SIOCSIWGENIE - if ((pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_ENABLE) && - (pAd->StaCfg.bRSN_IE_FromWpaSupplicant == FALSE)) -#endif // SIOCSIWGENIE // -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0); - - // Check for WPA PMK cache list - if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) - { - INT idx; - BOOLEAN FoundPMK = FALSE; - // Search chched PMKID, append it if existed - for (idx = 0; idx < PMKID_NO; idx++) - { - if (NdisEqualMemory(ApAddr, &pAd->StaCfg.SavedPMK[idx].BSSID, 6)) - { - FoundPMK = TRUE; - break; - } - } - - if (FoundPMK) - { - // Set PMK number - *(PUSHORT) &pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len] = 1; - NdisMoveMemory(&pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len + 2], &pAd->StaCfg.SavedPMK[idx].PMKID, 16); - pAd->StaCfg.RSNIE_Len += 18; - } - } - -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT -#ifdef SIOCSIWGENIE - if ((pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) && - (pAd->StaCfg.bRSN_IE_FromWpaSupplicant == TRUE)) - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, - END_OF_ARGS); - } - else -#endif -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &RSNIe, - 1, &pAd->StaCfg.RSNIE_Len, - pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, - END_OF_ARGS); - } - - FrameLen += tmp; - -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT -#ifdef SIOCSIWGENIE - if ((pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_ENABLE) || - (pAd->StaCfg.bRSN_IE_FromWpaSupplicant == FALSE)) -#endif -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - { - // Append Variable IE - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &RSNIe, 1); - VarIesOffset += 1; - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->StaCfg.RSNIE_Len, 1); - VarIesOffset += 1; - } - NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len); - VarIesOffset += pAd->StaCfg.RSNIE_Len; - - // Set Variable IEs Length - pAd->StaCfg.ReqVarIELen = VarIesOffset; - } - - - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - RTMPSetTimer(&pAd->MlmeAux.AssocTimer, Timeout); - pAd->Mlme.AssocMachine.CurrState = ASSOC_WAIT_RSP; - } - else - { - DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() sanity check failed. BUG!!!!!! \n")); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - Status = MLME_INVALID_FORMAT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); - } - -} - -/* - ========================================================================== - Description: - mlme reassoc req handling procedure - Parameters: - Elem - - Pre: - -# SSID (Adapter->StaCfg.ssid[]) - -# BSSID (AP address, Adapter->StaCfg.bssid) - -# Supported rates (Adapter->StaCfg.supported_rates[]) - -# Supported rates length (Adapter->StaCfg.supported_rates_len) - -# Tx power (Adapter->StaCfg.tx_power) - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID MlmeReassocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR ApAddr[6]; - HEADER_802_11 ReassocHdr; - UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; - USHORT CapabilityInfo, ListenIntv; - ULONG Timeout; - ULONG FrameLen = 0; - BOOLEAN TimerCancelled; - NDIS_STATUS NStatus; - ULONG tmp; - PUCHAR pOutBuffer = NULL; - USHORT Status; - - // Block all authentication request durning WPA block period - if (pAd->StaCfg.bBlockAssoc == TRUE) - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block ReAssoc request durning WPA block period!\n")); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); - } - // the parameters are the same as the association - else if(MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) - { - RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled); - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() allocate memory failed \n")); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - Status = MLME_FAIL_NO_RESOURCE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); - return; - } - - COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr); - - // make frame, use bssid as the AP address?? - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send RE-ASSOC request...\n")); - MgtMacHeaderInit(pAd, &ReassocHdr, SUBTYPE_REASSOC_REQ, 0, ApAddr, ApAddr); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &ReassocHdr, - 2, &CapabilityInfo, - 2, &ListenIntv, - MAC_ADDR_LEN, ApAddr, - 1, &SsidIe, - 1, &pAd->MlmeAux.SsidLen, - pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, - 1, &SupRateIe, - 1, &pAd->MlmeAux.SupRateLen, - pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, - END_OF_ARGS); - - if (pAd->MlmeAux.ExtRateLen != 0) - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &ExtRateIe, - 1, &pAd->MlmeAux.ExtRateLen, - pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, - END_OF_ARGS); - FrameLen += tmp; - } - - - if (pAd->MlmeAux.APEdcaParm.bValid) - { - if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable) - { - QBSS_STA_INFO_PARM QosInfo; - - NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); - QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE; - QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK; - QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI; - QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO; - QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength; - WmeIe[8] |= *(PUCHAR)&QosInfo; - } - - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 9, &WmeIe[0], - END_OF_ARGS); - FrameLen += tmp; - } - -#ifdef DOT11_N_SUPPORT - // HT - if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - ULONG TmpLen; - UCHAR HtLen; - UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; - if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE) - { - HtLen = SIZE_HT_CAP_IE + 4; - MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, - 1, &WpaIe, - 1, &HtLen, - 4, &BROADCOM[0], - pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, - END_OF_ARGS); - } - else - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, - 1, &HtCapIe, - 1, &pAd->MlmeAux.HtCapabilityLen, - pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, - END_OF_ARGS); - } - FrameLen += TmpLen; - } -#endif // DOT11_N_SUPPORT // - - // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION - // Case I: (Aggregation + Piggy-Back) - // 1. user enable aggregation, AND - // 2. Mac support piggy-back - // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON - // Case II: (Aggregation) - // 1. user enable aggregation, AND - // 2. AP annouces it's AGGREGATION-capable in BEACON - if (pAd->CommonCfg.bAggregationCapable) - { - if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)) - { - ULONG TmpLen; - UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00}; - MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, - 9, RalinkIe, - END_OF_ARGS); - FrameLen += TmpLen; - } - else if (pAd->MlmeAux.APRalinkIe & 0x00000001) - { - ULONG TmpLen; - UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00}; - MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, - 9, RalinkIe, - END_OF_ARGS); - FrameLen += TmpLen; - } - } - else - { - ULONG TmpLen; - UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x04, 0x00, 0x00, 0x00}; - MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, - 9, RalinkIe, - END_OF_ARGS); - FrameLen += TmpLen; - } - - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - RTMPSetTimer(&pAd->MlmeAux.ReassocTimer, Timeout); /* in mSec */ - pAd->Mlme.AssocMachine.CurrState = REASSOC_WAIT_RSP; - } - else - { - DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() sanity check failed. BUG!!!! \n")); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - Status = MLME_INVALID_FORMAT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); - } -} - -/* - ========================================================================== - Description: - Upper layer issues disassoc request - Parameters: - Elem - - - IRQL = PASSIVE_LEVEL - - ========================================================================== - */ -VOID MlmeDisassocReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - PMLME_DISASSOC_REQ_STRUCT pDisassocReq; - HEADER_802_11 DisassocHdr; - PHEADER_802_11 pDisassocHdr; - PUCHAR pOutBuffer = NULL; - ULONG FrameLen = 0; - NDIS_STATUS NStatus; - BOOLEAN TimerCancelled; - ULONG Timeout = 500; - USHORT Status; - -#ifdef QOS_DLS_SUPPORT - // send DLS-TEAR_DOWN message, - if (pAd->CommonCfg.bDLSCapable) - { - UCHAR i; - - // tear down local dls table entry - for (i=0; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) - { - RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - } - } - - // tear down peer dls table entry - for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) - { - RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - } - } - } -#endif // QOS_DLS_SUPPORT // - - // skip sanity check - pDisassocReq = (PMLME_DISASSOC_REQ_STRUCT)(Elem->Msg); - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - MlmeDisassocReqAction() allocate memory failed\n")); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - Status = MLME_FAIL_NO_RESOURCE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status); - return; - } - - - - - RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &TimerCancelled); - - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send DISASSOC request[BSSID::%02x:%02x:%02x:%02x:%02x:%02x (Reason=%d)\n", - pDisassocReq->Addr[0], pDisassocReq->Addr[1], pDisassocReq->Addr[2], - pDisassocReq->Addr[3], pDisassocReq->Addr[4], pDisassocReq->Addr[5], pDisassocReq->Reason)); - MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, pDisassocReq->Addr); // patch peap ttls switching issue - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11),&DisassocHdr, - 2, &pDisassocReq->Reason, - END_OF_ARGS); - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - - // To patch Instance and Buffalo(N) AP - // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine - // Therefore, we send both of them. - pDisassocHdr = (PHEADER_802_11)pOutBuffer; - pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH; - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - - MlmeFreeMemory(pAd, pOutBuffer); - - pAd->StaCfg.DisassocReason = REASON_DISASSOC_STA_LEAVING; - COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pDisassocReq->Addr); - - RTMPSetTimer(&pAd->MlmeAux.DisassocTimer, Timeout); /* in mSec */ - pAd->Mlme.AssocMachine.CurrState = DISASSOC_WAIT_RSP; - -#ifdef WPA_SUPPLICANT_SUPPORT -#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) - { - //send disassociate event to wpa_supplicant - RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, RT_DISASSOC_EVENT_FLAG, NULL, NULL, 0); - } -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // -#endif // WPA_SUPPLICANT_SUPPORT // - -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT - RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, 0); -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - -} - -/* - ========================================================================== - Description: - peer sends assoc rsp back - Parameters: - Elme - MLME message containing the received frame - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID PeerAssocRspAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT CapabilityInfo, Status, Aid; - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; - UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; - UCHAR Addr2[MAC_ADDR_LEN]; - BOOLEAN TimerCancelled; - UCHAR CkipFlag; - EDCA_PARM EdcaParm; - HT_CAPABILITY_IE HtCapability; - ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE - UCHAR HtCapabilityLen; - UCHAR AddHtInfoLen; - UCHAR NewExtChannelOffset = 0xff; - - if (PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, - &HtCapability,&AddHtInfo, &HtCapabilityLen,&AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag)) - { - // The frame is for me ? - if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():ASSOC - receive ASSOC_RSP to me (status=%d)\n", Status)); -#ifdef DOT11_N_SUPPORT - DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():MacTable [%d].AMsduSize = %d. ClientStatusFlags = 0x%lx \n",Elem->Wcid, pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); -#endif // DOT11_N_SUPPORT // - RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled); - - - if(Status == MLME_SUCCESS) - { - UCHAR MaxSupportedRateIn500Kbps = 0; - UCHAR idx; - - // supported rates array may not be sorted. sort it and find the maximum rate - for (idx=0; idxMacTab.Content[BSSID_WCID], - MaxSupportedRateIn500Kbps, - &HtCapability, - HtCapabilityLen, - &AddHtInfo, - AddHtInfoLen, - CapabilityInfo); - } - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); - } - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerAssocRspAction() sanity check fail\n")); - } -} - -/* - ========================================================================== - Description: - peer sends reassoc rsp - Parametrs: - Elem - MLME message cntaining the received frame - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID PeerReassocRspAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT CapabilityInfo; - USHORT Status; - USHORT Aid; - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; - UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; - UCHAR Addr2[MAC_ADDR_LEN]; - UCHAR CkipFlag; - BOOLEAN TimerCancelled; - EDCA_PARM EdcaParm; - HT_CAPABILITY_IE HtCapability; - ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE - UCHAR HtCapabilityLen; - UCHAR AddHtInfoLen; - UCHAR NewExtChannelOffset = 0xff; - - if(PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, - &HtCapability, &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag)) - { - if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) // The frame is for me ? - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - receive REASSOC_RSP to me (status=%d)\n", Status)); - RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled); - - if(Status == MLME_SUCCESS) - { - // go to procedure listed on page 376 - AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, SupRate, SupRateLen, ExtRate, ExtRateLen, - &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo); - -#ifdef WPA_SUPPLICANT_SUPPORT -#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) - { - SendAssocIEsToWpaSupplicant(pAd); - RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, RT_ASSOC_EVENT_FLAG, NULL, NULL, 0); - } -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // -#endif // WPA_SUPPLICANT_SUPPORT // - -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT - { - wext_notify_event_assoc(pAd); - RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, &pAd->MlmeAux.Bssid[0], NULL, 0); - } -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - - } - - // CkipFlag is no use for reassociate - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); - } - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerReassocRspAction() sanity check fail\n")); - } - -} - -/* - ========================================================================== - Description: - procedures on IEEE 802.11/1999 p.376 - Parametrs: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AssocPostProc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr2, - IN USHORT CapabilityInfo, - IN USHORT Aid, - IN UCHAR SupRate[], - IN UCHAR SupRateLen, - IN UCHAR ExtRate[], - IN UCHAR ExtRateLen, - IN PEDCA_PARM pEdcaParm, - IN HT_CAPABILITY_IE *pHtCapability, - IN UCHAR HtCapabilityLen, - IN ADD_HT_INFO_IE *pAddHtInfo) // AP might use this additional ht info IE -{ - ULONG Idx; - - pAd->MlmeAux.BssType = BSS_INFRA; - COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pAddr2); - pAd->MlmeAux.Aid = Aid; - pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; - -#ifdef DOT11_N_SUPPORT - // Some HT AP might lost WMM IE. We add WMM ourselves. beacuase HT requires QoS on. - if ((HtCapabilityLen > 0) && (pEdcaParm->bValid == FALSE)) - { - pEdcaParm->bValid = TRUE; - pEdcaParm->Aifsn[0] = 3; - pEdcaParm->Aifsn[1] = 7; - pEdcaParm->Aifsn[2] = 2; - pEdcaParm->Aifsn[3] = 2; - - pEdcaParm->Cwmin[0] = 4; - pEdcaParm->Cwmin[1] = 4; - pEdcaParm->Cwmin[2] = 3; - pEdcaParm->Cwmin[3] = 2; - - pEdcaParm->Cwmax[0] = 10; - pEdcaParm->Cwmax[1] = 10; - pEdcaParm->Cwmax[2] = 4; - pEdcaParm->Cwmax[3] = 3; - - pEdcaParm->Txop[0] = 0; - pEdcaParm->Txop[1] = 0; - pEdcaParm->Txop[2] = 96; - pEdcaParm->Txop[3] = 48; - - } -#endif // DOT11_N_SUPPORT // - - NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM)); - - // filter out un-supported rates - pAd->MlmeAux.SupRateLen = SupRateLen; - NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen); - RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); - - // filter out un-supported rates - pAd->MlmeAux.ExtRateLen = ExtRateLen; - NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen); - RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); - -#ifdef DOT11_N_SUPPORT - if (HtCapabilityLen > 0) - { - RTMPCheckHt(pAd, BSSID_WCID, pHtCapability, pAddHtInfo); - } - DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> AP.AMsduSize = %d. ClientStatusFlags = 0x%lx \n", pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); - - DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> (Mmps=%d, AmsduSize=%d, )\n", - pAd->MacTab.Content[BSSID_WCID].MmpsMode, pAd->MacTab.Content[BSSID_WCID].AMsduSize)); -#endif // DOT11_N_SUPPORT // - - // Set New WPA information - Idx = BssTableSearch(&pAd->ScanTab, pAddr2, pAd->MlmeAux.Channel); - if (Idx == BSS_NOT_FOUND) - { - DBGPRINT_ERR(("ASSOC - Can't find BSS after receiving Assoc response\n")); - } - else - { - // Init variable - pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = 0; - NdisZeroMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, MAX_LEN_OF_RSNIE); - - // Store appropriate RSN_IE for WPA SM negotiation later - if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAd->ScanTab.BssEntry[Idx].VarIELen != 0)) - { - PUCHAR pVIE; - USHORT len; - PEID_STRUCT pEid; - - pVIE = pAd->ScanTab.BssEntry[Idx].VarIEs; - len = pAd->ScanTab.BssEntry[Idx].VarIELen; - //KH need to check again - // Don't allow to go to sleep mode if authmode is WPA-related. - //This can make Authentication process more smoothly. - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); - - while (len > 0) - { - pEid = (PEID_STRUCT) pVIE; - // For WPA/WPAPSK - if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) - && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) - { - NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2)); - pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2); - DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA SM negotiation \n")); - } - // For WPA2/WPA2PSK - else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) - && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2)); - pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2); - DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA2 SM negotiation \n")); - } - - pVIE += (pEid->Len + 2); - len -= (pEid->Len + 2); - } - - - } - - if (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == 0) - { - DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> no RSN_IE \n")); - } - else - { - hex_dump("RSN_IE", pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len); - } - } -} - -/* - ========================================================================== - Description: - left part of IEEE 802.11/1999 p.374 - Parameters: - Elem - MLME message containing the received frame - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID PeerDisassocAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR Addr2[MAC_ADDR_LEN]; - USHORT Reason; - - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction()\n")); - if(PeerDisassocSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() Reason = %d\n", Reason)); - if (INFRA_ON(pAd) && MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, Addr2)) - { - - if (pAd->CommonCfg.bWirelessEvent) - { - RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - } - - - LinkDown(pAd, TRUE); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - -#ifdef WPA_SUPPLICANT_SUPPORT -#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) - { - //send disassociate event to wpa_supplicant - RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, RT_DISASSOC_EVENT_FLAG, NULL, NULL, 0); - } -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // -#endif // WPA_SUPPLICANT_SUPPORT // - -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT - RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, 0); -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - } - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() sanity check fail\n")); - } - -} - -/* - ========================================================================== - Description: - what the state machine will do after assoc timeout - Parameters: - Elme - - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AssocTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - AssocTimeoutAction\n")); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - Status = MLME_REJ_TIMEOUT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); -} - -/* - ========================================================================== - Description: - what the state machine will do after reassoc timeout - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID ReassocTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - ReassocTimeoutAction\n")); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - Status = MLME_REJ_TIMEOUT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); -} - -/* - ========================================================================== - Description: - what the state machine will do after disassoc timeout - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID DisassocTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - DisassocTimeoutAction\n")); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - Status = MLME_SUCCESS; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status); -} - -VOID InvalidStateWhenAssoc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenAssoc(state=%ld), reset ASSOC state machine\n", - pAd->Mlme.AssocMachine.CurrState)); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); -} - -VOID InvalidStateWhenReassoc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenReassoc(state=%ld), reset ASSOC state machine\n", - pAd->Mlme.AssocMachine.CurrState)); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); -} - -VOID InvalidStateWhenDisassociate( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenDisassoc(state=%ld), reset ASSOC state machine\n", - pAd->Mlme.AssocMachine.CurrState)); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status); -} - -/* - ========================================================================== - Description: - right part of IEEE 802.11/1999 page 374 - Note: - This event should never cause ASSOC state machine perform state - transition, and has no relationship with CNTL machine. So we separate - this routine as a service outside of ASSOC state transition table. - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID Cls3errAction( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr) -{ - HEADER_802_11 DisassocHdr; - PHEADER_802_11 pDisassocHdr; - PUCHAR pOutBuffer = NULL; - ULONG FrameLen = 0; - NDIS_STATUS NStatus; - USHORT Reason = REASON_CLS3ERR; - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - return; - - DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Class 3 Error, Send DISASSOC frame\n")); - MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pAddr, pAd->CommonCfg.Bssid); // patch peap ttls switching issue - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11),&DisassocHdr, - 2, &Reason, - END_OF_ARGS); - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - - // To patch Instance and Buffalo(N) AP - // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine - // Therefore, we send both of them. - pDisassocHdr = (PHEADER_802_11)pOutBuffer; - pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH; - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - - MlmeFreeMemory(pAd, pOutBuffer); - - pAd->StaCfg.DisassocReason = REASON_CLS3ERR; - COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pAddr); -} - -#ifdef WPA_SUPPLICANT_SUPPORT -#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT -VOID SendAssocIEsToWpaSupplicant( - IN PRTMP_ADAPTER pAd) -{ - STRING custom[IW_CUSTOM_MAX] = {0}; - - if ((pAd->StaCfg.ReqVarIELen + 17) <= IW_CUSTOM_MAX) - { - sprintf(custom, "ASSOCINFO_ReqIEs="); - NdisMoveMemory(custom+17, pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen); - RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, RT_REQIE_EVENT_FLAG, NULL, (PUCHAR)custom, pAd->StaCfg.ReqVarIELen + 17); - - RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, RT_ASSOCINFO_EVENT_FLAG, NULL, NULL, 0); - } - else - DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen + 17 > MAX_CUSTOM_LEN\n")); - - return; -} -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // -#endif // WPA_SUPPLICANT_SUPPORT // - -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT -int wext_notify_event_assoc( - IN RTMP_ADAPTER *pAd) -{ - char custom[IW_CUSTOM_MAX] = {0}; - -#if WIRELESS_EXT > 17 - if (pAd->StaCfg.ReqVarIELen <= IW_CUSTOM_MAX) - { - NdisMoveMemory(custom, pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen); - RtmpOSWrielessEventSend(pAd, IWEVASSOCREQIE, -1, NULL, custom, pAd->StaCfg.ReqVarIELen); - } - else - DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen > MAX_CUSTOM_LEN\n")); -#else - int len; - - len = (pAd->StaCfg.ReqVarIELen*2) + 17; - if (len <= IW_CUSTOM_MAX) - { - UCHAR idx; - sprintf(custom, "ASSOCINFO(ReqIEs="); - for (idx=0; idxStaCfg.ReqVarIELen; idx++) - sprintf(custom, "%s%02x", custom, pAd->StaCfg.ReqVarIEs[idx]); - RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, -1, NULL, custom, len); - } - else - DBGPRINT(RT_DEBUG_TRACE, ("len(%d) > MAX_CUSTOM_LEN\n", len)); -#endif - - return 0; - -} -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - - -BOOLEAN StaAddMacTableEntry( - IN PRTMP_ADAPTER pAd, - IN PMAC_TABLE_ENTRY pEntry, - IN UCHAR MaxSupportedRateIn500Kbps, - IN HT_CAPABILITY_IE *pHtCapability, - IN UCHAR HtCapabilityLen, - IN ADD_HT_INFO_IE *pAddHtInfo, - IN UCHAR AddHtInfoLen, - IN USHORT CapabilityInfo) -{ - UCHAR MaxSupportedRate = RATE_11; - - if (ADHOC_ON(pAd)) - CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); - - switch (MaxSupportedRateIn500Kbps) - { - case 108: MaxSupportedRate = RATE_54; break; - case 96: MaxSupportedRate = RATE_48; break; - case 72: MaxSupportedRate = RATE_36; break; - case 48: MaxSupportedRate = RATE_24; break; - case 36: MaxSupportedRate = RATE_18; break; - case 24: MaxSupportedRate = RATE_12; break; - case 18: MaxSupportedRate = RATE_9; break; - case 12: MaxSupportedRate = RATE_6; break; - case 22: MaxSupportedRate = RATE_11; break; - case 11: MaxSupportedRate = RATE_5_5; break; - case 4: MaxSupportedRate = RATE_2; break; - case 2: MaxSupportedRate = RATE_1; break; - default: MaxSupportedRate = RATE_11; break; - } - - if ((pAd->CommonCfg.PhyMode == PHY_11G) && (MaxSupportedRate < RATE_FIRST_OFDM_RATE)) - return FALSE; - -#ifdef DOT11_N_SUPPORT - // 11n only - if (((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))&& (HtCapabilityLen == 0)) - return FALSE; -#endif // DOT11_N_SUPPORT // - - if (!pEntry) - return FALSE; - - NdisAcquireSpinLock(&pAd->MacTabLock); - if (pEntry) - { - pEntry->PortSecured = WPA_802_1X_PORT_SECURED; - if ((MaxSupportedRate < RATE_FIRST_OFDM_RATE) || - (pAd->CommonCfg.PhyMode == PHY_11B)) - { - pEntry->RateLen = 4; - if (MaxSupportedRate >= RATE_FIRST_OFDM_RATE) - MaxSupportedRate = RATE_11; - } - else - pEntry->RateLen = 12; - - pEntry->MaxHTPhyMode.word = 0; - pEntry->MinHTPhyMode.word = 0; - pEntry->HTPhyMode.word = 0; - pEntry->MaxSupportedRate = MaxSupportedRate; - if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) - { - pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; - pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; - pEntry->MinHTPhyMode.field.MODE = MODE_CCK; - pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; - pEntry->HTPhyMode.field.MODE = MODE_CCK; - pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; - } - else - { - pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; - pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; - pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; - pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; - pEntry->HTPhyMode.field.MODE = MODE_OFDM; - pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; - } - pEntry->CapabilityInfo = CapabilityInfo; - CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); - CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); - } - -#ifdef DOT11_N_SUPPORT - NdisZeroMemory(&pEntry->HTCapability, sizeof(pEntry->HTCapability)); - // If this Entry supports 802.11n, upgrade to HT rate. - if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - UCHAR j, bitmask; //k,bitmask; - CHAR i; - - if (ADHOC_ON(pAd)) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); - if ((pHtCapability->HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) - { - pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; - } - else - { - pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; - pAd->MacTab.fAnyStationNonGF = TRUE; - pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; - } - - if ((pHtCapability->HtCapInfo.ChannelWidth) && - (pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && - ((pAd->StaCfg.BssType == BSS_INFRA) || ((pAd->StaCfg.BssType == BSS_ADHOC) && (pAddHtInfo->AddHtInfo.ExtChanOffset == pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset)))) - { - pEntry->MaxHTPhyMode.field.BW= BW_40; - pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(pHtCapability->HtCapInfo.ShortGIfor40)); - } - else - { - pEntry->MaxHTPhyMode.field.BW = BW_20; - pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(pHtCapability->HtCapInfo.ShortGIfor20)); - pAd->MacTab.fAnyStation20Only = TRUE; - } - - // 3*3 - if (pAd->MACVersion >= RALINK_2883_VERSION && pAd->MACVersion < RALINK_3070_VERSION) - pEntry->MaxHTPhyMode.field.TxBF = pAd->CommonCfg.RegTransmitSetting.field.TxBF; - - // find max fixed rate - for (i=23; i>=0; i--) // 3*3 - { - j = i/8; - bitmask = (1<<(i-(j*8))); - if ((pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j] & bitmask) && (pHtCapability->MCSSet[j] & bitmask)) - { - pEntry->MaxHTPhyMode.field.MCS = i; - break; - } - if (i==0) - break; - } - - - if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) - { - if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32) - { - // Fix MCS as HT Duplicated Mode - pEntry->MaxHTPhyMode.field.BW = 1; - pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; - pEntry->MaxHTPhyMode.field.STBC = 0; - pEntry->MaxHTPhyMode.field.ShortGI = 0; - pEntry->MaxHTPhyMode.field.MCS = 32; - } - else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS) - { - // STA supports fixed MCS - pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - } - } - - pEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); - pEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity; - pEntry->MaxRAmpduFactor = pHtCapability->HtCapParm.MaxRAmpduFactor; - pEntry->MmpsMode = (UCHAR)pHtCapability->HtCapInfo.MimoPs; - pEntry->AMsduSize = (UCHAR)pHtCapability->HtCapInfo.AMsduSize; - pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; - - if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED); - if (pHtCapability->HtCapInfo.ShortGIfor20) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); - if (pHtCapability->HtCapInfo.ShortGIfor40) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); - if (pHtCapability->HtCapInfo.TxSTBC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); - if (pHtCapability->HtCapInfo.RxSTBC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); - if (pHtCapability->ExtHtCapInfo.PlusHTC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); - if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); - if (pHtCapability->ExtHtCapInfo.MCSFeedback == 0x03) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); - NdisMoveMemory(&pEntry->HTCapability, pHtCapability, HtCapabilityLen); - } - else - { - pAd->MacTab.fAnyStationIsLegacy = TRUE; - } -#endif // DOT11_N_SUPPORT // - - pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; - pEntry->CurrTxRate = pEntry->MaxSupportedRate; - - // Set asic auto fall back - if (pAd->StaCfg.bAutoTxRateSwitch == TRUE) - { - PUCHAR pTable; - UCHAR TableSize = 0; - - MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex); - pEntry->bAutoTxRateSwitch = TRUE; - } - else - { - pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; - pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - pEntry->bAutoTxRateSwitch = FALSE; - - // If the legacy mode is set, overwrite the transmit setting of this entry. - RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); - } - - pEntry->PortSecured = WPA_802_1X_PORT_SECURED; - pEntry->Sst = SST_ASSOC; - pEntry->AuthState = AS_AUTH_OPEN; - pEntry->AuthMode = pAd->StaCfg.AuthMode; - pEntry->WepStatus = pAd->StaCfg.WepStatus; - - NdisReleaseSpinLock(&pAd->MacTabLock); - -#ifdef WPA_SUPPLICANT_SUPPORT -#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.WpaSupplicantUP) - { - union iwreq_data wrqu; - - SendAssocIEsToWpaSupplicant(pAd); - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.flags = RT_ASSOC_EVENT_FLAG; - wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); - } -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // -#endif // WPA_SUPPLICANT_SUPPORT // - -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT - { - union iwreq_data wrqu; - wext_notify_event_assoc(pAd); - - memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); - memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); - wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); - - } -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - return TRUE; -} diff --git a/drivers/staging/rt3090/sta/auth.c b/drivers/staging/rt3090/sta/auth.c deleted file mode 100644 index 157e2999fa192f9f6b4ae281eee3540e5ede6f32..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/sta/auth.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - auth.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - John 2004-9-3 porting from RT2500 -*/ - -#include "../rt_config.h" - - -/* - ========================================================================== - Description: - authenticate state machine init, including state transition and timer init - Parameters: - Sm - pointer to the auth state machine - Note: - The state machine looks like this - - AUTH_REQ_IDLE AUTH_WAIT_SEQ2 AUTH_WAIT_SEQ4 - MT2_MLME_AUTH_REQ mlme_auth_req_action invalid_state_when_auth invalid_state_when_auth - MT2_PEER_AUTH_EVEN drop peer_auth_even_at_seq2_action peer_auth_even_at_seq4_action - MT2_AUTH_TIMEOUT Drop auth_timeout_action auth_timeout_action - - IRQL = PASSIVE_LEVEL - - ========================================================================== - */ - -void AuthStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *Sm, - OUT STATE_MACHINE_FUNC Trans[]) -{ - StateMachineInit(Sm, Trans, MAX_AUTH_STATE, MAX_AUTH_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_REQ_IDLE, AUTH_MACHINE_BASE); - - // the first column - StateMachineSetAction(Sm, AUTH_REQ_IDLE, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)MlmeAuthReqAction); - - // the second column - StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth); - StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq2Action); - StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction); - - // the third column - StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth); - StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq4Action); - StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction); - - RTMPInitTimer(pAd, &pAd->MlmeAux.AuthTimer, GET_TIMER_FUNCTION(AuthTimeout), pAd, FALSE); -} - -/* - ========================================================================== - Description: - function to be executed at timer thread when auth timer expires - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AuthTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; - - DBGPRINT(RT_DEBUG_TRACE,("AUTH - AuthTimeout\n")); - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) - return; - - // send a de-auth to reset AP's state machine (Patch AP-Dir635) - if (pAd->Mlme.AuthMachine.CurrState == AUTH_WAIT_SEQ2) - Cls2errAction(pAd, pAd->MlmeAux.Bssid); - - - MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_AUTH_TIMEOUT, 0, NULL); - RTMP_MLME_HANDLER(pAd); -} - - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID MlmeAuthReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - if (AUTH_ReqSend(pAd, Elem, &pAd->MlmeAux.AuthTimer, "AUTH", 1, NULL, 0)) - pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ2; - else - { - USHORT Status; - - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status = MLME_INVALID_FORMAT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); - } -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID PeerAuthRspAtSeq2Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR Addr2[MAC_ADDR_LEN]; - USHORT Seq, Status, RemoteStatus, Alg; - UCHAR ChlgText[CIPHER_TEXT_LEN]; - UCHAR CyperChlgText[CIPHER_TEXT_LEN + 8 + 8]; - UCHAR Element[2]; - HEADER_802_11 AuthHdr; - BOOLEAN TimerCancelled; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - USHORT Status2; - - if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, (PCHAR)ChlgText)) - { - if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2) - { - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status)); - RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); - - if (Status == MLME_SUCCESS) - { - // Authentication Mode "LEAP" has allow for CCX 1.X - if (pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen) - { - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); - } - else - { - // 2. shared key, need to be challenged - Seq++; - RemoteStatus = MLME_SUCCESS; - - // Get an unused nonpaged memory - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n")); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status2 = MLME_FAIL_NO_RESOURCE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2); - return; - } - - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n")); - MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->MlmeAux.Bssid); - AuthHdr.FC.Wep = 1; - // Encrypt challenge text & auth information - RTMPInitWepEngine( - pAd, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, - pAd->StaCfg.DefaultKeyId, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen, - CyperChlgText); - - Alg = cpu2le16(*(USHORT *)&Alg); - Seq = cpu2le16(*(USHORT *)&Seq); - RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus); - - RTMPEncryptData(pAd, (PUCHAR) &Alg, CyperChlgText + 4, 2); - RTMPEncryptData(pAd, (PUCHAR) &Seq, CyperChlgText + 6, 2); - RTMPEncryptData(pAd, (PUCHAR) &RemoteStatus, CyperChlgText + 8, 2); - Element[0] = 16; - Element[1] = 128; - RTMPEncryptData(pAd, Element, CyperChlgText + 10, 2); - RTMPEncryptData(pAd, ChlgText, CyperChlgText + 12, 128); - RTMPSetICV(pAd, CyperChlgText + 140); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &AuthHdr, - CIPHER_TEXT_LEN + 16, CyperChlgText, - END_OF_ARGS); - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT); - pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4; - } - } - else - { - pAd->StaCfg.AuthFailReason = Status; - COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); - } - } - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n")); - } -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID PeerAuthRspAtSeq4Action( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR Addr2[MAC_ADDR_LEN]; - USHORT Alg, Seq, Status; - CHAR ChlgText[CIPHER_TEXT_LEN]; - BOOLEAN TimerCancelled; - - if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText)) - { - if(MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 4) - { - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#4 to me\n")); - RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); - - if (Status != MLME_SUCCESS) - { - pAd->StaCfg.AuthFailReason = Status; - COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); - } - - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); - } - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq4Action() sanity check fail\n")); - } -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID MlmeDeauthReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - MLME_DEAUTH_REQ_STRUCT *pInfo; - HEADER_802_11 DeauthHdr; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - USHORT Status; - - pInfo = (MLME_DEAUTH_REQ_STRUCT *)Elem->Msg; - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeDeauthReqAction() allocate memory fail\n")); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status = MLME_FAIL_NO_RESOURCE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status); - return; - } - - - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send DE-AUTH request (Reason=%d)...\n", pInfo->Reason)); - MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, pAd->MlmeAux.Bssid); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11),&DeauthHdr, - 2, &pInfo->Reason, - END_OF_ARGS); - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - pAd->StaCfg.DeauthReason = pInfo->Reason; - COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pInfo->Addr); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status = MLME_SUCCESS; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status); - - // send wireless event - for deauthentication - if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID AuthTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - AuthTimeoutAction\n")); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status = MLME_REJ_TIMEOUT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID InvalidStateWhenAuth( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", pAd->Mlme.AuthMachine.CurrState)); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); -} - -/* - ========================================================================== - Description: - Some STA/AP - Note: - This action should never trigger AUTH state transition, therefore we - separate it from AUTH state machine, and make it as a standalone service - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID Cls2errAction( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr) -{ - HEADER_802_11 DeauthHdr; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - USHORT Reason = REASON_CLS2ERR; - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - return; - - DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Class 2 error, Send DEAUTH frame...\n")); - MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pAddr, pAd->MlmeAux.Bssid); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11),&DeauthHdr, - 2, &Reason, - END_OF_ARGS); - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - pAd->StaCfg.DeauthReason = Reason; - COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pAddr); -} - -BOOLEAN AUTH_ReqSend( - IN PRTMP_ADAPTER pAd, - IN PMLME_QUEUE_ELEM pElem, - IN PRALINK_TIMER_STRUCT pAuthTimer, - IN PSTRING pSMName, - IN USHORT SeqNo, - IN PUCHAR pNewElement, - IN ULONG ElementLen) -{ - USHORT Alg, Seq, Status; - UCHAR Addr[6]; - ULONG Timeout; - HEADER_802_11 AuthHdr; - BOOLEAN TimerCancelled; - NDIS_STATUS NStatus; - PUCHAR pOutBuffer = NULL; - ULONG FrameLen = 0, tmp = 0; - - // Block all authentication request durning WPA block period - if (pAd->StaCfg.bBlockAssoc == TRUE) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s - Block Auth request durning WPA block period!\n", pSMName)); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); - } - else if(MlmeAuthReqSanity(pAd, pElem->Msg, pElem->MsgLen, Addr, &Timeout, &Alg)) - { - /* reset timer */ - RTMPCancelTimer(pAuthTimer, &TimerCancelled); - - COPY_MAC_ADDR(pAd->MlmeAux.Bssid, Addr); - pAd->MlmeAux.Alg = Alg; - Seq = SeqNo; - Status = MLME_SUCCESS; - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if(NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s - MlmeAuthReqAction(Alg:%d) allocate memory failed\n", pSMName, Alg)); - pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; - Status = MLME_FAIL_NO_RESOURCE; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); - return FALSE; - } - - DBGPRINT(RT_DEBUG_TRACE, ("%s - Send AUTH request seq#1 (Alg=%d)...\n", pSMName, Alg)); - MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, pAd->MlmeAux.Bssid); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11),&AuthHdr, - 2, &Alg, - 2, &Seq, - 2, &Status, - END_OF_ARGS); - - if (pNewElement && ElementLen) - { - MakeOutgoingFrame(pOutBuffer+FrameLen, &tmp, - ElementLen, pNewElement, - END_OF_ARGS); - FrameLen += tmp; - } - - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - RTMPSetTimer(pAuthTimer, Timeout); - return TRUE; - } - else - { - DBGPRINT_ERR(("%s - MlmeAuthReqAction() sanity check failed\n", pSMName)); - return FALSE; - } - - return TRUE; -} diff --git a/drivers/staging/rt3090/sta/auth_rsp.c b/drivers/staging/rt3090/sta/auth_rsp.c deleted file mode 100644 index 207bfeada1e489e8b96b33364dcb39edbe4f81d3..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/sta/auth_rsp.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - auth_rsp.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - John 2004-10-1 copy from RT2560 -*/ - -#include "../rt_config.h" - - -/* - ========================================================================== - Description: - authentication state machine init procedure - Parameters: - Sm - the state machine - - IRQL = PASSIVE_LEVEL - - ========================================================================== - */ -VOID AuthRspStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN PSTATE_MACHINE Sm, - IN STATE_MACHINE_FUNC Trans[]) -{ - StateMachineInit(Sm, Trans, MAX_AUTH_RSP_STATE, MAX_AUTH_RSP_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_RSP_IDLE, AUTH_RSP_MACHINE_BASE); - - // column 1 - StateMachineSetAction(Sm, AUTH_RSP_IDLE, MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)PeerDeauthAction); - - // column 2 - StateMachineSetAction(Sm, AUTH_RSP_WAIT_CHAL, MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)PeerDeauthAction); - -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID PeerAuthSimpleRspGenAndSend( - IN PRTMP_ADAPTER pAd, - IN PHEADER_802_11 pHdr80211, - IN USHORT Alg, - IN USHORT Seq, - IN USHORT Reason, - IN USHORT Status) -{ - HEADER_802_11 AuthHdr; - ULONG FrameLen = 0; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - - if (Reason != MLME_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("Peer AUTH fail...\n")); - return; - } - - //Get an unused nonpaged memory - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); - if (NStatus != NDIS_STATUS_SUCCESS) - return; - - DBGPRINT(RT_DEBUG_TRACE, ("Send AUTH response (seq#2)...\n")); - MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, pHdr80211->Addr2, pAd->MlmeAux.Bssid); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &AuthHdr, - 2, &Alg, - 2, &Seq, - 2, &Reason, - END_OF_ARGS); - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID PeerDeauthAction( - IN PRTMP_ADAPTER pAd, - IN PMLME_QUEUE_ELEM Elem) -{ - UCHAR Addr2[MAC_ADDR_LEN]; - USHORT Reason; - - if (PeerDeauthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) - { - if (INFRA_ON(pAd) - && MAC_ADDR_EQUAL(Addr2, pAd->CommonCfg.Bssid) - ) - { - DBGPRINT(RT_DEBUG_TRACE,("AUTH_RSP - receive DE-AUTH from our AP (Reason=%d)\n", Reason)); - - -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT - RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, 0); -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - - - // send wireless event - for deauthentication - if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - - LinkDown(pAd, TRUE); - } - } - else - { - DBGPRINT(RT_DEBUG_TRACE,("AUTH_RSP - PeerDeauthAction() sanity check fail\n")); - } -} diff --git a/drivers/staging/rt3090/sta/connect.c b/drivers/staging/rt3090/sta/connect.c deleted file mode 100644 index 4aa35ee3ade127165ada56c10bcfd4ccb9dacff3..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/sta/connect.c +++ /dev/null @@ -1,2759 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - connect.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - John 2004-08-08 Major modification from RT2560 -*/ - -#include "../rt_config.h" - - -UCHAR CipherSuiteWpaNoneTkip[] = { - 0x00, 0x50, 0xf2, 0x01, // oui - 0x01, 0x00, // Version - 0x00, 0x50, 0xf2, 0x02, // Multicast - 0x01, 0x00, // Number of unicast - 0x00, 0x50, 0xf2, 0x02, // unicast - 0x01, 0x00, // number of authentication method - 0x00, 0x50, 0xf2, 0x00 // authentication - }; -UCHAR CipherSuiteWpaNoneTkipLen = (sizeof(CipherSuiteWpaNoneTkip) / sizeof(UCHAR)); - -UCHAR CipherSuiteWpaNoneAes[] = { - 0x00, 0x50, 0xf2, 0x01, // oui - 0x01, 0x00, // Version - 0x00, 0x50, 0xf2, 0x04, // Multicast - 0x01, 0x00, // Number of unicast - 0x00, 0x50, 0xf2, 0x04, // unicast - 0x01, 0x00, // number of authentication method - 0x00, 0x50, 0xf2, 0x00 // authentication - }; -UCHAR CipherSuiteWpaNoneAesLen = (sizeof(CipherSuiteWpaNoneAes) / sizeof(UCHAR)); - -// The following MACRO is called after 1. starting an new IBSS, 2. succesfully JOIN an IBSS, -// or 3. succesfully ASSOCIATE to a BSS, 4. successfully RE_ASSOCIATE to a BSS -// All settings successfuly negotiated furing MLME state machines become final settings -// and are copied to pAd->StaActive -#define COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \ -{ \ - NdisZeroMemory((_pAd)->CommonCfg.Ssid, MAX_LEN_OF_SSID); \ - (_pAd)->CommonCfg.SsidLen = (_pAd)->MlmeAux.SsidLen; \ - NdisMoveMemory((_pAd)->CommonCfg.Ssid, (_pAd)->MlmeAux.Ssid, (_pAd)->MlmeAux.SsidLen); \ - COPY_MAC_ADDR((_pAd)->CommonCfg.Bssid, (_pAd)->MlmeAux.Bssid); \ - (_pAd)->CommonCfg.Channel = (_pAd)->MlmeAux.Channel; \ - (_pAd)->CommonCfg.CentralChannel = (_pAd)->MlmeAux.CentralChannel; \ - (_pAd)->StaActive.Aid = (_pAd)->MlmeAux.Aid; \ - (_pAd)->StaActive.AtimWin = (_pAd)->MlmeAux.AtimWin; \ - (_pAd)->StaActive.CapabilityInfo = (_pAd)->MlmeAux.CapabilityInfo; \ - (_pAd)->CommonCfg.BeaconPeriod = (_pAd)->MlmeAux.BeaconPeriod; \ - (_pAd)->StaActive.CfpMaxDuration = (_pAd)->MlmeAux.CfpMaxDuration; \ - (_pAd)->StaActive.CfpPeriod = (_pAd)->MlmeAux.CfpPeriod; \ - (_pAd)->StaActive.SupRateLen = (_pAd)->MlmeAux.SupRateLen; \ - NdisMoveMemory((_pAd)->StaActive.SupRate, (_pAd)->MlmeAux.SupRate, (_pAd)->MlmeAux.SupRateLen);\ - (_pAd)->StaActive.ExtRateLen = (_pAd)->MlmeAux.ExtRateLen; \ - NdisMoveMemory((_pAd)->StaActive.ExtRate, (_pAd)->MlmeAux.ExtRate, (_pAd)->MlmeAux.ExtRateLen);\ - NdisMoveMemory(&(_pAd)->CommonCfg.APEdcaParm, &(_pAd)->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));\ - NdisMoveMemory(&(_pAd)->CommonCfg.APQosCapability, &(_pAd)->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));\ - NdisMoveMemory(&(_pAd)->CommonCfg.APQbssLoad, &(_pAd)->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));\ - COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].Addr, (_pAd)->MlmeAux.Bssid); \ - (_pAd)->MacTab.Content[BSSID_WCID].Aid = (_pAd)->MlmeAux.Aid; \ - (_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = (_pAd)->StaCfg.PairCipher;\ - COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.BssId, (_pAd)->MlmeAux.Bssid);\ - (_pAd)->MacTab.Content[BSSID_WCID].RateLen = (_pAd)->StaActive.SupRateLen + (_pAd)->StaActive.ExtRateLen;\ -} - -/* - ========================================================================== - Description: - - IRQL = PASSIVE_LEVEL - - ========================================================================== -*/ -VOID MlmeCntlInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - OUT STATE_MACHINE_FUNC Trans[]) -{ - // Control state machine differs from other state machines, the interface - // follows the standard interface - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID MlmeCntlMachinePerformAction( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *S, - IN MLME_QUEUE_ELEM *Elem) -{ - switch(pAd->Mlme.CntlMachine.CurrState) - { - case CNTL_IDLE: - CntlIdleProc(pAd, Elem); - break; - case CNTL_WAIT_DISASSOC: - CntlWaitDisassocProc(pAd, Elem); - break; - case CNTL_WAIT_JOIN: - CntlWaitJoinProc(pAd, Elem); - break; - - // CNTL_WAIT_REASSOC is the only state in CNTL machine that does - // not triggered directly or indirectly by "RTMPSetInformation(OID_xxx)". - // Therefore not protected by NDIS's "only one outstanding OID request" - // rule. Which means NDIS may SET OID in the middle of ROAMing attempts. - // Current approach is to block new SET request at RTMPSetInformation() - // when CntlMachine.CurrState is not CNTL_IDLE - case CNTL_WAIT_REASSOC: - CntlWaitReassocProc(pAd, Elem); - break; - - case CNTL_WAIT_START: - CntlWaitStartProc(pAd, Elem); - break; - case CNTL_WAIT_AUTH: - CntlWaitAuthProc(pAd, Elem); - break; - case CNTL_WAIT_AUTH2: - CntlWaitAuthProc2(pAd, Elem); - break; - case CNTL_WAIT_ASSOC: - CntlWaitAssocProc(pAd, Elem); - break; - - case CNTL_WAIT_OID_LIST_SCAN: - if(Elem->MsgType == MT2_SCAN_CONF) - { - // Resume TxRing after SCANING complete. We hope the out-of-service time - // won't be too long to let upper layer time-out the waiting frames - RTMPResumeMsduTransmission(pAd); - - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - - // - // Set LED status to previous status. - // - if (pAd->bLedOnScanning) - { - pAd->bLedOnScanning = FALSE; - RTMPSetLED(pAd, pAd->LedStatus); - } -#ifdef DOT11N_DRAFT3 - // AP sent a 2040Coexistence mgmt frame, then station perform a scan, and then send back the respone. - if (pAd->CommonCfg.BSSCoexist2040.field.InfoReq == 1) - { - Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE); - } -#endif // DOT11N_DRAFT3 // - } - break; - - case CNTL_WAIT_OID_DISASSOC: - if (Elem->MsgType == MT2_DISASSOC_CONF) - { - LinkDown(pAd, FALSE); - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - } - break; - default: - DBGPRINT_ERR(("!ERROR! CNTL - Illegal message type(=%ld)", Elem->MsgType)); - break; - } -} - - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID CntlIdleProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - MLME_DISASSOC_REQ_STRUCT DisassocReq; - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) - return; - - switch(Elem->MsgType) - { - case OID_802_11_SSID: - CntlOidSsidProc(pAd, Elem); - break; - - case OID_802_11_BSSID: - CntlOidRTBssidProc(pAd,Elem); - break; - - case OID_802_11_BSSID_LIST_SCAN: - CntlOidScanProc(pAd,Elem); - break; - - case OID_802_11_DISASSOCIATE: - DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; -#ifdef WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_ENABLE_WITH_WEB_UI) -#endif // WPA_SUPPLICANT_SUPPORT // - { - // Set the AutoReconnectSsid to prevent it reconnect to old SSID - // Since calling this indicate user don't want to connect to that SSID anymore. - pAd->MlmeAux.AutoReconnectSsidLen= 32; - NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); - } - break; - - case MT2_MLME_ROAMING_REQ: - CntlMlmeRoamingProc(pAd, Elem); - break; - - case OID_802_11_MIC_FAILURE_REPORT_FRAME: - WpaMicFailureReportFrame(pAd, Elem); - break; - -#ifdef QOS_DLS_SUPPORT - case RT_OID_802_11_SET_DLS_PARAM: - CntlOidDLSSetupProc(pAd, Elem); - break; -#endif // QOS_DLS_SUPPORT // - - default: - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Illegal message in CntlIdleProc(MsgType=%ld)\n",Elem->MsgType)); - break; - } -} - -VOID CntlOidScanProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - MLME_SCAN_REQ_STRUCT ScanReq; - ULONG BssIdx = BSS_NOT_FOUND; - BSS_ENTRY CurrBss; - -#ifdef RALINK_ATE -/* Disable scanning when ATE is running. */ - if (ATE_ON(pAd)) - return; -#endif // RALINK_ATE // - - - // record current BSS if network is connected. - // 2003-2-13 do not include current IBSS if this is the only STA in this IBSS. - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - BssIdx = BssSsidTableSearch(&pAd->ScanTab, pAd->CommonCfg.Bssid, (PUCHAR)pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->CommonCfg.Channel); - if (BssIdx != BSS_NOT_FOUND) - { - NdisMoveMemory(&CurrBss, &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY)); - } - } - - // clean up previous SCAN result, add current BSS back to table if any - BssTableInit(&pAd->ScanTab); - if (BssIdx != BSS_NOT_FOUND) - { - // DDK Note: If the NIC is associated with a particular BSSID and SSID - // that are not contained in the list of BSSIDs generated by this scan, the - // BSSID description of the currently associated BSSID and SSID should be - // appended to the list of BSSIDs in the NIC's database. - // To ensure this, we append this BSS as the first entry in SCAN result - NdisMoveMemory(&pAd->ScanTab.BssEntry[0], &CurrBss, sizeof(BSS_ENTRY)); - pAd->ScanTab.BssNr = 1; - } - - ScanParmFill(pAd, &ScanReq, (PSTRING) Elem->Msg, Elem->MsgLen, BSS_ANY, SCAN_ACTIVE); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, - sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; -} - -/* - ========================================================================== - Description: - Before calling this routine, user desired SSID should already been - recorded in CommonCfg.Ssid[] - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID CntlOidSsidProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM * Elem) -{ - PNDIS_802_11_SSID pOidSsid = (NDIS_802_11_SSID *)Elem->Msg; - MLME_DISASSOC_REQ_STRUCT DisassocReq; - ULONG Now; - - - // Step 1. record the desired user settings to MlmeAux - NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); - NdisMoveMemory(pAd->MlmeAux.Ssid, pOidSsid->Ssid, pOidSsid->SsidLength); - pAd->MlmeAux.SsidLen = (UCHAR)pOidSsid->SsidLength; - NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN); - pAd->MlmeAux.BssType = pAd->StaCfg.BssType; - - pAd->StaCfg.bAutoConnectByBssid = FALSE; - - // - // Update Reconnect Ssid, that user desired to connect. - // - NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); - NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); - pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen; - - // step 2. find all matching BSS in the lastest SCAN result (inBssTab) - // & log them into MlmeAux.SsidBssTab for later-on iteration. Sort by RSSI order - BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, (PCHAR)pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); - - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - %d BSS of %d BSS match the desire (%d)SSID - %s\n", - pAd->MlmeAux.SsidBssTab.BssNr, pAd->ScanTab.BssNr, pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid)); - NdisGetSystemUpTime(&Now); - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && - (pAd->CommonCfg.SsidLen == pAd->MlmeAux.SsidBssTab.BssEntry[0].SsidLen) && - NdisEqualMemory(pAd->CommonCfg.Ssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Ssid, pAd->CommonCfg.SsidLen) && - MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Bssid)) - { - // Case 1. already connected with an AP who has the desired SSID - // with highest RSSI - - // Add checking Mode "LEAP" for CCX 1.0 - if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) - ) && - (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) - { - // case 1.1 For WPA, WPA-PSK, if the 1x port is not secured, we have to redo - // connection process - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP...\n")); - DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, - sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; - } - else if (pAd->bConfigChanged == TRUE) - { - // case 1.2 Important Config has changed, we have to reconnect to the same AP - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP Because config changed...\n")); - DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, - sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; - } - else - { - // case 1.3. already connected to the SSID with highest RSSI. - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - already with this BSSID. ignore this SET_SSID request\n")); - // - // (HCT 12.1) 1c_wlan_mediaevents required - // media connect events are indicated when associating with the same AP - // - if (INFRA_ON(pAd)) - { - // - // Since MediaState already is NdisMediaStateConnected - // We just indicate the connect event again to meet the WHQL required. - // - pAd->IndicateMediaState = NdisMediaStateConnected; - RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_UP; // Update extra information to link is up - } - - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT - RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, &pAd->MlmeAux.Bssid[0], NULL, 0); -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - } - } - else if (INFRA_ON(pAd)) - { - // - // For RT61 - // [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: ) - // RT61 may lost SSID, and not connect to NDTEST_WEP_AP2 and will connect to NDTEST_WEP_AP2 by Autoreconnect - // But media status is connected, so the SSID not report correctly. - // - if (!SSID_EQUAL(pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen)) - { - // - // Different SSID means not Roaming case, so we let LinkDown() to Indicate a disconnect event. - // - pAd->MlmeAux.CurrReqIsFromNdis = TRUE; - } - // case 2. active INFRA association existent - // roaming is done within miniport driver, nothing to do with configuration - // utility. so upon a new SET(OID_802_11_SSID) is received, we just - // disassociate with the current associated AP, - // then perform a new association with this new SSID, no matter the - // new/old SSID are the same or not. - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP...\n")); - DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, - sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; - } - else - { - if (ADHOC_ON(pAd)) - { - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - drop current ADHOC\n")); - LinkDown(pAd, FALSE); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); - pAd->IndicateMediaState = NdisMediaStateDisconnected; - RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_DOWN; - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():NDIS_STATUS_MEDIA_DISCONNECT Event C!\n")); - } - - if ((pAd->MlmeAux.SsidBssTab.BssNr == 0) && - (pAd->StaCfg.bAutoReconnect == TRUE) && - (pAd->MlmeAux.BssType == BSS_INFRA) && - (MlmeValidateSSID(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen) == TRUE) - ) - { - MLME_SCAN_REQ_STRUCT ScanReq; - - DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - No matching BSS, start a new scan\n")); - ScanParmFill(pAd, &ScanReq, (PSTRING) pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; - // Reset Missed scan number - pAd->StaCfg.LastScanTime = Now; - } - else - { - - pAd->MlmeAux.BssIdx = 0; - IterateOnBssTab(pAd); - } - } -} - - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID CntlOidRTBssidProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM * Elem) -{ - ULONG BssIdx; - PUCHAR pOidBssid = (PUCHAR)Elem->Msg; - MLME_DISASSOC_REQ_STRUCT DisassocReq; - MLME_JOIN_REQ_STRUCT JoinReq; - -#ifdef RALINK_ATE -/* No need to perform this routine when ATE is running. */ - if (ATE_ON(pAd)) - return; -#endif // RALINK_ATE // - - // record user desired settings - COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pOidBssid); - pAd->MlmeAux.BssType = pAd->StaCfg.BssType; - - // find the desired BSS in the latest SCAN result table - BssIdx = BssTableSearch(&pAd->ScanTab, pOidBssid, pAd->MlmeAux.Channel); - if (BssIdx == BSS_NOT_FOUND) - { - MLME_SCAN_REQ_STRUCT ScanReq; - - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - BSSID not found. reply NDIS_STATUS_NOT_ACCEPTED\n")); - //pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - BSSID not found. start a new scan\n")); - ScanParmFill(pAd, &ScanReq, (PSTRING) pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; - // Reset Missed scan number - NdisGetSystemUpTime(&pAd->StaCfg.LastScanTime); - return; - } - - // - // Update Reconnect Ssid, that user desired to connect. - // - NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); - pAd->MlmeAux.AutoReconnectSsidLen = pAd->ScanTab.BssEntry[BssIdx].SsidLen; - NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->ScanTab.BssEntry[BssIdx].Ssid, pAd->ScanTab.BssEntry[BssIdx].SsidLen); - - // copy the matched BSS entry from ScanTab to MlmeAux.SsidBssTab. Why? - // Because we need this entry to become the JOIN target in later on SYNC state machine - pAd->MlmeAux.BssIdx = 0; - pAd->MlmeAux.SsidBssTab.BssNr = 1; - NdisMoveMemory(&pAd->MlmeAux.SsidBssTab.BssEntry[0], &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY)); - - // Add SSID into MlmeAux for site surey joining hidden SSID - pAd->MlmeAux.SsidLen = pAd->ScanTab.BssEntry[BssIdx].SsidLen; - NdisMoveMemory(pAd->MlmeAux.Ssid, pAd->ScanTab.BssEntry[BssIdx].Ssid, pAd->MlmeAux.SsidLen); - - { - if (INFRA_ON(pAd)) - { - // disassoc from current AP first - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - disassociate with current AP ...\n")); - DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, - sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); - - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; - } - else - { - if (ADHOC_ON(pAd)) - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - drop current ADHOC\n")); - LinkDown(pAd, FALSE); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); - pAd->IndicateMediaState = NdisMediaStateDisconnected; - RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_DOWN; - DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event C!\n")); - } - - // Change the wepstatus to original wepstatus - pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus; - pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus; - pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus; - - // Check cipher suite, AP must have more secured cipher than station setting - // Set the Pairwise and Group cipher to match the intended AP setting - // We can only connect to AP with less secured cipher setting - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) - { - pAd->StaCfg.GroupCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.GroupCipher; - - if (pAd->StaCfg.WepStatus == pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipher) - pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipher; - else if (pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipherAux != Ndis802_11WEPDisabled) - pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipherAux; - else // There is no PairCipher Aux, downgrade our capability to TKIP - pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; - } - else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - pAd->StaCfg.GroupCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.GroupCipher; - - if (pAd->StaCfg.WepStatus == pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipher) - pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipher; - else if (pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipherAux != Ndis802_11WEPDisabled) - pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipherAux; - else // There is no PairCipher Aux, downgrade our capability to TKIP - pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; - - // RSN capability - pAd->StaCfg.RsnCapability = pAd->ScanTab.BssEntry[BssIdx].WPA2.RsnCapability; - } - - // Set Mix cipher flag - pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE; - /*if (pAd->StaCfg.bMixCipher == TRUE) - { - // If mix cipher, re-build RSNIE - RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0); - }*/ - // No active association, join the BSS immediately - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - joining %02x:%02x:%02x:%02x:%02x:%02x ...\n", - pOidBssid[0],pOidBssid[1],pOidBssid[2],pOidBssid[3],pOidBssid[4],pOidBssid[5])); - - JoinParmFill(pAd, &JoinReq, pAd->MlmeAux.BssIdx); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT), &JoinReq); - - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN; - } - } -} - -// Roaming is the only external request triggering CNTL state machine -// despite of other "SET OID" operation. All "SET OID" related oerations -// happen in sequence, because no other SET OID will be sent to this device -// until the the previous SET operation is complete (successful o failed). -// So, how do we quarantee this ROAMING request won't corrupt other "SET OID"? -// or been corrupted by other "SET OID"? -// -// IRQL = DISPATCH_LEVEL -VOID CntlMlmeRoamingProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR BBPValue = 0; - - DBGPRINT(RT_DEBUG_TRACE,("CNTL - Roaming in MlmeAux.RoamTab...\n")); - - { - //Let BBP register at 20MHz to do (fast) roaming. - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue &= (~0x18); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - - NdisMoveMemory(&pAd->MlmeAux.SsidBssTab, &pAd->MlmeAux.RoamTab, sizeof(pAd->MlmeAux.RoamTab)); - pAd->MlmeAux.SsidBssTab.BssNr = pAd->MlmeAux.RoamTab.BssNr; - - BssTableSortByRssi(&pAd->MlmeAux.SsidBssTab); - pAd->MlmeAux.BssIdx = 0; - IterateOnBssTab(pAd); - } -} - -#ifdef QOS_DLS_SUPPORT -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID CntlOidDLSSetupProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - PRT_802_11_DLS pDLS = (PRT_802_11_DLS)Elem->Msg; - MLME_DLS_REQ_STRUCT MlmeDlsReq; - INT i; - USHORT reason = REASON_UNSPECIFY; - - DBGPRINT(RT_DEBUG_TRACE,("CNTL - (OID set %02x:%02x:%02x:%02x:%02x:%02x with Valid=%d, Status=%d, TimeOut=%d, CountDownTimer=%d)\n", - pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5], - pDLS->Valid, pDLS->Status, pDLS->TimeOut, pDLS->CountDownTimer)); - - if (!pAd->CommonCfg.bDLSCapable) - return; - - // DLS will not be supported when Adhoc mode - if (INFRA_ON(pAd)) - { - for (i = 0; i < MAX_NUM_OF_DLS_ENTRY; i++) - { - if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && - (pDLS->TimeOut == pAd->StaCfg.DLSEntry[i].TimeOut) && MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - // 1. Same setting, just drop it - DBGPRINT(RT_DEBUG_TRACE,("CNTL - setting unchanged\n")); - break; - } - else if (!pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && - MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - // 2. Disable DLS link case, just tear down DLS link - reason = REASON_QOS_UNWANTED_MECHANISM; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); - MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); - DBGPRINT(RT_DEBUG_TRACE,("CNTL - start tear down procedure\n")); - break; - } - else if ((i < MAX_NUM_OF_DLS_ENTRY) && pDLS->Valid && !pAd->StaCfg.DLSEntry[i].Valid) - { - // 3. Enable case, start DLS setup procedure - NdisMoveMemory(&pAd->StaCfg.DLSEntry[i], pDLS, sizeof(RT_802_11_DLS_UI)); - - //Update countdown timer - pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut; - DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); - MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); - DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS setup case\n")); - break; - } - else if ((i < MAX_NUM_OF_DLS_ENTRY) && pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && - (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && !MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - // 4. update mac case, tear down old DLS and setup new DLS - reason = REASON_QOS_UNWANTED_MECHANISM; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); - MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); - NdisMoveMemory(&pAd->StaCfg.DLSEntry[i], pDLS, sizeof(RT_802_11_DLS_UI)); - DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); - MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); - DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS tear down and restart case\n")); - break; - } - else if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && - MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr) && (pAd->StaCfg.DLSEntry[i].TimeOut != pDLS->TimeOut)) - { - // 5. update timeout case, start DLS setup procedure (no tear down) - pAd->StaCfg.DLSEntry[i].TimeOut = pDLS->TimeOut; - //Update countdown timer - pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut; - DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); - MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); - DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS update timeout case\n")); - break; - } - else if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && - (pAd->StaCfg.DLSEntry[i].Status != DLS_FINISH) && MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - // 6. re-setup case, start DLS setup procedure (no tear down) - DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); - MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); - DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS retry setup procedure\n")); - break; - } - else - { - DBGPRINT(RT_DEBUG_WARN,("CNTL - DLS not changed in entry - %d - Valid=%d, Status=%d, TimeOut=%d\n", - i, pAd->StaCfg.DLSEntry[i].Valid, pAd->StaCfg.DLSEntry[i].Status, pAd->StaCfg.DLSEntry[i].TimeOut)); - } - } - } -} -#endif // QOS_DLS_SUPPORT // - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID CntlWaitDisassocProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - MLME_START_REQ_STRUCT StartReq; - - if (Elem->MsgType == MT2_DISASSOC_CONF) - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Dis-associate successful\n")); - - if (pAd->CommonCfg.bWirelessEvent) - { - RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - } - - LinkDown(pAd, FALSE); - - // case 1. no matching BSS, and user wants ADHOC, so we just start a new one - if ((pAd->MlmeAux.SsidBssTab.BssNr==0) && (pAd->StaCfg.BssType == BSS_ADHOC)) - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - No matching BSS, start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid)); - StartParmFill(pAd, &StartReq, (PCHAR)pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; - } - // case 2. try each matched BSS - else - { - pAd->MlmeAux.BssIdx = 0; - - IterateOnBssTab(pAd); - } - } -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID CntlWaitJoinProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Reason; - MLME_AUTH_REQ_STRUCT AuthReq; - - if (Elem->MsgType == MT2_JOIN_CONF) - { - NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); - if (Reason == MLME_SUCCESS) - { - // 1. joined an IBSS, we are pretty much done here - if (pAd->MlmeAux.BssType == BSS_ADHOC) - { - // - // 5G bands rules of Japan: - // Ad hoc must be disabled in W53(ch52,56,60,64) channels. - // - if ( (pAd->CommonCfg.bIEEE80211H == 1) && - RadarChannelCheck(pAd, pAd->CommonCfg.Channel) - ) - { - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Channel=%d, Join adhoc on W53(52,56,60,64) Channels are not accepted\n", pAd->CommonCfg.Channel)); - return; - } - - LinkUp(pAd, BSS_ADHOC); - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - join the IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n", - pAd->CommonCfg.Bssid[0],pAd->CommonCfg.Bssid[1],pAd->CommonCfg.Bssid[2], - pAd->CommonCfg.Bssid[3],pAd->CommonCfg.Bssid[4],pAd->CommonCfg.Bssid[5])); - - pAd->IndicateMediaState = NdisMediaStateConnected; - pAd->ExtraInfo = GENERAL_LINK_UP; - } - // 2. joined a new INFRA network, start from authentication - else - { - { - // either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch)) - { - AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, AUTH_MODE_KEY); - } - else - { - AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, AUTH_MODE_OPEN); - } - MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ, - sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq); - } - - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH; - } - } - else - { - // 3. failed, try next BSS - pAd->MlmeAux.BssIdx++; - IterateOnBssTab(pAd); - } - } -} - - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID CntlWaitStartProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Result; - - if (Elem->MsgType == MT2_START_CONF) - { - NdisMoveMemory(&Result, Elem->Msg, sizeof(USHORT)); - if (Result == MLME_SUCCESS) - { - // - // 5G bands rules of Japan: - // Ad hoc must be disabled in W53(ch52,56,60,64) channels. - // - if ( (pAd->CommonCfg.bIEEE80211H == 1) && - RadarChannelCheck(pAd, pAd->CommonCfg.Channel) - ) - { - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Channel=%d, Start adhoc on W53(52,56,60,64) Channels are not accepted\n", pAd->CommonCfg.Channel)); - return; - } -#ifdef DOT11_N_SUPPORT - NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], 16); - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) - { - N_ChannelCheck(pAd); - SetCommonHT(pAd); - NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, &pAd->CommonCfg.AddHTInfo, sizeof(ADD_HT_INFO_IE)); - RTMPCheckHt(pAd, BSSID_WCID, &pAd->CommonCfg.HtCapability, &pAd->CommonCfg.AddHTInfo); - pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE; - NdisMoveMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], &pAd->CommonCfg.HtCapability.MCSSet[0], 16); - COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); - - if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && - (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE)) - { - pAd->MlmeAux.CentralChannel = pAd->CommonCfg.Channel + 2; - } - else if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && - (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW)) - { - pAd->MlmeAux.CentralChannel = pAd->CommonCfg.Channel - 2; - } - } - else -#endif // DOT11_N_SUPPORT // - { - pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; - } - LinkUp(pAd, BSS_ADHOC); - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - // Before send beacon, driver need do radar detection - if ((pAd->CommonCfg.Channel > 14 ) - && (pAd->CommonCfg.bIEEE80211H == 1) - && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) - { - pAd->CommonCfg.RadarDetect.RDMode = RD_SILENCE_MODE; - pAd->CommonCfg.RadarDetect.RDCount = 0; -#ifdef DFS_SUPPORT - BbpRadarDetectionStart(pAd); -#endif // DFS_SUPPORT // - } - - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - start a new IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n", - pAd->CommonCfg.Bssid[0],pAd->CommonCfg.Bssid[1],pAd->CommonCfg.Bssid[2], - pAd->CommonCfg.Bssid[3],pAd->CommonCfg.Bssid[4],pAd->CommonCfg.Bssid[5])); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Start IBSS fail. BUG!!!!!\n")); - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - } - } -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID CntlWaitAuthProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Reason; - MLME_ASSOC_REQ_STRUCT AssocReq; - MLME_AUTH_REQ_STRUCT AuthReq; - - if (Elem->MsgType == MT2_AUTH_CONF) - { - NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); - if (Reason == MLME_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n")); - AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, pAd->MlmeAux.CapabilityInfo, - ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount); - - { - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_ASSOC_REQ, - sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq); - - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC; - } - } - else - { - // This fail may because of the AP already keep us in its MAC table without - // ageing-out. The previous authentication attempt must have let it remove us. - // so try Authentication again may help. For D-Link DWL-900AP+ compatibility. - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, try again...\n")); - { - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch)) - { - // either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first - AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, AUTH_MODE_KEY); - } - else - { - AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, AUTH_MODE_OPEN); - } - MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ, - sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq); - - } - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2; - } - } -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID CntlWaitAuthProc2( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Reason; - MLME_ASSOC_REQ_STRUCT AssocReq; - MLME_AUTH_REQ_STRUCT AuthReq; - - if (Elem->MsgType == MT2_AUTH_CONF) - { - NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); - if (Reason == MLME_SUCCESS) - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n")); - AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, pAd->MlmeAux.CapabilityInfo, - ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount); - { - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_ASSOC_REQ, - sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq); - - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC; - } - } - else - { - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch) && - (pAd->MlmeAux.Alg == Ndis802_11AuthModeShared)) - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, try OPEN system...\n")); - AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen); - MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ, - sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq); - - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2; - } - else - { - // not success, try next BSS - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, give up; try next BSS\n")); - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; //??????? - pAd->MlmeAux.BssIdx++; - IterateOnBssTab(pAd); - } - } - } -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID CntlWaitAssocProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Reason; - - if (Elem->MsgType == MT2_ASSOC_CONF) - { - NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); - if (Reason == MLME_SUCCESS) - { - if (pAd->CommonCfg.bWirelessEvent) - { - RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - } - - LinkUp(pAd, BSS_INFRA); - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Association successful on BSS #%ld\n",pAd->MlmeAux.BssIdx)); - } - else - { - // not success, try next BSS - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Association fails on BSS #%ld\n",pAd->MlmeAux.BssIdx)); - pAd->MlmeAux.BssIdx++; - IterateOnBssTab(pAd); - } - } -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID CntlWaitReassocProc( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Result; - - if (Elem->MsgType == MT2_REASSOC_CONF) - { - NdisMoveMemory(&Result, Elem->Msg, sizeof(USHORT)); - if (Result == MLME_SUCCESS) - { - // send wireless event - for association - if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - - // - // NDIS requires a new Link UP indication but no Link Down for RE-ASSOC - // - LinkUp(pAd, BSS_INFRA); - - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Re-assocition successful on BSS #%ld\n", pAd->MlmeAux.RoamIdx)); - } - else - { - // reassoc failed, try to pick next BSS in the BSS Table - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Re-assocition fails on BSS #%ld\n", pAd->MlmeAux.RoamIdx)); - { - pAd->MlmeAux.RoamIdx++; - IterateOnBssTab2(pAd); - } - } - } -} - - -VOID AdhocTurnOnQos( - IN PRTMP_ADAPTER pAd) -{ -#define AC0_DEF_TXOP 0 -#define AC1_DEF_TXOP 0 -#define AC2_DEF_TXOP 94 -#define AC3_DEF_TXOP 47 - - // Turn on QOs if use HT rate. - if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) - { - pAd->CommonCfg.APEdcaParm.bValid = TRUE; - pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; - pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; - pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; - pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; - - pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; - pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; - pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; - pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; - - pAd->CommonCfg.APEdcaParm.Cwmax[0] = 10; - pAd->CommonCfg.APEdcaParm.Cwmax[1] = 6; - pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; - pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; - - pAd->CommonCfg.APEdcaParm.Txop[0] = 0; - pAd->CommonCfg.APEdcaParm.Txop[1] = 0; - pAd->CommonCfg.APEdcaParm.Txop[2] = AC2_DEF_TXOP; - pAd->CommonCfg.APEdcaParm.Txop[3] = AC3_DEF_TXOP; - } - AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID LinkUp( - IN PRTMP_ADAPTER pAd, - IN UCHAR BssType) -{ - ULONG Now; - UINT32 Data; - BOOLEAN Cancelled; - UCHAR Value = 0, idx = 0, HashIdx = 0; - MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry = NULL; - - // Init ChannelQuality to prevent DEAD_CQI at initial LinkUp - pAd->Mlme.ChannelQuality = 50; - - pEntry = MacTableLookup(pAd, pAd->CommonCfg.Bssid); - if (pEntry) - { - MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); - pEntry = NULL; - } - - - pEntry = &pAd->MacTab.Content[BSSID_WCID]; - - // - // ASSOC - DisassocTimeoutAction - // CNTL - Dis-associate successful - // !!! LINK DOWN !!! - // [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: ) - // - // To prevent DisassocTimeoutAction to call Link down after we link up, - // cancel the DisassocTimer no matter what it start or not. - // - RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); - - COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); - -#ifdef DOT11_N_SUPPORT - COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); -#endif // DOT11_N_SUPPORT // - -#ifdef RTMP_MAC_PCI - // Before power save before link up function, We will force use 1R. - // So after link up, check Rx antenna # again. - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); - if(pAd->Antenna.field.RxPath == 3) - { - Value |= (0x10); - } - else if(pAd->Antenna.field.RxPath == 2) - { - Value |= (0x8); - } - else if(pAd->Antenna.field.RxPath == 1) - { - Value |= (0x0); - } - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); - pAd->StaCfg.BBPR3 = Value; -#endif // RTMP_MAC_PCI // - - if (BssType == BSS_ADHOC) - { - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_ADHOC_ON); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); - -#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier - // No carrier detection when adhoc - // CarrierDetectionStop(pAd); - pAd->CommonCfg.CarrierDetect.CD_State = CD_NORMAL; -#endif // CARRIER_DETECTION_SUPPORT // - -#ifdef DOT11_N_SUPPORT - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) - AdhocTurnOnQos(pAd); -#endif // DOT11_N_SUPPORT // - - DBGPRINT(RT_DEBUG_TRACE, ("!!!Adhoc LINK UP !!! \n" )); - } - else - { - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_INFRA_ON); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); - - DBGPRINT(RT_DEBUG_TRACE, ("!!!Infra LINK UP !!! \n" )); - } - - // 3*3 - // reset Tx beamforming bit - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); - Value &= (~0x01); - Value |= pAd->CommonCfg.RegTransmitSetting.field.TxBF; - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); - -#ifdef DOT11_N_SUPPORT - // Change to AP channel - if ((pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. - pAd->CommonCfg.BBPCurrentBW = BW_40; - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); - Value &= (~0x18); - Value |= 0x10; - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); - - // RX : control channel at lower - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); - Value &= (~0x20); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); -#ifdef RTMP_MAC_PCI - pAd->StaCfg.BBPR3 = Value; -#endif // RTMP_MAC_PCI // - - RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); - Data &= 0xfffffffe; - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); - - if (pAd->MACVersion == 0x28600100) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); - DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); - } - - DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel )); - } - else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. - pAd->CommonCfg.BBPCurrentBW = BW_40; - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); - Value &= (~0x18); - Value |= 0x10; - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); - - RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); - Data |= 0x1; - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); - - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); - Value |= (0x20); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); -#ifdef RTMP_MAC_PCI - pAd->StaCfg.BBPR3 = Value; -#endif // RTMP_MAC_PCI // - - if (pAd->MACVersion == 0x28600100) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); - DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); - } - - DBGPRINT(RT_DEBUG_TRACE, ("!!! 40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel )); - } - else -#endif // DOT11_N_SUPPORT // - { - pAd->CommonCfg.BBPCurrentBW = BW_20; - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); - Value &= (~0x18); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); - - RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); - Data &= 0xfffffffe; - RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); - - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); - Value &= (~0x20); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); -#ifdef RTMP_MAC_PCI - pAd->StaCfg.BBPR3 = Value; -#endif // RTMP_MAC_PCI // - - if (pAd->MACVersion == 0x28600100) - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11); - DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); - } - - DBGPRINT(RT_DEBUG_TRACE, ("!!! 20MHz LINK UP !!! \n" )); - } - - RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); - // - // Save BBP_R66 value, it will be used in RTUSBResumeMsduTransmission - // - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue); - - DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (BssType=%d, AID=%d, ssid=%s, Channel=%d, CentralChannel = %d)\n", - BssType, pAd->StaActive.Aid, pAd->CommonCfg.Ssid, pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); - -#ifdef DOT11_N_SUPPORT - DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (Density =%d, )\n", pAd->MacTab.Content[BSSID_WCID].MpduDensity)); -#endif // DOT11_N_SUPPORT // - - AsicSetBssid(pAd, pAd->CommonCfg.Bssid); - - AsicSetSlotTime(pAd, TRUE); - AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); - - - // Call this for RTS protectionfor legacy rate, we will always enable RTS threshold, but normally it will not hit - AsicUpdateProtect(pAd, 0, (OFDMSETPROTECT | CCKSETPROTECT), TRUE, FALSE); - -#ifdef DOT11_N_SUPPORT - if ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE)) - { - // Update HT protectionfor based on AP's operating mode. - if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1) - { - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE); - } - else - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); - } -#endif // DOT11_N_SUPPORT // - - NdisZeroMemory(&pAd->DrsCounters, sizeof(COUNTER_DRS)); - - NdisGetSystemUpTime(&Now); - pAd->StaCfg.LastBeaconRxTime = Now; // last RX timestamp - - if ((pAd->CommonCfg.TxPreamble != Rt802_11PreambleLong) && - CAP_IS_SHORT_PREAMBLE_ON(pAd->StaActive.CapabilityInfo)) - { - MlmeSetTxPreamble(pAd, Rt802_11PreambleShort); - } - - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); - - if (pAd->CommonCfg.RadarDetect.RDMode == RD_SILENCE_MODE) - { -#ifdef DFS_SUPPORT - RadarDetectionStop(pAd); -#endif // DFS_SUPPORT // - } - pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE; - - if (BssType == BSS_ADHOC) - { - MakeIbssBeacon(pAd); - if ((pAd->CommonCfg.Channel > 14) - && (pAd->CommonCfg.bIEEE80211H == 1) - && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) - { - ; //Do nothing - } - else - { - AsicEnableIbssSync(pAd); - } - - // In ad hoc mode, use MAC table from index 1. - // p.s ASIC use all 0xff as termination of WCID table search.To prevent it's 0xff-ff-ff-ff-ff-ff, Write 0 here. - RTMP_IO_WRITE32(pAd, MAC_WCID_BASE, 0x00); - RTMP_IO_WRITE32(pAd, 0x1808, 0x00); - - // If WEP is enabled, add key material and cipherAlg into Asic - // Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000) - - if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) - { - PUCHAR Key; - UCHAR CipherAlg; - - for (idx=0; idx < SHARE_KEY_NUM; idx++) - { - CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg; - Key = pAd->SharedKey[BSS0][idx].Key; - - if (pAd->SharedKey[BSS0][idx].KeyLen > 0) - { - // Set key material and cipherAlg to Asic - AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL); - - if (idx == pAd->StaCfg.DefaultKeyId) - { - // Update WCID attribute table and IVEIV table for this group key table - RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL); - } - } - - - } - } - // If WPANone is enabled, add key material and cipherAlg into Asic - // Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000) - else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - { - pAd->StaCfg.DefaultKeyId = 0; // always be zero - - NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); - pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pAd->StaCfg.PMK, LEN_TKIP_EK); - - if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) - { - NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_RXMICK); - NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_TXMICK); - } - - // Decide its ChiperAlg - if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; - else - { - DBGPRINT(RT_DEBUG_TRACE, ("Unknow Cipher (=%d), set Cipher to AES\n", pAd->StaCfg.PairCipher)); - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; - } - - // Set key material and cipherAlg to Asic - AsicAddSharedKeyEntry(pAd, - BSS0, - 0, - pAd->SharedKey[BSS0][0].CipherAlg, - pAd->SharedKey[BSS0][0].Key, - pAd->SharedKey[BSS0][0].TxMic, - pAd->SharedKey[BSS0][0].RxMic); - - // Update WCID attribute table and IVEIV table for this group key table - RTMPAddWcidAttributeEntry(pAd, BSS0, 0, pAd->SharedKey[BSS0][0].CipherAlg, NULL); - - } - - } - else // BSS_INFRA - { - // Check the new SSID with last SSID - while (Cancelled == TRUE) - { - if (pAd->CommonCfg.LastSsidLen == pAd->CommonCfg.SsidLen) - { - if (RTMPCompareMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen) == 0) - { - // Link to the old one no linkdown is required. - break; - } - } - // Send link down event before set to link up - pAd->IndicateMediaState = NdisMediaStateDisconnected; - RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_DOWN; - DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event AA!\n")); - break; - } - - // - // On WPA mode, Remove All Keys if not connect to the last BSSID - // Key will be set after 4-way handshake. - // - if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - { - ULONG IV; - - // Remove all WPA keys - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); - RTMPWPARemoveAllKeys(pAd); - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; - - // Fixed connection failed with Range Maximizer - 515 AP (Marvell Chip) when security is WPAPSK/TKIP - // If IV related values are too large in GroupMsg2, AP would ignore this message. - IV = 1; - IV |= (pAd->StaCfg.DefaultKeyId << 30); - AsicUpdateWCIDIVEIV(pAd, BSSID_WCID, IV, 0); - //RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); - } - - // NOTE: - // the decision of using "short slot time" or not may change dynamically due to - // new STA association to the AP. so we have to decide that upon parsing BEACON, not here - - // NOTE: - // the decision to use "RTC/CTS" or "CTS-to-self" protection or not may change dynamically - // due to new STA association to the AP. so we have to decide that upon parsing BEACON, not here - - ComposePsPoll(pAd); - ComposeNullFrame(pAd); - - AsicEnableBssSync(pAd); - - // Add BSSID to WCID search table - AsicUpdateRxWCIDTable(pAd, BSSID_WCID, pAd->CommonCfg.Bssid); - - // If WEP is enabled, add paiewise and shared key -#ifdef WPA_SUPPLICANT_SUPPORT - if (((pAd->StaCfg.WpaSupplicantUP)&& - (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)&& - (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED)) || - ((pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)&& - (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled))) -#else - if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) -#endif // WPA_SUPPLICANT_SUPPORT // - { - PUCHAR Key; - UCHAR CipherAlg; - - for (idx=0; idx < SHARE_KEY_NUM; idx++) - { - CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg; - Key = pAd->SharedKey[BSS0][idx].Key; - - if (pAd->SharedKey[BSS0][idx].KeyLen > 0) - { - // Set key material and cipherAlg to Asic - AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL); - - if (idx == pAd->StaCfg.DefaultKeyId) - { - // Assign group key info - RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL); - - pEntry->Aid = BSSID_WCID; - // Assign pairwise key info - RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry); - } - } - } - } - - // only INFRASTRUCTURE mode need to indicate connectivity immediately; ADHOC mode - // should wait until at least 2 active nodes in this BSSID. - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); - - // For GUI ++ - if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) - { - pAd->IndicateMediaState = NdisMediaStateConnected; - pAd->ExtraInfo = GENERAL_LINK_UP; - RTMP_IndicateMediaState(pAd); - } - else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { -#ifdef WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) -#endif // WPA_SUPPLICANT_SUPPORT // - RTMPSetTimer(&pAd->Mlme.LinkDownTimer, LINK_DOWN_TIMEOUT); - } - // -- - - // Add BSSID in my MAC Table. - NdisAcquireSpinLock(&pAd->MacTabLock); - // add this MAC entry into HASH table - if (pEntry) - { - HashIdx = MAC_ADDR_HASH_INDEX(pAd->CommonCfg.Bssid); - if (pAd->MacTab.Hash[HashIdx] == NULL) - { - pAd->MacTab.Hash[HashIdx] = pEntry; - } - else - { - pCurrEntry = pAd->MacTab.Hash[HashIdx]; - while (pCurrEntry->pNext != NULL) - { - pCurrEntry = pCurrEntry->pNext; - } - pCurrEntry->pNext = pEntry; - } - } - RTMPMoveMemory(pEntry->Addr, pAd->CommonCfg.Bssid, MAC_ADDR_LEN); - pEntry->Aid = BSSID_WCID; - pEntry->pAd = pAd; - pEntry->ValidAsCLI = TRUE; //Although this is bssid..still set ValidAsCl - pAd->MacTab.Size = 1; // infra mode always set MACtab size =1. - pEntry->Sst = SST_ASSOC; - pEntry->AuthState = SST_ASSOC; - pEntry->AuthMode = pAd->StaCfg.AuthMode; - pEntry->WepStatus = pAd->StaCfg.WepStatus; - if (pEntry->AuthMode < Ndis802_11AuthModeWPA) - { - pEntry->WpaState = AS_NOTUSE; - pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; - } - else - { - pEntry->WpaState = AS_PTKSTART; - pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; - } - NdisReleaseSpinLock(&pAd->MacTabLock); - - DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! ClientStatusFlags=%lx)\n", - pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); - - - MlmeUpdateTxRates(pAd, TRUE, BSS0); -#ifdef DOT11_N_SUPPORT - MlmeUpdateHtTxRates(pAd, BSS0); - DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !! (StaActive.bHtEnable =%d, )\n", pAd->StaActive.SupportedPhyInfo.bHtEnable)); -#endif // DOT11_N_SUPPORT // - - - if (pAd->CommonCfg.bAggregationCapable) - { - if ((pAd->CommonCfg.bPiggyBackCapable) && (pAd->MlmeAux.APRalinkIe & 0x00000003) == 3) - { - - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED); - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); - RTMPSetPiggyBack(pAd, TRUE); - DBGPRINT(RT_DEBUG_TRACE, ("Turn on Piggy-Back\n")); - } - else if (pAd->MlmeAux.APRalinkIe & 0x00000001) - { - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); - } - } - - if (pAd->MlmeAux.APRalinkIe != 0x0) - { -#ifdef DOT11_N_SUPPORT - if (CLIENT_STATUS_TEST_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RDG_CAPABLE)) - { - AsicEnableRDG(pAd); - } -#endif // DOT11_N_SUPPORT // - OPSTATUS_SET_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET); - CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RALINK_CHIPSET); - } - else - { - OPSTATUS_CLEAR_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET); - CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RALINK_CHIPSET); - } - } - - -#ifdef DOT11_N_SUPPORT - DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_CONNECT Event B!.BACapability = %x. ClientStatusFlags = %lx\n", pAd->CommonCfg.BACapability.word, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); -#endif // DOT11_N_SUPPORT // - - // Set LED - RTMPSetLED(pAd, LED_LINK_UP); - - pAd->Mlme.PeriodicRound = 0; - pAd->Mlme.OneSecPeriodicRound = 0; - pAd->bConfigChanged = FALSE; // Reset config flag - pAd->ExtraInfo = GENERAL_LINK_UP; // Update extra information to link is up - - // Set asic auto fall back - { - PUCHAR pTable; - UCHAR TableSize = 0; - - MlmeSelectTxRateTable(pAd, &pAd->MacTab.Content[BSSID_WCID], &pTable, &TableSize, &pAd->CommonCfg.TxRateIndex); - AsicUpdateAutoFallBackTable(pAd, pTable); - } - - NdisAcquireSpinLock(&pAd->MacTabLock); - pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word; - pEntry->MaxHTPhyMode.word = pAd->StaCfg.HTPhyMode.word; - if (pAd->StaCfg.bAutoTxRateSwitch == FALSE) - { - pEntry->bAutoTxRateSwitch = FALSE; -#ifdef DOT11_N_SUPPORT - if (pEntry->HTPhyMode.field.MCS == 32) - pEntry->HTPhyMode.field.ShortGI = GI_800; - - if ((pEntry->HTPhyMode.field.MCS > MCS_7) || (pEntry->HTPhyMode.field.MCS == 32)) - pEntry->HTPhyMode.field.STBC = STBC_NONE; -#endif // DOT11_N_SUPPORT // - // If the legacy mode is set, overwrite the transmit setting of this entry. - if (pEntry->HTPhyMode.field.MODE <= MODE_OFDM) - RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); - } - else - pEntry->bAutoTxRateSwitch = TRUE; - NdisReleaseSpinLock(&pAd->MacTabLock); - - // Let Link Status Page display first initial rate. - pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word); - // Select DAC according to HT or Legacy - if (pAd->StaActive.SupportedPhyInfo.MCSSet[0] != 0x00) - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value); - Value &= (~0x18); - if (pAd->Antenna.field.TxPath == 2) - { - Value |= 0x10; - } - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value); - } - else - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value); - Value &= (~0x18); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value); - } - -#ifdef DOT11_N_SUPPORT - if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) - { - } - else if (pEntry->MaxRAmpduFactor == 0) - { - // If HT AP doesn't support MaxRAmpduFactor = 1, we need to set max PSDU to 0. - // Because our Init value is 1 at MACRegTable. - RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x0fff); - } -#endif // DOT11_N_SUPPORT // - - // Patch for Marvel AP to gain high throughput - // Need to set as following, - // 1. Set txop in register-EDCA_AC0_CFG as 0x60 - // 2. Set EnTXWriteBackDDONE in register-WPDMA_GLO_CFG as zero - // 3. PBF_MAX_PCNT as 0x1F3FBF9F - // 4. kick per two packets when dequeue - // - // Txop can only be modified when RDG is off, WMM is disable and TxBurst is enable - // - // if 1. Legacy AP WMM on, or 2. 11n AP, AMPDU disable. Force turn off burst no matter what bEnableTxBurst is. -#ifdef DOT11_N_SUPPORT - if (!((pAd->CommonCfg.RxStream == 1)&&(pAd->CommonCfg.TxStream == 1)) && - (pAd->StaCfg.bForceTxBurst == FALSE) && - (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) - || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE)))) - { - RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); - Data &= 0xFFFFFF00; - RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); - - RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F); - DBGPRINT(RT_DEBUG_TRACE, ("Txburst 1\n")); - } - else -#endif // DOT11_N_SUPPORT // - if (pAd->CommonCfg.bEnableTxBurst) - { - RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); - Data &= 0xFFFFFF00; - Data |= 0x60; - RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); - pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = TRUE; - - RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3FBF9F); - DBGPRINT(RT_DEBUG_TRACE, ("Txburst 2\n")); - } - else - { - RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); - Data &= 0xFFFFFF00; - RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); - - RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F); - DBGPRINT(RT_DEBUG_TRACE, ("Txburst 3\n")); - } - -#ifdef DOT11_N_SUPPORT - // Re-check to turn on TX burst or not. - if ((pAd->CommonCfg.IOTestParm.bLastAtheros == TRUE) && ((STA_WEP_ON(pAd))||(STA_TKIP_ON(pAd)))) - { - pAd->CommonCfg.IOTestParm.bNextDisableRxBA = TRUE; - if (pAd->CommonCfg.bEnableTxBurst) - { - UINT32 MACValue = 0; - // Force disable TXOP value in this case. The same action in MLMEUpdateProtect too. - // I didn't change PBF_MAX_PCNT setting. - RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &MACValue); - MACValue &= 0xFFFFFF00; - RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, MACValue); - pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE; - } - } - else - { - pAd->CommonCfg.IOTestParm.bNextDisableRxBA = FALSE; - } -#endif // DOT11_N_SUPPORT // - - pAd->CommonCfg.IOTestParm.bLastAtheros = FALSE; - COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid); - DBGPRINT(RT_DEBUG_TRACE, ("!!!pAd->bNextDisableRxBA= %d \n", pAd->CommonCfg.IOTestParm.bNextDisableRxBA)); - // BSSID add in one MAC entry too. Because in Tx, ASIC need to check Cipher and IV/EIV, BAbitmap - // Pther information in MACTab.Content[BSSID_WCID] is not necessary for driver. - // Note: As STA, The MACTab.Content[BSSID_WCID]. PairwiseKey and Shared Key for BSS0 are the same. - - if (pAd->StaCfg.WepStatus <= Ndis802_11WEPDisabled) - { -#ifdef WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.WpaSupplicantUP && - (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) && - (pAd->StaCfg.IEEE8021X == TRUE)) - ; - else -#endif // WPA_SUPPLICANT_SUPPORT // - { - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilterAcceptAll; - } - } - - NdisAcquireSpinLock(&pAd->MacTabLock); - pEntry->PortSecured = pAd->StaCfg.PortSecured; - NdisReleaseSpinLock(&pAd->MacTabLock); - - // - // Patch Atheros AP TX will breakdown issue. - // AP Model: DLink DWL-8200AP - // - if (INFRA_ON(pAd) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && STA_TKIP_ON(pAd)) - { - RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x01); - } - else - { - RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x00); - } - - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); - -#ifdef DOT11_N_SUPPORT -#ifdef DOT11N_DRAFT3 - if ((pAd->CommonCfg.BACapability.field.b2040CoexistScanSup) && (pAd->CommonCfg.Channel <= 11)) - { - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SCAN_2040); - BuildEffectedChannelList(pAd); - } -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // -} - -/* - ========================================================================== - - Routine Description: - Disconnect current BSSID - - Arguments: - pAd - Pointer to our adapter - IsReqFromAP - Request from AP - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - We need more information to know it's this requst from AP. - If yes! we need to do extra handling, for example, remove the WPA key. - Otherwise on 4-way handshaking will faied, since the WPA key didn't be - remove while auto reconnect. - Disconnect request from AP, it means we will start afresh 4-way handshaking - on WPA mode. - - ========================================================================== -*/ -VOID LinkDown( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN IsReqFromAP) -{ - UCHAR i, ByteValue = 0; - - BOOLEAN Cancelled; - - // Do nothing if monitor mode is on - if (MONITOR_ON(pAd)) - return; - -#ifdef RALINK_ATE - // Nothing to do in ATE mode. - if (ATE_ON(pAd)) - return; -#endif // RALINK_ATE // - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); - //Comment the codes, beasue the line 2291 call the same function. - //RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - // Not allow go to sleep within linkdown function. - RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); - - if (pAd->CommonCfg.bWirelessEvent) - { - RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - } - - DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN !!!\n")); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); - -#ifdef RTMP_MAC_PCI - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - { - BOOLEAN Cancelled; - pAd->Mlme.bPsPollTimerRunning = FALSE; - RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - } - - pAd->bPCIclkOff = FALSE; -#endif // RTMP_MAC_PCI // - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) -|| RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND) - || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) - { - AUTO_WAKEUP_STRUC AutoWakeupCfg; - AsicForceWakeup(pAd, TRUE); - AutoWakeupCfg.word = 0; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); - } -#ifdef RTMP_MAC_PCI - pAd->bPCIclkOff = FALSE; -#endif // RTMP_MAC_PCI // - if (ADHOC_ON(pAd)) // Adhoc mode link down - { - DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 1!!!\n")); - - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); - pAd->IndicateMediaState = NdisMediaStateDisconnected; - RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_DOWN; - BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("!!! MacTab.Size=%d !!!\n", pAd->MacTab.Size)); - } - else // Infra structure mode - { - DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 2!!!\n")); - -#ifdef QOS_DLS_SUPPORT - // DLS tear down frame must be sent before link down - // send DLS-TEAR_DOWN message - if (pAd->CommonCfg.bDLSCapable) - { - // tear down local dls table entry - for (i=0; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) - { - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); - } - } - - // tear down peer dls table entry - for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) - { - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); - } - } - } -#endif // QOS_DLS_SUPPORT // - - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); - - // Saved last SSID for linkup comparison - pAd->CommonCfg.LastSsidLen = pAd->CommonCfg.SsidLen; - NdisMoveMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen); - COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid); - if (pAd->MlmeAux.CurrReqIsFromNdis == TRUE) - { - pAd->IndicateMediaState = NdisMediaStateDisconnected; - RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_DOWN; - DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event A!\n")); - pAd->MlmeAux.CurrReqIsFromNdis = FALSE; - } - else - { - // - // If disassociation request is from NDIS, then we don't need to delete BSSID from entry. - // Otherwise lost beacon or receive De-Authentication from AP, - // then we should delete BSSID from BssTable. - // If we don't delete from entry, roaming will fail. - // - BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel); - } - - // restore back to - - // 1. long slot (20 us) or short slot (9 us) time - // 2. turn on/off RTS/CTS and/or CTS-to-self protection - // 3. short preamble - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); - -#ifdef EXT_BUILD_CHANNEL_LIST - // Country IE of the AP will be evaluated and will be used. - if (pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None) - { - NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], &pAd->StaCfg.StaOriCountryCode[0], 2); - pAd->CommonCfg.Geography = pAd->StaCfg.StaOriGeography; - BuildChannelListEx(pAd); - } -#endif // EXT_BUILD_CHANNEL_LIST // - - } - - - for (i=1; iMacTab.Content[i].ValidAsCLI == TRUE) - MacTableDeleteEntry(pAd, pAd->MacTab.Content[i].Aid, pAd->MacTab.Content[i].Addr); - } - - AsicSetSlotTime(pAd, TRUE); //FALSE); - AsicSetEdcaParm(pAd, NULL); - - // Set LED - RTMPSetLED(pAd, LED_LINK_DOWN); - pAd->LedIndicatorStrength = 0xF0; - RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it. - - AsicDisableSync(pAd); - - pAd->Mlme.PeriodicRound = 0; - pAd->Mlme.OneSecPeriodicRound = 0; - - if (pAd->StaCfg.BssType == BSS_INFRA) - { - // Remove StaCfg Information after link down - NdisZeroMemory(pAd->CommonCfg.Bssid, MAC_ADDR_LEN); - NdisZeroMemory(pAd->CommonCfg.Ssid, MAX_LEN_OF_SSID); - pAd->CommonCfg.SsidLen = 0; - } -#ifdef DOT11_N_SUPPORT - NdisZeroMemory(&pAd->MlmeAux.HtCapability, sizeof(HT_CAPABILITY_IE)); - NdisZeroMemory(&pAd->MlmeAux.AddHtInfo, sizeof(ADD_HT_INFO_IE)); - pAd->MlmeAux.HtCapabilityLen = 0; - pAd->MlmeAux.NewExtChannelOffset = 0xff; -#endif // DOT11_N_SUPPORT // - - // Reset WPA-PSK state. Only reset when supplicant enabled - if (pAd->StaCfg.WpaState != SS_NOTUSE) - { - pAd->StaCfg.WpaState = SS_START; - // Clear Replay counter - NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); - -#ifdef QOS_DLS_SUPPORT - if (pAd->CommonCfg.bDLSCapable) - NdisZeroMemory(pAd->StaCfg.DlsReplayCounter, 8); -#endif // QOS_DLS_SUPPORT // - } - - // - // if link down come from AP, we need to remove all WPA keys on WPA mode. - // otherwise will cause 4-way handshaking failed, since the WPA key not empty. - // - if ((IsReqFromAP) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) - { - // Remove all WPA keys - RTMPWPARemoveAllKeys(pAd); - } - - // 802.1x port control -#ifdef WPA_SUPPLICANT_SUPPORT - // Prevent clear PortSecured here with static WEP - // NetworkManger set security policy first then set SSID to connect AP. - if (pAd->StaCfg.WpaSupplicantUP && - (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) && - (pAd->StaCfg.IEEE8021X == FALSE)) - { - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - } - else -#endif // WPA_SUPPLICANT_SUPPORT // - { - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; - } - - NdisAcquireSpinLock(&pAd->MacTabLock); - NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE)); - pAd->MacTab.Content[BSSID_WCID].PortSecured = pAd->StaCfg.PortSecured; - NdisReleaseSpinLock(&pAd->MacTabLock); - - pAd->StaCfg.MicErrCnt = 0; - - pAd->IndicateMediaState = NdisMediaStateDisconnected; - // Update extra information to link is up - pAd->ExtraInfo = GENERAL_LINK_DOWN; - - pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; - - - // Clean association information - NdisZeroMemory(&pAd->StaCfg.AssocInfo, sizeof(NDIS_802_11_ASSOCIATION_INFORMATION)); - pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); - pAd->StaCfg.ReqVarIELen = 0; - pAd->StaCfg.ResVarIELen = 0; - - // - // Reset RSSI value after link down - // - pAd->StaCfg.RssiSample.AvgRssi0 = 0; - pAd->StaCfg.RssiSample.AvgRssi0X8 = 0; - pAd->StaCfg.RssiSample.AvgRssi1 = 0; - pAd->StaCfg.RssiSample.AvgRssi1X8 = 0; - pAd->StaCfg.RssiSample.AvgRssi2 = 0; - pAd->StaCfg.RssiSample.AvgRssi2X8 = 0; - - // Restore MlmeRate - pAd->CommonCfg.MlmeRate = pAd->CommonCfg.BasicMlmeRate; - pAd->CommonCfg.RtsRate = pAd->CommonCfg.BasicMlmeRate; - -#ifdef DOT11_N_SUPPORT - // - // After Link down, reset piggy-back setting in ASIC. Disable RDG. - // - if (pAd->CommonCfg.BBPCurrentBW == BW_40) - { - pAd->CommonCfg.BBPCurrentBW = BW_20; - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &ByteValue); - ByteValue &= (~0x18); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, ByteValue); - } -#endif // DOT11_N_SUPPORT // - // Reset DAC - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &ByteValue); - ByteValue &= (~0x18); - if (pAd->Antenna.field.TxPath == 2) - { - ByteValue |= 0x10; - } - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, ByteValue); - - RTMPSetPiggyBack(pAd,FALSE); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED); - -#ifdef DOT11_N_SUPPORT - pAd->CommonCfg.BACapability.word = pAd->CommonCfg.REGBACapability.word; -#endif // DOT11_N_SUPPORT // - - // Restore all settings in the following. - AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE); - AsicDisableRDG(pAd); - pAd->CommonCfg.IOTestParm.bCurrentAtheros = FALSE; - pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE; - -#ifdef DOT11_N_SUPPORT -#ifdef DOT11N_DRAFT3 - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SCAN_2040); - pAd->CommonCfg.BSSCoexist2040.word = 0; - TriEventInit(pAd); - for (i = 0; i < (pAd->ChannelListNum - 1); i++) - { - pAd->ChannelList[i].bEffectedChannel = FALSE; - } -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // - - RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x1fff); - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); -// Allow go to sleep after linkdown steps. - RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); -#ifdef WPA_SUPPLICANT_SUPPORT -#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.WpaSupplicantUP) { - //send disassociate event to wpa_supplicant - RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, RT_DISASSOC_EVENT_FLAG, NULL, NULL, 0); - } -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // -#endif // WPA_SUPPLICANT_SUPPORT // - -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT - RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, 0); -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - -#ifdef RT30xx - if ((IS_RT30xx(pAd) || IS_RT3090(pAd)||IS_RT3390(pAd)) - &&(pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1)) - { - RTMP_ASIC_MMPS_DISABLE(pAd); - } -#endif // RT30xx // - -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID IterateOnBssTab( - IN PRTMP_ADAPTER pAd) -{ - MLME_START_REQ_STRUCT StartReq; - MLME_JOIN_REQ_STRUCT JoinReq; - ULONG BssIdx; - - // Change the wepstatus to original wepstatus - pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus; - pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus; - pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus; - - BssIdx = pAd->MlmeAux.BssIdx; - if (BssIdx < pAd->MlmeAux.SsidBssTab.BssNr) - { - // Check cipher suite, AP must have more secured cipher than station setting - // Set the Pairwise and Group cipher to match the intended AP setting - // We can only connect to AP with less secured cipher setting - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) - { - pAd->StaCfg.GroupCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.GroupCipher; - - if (pAd->StaCfg.WepStatus == pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipher) - pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipher; - else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipherAux != Ndis802_11WEPDisabled) - pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipherAux; - else // There is no PairCipher Aux, downgrade our capability to TKIP - pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; - } - else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - pAd->StaCfg.GroupCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.GroupCipher; - - if (pAd->StaCfg.WepStatus == pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipher) - pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipher; - else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipherAux != Ndis802_11WEPDisabled) - pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipherAux; - else // There is no PairCipher Aux, downgrade our capability to TKIP - pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; - - // RSN capability - pAd->StaCfg.RsnCapability = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.RsnCapability; - } - - // Set Mix cipher flag - pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE; - /*if (pAd->StaCfg.bMixCipher == TRUE) - { - // If mix cipher, re-build RSNIE - RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0); - }*/ - - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - iterate BSS %ld of %d\n", BssIdx, pAd->MlmeAux.SsidBssTab.BssNr)); - JoinParmFill(pAd, &JoinReq, BssIdx); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT), - &JoinReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN; - } - else if (pAd->StaCfg.BssType == BSS_ADHOC) - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All BSS fail; start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid)); - StartParmFill(pAd, &StartReq, (PCHAR)pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq); - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; - } - else // no more BSS - { - -#ifdef DOT11_N_SUPPORT -#endif // DOT11_N_SUPPORT // - { - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All roaming failed, restore to channel %d, Total BSS[%02d]\n",pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); - } - - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - } -} - -// for re-association only -// IRQL = DISPATCH_LEVEL -VOID IterateOnBssTab2( - IN PRTMP_ADAPTER pAd) -{ - MLME_REASSOC_REQ_STRUCT ReassocReq; - ULONG BssIdx; - BSS_ENTRY *pBss; - - BssIdx = pAd->MlmeAux.RoamIdx; - pBss = &pAd->MlmeAux.RoamTab.BssEntry[BssIdx]; - - if (BssIdx < pAd->MlmeAux.RoamTab.BssNr) - { - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - iterate BSS %ld of %d\n", BssIdx, pAd->MlmeAux.RoamTab.BssNr)); - - AsicSwitchChannel(pAd, pBss->Channel, FALSE); - AsicLockChannel(pAd, pBss->Channel); - - // reassociate message has the same structure as associate message - AssocParmFill(pAd, &ReassocReq, pBss->Bssid, pBss->CapabilityInfo, - ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount); - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_REASSOC_REQ, - sizeof(MLME_REASSOC_REQ_STRUCT), &ReassocReq); - - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC; - } - else // no more BSS - { - -#ifdef DOT11_N_SUPPORT -#endif // DOT11_N_SUPPORT // - { - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All roaming failed, restore to channel %d, Total BSS[%02d]\n",pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); - } - - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; - } -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID JoinParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_JOIN_REQ_STRUCT *JoinReq, - IN ULONG BssIdx) -{ - JoinReq->BssIdx = BssIdx; -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID ScanParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_SCAN_REQ_STRUCT *ScanReq, - IN STRING Ssid[], - IN UCHAR SsidLen, - IN UCHAR BssType, - IN UCHAR ScanType) -{ - NdisZeroMemory(ScanReq->Ssid, MAX_LEN_OF_SSID); - ScanReq->SsidLen = SsidLen; - NdisMoveMemory(ScanReq->Ssid, Ssid, SsidLen); - ScanReq->BssType = BssType; - ScanReq->ScanType = ScanType; -} - -#ifdef QOS_DLS_SUPPORT -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID DlsParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_DLS_REQ_STRUCT *pDlsReq, - IN PRT_802_11_DLS pDls, - IN USHORT reason) -{ - pDlsReq->pDLS = pDls; - pDlsReq->Reason = reason; -} -#endif // QOS_DLS_SUPPORT // - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID StartParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_START_REQ_STRUCT *StartReq, - IN CHAR Ssid[], - IN UCHAR SsidLen) -{ - ASSERT(SsidLen <= MAX_LEN_OF_SSID); - NdisMoveMemory(StartReq->Ssid, Ssid, SsidLen); - StartReq->SsidLen = SsidLen; -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -VOID AuthParmFill( - IN PRTMP_ADAPTER pAd, - IN OUT MLME_AUTH_REQ_STRUCT *AuthReq, - IN PUCHAR pAddr, - IN USHORT Alg) -{ - COPY_MAC_ADDR(AuthReq->Addr, pAddr); - AuthReq->Alg = Alg; - AuthReq->Timeout = AUTH_TIMEOUT; -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -#ifdef RTMP_MAC_PCI -VOID ComposePsPoll( - IN PRTMP_ADAPTER pAd) -{ - NdisZeroMemory(&pAd->PsPollFrame, sizeof(PSPOLL_FRAME)); - pAd->PsPollFrame.FC.Type = BTYPE_CNTL; - pAd->PsPollFrame.FC.SubType = SUBTYPE_PS_POLL; - pAd->PsPollFrame.Aid = pAd->StaActive.Aid | 0xC000; - COPY_MAC_ADDR(pAd->PsPollFrame.Bssid, pAd->CommonCfg.Bssid); - COPY_MAC_ADDR(pAd->PsPollFrame.Ta, pAd->CurrentAddress); -} - -// IRQL = DISPATCH_LEVEL -VOID ComposeNullFrame( - IN PRTMP_ADAPTER pAd) -{ - NdisZeroMemory(&pAd->NullFrame, sizeof(HEADER_802_11)); - pAd->NullFrame.FC.Type = BTYPE_DATA; - pAd->NullFrame.FC.SubType = SUBTYPE_NULL_FUNC; - pAd->NullFrame.FC.ToDs = 1; - COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->CommonCfg.Bssid); - COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->CurrentAddress); - COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->CommonCfg.Bssid); -} -#endif // RTMP_MAC_PCI // - - - - -/* - ========================================================================== - Description: - Pre-build a BEACON frame in the shared memory - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - ========================================================================== -*/ -ULONG MakeIbssBeacon( - IN PRTMP_ADAPTER pAd) -{ - UCHAR DsLen = 1, IbssLen = 2; - UCHAR LocalErpIe[3] = {IE_ERP, 1, 0x04}; - HEADER_802_11 BcnHdr; - USHORT CapabilityInfo; - LARGE_INTEGER FakeTimestamp; - ULONG FrameLen = 0; - PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; - UCHAR *pBeaconFrame = pAd->BeaconBuf; - BOOLEAN Privacy; - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen = 0; - UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR ExtRateLen = 0; - UCHAR RSNIe = IE_WPA; - - if ((pAd->CommonCfg.PhyMode == PHY_11B) && (pAd->CommonCfg.Channel <= 14)) - { - SupRate[0] = 0x82; // 1 mbps - SupRate[1] = 0x84; // 2 mbps - SupRate[2] = 0x8b; // 5.5 mbps - SupRate[3] = 0x96; // 11 mbps - SupRateLen = 4; - ExtRateLen = 0; - } - else if (pAd->CommonCfg.Channel > 14) - { - SupRate[0] = 0x8C; // 6 mbps, in units of 0.5 Mbps, basic rate - SupRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps - SupRate[2] = 0x98; // 12 mbps, in units of 0.5 Mbps, basic rate - SupRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps - SupRate[4] = 0xb0; // 24 mbps, in units of 0.5 Mbps, basic rate - SupRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps - SupRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps - SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps - SupRateLen = 8; - ExtRateLen = 0; - - // - // Also Update MlmeRate & RtsRate for G only & A only - // - pAd->CommonCfg.MlmeRate = RATE_6; - pAd->CommonCfg.RtsRate = RATE_6; - pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; - pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; - pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM; - pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; - } - else - { - SupRate[0] = 0x82; // 1 mbps - SupRate[1] = 0x84; // 2 mbps - SupRate[2] = 0x8b; // 5.5 mbps - SupRate[3] = 0x96; // 11 mbps - SupRateLen = 4; - - ExtRate[0] = 0x0C; // 6 mbps, in units of 0.5 Mbps, - ExtRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps - ExtRate[2] = 0x18; // 12 mbps, in units of 0.5 Mbps, - ExtRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps - ExtRate[4] = 0x30; // 24 mbps, in units of 0.5 Mbps, - ExtRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps - ExtRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps - ExtRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps - ExtRateLen = 8; - } - - pAd->StaActive.SupRateLen = SupRateLen; - NdisMoveMemory(pAd->StaActive.SupRate, SupRate, SupRateLen); - pAd->StaActive.ExtRateLen = ExtRateLen; - NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, ExtRateLen); - - // compose IBSS beacon frame - MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pAd->CommonCfg.Bssid); - Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || - (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || - (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); - CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0); - - MakeOutgoingFrame(pBeaconFrame, &FrameLen, - sizeof(HEADER_802_11), &BcnHdr, - TIMESTAMP_LEN, &FakeTimestamp, - 2, &pAd->CommonCfg.BeaconPeriod, - 2, &CapabilityInfo, - 1, &SsidIe, - 1, &pAd->CommonCfg.SsidLen, - pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, - 1, &SupRateIe, - 1, &SupRateLen, - SupRateLen, SupRate, - 1, &DsIe, - 1, &DsLen, - 1, &pAd->CommonCfg.Channel, - 1, &IbssIe, - 1, &IbssLen, - 2, &pAd->StaActive.AtimWin, - END_OF_ARGS); - - // add ERP_IE and EXT_RAE IE of in 802.11g - if (ExtRateLen) - { - ULONG tmp; - - MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp, - 3, LocalErpIe, - 1, &ExtRateIe, - 1, &ExtRateLen, - ExtRateLen, ExtRate, - END_OF_ARGS); - FrameLen += tmp; - } - - // If adhoc secruity is set for WPA-None, append the cipher suite IE - if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - { - ULONG tmp; - RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0); - - MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp, - 1, &RSNIe, - 1, &pAd->StaCfg.RSNIE_Len, - pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, - END_OF_ARGS); - FrameLen += tmp; - } - -#ifdef DOT11_N_SUPPORT - if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - ULONG TmpLen; - UCHAR HtLen, HtLen1; - -#ifdef RT_BIG_ENDIAN - HT_CAPABILITY_IE HtCapabilityTmp; - ADD_HT_INFO_IE addHTInfoTmp; - USHORT b2lTmp, b2lTmp2; -#endif - - // add HT Capability IE - HtLen = sizeof(pAd->CommonCfg.HtCapability); - HtLen1 = sizeof(pAd->CommonCfg.AddHTInfo); -#ifndef RT_BIG_ENDIAN - MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, - 1, &HtCapIe, - 1, &HtLen, - HtLen, &pAd->CommonCfg.HtCapability, - 1, &AddHtInfoIe, - 1, &HtLen1, - HtLen1, &pAd->CommonCfg.AddHTInfo, - END_OF_ARGS); -#else - NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); - *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); - *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); - - NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, HtLen1); - *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); - *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); - - MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, - 1, &HtCapIe, - 1, &HtLen, - HtLen, &HtCapabilityTmp, - 1, &AddHtInfoIe, - 1, &HtLen1, - HtLen1, &addHTInfoTmp, - END_OF_ARGS); -#endif - FrameLen += TmpLen; - } -#endif // DOT11_N_SUPPORT // - - //beacon use reserved WCID 0xff - if (pAd->CommonCfg.Channel > 14) - { - RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen, - PID_MGMT, PID_BEACON, RATE_1, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit); - } - else - { - // Set to use 1Mbps for Adhoc beacon. - HTTRANSMIT_SETTING Transmit; - Transmit.word = 0; - RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen, - PID_MGMT, PID_BEACON, RATE_1, IFS_HTTXOP, FALSE, &Transmit); - } - -#ifdef RT_BIG_ENDIAN - RTMPFrameEndianChange(pAd, pBeaconFrame, DIR_WRITE, FALSE); - RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); -#endif - - DBGPRINT(RT_DEBUG_TRACE, ("MakeIbssBeacon (len=%ld), SupRateLen=%d, ExtRateLen=%d, Channel=%d, PhyMode=%d\n", - FrameLen, SupRateLen, ExtRateLen, pAd->CommonCfg.Channel, pAd->CommonCfg.PhyMode)); - return FrameLen; -} diff --git a/drivers/staging/rt3090/sta/dls.c b/drivers/staging/rt3090/sta/dls.c deleted file mode 100644 index 306e16fdeeaeef68775e24df9bb60bb22047f38c..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/sta/dls.c +++ /dev/null @@ -1,2207 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - dls.c - - Abstract: - Handle WMM-DLS state machine - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Rory Chen 02-14-2006 - Arvin Tai 06-03-2008 Modified for RT28xx - */ - -#include "../rt_config.h" - - -/* - ========================================================================== - Description: - dls state machine init, including state transition and timer init - Parameters: - Sm - pointer to the dls state machine - Note: - The state machine looks like this - - DLS_IDLE - MT2_MLME_DLS_REQUEST MlmeDlsReqAction - MT2_PEER_DLS_REQUEST PeerDlsReqAction - MT2_PEER_DLS_RESPONSE PeerDlsRspAction - MT2_MLME_DLS_TEARDOWN MlmeTearDownAction - MT2_PEER_DLS_TEARDOWN PeerTearDownAction - - IRQL = PASSIVE_LEVEL - - ========================================================================== - */ -void DlsStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *Sm, - OUT STATE_MACHINE_FUNC Trans[]) -{ - UCHAR i; - - StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, MAX_DLS_STATE, MAX_DLS_MSG, (STATE_MACHINE_FUNC)Drop, DLS_IDLE, DLS_MACHINE_BASE); - - // the first column - StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_REQ, (STATE_MACHINE_FUNC)MlmeDlsReqAction); - StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_REQ, (STATE_MACHINE_FUNC)PeerDlsReqAction); - StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_RSP, (STATE_MACHINE_FUNC)PeerDlsRspAction); - StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)MlmeDlsTearDownAction); - StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)PeerDlsTearDownAction); - - for (i=0; iStaCfg.DLSEntry[i].pAd = pAd; - RTMPInitTimer(pAd, &pAd->StaCfg.DLSEntry[i].Timer, GET_TIMER_FUNCTION(DlsTimeoutAction), pAd, FALSE); - } -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID MlmeDlsReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - HEADER_802_11 DlsReqHdr; - PRT_802_11_DLS pDLS = NULL; - UCHAR Category = CATEGORY_DLS; - UCHAR Action = ACTION_DLS_REQUEST; - ULONG tmp; - USHORT reason; - ULONG Timeout; - BOOLEAN TimerCancelled; - - if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &reason)) - return; - - DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsReqAction() \n")); - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsReqAction() allocate memory failed \n")); - return; - } - - ActHeaderInit(pAd, &DlsReqHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid); - - // Build basic frame first - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &DlsReqHdr, - 1, &Category, - 1, &Action, - 6, &pDLS->MacAddr, - 6, pAd->CurrentAddress, - 2, &pAd->StaActive.CapabilityInfo, - 2, &pDLS->TimeOut, - 1, &SupRateIe, - 1, &pAd->MlmeAux.SupRateLen, - pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, - END_OF_ARGS); - - if (pAd->MlmeAux.ExtRateLen != 0) - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &ExtRateIe, - 1, &pAd->MlmeAux.ExtRateLen, - pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, - END_OF_ARGS); - FrameLen += tmp; - } - -#ifdef DOT11_N_SUPPORT - if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - UCHAR HtLen; - -#ifdef RT_BIG_ENDIAN - HT_CAPABILITY_IE HtCapabilityTmp; -#endif - - // add HT Capability IE - HtLen = sizeof(HT_CAPABILITY_IE); -#ifndef RT_BIG_ENDIAN - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &HtCapIe, - 1, &HtLen, - HtLen, &pAd->CommonCfg.HtCapability, - END_OF_ARGS); -#else - NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); - *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); - *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); - - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &HtCapIe, - 1, &HtLen, - HtLen, &HtCapabilityTmp, - END_OF_ARGS); -#endif - FrameLen = FrameLen + tmp; - } -#endif // DOT11_N_SUPPORT // - - RTMPCancelTimer(&pDLS->Timer, &TimerCancelled); - Timeout = DLS_TIMEOUT; - RTMPSetTimer(&pDLS->Timer, Timeout); - - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID PeerDlsReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - USHORT StatusCode = MLME_SUCCESS; - HEADER_802_11 DlsRspHdr; - UCHAR Category = CATEGORY_DLS; - UCHAR Action = ACTION_DLS_RESPONSE; - ULONG tmp; - USHORT CapabilityInfo; - UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; - USHORT DLSTimeOut; - SHORT i; - ULONG Timeout; - BOOLEAN TimerCancelled; - PRT_802_11_DLS pDLS = NULL; - UCHAR MaxSupportedRateIn500Kbps = 0; - UCHAR SupportedRatesLen; - UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR HtCapabilityLen; - HT_CAPABILITY_IE HtCapability; - - if (!PeerDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &DLSTimeOut, - &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability)) - return; - - // supported rates array may not be sorted. sort it and find the maximum rate - for (i = 0; i < SupportedRatesLen; i++) - { - if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f)) - MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f; - } - - DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() from %02x:%02x:%02x:%02x:%02x:%02x\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() allocate memory failed \n")); - return; - } - - if (!INFRA_ON(pAd)) - { - StatusCode = MLME_REQUEST_DECLINED; - } - else if (!pAd->CommonCfg.bWmmCapable) - { - StatusCode = MLME_DEST_STA_IS_NOT_A_QSTA; - } - else if (!pAd->CommonCfg.bDLSCapable) - { - StatusCode = MLME_REQUEST_DECLINED; - } - else - { - // find table to update parameters - for (i = (MAX_NUM_OF_DLS_ENTRY-1); i >= 0; i--) - { - if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; - else - { - RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); - pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; - } - - pAd->StaCfg.DLSEntry[i].Sequence = 0; - pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut; - pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut; - if (HtCapabilityLen != 0) - pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; - else - pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; - pDLS = &pAd->StaCfg.DLSEntry[i]; - break; - } - } - - // can not find in table, create a new one - if (i < 0) - { - DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() can not find same entry \n")); - for (i=(MAX_NUM_OF_DLS_ENTRY - 1); i >= MAX_NUM_OF_INIT_DLS_ENTRY; i--) - { - if (!pAd->StaCfg.DLSEntry[i].Valid) - { - MAC_TABLE_ENTRY *pEntry; - UCHAR MaxSupportedRate = RATE_11; - - if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - { - pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; - } - else - { - RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); - pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; - } - - pAd->StaCfg.DLSEntry[i].Sequence = 0; - pAd->StaCfg.DLSEntry[i].Valid = TRUE; - pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut; - pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut; - NdisMoveMemory(pAd->StaCfg.DLSEntry[i].MacAddr, SA, MAC_ADDR_LEN); - if (HtCapabilityLen != 0) - pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; - else - pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; - pDLS = &pAd->StaCfg.DLSEntry[i]; - pEntry = MacTableInsertDlsEntry(pAd, SA, i); - - switch (MaxSupportedRateIn500Kbps) - { - case 108: MaxSupportedRate = RATE_54; break; - case 96: MaxSupportedRate = RATE_48; break; - case 72: MaxSupportedRate = RATE_36; break; - case 48: MaxSupportedRate = RATE_24; break; - case 36: MaxSupportedRate = RATE_18; break; - case 24: MaxSupportedRate = RATE_12; break; - case 18: MaxSupportedRate = RATE_9; break; - case 12: MaxSupportedRate = RATE_6; break; - case 22: MaxSupportedRate = RATE_11; break; - case 11: MaxSupportedRate = RATE_5_5; break; - case 4: MaxSupportedRate = RATE_2; break; - case 2: MaxSupportedRate = RATE_1; break; - default: MaxSupportedRate = RATE_11; break; - } - - pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); - - if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) - { - pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; - pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; - pEntry->MinHTPhyMode.field.MODE = MODE_CCK; - pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; - pEntry->HTPhyMode.field.MODE = MODE_CCK; - pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; - } - else - { - pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; - pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; - pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; - pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; - pEntry->HTPhyMode.field.MODE = MODE_OFDM; - pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; - } - - pEntry->MaxHTPhyMode.field.BW = BW_20; - pEntry->MinHTPhyMode.field.BW = BW_20; - -#ifdef DOT11_N_SUPPORT - pEntry->HTCapability.MCSSet[0] = 0; - pEntry->HTCapability.MCSSet[1] = 0; - - // If this Entry supports 802.11n, upgrade to HT rate. - if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - UCHAR j, bitmask; //k,bitmask; - CHAR ii; - - DBGPRINT(RT_DEBUG_TRACE, ("DLS - PeerDlsReqAction() Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n", - SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); - - if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) - { - pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; - } - else - { - pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; - pAd->MacTab.fAnyStationNonGF = TRUE; - pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; - } - - if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) - { - pEntry->MaxHTPhyMode.field.BW= BW_40; - pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40)); - } - else - { - pEntry->MaxHTPhyMode.field.BW = BW_20; - pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20)); - pAd->MacTab.fAnyStation20Only = TRUE; - } - - // find max fixed rate - for (ii=15; ii>=0; ii--) - { - j = ii/8; - bitmask = (1<<(ii-(j*8))); - if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask)) - { - pEntry->MaxHTPhyMode.field.MCS = ii; - break; - } - if (ii==0) - break; - } - - - if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) - { - - DBGPRINT(RT_DEBUG_OFF, ("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n", - pAd->StaCfg.DesiredTransmitSetting.field.MCS)); - if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32) - { - // Fix MCS as HT Duplicated Mode - pEntry->MaxHTPhyMode.field.BW = 1; - pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; - pEntry->MaxHTPhyMode.field.STBC = 0; - pEntry->MaxHTPhyMode.field.ShortGI = 0; - pEntry->MaxHTPhyMode.field.MCS = 32; - } - else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS) - { - // STA supports fixed MCS - pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - } - } - - pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); - pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity; - pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor; - pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs; - pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize; - pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; - - if (HtCapability.HtCapInfo.ShortGIfor20) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); - if (HtCapability.HtCapInfo.ShortGIfor40) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); - if (HtCapability.HtCapInfo.TxSTBC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); - if (HtCapability.HtCapInfo.RxSTBC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); - if (HtCapability.ExtHtCapInfo.PlusHTC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); - if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); - if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); - - NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE)); - } -#endif // DOT11_N_SUPPORT // - - pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; - pEntry->CurrTxRate = pEntry->MaxSupportedRate; - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); - - if (pAd->StaCfg.bAutoTxRateSwitch == TRUE) - { - PUCHAR pTable; - UCHAR TableSize = 0; - - MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex); - pEntry->bAutoTxRateSwitch = TRUE; - } - else - { - pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; - pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - pEntry->bAutoTxRateSwitch = FALSE; - - RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); - } - pEntry->RateLen = SupportedRatesLen; - - break; - } - } - } - StatusCode = MLME_SUCCESS; - - // can not find in table, create a new one - if (i < 0) - { - StatusCode = MLME_QOS_UNSPECIFY; - DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() DLSEntry table full(only can support %d DLS session) \n", MAX_NUM_OF_DLS_ENTRY - MAX_NUM_OF_INIT_DLS_ENTRY)); - } - else - { - DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() use entry(%d) %02x:%02x:%02x:%02x:%02x:%02x\n", - i, SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); - } - } - - ActHeaderInit(pAd, &DlsRspHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid); - - // Build basic frame first - if (StatusCode == MLME_SUCCESS) - { - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &DlsRspHdr, - 1, &Category, - 1, &Action, - 2, &StatusCode, - 6, SA, - 6, pAd->CurrentAddress, - 2, &pAd->StaActive.CapabilityInfo, - 1, &SupRateIe, - 1, &pAd->MlmeAux.SupRateLen, - pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, - END_OF_ARGS); - - if (pAd->MlmeAux.ExtRateLen != 0) - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &ExtRateIe, - 1, &pAd->MlmeAux.ExtRateLen, - pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, - END_OF_ARGS); - FrameLen += tmp; - } - -#ifdef DOT11_N_SUPPORT - if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - UCHAR HtLen; - -#ifdef RT_BIG_ENDIAN - HT_CAPABILITY_IE HtCapabilityTmp; -#endif - - // add HT Capability IE - HtLen = sizeof(HT_CAPABILITY_IE); -#ifndef RT_BIG_ENDIAN - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &HtCapIe, - 1, &HtLen, - HtLen, &pAd->CommonCfg.HtCapability, - END_OF_ARGS); -#else - NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); - *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); - *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); - - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &HtCapIe, - 1, &HtLen, - HtLen, &HtCapabilityTmp, - END_OF_ARGS); -#endif - FrameLen = FrameLen + tmp; - } -#endif // DOT11_N_SUPPORT // - - if (pDLS && (pDLS->Status != DLS_FINISH)) - { - RTMPCancelTimer(&pDLS->Timer, &TimerCancelled); - Timeout = DLS_TIMEOUT; - RTMPSetTimer(&pDLS->Timer, Timeout); - } - } - else - { - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &DlsRspHdr, - 1, &Category, - 1, &Action, - 2, &StatusCode, - 6, SA, - 6, pAd->CurrentAddress, - END_OF_ARGS); - } - - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID PeerDlsRspAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT CapabilityInfo; - UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; - USHORT StatusCode; - SHORT i; - BOOLEAN TimerCancelled; - UCHAR MaxSupportedRateIn500Kbps = 0; - UCHAR SupportedRatesLen; - UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR HtCapabilityLen; - HT_CAPABILITY_IE HtCapability; - - if (!pAd->CommonCfg.bDLSCapable) - return; - - if (!INFRA_ON(pAd)) - return; - - if (!PeerDlsRspSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &StatusCode, - &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability)) - return; - - // supported rates array may not be sorted. sort it and find the maximum rate - for (i=0; iStaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - if (StatusCode == MLME_SUCCESS) - { - MAC_TABLE_ENTRY *pEntry; - UCHAR MaxSupportedRate = RATE_11; - - pEntry = MacTableInsertDlsEntry(pAd, SA, i); - - switch (MaxSupportedRateIn500Kbps) - { - case 108: MaxSupportedRate = RATE_54; break; - case 96: MaxSupportedRate = RATE_48; break; - case 72: MaxSupportedRate = RATE_36; break; - case 48: MaxSupportedRate = RATE_24; break; - case 36: MaxSupportedRate = RATE_18; break; - case 24: MaxSupportedRate = RATE_12; break; - case 18: MaxSupportedRate = RATE_9; break; - case 12: MaxSupportedRate = RATE_6; break; - case 22: MaxSupportedRate = RATE_11; break; - case 11: MaxSupportedRate = RATE_5_5; break; - case 4: MaxSupportedRate = RATE_2; break; - case 2: MaxSupportedRate = RATE_1; break; - default: MaxSupportedRate = RATE_11; break; - } - - pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); - - if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) - { - pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; - pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; - pEntry->MinHTPhyMode.field.MODE = MODE_CCK; - pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; - pEntry->HTPhyMode.field.MODE = MODE_CCK; - pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; - } - else - { - pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; - pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; - pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; - pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; - pEntry->HTPhyMode.field.MODE = MODE_OFDM; - pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; - } - - pEntry->MaxHTPhyMode.field.BW = BW_20; - pEntry->MinHTPhyMode.field.BW = BW_20; - -#ifdef DOT11_N_SUPPORT - pEntry->HTCapability.MCSSet[0] = 0; - pEntry->HTCapability.MCSSet[1] = 0; - - // If this Entry supports 802.11n, upgrade to HT rate. - if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - UCHAR j, bitmask; //k,bitmask; - CHAR ii; - - DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n", - SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); - - if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) - { - pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; - } - else - { - pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; - pAd->MacTab.fAnyStationNonGF = TRUE; - pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; - } - - if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) - { - pEntry->MaxHTPhyMode.field.BW= BW_40; - pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40)); - } - else - { - pEntry->MaxHTPhyMode.field.BW = BW_20; - pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20)); - pAd->MacTab.fAnyStation20Only = TRUE; - } - - // find max fixed rate - for (ii=15; ii>=0; ii--) - { - j = ii/8; - bitmask = (1<<(ii-(j*8))); - if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask)) - { - pEntry->MaxHTPhyMode.field.MCS = ii; - break; - } - if (ii==0) - break; - } - - if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) - { - if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32) - { - // Fix MCS as HT Duplicated Mode - pEntry->MaxHTPhyMode.field.BW = 1; - pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; - pEntry->MaxHTPhyMode.field.STBC = 0; - pEntry->MaxHTPhyMode.field.ShortGI = 0; - pEntry->MaxHTPhyMode.field.MCS = 32; - } - else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS) - { - // STA supports fixed MCS - pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - } - } - - pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); - pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity; - pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor; - pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs; - pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize; - pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; - - if (HtCapability.HtCapInfo.ShortGIfor20) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); - if (HtCapability.HtCapInfo.ShortGIfor40) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); - if (HtCapability.HtCapInfo.TxSTBC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); - if (HtCapability.HtCapInfo.RxSTBC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); - if (HtCapability.ExtHtCapInfo.PlusHTC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); - if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); - if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); - - NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE)); - } -#endif // DOT11_N_SUPPORT // - pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; - pEntry->CurrTxRate = pEntry->MaxSupportedRate; - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); - - if (pAd->StaCfg.bAutoTxRateSwitch == TRUE) - { - PUCHAR pTable; - UCHAR TableSize = 0; - - MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex); - pEntry->bAutoTxRateSwitch = TRUE; - } - else - { - pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; - pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - pEntry->bAutoTxRateSwitch = FALSE; - - RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); - } - pEntry->RateLen = SupportedRatesLen; - - if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - { - // If support WPA or WPA2, start STAKey hand shake, - // If failed hand shake, just tear down peer DLS - if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS) - { - MLME_DLS_REQ_STRUCT MlmeDlsReq; - USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT; - - DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); - MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n")); - } - else - { - pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; - DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n")); - } - } - else - { - RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); - pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; - DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); - } - - //initialize seq no for DLS frames. - pAd->StaCfg.DLSEntry[i].Sequence = 0; - if (HtCapabilityLen != 0) - pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; - else - pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; - } - else - { - // DLS setup procedure failed. - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); - DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode)); - } - } - } - - if (i >= MAX_NUM_OF_INIT_DLS_ENTRY) - { - DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() update timeout value \n")); - for (i=(MAX_NUM_OF_DLS_ENTRY-1); i>=MAX_NUM_OF_INIT_DLS_ENTRY; i--) - { - if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - if (StatusCode == MLME_SUCCESS) - { - MAC_TABLE_ENTRY *pEntry; - UCHAR MaxSupportedRate = RATE_11; - - pEntry = MacTableInsertDlsEntry(pAd, SA, i); - - switch (MaxSupportedRateIn500Kbps) - { - case 108: MaxSupportedRate = RATE_54; break; - case 96: MaxSupportedRate = RATE_48; break; - case 72: MaxSupportedRate = RATE_36; break; - case 48: MaxSupportedRate = RATE_24; break; - case 36: MaxSupportedRate = RATE_18; break; - case 24: MaxSupportedRate = RATE_12; break; - case 18: MaxSupportedRate = RATE_9; break; - case 12: MaxSupportedRate = RATE_6; break; - case 22: MaxSupportedRate = RATE_11; break; - case 11: MaxSupportedRate = RATE_5_5; break; - case 4: MaxSupportedRate = RATE_2; break; - case 2: MaxSupportedRate = RATE_1; break; - default: MaxSupportedRate = RATE_11; break; - } - - pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); - - if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) - { - pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; - pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; - pEntry->MinHTPhyMode.field.MODE = MODE_CCK; - pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; - pEntry->HTPhyMode.field.MODE = MODE_CCK; - pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; - } - else - { - pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; - pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; - pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; - pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; - pEntry->HTPhyMode.field.MODE = MODE_OFDM; - pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; - } - - pEntry->MaxHTPhyMode.field.BW = BW_20; - pEntry->MinHTPhyMode.field.BW = BW_20; - -#ifdef DOT11_N_SUPPORT - pEntry->HTCapability.MCSSet[0] = 0; - pEntry->HTCapability.MCSSet[1] = 0; - - // If this Entry supports 802.11n, upgrade to HT rate. - if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) - { - UCHAR j, bitmask; //k,bitmask; - CHAR ii; - - DBGPRINT(RT_DEBUG_TRACE, ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n", - SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); - - if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) - { - pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; - } - else - { - pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; - pAd->MacTab.fAnyStationNonGF = TRUE; - pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; - } - - if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) - { - pEntry->MaxHTPhyMode.field.BW= BW_40; - pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40)); - } - else - { - pEntry->MaxHTPhyMode.field.BW = BW_20; - pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20)); - pAd->MacTab.fAnyStation20Only = TRUE; - } - - // find max fixed rate - for (ii=15; ii>=0; ii--) - { - j = ii/8; - bitmask = (1<<(ii-(j*8))); - if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask)) - { - pEntry->MaxHTPhyMode.field.MCS = ii; - break; - } - if (ii==0) - break; - } - - if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) - { - DBGPRINT(RT_DEBUG_OFF, ("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n", - pAd->StaCfg.DesiredTransmitSetting.field.MCS)); - if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32) - { - // Fix MCS as HT Duplicated Mode - pEntry->MaxHTPhyMode.field.BW = 1; - pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; - pEntry->MaxHTPhyMode.field.STBC = 0; - pEntry->MaxHTPhyMode.field.ShortGI = 0; - pEntry->MaxHTPhyMode.field.MCS = 32; - } - else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS) - { - // STA supports fixed MCS - pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - } - } - - pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); - pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity; - pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor; - pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs; - pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize; - pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; - - if (HtCapability.HtCapInfo.ShortGIfor20) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); - if (HtCapability.HtCapInfo.ShortGIfor40) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); - if (HtCapability.HtCapInfo.TxSTBC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); - if (HtCapability.HtCapInfo.RxSTBC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); - if (HtCapability.ExtHtCapInfo.PlusHTC) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); - if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); - if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03) - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); - - NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE)); - } -#endif // DOT11_N_SUPPORT // - - pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; - pEntry->CurrTxRate = pEntry->MaxSupportedRate; - CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); - - if (pAd->StaCfg.bAutoTxRateSwitch == TRUE) - { - PUCHAR pTable; - UCHAR TableSize = 0; - - MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex); - pEntry->bAutoTxRateSwitch = TRUE; - } - else - { - pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; - pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; - pEntry->bAutoTxRateSwitch = FALSE; - - RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); - } - pEntry->RateLen = SupportedRatesLen; - - if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - { - // If support WPA or WPA2, start STAKey hand shake, - // If failed hand shake, just tear down peer DLS - if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS) - { - MLME_DLS_REQ_STRUCT MlmeDlsReq; - USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT; - - DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); - MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n")); - } - else - { - pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; - DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n")); - } - } - else - { - RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); - pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; - DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); - } - pAd->StaCfg.DLSEntry[i].Sequence = 0; - if (HtCapabilityLen != 0) - pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; - else - pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; - } - else - { - // DLS setup procedure failed. - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); - DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode)); - } - } - } - } -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID MlmeDlsTearDownAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - UCHAR Category = CATEGORY_DLS; - UCHAR Action = ACTION_DLS_TEARDOWN; - USHORT ReasonCode = REASON_QOS_UNSPECIFY; - HEADER_802_11 DlsTearDownHdr; - PRT_802_11_DLS pDLS; - BOOLEAN TimerCancelled; - UCHAR i; - - if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &ReasonCode)) - return; - - DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsTearDownAction() with ReasonCode=%d \n", ReasonCode)); - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsTearDownAction() allocate memory failed \n")); - return; - } - - ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid); - - // Build basic frame first - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &DlsTearDownHdr, - 1, &Category, - 1, &Action, - 6, &pDLS->MacAddr, - 6, pAd->CurrentAddress, - 2, &ReasonCode, - END_OF_ARGS); - - MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - RTMPCancelTimer(&pDLS->Timer, &TimerCancelled); - - // Remove key in local dls table entry - for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) - { - if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); - } - } - - // clear peer dls table entry - for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; i++) - { - if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); - MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); - } - } -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID PeerDlsTearDownAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; - USHORT ReasonCode; - UINT i; - BOOLEAN TimerCancelled; - - if (!pAd->CommonCfg.bDLSCapable) - return; - - if (!INFRA_ON(pAd)) - return; - - if (!PeerDlsTearDownSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &ReasonCode)) - return; - - DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsTearDownAction() from %02x:%02x:%02x:%02x:%02x:%02x with ReasonCode=%d\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], ReasonCode)); - - // clear local dls table entry - for (i=0; iStaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); - //AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); - //AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); - MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); - } - } - - // clear peer dls table entry - for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); - //AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); - //AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); - MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); - } - } -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID RTMPCheckDLSTimeOut( - IN PRTMP_ADAPTER pAd) -{ - ULONG i; - MLME_DLS_REQ_STRUCT MlmeDlsReq; - USHORT reason = REASON_QOS_UNSPECIFY; - - if (! pAd->CommonCfg.bDLSCapable) - return; - - if (! INFRA_ON(pAd)) - return; - - // If timeout value is equaled to zero, it means always not be timeout. - - // update local dls table entry - for (i=0; iStaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) - && (pAd->StaCfg.DLSEntry[i].TimeOut != 0)) - { - pAd->StaCfg.DLSEntry[i].CountDownTimer --; - - if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0) - { - reason = REASON_QOS_REQUEST_TIMEOUT; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); - MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); - } - } - } - - // update peer dls table entry - for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) - && (pAd->StaCfg.DLSEntry[i].TimeOut != 0)) - { - pAd->StaCfg.DLSEntry[i].CountDownTimer --; - - if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0) - { - reason = REASON_QOS_REQUEST_TIMEOUT; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); - MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); - } - } - } -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -BOOLEAN RTMPRcvFrameDLSCheck( - IN PRTMP_ADAPTER pAd, - IN PHEADER_802_11 pHeader, - IN ULONG Len, - IN PRT28XX_RXD_STRUC pRxD) -{ - ULONG i; - BOOLEAN bFindEntry = FALSE; - BOOLEAN bSTAKeyFrame = FALSE; - PEAPOL_PACKET pEap; - PUCHAR pProto, pAddr = NULL; - PUCHAR pSTAKey = NULL; - UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY]; - UCHAR Mic[16], OldMic[16]; - UCHAR digest[80]; - UCHAR DlsPTK[80]; - UCHAR temp[64]; - BOOLEAN TimerCancelled; - CIPHER_KEY PairwiseKey; - - - if (! pAd->CommonCfg.bDLSCapable) - return bSTAKeyFrame; - - if (! INFRA_ON(pAd)) - return bSTAKeyFrame; - - if (Len < LENGTH_802_11 + 6 + 2) /* LENGTH_802_11 + LLC + EAPOL protocol type */ - return bSTAKeyFrame; - - pProto = (PUCHAR)pHeader + LENGTH_802_11; - - if ((pHeader->FC.SubType & 0x08)) - pProto += 2; /* QOS Control field */ - - /* Skip 4-bytes for HTC */ - if (pHeader->FC.Order && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))) - { - pProto += 4; - } - - /* L2PAD bit on will pad 2 bytes at LLC */ - if (pRxD->L2PAD) - { - pProto += 2; - } - - pProto += 6; /* 0xAA 0xAA 0xAA 0x00 0x00 0x00 */ - - if ((!(pHeader->FC.SubType & 0x08)) && (!RTMPEqualMemory(EAPOL, pProto, 2))) - return bSTAKeyFrame; - - pAddr = pHeader->Addr2; - - if (RTMPEqualMemory(EAPOL, pProto, 2) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) - { - pEap = (PEAPOL_PACKET) (pProto + 2); - - DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff Len=%ld, DataLen=%d, KeyMic=%d, Install=%d, KeyAck=%d, Secure=%d, EKD_DL=%d, Error=%d, Request=%d\n", Len, - (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16), - pEap->KeyDesc.KeyInfo.KeyMic, - pEap->KeyDesc.KeyInfo.Install, - pEap->KeyDesc.KeyInfo.KeyAck, - pEap->KeyDesc.KeyInfo.Secure, - pEap->KeyDesc.KeyInfo.EKD_DL, - pEap->KeyDesc.KeyInfo.Error, - pEap->KeyDesc.KeyInfo.Request)); - - if ((Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16)) && pEap->KeyDesc.KeyInfo.KeyMic - && pEap->KeyDesc.KeyInfo.Install && pEap->KeyDesc.KeyInfo.KeyAck && pEap->KeyDesc.KeyInfo.Secure - && pEap->KeyDesc.KeyInfo.EKD_DL && !pEap->KeyDesc.KeyInfo.Error && !pEap->KeyDesc.KeyInfo.Request) - { - // First validate replay counter, only accept message with larger replay counter - // Let equal pass, some AP start with all zero replay counter - NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); - if ((RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) && - (RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0)) - return bSTAKeyFrame; - - //RTMPMoveMemory(pAd->StaCfg.ReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter (%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n", - pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2], - pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4], pAd->StaCfg.ReplayCounter[5], - pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1])); - - // put these code segment to get the replay counter - if (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) - return bSTAKeyFrame; - - // Check MIC value - // Save the MIC and replace with zero - // use proprietary PTK - NdisZeroMemory(temp, 64); - NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); - WpaDerivePTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK); - - NdisMoveMemory(OldMic, pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); - NdisZeroMemory(pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); - if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - // AES - HMAC_SHA1(DlsPTK, LEN_EAP_MICK, (PUCHAR) pEap, pEap->Body_Len[1] + 4, digest, SHA1_DIGEST_SIZE); - NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); - } - else - { - HMAC_MD5(DlsPTK, LEN_EAP_MICK, (PUCHAR) pEap, pEap->Body_Len[1] + 4, Mic, MD5_DIGEST_SIZE); - } - - if (!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC)) - { - DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in Msg1 of STAKey handshake! \n")); - return bSTAKeyFrame; - } - else - DBGPRINT(RT_DEBUG_TRACE, ("MIC VALID in Msg1 of STAKey handshake! \n")); - if ((pEap->KeyDesc.KeyData[0] == 0xDD) && (pEap->KeyDesc.KeyData[2] == 0x00) && (pEap->KeyDesc.KeyData[3] == 0x0C) - && (pEap->KeyDesc.KeyData[4] == 0x43) && (pEap->KeyDesc.KeyData[5] == 0x02)) - { - pAddr = pEap->KeyDesc.KeyData + 8; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2) - pSTAKey = pEap->KeyDesc.KeyData + 14; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2), STAKey_Mac_Addr(6) - - DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 from %02x:%02x:%02x:%02x:%02x:%02x Len=%ld, KeyDataLen=%d\n", - pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], Len, pEap->KeyDesc.KeyData[1])); - - bSTAKeyFrame = TRUE; - } - - } - else if (Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE)) - { - RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); - DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter 2(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n", - pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2], - pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4], pAd->StaCfg.ReplayCounter[5], - pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1])); - } - } - - // If timeout value is equaled to zero, it means always not be timeout. - // update local dls table entry - for (i= 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) - { - if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - if (bSTAKeyFrame) - { - PMAC_TABLE_ENTRY pEntry; - - // STAKey frame, add pairwise key table - pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; - RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); - - PairwiseKey.KeyLen = LEN_TKIP_EK; - NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK); - NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK); - NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK); - - //PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg; - if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) - PairwiseKey.CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) - PairwiseKey.CipherAlg = CIPHER_AES; - - pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE); - //AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast - //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr); - // Add Pair-wise key to Asic -#ifdef RTMP_MAC_PCI - AsicAddPairwiseKeyEntry(pAd, - pAd->StaCfg.DLSEntry[i].MacAddr, - (UCHAR)pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, - &PairwiseKey); - - RTMPAddWcidAttributeEntry(pAd, - BSS0, - 0, - PairwiseKey.CipherAlg, - pEntry); - -#endif // RTMP_MAC_PCI // - NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY)); - DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Peer STA MAC Address STAKey) \n")); - - RTMPSendSTAKeyHandShake(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); - - DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Initiator side)\n")); - } - else - { - // Data frame, update timeout value - if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) - { - pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut; - //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr); - } - } - - bFindEntry = TRUE; - } - } - - // update peer dls table entry - for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - if (bSTAKeyFrame) - { - PMAC_TABLE_ENTRY pEntry = NULL; - - // STAKey frame, add pairwise key table, and send STAkey Msg-2 - pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; - RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); - - PairwiseKey.KeyLen = LEN_TKIP_EK; - NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK); - NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK); - NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK); - - //PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg; - if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) - PairwiseKey.CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) - PairwiseKey.CipherAlg = CIPHER_AES; - - pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE); - //AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast - //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr); - // Add Pair-wise key to Asic -#ifdef RTMP_MAC_PCI - AsicAddPairwiseKeyEntry(pAd, - pAd->StaCfg.DLSEntry[i].MacAddr, - (UCHAR)pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, - &PairwiseKey); - - RTMPAddWcidAttributeEntry(pAd, - BSS0, - 0, - PairwiseKey.CipherAlg, - pEntry); -#endif // RTMP_MAC_PCI // - NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY)); - DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Initiator STA MAC Address STAKey)\n")); - - // If support WPA or WPA2, start STAKey hand shake, - // If failed hand shake, just tear down peer DLS - if (RTMPSendSTAKeyHandShake(pAd, pAddr) != NDIS_STATUS_SUCCESS) - { - MLME_DLS_REQ_STRUCT MlmeDlsReq; - USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT; - - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); - MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); - } - else - { - DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Peer side)\n")); - } - } - else - { - // Data frame, update timeout value - if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) - { - pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut; - } - } - - bFindEntry = TRUE; - } - } - - - return bSTAKeyFrame; -} - -/* - ======================================================================== - - Routine Description: - Check if the frame can be sent through DLS direct link interface - - Arguments: - pAd Pointer to adapter - - Return Value: - DLS entry index - - Note: - - ======================================================================== -*/ -INT RTMPCheckDLSFrame( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA) -{ - INT rval = -1; - INT i; - - if (!pAd->CommonCfg.bDLSCapable) - return rval; - - if (!INFRA_ON(pAd)) - return rval; - - do{ - // check local dls table entry - for (i=0; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && - MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - rval = i; - break; - } - } - - // check peer dls table entry - for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && - MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - rval = i; - break; - } - } - } while (FALSE); - - return rval; -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID RTMPSendDLSTearDownFrame( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA) -{ - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - HEADER_802_11 DlsTearDownHdr; - ULONG FrameLen = 0; - USHORT Reason = REASON_QOS_QSTA_LEAVING_QBSS; - UCHAR Category = CATEGORY_DLS; - UCHAR Action = ACTION_DLS_TEARDOWN; - UCHAR i = 0; - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) - return; - - DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame \n")); - - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - { - DBGPRINT(RT_DEBUG_ERROR,("ASSOC - RTMPSendDLSTearDownFrame() allocate memory failed \n")); - return; - } - - ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid); - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &DlsTearDownHdr, - 1, &Category, - 1, &Action, - 6, pDA, - 6, pAd->CurrentAddress, - 2, &Reason, - END_OF_ARGS); - - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - - // Remove key in local dls table entry - for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) - { - if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) - && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); - } - } - - // Remove key in peer dls table entry - for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) - && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) - { - MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); - } - } - - DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame and remove key in (i=%d) \n", i)); -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -NDIS_STATUS RTMPSendSTAKeyRequest( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA) -{ - UCHAR Header802_3[14]; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - EAPOL_PACKET Packet; - UCHAR Mic[16]; - UCHAR digest[80]; - PUCHAR pOutBuffer = NULL; - PNDIS_PACKET pNdisPacket; - UCHAR temp[64]; - UCHAR DlsPTK[80]; - - DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyRequest() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5])); - - pAd->Sequence ++; - MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); - - // Zero message body - NdisZeroMemory(&Packet, sizeof(Packet)); - Packet.ProVer = EAPOL_VER; - Packet.ProType = EAPOLKey; - Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN; // data field contain KDE andPeer MAC address - - // STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE) - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) - { - Packet.KeyDesc.Type = WPA1_KEY_DESC; - } - else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - Packet.KeyDesc.Type = WPA2_KEY_DESC; - } - - // Key descriptor version - Packet.KeyDesc.KeyInfo.KeyDescVer = - (((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP)); - - Packet.KeyDesc.KeyInfo.KeyMic = 1; - Packet.KeyDesc.KeyInfo.Secure = 1; - Packet.KeyDesc.KeyInfo.Request = 1; - - Packet.KeyDesc.KeyDataLen[1] = 12; - - // use our own OUI to distinguish proprietary with standard. - Packet.KeyDesc.KeyData[0] = 0xDD; - Packet.KeyDesc.KeyData[1] = 0x0A; - Packet.KeyDesc.KeyData[2] = 0x00; - Packet.KeyDesc.KeyData[3] = 0x0C; - Packet.KeyDesc.KeyData[4] = 0x43; - Packet.KeyDesc.KeyData[5] = 0x03; - NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN); - - NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY); - - // Allocate buffer for transmitting message - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); - if (NStatus != NDIS_STATUS_SUCCESS) - return NStatus; - - // Prepare EAPOL frame for MIC calculation - // Be careful, only EAPOL frame is counted for MIC calculation - MakeOutgoingFrame(pOutBuffer, &FrameLen, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - // use proprietary PTK - NdisZeroMemory(temp, 64); - NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); - WpaDerivePTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK); - - // calculate MIC - if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - // AES - NdisZeroMemory(digest, sizeof(digest)); - HMAC_SHA1(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE); - NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC); - } - else - { - NdisZeroMemory(Mic, sizeof(Mic)); - HMAC_MD5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic, MD5_DIGEST_SIZE); - NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); - } - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(Header802_3), Header802_3, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen); - if (NStatus == NDIS_STATUS_SUCCESS) - { - RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID); - STASendPacket(pAd, pNdisPacket); - RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); - } - - MlmeFreeMemory(pAd, pOutBuffer); - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyRequest- Send STAKey request (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen)); - - return NStatus; -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -NDIS_STATUS RTMPSendSTAKeyHandShake( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA) -{ - UCHAR Header802_3[14]; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - EAPOL_PACKET Packet; - UCHAR Mic[16]; - UCHAR digest[80]; - PUCHAR pOutBuffer = NULL; - PNDIS_PACKET pNdisPacket; - UCHAR temp[64]; - UCHAR DlsPTK[80]; // Due to dirver can not get PTK, use proprietary PTK - - DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyHandShake() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5])); - - pAd->Sequence ++; - MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); - - // Zero message body - NdisZeroMemory(&Packet, sizeof(Packet)); - Packet.ProVer = EAPOL_VER; - Packet.ProType = EAPOLKey; - Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN; // data field contain KDE and Peer MAC address - - // STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE) - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) - { - Packet.KeyDesc.Type = WPA1_KEY_DESC; - } - else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) - { - Packet.KeyDesc.Type = WPA2_KEY_DESC; - } - - // Key descriptor version - Packet.KeyDesc.KeyInfo.KeyDescVer = - (((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP)); - - Packet.KeyDesc.KeyInfo.KeyMic = 1; - Packet.KeyDesc.KeyInfo.Secure = 1; - - Packet.KeyDesc.KeyDataLen[1] = 12; - - // use our own OUI to distinguish proprietary with standard. - Packet.KeyDesc.KeyData[0] = 0xDD; - Packet.KeyDesc.KeyData[1] = 0x0A; - Packet.KeyDesc.KeyData[2] = 0x00; - Packet.KeyDesc.KeyData[3] = 0x0C; - Packet.KeyDesc.KeyData[4] = 0x43; - Packet.KeyDesc.KeyData[5] = 0x03; - NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN); - - NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY); - - // Allocate buffer for transmitting message - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); - if (NStatus != NDIS_STATUS_SUCCESS) - return NStatus; - - // Prepare EAPOL frame for MIC calculation - // Be careful, only EAPOL frame is counted for MIC calculation - MakeOutgoingFrame(pOutBuffer, &FrameLen, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - // use proprietary PTK - NdisZeroMemory(temp, 64); - NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); - WpaDerivePTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK); - - // calculate MIC - if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - // AES - NdisZeroMemory(digest, sizeof(digest)); - HMAC_SHA1(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE); - NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC); - } - else - { - NdisZeroMemory(Mic, sizeof(Mic)); - HMAC_MD5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic, MD5_DIGEST_SIZE); - NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); - } - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(Header802_3), Header802_3, - Packet.Body_Len[1] + 4, &Packet, - END_OF_ARGS); - - NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen); - if (NStatus == NDIS_STATUS_SUCCESS) - { - RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID); - STASendPacket(pAd, pNdisPacket); - RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); - } - - MlmeFreeMemory(pAd, pOutBuffer); - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyHandShake- Send STAKey Message-2 (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen)); - - return NStatus; -} - -VOID DlsTimeoutAction( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - MLME_DLS_REQ_STRUCT MlmeDlsReq; - USHORT reason; - PRT_802_11_DLS pDLS = (PRT_802_11_DLS)FunctionContext; - PRTMP_ADAPTER pAd = pDLS->pAd; - - DBGPRINT(RT_DEBUG_TRACE, ("DlsTimeout - Tear down DLS links (%02x:%02x:%02x:%02x:%02x:%02x)\n", - pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5])); - - if ((pDLS) && (pDLS->Valid)) - { - reason = REASON_QOS_REQUEST_TIMEOUT; - pDLS->Valid = FALSE; - pDLS->Status = DLS_NONE; - DlsParmFill(pAd, &MlmeDlsReq, pDLS, reason); - MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); - RTMP_MLME_HANDLER(pAd); - } -} - -/* -================================================================ -Description : because DLS and CLI share the same WCID table in ASIC. -Mesh entry also insert to pAd->MacTab.content[]. Such is marked as ValidAsDls = TRUE. -Also fills the pairwise key. -Because front MAX_AID_BA entries have direct mapping to BAEntry, which is only used as CLI. So we insert Dls -from index MAX_AID_BA. -================================================================ -*/ -MAC_TABLE_ENTRY *MacTableInsertDlsEntry( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN UINT DlsEntryIdx) -{ - PMAC_TABLE_ENTRY pEntry = NULL; - - DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableInsertDlsEntry\n")); - // if FULL, return - if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) - return NULL; - - do - { - if((pEntry = DlsEntryTableLookup(pAd, pAddr, TRUE)) != NULL) - break; - - // allocate one MAC entry - pEntry = MacTableInsertEntry(pAd, pAddr, DlsEntryIdx + MIN_NET_DEVICE_FOR_DLS, TRUE); - if (pEntry) - { - pAd->StaCfg.DLSEntry[DlsEntryIdx].MacTabMatchWCID = pEntry->Aid; - pEntry->MatchDlsEntryIdx = DlsEntryIdx; - pEntry->AuthMode = pAd->StaCfg.AuthMode; - pEntry->WepStatus = pAd->StaCfg.WepStatus; - pEntry->PortSecured = WPA_802_1X_PORT_SECURED; - - DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertDlsEntry - allocate entry #%d, Total= %d\n",pEntry->Aid, pAd->MacTab.Size)); - - // If legacy WEP is used, set pair-wise cipherAlg into WCID attribute table for this entry - if ((pEntry->ValidAsDls) && (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)) - { - UCHAR KeyIdx = 0; - UCHAR CipherAlg = 0; - - KeyIdx = pAd->StaCfg.DefaultKeyId; - - CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; - - RTMPAddWcidAttributeEntry(pAd, - BSS0, - pAd->StaCfg.DefaultKeyId, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, - pEntry); - } - - break; - } - } while(FALSE); - - DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableInsertDlsEntry\n")); - - return pEntry; -} - - -/* - ========================================================================== - Description: - Delete all Mesh Entry in pAd->MacTab - ========================================================================== - */ -BOOLEAN MacTableDeleteDlsEntry( - IN PRTMP_ADAPTER pAd, - IN USHORT wcid, - IN PUCHAR pAddr) -{ - DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableDeleteDlsEntry\n")); - - if (!VALID_WCID(wcid)) - return FALSE; - - MacTableDeleteEntry(pAd, wcid, pAddr); - - DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableDeleteDlsEntry\n")); - - return TRUE; -} - -MAC_TABLE_ENTRY *DlsEntryTableLookup( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pAddr, - IN BOOLEAN bResetIdelCount) -{ - ULONG HashIdx; - MAC_TABLE_ENTRY *pEntry = NULL; - - RTMP_SEM_LOCK(&pAd->MacTabLock); - HashIdx = MAC_ADDR_HASH_INDEX(pAddr); - pEntry = pAd->MacTab.Hash[HashIdx]; - - while (pEntry) - { - if ((pEntry->ValidAsDls == TRUE) - && MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) - { - if(bResetIdelCount) - pEntry->NoDataIdleCount = 0; - break; - } - else - pEntry = pEntry->pNext; - } - - RTMP_SEM_UNLOCK(&pAd->MacTabLock); - return pEntry; -} - -MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid( - IN PRTMP_ADAPTER pAd, - IN UCHAR wcid, - IN PUCHAR pAddr, - IN BOOLEAN bResetIdelCount) -{ - ULONG DLsIndex; - PMAC_TABLE_ENTRY pCurEntry = NULL; - PMAC_TABLE_ENTRY pEntry = NULL; - - if (!VALID_WCID(wcid)) - return NULL; - - RTMP_SEM_LOCK(&pAd->MacTabLock); - - do - { - pCurEntry = &pAd->MacTab.Content[wcid]; - - DLsIndex = 0xff; - if ((pCurEntry) && (pCurEntry->ValidAsDls== TRUE)) - { - DLsIndex = pCurEntry->MatchDlsEntryIdx; - } - - if (DLsIndex == 0xff) - break; - - if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddr)) - { - if(bResetIdelCount) - pCurEntry->NoDataIdleCount = 0; - pEntry = pCurEntry; - break; - } - } while(FALSE); - - RTMP_SEM_UNLOCK(&pAd->MacTabLock); - - return pEntry; -} - -INT Set_DlsEntryInfo_Display_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - INT i; - - DBGPRINT(RT_DEBUG_OFF, ("\n%-19s%-8s\n", "MAC", "TIMEOUT\n")); - for (i=0; iStaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) - { - PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[pAd->StaCfg.DLSEntry[i].MacTabMatchWCID]; - - DBGPRINT(RT_DEBUG_OFF, ("%02x:%02x:%02x:%02x:%02x:%02x ", - pAd->StaCfg.DLSEntry[i].MacAddr[0], pAd->StaCfg.DLSEntry[i].MacAddr[1], pAd->StaCfg.DLSEntry[i].MacAddr[2], - pAd->StaCfg.DLSEntry[i].MacAddr[3], pAd->StaCfg.DLSEntry[i].MacAddr[4], pAd->StaCfg.DLSEntry[i].MacAddr[5])); - DBGPRINT(RT_DEBUG_OFF, ("%-8d\n", pAd->StaCfg.DLSEntry[i].TimeOut)); - - DBGPRINT(RT_DEBUG_OFF, ("\n")); - DBGPRINT(RT_DEBUG_OFF, ("\n%-19s%-4s%-4s%-4s%-4s%-7s%-7s%-7s","MAC", "AID", "BSS", "PSM", "WMM", "RSSI0", "RSSI1", "RSSI2")); -#ifdef DOT11_N_SUPPORT - DBGPRINT(RT_DEBUG_OFF, ("%-8s%-10s%-6s%-6s%-6s%-6s", "MIMOPS", "PhMd", "BW", "MCS", "SGI", "STBC")); -#endif // DOT11_N_SUPPORT // - DBGPRINT(RT_DEBUG_OFF, ("\n%02X:%02X:%02X:%02X:%02X:%02X ", - pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], - pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5])); - DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->Aid)); - DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->apidx)); - DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->PsMode)); - DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))); - DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi0)); - DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi1)); - DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi2)); -#ifdef DOT11_N_SUPPORT - DBGPRINT(RT_DEBUG_OFF, ("%-8d", (int)pEntry->MmpsMode)); - DBGPRINT(RT_DEBUG_OFF, ("%-10s", GetPhyMode(pEntry->HTPhyMode.field.MODE))); - DBGPRINT(RT_DEBUG_OFF, ("%-6s", GetBW(pEntry->HTPhyMode.field.BW))); - DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.MCS)); - DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.ShortGI)); - DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.STBC)); -#endif // DOT11_N_SUPPORT // - DBGPRINT(RT_DEBUG_OFF, ("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount, - (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0)); - DBGPRINT(RT_DEBUG_OFF, ("\n")); - - } - } - - return TRUE; -} - -INT Set_DlsAddEntry_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UCHAR mac[MAC_ADDR_LEN]; - USHORT Timeout; - PSTRING token; - STRING sepValue[] = ":", DASH = '-'; - INT i; - RT_802_11_DLS Dls; - - if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and timeout value in decimal format. - return FALSE; - - token = strchr(arg, DASH); - if ((token != NULL) && (strlen(token)>1)) - { - Timeout = (USHORT) simple_strtol((token+1), 0, 10); - - *token = '\0'; - for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) - { - if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) - return FALSE; - AtoH(token, (&mac[i]), 1); - } - if(i != 6) - return FALSE; - - DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%d", mac[0], mac[1], - mac[2], mac[3], mac[4], mac[5], (int)Timeout)); - - NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS)); - Dls.TimeOut = Timeout; - COPY_MAC_ADDR(Dls.MacAddr, mac); - Dls.Valid = 1; - - MlmeEnqueue(pAd, - MLME_CNTL_STATE_MACHINE, - RT_OID_802_11_SET_DLS_PARAM, - sizeof(RT_802_11_DLS), - &Dls); - - return TRUE; - } - - return FALSE; - -} - -INT Set_DlsTearDownEntry_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - UCHAR macAddr[MAC_ADDR_LEN]; - PSTRING value; - INT i; - RT_802_11_DLS Dls; - - if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 - return FALSE; - - for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) - { - if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) - return FALSE; //Invalid - - AtoH(value, &macAddr[i++], 2); - } - - DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x", macAddr[0], macAddr[1], - macAddr[2], macAddr[3], macAddr[4], macAddr[5])); - - NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS)); - COPY_MAC_ADDR(Dls.MacAddr, macAddr); - Dls.Valid = 0; - - MlmeEnqueue(pAd, - MLME_CNTL_STATE_MACHINE, - RT_OID_802_11_SET_DLS_PARAM, - sizeof(RT_802_11_DLS), - &Dls); - - return TRUE; -} diff --git a/drivers/staging/rt3090/sta/rtmp_ckipmic.c b/drivers/staging/rt3090/sta/rtmp_ckipmic.c deleted file mode 100644 index 5f6dbd7cf057e024d0a1d53168b105361189bfd1..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/sta/rtmp_ckipmic.c +++ /dev/null @@ -1,579 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rtmp_ckipmic.c - - Abstract: - Data path subroutines - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#include "../rt_config.h" -#include "../rtmp_ckipmic.h" - - -#define MIC_ACCUM(v) pContext->accum += (ULONGLONG)v * RTMPMicGetCoefficient(pContext) -#define GB(p,i,s) ( ((ULONG) *((UCHAR*)(p)+i) ) << (s) ) -#define GETBIG32(p) GB(p,0,24)|GB(p,1,16)|GB(p,2,8)|GB(p,3,0) - -/*****************************/ -/******** SBOX Table *********/ -/*****************************/ - -UCHAR SboxTable[256] = -{ - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, - 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, - 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, - 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, - 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, - 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, - 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, - 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, - 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, - 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, - 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, - 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 -}; - -/*===========================================================================*/ -/*=================== CKIP KEY PERMUTATION ==================================*/ -/*===========================================================================*/ - -/* 2-byte by 2-byte subset of the full AES table */ -static const USHORT Sbox[256] = -{ - 0xC6A5,0xF884,0xEE99,0xF68D,0xFF0D,0xD6BD,0xDEB1,0x9154, - 0x6050,0x0203,0xCEA9,0x567D,0xE719,0xB562,0x4DE6,0xEC9A, - 0x8F45,0x1F9D,0x8940,0xFA87,0xEF15,0xB2EB,0x8EC9,0xFB0B, - 0x41EC,0xB367,0x5FFD,0x45EA,0x23BF,0x53F7,0xE496,0x9B5B, - 0x75C2,0xE11C,0x3DAE,0x4C6A,0x6C5A,0x7E41,0xF502,0x834F, - 0x685C,0x51F4,0xD134,0xF908,0xE293,0xAB73,0x6253,0x2A3F, - 0x080C,0x9552,0x4665,0x9D5E,0x3028,0x37A1,0x0A0F,0x2FB5, - 0x0E09,0x2436,0x1B9B,0xDF3D,0xCD26,0x4E69,0x7FCD,0xEA9F, - 0x121B,0x1D9E,0x5874,0x342E,0x362D,0xDCB2,0xB4EE,0x5BFB, - 0xA4F6,0x764D,0xB761,0x7DCE,0x527B,0xDD3E,0x5E71,0x1397, - 0xA6F5,0xB968,0x0000,0xC12C,0x4060,0xE31F,0x79C8,0xB6ED, - 0xD4BE,0x8D46,0x67D9,0x724B,0x94DE,0x98D4,0xB0E8,0x854A, - 0xBB6B,0xC52A,0x4FE5,0xED16,0x86C5,0x9AD7,0x6655,0x1194, - 0x8ACF,0xE910,0x0406,0xFE81,0xA0F0,0x7844,0x25BA,0x4BE3, - 0xA2F3,0x5DFE,0x80C0,0x058A,0x3FAD,0x21BC,0x7048,0xF104, - 0x63DF,0x77C1,0xAF75,0x4263,0x2030,0xE51A,0xFD0E,0xBF6D, - 0x814C,0x1814,0x2635,0xC32F,0xBEE1,0x35A2,0x88CC,0x2E39, - 0x9357,0x55F2,0xFC82,0x7A47,0xC8AC,0xBAE7,0x322B,0xE695, - 0xC0A0,0x1998,0x9ED1,0xA37F,0x4466,0x547E,0x3BAB,0x0B83, - 0x8CCA,0xC729,0x6BD3,0x283C,0xA779,0xBCE2,0x161D,0xAD76, - 0xDB3B,0x6456,0x744E,0x141E,0x92DB,0x0C0A,0x486C,0xB8E4, - 0x9F5D,0xBD6E,0x43EF,0xC4A6,0x39A8,0x31A4,0xD337,0xF28B, - 0xD532,0x8B43,0x6E59,0xDAB7,0x018C,0xB164,0x9CD2,0x49E0, - 0xD8B4,0xACFA,0xF307,0xCF25,0xCAAF,0xF48E,0x47E9,0x1018, - 0x6FD5,0xF088,0x4A6F,0x5C72,0x3824,0x57F1,0x73C7,0x9751, - 0xCB23,0xA17C,0xE89C,0x3E21,0x96DD,0x61DC,0x0D86,0x0F85, - 0xE090,0x7C42,0x71C4,0xCCAA,0x90D8,0x0605,0xF701,0x1C12, - 0xC2A3,0x6A5F,0xAEF9,0x69D0,0x1791,0x9958,0x3A27,0x27B9, - 0xD938,0xEB13,0x2BB3,0x2233,0xD2BB,0xA970,0x0789,0x33A7, - 0x2DB6,0x3C22,0x1592,0xC920,0x8749,0xAAFF,0x5078,0xA57A, - 0x038F,0x59F8,0x0980,0x1A17,0x65DA,0xD731,0x84C6,0xD0B8, - 0x82C3,0x29B0,0x5A77,0x1E11,0x7BCB,0xA8FC,0x6DD6,0x2C3A - }; - -#define Lo8(v16) ((v16) & 0xFF) -#define Hi8(v16) (((v16) >> 8) & 0xFF) -#define u16Swap(i) ( (((i) >> 8) & 0xFF) | (((i) << 8) & 0xFF00) ) -#define _S_(i) (Sbox[Lo8(i)] ^ u16Swap(Sbox[Hi8(i)])) - -#define rotLeft_1(x) ((((x) << 1) | ((x) >> 15)) & 0xFFFF) -VOID CKIP_key_permute - ( - OUT UCHAR *PK, /* output permuted key */ - IN UCHAR *CK, /* input CKIP key */ - IN UCHAR toDsFromDs, /* input toDs/FromDs bits */ - IN UCHAR *piv /* input pointer to IV */ - ) -{ - int i; - USHORT H[2], tmp; /* H=32-bits of per-packet hash value */ - USHORT L[8], R[8]; /* L=u16 array of CK, R=u16 array of PK */ - - /* build L from input key */ - memset(L, 0, sizeof(L)); - for (i=0; i<16; i++) { - L[i>>1] |= ( ((USHORT)(CK[i])) << ( i & 1 ? 8 : 0) ); - } - - H[0] = (((USHORT)piv[0]) << 8) + piv[1]; - H[1] = ( ((USHORT)toDsFromDs) << 8) | piv[2]; - - for (i=0; i<8; i++) { - H[0] ^= L[i]; /* 16-bits of key material */ - tmp = _S_(H[0]); /* 16x16 permutation */ - H[0] = tmp ^ H[1]; /* set up for next round */ - H[1] = tmp; - R[i] = H[0]; /* store into key array */ - } - - /* sweep in the other direction */ - tmp=L[0]; - for (i=7; i>0; i--) { - R[i] = tmp = rotLeft_1(tmp) + R[i]; - } - - /* IV of the permuted key is unchanged */ - PK[0] = piv[0]; - PK[1] = piv[1]; - PK[2] = piv[2]; - - /* key portion of the permuted key is changed */ - for (i=3; i<16; i++) { - PK[i] = (UCHAR) (R[i>>1] >> (i & 1 ? 8 : 0)); - } -} - -/* prepare for calculation of a new mic */ -VOID RTMPCkipMicInit( - IN PMIC_CONTEXT pContext, - IN PUCHAR CK) -{ - /* prepare for new mic calculation */ - NdisMoveMemory(pContext->CK, CK, sizeof(pContext->CK)); - pContext->accum = 0; - pContext->position = 0; -} - -/* add some bytes to the mic calculation */ -VOID RTMPMicUpdate( - IN PMIC_CONTEXT pContext, - IN PUCHAR pOctets, - IN INT len) -{ - INT byte_position; - ULONG val; - - byte_position = (pContext->position & 3); - while (len > 0) { - /* build a 32-bit word for MIC multiply accumulate */ - do { - if (len == 0) return; - pContext->part[byte_position++] = *pOctets++; - pContext->position++; - len--; - } while (byte_position < 4); - /* have a full 32-bit word to process */ - val = GETBIG32(&pContext->part[0]); - MIC_ACCUM(val); - byte_position = 0; - } -} - -ULONG RTMPMicGetCoefficient( - IN PMIC_CONTEXT pContext) -{ - UCHAR aes_counter[16]; - INT coeff_position; - UCHAR *p; - - coeff_position = (pContext->position - 1) >> 2; - if ( (coeff_position & 3) == 0) { - /* fetching the first coefficient -- get new 16-byte aes counter output */ - u32 counter = (coeff_position >> 2); - - /* new counter value */ - memset(&aes_counter[0], 0, sizeof(aes_counter)); - aes_counter[15] = (UINT8)(counter >> 0); - aes_counter[14] = (UINT8)(counter >> 8); - aes_counter[13] = (UINT8)(counter >> 16); - aes_counter[12] = (UINT8)(counter >> 24); - - RTMPAesEncrypt(&pContext->CK[0], &aes_counter[0], pContext->coefficient); - } - p = &(pContext->coefficient[ (coeff_position & 3) << 2 ]); - return GETBIG32(p); -} - -/****************************************/ -/* aes128k128d() */ -/* Performs a 128 bit AES encrypt with */ -/* 128 bit data. */ -/****************************************/ -VOID xor_128( - IN PUCHAR a, - IN PUCHAR b, - OUT PUCHAR out) -{ - INT i; - - for (i=0;i<16; i++) - { - out[i] = a[i] ^ b[i]; - } -} - -UCHAR RTMPCkipSbox( - IN UCHAR a) -{ - return SboxTable[(int)a]; -} - -VOID xor_32( - IN PUCHAR a, - IN PUCHAR b, - OUT PUCHAR out) -{ - INT i; - - for (i=0;i<4; i++) - { - out[i] = a[i] ^ b[i]; - } -} - -VOID next_key( - IN PUCHAR key, - IN INT round) -{ - UCHAR rcon; - UCHAR sbox_key[4]; - UCHAR rcon_table[12] = - { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, - 0x1b, 0x36, 0x36, 0x36 - }; - - sbox_key[0] = RTMPCkipSbox(key[13]); - sbox_key[1] = RTMPCkipSbox(key[14]); - sbox_key[2] = RTMPCkipSbox(key[15]); - sbox_key[3] = RTMPCkipSbox(key[12]); - - rcon = rcon_table[round]; - - xor_32(&key[0], sbox_key, &key[0]); - key[0] = key[0] ^ rcon; - - xor_32(&key[4], &key[0], &key[4]); - xor_32(&key[8], &key[4], &key[8]); - xor_32(&key[12], &key[8], &key[12]); -} - -VOID byte_sub( - IN PUCHAR in, - OUT PUCHAR out) -{ - INT i; - - for (i=0; i< 16; i++) - { - out[i] = RTMPCkipSbox(in[i]); - } -} - -VOID shift_row( - IN PUCHAR in, - OUT PUCHAR out) -{ - out[0] = in[0]; - out[1] = in[5]; - out[2] = in[10]; - out[3] = in[15]; - out[4] = in[4]; - out[5] = in[9]; - out[6] = in[14]; - out[7] = in[3]; - out[8] = in[8]; - out[9] = in[13]; - out[10] = in[2]; - out[11] = in[7]; - out[12] = in[12]; - out[13] = in[1]; - out[14] = in[6]; - out[15] = in[11]; -} - -VOID mix_column( - IN PUCHAR in, - OUT PUCHAR out) -{ - INT i; - UCHAR add1b[4]; - UCHAR add1bf7[4]; - UCHAR rotl[4]; - UCHAR swap_halfs[4]; - UCHAR andf7[4]; - UCHAR rotr[4]; - UCHAR temp[4]; - UCHAR tempb[4]; - - for (i=0 ; i<4; i++) - { - if ((in[i] & 0x80)== 0x80) - add1b[i] = 0x1b; - else - add1b[i] = 0x00; - } - - swap_halfs[0] = in[2]; /* Swap halfs */ - swap_halfs[1] = in[3]; - swap_halfs[2] = in[0]; - swap_halfs[3] = in[1]; - - rotl[0] = in[3]; /* Rotate left 8 bits */ - rotl[1] = in[0]; - rotl[2] = in[1]; - rotl[3] = in[2]; - - andf7[0] = in[0] & 0x7f; - andf7[1] = in[1] & 0x7f; - andf7[2] = in[2] & 0x7f; - andf7[3] = in[3] & 0x7f; - - for (i = 3; i>0; i--) /* logical shift left 1 bit */ - { - andf7[i] = andf7[i] << 1; - if ((andf7[i-1] & 0x80) == 0x80) - { - andf7[i] = (andf7[i] | 0x01); - } - } - andf7[0] = andf7[0] << 1; - andf7[0] = andf7[0] & 0xfe; - - xor_32(add1b, andf7, add1bf7); - - xor_32(in, add1bf7, rotr); - - temp[0] = rotr[0]; /* Rotate right 8 bits */ - rotr[0] = rotr[1]; - rotr[1] = rotr[2]; - rotr[2] = rotr[3]; - rotr[3] = temp[0]; - - xor_32(add1bf7, rotr, temp); - xor_32(swap_halfs, rotl,tempb); - xor_32(temp, tempb, out); -} - -VOID RTMPAesEncrypt( - IN PUCHAR key, - IN PUCHAR data, - IN PUCHAR ciphertext) -{ - INT round; - INT i; - UCHAR intermediatea[16]; - UCHAR intermediateb[16]; - UCHAR round_key[16]; - - for(i=0; i<16; i++) round_key[i] = key[i]; - - for (round = 0; round < 11; round++) - { - if (round == 0) - { - xor_128(round_key, data, ciphertext); - next_key(round_key, round); - } - else if (round == 10) - { - byte_sub(ciphertext, intermediatea); - shift_row(intermediatea, intermediateb); - xor_128(intermediateb, round_key, ciphertext); - } - else /* 1 - 9 */ - { - byte_sub(ciphertext, intermediatea); - shift_row(intermediatea, intermediateb); - mix_column(&intermediateb[0], &intermediatea[0]); - mix_column(&intermediateb[4], &intermediatea[4]); - mix_column(&intermediateb[8], &intermediatea[8]); - mix_column(&intermediateb[12], &intermediatea[12]); - xor_128(intermediatea, round_key, ciphertext); - next_key(round_key, round); - } - } - -} - -/* calculate the mic */ -VOID RTMPMicFinal( - IN PMIC_CONTEXT pContext, - OUT UCHAR digest[4]) -{ - INT byte_position; - ULONG val; - ULONGLONG sum, utmp; - LONGLONG stmp; - - /* deal with partial 32-bit word left over from last update */ - if ( (byte_position = (pContext->position & 3)) != 0) { - /* have a partial word in part to deal with -- zero unused bytes */ - do { - pContext->part[byte_position++] = 0; - pContext->position++; - } while (byte_position < 4); - val = GETBIG32(&pContext->part[0]); - MIC_ACCUM(val); - } - - /* reduce the accumulated u64 to a 32-bit MIC */ - sum = pContext->accum; - stmp = (sum & 0xffffffffL) - ((sum >> 32) * 15); - utmp = (stmp & 0xffffffffL) - ((stmp >> 32) * 15); - sum = utmp & 0xffffffffL; - if (utmp > 0x10000000fL) - sum -= 15; - - val = (ULONG)sum; - digest[0] = (UCHAR)((val>>24) & 0xFF); - digest[1] = (UCHAR) ((val>>16) & 0xFF); - digest[2] = (UCHAR) ((val>>8) & 0xFF); - digest[3] = (UCHAR)((val>>0) & 0xFF); -} - -VOID RTMPCkipInsertCMIC( - IN PRTMP_ADAPTER pAd, - OUT PUCHAR pMIC, - IN PUCHAR p80211hdr, - IN PNDIS_PACKET pPacket, - IN PCIPHER_KEY pKey, - IN PUCHAR mic_snap) -{ - PACKET_INFO PacketInfo; - PUCHAR pSrcBufVA; - ULONG SrcBufLen; - PUCHAR pDA, pSA, pProto; - UCHAR bigethlen[2]; - UCHAR ckip_ck[16]; - MIC_CONTEXT mic_ctx; - USHORT payloadlen; - UCHAR i; - - if (pKey == NULL) - { - DBGPRINT_ERR(("RTMPCkipInsertCMIC, Before to form the CKIP key (CK), pKey can't be NULL\n")); - return; - } - - switch (*(p80211hdr+1) & 3) - { - case 0: /* FromDs=0, ToDs=0 */ - pDA = p80211hdr+4; - pSA = p80211hdr+10; - break; - case 1: /* FromDs=0, ToDs=1 */ - pDA = p80211hdr+16; - pSA = p80211hdr+10; - break; - case 2: /* FromDs=1, ToDs=0 */ - pDA = p80211hdr+4; - pSA = p80211hdr+16; - break; - case 3: /* FromDs=1, ToDs=1 */ - pDA = p80211hdr+16; - pSA = p80211hdr+24; - break; - } - - RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); - - if (SrcBufLen < LENGTH_802_3) - return; - - pProto = pSrcBufVA + 12; - payloadlen = PacketInfo.TotalPacketLength - LENGTH_802_3 + 18; // CKIP_LLC(8)+CMIC(4)+TxSEQ(4)+PROTO(2)=18 - - bigethlen[0] = (unsigned char)(payloadlen >> 8); - bigethlen[1] = (unsigned char)payloadlen; - - // - // Encryption Key expansion to form the CKIP Key (CKIP_CK). - // - if (pKey->KeyLen < 16) - { - for(i = 0; i < (16 / pKey->KeyLen); i++) - { - NdisMoveMemory(ckip_ck + i * pKey->KeyLen, - pKey->Key, - pKey->KeyLen); - } - NdisMoveMemory(ckip_ck + i * pKey->KeyLen, - pKey->Key, - 16 - (i * pKey->KeyLen)); - } - else - { - NdisMoveMemory(ckip_ck, pKey->Key, pKey->KeyLen); - } - RTMPCkipMicInit(&mic_ctx, ckip_ck); - RTMPMicUpdate(&mic_ctx, pDA, MAC_ADDR_LEN); // MIC <-- DA - RTMPMicUpdate(&mic_ctx, pSA, MAC_ADDR_LEN); // MIC <-- SA - RTMPMicUpdate(&mic_ctx, bigethlen, 2); // MIC <-- payload length starting from CKIP SNAP - RTMPMicUpdate(&mic_ctx, mic_snap, 8); // MIC <-- snap header - RTMPMicUpdate(&mic_ctx, pAd->StaCfg.TxSEQ, 4); // MIC <-- TxSEQ - RTMPMicUpdate(&mic_ctx, pProto, 2); // MIC <-- Protocol - - pSrcBufVA += LENGTH_802_3; - SrcBufLen -= LENGTH_802_3; - - // Mic <-- original payload. loop until all payload processed - do - { - if (SrcBufLen > 0) - RTMPMicUpdate(&mic_ctx, pSrcBufVA, SrcBufLen); - - NdisGetNextBuffer(PacketInfo.pFirstBuffer, &PacketInfo.pFirstBuffer); - if (PacketInfo.pFirstBuffer) - { - NDIS_QUERY_BUFFER(PacketInfo.pFirstBuffer, &pSrcBufVA, &SrcBufLen); - } - else - break; - } while (TRUE); - - RTMPMicFinal(&mic_ctx, pMIC); // update MIC -} diff --git a/drivers/staging/rt3090/sta/rtmp_data.c b/drivers/staging/rt3090/sta/rtmp_data.c deleted file mode 100644 index 559136409ff2e660b9ed380c2855f75c2c67a1d3..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/sta/rtmp_data.c +++ /dev/null @@ -1,2661 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - rtmp_data.c - - Abstract: - Data path subroutines - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- -*/ - -#include "../rt_config.h" - - -VOID STARxEAPOLFrameIndicate( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) -{ - PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); - PRXWI_STRUC pRxWI = pRxBlk->pRxWI; - UCHAR *pTmpBuf; - - -#ifdef WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.WpaSupplicantUP) - { - // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon) - // TBD : process fragmented EAPol frames - { - // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable - if ( pAd->StaCfg.IEEE8021X == TRUE && - (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H))) - { - PUCHAR Key; - UCHAR CipherAlg; - int idx = 0; - - DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n")); - //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - STA_PORT_SECURED(pAd); - - if (pAd->StaCfg.IEEE8021x_required_keys == FALSE) - { - idx = pAd->StaCfg.DesireSharedKeyId; - CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg; - Key = pAd->StaCfg.DesireSharedKey[idx].Key; - - if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0) - { -#ifdef RTMP_MAC_PCI - MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID]; - - // Set key material and cipherAlg to Asic - AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL); - - // Assign group key info - RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL); - - // Assign pairwise key info - RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry); - - pAd->IndicateMediaState = NdisMediaStateConnected; - pAd->ExtraInfo = GENERAL_LINK_UP; -#endif // RTMP_MAC_PCI // - // For Preventing ShardKey Table is cleared by remove key procedure. - pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg; - pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen; - NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key, - pAd->StaCfg.DesireSharedKey[idx].Key, - pAd->StaCfg.DesireSharedKey[idx].KeyLen); - } - } - } - - Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); - return; - } - } - else -#endif // WPA_SUPPLICANT_SUPPORT // - { - // Special DATA frame that has to pass to MLME - // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process - // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process - { - pTmpBuf = pRxBlk->pData - LENGTH_802_11; - NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11); - REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal); - DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize)); - } - } - - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); - return; - -} - -VOID STARxDataFrameAnnounce( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN RX_BLK *pRxBlk, - IN UCHAR FromWhichBSSID) -{ - - // non-EAP frame - if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID)) - { - - { - // drop all non-EAP DATA frame before - // this client's Port-Access-Control is secured - if (pRxBlk->pHeader->FC.Wep) - { - // unsupported cipher suite - if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled) - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); - return; - } - } - else - { - // encryption in-use but receive a non-EAPOL clear text frame, drop it - if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) && - (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); - return; - } - } - } - RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP); - - - if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) - { - // Normal legacy, AMPDU or AMSDU - CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID); - - } - else - { - // ARALINK - CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); - } -#ifdef QOS_DLS_SUPPORT - RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS); -#endif // QOS_DLS_SUPPORT // - } - else - { - RX_BLK_SET_FLAG(pRxBlk, fRX_EAP); -#ifdef DOT11_N_SUPPORT - if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) - { - Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); - } - else -#endif // DOT11_N_SUPPORT // - { - // Determin the destination of the EAP frame - // to WPA state machine or upper layer - STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); - } - } -} - - -// For TKIP frame, calculate the MIC value -BOOLEAN STACheckTkipMICValue( - IN PRTMP_ADAPTER pAd, - IN MAC_TABLE_ENTRY *pEntry, - IN RX_BLK *pRxBlk) -{ - PHEADER_802_11 pHeader = pRxBlk->pHeader; - UCHAR *pData = pRxBlk->pData; - USHORT DataSize = pRxBlk->DataSize; - UCHAR UserPriority = pRxBlk->UserPriority; - PCIPHER_KEY pWpaKey; - UCHAR *pDA, *pSA; - - pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex]; - - pDA = pHeader->Addr1; - if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA)) - { - pSA = pHeader->Addr3; - } - else - { - pSA = pHeader->Addr2; - } - - if (RTMPTkipCompareMICValue(pAd, - pData, - pDA, - pSA, - pWpaKey->RxMic, - UserPriority, - DataSize) == FALSE) - { - DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n")); - -#ifdef WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.WpaSupplicantUP) - { - WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE); - } - else -#endif // WPA_SUPPLICANT_SUPPORT // - { - RTMPReportMicError(pAd, pWpaKey); - } - - // release packet - RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); - return FALSE; - } - - return TRUE; -} - - -// -// All Rx routines use RX_BLK structure to hande rx events -// It is very important to build pRxBlk attributes -// 1. pHeader pointer to 802.11 Header -// 2. pData pointer to payload including LLC (just skip Header) -// 3. set payload size including LLC to DataSize -// 4. set some flags with RX_BLK_SET_FLAG() -// -VOID STAHandleRxDataFrame( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk) -{ - PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); - PRXWI_STRUC pRxWI = pRxBlk->pRxWI; - PHEADER_802_11 pHeader = pRxBlk->pHeader; - PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; - BOOLEAN bFragment = FALSE; - MAC_TABLE_ENTRY *pEntry = NULL; - UCHAR FromWhichBSSID = BSS0; - UCHAR UserPriority = 0; - - { - // before LINK UP, all DATA frames are rejected - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); - return; - } - -#ifdef QOS_DLS_SUPPORT - //if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0)) - if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxWI->MPDUtotalByteCount, pRxD)) - { - return; - } -#endif // QOS_DLS_SUPPORT // - - // Drop not my BSS frames - if (pRxD->MyBss == 0) - { - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); - return; - } - } - - pAd->RalinkCounters.RxCountSinceLastNULL++; - if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08)) - { - UCHAR *pData; - DBGPRINT(RT_DEBUG_INFO,("bAPSDCapable\n")); - - // Qos bit 4 - pData = (PUCHAR)pHeader + LENGTH_802_11; - if ((*pData >> 4) & 0x01) - { - DBGPRINT(RT_DEBUG_INFO,("RxDone- Rcv EOSP frame, driver may fall into sleep\n")); - pAd->CommonCfg.bInServicePeriod = FALSE; - - // Force driver to fall into sleep mode when rcv EOSP frame - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - USHORT TbttNumToNextWakeUp; - USHORT NextDtim = pAd->StaCfg.DtimPeriod; - ULONG Now; - - NdisGetSystemUpTime(&Now); - NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod; - - TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) - TbttNumToNextWakeUp = NextDtim; - - RTMP_SET_PSM_BIT(pAd, PWR_SAVE); - // if WMM-APSD is failed, try to disable following line - AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); - } - } - - if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod)) - { - DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n")); - } - } - - // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame - if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); - return; - } - - // Drop not my BSS frame (we can not only check the MyBss bit in RxD) -#ifdef QOS_DLS_SUPPORT - if (!pAd->CommonCfg.bDLSCapable) - { -#endif // QOS_DLS_SUPPORT // - if (INFRA_ON(pAd)) - { - // Infrastructure mode, check address 2 for BSSID - if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6)) - { - // Receive frame not my BSSID - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); - return; - } - } - else // Ad-Hoc mode or Not associated - { - // Ad-Hoc mode, check address 3 for BSSID - if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6)) - { - // Receive frame not my BSSID - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); - return; - } - } -#ifdef QOS_DLS_SUPPORT - } -#endif // QOS_DLS_SUPPORT // - - // - // find pEntry - // - if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE) - { - pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; - - } - else - { - // 1. release packet if infra mode - // 2. new a pEntry if ad-hoc mode - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); - return; - } - - // infra or ad-hoc - if (INFRA_ON(pAd)) - { - RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA); -#ifdef QOS_DLS_SUPPORT - if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0)) - RX_BLK_SET_FLAG(pRxBlk, fRX_DLS); - else -#endif // QOS_DLS_SUPPORT // - ASSERT(pRxWI->WirelessCliID == BSSID_WCID); - } - - // check Atheros Client - if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry )) - { - pEntry->bIAmBadAtheros = TRUE; - pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE; - pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE; - if (!STA_AES_ON(pAd)) - { - AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE); - } - } - } - - pRxBlk->pData = (UCHAR *)pHeader; - - // - // update RxBlk->pData, DataSize - // 802.11 Header, QOS, HTC, Hw Padding - // - - // 1. skip 802.11 HEADER - { - pRxBlk->pData += LENGTH_802_11; - pRxBlk->DataSize -= LENGTH_802_11; - } - - // 2. QOS - if (pHeader->FC.SubType & 0x08) - { - RX_BLK_SET_FLAG(pRxBlk, fRX_QOS); - UserPriority = *(pRxBlk->pData) & 0x0f; - // bit 7 in QoS Control field signals the HT A-MSDU format - if ((*pRxBlk->pData) & 0x80) - { - RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU); - } - - // skip QOS contorl field - pRxBlk->pData += 2; - pRxBlk->DataSize -=2; - } - pRxBlk->UserPriority = UserPriority; - - /* check if need to resend PS Poll when received packet with MoreData = 1 */ - if ((pAd->StaCfg.Psm == PWR_SAVE) && (pHeader->FC.MoreData == 1)) - { - if ((((UserPriority == 0) || (UserPriority == 3)) && - pAd->CommonCfg.bAPSDAC_BE == 0) || - (((UserPriority == 1) || (UserPriority == 2)) && - pAd->CommonCfg.bAPSDAC_BK == 0) || - (((UserPriority == 4) || (UserPriority == 5)) && - pAd->CommonCfg.bAPSDAC_VI == 0) || - (((UserPriority == 6) || (UserPriority == 7)) && - pAd->CommonCfg.bAPSDAC_VO == 0)) - { - /* non-UAPSD delivery-enabled AC */ - RTMP_PS_POLL_ENQUEUE(pAd); - } - } - - // 3. Order bit: A-Ralink or HTC+ - if (pHeader->FC.Order) - { -#ifdef AGGREGATION_SUPPORT - if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))) - { - RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK); - } - else -#endif // AGGREGATION_SUPPORT // - { -#ifdef DOT11_N_SUPPORT - RX_BLK_SET_FLAG(pRxBlk, fRX_HTC); - // skip HTC contorl field - pRxBlk->pData += 4; - pRxBlk->DataSize -= 4; -#endif // DOT11_N_SUPPORT // - } - } - - // 4. skip HW padding - if (pRxD->L2PAD) - { - // just move pData pointer - // because DataSize excluding HW padding - RX_BLK_SET_FLAG(pRxBlk, fRX_PAD); - pRxBlk->pData += 2; - } - -#ifdef DOT11_N_SUPPORT - if (pRxD->BA) - { - RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU); - } -#endif // DOT11_N_SUPPORT // - - - // - // Case I Process Broadcast & Multicast data frame - // - if (pRxD->Bcast || pRxD->Mcast) - { - INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount); - - // Drop Mcast/Bcast frame with fragment bit on - if (pHeader->FC.MoreFrag) - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); - return; - } - - // Filter out Bcast frame which AP relayed for us - if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) - { - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); - return; - } - - Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); - return; - } - else if (pRxD->U2M) - { - pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ; - - -#ifdef QOS_DLS_SUPPORT - if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS)) - { - MAC_TABLE_ENTRY *pDlsEntry = NULL; - - pDlsEntry = DlsEntryTableLookupByWcid(pAd, pRxWI->WirelessCliID, pHeader->Addr2, TRUE); - if(pDlsEntry) - Update_Rssi_Sample(pAd, &pDlsEntry->RssiSample, pRxWI); - } - else -#endif // QOS_DLS_SUPPORT // - if (ADHOC_ON(pAd)) - { - pEntry = MacTableLookup(pAd, pHeader->Addr2); - if (pEntry) - Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI); - } - - - Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI); - - pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0); - pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1); - - pAd->RalinkCounters.OneSecRxOkDataCnt++; - - - if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0))) - { - // re-assemble the fragmented packets - // return complete frame (pRxPacket) or NULL - bFragment = TRUE; - pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk); - } - - if (pRxPacket) - { - pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; - - // process complete frame - if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled)) - { - // Minus MIC length - pRxBlk->DataSize -= 8; - - // For TKIP frame, calculate the MIC value - if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE) - { - return; - } - } - - STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID); - return; - } - else - { - // just return - // because RTMPDeFragmentDataFrame() will release rx packet, - // if packet is fragmented - return; - } - } - - ASSERT(0); - // release packet - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); -} - -VOID STAHandleRxMgmtFrame( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk) -{ - PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); - PRXWI_STRUC pRxWI = pRxBlk->pRxWI; - PHEADER_802_11 pHeader = pRxBlk->pHeader; - PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; - - do - { - - - /* check if need to resend PS Poll when received packet with MoreData = 1 */ - if ((pAd->StaCfg.Psm == PWR_SAVE) && (pHeader->FC.MoreData == 1)) - { - /* for UAPSD, all management frames will be VO priority */ - if (pAd->CommonCfg.bAPSDAC_VO == 0) - { - /* non-UAPSD delivery-enabled AC */ - RTMP_PS_POLL_ENQUEUE(pAd); - } - } - - /* TODO: if MoreData == 0, station can go to sleep */ - - - // We should collect RSSI not only U2M data but also my beacon - if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)) - && (pAd->RxAnt.EvaluatePeriod == 0)) - { - Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI); - - pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0); - pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1); - } - -#ifdef RT30xx -#ifdef ANT_DIVERSITY_SUPPORT - // collect rssi information for antenna diversity - if ((pAd->NicConfig2.field.AntDiversity) && - (pAd->CommonCfg.bRxAntDiversity != ANT_DIVERSITY_DISABLE)) - { - if ((pRxD->U2M) || ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))) - { - COLLECT_RX_ANTENNA_AVERAGE_RSSI(pAd, ConvertToRssi(pAd, (UCHAR)pRxWI->RSSI0, RSSI_0), 0); //Note: RSSI2 not used on RT73 - pAd->StaCfg.NumOfAvgRssiSample ++; - } - } -#endif // ANT_DIVERSITY_SUPPORT // -#endif // RT30xx // - - // First check the size, it MUST not exceed the mlme queue size - if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE) - { - DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount)); - break; - } - - REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount, - pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal); - } while (FALSE); - - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); -} - -VOID STAHandleRxControlFrame( - IN PRTMP_ADAPTER pAd, - IN RX_BLK *pRxBlk) -{ -#ifdef DOT11_N_SUPPORT - PRXWI_STRUC pRxWI = pRxBlk->pRxWI; -#endif // DOT11_N_SUPPORT // - PHEADER_802_11 pHeader = pRxBlk->pHeader; - PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; - - switch (pHeader->FC.SubType) - { - case SUBTYPE_BLOCK_ACK_REQ: -#ifdef DOT11_N_SUPPORT - { - CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader); - } - break; -#endif // DOT11_N_SUPPORT // - case SUBTYPE_BLOCK_ACK: - case SUBTYPE_ACK: - default: - break; - } - - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); -} - - -/* - ======================================================================== - - Routine Description: - Process RxDone interrupt, running in DPC level - - Arguments: - pAd Pointer to our adapter - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - This routine has to maintain Rx ring read pointer. - Need to consider QOS DATA format when converting to 802.3 - ======================================================================== -*/ -BOOLEAN STARxDoneInterruptHandle( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN argc) -{ - NDIS_STATUS Status; - UINT32 RxProcessed, RxPending; - BOOLEAN bReschedule = FALSE; - RT28XX_RXD_STRUC *pRxD; - UCHAR *pData; - PRXWI_STRUC pRxWI; - PNDIS_PACKET pRxPacket; - PHEADER_802_11 pHeader; - RX_BLK RxCell; - - RxProcessed = RxPending = 0; - - // process whole rx ring - while (1) - { - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF | - fRTMP_ADAPTER_RESET_IN_PROGRESS | - fRTMP_ADAPTER_HALT_IN_PROGRESS | - fRTMP_ADAPTER_NIC_NOT_EXIST) || - !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP)) - { - break; - } - -#ifdef RTMP_MAC_PCI - if (RxProcessed++ > MAX_RX_PROCESS_CNT) - { - // need to reschedule rx handle - bReschedule = TRUE; - break; - } -#endif // RTMP_MAC_PCI // - - RxProcessed ++; // test - - // 1. allocate a new data packet into rx ring to replace received packet - // then processing the received packet - // 2. the callee must take charge of release of packet - // 3. As far as driver is concerned , - // the rx packet must - // a. be indicated to upper layer or - // b. be released if it is discarded - pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending); - if (pRxPacket == NULL) - { - // no more packet to process - break; - } - - // get rx ring descriptor - pRxD = &(RxCell.RxD); - // get rx data buffer - pData = GET_OS_PKT_DATAPTR(pRxPacket); - pRxWI = (PRXWI_STRUC) pData; - pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ; - -#ifdef RT_BIG_ENDIAN - RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE); - RTMPWIEndianChange((PUCHAR)pRxWI, TYPE_RXWI); -#endif - - // build RxCell - RxCell.pRxWI = pRxWI; - RxCell.pHeader = pHeader; - RxCell.pRxPacket = pRxPacket; - RxCell.pData = (UCHAR *) pHeader; - RxCell.DataSize = pRxWI->MPDUtotalByteCount; - RxCell.Flags = 0; - - // Increase Total receive byte counter after real data received no mater any error or not - pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount; - pAd->RalinkCounters.OneSecReceivedByteCount += pRxWI->MPDUtotalByteCount; - pAd->RalinkCounters.RxCount ++; - - INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount); - - if (pRxWI->MPDUtotalByteCount < 14) - Status = NDIS_STATUS_FAILURE; - - if (MONITOR_ON(pAd)) - { - send_monitor_packets(pAd, &RxCell); - break; - } - - /* STARxDoneInterruptHandle() is called in rtusb_bulk.c */ -#ifdef RALINK_ATE - if (ATE_ON(pAd)) - { - pAd->ate.RxCntPerSec++; - ATESampleRssi(pAd, pRxWI); -#ifdef RALINK_28xx_QA - if (pAd->ate.bQARxStart == TRUE) - { - /* (*pRxD) has been swapped in GetPacketFromRxRing() */ - ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader); - } -#endif // RALINK_28xx_QA // - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); - continue; - } -#endif // RALINK_ATE // - - // Check for all RxD errors - Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD); - - // Handle the received frame - if (Status == NDIS_STATUS_SUCCESS) - { - switch (pHeader->FC.Type) - { - // CASE I, receive a DATA frame - case BTYPE_DATA: - { - // process DATA frame - STAHandleRxDataFrame(pAd, &RxCell); - } - break; - // CASE II, receive a MGMT frame - case BTYPE_MGMT: - { - STAHandleRxMgmtFrame(pAd, &RxCell); - } - break; - // CASE III. receive a CNTL frame - case BTYPE_CNTL: - { - STAHandleRxControlFrame(pAd, &RxCell); - } - break; - // discard other type - default: - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); - break; - } - } - else - { - pAd->Counters8023.RxErrors++; - // discard this frame - RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); - } - } - - return bReschedule; -} - -/* - ======================================================================== - - Routine Description: - Arguments: - pAd Pointer to our adapter - - IRQL = DISPATCH_LEVEL - - ======================================================================== -*/ -VOID RTMPHandleTwakeupInterrupt( - IN PRTMP_ADAPTER pAd) -{ - AsicForceWakeup(pAd, FALSE); -} - -/* -======================================================================== -Routine Description: - Early checking and OS-depened parsing for Tx packet send to our STA driver. - -Arguments: - NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd. - PPNDIS_PACKET ppPacketArray The packet array need to do transmission. - UINT NumberOfPackets Number of packet in packet array. - -Return Value: - NONE - -Note: - This function do early checking and classification for send-out packet. - You only can put OS-depened & STA related code in here. -======================================================================== -*/ -VOID STASendPackets( - IN NDIS_HANDLE MiniportAdapterContext, - IN PPNDIS_PACKET ppPacketArray, - IN UINT NumberOfPackets) -{ - UINT Index; - PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext; - PNDIS_PACKET pPacket; - BOOLEAN allowToSend = FALSE; - - - for (Index = 0; Index < NumberOfPackets; Index++) - { - pPacket = ppPacketArray[Index]; - - do - { - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || - RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) - { - // Drop send request since hardware is in reset state - break; - } - else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd)) - { - // Drop send request since there are no physical connection yet - break; - } - else - { - // Record that orignal packet source is from NDIS layer,so that - // later on driver knows how to release this NDIS PACKET -#ifdef QOS_DLS_SUPPORT - MAC_TABLE_ENTRY *pEntry; - PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); - - pEntry = MacTableLookup(pAd, pSrcBufVA); - if (pEntry && (pEntry->ValidAsDls == TRUE)) - { - RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid); - } - else -#endif // QOS_DLS_SUPPORT // - RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode - RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); - NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING); - pAd->RalinkCounters.PendingNdisPacketCount++; - - allowToSend = TRUE; - } - } while(FALSE); - - if (allowToSend == TRUE) - STASendPacket(pAd, pPacket); - else - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - } - - // Dequeue outgoing frames from TxSwQueue[] and process it - RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); - -} - - -/* -======================================================================== -Routine Description: - This routine is used to do packet parsing and classification for Tx packet - to STA device, and it will en-queue packets to our TxSwQueue depends on AC - class. - -Arguments: - pAd Pointer to our adapter - pPacket Pointer to send packet - -Return Value: - NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue. - NDIS_STATUS_FAILURE If failed to do en-queue. - -Note: - You only can put OS-indepened & STA related code in here. -======================================================================== -*/ -NDIS_STATUS STASendPacket( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket) -{ - PACKET_INFO PacketInfo; - PUCHAR pSrcBufVA; - UINT SrcBufLen; - UINT AllowFragSize; - UCHAR NumberOfFrag; - UCHAR RTSRequired; - UCHAR QueIdx, UserPriority; - MAC_TABLE_ENTRY *pEntry = NULL; - unsigned int IrqFlags; - UCHAR FlgIsIP = 0; - UCHAR Rate; - - // Prepare packet information structure for buffer descriptor - // chained within a single NDIS packet. - RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); - - if (pSrcBufVA == NULL) - { - DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen)); - // Resourece is low, system did not allocate virtual address - // return NDIS_STATUS_FAILURE directly to upper layer - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - return NDIS_STATUS_FAILURE; - } - - - if (SrcBufLen < 14) - { - DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n")); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - return (NDIS_STATUS_FAILURE); - } - - // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry. - // Note multicast packets in adhoc also use BSSID_WCID index. - { - if(INFRA_ON(pAd)) - { -#ifdef QOS_DLS_SUPPORT - USHORT tmpWcid; - - tmpWcid = RTMP_GET_PACKET_WCID(pPacket); - if (VALID_WCID(tmpWcid) && - (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE)) - { - pEntry = &pAd->MacTab.Content[tmpWcid]; - Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate; - } - else -#endif // QOS_DLS_SUPPORT // - { - pEntry = &pAd->MacTab.Content[BSSID_WCID]; - RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID); - Rate = pAd->CommonCfg.TxRate; - } - } - else if (ADHOC_ON(pAd)) - { - if (*pSrcBufVA & 0x01) - { - RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID); - pEntry = &pAd->MacTab.Content[MCAST_WCID]; - } - else - { - pEntry = MacTableLookup(pAd, pSrcBufVA); - } - Rate = pAd->CommonCfg.TxRate; - } - } - - if (!pEntry) - { - DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA))); - // Resourece is low, system did not allocate virtual address - // return NDIS_STATUS_FAILURE directly to upper layer - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - return NDIS_STATUS_FAILURE; - } - - if (ADHOC_ON(pAd) - ) - { - RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid); - } - - // - // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags. - // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL). - RTMPCheckEtherType(pAd, pPacket); - - - - // - // WPA 802.1x secured port control - drop all non-802.1x frame before port secured - // - if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) -#ifdef WPA_SUPPLICANT_SUPPORT - || (pAd->StaCfg.IEEE8021X == TRUE) -#endif // WPA_SUPPLICANT_SUPPORT // - ) - && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2)) - && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE) - ) - { - DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n")); - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - - return (NDIS_STATUS_FAILURE); - } - - - // STEP 1. Decide number of fragments required to deliver this MSDU. - // The estimation here is not very accurate because difficult to - // take encryption overhead into consideration here. The result - // "NumberOfFrag" is then just used to pre-check if enough free - // TXD are available to hold this MSDU. - - - if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast - NumberOfFrag = 1; - else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) - NumberOfFrag = 1; // Aggregation overwhelms fragmentation - else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED)) - NumberOfFrag = 1; // Aggregation overwhelms fragmentation -#ifdef DOT11_N_SUPPORT - else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD)) - NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation -#endif // DOT11_N_SUPPORT // - else - { - // The calculated "NumberOfFrag" is a rough estimation because of various - // encryption/encapsulation overhead not taken into consideration. This number is just - // used to make sure enough free TXD are available before fragmentation takes place. - // In case the actual required number of fragments of an NDIS packet - // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the - // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of - // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should - // rarely happen and the penalty is just like a TX RETRY fail. Affordable. - - AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; - NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1; - // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size - if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0) - { - NumberOfFrag--; - } - } - - // Save fragment number to Ndis packet reserved field - RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag); - - - // STEP 2. Check the requirement of RTS: - // If multiple fragment required, RTS is required only for the first fragment - // if the fragment size large than RTS threshold - // For RT28xx, Let ASIC send RTS/CTS -// RTMP_SET_PACKET_RTS(pPacket, 0); - if (NumberOfFrag > 1) - RTSRequired = (pAd->CommonCfg.FragmentThreshold > pAd->CommonCfg.RtsThreshold) ? 1 : 0; - else - RTSRequired = (PacketInfo.TotalPacketLength > pAd->CommonCfg.RtsThreshold) ? 1 : 0; - - // Save RTS requirement to Ndis packet reserved field - RTMP_SET_PACKET_RTS(pPacket, RTSRequired); - RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate); - - // - // STEP 3. Traffic classification. outcome = - // - UserPriority = 0; - QueIdx = QID_AC_BE; - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && - CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) - { - USHORT Protocol; - UCHAR LlcSnapLen = 0, Byte0, Byte1; - do - { - // get Ethernet protocol field - Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]); - if (Protocol <= 1500) - { - // get Ethernet protocol field from LLC/SNAP - if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS) - break; - - Protocol = (USHORT)((Byte0 << 8) + Byte1); - LlcSnapLen = 8; - } - - // always AC_BE for non-IP packet - if (Protocol != 0x0800) - break; - - // get IP header - if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS) - break; - - // return AC_BE if packet is not IPv4 - if ((Byte0 & 0xf0) != 0x40) - break; - - FlgIsIP = 1; - UserPriority = (Byte1 & 0xe0) >> 5; - QueIdx = MapUserPriorityToAccessCategory[UserPriority]; - - // TODO: have to check ACM bit. apply TSPEC if ACM is ON - // TODO: downgrade UP & QueIdx before passing ACM - /* - Under WMM ACM control, we dont need to check the bit; - Or when a TSPEC is built for VO but we will change to issue - BA session for BE here, so we will not use BA to send VO packets. - */ - if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx]) - { - UserPriority = 0; - QueIdx = QID_AC_BE; - } - } while (FALSE); - } - - RTMP_SET_PACKET_UP(pPacket, UserPriority); - - - - // Make sure SendTxWait queue resource won't be used by other threads - RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); - if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE) - { - RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); -#ifdef BLOCK_NET_IF - StopNetIfQueue(pAd, QueIdx, pPacket); -#endif // BLOCK_NET_IF // - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - - return NDIS_STATUS_FAILURE; - } - else - { - InsertTailQueueAc(pAd, pEntry, &pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket)); - } - RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); - -#ifdef DOT11_N_SUPPORT - if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&& - IS_HT_STA(pEntry)) - { - //PMAC_TABLE_ENTRY pMacEntry = &pAd->MacTab.Content[BSSID_WCID]; - if (((pEntry->TXBAbitmap & (1<BADeclineBitmap & (1<PortSecured == WPA_802_1X_PORT_SECURED) - // For IOT compatibility, if - // 1. It is Ralink chip or - // 2. It is OPEN or AES mode, - // then BA session can be bulit. - && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) || - (pEntry->WepStatus != Ndis802_11WEPEnabled && pEntry->WepStatus != Ndis802_11Encryption2Enabled)) - ) - { - BAOriSessionSetUp(pAd, pEntry, UserPriority, 0, 10, FALSE); - } - } -#endif // DOT11_N_SUPPORT // - - pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed - return NDIS_STATUS_SUCCESS; -} - - -/* - ======================================================================== - - Routine Description: - This subroutine will scan through releative ring descriptor to find - out avaliable free ring descriptor and compare with request size. - - Arguments: - pAd Pointer to our adapter - QueIdx Selected TX Ring - - Return Value: - NDIS_STATUS_FAILURE Not enough free descriptor - NDIS_STATUS_SUCCESS Enough free descriptor - - IRQL = PASSIVE_LEVEL - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -#ifdef RTMP_MAC_PCI -NDIS_STATUS RTMPFreeTXDRequest( - IN PRTMP_ADAPTER pAd, - IN UCHAR QueIdx, - IN UCHAR NumberRequired, - IN PUCHAR FreeNumberIs) -{ - ULONG FreeNumber = 0; - NDIS_STATUS Status = NDIS_STATUS_FAILURE; - - switch (QueIdx) - { - case QID_AC_BK: - case QID_AC_BE: - case QID_AC_VI: - case QID_AC_VO: - /*case QID_HCCA:*/ - if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx) - FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1; - else - FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1; - - if (FreeNumber >= NumberRequired) - Status = NDIS_STATUS_SUCCESS; - break; - - case QID_MGMT: - if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx) - FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1; - else - FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1; - - if (FreeNumber >= NumberRequired) - Status = NDIS_STATUS_SUCCESS; - break; - - default: - DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx)); - break; - } - *FreeNumberIs = (UCHAR)FreeNumber; - - return (Status); -} -#endif // RTMP_MAC_PCI // - - - -VOID RTMPSendDisassociationFrame( - IN PRTMP_ADAPTER pAd) -{ -} - -VOID RTMPSendNullFrame( - IN PRTMP_ADAPTER pAd, - IN UCHAR TxRate, - IN BOOLEAN bQosNull) -{ - UCHAR NullFrame[48]; - ULONG Length; - PHEADER_802_11 pHeader_802_11; - - -#ifdef RALINK_ATE - if(ATE_ON(pAd)) - { - return; - } -#endif // RALINK_ATE // - - // WPA 802.1x secured port control - if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) -#ifdef WPA_SUPPLICANT_SUPPORT - || (pAd->StaCfg.IEEE8021X == TRUE) -#endif - ) && - (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) - { - return; - } - - NdisZeroMemory(NullFrame, 48); - Length = sizeof(HEADER_802_11); - - pHeader_802_11 = (PHEADER_802_11) NullFrame; - - pHeader_802_11->FC.Type = BTYPE_DATA; - pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC; - pHeader_802_11->FC.ToDs = 1; - COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid); - COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); - COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); - - if (pAd->CommonCfg.bAPSDForcePowerSave) - { - pHeader_802_11->FC.PwrMgmt = PWR_SAVE; - } - else - { - pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0; - } - pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14); - - pAd->Sequence++; - pHeader_802_11->Sequence = pAd->Sequence; - - // Prepare QosNull function frame - if (bQosNull) - { - pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL; - - // copy QOS control bytes - NullFrame[Length] = 0; - NullFrame[Length+1] = 0; - Length += 2;// if pad with 2 bytes for alignment, APSD will fail - } - - HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length); - -} - -// IRQL = DISPATCH_LEVEL -VOID RTMPSendRTSFrame( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pDA, - IN unsigned int NextMpduSize, - IN UCHAR TxRate, - IN UCHAR RTSRate, - IN USHORT AckDuration, - IN UCHAR QueIdx, - IN UCHAR FrameGap) -{ -} - - - -// -------------------------------------------------------- -// FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM -// Find the WPA key, either Group or Pairwise Key -// LEAP + TKIP also use WPA key. -// -------------------------------------------------------- -// Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst -// In Cisco CCX 2.0 Leap Authentication -// WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey -// Instead of the SharedKey, SharedKey Length may be Zero. -VOID STAFindCipherAlgorithm( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk) -{ - NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet - UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm - UCHAR KeyIdx = 0xff; - PUCHAR pSrcBufVA; - PCIPHER_KEY pKey = NULL; - - pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket); - - { - // Select Cipher - if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) - Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast - else - Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast - - if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) - { - ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128); - - // 4-way handshaking frame must be clear - if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) && - (pAd->SharedKey[BSS0][0].KeyLen)) - { - CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; - KeyIdx = 0; - } - } - else if (Cipher == Ndis802_11Encryption1Enabled) - { - KeyIdx = pAd->StaCfg.DefaultKeyId; - } - else if ((Cipher == Ndis802_11Encryption2Enabled) || - (Cipher == Ndis802_11Encryption3Enabled)) - { - if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast - KeyIdx = pAd->StaCfg.DefaultKeyId; - else if (pAd->SharedKey[BSS0][0].KeyLen) - KeyIdx = 0; - else - KeyIdx = pAd->StaCfg.DefaultKeyId; - } - - if (KeyIdx == 0xff) - CipherAlg = CIPHER_NONE; - else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0)) - CipherAlg = CIPHER_NONE; -#ifdef WPA_SUPPLICANT_SUPPORT - else if ( pAd->StaCfg.WpaSupplicantUP && - (Cipher == Ndis802_11Encryption1Enabled) && - (pAd->StaCfg.IEEE8021X == TRUE) && - (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) - CipherAlg = CIPHER_NONE; -#endif // WPA_SUPPLICANT_SUPPORT // - else - { - //Header_802_11.FC.Wep = 1; - CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; - pKey = &pAd->SharedKey[BSS0][KeyIdx]; - } - } - - pTxBlk->CipherAlg = CipherAlg; - pTxBlk->pKey = pKey; -} - - -VOID STABuildCommon802_11Header( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk) -{ - - HEADER_802_11 *pHeader_802_11; -#ifdef QOS_DLS_SUPPORT - BOOLEAN bDLSFrame = FALSE; - INT DlsEntryIndex = 0; -#endif // QOS_DLS_SUPPORT // - - // - // MAKE A COMMON 802.11 HEADER - // - - // normal wlan header size : 24 octets - pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11); - - pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; - - NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11)); - - pHeader_802_11->FC.FrDs = 0; - pHeader_802_11->FC.Type = BTYPE_DATA; - pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA); - -#ifdef QOS_DLS_SUPPORT - if (INFRA_ON(pAd)) - { - // Check if the frame can be sent through DLS direct link interface - // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) - DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader); - if (DlsEntryIndex >= 0) - bDLSFrame = TRUE; - else - bDLSFrame = FALSE; - } -#endif // QOS_DLS_SUPPORT // - - if (pTxBlk->pMacEntry) - { - if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS)) - { - pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq; - pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ; - } - else - { - { - pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]; - pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; - } - } - } - else - { - pHeader_802_11->Sequence = pAd->Sequence; - pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence - } - - pHeader_802_11->Frag = 0; - - pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); - - { - if (INFRA_ON(pAd)) - { -#ifdef QOS_DLS_SUPPORT - if (bDLSFrame) - { - COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader); - COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); - COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); - pHeader_802_11->FC.ToDs = 0; - } - else -#endif // QOS_DLS_SUPPORT // - { - COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid); - COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); - COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader); - pHeader_802_11->FC.ToDs = 1; - } - } - else if (ADHOC_ON(pAd)) - { - COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader); - COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); - COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); - pHeader_802_11->FC.ToDs = 0; - } - } - - if (pTxBlk->CipherAlg != CIPHER_NONE) - pHeader_802_11->FC.Wep = 1; - - // ----------------------------------------------------------------- - // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. - // ----------------------------------------------------------------- - if (pAd->CommonCfg.bAPSDForcePowerSave) - pHeader_802_11->FC.PwrMgmt = PWR_SAVE; - else - pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); -} - -#ifdef DOT11_N_SUPPORT -VOID STABuildCache802_11Header( - IN RTMP_ADAPTER *pAd, - IN TX_BLK *pTxBlk, - IN UCHAR *pHeader) -{ - MAC_TABLE_ENTRY *pMacEntry; - PHEADER_802_11 pHeader80211; - - pHeader80211 = (PHEADER_802_11)pHeader; - pMacEntry = pTxBlk->pMacEntry; - - // - // Update the cached 802.11 HEADER - // - - // normal wlan header size : 24 octets - pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11); - - // More Bit - pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); - - // Sequence - pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority]; - pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; - - { - // Check if the frame can be sent through DLS direct link interface - // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) -#ifdef QOS_DLS_SUPPORT - BOOLEAN bDLSFrame = FALSE; - INT DlsEntryIndex = 0; - - DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader); - if (DlsEntryIndex >= 0) - bDLSFrame = TRUE; - else - bDLSFrame = FALSE; -#endif // QOS_DLS_SUPPORT // - - // The addr3 of normal packet send from DS is Dest Mac address. -#ifdef QOS_DLS_SUPPORT - if (bDLSFrame) - { - COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader); - COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid); - pHeader80211->FC.ToDs = 0; - } - else -#endif // QOS_DLS_SUPPORT // - if (ADHOC_ON(pAd)) - COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid); - else - COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader); - } - - // ----------------------------------------------------------------- - // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. - // ----------------------------------------------------------------- - if (pAd->CommonCfg.bAPSDForcePowerSave) - pHeader80211->FC.PwrMgmt = PWR_SAVE; - else - pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); -} -#endif // DOT11_N_SUPPORT // - -static inline PUCHAR STA_Build_ARalink_Frame_Header( - IN RTMP_ADAPTER *pAd, - IN TX_BLK *pTxBlk) -{ - PUCHAR pHeaderBufPtr; - HEADER_802_11 *pHeader_802_11; - PNDIS_PACKET pNextPacket; - UINT32 nextBufLen; - PQUEUE_ENTRY pQEntry; - - STAFindCipherAlgorithm(pAd, pTxBlk); - STABuildCommon802_11Header(pAd, pTxBlk); - - - pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; - pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; - - // steal "order" bit to mark "aggregation" - pHeader_802_11->FC.Order = 1; - - // skip common header - pHeaderBufPtr += pTxBlk->MpduHeaderLen; - - if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) - { - // - // build QOS Control bytes - // - *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); - - *(pHeaderBufPtr+1) = 0; - pHeaderBufPtr +=2; - pTxBlk->MpduHeaderLen += 2; - } - - // padding at front of LLC header. LLC header should at 4-bytes aligment. - pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; - pHeaderBufPtr = (PUCHAR)ROUND_UP(pHeaderBufPtr, 4); - pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); - - // For RA Aggregation, - // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format - pQEntry = pTxBlk->TxPacketList.Head; - pNextPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); - nextBufLen = GET_OS_PKT_LEN(pNextPacket); - if (RTMP_GET_PACKET_VLAN(pNextPacket)) - nextBufLen -= LENGTH_802_1Q; - - *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff; - *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8); - - pHeaderBufPtr += 2; - pTxBlk->MpduHeaderLen += 2; - - return pHeaderBufPtr; - -} - -#ifdef DOT11_N_SUPPORT -static inline PUCHAR STA_Build_AMSDU_Frame_Header( - IN RTMP_ADAPTER *pAd, - IN TX_BLK *pTxBlk) -{ - PUCHAR pHeaderBufPtr;//, pSaveBufPtr; - HEADER_802_11 *pHeader_802_11; - - - STAFindCipherAlgorithm(pAd, pTxBlk); - STABuildCommon802_11Header(pAd, pTxBlk); - - pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; - pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; - - // skip common header - pHeaderBufPtr += pTxBlk->MpduHeaderLen; - - // - // build QOS Control bytes - // - *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); - - // - // A-MSDU packet - // - *pHeaderBufPtr |= 0x80; - - *(pHeaderBufPtr+1) = 0; - pHeaderBufPtr +=2; - pTxBlk->MpduHeaderLen += 2; - - //pSaveBufPtr = pHeaderBufPtr; - - // - // padding at front of LLC header - // LLC header should locate at 4-octets aligment - // - // @@@ MpduHeaderLen excluding padding @@@ - // - pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; - pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4); - pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); - - return pHeaderBufPtr; - -} - - -VOID STA_AMPDU_Frame_Tx( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk) -{ - HEADER_802_11 *pHeader_802_11; - PUCHAR pHeaderBufPtr; - USHORT FreeNumber; - MAC_TABLE_ENTRY *pMacEntry; - BOOLEAN bVLANPkt; - PQUEUE_ENTRY pQEntry; - - ASSERT(pTxBlk); - - while(pTxBlk->TxPacketList.Head) - { - pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); - pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); - if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) - { - RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); - continue; - } - - bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); - - pMacEntry = pTxBlk->pMacEntry; - if (pMacEntry->isCached) - { - // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!! - NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11)); - pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]); - STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr); - } - else - { - STAFindCipherAlgorithm(pAd, pTxBlk); - STABuildCommon802_11Header(pAd, pTxBlk); - - pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; - } - - - pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; - - // skip common header - pHeaderBufPtr += pTxBlk->MpduHeaderLen; - - // - // build QOS Control bytes - // - *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); - *(pHeaderBufPtr+1) = 0; - pHeaderBufPtr +=2; - pTxBlk->MpduHeaderLen += 2; - - // - // build HTC+ - // HTC control filed following QoS field - // - if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)) - { - if (pMacEntry->isCached == FALSE) - { - // mark HTC bit - pHeader_802_11->FC.Order = 1; - - NdisZeroMemory(pHeaderBufPtr, 4); - *(pHeaderBufPtr+3) |= 0x80; - } - pHeaderBufPtr += 4; - pTxBlk->MpduHeaderLen += 4; - } - - //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE; - ASSERT(pTxBlk->MpduHeaderLen >= 24); - - // skip 802.3 header - pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; - pTxBlk->SrcBufLen -= LENGTH_802_3; - - // skip vlan tag - if (bVLANPkt) - { - pTxBlk->pSrcBufData += LENGTH_802_1Q; - pTxBlk->SrcBufLen -= LENGTH_802_1Q; - } - - // - // padding at front of LLC header - // LLC header should locate at 4-octets aligment - // - // @@@ MpduHeaderLen excluding padding @@@ - // - pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; - pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4); - pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); - - { - - // - // Insert LLC-SNAP encapsulation - 8 octets - // - EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); - if (pTxBlk->pExtraLlcSnapEncap) - { - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); - pHeaderBufPtr += 6; - // get 2 octets (TypeofLen) - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); - pHeaderBufPtr += 2; - pTxBlk->MpduHeaderLen += LENGTH_802_1_H; - } - - } - - if (pMacEntry->isCached) - { - RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); - } - else - { - RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); - - NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf)); - NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]))); - pMacEntry->isCached = TRUE; - } - - // calculate Transmitted AMPDU count and ByteCount - { - pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++; - pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen; - } - - //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); - - HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); - - // - // Kick out Tx - // - if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) - HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); - - pAd->RalinkCounters.KickTxCount++; - pAd->RalinkCounters.OneSecTxDoneCount++; - } - -} - - -VOID STA_AMSDU_Frame_Tx( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk) -{ - PUCHAR pHeaderBufPtr; - USHORT FreeNumber; - USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding. - USHORT totalMPDUSize=0; - UCHAR *subFrameHeader; - UCHAR padding = 0; - USHORT FirstTx = 0, LastTxIdx = 0; - BOOLEAN bVLANPkt; - int frameNum = 0; - PQUEUE_ENTRY pQEntry; - - - ASSERT(pTxBlk); - - ASSERT((pTxBlk->TxPacketList.Number > 1)); - - while(pTxBlk->TxPacketList.Head) - { - pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); - pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); - if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) - { - RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); - continue; - } - - bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); - - // skip 802.3 header - pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; - pTxBlk->SrcBufLen -= LENGTH_802_3; - - // skip vlan tag - if (bVLANPkt) - { - pTxBlk->pSrcBufData += LENGTH_802_1Q; - pTxBlk->SrcBufLen -= LENGTH_802_1Q; - } - - if (frameNum == 0) - { - pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk); - - // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled. - RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); - } - else - { - pHeaderBufPtr = &pTxBlk->HeaderBuf[0]; - padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen); - NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD); - pHeaderBufPtr += padding; - pTxBlk->MpduHeaderLen = padding; - } - - // - // A-MSDU subframe - // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap - // - subFrameHeader = pHeaderBufPtr; - subFramePayloadLen = pTxBlk->SrcBufLen; - - NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12); - - - pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD; - pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD; - - - // - // Insert LLC-SNAP encapsulation - 8 octets - // - EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); - - subFramePayloadLen = pTxBlk->SrcBufLen; - - if (pTxBlk->pExtraLlcSnapEncap) - { - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); - pHeaderBufPtr += 6; - // get 2 octets (TypeofLen) - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); - pHeaderBufPtr += 2; - pTxBlk->MpduHeaderLen += LENGTH_802_1_H; - subFramePayloadLen += LENGTH_802_1_H; - } - - // update subFrame Length field - subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8; - subFrameHeader[13] = subFramePayloadLen & 0xFF; - - totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; - - if (frameNum ==0) - FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); - else - LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); - - frameNum++; - - pAd->RalinkCounters.KickTxCount++; - pAd->RalinkCounters.OneSecTxDoneCount++; - - // calculate Transmitted AMSDU Count and ByteCount - { - pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++; - pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize; - } - - } - - HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx); - HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx); - - // - // Kick out Tx - // - if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) - HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); -} -#endif // DOT11_N_SUPPORT // - -VOID STA_Legacy_Frame_Tx( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk) -{ - HEADER_802_11 *pHeader_802_11; - PUCHAR pHeaderBufPtr; - USHORT FreeNumber; - BOOLEAN bVLANPkt; - PQUEUE_ENTRY pQEntry; - - ASSERT(pTxBlk); - - - pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); - pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); - if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) - { - RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); - return; - } - - if (pTxBlk->TxFrameType == TX_MCAST_FRAME) - { - INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount); - } - - if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket)) - TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired); - else - TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired); - - bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); - - if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate) - pTxBlk->TxRate = pAd->CommonCfg.MinTxRate; - - STAFindCipherAlgorithm(pAd, pTxBlk); - STABuildCommon802_11Header(pAd, pTxBlk); - - - // skip 802.3 header - pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; - pTxBlk->SrcBufLen -= LENGTH_802_3; - - // skip vlan tag - if (bVLANPkt) - { - pTxBlk->pSrcBufData += LENGTH_802_1Q; - pTxBlk->SrcBufLen -= LENGTH_802_1Q; - } - - pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; - pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; - - // skip common header - pHeaderBufPtr += pTxBlk->MpduHeaderLen; - - if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) - { - // - // build QOS Control bytes - // - *(pHeaderBufPtr) = ((pTxBlk->UserPriority & 0x0F) | (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx]<<5)); - *(pHeaderBufPtr+1) = 0; - pHeaderBufPtr +=2; - pTxBlk->MpduHeaderLen += 2; - } - - // The remaining content of MPDU header should locate at 4-octets aligment - pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; - pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4); - pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); - - { - - // - // Insert LLC-SNAP encapsulation - 8 octets - // - // - // if original Ethernet frame contains no LLC/SNAP, - // then an extra LLC/SNAP encap is required - // - EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap); - if (pTxBlk->pExtraLlcSnapEncap) - { - UCHAR vlan_size; - - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); - pHeaderBufPtr += 6; - // skip vlan tag - vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; - // get 2 octets (TypeofLen) - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2); - pHeaderBufPtr += 2; - pTxBlk->MpduHeaderLen += LENGTH_802_1_H; - } - - } - - // - // prepare for TXWI - // use Wcid as Key Index - // - - RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); - - //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); - - HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); - - pAd->RalinkCounters.KickTxCount++; - pAd->RalinkCounters.OneSecTxDoneCount++; - - // - // Kick out Tx - // - if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) - HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); -} - - -VOID STA_ARalink_Frame_Tx( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk) -{ - PUCHAR pHeaderBufPtr; - USHORT FreeNumber; - USHORT totalMPDUSize=0; - USHORT FirstTx, LastTxIdx; - int frameNum = 0; - BOOLEAN bVLANPkt; - PQUEUE_ENTRY pQEntry; - - - ASSERT(pTxBlk); - - ASSERT((pTxBlk->TxPacketList.Number== 2)); - - - FirstTx = LastTxIdx = 0; // Is it ok init they as 0? - while(pTxBlk->TxPacketList.Head) - { - pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); - pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); - - if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) - { - RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); - continue; - } - - bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); - - // skip 802.3 header - pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; - pTxBlk->SrcBufLen -= LENGTH_802_3; - - // skip vlan tag - if (bVLANPkt) - { - pTxBlk->pSrcBufData += LENGTH_802_1Q; - pTxBlk->SrcBufLen -= LENGTH_802_1Q; - } - - if (frameNum == 0) - { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header - - pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk); - - // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount - // will be updated after final frame was handled. - RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); - - - // - // Insert LLC-SNAP encapsulation - 8 octets - // - EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); - - if (pTxBlk->pExtraLlcSnapEncap) - { - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); - pHeaderBufPtr += 6; - // get 2 octets (TypeofLen) - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); - pHeaderBufPtr += 2; - pTxBlk->MpduHeaderLen += LENGTH_802_1_H; - } - } - else - { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0. - - pHeaderBufPtr = &pTxBlk->HeaderBuf[0]; - pTxBlk->MpduHeaderLen = 0; - - // A-Ralink sub-sequent frame header is the same as 802.3 header. - // DA(6)+SA(6)+FrameType(2) - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12); - pHeaderBufPtr += 12; - // get 2 octets (TypeofLen) - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); - pHeaderBufPtr += 2; - pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD; - } - - totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; - - //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); - if (frameNum ==0) - FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); - else - LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); - - frameNum++; - - pAd->RalinkCounters.OneSecTxAggregationCount++; - pAd->RalinkCounters.KickTxCount++; - pAd->RalinkCounters.OneSecTxDoneCount++; - - } - - HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx); - HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx); - - // - // Kick out Tx - // - if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) - HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); - -} - - -VOID STA_Fragment_Frame_Tx( - IN RTMP_ADAPTER *pAd, - IN TX_BLK *pTxBlk) -{ - HEADER_802_11 *pHeader_802_11; - PUCHAR pHeaderBufPtr; - USHORT FreeNumber; - UCHAR fragNum = 0; - PACKET_INFO PacketInfo; - USHORT EncryptionOverhead = 0; - UINT32 FreeMpduSize, SrcRemainingBytes; - USHORT AckDuration; - UINT NextMpduSize; - BOOLEAN bVLANPkt; - PQUEUE_ENTRY pQEntry; - HTTRANSMIT_SETTING *pTransmit; - - - ASSERT(pTxBlk); - - pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); - pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); - if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) - { - RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); - return; - } - - ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag)); - bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); - - STAFindCipherAlgorithm(pAd, pTxBlk); - STABuildCommon802_11Header(pAd, pTxBlk); - - if (pTxBlk->CipherAlg == CIPHER_TKIP) - { - pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket); - if (pTxBlk->pPacket == NULL) - return; - RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); - } - - // skip 802.3 header - pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; - pTxBlk->SrcBufLen -= LENGTH_802_3; - - - // skip vlan tag - if (bVLANPkt) - { - pTxBlk->pSrcBufData += LENGTH_802_1Q; - pTxBlk->SrcBufLen -= LENGTH_802_1Q; - } - - pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; - pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr; - - - // skip common header - pHeaderBufPtr += pTxBlk->MpduHeaderLen; - - if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) - { - // - // build QOS Control bytes - // - *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); - - *(pHeaderBufPtr+1) = 0; - pHeaderBufPtr +=2; - pTxBlk->MpduHeaderLen += 2; - } - - // - // padding at front of LLC header - // LLC header should locate at 4-octets aligment - // - pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; - pHeaderBufPtr = (PUCHAR) ROUND_UP(pHeaderBufPtr, 4); - pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); - - - - // - // Insert LLC-SNAP encapsulation - 8 octets - // - // - // if original Ethernet frame contains no LLC/SNAP, - // then an extra LLC/SNAP encap is required - // - EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap); - if (pTxBlk->pExtraLlcSnapEncap) - { - UCHAR vlan_size; - - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); - pHeaderBufPtr += 6; - // skip vlan tag - vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; - // get 2 octets (TypeofLen) - NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2); - pHeaderBufPtr += 2; - pTxBlk->MpduHeaderLen += LENGTH_802_1_H; - } - - - // If TKIP is used and fragmentation is required. Driver has to - // append TKIP MIC at tail of the scatter buffer - // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC - if (pTxBlk->CipherAlg == CIPHER_TKIP) - { - RTMPCalculateMICValue(pAd, pTxBlk->pPacket, pTxBlk->pExtraLlcSnapEncap, pTxBlk->pKey, 0); - - // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust - // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress. - NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8); - //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8); - pTxBlk->SrcBufLen += 8; - pTxBlk->TotalFrameLen += 8; - pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC; - } - - // - // calcuate the overhead bytes that encryption algorithm may add. This - // affects the calculate of "duration" field - // - if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128)) - EncryptionOverhead = 8; //WEP: IV[4] + ICV[4]; - else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC) - EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength - else if (pTxBlk->CipherAlg == CIPHER_TKIP) - EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8] - else if (pTxBlk->CipherAlg == CIPHER_AES) - EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8] - else - EncryptionOverhead = 0; - - pTransmit = pTxBlk->pTransmit; - // Decide the TX rate - if (pTransmit->field.MODE == MODE_CCK) - pTxBlk->TxRate = pTransmit->field.MCS; - else if (pTransmit->field.MODE == MODE_OFDM) - pTxBlk->TxRate = pTransmit->field.MCS + RATE_FIRST_OFDM_RATE; - else - pTxBlk->TxRate = RATE_6_5; - - // decide how much time an ACK/CTS frame will consume in the air - if (pTxBlk->TxRate <= RATE_LAST_OFDM_RATE) - AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14); - else - AckDuration = RTMPCalcDuration(pAd, RATE_6_5, 14); - - // Init the total payload length of this frame. - SrcRemainingBytes = pTxBlk->SrcBufLen; - - pTxBlk->TotalFragNum = 0xff; - - do { - - FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC; - - FreeMpduSize -= pTxBlk->MpduHeaderLen; - - if (SrcRemainingBytes <= FreeMpduSize) - { // this is the last or only fragment - - pTxBlk->SrcBufLen = SrcRemainingBytes; - - pHeader_802_11->FC.MoreFrag = 0; - pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration; - - // Indicate the lower layer that this's the last fragment. - pTxBlk->TotalFragNum = fragNum; - } - else - { // more fragment is required - - pTxBlk->SrcBufLen = FreeMpduSize; - - NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold)); - pHeader_802_11->FC.MoreFrag = 1; - pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead); - } - - if (fragNum == 0) - pTxBlk->FrameGap = IFS_HTTXOP; - else - pTxBlk->FrameGap = IFS_SIFS; - - RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); - - HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber); - - pAd->RalinkCounters.KickTxCount++; - pAd->RalinkCounters.OneSecTxDoneCount++; - - // Update the frame number, remaining size of the NDIS packet payload. - - // space for 802.11 header. - if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap) - pTxBlk->MpduHeaderLen -= LENGTH_802_1_H; - - fragNum++; - SrcRemainingBytes -= pTxBlk->SrcBufLen; - pTxBlk->pSrcBufData += pTxBlk->SrcBufLen; - - pHeader_802_11->Frag++; // increase Frag # - - }while(SrcRemainingBytes > 0); - - // - // Kick out Tx - // - if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) - HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); -} - - -#define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \ - while(_pTxBlk->TxPacketList.Head) \ - { \ - _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \ - RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \ - } - - -/* - ======================================================================== - - Routine Description: - Copy frame from waiting queue into relative ring buffer and set - appropriate ASIC register to kick hardware encryption before really - sent out to air. - - Arguments: - pAd Pointer to our adapter - PNDIS_PACKET Pointer to outgoing Ndis frame - NumberOfFrag Number of fragment required - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -NDIS_STATUS STAHardTransmit( - IN PRTMP_ADAPTER pAd, - IN TX_BLK *pTxBlk, - IN UCHAR QueIdx) -{ - NDIS_PACKET *pPacket; - PQUEUE_ENTRY pQEntry; - - // --------------------------------------------- - // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION. - // --------------------------------------------- - // - ASSERT(pTxBlk->TxPacketList.Number); - if (pTxBlk->TxPacketList.Head == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number)); - return NDIS_STATUS_FAILURE; - } - - pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head); - - - // ------------------------------------------------------------------ - // STEP 1. WAKE UP PHY - // outgoing frame always wakeup PHY to prevent frame lost and - // turn off PSM bit to improve performance - // ------------------------------------------------------------------ - // not to change PSM bit, just send this frame out? - if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - DBGPRINT_RAW(RT_DEBUG_INFO, ("AsicForceWakeup At HardTx\n")); -#ifdef RTMP_MAC_PCI - AsicForceWakeup(pAd, TRUE); -#endif // RTMP_MAC_PCI // - } - - // It should not change PSM bit, when APSD turn on. - if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE)) - || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) - || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket))) - { - if ((pAd->StaCfg.Psm == PWR_SAVE) && - (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP)) - RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE); - } - - switch (pTxBlk->TxFrameType) - { -#ifdef DOT11_N_SUPPORT - case TX_AMPDU_FRAME: - STA_AMPDU_Frame_Tx(pAd, pTxBlk); - break; - case TX_AMSDU_FRAME: - STA_AMSDU_Frame_Tx(pAd, pTxBlk); - break; -#endif // DOT11_N_SUPPORT // - case TX_LEGACY_FRAME: - STA_Legacy_Frame_Tx(pAd, pTxBlk); - break; - case TX_MCAST_FRAME: - STA_Legacy_Frame_Tx(pAd, pTxBlk); - break; - case TX_RALINK_FRAME: - STA_ARalink_Frame_Tx(pAd, pTxBlk); - break; - case TX_FRAG_FRAME: - STA_Fragment_Frame_Tx(pAd, pTxBlk); - break; - default: - { - // It should not happened! - DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n")); - while(pTxBlk->TxPacketList.Number) - { - pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); - pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); - if (pPacket) - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - } - } - break; - } - - return (NDIS_STATUS_SUCCESS); - -} - -ULONG HashBytesPolynomial(UCHAR *value, unsigned int len) -{ - unsigned char *word = value; - unsigned int ret = 0; - unsigned int i; - - for(i=0; i < len; i++) - { - int mod = i % 32; - ret ^=(unsigned int) (word[i]) << mod; - ret ^=(unsigned int) (word[i]) >> (32 - mod); - } - return ret; -} - -VOID Sta_Announce_or_Forward_802_3_Packet( - IN PRTMP_ADAPTER pAd, - IN PNDIS_PACKET pPacket, - IN UCHAR FromWhichBSSID) -{ - if (TRUE - ) - { - announce_802_3_packet(pAd, pPacket); - } - else - { - // release packet - RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); - } -} diff --git a/drivers/staging/rt3090/sta/sanity.c b/drivers/staging/rt3090/sta/sanity.c deleted file mode 100644 index aeda15bd5bcaa3f656ddd1da39b03646ee89991e..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/sta/sanity.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - sanity.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - John Chang 2004-09-01 add WMM support -*/ - -#include "../rt_config.h" - - -extern UCHAR CISCO_OUI[]; - -extern UCHAR WPA_OUI[]; -extern UCHAR RSN_OUI[]; -extern UCHAR WME_INFO_ELEM[]; -extern UCHAR WME_PARM_ELEM[]; -extern UCHAR Ccx2QosInfo[]; -extern UCHAR RALINK_OUI[]; -extern UCHAR BROADCOM_OUI[]; - -/* - ========================================================================== - Description: - MLME message sanity check - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== - */ -BOOLEAN MlmeStartReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT CHAR Ssid[], - OUT UCHAR *pSsidLen) -{ - MLME_START_REQ_STRUCT *Info; - - Info = (MLME_START_REQ_STRUCT *)(Msg); - - if (Info->SsidLen > MAX_LEN_OF_SSID) - { - DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqSanity fail - wrong SSID length\n")); - return FALSE; - } - - *pSsidLen = Info->SsidLen; - NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen); - - return TRUE; -} - -/* - ========================================================================== - Description: - MLME message sanity check - Return: - TRUE if all parameters are OK, FALSE otherwise - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -BOOLEAN PeerAssocRspSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *pMsg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT USHORT *pCapabilityInfo, - OUT USHORT *pStatus, - OUT USHORT *pAid, - OUT UCHAR SupRate[], - OUT UCHAR *pSupRateLen, - OUT UCHAR ExtRate[], - OUT UCHAR *pExtRateLen, - OUT HT_CAPABILITY_IE *pHtCapability, - OUT ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE - OUT UCHAR *pHtCapabilityLen, - OUT UCHAR *pAddHtInfoLen, - OUT UCHAR *pNewExtChannelOffset, - OUT PEDCA_PARM pEdcaParm, - OUT UCHAR *pCkipFlag) -{ - CHAR IeType, *Ptr; - PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; - PEID_STRUCT pEid; - ULONG Length = 0; - - *pNewExtChannelOffset = 0xff; - *pHtCapabilityLen = 0; - *pAddHtInfoLen = 0; - COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); - Ptr = (PCHAR)pFrame->Octet; - Length += LENGTH_802_11; - - NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2); - Length += 2; - NdisMoveMemory(pStatus, &pFrame->Octet[2], 2); - Length += 2; - *pCkipFlag = 0; - *pExtRateLen = 0; - pEdcaParm->bValid = FALSE; - - if (*pStatus != MLME_SUCCESS) - return TRUE; - - NdisMoveMemory(pAid, &pFrame->Octet[4], 2); - Length += 2; - - // Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform - *pAid = (*pAid) & 0x3fff; // AID is low 14-bit - - // -- get supported rates from payload and advance the pointer - IeType = pFrame->Octet[6]; - *pSupRateLen = pFrame->Octet[7]; - if ((IeType != IE_SUPP_RATES) || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES)) - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity fail - wrong SupportedRates IE\n")); - return FALSE; - } - else - NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen); - - - Length = Length + 2 + *pSupRateLen; - - // many AP implement proprietary IEs in non-standard order, we'd better - // tolerate mis-ordered IEs to get best compatibility - pEid = (PEID_STRUCT) &pFrame->Octet[8 + (*pSupRateLen)]; - - // get variable fields from payload and advance the pointer - while ((Length + 2 + pEid->Len) <= MsgLen) - { - switch (pEid->Eid) - { - case IE_EXT_SUPP_RATES: - if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) - { - NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); - *pExtRateLen = pEid->Len; - } - break; - - case IE_HT_CAP: - case IE_HT_CAP2: - if (pEid->Len >= SIZE_HT_CAP_IE) //Note: allow extension.!! - { - NdisMoveMemory(pHtCapability, pEid->Octet, SIZE_HT_CAP_IE); - - *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); - *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); - - *pHtCapabilityLen = SIZE_HT_CAP_IE; - } - else - { - DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_HT_CAP. \n")); - } - - break; -#ifdef DOT11_N_SUPPORT - case IE_ADD_HT: - case IE_ADD_HT2: - if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) - { - // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only - // copy first sizeof(ADD_HT_INFO_IE) - NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); - - *(USHORT *)(&pAddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo2)); - *(USHORT *)(&pAddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo3)); - - *pAddHtInfoLen = SIZE_ADD_HT_INFO_IE; - } - else - { - DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_ADD_HT. \n")); - } - - break; - case IE_SECONDARY_CH_OFFSET: - if (pEid->Len == 1) - { - *pNewExtChannelOffset = pEid->Octet[0]; - } - else - { - DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); - } -#endif // DOT11_N_SUPPORT // - break; - - case IE_VENDOR_SPECIFIC: - // handle WME PARAMTER ELEMENT - if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) - { - PUCHAR ptr; - int i; - - // parsing EDCA parameters - pEdcaParm->bValid = TRUE; - pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10; - pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20; - pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40; - //pEdcaParm->bMoreDataAck = FALSE; // pEid->Octet[0] & 0x80; - pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; - pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; - ptr = (PUCHAR)&pEid->Octet[8]; - for (i=0; i<4; i++) - { - UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX - pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); // b5 is ACM - pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; // b0~3 is AIFSN - pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; // b0~4 is Cwmin - pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; // b5~8 is Cwmax - pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us - ptr += 4; // point to next AC - } - } - break; - default: - DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity - ignore unrecognized EID = %d\n", pEid->Eid)); - break; - } - - Length = Length + 2 + pEid->Len; - pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); - } - - - return TRUE; -} - -/* - ========================================================================== - Description: - MLME message sanity check - Return: - TRUE if all parameters are OK, FALSE otherwise - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -BOOLEAN PeerProbeReqSanity( - IN PRTMP_ADAPTER pAd, - IN VOID *Msg, - IN ULONG MsgLen, - OUT PUCHAR pAddr2, - OUT CHAR Ssid[], - OUT UCHAR *pSsidLen) -{ - UCHAR Idx; - UCHAR RateLen; - CHAR IeType; - PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; - - COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); - - if ((pFrame->Octet[0] != IE_SSID) || (pFrame->Octet[1] > MAX_LEN_OF_SSID)) - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SSID IE(Type=%d,Len=%d)\n",pFrame->Octet[0],pFrame->Octet[1])); - return FALSE; - } - - *pSsidLen = pFrame->Octet[1]; - NdisMoveMemory(Ssid, &pFrame->Octet[2], *pSsidLen); - - Idx = *pSsidLen + 2; - - // -- get supported rates from payload and advance the pointer - IeType = pFrame->Octet[Idx]; - RateLen = pFrame->Octet[Idx + 1]; - if (IeType != IE_SUPP_RATES) - { - DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SupportRates IE(Type=%d,Len=%d)\n",pFrame->Octet[Idx],pFrame->Octet[Idx+1])); - return FALSE; - } - else - { - if ((pAd->CommonCfg.PhyMode == PHY_11G) && (RateLen < 8)) - return (FALSE); - } - - return TRUE; -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -BOOLEAN GetTimBit( - IN CHAR *Ptr, - IN USHORT Aid, - OUT UCHAR *TimLen, - OUT UCHAR *BcastFlag, - OUT UCHAR *DtimCount, - OUT UCHAR *DtimPeriod, - OUT UCHAR *MessageToMe) -{ - UCHAR BitCntl, N1, N2, MyByte, MyBit; - CHAR *IdxPtr; - - IdxPtr = Ptr; - - IdxPtr ++; - *TimLen = *IdxPtr; - - // get DTIM Count from TIM element - IdxPtr ++; - *DtimCount = *IdxPtr; - - // get DTIM Period from TIM element - IdxPtr++; - *DtimPeriod = *IdxPtr; - - // get Bitmap Control from TIM element - IdxPtr++; - BitCntl = *IdxPtr; - - if ((*DtimCount == 0) && (BitCntl & 0x01)) - *BcastFlag = TRUE; - else - *BcastFlag = FALSE; - - // Parse Partial Virtual Bitmap from TIM element - N1 = BitCntl & 0xfe; // N1 is the first bitmap byte# - N2 = *TimLen - 4 + N1; // N2 is the last bitmap byte# - - if ((Aid < (N1 << 3)) || (Aid >= ((N2 + 1) << 3))) - *MessageToMe = FALSE; - else - { - MyByte = (Aid >> 3) - N1; // my byte position in the bitmap byte-stream - MyBit = Aid % 16 - ((MyByte & 0x01)? 8:0); - - IdxPtr += (MyByte + 1); - - //if (*IdxPtr) - // DBGPRINT(RT_DEBUG_WARN, ("TIM bitmap = 0x%02x\n", *IdxPtr)); - - if (*IdxPtr & (0x01 << MyBit)) - *MessageToMe = TRUE; - else - *MessageToMe = FALSE; - } - - return TRUE; -} diff --git a/drivers/staging/rt3090/sta/sync.c b/drivers/staging/rt3090/sta/sync.c deleted file mode 100644 index 2520e038cb82b2d98e2c3a621fda0d73be41da8f..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/sta/sync.c +++ /dev/null @@ -1,1840 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - sync.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - John Chang 2004-09-01 modified for rt2561/2661 - Jan Lee 2006-08-01 modified for rt2860 for 802.11n -*/ - -#include "../rt_config.h" - - -#define ADHOC_ENTRY_BEACON_LOST_TIME (2*OS_HZ) // 2 sec - -/* - ========================================================================== - Description: - The sync state machine, - Parameters: - Sm - pointer to the state machine - Note: - the state machine looks like the following - - ========================================================================== - */ -VOID SyncStateMachineInit( - IN PRTMP_ADAPTER pAd, - IN STATE_MACHINE *Sm, - OUT STATE_MACHINE_FUNC Trans[]) -{ - StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, SYNC_IDLE, SYNC_MACHINE_BASE); - - // column 1 - StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction); - StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction); - StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)MlmeStartReqAction); - StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon); - StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)PeerProbeReqAction); - - //column 2 - StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan); - StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin); - StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart); - StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtJoinAction); - StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, (STATE_MACHINE_FUNC)BeaconTimeoutAtJoinAction); - - // column 3 - StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan); - StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin); - StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart); - StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction); - StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction); - StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)ScanTimeoutAction); - - // timer init - RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE); - RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE); -} - -/* - ========================================================================== - Description: - Beacon timeout handler, executed in timer thread - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID BeaconTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; - - DBGPRINT(RT_DEBUG_TRACE,("SYNC - BeaconTimeout\n")); - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) - return; - -#ifdef DOT11_N_SUPPORT - if ((pAd->CommonCfg.BBPCurrentBW == BW_40) - ) - { - UCHAR BBPValue = 0; - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue &= (~0x18); - BBPValue |= 0x10; - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); - } -#endif // DOT11_N_SUPPORT // - - MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL); - RTMP_MLME_HANDLER(pAd); -} - -/* - ========================================================================== - Description: - Scan timeout handler, executed in timer thread - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID ScanTimeout( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; - - - // Do nothing if the driver is starting halt state. - // This might happen when timer already been fired before cancel timer with mlmehalt - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) - return; - - if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL)) - { - RTMP_MLME_HANDLER(pAd); -} - else - { - // To prevent SyncMachine.CurrState is SCAN_LISTEN forever. - pAd->MlmeAux.Channel = 0; - ScanNextChannel(pAd); - if (pAd->CommonCfg.bWirelessEvent) - { - RTMPSendWirelessEvent(pAd, IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - } - } -} - -/* - ========================================================================== - Description: - MLME SCAN req state machine procedure - ========================================================================== - */ -VOID MlmeScanReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0; - BOOLEAN TimerCancelled; - ULONG Now; - USHORT Status; - PHEADER_802_11 pHdr80211; - PUCHAR pOutBuffer = NULL; - NDIS_STATUS NStatus; - - // Check the total scan tries for one single OID command - // If this is the CCX 2.0 Case, skip that! - if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) - { - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n")); - return; - } - - // Increase the scan retry counters. - pAd->StaCfg.ScanCnt++; - -#ifdef RTMP_MAC_PCI - if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) && - (IDLE_ON(pAd)) && - (pAd->StaCfg.bRadio == TRUE) && - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) - { - if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) - { - AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02); - AsicCheckCommanOk(pAd, PowerWakeCID); - RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); - DBGPRINT(RT_DEBUG_TRACE, ("PSM - Issue Wake up command \n")); - } - else - { - RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); - } - } -#endif // RTMP_MAC_PCI // - - // first check the parameter sanity - if (MlmeScanReqSanity(pAd, - Elem->Msg, - Elem->MsgLen, - &BssType, - (PCHAR)Ssid, - &SsidLen, - &ScanType)) - { - - // Check for channel load and noise hist request - // Suspend MSDU only at scan request, not the last two mentioned - // Suspend MSDU transmission here - RTMPSuspendMsduTransmission(pAd); - - // - // To prevent data lost. - // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. - // And should send an NULL data with turned PSM bit off to AP, when scan progress done - // - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) - { - NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); - if (NStatus == NDIS_STATUS_SUCCESS) - { - pHdr80211 = (PHEADER_802_11) pOutBuffer; - MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); - pHdr80211->Duration = 0; - pHdr80211->FC.Type = BTYPE_DATA; - pHdr80211->FC.PwrMgmt = PWR_SAVE; - - // Send using priority queue - MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); - DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n")); - MlmeFreeMemory(pAd, pOutBuffer); - RTMPusecDelay(5000); - } - } - - NdisGetSystemUpTime(&Now); - pAd->StaCfg.LastScanTime = Now; - // reset all the timers - RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); - RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); - - // record desired BSS parameters - pAd->MlmeAux.BssType = BssType; - pAd->MlmeAux.ScanType = ScanType; - pAd->MlmeAux.SsidLen = SsidLen; - NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); - NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); - - // start from the first channel - pAd->MlmeAux.Channel = FirstChannel(pAd); - - // Let BBP register at 20MHz to do scan - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue &= (~0x18); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); - ScanNextChannel(pAd); - } - else - { - DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n")); - pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; - Status = MLME_INVALID_FORMAT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); - } -} - -/* - ========================================================================== - Description: - MLME JOIN req state machine procedure - ========================================================================== - */ -VOID MlmeJoinReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR BBPValue = 0; - BSS_ENTRY *pBss; - BOOLEAN TimerCancelled; - HEADER_802_11 Hdr80211; - NDIS_STATUS NStatus; - ULONG FrameLen = 0; - PUCHAR pOutBuffer = NULL; - PUCHAR pSupRate = NULL; - UCHAR SupRateLen; - PUCHAR pExtRate = NULL; - UCHAR ExtRateLen; - UCHAR ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C}; - UCHAR ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR); - MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg); - - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx)); - -#ifdef RTMP_MAC_PCI - if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) && - (IDLE_ON(pAd)) && - (pAd->StaCfg.bRadio == TRUE) && - (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) - { - RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); - } -#endif // RTMP_MAC_PCI // - - // reset all the timers - RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); - RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); - - pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx]; - - // record the desired SSID & BSSID we're waiting for - COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid); - - // If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again. - if (pBss->Hidden == 0) - { - RTMPZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); - NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen); - pAd->MlmeAux.SsidLen = pBss->SsidLen; - } - - pAd->MlmeAux.BssType = pBss->BssType; - pAd->MlmeAux.Channel = pBss->Channel; - pAd->MlmeAux.CentralChannel = pBss->CentralChannel; - -#ifdef EXT_BUILD_CHANNEL_LIST - // Country IE of the AP will be evaluated and will be used. - if ((pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None) && - (pBss->bHasCountryIE == TRUE)) - { - NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], &pBss->CountryString[0], 2); - if (pBss->CountryString[2] == 'I') - pAd->CommonCfg.Geography = IDOR; - else if (pBss->CountryString[2] == 'O') - pAd->CommonCfg.Geography = ODOR; - else - pAd->CommonCfg.Geography = BOTH; - BuildChannelListEx(pAd); - } -#endif // EXT_BUILD_CHANNEL_LIST // - - // Let BBP register at 20MHz to do scan - RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); - BBPValue &= (~0x18); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); - - // switch channel and waiting for beacon timer - AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); - AsicLockChannel(pAd, pAd->MlmeAux.Channel); - - - RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT); - - do - { - if (((pAd->CommonCfg.bIEEE80211H == 1) && - (pAd->MlmeAux.Channel > 14) && - RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) -#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier - || (pAd->CommonCfg.CarrierDetect.Enable == TRUE) -#endif // CARRIER_DETECTION_SUPPORT // - ) - { - // - // We can't send any Probe request frame to meet 802.11h. - // - if (pBss->Hidden == 0) - break; - } - - // - // send probe request - // - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); - if (NStatus == NDIS_STATUS_SUCCESS) - { - if (pAd->MlmeAux.Channel <= 14) - { - pSupRate = pAd->CommonCfg.SupRate; - SupRateLen = pAd->CommonCfg.SupRateLen; - pExtRate = pAd->CommonCfg.ExtRate; - ExtRateLen = pAd->CommonCfg.ExtRateLen; - } - else - { - // - // Overwrite Support Rate, CCK rate are not allowed - // - pSupRate = ASupRate; - SupRateLen = ASupRateLen; - ExtRateLen = 0; - } - - if (pAd->MlmeAux.BssType == BSS_INFRA) - MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, pAd->MlmeAux.Bssid); - else - MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &Hdr80211, - 1, &SsidIe, - 1, &pAd->MlmeAux.SsidLen, - pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, - 1, &SupRateIe, - 1, &SupRateLen, - SupRateLen, pSupRate, - END_OF_ARGS); - - if (ExtRateLen) - { - ULONG Tmp; - MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, - 1, &ExtRateIe, - 1, &ExtRateLen, - ExtRateLen, pExtRate, - END_OF_ARGS); - FrameLen += Tmp; - } - - - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - } - } while (FALSE); - - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n", - pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); - - pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON; -} - -/* - ========================================================================== - Description: - MLME START Request state machine procedure, starting an IBSS - ========================================================================== - */ -VOID MlmeStartReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen; - BOOLEAN TimerCancelled; - - // New for WPA security suites - UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 - NDIS_802_11_VARIABLE_IEs *pVIE = NULL; - LARGE_INTEGER TimeStamp; - BOOLEAN Privacy; - USHORT Status; - - // Init Variable IE structure - pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; - pVIE->Length = 0; - TimeStamp.u.LowPart = 0; - TimeStamp.u.HighPart = 0; - - if (MlmeStartReqSanity(pAd, Elem->Msg, Elem->MsgLen, (PCHAR)Ssid, &SsidLen)) - { - // reset all the timers - RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); - RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); - - // - // Start a new IBSS. All IBSS parameters are decided now.... - // - DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n")); - pAd->MlmeAux.BssType = BSS_ADHOC; - NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); - pAd->MlmeAux.SsidLen = SsidLen; - - // generate a radom number as BSSID - MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid); - DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - generate a radom number as BSSID \n")); - - Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || - (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || - (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); - pAd->MlmeAux.CapabilityInfo = CAP_GENERATE(0,1,Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 1, 0); - pAd->MlmeAux.BeaconPeriod = pAd->CommonCfg.BeaconPeriod; - pAd->MlmeAux.AtimWin = pAd->StaCfg.AtimWin; - pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; - - pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; - pAd->MlmeAux.CentralChannel = pAd->CommonCfg.CentralChannel; - - pAd->MlmeAux.SupRateLen= pAd->CommonCfg.SupRateLen; - NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); - RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); - pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen; - NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES); - RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); -#ifdef DOT11_N_SUPPORT - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) - { - RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0], &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo); - pAd->MlmeAux.HtCapabilityLen = sizeof(HT_CAPABILITY_IE); - // Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here. - DBGPRINT(RT_DEBUG_TRACE, ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n")); - } - else -#endif // DOT11_N_SUPPORT // - { - pAd->MlmeAux.HtCapabilityLen = 0; - pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; - NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], 16); - } - // temporarily not support QOS in IBSS - NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM)); - NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); - NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); - - AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); - AsicLockChannel(pAd, pAd->MlmeAux.Channel); - - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n", - pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen)); - - pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; - Status = MLME_SUCCESS; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); - } - else - { - DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n")); - pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; - Status = MLME_INVALID_FORMAT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); - } -} - -/* - ========================================================================== - Description: - peer sends beacon back when scanning - ========================================================================== - */ -VOID PeerBeaconAtScanAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; - UCHAR Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel, - SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe; - CF_PARM CfParm; - USHORT BeaconPeriod, AtimWin, CapabilityInfo; - PFRAME_802_11 pFrame; - LARGE_INTEGER TimeStamp; - UCHAR Erp; - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen, ExtRateLen; - USHORT LenVIE; - UCHAR CkipFlag; - UCHAR AironetCellPowerLimit; - EDCA_PARM EdcaParm; - QBSS_LOAD_PARM QbssLoad; - QOS_CAPABILITY_PARM QosCapability; - ULONG RalinkIe; - UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 - NDIS_802_11_VARIABLE_IEs *pVIE = NULL; - HT_CAPABILITY_IE HtCapability; - ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE - UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0; - UCHAR AddHtInfoLen; - UCHAR NewExtChannelOffset = 0xff; - - - // NdisFillMemory(Ssid, MAX_LEN_OF_SSID, 0x00); - pFrame = (PFRAME_802_11) Elem->Msg; - // Init Variable IE structure - pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; - pVIE->Length = 0; -#ifdef DOT11_N_SUPPORT - RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); - RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); -#endif // DOT11_N_SUPPORT // - - if (PeerBeaconAndProbeRspSanity(pAd, - Elem->Msg, - Elem->MsgLen, - Elem->Channel, - Addr2, - Bssid, - (PCHAR)Ssid, - &SsidLen, - &BssType, - &BeaconPeriod, - &Channel, - &NewChannel, - &TimeStamp, - &CfParm, - &AtimWin, - &CapabilityInfo, - &Erp, - &DtimCount, - &DtimPeriod, - &BcastFlag, - &MessageToMe, - SupRate, - &SupRateLen, - ExtRate, - &ExtRateLen, - &CkipFlag, - &AironetCellPowerLimit, - &EdcaParm, - &QbssLoad, - &QosCapability, - &RalinkIe, - &HtCapabilityLen, - &PreNHtCapabilityLen, - &HtCapability, - &AddHtInfoLen, - &AddHtInfo, - &NewExtChannelOffset, - &LenVIE, - pVIE)) - { - ULONG Idx; - CHAR Rssi = 0; - - Idx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); - if (Idx != BSS_NOT_FOUND) - Rssi = pAd->ScanTab.BssEntry[Idx].Rssi; - - Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); - - -#ifdef DOT11_N_SUPPORT - if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) - HtCapabilityLen = SIZE_HT_CAP_IE; -#endif // DOT11_N_SUPPORT // - - Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, (PCHAR)Ssid, SsidLen, BssType, BeaconPeriod, - &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, - &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag, - &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); -#ifdef DOT11_N_SUPPORT -#ifdef DOT11N_DRAFT3 - if (pAd->ChannelList[pAd->CommonCfg.ChannelListIdx].bEffectedChannel == TRUE) - { - UCHAR RegClass; - PeerBeaconAndProbeRspSanity2(pAd, Elem->Msg, Elem->MsgLen, &RegClass); - TriEventTableSetEntry(pAd, &pAd->CommonCfg.TriggerEventTab, Bssid, &HtCapability, HtCapabilityLen, RegClass, Channel); - } -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // - if (Idx != BSS_NOT_FOUND) - { - NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4); - NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); - NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); - } - - } - // sanity check fail, ignored -} - -/* - ========================================================================== - Description: - When waiting joining the (I)BSS, beacon received from external - ========================================================================== - */ -VOID PeerBeaconAtJoinAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; - UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe, - DtimCount, DtimPeriod, BcastFlag, NewChannel; - LARGE_INTEGER TimeStamp; - USHORT BeaconPeriod, AtimWin, CapabilityInfo; - CF_PARM Cf; - BOOLEAN TimerCancelled; - UCHAR Erp; - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen, ExtRateLen; - UCHAR CkipFlag; - USHORT LenVIE; - UCHAR AironetCellPowerLimit; - EDCA_PARM EdcaParm; - QBSS_LOAD_PARM QbssLoad; - QOS_CAPABILITY_PARM QosCapability; - USHORT Status; - UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 - NDIS_802_11_VARIABLE_IEs *pVIE = NULL; - ULONG RalinkIe; - ULONG Idx; - HT_CAPABILITY_IE HtCapability; - ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE - UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0; - UCHAR AddHtInfoLen; - UCHAR NewExtChannelOffset = 0xff; -#ifdef DOT11_N_SUPPORT - UCHAR CentralChannel; - BOOLEAN bAllowNrate = FALSE; -#endif // DOT11_N_SUPPORT // - - // Init Variable IE structure - pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; - pVIE->Length = 0; - RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); - RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); - - - if (PeerBeaconAndProbeRspSanity(pAd, - Elem->Msg, - Elem->MsgLen, - Elem->Channel, - Addr2, - Bssid, - (PCHAR)Ssid, - &SsidLen, - &BssType, - &BeaconPeriod, - &Channel, - &NewChannel, - &TimeStamp, - &Cf, - &AtimWin, - &CapabilityInfo, - &Erp, - &DtimCount, - &DtimPeriod, - &BcastFlag, - &MessageToMe, - SupRate, - &SupRateLen, - ExtRate, - &ExtRateLen, - &CkipFlag, - &AironetCellPowerLimit, - &EdcaParm, - &QbssLoad, - &QosCapability, - &RalinkIe, - &HtCapabilityLen, - &PreNHtCapabilityLen, - &HtCapability, - &AddHtInfoLen, - &AddHtInfo, - &NewExtChannelOffset, - &LenVIE, - pVIE)) - { - // Disqualify 11b only adhoc when we are in 11g only adhoc mode - if ((BssType == BSS_ADHOC) && (pAd->CommonCfg.PhyMode == PHY_11G) && ((SupRateLen+ExtRateLen)< 12)) - return; - - // BEACON from desired BSS/IBSS found. We should be able to decide most - // BSS parameters here. - // Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION? - // Do we need to receover back all parameters belonging to previous BSS? - // A. Should be not. There's no back-door recover to previous AP. It still need - // a new JOIN-AUTH-ASSOC sequence. - if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid)) - { - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", Channel)); - RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); - - // Update RSSI to prevent No signal display when cards first initialized - pAd->StaCfg.RssiSample.LastRssi0 = ConvertToRssi(pAd, Elem->Rssi0, RSSI_0); - pAd->StaCfg.RssiSample.LastRssi1 = ConvertToRssi(pAd, Elem->Rssi1, RSSI_1); - pAd->StaCfg.RssiSample.LastRssi2 = ConvertToRssi(pAd, Elem->Rssi2, RSSI_2); - pAd->StaCfg.RssiSample.AvgRssi0 = pAd->StaCfg.RssiSample.LastRssi0; - pAd->StaCfg.RssiSample.AvgRssi0X8 = pAd->StaCfg.RssiSample.AvgRssi0 << 3; - pAd->StaCfg.RssiSample.AvgRssi1 = pAd->StaCfg.RssiSample.LastRssi1; - pAd->StaCfg.RssiSample.AvgRssi1X8 = pAd->StaCfg.RssiSample.AvgRssi1 << 3; - pAd->StaCfg.RssiSample.AvgRssi2 = pAd->StaCfg.RssiSample.LastRssi2; - pAd->StaCfg.RssiSample.AvgRssi2X8 = pAd->StaCfg.RssiSample.AvgRssi2 << 3; - - // - // We need to check if SSID only set to any, then we can record the current SSID. - // Otherwise will cause hidden SSID association failed. - // - if (pAd->MlmeAux.SsidLen == 0) - { - NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); - pAd->MlmeAux.SsidLen = SsidLen; - } - else - { - Idx = BssSsidTableSearch(&pAd->ScanTab, Bssid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Channel); - - if (Idx == BSS_NOT_FOUND) - { - CHAR Rssi = 0; - Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); - Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, (CHAR *) Ssid, SsidLen, BssType, BeaconPeriod, - &Cf, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, - &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag, - &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); - if (Idx != BSS_NOT_FOUND) - { - NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4); - NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); - NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); - CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo; - } - } - else - { - // - // Multiple SSID case, used correct CapabilityInfo - // - CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo; - } - } - NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN); - pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; - pAd->MlmeAux.BssType = BssType; - pAd->MlmeAux.BeaconPeriod = BeaconPeriod; - pAd->MlmeAux.Channel = Channel; - pAd->MlmeAux.AtimWin = AtimWin; - pAd->MlmeAux.CfpPeriod = Cf.CfpPeriod; - pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration; - pAd->MlmeAux.APRalinkIe = RalinkIe; - - // Copy AP's supported rate to MlmeAux for creating assoication request - // Also filter out not supported rate - pAd->MlmeAux.SupRateLen = SupRateLen; - NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen); - RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); - pAd->MlmeAux.ExtRateLen = ExtRateLen; - NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen); - RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); - - NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16); - - -#ifdef DOT11_N_SUPPORT - if (((pAd->StaCfg.WepStatus != Ndis802_11WEPEnabled) && (pAd->StaCfg.WepStatus != Ndis802_11Encryption2Enabled)) - || (pAd->CommonCfg.HT_DisallowTKIP == FALSE)) - { - bAllowNrate = TRUE; - } - - pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset; - pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen; - - RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); - // filter out un-supported ht rates - if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) && - ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (bAllowNrate))) - { - RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, SIZE_ADD_HT_INFO_IE); - - // StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability - NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16); - pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset; - pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE; - pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE; - if (PreNHtCapabilityLen > 0) - pAd->StaActive.SupportedPhyInfo.bPreNHt = TRUE; - RTMPCheckHt(pAd, BSSID_WCID, &HtCapability, &AddHtInfo); - // Copy AP Parameter to StaActive. This is also in LinkUp. - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n", - pAd->StaActive.SupportedHtPhy.MpduDensity, pAd->StaActive.SupportedHtPhy.MaxRAmpduFactor, HtCapability.HtCapInfo.ChannelWidth)); - - if (AddHtInfoLen > 0) - { - CentralChannel = AddHtInfo.ControlChan; - // Check again the Bandwidth capability of this AP. - if ((AddHtInfo.ControlChan > 2)&& (AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - CentralChannel = AddHtInfo.ControlChan - 2; - } - else if ((AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - CentralChannel = AddHtInfo.ControlChan + 2; - } - - // Check Error . - if (pAd->MlmeAux.CentralChannel != CentralChannel) - DBGPRINT(RT_DEBUG_ERROR, ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", CentralChannel, AddHtInfo.ControlChan, pAd->MlmeAux.CentralChannel)); - - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", CentralChannel, AddHtInfo.ControlChan)); - - } - - } - else -#endif // DOT11_N_SUPPORT // - { - // To prevent error, let legacy AP must have same CentralChannel and Channel. - if ((HtCapabilityLen == 0) && (PreNHtCapabilityLen == 0)) - pAd->MlmeAux.CentralChannel = pAd->MlmeAux.Channel; - - pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; - pAd->MlmeAux.NewExtChannelOffset = 0xff; - RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); - pAd->MlmeAux.HtCapabilityLen = 0; - RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE); - } - - RTMPUpdateMlmeRate(pAd); - - // copy QOS related information - if ((pAd->CommonCfg.bWmmCapable) -#ifdef DOT11_N_SUPPORT - || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) -#endif // DOT11_N_SUPPORT // - ) - { - NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, &EdcaParm, sizeof(EDCA_PARM)); - NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM)); - NdisMoveMemory(&pAd->MlmeAux.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM)); - } - else - { - NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM)); - NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); - NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); - } - - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n", - pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen)); - - if (AironetCellPowerLimit != 0xFF) - { - //We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power - ChangeToCellPowerLimit(pAd, AironetCellPowerLimit); - } - else //Used the default TX Power Percentage. - pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; - - pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; - Status = MLME_SUCCESS; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); - } - // not to me BEACON, ignored - } - // sanity check fail, ignore this frame -} - -/* - ========================================================================== - Description: - receive BEACON from peer - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID PeerBeacon( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; - CHAR Ssid[MAX_LEN_OF_SSID]; - CF_PARM CfParm; - UCHAR SsidLen, MessageToMe=0, BssType, Channel, NewChannel, index=0; - UCHAR DtimCount=0, DtimPeriod=0, BcastFlag=0; - USHORT CapabilityInfo, AtimWin, BeaconPeriod; - LARGE_INTEGER TimeStamp; - USHORT TbttNumToNextWakeUp; - UCHAR Erp; - UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; - UCHAR SupRateLen, ExtRateLen; - UCHAR CkipFlag; - USHORT LenVIE; - UCHAR AironetCellPowerLimit; - EDCA_PARM EdcaParm; - QBSS_LOAD_PARM QbssLoad; - QOS_CAPABILITY_PARM QosCapability; - ULONG RalinkIe; - // New for WPA security suites - UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 - NDIS_802_11_VARIABLE_IEs *pVIE = NULL; - HT_CAPABILITY_IE HtCapability; - ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE - UCHAR HtCapabilityLen, PreNHtCapabilityLen; - UCHAR AddHtInfoLen; - UCHAR NewExtChannelOffset = 0xff; - - -#ifdef RALINK_ATE - if (ATE_ON(pAd)) - { - return; - } -#endif // RALINK_ATE // - - if (!(INFRA_ON(pAd) || ADHOC_ON(pAd) - )) - return; - - // Init Variable IE structure - pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; - pVIE->Length = 0; - RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); - RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); - - if (PeerBeaconAndProbeRspSanity(pAd, - Elem->Msg, - Elem->MsgLen, - Elem->Channel, - Addr2, - Bssid, - Ssid, - &SsidLen, - &BssType, - &BeaconPeriod, - &Channel, - &NewChannel, - &TimeStamp, - &CfParm, - &AtimWin, - &CapabilityInfo, - &Erp, - &DtimCount, - &DtimPeriod, - &BcastFlag, - &MessageToMe, - SupRate, - &SupRateLen, - ExtRate, - &ExtRateLen, - &CkipFlag, - &AironetCellPowerLimit, - &EdcaParm, - &QbssLoad, - &QosCapability, - &RalinkIe, - &HtCapabilityLen, - &PreNHtCapabilityLen, - &HtCapability, - &AddHtInfoLen, - &AddHtInfo, - &NewExtChannelOffset, - &LenVIE, - pVIE)) - { - BOOLEAN is_my_bssid, is_my_ssid; - ULONG Bssidx, Now; - BSS_ENTRY *pBss; - CHAR RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); - - is_my_bssid = MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid)? TRUE : FALSE; - is_my_ssid = SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)? TRUE:FALSE; - - - // ignore BEACON not for my SSID - if ((! is_my_ssid) && (! is_my_bssid)) - return; - - // It means STA waits disassoc completely from this AP, ignores this beacon. - if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC) - return; - -#ifdef DOT11_N_SUPPORT - // Copy Control channel for this BSSID. - if (AddHtInfoLen != 0) - Channel = AddHtInfo.ControlChan; - - if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) - HtCapabilityLen = SIZE_HT_CAP_IE; -#endif // DOT11_N_SUPPORT // - - // - // Housekeeping "SsidBssTab" table for later-on ROAMing usage. - // - Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); - if (Bssidx == BSS_NOT_FOUND) - { - // discover new AP of this network, create BSS entry - Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, - &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, - &HtCapability, &AddHtInfo,HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel, - RealRssi, TimeStamp, CkipFlag, &EdcaParm, &QosCapability, - &QbssLoad, LenVIE, pVIE); - if (Bssidx == BSS_NOT_FOUND) // return if BSS table full - return; - - NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4); - NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); - NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); - - - - } - - if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel)) - { - // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). - // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. - AsicSwitchChannel(pAd, 1, FALSE); - AsicLockChannel(pAd, 1); - LinkDown(pAd, FALSE); - MlmeQueueInit(&pAd->Mlme.Queue); - BssTableInit(&pAd->ScanTab); - RTMPusecDelay(1000000); // use delay to prevent STA do reassoc - - // channel sanity check - for (index = 0 ; index < pAd->ChannelListNum; index++) - { - if (pAd->ChannelList[index].Channel == NewChannel) - { - pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel; - pAd->CommonCfg.Channel = NewChannel; - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel)); - break; - } - } - - if (index >= pAd->ChannelListNum) - { - DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); - } - } - - // if the ssid matched & bssid unmatched, we should select the bssid with large value. - // This might happened when two STA start at the same time - if ((! is_my_bssid) && ADHOC_ON(pAd)) - { - INT i; - - // Add the safeguard against the mismatch of adhoc wep status - if (pAd->StaCfg.WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus) - { - return; - } - - // collapse into the ADHOC network which has bigger BSSID value. - for (i = 0; i < 6; i++) - { - if (Bssid[i] > pAd->CommonCfg.Bssid[i]) - { - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", - Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); - AsicDisableSync(pAd); - COPY_MAC_ADDR(pAd->CommonCfg.Bssid, Bssid); - AsicSetBssid(pAd, pAd->CommonCfg.Bssid); - MakeIbssBeacon(pAd); // re-build BEACON frame - AsicEnableIbssSync(pAd); // copy BEACON frame to on-chip memory - is_my_bssid = TRUE; - break; - } - else if (Bssid[i] < pAd->CommonCfg.Bssid[i]) - break; - } - } - - - NdisGetSystemUpTime(&Now); - pBss = &pAd->ScanTab.BssEntry[Bssidx]; - pBss->Rssi = RealRssi; // lastest RSSI - pBss->LastBeaconRxTime = Now; // last RX timestamp - - // - // BEACON from my BSSID - either IBSS or INFRA network - // - if (is_my_bssid) - { - RXWI_STRUC RxWI; - - pAd->StaCfg.DtimCount = DtimCount; - pAd->StaCfg.DtimPeriod = DtimPeriod; - pAd->StaCfg.LastBeaconRxTime = Now; - - - RxWI.RSSI0 = Elem->Rssi0; - RxWI.RSSI1 = Elem->Rssi1; - RxWI.RSSI2 = Elem->Rssi2; - - Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI); - if (AironetCellPowerLimit != 0xFF) - { - // - // We get the Cisco (ccx) "TxPower Limit" required - // Changed to appropriate TxPower Limit for Ciso Compatible Extensions - // - ChangeToCellPowerLimit(pAd, AironetCellPowerLimit); - } - else - { - // - // AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist. - // Used the default TX Power Percentage, that set from UI. - // - pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; - } - - if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo))) - { - UCHAR MaxSupportedRateIn500Kbps = 0; - UCHAR idx; - MAC_TABLE_ENTRY *pEntry; - - // supported rates array may not be sorted. sort it and find the maximum rate - for (idx=0; idxWcid == RESERVED_WCID)) || - (pEntry && ((pEntry->LastBeaconRxTime + ADHOC_ENTRY_BEACON_LOST_TIME) < Now))) - { - if (pEntry == NULL) - // Another adhoc joining, add to our MAC table. - pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE); - - if (StaAddMacTableEntry(pAd, - pEntry, - MaxSupportedRateIn500Kbps, - &HtCapability, - HtCapabilityLen, - &AddHtInfo, - AddHtInfoLen, - CapabilityInfo) == FALSE) - { - DBGPRINT(RT_DEBUG_TRACE, ("ADHOC - Add Entry failed.\n")); - return; - } - - if (pEntry && - (Elem->Wcid == RESERVED_WCID)) - { - idx = pAd->StaCfg.DefaultKeyId; - RTMP_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry); - } - } - - if (pEntry && pEntry->ValidAsCLI) - pEntry->LastBeaconRxTime = Now; - - // At least another peer in this IBSS, declare MediaState as CONNECTED - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); - - pAd->IndicateMediaState = NdisMediaStateConnected; - RTMP_IndicateMediaState(pAd); - pAd->ExtraInfo = GENERAL_LINK_UP; - AsicSetBssid(pAd, pAd->CommonCfg.Bssid); - - // 2003/03/12 - john - // Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that - // "site survey" result should always include the current connected network. - // - Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); - if (Bssidx == BSS_NOT_FOUND) - { - Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, - &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, - &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0, - &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); - } - DBGPRINT(RT_DEBUG_TRACE, ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n")); - } - } - - if (INFRA_ON(pAd)) - { - BOOLEAN bUseShortSlot, bUseBGProtection; - - // decide to use/change to - - // 1. long slot (20 us) or short slot (9 us) time - // 2. turn on/off RTS/CTS and/or CTS-to-self protection - // 3. short preamble - - //bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo); - bUseShortSlot = CAP_IS_SHORT_SLOT(CapabilityInfo); - if (bUseShortSlot != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED)) - AsicSetSlotTime(pAd, bUseShortSlot); - - bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || // always use - ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(Erp)); - - if (pAd->CommonCfg.Channel > 14) // always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP - bUseBGProtection = FALSE; - - if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) - { - if (bUseBGProtection) - { - OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),FALSE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)); - } - else - { - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),TRUE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)); - } - - DBGPRINT(RT_DEBUG_WARN, ("SYNC - AP changed B/G protection to %d\n", bUseBGProtection)); - } - -#ifdef DOT11_N_SUPPORT - // check Ht protection mode. and adhere to the Non-GF device indication by AP. - if ((AddHtInfoLen != 0) && - ((AddHtInfo.AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) || - (AddHtInfo.AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent))) - { - pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = AddHtInfo.AddHtInfo2.NonGfPresent; - pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = AddHtInfo.AddHtInfo2.OperaionMode; - if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1) - { - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE); - } - else - AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); - - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP changed N OperaionMode to %d\n", pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode)); - } -#endif // DOT11_N_SUPPORT // - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) && - ERP_IS_USE_BARKER_PREAMBLE(Erp)) - { - MlmeSetTxPreamble(pAd, Rt802_11PreambleLong); - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP forced to use LONG preamble\n")); - } - - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && - (EdcaParm.bValid == TRUE) && - (EdcaParm.EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount)) - { - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n", - pAd->CommonCfg.APEdcaParm.EdcaUpdateCount, - EdcaParm.EdcaUpdateCount)); - AsicSetEdcaParm(pAd, &EdcaParm); - } - - // copy QOS related information - NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM)); - NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM)); - } - - // only INFRASTRUCTURE mode support power-saving feature - if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) || (pAd->CommonCfg.bAPSDForcePowerSave)) - { - UCHAR FreeNumber; - // 1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL - // 2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE - // 3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE - // 4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE - // 5. otherwise, put PHY back to sleep to save battery. - if (MessageToMe) - { -#ifdef RTMP_MAC_PCI - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - { - // Restore to correct BBP R3 value - if (pAd->Antenna.field.RxPath > 1) - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); - // Turn clk to 80Mhz. - } -#endif // RTMP_MAC_PCI // - if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && - pAd->CommonCfg.bAPSDAC_BE && pAd->CommonCfg.bAPSDAC_BK && pAd->CommonCfg.bAPSDAC_VI && pAd->CommonCfg.bAPSDAC_VO) - { - pAd->CommonCfg.bNeedSendTriggerFrame = TRUE; - } - else - RTMP_PS_POLL_ENQUEUE(pAd); - } - else if (BcastFlag && (DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM)) - { -#ifdef RTMP_MAC_PCI - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - { - if (pAd->Antenna.field.RxPath > 1) - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); - } -#endif // RTMP_MAC_PCI // - } - else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) || - (pAd->TxSwQueue[QID_AC_BE].Number != 0) || - (pAd->TxSwQueue[QID_AC_VI].Number != 0) || - (pAd->TxSwQueue[QID_AC_VO].Number != 0) || - (RTMPFreeTXDRequest(pAd, QID_AC_BK, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || - (RTMPFreeTXDRequest(pAd, QID_AC_BE, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || - (RTMPFreeTXDRequest(pAd, QID_AC_VI, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || - (RTMPFreeTXDRequest(pAd, QID_AC_VO, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || - (RTMPFreeTXDRequest(pAd, QID_MGMT, MGMT_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)) - { - // TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme - // can we cheat here (i.e. just check MGMT & AC_BE) for better performance? -#ifdef RTMP_MAC_PCI - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) - { - if (pAd->Antenna.field.RxPath > 1) - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); - } -#endif // RTMP_MAC_PCI // - } - else - { - if ((pAd->CommonCfg.bACMAPSDTr[QID_AC_VO]) || - (pAd->CommonCfg.bACMAPSDTr[QID_AC_VI]) || - (pAd->CommonCfg.bACMAPSDTr[QID_AC_BK]) || - (pAd->CommonCfg.bACMAPSDTr[QID_AC_BE])) - { - /* - WMM Spec v1.0 3.6.2.4, - The WMM STA shall remain awake until it receives a - QoS Data or Null frame addressed to it, with the - EOSP subfield in QoS Control field set to 1. - - So we can not sleep here or we will suffer a case: - - PS Management Frame --> - Trigger frame --> - Beacon (TIM=0) (Beacon is closer to Trig frame) --> - Station goes to sleep --> - AP delivery queued UAPSD packets --> - Station can NOT receive the reply - - Maybe we need a timeout timer to avoid that we do - NOT receive the EOSP frame. - - We can not use More Data to check if SP is ended - due to MaxSPLength. - */ - } - else - { - USHORT NextDtim = DtimCount; - - - if (NextDtim == 0) - NextDtim = DtimPeriod; - - TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) - TbttNumToNextWakeUp = NextDtim; - - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - { - // Set a flag to go to sleep . Then after parse this RxDoneInterrupt, will go to sleep mode. - pAd->ThisTbttNumToNextWakeUp = TbttNumToNextWakeUp; - AsicSleepThenAutoWakeup(pAd, pAd->ThisTbttNumToNextWakeUp); - - } - } - } - } - } - // not my BSSID, ignore it - } - // sanity check fail, ignore this frame -} - -/* - ========================================================================== - Description: - Receive PROBE REQ from remote peer when operating in IBSS mode - ========================================================================== - */ -VOID PeerProbeReqAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - UCHAR Addr2[MAC_ADDR_LEN]; - CHAR Ssid[MAX_LEN_OF_SSID]; - UCHAR SsidLen; -#ifdef DOT11_N_SUPPORT - UCHAR HtLen, AddHtLen, NewExtLen; -#endif // DOT11_N_SUPPORT // - HEADER_802_11 ProbeRspHdr; - NDIS_STATUS NStatus; - PUCHAR pOutBuffer = NULL; - ULONG FrameLen = 0; - LARGE_INTEGER FakeTimestamp; - UCHAR DsLen = 1, IbssLen = 2; - UCHAR LocalErpIe[3] = {IE_ERP, 1, 0}; - BOOLEAN Privacy; - USHORT CapabilityInfo; - UCHAR RSNIe = IE_WPA; - - if (! ADHOC_ON(pAd)) - return; - - if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen)) - { - if ((SsidLen == 0) || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)) - { - // allocate and send out ProbeRsp frame - NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NStatus != NDIS_STATUS_SUCCESS) - return; - - //pAd->StaCfg.AtimWin = 0; // ?????? - - Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || - (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || - (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); - CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0); - - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &ProbeRspHdr, - TIMESTAMP_LEN, &FakeTimestamp, - 2, &pAd->CommonCfg.BeaconPeriod, - 2, &CapabilityInfo, - 1, &SsidIe, - 1, &pAd->CommonCfg.SsidLen, - pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, - 1, &SupRateIe, - 1, &pAd->StaActive.SupRateLen, - pAd->StaActive.SupRateLen, pAd->StaActive.SupRate, - 1, &DsIe, - 1, &DsLen, - 1, &pAd->CommonCfg.Channel, - 1, &IbssIe, - 1, &IbssLen, - 2, &pAd->StaActive.AtimWin, - END_OF_ARGS); - - if (pAd->StaActive.ExtRateLen) - { - ULONG tmp; - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 3, LocalErpIe, - 1, &ExtRateIe, - 1, &pAd->StaActive.ExtRateLen, - pAd->StaActive.ExtRateLen, &pAd->StaActive.ExtRate, - END_OF_ARGS); - FrameLen += tmp; - } - - // If adhoc secruity is set for WPA-None, append the cipher suite IE - if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - { - ULONG tmp; - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - 1, &RSNIe, - 1, &pAd->StaCfg.RSNIE_Len, - pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, - END_OF_ARGS); - FrameLen += tmp; - } -#ifdef DOT11_N_SUPPORT - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) - { - ULONG TmpLen; - UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; - HtLen = sizeof(pAd->CommonCfg.HtCapability); - AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); - NewExtLen = 1; - //New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame - if (pAd->bBroadComHT == TRUE) - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, - 1, &WpaIe, - 4, &BROADCOM[0], - pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, - END_OF_ARGS); - } - else - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, - 1, &HtCapIe, - 1, &HtLen, - sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability, - 1, &AddHtInfoIe, - 1, &AddHtLen, - sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo, - 1, &NewExtChanIe, - 1, &NewExtLen, - sizeof(NEW_EXT_CHAN_IE), &pAd->CommonCfg.NewExtChanOffset, - END_OF_ARGS); - } - FrameLen += TmpLen; - } -#endif // DOT11_N_SUPPORT // - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - } - } -} - -VOID BeaconTimeoutAtJoinAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n")); - pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; - Status = MLME_REJ_TIMEOUT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); -} - -/* - ========================================================================== - Description: - Scan timeout procedure. basically add channel index by 1 and rescan - ========================================================================== - */ -VOID ScanTimeoutAction( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel); - - // Only one channel scanned for CISCO beacon request - if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) || - (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) || - (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) || - (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD)) - pAd->MlmeAux.Channel = 0; - - // this routine will stop if pAd->MlmeAux.Channel == 0 - ScanNextChannel(pAd); -} - -/* - ========================================================================== - Description: - ========================================================================== - */ -VOID InvalidStateWhenScan( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); - pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; - Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); -} - -/* - ========================================================================== - Description: - ========================================================================== - */ -VOID InvalidStateWhenJoin( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); - pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; - Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); -} - -/* - ========================================================================== - Description: - ========================================================================== - */ -VOID InvalidStateWhenStart( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - USHORT Status; - DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); - pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; - Status = MLME_STATE_MACHINE_REJECT; - MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); -} - -/* - ========================================================================== - Description: - - IRQL = DISPATCH_LEVEL - - ========================================================================== - */ -VOID EnqueuePsPoll( - IN PRTMP_ADAPTER pAd) -{ -#ifdef RALINK_ATE - if (ATE_ON(pAd)) - { - return; - } -#endif // RALINK_ATE // - - - if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP) - pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE; - MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->PsPollFrame, sizeof(PSPOLL_FRAME)); -} - - -/* - ========================================================================== - Description: - ========================================================================== - */ -VOID EnqueueProbeRequest( - IN PRTMP_ADAPTER pAd) -{ - NDIS_STATUS NState; - PUCHAR pOutBuffer; - ULONG FrameLen = 0; - HEADER_802_11 Hdr80211; - - DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n")); - - NState = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory - if (NState == NDIS_STATUS_SUCCESS) - { - MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); - - // this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse - MakeOutgoingFrame(pOutBuffer, &FrameLen, - sizeof(HEADER_802_11), &Hdr80211, - 1, &SsidIe, - 1, &pAd->CommonCfg.SsidLen, - pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, - 1, &SupRateIe, - 1, &pAd->StaActive.SupRateLen, - pAd->StaActive.SupRateLen, pAd->StaActive.SupRate, - END_OF_ARGS); - MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); - MlmeFreeMemory(pAd, pOutBuffer); - } - -} - -#ifdef DOT11_N_SUPPORT -#ifdef DOT11N_DRAFT3 -VOID BuildEffectedChannelList( - IN PRTMP_ADAPTER pAd) -{ - UCHAR EChannel[11]; - UCHAR i, j, k; - UCHAR UpperChannel = 0, LowerChannel = 0; - - RTMPZeroMemory(EChannel, 11); - i = 0; - // Find upper channel and lower channel. - if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) - { - UpperChannel = pAd->CommonCfg.Channel; - LowerChannel = pAd->CommonCfg.CentralChannel; - } - else if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) - { - UpperChannel = pAd->CommonCfg.CentralChannel; - LowerChannel = pAd->CommonCfg.Channel; - } - else - { - return; - } - - // Record channels that is below lower channel.. - if (LowerChannel > 1) - { - EChannel[0] = LowerChannel - 1; - i = 1; - if (LowerChannel > 2) - { - EChannel[1] = LowerChannel - 2; - i = 2; - if (LowerChannel > 3) - { - EChannel[2] = LowerChannel - 3; - i = 3; - } - } - } - // Record channels that is between lower channel and upper channel. - for (k = LowerChannel;k < UpperChannel;k++) - { - EChannel[i] = k; - i++; - } - // Record channels that is above upper channel.. - if (LowerChannel < 11) - { - EChannel[i] = UpperChannel + 1; - i++; - if (LowerChannel < 10) - { - EChannel[i] = LowerChannel + 2; - i++; - if (LowerChannel < 9) - { - EChannel[i] = LowerChannel + 3; - i++; - } - } - } - // - for (j = 0;j < i;j++) - { - for (k = 0;k < pAd->ChannelListNum;k++) - { - if (pAd->ChannelList[k].Channel == EChannel[j]) - { - pAd->ChannelList[k].bEffectedChannel = TRUE; - DBGPRINT(RT_DEBUG_TRACE,(" EffectedChannel( =%d)\n", EChannel[j])); - break; - } - } - } -} -#endif // DOT11N_DRAFT3 // -#endif // DOT11_N_SUPPORT // - -BOOLEAN ScanRunning( - IN PRTMP_ADAPTER pAd) -{ - return (pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) ? TRUE : FALSE; -} diff --git a/drivers/staging/rt3090/sta/wpa.c b/drivers/staging/rt3090/sta/wpa.c deleted file mode 100644 index 2dbdba541c3f25a7d1d44ebbdd65855f0fd50622..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/sta/wpa.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - wpa.c - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Jan Lee 03-07-22 Initial - Paul Lin 03-11-28 Modify for supplicant -*/ - -#include "../rt_config.h" - - -void inc_byte_array(UCHAR *counter, int len); - -/* - ======================================================================== - - Routine Description: - Process MIC error indication and record MIC error timer. - - Arguments: - pAd Pointer to our adapter - pWpaKey Pointer to the WPA key structure - - Return Value: - None - - IRQL = DISPATCH_LEVEL - - Note: - - ======================================================================== -*/ -VOID RTMPReportMicError( - IN PRTMP_ADAPTER pAd, - IN PCIPHER_KEY pWpaKey) -{ - ULONG Now; - UCHAR unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1:0); - - // Record Last MIC error time and count - NdisGetSystemUpTime(&Now); - if (pAd->StaCfg.MicErrCnt == 0) - { - pAd->StaCfg.MicErrCnt++; - pAd->StaCfg.LastMicErrorTime = Now; - NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); - } - else if (pAd->StaCfg.MicErrCnt == 1) - { - if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now) - { - // Update Last MIC error time, this did not violate two MIC errors within 60 seconds - pAd->StaCfg.LastMicErrorTime = Now; - } - else - { - - if (pAd->CommonCfg.bWirelessEvent) - RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); - - pAd->StaCfg.LastMicErrorTime = Now; - // Violate MIC error counts, MIC countermeasures kicks in - pAd->StaCfg.MicErrCnt++; - // We shall block all reception - // We shall clean all Tx ring and disassoicate from AP after next EAPOL frame - // - // No necessary to clean all Tx ring, on RTMPHardTransmit will stop sending non-802.1X EAPOL packets - // if pAd->StaCfg.MicErrCnt greater than 2. - // - // RTMPRingCleanUp(pAd, QID_AC_BK); - // RTMPRingCleanUp(pAd, QID_AC_BE); - // RTMPRingCleanUp(pAd, QID_AC_VI); - // RTMPRingCleanUp(pAd, QID_AC_VO); - // RTMPRingCleanUp(pAd, QID_HCCA); - } - } - else - { - // MIC error count >= 2 - // This should not happen - ; - } - MlmeEnqueue(pAd, - MLME_CNTL_STATE_MACHINE, - OID_802_11_MIC_FAILURE_REPORT_FRAME, - 1, - &unicastKey); - - if (pAd->StaCfg.MicErrCnt == 2) - { - RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100); - } -} - - -#ifdef WPA_SUPPLICANT_SUPPORT -#define LENGTH_EAP_H 4 -// If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)). -INT WpaCheckEapCode( - IN PRTMP_ADAPTER pAd, - IN PUCHAR pFrame, - IN USHORT FrameLen, - IN USHORT OffSet) -{ - - PUCHAR pData; - INT result = 0; - - if( FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H ) - return result; - - pData = pFrame + OffSet; // skip offset bytes - - if(*(pData+1) == EAPPacket) // 802.1x header - Packet Type - { - result = *(pData+4); // EAP header - Code - } - - return result; -} - -VOID WpaSendMicFailureToWpaSupplicant( - IN PRTMP_ADAPTER pAd, - IN BOOLEAN bUnicast) -{ - char custom[IW_CUSTOM_MAX] = {0}; - - sprintf(custom, "MLME-MICHAELMICFAILURE.indication"); - if(bUnicast) - sprintf(custom, "%s unicast", custom); - - RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, -1, NULL, (PUCHAR)custom, strlen(custom)); - - return; -} -#endif // WPA_SUPPLICANT_SUPPORT // - -VOID WpaMicFailureReportFrame( - IN PRTMP_ADAPTER pAd, - IN MLME_QUEUE_ELEM *Elem) -{ - PUCHAR pOutBuffer = NULL; - UCHAR Header802_3[14]; - ULONG FrameLen = 0; - EAPOL_PACKET Packet; - UCHAR Mic[16]; - BOOLEAN bUnicast; - - DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n")); - - bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE); - pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER); - - // init 802.3 header and Fill Packet - MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); - - NdisZeroMemory(&Packet, sizeof(Packet)); - Packet.ProVer = EAPOL_VER; - Packet.ProType = EAPOLKey; - - Packet.KeyDesc.Type = WPA1_KEY_DESC; - - // Request field presented - Packet.KeyDesc.KeyInfo.Request = 1; - - if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { - Packet.KeyDesc.KeyInfo.KeyDescVer = 2; - } - else // TKIP - { - Packet.KeyDesc.KeyInfo.KeyDescVer = 1; - } - - Packet.KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY); - - // KeyMic field presented - Packet.KeyDesc.KeyInfo.KeyMic = 1; - - // Error field presented - Packet.KeyDesc.KeyInfo.Error = 1; - - // Update packet length after decide Key data payload - SET_UINT16_TO_ARRARY(Packet.Body_Len, LEN_EAPOL_KEY_MSG) - - // Key Replay Count - NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); - inc_byte_array(pAd->StaCfg.ReplayCounter, 8); - - // Convert to little-endian format. - *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); - - - MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory - if(pOutBuffer == NULL) - { - return; - } - - // Prepare EAPOL frame for MIC calculation - // Be careful, only EAPOL frame is counted for MIC calculation - MakeOutgoingFrame(pOutBuffer, &FrameLen, - CONV_ARRARY_TO_UINT16(Packet.Body_Len) + 4, &Packet, - END_OF_ARGS); - - // Prepare and Fill MIC value - NdisZeroMemory(Mic, sizeof(Mic)); - if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) - { // AES - UCHAR digest[20] = {0}; - HMAC_SHA1(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE); - NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); - } - else - { // TKIP - HMAC_MD5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic, MD5_DIGEST_SIZE); - } - NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); - - // copy frame to Tx ring and send MIC failure report frame to authenticator - RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], - Header802_3, LENGTH_802_3, - (PUCHAR)&Packet, - CONV_ARRARY_TO_UINT16(Packet.Body_Len) + 4, FALSE); - - MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); - - DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n")); -} - -/** from wpa_supplicant - * inc_byte_array - Increment arbitrary length byte array by one - * @counter: Pointer to byte array - * @len: Length of the counter in bytes - * - * This function increments the last byte of the counter by one and continues - * rolling over to more significant bytes if the byte was incremented from - * 0xff to 0x00. - */ -void inc_byte_array(UCHAR *counter, int len) -{ - int pos = len - 1; - while (pos >= 0) { - counter[pos]++; - if (counter[pos] != 0) - break; - pos--; - } -} - -VOID WpaDisassocApAndBlockAssoc( - IN PVOID SystemSpecific1, - IN PVOID FunctionContext, - IN PVOID SystemSpecific2, - IN PVOID SystemSpecific3) -{ - RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext; - MLME_DISASSOC_REQ_STRUCT DisassocReq; - - // disassoc from current AP first - DBGPRINT(RT_DEBUG_TRACE, ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n")); - DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_MIC_FAILURE); - MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); - - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; - pAd->StaCfg.bBlockAssoc = TRUE; -} - -VOID WpaStaPairwiseKeySetting( - IN PRTMP_ADAPTER pAd) -{ - PCIPHER_KEY pSharedKey; - PMAC_TABLE_ENTRY pEntry; - - pEntry = &pAd->MacTab.Content[BSSID_WCID]; - - // Pairwise key shall use key#0 - pSharedKey = &pAd->SharedKey[BSS0][0]; - - NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK); - - // Prepare pair-wise key information into shared key table - NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY)); - pSharedKey->KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); - NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); - NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); - - // Decide its ChiperAlg - if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) - pSharedKey->CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) - pSharedKey->CipherAlg = CIPHER_AES; - else - pSharedKey->CipherAlg = CIPHER_NONE; - - // Update these related information to MAC_TABLE_ENTRY - NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); - NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); - NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); - pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg; - - // Update pairwise key information to ASIC Shared Key Table - AsicAddSharedKeyEntry(pAd, - BSS0, - 0, - pSharedKey->CipherAlg, - pSharedKey->Key, - pSharedKey->TxMic, - pSharedKey->RxMic); - - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAd, - BSS0, - 0, - pSharedKey->CipherAlg, - pEntry); - STA_PORT_SECURED(pAd); - pAd->IndicateMediaState = NdisMediaStateConnected; - - DBGPRINT(RT_DEBUG_TRACE, ("%s : AID(%d) port secured\n", __FUNCTION__, pEntry->Aid)); - -} - -VOID WpaStaGroupKeySetting( - IN PRTMP_ADAPTER pAd) -{ - PCIPHER_KEY pSharedKey; - - pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId]; - - // Prepare pair-wise key information into shared key table - NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY)); - pSharedKey->KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK); - NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16], LEN_TKIP_RXMICK); - NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24], LEN_TKIP_TXMICK); - - // Update Shared Key CipherAlg - pSharedKey->CipherAlg = CIPHER_NONE; - if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) - pSharedKey->CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) - pSharedKey->CipherAlg = CIPHER_AES; - else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled) - pSharedKey->CipherAlg = CIPHER_WEP64; - else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled) - pSharedKey->CipherAlg = CIPHER_WEP128; - - // Update group key information to ASIC Shared Key Table - AsicAddSharedKeyEntry(pAd, - BSS0, - pAd->StaCfg.DefaultKeyId, - pSharedKey->CipherAlg, - pSharedKey->Key, - pSharedKey->TxMic, - pSharedKey->RxMic); - - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAd, - BSS0, - pAd->StaCfg.DefaultKeyId, - pSharedKey->CipherAlg, - NULL); - -} diff --git a/drivers/staging/rt3090/sta_ioctl.c b/drivers/staging/rt3090/sta_ioctl.c deleted file mode 100644 index b8ab84a0469b3e103a74cad768e7ec278fb8e387..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/sta_ioctl.c +++ /dev/null @@ -1,7557 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - sta_ioctl.c - - Abstract: - IOCTL related subroutines - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Rory Chen 01-03-2003 created - Rory Chen 02-14-2005 modify to support RT61 -*/ - -#include "rt_config.h" - -#ifdef DBG -extern ULONG RTDebugLevel; -#endif - -#define NR_WEP_KEYS 4 -#define WEP_SMALL_KEY_LEN (40/8) -#define WEP_LARGE_KEY_LEN (104/8) - -#define GROUP_KEY_NO 4 - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) -#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E) iwe_stream_add_event(_A, _B, _C, _D, _E) -#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E) iwe_stream_add_point(_A, _B, _C, _D, _E) -#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F) iwe_stream_add_value(_A, _B, _C, _D, _E, _F) -#else -#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E) iwe_stream_add_event(_B, _C, _D, _E) -#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E) iwe_stream_add_point(_B, _C, _D, _E) -#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F) iwe_stream_add_value(_B, _C, _D, _E, _F) -#endif - -extern UCHAR CipherWpa2Template[]; - -typedef struct PACKED _RT_VERSION_INFO{ - UCHAR DriverVersionW; - UCHAR DriverVersionX; - UCHAR DriverVersionY; - UCHAR DriverVersionZ; - UINT DriverBuildYear; - UINT DriverBuildMonth; - UINT DriverBuildDay; -} RT_VERSION_INFO, *PRT_VERSION_INFO; - -struct iw_priv_args privtab[] = { -{ RTPRIV_IOCTL_SET, - IW_PRIV_TYPE_CHAR | 1024, 0, - "set"}, - -{ RTPRIV_IOCTL_SHOW, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, - ""}, -/* --- sub-ioctls definitions --- */ - { SHOW_CONN_STATUS, - IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "connStatus" }, - { SHOW_DRVIER_VERION, - IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "driverVer" }, - { SHOW_BA_INFO, - IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "bainfo" }, - { SHOW_DESC_INFO, - IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "descinfo" }, - { RAIO_OFF, - IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_off" }, - { RAIO_ON, - IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_on" }, -#ifdef QOS_DLS_SUPPORT - { SHOW_DLS_ENTRY_INFO, - IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "dlsentryinfo" }, -#endif // QOS_DLS_SUPPORT // - { SHOW_CFG_VALUE, - IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "show" }, - { SHOW_ADHOC_ENTRY_INFO, - IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "adhocEntry" }, -/* --- sub-ioctls relations --- */ - -#ifdef DBG -{ RTPRIV_IOCTL_BBP, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, - "bbp"}, -{ RTPRIV_IOCTL_MAC, - IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, - "mac"}, -#ifdef RTMP_RF_RW_SUPPORT -{ RTPRIV_IOCTL_RF, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, - "rf"}, -#endif // RTMP_RF_RW_SUPPORT // -{ RTPRIV_IOCTL_E2P, - IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, - "e2p"}, -#endif /* DBG */ - -{ RTPRIV_IOCTL_STATISTICS, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, - "stat"}, -{ RTPRIV_IOCTL_GSITESURVEY, - 0, IW_PRIV_TYPE_CHAR | 1024, - "get_site_survey"}, - - -}; - -static __s32 ralinkrate[] = - {2, 4, 11, 22, // CCK - 12, 18, 24, 36, 48, 72, 96, 108, // OFDM - 13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, // 20MHz, 800ns GI, MCS: 0 ~ 15 - 39, 78, 117, 156, 234, 312, 351, 390, // 20MHz, 800ns GI, MCS: 16 ~ 23 - 27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, // 40MHz, 800ns GI, MCS: 0 ~ 15 - 81, 162, 243, 324, 486, 648, 729, 810, // 40MHz, 800ns GI, MCS: 16 ~ 23 - 14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, // 20MHz, 400ns GI, MCS: 0 ~ 15 - 43, 87, 130, 173, 260, 317, 390, 433, // 20MHz, 400ns GI, MCS: 16 ~ 23 - 30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, // 40MHz, 400ns GI, MCS: 0 ~ 15 - 90, 180, 270, 360, 540, 720, 810, 900}; - - - -INT Set_SSID_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -#ifdef WMM_SUPPORT -INT Set_WmmCapable_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); -#endif - -INT Set_NetworkType_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -INT Set_AuthMode_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -INT Set_EncrypType_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -INT Set_DefaultKeyID_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -INT Set_Key1_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -INT Set_Key2_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -INT Set_Key3_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -INT Set_Key4_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -INT Set_WPAPSK_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - - -INT Set_PSMode_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -#ifdef RT3090 -INT Set_PCIePSLevel_Proc( -IN PRTMP_ADAPTER pAdapter, -IN PUCHAR arg); -#endif // RT3090 // -#ifdef WPA_SUPPLICANT_SUPPORT -INT Set_Wpa_Support( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); -#endif // WPA_SUPPLICANT_SUPPORT // - -#ifdef DBG - -VOID RTMPIoctlMAC( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq); - -VOID RTMPIoctlE2PROM( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq); -#endif // DBG // - - -NDIS_STATUS RTMPWPANoneAddKeyProc( - IN PRTMP_ADAPTER pAd, - IN PVOID pBuf); - -INT Set_FragTest_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -#ifdef DOT11_N_SUPPORT -INT Set_TGnWifiTest_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); -#endif // DOT11_N_SUPPORT // - -INT Set_LongRetryLimit_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -INT Set_ShortRetryLimit_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); - -#ifdef EXT_BUILD_CHANNEL_LIST -INT Set_Ieee80211dClientMode_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg); -#endif // EXT_BUILD_CHANNEL_LIST // - -#ifdef CARRIER_DETECTION_SUPPORT -INT Set_CarrierDetect_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); -#endif // CARRIER_DETECTION_SUPPORT // - -INT Show_Adhoc_MacTable_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING extra); - -#ifdef RTMP_RF_RW_SUPPORT -VOID RTMPIoctlRF( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq); -#endif // RTMP_RF_RW_SUPPORT // - - -INT Set_BeaconLostTime_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_AutoRoaming_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_SiteSurvey_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -INT Set_ForceTxBurst_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg); - -#ifdef ANT_DIVERSITY_SUPPORT -INT Set_Antenna_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg); -#endif // ANT_DIVERSITY_SUPPORT // - -static struct { - PSTRING name; - INT (*set_proc)(PRTMP_ADAPTER pAdapter, PSTRING arg); -} *PRTMP_PRIVATE_SET_PROC, RTMP_PRIVATE_SUPPORT_PROC[] = { - {"DriverVersion", Set_DriverVersion_Proc}, - {"CountryRegion", Set_CountryRegion_Proc}, - {"CountryRegionABand", Set_CountryRegionABand_Proc}, - {"SSID", Set_SSID_Proc}, - {"WirelessMode", Set_WirelessMode_Proc}, - {"TxBurst", Set_TxBurst_Proc}, - {"TxPreamble", Set_TxPreamble_Proc}, - {"TxPower", Set_TxPower_Proc}, - {"Channel", Set_Channel_Proc}, - {"BGProtection", Set_BGProtection_Proc}, - {"RTSThreshold", Set_RTSThreshold_Proc}, - {"FragThreshold", Set_FragThreshold_Proc}, -#ifdef DOT11_N_SUPPORT - {"HtBw", Set_HtBw_Proc}, - {"HtMcs", Set_HtMcs_Proc}, - {"HtGi", Set_HtGi_Proc}, - {"HtOpMode", Set_HtOpMode_Proc}, - {"HtExtcha", Set_HtExtcha_Proc}, - {"HtMpduDensity", Set_HtMpduDensity_Proc}, - {"HtBaWinSize", Set_HtBaWinSize_Proc}, - {"HtRdg", Set_HtRdg_Proc}, - {"HtAmsdu", Set_HtAmsdu_Proc}, - {"HtAutoBa", Set_HtAutoBa_Proc}, - {"HtBaDecline", Set_BADecline_Proc}, - {"HtProtect", Set_HtProtect_Proc}, - {"HtMimoPs", Set_HtMimoPs_Proc}, - {"HtDisallowTKIP", Set_HtDisallowTKIP_Proc}, -#endif // DOT11_N_SUPPORT // - -#ifdef AGGREGATION_SUPPORT - {"PktAggregate", Set_PktAggregate_Proc}, -#endif // AGGREGATION_SUPPORT // - -#ifdef WMM_SUPPORT - {"WmmCapable", Set_WmmCapable_Proc}, -#endif - {"IEEE80211H", Set_IEEE80211H_Proc}, - {"NetworkType", Set_NetworkType_Proc}, - {"AuthMode", Set_AuthMode_Proc}, - {"EncrypType", Set_EncrypType_Proc}, - {"DefaultKeyID", Set_DefaultKeyID_Proc}, - {"Key1", Set_Key1_Proc}, - {"Key2", Set_Key2_Proc}, - {"Key3", Set_Key3_Proc}, - {"Key4", Set_Key4_Proc}, - {"WPAPSK", Set_WPAPSK_Proc}, - {"ResetCounter", Set_ResetStatCounter_Proc}, - {"PSMode", Set_PSMode_Proc}, -#ifdef DBG - {"Debug", Set_Debug_Proc}, -#endif // DBG // - -#ifdef RALINK_ATE - {"ATE", Set_ATE_Proc}, - {"ATEDA", Set_ATE_DA_Proc}, - {"ATESA", Set_ATE_SA_Proc}, - {"ATEBSSID", Set_ATE_BSSID_Proc}, - {"ATECHANNEL", Set_ATE_CHANNEL_Proc}, - {"ATETXPOW0", Set_ATE_TX_POWER0_Proc}, - {"ATETXPOW1", Set_ATE_TX_POWER1_Proc}, - {"ATETXANT", Set_ATE_TX_Antenna_Proc}, - {"ATERXANT", Set_ATE_RX_Antenna_Proc}, - {"ATETXFREQOFFSET", Set_ATE_TX_FREQOFFSET_Proc}, - {"ATETXBW", Set_ATE_TX_BW_Proc}, - {"ATETXLEN", Set_ATE_TX_LENGTH_Proc}, - {"ATETXCNT", Set_ATE_TX_COUNT_Proc}, - {"ATETXMCS", Set_ATE_TX_MCS_Proc}, - {"ATETXMODE", Set_ATE_TX_MODE_Proc}, - {"ATETXGI", Set_ATE_TX_GI_Proc}, - {"ATERXFER", Set_ATE_RX_FER_Proc}, - {"ATERRF", Set_ATE_Read_RF_Proc}, - {"ATEWRF1", Set_ATE_Write_RF1_Proc}, - {"ATEWRF2", Set_ATE_Write_RF2_Proc}, - {"ATEWRF3", Set_ATE_Write_RF3_Proc}, - {"ATEWRF4", Set_ATE_Write_RF4_Proc}, - {"ATELDE2P", Set_ATE_Load_E2P_Proc}, - {"ATERE2P", Set_ATE_Read_E2P_Proc}, - {"ATESHOW", Set_ATE_Show_Proc}, - {"ATEHELP", Set_ATE_Help_Proc}, - -#ifdef RALINK_28xx_QA - {"TxStop", Set_TxStop_Proc}, - {"RxStop", Set_RxStop_Proc}, -#endif // RALINK_28xx_QA // -#endif // RALINK_ATE // - -#ifdef WPA_SUPPLICANT_SUPPORT - {"WpaSupport", Set_Wpa_Support}, -#endif // WPA_SUPPLICANT_SUPPORT // - - - - - - {"FixedTxMode", Set_FixedTxMode_Proc}, -#ifdef CONFIG_APSTA_MIXED_SUPPORT - {"OpMode", Set_OpMode_Proc}, -#endif // CONFIG_APSTA_MIXED_SUPPORT // -#ifdef DOT11_N_SUPPORT - {"TGnWifiTest", Set_TGnWifiTest_Proc}, - {"ForceGF", Set_ForceGF_Proc}, -#endif // DOT11_N_SUPPORT // -#ifdef QOS_DLS_SUPPORT - {"DlsAddEntry", Set_DlsAddEntry_Proc}, - {"DlsTearDownEntry", Set_DlsTearDownEntry_Proc}, -#endif // QOS_DLS_SUPPORT // - {"LongRetry", Set_LongRetryLimit_Proc}, - {"ShortRetry", Set_ShortRetryLimit_Proc}, -#ifdef EXT_BUILD_CHANNEL_LIST - {"11dClientMode", Set_Ieee80211dClientMode_Proc}, -#endif // EXT_BUILD_CHANNEL_LIST // -#ifdef CARRIER_DETECTION_SUPPORT - {"CarrierDetect", Set_CarrierDetect_Proc}, -#endif // CARRIER_DETECTION_SUPPORT // - - -//2008/09/11:KH add to support efuse<-- -#ifdef RT30xx -#ifdef RTMP_EFUSE_SUPPORT - {"efuseFreeNumber", set_eFuseGetFreeBlockCount_Proc}, - {"efuseDump", set_eFusedump_Proc}, - {"efuseLoadFromBin", set_eFuseLoadFromBin_Proc}, - {"efuseBufferModeWriteBack", set_eFuseBufferModeWriteBack_Proc}, -#endif // RTMP_EFUSE_SUPPORT // -#ifdef ANT_DIVERSITY_SUPPORT - {"ant", Set_Antenna_Proc}, -#endif // ANT_DIVERSITY_SUPPORT // -#endif // RT30xx // -//2008/09/11:KH add to support efuse--> - - {"BeaconLostTime", Set_BeaconLostTime_Proc}, - {"AutoRoaming", Set_AutoRoaming_Proc}, - {"SiteSurvey", Set_SiteSurvey_Proc}, - {"ForceTxBurst", Set_ForceTxBurst_Proc}, - - {NULL,} -}; - - -VOID RTMPAddKey( - IN PRTMP_ADAPTER pAd, - IN PNDIS_802_11_KEY pKey) -{ - ULONG KeyIdx; - MAC_TABLE_ENTRY *pEntry; - - DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey ------>\n")); - - if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - { - if (pKey->KeyIndex & 0x80000000) - { - if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - { - NdisZeroMemory(pAd->StaCfg.PMK, 32); - NdisMoveMemory(pAd->StaCfg.PMK, pKey->KeyMaterial, pKey->KeyLength); - goto end; - } - // Update PTK - NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); - pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pKey->KeyMaterial, LEN_TKIP_EK); -#ifdef WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) - { - NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); - NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); - } - else -#endif // WPA_SUPPLICANT_SUPPORT // - { - NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); - NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); - } - - // Decide its ChiperAlg - if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; - else - pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE; - - // Update these related information to MAC_TABLE_ENTRY - pEntry = &pAd->MacTab.Content[BSSID_WCID]; - NdisMoveMemory(pEntry->PairwiseKey.Key, pAd->SharedKey[BSS0][0].Key, LEN_TKIP_EK); - NdisMoveMemory(pEntry->PairwiseKey.RxMic, pAd->SharedKey[BSS0][0].RxMic, LEN_TKIP_RXMICK); - NdisMoveMemory(pEntry->PairwiseKey.TxMic, pAd->SharedKey[BSS0][0].TxMic, LEN_TKIP_TXMICK); - pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; - - // Update pairwise key information to ASIC Shared Key Table - AsicAddSharedKeyEntry(pAd, - BSS0, - 0, - pAd->SharedKey[BSS0][0].CipherAlg, - pAd->SharedKey[BSS0][0].Key, - pAd->SharedKey[BSS0][0].TxMic, - pAd->SharedKey[BSS0][0].RxMic); - - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAd, - BSS0, - 0, - pAd->SharedKey[BSS0][0].CipherAlg, - pEntry); - - if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2) - { - // set 802.1x port control - //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - STA_PORT_SECURED(pAd); - - // Indicate Connected for GUI - pAd->IndicateMediaState = NdisMediaStateConnected; - } - } - else - { - // Update GTK - pAd->StaCfg.DefaultKeyId = (pKey->KeyIndex & 0xFF); - NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY)); - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKey->KeyMaterial, LEN_TKIP_EK); -#ifdef WPA_SUPPLICANT_SUPPORT - if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) - { - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); - } - else -#endif // WPA_SUPPLICANT_SUPPORT // - { - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); - NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); - } - - // Update Shared Key CipherAlg - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE; - if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP; - else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES; - - // Update group key information to ASIC Shared Key Table - AsicAddSharedKeyEntry(pAd, - BSS0, - pAd->StaCfg.DefaultKeyId, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic); - - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAd, - BSS0, - pAd->StaCfg.DefaultKeyId, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, - NULL); - - // set 802.1x port control - //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - STA_PORT_SECURED(pAd); - - // Indicate Connected for GUI - pAd->IndicateMediaState = NdisMediaStateConnected; - } - } - else // dynamic WEP from wpa_supplicant - { - UCHAR CipherAlg; - PUCHAR Key; - - if(pKey->KeyLength == 32) - goto end; - - KeyIdx = pKey->KeyIndex & 0x0fffffff; - - if (KeyIdx < 4) - { - // it is a default shared key, for Pairwise key setting - if (pKey->KeyIndex & 0x80000000) - { - pEntry = MacTableLookup(pAd, pKey->BSSID); - - if (pEntry) - { - DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey: Set Pair-wise Key\n")); - - // set key material and key length - pEntry->PairwiseKey.KeyLen = (UCHAR)pKey->KeyLength; - NdisMoveMemory(pEntry->PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength); - - // set Cipher type - if (pKey->KeyLength == 5) - pEntry->PairwiseKey.CipherAlg = CIPHER_WEP64; - else - pEntry->PairwiseKey.CipherAlg = CIPHER_WEP128; - - // Add Pair-wise key to Asic - AsicAddPairwiseKeyEntry( - pAd, - pEntry->Addr, - (UCHAR)pEntry->Aid, - &pEntry->PairwiseKey); - - // update WCID attribute table and IVEIV table for this entry - RTMPAddWcidAttributeEntry( - pAd, - BSS0, - KeyIdx, // The value may be not zero - pEntry->PairwiseKey.CipherAlg, - pEntry); - - } - } - else - { - // Default key for tx (shared key) - pAd->StaCfg.DefaultKeyId = (UCHAR) KeyIdx; - - // set key material and key length - pAd->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pKey->KeyLength; - NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, &pKey->KeyMaterial, pKey->KeyLength); - - // Set Ciper type - if (pKey->KeyLength == 5) - pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP64; - else - pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP128; - - CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; - Key = pAd->SharedKey[BSS0][KeyIdx].Key; - - // Set Group key material to Asic - AsicAddSharedKeyEntry(pAd, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL); - - // Update WCID attribute table and IVEIV table for this group key table - RTMPAddWcidAttributeEntry(pAd, BSS0, KeyIdx, CipherAlg, NULL); - - } - } - } -end: - return; -} - -char * rtstrchr(const char * s, int c) -{ - for(; *s != (char) c; ++s) - if (*s == '\0') - return NULL; - return (char *) s; -} - -/* -This is required for LinEX2004/kernel2.6.7 to provide iwlist scanning function -*/ - -int -rt_ioctl_giwname(struct net_device *dev, - struct iw_request_info *info, - char *name, char *extra) -{ - -#ifdef RTMP_MAC_PCI - strncpy(name, "RT2860 Wireless", IFNAMSIZ); -#endif // RTMP_MAC_PCI // - return 0; -} - -int rt_ioctl_siwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - int chan = -1; - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - - if (freq->e > 1) - return -EINVAL; - - if((freq->e == 0) && (freq->m <= 1000)) - chan = freq->m; // Setting by channel number - else - MAP_KHZ_TO_CHANNEL_ID( (freq->m /100) , chan); // Setting by frequency - search the table , like 2.412G, 2.422G, - - if (ChannelSanity(pAdapter, chan) == TRUE) - { - pAdapter->CommonCfg.Channel = chan; - DBGPRINT(RT_DEBUG_ERROR, ("==>rt_ioctl_siwfreq::SIOCSIWFREQ[cmd=0x%x] (Channel=%d)\n", SIOCSIWFREQ, pAdapter->CommonCfg.Channel)); - } - else - return -EINVAL; - - return 0; -} - - -int rt_ioctl_giwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - PRTMP_ADAPTER pAdapter = NULL; - UCHAR ch; - ULONG m = 2412000; - - pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - if (pAdapter == NULL) - { - /* if 1st open fail, pAd will be free; - So the net_dev->priv will be NULL in 2rd open */ - return -ENETDOWN; - } - - ch = pAdapter->CommonCfg.Channel; - - DBGPRINT(RT_DEBUG_TRACE,("==>rt_ioctl_giwfreq %d\n", ch)); - - MAP_CHANNEL_ID_TO_KHZ(ch, m); - freq->m = m * 100; - freq->e = 1; - return 0; -} - - -int rt_ioctl_siwmode(struct net_device *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - switch (*mode) - { - case IW_MODE_ADHOC: - Set_NetworkType_Proc(pAdapter, "Adhoc"); - break; - case IW_MODE_INFRA: - Set_NetworkType_Proc(pAdapter, "Infra"); - break; -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) - case IW_MODE_MONITOR: - Set_NetworkType_Proc(pAdapter, "Monitor"); - break; -#endif - default: - DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_siwmode::SIOCSIWMODE (unknown %d)\n", *mode)); - return -EINVAL; - } - - // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key - pAdapter->StaCfg.WpaState = SS_NOTUSE; - - return 0; -} - - -int rt_ioctl_giwmode(struct net_device *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - if (pAdapter == NULL) - { - /* if 1st open fail, pAd will be free; - So the net_dev->priv will be NULL in 2rd open */ - return -ENETDOWN; - } - - if (ADHOC_ON(pAdapter)) - *mode = IW_MODE_ADHOC; - else if (INFRA_ON(pAdapter)) - *mode = IW_MODE_INFRA; -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) - else if (MONITOR_ON(pAdapter)) - { - *mode = IW_MODE_MONITOR; - } -#endif - else - *mode = IW_MODE_AUTO; - - DBGPRINT(RT_DEBUG_TRACE, ("==>rt_ioctl_giwmode(mode=%d)\n", *mode)); - return 0; -} - -int rt_ioctl_siwsens(struct net_device *dev, - struct iw_request_info *info, - char *name, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - return 0; -} - -int rt_ioctl_giwsens(struct net_device *dev, - struct iw_request_info *info, - char *name, char *extra) -{ - return 0; -} - -int rt_ioctl_giwrange(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - struct iw_range *range = (struct iw_range *) extra; - u16 val; - int i; - - if (pAdapter == NULL) - { - /* if 1st open fail, pAd will be free; - So the net_dev->priv will be NULL in 2rd open */ - return -ENETDOWN; - } - - DBGPRINT(RT_DEBUG_TRACE ,("===>rt_ioctl_giwrange\n")); - data->length = sizeof(struct iw_range); - memset(range, 0, sizeof(struct iw_range)); - - range->txpower_capa = IW_TXPOW_DBM; - - if (INFRA_ON(pAdapter)||ADHOC_ON(pAdapter)) - { - range->min_pmp = 1 * 1024; - range->max_pmp = 65535 * 1024; - range->min_pmt = 1 * 1024; - range->max_pmt = 1000 * 1024; - range->pmp_flags = IW_POWER_PERIOD; - range->pmt_flags = IW_POWER_TIMEOUT; - range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | - IW_POWER_UNICAST_R | IW_POWER_ALL_R; - } - - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 14; - - range->retry_capa = IW_RETRY_LIMIT; - range->retry_flags = IW_RETRY_LIMIT; - range->min_retry = 0; - range->max_retry = 255; - - range->num_channels = pAdapter->ChannelListNum; - - val = 0; - for (i = 1; i <= range->num_channels; i++) - { - u32 m = 2412000; - range->freq[val].i = pAdapter->ChannelList[i-1].Channel; - MAP_CHANNEL_ID_TO_KHZ(pAdapter->ChannelList[i-1].Channel, m); - range->freq[val].m = m * 100; /* OS_HZ */ - - range->freq[val].e = 1; - val++; - if (val == IW_MAX_FREQUENCIES) - break; - } - range->num_frequency = val; - - range->max_qual.qual = 100; /* what is correct max? This was not - * documented exactly. At least - * 69 has been observed. */ - range->max_qual.level = 0; /* dB */ - range->max_qual.noise = 0; /* dB */ - - /* What would be suitable values for "average/typical" qual? */ - range->avg_qual.qual = 20; - range->avg_qual.level = -60; - range->avg_qual.noise = -95; - range->sensitivity = 3; - - range->max_encoding_tokens = NR_WEP_KEYS; - range->num_encoding_sizes = 2; - range->encoding_size[0] = 5; - range->encoding_size[1] = 13; - - range->min_rts = 0; - range->max_rts = 2347; - range->min_frag = 256; - range->max_frag = 2346; - -#if WIRELESS_EXT > 17 - /* IW_ENC_CAPA_* bit field */ - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; -#endif - - return 0; -} - -int rt_ioctl_siwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - NDIS_802_11_MAC_ADDRESS Bssid; - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) - { - RTMP_MLME_RESET_STATE_MACHINE(pAdapter); - DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); - } - - // tell CNTL state machine to call NdisMSetInformationComplete() after completing - // this request, because this request is initiated by NDIS. - pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE; - // Prevent to connect AP again in STAMlmePeriodicExec - pAdapter->MlmeAux.AutoReconnectSsidLen= 32; - - memset(Bssid, 0, MAC_ADDR_LEN); - memcpy(Bssid, ap_addr->sa_data, MAC_ADDR_LEN); - MlmeEnqueue(pAdapter, - MLME_CNTL_STATE_MACHINE, - OID_802_11_BSSID, - sizeof(NDIS_802_11_MAC_ADDRESS), - (VOID *)&Bssid); - - DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCSIWAP %02x:%02x:%02x:%02x:%02x:%02x\n", - Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); - - return 0; -} - -int rt_ioctl_giwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - if (pAdapter == NULL) - { - /* if 1st open fail, pAd will be free; - So the net_dev->priv will be NULL in 2rd open */ - return -ENETDOWN; - } - - if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter)) - { - ap_addr->sa_family = ARPHRD_ETHER; - memcpy(ap_addr->sa_data, &pAdapter->CommonCfg.Bssid, ETH_ALEN); - } -#ifdef WPA_SUPPLICANT_SUPPORT - // Add for RT2870 - else if (pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) - { - ap_addr->sa_family = ARPHRD_ETHER; - memcpy(ap_addr->sa_data, &pAdapter->MlmeAux.Bssid, ETH_ALEN); - } -#endif // WPA_SUPPLICANT_SUPPORT // - else - { - DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWAP(=EMPTY)\n")); - return -ENOTCONN; - } - - return 0; -} - -/* - * Units are in db above the noise floor. That means the - * rssi values reported in the tx/rx descriptors in the - * driver are the SNR expressed in db. - * - * If you assume that the noise floor is -95, which is an - * excellent assumption 99.5 % of the time, then you can - * derive the absolute signal level (i.e. -95 + rssi). - * There are some other slight factors to take into account - * depending on whether the rssi measurement is from 11b, - * 11g, or 11a. These differences are at most 2db and - * can be documented. - * - * NB: various calculations are based on the orinoco/wavelan - * drivers for compatibility - */ -static void set_quality(PRTMP_ADAPTER pAdapter, - struct iw_quality *iq, - signed char rssi) -{ - __u8 ChannelQuality; - - // Normalize Rssi - if (rssi >= -50) - ChannelQuality = 100; - else if (rssi >= -80) // between -50 ~ -80dbm - ChannelQuality = (__u8)(24 + ((rssi + 80) * 26)/10); - else if (rssi >= -90) // between -80 ~ -90dbm - ChannelQuality = (__u8)((rssi + 90) * 26)/10; - else - ChannelQuality = 0; - - iq->qual = (__u8)ChannelQuality; - - iq->level = (__u8)(rssi); - iq->noise = (pAdapter->BbpWriteLatch[66] > pAdapter->BbpTuning.FalseCcaUpperThreshold) ? ((__u8)pAdapter->BbpTuning.FalseCcaUpperThreshold) : ((__u8) pAdapter->BbpWriteLatch[66]); // noise level (dBm) - iq->noise += 256 - 143; - iq->updated = pAdapter->iw_stats.qual.updated; -} - -int rt_ioctl_iwaplist(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - struct sockaddr addr[IW_MAX_AP]; - struct iw_quality qual[IW_MAX_AP]; - int i; - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - data->length = 0; - return 0; - //return -ENETDOWN; - } - - for (i = 0; i = pAdapter->ScanTab.BssNr) - break; - addr[i].sa_family = ARPHRD_ETHER; - memcpy(addr[i].sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN); - set_quality(pAdapter, &qual[i], pAdapter->ScanTab.BssEntry[i].Rssi); - } - data->length = i; - memcpy(extra, &addr, i*sizeof(addr[0])); - data->flags = 1; /* signal quality present (sort of) */ - memcpy(extra + i*sizeof(addr[0]), &qual, i*sizeof(qual[i])); - - return 0; -} - -#ifdef SIOCGIWSCAN -int rt_ioctl_siwscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - ULONG Now; - int Status = NDIS_STATUS_SUCCESS; - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - if (MONITOR_ON(pAdapter)) - { - DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n")); - return -EINVAL; - } - - -#ifdef WPA_SUPPLICANT_SUPPORT - if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) - { - pAdapter->StaCfg.WpaSupplicantScanCount++; - } -#endif // WPA_SUPPLICANT_SUPPORT // - - pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE; - if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - return NDIS_STATUS_SUCCESS; - do{ - Now = jiffies; - -#ifdef WPA_SUPPLICANT_SUPPORT - if ((pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) && - (pAdapter->StaCfg.WpaSupplicantScanCount > 3)) - { - DBGPRINT(RT_DEBUG_TRACE, ("!!! WpaSupplicantScanCount > 3\n")); - Status = NDIS_STATUS_SUCCESS; - break; - } -#endif // WPA_SUPPLICANT_SUPPORT // - - if ((OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) && - ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || - (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) && - (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) - { - DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); - Status = NDIS_STATUS_SUCCESS; - break; - } - - if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) - { - RTMP_MLME_RESET_STATE_MACHINE(pAdapter); - DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); - } - - // tell CNTL state machine to call NdisMSetInformationComplete() after completing - // this request, because this request is initiated by NDIS. - pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE; - // Reset allowed scan retries - pAdapter->StaCfg.ScanCnt = 0; - pAdapter->StaCfg.LastScanTime = Now; - - MlmeEnqueue(pAdapter, - MLME_CNTL_STATE_MACHINE, - OID_802_11_BSSID_LIST_SCAN, - 0, - NULL); - - Status = NDIS_STATUS_SUCCESS; - RTMP_MLME_HANDLER(pAdapter); - }while(0); - return NDIS_STATUS_SUCCESS; -} - -int rt_ioctl_giwscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - int i=0; - PSTRING current_ev = extra, previous_ev = extra; - PSTRING end_buf; - PSTRING current_val; - STRING custom[MAX_CUSTOM_LEN] = {0}; -#ifndef IWEVGENIE - unsigned char idx; -#endif // IWEVGENIE // - struct iw_event iwe; - - if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - { - /* - * Still scanning, indicate the caller should try again. - */ - return -EAGAIN; - } - - -#ifdef WPA_SUPPLICANT_SUPPORT - if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) - { - pAdapter->StaCfg.WpaSupplicantScanCount = 0; - } -#endif // WPA_SUPPLICANT_SUPPORT // - - if (pAdapter->ScanTab.BssNr == 0) - { - data->length = 0; - return 0; - } - -#if WIRELESS_EXT >= 17 - if (data->length > 0) - end_buf = extra + data->length; - else - end_buf = extra + IW_SCAN_MAX_DATA; -#else - end_buf = extra + IW_SCAN_MAX_DATA; -#endif - - for (i = 0; i < pAdapter->ScanTab.BssNr; i++) - { - if (current_ev >= end_buf) - { -#if WIRELESS_EXT >= 17 - return -E2BIG; -#else - break; -#endif - } - - //MAC address - //================================ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, ETH_ALEN); - - previous_ev = current_ev; - current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN); - if (current_ev == previous_ev) -#if WIRELESS_EXT >= 17 - return -E2BIG; -#else - break; -#endif - - /* - Protocol: - it will show scanned AP's WirelessMode . - it might be - 802.11a - 802.11a/n - 802.11g/n - 802.11b/g/n - 802.11g - 802.11b/g - */ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWNAME; - - - { - PBSS_ENTRY pBssEntry=&pAdapter->ScanTab.BssEntry[i]; - BOOLEAN isGonly=FALSE; - int rateCnt=0; - - if (pBssEntry->Channel>14) - { - if (pBssEntry->HtCapabilityLen!=0) - strcpy(iwe.u.name,"802.11a/n"); - else - strcpy(iwe.u.name,"802.11a"); - } - else - { - /* - if one of non B mode rate is set supported rate . it mean G only. - */ - for (rateCnt=0;rateCntSupRateLen;rateCnt++) - { - /* - 6Mbps(140) 9Mbps(146) and >=12Mbps(152) are supported rate , it mean G only. - */ - if (pBssEntry->SupRate[rateCnt]==140 || pBssEntry->SupRate[rateCnt]==146 || pBssEntry->SupRate[rateCnt]>=152) - isGonly=TRUE; - } - - for (rateCnt=0;rateCntExtRateLen;rateCnt++) - { - if (pBssEntry->ExtRate[rateCnt]==140 || pBssEntry->ExtRate[rateCnt]==146 || pBssEntry->ExtRate[rateCnt]>=152) - isGonly=TRUE; - } - - - if (pBssEntry->HtCapabilityLen!=0) - { - if (isGonly==TRUE) - strcpy(iwe.u.name,"802.11g/n"); - else - strcpy(iwe.u.name,"802.11b/g/n"); - } - else - { - if (isGonly==TRUE) - strcpy(iwe.u.name,"802.11g"); - else - { - if (pBssEntry->SupRateLen==4 && pBssEntry->ExtRateLen==0) - strcpy(iwe.u.name,"802.11b"); - else - strcpy(iwe.u.name,"802.11b/g"); - } - } - } - } - - previous_ev = current_ev; - current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN); - if (current_ev == previous_ev) -#if WIRELESS_EXT >= 17 - return -E2BIG; -#else - break; -#endif - - //ESSID - //================================ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWESSID; - iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].SsidLen; - iwe.u.data.flags = 1; - - previous_ev = current_ev; - current_ev = IWE_STREAM_ADD_POINT(info, current_ev,end_buf, &iwe, (PSTRING) pAdapter->ScanTab.BssEntry[i].Ssid); - if (current_ev == previous_ev) -#if WIRELESS_EXT >= 17 - return -E2BIG; -#else - break; -#endif - - //Network Type - //================================ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWMODE; - if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11IBSS) - { - iwe.u.mode = IW_MODE_ADHOC; - } - else if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11Infrastructure) - { - iwe.u.mode = IW_MODE_INFRA; - } - else - { - iwe.u.mode = IW_MODE_AUTO; - } - iwe.len = IW_EV_UINT_LEN; - - previous_ev = current_ev; - current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN); - if (current_ev == previous_ev) -#if WIRELESS_EXT >= 17 - return -E2BIG; -#else - break; -#endif - - //Channel and Frequency - //================================ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWFREQ; - if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter)) - iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel; - else - iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel; - iwe.u.freq.e = 0; - iwe.u.freq.i = 0; - - previous_ev = current_ev; - current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_FREQ_LEN); - if (current_ev == previous_ev) -#if WIRELESS_EXT >= 17 - return -E2BIG; -#else - break; -#endif - - //Add quality statistics - //================================ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVQUAL; - iwe.u.qual.level = 0; - iwe.u.qual.noise = 0; - set_quality(pAdapter, &iwe.u.qual, pAdapter->ScanTab.BssEntry[i].Rssi); - current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); - if (current_ev == previous_ev) -#if WIRELESS_EXT >= 17 - return -E2BIG; -#else - break; -#endif - - //Encyption key - //================================ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWENCODE; - if (CAP_IS_PRIVACY_ON (pAdapter->ScanTab.BssEntry[i].CapabilityInfo )) - iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - - previous_ev = current_ev; - current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,&iwe, (char *)pAdapter->SharedKey[BSS0][(iwe.u.data.flags & IW_ENCODE_INDEX)-1].Key); - if (current_ev == previous_ev) -#if WIRELESS_EXT >= 17 - return -E2BIG; -#else - break; -#endif - - //Bit Rate - //================================ - if (pAdapter->ScanTab.BssEntry[i].SupRateLen) - { - UCHAR tmpRate = pAdapter->ScanTab.BssEntry[i].SupRate[pAdapter->ScanTab.BssEntry[i].SupRateLen-1]; - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWRATE; - current_val = current_ev + IW_EV_LCP_LEN; - if (tmpRate == 0x82) - iwe.u.bitrate.value = 1 * 1000000; - else if (tmpRate == 0x84) - iwe.u.bitrate.value = 2 * 1000000; - else if (tmpRate == 0x8B) - iwe.u.bitrate.value = 5.5 * 1000000; - else if (tmpRate == 0x96) - iwe.u.bitrate.value = 11 * 1000000; - else - iwe.u.bitrate.value = (tmpRate/2) * 1000000; - - if (tmpRate == 0x6c && pAdapter->ScanTab.BssEntry[i].HtCapabilityLen > 0) - { - int rate_count = sizeof(ralinkrate)/sizeof(__s32); - HT_CAP_INFO capInfo = pAdapter->ScanTab.BssEntry[i].HtCapability.HtCapInfo; - int shortGI = capInfo.ChannelWidth ? capInfo.ShortGIfor40 : capInfo.ShortGIfor20; - int maxMCS = pAdapter->ScanTab.BssEntry[i].HtCapability.MCSSet[1] ? 15 : 7; - int rate_index = 12 + ((UCHAR)capInfo.ChannelWidth * 24) + ((UCHAR)shortGI *48) + ((UCHAR)maxMCS); - if (rate_index < 0) - rate_index = 0; - if (rate_index > rate_count) - rate_index = rate_count; - iwe.u.bitrate.value = ralinkrate[rate_index] * 500000; - } - - iwe.u.bitrate.disabled = 0; - current_val = IWE_STREAM_ADD_VALUE(info, current_ev, - current_val, end_buf, &iwe, - IW_EV_PARAM_LEN); - - if((current_val-current_ev)>IW_EV_LCP_LEN) - current_ev = current_val; - else -#if WIRELESS_EXT >= 17 - return -E2BIG; -#else - break; -#endif - } - -#ifdef IWEVGENIE - //WPA IE - if (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen > 0) - { - memset(&iwe, 0, sizeof(iwe)); - memset(&custom[0], 0, MAX_CUSTOM_LEN); - memcpy(custom, &(pAdapter->ScanTab.BssEntry[i].WpaIE.IE[0]), - pAdapter->ScanTab.BssEntry[i].WpaIE.IELen); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].WpaIE.IELen; - current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom); - if (current_ev == previous_ev) -#if WIRELESS_EXT >= 17 - return -E2BIG; -#else - break; -#endif - } - - //WPA2 IE - if (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen > 0) - { - memset(&iwe, 0, sizeof(iwe)); - memset(&custom[0], 0, MAX_CUSTOM_LEN); - memcpy(custom, &(pAdapter->ScanTab.BssEntry[i].RsnIE.IE[0]), - pAdapter->ScanTab.BssEntry[i].RsnIE.IELen); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].RsnIE.IELen; - current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom); - if (current_ev == previous_ev) -#if WIRELESS_EXT >= 17 - return -E2BIG; -#else - break; -#endif - } -#else - //WPA IE - //================================ - if (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen > 0) - { - NdisZeroMemory(&iwe, sizeof(iwe)); - memset(&custom[0], 0, MAX_CUSTOM_LEN); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen * 2) + 7; - NdisMoveMemory(custom, "wpa_ie=", 7); - for (idx = 0; idx < pAdapter->ScanTab.BssEntry[i].WpaIE.IELen; idx++) - sprintf(custom, "%s%02x", custom, pAdapter->ScanTab.BssEntry[i].WpaIE.IE[idx]); - previous_ev = current_ev; - current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom); - if (current_ev == previous_ev) -#if WIRELESS_EXT >= 17 - return -E2BIG; -#else - break; -#endif - } - - //WPA2 IE - if (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen > 0) - { - NdisZeroMemory(&iwe, sizeof(iwe)); - memset(&custom[0], 0, MAX_CUSTOM_LEN); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen * 2) + 7; - NdisMoveMemory(custom, "rsn_ie=", 7); - for (idx = 0; idx < pAdapter->ScanTab.BssEntry[i].RsnIE.IELen; idx++) - sprintf(custom, "%s%02x", custom, pAdapter->ScanTab.BssEntry[i].RsnIE.IE[idx]); - previous_ev = current_ev; - current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, custom); - if (current_ev == previous_ev) -#if WIRELESS_EXT >= 17 - return -E2BIG; -#else - break; -#endif - } -#endif // IWEVGENIE // - } - - data->length = current_ev - extra; - pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; - DBGPRINT(RT_DEBUG_ERROR ,("===>rt_ioctl_giwscan. %d(%d) BSS returned, data->length = %d\n",i , pAdapter->ScanTab.BssNr, data->length)); - return 0; -} -#endif - -int rt_ioctl_siwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *essid) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - if (data->flags) - { - PSTRING pSsidString = NULL; - - // Includes null character. - if (data->length > (IW_ESSID_MAX_SIZE + 1)) - return -E2BIG; - - pSsidString = kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG); - if (pSsidString) - { - NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1); - NdisMoveMemory(pSsidString, essid, data->length); - if (Set_SSID_Proc(pAdapter, pSsidString) == FALSE) - return -EINVAL; - } - else - return -ENOMEM; - } - else - { - // ANY ssid - if (Set_SSID_Proc(pAdapter, "") == FALSE) - return -EINVAL; - } - return 0; -} - -int rt_ioctl_giwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *essid) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - if (pAdapter == NULL) - { - /* if 1st open fail, pAd will be free; - So the net_dev->priv will be NULL in 2rd open */ - return -ENETDOWN; - } - - data->flags = 1; - if (MONITOR_ON(pAdapter)) - { - data->length = 0; - return 0; - } - - if (OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) - { - DBGPRINT(RT_DEBUG_TRACE ,("MediaState is connected\n")); - data->length = pAdapter->CommonCfg.SsidLen; - memcpy(essid, pAdapter->CommonCfg.Ssid, pAdapter->CommonCfg.SsidLen); - } - else - {//the ANY ssid was specified - data->length = 0; - DBGPRINT(RT_DEBUG_TRACE ,("MediaState is not connected, ess\n")); - } - - return 0; - -} - -int rt_ioctl_siwnickn(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *nickname) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE ,("INFO::Network is down!\n")); - return -ENETDOWN; - } - - if (data->length > IW_ESSID_MAX_SIZE) - return -EINVAL; - - memset(pAdapter->nickname, 0, IW_ESSID_MAX_SIZE + 1); - memcpy(pAdapter->nickname, nickname, data->length); - - - return 0; -} - -int rt_ioctl_giwnickn(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *nickname) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - if (pAdapter == NULL) - { - /* if 1st open fail, pAd will be free; - So the net_dev->priv will be NULL in 2rd open */ - return -ENETDOWN; - } - - if (data->length > strlen((PSTRING) pAdapter->nickname) + 1) - data->length = strlen((PSTRING) pAdapter->nickname) + 1; - if (data->length > 0) { - memcpy(nickname, pAdapter->nickname, data->length-1); - nickname[data->length-1] = '\0'; - } - return 0; -} - -int rt_ioctl_siwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - u16 val; - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - if (rts->disabled) - val = MAX_RTS_THRESHOLD; - else if (rts->value < 0 || rts->value > MAX_RTS_THRESHOLD) - return -EINVAL; - else if (rts->value == 0) - val = MAX_RTS_THRESHOLD; - else - val = rts->value; - - if (val != pAdapter->CommonCfg.RtsThreshold) - pAdapter->CommonCfg.RtsThreshold = val; - - return 0; -} - -int rt_ioctl_giwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - if (pAdapter == NULL) - { - /* if 1st open fail, pAd will be free; - So the net_dev->priv will be NULL in 2rd open */ - return -ENETDOWN; - } - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - rts->value = pAdapter->CommonCfg.RtsThreshold; - rts->disabled = (rts->value == MAX_RTS_THRESHOLD); - rts->fixed = 1; - - return 0; -} - -int rt_ioctl_siwfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - u16 val; - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - if (frag->disabled) - val = MAX_FRAG_THRESHOLD; - else if (frag->value >= MIN_FRAG_THRESHOLD || frag->value <= MAX_FRAG_THRESHOLD) - val = __cpu_to_le16(frag->value & ~0x1); /* even numbers only */ - else if (frag->value == 0) - val = MAX_FRAG_THRESHOLD; - else - return -EINVAL; - - pAdapter->CommonCfg.FragmentThreshold = val; - return 0; -} - -int rt_ioctl_giwfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - if (pAdapter == NULL) - { - /* if 1st open fail, pAd will be free; - So the net_dev->priv will be NULL in 2rd open */ - return -ENETDOWN; - } - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - frag->value = pAdapter->CommonCfg.FragmentThreshold; - frag->disabled = (frag->value == MAX_FRAG_THRESHOLD); - frag->fixed = 1; - - return 0; -} - -#define MAX_WEP_KEY_SIZE 13 -#define MIN_WEP_KEY_SIZE 5 -int rt_ioctl_siwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - if ((erq->length == 0) && - (erq->flags & IW_ENCODE_DISABLED)) - { - pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; - pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; - pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; - goto done; - } - else if (erq->flags & IW_ENCODE_RESTRICTED || erq->flags & IW_ENCODE_OPEN) - { - //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - STA_PORT_SECURED(pAdapter); - pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled; - pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled; - pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled; - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; - if (erq->flags & IW_ENCODE_RESTRICTED) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared; - else - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; - } - - if (erq->length > 0) - { - int keyIdx = (erq->flags & IW_ENCODE_INDEX) - 1; - /* Check the size of the key */ - if (erq->length > MAX_WEP_KEY_SIZE) - { - return -EINVAL; - } - /* Check key index */ - if ((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS)) - { - DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::Wrong keyIdx=%d! Using default key instead (%d)\n", - keyIdx, pAdapter->StaCfg.DefaultKeyId)); - - //Using default key - keyIdx = pAdapter->StaCfg.DefaultKeyId; - } - else - pAdapter->StaCfg.DefaultKeyId = keyIdx; - - NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, 16); - - if (erq->length == MAX_WEP_KEY_SIZE) - { - pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE; - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128; - } - else if (erq->length == MIN_WEP_KEY_SIZE) - { - pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE; - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64; - } - else - /* Disable the key */ - pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0; - - /* Check if the key is not marked as invalid */ - if(!(erq->flags & IW_ENCODE_NOKEY)) - { - /* Copy the key in the driver */ - NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, extra, erq->length); - } - } - else - { - /* Do we want to just set the transmit key index ? */ - int index = (erq->flags & IW_ENCODE_INDEX) - 1; - if ((index >= 0) && (index < 4)) - { - pAdapter->StaCfg.DefaultKeyId = index; - } - else - /* Don't complain if only change the mode */ - if (!(erq->flags & IW_ENCODE_MODE)) - return -EINVAL; - } - -done: - DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::erq->flags=%x\n",erq->flags)); - DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::AuthMode=%x\n",pAdapter->StaCfg.AuthMode)); - DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::DefaultKeyId=%x, KeyLen = %d\n",pAdapter->StaCfg.DefaultKeyId , pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen)); - DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::WepStatus=%x\n",pAdapter->StaCfg.WepStatus)); - return 0; -} - -int -rt_ioctl_giwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *key) -{ - int kid; - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - if (pAdapter == NULL) - { - /* if 1st open fail, pAd will be free; - So the net_dev->priv will be NULL in 2rd open */ - return -ENETDOWN; - } - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - kid = erq->flags & IW_ENCODE_INDEX; - DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_giwencode %d\n", erq->flags & IW_ENCODE_INDEX)); - - if (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled) - { - erq->length = 0; - erq->flags = IW_ENCODE_DISABLED; - } - else if ((kid > 0) && (kid <=4)) - { - // copy wep key - erq->flags = kid ; /* NB: base 1 */ - if (erq->length > pAdapter->SharedKey[BSS0][kid-1].KeyLen) - erq->length = pAdapter->SharedKey[BSS0][kid-1].KeyLen; - memcpy(key, pAdapter->SharedKey[BSS0][kid-1].Key, erq->length); - //if ((kid == pAdapter->PortCfg.DefaultKeyId)) - //erq->flags |= IW_ENCODE_ENABLED; /* XXX */ - if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) - erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ - else - erq->flags |= IW_ENCODE_OPEN; /* XXX */ - - } - else if (kid == 0) - { - if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) - erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ - else - erq->flags |= IW_ENCODE_OPEN; /* XXX */ - erq->length = pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen; - memcpy(key, pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key, erq->length); - // copy default key ID - if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) - erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ - else - erq->flags |= IW_ENCODE_OPEN; /* XXX */ - erq->flags = pAdapter->StaCfg.DefaultKeyId + 1; /* NB: base 1 */ - erq->flags |= IW_ENCODE_ENABLED; /* XXX */ - } - - return 0; - -} - -static int -rt_ioctl_setparam(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - PRTMP_ADAPTER pAdapter; - POS_COOKIE pObj; - PSTRING this_char = extra; - PSTRING value; - int Status=0; - - pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - if (pAdapter == NULL) - { - /* if 1st open fail, pAd will be free; - So the net_dev->priv will be NULL in 2rd open */ - return -ENETDOWN; - } - - pObj = (POS_COOKIE) pAdapter->OS_Cookie; - { - pObj->ioctl_if_type = INT_MAIN; - pObj->ioctl_if = MAIN_MBSSID; - } - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - if (!*this_char) - return -EINVAL; - - if ((value = rtstrchr(this_char, '=')) != NULL) - *value++ = 0; - - if (!value && (strcmp(this_char, "SiteSurvey") != 0)) - return -EINVAL; - else - goto SET_PROC; - - // reject setting nothing besides ANY ssid(ssidLen=0) - if (!*value && (strcmp(this_char, "SSID") != 0)) - return -EINVAL; - -SET_PROC: - for (PRTMP_PRIVATE_SET_PROC = RTMP_PRIVATE_SUPPORT_PROC; PRTMP_PRIVATE_SET_PROC->name; PRTMP_PRIVATE_SET_PROC++) - { - if (strcmp(this_char, PRTMP_PRIVATE_SET_PROC->name) == 0) - { - if(!PRTMP_PRIVATE_SET_PROC->set_proc(pAdapter, value)) - { //FALSE:Set private failed then return Invalid argument - Status = -EINVAL; - } - break; //Exit for loop. - } - } - - if(PRTMP_PRIVATE_SET_PROC->name == NULL) - { //Not found argument - Status = -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_setparam:: (iwpriv) Not Support Set Command [%s=%s]\n", this_char, value)); - } - - return Status; -} - - -static int -rt_private_get_statistics(struct net_device *dev, struct iw_request_info *info, - struct iw_point *wrq, char *extra) -{ - INT Status = 0; - PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(dev); - - if (extra == NULL) - { - wrq->length = 0; - return -EIO; - } - - memset(extra, 0x00, IW_PRIV_SIZE_MASK); - sprintf(extra, "\n\n"); - -#ifdef RALINK_ATE - if (ATE_ON(pAd)) - { - sprintf(extra+strlen(extra), "Tx success = %ld\n", (ULONG)pAd->ate.TxDoneCount); - //sprintf(extra+strlen(extra), "Tx success without retry = %ld\n", (ULONG)pAd->ate.TxDoneCount); - } - else -#endif // RALINK_ATE // - { - sprintf(extra+strlen(extra), "Tx success = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.QuadPart); - sprintf(extra+strlen(extra), "Tx success without retry = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.QuadPart - (ULONG)pAd->WlanCounters.RetryCount.QuadPart); - } - sprintf(extra+strlen(extra), "Tx success after retry = %ld\n", (ULONG)pAd->WlanCounters.RetryCount.QuadPart); - sprintf(extra+strlen(extra), "Tx fail to Rcv ACK after retry = %ld\n", (ULONG)pAd->WlanCounters.FailedCount.QuadPart); - sprintf(extra+strlen(extra), "RTS Success Rcv CTS = %ld\n", (ULONG)pAd->WlanCounters.RTSSuccessCount.QuadPart); - sprintf(extra+strlen(extra), "RTS Fail Rcv CTS = %ld\n", (ULONG)pAd->WlanCounters.RTSFailureCount.QuadPart); - - sprintf(extra+strlen(extra), "Rx success = %ld\n", (ULONG)pAd->WlanCounters.ReceivedFragmentCount.QuadPart); - sprintf(extra+strlen(extra), "Rx with CRC = %ld\n", (ULONG)pAd->WlanCounters.FCSErrorCount.QuadPart); - sprintf(extra+strlen(extra), "Rx drop due to out of resource = %ld\n", (ULONG)pAd->Counters8023.RxNoBuffer); - sprintf(extra+strlen(extra), "Rx duplicate frame = %ld\n", (ULONG)pAd->WlanCounters.FrameDuplicateCount.QuadPart); - - sprintf(extra+strlen(extra), "False CCA (one second) = %ld\n", (ULONG)pAd->RalinkCounters.OneSecFalseCCACnt); - -#ifdef RALINK_ATE - if (ATE_ON(pAd)) - { - if (pAd->ate.RxAntennaSel == 0) - { - sprintf(extra+strlen(extra), "RSSI-A = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta)); - sprintf(extra+strlen(extra), "RSSI-B (if available) = %ld\n", (LONG)(pAd->ate.LastRssi1 - pAd->BbpRssiToDbmDelta)); - sprintf(extra+strlen(extra), "RSSI-C (if available) = %ld\n\n", (LONG)(pAd->ate.LastRssi2 - pAd->BbpRssiToDbmDelta)); - } - else - { - sprintf(extra+strlen(extra), "RSSI = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta)); - } - } - else -#endif // RALINK_ATE // - { - sprintf(extra+strlen(extra), "RSSI-A = %ld\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi0 - pAd->BbpRssiToDbmDelta)); - sprintf(extra+strlen(extra), "RSSI-B (if available) = %ld\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi1 - pAd->BbpRssiToDbmDelta)); - sprintf(extra+strlen(extra), "RSSI-C (if available) = %ld\n\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi2 - pAd->BbpRssiToDbmDelta)); - } -#ifdef WPA_SUPPLICANT_SUPPORT - sprintf(extra+strlen(extra), "WpaSupplicantUP = %d\n\n", pAd->StaCfg.WpaSupplicantUP); -#endif // WPA_SUPPLICANT_SUPPORT // - - - - wrq->length = strlen(extra) + 1; // 1: size of '\0' - DBGPRINT(RT_DEBUG_TRACE, ("<== rt_private_get_statistics, wrq->length = %d\n", wrq->length)); - - return Status; -} - -#ifdef DOT11_N_SUPPORT -void getBaInfo( - IN PRTMP_ADAPTER pAd, - IN PSTRING pOutBuf) -{ - INT i, j; - BA_ORI_ENTRY *pOriBAEntry; - BA_REC_ENTRY *pRecBAEntry; - - for (i=0; iMacTab.Content[i]; - if (((pEntry->ValidAsCLI || pEntry->ValidAsApCli) && (pEntry->Sst == SST_ASSOC)) - || (pEntry->ValidAsWDS) || (pEntry->ValidAsMesh)) - { - sprintf(pOutBuf, "%s\n%02X:%02X:%02X:%02X:%02X:%02X (Aid = %d) (AP) -\n", - pOutBuf, - pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], - pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5], pEntry->Aid); - - sprintf(pOutBuf, "%s[Recipient]\n", pOutBuf); - for (j=0; j < NUM_OF_TID; j++) - { - if (pEntry->BARecWcidArray[j] != 0) - { - pRecBAEntry =&pAd->BATable.BARecEntry[pEntry->BARecWcidArray[j]]; - sprintf(pOutBuf, "%sTID=%d, BAWinSize=%d, LastIndSeq=%d, ReorderingPkts=%d\n", pOutBuf, j, pRecBAEntry->BAWinSize, pRecBAEntry->LastIndSeq, pRecBAEntry->list.qlen); - } - } - sprintf(pOutBuf, "%s\n", pOutBuf); - - sprintf(pOutBuf, "%s[Originator]\n", pOutBuf); - for (j=0; j < NUM_OF_TID; j++) - { - if (pEntry->BAOriWcidArray[j] != 0) - { - pOriBAEntry =&pAd->BATable.BAOriEntry[pEntry->BAOriWcidArray[j]]; - sprintf(pOutBuf, "%sTID=%d, BAWinSize=%d, StartSeq=%d, CurTxSeq=%d\n", pOutBuf, j, pOriBAEntry->BAWinSize, pOriBAEntry->Sequence, pEntry->TxSeq[j]); - } - } - sprintf(pOutBuf, "%s\n\n", pOutBuf); - } - if (strlen(pOutBuf) > (IW_PRIV_SIZE_MASK - 30)) - break; - } - - return; -} -#endif // DOT11_N_SUPPORT // - -static int -rt_private_show(struct net_device *dev, struct iw_request_info *info, - struct iw_point *wrq, PSTRING extra) -{ - INT Status = 0; - PRTMP_ADAPTER pAd; - POS_COOKIE pObj; - u32 subcmd = wrq->flags; - - pAd = RTMP_OS_NETDEV_GET_PRIV(dev); - if (pAd == NULL) - { - /* if 1st open fail, pAd will be free; - So the net_dev->priv will be NULL in 2rd open */ - return -ENETDOWN; - } - - pObj = (POS_COOKIE) pAd->OS_Cookie; - if (extra == NULL) - { - wrq->length = 0; - return -EIO; - } - memset(extra, 0x00, IW_PRIV_SIZE_MASK); - - { - pObj->ioctl_if_type = INT_MAIN; - pObj->ioctl_if = MAIN_MBSSID; - } - - switch(subcmd) - { - - case SHOW_CONN_STATUS: - if (MONITOR_ON(pAd)) - { -#ifdef DOT11_N_SUPPORT - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && - pAd->CommonCfg.RegTransmitSetting.field.BW) - sprintf(extra, "Monitor Mode(CentralChannel %d)\n", pAd->CommonCfg.CentralChannel); - else -#endif // DOT11_N_SUPPORT // - sprintf(extra, "Monitor Mode(Channel %d)\n", pAd->CommonCfg.Channel); - } - else - { - if (pAd->IndicateMediaState == NdisMediaStateConnected) - { - if (INFRA_ON(pAd)) - { - sprintf(extra, "Connected(AP: %s[%02X:%02X:%02X:%02X:%02X:%02X])\n", - pAd->CommonCfg.Ssid, - pAd->CommonCfg.Bssid[0], - pAd->CommonCfg.Bssid[1], - pAd->CommonCfg.Bssid[2], - pAd->CommonCfg.Bssid[3], - pAd->CommonCfg.Bssid[4], - pAd->CommonCfg.Bssid[5]); - DBGPRINT(RT_DEBUG_TRACE ,("Ssid=%s ,Ssidlen = %d\n",pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)); - } - else if (ADHOC_ON(pAd)) - sprintf(extra, "Connected\n"); - } - else - { - sprintf(extra, "Disconnected\n"); - DBGPRINT(RT_DEBUG_TRACE ,("ConnStatus is not connected\n")); - } - } - wrq->length = strlen(extra) + 1; // 1: size of '\0' - break; - case SHOW_DRVIER_VERION: - sprintf(extra, "Driver version-%s, %s %s\n", STA_DRIVER_VERSION, __DATE__, __TIME__ ); - wrq->length = strlen(extra) + 1; // 1: size of '\0' - break; -#ifdef DOT11_N_SUPPORT - case SHOW_BA_INFO: - getBaInfo(pAd, extra); - wrq->length = strlen(extra) + 1; // 1: size of '\0' - break; -#endif // DOT11_N_SUPPORT // - case SHOW_DESC_INFO: - { - Show_DescInfo_Proc(pAd, NULL); - wrq->length = 0; // 1: size of '\0' - } - break; - case RAIO_OFF: - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - { - if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) - { - RTMP_MLME_RESET_STATE_MACHINE(pAd); - DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); - } - } - pAd->StaCfg.bSwRadio = FALSE; - if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) - { - pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); - if (pAd->StaCfg.bRadio == FALSE) - { - MlmeRadioOff(pAd); - // Update extra information - pAd->ExtraInfo = SW_RADIO_OFF; - } - } - sprintf(extra, "Radio Off\n"); - wrq->length = strlen(extra) + 1; // 1: size of '\0' - break; - case RAIO_ON: - pAd->StaCfg.bSwRadio = TRUE; - //if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) - { - pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); - if (pAd->StaCfg.bRadio == TRUE) - { - MlmeRadioOn(pAd); - // Update extra information - pAd->ExtraInfo = EXTRA_INFO_CLEAR; - } - } - sprintf(extra, "Radio On\n"); - wrq->length = strlen(extra) + 1; // 1: size of '\0' - break; - - -#ifdef QOS_DLS_SUPPORT - case SHOW_DLS_ENTRY_INFO: - { - Set_DlsEntryInfo_Display_Proc(pAd, NULL); - wrq->length = 0; // 1: size of '\0' - } - break; -#endif // QOS_DLS_SUPPORT // - - case SHOW_CFG_VALUE: - { - Status = RTMPShowCfgValue(pAd, (PSTRING) wrq->pointer, extra); - if (Status == 0) - wrq->length = strlen(extra) + 1; // 1: size of '\0' - } - break; - case SHOW_ADHOC_ENTRY_INFO: - Show_Adhoc_MacTable_Proc(pAd, extra); - wrq->length = strlen(extra) + 1; // 1: size of '\0' - break; - default: - DBGPRINT(RT_DEBUG_TRACE, ("%s - unknow subcmd = %d\n", __FUNCTION__, subcmd)); - break; - } - - return Status; -} - -#ifdef SIOCSIWMLME -int rt_ioctl_siwmlme(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(dev); - struct iw_mlme *pMlme = (struct iw_mlme *)wrqu->data.pointer; - MLME_QUEUE_ELEM MsgElem; - MLME_DISASSOC_REQ_STRUCT DisAssocReq; - MLME_DEAUTH_REQ_STRUCT DeAuthReq; - - DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__)); - - if (pMlme == NULL) - return -EINVAL; - - switch(pMlme->cmd) - { -#ifdef IW_MLME_DEAUTH - case IW_MLME_DEAUTH: - DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DEAUTH\n", __FUNCTION__)); - COPY_MAC_ADDR(DeAuthReq.Addr, pAd->CommonCfg.Bssid); - DeAuthReq.Reason = pMlme->reason_code; - MsgElem.MsgLen = sizeof(MLME_DEAUTH_REQ_STRUCT); - NdisMoveMemory(MsgElem.Msg, &DeAuthReq, sizeof(MLME_DEAUTH_REQ_STRUCT)); - MlmeDeauthReqAction(pAd, &MsgElem); - if (INFRA_ON(pAd)) - { - LinkDown(pAd, FALSE); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - } - break; -#endif // IW_MLME_DEAUTH // -#ifdef IW_MLME_DISASSOC - case IW_MLME_DISASSOC: - DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DISASSOC\n", __FUNCTION__)); - COPY_MAC_ADDR(DisAssocReq.Addr, pAd->CommonCfg.Bssid); - DisAssocReq.Reason = pMlme->reason_code; - - MsgElem.Machine = ASSOC_STATE_MACHINE; - MsgElem.MsgType = MT2_MLME_DISASSOC_REQ; - MsgElem.MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); - NdisMoveMemory(MsgElem.Msg, &DisAssocReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); - - pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; - MlmeDisassocReqAction(pAd, &MsgElem); - break; -#endif // IW_MLME_DISASSOC // - default: - DBGPRINT(RT_DEBUG_TRACE, ("====> %s - Unknow Command\n", __FUNCTION__)); - break; - } - - return 0; -} -#endif // SIOCSIWMLME // - -#if WIRELESS_EXT > 17 -int rt_ioctl_siwauth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - struct iw_param *param = &wrqu->param; - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - if (param->value == IW_AUTH_WPA_VERSION_WPA) - { - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; - if (pAdapter->StaCfg.BssType == BSS_ADHOC) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; - } - else if (param->value == IW_AUTH_WPA_VERSION_WPA2) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; - - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __FUNCTION__, param->value)); - break; - case IW_AUTH_CIPHER_PAIRWISE: - if (param->value == IW_AUTH_CIPHER_NONE) - { - pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; - pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; - } - else if (param->value == IW_AUTH_CIPHER_WEP40 || - param->value == IW_AUTH_CIPHER_WEP104) - { - pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled; - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; - pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled; -#ifdef WPA_SUPPLICANT_SUPPORT - pAdapter->StaCfg.IEEE8021X = FALSE; -#endif // WPA_SUPPLICANT_SUPPORT // - } - else if (param->value == IW_AUTH_CIPHER_TKIP) - { - pAdapter->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; - pAdapter->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; - } - else if (param->value == IW_AUTH_CIPHER_CCMP) - { - pAdapter->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; - pAdapter->StaCfg.PairCipher = Ndis802_11Encryption3Enabled; - } - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_PAIRWISE - param->value = %d!\n", __FUNCTION__, param->value)); - break; - case IW_AUTH_CIPHER_GROUP: - if (param->value == IW_AUTH_CIPHER_NONE) - { - pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; - } - else if (param->value == IW_AUTH_CIPHER_WEP40 || - param->value == IW_AUTH_CIPHER_WEP104) - { - pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled; - } - else if (param->value == IW_AUTH_CIPHER_TKIP) - { - pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption2Enabled; - } - else if (param->value == IW_AUTH_CIPHER_CCMP) - { - pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption3Enabled; - } - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_GROUP - param->value = %d!\n", __FUNCTION__, param->value)); - break; - case IW_AUTH_KEY_MGMT: - if (param->value == IW_AUTH_KEY_MGMT_802_1X) - { - if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) - { - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA; -#ifdef WPA_SUPPLICANT_SUPPORT - pAdapter->StaCfg.IEEE8021X = FALSE; -#endif // WPA_SUPPLICANT_SUPPORT // - } - else if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) - { - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; -#ifdef WPA_SUPPLICANT_SUPPORT - pAdapter->StaCfg.IEEE8021X = FALSE; -#endif // WPA_SUPPLICANT_SUPPORT // - } -#ifdef WPA_SUPPLICANT_SUPPORT - else - // WEP 1x - pAdapter->StaCfg.IEEE8021X = TRUE; -#endif // WPA_SUPPLICANT_SUPPORT // - } - else if (param->value == 0) - { - //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - STA_PORT_SECURED(pAdapter); - } - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_KEY_MGMT - param->value = %d!\n", __FUNCTION__, param->value)); - break; - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - break; - case IW_AUTH_PRIVACY_INVOKED: - /*if (param->value == 0) - { - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; - pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; - pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; - pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; - }*/ - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_PRIVACY_INVOKED - param->value = %d!\n", __FUNCTION__, param->value)); - break; - case IW_AUTH_DROP_UNENCRYPTED: - if (param->value != 0) - pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - else - { - //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - STA_PORT_SECURED(pAdapter); - } - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __FUNCTION__, param->value)); - break; - case IW_AUTH_80211_AUTH_ALG: - if (param->value & IW_AUTH_ALG_SHARED_KEY) - { - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared; - } - else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) - { - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; - } - else - return -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_80211_AUTH_ALG - param->value = %d!\n", __FUNCTION__, param->value)); - break; - case IW_AUTH_WPA_ENABLED: - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_ENABLED - Driver supports WPA!(param->value = %d)\n", __FUNCTION__, param->value)); - break; - default: - return -EOPNOTSUPP; -} - - return 0; -} - -int rt_ioctl_giwauth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - struct iw_param *param = &wrqu->param; - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_DROP_UNENCRYPTED: - param->value = (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled) ? 0 : 1; - break; - - case IW_AUTH_80211_AUTH_ALG: - param->value = (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) ? IW_AUTH_ALG_SHARED_KEY : IW_AUTH_ALG_OPEN_SYSTEM; - break; - - case IW_AUTH_WPA_ENABLED: - param->value = (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) ? 1 : 0; - break; - - default: - return -EOPNOTSUPP; - } - DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_giwauth::param->value = %d!\n", param->value)); - return 0; -} - -void fnSetCipherKey( - IN PRTMP_ADAPTER pAdapter, - IN INT keyIdx, - IN UCHAR CipherAlg, - IN BOOLEAN bGTK, - IN struct iw_encode_ext *ext) -{ - NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY)); - pAdapter->SharedKey[BSS0][keyIdx].KeyLen = LEN_TKIP_EK; - NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, LEN_TKIP_EK); - NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].TxMic, ext->key + LEN_TKIP_EK, LEN_TKIP_TXMICK); - NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].RxMic, ext->key + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CipherAlg; - - // Update group key information to ASIC Shared Key Table - AsicAddSharedKeyEntry(pAdapter, - BSS0, - keyIdx, - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, - pAdapter->SharedKey[BSS0][keyIdx].Key, - pAdapter->SharedKey[BSS0][keyIdx].TxMic, - pAdapter->SharedKey[BSS0][keyIdx].RxMic); - - if (bGTK) - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAdapter, - BSS0, - keyIdx, - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, - NULL); - else - // Update ASIC WCID attribute table and IVEIV table - RTMPAddWcidAttributeEntry(pAdapter, - BSS0, - keyIdx, - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, - &pAdapter->MacTab.Content[BSSID_WCID]); -} - -int rt_ioctl_siwencodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) - { - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int keyIdx, alg = ext->alg; - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - if (encoding->flags & IW_ENCODE_DISABLED) - { - keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1; - // set BSSID wcid entry of the Pair-wise Key table as no-security mode - AsicRemovePairwiseKeyEntry(pAdapter, BSS0, BSSID_WCID); - pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0; - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_NONE; - AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)keyIdx); - NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY)); - DBGPRINT(RT_DEBUG_TRACE, ("%s::Remove all keys!(encoding->flags = %x)\n", __FUNCTION__, encoding->flags)); - } - else - { - // Get Key Index and convet to our own defined key index - keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1; - if((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS)) - return -EINVAL; - - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) - { - pAdapter->StaCfg.DefaultKeyId = keyIdx; - DBGPRINT(RT_DEBUG_TRACE, ("%s::DefaultKeyId = %d\n", __FUNCTION__, pAdapter->StaCfg.DefaultKeyId)); - } - - switch (alg) { - case IW_ENCODE_ALG_NONE: - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_NONE\n", __FUNCTION__)); - break; - case IW_ENCODE_ALG_WEP: - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_WEP - ext->key_len = %d, keyIdx = %d\n", __FUNCTION__, ext->key_len, keyIdx)); - if (ext->key_len == MAX_WEP_KEY_SIZE) - { - pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE; - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128; - } - else if (ext->key_len == MIN_WEP_KEY_SIZE) - { - pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE; - pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64; - } - else - return -EINVAL; - - NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, 16); - NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, ext->key_len); - - if (pAdapter->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled || - pAdapter->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled) - { - // Set Group key material to Asic - AsicAddSharedKeyEntry(pAdapter, BSS0, keyIdx, pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, pAdapter->SharedKey[BSS0][keyIdx].Key, NULL, NULL); - // Update WCID attribute table and IVEIV table for this group key table - RTMPAddWcidAttributeEntry(pAdapter, BSS0, keyIdx, pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, NULL); - STA_PORT_SECURED(pAdapter); - // Indicate Connected for GUI - pAdapter->IndicateMediaState = NdisMediaStateConnected; - } - break; - case IW_ENCODE_ALG_TKIP: - DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_TKIP - keyIdx = %d, ext->key_len = %d\n", __FUNCTION__, keyIdx, ext->key_len)); - if (ext->key_len == 32) - { - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) - { - fnSetCipherKey(pAdapter, keyIdx, CIPHER_TKIP, FALSE, ext); - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2) - { - //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - STA_PORT_SECURED(pAdapter); - pAdapter->IndicateMediaState = NdisMediaStateConnected; - } - } - else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) - { - fnSetCipherKey(pAdapter, keyIdx, CIPHER_TKIP, TRUE, ext); - - // set 802.1x port control - //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - STA_PORT_SECURED(pAdapter); - pAdapter->IndicateMediaState = NdisMediaStateConnected; - } - } - else - return -EINVAL; - break; - case IW_ENCODE_ALG_CCMP: - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) - { - fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, FALSE, ext); - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2) - //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - STA_PORT_SECURED(pAdapter); - pAdapter->IndicateMediaState = NdisMediaStateConnected; - } - else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) - { - fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, TRUE, ext); - - // set 802.1x port control - //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - STA_PORT_SECURED(pAdapter); - pAdapter->IndicateMediaState = NdisMediaStateConnected; - } - break; - default: - return -EINVAL; - } - } - - return 0; -} - -int -rt_ioctl_giwencodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(dev); - PCHAR pKey = NULL; - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int idx, max_key_len; - - DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_giwencodeext\n")); - - max_key_len = encoding->length - sizeof(*ext); - if (max_key_len < 0) - return -EINVAL; - - idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) - { - if (idx < 1 || idx > 4) - return -EINVAL; - idx--; - - if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || - (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)) - { - if (idx != pAd->StaCfg.DefaultKeyId) - { - ext->key_len = 0; - return 0; - } - } - } - else - idx = pAd->StaCfg.DefaultKeyId; - - encoding->flags = idx + 1; - memset(ext, 0, sizeof(*ext)); - - ext->key_len = 0; - switch(pAd->StaCfg.WepStatus) { - case Ndis802_11WEPDisabled: - ext->alg = IW_ENCODE_ALG_NONE; - encoding->flags |= IW_ENCODE_DISABLED; - break; - case Ndis802_11WEPEnabled: - ext->alg = IW_ENCODE_ALG_WEP; - if (pAd->SharedKey[BSS0][idx].KeyLen > max_key_len) - return -E2BIG; - else - { - ext->key_len = pAd->SharedKey[BSS0][idx].KeyLen; - pKey = (PCHAR)&(pAd->SharedKey[BSS0][idx].Key[0]); - } - break; - case Ndis802_11Encryption2Enabled: - case Ndis802_11Encryption3Enabled: - if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) - ext->alg = IW_ENCODE_ALG_TKIP; - else - ext->alg = IW_ENCODE_ALG_CCMP; - - if (max_key_len < 32) - return -E2BIG; - else - { - ext->key_len = 32; - pKey = (PCHAR)&pAd->StaCfg.PMK[0]; - } - break; - default: - return -EINVAL; - } - - if (ext->key_len && pKey) - { - encoding->flags |= IW_ENCODE_ENABLED; - memcpy(ext->key, pKey, ext->key_len); - } - - return 0; -} - -#ifdef SIOCSIWGENIE -int rt_ioctl_siwgenie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(dev); - - DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_siwgenie\n")); -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT - pAd->StaCfg.bRSN_IE_FromWpaSupplicant = FALSE; -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - if (wrqu->data.length > MAX_LEN_OF_RSNIE || - (wrqu->data.length && extra == NULL)) - return -EINVAL; - - if (wrqu->data.length) - { - pAd->StaCfg.RSNIE_Len = wrqu->data.length; - NdisMoveMemory(&pAd->StaCfg.RSN_IE[0], extra, pAd->StaCfg.RSNIE_Len); -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT - pAd->StaCfg.bRSN_IE_FromWpaSupplicant = TRUE; -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - } - else - { - pAd->StaCfg.RSNIE_Len = 0; - NdisZeroMemory(&pAd->StaCfg.RSN_IE[0], MAX_LEN_OF_RSNIE); - } - - return 0; -} -#endif // SIOCSIWGENIE // - -int rt_ioctl_giwgenie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(dev); - - if ((pAd->StaCfg.RSNIE_Len == 0) || - (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA)) - { - wrqu->data.length = 0; - return 0; - } - -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT -#ifdef SIOCSIWGENIE - if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) - { - if (wrqu->data.length < pAd->StaCfg.RSNIE_Len) - return -E2BIG; - - wrqu->data.length = pAd->StaCfg.RSNIE_Len; - memcpy(extra, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len); - } - else -#endif // SIOCSIWGENIE // -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - { - UCHAR RSNIe = IE_WPA; - - if (wrqu->data.length < (pAd->StaCfg.RSNIE_Len + 2)) // ID, Len - return -E2BIG; - wrqu->data.length = pAd->StaCfg.RSNIE_Len + 2; - - if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)) - RSNIe = IE_RSN; - - extra[0] = (char)RSNIe; - extra[1] = pAd->StaCfg.RSNIE_Len; - memcpy(extra+2, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len); - } - - return 0; -} - -int rt_ioctl_siwpmksa(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(dev); - struct iw_pmksa *pPmksa = (struct iw_pmksa *)wrqu->data.pointer; - INT CachedIdx = 0, idx = 0; - - if (pPmksa == NULL) - return -EINVAL; - - DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_siwpmksa\n")); - switch(pPmksa->cmd) - { - case IW_PMKSA_FLUSH: - NdisZeroMemory(pAd->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO); - DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_FLUSH\n")); - break; - case IW_PMKSA_REMOVE: - for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++) - { - // compare the BSSID - if (NdisEqualMemory(pPmksa->bssid.sa_data, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN)) - { - NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN); - NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].PMKID, 16); - for (idx = CachedIdx; idx < (pAd->StaCfg.SavedPMKNum - 1); idx++) - { - NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].BSSID[0], &pAd->StaCfg.SavedPMK[idx+1].BSSID[0], MAC_ADDR_LEN); - NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].PMKID[0], &pAd->StaCfg.SavedPMK[idx+1].PMKID[0], 16); - } - pAd->StaCfg.SavedPMKNum--; - break; - } - } - - DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_REMOVE\n")); - break; - case IW_PMKSA_ADD: - for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++) - { - // compare the BSSID - if (NdisEqualMemory(pPmksa->bssid.sa_data, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN)) - break; - } - - // Found, replace it - if (CachedIdx < PMKID_NO) - { - DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx)); - NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pPmksa->bssid.sa_data, MAC_ADDR_LEN); - NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pPmksa->pmkid, 16); - pAd->StaCfg.SavedPMKNum++; - } - // Not found, replace the last one - else - { - // Randomly replace one - CachedIdx = (pPmksa->bssid.sa_data[5] % PMKID_NO); - DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx)); - NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pPmksa->bssid.sa_data, MAC_ADDR_LEN); - NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pPmksa->pmkid, 16); - } - - DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_ADD\n")); - break; - default: - DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - Unknow Command!!\n")); - break; - } - - return 0; -} -#endif // #if WIRELESS_EXT > 17 - -#ifdef DBG -static int -rt_private_ioctl_bbp(struct net_device *dev, struct iw_request_info *info, - struct iw_point *wrq, char *extra) - { - PSTRING this_char; - PSTRING value = NULL; - UCHAR regBBP = 0; -// CHAR arg[255]={0}; - UINT32 bbpId; - UINT32 bbpValue; - BOOLEAN bIsPrintAllBBP = FALSE; - INT Status = 0; - PRTMP_ADAPTER pAdapter = RTMP_OS_NETDEV_GET_PRIV(dev); - - - memset(extra, 0x00, IW_PRIV_SIZE_MASK); - - if (wrq->length > 1) //No parameters. - { - sprintf(extra, "\n"); - - //Parsing Read or Write - this_char = wrq->pointer; - DBGPRINT(RT_DEBUG_TRACE, ("this_char=%s\n", this_char)); - if (!*this_char) - goto next; - - if ((value = rtstrchr(this_char, '=')) != NULL) - *value++ = 0; - - if (!value || !*value) - { //Read - DBGPRINT(RT_DEBUG_TRACE, ("this_char=%s, value=%s\n", this_char, value)); - if (sscanf(this_char, "%d", &(bbpId)) == 1) - { - if (bbpId <= MAX_BBP_ID) - { -#ifdef RALINK_ATE - if (ATE_ON(pAdapter)) - { - ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); - } - else -#endif // RALINK_ATE // - { - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); - } - sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X\n", bbpId, bbpId, regBBP); - wrq->length = strlen(extra) + 1; // 1: size of '\0' - DBGPRINT(RT_DEBUG_TRACE, ("msg=%s\n", extra)); - } - else - {//Invalid parametes, so default printk all bbp - bIsPrintAllBBP = TRUE; - goto next; - } - } - else - { //Invalid parametes, so default printk all bbp - bIsPrintAllBBP = TRUE; - goto next; - } - } - else - { //Write - if ((sscanf(this_char, "%d", &(bbpId)) == 1) && (sscanf(value, "%x", &(bbpValue)) == 1)) - { - if (bbpId <= MAX_BBP_ID) - { -#ifdef RALINK_ATE - if (ATE_ON(pAdapter)) - { - ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, bbpId, bbpValue); - /* read it back for showing */ - ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); - } - else -#endif // RALINK_ATE // - { - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, bbpId, bbpValue); - /* read it back for showing */ - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); - } - sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X\n", bbpId, bbpId, regBBP); - wrq->length = strlen(extra) + 1; // 1: size of '\0' - DBGPRINT(RT_DEBUG_TRACE, ("msg=%s\n", extra)); - } - else - {//Invalid parametes, so default printk all bbp - bIsPrintAllBBP = TRUE; - goto next; - } - } - else - { //Invalid parametes, so default printk all bbp - bIsPrintAllBBP = TRUE; - goto next; - } - } - } - else - bIsPrintAllBBP = TRUE; - -next: - if (bIsPrintAllBBP) - { - memset(extra, 0x00, IW_PRIV_SIZE_MASK); - sprintf(extra, "\n"); - for (bbpId = 0; bbpId <= MAX_BBP_ID; bbpId++) - { - if (strlen(extra) >= (IW_PRIV_SIZE_MASK - 20)) - break; -#ifdef RALINK_ATE - if (ATE_ON(pAdapter)) - { - ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); - } - else -#endif // RALINK_ATE // - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); - sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X ", bbpId, bbpId, regBBP); - if (bbpId%5 == 4) - sprintf(extra+strlen(extra), "%03d = %02X\n", bbpId, regBBP); // edit by johnli, change display format - } - - wrq->length = strlen(extra) + 1; // 1: size of '\0' - DBGPRINT(RT_DEBUG_TRACE, ("wrq->length = %d\n", wrq->length)); - } - - DBGPRINT(RT_DEBUG_TRACE, ("<==rt_private_ioctl_bbp\n\n")); - - return Status; -} -#endif // DBG // - -int rt_ioctl_siwrate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(dev); - UINT32 rate = wrqu->bitrate.value, fixed = wrqu->bitrate.fixed; - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::Network is down!\n")); - return -ENETDOWN; - } - - DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(rate = %d, fixed = %d)\n", rate, fixed)); - /* rate = -1 => auto rate - rate = X, fixed = 1 => (fixed rate X) - */ - if (rate == -1) - { - //Auto Rate - pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; - pAd->StaCfg.bAutoTxRateSwitch = TRUE; - if ((pAd->CommonCfg.PhyMode <= PHY_11G) || - (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)) - RTMPSetDesiredRates(pAd, -1); - -#ifdef DOT11_N_SUPPORT - SetCommonHT(pAd); -#endif // DOT11_N_SUPPORT // - } - else - { - if (fixed) - { - pAd->StaCfg.bAutoTxRateSwitch = FALSE; - if ((pAd->CommonCfg.PhyMode <= PHY_11G) || - (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)) - RTMPSetDesiredRates(pAd, rate); - else - { - pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; -#ifdef DOT11_N_SUPPORT - SetCommonHT(pAd); -#endif // DOT11_N_SUPPORT // - } - DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(HtMcs=%d)\n",pAd->StaCfg.DesiredTransmitSetting.field.MCS)); - } - else - { - // TODO: rate = X, fixed = 0 => (rates <= X) - return -EOPNOTSUPP; - } - } - - return 0; -} - -int rt_ioctl_giwrate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(dev); - int rate_index = 0, rate_count = 0; - HTTRANSMIT_SETTING ht_setting; -/* Remove to global variable - __s32 ralinkrate[] = - {2, 4, 11, 22, // CCK - 12, 18, 24, 36, 48, 72, 96, 108, // OFDM - 13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, // 20MHz, 800ns GI, MCS: 0 ~ 15 - 39, 78, 117, 156, 234, 312, 351, 390, // 20MHz, 800ns GI, MCS: 16 ~ 23 - 27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, // 40MHz, 800ns GI, MCS: 0 ~ 15 - 81, 162, 243, 324, 486, 648, 729, 810, // 40MHz, 800ns GI, MCS: 16 ~ 23 - 14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, // 20MHz, 400ns GI, MCS: 0 ~ 15 - 43, 87, 130, 173, 260, 317, 390, 433, // 20MHz, 400ns GI, MCS: 16 ~ 23 - 30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, // 40MHz, 400ns GI, MCS: 0 ~ 15 - 90, 180, 270, 360, 540, 720, 810, 900}; // 40MHz, 400ns GI, MCS: 16 ~ 23 -*/ - - rate_count = sizeof(ralinkrate)/sizeof(__s32); - //check if the interface is down - if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - if ((pAd->StaCfg.bAutoTxRateSwitch == FALSE) && - (INFRA_ON(pAd)) && - ((pAd->CommonCfg.PhyMode <= PHY_11G) || (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM))) - ht_setting.word = pAd->StaCfg.HTPhyMode.word; - else - ht_setting.word = pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word; - -#ifdef DOT11_N_SUPPORT - if (ht_setting.field.MODE >= MODE_HTMIX) - { -// rate_index = 12 + ((UCHAR)ht_setting.field.BW *16) + ((UCHAR)ht_setting.field.ShortGI *32) + ((UCHAR)ht_setting.field.MCS); - rate_index = 12 + ((UCHAR)ht_setting.field.BW *24) + ((UCHAR)ht_setting.field.ShortGI *48) + ((UCHAR)ht_setting.field.MCS); - } - else -#endif // DOT11_N_SUPPORT // - if (ht_setting.field.MODE == MODE_OFDM) - rate_index = (UCHAR)(ht_setting.field.MCS) + 4; - else if (ht_setting.field.MODE == MODE_CCK) - rate_index = (UCHAR)(ht_setting.field.MCS); - - if (rate_index < 0) - rate_index = 0; - - if (rate_index > rate_count) - rate_index = rate_count; - - wrqu->bitrate.value = ralinkrate[rate_index] * 500000; - wrqu->bitrate.disabled = 0; - - return 0; -} - -static const iw_handler rt_handler[] = -{ - (iw_handler) NULL, /* SIOCSIWCOMMIT */ - (iw_handler) rt_ioctl_giwname, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) rt_ioctl_siwfreq, /* SIOCSIWFREQ */ - (iw_handler) rt_ioctl_giwfreq, /* SIOCGIWFREQ */ - (iw_handler) rt_ioctl_siwmode, /* SIOCSIWMODE */ - (iw_handler) rt_ioctl_giwmode, /* SIOCGIWMODE */ - (iw_handler) NULL, /* SIOCSIWSENS */ - (iw_handler) NULL, /* SIOCGIWSENS */ - (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */ - (iw_handler) rt_ioctl_giwrange, /* SIOCGIWRANGE */ - (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ - (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ - (iw_handler) rt28xx_get_wireless_stats /* kernel code */, /* SIOCGIWSTATS */ - (iw_handler) NULL, /* SIOCSIWSPY */ - (iw_handler) NULL, /* SIOCGIWSPY */ - (iw_handler) NULL, /* SIOCSIWTHRSPY */ - (iw_handler) NULL, /* SIOCGIWTHRSPY */ - (iw_handler) rt_ioctl_siwap, /* SIOCSIWAP */ - (iw_handler) rt_ioctl_giwap, /* SIOCGIWAP */ -#ifdef SIOCSIWMLME - (iw_handler) rt_ioctl_siwmlme, /* SIOCSIWMLME */ -#else - (iw_handler) NULL, /* SIOCSIWMLME */ -#endif // SIOCSIWMLME // - (iw_handler) rt_ioctl_iwaplist, /* SIOCGIWAPLIST */ -#ifdef SIOCGIWSCAN - (iw_handler) rt_ioctl_siwscan, /* SIOCSIWSCAN */ - (iw_handler) rt_ioctl_giwscan, /* SIOCGIWSCAN */ -#else - (iw_handler) NULL, /* SIOCSIWSCAN */ - (iw_handler) NULL, /* SIOCGIWSCAN */ -#endif /* SIOCGIWSCAN */ - (iw_handler) rt_ioctl_siwessid, /* SIOCSIWESSID */ - (iw_handler) rt_ioctl_giwessid, /* SIOCGIWESSID */ - (iw_handler) rt_ioctl_siwnickn, /* SIOCSIWNICKN */ - (iw_handler) rt_ioctl_giwnickn, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) rt_ioctl_siwrate, /* SIOCSIWRATE */ - (iw_handler) rt_ioctl_giwrate, /* SIOCGIWRATE */ - (iw_handler) rt_ioctl_siwrts, /* SIOCSIWRTS */ - (iw_handler) rt_ioctl_giwrts, /* SIOCGIWRTS */ - (iw_handler) rt_ioctl_siwfrag, /* SIOCSIWFRAG */ - (iw_handler) rt_ioctl_giwfrag, /* SIOCGIWFRAG */ - (iw_handler) NULL, /* SIOCSIWTXPOW */ - (iw_handler) NULL, /* SIOCGIWTXPOW */ - (iw_handler) NULL, /* SIOCSIWRETRY */ - (iw_handler) NULL, /* SIOCGIWRETRY */ - (iw_handler) rt_ioctl_siwencode, /* SIOCSIWENCODE */ - (iw_handler) rt_ioctl_giwencode, /* SIOCGIWENCODE */ - (iw_handler) NULL, /* SIOCSIWPOWER */ - (iw_handler) NULL, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ -#if WIRELESS_EXT > 17 - (iw_handler) rt_ioctl_siwgenie, /* SIOCSIWGENIE */ - (iw_handler) rt_ioctl_giwgenie, /* SIOCGIWGENIE */ - (iw_handler) rt_ioctl_siwauth, /* SIOCSIWAUTH */ - (iw_handler) rt_ioctl_giwauth, /* SIOCGIWAUTH */ - (iw_handler) rt_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */ - (iw_handler) rt_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */ - (iw_handler) rt_ioctl_siwpmksa, /* SIOCSIWPMKSA */ -#endif -}; - -static const iw_handler rt_priv_handlers[] = { - (iw_handler) NULL, /* + 0x00 */ - (iw_handler) NULL, /* + 0x01 */ - (iw_handler) rt_ioctl_setparam, /* + 0x02 */ -#ifdef DBG - (iw_handler) rt_private_ioctl_bbp, /* + 0x03 */ -#else - (iw_handler) NULL, /* + 0x03 */ -#endif - (iw_handler) NULL, /* + 0x04 */ - (iw_handler) NULL, /* + 0x05 */ - (iw_handler) NULL, /* + 0x06 */ - (iw_handler) NULL, /* + 0x07 */ - (iw_handler) NULL, /* + 0x08 */ - (iw_handler) rt_private_get_statistics, /* + 0x09 */ - (iw_handler) NULL, /* + 0x0A */ - (iw_handler) NULL, /* + 0x0B */ - (iw_handler) NULL, /* + 0x0C */ - (iw_handler) NULL, /* + 0x0D */ - (iw_handler) NULL, /* + 0x0E */ - (iw_handler) NULL, /* + 0x0F */ - (iw_handler) NULL, /* + 0x10 */ - (iw_handler) rt_private_show, /* + 0x11 */ - (iw_handler) NULL, /* + 0x12 */ - (iw_handler) NULL, /* + 0x13 */ - (iw_handler) NULL, /* + 0x14 */ - (iw_handler) NULL, /* + 0x15 */ - (iw_handler) NULL, /* + 0x16 */ - (iw_handler) NULL, /* + 0x17 */ - (iw_handler) NULL, /* + 0x18 */ -}; - -const struct iw_handler_def rt28xx_iw_handler_def = -{ -#define N(a) (sizeof (a) / sizeof (a[0])) - .standard = (iw_handler *) rt_handler, - .num_standard = sizeof(rt_handler) / sizeof(iw_handler), - .private = (iw_handler *) rt_priv_handlers, - .num_private = N(rt_priv_handlers), - .private_args = (struct iw_priv_args *) privtab, - .num_private_args = N(privtab), -#if IW_HANDLER_VERSION >= 7 - .get_wireless_stats = rt28xx_get_wireless_stats, -#endif -}; - -INT RTMPSetInformation( - IN PRTMP_ADAPTER pAd, - IN OUT struct ifreq *rq, - IN INT cmd) -{ - struct iwreq *wrq = (struct iwreq *) rq; - NDIS_802_11_SSID Ssid; - NDIS_802_11_MAC_ADDRESS Bssid; - RT_802_11_PHY_MODE PhyMode; - RT_802_11_STA_CONFIG StaConfig; - NDIS_802_11_RATES aryRates; - RT_802_11_PREAMBLE Preamble; - NDIS_802_11_WEP_STATUS WepStatus; - NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeMax; - NDIS_802_11_NETWORK_INFRASTRUCTURE BssType; - NDIS_802_11_RTS_THRESHOLD RtsThresh; - NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh; - NDIS_802_11_POWER_MODE PowerMode; - PNDIS_802_11_KEY pKey = NULL; - PNDIS_802_11_WEP pWepKey =NULL; - PNDIS_802_11_REMOVE_KEY pRemoveKey = NULL; - NDIS_802_11_CONFIGURATION Config, *pConfig = NULL; - NDIS_802_11_NETWORK_TYPE NetType; - ULONG Now; - UINT KeyIdx = 0; - INT Status = NDIS_STATUS_SUCCESS, MaxPhyMode = PHY_11G; - ULONG PowerTemp; - BOOLEAN RadioState; - BOOLEAN StateMachineTouched = FALSE; - PNDIS_802_11_PASSPHRASE ppassphrase = NULL; -#ifdef DOT11_N_SUPPORT - OID_SET_HT_PHYMODE HT_PhyMode; //11n ,kathy -#endif // DOT11_N_SUPPORT // -#ifdef WPA_SUPPLICANT_SUPPORT - PNDIS_802_11_PMKID pPmkId = NULL; - BOOLEAN IEEE8021xState = FALSE; - BOOLEAN IEEE8021x_required_keys = FALSE; - UCHAR wpa_supplicant_enable = 0; -#endif // WPA_SUPPLICANT_SUPPORT // - -#ifdef SNMP_SUPPORT - TX_RTY_CFG_STRUC tx_rty_cfg; - ULONG ShortRetryLimit, LongRetryLimit; - UCHAR ctmp; -#endif // SNMP_SUPPORT // - - - - -#ifdef DOT11_N_SUPPORT - MaxPhyMode = PHY_11N_5G; -#endif // DOT11_N_SUPPORT // - - DBGPRINT(RT_DEBUG_TRACE, ("-->RTMPSetInformation(), 0x%08x\n", cmd&0x7FFF)); - switch(cmd & 0x7FFF) { - case RT_OID_802_11_COUNTRY_REGION: - if (wrq->u.data.length < sizeof(UCHAR)) - Status = -EINVAL; - // Only avaliable when EEPROM not programming - else if (!(pAd->CommonCfg.CountryRegion & 0x80) && !(pAd->CommonCfg.CountryRegionForABand & 0x80)) - { - ULONG Country; - UCHAR TmpPhy; - - Status = copy_from_user(&Country, wrq->u.data.pointer, wrq->u.data.length); - pAd->CommonCfg.CountryRegion = (UCHAR)(Country & 0x000000FF); - pAd->CommonCfg.CountryRegionForABand = (UCHAR)((Country >> 8) & 0x000000FF); - TmpPhy = pAd->CommonCfg.PhyMode; - pAd->CommonCfg.PhyMode = 0xff; - // Build all corresponding channel information - RTMPSetPhyMode(pAd, TmpPhy); -#ifdef DOT11_N_SUPPORT - SetCommonHT(pAd); -#endif // DOT11_N_SUPPORT // - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_COUNTRY_REGION (A:%d B/G:%d)\n", pAd->CommonCfg.CountryRegionForABand, - pAd->CommonCfg.CountryRegion)); - } - break; - case OID_802_11_BSSID_LIST_SCAN: - Now = jiffies; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_BSSID_LIST_SCAN, TxCnt = %d \n", pAd->RalinkCounters.LastOneSecTotalTxCount)); - - if (MONITOR_ON(pAd)) - { - DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n")); - break; - } - - //Benson add 20080527, when radio off, sta don't need to scan - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) - break; - - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - { - DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is scanning now !!!\n")); - pAd->StaCfg.bScanReqIsFromWebUI = TRUE; - Status = NDIS_STATUS_SUCCESS; - break; - } - - if (pAd->RalinkCounters.LastOneSecTotalTxCount > 100) - { - DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); - Status = NDIS_STATUS_SUCCESS; - pAd->StaCfg.ScanCnt = 99; // Prevent auto scan triggered by this OID - break; - } - - if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) && - ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) && - (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) - { - DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); - Status = NDIS_STATUS_SUCCESS; - pAd->StaCfg.ScanCnt = 99; // Prevent auto scan triggered by this OID - break; - } - - - if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) - { - RTMP_MLME_RESET_STATE_MACHINE(pAd); - DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); - } - - // tell CNTL state machine to call NdisMSetInformationComplete() after completing - // this request, because this request is initiated by NDIS. - pAd->MlmeAux.CurrReqIsFromNdis = FALSE; - // Reset allowed scan retries - pAd->StaCfg.ScanCnt = 0; - pAd->StaCfg.LastScanTime = Now; - - pAd->StaCfg.bScanReqIsFromWebUI = TRUE; - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); - MlmeEnqueue(pAd, - MLME_CNTL_STATE_MACHINE, - OID_802_11_BSSID_LIST_SCAN, - 0, - NULL); - - Status = NDIS_STATUS_SUCCESS; - StateMachineTouched = TRUE; - break; - case OID_802_11_SSID: - if (wrq->u.data.length != sizeof(NDIS_802_11_SSID)) - Status = -EINVAL; - else - { - PSTRING pSsidString = NULL; - Status = copy_from_user(&Ssid, wrq->u.data.pointer, wrq->u.data.length); - - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SSID (Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid)); - if (Ssid.SsidLength > MAX_LEN_OF_SSID) - Status = -EINVAL; - else - { - if (Ssid.SsidLength == 0) - { - Set_SSID_Proc(pAd, ""); - } - else - { - pSsidString = (PSTRING)kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG); - if (pSsidString) - { - NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1); - NdisMoveMemory(pSsidString, Ssid.Ssid, Ssid.SsidLength); - Set_SSID_Proc(pAd, pSsidString); - kfree(pSsidString); - } - else - Status = -ENOMEM; - } - } - } - break; - case OID_802_11_SET_PASSPHRASE: - ppassphrase= kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); - - if(ppassphrase== NULL) - { - Status = -ENOMEM; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_PASSPHRASE, Failed!!\n")); - break; - } - else - { - Status = copy_from_user(ppassphrase, wrq->u.data.pointer, wrq->u.data.length); - - if (Status) - { - Status = -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_PASSPHRASE, Failed (length mismatch)!!\n")); - } - else - { - if(ppassphrase->KeyLength < 8 || ppassphrase->KeyLength > 64) - { - Status = -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_PASSPHRASE, Failed (len less than 8 or greater than 64)!!\n")); - } - else - { - // set key passphrase and length - NdisZeroMemory(pAd->StaCfg.WpaPassPhrase, 64); - NdisMoveMemory(pAd->StaCfg.WpaPassPhrase, &ppassphrase->KeyMaterial, ppassphrase->KeyLength); - pAd->StaCfg.WpaPassPhraseLen = ppassphrase->KeyLength; - hex_dump("pAd->StaCfg.WpaPassPhrase", pAd->StaCfg.WpaPassPhrase, 64); - printk("WpaPassPhrase=%s\n",pAd->StaCfg.WpaPassPhrase); - } - } - } - kfree(ppassphrase); - break; - - case OID_802_11_BSSID: - if (wrq->u.data.length != sizeof(NDIS_802_11_MAC_ADDRESS)) - Status = -EINVAL; - else - { - Status = copy_from_user(&Bssid, wrq->u.data.pointer, wrq->u.data.length); - - // tell CNTL state machine to call NdisMSetInformationComplete() after completing - // this request, because this request is initiated by NDIS. - pAd->MlmeAux.CurrReqIsFromNdis = FALSE; - - // Prevent to connect AP again in STAMlmePeriodicExec - pAd->MlmeAux.AutoReconnectSsidLen= 32; - - // Reset allowed scan retries - pAd->StaCfg.ScanCnt = 0; - - if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) - { - RTMP_MLME_RESET_STATE_MACHINE(pAd); - DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); - } - MlmeEnqueue(pAd, - MLME_CNTL_STATE_MACHINE, - OID_802_11_BSSID, - sizeof(NDIS_802_11_MAC_ADDRESS), - (VOID *)&Bssid); - Status = NDIS_STATUS_SUCCESS; - StateMachineTouched = TRUE; - - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", - Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); - } - break; - case RT_OID_802_11_RADIO: - if (wrq->u.data.length != sizeof(BOOLEAN)) - Status = -EINVAL; - else - { - Status = copy_from_user(&RadioState, wrq->u.data.pointer, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_RADIO (=%d)\n", RadioState)); - if (pAd->StaCfg.bSwRadio != RadioState) - { - pAd->StaCfg.bSwRadio = RadioState; - if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) - { - pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); - if (pAd->StaCfg.bRadio == TRUE) - { - MlmeRadioOn(pAd); - // Update extra information - pAd->ExtraInfo = EXTRA_INFO_CLEAR; - } - else - { - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - { - if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) - { - RTMP_MLME_RESET_STATE_MACHINE(pAd); - DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); - } - } - - MlmeRadioOff(pAd); - // Update extra information - pAd->ExtraInfo = SW_RADIO_OFF; - } - } - } - } - break; - case RT_OID_802_11_PHY_MODE: - if (wrq->u.data.length != sizeof(RT_802_11_PHY_MODE)) - Status = -EINVAL; - else - { - Status = copy_from_user(&PhyMode, wrq->u.data.pointer, wrq->u.data.length); - if (PhyMode <= MaxPhyMode) - { - RTMPSetPhyMode(pAd, PhyMode); -#ifdef DOT11_N_SUPPORT - SetCommonHT(pAd); -#endif // DOT11_N_SUPPORT // - } - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_PHY_MODE (=%d)\n", PhyMode)); - } - break; - case RT_OID_802_11_STA_CONFIG: - if (wrq->u.data.length != sizeof(RT_802_11_STA_CONFIG)) - Status = -EINVAL; - else - { - UINT32 Value; - - Status = copy_from_user(&StaConfig, wrq->u.data.pointer, wrq->u.data.length); - pAd->CommonCfg.bEnableTxBurst = StaConfig.EnableTxBurst; - pAd->CommonCfg.UseBGProtection = StaConfig.UseBGProtection; - pAd->CommonCfg.bUseShortSlotTime = 1; // 2003-10-30 always SHORT SLOT capable - if ((pAd->CommonCfg.PhyMode != StaConfig.AdhocMode) && - (StaConfig.AdhocMode <= MaxPhyMode)) - { - // allow dynamic change of "USE OFDM rate or not" in ADHOC mode - // if setting changed, need to reset current TX rate as well as BEACON frame format - if (pAd->StaCfg.BssType == BSS_ADHOC) - { - pAd->CommonCfg.PhyMode = StaConfig.AdhocMode; - RTMPSetPhyMode(pAd, PhyMode); - MlmeUpdateTxRates(pAd, FALSE, 0); - MakeIbssBeacon(pAd); // re-build BEACON frame - AsicEnableIbssSync(pAd); // copy to on-chip memory - } - } - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_STA_CONFIG (Burst=%d, Protection=%ld,ShortSlot=%d\n", - pAd->CommonCfg.bEnableTxBurst, - pAd->CommonCfg.UseBGProtection, - pAd->CommonCfg.bUseShortSlotTime)); - - if (pAd->CommonCfg.PSPXlink) - Value = PSPXLINK; - else - Value = STANORMAL; - RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, Value); - Value = 0; - RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); - Value &= (~0x80); - RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); - } - break; - case OID_802_11_DESIRED_RATES: - if (wrq->u.data.length != sizeof(NDIS_802_11_RATES)) - Status = -EINVAL; - else - { - Status = copy_from_user(&aryRates, wrq->u.data.pointer, wrq->u.data.length); - NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); - NdisMoveMemory(pAd->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES)); - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DESIRED_RATES (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n", - pAd->CommonCfg.DesireRate[0],pAd->CommonCfg.DesireRate[1], - pAd->CommonCfg.DesireRate[2],pAd->CommonCfg.DesireRate[3], - pAd->CommonCfg.DesireRate[4],pAd->CommonCfg.DesireRate[5], - pAd->CommonCfg.DesireRate[6],pAd->CommonCfg.DesireRate[7] )); - // Changing DesiredRate may affect the MAX TX rate we used to TX frames out - MlmeUpdateTxRates(pAd, FALSE, 0); - } - break; - case RT_OID_802_11_PREAMBLE: - if (wrq->u.data.length != sizeof(RT_802_11_PREAMBLE)) - Status = -EINVAL; - else - { - Status = copy_from_user(&Preamble, wrq->u.data.pointer, wrq->u.data.length); - if (Preamble == Rt802_11PreambleShort) - { - pAd->CommonCfg.TxPreamble = Preamble; - MlmeSetTxPreamble(pAd, Rt802_11PreambleShort); - } - else if ((Preamble == Rt802_11PreambleLong) || (Preamble == Rt802_11PreambleAuto)) - { - // if user wants AUTO, initialize to LONG here, then change according to AP's - // capability upon association. - pAd->CommonCfg.TxPreamble = Preamble; - MlmeSetTxPreamble(pAd, Rt802_11PreambleLong); - } - else - { - Status = -EINVAL; - break; - } - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_PREAMBLE (=%d)\n", Preamble)); - } - break; - case OID_802_11_WEP_STATUS: - if (wrq->u.data.length != sizeof(NDIS_802_11_WEP_STATUS)) - Status = -EINVAL; - else - { - Status = copy_from_user(&WepStatus, wrq->u.data.pointer, wrq->u.data.length); - // Since TKIP, AES, WEP are all supported. It should not have any invalid setting - if (WepStatus <= Ndis802_11Encryption3KeyAbsent) - { - if (pAd->StaCfg.WepStatus != WepStatus) - { - // Config has changed - pAd->bConfigChanged = TRUE; - } - pAd->StaCfg.WepStatus = WepStatus; - pAd->StaCfg.OrigWepStatus = WepStatus; - pAd->StaCfg.PairCipher = WepStatus; - pAd->StaCfg.GroupCipher = WepStatus; - } - else - { - Status = -EINVAL; - break; - } - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEP_STATUS (=%d)\n",WepStatus)); - } - break; - case OID_802_11_AUTHENTICATION_MODE: - if (wrq->u.data.length != sizeof(NDIS_802_11_AUTHENTICATION_MODE)) - Status = -EINVAL; - else - { - Status = copy_from_user(&AuthMode, wrq->u.data.pointer, wrq->u.data.length); - if (AuthMode > Ndis802_11AuthModeMax) - { - Status = -EINVAL; - break; - } - else - { - if (pAd->StaCfg.AuthMode != AuthMode) - { - // Config has changed - pAd->bConfigChanged = TRUE; - } - pAd->StaCfg.AuthMode = AuthMode; - } - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_AUTHENTICATION_MODE (=%d) \n",pAd->StaCfg.AuthMode)); - } - break; - case OID_802_11_INFRASTRUCTURE_MODE: - if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_INFRASTRUCTURE)) - Status = -EINVAL; - else - { - Status = copy_from_user(&BssType, wrq->u.data.pointer, wrq->u.data.length); - - if (BssType == Ndis802_11IBSS) - Set_NetworkType_Proc(pAd, "Adhoc"); - else if (BssType == Ndis802_11Infrastructure) - Set_NetworkType_Proc(pAd, "Infra"); - else if (BssType == Ndis802_11Monitor) - Set_NetworkType_Proc(pAd, "Monitor"); - else - { - Status = -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_INFRASTRUCTURE_MODE (unknown)\n")); - } - } - break; - case OID_802_11_REMOVE_WEP: - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_WEP\n")); - if (wrq->u.data.length != sizeof(NDIS_802_11_KEY_INDEX)) - { - Status = -EINVAL; - } - else - { - KeyIdx = *(NDIS_802_11_KEY_INDEX *) wrq->u.data.pointer; - - if (KeyIdx & 0x80000000) - { - // Should never set default bit when remove key - Status = -EINVAL; - } - else - { - KeyIdx = KeyIdx & 0x0fffffff; - if (KeyIdx >= 4){ - Status = -EINVAL; - } - else - { - pAd->SharedKey[BSS0][KeyIdx].KeyLen = 0; - pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE; - AsicRemoveSharedKeyEntry(pAd, 0, (UCHAR)KeyIdx); - } - } - } - break; - case RT_OID_802_11_RESET_COUNTERS: - NdisZeroMemory(&pAd->WlanCounters, sizeof(COUNTER_802_11)); - NdisZeroMemory(&pAd->Counters8023, sizeof(COUNTER_802_3)); - NdisZeroMemory(&pAd->RalinkCounters, sizeof(COUNTER_RALINK)); - pAd->Counters8023.RxNoBuffer = 0; - pAd->Counters8023.GoodReceives = 0; - pAd->Counters8023.RxNoBuffer = 0; - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_RESET_COUNTERS \n")); - break; - case OID_802_11_RTS_THRESHOLD: - if (wrq->u.data.length != sizeof(NDIS_802_11_RTS_THRESHOLD)) - Status = -EINVAL; - else - { - Status = copy_from_user(&RtsThresh, wrq->u.data.pointer, wrq->u.data.length); - if (RtsThresh > MAX_RTS_THRESHOLD) - Status = -EINVAL; - else - pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh; - } - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_RTS_THRESHOLD (=%ld)\n",RtsThresh)); - break; - case OID_802_11_FRAGMENTATION_THRESHOLD: - if (wrq->u.data.length != sizeof(NDIS_802_11_FRAGMENTATION_THRESHOLD)) - Status = -EINVAL; - else - { - Status = copy_from_user(&FragThresh, wrq->u.data.pointer, wrq->u.data.length); - pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; - if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD) - { - if (FragThresh == 0) - { - pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; - pAd->CommonCfg.bUseZeroToDisableFragment = TRUE; - } - else - Status = -EINVAL; - } - else - pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh; - } - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_FRAGMENTATION_THRESHOLD (=%ld) \n",FragThresh)); - break; - case OID_802_11_POWER_MODE: - if (wrq->u.data.length != sizeof(NDIS_802_11_POWER_MODE)) - Status = -EINVAL; - else - { - Status = copy_from_user(&PowerMode, wrq->u.data.pointer, wrq->u.data.length); - if (PowerMode == Ndis802_11PowerModeCAM) - Set_PSMode_Proc(pAd, "CAM"); - else if (PowerMode == Ndis802_11PowerModeMAX_PSP) - Set_PSMode_Proc(pAd, "Max_PSP"); - else if (PowerMode == Ndis802_11PowerModeFast_PSP) - Set_PSMode_Proc(pAd, "Fast_PSP"); - else if (PowerMode == Ndis802_11PowerModeLegacy_PSP) - Set_PSMode_Proc(pAd, "Legacy_PSP"); - else - Status = -EINVAL; - } - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_POWER_MODE (=%d)\n",PowerMode)); - break; - case RT_OID_802_11_TX_POWER_LEVEL_1: - if (wrq->u.data.length < sizeof(ULONG)) - Status = -EINVAL; - else - { - Status = copy_from_user(&PowerTemp, wrq->u.data.pointer, wrq->u.data.length); - if (PowerTemp > 100) - PowerTemp = 0xffffffff; // AUTO - pAd->CommonCfg.TxPowerDefault = PowerTemp; //keep current setting. - pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAd->CommonCfg.TxPowerPercentage)); - } - break; - case OID_802_11_NETWORK_TYPE_IN_USE: - if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_TYPE)) - Status = -EINVAL; - else - { - Status = copy_from_user(&NetType, wrq->u.data.pointer, wrq->u.data.length); - - if (NetType == Ndis802_11DS) - RTMPSetPhyMode(pAd, PHY_11B); - else if (NetType == Ndis802_11OFDM24) - RTMPSetPhyMode(pAd, PHY_11BG_MIXED); - else if (NetType == Ndis802_11OFDM5) - RTMPSetPhyMode(pAd, PHY_11A); - else - Status = -EINVAL; -#ifdef DOT11_N_SUPPORT - if (Status == NDIS_STATUS_SUCCESS) - SetCommonHT(pAd); -#endif // DOT11_N_SUPPORT // - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_NETWORK_TYPE_IN_USE (=%d)\n",NetType)); - } - break; - // For WPA PSK PMK key - case RT_OID_802_11_ADD_WPA: - pKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); - if(pKey == NULL) - { - Status = -ENOMEM; - break; - } - - Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length); - if (pKey->Length != wrq->u.data.length) - { - Status = -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!!\n")); - } - else - { - if ((pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && - (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) && - (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) ) - { - Status = -EOPNOTSUPP; - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!! [AuthMode != WPAPSK/WPA2PSK/WPANONE]\n")); - } - else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || - (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) ) // Only for WPA PSK mode - { - NdisMoveMemory(pAd->StaCfg.PMK, &pKey->KeyMaterial, pKey->KeyLength); - // Use RaConfig as PSK agent. - // Start STA supplicant state machine - if (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) - pAd->StaCfg.WpaState = SS_START; - - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength)); - } - else - { - pAd->StaCfg.WpaState = SS_NOTUSE; - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength)); - } - } - kfree(pKey); - break; - case OID_802_11_REMOVE_KEY: - pRemoveKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); - if(pRemoveKey == NULL) - { - Status = -ENOMEM; - break; - } - - Status = copy_from_user(pRemoveKey, wrq->u.data.pointer, wrq->u.data.length); - if (pRemoveKey->Length != wrq->u.data.length) - { - Status = -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!\n")); - } - else - { - if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - { - RTMPWPARemoveKeyProc(pAd, pRemoveKey); - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Remove WPA Key!!\n")); - } - else - { - KeyIdx = pRemoveKey->KeyIndex; - - if (KeyIdx & 0x80000000) - { - // Should never set default bit when remove key - Status = -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(Should never set default bit when remove key)\n")); - } - else - { - KeyIdx = KeyIdx & 0x0fffffff; - if (KeyIdx > 3) - { - Status = -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(KeyId[%d] out of range)\n", KeyIdx)); - } - else - { - pAd->SharedKey[BSS0][KeyIdx].KeyLen = 0; - pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE; - AsicRemoveSharedKeyEntry(pAd, 0, (UCHAR)KeyIdx); - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY (id=0x%x, Len=%d-byte)\n", pRemoveKey->KeyIndex, pRemoveKey->Length)); - } - } - } - } - kfree(pRemoveKey); - break; - // New for WPA - case OID_802_11_ADD_KEY: - pKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); - if(pKey == NULL) - { - Status = -ENOMEM; - break; - } - Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length); - if (pKey->Length != wrq->u.data.length) - { - Status = -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY, Failed!!\n")); - } - else - { - RTMPAddKey(pAd, pKey); - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength)); - } - kfree(pKey); - break; - case OID_802_11_CONFIGURATION: - if (wrq->u.data.length != sizeof(NDIS_802_11_CONFIGURATION)) - Status = -EINVAL; - else - { - Status = copy_from_user(&Config, wrq->u.data.pointer, wrq->u.data.length); - pConfig = &Config; - - if ((pConfig->BeaconPeriod >= 20) && (pConfig->BeaconPeriod <=400)) - pAd->CommonCfg.BeaconPeriod = (USHORT) pConfig->BeaconPeriod; - - pAd->StaActive.AtimWin = (USHORT) pConfig->ATIMWindow; - MAP_KHZ_TO_CHANNEL_ID(pConfig->DSConfig, pAd->CommonCfg.Channel); - // - // Save the channel on MlmeAux for CntlOidRTBssidProc used. - // - pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; - - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_CONFIGURATION (BeacnPeriod=%ld,AtimW=%ld,Ch=%d)\n", - pConfig->BeaconPeriod, pConfig->ATIMWindow, pAd->CommonCfg.Channel)); - // Config has changed - pAd->bConfigChanged = TRUE; - } - break; -#ifdef DOT11_N_SUPPORT - case RT_OID_802_11_SET_HT_PHYMODE: - if (wrq->u.data.length != sizeof(OID_SET_HT_PHYMODE)) - Status = -EINVAL; - else - { - POID_SET_HT_PHYMODE pHTPhyMode = &HT_PhyMode; - - Status = copy_from_user(&HT_PhyMode, wrq->u.data.pointer, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Set::pHTPhyMode (PhyMode = %d,TransmitNo = %d, HtMode = %d, ExtOffset = %d , MCS = %d, BW = %d, STBC = %d, SHORTGI = %d) \n", - pHTPhyMode->PhyMode, pHTPhyMode->TransmitNo,pHTPhyMode->HtMode,pHTPhyMode->ExtOffset, - pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->SHORTGI)); - if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) - RTMPSetHT(pAd, pHTPhyMode); - } - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_HT_PHYMODE(MCS=%d,BW=%d,SGI=%d,STBC=%d)\n", - pAd->StaCfg.HTPhyMode.field.MCS, pAd->StaCfg.HTPhyMode.field.BW, pAd->StaCfg.HTPhyMode.field.ShortGI, - pAd->StaCfg.HTPhyMode.field.STBC)); - break; -#endif // DOT11_N_SUPPORT // - case RT_OID_802_11_SET_APSD_SETTING: - if (wrq->u.data.length != sizeof(ULONG)) - Status = -EINVAL; - else - { - ULONG apsd ; - Status = copy_from_user(&apsd, wrq->u.data.pointer, wrq->u.data.length); - - /*------------------------------------------------------------------- - |B31~B7 | B6~B5 | B4 | B3 | B2 | B1 | B0 | - --------------------------------------------------------------------- - | Rsvd | Max SP Len | AC_VO | AC_VI | AC_BK | AC_BE | APSD Capable | - ---------------------------------------------------------------------*/ - pAd->CommonCfg.bAPSDCapable = (apsd & 0x00000001) ? TRUE : FALSE; - pAd->CommonCfg.bAPSDAC_BE = ((apsd & 0x00000002) >> 1) ? TRUE : FALSE; - pAd->CommonCfg.bAPSDAC_BK = ((apsd & 0x00000004) >> 2) ? TRUE : FALSE; - pAd->CommonCfg.bAPSDAC_VI = ((apsd & 0x00000008) >> 3) ? TRUE : FALSE; - pAd->CommonCfg.bAPSDAC_VO = ((apsd & 0x00000010) >> 4) ? TRUE : FALSE; - pAd->CommonCfg.MaxSPLength = (UCHAR)((apsd & 0x00000060) >> 5); - - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_APSD_SETTING (apsd=0x%lx, APSDCap=%d, [BE,BK,VI,VO]=[%d/%d/%d/%d], MaxSPLen=%d)\n", apsd, pAd->CommonCfg.bAPSDCapable, - pAd->CommonCfg.bAPSDAC_BE, pAd->CommonCfg.bAPSDAC_BK, pAd->CommonCfg.bAPSDAC_VI, pAd->CommonCfg.bAPSDAC_VO, pAd->CommonCfg.MaxSPLength)); - } - break; - - case RT_OID_802_11_SET_APSD_PSM: - if (wrq->u.data.length != sizeof(ULONG)) - Status = -EINVAL; - else - { - // Driver needs to notify AP when PSM changes - Status = copy_from_user(&pAd->CommonCfg.bAPSDForcePowerSave, wrq->u.data.pointer, wrq->u.data.length); - if (pAd->CommonCfg.bAPSDForcePowerSave != pAd->StaCfg.Psm) - { - RTMP_SET_PSM_BIT(pAd, pAd->CommonCfg.bAPSDForcePowerSave); - RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); - } - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_APSD_PSM (bAPSDForcePowerSave:%d)\n", pAd->CommonCfg.bAPSDForcePowerSave)); - } - break; -#ifdef QOS_DLS_SUPPORT - case RT_OID_802_11_SET_DLS: - if (wrq->u.data.length != sizeof(ULONG)) - Status = -EINVAL; - else - { - BOOLEAN oldvalue = pAd->CommonCfg.bDLSCapable; - Status = copy_from_user(&pAd->CommonCfg.bDLSCapable, wrq->u.data.pointer, wrq->u.data.length); - if (oldvalue && !pAd->CommonCfg.bDLSCapable) - { - int i; - // tear down local dls table entry - for (i=0; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) - { - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); - } - } - - // tear down peer dls table entry - for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) - { - pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; - pAd->StaCfg.DLSEntry[i].Valid = FALSE; - RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); - } - } - } - - DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS (=%d)\n", pAd->CommonCfg.bDLSCapable)); - } - break; - - case RT_OID_802_11_SET_DLS_PARAM: - if (wrq->u.data.length != sizeof(RT_802_11_DLS_UI)) - Status = -EINVAL; - else - { - RT_802_11_DLS Dls; - - NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS)); - RTMPMoveMemory(&Dls, wrq->u.data.pointer, sizeof(RT_802_11_DLS_UI)); - MlmeEnqueue(pAd, - MLME_CNTL_STATE_MACHINE, - RT_OID_802_11_SET_DLS_PARAM, - sizeof(RT_802_11_DLS), - &Dls); - DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS_PARAM \n")); - } - break; -#endif // QOS_DLS_SUPPORT // - case RT_OID_802_11_SET_WMM: - if (wrq->u.data.length != sizeof(BOOLEAN)) - Status = -EINVAL; - else - { - Status = copy_from_user(&pAd->CommonCfg.bWmmCapable, wrq->u.data.pointer, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_WMM (=%d) \n", pAd->CommonCfg.bWmmCapable)); - } - break; - - case OID_802_11_DISASSOCIATE: - // - // Set NdisRadioStateOff to TRUE, instead of called MlmeRadioOff. - // Later on, NDIS_802_11_BSSID_LIST_EX->NumberOfItems should be 0 - // when query OID_802_11_BSSID_LIST. - // - // TRUE: NumberOfItems will set to 0. - // FALSE: NumberOfItems no change. - // - pAd->CommonCfg.NdisRadioStateOff = TRUE; - // Set to immediately send the media disconnect event - pAd->MlmeAux.CurrReqIsFromNdis = TRUE; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DISASSOCIATE \n")); - - - if (INFRA_ON(pAd)) - { - if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) - { - RTMP_MLME_RESET_STATE_MACHINE(pAd); - DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); - } - - MlmeEnqueue(pAd, - MLME_CNTL_STATE_MACHINE, - OID_802_11_DISASSOCIATE, - 0, - NULL); - - StateMachineTouched = TRUE; - } - break; - -#ifdef DOT11_N_SUPPORT - case RT_OID_802_11_SET_IMME_BA_CAP: - if (wrq->u.data.length != sizeof(OID_BACAP_STRUC)) - Status = -EINVAL; - else - { - OID_BACAP_STRUC Orde ; - Status = copy_from_user(&Orde, wrq->u.data.pointer, wrq->u.data.length); - if (Orde.Policy > BA_NOTUSE) - { - Status = NDIS_STATUS_INVALID_DATA; - } - else if (Orde.Policy == BA_NOTUSE) - { - pAd->CommonCfg.BACapability.field.Policy = BA_NOTUSE; - pAd->CommonCfg.BACapability.field.MpduDensity = Orde.MpduDensity; - pAd->CommonCfg.DesiredHtPhy.MpduDensity = Orde.MpduDensity; - pAd->CommonCfg.DesiredHtPhy.AmsduEnable = Orde.AmsduEnable; - pAd->CommonCfg.DesiredHtPhy.AmsduSize= Orde.AmsduSize; - pAd->CommonCfg.DesiredHtPhy.MimoPs= Orde.MMPSmode; - pAd->CommonCfg.BACapability.field.MMPSmode = Orde.MMPSmode; - // UPdata to HT IE - pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = Orde.MMPSmode; - pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = Orde.AmsduSize; - pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = Orde.MpduDensity; - } - else - { - pAd->CommonCfg.BACapability.field.AutoBA = Orde.AutoBA; - pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; // we only support immediate BA. - pAd->CommonCfg.BACapability.field.MpduDensity = Orde.MpduDensity; - pAd->CommonCfg.DesiredHtPhy.MpduDensity = Orde.MpduDensity; - pAd->CommonCfg.DesiredHtPhy.AmsduEnable = Orde.AmsduEnable; - pAd->CommonCfg.DesiredHtPhy.AmsduSize= Orde.AmsduSize; - pAd->CommonCfg.DesiredHtPhy.MimoPs = Orde.MMPSmode; - pAd->CommonCfg.BACapability.field.MMPSmode = Orde.MMPSmode; - - // UPdata to HT IE - pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = Orde.MMPSmode; - pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = Orde.AmsduSize; - pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = Orde.MpduDensity; - - if (pAd->CommonCfg.BACapability.field.RxBAWinLimit > MAX_RX_REORDERBUF) - pAd->CommonCfg.BACapability.field.RxBAWinLimit = MAX_RX_REORDERBUF; - - } - - pAd->CommonCfg.REGBACapability.word = pAd->CommonCfg.BACapability.word; - DBGPRINT(RT_DEBUG_TRACE, ("Set::(Orde.AutoBA = %d) (Policy=%d)(ReBAWinLimit=%d)(TxBAWinLimit=%d)(AutoMode=%d)\n",Orde.AutoBA, pAd->CommonCfg.BACapability.field.Policy, - pAd->CommonCfg.BACapability.field.RxBAWinLimit,pAd->CommonCfg.BACapability.field.TxBAWinLimit, pAd->CommonCfg.BACapability.field.AutoBA)); - DBGPRINT(RT_DEBUG_TRACE, ("Set::(MimoPs = %d)(AmsduEnable = %d) (AmsduSize=%d)(MpduDensity=%d)\n",pAd->CommonCfg.DesiredHtPhy.MimoPs, pAd->CommonCfg.DesiredHtPhy.AmsduEnable, - pAd->CommonCfg.DesiredHtPhy.AmsduSize, pAd->CommonCfg.DesiredHtPhy.MpduDensity)); - } - - break; - case RT_OID_802_11_ADD_IMME_BA: - DBGPRINT(RT_DEBUG_TRACE, (" Set :: RT_OID_802_11_ADD_IMME_BA \n")); - if (wrq->u.data.length != sizeof(OID_ADD_BA_ENTRY)) - Status = -EINVAL; - else - { - UCHAR index; - OID_ADD_BA_ENTRY BA; - MAC_TABLE_ENTRY *pEntry; - - Status = copy_from_user(&BA, wrq->u.data.pointer, wrq->u.data.length); - if (BA.TID > 15) - { - Status = NDIS_STATUS_INVALID_DATA; - break; - } - else - { - //BATableInsertEntry - //As ad-hoc mode, BA pair is not limited to only BSSID. so add via OID. - index = BA.TID; - // in ad hoc mode, when adding BA pair, we should insert this entry into MACEntry too - pEntry = MacTableLookup(pAd, BA.MACAddr); - if (!pEntry) - { - DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_802_11_ADD_IMME_BA. break on no connection.----:%x:%x\n", BA.MACAddr[4], BA.MACAddr[5])); - break; - } - if (BA.IsRecipient == FALSE) - { - if (pEntry->bIAmBadAtheros == TRUE) - pAd->CommonCfg.BACapability.field.RxBAWinLimit = 0x10; - - BAOriSessionSetUp(pAd, pEntry, index, 0, 100, TRUE); - } - else - { - //BATableInsertEntry(pAd, pEntry->Aid, BA.MACAddr, 0, 0xffff, BA.TID, BA.nMSDU, BA.IsRecipient); - } - - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_IMME_BA. Rec = %d. Mac = %x:%x:%x:%x:%x:%x . \n", - BA.IsRecipient, BA.MACAddr[0], BA.MACAddr[1], BA.MACAddr[2], BA.MACAddr[2] - , BA.MACAddr[4], BA.MACAddr[5])); - } - } - break; - - case RT_OID_802_11_TEAR_IMME_BA: - DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA \n")); - if (wrq->u.data.length != sizeof(OID_ADD_BA_ENTRY)) - Status = -EINVAL; - else - { - POID_ADD_BA_ENTRY pBA; - MAC_TABLE_ENTRY *pEntry; - - pBA = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); - - if (pBA == NULL) - { - DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA kmalloc() can't allocate enough memory\n")); - Status = NDIS_STATUS_FAILURE; - } - else - { - Status = copy_from_user(pBA, wrq->u.data.pointer, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA(TID=%d, bAllTid=%d)\n", pBA->TID, pBA->bAllTid)); - - if (!pBA->bAllTid && (pBA->TID > NUM_OF_TID)) - { - Status = NDIS_STATUS_INVALID_DATA; - break; - } - - if (pBA->IsRecipient == FALSE) - { - pEntry = MacTableLookup(pAd, pBA->MACAddr); - DBGPRINT(RT_DEBUG_TRACE, (" pBA->IsRecipient == FALSE\n")); - if (pEntry) - { - DBGPRINT(RT_DEBUG_TRACE, (" pBA->pEntry\n")); - BAOriSessionTearDown(pAd, pEntry->Aid, pBA->TID, FALSE, TRUE); - } - else - DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n")); - } - else - { - pEntry = MacTableLookup(pAd, pBA->MACAddr); - if (pEntry) - { - BARecSessionTearDown( pAd, (UCHAR)pEntry->Aid, pBA->TID, TRUE); - } - else - DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n")); - } - kfree(pBA); - } - } - break; -#endif // DOT11_N_SUPPORT // - - // For WPA_SUPPLICANT to set static wep key - case OID_802_11_ADD_WEP: - pWepKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); - - if(pWepKey == NULL) - { - Status = -ENOMEM; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed!!\n")); - break; - } - Status = copy_from_user(pWepKey, wrq->u.data.pointer, wrq->u.data.length); - if (Status) - { - Status = -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (length mismatch)!!\n")); - } - else - { - KeyIdx = pWepKey->KeyIndex & 0x0fffffff; - // KeyIdx must be 0 ~ 3 - if (KeyIdx > 4) - { - Status = -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (KeyIdx must be smaller than 4)!!\n")); - } - else - { - UCHAR CipherAlg = 0; - PUCHAR Key; - - // set key material and key length - NdisZeroMemory(pAd->SharedKey[BSS0][KeyIdx].Key, 16); - pAd->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength; - NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength); - - switch(pWepKey->KeyLength) - { - case 5: - CipherAlg = CIPHER_WEP64; - break; - case 13: - CipherAlg = CIPHER_WEP128; - break; - default: - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, only support CIPHER_WEP64(len:5) & CIPHER_WEP128(len:13)!!\n")); - Status = -EINVAL; - break; - } - pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CipherAlg; - - // Default key for tx (shared key) - if (pWepKey->KeyIndex & 0x80000000) - { -#ifdef WPA_SUPPLICANT_SUPPORT - // set key material and key length - NdisZeroMemory(pAd->StaCfg.DesireSharedKey[KeyIdx].Key, 16); - pAd->StaCfg.DesireSharedKey[KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength; - NdisMoveMemory(pAd->StaCfg.DesireSharedKey[KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength); - pAd->StaCfg.DesireSharedKeyId = KeyIdx; - pAd->StaCfg.DesireSharedKey[KeyIdx].CipherAlg = CipherAlg; -#endif // WPA_SUPPLICANT_SUPPORT // - pAd->StaCfg.DefaultKeyId = (UCHAR) KeyIdx; - } - -#ifdef WPA_SUPPLICANT_SUPPORT - if ((pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && - (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) - { - Key = pWepKey->KeyMaterial; - - // Set Group key material to Asic - AsicAddSharedKeyEntry(pAd, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL); - - // Update WCID attribute table and IVEIV table for this group key table - RTMPAddWcidAttributeEntry(pAd, BSS0, KeyIdx, CipherAlg, NULL); - - STA_PORT_SECURED(pAd); - - // Indicate Connected for GUI - pAd->IndicateMediaState = NdisMediaStateConnected; - } - else if (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED) -#endif // WPA_SUPPLICANT_SUPPORT - { - Key = pAd->SharedKey[BSS0][KeyIdx].Key; - - // Set key material and cipherAlg to Asic - AsicAddSharedKeyEntry(pAd, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL); - - if (pWepKey->KeyIndex & 0x80000000) - { - PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[BSSID_WCID]; - // Assign group key info - RTMPAddWcidAttributeEntry(pAd, BSS0, KeyIdx, CipherAlg, NULL); - // Assign pairwise key info - RTMPAddWcidAttributeEntry(pAd, BSS0, KeyIdx, CipherAlg, pEntry); - } - } - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP (id=0x%x, Len=%d-byte), %s\n", pWepKey->KeyIndex, pWepKey->KeyLength, (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED) ? "Port Secured":"Port NOT Secured")); - } - } - kfree(pWepKey); - break; -#ifdef WPA_SUPPLICANT_SUPPORT - case OID_SET_COUNTERMEASURES: - if (wrq->u.data.length != sizeof(int)) - Status = -EINVAL; - else - { - int enabled = 0; - Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length); - if (enabled == 1) - pAd->StaCfg.bBlockAssoc = TRUE; - else - // WPA MIC error should block association attempt for 60 seconds - pAd->StaCfg.bBlockAssoc = FALSE; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_SET_COUNTERMEASURES bBlockAssoc=%s\n", pAd->StaCfg.bBlockAssoc ? "TRUE":"FALSE")); - } - break; - case RT_OID_WPA_SUPPLICANT_SUPPORT: - if (wrq->u.data.length != sizeof(UCHAR)) - Status = -EINVAL; - else - { - Status = copy_from_user(&wpa_supplicant_enable, wrq->u.data.pointer, wrq->u.data.length); - pAd->StaCfg.WpaSupplicantUP = wpa_supplicant_enable; - DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_WPA_SUPPLICANT_SUPPORT (=%d)\n", pAd->StaCfg.WpaSupplicantUP)); - } - break; - case OID_802_11_DEAUTHENTICATION: - if (wrq->u.data.length != sizeof(MLME_DEAUTH_REQ_STRUCT)) - Status = -EINVAL; - else - { - MLME_DEAUTH_REQ_STRUCT *pInfo; - MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); - if (MsgElem == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__)); - return -EINVAL; - } - - pInfo = (MLME_DEAUTH_REQ_STRUCT *) MsgElem->Msg; - Status = copy_from_user(pInfo, wrq->u.data.pointer, wrq->u.data.length); - MlmeDeauthReqAction(pAd, MsgElem); - kfree(MsgElem); - - if (INFRA_ON(pAd)) - { - LinkDown(pAd, FALSE); - pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; - } - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DEAUTHENTICATION (Reason=%d)\n", pInfo->Reason)); - } - break; - case OID_802_11_DROP_UNENCRYPTED: - if (wrq->u.data.length != sizeof(int)) - Status = -EINVAL; - else - { - int enabled = 0; - Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length); - if (enabled == 1) - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - else - pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; - NdisAcquireSpinLock(&pAd->MacTabLock); - pAd->MacTab.Content[BSSID_WCID].PortSecured = pAd->StaCfg.PortSecured; - NdisReleaseSpinLock(&pAd->MacTabLock); - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DROP_UNENCRYPTED (=%d)\n", enabled)); - } - break; - case OID_802_11_SET_IEEE8021X: - if (wrq->u.data.length != sizeof(BOOLEAN)) - Status = -EINVAL; - else - { - Status = copy_from_user(&IEEE8021xState, wrq->u.data.pointer, wrq->u.data.length); - pAd->StaCfg.IEEE8021X = IEEE8021xState; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_IEEE8021X (=%d)\n", IEEE8021xState)); - } - break; - case OID_802_11_SET_IEEE8021X_REQUIRE_KEY: - if (wrq->u.data.length != sizeof(BOOLEAN)) - Status = -EINVAL; - else - { - Status = copy_from_user(&IEEE8021x_required_keys, wrq->u.data.pointer, wrq->u.data.length); - pAd->StaCfg.IEEE8021x_required_keys = IEEE8021x_required_keys; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_IEEE8021X_REQUIRE_KEY (%d)\n", IEEE8021x_required_keys)); - } - break; - case OID_802_11_PMKID: - pPmkId = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); - - if(pPmkId == NULL) { - Status = -ENOMEM; - break; - } - Status = copy_from_user(pPmkId, wrq->u.data.pointer, wrq->u.data.length); - - // check the PMKID information - if (pPmkId->BSSIDInfoCount == 0) - NdisZeroMemory(pAd->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO); - else - { - PBSSID_INFO pBssIdInfo; - UINT BssIdx; - UINT CachedIdx; - - for (BssIdx = 0; BssIdx < pPmkId->BSSIDInfoCount; BssIdx++) - { - // point to the indexed BSSID_INFO structure - pBssIdInfo = (PBSSID_INFO) ((PUCHAR) pPmkId + 2 * sizeof(UINT) + BssIdx * sizeof(BSSID_INFO)); - // Find the entry in the saved data base. - for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++) - { - // compare the BSSID - if (NdisEqualMemory(pBssIdInfo->BSSID, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, sizeof(NDIS_802_11_MAC_ADDRESS))) - break; - } - - // Found, replace it - if (CachedIdx < PMKID_NO) - { - DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx)); - NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO)); - pAd->StaCfg.SavedPMKNum++; - } - // Not found, replace the last one - else - { - // Randomly replace one - CachedIdx = (pBssIdInfo->BSSID[5] % PMKID_NO); - DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx)); - NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO)); - } - } - } - if(pPmkId) - kfree(pPmkId); - break; -#endif // WPA_SUPPLICANT_SUPPORT // - - - -#ifdef SNMP_SUPPORT - case OID_802_11_SHORTRETRYLIMIT: - if (wrq->u.data.length != sizeof(ULONG)) - Status = -EINVAL; - else - { - Status = copy_from_user(&ShortRetryLimit, wrq->u.data.pointer, wrq->u.data.length); - RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); - tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit; - RTMP_IO_WRITE32(pAd, TX_RTY_CFG, tx_rty_cfg.word); - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SHORTRETRYLIMIT (tx_rty_cfg.field.ShortRetryLimit=%d, ShortRetryLimit=%ld)\n", tx_rty_cfg.field.ShortRtyLimit, ShortRetryLimit)); - } - break; - - case OID_802_11_LONGRETRYLIMIT: - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT \n")); - if (wrq->u.data.length != sizeof(ULONG)) - Status = -EINVAL; - else - { - Status = copy_from_user(&LongRetryLimit, wrq->u.data.pointer, wrq->u.data.length); - RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); - tx_rty_cfg.field.LongRtyLimit = LongRetryLimit; - RTMP_IO_WRITE32(pAd, TX_RTY_CFG, tx_rty_cfg.word); - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT (tx_rty_cfg.field.LongRetryLimit= %d,LongRetryLimit=%ld)\n", tx_rty_cfg.field.LongRtyLimit, LongRetryLimit)); - } - break; - - case OID_802_11_WEPDEFAULTKEYVALUE: - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE\n")); - pKey = kmalloc(wrq->u.data.length, GFP_KERNEL); - Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length); - //pKey = &WepKey; - - if ( pKey->Length != wrq->u.data.length) - { - Status = -EINVAL; - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE, Failed!!\n")); - } - KeyIdx = pKey->KeyIndex & 0x0fffffff; - DBGPRINT(RT_DEBUG_TRACE,("pKey->KeyIndex =%d, pKey->KeyLength=%d\n", pKey->KeyIndex, pKey->KeyLength)); - - // it is a shared key - if (KeyIdx > 4) - Status = -EINVAL; - else - { - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = (UCHAR) pKey->KeyLength; - NdisMoveMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, &pKey->KeyMaterial, pKey->KeyLength); - if (pKey->KeyIndex & 0x80000000) - { - // Default key for tx (shared key) - pAd->StaCfg.DefaultKeyId = (UCHAR) KeyIdx; - } - //RestartAPIsRequired = TRUE; - } - break; - - - case OID_802_11_WEPDEFAULTKEYID: - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYID \n")); - - if (wrq->u.data.length != sizeof(UCHAR)) - Status = -EINVAL; - else - Status = copy_from_user(&pAd->StaCfg.DefaultKeyId, wrq->u.data.pointer, wrq->u.data.length); - - break; - - - case OID_802_11_CURRENTCHANNEL: - DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_CURRENTCHANNEL \n")); - if (wrq->u.data.length != sizeof(UCHAR)) - Status = -EINVAL; - else - { - Status = copy_from_user(&ctmp, wrq->u.data.pointer, wrq->u.data.length); - sprintf((PSTRING)&ctmp,"%d", ctmp); - Set_Channel_Proc(pAd, (PSTRING)&ctmp); - } - break; -#endif - - - - case RT_OID_802_11_SET_PSPXLINK_MODE: - if (wrq->u.data.length != sizeof(BOOLEAN)) - Status = -EINVAL; - else - { - Status = copy_from_user(&pAd->CommonCfg.PSPXlink, wrq->u.data.pointer, wrq->u.data.length); - /*if (pAd->CommonCfg.PSPXlink) - RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_PROMISCUOUS)*/ - DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_PSPXLINK_MODE(=%d) \n", pAd->CommonCfg.PSPXlink)); - } - break; - - - default: - DBGPRINT(RT_DEBUG_TRACE, ("Set::unknown IOCTL's subcmd = 0x%08x\n", cmd)); - Status = -EOPNOTSUPP; - break; - } - - - return Status; -} - -INT RTMPQueryInformation( - IN PRTMP_ADAPTER pAd, - IN OUT struct ifreq *rq, - IN INT cmd) -{ - struct iwreq *wrq = (struct iwreq *) rq; - NDIS_802_11_BSSID_LIST_EX *pBssidList = NULL; - PNDIS_WLAN_BSSID_EX pBss; - NDIS_802_11_SSID Ssid; - NDIS_802_11_CONFIGURATION *pConfiguration = NULL; - RT_802_11_LINK_STATUS *pLinkStatus = NULL; - RT_802_11_STA_CONFIG *pStaConfig = NULL; - NDIS_802_11_STATISTICS *pStatistics = NULL; - NDIS_802_11_RTS_THRESHOLD RtsThresh; - NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh; - NDIS_802_11_POWER_MODE PowerMode; - NDIS_802_11_NETWORK_INFRASTRUCTURE BssType; - RT_802_11_PREAMBLE PreamType; - NDIS_802_11_AUTHENTICATION_MODE AuthMode; - NDIS_802_11_WEP_STATUS WepStatus; - NDIS_MEDIA_STATE MediaState; - ULONG BssBufSize, ulInfo=0, NetworkTypeList[4], apsd = 0; - USHORT BssLen = 0; - PUCHAR pBuf = NULL, pPtr; - INT Status = NDIS_STATUS_SUCCESS; - UINT we_version_compiled; - UCHAR i, Padding = 0; - BOOLEAN RadioState; - STRING driverVersion[8]; - OID_SET_HT_PHYMODE *pHTPhyMode = NULL; - - -#ifdef SNMP_SUPPORT - //for snmp, kathy - DefaultKeyIdxValue *pKeyIdxValue; - INT valueLen; - TX_RTY_CFG_STRUC tx_rty_cfg; - ULONG ShortRetryLimit, LongRetryLimit; - UCHAR tmp[64]; -#endif //SNMP - - switch(cmd) - { - case RT_OID_DEVICE_NAME: - wrq->u.data.length = sizeof(pAd->nickname); - Status = copy_to_user(wrq->u.data.pointer, pAd->nickname, wrq->u.data.length); - break; - case RT_OID_VERSION_INFO: - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_VERSION_INFO \n")); - wrq->u.data.length = 8*sizeof(CHAR); - sprintf(&driverVersion[0], "%s", STA_DRIVER_VERSION); - driverVersion[7] = '\0'; - if (copy_to_user(wrq->u.data.pointer, &driverVersion[0], wrq->u.data.length)) - { - Status = -EFAULT; - } - break; - - case OID_802_11_BSSID_LIST: - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - { - /* - * Still scanning, indicate the caller should try again. - */ - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (Still scanning)\n")); - return -EAGAIN; - } - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (%d BSS returned)\n",pAd->ScanTab.BssNr)); - pAd->StaCfg.bScanReqIsFromWebUI = FALSE; - // Claculate total buffer size required - BssBufSize = sizeof(ULONG); - - for (i = 0; i < pAd->ScanTab.BssNr; i++) - { - // Align pointer to 4 bytes boundary. - //Padding = 4 - (pAdapter->ScanTab.BssEntry[i].VarIELen & 0x0003); - //if (Padding == 4) - // Padding = 0; - BssBufSize += (sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAd->ScanTab.BssEntry[i].VarIELen + Padding); - } - - // For safety issue, we add 256 bytes just in case - BssBufSize += 256; - // Allocate the same size as passed from higher layer - pBuf = kmalloc(BssBufSize, MEM_ALLOC_FLAG); - if(pBuf == NULL) - { - Status = -ENOMEM; - break; - } - // Init 802_11_BSSID_LIST_EX structure - NdisZeroMemory(pBuf, BssBufSize); - pBssidList = (PNDIS_802_11_BSSID_LIST_EX) pBuf; - pBssidList->NumberOfItems = pAd->ScanTab.BssNr; - - // Calculate total buffer length - BssLen = 4; // Consist of NumberOfItems - // Point to start of NDIS_WLAN_BSSID_EX - // pPtr = pBuf + sizeof(ULONG); - pPtr = (PUCHAR) &pBssidList->Bssid[0]; - for (i = 0; i < pAd->ScanTab.BssNr; i++) - { - pBss = (PNDIS_WLAN_BSSID_EX) pPtr; - NdisMoveMemory(&pBss->MacAddress, &pAd->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN); - if ((pAd->ScanTab.BssEntry[i].Hidden == 1) && (pAd->StaCfg.bShowHiddenSSID == FALSE)) - { - // - // We must return this SSID during 4way handshaking, otherwise Aegis will failed to parse WPA infomation - // and then failed to send EAPOl farame. - // - if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAd->StaCfg.PortSecured != WPA_802_1X_PORT_SECURED)) - { - pBss->Ssid.SsidLength = pAd->ScanTab.BssEntry[i].SsidLen; - NdisMoveMemory(pBss->Ssid.Ssid, pAd->ScanTab.BssEntry[i].Ssid, pAd->ScanTab.BssEntry[i].SsidLen); - } - else - pBss->Ssid.SsidLength = 0; - } - else - { - pBss->Ssid.SsidLength = pAd->ScanTab.BssEntry[i].SsidLen; - NdisMoveMemory(pBss->Ssid.Ssid, pAd->ScanTab.BssEntry[i].Ssid, pAd->ScanTab.BssEntry[i].SsidLen); - } - pBss->Privacy = pAd->ScanTab.BssEntry[i].Privacy; - pBss->Rssi = pAd->ScanTab.BssEntry[i].Rssi - pAd->BbpRssiToDbmDelta; - pBss->NetworkTypeInUse = NetworkTypeInUseSanity(&pAd->ScanTab.BssEntry[i]); - pBss->Configuration.Length = sizeof(NDIS_802_11_CONFIGURATION); - pBss->Configuration.BeaconPeriod = pAd->ScanTab.BssEntry[i].BeaconPeriod; - pBss->Configuration.ATIMWindow = pAd->ScanTab.BssEntry[i].AtimWin; - - MAP_CHANNEL_ID_TO_KHZ(pAd->ScanTab.BssEntry[i].Channel, pBss->Configuration.DSConfig); - - if (pAd->ScanTab.BssEntry[i].BssType == BSS_INFRA) - pBss->InfrastructureMode = Ndis802_11Infrastructure; - else - pBss->InfrastructureMode = Ndis802_11IBSS; - - NdisMoveMemory(pBss->SupportedRates, pAd->ScanTab.BssEntry[i].SupRate, pAd->ScanTab.BssEntry[i].SupRateLen); - NdisMoveMemory(pBss->SupportedRates + pAd->ScanTab.BssEntry[i].SupRateLen, - pAd->ScanTab.BssEntry[i].ExtRate, - pAd->ScanTab.BssEntry[i].ExtRateLen); - - if (pAd->ScanTab.BssEntry[i].VarIELen == 0) - { - pBss->IELength = sizeof(NDIS_802_11_FIXED_IEs); - NdisMoveMemory(pBss->IEs, &pAd->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs)); - pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs); - } - else - { - pBss->IELength = (ULONG)(sizeof(NDIS_802_11_FIXED_IEs) + pAd->ScanTab.BssEntry[i].VarIELen); - pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs); - NdisMoveMemory(pBss->IEs, &pAd->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs)); - NdisMoveMemory(pBss->IEs + sizeof(NDIS_802_11_FIXED_IEs), pAd->ScanTab.BssEntry[i].VarIEs, pAd->ScanTab.BssEntry[i].VarIELen); - pPtr += pAd->ScanTab.BssEntry[i].VarIELen; - } - pBss->Length = (ULONG)(sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAd->ScanTab.BssEntry[i].VarIELen + Padding); - -#if WIRELESS_EXT < 17 - if ((BssLen + pBss->Length) < wrq->u.data.length) - BssLen += pBss->Length; - else - { - pBssidList->NumberOfItems = i; - break; - } -#else - BssLen += pBss->Length; -#endif - } - -#if WIRELESS_EXT < 17 - wrq->u.data.length = BssLen; -#else - if (BssLen > wrq->u.data.length) - { - kfree(pBssidList); - return -E2BIG; - } - else - wrq->u.data.length = BssLen; -#endif - Status = copy_to_user(wrq->u.data.pointer, pBssidList, BssLen); - kfree(pBssidList); - break; - case OID_802_3_CURRENT_ADDRESS: - wrq->u.data.length = MAC_ADDR_LEN; - Status = copy_to_user(wrq->u.data.pointer, &pAd->CurrentAddress, wrq->u.data.length); - break; - case OID_GEN_MEDIA_CONNECT_STATUS: - if (pAd->IndicateMediaState == NdisMediaStateConnected) - MediaState = NdisMediaStateConnected; - else - MediaState = NdisMediaStateDisconnected; - - wrq->u.data.length = sizeof(NDIS_MEDIA_STATE); - Status = copy_to_user(wrq->u.data.pointer, &MediaState, wrq->u.data.length); - break; - case OID_802_11_BSSID: - if (INFRA_ON(pAd) || ADHOC_ON(pAd)) - { - Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.Bssid, sizeof(NDIS_802_11_MAC_ADDRESS)); - - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID(=EMPTY)\n")); - Status = -ENOTCONN; - } - break; - case OID_802_11_SSID: - NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); - NdisZeroMemory(Ssid.Ssid, MAX_LEN_OF_SSID); - Ssid.SsidLength = pAd->CommonCfg.SsidLen; - memcpy(Ssid.Ssid, pAd->CommonCfg.Ssid, Ssid.SsidLength); - wrq->u.data.length = sizeof(NDIS_802_11_SSID); - Status = copy_to_user(wrq->u.data.pointer, &Ssid, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SSID (Len=%d, ssid=%s)\n", Ssid.SsidLength,Ssid.Ssid)); - break; - case RT_OID_802_11_QUERY_LINK_STATUS: - pLinkStatus = (RT_802_11_LINK_STATUS *) kmalloc(sizeof(RT_802_11_LINK_STATUS), MEM_ALLOC_FLAG); - if (pLinkStatus) - { - pLinkStatus->CurrTxRate = RateIdTo500Kbps[pAd->CommonCfg.TxRate]; // unit : 500 kbps - pLinkStatus->ChannelQuality = pAd->Mlme.ChannelQuality; - pLinkStatus->RxByteCount = pAd->RalinkCounters.ReceivedByteCount; - pLinkStatus->TxByteCount = pAd->RalinkCounters.TransmittedByteCount; - pLinkStatus->CentralChannel = pAd->CommonCfg.CentralChannel; - wrq->u.data.length = sizeof(RT_802_11_LINK_STATUS); - Status = copy_to_user(wrq->u.data.pointer, pLinkStatus, wrq->u.data.length); - kfree(pLinkStatus); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LINK_STATUS\n")); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LINK_STATUS(kmalloc failed)\n")); - Status = -EFAULT; - } - break; - case OID_802_11_CONFIGURATION: - pConfiguration = (NDIS_802_11_CONFIGURATION *) kmalloc(sizeof(NDIS_802_11_CONFIGURATION), MEM_ALLOC_FLAG); - if (pConfiguration) - { - pConfiguration->Length = sizeof(NDIS_802_11_CONFIGURATION); - pConfiguration->BeaconPeriod = pAd->CommonCfg.BeaconPeriod; - pConfiguration->ATIMWindow = pAd->StaActive.AtimWin; - MAP_CHANNEL_ID_TO_KHZ(pAd->CommonCfg.Channel, pConfiguration->DSConfig); - wrq->u.data.length = sizeof(NDIS_802_11_CONFIGURATION); - Status = copy_to_user(wrq->u.data.pointer, pConfiguration, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CONFIGURATION(BeaconPeriod=%ld,AtimW=%ld,Channel=%d) \n", - pConfiguration->BeaconPeriod, pConfiguration->ATIMWindow, pAd->CommonCfg.Channel)); - kfree(pConfiguration); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CONFIGURATION(kmalloc failed)\n")); - Status = -EFAULT; - } - break; - case RT_OID_802_11_SNR_0: - if ((pAd->StaCfg.LastSNR0 > 0)) - { - ulInfo = ((0xeb - pAd->StaCfg.LastSNR0) * 3) / 16 ; - wrq->u.data.length = sizeof(ulInfo); - Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_SNR_0(0x=%lx)\n", ulInfo)); - } - else - Status = -EFAULT; - break; - case RT_OID_802_11_SNR_1: - if ((pAd->Antenna.field.RxPath > 1) && - (pAd->StaCfg.LastSNR1 > 0)) - { - ulInfo = ((0xeb - pAd->StaCfg.LastSNR1) * 3) / 16 ; - wrq->u.data.length = sizeof(ulInfo); - Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(0x=%lx)\n",ulInfo)); - } - else - Status = -EFAULT; - DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(pAd->StaCfg.LastSNR1=%d)\n",pAd->StaCfg.LastSNR1)); - break; - case OID_802_11_RSSI_TRIGGER: - ulInfo = pAd->StaCfg.RssiSample.LastRssi0 - pAd->BbpRssiToDbmDelta; - wrq->u.data.length = sizeof(ulInfo); - Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_RSSI_TRIGGER(=%ld)\n", ulInfo)); - break; - case OID_802_11_RSSI: - case RT_OID_802_11_RSSI: - ulInfo = pAd->StaCfg.RssiSample.LastRssi0; - wrq->u.data.length = sizeof(ulInfo); - Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); - break; - case RT_OID_802_11_RSSI_1: - ulInfo = pAd->StaCfg.RssiSample.LastRssi1; - wrq->u.data.length = sizeof(ulInfo); - Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); - break; - case RT_OID_802_11_RSSI_2: - ulInfo = pAd->StaCfg.RssiSample.LastRssi2; - wrq->u.data.length = sizeof(ulInfo); - Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); - break; - case OID_802_11_STATISTICS: - pStatistics = (NDIS_802_11_STATISTICS *) kmalloc(sizeof(NDIS_802_11_STATISTICS), MEM_ALLOC_FLAG); - if (pStatistics) - { - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS \n")); - // add the most up-to-date h/w raw counters into software counters - NICUpdateRawCounters(pAd); - - // Sanity check for calculation of sucessful count - if (pAd->WlanCounters.TransmittedFragmentCount.QuadPart < pAd->WlanCounters.RetryCount.QuadPart) - pAd->WlanCounters.TransmittedFragmentCount.QuadPart = pAd->WlanCounters.RetryCount.QuadPart; - - pStatistics->TransmittedFragmentCount.QuadPart = pAd->WlanCounters.TransmittedFragmentCount.QuadPart; - pStatistics->MulticastTransmittedFrameCount.QuadPart = pAd->WlanCounters.MulticastTransmittedFrameCount.QuadPart; - pStatistics->FailedCount.QuadPart = pAd->WlanCounters.FailedCount.QuadPart; - pStatistics->RetryCount.QuadPart = pAd->WlanCounters.RetryCount.QuadPart; - pStatistics->MultipleRetryCount.QuadPart = pAd->WlanCounters.MultipleRetryCount.QuadPart; - pStatistics->RTSSuccessCount.QuadPart = pAd->WlanCounters.RTSSuccessCount.QuadPart; - pStatistics->RTSFailureCount.QuadPart = pAd->WlanCounters.RTSFailureCount.QuadPart; - pStatistics->ACKFailureCount.QuadPart = pAd->WlanCounters.ACKFailureCount.QuadPart; - pStatistics->FrameDuplicateCount.QuadPart = pAd->WlanCounters.FrameDuplicateCount.QuadPart; - pStatistics->ReceivedFragmentCount.QuadPart = pAd->WlanCounters.ReceivedFragmentCount.QuadPart; - pStatistics->MulticastReceivedFrameCount.QuadPart = pAd->WlanCounters.MulticastReceivedFrameCount.QuadPart; -#ifdef DBG - pStatistics->FCSErrorCount = pAd->RalinkCounters.RealFcsErrCount; -#else - pStatistics->FCSErrorCount.QuadPart = pAd->WlanCounters.FCSErrorCount.QuadPart; - pStatistics->FrameDuplicateCount.u.LowPart = pAd->WlanCounters.FrameDuplicateCount.u.LowPart / 100; -#endif - wrq->u.data.length = sizeof(NDIS_802_11_STATISTICS); - Status = copy_to_user(wrq->u.data.pointer, pStatistics, wrq->u.data.length); - kfree(pStatistics); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS(kmalloc failed)\n")); - Status = -EFAULT; - } - break; - case OID_GEN_RCV_OK: - ulInfo = pAd->Counters8023.GoodReceives; - wrq->u.data.length = sizeof(ulInfo); - Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); - break; - case OID_GEN_RCV_NO_BUFFER: - ulInfo = pAd->Counters8023.RxNoBuffer; - wrq->u.data.length = sizeof(ulInfo); - Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); - break; - case RT_OID_802_11_PHY_MODE: - ulInfo = (ULONG)pAd->CommonCfg.PhyMode; - wrq->u.data.length = sizeof(ulInfo); - Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PHY_MODE (=%ld)\n", ulInfo)); - break; - case RT_OID_802_11_STA_CONFIG: - pStaConfig = (RT_802_11_STA_CONFIG *) kmalloc(sizeof(RT_802_11_STA_CONFIG), MEM_ALLOC_FLAG); - if (pStaConfig) - { - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG\n")); - pStaConfig->EnableTxBurst = pAd->CommonCfg.bEnableTxBurst; - pStaConfig->EnableTurboRate = 0; - pStaConfig->UseBGProtection = pAd->CommonCfg.UseBGProtection; - pStaConfig->UseShortSlotTime = pAd->CommonCfg.bUseShortSlotTime; - //pStaConfig->AdhocMode = pAd->StaCfg.AdhocMode; - pStaConfig->HwRadioStatus = (pAd->StaCfg.bHwRadio == TRUE) ? 1 : 0; - pStaConfig->Rsv1 = 0; - pStaConfig->SystemErrorBitmap = pAd->SystemErrorBitmap; - wrq->u.data.length = sizeof(RT_802_11_STA_CONFIG); - Status = copy_to_user(wrq->u.data.pointer, pStaConfig, wrq->u.data.length); - kfree(pStaConfig); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n")); - Status = -EFAULT; - } - break; - case OID_802_11_RTS_THRESHOLD: - RtsThresh = pAd->CommonCfg.RtsThreshold; - wrq->u.data.length = sizeof(RtsThresh); - Status = copy_to_user(wrq->u.data.pointer, &RtsThresh, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_RTS_THRESHOLD(=%ld)\n", RtsThresh)); - break; - case OID_802_11_FRAGMENTATION_THRESHOLD: - FragThresh = pAd->CommonCfg.FragmentThreshold; - if (pAd->CommonCfg.bUseZeroToDisableFragment == TRUE) - FragThresh = 0; - wrq->u.data.length = sizeof(FragThresh); - Status = copy_to_user(wrq->u.data.pointer, &FragThresh, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_FRAGMENTATION_THRESHOLD(=%ld)\n", FragThresh)); - break; - case OID_802_11_POWER_MODE: - PowerMode = pAd->StaCfg.WindowsPowerMode; - wrq->u.data.length = sizeof(PowerMode); - Status = copy_to_user(wrq->u.data.pointer, &PowerMode, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_POWER_MODE(=%d)\n", PowerMode)); - break; - case RT_OID_802_11_RADIO: - RadioState = (BOOLEAN) pAd->StaCfg.bSwRadio; - wrq->u.data.length = sizeof(RadioState); - Status = copy_to_user(wrq->u.data.pointer, &RadioState, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_RADIO (=%d)\n", RadioState)); - break; - case OID_802_11_INFRASTRUCTURE_MODE: - if (pAd->StaCfg.BssType == BSS_ADHOC) - BssType = Ndis802_11IBSS; - else if (pAd->StaCfg.BssType == BSS_INFRA) - BssType = Ndis802_11Infrastructure; - else if (pAd->StaCfg.BssType == BSS_MONITOR) - BssType = Ndis802_11Monitor; - else - BssType = Ndis802_11AutoUnknown; - - wrq->u.data.length = sizeof(BssType); - Status = copy_to_user(wrq->u.data.pointer, &BssType, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_INFRASTRUCTURE_MODE(=%d)\n", BssType)); - break; - case RT_OID_802_11_PREAMBLE: - PreamType = pAd->CommonCfg.TxPreamble; - wrq->u.data.length = sizeof(PreamType); - Status = copy_to_user(wrq->u.data.pointer, &PreamType, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PREAMBLE(=%d)\n", PreamType)); - break; - case OID_802_11_AUTHENTICATION_MODE: - AuthMode = pAd->StaCfg.AuthMode; - wrq->u.data.length = sizeof(AuthMode); - Status = copy_to_user(wrq->u.data.pointer, &AuthMode, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_AUTHENTICATION_MODE(=%d)\n", AuthMode)); - break; - case OID_802_11_WEP_STATUS: - WepStatus = pAd->StaCfg.WepStatus; - wrq->u.data.length = sizeof(WepStatus); - Status = copy_to_user(wrq->u.data.pointer, &WepStatus, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEP_STATUS(=%d)\n", WepStatus)); - break; - case OID_802_11_TX_POWER_LEVEL: - wrq->u.data.length = sizeof(ULONG); - Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.TxPower, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_TX_POWER_LEVEL %x\n",pAd->CommonCfg.TxPower)); - break; - case RT_OID_802_11_TX_POWER_LEVEL_1: - wrq->u.data.length = sizeof(ULONG); - Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.TxPowerPercentage, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAd->CommonCfg.TxPowerPercentage)); - break; - case OID_802_11_NETWORK_TYPES_SUPPORTED: - if ((pAd->RfIcType == RFIC_2850) || (pAd->RfIcType == RFIC_2750) || (pAd->RfIcType == RFIC_3052)) - { - NetworkTypeList[0] = 3; // NumberOfItems = 3 - NetworkTypeList[1] = Ndis802_11DS; // NetworkType[1] = 11b - NetworkTypeList[2] = Ndis802_11OFDM24; // NetworkType[2] = 11g - NetworkTypeList[3] = Ndis802_11OFDM5; // NetworkType[3] = 11a - wrq->u.data.length = 16; - Status = copy_to_user(wrq->u.data.pointer, &NetworkTypeList[0], wrq->u.data.length); - } - else - { - NetworkTypeList[0] = 2; // NumberOfItems = 2 - NetworkTypeList[1] = Ndis802_11DS; // NetworkType[1] = 11b - NetworkTypeList[2] = Ndis802_11OFDM24; // NetworkType[2] = 11g - wrq->u.data.length = 12; - Status = copy_to_user(wrq->u.data.pointer, &NetworkTypeList[0], wrq->u.data.length); - } - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_NETWORK_TYPES_SUPPORTED\n")); - break; - case OID_802_11_NETWORK_TYPE_IN_USE: - wrq->u.data.length = sizeof(ULONG); - if (pAd->CommonCfg.PhyMode == PHY_11A) - ulInfo = Ndis802_11OFDM5; - else if ((pAd->CommonCfg.PhyMode == PHY_11BG_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11G)) - ulInfo = Ndis802_11OFDM24; - else - ulInfo = Ndis802_11DS; - Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); - break; - case RT_OID_802_11_QUERY_LAST_RX_RATE: - ulInfo = (ULONG)pAd->LastRxRate; - wrq->u.data.length = sizeof(ulInfo); - Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_RX_RATE (=%ld)\n", ulInfo)); - break; - case RT_OID_802_11_QUERY_LAST_TX_RATE: - //ulInfo = (ULONG)pAd->LastTxRate; - ulInfo = (ULONG)pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word; - wrq->u.data.length = sizeof(ulInfo); - Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_TX_RATE (=%lx)\n", ulInfo)); - break; - case RT_OID_802_11_QUERY_EEPROM_VERSION: - wrq->u.data.length = sizeof(ULONG); - Status = copy_to_user(wrq->u.data.pointer, &pAd->EepromVersion, wrq->u.data.length); - break; - case RT_OID_802_11_QUERY_FIRMWARE_VERSION: - wrq->u.data.length = sizeof(ULONG); - Status = copy_to_user(wrq->u.data.pointer, &pAd->FirmwareVersion, wrq->u.data.length); - break; - case RT_OID_802_11_QUERY_NOISE_LEVEL: - wrq->u.data.length = sizeof(UCHAR); - Status = copy_to_user(wrq->u.data.pointer, &pAd->BbpWriteLatch[66], wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_NOISE_LEVEL (=%d)\n", pAd->BbpWriteLatch[66])); - break; - case RT_OID_802_11_EXTRA_INFO: - wrq->u.data.length = sizeof(ULONG); - Status = copy_to_user(wrq->u.data.pointer, &pAd->ExtraInfo, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_EXTRA_INFO (=%ld)\n", pAd->ExtraInfo)); - break; - case RT_OID_WE_VERSION_COMPILED: - wrq->u.data.length = sizeof(UINT); - we_version_compiled = WIRELESS_EXT; - Status = copy_to_user(wrq->u.data.pointer, &we_version_compiled, wrq->u.data.length); - break; - case RT_OID_802_11_QUERY_APSD_SETTING: - apsd = (pAd->CommonCfg.bAPSDCapable | (pAd->CommonCfg.bAPSDAC_BE << 1) | (pAd->CommonCfg.bAPSDAC_BK << 2) - | (pAd->CommonCfg.bAPSDAC_VI << 3) | (pAd->CommonCfg.bAPSDAC_VO << 4) | (pAd->CommonCfg.MaxSPLength << 5)); - - wrq->u.data.length = sizeof(ULONG); - Status = copy_to_user(wrq->u.data.pointer, &apsd, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_APSD_SETTING (=0x%lx,APSDCap=%d,AC_BE=%d,AC_BK=%d,AC_VI=%d,AC_VO=%d,MAXSPLen=%d)\n", - apsd,pAd->CommonCfg.bAPSDCapable,pAd->CommonCfg.bAPSDAC_BE,pAd->CommonCfg.bAPSDAC_BK,pAd->CommonCfg.bAPSDAC_VI,pAd->CommonCfg.bAPSDAC_VO,pAd->CommonCfg.MaxSPLength)); - break; - case RT_OID_802_11_QUERY_APSD_PSM: - wrq->u.data.length = sizeof(ULONG); - Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.bAPSDForcePowerSave, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_APSD_PSM (=%d)\n", pAd->CommonCfg.bAPSDForcePowerSave)); - break; - case RT_OID_802_11_QUERY_WMM: - wrq->u.data.length = sizeof(BOOLEAN); - Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.bWmmCapable, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_WMM (=%d)\n", pAd->CommonCfg.bWmmCapable)); - break; -#ifdef WPA_SUPPLICANT_SUPPORT - case RT_OID_NEW_DRIVER: - { - UCHAR enabled = 1; - wrq->u.data.length = sizeof(UCHAR); - Status = copy_to_user(wrq->u.data.pointer, &enabled, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_NEW_DRIVER (=%d)\n", enabled)); - } - break; - case RT_OID_WPA_SUPPLICANT_SUPPORT: - wrq->u.data.length = sizeof(UCHAR); - Status = copy_to_user(wrq->u.data.pointer, &pAd->StaCfg.WpaSupplicantUP, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WPA_SUPPLICANT_SUPPORT (=%d)\n", pAd->StaCfg.WpaSupplicantUP)); - break; -#endif // WPA_SUPPLICANT_SUPPORT // - - case RT_OID_DRIVER_DEVICE_NAME: - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_DRIVER_DEVICE_NAME \n")); - wrq->u.data.length = 16; - if (copy_to_user(wrq->u.data.pointer, pAd->StaCfg.dev_name, wrq->u.data.length)) - { - Status = -EFAULT; - } - break; - case RT_OID_802_11_QUERY_HT_PHYMODE: - pHTPhyMode = (OID_SET_HT_PHYMODE *) kmalloc(sizeof(OID_SET_HT_PHYMODE), MEM_ALLOC_FLAG); - if (pHTPhyMode) - { - pHTPhyMode->PhyMode = pAd->CommonCfg.PhyMode; - pHTPhyMode->HtMode = (UCHAR)pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE; - pHTPhyMode->BW = (UCHAR)pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.BW; - pHTPhyMode->MCS= (UCHAR)pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS; - pHTPhyMode->SHORTGI= (UCHAR)pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI; - pHTPhyMode->STBC= (UCHAR)pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC; - - pHTPhyMode->ExtOffset = ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) ? (EXTCHA_BELOW) : (EXTCHA_ABOVE)); - wrq->u.data.length = sizeof(OID_SET_HT_PHYMODE); - if (copy_to_user(wrq->u.data.pointer, pHTPhyMode, wrq->u.data.length)) - { - Status = -EFAULT; - } - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_HT_PHYMODE (PhyMode = %d, MCS =%d, BW = %d, STBC = %d, ExtOffset=%d)\n", - pHTPhyMode->HtMode, pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->ExtOffset)); - DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (.word = %x )\n", pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word)); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n")); - Status = -EFAULT; - } - break; - case RT_OID_802_11_COUNTRY_REGION: - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_COUNTRY_REGION \n")); - wrq->u.data.length = sizeof(ulInfo); - ulInfo = pAd->CommonCfg.CountryRegionForABand; - ulInfo = (ulInfo << 8)|(pAd->CommonCfg.CountryRegion); - if (copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length)) - { - Status = -EFAULT; - } - break; - case RT_OID_802_11_QUERY_DAT_HT_PHYMODE: - pHTPhyMode = (OID_SET_HT_PHYMODE *) kmalloc(sizeof(OID_SET_HT_PHYMODE), MEM_ALLOC_FLAG); - if (pHTPhyMode) - { - pHTPhyMode->PhyMode = pAd->CommonCfg.PhyMode; - pHTPhyMode->HtMode = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.HTMODE; - pHTPhyMode->BW = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.BW; - pHTPhyMode->MCS= (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.MCS; - pHTPhyMode->SHORTGI= (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.ShortGI; - pHTPhyMode->STBC= (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.STBC; - - wrq->u.data.length = sizeof(OID_SET_HT_PHYMODE); - if (copy_to_user(wrq->u.data.pointer, pHTPhyMode, wrq->u.data.length)) - { - Status = -EFAULT; - } - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_HT_PHYMODE (PhyMode = %d, MCS =%d, BW = %d, STBC = %d, ExtOffset=%d)\n", - pHTPhyMode->HtMode, pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->ExtOffset)); - DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (.word = %x )\n", pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word)); - } - else - { - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n")); - Status = -EFAULT; - } - break; - case RT_OID_QUERY_MULTIPLE_CARD_SUPPORT: - wrq->u.data.length = sizeof(UCHAR); - i = 0; -#ifdef MULTIPLE_CARD_SUPPORT - i = 1; -#endif // MULTIPLE_CARD_SUPPORT // - if (copy_to_user(wrq->u.data.pointer, &i, wrq->u.data.length)) - { - Status = -EFAULT; - } - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_QUERY_MULTIPLE_CARD_SUPPORT(=%d) \n", i)); - break; -#ifdef SNMP_SUPPORT - case RT_OID_802_11_MAC_ADDRESS: - wrq->u.data.length = MAC_ADDR_LEN; - Status = copy_to_user(wrq->u.data.pointer, &pAd->CurrentAddress, wrq->u.data.length); - break; - - case RT_OID_802_11_MANUFACTUREROUI: - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREROUI \n")); - wrq->u.data.length = ManufacturerOUI_LEN; - Status = copy_to_user(wrq->u.data.pointer, &pAd->CurrentAddress, wrq->u.data.length); - break; - - case RT_OID_802_11_MANUFACTURERNAME: - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTURERNAME \n")); - wrq->u.data.length = strlen(ManufacturerNAME); - Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length); - break; - - case RT_OID_802_11_RESOURCETYPEIDNAME: - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_RESOURCETYPEIDNAME \n")); - wrq->u.data.length = strlen(ResourceTypeIdName); - Status = copy_to_user(wrq->u.data.pointer, ResourceTypeIdName, wrq->u.data.length); - break; - - case RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED: - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED \n")); - ulInfo = 1; // 1 is support wep else 2 is not support. - wrq->u.data.length = sizeof(ulInfo); - Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); - break; - - case RT_OID_802_11_POWERMANAGEMENTMODE: - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_POWERMANAGEMENTMODE \n")); - if (pAd->StaCfg.Psm == PSMP_ACTION) - ulInfo = 1; // 1 is power active else 2 is power save. - else - ulInfo = 2; - - wrq->u.data.length = sizeof(ulInfo); - Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); - break; - - case OID_802_11_WEPDEFAULTKEYVALUE: - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEPDEFAULTKEYVALUE \n")); - //KeyIdxValue.KeyIdx = pAd->PortCfg.MBSSID[pAd->IoctlIF].DefaultKeyId; - pKeyIdxValue = wrq->u.data.pointer; - DBGPRINT(RT_DEBUG_TRACE,("KeyIdxValue.KeyIdx = %d, \n",pKeyIdxValue->KeyIdx)); - valueLen = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen; - NdisMoveMemory(pKeyIdxValue->Value, - &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, - valueLen); - pKeyIdxValue->Value[valueLen]='\0'; - - wrq->u.data.length = sizeof(DefaultKeyIdxValue); - - Status = copy_to_user(wrq->u.data.pointer, pKeyIdxValue, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE,("DefaultKeyId = %d, total len = %d, str len=%d, KeyValue= %02x %02x %02x %02x \n", - pAd->StaCfg.DefaultKeyId, - wrq->u.data.length, - pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen, - pAd->SharedKey[BSS0][0].Key[0], - pAd->SharedKey[BSS0][1].Key[0], - pAd->SharedKey[BSS0][2].Key[0], - pAd->SharedKey[BSS0][3].Key[0])); - break; - - case OID_802_11_WEPDEFAULTKEYID: - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPDEFAULTKEYID \n")); - wrq->u.data.length = sizeof(UCHAR); - Status = copy_to_user(wrq->u.data.pointer, &pAd->StaCfg.DefaultKeyId, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyId =%d \n", pAd->StaCfg.DefaultKeyId)); - break; - - case RT_OID_802_11_WEPKEYMAPPINGLENGTH: - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPKEYMAPPINGLENGTH \n")); - wrq->u.data.length = sizeof(UCHAR); - Status = copy_to_user(wrq->u.data.pointer, - &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen, - wrq->u.data.length); - break; - - case OID_802_11_SHORTRETRYLIMIT: - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SHORTRETRYLIMIT \n")); - wrq->u.data.length = sizeof(ULONG); - RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); - ShortRetryLimit = tx_rty_cfg.field.ShortRtyLimit; - DBGPRINT(RT_DEBUG_TRACE, ("ShortRetryLimit =%ld, tx_rty_cfg.field.ShortRetryLimit=%d\n", ShortRetryLimit, tx_rty_cfg.field.ShortRtyLimit)); - Status = copy_to_user(wrq->u.data.pointer, &ShortRetryLimit, wrq->u.data.length); - break; - - case OID_802_11_LONGRETRYLIMIT: - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_LONGRETRYLIMIT \n")); - wrq->u.data.length = sizeof(ULONG); - RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); - LongRetryLimit = tx_rty_cfg.field.LongRtyLimit; - DBGPRINT(RT_DEBUG_TRACE, ("LongRetryLimit =%ld, tx_rty_cfg.field.LongRtyLimit=%d\n", LongRetryLimit, tx_rty_cfg.field.LongRtyLimit)); - Status = copy_to_user(wrq->u.data.pointer, &LongRetryLimit, wrq->u.data.length); - break; - - case RT_OID_802_11_PRODUCTID: - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRODUCTID \n")); - -#ifdef RTMP_MAC_PCI - { - - USHORT device_id; - if (((POS_COOKIE)pAd->OS_Cookie)->pci_dev != NULL) - pci_read_config_word(((POS_COOKIE)pAd->OS_Cookie)->pci_dev, PCI_DEVICE_ID, &device_id); - else - DBGPRINT(RT_DEBUG_TRACE, (" pci_dev = NULL\n")); - sprintf((PSTRING)tmp, "%04x %04x\n", NIC_PCI_VENDOR_ID, device_id); - } -#endif // RTMP_MAC_PCI // - wrq->u.data.length = strlen((PSTRING)tmp); - Status = copy_to_user(wrq->u.data.pointer, tmp, wrq->u.data.length); - break; - - case RT_OID_802_11_MANUFACTUREID: - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREID \n")); - wrq->u.data.length = strlen(ManufacturerNAME); - Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length); - break; - - case OID_802_11_CURRENTCHANNEL: - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CURRENTCHANNEL \n")); - wrq->u.data.length = sizeof(UCHAR); - DBGPRINT(RT_DEBUG_TRACE, ("sizeof UCHAR=%d, channel=%d \n", sizeof(UCHAR), pAd->CommonCfg.Channel)); - Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.Channel, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); - break; -#endif //SNMP_SUPPORT - - case OID_802_11_BUILD_CHANNEL_EX: - { - UCHAR value; - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BUILD_CHANNEL_EX \n")); - wrq->u.data.length = sizeof(UCHAR); -#ifdef EXT_BUILD_CHANNEL_LIST - DBGPRINT(RT_DEBUG_TRACE, ("Support EXT_BUILD_CHANNEL_LIST.\n")); - value = 1; -#else - DBGPRINT(RT_DEBUG_TRACE, ("Doesn't support EXT_BUILD_CHANNEL_LIST.\n")); - value = 0; -#endif // EXT_BUILD_CHANNEL_LIST // - Status = copy_to_user(wrq->u.data.pointer, &value, 1); - DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); - } - break; - - case OID_802_11_GET_CH_LIST: - { - PRT_CHANNEL_LIST_INFO pChListBuf; - - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_CH_LIST \n")); - if (pAd->ChannelListNum == 0) - { - wrq->u.data.length = 0; - break; - } - - pChListBuf = (RT_CHANNEL_LIST_INFO *) kmalloc(sizeof(RT_CHANNEL_LIST_INFO), MEM_ALLOC_FLAG); - if (pChListBuf == NULL) - { - wrq->u.data.length = 0; - break; - } - - pChListBuf->ChannelListNum = pAd->ChannelListNum; - for (i = 0; i < pChListBuf->ChannelListNum; i++) - pChListBuf->ChannelList[i] = pAd->ChannelList[i].Channel; - - wrq->u.data.length = sizeof(RT_CHANNEL_LIST_INFO); - Status = copy_to_user(wrq->u.data.pointer, pChListBuf, sizeof(RT_CHANNEL_LIST_INFO)); - DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); - - if (pChListBuf) - kfree(pChListBuf); - } - break; - - case OID_802_11_GET_COUNTRY_CODE: - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_COUNTRY_CODE \n")); - wrq->u.data.length = 2; - Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.CountryCode, 2); - DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); - break; - - case OID_802_11_GET_CHANNEL_GEOGRAPHY: - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_CHANNEL_GEOGRAPHY \n")); - wrq->u.data.length = 1; - Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.Geography, 1); - DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); - break; - - -#ifdef QOS_DLS_SUPPORT - case RT_OID_802_11_QUERY_DLS: - wrq->u.data.length = sizeof(BOOLEAN); - Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.bDLSCapable, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_DLS(=%d)\n", pAd->CommonCfg.bDLSCapable)); - break; - - case RT_OID_802_11_QUERY_DLS_PARAM: - { - PRT_802_11_DLS_INFO pDlsInfo = kmalloc(sizeof(RT_802_11_DLS_INFO), GFP_ATOMIC); - if (pDlsInfo == NULL) - break; - - for (i=0; iEntry[i], &pAd->StaCfg.DLSEntry[i], sizeof(RT_802_11_DLS_UI)); - } - - pDlsInfo->num = MAX_NUM_OF_DLS_ENTRY; - wrq->u.data.length = sizeof(RT_802_11_DLS_INFO); - Status = copy_to_user(wrq->u.data.pointer, pDlsInfo, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_DLS_PARAM\n")); - - if (pDlsInfo) - kfree(pDlsInfo); - } - break; -#endif // QOS_DLS_SUPPORT // - - case OID_802_11_SET_PSPXLINK_MODE: - wrq->u.data.length = sizeof(BOOLEAN); - Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.PSPXlink, wrq->u.data.length); - DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SET_PSPXLINK_MODE(=%d)\n", pAd->CommonCfg.PSPXlink)); - break; - - - default: - DBGPRINT(RT_DEBUG_TRACE, ("Query::unknown IOCTL's subcmd = 0x%08x\n", cmd)); - Status = -EOPNOTSUPP; - break; - } - return Status; -} - -INT rt28xx_sta_ioctl( - IN struct net_device *net_dev, - IN OUT struct ifreq *rq, - IN INT cmd) -{ - POS_COOKIE pObj; - RTMP_ADAPTER *pAd = NULL; - struct iwreq *wrq = (struct iwreq *) rq; - BOOLEAN StateMachineTouched = FALSE; - INT Status = NDIS_STATUS_SUCCESS; - USHORT subcmd; - - - pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev); - if (pAd == NULL) - { - /* if 1st open fail, pAd will be free; - So the net_dev->priv will be NULL in 2rd open */ - return -ENETDOWN; - } - pObj = (POS_COOKIE) pAd->OS_Cookie; - - //check if the interface is down - if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { -#ifdef CONFIG_APSTA_MIXED_SUPPORT - if (wrq->u.data.pointer == NULL) - { - return Status; - } - - if (strstr(wrq->u.data.pointer, "OpMode") == NULL) -#endif // CONFIG_APSTA_MIXED_SUPPORT // - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - } - - { // determine this ioctl command is comming from which interface. - pObj->ioctl_if_type = INT_MAIN; - pObj->ioctl_if = MAIN_MBSSID; - } - - switch(cmd) - { -#ifdef RALINK_ATE -#ifdef RALINK_28xx_QA - case RTPRIV_IOCTL_ATE: - { - RtmpDoAte(pAd, wrq); - } - break; -#endif // RALINK_28xx_QA // -#endif // RALINK_ATE // - case SIOCGIFHWADDR: - DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIFHWADDR\n")); - memcpy(wrq->u.name, pAd->CurrentAddress, ETH_ALEN); - break; - case SIOCGIWNAME: - { - char *name=&wrq->u.name[0]; - rt_ioctl_giwname(net_dev, NULL, name, NULL); - break; - } - case SIOCGIWESSID: //Get ESSID - { - struct iw_point *essid=&wrq->u.essid; - rt_ioctl_giwessid(net_dev, NULL, essid, essid->pointer); - break; - } - case SIOCSIWESSID: //Set ESSID - { - struct iw_point *essid=&wrq->u.essid; - rt_ioctl_siwessid(net_dev, NULL, essid, essid->pointer); - break; - } - case SIOCSIWNWID: // set network id (the cell) - case SIOCGIWNWID: // get network id - Status = -EOPNOTSUPP; - break; - case SIOCSIWFREQ: //set channel/frequency (Hz) - { - struct iw_freq *freq=&wrq->u.freq; - rt_ioctl_siwfreq(net_dev, NULL, freq, NULL); - break; - } - case SIOCGIWFREQ: // get channel/frequency (Hz) - { - struct iw_freq *freq=&wrq->u.freq; - rt_ioctl_giwfreq(net_dev, NULL, freq, NULL); - break; - } - case SIOCSIWNICKN: //set node name/nickname - { - //struct iw_point *data=&wrq->u.data; - //rt_ioctl_siwnickn(net_dev, NULL, data, NULL); - break; - } - case SIOCGIWNICKN: //get node name/nickname - { - struct iw_point *erq = NULL; - erq = &wrq->u.data; - erq->length = strlen((PSTRING) pAd->nickname); - Status = copy_to_user(erq->pointer, pAd->nickname, erq->length); - break; - } - case SIOCGIWRATE: //get default bit rate (bps) - rt_ioctl_giwrate(net_dev, NULL, &wrq->u, NULL); - break; - case SIOCSIWRATE: //set default bit rate (bps) - rt_ioctl_siwrate(net_dev, NULL, &wrq->u, NULL); - break; - case SIOCGIWRTS: // get RTS/CTS threshold (bytes) - { - struct iw_param *rts=&wrq->u.rts; - rt_ioctl_giwrts(net_dev, NULL, rts, NULL); - break; - } - case SIOCSIWRTS: //set RTS/CTS threshold (bytes) - { - struct iw_param *rts=&wrq->u.rts; - rt_ioctl_siwrts(net_dev, NULL, rts, NULL); - break; - } - case SIOCGIWFRAG: //get fragmentation thr (bytes) - { - struct iw_param *frag=&wrq->u.frag; - rt_ioctl_giwfrag(net_dev, NULL, frag, NULL); - break; - } - case SIOCSIWFRAG: //set fragmentation thr (bytes) - { - struct iw_param *frag=&wrq->u.frag; - rt_ioctl_siwfrag(net_dev, NULL, frag, NULL); - break; - } - case SIOCGIWENCODE: //get encoding token & mode - { - struct iw_point *erq=&wrq->u.encoding; - if(erq) - rt_ioctl_giwencode(net_dev, NULL, erq, erq->pointer); - break; - } - case SIOCSIWENCODE: //set encoding token & mode - { - struct iw_point *erq=&wrq->u.encoding; - if(erq) - rt_ioctl_siwencode(net_dev, NULL, erq, erq->pointer); - break; - } - case SIOCGIWAP: //get access point MAC addresses - { - struct sockaddr *ap_addr=&wrq->u.ap_addr; - rt_ioctl_giwap(net_dev, NULL, ap_addr, ap_addr->sa_data); - break; - } - case SIOCSIWAP: //set access point MAC addresses - { - struct sockaddr *ap_addr=&wrq->u.ap_addr; - rt_ioctl_siwap(net_dev, NULL, ap_addr, ap_addr->sa_data); - break; - } - case SIOCGIWMODE: //get operation mode - { - __u32 *mode=&wrq->u.mode; - rt_ioctl_giwmode(net_dev, NULL, mode, NULL); - break; - } - case SIOCSIWMODE: //set operation mode - { - __u32 *mode=&wrq->u.mode; - rt_ioctl_siwmode(net_dev, NULL, mode, NULL); - break; - } - case SIOCGIWSENS: //get sensitivity (dBm) - case SIOCSIWSENS: //set sensitivity (dBm) - case SIOCGIWPOWER: //get Power Management settings - case SIOCSIWPOWER: //set Power Management settings - case SIOCGIWTXPOW: //get transmit power (dBm) - case SIOCSIWTXPOW: //set transmit power (dBm) - case SIOCGIWRANGE: //Get range of parameters - case SIOCGIWRETRY: //get retry limits and lifetime - case SIOCSIWRETRY: //set retry limits and lifetime - Status = -EOPNOTSUPP; - break; - case RT_PRIV_IOCTL: - case RT_PRIV_IOCTL_EXT: - subcmd = wrq->u.data.flags; - if( subcmd & OID_GET_SET_TOGGLE) - Status = RTMPSetInformation(pAd, rq, subcmd); - else - Status = RTMPQueryInformation(pAd, rq, subcmd); - break; - case SIOCGIWPRIV: - if (wrq->u.data.pointer) - { - if ( access_ok(VERIFY_WRITE, wrq->u.data.pointer, sizeof(privtab)) != TRUE) - break; - wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]); - if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab))) - Status = -EFAULT; - } - break; - case RTPRIV_IOCTL_SET: - if(access_ok(VERIFY_READ, wrq->u.data.pointer, wrq->u.data.length) != TRUE) - break; - rt_ioctl_setparam(net_dev, NULL, NULL, wrq->u.data.pointer); - break; - case RTPRIV_IOCTL_GSITESURVEY: - RTMPIoctlGetSiteSurvey(pAd, wrq); - break; -#ifdef DBG - case RTPRIV_IOCTL_MAC: - RTMPIoctlMAC(pAd, wrq); - break; - case RTPRIV_IOCTL_E2P: - RTMPIoctlE2PROM(pAd, wrq); - break; -#ifdef RTMP_RF_RW_SUPPORT - case RTPRIV_IOCTL_RF: - RTMPIoctlRF(pAd, wrq); - break; -#endif // RTMP_RF_RW_SUPPORT // -#endif // DBG // - - case SIOCETHTOOL: - break; - default: - DBGPRINT(RT_DEBUG_ERROR, ("IOCTL::unknown IOCTL's cmd = 0x%08x\n", cmd)); - Status = -EOPNOTSUPP; - break; - } - - if(StateMachineTouched) // Upper layer sent a MLME-related operations - RTMP_MLME_HANDLER(pAd); - - return Status; -} - -/* - ========================================================================== - Description: - Set SSID - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_SSID_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg) -{ - NDIS_802_11_SSID Ssid, *pSsid=NULL; - BOOLEAN StateMachineTouched = FALSE; - int success = TRUE; - - if( strlen(arg) <= MAX_LEN_OF_SSID) - { - NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); - if (strlen(arg) != 0) - { - NdisMoveMemory(Ssid.Ssid, arg, strlen(arg)); - Ssid.SsidLength = strlen(arg); - } - else //ANY ssid - { - Ssid.SsidLength = 0; - memcpy(Ssid.Ssid, "", 0); - pAdapter->StaCfg.BssType = BSS_INFRA; - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; - pAdapter->StaCfg.WepStatus = Ndis802_11EncryptionDisabled; - } - pSsid = &Ssid; - - if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) - { - RTMP_MLME_RESET_STATE_MACHINE(pAdapter); - DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); - } - - if ((pAdapter->StaCfg.WpaPassPhraseLen >= 8) && - (pAdapter->StaCfg.WpaPassPhraseLen <= 64)) - { - STRING passphrase_str[65] = {0}; - UCHAR keyMaterial[40]; - - RTMPMoveMemory(passphrase_str, pAdapter->StaCfg.WpaPassPhrase, pAdapter->StaCfg.WpaPassPhraseLen); - RTMPZeroMemory(pAdapter->StaCfg.PMK, 32); - if (pAdapter->StaCfg.WpaPassPhraseLen == 64) - { - AtoH((PSTRING) pAdapter->StaCfg.WpaPassPhrase, pAdapter->StaCfg.PMK, 32); - } - else - { - PasswordHash((PSTRING) pAdapter->StaCfg.WpaPassPhrase, Ssid.Ssid, Ssid.SsidLength, keyMaterial); - NdisMoveMemory(pAdapter->StaCfg.PMK, keyMaterial, 32); - } - } - - pAdapter->MlmeAux.CurrReqIsFromNdis = TRUE; - pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; - pAdapter->bConfigChanged = TRUE; - - MlmeEnqueue(pAdapter, - MLME_CNTL_STATE_MACHINE, - OID_802_11_SSID, - sizeof(NDIS_802_11_SSID), - (VOID *)pSsid); - - StateMachineTouched = TRUE; - DBGPRINT(RT_DEBUG_TRACE, ("Set_SSID_Proc::(Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid)); - } - else - success = FALSE; - - if (StateMachineTouched) // Upper layer sent a MLME-related operations - RTMP_MLME_HANDLER(pAdapter); - - return success; -} - -#ifdef WMM_SUPPORT -/* - ========================================================================== - Description: - Set WmmCapable Enable or Disable - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_WmmCapable_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - BOOLEAN bWmmCapable; - - bWmmCapable = simple_strtol(arg, 0, 10); - - if ((bWmmCapable == 1) - ) - pAd->CommonCfg.bWmmCapable = TRUE; - else if (bWmmCapable == 0) - pAd->CommonCfg.bWmmCapable = FALSE; - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_WmmCapable_Proc::(bWmmCapable=%d)\n", - pAd->CommonCfg.bWmmCapable)); - - return TRUE; -} -#endif // WMM_SUPPORT // - -/* - ========================================================================== - Description: - Set Network Type(Infrastructure/Adhoc mode) - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_NetworkType_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg) -{ - UINT32 Value = 0; - - if (strcmp(arg, "Adhoc") == 0) - { - if (pAdapter->StaCfg.BssType != BSS_ADHOC) - { - // Config has changed - pAdapter->bConfigChanged = TRUE; - if (MONITOR_ON(pAdapter)) - { - RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, STANORMAL); - RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); - Value &= (~0x80); - RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value); - OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED); - pAdapter->StaCfg.bAutoReconnect = TRUE; - LinkDown(pAdapter, FALSE); - } - if (INFRA_ON(pAdapter)) - { - //BOOLEAN Cancelled; - // Set the AutoReconnectSsid to prevent it reconnect to old SSID - // Since calling this indicate user don't want to connect to that SSID anymore. - pAdapter->MlmeAux.AutoReconnectSsidLen= 32; - NdisZeroMemory(pAdapter->MlmeAux.AutoReconnectSsid, pAdapter->MlmeAux.AutoReconnectSsidLen); - - LinkDown(pAdapter, FALSE); - - DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event BB!\n")); - } - } - pAdapter->StaCfg.BssType = BSS_ADHOC; - pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType; - DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(AD-HOC)\n")); - } - else if (strcmp(arg, "Infra") == 0) - { - if (pAdapter->StaCfg.BssType != BSS_INFRA) - { - // Config has changed - pAdapter->bConfigChanged = TRUE; - if (MONITOR_ON(pAdapter)) - { - RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, STANORMAL); - RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); - Value &= (~0x80); - RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value); - OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED); - pAdapter->StaCfg.bAutoReconnect = TRUE; - LinkDown(pAdapter, FALSE); - } - if (ADHOC_ON(pAdapter)) - { - // Set the AutoReconnectSsid to prevent it reconnect to old SSID - // Since calling this indicate user don't want to connect to that SSID anymore. - pAdapter->MlmeAux.AutoReconnectSsidLen= 32; - NdisZeroMemory(pAdapter->MlmeAux.AutoReconnectSsid, pAdapter->MlmeAux.AutoReconnectSsidLen); - - LinkDown(pAdapter, FALSE); - } - } - pAdapter->StaCfg.BssType = BSS_INFRA; - pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType; - DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(INFRA)\n")); - } - else if (strcmp(arg, "Monitor") == 0) - { - UCHAR bbpValue = 0; - BCN_TIME_CFG_STRUC csr; - OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_INFRA_ON); - OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_ADHOC_ON); - OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED); - // disable all periodic state machine - pAdapter->StaCfg.bAutoReconnect = FALSE; - // reset all mlme state machine - RTMP_MLME_RESET_STATE_MACHINE(pAdapter); - DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_MEDIA_STATE_CONNECTED \n")); - if (pAdapter->CommonCfg.CentralChannel == 0) - { -#ifdef DOT11_N_SUPPORT - if (pAdapter->CommonCfg.PhyMode == PHY_11AN_MIXED) - pAdapter->CommonCfg.CentralChannel = 36; - else -#endif // DOT11_N_SUPPORT // - pAdapter->CommonCfg.CentralChannel = 6; - } -#ifdef DOT11_N_SUPPORT - else - N_ChannelCheck(pAdapter); -#endif // DOT11_N_SUPPORT // - -#ifdef DOT11_N_SUPPORT - if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && - pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 && - pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) - { - // 40MHz ,control channel at lower - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue); - bbpValue &= (~0x18); - bbpValue |= 0x10; - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue); - pAdapter->CommonCfg.BBPCurrentBW = BW_40; - // RX : control channel at lower - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, &bbpValue); - bbpValue &= (~0x20); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, bbpValue); - - RTMP_IO_READ32(pAdapter, TX_BAND_CFG, &Value); - Value &= 0xfffffffe; - RTMP_IO_WRITE32(pAdapter, TX_BAND_CFG, Value); - pAdapter->CommonCfg.CentralChannel = pAdapter->CommonCfg.Channel + 2; - AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAdapter, pAdapter->CommonCfg.CentralChannel); - DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n", - pAdapter->CommonCfg.Channel, - pAdapter->CommonCfg.CentralChannel)); - } - else if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && - pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 && - pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW) - { - // 40MHz ,control channel at upper - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue); - bbpValue &= (~0x18); - bbpValue |= 0x10; - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue); - pAdapter->CommonCfg.BBPCurrentBW = BW_40; - RTMP_IO_READ32(pAdapter, TX_BAND_CFG, &Value); - Value |= 0x1; - RTMP_IO_WRITE32(pAdapter, TX_BAND_CFG, Value); - - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, &bbpValue); - bbpValue |= (0x20); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, bbpValue); - pAdapter->CommonCfg.CentralChannel = pAdapter->CommonCfg.Channel - 2; - AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAdapter, pAdapter->CommonCfg.CentralChannel); - DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n", - pAdapter->CommonCfg.Channel, - pAdapter->CommonCfg.CentralChannel)); - } - else -#endif // DOT11_N_SUPPORT // - { - // 20MHz - RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue); - bbpValue &= (~0x18); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue); - pAdapter->CommonCfg.BBPCurrentBW = BW_20; - AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.Channel, FALSE); - AsicLockChannel(pAdapter, pAdapter->CommonCfg.Channel); - DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAdapter->CommonCfg.Channel)); - } - // Enable Rx with promiscuous reception - RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, 0x3); - // ASIC supporsts sniffer function with replacing RSSI with timestamp. - //RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); - //Value |= (0x80); - //RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value); - // disable sync - RTMP_IO_READ32(pAdapter, BCN_TIME_CFG, &csr.word); - csr.field.bBeaconGen = 0; - csr.field.bTBTTEnable = 0; - csr.field.TsfSyncMode = 0; - RTMP_IO_WRITE32(pAdapter, BCN_TIME_CFG, csr.word); - - pAdapter->StaCfg.BssType = BSS_MONITOR; - pAdapter->net_dev->type = ARPHRD_IEEE80211_PRISM; //ARPHRD_IEEE80211; // IEEE80211 - DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(MONITOR)\n")); - } - - // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key - pAdapter->StaCfg.WpaState = SS_NOTUSE; - - DBGPRINT(RT_DEBUG_TRACE, ("Set_NetworkType_Proc::(NetworkType=%d)\n", pAdapter->StaCfg.BssType)); - - return TRUE; -} - -/* - ========================================================================== - Description: - Set Authentication mode - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_AuthMode_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg) -{ - if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch; - else if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; - else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared; - else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; - else if ((strcmp(arg, "WPANONE") == 0) || (strcmp(arg, "wpanone") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; - else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; -#ifdef WPA_SUPPLICANT_SUPPORT - else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA; - else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0)) - pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; -#endif // WPA_SUPPLICANT_SUPPORT // - else - return FALSE; - - pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; - - DBGPRINT(RT_DEBUG_TRACE, ("Set_AuthMode_Proc::(AuthMode=%d)\n", pAdapter->StaCfg.AuthMode)); - - return TRUE; -} - -/* - ========================================================================== - Description: - Set Encryption Type - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_EncrypType_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg) -{ - if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0)) - { - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; - pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; - pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; - } - else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0)) - { - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled; - pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled; - pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled; - } - else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0)) - { - if (pAdapter->StaCfg.AuthMode < Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - pAdapter->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; - pAdapter->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; - pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption2Enabled; - } - else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0)) - { - if (pAdapter->StaCfg.AuthMode < Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - pAdapter->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; - pAdapter->StaCfg.PairCipher = Ndis802_11Encryption3Enabled; - pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption3Enabled; - } - else - return FALSE; - - pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; - - DBGPRINT(RT_DEBUG_TRACE, ("Set_EncrypType_Proc::(EncrypType=%d)\n", pAdapter->StaCfg.WepStatus)); - - return TRUE; -} - -/* - ========================================================================== - Description: - Set Default Key ID - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_DefaultKeyID_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg) -{ - ULONG KeyIdx; - - KeyIdx = simple_strtol(arg, 0, 10); - if((KeyIdx >= 1 ) && (KeyIdx <= 4)) - pAdapter->StaCfg.DefaultKeyId = (UCHAR) (KeyIdx - 1 ); - else - return FALSE; //Invalid argument - - DBGPRINT(RT_DEBUG_TRACE, ("Set_DefaultKeyID_Proc::(DefaultKeyID=%d)\n", pAdapter->StaCfg.DefaultKeyId)); - - return TRUE; -} - -/* - ========================================================================== - Description: - Set WEP KEY1 - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_Key1_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg) -{ - int KeyLen; - int i; - UCHAR CipherAlg=CIPHER_WEP64; - - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - KeyLen = strlen(arg); - - switch (KeyLen) - { - case 5: //wep 40 Ascii type - pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii")); - break; - case 10: //wep 40 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex")); - break; - case 13: //wep 104 Ascii type - pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii")); - break; - case 26: //wep 104 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex")); - break; - default: //Invalid argument - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::Invalid argument (=%s)\n", arg)); - return FALSE; - } - - pAdapter->SharedKey[BSS0][0].CipherAlg = CipherAlg; - - // Set keys (into ASIC) - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - ; // not support - else // Old WEP stuff - { - AsicAddSharedKeyEntry(pAdapter, - 0, - 0, - pAdapter->SharedKey[BSS0][0].CipherAlg, - pAdapter->SharedKey[BSS0][0].Key, - NULL, - NULL); - } - - return TRUE; -} -/* - ========================================================================== - - Description: - Set WEP KEY2 - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_Key2_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg) -{ - int KeyLen; - int i; - UCHAR CipherAlg=CIPHER_WEP64; - - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - KeyLen = strlen(arg); - - switch (KeyLen) - { - case 5: //wep 40 Ascii type - pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii")); - break; - case 10: //wep 40 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex")); - break; - case 13: //wep 104 Ascii type - pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii")); - break; - case 26: //wep 104 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex")); - break; - default: //Invalid argument - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::Invalid argument (=%s)\n", arg)); - return FALSE; - } - pAdapter->SharedKey[BSS0][1].CipherAlg = CipherAlg; - - // Set keys (into ASIC) - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - ; // not support - else // Old WEP stuff - { - AsicAddSharedKeyEntry(pAdapter, - 0, - 1, - pAdapter->SharedKey[BSS0][1].CipherAlg, - pAdapter->SharedKey[BSS0][1].Key, - NULL, - NULL); - } - - return TRUE; -} -/* - ========================================================================== - Description: - Set WEP KEY3 - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_Key3_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg) -{ - int KeyLen; - int i; - UCHAR CipherAlg=CIPHER_WEP64; - - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - KeyLen = strlen(arg); - - switch (KeyLen) - { - case 5: //wep 40 Ascii type - pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg)); - break; - case 10: //wep 40 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg)); - break; - case 13: //wep 104 Ascii type - pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg)); - break; - case 26: //wep 104 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg)); - break; - default: //Invalid argument - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::Invalid argument (=%s)\n", arg)); - return FALSE; - } - pAdapter->SharedKey[BSS0][2].CipherAlg = CipherAlg; - - // Set keys (into ASIC) - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - ; // not support - else // Old WEP stuff - { - AsicAddSharedKeyEntry(pAdapter, - 0, - 2, - pAdapter->SharedKey[BSS0][2].CipherAlg, - pAdapter->SharedKey[BSS0][2].Key, - NULL, - NULL); - } - - return TRUE; -} -/* - ========================================================================== - Description: - Set WEP KEY4 - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_Key4_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg) -{ - int KeyLen; - int i; - UCHAR CipherAlg=CIPHER_WEP64; - - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - return TRUE; // do nothing - - KeyLen = strlen(arg); - - switch (KeyLen) - { - case 5: //wep 40 Ascii type - pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii")); - break; - case 10: //wep 40 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP64; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex")); - break; - case 13: //wep 104 Ascii type - pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen; - memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii")); - break; - case 26: //wep 104 Hex type - for(i=0; i < KeyLen; i++) - { - if( !isxdigit(*(arg+i)) ) - return FALSE; //Not Hex value; - } - pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ; - AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2); - CipherAlg = CIPHER_WEP128; - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex")); - break; - default: //Invalid argument - DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::Invalid argument (=%s)\n", arg)); - return FALSE; - } - pAdapter->SharedKey[BSS0][3].CipherAlg = CipherAlg; - - // Set keys (into ASIC) - if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) - ; // not support - else // Old WEP stuff - { - AsicAddSharedKeyEntry(pAdapter, - 0, - 3, - pAdapter->SharedKey[BSS0][3].CipherAlg, - pAdapter->SharedKey[BSS0][3].Key, - NULL, - NULL); - } - - return TRUE; -} - -/* - ========================================================================== - Description: - Set WPA PSK key - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_WPAPSK_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - int status; - - if ((pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && - (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) && - (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) - ) - return TRUE; // do nothing - - DBGPRINT(RT_DEBUG_TRACE, ("Set_WPAPSK_Proc::(WPAPSK=%s)\n", arg)); - - status = RT_CfgSetWPAPSKKey(pAd, arg, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, pAd->StaCfg.PMK); - if (status == FALSE) - { - DBGPRINT(RT_DEBUG_TRACE, ("Set_WPAPSK_Proc(): Set key failed!\n")); - return FALSE; - } - NdisZeroMemory(pAd->StaCfg.WpaPassPhrase, 64); - NdisMoveMemory(pAd->StaCfg.WpaPassPhrase, arg, strlen(arg)); - pAd->StaCfg.WpaPassPhraseLen = (UINT)strlen(arg); - - - - if(pAd->StaCfg.BssType == BSS_ADHOC && - pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) - { - pAd->StaCfg.WpaState = SS_NOTUSE; - } - else - { - // Start STA supplicant state machine - pAd->StaCfg.WpaState = SS_START; - } - - return TRUE; -} - -/* - ========================================================================== - Description: - Set Power Saving mode - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_PSMode_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg) -{ - if (pAdapter->StaCfg.BssType == BSS_INFRA) - { - if ((strcmp(arg, "Max_PSP") == 0) || - (strcmp(arg, "max_psp") == 0) || - (strcmp(arg, "MAX_PSP") == 0)) - { - // do NOT turn on PSM bit here, wait until MlmeCheckPsmChange() - // to exclude certain situations. - if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) - pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP; - pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP; - OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); - pAdapter->StaCfg.DefaultListenCount = 5; - - } - else if ((strcmp(arg, "Fast_PSP") == 0) || - (strcmp(arg, "fast_psp") == 0) || - (strcmp(arg, "FAST_PSP") == 0)) - { - // do NOT turn on PSM bit here, wait until MlmeCheckPsmChange() - // to exclude certain situations. - OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); - if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) - pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP; - pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP; - pAdapter->StaCfg.DefaultListenCount = 3; - } - else if ((strcmp(arg, "Legacy_PSP") == 0) || - (strcmp(arg, "legacy_psp") == 0) || - (strcmp(arg, "LEGACY_PSP") == 0)) - { - // do NOT turn on PSM bit here, wait until MlmeCheckPsmChange() - // to exclude certain situations. - OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); - if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) - pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP; - pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP; - pAdapter->StaCfg.DefaultListenCount = 3; - } - else - { - //Default Ndis802_11PowerModeCAM - // clear PSM bit immediately - RTMP_SET_PSM_BIT(pAdapter, PWR_ACTIVE); - OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); - if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) - pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; - pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; - } - - DBGPRINT(RT_DEBUG_TRACE, ("Set_PSMode_Proc::(PSMode=%ld)\n", pAdapter->StaCfg.WindowsPowerMode)); - } - else - return FALSE; - - - return TRUE; -} -//Add to suport the function which clould dynamicallly enable/disable PCIe Power Saving - -#ifdef WPA_SUPPLICANT_SUPPORT -/* - ========================================================================== - Description: - Set WpaSupport flag. - Value: - 0: Driver ignore wpa_supplicant. - 1: wpa_supplicant initiates scanning and AP selection. - 2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters. - Return: - TRUE if all parameters are OK, FALSE otherwise - ========================================================================== -*/ -INT Set_Wpa_Support( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - - if ( simple_strtol(arg, 0, 10) == 0) - pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; - else if ( simple_strtol(arg, 0, 10) == 1) - pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; - else if ( simple_strtol(arg, 0, 10) == 2) - pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE_WITH_WEB_UI; - else - pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; - - DBGPRINT(RT_DEBUG_TRACE, ("Set_Wpa_Support::(WpaSupplicantUP=%d)\n", pAd->StaCfg.WpaSupplicantUP)); - - return TRUE; -} -#endif // WPA_SUPPLICANT_SUPPORT // - -#ifdef DBG -/* - ========================================================================== - Description: - Read / Write MAC - Arguments: - pAdapter Pointer to our adapter - wrq Pointer to the ioctl argument - - Return Value: - None - - Note: - Usage: - 1.) iwpriv ra0 mac 0 ==> read MAC where Addr=0x0 - 2.) iwpriv ra0 mac 0=12 ==> write MAC where Addr=0x0, value=12 - ========================================================================== -*/ -VOID RTMPIoctlMAC( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq) -{ - PSTRING this_char; - PSTRING value; - INT j = 0, k = 0; - STRING msg[1024]; - STRING arg[255]; - ULONG macAddr = 0; - UCHAR temp[16]; - STRING temp2[16]; - UINT32 macValue = 0; - INT Status; - BOOLEAN bIsPrintAllMAC = FALSE; - - - memset(msg, 0x00, 1024); - if (wrq->u.data.length > 1) //No parameters. - { - Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); - sprintf(msg, "\n"); - - //Parsing Read or Write - this_char = arg; - if (!*this_char) - goto next; - - if ((value = rtstrchr(this_char, '=')) != NULL) - *value++ = 0; - - if (!value || !*value) - { //Read - // Sanity check - if(strlen(this_char) > 4) - goto next; - - j = strlen(this_char); - while(j-- > 0) - { - if(this_char[j] > 'f' || this_char[j] < '0') - return; - } - - // Mac Addr - k = j = strlen(this_char); - while(j-- > 0) - { - this_char[4-k+j] = this_char[j]; - } - - while(k < 4) - this_char[3-k++]='0'; - this_char[4]='\0'; - - if(strlen(this_char) == 4) - { - AtoH(this_char, temp, 2); - macAddr = *temp*256 + temp[1]; - if (macAddr < 0xFFFF) - { - RTMP_IO_READ32(pAdapter, macAddr, &macValue); - DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=%lx, MacValue=%x\n", macAddr, macValue)); - sprintf(msg+strlen(msg), "[0x%08lX]:%08X ", macAddr , macValue); - } - else - {//Invalid parametes, so default printk all mac - bIsPrintAllMAC = TRUE; - goto next; - } - } - } - else - { //Write - memcpy(&temp2, value, strlen(value)); - temp2[strlen(value)] = '\0'; - - // Sanity check - if((strlen(this_char) > 4) || strlen(temp2) > 8) - goto next; - - j = strlen(this_char); - while(j-- > 0) - { - if(this_char[j] > 'f' || this_char[j] < '0') - return; - } - - j = strlen(temp2); - while(j-- > 0) - { - if(temp2[j] > 'f' || temp2[j] < '0') - return; - } - - //MAC Addr - k = j = strlen(this_char); - while(j-- > 0) - { - this_char[4-k+j] = this_char[j]; - } - - while(k < 4) - this_char[3-k++]='0'; - this_char[4]='\0'; - - //MAC value - k = j = strlen(temp2); - while(j-- > 0) - { - temp2[8-k+j] = temp2[j]; - } - - while(k < 8) - temp2[7-k++]='0'; - temp2[8]='\0'; - - { - AtoH(this_char, temp, 2); - macAddr = *temp*256 + temp[1]; - - AtoH(temp2, temp, 4); - macValue = *temp*256*256*256 + temp[1]*256*256 + temp[2]*256 + temp[3]; - - // debug mode - if (macAddr == (HW_DEBUG_SETTING_BASE + 4)) - { - // 0x2bf4: byte0 non-zero: enable R17 tuning, 0: disable R17 tuning - if (macValue & 0x000000ff) - { - pAdapter->BbpTuning.bEnable = TRUE; - DBGPRINT(RT_DEBUG_TRACE,("turn on R17 tuning\n")); - } - else - { - UCHAR R66; - pAdapter->BbpTuning.bEnable = FALSE; - R66 = 0x26 + GET_LNA_GAIN(pAdapter); -#ifdef RALINK_ATE - if (ATE_ON(pAdapter)) - { - ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R66, (0x26 + GET_LNA_GAIN(pAdapter))); - } - else -#endif // RALINK_ATE // - - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R66, (0x26 + GET_LNA_GAIN(pAdapter))); - DBGPRINT(RT_DEBUG_TRACE,("turn off R17 tuning, restore to 0x%02x\n", R66)); - } - return; - } - - DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=%02lx, MacValue=0x%x\n", macAddr, macValue)); - - RTMP_IO_WRITE32(pAdapter, macAddr, macValue); - sprintf(msg+strlen(msg), "[0x%08lX]:%08X ", macAddr, macValue); - } - } - } - else - bIsPrintAllMAC = TRUE; -next: - if (bIsPrintAllMAC) - { - struct file *file_w; - PSTRING fileName = "MacDump.txt"; - mm_segment_t orig_fs; - - orig_fs = get_fs(); - set_fs(KERNEL_DS); - - // open file - file_w = filp_open(fileName, O_WRONLY|O_CREAT, 0); - if (IS_ERR(file_w)) - { - DBGPRINT(RT_DEBUG_TRACE, ("-->2) %s: Error %ld opening %s\n", __FUNCTION__, -PTR_ERR(file_w), fileName)); - } - else - { - if (file_w->f_op && file_w->f_op->write) - { - file_w->f_pos = 0; - macAddr = 0x1000; - - while (macAddr <= 0x1800) - { - RTMP_IO_READ32(pAdapter, macAddr, &macValue); - sprintf(msg, "%08lx = %08X\n", macAddr, macValue); - - // write data to file - file_w->f_op->write(file_w, msg, strlen(msg), &file_w->f_pos); - - printk("%s", msg); - macAddr += 4; - } - sprintf(msg, "\nDump all MAC values to %s\n", fileName); - } - filp_close(file_w, NULL); - } - set_fs(orig_fs); - } - if(strlen(msg) == 1) - sprintf(msg+strlen(msg), "===>Error command format!"); - - // Copy the information into the user buffer - wrq->u.data.length = strlen(msg); - Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); - - DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlMAC\n\n")); -} - -/* - ========================================================================== - Description: - Read / Write E2PROM - Arguments: - pAdapter Pointer to our adapter - wrq Pointer to the ioctl argument - - Return Value: - None - - Note: - Usage: - 1.) iwpriv ra0 e2p 0 ==> read E2PROM where Addr=0x0 - 2.) iwpriv ra0 e2p 0=1234 ==> write E2PROM where Addr=0x0, value=1234 - ========================================================================== -*/ -VOID RTMPIoctlE2PROM( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq) -{ - PSTRING this_char; - PSTRING value; - INT j = 0, k = 0; - STRING msg[1024]; - STRING arg[255]; - USHORT eepAddr = 0; - UCHAR temp[16]; - STRING temp2[16]; - USHORT eepValue; - int Status; - BOOLEAN bIsPrintAllE2P = FALSE; - - - memset(msg, 0x00, 1024); - if (wrq->u.data.length > 1) //No parameters. - { - Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); - sprintf(msg, "\n"); - - //Parsing Read or Write - this_char = arg; - - - if (!*this_char) - goto next; - - if ((value = rtstrchr(this_char, '=')) != NULL) - *value++ = 0; - - if (!value || !*value) - { //Read - - // Sanity check - if(strlen(this_char) > 4) - goto next; - - j = strlen(this_char); - while(j-- > 0) - { - if(this_char[j] > 'f' || this_char[j] < '0') - return; - } - - // E2PROM addr - k = j = strlen(this_char); - while(j-- > 0) - { - this_char[4-k+j] = this_char[j]; - } - - while(k < 4) - this_char[3-k++]='0'; - this_char[4]='\0'; - - if(strlen(this_char) == 4) - { - AtoH(this_char, temp, 2); - eepAddr = *temp*256 + temp[1]; - if (eepAddr < 0xFFFF) - { - RT28xx_EEPROM_READ16(pAdapter, eepAddr, eepValue); - sprintf(msg+strlen(msg), "[0x%04X]:0x%04X ", eepAddr , eepValue); - } - else - {//Invalid parametes, so default printk all bbp - bIsPrintAllE2P = TRUE; - goto next; - } - } - } - else - { //Write - memcpy(&temp2, value, strlen(value)); - temp2[strlen(value)] = '\0'; - - // Sanity check - if((strlen(this_char) > 4) || strlen(temp2) > 8) - goto next; - - j = strlen(this_char); - while(j-- > 0) - { - if(this_char[j] > 'f' || this_char[j] < '0') - return; - } - j = strlen(temp2); - while(j-- > 0) - { - if(temp2[j] > 'f' || temp2[j] < '0') - return; - } - - //MAC Addr - k = j = strlen(this_char); - while(j-- > 0) - { - this_char[4-k+j] = this_char[j]; - } - - while(k < 4) - this_char[3-k++]='0'; - this_char[4]='\0'; - - //MAC value - k = j = strlen(temp2); - while(j-- > 0) - { - temp2[4-k+j] = temp2[j]; - } - - while(k < 4) - temp2[3-k++]='0'; - temp2[4]='\0'; - - AtoH(this_char, temp, 2); - eepAddr = *temp*256 + temp[1]; - - AtoH(temp2, temp, 2); - eepValue = *temp*256 + temp[1]; - - RT28xx_EEPROM_WRITE16(pAdapter, eepAddr, eepValue); - sprintf(msg+strlen(msg), "[0x%02X]:%02X ", eepAddr, eepValue); - } - } - else - bIsPrintAllE2P = TRUE; -next: - if (bIsPrintAllE2P) - { - struct file *file_w; - PSTRING fileName = "EEPROMDump.txt"; - mm_segment_t orig_fs; - - orig_fs = get_fs(); - set_fs(KERNEL_DS); - - // open file - file_w = filp_open(fileName, O_WRONLY|O_CREAT, 0); - if (IS_ERR(file_w)) - { - DBGPRINT(RT_DEBUG_TRACE, ("-->2) %s: Error %ld opening %s\n", __FUNCTION__, -PTR_ERR(file_w), fileName)); - } - else - { - if (file_w->f_op && file_w->f_op->write) - { - file_w->f_pos = 0; - eepAddr = 0x00; - - while (eepAddr <= 0xFE) - { - RT28xx_EEPROM_READ16(pAdapter, eepAddr, eepValue); - sprintf(msg, "%08x = %04x\n", eepAddr , eepValue); - - // write data to file - file_w->f_op->write(file_w, msg, strlen(msg), &file_w->f_pos); - - printk("%s", msg); - eepAddr += 2; - } - sprintf(msg, "\nDump all EEPROM values to %s\n", fileName); - } - filp_close(file_w, NULL); - } - set_fs(orig_fs); - } - if(strlen(msg) == 1) - sprintf(msg+strlen(msg), "===>Error command format!"); - - - // Copy the information into the user buffer - wrq->u.data.length = strlen(msg); - Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); - - DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlE2PROM\n")); -} - - -#ifdef RT30xx -/* - ========================================================================== - Description: - Read / Write RF register -Arguments: - pAdapter Pointer to our adapter - wrq Pointer to the ioctl argument - - Return Value: - None - - Note: - Usage: - 1.) iwpriv ra0 rf ==> read all RF registers - 2.) iwpriv ra0 rf 1 ==> read RF where RegID=1 - 3.) iwpriv ra0 rf 1=10 ==> write RF R1=0x10 - ========================================================================== -*/ -VOID RTMPIoctlRF( - IN PRTMP_ADAPTER pAdapter, - IN struct iwreq *wrq) -{ - CHAR *this_char; - CHAR *value; - UCHAR regRF = 0; - STRING msg[2048]; - CHAR arg[255]; - INT rfId; - LONG rfValue; - int Status; - BOOLEAN bIsPrintAllRF = FALSE; - - - memset(msg, 0x00, 2048); - if (wrq->u.data.length > 1) //No parameters. - { - Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); - sprintf(msg, "\n"); - - //Parsing Read or Write - this_char = arg; - if (!*this_char) - goto next; - - if ((value = strchr(this_char, '=')) != NULL) - *value++ = 0; - - if (!value || !*value) - { //Read - if (sscanf((PSTRING) this_char, "%d", &(rfId)) == 1) - { - if (rfId <= 31) - { -#ifdef RALINK_ATE - /* - In RT2860 ATE mode, we do not load 8051 firmware. - We must access RF directly. - For RT2870 ATE mode, ATE_RF_IO_WRITE8(/READ8)_BY_REG_ID are redefined. - */ - if (ATE_ON(pAdapter)) - { - ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); - } - else -#endif // RALINK_ATE // - // according to Andy, Gary, David require. - // the command rf shall read rf register directly for dubug. - // BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); - RT30xxReadRFRegister(pAdapter, rfId, ®RF); - - sprintf(msg+strlen(msg), "R%02d[0x%02x]:%02X ", rfId, rfId, regRF); - } - else - {//Invalid parametes, so default printk all RF - bIsPrintAllRF = TRUE; - goto next; - } - } - else - { //Invalid parametes, so default printk all RF - bIsPrintAllRF = TRUE; - goto next; - } - } - else - { //Write - if ((sscanf((PSTRING) this_char, "%d", &(rfId)) == 1) && (sscanf((PSTRING) value, "%lx", &(rfValue)) == 1)) - { - if (rfId <= 31) - { -#ifdef RALINK_ATE - /* - In RT2860 ATE mode, we do not load 8051 firmware. - We must access RF directly. - For RT2870 ATE mode, ATE_RF_IO_WRITE8(/READ8)_BY_REG_ID are redefined. - */ - if (ATE_ON(pAdapter)) - { - ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); - ATE_RF_IO_WRITE8_BY_REG_ID(pAdapter, (UCHAR)rfId,(UCHAR) rfValue); - //Read it back for showing - ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); - sprintf(msg+strlen(msg), "R%02d[0x%02X]:%02X\n", rfId, rfId, regRF); - } - else -#endif // RALINK_ATE // - { - // according to Andy, Gary, David require. - // the command RF shall read/write RF register directly for dubug. - //BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); - //BBP_IO_WRITE8_BY_REG_ID(pAdapter, (UCHAR)bbpId,(UCHAR) bbpValue); - RT30xxReadRFRegister(pAdapter, rfId, ®RF); - RT30xxWriteRFRegister(pAdapter, (UCHAR)rfId,(UCHAR) rfValue); - //Read it back for showing - //BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); - RT30xxReadRFRegister(pAdapter, rfId, ®RF); - sprintf(msg+strlen(msg), "R%02d[0x%02X]:%02X\n", rfId, rfId, regRF); - } - } - else - {//Invalid parametes, so default printk all RF - bIsPrintAllRF = TRUE; - } - } - else - { //Invalid parametes, so default printk all RF - bIsPrintAllRF = TRUE; - } - } - } - else - bIsPrintAllRF = TRUE; -next: - if (bIsPrintAllRF) - { - memset(msg, 0x00, 2048); - sprintf(msg, "\n"); - for (rfId = 0; rfId <= 31; rfId++) - { -#ifdef RALINK_ATE - /* - In RT2860 ATE mode, we do not load 8051 firmware. - We must access RF directly. - For RT2870 ATE mode, ATE_RF_IO_WRITE8(/READ8)_BY_REG_ID are redefined. - */ - if (ATE_ON(pAdapter)) - { - ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); - } - else -#endif // RALINK_ATE // - - // according to Andy, Gary, David require. - // the command RF shall read/write RF register directly for dubug. - RT30xxReadRFRegister(pAdapter, rfId, ®RF); - sprintf(msg+strlen(msg), "%03d = %02X\n", rfId, regRF); - } - // Copy the information into the user buffer - DBGPRINT(RT_DEBUG_TRACE, ("strlen(msg)=%d\n", (UINT32)strlen(msg))); - wrq->u.data.length = strlen(msg); - if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) - { - DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); - } - } - else - { - if(strlen(msg) == 1) - sprintf(msg+strlen(msg), "===>Error command format!"); - - DBGPRINT(RT_DEBUG_TRACE, ("copy to user [msg=%s]\n", msg)); - // Copy the information into the user buffer - DBGPRINT(RT_DEBUG_TRACE, ("strlen(msg) =%d\n", (UINT32)strlen(msg))); - - // Copy the information into the user buffer - wrq->u.data.length = strlen(msg); - Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); - } - - DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlRF\n\n")); -} -#endif // RT30xx // -#endif // DBG // - - - - -INT Set_TGnWifiTest_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - if (simple_strtol(arg, 0, 10) == 0) - pAd->StaCfg.bTGnWifiTest = FALSE; - else - pAd->StaCfg.bTGnWifiTest = TRUE; - - DBGPRINT(RT_DEBUG_TRACE, ("IF Set_TGnWifiTest_Proc::(bTGnWifiTest=%d)\n", pAd->StaCfg.bTGnWifiTest)); - return TRUE; -} - -#ifdef EXT_BUILD_CHANNEL_LIST -INT Set_Ieee80211dClientMode_Proc( - IN PRTMP_ADAPTER pAdapter, - IN PSTRING arg) -{ - if (simple_strtol(arg, 0, 10) == 0) - pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_None; - else if (simple_strtol(arg, 0, 10) == 1) - pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_Flexible; - else if (simple_strtol(arg, 0, 10) == 2) - pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_Strict; - else - return FALSE; - - DBGPRINT(RT_DEBUG_TRACE, ("Set_Ieee802dMode_Proc::(IEEEE0211dMode=%d)\n", pAdapter->StaCfg.IEEE80211dClientMode)); - return TRUE; -} -#endif // EXT_BUILD_CHANNEL_LIST // - -#ifdef CARRIER_DETECTION_SUPPORT -INT Set_CarrierDetect_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - if (simple_strtol(arg, 0, 10) == 0) - pAd->CommonCfg.CarrierDetect.Enable = FALSE; - else - pAd->CommonCfg.CarrierDetect.Enable = TRUE; - - DBGPRINT(RT_DEBUG_TRACE, ("IF Set_CarrierDetect_Proc::(CarrierDetect.Enable=%d)\n", pAd->CommonCfg.CarrierDetect.Enable)); - return TRUE; -} -#endif // CARRIER_DETECTION_SUPPORT // - - -INT Show_Adhoc_MacTable_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING extra) -{ - INT i; - - sprintf(extra, "\n"); - -#ifdef DOT11_N_SUPPORT - sprintf(extra, "%sHT Operating Mode : %d\n", extra, pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode); -#endif // DOT11_N_SUPPORT // - - sprintf(extra, "%s\n%-19s%-4s%-4s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s\n", extra, - "MAC", "AID", "BSS", "RSSI0", "RSSI1", "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC"); - - for (i=1; iMacTab.Content[i]; - - if (strlen(extra) > (IW_PRIV_SIZE_MASK - 30)) - break; - if ((pEntry->ValidAsCLI || pEntry->ValidAsApCli) && (pEntry->Sst == SST_ASSOC)) - { - sprintf(extra, "%s%02X:%02X:%02X:%02X:%02X:%02X ", extra, - pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], - pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); - sprintf(extra, "%s%-4d", extra, (int)pEntry->Aid); - sprintf(extra, "%s%-4d", extra, (int)pEntry->apidx); - sprintf(extra, "%s%-7d", extra, pEntry->RssiSample.AvgRssi0); - sprintf(extra, "%s%-7d", extra, pEntry->RssiSample.AvgRssi1); - sprintf(extra, "%s%-7d", extra, pEntry->RssiSample.AvgRssi2); - sprintf(extra, "%s%-10s", extra, GetPhyMode(pEntry->HTPhyMode.field.MODE)); - sprintf(extra, "%s%-6s", extra, GetBW(pEntry->HTPhyMode.field.BW)); - sprintf(extra, "%s%-6d", extra, pEntry->HTPhyMode.field.MCS); - sprintf(extra, "%s%-6d", extra, pEntry->HTPhyMode.field.ShortGI); - sprintf(extra, "%s%-6d", extra, pEntry->HTPhyMode.field.STBC); - sprintf(extra, "%s%-10d, %d, %d%%\n", extra, pEntry->DebugFIFOCount, pEntry->DebugTxCount, - (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0); - sprintf(extra, "%s\n", extra); - } - } - - return TRUE; -} - - -INT Set_BeaconLostTime_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - ULONG ltmp = (ULONG)simple_strtol(arg, 0, 10); - - if ((ltmp != 0) && (ltmp <= 60)) - pAd->StaCfg.BeaconLostTime = (ltmp * OS_HZ); - - DBGPRINT(RT_DEBUG_TRACE, ("IF Set_BeaconLostTime_Proc::(BeaconLostTime=%ld)\n", pAd->StaCfg.BeaconLostTime)); - return TRUE; -} - -INT Set_AutoRoaming_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - if (simple_strtol(arg, 0, 10) == 0) - pAd->StaCfg.bAutoRoaming = FALSE; - else - pAd->StaCfg.bAutoRoaming = TRUE; - - DBGPRINT(RT_DEBUG_TRACE, ("IF Set_AutoRoaming_Proc::(bAutoRoaming=%d)\n", pAd->StaCfg.bAutoRoaming)); - return TRUE; -} - - -/* - ========================================================================== - Description: - Issue a site survey command to driver - Arguments: - pAdapter Pointer to our adapter - wrq Pointer to the ioctl argument - - Return Value: - None - - Note: - Usage: - 1.) iwpriv ra0 set site_survey - ========================================================================== -*/ -INT Set_SiteSurvey_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - NDIS_802_11_SSID Ssid; - - //check if the interface is down - if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) - { - DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); - return -ENETDOWN; - } - - if (MONITOR_ON(pAd)) - { - DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n")); - return -EINVAL; - } - - RTMPZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); - Ssid.SsidLength = 0; - if ((arg != NULL) && - (strlen(arg) <= MAX_LEN_OF_SSID)) - { - RTMPMoveMemory(Ssid.Ssid, arg, strlen(arg)); - Ssid.SsidLength = strlen(arg); - } - - pAd->StaCfg.bScanReqIsFromWebUI = TRUE; - - if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) - { - RTMP_MLME_RESET_STATE_MACHINE(pAd); - DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); - } - - // tell CNTL state machine to call NdisMSetInformationComplete() after completing - // this request, because this request is initiated by NDIS. - pAd->MlmeAux.CurrReqIsFromNdis = FALSE; - // Reset allowed scan retries - pAd->StaCfg.ScanCnt = 0; - NdisGetSystemUpTime(&pAd->StaCfg.LastScanTime); - - MlmeEnqueue(pAd, - MLME_CNTL_STATE_MACHINE, - OID_802_11_BSSID_LIST_SCAN, - Ssid.SsidLength, - Ssid.Ssid); - - RTMP_MLME_HANDLER(pAd); - - DBGPRINT(RT_DEBUG_TRACE, ("Set_SiteSurvey_Proc\n")); - - return TRUE; -} - -INT Set_ForceTxBurst_Proc( - IN PRTMP_ADAPTER pAd, - IN PSTRING arg) -{ - if (simple_strtol(arg, 0, 10) == 0) - pAd->StaCfg.bForceTxBurst = FALSE; - else - pAd->StaCfg.bForceTxBurst = TRUE; - - DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ForceTxBurst_Proc::(bForceTxBurst=%d)\n", pAd->StaCfg.bForceTxBurst)); - return TRUE; -} - -#ifdef ANT_DIVERSITY_SUPPORT -INT Set_Antenna_Proc( - IN PRTMP_ADAPTER pAd, - IN PUCHAR arg) -{ - UCHAR UsedAnt; - DBGPRINT(RT_DEBUG_TRACE, ("==> Set_Antenna_Proc *******************\n")); - - if(simple_strtol(arg, 0, 10) <= 3) - UsedAnt = simple_strtol(arg, 0, 10); - - pAd->CommonCfg.bRxAntDiversity = UsedAnt; // Auto switch - if (UsedAnt == ANT_DIVERSITY_ENABLE) - { - pAd->RxAnt.EvaluateStableCnt = 0; - DBGPRINT(RT_DEBUG_TRACE, ("<== Set_Antenna_Proc(Auto Switch Mode), (%d,%d)\n", pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt)); - } - /* 2: Fix in the PHY Antenna CON1*/ - if (UsedAnt == ANT_FIX_ANT1) - { - AsicSetRxAnt(pAd, 0); - DBGPRINT(RT_DEBUG_TRACE, ("<== Set_Antenna_Proc(Fix in Ant CON1), (%d,%d)\n", pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt)); - } - /* 3: Fix in the PHY Antenna CON2*/ - if (UsedAnt == ANT_FIX_ANT2) - { - AsicSetRxAnt(pAd, 1); - DBGPRINT(RT_DEBUG_TRACE, ("<== Set_Antenna_Proc(Fix in Ant CON2), (%d,%d)\n", pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt)); - } - - return TRUE; -} -#endif // ANT_DIVERSITY_SUPPORT // \ No newline at end of file diff --git a/drivers/staging/rt3090/wpa.h b/drivers/staging/rt3090/wpa.h deleted file mode 100644 index 8baa28774e3007cb375bea295446d5656a84cc55..0000000000000000000000000000000000000000 --- a/drivers/staging/rt3090/wpa.h +++ /dev/null @@ -1,447 +0,0 @@ -/* - ************************************************************************* - * Ralink Tech Inc. - * 5F., No.36, Taiyuan St., Jhubei City, - * Hsinchu County 302, - * Taiwan, R.O.C. - * - * (c) Copyright 2002-2007, Ralink Technology, 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. * - * * - ************************************************************************* - - Module Name: - wpa.h - - Abstract: - - Revision History: - Who When What - -------- ---------- ---------------------------------------------- - Name Date Modification logs -*/ - -#ifndef __WPA_H__ -#define __WPA_H__ - -// EAPOL Key descripter frame format related length -#define LEN_KEY_DESC_NONCE 32 -#define LEN_KEY_DESC_IV 16 -#define LEN_KEY_DESC_RSC 8 -#define LEN_KEY_DESC_ID 8 -#define LEN_KEY_DESC_REPLAY 8 -#define LEN_KEY_DESC_MIC 16 - -// The length is the EAPoL-Key frame except key data field. -// Please refer to 802.11i-2004 ,Figure 43u in p.78 -#define LEN_EAPOL_KEY_MSG (sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE) - -// EAP Code Type. -#define EAP_CODE_REQUEST 1 -#define EAP_CODE_RESPONSE 2 -#define EAP_CODE_SUCCESS 3 -#define EAP_CODE_FAILURE 4 - -// EAPOL frame Protocol Version -#define EAPOL_VER 1 -#define EAPOL_VER2 2 - -// EAPOL-KEY Descriptor Type -#define WPA1_KEY_DESC 0xfe -#define WPA2_KEY_DESC 0x02 - -// Key Descriptor Version of Key Information -#define DESC_TYPE_TKIP 1 -#define DESC_TYPE_AES 2 - -#define LEN_MSG1_2WAY 0x7f -#define MAX_LEN_OF_EAP_HS 256 - -#define LEN_MASTER_KEY 32 - -// EAPOL EK, MK -#define LEN_EAP_EK 16 -#define LEN_EAP_MICK 16 -#define LEN_EAP_KEY ((LEN_EAP_EK)+(LEN_EAP_MICK)) -// TKIP key related -#define LEN_PMKID 16 -#define LEN_TKIP_EK 16 -#define LEN_TKIP_RXMICK 8 -#define LEN_TKIP_TXMICK 8 -#define LEN_AES_EK 16 -#define LEN_AES_KEY LEN_AES_EK -#define LEN_TKIP_KEY ((LEN_TKIP_EK)+(LEN_TKIP_RXMICK)+(LEN_TKIP_TXMICK)) -#define TKIP_AP_TXMICK_OFFSET ((LEN_EAP_KEY)+(LEN_TKIP_EK)) -#define TKIP_AP_RXMICK_OFFSET (TKIP_AP_TXMICK_OFFSET+LEN_TKIP_TXMICK) -#define TKIP_GTK_LENGTH ((LEN_TKIP_EK)+(LEN_TKIP_RXMICK)+(LEN_TKIP_TXMICK)) -#define LEN_PTK ((LEN_EAP_KEY)+(LEN_TKIP_KEY)) -#define MIN_LEN_OF_GTK 5 -#define LEN_PMK 32 -#define LEN_PMK_NAME 16 -#define LEN_NONCE 32 - -// RSN IE Length definition -#define MAX_LEN_OF_RSNIE 255 -#define MIN_LEN_OF_RSNIE 8 - -#define KEY_LIFETIME 3600 - -//EAP Packet Type -#define EAPPacket 0 -#define EAPOLStart 1 -#define EAPOLLogoff 2 -#define EAPOLKey 3 -#define EAPOLASFAlert 4 -#define EAPTtypeMax 5 - -#define EAPOL_MSG_INVALID 0 -#define EAPOL_PAIR_MSG_1 1 -#define EAPOL_PAIR_MSG_2 2 -#define EAPOL_PAIR_MSG_3 3 -#define EAPOL_PAIR_MSG_4 4 -#define EAPOL_GROUP_MSG_1 5 -#define EAPOL_GROUP_MSG_2 6 - -#define PAIRWISEKEY 1 -#define GROUPKEY 0 - -// Retry timer counter initial value -#define PEER_MSG1_RETRY_TIMER_CTR 0 -#define PEER_MSG3_RETRY_TIMER_CTR 10 -#define GROUP_MSG1_RETRY_TIMER_CTR 20 - -// WPA mechanism retry timer interval -#define PEER_MSG1_RETRY_EXEC_INTV 1000 // 1 sec -#define PEER_MSG3_RETRY_EXEC_INTV 3000 // 3 sec -#define GROUP_KEY_UPDATE_EXEC_INTV 1000 // 1 sec -#define PEER_GROUP_KEY_UPDATE_INIV 2000 // 2 sec - -#define ENQUEUE_EAPOL_START_TIMER 200 // 200 ms - -// group rekey interval -#define TIME_REKEY 0 -#define PKT_REKEY 1 -#define DISABLE_REKEY 2 -#define MAX_REKEY 2 - -#define MAX_REKEY_INTER 0x3ffffff - -#define GROUP_SUITE 0 -#define PAIRWISE_SUITE 1 -#define AKM_SUITE 2 -#define PMKID_LIST 3 - - -#define EAPOL_START_DISABLE 0 -#define EAPOL_START_PSK 1 -#define EAPOL_START_1X 2 - -#define MIX_CIPHER_WPA_TKIP_ON(x) (((x) & 0x08) != 0) -#define MIX_CIPHER_WPA_AES_ON(x) (((x) & 0x04) != 0) -#define MIX_CIPHER_WPA2_TKIP_ON(x) (((x) & 0x02) != 0) -#define MIX_CIPHER_WPA2_AES_ON(x) (((x) & 0x01) != 0) - -#ifndef ROUND_UP -#define ROUND_UP(__x, __y) \ - (((ULONG)((__x)+((__y)-1))) & ((ULONG)~((__y)-1))) -#endif - -#define SET_UINT16_TO_ARRARY(_V, _LEN) \ -{ \ - _V[0] = (_LEN & 0xFF00) >> 8; \ - _V[1] = (_LEN & 0xFF); \ -} - -#define INC_UINT16_TO_ARRARY(_V, _LEN) \ -{ \ - UINT16 var_len; \ - \ - var_len = (_V[0]<<8) | (_V[1]); \ - var_len += _LEN; \ - \ - _V[0] = (var_len & 0xFF00) >> 8; \ - _V[1] = (var_len & 0xFF); \ -} - -#define CONV_ARRARY_TO_UINT16(_V) ((_V[0]<<8) | (_V[1])) - - -#define ADD_ONE_To_64BIT_VAR(_V) \ -{ \ - UCHAR cnt = LEN_KEY_DESC_REPLAY; \ - do \ - { \ - cnt--; \ - _V[cnt]++; \ - if (cnt == 0) \ - break; \ - }while (_V[cnt] == 0); \ -} - -#define IS_WPA_CAPABILITY(a) (((a) >= Ndis802_11AuthModeWPA) && ((a) <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) - -// EAPOL Key Information definition within Key descriptor format -typedef struct PACKED _KEY_INFO -{ -#ifdef RT_BIG_ENDIAN - UCHAR KeyAck:1; - UCHAR Install:1; - UCHAR KeyIndex:2; - UCHAR KeyType:1; - UCHAR KeyDescVer:3; - UCHAR Rsvd:3; - UCHAR EKD_DL:1; // EKD for AP; DL for STA - UCHAR Request:1; - UCHAR Error:1; - UCHAR Secure:1; - UCHAR KeyMic:1; -#else - UCHAR KeyMic:1; - UCHAR Secure:1; - UCHAR Error:1; - UCHAR Request:1; - UCHAR EKD_DL:1; // EKD for AP; DL for STA - UCHAR Rsvd:3; - UCHAR KeyDescVer:3; - UCHAR KeyType:1; - UCHAR KeyIndex:2; - UCHAR Install:1; - UCHAR KeyAck:1; -#endif -} KEY_INFO, *PKEY_INFO; - -// EAPOL Key descriptor format -typedef struct PACKED _KEY_DESCRIPTER -{ - UCHAR Type; - KEY_INFO KeyInfo; - UCHAR KeyLength[2]; - UCHAR ReplayCounter[LEN_KEY_DESC_REPLAY]; - UCHAR KeyNonce[LEN_KEY_DESC_NONCE]; - UCHAR KeyIv[LEN_KEY_DESC_IV]; - UCHAR KeyRsc[LEN_KEY_DESC_RSC]; - UCHAR KeyId[LEN_KEY_DESC_ID]; - UCHAR KeyMic[LEN_KEY_DESC_MIC]; - UCHAR KeyDataLen[2]; - UCHAR KeyData[MAX_LEN_OF_RSNIE]; -} KEY_DESCRIPTER, *PKEY_DESCRIPTER; - -typedef struct PACKED _EAPOL_PACKET -{ - UCHAR ProVer; - UCHAR ProType; - UCHAR Body_Len[2]; - KEY_DESCRIPTER KeyDesc; -} EAPOL_PACKET, *PEAPOL_PACKET; - -//802.11i D10 page 83 -typedef struct PACKED _GTK_ENCAP -{ -#ifndef RT_BIG_ENDIAN - UCHAR Kid:2; - UCHAR tx:1; - UCHAR rsv:5; - UCHAR rsv1; -#else - UCHAR rsv:5; - UCHAR tx:1; - UCHAR Kid:2; - UCHAR rsv1; -#endif - UCHAR GTK[TKIP_GTK_LENGTH]; -} GTK_ENCAP, *PGTK_ENCAP; - -typedef struct PACKED _KDE_ENCAP -{ - UCHAR Type; - UCHAR Len; - UCHAR OUI[3]; - UCHAR DataType; - GTK_ENCAP GTKEncap; -} KDE_ENCAP, *PKDE_ENCAP; - -// For WPA1 -typedef struct PACKED _RSNIE { - UCHAR oui[4]; - USHORT version; - UCHAR mcast[4]; - USHORT ucount; - struct PACKED { - UCHAR oui[4]; - }ucast[1]; -} RSNIE, *PRSNIE; - -// For WPA2 -typedef struct PACKED _RSNIE2 { - USHORT version; - UCHAR mcast[4]; - USHORT ucount; - struct PACKED { - UCHAR oui[4]; - }ucast[1]; -} RSNIE2, *PRSNIE2; - -// AKM Suite -typedef struct PACKED _RSNIE_AUTH { - USHORT acount; - struct PACKED { - UCHAR oui[4]; - }auth[1]; -} RSNIE_AUTH,*PRSNIE_AUTH; - -typedef union PACKED _RSN_CAPABILITIES { - struct PACKED { -#ifdef RT_BIG_ENDIAN - USHORT Rsvd:10; - USHORT GTKSA_R_Counter:2; - USHORT PTKSA_R_Counter:2; - USHORT No_Pairwise:1; - USHORT PreAuth:1; -#else - USHORT PreAuth:1; - USHORT No_Pairwise:1; - USHORT PTKSA_R_Counter:2; - USHORT GTKSA_R_Counter:2; - USHORT Rsvd:10; -#endif - } field; - USHORT word; -} RSN_CAPABILITIES, *PRSN_CAPABILITIES; - -typedef struct PACKED _EAP_HDR { - UCHAR ProVer; - UCHAR ProType; - UCHAR Body_Len[2]; - UCHAR code; - UCHAR identifier; - UCHAR length[2]; // including code and identifier, followed by length-2 octets of data -} EAP_HDR, *PEAP_HDR; - -// For supplicant state machine states. 802.11i Draft 4.1, p. 97 -// We simplified it -typedef enum _WpaState -{ - SS_NOTUSE, // 0 - SS_START, // 1 - SS_WAIT_MSG_3, // 2 - SS_WAIT_GROUP, // 3 - SS_FINISH, // 4 - SS_KEYUPDATE, // 5 -} WPA_STATE; - -// -// The definition of the cipher combination -// -// bit3 bit2 bit1 bit0 -// +------------+------------+ -// | WPA | WPA2 | -// +------+-----+------+-----+ -// | TKIP | AES | TKIP | AES | -// | 0 | 1 | 1 | 0 | -> 0x06 -// | 0 | 1 | 1 | 1 | -> 0x07 -// | 1 | 0 | 0 | 1 | -> 0x09 -// | 1 | 0 | 1 | 1 | -> 0x0B -// | 1 | 1 | 0 | 1 | -> 0x0D -// | 1 | 1 | 1 | 0 | -> 0x0E -// | 1 | 1 | 1 | 1 | -> 0x0F -// +------+-----+------+-----+ -// -typedef enum _WpaMixPairCipher -{ - MIX_CIPHER_NOTUSE = 0x00, - WPA_NONE_WPA2_TKIPAES = 0x03, // WPA2-TKIPAES - WPA_AES_WPA2_TKIP = 0x06, - WPA_AES_WPA2_TKIPAES = 0x07, - WPA_TKIP_WPA2_AES = 0x09, - WPA_TKIP_WPA2_TKIPAES = 0x0B, - WPA_TKIPAES_WPA2_NONE = 0x0C, // WPA-TKIPAES - WPA_TKIPAES_WPA2_AES = 0x0D, - WPA_TKIPAES_WPA2_TKIP = 0x0E, - WPA_TKIPAES_WPA2_TKIPAES = 0x0F, -} WPA_MIX_PAIR_CIPHER; - -typedef struct PACKED _RSN_IE_HEADER_STRUCT { - UCHAR Eid; - UCHAR Length; - USHORT Version; // Little endian format -} RSN_IE_HEADER_STRUCT, *PRSN_IE_HEADER_STRUCT; - -// Cipher suite selector types -typedef struct PACKED _CIPHER_SUITE_STRUCT { - UCHAR Oui[3]; - UCHAR Type; -} CIPHER_SUITE_STRUCT, *PCIPHER_SUITE_STRUCT; - -// Authentication and Key Management suite selector -typedef struct PACKED _AKM_SUITE_STRUCT { - UCHAR Oui[3]; - UCHAR Type; -} AKM_SUITE_STRUCT, *PAKM_SUITE_STRUCT; - -// RSN capability -typedef struct PACKED _RSN_CAPABILITY { - USHORT Rsv:10; - USHORT GTKSAReplayCnt:2; - USHORT PTKSAReplayCnt:2; - USHORT NoPairwise:1; - USHORT PreAuth:1; -} RSN_CAPABILITY, *PRSN_CAPABILITY; - - -/*======================================== - The prototype is defined in cmm_wpa.c - ========================================*/ -BOOLEAN WpaMsgTypeSubst( - IN UCHAR EAPType, - OUT INT *MsgType); - -VOID PRF( - IN UCHAR *key, - IN INT key_len, - IN UCHAR *prefix, - IN INT prefix_len, - IN UCHAR *data, - IN INT data_len, - OUT UCHAR *output, - IN INT len); - -int PasswordHash( - char *password, - unsigned char *ssid, - int ssidlength, - unsigned char *output); - -PUINT8 GetSuiteFromRSNIE( - IN PUINT8 rsnie, - IN UINT rsnie_len, - IN UINT8 type, - OUT UINT8 *count); - -VOID WpaShowAllsuite( - IN PUINT8 rsnie, - IN UINT rsnie_len); - -VOID RTMPInsertRSNIE( - IN PUCHAR pFrameBuf, - OUT PULONG pFrameLen, - IN PUINT8 rsnie_ptr, - IN UINT8 rsnie_len, - IN PUINT8 pmkid_ptr, - IN UINT8 pmkid_len); - - -#endif diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig index 3211dd3765a094b43ad876397962841e9fa96877..e24a6f7a0d859691534210f5cab918918ec089ca 100644 --- a/drivers/staging/rtl8187se/Kconfig +++ b/drivers/staging/rtl8187se/Kconfig @@ -1,7 +1,8 @@ -config RTL8187SE +config R8187SE tristate "RealTek RTL8187SE Wireless LAN NIC driver" depends on PCI && WLAN select WIRELESS_EXT select WEXT_PRIV default N ---help--- + If built as a module, it will be called r8187se.ko. diff --git a/drivers/staging/rtl8187se/Makefile b/drivers/staging/rtl8187se/Makefile index ac35cffe5d4a0e6abe6f3aec7882ea3bdb197d60..b395acf5a38e5a9ac29025633c694167e5b768c0 100644 --- a/drivers/staging/rtl8187se/Makefile +++ b/drivers/staging/rtl8187se/Makefile @@ -16,7 +16,7 @@ EXTRA_CFLAGS += -DENABLE_LPS #EXTRA_CFLAGS += -mhard-float -DCONFIG_FORCE_HARD_FLOAT=y -rtl8187se-objs := \ +r8187se-objs := \ r8180_core.o \ r8180_93cx6.o \ r8180_wx.o \ @@ -35,5 +35,5 @@ rtl8187se-objs := \ ieee80211/ieee80211_crypt_ccmp.o \ ieee80211/ieee80211_crypt_wep.o -obj-$(CONFIG_RTL8187SE) += rtl8187se.o +obj-$(CONFIG_R8187SE) += r8187se.o diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c index 5e2e79b1e341aa4380548dd0c778d9b8b24e4316..f882dd8cf9b56ec38ea12cff7d315190cf62aeff 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index 334e4c7ec61bda83a9a80792a5f95f4e6db5dade..1fe19c39d702000a95652f0dbeed42e08506bac6 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -1837,7 +1837,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, if (((ieee->current_network.wmm_info^info_element->data[6])& \ 0x0f)||(!ieee->init_wmmparam_flag)) { - //refresh paramete element for current network + // refresh parameter element for current network // update the register parameter for hardware ieee->init_wmmparam_flag = 1; queue_work(ieee->wq, &ieee->wmm_param_update_wq); @@ -1958,10 +1958,10 @@ associate_complete: * care of the ieee802.11 fragmentation. * So the driver receives a fragment per time and might * call the stop function when it want without take care - * to have enought room to TX an entire packet. + * to have enough room to TX an entire packet. * This might be useful if each fragment need it's own * descriptor, thus just keep a total free memory > than - * the max fragmentation treshold is not enought.. If the + * the max fragmentation threshold is not enough.. If the * ieee802.11 stack passed a TXB struct then you needed * to keep N free descriptors where * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c index e2945db617952968c0d8fffffe73c353eef1c1d6..dde1f2e0cf32c4b1eb7d2634e0ce410938088ca4 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c index a08b97a09512a92c4544d1cfe22983945b1e7464..6aad48fe2e183f4b92ed7b0798e9f79fed2e9bb7 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c @@ -30,7 +30,6 @@ ******************************************************************************/ #include -#include #include #include diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h index 35ed60be891a09f81603991ee09b3489a6cf1d5b..ce828885b64f755f7d69914b2710a886a1dfe1f3 100644 --- a/drivers/staging/rtl8187se/r8180.h +++ b/drivers/staging/rtl8187se/r8180.h @@ -77,21 +77,6 @@ typedef enum _WIRELESS_MODE { WIRELESS_MODE_AUTO = 0x08, } WIRELESS_MODE; -typedef enum _VERSION_8185{ - // RTL8185 - VERSION_8185_UNKNOWN, - VERSION_8185_C, // C-cut - VERSION_8185_D, // D-cut - // RTL8185B - VERSION_8185B_B, // B-cut - VERSION_8185B_D, // D-cut - VERSION_8185B_E, // E-cut - //RTL8187S-PCIE - VERSION_8187S_B, // B-cut - VERSION_8187S_C, // C-cut - VERSION_8187S_D, // D-cut - -}VERSION_8185,*PVERSION_8185; typedef struct ChnlAccessSetting { u16 SIFS_Timer; u16 DIFS_Timer; @@ -341,11 +326,8 @@ typedef struct r8180_priv int irq; struct ieee80211_device *ieee80211; - short card_8185; /* O: rtl8180, 1:rtl8185 V B/C, 2:rtl8185 V D, 3:rtl8185B */ - short card_8185_Bversion; /* if TCR reports card V B/C this discriminates */ short phy_ver; /* meaningful for rtl8225 1:A 2:B 3:C */ short enable_gpio0; - enum card_type {PCI,MINIPCI,CARDBUS,USB/*rtl8187*/}card_type; short hw_plcp_len; short plcp_preamble_mode; // 0:auto 1:short 2:long @@ -599,7 +581,7 @@ typedef struct r8180_priv u8 RSSI; char RxPower; u8 InitialGain; - //For adjust Dig Threshhold during Legacy/Leisure Power Save Mode + //For adjust Dig Threshold during Legacy/Leisure Power Save Mode u32 DozePeriodInPast2Sec; // Don't access BB/RF under disable PLL situation. u8 InitialGainBackUp; diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index 53e654d0d4fa43aa284ecea15570c1bc376e360c..57c62b0a402fd08ba4f2f5d8bcce2115ddef960e 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -886,8 +886,6 @@ void rtl8180_rx_enable(struct net_device *dev) rxconf = rxconf | (1<card_8185 == 0) - rxconf = rxconf | (1<ieee80211->iw_mode == IW_MODE_MONITOR){ @@ -910,9 +908,6 @@ void rtl8180_rx_enable(struct net_device *dev) rxconf = rxconf &~ RCR_CS_MASK; - if (!priv->card_8185) - rxconf |= (priv->rcr_csense<card_8185) { - byte = read_nic_byte(dev,CW_CONF); - byte &= ~(1<card_8185) - txconf = txconf &~ (1<retry_rts<card_8185) { - if (priv->hw_plcp_len) - txconf = txconf &~ TCR_PLCP_LEN; - else - txconf = txconf | TCR_PLCP_LEN; - } else - txconf = txconf &~ TCR_SAT; + if (priv->hw_plcp_len) + txconf = txconf & ~TCR_PLCP_LEN; + else + txconf = txconf | TCR_PLCP_LEN; txconf = txconf &~ TCR_MXDMA_MASK; txconf = txconf | (TCR_MXDMA_2048<SignalQuality = quality; - if(!priv->card_8185) - printk("check your card type\n"); stats.signal = (u8)quality;//priv->wstats.qual.level = priv->SignalStrength; stats.signalstrength = RXAGC; @@ -1848,7 +1829,7 @@ void rtl8180_rx(struct net_device *dev) sizeof(u8), PCI_DMA_FROMDEVICE); -drop: // this is used when we have not enought mem +drop: // this is used when we have not enough mem /* restore the descriptor */ *(priv->rxringtail+2)=priv->rxbuffer->dma; *(priv->rxringtail)=*(priv->rxringtail) &~ 0xfff; @@ -1919,8 +1900,8 @@ rate) /* * This function doesn't require lock because we make * sure it's called with the tx_lock already acquired. - * this come from the kernel's hard_xmit callback (trought - * the ieee stack, or from the try_wake_queue (again trought + * this come from the kernel's hard_xmit callback (through + * the ieee stack, or from the try_wake_queue (again through * the ieee stack. */ priority = AC2Q(skb->priority); @@ -2221,10 +2202,8 @@ short rtl8180_tx(struct net_device *dev, u8* txbuf, int len, int priority, *(tail+6) = 0; *(tail+7) = 0; - if(priv->card_8185){ - //FIXME: this should be triggered by HW encryption parameters. - *tail |= (1<<15); //no encrypt - } + /*FIXME: this should be triggered by HW encryption parameters.*/ + *tail |= (1<<15); /* no encrypt */ if(remain==len && !descfrag) { ownbit_flag = false; //added by david woo,2007.12.14 @@ -2266,7 +2245,7 @@ short rtl8180_tx(struct net_device *dev, u8* txbuf, int len, int priority, /* hw_plcp_len is not used for rtl8180 chip */ /* FIXME */ - if(priv->card_8185 == 0 || !priv->hw_plcp_len){ + if (!priv->hw_plcp_len) { duration = rtl8180_len2duration(len, rate, &ext); *(tail+1) = *(tail+1) | ((duration & 0x7fff)<<16); if(ext) *(tail+1) = *(tail+1) |(1<<31); //plcp length extension @@ -2355,8 +2334,7 @@ void rtl8180_link_change(struct net_device *dev) rtl8180_set_mode(dev, EPROM_CMD_NORMAL); - if(priv->card_8185) - rtl8180_set_chan(dev, priv->chan); + rtl8180_set_chan(dev, priv->chan); } void rtl8180_rq_tx_ack(struct net_device *dev){ @@ -2702,8 +2680,6 @@ short rtl8180_init(struct net_device *dev) struct r8180_priv *priv = ieee80211_priv(dev); u16 word; u16 version; - u8 hw_version; - //u8 config3; u32 usValue; u16 tmpu16; int i, j; @@ -2928,50 +2904,13 @@ short rtl8180_init(struct net_device *dev) priv->InitialGain = 6; - hw_version =( read_nic_dword(dev, TCR) & TCR_HWVERID_MASK)>>TCR_HWVERID_SHIFT; - - switch (hw_version){ - case HW_VERID_R8185B_B: - priv->card_8185 = VERSION_8187S_C; - DMESG("MAC controller is a RTL8187SE b/g"); - priv->phy_ver = 2; - break; - case HW_VERID_R8185_ABC: - DMESG("MAC controller is a RTL8185 b/g"); - priv->card_8185 = 1; - /* you should not find a card with 8225 PHY ver < C*/ - priv->phy_ver = 2; - break; - case HW_VERID_R8185_D: - DMESG("MAC controller is a RTL8185 b/g (V. D)"); - priv->card_8185 = 2; - /* you should not find a card with 8225 PHY ver < C*/ - priv->phy_ver = 2; - break; - case HW_VERID_R8180_ABCD: - DMESG("MAC controller is a RTL8180"); - priv->card_8185 = 0; - break; - case HW_VERID_R8180_F: - DMESG("MAC controller is a RTL8180 (v. F)"); - priv->card_8185 = 0; - break; - default: - DMESGW("MAC chip not recognized: version %x. Assuming RTL8180",hw_version); - priv->card_8185 = 0; - break; - } + DMESG("MAC controller is a RTL8187SE b/g"); + priv->phy_ver = 2; - if(priv->card_8185){ - priv->ieee80211->modulation |= IEEE80211_OFDM_MODULATION; - priv->ieee80211->short_slot = 1; - } - /* you should not found any 8185 Ver B Card */ - priv->card_8185_Bversion = 0; + priv->ieee80211->modulation |= IEEE80211_OFDM_MODULATION; + priv->ieee80211->short_slot = 1; // just for sync 85 - priv->card_type = PCI; - DMESG("This is a PCI NIC"); priv->enable_gpio0 = 0; usValue = eprom_read(dev, EEPROM_SW_REVD_OFFSET); @@ -3026,12 +2965,10 @@ short rtl8180_init(struct net_device *dev) priv->chtxpwr[i]=word & 0xff; priv->chtxpwr[i+1]=(word & 0xff00)>>8; } - if(priv->card_8185){ - for(i=1,j=0; i<14; i+=2,j++){ - word = eprom_read(dev,EPROM_TXPW_OFDM_CH1_2 + j); - priv->chtxpwr_ofdm[i]=word & 0xff; - priv->chtxpwr_ofdm[i+1]=(word & 0xff00)>>8; - } + for (i = 1, j = 0; i < 14; i += 2, j++) { + word = eprom_read(dev, EPROM_TXPW_OFDM_CH1_2 + j); + priv->chtxpwr_ofdm[i] = word & 0xff; + priv->chtxpwr_ofdm[i+1] = (word & 0xff00)>>8; } //3Read crystal calibtration and thermal meter indication on 87SE. @@ -3057,37 +2994,11 @@ short rtl8180_init(struct net_device *dev) version = eprom_read(dev,EPROM_VERSION); DMESG("EEPROM version %x",version); - if( (!priv->card_8185) && version < 0x0101){ - DMESG ("EEPROM version too old, assuming defaults"); - DMESG ("If you see this message *plase* send your \ -DMESG output to andreamrl@tiscali.it THANKS"); - priv->digphy=1; - priv->antb=0; - priv->diversity=1; - priv->cs_treshold=0xc; - priv->rcr_csense=1; - priv->rf_chip=RFCHIPID_PHILIPS; - }else{ - if(!priv->card_8185){ - u8 rfparam = eprom_read(dev,RF_PARAM); - DMESG("RfParam: %x",rfparam); + priv->rcr_csense = 3; - priv->digphy = rfparam & (1<antb = rfparam & (1<cs_treshold = (eprom_read(dev, ENERGY_TRESHOLD) & 0xff00) >> 8; - priv->rcr_csense = (rfparam & RF_PARAM_CARRIERSENSE_MASK) >> - RF_PARAM_CARRIERSENSE_SHIFT; - - priv->diversity = - (read_nic_byte(dev,CONFIG2)&(1<rcr_csense = 3; - } - - priv->cs_treshold = (eprom_read(dev,ENERGY_TRESHOLD)&0xff00) >>8; - - priv->rf_chip = 0xff & eprom_read(dev,RFCHIPID); - } + priv->rf_chip = 0xff & eprom_read(dev, RFCHIPID); priv->rf_chip = RF_ZEBRA4; priv->rf_sleep = rtl8225z4_rf_sleep; @@ -3099,19 +3010,6 @@ DMESG output to andreamrl@tiscali.it THANKS"); priv->rf_set_chan = rtl8225z2_rf_set_chan; priv->rf_set_sens = NULL; - if(!priv->card_8185){ - if(priv->antb) - DMESG ("Antenna B is default antenna"); - else - DMESG ("Antenna A is default antenna"); - - if(priv->diversity) - DMESG ("Antenna diversity is enabled"); - else - DMESG("Antenna diversity is disabled"); - - DMESG("Carrier sense %d",priv->rcr_csense); - } if (0!=alloc_rx_desc_ring(dev, priv->rxbuffersize, priv->rxringcount)) return -ENOMEM; @@ -3144,17 +3042,6 @@ DMESG output to andreamrl@tiscali.it THANKS"); TX_BEACON_RING_ADDR)) return -ENOMEM; - if(!priv->card_8185){ - if(read_nic_byte(dev, CONFIG0) & (1<irq, (void *)rtl8180_interrupt, IRQF_SHARED, dev->name, dev)){ #else @@ -3172,17 +3059,6 @@ DMESG output to andreamrl@tiscali.it THANKS"); void rtl8180_no_hw_wep(struct net_device *dev) { - struct r8180_priv *priv = ieee80211_priv(dev); - - if (!priv->card_8185) { - u8 security; - - security = read_nic_byte(dev, SECURITY); - security &=~(1<card_type == CARDBUS ){ - config3=read_nic_byte(dev, CONFIG3); - write_nic_byte(dev,CONFIG3,config3 | CONFIG3_FuncRegEn); - write_nic_word(dev,FEMR, FEMR_INTR | FEMR_WKUP | FEMR_GWAKE | - read_nic_word(dev, FEMR)); - } rtl8180_set_mode(dev, EPROM_CMD_CONFIG); write_nic_dword(dev, MAC0, ((u32*)dev->dev_addr)[0]); write_nic_word(dev, MAC4, ((u32*)dev->dev_addr)[1] & 0xffff ); @@ -3384,12 +3251,6 @@ void rtl8180_adapter_start(struct net_device *dev) rtl8180_update_msr(dev); - if(!priv->card_8185){ - anaparam = eprom_read(dev,EPROM_ANAPARAM_ADDRLWORD); - anaparam |= eprom_read(dev,EPROM_ANAPARAM_ADDRHWORD)<<16; - - rtl8180_set_anaparam(dev,anaparam); - } /* These might be unnecessary since we do in rx_enable / tx_enable */ fix_rx_fifo(dev); fix_tx_fifo(dev); @@ -3399,61 +3260,34 @@ void rtl8180_adapter_start(struct net_device *dev) /* The following is very strange. seems to be that 1 means test mode, but we need to acknolwledges the nic when a packet is ready - altought we set it to 0 + although we set it to 0 */ write_nic_byte(dev, CONFIG2, read_nic_byte(dev,CONFIG2) &~\ (1<card_8185) - write_nic_byte(dev, + write_nic_byte(dev, CONFIG2, read_nic_byte(dev,CONFIG2)|(1<<4)); rtl8180_set_mode(dev,EPROM_CMD_NORMAL); write_nic_dword(dev,INT_TIMEOUT,0); - if(!priv->card_8185) - { - /* - experimental - this might be needed to calibrate AGC, - anyway it shouldn't hurt - */ - write_nic_byte(dev, CONFIG5, - read_nic_byte(dev, CONFIG5) | (1<card_8185){ - rtl8185_set_rate(dev); - write_nic_byte(dev, RATE_FALLBACK, 0x81); - }else{ - word = read_nic_word(dev, BRSR); - word &= ~BRSR_MBR; - word &= ~BRSR_BPLCP; - word |= ieeerate2rtlrate(priv->ieee80211->basic_rate); - word |= 0x0f; - write_nic_word(dev, BRSR, word); - } + rtl8185_set_rate(dev); + write_nic_byte(dev, RATE_FALLBACK, 0x81); - if(priv->card_8185){ - write_nic_byte(dev, GP_ENABLE,read_nic_byte(dev, GP_ENABLE) & ~(1<<6)); + write_nic_byte(dev, GP_ENABLE, read_nic_byte(dev, GP_ENABLE) & ~(1<<6)); - //FIXME cfg 3 ClkRun enable - isn't it ReadOnly ? - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - write_nic_byte(dev,CONFIG3, read_nic_byte(dev, CONFIG3) - | (1 << CONFIG3_CLKRUN_SHIFT)); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); - } + /*FIXME cfg 3 ClkRun enable - isn't it ReadOnly ? */ + rtl8180_set_mode(dev, EPROM_CMD_CONFIG); + write_nic_byte(dev, CONFIG3, read_nic_byte(dev, CONFIG3) + | (1 << CONFIG3_CLKRUN_SHIFT)); + rtl8180_set_mode(dev, EPROM_CMD_NORMAL); priv->rf_init(dev); @@ -4144,7 +3978,7 @@ void rtl8180_tx_isr(struct net_device *dev, int pri,short error) } /* we check all the descriptors between the head and the nic, - * but not the currenly pointed by the nic (the next to be txed) + * but not the currently pointed by the nic (the next to be txed) * and the previous of the pointed (might be in process ??) */ offs = (nic - nicbegin); diff --git a/drivers/staging/rtl8187se/r8180_dm.c b/drivers/staging/rtl8187se/r8180_dm.c index b6eeeeccff9e2f708fdb7ab71f58fd7e1395c85b..cbca58db85e18bd70fd530e08a6d22f1c878c55f 100644 --- a/drivers/staging/rtl8187se/r8180_dm.c +++ b/drivers/staging/rtl8187se/r8180_dm.c @@ -36,7 +36,7 @@ bool CheckHighPower(struct net_device *dev) // // Note: // The reason why we udpate Tx power level here instead of DoRxHighPower() -// is the number of IO to change Tx power is much more than chane TR switch +// is the number of IO to change Tx power is much more than channel TR switch // and they are related to OFDM and MAC registers. // So, we don't want to update it so frequently in per-Rx packet base. // @@ -197,7 +197,6 @@ DIG_Zebra( { // Advised from SD3 DZ priv->InitialGain = 4; // In 87B, m74dBm means State 4 (m82dBm) } - //if(pHalData->VersionID != VERSION_8187B_B) { // Advised from SD3 DZ OfdmFA1 = 0x20; } @@ -1326,7 +1325,7 @@ SetAntenna8185( break; default: - printk("SetAntenna8185: unkown RFChipID(%d)\n", priv->rf_chip); + printk("SetAntenna8185: unknown RFChipID(%d)\n", priv->rf_chip); break; } break; @@ -1346,13 +1345,13 @@ SetAntenna8185( break; default: - printk("SetAntenna8185: unkown RFChipID(%d)\n", priv->rf_chip); + printk("SetAntenna8185: unknown RFChipID(%d)\n", priv->rf_chip); break; } break; default: - printk("SetAntenna8185: unkown u1bAntennaIndex(%d)\n", u1bAntennaIndex); + printk("SetAntenna8185: unknown u1bAntennaIndex(%d)\n", u1bAntennaIndex); break; } @@ -1448,7 +1447,7 @@ SwAntennaDiversity( priv->bAdSwitchedChecking = false; - // Adjust Rx signal strength threashold. + // Adjust Rx signal strength threshold. priv->AdRxSsThreshold = (priv->AdRxSignalStrength + priv->AdRxSsBeforeSwitched) / 2; priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ? @@ -1562,7 +1561,7 @@ SwAntennaDiversity( // priv->AdRxSignalStrength, priv->AdRxSsThreshold); priv->bAdSwitchedChecking = false; - // Increase Rx signal strength threashold if necessary. + // Increase Rx signal strength threshold if necessary. if( (priv->AdRxSignalStrength > (priv->AdRxSsThreshold + 10)) && // Signal is much stronger than current threshold priv->AdRxSsThreshold <= priv->AdMaxRxSsThreshold) // Current threhold is not yet reach upper limit. { diff --git a/drivers/staging/rtl8187se/r8180_rtl8225z2.c b/drivers/staging/rtl8187se/r8180_rtl8225z2.c index b648751cdaa37a31d36a3ee8c75fa8628074ed17..afe10f0b75a80bb8bea3c50bb721e9468b79a9ee 100644 --- a/drivers/staging/rtl8187se/r8180_rtl8225z2.c +++ b/drivers/staging/rtl8187se/r8180_rtl8225z2.c @@ -23,7 +23,6 @@ static void write_rtl8225(struct net_device *dev, u8 adr, u16 data) u16 out, select; u8 bit; u32 bangdata = (data << 4) | (adr & 0xf); - struct r8180_priv *priv = ieee80211_priv(dev); out = read_nic_word(dev, RFPinsOutput) & 0xfff3; @@ -33,7 +32,7 @@ static void write_rtl8225(struct net_device *dev, u8 adr, u16 data) select = read_nic_word(dev, RFPinsSelect); write_nic_word(dev, RFPinsSelect, select | 0x7 | - ((priv->card_type == USB) ? 0 : SW_CONTROL_GPIO)); + SW_CONTROL_GPIO); force_pci_posting(dev); udelay(10); @@ -71,16 +70,11 @@ static void write_rtl8225(struct net_device *dev, u8 adr, u16 data) force_pci_posting(dev); udelay(10); - write_nic_word(dev, RFPinsOutput, out | - ((priv->card_type == USB) ? 4 : BB_HOST_BANG_EN)); + write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN); - write_nic_word(dev, RFPinsSelect, select | - ((priv->card_type == USB) ? 0 : SW_CONTROL_GPIO)); + write_nic_word(dev, RFPinsSelect, select | SW_CONTROL_GPIO); - if (priv->card_type == USB) - mdelay(2); - else - rtl8185_rf_pins_enable(dev); + rtl8185_rf_pins_enable(dev); } static const u16 rtl8225bcd_rxgain[] = { @@ -174,15 +168,9 @@ static void rtl8225_SetTXPowerLevel(struct net_device *dev, short ch) u8 cck_power_level = 0xff & priv->chtxpwr[ch]; u8 ofdm_power_level = 0xff & priv->chtxpwr_ofdm[ch]; - if (priv->card_type == USB) { - max_cck_power_level = 11; - max_ofdm_power_level = 25; - min_ofdm_power_level = 10; - } else { - max_cck_power_level = 35; - max_ofdm_power_level = 35; - min_ofdm_power_level = 0; - } + max_cck_power_level = 35; + max_ofdm_power_level = 35; + min_ofdm_power_level = 0; if (cck_power_level > max_cck_power_level) cck_power_level = max_cck_power_level; @@ -445,30 +433,28 @@ s8 DbmToTxPwrIdx(struct r8180_priv *priv, WIRELESS_MODE WirelessMode, * OFDM Power in dBm = Index * 0.5 + 0 * CCK Power in dBm = Index * 0.25 + 13 */ - if (priv->card_8185 >= VERSION_8187S_B) { - s32 tmp = 0; - - if (WirelessMode == WIRELESS_MODE_G) { - bUseDefault = false; - tmp = (2 * PowerInDbm); - - if (tmp < 0) - TxPwrIdx = 0; - else if (tmp > 40) /* 40 means 20 dBm. */ - TxPwrIdx = 40; - else - TxPwrIdx = (s8)tmp; - } else if (WirelessMode == WIRELESS_MODE_B) { - bUseDefault = false; - tmp = (4 * PowerInDbm) - 52; - - if(tmp < 0) - TxPwrIdx = 0; - else if (tmp > 28) /* 28 means 20 dBm. */ - TxPwrIdx = 28; - else - TxPwrIdx = (s8)tmp; - } + s32 tmp = 0; + + if (WirelessMode == WIRELESS_MODE_G) { + bUseDefault = false; + tmp = (2 * PowerInDbm); + + if (tmp < 0) + TxPwrIdx = 0; + else if (tmp > 40) /* 40 means 20 dBm. */ + TxPwrIdx = 40; + else + TxPwrIdx = (s8)tmp; + } else if (WirelessMode == WIRELESS_MODE_B) { + bUseDefault = false; + tmp = (4 * PowerInDbm) - 52; + + if (tmp < 0) + TxPwrIdx = 0; + else if (tmp > 28) /* 28 means 20 dBm. */ + TxPwrIdx = 28; + else + TxPwrIdx = (s8)tmp; } /* @@ -631,8 +617,7 @@ void rtl8225z2_rf_init(struct net_device *dev) priv->chan = channel; - if (priv->card_type != USB) - rtl8225_host_pci_init(dev); + rtl8225_host_pci_init(dev); write_nic_dword(dev, RF_TIMING, 0x000a8008); @@ -655,7 +640,7 @@ void rtl8225z2_rf_init(struct net_device *dev) write_rtl8225(dev, 0x4, 0x8c3); mdelay(1); write_rtl8225(dev, 0x5, 0xc72); mdelay(1); write_rtl8225(dev, 0x6, 0xe6); mdelay(1); - write_rtl8225(dev, 0x7, ((priv->card_type == USB)? 0x82a : rtl8225_chan[channel])); mdelay(1); + write_rtl8225(dev, 0x7, rtl8225_chan[channel]); mdelay(1); write_rtl8225(dev, 0x8, 0x3f); mdelay(1); write_rtl8225(dev, 0x9, 0x335); mdelay(1); write_rtl8225(dev, 0xa, 0x9d4); mdelay(1); @@ -681,13 +666,6 @@ void rtl8225z2_rf_init(struct net_device *dev) write_rtl8225(dev, 0x2, 0xc4d); - if (priv->card_type == USB) { - mdelay(200); - - write_rtl8225(dev, 0x2, 0x44d); - mdelay(100); - } - /* FIXME!! rtl8187 we have to check if calibrarion * is successful and eventually cal. again (repeat * the two write on reg 2) @@ -707,9 +685,6 @@ void rtl8225z2_rf_init(struct net_device *dev) write_rtl8225(dev, 0x0, 0x2bf); - if (priv->card_type != USB) - rtl8185_rf_pins_enable(dev); - for (i = 0; i < 128; i++) { data = rtl8225_agc[i]; @@ -726,7 +701,7 @@ void rtl8225z2_rf_init(struct net_device *dev) write_phy_ofdm(dev, 0x00, 0x01); mdelay(1); write_phy_ofdm(dev, 0x01, 0x02); mdelay(1); - write_phy_ofdm(dev, 0x02, ((priv->card_type == USB) ? 0x42 : 0x62)); mdelay(1); + write_phy_ofdm(dev, 0x02, 0x62); mdelay(1); write_phy_ofdm(dev, 0x03, 0x00); mdelay(1); write_phy_ofdm(dev, 0x04, 0x00); mdelay(1); write_phy_ofdm(dev, 0x05, 0x00); mdelay(1); @@ -774,7 +749,7 @@ void rtl8225z2_rf_init(struct net_device *dev) write_phy_cck(dev, 0x6, 0xfc); mdelay(1); write_phy_cck(dev, 0x7, 0x78); mdelay(1); write_phy_cck(dev, 0x8, 0x2e); mdelay(1); - write_phy_cck(dev, 0x10, ((priv->card_type == USB) ? 0x9b: 0x93)); mdelay(1); + write_phy_cck(dev, 0x10, 0x93); mdelay(1); write_phy_cck(dev, 0x11, 0x88); mdelay(1); write_phy_cck(dev, 0x12, 0x47); mdelay(1); write_phy_cck(dev, 0x13, 0xd0); @@ -808,12 +783,8 @@ void rtl8225z2_rf_init(struct net_device *dev) /* switch to high-speed 3-wire * last digit. 2 for both cck and ofdm */ - if (priv->card_type == USB) - write_nic_dword(dev, 0x94, 0x3dc00002); - else { - write_nic_dword(dev, 0x94, 0x15c00002); - rtl8185_rf_pins_enable(dev); - } + write_nic_dword(dev, 0x94, 0x15c00002); + rtl8185_rf_pins_enable(dev); rtl8225_rf_set_chan(dev, priv->chan); } @@ -1058,7 +1029,7 @@ bool SetZebraRFPowerState8185(struct net_device *dev, break; default: bResult = false; - printk("SetZebraRFPowerState8185(): unknow state to set: 0x%X!!!\n", eRFPowerState); + printk("SetZebraRFPowerState8185(): unknown state to set: 0x%X!!!\n", eRFPowerState); break; } break; diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c index 766892e31f52196ed2c914c47932c392c34f1d9e..536cb6e8e7966ea12021c0c2da969e99f3409d04 100644 --- a/drivers/staging/rtl8187se/r8180_wx.c +++ b/drivers/staging/rtl8187se/r8180_wx.c @@ -276,7 +276,7 @@ static int rtl8180_wx_get_range(struct net_device *dev, range->max_qual.updated = 7; /* Updated all three */ range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */ - /* TODO: Find real 'good' to 'bad' threshol value for RSSI */ + /* TODO: Find real 'good' to 'bad' threshold value for RSSI */ range->avg_qual.level = 20 + -98; range->avg_qual.noise = 0; range->avg_qual.updated = 7; /* Updated all three */ diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c index cd07059b25b51dc29da0651b769f5e57f743e803..50309f2da9c1b5c644217b38106266034df75cc3 100644 --- a/drivers/staging/rtl8187se/r8185b_init.c +++ b/drivers/staging/rtl8187se/r8185b_init.c @@ -1023,6 +1023,7 @@ ZEBRA_Config_85BASIC_HardCode( u32 addr,data; u32 u4bRegOffset, u4bRegValue, u4bRF23, u4bRF24; u8 u1b24E; + int d_cut = 0; //============================================================================= @@ -1035,8 +1036,10 @@ ZEBRA_Config_85BASIC_HardCode( u4bRF23= RF_ReadReg(dev, 0x08); mdelay(1); u4bRF24= RF_ReadReg(dev, 0x09); mdelay(1); - if (u4bRF23==0x818 && u4bRF24==0x70C && priv->card_8185 == VERSION_8187S_C) - priv->card_8185 = VERSION_8187S_D; + if (u4bRF23 == 0x818 && u4bRF24 == 0x70C) { + d_cut = 1; + printk(KERN_INFO "rtl8187se: card type changed from C- to D-cut\n"); + } // Page0 : reg0-reg15 @@ -1070,18 +1073,9 @@ ZEBRA_Config_85BASIC_HardCode( RF_WriteReg(dev, 0x03, 0x0806); mdelay(1); - if(priv->card_8185 < VERSION_8187S_C) - { - RF_WriteReg(dev, 0x04, 0x03f7); mdelay(1); - RF_WriteReg(dev, 0x05, 0x05ab); mdelay(1); - RF_WriteReg(dev, 0x06, 0x00c1); mdelay(1); - } - else - { - RF_WriteReg(dev, 0x04, 0x03a7); mdelay(1); - RF_WriteReg(dev, 0x05, 0x059b); mdelay(1); - RF_WriteReg(dev, 0x06, 0x0081); mdelay(1); - } + RF_WriteReg(dev, 0x04, 0x03a7); mdelay(1); + RF_WriteReg(dev, 0x05, 0x059b); mdelay(1); + RF_WriteReg(dev, 0x06, 0x0081); mdelay(1); RF_WriteReg(dev, 0x07, 0x01A0); mdelay(1); @@ -1091,14 +1085,11 @@ ZEBRA_Config_85BASIC_HardCode( RF_WriteReg(dev, 0x0a, 0x0001); mdelay(1); RF_WriteReg(dev, 0x0b, 0x0418); mdelay(1); - if(priv->card_8185 == VERSION_8187S_D) - { + if (d_cut) { RF_WriteReg(dev, 0x0c, 0x0fbe); mdelay(1); RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1); RF_WriteReg(dev, 0x0e, 0x0807); mdelay(1); // RX LO buffer - } - else - { + } else { RF_WriteReg(dev, 0x0c, 0x0fbe); mdelay(1); RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1); RF_WriteReg(dev, 0x0e, 0x0806); mdelay(1); // RX LO buffer @@ -2493,8 +2484,8 @@ void rtl8185b_adapter_start(struct net_device *dev) PhyConfig8185(dev); // We assume RegWirelessMode has already been initialized before, - // however, we has to validate the wireless mode here and provide a reasonble - // initialized value if necessary. 2005.01.13, by rcnjko. + // however, we has to validate the wireless mode here and provide a + // reasonable initialized value if necessary. 2005.01.13, by rcnjko. SupportedWirelessMode = GetSupportedWirelessMode8185(dev); if( (ieee->mode != WIRELESS_MODE_B) && (ieee->mode != WIRELESS_MODE_G) && diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c index 12c2a18e1fa2a832803aa1fdc11f661b837bc5ed..2644155737a8e2c4a4535ddd71607f7fda1279b9 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c @@ -164,7 +164,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv) ieee->privacy_invoked = 0; ieee->ieee802_1x = 1; ieee->raw_tx = 0; - //ieee->hwsec_support = 1; //defalt support hw security. //use module_param instead. + //ieee->hwsec_support = 1; //default support hw security. //use module_param instead. ieee->hwsec_active = 0; //disable hwsec, switch it on when necessary. ieee80211_softmac_init(ieee); diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c index eae7c4579a681d8ab4b0f2fb9a4ec98e013c6197..593d228251849692dfded47831551c360ba42da0 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c @@ -2330,10 +2330,10 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, * care of the ieee802.11 fragmentation. * So the driver receives a fragment per time and might * call the stop function when it want without take care - * to have enought room to TX an entire packet. + * to have enough room to TX an entire packet. * This might be useful if each fragment need it's own * descriptor, thus just keep a total free memory > than - * the max fragmentation treshold is not enought.. If the + * the max fragmentation threshold is not enough.. If the * ieee802.11 stack passed a TXB struct then you needed * to keep N free descriptors where * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD diff --git a/drivers/staging/rtl8192e/r8190_rtl8256.c b/drivers/staging/rtl8192e/r8190_rtl8256.c index 0eaee3ad22303b4fdf5a5ae2444361f8a533c6fc..3d67fbb65b9663eccafd445ca2753064d0043e75 100644 --- a/drivers/staging/rtl8192e/r8190_rtl8256.c +++ b/drivers/staging/rtl8192e/r8190_rtl8256.c @@ -629,7 +629,7 @@ SetRFPowerState8190( default: bResult = false; - RT_TRACE(COMP_ERR, "SetRFPowerState8190(): unknow state to set: 0x%X!!!\n", eRFPowerState); + RT_TRACE(COMP_ERR, "SetRFPowerState8190(): unknown state to set: 0x%X!!!\n", eRFPowerState); break; } diff --git a/drivers/staging/rtl8192e/r8192E_core.c b/drivers/staging/rtl8192e/r8192E_core.c index b0802a7aeb5f01b40839e54bffdefaf7c494ecbd..ff8fe7e32a9284d6a6cac344961fd9423867767e 100644 --- a/drivers/staging/rtl8192e/r8192E_core.c +++ b/drivers/staging/rtl8192e/r8192E_core.c @@ -1041,7 +1041,7 @@ static void rtl8192_tx_isr(struct net_device *dev, int prio) tx_desc_819x_pci *entry = &ring->desc[ring->idx]; struct sk_buff *skb; - /* beacon packet will only use the first descriptor defautly, + /* beacon packet will only use the first descriptor defaultly, * and the OWN may not be cleared by the hardware * */ if(prio != BEACON_QUEUE) { @@ -2562,7 +2562,7 @@ static void rtl8192_read_eeprom_info(struct net_device* dev) priv->bTXPowerDataReadFromEEPORM = false; } - // 2007/11/15 MH 8190PCI Default=2T4R, 8192PCIE dafault=1T2R + // 2007/11/15 MH 8190PCI Default=2T4R, 8192PCIE default=1T2R priv->rf_type = RTL819X_DEFAULT_RF_TYPE; if(priv->card_8192_version > VERSION_8190_BD) @@ -3554,7 +3554,7 @@ void rtl8192_prepare_beacon(struct r8192_priv *priv) //spin_lock_irqsave(&priv->tx_lock,flags); /* prepare misc info for the beacon xmit */ tcb_desc->queue_index = BEACON_QUEUE; - /* IBSS does not support HT yet, use 1M defautly */ + /* IBSS does not support HT yet, use 1M defaultly */ tcb_desc->data_rate = 2; tcb_desc->RATRIndex = 7; tcb_desc->bTxDisableRateFallBack = 1; diff --git a/drivers/staging/rtl8192e/r8192E_dm.c b/drivers/staging/rtl8192e/r8192E_dm.c index bf876322dac2130ccd969d548be67ed10104c704..5ffb4f74055bf327652a95cd25c97ec8d4e1f5c9 100644 --- a/drivers/staging/rtl8192e/r8192E_dm.c +++ b/drivers/staging/rtl8192e/r8192E_dm.c @@ -455,7 +455,7 @@ static void dm_check_rate_adaptive(struct net_device * dev) (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M); } - //DbgPrint("[DM] THresh H/L=%d/%d\n\r", RATR.HighRSSIThreshForRA, RATR.LowRSSIThreshForRA); + //DbgPrint("[DM] Thresh H/L=%d/%d\n\r", RATR.HighRSSIThreshForRA, RATR.LowRSSIThreshForRA); if(priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA) { //DbgPrint("[DM] RSSI=%d STA=HIGH\n\r", pHalData->UndecoratedSmoothedPWDB); @@ -571,7 +571,7 @@ static u32 OFDMSwingTable[OFDM_Table_Length] = { 0x5a400169, // 3, +3db 0x50800142, // 4, +2db 0x47c0011f, // 5, +1db - 0x40000100, // 6, +0db ===> default, upper for higher temprature, lower for low temprature + 0x40000100, // 6, +0db ===> default, upper for higher temperature, lower for low temperature 0x390000e4, // 7, -1db 0x32c000cb, // 8, -2db 0x2d4000b5, // 9, -3db @@ -932,14 +932,14 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev) RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d \n", tmpRegA); if(tmpRegA < 3 || tmpRegA > 13) return; - if(tmpRegA >= 12) // if over 12, TP will be bad when high temprature + if(tmpRegA >= 12) // if over 12, TP will be bad when high temperature tmpRegA = 12; RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d \n", tmpRegA); priv->ThermalMeter[0] = ThermalMeterVal; //We use fixed value by Bryant's suggestion priv->ThermalMeter[1] = ThermalMeterVal; //We use fixed value by Bryant's suggestion - //Get current RF-A temprature index - if(priv->ThermalMeter[0] >= (u8)tmpRegA) //lower temprature + //Get current RF-A temperature index + if(priv->ThermalMeter[0] >= (u8)tmpRegA) //lower temperature { tmpOFDMindex = tmpCCK20Mindex = 6+(priv->ThermalMeter[0]-(u8)tmpRegA); tmpCCK40Mindex = tmpCCK20Mindex - 6; @@ -953,7 +953,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev) else { tmpval = ((u8)tmpRegA - priv->ThermalMeter[0]); - if(tmpval >= 6) // higher temprature + if(tmpval >= 6) // higher temperature tmpOFDMindex = tmpCCK20Mindex = 0; // max to +6dB else tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval; @@ -2017,7 +2017,7 @@ static void dm_dig_init(struct net_device *dev) dm_digtable.dbg_mode = DM_DBG_OFF; //off=by real rssi value, on=by DM_DigTable.Rssi_val for new dig dm_digtable.dig_algorithm_switch = 0; - /* 2007/10/04 MH Define init gain threshol. */ + /* 2007/10/04 MH Define init gain threshold. */ dm_digtable.dig_state = DM_STA_DIG_MAX; dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX; dm_digtable.initialgain_lowerbound_state = false; @@ -2145,7 +2145,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( /*DbgPrint("DIG Check\n\r RSSI=%d LOW=%d HIGH=%d STATE=%d", pHalData->UndecoratedSmoothedPWDB, DM_DigTable.RssiLowThresh, DM_DigTable.RssiHighThresh, DM_DigTable.Dig_State);*/ - /* 1. When RSSI decrease, We have to judge if it is smaller than a treshold + /* 1. When RSSI decrease, We have to judge if it is smaller than a threshold and then execute below step. */ if ((priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh)) { @@ -2205,7 +2205,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( } - /* 2. When RSSI increase, We have to judge if it is larger than a treshold + /* 2. When RSSI increase, We have to judge if it is larger than a threshold and then execute below step. */ if ((priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) ) { @@ -2314,7 +2314,7 @@ static void dm_ctrl_initgain_byrssi_highpwr( } /* 3. When RSSI >75% or <70%, it is a high power issue. We have to judge if - it is larger than a treshold and then execute below step. */ + it is larger than a threshold and then execute below step. */ // 2008/02/05 MH SD3-Jerry Modify PD_TH for high power issue. if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh) { diff --git a/drivers/staging/rtl8192e/r8192E_wx.c b/drivers/staging/rtl8192e/r8192E_wx.c index e9e799c228632d6f292b99322c3988075567fedc..d1eb89229cdf43119d0c00078bc31ab34ed327ad 100644 --- a/drivers/staging/rtl8192e/r8192E_wx.c +++ b/drivers/staging/rtl8192e/r8192E_wx.c @@ -446,7 +446,7 @@ static int rtl8180_wx_get_range(struct net_device *dev, range->max_qual.updated = 7; /* Updated all three */ range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */ - /* TODO: Find real 'good' to 'bad' threshol value for RSSI */ + /* TODO: Find real 'good' to 'bad' threshold value for RSSI */ range->avg_qual.level = 20 + -98; range->avg_qual.noise = 0; range->avg_qual.updated = 7; /* Updated all three */ diff --git a/drivers/staging/rtl8192e/r819xE_cmdpkt.c b/drivers/staging/rtl8192e/r819xE_cmdpkt.c index d6b7d2f39e3efb73af5f9296a07fd719fe64bb78..2aaa4e1bb37593e665426657bb639c3c0c19adae 100644 --- a/drivers/staging/rtl8192e/r819xE_cmdpkt.c +++ b/drivers/staging/rtl8192e/r819xE_cmdpkt.c @@ -783,7 +783,7 @@ u32 cmpk_message_handle_rx(struct net_device *dev, struct ieee80211_rx_stats *ps default: - RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():unknow CMD Element\n"); + RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():unknown CMD Element\n"); return 1; /* This is a command packet. */ } // 2007/01/22 MH Display received rx command packet info. diff --git a/drivers/staging/rtl8192e/r819xE_phyreg.h b/drivers/staging/rtl8192e/r819xE_phyreg.h index d4a439275effa999d2862d41521a8d8532793fbc..37f0feefaf2c13e6cdb68b0a512cacd93b4820d5 100644 --- a/drivers/staging/rtl8192e/r819xE_phyreg.h +++ b/drivers/staging/rtl8192e/r819xE_phyreg.h @@ -294,7 +294,7 @@ #define bR2RCCAMask 0x00000f00 #define bHSSI_R2TDelay 0xf8000000 #define bHSSI_T2RDelay 0xf80000 -#define bContTxHSSI 0x400 //chane gain at continue Tx +#define bContTxHSSI 0x400 //channel gain at continue Tx #define bIGFromCCK 0x200 #define bAGCAddress 0x3f #define bRxHPTx 0x7000 diff --git a/drivers/staging/rtl8192su/Kconfig b/drivers/staging/rtl8192su/Kconfig index b8c95f942069c22be8f5cbd94c876950111cd899..123fa6d6a93b433be203ef38d1fdbc881fa8e710 100644 --- a/drivers/staging/rtl8192su/Kconfig +++ b/drivers/staging/rtl8192su/Kconfig @@ -1,6 +1,6 @@ config RTL8192SU tristate "RealTek RTL8192SU Wireless LAN NIC driver" - depends on PCI && WLAN + depends on PCI && WLAN && USB depends on WIRELESS_EXT default N ---help--- diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c index c3383bb8b760dda21229cedbca5daffe2988a1b0..e8c67d5dfb76285bc5443dcf121758809759d0d7 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c @@ -156,7 +156,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv) ieee->privacy_invoked = 0; ieee->ieee802_1x = 1; ieee->raw_tx = 0; - //ieee->hwsec_support = 1; //defalt support hw security. //use module_param instead. + //ieee->hwsec_support = 1; //default support hw security. //use module_param instead. ieee->hwsec_active = 0; //disable hwsec, switch it on when necessary. ieee80211_softmac_init(ieee); diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c index 8e56f97a8f57c9f6ba62bfdf4f943f2b47aa243e..ac223cef1d3334aac059a8bf46bea0a38d0eaa88 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c index fd8e11252f1b254ca5e5a8b01182839d3ee024bd..203c0a5cc8c16f2f7dbeed4da26efefb3554c26f 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c @@ -2120,10 +2120,10 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, * care of the ieee802.11 fragmentation. * So the driver receives a fragment per time and might * call the stop function when it want without take care - * to have enought room to TX an entire packet. + * to have enough room to TX an entire packet. * This might be useful if each fragment need it's own * descriptor, thus just keep a total free memory > than - * the max fragmentation treshold is not enought.. If the + * the max fragmentation threshold is not enough.. If the * ieee802.11 stack passed a TXB struct then you needed * to keep N free descriptors where * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c index 47ff0efb637089ab01282ef1be335f3e80afafc2..60621d6b2a6bbb3565de8c3071573aaf47b88c3b 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c index 6146c6435ddeebbf4ac63ee70f9f39fcc49ce52b..85c7e96b622d669c89d90b62c475a70102bbd502 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c @@ -30,7 +30,6 @@ ******************************************************************************/ #include -#include #include #include diff --git a/drivers/staging/rtl8192su/ieee80211/readme b/drivers/staging/rtl8192su/ieee80211/readme index 5764f2859286f9ef5ead5ae4ce366aa5d5a24cc1..7ba177ba3e335ea764c9a35c7b4de70544f17aa2 100644 --- a/drivers/staging/rtl8192su/ieee80211/readme +++ b/drivers/staging/rtl8192su/ieee80211/readme @@ -37,7 +37,7 @@ What this layer doesn't do (yet) disassociate clients, and it is really prone to always allow access. In bss client mode it is a bit rough with AP deauth and disassoc requests. - It has not any entry point to view the collected stats. -- Altought it takes care of the card supported rates in the management frame +- Although it takes care of the card supported rates in the management frame it sends, support for rate changing on TXed packet is not complete. - Give up once associated in bss client mode (it never detect a signal loss condition to disassociate and restart scanning) diff --git a/drivers/staging/rtl8192su/r8192S_phy.c b/drivers/staging/rtl8192su/r8192S_phy.c index 2c111d712f8fd61aa7fd21dd441397d29fc2b2c1..77ab026288d366b4647b303d4342972062869f78 100644 --- a/drivers/staging/rtl8192su/r8192S_phy.c +++ b/drivers/staging/rtl8192su/r8192S_phy.c @@ -1728,7 +1728,7 @@ static bool phy_SetRFPowerState8192SU(struct net_device* dev,RT_RF_POWER_STATE e default: bResult = FALSE; - //RT_ASSERT(FALSE, ("phy_SetRFPowerState8192SU(): unknow state to set: 0x%X!!!\n", eRFPowerState)); + //RT_ASSERT(FALSE, ("phy_SetRFPowerState8192SU(): unknown state to set: 0x%X!!!\n", eRFPowerState)); break; } break; @@ -2711,7 +2711,7 @@ u8 rtl8192_phy_SwChnl(struct net_device* dev, u8 channel) // However, this procedure is performed synchronously which should be running under // passive level. // -//not understant it +//not understand it void PHY_SwChnlPhy8192S( // Only called during initialize struct net_device* dev, u8 channel diff --git a/drivers/staging/rtl8192su/r8192S_phyreg.h b/drivers/staging/rtl8192su/r8192S_phyreg.h index acf644f430aa3d101cf5b30b2eb6ae941ce23b2f..2e4d76d196aa7ebef93653a690703e4600027026 100644 --- a/drivers/staging/rtl8192su/r8192S_phyreg.h +++ b/drivers/staging/rtl8192su/r8192S_phyreg.h @@ -453,7 +453,7 @@ #define bR2RCCAMask 0x00000f00 #define bHSSI_R2TDelay 0xf8000000 #define bHSSI_T2RDelay 0xf80000 -#define bContTxHSSI 0x400 //chane gain at continue Tx +#define bContTxHSSI 0x400 //channel gain at continue Tx #define bIGFromCCK 0x200 #define bAGCAddress 0x3f #define bRxHPTx 0x7000 diff --git a/drivers/staging/rtl8192su/r8192S_rtl6052.c b/drivers/staging/rtl8192su/r8192S_rtl6052.c index 69ef6dfc588be41ccdfe140ea68d9212abbdcc22..22398099adae514f31e6179609f6a306011a0e34 100644 --- a/drivers/staging/rtl8192su/r8192S_rtl6052.c +++ b/drivers/staging/rtl8192su/r8192S_rtl6052.c @@ -326,7 +326,7 @@ extern void PHY_RF6052SetOFDMTxPower(struct net_device* dev, u8 powerlevel) // // If path A and Path B coexist, we must limit Path A tx power. - // Protect Path B pwr over or under flow. We need to calculate upper and + // Protect Path B pwr over or underflow. We need to calculate upper and // lower bound of path A tx power. // if (priv->rf_type == RF_2T2R) @@ -354,7 +354,7 @@ extern void PHY_RF6052SetOFDMTxPower(struct net_device* dev, u8 powerlevel) // // If path A and Path B coexist, we must limit Path A tx power. - // Protect Path B pwr over or under flow. We need to calculate upper and + // Protect Path B pwr under/over flow. We need to calculate upper and // lower bound of path A tx power. // if (priv->rf_type == RF_2T2R) diff --git a/drivers/staging/rtl8192su/r8192U_dm.c b/drivers/staging/rtl8192su/r8192U_dm.c index 5358ae8ba6166a88a76a6f66938cede8c46839a0..7891e96402726bd753fa412c81f5b4cf4e5c4049 100644 --- a/drivers/staging/rtl8192su/r8192U_dm.c +++ b/drivers/staging/rtl8192su/r8192U_dm.c @@ -593,7 +593,7 @@ static u32 OFDMSwingTable[OFDM_Table_Length] = { 0x5a400169, // 3, +3db 0x50800142, // 4, +2db 0x47c0011f, // 5, +1db - 0x40000100, // 6, +0db ===> default, upper for higher temprature, lower for low temprature + 0x40000100, // 6, +0db ===> default, upper for higher temperature, lower for low temperature 0x390000e4, // 7, -1db 0x32c000cb, // 8, -2db 0x2d4000b5, // 9, -3db @@ -912,14 +912,14 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev) RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d \n", tmpRegA); if(tmpRegA < 3 || tmpRegA > 13) return; - if(tmpRegA >= 12) // if over 12, TP will be bad when high temprature + if(tmpRegA >= 12) // if over 12, TP will be bad when high temperature tmpRegA = 12; RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d \n", tmpRegA); priv->ThermalMeter[0] = ThermalMeterVal; //We use fixed value by Bryant's suggestion priv->ThermalMeter[1] = ThermalMeterVal; //We use fixed value by Bryant's suggestion - //Get current RF-A temprature index - if(priv->ThermalMeter[0] >= (u8)tmpRegA) //lower temprature + //Get current RF-A temperature index + if(priv->ThermalMeter[0] >= (u8)tmpRegA) //lower temperature { tmpOFDMindex = tmpCCK20Mindex = 6+(priv->ThermalMeter[0]-(u8)tmpRegA); tmpCCK40Mindex = tmpCCK20Mindex - 6; @@ -933,7 +933,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev) else { tmpval = ((u8)tmpRegA - priv->ThermalMeter[0]); - if(tmpval >= 6) // higher temprature + if(tmpval >= 6) // higher temperature tmpOFDMindex = tmpCCK20Mindex = 0; // max to +6dB else tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval; diff --git a/drivers/staging/rtl8192su/r8192U_wx.c b/drivers/staging/rtl8192su/r8192U_wx.c index 2208c9b1e726d90bb77a71258b2cda2204445ba8..a7cc6f9a4739d4f9a6a78e819c5689aa1a020c44 100644 --- a/drivers/staging/rtl8192su/r8192U_wx.c +++ b/drivers/staging/rtl8192su/r8192U_wx.c @@ -435,7 +435,7 @@ static int rtl8180_wx_get_range(struct net_device *dev, range->max_qual.updated = 7; /* Updated all three */ range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */ - /* TODO: Find real 'good' to 'bad' threshol value for RSSI */ + /* TODO: Find real 'good' to 'bad' threshold value for RSSI */ range->avg_qual.level = 20 + -98; range->avg_qual.noise = 0; range->avg_qual.updated = 7; /* Updated all three */ diff --git a/drivers/staging/rtl8192su/r819xU_cmdpkt.c b/drivers/staging/rtl8192su/r819xU_cmdpkt.c index e2ba93e307578c4507daec1f816fc2cbc56d6f7b..3ebfe79bb663b388bbabddd49075aade6466f208 100644 --- a/drivers/staging/rtl8192su/r819xU_cmdpkt.c +++ b/drivers/staging/rtl8192su/r819xU_cmdpkt.c @@ -697,7 +697,7 @@ cmpk_message_handle_rx( default: - RT_TRACE(COMP_ERR, "---->cmpk_message_handle_rx():unknow CMD Element\n"); + RT_TRACE(COMP_ERR, "---->cmpk_message_handle_rx():unknown CMD Element\n"); return 1; /* This is a command packet. */ } // 2007/01/22 MH Display received rx command packet info. diff --git a/drivers/staging/rtl8192u/Kconfig b/drivers/staging/rtl8192u/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..9913ab8fb3595df422ff301681a96bb84afc6eda --- /dev/null +++ b/drivers/staging/rtl8192u/Kconfig @@ -0,0 +1,6 @@ +config RTL8192U + tristate "RealTek RTL8192U Wireless LAN NIC driver" + depends on PCI && WLAN && USB + depends on WIRELESS_EXT + default N + ---help--- diff --git a/drivers/staging/rtl8192u/Makefile b/drivers/staging/rtl8192u/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..2d59c4ef6c5beb1648c10d9c4f678e9727896eae --- /dev/null +++ b/drivers/staging/rtl8192u/Makefile @@ -0,0 +1,33 @@ +NIC_SELECT = RTL8192U + +EXTRA_CFLAGS += -std=gnu89 +EXTRA_CFLAGS += -O2 + +EXTRA_CFLAGS += -mhard-float -DCONFIG_FORCE_HARD_FLOAT=y +EXTRA_CFLAGS += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX +EXTRA_CFLAGS += -DTHOMAS_BEACON -DTHOMAS_TASKLET -DTHOMAS_SKB -DTHOMAS_TURBO +#EXTRA_CFLAGS += -DUSB_TX_DRIVER_AGGREGATION_ENABLE +#EXTRA_CFLAGS += -DUSB_RX_AGGREGATION_SUPPORT +EXTRA_CFLAGS += -DUSE_ONE_PIPE +EXTRA_CFLAGS += -DENABLE_DOT11D +EXTRA_CFLAGS += -Idrivers/staging/rtl8192u/ieee80211 + +r8192u_usb-objs := r8192U_core.o r8180_93cx6.o r8192U_wx.o \ + r8190_rtl8256.o r819xU_phy.o r819xU_firmware.o \ + r819xU_cmdpkt.o r8192U_dm.o r819xU_firmware_img.o \ + ieee80211/ieee80211_crypt.o \ + ieee80211/ieee80211_crypt_tkip.o \ + ieee80211/ieee80211_crypt_ccmp.o \ + ieee80211/ieee80211_crypt_wep.o \ + ieee80211/ieee80211_rx.o \ + ieee80211/ieee80211_softmac.o \ + ieee80211/ieee80211_tx.o \ + ieee80211/ieee80211_wx.o \ + ieee80211/ieee80211_module.o \ + ieee80211/ieee80211_softmac_wx.o \ + ieee80211/rtl819x_HTProc.o \ + ieee80211/rtl819x_TSProc.o \ + ieee80211/rtl819x_BAProc.o \ + ieee80211/dot11d.o + +obj-$(CONFIG_RTL8192U) += r8192u_usb.o diff --git a/drivers/staging/rtl8192u/authors b/drivers/staging/rtl8192u/authors new file mode 100644 index 0000000000000000000000000000000000000000..b08bbae39e727e5661fd889c25016c698e40ba87 --- /dev/null +++ b/drivers/staging/rtl8192u/authors @@ -0,0 +1 @@ +Andrea Merello diff --git a/drivers/staging/rtl8192u/changes b/drivers/staging/rtl8192u/changes new file mode 100644 index 0000000000000000000000000000000000000000..87c33fdb95267e5ca9a5429e039aae1802a10c5a --- /dev/null +++ b/drivers/staging/rtl8192u/changes @@ -0,0 +1,5 @@ +v 0.1 + +First version. +This is based on the rtl8180-sa2400 pre-0.22-CVS code.. + diff --git a/drivers/staging/rtl8192u/copying b/drivers/staging/rtl8192u/copying new file mode 100644 index 0000000000000000000000000000000000000000..d60c31a97a544b53039088d14fe9114583c0efc3 --- /dev/null +++ b/drivers/staging/rtl8192u/copying @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/drivers/staging/rtl8192u/dot11d.h b/drivers/staging/rtl8192u/dot11d.h new file mode 100644 index 0000000000000000000000000000000000000000..15b7a4ba37b6d2eba496686cba3571b1434879cf --- /dev/null +++ b/drivers/staging/rtl8192u/dot11d.h @@ -0,0 +1,102 @@ +#ifndef __INC_DOT11D_H +#define __INC_DOT11D_H + +#ifdef ENABLE_DOT11D +#include "ieee80211.h" + +//#define ENABLE_DOT11D + +//#define DOT11D_MAX_CHNL_NUM 83 + +typedef struct _CHNL_TXPOWER_TRIPLE { + u8 FirstChnl; + u8 NumChnls; + u8 MaxTxPowerInDbm; +}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE; + +typedef enum _DOT11D_STATE { + DOT11D_STATE_NONE = 0, + DOT11D_STATE_LEARNED, + DOT11D_STATE_DONE, +}DOT11D_STATE; + +typedef struct _RT_DOT11D_INFO { + //DECLARE_RT_OBJECT(RT_DOT11D_INFO); + + bool bEnabled; // dot11MultiDomainCapabilityEnabled + + u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element. + u8 CountryIeBuf[MAX_IE_LEN]; + u8 CountryIeSrcAddr[6]; // Source AP of the country IE. + u8 CountryIeWatchdog; + + u8 channel_map[MAX_CHANNEL_NUMBER+1]; //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) + //u8 ChnlListLen; // #Bytes valid in ChnlList[]. + //u8 ChnlList[DOT11D_MAX_CHNL_NUM]; + u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1]; + + DOT11D_STATE State; +}RT_DOT11D_INFO, *PRT_DOT11D_INFO; +#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 ) +#define cpMacAddr(des,src) ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5]) +#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo)) + +#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled +#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0) + +#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) +#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) + +#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \ + (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \ + FALSE : \ + (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length))) + +#define CIE_WATCHDOG_TH 1 +#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog +#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0 +#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev) + +#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE) + + +void +Dot11d_Init( + struct ieee80211_device *dev + ); + +void +Dot11d_Reset( + struct ieee80211_device *dev + ); + +void +Dot11d_UpdateCountryIe( + struct ieee80211_device *dev, + u8 * pTaddr, + u16 CoutryIeLen, + u8 * pCoutryIe + ); + +u8 +DOT11D_GetMaxTxPwrInDbm( + struct ieee80211_device *dev, + u8 Channel + ); + +void +DOT11D_ScanComplete( + struct ieee80211_device * dev + ); + +int IsLegalChannel( + struct ieee80211_device * dev, + u8 channel +); + +int ToLegalChannel( + struct ieee80211_device * dev, + u8 channel +); +#endif //ENABLE_DOT11D +#endif // #ifndef __INC_DOT11D_H diff --git a/drivers/staging/rtl8192u/ieee80211.h b/drivers/staging/rtl8192u/ieee80211.h new file mode 100644 index 0000000000000000000000000000000000000000..3a47f1213e8593c77e7cfcdab226526417e8fb62 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211.h @@ -0,0 +1,2638 @@ +/* + * Merged with mainline ieee80211.h in Aug 2004. Original ieee802_11 + * remains copyright by the original authors + * + * Portions of the merged code are based on Host AP (software wireless + * LAN access point) driver for Intersil Prism2/2.5/3. + * + * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen + * + * Copyright (c) 2002-2003, Jouni Malinen + * + * Adaption to a generic IEEE 802.11 stack by James Ketrenos + * + * Copyright (c) 2004, Intel Corporation + * + * Modified for Realtek's wi-fi cards by Andrea Merello + * + * + * 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. See README and COPYING for + * more details. + */ +#ifndef IEEE80211_H +#define IEEE80211_H +#include /* ETH_ALEN */ +#include /* ARRAY_SIZE */ +#include +#include +#include +#include +#include + +#include +#include + +#include "ieee80211/rtl819x_HT.h" +#include "ieee80211/rtl819x_BA.h" +#include "ieee80211/rtl819x_TS.h" + + +#ifndef IW_MODE_MONITOR +#define IW_MODE_MONITOR 6 +#endif + +#ifndef IWEVCUSTOM +#define IWEVCUSTOM 0x8c02 +#endif + + +#ifndef container_of +/** + * container_of - cast a member of a structure out to the containing structure + * + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#endif + +#define KEY_TYPE_NA 0x0 +#define KEY_TYPE_WEP40 0x1 +#define KEY_TYPE_TKIP 0x2 +#define KEY_TYPE_CCMP 0x4 +#define KEY_TYPE_WEP104 0x5 + +/* added for rtl819x tx procedure */ +#define MAX_QUEUE_SIZE 0x10 + +// +// 8190 queue mapping +// +#define BK_QUEUE 0 +#define BE_QUEUE 1 +#define VI_QUEUE 2 +#define VO_QUEUE 3 +#define HCCA_QUEUE 4 +#define TXCMD_QUEUE 5 +#define MGNT_QUEUE 6 +#define HIGH_QUEUE 7 +#define BEACON_QUEUE 8 + +#define LOW_QUEUE BE_QUEUE +#define NORMAL_QUEUE MGNT_QUEUE + +//added by amy for ps +#define SWRF_TIMEOUT 50 + +//added by amy for LEAP related +#define IE_CISCO_FLAG_POSITION 0x08 // Flag byte: byte 8, numbered from 0. +#define SUPPORT_CKIP_MIC 0x08 // bit3 +#define SUPPORT_CKIP_PK 0x10 // bit4 +/* defined for skb cb field */ +/* At most 28 byte */ +typedef struct cb_desc { + /* Tx Desc Related flags (8-9) */ + u8 bLastIniPkt:1; + u8 bCmdOrInit:1; + u8 bFirstSeg:1; + u8 bLastSeg:1; + u8 bEncrypt:1; + u8 bTxDisableRateFallBack:1; + u8 bTxUseDriverAssingedRate:1; + u8 bHwSec:1; //indicate whether use Hw security. WB + + u8 reserved1; + + /* Tx Firmware Relaged flags (10-11)*/ + u8 bCTSEnable:1; + u8 bRTSEnable:1; + u8 bUseShortGI:1; + u8 bUseShortPreamble:1; + u8 bTxEnableFwCalcDur:1; + u8 bAMPDUEnable:1; + u8 bRTSSTBC:1; + u8 RTSSC:1; + + u8 bRTSBW:1; + u8 bPacketBW:1; + u8 bRTSUseShortPreamble:1; + u8 bRTSUseShortGI:1; + u8 bMulticast:1; + u8 bBroadcast:1; + //u8 reserved2:2; + u8 drv_agg_enable:1; + u8 reserved2:1; + + /* Tx Desc related element(12-19) */ + u8 rata_index; + u8 queue_index; + //u8 reserved3; + //u8 reserved4; + u16 txbuf_size; + //u8 reserved5; + u8 RATRIndex; + u8 reserved6; + u8 reserved7; + u8 reserved8; + + /* Tx firmware related element(20-27) */ + u8 data_rate; + u8 rts_rate; + u8 ampdu_factor; + u8 ampdu_density; + //u8 reserved9; + //u8 reserved10; + //u8 reserved11; + u8 DrvAggrNum; + u16 pkt_size; + u8 reserved12; +}cb_desc, *pcb_desc; + +/*--------------------------Define -------------------------------------------*/ +#define MGN_1M 0x02 +#define MGN_2M 0x04 +#define MGN_5_5M 0x0b +#define MGN_11M 0x16 + +#define MGN_6M 0x0c +#define MGN_9M 0x12 +#define MGN_12M 0x18 +#define MGN_18M 0x24 +#define MGN_24M 0x30 +#define MGN_36M 0x48 +#define MGN_48M 0x60 +#define MGN_54M 0x6c + +#define MGN_MCS0 0x80 +#define MGN_MCS1 0x81 +#define MGN_MCS2 0x82 +#define MGN_MCS3 0x83 +#define MGN_MCS4 0x84 +#define MGN_MCS5 0x85 +#define MGN_MCS6 0x86 +#define MGN_MCS7 0x87 +#define MGN_MCS8 0x88 +#define MGN_MCS9 0x89 +#define MGN_MCS10 0x8a +#define MGN_MCS11 0x8b +#define MGN_MCS12 0x8c +#define MGN_MCS13 0x8d +#define MGN_MCS14 0x8e +#define MGN_MCS15 0x8f + +//---------------------------------------------------------------------------- +// 802.11 Management frame Reason Code field +//---------------------------------------------------------------------------- +enum _ReasonCode{ + unspec_reason = 0x1, + auth_not_valid = 0x2, + deauth_lv_ss = 0x3, + inactivity = 0x4, + ap_overload = 0x5, + class2_err = 0x6, + class3_err = 0x7, + disas_lv_ss = 0x8, + asoc_not_auth = 0x9, + + //----MIC_CHECK + mic_failure = 0xe, + //----END MIC_CHECK + + // Reason code defined in 802.11i D10.0 p.28. + invalid_IE = 0x0d, + four_way_tmout = 0x0f, + two_way_tmout = 0x10, + IE_dismatch = 0x11, + invalid_Gcipher = 0x12, + invalid_Pcipher = 0x13, + invalid_AKMP = 0x14, + unsup_RSNIEver = 0x15, + invalid_RSNIE = 0x16, + auth_802_1x_fail= 0x17, + ciper_reject = 0x18, + + // Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie, 2005-11-15. + QoS_unspec = 0x20, // 32 + QAP_bandwidth = 0x21, // 33 + poor_condition = 0x22, // 34 + no_facility = 0x23, // 35 + // Where is 36??? + req_declined = 0x25, // 37 + invalid_param = 0x26, // 38 + req_not_honored= 0x27, // 39 + TS_not_created = 0x2F, // 47 + DL_not_allowed = 0x30, // 48 + dest_not_exist = 0x31, // 49 + dest_not_QSTA = 0x32, // 50 +}; + + + +#define aSifsTime ((priv->ieee80211->current_network.mode == IEEE_A)||(priv->ieee80211->current_network.mode == IEEE_N_24G)||(priv->ieee80211->current_network.mode == IEEE_N_5G))? 16 : 10 + +#define MGMT_QUEUE_NUM 5 + +#define IEEE_CMD_SET_WPA_PARAM 1 +#define IEEE_CMD_SET_WPA_IE 2 +#define IEEE_CMD_SET_ENCRYPTION 3 +#define IEEE_CMD_MLME 4 + +#define IEEE_PARAM_WPA_ENABLED 1 +#define IEEE_PARAM_TKIP_COUNTERMEASURES 2 +#define IEEE_PARAM_DROP_UNENCRYPTED 3 +#define IEEE_PARAM_PRIVACY_INVOKED 4 +#define IEEE_PARAM_AUTH_ALGS 5 +#define IEEE_PARAM_IEEE_802_1X 6 +//It should consistent with the driver_XXX.c +// David, 2006.9.26 +#define IEEE_PARAM_WPAX_SELECT 7 +//Added for notify the encryption type selection +// David, 2006.9.26 +#define IEEE_PROTO_WPA 1 +#define IEEE_PROTO_RSN 2 +//Added for notify the encryption type selection +// David, 2006.9.26 +#define IEEE_WPAX_USEGROUP 0 +#define IEEE_WPAX_WEP40 1 +#define IEEE_WPAX_TKIP 2 +#define IEEE_WPAX_WRAP 3 +#define IEEE_WPAX_CCMP 4 +#define IEEE_WPAX_WEP104 5 + +#define IEEE_KEY_MGMT_IEEE8021X 1 +#define IEEE_KEY_MGMT_PSK 2 + +#define IEEE_MLME_STA_DEAUTH 1 +#define IEEE_MLME_STA_DISASSOC 2 + + +#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2 +#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3 +#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4 +#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5 +#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6 +#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7 + + +#define IEEE_CRYPT_ALG_NAME_LEN 16 + +#define MAX_IE_LEN 0xff + +// added for kernel conflict +#define ieee80211_crypt_deinit_entries ieee80211_crypt_deinit_entries_rsl +#define ieee80211_crypt_deinit_handler ieee80211_crypt_deinit_handler_rsl +#define ieee80211_crypt_delayed_deinit ieee80211_crypt_delayed_deinit_rsl +#define ieee80211_register_crypto_ops ieee80211_register_crypto_ops_rsl +#define ieee80211_unregister_crypto_ops ieee80211_unregister_crypto_ops_rsl +#define ieee80211_get_crypto_ops ieee80211_get_crypto_ops_rsl + +#define ieee80211_ccmp_null ieee80211_ccmp_null_rsl + +#define ieee80211_tkip_null ieee80211_tkip_null_rsl + +#define ieee80211_wep_null ieee80211_wep_null_rsl + +#define free_ieee80211 free_ieee80211_rsl +#define alloc_ieee80211 alloc_ieee80211_rsl + +#define ieee80211_rx ieee80211_rx_rsl +#define ieee80211_rx_mgt ieee80211_rx_mgt_rsl + +#define ieee80211_get_beacon ieee80211_get_beacon_rsl +#define ieee80211_wake_queue ieee80211_wake_queue_rsl +#define ieee80211_stop_queue ieee80211_stop_queue_rsl +#define ieee80211_reset_queue ieee80211_reset_queue_rsl +#define ieee80211_softmac_stop_protocol ieee80211_softmac_stop_protocol_rsl +#define ieee80211_softmac_start_protocol ieee80211_softmac_start_protocol_rsl +#define ieee80211_is_shortslot ieee80211_is_shortslot_rsl +#define ieee80211_is_54g ieee80211_is_54g_rsl +#define ieee80211_wpa_supplicant_ioctl ieee80211_wpa_supplicant_ioctl_rsl +#define ieee80211_ps_tx_ack ieee80211_ps_tx_ack_rsl +#define ieee80211_softmac_xmit ieee80211_softmac_xmit_rsl +#define ieee80211_stop_send_beacons ieee80211_stop_send_beacons_rsl +#define notify_wx_assoc_event notify_wx_assoc_event_rsl +#define SendDisassociation SendDisassociation_rsl +#define ieee80211_disassociate ieee80211_disassociate_rsl +#define ieee80211_start_send_beacons ieee80211_start_send_beacons_rsl +#define ieee80211_stop_scan ieee80211_stop_scan_rsl +#define ieee80211_send_probe_requests ieee80211_send_probe_requests_rsl +#define ieee80211_softmac_scan_syncro ieee80211_softmac_scan_syncro_rsl +#define ieee80211_start_scan_syncro ieee80211_start_scan_syncro_rsl + +#define ieee80211_wx_get_essid ieee80211_wx_get_essid_rsl +#define ieee80211_wx_set_essid ieee80211_wx_set_essid_rsl +#define ieee80211_wx_set_rate ieee80211_wx_set_rate_rsl +#define ieee80211_wx_get_rate ieee80211_wx_get_rate_rsl +#define ieee80211_wx_set_wap ieee80211_wx_set_wap_rsl +#define ieee80211_wx_get_wap ieee80211_wx_get_wap_rsl +#define ieee80211_wx_set_mode ieee80211_wx_set_mode_rsl +#define ieee80211_wx_get_mode ieee80211_wx_get_mode_rsl +#define ieee80211_wx_set_scan ieee80211_wx_set_scan_rsl +#define ieee80211_wx_get_freq ieee80211_wx_get_freq_rsl +#define ieee80211_wx_set_freq ieee80211_wx_set_freq_rsl +#define ieee80211_wx_set_rawtx ieee80211_wx_set_rawtx_rsl +#define ieee80211_wx_get_name ieee80211_wx_get_name_rsl +#define ieee80211_wx_set_power ieee80211_wx_set_power_rsl +#define ieee80211_wx_get_power ieee80211_wx_get_power_rsl +#define ieee80211_wlan_frequencies ieee80211_wlan_frequencies_rsl +#define ieee80211_wx_set_rts ieee80211_wx_set_rts_rsl +#define ieee80211_wx_get_rts ieee80211_wx_get_rts_rsl + +#define ieee80211_txb_free ieee80211_txb_free_rsl + +#define ieee80211_wx_set_gen_ie ieee80211_wx_set_gen_ie_rsl +#define ieee80211_wx_get_scan ieee80211_wx_get_scan_rsl +#define ieee80211_wx_set_encode ieee80211_wx_set_encode_rsl +#define ieee80211_wx_get_encode ieee80211_wx_get_encode_rsl +#if WIRELESS_EXT >= 18 +#define ieee80211_wx_set_mlme ieee80211_wx_set_mlme_rsl +#define ieee80211_wx_set_auth ieee80211_wx_set_auth_rsl +#define ieee80211_wx_set_encode_ext ieee80211_wx_set_encode_ext_rsl +#define ieee80211_wx_get_encode_ext ieee80211_wx_get_encode_ext_rsl +#endif + + +typedef struct ieee_param { + u32 cmd; + u8 sta_addr[ETH_ALEN]; + union { + struct { + u8 name; + u32 value; + } wpa_param; + struct { + u32 len; + u8 reserved[32]; + u8 data[0]; + } wpa_ie; + struct{ + int command; + int reason_code; + } mlme; + struct { + u8 alg[IEEE_CRYPT_ALG_NAME_LEN]; + u8 set_tx; + u32 err; + u8 idx; + u8 seq[8]; /* sequence counter (set: RX, get: TX) */ + u16 key_len; + u8 key[0]; + } crypt; + } u; +}ieee_param; + + +#if WIRELESS_EXT < 17 +#define IW_QUAL_QUAL_INVALID 0x10 +#define IW_QUAL_LEVEL_INVALID 0x20 +#define IW_QUAL_NOISE_INVALID 0x40 +#define IW_QUAL_QUAL_UPDATED 0x1 +#define IW_QUAL_LEVEL_UPDATED 0x2 +#define IW_QUAL_NOISE_UPDATED 0x4 +#endif + + +// linux under 2.6.9 release may not support it, so modify it for common use +#define MSECS(t) msecs_to_jiffies(t) +#define msleep_interruptible_rsl msleep_interruptible + +#define IEEE80211_DATA_LEN 2304 +/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section + 6.2.1.1.2. + + The figure in section 7.1.2 suggests a body size of up to 2312 + bytes is allowed, which is a bit confusing, I suspect this + represents the 2304 bytes of real data, plus a possible 8 bytes of + WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */ +#define IEEE80211_1ADDR_LEN 10 +#define IEEE80211_2ADDR_LEN 16 +#define IEEE80211_3ADDR_LEN 24 +#define IEEE80211_4ADDR_LEN 30 +#define IEEE80211_FCS_LEN 4 +#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) +#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) +#define IEEE80211_MGMT_HDR_LEN 24 +#define IEEE80211_DATA_HDR3_LEN 24 +#define IEEE80211_DATA_HDR4_LEN 30 + +#define MIN_FRAG_THRESHOLD 256U +#define MAX_FRAG_THRESHOLD 2346U + + +/* Frame control field constants */ +#define IEEE80211_FCTL_VERS 0x0003 +#define IEEE80211_FCTL_FTYPE 0x000c +#define IEEE80211_FCTL_STYPE 0x00f0 +#define IEEE80211_FCTL_FRAMETYPE 0x00fc +#define IEEE80211_FCTL_TODS 0x0100 +#define IEEE80211_FCTL_FROMDS 0x0200 +#define IEEE80211_FCTL_DSTODS 0x0300 //added by david +#define IEEE80211_FCTL_MOREFRAGS 0x0400 +#define IEEE80211_FCTL_RETRY 0x0800 +#define IEEE80211_FCTL_PM 0x1000 +#define IEEE80211_FCTL_MOREDATA 0x2000 +#define IEEE80211_FCTL_WEP 0x4000 +#define IEEE80211_FCTL_ORDER 0x8000 + +#define IEEE80211_FTYPE_MGMT 0x0000 +#define IEEE80211_FTYPE_CTL 0x0004 +#define IEEE80211_FTYPE_DATA 0x0008 + +/* management */ +#define IEEE80211_STYPE_ASSOC_REQ 0x0000 +#define IEEE80211_STYPE_ASSOC_RESP 0x0010 +#define IEEE80211_STYPE_REASSOC_REQ 0x0020 +#define IEEE80211_STYPE_REASSOC_RESP 0x0030 +#define IEEE80211_STYPE_PROBE_REQ 0x0040 +#define IEEE80211_STYPE_PROBE_RESP 0x0050 +#define IEEE80211_STYPE_BEACON 0x0080 +#define IEEE80211_STYPE_ATIM 0x0090 +#define IEEE80211_STYPE_DISASSOC 0x00A0 +#define IEEE80211_STYPE_AUTH 0x00B0 +#define IEEE80211_STYPE_DEAUTH 0x00C0 +#define IEEE80211_STYPE_MANAGE_ACT 0x00D0 + +/* control */ +#define IEEE80211_STYPE_PSPOLL 0x00A0 +#define IEEE80211_STYPE_RTS 0x00B0 +#define IEEE80211_STYPE_CTS 0x00C0 +#define IEEE80211_STYPE_ACK 0x00D0 +#define IEEE80211_STYPE_CFEND 0x00E0 +#define IEEE80211_STYPE_CFENDACK 0x00F0 +#define IEEE80211_STYPE_BLOCKACK 0x0094 + +/* data */ +#define IEEE80211_STYPE_DATA 0x0000 +#define IEEE80211_STYPE_DATA_CFACK 0x0010 +#define IEEE80211_STYPE_DATA_CFPOLL 0x0020 +#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 +#define IEEE80211_STYPE_NULLFUNC 0x0040 +#define IEEE80211_STYPE_CFACK 0x0050 +#define IEEE80211_STYPE_CFPOLL 0x0060 +#define IEEE80211_STYPE_CFACKPOLL 0x0070 +#define IEEE80211_STYPE_QOS_DATA 0x0080 //added for WMM 2006/8/2 +#define IEEE80211_STYPE_QOS_NULL 0x00C0 + +#define IEEE80211_SCTL_FRAG 0x000F +#define IEEE80211_SCTL_SEQ 0xFFF0 + +/* QOS control */ +#define IEEE80211_QCTL_TID 0x000F + +#define FC_QOS_BIT BIT7 +#define IsDataFrame(pdu) ( ((pdu[0] & 0x0C)==0x08) ? true : false ) +#define IsLegacyDataFrame(pdu) (IsDataFrame(pdu) && (!(pdu[0]&FC_QOS_BIT)) ) +//added by wb. Is this right? +#define IsQoSDataFrame(pframe) ((*(u16*)pframe&(IEEE80211_STYPE_QOS_DATA|IEEE80211_FTYPE_DATA)) == (IEEE80211_STYPE_QOS_DATA|IEEE80211_FTYPE_DATA)) +#define Frame_Order(pframe) (*(u16*)pframe&IEEE80211_FCTL_ORDER) +#define SN_LESS(a, b) (((a-b)&0x800)!=0) +#define SN_EQUAL(a, b) (a == b) +#define MAX_DEV_ADDR_SIZE 8 +typedef enum _ACT_CATEGORY{ + ACT_CAT_QOS = 1, + ACT_CAT_DLS = 2, + ACT_CAT_BA = 3, + ACT_CAT_HT = 7, + ACT_CAT_WMM = 17, +} ACT_CATEGORY, *PACT_CATEGORY; + +typedef enum _TS_ACTION{ + ACT_ADDTSREQ = 0, + ACT_ADDTSRSP = 1, + ACT_DELTS = 2, + ACT_SCHEDULE = 3, +} TS_ACTION, *PTS_ACTION; + +typedef enum _BA_ACTION{ + ACT_ADDBAREQ = 0, + ACT_ADDBARSP = 1, + ACT_DELBA = 2, +} BA_ACTION, *PBA_ACTION; + +typedef enum _InitialGainOpType{ + IG_Backup=0, + IG_Restore, + IG_Max +}InitialGainOpType; + +/* debug macros */ +#define CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_IEEE80211_DEBUG +extern u32 ieee80211_debug_level; +#define IEEE80211_DEBUG(level, fmt, args...) \ +do { if (ieee80211_debug_level & (level)) \ + printk(KERN_DEBUG "ieee80211: " fmt, ## args); } while (0) +//wb added to debug out data buf +//if you want print DATA buffer related BA, please set ieee80211_debug_level to DATA|BA +#define IEEE80211_DEBUG_DATA(level, data, datalen) \ + do{ if ((ieee80211_debug_level & (level)) == (level)) \ + { \ + int i; \ + u8* pdata = (u8*) data; \ + printk(KERN_DEBUG "ieee80211: %s()\n", __FUNCTION__); \ + for(i=0; i<(int)(datalen); i++) \ + { \ + printk("%2x ", pdata[i]); \ + if ((i+1)%16 == 0) printk("\n"); \ + } \ + printk("\n"); \ + } \ + } while (0) +#else +#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0) +#define IEEE80211_DEBUG_DATA(level, data, datalen) do {} while(0) +#endif /* CONFIG_IEEE80211_DEBUG */ + +/* debug macros not dependent on CONFIG_IEEE80211_DEBUG */ + +#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5] + +/* + * To use the debug system; + * + * If you are defining a new debug classification, simply add it to the #define + * list here in the form of: + * + * #define IEEE80211_DL_xxxx VALUE + * + * shifting value to the left one bit from the previous entry. xxxx should be + * the name of the classification (for example, WEP) + * + * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your + * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want + * to send output to that classification. + * + * To add your debug level to the list of levels seen when you perform + * + * % cat /proc/net/ipw/debug_level + * + * you simply need to add your entry to the ipw_debug_levels array. + * + * If you do not see debug_level in /proc/net/ipw then you do not have + * CONFIG_IEEE80211_DEBUG defined in your kernel configuration + * + */ + +#define IEEE80211_DL_INFO (1<<0) +#define IEEE80211_DL_WX (1<<1) +#define IEEE80211_DL_SCAN (1<<2) +#define IEEE80211_DL_STATE (1<<3) +#define IEEE80211_DL_MGMT (1<<4) +#define IEEE80211_DL_FRAG (1<<5) +#define IEEE80211_DL_EAP (1<<6) +#define IEEE80211_DL_DROP (1<<7) + +#define IEEE80211_DL_TX (1<<8) +#define IEEE80211_DL_RX (1<<9) + +#define IEEE80211_DL_HT (1<<10) //HT +#define IEEE80211_DL_BA (1<<11) //ba +#define IEEE80211_DL_TS (1<<12) //TS +#define IEEE80211_DL_QOS (1<<13) +#define IEEE80211_DL_REORDER (1<<14) +#define IEEE80211_DL_IOT (1<<15) +#define IEEE80211_DL_IPS (1<<16) +#define IEEE80211_DL_TRACE (1<<29) //trace function, need to user net_ratelimit() together in order not to print too much to the screen +#define IEEE80211_DL_DATA (1<<30) //use this flag to control whether print data buf out. +#define IEEE80211_DL_ERR (1<<31) //always open +#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a) +#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a) +#define IEEE80211_DEBUG_INFO(f, a...) IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a) + +#define IEEE80211_DEBUG_WX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a) +#define IEEE80211_DEBUG_SCAN(f, a...) IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a) +#define IEEE80211_DEBUG_STATE(f, a...) IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a) +#define IEEE80211_DEBUG_MGMT(f, a...) IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a) +#define IEEE80211_DEBUG_FRAG(f, a...) IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a) +#define IEEE80211_DEBUG_EAP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a) +#define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a) +#define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a) +#define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a) +#define IEEE80211_DEBUG_QOS(f, a...) IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a) + +#ifdef CONFIG_IEEE80211_DEBUG +/* Added by Annie, 2005-11-22. */ +#define MAX_STR_LEN 64 +/* I want to see ASCII 33 to 126 only. Otherwise, I print '?'. Annie, 2005-11-22.*/ +#define PRINTABLE(_ch) (_ch>'!' && _ch<'~') +#define IEEE80211_PRINT_STR(_Comp, _TitleString, _Ptr, _Len) \ + if((_Comp) & level) \ + { \ + int __i; \ + u8 buffer[MAX_STR_LEN]; \ + int length = (_Len\n", _Len, buffer); \ + } +#else +#define IEEE80211_PRINT_STR(_Comp, _TitleString, _Ptr, _Len) do {} while (0) +#endif + +#include +#include /* ARPHRD_ETHER */ + +#ifndef WIRELESS_SPY +#define WIRELESS_SPY // enable iwspy support +#endif +#include // new driver API + +#ifndef ETH_P_PAE +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#endif /* ETH_P_PAE */ + +#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ + +#ifndef ETH_P_80211_RAW +#define ETH_P_80211_RAW (ETH_P_ECONET + 1) +#endif + +/* IEEE 802.11 defines */ + +#define P80211_OUI_LEN 3 + +struct ieee80211_snap_hdr { + + u8 dsap; /* always 0xAA */ + u8 ssap; /* always 0xAA */ + u8 ctrl; /* always 0x03 */ + u8 oui[P80211_OUI_LEN]; /* organizational universal id */ + +} __attribute__ ((packed)); + +#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) + +#define WLAN_FC_GET_VERS(fc) ((fc) & IEEE80211_FCTL_VERS) +#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE) +#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE) + +#define WLAN_FC_GET_FRAMETYPE(fc) ((fc) & IEEE80211_FCTL_FRAMETYPE) +#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG) +#define WLAN_GET_SEQ_SEQ(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) + +/* Authentication algorithms */ +#define WLAN_AUTH_OPEN 0 +#define WLAN_AUTH_SHARED_KEY 1 +#define WLAN_AUTH_LEAP 2 + +#define WLAN_AUTH_CHALLENGE_LEN 128 + +#define WLAN_CAPABILITY_BSS (1<<0) +#define WLAN_CAPABILITY_IBSS (1<<1) +#define WLAN_CAPABILITY_CF_POLLABLE (1<<2) +#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) +#define WLAN_CAPABILITY_PRIVACY (1<<4) +#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) +#define WLAN_CAPABILITY_PBCC (1<<6) +#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) +#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) +#define WLAN_CAPABILITY_QOS (1<<9) +#define WLAN_CAPABILITY_SHORT_SLOT (1<<10) +#define WLAN_CAPABILITY_DSSS_OFDM (1<<13) + +/* 802.11g ERP information element */ +#define WLAN_ERP_NON_ERP_PRESENT (1<<0) +#define WLAN_ERP_USE_PROTECTION (1<<1) +#define WLAN_ERP_BARKER_PREAMBLE (1<<2) + +/* Status codes */ +enum ieee80211_statuscode { + WLAN_STATUS_SUCCESS = 0, + WLAN_STATUS_UNSPECIFIED_FAILURE = 1, + WLAN_STATUS_CAPS_UNSUPPORTED = 10, + WLAN_STATUS_REASSOC_NO_ASSOC = 11, + WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12, + WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13, + WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14, + WLAN_STATUS_CHALLENGE_FAIL = 15, + WLAN_STATUS_AUTH_TIMEOUT = 16, + WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17, + WLAN_STATUS_ASSOC_DENIED_RATES = 18, + /* 802.11b */ + WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19, + WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20, + WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21, + /* 802.11h */ + WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22, + WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23, + WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24, + /* 802.11g */ + WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25, + WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26, + /* 802.11i */ + WLAN_STATUS_INVALID_IE = 40, + WLAN_STATUS_INVALID_GROUP_CIPHER = 41, + WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42, + WLAN_STATUS_INVALID_AKMP = 43, + WLAN_STATUS_UNSUPP_RSN_VERSION = 44, + WLAN_STATUS_INVALID_RSN_IE_CAP = 45, + WLAN_STATUS_CIPHER_SUITE_REJECTED = 46, +}; + +/* Reason codes */ +enum ieee80211_reasoncode { + WLAN_REASON_UNSPECIFIED = 1, + WLAN_REASON_PREV_AUTH_NOT_VALID = 2, + WLAN_REASON_DEAUTH_LEAVING = 3, + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4, + WLAN_REASON_DISASSOC_AP_BUSY = 5, + WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6, + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7, + WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8, + WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9, + /* 802.11h */ + WLAN_REASON_DISASSOC_BAD_POWER = 10, + WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11, + /* 802.11i */ + WLAN_REASON_INVALID_IE = 13, + WLAN_REASON_MIC_FAILURE = 14, + WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, + WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16, + WLAN_REASON_IE_DIFFERENT = 17, + WLAN_REASON_INVALID_GROUP_CIPHER = 18, + WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19, + WLAN_REASON_INVALID_AKMP = 20, + WLAN_REASON_UNSUPP_RSN_VERSION = 21, + WLAN_REASON_INVALID_RSN_IE_CAP = 22, + WLAN_REASON_IEEE8021X_FAILED = 23, + WLAN_REASON_CIPHER_SUITE_REJECTED = 24, +}; + +#define IEEE80211_STATMASK_SIGNAL (1<<0) +#define IEEE80211_STATMASK_RSSI (1<<1) +#define IEEE80211_STATMASK_NOISE (1<<2) +#define IEEE80211_STATMASK_RATE (1<<3) +#define IEEE80211_STATMASK_WEMASK 0x7 + +#define IEEE80211_CCK_MODULATION (1<<0) +#define IEEE80211_OFDM_MODULATION (1<<1) + +#define IEEE80211_24GHZ_BAND (1<<0) +#define IEEE80211_52GHZ_BAND (1<<1) + +#define IEEE80211_CCK_RATE_LEN 4 +#define IEEE80211_CCK_RATE_1MB 0x02 +#define IEEE80211_CCK_RATE_2MB 0x04 +#define IEEE80211_CCK_RATE_5MB 0x0B +#define IEEE80211_CCK_RATE_11MB 0x16 +#define IEEE80211_OFDM_RATE_LEN 8 +#define IEEE80211_OFDM_RATE_6MB 0x0C +#define IEEE80211_OFDM_RATE_9MB 0x12 +#define IEEE80211_OFDM_RATE_12MB 0x18 +#define IEEE80211_OFDM_RATE_18MB 0x24 +#define IEEE80211_OFDM_RATE_24MB 0x30 +#define IEEE80211_OFDM_RATE_36MB 0x48 +#define IEEE80211_OFDM_RATE_48MB 0x60 +#define IEEE80211_OFDM_RATE_54MB 0x6C +#define IEEE80211_BASIC_RATE_MASK 0x80 + +#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) +#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) +#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) +#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) +#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) +#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) +#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) +#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) +#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) +#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) +#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) +#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) + +#define IEEE80211_CCK_RATES_MASK 0x0000000F +#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ + IEEE80211_CCK_RATE_2MB_MASK) +#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ + IEEE80211_CCK_RATE_5MB_MASK | \ + IEEE80211_CCK_RATE_11MB_MASK) + +#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 +#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ + IEEE80211_OFDM_RATE_12MB_MASK | \ + IEEE80211_OFDM_RATE_24MB_MASK) +#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ + IEEE80211_OFDM_RATE_9MB_MASK | \ + IEEE80211_OFDM_RATE_18MB_MASK | \ + IEEE80211_OFDM_RATE_36MB_MASK | \ + IEEE80211_OFDM_RATE_48MB_MASK | \ + IEEE80211_OFDM_RATE_54MB_MASK) +#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ + IEEE80211_CCK_DEFAULT_RATES_MASK) + +#define IEEE80211_NUM_OFDM_RATES 8 +#define IEEE80211_NUM_CCK_RATES 4 +#define IEEE80211_OFDM_SHIFT_MASK_A 4 + + +/* this is stolen and modified from the madwifi driver*/ +#define IEEE80211_FC0_TYPE_MASK 0x0c +#define IEEE80211_FC0_TYPE_DATA 0x08 +#define IEEE80211_FC0_SUBTYPE_MASK 0xB0 +#define IEEE80211_FC0_SUBTYPE_QOS 0x80 + +#define IEEE80211_QOS_HAS_SEQ(fc) \ + (((fc) & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == \ + (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) + +/* this is stolen from ipw2200 driver */ +#define IEEE_IBSS_MAC_HASH_SIZE 31 +struct ieee_ibss_seq { + u8 mac[ETH_ALEN]; + u16 seq_num[17]; + u16 frag_num[17]; + unsigned long packet_time[17]; + struct list_head list; +}; + +/* NOTE: This data is for statistical purposes; not all hardware provides this + * information for frames received. Not setting these will not cause + * any adverse affects. */ +struct ieee80211_rx_stats { + u32 mac_time[2]; + s8 rssi; + u8 signal; + u8 noise; + u16 rate; /* in 100 kbps */ + u8 received_channel; + u8 control; + u8 mask; + u8 freq; + u16 len; + u64 tsf; + u32 beacon_time; + u8 nic_type; + u16 Length; + // u8 DataRate; // In 0.5 Mbps + u8 SignalQuality; // in 0-100 index. + s32 RecvSignalPower; // Real power in dBm for this packet, no beautification and aggregation. + s8 RxPower; // in dBm Translate from PWdB + u8 SignalStrength; // in 0-100 index. + u16 bHwError:1; + u16 bCRC:1; + u16 bICV:1; + u16 bShortPreamble:1; + u16 Antenna:1; //for rtl8185 + u16 Decrypted:1; //for rtl8185, rtl8187 + u16 Wakeup:1; //for rtl8185 + u16 Reserved0:1; //for rtl8185 + u8 AGC; + u32 TimeStampLow; + u32 TimeStampHigh; + bool bShift; + bool bIsQosData; // Added by Annie, 2005-12-22. + u8 UserPriority; + + //1!!!!!!!!!!!!!!!!!!!!!!!!!!! + //1Attention Please!!!<11n or 8190 specific code should be put below this line> + //1!!!!!!!!!!!!!!!!!!!!!!!!!!! + + u8 RxDrvInfoSize; + u8 RxBufShift; + bool bIsAMPDU; + bool bFirstMPDU; + bool bContainHTC; + bool RxIs40MHzPacket; + u32 RxPWDBAll; + u8 RxMIMOSignalStrength[4]; // in 0~100 index + s8 RxMIMOSignalQuality[2]; + bool bPacketMatchBSSID; + bool bIsCCK; + bool bPacketToSelf; + //added by amy + u8* virtual_address; + u16 packetlength; // Total packet length: Must equal to sum of all FragLength + u16 fraglength; // FragLength should equal to PacketLength in non-fragment case + u16 fragoffset; // Data offset for this fragment + u16 ntotalfrag; + bool bisrxaggrsubframe; + bool bPacketBeacon; //cosa add for rssi + bool bToSelfBA; //cosa add for rssi + char cck_adc_pwdb[4]; //cosa add for rx path selection + u16 Seq_Num; + +}; + +/* IEEE 802.11 requires that STA supports concurrent reception of at least + * three fragmented frames. This define can be increased to support more + * concurrent frames, but it should be noted that each entry can consume about + * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ +#define IEEE80211_FRAG_CACHE_LEN 4 + +struct ieee80211_frag_entry { + unsigned long first_frag_time; + unsigned int seq; + unsigned int last_frag; + struct sk_buff *skb; + u8 src_addr[ETH_ALEN]; + u8 dst_addr[ETH_ALEN]; +}; + +struct ieee80211_stats { + unsigned int tx_unicast_frames; + unsigned int tx_multicast_frames; + unsigned int tx_fragments; + unsigned int tx_unicast_octets; + unsigned int tx_multicast_octets; + unsigned int tx_deferred_transmissions; + unsigned int tx_single_retry_frames; + unsigned int tx_multiple_retry_frames; + unsigned int tx_retry_limit_exceeded; + unsigned int tx_discards; + unsigned int rx_unicast_frames; + unsigned int rx_multicast_frames; + unsigned int rx_fragments; + unsigned int rx_unicast_octets; + unsigned int rx_multicast_octets; + unsigned int rx_fcs_errors; + unsigned int rx_discards_no_buffer; + unsigned int tx_discards_wrong_sa; + unsigned int rx_discards_undecryptable; + unsigned int rx_message_in_msg_fragments; + unsigned int rx_message_in_bad_msg_fragments; +}; + +struct ieee80211_device; + +#include "ieee80211_crypt.h" + +#define SEC_KEY_1 (1<<0) +#define SEC_KEY_2 (1<<1) +#define SEC_KEY_3 (1<<2) +#define SEC_KEY_4 (1<<3) +#define SEC_ACTIVE_KEY (1<<4) +#define SEC_AUTH_MODE (1<<5) +#define SEC_UNICAST_GROUP (1<<6) +#define SEC_LEVEL (1<<7) +#define SEC_ENABLED (1<<8) +#define SEC_ENCRYPT (1<<9) + +#define SEC_LEVEL_0 0 /* None */ +#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */ +#define SEC_LEVEL_2 2 /* Level 1 + TKIP */ +#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */ +#define SEC_LEVEL_3 4 /* Level 2 + CCMP */ + +#define SEC_ALG_NONE 0 +#define SEC_ALG_WEP 1 +#define SEC_ALG_TKIP 2 +#define SEC_ALG_CCMP 3 + +#define WEP_KEYS 4 +#define WEP_KEY_LEN 13 +#define SCM_KEY_LEN 32 +#define SCM_TEMPORAL_KEY_LENGTH 16 + +struct ieee80211_security { + u16 active_key:2, + enabled:1, + auth_mode:2, + auth_algo:4, + unicast_uses_group:1, + encrypt:1; + u8 key_sizes[WEP_KEYS]; + u8 keys[WEP_KEYS][SCM_KEY_LEN]; + u8 level; + u16 flags; +} __attribute__ ((packed)); + + +/* + 802.11 data frame from AP + ,-------------------------------------------------------------------. +Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | + |------|------|---------|---------|---------|------|---------|------| +Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | + | | tion | (BSSID) | | | ence | data | | + `-------------------------------------------------------------------' +Total: 28-2340 bytes +*/ + +/* Management Frame Information Element Types */ +enum ieee80211_mfie { + MFIE_TYPE_SSID = 0, + MFIE_TYPE_RATES = 1, + MFIE_TYPE_FH_SET = 2, + MFIE_TYPE_DS_SET = 3, + MFIE_TYPE_CF_SET = 4, + MFIE_TYPE_TIM = 5, + MFIE_TYPE_IBSS_SET = 6, + MFIE_TYPE_COUNTRY = 7, + MFIE_TYPE_HOP_PARAMS = 8, + MFIE_TYPE_HOP_TABLE = 9, + MFIE_TYPE_REQUEST = 10, + MFIE_TYPE_CHALLENGE = 16, + MFIE_TYPE_POWER_CONSTRAINT = 32, + MFIE_TYPE_POWER_CAPABILITY = 33, + MFIE_TYPE_TPC_REQUEST = 34, + MFIE_TYPE_TPC_REPORT = 35, + MFIE_TYPE_SUPP_CHANNELS = 36, + MFIE_TYPE_CSA = 37, + MFIE_TYPE_MEASURE_REQUEST = 38, + MFIE_TYPE_MEASURE_REPORT = 39, + MFIE_TYPE_QUIET = 40, + MFIE_TYPE_IBSS_DFS = 41, + MFIE_TYPE_ERP = 42, + MFIE_TYPE_RSN = 48, + MFIE_TYPE_RATES_EX = 50, + MFIE_TYPE_HT_CAP= 45, + MFIE_TYPE_HT_INFO= 61, + MFIE_TYPE_AIRONET=133, + MFIE_TYPE_GENERIC = 221, + MFIE_TYPE_QOS_PARAMETER = 222, +}; + +/* Minimal header; can be used for passing 802.11 frames with sufficient + * information to determine what type of underlying data type is actually + * stored in the data. */ +struct ieee80211_hdr { + __le16 frame_ctl; + __le16 duration_id; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_1addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_2addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_3addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_4addr { + __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]; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_3addrqos { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + u8 payload[0]; + __le16 qos_ctl; +} __attribute__ ((packed)); + +struct ieee80211_hdr_4addrqos { + __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]; + u8 payload[0]; + __le16 qos_ctl; +} __attribute__ ((packed)); + +struct ieee80211_info_element { + u8 id; + u8 len; + u8 data[0]; +} __attribute__ ((packed)); + +struct ieee80211_authentication { + struct ieee80211_hdr_3addr header; + __le16 algorithm; + __le16 transaction; + __le16 status; + /*challenge*/ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_disassoc { + struct ieee80211_hdr_3addr header; + __le16 reason; +} __attribute__ ((packed)); + +struct ieee80211_probe_request { + struct ieee80211_hdr_3addr header; + /* SSID, supported rates */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_probe_response { + struct ieee80211_hdr_3addr header; + u32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + /* SSID, supported rates, FH params, DS params, + * CF params, IBSS params, TIM (if beacon), RSN */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +/* Alias beacon for probe_response */ +#define ieee80211_beacon ieee80211_probe_response + +struct ieee80211_assoc_request_frame { + struct ieee80211_hdr_3addr header; + __le16 capability; + __le16 listen_interval; + /* SSID, supported rates, RSN */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_reassoc_request_frame { + struct ieee80211_hdr_3addr header; + __le16 capability; + __le16 listen_interval; + u8 current_ap[ETH_ALEN]; + /* SSID, supported rates, RSN */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_assoc_response_frame { + struct ieee80211_hdr_3addr header; + __le16 capability; + __le16 status; + __le16 aid; + struct ieee80211_info_element info_element[0]; /* supported rates */ +} __attribute__ ((packed)); + +struct ieee80211_txb { + u8 nr_frags; + u8 encrypted; + u8 queue_index; + u8 rts_included; + u16 reserved; + __le16 frag_size; + __le16 payload_size; + struct sk_buff *fragments[0]; +}; + +#define MAX_TX_AGG_COUNT 16 +struct ieee80211_drv_agg_txb { + u8 nr_drv_agg_frames; + struct sk_buff *tx_agg_frames[MAX_TX_AGG_COUNT]; +}__attribute__((packed)); + +#define MAX_SUBFRAME_COUNT 64 +struct ieee80211_rxb { + u8 nr_subframes; + struct sk_buff *subframes[MAX_SUBFRAME_COUNT]; + u8 dst[ETH_ALEN]; + u8 src[ETH_ALEN]; +}__attribute__((packed)); + +typedef union _frameqos { + u16 shortdata; + u8 chardata[2]; + struct { + u16 tid:4; + u16 eosp:1; + u16 ack_policy:2; + u16 reserved:1; + u16 txop:8; + }field; +}frameqos,*pframeqos; + +/* SWEEP TABLE ENTRIES NUMBER*/ +#define MAX_SWEEP_TAB_ENTRIES 42 +#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7 +/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs + * only use 8, and then use extended rates for the remaining supported + * rates. Other APs, however, stick all of their supported rates on the + * main rates information element... */ +#define MAX_RATES_LENGTH ((u8)12) +#define MAX_RATES_EX_LENGTH ((u8)16) +#define MAX_NETWORK_COUNT 128 + +#define MAX_CHANNEL_NUMBER 161 +#define IEEE80211_SOFTMAC_SCAN_TIME 100 +//(HZ / 2) +#define IEEE80211_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2) + +#define CRC_LENGTH 4U + +#define MAX_WPA_IE_LEN 64 + +#define NETWORK_EMPTY_ESSID (1<<0) +#define NETWORK_HAS_OFDM (1<<1) +#define NETWORK_HAS_CCK (1<<2) + +/* QoS structure */ +#define NETWORK_HAS_QOS_PARAMETERS (1<<3) +#define NETWORK_HAS_QOS_INFORMATION (1<<4) +#define NETWORK_HAS_QOS_MASK (NETWORK_HAS_QOS_PARAMETERS | \ + NETWORK_HAS_QOS_INFORMATION) +/* 802.11h */ +#define NETWORK_HAS_POWER_CONSTRAINT (1<<5) +#define NETWORK_HAS_CSA (1<<6) +#define NETWORK_HAS_QUIET (1<<7) +#define NETWORK_HAS_IBSS_DFS (1<<8) +#define NETWORK_HAS_TPC_REPORT (1<<9) + +#define NETWORK_HAS_ERP_VALUE (1<<10) + +#define QOS_QUEUE_NUM 4 +#define QOS_OUI_LEN 3 +#define QOS_OUI_TYPE 2 +#define QOS_ELEMENT_ID 221 +#define QOS_OUI_INFO_SUB_TYPE 0 +#define QOS_OUI_PARAM_SUB_TYPE 1 +#define QOS_VERSION_1 1 +#define QOS_AIFSN_MIN_VALUE 2 +struct ieee80211_qos_information_element { + u8 elementID; + u8 length; + u8 qui[QOS_OUI_LEN]; + u8 qui_type; + u8 qui_subtype; + u8 version; + u8 ac_info; +} __attribute__ ((packed)); + +struct ieee80211_qos_ac_parameter { + u8 aci_aifsn; + u8 ecw_min_max; + __le16 tx_op_limit; +} __attribute__ ((packed)); + +struct ieee80211_qos_parameter_info { + struct ieee80211_qos_information_element info_element; + u8 reserved; + struct ieee80211_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM]; +} __attribute__ ((packed)); + +struct ieee80211_qos_parameters { + __le16 cw_min[QOS_QUEUE_NUM]; + __le16 cw_max[QOS_QUEUE_NUM]; + u8 aifs[QOS_QUEUE_NUM]; + u8 flag[QOS_QUEUE_NUM]; + __le16 tx_op_limit[QOS_QUEUE_NUM]; +} __attribute__ ((packed)); + +struct ieee80211_qos_data { + struct ieee80211_qos_parameters parameters; + int active; + int supported; + u8 param_count; + u8 old_param_count; +}; + +struct ieee80211_tim_parameters { + u8 tim_count; + u8 tim_period; +} __attribute__ ((packed)); + +//#else +struct ieee80211_wmm_ac_param { + u8 ac_aci_acm_aifsn; + u8 ac_ecwmin_ecwmax; + u16 ac_txop_limit; +}; + +struct ieee80211_wmm_ts_info { + u8 ac_dir_tid; + u8 ac_up_psb; + u8 reserved; +} __attribute__ ((packed)); + +struct ieee80211_wmm_tspec_elem { + struct ieee80211_wmm_ts_info ts_info; + u16 norm_msdu_size; + u16 max_msdu_size; + u32 min_serv_inter; + u32 max_serv_inter; + u32 inact_inter; + u32 suspen_inter; + u32 serv_start_time; + u32 min_data_rate; + u32 mean_data_rate; + u32 peak_data_rate; + u32 max_burst_size; + u32 delay_bound; + u32 min_phy_rate; + u16 surp_band_allow; + u16 medium_time; +}__attribute__((packed)); +enum eap_type { + EAP_PACKET = 0, + EAPOL_START, + EAPOL_LOGOFF, + EAPOL_KEY, + EAPOL_ENCAP_ASF_ALERT +}; + +static const char *eap_types[] = { + [EAP_PACKET] = "EAP-Packet", + [EAPOL_START] = "EAPOL-Start", + [EAPOL_LOGOFF] = "EAPOL-Logoff", + [EAPOL_KEY] = "EAPOL-Key", + [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert" +}; + +static inline const char *eap_get_type(int type) +{ + return ((u32)type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type]; +} +//added by amy for reorder +static inline u8 Frame_QoSTID(u8* buf) +{ + struct ieee80211_hdr_3addr *hdr; + u16 fc; + hdr = (struct ieee80211_hdr_3addr *)buf; + fc = le16_to_cpu(hdr->frame_ctl); + return (u8)((frameqos*)(buf + (((fc & IEEE80211_FCTL_TODS)&&(fc & IEEE80211_FCTL_FROMDS))? 30 : 24)))->field.tid; +} + +//added by amy for reorder + +struct eapol { + u8 snap[6]; + u16 ethertype; + u8 version; + u8 type; + u16 length; +} __attribute__ ((packed)); + +struct ieee80211_softmac_stats{ + unsigned int rx_ass_ok; + unsigned int rx_ass_err; + unsigned int rx_probe_rq; + unsigned int tx_probe_rs; + unsigned int tx_beacons; + unsigned int rx_auth_rq; + unsigned int rx_auth_rs_ok; + unsigned int rx_auth_rs_err; + unsigned int tx_auth_rq; + unsigned int no_auth_rs; + unsigned int no_ass_rs; + unsigned int tx_ass_rq; + unsigned int rx_ass_rq; + unsigned int tx_probe_rq; + unsigned int reassoc; + unsigned int swtxstop; + unsigned int swtxawake; + unsigned char CurrentShowTxate; + unsigned char last_packet_rate; + unsigned int txretrycount; +}; + +#define BEACON_PROBE_SSID_ID_POSITION 12 + +struct ieee80211_info_element_hdr { + u8 id; + u8 len; +} __attribute__ ((packed)); + +/* + * These are the data types that can make up management packets + * + u16 auth_algorithm; + u16 auth_sequence; + u16 beacon_interval; + u16 capability; + u8 current_ap[ETH_ALEN]; + u16 listen_interval; + struct { + u16 association_id:14, reserved:2; + } __attribute__ ((packed)); + u32 time_stamp[2]; + u16 reason; + u16 status; +*/ + +#define IEEE80211_DEFAULT_TX_ESSID "Penguin" +#define IEEE80211_DEFAULT_BASIC_RATE 2 //1Mbps + +enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame}; +#define MAX_SP_Len (WMM_all_frame << 4) +#define IEEE80211_QOS_TID 0x0f +#define QOS_CTL_NOTCONTAIN_ACK (0x01 << 5) + +#define IEEE80211_DTIM_MBCAST 4 +#define IEEE80211_DTIM_UCAST 2 +#define IEEE80211_DTIM_VALID 1 +#define IEEE80211_DTIM_INVALID 0 + +#define IEEE80211_PS_DISABLED 0 +#define IEEE80211_PS_UNICAST IEEE80211_DTIM_UCAST +#define IEEE80211_PS_MBCAST IEEE80211_DTIM_MBCAST + +//added by David for QoS 2006/6/30 +//#define WMM_Hang_8187 +#ifdef WMM_Hang_8187 +#undef WMM_Hang_8187 +#endif + +#define WME_AC_BK 0x00 +#define WME_AC_BE 0x01 +#define WME_AC_VI 0x02 +#define WME_AC_VO 0x03 +#define WME_ACI_MASK 0x03 +#define WME_AIFSN_MASK 0x03 +#define WME_AC_PRAM_LEN 16 + +#define MAX_RECEIVE_BUFFER_SIZE 9100 + +//UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP +//#define UP2AC(up) ((up<3) ? ((up==0)?1:0) : (up>>1)) +#define UP2AC(up) ( \ + ((up) < 1) ? WME_AC_BE : \ + ((up) < 3) ? WME_AC_BK : \ + ((up) < 4) ? WME_AC_BE : \ + ((up) < 6) ? WME_AC_VI : \ + WME_AC_VO) +//AC Mapping to UP, using in Tx part for selecting the corresponding TX queue +#define AC2UP(_ac) ( \ + ((_ac) == WME_AC_VO) ? 6 : \ + ((_ac) == WME_AC_VI) ? 5 : \ + ((_ac) == WME_AC_BK) ? 1 : \ + 0) + +#define ETHER_ADDR_LEN 6 /* length of an Ethernet address */ +#define ETHERNET_HEADER_SIZE 14 /* length of two Ethernet address plus ether type*/ + +struct ether_header { + u8 ether_dhost[ETHER_ADDR_LEN]; + u8 ether_shost[ETHER_ADDR_LEN]; + u16 ether_type; +} __attribute__((packed)); + +#ifndef ETHERTYPE_PAE +#define ETHERTYPE_PAE 0x888e /* EAPOL PAE/802.1x */ +#endif +#ifndef ETHERTYPE_IP +#define ETHERTYPE_IP 0x0800 /* IP protocol */ +#endif + +typedef struct _bss_ht{ + + bool support_ht; + + // HT related elements + u8 ht_cap_buf[32]; + u16 ht_cap_len; + u8 ht_info_buf[32]; + u16 ht_info_len; + + HT_SPEC_VER ht_spec_ver; + //HT_CAPABILITY_ELE bdHTCapEle; + //HT_INFORMATION_ELE bdHTInfoEle; + + bool aggregation; + bool long_slot_time; +}bss_ht, *pbss_ht; + +typedef enum _erp_t{ + ERP_NonERPpresent = 0x01, + ERP_UseProtection = 0x02, + ERP_BarkerPreambleMode = 0x04, +} erp_t; + + +struct ieee80211_network { + /* These entries are used to identify a unique network */ + u8 bssid[ETH_ALEN]; + u8 channel; + /* Ensure null-terminated for any debug msgs */ + u8 ssid[IW_ESSID_MAX_SIZE + 1]; + u8 ssid_len; + struct ieee80211_qos_data qos_data; + //added by amy for LEAP + bool bWithAironetIE; + bool bCkipSupported; + bool bCcxRmEnable; + u16 CcxRmState[2]; + // CCXv4 S59, MBSSID. + bool bMBssidValid; + u8 MBssidMask; + u8 MBssid[6]; + // CCX 2 S38, WLAN Device Version Number element. Annie, 2006-08-20. + bool bWithCcxVerNum; + u8 BssCcxVerNumber; + /* These are network statistics */ + struct ieee80211_rx_stats stats; + u16 capability; + u8 rates[MAX_RATES_LENGTH]; + u8 rates_len; + u8 rates_ex[MAX_RATES_EX_LENGTH]; + u8 rates_ex_len; + unsigned long last_scanned; + u8 mode; + u32 flags; + u32 last_associate; + u32 time_stamp[2]; + u16 beacon_interval; + u16 listen_interval; + u16 atim_window; + u8 erp_value; + u8 wpa_ie[MAX_WPA_IE_LEN]; + size_t wpa_ie_len; + u8 rsn_ie[MAX_WPA_IE_LEN]; + size_t rsn_ie_len; + + struct ieee80211_tim_parameters tim; + u8 dtim_period; + u8 dtim_data; + u32 last_dtim_sta_time[2]; + + //appeded for QoS + u8 wmm_info; + struct ieee80211_wmm_ac_param wmm_param[4]; + u8 QoS_Enable; +#ifdef THOMAS_TURBO + u8 Turbo_Enable;//enable turbo mode, added by thomas +#endif +#ifdef ENABLE_DOT11D + u16 CountryIeLen; + u8 CountryIeBuf[MAX_IE_LEN]; +#endif + // HT Related, by amy, 2008.04.29 + BSS_HT bssht; + // Add to handle broadcom AP management frame CCK rate. + bool broadcom_cap_exist; + bool ralink_cap_exist; + bool atheros_cap_exist; + bool cisco_cap_exist; + bool unknown_cap_exist; +// u8 berp_info; + bool berp_info_valid; + bool buseprotection; + //put at the end of the structure. + struct list_head list; +}; + +enum ieee80211_state { + + /* the card is not linked at all */ + IEEE80211_NOLINK = 0, + + /* IEEE80211_ASSOCIATING* are for BSS client mode + * the driver shall not perform RX filtering unless + * the state is LINKED. + * The driver shall just check for the state LINKED and + * defaults to NOLINK for ALL the other states (including + * LINKED_SCANNING) + */ + + /* the association procedure will start (wq scheduling)*/ + IEEE80211_ASSOCIATING, + IEEE80211_ASSOCIATING_RETRY, + + /* the association procedure is sending AUTH request*/ + IEEE80211_ASSOCIATING_AUTHENTICATING, + + /* the association procedure has successfully authentcated + * and is sending association request + */ + IEEE80211_ASSOCIATING_AUTHENTICATED, + + /* the link is ok. the card associated to a BSS or linked + * to a ibss cell or acting as an AP and creating the bss + */ + IEEE80211_LINKED, + + /* same as LINKED, but the driver shall apply RX filter + * rules as we are in NO_LINK mode. As the card is still + * logically linked, but it is doing a syncro site survey + * then it will be back to LINKED state. + */ + IEEE80211_LINKED_SCANNING, + +}; + +#define DEFAULT_MAX_SCAN_AGE (15 * HZ) +#define DEFAULT_FTS 2346 + +#define CFG_IEEE80211_RESERVE_FCS (1<<0) +#define CFG_IEEE80211_COMPUTE_FCS (1<<1) +#define CFG_IEEE80211_RTS (1<<2) + +#define IEEE80211_24GHZ_MIN_CHANNEL 1 +#define IEEE80211_24GHZ_MAX_CHANNEL 14 +#define IEEE80211_24GHZ_CHANNELS (IEEE80211_24GHZ_MAX_CHANNEL - \ + IEEE80211_24GHZ_MIN_CHANNEL + 1) + +#define IEEE80211_52GHZ_MIN_CHANNEL 34 +#define IEEE80211_52GHZ_MAX_CHANNEL 165 +#define IEEE80211_52GHZ_CHANNELS (IEEE80211_52GHZ_MAX_CHANNEL - \ + IEEE80211_52GHZ_MIN_CHANNEL + 1) + + + +typedef struct tx_pending_t{ + int frag; + struct ieee80211_txb *txb; +}tx_pending_t; + +typedef struct _bandwidth_autoswitch +{ + long threshold_20Mhzto40Mhz; + long threshold_40Mhzto20Mhz; + bool bforced_tx20Mhz; + bool bautoswitch_enable; +}bandwidth_autoswitch,*pbandwidth_autoswitch; + + +//added by amy for order + +#define REORDER_WIN_SIZE 128 +#define REORDER_ENTRY_NUM 128 +typedef struct _RX_REORDER_ENTRY +{ + struct list_head List; + u16 SeqNum; + struct ieee80211_rxb* prxb; +} RX_REORDER_ENTRY, *PRX_REORDER_ENTRY; +//added by amy for order +typedef enum _Fsync_State{ + Default_Fsync, + HW_Fsync, + SW_Fsync +}Fsync_State; + +// Power save mode configured. +typedef enum _RT_PS_MODE +{ + eActive, // Active/Continuous access. + eMaxPs, // Max power save mode. + eFastPs // Fast power save mode. +}RT_PS_MODE; + +typedef enum _IPS_CALLBACK_FUNCION +{ + IPS_CALLBACK_NONE = 0, + IPS_CALLBACK_MGNT_LINK_REQUEST = 1, + IPS_CALLBACK_JOIN_REQUEST = 2, +}IPS_CALLBACK_FUNCION; + +typedef enum _RT_JOIN_ACTION{ + RT_JOIN_INFRA = 1, + RT_JOIN_IBSS = 2, + RT_START_IBSS = 3, + RT_NO_ACTION = 4, +}RT_JOIN_ACTION; + +typedef struct _IbssParms{ + u16 atimWin; +}IbssParms, *PIbssParms; +#define MAX_NUM_RATES 264 // Max num of support rates element: 8, Max num of ext. support rate: 255. 061122, by rcnjko. + +// RF state. +typedef enum _RT_RF_POWER_STATE +{ + eRfOn, + eRfSleep, + eRfOff +}RT_RF_POWER_STATE; + +typedef struct _RT_POWER_SAVE_CONTROL +{ + + // + // Inactive Power Save(IPS) : Disable RF when disconnected + // + bool bInactivePs; + bool bIPSModeBackup; + bool bSwRfProcessing; + RT_RF_POWER_STATE eInactivePowerState; + struct work_struct InactivePsWorkItem; + struct timer_list InactivePsTimer; + + // Return point for join action + IPS_CALLBACK_FUNCION ReturnPoint; + + // Recored Parameters for rescheduled JoinRequest + bool bTmpBssDesc; + RT_JOIN_ACTION tmpJoinAction; + struct ieee80211_network tmpBssDesc; + + // Recored Parameters for rescheduled MgntLinkRequest + bool bTmpScanOnly; + bool bTmpActiveScan; + bool bTmpFilterHiddenAP; + bool bTmpUpdateParms; + u8 tmpSsidBuf[33]; + OCTET_STRING tmpSsid2Scan; + bool bTmpSsid2Scan; + u8 tmpNetworkType; + u8 tmpChannelNumber; + u16 tmpBcnPeriod; + u8 tmpDtimPeriod; + u16 tmpmCap; + OCTET_STRING tmpSuppRateSet; + u8 tmpSuppRateBuf[MAX_NUM_RATES]; + bool bTmpSuppRate; + IbssParms tmpIbpm; + bool bTmpIbpm; + + // + // Leisre Poswer Save : Disable RF if connected but traffic is not busy + // + bool bLeisurePs; + +}RT_POWER_SAVE_CONTROL,*PRT_POWER_SAVE_CONTROL; + +typedef u32 RT_RF_CHANGE_SOURCE; +#define RF_CHANGE_BY_SW BIT31 +#define RF_CHANGE_BY_HW BIT30 +#define RF_CHANGE_BY_PS BIT29 +#define RF_CHANGE_BY_IPS BIT28 +#define RF_CHANGE_BY_INIT 0 // Do not change the RFOff reason. Defined by Bruce, 2008-01-17. + +#ifdef ENABLE_DOT11D +typedef enum +{ + COUNTRY_CODE_FCC = 0, + COUNTRY_CODE_IC = 1, + COUNTRY_CODE_ETSI = 2, + COUNTRY_CODE_SPAIN = 3, + COUNTRY_CODE_FRANCE = 4, + COUNTRY_CODE_MKK = 5, + COUNTRY_CODE_MKK1 = 6, + COUNTRY_CODE_ISRAEL = 7, + COUNTRY_CODE_TELEC, + COUNTRY_CODE_MIC, + COUNTRY_CODE_GLOBAL_DOMAIN +}country_code_type_t; +#endif + +#define RT_MAX_LD_SLOT_NUM 10 +typedef struct _RT_LINK_DETECT_T{ + + u32 NumRecvBcnInPeriod; + u32 NumRecvDataInPeriod; + + u32 RxBcnNum[RT_MAX_LD_SLOT_NUM]; // number of Rx beacon / CheckForHang_period to determine link status + u32 RxDataNum[RT_MAX_LD_SLOT_NUM]; // number of Rx data / CheckForHang_period to determine link status + u16 SlotNum; // number of CheckForHang period to determine link status + u16 SlotIndex; + + u32 NumTxOkInPeriod; + u32 NumRxOkInPeriod; + bool bBusyTraffic; +}RT_LINK_DETECT_T, *PRT_LINK_DETECT_T; + + +struct ieee80211_device { + struct net_device *dev; + struct ieee80211_security sec; + + //hw security related +// u8 hwsec_support; //support? + u8 hwsec_active; //hw security active. + bool is_silent_reset; + bool ieee_up; + //added by amy + bool bSupportRemoteWakeUp; + RT_PS_MODE dot11PowerSaveMode; // Power save mode configured. + bool actscanning; + bool beinretry; + RT_RF_POWER_STATE eRFPowerState; + RT_RF_CHANGE_SOURCE RfOffReason; + bool is_set_key; + //11n spec related I wonder if These info structure need to be moved out of ieee80211_device + + //11n HT below + PRT_HIGH_THROUGHPUT pHTInfo; + //struct timer_list SwBwTimer; +// spinlock_t chnlop_spinlock; + spinlock_t bw_spinlock; + + spinlock_t reorder_spinlock; + // for HT operation rate set. we use this one for HT data rate to seperate different descriptors + //the way fill this is the same as in the IE + u8 Regdot11HTOperationalRateSet[16]; //use RATR format + u8 dot11HTOperationalRateSet[16]; //use RATR format + u8 RegHTSuppRateSet[16]; + u8 HTCurrentOperaRate; + u8 HTHighestOperaRate; + //wb added for rate operation mode to firmware + u8 bTxDisableRateFallBack; + u8 bTxUseDriverAssingedRate; + atomic_t atm_chnlop; + atomic_t atm_swbw; +// u8 HTHighestOperaRate; +// u8 HTCurrentOperaRate; + + // 802.11e and WMM Traffic Stream Info (TX) + struct list_head Tx_TS_Admit_List; + struct list_head Tx_TS_Pending_List; + struct list_head Tx_TS_Unused_List; + TX_TS_RECORD TxTsRecord[TOTAL_TS_NUM]; + // 802.11e and WMM Traffic Stream Info (RX) + struct list_head Rx_TS_Admit_List; + struct list_head Rx_TS_Pending_List; + struct list_head Rx_TS_Unused_List; + RX_TS_RECORD RxTsRecord[TOTAL_TS_NUM]; +//#ifdef TO_DO_LIST + RX_REORDER_ENTRY RxReorderEntry[128]; + struct list_head RxReorder_Unused_List; +//#endif + // Qos related. Added by Annie, 2005-11-01. +// PSTA_QOS pStaQos; + u8 ForcedPriority; // Force per-packet priority 1~7. (default: 0, not to force it.) + + + /* Bookkeeping structures */ + struct net_device_stats stats; + struct ieee80211_stats ieee_stats; + struct ieee80211_softmac_stats softmac_stats; + + /* Probe / Beacon management */ + struct list_head network_free_list; + struct list_head network_list; + struct ieee80211_network *networks; + int scans; + int scan_age; + + int iw_mode; /* operating mode (IW_MODE_*) */ + struct iw_spy_data spy_data; + + spinlock_t lock; + spinlock_t wpax_suitlist_lock; + + int tx_headroom; /* Set to size of any additional room needed at front + * of allocated Tx SKBs */ + u32 config; + + /* WEP and other encryption related settings at the device level */ + int open_wep; /* Set to 1 to allow unencrypted frames */ + int auth_mode; + int reset_on_keychange; /* Set to 1 if the HW needs to be reset on + * WEP key changes */ + + /* If the host performs {en,de}cryption, then set to 1 */ + int host_encrypt; + int host_encrypt_msdu; + int host_decrypt; + /* host performs multicast decryption */ + int host_mc_decrypt; + + /* host should strip IV and ICV from protected frames */ + /* meaningful only when hardware decryption is being used */ + int host_strip_iv_icv; + + int host_open_frag; + int host_build_iv; + int ieee802_1x; /* is IEEE 802.1X used */ + + /* WPA data */ + bool bHalfWirelessN24GMode; + int wpa_enabled; + int drop_unencrypted; + int tkip_countermeasures; + int privacy_invoked; + size_t wpa_ie_len; + u8 *wpa_ie; + u8 ap_mac_addr[6]; + u16 pairwise_key_type; + u16 group_key_type; + struct list_head crypt_deinit_list; + struct ieee80211_crypt_data *crypt[WEP_KEYS]; + int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */ + struct timer_list crypt_deinit_timer; + int crypt_quiesced; + + int bcrx_sta_key; /* use individual keys to override default keys even + * with RX of broad/multicast frames */ + + /* Fragmentation structures */ + // each streaming contain a entry + struct ieee80211_frag_entry frag_cache[17][IEEE80211_FRAG_CACHE_LEN]; + unsigned int frag_next_idx[17]; + u16 fts; /* Fragmentation Threshold */ +#define DEFAULT_RTS_THRESHOLD 2346U +#define MIN_RTS_THRESHOLD 1 +#define MAX_RTS_THRESHOLD 2346U + u16 rts; /* RTS threshold */ + + /* Association info */ + u8 bssid[ETH_ALEN]; + + /* This stores infos for the current network. + * Either the network we are associated in INFRASTRUCTURE + * or the network that we are creating in MASTER mode. + * ad-hoc is a mixture ;-). + * Note that in infrastructure mode, even when not associated, + * fields bssid and essid may be valid (if wpa_set and essid_set + * are true) as thy carry the value set by the user via iwconfig + */ + struct ieee80211_network current_network; + + enum ieee80211_state state; + + int short_slot; + int reg_mode; + int mode; /* A, B, G */ + int modulation; /* CCK, OFDM */ + int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */ + int abg_true; /* ABG flag */ + + /* used for forcing the ibss workqueue to terminate + * without wait for the syncro scan to terminate + */ + short sync_scan_hurryup; + + int perfect_rssi; + int worst_rssi; + + u16 prev_seq_ctl; /* used to drop duplicate frames */ + + /* map of allowed channels. 0 is dummy */ + // FIXME: remeber to default to a basic channel plan depending of the PHY type +#ifdef ENABLE_DOT11D + void* pDot11dInfo; + bool bGlobalDomain; +#else + int channel_map[MAX_CHANNEL_NUMBER+1]; +#endif + int rate; /* current rate */ + int basic_rate; + //FIXME: pleace callback, see if redundant with softmac_features + short active_scan; + + /* this contains flags for selectively enable softmac support */ + u16 softmac_features; + + /* if the sequence control field is not filled by HW */ + u16 seq_ctrl[5]; + + /* association procedure transaction sequence number */ + u16 associate_seq; + + /* AID for RTXed association responses */ + u16 assoc_id; + + /* power save mode related*/ + short ps; + short sta_sleep; + int ps_timeout; + int ps_period; + struct tasklet_struct ps_task; + u32 ps_th; + u32 ps_tl; + + short raw_tx; + /* used if IEEE_SOFTMAC_TX_QUEUE is set */ + short queue_stop; + short scanning; + short proto_started; + + struct semaphore wx_sem; + struct semaphore scan_sem; + + spinlock_t mgmt_tx_lock; + spinlock_t beacon_lock; + + short beacon_txing; + + short wap_set; + short ssid_set; + + u8 wpax_type_set; //{added by David, 2006.9.28} + u32 wpax_type_notify; //{added by David, 2006.9.26} + + /* QoS related flag */ + char init_wmmparam_flag; + /* set on initialization */ + u8 qos_support; + + /* for discarding duplicated packets in IBSS */ + struct list_head ibss_mac_hash[IEEE_IBSS_MAC_HASH_SIZE]; + + /* for discarding duplicated packets in BSS */ + u16 last_rxseq_num[17]; /* rx seq previous per-tid */ + u16 last_rxfrag_num[17];/* tx frag previous per-tid */ + unsigned long last_packet_time[17]; + + /* for PS mode */ + unsigned long last_rx_ps_time; + + /* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */ + struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM]; + int mgmt_queue_head; + int mgmt_queue_tail; +//{ added for rtl819x +#define IEEE80211_QUEUE_LIMIT 128 + u8 AsocRetryCount; + unsigned int hw_header; + struct sk_buff_head skb_waitQ[MAX_QUEUE_SIZE]; + struct sk_buff_head skb_aggQ[MAX_QUEUE_SIZE]; + struct sk_buff_head skb_drv_aggQ[MAX_QUEUE_SIZE]; + u32 sta_edca_param[4]; + bool aggregation; + // Enable/Disable Rx immediate BA capability. + bool enable_rx_imm_BA; + bool bibsscoordinator; + + //+by amy for DM ,080515 + //Dynamic Tx power for near/far range enable/Disable , by amy , 2008-05-15 + bool bdynamic_txpower_enable; + + bool bCTSToSelfEnable; + u8 CTSToSelfTH; + + u32 fsync_time_interval; + u32 fsync_rate_bitmap; + u8 fsync_rssi_threshold; + bool bfsync_enable; + + u8 fsync_multiple_timeinterval; // FsyncMultipleTimeInterval * FsyncTimeInterval + u32 fsync_firstdiff_ratethreshold; // low threshold + u32 fsync_seconddiff_ratethreshold; // decrease threshold + Fsync_State fsync_state; + bool bis_any_nonbepkts; + //20Mhz 40Mhz AutoSwitch Threshold + bandwidth_autoswitch bandwidth_auto_switch; + //for txpower tracking + bool FwRWRF; + + //added by amy for AP roaming + RT_LINK_DETECT_T LinkDetectInfo; + //added by amy for ps + RT_POWER_SAVE_CONTROL PowerSaveControl; +//} + /* used if IEEE_SOFTMAC_TX_QUEUE is set */ + struct tx_pending_t tx_pending; + + /* used if IEEE_SOFTMAC_ASSOCIATE is set */ + struct timer_list associate_timer; + + /* used if IEEE_SOFTMAC_BEACONS is set */ + struct timer_list beacon_timer; + struct work_struct associate_complete_wq; + struct work_struct associate_procedure_wq; + struct delayed_work softmac_scan_wq; + struct delayed_work associate_retry_wq; + struct delayed_work start_ibss_wq; + struct work_struct wx_sync_scan_wq; + struct workqueue_struct *wq; + // Qos related. Added by Annie, 2005-11-01. + //STA_QOS StaQos; + + //u32 STA_EDCA_PARAM[4]; + //CHANNEL_ACCESS_SETTING ChannelAccessSetting; + + + /* Callback functions */ + void (*set_security)(struct net_device *dev, + struct ieee80211_security *sec); + + /* Used to TX data frame by using txb structs. + * this is not used if in the softmac_features + * is set the flag IEEE_SOFTMAC_TX_QUEUE + */ + int (*hard_start_xmit)(struct ieee80211_txb *txb, + struct net_device *dev); + + int (*reset_port)(struct net_device *dev); + int (*is_queue_full) (struct net_device * dev, int pri); + + int (*handle_management) (struct net_device * dev, + struct ieee80211_network * network, u16 type); + int (*is_qos_active) (struct net_device *dev, struct sk_buff *skb); + + /* Softmac-generated frames (mamagement) are TXed via this + * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is + * not set. As some cards may have different HW queues that + * one might want to use for data and management frames + * the option to have two callbacks might be useful. + * This fucntion can't sleep. + */ + int (*softmac_hard_start_xmit)(struct sk_buff *skb, + struct net_device *dev); + + /* used instead of hard_start_xmit (not softmac_hard_start_xmit) + * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data + * frames. I the option IEEE_SOFTMAC_SINGLE_QUEUE is also set + * then also management frames are sent via this callback. + * This function can't sleep. + */ + void (*softmac_data_hard_start_xmit)(struct sk_buff *skb, + struct net_device *dev,int rate); + + /* stops the HW queue for DATA frames. Useful to avoid + * waste time to TX data frame when we are reassociating + * This function can sleep. + */ + void (*data_hard_stop)(struct net_device *dev); + + /* OK this is complementar to data_poll_hard_stop */ + void (*data_hard_resume)(struct net_device *dev); + + /* ask to the driver to retune the radio . + * This function can sleep. the driver should ensure + * the radio has been swithced before return. + */ + void (*set_chan)(struct net_device *dev,short ch); + + /* These are not used if the ieee stack takes care of + * scanning (IEEE_SOFTMAC_SCAN feature set). + * In this case only the set_chan is used. + * + * The syncro version is similar to the start_scan but + * does not return until all channels has been scanned. + * this is called in user context and should sleep, + * it is called in a work_queue when swithcing to ad-hoc mode + * or in behalf of iwlist scan when the card is associated + * and root user ask for a scan. + * the fucntion stop_scan should stop both the syncro and + * background scanning and can sleep. + * The fucntion start_scan should initiate the background + * scanning and can't sleep. + */ + void (*scan_syncro)(struct net_device *dev); + void (*start_scan)(struct net_device *dev); + void (*stop_scan)(struct net_device *dev); + + /* indicate the driver that the link state is changed + * for example it may indicate the card is associated now. + * Driver might be interested in this to apply RX filter + * rules or simply light the LINK led + */ + void (*link_change)(struct net_device *dev); + + /* these two function indicates to the HW when to start + * and stop to send beacons. This is used when the + * IEEE_SOFTMAC_BEACONS is not set. For now the + * stop_send_bacons is NOT guaranteed to be called only + * after start_send_beacons. + */ + void (*start_send_beacons) (struct net_device *dev,u16 tx_rate); + void (*stop_send_beacons) (struct net_device *dev); + + /* power save mode related */ + void (*sta_wake_up) (struct net_device *dev); + void (*ps_request_tx_ack) (struct net_device *dev); + void (*enter_sleep_state) (struct net_device *dev, u32 th, u32 tl); + short (*ps_is_queue_empty) (struct net_device *dev); + int (*handle_beacon) (struct net_device * dev, struct ieee80211_beacon * beacon, struct ieee80211_network * network); + int (*handle_assoc_response) (struct net_device * dev, struct ieee80211_assoc_response_frame * resp, struct ieee80211_network * network); + + + /* check whether Tx hw resouce available */ + short (*check_nic_enough_desc)(struct net_device *dev, int queue_index); + //added by wb for HT related +// void (*SwChnlByTimerHandler)(struct net_device *dev, int channel); + void (*SetBWModeHandler)(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset); +// void (*UpdateHalRATRTableHandler)(struct net_device* dev, u8* pMcsRate); + bool (*GetNmodeSupportBySecCfg)(struct net_device* dev); + void (*SetWirelessMode)(struct net_device* dev, u8 wireless_mode); + bool (*GetHalfNmodeSupportByAPsHandler)(struct net_device* dev); + void (*InitialGainHandler)(struct net_device *dev, u8 Operation); + + /* This must be the last item so that it points to the data + * allocated beyond this structure by alloc_ieee80211 */ + u8 priv[0]; +}; + +#define IEEE_A (1<<0) +#define IEEE_B (1<<1) +#define IEEE_G (1<<2) +#define IEEE_N_24G (1<<4) +#define IEEE_N_5G (1<<5) +#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G) + +/* Generate a 802.11 header */ + +/* Uses the channel change callback directly + * instead of [start/stop] scan callbacks + */ +#define IEEE_SOFTMAC_SCAN (1<<2) + +/* Perform authentication and association handshake */ +#define IEEE_SOFTMAC_ASSOCIATE (1<<3) + +/* Generate probe requests */ +#define IEEE_SOFTMAC_PROBERQ (1<<4) + +/* Generate respones to probe requests */ +#define IEEE_SOFTMAC_PROBERS (1<<5) + +/* The ieee802.11 stack will manages the netif queue + * wake/stop for the driver, taking care of 802.11 + * fragmentation. See softmac.c for details. */ +#define IEEE_SOFTMAC_TX_QUEUE (1<<7) + +/* Uses only the softmac_data_hard_start_xmit + * even for TX management frames. + */ +#define IEEE_SOFTMAC_SINGLE_QUEUE (1<<8) + +/* Generate beacons. The stack will enqueue beacons + * to the card + */ +#define IEEE_SOFTMAC_BEACONS (1<<6) + +static inline void *ieee80211_priv(struct net_device *dev) +{ + return ((struct ieee80211_device *)netdev_priv(dev))->priv; +} + +extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len) +{ + /* Single white space is for Linksys APs */ + if (essid_len == 1 && essid[0] == ' ') + return 1; + + /* Otherwise, if the entire essid is 0, we assume it is hidden */ + while (essid_len) { + essid_len--; + if (essid[essid_len] != '\0') + return 0; + } + + return 1; +} + +extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode) +{ + /* + * It is possible for both access points and our device to support + * combinations of modes, so as long as there is one valid combination + * of ap/device supported modes, then return success + * + */ + if ((mode & IEEE_A) && + (ieee->modulation & IEEE80211_OFDM_MODULATION) && + (ieee->freq_band & IEEE80211_52GHZ_BAND)) + return 1; + + if ((mode & IEEE_G) && + (ieee->modulation & IEEE80211_OFDM_MODULATION) && + (ieee->freq_band & IEEE80211_24GHZ_BAND)) + return 1; + + if ((mode & IEEE_B) && + (ieee->modulation & IEEE80211_CCK_MODULATION) && + (ieee->freq_band & IEEE80211_24GHZ_BAND)) + return 1; + + return 0; +} + +extern inline int ieee80211_get_hdrlen(u16 fc) +{ + int hdrlen = IEEE80211_3ADDR_LEN; + + switch (WLAN_FC_GET_TYPE(fc)) { + case IEEE80211_FTYPE_DATA: + if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) + hdrlen = IEEE80211_4ADDR_LEN; /* Addr4 */ + if(IEEE80211_QOS_HAS_SEQ(fc)) + hdrlen += 2; /* QOS ctrl*/ + break; + case IEEE80211_FTYPE_CTL: + switch (WLAN_FC_GET_STYPE(fc)) { + case IEEE80211_STYPE_CTS: + case IEEE80211_STYPE_ACK: + hdrlen = IEEE80211_1ADDR_LEN; + break; + default: + hdrlen = IEEE80211_2ADDR_LEN; + break; + } + break; + } + + return hdrlen; +} + +static inline u8 *ieee80211_get_payload(struct ieee80211_hdr *hdr) +{ + switch (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl))) { + case IEEE80211_1ADDR_LEN: + return ((struct ieee80211_hdr_1addr *)hdr)->payload; + case IEEE80211_2ADDR_LEN: + return ((struct ieee80211_hdr_2addr *)hdr)->payload; + case IEEE80211_3ADDR_LEN: + return ((struct ieee80211_hdr_3addr *)hdr)->payload; + case IEEE80211_4ADDR_LEN: + return ((struct ieee80211_hdr_4addr *)hdr)->payload; + } + return NULL; +} + +static inline int ieee80211_is_ofdm_rate(u8 rate) +{ + switch (rate & ~IEEE80211_BASIC_RATE_MASK) { + case IEEE80211_OFDM_RATE_6MB: + case IEEE80211_OFDM_RATE_9MB: + case IEEE80211_OFDM_RATE_12MB: + case IEEE80211_OFDM_RATE_18MB: + case IEEE80211_OFDM_RATE_24MB: + case IEEE80211_OFDM_RATE_36MB: + case IEEE80211_OFDM_RATE_48MB: + case IEEE80211_OFDM_RATE_54MB: + return 1; + } + return 0; +} + +static inline int ieee80211_is_cck_rate(u8 rate) +{ + switch (rate & ~IEEE80211_BASIC_RATE_MASK) { + case IEEE80211_CCK_RATE_1MB: + case IEEE80211_CCK_RATE_2MB: + case IEEE80211_CCK_RATE_5MB: + case IEEE80211_CCK_RATE_11MB: + return 1; + } + return 0; +} + + +/* ieee80211.c */ +extern void free_ieee80211(struct net_device *dev); +extern struct net_device *alloc_ieee80211(int sizeof_priv); + +extern int ieee80211_set_encryption(struct ieee80211_device *ieee); + +/* ieee80211_tx.c */ + +extern int ieee80211_encrypt_fragment( + struct ieee80211_device *ieee, + struct sk_buff *frag, + int hdr_len); + +extern int ieee80211_xmit(struct sk_buff *skb, + struct net_device *dev); +extern void ieee80211_txb_free(struct ieee80211_txb *); + + +/* ieee80211_rx.c */ +extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, + struct ieee80211_rx_stats *rx_stats); +extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, + struct ieee80211_hdr_4addr *header, + struct ieee80211_rx_stats *stats); + +/* ieee80211_wx.c */ +extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key); +extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key); +extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key); +#if WIRELESS_EXT >= 18 +extern int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data* wrqu, char *extra); +extern int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data* wrqu, char *extra); +extern int ieee80211_wx_set_auth(struct ieee80211_device *ieee, + struct iw_request_info *info, + struct iw_param *data, char *extra); +extern int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +#endif +extern int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len); + +/* ieee80211_softmac.c */ +extern short ieee80211_is_54g(struct ieee80211_network net); +extern short ieee80211_is_shortslot(struct ieee80211_network net); +extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, + struct ieee80211_rx_stats *rx_stats, u16 type, + u16 stype); +extern void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net); + +void SendDisassociation(struct ieee80211_device *ieee, u8* asSta, u8 asRsn); +extern void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee); + +extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee); +extern void notify_wx_assoc_event(struct ieee80211_device *ieee); +extern void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee); +extern void ieee80211_start_bss(struct ieee80211_device *ieee); +extern void ieee80211_start_master_bss(struct ieee80211_device *ieee); +extern void ieee80211_start_ibss(struct ieee80211_device *ieee); +extern void ieee80211_softmac_init(struct ieee80211_device *ieee); +extern void ieee80211_softmac_free(struct ieee80211_device *ieee); +extern void ieee80211_associate_abort(struct ieee80211_device *ieee); +extern void ieee80211_disassociate(struct ieee80211_device *ieee); +extern void ieee80211_stop_scan(struct ieee80211_device *ieee); +extern void ieee80211_start_scan_syncro(struct ieee80211_device *ieee); +extern void ieee80211_check_all_nets(struct ieee80211_device *ieee); +extern void ieee80211_start_protocol(struct ieee80211_device *ieee); +extern void ieee80211_stop_protocol(struct ieee80211_device *ieee); +extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee); +extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee); +extern void ieee80211_reset_queue(struct ieee80211_device *ieee); +extern void ieee80211_wake_queue(struct ieee80211_device *ieee); +extern void ieee80211_stop_queue(struct ieee80211_device *ieee); +extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee); +extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee); +extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee); +extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p); +extern void notify_wx_assoc_event(struct ieee80211_device *ieee); +extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success); + +extern void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee); + +/* ieee80211_crypt_ccmp&tkip&wep.c */ +extern void ieee80211_tkip_null(void); +extern void ieee80211_wep_null(void); +extern void ieee80211_ccmp_null(void); + +/* ieee80211_softmac_wx.c */ + +extern int ieee80211_wx_get_wap(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *ext); + +extern int ieee80211_wx_set_wap(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *awrq, + char *extra); + +extern int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b); + +extern int ieee80211_wx_set_rate(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_get_rate(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); + +extern int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); + +extern int ieee80211_wx_set_essid(struct ieee80211_device *ieee, + struct iw_request_info *a, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); + +extern int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); + +extern int ieee80211_wx_get_freq(struct ieee80211_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); + +//extern void ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee); +extern void ieee80211_wx_sync_scan_wq(struct work_struct *work); + + +extern int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_get_name(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_set_power(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_get_power(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_set_rts(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_get_rts(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +//HT +#define MAX_RECEIVE_BUFFER_SIZE 9100 // +extern void HTDebugHTCapability(u8* CapIE, u8* TitleString ); +extern void HTDebugHTInfo(u8* InfoIE, u8* TitleString); + +void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset); +extern void HTUpdateDefaultSetting(struct ieee80211_device* ieee); +extern void HTConstructCapabilityElement(struct ieee80211_device* ieee, u8* posHTCap, u8* len, u8 isEncrypt); +extern void HTConstructInfoElement(struct ieee80211_device* ieee, u8* posHTInfo, u8* len, u8 isEncrypt); +extern void HTConstructRT2RTAggElement(struct ieee80211_device* ieee, u8* posRT2RTAgg, u8* len); +extern void HTOnAssocRsp(struct ieee80211_device *ieee); +extern void HTInitializeHTInfo(struct ieee80211_device* ieee); +extern void HTInitializeBssDesc(PBSS_HT pBssHT); +extern void HTResetSelfAndSavePeerSetting(struct ieee80211_device* ieee, struct ieee80211_network * pNetwork); +extern void HTUpdateSelfAndPeerSetting(struct ieee80211_device* ieee, struct ieee80211_network * pNetwork); +extern u8 HTGetHighestMCSRate(struct ieee80211_device* ieee, u8* pMCSRateSet, u8* pMCSFilter); +extern u8 MCS_FILTER_ALL[]; +extern u16 MCS_DATA_RATE[2][2][77] ; +extern u8 HTCCheck(struct ieee80211_device* ieee, u8* pFrame); +//extern void HTSetConnectBwModeCallback(unsigned long data); +extern void HTResetIOTSetting(PRT_HIGH_THROUGHPUT pHTInfo); +extern bool IsHTHalfNmodeAPs(struct ieee80211_device* ieee); +extern u16 HTHalfMcsToDataRate(struct ieee80211_device* ieee, u8 nMcsRate); +extern u16 HTMcsToDataRate( struct ieee80211_device* ieee, u8 nMcsRate); +extern u16 TxCountToDataRate( struct ieee80211_device* ieee, u8 nDataRate); +//function in BAPROC.c +extern int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb); +extern int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb); +extern int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb); +extern void TsInitAddBA( struct ieee80211_device* ieee, PTX_TS_RECORD pTS, u8 Policy, u8 bOverwritePending); +extern void TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect); +extern void BaSetupTimeOut(unsigned long data); +extern void TxBaInactTimeout(unsigned long data); +extern void RxBaInactTimeout(unsigned long data); +extern void ResetBaEntry( PBA_RECORD pBA); +//function in TS.c +extern bool GetTs( + struct ieee80211_device* ieee, + PTS_COMMON_INFO *ppTS, + u8* Addr, + u8 TID, + TR_SELECT TxRxSelect, //Rx:1, Tx:0 + bool bAddNewTs + ); +extern void TSInitialize(struct ieee80211_device *ieee); +extern void TsStartAddBaProcess(struct ieee80211_device* ieee, PTX_TS_RECORD pTxTS); +extern void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr); +extern void RemoveAllTS(struct ieee80211_device* ieee); +void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee); + +extern const long ieee80211_wlan_frequencies[]; + +extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee) +{ + ieee->scans++; +} + +extern inline int ieee80211_get_scans(struct ieee80211_device *ieee) +{ + return ieee->scans; +} + +static inline const char *escape_essid(const char *essid, u8 essid_len) { + static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; + const char *s = essid; + char *d = escaped; + + if (ieee80211_is_empty_essid(essid, essid_len)) { + memcpy(escaped, "", sizeof("")); + return escaped; + } + + essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE); + while (essid_len--) { + if (*s == '\0') { + *d++ = '\\'; + *d++ = '0'; + s++; + } else { + *d++ = *s++; + } + } + *d = '\0'; + return escaped; +} + +/* For the function is more related to hardware setting, it's better to use the + * ieee handler to refer to it. + */ +extern short check_nic_enough_desc(struct net_device *dev, int queue_index); +extern int ieee80211_data_xmit(struct sk_buff *skb, struct net_device *dev); +extern int ieee80211_parse_info_param(struct ieee80211_device *ieee, + struct ieee80211_info_element *info_element, + u16 length, + struct ieee80211_network *network, + struct ieee80211_rx_stats *stats); + +void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb** prxbIndicateArray,u8 index); +#define RT_ASOC_RETRY_LIMIT 5 +#endif /* IEEE80211_H */ diff --git a/drivers/staging/rtl8192u/ieee80211/EndianFree.h b/drivers/staging/rtl8192u/ieee80211/EndianFree.h new file mode 100644 index 0000000000000000000000000000000000000000..dc85fb913dc261e026508f9bb745eefcc65ba57f --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/EndianFree.h @@ -0,0 +1,194 @@ +#ifndef __INC_ENDIANFREE_H +#define __INC_ENDIANFREE_H + +/* + * Call endian free function when + * 1. Read/write packet content. + * 2. Before write integer to IO. + * 3. After read integer from IO. + */ + +#define __MACHINE_LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ +#define __MACHINE_BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net, ppc */ + +#define BYTE_ORDER __MACHINE_LITTLE_ENDIAN + +#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN +// Convert data +#define EF1Byte(_val) ((u8)(_val)) +#define EF2Byte(_val) ((u16)(_val)) +#define EF4Byte(_val) ((u32)(_val)) + +#else +// Convert data +#define EF1Byte(_val) ((u8)(_val)) +#define EF2Byte(_val) (((((u16)(_val))&0x00ff)<<8)|((((u16)(_val))&0xff00)>>8)) +#define EF4Byte(_val) (((((u32)(_val))&0x000000ff)<<24)|\ + ((((u32)(_val))&0x0000ff00)<<8)|\ + ((((u32)(_val))&0x00ff0000)>>8)|\ + ((((u32)(_val))&0xff000000)>>24)) +#endif + +// Read data from memory +#define ReadEF1Byte(_ptr) EF1Byte(*((u8 *)(_ptr))) +#define ReadEF2Byte(_ptr) EF2Byte(*((u16 *)(_ptr))) +#define ReadEF4Byte(_ptr) EF4Byte(*((u32 *)(_ptr))) + +// Write data to memory +#define WriteEF1Byte(_ptr, _val) (*((u8 *)(_ptr)))=EF1Byte(_val) +#define WriteEF2Byte(_ptr, _val) (*((u16 *)(_ptr)))=EF2Byte(_val) +#define WriteEF4Byte(_ptr, _val) (*((u32 *)(_ptr)))=EF4Byte(_val) +// Convert Host system specific byte ording (litten or big endia) to Network byte ording (big endian). +// 2006.05.07, by rcnjko. +#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN +#define H2N1BYTE(_val) ((u8)(_val)) +#define H2N2BYTE(_val) (((((u16)(_val))&0x00ff)<<8)|\ + ((((u16)(_val))&0xff00)>>8)) +#define H2N4BYTE(_val) (((((u32)(_val))&0x000000ff)<<24)|\ + ((((u32)(_val))&0x0000ff00)<<8) |\ + ((((u32)(_val))&0x00ff0000)>>8) |\ + ((((u32)(_val))&0xff000000)>>24)) +#else +#define H2N1BYTE(_val) ((u8)(_val)) +#define H2N2BYTE(_val) ((u16)(_val)) +#define H2N4BYTE(_val) ((u32)(_val)) +#endif + +// Convert from Network byte ording (big endian) to Host system specific byte ording (litten or big endia). +// 2006.05.07, by rcnjko. +#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN +#define N2H1BYTE(_val) ((u8)(_val)) +#define N2H2BYTE(_val) (((((u16)(_val))&0x00ff)<<8)|\ + ((((u16)(_val))&0xff00)>>8)) +#define N2H4BYTE(_val) (((((u32)(_val))&0x000000ff)<<24)|\ + ((((u32)(_val))&0x0000ff00)<<8) |\ + ((((u32)(_val))&0x00ff0000)>>8) |\ + ((((u32)(_val))&0xff000000)>>24)) +#else +#define N2H1BYTE(_val) ((u8)(_val)) +#define N2H2BYTE(_val) ((u16)(_val)) +#define N2H4BYTE(_val) ((u32)(_val)) +#endif + +// +// Example: +// BIT_LEN_MASK_32(0) => 0x00000000 +// BIT_LEN_MASK_32(1) => 0x00000001 +// BIT_LEN_MASK_32(2) => 0x00000003 +// BIT_LEN_MASK_32(32) => 0xFFFFFFFF +// +#define BIT_LEN_MASK_32(__BitLen) (0xFFFFFFFF >> (32 - (__BitLen))) +// +// Example: +// BIT_OFFSET_LEN_MASK_32(0, 2) => 0x00000003 +// BIT_OFFSET_LEN_MASK_32(16, 2) => 0x00030000 +// +#define BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen) (BIT_LEN_MASK_32(__BitLen) << (__BitOffset)) + +// +// Description: +// Return 4-byte value in host byte ordering from +// 4-byte pointer in litten-endian system. +// +#define LE_P4BYTE_TO_HOST_4BYTE(__pStart) (EF4Byte(*((u32 *)(__pStart)))) + +// +// Description: +// Translate subfield (continuous bits in little-endian) of 4-byte value in litten byte to +// 4-byte value in host byte ordering. +// +#define LE_BITS_TO_4BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + ( LE_P4BYTE_TO_HOST_4BYTE(__pStart) >> (__BitOffset) ) \ + & \ + BIT_LEN_MASK_32(__BitLen) \ + ) + +// +// Description: +// Mask subfield (continuous bits in little-endian) of 4-byte value in litten byte oredering +// and return the result in 4-byte value in host byte ordering. +// +#define LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + LE_P4BYTE_TO_HOST_4BYTE(__pStart) \ + & \ + ( ~BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen) ) \ + ) + +// +// Description: +// Set subfield of little-endian 4-byte value to specified value. +// +#define SET_BITS_TO_LE_4BYTE(__pStart, __BitOffset, __BitLen, __Value) \ + *((u32 *)(__pStart)) = \ + EF4Byte( \ + LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \ + | \ + ( (((u32)__Value) & BIT_LEN_MASK_32(__BitLen)) << (__BitOffset) ) \ + ); + + +#define BIT_LEN_MASK_16(__BitLen) \ + (0xFFFF >> (16 - (__BitLen))) + +#define BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) \ + (BIT_LEN_MASK_16(__BitLen) << (__BitOffset)) + +#define LE_P2BYTE_TO_HOST_2BYTE(__pStart) \ + (EF2Byte(*((u16 *)(__pStart)))) + +#define LE_BITS_TO_2BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + ( LE_P2BYTE_TO_HOST_2BYTE(__pStart) >> (__BitOffset) ) \ + & \ + BIT_LEN_MASK_16(__BitLen) \ + ) + +#define LE_BITS_CLEARED_TO_2BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + LE_P2BYTE_TO_HOST_2BYTE(__pStart) \ + & \ + ( ~BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) ) \ + ) + +#define SET_BITS_TO_LE_2BYTE(__pStart, __BitOffset, __BitLen, __Value) \ + *((u16 *)(__pStart)) = \ + EF2Byte( \ + LE_BITS_CLEARED_TO_2BYTE(__pStart, __BitOffset, __BitLen) \ + | \ + ( (((u16)__Value) & BIT_LEN_MASK_16(__BitLen)) << (__BitOffset) ) \ + ); + +#define BIT_LEN_MASK_8(__BitLen) \ + (0xFF >> (8 - (__BitLen))) + +#define BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) \ + (BIT_LEN_MASK_8(__BitLen) << (__BitOffset)) + +#define LE_P1BYTE_TO_HOST_1BYTE(__pStart) \ + (EF1Byte(*((u8 *)(__pStart)))) + +#define LE_BITS_TO_1BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + ( LE_P1BYTE_TO_HOST_1BYTE(__pStart) >> (__BitOffset) ) \ + & \ + BIT_LEN_MASK_8(__BitLen) \ + ) + +#define LE_BITS_CLEARED_TO_1BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + LE_P1BYTE_TO_HOST_1BYTE(__pStart) \ + & \ + ( ~BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) ) \ + ) + +#define SET_BITS_TO_LE_1BYTE(__pStart, __BitOffset, __BitLen, __Value) \ + *((u8 *)(__pStart)) = \ + EF1Byte( \ + LE_BITS_CLEARED_TO_1BYTE(__pStart, __BitOffset, __BitLen) \ + | \ + ( (((u8)__Value) & BIT_LEN_MASK_8(__BitLen)) << (__BitOffset) ) \ + ); + +#endif // #ifndef __INC_ENDIANFREE_H diff --git a/drivers/staging/rtl8192u/ieee80211/Makefile b/drivers/staging/rtl8192u/ieee80211/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..71ca5d93a1b7864bbf2776604a9e4daeffa24f2f --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/Makefile @@ -0,0 +1,139 @@ +NIC_SELECT = RTL8192U + +KVER := $(shell uname -r) +MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless/$(NIC_SELECT) + +CC = gcc +ifneq ($(shell uname -r|cut -d. -f1,2), 2.4) +EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/wireless +EXTRA_CFLAGS += -O2 +EXTRA_CFLAGS += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX + +#it will fail to compile in suse linux enterprise 10 sp2. This flag is to solve this problem. +ifeq ($(shell uname -r | cut -d. -f1,2,3,4), 2.6.16.60-0) +EXTRA_CFLAGS += -DOPENSUSE_SLED +endif + +ifeq ($(NIC_SELECT),RTL8192U) +#EXTRA_CFLAGS += -DUSB_TX_DRIVER_AGGREGATION_ENABLE +#EXTRA_CFLAGS += -DUSB_RX_AGGREGATION_SUPPORT +endif +#EXTRA_CFLAGS += -DJOHN_NOCPY +#flags to enable or disble 80211D feature +EXTRA_CFLAGS += -DENABLE_DOT11D +ieee80211-rsl-objs := ieee80211_rx.o \ + ieee80211_softmac.o \ + ieee80211_tx.o \ + ieee80211_wx.o \ + ieee80211_module.o \ + ieee80211_softmac_wx.o\ + rtl819x_HTProc.o\ + rtl819x_TSProc.o\ + rtl819x_BAProc.o\ + dot11d.o + +ieee80211_crypt-rsl-objs := ieee80211_crypt.o +ieee80211_crypt_tkip-rsl-objs := ieee80211_crypt_tkip.o +ieee80211_crypt_ccmp-rsl-objs := ieee80211_crypt_ccmp.o +ieee80211_crypt_wep-rsl-objs := ieee80211_crypt_wep.o + +obj-m +=ieee80211-rsl.o +obj-m +=ieee80211_crypt-rsl.o +obj-m +=ieee80211_crypt_wep-rsl.o +obj-m +=ieee80211_crypt_tkip-rsl.o +obj-m +=ieee80211_crypt_ccmp-rsl.o + +KSRC := /lib/modules/$(KVER)/build +INSTALL_PREFIX := + +all: modules + +modules: + $(MAKE) -C $(KSRC) M=$(PWD) CC=$(CC) modules + +install: modules + rm -fr $(MODDESTDIR) + mkdir -p $(MODDESTDIR) + @install -p -m 644 ieee80211_crypt-rsl.ko $(MODDESTDIR) + @install -p -m 644 ieee80211_crypt_wep-rsl.ko $(MODDESTDIR) + @install -p -m 644 ieee80211_crypt_tkip-rsl.ko $(MODDESTDIR) + @install -p -m 644 ieee80211_crypt_ccmp-rsl.ko $(MODDESTDIR) + @install -p -m 644 ieee80211-rsl.ko $(MODDESTDIR) + depmod -a +uninstall: + rm -fr $(MODDESTDIR) + depmod -a + +else +LD := ld +KSRC := /lib/modules/$(KVER)/build +CONFIG_FILE := $(KSRC)/include/linux/autoconf.h + +CFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall +CFLAGS += -I$(KSRC)/include -I. +#Kernel 2.4.31 +CFLAGS += -DMODVERSIONS -DEXPORT_SYMTAB -include $(KSRC)/include/linux/modversions.h +#Kernel 2.4.20 +#CFLAGS += -D__NO_VERSION__ -DEXPORT_SYMTAB +#CFLAGS += -DENABLE_DOT11D +SMP := $(shell $(CC) $(MODCFLAGS) -E -dM $(CONFIG_FILE) | \ + grep CONFIG_SMP | awk '{print $$3}') +ifneq ($(SMP),1) + SMP := 0 +endif +ifeq ($(SMP),1) + CFLAGS += -D__SMP__ +endif + +#CFLAGS += -DJOHN_NOCPY + +OBJS := ${patsubst %.c, %.o, ${wildcard *.c}} +all:${OBJS} ieee80211_crypt-rsl.o michael_mic-rsl.o aes-rsl.o ieee80211_crypt_wep-rsl.o ieee80211_crypt_tkip-rsl.o ieee80211_crypt_ccmp-rsl.o crypto-rsl.o ieee80211-rsl.o + +ieee80211_crypt-rsl.o: ieee80211_crypt.o + mv $^ $@ + +michael_mic-rsl.o: michael_mic.o + mv $^ $@ + +aes-rsl.o: aes.o + mv $^ $@ + +ieee80211_crypt_wep-rsl.o: ieee80211_crypt_wep.o + mv $^ $@ + +ieee80211_crypt_tkip-rsl.o: ieee80211_crypt_tkip.o + mv $^ $@ + +ieee80211_crypt_ccmp-rsl.o: ieee80211_crypt_ccmp.o + mv $^ $@ + +crypto-rsl.o: arc4.o api.o autoload.o cipher.o compress.o digest.o scatterwalk.o proc.o + $(LD) -r $^ -o $@ + +ieee80211-rsl.o: ieee80211_rx.o ieee80211_tx.o ieee80211_wx.o ieee80211_module.o ieee80211_softmac_wx.o ieee80211_softmac.o rtl819x_HTProc.o rtl819x_TSProc.o rtl819x_BAProc.o dot11d.o + $(LD) -r $^ -o $@ +install: + rm -fr $(MODDESTDIR) + mkdir -p $(MODDESTDIR) + @install -p -m 644 ieee80211_crypt-rsl.o $(MODDESTDIR) + @install -p -m 644 crypto-rsl.o $(MODDESTDIR) + @install -p -m 644 michael_mic-rsl.o $(MODDESTDIR) + @install -p -m 644 aes-rsl.o $(MODDESTDIR) + @install -p -m 644 ieee80211_crypt_wep-rsl.o $(MODDESTDIR) + @install -p -m 644 ieee80211_crypt_tkip-rsl.o $(MODDESTDIR) + @install -p -m 644 ieee80211_crypt_ccmp-rsl.o $(MODDESTDIR) + @install -p -m 644 ieee80211-rsl.o $(MODDESTDIR) + /sbin/depmod -a ${shell uname -r} + +uninstall: + rm -fr $(MODDESTDIR) + /sbin/depmod -a ${shell uname -r} + +endif + +.PHONY: clean +clean: + rm -fr *.mod.c *.mod *.o .*.cmd *.mod.* *.ko *.o *~ + rm -rf .tmp_versions + rm -rf Module.symvers diff --git a/drivers/staging/rtl8192u/ieee80211/aes.c b/drivers/staging/rtl8192u/ieee80211/aes.c new file mode 100644 index 0000000000000000000000000000000000000000..a6bb6c9207d32e2c6242ef4fceeba071d38e96d9 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/aes.c @@ -0,0 +1,469 @@ +/* + * Cryptographic API. + * + * AES Cipher Algorithm. + * + * Based on Brian Gladman's code. + * + * Linux developers: + * Alexander Kjeldaas + * Herbert Valerio Riedel + * Kyle McMartin + * Adam J. Richter (conversion to 2.5 API). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * --------------------------------------------------------------------------- + * Copyright (c) 2002, Dr Brian Gladman , Worcester, UK. + * All rights reserved. + * + * LICENSE TERMS + * + * The free distribution and use of this software in both source and binary + * form is allowed (with or without changes) provided that: + * + * 1. distributions of this source code include the above copyright + * notice, this list of conditions and the following disclaimer; + * + * 2. distributions in binary form include the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other associated materials; + * + * 3. the copyright holder's name is not used to endorse products + * built using this software without specific written permission. + * + * ALTERNATIVELY, provided that this notice is retained in full, this product + * may be distributed under the terms of the GNU General Public License (GPL), + * in which case the provisions of the GPL apply INSTEAD OF those given above. + * + * DISCLAIMER + * + * This software is provided 'as is' with no explicit or implied warranties + * in respect of its properties, including, but not limited to, correctness + * and/or fitness for purpose. + * --------------------------------------------------------------------------- + */ + +/* Some changes from the Gladman version: + s/RIJNDAEL(e_key)/E_KEY/g + s/RIJNDAEL(d_key)/D_KEY/g +*/ + +#include +#include +#include +#include +//#include +#include "rtl_crypto.h" +#include + +#define AES_MIN_KEY_SIZE 16 +#define AES_MAX_KEY_SIZE 32 + +#define AES_BLOCK_SIZE 16 + +static inline +u32 generic_rotr32 (const u32 x, const unsigned bits) +{ + const unsigned n = bits % 32; + return (x >> n) | (x << (32 - n)); +} + +static inline +u32 generic_rotl32 (const u32 x, const unsigned bits) +{ + const unsigned n = bits % 32; + return (x << n) | (x >> (32 - n)); +} + +#define rotl generic_rotl32 +#define rotr generic_rotr32 + +/* + * #define byte(x, nr) ((unsigned char)((x) >> (nr*8))) + */ +inline static u8 +byte(const u32 x, const unsigned n) +{ + return x >> (n << 3); +} + +#define u32_in(x) le32_to_cpu(*(const u32 *)(x)) +#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from)) + +struct aes_ctx { + int key_length; + u32 E[60]; + u32 D[60]; +}; + +#define E_KEY ctx->E +#define D_KEY ctx->D + +static u8 pow_tab[256] __initdata; +static u8 log_tab[256] __initdata; +static u8 sbx_tab[256] __initdata; +static u8 isb_tab[256] __initdata; +static u32 rco_tab[10]; +static u32 ft_tab[4][256]; +static u32 it_tab[4][256]; + +static u32 fl_tab[4][256]; +static u32 il_tab[4][256]; + +static inline u8 __init +f_mult (u8 a, u8 b) +{ + u8 aa = log_tab[a], cc = aa + log_tab[b]; + + return pow_tab[cc + (cc < aa ? 1 : 0)]; +} + +#define ff_mult(a,b) (a && b ? f_mult(a, b) : 0) + +#define f_rn(bo, bi, n, k) \ + bo[n] = ft_tab[0][byte(bi[n],0)] ^ \ + ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ + ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) + +#define i_rn(bo, bi, n, k) \ + bo[n] = it_tab[0][byte(bi[n],0)] ^ \ + it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ + it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) + +#define ls_box(x) \ + ( fl_tab[0][byte(x, 0)] ^ \ + fl_tab[1][byte(x, 1)] ^ \ + fl_tab[2][byte(x, 2)] ^ \ + fl_tab[3][byte(x, 3)] ) + +#define f_rl(bo, bi, n, k) \ + bo[n] = fl_tab[0][byte(bi[n],0)] ^ \ + fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ + fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) + +#define i_rl(bo, bi, n, k) \ + bo[n] = il_tab[0][byte(bi[n],0)] ^ \ + il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ + il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) + +static void __init +gen_tabs (void) +{ + u32 i, t; + u8 p, q; + + /* log and power tables for GF(2**8) finite field with + 0x011b as modular polynomial - the simplest primitive + root is 0x03, used here to generate the tables */ + + for (i = 0, p = 1; i < 256; ++i) { + pow_tab[i] = (u8) p; + log_tab[p] = (u8) i; + + p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0); + } + + log_tab[1] = 0; + + for (i = 0, p = 1; i < 10; ++i) { + rco_tab[i] = p; + + p = (p << 1) ^ (p & 0x80 ? 0x01b : 0); + } + + for (i = 0; i < 256; ++i) { + p = (i ? pow_tab[255 - log_tab[i]] : 0); + q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2)); + p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2)); + sbx_tab[i] = p; + isb_tab[p] = (u8) i; + } + + for (i = 0; i < 256; ++i) { + p = sbx_tab[i]; + + t = p; + fl_tab[0][i] = t; + fl_tab[1][i] = rotl (t, 8); + fl_tab[2][i] = rotl (t, 16); + fl_tab[3][i] = rotl (t, 24); + + t = ((u32) ff_mult (2, p)) | + ((u32) p << 8) | + ((u32) p << 16) | ((u32) ff_mult (3, p) << 24); + + ft_tab[0][i] = t; + ft_tab[1][i] = rotl (t, 8); + ft_tab[2][i] = rotl (t, 16); + ft_tab[3][i] = rotl (t, 24); + + p = isb_tab[i]; + + t = p; + il_tab[0][i] = t; + il_tab[1][i] = rotl (t, 8); + il_tab[2][i] = rotl (t, 16); + il_tab[3][i] = rotl (t, 24); + + t = ((u32) ff_mult (14, p)) | + ((u32) ff_mult (9, p) << 8) | + ((u32) ff_mult (13, p) << 16) | + ((u32) ff_mult (11, p) << 24); + + it_tab[0][i] = t; + it_tab[1][i] = rotl (t, 8); + it_tab[2][i] = rotl (t, 16); + it_tab[3][i] = rotl (t, 24); + } +} + +#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b) + +#define imix_col(y,x) \ + u = star_x(x); \ + v = star_x(u); \ + w = star_x(v); \ + t = w ^ (x); \ + (y) = u ^ v ^ w; \ + (y) ^= rotr(u ^ t, 8) ^ \ + rotr(v ^ t, 16) ^ \ + rotr(t,24) + +/* initialise the key schedule from the user supplied key */ + +#define loop4(i) \ +{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[4 * i]; E_KEY[4 * i + 4] = t; \ + t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t; \ + t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t; \ + t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t; \ +} + +#define loop6(i) \ +{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[6 * i]; E_KEY[6 * i + 6] = t; \ + t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t; \ + t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t; \ + t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t; \ + t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t; \ + t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t; \ +} + +#define loop8(i) \ +{ t = rotr(t, 8); ; t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[8 * i]; E_KEY[8 * i + 8] = t; \ + t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t; \ + t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t; \ + t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t; \ + t = E_KEY[8 * i + 4] ^ ls_box(t); \ + E_KEY[8 * i + 12] = t; \ + t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t; \ + t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t; \ + 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) +{ + struct aes_ctx *ctx = ctx_arg; + u32 i, t, u, v, w; + + if (key_len != 16 && key_len != 24 && key_len != 32) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + ctx->key_length = key_len; + + E_KEY[0] = u32_in (in_key); + E_KEY[1] = u32_in (in_key + 4); + E_KEY[2] = u32_in (in_key + 8); + E_KEY[3] = u32_in (in_key + 12); + + switch (key_len) { + case 16: + t = E_KEY[3]; + for (i = 0; i < 10; ++i) + loop4 (i); + break; + + case 24: + E_KEY[4] = u32_in (in_key + 16); + t = E_KEY[5] = u32_in (in_key + 20); + for (i = 0; i < 8; ++i) + loop6 (i); + break; + + case 32: + E_KEY[4] = u32_in (in_key + 16); + E_KEY[5] = u32_in (in_key + 20); + E_KEY[6] = u32_in (in_key + 24); + t = E_KEY[7] = u32_in (in_key + 28); + for (i = 0; i < 7; ++i) + loop8 (i); + break; + } + + D_KEY[0] = E_KEY[0]; + D_KEY[1] = E_KEY[1]; + D_KEY[2] = E_KEY[2]; + D_KEY[3] = E_KEY[3]; + + for (i = 4; i < key_len + 24; ++i) { + imix_col (D_KEY[i], E_KEY[i]); + } + + return 0; +} + +/* encrypt a block of text */ + +#define f_nround(bo, bi, k) \ + f_rn(bo, bi, 0, k); \ + f_rn(bo, bi, 1, k); \ + f_rn(bo, bi, 2, k); \ + f_rn(bo, bi, 3, k); \ + k += 4 + +#define f_lround(bo, bi, k) \ + f_rl(bo, bi, 0, k); \ + f_rl(bo, bi, 1, 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) +{ + const struct aes_ctx *ctx = ctx_arg; + u32 b0[4], b1[4]; + const u32 *kp = E_KEY + 4; + + b0[0] = u32_in (in) ^ E_KEY[0]; + b0[1] = u32_in (in + 4) ^ E_KEY[1]; + b0[2] = u32_in (in + 8) ^ E_KEY[2]; + b0[3] = u32_in (in + 12) ^ E_KEY[3]; + + if (ctx->key_length > 24) { + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + } + + if (ctx->key_length > 16) { + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + } + + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_lround (b0, b1, kp); + + u32_out (out, b0[0]); + u32_out (out + 4, b0[1]); + u32_out (out + 8, b0[2]); + u32_out (out + 12, b0[3]); +} + +/* decrypt a block of text */ + +#define i_nround(bo, bi, k) \ + i_rn(bo, bi, 0, k); \ + i_rn(bo, bi, 1, k); \ + i_rn(bo, bi, 2, k); \ + i_rn(bo, bi, 3, k); \ + k -= 4 + +#define i_lround(bo, bi, k) \ + i_rl(bo, bi, 0, k); \ + i_rl(bo, bi, 1, 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) +{ + const struct aes_ctx *ctx = ctx_arg; + u32 b0[4], b1[4]; + const int key_len = ctx->key_length; + const u32 *kp = D_KEY + key_len + 20; + + b0[0] = u32_in (in) ^ E_KEY[key_len + 24]; + b0[1] = u32_in (in + 4) ^ E_KEY[key_len + 25]; + b0[2] = u32_in (in + 8) ^ E_KEY[key_len + 26]; + b0[3] = u32_in (in + 12) ^ E_KEY[key_len + 27]; + + if (key_len > 24) { + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + } + + if (key_len > 16) { + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + } + + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_lround (b0, b1, kp); + + u32_out (out, b0[0]); + u32_out (out + 4, b0[1]); + u32_out (out + 8, b0[2]); + u32_out (out + 12, b0[3]); +} + + +static struct crypto_alg aes_alg = { + .cra_name = "aes", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct aes_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), + .cra_u = { + .cipher = { + .cia_min_keysize = AES_MIN_KEY_SIZE, + .cia_max_keysize = AES_MAX_KEY_SIZE, + .cia_setkey = aes_set_key, + .cia_encrypt = aes_encrypt, + .cia_decrypt = aes_decrypt + } + } +}; + +static int __init aes_init(void) +{ + gen_tabs(); + return crypto_register_alg(&aes_alg); +} + +static void __exit aes_fini(void) +{ + crypto_unregister_alg(&aes_alg); +} + +module_init(aes_init); +module_exit(aes_fini); + +MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); +MODULE_LICENSE("Dual BSD/GPL"); + diff --git a/drivers/staging/rtl8192u/ieee80211/api.c b/drivers/staging/rtl8192u/ieee80211/api.c new file mode 100644 index 0000000000000000000000000000000000000000..c627d029528b4cce212c949ddc7518d7dd287728 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/api.c @@ -0,0 +1,246 @@ +/* + * Scatterlist Cryptographic API. + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * + * Portions derived from Cryptoapi, by Alexander Kjeldaas + * and Nettle, by Niels Mé°ˆler. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the 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 "kmap_types.h" + +#include +#include +//#include +#include "rtl_crypto.h" +#include +#include +#include +#include "internal.h" + +LIST_HEAD(crypto_alg_list); +DECLARE_RWSEM(crypto_alg_sem); + +static inline int crypto_alg_get(struct crypto_alg *alg) +{ + return try_inc_mod_count(alg->cra_module); +} + +static inline void crypto_alg_put(struct crypto_alg *alg) +{ + if (alg->cra_module) + __MOD_DEC_USE_COUNT(alg->cra_module); +} + +struct crypto_alg *crypto_alg_lookup(const char *name) +{ + struct crypto_alg *q, *alg = NULL; + + if (!name) + return NULL; + + down_read(&crypto_alg_sem); + + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (!(strcmp(q->cra_name, name))) { + if (crypto_alg_get(q)) + alg = q; + break; + } + } + + up_read(&crypto_alg_sem); + return alg; +} + +static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) +{ + tfm->crt_flags = 0; + + switch (crypto_tfm_alg_type(tfm)) { + case CRYPTO_ALG_TYPE_CIPHER: + return crypto_init_cipher_flags(tfm, flags); + + case CRYPTO_ALG_TYPE_DIGEST: + return crypto_init_digest_flags(tfm, flags); + + case CRYPTO_ALG_TYPE_COMPRESS: + return crypto_init_compress_flags(tfm, flags); + + default: + break; + } + + BUG(); + return -EINVAL; +} + +static int crypto_init_ops(struct crypto_tfm *tfm) +{ + switch (crypto_tfm_alg_type(tfm)) { + case CRYPTO_ALG_TYPE_CIPHER: + return crypto_init_cipher_ops(tfm); + + case CRYPTO_ALG_TYPE_DIGEST: + return crypto_init_digest_ops(tfm); + + case CRYPTO_ALG_TYPE_COMPRESS: + return crypto_init_compress_ops(tfm); + + default: + break; + } + + BUG(); + return -EINVAL; +} + +static void crypto_exit_ops(struct crypto_tfm *tfm) +{ + switch (crypto_tfm_alg_type(tfm)) { + case CRYPTO_ALG_TYPE_CIPHER: + crypto_exit_cipher_ops(tfm); + break; + + case CRYPTO_ALG_TYPE_DIGEST: + crypto_exit_digest_ops(tfm); + break; + + case CRYPTO_ALG_TYPE_COMPRESS: + crypto_exit_compress_ops(tfm); + break; + + default: + BUG(); + + } +} + +struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) +{ + struct crypto_tfm *tfm = NULL; + struct crypto_alg *alg; + + alg = crypto_alg_mod_lookup(name); + if (alg == NULL) + goto out; + + tfm = kmalloc(sizeof(*tfm) + alg->cra_ctxsize, GFP_KERNEL); + if (tfm == NULL) + goto out_put; + + memset(tfm, 0, sizeof(*tfm) + alg->cra_ctxsize); + + tfm->__crt_alg = alg; + + if (crypto_init_flags(tfm, flags)) + goto out_free_tfm; + + if (crypto_init_ops(tfm)) { + crypto_exit_ops(tfm); + goto out_free_tfm; + } + + goto out; + +out_free_tfm: + kfree(tfm); + tfm = NULL; +out_put: + crypto_alg_put(alg); +out: + return tfm; +} + +void crypto_free_tfm(struct crypto_tfm *tfm) +{ + struct crypto_alg *alg = tfm->__crt_alg; + int size = sizeof(*tfm) + alg->cra_ctxsize; + + crypto_exit_ops(tfm); + crypto_alg_put(alg); + memset(tfm, 0, size); + kfree(tfm); +} + +int crypto_register_alg(struct crypto_alg *alg) +{ + int ret = 0; + struct crypto_alg *q; + + down_write(&crypto_alg_sem); + + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (!(strcmp(q->cra_name, alg->cra_name))) { + ret = -EEXIST; + goto out; + } + } + + list_add_tail(&alg->cra_list, &crypto_alg_list); +out: + up_write(&crypto_alg_sem); + return ret; +} + +int crypto_unregister_alg(struct crypto_alg *alg) +{ + int ret = -ENOENT; + struct crypto_alg *q; + + BUG_ON(!alg->cra_module); + + down_write(&crypto_alg_sem); + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (alg == q) { + list_del(&alg->cra_list); + ret = 0; + goto out; + } + } +out: + up_write(&crypto_alg_sem); + return ret; +} + +int crypto_alg_available(const char *name, u32 flags) +{ + int ret = 0; + struct crypto_alg *alg = crypto_alg_mod_lookup(name); + + if (alg) { + crypto_alg_put(alg); + ret = 1; + } + + return ret; +} + +static int __init init_crypto(void) +{ + printk(KERN_INFO "Initializing Cryptographic API\n"); + crypto_init_proc(); + return 0; +} + +__initcall(init_crypto); + +/* +EXPORT_SYMBOL_GPL(crypto_register_alg); +EXPORT_SYMBOL_GPL(crypto_unregister_alg); +EXPORT_SYMBOL_GPL(crypto_alloc_tfm); +EXPORT_SYMBOL_GPL(crypto_free_tfm); +EXPORT_SYMBOL_GPL(crypto_alg_available); +*/ + +EXPORT_SYMBOL_NOVERS(crypto_register_alg); +EXPORT_SYMBOL_NOVERS(crypto_unregister_alg); +EXPORT_SYMBOL_NOVERS(crypto_alloc_tfm); +EXPORT_SYMBOL_NOVERS(crypto_free_tfm); +EXPORT_SYMBOL_NOVERS(crypto_alg_available); diff --git a/drivers/staging/rtl8192u/ieee80211/arc4.c b/drivers/staging/rtl8192u/ieee80211/arc4.c new file mode 100644 index 0000000000000000000000000000000000000000..e3ad8d2f415e802255b283353a5dd2288dde2dd2 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/arc4.c @@ -0,0 +1,103 @@ +/* + * Cryptographic API + * + * ARC4 Cipher Algorithm + * + * Jon Oberheide + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "rtl_crypto.h" + +#define ARC4_MIN_KEY_SIZE 1 +#define ARC4_MAX_KEY_SIZE 256 +#define ARC4_BLOCK_SIZE 1 + +struct arc4_ctx { + u8 S[256]; + u8 x, y; +}; + +static int arc4_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) +{ + struct arc4_ctx *ctx = ctx_arg; + int i, j = 0, k = 0; + + ctx->x = 1; + ctx->y = 0; + + for(i = 0; i < 256; i++) + ctx->S[i] = i; + + for(i = 0; i < 256; i++) + { + u8 a = ctx->S[i]; + j = (j + in_key[k] + a) & 0xff; + ctx->S[i] = ctx->S[j]; + ctx->S[j] = a; + if((unsigned int)++k >= key_len) + k = 0; + } + + return 0; +} + +static void arc4_crypt(void *ctx_arg, u8 *out, const u8 *in) +{ + struct arc4_ctx *ctx = ctx_arg; + + u8 *const S = ctx->S; + u8 x = ctx->x; + u8 y = ctx->y; + u8 a, b; + + a = S[x]; + y = (y + a) & 0xff; + b = S[y]; + S[x] = b; + S[y] = a; + x = (x + 1) & 0xff; + *out++ = *in ^ S[(a + b) & 0xff]; + + ctx->x = x; + ctx->y = y; +} + +static struct crypto_alg arc4_alg = { + .cra_name = "arc4", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = ARC4_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct arc4_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(arc4_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = ARC4_MIN_KEY_SIZE, + .cia_max_keysize = ARC4_MAX_KEY_SIZE, + .cia_setkey = arc4_set_key, + .cia_encrypt = arc4_crypt, + .cia_decrypt = arc4_crypt } } +}; + +static int __init arc4_init(void) +{ + return crypto_register_alg(&arc4_alg); +} + + +static void __exit arc4_exit(void) +{ + crypto_unregister_alg(&arc4_alg); +} + +module_init(arc4_init); +module_exit(arc4_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); +MODULE_AUTHOR("Jon Oberheide "); diff --git a/drivers/staging/rtl8192u/ieee80211/autoload.c b/drivers/staging/rtl8192u/ieee80211/autoload.c new file mode 100644 index 0000000000000000000000000000000000000000..c97756f3b2ead701adbc94f30064e0cb9add490b --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/autoload.c @@ -0,0 +1,40 @@ +/* + * Cryptographic API. + * + * Algorithm autoloader. + * + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the 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 "kmap_types.h" + +#include +//#include +#include "rtl_crypto.h" +#include +#include +#include "internal.h" + +/* + * A far more intelligent version of this is planned. For now, just + * try an exact match on the name of the algorithm. + */ +void crypto_alg_autoload(const char *name) +{ + request_module(name); +} + +struct crypto_alg *crypto_alg_mod_lookup(const char *name) +{ + struct crypto_alg *alg = crypto_alg_lookup(name); + if (alg == NULL) { + crypto_alg_autoload(name); + alg = crypto_alg_lookup(name); + } + return alg; +} diff --git a/drivers/staging/rtl8192u/ieee80211/cipher.c b/drivers/staging/rtl8192u/ieee80211/cipher.c new file mode 100644 index 0000000000000000000000000000000000000000..0b9e8a4ae7b5bb59107e329674e81674055e0ee9 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/cipher.c @@ -0,0 +1,299 @@ +/* + * Cryptographic API. + * + * Cipher operations. + * + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the 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 "rtl_crypto.h" +#include +#include +#include +#include +#include "internal.h" +#include "scatterwalk.h" + +typedef void (cryptfn_t)(void *, u8 *, const u8 *); +typedef void (procfn_t)(struct crypto_tfm *, u8 *, + u8*, cryptfn_t, int enc, void *, int); + +static inline void xor_64(u8 *a, const u8 *b) +{ + ((u32 *)a)[0] ^= ((u32 *)b)[0]; + ((u32 *)a)[1] ^= ((u32 *)b)[1]; +} + +static inline void xor_128(u8 *a, const u8 *b) +{ + ((u32 *)a)[0] ^= ((u32 *)b)[0]; + ((u32 *)a)[1] ^= ((u32 *)b)[1]; + ((u32 *)a)[2] ^= ((u32 *)b)[2]; + ((u32 *)a)[3] ^= ((u32 *)b)[3]; +} + + +/* + * Generic encrypt/decrypt wrapper for ciphers, handles operations across + * multiple page boundaries by using temporary blocks. In user context, + * the kernel is given a chance to schedule us once per block. + */ +static int crypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, cryptfn_t crfn, + procfn_t prfn, int enc, void *info) +{ + struct scatter_walk walk_in, walk_out; + const unsigned int bsize = crypto_tfm_alg_blocksize(tfm); + u8 tmp_src[bsize]; + u8 tmp_dst[bsize]; + + if (!nbytes) + return 0; + + if (nbytes % bsize) { + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; + return -EINVAL; + } + + scatterwalk_start(&walk_in, src); + scatterwalk_start(&walk_out, dst); + + for(;;) { + u8 *src_p, *dst_p; + int in_place; + + scatterwalk_map(&walk_in, 0); + scatterwalk_map(&walk_out, 1); + src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src); + dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst); + in_place = scatterwalk_samebuf(&walk_in, &walk_out, + src_p, dst_p); + + nbytes -= bsize; + + scatterwalk_copychunks(src_p, &walk_in, bsize, 0); + + prfn(tfm, dst_p, src_p, crfn, enc, info, in_place); + + scatterwalk_done(&walk_in, 0, nbytes); + + scatterwalk_copychunks(dst_p, &walk_out, bsize, 1); + scatterwalk_done(&walk_out, 1, nbytes); + + if (!nbytes) + return 0; + + crypto_yield(tfm); + } +} + +static void cbc_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, + cryptfn_t fn, int enc, void *info, int in_place) +{ + u8 *iv = info; + + /* Null encryption */ + if (!iv) + return; + + if (enc) { + tfm->crt_u.cipher.cit_xor_block(iv, src); + fn(crypto_tfm_ctx(tfm), dst, iv); + memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm)); + } else { + u8 stack[in_place ? crypto_tfm_alg_blocksize(tfm) : 0]; + u8 *buf = in_place ? stack : dst; + + fn(crypto_tfm_ctx(tfm), buf, src); + tfm->crt_u.cipher.cit_xor_block(buf, iv); + memcpy(iv, src, crypto_tfm_alg_blocksize(tfm)); + if (buf != dst) + memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm)); + } +} + +static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, + cryptfn_t fn, int enc, void *info, int in_place) +{ + fn(crypto_tfm_ctx(tfm), dst, src); +} + +static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) +{ + struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; + + if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) { + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } else + return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen, + &tfm->crt_flags); +} + +static int ecb_encrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + ecb_process, 1, NULL); +} + +static int ecb_decrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + ecb_process, 1, NULL); +} + +static int cbc_encrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, tfm->crt_cipher.cit_iv); +} + +static int cbc_encrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, iv); +} + +static int cbc_decrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, tfm->crt_cipher.cit_iv); +} + +static int cbc_decrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, iv); +} + +static int nocrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return -ENOSYS; +} + +static int nocrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return -ENOSYS; +} + +int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags) +{ + u32 mode = flags & CRYPTO_TFM_MODE_MASK; + + tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB; + if (flags & CRYPTO_TFM_REQ_WEAK_KEY) + tfm->crt_flags = CRYPTO_TFM_REQ_WEAK_KEY; + + return 0; +} + +int crypto_init_cipher_ops(struct crypto_tfm *tfm) +{ + int ret = 0; + struct cipher_tfm *ops = &tfm->crt_cipher; + + ops->cit_setkey = setkey; + + switch (tfm->crt_cipher.cit_mode) { + case CRYPTO_TFM_MODE_ECB: + ops->cit_encrypt = ecb_encrypt; + ops->cit_decrypt = ecb_decrypt; + break; + + case CRYPTO_TFM_MODE_CBC: + ops->cit_encrypt = cbc_encrypt; + ops->cit_decrypt = cbc_decrypt; + ops->cit_encrypt_iv = cbc_encrypt_iv; + ops->cit_decrypt_iv = cbc_decrypt_iv; + break; + + case CRYPTO_TFM_MODE_CFB: + ops->cit_encrypt = nocrypt; + ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; + break; + + case CRYPTO_TFM_MODE_CTR: + ops->cit_encrypt = nocrypt; + ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; + break; + + default: + BUG(); + } + + if (ops->cit_mode == CRYPTO_TFM_MODE_CBC) { + + switch (crypto_tfm_alg_blocksize(tfm)) { + case 8: + ops->cit_xor_block = xor_64; + break; + + case 16: + ops->cit_xor_block = xor_128; + break; + + default: + printk(KERN_WARNING "%s: block size %u not supported\n", + crypto_tfm_alg_name(tfm), + crypto_tfm_alg_blocksize(tfm)); + ret = -EINVAL; + goto out; + } + + ops->cit_ivsize = crypto_tfm_alg_blocksize(tfm); + ops->cit_iv = kmalloc(ops->cit_ivsize, GFP_KERNEL); + if (ops->cit_iv == NULL) + ret = -ENOMEM; + } + +out: + return ret; +} + +void crypto_exit_cipher_ops(struct crypto_tfm *tfm) +{ + if (tfm->crt_cipher.cit_iv) + kfree(tfm->crt_cipher.cit_iv); +} diff --git a/drivers/staging/rtl8192u/ieee80211/compress.c b/drivers/staging/rtl8192u/ieee80211/compress.c new file mode 100644 index 0000000000000000000000000000000000000000..86c23c9223f26f319c198afbdd2708453c60da95 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/compress.c @@ -0,0 +1,64 @@ +/* + * Cryptographic API. + * + * Compression operations. + * + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the 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 "rtl_crypto.h" +#include +#include +#include +#include "internal.h" + +static int crypto_compress(struct crypto_tfm *tfm, + 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, + dlen); +} + +static int crypto_decompress(struct crypto_tfm *tfm, + 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, + dlen); +} + +int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags) +{ + return flags ? -EINVAL : 0; +} + +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; +} + +void crypto_exit_compress_ops(struct crypto_tfm *tfm) +{ + tfm->__crt_alg->cra_compress.coa_exit(crypto_tfm_ctx(tfm)); +} diff --git a/drivers/staging/rtl8192u/ieee80211/crypto_compat.h b/drivers/staging/rtl8192u/ieee80211/crypto_compat.h new file mode 100644 index 0000000000000000000000000000000000000000..da486588f1c03c96fed4472da6c05e12bcd5edda --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/crypto_compat.h @@ -0,0 +1,60 @@ +/* + * Header file to maintain compatibility among different kernel versions. + * + * Copyright (c) 2004-2006 + * + * 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. See README and COPYING for + * more details. + */ + +#include + +static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes); +} + + +static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes); +} + + struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) +{ + struct crypto_tfm *tfm = NULL; + int err; + printk("call crypto_alloc_tfm!!!\n"); + do { + struct crypto_alg *alg; + + alg = crypto_alg_mod_lookup(name, 0, CRYPTO_ALG_ASYNC); + err = PTR_ERR(alg); + if (IS_ERR(alg)) + continue; + + tfm = __crypto_alloc_tfm(alg, flags); + err = 0; + if (IS_ERR(tfm)) { + crypto_mod_put(alg); + err = PTR_ERR(tfm); + tfm = NULL; + } + } while (err == -EAGAIN && !signal_pending(current)); + + return tfm; +} +//EXPORT_SYMBOL_GPL(crypto_alloc_tfm); +//EXPORT_SYMBOL_GPL(crypto_free_tfm); + + diff --git a/drivers/staging/rtl8192u/ieee80211/digest.c b/drivers/staging/rtl8192u/ieee80211/digest.c new file mode 100644 index 0000000000000000000000000000000000000000..301ed514ac9e132cdd2c0eae0b011988cfc3643d --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/digest.c @@ -0,0 +1,108 @@ +/* + * Cryptographic API. + * + * Digest operations. + * + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the 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 "rtl_crypto.h" +#include +#include +#include +#include +#include "internal.h" + +static void init(struct crypto_tfm *tfm) +{ + tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm)); +} + +static void update(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg) +{ + unsigned int i; + + for (i = 0; i < nsg; i++) { + + struct page *pg = sg[i].page; + unsigned int offset = sg[i].offset; + unsigned int l = sg[i].length; + + do { + unsigned int bytes_from_page = min(l, ((unsigned int) + (PAGE_SIZE)) - + offset); + char *p = crypto_kmap(pg, 0) + offset; + + tfm->__crt_alg->cra_digest.dia_update + (crypto_tfm_ctx(tfm), p, + bytes_from_page); + crypto_kunmap(p, 0); + crypto_yield(tfm); + offset = 0; + pg++; + l -= bytes_from_page; + } while (l > 0); + } +} + +static void final(struct crypto_tfm *tfm, u8 *out) +{ + tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out); +} + +static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) +{ + 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); +} + +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); +} + +int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags) +{ + return flags ? -EINVAL : 0; +} + +int crypto_init_digest_ops(struct crypto_tfm *tfm) +{ + struct digest_tfm *ops = &tfm->crt_digest; + + ops->dit_init = init; + ops->dit_update = update; + ops->dit_final = final; + ops->dit_digest = digest; + ops->dit_setkey = setkey; + + return crypto_alloc_hmac_block(tfm); +} + +void crypto_exit_digest_ops(struct crypto_tfm *tfm) +{ + crypto_free_hmac_block(tfm); +} diff --git a/drivers/staging/rtl8192u/ieee80211/dot11d.c b/drivers/staging/rtl8192u/ieee80211/dot11d.c new file mode 100644 index 0000000000000000000000000000000000000000..b91cbfcfa71f8084961c4521aacb0ffe0caf6886 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/dot11d.c @@ -0,0 +1,223 @@ +#ifdef ENABLE_DOT11D +//----------------------------------------------------------------------------- +// File: +// Dot11d.c +// +// Description: +// Implement 802.11d. +// +//----------------------------------------------------------------------------- + +#include "dot11d.h" + +void +Dot11d_Init(struct ieee80211_device *ieee) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); + + pDot11dInfo->bEnabled = 0; + + pDot11dInfo->State = DOT11D_STATE_NONE; + pDot11dInfo->CountryIeLen = 0; + memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + RESET_CIE_WATCHDOG(ieee); + + printk("Dot11d_Init()\n"); +} + +// +// Description: +// Reset to the state as we are just entering a regulatory domain. +// +void +Dot11d_Reset(struct ieee80211_device *ieee) +{ + u32 i; + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); + // Clear old channel map + memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + // Set new channel map + for (i=1; i<=11; i++) { + (pDot11dInfo->channel_map)[i] = 1; + } + for (i=12; i<=14; i++) { + (pDot11dInfo->channel_map)[i] = 2; + } + + pDot11dInfo->State = DOT11D_STATE_NONE; + pDot11dInfo->CountryIeLen = 0; + RESET_CIE_WATCHDOG(ieee); + + //printk("Dot11d_Reset()\n"); +} + +// +// Description: +// Update country IE from Beacon or Probe Resopnse +// and configure PHY for operation in the regulatory domain. +// +// TODO: +// Configure Tx power. +// +// Assumption: +// 1. IS_DOT11D_ENABLE() is TRUE. +// 2. Input IE is an valid one. +// +void +Dot11d_UpdateCountryIe( + struct ieee80211_device *dev, + u8 * pTaddr, + u16 CoutryIeLen, + u8 * pCoutryIe + ) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); + u8 i, j, NumTriples, MaxChnlNum; + PCHNL_TXPOWER_TRIPLE pTriple; + + memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + MaxChnlNum = 0; + NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string. + pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3); + for(i = 0; i < NumTriples; i++) + { + if(MaxChnlNum >= pTriple->FirstChnl) + { // It is not in a monotonically increasing order, so stop processing. + printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); + return; + } + if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls)) + { // It is not a valid set of channel id, so stop processing. + printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n"); + return; + } + + for(j = 0 ; j < pTriple->NumChnls; j++) + { + pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1; + pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm; + MaxChnlNum = pTriple->FirstChnl + j; + } + + pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3); + } + //printk("Dot11d_UpdateCountryIe(): Channel List:\n"); + printk("Channel List:"); + for(i=1; i<= MAX_CHANNEL_NUMBER; i++) + if(pDot11dInfo->channel_map[i] > 0) + printk(" %d", i); + printk("\n"); + + UPDATE_CIE_SRC(dev, pTaddr); + + pDot11dInfo->CountryIeLen = CoutryIeLen; + memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen); + pDot11dInfo->State = DOT11D_STATE_LEARNED; +} + + +u8 +DOT11D_GetMaxTxPwrInDbm( + struct ieee80211_device *dev, + u8 Channel + ) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); + u8 MaxTxPwrInDbm = 255; + + if(MAX_CHANNEL_NUMBER < Channel) + { + printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n"); + return MaxTxPwrInDbm; + } + if(pDot11dInfo->channel_map[Channel]) + { + MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel]; + } + + return MaxTxPwrInDbm; +} + + +void +DOT11D_ScanComplete( + struct ieee80211_device * dev + ) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); + + switch(pDot11dInfo->State) + { + case DOT11D_STATE_LEARNED: + pDot11dInfo->State = DOT11D_STATE_DONE; + break; + + case DOT11D_STATE_DONE: + if( GET_CIE_WATCHDOG(dev) == 0 ) + { // Reset country IE if previous one is gone. + Dot11d_Reset(dev); + } + break; + case DOT11D_STATE_NONE: + break; + } +} + +int IsLegalChannel( + struct ieee80211_device * dev, + u8 channel +) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); + + if(MAX_CHANNEL_NUMBER < channel) + { + printk("IsLegalChannel(): Invalid Channel\n"); + return 0; + } + if(pDot11dInfo->channel_map[channel] > 0) + return 1; + return 0; +} + +int ToLegalChannel( + struct ieee80211_device * dev, + u8 channel +) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); + u8 default_chn = 0; + u32 i = 0; + + for (i=1; i<= MAX_CHANNEL_NUMBER; i++) + { + if(pDot11dInfo->channel_map[i] > 0) + { + default_chn = i; + break; + } + } + + if(MAX_CHANNEL_NUMBER < channel) + { + printk("IsLegalChannel(): Invalid Channel\n"); + return default_chn; + } + + if(pDot11dInfo->channel_map[channel] > 0) + return channel; + + return default_chn; +} +EXPORT_SYMBOL(Dot11d_Init); +EXPORT_SYMBOL(Dot11d_Reset); +EXPORT_SYMBOL(Dot11d_UpdateCountryIe); +EXPORT_SYMBOL(DOT11D_GetMaxTxPwrInDbm); +EXPORT_SYMBOL(DOT11D_ScanComplete); +EXPORT_SYMBOL(IsLegalChannel); +EXPORT_SYMBOL(ToLegalChannel); + +#endif diff --git a/drivers/staging/rtl8192u/ieee80211/dot11d.h b/drivers/staging/rtl8192u/ieee80211/dot11d.h new file mode 100644 index 0000000000000000000000000000000000000000..15b7a4ba37b6d2eba496686cba3571b1434879cf --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/dot11d.h @@ -0,0 +1,102 @@ +#ifndef __INC_DOT11D_H +#define __INC_DOT11D_H + +#ifdef ENABLE_DOT11D +#include "ieee80211.h" + +//#define ENABLE_DOT11D + +//#define DOT11D_MAX_CHNL_NUM 83 + +typedef struct _CHNL_TXPOWER_TRIPLE { + u8 FirstChnl; + u8 NumChnls; + u8 MaxTxPowerInDbm; +}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE; + +typedef enum _DOT11D_STATE { + DOT11D_STATE_NONE = 0, + DOT11D_STATE_LEARNED, + DOT11D_STATE_DONE, +}DOT11D_STATE; + +typedef struct _RT_DOT11D_INFO { + //DECLARE_RT_OBJECT(RT_DOT11D_INFO); + + bool bEnabled; // dot11MultiDomainCapabilityEnabled + + u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element. + u8 CountryIeBuf[MAX_IE_LEN]; + u8 CountryIeSrcAddr[6]; // Source AP of the country IE. + u8 CountryIeWatchdog; + + u8 channel_map[MAX_CHANNEL_NUMBER+1]; //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) + //u8 ChnlListLen; // #Bytes valid in ChnlList[]. + //u8 ChnlList[DOT11D_MAX_CHNL_NUM]; + u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1]; + + DOT11D_STATE State; +}RT_DOT11D_INFO, *PRT_DOT11D_INFO; +#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 ) +#define cpMacAddr(des,src) ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5]) +#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo)) + +#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled +#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0) + +#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) +#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) + +#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \ + (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \ + FALSE : \ + (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length))) + +#define CIE_WATCHDOG_TH 1 +#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog +#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0 +#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev) + +#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE) + + +void +Dot11d_Init( + struct ieee80211_device *dev + ); + +void +Dot11d_Reset( + struct ieee80211_device *dev + ); + +void +Dot11d_UpdateCountryIe( + struct ieee80211_device *dev, + u8 * pTaddr, + u16 CoutryIeLen, + u8 * pCoutryIe + ); + +u8 +DOT11D_GetMaxTxPwrInDbm( + struct ieee80211_device *dev, + u8 Channel + ); + +void +DOT11D_ScanComplete( + struct ieee80211_device * dev + ); + +int IsLegalChannel( + struct ieee80211_device * dev, + u8 channel +); + +int ToLegalChannel( + struct ieee80211_device * dev, + u8 channel +); +#endif //ENABLE_DOT11D +#endif // #ifndef __INC_DOT11D_H diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h new file mode 100644 index 0000000000000000000000000000000000000000..10908e123b86f7486ed3890f4879bb0bb63ddde0 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -0,0 +1,2639 @@ +/* + * Merged with mainline ieee80211.h in Aug 2004. Original ieee802_11 + * remains copyright by the original authors + * + * Portions of the merged code are based on Host AP (software wireless + * LAN access point) driver for Intersil Prism2/2.5/3. + * + * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen + * + * Copyright (c) 2002-2003, Jouni Malinen + * + * Adaption to a generic IEEE 802.11 stack by James Ketrenos + * + * Copyright (c) 2004, Intel Corporation + * + * Modified for Realtek's wi-fi cards by Andrea Merello + * + * + * 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. See README and COPYING for + * more details. + */ +#ifndef IEEE80211_H +#define IEEE80211_H +#include /* ETH_ALEN */ +#include /* ARRAY_SIZE */ +#include +#include +#include +#include +#include + +#include +#include + +#include "rtl819x_HT.h" +#include "rtl819x_BA.h" +#include "rtl819x_TS.h" + + +#ifndef IW_MODE_MONITOR +#define IW_MODE_MONITOR 6 +#endif + +#ifndef IWEVCUSTOM +#define IWEVCUSTOM 0x8c02 +#endif + + +#ifndef container_of +/** + * container_of - cast a member of a structure out to the containing structure + * + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#endif + +#define KEY_TYPE_NA 0x0 +#define KEY_TYPE_WEP40 0x1 +#define KEY_TYPE_TKIP 0x2 +#define KEY_TYPE_CCMP 0x4 +#define KEY_TYPE_WEP104 0x5 + +/* added for rtl819x tx procedure */ +#define MAX_QUEUE_SIZE 0x10 + +// +// 8190 queue mapping +// +#define BK_QUEUE 0 +#define BE_QUEUE 1 +#define VI_QUEUE 2 +#define VO_QUEUE 3 +#define HCCA_QUEUE 4 +#define TXCMD_QUEUE 5 +#define MGNT_QUEUE 6 +#define HIGH_QUEUE 7 +#define BEACON_QUEUE 8 + +#define LOW_QUEUE BE_QUEUE +#define NORMAL_QUEUE MGNT_QUEUE + +//added by amy for ps +#define SWRF_TIMEOUT 50 + +//added by amy for LEAP related +#define IE_CISCO_FLAG_POSITION 0x08 // Flag byte: byte 8, numbered from 0. +#define SUPPORT_CKIP_MIC 0x08 // bit3 +#define SUPPORT_CKIP_PK 0x10 // bit4 +/* defined for skb cb field */ +/* At most 28 byte */ +typedef struct cb_desc { + /* Tx Desc Related flags (8-9) */ + u8 bLastIniPkt:1; + u8 bCmdOrInit:1; + u8 bFirstSeg:1; + u8 bLastSeg:1; + u8 bEncrypt:1; + u8 bTxDisableRateFallBack:1; + u8 bTxUseDriverAssingedRate:1; + u8 bHwSec:1; //indicate whether use Hw security. WB + + u8 reserved1; + + /* Tx Firmware Relaged flags (10-11)*/ + u8 bCTSEnable:1; + u8 bRTSEnable:1; + u8 bUseShortGI:1; + u8 bUseShortPreamble:1; + u8 bTxEnableFwCalcDur:1; + u8 bAMPDUEnable:1; + u8 bRTSSTBC:1; + u8 RTSSC:1; + + u8 bRTSBW:1; + u8 bPacketBW:1; + u8 bRTSUseShortPreamble:1; + u8 bRTSUseShortGI:1; + u8 bMulticast:1; + u8 bBroadcast:1; + //u8 reserved2:2; + u8 drv_agg_enable:1; + u8 reserved2:1; + + /* Tx Desc related element(12-19) */ + u8 rata_index; + u8 queue_index; + //u8 reserved3; + //u8 reserved4; + u16 txbuf_size; + //u8 reserved5; + u8 RATRIndex; + u8 reserved6; + u8 reserved7; + u8 reserved8; + + /* Tx firmware related element(20-27) */ + u8 data_rate; + u8 rts_rate; + u8 ampdu_factor; + u8 ampdu_density; + //u8 reserved9; + //u8 reserved10; + //u8 reserved11; + u8 DrvAggrNum; + u16 pkt_size; + u8 reserved12; +}cb_desc, *pcb_desc; + +/*--------------------------Define -------------------------------------------*/ +#define MGN_1M 0x02 +#define MGN_2M 0x04 +#define MGN_5_5M 0x0b +#define MGN_11M 0x16 + +#define MGN_6M 0x0c +#define MGN_9M 0x12 +#define MGN_12M 0x18 +#define MGN_18M 0x24 +#define MGN_24M 0x30 +#define MGN_36M 0x48 +#define MGN_48M 0x60 +#define MGN_54M 0x6c + +#define MGN_MCS0 0x80 +#define MGN_MCS1 0x81 +#define MGN_MCS2 0x82 +#define MGN_MCS3 0x83 +#define MGN_MCS4 0x84 +#define MGN_MCS5 0x85 +#define MGN_MCS6 0x86 +#define MGN_MCS7 0x87 +#define MGN_MCS8 0x88 +#define MGN_MCS9 0x89 +#define MGN_MCS10 0x8a +#define MGN_MCS11 0x8b +#define MGN_MCS12 0x8c +#define MGN_MCS13 0x8d +#define MGN_MCS14 0x8e +#define MGN_MCS15 0x8f + +//---------------------------------------------------------------------------- +// 802.11 Management frame Reason Code field +//---------------------------------------------------------------------------- +enum _ReasonCode{ + unspec_reason = 0x1, + auth_not_valid = 0x2, + deauth_lv_ss = 0x3, + inactivity = 0x4, + ap_overload = 0x5, + class2_err = 0x6, + class3_err = 0x7, + disas_lv_ss = 0x8, + asoc_not_auth = 0x9, + + //----MIC_CHECK + mic_failure = 0xe, + //----END MIC_CHECK + + // Reason code defined in 802.11i D10.0 p.28. + invalid_IE = 0x0d, + four_way_tmout = 0x0f, + two_way_tmout = 0x10, + IE_dismatch = 0x11, + invalid_Gcipher = 0x12, + invalid_Pcipher = 0x13, + invalid_AKMP = 0x14, + unsup_RSNIEver = 0x15, + invalid_RSNIE = 0x16, + auth_802_1x_fail= 0x17, + ciper_reject = 0x18, + + // Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie, 2005-11-15. + QoS_unspec = 0x20, // 32 + QAP_bandwidth = 0x21, // 33 + poor_condition = 0x22, // 34 + no_facility = 0x23, // 35 + // Where is 36??? + req_declined = 0x25, // 37 + invalid_param = 0x26, // 38 + req_not_honored= 0x27, // 39 + TS_not_created = 0x2F, // 47 + DL_not_allowed = 0x30, // 48 + dest_not_exist = 0x31, // 49 + dest_not_QSTA = 0x32, // 50 +}; + + + +#define aSifsTime ((priv->ieee80211->current_network.mode == IEEE_A)||(priv->ieee80211->current_network.mode == IEEE_N_24G)||(priv->ieee80211->current_network.mode == IEEE_N_5G))? 16 : 10 + +#define MGMT_QUEUE_NUM 5 + +#define IEEE_CMD_SET_WPA_PARAM 1 +#define IEEE_CMD_SET_WPA_IE 2 +#define IEEE_CMD_SET_ENCRYPTION 3 +#define IEEE_CMD_MLME 4 + +#define IEEE_PARAM_WPA_ENABLED 1 +#define IEEE_PARAM_TKIP_COUNTERMEASURES 2 +#define IEEE_PARAM_DROP_UNENCRYPTED 3 +#define IEEE_PARAM_PRIVACY_INVOKED 4 +#define IEEE_PARAM_AUTH_ALGS 5 +#define IEEE_PARAM_IEEE_802_1X 6 +//It should consistent with the driver_XXX.c +// David, 2006.9.26 +#define IEEE_PARAM_WPAX_SELECT 7 +//Added for notify the encryption type selection +// David, 2006.9.26 +#define IEEE_PROTO_WPA 1 +#define IEEE_PROTO_RSN 2 +//Added for notify the encryption type selection +// David, 2006.9.26 +#define IEEE_WPAX_USEGROUP 0 +#define IEEE_WPAX_WEP40 1 +#define IEEE_WPAX_TKIP 2 +#define IEEE_WPAX_WRAP 3 +#define IEEE_WPAX_CCMP 4 +#define IEEE_WPAX_WEP104 5 + +#define IEEE_KEY_MGMT_IEEE8021X 1 +#define IEEE_KEY_MGMT_PSK 2 + +#define IEEE_MLME_STA_DEAUTH 1 +#define IEEE_MLME_STA_DISASSOC 2 + + +#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2 +#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3 +#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4 +#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5 +#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6 +#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7 + + +#define IEEE_CRYPT_ALG_NAME_LEN 16 + +#define MAX_IE_LEN 0xff + +// added for kernel conflict +#define ieee80211_crypt_deinit_entries ieee80211_crypt_deinit_entries_rsl +#define ieee80211_crypt_deinit_handler ieee80211_crypt_deinit_handler_rsl +#define ieee80211_crypt_delayed_deinit ieee80211_crypt_delayed_deinit_rsl +#define ieee80211_register_crypto_ops ieee80211_register_crypto_ops_rsl +#define ieee80211_unregister_crypto_ops ieee80211_unregister_crypto_ops_rsl +#define ieee80211_get_crypto_ops ieee80211_get_crypto_ops_rsl + +#define ieee80211_ccmp_null ieee80211_ccmp_null_rsl + +#define ieee80211_tkip_null ieee80211_tkip_null_rsl + +#define ieee80211_wep_null ieee80211_wep_null_rsl + +#define free_ieee80211 free_ieee80211_rsl +#define alloc_ieee80211 alloc_ieee80211_rsl + +#define ieee80211_rx ieee80211_rx_rsl +#define ieee80211_rx_mgt ieee80211_rx_mgt_rsl + +#define ieee80211_get_beacon ieee80211_get_beacon_rsl +#define ieee80211_wake_queue ieee80211_wake_queue_rsl +#define ieee80211_stop_queue ieee80211_stop_queue_rsl +#define ieee80211_reset_queue ieee80211_reset_queue_rsl +#define ieee80211_softmac_stop_protocol ieee80211_softmac_stop_protocol_rsl +#define ieee80211_softmac_start_protocol ieee80211_softmac_start_protocol_rsl +#define ieee80211_is_shortslot ieee80211_is_shortslot_rsl +#define ieee80211_is_54g ieee80211_is_54g_rsl +#define ieee80211_wpa_supplicant_ioctl ieee80211_wpa_supplicant_ioctl_rsl +#define ieee80211_ps_tx_ack ieee80211_ps_tx_ack_rsl +#define ieee80211_softmac_xmit ieee80211_softmac_xmit_rsl +#define ieee80211_stop_send_beacons ieee80211_stop_send_beacons_rsl +#define notify_wx_assoc_event notify_wx_assoc_event_rsl +#define SendDisassociation SendDisassociation_rsl +#define ieee80211_disassociate ieee80211_disassociate_rsl +#define ieee80211_start_send_beacons ieee80211_start_send_beacons_rsl +#define ieee80211_stop_scan ieee80211_stop_scan_rsl +#define ieee80211_send_probe_requests ieee80211_send_probe_requests_rsl +#define ieee80211_softmac_scan_syncro ieee80211_softmac_scan_syncro_rsl +#define ieee80211_start_scan_syncro ieee80211_start_scan_syncro_rsl + +#define ieee80211_wx_get_essid ieee80211_wx_get_essid_rsl +#define ieee80211_wx_set_essid ieee80211_wx_set_essid_rsl +#define ieee80211_wx_set_rate ieee80211_wx_set_rate_rsl +#define ieee80211_wx_get_rate ieee80211_wx_get_rate_rsl +#define ieee80211_wx_set_wap ieee80211_wx_set_wap_rsl +#define ieee80211_wx_get_wap ieee80211_wx_get_wap_rsl +#define ieee80211_wx_set_mode ieee80211_wx_set_mode_rsl +#define ieee80211_wx_get_mode ieee80211_wx_get_mode_rsl +#define ieee80211_wx_set_scan ieee80211_wx_set_scan_rsl +#define ieee80211_wx_get_freq ieee80211_wx_get_freq_rsl +#define ieee80211_wx_set_freq ieee80211_wx_set_freq_rsl +#define ieee80211_wx_set_rawtx ieee80211_wx_set_rawtx_rsl +#define ieee80211_wx_get_name ieee80211_wx_get_name_rsl +#define ieee80211_wx_set_power ieee80211_wx_set_power_rsl +#define ieee80211_wx_get_power ieee80211_wx_get_power_rsl +#define ieee80211_wlan_frequencies ieee80211_wlan_frequencies_rsl +#define ieee80211_wx_set_rts ieee80211_wx_set_rts_rsl +#define ieee80211_wx_get_rts ieee80211_wx_get_rts_rsl + +#define ieee80211_txb_free ieee80211_txb_free_rsl + +#define ieee80211_wx_set_gen_ie ieee80211_wx_set_gen_ie_rsl +#define ieee80211_wx_get_scan ieee80211_wx_get_scan_rsl +#define ieee80211_wx_set_encode ieee80211_wx_set_encode_rsl +#define ieee80211_wx_get_encode ieee80211_wx_get_encode_rsl +#if WIRELESS_EXT >= 18 +#define ieee80211_wx_set_mlme ieee80211_wx_set_mlme_rsl +#define ieee80211_wx_set_auth ieee80211_wx_set_auth_rsl +#define ieee80211_wx_set_encode_ext ieee80211_wx_set_encode_ext_rsl +#define ieee80211_wx_get_encode_ext ieee80211_wx_get_encode_ext_rsl +#endif + + +typedef struct ieee_param { + u32 cmd; + u8 sta_addr[ETH_ALEN]; + union { + struct { + u8 name; + u32 value; + } wpa_param; + struct { + u32 len; + u8 reserved[32]; + u8 data[0]; + } wpa_ie; + struct{ + int command; + int reason_code; + } mlme; + struct { + u8 alg[IEEE_CRYPT_ALG_NAME_LEN]; + u8 set_tx; + u32 err; + u8 idx; + u8 seq[8]; /* sequence counter (set: RX, get: TX) */ + u16 key_len; + u8 key[0]; + } crypt; + } u; +}ieee_param; + + +#if WIRELESS_EXT < 17 +#define IW_QUAL_QUAL_INVALID 0x10 +#define IW_QUAL_LEVEL_INVALID 0x20 +#define IW_QUAL_NOISE_INVALID 0x40 +#define IW_QUAL_QUAL_UPDATED 0x1 +#define IW_QUAL_LEVEL_UPDATED 0x2 +#define IW_QUAL_NOISE_UPDATED 0x4 +#endif + + +// linux under 2.6.9 release may not support it, so modify it for common use +#define MSECS(t) msecs_to_jiffies(t) +#define msleep_interruptible_rsl msleep_interruptible + +#define IEEE80211_DATA_LEN 2304 +/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section + 6.2.1.1.2. + + The figure in section 7.1.2 suggests a body size of up to 2312 + bytes is allowed, which is a bit confusing, I suspect this + represents the 2304 bytes of real data, plus a possible 8 bytes of + WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */ +#define IEEE80211_1ADDR_LEN 10 +#define IEEE80211_2ADDR_LEN 16 +#define IEEE80211_3ADDR_LEN 24 +#define IEEE80211_4ADDR_LEN 30 +#define IEEE80211_FCS_LEN 4 +#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) +#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) +#define IEEE80211_MGMT_HDR_LEN 24 +#define IEEE80211_DATA_HDR3_LEN 24 +#define IEEE80211_DATA_HDR4_LEN 30 + +#define MIN_FRAG_THRESHOLD 256U +#define MAX_FRAG_THRESHOLD 2346U + + +/* Frame control field constants */ +#define IEEE80211_FCTL_VERS 0x0003 +#define IEEE80211_FCTL_FTYPE 0x000c +#define IEEE80211_FCTL_STYPE 0x00f0 +#define IEEE80211_FCTL_FRAMETYPE 0x00fc +#define IEEE80211_FCTL_TODS 0x0100 +#define IEEE80211_FCTL_FROMDS 0x0200 +#define IEEE80211_FCTL_DSTODS 0x0300 //added by david +#define IEEE80211_FCTL_MOREFRAGS 0x0400 +#define IEEE80211_FCTL_RETRY 0x0800 +#define IEEE80211_FCTL_PM 0x1000 +#define IEEE80211_FCTL_MOREDATA 0x2000 +#define IEEE80211_FCTL_WEP 0x4000 +#define IEEE80211_FCTL_ORDER 0x8000 + +#define IEEE80211_FTYPE_MGMT 0x0000 +#define IEEE80211_FTYPE_CTL 0x0004 +#define IEEE80211_FTYPE_DATA 0x0008 + +/* management */ +#define IEEE80211_STYPE_ASSOC_REQ 0x0000 +#define IEEE80211_STYPE_ASSOC_RESP 0x0010 +#define IEEE80211_STYPE_REASSOC_REQ 0x0020 +#define IEEE80211_STYPE_REASSOC_RESP 0x0030 +#define IEEE80211_STYPE_PROBE_REQ 0x0040 +#define IEEE80211_STYPE_PROBE_RESP 0x0050 +#define IEEE80211_STYPE_BEACON 0x0080 +#define IEEE80211_STYPE_ATIM 0x0090 +#define IEEE80211_STYPE_DISASSOC 0x00A0 +#define IEEE80211_STYPE_AUTH 0x00B0 +#define IEEE80211_STYPE_DEAUTH 0x00C0 +#define IEEE80211_STYPE_MANAGE_ACT 0x00D0 + +/* control */ +#define IEEE80211_STYPE_PSPOLL 0x00A0 +#define IEEE80211_STYPE_RTS 0x00B0 +#define IEEE80211_STYPE_CTS 0x00C0 +#define IEEE80211_STYPE_ACK 0x00D0 +#define IEEE80211_STYPE_CFEND 0x00E0 +#define IEEE80211_STYPE_CFENDACK 0x00F0 +#define IEEE80211_STYPE_BLOCKACK 0x0094 + +/* data */ +#define IEEE80211_STYPE_DATA 0x0000 +#define IEEE80211_STYPE_DATA_CFACK 0x0010 +#define IEEE80211_STYPE_DATA_CFPOLL 0x0020 +#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 +#define IEEE80211_STYPE_NULLFUNC 0x0040 +#define IEEE80211_STYPE_CFACK 0x0050 +#define IEEE80211_STYPE_CFPOLL 0x0060 +#define IEEE80211_STYPE_CFACKPOLL 0x0070 +#define IEEE80211_STYPE_QOS_DATA 0x0080 //added for WMM 2006/8/2 +#define IEEE80211_STYPE_QOS_NULL 0x00C0 + +#define IEEE80211_SCTL_FRAG 0x000F +#define IEEE80211_SCTL_SEQ 0xFFF0 + +/* QOS control */ +#define IEEE80211_QCTL_TID 0x000F + +#define FC_QOS_BIT BIT7 +#define IsDataFrame(pdu) ( ((pdu[0] & 0x0C)==0x08) ? true : false ) +#define IsLegacyDataFrame(pdu) (IsDataFrame(pdu) && (!(pdu[0]&FC_QOS_BIT)) ) +//added by wb. Is this right? +#define IsQoSDataFrame(pframe) ((*(u16*)pframe&(IEEE80211_STYPE_QOS_DATA|IEEE80211_FTYPE_DATA)) == (IEEE80211_STYPE_QOS_DATA|IEEE80211_FTYPE_DATA)) +#define Frame_Order(pframe) (*(u16*)pframe&IEEE80211_FCTL_ORDER) +#define SN_LESS(a, b) (((a-b)&0x800)!=0) +#define SN_EQUAL(a, b) (a == b) +#define MAX_DEV_ADDR_SIZE 8 +typedef enum _ACT_CATEGORY{ + ACT_CAT_QOS = 1, + ACT_CAT_DLS = 2, + ACT_CAT_BA = 3, + ACT_CAT_HT = 7, + ACT_CAT_WMM = 17, +} ACT_CATEGORY, *PACT_CATEGORY; + +typedef enum _TS_ACTION{ + ACT_ADDTSREQ = 0, + ACT_ADDTSRSP = 1, + ACT_DELTS = 2, + ACT_SCHEDULE = 3, +} TS_ACTION, *PTS_ACTION; + +typedef enum _BA_ACTION{ + ACT_ADDBAREQ = 0, + ACT_ADDBARSP = 1, + ACT_DELBA = 2, +} BA_ACTION, *PBA_ACTION; + +typedef enum _InitialGainOpType{ + IG_Backup=0, + IG_Restore, + IG_Max +}InitialGainOpType; + +/* debug macros */ +#define CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_IEEE80211_DEBUG +extern u32 ieee80211_debug_level; +#define IEEE80211_DEBUG(level, fmt, args...) \ +do { if (ieee80211_debug_level & (level)) \ + printk(KERN_DEBUG "ieee80211: " fmt, ## args); } while (0) +//wb added to debug out data buf +//if you want print DATA buffer related BA, please set ieee80211_debug_level to DATA|BA +#define IEEE80211_DEBUG_DATA(level, data, datalen) \ + do{ if ((ieee80211_debug_level & (level)) == (level)) \ + { \ + int i; \ + u8* pdata = (u8*) data; \ + printk(KERN_DEBUG "ieee80211: %s()\n", __FUNCTION__); \ + for(i=0; i<(int)(datalen); i++) \ + { \ + printk("%2x ", pdata[i]); \ + if ((i+1)%16 == 0) printk("\n"); \ + } \ + printk("\n"); \ + } \ + } while (0) +#else +#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0) +#define IEEE80211_DEBUG_DATA(level, data, datalen) do {} while(0) +#endif /* CONFIG_IEEE80211_DEBUG */ + +/* debug macros not dependent on CONFIG_IEEE80211_DEBUG */ + +#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5] + +/* + * To use the debug system; + * + * If you are defining a new debug classification, simply add it to the #define + * list here in the form of: + * + * #define IEEE80211_DL_xxxx VALUE + * + * shifting value to the left one bit from the previous entry. xxxx should be + * the name of the classification (for example, WEP) + * + * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your + * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want + * to send output to that classification. + * + * To add your debug level to the list of levels seen when you perform + * + * % cat /proc/net/ipw/debug_level + * + * you simply need to add your entry to the ipw_debug_levels array. + * + * If you do not see debug_level in /proc/net/ipw then you do not have + * CONFIG_IEEE80211_DEBUG defined in your kernel configuration + * + */ + +#define IEEE80211_DL_INFO (1<<0) +#define IEEE80211_DL_WX (1<<1) +#define IEEE80211_DL_SCAN (1<<2) +#define IEEE80211_DL_STATE (1<<3) +#define IEEE80211_DL_MGMT (1<<4) +#define IEEE80211_DL_FRAG (1<<5) +#define IEEE80211_DL_EAP (1<<6) +#define IEEE80211_DL_DROP (1<<7) + +#define IEEE80211_DL_TX (1<<8) +#define IEEE80211_DL_RX (1<<9) + +#define IEEE80211_DL_HT (1<<10) //HT +#define IEEE80211_DL_BA (1<<11) //ba +#define IEEE80211_DL_TS (1<<12) //TS +#define IEEE80211_DL_QOS (1<<13) +#define IEEE80211_DL_REORDER (1<<14) +#define IEEE80211_DL_IOT (1<<15) +#define IEEE80211_DL_IPS (1<<16) +#define IEEE80211_DL_TRACE (1<<29) //trace function, need to user net_ratelimit() together in order not to print too much to the screen +#define IEEE80211_DL_DATA (1<<30) //use this flag to control whether print data buf out. +#define IEEE80211_DL_ERR (1<<31) //always open +#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a) +#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a) +#define IEEE80211_DEBUG_INFO(f, a...) IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a) + +#define IEEE80211_DEBUG_WX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a) +#define IEEE80211_DEBUG_SCAN(f, a...) IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a) +#define IEEE80211_DEBUG_STATE(f, a...) IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a) +#define IEEE80211_DEBUG_MGMT(f, a...) IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a) +#define IEEE80211_DEBUG_FRAG(f, a...) IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a) +#define IEEE80211_DEBUG_EAP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a) +#define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a) +#define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a) +#define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a) +#define IEEE80211_DEBUG_QOS(f, a...) IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a) + +#ifdef CONFIG_IEEE80211_DEBUG +/* Added by Annie, 2005-11-22. */ +#define MAX_STR_LEN 64 +/* I want to see ASCII 33 to 126 only. Otherwise, I print '?'. Annie, 2005-11-22.*/ +#define PRINTABLE(_ch) (_ch>'!' && _ch<'~') +#define IEEE80211_PRINT_STR(_Comp, _TitleString, _Ptr, _Len) \ + if((_Comp) & level) \ + { \ + int __i; \ + u8 buffer[MAX_STR_LEN]; \ + int length = (_Len\n", _Len, buffer); \ + } +#else +#define IEEE80211_PRINT_STR(_Comp, _TitleString, _Ptr, _Len) do {} while (0) +#endif + +#include +#include /* ARPHRD_ETHER */ + +#ifndef WIRELESS_SPY +#define WIRELESS_SPY // enable iwspy support +#endif +#include // new driver API + +#ifndef ETH_P_PAE +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#endif /* ETH_P_PAE */ + +#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ + +#ifndef ETH_P_80211_RAW +#define ETH_P_80211_RAW (ETH_P_ECONET + 1) +#endif + +/* IEEE 802.11 defines */ + +#define P80211_OUI_LEN 3 + +struct ieee80211_snap_hdr { + + u8 dsap; /* always 0xAA */ + u8 ssap; /* always 0xAA */ + u8 ctrl; /* always 0x03 */ + u8 oui[P80211_OUI_LEN]; /* organizational universal id */ + +} __attribute__ ((packed)); + +#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) + +#define WLAN_FC_GET_VERS(fc) ((fc) & IEEE80211_FCTL_VERS) +#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE) +#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE) + +#define WLAN_FC_GET_FRAMETYPE(fc) ((fc) & IEEE80211_FCTL_FRAMETYPE) +#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG) +#define WLAN_GET_SEQ_SEQ(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) + +/* Authentication algorithms */ +#define WLAN_AUTH_OPEN 0 +#define WLAN_AUTH_SHARED_KEY 1 +#define WLAN_AUTH_LEAP 2 + +#define WLAN_AUTH_CHALLENGE_LEN 128 + +#define WLAN_CAPABILITY_BSS (1<<0) +#define WLAN_CAPABILITY_IBSS (1<<1) +#define WLAN_CAPABILITY_CF_POLLABLE (1<<2) +#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) +#define WLAN_CAPABILITY_PRIVACY (1<<4) +#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) +#define WLAN_CAPABILITY_PBCC (1<<6) +#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) +#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) +#define WLAN_CAPABILITY_QOS (1<<9) +#define WLAN_CAPABILITY_SHORT_SLOT (1<<10) +#define WLAN_CAPABILITY_DSSS_OFDM (1<<13) + +/* 802.11g ERP information element */ +#define WLAN_ERP_NON_ERP_PRESENT (1<<0) +#define WLAN_ERP_USE_PROTECTION (1<<1) +#define WLAN_ERP_BARKER_PREAMBLE (1<<2) + +/* Status codes */ +enum ieee80211_statuscode { + WLAN_STATUS_SUCCESS = 0, + WLAN_STATUS_UNSPECIFIED_FAILURE = 1, + WLAN_STATUS_CAPS_UNSUPPORTED = 10, + WLAN_STATUS_REASSOC_NO_ASSOC = 11, + WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12, + WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13, + WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14, + WLAN_STATUS_CHALLENGE_FAIL = 15, + WLAN_STATUS_AUTH_TIMEOUT = 16, + WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17, + WLAN_STATUS_ASSOC_DENIED_RATES = 18, + /* 802.11b */ + WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19, + WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20, + WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21, + /* 802.11h */ + WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22, + WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23, + WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24, + /* 802.11g */ + WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25, + WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26, + /* 802.11i */ + WLAN_STATUS_INVALID_IE = 40, + WLAN_STATUS_INVALID_GROUP_CIPHER = 41, + WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42, + WLAN_STATUS_INVALID_AKMP = 43, + WLAN_STATUS_UNSUPP_RSN_VERSION = 44, + WLAN_STATUS_INVALID_RSN_IE_CAP = 45, + WLAN_STATUS_CIPHER_SUITE_REJECTED = 46, +}; + +/* Reason codes */ +enum ieee80211_reasoncode { + WLAN_REASON_UNSPECIFIED = 1, + WLAN_REASON_PREV_AUTH_NOT_VALID = 2, + WLAN_REASON_DEAUTH_LEAVING = 3, + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4, + WLAN_REASON_DISASSOC_AP_BUSY = 5, + WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6, + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7, + WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8, + WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9, + /* 802.11h */ + WLAN_REASON_DISASSOC_BAD_POWER = 10, + WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11, + /* 802.11i */ + WLAN_REASON_INVALID_IE = 13, + WLAN_REASON_MIC_FAILURE = 14, + WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, + WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16, + WLAN_REASON_IE_DIFFERENT = 17, + WLAN_REASON_INVALID_GROUP_CIPHER = 18, + WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19, + WLAN_REASON_INVALID_AKMP = 20, + WLAN_REASON_UNSUPP_RSN_VERSION = 21, + WLAN_REASON_INVALID_RSN_IE_CAP = 22, + WLAN_REASON_IEEE8021X_FAILED = 23, + WLAN_REASON_CIPHER_SUITE_REJECTED = 24, +}; + +#define IEEE80211_STATMASK_SIGNAL (1<<0) +#define IEEE80211_STATMASK_RSSI (1<<1) +#define IEEE80211_STATMASK_NOISE (1<<2) +#define IEEE80211_STATMASK_RATE (1<<3) +#define IEEE80211_STATMASK_WEMASK 0x7 + +#define IEEE80211_CCK_MODULATION (1<<0) +#define IEEE80211_OFDM_MODULATION (1<<1) + +#define IEEE80211_24GHZ_BAND (1<<0) +#define IEEE80211_52GHZ_BAND (1<<1) + +#define IEEE80211_CCK_RATE_LEN 4 +#define IEEE80211_CCK_RATE_1MB 0x02 +#define IEEE80211_CCK_RATE_2MB 0x04 +#define IEEE80211_CCK_RATE_5MB 0x0B +#define IEEE80211_CCK_RATE_11MB 0x16 +#define IEEE80211_OFDM_RATE_LEN 8 +#define IEEE80211_OFDM_RATE_6MB 0x0C +#define IEEE80211_OFDM_RATE_9MB 0x12 +#define IEEE80211_OFDM_RATE_12MB 0x18 +#define IEEE80211_OFDM_RATE_18MB 0x24 +#define IEEE80211_OFDM_RATE_24MB 0x30 +#define IEEE80211_OFDM_RATE_36MB 0x48 +#define IEEE80211_OFDM_RATE_48MB 0x60 +#define IEEE80211_OFDM_RATE_54MB 0x6C +#define IEEE80211_BASIC_RATE_MASK 0x80 + +#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) +#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) +#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) +#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) +#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) +#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) +#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) +#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) +#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) +#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) +#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) +#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) + +#define IEEE80211_CCK_RATES_MASK 0x0000000F +#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ + IEEE80211_CCK_RATE_2MB_MASK) +#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ + IEEE80211_CCK_RATE_5MB_MASK | \ + IEEE80211_CCK_RATE_11MB_MASK) + +#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 +#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ + IEEE80211_OFDM_RATE_12MB_MASK | \ + IEEE80211_OFDM_RATE_24MB_MASK) +#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ + IEEE80211_OFDM_RATE_9MB_MASK | \ + IEEE80211_OFDM_RATE_18MB_MASK | \ + IEEE80211_OFDM_RATE_36MB_MASK | \ + IEEE80211_OFDM_RATE_48MB_MASK | \ + IEEE80211_OFDM_RATE_54MB_MASK) +#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ + IEEE80211_CCK_DEFAULT_RATES_MASK) + +#define IEEE80211_NUM_OFDM_RATES 8 +#define IEEE80211_NUM_CCK_RATES 4 +#define IEEE80211_OFDM_SHIFT_MASK_A 4 + + +/* this is stolen and modified from the madwifi driver*/ +#define IEEE80211_FC0_TYPE_MASK 0x0c +#define IEEE80211_FC0_TYPE_DATA 0x08 +#define IEEE80211_FC0_SUBTYPE_MASK 0xB0 +#define IEEE80211_FC0_SUBTYPE_QOS 0x80 + +#define IEEE80211_QOS_HAS_SEQ(fc) \ + (((fc) & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == \ + (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) + +/* this is stolen from ipw2200 driver */ +#define IEEE_IBSS_MAC_HASH_SIZE 31 +struct ieee_ibss_seq { + u8 mac[ETH_ALEN]; + u16 seq_num[17]; + u16 frag_num[17]; + unsigned long packet_time[17]; + struct list_head list; +}; + +/* NOTE: This data is for statistical purposes; not all hardware provides this + * information for frames received. Not setting these will not cause + * any adverse affects. */ +struct ieee80211_rx_stats { + u32 mac_time[2]; + s8 rssi; + u8 signal; + u8 noise; + u16 rate; /* in 100 kbps */ + u8 received_channel; + u8 control; + u8 mask; + u8 freq; + u16 len; + u64 tsf; + u32 beacon_time; + u8 nic_type; + u16 Length; + // u8 DataRate; // In 0.5 Mbps + u8 SignalQuality; // in 0-100 index. + s32 RecvSignalPower; // Real power in dBm for this packet, no beautification and aggregation. + s8 RxPower; // in dBm Translate from PWdB + u8 SignalStrength; // in 0-100 index. + u16 bHwError:1; + u16 bCRC:1; + u16 bICV:1; + u16 bShortPreamble:1; + u16 Antenna:1; //for rtl8185 + u16 Decrypted:1; //for rtl8185, rtl8187 + u16 Wakeup:1; //for rtl8185 + u16 Reserved0:1; //for rtl8185 + u8 AGC; + u32 TimeStampLow; + u32 TimeStampHigh; + bool bShift; + bool bIsQosData; // Added by Annie, 2005-12-22. + u8 UserPriority; + + //1!!!!!!!!!!!!!!!!!!!!!!!!!!! + //1Attention Please!!!<11n or 8190 specific code should be put below this line> + //1!!!!!!!!!!!!!!!!!!!!!!!!!!! + + u8 RxDrvInfoSize; + u8 RxBufShift; + bool bIsAMPDU; + bool bFirstMPDU; + bool bContainHTC; + bool RxIs40MHzPacket; + u32 RxPWDBAll; + u8 RxMIMOSignalStrength[4]; // in 0~100 index + s8 RxMIMOSignalQuality[2]; + bool bPacketMatchBSSID; + bool bIsCCK; + bool bPacketToSelf; + //added by amy + u8* virtual_address; + u16 packetlength; // Total packet length: Must equal to sum of all FragLength + u16 fraglength; // FragLength should equal to PacketLength in non-fragment case + u16 fragoffset; // Data offset for this fragment + u16 ntotalfrag; + bool bisrxaggrsubframe; + bool bPacketBeacon; //cosa add for rssi + bool bToSelfBA; //cosa add for rssi + char cck_adc_pwdb[4]; //cosa add for rx path selection + u16 Seq_Num; + +}; + +/* IEEE 802.11 requires that STA supports concurrent reception of at least + * three fragmented frames. This define can be increased to support more + * concurrent frames, but it should be noted that each entry can consume about + * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ +#define IEEE80211_FRAG_CACHE_LEN 4 + +struct ieee80211_frag_entry { + unsigned long first_frag_time; + unsigned int seq; + unsigned int last_frag; + struct sk_buff *skb; + u8 src_addr[ETH_ALEN]; + u8 dst_addr[ETH_ALEN]; +}; + +struct ieee80211_stats { + unsigned int tx_unicast_frames; + unsigned int tx_multicast_frames; + unsigned int tx_fragments; + unsigned int tx_unicast_octets; + unsigned int tx_multicast_octets; + unsigned int tx_deferred_transmissions; + unsigned int tx_single_retry_frames; + unsigned int tx_multiple_retry_frames; + unsigned int tx_retry_limit_exceeded; + unsigned int tx_discards; + unsigned int rx_unicast_frames; + unsigned int rx_multicast_frames; + unsigned int rx_fragments; + unsigned int rx_unicast_octets; + unsigned int rx_multicast_octets; + unsigned int rx_fcs_errors; + unsigned int rx_discards_no_buffer; + unsigned int tx_discards_wrong_sa; + unsigned int rx_discards_undecryptable; + unsigned int rx_message_in_msg_fragments; + unsigned int rx_message_in_bad_msg_fragments; +}; + +struct ieee80211_device; + +#include "ieee80211_crypt.h" + +#define SEC_KEY_1 (1<<0) +#define SEC_KEY_2 (1<<1) +#define SEC_KEY_3 (1<<2) +#define SEC_KEY_4 (1<<3) +#define SEC_ACTIVE_KEY (1<<4) +#define SEC_AUTH_MODE (1<<5) +#define SEC_UNICAST_GROUP (1<<6) +#define SEC_LEVEL (1<<7) +#define SEC_ENABLED (1<<8) +#define SEC_ENCRYPT (1<<9) + +#define SEC_LEVEL_0 0 /* None */ +#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */ +#define SEC_LEVEL_2 2 /* Level 1 + TKIP */ +#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */ +#define SEC_LEVEL_3 4 /* Level 2 + CCMP */ + +#define SEC_ALG_NONE 0 +#define SEC_ALG_WEP 1 +#define SEC_ALG_TKIP 2 +#define SEC_ALG_CCMP 3 + +#define WEP_KEYS 4 +#define WEP_KEY_LEN 13 +#define SCM_KEY_LEN 32 +#define SCM_TEMPORAL_KEY_LENGTH 16 + +struct ieee80211_security { + u16 active_key:2, + enabled:1, + auth_mode:2, + auth_algo:4, + unicast_uses_group:1, + encrypt:1; + u8 key_sizes[WEP_KEYS]; + u8 keys[WEP_KEYS][SCM_KEY_LEN]; + u8 level; + u16 flags; +} __attribute__ ((packed)); + + +/* + 802.11 data frame from AP + ,-------------------------------------------------------------------. +Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | + |------|------|---------|---------|---------|------|---------|------| +Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | + | | tion | (BSSID) | | | ence | data | | + `-------------------------------------------------------------------' +Total: 28-2340 bytes +*/ + +/* Management Frame Information Element Types */ +enum ieee80211_mfie { + MFIE_TYPE_SSID = 0, + MFIE_TYPE_RATES = 1, + MFIE_TYPE_FH_SET = 2, + MFIE_TYPE_DS_SET = 3, + MFIE_TYPE_CF_SET = 4, + MFIE_TYPE_TIM = 5, + MFIE_TYPE_IBSS_SET = 6, + MFIE_TYPE_COUNTRY = 7, + MFIE_TYPE_HOP_PARAMS = 8, + MFIE_TYPE_HOP_TABLE = 9, + MFIE_TYPE_REQUEST = 10, + MFIE_TYPE_CHALLENGE = 16, + MFIE_TYPE_POWER_CONSTRAINT = 32, + MFIE_TYPE_POWER_CAPABILITY = 33, + MFIE_TYPE_TPC_REQUEST = 34, + MFIE_TYPE_TPC_REPORT = 35, + MFIE_TYPE_SUPP_CHANNELS = 36, + MFIE_TYPE_CSA = 37, + MFIE_TYPE_MEASURE_REQUEST = 38, + MFIE_TYPE_MEASURE_REPORT = 39, + MFIE_TYPE_QUIET = 40, + MFIE_TYPE_IBSS_DFS = 41, + MFIE_TYPE_ERP = 42, + MFIE_TYPE_RSN = 48, + MFIE_TYPE_RATES_EX = 50, + MFIE_TYPE_HT_CAP= 45, + MFIE_TYPE_HT_INFO= 61, + MFIE_TYPE_AIRONET=133, + MFIE_TYPE_GENERIC = 221, + MFIE_TYPE_QOS_PARAMETER = 222, +}; + +/* Minimal header; can be used for passing 802.11 frames with sufficient + * information to determine what type of underlying data type is actually + * stored in the data. */ +struct ieee80211_hdr { + __le16 frame_ctl; + __le16 duration_id; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_1addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_2addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_3addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_4addr { + __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]; + u8 payload[0]; +} __attribute__ ((packed)); + +struct ieee80211_hdr_3addrqos { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + u8 payload[0]; + __le16 qos_ctl; +} __attribute__ ((packed)); + +struct ieee80211_hdr_4addrqos { + __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]; + u8 payload[0]; + __le16 qos_ctl; +} __attribute__ ((packed)); + +struct ieee80211_info_element { + u8 id; + u8 len; + u8 data[0]; +} __attribute__ ((packed)); + +struct ieee80211_authentication { + struct ieee80211_hdr_3addr header; + __le16 algorithm; + __le16 transaction; + __le16 status; + /*challenge*/ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_disassoc { + struct ieee80211_hdr_3addr header; + __le16 reason; +} __attribute__ ((packed)); + +struct ieee80211_probe_request { + struct ieee80211_hdr_3addr header; + /* SSID, supported rates */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_probe_response { + struct ieee80211_hdr_3addr header; + u32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + /* SSID, supported rates, FH params, DS params, + * CF params, IBSS params, TIM (if beacon), RSN */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +/* Alias beacon for probe_response */ +#define ieee80211_beacon ieee80211_probe_response + +struct ieee80211_assoc_request_frame { + struct ieee80211_hdr_3addr header; + __le16 capability; + __le16 listen_interval; + /* SSID, supported rates, RSN */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_reassoc_request_frame { + struct ieee80211_hdr_3addr header; + __le16 capability; + __le16 listen_interval; + u8 current_ap[ETH_ALEN]; + /* SSID, supported rates, RSN */ + struct ieee80211_info_element info_element[0]; +} __attribute__ ((packed)); + +struct ieee80211_assoc_response_frame { + struct ieee80211_hdr_3addr header; + __le16 capability; + __le16 status; + __le16 aid; + struct ieee80211_info_element info_element[0]; /* supported rates */ +} __attribute__ ((packed)); + +struct ieee80211_txb { + u8 nr_frags; + u8 encrypted; + u8 queue_index; + u8 rts_included; + u16 reserved; + __le16 frag_size; + __le16 payload_size; + struct sk_buff *fragments[0]; +}; + +#define MAX_TX_AGG_COUNT 16 +struct ieee80211_drv_agg_txb { + u8 nr_drv_agg_frames; + struct sk_buff *tx_agg_frames[MAX_TX_AGG_COUNT]; +}__attribute__((packed)); + +#define MAX_SUBFRAME_COUNT 64 +struct ieee80211_rxb { + u8 nr_subframes; + struct sk_buff *subframes[MAX_SUBFRAME_COUNT]; + u8 dst[ETH_ALEN]; + u8 src[ETH_ALEN]; +}__attribute__((packed)); + +typedef union _frameqos { + u16 shortdata; + u8 chardata[2]; + struct { + u16 tid:4; + u16 eosp:1; + u16 ack_policy:2; + u16 reserved:1; + u16 txop:8; + }field; +}frameqos,*pframeqos; + +/* SWEEP TABLE ENTRIES NUMBER*/ +#define MAX_SWEEP_TAB_ENTRIES 42 +#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7 +/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs + * only use 8, and then use extended rates for the remaining supported + * rates. Other APs, however, stick all of their supported rates on the + * main rates information element... */ +#define MAX_RATES_LENGTH ((u8)12) +#define MAX_RATES_EX_LENGTH ((u8)16) +#define MAX_NETWORK_COUNT 128 + +#define MAX_CHANNEL_NUMBER 161 +#define IEEE80211_SOFTMAC_SCAN_TIME 100 +//(HZ / 2) +#define IEEE80211_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2) + +#define CRC_LENGTH 4U + +#define MAX_WPA_IE_LEN 64 + +#define NETWORK_EMPTY_ESSID (1<<0) +#define NETWORK_HAS_OFDM (1<<1) +#define NETWORK_HAS_CCK (1<<2) + +/* QoS structure */ +#define NETWORK_HAS_QOS_PARAMETERS (1<<3) +#define NETWORK_HAS_QOS_INFORMATION (1<<4) +#define NETWORK_HAS_QOS_MASK (NETWORK_HAS_QOS_PARAMETERS | \ + NETWORK_HAS_QOS_INFORMATION) +/* 802.11h */ +#define NETWORK_HAS_POWER_CONSTRAINT (1<<5) +#define NETWORK_HAS_CSA (1<<6) +#define NETWORK_HAS_QUIET (1<<7) +#define NETWORK_HAS_IBSS_DFS (1<<8) +#define NETWORK_HAS_TPC_REPORT (1<<9) + +#define NETWORK_HAS_ERP_VALUE (1<<10) + +#define QOS_QUEUE_NUM 4 +#define QOS_OUI_LEN 3 +#define QOS_OUI_TYPE 2 +#define QOS_ELEMENT_ID 221 +#define QOS_OUI_INFO_SUB_TYPE 0 +#define QOS_OUI_PARAM_SUB_TYPE 1 +#define QOS_VERSION_1 1 +#define QOS_AIFSN_MIN_VALUE 2 +struct ieee80211_qos_information_element { + u8 elementID; + u8 length; + u8 qui[QOS_OUI_LEN]; + u8 qui_type; + u8 qui_subtype; + u8 version; + u8 ac_info; +} __attribute__ ((packed)); + +struct ieee80211_qos_ac_parameter { + u8 aci_aifsn; + u8 ecw_min_max; + __le16 tx_op_limit; +} __attribute__ ((packed)); + +struct ieee80211_qos_parameter_info { + struct ieee80211_qos_information_element info_element; + u8 reserved; + struct ieee80211_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM]; +} __attribute__ ((packed)); + +struct ieee80211_qos_parameters { + __le16 cw_min[QOS_QUEUE_NUM]; + __le16 cw_max[QOS_QUEUE_NUM]; + u8 aifs[QOS_QUEUE_NUM]; + u8 flag[QOS_QUEUE_NUM]; + __le16 tx_op_limit[QOS_QUEUE_NUM]; +} __attribute__ ((packed)); + +struct ieee80211_qos_data { + struct ieee80211_qos_parameters parameters; + int active; + int supported; + u8 param_count; + u8 old_param_count; +}; + +struct ieee80211_tim_parameters { + u8 tim_count; + u8 tim_period; +} __attribute__ ((packed)); + +//#else +struct ieee80211_wmm_ac_param { + u8 ac_aci_acm_aifsn; + u8 ac_ecwmin_ecwmax; + u16 ac_txop_limit; +}; + +struct ieee80211_wmm_ts_info { + u8 ac_dir_tid; + u8 ac_up_psb; + u8 reserved; +} __attribute__ ((packed)); + +struct ieee80211_wmm_tspec_elem { + struct ieee80211_wmm_ts_info ts_info; + u16 norm_msdu_size; + u16 max_msdu_size; + u32 min_serv_inter; + u32 max_serv_inter; + u32 inact_inter; + u32 suspen_inter; + u32 serv_start_time; + u32 min_data_rate; + u32 mean_data_rate; + u32 peak_data_rate; + u32 max_burst_size; + u32 delay_bound; + u32 min_phy_rate; + u16 surp_band_allow; + u16 medium_time; +}__attribute__((packed)); +enum eap_type { + EAP_PACKET = 0, + EAPOL_START, + EAPOL_LOGOFF, + EAPOL_KEY, + EAPOL_ENCAP_ASF_ALERT +}; + +static const char *eap_types[] = { + [EAP_PACKET] = "EAP-Packet", + [EAPOL_START] = "EAPOL-Start", + [EAPOL_LOGOFF] = "EAPOL-Logoff", + [EAPOL_KEY] = "EAPOL-Key", + [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert" +}; + +static inline const char *eap_get_type(int type) +{ + return ((u32)type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type]; +} +//added by amy for reorder +static inline u8 Frame_QoSTID(u8* buf) +{ + struct ieee80211_hdr_3addr *hdr; + u16 fc; + hdr = (struct ieee80211_hdr_3addr *)buf; + fc = le16_to_cpu(hdr->frame_ctl); + return (u8)((frameqos*)(buf + (((fc & IEEE80211_FCTL_TODS)&&(fc & IEEE80211_FCTL_FROMDS))? 30 : 24)))->field.tid; +} + +//added by amy for reorder + +struct eapol { + u8 snap[6]; + u16 ethertype; + u8 version; + u8 type; + u16 length; +} __attribute__ ((packed)); + +struct ieee80211_softmac_stats{ + unsigned int rx_ass_ok; + unsigned int rx_ass_err; + unsigned int rx_probe_rq; + unsigned int tx_probe_rs; + unsigned int tx_beacons; + unsigned int rx_auth_rq; + unsigned int rx_auth_rs_ok; + unsigned int rx_auth_rs_err; + unsigned int tx_auth_rq; + unsigned int no_auth_rs; + unsigned int no_ass_rs; + unsigned int tx_ass_rq; + unsigned int rx_ass_rq; + unsigned int tx_probe_rq; + unsigned int reassoc; + unsigned int swtxstop; + unsigned int swtxawake; + unsigned char CurrentShowTxate; + unsigned char last_packet_rate; + unsigned int txretrycount; +}; + +#define BEACON_PROBE_SSID_ID_POSITION 12 + +struct ieee80211_info_element_hdr { + u8 id; + u8 len; +} __attribute__ ((packed)); + +/* + * These are the data types that can make up management packets + * + u16 auth_algorithm; + u16 auth_sequence; + u16 beacon_interval; + u16 capability; + u8 current_ap[ETH_ALEN]; + u16 listen_interval; + struct { + u16 association_id:14, reserved:2; + } __attribute__ ((packed)); + u32 time_stamp[2]; + u16 reason; + u16 status; +*/ + +#define IEEE80211_DEFAULT_TX_ESSID "Penguin" +#define IEEE80211_DEFAULT_BASIC_RATE 2 //1Mbps + +enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame}; +#define MAX_SP_Len (WMM_all_frame << 4) +#define IEEE80211_QOS_TID 0x0f +#define QOS_CTL_NOTCONTAIN_ACK (0x01 << 5) + +#define IEEE80211_DTIM_MBCAST 4 +#define IEEE80211_DTIM_UCAST 2 +#define IEEE80211_DTIM_VALID 1 +#define IEEE80211_DTIM_INVALID 0 + +#define IEEE80211_PS_DISABLED 0 +#define IEEE80211_PS_UNICAST IEEE80211_DTIM_UCAST +#define IEEE80211_PS_MBCAST IEEE80211_DTIM_MBCAST + +//added by David for QoS 2006/6/30 +//#define WMM_Hang_8187 +#ifdef WMM_Hang_8187 +#undef WMM_Hang_8187 +#endif + +#define WME_AC_BK 0x00 +#define WME_AC_BE 0x01 +#define WME_AC_VI 0x02 +#define WME_AC_VO 0x03 +#define WME_ACI_MASK 0x03 +#define WME_AIFSN_MASK 0x03 +#define WME_AC_PRAM_LEN 16 + +#define MAX_RECEIVE_BUFFER_SIZE 9100 + +//UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP +//#define UP2AC(up) ((up<3) ? ((up==0)?1:0) : (up>>1)) +#define UP2AC(up) ( \ + ((up) < 1) ? WME_AC_BE : \ + ((up) < 3) ? WME_AC_BK : \ + ((up) < 4) ? WME_AC_BE : \ + ((up) < 6) ? WME_AC_VI : \ + WME_AC_VO) +//AC Mapping to UP, using in Tx part for selecting the corresponding TX queue +#define AC2UP(_ac) ( \ + ((_ac) == WME_AC_VO) ? 6 : \ + ((_ac) == WME_AC_VI) ? 5 : \ + ((_ac) == WME_AC_BK) ? 1 : \ + 0) + +#define ETHER_ADDR_LEN 6 /* length of an Ethernet address */ +#define ETHERNET_HEADER_SIZE 14 /* length of two Ethernet address plus ether type*/ + +struct ether_header { + u8 ether_dhost[ETHER_ADDR_LEN]; + u8 ether_shost[ETHER_ADDR_LEN]; + u16 ether_type; +} __attribute__((packed)); + +#ifndef ETHERTYPE_PAE +#define ETHERTYPE_PAE 0x888e /* EAPOL PAE/802.1x */ +#endif +#ifndef ETHERTYPE_IP +#define ETHERTYPE_IP 0x0800 /* IP protocol */ +#endif + +typedef struct _bss_ht{ + + bool support_ht; + + // HT related elements + u8 ht_cap_buf[32]; + u16 ht_cap_len; + u8 ht_info_buf[32]; + u16 ht_info_len; + + HT_SPEC_VER ht_spec_ver; + //HT_CAPABILITY_ELE bdHTCapEle; + //HT_INFORMATION_ELE bdHTInfoEle; + + bool aggregation; + bool long_slot_time; +}bss_ht, *pbss_ht; + +typedef enum _erp_t{ + ERP_NonERPpresent = 0x01, + ERP_UseProtection = 0x02, + ERP_BarkerPreambleMode = 0x04, +} erp_t; + + +struct ieee80211_network { + /* These entries are used to identify a unique network */ + u8 bssid[ETH_ALEN]; + u8 channel; + /* Ensure null-terminated for any debug msgs */ + u8 ssid[IW_ESSID_MAX_SIZE + 1]; + u8 ssid_len; + struct ieee80211_qos_data qos_data; + + //added by amy for LEAP + bool bWithAironetIE; + bool bCkipSupported; + bool bCcxRmEnable; + u16 CcxRmState[2]; + // CCXv4 S59, MBSSID. + bool bMBssidValid; + u8 MBssidMask; + u8 MBssid[6]; + // CCX 2 S38, WLAN Device Version Number element. Annie, 2006-08-20. + bool bWithCcxVerNum; + u8 BssCcxVerNumber; + /* These are network statistics */ + struct ieee80211_rx_stats stats; + u16 capability; + u8 rates[MAX_RATES_LENGTH]; + u8 rates_len; + u8 rates_ex[MAX_RATES_EX_LENGTH]; + u8 rates_ex_len; + unsigned long last_scanned; + u8 mode; + u32 flags; + u32 last_associate; + u32 time_stamp[2]; + u16 beacon_interval; + u16 listen_interval; + u16 atim_window; + u8 erp_value; + u8 wpa_ie[MAX_WPA_IE_LEN]; + size_t wpa_ie_len; + u8 rsn_ie[MAX_WPA_IE_LEN]; + size_t rsn_ie_len; + + struct ieee80211_tim_parameters tim; + u8 dtim_period; + u8 dtim_data; + u32 last_dtim_sta_time[2]; + + //appeded for QoS + u8 wmm_info; + struct ieee80211_wmm_ac_param wmm_param[4]; + u8 QoS_Enable; +#ifdef THOMAS_TURBO + u8 Turbo_Enable;//enable turbo mode, added by thomas +#endif +#ifdef ENABLE_DOT11D + u16 CountryIeLen; + u8 CountryIeBuf[MAX_IE_LEN]; +#endif + // HT Related, by amy, 2008.04.29 + BSS_HT bssht; + // Add to handle broadcom AP management frame CCK rate. + bool broadcom_cap_exist; + bool ralink_cap_exist; + bool atheros_cap_exist; + bool cisco_cap_exist; + bool unknown_cap_exist; +// u8 berp_info; + bool berp_info_valid; + bool buseprotection; + //put at the end of the structure. + struct list_head list; +}; + +enum ieee80211_state { + + /* the card is not linked at all */ + IEEE80211_NOLINK = 0, + + /* IEEE80211_ASSOCIATING* are for BSS client mode + * the driver shall not perform RX filtering unless + * the state is LINKED. + * The driver shall just check for the state LINKED and + * defaults to NOLINK for ALL the other states (including + * LINKED_SCANNING) + */ + + /* the association procedure will start (wq scheduling)*/ + IEEE80211_ASSOCIATING, + IEEE80211_ASSOCIATING_RETRY, + + /* the association procedure is sending AUTH request*/ + IEEE80211_ASSOCIATING_AUTHENTICATING, + + /* the association procedure has successfully authentcated + * and is sending association request + */ + IEEE80211_ASSOCIATING_AUTHENTICATED, + + /* the link is ok. the card associated to a BSS or linked + * to a ibss cell or acting as an AP and creating the bss + */ + IEEE80211_LINKED, + + /* same as LINKED, but the driver shall apply RX filter + * rules as we are in NO_LINK mode. As the card is still + * logically linked, but it is doing a syncro site survey + * then it will be back to LINKED state. + */ + IEEE80211_LINKED_SCANNING, + +}; + +#define DEFAULT_MAX_SCAN_AGE (15 * HZ) +#define DEFAULT_FTS 2346 + +#define CFG_IEEE80211_RESERVE_FCS (1<<0) +#define CFG_IEEE80211_COMPUTE_FCS (1<<1) +#define CFG_IEEE80211_RTS (1<<2) + +#define IEEE80211_24GHZ_MIN_CHANNEL 1 +#define IEEE80211_24GHZ_MAX_CHANNEL 14 +#define IEEE80211_24GHZ_CHANNELS (IEEE80211_24GHZ_MAX_CHANNEL - \ + IEEE80211_24GHZ_MIN_CHANNEL + 1) + +#define IEEE80211_52GHZ_MIN_CHANNEL 34 +#define IEEE80211_52GHZ_MAX_CHANNEL 165 +#define IEEE80211_52GHZ_CHANNELS (IEEE80211_52GHZ_MAX_CHANNEL - \ + IEEE80211_52GHZ_MIN_CHANNEL + 1) + + + +typedef struct tx_pending_t{ + int frag; + struct ieee80211_txb *txb; +}tx_pending_t; + +typedef struct _bandwidth_autoswitch +{ + long threshold_20Mhzto40Mhz; + long threshold_40Mhzto20Mhz; + bool bforced_tx20Mhz; + bool bautoswitch_enable; +}bandwidth_autoswitch,*pbandwidth_autoswitch; + + +//added by amy for order + +#define REORDER_WIN_SIZE 128 +#define REORDER_ENTRY_NUM 128 +typedef struct _RX_REORDER_ENTRY +{ + struct list_head List; + u16 SeqNum; + struct ieee80211_rxb* prxb; +} RX_REORDER_ENTRY, *PRX_REORDER_ENTRY; +//added by amy for order +typedef enum _Fsync_State{ + Default_Fsync, + HW_Fsync, + SW_Fsync +}Fsync_State; + +// Power save mode configured. +typedef enum _RT_PS_MODE +{ + eActive, // Active/Continuous access. + eMaxPs, // Max power save mode. + eFastPs // Fast power save mode. +}RT_PS_MODE; + +typedef enum _IPS_CALLBACK_FUNCION +{ + IPS_CALLBACK_NONE = 0, + IPS_CALLBACK_MGNT_LINK_REQUEST = 1, + IPS_CALLBACK_JOIN_REQUEST = 2, +}IPS_CALLBACK_FUNCION; + +typedef enum _RT_JOIN_ACTION{ + RT_JOIN_INFRA = 1, + RT_JOIN_IBSS = 2, + RT_START_IBSS = 3, + RT_NO_ACTION = 4, +}RT_JOIN_ACTION; + +typedef struct _IbssParms{ + u16 atimWin; +}IbssParms, *PIbssParms; +#define MAX_NUM_RATES 264 // Max num of support rates element: 8, Max num of ext. support rate: 255. 061122, by rcnjko. + +// RF state. +typedef enum _RT_RF_POWER_STATE +{ + eRfOn, + eRfSleep, + eRfOff +}RT_RF_POWER_STATE; + +typedef struct _RT_POWER_SAVE_CONTROL +{ + + // + // Inactive Power Save(IPS) : Disable RF when disconnected + // + bool bInactivePs; + bool bIPSModeBackup; + bool bSwRfProcessing; + RT_RF_POWER_STATE eInactivePowerState; + struct work_struct InactivePsWorkItem; + struct timer_list InactivePsTimer; + + // Return point for join action + IPS_CALLBACK_FUNCION ReturnPoint; + + // Recored Parameters for rescheduled JoinRequest + bool bTmpBssDesc; + RT_JOIN_ACTION tmpJoinAction; + struct ieee80211_network tmpBssDesc; + + // Recored Parameters for rescheduled MgntLinkRequest + bool bTmpScanOnly; + bool bTmpActiveScan; + bool bTmpFilterHiddenAP; + bool bTmpUpdateParms; + u8 tmpSsidBuf[33]; + OCTET_STRING tmpSsid2Scan; + bool bTmpSsid2Scan; + u8 tmpNetworkType; + u8 tmpChannelNumber; + u16 tmpBcnPeriod; + u8 tmpDtimPeriod; + u16 tmpmCap; + OCTET_STRING tmpSuppRateSet; + u8 tmpSuppRateBuf[MAX_NUM_RATES]; + bool bTmpSuppRate; + IbssParms tmpIbpm; + bool bTmpIbpm; + + // + // Leisre Poswer Save : Disable RF if connected but traffic is not busy + // + bool bLeisurePs; + +}RT_POWER_SAVE_CONTROL,*PRT_POWER_SAVE_CONTROL; + +typedef u32 RT_RF_CHANGE_SOURCE; +#define RF_CHANGE_BY_SW BIT31 +#define RF_CHANGE_BY_HW BIT30 +#define RF_CHANGE_BY_PS BIT29 +#define RF_CHANGE_BY_IPS BIT28 +#define RF_CHANGE_BY_INIT 0 // Do not change the RFOff reason. Defined by Bruce, 2008-01-17. + +#ifdef ENABLE_DOT11D +typedef enum +{ + COUNTRY_CODE_FCC = 0, + COUNTRY_CODE_IC = 1, + COUNTRY_CODE_ETSI = 2, + COUNTRY_CODE_SPAIN = 3, + COUNTRY_CODE_FRANCE = 4, + COUNTRY_CODE_MKK = 5, + COUNTRY_CODE_MKK1 = 6, + COUNTRY_CODE_ISRAEL = 7, + COUNTRY_CODE_TELEC, + COUNTRY_CODE_MIC, + COUNTRY_CODE_GLOBAL_DOMAIN +}country_code_type_t; +#endif + +#define RT_MAX_LD_SLOT_NUM 10 +typedef struct _RT_LINK_DETECT_T{ + + u32 NumRecvBcnInPeriod; + u32 NumRecvDataInPeriod; + + u32 RxBcnNum[RT_MAX_LD_SLOT_NUM]; // number of Rx beacon / CheckForHang_period to determine link status + u32 RxDataNum[RT_MAX_LD_SLOT_NUM]; // number of Rx data / CheckForHang_period to determine link status + u16 SlotNum; // number of CheckForHang period to determine link status + u16 SlotIndex; + + u32 NumTxOkInPeriod; + u32 NumRxOkInPeriod; + bool bBusyTraffic; +}RT_LINK_DETECT_T, *PRT_LINK_DETECT_T; + + +struct ieee80211_device { + struct net_device *dev; + struct ieee80211_security sec; + + //hw security related +// u8 hwsec_support; //support? + u8 hwsec_active; //hw security active. + bool is_silent_reset; + bool ieee_up; + //added by amy + bool bSupportRemoteWakeUp; + RT_PS_MODE dot11PowerSaveMode; // Power save mode configured. + bool actscanning; + bool beinretry; + RT_RF_POWER_STATE eRFPowerState; + RT_RF_CHANGE_SOURCE RfOffReason; + bool is_set_key; + //11n spec related I wonder if These info structure need to be moved out of ieee80211_device + + //11n HT below + PRT_HIGH_THROUGHPUT pHTInfo; + //struct timer_list SwBwTimer; +// spinlock_t chnlop_spinlock; + spinlock_t bw_spinlock; + + spinlock_t reorder_spinlock; + // for HT operation rate set. we use this one for HT data rate to seperate different descriptors + //the way fill this is the same as in the IE + u8 Regdot11HTOperationalRateSet[16]; //use RATR format + u8 dot11HTOperationalRateSet[16]; //use RATR format + u8 RegHTSuppRateSet[16]; + u8 HTCurrentOperaRate; + u8 HTHighestOperaRate; + //wb added for rate operation mode to firmware + u8 bTxDisableRateFallBack; + u8 bTxUseDriverAssingedRate; + atomic_t atm_chnlop; + atomic_t atm_swbw; +// u8 HTHighestOperaRate; +// u8 HTCurrentOperaRate; + + // 802.11e and WMM Traffic Stream Info (TX) + struct list_head Tx_TS_Admit_List; + struct list_head Tx_TS_Pending_List; + struct list_head Tx_TS_Unused_List; + TX_TS_RECORD TxTsRecord[TOTAL_TS_NUM]; + // 802.11e and WMM Traffic Stream Info (RX) + struct list_head Rx_TS_Admit_List; + struct list_head Rx_TS_Pending_List; + struct list_head Rx_TS_Unused_List; + RX_TS_RECORD RxTsRecord[TOTAL_TS_NUM]; +//#ifdef TO_DO_LIST + RX_REORDER_ENTRY RxReorderEntry[128]; + struct list_head RxReorder_Unused_List; +//#endif + // Qos related. Added by Annie, 2005-11-01. +// PSTA_QOS pStaQos; + u8 ForcedPriority; // Force per-packet priority 1~7. (default: 0, not to force it.) + + + /* Bookkeeping structures */ + struct net_device_stats stats; + struct ieee80211_stats ieee_stats; + struct ieee80211_softmac_stats softmac_stats; + + /* Probe / Beacon management */ + struct list_head network_free_list; + struct list_head network_list; + struct ieee80211_network *networks; + int scans; + int scan_age; + + int iw_mode; /* operating mode (IW_MODE_*) */ + struct iw_spy_data spy_data; + + spinlock_t lock; + spinlock_t wpax_suitlist_lock; + + int tx_headroom; /* Set to size of any additional room needed at front + * of allocated Tx SKBs */ + u32 config; + + /* WEP and other encryption related settings at the device level */ + int open_wep; /* Set to 1 to allow unencrypted frames */ + int auth_mode; + int reset_on_keychange; /* Set to 1 if the HW needs to be reset on + * WEP key changes */ + + /* If the host performs {en,de}cryption, then set to 1 */ + int host_encrypt; + int host_encrypt_msdu; + int host_decrypt; + /* host performs multicast decryption */ + int host_mc_decrypt; + + /* host should strip IV and ICV from protected frames */ + /* meaningful only when hardware decryption is being used */ + int host_strip_iv_icv; + + int host_open_frag; + int host_build_iv; + int ieee802_1x; /* is IEEE 802.1X used */ + + /* WPA data */ + bool bHalfWirelessN24GMode; + int wpa_enabled; + int drop_unencrypted; + int tkip_countermeasures; + int privacy_invoked; + size_t wpa_ie_len; + u8 *wpa_ie; + u8 ap_mac_addr[6]; + u16 pairwise_key_type; + u16 group_key_type; + struct list_head crypt_deinit_list; + struct ieee80211_crypt_data *crypt[WEP_KEYS]; + int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */ + struct timer_list crypt_deinit_timer; + int crypt_quiesced; + + int bcrx_sta_key; /* use individual keys to override default keys even + * with RX of broad/multicast frames */ + + /* Fragmentation structures */ + // each streaming contain a entry + struct ieee80211_frag_entry frag_cache[17][IEEE80211_FRAG_CACHE_LEN]; + unsigned int frag_next_idx[17]; + u16 fts; /* Fragmentation Threshold */ +#define DEFAULT_RTS_THRESHOLD 2346U +#define MIN_RTS_THRESHOLD 1 +#define MAX_RTS_THRESHOLD 2346U + u16 rts; /* RTS threshold */ + + /* Association info */ + u8 bssid[ETH_ALEN]; + + /* This stores infos for the current network. + * Either the network we are associated in INFRASTRUCTURE + * or the network that we are creating in MASTER mode. + * ad-hoc is a mixture ;-). + * Note that in infrastructure mode, even when not associated, + * fields bssid and essid may be valid (if wpa_set and essid_set + * are true) as thy carry the value set by the user via iwconfig + */ + struct ieee80211_network current_network; + + enum ieee80211_state state; + + int short_slot; + int reg_mode; + int mode; /* A, B, G */ + int modulation; /* CCK, OFDM */ + int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */ + int abg_true; /* ABG flag */ + + /* used for forcing the ibss workqueue to terminate + * without wait for the syncro scan to terminate + */ + short sync_scan_hurryup; + + int perfect_rssi; + int worst_rssi; + + u16 prev_seq_ctl; /* used to drop duplicate frames */ + + /* map of allowed channels. 0 is dummy */ + // FIXME: remeber to default to a basic channel plan depending of the PHY type +#ifdef ENABLE_DOT11D + void* pDot11dInfo; + bool bGlobalDomain; +#else + int channel_map[MAX_CHANNEL_NUMBER+1]; +#endif + int rate; /* current rate */ + int basic_rate; + //FIXME: pleace callback, see if redundant with softmac_features + short active_scan; + + /* this contains flags for selectively enable softmac support */ + u16 softmac_features; + + /* if the sequence control field is not filled by HW */ + u16 seq_ctrl[5]; + + /* association procedure transaction sequence number */ + u16 associate_seq; + + /* AID for RTXed association responses */ + u16 assoc_id; + + /* power save mode related*/ + short ps; + short sta_sleep; + int ps_timeout; + int ps_period; + struct tasklet_struct ps_task; + u32 ps_th; + u32 ps_tl; + + short raw_tx; + /* used if IEEE_SOFTMAC_TX_QUEUE is set */ + short queue_stop; + short scanning; + short proto_started; + + struct semaphore wx_sem; + struct semaphore scan_sem; + + spinlock_t mgmt_tx_lock; + spinlock_t beacon_lock; + + short beacon_txing; + + short wap_set; + short ssid_set; + + u8 wpax_type_set; //{added by David, 2006.9.28} + u32 wpax_type_notify; //{added by David, 2006.9.26} + + /* QoS related flag */ + char init_wmmparam_flag; + /* set on initialization */ + u8 qos_support; + + /* for discarding duplicated packets in IBSS */ + struct list_head ibss_mac_hash[IEEE_IBSS_MAC_HASH_SIZE]; + + /* for discarding duplicated packets in BSS */ + u16 last_rxseq_num[17]; /* rx seq previous per-tid */ + u16 last_rxfrag_num[17];/* tx frag previous per-tid */ + unsigned long last_packet_time[17]; + + /* for PS mode */ + unsigned long last_rx_ps_time; + + /* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */ + struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM]; + int mgmt_queue_head; + int mgmt_queue_tail; +//{ added for rtl819x +#define IEEE80211_QUEUE_LIMIT 128 + u8 AsocRetryCount; + unsigned int hw_header; + struct sk_buff_head skb_waitQ[MAX_QUEUE_SIZE]; + struct sk_buff_head skb_aggQ[MAX_QUEUE_SIZE]; + struct sk_buff_head skb_drv_aggQ[MAX_QUEUE_SIZE]; + u32 sta_edca_param[4]; + bool aggregation; + // Enable/Disable Rx immediate BA capability. + bool enable_rx_imm_BA; + bool bibsscoordinator; + + //+by amy for DM ,080515 + //Dynamic Tx power for near/far range enable/Disable , by amy , 2008-05-15 + bool bdynamic_txpower_enable; + + bool bCTSToSelfEnable; + u8 CTSToSelfTH; + + u32 fsync_time_interval; + u32 fsync_rate_bitmap; + u8 fsync_rssi_threshold; + bool bfsync_enable; + + u8 fsync_multiple_timeinterval; // FsyncMultipleTimeInterval * FsyncTimeInterval + u32 fsync_firstdiff_ratethreshold; // low threshold + u32 fsync_seconddiff_ratethreshold; // decrease threshold + Fsync_State fsync_state; + bool bis_any_nonbepkts; + //20Mhz 40Mhz AutoSwitch Threshold + bandwidth_autoswitch bandwidth_auto_switch; + //for txpower tracking + bool FwRWRF; + + //added by amy for AP roaming + RT_LINK_DETECT_T LinkDetectInfo; + //added by amy for ps + RT_POWER_SAVE_CONTROL PowerSaveControl; +//} + /* used if IEEE_SOFTMAC_TX_QUEUE is set */ + struct tx_pending_t tx_pending; + + /* used if IEEE_SOFTMAC_ASSOCIATE is set */ + struct timer_list associate_timer; + + /* used if IEEE_SOFTMAC_BEACONS is set */ + struct timer_list beacon_timer; + struct work_struct associate_complete_wq; + struct work_struct associate_procedure_wq; + struct delayed_work softmac_scan_wq; + struct delayed_work associate_retry_wq; + struct delayed_work start_ibss_wq; + struct work_struct wx_sync_scan_wq; + struct workqueue_struct *wq; + // Qos related. Added by Annie, 2005-11-01. + //STA_QOS StaQos; + + //u32 STA_EDCA_PARAM[4]; + //CHANNEL_ACCESS_SETTING ChannelAccessSetting; + + + /* Callback functions */ + void (*set_security)(struct net_device *dev, + struct ieee80211_security *sec); + + /* Used to TX data frame by using txb structs. + * this is not used if in the softmac_features + * is set the flag IEEE_SOFTMAC_TX_QUEUE + */ + int (*hard_start_xmit)(struct ieee80211_txb *txb, + struct net_device *dev); + + int (*reset_port)(struct net_device *dev); + int (*is_queue_full) (struct net_device * dev, int pri); + + int (*handle_management) (struct net_device * dev, + struct ieee80211_network * network, u16 type); + int (*is_qos_active) (struct net_device *dev, struct sk_buff *skb); + + /* Softmac-generated frames (mamagement) are TXed via this + * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is + * not set. As some cards may have different HW queues that + * one might want to use for data and management frames + * the option to have two callbacks might be useful. + * This fucntion can't sleep. + */ + int (*softmac_hard_start_xmit)(struct sk_buff *skb, + struct net_device *dev); + + /* used instead of hard_start_xmit (not softmac_hard_start_xmit) + * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data + * frames. I the option IEEE_SOFTMAC_SINGLE_QUEUE is also set + * then also management frames are sent via this callback. + * This function can't sleep. + */ + void (*softmac_data_hard_start_xmit)(struct sk_buff *skb, + struct net_device *dev,int rate); + + /* stops the HW queue for DATA frames. Useful to avoid + * waste time to TX data frame when we are reassociating + * This function can sleep. + */ + void (*data_hard_stop)(struct net_device *dev); + + /* OK this is complementar to data_poll_hard_stop */ + void (*data_hard_resume)(struct net_device *dev); + + /* ask to the driver to retune the radio . + * This function can sleep. the driver should ensure + * the radio has been swithced before return. + */ + void (*set_chan)(struct net_device *dev,short ch); + + /* These are not used if the ieee stack takes care of + * scanning (IEEE_SOFTMAC_SCAN feature set). + * In this case only the set_chan is used. + * + * The syncro version is similar to the start_scan but + * does not return until all channels has been scanned. + * this is called in user context and should sleep, + * it is called in a work_queue when swithcing to ad-hoc mode + * or in behalf of iwlist scan when the card is associated + * and root user ask for a scan. + * the fucntion stop_scan should stop both the syncro and + * background scanning and can sleep. + * The fucntion start_scan should initiate the background + * scanning and can't sleep. + */ + void (*scan_syncro)(struct net_device *dev); + void (*start_scan)(struct net_device *dev); + void (*stop_scan)(struct net_device *dev); + + /* indicate the driver that the link state is changed + * for example it may indicate the card is associated now. + * Driver might be interested in this to apply RX filter + * rules or simply light the LINK led + */ + void (*link_change)(struct net_device *dev); + + /* these two function indicates to the HW when to start + * and stop to send beacons. This is used when the + * IEEE_SOFTMAC_BEACONS is not set. For now the + * stop_send_bacons is NOT guaranteed to be called only + * after start_send_beacons. + */ + void (*start_send_beacons) (struct net_device *dev,u16 tx_rate); + void (*stop_send_beacons) (struct net_device *dev); + + /* power save mode related */ + void (*sta_wake_up) (struct net_device *dev); + void (*ps_request_tx_ack) (struct net_device *dev); + void (*enter_sleep_state) (struct net_device *dev, u32 th, u32 tl); + short (*ps_is_queue_empty) (struct net_device *dev); + int (*handle_beacon) (struct net_device * dev, struct ieee80211_beacon * beacon, struct ieee80211_network * network); + int (*handle_assoc_response) (struct net_device * dev, struct ieee80211_assoc_response_frame * resp, struct ieee80211_network * network); + + + /* check whether Tx hw resouce available */ + short (*check_nic_enough_desc)(struct net_device *dev, int queue_index); + //added by wb for HT related +// void (*SwChnlByTimerHandler)(struct net_device *dev, int channel); + void (*SetBWModeHandler)(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset); +// void (*UpdateHalRATRTableHandler)(struct net_device* dev, u8* pMcsRate); + bool (*GetNmodeSupportBySecCfg)(struct net_device* dev); + void (*SetWirelessMode)(struct net_device* dev, u8 wireless_mode); + bool (*GetHalfNmodeSupportByAPsHandler)(struct net_device* dev); + void (*InitialGainHandler)(struct net_device *dev, u8 Operation); + + /* This must be the last item so that it points to the data + * allocated beyond this structure by alloc_ieee80211 */ + u8 priv[0]; +}; + +#define IEEE_A (1<<0) +#define IEEE_B (1<<1) +#define IEEE_G (1<<2) +#define IEEE_N_24G (1<<4) +#define IEEE_N_5G (1<<5) +#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G) + +/* Generate a 802.11 header */ + +/* Uses the channel change callback directly + * instead of [start/stop] scan callbacks + */ +#define IEEE_SOFTMAC_SCAN (1<<2) + +/* Perform authentication and association handshake */ +#define IEEE_SOFTMAC_ASSOCIATE (1<<3) + +/* Generate probe requests */ +#define IEEE_SOFTMAC_PROBERQ (1<<4) + +/* Generate respones to probe requests */ +#define IEEE_SOFTMAC_PROBERS (1<<5) + +/* The ieee802.11 stack will manages the netif queue + * wake/stop for the driver, taking care of 802.11 + * fragmentation. See softmac.c for details. */ +#define IEEE_SOFTMAC_TX_QUEUE (1<<7) + +/* Uses only the softmac_data_hard_start_xmit + * even for TX management frames. + */ +#define IEEE_SOFTMAC_SINGLE_QUEUE (1<<8) + +/* Generate beacons. The stack will enqueue beacons + * to the card + */ +#define IEEE_SOFTMAC_BEACONS (1<<6) + +static inline void *ieee80211_priv(struct net_device *dev) +{ + return ((struct ieee80211_device *)netdev_priv(dev))->priv; +} + +extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len) +{ + /* Single white space is for Linksys APs */ + if (essid_len == 1 && essid[0] == ' ') + return 1; + + /* Otherwise, if the entire essid is 0, we assume it is hidden */ + while (essid_len) { + essid_len--; + if (essid[essid_len] != '\0') + return 0; + } + + return 1; +} + +extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode) +{ + /* + * It is possible for both access points and our device to support + * combinations of modes, so as long as there is one valid combination + * of ap/device supported modes, then return success + * + */ + if ((mode & IEEE_A) && + (ieee->modulation & IEEE80211_OFDM_MODULATION) && + (ieee->freq_band & IEEE80211_52GHZ_BAND)) + return 1; + + if ((mode & IEEE_G) && + (ieee->modulation & IEEE80211_OFDM_MODULATION) && + (ieee->freq_band & IEEE80211_24GHZ_BAND)) + return 1; + + if ((mode & IEEE_B) && + (ieee->modulation & IEEE80211_CCK_MODULATION) && + (ieee->freq_band & IEEE80211_24GHZ_BAND)) + return 1; + + return 0; +} + +extern inline int ieee80211_get_hdrlen(u16 fc) +{ + int hdrlen = IEEE80211_3ADDR_LEN; + + switch (WLAN_FC_GET_TYPE(fc)) { + case IEEE80211_FTYPE_DATA: + if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) + hdrlen = IEEE80211_4ADDR_LEN; /* Addr4 */ + if(IEEE80211_QOS_HAS_SEQ(fc)) + hdrlen += 2; /* QOS ctrl*/ + break; + case IEEE80211_FTYPE_CTL: + switch (WLAN_FC_GET_STYPE(fc)) { + case IEEE80211_STYPE_CTS: + case IEEE80211_STYPE_ACK: + hdrlen = IEEE80211_1ADDR_LEN; + break; + default: + hdrlen = IEEE80211_2ADDR_LEN; + break; + } + break; + } + + return hdrlen; +} + +static inline u8 *ieee80211_get_payload(struct ieee80211_hdr *hdr) +{ + switch (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl))) { + case IEEE80211_1ADDR_LEN: + return ((struct ieee80211_hdr_1addr *)hdr)->payload; + case IEEE80211_2ADDR_LEN: + return ((struct ieee80211_hdr_2addr *)hdr)->payload; + case IEEE80211_3ADDR_LEN: + return ((struct ieee80211_hdr_3addr *)hdr)->payload; + case IEEE80211_4ADDR_LEN: + return ((struct ieee80211_hdr_4addr *)hdr)->payload; + } + return NULL; +} + +static inline int ieee80211_is_ofdm_rate(u8 rate) +{ + switch (rate & ~IEEE80211_BASIC_RATE_MASK) { + case IEEE80211_OFDM_RATE_6MB: + case IEEE80211_OFDM_RATE_9MB: + case IEEE80211_OFDM_RATE_12MB: + case IEEE80211_OFDM_RATE_18MB: + case IEEE80211_OFDM_RATE_24MB: + case IEEE80211_OFDM_RATE_36MB: + case IEEE80211_OFDM_RATE_48MB: + case IEEE80211_OFDM_RATE_54MB: + return 1; + } + return 0; +} + +static inline int ieee80211_is_cck_rate(u8 rate) +{ + switch (rate & ~IEEE80211_BASIC_RATE_MASK) { + case IEEE80211_CCK_RATE_1MB: + case IEEE80211_CCK_RATE_2MB: + case IEEE80211_CCK_RATE_5MB: + case IEEE80211_CCK_RATE_11MB: + return 1; + } + return 0; +} + + +/* ieee80211.c */ +extern void free_ieee80211(struct net_device *dev); +extern struct net_device *alloc_ieee80211(int sizeof_priv); + +extern int ieee80211_set_encryption(struct ieee80211_device *ieee); + +/* ieee80211_tx.c */ + +extern int ieee80211_encrypt_fragment( + struct ieee80211_device *ieee, + struct sk_buff *frag, + int hdr_len); + +extern int ieee80211_xmit(struct sk_buff *skb, + struct net_device *dev); +extern void ieee80211_txb_free(struct ieee80211_txb *); + + +/* ieee80211_rx.c */ +extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, + struct ieee80211_rx_stats *rx_stats); +extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, + struct ieee80211_hdr_4addr *header, + struct ieee80211_rx_stats *stats); + +/* ieee80211_wx.c */ +extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key); +extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key); +extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key); +#if WIRELESS_EXT >= 18 +extern int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data* wrqu, char *extra); +extern int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data* wrqu, char *extra); +extern int ieee80211_wx_set_auth(struct ieee80211_device *ieee, + struct iw_request_info *info, + struct iw_param *data, char *extra); +extern int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +#endif +extern int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len); + +/* ieee80211_softmac.c */ +extern short ieee80211_is_54g(struct ieee80211_network net); +extern short ieee80211_is_shortslot(struct ieee80211_network net); +extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, + struct ieee80211_rx_stats *rx_stats, u16 type, + u16 stype); +extern void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net); + +void SendDisassociation(struct ieee80211_device *ieee, u8* asSta, u8 asRsn); +extern void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee); + +extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee); +extern void notify_wx_assoc_event(struct ieee80211_device *ieee); +extern void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee); +extern void ieee80211_start_bss(struct ieee80211_device *ieee); +extern void ieee80211_start_master_bss(struct ieee80211_device *ieee); +extern void ieee80211_start_ibss(struct ieee80211_device *ieee); +extern void ieee80211_softmac_init(struct ieee80211_device *ieee); +extern void ieee80211_softmac_free(struct ieee80211_device *ieee); +extern void ieee80211_associate_abort(struct ieee80211_device *ieee); +extern void ieee80211_disassociate(struct ieee80211_device *ieee); +extern void ieee80211_stop_scan(struct ieee80211_device *ieee); +extern void ieee80211_start_scan_syncro(struct ieee80211_device *ieee); +extern void ieee80211_check_all_nets(struct ieee80211_device *ieee); +extern void ieee80211_start_protocol(struct ieee80211_device *ieee); +extern void ieee80211_stop_protocol(struct ieee80211_device *ieee); +extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee); +extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee); +extern void ieee80211_reset_queue(struct ieee80211_device *ieee); +extern void ieee80211_wake_queue(struct ieee80211_device *ieee); +extern void ieee80211_stop_queue(struct ieee80211_device *ieee); +extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee); +extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee); +extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee); +extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p); +extern void notify_wx_assoc_event(struct ieee80211_device *ieee); +extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success); + +extern void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee); + +/* ieee80211_crypt_ccmp&tkip&wep.c */ +extern void ieee80211_tkip_null(void); +extern void ieee80211_wep_null(void); +extern void ieee80211_ccmp_null(void); + +/* ieee80211_softmac_wx.c */ + +extern int ieee80211_wx_get_wap(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *ext); + +extern int ieee80211_wx_set_wap(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *awrq, + char *extra); + +extern int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b); + +extern int ieee80211_wx_set_rate(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_get_rate(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); + +extern int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); + +extern int ieee80211_wx_set_essid(struct ieee80211_device *ieee, + struct iw_request_info *a, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); + +extern int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); + +extern int ieee80211_wx_get_freq(struct ieee80211_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); + +//extern void ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee); +extern void ieee80211_wx_sync_scan_wq(struct work_struct *work); + + +extern int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_get_name(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_set_power(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_get_power(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_set_rts(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int ieee80211_wx_get_rts(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +//HT +#define MAX_RECEIVE_BUFFER_SIZE 9100 // +extern void HTDebugHTCapability(u8* CapIE, u8* TitleString ); +extern void HTDebugHTInfo(u8* InfoIE, u8* TitleString); + +void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset); +extern void HTUpdateDefaultSetting(struct ieee80211_device* ieee); +extern void HTConstructCapabilityElement(struct ieee80211_device* ieee, u8* posHTCap, u8* len, u8 isEncrypt); +extern void HTConstructInfoElement(struct ieee80211_device* ieee, u8* posHTInfo, u8* len, u8 isEncrypt); +extern void HTConstructRT2RTAggElement(struct ieee80211_device* ieee, u8* posRT2RTAgg, u8* len); +extern void HTOnAssocRsp(struct ieee80211_device *ieee); +extern void HTInitializeHTInfo(struct ieee80211_device* ieee); +extern void HTInitializeBssDesc(PBSS_HT pBssHT); +extern void HTResetSelfAndSavePeerSetting(struct ieee80211_device* ieee, struct ieee80211_network * pNetwork); +extern void HTUpdateSelfAndPeerSetting(struct ieee80211_device* ieee, struct ieee80211_network * pNetwork); +extern u8 HTGetHighestMCSRate(struct ieee80211_device* ieee, u8* pMCSRateSet, u8* pMCSFilter); +extern u8 MCS_FILTER_ALL[]; +extern u16 MCS_DATA_RATE[2][2][77] ; +extern u8 HTCCheck(struct ieee80211_device* ieee, u8* pFrame); +//extern void HTSetConnectBwModeCallback(unsigned long data); +extern void HTResetIOTSetting(PRT_HIGH_THROUGHPUT pHTInfo); +extern bool IsHTHalfNmodeAPs(struct ieee80211_device* ieee); +extern u16 HTHalfMcsToDataRate(struct ieee80211_device* ieee, u8 nMcsRate); +extern u16 HTMcsToDataRate( struct ieee80211_device* ieee, u8 nMcsRate); +extern u16 TxCountToDataRate( struct ieee80211_device* ieee, u8 nDataRate); +//function in BAPROC.c +extern int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb); +extern int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb); +extern int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb); +extern void TsInitAddBA( struct ieee80211_device* ieee, PTX_TS_RECORD pTS, u8 Policy, u8 bOverwritePending); +extern void TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect); +extern void BaSetupTimeOut(unsigned long data); +extern void TxBaInactTimeout(unsigned long data); +extern void RxBaInactTimeout(unsigned long data); +extern void ResetBaEntry( PBA_RECORD pBA); +//function in TS.c +extern bool GetTs( + struct ieee80211_device* ieee, + PTS_COMMON_INFO *ppTS, + u8* Addr, + u8 TID, + TR_SELECT TxRxSelect, //Rx:1, Tx:0 + bool bAddNewTs + ); +extern void TSInitialize(struct ieee80211_device *ieee); +extern void TsStartAddBaProcess(struct ieee80211_device* ieee, PTX_TS_RECORD pTxTS); +extern void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr); +extern void RemoveAllTS(struct ieee80211_device* ieee); +void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee); + +extern const long ieee80211_wlan_frequencies[]; + +extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee) +{ + ieee->scans++; +} + +extern inline int ieee80211_get_scans(struct ieee80211_device *ieee) +{ + return ieee->scans; +} + +static inline const char *escape_essid(const char *essid, u8 essid_len) { + static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; + const char *s = essid; + char *d = escaped; + + if (ieee80211_is_empty_essid(essid, essid_len)) { + memcpy(escaped, "", sizeof("")); + return escaped; + } + + essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE); + while (essid_len--) { + if (*s == '\0') { + *d++ = '\\'; + *d++ = '0'; + s++; + } else { + *d++ = *s++; + } + } + *d = '\0'; + return escaped; +} + +/* For the function is more related to hardware setting, it's better to use the + * ieee handler to refer to it. + */ +extern short check_nic_enough_desc(struct net_device *dev, int queue_index); +extern int ieee80211_data_xmit(struct sk_buff *skb, struct net_device *dev); +extern int ieee80211_parse_info_param(struct ieee80211_device *ieee, + struct ieee80211_info_element *info_element, + u16 length, + struct ieee80211_network *network, + struct ieee80211_rx_stats *stats); + +void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb** prxbIndicateArray,u8 index); +#define RT_ASOC_RETRY_LIMIT 5 +#endif /* IEEE80211_H */ diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c new file mode 100644 index 0000000000000000000000000000000000000000..521e7b989934eae69614cfa1a74ba32ec4dcd52f --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c @@ -0,0 +1,244 @@ +/* + * Host AP crypto routines + * + * Copyright (c) 2002-2003, Jouni Malinen + * Portions Copyright (C) 2004, Intel Corporation + * + * 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. See README and COPYING for + * more details. + * + */ + +//#include +#include +#include +#include +#include +#include +#include + +#include "ieee80211.h" + +MODULE_AUTHOR("Jouni Malinen"); +MODULE_DESCRIPTION("HostAP crypto"); +MODULE_LICENSE("GPL"); + +struct ieee80211_crypto_alg { + struct list_head list; + struct ieee80211_crypto_ops *ops; +}; + + +struct ieee80211_crypto { + struct list_head algs; + spinlock_t lock; +}; + +static struct ieee80211_crypto *hcrypt; + +void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, + int force) +{ + struct list_head *ptr, *n; + struct ieee80211_crypt_data *entry; + + for (ptr = ieee->crypt_deinit_list.next, n = ptr->next; + ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) { + entry = list_entry(ptr, struct ieee80211_crypt_data, list); + + if (atomic_read(&entry->refcnt) != 0 && !force) + continue; + + list_del(ptr); + + if (entry->ops) + entry->ops->deinit(entry->priv); + kfree(entry); + } +} + +void ieee80211_crypt_deinit_handler(unsigned long data) +{ + struct ieee80211_device *ieee = (struct ieee80211_device *)data; + unsigned long flags; + + spin_lock_irqsave(&ieee->lock, flags); + ieee80211_crypt_deinit_entries(ieee, 0); + if (!list_empty(&ieee->crypt_deinit_list)) { + printk(KERN_DEBUG "%s: entries remaining in delayed crypt " + "deletion list\n", ieee->dev->name); + ieee->crypt_deinit_timer.expires = jiffies + HZ; + add_timer(&ieee->crypt_deinit_timer); + } + spin_unlock_irqrestore(&ieee->lock, flags); + +} + +void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, + struct ieee80211_crypt_data **crypt) +{ + struct ieee80211_crypt_data *tmp; + unsigned long flags; + + if (*crypt == NULL) + return; + + tmp = *crypt; + *crypt = NULL; + + /* must not run ops->deinit() while there may be pending encrypt or + * decrypt operations. Use a list of delayed deinits to avoid needing + * locking. */ + + spin_lock_irqsave(&ieee->lock, flags); + list_add(&tmp->list, &ieee->crypt_deinit_list); + if (!timer_pending(&ieee->crypt_deinit_timer)) { + ieee->crypt_deinit_timer.expires = jiffies + HZ; + add_timer(&ieee->crypt_deinit_timer); + } + spin_unlock_irqrestore(&ieee->lock, flags); +} + +int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops) +{ + unsigned long flags; + struct ieee80211_crypto_alg *alg; + + if (hcrypt == NULL) + return -1; + + alg = kmalloc(sizeof(*alg), GFP_KERNEL); + if (alg == NULL) + return -ENOMEM; + + memset(alg, 0, sizeof(*alg)); + alg->ops = ops; + + spin_lock_irqsave(&hcrypt->lock, flags); + list_add(&alg->list, &hcrypt->algs); + spin_unlock_irqrestore(&hcrypt->lock, flags); + + printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n", + ops->name); + + return 0; +} + +int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops) +{ + unsigned long flags; + struct list_head *ptr; + struct ieee80211_crypto_alg *del_alg = NULL; + + if (hcrypt == NULL) + return -1; + + spin_lock_irqsave(&hcrypt->lock, flags); + for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { + struct ieee80211_crypto_alg *alg = + (struct ieee80211_crypto_alg *) ptr; + if (alg->ops == ops) { + list_del(&alg->list); + del_alg = alg; + break; + } + } + spin_unlock_irqrestore(&hcrypt->lock, flags); + + if (del_alg) { + printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " + "'%s'\n", ops->name); + kfree(del_alg); + } + + return del_alg ? 0 : -1; +} + + +struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name) +{ + unsigned long flags; + struct list_head *ptr; + struct ieee80211_crypto_alg *found_alg = NULL; + + if (hcrypt == NULL) + return NULL; + + spin_lock_irqsave(&hcrypt->lock, flags); + for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { + struct ieee80211_crypto_alg *alg = + (struct ieee80211_crypto_alg *) ptr; + if (strcmp(alg->ops->name, name) == 0) { + found_alg = alg; + break; + } + } + spin_unlock_irqrestore(&hcrypt->lock, flags); + + if (found_alg) + return found_alg->ops; + else + return NULL; +} + + +static void * ieee80211_crypt_null_init(int keyidx) { return (void *) 1; } +static void ieee80211_crypt_null_deinit(void *priv) {} + +static struct ieee80211_crypto_ops ieee80211_crypt_null = { + .name = "NULL", + .init = ieee80211_crypt_null_init, + .deinit = ieee80211_crypt_null_deinit, + .encrypt_mpdu = NULL, + .decrypt_mpdu = NULL, + .encrypt_msdu = NULL, + .decrypt_msdu = NULL, + .set_key = NULL, + .get_key = NULL, + .extra_prefix_len = 0, + .extra_postfix_len = 0, + .owner = THIS_MODULE, +}; + +int __init ieee80211_crypto_init(void) +{ + int ret = -ENOMEM; + + hcrypt = kmalloc(sizeof(*hcrypt), GFP_KERNEL); + if (!hcrypt) + goto out; + + memset(hcrypt, 0, sizeof(*hcrypt)); + INIT_LIST_HEAD(&hcrypt->algs); + spin_lock_init(&hcrypt->lock); + + ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null); + if (ret < 0) { + kfree(hcrypt); + hcrypt = NULL; + } +out: + return ret; +} + +void __exit ieee80211_crypto_deinit(void) +{ + struct list_head *ptr, *n; + + if (hcrypt == NULL) + return; + + for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs; + ptr = n, n = ptr->next) { + struct ieee80211_crypto_alg *alg = + (struct ieee80211_crypto_alg *) ptr; + list_del(ptr); + printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " + "'%s' (deinit)\n", alg->ops->name); + kfree(alg); + } + + kfree(hcrypt); +} diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h new file mode 100644 index 0000000000000000000000000000000000000000..b58a3bcc0dc0972c882f5992ad02264510769bf5 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h @@ -0,0 +1,86 @@ +/* + * Original code based on Host AP (software wireless LAN access point) driver + * for Intersil Prism2/2.5/3. + * + * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen + * + * Copyright (c) 2002-2003, Jouni Malinen + * + * Adaption to a generic IEEE 802.11 stack by James Ketrenos + * + * + * Copyright (c) 2004, Intel Corporation + * + * 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. See README and COPYING for + * more details. + */ + +/* + * This file defines the interface to the ieee80211 crypto module. + */ +#ifndef IEEE80211_CRYPT_H +#define IEEE80211_CRYPT_H + +#include + +struct ieee80211_crypto_ops { + const char *name; + + /* init new crypto context (e.g., allocate private data space, + * select IV, etc.); returns NULL on failure or pointer to allocated + * private data on success */ + void * (*init)(int keyidx); + + /* deinitialize crypto context and free allocated private data */ + void (*deinit)(void *priv); + + /* encrypt/decrypt return < 0 on error or >= 0 on success. The return + * value from decrypt_mpdu is passed as the keyidx value for + * decrypt_msdu. skb must have enough head and tail room for the + * encryption; if not, error will be returned; these functions are + * called for all MPDUs (i.e., fragments). + */ + int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv); + int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv); + + /* These functions are called for full MSDUs, i.e. full frames. + * These can be NULL if full MSDU operations are not needed. */ + int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv); + int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len, + void *priv); + + int (*set_key)(void *key, int len, u8 *seq, void *priv); + int (*get_key)(void *key, int len, u8 *seq, void *priv); + + /* procfs handler for printing out key information and possible + * statistics */ + char * (*print_stats)(char *p, void *priv); + + /* maximum number of bytes added by encryption; encrypt buf is + * allocated with extra_prefix_len bytes, copy of in_buf, and + * extra_postfix_len; encrypt need not use all this space, but + * the result must start at the beginning of the buffer and correct + * length must be returned */ + int extra_prefix_len, extra_postfix_len; + + struct module *owner; +}; + +struct ieee80211_crypt_data { + struct list_head list; /* delayed deletion list */ + struct ieee80211_crypto_ops *ops; + void *priv; + atomic_t refcnt; +}; + +int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops); +int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops); +struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name); +void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int); +void ieee80211_crypt_deinit_handler(unsigned long); +void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, + struct ieee80211_crypt_data **crypt); + +#endif diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c new file mode 100644 index 0000000000000000000000000000000000000000..0b33bf4633208a89c9041f7b86a59ad792a0d1df --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c @@ -0,0 +1,480 @@ +/* + * Host AP crypt: host-based CCMP encryption implementation for Host AP driver + * + * Copyright (c) 2003-2004, Jouni Malinen + * + * 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. See README and COPYING for + * more details. + */ + +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ieee80211.h" + +#include + #include + +MODULE_AUTHOR("Jouni Malinen"); +MODULE_DESCRIPTION("Host AP crypt: CCMP"); +MODULE_LICENSE("GPL"); + +#define AES_BLOCK_LEN 16 +#define CCMP_HDR_LEN 8 +#define CCMP_MIC_LEN 8 +#define CCMP_TK_LEN 16 +#define CCMP_PN_LEN 6 + +struct ieee80211_ccmp_data { + u8 key[CCMP_TK_LEN]; + int key_set; + + u8 tx_pn[CCMP_PN_LEN]; + u8 rx_pn[CCMP_PN_LEN]; + + u32 dot11RSNAStatsCCMPFormatErrors; + u32 dot11RSNAStatsCCMPReplays; + u32 dot11RSNAStatsCCMPDecryptErrors; + + int key_idx; + + struct crypto_tfm *tfm; + + /* scratch buffers for virt_to_page() (crypto API) */ + u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], + tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN]; + u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; +}; + +void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm, + const u8 pt[16], u8 ct[16]) +{ + crypto_cipher_encrypt_one((void*)tfm, ct, pt); +} + +static void * ieee80211_ccmp_init(int key_idx) +{ + struct ieee80211_ccmp_data *priv; + + priv = kmalloc(sizeof(*priv), GFP_ATOMIC); + if (priv == NULL) + goto fail; + memset(priv, 0, sizeof(*priv)); + priv->key_idx = key_idx; + + priv->tfm = (void*)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(priv->tfm)) { + printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate " + "crypto API aes\n"); + priv->tfm = NULL; + goto fail; + } + + return priv; + +fail: + if (priv) { + if (priv->tfm) + crypto_free_cipher((void*)priv->tfm); + kfree(priv); + } + + return NULL; +} + + +static void ieee80211_ccmp_deinit(void *priv) +{ + struct ieee80211_ccmp_data *_priv = priv; + + if (_priv && _priv->tfm) + crypto_free_cipher((void*)_priv->tfm); + kfree(priv); +} + + +static inline void xor_block(u8 *b, u8 *a, size_t len) +{ + int i; + for (i = 0; i < len; i++) + b[i] ^= a[i]; +} + + + +static void ccmp_init_blocks(struct crypto_tfm *tfm, + struct ieee80211_hdr_4addr *hdr, + u8 *pn, size_t dlen, u8 *b0, u8 *auth, + u8 *s0) +{ + u8 *pos, qc = 0; + size_t aad_len; + u16 fc; + int a4_included, qc_included; + u8 aad[2 * AES_BLOCK_LEN]; + + fc = le16_to_cpu(hdr->frame_ctl); + a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == + (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)); + /* + qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) && + (WLAN_FC_GET_STYPE(fc) & 0x08)); + */ + // fixed by David :2006.9.6 + qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) && + (WLAN_FC_GET_STYPE(fc) & 0x80)); + aad_len = 22; + if (a4_included) + aad_len += 6; + if (qc_included) { + pos = (u8 *) &hdr->addr4; + if (a4_included) + pos += 6; + qc = *pos & 0x0f; + aad_len += 2; + } + /* CCM Initial Block: + * Flag (Include authentication header, M=3 (8-octet MIC), + * L=1 (2-octet Dlen)) + * Nonce: 0x00 | A2 | PN + * Dlen */ + b0[0] = 0x59; + b0[1] = qc; + memcpy(b0 + 2, hdr->addr2, ETH_ALEN); + memcpy(b0 + 8, pn, CCMP_PN_LEN); + b0[14] = (dlen >> 8) & 0xff; + b0[15] = dlen & 0xff; + + /* AAD: + * FC with bits 4..6 and 11..13 masked to zero; 14 is always one + * A1 | A2 | A3 + * SC with bits 4..15 (seq#) masked to zero + * A4 (if present) + * QC (if present) + */ + pos = (u8 *) hdr; + aad[0] = 0; /* aad_len >> 8 */ + aad[1] = aad_len & 0xff; + aad[2] = pos[0] & 0x8f; + aad[3] = pos[1] & 0xc7; + memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); + pos = (u8 *) &hdr->seq_ctl; + aad[22] = pos[0] & 0x0f; + aad[23] = 0; /* all bits masked */ + memset(aad + 24, 0, 8); + if (a4_included) + memcpy(aad + 24, hdr->addr4, ETH_ALEN); + if (qc_included) { + aad[a4_included ? 30 : 24] = qc; + /* rest of QC masked */ + } + + /* Start with the first block and AAD */ + ieee80211_ccmp_aes_encrypt(tfm, b0, auth); + xor_block(auth, aad, AES_BLOCK_LEN); + ieee80211_ccmp_aes_encrypt(tfm, auth, auth); + xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN); + ieee80211_ccmp_aes_encrypt(tfm, auth, auth); + b0[0] &= 0x07; + b0[14] = b0[15] = 0; + ieee80211_ccmp_aes_encrypt(tfm, b0, s0); +} + + + +static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) +{ + struct ieee80211_ccmp_data *key = priv; + int data_len, i; + u8 *pos; + struct ieee80211_hdr_4addr *hdr; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + + if (skb_headroom(skb) < CCMP_HDR_LEN || + skb_tailroom(skb) < CCMP_MIC_LEN || + skb->len < hdr_len) + return -1; + + data_len = skb->len - hdr_len; + pos = skb_push(skb, CCMP_HDR_LEN); + memmove(pos, pos + CCMP_HDR_LEN, hdr_len); + pos += hdr_len; +// mic = skb_put(skb, CCMP_MIC_LEN); + + i = CCMP_PN_LEN - 1; + while (i >= 0) { + key->tx_pn[i]++; + if (key->tx_pn[i] != 0) + break; + i--; + } + + *pos++ = key->tx_pn[5]; + *pos++ = key->tx_pn[4]; + *pos++ = 0; + *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */; + *pos++ = key->tx_pn[3]; + *pos++ = key->tx_pn[2]; + *pos++ = key->tx_pn[1]; + *pos++ = key->tx_pn[0]; + + + hdr = (struct ieee80211_hdr_4addr *) skb->data; + if (!tcb_desc->bHwSec) + { + int blocks, last, len; + u8 *mic; + u8 *b0 = key->tx_b0; + u8 *b = key->tx_b; + u8 *e = key->tx_e; + u8 *s0 = key->tx_s0; + + //mic is moved to here by john + mic = skb_put(skb, CCMP_MIC_LEN); + + ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); + + blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; + last = data_len % AES_BLOCK_LEN; + + for (i = 1; i <= blocks; i++) { + len = (i == blocks && last) ? last : AES_BLOCK_LEN; + /* Authentication */ + xor_block(b, pos, len); + ieee80211_ccmp_aes_encrypt(key->tfm, b, b); + /* Encryption, with counter */ + b0[14] = (i >> 8) & 0xff; + b0[15] = i & 0xff; + ieee80211_ccmp_aes_encrypt(key->tfm, b0, e); + xor_block(pos, e, len); + pos += len; + } + + for (i = 0; i < CCMP_MIC_LEN; i++) + mic[i] = b[i] ^ s0[i]; + } + return 0; +} + + +static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) +{ + struct ieee80211_ccmp_data *key = priv; + u8 keyidx, *pos; + struct ieee80211_hdr_4addr *hdr; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + u8 pn[6]; + + if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) { + key->dot11RSNAStatsCCMPFormatErrors++; + return -1; + } + + hdr = (struct ieee80211_hdr_4addr *) skb->data; + pos = skb->data + hdr_len; + keyidx = pos[3]; + if (!(keyidx & (1 << 5))) { + if (net_ratelimit()) { + printk(KERN_DEBUG "CCMP: received packet without ExtIV" + " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2)); + } + key->dot11RSNAStatsCCMPFormatErrors++; + return -2; + } + keyidx >>= 6; + if (key->key_idx != keyidx) { + printk(KERN_DEBUG "CCMP: RX tkey->key_idx=%d frame " + "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv); + return -6; + } + if (!key->key_set) { + if (net_ratelimit()) { + printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT + " with keyid=%d that does not have a configured" + " key\n", MAC_ARG(hdr->addr2), keyidx); + } + return -3; + } + + pn[0] = pos[7]; + pn[1] = pos[6]; + pn[2] = pos[5]; + pn[3] = pos[4]; + pn[4] = pos[1]; + pn[5] = pos[0]; + pos += 8; + + if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) { + if (net_ratelimit()) { + printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT + " previous PN %02x%02x%02x%02x%02x%02x " + "received PN %02x%02x%02x%02x%02x%02x\n", + MAC_ARG(hdr->addr2), MAC_ARG(key->rx_pn), + MAC_ARG(pn)); + } + key->dot11RSNAStatsCCMPReplays++; + return -4; + } + if (!tcb_desc->bHwSec) + { + size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN; + u8 *mic = skb->data + skb->len - CCMP_MIC_LEN; + u8 *b0 = key->rx_b0; + u8 *b = key->rx_b; + u8 *a = key->rx_a; + int i, blocks, last, len; + + + ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b); + xor_block(mic, b, CCMP_MIC_LEN); + + blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; + last = data_len % AES_BLOCK_LEN; + + for (i = 1; i <= blocks; i++) { + len = (i == blocks && last) ? last : AES_BLOCK_LEN; + /* Decrypt, with counter */ + b0[14] = (i >> 8) & 0xff; + b0[15] = i & 0xff; + ieee80211_ccmp_aes_encrypt(key->tfm, b0, b); + xor_block(pos, b, len); + /* Authentication */ + xor_block(a, pos, len); + ieee80211_ccmp_aes_encrypt(key->tfm, a, a); + pos += len; + } + + if (memcmp(mic, a, CCMP_MIC_LEN) != 0) { + if (net_ratelimit()) { + printk(KERN_DEBUG "CCMP: decrypt failed: STA=" + MAC_FMT "\n", MAC_ARG(hdr->addr2)); + } + key->dot11RSNAStatsCCMPDecryptErrors++; + return -5; + } + + memcpy(key->rx_pn, pn, CCMP_PN_LEN); + } + /* Remove hdr and MIC */ + memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len); + skb_pull(skb, CCMP_HDR_LEN); + skb_trim(skb, skb->len - CCMP_MIC_LEN); + + return keyidx; +} + + +static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv) +{ + struct ieee80211_ccmp_data *data = priv; + int keyidx; + struct crypto_tfm *tfm = data->tfm; + + keyidx = data->key_idx; + memset(data, 0, sizeof(*data)); + data->key_idx = keyidx; + data->tfm = tfm; + if (len == CCMP_TK_LEN) { + memcpy(data->key, key, CCMP_TK_LEN); + data->key_set = 1; + if (seq) { + data->rx_pn[0] = seq[5]; + data->rx_pn[1] = seq[4]; + data->rx_pn[2] = seq[3]; + data->rx_pn[3] = seq[2]; + data->rx_pn[4] = seq[1]; + data->rx_pn[5] = seq[0]; + } + crypto_cipher_setkey((void*)data->tfm, data->key, CCMP_TK_LEN); + } else if (len == 0) + data->key_set = 0; + else + return -1; + + return 0; +} + + +static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv) +{ + struct ieee80211_ccmp_data *data = priv; + + if (len < CCMP_TK_LEN) + return -1; + + if (!data->key_set) + return 0; + memcpy(key, data->key, CCMP_TK_LEN); + + if (seq) { + seq[0] = data->tx_pn[5]; + seq[1] = data->tx_pn[4]; + seq[2] = data->tx_pn[3]; + seq[3] = data->tx_pn[2]; + seq[4] = data->tx_pn[1]; + seq[5] = data->tx_pn[0]; + } + + return CCMP_TK_LEN; +} + + +static char * ieee80211_ccmp_print_stats(char *p, void *priv) +{ + struct ieee80211_ccmp_data *ccmp = priv; + p += sprintf(p, "key[%d] alg=CCMP key_set=%d " + "tx_pn=%02x%02x%02x%02x%02x%02x " + "rx_pn=%02x%02x%02x%02x%02x%02x " + "format_errors=%d replays=%d decrypt_errors=%d\n", + ccmp->key_idx, ccmp->key_set, + MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn), + ccmp->dot11RSNAStatsCCMPFormatErrors, + ccmp->dot11RSNAStatsCCMPReplays, + ccmp->dot11RSNAStatsCCMPDecryptErrors); + + return p; +} + +void ieee80211_ccmp_null(void) +{ +// printk("============>%s()\n", __FUNCTION__); + return; +} + +static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = { + .name = "CCMP", + .init = ieee80211_ccmp_init, + .deinit = ieee80211_ccmp_deinit, + .encrypt_mpdu = ieee80211_ccmp_encrypt, + .decrypt_mpdu = ieee80211_ccmp_decrypt, + .encrypt_msdu = NULL, + .decrypt_msdu = NULL, + .set_key = ieee80211_ccmp_set_key, + .get_key = ieee80211_ccmp_get_key, + .print_stats = ieee80211_ccmp_print_stats, + .extra_prefix_len = CCMP_HDR_LEN, + .extra_postfix_len = CCMP_MIC_LEN, + .owner = THIS_MODULE, +}; + +int __init ieee80211_crypto_ccmp_init(void) +{ + return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp); +} + +void __exit ieee80211_crypto_ccmp_exit(void) +{ + ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp); +} diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c new file mode 100644 index 0000000000000000000000000000000000000000..841b99955b7900cd2f7b380c8e8f812189f02ee7 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c @@ -0,0 +1,780 @@ +/* + * Host AP crypt: host-based TKIP encryption implementation for Host AP driver + * + * Copyright (c) 2003-2004, Jouni Malinen + * + * 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. See README and COPYING for + * more details. + */ + +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ieee80211.h" + +#include + #include +#include + +MODULE_AUTHOR("Jouni Malinen"); +MODULE_DESCRIPTION("Host AP crypt: TKIP"); +MODULE_LICENSE("GPL"); + +struct ieee80211_tkip_data { +#define TKIP_KEY_LEN 32 + u8 key[TKIP_KEY_LEN]; + int key_set; + + u32 tx_iv32; + u16 tx_iv16; + u16 tx_ttak[5]; + int tx_phase1_done; + + u32 rx_iv32; + u16 rx_iv16; + u16 rx_ttak[5]; + int rx_phase1_done; + u32 rx_iv32_new; + u16 rx_iv16_new; + + u32 dot11RSNAStatsTKIPReplays; + u32 dot11RSNAStatsTKIPICVErrors; + u32 dot11RSNAStatsTKIPLocalMICFailures; + + int key_idx; + + struct crypto_blkcipher *rx_tfm_arc4; + struct crypto_hash *rx_tfm_michael; + struct crypto_blkcipher *tx_tfm_arc4; + struct crypto_hash *tx_tfm_michael; + + /* scratch buffers for virt_to_page() (crypto API) */ + u8 rx_hdr[16], tx_hdr[16]; +}; + +static void * ieee80211_tkip_init(int key_idx) +{ + struct ieee80211_tkip_data *priv; + + priv = kmalloc(sizeof(*priv), GFP_ATOMIC); + if (priv == NULL) + goto fail; + memset(priv, 0, sizeof(*priv)); + priv->key_idx = key_idx; + + priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); + if (IS_ERR(priv->tx_tfm_arc4)) { + printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " + "crypto API arc4\n"); + priv->tx_tfm_arc4 = NULL; + goto fail; + } + + priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0, + CRYPTO_ALG_ASYNC); + if (IS_ERR(priv->tx_tfm_michael)) { + printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " + "crypto API michael_mic\n"); + priv->tx_tfm_michael = NULL; + goto fail; + } + + priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); + if (IS_ERR(priv->rx_tfm_arc4)) { + printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " + "crypto API arc4\n"); + priv->rx_tfm_arc4 = NULL; + goto fail; + } + + priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0, + CRYPTO_ALG_ASYNC); + if (IS_ERR(priv->rx_tfm_michael)) { + printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " + "crypto API michael_mic\n"); + priv->rx_tfm_michael = NULL; + goto fail; + } + + return priv; + +fail: + if (priv) { + if (priv->tx_tfm_michael) + crypto_free_hash(priv->tx_tfm_michael); + if (priv->tx_tfm_arc4) + crypto_free_blkcipher(priv->tx_tfm_arc4); + if (priv->rx_tfm_michael) + crypto_free_hash(priv->rx_tfm_michael); + if (priv->rx_tfm_arc4) + crypto_free_blkcipher(priv->rx_tfm_arc4); + kfree(priv); + } + + return NULL; +} + + +static void ieee80211_tkip_deinit(void *priv) +{ + struct ieee80211_tkip_data *_priv = priv; + + if (_priv) { + if (_priv->tx_tfm_michael) + crypto_free_hash(_priv->tx_tfm_michael); + if (_priv->tx_tfm_arc4) + crypto_free_blkcipher(_priv->tx_tfm_arc4); + if (_priv->rx_tfm_michael) + crypto_free_hash(_priv->rx_tfm_michael); + if (_priv->rx_tfm_arc4) + crypto_free_blkcipher(_priv->rx_tfm_arc4); + } + kfree(priv); +} + + +static inline u16 RotR1(u16 val) +{ + return (val >> 1) | (val << 15); +} + + +static inline u8 Lo8(u16 val) +{ + return val & 0xff; +} + + +static inline u8 Hi8(u16 val) +{ + return val >> 8; +} + + +static inline u16 Lo16(u32 val) +{ + return val & 0xffff; +} + + +static inline u16 Hi16(u32 val) +{ + return val >> 16; +} + + +static inline u16 Mk16(u8 hi, u8 lo) +{ + return lo | (((u16) hi) << 8); +} + + +static inline u16 Mk16_le(u16 *v) +{ + return le16_to_cpu(*v); +} + + +static const u16 Sbox[256] = +{ + 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, + 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, + 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, + 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, + 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, + 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, + 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, + 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, + 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, + 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, + 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, + 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, + 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, + 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, + 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, + 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, + 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, + 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, + 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, + 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, + 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, + 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, + 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, + 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, + 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, + 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, + 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, + 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, + 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, + 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, + 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, + 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, +}; + + +static inline u16 _S_(u16 v) +{ + u16 t = Sbox[Hi8(v)]; + return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8)); +} + + +#define PHASE1_LOOP_COUNT 8 + + +static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32) +{ + int i, j; + + /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */ + TTAK[0] = Lo16(IV32); + TTAK[1] = Hi16(IV32); + TTAK[2] = Mk16(TA[1], TA[0]); + TTAK[3] = Mk16(TA[3], TA[2]); + TTAK[4] = Mk16(TA[5], TA[4]); + + for (i = 0; i < PHASE1_LOOP_COUNT; i++) { + j = 2 * (i & 1); + TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j])); + TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j])); + TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j])); + TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j])); + TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i; + } +} + + +static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, + u16 IV16) +{ + /* Make temporary area overlap WEP seed so that the final copy can be + * avoided on little endian hosts. */ + u16 *PPK = (u16 *) &WEPSeed[4]; + + /* Step 1 - make copy of TTAK and bring in TSC */ + PPK[0] = TTAK[0]; + PPK[1] = TTAK[1]; + PPK[2] = TTAK[2]; + PPK[3] = TTAK[3]; + PPK[4] = TTAK[4]; + PPK[5] = TTAK[4] + IV16; + + /* Step 2 - 96-bit bijective mixing using S-box */ + PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0])); + PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2])); + PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4])); + PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6])); + PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8])); + PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10])); + + PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12])); + PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14])); + PPK[2] += RotR1(PPK[1]); + PPK[3] += RotR1(PPK[2]); + PPK[4] += RotR1(PPK[3]); + PPK[5] += RotR1(PPK[4]); + + /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value + * WEPSeed[0..2] is transmitted as WEP IV */ + WEPSeed[0] = Hi8(IV16); + WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F; + WEPSeed[2] = Lo8(IV16); + WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1); + +#ifdef __BIG_ENDIAN + { + int i; + for (i = 0; i < 6; i++) + PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8); + } +#endif +} + + +static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) +{ + struct ieee80211_tkip_data *tkey = priv; + int len; + u8 *pos; + struct ieee80211_hdr_4addr *hdr; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4}; + int ret = 0; + u8 rc4key[16], *icv; + u32 crc; + struct scatterlist sg; + + if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 || + skb->len < hdr_len) + return -1; + + hdr = (struct ieee80211_hdr_4addr *) skb->data; + + if (!tcb_desc->bHwSec) + { + if (!tkey->tx_phase1_done) { + tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, + tkey->tx_iv32); + tkey->tx_phase1_done = 1; + } + tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); + } + else + tkey->tx_phase1_done = 1; + + + len = skb->len - hdr_len; + pos = skb_push(skb, 8); + memmove(pos, pos + 8, hdr_len); + pos += hdr_len; + + if (tcb_desc->bHwSec) + { + *pos++ = Hi8(tkey->tx_iv16); + *pos++ = (Hi8(tkey->tx_iv16) | 0x20) & 0x7F; + *pos++ = Lo8(tkey->tx_iv16); + } + else + { + *pos++ = rc4key[0]; + *pos++ = rc4key[1]; + *pos++ = rc4key[2]; + } + + *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */; + *pos++ = tkey->tx_iv32 & 0xff; + *pos++ = (tkey->tx_iv32 >> 8) & 0xff; + *pos++ = (tkey->tx_iv32 >> 16) & 0xff; + *pos++ = (tkey->tx_iv32 >> 24) & 0xff; + + if (!tcb_desc->bHwSec) + { + icv = skb_put(skb, 4); + crc = ~crc32_le(~0, pos, len); + icv[0] = crc; + icv[1] = crc >> 8; + icv[2] = crc >> 16; + icv[3] = crc >> 24; + crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); + sg_init_one(&sg, pos, len+4); + ret= crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + } + + tkey->tx_iv16++; + if (tkey->tx_iv16 == 0) { + tkey->tx_phase1_done = 0; + tkey->tx_iv32++; + } + + if (!tcb_desc->bHwSec) + return ret; + else + return 0; + + +} + +static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) +{ + struct ieee80211_tkip_data *tkey = priv; + u8 keyidx, *pos; + u32 iv32; + u16 iv16; + struct ieee80211_hdr_4addr *hdr; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + struct blkcipher_desc desc = {.tfm = tkey->rx_tfm_arc4}; + u8 rc4key[16]; + u8 icv[4]; + u32 crc; + struct scatterlist sg; + int plen; + if (skb->len < hdr_len + 8 + 4) + return -1; + + hdr = (struct ieee80211_hdr_4addr *) skb->data; + pos = skb->data + hdr_len; + keyidx = pos[3]; + if (!(keyidx & (1 << 5))) { + if (net_ratelimit()) { + printk(KERN_DEBUG "TKIP: received packet without ExtIV" + " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2)); + } + return -2; + } + keyidx >>= 6; + if (tkey->key_idx != keyidx) { + printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame " + "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv); + return -6; + } + if (!tkey->key_set) { + if (net_ratelimit()) { + printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT + " with keyid=%d that does not have a configured" + " key\n", MAC_ARG(hdr->addr2), keyidx); + } + return -3; + } + iv16 = (pos[0] << 8) | pos[2]; + iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); + pos += 8; + + if (!tcb_desc->bHwSec) + { + if (iv32 < tkey->rx_iv32 || + (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) { + if (net_ratelimit()) { + printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT + " previous TSC %08x%04x received TSC " + "%08x%04x\n", MAC_ARG(hdr->addr2), + tkey->rx_iv32, tkey->rx_iv16, iv32, iv16); + } + tkey->dot11RSNAStatsTKIPReplays++; + return -4; + } + + if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) { + tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32); + tkey->rx_phase1_done = 1; + } + tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16); + + plen = skb->len - hdr_len - 12; + + crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); + sg_init_one(&sg, pos, plen+4); + + if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { + if (net_ratelimit()) { + printk(KERN_DEBUG ": TKIP: failed to decrypt " + "received packet from " MAC_FMT "\n", + MAC_ARG(hdr->addr2)); + } + return -7; + } + + crc = ~crc32_le(~0, pos, plen); + icv[0] = crc; + icv[1] = crc >> 8; + icv[2] = crc >> 16; + icv[3] = crc >> 24; + + if (memcmp(icv, pos + plen, 4) != 0) { + if (iv32 != tkey->rx_iv32) { + /* Previously cached Phase1 result was already lost, so + * it needs to be recalculated for the next packet. */ + tkey->rx_phase1_done = 0; + } + if (net_ratelimit()) { + printk(KERN_DEBUG "TKIP: ICV error detected: STA=" + MAC_FMT "\n", MAC_ARG(hdr->addr2)); + } + tkey->dot11RSNAStatsTKIPICVErrors++; + return -5; + } + + } + + /* Update real counters only after Michael MIC verification has + * completed */ + tkey->rx_iv32_new = iv32; + tkey->rx_iv16_new = iv16; + + /* Remove IV and ICV */ + memmove(skb->data + 8, skb->data, hdr_len); + skb_pull(skb, 8); + skb_trim(skb, skb->len - 4); + + return keyidx; +} + +static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr, + u8 * data, size_t data_len, u8 * mic) +{ + struct hash_desc desc; + struct scatterlist sg[2]; + + if (tfm_michael == NULL) { + printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); + return -1; + } + + sg_init_table(sg, 2); + sg_set_buf(&sg[0], hdr, 16); + sg_set_buf(&sg[1], data, data_len); + + if (crypto_hash_setkey(tfm_michael, key, 8)) + return -1; + + desc.tfm = tfm_michael; + desc.flags = 0; + return crypto_hash_digest(&desc, sg, data_len + 16, mic); +} + +static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) +{ + struct ieee80211_hdr_4addr *hdr11; + + hdr11 = (struct ieee80211_hdr_4addr *) skb->data; + switch (le16_to_cpu(hdr11->frame_ctl) & + (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { + case IEEE80211_FCTL_TODS: + memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ + memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ + break; + case IEEE80211_FCTL_FROMDS: + memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ + memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */ + break; + case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: + memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ + memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */ + break; + case 0: + memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ + memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ + break; + } + + hdr[12] = 0; /* priority */ + + hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */ +} + + +static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv) +{ + struct ieee80211_tkip_data *tkey = priv; + u8 *pos; + struct ieee80211_hdr_4addr *hdr; + + hdr = (struct ieee80211_hdr_4addr *) skb->data; + + if (skb_tailroom(skb) < 8 || skb->len < hdr_len) { + printk(KERN_DEBUG "Invalid packet for Michael MIC add " + "(tailroom=%d hdr_len=%d skb->len=%d)\n", + skb_tailroom(skb), hdr_len, skb->len); + return -1; + } + + michael_mic_hdr(skb, tkey->tx_hdr); + + // { david, 2006.9.1 + // fix the wpa process with wmm enabled. + if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) { + tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; + } + // } + pos = skb_put(skb, 8); + + if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr, + skb->data + hdr_len, skb->len - 8 - hdr_len, pos)) + return -1; + + return 0; +} + +static void ieee80211_michael_mic_failure(struct net_device *dev, + struct ieee80211_hdr_4addr *hdr, + int keyidx) +{ + union iwreq_data wrqu; + struct iw_michaelmicfailure ev; + + /* TODO: needed parameters: count, keyid, key type, TSC */ + memset(&ev, 0, sizeof(ev)); + ev.flags = keyidx & IW_MICFAILURE_KEY_ID; + if (hdr->addr1[0] & 0x01) + ev.flags |= IW_MICFAILURE_GROUP; + else + ev.flags |= IW_MICFAILURE_PAIRWISE; + ev.src_addr.sa_family = ARPHRD_ETHER; + memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = sizeof(ev); + wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev); +} + +static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, + int hdr_len, void *priv) +{ + struct ieee80211_tkip_data *tkey = priv; + u8 mic[8]; + struct ieee80211_hdr_4addr *hdr; + + hdr = (struct ieee80211_hdr_4addr *) skb->data; + + if (!tkey->key_set) + return -1; + + michael_mic_hdr(skb, tkey->rx_hdr); + // { david, 2006.9.1 + // fix the wpa process with wmm enabled. + if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) { + tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; + } + // } + + if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr, + skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) + return -1; + if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { + struct ieee80211_hdr_4addr *hdr; + hdr = (struct ieee80211_hdr_4addr *) skb->data; + printk(KERN_DEBUG "%s: Michael MIC verification failed for " + "MSDU from " MAC_FMT " keyidx=%d\n", + skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2), + keyidx); + if (skb->dev) + ieee80211_michael_mic_failure(skb->dev, hdr, keyidx); + tkey->dot11RSNAStatsTKIPLocalMICFailures++; + return -1; + } + + /* Update TSC counters for RX now that the packet verification has + * completed. */ + tkey->rx_iv32 = tkey->rx_iv32_new; + tkey->rx_iv16 = tkey->rx_iv16_new; + + skb_trim(skb, skb->len - 8); + + return 0; +} + + +static int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv) +{ + struct ieee80211_tkip_data *tkey = priv; + int keyidx; + struct crypto_hash *tfm = tkey->tx_tfm_michael; + struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4; + struct crypto_hash *tfm3 = tkey->rx_tfm_michael; + struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4; + + keyidx = tkey->key_idx; + memset(tkey, 0, sizeof(*tkey)); + tkey->key_idx = keyidx; + tkey->tx_tfm_michael = tfm; + tkey->tx_tfm_arc4 = tfm2; + tkey->rx_tfm_michael = tfm3; + tkey->rx_tfm_arc4 = tfm4; + + if (len == TKIP_KEY_LEN) { + memcpy(tkey->key, key, TKIP_KEY_LEN); + tkey->key_set = 1; + tkey->tx_iv16 = 1; /* TSC is initialized to 1 */ + if (seq) { + tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) | + (seq[3] << 8) | seq[2]; + tkey->rx_iv16 = (seq[1] << 8) | seq[0]; + } + } else if (len == 0) + tkey->key_set = 0; + else + return -1; + + return 0; +} + + +static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv) +{ + struct ieee80211_tkip_data *tkey = priv; + + if (len < TKIP_KEY_LEN) + return -1; + + if (!tkey->key_set) + return 0; + memcpy(key, tkey->key, TKIP_KEY_LEN); + + if (seq) { + /* Return the sequence number of the last transmitted frame. */ + u16 iv16 = tkey->tx_iv16; + u32 iv32 = tkey->tx_iv32; + if (iv16 == 0) + iv32--; + iv16--; + seq[0] = tkey->tx_iv16; + seq[1] = tkey->tx_iv16 >> 8; + seq[2] = tkey->tx_iv32; + seq[3] = tkey->tx_iv32 >> 8; + seq[4] = tkey->tx_iv32 >> 16; + seq[5] = tkey->tx_iv32 >> 24; + } + + return TKIP_KEY_LEN; +} + + +static char * ieee80211_tkip_print_stats(char *p, void *priv) +{ + struct ieee80211_tkip_data *tkip = priv; + p += sprintf(p, "key[%d] alg=TKIP key_set=%d " + "tx_pn=%02x%02x%02x%02x%02x%02x " + "rx_pn=%02x%02x%02x%02x%02x%02x " + "replays=%d icv_errors=%d local_mic_failures=%d\n", + tkip->key_idx, tkip->key_set, + (tkip->tx_iv32 >> 24) & 0xff, + (tkip->tx_iv32 >> 16) & 0xff, + (tkip->tx_iv32 >> 8) & 0xff, + tkip->tx_iv32 & 0xff, + (tkip->tx_iv16 >> 8) & 0xff, + tkip->tx_iv16 & 0xff, + (tkip->rx_iv32 >> 24) & 0xff, + (tkip->rx_iv32 >> 16) & 0xff, + (tkip->rx_iv32 >> 8) & 0xff, + tkip->rx_iv32 & 0xff, + (tkip->rx_iv16 >> 8) & 0xff, + tkip->rx_iv16 & 0xff, + tkip->dot11RSNAStatsTKIPReplays, + tkip->dot11RSNAStatsTKIPICVErrors, + tkip->dot11RSNAStatsTKIPLocalMICFailures); + return p; +} + + +static struct ieee80211_crypto_ops ieee80211_crypt_tkip = { + .name = "TKIP", + .init = ieee80211_tkip_init, + .deinit = ieee80211_tkip_deinit, + .encrypt_mpdu = ieee80211_tkip_encrypt, + .decrypt_mpdu = ieee80211_tkip_decrypt, + .encrypt_msdu = ieee80211_michael_mic_add, + .decrypt_msdu = ieee80211_michael_mic_verify, + .set_key = ieee80211_tkip_set_key, + .get_key = ieee80211_tkip_get_key, + .print_stats = ieee80211_tkip_print_stats, + .extra_prefix_len = 4 + 4, /* IV + ExtIV */ + .extra_postfix_len = 8 + 4, /* MIC + ICV */ + .owner = THIS_MODULE, +}; + +int __init ieee80211_crypto_tkip_init(void) +{ + return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip); +} + +void __exit ieee80211_crypto_tkip_exit(void) +{ + ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip); +} + +void ieee80211_tkip_null(void) +{ +// printk("============>%s()\n", __FUNCTION__); + return; +} diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c new file mode 100644 index 0000000000000000000000000000000000000000..61ad11cae38c02b8720ab7a32f28268fffb2dcd0 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c @@ -0,0 +1,297 @@ +/* + * Host AP crypt: host-based WEP encryption implementation for Host AP driver + * + * Copyright (c) 2002-2004, Jouni Malinen + * + * 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. See README and COPYING for + * more details. + */ + +//#include +#include +#include +#include +#include +#include +#include +#include + +#include "ieee80211.h" + +#include + #include +#include + +MODULE_AUTHOR("Jouni Malinen"); +MODULE_DESCRIPTION("Host AP crypt: WEP"); +MODULE_LICENSE("GPL"); + +struct prism2_wep_data { + u32 iv; +#define WEP_KEY_LEN 13 + u8 key[WEP_KEY_LEN + 1]; + u8 key_len; + u8 key_idx; + struct crypto_blkcipher *tx_tfm; + struct crypto_blkcipher *rx_tfm; +}; + + +static void * prism2_wep_init(int keyidx) +{ + struct prism2_wep_data *priv; + + priv = kmalloc(sizeof(*priv), GFP_ATOMIC); + if (priv == NULL) + goto fail; + memset(priv, 0, sizeof(*priv)); + priv->key_idx = keyidx; + + priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(priv->tx_tfm)) { + printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " + "crypto API arc4\n"); + priv->tx_tfm = NULL; + goto fail; + } + priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(priv->rx_tfm)) { + printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " + "crypto API arc4\n"); + priv->rx_tfm = NULL; + goto fail; + } + + /* start WEP IV from a random value */ + get_random_bytes(&priv->iv, 4); + + return priv; + +fail: + if (priv) { + if (priv->tx_tfm) + crypto_free_blkcipher(priv->tx_tfm); + if (priv->rx_tfm) + crypto_free_blkcipher(priv->rx_tfm); + kfree(priv); + } + + return NULL; +} + + +static void prism2_wep_deinit(void *priv) +{ + struct prism2_wep_data *_priv = priv; + + if (_priv) { + if (_priv->tx_tfm) + crypto_free_blkcipher(_priv->tx_tfm); + if (_priv->rx_tfm) + crypto_free_blkcipher(_priv->rx_tfm); + } + kfree(priv); +} + +/* Perform WEP encryption on given skb that has at least 4 bytes of headroom + * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted, + * so the payload length increases with 8 bytes. + * + * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) + */ +static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) +{ + struct prism2_wep_data *wep = priv; + u32 klen, len; + u8 key[WEP_KEY_LEN + 3]; + u8 *pos; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + struct blkcipher_desc desc = {.tfm = wep->tx_tfm}; + u32 crc; + u8 *icv; + struct scatterlist sg; + if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 || + skb->len < hdr_len) + return -1; + + len = skb->len - hdr_len; + pos = skb_push(skb, 4); + memmove(pos, pos + 4, hdr_len); + pos += hdr_len; + + klen = 3 + wep->key_len; + + wep->iv++; + + /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key + * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N) + * can be used to speedup attacks, so avoid using them. */ + if ((wep->iv & 0xff00) == 0xff00) { + u8 B = (wep->iv >> 16) & 0xff; + if (B >= 3 && B < klen) + wep->iv += 0x0100; + } + + /* Prepend 24-bit IV to RC4 key and TX frame */ + *pos++ = key[0] = (wep->iv >> 16) & 0xff; + *pos++ = key[1] = (wep->iv >> 8) & 0xff; + *pos++ = key[2] = wep->iv & 0xff; + *pos++ = wep->key_idx << 6; + + /* Copy rest of the WEP key (the secret part) */ + memcpy(key + 3, wep->key, wep->key_len); + + if (!tcb_desc->bHwSec) + { + + /* Append little-endian CRC32 and encrypt it to produce ICV */ + crc = ~crc32_le(~0, pos, len); + icv = skb_put(skb, 4); + icv[0] = crc; + icv[1] = crc >> 8; + icv[2] = crc >> 16; + icv[3] = crc >> 24; + + crypto_blkcipher_setkey(wep->tx_tfm, key, klen); + sg_init_one(&sg, pos, len+4); + + return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + } + + return 0; +} + + +/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of + * the frame: IV (4 bytes), encrypted payload (including SNAP header), + * ICV (4 bytes). len includes both IV and ICV. + * + * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on + * failure. If frame is OK, IV and ICV will be removed. + */ +static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) +{ + struct prism2_wep_data *wep = priv; + u32 klen, plen; + u8 key[WEP_KEY_LEN + 3]; + u8 keyidx, *pos; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + struct blkcipher_desc desc = {.tfm = wep->rx_tfm}; + u32 crc; + u8 icv[4]; + struct scatterlist sg; + if (skb->len < hdr_len + 8) + return -1; + + pos = skb->data + hdr_len; + key[0] = *pos++; + key[1] = *pos++; + key[2] = *pos++; + keyidx = *pos++ >> 6; + if (keyidx != wep->key_idx) + return -1; + + klen = 3 + wep->key_len; + + /* Copy rest of the WEP key (the secret part) */ + memcpy(key + 3, wep->key, wep->key_len); + + /* Apply RC4 to data and compute CRC32 over decrypted data */ + plen = skb->len - hdr_len - 8; + + if (!tcb_desc->bHwSec) + { + crypto_blkcipher_setkey(wep->rx_tfm, key, klen); + sg_init_one(&sg, pos, plen+4); + + if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) + return -7; + + crc = ~crc32_le(~0, pos, plen); + icv[0] = crc; + icv[1] = crc >> 8; + icv[2] = crc >> 16; + icv[3] = crc >> 24; + if (memcmp(icv, pos + plen, 4) != 0) { + /* ICV mismatch - drop frame */ + return -2; + } + } + /* Remove IV and ICV */ + memmove(skb->data + 4, skb->data, hdr_len); + skb_pull(skb, 4); + skb_trim(skb, skb->len - 4); + + return 0; +} + + +static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv) +{ + struct prism2_wep_data *wep = priv; + + if (len < 0 || len > WEP_KEY_LEN) + return -1; + + memcpy(wep->key, key, len); + wep->key_len = len; + + return 0; +} + + +static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv) +{ + struct prism2_wep_data *wep = priv; + + if (len < wep->key_len) + return -1; + + memcpy(key, wep->key, wep->key_len); + + return wep->key_len; +} + + +static char * prism2_wep_print_stats(char *p, void *priv) +{ + struct prism2_wep_data *wep = priv; + p += sprintf(p, "key[%d] alg=WEP len=%d\n", + wep->key_idx, wep->key_len); + return p; +} + + +static struct ieee80211_crypto_ops ieee80211_crypt_wep = { + .name = "WEP", + .init = prism2_wep_init, + .deinit = prism2_wep_deinit, + .encrypt_mpdu = prism2_wep_encrypt, + .decrypt_mpdu = prism2_wep_decrypt, + .encrypt_msdu = NULL, + .decrypt_msdu = NULL, + .set_key = prism2_wep_set_key, + .get_key = prism2_wep_get_key, + .print_stats = prism2_wep_print_stats, + .extra_prefix_len = 4, /* IV */ + .extra_postfix_len = 4, /* ICV */ + .owner = THIS_MODULE, +}; + +int __init ieee80211_crypto_wep_init(void) +{ + return ieee80211_register_crypto_ops(&ieee80211_crypt_wep); +} + +void __exit ieee80211_crypto_wep_exit(void) +{ + ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep); +} + +void ieee80211_wep_null(void) +{ +// printk("============>%s()\n", __FUNCTION__); + return; +} diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c new file mode 100644 index 0000000000000000000000000000000000000000..7a8690f449b4eec90bb27d11243a9ad4e3bcfcde --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c @@ -0,0 +1,324 @@ +/******************************************************************************* + + Copyright(c) 2004 Intel Corporation. All rights reserved. + + Portions of this file are based on the WEP enablement code provided by the + Host AP project hostap-drivers v0.1.3 + Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen + + Copyright (c) 2002-2003, Jouni Malinen + + 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 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + James P. Ketrenos + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ieee80211.h" + +MODULE_DESCRIPTION("802.11 data/management/control stack"); +MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation "); +MODULE_LICENSE("GPL"); + +#define DRV_NAME "ieee80211" + +static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee) +{ + if (ieee->networks) + return 0; + + ieee->networks = kmalloc( + MAX_NETWORK_COUNT * sizeof(struct ieee80211_network), + GFP_KERNEL); + if (!ieee->networks) { + printk(KERN_WARNING "%s: Out of memory allocating beacons\n", + ieee->dev->name); + return -ENOMEM; + } + + memset(ieee->networks, 0, + MAX_NETWORK_COUNT * sizeof(struct ieee80211_network)); + + return 0; +} + +static inline void ieee80211_networks_free(struct ieee80211_device *ieee) +{ + if (!ieee->networks) + return; + kfree(ieee->networks); + ieee->networks = NULL; +} + +static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee) +{ + int i; + + INIT_LIST_HEAD(&ieee->network_free_list); + INIT_LIST_HEAD(&ieee->network_list); + for (i = 0; i < MAX_NETWORK_COUNT; i++) + list_add_tail(&ieee->networks[i].list, &ieee->network_free_list); +} + + +struct net_device *alloc_ieee80211(int sizeof_priv) +{ + struct ieee80211_device *ieee; + struct net_device *dev; + int i,err; + + IEEE80211_DEBUG_INFO("Initializing...\n"); + + dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv); + if (!dev) { + IEEE80211_ERROR("Unable to network device.\n"); + goto failed; + } + + ieee = netdev_priv(dev); + memset(ieee, 0, sizeof(struct ieee80211_device)+sizeof_priv); + ieee->dev = dev; + + err = ieee80211_networks_allocate(ieee); + if (err) { + IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", + err); + goto failed; + } + ieee80211_networks_initialize(ieee); + + + /* Default fragmentation threshold is maximum payload size */ + ieee->fts = DEFAULT_FTS; + ieee->scan_age = DEFAULT_MAX_SCAN_AGE; + ieee->open_wep = 1; + + /* Default to enabling full open WEP with host based encrypt/decrypt */ + ieee->host_encrypt = 1; + ieee->host_decrypt = 1; + ieee->ieee802_1x = 1; /* Default to supporting 802.1x */ + + INIT_LIST_HEAD(&ieee->crypt_deinit_list); + init_timer(&ieee->crypt_deinit_timer); + ieee->crypt_deinit_timer.data = (unsigned long)ieee; + ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler; + + spin_lock_init(&ieee->lock); + spin_lock_init(&ieee->wpax_suitlist_lock); + spin_lock_init(&ieee->bw_spinlock); + spin_lock_init(&ieee->reorder_spinlock); + //added by WB + atomic_set(&(ieee->atm_chnlop), 0); + atomic_set(&(ieee->atm_swbw), 0); + + ieee->wpax_type_set = 0; + ieee->wpa_enabled = 0; + ieee->tkip_countermeasures = 0; + ieee->drop_unencrypted = 0; + ieee->privacy_invoked = 0; + ieee->ieee802_1x = 1; + ieee->raw_tx = 0; + //ieee->hwsec_support = 1; //defalt support hw security. //use module_param instead. + ieee->hwsec_active = 0; //disable hwsec, switch it on when necessary. + + ieee80211_softmac_init(ieee); + + ieee->pHTInfo = (RT_HIGH_THROUGHPUT*)kzalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL); + if (ieee->pHTInfo == NULL) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for HTInfo\n"); + return NULL; + } + HTUpdateDefaultSetting(ieee); + HTInitializeHTInfo(ieee); //may move to other place. + TSInitialize(ieee); + + for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) + INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]); + + for (i = 0; i < 17; i++) { + ieee->last_rxseq_num[i] = -1; + ieee->last_rxfrag_num[i] = -1; + ieee->last_packet_time[i] = 0; + } + +//These function were added to load crypte module autoly + ieee80211_tkip_null(); + ieee80211_wep_null(); + ieee80211_ccmp_null(); + + return dev; + + failed: + if (dev) + free_netdev(dev); + + return NULL; +} + + +void free_ieee80211(struct net_device *dev) +{ + struct ieee80211_device *ieee = netdev_priv(dev); + int i; + //struct list_head *p, *q; +// del_timer_sync(&ieee->SwBwTimer); + if (ieee->pHTInfo != NULL) + { + kfree(ieee->pHTInfo); + ieee->pHTInfo = NULL; + } + RemoveAllTS(ieee); + ieee80211_softmac_free(ieee); + del_timer_sync(&ieee->crypt_deinit_timer); + ieee80211_crypt_deinit_entries(ieee, 1); + + for (i = 0; i < WEP_KEYS; i++) { + struct ieee80211_crypt_data *crypt = ieee->crypt[i]; + if (crypt) { + if (crypt->ops) + crypt->ops->deinit(crypt->priv); + kfree(crypt); + ieee->crypt[i] = NULL; + } + } + + ieee80211_networks_free(ieee); + free_netdev(dev); +} + +#ifdef CONFIG_IEEE80211_DEBUG + +u32 ieee80211_debug_level = 0; +static int debug = \ + // IEEE80211_DL_INFO | + // IEEE80211_DL_WX | + // IEEE80211_DL_SCAN | + // IEEE80211_DL_STATE | + // IEEE80211_DL_MGMT | + // IEEE80211_DL_FRAG | + // IEEE80211_DL_EAP | + // IEEE80211_DL_DROP | + // IEEE80211_DL_TX | + // IEEE80211_DL_RX | + //IEEE80211_DL_QOS | + // IEEE80211_DL_HT | + // IEEE80211_DL_TS | +// IEEE80211_DL_BA | + // IEEE80211_DL_REORDER| +// IEEE80211_DL_TRACE | + //IEEE80211_DL_DATA | + IEEE80211_DL_ERR //awayls open this flags to show error out + ; +struct proc_dir_entry *ieee80211_proc = NULL; + +static int show_debug_level(char *page, char **start, off_t offset, + int count, int *eof, void *data) +{ + return snprintf(page, count, "0x%08X\n", ieee80211_debug_level); +} + +static int store_debug_level(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char buf[] = "0x00000000"; + unsigned long len = min(sizeof(buf) - 1, count); + char *p = (char *)buf; + unsigned long val; + + if (copy_from_user(buf, buffer, len)) + return count; + buf[len] = 0; + if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { + p++; + if (p[0] == 'x' || p[0] == 'X') + p++; + val = simple_strtoul(p, &p, 16); + } else + val = simple_strtoul(p, &p, 10); + if (p == buf) + printk(KERN_INFO DRV_NAME + ": %s is not in hex or decimal form.\n", buf); + else + ieee80211_debug_level = val; + + return strnlen(buf, count); +} + +int __init ieee80211_debug_init(void) +{ + struct proc_dir_entry *e; + + ieee80211_debug_level = debug; + + ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net); + if (ieee80211_proc == NULL) { + IEEE80211_ERROR("Unable to create " DRV_NAME + " proc directory\n"); + return -EIO; + } + e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR, + ieee80211_proc); + if (!e) { + remove_proc_entry(DRV_NAME, init_net.proc_net); + ieee80211_proc = NULL; + return -EIO; + } + e->read_proc = show_debug_level; + e->write_proc = store_debug_level; + e->data = NULL; + + return 0; +} + +void __exit ieee80211_debug_exit(void) +{ + if (ieee80211_proc) { + remove_proc_entry("debug_level", ieee80211_proc); + remove_proc_entry(DRV_NAME, init_net.proc_net); + ieee80211_proc = NULL; + } +} + +#include +module_param(debug, int, 0444); +MODULE_PARM_DESC(debug, "debug output mask"); +#endif diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c new file mode 100644 index 0000000000000000000000000000000000000000..0e003c5bb0004a99e33f6618b89a73db644881ad --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -0,0 +1,2668 @@ +/* + * Original code based Host AP (software wireless LAN access point) driver + * for Intersil Prism2/2.5/3 - hostap.o module, common routines + * + * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen + * + * Copyright (c) 2002-2003, Jouni Malinen + * Copyright (c) 2004, Intel Corporation + * + * 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. See README and COPYING for + * more details. + ****************************************************************************** + + Few modifications for Realtek's Wi-Fi drivers by + Andrea Merello + + A special thanks goes to Realtek for their support ! + +******************************************************************************/ + + +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ieee80211.h" +#ifdef ENABLE_DOT11D +#include "dot11d.h" +#endif +static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee, + struct sk_buff *skb, + struct ieee80211_rx_stats *rx_stats) +{ + struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *)skb->data; + u16 fc = le16_to_cpu(hdr->frame_ctl); + + skb->dev = ieee->dev; + skb_reset_mac_header(skb); + + skb_pull(skb, ieee80211_get_hdrlen(fc)); + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = __constant_htons(ETH_P_80211_RAW); + memset(skb->cb, 0, sizeof(skb->cb)); + netif_rx(skb); +} + + +/* Called only as a tasklet (software IRQ) */ +static struct ieee80211_frag_entry * +ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq, + unsigned int frag, u8 tid,u8 *src, u8 *dst) +{ + struct ieee80211_frag_entry *entry; + int i; + + for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) { + entry = &ieee->frag_cache[tid][i]; + if (entry->skb != NULL && + time_after(jiffies, entry->first_frag_time + 2 * HZ)) { + IEEE80211_DEBUG_FRAG( + "expiring fragment cache entry " + "seq=%u last_frag=%u\n", + entry->seq, entry->last_frag); + dev_kfree_skb_any(entry->skb); + entry->skb = NULL; + } + + if (entry->skb != NULL && entry->seq == seq && + (entry->last_frag + 1 == frag || frag == -1) && + memcmp(entry->src_addr, src, ETH_ALEN) == 0 && + memcmp(entry->dst_addr, dst, ETH_ALEN) == 0) + return entry; + } + + return NULL; +} + +/* Called only as a tasklet (software IRQ) */ +static struct sk_buff * +ieee80211_frag_cache_get(struct ieee80211_device *ieee, + struct ieee80211_hdr_4addr *hdr) +{ + struct sk_buff *skb = NULL; + u16 fc = le16_to_cpu(hdr->frame_ctl); + u16 sc = le16_to_cpu(hdr->seq_ctl); + unsigned int frag = WLAN_GET_SEQ_FRAG(sc); + unsigned int seq = WLAN_GET_SEQ_SEQ(sc); + struct ieee80211_frag_entry *entry; + struct ieee80211_hdr_3addrqos *hdr_3addrqos; + struct ieee80211_hdr_4addrqos *hdr_4addrqos; + u8 tid; + + if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) { + hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr; + tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid ++; + } else if (IEEE80211_QOS_HAS_SEQ(fc)) { + hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr; + tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid ++; + } else { + tid = 0; + } + + if (frag == 0) { + /* Reserve enough space to fit maximum frame length */ + skb = dev_alloc_skb(ieee->dev->mtu + + sizeof(struct ieee80211_hdr_4addr) + + 8 /* LLC */ + + 2 /* alignment */ + + 8 /* WEP */ + + ETH_ALEN /* WDS */ + + (IEEE80211_QOS_HAS_SEQ(fc)?2:0) /* QOS Control */); + if (skb == NULL) + return NULL; + + entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]]; + ieee->frag_next_idx[tid]++; + if (ieee->frag_next_idx[tid] >= IEEE80211_FRAG_CACHE_LEN) + ieee->frag_next_idx[tid] = 0; + + if (entry->skb != NULL) + dev_kfree_skb_any(entry->skb); + + entry->first_frag_time = jiffies; + entry->seq = seq; + entry->last_frag = frag; + entry->skb = skb; + memcpy(entry->src_addr, hdr->addr2, ETH_ALEN); + memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN); + } else { + /* received a fragment of a frame for which the head fragment + * should have already been received */ + entry = ieee80211_frag_cache_find(ieee, seq, frag, tid,hdr->addr2, + hdr->addr1); + if (entry != NULL) { + entry->last_frag = frag; + skb = entry->skb; + } + } + + return skb; +} + + +/* Called only as a tasklet (software IRQ) */ +static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee, + struct ieee80211_hdr_4addr *hdr) +{ + u16 fc = le16_to_cpu(hdr->frame_ctl); + u16 sc = le16_to_cpu(hdr->seq_ctl); + unsigned int seq = WLAN_GET_SEQ_SEQ(sc); + struct ieee80211_frag_entry *entry; + struct ieee80211_hdr_3addrqos *hdr_3addrqos; + struct ieee80211_hdr_4addrqos *hdr_4addrqos; + u8 tid; + + if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) { + hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr; + tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid ++; + } else if (IEEE80211_QOS_HAS_SEQ(fc)) { + hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr; + tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid ++; + } else { + tid = 0; + } + + entry = ieee80211_frag_cache_find(ieee, seq, -1, tid,hdr->addr2, + hdr->addr1); + + if (entry == NULL) { + IEEE80211_DEBUG_FRAG( + "could not invalidate fragment cache " + "entry (seq=%u)\n", seq); + return -1; + } + + entry->skb = NULL; + return 0; +} + + + +/* ieee80211_rx_frame_mgtmt + * + * Responsible for handling management control frames + * + * Called by ieee80211_rx */ +static inline int +ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, + struct ieee80211_rx_stats *rx_stats, u16 type, + u16 stype) +{ + /* On the struct stats definition there is written that + * this is not mandatory.... but seems that the probe + * response parser uses it + */ + struct ieee80211_hdr_3addr * hdr = (struct ieee80211_hdr_3addr *)skb->data; + + rx_stats->len = skb->len; + ieee80211_rx_mgt(ieee,(struct ieee80211_hdr_4addr *)skb->data,rx_stats); + //if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))) + if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN)))//use ADDR1 to perform address matching for Management frames + { + dev_kfree_skb_any(skb); + return 0; + } + + ieee80211_rx_frame_softmac(ieee, skb, rx_stats, type, stype); + + dev_kfree_skb_any(skb); + + return 0; + + #ifdef NOT_YET + if (ieee->iw_mode == IW_MODE_MASTER) { + printk(KERN_DEBUG "%s: Master mode not yet suppported.\n", + ieee->dev->name); + return 0; +/* + hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr_4addr *) + skb->data);*/ + } + + if (ieee->hostapd && type == IEEE80211_TYPE_MGMT) { + if (stype == WLAN_FC_STYPE_BEACON && + ieee->iw_mode == IW_MODE_MASTER) { + struct sk_buff *skb2; + /* Process beacon frames also in kernel driver to + * update STA(AP) table statistics */ + skb2 = skb_clone(skb, GFP_ATOMIC); + if (skb2) + hostap_rx(skb2->dev, skb2, rx_stats); + } + + /* send management frames to the user space daemon for + * processing */ + ieee->apdevstats.rx_packets++; + ieee->apdevstats.rx_bytes += skb->len; + prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT); + return 0; + } + + if (ieee->iw_mode == IW_MODE_MASTER) { + if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) { + printk(KERN_DEBUG "%s: unknown management frame " + "(type=0x%02x, stype=0x%02x) dropped\n", + skb->dev->name, type, stype); + return -1; + } + + hostap_rx(skb->dev, skb, rx_stats); + return 0; + } + + printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame " + "received in non-Host AP mode\n", skb->dev->name); + return -1; + #endif +} + + + +/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ +/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ +static unsigned char rfc1042_header[] = +{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; +/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ +static unsigned char bridge_tunnel_header[] = +{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; +/* No encapsulation header if EtherType < 0x600 (=length) */ + +/* Called by ieee80211_rx_frame_decrypt */ +static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee, + struct sk_buff *skb, size_t hdrlen) +{ + struct net_device *dev = ieee->dev; + u16 fc, ethertype; + struct ieee80211_hdr_4addr *hdr; + u8 *pos; + + if (skb->len < 24) + return 0; + + hdr = (struct ieee80211_hdr_4addr *) skb->data; + fc = le16_to_cpu(hdr->frame_ctl); + + /* check that the frame is unicast frame to us */ + if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == + IEEE80211_FCTL_TODS && + memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 && + memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) { + /* ToDS frame with own addr BSSID and DA */ + } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == + IEEE80211_FCTL_FROMDS && + memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) { + /* FromDS frame with own addr as DA */ + } else + return 0; + + if (skb->len < 24 + 8) + return 0; + + /* check for port access entity Ethernet type */ +// pos = skb->data + 24; + pos = skb->data + hdrlen; + ethertype = (pos[6] << 8) | pos[7]; + if (ethertype == ETH_P_PAE) + return 1; + + return 0; +} + +/* Called only as a tasklet (software IRQ), by ieee80211_rx */ +static inline int +ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb, + struct ieee80211_crypt_data *crypt) +{ + struct ieee80211_hdr_4addr *hdr; + int res, hdrlen; + + if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL) + return 0; + if (ieee->hwsec_active) + { + cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE); + tcb_desc->bHwSec = 1; + } + hdr = (struct ieee80211_hdr_4addr *) skb->data; + hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); + +#ifdef CONFIG_IEEE80211_CRYPT_TKIP + if (ieee->tkip_countermeasures && + strcmp(crypt->ops->name, "TKIP") == 0) { + if (net_ratelimit()) { + printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " + "received packet from " MAC_FMT "\n", + ieee->dev->name, MAC_ARG(hdr->addr2)); + } + return -1; + } +#endif + + atomic_inc(&crypt->refcnt); + res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv); + atomic_dec(&crypt->refcnt); + if (res < 0) { + IEEE80211_DEBUG_DROP( + "decryption failed (SA=" MAC_FMT + ") res=%d\n", MAC_ARG(hdr->addr2), res); + if (res == -2) + IEEE80211_DEBUG_DROP("Decryption failed ICV " + "mismatch (key %d)\n", + skb->data[hdrlen + 3] >> 6); + ieee->ieee_stats.rx_discards_undecryptable++; + return -1; + } + + return res; +} + + +/* Called only as a tasklet (software IRQ), by ieee80211_rx */ +static inline int +ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *skb, + int keyidx, struct ieee80211_crypt_data *crypt) +{ + struct ieee80211_hdr_4addr *hdr; + int res, hdrlen; + + if (crypt == NULL || crypt->ops->decrypt_msdu == NULL) + return 0; + if (ieee->hwsec_active) + { + cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE); + tcb_desc->bHwSec = 1; + } + + hdr = (struct ieee80211_hdr_4addr *) skb->data; + hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); + + atomic_inc(&crypt->refcnt); + res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv); + atomic_dec(&crypt->refcnt); + if (res < 0) { + printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed" + " (SA=" MAC_FMT " keyidx=%d)\n", + ieee->dev->name, MAC_ARG(hdr->addr2), keyidx); + return -1; + } + + return 0; +} + + +/* this function is stolen from ipw2200 driver*/ +#define IEEE_PACKET_RETRY_TIME (5*HZ) +static int is_duplicate_packet(struct ieee80211_device *ieee, + struct ieee80211_hdr_4addr *header) +{ + u16 fc = le16_to_cpu(header->frame_ctl); + u16 sc = le16_to_cpu(header->seq_ctl); + u16 seq = WLAN_GET_SEQ_SEQ(sc); + u16 frag = WLAN_GET_SEQ_FRAG(sc); + u16 *last_seq, *last_frag; + unsigned long *last_time; + struct ieee80211_hdr_3addrqos *hdr_3addrqos; + struct ieee80211_hdr_4addrqos *hdr_4addrqos; + u8 tid; + + + //TO2DS and QoS + if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) { + hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)header; + tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid ++; + } else if(IEEE80211_QOS_HAS_SEQ(fc)) { //QoS + hdr_3addrqos = (struct ieee80211_hdr_3addrqos*)header; + tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid ++; + } else { // no QoS + tid = 0; + } + + switch (ieee->iw_mode) { + case IW_MODE_ADHOC: + { + struct list_head *p; + struct ieee_ibss_seq *entry = NULL; + u8 *mac = header->addr2; + int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE; + //for (pos = (head)->next; pos != (head); pos = pos->next) + //__list_for_each(p, &ieee->ibss_mac_hash[index]) { + list_for_each(p, &ieee->ibss_mac_hash[index]) { + entry = list_entry(p, struct ieee_ibss_seq, list); + if (!memcmp(entry->mac, mac, ETH_ALEN)) + break; + } + // if (memcmp(entry->mac, mac, ETH_ALEN)){ + if (p == &ieee->ibss_mac_hash[index]) { + entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC); + if (!entry) { + printk(KERN_WARNING "Cannot malloc new mac entry\n"); + return 0; + } + memcpy(entry->mac, mac, ETH_ALEN); + entry->seq_num[tid] = seq; + entry->frag_num[tid] = frag; + entry->packet_time[tid] = jiffies; + list_add(&entry->list, &ieee->ibss_mac_hash[index]); + return 0; + } + last_seq = &entry->seq_num[tid]; + last_frag = &entry->frag_num[tid]; + last_time = &entry->packet_time[tid]; + break; + } + + case IW_MODE_INFRA: + last_seq = &ieee->last_rxseq_num[tid]; + last_frag = &ieee->last_rxfrag_num[tid]; + last_time = &ieee->last_packet_time[tid]; + + break; + default: + return 0; + } + +// if(tid != 0) { +// printk(KERN_WARNING ":)))))))))))%x %x %x, fc(%x)\n", tid, *last_seq, seq, header->frame_ctl); +// } + if ((*last_seq == seq) && + time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) { + if (*last_frag == frag){ + //printk(KERN_WARNING "[1] go drop!\n"); + goto drop; + + } + if (*last_frag + 1 != frag) + /* out-of-order fragment */ + //printk(KERN_WARNING "[2] go drop!\n"); + goto drop; + } else + *last_seq = seq; + + *last_frag = frag; + *last_time = jiffies; + return 0; + +drop: +// BUG_ON(!(fc & IEEE80211_FCTL_RETRY)); +// printk("DUP\n"); + + return 1; +} +bool +AddReorderEntry( + PRX_TS_RECORD pTS, + PRX_REORDER_ENTRY pReorderEntry + ) +{ + struct list_head *pList = &pTS->RxPendingPktList; + while(pList->next != &pTS->RxPendingPktList) + { + if( SN_LESS(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)list_entry(pList->next,RX_REORDER_ENTRY,List))->SeqNum) ) + { + pList = pList->next; + } + else if( SN_EQUAL(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)list_entry(pList->next,RX_REORDER_ENTRY,List))->SeqNum) ) + { + return false; + } + else + { + break; + } + } + pReorderEntry->List.next = pList->next; + pReorderEntry->List.next->prev = &pReorderEntry->List; + pReorderEntry->List.prev = pList; + pList->next = &pReorderEntry->List; + + return true; +} + +void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb** prxbIndicateArray,u8 index) +{ + u8 i = 0 , j=0; + u16 ethertype; +// if(index > 1) +// IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): hahahahhhh, We indicate packet from reorder list, index is %u\n",__FUNCTION__,index); + for(j = 0; jnr_subframes; i++) { + struct sk_buff *sub_skb = prxb->subframes[i]; + + /* convert hdr + possible LLC headers into Ethernet header */ + ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7]; + if (sub_skb->len >= 8 && + ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 && + ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || + memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) { + /* remove RFC1042 or Bridge-Tunnel encapsulation and + * replace EtherType */ + skb_pull(sub_skb, SNAP_SIZE); + memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN); + memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN); + } else { + u16 len; + /* Leave Ethernet header part of hdr and full payload */ + len = htons(sub_skb->len); + memcpy(skb_push(sub_skb, 2), &len, 2); + memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN); + memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN); + } + //stats->rx_packets++; + //stats->rx_bytes += sub_skb->len; + + /* Indicat the packets to upper layer */ + if (sub_skb) { + //printk("0skb_len(%d)\n", skb->len); + sub_skb->protocol = eth_type_trans(sub_skb, ieee->dev); + memset(sub_skb->cb, 0, sizeof(sub_skb->cb)); + sub_skb->dev = ieee->dev; + sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */ + //skb->ip_summed = CHECKSUM_UNNECESSARY; /* 802.11 crc not sufficient */ + ieee->last_rx_ps_time = jiffies; + //printk("1skb_len(%d)\n", skb->len); + netif_rx(sub_skb); + } + } + kfree(prxb); + prxb = NULL; + } +} + + +void RxReorderIndicatePacket( struct ieee80211_device *ieee, + struct ieee80211_rxb* prxb, + PRX_TS_RECORD pTS, + u16 SeqNum) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + PRX_REORDER_ENTRY pReorderEntry = NULL; + struct ieee80211_rxb* prxbIndicateArray[REORDER_WIN_SIZE]; + u8 WinSize = pHTInfo->RxReorderWinSize; + u16 WinEnd = (pTS->RxIndicateSeq + WinSize -1)%4096; + u8 index = 0; + bool bMatchWinStart = false, bPktInBuf = false; + IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): Seq is %d,pTS->RxIndicateSeq is %d, WinSize is %d\n",__FUNCTION__,SeqNum,pTS->RxIndicateSeq,WinSize); + /* Rx Reorder initialize condition.*/ + if(pTS->RxIndicateSeq == 0xffff) { + pTS->RxIndicateSeq = SeqNum; + } + + /* Drop out the packet which SeqNum is smaller than WinStart */ + if(SN_LESS(SeqNum, pTS->RxIndicateSeq)) { + IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packet Drop! IndicateSeq: %d, NewSeq: %d\n", + pTS->RxIndicateSeq, SeqNum); + pHTInfo->RxReorderDropCounter++; + { + int i; + for(i =0; i < prxb->nr_subframes; i++) { + dev_kfree_skb(prxb->subframes[i]); + } + kfree(prxb); + prxb = NULL; + } + return; + } + + /* + * Sliding window manipulation. Conditions includes: + * 1. Incoming SeqNum is equal to WinStart =>Window shift 1 + * 2. Incoming SeqNum is larger than the WinEnd => Window shift N + */ + if(SN_EQUAL(SeqNum, pTS->RxIndicateSeq)) { + pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096; + bMatchWinStart = true; + } else if(SN_LESS(WinEnd, SeqNum)) { + if(SeqNum >= (WinSize - 1)) { + pTS->RxIndicateSeq = SeqNum + 1 -WinSize; + } else { + pTS->RxIndicateSeq = 4095 - (WinSize - (SeqNum +1)) + 1; + } + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum); + } + + /* + * Indication process. + * After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets + * with the SeqNum smaller than latest WinStart and buffer other packets. + */ + /* For Rx Reorder condition: + * 1. All packets with SeqNum smaller than WinStart => Indicate + * 2. All packets with SeqNum larger than or equal to WinStart => Buffer it. + */ + if(bMatchWinStart) { + /* Current packet is going to be indicated.*/ + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n",\ + pTS->RxIndicateSeq, SeqNum); + prxbIndicateArray[0] = prxb; +// printk("========================>%s(): SeqNum is %d\n",__FUNCTION__,SeqNum); + index = 1; + } else { + /* Current packet is going to be inserted into pending list.*/ + //IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): We RX no ordered packed, insert to orderd list\n",__FUNCTION__); + if(!list_empty(&ieee->RxReorder_Unused_List)) { + pReorderEntry = (PRX_REORDER_ENTRY)list_entry(ieee->RxReorder_Unused_List.next,RX_REORDER_ENTRY,List); + list_del_init(&pReorderEntry->List); + + /* Make a reorder entry and insert into a the packet list.*/ + pReorderEntry->SeqNum = SeqNum; + pReorderEntry->prxb = prxb; + // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pREorderEntry->SeqNum is %d\n",__FUNCTION__,pReorderEntry->SeqNum); + + if(!AddReorderEntry(pTS, pReorderEntry)) { + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", + __FUNCTION__, pTS->RxIndicateSeq, SeqNum); + list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List); + { + int i; + for(i =0; i < prxb->nr_subframes; i++) { + dev_kfree_skb(prxb->subframes[i]); + } + kfree(prxb); + prxb = NULL; + } + } else { + IEEE80211_DEBUG(IEEE80211_DL_REORDER, + "Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum); + } + } + else { + /* + * Packets are dropped if there is not enough reorder entries. + * This part shall be modified!! We can just indicate all the + * packets in buffer and get reorder entries. + */ + IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n"); + { + int i; + for(i =0; i < prxb->nr_subframes; i++) { + dev_kfree_skb(prxb->subframes[i]); + } + kfree(prxb); + prxb = NULL; + } + } + } + + /* Check if there is any packet need indicate.*/ + while(!list_empty(&pTS->RxPendingPktList)) { + IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): start RREORDER indicate\n",__FUNCTION__); + pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List); + if( SN_LESS(pReorderEntry->SeqNum, pTS->RxIndicateSeq) || + SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq)) + { + /* This protect buffer from overflow. */ + if(index >= REORDER_WIN_SIZE) { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!! \n"); + bPktInBuf = true; + break; + } + + list_del_init(&pReorderEntry->List); + + if(SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq)) + pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096; + + IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packets indication!! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum); + prxbIndicateArray[index] = pReorderEntry->prxb; + // printk("========================>%s(): pReorderEntry->SeqNum is %d\n",__FUNCTION__,pReorderEntry->SeqNum); + index++; + + list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List); + } else { + bPktInBuf = true; + break; + } + } + + /* Handling pending timer. Set this timer to prevent from long time Rx buffering.*/ + if(index>0) { + // Cancel previous pending timer. + // del_timer_sync(&pTS->RxPktPendingTimer); + pTS->RxTimeoutIndicateSeq = 0xffff; + + // Indicate packets + if(index>REORDER_WIN_SIZE){ + IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n"); + return; + } + ieee80211_indicate_packets(ieee, prxbIndicateArray, index); + } + + if(bPktInBuf && pTS->RxTimeoutIndicateSeq==0xffff) { + // Set new pending timer. + IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): SET rx timeout timer\n", __FUNCTION__); + pTS->RxTimeoutIndicateSeq = pTS->RxIndicateSeq; + if(timer_pending(&pTS->RxPktPendingTimer)) + del_timer_sync(&pTS->RxPktPendingTimer); + pTS->RxPktPendingTimer.expires = jiffies + MSECS(pHTInfo->RxReorderPendingTime); + add_timer(&pTS->RxPktPendingTimer); + } +} + +u8 parse_subframe(struct sk_buff *skb, + struct ieee80211_rx_stats *rx_stats, + struct ieee80211_rxb *rxb,u8* src,u8* dst) +{ + struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr* )skb->data; + u16 fc = le16_to_cpu(hdr->frame_ctl); + + u16 LLCOffset= sizeof(struct ieee80211_hdr_3addr); + u16 ChkLength; + bool bIsAggregateFrame = false; + u16 nSubframe_Length; + u8 nPadding_Length = 0; + u16 SeqNum=0; + + struct sk_buff *sub_skb; + u8 *data_ptr; + /* just for debug purpose */ + SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl)); + + if((IEEE80211_QOS_HAS_SEQ(fc))&&\ + (((frameqos *)(skb->data + IEEE80211_3ADDR_LEN))->field.reserved)) { + bIsAggregateFrame = true; + } + + if(IEEE80211_QOS_HAS_SEQ(fc)) { + LLCOffset += 2; + } + + if(rx_stats->bContainHTC) { + LLCOffset += sHTCLng; + } + //printk("ChkLength = %d\n", LLCOffset); + // Null packet, don't indicate it to upper layer + ChkLength = LLCOffset;/* + (Frame_WEP(frame)!=0 ?Adapter->MgntInfo.SecurityInfo.EncryptionHeadOverhead:0);*/ + + if( skb->len <= ChkLength ) { + return 0; + } + + skb_pull(skb, LLCOffset); + + if(!bIsAggregateFrame) { + rxb->nr_subframes = 1; +#ifdef JOHN_NOCPY + rxb->subframes[0] = skb; +#else + rxb->subframes[0] = skb_copy(skb, GFP_ATOMIC); +#endif + + memcpy(rxb->src,src,ETH_ALEN); + memcpy(rxb->dst,dst,ETH_ALEN); + //IEEE80211_DEBUG_DATA(IEEE80211_DL_RX,skb->data,skb->len); + return 1; + } else { + rxb->nr_subframes = 0; + memcpy(rxb->src,src,ETH_ALEN); + memcpy(rxb->dst,dst,ETH_ALEN); + while(skb->len > ETHERNET_HEADER_SIZE) { + /* Offset 12 denote 2 mac address */ + nSubframe_Length = *((u16*)(skb->data + 12)); + //==m==>change the length order + nSubframe_Length = (nSubframe_Length>>8) + (nSubframe_Length<<8); + + if(skb->len<(ETHERNET_HEADER_SIZE + nSubframe_Length)) { + printk("%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\ + __FUNCTION__,rxb->nr_subframes); + printk("%s: A-MSDU parse error!! Subframe Length: %d\n",__FUNCTION__, nSubframe_Length); + printk("nRemain_Length is %d and nSubframe_Length is : %d\n",skb->len,nSubframe_Length); + printk("The Packet SeqNum is %d\n",SeqNum); + return 0; + } + + /* move the data point to data content */ + skb_pull(skb, ETHERNET_HEADER_SIZE); + +#ifdef JOHN_NOCPY + sub_skb = skb_clone(skb, GFP_ATOMIC); + sub_skb->len = nSubframe_Length; + sub_skb->tail = sub_skb->data + nSubframe_Length; +#else + /* Allocate new skb for releasing to upper layer */ + sub_skb = dev_alloc_skb(nSubframe_Length + 12); + skb_reserve(sub_skb, 12); + data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length); + memcpy(data_ptr,skb->data,nSubframe_Length); +#endif + rxb->subframes[rxb->nr_subframes++] = sub_skb; + if(rxb->nr_subframes >= MAX_SUBFRAME_COUNT) { + IEEE80211_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n"); + break; + } + skb_pull(skb,nSubframe_Length); + + if(skb->len != 0) { + nPadding_Length = 4 - ((nSubframe_Length + ETHERNET_HEADER_SIZE) % 4); + if(nPadding_Length == 4) { + nPadding_Length = 0; + } + + if(skb->len < nPadding_Length) { + return 0; + } + + skb_pull(skb,nPadding_Length); + } + } +#ifdef JOHN_NOCPY + dev_kfree_skb(skb); +#endif + //{just for debug added by david + //printk("AMSDU::rxb->nr_subframes = %d\n",rxb->nr_subframes); + //} + return rxb->nr_subframes; + } +} + +/* All received frames are sent to this function. @skb contains the frame in + * IEEE 802.11 format, i.e., in the format it was sent over air. + * This function is called only as a tasklet (software IRQ). */ +int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, + struct ieee80211_rx_stats *rx_stats) +{ + struct net_device *dev = ieee->dev; + struct ieee80211_hdr_4addr *hdr; + //struct ieee80211_hdr_3addrqos *hdr; + + size_t hdrlen; + u16 fc, type, stype, sc; + struct net_device_stats *stats; + unsigned int frag; + u8 *payload; + u16 ethertype; + //added by amy for reorder + u8 TID = 0; + u16 SeqNum = 0; + PRX_TS_RECORD pTS = NULL; + //bool bIsAggregateFrame = false; + //added by amy for reorder +#ifdef NOT_YET + struct net_device *wds = NULL; + struct sk_buff *skb2 = NULL; + struct net_device *wds = NULL; + int frame_authorized = 0; + int from_assoc_ap = 0; + void *sta = NULL; +#endif +// u16 qos_ctl = 0; + u8 dst[ETH_ALEN]; + u8 src[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + struct ieee80211_crypt_data *crypt = NULL; + int keyidx = 0; + + int i; + struct ieee80211_rxb* rxb = NULL; + // cheat the the hdr type + hdr = (struct ieee80211_hdr_4addr *)skb->data; + stats = &ieee->stats; + + if (skb->len < 10) { + printk(KERN_INFO "%s: SKB length < 10\n", + dev->name); + goto rx_dropped; + } + + fc = le16_to_cpu(hdr->frame_ctl); + type = WLAN_FC_GET_TYPE(fc); + stype = WLAN_FC_GET_STYPE(fc); + sc = le16_to_cpu(hdr->seq_ctl); + + frag = WLAN_GET_SEQ_FRAG(sc); + hdrlen = ieee80211_get_hdrlen(fc); + + if(HTCCheck(ieee, skb->data)) + { + if(net_ratelimit()) + printk("find HTCControl\n"); + hdrlen += 4; + rx_stats->bContainHTC = 1; + } + + //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len); +#ifdef NOT_YET +#if WIRELESS_EXT > 15 + /* Put this code here so that we avoid duplicating it in all + * Rx paths. - Jean II */ +#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ + /* If spy monitoring on */ + if (iface->spy_data.spy_number > 0) { + struct iw_quality wstats; + wstats.level = rx_stats->rssi; + wstats.noise = rx_stats->noise; + wstats.updated = 6; /* No qual value */ + /* Update spy records */ + wireless_spy_update(dev, hdr->addr2, &wstats); + } +#endif /* IW_WIRELESS_SPY */ +#endif /* WIRELESS_EXT > 15 */ + hostap_update_rx_stats(local->ap, hdr, rx_stats); +#endif + +#if WIRELESS_EXT > 15 + if (ieee->iw_mode == IW_MODE_MONITOR) { + ieee80211_monitor_rx(ieee, skb, rx_stats); + stats->rx_packets++; + stats->rx_bytes += skb->len; + return 1; + } +#endif + if (ieee->host_decrypt) { + int idx = 0; + if (skb->len >= hdrlen + 3) + idx = skb->data[hdrlen + 3] >> 6; + crypt = ieee->crypt[idx]; +#ifdef NOT_YET + sta = NULL; + + /* Use station specific key to override default keys if the + * receiver address is a unicast address ("individual RA"). If + * bcrx_sta_key parameter is set, station specific key is used + * even with broad/multicast targets (this is against IEEE + * 802.11, but makes it easier to use different keys with + * stations that do not support WEP key mapping). */ + + if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key) + (void) hostap_handle_sta_crypto(local, hdr, &crypt, + &sta); +#endif + + /* allow NULL decrypt to indicate an station specific override + * for default encryption */ + if (crypt && (crypt->ops == NULL || + crypt->ops->decrypt_mpdu == NULL)) + crypt = NULL; + + if (!crypt && (fc & IEEE80211_FCTL_WEP)) { + /* This seems to be triggered by some (multicast?) + * frames from other than current BSS, so just drop the + * frames silently instead of filling system log with + * these reports. */ + IEEE80211_DEBUG_DROP("Decryption failed (not set)" + " (SA=" MAC_FMT ")\n", + MAC_ARG(hdr->addr2)); + ieee->ieee_stats.rx_discards_undecryptable++; + goto rx_dropped; + } + } + + if (skb->len < IEEE80211_DATA_HDR3_LEN) + goto rx_dropped; + + // if QoS enabled, should check the sequence for each of the AC + if( (ieee->pHTInfo->bCurRxReorderEnable == false) || !ieee->current_network.qos_data.active|| !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)){ + if (is_duplicate_packet(ieee, hdr)) + goto rx_dropped; + + } + else + { + PRX_TS_RECORD pRxTS = NULL; + //IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): QOS ENABLE AND RECEIVE QOS DATA , we will get Ts, tid:%d\n",__FUNCTION__, tid); + if(GetTs( + ieee, + (PTS_COMMON_INFO*) &pRxTS, + hdr->addr2, + (u8)Frame_QoSTID((u8*)(skb->data)), + RX_DIR, + true)) + { + + // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pRxTS->RxLastFragNum is %d,frag is %d,pRxTS->RxLastSeqNum is %d,seq is %d\n",__FUNCTION__,pRxTS->RxLastFragNum,frag,pRxTS->RxLastSeqNum,WLAN_GET_SEQ_SEQ(sc)); + if( (fc & (1<<11)) && + (frag == pRxTS->RxLastFragNum) && + (WLAN_GET_SEQ_SEQ(sc) == pRxTS->RxLastSeqNum) ) + { + goto rx_dropped; + } + else + { + pRxTS->RxLastFragNum = frag; + pRxTS->RxLastSeqNum = WLAN_GET_SEQ_SEQ(sc); + } + } + else + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s(): No TS!! Skip the check!!\n",__FUNCTION__); + goto rx_dropped; + } + } + if (type == IEEE80211_FTYPE_MGMT) { + + + //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len); + if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype)) + goto rx_dropped; + else + goto rx_exit; + } + + /* Data frame - extract src/dst addresses */ + switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { + case IEEE80211_FCTL_FROMDS: + memcpy(dst, hdr->addr1, ETH_ALEN); + memcpy(src, hdr->addr3, ETH_ALEN); + memcpy(bssid, hdr->addr2, ETH_ALEN); + break; + case IEEE80211_FCTL_TODS: + memcpy(dst, hdr->addr3, ETH_ALEN); + memcpy(src, hdr->addr2, ETH_ALEN); + memcpy(bssid, hdr->addr1, ETH_ALEN); + break; + case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: + if (skb->len < IEEE80211_DATA_HDR4_LEN) + goto rx_dropped; + memcpy(dst, hdr->addr3, ETH_ALEN); + memcpy(src, hdr->addr4, ETH_ALEN); + memcpy(bssid, ieee->current_network.bssid, ETH_ALEN); + break; + case 0: + memcpy(dst, hdr->addr1, ETH_ALEN); + memcpy(src, hdr->addr2, ETH_ALEN); + memcpy(bssid, hdr->addr3, ETH_ALEN); + break; + } + +#ifdef NOT_YET + if (hostap_rx_frame_wds(ieee, hdr, fc, &wds)) + goto rx_dropped; + if (wds) { + skb->dev = dev = wds; + stats = hostap_get_stats(dev); + } + + if (ieee->iw_mode == IW_MODE_MASTER && !wds && + (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS && + ieee->stadev && + memcmp(hdr->addr2, ieee->assoc_ap_addr, ETH_ALEN) == 0) { + /* Frame from BSSID of the AP for which we are a client */ + skb->dev = dev = ieee->stadev; + stats = hostap_get_stats(dev); + from_assoc_ap = 1; + } +#endif + + dev->last_rx = jiffies; + +#ifdef NOT_YET + if ((ieee->iw_mode == IW_MODE_MASTER || + ieee->iw_mode == IW_MODE_REPEAT) && + !from_assoc_ap) { + switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats, + wds != NULL)) { + case AP_RX_CONTINUE_NOT_AUTHORIZED: + frame_authorized = 0; + break; + case AP_RX_CONTINUE: + frame_authorized = 1; + break; + case AP_RX_DROP: + goto rx_dropped; + case AP_RX_EXIT: + goto rx_exit; + } + } +#endif + //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len); + /* Nullfunc frames may have PS-bit set, so they must be passed to + * hostap_handle_sta_rx() before being dropped here. */ + if (stype != IEEE80211_STYPE_DATA && + stype != IEEE80211_STYPE_DATA_CFACK && + stype != IEEE80211_STYPE_DATA_CFPOLL && + stype != IEEE80211_STYPE_DATA_CFACKPOLL&& + stype != IEEE80211_STYPE_QOS_DATA//add by David,2006.8.4 + ) { + if (stype != IEEE80211_STYPE_NULLFUNC) + IEEE80211_DEBUG_DROP( + "RX: dropped data frame " + "with no data (type=0x%02x, " + "subtype=0x%02x, len=%d)\n", + type, stype, skb->len); + goto rx_dropped; + } + if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN)) + goto rx_dropped; + + /* skb: hdr + (possibly fragmented, possibly encrypted) payload */ + + if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && + (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) + { + printk("decrypt frame error\n"); + goto rx_dropped; + } + + + hdr = (struct ieee80211_hdr_4addr *) skb->data; + + /* skb: hdr + (possibly fragmented) plaintext payload */ + // PR: FIXME: hostap has additional conditions in the "if" below: + // ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && + if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) { + int flen; + struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr); + IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag); + + if (!frag_skb) { + IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG, + "Rx cannot get skb from fragment " + "cache (morefrag=%d seq=%u frag=%u)\n", + (fc & IEEE80211_FCTL_MOREFRAGS) != 0, + WLAN_GET_SEQ_SEQ(sc), frag); + goto rx_dropped; + } + flen = skb->len; + if (frag != 0) + flen -= hdrlen; + + if (frag_skb->tail + flen > frag_skb->end) { + printk(KERN_WARNING "%s: host decrypted and " + "reassembled frame did not fit skb\n", + dev->name); + ieee80211_frag_cache_invalidate(ieee, hdr); + goto rx_dropped; + } + + if (frag == 0) { + /* copy first fragment (including full headers) into + * beginning of the fragment cache skb */ + memcpy(skb_put(frag_skb, flen), skb->data, flen); + } else { + /* append frame payload to the end of the fragment + * cache skb */ + memcpy(skb_put(frag_skb, flen), skb->data + hdrlen, + flen); + } + dev_kfree_skb_any(skb); + skb = NULL; + + if (fc & IEEE80211_FCTL_MOREFRAGS) { + /* more fragments expected - leave the skb in fragment + * cache for now; it will be delivered to upper layers + * after all fragments have been received */ + goto rx_exit; + } + + /* this was the last fragment and the frame will be + * delivered, so remove skb from fragment cache */ + skb = frag_skb; + hdr = (struct ieee80211_hdr_4addr *) skb->data; + ieee80211_frag_cache_invalidate(ieee, hdr); + } + + /* skb: hdr + (possible reassembled) full MSDU payload; possibly still + * encrypted/authenticated */ + if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && + ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) + { + printk("==>decrypt msdu error\n"); + goto rx_dropped; + } + + //added by amy for AP roaming + ieee->LinkDetectInfo.NumRecvDataInPeriod++; + ieee->LinkDetectInfo.NumRxOkInPeriod++; + + hdr = (struct ieee80211_hdr_4addr *) skb->data; + if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) { + if (/*ieee->ieee802_1x &&*/ + ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { + +#ifdef CONFIG_IEEE80211_DEBUG + /* pass unencrypted EAPOL frames even if encryption is + * configured */ + struct eapol *eap = (struct eapol *)(skb->data + + 24); + IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", + eap_get_type(eap->type)); +#endif + } else { + IEEE80211_DEBUG_DROP( + "encryption configured, but RX " + "frame not encrypted (SA=" MAC_FMT ")\n", + MAC_ARG(hdr->addr2)); + goto rx_dropped; + } + } + +#ifdef CONFIG_IEEE80211_DEBUG + if (crypt && !(fc & IEEE80211_FCTL_WEP) && + ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { + struct eapol *eap = (struct eapol *)(skb->data + + 24); + IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", + eap_get_type(eap->type)); + } +#endif + + if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep && + !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { + IEEE80211_DEBUG_DROP( + "dropped unencrypted RX data " + "frame from " MAC_FMT + " (drop_unencrypted=1)\n", + MAC_ARG(hdr->addr2)); + goto rx_dropped; + } +/* + if(ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { + printk(KERN_WARNING "RX: IEEE802.1X EPAOL frame!\n"); + } +*/ +//added by amy for reorder + if(ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data) + && !is_multicast_ether_addr(hdr->addr1) && !is_broadcast_ether_addr(hdr->addr1)) + { + TID = Frame_QoSTID(skb->data); + SeqNum = WLAN_GET_SEQ_SEQ(sc); + GetTs(ieee,(PTS_COMMON_INFO*) &pTS,hdr->addr2,TID,RX_DIR,true); + if(TID !=0 && TID !=3) + { + ieee->bis_any_nonbepkts = true; + } + } +//added by amy for reorder + /* skb: hdr + (possible reassembled) full plaintext payload */ + payload = skb->data + hdrlen; + //ethertype = (payload[6] << 8) | payload[7]; + rxb = (struct ieee80211_rxb*)kmalloc(sizeof(struct ieee80211_rxb),GFP_ATOMIC); + if(rxb == NULL) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR,"%s(): kmalloc rxb error\n",__FUNCTION__); + goto rx_dropped; + } + /* to parse amsdu packets */ + /* qos data packets & reserved bit is 1 */ + if(parse_subframe(skb,rx_stats,rxb,src,dst) == 0) { + /* only to free rxb, and not submit the packets to upper layer */ + for(i =0; i < rxb->nr_subframes; i++) { + dev_kfree_skb(rxb->subframes[i]); + } + kfree(rxb); + rxb = NULL; + goto rx_dropped; + } + +//added by amy for reorder + if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL){ +//added by amy for reorder + for(i = 0; inr_subframes; i++) { + struct sk_buff *sub_skb = rxb->subframes[i]; + + if (sub_skb) { + /* convert hdr + possible LLC headers into Ethernet header */ + ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7]; + if (sub_skb->len >= 8 && + ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 && + ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || + memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) { + /* remove RFC1042 or Bridge-Tunnel encapsulation and + * replace EtherType */ + skb_pull(sub_skb, SNAP_SIZE); + memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN); + memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN); + } else { + u16 len; + /* Leave Ethernet header part of hdr and full payload */ + len = htons(sub_skb->len); + memcpy(skb_push(sub_skb, 2), &len, 2); + memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN); + memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN); + } + + stats->rx_packets++; + stats->rx_bytes += sub_skb->len; + if(is_multicast_ether_addr(dst)) { + stats->multicast++; + } + + /* Indicat the packets to upper layer */ + //printk("0skb_len(%d)\n", skb->len); + sub_skb->protocol = eth_type_trans(sub_skb, dev); + memset(sub_skb->cb, 0, sizeof(sub_skb->cb)); + sub_skb->dev = dev; + sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */ + //skb->ip_summed = CHECKSUM_UNNECESSARY; /* 802.11 crc not sufficient */ + ieee->last_rx_ps_time = jiffies; + //printk("1skb_len(%d)\n", skb->len); + netif_rx(sub_skb); + } + } + kfree(rxb); + rxb = NULL; + + } + else + { + IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n",__FUNCTION__); + RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum); + } +#ifndef JOHN_NOCPY + dev_kfree_skb(skb); +#endif + + rx_exit: +#ifdef NOT_YET + if (sta) + hostap_handle_sta_release(sta); +#endif + return 1; + + rx_dropped: + if (rxb != NULL) + { + kfree(rxb); + rxb = NULL; + } + stats->rx_dropped++; + + /* Returning 0 indicates to caller that we have not handled the SKB-- + * so it is still allocated and can be used again by underlying + * hardware as a DMA target */ + return 0; +} + +#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 + +static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; + +/* +* Make ther structure we read from the beacon packet has +* the right values +*/ +static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element + *info_element, int sub_type) +{ + + if (info_element->qui_subtype != sub_type) + return -1; + if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN)) + return -1; + if (info_element->qui_type != QOS_OUI_TYPE) + return -1; + if (info_element->version != QOS_VERSION_1) + return -1; + + return 0; +} + + +/* + * Parse a QoS parameter element + */ +static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info + *element_param, struct ieee80211_info_element + *info_element) +{ + int ret = 0; + u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2; + + if ((info_element == NULL) || (element_param == NULL)) + return -1; + + if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) { + memcpy(element_param->info_element.qui, info_element->data, + info_element->len); + element_param->info_element.elementID = info_element->id; + element_param->info_element.length = info_element->len; + } else + ret = -1; + if (ret == 0) + ret = ieee80211_verify_qos_info(&element_param->info_element, + QOS_OUI_PARAM_SUB_TYPE); + return ret; +} + +/* + * Parse a QoS information element + */ +static int ieee80211_read_qos_info_element(struct + ieee80211_qos_information_element + *element_info, struct ieee80211_info_element + *info_element) +{ + int ret = 0; + u16 size = sizeof(struct ieee80211_qos_information_element) - 2; + + if (element_info == NULL) + return -1; + if (info_element == NULL) + return -1; + + if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) { + memcpy(element_info->qui, info_element->data, + info_element->len); + element_info->elementID = info_element->id; + element_info->length = info_element->len; + } else + ret = -1; + + if (ret == 0) + ret = ieee80211_verify_qos_info(element_info, + QOS_OUI_INFO_SUB_TYPE); + return ret; +} + + +/* + * Write QoS parameters from the ac parameters. + */ +static int ieee80211_qos_convert_ac_to_parameters(struct + ieee80211_qos_parameter_info + *param_elm, struct + ieee80211_qos_parameters + *qos_param) +{ + int rc = 0; + int i; + struct ieee80211_qos_ac_parameter *ac_params; + u8 aci; + //u8 cw_min; + //u8 cw_max; + + for (i = 0; i < QOS_QUEUE_NUM; i++) { + ac_params = &(param_elm->ac_params_record[i]); + + aci = (ac_params->aci_aifsn & 0x60) >> 5; + + if(aci >= QOS_QUEUE_NUM) + continue; + qos_param->aifs[aci] = (ac_params->aci_aifsn) & 0x0f; + + /* WMM spec P.11: The minimum value for AIFSN shall be 2 */ + qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2:qos_param->aifs[aci]; + + qos_param->cw_min[aci] = ac_params->ecw_min_max & 0x0F; + + qos_param->cw_max[aci] = (ac_params->ecw_min_max & 0xF0) >> 4; + + qos_param->flag[aci] = + (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00; + qos_param->tx_op_limit[aci] = le16_to_cpu(ac_params->tx_op_limit); + } + return rc; +} + +/* + * we have a generic data element which it may contain QoS information or + * parameters element. check the information element length to decide + * which type to read + */ +static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element + *info_element, + struct ieee80211_network *network) +{ + int rc = 0; + struct ieee80211_qos_parameters *qos_param = NULL; + struct ieee80211_qos_information_element qos_info_element; + + rc = ieee80211_read_qos_info_element(&qos_info_element, info_element); + + if (rc == 0) { + network->qos_data.param_count = qos_info_element.ac_info & 0x0F; + network->flags |= NETWORK_HAS_QOS_INFORMATION; + } else { + struct ieee80211_qos_parameter_info param_element; + + rc = ieee80211_read_qos_param_element(¶m_element, + info_element); + if (rc == 0) { + qos_param = &(network->qos_data.parameters); + ieee80211_qos_convert_ac_to_parameters(¶m_element, + qos_param); + network->flags |= NETWORK_HAS_QOS_PARAMETERS; + network->qos_data.param_count = + param_element.info_element.ac_info & 0x0F; + } + } + + if (rc == 0) { + IEEE80211_DEBUG_QOS("QoS is supported\n"); + network->qos_data.supported = 1; + } + return rc; +} + +#ifdef CONFIG_IEEE80211_DEBUG +#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x + +static const char *get_info_element_string(u16 id) +{ + switch (id) { + MFIE_STRING(SSID); + MFIE_STRING(RATES); + MFIE_STRING(FH_SET); + MFIE_STRING(DS_SET); + MFIE_STRING(CF_SET); + MFIE_STRING(TIM); + MFIE_STRING(IBSS_SET); + MFIE_STRING(COUNTRY); + MFIE_STRING(HOP_PARAMS); + MFIE_STRING(HOP_TABLE); + MFIE_STRING(REQUEST); + MFIE_STRING(CHALLENGE); + MFIE_STRING(POWER_CONSTRAINT); + MFIE_STRING(POWER_CAPABILITY); + MFIE_STRING(TPC_REQUEST); + MFIE_STRING(TPC_REPORT); + MFIE_STRING(SUPP_CHANNELS); + MFIE_STRING(CSA); + MFIE_STRING(MEASURE_REQUEST); + MFIE_STRING(MEASURE_REPORT); + MFIE_STRING(QUIET); + MFIE_STRING(IBSS_DFS); + // MFIE_STRING(ERP_INFO); + MFIE_STRING(RSN); + MFIE_STRING(RATES_EX); + MFIE_STRING(GENERIC); + MFIE_STRING(QOS_PARAMETER); + default: + return "UNKNOWN"; + } +} +#endif + +#ifdef ENABLE_DOT11D +static inline void ieee80211_extract_country_ie( + struct ieee80211_device *ieee, + struct ieee80211_info_element *info_element, + struct ieee80211_network *network, + u8 * addr2 +) +{ + if(IS_DOT11D_ENABLE(ieee)) + { + if(info_element->len!= 0) + { + memcpy(network->CountryIeBuf, info_element->data, info_element->len); + network->CountryIeLen = info_element->len; + + if(!IS_COUNTRY_IE_VALID(ieee)) + { + Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data); + } + } + + // + // 070305, rcnjko: I update country IE watch dog here because + // some AP (e.g. Cisco 1242) don't include country IE in their + // probe response frame. + // + if(IS_EQUAL_CIE_SRC(ieee, addr2) ) + { + UPDATE_CIE_WATCHDOG(ieee); + } + } + +} +#endif + +int ieee80211_parse_info_param(struct ieee80211_device *ieee, + struct ieee80211_info_element *info_element, + u16 length, + struct ieee80211_network *network, + struct ieee80211_rx_stats *stats) +{ + u8 i; + short offset; + u16 tmp_htcap_len=0; + u16 tmp_htinfo_len=0; + u16 ht_realtek_agg_len=0; + u8 ht_realtek_agg_buf[MAX_IE_LEN]; +// u16 broadcom_len = 0; +#ifdef CONFIG_IEEE80211_DEBUG + char rates_str[64]; + char *p; +#endif + + while (length >= sizeof(*info_element)) { + if (sizeof(*info_element) + info_element->len > length) { + IEEE80211_DEBUG_MGMT("Info elem: parse failed: " + "info_element->len + 2 > left : " + "info_element->len+2=%zd left=%d, id=%d.\n", + info_element->len + + sizeof(*info_element), + length, info_element->id); + /* We stop processing but don't return an error here + * because some misbehaviour APs break this rule. ie. + * Orinoco AP1000. */ + break; + } + + switch (info_element->id) { + case MFIE_TYPE_SSID: + if (ieee80211_is_empty_essid(info_element->data, + info_element->len)) { + network->flags |= NETWORK_EMPTY_ESSID; + break; + } + + network->ssid_len = min(info_element->len, + (u8) IW_ESSID_MAX_SIZE); + memcpy(network->ssid, info_element->data, network->ssid_len); + if (network->ssid_len < IW_ESSID_MAX_SIZE) + memset(network->ssid + network->ssid_len, 0, + IW_ESSID_MAX_SIZE - network->ssid_len); + + IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n", + network->ssid, network->ssid_len); + break; + + case MFIE_TYPE_RATES: +#ifdef CONFIG_IEEE80211_DEBUG + p = rates_str; +#endif + network->rates_len = min(info_element->len, + MAX_RATES_LENGTH); + for (i = 0; i < network->rates_len; i++) { + network->rates[i] = info_element->data[i]; +#ifdef CONFIG_IEEE80211_DEBUG + p += snprintf(p, sizeof(rates_str) - + (p - rates_str), "%02X ", + network->rates[i]); +#endif + if (ieee80211_is_ofdm_rate + (info_element->data[i])) { + network->flags |= NETWORK_HAS_OFDM; + if (info_element->data[i] & + IEEE80211_BASIC_RATE_MASK) + network->flags &= + ~NETWORK_HAS_CCK; + } + } + + IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n", + rates_str, network->rates_len); + break; + + case MFIE_TYPE_RATES_EX: +#ifdef CONFIG_IEEE80211_DEBUG + p = rates_str; +#endif + network->rates_ex_len = min(info_element->len, + MAX_RATES_EX_LENGTH); + for (i = 0; i < network->rates_ex_len; i++) { + network->rates_ex[i] = info_element->data[i]; +#ifdef CONFIG_IEEE80211_DEBUG + p += snprintf(p, sizeof(rates_str) - + (p - rates_str), "%02X ", + network->rates[i]); +#endif + if (ieee80211_is_ofdm_rate + (info_element->data[i])) { + network->flags |= NETWORK_HAS_OFDM; + if (info_element->data[i] & + IEEE80211_BASIC_RATE_MASK) + network->flags &= + ~NETWORK_HAS_CCK; + } + } + + IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n", + rates_str, network->rates_ex_len); + break; + + case MFIE_TYPE_DS_SET: + IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n", + info_element->data[0]); + network->channel = info_element->data[0]; + break; + + case MFIE_TYPE_FH_SET: + IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n"); + break; + + case MFIE_TYPE_CF_SET: + IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n"); + break; + + case MFIE_TYPE_TIM: + if(info_element->len < 4) + break; + + network->tim.tim_count = info_element->data[0]; + network->tim.tim_period = info_element->data[1]; + + network->dtim_period = info_element->data[1]; + if(ieee->state != IEEE80211_LINKED) + break; + + network->last_dtim_sta_time[0] = stats->mac_time[0]; + network->last_dtim_sta_time[1] = stats->mac_time[1]; + + network->dtim_data = IEEE80211_DTIM_VALID; + + if(info_element->data[0] != 0) + break; + + if(info_element->data[2] & 1) + network->dtim_data |= IEEE80211_DTIM_MBCAST; + + offset = (info_element->data[2] >> 1)*2; + + //printk("offset1:%x aid:%x\n",offset, ieee->assoc_id); + + if(ieee->assoc_id < 8*offset || + ieee->assoc_id > 8*(offset + info_element->len -3)) + + break; + + offset = (ieee->assoc_id / 8) - offset;// + ((aid % 8)? 0 : 1) ; + + if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8))) + network->dtim_data |= IEEE80211_DTIM_UCAST; + + //IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n"); + break; + + case MFIE_TYPE_ERP: + network->erp_value = info_element->data[0]; + network->flags |= NETWORK_HAS_ERP_VALUE; + IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n", + network->erp_value); + break; + case MFIE_TYPE_IBSS_SET: + network->atim_window = info_element->data[0]; + IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n", + network->atim_window); + break; + + case MFIE_TYPE_CHALLENGE: + IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n"); + break; + + case MFIE_TYPE_GENERIC: + IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n", + info_element->len); + if (!ieee80211_parse_qos_info_param_IE(info_element, + network)) + break; + + 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) { + network->wpa_ie_len = min(info_element->len + 2, + MAX_WPA_IE_LEN); + memcpy(network->wpa_ie, info_element, + network->wpa_ie_len); + break; + } + +#ifdef THOMAS_TURBO + if (info_element->len == 7 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0xe0 && + info_element->data[2] == 0x4c && + info_element->data[3] == 0x01 && + info_element->data[4] == 0x02) { + network->Turbo_Enable = 1; + } +#endif + + //for HTcap and HTinfo parameters + if(tmp_htcap_len == 0){ + if(info_element->len >= 4 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x90 && + info_element->data[2] == 0x4c && + info_element->data[3] == 0x033){ + + tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN); + if(tmp_htcap_len != 0){ + network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; + network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\ + sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len; + memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen); + } + } + if(tmp_htcap_len != 0) + network->bssht.bdSupportHT = true; + else + network->bssht.bdSupportHT = false; + } + + + if(tmp_htinfo_len == 0){ + if(info_element->len >= 4 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x90 && + info_element->data[2] == 0x4c && + info_element->data[3] == 0x034){ + + tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN); + if(tmp_htinfo_len != 0){ + network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; + if(tmp_htinfo_len){ + network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\ + sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len; + memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen); + } + + } + + } + } + + if(ieee->aggregation){ + if(network->bssht.bdSupportHT){ + if(info_element->len >= 4 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0xe0 && + info_element->data[2] == 0x4c && + info_element->data[3] == 0x02){ + + ht_realtek_agg_len = min(info_element->len,(u8)MAX_IE_LEN); + memcpy(ht_realtek_agg_buf,info_element->data,info_element->len); + + } + if(ht_realtek_agg_len >= 5){ + network->bssht.bdRT2RTAggregation = true; + + if((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02)) + network->bssht.bdRT2RTLongSlotTime = true; + } + } + + } + + //if(tmp_htcap_len !=0 || tmp_htinfo_len != 0) + { + if((info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x05 && + info_element->data[2] == 0xb5) || + (info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x0a && + info_element->data[2] == 0xf7) || + (info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x10 && + info_element->data[2] == 0x18)){ + + network->broadcom_cap_exist = true; + + } + } + if(info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x0c && + info_element->data[2] == 0x43) + { + network->ralink_cap_exist = true; + } + else + network->ralink_cap_exist = false; + //added by amy for atheros AP + if((info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x03 && + info_element->data[2] == 0x7f) || + (info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x13 && + info_element->data[2] == 0x74)) + { + printk("========>%s(): athros AP is exist\n",__FUNCTION__); + network->atheros_cap_exist = true; + } + else + network->atheros_cap_exist = false; + + if(info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x40 && + info_element->data[2] == 0x96) + { + network->cisco_cap_exist = true; + } + else + network->cisco_cap_exist = false; + //added by amy for LEAP of cisco + if(info_element->len > 4 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x40 && + info_element->data[2] == 0x96 && + info_element->data[3] == 0x01) + { + if(info_element->len == 6) + { + memcpy(network->CcxRmState, &info_element[4], 2); + if(network->CcxRmState[0] != 0) + { + network->bCcxRmEnable = true; + } + else + network->bCcxRmEnable = false; + // + // CCXv4 Table 59-1 MBSSID Masks. + // + network->MBssidMask = network->CcxRmState[1] & 0x07; + if(network->MBssidMask != 0) + { + network->bMBssidValid = true; + network->MBssidMask = 0xff << (network->MBssidMask); + cpMacAddr(network->MBssid, network->bssid); + network->MBssid[5] &= network->MBssidMask; + } + else + { + network->bMBssidValid = false; + } + } + else + { + network->bCcxRmEnable = false; + } + } + if(info_element->len > 4 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x40 && + info_element->data[2] == 0x96 && + info_element->data[3] == 0x03) + { + if(info_element->len == 5) + { + network->bWithCcxVerNum = true; + network->BssCcxVerNumber = info_element->data[4]; + } + else + { + network->bWithCcxVerNum = false; + network->BssCcxVerNumber = 0; + } + } + break; + + case MFIE_TYPE_RSN: + IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n", + info_element->len); + network->rsn_ie_len = min(info_element->len + 2, + MAX_WPA_IE_LEN); + memcpy(network->rsn_ie, info_element, + network->rsn_ie_len); + break; + + //HT related element. + case MFIE_TYPE_HT_CAP: + IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_CAP: %d bytes\n", + info_element->len); + tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN); + if(tmp_htcap_len != 0){ + network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; + network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\ + sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len; + memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen); + + //If peer is HT, but not WMM, call QosSetLegacyWMMParamWithHT() + // windows driver will update WMM parameters each beacon received once connected + // Linux driver is a bit different. + network->bssht.bdSupportHT = true; + } + else + network->bssht.bdSupportHT = false; + break; + + + case MFIE_TYPE_HT_INFO: + IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_INFO: %d bytes\n", + info_element->len); + tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN); + if(tmp_htinfo_len){ + network->bssht.bdHTSpecVer = HT_SPEC_VER_IEEE; + network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\ + sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len; + memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen); + } + break; + + case MFIE_TYPE_AIRONET: + IEEE80211_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n", + info_element->len); + if(info_element->len >IE_CISCO_FLAG_POSITION) + { + network->bWithAironetIE = true; + + // CCX 1 spec v1.13, A01.1 CKIP Negotiation (page23): + // "A Cisco access point advertises support for CKIP in beacon and probe response packets, + // by adding an Aironet element and setting one or both of the CKIP negotiation bits." + if( (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_MIC) || + (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_PK) ) + { + network->bCkipSupported = true; + } + else + { + network->bCkipSupported = false; + } + } + else + { + network->bWithAironetIE = false; + network->bCkipSupported = false; + } + break; + case MFIE_TYPE_QOS_PARAMETER: + printk(KERN_ERR + "QoS Error need to parse QOS_PARAMETER IE\n"); + break; + +#ifdef ENABLE_DOT11D + case MFIE_TYPE_COUNTRY: + IEEE80211_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n", + info_element->len); + //printk("=====>Receive <%s> Country IE\n",network->ssid); + ieee80211_extract_country_ie(ieee, info_element, network, network->bssid);//addr2 is same as addr3 when from an AP + break; +#endif +/* TODO */ + default: + IEEE80211_DEBUG_MGMT + ("Unsupported info element: %s (%d)\n", + get_info_element_string(info_element->id), + info_element->id); + break; + } + + length -= sizeof(*info_element) + info_element->len; + info_element = + (struct ieee80211_info_element *)&info_element-> + data[info_element->len]; + } + + if(!network->atheros_cap_exist && !network->broadcom_cap_exist && + !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation) + { + network->unknown_cap_exist = true; + } + else + { + network->unknown_cap_exist = false; + } + return 0; +} + +static inline u8 ieee80211_SignalStrengthTranslate( + u8 CurrSS + ) +{ + u8 RetSS; + + // Step 1. Scale mapping. + if(CurrSS >= 71 && CurrSS <= 100) + { + RetSS = 90 + ((CurrSS - 70) / 3); + } + else if(CurrSS >= 41 && CurrSS <= 70) + { + RetSS = 78 + ((CurrSS - 40) / 3); + } + else if(CurrSS >= 31 && CurrSS <= 40) + { + RetSS = 66 + (CurrSS - 30); + } + else if(CurrSS >= 21 && CurrSS <= 30) + { + RetSS = 54 + (CurrSS - 20); + } + else if(CurrSS >= 5 && CurrSS <= 20) + { + RetSS = 42 + (((CurrSS - 5) * 2) / 3); + } + else if(CurrSS == 4) + { + RetSS = 36; + } + else if(CurrSS == 3) + { + RetSS = 27; + } + else if(CurrSS == 2) + { + RetSS = 18; + } + else if(CurrSS == 1) + { + RetSS = 9; + } + else + { + RetSS = CurrSS; + } + //RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS)); + + // Step 2. Smoothing. + + //RT_TRACE(COMP_DBG, DBG_LOUD, ("$$$$$ After Smoothing: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS)); + + return RetSS; +} + +long ieee80211_translate_todbm(u8 signal_strength_index )// 0-100 index. +{ + long signal_power; // in dBm. + + // Translate to dBm (x=0.5y-95). + signal_power = (long)((signal_strength_index + 1) >> 1); + signal_power -= 95; + + return signal_power; +} + +static inline int ieee80211_network_init( + struct ieee80211_device *ieee, + struct ieee80211_probe_response *beacon, + struct ieee80211_network *network, + struct ieee80211_rx_stats *stats) +{ +#ifdef CONFIG_IEEE80211_DEBUG + //char rates_str[64]; + //char *p; +#endif + + network->qos_data.active = 0; + network->qos_data.supported = 0; + network->qos_data.param_count = 0; + network->qos_data.old_param_count = 0; + + /* Pull out fixed field data */ + memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); + network->capability = le16_to_cpu(beacon->capability); + network->last_scanned = jiffies; + network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]); + network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]); + network->beacon_interval = le32_to_cpu(beacon->beacon_interval); + /* Where to pull this? beacon->listen_interval;*/ + network->listen_interval = 0x0A; + network->rates_len = network->rates_ex_len = 0; + network->last_associate = 0; + network->ssid_len = 0; + network->flags = 0; + network->atim_window = 0; + network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ? + 0x3 : 0x0; + network->berp_info_valid = false; + network->broadcom_cap_exist = false; + network->ralink_cap_exist = false; + network->atheros_cap_exist = false; + network->cisco_cap_exist = false; + network->unknown_cap_exist = false; +#ifdef THOMAS_TURBO + network->Turbo_Enable = 0; +#endif +#ifdef ENABLE_DOT11D + network->CountryIeLen = 0; + memset(network->CountryIeBuf, 0, MAX_IE_LEN); +#endif +//Initialize HT parameters + //ieee80211_ht_initialize(&network->bssht); + HTInitializeBssDesc(&network->bssht); + if (stats->freq == IEEE80211_52GHZ_BAND) { + /* for A band (No DS info) */ + network->channel = stats->received_channel; + } else + network->flags |= NETWORK_HAS_CCK; + + network->wpa_ie_len = 0; + network->rsn_ie_len = 0; + + if (ieee80211_parse_info_param + (ieee,beacon->info_element, stats->len - sizeof(*beacon), network, stats)) + return 1; + + network->mode = 0; + if (stats->freq == IEEE80211_52GHZ_BAND) + network->mode = IEEE_A; + else { + if (network->flags & NETWORK_HAS_OFDM) + network->mode |= IEEE_G; + if (network->flags & NETWORK_HAS_CCK) + network->mode |= IEEE_B; + } + + if (network->mode == 0) { + IEEE80211_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' " + "network.\n", + escape_essid(network->ssid, + network->ssid_len), + MAC_ARG(network->bssid)); + return 1; + } + + if(network->bssht.bdSupportHT){ + if(network->mode == IEEE_A) + network->mode = IEEE_N_5G; + else if(network->mode & (IEEE_G | IEEE_B)) + network->mode = IEEE_N_24G; + } + if (ieee80211_is_empty_essid(network->ssid, network->ssid_len)) + network->flags |= NETWORK_EMPTY_ESSID; + + stats->signal = 30 + (stats->SignalStrength * 70) / 100; + //stats->signal = ieee80211_SignalStrengthTranslate(stats->signal); + stats->noise = ieee80211_translate_todbm((u8)(100-stats->signal)) -25; + + memcpy(&network->stats, stats, sizeof(network->stats)); + + return 0; +} + +static inline int is_same_network(struct ieee80211_network *src, + struct ieee80211_network *dst, struct ieee80211_device* ieee) +{ + /* A network is only a duplicate if the channel, BSSID, ESSID + * and the capability field (in particular IBSS and BSS) all match. + * We treat all with the same BSSID and channel + * as one network */ + return //((src->ssid_len == dst->ssid_len) && + (((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && + (src->channel == dst->channel) && + !memcmp(src->bssid, dst->bssid, ETH_ALEN) && + //!memcmp(src->ssid, dst->ssid, src->ssid_len) && + (!memcmp(src->ssid, dst->ssid, src->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && + ((src->capability & WLAN_CAPABILITY_IBSS) == + (dst->capability & WLAN_CAPABILITY_IBSS)) && + ((src->capability & WLAN_CAPABILITY_BSS) == + (dst->capability & WLAN_CAPABILITY_BSS))); +} + +static inline void update_network(struct ieee80211_network *dst, + struct ieee80211_network *src) +{ + int qos_active; + u8 old_param; + + memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats)); + dst->capability = src->capability; + memcpy(dst->rates, src->rates, src->rates_len); + dst->rates_len = src->rates_len; + memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len); + dst->rates_ex_len = src->rates_ex_len; + if(src->ssid_len > 0) + { + memset(dst->ssid, 0, dst->ssid_len); + dst->ssid_len = src->ssid_len; + memcpy(dst->ssid, src->ssid, src->ssid_len); + } + dst->mode = src->mode; + dst->flags = src->flags; + dst->time_stamp[0] = src->time_stamp[0]; + dst->time_stamp[1] = src->time_stamp[1]; + if (src->flags & NETWORK_HAS_ERP_VALUE) + { + dst->erp_value = src->erp_value; + dst->berp_info_valid = src->berp_info_valid = true; + } + dst->beacon_interval = src->beacon_interval; + dst->listen_interval = src->listen_interval; + dst->atim_window = src->atim_window; + dst->dtim_period = src->dtim_period; + dst->dtim_data = src->dtim_data; + dst->last_dtim_sta_time[0] = src->last_dtim_sta_time[0]; + dst->last_dtim_sta_time[1] = src->last_dtim_sta_time[1]; + memcpy(&dst->tim, &src->tim, sizeof(struct ieee80211_tim_parameters)); + + dst->bssht.bdSupportHT = src->bssht.bdSupportHT; + dst->bssht.bdRT2RTAggregation = src->bssht.bdRT2RTAggregation; + dst->bssht.bdHTCapLen= src->bssht.bdHTCapLen; + memcpy(dst->bssht.bdHTCapBuf,src->bssht.bdHTCapBuf,src->bssht.bdHTCapLen); + dst->bssht.bdHTInfoLen= src->bssht.bdHTInfoLen; + memcpy(dst->bssht.bdHTInfoBuf,src->bssht.bdHTInfoBuf,src->bssht.bdHTInfoLen); + dst->bssht.bdHTSpecVer = src->bssht.bdHTSpecVer; + dst->bssht.bdRT2RTLongSlotTime = src->bssht.bdRT2RTLongSlotTime; + dst->broadcom_cap_exist = src->broadcom_cap_exist; + dst->ralink_cap_exist = src->ralink_cap_exist; + dst->atheros_cap_exist = src->atheros_cap_exist; + dst->cisco_cap_exist = src->cisco_cap_exist; + dst->unknown_cap_exist = src->unknown_cap_exist; + memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len); + dst->wpa_ie_len = src->wpa_ie_len; + memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len); + dst->rsn_ie_len = src->rsn_ie_len; + + dst->last_scanned = jiffies; + /* qos related parameters */ + //qos_active = src->qos_data.active; + qos_active = dst->qos_data.active; + //old_param = dst->qos_data.old_param_count; + old_param = dst->qos_data.param_count; + if(dst->flags & NETWORK_HAS_QOS_MASK) + memcpy(&dst->qos_data, &src->qos_data, + sizeof(struct ieee80211_qos_data)); + else { + dst->qos_data.supported = src->qos_data.supported; + dst->qos_data.param_count = src->qos_data.param_count; + } + + if(dst->qos_data.supported == 1) { + dst->QoS_Enable = 1; + if(dst->ssid_len) + IEEE80211_DEBUG_QOS + ("QoS the network %s is QoS supported\n", + dst->ssid); + else + IEEE80211_DEBUG_QOS + ("QoS the network is QoS supported\n"); + } + dst->qos_data.active = qos_active; + dst->qos_data.old_param_count = old_param; + + /* dst->last_associate is not overwritten */ + dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame. + if(src->wmm_param[0].ac_aci_acm_aifsn|| \ + src->wmm_param[1].ac_aci_acm_aifsn|| \ + src->wmm_param[2].ac_aci_acm_aifsn|| \ + src->wmm_param[1].ac_aci_acm_aifsn) { + memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN); + } + //dst->QoS_Enable = src->QoS_Enable; +#ifdef THOMAS_TURBO + dst->Turbo_Enable = src->Turbo_Enable; +#endif + +#ifdef ENABLE_DOT11D + dst->CountryIeLen = src->CountryIeLen; + memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen); +#endif + + //added by amy for LEAP + dst->bWithAironetIE = src->bWithAironetIE; + dst->bCkipSupported = src->bCkipSupported; + memcpy(dst->CcxRmState,src->CcxRmState,2); + dst->bCcxRmEnable = src->bCcxRmEnable; + dst->MBssidMask = src->MBssidMask; + dst->bMBssidValid = src->bMBssidValid; + memcpy(dst->MBssid,src->MBssid,6); + dst->bWithCcxVerNum = src->bWithCcxVerNum; + dst->BssCcxVerNumber = src->BssCcxVerNumber; + +} + +static inline int is_beacon(__le16 fc) +{ + return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON); +} + +static inline void ieee80211_process_probe_response( + struct ieee80211_device *ieee, + struct ieee80211_probe_response *beacon, + struct ieee80211_rx_stats *stats) +{ + struct ieee80211_network network; + struct ieee80211_network *target; + struct ieee80211_network *oldest = NULL; +#ifdef CONFIG_IEEE80211_DEBUG + struct ieee80211_info_element *info_element = &beacon->info_element[0]; +#endif + unsigned long flags; + short renew; + //u8 wmm_info; + + memset(&network, 0, sizeof(struct ieee80211_network)); + IEEE80211_DEBUG_SCAN( + "'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", + escape_essid(info_element->data, info_element->len), + MAC_ARG(beacon->header.addr3), + (beacon->capability & (1<<0xf)) ? '1' : '0', + (beacon->capability & (1<<0xe)) ? '1' : '0', + (beacon->capability & (1<<0xd)) ? '1' : '0', + (beacon->capability & (1<<0xc)) ? '1' : '0', + (beacon->capability & (1<<0xb)) ? '1' : '0', + (beacon->capability & (1<<0xa)) ? '1' : '0', + (beacon->capability & (1<<0x9)) ? '1' : '0', + (beacon->capability & (1<<0x8)) ? '1' : '0', + (beacon->capability & (1<<0x7)) ? '1' : '0', + (beacon->capability & (1<<0x6)) ? '1' : '0', + (beacon->capability & (1<<0x5)) ? '1' : '0', + (beacon->capability & (1<<0x4)) ? '1' : '0', + (beacon->capability & (1<<0x3)) ? '1' : '0', + (beacon->capability & (1<<0x2)) ? '1' : '0', + (beacon->capability & (1<<0x1)) ? '1' : '0', + (beacon->capability & (1<<0x0)) ? '1' : '0'); + + if (ieee80211_network_init(ieee, beacon, &network, stats)) { + IEEE80211_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n", + escape_essid(info_element->data, + info_element->len), + MAC_ARG(beacon->header.addr3), + WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == + IEEE80211_STYPE_PROBE_RESP ? + "PROBE RESPONSE" : "BEACON"); + return; + } + +#ifdef ENABLE_DOT11D + // For Asus EeePc request, + // (1) if wireless adapter receive get any 802.11d country code in AP beacon, + // wireless adapter should follow the country code. + // (2) If there is no any country code in beacon, + // then wireless adapter should do active scan from ch1~11 and + // passive scan from ch12~14 + + if( !IsLegalChannel(ieee, network.channel) ) + return; + if(ieee->bGlobalDomain) + { + if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP) + { + // Case 1: Country code + if(IS_COUNTRY_IE_VALID(ieee) ) + { + if( !IsLegalChannel(ieee, network.channel) ) + { + printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network.channel); + return; + } + } + // Case 2: No any country code. + else + { + // Filter over channel ch12~14 + if(network.channel > 11) + { + printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel); + return; + } + } + } + else + { + // Case 1: Country code + if(IS_COUNTRY_IE_VALID(ieee) ) + { + if( !IsLegalChannel(ieee, network.channel) ) + { + printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n",network.channel); + return; + } + } + // Case 2: No any country code. + else + { + // Filter over channel ch12~14 + if(network.channel > 14) + { + printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network.channel); + return; + } + } + } + } +#endif + + /* The network parsed correctly -- so now we scan our known networks + * to see if we can find it in our list. + * + * NOTE: This search is definitely not optimized. Once its doing + * the "right thing" we'll optimize it for efficiency if + * necessary */ + + /* Search for this entry in the list and update it if it is + * already there. */ + + spin_lock_irqsave(&ieee->lock, flags); + + if(is_same_network(&ieee->current_network, &network, ieee)) { + update_network(&ieee->current_network, &network); + if((ieee->current_network.mode == IEEE_N_24G || ieee->current_network.mode == IEEE_G) + && ieee->current_network.berp_info_valid){ + if(ieee->current_network.erp_value& ERP_UseProtection) + ieee->current_network.buseprotection = true; + else + ieee->current_network.buseprotection = false; + } + if(is_beacon(beacon->header.frame_ctl)) + { + if(ieee->state == IEEE80211_LINKED) + ieee->LinkDetectInfo.NumRecvBcnInPeriod++; + } + else //hidden AP + network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags); + } + + list_for_each_entry(target, &ieee->network_list, list) { + if (is_same_network(target, &network, ieee)) + break; + if ((oldest == NULL) || + (target->last_scanned < oldest->last_scanned)) + oldest = target; + } + + /* If we didn't find a match, then get a new network slot to initialize + * with this beacon's information */ + if (&target->list == &ieee->network_list) { + if (list_empty(&ieee->network_free_list)) { + /* If there are no more slots, expire the oldest */ + list_del(&oldest->list); + target = oldest; + IEEE80211_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from " + "network list.\n", + escape_essid(target->ssid, + target->ssid_len), + MAC_ARG(target->bssid)); + } else { + /* Otherwise just pull from the free list */ + target = list_entry(ieee->network_free_list.next, + struct ieee80211_network, list); + list_del(ieee->network_free_list.next); + } + + +#ifdef CONFIG_IEEE80211_DEBUG + IEEE80211_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n", + escape_essid(network.ssid, + network.ssid_len), + MAC_ARG(network.bssid), + WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == + IEEE80211_STYPE_PROBE_RESP ? + "PROBE RESPONSE" : "BEACON"); +#endif + memcpy(target, &network, sizeof(*target)); + list_add_tail(&target->list, &ieee->network_list); + if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) + ieee80211_softmac_new_net(ieee,&network); + } else { + IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n", + escape_essid(target->ssid, + target->ssid_len), + MAC_ARG(target->bssid), + WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == + IEEE80211_STYPE_PROBE_RESP ? + "PROBE RESPONSE" : "BEACON"); + + /* we have an entry and we are going to update it. But this entry may + * be already expired. In this case we do the same as we found a new + * net and call the new_net handler + */ + renew = !time_after(target->last_scanned + ieee->scan_age, jiffies); + //YJ,add,080819,for hidden ap + if(is_beacon(beacon->header.frame_ctl) == 0) + network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags); + //if(strncmp(network.ssid, "linksys-c",9) == 0) + // printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags); + if(((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \ + && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\ + ||((ieee->current_network.ssid_len == network.ssid_len)&&(strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0)&&(ieee->state == IEEE80211_NOLINK)))) + renew = 1; + //YJ,add,080819,for hidden ap,end + + update_network(target, &network); + if(renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)) + ieee80211_softmac_new_net(ieee,&network); + } + + spin_unlock_irqrestore(&ieee->lock, flags); + if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, &network, ieee)&&\ + (ieee->state == IEEE80211_LINKED)) { + if(ieee->handle_beacon != NULL) { + ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network); + } + } +} + +void ieee80211_rx_mgt(struct ieee80211_device *ieee, + struct ieee80211_hdr_4addr *header, + struct ieee80211_rx_stats *stats) +{ + switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { + + case IEEE80211_STYPE_BEACON: + IEEE80211_DEBUG_MGMT("received BEACON (%d)\n", + WLAN_FC_GET_STYPE(header->frame_ctl)); + IEEE80211_DEBUG_SCAN("Beacon\n"); + ieee80211_process_probe_response( + ieee, (struct ieee80211_probe_response *)header, stats); + break; + + case IEEE80211_STYPE_PROBE_RESP: + IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n", + WLAN_FC_GET_STYPE(header->frame_ctl)); + IEEE80211_DEBUG_SCAN("Probe response\n"); + ieee80211_process_probe_response( + ieee, (struct ieee80211_probe_response *)header, stats); + break; + + } +} + +EXPORT_SYMBOL(ieee80211_rx_mgt); +EXPORT_SYMBOL(ieee80211_rx); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c new file mode 100644 index 0000000000000000000000000000000000000000..8a86e93465c87203513921a76196170ea54104ab --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -0,0 +1,3287 @@ +/* IEEE 802.11 SoftMAC layer + * Copyright (c) 2005 Andrea Merello + * + * Mostly extracted from the rtl8180-sa2400 driver for the + * in-kernel generic ieee802.11 stack. + * + * Few lines might be stolen from other part of the ieee80211 + * stack. Copyright who own it's copyright + * + * WPA code stolen from the ipw2200 driver. + * Copyright who own it's copyright. + * + * released under the GPL + */ + + +#include "ieee80211.h" + +#include +#include +#include +#include +#ifdef ENABLE_DOT11D +#include "dot11d.h" +#endif + +u8 rsn_authen_cipher_suite[16][4] = { + {0x00,0x0F,0xAC,0x00}, //Use group key, //Reserved + {0x00,0x0F,0xAC,0x01}, //WEP-40 //RSNA default + {0x00,0x0F,0xAC,0x02}, //TKIP //NONE //{used just as default} + {0x00,0x0F,0xAC,0x03}, //WRAP-historical + {0x00,0x0F,0xAC,0x04}, //CCMP + {0x00,0x0F,0xAC,0x05}, //WEP-104 +}; + +short ieee80211_is_54g(struct ieee80211_network net) +{ + return ((net.rates_ex_len > 0) || (net.rates_len > 4)); +} + +short ieee80211_is_shortslot(struct ieee80211_network net) +{ + return (net.capability & WLAN_CAPABILITY_SHORT_SLOT); +} + +/* returns the total length needed for pleacing the RATE MFIE + * tag and the EXTENDED RATE MFIE tag if needed. + * It encludes two bytes per tag for the tag itself and its len + */ +unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee) +{ + unsigned int rate_len = 0; + + if (ieee->modulation & IEEE80211_CCK_MODULATION) + rate_len = IEEE80211_CCK_RATE_LEN + 2; + + if (ieee->modulation & IEEE80211_OFDM_MODULATION) + + rate_len += IEEE80211_OFDM_RATE_LEN + 2; + + return rate_len; +} + +/* pleace the MFIE rate, tag to the memory (double) poined. + * Then it updates the pointer so that + * it points after the new MFIE tag added. + */ +void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p) +{ + u8 *tag = *tag_p; + + if (ieee->modulation & IEEE80211_CCK_MODULATION){ + *tag++ = MFIE_TYPE_RATES; + *tag++ = 4; + *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; + *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; + *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; + *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; + } + + /* We may add an option for custom rates that specific HW might support */ + *tag_p = tag; +} + +void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p) +{ + u8 *tag = *tag_p; + + if (ieee->modulation & IEEE80211_OFDM_MODULATION){ + + *tag++ = MFIE_TYPE_RATES_EX; + *tag++ = 8; + *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; + *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; + *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; + *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; + *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; + *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; + *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; + *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; + + } + + /* We may add an option for custom rates that specific HW might support */ + *tag_p = tag; +} + + +void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) { + u8 *tag = *tag_p; + + *tag++ = MFIE_TYPE_GENERIC; //0 + *tag++ = 7; + *tag++ = 0x00; + *tag++ = 0x50; + *tag++ = 0xf2; + *tag++ = 0x02;//5 + *tag++ = 0x00; + *tag++ = 0x01; +#ifdef SUPPORT_USPD + if(ieee->current_network.wmm_info & 0x80) { + *tag++ = 0x0f|MAX_SP_Len; + } else { + *tag++ = MAX_SP_Len; + } +#else + *tag++ = MAX_SP_Len; +#endif + *tag_p = tag; +} + +#ifdef THOMAS_TURBO +void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) { + u8 *tag = *tag_p; + + *tag++ = MFIE_TYPE_GENERIC; //0 + *tag++ = 7; + *tag++ = 0x00; + *tag++ = 0xe0; + *tag++ = 0x4c; + *tag++ = 0x01;//5 + *tag++ = 0x02; + *tag++ = 0x11; + *tag++ = 0x00; + + *tag_p = tag; + printk(KERN_ALERT "This is enable turbo mode IE process\n"); +} +#endif + +void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb) +{ + int nh; + nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM; + +/* + * if the queue is full but we have newer frames then + * just overwrites the oldest. + * + * if (nh == ieee->mgmt_queue_tail) + * return -1; + */ + ieee->mgmt_queue_head = nh; + ieee->mgmt_queue_ring[nh] = skb; + + //return 0; +} + +struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee) +{ + struct sk_buff *ret; + + if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head) + return NULL; + + ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail]; + + ieee->mgmt_queue_tail = + (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM; + + return ret; +} + +void init_mgmt_queue(struct ieee80211_device *ieee) +{ + ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0; +} + +u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + u8 rate; + + // 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M. + if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M) + rate = 0x0c; + else + rate = ieee->basic_rate & 0x7f; + + if(rate == 0){ + // 2005.01.26, by rcnjko. + if(ieee->mode == IEEE_A|| + ieee->mode== IEEE_N_5G|| + (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK)) + rate = 0x0c; + else + rate = 0x02; + } + + /* + // Data rate of ProbeReq is already decided. Annie, 2005-03-31 + if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) ) + { + if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A) + rate = 0x0c; + else + rate = 0x02; + } + */ + return rate; +} + + +void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl); + +inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee) +{ + unsigned long flags; + short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; + struct ieee80211_hdr_3addr *header= + (struct ieee80211_hdr_3addr *) skb->data; + + cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8); + spin_lock_irqsave(&ieee->lock, flags); + + /* called with 2nd param 0, no mgmt lock required */ + ieee80211_sta_wakeup(ieee,0); + + tcb_desc->queue_index = MGNT_QUEUE; + tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee); + tcb_desc->RATRIndex = 7; + tcb_desc->bTxDisableRateFallBack = 1; + tcb_desc->bTxUseDriverAssingedRate = 1; + + if(single){ + if(ieee->queue_stop){ + enqueue_mgmt(ieee,skb); + }else{ + header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4); + + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + + /* avoid watchdog triggers */ + ieee->dev->trans_start = jiffies; + ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate); + //dev_kfree_skb_any(skb);//edit by thomas + } + + spin_unlock_irqrestore(&ieee->lock, flags); + }else{ + spin_unlock_irqrestore(&ieee->lock, flags); + spin_lock_irqsave(&ieee->mgmt_tx_lock, flags); + + header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + + /* check wether the managed packet queued greater than 5 */ + if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\ + (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\ + (ieee->queue_stop) ) { + /* insert the skb packet to the management queue */ + /* as for the completion function, it does not need + * to check it any more. + * */ + printk("%s():insert to waitqueue!\n",__FUNCTION__); + skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb); + } else { + //printk("TX packet!\n"); + ieee->softmac_hard_start_xmit(skb,ieee->dev); + //dev_kfree_skb_any(skb);//edit by thomas + } + spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags); + } +} + +inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee) +{ + + short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; + struct ieee80211_hdr_3addr *header = + (struct ieee80211_hdr_3addr *) skb->data; + + + if(single){ + + header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + + /* avoid watchdog triggers */ + ieee->dev->trans_start = jiffies; + ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate); + + }else{ + + header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + + ieee->softmac_hard_start_xmit(skb,ieee->dev); + + } + //dev_kfree_skb_any(skb);//edit by thomas +} + +inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee) +{ + unsigned int len,rate_len; + u8 *tag; + struct sk_buff *skb; + struct ieee80211_probe_request *req; + + len = ieee->current_network.ssid_len; + + rate_len = ieee80211_MFIE_rate_len(ieee); + + skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) + + 2 + len + rate_len + ieee->tx_headroom); + if (!skb) + return NULL; + + skb_reserve(skb, ieee->tx_headroom); + + req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request)); + req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); + req->header.duration_id = 0; //FIXME: is this OK ? + + memset(req->header.addr1, 0xff, ETH_ALEN); + memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + memset(req->header.addr3, 0xff, ETH_ALEN); + + tag = (u8 *) skb_put(skb,len+2+rate_len); + + *tag++ = MFIE_TYPE_SSID; + *tag++ = len; + memcpy(tag, ieee->current_network.ssid, len); + tag += len; + + ieee80211_MFIE_Brate(ieee,&tag); + ieee80211_MFIE_Grate(ieee,&tag); + return skb; +} + +struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee); +void ieee80211_send_beacon(struct ieee80211_device *ieee) +{ + struct sk_buff *skb; + if(!ieee->ieee_up) + return; + //unsigned long flags; + skb = ieee80211_get_beacon_(ieee); + + if (skb){ + softmac_mgmt_xmit(skb, ieee); + ieee->softmac_stats.tx_beacons++; + //dev_kfree_skb_any(skb);//edit by thomas + } +// ieee->beacon_timer.expires = jiffies + +// (MSECS( ieee->current_network.beacon_interval -5)); + + //spin_lock_irqsave(&ieee->beacon_lock,flags); + if(ieee->beacon_txing && ieee->ieee_up){ +// if(!timer_pending(&ieee->beacon_timer)) +// add_timer(&ieee->beacon_timer); + mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5))); + } + //spin_unlock_irqrestore(&ieee->beacon_lock,flags); +} + + +void ieee80211_send_beacon_cb(unsigned long _ieee) +{ + struct ieee80211_device *ieee = + (struct ieee80211_device *) _ieee; + unsigned long flags; + + spin_lock_irqsave(&ieee->beacon_lock, flags); + ieee80211_send_beacon(ieee); + spin_unlock_irqrestore(&ieee->beacon_lock, flags); +} + + +void ieee80211_send_probe(struct ieee80211_device *ieee) +{ + struct sk_buff *skb; + + skb = ieee80211_probe_req(ieee); + if (skb){ + softmac_mgmt_xmit(skb, ieee); + ieee->softmac_stats.tx_probe_rq++; + //dev_kfree_skb_any(skb);//edit by thomas + } +} + +void ieee80211_send_probe_requests(struct ieee80211_device *ieee) +{ + if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){ + ieee80211_send_probe(ieee); + ieee80211_send_probe(ieee); + } +} + +/* this performs syncro scan blocking the caller until all channels + * in the allowed channel map has been checked. + */ +void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee) +{ + short ch = 0; +#ifdef ENABLE_DOT11D + u8 channel_map[MAX_CHANNEL_NUMBER+1]; + memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1); +#endif + down(&ieee->scan_sem); + + while(1) + { + + do{ + ch++; + if (ch > MAX_CHANNEL_NUMBER) + goto out; /* scan completed */ +#ifdef ENABLE_DOT11D + }while(!channel_map[ch]); +#else + }while(!ieee->channel_map[ch]); +#endif + + /* this fuction can be called in two situations + * 1- We have switched to ad-hoc mode and we are + * performing a complete syncro scan before conclude + * there are no interesting cell and to create a + * new one. In this case the link state is + * IEEE80211_NOLINK until we found an interesting cell. + * If so the ieee8021_new_net, called by the RX path + * will set the state to IEEE80211_LINKED, so we stop + * scanning + * 2- We are linked and the root uses run iwlist scan. + * So we switch to IEEE80211_LINKED_SCANNING to remember + * that we are still logically linked (not interested in + * new network events, despite for updating the net list, + * but we are temporarly 'unlinked' as the driver shall + * not filter RX frames and the channel is changing. + * So the only situation in witch are interested is to check + * if the state become LINKED because of the #1 situation + */ + + if (ieee->state == IEEE80211_LINKED) + goto out; + ieee->set_chan(ieee->dev, ch); +#ifdef ENABLE_DOT11D + if(channel_map[ch] == 1) +#endif + ieee80211_send_probe_requests(ieee); + + /* this prevent excessive time wait when we + * need to wait for a syncro scan to end.. + */ + if(ieee->state < IEEE80211_LINKED) + ; + else + if (ieee->sync_scan_hurryup) + goto out; + + + msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME); + + } +out: + if(ieee->state < IEEE80211_LINKED){ + ieee->actscanning = false; + up(&ieee->scan_sem); + } + else{ + ieee->sync_scan_hurryup = 0; +#ifdef ENABLE_DOT11D + if(IS_DOT11D_ENABLE(ieee)) + DOT11D_ScanComplete(ieee); +#endif + up(&ieee->scan_sem); +} +} + + +void ieee80211_softmac_scan_wq(struct work_struct *work) +{ + struct delayed_work *dwork = container_of(work, struct delayed_work, work); + struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq); + static short watchdog = 0; +#ifdef ENABLE_DOT11D + u8 channel_map[MAX_CHANNEL_NUMBER+1]; + memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1); +#endif + if(!ieee->ieee_up) + return; + down(&ieee->scan_sem); + do{ + ieee->current_network.channel = + (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER; + if (watchdog++ > MAX_CHANNEL_NUMBER) + { + //if current channel is not in channel map, set to default channel. + #ifdef ENABLE_DOT11D + if (!channel_map[ieee->current_network.channel]); + #else + if (!ieee->channel_map[ieee->current_network.channel]); + #endif + ieee->current_network.channel = 6; + goto out; /* no good chans */ + } +#ifdef ENABLE_DOT11D + }while(!channel_map[ieee->current_network.channel]); +#else + }while(!ieee->channel_map[ieee->current_network.channel]); +#endif + if (ieee->scanning == 0 ) + goto out; + ieee->set_chan(ieee->dev, ieee->current_network.channel); +#ifdef ENABLE_DOT11D + if(channel_map[ieee->current_network.channel] == 1) +#endif + ieee80211_send_probe_requests(ieee); + + + queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME); + + up(&ieee->scan_sem); + return; +out: +#ifdef ENABLE_DOT11D + if(IS_DOT11D_ENABLE(ieee)) + DOT11D_ScanComplete(ieee); +#endif + ieee->actscanning = false; + watchdog = 0; + ieee->scanning = 0; + up(&ieee->scan_sem); +} + + + +void ieee80211_beacons_start(struct ieee80211_device *ieee) +{ + unsigned long flags; + spin_lock_irqsave(&ieee->beacon_lock,flags); + + ieee->beacon_txing = 1; + ieee80211_send_beacon(ieee); + + spin_unlock_irqrestore(&ieee->beacon_lock,flags); +} + +void ieee80211_beacons_stop(struct ieee80211_device *ieee) +{ + unsigned long flags; + + spin_lock_irqsave(&ieee->beacon_lock,flags); + + ieee->beacon_txing = 0; + del_timer_sync(&ieee->beacon_timer); + + spin_unlock_irqrestore(&ieee->beacon_lock,flags); + +} + + +void ieee80211_stop_send_beacons(struct ieee80211_device *ieee) +{ + if(ieee->stop_send_beacons) + ieee->stop_send_beacons(ieee->dev); + if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS) + ieee80211_beacons_stop(ieee); +} + + +void ieee80211_start_send_beacons(struct ieee80211_device *ieee) +{ + if(ieee->start_send_beacons) + ieee->start_send_beacons(ieee->dev,ieee->basic_rate); + if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS) + ieee80211_beacons_start(ieee); +} + + +void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee) +{ +// unsigned long flags; + + //ieee->sync_scan_hurryup = 1; + + down(&ieee->scan_sem); +// spin_lock_irqsave(&ieee->lock, flags); + + if (ieee->scanning == 1){ + ieee->scanning = 0; + + cancel_delayed_work(&ieee->softmac_scan_wq); + } + +// spin_unlock_irqrestore(&ieee->lock, flags); + up(&ieee->scan_sem); +} + +void ieee80211_stop_scan(struct ieee80211_device *ieee) +{ + if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) + ieee80211_softmac_stop_scan(ieee); + else + ieee->stop_scan(ieee->dev); +} + +/* called with ieee->lock held */ +void ieee80211_start_scan(struct ieee80211_device *ieee) +{ +#ifdef ENABLE_DOT11D + if(IS_DOT11D_ENABLE(ieee) ) + { + if(IS_COUNTRY_IE_VALID(ieee)) + { + RESET_CIE_WATCHDOG(ieee); + } + } +#endif + if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){ + if (ieee->scanning == 0){ + ieee->scanning = 1; + queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0); + } + }else + ieee->start_scan(ieee->dev); + +} + +/* called with wx_sem held */ +void ieee80211_start_scan_syncro(struct ieee80211_device *ieee) +{ +#ifdef ENABLE_DOT11D + if(IS_DOT11D_ENABLE(ieee) ) + { + if(IS_COUNTRY_IE_VALID(ieee)) + { + RESET_CIE_WATCHDOG(ieee); + } + } +#endif + ieee->sync_scan_hurryup = 0; + if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) + ieee80211_softmac_scan_syncro(ieee); + else + ieee->scan_syncro(ieee->dev); + +} + +inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon, + struct ieee80211_device *ieee, int challengelen) +{ + struct sk_buff *skb; + struct ieee80211_authentication *auth; + int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom; + + + skb = dev_alloc_skb(len); + if (!skb) return NULL; + + skb_reserve(skb, ieee->tx_headroom); + auth = (struct ieee80211_authentication *) + skb_put(skb, sizeof(struct ieee80211_authentication)); + + auth->header.frame_ctl = IEEE80211_STYPE_AUTH; + if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP; + + auth->header.duration_id = 0x013a; //FIXME + + memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN); + memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN); + + //auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; + if(ieee->auth_mode == 0) + auth->algorithm = WLAN_AUTH_OPEN; + else if(ieee->auth_mode == 1) + auth->algorithm = WLAN_AUTH_SHARED_KEY; + else if(ieee->auth_mode == 2) + auth->algorithm = WLAN_AUTH_OPEN;//0x80; + printk("=================>%s():auth->algorithm is %d\n",__FUNCTION__,auth->algorithm); + auth->transaction = cpu_to_le16(ieee->associate_seq); + ieee->associate_seq++; + + auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS); + + return skb; + +} + + +static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest) +{ + u8 *tag; + int beacon_size; + struct ieee80211_probe_response *beacon_buf; + struct sk_buff *skb = NULL; + int encrypt; + int atim_len,erp_len; + struct ieee80211_crypt_data* crypt; + + char *ssid = ieee->current_network.ssid; + int ssid_len = ieee->current_network.ssid_len; + int rate_len = ieee->current_network.rates_len+2; + int rate_ex_len = ieee->current_network.rates_ex_len; + int wpa_ie_len = ieee->wpa_ie_len; + u8 erpinfo_content = 0; + + u8* tmp_ht_cap_buf; + u8 tmp_ht_cap_len=0; + u8* tmp_ht_info_buf; + u8 tmp_ht_info_len=0; + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + u8* tmp_generic_ie_buf=NULL; + u8 tmp_generic_ie_len=0; + + if(rate_ex_len > 0) rate_ex_len+=2; + + if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS) + atim_len = 4; + else + atim_len = 0; + + if(ieee80211_is_54g(ieee->current_network)) + erp_len = 3; + else + erp_len = 0; + + + crypt = ieee->crypt[ieee->tx_keyidx]; + + + encrypt = ieee->host_encrypt && crypt && crypt->ops && + ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len)); + //HT ralated element + tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap); + tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap); + tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo); + tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo); + HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt); + HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt); + + + if(pHTInfo->bRegRT2RTAggregation) + { + tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer; + tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer); + HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len); + } +// printk("===============>tmp_ht_cap_len is %d,tmp_ht_info_len is %d, tmp_generic_ie_len is %d\n",tmp_ht_cap_len,tmp_ht_info_len,tmp_generic_ie_len); + beacon_size = sizeof(struct ieee80211_probe_response)+2+ + ssid_len + +3 //channel + +rate_len + +rate_ex_len + +atim_len + +erp_len + +wpa_ie_len + // +tmp_ht_cap_len + // +tmp_ht_info_len + // +tmp_generic_ie_len +// +wmm_len+2 + +ieee->tx_headroom; + skb = dev_alloc_skb(beacon_size); + if (!skb) + return NULL; + skb_reserve(skb, ieee->tx_headroom); + beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom)); + memcpy (beacon_buf->header.addr1, dest,ETH_ALEN); + memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN); + + beacon_buf->header.duration_id = 0; //FIXME + beacon_buf->beacon_interval = + cpu_to_le16(ieee->current_network.beacon_interval); + beacon_buf->capability = + cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS); + beacon_buf->capability |= + cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here + + if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT)) + cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT)); + + crypt = ieee->crypt[ieee->tx_keyidx]; + if (encrypt) + beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); + + + beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP); + beacon_buf->info_element[0].id = MFIE_TYPE_SSID; + beacon_buf->info_element[0].len = ssid_len; + + tag = (u8*) beacon_buf->info_element[0].data; + + memcpy(tag, ssid, ssid_len); + + tag += ssid_len; + + *(tag++) = MFIE_TYPE_RATES; + *(tag++) = rate_len-2; + memcpy(tag,ieee->current_network.rates,rate_len-2); + tag+=rate_len-2; + + *(tag++) = MFIE_TYPE_DS_SET; + *(tag++) = 1; + *(tag++) = ieee->current_network.channel; + + if(atim_len){ + u16 val16; + *(tag++) = MFIE_TYPE_IBSS_SET; + *(tag++) = 2; + //*((u16*)(tag)) = cpu_to_le16(ieee->current_network.atim_window); + val16 = cpu_to_le16(ieee->current_network.atim_window); + memcpy((u8 *)tag, (u8 *)&val16, 2); + tag+=2; + } + + if(erp_len){ + *(tag++) = MFIE_TYPE_ERP; + *(tag++) = 1; + *(tag++) = erpinfo_content; + } + if(rate_ex_len){ + *(tag++) = MFIE_TYPE_RATES_EX; + *(tag++) = rate_ex_len-2; + memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2); + tag+=rate_ex_len-2; + } + + if (wpa_ie_len) + { + if (ieee->iw_mode == IW_MODE_ADHOC) + {//as Windows will set pairwise key same as the group key which is not allowed in Linux, so set this for IOT issue. WB 2008.07.07 + memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4); + } + memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len); + tag += wpa_ie_len; + } + + //skb->dev = ieee->dev; + return skb; +} + + +struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest) +{ + struct sk_buff *skb; + u8* tag; + + struct ieee80211_crypt_data* crypt; + struct ieee80211_assoc_response_frame *assoc; + short encrypt; + + unsigned int rate_len = ieee80211_MFIE_rate_len(ieee); + int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom; + + skb = dev_alloc_skb(len); + + if (!skb) + return NULL; + + skb_reserve(skb, ieee->tx_headroom); + + assoc = (struct ieee80211_assoc_response_frame *) + skb_put(skb,sizeof(struct ieee80211_assoc_response_frame)); + + assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP); + memcpy(assoc->header.addr1, dest,ETH_ALEN); + memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN); + memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ? + WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS); + + + if(ieee->short_slot) + assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); + + if (ieee->host_encrypt) + crypt = ieee->crypt[ieee->tx_keyidx]; + else crypt = NULL; + + encrypt = ( crypt && crypt->ops); + + if (encrypt) + assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); + + assoc->status = 0; + assoc->aid = cpu_to_le16(ieee->assoc_id); + if (ieee->assoc_id == 0x2007) ieee->assoc_id=0; + else ieee->assoc_id++; + + tag = (u8*) skb_put(skb, rate_len); + + ieee80211_MFIE_Brate(ieee, &tag); + ieee80211_MFIE_Grate(ieee, &tag); + + return skb; +} + +struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest) +{ + struct sk_buff *skb; + struct ieee80211_authentication *auth; + int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1; + + skb = dev_alloc_skb(len); + + if (!skb) + return NULL; + + skb->len = sizeof(struct ieee80211_authentication); + + auth = (struct ieee80211_authentication *)skb->data; + + auth->status = cpu_to_le16(status); + auth->transaction = cpu_to_le16(2); + auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN); + + memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN); + memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + memcpy(auth->header.addr1, dest, ETH_ALEN); + auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH); + return skb; + + +} + +struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr) +{ + struct sk_buff *skb; + struct ieee80211_hdr_3addr* hdr; + + skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr)); + + if (!skb) + return NULL; + + hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr)); + + memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN); + memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN); + memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN); + + hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | + IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS | + (pwr ? IEEE80211_FCTL_PM:0)); + + return skb; + + +} + + +void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest) +{ + struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest); + + if (buf) + softmac_mgmt_xmit(buf, ieee); +} + + +void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest) +{ + struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest); + + if (buf) + softmac_mgmt_xmit(buf, ieee); +} + + +void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest) +{ + + + struct sk_buff *buf = ieee80211_probe_resp(ieee, dest); + if (buf) + softmac_mgmt_xmit(buf, ieee); +} + + +inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee) +{ + struct sk_buff *skb; + //unsigned long flags; + + struct ieee80211_assoc_request_frame *hdr; + u8 *tag;//,*rsn_ie; + //short info_addr = 0; + //int i; + //u16 suite_count = 0; + //u8 suit_select = 0; + //unsigned int wpa_len = beacon->wpa_ie_len; + //for HT + u8* ht_cap_buf = NULL; + u8 ht_cap_len=0; + u8* realtek_ie_buf=NULL; + u8 realtek_ie_len=0; + int wpa_ie_len= ieee->wpa_ie_len; + unsigned int ckip_ie_len=0; + unsigned int ccxrm_ie_len=0; + unsigned int cxvernum_ie_len=0; + struct ieee80211_crypt_data* crypt; + int encrypt; + + unsigned int rate_len = ieee80211_MFIE_rate_len(ieee); + unsigned int wmm_info_len = beacon->qos_data.supported?9:0; +#ifdef THOMAS_TURBO + unsigned int turbo_info_len = beacon->Turbo_Enable?9:0; +#endif + + int len = 0; + + crypt = ieee->crypt[ieee->tx_keyidx]; + encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len)); + + //Include High Throuput capability && Realtek proprietary + if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT) + { + ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap); + ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap); + HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt); + if(ieee->pHTInfo->bCurrentRT2RTAggregation) + { + realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer; + realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer); + HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len); + + } + } + if(ieee->qos_support){ + wmm_info_len = beacon->qos_data.supported?9:0; + } + + + if(beacon->bCkipSupported) + { + ckip_ie_len = 30+2; + } + if(beacon->bCcxRmEnable) + { + ccxrm_ie_len = 6+2; + } + if( beacon->BssCcxVerNumber >= 2 ) + { + cxvernum_ie_len = 5+2; + } +#ifdef THOMAS_TURBO + len = sizeof(struct ieee80211_assoc_request_frame)+ 2 + + beacon->ssid_len//essid tagged val + + rate_len//rates tagged val + + wpa_ie_len + + wmm_info_len + + turbo_info_len + + ht_cap_len + + realtek_ie_len + + ckip_ie_len + + ccxrm_ie_len + + cxvernum_ie_len + + ieee->tx_headroom; +#else + len = sizeof(struct ieee80211_assoc_request_frame)+ 2 + + beacon->ssid_len//essid tagged val + + rate_len//rates tagged val + + wpa_ie_len + + wmm_info_len + + ht_cap_len + + realtek_ie_len + + ckip_ie_len + + ccxrm_ie_len + + cxvernum_ie_len + + ieee->tx_headroom; +#endif + + skb = dev_alloc_skb(len); + + if (!skb) + return NULL; + + skb_reserve(skb, ieee->tx_headroom); + + hdr = (struct ieee80211_assoc_request_frame *) + skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2); + + + hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ; + hdr->header.duration_id= 37; //FIXME + memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN); + memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN); + + memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John + + hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS); + if (beacon->capability & WLAN_CAPABILITY_PRIVACY ) + hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); + + if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here + + if(ieee->short_slot) + hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); + if (wmm_info_len) //QOS + hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS); + + hdr->listen_interval = 0xa; //FIXME + + hdr->info_element[0].id = MFIE_TYPE_SSID; + + hdr->info_element[0].len = beacon->ssid_len; + tag = skb_put(skb, beacon->ssid_len); + memcpy(tag, beacon->ssid, beacon->ssid_len); + + tag = skb_put(skb, rate_len); + + ieee80211_MFIE_Brate(ieee, &tag); + ieee80211_MFIE_Grate(ieee, &tag); + // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14. + if( beacon->bCkipSupported ) + { + static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client" + u8 CcxAironetBuf[30]; + OCTET_STRING osCcxAironetIE; + + memset(CcxAironetBuf, 0,30); + osCcxAironetIE.Octet = CcxAironetBuf; + osCcxAironetIE.Length = sizeof(CcxAironetBuf); + // + // Ref. CCX test plan v3.61, 3.2.3.1 step 13. + // We want to make the device type as "4500-client". 060926, by CCW. + // + memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui)); + + // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23): + // "The CKIP negotiation is started with the associate request from the client to the access point, + // containing an Aironet element with both the MIC and KP bits set." + osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ; + tag = skb_put(skb, ckip_ie_len); + *tag++ = MFIE_TYPE_AIRONET; + *tag++ = osCcxAironetIE.Length; + memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length); + tag += osCcxAironetIE.Length; + } + + if(beacon->bCcxRmEnable) + { + static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00}; + OCTET_STRING osCcxRmCap; + + osCcxRmCap.Octet = CcxRmCapBuf; + osCcxRmCap.Length = sizeof(CcxRmCapBuf); + tag = skb_put(skb,ccxrm_ie_len); + *tag++ = MFIE_TYPE_GENERIC; + *tag++ = osCcxRmCap.Length; + memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length); + tag += osCcxRmCap.Length; + } + + if( beacon->BssCcxVerNumber >= 2 ) + { + u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00}; + OCTET_STRING osCcxVerNum; + CcxVerNumBuf[4] = beacon->BssCcxVerNumber; + osCcxVerNum.Octet = CcxVerNumBuf; + osCcxVerNum.Length = sizeof(CcxVerNumBuf); + tag = skb_put(skb,cxvernum_ie_len); + *tag++ = MFIE_TYPE_GENERIC; + *tag++ = osCcxVerNum.Length; + memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length); + tag += osCcxVerNum.Length; + } + //HT cap element + if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){ + if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC) + { + tag = skb_put(skb, ht_cap_len); + *tag++ = MFIE_TYPE_HT_CAP; + *tag++ = ht_cap_len - 2; + memcpy(tag, ht_cap_buf,ht_cap_len -2); + tag += ht_cap_len -2; + } + } + + + //choose what wpa_supplicant gives to associate. + tag = skb_put(skb, wpa_ie_len); + if (wpa_ie_len){ + memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len); + } + + tag = skb_put(skb,wmm_info_len); + if(wmm_info_len) { + ieee80211_WMM_Info(ieee, &tag); + } +#ifdef THOMAS_TURBO + tag = skb_put(skb,turbo_info_len); + if(turbo_info_len) { + ieee80211_TURBO_Info(ieee, &tag); + } +#endif + + if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){ + if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC) + { + tag = skb_put(skb, ht_cap_len); + *tag++ = MFIE_TYPE_GENERIC; + *tag++ = ht_cap_len - 2; + memcpy(tag, ht_cap_buf,ht_cap_len - 2); + tag += ht_cap_len -2; + } + + if(ieee->pHTInfo->bCurrentRT2RTAggregation){ + tag = skb_put(skb, realtek_ie_len); + *tag++ = MFIE_TYPE_GENERIC; + *tag++ = realtek_ie_len - 2; + memcpy(tag, realtek_ie_buf,realtek_ie_len -2 ); + } + } +// printk("<=====%s(), %p, %p\n", __FUNCTION__, ieee->dev, ieee->dev->dev_addr); +// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len); + return skb; +} + +void ieee80211_associate_abort(struct ieee80211_device *ieee) +{ + + unsigned long flags; + spin_lock_irqsave(&ieee->lock, flags); + + ieee->associate_seq++; + + /* don't scan, and avoid to have the RX path possibily + * try again to associate. Even do not react to AUTH or + * ASSOC response. Just wait for the retry wq to be scheduled. + * Here we will check if there are good nets to associate + * with, so we retry or just get back to NO_LINK and scanning + */ + if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){ + IEEE80211_DEBUG_MGMT("Authentication failed\n"); + ieee->softmac_stats.no_auth_rs++; + }else{ + IEEE80211_DEBUG_MGMT("Association failed\n"); + ieee->softmac_stats.no_ass_rs++; + } + + ieee->state = IEEE80211_ASSOCIATING_RETRY; + + queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \ + IEEE80211_SOFTMAC_ASSOC_RETRY_TIME); + + spin_unlock_irqrestore(&ieee->lock, flags); +} + +void ieee80211_associate_abort_cb(unsigned long dev) +{ + ieee80211_associate_abort((struct ieee80211_device *) dev); +} + + +void ieee80211_associate_step1(struct ieee80211_device *ieee) +{ + struct ieee80211_network *beacon = &ieee->current_network; + struct sk_buff *skb; + + IEEE80211_DEBUG_MGMT("Stopping scan\n"); + + ieee->softmac_stats.tx_auth_rq++; + skb=ieee80211_authentication_req(beacon, ieee, 0); + + if (!skb) + ieee80211_associate_abort(ieee); + else{ + ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ; + IEEE80211_DEBUG_MGMT("Sending authentication request\n"); + //printk(KERN_WARNING "Sending authentication request\n"); + softmac_mgmt_xmit(skb, ieee); + //BUGON when you try to add_timer twice, using mod_timer may be better, john0709 + if(!timer_pending(&ieee->associate_timer)){ + ieee->associate_timer.expires = jiffies + (HZ / 2); + add_timer(&ieee->associate_timer); + } + //dev_kfree_skb_any(skb);//edit by thomas + } +} + +void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) +{ + u8 *c; + struct sk_buff *skb; + struct ieee80211_network *beacon = &ieee->current_network; +// int hlen = sizeof(struct ieee80211_authentication); + + ieee->associate_seq++; + ieee->softmac_stats.tx_auth_rq++; + + skb = ieee80211_authentication_req(beacon, ieee, chlen+2); + if (!skb) + ieee80211_associate_abort(ieee); + else{ + c = skb_put(skb, chlen+2); + *(c++) = MFIE_TYPE_CHALLENGE; + *(c++) = chlen; + memcpy(c, challenge, chlen); + + IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n"); + + ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr )); + + softmac_mgmt_xmit(skb, ieee); + mod_timer(&ieee->associate_timer, jiffies + (HZ/2)); + //dev_kfree_skb_any(skb);//edit by thomas + } + kfree(challenge); +} + +void ieee80211_associate_step2(struct ieee80211_device *ieee) +{ + struct sk_buff* skb; + struct ieee80211_network *beacon = &ieee->current_network; + + del_timer_sync(&ieee->associate_timer); + + IEEE80211_DEBUG_MGMT("Sending association request\n"); + + ieee->softmac_stats.tx_ass_rq++; + skb=ieee80211_association_req(beacon, ieee); + if (!skb) + ieee80211_associate_abort(ieee); + else{ + softmac_mgmt_xmit(skb, ieee); + mod_timer(&ieee->associate_timer, jiffies + (HZ/2)); + //dev_kfree_skb_any(skb);//edit by thomas + } +} +void ieee80211_associate_complete_wq(struct work_struct *work) +{ + struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq); + printk(KERN_INFO "Associated successfully\n"); + if(ieee80211_is_54g(ieee->current_network) && + (ieee->modulation & IEEE80211_OFDM_MODULATION)){ + + ieee->rate = 108; + printk(KERN_INFO"Using G rates:%d\n", ieee->rate); + }else{ + ieee->rate = 22; + printk(KERN_INFO"Using B rates:%d\n", ieee->rate); + } + if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT) + { + printk("Successfully associated, ht enabled\n"); + HTOnAssocRsp(ieee); + } + else + { + printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT); + memset(ieee->dot11HTOperationalRateSet, 0, 16); + //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + } + ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500); + // To prevent the immediately calling watch_dog after association. + if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 ) + { + ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1; + ieee->LinkDetectInfo.NumRecvDataInPeriod= 1; + } + ieee->link_change(ieee->dev); + if(ieee->is_silent_reset == 0){ + printk("============>normal associate\n"); + notify_wx_assoc_event(ieee); + } + else if(ieee->is_silent_reset == 1) + { + printk("==================>silent reset associate\n"); + ieee->is_silent_reset = 0; + } + + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + netif_carrier_on(ieee->dev); +} + +void ieee80211_associate_complete(struct ieee80211_device *ieee) +{ +// int i; +// struct net_device* dev = ieee->dev; + del_timer_sync(&ieee->associate_timer); + + ieee->state = IEEE80211_LINKED; + //ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet); + queue_work(ieee->wq, &ieee->associate_complete_wq); +} + +void ieee80211_associate_procedure_wq(struct work_struct *work) +{ + struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq); + ieee->sync_scan_hurryup = 1; + down(&ieee->wx_sem); + + if (ieee->data_hard_stop) + ieee->data_hard_stop(ieee->dev); + + ieee80211_stop_scan(ieee); + printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel); + //ieee->set_chan(ieee->dev, ieee->current_network.channel); + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + + ieee->associate_seq = 1; + ieee80211_associate_step1(ieee); + + up(&ieee->wx_sem); +} + +inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net) +{ + u8 tmp_ssid[IW_ESSID_MAX_SIZE+1]; + int tmp_ssid_len = 0; + + short apset,ssidset,ssidbroad,apmatch,ssidmatch; + + /* we are interested in new new only if we are not associated + * and we are not associating / authenticating + */ + if (ieee->state != IEEE80211_NOLINK) + return; + + if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS)) + return; + + if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS)) + return; + + + if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){ + /* if the user specified the AP MAC, we need also the essid + * This could be obtained by beacons or, if the network does not + * broadcast it, it can be put manually. + */ + apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 ); + ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0'; + ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0'); + apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0); + ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\ + (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len)); + + + if ( /* if the user set the AP check if match. + * if the network does not broadcast essid we check the user supplyed ANY essid + * if the network does broadcast and the user does not set essid it is OK + * if the network does broadcast and the user did set essid chech if essid match + */ + ( apset && apmatch && + ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) || + /* if the ap is not set, check that the user set the bssid + * and the network does bradcast and that those two bssid matches + */ + (!apset && ssidset && ssidbroad && ssidmatch) + ){ + /* if the essid is hidden replace it with the + * essid provided by the user. + */ + if (!ssidbroad){ + strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE); + tmp_ssid_len = ieee->current_network.ssid_len; + } + memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network)); + + if (!ssidbroad){ + strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE); + ieee->current_network.ssid_len = tmp_ssid_len; + } + printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d\n",ieee->current_network.ssid,ieee->current_network.channel, ieee->current_network.qos_data.supported, ieee->pHTInfo->bEnableHT, ieee->current_network.bssht.bdSupportHT); + + //ieee->pHTInfo->IOTAction = 0; + HTResetIOTSetting(ieee->pHTInfo); + if (ieee->iw_mode == IW_MODE_INFRA){ + /* Join the network for the first time */ + ieee->AsocRetryCount = 0; + //for HT by amy 080514 + if((ieee->current_network.qos_data.supported == 1) && + // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT)) + ieee->current_network.bssht.bdSupportHT) +/*WB, 2008.09.09:bCurrentHTSupport and bEnableHT two flags are going to put together to check whether we are in HT now, so needn't to check bEnableHT flags here. That's is to say we will set to HT support whenever joined AP has the ability to support HT. And whether we are in HT or not, please check bCurrentHTSupport&&bEnableHT now please.*/ + { + // ieee->pHTInfo->bCurrentHTSupport = true; + HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network)); + } + else + { + ieee->pHTInfo->bCurrentHTSupport = false; + } + + ieee->state = IEEE80211_ASSOCIATING; + queue_work(ieee->wq, &ieee->associate_procedure_wq); + }else{ + if(ieee80211_is_54g(ieee->current_network) && + (ieee->modulation & IEEE80211_OFDM_MODULATION)){ + ieee->rate = 108; + ieee->SetWirelessMode(ieee->dev, IEEE_G); + printk(KERN_INFO"Using G rates\n"); + }else{ + ieee->rate = 22; + ieee->SetWirelessMode(ieee->dev, IEEE_B); + printk(KERN_INFO"Using B rates\n"); + } + memset(ieee->dot11HTOperationalRateSet, 0, 16); + //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + ieee->state = IEEE80211_LINKED; + } + + } + } + +} + +void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee) +{ + unsigned long flags; + struct ieee80211_network *target; + + spin_lock_irqsave(&ieee->lock, flags); + + list_for_each_entry(target, &ieee->network_list, list) { + + /* if the state become different that NOLINK means + * we had found what we are searching for + */ + + if (ieee->state != IEEE80211_NOLINK) + break; + + if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies)) + ieee80211_softmac_new_net(ieee, target); + } + + spin_unlock_irqrestore(&ieee->lock, flags); + +} + + +static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen) +{ + struct ieee80211_authentication *a; + u8 *t; + if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){ + IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len); + return 0xcafe; + } + *challenge = NULL; + a = (struct ieee80211_authentication*) skb->data; + if(skb->len > (sizeof(struct ieee80211_authentication) +3)){ + t = skb->data + sizeof(struct ieee80211_authentication); + + if(*(t++) == MFIE_TYPE_CHALLENGE){ + *chlen = *(t++); + *challenge = (u8*)kmalloc(*chlen, GFP_ATOMIC); + memcpy(*challenge, t, *chlen); + } + } + + return cpu_to_le16(a->status); + +} + + +int auth_rq_parse(struct sk_buff *skb,u8* dest) +{ + struct ieee80211_authentication *a; + + if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){ + IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len); + return -1; + } + a = (struct ieee80211_authentication*) skb->data; + + memcpy(dest,a->header.addr2, ETH_ALEN); + + if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN) + return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; + + return WLAN_STATUS_SUCCESS; +} + +static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src) +{ + u8 *tag; + u8 *skbend; + u8 *ssid=NULL; + u8 ssidlen = 0; + + struct ieee80211_hdr_3addr *header = + (struct ieee80211_hdr_3addr *) skb->data; + + if (skb->len < sizeof (struct ieee80211_hdr_3addr )) + return -1; /* corrupted */ + + memcpy(src,header->addr2, ETH_ALEN); + + skbend = (u8*)skb->data + skb->len; + + tag = skb->data + sizeof (struct ieee80211_hdr_3addr ); + + while (tag+1 < skbend){ + if (*tag == 0){ + ssid = tag+2; + ssidlen = *(tag+1); + break; + } + tag++; /* point to the len field */ + tag = tag + *(tag); /* point to the last data byte of the tag */ + tag++; /* point to the next tag */ + } + + //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src)); + if (ssidlen == 0) return 1; + + if (!ssid) return 1; /* ssid not found in tagged param */ + return (!strncmp(ssid, ieee->current_network.ssid, ssidlen)); + +} + +int assoc_rq_parse(struct sk_buff *skb,u8* dest) +{ + struct ieee80211_assoc_request_frame *a; + + if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) - + sizeof(struct ieee80211_info_element))) { + + IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len); + return -1; + } + + a = (struct ieee80211_assoc_request_frame*) skb->data; + + memcpy(dest,a->header.addr2,ETH_ALEN); + + return 0; +} + +static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid) +{ + struct ieee80211_assoc_response_frame *response_head; + u16 status_code; + + if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){ + IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len); + return 0xcafe; + } + + response_head = (struct ieee80211_assoc_response_frame*) skb->data; + *aid = le16_to_cpu(response_head->aid) & 0x3fff; + + status_code = le16_to_cpu(response_head->status); + if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \ + status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&& + ((ieee->mode == IEEE_G) && + (ieee->current_network.mode == IEEE_N_24G) && + (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) { + ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE; + }else { + ieee->AsocRetryCount = 0; + } + + return le16_to_cpu(response_head->status); +} + +static inline void +ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb) +{ + u8 dest[ETH_ALEN]; + + //IEEE80211DMESG("Rx probe"); + ieee->softmac_stats.rx_probe_rq++; + //DMESG("Dest is "MACSTR, MAC2STR(dest)); + if (probe_rq_parse(ieee, skb, dest)){ + //IEEE80211DMESG("Was for me!"); + ieee->softmac_stats.tx_probe_rs++; + ieee80211_resp_to_probe(ieee, dest); + } +} + +static inline void +ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb) +{ + u8 dest[ETH_ALEN]; + int status; + //IEEE80211DMESG("Rx probe"); + ieee->softmac_stats.rx_auth_rq++; + + if ((status = auth_rq_parse(skb, dest))!= -1){ + ieee80211_resp_to_auth(ieee, status, dest); + } + //DMESG("Dest is "MACSTR, MAC2STR(dest)); + +} + +static inline void +ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb) +{ + + u8 dest[ETH_ALEN]; + //unsigned long flags; + + ieee->softmac_stats.rx_ass_rq++; + if (assoc_rq_parse(skb,dest) != -1){ + ieee80211_resp_to_assoc_rq(ieee, dest); + } + + printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest)); + //FIXME +} + + + +void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr) +{ + + struct sk_buff *buf = ieee80211_null_func(ieee, pwr); + + if (buf) + softmac_ps_mgmt_xmit(buf, ieee); + +} + + +short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l) +{ + int timeout = ieee->ps_timeout; + u8 dtim; + /*if(ieee->ps == IEEE80211_PS_DISABLED || + ieee->iw_mode != IW_MODE_INFRA || + ieee->state != IEEE80211_LINKED) + + return 0; + */ + dtim = ieee->current_network.dtim_data; + //printk("DTIM\n"); + if(!(dtim & IEEE80211_DTIM_VALID)) + return 0; + timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval + //printk("VALID\n"); + ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID; + + if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps)) + return 2; + + if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))) + return 0; + + if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))) + return 0; + + if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) && + (ieee->mgmt_queue_tail != ieee->mgmt_queue_head)) + return 0; + + if(time_l){ + *time_l = ieee->current_network.last_dtim_sta_time[0] + + (ieee->current_network.beacon_interval + * ieee->current_network.dtim_period) * 1000; + } + + if(time_h){ + *time_h = ieee->current_network.last_dtim_sta_time[1]; + if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0]) + *time_h += 1; + } + + return 1; + + +} + +inline void ieee80211_sta_ps(struct ieee80211_device *ieee) +{ + + u32 th,tl; + short sleep; + + unsigned long flags,flags2; + + spin_lock_irqsave(&ieee->lock, flags); + + if((ieee->ps == IEEE80211_PS_DISABLED || + ieee->iw_mode != IW_MODE_INFRA || + ieee->state != IEEE80211_LINKED)){ + + // #warning CHECK_LOCK_HERE + spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); + + ieee80211_sta_wakeup(ieee, 1); + + spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); + } + + sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl); + /* 2 wake, 1 sleep, 0 do nothing */ + if(sleep == 0) + goto out; + + if(sleep == 1){ + + if(ieee->sta_sleep == 1) + ieee->enter_sleep_state(ieee->dev,th,tl); + + else if(ieee->sta_sleep == 0){ + // printk("send null 1\n"); + spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); + + if(ieee->ps_is_queue_empty(ieee->dev)){ + + + ieee->sta_sleep = 2; + + ieee->ps_request_tx_ack(ieee->dev); + + ieee80211_sta_ps_send_null_frame(ieee,1); + + ieee->ps_th = th; + ieee->ps_tl = tl; + } + spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); + + } + + + }else if(sleep == 2){ +//#warning CHECK_LOCK_HERE + spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); + + ieee80211_sta_wakeup(ieee,1); + + spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); + } + +out: + spin_unlock_irqrestore(&ieee->lock, flags); + +} + +void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl) +{ + if(ieee->sta_sleep == 0){ + if(nl){ + printk("Warning: driver is probably failing to report TX ps error\n"); + ieee->ps_request_tx_ack(ieee->dev); + ieee80211_sta_ps_send_null_frame(ieee, 0); + } + return; + + } + + if(ieee->sta_sleep == 1) + ieee->sta_wake_up(ieee->dev); + + ieee->sta_sleep = 0; + + if(nl){ + ieee->ps_request_tx_ack(ieee->dev); + ieee80211_sta_ps_send_null_frame(ieee, 0); + } +} + +void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success) +{ + unsigned long flags,flags2; + + spin_lock_irqsave(&ieee->lock, flags); + + if(ieee->sta_sleep == 2){ + /* Null frame with PS bit set */ + if(success){ + ieee->sta_sleep = 1; + ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl); + } + /* if the card report not success we can't be sure the AP + * has not RXed so we can't assume the AP believe us awake + */ + } + /* 21112005 - tx again null without PS bit if lost */ + else { + + if((ieee->sta_sleep == 0) && !success){ + spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); + ieee80211_sta_ps_send_null_frame(ieee, 0); + spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); + } + } + spin_unlock_irqrestore(&ieee->lock, flags); +} +void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb) +{ + struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data; + u8* act = ieee80211_get_payload(header); + u8 tmp = 0; +// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + if (act == NULL) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n"); + return; + } + tmp = *act; + act ++; + switch (tmp) + { + case ACT_CAT_BA: + if (*act == ACT_ADDBAREQ) + ieee80211_rx_ADDBAReq(ieee, skb); + else if (*act == ACT_ADDBARSP) + ieee80211_rx_ADDBARsp(ieee, skb); + else if (*act == ACT_DELBA) + ieee80211_rx_DELBA(ieee, skb); + break; + default: +// if (net_ratelimit()) +// IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp); + break; + } + return; + +} +inline int +ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, + struct ieee80211_rx_stats *rx_stats, u16 type, + u16 stype) +{ + struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data; + u16 errcode; + u8* challenge; + int chlen=0; + int aid; + struct ieee80211_assoc_response_frame *assoc_resp; +// struct ieee80211_info_element *info_element; + bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode + + if(!ieee->proto_started) + return 0; + + if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED && + ieee->iw_mode == IW_MODE_INFRA && + ieee->state == IEEE80211_LINKED)) + + tasklet_schedule(&ieee->ps_task); + + if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP && + WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON) + ieee->last_rx_ps_time = jiffies; + + switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { + + case IEEE80211_STYPE_ASSOC_RESP: + case IEEE80211_STYPE_REASSOC_RESP: + + IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n", + WLAN_FC_GET_STYPE(header->frame_ctl)); + if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && + ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED && + ieee->iw_mode == IW_MODE_INFRA){ + struct ieee80211_network network_resp; + struct ieee80211_network *network = &network_resp; + + if (0 == (errcode=assoc_parse(ieee,skb, &aid))){ + ieee->state=IEEE80211_LINKED; + ieee->assoc_id = aid; + ieee->softmac_stats.rx_ass_ok++; + /* station support qos */ + /* Let the register setting defaultly with Legacy station */ + if(ieee->qos_support) { + assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data; + memset(network, 0, sizeof(*network)); + if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\ + rx_stats->len - sizeof(*assoc_resp),\ + network,rx_stats)){ + return 1; + } + else + { //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network. + memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen); + memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen); + } + if (ieee->handle_assoc_response != NULL) + ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network); + } + ieee80211_associate_complete(ieee); + } else { + /* aid could not been allocated */ + ieee->softmac_stats.rx_ass_err++; + printk( + "Association response status code 0x%x\n", + errcode); + IEEE80211_DEBUG_MGMT( + "Association response status code 0x%x\n", + errcode); + if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) { + queue_work(ieee->wq, &ieee->associate_procedure_wq); + } else { + ieee80211_associate_abort(ieee); + } + } + } + break; + + case IEEE80211_STYPE_ASSOC_REQ: + case IEEE80211_STYPE_REASSOC_REQ: + + if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && + ieee->iw_mode == IW_MODE_MASTER) + + ieee80211_rx_assoc_rq(ieee, skb); + break; + + case IEEE80211_STYPE_AUTH: + + if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){ + if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING && + ieee->iw_mode == IW_MODE_INFRA){ + + IEEE80211_DEBUG_MGMT("Received authentication response"); + + if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){ + if(ieee->open_wep || !challenge){ + ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED; + ieee->softmac_stats.rx_auth_rs_ok++; + if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE)) + { + if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) + { + // WEP or TKIP encryption + if(IsHTHalfNmodeAPs(ieee)) + { + bSupportNmode = true; + bHalfSupportNmode = true; + } + else + { + bSupportNmode = false; + bHalfSupportNmode = false; + } + printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode); + } + } + /* Dummy wirless mode setting to avoid encryption issue */ + if(bSupportNmode) { + //N mode setting + ieee->SetWirelessMode(ieee->dev, \ + ieee->current_network.mode); + }else{ + //b/g mode setting + /*TODO*/ + ieee->SetWirelessMode(ieee->dev, IEEE_G); + } + + if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true) + { + printk("===============>entern half N mode\n"); + ieee->bHalfWirelessN24GMode = true; + } + else + ieee->bHalfWirelessN24GMode = false; + + ieee80211_associate_step2(ieee); + }else{ + ieee80211_auth_challenge(ieee, challenge, chlen); + } + }else{ + ieee->softmac_stats.rx_auth_rs_err++; + IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode); + ieee80211_associate_abort(ieee); + } + + }else if (ieee->iw_mode == IW_MODE_MASTER){ + ieee80211_rx_auth_rq(ieee, skb); + } + } + break; + + case IEEE80211_STYPE_PROBE_REQ: + + if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) && + ((ieee->iw_mode == IW_MODE_ADHOC || + ieee->iw_mode == IW_MODE_MASTER) && + ieee->state == IEEE80211_LINKED)){ + ieee80211_rx_probe_rq(ieee, skb); + } + break; + + case IEEE80211_STYPE_DISASSOC: + case IEEE80211_STYPE_DEAUTH: + /* FIXME for now repeat all the association procedure + * both for disassociation and deauthentication + */ + if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && + ieee->state == IEEE80211_LINKED && + ieee->iw_mode == IW_MODE_INFRA){ + + ieee->state = IEEE80211_ASSOCIATING; + ieee->softmac_stats.reassoc++; + + notify_wx_assoc_event(ieee); + //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + RemovePeerTS(ieee, header->addr2); + queue_work(ieee->wq, &ieee->associate_procedure_wq); + } + break; + case IEEE80211_STYPE_MANAGE_ACT: + ieee80211_process_action(ieee,skb); + break; + default: + return -1; + break; + } + + //dev_kfree_skb_any(skb); + return 0; +} + +/* following are for a simplier TX queue management. + * Instead of using netif_[stop/wake]_queue the driver + * will uses these two function (plus a reset one), that + * will internally uses the kernel netif_* and takes + * care of the ieee802.11 fragmentation. + * So the driver receives a fragment per time and might + * call the stop function when it want without take care + * to have enought room to TX an entire packet. + * This might be useful if each fragment need it's own + * descriptor, thus just keep a total free memory > than + * the max fragmentation treshold is not enought.. If the + * ieee802.11 stack passed a TXB struct then you needed + * to keep N free descriptors where + * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD + * In this way you need just one and the 802.11 stack + * will take care of buffering fragments and pass them to + * to the driver later, when it wakes the queue. + */ +void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee) +{ + + unsigned int queue_index = txb->queue_index; + unsigned long flags; + int i; + cb_desc *tcb_desc = NULL; + + spin_lock_irqsave(&ieee->lock,flags); + + /* called with 2nd parm 0, no tx mgmt lock required */ + ieee80211_sta_wakeup(ieee,0); + + /* update the tx status */ + ieee->stats.tx_bytes += txb->payload_size; + ieee->stats.tx_packets++; + tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); + if(tcb_desc->bMulticast) { + ieee->stats.multicast++; + } + /* if xmit available, just xmit it immediately, else just insert it to the wait queue */ + for(i = 0; i < txb->nr_frags; i++) { +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) || +#else + if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) || +#endif + (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\ + (ieee->queue_stop)) { + /* insert the skb packet to the wait queue */ + /* as for the completion function, it does not need + * to check it any more. + * */ + //printk("error:no descriptor left@queue_index %d\n", queue_index); + //ieee80211_stop_queue(ieee); +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]); +#else + skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]); +#endif + }else{ + ieee->softmac_data_hard_start_xmit( + txb->fragments[i], + ieee->dev,ieee->rate); + //ieee->stats.tx_packets++; + //ieee->stats.tx_bytes += txb->fragments[i]->len; + //ieee->dev->trans_start = jiffies; + } + } + ieee80211_txb_free(txb); + +//exit: + spin_unlock_irqrestore(&ieee->lock,flags); + +} + +/* called with ieee->lock acquired */ +void ieee80211_resume_tx(struct ieee80211_device *ieee) +{ + int i; + for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) { + + if (ieee->queue_stop){ + ieee->tx_pending.frag = i; + return; + }else{ + + ieee->softmac_data_hard_start_xmit( + ieee->tx_pending.txb->fragments[i], + ieee->dev,ieee->rate); + //(i+1)tx_pending.txb->nr_frags); + ieee->stats.tx_packets++; + ieee->dev->trans_start = jiffies; + } + } + + + ieee80211_txb_free(ieee->tx_pending.txb); + ieee->tx_pending.txb = NULL; +} + + +void ieee80211_reset_queue(struct ieee80211_device *ieee) +{ + unsigned long flags; + + spin_lock_irqsave(&ieee->lock,flags); + init_mgmt_queue(ieee); + if (ieee->tx_pending.txb){ + ieee80211_txb_free(ieee->tx_pending.txb); + ieee->tx_pending.txb = NULL; + } + ieee->queue_stop = 0; + spin_unlock_irqrestore(&ieee->lock,flags); + +} + +void ieee80211_wake_queue(struct ieee80211_device *ieee) +{ + + unsigned long flags; + struct sk_buff *skb; + struct ieee80211_hdr_3addr *header; + + spin_lock_irqsave(&ieee->lock,flags); + if (! ieee->queue_stop) goto exit; + + ieee->queue_stop = 0; + + if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){ + while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){ + + header = (struct ieee80211_hdr_3addr *) skb->data; + + header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + + ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate); + //dev_kfree_skb_any(skb);//edit by thomas + } + } + if (!ieee->queue_stop && ieee->tx_pending.txb) + ieee80211_resume_tx(ieee); + + if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){ + ieee->softmac_stats.swtxawake++; + netif_wake_queue(ieee->dev); + } + +exit : + spin_unlock_irqrestore(&ieee->lock,flags); +} + + +void ieee80211_stop_queue(struct ieee80211_device *ieee) +{ + //unsigned long flags; + //spin_lock_irqsave(&ieee->lock,flags); + + if (! netif_queue_stopped(ieee->dev)){ + netif_stop_queue(ieee->dev); + ieee->softmac_stats.swtxstop++; + } + ieee->queue_stop = 1; + //spin_unlock_irqrestore(&ieee->lock,flags); + +} + + +inline void ieee80211_randomize_cell(struct ieee80211_device *ieee) +{ + + get_random_bytes(ieee->current_network.bssid, ETH_ALEN); + + /* an IBSS cell address must have the two less significant + * bits of the first byte = 2 + */ + ieee->current_network.bssid[0] &= ~0x01; + ieee->current_network.bssid[0] |= 0x02; +} + +/* called in user context only */ +void ieee80211_start_master_bss(struct ieee80211_device *ieee) +{ + ieee->assoc_id = 1; + + if (ieee->current_network.ssid_len == 0){ + strncpy(ieee->current_network.ssid, + IEEE80211_DEFAULT_TX_ESSID, + IW_ESSID_MAX_SIZE); + + ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID); + ieee->ssid_set = 1; + } + + memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN); + + ieee->set_chan(ieee->dev, ieee->current_network.channel); + ieee->state = IEEE80211_LINKED; + ieee->link_change(ieee->dev); + notify_wx_assoc_event(ieee); + + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + + netif_carrier_on(ieee->dev); +} + +void ieee80211_start_monitor_mode(struct ieee80211_device *ieee) +{ + if(ieee->raw_tx){ + + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + + netif_carrier_on(ieee->dev); + } +} +void ieee80211_start_ibss_wq(struct work_struct *work) +{ + + struct delayed_work *dwork = container_of(work, struct delayed_work, work); + struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq); + /* iwconfig mode ad-hoc will schedule this and return + * on the other hand this will block further iwconfig SET + * operations because of the wx_sem hold. + * Anyway some most set operations set a flag to speed-up + * (abort) this wq (when syncro scanning) before sleeping + * on the semaphore + */ + if(!ieee->proto_started){ + printk("==========oh driver down return\n"); + return; + } + down(&ieee->wx_sem); + + if (ieee->current_network.ssid_len == 0){ + strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID); + ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID); + ieee->ssid_set = 1; + } + + /* check if we have this cell in our network list */ + ieee80211_softmac_check_all_nets(ieee); + + +#ifdef ENABLE_DOT11D //if creating an ad-hoc, set its channel to 10 temporarily--this is the requirement for ASUS, not 11D, so disable 11d. +// if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK)) + if (ieee->state == IEEE80211_NOLINK) + ieee->current_network.channel = 6; +#endif + /* if not then the state is not linked. Maybe the user swithced to + * ad-hoc mode just after being in monitor mode, or just after + * being very few time in managed mode (so the card have had no + * time to scan all the chans..) or we have just run up the iface + * after setting ad-hoc mode. So we have to give another try.. + * Here, in ibss mode, should be safe to do this without extra care + * (in bss mode we had to make sure no-one tryed to associate when + * we had just checked the ieee->state and we was going to start the + * scan) beacause in ibss mode the ieee80211_new_net function, when + * finds a good net, just set the ieee->state to IEEE80211_LINKED, + * so, at worst, we waste a bit of time to initiate an unneeded syncro + * scan, that will stop at the first round because it sees the state + * associated. + */ + if (ieee->state == IEEE80211_NOLINK) + ieee80211_start_scan_syncro(ieee); + + /* the network definitively is not here.. create a new cell */ + if (ieee->state == IEEE80211_NOLINK){ + printk("creating new IBSS cell\n"); + if(!ieee->wap_set) + ieee80211_randomize_cell(ieee); + + if(ieee->modulation & IEEE80211_CCK_MODULATION){ + + ieee->current_network.rates_len = 4; + + ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; + ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; + ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; + ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; + + }else + ieee->current_network.rates_len = 0; + + if(ieee->modulation & IEEE80211_OFDM_MODULATION){ + ieee->current_network.rates_ex_len = 8; + + ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; + ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; + ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; + ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; + ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; + ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; + ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; + ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; + + ieee->rate = 108; + }else{ + ieee->current_network.rates_ex_len = 0; + ieee->rate = 22; + } + + // By default, WMM function will be disabled in IBSS mode + ieee->current_network.QoS_Enable = 0; + ieee->SetWirelessMode(ieee->dev, IEEE_G); + ieee->current_network.atim_window = 0; + ieee->current_network.capability = WLAN_CAPABILITY_IBSS; + if(ieee->short_slot) + ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT; + + } + + ieee->state = IEEE80211_LINKED; + + ieee->set_chan(ieee->dev, ieee->current_network.channel); + ieee->link_change(ieee->dev); + + notify_wx_assoc_event(ieee); + + ieee80211_start_send_beacons(ieee); + + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + netif_carrier_on(ieee->dev); + + up(&ieee->wx_sem); +} + +inline void ieee80211_start_ibss(struct ieee80211_device *ieee) +{ + queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150); +} + +/* this is called only in user context, with wx_sem held */ +void ieee80211_start_bss(struct ieee80211_device *ieee) +{ + unsigned long flags; +#ifdef ENABLE_DOT11D + // + // Ref: 802.11d 11.1.3.3 + // STA shall not start a BSS unless properly formed Beacon frame including a Country IE. + // + if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee)) + { + if(! ieee->bGlobalDomain) + { + return; + } + } +#endif + /* check if we have already found the net we + * are interested in (if any). + * if not (we are disassociated and we are not + * in associating / authenticating phase) start the background scanning. + */ + ieee80211_softmac_check_all_nets(ieee); + + /* ensure no-one start an associating process (thus setting + * the ieee->state to ieee80211_ASSOCIATING) while we + * have just cheked it and we are going to enable scan. + * The ieee80211_new_net function is always called with + * lock held (from both ieee80211_softmac_check_all_nets and + * the rx path), so we cannot be in the middle of such function + */ + spin_lock_irqsave(&ieee->lock, flags); + + if (ieee->state == IEEE80211_NOLINK){ + ieee->actscanning = true; + ieee80211_start_scan(ieee); + } + spin_unlock_irqrestore(&ieee->lock, flags); +} + +/* called only in userspace context */ +void ieee80211_disassociate(struct ieee80211_device *ieee) +{ + + + netif_carrier_off(ieee->dev); + if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) + ieee80211_reset_queue(ieee); + + if (ieee->data_hard_stop) + ieee->data_hard_stop(ieee->dev); +#ifdef ENABLE_DOT11D + if(IS_DOT11D_ENABLE(ieee)) + Dot11d_Reset(ieee); +#endif + ieee->state = IEEE80211_NOLINK; + ieee->is_set_key = false; + ieee->link_change(ieee->dev); + //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + notify_wx_assoc_event(ieee); + +} +void ieee80211_associate_retry_wq(struct work_struct *work) +{ + struct delayed_work *dwork = container_of(work, struct delayed_work, work); + struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq); + unsigned long flags; + + down(&ieee->wx_sem); + if(!ieee->proto_started) + goto exit; + + if(ieee->state != IEEE80211_ASSOCIATING_RETRY) + goto exit; + + /* until we do not set the state to IEEE80211_NOLINK + * there are no possibility to have someone else trying + * to start an association procdure (we get here with + * ieee->state = IEEE80211_ASSOCIATING). + * When we set the state to IEEE80211_NOLINK it is possible + * that the RX path run an attempt to associate, but + * both ieee80211_softmac_check_all_nets and the + * RX path works with ieee->lock held so there are no + * problems. If we are still disassociated then start a scan. + * the lock here is necessary to ensure no one try to start + * an association procedure when we have just checked the + * state and we are going to start the scan. + */ + ieee->state = IEEE80211_NOLINK; + + ieee80211_softmac_check_all_nets(ieee); + + spin_lock_irqsave(&ieee->lock, flags); + + if(ieee->state == IEEE80211_NOLINK) + ieee80211_start_scan(ieee); + + spin_unlock_irqrestore(&ieee->lock, flags); + +exit: + up(&ieee->wx_sem); +} + +struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee) +{ + u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff}; + + struct sk_buff *skb; + struct ieee80211_probe_response *b; + + skb = ieee80211_probe_resp(ieee, broadcast_addr); + + if (!skb) + return NULL; + + b = (struct ieee80211_probe_response *) skb->data; + b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON); + + return skb; + +} + +struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee) +{ + struct sk_buff *skb; + struct ieee80211_probe_response *b; + + skb = ieee80211_get_beacon_(ieee); + if(!skb) + return NULL; + + b = (struct ieee80211_probe_response *) skb->data; + b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + + return skb; +} + +void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee) +{ + ieee->sync_scan_hurryup = 1; + down(&ieee->wx_sem); + ieee80211_stop_protocol(ieee); + up(&ieee->wx_sem); +} + + +void ieee80211_stop_protocol(struct ieee80211_device *ieee) +{ + if (!ieee->proto_started) + return; + + ieee->proto_started = 0; + + ieee80211_stop_send_beacons(ieee); + del_timer_sync(&ieee->associate_timer); + cancel_delayed_work(&ieee->associate_retry_wq); + cancel_delayed_work(&ieee->start_ibss_wq); + ieee80211_stop_scan(ieee); + + ieee80211_disassociate(ieee); + RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS +} + +void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee) +{ + ieee->sync_scan_hurryup = 0; + down(&ieee->wx_sem); + ieee80211_start_protocol(ieee); + up(&ieee->wx_sem); +} + +void ieee80211_start_protocol(struct ieee80211_device *ieee) +{ + short ch = 0; + int i = 0; + if (ieee->proto_started) + return; + + ieee->proto_started = 1; + + if (ieee->current_network.channel == 0){ + do{ + ch++; + if (ch > MAX_CHANNEL_NUMBER) + return; /* no channel found */ +#ifdef ENABLE_DOT11D + }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]); +#else + }while(!ieee->channel_map[ch]); +#endif + ieee->current_network.channel = ch; + } + + if (ieee->current_network.beacon_interval == 0) + ieee->current_network.beacon_interval = 100; +// printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel); +// ieee->set_chan(ieee->dev,ieee->current_network.channel); + + for(i = 0; i < 17; i++) { + ieee->last_rxseq_num[i] = -1; + ieee->last_rxfrag_num[i] = -1; + ieee->last_packet_time[i] = 0; + } + + ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers. + + + /* if the user set the MAC of the ad-hoc cell and then + * switch to managed mode, shall we make sure that association + * attempts does not fail just because the user provide the essid + * and the nic is still checking for the AP MAC ?? + */ + if (ieee->iw_mode == IW_MODE_INFRA) + ieee80211_start_bss(ieee); + + else if (ieee->iw_mode == IW_MODE_ADHOC) + ieee80211_start_ibss(ieee); + + else if (ieee->iw_mode == IW_MODE_MASTER) + ieee80211_start_master_bss(ieee); + + else if(ieee->iw_mode == IW_MODE_MONITOR) + ieee80211_start_monitor_mode(ieee); +} + + +#define DRV_NAME "Ieee80211" +void ieee80211_softmac_init(struct ieee80211_device *ieee) +{ + int i; + memset(&ieee->current_network, 0, sizeof(struct ieee80211_network)); + + ieee->state = IEEE80211_NOLINK; + ieee->sync_scan_hurryup = 0; + for(i = 0; i < 5; i++) { + ieee->seq_ctrl[i] = 0; + } +#ifdef ENABLE_DOT11D + ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC); + if (!ieee->pDot11dInfo) + IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n"); + memset(ieee->pDot11dInfo, 0, sizeof(RT_DOT11D_INFO)); +#endif + //added for AP roaming + ieee->LinkDetectInfo.SlotNum = 2; + ieee->LinkDetectInfo.NumRecvBcnInPeriod=0; + ieee->LinkDetectInfo.NumRecvDataInPeriod=0; + + ieee->assoc_id = 0; + ieee->queue_stop = 0; + ieee->scanning = 0; + ieee->softmac_features = 0; //so IEEE2100-like driver are happy + ieee->wap_set = 0; + ieee->ssid_set = 0; + ieee->proto_started = 0; + ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE; + ieee->rate = 22; + ieee->ps = IEEE80211_PS_DISABLED; + ieee->sta_sleep = 0; + ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7 + ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15 + ieee->Regdot11HTOperationalRateSet[4]= 0x01; + //added by amy + ieee->actscanning = false; + ieee->beinretry = false; + ieee->is_set_key = false; + init_mgmt_queue(ieee); + + ieee->sta_edca_param[0] = 0x0000A403; + ieee->sta_edca_param[1] = 0x0000A427; + ieee->sta_edca_param[2] = 0x005E4342; + ieee->sta_edca_param[3] = 0x002F3262; + ieee->aggregation = true; + ieee->enable_rx_imm_BA = 1; + ieee->tx_pending.txb = NULL; + + init_timer(&ieee->associate_timer); + ieee->associate_timer.data = (unsigned long)ieee; + ieee->associate_timer.function = ieee80211_associate_abort_cb; + + init_timer(&ieee->beacon_timer); + ieee->beacon_timer.data = (unsigned long) ieee; + ieee->beacon_timer.function = ieee80211_send_beacon_cb; + +#ifdef PF_SYNCTHREAD + ieee->wq = create_workqueue(DRV_NAME,0); +#else + ieee->wq = create_workqueue(DRV_NAME); +#endif + + INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq); + INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq); + INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq); + INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq); + INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq); + INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq); + + + sema_init(&ieee->wx_sem, 1); + sema_init(&ieee->scan_sem, 1); + + spin_lock_init(&ieee->mgmt_tx_lock); + spin_lock_init(&ieee->beacon_lock); + + tasklet_init(&ieee->ps_task, + (void(*)(unsigned long)) ieee80211_sta_ps, + (unsigned long)ieee); + +} + +void ieee80211_softmac_free(struct ieee80211_device *ieee) +{ + down(&ieee->wx_sem); +#ifdef ENABLE_DOT11D + if(NULL != ieee->pDot11dInfo) + { + kfree(ieee->pDot11dInfo); + ieee->pDot11dInfo = NULL; + } +#endif + del_timer_sync(&ieee->associate_timer); + + cancel_delayed_work(&ieee->associate_retry_wq); + destroy_workqueue(ieee->wq); + + up(&ieee->wx_sem); +} + +/******************************************************** + * Start of WPA code. * + * this is stolen from the ipw2200 driver * + ********************************************************/ + + +static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value) +{ + /* This is called when wpa_supplicant loads and closes the driver + * interface. */ + printk("%s WPA\n",value ? "enabling" : "disabling"); + ieee->wpa_enabled = value; + return 0; +} + + +void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len) +{ + /* make sure WPA is enabled */ + ieee80211_wpa_enable(ieee, 1); + + ieee80211_disassociate(ieee); +} + + +static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason) +{ + + int ret = 0; + + switch (command) { + case IEEE_MLME_STA_DEAUTH: + // silently ignore + break; + + case IEEE_MLME_STA_DISASSOC: + ieee80211_disassociate(ieee); + break; + + default: + printk("Unknown MLME request: %d\n", command); + ret = -EOPNOTSUPP; + } + + return ret; +} + + +static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee, + struct ieee_param *param, int plen) +{ + u8 *buf; + + if (param->u.wpa_ie.len > MAX_WPA_IE_LEN || + (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL)) + return -EINVAL; + + if (param->u.wpa_ie.len) { + buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len); + kfree(ieee->wpa_ie); + ieee->wpa_ie = buf; + ieee->wpa_ie_len = param->u.wpa_ie.len; + } else { + kfree(ieee->wpa_ie); + ieee->wpa_ie = NULL; + ieee->wpa_ie_len = 0; + } + + ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len); + return 0; +} + +#define AUTH_ALG_OPEN_SYSTEM 0x1 +#define AUTH_ALG_SHARED_KEY 0x2 + +static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value) +{ + + struct ieee80211_security sec = { + .flags = SEC_AUTH_MODE, + }; + int ret = 0; + + if (value & AUTH_ALG_SHARED_KEY) { + sec.auth_mode = WLAN_AUTH_SHARED_KEY; + ieee->open_wep = 0; + ieee->auth_mode = 1; + } else if (value & AUTH_ALG_OPEN_SYSTEM){ + sec.auth_mode = WLAN_AUTH_OPEN; + ieee->open_wep = 1; + ieee->auth_mode = 0; + } + else if (value & IW_AUTH_ALG_LEAP){ + sec.auth_mode = WLAN_AUTH_LEAP; + ieee->open_wep = 1; + ieee->auth_mode = 2; + } + + + if (ieee->set_security) + ieee->set_security(ieee->dev, &sec); + //else + // ret = -EOPNOTSUPP; + + return ret; +} + +static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value) +{ + int ret=0; + unsigned long flags; + + switch (name) { + case IEEE_PARAM_WPA_ENABLED: + ret = ieee80211_wpa_enable(ieee, value); + break; + + case IEEE_PARAM_TKIP_COUNTERMEASURES: + ieee->tkip_countermeasures=value; + break; + + case IEEE_PARAM_DROP_UNENCRYPTED: { + /* HACK: + * + * wpa_supplicant calls set_wpa_enabled when the driver + * is loaded and unloaded, regardless of if WPA is being + * used. No other calls are made which can be used to + * determine if encryption will be used or not prior to + * association being expected. If encryption is not being + * used, drop_unencrypted is set to false, else true -- we + * can use this to determine if the CAP_PRIVACY_ON bit should + * be set. + */ + struct ieee80211_security sec = { + .flags = SEC_ENABLED, + .enabled = value, + }; + ieee->drop_unencrypted = value; + /* We only change SEC_LEVEL for open mode. Others + * are set by ipw_wpa_set_encryption. + */ + if (!value) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_0; + } + else { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_1; + } + if (ieee->set_security) + ieee->set_security(ieee->dev, &sec); + break; + } + + case IEEE_PARAM_PRIVACY_INVOKED: + ieee->privacy_invoked=value; + break; + + case IEEE_PARAM_AUTH_ALGS: + ret = ieee80211_wpa_set_auth_algs(ieee, value); + break; + + case IEEE_PARAM_IEEE_802_1X: + ieee->ieee802_1x=value; + break; + case IEEE_PARAM_WPAX_SELECT: + // added for WPA2 mixed mode + spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags); + ieee->wpax_type_set = 1; + ieee->wpax_type_notify = value; + spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags); + break; + + default: + printk("Unknown WPA param: %d\n",name); + ret = -EOPNOTSUPP; + } + + return ret; +} + +/* implementation borrowed from hostap driver */ + +static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, + struct ieee_param *param, int param_len) +{ + int ret = 0; + + struct ieee80211_crypto_ops *ops; + struct ieee80211_crypt_data **crypt; + + struct ieee80211_security sec = { + .flags = 0, + }; + + param->u.crypt.err = 0; + param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; + + if (param_len != + (int) ((char *) param->u.crypt.key - (char *) param) + + param->u.crypt.key_len) { + printk("Len mismatch %d, %d\n", param_len, + param->u.crypt.key_len); + return -EINVAL; + } + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { + if (param->u.crypt.idx >= WEP_KEYS) + return -EINVAL; + crypt = &ieee->crypt[param->u.crypt.idx]; + } else { + return -EINVAL; + } + + if (strcmp(param->u.crypt.alg, "none") == 0) { + if (crypt) { + sec.enabled = 0; + // FIXME FIXME + //sec.encrypt = 0; + sec.level = SEC_LEVEL_0; + sec.flags |= SEC_ENABLED | SEC_LEVEL; + ieee80211_crypt_delayed_deinit(ieee, crypt); + } + goto done; + } + sec.enabled = 1; +// FIXME FIXME +// sec.encrypt = 1; + sec.flags |= SEC_ENABLED; + + /* IPW HW cannot build TKIP MIC, host decryption still needed. */ + if (!(ieee->host_encrypt || ieee->host_decrypt) && + strcmp(param->u.crypt.alg, "TKIP")) + goto skip_host_crypt; + + ops = ieee80211_get_crypto_ops(param->u.crypt.alg); + if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { + request_module("ieee80211_crypt_wep"); + ops = ieee80211_get_crypto_ops(param->u.crypt.alg); + //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place + } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) { + request_module("ieee80211_crypt_tkip"); + ops = ieee80211_get_crypto_ops(param->u.crypt.alg); + } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) { + request_module("ieee80211_crypt_ccmp"); + ops = ieee80211_get_crypto_ops(param->u.crypt.alg); + } + if (ops == NULL) { + printk("unknown crypto alg '%s'\n", param->u.crypt.alg); + param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG; + ret = -EINVAL; + goto done; + } + + if (*crypt == NULL || (*crypt)->ops != ops) { + struct ieee80211_crypt_data *new_crypt; + + ieee80211_crypt_delayed_deinit(ieee, crypt); + + new_crypt = (struct ieee80211_crypt_data *) + kmalloc(sizeof(*new_crypt), GFP_KERNEL); + if (new_crypt == NULL) { + ret = -ENOMEM; + goto done; + } + memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); + new_crypt->ops = ops; + if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) + new_crypt->priv = + new_crypt->ops->init(param->u.crypt.idx); + + if (new_crypt->priv == NULL) { + kfree(new_crypt); + param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED; + ret = -EINVAL; + goto done; + } + + *crypt = new_crypt; + } + + if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key && + (*crypt)->ops->set_key(param->u.crypt.key, + param->u.crypt.key_len, param->u.crypt.seq, + (*crypt)->priv) < 0) { + printk("key setting failed\n"); + param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED; + ret = -EINVAL; + goto done; + } + + skip_host_crypt: + if (param->u.crypt.set_tx) { + ieee->tx_keyidx = param->u.crypt.idx; + sec.active_key = param->u.crypt.idx; + sec.flags |= SEC_ACTIVE_KEY; + } else + sec.flags &= ~SEC_ACTIVE_KEY; + + if (param->u.crypt.alg != NULL) { + memcpy(sec.keys[param->u.crypt.idx], + param->u.crypt.key, + param->u.crypt.key_len); + sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len; + sec.flags |= (1 << param->u.crypt.idx); + + if (strcmp(param->u.crypt.alg, "WEP") == 0) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_1; + } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_2; + } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_3; + } + } + done: + if (ieee->set_security) + ieee->set_security(ieee->dev, &sec); + + /* Do not reset port if card is in Managed mode since resetting will + * generate new IEEE 802.11 authentication which may end up in looping + * with IEEE 802.1X. If your hardware requires a reset after WEP + * configuration (for example... Prism2), implement the reset_port in + * the callbacks structures used to initialize the 802.11 stack. */ + if (ieee->reset_on_keychange && + ieee->iw_mode != IW_MODE_INFRA && + ieee->reset_port && + ieee->reset_port(ieee->dev)) { + printk("reset_port failed\n"); + param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED; + return -EINVAL; + } + + return ret; +} + +inline struct sk_buff *ieee80211_disassociate_skb( + struct ieee80211_network *beacon, + struct ieee80211_device *ieee, + u8 asRsn) +{ + struct sk_buff *skb; + struct ieee80211_disassoc *disass; + + skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc)); + if (!skb) + return NULL; + + disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc)); + disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC); + disass->header.duration_id = 0; + + memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN); + memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN); + + disass->reason = asRsn; + return skb; +} + + +void +SendDisassociation( + struct ieee80211_device *ieee, + u8* asSta, + u8 asRsn +) +{ + struct ieee80211_network *beacon = &ieee->current_network; + struct sk_buff *skb; + skb = ieee80211_disassociate_skb(beacon,ieee,asRsn); + if (skb){ + softmac_mgmt_xmit(skb, ieee); + //dev_kfree_skb_any(skb);//edit by thomas + } +} + +int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p) +{ + struct ieee_param *param; + int ret=0; + + down(&ieee->wx_sem); + //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length); + + if (p->length < sizeof(struct ieee_param) || !p->pointer){ + ret = -EINVAL; + goto out; + } + + param = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL); + if (param == NULL){ + ret = -ENOMEM; + goto out; + } + if (copy_from_user(param, p->pointer, p->length)) { + kfree(param); + ret = -EFAULT; + goto out; + } + + switch (param->cmd) { + + case IEEE_CMD_SET_WPA_PARAM: + ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name, + param->u.wpa_param.value); + break; + + case IEEE_CMD_SET_WPA_IE: + ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length); + break; + + case IEEE_CMD_SET_ENCRYPTION: + ret = ieee80211_wpa_set_encryption(ieee, param, p->length); + break; + + case IEEE_CMD_MLME: + ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command, + param->u.mlme.reason_code); + break; + + default: + printk("Unknown WPA supplicant request: %d\n",param->cmd); + ret = -EOPNOTSUPP; + break; + } + + if (ret == 0 && copy_to_user(p->pointer, param, p->length)) + ret = -EFAULT; + + kfree(param); +out: + up(&ieee->wx_sem); + + return ret; +} + +void notify_wx_assoc_event(struct ieee80211_device *ieee) +{ + union iwreq_data wrqu; + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + if (ieee->state == IEEE80211_LINKED) + memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN); + else + memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); + wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL); +} + +EXPORT_SYMBOL(ieee80211_get_beacon); +EXPORT_SYMBOL(ieee80211_wake_queue); +EXPORT_SYMBOL(ieee80211_stop_queue); +EXPORT_SYMBOL(ieee80211_reset_queue); +EXPORT_SYMBOL(ieee80211_softmac_stop_protocol); +EXPORT_SYMBOL(ieee80211_softmac_start_protocol); +EXPORT_SYMBOL(ieee80211_is_shortslot); +EXPORT_SYMBOL(ieee80211_is_54g); +EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl); +EXPORT_SYMBOL(ieee80211_ps_tx_ack); +EXPORT_SYMBOL(ieee80211_softmac_xmit); +EXPORT_SYMBOL(ieee80211_stop_send_beacons); +EXPORT_SYMBOL(notify_wx_assoc_event); +EXPORT_SYMBOL(SendDisassociation); +EXPORT_SYMBOL(ieee80211_disassociate); +EXPORT_SYMBOL(ieee80211_start_send_beacons); +EXPORT_SYMBOL(ieee80211_stop_scan); +EXPORT_SYMBOL(ieee80211_send_probe_requests); +EXPORT_SYMBOL(ieee80211_softmac_scan_syncro); +EXPORT_SYMBOL(ieee80211_start_scan_syncro); +//EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c new file mode 100644 index 0000000000000000000000000000000000000000..f335c258ba84998703f8ac1b35975768c60d9208 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c @@ -0,0 +1,615 @@ +/* IEEE 802.11 SoftMAC layer + * Copyright (c) 2005 Andrea Merello + * + * Mostly extracted from the rtl8180-sa2400 driver for the + * in-kernel generic ieee802.11 stack. + * + * Some pieces of code might be stolen from ipw2100 driver + * copyright of who own it's copyright ;-) + * + * PS wx handler mostly stolen from hostap, copyright who + * own it's copyright ;-) + * + * released under the GPL + */ + + +#include "ieee80211.h" +#ifdef ENABLE_DOT11D +#include "dot11d.h" +#endif +/* FIXME: add A freqs */ + +const long ieee80211_wlan_frequencies[] = { + 2412, 2417, 2422, 2427, + 2432, 2437, 2442, 2447, + 2452, 2457, 2462, 2467, + 2472, 2484 +}; + + +int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + int ret; + struct iw_freq *fwrq = & wrqu->freq; + + down(&ieee->wx_sem); + + if(ieee->iw_mode == IW_MODE_INFRA){ + ret = -EOPNOTSUPP; + goto out; + } + + /* if setting by freq convert to channel */ + if (fwrq->e == 1) { + if ((fwrq->m >= (int) 2.412e8 && + fwrq->m <= (int) 2.487e8)) { + int f = fwrq->m / 100000; + int c = 0; + + while ((c < 14) && (f != ieee80211_wlan_frequencies[c])) + c++; + + /* hack to fall through */ + fwrq->e = 0; + fwrq->m = c + 1; + } + } + + if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1 ){ + ret = -EOPNOTSUPP; + goto out; + + }else { /* Set the channel */ + +#ifdef ENABLE_DOT11D + if (!(GET_DOT11D_INFO(ieee)->channel_map)[fwrq->m]) { + ret = -EINVAL; + goto out; + } +#endif + ieee->current_network.channel = fwrq->m; + ieee->set_chan(ieee->dev, ieee->current_network.channel); + + if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) + if(ieee->state == IEEE80211_LINKED){ + + ieee80211_stop_send_beacons(ieee); + ieee80211_start_send_beacons(ieee); + } + } + + ret = 0; +out: + up(&ieee->wx_sem); + return ret; +} + + +int ieee80211_wx_get_freq(struct ieee80211_device *ieee, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + struct iw_freq *fwrq = & wrqu->freq; + + if (ieee->current_network.channel == 0) + return -1; + //NM 0.7.0 will not accept channel any more. + fwrq->m = ieee80211_wlan_frequencies[ieee->current_network.channel-1] * 100000; + fwrq->e = 1; +// fwrq->m = ieee->current_network.channel; +// fwrq->e = 0; + + return 0; +} + +int ieee80211_wx_get_wap(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + unsigned long flags; + + wrqu->ap_addr.sa_family = ARPHRD_ETHER; + + if (ieee->iw_mode == IW_MODE_MONITOR) + return -1; + + /* We want avoid to give to the user inconsistent infos*/ + spin_lock_irqsave(&ieee->lock, flags); + + if (ieee->state != IEEE80211_LINKED && + ieee->state != IEEE80211_LINKED_SCANNING && + ieee->wap_set == 0) + + memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); + else + memcpy(wrqu->ap_addr.sa_data, + ieee->current_network.bssid, ETH_ALEN); + + spin_unlock_irqrestore(&ieee->lock, flags); + + return 0; +} + + +int ieee80211_wx_set_wap(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *awrq, + char *extra) +{ + + int ret = 0; + u8 zero[] = {0,0,0,0,0,0}; + unsigned long flags; + + short ifup = ieee->proto_started;//dev->flags & IFF_UP; + struct sockaddr *temp = (struct sockaddr *)awrq; + + ieee->sync_scan_hurryup = 1; + + down(&ieee->wx_sem); + /* use ifconfig hw ether */ + if (ieee->iw_mode == IW_MODE_MASTER){ + ret = -1; + goto out; + } + + if (temp->sa_family != ARPHRD_ETHER){ + ret = -EINVAL; + goto out; + } + + if (ifup) + ieee80211_stop_protocol(ieee); + + /* just to avoid to give inconsistent infos in the + * get wx method. not really needed otherwise + */ + spin_lock_irqsave(&ieee->lock, flags); + + memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN); + ieee->wap_set = memcmp(temp->sa_data, zero,ETH_ALEN)!=0; + + spin_unlock_irqrestore(&ieee->lock, flags); + + if (ifup) + ieee80211_start_protocol(ieee); +out: + up(&ieee->wx_sem); + return ret; +} + + int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b) +{ + int len,ret = 0; + unsigned long flags; + + if (ieee->iw_mode == IW_MODE_MONITOR) + return -1; + + /* We want avoid to give to the user inconsistent infos*/ + spin_lock_irqsave(&ieee->lock, flags); + + if (ieee->current_network.ssid[0] == '\0' || + ieee->current_network.ssid_len == 0){ + ret = -1; + goto out; + } + + if (ieee->state != IEEE80211_LINKED && + ieee->state != IEEE80211_LINKED_SCANNING && + ieee->ssid_set == 0){ + ret = -1; + goto out; + } + len = ieee->current_network.ssid_len; + wrqu->essid.length = len; + strncpy(b,ieee->current_network.ssid,len); + wrqu->essid.flags = 1; + +out: + spin_unlock_irqrestore(&ieee->lock, flags); + + return ret; + +} + +int ieee80211_wx_set_rate(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + u32 target_rate = wrqu->bitrate.value; + + ieee->rate = target_rate/100000; + //FIXME: we might want to limit rate also in management protocols. + return 0; +} + + + +int ieee80211_wx_get_rate(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + u32 tmp_rate; + tmp_rate = TxCountToDataRate(ieee, ieee->softmac_stats.CurrentShowTxate); + + wrqu->bitrate.value = tmp_rate * 500000; + + return 0; +} + + +int ieee80211_wx_set_rts(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + if (wrqu->rts.disabled || !wrqu->rts.fixed) + ieee->rts = DEFAULT_RTS_THRESHOLD; + else + { + if (wrqu->rts.value < MIN_RTS_THRESHOLD || + wrqu->rts.value > MAX_RTS_THRESHOLD) + return -EINVAL; + ieee->rts = wrqu->rts.value; + } + return 0; +} + +int ieee80211_wx_get_rts(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + wrqu->rts.value = ieee->rts; + wrqu->rts.fixed = 0; /* no auto select */ + wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); + return 0; +} +int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + + ieee->sync_scan_hurryup = 1; + + down(&ieee->wx_sem); + + if (wrqu->mode == ieee->iw_mode) + goto out; + + if (wrqu->mode == IW_MODE_MONITOR){ + + ieee->dev->type = ARPHRD_IEEE80211; + }else{ + ieee->dev->type = ARPHRD_ETHER; + } + + if (!ieee->proto_started){ + ieee->iw_mode = wrqu->mode; + }else{ + ieee80211_stop_protocol(ieee); + ieee->iw_mode = wrqu->mode; + ieee80211_start_protocol(ieee); + } + +out: + up(&ieee->wx_sem); + return 0; +} + +void ieee80211_wx_sync_scan_wq(struct work_struct *work) +{ + struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wx_sync_scan_wq); + short chan; + HT_EXTCHNL_OFFSET chan_offset=0; + HT_CHANNEL_WIDTH bandwidth=0; + int b40M = 0; + static int count = 0; + chan = ieee->current_network.channel; + netif_carrier_off(ieee->dev); + + if (ieee->data_hard_stop) + ieee->data_hard_stop(ieee->dev); + + ieee80211_stop_send_beacons(ieee); + + ieee->state = IEEE80211_LINKED_SCANNING; + ieee->link_change(ieee->dev); + ieee->InitialGainHandler(ieee->dev,IG_Backup); + if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && ieee->pHTInfo->bCurBW40MHz) { + b40M = 1; + chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset; + bandwidth = (HT_CHANNEL_WIDTH)ieee->pHTInfo->bCurBW40MHz; + printk("Scan in 40M, force to 20M first:%d, %d\n", chan_offset, bandwidth); + ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + } + ieee80211_start_scan_syncro(ieee); + if (b40M) { + printk("Scan in 20M, back to 40M\n"); + if (chan_offset == HT_EXTCHNL_OFFSET_UPPER) + ieee->set_chan(ieee->dev, chan + 2); + else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER) + ieee->set_chan(ieee->dev, chan - 2); + else + ieee->set_chan(ieee->dev, chan); + ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset); + } else { + ieee->set_chan(ieee->dev, chan); + } + + ieee->InitialGainHandler(ieee->dev,IG_Restore); + ieee->state = IEEE80211_LINKED; + ieee->link_change(ieee->dev); + // To prevent the immediately calling watch_dog after scan. + if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 ) + { + ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1; + ieee->LinkDetectInfo.NumRecvDataInPeriod= 1; + } + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + + if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) + ieee80211_start_send_beacons(ieee); + + netif_carrier_on(ieee->dev); + count = 0; + up(&ieee->wx_sem); + +} + +int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + int ret = 0; + + down(&ieee->wx_sem); + + if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)){ + ret = -1; + goto out; + } + + if ( ieee->state == IEEE80211_LINKED){ + queue_work(ieee->wq, &ieee->wx_sync_scan_wq); + /* intentionally forget to up sem */ + return 0; + } + +out: + up(&ieee->wx_sem); + return ret; +} + +int ieee80211_wx_set_essid(struct ieee80211_device *ieee, + struct iw_request_info *a, + union iwreq_data *wrqu, char *extra) +{ + + int ret=0,len; + short proto_started; + unsigned long flags; + + ieee->sync_scan_hurryup = 1; + down(&ieee->wx_sem); + + proto_started = ieee->proto_started; + + if (wrqu->essid.length > IW_ESSID_MAX_SIZE){ + ret= -E2BIG; + goto out; + } + + if (ieee->iw_mode == IW_MODE_MONITOR){ + ret= -1; + goto out; + } + + if(proto_started) + ieee80211_stop_protocol(ieee); + + + /* this is just to be sure that the GET wx callback + * has consisten infos. not needed otherwise + */ + spin_lock_irqsave(&ieee->lock, flags); + + if (wrqu->essid.flags && wrqu->essid.length) { + //first flush current network.ssid + len = ((wrqu->essid.length-1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length-1) : IW_ESSID_MAX_SIZE; + strncpy(ieee->current_network.ssid, extra, len+1); + ieee->current_network.ssid_len = len+1; + ieee->ssid_set = 1; + } + else{ + ieee->ssid_set = 0; + ieee->current_network.ssid[0] = '\0'; + ieee->current_network.ssid_len = 0; + } + spin_unlock_irqrestore(&ieee->lock, flags); + + if (proto_started) + ieee80211_start_protocol(ieee); +out: + up(&ieee->wx_sem); + return ret; +} + + int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + + wrqu->mode = ieee->iw_mode; + return 0; +} + + int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + int *parms = (int *)extra; + int enable = (parms[0] > 0); + short prev = ieee->raw_tx; + + down(&ieee->wx_sem); + + if(enable) + ieee->raw_tx = 1; + else + ieee->raw_tx = 0; + + printk(KERN_INFO"raw TX is %s\n", + ieee->raw_tx ? "enabled" : "disabled"); + + if(ieee->iw_mode == IW_MODE_MONITOR) + { + if(prev == 0 && ieee->raw_tx){ + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + + netif_carrier_on(ieee->dev); + } + + if(prev && ieee->raw_tx == 1) + netif_carrier_off(ieee->dev); + } + + up(&ieee->wx_sem); + + return 0; +} + +int ieee80211_wx_get_name(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + strcpy(wrqu->name, "802.11"); + if(ieee->modulation & IEEE80211_CCK_MODULATION){ + strcat(wrqu->name, "b"); + if(ieee->modulation & IEEE80211_OFDM_MODULATION) + strcat(wrqu->name, "/g"); + }else if(ieee->modulation & IEEE80211_OFDM_MODULATION) + strcat(wrqu->name, "g"); + if (ieee->mode & (IEEE_N_24G | IEEE_N_5G)) + strcat(wrqu->name, "/n"); + + if((ieee->state == IEEE80211_LINKED) || + (ieee->state == IEEE80211_LINKED_SCANNING)) + strcat(wrqu->name," linked"); + else if(ieee->state != IEEE80211_NOLINK) + strcat(wrqu->name," link.."); + + + return 0; +} + + +/* this is mostly stolen from hostap */ +int ieee80211_wx_set_power(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret = 0; + down(&ieee->wx_sem); + + if (wrqu->power.disabled){ + ieee->ps = IEEE80211_PS_DISABLED; + goto exit; + } + if (wrqu->power.flags & IW_POWER_TIMEOUT) { + //ieee->ps_period = wrqu->power.value / 1000; + ieee->ps_timeout = wrqu->power.value / 1000; + } + + if (wrqu->power.flags & IW_POWER_PERIOD) { + + //ieee->ps_timeout = wrqu->power.value / 1000; + ieee->ps_period = wrqu->power.value / 1000; + //wrq->value / 1024; + + } + switch (wrqu->power.flags & IW_POWER_MODE) { + case IW_POWER_UNICAST_R: + ieee->ps = IEEE80211_PS_UNICAST; + break; + case IW_POWER_MULTICAST_R: + ieee->ps = IEEE80211_PS_MBCAST; + break; + case IW_POWER_ALL_R: + ieee->ps = IEEE80211_PS_UNICAST | IEEE80211_PS_MBCAST; + break; + + case IW_POWER_ON: + // ieee->ps = IEEE80211_PS_DISABLED; + break; + + default: + ret = -EINVAL; + goto exit; + + } +exit: + up(&ieee->wx_sem); + return ret; + +} + +/* this is stolen from hostap */ +int ieee80211_wx_get_power(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret =0; + + down(&ieee->wx_sem); + + if(ieee->ps == IEEE80211_PS_DISABLED){ + wrqu->power.disabled = 1; + goto exit; + } + + wrqu->power.disabled = 0; + + if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { + wrqu->power.flags = IW_POWER_TIMEOUT; + wrqu->power.value = ieee->ps_timeout * 1000; + } else { +// ret = -EOPNOTSUPP; +// goto exit; + wrqu->power.flags = IW_POWER_PERIOD; + wrqu->power.value = ieee->ps_period * 1000; +//ieee->current_network.dtim_period * ieee->current_network.beacon_interval * 1024; + } + + if ((ieee->ps & (IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST)) == (IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST)) + wrqu->power.flags |= IW_POWER_ALL_R; + else if (ieee->ps & IEEE80211_PS_MBCAST) + wrqu->power.flags |= IW_POWER_MULTICAST_R; + else + wrqu->power.flags |= IW_POWER_UNICAST_R; + +exit: + up(&ieee->wx_sem); + return ret; + +} +EXPORT_SYMBOL(ieee80211_wx_get_essid); +EXPORT_SYMBOL(ieee80211_wx_set_essid); +EXPORT_SYMBOL(ieee80211_wx_set_rate); +EXPORT_SYMBOL(ieee80211_wx_get_rate); +EXPORT_SYMBOL(ieee80211_wx_set_wap); +EXPORT_SYMBOL(ieee80211_wx_get_wap); +EXPORT_SYMBOL(ieee80211_wx_set_mode); +EXPORT_SYMBOL(ieee80211_wx_get_mode); +EXPORT_SYMBOL(ieee80211_wx_set_scan); +EXPORT_SYMBOL(ieee80211_wx_get_freq); +EXPORT_SYMBOL(ieee80211_wx_set_freq); +EXPORT_SYMBOL(ieee80211_wx_set_rawtx); +EXPORT_SYMBOL(ieee80211_wx_get_name); +EXPORT_SYMBOL(ieee80211_wx_set_power); +EXPORT_SYMBOL(ieee80211_wx_get_power); +EXPORT_SYMBOL(ieee80211_wlan_frequencies); +EXPORT_SYMBOL(ieee80211_wx_set_rts); +EXPORT_SYMBOL(ieee80211_wx_get_rts); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c new file mode 100644 index 0000000000000000000000000000000000000000..b29c36bac377d005d7308f52c4ad024df2cb1be0 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c @@ -0,0 +1,912 @@ +/****************************************************************************** + + Copyright(c) 2003 - 2004 Intel Corporation. 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 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + James P. Ketrenos + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +****************************************************************************** + + Few modifications for Realtek's Wi-Fi drivers by + Andrea Merello + + A special thanks goes to Realtek for their support ! + +******************************************************************************/ + +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ieee80211.h" + + +/* + + +802.11 Data Frame + + +802.11 frame_contorl for data frames - 2 bytes + ,-----------------------------------------------------------------------------------------. +bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | + |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------| +val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x | + |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------| +desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep | + | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | | + '-----------------------------------------------------------------------------------------' + /\ + | +802.11 Data Frame | + ,--------- 'ctrl' expands to >-----------' + | + ,--'---,-------------------------------------------------------------. +Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | + |------|------|---------|---------|---------|------|---------|------| +Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs | + | | tion | (BSSID) | | | ence | data | | + `--------------------------------------------------| |------' +Total: 28 non-data bytes `----.----' + | + .- 'Frame data' expands to <---------------------------' + | + V + ,---------------------------------------------------. +Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 | + |------|------|---------|----------|------|---------| +Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP | + | DSAP | SSAP | | | | Packet | + | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | | + `-----------------------------------------| | +Total: 8 non-data bytes `----.----' + | + .- 'IP Packet' expands, if WEP enabled, to <--' + | + V + ,-----------------------. +Bytes | 4 | 0-2296 | 4 | + |-----|-----------|-----| +Desc. | IV | Encrypted | ICV | + | | IP Packet | | + `-----------------------' +Total: 8 non-data bytes + + +802.3 Ethernet Data Frame + + ,-----------------------------------------. +Bytes | 6 | 6 | 2 | Variable | 4 | + |-------|-------|------|-----------|------| +Desc. | Dest. | Source| Type | IP Packet | fcs | + | MAC | MAC | | | | + `-----------------------------------------' +Total: 18 non-data bytes + +In the event that fragmentation is required, the incoming payload is split into +N parts of size ieee->fts. The first fragment contains the SNAP header and the +remaining packets are just data. + +If encryption is enabled, each fragment payload size is reduced by enough space +to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP) +So if you have 1500 bytes of payload with ieee->fts set to 500 without +encryption it will take 3 frames. With WEP it will take 4 frames as the +payload of each frame is reduced to 492 bytes. + +* SKB visualization +* +* ,- skb->data +* | +* | ETHERNET HEADER ,-<-- PAYLOAD +* | | 14 bytes from skb->data +* | 2 bytes for Type --> ,T. | (sizeof ethhdr) +* | | | | +* |,-Dest.--. ,--Src.---. | | | +* | 6 bytes| | 6 bytes | | | | +* v | | | | | | +* 0 | v 1 | v | v 2 +* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +* ^ | ^ | ^ | +* | | | | | | +* | | | | `T' <---- 2 bytes for Type +* | | | | +* | | '---SNAP--' <-------- 6 bytes for SNAP +* | | +* `-IV--' <-------------------- 4 bytes for IV (WEP) +* +* SNAP HEADER +* +*/ + +static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; +static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; + +static inline int ieee80211_put_snap(u8 *data, u16 h_proto) +{ + struct ieee80211_snap_hdr *snap; + u8 *oui; + + snap = (struct ieee80211_snap_hdr *)data; + snap->dsap = 0xaa; + snap->ssap = 0xaa; + snap->ctrl = 0x03; + + if (h_proto == 0x8137 || h_proto == 0x80f3) + oui = P802_1H_OUI; + else + oui = RFC1042_OUI; + snap->oui[0] = oui[0]; + snap->oui[1] = oui[1]; + snap->oui[2] = oui[2]; + + *(u16 *)(data + SNAP_SIZE) = htons(h_proto); + + return SNAP_SIZE + sizeof(u16); +} + +int ieee80211_encrypt_fragment( + struct ieee80211_device *ieee, + struct sk_buff *frag, + int hdr_len) +{ + struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx]; + int res; + + if (!(crypt && crypt->ops)) + { + printk("=========>%s(), crypt is null\n", __FUNCTION__); + return -1; + } +#ifdef CONFIG_IEEE80211_CRYPT_TKIP + struct ieee80211_hdr *header; + + if (ieee->tkip_countermeasures && + crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) { + header = (struct ieee80211_hdr *) frag->data; + if (net_ratelimit()) { + printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " + "TX packet to " MAC_FMT "\n", + ieee->dev->name, MAC_ARG(header->addr1)); + } + return -1; + } +#endif + /* To encrypt, frame format is: + * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */ + + // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption. + /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so + * call both MSDU and MPDU encryption functions from here. */ + atomic_inc(&crypt->refcnt); + res = 0; + if (crypt->ops->encrypt_msdu) + res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv); + if (res == 0 && crypt->ops->encrypt_mpdu) + res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); + + atomic_dec(&crypt->refcnt); + if (res < 0) { + printk(KERN_INFO "%s: Encryption failed: len=%d.\n", + ieee->dev->name, frag->len); + ieee->ieee_stats.tx_discards++; + return -1; + } + + return 0; +} + + +void ieee80211_txb_free(struct ieee80211_txb *txb) { + //int i; + if (unlikely(!txb)) + return; + kfree(txb); +} + +struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, + int gfp_mask) +{ + struct ieee80211_txb *txb; + int i; + txb = kmalloc( + sizeof(struct ieee80211_txb) + (sizeof(u8*) * nr_frags), + gfp_mask); + if (!txb) + return NULL; + + memset(txb, 0, sizeof(struct ieee80211_txb)); + txb->nr_frags = nr_frags; + txb->frag_size = txb_size; + + for (i = 0; i < nr_frags; i++) { + txb->fragments[i] = dev_alloc_skb(txb_size); + if (unlikely(!txb->fragments[i])) { + i--; + break; + } + memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb)); + } + if (unlikely(i != nr_frags)) { + while (i >= 0) + dev_kfree_skb_any(txb->fragments[i--]); + kfree(txb); + return NULL; + } + return txb; +} + +// Classify the to-be send data packet +// Need to acquire the sent queue index. +static int +ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network) +{ + struct ethhdr *eth; + struct iphdr *ip; + eth = (struct ethhdr *)skb->data; + if (eth->h_proto != htons(ETH_P_IP)) + return 0; + +// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len); + ip = ip_hdr(skb); + switch (ip->tos & 0xfc) { + case 0x20: + return 2; + case 0x40: + return 1; + case 0x60: + return 3; + case 0x80: + return 4; + case 0xa0: + return 5; + case 0xc0: + return 6; + case 0xe0: + return 7; + default: + return 0; + } +} + +#define SN_LESS(a, b) (((a-b)&0x800)!=0) +void ieee80211_tx_query_agg_cap(struct ieee80211_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + PTX_TS_RECORD pTxTs = NULL; + struct ieee80211_hdr_1addr* hdr = (struct ieee80211_hdr_1addr*)skb->data; + + if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) + return; + if (!IsQoSDataFrame(skb->data)) + return; + + if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1)) + return; + //check packet and mode later +#ifdef TO_DO_LIST + if(pTcb->PacketLength >= 4096) + return; + // For RTL819X, if pairwisekey = wep/tkip, we don't aggrregation. + if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter)) + return; +#endif + if(!ieee->GetNmodeSupportBySecCfg(ieee->dev)) + { + return; + } + if(pHTInfo->bCurrentAMPDUEnable) + { + if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true)) + { + printk("===>can't get TS\n"); + return; + } + if (pTxTs->TxAdmittedBARecord.bValid == false) + { + TsStartAddBaProcess(ieee, pTxTs); + goto FORCED_AGG_SETTING; + } + else if (pTxTs->bUsingBa == false) + { + if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096)) + pTxTs->bUsingBa = true; + else + goto FORCED_AGG_SETTING; + } + + if (ieee->iw_mode == IW_MODE_INFRA) + { + tcb_desc->bAMPDUEnable = true; + tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor; + tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity; + } + } +FORCED_AGG_SETTING: + switch(pHTInfo->ForcedAMPDUMode ) + { + case HT_AGG_AUTO: + break; + + case HT_AGG_FORCE_ENABLE: + tcb_desc->bAMPDUEnable = true; + tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity; + tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor; + break; + + case HT_AGG_FORCE_DISABLE: + tcb_desc->bAMPDUEnable = false; + tcb_desc->ampdu_density = 0; + tcb_desc->ampdu_factor = 0; + break; + + } + return; +} + +extern void ieee80211_qurey_ShortPreambleMode(struct ieee80211_device* ieee, cb_desc* tcb_desc) +{ + tcb_desc->bUseShortPreamble = false; + if (tcb_desc->data_rate == 2) + {//// 1M can only use Long Preamble. 11B spec + return; + } + else if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + { + tcb_desc->bUseShortPreamble = true; + } + return; +} +extern void +ieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, cb_desc *tcb_desc) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + tcb_desc->bUseShortGI = false; + + if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) + return; + + if(pHTInfo->bForcedShortGI) + { + tcb_desc->bUseShortGI = true; + return; + } + + if((pHTInfo->bCurBW40MHz==true) && pHTInfo->bCurShortGI40MHz) + tcb_desc->bUseShortGI = true; + else if((pHTInfo->bCurBW40MHz==false) && pHTInfo->bCurShortGI20MHz) + tcb_desc->bUseShortGI = true; +} + +void ieee80211_query_BandwidthMode(struct ieee80211_device* ieee, cb_desc *tcb_desc) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + tcb_desc->bPacketBW = false; + + if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) + return; + + if(tcb_desc->bMulticast || tcb_desc->bBroadcast) + return; + + if((tcb_desc->data_rate & 0x80)==0) // If using legacy rate, it shall use 20MHz channel. + return; + //BandWidthAutoSwitch is for auto switch to 20 or 40 in long distance + if(pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz) + tcb_desc->bPacketBW = true; + return; +} + +void ieee80211_query_protectionmode(struct ieee80211_device* ieee, cb_desc* tcb_desc, struct sk_buff* skb) +{ + // Common Settings + tcb_desc->bRTSSTBC = false; + tcb_desc->bRTSUseShortGI = false; // Since protection frames are always sent by legacy rate, ShortGI will never be used. + tcb_desc->bCTSEnable = false; // Most of protection using RTS/CTS + tcb_desc->RTSSC = 0; // 20MHz: Don't care; 40MHz: Duplicate. + tcb_desc->bRTSBW = false; // RTS frame bandwidth is always 20MHz + + if(tcb_desc->bBroadcast || tcb_desc->bMulticast)//only unicast frame will use rts/cts + return; + + if (is_broadcast_ether_addr(skb->data+16)) //check addr3 as infrastructure add3 is DA. + return; + + if (ieee->mode < IEEE_N_24G) //b, g mode + { + // (1) RTS_Threshold is compared to the MPDU, not MSDU. + // (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. + // Other fragments are protected by previous fragment. + // So we only need to check the length of first fragment. + if (skb->len > ieee->rts) + { + tcb_desc->bRTSEnable = true; + tcb_desc->rts_rate = MGN_24M; + } + else if (ieee->current_network.buseprotection) + { + // Use CTS-to-SELF in protection mode. + tcb_desc->bRTSEnable = true; + tcb_desc->bCTSEnable = true; + tcb_desc->rts_rate = MGN_24M; + } + //otherwise return; + return; + } + else + {// 11n High throughput case. + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + while (true) + { + //check ERP protection + if (ieee->current_network.buseprotection) + {// CTS-to-SELF + tcb_desc->bRTSEnable = true; + tcb_desc->bCTSEnable = true; + tcb_desc->rts_rate = MGN_24M; + break; + } + //check HT op mode + if(pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) + { + u8 HTOpMode = pHTInfo->CurrentOpMode; + if((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) || + (!pHTInfo->bCurBW40MHz && HTOpMode == 3) ) + { + tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. + tcb_desc->bRTSEnable = true; + break; + } + } + //check rts + if (skb->len > ieee->rts) + { + tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. + tcb_desc->bRTSEnable = true; + break; + } + //to do list: check MIMO power save condition. + //check AMPDU aggregation for TXOP + if(tcb_desc->bAMPDUEnable) + { + tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. + // According to 8190 design, firmware sends CF-End only if RTS/CTS is enabled. However, it degrads + // throughput around 10M, so we disable of this mechanism. 2007.08.03 by Emily + tcb_desc->bRTSEnable = false; + break; + } + //check IOT action + if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) + { + tcb_desc->bCTSEnable = true; + tcb_desc->rts_rate = MGN_24M; + tcb_desc->bRTSEnable = true; + break; + } + // Totally no protection case!! + goto NO_PROTECTION; + } + } + // For test , CTS replace with RTS + if( 0 ) + { + tcb_desc->bCTSEnable = true; + tcb_desc->rts_rate = MGN_24M; + tcb_desc->bRTSEnable = true; + } + if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + tcb_desc->bUseShortPreamble = true; + if (ieee->mode == IW_MODE_MASTER) + goto NO_PROTECTION; + return; +NO_PROTECTION: + tcb_desc->bRTSEnable = false; + tcb_desc->bCTSEnable = false; + tcb_desc->rts_rate = 0; + tcb_desc->RTSSC = 0; + tcb_desc->bRTSBW = false; +} + + +void ieee80211_txrate_selectmode(struct ieee80211_device* ieee, cb_desc* tcb_desc) +{ +#ifdef TO_DO_LIST + if(!IsDataFrame(pFrame)) + { + pTcb->bTxDisableRateFallBack = TRUE; + pTcb->bTxUseDriverAssingedRate = TRUE; + pTcb->RATRIndex = 7; + return; + } + + if(pMgntInfo->ForcedDataRate!= 0) + { + pTcb->bTxDisableRateFallBack = TRUE; + pTcb->bTxUseDriverAssingedRate = TRUE; + return; + } +#endif + if(ieee->bTxDisableRateFallBack) + tcb_desc->bTxDisableRateFallBack = true; + + if(ieee->bTxUseDriverAssingedRate) + tcb_desc->bTxUseDriverAssingedRate = true; + if(!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate) + { + if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) + tcb_desc->RATRIndex = 0; + } +} + +void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u8* dst) +{ + if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst)) + return; + if (IsQoSDataFrame(skb->data)) //we deal qos data only + { + PTX_TS_RECORD pTS = NULL; + if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTS), dst, skb->priority, TX_DIR, true)) + { + return; + } + pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096; + } +} + +int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct ieee80211_device *ieee = netdev_priv(dev); + struct ieee80211_txb *txb = NULL; + struct ieee80211_hdr_3addrqos *frag_hdr; + int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; + unsigned long flags; + struct net_device_stats *stats = &ieee->stats; + int ether_type = 0, encrypt; + int bytes, fc, qos_ctl = 0, hdr_len; + struct sk_buff *skb_frag; + struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */ + .duration_id = 0, + .seq_ctl = 0, + .qos_ctl = 0 + }; + u8 dest[ETH_ALEN], src[ETH_ALEN]; + int qos_actived = ieee->current_network.qos_data.active; + + struct ieee80211_crypt_data* crypt; + + cb_desc *tcb_desc; + + spin_lock_irqsave(&ieee->lock, flags); + + /* If there is no driver handler to take the TXB, dont' bother + * creating it... */ + if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))|| + ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { + printk(KERN_WARNING "%s: No xmit handler.\n", + ieee->dev->name); + goto success; + } + + + if(likely(ieee->raw_tx == 0)){ + if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { + printk(KERN_WARNING "%s: skb too small (%d).\n", + ieee->dev->name, skb->len); + goto success; + } + + memset(skb->cb, 0, sizeof(skb->cb)); + ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); + + crypt = ieee->crypt[ieee->tx_keyidx]; + + encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && + ieee->host_encrypt && crypt && crypt->ops; + + if (!encrypt && ieee->ieee802_1x && + ieee->drop_unencrypted && ether_type != ETH_P_PAE) { + stats->tx_dropped++; + goto success; + } + #ifdef CONFIG_IEEE80211_DEBUG + if (crypt && !encrypt && ether_type == ETH_P_PAE) { + struct eapol *eap = (struct eapol *)(skb->data + + sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16)); + IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n", + eap_get_type(eap->type)); + } + #endif + + /* Save source and destination addresses */ + memcpy(&dest, skb->data, ETH_ALEN); + memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN); + + /* Advance the SKB to the start of the payload */ + skb_pull(skb, sizeof(struct ethhdr)); + + /* Determine total amount of storage required for TXB packets */ + bytes = skb->len + SNAP_SIZE + sizeof(u16); + + if (encrypt) + fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_WEP; + else + + fc = IEEE80211_FTYPE_DATA; + + //if(ieee->current_network.QoS_Enable) + if(qos_actived) + fc |= IEEE80211_STYPE_QOS_DATA; + else + fc |= IEEE80211_STYPE_DATA; + + if (ieee->iw_mode == IW_MODE_INFRA) { + fc |= IEEE80211_FCTL_TODS; + /* To DS: Addr1 = BSSID, Addr2 = SA, + Addr3 = DA */ + memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN); + memcpy(&header.addr2, &src, ETH_ALEN); + memcpy(&header.addr3, &dest, ETH_ALEN); + } else if (ieee->iw_mode == IW_MODE_ADHOC) { + /* not From/To DS: Addr1 = DA, Addr2 = SA, + Addr3 = BSSID */ + memcpy(&header.addr1, dest, ETH_ALEN); + memcpy(&header.addr2, src, ETH_ALEN); + memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); + } + + header.frame_ctl = cpu_to_le16(fc); + + /* Determine fragmentation size based on destination (multicast + * and broadcast are not fragmented) */ + if (is_multicast_ether_addr(header.addr1) || + is_broadcast_ether_addr(header.addr1)) { + frag_size = MAX_FRAG_THRESHOLD; + qos_ctl |= QOS_CTL_NOTCONTAIN_ACK; + } + else { + frag_size = ieee->fts;//default:392 + qos_ctl = 0; + } + + //if (ieee->current_network.QoS_Enable) + if(qos_actived) + { + hdr_len = IEEE80211_3ADDR_LEN + 2; + + skb->priority = ieee80211_classify(skb, &ieee->current_network); + qos_ctl |= skb->priority; //set in the ieee80211_classify + header.qos_ctl = cpu_to_le16(qos_ctl & IEEE80211_QOS_TID); + } else { + hdr_len = IEEE80211_3ADDR_LEN; + } + /* Determine amount of payload per fragment. Regardless of if + * this stack is providing the full 802.11 header, one will + * eventually be affixed to this fragment -- so we must account for + * it when determining the amount of payload space. */ + bytes_per_frag = frag_size - hdr_len; + if (ieee->config & + (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) + bytes_per_frag -= IEEE80211_FCS_LEN; + + /* Each fragment may need to have room for encryptiong pre/postfix */ + if (encrypt) + bytes_per_frag -= crypt->ops->extra_prefix_len + + crypt->ops->extra_postfix_len; + + /* Number of fragments is the total bytes_per_frag / + * payload_per_fragment */ + nr_frags = bytes / bytes_per_frag; + bytes_last_frag = bytes % bytes_per_frag; + if (bytes_last_frag) + nr_frags++; + else + bytes_last_frag = bytes_per_frag; + + /* When we allocate the TXB we allocate enough space for the reserve + * and full fragment bytes (bytes_per_frag doesn't include prefix, + * postfix, header, FCS, etc.) */ + txb = ieee80211_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC); + if (unlikely(!txb)) { + printk(KERN_WARNING "%s: Could not allocate TXB\n", + ieee->dev->name); + goto failed; + } + txb->encrypted = encrypt; + txb->payload_size = bytes; + + //if (ieee->current_network.QoS_Enable) + if(qos_actived) + { + txb->queue_index = UP2AC(skb->priority); + } else { + txb->queue_index = WME_AC_BK;; + } + + + + for (i = 0; i < nr_frags; i++) { + skb_frag = txb->fragments[i]; + tcb_desc = (cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE); + if(qos_actived){ + skb_frag->priority = skb->priority;//UP2AC(skb->priority); + tcb_desc->queue_index = UP2AC(skb->priority); + } else { + skb_frag->priority = WME_AC_BK; + tcb_desc->queue_index = WME_AC_BK; + } + skb_reserve(skb_frag, ieee->tx_headroom); + + if (encrypt){ + if (ieee->hwsec_active) + tcb_desc->bHwSec = 1; + else + tcb_desc->bHwSec = 0; + skb_reserve(skb_frag, crypt->ops->extra_prefix_len); + } + else + { + tcb_desc->bHwSec = 0; + } + frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len); + memcpy(frag_hdr, &header, hdr_len); + + /* If this is not the last fragment, then add the MOREFRAGS + * bit to the frame control */ + if (i != nr_frags - 1) { + frag_hdr->frame_ctl = cpu_to_le16( + fc | IEEE80211_FCTL_MOREFRAGS); + bytes = bytes_per_frag; + + } else { + /* The last fragment takes the remaining length */ + bytes = bytes_last_frag; + } + //if(ieee->current_network.QoS_Enable) + if(qos_actived) + { + // add 1 only indicate to corresponding seq number control 2006/7/12 + frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i); + } else { + frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); + } + + /* Put a SNAP header on the first fragment */ + if (i == 0) { + ieee80211_put_snap( + skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), + ether_type); + bytes -= SNAP_SIZE + sizeof(u16); + } + + memcpy(skb_put(skb_frag, bytes), skb->data, bytes); + + /* Advance the SKB... */ + skb_pull(skb, bytes); + + /* Encryption routine will move the header forward in order + * to insert the IV between the header and the payload */ + if (encrypt) + ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); + if (ieee->config & + (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) + skb_put(skb_frag, 4); + } + + if(qos_actived) + { + if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) + ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; + else + ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; + } else { + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + } + }else{ + if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) { + printk(KERN_WARNING "%s: skb too small (%d).\n", + ieee->dev->name, skb->len); + goto success; + } + + txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC); + if(!txb){ + printk(KERN_WARNING "%s: Could not allocate TXB\n", + ieee->dev->name); + goto failed; + } + + txb->encrypted = 0; + txb->payload_size = skb->len; + memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len); + } + + success: +//WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place. + if (txb) + { + cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); + tcb_desc->bTxEnableFwCalcDur = 1; + if (is_multicast_ether_addr(header.addr1)) + tcb_desc->bMulticast = 1; + if (is_broadcast_ether_addr(header.addr1)) + tcb_desc->bBroadcast = 1; + ieee80211_txrate_selectmode(ieee, tcb_desc); + if ( tcb_desc->bMulticast || tcb_desc->bBroadcast) + tcb_desc->data_rate = ieee->basic_rate; + else + //tcb_desc->data_rate = CURRENT_RATE(ieee->current_network.mode, ieee->rate, ieee->HTCurrentOperaRate); + tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate); + ieee80211_qurey_ShortPreambleMode(ieee, tcb_desc); + ieee80211_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); + ieee80211_query_HTCapShortGI(ieee, tcb_desc); + ieee80211_query_BandwidthMode(ieee, tcb_desc); + ieee80211_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); + ieee80211_query_seqnum(ieee, txb->fragments[0], header.addr1); +// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, txb->fragments[0]->data, txb->fragments[0]->len); + //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, tcb_desc, sizeof(cb_desc)); + } + spin_unlock_irqrestore(&ieee->lock, flags); + dev_kfree_skb_any(skb); + if (txb) { + if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){ + ieee80211_softmac_xmit(txb, ieee); + }else{ + if ((*ieee->hard_start_xmit)(txb, dev) == 0) { + stats->tx_packets++; + stats->tx_bytes += txb->payload_size; + return 0; + } + ieee80211_txb_free(txb); + } + } + + return 0; + + failed: + spin_unlock_irqrestore(&ieee->lock, flags); + netif_stop_queue(dev); + stats->tx_errors++; + return 1; + +} + +EXPORT_SYMBOL(ieee80211_txb_free); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c new file mode 100644 index 0000000000000000000000000000000000000000..d397f1d68eb7640668ad05591f0d1908d0d4e957 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c @@ -0,0 +1,878 @@ +/****************************************************************************** + + Copyright(c) 2004 Intel Corporation. All rights reserved. + + Portions of this file are based on the WEP enablement code provided by the + Host AP project hostap-drivers v0.1.3 + Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen + + Copyright (c) 2002-2003, Jouni Malinen + + 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 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + James P. Ketrenos + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +******************************************************************************/ +#include +#include +#include +#include + +#include "ieee80211.h" +struct modes_unit { + char *mode_string; + int mode_size; +}; +struct modes_unit ieee80211_modes[] = { + {"a",1}, + {"b",1}, + {"g",1}, + {"?",1}, + {"N-24G",5}, + {"N-5G",4}, +}; + +#define iwe_stream_add_event_rsl iwe_stream_add_event + +#define MAX_CUSTOM_LEN 64 +static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, + char *start, char *stop, + struct ieee80211_network *network, + struct iw_request_info *info) +{ + char custom[MAX_CUSTOM_LEN]; + char proto_name[IFNAMSIZ]; + char *pname = proto_name; + char *p; + struct iw_event iwe; + int i, j; + u16 max_rate, rate; + static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; + + /* First entry *MUST* be the AP MAC address */ + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN); + start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_ADDR_LEN); + /* Remaining entries will be displayed in the order we provide them */ + + /* Add the ESSID */ + iwe.cmd = SIOCGIWESSID; + iwe.u.data.flags = 1; +// if (network->flags & NETWORK_EMPTY_ESSID) { + if (network->ssid_len == 0) { + iwe.u.data.length = sizeof(""); + start = iwe_stream_add_point(info, start, stop, &iwe, ""); + } else { + iwe.u.data.length = min(network->ssid_len, (u8)32); + start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid); + } + /* Add the protocol name */ + iwe.cmd = SIOCGIWNAME; + for(i=0; i<(sizeof(ieee80211_modes)/sizeof(ieee80211_modes[0])); i++) { + if(network->mode&(1<capability & + (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) { + if (network->capability & WLAN_CAPABILITY_BSS) + iwe.u.mode = IW_MODE_MASTER; + else + iwe.u.mode = IW_MODE_ADHOC; + start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_UINT_LEN); + } + + /* Add frequency/channel */ + iwe.cmd = SIOCGIWFREQ; +/* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode); + iwe.u.freq.e = 3; */ + iwe.u.freq.m = network->channel; + iwe.u.freq.e = 0; + iwe.u.freq.i = 0; + start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_FREQ_LEN); + /* Add encryption capability */ + iwe.cmd = SIOCGIWENCODE; + if (network->capability & WLAN_CAPABILITY_PRIVACY) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + iwe.u.data.length = 0; + start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid); + /* Add basic and extended rates */ + max_rate = 0; + p = custom; + p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): "); + for (i = 0, j = 0; i < network->rates_len; ) { + if (j < network->rates_ex_len && + ((network->rates_ex[j] & 0x7F) < + (network->rates[i] & 0x7F))) + rate = network->rates_ex[j++] & 0x7F; + else + rate = network->rates[i++] & 0x7F; + if (rate > max_rate) + max_rate = rate; + p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), + "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); + } + for (; j < network->rates_ex_len; j++) { + rate = network->rates_ex[j] & 0x7F; + p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), + "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); + if (rate > max_rate) + max_rate = rate; + } + + if (network->mode >= IEEE_N_24G)//add N rate here; + { + PHT_CAPABILITY_ELE ht_cap = NULL; + bool is40M = false, isShortGI = false; + u8 max_mcs = 0; + if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4)) + ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[4]; + else + ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[0]; + is40M = (ht_cap->ChlWidth)?1:0; + isShortGI = (ht_cap->ChlWidth)? + ((ht_cap->ShortGI40Mhz)?1:0): + ((ht_cap->ShortGI20Mhz)?1:0); + + max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL); + rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f]; + if (rate > max_rate) + max_rate = rate; + } + iwe.cmd = SIOCGIWRATE; + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; + iwe.u.bitrate.value = max_rate * 500000; + start = iwe_stream_add_event_rsl(info, start, stop, &iwe, + IW_EV_PARAM_LEN); + iwe.cmd = IWEVCUSTOM; + iwe.u.data.length = p - custom; + if (iwe.u.data.length) + start = iwe_stream_add_point(info, start, stop, &iwe, custom); + /* Add quality statistics */ + /* TODO: Fix these values... */ + iwe.cmd = IWEVQUAL; + iwe.u.qual.qual = network->stats.signal; + iwe.u.qual.level = network->stats.rssi; + iwe.u.qual.noise = network->stats.noise; + iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK; + if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) + iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID; + if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) + iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID; + if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) + iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID; + iwe.u.qual.updated = 7; + start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN); + iwe.cmd = IWEVCUSTOM; + p = custom; + + iwe.u.data.length = p - custom; + if (iwe.u.data.length) + start = iwe_stream_add_point(info, start, stop, &iwe, custom); +#if (WIRELESS_EXT < 18) + if (ieee->wpa_enabled && network->wpa_ie_len){ + char buf[MAX_WPA_IE_LEN * 2 + 30]; + // printk("WPA IE\n"); + u8 *p = buf; + p += sprintf(p, "wpa_ie="); + for (i = 0; i < network->wpa_ie_len; i++) { + p += sprintf(p, "%02x", network->wpa_ie[i]); + } + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + iwe.u.data.length = strlen(buf); + start = iwe_stream_add_point(info, start, stop, &iwe, buf); + } + + if (ieee->wpa_enabled && network->rsn_ie_len){ + char buf[MAX_WPA_IE_LEN * 2 + 30]; + + u8 *p = buf; + p += sprintf(p, "rsn_ie="); + for (i = 0; i < network->rsn_ie_len; i++) { + p += sprintf(p, "%02x", network->rsn_ie[i]); + } + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + iwe.u.data.length = strlen(buf); + start = iwe_stream_add_point(info, start, stop, &iwe, buf); + } +#else + memset(&iwe, 0, sizeof(iwe)); + if (network->wpa_ie_len) + { + char buf[MAX_WPA_IE_LEN]; + memcpy(buf, network->wpa_ie, network->wpa_ie_len); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = network->wpa_ie_len; + start = iwe_stream_add_point(info, start, stop, &iwe, buf); + } + memset(&iwe, 0, sizeof(iwe)); + if (network->rsn_ie_len) + { + char buf[MAX_WPA_IE_LEN]; + memcpy(buf, network->rsn_ie, network->rsn_ie_len); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = network->rsn_ie_len; + start = iwe_stream_add_point(info, start, stop, &iwe, buf); + } +#endif + + + /* Add EXTRA: Age to display seconds since last beacon/probe response + * for given network. */ + iwe.cmd = IWEVCUSTOM; + p = custom; + p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), + " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100)); + iwe.u.data.length = p - custom; + if (iwe.u.data.length) + start = iwe_stream_add_point(info, start, stop, &iwe, custom); + + return start; +} + +int ieee80211_wx_get_scan(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ieee80211_network *network; + unsigned long flags; + + char *ev = extra; +// char *stop = ev + IW_SCAN_MAX_DATA; + char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA; + //char *stop = ev + IW_SCAN_MAX_DATA; + int i = 0; + int err = 0; + IEEE80211_DEBUG_WX("Getting scan\n"); + down(&ieee->wx_sem); + spin_lock_irqsave(&ieee->lock, flags); + + list_for_each_entry(network, &ieee->network_list, list) { + i++; + if((stop-ev)<200) + { + err = -E2BIG; + break; + } + if (ieee->scan_age == 0 || + time_after(network->last_scanned + ieee->scan_age, jiffies)) + ev = rtl819x_translate_scan(ieee, ev, stop, network, info); + else + IEEE80211_DEBUG_SCAN( + "Not showing network '%s (" + MAC_FMT ")' due to age (%lums).\n", + escape_essid(network->ssid, + network->ssid_len), + MAC_ARG(network->bssid), + (jiffies - network->last_scanned) / (HZ / 100)); + } + + spin_unlock_irqrestore(&ieee->lock, flags); + up(&ieee->wx_sem); + wrqu->data.length = ev - extra; + wrqu->data.flags = 0; + + IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i); + + return err; +} + +int ieee80211_wx_set_encode(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *keybuf) +{ + struct iw_point *erq = &(wrqu->encoding); + struct net_device *dev = ieee->dev; + struct ieee80211_security sec = { + .flags = 0 + }; + int i, key, key_provided, len; + struct ieee80211_crypt_data **crypt; + + IEEE80211_DEBUG_WX("SET_ENCODE\n"); + + key = erq->flags & IW_ENCODE_INDEX; + if (key) { + if (key > WEP_KEYS) + return -EINVAL; + key--; + key_provided = 1; + } else { + key_provided = 0; + key = ieee->tx_keyidx; + } + + IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ? + "provided" : "default"); + crypt = &ieee->crypt[key]; + + if (erq->flags & IW_ENCODE_DISABLED) { + if (key_provided && *crypt) { + IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n", + key); + ieee80211_crypt_delayed_deinit(ieee, crypt); + } else + IEEE80211_DEBUG_WX("Disabling encryption.\n"); + + /* Check all the keys to see if any are still configured, + * and if no key index was provided, de-init them all */ + for (i = 0; i < WEP_KEYS; i++) { + if (ieee->crypt[i] != NULL) { + if (key_provided) + break; + ieee80211_crypt_delayed_deinit( + ieee, &ieee->crypt[i]); + } + } + + if (i == WEP_KEYS) { + sec.enabled = 0; + sec.level = SEC_LEVEL_0; + sec.flags |= SEC_ENABLED | SEC_LEVEL; + } + + goto done; + } + + + + sec.enabled = 1; + sec.flags |= SEC_ENABLED; + + if (*crypt != NULL && (*crypt)->ops != NULL && + strcmp((*crypt)->ops->name, "WEP") != 0) { + /* changing to use WEP; deinit previously used algorithm + * on this key */ + ieee80211_crypt_delayed_deinit(ieee, crypt); + } + + if (*crypt == NULL) { + struct ieee80211_crypt_data *new_crypt; + + /* take WEP into use */ + new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data), + GFP_KERNEL); + if (new_crypt == NULL) + return -ENOMEM; + memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); + new_crypt->ops = ieee80211_get_crypto_ops("WEP"); + if (!new_crypt->ops) { + request_module("ieee80211_crypt_wep"); + new_crypt->ops = ieee80211_get_crypto_ops("WEP"); + } + if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) + new_crypt->priv = new_crypt->ops->init(key); + + if (!new_crypt->ops || !new_crypt->priv) { + kfree(new_crypt); + new_crypt = NULL; + + printk(KERN_WARNING "%s: could not initialize WEP: " + "load module ieee80211_crypt_wep\n", + dev->name); + return -EOPNOTSUPP; + } + *crypt = new_crypt; + } + + /* If a new key was provided, set it up */ + if (erq->length > 0) { + len = erq->length <= 5 ? 5 : 13; + memcpy(sec.keys[key], keybuf, erq->length); + if (len > erq->length) + memset(sec.keys[key] + erq->length, 0, + len - erq->length); + IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n", + key, escape_essid(sec.keys[key], len), + erq->length, len); + sec.key_sizes[key] = len; + (*crypt)->ops->set_key(sec.keys[key], len, NULL, + (*crypt)->priv); + sec.flags |= (1 << key); + /* This ensures a key will be activated if no key is + * explicitely set */ + if (key == sec.active_key) + sec.flags |= SEC_ACTIVE_KEY; + ieee->tx_keyidx = key; + + } else { + len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN, + NULL, (*crypt)->priv); + if (len == 0) { + /* Set a default key of all 0 */ + printk("Setting key %d to all zero.\n", + key); + + IEEE80211_DEBUG_WX("Setting key %d to all zero.\n", + key); + memset(sec.keys[key], 0, 13); + (*crypt)->ops->set_key(sec.keys[key], 13, NULL, + (*crypt)->priv); + sec.key_sizes[key] = 13; + sec.flags |= (1 << key); + } + + /* No key data - just set the default TX key index */ + if (key_provided) { + IEEE80211_DEBUG_WX( + "Setting key %d to default Tx key.\n", key); + ieee->tx_keyidx = key; + sec.active_key = key; + sec.flags |= SEC_ACTIVE_KEY; + } + } + + done: + ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED); + ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; + sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; + sec.flags |= SEC_AUTH_MODE; + IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ? + "OPEN" : "SHARED KEY"); + + /* For now we just support WEP, so only set that security level... + * TODO: When WPA is added this is one place that needs to change */ + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */ + + if (ieee->set_security) + ieee->set_security(dev, &sec); + + /* Do not reset port if card is in Managed mode since resetting will + * generate new IEEE 802.11 authentication which may end up in looping + * with IEEE 802.1X. If your hardware requires a reset after WEP + * configuration (for example... Prism2), implement the reset_port in + * the callbacks structures used to initialize the 802.11 stack. */ + if (ieee->reset_on_keychange && + ieee->iw_mode != IW_MODE_INFRA && + ieee->reset_port && ieee->reset_port(dev)) { + printk(KERN_DEBUG "%s: reset_port failed\n", dev->name); + return -EINVAL; + } + return 0; +} + +int ieee80211_wx_get_encode(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *keybuf) +{ + struct iw_point *erq = &(wrqu->encoding); + int len, key; + struct ieee80211_crypt_data *crypt; + + IEEE80211_DEBUG_WX("GET_ENCODE\n"); + + if(ieee->iw_mode == IW_MODE_MONITOR) + return -1; + + key = erq->flags & IW_ENCODE_INDEX; + if (key) { + if (key > WEP_KEYS) + return -EINVAL; + key--; + } else + key = ieee->tx_keyidx; + + crypt = ieee->crypt[key]; + erq->flags = key + 1; + + if (crypt == NULL || crypt->ops == NULL) { + erq->length = 0; + erq->flags |= IW_ENCODE_DISABLED; + return 0; + } + len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv); + erq->length = (len >= 0 ? len : 0); + + erq->flags |= IW_ENCODE_ENABLED; + + if (ieee->open_wep) + erq->flags |= IW_ENCODE_OPEN; + else + erq->flags |= IW_ENCODE_RESTRICTED; + + return 0; +} +#if (WIRELESS_EXT >= 18) +int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret = 0; + struct net_device *dev = ieee->dev; + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + int i, idx; + int group_key = 0; + const char *alg, *module; + struct ieee80211_crypto_ops *ops; + struct ieee80211_crypt_data **crypt; + + struct ieee80211_security sec = { + .flags = 0, + }; + //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg); + idx = encoding->flags & IW_ENCODE_INDEX; + if (idx) { + if (idx < 1 || idx > WEP_KEYS) + return -EINVAL; + idx--; + } else + idx = ieee->tx_keyidx; + + if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + + crypt = &ieee->crypt[idx]; + + group_key = 1; + } else { + /* some Cisco APs use idx>0 for unicast in dynamic WEP */ + //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg); + if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP) + return -EINVAL; + if (ieee->iw_mode == IW_MODE_INFRA) + + crypt = &ieee->crypt[idx]; + + else + return -EINVAL; + } + + sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT; + if ((encoding->flags & IW_ENCODE_DISABLED) || + ext->alg == IW_ENCODE_ALG_NONE) { + if (*crypt) + ieee80211_crypt_delayed_deinit(ieee, crypt); + + for (i = 0; i < WEP_KEYS; i++) + + if (ieee->crypt[i] != NULL) + + break; + + if (i == WEP_KEYS) { + sec.enabled = 0; + // sec.encrypt = 0; + sec.level = SEC_LEVEL_0; + sec.flags |= SEC_LEVEL; + } + //printk("disabled: flag:%x\n", encoding->flags); + goto done; + } + + sec.enabled = 1; + // sec.encrypt = 1; + switch (ext->alg) { + case IW_ENCODE_ALG_WEP: + alg = "WEP"; + module = "ieee80211_crypt_wep"; + break; + case IW_ENCODE_ALG_TKIP: + alg = "TKIP"; + module = "ieee80211_crypt_tkip"; + break; + case IW_ENCODE_ALG_CCMP: + alg = "CCMP"; + module = "ieee80211_crypt_ccmp"; + break; + default: + IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", + dev->name, ext->alg); + ret = -EINVAL; + goto done; + } + printk("alg name:%s\n",alg); + + ops = ieee80211_get_crypto_ops(alg); + if (ops == NULL) { + request_module(module); + ops = ieee80211_get_crypto_ops(alg); + } + if (ops == NULL) { + IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", + dev->name, ext->alg); + printk("========>unknown crypto alg %d\n", ext->alg); + ret = -EINVAL; + goto done; + } + + if (*crypt == NULL || (*crypt)->ops != ops) { + struct ieee80211_crypt_data *new_crypt; + + ieee80211_crypt_delayed_deinit(ieee, crypt); + + new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL); + if (new_crypt == NULL) { + ret = -ENOMEM; + goto done; + } + new_crypt->ops = ops; + if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) + new_crypt->priv = new_crypt->ops->init(idx); + if (new_crypt->priv == NULL) { + kfree(new_crypt); + ret = -EINVAL; + goto done; + } + *crypt = new_crypt; + + } + + if (ext->key_len > 0 && (*crypt)->ops->set_key && + (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq, + (*crypt)->priv) < 0) { + IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name); + printk("key setting failed\n"); + ret = -EINVAL; + goto done; + } + //skip_host_crypt: + //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags); + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + ieee->tx_keyidx = idx; + sec.active_key = idx; + sec.flags |= SEC_ACTIVE_KEY; + } + + if (ext->alg != IW_ENCODE_ALG_NONE) { + //memcpy(sec.keys[idx], ext->key, ext->key_len); + sec.key_sizes[idx] = ext->key_len; + sec.flags |= (1 << idx); + if (ext->alg == IW_ENCODE_ALG_WEP) { + // sec.encode_alg[idx] = SEC_ALG_WEP; + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_1; + } else if (ext->alg == IW_ENCODE_ALG_TKIP) { + // sec.encode_alg[idx] = SEC_ALG_TKIP; + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_2; + } else if (ext->alg == IW_ENCODE_ALG_CCMP) { + // sec.encode_alg[idx] = SEC_ALG_CCMP; + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_3; + } + /* Don't set sec level for group keys. */ + if (group_key) + sec.flags &= ~SEC_LEVEL; + } +done: + if (ieee->set_security) + ieee->set_security(ieee->dev, &sec); + + if (ieee->reset_on_keychange && + ieee->iw_mode != IW_MODE_INFRA && + ieee->reset_port && ieee->reset_port(dev)) { + IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name); + return -EINVAL; + } + return ret; +} + +int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + struct ieee80211_crypt_data *crypt; + int idx, max_key_len; + + max_key_len = encoding->length - sizeof(*ext); + if (max_key_len < 0) + return -EINVAL; + + idx = encoding->flags & IW_ENCODE_INDEX; + if (idx) { + if (idx < 1 || idx > WEP_KEYS) + return -EINVAL; + idx--; + } else + idx = ieee->tx_keyidx; + + if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY && + ext->alg != IW_ENCODE_ALG_WEP) + if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA) + return -EINVAL; + + crypt = ieee->crypt[idx]; + encoding->flags = idx + 1; + memset(ext, 0, sizeof(*ext)); + + if (crypt == NULL || crypt->ops == NULL ) { + ext->alg = IW_ENCODE_ALG_NONE; + ext->key_len = 0; + encoding->flags |= IW_ENCODE_DISABLED; + } else { + if (strcmp(crypt->ops->name, "WEP") == 0 ) + ext->alg = IW_ENCODE_ALG_WEP; + else if (strcmp(crypt->ops->name, "TKIP")) + ext->alg = IW_ENCODE_ALG_TKIP; + else if (strcmp(crypt->ops->name, "CCMP")) + ext->alg = IW_ENCODE_ALG_CCMP; + else + return -EINVAL; + ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv); + encoding->flags |= IW_ENCODE_ENABLED; + if (ext->key_len && + (ext->alg == IW_ENCODE_ALG_TKIP || + ext->alg == IW_ENCODE_ALG_CCMP)) + ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID; + + } + + return 0; +} + +int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_mlme *mlme = (struct iw_mlme *) extra; + switch (mlme->cmd) { + case IW_MLME_DEAUTH: + case IW_MLME_DISASSOC: + ieee80211_disassociate(ieee); + break; + default: + return -EOPNOTSUPP; + } + return 0; +} + +int ieee80211_wx_set_auth(struct ieee80211_device *ieee, + struct iw_request_info *info, + struct iw_param *data, char *extra) +{ + switch (data->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + /*need to support wpa2 here*/ + //printk("wpa version:%x\n", data->value); + break; + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_KEY_MGMT: + /* + * * Host AP driver does not use these parameters and allows + * * wpa_supplicant to control them internally. + * */ + break; + case IW_AUTH_TKIP_COUNTERMEASURES: + ieee->tkip_countermeasures = data->value; + break; + case IW_AUTH_DROP_UNENCRYPTED: + ieee->drop_unencrypted = data->value; + break; + + case IW_AUTH_80211_AUTH_ALG: + //printk("======>%s():data->value is %d\n",__FUNCTION__,data->value); + // ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0; + if(data->value & IW_AUTH_ALG_SHARED_KEY){ + ieee->open_wep = 0; + ieee->auth_mode = 1; + } + else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){ + ieee->open_wep = 1; + ieee->auth_mode = 0; + } + else if(data->value & IW_AUTH_ALG_LEAP){ + ieee->open_wep = 1; + ieee->auth_mode = 2; + //printk("hahahaa:LEAP\n"); + } + else + return -EINVAL; + //printk("open_wep:%d\n", ieee->open_wep); + break; + + case IW_AUTH_WPA_ENABLED: + ieee->wpa_enabled = (data->value)?1:0; + //printk("enalbe wpa:%d\n", ieee->wpa_enabled); + break; + + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + ieee->ieee802_1x = data->value; + break; + case IW_AUTH_PRIVACY_INVOKED: + ieee->privacy_invoked = data->value; + break; + default: + return -EOPNOTSUPP; + } + return 0; +} +#endif +int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len) +{ + u8 *buf; + + if (len>MAX_WPA_IE_LEN || (len && ie == NULL)) + { + // printk("return error out, len:%d\n", len); + return -EINVAL; + } + + + if (len) + { + if (len != ie[1]+2) + { + printk("len:%d, ie:%d\n", len, ie[1]); + return -EINVAL; + } + buf = kmalloc(len, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + memcpy(buf, ie, len); + kfree(ieee->wpa_ie); + ieee->wpa_ie = buf; + ieee->wpa_ie_len = len; + } + else{ + if (ieee->wpa_ie) + kfree(ieee->wpa_ie); + ieee->wpa_ie = NULL; + ieee->wpa_ie_len = 0; + } + return 0; + +} + +EXPORT_SYMBOL(ieee80211_wx_set_gen_ie); +#if (WIRELESS_EXT >= 18) +EXPORT_SYMBOL(ieee80211_wx_set_mlme); +EXPORT_SYMBOL(ieee80211_wx_set_auth); +EXPORT_SYMBOL(ieee80211_wx_set_encode_ext); +EXPORT_SYMBOL(ieee80211_wx_get_encode_ext); +#endif +EXPORT_SYMBOL(ieee80211_wx_get_scan); +EXPORT_SYMBOL(ieee80211_wx_set_encode); +EXPORT_SYMBOL(ieee80211_wx_get_encode); diff --git a/drivers/staging/rtl8192u/ieee80211/internal.h b/drivers/staging/rtl8192u/ieee80211/internal.h new file mode 100644 index 0000000000000000000000000000000000000000..a7c096eb269fdc4d284de4f6cdfa4332e0f11c3b --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/internal.h @@ -0,0 +1,99 @@ +/* + * Cryptographic API. + * + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the 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 _CRYPTO_INTERNAL_H +#define _CRYPTO_INTERNAL_H + + +//#include +#include "rtl_crypto.h" +#include +#include +#include +#include +#include +#include + + +extern enum km_type crypto_km_types[]; + +static inline enum km_type crypto_kmap_type(int out) +{ + return crypto_km_types[(in_softirq() ? 2 : 0) + out]; +} + +static inline void *crypto_kmap(struct page *page, int out) +{ + return kmap_atomic(page, crypto_kmap_type(out)); +} + +static inline void crypto_kunmap(void *vaddr, int out) +{ + kunmap_atomic(vaddr, crypto_kmap_type(out)); +} + +static inline void crypto_yield(struct crypto_tfm *tfm) +{ + if (!in_softirq()) + cond_resched(); +} + +static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) +{ + return (void *)&tfm[1]; +} + +struct crypto_alg *crypto_alg_lookup(const char *name); + +#ifdef CONFIG_KMOD +void crypto_alg_autoload(const char *name); +struct crypto_alg *crypto_alg_mod_lookup(const char *name); +#else +static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name) +{ + return crypto_alg_lookup(name); +} +#endif + +#ifdef CONFIG_CRYPTO_HMAC +int crypto_alloc_hmac_block(struct crypto_tfm *tfm); +void crypto_free_hmac_block(struct crypto_tfm *tfm); +#else +static inline int crypto_alloc_hmac_block(struct crypto_tfm *tfm) +{ + return 0; +} + +static inline void crypto_free_hmac_block(struct crypto_tfm *tfm) +{ } +#endif + +#ifdef CONFIG_PROC_FS +void __init crypto_init_proc(void); +#else +static inline void crypto_init_proc(void) +{ } +#endif + +int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags); +int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags); +int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags); + +int crypto_init_digest_ops(struct crypto_tfm *tfm); +int crypto_init_cipher_ops(struct crypto_tfm *tfm); +int crypto_init_compress_ops(struct crypto_tfm *tfm); + +void crypto_exit_digest_ops(struct crypto_tfm *tfm); +void crypto_exit_cipher_ops(struct crypto_tfm *tfm); +void crypto_exit_compress_ops(struct crypto_tfm *tfm); + +#endif /* _CRYPTO_INTERNAL_H */ + diff --git a/drivers/staging/rtl8192u/ieee80211/kmap_types.h b/drivers/staging/rtl8192u/ieee80211/kmap_types.h new file mode 100644 index 0000000000000000000000000000000000000000..de67bb01b5f5c85eaf9efa019fc185db57cb6b34 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/kmap_types.h @@ -0,0 +1,20 @@ +#ifndef __KMAP_TYPES_H + +#define __KMAP_TYPES_H + + +enum km_type { + KM_BOUNCE_READ, + KM_SKB_SUNRPC_DATA, + KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, + KM_BH_IRQ, + KM_SOFTIRQ0, + KM_SOFTIRQ1, + KM_TYPE_NR +}; + +#define _ASM_KMAP_TYPES_H + +#endif diff --git a/drivers/staging/rtl8192u/ieee80211/michael_mic.c b/drivers/staging/rtl8192u/ieee80211/michael_mic.c new file mode 100644 index 0000000000000000000000000000000000000000..df256e487c20008693a4bdfe2209058ad19b91c2 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/michael_mic.c @@ -0,0 +1,194 @@ +/* + * Cryptographic API + * + * Michael MIC (IEEE 802.11i/TKIP) keyed digest + * + * Copyright (c) 2004 Jouni Malinen + * + * 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 "rtl_crypto.h" + + +struct michael_mic_ctx { + u8 pending[4]; + size_t pending_len; + + u32 l, r; +}; + + +static inline u32 rotl(u32 val, int bits) +{ + return (val << bits) | (val >> (32 - bits)); +} + + +static inline u32 rotr(u32 val, int bits) +{ + return (val >> bits) | (val << (32 - bits)); +} + + +static inline u32 xswap(u32 val) +{ + return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8); +} + + +#define michael_block(l, r) \ +do { \ + r ^= rotl(l, 17); \ + l += r; \ + r ^= xswap(l); \ + l += r; \ + r ^= rotl(l, 3); \ + l += r; \ + r ^= rotr(l, 2); \ + l += r; \ +} while (0) + + +static inline u32 get_le32(const u8 *p) +{ + return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +} + + +static inline void put_le32(u8 *p, u32 v) +{ + p[0] = v; + p[1] = v >> 8; + p[2] = v >> 16; + p[3] = v >> 24; +} + + +static void michael_init(void *ctx) +{ + struct michael_mic_ctx *mctx = ctx; + mctx->pending_len = 0; +} + + +static void michael_update(void *ctx, const u8 *data, unsigned int len) +{ + struct michael_mic_ctx *mctx = ctx; + + if (mctx->pending_len) { + int flen = 4 - mctx->pending_len; + if (flen > len) + flen = len; + memcpy(&mctx->pending[mctx->pending_len], data, flen); + mctx->pending_len += flen; + data += flen; + len -= flen; + + if (mctx->pending_len < 4) + return; + + mctx->l ^= get_le32(mctx->pending); + michael_block(mctx->l, mctx->r); + mctx->pending_len = 0; + } + + while (len >= 4) { + mctx->l ^= get_le32(data); + michael_block(mctx->l, mctx->r); + data += 4; + len -= 4; + } + + if (len > 0) { + mctx->pending_len = len; + memcpy(mctx->pending, data, len); + } +} + + +static void michael_final(void *ctx, u8 *out) +{ + struct michael_mic_ctx *mctx = ctx; + u8 *data = mctx->pending; + + /* Last block and padding (0x5a, 4..7 x 0) */ + switch (mctx->pending_len) { + case 0: + mctx->l ^= 0x5a; + break; + case 1: + mctx->l ^= data[0] | 0x5a00; + break; + case 2: + mctx->l ^= data[0] | (data[1] << 8) | 0x5a0000; + break; + case 3: + mctx->l ^= data[0] | (data[1] << 8) | (data[2] << 16) | + 0x5a000000; + break; + } + michael_block(mctx->l, mctx->r); + /* l ^= 0; */ + michael_block(mctx->l, mctx->r); + + put_le32(out, mctx->l); + put_le32(out + 4, mctx->r); +} + + +static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen, + u32 *flags) +{ + struct michael_mic_ctx *mctx = ctx; + if (keylen != 8) { + if (flags) + *flags = CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + mctx->l = get_le32(key); + mctx->r = get_le32(key + 4); + return 0; +} + + +static struct crypto_alg michael_mic_alg = { + .cra_name = "michael_mic", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = 8, + .cra_ctxsize = sizeof(struct michael_mic_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(michael_mic_alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = 8, + .dia_init = michael_init, + .dia_update = michael_update, + .dia_final = michael_final, + .dia_setkey = michael_setkey } } +}; + + +static int __init michael_mic_init(void) +{ + return crypto_register_alg(&michael_mic_alg); +} + + +static void __exit michael_mic_exit(void) +{ + crypto_unregister_alg(&michael_mic_alg); +} + + +module_init(michael_mic_init); +module_exit(michael_mic_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Michael MIC"); +MODULE_AUTHOR("Jouni Malinen "); diff --git a/drivers/staging/rtl8192u/ieee80211/proc.c b/drivers/staging/rtl8192u/ieee80211/proc.c new file mode 100644 index 0000000000000000000000000000000000000000..6eda928e4090559c74d82fb3e2bbd52cb2f970ab --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/proc.c @@ -0,0 +1,116 @@ +/* + * Scatterlist Cryptographic API. + * + * Procfs information. + * + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the 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 "rtl_crypto.h" +#include +#include +#include +#include "internal.h" + +extern struct list_head crypto_alg_list; +extern struct rw_semaphore crypto_alg_sem; + +static void *c_start(struct seq_file *m, loff_t *pos) +{ + struct list_head *v; + loff_t n = *pos; + + down_read(&crypto_alg_sem); + list_for_each(v, &crypto_alg_list) + if (!n--) + return list_entry(v, struct crypto_alg, cra_list); + return NULL; +} + +static void *c_next(struct seq_file *m, void *p, loff_t *pos) +{ + struct list_head *v = p; + + (*pos)++; + v = v->next; + return (v == &crypto_alg_list) ? + NULL : list_entry(v, struct crypto_alg, cra_list); +} + +static void c_stop(struct seq_file *m, void *p) +{ + up_read(&crypto_alg_sem); +} + +static int c_show(struct seq_file *m, void *p) +{ + struct crypto_alg *alg = (struct crypto_alg *)p; + + seq_printf(m, "name : %s\n", alg->cra_name); + seq_printf(m, "module : %s\n", + (alg->cra_module ? + alg->cra_module->name : + "kernel")); + + switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { + case CRYPTO_ALG_TYPE_CIPHER: + seq_printf(m, "type : cipher\n"); + seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); + seq_printf(m, "min keysize : %u\n", + alg->cra_cipher.cia_min_keysize); + seq_printf(m, "max keysize : %u\n", + alg->cra_cipher.cia_max_keysize); + break; + + case CRYPTO_ALG_TYPE_DIGEST: + seq_printf(m, "type : digest\n"); + seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); + seq_printf(m, "digestsize : %u\n", + alg->cra_digest.dia_digestsize); + break; + case CRYPTO_ALG_TYPE_COMPRESS: + seq_printf(m, "type : compression\n"); + break; + default: + seq_printf(m, "type : unknown\n"); + break; + } + + seq_putc(m, '\n'); + return 0; +} + +static struct seq_operations crypto_seq_ops = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = c_show +}; + +static int crypto_info_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &crypto_seq_ops); +} + +static struct file_operations proc_crypto_ops = { + .open = crypto_info_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; + +void __init crypto_init_proc(void) +{ + struct proc_dir_entry *proc; + + proc = create_proc_entry("crypto", 0, NULL); + if (proc) + proc->proc_fops = &proc_crypto_ops; +} diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BA.h b/drivers/staging/rtl8192u/ieee80211/rtl819x_BA.h new file mode 100644 index 0000000000000000000000000000000000000000..8ddc8bf9dc268332b43bf47b152411fe0ff31b48 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BA.h @@ -0,0 +1,69 @@ +#ifndef _BATYPE_H_ +#define _BATYPE_H_ + +#define TOTAL_TXBA_NUM 16 +#define TOTAL_RXBA_NUM 16 + +#define BA_SETUP_TIMEOUT 200 +#define BA_INACT_TIMEOUT 60000 + +#define BA_POLICY_DELAYED 0 +#define BA_POLICY_IMMEDIATE 1 + +#define ADDBA_STATUS_SUCCESS 0 +#define ADDBA_STATUS_REFUSED 37 +#define ADDBA_STATUS_INVALID_PARAM 38 + +#define DELBA_REASON_QSTA_LEAVING 36 +#define DELBA_REASON_END_BA 37 +#define DELBA_REASON_UNKNOWN_BA 38 +#define DELBA_REASON_TIMEOUT 39 +/* whether need define BA Action frames here? +struct ieee80211_ADDBA_Req{ + struct ieee80211_header_data header; + u8 category; + u8 +} __attribute__ ((packed)); +*/ +//Is this need?I put here just to make it easier to define structure BA_RECORD //WB +typedef union _SEQUENCE_CONTROL{ + u16 ShortData; + struct + { + u16 FragNum:4; + u16 SeqNum:12; + }field; +}SEQUENCE_CONTROL, *PSEQUENCE_CONTROL; + +typedef union _BA_PARAM_SET { + u8 charData[2]; + u16 shortData; + struct { + u16 AMSDU_Support:1; + u16 BAPolicy:1; + u16 TID:4; + u16 BufferSize:10; + } field; +} BA_PARAM_SET, *PBA_PARAM_SET; + +typedef union _DELBA_PARAM_SET { + u8 charData[2]; + u16 shortData; + struct { + u16 Reserved:11; + u16 Initiator:1; + u16 TID:4; + } field; +} DELBA_PARAM_SET, *PDELBA_PARAM_SET; + +typedef struct _BA_RECORD { + struct timer_list Timer; + u8 bValid; + u8 DialogToken; + BA_PARAM_SET BaParamSet; + u16 BaTimeoutValue; + SEQUENCE_CONTROL BaStartSeqCtrl; +} BA_RECORD, *PBA_RECORD; + +#endif //end _BATYPE_H_ + diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c new file mode 100644 index 0000000000000000000000000000000000000000..26af43bb8390632e248e8ccbd88d68bfe5139c4a --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c @@ -0,0 +1,737 @@ +/******************************************************************************************************************************** + * This file is created to process BA Action Frame. According to 802.11 spec, there are 3 BA action types at all. And as BA is + * related to TS, this part need some struture defined in QOS side code. Also TX RX is going to be resturctured, so how to send + * ADDBAREQ ADDBARSP and DELBA packet is still on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue. + * WB 2008-05-27 + * *****************************************************************************************************************************/ +#include "ieee80211.h" +#include "rtl819x_BA.h" + +/******************************************************************************************************************** + *function: Activate BA entry. And if Time is nozero, start timer. + * input: PBA_RECORD pBA //BA entry to be enabled + * u16 Time //indicate time delay. + * output: none +********************************************************************************************************************/ +void ActivateBAEntry(struct ieee80211_device* ieee, PBA_RECORD pBA, u16 Time) +{ + pBA->bValid = true; + if(Time != 0) + mod_timer(&pBA->Timer, jiffies + MSECS(Time)); +} + +/******************************************************************************************************************** + *function: deactivate BA entry, including its timer. + * input: PBA_RECORD pBA //BA entry to be disabled + * output: none +********************************************************************************************************************/ +void DeActivateBAEntry( struct ieee80211_device* ieee, PBA_RECORD pBA) +{ + pBA->bValid = false; + del_timer_sync(&pBA->Timer); +} +/******************************************************************************************************************** + *function: deactivete BA entry in Tx Ts, and send DELBA. + * input: + * PTX_TS_RECORD pTxTs //Tx Ts which is to deactivate BA entry. + * output: none + * notice: As PTX_TS_RECORD structure will be defined in QOS, so wait to be merged. //FIXME +********************************************************************************************************************/ +u8 TxTsDeleteBA( struct ieee80211_device* ieee, PTX_TS_RECORD pTxTs) +{ + PBA_RECORD pAdmittedBa = &pTxTs->TxAdmittedBARecord; //These two BA entries must exist in TS structure + PBA_RECORD pPendingBa = &pTxTs->TxPendingBARecord; + u8 bSendDELBA = false; + + // Delete pending BA + if(pPendingBa->bValid) + { + DeActivateBAEntry(ieee, pPendingBa); + bSendDELBA = true; + } + + // Delete admitted BA + if(pAdmittedBa->bValid) + { + DeActivateBAEntry(ieee, pAdmittedBa); + bSendDELBA = true; + } + + return bSendDELBA; +} + +/******************************************************************************************************************** + *function: deactivete BA entry in Tx Ts, and send DELBA. + * input: + * PRX_TS_RECORD pRxTs //Rx Ts which is to deactivate BA entry. + * output: none + * notice: As PRX_TS_RECORD structure will be defined in QOS, so wait to be merged. //FIXME, same with above +********************************************************************************************************************/ +u8 RxTsDeleteBA( struct ieee80211_device* ieee, PRX_TS_RECORD pRxTs) +{ + PBA_RECORD pBa = &pRxTs->RxAdmittedBARecord; + u8 bSendDELBA = false; + + if(pBa->bValid) + { + DeActivateBAEntry(ieee, pBa); + bSendDELBA = true; + } + + return bSendDELBA; +} + +/******************************************************************************************************************** + *function: reset BA entry + * input: + * PBA_RECORD pBA //entry to be reset + * output: none +********************************************************************************************************************/ +void ResetBaEntry( PBA_RECORD pBA) +{ + pBA->bValid = false; + pBA->BaParamSet.shortData = 0; + pBA->BaTimeoutValue = 0; + pBA->DialogToken = 0; + pBA->BaStartSeqCtrl.ShortData = 0; +} +//These functions need porting here or not? +/******************************************************************************************************************************* + *function: construct ADDBAREQ and ADDBARSP frame here together. + * input: u8* Dst //ADDBA frame's destination + * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA. + * u16 StatusCode //status code in RSP and I will use it to indicate whether it's RSP or REQ(will I?) + * u8 type //indicate whether it's RSP(ACT_ADDBARSP) ow REQ(ACT_ADDBAREQ) + * output: none + * return: sk_buff* skb //return constructed skb to xmit +*******************************************************************************************************************************/ +static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, PBA_RECORD pBA, u16 StatusCode, u8 type) +{ + struct sk_buff *skb = NULL; + struct ieee80211_hdr_3addr* BAReq = NULL; + u8* tag = NULL; + u16 tmp = 0; + u16 len = ieee->tx_headroom + 9; + //category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) + BA Timeout Value(2) + BA Start SeqCtrl(2)(or StatusCode(2)) + IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:"MAC_FMT", ieee->dev:%p\n", __FUNCTION__, type, MAC_ARG(Dst), ieee->dev); + if (pBA == NULL||ieee == NULL) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee); + return NULL; + } + skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME + if (skb == NULL) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n"); + return NULL; + } + + memset(skb->data, 0, sizeof( struct ieee80211_hdr_3addr)); //I wonder whether it's necessary. Apparently kernel will not do it when alloc a skb. + skb_reserve(skb, ieee->tx_headroom); + + BAReq = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr)); + + memcpy(BAReq->addr1, Dst, ETH_ALEN); + memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN); + + memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN); + + BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame + + //tag += sizeof( struct ieee80211_hdr_3addr); //move to action field + tag = (u8*)skb_put(skb, 9); + *tag ++= ACT_CAT_BA; + *tag ++= type; + // Dialog Token + *tag ++= pBA->DialogToken; + + if (ACT_ADDBARSP == type) + { + // Status Code + printk("=====>to send ADDBARSP\n"); + tmp = cpu_to_le16(StatusCode); + memcpy(tag, (u8*)&tmp, 2); + tag += 2; + } + // BA Parameter Set + tmp = cpu_to_le16(pBA->BaParamSet.shortData); + memcpy(tag, (u8*)&tmp, 2); + tag += 2; + // BA Timeout Value + tmp = cpu_to_le16(pBA->BaTimeoutValue); + memcpy(tag, (u8*)&tmp, 2); + tag += 2; + + if (ACT_ADDBAREQ == type) + { + // BA Start SeqCtrl + memcpy(tag,(u8*)&(pBA->BaStartSeqCtrl), 2); + tag += 2; + } + + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + return skb; + //return NULL; +} + + +/******************************************************************************************************************** + *function: construct DELBA frame + * input: u8* dst //DELBA frame's destination + * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA + * TR_SELECT TxRxSelect //TX RX direction + * u16 ReasonCode //status code. + * output: none + * return: sk_buff* skb //return constructed skb to xmit +********************************************************************************************************************/ +static struct sk_buff* ieee80211_DELBA( + struct ieee80211_device* ieee, + u8* dst, + PBA_RECORD pBA, + TR_SELECT TxRxSelect, + u16 ReasonCode + ) +{ + DELBA_PARAM_SET DelbaParamSet; + struct sk_buff *skb = NULL; + struct ieee80211_hdr_3addr* Delba = NULL; + u8* tag = NULL; + u16 tmp = 0; + //len = head len + DELBA Parameter Set(2) + Reason Code(2) + u16 len = 6 + ieee->tx_headroom; + + if (net_ratelimit()) + IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:"MAC_FMT"\n", __FUNCTION__, ReasonCode, MAC_ARG(dst)); + + memset(&DelbaParamSet, 0, 2); + + DelbaParamSet.field.Initiator = (TxRxSelect==TX_DIR)?1:0; + DelbaParamSet.field.TID = pBA->BaParamSet.field.TID; + + skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME + if (skb == NULL) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n"); + return NULL; + } +// memset(skb->data, 0, len+sizeof( struct ieee80211_hdr_3addr)); + skb_reserve(skb, ieee->tx_headroom); + + Delba = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr)); + + memcpy(Delba->addr1, dst, ETH_ALEN); + memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN); + memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN); + Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame + + tag = (u8*)skb_put(skb, 6); + + *tag ++= ACT_CAT_BA; + *tag ++= ACT_DELBA; + + // DELBA Parameter Set + tmp = cpu_to_le16(DelbaParamSet.shortData); + memcpy(tag, (u8*)&tmp, 2); + tag += 2; + // Reason Code + tmp = cpu_to_le16(ReasonCode); + memcpy(tag, (u8*)&tmp, 2); + tag += 2; + + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + if (net_ratelimit()) + IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "<=====%s()\n", __FUNCTION__); + return skb; +} + +/******************************************************************************************************************** + *function: send ADDBAReq frame out + * input: u8* dst //ADDBAReq frame's destination + * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA + * output: none + * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does +********************************************************************************************************************/ +void ieee80211_send_ADDBAReq(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA) +{ + struct sk_buff *skb = NULL; + skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero. + + if (skb) + { + softmac_mgmt_xmit(skb, ieee); + //add statistic needed here. + //and skb will be freed in softmac_mgmt_xmit(), so omit all dev_kfree_skb_any() outside softmac_mgmt_xmit() + //WB + } + else + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__); + } + return; +} + +/******************************************************************************************************************** + *function: send ADDBARSP frame out + * input: u8* dst //DELBA frame's destination + * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA + * u16 StatusCode //RSP StatusCode + * output: none + * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does +********************************************************************************************************************/ +void ieee80211_send_ADDBARsp(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode) +{ + struct sk_buff *skb = NULL; + skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames + if (skb) + { + softmac_mgmt_xmit(skb, ieee); + //same above + } + else + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__); + } + + return; + +} +/******************************************************************************************************************** + *function: send ADDBARSP frame out + * input: u8* dst //DELBA frame's destination + * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA + * TR_SELECT TxRxSelect //TX or RX + * u16 ReasonCode //DEL ReasonCode + * output: none + * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does +********************************************************************************************************************/ + +void ieee80211_send_DELBA(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, TR_SELECT TxRxSelect, u16 ReasonCode) +{ + struct sk_buff *skb = NULL; + skb = ieee80211_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); //construct ACT_ADDBARSP frames + if (skb) + { + softmac_mgmt_xmit(skb, ieee); + //same above + } + else + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__); + } + return ; +} + +/******************************************************************************************************************** + *function: RX ADDBAReq + * input: struct sk_buff * skb //incoming ADDBAReq skb. + * return: 0(pass), other(fail) + * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support. +********************************************************************************************************************/ +int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb) +{ + struct ieee80211_hdr_3addr* req = NULL; + u16 rc = 0; + u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL; + PBA_RECORD pBA = NULL; + PBA_PARAM_SET pBaParamSet = NULL; + u16* pBaTimeoutVal = NULL; + PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL; + PRX_TS_RECORD pTS = NULL; + + if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); + return -1; + } + + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + + req = ( struct ieee80211_hdr_3addr*) skb->data; + tag = (u8*)req; + dst = (u8*)(&req->addr2[0]); + tag += sizeof( struct ieee80211_hdr_3addr); + pDialogToken = tag + 2; //category+action + pBaParamSet = (PBA_PARAM_SET)(tag + 3); //+DialogToken + pBaTimeoutVal = (u16*)(tag + 5); + pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7); + + printk("====================>rx ADDBAREQ from :"MAC_FMT"\n", MAC_ARG(dst)); +//some other capability is not ready now. + if( (ieee->current_network.qos_data.active == 0) || + (ieee->pHTInfo->bCurrentHTSupport == false)) //|| + // (ieee->pStaQos->bEnableRxImmBA == false) ) + { + rc = ADDBA_STATUS_REFUSED; + IEEE80211_DEBUG(IEEE80211_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport); + goto OnADDBAReq_Fail; + } + // Search for related traffic stream. + // If there is no matched TS, reject the ADDBA request. + if( !GetTs( + ieee, + (PTS_COMMON_INFO*)(&pTS), + dst, + (u8)(pBaParamSet->field.TID), + RX_DIR, + true) ) + { + rc = ADDBA_STATUS_REFUSED; + IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__); + goto OnADDBAReq_Fail; + } + pBA = &pTS->RxAdmittedBARecord; + // To Determine the ADDBA Req content + // We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl... + // I want to check StartSeqCtrl to make sure when we start aggregation!!! + // + if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) + { + rc = ADDBA_STATUS_INVALID_PARAM; + IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __FUNCTION__); + goto OnADDBAReq_Fail; + } + // Admit the ADDBA Request + // + DeActivateBAEntry(ieee, pBA); + pBA->DialogToken = *pDialogToken; + pBA->BaParamSet = *pBaParamSet; + pBA->BaTimeoutValue = *pBaTimeoutVal; + pBA->BaStartSeqCtrl = *pBaStartSeqCtrl; + //for half N mode we only aggregate 1 frame + if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) + pBA->BaParamSet.field.BufferSize = 1; + else + pBA->BaParamSet.field.BufferSize = 32; + ActivateBAEntry(ieee, pBA, pBA->BaTimeoutValue); + ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS); + + // End of procedure. + return 0; + +OnADDBAReq_Fail: + { + BA_RECORD BA; + BA.BaParamSet = *pBaParamSet; + BA.BaTimeoutValue = *pBaTimeoutVal; + BA.DialogToken = *pDialogToken; + BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE; + ieee80211_send_ADDBARsp(ieee, dst, &BA, rc); + return 0; //we send RSP out. + } + +} + +/******************************************************************************************************************** + *function: RX ADDBARSP + * input: struct sk_buff * skb //incoming ADDBAReq skb. + * return: 0(pass), other(fail) + * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support. +********************************************************************************************************************/ +int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb) +{ + struct ieee80211_hdr_3addr* rsp = NULL; + PBA_RECORD pPendingBA, pAdmittedBA; + PTX_TS_RECORD pTS = NULL; + u8* dst = NULL, *pDialogToken = NULL, *tag = NULL; + u16* pStatusCode = NULL, *pBaTimeoutVal = NULL; + PBA_PARAM_SET pBaParamSet = NULL; + u16 ReasonCode; + + if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); + return -1; + } + rsp = ( struct ieee80211_hdr_3addr*)skb->data; + tag = (u8*)rsp; + dst = (u8*)(&rsp->addr2[0]); + tag += sizeof( struct ieee80211_hdr_3addr); + pDialogToken = tag + 2; + pStatusCode = (u16*)(tag + 3); + pBaParamSet = (PBA_PARAM_SET)(tag + 5); + pBaTimeoutVal = (u16*)(tag + 7); + + // Check the capability + // Since we can always receive A-MPDU, we just check if it is under HT mode. + if( ieee->current_network.qos_data.active == 0 || + ieee->pHTInfo->bCurrentHTSupport == false || + ieee->pHTInfo->bCurrentAMPDUEnable == false ) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable); + ReasonCode = DELBA_REASON_UNKNOWN_BA; + goto OnADDBARsp_Reject; + } + + + // + // Search for related TS. + // If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame. + // + if (!GetTs( + ieee, + (PTS_COMMON_INFO*)(&pTS), + dst, + (u8)(pBaParamSet->field.TID), + TX_DIR, + false) ) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__); + ReasonCode = DELBA_REASON_UNKNOWN_BA; + goto OnADDBARsp_Reject; + } + + pTS->bAddBaReqInProgress = false; + pPendingBA = &pTS->TxPendingBARecord; + pAdmittedBA = &pTS->TxAdmittedBARecord; + + + // + // Check if related BA is waiting for setup. + // If not, reject by sending DELBA frame. + // + if((pAdmittedBA->bValid==true)) + { + // Since BA is already setup, we ignore all other ADDBA Response. + IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n"); + return -1; + } + else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken)) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n"); + ReasonCode = DELBA_REASON_UNKNOWN_BA; + goto OnADDBARsp_Reject; + } + else + { + IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode); + DeActivateBAEntry(ieee, pPendingBA); + } + + + if(*pStatusCode == ADDBA_STATUS_SUCCESS) + { + // + // Determine ADDBA Rsp content here. + // We can compare the value of BA parameter set that Peer returned and Self sent. + // If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism. + // + if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) + { + // Since this is a kind of ADDBA failed, we delay next ADDBA process. + pTS->bAddBaReqDelayed = true; + DeActivateBAEntry(ieee, pAdmittedBA); + ReasonCode = DELBA_REASON_END_BA; + goto OnADDBARsp_Reject; + } + + + // + // Admitted condition + // + pAdmittedBA->DialogToken = *pDialogToken; + pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal; + pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl; + pAdmittedBA->BaParamSet = *pBaParamSet; + DeActivateBAEntry(ieee, pAdmittedBA); + ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal); + } + else + { + // Delay next ADDBA process. + pTS->bAddBaReqDelayed = true; + } + + // End of procedure + return 0; + +OnADDBARsp_Reject: + { + BA_RECORD BA; + BA.BaParamSet = *pBaParamSet; + ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode); + return 0; + } + +} + +/******************************************************************************************************************** + *function: RX DELBA + * input: struct sk_buff * skb //incoming ADDBAReq skb. + * return: 0(pass), other(fail) + * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support. +********************************************************************************************************************/ +int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb) +{ + struct ieee80211_hdr_3addr* delba = NULL; + PDELBA_PARAM_SET pDelBaParamSet = NULL; + u16* pReasonCode = NULL; + u8* dst = NULL; + + if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6)); + return -1; + } + + if(ieee->current_network.qos_data.active == 0 || + ieee->pHTInfo->bCurrentHTSupport == false ) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport); + return -1; + } + + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + delba = ( struct ieee80211_hdr_3addr*)skb->data; + dst = (u8*)(&delba->addr2[0]); + delba += sizeof( struct ieee80211_hdr_3addr); + pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2); + pReasonCode = (u16*)(delba+4); + + if(pDelBaParamSet->field.Initiator == 1) + { + PRX_TS_RECORD pRxTs; + + if( !GetTs( + ieee, + (PTS_COMMON_INFO*)&pRxTs, + dst, + (u8)pDelBaParamSet->field.TID, + RX_DIR, + false) ) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for RXTS in %s()\n", __FUNCTION__); + return -1; + } + + RxTsDeleteBA(ieee, pRxTs); + } + else + { + PTX_TS_RECORD pTxTs; + + if(!GetTs( + ieee, + (PTS_COMMON_INFO*)&pTxTs, + dst, + (u8)pDelBaParamSet->field.TID, + TX_DIR, + false) ) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for TXTS in %s()\n", __FUNCTION__); + return -1; + } + + pTxTs->bUsingBa = false; + pTxTs->bAddBaReqInProgress = false; + pTxTs->bAddBaReqDelayed = false; + del_timer_sync(&pTxTs->TsAddBaTimer); + //PlatformCancelTimer(Adapter, &pTxTs->TsAddBaTimer); + TxTsDeleteBA(ieee, pTxTs); + } + return 0; +} + +// +// ADDBA initiate. This can only be called by TX side. +// +void +TsInitAddBA( + struct ieee80211_device* ieee, + PTX_TS_RECORD pTS, + u8 Policy, + u8 bOverwritePending + ) +{ + PBA_RECORD pBA = &pTS->TxPendingBARecord; + + if(pBA->bValid==true && bOverwritePending==false) + return; + + // Set parameters to "Pending" variable set + DeActivateBAEntry(ieee, pBA); + + pBA->DialogToken++; // DialogToken: Only keep the latest dialog token + pBA->BaParamSet.field.AMSDU_Support = 0; // Do not support A-MSDU with A-MPDU now!! + pBA->BaParamSet.field.BAPolicy = Policy; // Policy: Delayed or Immediate + pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID; // TID + // BufferSize: This need to be set according to A-MPDU vector + pBA->BaParamSet.field.BufferSize = 32; // BufferSize: This need to be set according to A-MPDU vector + pBA->BaTimeoutValue = 0; // Timeout value: Set 0 to disable Timer + pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096; // Block Ack will start after 3 packets later. + + ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT); + + ieee80211_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA); +} + +void +TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect) +{ + + if(TxRxSelect == TX_DIR) + { + PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)pTsCommonInfo; + + if(TxTsDeleteBA(ieee, pTxTs)) + ieee80211_send_DELBA( + ieee, + pTsCommonInfo->Addr, + (pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord), + TxRxSelect, + DELBA_REASON_END_BA); + } + else if(TxRxSelect == RX_DIR) + { + PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)pTsCommonInfo; + if(RxTsDeleteBA(ieee, pRxTs)) + ieee80211_send_DELBA( + ieee, + pTsCommonInfo->Addr, + &pRxTs->RxAdmittedBARecord, + TxRxSelect, + DELBA_REASON_END_BA ); + } +} +/******************************************************************************************************************** + *function: BA setup timer + * input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer + * return: NULL + * notice: +********************************************************************************************************************/ +void BaSetupTimeOut(unsigned long data) +{ + PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data; + + pTxTs->bAddBaReqInProgress = false; + pTxTs->bAddBaReqDelayed = true; + pTxTs->TxPendingBARecord.bValid = false; +} + +void TxBaInactTimeout(unsigned long data) +{ + PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data; + struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]); + TxTsDeleteBA(ieee, pTxTs); + ieee80211_send_DELBA( + ieee, + pTxTs->TsCommonInfo.Addr, + &pTxTs->TxAdmittedBARecord, + TX_DIR, + DELBA_REASON_TIMEOUT); +} + +void RxBaInactTimeout(unsigned long data) +{ + PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data; + struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]); + + RxTsDeleteBA(ieee, pRxTs); + ieee80211_send_DELBA( + ieee, + pRxTs->TsCommonInfo.Addr, + &pRxTs->RxAdmittedBARecord, + RX_DIR, + DELBA_REASON_TIMEOUT); + return ; +} + diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h new file mode 100644 index 0000000000000000000000000000000000000000..cde603f67f43494c6c4ca78fa614582be0453bdb --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h @@ -0,0 +1,481 @@ +#ifndef _RTL819XU_HTTYPE_H_ +#define _RTL819XU_HTTYPE_H_ + +//------------------------------------------------------------ +// The HT Capability element is present in beacons, association request, +// reassociation request and probe response frames +//------------------------------------------------------------ + +// +// Operation mode value +// +#define HT_OPMODE_NO_PROTECT 0 +#define HT_OPMODE_OPTIONAL 1 +#define HT_OPMODE_40MHZ_PROTECT 2 +#define HT_OPMODE_MIXED 3 + +// +// MIMO Power Save Setings +// +#define MIMO_PS_STATIC 0 +#define MIMO_PS_DYNAMIC 1 +#define MIMO_PS_NOLIMIT 3 + + +// +// There should be 128 bits to cover all of the MCS rates. However, since +// 8190 does not support too much rates, one integer is quite enough. +// + +#define sHTCLng 4 + + +#define HT_SUPPORTED_MCS_1SS_BITMAP 0x000000ff +#define HT_SUPPORTED_MCS_2SS_BITMAP 0x0000ff00 +#define HT_SUPPORTED_MCS_1SS_2SS_BITMAP HT_MCS_1SS_BITMAP|HT_MCS_1SS_2SS_BITMAP + + +typedef enum _HT_MCS_RATE{ + HT_MCS0 = 0x00000001, + HT_MCS1 = 0x00000002, + HT_MCS2 = 0x00000004, + HT_MCS3 = 0x00000008, + HT_MCS4 = 0x00000010, + HT_MCS5 = 0x00000020, + HT_MCS6 = 0x00000040, + HT_MCS7 = 0x00000080, + HT_MCS8 = 0x00000100, + HT_MCS9 = 0x00000200, + HT_MCS10 = 0x00000400, + HT_MCS11 = 0x00000800, + HT_MCS12 = 0x00001000, + HT_MCS13 = 0x00002000, + HT_MCS14 = 0x00004000, + HT_MCS15 = 0x00008000, + // Do not define MCS32 here although 8190 support MCS32 +}HT_MCS_RATE,*PHT_MCS_RATE; + +// +// Represent Channel Width in HT Capabilities +// +typedef enum _HT_CHANNEL_WIDTH{ + HT_CHANNEL_WIDTH_20 = 0, + HT_CHANNEL_WIDTH_20_40 = 1, +}HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH; + +// +// Represent Extention Channel Offset in HT Capabilities +// This is available only in 40Mhz mode. +// +typedef enum _HT_EXTCHNL_OFFSET{ + HT_EXTCHNL_OFFSET_NO_EXT = 0, + HT_EXTCHNL_OFFSET_UPPER = 1, + HT_EXTCHNL_OFFSET_NO_DEF = 2, + HT_EXTCHNL_OFFSET_LOWER = 3, +}HT_EXTCHNL_OFFSET, *PHT_EXTCHNL_OFFSET; + +typedef enum _CHNLOP{ + CHNLOP_NONE = 0, // No Action now + CHNLOP_SCAN = 1, // Scan in progress + CHNLOP_SWBW = 2, // Bandwidth switching in progress + CHNLOP_SWCHNL = 3, // Software Channel switching in progress +} CHNLOP, *PCHNLOP; + +// Determine if the Channel Operation is in progress +#define CHHLOP_IN_PROGRESS(_pHTInfo) \ + ((_pHTInfo)->ChnlOp > CHNLOP_NONE) ? TRUE : FALSE + +/* +typedef union _HT_CAPABILITY{ + u16 ShortData; + u8 CharData[2]; + struct + { + u16 AdvCoding:1; + u16 ChlWidth:1; + u16 MimoPwrSave:2; + u16 GreenField:1; + u16 ShortGI20Mhz:1; + u16 ShortGI40Mhz:1; + u16 STBC:1; + u16 BeamForm:1; + u16 DelayBA:1; + u16 MaxAMSDUSize:1; + u16 DssCCk:1; + u16 PSMP:1; + u16 Rsvd:3; + }Field; +}HT_CAPABILITY, *PHT_CAPABILITY; + +typedef union _HT_CAPABILITY_MACPARA{ + u8 ShortData; + u8 CharData[1]; + struct + { + u8 MaxRxAMPDU:2; + u8 MPDUDensity:2; + u8 Rsvd:4; + }Field; +}HT_CAPABILITY_MACPARA, *PHT_CAPABILITY_MACPARA; +*/ + +typedef enum _HT_ACTION{ + ACT_RECOMMAND_WIDTH = 0, + ACT_MIMO_PWR_SAVE = 1, + ACT_PSMP = 2, + ACT_SET_PCO_PHASE = 3, + ACT_MIMO_CHL_MEASURE = 4, + ACT_RECIPROCITY_CORRECT = 5, + ACT_MIMO_CSI_MATRICS = 6, + ACT_MIMO_NOCOMPR_STEER = 7, + ACT_MIMO_COMPR_STEER = 8, + ACT_ANTENNA_SELECT = 9, +} HT_ACTION, *PHT_ACTION; + + +/* 2007/06/07 MH Define sub-carrier mode for 40MHZ. */ +typedef enum _HT_Bandwidth_40MHZ_Sub_Carrier{ + SC_MODE_DUPLICATE = 0, + SC_MODE_LOWER = 1, + SC_MODE_UPPER = 2, + SC_MODE_FULL40MHZ = 3, +}HT_BW40_SC_E; + +typedef struct _HT_CAPABILITY_ELE{ + + //HT capability info + u8 AdvCoding:1; + u8 ChlWidth:1; + u8 MimoPwrSave:2; + u8 GreenField:1; + u8 ShortGI20Mhz:1; + u8 ShortGI40Mhz:1; + u8 TxSTBC:1; + u8 RxSTBC:2; + u8 DelayBA:1; + u8 MaxAMSDUSize:1; + u8 DssCCk:1; + u8 PSMP:1; + u8 Rsvd1:1; + u8 LSigTxopProtect:1; + + //MAC HT parameters info + u8 MaxRxAMPDUFactor:2; + u8 MPDUDensity:3; + u8 Rsvd2:3; + + //Supported MCS set + u8 MCS[16]; + + + //Extended HT Capability Info + u16 ExtHTCapInfo; + + //TXBF Capabilities + u8 TxBFCap[4]; + + //Antenna Selection Capabilities + u8 ASCap; + +} __attribute__ ((packed)) HT_CAPABILITY_ELE, *PHT_CAPABILITY_ELE; + +//------------------------------------------------------------ +// The HT Information element is present in beacons +// Only AP is required to include this element +//------------------------------------------------------------ + +typedef struct _HT_INFORMATION_ELE{ + u8 ControlChl; + + u8 ExtChlOffset:2; + u8 RecommemdedTxWidth:1; + u8 RIFS:1; + u8 PSMPAccessOnly:1; + u8 SrvIntGranularity:3; + + u8 OptMode:2; + u8 NonGFDevPresent:1; + u8 Revd1:5; + u8 Revd2:8; + + u8 Rsvd3:6; + u8 DualBeacon:1; + u8 DualCTSProtect:1; + + u8 SecondaryBeacon:1; + u8 LSigTxopProtectFull:1; + u8 PcoActive:1; + u8 PcoPhase:1; + u8 Rsvd4:4; + + u8 BasicMSC[16]; +} __attribute__ ((packed)) HT_INFORMATION_ELE, *PHT_INFORMATION_ELE; + +// +// MIMO Power Save control field. +// This is appear in MIMO Power Save Action Frame +// +typedef struct _MIMOPS_CTRL{ + u8 MimoPsEnable:1; + u8 MimoPsMode:1; + u8 Reserved:6; +} MIMOPS_CTRL, *PMIMOPS_CTRL; + +typedef enum _HT_SPEC_VER{ + HT_SPEC_VER_IEEE = 0, + HT_SPEC_VER_EWC = 1, +}HT_SPEC_VER, *PHT_SPEC_VER; + +typedef enum _HT_AGGRE_MODE_E{ + HT_AGG_AUTO = 0, + HT_AGG_FORCE_ENABLE = 1, + HT_AGG_FORCE_DISABLE = 2, +}HT_AGGRE_MODE_E, *PHT_AGGRE_MODE_E; + +//------------------------------------------------------------ +// The Data structure is used to keep HT related variables when card is +// configured as non-AP STA mode. **Note** Current_xxx should be set +// to default value in HTInitializeHTInfo() +//------------------------------------------------------------ + +typedef struct _RT_HIGH_THROUGHPUT{ + u8 bEnableHT; + u8 bCurrentHTSupport; + + u8 bRegBW40MHz; // Tx 40MHz channel capablity + u8 bCurBW40MHz; // Tx 40MHz channel capability + + u8 bRegShortGI40MHz; // Tx Short GI for 40Mhz + u8 bCurShortGI40MHz; // Tx Short GI for 40MHz + + u8 bRegShortGI20MHz; // Tx Short GI for 20MHz + u8 bCurShortGI20MHz; // Tx Short GI for 20MHz + + u8 bRegSuppCCK; // Tx CCK rate capability + u8 bCurSuppCCK; // Tx CCK rate capability + + // 802.11n spec version for "peer" + HT_SPEC_VER ePeerHTSpecVer; + + + // HT related information for "Self" + HT_CAPABILITY_ELE SelfHTCap; // This is HT cap element sent to peer STA, which also indicate HT Rx capabilities. + HT_INFORMATION_ELE SelfHTInfo; // This is HT info element sent to peer STA, which also indicate HT Rx capabilities. + + // HT related information for "Peer" + u8 PeerHTCapBuf[32]; + u8 PeerHTInfoBuf[32]; + + + // A-MSDU related + u8 bAMSDU_Support; // This indicates Tx A-MSDU capability + u16 nAMSDU_MaxSize; // This indicates Tx A-MSDU capability + u8 bCurrent_AMSDU_Support; // This indicates Tx A-MSDU capability + u16 nCurrent_AMSDU_MaxSize; // This indicates Tx A-MSDU capability + + + // AMPDU related <2006.08.10 Emily> + u8 bAMPDUEnable; // This indicate Tx A-MPDU capability + u8 bCurrentAMPDUEnable; // This indicate Tx A-MPDU capability + u8 AMPDU_Factor; // This indicate Tx A-MPDU capability + u8 CurrentAMPDUFactor; // This indicate Tx A-MPDU capability + u8 MPDU_Density; // This indicate Tx A-MPDU capability + u8 CurrentMPDUDensity; // This indicate Tx A-MPDU capability + + // Forced A-MPDU enable + HT_AGGRE_MODE_E ForcedAMPDUMode; + u8 ForcedAMPDUFactor; + u8 ForcedMPDUDensity; + + // Forced A-MSDU enable + HT_AGGRE_MODE_E ForcedAMSDUMode; + u16 ForcedAMSDUMaxSize; + + u8 bForcedShortGI; + + u8 CurrentOpMode; + + // MIMO PS related + u8 SelfMimoPs; + u8 PeerMimoPs; + + // 40MHz Channel Offset settings. + HT_EXTCHNL_OFFSET CurSTAExtChnlOffset; + u8 bCurTxBW40MHz; // If we use 40 MHz to Tx + u8 PeerBandwidth; + + // For Bandwidth Switching + u8 bSwBwInProgress; + CHNLOP ChnlOp; // software switching channel in progress. By Bruce, 2008-02-15. + u8 SwBwStep; + //struct timer_list SwBwTimer; //moved to ieee80211_device. as timer_list need include some header file here. + + // For Realtek proprietary A-MPDU factor for aggregation + u8 bRegRT2RTAggregation; + u8 bCurrentRT2RTAggregation; + u8 bCurrentRT2RTLongSlotTime; + u8 szRT2RTAggBuffer[10]; + + // Rx Reorder control + u8 bRegRxReorderEnable; + u8 bCurRxReorderEnable; + u8 RxReorderWinSize; + u8 RxReorderPendingTime; + u16 RxReorderDropCounter; + +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + u8 UsbTxAggrNum; +#endif +#ifdef USB_RX_AGGREGATION_SUPPORT + u8 UsbRxFwAggrEn; + u8 UsbRxFwAggrPageNum; + u8 UsbRxFwAggrPacketNum; + u8 UsbRxFwAggrTimeout; +#endif + + // Add for Broadcom(Linksys) IOT. Joseph + u8 bIsPeerBcm; + + // For IOT issue. + u8 IOTPeer; + u32 IOTAction; +} __attribute__ ((packed)) RT_HIGH_THROUGHPUT, *PRT_HIGH_THROUGHPUT; + + +//------------------------------------------------------------ +// The Data structure is used to keep HT related variable for "each Sta" +// when card is configured as "AP mode" +//------------------------------------------------------------ + +typedef struct _RT_HTINFO_STA_ENTRY{ + u8 bEnableHT; + + u8 bSupportCck; + + u16 AMSDU_MaxSize; + + u8 AMPDU_Factor; + u8 MPDU_Density; + + u8 HTHighestOperaRate; + + u8 bBw40MHz; + + u8 MimoPs; + + u8 McsRateSet[16]; + + +}RT_HTINFO_STA_ENTRY, *PRT_HTINFO_STA_ENTRY; + + + + + +//------------------------------------------------------------ +// The Data structure is used to keep HT related variable for "each AP" +// when card is configured as "STA mode" +//------------------------------------------------------------ + +typedef struct _BSS_HT{ + + u8 bdSupportHT; + + // HT related elements + u8 bdHTCapBuf[32]; + u16 bdHTCapLen; + u8 bdHTInfoBuf[32]; + u16 bdHTInfoLen; + + HT_SPEC_VER bdHTSpecVer; + //HT_CAPABILITY_ELE bdHTCapEle; + //HT_INFORMATION_ELE bdHTInfoEle; + + u8 bdRT2RTAggregation; + u8 bdRT2RTLongSlotTime; +} __attribute__ ((packed)) BSS_HT, *PBSS_HT; + +typedef struct _MIMO_RSSI{ + u32 EnableAntenna; + u32 AntennaA; + u32 AntennaB; + u32 AntennaC; + u32 AntennaD; + u32 Average; +}MIMO_RSSI, *PMIMO_RSSI; + +typedef struct _MIMO_EVM{ + u32 EVM1; + u32 EVM2; +}MIMO_EVM, *PMIMO_EVM; + +typedef struct _FALSE_ALARM_STATISTICS{ + u32 Cnt_Parity_Fail; + u32 Cnt_Rate_Illegal; + u32 Cnt_Crc8_fail; + u32 Cnt_all; +}FALSE_ALARM_STATISTICS, *PFALSE_ALARM_STATISTICS; + + +extern u8 MCS_FILTER_ALL[16]; +extern u8 MCS_FILTER_1SS[16]; + +/* 2007/07/11 MH Modify the macro. Becaus STA may link with a N-AP. If we set + STA in A/B/G mode and AP is still in N mode. The macro will be wrong. We have + to add a macro to judge wireless mode. */ +#define PICK_RATE(_nLegacyRate, _nMcsRate) \ + (_nMcsRate==0)?(_nLegacyRate&0x7f):(_nMcsRate) +/* 2007/07/12 MH We only define legacy and HT wireless mode now. */ +#define LEGACY_WIRELESS_MODE IEEE_MODE_MASK + +#define CURRENT_RATE(WirelessMode, LegacyRate, HTRate) \ + ((WirelessMode & (LEGACY_WIRELESS_MODE))!=0)?\ + (LegacyRate):\ + (PICK_RATE(LegacyRate, HTRate)) + + + +// MCS Bw 40 {1~7, 12~15,32} +#define RATE_ADPT_1SS_MASK 0xFF +#define RATE_ADPT_2SS_MASK 0xF0 //Skip MCS8~11 because mcs7 > mcs6, 9, 10, 11. 2007.01.16 by Emily +#define RATE_ADPT_MCS32_MASK 0x01 + +#define IS_11N_MCS_RATE(rate) (rate&0x80) + +typedef enum _HT_AGGRE_SIZE{ + HT_AGG_SIZE_8K = 0, + HT_AGG_SIZE_16K = 1, + HT_AGG_SIZE_32K = 2, + HT_AGG_SIZE_64K = 3, +}HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E; + +/* Indicate different AP vendor for IOT issue */ +typedef enum _HT_IOT_PEER +{ + HT_IOT_PEER_UNKNOWN = 0, + HT_IOT_PEER_REALTEK = 1, + HT_IOT_PEER_BROADCOM = 2, + HT_IOT_PEER_RALINK = 3, + HT_IOT_PEER_ATHEROS = 4, + HT_IOT_PEER_CISCO= 5, + HT_IOT_PEER_MAX = 6 +}HT_IOT_PEER_E, *PHTIOT_PEER_E; + +// +// IOT Action for different AP +// +typedef enum _HT_IOT_ACTION{ + HT_IOT_ACT_TX_USE_AMSDU_4K = 0x00000001, + HT_IOT_ACT_TX_USE_AMSDU_8K = 0x00000002, + HT_IOT_ACT_DISABLE_MCS14 = 0x00000004, + HT_IOT_ACT_DISABLE_MCS15 = 0x00000008, + HT_IOT_ACT_DISABLE_ALL_2SS = 0x00000010, + HT_IOT_ACT_DISABLE_EDCA_TURBO = 0x00000020, + HT_IOT_ACT_MGNT_USE_CCK_6M = 0x00000040, + HT_IOT_ACT_CDD_FSYNC = 0x00000080, + HT_IOT_ACT_PURE_N_MODE = 0x00000100, + HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200, +}HT_IOT_ACTION_E, *PHT_IOT_ACTION_E; + +#endif //_RTL819XU_HTTYPE_H_ + diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c new file mode 100644 index 0000000000000000000000000000000000000000..2c4eb38c89a85d8000461fd0c6062ad3bcb9a429 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c @@ -0,0 +1,1462 @@ + +//As this function is mainly ported from Windows driver, so leave the name little changed. If any confusion caused, tell me. Created by WB. 2008.05.08 +#include "ieee80211.h" +#include "rtl819x_HT.h" +u8 MCS_FILTER_ALL[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +u8 MCS_FILTER_1SS[16] = {0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +u16 MCS_DATA_RATE[2][2][77] = + { { {13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78 ,104, 156, 208, 234, 260, + 39, 78, 117, 234, 312, 351, 390, 52, 104, 156, 208, 312, 416, 468, 520, + 0, 78, 104, 130, 117, 156, 195, 104, 130, 130, 156, 182, 182, 208, 156, 195, + 195, 234, 273, 273, 312, 130, 156, 181, 156, 181, 208, 234, 208, 234, 260, 260, + 286, 195, 234, 273, 234, 273, 312, 351, 312, 351, 390, 390, 429}, // Long GI, 20MHz + {14, 29, 43, 58, 87, 116, 130, 144, 29, 58, 87, 116, 173, 231, 260, 289, + 43, 87, 130, 173, 260, 347, 390, 433, 58, 116, 173, 231, 347, 462, 520, 578, + 0, 87, 116, 144, 130, 173, 217, 116, 144, 144, 173, 202, 202, 231, 173, 217, + 217, 260, 303, 303, 347, 144, 173, 202, 173, 202, 231, 260, 231, 260, 289, 289, + 318, 217, 260, 303, 260, 303, 347, 390, 347, 390, 433, 433, 477} }, // Short GI, 20MHz + { {27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, + 81, 162, 243, 324, 486, 648, 729, 810, 108, 216, 324, 432, 648, 864, 972, 1080, + 12, 162, 216, 270, 243, 324, 405, 216, 270, 270, 324, 378, 378, 432, 324, 405, + 405, 486, 567, 567, 648, 270, 324, 378, 324, 378, 432, 486, 432, 486, 540, 540, + 594, 405, 486, 567, 486, 567, 648, 729, 648, 729, 810, 810, 891}, // Long GI, 40MHz + {30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, + 90, 180, 270, 360, 540, 720, 810, 900, 120, 240, 360, 480, 720, 960, 1080, 1200, + 13, 180, 240, 300, 270, 360, 450, 240, 300, 300, 360, 420, 420, 480, 360, 450, + 450, 540, 630, 630, 720, 300, 360, 420, 360, 420, 480, 540, 480, 540, 600, 600, + 660, 450, 540, 630, 540, 630, 720, 810, 720, 810, 900, 900, 990} } // Short GI, 40MHz + }; + +static u8 UNKNOWN_BORADCOM[3] = {0x00, 0x14, 0xbf}; +static u8 LINKSYSWRT330_LINKSYSWRT300_BROADCOM[3] = {0x00, 0x1a, 0x70}; +static u8 LINKSYSWRT350_LINKSYSWRT150_BROADCOM[3] = {0x00, 0x1d, 0x7e}; +static u8 NETGEAR834Bv2_BROADCOM[3] = {0x00, 0x1b, 0x2f}; +static u8 BELKINF5D8233V1_RALINK[3] = {0x00, 0x17, 0x3f}; //cosa 03202008 +static u8 BELKINF5D82334V3_RALINK[3] = {0x00, 0x1c, 0xdf}; +static u8 PCI_RALINK[3] = {0x00, 0x90, 0xcc}; +static u8 EDIMAX_RALINK[3] = {0x00, 0x0e, 0x2e}; +static u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02}; +//static u8 DLINK_ATHEROS[3] = {0x00, 0x1c, 0xf0}; +static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94}; + +// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Shoud we put the +// code in other place?? +//static u8 WIFI_CISCO_G_AP[3] = {0x00, 0x40, 0x96}; +/******************************************************************************************************************** + *function: This function update default settings in pHTInfo structure + * input: PRT_HIGH_THROUGHPUT pHTInfo + * output: none + * return: none + * notice: These value need be modified if any changes. + * *****************************************************************************************************************/ +void HTUpdateDefaultSetting(struct ieee80211_device* ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + //const typeof( ((struct ieee80211_device *)0)->pHTInfo ) *__mptr = &pHTInfo; + + //printk("pHTinfo:%p, &pHTinfo:%p, mptr:%p, offsetof:%x\n", pHTInfo, &pHTInfo, __mptr, offsetof(struct ieee80211_device, pHTInfo)); + //printk("===>ieee:%p,\n", ieee); + // ShortGI support + pHTInfo->bRegShortGI20MHz= 1; + pHTInfo->bRegShortGI40MHz= 1; + + // 40MHz channel support + pHTInfo->bRegBW40MHz = 1; + + // CCK rate support in 40MHz channel + if(pHTInfo->bRegBW40MHz) + pHTInfo->bRegSuppCCK = 1; + else + pHTInfo->bRegSuppCCK = true; + + // AMSDU related + pHTInfo->nAMSDU_MaxSize = 7935UL; + pHTInfo->bAMSDU_Support = 0; + + // AMPDU related + pHTInfo->bAMPDUEnable = 1; + pHTInfo->AMPDU_Factor = 2; //// 0: 2n13(8K), 1:2n14(16K), 2:2n15(32K), 3:2n16(64k) + pHTInfo->MPDU_Density = 0;// 0: No restriction, 1: 1/8usec, 2: 1/4usec, 3: 1/2usec, 4: 1usec, 5: 2usec, 6: 4usec, 7:8usec + + // MIMO Power Save + pHTInfo->SelfMimoPs = 3;// 0: Static Mimo Ps, 1: Dynamic Mimo Ps, 3: No Limitation, 2: Reserved(Set to 3 automatically.) + if(pHTInfo->SelfMimoPs == 2) + pHTInfo->SelfMimoPs = 3; + // 8190 only. Assign rate operation mode to firmware + ieee->bTxDisableRateFallBack = 0; + ieee->bTxUseDriverAssingedRate = 0; + +#ifdef TO_DO_LIST + // 8190 only. Assign duration operation mode to firmware + pMgntInfo->bTxEnableFwCalcDur = (BOOLEAN)pNdisCommon->bRegTxEnableFwCalcDur; +#endif + // 8190 only, Realtek proprietary aggregation mode + // Set MPDUDensity=2, 1: Set MPDUDensity=2(32k) for Realtek AP and set MPDUDensity=0(8k) for others + pHTInfo->bRegRT2RTAggregation = 1;//0: Set MPDUDensity=2, 1: Set MPDUDensity=2(32k) for Realtek AP and set MPDUDensity=0(8k) for others + + // For Rx Reorder Control + pHTInfo->bRegRxReorderEnable = 1; + pHTInfo->RxReorderWinSize = 64; + pHTInfo->RxReorderPendingTime = 30; + +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + pHTInfo->UsbTxAggrNum = 4; +#endif +#ifdef USB_RX_AGGREGATION_SUPPORT + pHTInfo->UsbRxFwAggrEn = 1; + pHTInfo->UsbRxFwAggrPageNum = 24; + pHTInfo->UsbRxFwAggrPacketNum = 8; + pHTInfo->UsbRxFwAggrTimeout = 16; ////usb rx FW aggregation timeout threshold.It's in units of 64us +#endif + + +} +/******************************************************************************************************************** + *function: This function print out each field on HT capability IE mainly from (Beacon/ProbeRsp/AssocReq) + * input: u8* CapIE //Capability IE to be printed out + * u8* TitleString //mainly print out caller function + * output: none + * return: none + * notice: Driver should not print out this message by default. + * *****************************************************************************************************************/ +void HTDebugHTCapability(u8* CapIE, u8* TitleString ) +{ + + static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; // For 11n EWC definition, 2007.07.17, by Emily + PHT_CAPABILITY_ELE pCapELE; + + if(!memcmp(CapIE, EWC11NHTCap, sizeof(EWC11NHTCap))) + { + //EWC IE + IEEE80211_DEBUG(IEEE80211_DL_HT, "EWC IE in %s()\n", __FUNCTION__); + pCapELE = (PHT_CAPABILITY_ELE)(&CapIE[4]); + }else + pCapELE = (PHT_CAPABILITY_ELE)(&CapIE[0]); + + IEEE80211_DEBUG(IEEE80211_DL_HT, ". Called by %s\n", TitleString ); + + IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupported Channel Width = %s\n", (pCapELE->ChlWidth)?"20MHz": "20/40MHz"); + IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupport Short GI for 20M = %s\n", (pCapELE->ShortGI20Mhz)?"YES": "NO"); + IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupport Short GI for 40M = %s\n", (pCapELE->ShortGI40Mhz)?"YES": "NO"); + IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupport TX STBC = %s\n", (pCapELE->TxSTBC)?"YES": "NO"); + IEEE80211_DEBUG(IEEE80211_DL_HT, "\tMax AMSDU Size = %s\n", (pCapELE->MaxAMSDUSize)?"3839": "7935"); + IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupport CCK in 20/40 mode = %s\n", (pCapELE->DssCCk)?"YES": "NO"); + IEEE80211_DEBUG(IEEE80211_DL_HT, "\tMax AMPDU Factor = %d\n", pCapELE->MaxRxAMPDUFactor); + IEEE80211_DEBUG(IEEE80211_DL_HT, "\tMPDU Density = %d\n", pCapELE->MPDUDensity); + IEEE80211_DEBUG(IEEE80211_DL_HT, "\tMCS Rate Set = [%x][%x][%x][%x][%x]\n", pCapELE->MCS[0],\ + pCapELE->MCS[1], pCapELE->MCS[2], pCapELE->MCS[3], pCapELE->MCS[4]); + return; + +} +/******************************************************************************************************************** + *function: This function print out each field on HT Information IE mainly from (Beacon/ProbeRsp) + * input: u8* InfoIE //Capability IE to be printed out + * u8* TitleString //mainly print out caller function + * output: none + * return: none + * notice: Driver should not print out this message by default. + * *****************************************************************************************************************/ +void HTDebugHTInfo(u8* InfoIE, u8* TitleString) +{ + + static u8 EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34}; // For 11n EWC definition, 2007.07.17, by Emily + PHT_INFORMATION_ELE pHTInfoEle; + + if(!memcmp(InfoIE, EWC11NHTInfo, sizeof(EWC11NHTInfo))) + { + // Not EWC IE + IEEE80211_DEBUG(IEEE80211_DL_HT, "EWC IE in %s()\n", __FUNCTION__); + pHTInfoEle = (PHT_INFORMATION_ELE)(&InfoIE[4]); + }else + pHTInfoEle = (PHT_INFORMATION_ELE)(&InfoIE[0]); + + + IEEE80211_DEBUG(IEEE80211_DL_HT, ". Called by %s\n", TitleString); + + IEEE80211_DEBUG(IEEE80211_DL_HT, "\tPrimary channel = %d\n", pHTInfoEle->ControlChl); + IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSenondary channel ="); + switch(pHTInfoEle->ExtChlOffset) + { + case 0: + IEEE80211_DEBUG(IEEE80211_DL_HT, "Not Present\n"); + break; + case 1: + IEEE80211_DEBUG(IEEE80211_DL_HT, "Upper channel\n"); + break; + case 2: + IEEE80211_DEBUG(IEEE80211_DL_HT, "Reserved. Eooro!!!\n"); + break; + case 3: + IEEE80211_DEBUG(IEEE80211_DL_HT, "Lower Channel\n"); + break; + } + IEEE80211_DEBUG(IEEE80211_DL_HT, "\tRecommended channel width = %s\n", (pHTInfoEle->RecommemdedTxWidth)?"20Mhz": "40Mhz"); + + IEEE80211_DEBUG(IEEE80211_DL_HT, "\tOperation mode for protection = "); + switch(pHTInfoEle->OptMode) + { + case 0: + IEEE80211_DEBUG(IEEE80211_DL_HT, "No Protection\n"); + break; + case 1: + IEEE80211_DEBUG(IEEE80211_DL_HT, "HT non-member protection mode\n"); + break; + case 2: + IEEE80211_DEBUG(IEEE80211_DL_HT, "Suggest to open protection\n"); + break; + case 3: + IEEE80211_DEBUG(IEEE80211_DL_HT, "HT mixed mode\n"); + break; + } + + IEEE80211_DEBUG(IEEE80211_DL_HT, "\tBasic MCS Rate Set = [%x][%x][%x][%x][%x]\n", pHTInfoEle->BasicMSC[0],\ + pHTInfoEle->BasicMSC[1], pHTInfoEle->BasicMSC[2], pHTInfoEle->BasicMSC[3], pHTInfoEle->BasicMSC[4]); + return; +} + +/* +* Return: true if station in half n mode and AP supports 40 bw +*/ +bool IsHTHalfNmode40Bandwidth(struct ieee80211_device* ieee) +{ + bool retValue = false; + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + if(pHTInfo->bCurrentHTSupport == false ) // wireless is n mode + retValue = false; + else if(pHTInfo->bRegBW40MHz == false) // station supports 40 bw + retValue = false; + else if(!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) // station in half n mode + retValue = false; + else if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ChlWidth) // ap support 40 bw + retValue = true; + else + retValue = false; + + return retValue; +} + +bool IsHTHalfNmodeSGI(struct ieee80211_device* ieee, bool is40MHz) +{ + bool retValue = false; + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + if(pHTInfo->bCurrentHTSupport == false ) // wireless is n mode + retValue = false; + else if(!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) // station in half n mode + retValue = false; + else if(is40MHz) // ap support 40 bw + { + if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ShortGI40Mhz) // ap support 40 bw short GI + retValue = true; + else + retValue = false; + } + else + { + if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ShortGI20Mhz) // ap support 40 bw short GI + retValue = true; + else + retValue = false; + } + + return retValue; +} + +u16 HTHalfMcsToDataRate(struct ieee80211_device* ieee, u8 nMcsRate) +{ + + u8 is40MHz; + u8 isShortGI; + + is40MHz = (IsHTHalfNmode40Bandwidth(ieee))?1:0; + isShortGI = (IsHTHalfNmodeSGI(ieee, is40MHz))? 1:0; + + return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate&0x7f)]; +} + + +u16 HTMcsToDataRate( struct ieee80211_device* ieee, u8 nMcsRate) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + u8 is40MHz = (pHTInfo->bCurBW40MHz)?1:0; + u8 isShortGI = (pHTInfo->bCurBW40MHz)? + ((pHTInfo->bCurShortGI40MHz)?1:0): + ((pHTInfo->bCurShortGI20MHz)?1:0); + return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate&0x7f)]; +} + +/******************************************************************************************************************** + *function: This function returns current datarate. + * input: struct ieee80211_device* ieee + * u8 nDataRate + * output: none + * return: tx rate + * notice: quite unsure about how to use this function //wb + * *****************************************************************************************************************/ +u16 TxCountToDataRate( struct ieee80211_device* ieee, u8 nDataRate) +{ + //PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + u16 CCKOFDMRate[12] = {0x02 , 0x04 , 0x0b , 0x16 , 0x0c , 0x12 , 0x18 , 0x24 , 0x30 , 0x48 , 0x60 , 0x6c}; + u8 is40MHz = 0; + u8 isShortGI = 0; + + if(nDataRate < 12) + { + return CCKOFDMRate[nDataRate]; + } + else + { + if (nDataRate >= 0x10 && nDataRate <= 0x1f)//if(nDataRate > 11 && nDataRate < 28 ) + { + is40MHz = 0; + isShortGI = 0; + + // nDataRate = nDataRate - 12; + } + else if(nDataRate >=0x20 && nDataRate <= 0x2f ) //(27, 44) + { + is40MHz = 1; + isShortGI = 0; + + //nDataRate = nDataRate - 28; + } + else if(nDataRate >= 0x30 && nDataRate <= 0x3f ) //(43, 60) + { + is40MHz = 0; + isShortGI = 1; + + //nDataRate = nDataRate - 44; + } + else if(nDataRate >= 0x40 && nDataRate <= 0x4f ) //(59, 76) + { + is40MHz = 1; + isShortGI = 1; + + //nDataRate = nDataRate - 60; + } + return MCS_DATA_RATE[is40MHz][isShortGI][nDataRate&0xf]; + } +} + + + +bool IsHTHalfNmodeAPs(struct ieee80211_device* ieee) +{ + bool retValue = false; + struct ieee80211_network* net = &ieee->current_network; + if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) || + (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) || + (memcmp(net->bssid, PCI_RALINK, 3)==0) || + (memcmp(net->bssid, EDIMAX_RALINK, 3)==0) || + (memcmp(net->bssid, AIRLINK_RALINK, 3)==0) || + (net->ralink_cap_exist)) + retValue = true; + else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) || + (memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)|| + (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)|| + (memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) || + (net->broadcom_cap_exist)) + retValue = true; + else if(net->bssht.bdRT2RTAggregation) + retValue = true; + else + retValue = false; + + return retValue; +} + +/******************************************************************************************************************** + *function: This function returns peer IOT. + * input: struct ieee80211_device* ieee + * output: none + * return: + * notice: + * *****************************************************************************************************************/ +void HTIOTPeerDetermine(struct ieee80211_device* ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + struct ieee80211_network* net = &ieee->current_network; + if(net->bssht.bdRT2RTAggregation) + pHTInfo->IOTPeer = HT_IOT_PEER_REALTEK; + else if(net->broadcom_cap_exist) + pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM; + else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) || + (memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)|| + (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)|| + (memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) ) + pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM; + else if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) || + (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) || + (memcmp(net->bssid, PCI_RALINK, 3)==0) || + (memcmp(net->bssid, EDIMAX_RALINK, 3)==0) || + (memcmp(net->bssid, AIRLINK_RALINK, 3)==0) || + net->ralink_cap_exist) + pHTInfo->IOTPeer = HT_IOT_PEER_RALINK; + else if(net->atheros_cap_exist) + pHTInfo->IOTPeer = HT_IOT_PEER_ATHEROS; + else if(memcmp(net->bssid, CISCO_BROADCOM, 3)==0) + pHTInfo->IOTPeer = HT_IOT_PEER_CISCO; + else + pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN; + + IEEE80211_DEBUG(IEEE80211_DL_IOT, "Joseph debug!! IOTPEER: %x\n", pHTInfo->IOTPeer); +} +/******************************************************************************************************************** + *function: Check whether driver should declare received rate up to MCS13 only since some chipset is not good + * at receiving MCS14~15 frame from some AP. + * input: struct ieee80211_device* ieee + * u8 * PeerMacAddr + * output: none + * return: return 1 if driver should declare MCS13 only(otherwise return 0) + * *****************************************************************************************************************/ +u8 HTIOTActIsDisableMCS14(struct ieee80211_device* ieee, u8* PeerMacAddr) +{ + u8 ret = 0; + return ret; + } + + +/** +* Function: HTIOTActIsDisableMCS15 +* +* Overview: Check whether driver should declare capability of receving MCS15 +* +* Input: +* PADAPTER Adapter, +* +* Output: None +* Return: true if driver should disable MCS15 +* 2008.04.15 Emily +*/ +bool HTIOTActIsDisableMCS15(struct ieee80211_device* ieee) +{ + bool retValue = false; + +#ifdef TODO + // Apply for 819u only +#if (HAL_CODE_BASE==RTL8192) + +#if (DEV_BUS_TYPE == USB_INTERFACE) + // Alway disable MCS15 by Jerry Chang's request.by Emily, 2008.04.15 + retValue = true; +#elif (DEV_BUS_TYPE == PCI_INTERFACE) + // Enable MCS15 if the peer is Cisco AP. by Emily, 2008.05.12 +// if(pBssDesc->bCiscoCapExist) +// retValue = false; +// else + retValue = false; +#endif +#endif +#endif + // Jerry Chang suggest that 8190 1x2 does not need to disable MCS15 + + return retValue; +} + +/** +* Function: HTIOTActIsDisableMCSTwoSpatialStream +* +* Overview: Check whether driver should declare capability of receving All 2 ss packets +* +* Input: +* PADAPTER Adapter, +* +* Output: None +* Return: true if driver should disable all two spatial stream packet +* 2008.04.21 Emily +*/ +bool HTIOTActIsDisableMCSTwoSpatialStream(struct ieee80211_device* ieee, u8 *PeerMacAddr) +{ + bool retValue = false; + +#ifdef TODO + // Apply for 819u only +#endif + return retValue; +} + +/******************************************************************************************************************** + *function: Check whether driver should disable EDCA turbo mode + * input: struct ieee80211_device* ieee + * u8* PeerMacAddr + * output: none + * return: return 1 if driver should disable EDCA turbo mode(otherwise return 0) + * *****************************************************************************************************************/ +u8 HTIOTActIsDisableEDCATurbo(struct ieee80211_device* ieee, u8* PeerMacAddr) +{ + u8 retValue = false; // default enable EDCA Turbo mode. + // Set specific EDCA parameter for different AP in DM handler. + + return retValue; +} + +/******************************************************************************************************************** + *function: Check whether we need to use OFDM to sned MGNT frame for broadcom AP + * input: struct ieee80211_network *network //current network we live + * output: none + * return: return 1 if true + * *****************************************************************************************************************/ +u8 HTIOTActIsMgntUseCCK6M(struct ieee80211_network *network) +{ + u8 retValue = 0; + + // 2008/01/25 MH Judeg if we need to use OFDM to sned MGNT frame for broadcom AP. + // 2008/01/28 MH We must prevent that we select null bssid to link. + + if(network->broadcom_cap_exist) + { + retValue = 1; + } + + return retValue; +} + +u8 HTIOTActIsCCDFsync(u8* PeerMacAddr) +{ + u8 retValue = 0; + if( (memcmp(PeerMacAddr, UNKNOWN_BORADCOM, 3)==0) || + (memcmp(PeerMacAddr, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0) || + (memcmp(PeerMacAddr, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3) ==0)) + { + retValue = 1; + } + + return retValue; +} + +void HTResetIOTSetting( + PRT_HIGH_THROUGHPUT pHTInfo +) +{ + pHTInfo->IOTAction = 0; + pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN; +} + + +/******************************************************************************************************************** + *function: Construct Capablility Element in Beacon... if HTEnable is turned on + * input: struct ieee80211_device* ieee + * u8* posHTCap //pointer to store Capability Ele + * u8* len //store length of CE + * u8 IsEncrypt //whether encrypt, needed further + * output: none + * return: none + * notice: posHTCap can't be null and should be initialized before. + * *****************************************************************************************************************/ +void HTConstructCapabilityElement(struct ieee80211_device* ieee, u8* posHTCap, u8* len, u8 IsEncrypt) +{ + PRT_HIGH_THROUGHPUT pHT = ieee->pHTInfo; + PHT_CAPABILITY_ELE pCapELE = NULL; + //u8 bIsDeclareMCS13; + + if ((posHTCap == NULL) || (pHT == NULL)) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "posHTCap or pHTInfo can't be null in HTConstructCapabilityElement()\n"); + return; + } + memset(posHTCap, 0, *len); + if(pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC) + { + u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; // For 11n EWC definition, 2007.07.17, by Emily + memcpy(posHTCap, EWC11NHTCap, sizeof(EWC11NHTCap)); + pCapELE = (PHT_CAPABILITY_ELE)&(posHTCap[4]); + }else + { + pCapELE = (PHT_CAPABILITY_ELE)posHTCap; + } + + + //HT capability info + pCapELE->AdvCoding = 0; // This feature is not supported now!! + if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) + { + pCapELE->ChlWidth = 0; + } + else + { + pCapELE->ChlWidth = (pHT->bRegBW40MHz?1:0); + } + +// pCapELE->ChlWidth = (pHT->bRegBW40MHz?1:0); + pCapELE->MimoPwrSave = pHT->SelfMimoPs; + pCapELE->GreenField = 0; // This feature is not supported now!! + pCapELE->ShortGI20Mhz = 1; // We can receive Short GI!! + pCapELE->ShortGI40Mhz = 1; // We can receive Short GI!! + //DbgPrint("TX HT cap/info ele BW=%d SG20=%d SG40=%d\n\r", + //pCapELE->ChlWidth, pCapELE->ShortGI20Mhz, pCapELE->ShortGI40Mhz); + pCapELE->TxSTBC = 1; + pCapELE->RxSTBC = 0; + pCapELE->DelayBA = 0; // Do not support now!! + pCapELE->MaxAMSDUSize = (MAX_RECEIVE_BUFFER_SIZE>=7935)?1:0; + pCapELE->DssCCk = ((pHT->bRegBW40MHz)?(pHT->bRegSuppCCK?1:0):0); + pCapELE->PSMP = 0; // Do not support now!! + pCapELE->LSigTxopProtect = 0; // Do not support now!! + + + //MAC HT parameters info + // TODO: Nedd to take care of this part + IEEE80211_DEBUG(IEEE80211_DL_HT, "TX HT cap/info ele BW=%d MaxAMSDUSize:%d DssCCk:%d\n", pCapELE->ChlWidth, pCapELE->MaxAMSDUSize, pCapELE->DssCCk); + + if( IsEncrypt) + { + pCapELE->MPDUDensity = 7; // 8us + pCapELE->MaxRxAMPDUFactor = 2; // 2 is for 32 K and 3 is 64K + } + else + { + pCapELE->MaxRxAMPDUFactor = 3; // 2 is for 32 K and 3 is 64K + pCapELE->MPDUDensity = 0; // no density + } + + //Supported MCS set + memcpy(pCapELE->MCS, ieee->Regdot11HTOperationalRateSet, 16); + if(pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS15) + pCapELE->MCS[1] &= 0x7f; + + if(pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS14) + pCapELE->MCS[1] &= 0xbf; + + if(pHT->IOTAction & HT_IOT_ACT_DISABLE_ALL_2SS) + pCapELE->MCS[1] &= 0x00; + + // 2008.06.12 + // For RTL819X, if pairwisekey = wep/tkip, ap is ralink, we support only MCS0~7. + if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) + { + int i; + for(i = 1; i< 16; i++) + pCapELE->MCS[i] = 0; + } + + //Extended HT Capability Info + memset(&pCapELE->ExtHTCapInfo, 0, 2); + + + //TXBF Capabilities + memset(pCapELE->TxBFCap, 0, 4); + + //Antenna Selection Capabilities + pCapELE->ASCap = 0; +//add 2 to give space for element ID and len when construct frames + if(pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC) + *len = 30 + 2; + else + *len = 26 + 2; + + + +// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_HT, posHTCap, *len -2); + + //Print each field in detail. Driver should not print out this message by default +// HTDebugHTCapability(posHTCap, (u8*)"HTConstructCapability()"); + return; + +} +/******************************************************************************************************************** + *function: Construct Information Element in Beacon... if HTEnable is turned on + * input: struct ieee80211_device* ieee + * u8* posHTCap //pointer to store Information Ele + * u8* len //store len of + * u8 IsEncrypt //whether encrypt, needed further + * output: none + * return: none + * notice: posHTCap can't be null and be initialized before. only AP and IBSS sta should do this + * *****************************************************************************************************************/ +void HTConstructInfoElement(struct ieee80211_device* ieee, u8* posHTInfo, u8* len, u8 IsEncrypt) +{ + PRT_HIGH_THROUGHPUT pHT = ieee->pHTInfo; + PHT_INFORMATION_ELE pHTInfoEle = (PHT_INFORMATION_ELE)posHTInfo; + if ((posHTInfo == NULL) || (pHTInfoEle == NULL)) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "posHTInfo or pHTInfoEle can't be null in HTConstructInfoElement()\n"); + return; + } + + memset(posHTInfo, 0, *len); + if ( (ieee->iw_mode == IW_MODE_ADHOC) || (ieee->iw_mode == IW_MODE_MASTER)) //ap mode is not currently supported + { + pHTInfoEle->ControlChl = ieee->current_network.channel; + pHTInfoEle->ExtChlOffset = ((pHT->bRegBW40MHz == false)?HT_EXTCHNL_OFFSET_NO_EXT: + (ieee->current_network.channel<=6)? + HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + pHTInfoEle->RecommemdedTxWidth = pHT->bRegBW40MHz; + pHTInfoEle->RIFS = 0; + pHTInfoEle->PSMPAccessOnly = 0; + pHTInfoEle->SrvIntGranularity = 0; + pHTInfoEle->OptMode = pHT->CurrentOpMode; + pHTInfoEle->NonGFDevPresent = 0; + pHTInfoEle->DualBeacon = 0; + pHTInfoEle->SecondaryBeacon = 0; + pHTInfoEle->LSigTxopProtectFull = 0; + pHTInfoEle->PcoActive = 0; + pHTInfoEle->PcoPhase = 0; + + memset(pHTInfoEle->BasicMSC, 0, 16); + + + *len = 22 + 2; //same above + + } + else + { + //STA should not generate High Throughput Information Element + *len = 0; + } + //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_HT, posHTInfo, *len - 2); + //HTDebugHTInfo(posHTInfo, "HTConstructInforElement"); + return; +} + +/* + * According to experiment, Realtek AP to STA (based on rtl8190) may achieve best performance + * if both STA and AP set limitation of aggregation size to 32K, that is, set AMPDU density to 2 + * (Ref: IEEE 11n specification). However, if Realtek STA associates to other AP, STA should set + * limitation of aggregation size to 8K, otherwise, performance of traffic stream from STA to AP + * will be much less than the traffic stream from AP to STA if both of the stream runs concurrently + * at the same time. + * + * Frame Format + * Element ID Length OUI Type1 Reserved + * 1 byte 1 byte 3 bytes 1 byte 1 byte + * + * OUI = 0x00, 0xe0, 0x4c, + * Type = 0x02 + * Reserved = 0x00 + * + * 2007.8.21 by Emily +*/ +/******************************************************************************************************************** + *function: Construct Information Element in Beacon... in RT2RT condition + * input: struct ieee80211_device* ieee + * u8* posRT2RTAgg //pointer to store Information Ele + * u8* len //store len + * output: none + * return: none + * notice: + * *****************************************************************************************************************/ +void HTConstructRT2RTAggElement(struct ieee80211_device* ieee, u8* posRT2RTAgg, u8* len) +{ + if (posRT2RTAgg == NULL) { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "posRT2RTAgg can't be null in HTConstructRT2RTAggElement()\n"); + return; + } + memset(posRT2RTAgg, 0, *len); + *posRT2RTAgg++ = 0x00; + *posRT2RTAgg++ = 0xe0; + *posRT2RTAgg++ = 0x4c; + *posRT2RTAgg++ = 0x02; + *posRT2RTAgg++ = 0x01; + *posRT2RTAgg = 0x10;//*posRT2RTAgg = 0x02; + + if(ieee->bSupportRemoteWakeUp) { + *posRT2RTAgg |= 0x08;//RT_HT_CAP_USE_WOW; + } + + *len = 6 + 2; + return; +#ifdef TODO +#if (HAL_CODE_BASE == RTL8192 && DEV_BUS_TYPE == USB_INTERFACE) + /* + //Emily. If it is required to Ask Realtek AP to send AMPDU during AES mode, enable this + section of code. + if(IS_UNDER_11N_AES_MODE(Adapter)) + { + posRT2RTAgg->Octet[5] |=RT_HT_CAP_USE_AMPDU; + }else + { + posRT2RTAgg->Octet[5] &= 0xfb; + } + */ + +#else + // Do Nothing +#endif + + posRT2RTAgg->Length = 6; +#endif + + + + +} + + +/******************************************************************************************************************** + *function: Pick the right Rate Adaptive table to use + * input: struct ieee80211_device* ieee + * u8* pOperateMCS //A pointer to MCS rate bitmap + * return: always we return true + * notice: + * *****************************************************************************************************************/ +u8 HT_PickMCSRate(struct ieee80211_device* ieee, u8* pOperateMCS) +{ + u8 i; + if (pOperateMCS == NULL) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "pOperateMCS can't be null in HT_PickMCSRate()\n"); + return false; + } + + switch(ieee->mode) + { + case IEEE_A: + case IEEE_B: + case IEEE_G: + //legacy rate routine handled at selectedrate + + //no MCS rate + for(i=0;i<=15;i++){ + pOperateMCS[i] = 0; + } + break; + + case IEEE_N_24G: //assume CCK rate ok + case IEEE_N_5G: + // Legacy part we only use 6, 5.5,2,1 for N_24G and 6 for N_5G. + // Legacy part shall be handled at SelectRateSet(). + + //HT part + // TODO: may be different if we have different number of antenna + pOperateMCS[0] &=RATE_ADPT_1SS_MASK; //support MCS 0~7 + pOperateMCS[1] &=RATE_ADPT_2SS_MASK; + pOperateMCS[3] &=RATE_ADPT_MCS32_MASK; + break; + + //should never reach here + default: + + break; + + } + + return true; +} + +/* +* Description: +* This function will get the highest speed rate in input MCS set. +* +* /param Adapter Pionter to Adapter entity +* pMCSRateSet Pointer to MCS rate bitmap +* pMCSFilter Pointer to MCS rate filter +* +* /return Highest MCS rate included in pMCSRateSet and filtered by pMCSFilter. +* +*/ +/******************************************************************************************************************** + *function: This function will get the highest speed rate in input MCS set. + * input: struct ieee80211_device* ieee + * u8* pMCSRateSet //Pointer to MCS rate bitmap + * u8* pMCSFilter //Pointer to MCS rate filter + * return: Highest MCS rate included in pMCSRateSet and filtered by pMCSFilter + * notice: + * *****************************************************************************************************************/ +u8 HTGetHighestMCSRate(struct ieee80211_device* ieee, u8* pMCSRateSet, u8* pMCSFilter) +{ + u8 i, j; + u8 bitMap; + u8 mcsRate = 0; + u8 availableMcsRate[16]; + if (pMCSRateSet == NULL || pMCSFilter == NULL) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "pMCSRateSet or pMCSFilter can't be null in HTGetHighestMCSRate()\n"); + return false; + } + for(i=0; i<16; i++) + availableMcsRate[i] = pMCSRateSet[i] & pMCSFilter[i]; + + for(i = 0; i < 16; i++) + { + if(availableMcsRate[i] != 0) + break; + } + if(i == 16) + return false; + + for(i = 0; i < 16; i++) + { + if(availableMcsRate[i] != 0) + { + bitMap = availableMcsRate[i]; + for(j = 0; j < 8; j++) + { + if((bitMap%2) != 0) + { + if(HTMcsToDataRate(ieee, (8*i+j)) > HTMcsToDataRate(ieee, mcsRate)) + mcsRate = (8*i+j); + } + bitMap = bitMap>>1; + } + } + } + return (mcsRate|0x80); +} + + + +/* +** +**1.Filter our operation rate set with AP's rate set +**2.shall reference channel bandwidth, STBC, Antenna number +**3.generate rate adative table for firmware +**David 20060906 +** +** \pHTSupportedCap: the connected STA's supported rate Capability element +*/ +u8 HTFilterMCSRate( struct ieee80211_device* ieee, u8* pSupportMCS, u8* pOperateMCS) +{ + + u8 i=0; + + // filter out operational rate set not supported by AP, the lenth of it is 16 + for(i=0;i<=15;i++){ + pOperateMCS[i] = ieee->Regdot11HTOperationalRateSet[i]&pSupportMCS[i]; + } + + + // TODO: adjust our operational rate set according to our channel bandwidth, STBC and Antenna number + + // TODO: fill suggested rate adaptive rate index and give firmware info using Tx command packet + // we also shall suggested the first start rate set according to our singal strength + HT_PickMCSRate(ieee, pOperateMCS); + + // For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7. + if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) + pOperateMCS[1] = 0; + + // + // For RTL819X, we support only MCS0~15. + // And also, we do not know how to use MCS32 now. + // + for(i=2; i<=15; i++) + pOperateMCS[i] = 0; + + return true; +} +void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset); +void HTOnAssocRsp(struct ieee80211_device *ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + PHT_CAPABILITY_ELE pPeerHTCap = NULL; + PHT_INFORMATION_ELE pPeerHTInfo = NULL; + u16 nMaxAMSDUSize = 0; + u8* pMcsFilter = NULL; + + static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; // For 11n EWC definition, 2007.07.17, by Emily + static u8 EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34}; // For 11n EWC definition, 2007.07.17, by Emily + + if( pHTInfo->bCurrentHTSupport == false ) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "<=== HTOnAssocRsp(): HT_DISABLE\n"); + return; + } + IEEE80211_DEBUG(IEEE80211_DL_HT, "===> HTOnAssocRsp_wq(): HT_ENABLE\n"); +// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, pHTInfo->PeerHTCapBuf, sizeof(HT_CAPABILITY_ELE)); +// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, pHTInfo->PeerHTInfoBuf, sizeof(HT_INFORMATION_ELE)); + +// HTDebugHTCapability(pHTInfo->PeerHTCapBuf,"HTOnAssocRsp_wq"); +// HTDebugHTInfo(pHTInfo->PeerHTInfoBuf,"HTOnAssocRsp_wq"); + // + if(!memcmp(pHTInfo->PeerHTCapBuf,EWC11NHTCap, sizeof(EWC11NHTCap))) + pPeerHTCap = (PHT_CAPABILITY_ELE)(&pHTInfo->PeerHTCapBuf[4]); + else + pPeerHTCap = (PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf); + + if(!memcmp(pHTInfo->PeerHTInfoBuf, EWC11NHTInfo, sizeof(EWC11NHTInfo))) + pPeerHTInfo = (PHT_INFORMATION_ELE)(&pHTInfo->PeerHTInfoBuf[4]); + else + pPeerHTInfo = (PHT_INFORMATION_ELE)(pHTInfo->PeerHTInfoBuf); + + + //////////////////////////////////////////////////////// + // Configurations: + //////////////////////////////////////////////////////// + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_HT, pPeerHTCap, sizeof(HT_CAPABILITY_ELE)); +// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_HT, pPeerHTInfo, sizeof(HT_INFORMATION_ELE)); + // Config Supported Channel Width setting + // + HTSetConnectBwMode(ieee, (HT_CHANNEL_WIDTH)(pPeerHTCap->ChlWidth), (HT_EXTCHNL_OFFSET)(pPeerHTInfo->ExtChlOffset)); + +// if(pHTInfo->bCurBW40MHz == true) + pHTInfo->bCurTxBW40MHz = ((pPeerHTInfo->RecommemdedTxWidth == 1)?true:false); + + // + // Update short GI/ long GI setting + // + // TODO: + pHTInfo->bCurShortGI20MHz= + ((pHTInfo->bRegShortGI20MHz)?((pPeerHTCap->ShortGI20Mhz==1)?true:false):false); + pHTInfo->bCurShortGI40MHz= + ((pHTInfo->bRegShortGI40MHz)?((pPeerHTCap->ShortGI40Mhz==1)?true:false):false); + + // + // Config TX STBC setting + // + // TODO: + + // + // Config DSSS/CCK mode in 40MHz mode + // + // TODO: + pHTInfo->bCurSuppCCK = + ((pHTInfo->bRegSuppCCK)?((pPeerHTCap->DssCCk==1)?true:false):false); + + + // + // Config and configure A-MSDU setting + // + pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support; + + nMaxAMSDUSize = (pPeerHTCap->MaxAMSDUSize==0)?3839:7935; + + if(pHTInfo->nAMSDU_MaxSize > nMaxAMSDUSize ) + pHTInfo->nCurrent_AMSDU_MaxSize = nMaxAMSDUSize; + else + pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize; + + + // + // Config A-MPDU setting + // + pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable; + + // <1> Decide AMPDU Factor + + // By Emily + if(!pHTInfo->bRegRT2RTAggregation) + { + // Decide AMPDU Factor according to protocol handshake + if(pHTInfo->AMPDU_Factor > pPeerHTCap->MaxRxAMPDUFactor) + pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor; + else + pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor; + + }else + { + // Set MPDU density to 2 to Realtek AP, and set it to 0 for others + // Replace MPDU factor declared in original association response frame format. 2007.08.20 by Emily + if (ieee->current_network.bssht.bdRT2RTAggregation) + { + if( ieee->pairwise_key_type != KEY_TYPE_NA) + // Realtek may set 32k in security mode and 64k for others + pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor; + else + pHTInfo->CurrentAMPDUFactor = HT_AGG_SIZE_64K; + }else + { + if(pPeerHTCap->MaxRxAMPDUFactor < HT_AGG_SIZE_32K) + pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor; + else + pHTInfo->CurrentAMPDUFactor = HT_AGG_SIZE_32K; + } + } + + // <2> Set AMPDU Minimum MPDU Start Spacing + // 802.11n 3.0 section 9.7d.3 + if(pHTInfo->MPDU_Density > pPeerHTCap->MPDUDensity) + pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density; + else + pHTInfo->CurrentMPDUDensity = pPeerHTCap->MPDUDensity; + if(ieee->pairwise_key_type != KEY_TYPE_NA ) + pHTInfo->CurrentMPDUDensity = 7; // 8us + // Force TX AMSDU + + // Lanhsin: mark for tmp to avoid deauth by ap from s3 + //if(memcmp(pMgntInfo->Bssid, NETGEAR834Bv2_BROADCOM, 3)==0) + if(0) + { + + pHTInfo->bCurrentAMPDUEnable = false; + pHTInfo->ForcedAMSDUMode = HT_AGG_FORCE_ENABLE; + pHTInfo->ForcedAMSDUMaxSize = 7935; + + pHTInfo->IOTAction |= HT_IOT_ACT_TX_USE_AMSDU_8K; + } + + // Rx Reorder Setting + pHTInfo->bCurRxReorderEnable = pHTInfo->bRegRxReorderEnable; + + // + // Filter out unsupported HT rate for this AP + // Update RATR table + // This is only for 8190 ,8192 or later product which using firmware to handle rate adaptive mechanism. + // + + // Handle Ralink AP bad MCS rate set condition. Joseph. + // This fix the bug of Ralink AP. This may be removed in the future. + if(pPeerHTCap->MCS[0] == 0) + pPeerHTCap->MCS[0] = 0xff; + + HTFilterMCSRate(ieee, pPeerHTCap->MCS, ieee->dot11HTOperationalRateSet); + + // + // Config MIMO Power Save setting + // + pHTInfo->PeerMimoPs = pPeerHTCap->MimoPwrSave; + if(pHTInfo->PeerMimoPs == MIMO_PS_STATIC) + pMcsFilter = MCS_FILTER_1SS; + else + pMcsFilter = MCS_FILTER_ALL; + //WB add for MCS8 bug +// pMcsFilter = MCS_FILTER_1SS; + ieee->HTHighestOperaRate = HTGetHighestMCSRate(ieee, ieee->dot11HTOperationalRateSet, pMcsFilter); + ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate; + + // + // Config current operation mode. + // + pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode; + + + +} + +void HTSetConnectBwModeCallback(struct ieee80211_device* ieee); +/******************************************************************************************************************** + *function: initialize HT info(struct PRT_HIGH_THROUGHPUT) + * input: struct ieee80211_device* ieee + * output: none + * return: none + * notice: This function is called when * (1) MPInitialization Phase * (2) Receiving of Deauthentication from AP +********************************************************************************************************************/ +// TODO: Should this funciton be called when receiving of Disassociation? +void HTInitializeHTInfo(struct ieee80211_device* ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + // + // These parameters will be reset when receiving deauthentication packet + // + IEEE80211_DEBUG(IEEE80211_DL_HT, "===========>%s()\n", __FUNCTION__); + pHTInfo->bCurrentHTSupport = false; + + // 40MHz channel support + pHTInfo->bCurBW40MHz = false; + pHTInfo->bCurTxBW40MHz = false; + + // Short GI support + pHTInfo->bCurShortGI20MHz = false; + pHTInfo->bCurShortGI40MHz = false; + pHTInfo->bForcedShortGI = false; + + // CCK rate support + // This flag is set to true to support CCK rate by default. + // It will be affected by "pHTInfo->bRegSuppCCK" and AP capabilities only when associate to + // 11N BSS. + pHTInfo->bCurSuppCCK = true; + + // AMSDU related + pHTInfo->bCurrent_AMSDU_Support = false; + pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize; + + // AMPUD related + pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density; + pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor; + + + + // Initialize all of the parameters related to 11n + memset((void*)(&(pHTInfo->SelfHTCap)), 0, sizeof(pHTInfo->SelfHTCap)); + memset((void*)(&(pHTInfo->SelfHTInfo)), 0, sizeof(pHTInfo->SelfHTInfo)); + memset((void*)(&(pHTInfo->PeerHTCapBuf)), 0, sizeof(pHTInfo->PeerHTCapBuf)); + memset((void*)(&(pHTInfo->PeerHTInfoBuf)), 0, sizeof(pHTInfo->PeerHTInfoBuf)); + + pHTInfo->bSwBwInProgress = false; + pHTInfo->ChnlOp = CHNLOP_NONE; + + // Set default IEEE spec for Draft N + pHTInfo->ePeerHTSpecVer = HT_SPEC_VER_IEEE; + + // Realtek proprietary aggregation mode + pHTInfo->bCurrentRT2RTAggregation = false; + pHTInfo->bCurrentRT2RTLongSlotTime = false; + pHTInfo->IOTPeer = 0; + pHTInfo->IOTAction = 0; + + //MCS rate initialized here + { + u8* RegHTSuppRateSets = &(ieee->RegHTSuppRateSet[0]); + RegHTSuppRateSets[0] = 0xFF; //support MCS 0~7 + RegHTSuppRateSets[1] = 0xFF; //support MCS 8~15 + RegHTSuppRateSets[4] = 0x01; //support MCS 32 + } +} +/******************************************************************************************************************** + *function: initialize Bss HT structure(struct PBSS_HT) + * input: PBSS_HT pBssHT //to be initialized + * output: none + * return: none + * notice: This function is called when initialize network structure +********************************************************************************************************************/ +void HTInitializeBssDesc(PBSS_HT pBssHT) +{ + + pBssHT->bdSupportHT = false; + memset(pBssHT->bdHTCapBuf, 0, sizeof(pBssHT->bdHTCapBuf)); + pBssHT->bdHTCapLen = 0; + memset(pBssHT->bdHTInfoBuf, 0, sizeof(pBssHT->bdHTInfoBuf)); + pBssHT->bdHTInfoLen = 0; + + pBssHT->bdHTSpecVer= HT_SPEC_VER_IEEE; + + pBssHT->bdRT2RTAggregation = false; + pBssHT->bdRT2RTLongSlotTime = false; +} +/******************************************************************************************************************** + *function: initialize Bss HT structure(struct PBSS_HT) + * input: struct ieee80211_device *ieee + * struct ieee80211_network *pNetwork //usually current network we are live in + * output: none + * return: none + * notice: This function should ONLY be called before association +********************************************************************************************************************/ +void HTResetSelfAndSavePeerSetting(struct ieee80211_device* ieee, struct ieee80211_network * pNetwork) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; +// u16 nMaxAMSDUSize; +// PHT_CAPABILITY_ELE pPeerHTCap = (PHT_CAPABILITY_ELE)pNetwork->bssht.bdHTCapBuf; +// PHT_INFORMATION_ELE pPeerHTInfo = (PHT_INFORMATION_ELE)pNetwork->bssht.bdHTInfoBuf; +// u8* pMcsFilter; + u8 bIOTAction = 0; + + // + // Save Peer Setting before Association + // + IEEE80211_DEBUG(IEEE80211_DL_HT, "==============>%s()\n", __FUNCTION__); + /*unmark bEnableHT flag here is the same reason why unmarked in function ieee80211_softmac_new_net. WB 2008.09.10*/ +// if( pHTInfo->bEnableHT && pNetwork->bssht.bdSupportHT) + if (pNetwork->bssht.bdSupportHT) + { + pHTInfo->bCurrentHTSupport = true; + pHTInfo->ePeerHTSpecVer = pNetwork->bssht.bdHTSpecVer; + + // Save HTCap and HTInfo information Element + if(pNetwork->bssht.bdHTCapLen > 0 && pNetwork->bssht.bdHTCapLen <= sizeof(pHTInfo->PeerHTCapBuf)) + memcpy(pHTInfo->PeerHTCapBuf, pNetwork->bssht.bdHTCapBuf, pNetwork->bssht.bdHTCapLen); + + if(pNetwork->bssht.bdHTInfoLen > 0 && pNetwork->bssht.bdHTInfoLen <= sizeof(pHTInfo->PeerHTInfoBuf)) + memcpy(pHTInfo->PeerHTInfoBuf, pNetwork->bssht.bdHTInfoBuf, pNetwork->bssht.bdHTInfoLen); + + // Check whether RT to RT aggregation mode is enabled + if(pHTInfo->bRegRT2RTAggregation) + { + pHTInfo->bCurrentRT2RTAggregation = pNetwork->bssht.bdRT2RTAggregation; + pHTInfo->bCurrentRT2RTLongSlotTime = pNetwork->bssht.bdRT2RTLongSlotTime; + } + else + { + pHTInfo->bCurrentRT2RTAggregation = false; + pHTInfo->bCurrentRT2RTLongSlotTime = false; + } + + // Determine the IOT Peer Vendor. + HTIOTPeerDetermine(ieee); + + // Decide IOT Action + // Must be called after the parameter of pHTInfo->bCurrentRT2RTAggregation is decided + pHTInfo->IOTAction = 0; + bIOTAction = HTIOTActIsDisableMCS14(ieee, pNetwork->bssid); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS14; + + bIOTAction = HTIOTActIsDisableMCS15(ieee); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS15; + + bIOTAction = HTIOTActIsDisableMCSTwoSpatialStream(ieee, pNetwork->bssid); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_ALL_2SS; + + + bIOTAction = HTIOTActIsDisableEDCATurbo(ieee, pNetwork->bssid); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_EDCA_TURBO; + + bIOTAction = HTIOTActIsMgntUseCCK6M(pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_MGNT_USE_CCK_6M; + + bIOTAction = HTIOTActIsCCDFsync(pNetwork->bssid); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_CDD_FSYNC; + + + } + else + { + pHTInfo->bCurrentHTSupport = false; + pHTInfo->bCurrentRT2RTAggregation = false; + pHTInfo->bCurrentRT2RTLongSlotTime = false; + + pHTInfo->IOTAction = 0; + } + +} + +void HTUpdateSelfAndPeerSetting(struct ieee80211_device* ieee, struct ieee80211_network * pNetwork) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; +// PHT_CAPABILITY_ELE pPeerHTCap = (PHT_CAPABILITY_ELE)pNetwork->bssht.bdHTCapBuf; + PHT_INFORMATION_ELE pPeerHTInfo = (PHT_INFORMATION_ELE)pNetwork->bssht.bdHTInfoBuf; + + if(pHTInfo->bCurrentHTSupport) + { + // + // Config current operation mode. + // + if(pNetwork->bssht.bdHTInfoLen != 0) + pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode; + + // + // + // + } +} + +void HTUseDefaultSetting(struct ieee80211_device* ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; +// u8 regBwOpMode; + + if(pHTInfo->bEnableHT) + { + pHTInfo->bCurrentHTSupport = true; + + pHTInfo->bCurSuppCCK = pHTInfo->bRegSuppCCK; + + pHTInfo->bCurBW40MHz = pHTInfo->bRegBW40MHz; + + pHTInfo->bCurShortGI20MHz= pHTInfo->bRegShortGI20MHz; + + pHTInfo->bCurShortGI40MHz= pHTInfo->bRegShortGI40MHz; + + pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support; + + pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize; + + pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable; + + pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor; + + pHTInfo->CurrentMPDUDensity = pHTInfo->CurrentMPDUDensity; + + // Set BWOpMode register + + //update RATR index0 + HTFilterMCSRate(ieee, ieee->Regdot11HTOperationalRateSet, ieee->dot11HTOperationalRateSet); + //function below is not implemented at all. WB +#ifdef TODO + Adapter->HalFunc.InitHalRATRTableHandler( Adapter, &pMgntInfo->dot11OperationalRateSet, pMgntInfo->dot11HTOperationalRateSet); +#endif + ieee->HTHighestOperaRate = HTGetHighestMCSRate(ieee, ieee->dot11HTOperationalRateSet, MCS_FILTER_ALL); + ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate; + + } + else + { + pHTInfo->bCurrentHTSupport = false; + } + return; +} +/******************************************************************************************************************** + *function: check whether HT control field exists + * input: struct ieee80211_device *ieee + * u8* pFrame //coming skb->data + * output: none + * return: return true if HT control field exists(false otherwise) + * notice: +********************************************************************************************************************/ +u8 HTCCheck(struct ieee80211_device* ieee, u8* pFrame) +{ + if(ieee->pHTInfo->bCurrentHTSupport) + { + if( (IsQoSDataFrame(pFrame) && Frame_Order(pFrame)) == 1) + { + IEEE80211_DEBUG(IEEE80211_DL_HT, "HT CONTROL FILED EXIST!!\n"); + return true; + } + } + return false; +} + +// +// This function set bandwidth mode in protocol layer. +// +void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; +// u32 flags = 0; + + if(pHTInfo->bRegBW40MHz == false) + return; + + + + // To reduce dummy operation +// if((pHTInfo->bCurBW40MHz==false && Bandwidth==HT_CHANNEL_WIDTH_20) || +// (pHTInfo->bCurBW40MHz==true && Bandwidth==HT_CHANNEL_WIDTH_20_40 && Offset==pHTInfo->CurSTAExtChnlOffset)) +// return; + +// spin_lock_irqsave(&(ieee->bw_spinlock), flags); + if(pHTInfo->bSwBwInProgress) { +// spin_unlock_irqrestore(&(ieee->bw_spinlock), flags); + return; + } + //if in half N mode, set to 20M bandwidth please 09.08.2008 WB. + if(Bandwidth==HT_CHANNEL_WIDTH_20_40 && (!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))) + { + // Handle Illegal extention channel offset!! + if(ieee->current_network.channel<2 && Offset==HT_EXTCHNL_OFFSET_LOWER) + Offset = HT_EXTCHNL_OFFSET_NO_EXT; + if(Offset==HT_EXTCHNL_OFFSET_UPPER || Offset==HT_EXTCHNL_OFFSET_LOWER) { + pHTInfo->bCurBW40MHz = true; + pHTInfo->CurSTAExtChnlOffset = Offset; + } else { + pHTInfo->bCurBW40MHz = false; + pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT; + } + } else { + pHTInfo->bCurBW40MHz = false; + pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT; + } + + pHTInfo->bSwBwInProgress = true; + + // TODO: 2007.7.13 by Emily Wait 2000ms in order to garantee that switching + // bandwidth is executed after scan is finished. It is a temporal solution + // because software should ganrantee the last operation of switching bandwidth + // is executed properlly. + HTSetConnectBwModeCallback(ieee); + +// spin_unlock_irqrestore(&(ieee->bw_spinlock), flags); +} + +void HTSetConnectBwModeCallback(struct ieee80211_device* ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + IEEE80211_DEBUG(IEEE80211_DL_HT, "======>%s()\n", __FUNCTION__); + + if(pHTInfo->bCurBW40MHz) + { + if(pHTInfo->CurSTAExtChnlOffset==HT_EXTCHNL_OFFSET_UPPER) + ieee->set_chan(ieee->dev, ieee->current_network.channel+2); + else if(pHTInfo->CurSTAExtChnlOffset==HT_EXTCHNL_OFFSET_LOWER) + ieee->set_chan(ieee->dev, ieee->current_network.channel-2); + else + ieee->set_chan(ieee->dev, ieee->current_network.channel); + + ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset); + } else { + ieee->set_chan(ieee->dev, ieee->current_network.channel); + ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + } + + pHTInfo->bSwBwInProgress = false; +} + +EXPORT_SYMBOL(HTUpdateSelfAndPeerSetting); diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_Qos.h b/drivers/staging/rtl8192u/ieee80211/rtl819x_Qos.h new file mode 100644 index 0000000000000000000000000000000000000000..13b1e5ca436d6911d644cbe116bdd10c69a440a5 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_Qos.h @@ -0,0 +1,583 @@ +#ifndef __INC_QOS_TYPE_H +#define __INC_QOS_TYPE_H + +//#include "EndianFree.h" +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#define MAX_WMMELE_LENGTH 64 + +// +// QoS mode. +// enum 0, 1, 2, 4: since we can use the OR(|) operation. +// +// QOS_MODE is redefined for enum can't be ++, | under C++ compiler, 2006.05.17, by rcnjko. +//typedef enum _QOS_MODE{ +// QOS_DISABLE = 0, +// QOS_WMM = 1, +// QOS_EDCA = 2, +// QOS_HCCA = 4, +//}QOS_MODE,*PQOS_MODE; +// +typedef u32 QOS_MODE, *PQOS_MODE; +#define QOS_DISABLE 0 +#define QOS_WMM 1 +#define QOS_WMMSA 2 +#define QOS_EDCA 4 +#define QOS_HCCA 8 +#define QOS_WMM_UAPSD 16 //WMM Power Save, 2006-06-14 Isaiah + +#define AC_PARAM_SIZE 4 +#define WMM_PARAM_ELE_BODY_LEN 18 + +// +// QoS ACK Policy Field Values +// Ref: WMM spec 2.1.6: QoS Control Field, p.10. +// +typedef enum _ACK_POLICY{ + eAckPlc0_ACK = 0x00, + eAckPlc1_NoACK = 0x01, +}ACK_POLICY,*PACK_POLICY; + +#define WMM_PARAM_ELEMENT_SIZE (8+(4*AC_PARAM_SIZE)) + +// +// QoS Control Field +// Ref: +// 1. WMM spec 2.1.6: QoS Control Field, p.9. +// 2. 802.11e/D13.0 7.1.3.5, p.26. +// +typedef union _QOS_CTRL_FIELD{ + u8 charData[2]; + u16 shortData; + + // WMM spec + struct + { + u8 UP:3; + u8 usRsvd1:1; + u8 EOSP:1; + u8 AckPolicy:2; + u8 usRsvd2:1; + u8 ucRsvdByte; + }WMM; + + // 802.11e: QoS data type frame sent by non-AP QSTAs. + struct + { + u8 TID:4; + u8 bIsQsize:1;// 0: BIT[8:15] is TXOP Duration Requested, 1: BIT[8:15] is Queue Size. + u8 AckPolicy:2; + u8 usRsvd:1; + u8 TxopOrQsize; // (BIT4=0)TXOP Duration Requested or (BIT4=1)Queue Size. + }BySta; + + // 802.11e: QoS data, QoS Null, and QoS Data+CF-Ack frames sent by HC. + struct + { + u8 TID:4; + u8 EOSP:1; + u8 AckPolicy:2; + u8 usRsvd:1; + u8 PSBufState; // QAP PS Buffer State. + }ByHc_Data; + + // 802.11e: QoS (+) CF-Poll frames sent by HC. + struct + { + u8 TID:4; + u8 EOSP:1; + u8 AckPolicy:2; + u8 usRsvd:1; + u8 TxopLimit; // TXOP Limit. + }ByHc_CFP; + +}QOS_CTRL_FIELD, *PQOS_CTRL_FIELD; + + +// +// QoS Info Field +// Ref: +// 1. WMM spec 2.2.1: WME Information Element, p.11. +// 2. 8185 QoS code: QOS_INFO [def. in QoS_mp.h] +// +typedef union _QOS_INFO_FIELD{ + u8 charData; + + struct + { + u8 ucParameterSetCount:4; + u8 ucReserved:4; + }WMM; + + struct + { + //Ref WMM_Specification_1-1.pdf, 2006-06-13 Isaiah + u8 ucAC_VO_UAPSD:1; + u8 ucAC_VI_UAPSD:1; + u8 ucAC_BE_UAPSD:1; + u8 ucAC_BK_UAPSD:1; + u8 ucReserved1:1; + u8 ucMaxSPLen:2; + u8 ucReserved2:1; + + }ByWmmPsSta; + + struct + { + //Ref WMM_Specification_1-1.pdf, 2006-06-13 Isaiah + u8 ucParameterSetCount:4; + u8 ucReserved:3; + u8 ucApUapsd:1; + }ByWmmPsAp; + + struct + { + u8 ucAC3_UAPSD:1; + u8 ucAC2_UAPSD:1; + u8 ucAC1_UAPSD:1; + u8 ucAC0_UAPSD:1; + u8 ucQAck:1; + u8 ucMaxSPLen:2; + u8 ucMoreDataAck:1; + } By11eSta; + + struct + { + u8 ucParameterSetCount:4; + u8 ucQAck:1; + u8 ucQueueReq:1; + u8 ucTXOPReq:1; + u8 ucReserved:1; + } By11eAp; + + struct + { + u8 ucReserved1:4; + u8 ucQAck:1; + u8 ucReserved2:2; + u8 ucMoreDataAck:1; + } ByWmmsaSta; + + struct + { + u8 ucReserved1:4; + u8 ucQAck:1; + u8 ucQueueReq:1; + u8 ucTXOPReq:1; + u8 ucReserved2:1; + } ByWmmsaAp; + + struct + { + u8 ucAC3_UAPSD:1; + u8 ucAC2_UAPSD:1; + u8 ucAC1_UAPSD:1; + u8 ucAC0_UAPSD:1; + u8 ucQAck:1; + u8 ucMaxSPLen:2; + u8 ucMoreDataAck:1; + } ByAllSta; + + struct + { + u8 ucParameterSetCount:4; + u8 ucQAck:1; + u8 ucQueueReq:1; + u8 ucTXOPReq:1; + u8 ucApUapsd:1; + } ByAllAp; + +}QOS_INFO_FIELD, *PQOS_INFO_FIELD; + + +// +// ACI to AC coding. +// Ref: WMM spec 2.2.2: WME Parameter Element, p.13. +// +// AC_CODING is redefined for enum can't be ++, | under C++ compiler, 2006.05.17, by rcnjko. +//typedef enum _AC_CODING{ +// AC0_BE = 0, // ACI: 0x00 // Best Effort +// AC1_BK = 1, // ACI: 0x01 // Background +// AC2_VI = 2, // ACI: 0x10 // Video +// AC3_VO = 3, // ACI: 0x11 // Voice +// AC_MAX = 4, // Max: define total number; Should not to be used as a real enum. +//}AC_CODING,*PAC_CODING; +// +typedef u32 AC_CODING; +#define AC0_BE 0 // ACI: 0x00 // Best Effort +#define AC1_BK 1 // ACI: 0x01 // Background +#define AC2_VI 2 // ACI: 0x10 // Video +#define AC3_VO 3 // ACI: 0x11 // Voice +#define AC_MAX 4 // Max: define total number; Should not to be used as a real enum. + +// +// ACI/AIFSN Field. +// Ref: WMM spec 2.2.2: WME Parameter Element, p.12. +// +typedef union _ACI_AIFSN{ + u8 charData; + + struct + { + u8 AIFSN:4; + u8 ACM:1; + u8 ACI:2; + u8 Reserved:1; + }f; // Field +}ACI_AIFSN, *PACI_AIFSN; + +// +// ECWmin/ECWmax field. +// Ref: WMM spec 2.2.2: WME Parameter Element, p.13. +// +typedef union _ECW{ + u8 charData; + struct + { + u8 ECWmin:4; + u8 ECWmax:4; + }f; // Field +}ECW, *PECW; + +// +// AC Parameters Record Format. +// Ref: WMM spec 2.2.2: WME Parameter Element, p.12. +// +typedef union _AC_PARAM{ + u32 longData; + u8 charData[4]; + + struct + { + ACI_AIFSN AciAifsn; + ECW Ecw; + u16 TXOPLimit; + }f; // Field +}AC_PARAM, *PAC_PARAM; + + + +// +// QoS element subtype +// +typedef enum _QOS_ELE_SUBTYPE{ + QOSELE_TYPE_INFO = 0x00, // 0x00: Information element + QOSELE_TYPE_PARAM = 0x01, // 0x01: parameter element +}QOS_ELE_SUBTYPE,*PQOS_ELE_SUBTYPE; + + +// +// Direction Field Values. +// Ref: WMM spec 2.2.11: WME TSPEC Element, p.18. +// +typedef enum _DIRECTION_VALUE{ + DIR_UP = 0, // 0x00 // UpLink + DIR_DOWN = 1, // 0x01 // DownLink + DIR_DIRECT = 2, // 0x10 // DirectLink + DIR_BI_DIR = 3, // 0x11 // Bi-Direction +}DIRECTION_VALUE,*PDIRECTION_VALUE; + + +// +// TS Info field in WMM TSPEC Element. +// Ref: +// 1. WMM spec 2.2.11: WME TSPEC Element, p.18. +// 2. 8185 QoS code: QOS_TSINFO [def. in QoS_mp.h] +// +typedef union _QOS_TSINFO{ + u8 charData[3]; + struct { + u8 ucTrafficType:1; //WMM is reserved + u8 ucTSID:4; + u8 ucDirection:2; + u8 ucAccessPolicy:2; //WMM: bit8=0, bit7=1 + u8 ucAggregation:1; //WMM is reserved + u8 ucPSB:1; //WMMSA is APSD + u8 ucUP:3; + u8 ucTSInfoAckPolicy:2; //WMM is reserved + u8 ucSchedule:1; //WMM is reserved + u8 ucReserved:7; + }field; +}QOS_TSINFO, *PQOS_TSINFO; + +// +// WMM TSPEC Body. +// Ref: WMM spec 2.2.11: WME TSPEC Element, p.16. +// +typedef union _TSPEC_BODY{ + u8 charData[55]; + + struct + { + QOS_TSINFO TSInfo; //u8 TSInfo[3]; + u16 NominalMSDUsize; + u16 MaxMSDUsize; + u32 MinServiceItv; + u32 MaxServiceItv; + u32 InactivityItv; + u32 SuspenItv; + u32 ServiceStartTime; + u32 MinDataRate; + u32 MeanDataRate; + u32 PeakDataRate; + u32 MaxBurstSize; + u32 DelayBound; + u32 MinPhyRate; + u16 SurplusBandwidthAllowance; + u16 MediumTime; + } f; // Field +}TSPEC_BODY, *PTSPEC_BODY; + + +// +// WMM TSPEC Element. +// Ref: WMM spec 2.2.11: WME TSPEC Element, p.16. +// +typedef struct _WMM_TSPEC{ + u8 ID; + u8 Length; + u8 OUI[3]; + u8 OUI_Type; + u8 OUI_SubType; + u8 Version; + TSPEC_BODY Body; +} WMM_TSPEC, *PWMM_TSPEC; + +// +// ACM implementation method. +// Annie, 2005-12-13. +// +typedef enum _ACM_METHOD{ + eAcmWay0_SwAndHw = 0, // By SW and HW. + eAcmWay1_HW = 1, // By HW. + eAcmWay2_SW = 2, // By SW. +}ACM_METHOD,*PACM_METHOD; + + +typedef struct _ACM{ +// u8 RegEnableACM; + u64 UsedTime; + u64 MediumTime; + u8 HwAcmCtl; // TRUE: UsedTime exceed => Do NOT USE this AC. It wll be written to ACM_CONTROL(0xBF BIT 0/1/2 in 8185B). +}ACM, *PACM; + +typedef u8 AC_UAPSD, *PAC_UAPSD; + +#define GET_VO_UAPSD(_apsd) ((_apsd) & BIT0) +#define SET_VO_UAPSD(_apsd) ((_apsd) |= BIT0) + +#define GET_VI_UAPSD(_apsd) ((_apsd) & BIT1) +#define SET_VI_UAPSD(_apsd) ((_apsd) |= BIT1) + +#define GET_BK_UAPSD(_apsd) ((_apsd) & BIT2) +#define SET_BK_UAPSD(_apsd) ((_apsd) |= BIT2) + +#define GET_BE_UAPSD(_apsd) ((_apsd) & BIT3) +#define SET_BE_UAPSD(_apsd) ((_apsd) |= BIT3) + + +//typedef struct _TCLASS{ +// TODO +//} TCLASS, *PTCLASS; +typedef union _QOS_TCLAS{ + + struct _TYPE_GENERAL{ + u8 Priority; + u8 ClassifierType; + u8 Mask; + } TYPE_GENERAL; + + struct _TYPE0_ETH{ + u8 Priority; + u8 ClassifierType; + u8 Mask; + u8 SrcAddr[6]; + u8 DstAddr[6]; + u16 Type; + } TYPE0_ETH; + + struct _TYPE1_IPV4{ + u8 Priority; + u8 ClassifierType; + u8 Mask; + u8 Version; + u8 SrcIP[4]; + u8 DstIP[4]; + u16 SrcPort; + u16 DstPort; + u8 DSCP; + u8 Protocol; + u8 Reserved; + } TYPE1_IPV4; + + struct _TYPE1_IPV6{ + u8 Priority; + u8 ClassifierType; + u8 Mask; + u8 Version; + u8 SrcIP[16]; + u8 DstIP[16]; + u16 SrcPort; + u16 DstPort; + u8 FlowLabel[3]; + } TYPE1_IPV6; + + struct _TYPE2_8021Q{ + u8 Priority; + u8 ClassifierType; + u8 Mask; + u16 TagType; + } TYPE2_8021Q; +} QOS_TCLAS, *PQOS_TCLAS; + +//typedef struct _WMM_TSTREAM{ +// +//- TSPEC +//- AC (which to mapping) +//} WMM_TSTREAM, *PWMM_TSTREAM; +typedef struct _QOS_TSTREAM{ + u8 AC; + WMM_TSPEC TSpec; + QOS_TCLAS TClass; +} QOS_TSTREAM, *PQOS_TSTREAM; + +//typedef struct _U_APSD{ +//- TriggerEnable [4] +//- MaxSPLength +//- HighestAcBuffered +//} U_APSD, *PU_APSD; + +//joseph TODO: +// UAPSD function should be implemented by 2 data structure +// "Qos control field" and "Qos info field" +//typedef struct _QOS_UAPSD{ +// u8 bTriggerEnable[4]; +// u8 MaxSPLength; +// u8 HighestBufAC; +//} QOS_UAPSD, *PQOS_APSD; + +//---------------------------------------------------------------------------- +// 802.11 Management frame Status Code field +//---------------------------------------------------------------------------- +typedef struct _OCTET_STRING{ + u8 *Octet; + u16 Length; +}OCTET_STRING, *POCTET_STRING; +// +// STA QoS data. +// Ref: DOT11_QOS in 8185 code. [def. in QoS_mp.h] +// +typedef struct _STA_QOS{ + //DECLARE_RT_OBJECT(STA_QOS); + u8 WMMIEBuf[MAX_WMMELE_LENGTH]; + u8* WMMIE; + + // Part 1. Self QoS Mode. + QOS_MODE QosCapability; //QoS Capability, 2006-06-14 Isaiah + QOS_MODE CurrentQosMode; + + // For WMM Power Save Mode : + // ACs are trigger/delivery enabled or legacy power save enabled. 2006-06-13 Isaiah + AC_UAPSD b4ac_Uapsd; //VoUapsd(bit0), ViUapsd(bit1), BkUapsd(bit2), BeUapsd(bit3), + AC_UAPSD Curr4acUapsd; + u8 bInServicePeriod; + u8 MaxSPLength; + int NumBcnBeforeTrigger; + + // Part 2. EDCA Parameter (perAC) + u8 * pWMMInfoEle; + u8 WMMParamEle[WMM_PARAM_ELEMENT_SIZE]; + u8 WMMPELength; + + // + //2 ToDo: remove the Qos Info Field and replace it by the above WMM Info element. + // By Bruce, 2008-01-30. + // Part 2. EDCA Parameter (perAC) + QOS_INFO_FIELD QosInfoField_STA; // Maintained by STA + QOS_INFO_FIELD QosInfoField_AP; // Retrieved from AP + + AC_PARAM CurAcParameters[4]; + + // Part 3. ACM + ACM acm[4]; + ACM_METHOD AcmMethod; + + // Part 4. Per TID (Part 5: TCLASS will be described by TStream) + QOS_TSTREAM TStream[16]; + WMM_TSPEC TSpec; + + u32 QBssWirelessMode; + + // No Ack Setting + u8 bNoAck; + + // Enable/Disable Rx immediate BA capability. + u8 bEnableRxImmBA; + +}STA_QOS, *PSTA_QOS; + +// +// BSS QOS data. +// Ref: BssDscr in 8185 code. [def. in BssDscr.h] +// +typedef struct _BSS_QOS{ + QOS_MODE bdQoSMode; + + u8 bdWMMIEBuf[MAX_WMMELE_LENGTH]; + u8* bdWMMIE; + + QOS_ELE_SUBTYPE EleSubType; + + u8 * pWMMInfoEle; + u8 * pWMMParamEle; + + QOS_INFO_FIELD QosInfoField; + AC_PARAM AcParameter[4]; +}BSS_QOS, *PBSS_QOS; + + +// +// Ref: sQoSCtlLng and QoSCtl definition in 8185 QoS code. +//#define QoSCtl (( (Adapter->bRegQoS) && (Adapter->dot11QoS.QoSMode &(QOS_EDCA|QOS_HCCA)) ) ?sQoSCtlLng:0) +// +#define sQoSCtlLng 2 +#define QOS_CTRL_LEN(_QosMode) ((_QosMode > QOS_DISABLE)? sQoSCtlLng : 0) + + +//Added by joseph +//UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP +//#define UP2AC(up) ((up<3)?((up==0)?1:0):(up>>1)) +#define IsACValid(ac) ((ac<=7 )?true:false ) + +#endif // #ifndef __INC_QOS_TYPE_H diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TS.h b/drivers/staging/rtl8192u/ieee80211/rtl819x_TS.h new file mode 100644 index 0000000000000000000000000000000000000000..baaac2149de1fb129660c42d8639c5535ba7e9b0 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TS.h @@ -0,0 +1,56 @@ +#ifndef _TSTYPE_H_ +#define _TSTYPE_H_ +#include "rtl819x_Qos.h" +#define TS_SETUP_TIMEOUT 60 // In millisecond +#define TS_INACT_TIMEOUT 60 +#define TS_ADDBA_DELAY 60 + +#define TOTAL_TS_NUM 16 +#define TCLAS_NUM 4 + +// This define the Tx/Rx directions +typedef enum _TR_SELECT { + TX_DIR = 0, + RX_DIR = 1, +} TR_SELECT, *PTR_SELECT; + +typedef struct _TS_COMMON_INFO{ + struct list_head List; + struct timer_list SetupTimer; + struct timer_list InactTimer; + u8 Addr[6]; + TSPEC_BODY TSpec; + QOS_TCLAS TClass[TCLAS_NUM]; + u8 TClasProc; + u8 TClasNum; +} TS_COMMON_INFO, *PTS_COMMON_INFO; + +typedef struct _TX_TS_RECORD{ + TS_COMMON_INFO TsCommonInfo; + u16 TxCurSeq; + BA_RECORD TxPendingBARecord; // For BA Originator + BA_RECORD TxAdmittedBARecord; // For BA Originator +// QOS_DL_RECORD DLRecord; + u8 bAddBaReqInProgress; + u8 bAddBaReqDelayed; + u8 bUsingBa; + struct timer_list TsAddBaTimer; + u8 num; +} TX_TS_RECORD, *PTX_TS_RECORD; + +typedef struct _RX_TS_RECORD { + TS_COMMON_INFO TsCommonInfo; + u16 RxIndicateSeq; + u16 RxTimeoutIndicateSeq; + struct list_head RxPendingPktList; + struct timer_list RxPktPendingTimer; + BA_RECORD RxAdmittedBARecord; // For BA Recepient + u16 RxLastSeqNum; + u8 RxLastFragNum; + u8 num; +// QOS_DL_RECORD DLRecord; +} RX_TS_RECORD, *PRX_TS_RECORD; + + +#endif + diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c new file mode 100644 index 0000000000000000000000000000000000000000..5373d565af244c8f6410427721176b37f16d44f3 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c @@ -0,0 +1,628 @@ +#include "ieee80211.h" +#include +#include "rtl819x_TS.h" + +void TsSetupTimeOut(unsigned long data) +{ + // Not implement yet + // This is used for WMMSA and ACM , that would send ADDTSReq frame. +} + +void TsInactTimeout(unsigned long data) +{ + // Not implement yet + // This is used for WMMSA and ACM. + // This function would be call when TS is no Tx/Rx for some period of time. +} + +/******************************************************************************************************************** + *function: I still not understand this function, so wait for further implementation + * input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer + * return: NULL + * notice: +********************************************************************************************************************/ +void RxPktPendingTimeout(unsigned long data) +{ + PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data; + struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]); + + PRX_REORDER_ENTRY pReorderEntry = NULL; + + //u32 flags = 0; + unsigned long flags = 0; + struct ieee80211_rxb *stats_IndicateArray[REORDER_WIN_SIZE]; + u8 index = 0; + bool bPktInBuf = false; + + + spin_lock_irqsave(&(ieee->reorder_spinlock), flags); + //PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK); + IEEE80211_DEBUG(IEEE80211_DL_REORDER,"==================>%s()\n",__FUNCTION__); + if(pRxTs->RxTimeoutIndicateSeq != 0xffff) + { + // Indicate the pending packets sequentially according to SeqNum until meet the gap. + while(!list_empty(&pRxTs->RxPendingPktList)) + { + pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTs->RxPendingPktList.prev,RX_REORDER_ENTRY,List); + if(index == 0) + pRxTs->RxIndicateSeq = pReorderEntry->SeqNum; + + if( SN_LESS(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) || + SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) ) + { + list_del_init(&pReorderEntry->List); + + if(SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq)) + pRxTs->RxIndicateSeq = (pRxTs->RxIndicateSeq + 1) % 4096; + + IEEE80211_DEBUG(IEEE80211_DL_REORDER,"RxPktPendingTimeout(): IndicateSeq: %d\n", pReorderEntry->SeqNum); + stats_IndicateArray[index] = pReorderEntry->prxb; + index++; + + list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List); + } + else + { + bPktInBuf = true; + break; + } + } + } + + if(index>0) + { + // Set RxTimeoutIndicateSeq to 0xffff to indicate no pending packets in buffer now. + pRxTs->RxTimeoutIndicateSeq = 0xffff; + + // Indicate packets + if(index > REORDER_WIN_SIZE){ + IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n"); + spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); + return; + } + ieee80211_indicate_packets(ieee, stats_IndicateArray, index); + } + + if(bPktInBuf && (pRxTs->RxTimeoutIndicateSeq==0xffff)) + { + pRxTs->RxTimeoutIndicateSeq = pRxTs->RxIndicateSeq; + if(timer_pending(&pRxTs->RxPktPendingTimer)) + del_timer_sync(&pRxTs->RxPktPendingTimer); + pRxTs->RxPktPendingTimer.expires = jiffies + ieee->pHTInfo->RxReorderPendingTime; + add_timer(&pRxTs->RxPktPendingTimer); + } + spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); + //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK); +} + +/******************************************************************************************************************** + *function: Add BA timer function + * input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer + * return: NULL + * notice: +********************************************************************************************************************/ +void TsAddBaProcess(unsigned long data) +{ + PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data; + u8 num = pTxTs->num; + struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[num]); + + TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false); + IEEE80211_DEBUG(IEEE80211_DL_BA, "TsAddBaProcess(): ADDBA Req is started!! \n"); +} + + +void ResetTsCommonInfo(PTS_COMMON_INFO pTsCommonInfo) +{ + memset(pTsCommonInfo->Addr, 0, 6); + memset(&pTsCommonInfo->TSpec, 0, sizeof(TSPEC_BODY)); + memset(&pTsCommonInfo->TClass, 0, sizeof(QOS_TCLAS)*TCLAS_NUM); + pTsCommonInfo->TClasProc = 0; + pTsCommonInfo->TClasNum = 0; +} + +void ResetTxTsEntry(PTX_TS_RECORD pTS) +{ + ResetTsCommonInfo(&pTS->TsCommonInfo); + pTS->TxCurSeq = 0; + pTS->bAddBaReqInProgress = false; + pTS->bAddBaReqDelayed = false; + pTS->bUsingBa = false; + ResetBaEntry(&pTS->TxAdmittedBARecord); //For BA Originator + ResetBaEntry(&pTS->TxPendingBARecord); +} + +void ResetRxTsEntry(PRX_TS_RECORD pTS) +{ + ResetTsCommonInfo(&pTS->TsCommonInfo); + pTS->RxIndicateSeq = 0xffff; // This indicate the RxIndicateSeq is not used now!! + pTS->RxTimeoutIndicateSeq = 0xffff; // This indicate the RxTimeoutIndicateSeq is not used now!! + ResetBaEntry(&pTS->RxAdmittedBARecord); // For BA Recepient +} + +void TSInitialize(struct ieee80211_device *ieee) +{ + PTX_TS_RECORD pTxTS = ieee->TxTsRecord; + PRX_TS_RECORD pRxTS = ieee->RxTsRecord; + PRX_REORDER_ENTRY pRxReorderEntry = ieee->RxReorderEntry; + u8 count = 0; + IEEE80211_DEBUG(IEEE80211_DL_TS, "==========>%s()\n", __FUNCTION__); + // Initialize Tx TS related info. + INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List); + INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List); + INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List); + + for(count = 0; count < TOTAL_TS_NUM; count++) + { + // + pTxTS->num = count; + // The timers for the operation of Traffic Stream and Block Ack. + // DLS related timer will be add here in the future!! + init_timer(&pTxTS->TsCommonInfo.SetupTimer); + pTxTS->TsCommonInfo.SetupTimer.data = (unsigned long)pTxTS; + pTxTS->TsCommonInfo.SetupTimer.function = TsSetupTimeOut; + + init_timer(&pTxTS->TsCommonInfo.InactTimer); + pTxTS->TsCommonInfo.InactTimer.data = (unsigned long)pTxTS; + pTxTS->TsCommonInfo.InactTimer.function = TsInactTimeout; + + init_timer(&pTxTS->TsAddBaTimer); + pTxTS->TsAddBaTimer.data = (unsigned long)pTxTS; + pTxTS->TsAddBaTimer.function = TsAddBaProcess; + + init_timer(&pTxTS->TxPendingBARecord.Timer); + pTxTS->TxPendingBARecord.Timer.data = (unsigned long)pTxTS; + pTxTS->TxPendingBARecord.Timer.function = BaSetupTimeOut; + + init_timer(&pTxTS->TxAdmittedBARecord.Timer); + pTxTS->TxAdmittedBARecord.Timer.data = (unsigned long)pTxTS; + pTxTS->TxAdmittedBARecord.Timer.function = TxBaInactTimeout; + + ResetTxTsEntry(pTxTS); + list_add_tail(&pTxTS->TsCommonInfo.List, &ieee->Tx_TS_Unused_List); + pTxTS++; + } + + // Initialize Rx TS related info. + INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List); + INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List); + INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List); + for(count = 0; count < TOTAL_TS_NUM; count++) + { + pRxTS->num = count; + INIT_LIST_HEAD(&pRxTS->RxPendingPktList); + + init_timer(&pRxTS->TsCommonInfo.SetupTimer); + pRxTS->TsCommonInfo.SetupTimer.data = (unsigned long)pRxTS; + pRxTS->TsCommonInfo.SetupTimer.function = TsSetupTimeOut; + + init_timer(&pRxTS->TsCommonInfo.InactTimer); + pRxTS->TsCommonInfo.InactTimer.data = (unsigned long)pRxTS; + pRxTS->TsCommonInfo.InactTimer.function = TsInactTimeout; + + init_timer(&pRxTS->RxAdmittedBARecord.Timer); + pRxTS->RxAdmittedBARecord.Timer.data = (unsigned long)pRxTS; + pRxTS->RxAdmittedBARecord.Timer.function = RxBaInactTimeout; + + init_timer(&pRxTS->RxPktPendingTimer); + pRxTS->RxPktPendingTimer.data = (unsigned long)pRxTS; + pRxTS->RxPktPendingTimer.function = RxPktPendingTimeout; + + ResetRxTsEntry(pRxTS); + list_add_tail(&pRxTS->TsCommonInfo.List, &ieee->Rx_TS_Unused_List); + pRxTS++; + } + // Initialize unused Rx Reorder List. + INIT_LIST_HEAD(&ieee->RxReorder_Unused_List); +//#ifdef TO_DO_LIST + for(count = 0; count < REORDER_ENTRY_NUM; count++) + { + list_add_tail( &pRxReorderEntry->List,&ieee->RxReorder_Unused_List); + if(count == (REORDER_ENTRY_NUM-1)) + break; + pRxReorderEntry = &ieee->RxReorderEntry[count+1]; + } +//#endif + +} + +void AdmitTS(struct ieee80211_device *ieee, PTS_COMMON_INFO pTsCommonInfo, u32 InactTime) +{ + del_timer_sync(&pTsCommonInfo->SetupTimer); + del_timer_sync(&pTsCommonInfo->InactTimer); + + if(InactTime!=0) + mod_timer(&pTsCommonInfo->InactTimer, jiffies + MSECS(InactTime)); +} + + +PTS_COMMON_INFO SearchAdmitTRStream(struct ieee80211_device *ieee, u8* Addr, u8 TID, TR_SELECT TxRxSelect) +{ + //DIRECTION_VALUE dir; + u8 dir; + bool search_dir[4] = {0, 0, 0, 0}; + struct list_head* psearch_list; //FIXME + PTS_COMMON_INFO pRet = NULL; + if(ieee->iw_mode == IW_MODE_MASTER) //ap mode + { + if(TxRxSelect == TX_DIR) + { + search_dir[DIR_DOWN] = true; + search_dir[DIR_BI_DIR]= true; + } + else + { + search_dir[DIR_UP] = true; + search_dir[DIR_BI_DIR]= true; + } + } + else if(ieee->iw_mode == IW_MODE_ADHOC) + { + if(TxRxSelect == TX_DIR) + search_dir[DIR_UP] = true; + else + search_dir[DIR_DOWN] = true; + } + else + { + if(TxRxSelect == TX_DIR) + { + search_dir[DIR_UP] = true; + search_dir[DIR_BI_DIR]= true; + search_dir[DIR_DIRECT]= true; + } + else + { + search_dir[DIR_DOWN] = true; + search_dir[DIR_BI_DIR]= true; + search_dir[DIR_DIRECT]= true; + } + } + + if(TxRxSelect == TX_DIR) + psearch_list = &ieee->Tx_TS_Admit_List; + else + psearch_list = &ieee->Rx_TS_Admit_List; + + //for(dir = DIR_UP; dir <= DIR_BI_DIR; dir++) + for(dir = 0; dir <= DIR_BI_DIR; dir++) + { + if(search_dir[dir] ==false ) + continue; + list_for_each_entry(pRet, psearch_list, List){ + // IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:"MAC_FMT", TID:%d, dir:%d\n", MAC_ARG(pRet->Addr), pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection); + if (memcmp(pRet->Addr, Addr, 6) == 0) + if (pRet->TSpec.f.TSInfo.field.ucTSID == TID) + if(pRet->TSpec.f.TSInfo.field.ucDirection == dir) + { + // printk("Bingo! got it\n"); + break; + } + + } + if(&pRet->List != psearch_list) + break; + } + + if(&pRet->List != psearch_list){ + return pRet ; + } + else + return NULL; +} + +void MakeTSEntry( + PTS_COMMON_INFO pTsCommonInfo, + u8* Addr, + PTSPEC_BODY pTSPEC, + PQOS_TCLAS pTCLAS, + u8 TCLAS_Num, + u8 TCLAS_Proc + ) +{ + u8 count; + + if(pTsCommonInfo == NULL) + return; + + memcpy(pTsCommonInfo->Addr, Addr, 6); + + if(pTSPEC != NULL) + memcpy((u8*)(&(pTsCommonInfo->TSpec)), (u8*)pTSPEC, sizeof(TSPEC_BODY)); + + for(count = 0; count < TCLAS_Num; count++) + memcpy((u8*)(&(pTsCommonInfo->TClass[count])), (u8*)pTCLAS, sizeof(QOS_TCLAS)); + + pTsCommonInfo->TClasProc = TCLAS_Proc; + pTsCommonInfo->TClasNum = TCLAS_Num; +} + + +bool GetTs( + struct ieee80211_device* ieee, + PTS_COMMON_INFO *ppTS, + u8* Addr, + u8 TID, + TR_SELECT TxRxSelect, //Rx:1, Tx:0 + bool bAddNewTs + ) +{ + u8 UP = 0; + // + // We do not build any TS for Broadcast or Multicast stream. + // So reject these kinds of search here. + // + if(is_broadcast_ether_addr(Addr) || is_multicast_ether_addr(Addr)) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "get TS for Broadcast or Multicast\n"); + return false; + } + if (ieee->current_network.qos_data.supported == 0) + UP = 0; + else + { + // In WMM case: we use 4 TID only + if (!IsACValid(TID)) + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, " in %s(), TID(%d) is not valid\n", __FUNCTION__, TID); + return false; + } + + switch(TID) + { + case 0: + case 3: + UP = 0; + break; + + case 1: + case 2: + UP = 2; + break; + + case 4: + case 5: + UP = 5; + break; + + case 6: + case 7: + UP = 7; + break; + } + } + + *ppTS = SearchAdmitTRStream( + ieee, + Addr, + UP, + TxRxSelect); + if(*ppTS != NULL) + { + return true; + } + else + { + if(bAddNewTs == false) + { + IEEE80211_DEBUG(IEEE80211_DL_TS, "add new TS failed(tid:%d)\n", UP); + return false; + } + else + { + // + // Create a new Traffic stream for current Tx/Rx + // This is for EDCA and WMM to add a new TS. + // For HCCA or WMMSA, TS cannot be addmit without negotiation. + // + TSPEC_BODY TSpec; + PQOS_TSINFO pTSInfo = &TSpec.f.TSInfo; + struct list_head* pUnusedList = + (TxRxSelect == TX_DIR)? + (&ieee->Tx_TS_Unused_List): + (&ieee->Rx_TS_Unused_List); + + struct list_head* pAddmitList = + (TxRxSelect == TX_DIR)? + (&ieee->Tx_TS_Admit_List): + (&ieee->Rx_TS_Admit_List); + + DIRECTION_VALUE Dir = (ieee->iw_mode == IW_MODE_MASTER)? + ((TxRxSelect==TX_DIR)?DIR_DOWN:DIR_UP): + ((TxRxSelect==TX_DIR)?DIR_UP:DIR_DOWN); + IEEE80211_DEBUG(IEEE80211_DL_TS, "to add Ts\n"); + if(!list_empty(pUnusedList)) + { + (*ppTS) = list_entry(pUnusedList->next, TS_COMMON_INFO, List); + list_del_init(&(*ppTS)->List); + if(TxRxSelect==TX_DIR) + { + PTX_TS_RECORD tmp = container_of(*ppTS, TX_TS_RECORD, TsCommonInfo); + ResetTxTsEntry(tmp); + } + else{ + PRX_TS_RECORD tmp = container_of(*ppTS, RX_TS_RECORD, TsCommonInfo); + ResetRxTsEntry(tmp); + } + + IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:"MAC_FMT"\n", UP, Dir, MAC_ARG(Addr)); + // Prepare TS Info releated field + pTSInfo->field.ucTrafficType = 0; // Traffic type: WMM is reserved in this field + pTSInfo->field.ucTSID = UP; // TSID + pTSInfo->field.ucDirection = Dir; // Direction: if there is DirectLink, this need additional consideration. + pTSInfo->field.ucAccessPolicy = 1; // Access policy + pTSInfo->field.ucAggregation = 0; // Aggregation + pTSInfo->field.ucPSB = 0; // Aggregation + pTSInfo->field.ucUP = UP; // User priority + pTSInfo->field.ucTSInfoAckPolicy = 0; // Ack policy + pTSInfo->field.ucSchedule = 0; // Schedule + + MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0); + AdmitTS(ieee, *ppTS, 0); + list_add_tail(&((*ppTS)->List), pAddmitList); + // if there is DirectLink, we need to do additional operation here!! + + return true; + } + else + { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "in function %s() There is not enough TS record to be used!!", __FUNCTION__); + return false; + } + } + } +} + +void RemoveTsEntry( + struct ieee80211_device* ieee, + PTS_COMMON_INFO pTs, + TR_SELECT TxRxSelect + ) +{ + //u32 flags = 0; + unsigned long flags = 0; + del_timer_sync(&pTs->SetupTimer); + del_timer_sync(&pTs->InactTimer); + TsInitDelBA(ieee, pTs, TxRxSelect); + + if(TxRxSelect == RX_DIR) + { +//#ifdef TO_DO_LIST + PRX_REORDER_ENTRY pRxReorderEntry; + PRX_TS_RECORD pRxTS = (PRX_TS_RECORD)pTs; + if(timer_pending(&pRxTS->RxPktPendingTimer)) + del_timer_sync(&pRxTS->RxPktPendingTimer); + + while(!list_empty(&pRxTS->RxPendingPktList)) + { + // PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK); + spin_lock_irqsave(&(ieee->reorder_spinlock), flags); + //pRxReorderEntry = list_entry(&pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List); + pRxReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List); + list_del_init(&pRxReorderEntry->List); + { + int i = 0; + struct ieee80211_rxb * prxb = pRxReorderEntry->prxb; + if (unlikely(!prxb)) + { + spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); + return; + } + for(i =0; i < prxb->nr_subframes; i++) { + dev_kfree_skb(prxb->subframes[i]); + } + kfree(prxb); + prxb = NULL; + } + list_add_tail(&pRxReorderEntry->List,&ieee->RxReorder_Unused_List); + //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK); + spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); + } + +//#endif + } + else + { + PTX_TS_RECORD pTxTS = (PTX_TS_RECORD)pTs; + del_timer_sync(&pTxTS->TsAddBaTimer); + } +} + +void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr) +{ + PTS_COMMON_INFO pTS, pTmpTS; + printk("===========>RemovePeerTS,"MAC_FMT"\n", MAC_ARG(Addr)); + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) + { + if (memcmp(pTS->Addr, Addr, 6) == 0) + { + RemoveTsEntry(ieee, pTS, TX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); + } + } + + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) + { + if (memcmp(pTS->Addr, Addr, 6) == 0) + { + printk("====>remove Tx_TS_admin_list\n"); + RemoveTsEntry(ieee, pTS, TX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); + } + } + + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List) + { + if (memcmp(pTS->Addr, Addr, 6) == 0) + { + RemoveTsEntry(ieee, pTS, RX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); + } + } + + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List) + { + if (memcmp(pTS->Addr, Addr, 6) == 0) + { + RemoveTsEntry(ieee, pTS, RX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); + } + } +} + +void RemoveAllTS(struct ieee80211_device* ieee) +{ + PTS_COMMON_INFO pTS, pTmpTS; + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) + { + RemoveTsEntry(ieee, pTS, TX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); + } + + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) + { + RemoveTsEntry(ieee, pTS, TX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); + } + + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List) + { + RemoveTsEntry(ieee, pTS, RX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); + } + + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List) + { + RemoveTsEntry(ieee, pTS, RX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); + } +} + +void TsStartAddBaProcess(struct ieee80211_device* ieee, PTX_TS_RECORD pTxTS) +{ + if(pTxTS->bAddBaReqInProgress == false) + { + pTxTS->bAddBaReqInProgress = true; + if(pTxTS->bAddBaReqDelayed) + { + IEEE80211_DEBUG(IEEE80211_DL_BA, "TsStartAddBaProcess(): Delayed Start ADDBA after 60 sec!!\n"); + mod_timer(&pTxTS->TsAddBaTimer, jiffies + MSECS(TS_ADDBA_DELAY)); + } + else + { + IEEE80211_DEBUG(IEEE80211_DL_BA,"TsStartAddBaProcess(): Immediately Start ADDBA now!!\n"); + mod_timer(&pTxTS->TsAddBaTimer, jiffies+10); //set 10 ticks + } + } + else + IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s()==>BA timer is already added\n", __FUNCTION__); +} +EXPORT_SYMBOL(RemovePeerTS); diff --git a/drivers/staging/rtl8192u/ieee80211/rtl_crypto.h b/drivers/staging/rtl8192u/ieee80211/rtl_crypto.h new file mode 100644 index 0000000000000000000000000000000000000000..ccf6ae76357285686d62027574b867b1b324113e --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/rtl_crypto.h @@ -0,0 +1,399 @@ +/* + * Scatterlist Cryptographic API. + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * + * Portions derived from Cryptoapi, by Alexander Kjeldaas + * and Nettle, by Niels Mé°ˆler. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the 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 _LINUX_CRYPTO_H +#define _LINUX_CRYPTO_H + +#include +#include +#include +#include +#include +#include +#include + +#define crypto_register_alg crypto_register_alg_rsl +#define crypto_unregister_alg crypto_unregister_alg_rsl +#define crypto_alloc_tfm crypto_alloc_tfm_rsl +#define crypto_free_tfm crypto_free_tfm_rsl +#define crypto_alg_available crypto_alg_available_rsl + +/* + * Algorithm masks and types. + */ +#define CRYPTO_ALG_TYPE_MASK 0x000000ff +#define CRYPTO_ALG_TYPE_CIPHER 0x00000001 +#define CRYPTO_ALG_TYPE_DIGEST 0x00000002 +#define CRYPTO_ALG_TYPE_COMPRESS 0x00000004 + +/* + * Transform masks and values (for crt_flags). + */ +#define CRYPTO_TFM_MODE_MASK 0x000000ff +#define CRYPTO_TFM_REQ_MASK 0x000fff00 +#define CRYPTO_TFM_RES_MASK 0xfff00000 + +#define CRYPTO_TFM_MODE_ECB 0x00000001 +#define CRYPTO_TFM_MODE_CBC 0x00000002 +#define CRYPTO_TFM_MODE_CFB 0x00000004 +#define CRYPTO_TFM_MODE_CTR 0x00000008 + +#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100 +#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000 +#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000 +#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000 +#define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000 +#define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000 + +/* + * Miscellaneous stuff. + */ +#define CRYPTO_UNSPEC 0 +#define CRYPTO_MAX_ALG_NAME 64 + +struct scatterlist; + +/* + * Algorithms: modular crypto algorithm implementations, managed + * via crypto_register_alg() and crypto_unregister_alg(). + */ +struct cipher_alg { + unsigned int cia_min_keysize; + unsigned int cia_max_keysize; + int (*cia_setkey)(void *ctx, const u8 *key, + unsigned int keylen, u32 *flags); + void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src); + void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src); +}; + +struct digest_alg { + unsigned int dia_digestsize; + void (*dia_init)(void *ctx); + void (*dia_update)(void *ctx, const u8 *data, unsigned int len); + void (*dia_final)(void *ctx, u8 *out); + int (*dia_setkey)(void *ctx, const u8 *key, + unsigned int keylen, u32 *flags); +}; + +struct compress_alg { + int (*coa_init)(void *ctx); + void (*coa_exit)(void *ctx); + int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen); + int (*coa_decompress)(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen); +}; + +#define cra_cipher cra_u.cipher +#define cra_digest cra_u.digest +#define cra_compress cra_u.compress + +struct crypto_alg { + struct list_head cra_list; + u32 cra_flags; + unsigned int cra_blocksize; + unsigned int cra_ctxsize; + const char cra_name[CRYPTO_MAX_ALG_NAME]; + + union { + struct cipher_alg cipher; + struct digest_alg digest; + struct compress_alg compress; + } cra_u; + + struct module *cra_module; +}; + +/* + * Algorithm registration interface. + */ +int crypto_register_alg(struct crypto_alg *alg); +int crypto_unregister_alg(struct crypto_alg *alg); + +/* + * Algorithm query interface. + */ +int crypto_alg_available(const char *name, u32 flags); + +/* + * Transforms: user-instantiated objects which encapsulate algorithms + * and core processing logic. Managed via crypto_alloc_tfm() and + * crypto_free_tfm(), as well as the various helpers below. + */ +struct crypto_tfm; + +struct cipher_tfm { + void *cit_iv; + unsigned int cit_ivsize; + u32 cit_mode; + int (*cit_setkey)(struct crypto_tfm *tfm, + const u8 *key, unsigned int keylen); + int (*cit_encrypt)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes); + int (*cit_encrypt_iv)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv); + int (*cit_decrypt)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes); + int (*cit_decrypt_iv)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv); + void (*cit_xor_block)(u8 *dst, const u8 *src); +}; + +struct digest_tfm { + void (*dit_init)(struct crypto_tfm *tfm); + void (*dit_update)(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg); + void (*dit_final)(struct crypto_tfm *tfm, u8 *out); + void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg, + unsigned int nsg, u8 *out); + int (*dit_setkey)(struct crypto_tfm *tfm, + const u8 *key, unsigned int keylen); +#ifdef CONFIG_CRYPTO_HMAC + void *dit_hmac_block; +#endif +}; + +struct compress_tfm { + int (*cot_compress)(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen); + int (*cot_decompress)(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen); +}; + +#define crt_cipher crt_u.cipher +#define crt_digest crt_u.digest +#define crt_compress crt_u.compress + +struct crypto_tfm { + + u32 crt_flags; + + union { + struct cipher_tfm cipher; + struct digest_tfm digest; + struct compress_tfm compress; + } crt_u; + + struct crypto_alg *__crt_alg; +}; + +/* + * Transform user interface. + */ + +/* + * crypto_alloc_tfm() will first attempt to locate an already loaded algorithm. + * If that fails and the kernel supports dynamically loadable modules, it + * will then attempt to load a module of the same name or alias. A refcount + * is grabbed on the algorithm which is then associated with the new transform. + * + * crypto_free_tfm() frees up the transform and any associated resources, + * then drops the refcount on the associated algorithm. + */ +struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags); +void crypto_free_tfm(struct crypto_tfm *tfm); + +/* + * Transform helpers which query the underlying algorithm. + */ +static inline const char *crypto_tfm_alg_name(struct crypto_tfm *tfm) +{ + return tfm->__crt_alg->cra_name; +} + +static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm) +{ + struct crypto_alg *alg = tfm->__crt_alg; + + if (alg->cra_module) + return alg->cra_module->name; + else + return NULL; +} + +static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm) +{ + return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK; +} + +static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->__crt_alg->cra_cipher.cia_min_keysize; +} + +static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->__crt_alg->cra_cipher.cia_max_keysize; +} + +static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_ivsize; +} + +static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm) +{ + return tfm->__crt_alg->cra_blocksize; +} + +static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + return tfm->__crt_alg->cra_digest.dia_digestsize; +} + +/* + * API wrappers. + */ +static inline void crypto_digest_init(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_init(tfm); +} + +static inline void crypto_digest_update(struct crypto_tfm *tfm, + struct scatterlist *sg, + unsigned int nsg) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_update(tfm, sg, nsg); +} + +static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_final(tfm, out); +} + +static inline void crypto_digest_digest(struct crypto_tfm *tfm, + struct scatterlist *sg, + unsigned int nsg, u8 *out) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_digest(tfm, sg, nsg, out); +} + +static inline int crypto_digest_setkey(struct crypto_tfm *tfm, + const u8 *key, unsigned int keylen) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + if (tfm->crt_digest.dit_setkey == NULL) + return -ENOSYS; + return tfm->crt_digest.dit_setkey(tfm, key, keylen); +} + +static inline int crypto_cipher_setkey(struct crypto_tfm *tfm, + const u8 *key, unsigned int keylen) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_setkey(tfm, key, keylen); +} + +static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes); +} + +static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); + return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv); +} + +static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes); +} + +static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); + return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv); +} + +static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm, + const u8 *src, unsigned int len) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + memcpy(tfm->crt_cipher.cit_iv, src, len); +} + +static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm, + u8 *dst, unsigned int len) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + memcpy(dst, tfm->crt_cipher.cit_iv, len); +} + +static inline int crypto_comp_compress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); + return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen); +} + +static inline int crypto_comp_decompress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); + return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen); +} + +/* + * HMAC support. + */ +#ifdef CONFIG_CRYPTO_HMAC +void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen); +void crypto_hmac_update(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg); +void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key, + unsigned int *keylen, u8 *out); +void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, + struct scatterlist *sg, unsigned int nsg, u8 *out); +#endif /* CONFIG_CRYPTO_HMAC */ + +#endif /* _LINUX_CRYPTO_H */ + diff --git a/drivers/staging/rtl8192u/ieee80211/scatterwalk.c b/drivers/staging/rtl8192u/ieee80211/scatterwalk.c new file mode 100644 index 0000000000000000000000000000000000000000..49f401fbce888f0e099042f4d997ff0972b31333 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/scatterwalk.c @@ -0,0 +1,126 @@ +/* + * Cryptographic API. + * + * Cipher operations. + * + * Copyright (c) 2002 James Morris + * 2002 Adam J. Richter + * 2004 Jean-Luc Cooke + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the 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 "kmap_types.h" + +#include +#include +#include +#include +#include +#include "internal.h" +#include "scatterwalk.h" + +enum km_type crypto_km_types[] = { + KM_USER0, + KM_USER1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, +}; + +void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch) +{ + if (nbytes <= walk->len_this_page && + (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <= + PAGE_CACHE_SIZE) + return walk->data; + else + return scratch; +} + +static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out) +{ + if (out) + memcpy(sgdata, buf, nbytes); + else + memcpy(buf, sgdata, nbytes); +} + +void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg) +{ + unsigned int rest_of_page; + + walk->sg = sg; + + walk->page = sg->page; + walk->len_this_segment = sg->length; + + rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1)); + walk->len_this_page = min(sg->length, rest_of_page); + walk->offset = sg->offset; +} + +void scatterwalk_map(struct scatter_walk *walk, int out) +{ + walk->data = crypto_kmap(walk->page, out) + walk->offset; +} + +static void scatterwalk_pagedone(struct scatter_walk *walk, int out, + unsigned int more) +{ + /* walk->data may be pointing the first byte of the next page; + however, we know we transfered at least one byte. So, + walk->data - 1 will be a virtual address in the mapped page. */ + + if (out) + flush_dcache_page(walk->page); + + if (more) { + walk->len_this_segment -= walk->len_this_page; + + if (walk->len_this_segment) { + walk->page++; + walk->len_this_page = min(walk->len_this_segment, + (unsigned)PAGE_CACHE_SIZE); + walk->offset = 0; + } + else + scatterwalk_start(walk, sg_next(walk->sg)); + } +} + +void scatterwalk_done(struct scatter_walk *walk, int out, int more) +{ + crypto_kunmap(walk->data, out); + if (walk->len_this_page == 0 || !more) + scatterwalk_pagedone(walk, out, more); +} + +/* + * Do not call this unless the total length of all of the fragments + * has been verified as multiple of the block size. + */ +int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, + size_t nbytes, int out) +{ + if (buf != walk->data) { + while (nbytes > walk->len_this_page) { + memcpy_dir(buf, walk->data, walk->len_this_page, out); + buf += walk->len_this_page; + nbytes -= walk->len_this_page; + + crypto_kunmap(walk->data, out); + scatterwalk_pagedone(walk, out, 1); + scatterwalk_map(walk, out); + } + + memcpy_dir(buf, walk->data, nbytes, out); + } + + walk->offset += nbytes; + walk->len_this_page -= nbytes; + walk->len_this_segment -= nbytes; + return 0; +} diff --git a/drivers/staging/rtl8192u/ieee80211/scatterwalk.h b/drivers/staging/rtl8192u/ieee80211/scatterwalk.h new file mode 100644 index 0000000000000000000000000000000000000000..b16446519017f3509ad17209fa6ccbfffa2d1584 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211/scatterwalk.h @@ -0,0 +1,51 @@ +/* + * Cryptographic API. + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 Adam J. Richter + * Copyright (c) 2004 Jean-Luc Cooke + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the 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 _CRYPTO_SCATTERWALK_H +#define _CRYPTO_SCATTERWALK_H +#include +#include + +struct scatter_walk { + struct scatterlist *sg; + struct page *page; + void *data; + unsigned int len_this_page; + unsigned int len_this_segment; + unsigned int offset; +}; + +/* Define sg_next is an inline routine now in case we want to change + scatterlist to a linked list later. */ +static inline struct scatterlist *sg_next(struct scatterlist *sg) +{ + return sg + 1; +} + +static inline int scatterwalk_samebuf(struct scatter_walk *walk_in, + struct scatter_walk *walk_out, + void *src_p, void *dst_p) +{ + return walk_in->page == walk_out->page && + walk_in->offset == walk_out->offset && + walk_in->data == src_p && walk_out->data == dst_p; +} + +void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch); +void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg); +int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out); +void scatterwalk_map(struct scatter_walk *walk, int out); +void scatterwalk_done(struct scatter_walk *walk, int out, int more); + +#endif /* _CRYPTO_SCATTERWALK_H */ diff --git a/drivers/staging/rtl8192u/ieee80211_crypt.h b/drivers/staging/rtl8192u/ieee80211_crypt.h new file mode 100644 index 0000000000000000000000000000000000000000..b58a3bcc0dc0972c882f5992ad02264510769bf5 --- /dev/null +++ b/drivers/staging/rtl8192u/ieee80211_crypt.h @@ -0,0 +1,86 @@ +/* + * Original code based on Host AP (software wireless LAN access point) driver + * for Intersil Prism2/2.5/3. + * + * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen + * + * Copyright (c) 2002-2003, Jouni Malinen + * + * Adaption to a generic IEEE 802.11 stack by James Ketrenos + * + * + * Copyright (c) 2004, Intel Corporation + * + * 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. See README and COPYING for + * more details. + */ + +/* + * This file defines the interface to the ieee80211 crypto module. + */ +#ifndef IEEE80211_CRYPT_H +#define IEEE80211_CRYPT_H + +#include + +struct ieee80211_crypto_ops { + const char *name; + + /* init new crypto context (e.g., allocate private data space, + * select IV, etc.); returns NULL on failure or pointer to allocated + * private data on success */ + void * (*init)(int keyidx); + + /* deinitialize crypto context and free allocated private data */ + void (*deinit)(void *priv); + + /* encrypt/decrypt return < 0 on error or >= 0 on success. The return + * value from decrypt_mpdu is passed as the keyidx value for + * decrypt_msdu. skb must have enough head and tail room for the + * encryption; if not, error will be returned; these functions are + * called for all MPDUs (i.e., fragments). + */ + int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv); + int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv); + + /* These functions are called for full MSDUs, i.e. full frames. + * These can be NULL if full MSDU operations are not needed. */ + int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv); + int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len, + void *priv); + + int (*set_key)(void *key, int len, u8 *seq, void *priv); + int (*get_key)(void *key, int len, u8 *seq, void *priv); + + /* procfs handler for printing out key information and possible + * statistics */ + char * (*print_stats)(char *p, void *priv); + + /* maximum number of bytes added by encryption; encrypt buf is + * allocated with extra_prefix_len bytes, copy of in_buf, and + * extra_postfix_len; encrypt need not use all this space, but + * the result must start at the beginning of the buffer and correct + * length must be returned */ + int extra_prefix_len, extra_postfix_len; + + struct module *owner; +}; + +struct ieee80211_crypt_data { + struct list_head list; /* delayed deletion list */ + struct ieee80211_crypto_ops *ops; + void *priv; + atomic_t refcnt; +}; + +int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops); +int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops); +struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name); +void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int); +void ieee80211_crypt_deinit_handler(unsigned long); +void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, + struct ieee80211_crypt_data **crypt); + +#endif diff --git a/drivers/staging/rtl8192u/r8180_93cx6.c b/drivers/staging/rtl8192u/r8180_93cx6.c new file mode 100644 index 0000000000000000000000000000000000000000..8878cfeb0fbb137c37fab453d8f5e734f7eec6d0 --- /dev/null +++ b/drivers/staging/rtl8192u/r8180_93cx6.c @@ -0,0 +1,146 @@ +/* + This files contains card eeprom (93c46 or 93c56) programming routines, + memory is addressed by 16 bits words. + + This is part of rtl8180 OpenSource driver. + Copyright (C) Andrea Merello 2004 + Released under the terms of GPL (General Public Licence) + + Parts of this driver are based on the GPL part of the + official realtek driver. + + Parts of this driver are based on the rtl8180 driver skeleton + from Patric Schenke & Andres Salomon. + + Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver. + + We want to tanks the Authors of those projects and the Ndiswrapper + project Authors. +*/ + +#include "r8180_93cx6.h" + +void eprom_cs(struct net_device *dev, short bit) +{ + if(bit) + write_nic_byte_E(dev, EPROM_CMD, + (1<epromtype==EPROM_93c56){ + addr_str[7]=addr & 1; + addr_str[6]=addr & (1<<1); + addr_str[5]=addr & (1<<2); + addr_str[4]=addr & (1<<3); + addr_str[3]=addr & (1<<4); + addr_str[2]=addr & (1<<5); + addr_str[1]=addr & (1<<6); + addr_str[0]=addr & (1<<7); + addr_len=8; + }else{ + addr_str[5]=addr & 1; + addr_str[4]=addr & (1<<1); + addr_str[3]=addr & (1<<2); + addr_str[2]=addr & (1<<3); + addr_str[1]=addr & (1<<4); + addr_str[0]=addr & (1<<5); + addr_len=6; + } + eprom_cs(dev, 1); + eprom_ck_cycle(dev); + eprom_send_bits_string(dev, read_cmd, 3); + eprom_send_bits_string(dev, addr_str, addr_len); + + //keep chip pin D to low state while reading. + //I'm unsure if it is necessary, but anyway shouldn't hurt + eprom_w(dev, 0); + + for(i=0;i<16;i++){ + //eeprom needs a clk cycle between writing opcode&adr + //and reading data. (eeprom outs a dummy 0) + eprom_ck_cycle(dev); + ret |= (eprom_r(dev)<<(15-i)); + } + + eprom_cs(dev, 0); + eprom_ck_cycle(dev); + + //disable EPROM programming + write_nic_byte_E(dev, EPROM_CMD, + (EPROM_CMD_NORMAL< + Released under the terms of GPL (General Public Licence) + + Parts of this driver are based on the GPL part of the official realtek driver + Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon + Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver + + We want to tanks the Authors of such projects and the Ndiswrapper project Authors. +*/ + +/*This files contains card eeprom (93c46 or 93c56) programming routines*/ +/*memory is addressed by WORDS*/ + +#include "r8192U.h" +#include "r8192U_hw.h" + +#define EPROM_DELAY 10 + +#define EPROM_ANAPARAM_ADDRLWORD 0xd +#define EPROM_ANAPARAM_ADDRHWORD 0xe + +#define EPROM_RFCHIPID 0x6 +#define EPROM_TXPW_BASE 0x05 +#define EPROM_RFCHIPID_RTL8225U 5 +#define EPROM_RF_PARAM 0x4 +#define EPROM_CONFIG2 0xc + +#define EPROM_VERSION 0x1E +#define MAC_ADR 0x7 + +#define CIS 0x18 + +#define EPROM_TXPW0 0x16 +#define EPROM_TXPW2 0x1b +#define EPROM_TXPW1 0x3d + + +u32 eprom_read(struct net_device *dev,u32 addr); //reads a 16 bits word diff --git a/drivers/staging/rtl8192u/r8180_pm.c b/drivers/staging/rtl8192u/r8180_pm.c new file mode 100644 index 0000000000000000000000000000000000000000..0c58d0ed502af9591b9d6209f8d06117da959959 --- /dev/null +++ b/drivers/staging/rtl8192u/r8180_pm.c @@ -0,0 +1,48 @@ +/* + Power management interface routines. + Written by Mariusz Matuszek. + This code is currently just a placeholder for later work and + does not do anything useful. + + This is part of rtl8180 OpenSource driver. + Copyright (C) Andrea Merello 2004 + Released under the terms of GPL (General Public Licence) +*/ + +#ifdef CONFIG_RTL8180_PM + + +#include "r8180_hw.h" +#include "r8180_pm.h" + +int rtl8180_save_state (struct pci_dev *dev, u32 state) +{ + printk(KERN_NOTICE "r8180 save state call (state %u).\n", state); + return(-EAGAIN); +} + + +int rtl8180_suspend (struct pci_dev *dev, u32 state) +{ + printk(KERN_NOTICE "r8180 suspend call (state %u).\n", state); + return(-EAGAIN); +} + + +int rtl8180_resume (struct pci_dev *dev) +{ + printk(KERN_NOTICE "r8180 resume call.\n"); + return(-EAGAIN); +} + + +int rtl8180_enable_wake (struct pci_dev *dev, u32 state, int enable) +{ + printk(KERN_NOTICE "r8180 enable wake call (state %u, enable %d).\n", + state, enable); + return(-EAGAIN); +} + + + +#endif //CONFIG_RTL8180_PM diff --git a/drivers/staging/rtl8192u/r8180_pm.h b/drivers/staging/rtl8192u/r8180_pm.h new file mode 100644 index 0000000000000000000000000000000000000000..c7d18a8b79a12268a7fcb380b519031c70bae24d --- /dev/null +++ b/drivers/staging/rtl8192u/r8180_pm.h @@ -0,0 +1,28 @@ +/* + Power management interface routines. + Written by Mariusz Matuszek. + This code is currently just a placeholder for later work and + does not do anything useful. + + This is part of rtl8180 OpenSource driver. + Copyright (C) Andrea Merello 2004 + Released under the terms of GPL (General Public Licence) + +*/ + +#ifdef CONFIG_RTL8180_PM + +#ifndef R8180_PM_H +#define R8180_PM_H + +#include +#include + +int rtl8180_save_state (struct pci_dev *dev, u32 state); +int rtl8180_suspend (struct pci_dev *dev, u32 state); +int rtl8180_resume (struct pci_dev *dev); +int rtl8180_enable_wake (struct pci_dev *dev, u32 state, int enable); + +#endif //R8180_PM_H + +#endif // CONFIG_RTL8180_PM diff --git a/drivers/staging/rtl8192u/r8190_rtl8256.c b/drivers/staging/rtl8192u/r8190_rtl8256.c new file mode 100644 index 0000000000000000000000000000000000000000..74ff337b0583500a5e6922f1077d76b27191b209 --- /dev/null +++ b/drivers/staging/rtl8192u/r8190_rtl8256.c @@ -0,0 +1,312 @@ +/* + This is part of the rtl8192 driver + released under the GPL (See file COPYING for details). + + This files contains programming code for the rtl8256 + radio frontend. + + *Many* thanks to Realtek Corp. for their great support! + +*/ + +#include "r8192U.h" +#include "r8192U_hw.h" +#include "r819xU_phyreg.h" +#include "r819xU_phy.h" +#include "r8190_rtl8256.h" + +/*-------------------------------------------------------------------------- + * Overview: set RF band width (20M or 40M) + * Input: struct net_device* dev + * WIRELESS_BANDWIDTH_E Bandwidth //20M or 40M + * Output: NONE + * Return: NONE + * Note: 8226 support both 20M and 40 MHz + *---------------------------------------------------------------------------*/ +void PHY_SetRF8256Bandwidth(struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth) //20M or 40M +{ + u8 eRFPath; + struct r8192_priv *priv = ieee80211_priv(dev); + + //for(eRFPath = RF90_PATH_A; eRFPath NumTotalRFPath; eRFPath++) + for(eRFPath = 0; eRFPath card_8192_version == VERSION_819xU_A || priv->card_8192_version == VERSION_819xU_B)// 8256 D-cut, E-cut, xiong: consider it later! + { + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x100); //phy para:1ba + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3d7); + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0e, bMask12Bits, 0x021); + + //cosa add for sd3's request 01/23/2008 + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x5ab); + } + else + { + RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown hardware version\n"); + } + + break; + case HT_CHANNEL_WIDTH_20_40: + if(priv->card_8192_version == VERSION_819xU_A ||priv->card_8192_version == VERSION_819xU_B)// 8256 D-cut, E-cut, xiong: consider it later! + { + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x300); //phy para:3ba + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3df); + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0e, bMask12Bits, 0x0a1); + + //cosa add for sd3's request 01/23/2008 + if(priv->chan == 3 || priv->chan == 9) //I need to set priv->chan whenever current channel changes + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x59b); + else + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x5ab); + } + else + { + RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown hardware version\n"); + } + + + break; + default: + RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown Bandwidth: %#X\n",Bandwidth ); + break; + + } + } + return; +} +/*-------------------------------------------------------------------------- + * Overview: Interface to config 8256 + * Input: struct net_device* dev + * Output: NONE + * Return: NONE + *---------------------------------------------------------------------------*/ +void PHY_RF8256_Config(struct net_device* dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + // Initialize general global value + // + // TODO: Extend RF_PATH_C and RF_PATH_D in the future + priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH; + // Config BB and RF + phy_RF8256_Config_ParaFile(dev); + + return; +} +/*-------------------------------------------------------------------------- + * Overview: Interface to config 8256 + * Input: struct net_device* dev + * Output: NONE + * Return: NONE + *---------------------------------------------------------------------------*/ +void phy_RF8256_Config_ParaFile(struct net_device* dev) +{ + u32 u4RegValue = 0; + //static s1Byte szRadioAFile[] = RTL819X_PHY_RADIO_A; + //static s1Byte szRadioBFile[] = RTL819X_PHY_RADIO_B; + //static s1Byte szRadioCFile[] = RTL819X_PHY_RADIO_C; + //static s1Byte szRadioDFile[] = RTL819X_PHY_RADIO_D; + u8 eRFPath; + BB_REGISTER_DEFINITION_T *pPhyReg; + struct r8192_priv *priv = ieee80211_priv(dev); + u32 RegOffSetToBeCheck = 0x3; + u32 RegValueToBeCheck = 0x7f1; + u32 RF3_Final_Value = 0; + u8 ConstRetryTimes = 5, RetryTimes = 5; + u8 ret = 0; + //3//----------------------------------------------------------------- + //3// <2> Initialize RF + //3//----------------------------------------------------------------- + for(eRFPath = (RF90_RADIO_PATH_E)RF90_PATH_A; eRFPath NumTotalRFPath; eRFPath++) + { + if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) + continue; + + pPhyReg = &priv->PHYRegDef[eRFPath]; + + // Joseph test for shorten RF config + // pHalData->RfReg0Value[eRFPath] = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rGlobalCtrl, bMaskDWord); + + /*----Store original RFENV control type----*/ + switch(eRFPath) + { + case RF90_PATH_A: + case RF90_PATH_C: + u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV); + break; + case RF90_PATH_B : + case RF90_PATH_D: + u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16); + break; + } + + /*----Set RF_ENV enable----*/ + rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1); + + /*----Set RF_ENV output high----*/ + rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); + + /* Set bit number of Address and Data for RF register */ + rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); // Set 0 to 4 bits for Z-serial and set 1 to 6 bits for 8258 + rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); // Set 0 to 12 bits for Z-serial and 8258, and set 1 to 14 bits for ??? + + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E) eRFPath, 0x0, bMask12Bits, 0xbf); + + /*----Check RF block (for FPGA platform only)----*/ + // TODO: this function should be removed on ASIC , Emily 2007.2.2 + if (rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF, (RF90_RADIO_PATH_E)eRFPath)) + { + RT_TRACE(COMP_ERR, "PHY_RF8256_Config():Check Radio[%d] Fail!!\n", eRFPath); + goto phy_RF8256_Config_ParaFile_Fail; + } + + RetryTimes = ConstRetryTimes; + RF3_Final_Value = 0; + /*----Initialize RF fom connfiguration file----*/ + switch(eRFPath) + { + case RF90_PATH_A: + while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0) + { + ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath); + RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits); + RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value); + RetryTimes--; + } + break; + case RF90_PATH_B: + while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0) + { + ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath); + RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits); + RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value); + RetryTimes--; + } + break; + case RF90_PATH_C: + while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0) + { + ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath); + RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits); + RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value); + RetryTimes--; + } + break; + case RF90_PATH_D: + while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0) + { + ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath); + RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits); + RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value); + RetryTimes--; + } + break; + } + + /*----Restore RFENV control type----*/; + switch(eRFPath) + { + case RF90_PATH_A: + case RF90_PATH_C: + rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue); + break; + case RF90_PATH_B : + case RF90_PATH_D: + rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue); + break; + } + + if(ret){ + RT_TRACE(COMP_ERR, "phy_RF8256_Config_ParaFile():Radio[%d] Fail!!", eRFPath); + goto phy_RF8256_Config_ParaFile_Fail; + } + + } + + RT_TRACE(COMP_PHY, "PHY Initialization Success\n") ; + return ; + +phy_RF8256_Config_ParaFile_Fail: + RT_TRACE(COMP_ERR, "PHY Initialization failed\n") ; + return ; +} + + +void PHY_SetRF8256CCKTxPower(struct net_device* dev, u8 powerlevel) +{ + u32 TxAGC=0; + struct r8192_priv *priv = ieee80211_priv(dev); + //modified by vivi, 20080109 + TxAGC = powerlevel; + + if(priv->bDynamicTxLowPower == TRUE ) //cosa 05/22/2008 for scan + { + if(priv->CustomerID == RT_CID_819x_Netcore) + TxAGC = 0x22; + else + TxAGC += priv->CckPwEnl; + } + + if(TxAGC > 0x24) + TxAGC = 0x24; + rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC); +} + + +void PHY_SetRF8256OFDMTxPower(struct net_device* dev, u8 powerlevel) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + //Joseph TxPower for 8192 testing + u32 writeVal, powerBase0, powerBase1, writeVal_tmp; + u8 index = 0; + u16 RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c}; + u8 byte0, byte1, byte2, byte3; + + powerBase0 = powerlevel + priv->TxPowerDiff; //OFDM rates + powerBase0 = (powerBase0<<24) | (powerBase0<<16) |(powerBase0<<8) |powerBase0; + powerBase1 = powerlevel; //MCS rates + powerBase1 = (powerBase1<<24) | (powerBase1<<16) |(powerBase1<<8) |powerBase1; + + for(index=0; index<6; index++) + { + writeVal = priv->MCSTxPowerLevelOriginalOffset[index] + ((index<2)?powerBase0:powerBase1); + byte0 = (u8)(writeVal & 0x7f); + byte1 = (u8)((writeVal & 0x7f00)>>8); + byte2 = (u8)((writeVal & 0x7f0000)>>16); + byte3 = (u8)((writeVal & 0x7f000000)>>24); + if(byte0 > 0x24) // Max power index = 0x24 + byte0 = 0x24; + if(byte1 > 0x24) + byte1 = 0x24; + if(byte2 > 0x24) + byte2 = 0x24; + if(byte3 > 0x24) + byte3 = 0x24; + + //for tx power track + if(index == 3) + { + writeVal_tmp = (byte3<<24) | (byte2<<16) |(byte1<<8) |byte0; + priv->Pwr_Track = writeVal_tmp; + } + + if(priv->bDynamicTxHighPower == TRUE) //Add by Jacken 2008/03/06 + { + // Emily, 20080613. Set low tx power for both MCS and legacy OFDM + writeVal = 0x03030303; + } + else + { + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) |byte0; + } + rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); + } + return; + +} + diff --git a/drivers/staging/rtl8192u/r8190_rtl8256.h b/drivers/staging/rtl8192u/r8190_rtl8256.h new file mode 100644 index 0000000000000000000000000000000000000000..5c1f650fe8248a969a464e0b14300ef9c4c44bba --- /dev/null +++ b/drivers/staging/rtl8192u/r8190_rtl8256.h @@ -0,0 +1,27 @@ +/* + This is part of the rtl8180-sa2400 driver + released under the GPL (See file COPYING for details). + Copyright (c) 2005 Andrea Merello + + This files contains programming code for the rtl8256 + radio frontend. + + *Many* thanks to Realtek Corp. for their great support! + +*/ + +#ifndef RTL8225H +#define RTL8225H + +#ifdef RTL8190P +#define RTL819X_TOTAL_RF_PATH 4 //for 90P +#else +#define RTL819X_TOTAL_RF_PATH 2 //for 8192U +#endif +extern void PHY_SetRF8256Bandwidth(struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth); +extern void PHY_RF8256_Config(struct net_device* dev); +extern void phy_RF8256_Config_ParaFile(struct net_device* dev); +extern void PHY_SetRF8256CCKTxPower(struct net_device* dev, u8 powerlevel); +extern void PHY_SetRF8256OFDMTxPower(struct net_device* dev, u8 powerlevel); + +#endif diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h new file mode 100644 index 0000000000000000000000000000000000000000..69a2721e850c220f2856a8a193c1a3ced8c9d1f9 --- /dev/null +++ b/drivers/staging/rtl8192u/r8192U.h @@ -0,0 +1,1263 @@ +/* + This is part of rtl8187 OpenSource driver. + Copyright (C) Andrea Merello 2004-2005 + Released under the terms of GPL (General Public Licence) + + Parts of this driver are based on the GPL part of the + official realtek driver + + Parts of this driver are based on the rtl8192 driver skeleton + from Patric Schenke & Andres Salomon + + Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver + + We want to tanks the Authors of those projects and the Ndiswrapper + project Authors. +*/ + +#ifndef R819xU_H +#define R819xU_H + +#include +#include +//#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include //for rtnl_lock() +#include +#include +#include // Necessary because we use the proc fs +#include +#include +#include +#include +#include "ieee80211.h" + +#define RTL8192U +#define RTL819xU_MODULE_NAME "rtl819xU" +//added for HW security, john.0629 +#define FALSE 0 +#define TRUE 1 +#define MAX_KEY_LEN 61 +#define KEY_BUF_SIZE 5 + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +// Rx smooth factor +#define Rx_Smooth_Factor 20 +#define DMESG(x,a...) +#define DMESGW(x,a...) +#define DMESGE(x,a...) +extern u32 rt_global_debug_component; +#define RT_TRACE(component, x, args...) \ +do { if(rt_global_debug_component & component) \ + printk(KERN_DEBUG RTL819xU_MODULE_NAME ":" x "\n" , \ + ##args);\ +}while(0); + +#define COMP_TRACE BIT0 // For function call tracing. +#define COMP_DBG BIT1 // Only for temporary debug message. +#define COMP_INIT BIT2 // during driver initialization / halt / reset. + + +#define COMP_RECV BIT3 // Reveive part data path. +#define COMP_SEND BIT4 // Send part path. +#define COMP_IO BIT5 // I/O Related. Added by Annie, 2006-03-02. +#define COMP_POWER BIT6 // 802.11 Power Save mode or System/Device Power state related. +#define COMP_EPROM BIT7 // 802.11 link related: join/start BSS, leave BSS. +#define COMP_SWBW BIT8 // For bandwidth switch. +#define COMP_POWER_TRACKING BIT9 //FOR 8190 TX POWER TRACKING +#define COMP_TURBO BIT10 // For Turbo Mode related. By Annie, 2005-10-21. +#define COMP_QOS BIT11 // For QoS. +#define COMP_RATE BIT12 // For Rate Adaptive mechanism, 2006.07.02, by rcnjko. +#define COMP_RM BIT13 // For Radio Measurement. +#define COMP_DIG BIT14 // For DIG, 2006.09.25, by rcnjko. +#define COMP_PHY BIT15 +#define COMP_CH BIT16 //channel setting debug +#define COMP_TXAGC BIT17 // For Tx power, 060928, by rcnjko. +#define COMP_HIPWR BIT18 // For High Power Mechanism, 060928, by rcnjko. +#define COMP_HALDM BIT19 // For HW Dynamic Mechanism, 061010, by rcnjko. +#define COMP_SEC BIT20 // Event handling +#define COMP_LED BIT21 // For LED. +#define COMP_RF BIT22 // For RF. +//1!!!!!!!!!!!!!!!!!!!!!!!!!!! +#define COMP_RXDESC BIT23 // Show Rx desc information for SD3 debug. Added by Annie, 2006-07-15. +//1//1Attention Please!!!<11n or 8190 specific code should be put below this line> +//1!!!!!!!!!!!!!!!!!!!!!!!!!!! + +#define COMP_FIRMWARE BIT24 //for firmware downloading +#define COMP_HT BIT25 // For 802.11n HT related information. by Emily 2006-8-11 +#define COMP_AMSDU BIT26 // For A-MSDU Debugging + +#define COMP_SCAN BIT27 +//#define COMP_RESET BIT28 +#define COMP_DOWN BIT29 //for rm driver module +#define COMP_RESET BIT30 //for silent reset +#define COMP_ERR BIT31 //for error out, always on + +#define RTL819x_DEBUG +#ifdef RTL819x_DEBUG +#define assert(expr) \ + if (!(expr)) { \ + printk( "Assertion failed! %s,%s,%s,line=%d\n", \ + #expr,__FILE__,__FUNCTION__,__LINE__); \ + } +//wb added to debug out data buf +//if you want print DATA buffer related BA, please set ieee80211_debug_level to DATA|BA +#define RT_DEBUG_DATA(level, data, datalen) \ + do{ if ((rt_global_debug_component & (level)) == (level)) \ + { \ + int i; \ + u8* pdata = (u8*) data; \ + printk(KERN_DEBUG RTL819xU_MODULE_NAME ": %s()\n", __FUNCTION__); \ + for(i=0; i<(int)(datalen); i++) \ + { \ + printk("%2x ", pdata[i]); \ + if ((i+1)%16 == 0) printk("\n"); \ + } \ + printk("\n"); \ + } \ + } while (0) +#else +#define assert(expr) do {} while (0) +#define RT_DEBUG_DATA(level, data, datalen) do {} while(0) +#endif /* RTL8169_DEBUG */ + + +// +// Queue Select Value in TxDesc +// +#define QSLT_BK 0x1 +#define QSLT_BE 0x0 +#define QSLT_VI 0x4 +#define QSLT_VO 0x6 +#define QSLT_BEACON 0x10 +#define QSLT_HIGH 0x11 +#define QSLT_MGNT 0x12 +#define QSLT_CMD 0x13 + +#define DESC90_RATE1M 0x00 +#define DESC90_RATE2M 0x01 +#define DESC90_RATE5_5M 0x02 +#define DESC90_RATE11M 0x03 +#define DESC90_RATE6M 0x04 +#define DESC90_RATE9M 0x05 +#define DESC90_RATE12M 0x06 +#define DESC90_RATE18M 0x07 +#define DESC90_RATE24M 0x08 +#define DESC90_RATE36M 0x09 +#define DESC90_RATE48M 0x0a +#define DESC90_RATE54M 0x0b +#define DESC90_RATEMCS0 0x00 +#define DESC90_RATEMCS1 0x01 +#define DESC90_RATEMCS2 0x02 +#define DESC90_RATEMCS3 0x03 +#define DESC90_RATEMCS4 0x04 +#define DESC90_RATEMCS5 0x05 +#define DESC90_RATEMCS6 0x06 +#define DESC90_RATEMCS7 0x07 +#define DESC90_RATEMCS8 0x08 +#define DESC90_RATEMCS9 0x09 +#define DESC90_RATEMCS10 0x0a +#define DESC90_RATEMCS11 0x0b +#define DESC90_RATEMCS12 0x0c +#define DESC90_RATEMCS13 0x0d +#define DESC90_RATEMCS14 0x0e +#define DESC90_RATEMCS15 0x0f +#define DESC90_RATEMCS32 0x20 + +#define RTL819X_DEFAULT_RF_TYPE RF_1T2R + +#define IEEE80211_WATCH_DOG_TIME 2000 +#define PHY_Beacon_RSSI_SLID_WIN_MAX 10 +//for txpowertracking by amy +#define OFDM_Table_Length 19 +#define CCK_Table_length 12 + +/* for rtl819x */ +typedef struct _tx_desc_819x_usb { + //DWORD 0 + u16 PktSize; + u8 Offset; + u8 Reserved0:3; + u8 CmdInit:1; + u8 LastSeg:1; + u8 FirstSeg:1; + u8 LINIP:1; + u8 OWN:1; + + //DWORD 1 + u8 TxFWInfoSize; + u8 RATid:3; + u8 DISFB:1; + u8 USERATE:1; + u8 MOREFRAG:1; + u8 NoEnc:1; + u8 PIFS:1; + u8 QueueSelect:5; + u8 NoACM:1; + u8 Reserved1:2; + u8 SecCAMID:5; + u8 SecDescAssign:1; + u8 SecType:2; + + //DWORD 2 + u16 TxBufferSize; + //u16 Reserved2; + u8 ResvForPaddingLen:7; + u8 Reserved3:1; + u8 Reserved4; + + //DWORD 3, 4, 5 + u32 Reserved5; + u32 Reserved6; + u32 Reserved7; +}tx_desc_819x_usb, *ptx_desc_819x_usb; + +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE +typedef struct _tx_desc_819x_usb_aggr_subframe { + //DWORD 0 + u16 PktSize; + u8 Offset; + u8 TxFWInfoSize; + + //DWORD 1 + u8 RATid:3; + u8 DISFB:1; + u8 USERATE:1; + u8 MOREFRAG:1; + u8 NoEnc:1; + u8 PIFS:1; + u8 QueueSelect:5; + u8 NoACM:1; + u8 Reserved1:2; + u8 SecCAMID:5; + u8 SecDescAssign:1; + u8 SecType:2; + u8 PacketID:7; + u8 OWN:1; +}tx_desc_819x_usb_aggr_subframe, *ptx_desc_819x_usb_aggr_subframe; +#endif + + + +typedef struct _tx_desc_cmd_819x_usb { + //DWORD 0 + u16 Reserved0; + u8 Reserved1; + u8 Reserved2:3; + u8 CmdInit:1; + u8 LastSeg:1; + u8 FirstSeg:1; + u8 LINIP:1; + u8 OWN:1; + + //DOWRD 1 + //u32 Reserved3; + u8 TxFWInfoSize; + u8 Reserved3; + u8 QueueSelect; + u8 Reserved4; + + //DOWRD 2 + u16 TxBufferSize; + u16 Reserved5; + + //DWORD 3,4,5 + //u32 TxBufferAddr; + //u32 NextDescAddress; + u32 Reserved6; + u32 Reserved7; + u32 Reserved8; +}tx_desc_cmd_819x_usb, *ptx_desc_cmd_819x_usb; + + +typedef struct _tx_fwinfo_819x_usb { + //DOWRD 0 + u8 TxRate:7; + u8 CtsEnable:1; + u8 RtsRate:7; + u8 RtsEnable:1; + u8 TxHT:1; + u8 Short:1; //Short PLCP for CCK, or short GI for 11n MCS + u8 TxBandwidth:1; // This is used for HT MCS rate only. + u8 TxSubCarrier:2; // This is used for legacy OFDM rate only. + u8 STBC:2; + u8 AllowAggregation:1; + u8 RtsHT:1; //Interpre RtsRate field as high throughput data rate + u8 RtsShort:1; //Short PLCP for CCK, or short GI for 11n MCS + u8 RtsBandwidth:1; // This is used for HT MCS rate only. + u8 RtsSubcarrier:2; // This is used for legacy OFDM rate only. + u8 RtsSTBC:2; + u8 EnableCPUDur:1; //Enable firmware to recalculate and assign packet duration + + //DWORD 1 + u32 RxMF:2; + u32 RxAMD:3; + u32 TxPerPktInfoFeedback:1;//1 indicate Tx info gathtered by firmware and returned by Rx Cmd + u32 Reserved1:2; + u32 TxAGCOffSet:4; + u32 TxAGCSign:1; + u32 Tx_INFO_RSVD:6; + u32 PacketID:13; + //u32 Reserved; +}tx_fwinfo_819x_usb, *ptx_fwinfo_819x_usb; + +typedef struct rtl8192_rx_info { + struct urb *urb; + struct net_device *dev; + u8 out_pipe; +}rtl8192_rx_info ; + +typedef struct rx_desc_819x_usb{ + //DOWRD 0 + u16 Length:14; + u16 CRC32:1; + u16 ICV:1; + u8 RxDrvInfoSize; + u8 Shift:2; + u8 PHYStatus:1; + u8 SWDec:1; + //u8 LastSeg:1; + //u8 FirstSeg:1; + //u8 EOR:1; + //u8 OWN:1; + u8 Reserved1:4; + + //DWORD 1 + u32 Reserved2; + + //DWORD 2 + //u32 Reserved3; + + //DWORD 3 + //u32 BufferAddress; + +}rx_desc_819x_usb, *prx_desc_819x_usb; + +#ifdef USB_RX_AGGREGATION_SUPPORT +typedef struct _rx_desc_819x_usb_aggr_subframe{ + //DOWRD 0 + u16 Length:14; + u16 CRC32:1; + u16 ICV:1; + u8 Offset; + u8 RxDrvInfoSize; + //DOWRD 1 + u8 Shift:2; + u8 PHYStatus:1; + u8 SWDec:1; + u8 Reserved1:4; + u8 Reserved2; + u16 Reserved3; + //DWORD 2 + //u4Byte Reserved3; + //DWORD 3 + //u4Byte BufferAddress; +}rx_desc_819x_usb_aggr_subframe, *prx_desc_819x_usb_aggr_subframe; +#endif + +typedef struct rx_drvinfo_819x_usb{ + //DWORD 0 + u16 Reserved1:12; + u16 PartAggr:1; + u16 FirstAGGR:1; + u16 Reserved2:2; + + u8 RxRate:7; + u8 RxHT:1; + + u8 BW:1; + u8 SPLCP:1; + u8 Reserved3:2; + u8 PAM:1; + u8 Mcast:1; + u8 Bcast:1; + u8 Reserved4:1; + + //DWORD 1 + u32 TSFL; + +}rx_drvinfo_819x_usb, *prx_drvinfo_819x_usb; + + +#define MAX_DEV_ADDR_SIZE 8 /* support till 64 bit bus width OS */ +#define MAX_FIRMWARE_INFORMATION_SIZE 32 /*2006/04/30 by Emily forRTL8190*/ +#define MAX_802_11_HEADER_LENGTH (40 + MAX_FIRMWARE_INFORMATION_SIZE) +#define ENCRYPTION_MAX_OVERHEAD 128 +#define USB_HWDESC_HEADER_LEN sizeof(tx_desc_819x_usb) +#define TX_PACKET_SHIFT_BYTES (USB_HWDESC_HEADER_LEN + sizeof(tx_fwinfo_819x_usb)) +#define MAX_FRAGMENT_COUNT 8 +#ifdef RTL8192U +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE +#define MAX_TRANSMIT_BUFFER_SIZE 32000 +#else +#define MAX_TRANSMIT_BUFFER_SIZE 8000 +#endif +#else +#define MAX_TRANSMIT_BUFFER_SIZE (1600+(MAX_802_11_HEADER_LENGTH+ENCRYPTION_MAX_OVERHEAD)*MAX_FRAGMENT_COUNT) +#endif +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE +#define TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES (sizeof(tx_desc_819x_usb_aggr_subframe) + sizeof(tx_fwinfo_819x_usb)) +#endif +#define scrclng 4 // octets for crc32 (FCS, ICV) + +typedef enum rf_optype +{ + RF_OP_By_SW_3wire = 0, + RF_OP_By_FW, + RF_OP_MAX +}rf_op_type; +/* 8190 Loopback Mode definition */ +typedef enum _rtl819xUsb_loopback{ + RTL819xU_NO_LOOPBACK = 0, + RTL819xU_MAC_LOOPBACK = 1, + RTL819xU_DMA_LOOPBACK = 2, + RTL819xU_CCK_LOOPBACK = 3, +}rtl819xUsb_loopback_e; + +/* due to rtl8192 firmware */ +typedef enum _desc_packet_type_e{ + DESC_PACKET_TYPE_INIT = 0, + DESC_PACKET_TYPE_NORMAL = 1, +}desc_packet_type_e; + +typedef enum _firmware_source{ + FW_SOURCE_IMG_FILE = 0, + FW_SOURCE_HEADER_FILE = 1, //from header file +}firmware_source_e, *pfirmware_source_e; + +typedef enum _firmware_status{ + FW_STATUS_0_INIT = 0, + FW_STATUS_1_MOVE_BOOT_CODE = 1, + FW_STATUS_2_MOVE_MAIN_CODE = 2, + FW_STATUS_3_TURNON_CPU = 3, + FW_STATUS_4_MOVE_DATA_CODE = 4, + FW_STATUS_5_READY = 5, +}firmware_status_e; + +typedef struct _rt_firmare_seg_container { + u16 seg_size; + u8 *seg_ptr; +}fw_seg_container, *pfw_seg_container; +typedef struct _rt_firmware{ + firmware_status_e firmware_status; + u16 cmdpacket_frag_thresold; +#define RTL8190_MAX_FIRMWARE_CODE_SIZE 64000 //64k + u8 firmware_buf[RTL8190_MAX_FIRMWARE_CODE_SIZE]; + u16 firmware_buf_size; +}rt_firmware, *prt_firmware; + +//+by amy 080507 +#define MAX_RECEIVE_BUFFER_SIZE 9100 // Add this to 9100 bytes to receive A-MSDU from RT-AP + +typedef struct _rt_firmware_info_819xUsb{ + u8 sz_info[16]; +}rt_firmware_info_819xUsb, *prt_firmware_info_819xUsb; + +/* Firmware Queue Layout */ +#define NUM_OF_FIRMWARE_QUEUE 10 +#define NUM_OF_PAGES_IN_FW 0x100 + +#ifdef USE_ONE_PIPE +#define NUM_OF_PAGE_IN_FW_QUEUE_BE 0x000 +#define NUM_OF_PAGE_IN_FW_QUEUE_BK 0x000 +#define NUM_OF_PAGE_IN_FW_QUEUE_VI 0x0ff +#define NUM_OF_PAGE_IN_FW_QUEUE_VO 0x000 +#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA 0 +#define NUM_OF_PAGE_IN_FW_QUEUE_CMD 0x0 +#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT 0x00 +#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH 0 +#define NUM_OF_PAGE_IN_FW_QUEUE_BCN 0x0 +#define NUM_OF_PAGE_IN_FW_QUEUE_PUB 0x00 +#else + +#define NUM_OF_PAGE_IN_FW_QUEUE_BE 0x020 +#define NUM_OF_PAGE_IN_FW_QUEUE_BK 0x020 +#define NUM_OF_PAGE_IN_FW_QUEUE_VI 0x040 +#define NUM_OF_PAGE_IN_FW_QUEUE_VO 0x040 +#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA 0 +#define NUM_OF_PAGE_IN_FW_QUEUE_CMD 0x4 +#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT 0x20 +#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH 0 +#define NUM_OF_PAGE_IN_FW_QUEUE_BCN 0x4 +#define NUM_OF_PAGE_IN_FW_QUEUE_PUB 0x18 + +#endif + +#define APPLIED_RESERVED_QUEUE_IN_FW 0x80000000 +#define RSVD_FW_QUEUE_PAGE_BK_SHIFT 0x00 +#define RSVD_FW_QUEUE_PAGE_BE_SHIFT 0x08 +#define RSVD_FW_QUEUE_PAGE_VI_SHIFT 0x10 +#define RSVD_FW_QUEUE_PAGE_VO_SHIFT 0x18 +#define RSVD_FW_QUEUE_PAGE_MGNT_SHIFT 0x10 +#define RSVD_FW_QUEUE_PAGE_CMD_SHIFT 0x08 +#define RSVD_FW_QUEUE_PAGE_BCN_SHIFT 0x00 +#define RSVD_FW_QUEUE_PAGE_PUB_SHIFT 0x08 +//================================================================= +//================================================================= + +#define EPROM_93c46 0 +#define EPROM_93c56 1 + +#define DEFAULT_FRAG_THRESHOLD 2342U +#define MIN_FRAG_THRESHOLD 256U +#define DEFAULT_BEACONINTERVAL 0x64U +#define DEFAULT_BEACON_ESSID "Rtl819xU" + +#define DEFAULT_SSID "" +#define DEFAULT_RETRY_RTS 7 +#define DEFAULT_RETRY_DATA 7 +#define PRISM_HDR_SIZE 64 + +#define PHY_RSSI_SLID_WIN_MAX 100 + + +typedef enum _WIRELESS_MODE { + WIRELESS_MODE_UNKNOWN = 0x00, + WIRELESS_MODE_A = 0x01, + WIRELESS_MODE_B = 0x02, + WIRELESS_MODE_G = 0x04, + WIRELESS_MODE_AUTO = 0x08, + WIRELESS_MODE_N_24G = 0x10, + WIRELESS_MODE_N_5G = 0x20 +} WIRELESS_MODE; + + +#define RTL_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30 + +typedef struct buffer +{ + struct buffer *next; + u32 *buf; + +} buffer; + +typedef struct rtl_reg_debug{ + unsigned int cmd; + struct { + unsigned char type; + unsigned char addr; + unsigned char page; + unsigned char length; + } head; + unsigned char buf[0xff]; +}rtl_reg_debug; + + + + + + +typedef struct _rt_9x_tx_rate_history { + u32 cck[4]; + u32 ofdm[8]; + // HT_MCS[0][]: BW=0 SG=0 + // HT_MCS[1][]: BW=1 SG=0 + // HT_MCS[2][]: BW=0 SG=1 + // HT_MCS[3][]: BW=1 SG=1 + u32 ht_mcs[4][16]; +}rt_tx_rahis_t, *prt_tx_rahis_t; +typedef struct _RT_SMOOTH_DATA_4RF { + char elements[4][100];//array to store values + u32 index; //index to current array to store + u32 TotalNum; //num of valid elements + u32 TotalVal[4]; //sum of valid elements +}RT_SMOOTH_DATA_4RF, *PRT_SMOOTH_DATA_4RF; + +#define MAX_8192U_RX_SIZE 8192 // This maybe changed for D-cut larger aggregation size +//stats seems messed up, clean it ASAP +typedef struct Stats +{ + unsigned long txrdu; +// unsigned long rxrdu; + //unsigned long rxnolast; + //unsigned long rxnodata; +// unsigned long rxreset; +// unsigned long rxnopointer; + unsigned long rxok; + unsigned long rxframgment; + unsigned long rxcmdpkt[4]; //08/05/08 amy rx cmd element txfeedback/bcn report/cfg set/query + unsigned long rxurberr; + unsigned long rxstaterr; + unsigned long received_rate_histogram[4][32]; //0: Total, 1:OK, 2:CRC, 3:ICV, 2007 07 03 cosa + unsigned long received_preamble_GI[2][32]; //0: Long preamble/GI, 1:Short preamble/GI + unsigned long rx_AMPDUsize_histogram[5]; // level: (<4K), (4K~8K), (8K~16K), (16K~32K), (32K~64K) + unsigned long rx_AMPDUnum_histogram[5]; // level: (<5), (5~10), (10~20), (20~40), (>40) + unsigned long numpacket_matchbssid; // debug use only. + unsigned long numpacket_toself; // debug use only. + unsigned long num_process_phyinfo; // debug use only. + unsigned long numqry_phystatus; + unsigned long numqry_phystatusCCK; + unsigned long numqry_phystatusHT; + unsigned long received_bwtype[5]; //0: 20M, 1: funn40M, 2: upper20M, 3: lower20M, 4: duplicate + unsigned long txnperr; + unsigned long txnpdrop; + unsigned long txresumed; +// unsigned long rxerr; +// unsigned long rxoverflow; +// unsigned long rxint; + unsigned long txnpokint; +// unsigned long txhpokint; +// unsigned long txhperr; +// unsigned long ints; +// unsigned long shints; + unsigned long txoverflow; +// unsigned long rxdmafail; +// unsigned long txbeacon; +// unsigned long txbeaconerr; + unsigned long txlpokint; + unsigned long txlpdrop; + unsigned long txlperr; + unsigned long txbeokint; + unsigned long txbedrop; + unsigned long txbeerr; + unsigned long txbkokint; + unsigned long txbkdrop; + unsigned long txbkerr; + unsigned long txviokint; + unsigned long txvidrop; + unsigned long txvierr; + unsigned long txvookint; + unsigned long txvodrop; + unsigned long txvoerr; + unsigned long txbeaconokint; + unsigned long txbeacondrop; + unsigned long txbeaconerr; + unsigned long txmanageokint; + unsigned long txmanagedrop; + unsigned long txmanageerr; + unsigned long txdatapkt; + unsigned long txfeedback; + unsigned long txfeedbackok; + + unsigned long txoktotal; + unsigned long txokbytestotal; + unsigned long txokinperiod; + unsigned long txmulticast; + unsigned long txbytesmulticast; + unsigned long txbroadcast; + unsigned long txbytesbroadcast; + unsigned long txunicast; + unsigned long txbytesunicast; + + unsigned long rxoktotal; + unsigned long rxbytesunicast; + unsigned long txfeedbackfail; + unsigned long txerrtotal; + unsigned long txerrbytestotal; + unsigned long txerrmulticast; + unsigned long txerrbroadcast; + unsigned long txerrunicast; + unsigned long txretrycount; + unsigned long txfeedbackretry; + u8 last_packet_rate; + unsigned long slide_signal_strength[100]; + unsigned long slide_evm[100]; + unsigned long slide_rssi_total; // For recording sliding window's RSSI value + unsigned long slide_evm_total; // For recording sliding window's EVM value + long signal_strength; // Transformed, in dbm. Beautified signal strength for UI, not correct. + long signal_quality; + long last_signal_strength_inpercent; + long recv_signal_power; // Correct smoothed ss in Dbm, only used in driver to report real power now. + u8 rx_rssi_percentage[4]; + u8 rx_evm_percentage[2]; + long rxSNRdB[4]; + rt_tx_rahis_t txrate; + u32 Slide_Beacon_pwdb[100]; //cosa add for beacon rssi + u32 Slide_Beacon_Total; //cosa add for beacon rssi + RT_SMOOTH_DATA_4RF cck_adc_pwdb; + + u32 CurrentShowTxate; +} Stats; + + +// Bandwidth Offset +#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 +#define HAL_PRIME_CHNL_OFFSET_LOWER 1 +#define HAL_PRIME_CHNL_OFFSET_UPPER 2 + +//+by amy 080507 + +typedef struct ChnlAccessSetting { + u16 SIFS_Timer; + u16 DIFS_Timer; + u16 SlotTimeTimer; + u16 EIFS_Timer; + u16 CWminIndex; + u16 CWmaxIndex; +}*PCHANNEL_ACCESS_SETTING,CHANNEL_ACCESS_SETTING; + +typedef struct _BB_REGISTER_DEFINITION{ + u32 rfintfs; // set software control: // 0x870~0x877[8 bytes] + u32 rfintfi; // readback data: // 0x8e0~0x8e7[8 bytes] + u32 rfintfo; // output data: // 0x860~0x86f [16 bytes] + u32 rfintfe; // output enable: // 0x860~0x86f [16 bytes] + u32 rf3wireOffset; // LSSI data: // 0x840~0x84f [16 bytes] + u32 rfLSSI_Select; // BB Band Select: // 0x878~0x87f [8 bytes] + u32 rfTxGainStage; // Tx gain stage: // 0x80c~0x80f [4 bytes] + u32 rfHSSIPara1; // wire parameter control1 : // 0x820~0x823,0x828~0x82b, 0x830~0x833, 0x838~0x83b [16 bytes] + u32 rfHSSIPara2; // wire parameter control2 : // 0x824~0x827,0x82c~0x82f, 0x834~0x837, 0x83c~0x83f [16 bytes] + u32 rfSwitchControl; //Tx Rx antenna control : // 0x858~0x85f [16 bytes] + u32 rfAGCControl1; //AGC parameter control1 : // 0xc50~0xc53,0xc58~0xc5b, 0xc60~0xc63, 0xc68~0xc6b [16 bytes] + u32 rfAGCControl2; //AGC parameter control2 : // 0xc54~0xc57,0xc5c~0xc5f, 0xc64~0xc67, 0xc6c~0xc6f [16 bytes] + u32 rfRxIQImbalance; //OFDM Rx IQ imbalance matrix : // 0xc14~0xc17,0xc1c~0xc1f, 0xc24~0xc27, 0xc2c~0xc2f [16 bytes] + u32 rfRxAFE; //Rx IQ DC ofset and Rx digital filter, Rx DC notch filter : // 0xc10~0xc13,0xc18~0xc1b, 0xc20~0xc23, 0xc28~0xc2b [16 bytes] + u32 rfTxIQImbalance; //OFDM Tx IQ imbalance matrix // 0xc80~0xc83,0xc88~0xc8b, 0xc90~0xc93, 0xc98~0xc9b [16 bytes] + u32 rfTxAFE; //Tx IQ DC Offset and Tx DFIR type // 0xc84~0xc87,0xc8c~0xc8f, 0xc94~0xc97, 0xc9c~0xc9f [16 bytes] + u32 rfLSSIReadBack; //LSSI RF readback data // 0x8a0~0x8af [16 bytes] +}BB_REGISTER_DEFINITION_T, *PBB_REGISTER_DEFINITION_T; + +typedef enum _RT_RF_TYPE_819xU{ + RF_TYPE_MIN = 0, + RF_8225, + RF_8256, + RF_8258, + RF_PSEUDO_11N = 4, +}RT_RF_TYPE_819xU, *PRT_RF_TYPE_819xU; + +typedef struct _rate_adaptive +{ + u8 rate_adaptive_disabled; + u8 ratr_state; + u16 reserve; + + u32 high_rssi_thresh_for_ra; + u32 high2low_rssi_thresh_for_ra; + u8 low2high_rssi_thresh_for_ra40M; + u32 low_rssi_thresh_for_ra40M; + u8 low2high_rssi_thresh_for_ra20M; + u32 low_rssi_thresh_for_ra20M; + u32 upper_rssi_threshold_ratr; + u32 middle_rssi_threshold_ratr; + u32 low_rssi_threshold_ratr; + u32 low_rssi_threshold_ratr_40M; + u32 low_rssi_threshold_ratr_20M; + u8 ping_rssi_enable; //cosa add for test + u32 ping_rssi_ratr; //cosa add for test + u32 ping_rssi_thresh_for_ra;//cosa add for test + u32 last_ratr; + +} rate_adaptive, *prate_adaptive; + +#define TxBBGainTableLength 37 +#define CCKTxBBGainTableLength 23 + +typedef struct _txbbgain_struct +{ + long txbb_iq_amplifygain; + u32 txbbgain_value; +} txbbgain_struct, *ptxbbgain_struct; + +typedef struct _ccktxbbgain_struct +{ + //The Value is from a22 to a29 one Byte one time is much Safer + u8 ccktxbb_valuearray[8]; +} ccktxbbgain_struct,*pccktxbbgain_struct; + + +typedef struct _init_gain +{ + u8 xaagccore1; + u8 xbagccore1; + u8 xcagccore1; + u8 xdagccore1; + u8 cca; + +} init_gain, *pinit_gain; +//by amy 0606 + +typedef struct _phy_ofdm_rx_status_report_819xusb +{ + u8 trsw_gain_X[4]; + u8 pwdb_all; + u8 cfosho_X[4]; + u8 cfotail_X[4]; + u8 rxevm_X[2]; + u8 rxsnr_X[4]; + u8 pdsnr_X[2]; + u8 csi_current_X[2]; + u8 csi_target_X[2]; + u8 sigevm; + u8 max_ex_pwr; + u8 sgi_en; + u8 rxsc_sgien_exflg; +}phy_sts_ofdm_819xusb_t; + +typedef struct _phy_cck_rx_status_report_819xusb +{ + /* For CCK rate descriptor. This is a unsigned 8:1 variable. LSB bit presend + 0.5. And MSB 7 bts presend a signed value. Range from -64~+63.5. */ + u8 adc_pwdb_X[4]; + u8 sq_rpt; + u8 cck_agc_rpt; +}phy_sts_cck_819xusb_t; + + +typedef struct _phy_ofdm_rx_status_rxsc_sgien_exintfflag{ + u8 reserved:4; + u8 rxsc:2; + u8 sgi_en:1; + u8 ex_intf_flag:1; +}phy_ofdm_rx_status_rxsc_sgien_exintfflag; + +typedef enum _RT_CUSTOMER_ID +{ + RT_CID_DEFAULT = 0, + RT_CID_8187_ALPHA0 = 1, + RT_CID_8187_SERCOMM_PS = 2, + RT_CID_8187_HW_LED = 3, + RT_CID_8187_NETGEAR = 4, + RT_CID_WHQL = 5, + RT_CID_819x_CAMEO = 6, + RT_CID_819x_RUNTOP = 7, + RT_CID_819x_Senao = 8, + RT_CID_TOSHIBA = 9, // Merge by Jacken, 2008/01/31. + RT_CID_819x_Netcore = 10, + RT_CID_Nettronix = 11, + RT_CID_DLINK = 12, + RT_CID_PRONET = 13, +}RT_CUSTOMER_ID, *PRT_CUSTOMER_ID; + +//================================================================================ +// LED customization. +//================================================================================ + +typedef enum _LED_STRATEGY_8190{ + SW_LED_MODE0, // SW control 1 LED via GPIO0. It is default option. + SW_LED_MODE1, // SW control for PCI Express + SW_LED_MODE2, // SW control for Cameo. + SW_LED_MODE3, // SW contorl for RunTop. + SW_LED_MODE4, // SW control for Netcore + HW_LED, // HW control 2 LEDs, LED0 and LED1 (there are 4 different control modes) +}LED_STRATEGY_8190, *PLED_STRATEGY_8190; + +typedef enum _RESET_TYPE { + RESET_TYPE_NORESET = 0x00, + RESET_TYPE_NORMAL = 0x01, + RESET_TYPE_SILENT = 0x02 +} RESET_TYPE; + +/* The simple tx command OP code. */ +typedef enum _tag_TxCmd_Config_Index{ + TXCMD_TXRA_HISTORY_CTRL = 0xFF900000, + TXCMD_RESET_TX_PKT_BUFF = 0xFF900001, + TXCMD_RESET_RX_PKT_BUFF = 0xFF900002, + TXCMD_SET_TX_DURATION = 0xFF900003, + TXCMD_SET_RX_RSSI = 0xFF900004, + TXCMD_SET_TX_PWR_TRACKING = 0xFF900005, + TXCMD_XXXX_CTRL, +}DCMD_TXCMD_OP; + +typedef struct r8192_priv +{ + struct usb_device *udev; + //added for maintain info from eeprom + short epromtype; + u16 eeprom_vid; + u16 eeprom_pid; + u8 eeprom_CustomerID; + u8 eeprom_ChannelPlan; + RT_CUSTOMER_ID CustomerID; + LED_STRATEGY_8190 LedStrategy; + u8 txqueue_to_outpipemap[9]; + int irq; + struct ieee80211_device *ieee80211; + + short card_8192; /* O: rtl8192, 1:rtl8185 V B/C, 2:rtl8185 V D */ + u8 card_8192_version; /* if TCR reports card V B/C this discriminates */ +// short phy_ver; /* meaningful for rtl8225 1:A 2:B 3:C */ + short enable_gpio0; + enum card_type {PCI,MINIPCI,CARDBUS,USB}card_type; + short hw_plcp_len; + short plcp_preamble_mode; + + spinlock_t irq_lock; +// spinlock_t irq_th_lock; + spinlock_t tx_lock; + struct mutex mutex; + //spinlock_t rf_lock; //used to lock rf write operation added by wb + + u16 irq_mask; +// short irq_enabled; +// struct net_device *dev; //comment this out. + short chan; + short sens; + short max_sens; + + + // u8 chtxpwr[15]; //channels from 1 to 14, 0 not used +// u8 chtxpwr_ofdm[15]; //channels from 1 to 14, 0 not used +// u8 cck_txpwr_base; +// u8 ofdm_txpwr_base; +// u8 challow[15]; //channels from 1 to 14, 0 not used + short up; + short crcmon; //if 1 allow bad crc frame reception in monitor mode +// short prism_hdr; + +// struct timer_list scan_timer; + /*short scanpending; + short stopscan;*/ +// spinlock_t scan_lock; +// u8 active_probe; + //u8 active_scan_num; + struct semaphore wx_sem; + struct semaphore rf_sem; //used to lock rf write operation added by wb, modified by david +// short hw_wep; + +// short digphy; +// short antb; +// short diversity; +// u8 cs_treshold; +// short rcr_csense; + u8 rf_type; //0 means 1T2R, 1 means 2T4R + RT_RF_TYPE_819xU rf_chip; + +// u32 key0[4]; + short (*rf_set_sens)(struct net_device *dev,short sens); + u8 (*rf_set_chan)(struct net_device *dev,u8 ch); + void (*rf_close)(struct net_device *dev); + void (*rf_init)(struct net_device *dev); + //short rate; + short promisc; + /*stats*/ + struct Stats stats; + struct iw_statistics wstats; + struct proc_dir_entry *dir_dev; + + /*RX stuff*/ +// u32 *rxring; +// u32 *rxringtail; +// dma_addr_t rxringdma; + struct urb **rx_urb; + struct urb **rx_cmd_urb; +#ifdef THOMAS_BEACON + u32 *oldaddr; +#endif +#ifdef THOMAS_TASKLET + atomic_t irt_counter;//count for irq_rx_tasklet +#endif +#ifdef JACKSON_NEW_RX + struct sk_buff **pp_rxskb; + int rx_inx; +#endif + +/* modified by davad for Rx process */ + struct sk_buff_head rx_queue; + struct sk_buff_head skb_queue; + struct work_struct qos_activate; + short tx_urb_index; + atomic_t tx_pending[0x10];//UART_PRIORITY+1 + + + struct tasklet_struct irq_rx_tasklet; + struct urb *rxurb_task; + + //2 Tx Related variables + u16 ShortRetryLimit; + u16 LongRetryLimit; + u32 TransmitConfig; + u8 RegCWinMin; // For turbo mode CW adaptive. Added by Annie, 2005-10-27. + + u32 LastRxDescTSFHigh; + u32 LastRxDescTSFLow; + + + //2 Rx Related variables + u16 EarlyRxThreshold; + u32 ReceiveConfig; + u8 AcmControl; + + u8 RFProgType; + + u8 retry_data; + u8 retry_rts; + u16 rts; + + struct ChnlAccessSetting ChannelAccessSetting; + struct work_struct reset_wq; + +/**********************************************************/ + //for rtl819xUsb + u16 basic_rate; + u8 short_preamble; + u8 slot_time; + bool bDcut; + bool bCurrentRxAggrEnable; + u8 Rf_Mode; //add for Firmware RF -R/W switch + prt_firmware pFirmware; + rtl819xUsb_loopback_e LoopbackMode; + firmware_source_e firmware_source; + u16 EEPROMTxPowerDiff; + u8 EEPROMThermalMeter; + u8 EEPROMPwDiff; + u8 EEPROMCrystalCap; + u8 EEPROM_Def_Ver; + u8 EEPROMTxPowerLevelCCK;// CCK channel 1~14 + u8 EEPROMTxPowerLevelCCK_V1[3]; + u8 EEPROMTxPowerLevelOFDM24G[3]; // OFDM 2.4G channel 1~14 + u8 EEPROMTxPowerLevelOFDM5G[24]; // OFDM 5G + +/*PHY related*/ + BB_REGISTER_DEFINITION_T PHYRegDef[4]; //Radio A/B/C/D + // Read/write are allow for following hardware information variables + u32 MCSTxPowerLevelOriginalOffset[6]; + u32 CCKTxPowerLevelOriginalOffset; + u8 TxPowerLevelCCK[14]; // CCK channel 1~14 + u8 TxPowerLevelOFDM24G[14]; // OFDM 2.4G channel 1~14 + u8 TxPowerLevelOFDM5G[14]; // OFDM 5G + u32 Pwr_Track; + u8 TxPowerDiff; + u8 AntennaTxPwDiff[2]; // Antenna gain offset, index 0 for B, 1 for C, and 2 for D + u8 CrystalCap; // CrystalCap. + u8 ThermalMeter[2]; // ThermalMeter, index 0 for RFIC0, and 1 for RFIC1 + + u8 CckPwEnl; + // Use to calculate PWBD. + u8 bCckHighPower; + long undecorated_smoothed_pwdb; + + //for set channel + u8 SwChnlInProgress; + u8 SwChnlStage; + u8 SwChnlStep; + u8 SetBWModeInProgress; + HT_CHANNEL_WIDTH CurrentChannelBW; + u8 ChannelPlan; + // 8190 40MHz mode + // + u8 nCur40MhzPrimeSC; // Control channel sub-carrier + // Joseph test for shorten RF configuration time. + // We save RF reg0 in this variable to reduce RF reading. + // + u32 RfReg0Value[4]; + u8 NumTotalRFPath; + bool brfpath_rxenable[4]; + //RF set related + bool SetRFPowerStateInProgress; +//+by amy 080507 + struct timer_list watch_dog_timer; + +//+by amy 080515 for dynamic mechenism + //Add by amy Tx Power Control for Near/Far Range 2008/05/15 + bool bdynamic_txpower; //bDynamicTxPower + bool bDynamicTxHighPower; // Tx high power state + bool bDynamicTxLowPower; // Tx low power state + bool bLastDTPFlag_High; + bool bLastDTPFlag_Low; + + bool bstore_last_dtpflag; + bool bstart_txctrl_bydtp; //Define to discriminate on High power State or on sitesuvey to change Tx gain index + //Add by amy for Rate Adaptive + rate_adaptive rate_adaptive; + //Add by amy for TX power tracking + //2008/05/15 Mars OPEN/CLOSE TX POWER TRACKING + txbbgain_struct txbbgain_table[TxBBGainTableLength]; + u8 txpower_count;//For 6 sec do tracking again + bool btxpower_trackingInit; + u8 OFDM_index; + u8 CCK_index; + //2007/09/10 Mars Add CCK TX Power Tracking + ccktxbbgain_struct cck_txbbgain_table[CCKTxBBGainTableLength]; + ccktxbbgain_struct cck_txbbgain_ch14_table[CCKTxBBGainTableLength]; + u8 rfa_txpowertrackingindex; + u8 rfa_txpowertrackingindex_real; + u8 rfa_txpowertracking_default; + u8 rfc_txpowertrackingindex; + u8 rfc_txpowertrackingindex_real; + + s8 cck_present_attentuation; + u8 cck_present_attentuation_20Mdefault; + u8 cck_present_attentuation_40Mdefault; + char cck_present_attentuation_difference; + bool btxpower_tracking; + bool bcck_in_ch14; + bool btxpowerdata_readfromEEPORM; + u16 TSSI_13dBm; + //For Backup Initial Gain + init_gain initgain_backup; + u8 DefaultInitialGain[4]; + // For EDCA Turbo mode, Added by amy 080515. + bool bis_any_nonbepkts; + bool bcurrent_turbo_EDCA; + bool bis_cur_rdlstate; + struct timer_list fsync_timer; + bool bfsync_processing; // 500ms Fsync timer is active or not + u32 rate_record; + u32 rateCountDiffRecord; + u32 ContiuneDiffCount; + bool bswitch_fsync; + + u8 framesync; + u32 framesyncC34; + u8 framesyncMonitor; + //Added by amy 080516 for RX related + u16 nrxAMPDU_size; + u8 nrxAMPDU_aggr_num; + + //by amy for gpio + bool bHwRadioOff; + + //by amy for reset_count + u32 reset_count; + bool bpbc_pressed; + //by amy for debug + u32 txpower_checkcnt; + u32 txpower_tracking_callback_cnt; + u8 thermal_read_val[40]; + u8 thermal_readback_index; + u32 ccktxpower_adjustcnt_not_ch14; + u32 ccktxpower_adjustcnt_ch14; + u8 tx_fwinfo_force_subcarriermode; + u8 tx_fwinfo_force_subcarrierval; + //by amy for silent reset + RESET_TYPE ResetProgress; + bool bForcedSilentReset; + bool bDisableNormalResetCheck; + u16 TxCounter; + u16 RxCounter; + int IrpPendingCount; + bool bResetInProgress; + bool force_reset; + u8 InitialGainOperateType; + + u16 SifsTime; + + //define work item by amy 080526 + + struct delayed_work update_beacon_wq; + struct delayed_work watch_dog_wq; + struct delayed_work txpower_tracking_wq; + struct delayed_work rfpath_check_wq; + struct delayed_work gpio_change_rf_wq; + struct delayed_work initialgain_operate_wq; + struct workqueue_struct *priv_wq; +}r8192_priv; + +// for rtl8187 +// now mirging to rtl8187B +/* +typedef enum{ + LOW_PRIORITY = 0x02, + NORM_PRIORITY + } priority_t; +*/ +//for rtl8187B +typedef enum{ + BULK_PRIORITY = 0x01, + //RSVD0, + //RSVD1, + LOW_PRIORITY, + NORM_PRIORITY, + VO_PRIORITY, + VI_PRIORITY, //0x05 + BE_PRIORITY, + BK_PRIORITY, + RSVD2, + RSVD3, + BEACON_PRIORITY, //0x0A + HIGH_PRIORITY, + MANAGE_PRIORITY, + RSVD4, + RSVD5, + UART_PRIORITY //0x0F +} priority_t; + +typedef enum{ + NIC_8192U = 1, + NIC_8190P = 2, + NIC_8192E = 3, + } nic_t; + + +#ifdef JOHN_HWSEC +struct ssid_thread { + struct net_device *dev; + u8 name[IW_ESSID_MAX_SIZE + 1]; +}; +#endif + +bool init_firmware(struct net_device *dev); +short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb); +short rtl8192_tx(struct net_device *dev, struct sk_buff* skb); + +u32 read_cam(struct net_device *dev, u8 addr); +void write_cam(struct net_device *dev, u8 addr, u32 data); + +u8 read_nic_byte(struct net_device *dev, int x); +u8 read_nic_byte_E(struct net_device *dev, int x); +u32 read_nic_dword(struct net_device *dev, int x); +u16 read_nic_word(struct net_device *dev, int x) ; +void write_nic_byte(struct net_device *dev, int x,u8 y); +void write_nic_byte_E(struct net_device *dev, int x,u8 y); +void write_nic_word(struct net_device *dev, int x,u16 y); +void write_nic_dword(struct net_device *dev, int x,u32 y); +void force_pci_posting(struct net_device *dev); + +void rtl8192_rtx_disable(struct net_device *); +void rtl8192_rx_enable(struct net_device *); +void rtl8192_tx_enable(struct net_device *); + +void rtl8192_disassociate(struct net_device *dev); +//void fix_rx_fifo(struct net_device *dev); +void rtl8185_set_rf_pins_enable(struct net_device *dev,u32 a); + +void rtl8192_set_anaparam(struct net_device *dev,u32 a); +void rtl8185_set_anaparam2(struct net_device *dev,u32 a); +void rtl8192_update_msr(struct net_device *dev); +int rtl8192_down(struct net_device *dev); +int rtl8192_up(struct net_device *dev); +void rtl8192_commit(struct net_device *dev); +void rtl8192_set_chan(struct net_device *dev,short ch); +void write_phy(struct net_device *dev, u8 adr, u8 data); +void write_phy_cck(struct net_device *dev, u8 adr, u32 data); +void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data); +void rtl8185_tx_antenna(struct net_device *dev, u8 ant); +void rtl8192_set_rxconf(struct net_device *dev); +//short check_nic_enough_desc(struct net_device *dev, priority_t priority); +extern void rtl819xusb_beacon_tx(struct net_device *dev,u16 tx_rate); + +void EnableHWSecurityConfig8192(struct net_device *dev); +void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, u8 *MacAddr, u8 DefaultKey, u32 *KeyContent ); + + +#endif diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c new file mode 100644 index 0000000000000000000000000000000000000000..adade13e1e19fc98fa3c85a0ba53ebc355868f15 --- /dev/null +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -0,0 +1,6085 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * Linux device driver for RTL8192U + * + * Based on the r8187 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * 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 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Jerry chuang + */ + +#ifndef CONFIG_FORCE_HARD_FLOAT +double __floatsidf (int i) { return i; } +unsigned int __fixunsdfsi (double d) { return d; } +double __adddf3(double a, double b) { return a+b; } +double __addsf3(float a, float b) { return a+b; } +double __subdf3(double a, double b) { return a-b; } +double __extendsfdf2(float a) {return a;} +#endif + +#undef LOOP_TEST +#undef DUMP_RX +#undef DUMP_TX +#undef DEBUG_TX_DESC2 +#undef RX_DONT_PASS_UL +#undef DEBUG_EPROM +#undef DEBUG_RX_VERBOSE +#undef DUMMY_RX +#undef DEBUG_ZERO_RX +#undef DEBUG_RX_SKB +#undef DEBUG_TX_FRAG +#undef DEBUG_RX_FRAG +#undef DEBUG_TX_FILLDESC +#undef DEBUG_TX +#undef DEBUG_IRQ +#undef DEBUG_RX +#undef DEBUG_RXALLOC +#undef DEBUG_REGISTERS +#undef DEBUG_RING +#undef DEBUG_IRQ_TASKLET +#undef DEBUG_TX_ALLOC +#undef DEBUG_TX_DESC + +#define CONFIG_RTL8192_IO_MAP + +#include +#include "r8192U_hw.h" +#include "r8192U.h" +#include "r8190_rtl8256.h" /* RTL8225 Radio frontend */ +#include "r8180_93cx6.h" /* Card EEPROM */ +#include "r8192U_wx.h" +#include "r819xU_phy.h" //added by WB 4.30.2008 +#include "r819xU_phyreg.h" +#include "r819xU_cmdpkt.h" +#include "r8192U_dm.h" +//#include "r8192xU_phyreg.h" +#include +// FIXME: check if 2.6.7 is ok + +#ifdef CONFIG_RTL8192_PM +#include "r8192_pm.h" +#endif + +#ifdef ENABLE_DOT11D +#include "dot11d.h" +#endif +//set here to open your trace code. //WB +u32 rt_global_debug_component = \ + // COMP_INIT | +// COMP_DBG | + // COMP_EPROM | +// COMP_PHY | + // COMP_RF | +// COMP_FIRMWARE | +// COMP_CH | + // COMP_POWER_TRACKING | +// COMP_RATE | + // COMP_TXAGC | + // COMP_TRACE | + COMP_DOWN | + // COMP_RECV | + // COMP_SWBW | + COMP_SEC | + // COMP_RESET | + // COMP_SEND | + // COMP_EVENTS | + COMP_ERR ; //always open err flags on + +#define TOTAL_CAM_ENTRY 32 +#define CAM_CONTENT_COUNT 8 + +static struct usb_device_id rtl8192_usb_id_tbl[] = { + /* Realtek */ + {USB_DEVICE(0x0bda, 0x8192)}, + {USB_DEVICE(0x0bda, 0x8709)}, + /* Corega */ + {USB_DEVICE(0x07aa, 0x0043)}, + /* Belkin */ + {USB_DEVICE(0x050d, 0x805E)}, + /* Sitecom */ + {USB_DEVICE(0x0df6, 0x0031)}, + /* EnGenius */ + {USB_DEVICE(0x1740, 0x9201)}, + /* Dlink */ + {USB_DEVICE(0x2001, 0x3301)}, + /* Zinwell */ + {USB_DEVICE(0x5a57, 0x0290)}, + {} +}; + +MODULE_LICENSE("GPL"); +MODULE_VERSION("V 1.1"); +MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl); +MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards"); + +static char* ifname = "wlan%d"; +static int hwwep = 1; //default use hw. set 0 to use software security +static int channels = 0x3fff; + + + +module_param(ifname, charp, S_IRUGO|S_IWUSR ); +//module_param(hwseqnum,int, S_IRUGO|S_IWUSR); +module_param(hwwep,int, S_IRUGO|S_IWUSR); +module_param(channels,int, S_IRUGO|S_IWUSR); + +MODULE_PARM_DESC(ifname," Net interface name, wlan%d=default"); +//MODULE_PARM_DESC(hwseqnum," Try to use hardware 802.11 header sequence numbers. Zero=default"); +MODULE_PARM_DESC(hwwep," Try to use hardware security support. "); +MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI"); + +static int __devinit rtl8192_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id); +static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf); + + +static struct usb_driver rtl8192_usb_driver = { + .name = RTL819xU_MODULE_NAME, /* Driver name */ + .id_table = rtl8192_usb_id_tbl, /* PCI_ID table */ + .probe = rtl8192_usb_probe, /* probe fn */ + .disconnect = rtl8192_usb_disconnect, /* remove fn */ +#ifdef CONFIG_RTL8192_PM + .suspend = rtl8192_suspend, /* PM suspend fn */ + .resume = rtl8192_resume, /* PM resume fn */ +#else + .suspend = NULL, /* PM suspend fn */ + .resume = NULL, /* PM resume fn */ +#endif +}; + +#ifdef ENABLE_DOT11D + +typedef struct _CHANNEL_LIST +{ + u8 Channel[32]; + u8 Len; +}CHANNEL_LIST, *PCHANNEL_LIST; + +static CHANNEL_LIST ChannelPlan[] = { + {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64,149,153,157,161,165},24}, //FCC + {{1,2,3,4,5,6,7,8,9,10,11},11}, //IC + {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, //ETSI + {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Spain. Change to ETSI. + {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //France. Change to ETSI. + {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, //MKK //MKK + {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},//MKK1 + {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Israel. + {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, // For 11a , TELEC + {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64}, 22}, //MIC + {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14} //For Global Domain. 1-11:active scan, 12-14 passive scan. //+YJ, 080626 +}; + +static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv* priv) +{ + int i, max_chan=-1, min_chan=-1; + struct ieee80211_device* ieee = priv->ieee80211; + switch (channel_plan) + { + case COUNTRY_CODE_FCC: + case COUNTRY_CODE_IC: + case COUNTRY_CODE_ETSI: + case COUNTRY_CODE_SPAIN: + case COUNTRY_CODE_FRANCE: + case COUNTRY_CODE_MKK: + case COUNTRY_CODE_MKK1: + case COUNTRY_CODE_ISRAEL: + case COUNTRY_CODE_TELEC: + case COUNTRY_CODE_MIC: + { + Dot11d_Init(ieee); + ieee->bGlobalDomain = false; + //acturally 8225 & 8256 rf chip only support B,G,24N mode + if ((priv->rf_chip == RF_8225) || (priv->rf_chip == RF_8256)) + { + min_chan = 1; + max_chan = 14; + } + else + { + RT_TRACE(COMP_ERR, "unknown rf chip, can't set channel map in function:%s()\n", __FUNCTION__); + } + if (ChannelPlan[channel_plan].Len != 0){ + // Clear old channel map + memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map)); + // Set new channel map + for (i=0;i max_chan) + break; + GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1; + } + } + break; + } + case COUNTRY_CODE_GLOBAL_DOMAIN: + { + GET_DOT11D_INFO(ieee)->bEnabled = 0;//this flag enabled to follow 11d country IE setting, otherwise, it shall follow global domain settings. + Dot11d_Reset(ieee); + ieee->bGlobalDomain = true; + break; + } + default: + break; + } + return; +} +#endif + +#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 ) + +#define rx_hal_is_cck_rate(_pdrvinfo)\ + (_pdrvinfo->RxRate == DESC90_RATE1M ||\ + _pdrvinfo->RxRate == DESC90_RATE2M ||\ + _pdrvinfo->RxRate == DESC90_RATE5_5M ||\ + _pdrvinfo->RxRate == DESC90_RATE11M) &&\ + !_pdrvinfo->RxHT\ + + +void CamResetAllEntry(struct net_device *dev) +{ + u32 ulcommand = 0; + //2004/02/11 In static WEP, OID_ADD_KEY or OID_ADD_WEP are set before STA associate to AP. + // However, ResetKey is called on OID_802_11_INFRASTRUCTURE_MODE and MlmeAssociateRequest + // In this condition, Cam can not be reset because upper layer will not set this static key again. + //if(Adapter->EncAlgorithm == WEP_Encryption) + // return; +//debug + //DbgPrint("========================================\n"); + //DbgPrint(" Call ResetAllEntry \n"); + //DbgPrint("========================================\n\n"); + ulcommand |= BIT31|BIT30; + write_nic_dword(dev, RWCAM, ulcommand); + +} + + +void write_cam(struct net_device *dev, u8 addr, u32 data) +{ + write_nic_dword(dev, WCAMI, data); + write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff) ); +} + +u32 read_cam(struct net_device *dev, u8 addr) +{ + write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff) ); + return read_nic_dword(dev, 0xa8); +} + +void write_nic_byte_E(struct net_device *dev, int indx, u8 data) +{ + int status; + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + struct usb_device *udev = priv->udev; + + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, + indx|0xfe00, 0, &data, 1, HZ / 2); + + if (status < 0) + { + printk("write_nic_byte_E TimeOut! status:%d\n", status); + } +} + +u8 read_nic_byte_E(struct net_device *dev, int indx) +{ + int status; + u8 data; + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + struct usb_device *udev = priv->udev; + + status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, + indx|0xfe00, 0, &data, 1, HZ / 2); + + if (status < 0) + { + printk("read_nic_byte_E TimeOut! status:%d\n", status); + } + + return data; +} +//as 92U has extend page from 4 to 16, so modify functions below. +void write_nic_byte(struct net_device *dev, int indx, u8 data) +{ + int status; + + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + struct usb_device *udev = priv->udev; + + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, + (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2); + + if (status < 0) + { + printk("write_nic_byte TimeOut! status:%d\n", status); + } + + +} + + +void write_nic_word(struct net_device *dev, int indx, u16 data) +{ + + int status; + + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + struct usb_device *udev = priv->udev; + + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, + (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 2, HZ / 2); + + if (status < 0) + { + printk("write_nic_word TimeOut! status:%d\n", status); + } + +} + + +void write_nic_dword(struct net_device *dev, int indx, u32 data) +{ + + int status; + + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + struct usb_device *udev = priv->udev; + + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, + (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 4, HZ / 2); + + + if (status < 0) + { + printk("write_nic_dword TimeOut! status:%d\n", status); + } + +} + + + +u8 read_nic_byte(struct net_device *dev, int indx) +{ + u8 data; + int status; + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + struct usb_device *udev = priv->udev; + + status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, + (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2); + + if (status < 0) + { + printk("read_nic_byte TimeOut! status:%d\n", status); + } + + return data; +} + + + +u16 read_nic_word(struct net_device *dev, int indx) +{ + u16 data; + int status; + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + struct usb_device *udev = priv->udev; + + status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, + (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 2, HZ / 2); + + if (status < 0) + { + printk("read_nic_word TimeOut! status:%d\n", status); + } + + + return data; +} + +u16 read_nic_word_E(struct net_device *dev, int indx) +{ + u16 data; + int status; + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + struct usb_device *udev = priv->udev; + + status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, + indx|0xfe00, 0, &data, 2, HZ / 2); + + if (status < 0) + { + printk("read_nic_word TimeOut! status:%d\n", status); + } + + + return data; +} + +u32 read_nic_dword(struct net_device *dev, int indx) +{ + u32 data; + int status; +// int result; + + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + struct usb_device *udev = priv->udev; + + status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, + (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 4, HZ / 2); +// if(0 != result) { +// printk(KERN_WARNING "read size of data = %d\, date = %d\n", result, data); +// } + + if (status < 0) + { + printk("read_nic_dword TimeOut! status:%d\n", status); + } + + + + return data; +} + + +//u8 read_phy_cck(struct net_device *dev, u8 adr); +//u8 read_phy_ofdm(struct net_device *dev, u8 adr); +/* this might still called in what was the PHY rtl8185/rtl8192 common code + * plans are to possibilty turn it again in one common code... + */ +inline void force_pci_posting(struct net_device *dev) +{ +} + + +static struct net_device_stats *rtl8192_stats(struct net_device *dev); +void rtl8192_commit(struct net_device *dev); +//void rtl8192_restart(struct net_device *dev); +void rtl8192_restart(struct work_struct *work); +//void rtl8192_rq_tx_ack(struct work_struct *work); + +void watch_dog_timer_callback(unsigned long data); + +/**************************************************************************** + -----------------------------PROCFS STUFF------------------------- +*****************************************************************************/ + +static struct proc_dir_entry *rtl8192_proc = NULL; + + + +static int proc_get_stats_ap(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee80211; + struct ieee80211_network *target; + + int len = 0; + + list_for_each_entry(target, &ieee->network_list, list) { + + len += snprintf(page + len, count - len, + "%s ", target->ssid); + + if(target->wpa_ie_len>0 || target->rsn_ie_len>0){ + len += snprintf(page + len, count - len, + "WPA\n"); + } + else{ + len += snprintf(page + len, count - len, + "non_WPA\n"); + } + + } + + *eof = 1; + return len; +} + +static int proc_get_registers(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; +// struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + + int len = 0; + int i,n; + + int max=0xff; + + /* This dump the current register page */ +len += snprintf(page + len, count - len, + "\n####################page 0##################\n "); + + for(n=0;n<=max;) + { + //printk( "\nD: %2x> ", n); + len += snprintf(page + len, count - len, + "\nD: %2x > ",n); + + for(i=0;i<16 && n<=max;i++,n++) + len += snprintf(page + len, count - len, + "%2x ",read_nic_byte(dev,0x000|n)); + + // printk("%2x ",read_nic_byte(dev,n)); + } +len += snprintf(page + len, count - len, + "\n####################page 1##################\n "); + for(n=0;n<=max;) + { + //printk( "\nD: %2x> ", n); + len += snprintf(page + len, count - len, + "\nD: %2x > ",n); + + for(i=0;i<16 && n<=max;i++,n++) + len += snprintf(page + len, count - len, + "%2x ",read_nic_byte(dev,0x100|n)); + + // printk("%2x ",read_nic_byte(dev,n)); + } +len += snprintf(page + len, count - len, + "\n####################page 3##################\n "); + for(n=0;n<=max;) + { + //printk( "\nD: %2x> ", n); + len += snprintf(page + len, count - len, + "\nD: %2x > ",n); + + for(i=0;i<16 && n<=max;i++,n++) + len += snprintf(page + len, count - len, + "%2x ",read_nic_byte(dev,0x300|n)); + + // printk("%2x ",read_nic_byte(dev,n)); + } + + + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; + +} + + + + + +static int proc_get_stats_tx(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + + int len = 0; + + len += snprintf(page + len, count - len, + "TX VI priority ok int: %lu\n" + "TX VI priority error int: %lu\n" + "TX VO priority ok int: %lu\n" + "TX VO priority error int: %lu\n" + "TX BE priority ok int: %lu\n" + "TX BE priority error int: %lu\n" + "TX BK priority ok int: %lu\n" + "TX BK priority error int: %lu\n" + "TX MANAGE priority ok int: %lu\n" + "TX MANAGE priority error int: %lu\n" + "TX BEACON priority ok int: %lu\n" + "TX BEACON priority error int: %lu\n" +// "TX high priority ok int: %lu\n" +// "TX high priority failed error int: %lu\n" + "TX queue resume: %lu\n" + "TX queue stopped?: %d\n" + "TX fifo overflow: %lu\n" +// "TX beacon: %lu\n" + "TX VI queue: %d\n" + "TX VO queue: %d\n" + "TX BE queue: %d\n" + "TX BK queue: %d\n" +// "TX HW queue: %d\n" + "TX VI dropped: %lu\n" + "TX VO dropped: %lu\n" + "TX BE dropped: %lu\n" + "TX BK dropped: %lu\n" + "TX total data packets %lu\n", +// "TX beacon aborted: %lu\n", + priv->stats.txviokint, + priv->stats.txvierr, + priv->stats.txvookint, + priv->stats.txvoerr, + priv->stats.txbeokint, + priv->stats.txbeerr, + priv->stats.txbkokint, + priv->stats.txbkerr, + priv->stats.txmanageokint, + priv->stats.txmanageerr, + priv->stats.txbeaconokint, + priv->stats.txbeaconerr, +// priv->stats.txhpokint, +// priv->stats.txhperr, + priv->stats.txresumed, + netif_queue_stopped(dev), + priv->stats.txoverflow, +// priv->stats.txbeacon, + atomic_read(&(priv->tx_pending[VI_PRIORITY])), + atomic_read(&(priv->tx_pending[VO_PRIORITY])), + atomic_read(&(priv->tx_pending[BE_PRIORITY])), + atomic_read(&(priv->tx_pending[BK_PRIORITY])), +// read_nic_byte(dev, TXFIFOCOUNT), + priv->stats.txvidrop, + priv->stats.txvodrop, + priv->stats.txbedrop, + priv->stats.txbkdrop, + priv->stats.txdatapkt +// priv->stats.txbeaconerr + ); + + *eof = 1; + return len; +} + + + +static int proc_get_stats_rx(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + + int len = 0; + + len += snprintf(page + len, count - len, + "RX packets: %lu\n" + "RX urb status error: %lu\n" + "RX invalid urb error: %lu\n", + priv->stats.rxoktotal, + priv->stats.rxstaterr, + priv->stats.rxurberr); + + *eof = 1; + return len; +} +void rtl8192_proc_module_init(void) +{ + RT_TRACE(COMP_INIT, "Initializing proc filesystem"); + rtl8192_proc=create_proc_entry(RTL819xU_MODULE_NAME, S_IFDIR, init_net.proc_net); +} + + +void rtl8192_proc_module_remove(void) +{ + remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net); +} + + +void rtl8192_proc_remove_one(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + + + if (priv->dir_dev) { + // remove_proc_entry("stats-hw", priv->dir_dev); + remove_proc_entry("stats-tx", priv->dir_dev); + remove_proc_entry("stats-rx", priv->dir_dev); + // remove_proc_entry("stats-ieee", priv->dir_dev); + remove_proc_entry("stats-ap", priv->dir_dev); + remove_proc_entry("registers", priv->dir_dev); + // remove_proc_entry("cck-registers",priv->dir_dev); + // remove_proc_entry("ofdm-registers",priv->dir_dev); + //remove_proc_entry(dev->name, rtl8192_proc); + remove_proc_entry("wlan0", rtl8192_proc); + priv->dir_dev = NULL; + } +} + + +void rtl8192_proc_init_one(struct net_device *dev) +{ + struct proc_dir_entry *e; + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + priv->dir_dev = create_proc_entry(dev->name, + S_IFDIR | S_IRUGO | S_IXUGO, + rtl8192_proc); + if (!priv->dir_dev) { + RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n", + dev->name); + return; + } + e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_stats_rx, dev); + + if (!e) { + RT_TRACE(COMP_ERR,"Unable to initialize " + "/proc/net/rtl8192/%s/stats-rx\n", + dev->name); + } + + + e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_stats_tx, dev); + + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/stats-tx\n", + dev->name); + } + + e = create_proc_read_entry("stats-ap", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_stats_ap, dev); + + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/stats-ap\n", + dev->name); + } + + e = create_proc_read_entry("registers", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers\n", + dev->name); + } +} +/**************************************************************************** + -----------------------------MISC STUFF------------------------- +*****************************************************************************/ + +/* this is only for debugging */ +void print_buffer(u32 *buffer, int len) +{ + int i; + u8 *buf =(u8*)buffer; + + printk("ASCII BUFFER DUMP (len: %x):\n",len); + + for(i=0;itx_pending[queue_index]); + + return (used < MAX_TX_URB); +} + +void tx_timeout(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + //rtl8192_commit(dev); + + schedule_work(&priv->reset_wq); + //DMESG("TXTIMEOUT"); +} + + +/* this is only for debug */ +void dump_eprom(struct net_device *dev) +{ + int i; + for(i=0; i<63; i++) + RT_TRACE(COMP_EPROM, "EEPROM addr %x : %x", i, eprom_read(dev,i)); +} + +/* this is only for debug */ +void rtl8192_dump_reg(struct net_device *dev) +{ + int i; + int n; + int max=0x1ff; + + RT_TRACE(COMP_PHY, "Dumping NIC register map"); + + for(n=0;n<=max;) + { + printk( "\nD: %2x> ", n); + for(i=0;i<16 && n<=max;i++,n++) + printk("%2x ",read_nic_byte(dev,n)); + } + printk("\n"); +} + +/**************************************************************************** + ------------------------------HW STUFF--------------------------- +*****************************************************************************/ + + +void rtl8192_set_mode(struct net_device *dev,int mode) +{ + u8 ecmd; + ecmd=read_nic_byte(dev, EPROM_CMD); + ecmd=ecmd &~ EPROM_CMD_OPERATING_MODE_MASK; + ecmd=ecmd | (mode<ieee80211->state == IEEE80211_LINKED){ + + if (priv->ieee80211->iw_mode == IW_MODE_INFRA) + msr |= (MSR_LINK_MANAGED<ieee80211->iw_mode == IW_MODE_ADHOC) + msr |= (MSR_LINK_ADHOC<ieee80211->iw_mode == IW_MODE_MASTER) + msr |= (MSR_LINK_MASTER<%s()====ch:%d\n", __FUNCTION__, ch); + priv->chan=ch; + + /* this hack should avoid frame TX during channel setting*/ + + +// tx = read_nic_dword(dev,TX_CONF); +// tx &= ~TX_LOOPBACK_MASK; + +#ifndef LOOP_TEST +// write_nic_dword(dev,TX_CONF, tx |( TX_LOOPBACK_MAC<rf_set_chan) + priv->rf_set_chan(dev,priv->chan); + mdelay(10); +// write_nic_dword(dev,TX_CONF,tx | (TX_LOOPBACK_NONE<bisrxaggrsubframe) + return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize + + pstats->RxBufShift + 8); + else +#endif + return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize + + pstats->RxBufShift); + +} +static int rtl8192_rx_initiate(struct net_device*dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + struct urb *entry; + struct sk_buff *skb; + struct rtl8192_rx_info *info; + + /* nomal packet rx procedure */ + while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB) { + skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL); + if (!skb) + break; + entry = usb_alloc_urb(0, GFP_KERNEL); + if (!entry) { + kfree_skb(skb); + break; + } +// printk("nomal packet IN request!\n"); + usb_fill_bulk_urb(entry, priv->udev, + usb_rcvbulkpipe(priv->udev, 3), skb_tail_pointer(skb), + RX_URB_SIZE, rtl8192_rx_isr, skb); + info = (struct rtl8192_rx_info *) skb->cb; + info->urb = entry; + info->dev = dev; + info->out_pipe = 3; //denote rx normal packet queue + skb_queue_tail(&priv->rx_queue, skb); + usb_submit_urb(entry, GFP_KERNEL); + } + + /* command packet rx procedure */ + while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB + 3) { +// printk("command packet IN request!\n"); + skb = __dev_alloc_skb(RX_URB_SIZE ,GFP_KERNEL); + if (!skb) + break; + entry = usb_alloc_urb(0, GFP_KERNEL); + if (!entry) { + kfree_skb(skb); + break; + } + usb_fill_bulk_urb(entry, priv->udev, + usb_rcvbulkpipe(priv->udev, 9), skb_tail_pointer(skb), + RX_URB_SIZE, rtl8192_rx_isr, skb); + info = (struct rtl8192_rx_info *) skb->cb; + info->urb = entry; + info->dev = dev; + info->out_pipe = 9; //denote rx cmd packet queue + skb_queue_tail(&priv->rx_queue, skb); + usb_submit_urb(entry, GFP_KERNEL); + } + + return 0; +} + +void rtl8192_set_rxconf(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + u32 rxconf; + + rxconf=read_nic_dword(dev,RCR); + rxconf = rxconf &~ MAC_FILTER_MASK; + rxconf = rxconf | RCR_AMF; + rxconf = rxconf | RCR_ADF; + rxconf = rxconf | RCR_AB; + rxconf = rxconf | RCR_AM; + //rxconf = rxconf | RCR_ACF; + + if (dev->flags & IFF_PROMISC) {DMESG ("NIC in promisc mode");} + + if(priv->ieee80211->iw_mode == IW_MODE_MONITOR || \ + dev->flags & IFF_PROMISC){ + rxconf = rxconf | RCR_AAP; + } /*else if(priv->ieee80211->iw_mode == IW_MODE_MASTER){ + rxconf = rxconf | (1<ieee80211->iw_mode == IW_MODE_MONITOR){ + rxconf = rxconf | RCR_AICV; + rxconf = rxconf | RCR_APWRMGT; + } + + if( priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR) + rxconf = rxconf | RCR_ACRC32; + + + rxconf = rxconf &~ RX_FIFO_THRESHOLD_MASK; + rxconf = rxconf | (RX_FIFO_THRESHOLD_NONE<rx_queue))) { + info = (struct rtl8192_rx_info *) skb->cb; + if (!info->urb) + continue; + + usb_kill_urb(info->urb); + kfree_skb(skb); + } + + if (skb_queue_len(&priv->skb_queue)) { + printk(KERN_WARNING "skb_queue not empty\n"); + } + + skb_queue_purge(&priv->skb_queue); + return; +} + + +int alloc_tx_beacon_desc_ring(struct net_device *dev, int count) +{ + return 0; +} + +inline u16 ieeerate2rtlrate(int rate) +{ + switch(rate){ + case 10: + return 0; + case 20: + return 1; + case 55: + return 2; + case 110: + return 3; + case 60: + return 4; + case 90: + return 5; + case 120: + return 6; + case 180: + return 7; + case 240: + return 8; + case 360: + return 9; + case 480: + return 10; + case 540: + return 11; + default: + return 3; + + } +} +static u16 rtl_rate[] = {10,20,55,110,60,90,120,180,240,360,480,540}; +inline u16 rtl8192_rate2rate(short rate) +{ + if (rate >11) return 0; + return rtl_rate[rate]; +} + + +/* The protype of rx_isr has changed since one verion of Linux Kernel */ +static void rtl8192_rx_isr(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *) urb->context; + struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb; + struct net_device *dev = info->dev; + struct r8192_priv *priv = ieee80211_priv(dev); + int out_pipe = info->out_pipe; + int err; + if(!priv->up) + return; + if (unlikely(urb->status)) { + info->urb = NULL; + priv->stats.rxstaterr++; + priv->ieee80211->stats.rx_errors++; + usb_free_urb(urb); + // printk("%s():rx status err\n",__FUNCTION__); + return; + } + skb_unlink(skb, &priv->rx_queue); + skb_put(skb, urb->actual_length); + + skb_queue_tail(&priv->skb_queue, skb); + tasklet_schedule(&priv->irq_rx_tasklet); + + skb = dev_alloc_skb(RX_URB_SIZE); + if (unlikely(!skb)) { + usb_free_urb(urb); + printk("%s():can,t alloc skb\n",__FUNCTION__); + /* TODO check rx queue length and refill *somewhere* */ + return; + } + + usb_fill_bulk_urb(urb, priv->udev, + usb_rcvbulkpipe(priv->udev, out_pipe), skb_tail_pointer(skb), + RX_URB_SIZE, rtl8192_rx_isr, skb); + + info = (struct rtl8192_rx_info *) skb->cb; + info->urb = urb; + info->dev = dev; + info->out_pipe = out_pipe; + + urb->transfer_buffer = skb_tail_pointer(skb); + urb->context = skb; + skb_queue_tail(&priv->rx_queue, skb); + err = usb_submit_urb(urb, GFP_ATOMIC); + if(err && err != EPERM) + printk("can not submit rxurb, err is %x,URB status is %x\n",err,urb->status); +} + +u32 +rtl819xusb_rx_command_packet( + struct net_device *dev, + struct ieee80211_rx_stats *pstats + ) +{ + u32 status; + + //RT_TRACE(COMP_RECV, DBG_TRACE, ("---> RxCommandPacketHandle819xUsb()\n")); + + status = cmpk_message_handle_rx(dev, pstats); + if (status) + { + DMESG("rxcommandpackethandle819xusb: It is a command packet\n"); + } + else + { + //RT_TRACE(COMP_RECV, DBG_TRACE, ("RxCommandPacketHandle819xUsb: It is not a command packet\n")); + } + + //RT_TRACE(COMP_RECV, DBG_TRACE, ("<--- RxCommandPacketHandle819xUsb()\n")); + return status; +} + + +void rtl8192_data_hard_stop(struct net_device *dev) +{ + //FIXME !! +} + + +void rtl8192_data_hard_resume(struct net_device *dev) +{ + // FIXME !! +} + +/* this function TX data frames when the ieee80211 stack requires this. + * It checks also if we need to stop the ieee tx queue, eventually do it + */ +void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate) +{ + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + int ret; + unsigned long flags; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + u8 queue_index = tcb_desc->queue_index; + + /* shall not be referred by command packet */ + assert(queue_index != TXCMD_QUEUE); + + spin_lock_irqsave(&priv->tx_lock,flags); + + memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); +// tcb_desc->RATRIndex = 7; +// tcb_desc->bTxDisableRateFallBack = 1; +// tcb_desc->bTxUseDriverAssingedRate = 1; + tcb_desc->bTxEnableFwCalcDur = 1; + skb_push(skb, priv->ieee80211->tx_headroom); + ret = rtl8192_tx(dev, skb); + + //priv->ieee80211->stats.tx_bytes+=(skb->len - priv->ieee80211->tx_headroom); + //priv->ieee80211->stats.tx_packets++; + + spin_unlock_irqrestore(&priv->tx_lock,flags); + +// return ret; + return; +} + +/* This is a rough attempt to TX a frame + * This is called by the ieee 80211 stack to TX management frames. + * If the ring is full packet are dropped (for data frame the queue + * is stopped before this can happen). + */ +int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + int ret; + unsigned long flags; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + u8 queue_index = tcb_desc->queue_index; + + + spin_lock_irqsave(&priv->tx_lock,flags); + + memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); + if(queue_index == TXCMD_QUEUE) { + skb_push(skb, USB_HWDESC_HEADER_LEN); + rtl819xU_tx_cmd(dev, skb); + ret = 1; + spin_unlock_irqrestore(&priv->tx_lock,flags); + return ret; + } else { + skb_push(skb, priv->ieee80211->tx_headroom); + ret = rtl8192_tx(dev, skb); + } + + spin_unlock_irqrestore(&priv->tx_lock,flags); + + return ret; +} + + +void rtl8192_try_wake_queue(struct net_device *dev, int pri); + +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE +u16 DrvAggr_PaddingAdd(struct net_device *dev, struct sk_buff *skb) +{ + u16 PaddingNum = 256 - ((skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES) % 256); + return (PaddingNum&0xff); +} + +u8 MRateToHwRate8190Pci(u8 rate); +u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc); +u8 MapHwQueueToFirmwareQueue(u8 QueueID); +struct sk_buff *DrvAggr_Aggregation(struct net_device *dev, struct ieee80211_drv_agg_txb *pSendList) +{ + struct ieee80211_device *ieee = netdev_priv(dev); + struct r8192_priv *priv = ieee80211_priv(dev); + cb_desc *tcb_desc = NULL; + u8 i; + u32 TotalLength; + struct sk_buff *skb; + struct sk_buff *agg_skb; + tx_desc_819x_usb_aggr_subframe *tx_agg_desc = NULL; + tx_fwinfo_819x_usb *tx_fwinfo = NULL; + + // + // Local variable initialization. + // + /* first skb initialization */ + skb = pSendList->tx_agg_frames[0]; + TotalLength = skb->len; + + /* Get the total aggregation length including the padding space and + * sub frame header. + */ + for(i = 1; i < pSendList->nr_drv_agg_frames; i++) { + TotalLength += DrvAggr_PaddingAdd(dev, skb); + skb = pSendList->tx_agg_frames[i]; + TotalLength += (skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES); + } + + /* allocate skb to contain the aggregated packets */ + agg_skb = dev_alloc_skb(TotalLength + ieee->tx_headroom); + memset(agg_skb->data, 0, agg_skb->len); + skb_reserve(agg_skb, ieee->tx_headroom); + +// RT_DEBUG_DATA(COMP_SEND, skb->cb, sizeof(skb->cb)); + /* reserve info for first subframe Tx descriptor to be set in the tx function */ + skb = pSendList->tx_agg_frames[0]; + tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + tcb_desc->drv_agg_enable = 1; + tcb_desc->pkt_size = skb->len; + tcb_desc->DrvAggrNum = pSendList->nr_drv_agg_frames; + printk("DrvAggNum = %d\n", tcb_desc->DrvAggrNum); +// RT_DEBUG_DATA(COMP_SEND, skb->cb, sizeof(skb->cb)); +// printk("========>skb->data ======> \n"); +// RT_DEBUG_DATA(COMP_SEND, skb->data, skb->len); + memcpy(agg_skb->cb, skb->cb, sizeof(skb->cb)); + memcpy(skb_put(agg_skb,skb->len),skb->data,skb->len); + + for(i = 1; i < pSendList->nr_drv_agg_frames; i++) { + /* push the next sub frame to be 256 byte aline */ + skb_put(agg_skb,DrvAggr_PaddingAdd(dev,skb)); + + /* Subframe drv Tx descriptor and firmware info setting */ + skb = pSendList->tx_agg_frames[i]; + tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + tx_agg_desc = (tx_desc_819x_usb_aggr_subframe *)agg_skb->tail; + tx_fwinfo = (tx_fwinfo_819x_usb *)(agg_skb->tail + sizeof(tx_desc_819x_usb_aggr_subframe)); + + memset(tx_fwinfo,0,sizeof(tx_fwinfo_819x_usb)); + /* DWORD 0 */ + tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80)?1:0; + tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate); + tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur; + tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc); + if(tcb_desc->bAMPDUEnable) {//AMPDU enabled + tx_fwinfo->AllowAggregation = 1; + /* DWORD 1 */ + tx_fwinfo->RxMF = tcb_desc->ampdu_factor; + tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity + } else { + tx_fwinfo->AllowAggregation = 0; + /* DWORD 1 */ + tx_fwinfo->RxMF = 0; + tx_fwinfo->RxAMD = 0; + } + + /* Protection mode related */ + tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable)?1:0; + tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable)?1:0; + tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC)?1:0; + tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80)?1:0; + tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate); + tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT==0)?(tcb_desc->RTSSC):0; + tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT==1)?((tcb_desc->bRTSBW)?1:0):0; + tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT==0)?(tcb_desc->bRTSUseShortPreamble?1:0):\ + (tcb_desc->bRTSUseShortGI?1:0); + + /* Set Bandwidth and sub-channel settings. */ + if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) + { + if(tcb_desc->bPacketBW) { + tx_fwinfo->TxBandwidth = 1; + tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode + } else { + tx_fwinfo->TxBandwidth = 0; + tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC; + } + } else { + tx_fwinfo->TxBandwidth = 0; + tx_fwinfo->TxSubCarrier = 0; + } + + /* Fill Tx descriptor */ + memset(tx_agg_desc, 0, sizeof(tx_desc_819x_usb_aggr_subframe)); + /* DWORD 0 */ + //tx_agg_desc->LINIP = 0; + //tx_agg_desc->CmdInit = 1; + tx_agg_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8; + /* already raw data, need not to substract header length */ + tx_agg_desc->PktSize = skb->len & 0xffff; + + /*DWORD 1*/ + tx_agg_desc->SecCAMID= 0; + tx_agg_desc->RATid = tcb_desc->RATRIndex; + { + //MPDUOverhead = 0; + tx_agg_desc->NoEnc = 1; + } + tx_agg_desc->SecType = 0x0; + + if (tcb_desc->bHwSec) { + switch (priv->ieee80211->pairwise_key_type) + { + case KEY_TYPE_WEP40: + case KEY_TYPE_WEP104: + tx_agg_desc->SecType = 0x1; + tx_agg_desc->NoEnc = 0; + break; + case KEY_TYPE_TKIP: + tx_agg_desc->SecType = 0x2; + tx_agg_desc->NoEnc = 0; + break; + case KEY_TYPE_CCMP: + tx_agg_desc->SecType = 0x3; + tx_agg_desc->NoEnc = 0; + break; + case KEY_TYPE_NA: + tx_agg_desc->SecType = 0x0; + tx_agg_desc->NoEnc = 1; + break; + } + } + + tx_agg_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index); + tx_agg_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb); + + tx_agg_desc->DISFB = tcb_desc->bTxDisableRateFallBack; + tx_agg_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate; + + tx_agg_desc->OWN = 1; + + //DWORD 2 + /* According windows driver, it seems that there no need to fill this field */ + //tx_agg_desc->TxBufferSize= (u32)(skb->len - USB_HWDESC_HEADER_LEN); + + /* to fill next packet */ + skb_put(agg_skb,TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES); + memcpy(skb_put(agg_skb,skb->len),skb->data,skb->len); + } + + for(i = 0; i < pSendList->nr_drv_agg_frames; i++) { + dev_kfree_skb_any(pSendList->tx_agg_frames[i]); + } + + return agg_skb; +} + +/* NOTE: + This function return a list of PTCB which is proper to be aggregate with the input TCB. + If no proper TCB is found to do aggregation, SendList will only contain the input TCB. +*/ +u8 DrvAggr_GetAggregatibleList(struct net_device *dev, struct sk_buff *skb, + struct ieee80211_drv_agg_txb *pSendList) +{ + struct ieee80211_device *ieee = netdev_priv(dev); + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + u16 nMaxAggrNum = pHTInfo->UsbTxAggrNum; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + u8 QueueID = tcb_desc->queue_index; + + do { + pSendList->tx_agg_frames[pSendList->nr_drv_agg_frames++] = skb; + if(pSendList->nr_drv_agg_frames >= nMaxAggrNum) { + break; + } + + } while((skb = skb_dequeue(&ieee->skb_drv_aggQ[QueueID]))); + + RT_TRACE(COMP_AMSDU, "DrvAggr_GetAggregatibleList, nAggrTcbNum = %d \n", pSendList->nr_drv_agg_frames); + return pSendList->nr_drv_agg_frames; +} +#endif + +static void rtl8192_tx_isr(struct urb *tx_urb) +{ + struct sk_buff *skb = (struct sk_buff*)tx_urb->context; + struct net_device *dev = NULL; + struct r8192_priv *priv = NULL; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + u8 queue_index = tcb_desc->queue_index; +// bool bToSend0Byte; +// u16 BufLen = skb->len; + + memcpy(&dev,(struct net_device*)(skb->cb),sizeof(struct net_device*)); + priv = ieee80211_priv(dev); + + if(tcb_desc->queue_index != TXCMD_QUEUE) { + if(tx_urb->status == 0) { + dev->trans_start = jiffies; + // As act as station mode, destion shall be unicast address. + //priv->ieee80211->stats.tx_bytes+=(skb->len - priv->ieee80211->tx_headroom); + //priv->ieee80211->stats.tx_packets++; + priv->stats.txoktotal++; + priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++; + priv->stats.txbytesunicast += (skb->len - priv->ieee80211->tx_headroom); + } else { + priv->ieee80211->stats.tx_errors++; + //priv->stats.txmanageerr++; + /* TODO */ + } + } + + /* free skb and tx_urb */ + if(skb != NULL) { + dev_kfree_skb_any(skb); + usb_free_urb(tx_urb); + atomic_dec(&priv->tx_pending[queue_index]); + } + + { + // + // Handle HW Beacon: + // We had transfer our beacon frame to host controler at this moment. + // + // + // Caution: + // Handling the wait queue of command packets. + // For Tx command packets, we must not do TCB fragment because it is not handled right now. + // We must cut the packets to match the size of TX_CMD_PKT before we send it. + // + + /* Handle MPDU in wait queue. */ + if(queue_index != BEACON_QUEUE) { + /* Don't send data frame during scanning.*/ + if((skb_queue_len(&priv->ieee80211->skb_waitQ[queue_index]) != 0)&&\ + (!(priv->ieee80211->queue_stop))) { + if(NULL != (skb = skb_dequeue(&(priv->ieee80211->skb_waitQ[queue_index])))) + priv->ieee80211->softmac_hard_start_xmit(skb, dev); + + return; //modified by david to avoid further processing AMSDU + } +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + else if ((skb_queue_len(&priv->ieee80211->skb_drv_aggQ[queue_index])!= 0)&&\ + (!(priv->ieee80211->queue_stop))) { + // Tx Driver Aggregation process + /* The driver will aggregation the packets according to the following stets + * 1. check whether there's tx irq available, for it's a completion return + * function, it should contain enough tx irq; + * 2. check pakcet type; + * 3. intialize sendlist, check whether the to-be send packet no greater than 1 + * 4. aggregation the packets, and fill firmware info and tx desc to it, etc. + * 5. check whehter the packet could be sent, otherwise just insert to wait head + * */ + skb = skb_dequeue(&priv->ieee80211->skb_drv_aggQ[queue_index]); + if(!check_nic_enough_desc(dev, queue_index)) { + skb_queue_head(&(priv->ieee80211->skb_drv_aggQ[queue_index]), skb); + return; + } + + { + /*TODO*/ + /* + u8* pHeader = skb->data; + + if(IsMgntQosData(pHeader) || + IsMgntQData_Ack(pHeader) || + IsMgntQData_Poll(pHeader) || + IsMgntQData_Poll_Ack(pHeader) + ) + */ + { + struct ieee80211_drv_agg_txb SendList; + + memset(&SendList, 0, sizeof(struct ieee80211_drv_agg_txb)); + if(DrvAggr_GetAggregatibleList(dev, skb, &SendList) > 1) { + skb = DrvAggr_Aggregation(dev, &SendList); + + } + } + priv->ieee80211->softmac_hard_start_xmit(skb, dev); + } + } +#endif + } + } + +} + +void rtl8192_beacon_stop(struct net_device *dev) +{ + u8 msr, msrm, msr2; + struct r8192_priv *priv = ieee80211_priv(dev); + + msr = read_nic_byte(dev, MSR); + msrm = msr & MSR_LINK_MASK; + msr2 = msr & ~MSR_LINK_MASK; + + if(NIC_8192U == priv->card_8192) { + usb_kill_urb(priv->rx_urb[MAX_RX_URB]); + } + if ((msrm == (MSR_LINK_ADHOC<ieee80211->current_network; + + for (i=0; irates_len; i++) + { + basic_rate = net->rates[i]&0x7f; + switch(basic_rate) + { + case MGN_1M: *rate_config |= RRSR_1M; break; + case MGN_2M: *rate_config |= RRSR_2M; break; + case MGN_5_5M: *rate_config |= RRSR_5_5M; break; + case MGN_11M: *rate_config |= RRSR_11M; break; + case MGN_6M: *rate_config |= RRSR_6M; break; + case MGN_9M: *rate_config |= RRSR_9M; break; + case MGN_12M: *rate_config |= RRSR_12M; break; + case MGN_18M: *rate_config |= RRSR_18M; break; + case MGN_24M: *rate_config |= RRSR_24M; break; + case MGN_36M: *rate_config |= RRSR_36M; break; + case MGN_48M: *rate_config |= RRSR_48M; break; + case MGN_54M: *rate_config |= RRSR_54M; break; + } + } + for (i=0; irates_ex_len; i++) + { + basic_rate = net->rates_ex[i]&0x7f; + switch(basic_rate) + { + case MGN_1M: *rate_config |= RRSR_1M; break; + case MGN_2M: *rate_config |= RRSR_2M; break; + case MGN_5_5M: *rate_config |= RRSR_5_5M; break; + case MGN_11M: *rate_config |= RRSR_11M; break; + case MGN_6M: *rate_config |= RRSR_6M; break; + case MGN_9M: *rate_config |= RRSR_9M; break; + case MGN_12M: *rate_config |= RRSR_12M; break; + case MGN_18M: *rate_config |= RRSR_18M; break; + case MGN_24M: *rate_config |= RRSR_24M; break; + case MGN_36M: *rate_config |= RRSR_36M; break; + case MGN_48M: *rate_config |= RRSR_48M; break; + case MGN_54M: *rate_config |= RRSR_54M; break; + } + } +} + + +#define SHORT_SLOT_TIME 9 +#define NON_SHORT_SLOT_TIME 20 + +void rtl8192_update_cap(struct net_device* dev, u16 cap) +{ + u32 tmp = 0; + struct r8192_priv *priv = ieee80211_priv(dev); + struct ieee80211_network *net = &priv->ieee80211->current_network; + priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE; + tmp = priv->basic_rate; + if (priv->short_preamble) + tmp |= BRSR_AckShortPmb; + write_nic_dword(dev, RRSR, tmp); + + if (net->mode & (IEEE_G|IEEE_N_24G)) + { + u8 slot_time = 0; + if ((cap & WLAN_CAPABILITY_SHORT_SLOT)&&(!priv->ieee80211->pHTInfo->bCurrentRT2RTLongSlotTime)) + {//short slot time + slot_time = SHORT_SLOT_TIME; + } + else //long slot time + slot_time = NON_SHORT_SLOT_TIME; + priv->slot_time = slot_time; + write_nic_byte(dev, SLOT_TIME, slot_time); + } + +} +void rtl8192_net_update(struct net_device *dev) +{ + + struct r8192_priv *priv = ieee80211_priv(dev); + struct ieee80211_network *net; + u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf; + u16 rate_config = 0; + net = & priv->ieee80211->current_network; + + rtl8192_config_rate(dev, &rate_config); + priv->basic_rate = rate_config &= 0x15f; + + write_nic_dword(dev,BSSIDR,((u32*)net->bssid)[0]); + write_nic_word(dev,BSSIDR+4,((u16*)net->bssid)[2]); + //for(i=0;ibssid[i]); + + rtl8192_update_msr(dev); +// rtl8192_update_cap(dev, net->capability); + if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) + { + write_nic_word(dev, ATIMWND, 2); + write_nic_word(dev, BCN_DMATIME, 1023); + write_nic_word(dev, BCN_INTERVAL, net->beacon_interval); +// write_nic_word(dev, BcnIntTime, 100); + write_nic_word(dev, BCN_DRV_EARLY_INT, 1); + write_nic_byte(dev, BCN_ERR_THRESH, 100); + BcnTimeCfg |= (BcnCW<= 9) + { + RT_TRACE(COMP_ERR,"%s():Unknown queue ID!!!\n",__FUNCTION__); + return 0x04; + } + return priv->txqueue_to_outpipemap[tx_queue]; +} + +short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + //u8 *tx; + int status; + struct urb *tx_urb; + //int urb_buf_len; + unsigned int idx_pipe; + tx_desc_cmd_819x_usb *pdesc = (tx_desc_cmd_819x_usb *)skb->data; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + u8 queue_index = tcb_desc->queue_index; + + //printk("\n %s::queue_index = %d\n",__FUNCTION__, queue_index); + atomic_inc(&priv->tx_pending[queue_index]); + tx_urb = usb_alloc_urb(0,GFP_ATOMIC); + if(!tx_urb){ + dev_kfree_skb(skb); + return -ENOMEM; + } + + memset(pdesc, 0, USB_HWDESC_HEADER_LEN); + /* Tx descriptor ought to be set according to the skb->cb */ + pdesc->FirstSeg = 1;//bFirstSeg; + pdesc->LastSeg = 1;//bLastSeg; + pdesc->CmdInit = tcb_desc->bCmdOrInit; + pdesc->TxBufferSize = tcb_desc->txbuf_size; + pdesc->OWN = 1; + pdesc->LINIP = tcb_desc->bLastIniPkt; + + //---------------------------------------------------------------------------- + // Fill up USB_OUT_CONTEXT. + //---------------------------------------------------------------------------- + // Get index to out pipe from specified QueueID. +#ifndef USE_ONE_PIPE + idx_pipe = txqueue2outpipe(priv,queue_index); +#else + idx_pipe = 0x04; +#endif +#ifdef JOHN_DUMP_TXDESC + int i; + printk("--rate %x---",rate); + for (i = 0; i < 8; i++) + printk("%8x ", tx[i]); + printk("\n"); +#endif + usb_fill_bulk_urb(tx_urb,priv->udev, usb_sndbulkpipe(priv->udev,idx_pipe), \ + skb->data, skb->len, rtl8192_tx_isr, skb); + + status = usb_submit_urb(tx_urb, GFP_ATOMIC); + + if (!status){ + return 0; + }else{ + DMESGE("Error TX CMD URB, error %d", + status); + return -1; + } +} + +/* + * Mapping Software/Hardware descriptor queue id to "Queue Select Field" + * in TxFwInfo data structure + * 2006.10.30 by Emily + * + * \param QUEUEID Software Queue +*/ +u8 MapHwQueueToFirmwareQueue(u8 QueueID) +{ + u8 QueueSelect = 0x0; //defualt set to + + switch(QueueID) { + case BE_QUEUE: + QueueSelect = QSLT_BE; //or QSelect = pTcb->priority; + break; + + case BK_QUEUE: + QueueSelect = QSLT_BK; //or QSelect = pTcb->priority; + break; + + case VO_QUEUE: + QueueSelect = QSLT_VO; //or QSelect = pTcb->priority; + break; + + case VI_QUEUE: + QueueSelect = QSLT_VI; //or QSelect = pTcb->priority; + break; + case MGNT_QUEUE: + QueueSelect = QSLT_MGNT; + break; + + case BEACON_QUEUE: + QueueSelect = QSLT_BEACON; + break; + + // TODO: 2006.10.30 mark other queue selection until we verify it is OK + // TODO: Remove Assertions +//#if (RTL819X_FPGA_VER & RTL819X_FPGA_GUANGAN_070502) + case TXCMD_QUEUE: + QueueSelect = QSLT_CMD; + break; +//#endif + case HIGH_QUEUE: + QueueSelect = QSLT_HIGH; + break; + + default: + RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID); + break; + } + return QueueSelect; +} + +u8 MRateToHwRate8190Pci(u8 rate) +{ + u8 ret = DESC90_RATE1M; + + switch(rate) { + case MGN_1M: ret = DESC90_RATE1M; break; + case MGN_2M: ret = DESC90_RATE2M; break; + case MGN_5_5M: ret = DESC90_RATE5_5M; break; + case MGN_11M: ret = DESC90_RATE11M; break; + case MGN_6M: ret = DESC90_RATE6M; break; + case MGN_9M: ret = DESC90_RATE9M; break; + case MGN_12M: ret = DESC90_RATE12M; break; + case MGN_18M: ret = DESC90_RATE18M; break; + case MGN_24M: ret = DESC90_RATE24M; break; + case MGN_36M: ret = DESC90_RATE36M; break; + case MGN_48M: ret = DESC90_RATE48M; break; + case MGN_54M: ret = DESC90_RATE54M; break; + + // HT rate since here + case MGN_MCS0: ret = DESC90_RATEMCS0; break; + case MGN_MCS1: ret = DESC90_RATEMCS1; break; + case MGN_MCS2: ret = DESC90_RATEMCS2; break; + case MGN_MCS3: ret = DESC90_RATEMCS3; break; + case MGN_MCS4: ret = DESC90_RATEMCS4; break; + case MGN_MCS5: ret = DESC90_RATEMCS5; break; + case MGN_MCS6: ret = DESC90_RATEMCS6; break; + case MGN_MCS7: ret = DESC90_RATEMCS7; break; + case MGN_MCS8: ret = DESC90_RATEMCS8; break; + case MGN_MCS9: ret = DESC90_RATEMCS9; break; + case MGN_MCS10: ret = DESC90_RATEMCS10; break; + case MGN_MCS11: ret = DESC90_RATEMCS11; break; + case MGN_MCS12: ret = DESC90_RATEMCS12; break; + case MGN_MCS13: ret = DESC90_RATEMCS13; break; + case MGN_MCS14: ret = DESC90_RATEMCS14; break; + case MGN_MCS15: ret = DESC90_RATEMCS15; break; + case (0x80|0x20): ret = DESC90_RATEMCS32; break; + + default: break; + } + return ret; +} + + +u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc) +{ + u8 tmp_Short; + + tmp_Short = (TxHT==1)?((tcb_desc->bUseShortGI)?1:0):((tcb_desc->bUseShortPreamble)?1:0); + + if(TxHT==1 && TxRate != DESC90_RATEMCS15) + tmp_Short = 0; + + return tmp_Short; +} + +static void tx_zero_isr(struct urb *tx_urb) +{ + return; +} + +/* + * The tx procedure is just as following, + * skb->cb will contain all the following information, + * priority, morefrag, rate, &dev. + * */ +short rtl8192_tx(struct net_device *dev, struct sk_buff* skb) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + tx_desc_819x_usb *tx_desc = (tx_desc_819x_usb *)skb->data; + tx_fwinfo_819x_usb *tx_fwinfo = (tx_fwinfo_819x_usb *)(skb->data + USB_HWDESC_HEADER_LEN); + struct usb_device *udev = priv->udev; + int pend; + int status; + struct urb *tx_urb = NULL, *tx_urb_zero = NULL; + //int urb_len; + unsigned int idx_pipe; +// RT_DEBUG_DATA(COMP_SEND, tcb_desc, sizeof(cb_desc)); +// printk("=============> %s\n", __FUNCTION__); + pend = atomic_read(&priv->tx_pending[tcb_desc->queue_index]); + /* we are locked here so the two atomic_read and inc are executed + * without interleaves + * !!! For debug purpose + */ + if( pend > MAX_TX_URB){ + printk("To discard skb packet!\n"); + dev_kfree_skb_any(skb); + return -1; + } + + tx_urb = usb_alloc_urb(0,GFP_ATOMIC); + if(!tx_urb){ + dev_kfree_skb_any(skb); + return -ENOMEM; + } + + /* Fill Tx firmware info */ + memset(tx_fwinfo,0,sizeof(tx_fwinfo_819x_usb)); + /* DWORD 0 */ + tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80)?1:0; + tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate); + tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur; + tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc); + if(tcb_desc->bAMPDUEnable) {//AMPDU enabled + tx_fwinfo->AllowAggregation = 1; + /* DWORD 1 */ + tx_fwinfo->RxMF = tcb_desc->ampdu_factor; + tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity + } else { + tx_fwinfo->AllowAggregation = 0; + /* DWORD 1 */ + tx_fwinfo->RxMF = 0; + tx_fwinfo->RxAMD = 0; + } + + /* Protection mode related */ + tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable)?1:0; + tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable)?1:0; + tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC)?1:0; + tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80)?1:0; + tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate); + tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT==0)?(tcb_desc->RTSSC):0; + tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT==1)?((tcb_desc->bRTSBW)?1:0):0; + tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT==0)?(tcb_desc->bRTSUseShortPreamble?1:0):\ + (tcb_desc->bRTSUseShortGI?1:0); + + /* Set Bandwidth and sub-channel settings. */ + if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) + { + if(tcb_desc->bPacketBW) { + tx_fwinfo->TxBandwidth = 1; + tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode + } else { + tx_fwinfo->TxBandwidth = 0; + tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC; + } + } else { + tx_fwinfo->TxBandwidth = 0; + tx_fwinfo->TxSubCarrier = 0; + } + +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + if (tcb_desc->drv_agg_enable) + { + tx_fwinfo->Tx_INFO_RSVD = (tcb_desc->DrvAggrNum & 0x1f) << 1; + } +#endif + /* Fill Tx descriptor */ + memset(tx_desc, 0, sizeof(tx_desc_819x_usb)); + /* DWORD 0 */ + tx_desc->LINIP = 0; + tx_desc->CmdInit = 1; + tx_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8; + +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + if (tcb_desc->drv_agg_enable) { + tx_desc->PktSize = tcb_desc->pkt_size; + } else +#endif + { + tx_desc->PktSize = (skb->len - TX_PACKET_SHIFT_BYTES) & 0xffff; + } + + /*DWORD 1*/ + tx_desc->SecCAMID= 0; + tx_desc->RATid = tcb_desc->RATRIndex; + { + //MPDUOverhead = 0; + tx_desc->NoEnc = 1; + } + tx_desc->SecType = 0x0; + if (tcb_desc->bHwSec) + { + switch (priv->ieee80211->pairwise_key_type) + { + case KEY_TYPE_WEP40: + case KEY_TYPE_WEP104: + tx_desc->SecType = 0x1; + tx_desc->NoEnc = 0; + break; + case KEY_TYPE_TKIP: + tx_desc->SecType = 0x2; + tx_desc->NoEnc = 0; + break; + case KEY_TYPE_CCMP: + tx_desc->SecType = 0x3; + tx_desc->NoEnc = 0; + break; + case KEY_TYPE_NA: + tx_desc->SecType = 0x0; + tx_desc->NoEnc = 1; + break; + } + } + + tx_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index); + tx_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb); + + tx_desc->DISFB = tcb_desc->bTxDisableRateFallBack; + tx_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate; + + /* Fill fields that are required to be initialized in all of the descriptors */ + //DWORD 0 + tx_desc->FirstSeg = 1; + tx_desc->LastSeg = 1; + tx_desc->OWN = 1; + +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + if (tcb_desc->drv_agg_enable) { + tx_desc->TxBufferSize = tcb_desc->pkt_size + sizeof(tx_fwinfo_819x_usb); + } else +#endif + { + //DWORD 2 + tx_desc->TxBufferSize = (u32)(skb->len - USB_HWDESC_HEADER_LEN); + } + /* Get index to out pipe from specified QueueID */ +#ifndef USE_ONE_PIPE + idx_pipe = txqueue2outpipe(priv,tcb_desc->queue_index); +#else + idx_pipe = 0x5; +#endif + + //RT_DEBUG_DATA(COMP_SEND,tx_fwinfo,sizeof(tx_fwinfo_819x_usb)); + //RT_DEBUG_DATA(COMP_SEND,tx_desc,sizeof(tx_desc_819x_usb)); + + /* To submit bulk urb */ + usb_fill_bulk_urb(tx_urb,udev, + usb_sndbulkpipe(udev,idx_pipe), skb->data, + skb->len, rtl8192_tx_isr, skb); + + status = usb_submit_urb(tx_urb, GFP_ATOMIC); + if (!status){ +//we need to send 0 byte packet whenever 512N bytes/64N(HIGN SPEED/NORMAL SPEED) bytes packet has been transmitted. Otherwise, it will be halt to wait for another packet. WB. 2008.08.27 + bool bSend0Byte = false; + u8 zero = 0; + if(udev->speed == USB_SPEED_HIGH) + { + if (skb->len > 0 && skb->len % 512 == 0) + bSend0Byte = true; + } + else + { + if (skb->len > 0 && skb->len % 64 == 0) + bSend0Byte = true; + } + if (bSend0Byte) + { + tx_urb_zero = usb_alloc_urb(0,GFP_ATOMIC); + if(!tx_urb_zero){ + RT_TRACE(COMP_ERR, "can't alloc urb for zero byte\n"); + return -ENOMEM; + } + usb_fill_bulk_urb(tx_urb_zero,udev, + usb_sndbulkpipe(udev,idx_pipe), &zero, + 0, tx_zero_isr, dev); + status = usb_submit_urb(tx_urb_zero, GFP_ATOMIC); + if (status){ + RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status); + return -1; + } + } + dev->trans_start = jiffies; + atomic_inc(&priv->tx_pending[tcb_desc->queue_index]); + return 0; + }else{ + RT_TRACE(COMP_ERR, "Error TX URB %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), + status); + return -1; + } +} + +short rtl8192_usb_initendpoints(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + priv->rx_urb = (struct urb**) kmalloc (sizeof(struct urb*) * (MAX_RX_URB+1), GFP_KERNEL); + +#ifndef JACKSON_NEW_RX + for(i=0;i<(MAX_RX_URB+1);i++){ + + priv->rx_urb[i] = usb_alloc_urb(0,GFP_KERNEL); + + priv->rx_urb[i]->transfer_buffer = kmalloc(RX_URB_SIZE, GFP_KERNEL); + + priv->rx_urb[i]->transfer_buffer_length = RX_URB_SIZE; + } +#endif + +#ifdef THOMAS_BEACON +{ + long align = 0; + void *oldaddr, *newaddr; + + priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL); + priv->oldaddr = kmalloc(16, GFP_KERNEL); + oldaddr = priv->oldaddr; + align = ((long)oldaddr) & 3; + if (align) { + newaddr = oldaddr + 4 - align; + priv->rx_urb[16]->transfer_buffer_length = 16 - 4 + align; + } else { + newaddr = oldaddr; + priv->rx_urb[16]->transfer_buffer_length = 16; + } + priv->rx_urb[16]->transfer_buffer = newaddr; +} +#endif + + memset(priv->rx_urb, 0, sizeof(struct urb*) * MAX_RX_URB); + priv->pp_rxskb = (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) * MAX_RX_URB, GFP_KERNEL); + if (priv->pp_rxskb == NULL) + goto destroy; + + memset(priv->pp_rxskb, 0, sizeof(struct sk_buff*) * MAX_RX_URB); + + goto _middle; + + +destroy: + if (priv->pp_rxskb) { + kfree(priv->pp_rxskb); + } + if (priv->rx_urb) { + kfree(priv->rx_urb); + } + + priv->pp_rxskb = NULL; + priv->rx_urb = NULL; + + DMESGE("Endpoint Alloc Failure"); + return -ENOMEM; + + +_middle: + + printk("End of initendpoints\n"); + return 0; + +} +#ifdef THOMAS_BEACON +void rtl8192_usb_deleteendpoints(struct net_device *dev) +{ + int i; + struct r8192_priv *priv = ieee80211_priv(dev); + + if(priv->rx_urb){ + for(i=0;i<(MAX_RX_URB+1);i++){ + usb_kill_urb(priv->rx_urb[i]); + usb_free_urb(priv->rx_urb[i]); + } + kfree(priv->rx_urb); + priv->rx_urb = NULL; + } + if(priv->oldaddr){ + kfree(priv->oldaddr); + priv->oldaddr = NULL; + } + if (priv->pp_rxskb) { + kfree(priv->pp_rxskb); + priv->pp_rxskb = 0; + } +} +#else +void rtl8192_usb_deleteendpoints(struct net_device *dev) +{ + int i; + struct r8192_priv *priv = ieee80211_priv(dev); + +#ifndef JACKSON_NEW_RX + + if(priv->rx_urb){ + for(i=0;i<(MAX_RX_URB+1);i++){ + usb_kill_urb(priv->rx_urb[i]); + kfree(priv->rx_urb[i]->transfer_buffer); + usb_free_urb(priv->rx_urb[i]); + } + kfree(priv->rx_urb); + priv->rx_urb = NULL; + + } +#else + if(priv->rx_urb){ + kfree(priv->rx_urb); + priv->rx_urb = NULL; + } + if(priv->oldaddr){ + kfree(priv->oldaddr); + priv->oldaddr = NULL; + } + if (priv->pp_rxskb) { + kfree(priv->pp_rxskb); + priv->pp_rxskb = 0; + + } + +#endif +} +#endif + +extern void rtl8192_update_ratr_table(struct net_device* dev); +void rtl8192_link_change(struct net_device *dev) +{ +// int i; + + struct r8192_priv *priv = ieee80211_priv(dev); + struct ieee80211_device* ieee = priv->ieee80211; + //write_nic_word(dev, BCN_INTR_ITV, net->beacon_interval); + if (ieee->state == IEEE80211_LINKED) + { + rtl8192_net_update(dev); + rtl8192_update_ratr_table(dev); + //add this as in pure N mode, wep encryption will use software way, but there is no chance to set this as wep will not set group key in wext. WB.2008.07.08 + if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) + EnableHWSecurityConfig8192(dev); + } + /*update timing params*/ +// RT_TRACE(COMP_CH, "========>%s(), chan:%d\n", __FUNCTION__, priv->chan); +// rtl8192_set_chan(dev, priv->chan); + if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) + { + u32 reg = 0; + reg = read_nic_dword(dev, RCR); + if (priv->ieee80211->state == IEEE80211_LINKED) + priv->ReceiveConfig = reg |= RCR_CBSSID; + else + priv->ReceiveConfig = reg &= ~RCR_CBSSID; + write_nic_dword(dev, RCR, reg); + } + +// rtl8192_set_rxconf(dev); +} + +static struct ieee80211_qos_parameters def_qos_parameters = { + {3,3,3,3},/* cw_min */ + {7,7,7,7},/* cw_max */ + {2,2,2,2},/* aifs */ + {0,0,0,0},/* flags */ + {0,0,0,0} /* tx_op_limit */ +}; + + +void rtl8192_update_beacon(struct work_struct * work) +{ + struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work); + struct net_device *dev = priv->ieee80211->dev; + struct ieee80211_device* ieee = priv->ieee80211; + struct ieee80211_network* net = &ieee->current_network; + + if (ieee->pHTInfo->bCurrentHTSupport) + HTUpdateSelfAndPeerSetting(ieee, net); + ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime; + rtl8192_update_cap(dev, net->capability); +} +/* +* background support to run QoS activate functionality +*/ +int WDCAPARA_ADD[] = {EDCAPARA_BE,EDCAPARA_BK,EDCAPARA_VI,EDCAPARA_VO}; +void rtl8192_qos_activate(struct work_struct * work) +{ + struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate); + struct net_device *dev = priv->ieee80211->dev; + struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters; + u8 mode = priv->ieee80211->current_network.mode; + //u32 size = sizeof(struct ieee80211_qos_parameters); + u8 u1bAIFS; + u32 u4bAcParam; + int i; + + if (priv == NULL) + return; + + mutex_lock(&priv->mutex); + if(priv->ieee80211->state != IEEE80211_LINKED) + goto success; + RT_TRACE(COMP_QOS,"qos active process with associate response received\n"); + /* It better set slot time at first */ + /* For we just support b/g mode at present, let the slot time at 9/20 selection */ + /* update the ac parameter to related registers */ + for(i = 0; i < QOS_QUEUE_NUM; i++) { + //Mode G/A: slotTimeTimer = 9; Mode B: 20 + u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime; + u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)| + (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)| + (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)| + ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET)); + + write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam); + //write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332); + } + +success: + mutex_unlock(&priv->mutex); +} + +static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv, + int active_network, + struct ieee80211_network *network) +{ + int ret = 0; + u32 size = sizeof(struct ieee80211_qos_parameters); + + if(priv->ieee80211->state !=IEEE80211_LINKED) + return ret; + + if ((priv->ieee80211->iw_mode != IW_MODE_INFRA)) + return ret; + + if (network->flags & NETWORK_HAS_QOS_MASK) { + if (active_network && + (network->flags & NETWORK_HAS_QOS_PARAMETERS)) + network->qos_data.active = network->qos_data.supported; + + if ((network->qos_data.active == 1) && (active_network == 1) && + (network->flags & NETWORK_HAS_QOS_PARAMETERS) && + (network->qos_data.old_param_count != + network->qos_data.param_count)) { + network->qos_data.old_param_count = + network->qos_data.param_count; + queue_work(priv->priv_wq, &priv->qos_activate); + RT_TRACE (COMP_QOS, "QoS parameters change call " + "qos_activate\n"); + } + } else { + memcpy(&priv->ieee80211->current_network.qos_data.parameters,\ + &def_qos_parameters, size); + + if ((network->qos_data.active == 1) && (active_network == 1)) { + queue_work(priv->priv_wq, &priv->qos_activate); + RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n"); + } + network->qos_data.active = 0; + network->qos_data.supported = 0; + } + + return 0; +} + +/* handle manage frame frame beacon and probe response */ +static int rtl8192_handle_beacon(struct net_device * dev, + struct ieee80211_beacon * beacon, + struct ieee80211_network * network) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + rtl8192_qos_handle_probe_response(priv,1,network); + queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0); + return 0; + +} + +/* +* handling the beaconing responses. if we get different QoS setting +* off the network from the associated setting, adjust the QoS +* setting +*/ +static int rtl8192_qos_association_resp(struct r8192_priv *priv, + struct ieee80211_network *network) +{ + int ret = 0; + unsigned long flags; + u32 size = sizeof(struct ieee80211_qos_parameters); + int set_qos_param = 0; + + if ((priv == NULL) || (network == NULL)) + return ret; + + if(priv->ieee80211->state !=IEEE80211_LINKED) + return ret; + + if ((priv->ieee80211->iw_mode != IW_MODE_INFRA)) + return ret; + + spin_lock_irqsave(&priv->ieee80211->lock, flags); + if(network->flags & NETWORK_HAS_QOS_PARAMETERS) { + memcpy(&priv->ieee80211->current_network.qos_data.parameters,\ + &network->qos_data.parameters,\ + sizeof(struct ieee80211_qos_parameters)); + priv->ieee80211->current_network.qos_data.active = 1; + { + set_qos_param = 1; + /* update qos parameter for current network */ + priv->ieee80211->current_network.qos_data.old_param_count = \ + priv->ieee80211->current_network.qos_data.param_count; + priv->ieee80211->current_network.qos_data.param_count = \ + network->qos_data.param_count; + } + } else { + memcpy(&priv->ieee80211->current_network.qos_data.parameters,\ + &def_qos_parameters, size); + priv->ieee80211->current_network.qos_data.active = 0; + priv->ieee80211->current_network.qos_data.supported = 0; + set_qos_param = 1; + } + + spin_unlock_irqrestore(&priv->ieee80211->lock, flags); + + RT_TRACE(COMP_QOS, "%s: network->flags = %d,%d\n",__FUNCTION__,network->flags ,priv->ieee80211->current_network.qos_data.active); + if (set_qos_param == 1) + queue_work(priv->priv_wq, &priv->qos_activate); + + + return ret; +} + + +static int rtl8192_handle_assoc_response(struct net_device *dev, + struct ieee80211_assoc_response_frame *resp, + struct ieee80211_network *network) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + rtl8192_qos_association_resp(priv, network); + return 0; +} + + +void rtl8192_update_ratr_table(struct net_device* dev) + // POCTET_STRING posLegacyRate, + // u8* pMcsRate) + // PRT_WLAN_STA pEntry) +{ + struct r8192_priv* priv = ieee80211_priv(dev); + struct ieee80211_device* ieee = priv->ieee80211; + u8* pMcsRate = ieee->dot11HTOperationalRateSet; + //struct ieee80211_network *net = &ieee->current_network; + u32 ratr_value = 0; + u8 rate_index = 0; + rtl8192_config_rate(dev, (u16*)(&ratr_value)); + ratr_value |= (*(u16*)(pMcsRate)) << 12; +// switch (net->mode) + switch (ieee->mode) + { + case IEEE_A: + ratr_value &= 0x00000FF0; + break; + case IEEE_B: + ratr_value &= 0x0000000F; + break; + case IEEE_G: + ratr_value &= 0x00000FF7; + break; + case IEEE_N_24G: + case IEEE_N_5G: + if (ieee->pHTInfo->PeerMimoPs == 0) //MIMO_PS_STATIC + ratr_value &= 0x0007F007; + else{ + if (priv->rf_type == RF_1T2R) + ratr_value &= 0x000FF007; + else + ratr_value &= 0x0F81F007; + } + break; + default: + break; + } + ratr_value &= 0x0FFFFFFF; + if(ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz){ + ratr_value |= 0x80000000; + }else if(!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz){ + ratr_value |= 0x80000000; + } + write_nic_dword(dev, RATR0+rate_index*4, ratr_value); + write_nic_byte(dev, UFWP, 1); +} + +static u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04}; +static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04}; +bool GetNmodeSupportBySecCfg8192(struct net_device*dev) +{ + struct r8192_priv* priv = ieee80211_priv(dev); + struct ieee80211_device* ieee = priv->ieee80211; + struct ieee80211_network * network = &ieee->current_network; + int wpa_ie_len= ieee->wpa_ie_len; + struct ieee80211_crypt_data* crypt; + int encrypt; + + crypt = ieee->crypt[ieee->tx_keyidx]; + //we use connecting AP's capability instead of only security config on our driver to distinguish whether it should use N mode or G mode + encrypt = (network->capability & WLAN_CAPABILITY_PRIVACY) || (ieee->host_encrypt && crypt && crypt->ops && (0 == strcmp(crypt->ops->name,"WEP"))); + + /* simply judge */ + if(encrypt && (wpa_ie_len == 0)) { + /* wep encryption, no N mode setting */ + return false; +// } else if((wpa_ie_len != 0)&&(memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) { + } else if((wpa_ie_len != 0)) { + /* parse pairwise key type */ + //if((pairwisekey = WEP40)||(pairwisekey = WEP104)||(pairwisekey = TKIP)) + if (((ieee->wpa_ie[0] == 0xdd) && (!memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) || ((ieee->wpa_ie[0] == 0x30) && (!memcmp(&ieee->wpa_ie[10],ccmp_rsn_ie, 4)))) + return true; + else + return false; + } else { + return true; + } + + return true; +} + +bool GetHalfNmodeSupportByAPs819xUsb(struct net_device* dev) +{ + bool Reval; + struct r8192_priv* priv = ieee80211_priv(dev); + struct ieee80211_device* ieee = priv->ieee80211; + + if(ieee->bHalfWirelessN24GMode == true) + Reval = true; + else + Reval = false; + + return Reval; +} + +void rtl8192_refresh_supportrate(struct r8192_priv* priv) +{ + struct ieee80211_device* ieee = priv->ieee80211; + //we donot consider set support rate for ABG mode, only HT MCS rate is set here. + if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G) + { + memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16); + //RT_DEBUG_DATA(COMP_INIT, ieee->RegHTSuppRateSet, 16); + //RT_DEBUG_DATA(COMP_INIT, ieee->Regdot11HTOperationalRateSet, 16); + } + else + memset(ieee->Regdot11HTOperationalRateSet, 0, 16); + return; +} + +u8 rtl8192_getSupportedWireleeMode(struct net_device*dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u8 ret = 0; + switch(priv->rf_chip) + { + case RF_8225: + case RF_8256: + case RF_PSEUDO_11N: + ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B); + break; + case RF_8258: + ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G); + break; + default: + ret = WIRELESS_MODE_B; + break; + } + return ret; +} +void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev); + + if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode)==0)) + { + if(bSupportMode & WIRELESS_MODE_N_24G) + { + wireless_mode = WIRELESS_MODE_N_24G; + } + else if(bSupportMode & WIRELESS_MODE_N_5G) + { + wireless_mode = WIRELESS_MODE_N_5G; + } + else if((bSupportMode & WIRELESS_MODE_A)) + { + wireless_mode = WIRELESS_MODE_A; + } + else if((bSupportMode & WIRELESS_MODE_G)) + { + wireless_mode = WIRELESS_MODE_G; + } + else if((bSupportMode & WIRELESS_MODE_B)) + { + wireless_mode = WIRELESS_MODE_B; + } + else{ + RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __FUNCTION__,bSupportMode); + wireless_mode = WIRELESS_MODE_B; + } + } +#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we shoud wait for FPGA + ActUpdateChannelAccessSetting( pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting ); +#endif + priv->ieee80211->mode = wireless_mode; + + if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G)) + priv->ieee80211->pHTInfo->bEnableHT = 1; + else + priv->ieee80211->pHTInfo->bEnableHT = 0; + RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode); + rtl8192_refresh_supportrate(priv); + +} +//init priv variables here. only non_zero value should be initialized here. +static void rtl8192_init_priv_variable(struct net_device* dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u8 i; + priv->card_8192 = NIC_8192U; + priv->chan = 1; //set to channel 1 + priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO + priv->ieee80211->iw_mode = IW_MODE_INFRA; + priv->ieee80211->ieee_up=0; + priv->retry_rts = DEFAULT_RETRY_RTS; + priv->retry_data = DEFAULT_RETRY_DATA; + priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD; + priv->ieee80211->rate = 110; //11 mbps + priv->ieee80211->short_slot = 1; + priv->promisc = (dev->flags & IFF_PROMISC) ? 1:0; + priv->CckPwEnl = 6; + //for silent reset + priv->IrpPendingCount = 1; + priv->ResetProgress = RESET_TYPE_NORESET; + priv->bForcedSilentReset = 0; + priv->bDisableNormalResetCheck = false; + priv->force_reset = false; + + priv->ieee80211->FwRWRF = 0; //we don't use FW read/write RF until stable firmware is available. + priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL; + priv->ieee80211->iw_mode = IW_MODE_INFRA; + priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN | + IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ | + IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE | + IEEE_SOFTMAC_BEACONS;//added by amy 080604 //| //IEEE_SOFTMAC_SINGLE_QUEUE; + + priv->ieee80211->active_scan = 1; + priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION; + priv->ieee80211->host_encrypt = 1; + priv->ieee80211->host_decrypt = 1; + priv->ieee80211->start_send_beacons = NULL;//rtl819xusb_beacon_tx;//-by amy 080604 + priv->ieee80211->stop_send_beacons = NULL;//rtl8192_beacon_stop;//-by amy 080604 + priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit; + priv->ieee80211->set_chan = rtl8192_set_chan; + priv->ieee80211->link_change = rtl8192_link_change; + priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit; + priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop; + priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume; + priv->ieee80211->init_wmmparam_flag = 0; + priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD; + priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc; + priv->ieee80211->tx_headroom = TX_PACKET_SHIFT_BYTES; + priv->ieee80211->qos_support = 1; + + //added by WB +// priv->ieee80211->SwChnlByTimerHandler = rtl8192_phy_SwChnl; + priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode; + priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response; + priv->ieee80211->handle_beacon = rtl8192_handle_beacon; + //added by david + priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8192; + priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xUsb; + priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode; + //added by amy + priv->ieee80211->InitialGainHandler = InitialGain819xUsb; + priv->card_type = USB; +#ifdef TO_DO_LIST + if(Adapter->bInHctTest) + { + pHalData->ShortRetryLimit = 7; + pHalData->LongRetryLimit = 7; + } +#endif + { + priv->ShortRetryLimit = 0x30; + priv->LongRetryLimit = 0x30; + } + priv->EarlyRxThreshold = 7; + priv->enable_gpio0 = 0; + priv->TransmitConfig = + // TCR_DurProcMode | //for RTL8185B, duration setting by HW + //? TCR_DISReqQsize | + (TCR_MXDMA_2048<ShortRetryLimit<LongRetryLimit<bInHctTest) + pHalData->ReceiveConfig = pHalData->CSMethod | + RCR_AMF | RCR_ADF | //RCR_AAP | //accept management/data + //guangan200710 + RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko. + RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC + RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet + ((u32)7<EarlyRxThreshold<EarlyRxThreshold == 7 ? RCR_OnlyErlPkt:0); + else + +#endif + priv->ReceiveConfig = + RCR_AMF | RCR_ADF | //accept management/data + RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko. + RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC + //RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet + ((u32)7<EarlyRxThreshold<EarlyRxThreshold == 7 ? RCR_ONLYERLPKT:0); + + priv->AcmControl = 0; + priv->pFirmware = (rt_firmware*)kmalloc(sizeof(rt_firmware), GFP_KERNEL); + if (priv->pFirmware) + memset(priv->pFirmware, 0, sizeof(rt_firmware)); + + /* rx related queue */ + skb_queue_head_init(&priv->rx_queue); + skb_queue_head_init(&priv->skb_queue); + + /* Tx related queue */ + for(i = 0; i < MAX_QUEUE_SIZE; i++) { + skb_queue_head_init(&priv->ieee80211->skb_waitQ [i]); + } + for(i = 0; i < MAX_QUEUE_SIZE; i++) { + skb_queue_head_init(&priv->ieee80211->skb_aggQ [i]); + } + for(i = 0; i < MAX_QUEUE_SIZE; i++) { + skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ [i]); + } + priv->rf_set_chan = rtl8192_phy_SwChnl; +} + +//init lock here +static void rtl8192_init_priv_lock(struct r8192_priv* priv) +{ + spin_lock_init(&priv->tx_lock); + spin_lock_init(&priv->irq_lock);//added by thomas + //spin_lock_init(&priv->rf_lock); + sema_init(&priv->wx_sem,1); + sema_init(&priv->rf_sem,1); + mutex_init(&priv->mutex); +} + +extern void rtl819x_watchdog_wqcallback(struct work_struct *work); + +void rtl8192_irq_rx_tasklet(struct r8192_priv *priv); +//init tasklet and wait_queue here. only 2.6 above kernel is considered +#define DRV_NAME "wlan0" +static void rtl8192_init_priv_task(struct net_device* dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + +#ifdef PF_SYNCTHREAD + priv->priv_wq = create_workqueue(DRV_NAME,0); +#else + priv->priv_wq = create_workqueue(DRV_NAME); +#endif + + INIT_WORK(&priv->reset_wq, rtl8192_restart); + + //INIT_DELAYED_WORK(&priv->watch_dog_wq, hal_dm_watchdog); + INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback); + INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback); +// INIT_DELAYED_WORK(&priv->gpio_change_rf_wq, dm_gpio_change_rf_callback); + INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback); + INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon); + INIT_DELAYED_WORK(&priv->initialgain_operate_wq, InitialGainOperateWorkItemCallBack); + //INIT_WORK(&priv->SwChnlWorkItem, rtl8192_SwChnl_WorkItem); + //INIT_WORK(&priv->SetBWModeWorkItem, rtl8192_SetBWModeWorkItem); + INIT_WORK(&priv->qos_activate, rtl8192_qos_activate); + + tasklet_init(&priv->irq_rx_tasklet, + (void(*)(unsigned long))rtl8192_irq_rx_tasklet, + (unsigned long)priv); +} + +static void rtl8192_get_eeprom_size(struct net_device* dev) +{ + u16 curCR = 0; + struct r8192_priv *priv = ieee80211_priv(dev); + RT_TRACE(COMP_EPROM, "===========>%s()\n", __FUNCTION__); + curCR = read_nic_word_E(dev,EPROM_CMD); + RT_TRACE(COMP_EPROM, "read from Reg EPROM_CMD(%x):%x\n", EPROM_CMD, curCR); + //whether need I consider BIT5? + priv->epromtype = (curCR & Cmd9346CR_9356SEL) ? EPROM_93c56 : EPROM_93c46; + RT_TRACE(COMP_EPROM, "<===========%s(), epromtype:%d\n", __FUNCTION__, priv->epromtype); +} + +//used to swap endian. as ntohl & htonl are not neccessary to swap endian, so use this instead. +static inline u16 endian_swap(u16* data) +{ + u16 tmp = *data; + *data = (tmp >> 8) | (tmp << 8); + return *data; +} +static void rtl8192_read_eeprom_info(struct net_device* dev) +{ + u16 wEPROM_ID = 0; + u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x02}; + u8 bLoad_From_EEPOM = false; + struct r8192_priv *priv = ieee80211_priv(dev); + u16 tmpValue = 0; + RT_TRACE(COMP_EPROM, "===========>%s()\n", __FUNCTION__); + wEPROM_ID = eprom_read(dev, 0); //first read EEPROM ID out; + RT_TRACE(COMP_EPROM, "EEPROM ID is 0x%x\n", wEPROM_ID); + + if (wEPROM_ID != RTL8190_EEPROM_ID) + { + RT_TRACE(COMP_ERR, "EEPROM ID is invalid(is 0x%x(should be 0x%x)\n", wEPROM_ID, RTL8190_EEPROM_ID); + } + else + bLoad_From_EEPOM = true; + + if (bLoad_From_EEPOM) + { + tmpValue = eprom_read(dev, (EEPROM_VID>>1)); + priv->eeprom_vid = endian_swap(&tmpValue); + priv->eeprom_pid = eprom_read(dev, (EEPROM_PID>>1)); + tmpValue = eprom_read(dev, (EEPROM_ChannelPlan>>1)); + priv->eeprom_ChannelPlan =((tmpValue&0xff00)>>8); + priv->btxpowerdata_readfromEEPORM = true; + priv->eeprom_CustomerID = eprom_read(dev, (EEPROM_Customer_ID>>1)) >>8; + } + else + { + priv->eeprom_vid = 0; + priv->eeprom_pid = 0; + priv->card_8192_version = VERSION_819xU_B; + priv->eeprom_ChannelPlan = 0; + priv->eeprom_CustomerID = 0; + } + RT_TRACE(COMP_EPROM, "vid:0x%4x, pid:0x%4x, CustomID:0x%2x, ChanPlan:0x%x\n", priv->eeprom_vid, priv->eeprom_pid, priv->eeprom_CustomerID, priv->eeprom_ChannelPlan); + //set channelplan from eeprom + priv->ChannelPlan = priv->eeprom_ChannelPlan; + if (bLoad_From_EEPOM) + { + int i; + for (i=0; i<6; i+=2) + { + u16 tmp = 0; + tmp = eprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i)>>1)); + *(u16*)(&dev->dev_addr[i]) = tmp; + } + } + else + { + memcpy(dev->dev_addr, bMac_Tmp_Addr, 6); + //should I set IDR0 here? + } + RT_TRACE(COMP_EPROM, "MAC addr:"MAC_FMT"\n", MAC_ARG(dev->dev_addr)); + priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R + priv->rf_chip = RF_8256; + + if (priv->card_8192_version == (u8)VERSION_819xU_A) + { + //read Tx power gain offset of legacy OFDM to HT rate + if (bLoad_From_EEPOM) + priv->EEPROMTxPowerDiff = (eprom_read(dev, (EEPROM_TxPowerDiff>>1))&0xff00) >> 8; + else + priv->EEPROMTxPowerDiff = EEPROM_Default_TxPower; + RT_TRACE(COMP_EPROM, "TxPowerDiff:%d\n", priv->EEPROMTxPowerDiff); + //read ThermalMeter from EEPROM + if (bLoad_From_EEPOM) + priv->EEPROMThermalMeter = (u8)(eprom_read(dev, (EEPROM_ThermalMeter>>1))&0x00ff); + else + priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter; + RT_TRACE(COMP_EPROM, "ThermalMeter:%d\n", priv->EEPROMThermalMeter); + //vivi, for tx power track + priv->TSSI_13dBm = priv->EEPROMThermalMeter *100; + //read antenna tx power offset of B/C/D to A from EEPROM + if (bLoad_From_EEPOM) + priv->EEPROMPwDiff = (eprom_read(dev, (EEPROM_PwDiff>>1))&0x0f00)>>8; + else + priv->EEPROMPwDiff = EEPROM_Default_PwDiff; + RT_TRACE(COMP_EPROM, "TxPwDiff:%d\n", priv->EEPROMPwDiff); + // Read CrystalCap from EEPROM + if (bLoad_From_EEPOM) + priv->EEPROMCrystalCap = (eprom_read(dev, (EEPROM_CrystalCap>>1))&0x0f); + else + priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap; + RT_TRACE(COMP_EPROM, "CrystalCap = %d\n", priv->EEPROMCrystalCap); + //get per-channel Tx power level + if (bLoad_From_EEPOM) + priv->EEPROM_Def_Ver = (eprom_read(dev, (EEPROM_TxPwIndex_Ver>>1))&0xff00)>>8; + else + priv->EEPROM_Def_Ver = 1; + RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver); + if (priv->EEPROM_Def_Ver == 0) //old eeprom definition + { + int i; + if (bLoad_From_EEPOM) + priv->EEPROMTxPowerLevelCCK = (eprom_read(dev, (EEPROM_TxPwIndex_CCK>>1))&0xff) >> 8; + else + priv->EEPROMTxPowerLevelCCK = 0x10; + RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK); + for (i=0; i<3; i++) + { + if (bLoad_From_EEPOM) + { + tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G+i)>>1); + if (((EEPROM_TxPwIndex_OFDM_24G+i) % 2) == 0) + tmpValue = tmpValue & 0x00ff; + else + tmpValue = (tmpValue & 0xff00) >> 8; + } + else + tmpValue = 0x10; + priv->EEPROMTxPowerLevelOFDM24G[i] = (u8) tmpValue; + RT_TRACE(COMP_EPROM, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK); + } + }//end if EEPROM_DEF_VER == 0 + else if (priv->EEPROM_Def_Ver == 1) + { + if (bLoad_From_EEPOM) + { + tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1>>1)); + tmpValue = (tmpValue & 0xff00) >> 8; + } + else + tmpValue = 0x10; + priv->EEPROMTxPowerLevelCCK_V1[0] = (u8)tmpValue; + + if (bLoad_From_EEPOM) + tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1 + 2)>>1); + else + tmpValue = 0x1010; + *((u16*)(&priv->EEPROMTxPowerLevelCCK_V1[1])) = tmpValue; + if (bLoad_From_EEPOM) + tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1>>1)); + else + tmpValue = 0x1010; + *((u16*)(&priv->EEPROMTxPowerLevelOFDM24G[0])) = tmpValue; + if (bLoad_From_EEPOM) + tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1+2)>>1); + else + tmpValue = 0x10; + priv->EEPROMTxPowerLevelOFDM24G[2] = (u8)tmpValue; + }//endif EEPROM_Def_Ver == 1 + + //update HAL variables + // + { + int i; + for (i=0; i<14; i++) + { + if (i<=3) + priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[0]; + else if (i>=4 && i<=9) + priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[1]; + else + priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[2]; + } + + for (i=0; i<14; i++) + { + if (priv->EEPROM_Def_Ver == 0) + { + if (i<=3) + priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[0] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]); + else if (i>=4 && i<=9) + priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK; + else + priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[2] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]); + } + else if (priv->EEPROM_Def_Ver == 1) + { + if (i<=3) + priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[0]; + else if (i>=4 && i<=9) + priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[1]; + else + priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[2]; + } + } + }//end update HAL variables + priv->TxPowerDiff = priv->EEPROMPwDiff; +// Antenna B gain offset to antenna A, bit0~3 + priv->AntennaTxPwDiff[0] = (priv->EEPROMTxPowerDiff & 0xf); + // Antenna C gain offset to antenna A, bit4~7 + priv->AntennaTxPwDiff[1] = ((priv->EEPROMTxPowerDiff & 0xf0)>>4); + // CrystalCap, bit12~15 + priv->CrystalCap = priv->EEPROMCrystalCap; + // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2 + // 92U does not enable TX power tracking. + priv->ThermalMeter[0] = priv->EEPROMThermalMeter; + }//end if VersionID == VERSION_819xU_A + +//added by vivi, for dlink led, 20080416 + switch(priv->eeprom_CustomerID) + { + case EEPROM_CID_RUNTOP: + priv->CustomerID = RT_CID_819x_RUNTOP; + break; + + case EEPROM_CID_DLINK: + priv->CustomerID = RT_CID_DLINK; + break; + + default: + priv->CustomerID = RT_CID_DEFAULT; + break; + + } + + switch(priv->CustomerID) + { + case RT_CID_819x_RUNTOP: + priv->LedStrategy = SW_LED_MODE2; + break; + + case RT_CID_DLINK: + priv->LedStrategy = SW_LED_MODE4; + break; + + default: + priv->LedStrategy = SW_LED_MODE0; + break; + + } + + + if(priv->rf_type == RF_1T2R) + { + RT_TRACE(COMP_EPROM, "\n1T2R config\n"); + } + else + { + RT_TRACE(COMP_EPROM, "\n2T4R config\n"); + } + + // 2008/01/16 MH We can only know RF type in the function. So we have to init + // DIG RATR table again. + init_rate_adaptive(dev); + //we need init DIG RATR table here again. + + RT_TRACE(COMP_EPROM, "<===========%s()\n", __FUNCTION__); + return; +} + +short rtl8192_get_channel_map(struct net_device * dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); +#ifdef ENABLE_DOT11D + if(priv->ChannelPlan > COUNTRY_CODE_GLOBAL_DOMAIN){ + printk("rtl8180_init:Error channel plan! Set to default.\n"); + priv->ChannelPlan= 0; + } + RT_TRACE(COMP_INIT, "Channel plan is %d\n",priv->ChannelPlan); + + rtl819x_set_channel_map(priv->ChannelPlan, priv); +#else + int ch,i; + //Set Default Channel Plan + if(!channels){ + DMESG("No channels, aborting"); + return -1; + } + ch=channels; + priv->ChannelPlan= 0;//hikaru + // set channels 1..14 allowed in given locale + for (i=1; i<=14; i++) { + (priv->ieee80211->channel_map)[i] = (u8)(ch & 0x01); + ch >>= 1; + } +#endif + return 0; +} + +short rtl8192_init(struct net_device *dev) +{ + + struct r8192_priv *priv = ieee80211_priv(dev); + + memset(&(priv->stats),0,sizeof(struct Stats)); + memset(priv->txqueue_to_outpipemap,0,9); +#ifdef PIPE12 + { + int i=0; + u8 queuetopipe[]={3,2,1,0,4,8,7,6,5}; + memcpy(priv->txqueue_to_outpipemap,queuetopipe,9); +/* for(i=0;i<9;i++) + printk("%d ",priv->txqueue_to_outpipemap[i]); + printk("\n");*/ + } +#else + { + u8 queuetopipe[]={3,2,1,0,4,4,0,4,4}; + memcpy(priv->txqueue_to_outpipemap,queuetopipe,9); +/* for(i=0;i<9;i++) + printk("%d ",priv->txqueue_to_outpipemap[i]); + printk("\n");*/ + } +#endif + rtl8192_init_priv_variable(dev); + rtl8192_init_priv_lock(priv); + rtl8192_init_priv_task(dev); + rtl8192_get_eeprom_size(dev); + rtl8192_read_eeprom_info(dev); + rtl8192_get_channel_map(dev); + init_hal_dm(dev); + init_timer(&priv->watch_dog_timer); + priv->watch_dog_timer.data = (unsigned long)dev; + priv->watch_dog_timer.function = watch_dog_timer_callback; + if(rtl8192_usb_initendpoints(dev)!=0){ + DMESG("Endopoints initialization failed"); + return -ENOMEM; + } + + //rtl8192_adapter_start(dev); +#ifdef DEBUG_EPROM + dump_eprom(dev); +#endif + return 0; +} + +/****************************************************************************** + *function: This function actually only set RRSR, RATR and BW_OPMODE registers + * not to do all the hw config as its name says + * input: net_device dev + * output: none + * return: none + * notice: This part need to modified according to the rate set we filtered + * ****************************************************************************/ +void rtl8192_hwconfig(struct net_device* dev) +{ + u32 regRATR = 0, regRRSR = 0; + u8 regBwOpMode = 0, regTmp = 0; + struct r8192_priv *priv = ieee80211_priv(dev); + +// Set RRSR, RATR, and BW_OPMODE registers + // + switch(priv->ieee80211->mode) + { + case WIRELESS_MODE_B: + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK; + regRRSR = RATE_ALL_CCK; + break; + case WIRELESS_MODE_A: + regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ; + regRATR = RATE_ALL_OFDM_AG; + regRRSR = RATE_ALL_OFDM_AG; + break; + case WIRELESS_MODE_G: + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + break; + case WIRELESS_MODE_AUTO: +#ifdef TO_DO_LIST + if (Adapter->bInHctTest) + { + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + } + else +#endif + { + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + } + break; + case WIRELESS_MODE_N_24G: + // It support CCK rate by default. + // CCK rate will be filtered out only when associated AP does not support it. + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + break; + case WIRELESS_MODE_N_5G: + regBwOpMode = BW_OPMODE_5G; + regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + regRRSR = RATE_ALL_OFDM_AG; + break; + } + + write_nic_byte(dev, BW_OPMODE, regBwOpMode); + { + u32 ratr_value = 0; + ratr_value = regRATR; + if (priv->rf_type == RF_1T2R) + { + ratr_value &= ~(RATE_ALL_OFDM_2SS); + } + write_nic_dword(dev, RATR0, ratr_value); + write_nic_byte(dev, UFWP, 1); + } + regTmp = read_nic_byte(dev, 0x313); + regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff); + write_nic_dword(dev, RRSR, regRRSR); + + // + // Set Retry Limit here + // + write_nic_word(dev, RETRY_LIMIT, + priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT | \ + priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT); + // Set Contention Window here + + // Set Tx AGC + + // Set Tx Antenna including Feedback control + + // Set Auto Rate fallback control + + +} + + +//InitializeAdapter and PhyCfg +bool rtl8192_adapter_start(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u32 dwRegRead = 0; + bool init_status = true; + RT_TRACE(COMP_INIT, "====>%s()\n", __FUNCTION__); + priv->Rf_Mode = RF_OP_By_SW_3wire; + //for ASIC power on sequence + write_nic_byte_E(dev, 0x5f, 0x80); + mdelay(50); + write_nic_byte_E(dev, 0x5f, 0xf0); + write_nic_byte_E(dev, 0x5d, 0x00); + write_nic_byte_E(dev, 0x5e, 0x80); + write_nic_byte(dev, 0x17, 0x37); + mdelay(10); +//#ifdef TO_DO_LIST + priv->pFirmware->firmware_status = FW_STATUS_0_INIT; + //config CPUReset Register + //Firmware Reset or not? + dwRegRead = read_nic_dword(dev, CPU_GEN); + if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT) + dwRegRead |= CPU_GEN_SYSTEM_RESET; //do nothing here? + else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY) + dwRegRead |= CPU_GEN_FIRMWARE_RESET; + else + RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __FUNCTION__, priv->pFirmware->firmware_status); + + write_nic_dword(dev, CPU_GEN, dwRegRead); + //mdelay(30); + //config BB. + rtl8192_BBConfig(dev); + + //Loopback mode or not + priv->LoopbackMode = RTL819xU_NO_LOOPBACK; +// priv->LoopbackMode = RTL819xU_MAC_LOOPBACK; + + dwRegRead = read_nic_dword(dev, CPU_GEN); + if (priv->LoopbackMode == RTL819xU_NO_LOOPBACK) + dwRegRead = ((dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET); + else if (priv->LoopbackMode == RTL819xU_MAC_LOOPBACK) + dwRegRead |= CPU_CCK_LOOPBACK; + else + RT_TRACE(COMP_ERR, "Serious error in %s(): wrong loopback mode setting(%d)\n", __FUNCTION__, priv->LoopbackMode); + + write_nic_dword(dev, CPU_GEN, dwRegRead); + + //after reset cpu, we need wait for a seconds to write in register. + udelay(500); + + //xiong add for new bitfile:usb suspend reset pin set to 1. //do we need? + write_nic_byte_E(dev, 0x5f, (read_nic_byte_E(dev, 0x5f)|0x20)); + + //Set Hardware + rtl8192_hwconfig(dev); + + //turn on Tx/Rx + write_nic_byte(dev, CMDR, CR_RE|CR_TE); + + //set IDR0 here + write_nic_dword(dev, MAC0, ((u32*)dev->dev_addr)[0]); + write_nic_word(dev, MAC4, ((u16*)(dev->dev_addr + 4))[0]); + + //set RCR + write_nic_dword(dev, RCR, priv->ReceiveConfig); + + //Initialize Number of Reserved Pages in Firmware Queue + write_nic_dword(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK << RSVD_FW_QUEUE_PAGE_BK_SHIFT |\ + NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT | \ + NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT | \ + NUM_OF_PAGE_IN_FW_QUEUE_VO <ResetProgress is %d\n", __FUNCTION__,priv->ResetProgress); + if(priv->ResetProgress == RESET_TYPE_NORESET) + rtl8192_SetWirelessMode(dev, priv->ieee80211->mode); + if(priv->ResetProgress == RESET_TYPE_NORESET){ + CamResetAllEntry(dev); + { + u8 SECR_value = 0x0; + SECR_value |= SCR_TxEncEnable; + SECR_value |= SCR_RxDecEnable; + SECR_value |= SCR_NoSKMC; + write_nic_byte(dev, SECR, SECR_value); + } + } + + //Beacon related + write_nic_word(dev, ATIMWND, 2); + write_nic_word(dev, BCN_INTERVAL, 100); + + { +#define DEFAULT_EDCA 0x005e4332 + int i; + for (i=0; iResetProgress == RESET_TYPE_NORESET) + { + u32 ulValue; + PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo; + ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) | + (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout); + /* + * If usb rx firmware aggregation is enabled, + * when anyone of three threshold conditions above is reached, + * firmware will send aggregated packet to driver. + */ + write_nic_dword(dev, 0x1a8, ulValue); + priv->bCurrentRxAggrEnable = true; + } +#endif + + rtl8192_phy_configmac(dev); + + if (priv->card_8192_version == (u8) VERSION_819xU_A) + { + rtl8192_phy_getTxPower(dev); + rtl8192_phy_setTxPower(dev, priv->chan); + } + + //Firmware download + init_status = init_firmware(dev); + if(!init_status) + { + RT_TRACE(COMP_ERR,"ERR!!! %s(): Firmware download is failed\n", __FUNCTION__); + return init_status; + } + RT_TRACE(COMP_INIT, "%s():after firmware download\n", __FUNCTION__); + // +#ifdef TO_DO_LIST +if(Adapter->ResetProgress == RESET_TYPE_NORESET) + { + if(pMgntInfo->RegRfOff == TRUE) + { // User disable RF via registry. + RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n")); + MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW); + // Those action will be discard in MgntActSet_RF_State because off the same state + for(eRFPath = 0; eRFPath NumTotalRFPath; eRFPath++) + PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0); + } + else if(pMgntInfo->RfOffReason > RF_CHANGE_BY_PS) + { // H/W or S/W RF OFF before sleep. + RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", pMgntInfo->RfOffReason)); + MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason); + } + else + { + pHalData->eRFPowerState = eRfOn; + pMgntInfo->RfOffReason = 0; + RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): RF is on ----------\n")); + } + } + else + { + if(pHalData->eRFPowerState == eRfOff) + { + MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason); + // Those action will be discard in MgntActSet_RF_State because off the same state + for(eRFPath = 0; eRFPath NumTotalRFPath; eRFPath++) + PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0); + } + } +#endif + //config RF. + if(priv->ResetProgress == RESET_TYPE_NORESET){ + rtl8192_phy_RFConfig(dev); + RT_TRACE(COMP_INIT, "%s():after phy RF config\n", __FUNCTION__); + } + + + if(priv->ieee80211->FwRWRF) + // We can force firmware to do RF-R/W + priv->Rf_Mode = RF_OP_By_FW; + else + priv->Rf_Mode = RF_OP_By_SW_3wire; + + + rtl8192_phy_updateInitGain(dev); + /*--set CCK and OFDM Block "ON"--*/ + rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1); + rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1); + + if(priv->ResetProgress == RESET_TYPE_NORESET) + { + //if D or C cut + u8 tmpvalue = read_nic_byte(dev, 0x301); + if(tmpvalue ==0x03) + { + priv->bDcut = TRUE; + RT_TRACE(COMP_POWER_TRACKING, "D-cut\n"); + } + else + { + priv->bDcut = FALSE; + RT_TRACE(COMP_POWER_TRACKING, "C-cut\n"); + } + dm_initialize_txpower_tracking(dev); + + if(priv->bDcut == TRUE) + { + u32 i, TempCCk; + u32 tmpRegA= rtl8192_QueryBBReg(dev,rOFDM0_XATxIQImbalance,bMaskDWord); + // u32 tmpRegC= rtl8192_QueryBBReg(dev,rOFDM0_XCTxIQImbalance,bMaskDWord); + for(i = 0; itxbbgain_table[i].txbbgain_value) + { + priv->rfa_txpowertrackingindex= (u8)i; + priv->rfa_txpowertrackingindex_real= (u8)i; + priv->rfa_txpowertracking_default= priv->rfa_txpowertrackingindex; + break; + } + } + + TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2); + + for(i=0 ; icck_txbbgain_table[i].ccktxbb_valuearray[0]) + { + priv->cck_present_attentuation_20Mdefault=(u8) i; + break; + } + } + priv->cck_present_attentuation_40Mdefault= 0; + priv->cck_present_attentuation_difference= 0; + priv->cck_present_attentuation = priv->cck_present_attentuation_20Mdefault; + + // pMgntInfo->bTXPowerTracking = FALSE;//TEMPLY DISABLE + } + } + write_nic_byte(dev, 0x87, 0x0); + + + return init_status; +} + +/* this configures registers for beacon tx and enables it via + * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might + * be used to stop beacon transmission + */ +/*************************************************************************** + -------------------------------NET STUFF--------------------------- +***************************************************************************/ + +static struct net_device_stats *rtl8192_stats(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + return &priv->ieee80211->stats; +} + +bool +HalTxCheckStuck819xUsb( + struct net_device *dev + ) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u16 RegTxCounter = read_nic_word(dev, 0x128); + bool bStuck = FALSE; + RT_TRACE(COMP_RESET,"%s():RegTxCounter is %d,TxCounter is %d\n",__FUNCTION__,RegTxCounter,priv->TxCounter); + if(priv->TxCounter==RegTxCounter) + bStuck = TRUE; + + priv->TxCounter = RegTxCounter; + + return bStuck; +} + +/* +* +* First added: 2006.11.19 by emily +*/ +RESET_TYPE +TxCheckStuck(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u8 QueueID; +// PRT_TCB pTcb; +// u8 ResetThreshold; + bool bCheckFwTxCnt = false; + //unsigned long flags; + + // + // Decide Stuch threshold according to current power save mode + // + +// RT_TRACE(COMP_RESET, " ==> TxCheckStuck()\n"); +// PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK); +// spin_lock_irqsave(&priv->ieee80211->lock,flags); + for (QueueID = 0; QueueID<=BEACON_QUEUE;QueueID ++) + { + if(QueueID == TXCMD_QUEUE) + continue; +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + if((skb_queue_len(&priv->ieee80211->skb_waitQ[QueueID]) == 0) && (skb_queue_len(&priv->ieee80211->skb_aggQ[QueueID]) == 0) && (skb_queue_len(&priv->ieee80211->skb_drv_aggQ[QueueID]) == 0)) +#else + if((skb_queue_len(&priv->ieee80211->skb_waitQ[QueueID]) == 0) && (skb_queue_len(&priv->ieee80211->skb_aggQ[QueueID]) == 0)) +#endif + continue; + + bCheckFwTxCnt = true; + } +// PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK); +// spin_unlock_irqrestore(&priv->ieee80211->lock,flags); +// RT_TRACE(COMP_RESET,"bCheckFwTxCnt is %d\n",bCheckFwTxCnt); + if(bCheckFwTxCnt) + { + if(HalTxCheckStuck819xUsb(dev)) + { + RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n"); + return RESET_TYPE_SILENT; + } + } + return RESET_TYPE_NORESET; +} + +bool +HalRxCheckStuck819xUsb(struct net_device *dev) +{ + u16 RegRxCounter = read_nic_word(dev, 0x130); + struct r8192_priv *priv = ieee80211_priv(dev); + bool bStuck = FALSE; + static u8 rx_chk_cnt = 0; + RT_TRACE(COMP_RESET,"%s(): RegRxCounter is %d,RxCounter is %d\n",__FUNCTION__,RegRxCounter,priv->RxCounter); + // If rssi is small, we should check rx for long time because of bad rx. + // or maybe it will continuous silent reset every 2 seconds. + rx_chk_cnt++; + if(priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5)) + { + rx_chk_cnt = 0; //high rssi, check rx stuck right now. + } + else if(priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) && + ((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_40M) || + (priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_20M)) ) + { + if(rx_chk_cnt < 2) + { + return bStuck; + } + else + { + rx_chk_cnt = 0; + } + } + else if(((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdbCurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdbundecorated_smoothed_pwdb >= VeryLowRSSI) + { + if(rx_chk_cnt < 4) + { + //DbgPrint("RSSI < %d && RSSI >= %d, no check this time \n", RateAdaptiveTH_Low, VeryLowRSSI); + return bStuck; + } + else + { + rx_chk_cnt = 0; + //DbgPrint("RSSI < %d && RSSI >= %d, check this time \n", RateAdaptiveTH_Low, VeryLowRSSI); + } + } + else + { + if(rx_chk_cnt < 8) + { + //DbgPrint("RSSI <= %d, no check this time \n", VeryLowRSSI); + return bStuck; + } + else + { + rx_chk_cnt = 0; + //DbgPrint("RSSI <= %d, check this time \n", VeryLowRSSI); + } + } + + if(priv->RxCounter==RegRxCounter) + bStuck = TRUE; + + priv->RxCounter = RegRxCounter; + + return bStuck; +} + +RESET_TYPE +RxCheckStuck(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + //int i; + bool bRxCheck = FALSE; + +// RT_TRACE(COMP_RESET," ==> RxCheckStuck()\n"); + //PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK); + + if(priv->IrpPendingCount > 1) + bRxCheck = TRUE; + //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK); + +// RT_TRACE(COMP_RESET,"bRxCheck is %d \n",bRxCheck); + if(bRxCheck) + { + if(HalRxCheckStuck819xUsb(dev)) + { + RT_TRACE(COMP_RESET, "RxStuck Condition\n"); + return RESET_TYPE_SILENT; + } + } + return RESET_TYPE_NORESET; +} + + +/** +* This function is called by Checkforhang to check whether we should ask OS to reset driver +* +* \param pAdapter The adapter context for this miniport +* +* Note:NIC with USB interface sholud not call this function because we cannot scan descriptor +* to judge whether there is tx stuck. +* Note: This function may be required to be rewrite for Vista OS. +* <<>> +* +* 8185 and 8185b does not implement this function. This is added by Emily at 2006.11.24 +*/ +RESET_TYPE +rtl819x_ifcheck_resetornot(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + RESET_TYPE TxResetType = RESET_TYPE_NORESET; + RESET_TYPE RxResetType = RESET_TYPE_NORESET; + RT_RF_POWER_STATE rfState; + + rfState = priv->ieee80211->eRFPowerState; + + TxResetType = TxCheckStuck(dev); + if( rfState != eRfOff || + /*ADAPTER_TEST_STATUS_FLAG(Adapter, ADAPTER_STATUS_FW_DOWNLOAD_FAILURE)) &&*/ + (priv->ieee80211->iw_mode != IW_MODE_ADHOC)) + { + // If driver is in the status of firmware download failure , driver skips RF initialization and RF is + // in turned off state. Driver should check whether Rx stuck and do silent reset. And + // if driver is in firmware download failure status, driver should initialize RF in the following + // silent reset procedure Emily, 2008.01.21 + + // Driver should not check RX stuck in IBSS mode because it is required to + // set Check BSSID in order to send beacon, however, if check BSSID is + // set, STA cannot hear any packet a all. Emily, 2008.04.12 + RxResetType = RxCheckStuck(dev); + } + if(TxResetType==RESET_TYPE_NORMAL || RxResetType==RESET_TYPE_NORMAL) + return RESET_TYPE_NORMAL; + else if(TxResetType==RESET_TYPE_SILENT || RxResetType==RESET_TYPE_SILENT){ + RT_TRACE(COMP_RESET,"%s():silent reset\n",__FUNCTION__); + return RESET_TYPE_SILENT; + } + else + return RESET_TYPE_NORESET; + +} + +void rtl8192_cancel_deferred_work(struct r8192_priv* priv); +int _rtl8192_up(struct net_device *dev); +int rtl8192_close(struct net_device *dev); + + + +void +CamRestoreAllEntry( struct net_device *dev) +{ + u8 EntryId = 0; + struct r8192_priv *priv = ieee80211_priv(dev); + u8* MacAddr = priv->ieee80211->current_network.bssid; + + static u8 CAM_CONST_ADDR[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}}; + static u8 CAM_CONST_BROAD[] = + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n"); + + + if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40)|| + (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104)) + { + + for(EntryId=0; EntryId<4; EntryId++) + { + { + MacAddr = CAM_CONST_ADDR[EntryId]; + setKey(dev, + EntryId , + EntryId, + priv->ieee80211->pairwise_key_type, + MacAddr, + 0, + NULL); + } + } + + } + else if(priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP) + { + + { + if(priv->ieee80211->iw_mode == IW_MODE_ADHOC) + setKey(dev, + 4, + 0, + priv->ieee80211->pairwise_key_type, + (u8*)dev->dev_addr, + 0, + NULL); + else + setKey(dev, + 4, + 0, + priv->ieee80211->pairwise_key_type, + MacAddr, + 0, + NULL); + } + } + else if(priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP) + { + + { + if(priv->ieee80211->iw_mode == IW_MODE_ADHOC) + setKey(dev, + 4, + 0, + priv->ieee80211->pairwise_key_type, + (u8*)dev->dev_addr, + 0, + NULL); + else + setKey(dev, + 4, + 0, + priv->ieee80211->pairwise_key_type, + MacAddr, + 0, + NULL); + } + } + + + + if(priv->ieee80211->group_key_type == KEY_TYPE_TKIP) + { + MacAddr = CAM_CONST_BROAD; + for(EntryId=1 ; EntryId<4 ; EntryId++) + { + { + setKey(dev, + EntryId, + EntryId, + priv->ieee80211->group_key_type, + MacAddr, + 0, + NULL); + } + } + if(priv->ieee80211->iw_mode == IW_MODE_ADHOC) + setKey(dev, + 0, + 0, + priv->ieee80211->group_key_type, + CAM_CONST_ADDR[0], + 0, + NULL); + } + else if(priv->ieee80211->group_key_type == KEY_TYPE_CCMP) + { + MacAddr = CAM_CONST_BROAD; + for(EntryId=1; EntryId<4 ; EntryId++) + { + { + setKey(dev, + EntryId , + EntryId, + priv->ieee80211->group_key_type, + MacAddr, + 0, + NULL); + } + } + + if(priv->ieee80211->iw_mode == IW_MODE_ADHOC) + setKey(dev, + 0 , + 0, + priv->ieee80211->group_key_type, + CAM_CONST_ADDR[0], + 0, + NULL); + } +} +////////////////////////////////////////////////////////////// +// This function is used to fix Tx/Rx stop bug temporarily. +// This function will do "system reset" to NIC when Tx or Rx is stuck. +// The method checking Tx/Rx stuck of this function is supported by FW, +// which reports Tx and Rx counter to register 0x128 and 0x130. +////////////////////////////////////////////////////////////// +void +rtl819x_ifsilentreset(struct net_device *dev) +{ + //OCTET_STRING asocpdu; + struct r8192_priv *priv = ieee80211_priv(dev); + u8 reset_times = 0; + int reset_status = 0; + struct ieee80211_device *ieee = priv->ieee80211; + + + // 2007.07.20. If we need to check CCK stop, please uncomment this line. + //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter); + + if(priv->ResetProgress==RESET_TYPE_NORESET) + { +RESET_START: + + RT_TRACE(COMP_RESET,"=========>Reset progress!! \n"); + + // Set the variable for reset. + priv->ResetProgress = RESET_TYPE_SILENT; +// rtl8192_close(dev); + down(&priv->wx_sem); + if(priv->up == 0) + { + RT_TRACE(COMP_ERR,"%s():the driver is not up! return\n",__FUNCTION__); + up(&priv->wx_sem); + return ; + } + priv->up = 0; + RT_TRACE(COMP_RESET,"%s():======>start to down the driver\n",__FUNCTION__); +// if(!netif_queue_stopped(dev)) +// netif_stop_queue(dev); + + rtl8192_rtx_disable(dev); + rtl8192_cancel_deferred_work(priv); + deinit_hal_dm(dev); + del_timer_sync(&priv->watch_dog_timer); + + ieee->sync_scan_hurryup = 1; + if(ieee->state == IEEE80211_LINKED) + { + down(&ieee->wx_sem); + printk("ieee->state is IEEE80211_LINKED\n"); + ieee80211_stop_send_beacons(priv->ieee80211); + del_timer_sync(&ieee->associate_timer); + cancel_delayed_work(&ieee->associate_retry_wq); + ieee80211_stop_scan(ieee); + netif_carrier_off(dev); + up(&ieee->wx_sem); + } + else{ + printk("ieee->state is NOT LINKED\n"); + ieee80211_softmac_stop_protocol(priv->ieee80211); } + up(&priv->wx_sem); + RT_TRACE(COMP_RESET,"%s():<==========down process is finished\n",__FUNCTION__); + //rtl8192_irq_disable(dev); + RT_TRACE(COMP_RESET,"%s():===========>start to up the driver\n",__FUNCTION__); + reset_status = _rtl8192_up(dev); + + RT_TRACE(COMP_RESET,"%s():<===========up process is finished\n",__FUNCTION__); + if(reset_status == -EAGAIN) + { + if(reset_times < 3) + { + reset_times++; + goto RESET_START; + } + else + { + RT_TRACE(COMP_ERR," ERR!!! %s(): Reset Failed!!\n", __FUNCTION__); + } + } + ieee->is_silent_reset = 1; + EnableHWSecurityConfig8192(dev); + if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA) + { + ieee->set_chan(ieee->dev, ieee->current_network.channel); + + queue_work(ieee->wq, &ieee->associate_complete_wq); + + } + else if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC) + { + ieee->set_chan(ieee->dev, ieee->current_network.channel); + ieee->link_change(ieee->dev); + + // notify_wx_assoc_event(ieee); + + ieee80211_start_send_beacons(ieee); + + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + netif_carrier_on(ieee->dev); + } + + CamRestoreAllEntry(dev); + + priv->ResetProgress = RESET_TYPE_NORESET; + priv->reset_count++; + + priv->bForcedSilentReset =false; + priv->bResetInProgress = false; + + // For test --> force write UFWP. + write_nic_byte(dev, UFWP, 1); + RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count); + } +} + +void CAM_read_entry( + struct net_device *dev, + u32 iIndex +) +{ + u32 target_command=0; + u32 target_content=0; + u8 entry_i=0; + u32 ulStatus; + s32 i=100; +// printk("=======>start read CAM\n"); + for(entry_i=0;entry_i=0) + { + ulStatus = read_nic_dword(dev, RWCAM); + if(ulStatus & BIT31){ + continue; + } + else{ + break; + } + } + write_nic_dword(dev, RWCAM, target_command); + RT_TRACE(COMP_SEC,"CAM_read_entry(): WRITE A0: %x \n",target_command); + // printk("CAM_read_entry(): WRITE A0: %lx \n",target_command); + target_content = read_nic_dword(dev, RCAMO); + RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n",target_content); + // printk("CAM_read_entry(): WRITE A8: %lx \n",target_content); + } + printk("\n"); +} + +void rtl819x_update_rxcounts( + struct r8192_priv *priv, + u32* TotalRxBcnNum, + u32* TotalRxDataNum +) +{ + u16 SlotIndex; + u8 i; + + *TotalRxBcnNum = 0; + *TotalRxDataNum = 0; + + SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum); + priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod; + priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod; + for( i=0; iieee80211->LinkDetectInfo.SlotNum; i++ ){ + *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i]; + *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i]; + } +} + + +extern void rtl819x_watchdog_wqcallback(struct work_struct *work) +{ + struct delayed_work *dwork = container_of(work,struct delayed_work,work); + struct r8192_priv *priv = container_of(dwork,struct r8192_priv,watch_dog_wq); + struct net_device *dev = priv->ieee80211->dev; + struct ieee80211_device* ieee = priv->ieee80211; + RESET_TYPE ResetType = RESET_TYPE_NORESET; + static u8 check_reset_cnt=0; + bool bBusyTraffic = false; + + if(!priv->up) + return; + hal_dm_watchdog(dev); + + {//to get busy traffic condition + if(ieee->state == IEEE80211_LINKED) + { + if( ieee->LinkDetectInfo.NumRxOkInPeriod> 666 || + ieee->LinkDetectInfo.NumTxOkInPeriod> 666 ) { + bBusyTraffic = true; + } + ieee->LinkDetectInfo.NumRxOkInPeriod = 0; + ieee->LinkDetectInfo.NumTxOkInPeriod = 0; + ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic; + } + } + //added by amy for AP roaming + { + if(priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->iw_mode == IW_MODE_INFRA) + { + u32 TotalRxBcnNum = 0; + u32 TotalRxDataNum = 0; + + rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum); + if((TotalRxBcnNum+TotalRxDataNum) == 0) + { + #ifdef TODO + if(rfState == eRfOff) + RT_TRACE(COMP_ERR,"========>%s()\n",__FUNCTION__); + #endif + printk("===>%s(): AP is power off,connect another one\n",__FUNCTION__); + // Dot11d_Reset(dev); + priv->ieee80211->state = IEEE80211_ASSOCIATING; + notify_wx_assoc_event(priv->ieee80211); + RemovePeerTS(priv->ieee80211,priv->ieee80211->current_network.bssid); + priv->ieee80211->link_change(dev); + queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq); + + } + } + priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod=0; + priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod=0; + } +// CAM_read_entry(dev,4); + //check if reset the driver + if(check_reset_cnt++ >= 3) + { + ResetType = rtl819x_ifcheck_resetornot(dev); + check_reset_cnt = 3; + //DbgPrint("Start to check silent reset\n"); + } + // RT_TRACE(COMP_RESET,"%s():priv->force_reset is %d,priv->ResetProgress is %d, priv->bForcedSilentReset is %d,priv->bDisableNormalResetCheck is %d,ResetType is %d\n",__FUNCTION__,priv->force_reset,priv->ResetProgress,priv->bForcedSilentReset,priv->bDisableNormalResetCheck,ResetType); + if( (priv->force_reset) || (priv->ResetProgress==RESET_TYPE_NORESET && + (priv->bForcedSilentReset || + (!priv->bDisableNormalResetCheck && ResetType==RESET_TYPE_SILENT)))) // This is control by OID set in Pomelo + { + RT_TRACE(COMP_RESET,"%s():priv->force_reset is %d,priv->ResetProgress is %d, priv->bForcedSilentReset is %d,priv->bDisableNormalResetCheck is %d,ResetType is %d\n",__FUNCTION__,priv->force_reset,priv->ResetProgress,priv->bForcedSilentReset,priv->bDisableNormalResetCheck,ResetType); + rtl819x_ifsilentreset(dev); + } + priv->force_reset = false; + priv->bForcedSilentReset = false; + priv->bResetInProgress = false; + RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n"); + +} + +void watch_dog_timer_callback(unsigned long data) +{ + struct r8192_priv *priv = ieee80211_priv((struct net_device *) data); + //printk("===============>watch_dog timer\n"); + queue_delayed_work(priv->priv_wq,&priv->watch_dog_wq, 0); + mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME)); +} +int _rtl8192_up(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + //int i; + int init_status = 0; + priv->up=1; + priv->ieee80211->ieee_up=1; + RT_TRACE(COMP_INIT, "Bringing up iface"); + init_status = rtl8192_adapter_start(dev); + if(!init_status) + { + RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n", __FUNCTION__); + priv->up=priv->ieee80211->ieee_up = 0; + return -EAGAIN; + } + RT_TRACE(COMP_INIT, "start adapter finished\n"); + rtl8192_rx_enable(dev); +// rtl8192_tx_enable(dev); + if(priv->ieee80211->state != IEEE80211_LINKED) + ieee80211_softmac_start_protocol(priv->ieee80211); + ieee80211_reset_queue(priv->ieee80211); + watch_dog_timer_callback((unsigned long) dev); + if(!netif_queue_stopped(dev)) + netif_start_queue(dev); + else + netif_wake_queue(dev); + + return 0; +} + + +int rtl8192_open(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + int ret; + down(&priv->wx_sem); + ret = rtl8192_up(dev); + up(&priv->wx_sem); + return ret; + +} + + +int rtl8192_up(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + if (priv->up == 1) return -1; + + return _rtl8192_up(dev); +} + + +int rtl8192_close(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + int ret; + + down(&priv->wx_sem); + + ret = rtl8192_down(dev); + + up(&priv->wx_sem); + + return ret; + +} + +int rtl8192_down(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + int i; + + if (priv->up == 0) return -1; + + priv->up=0; + priv->ieee80211->ieee_up = 0; + RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__); +/* FIXME */ + if (!netif_queue_stopped(dev)) + netif_stop_queue(dev); + + rtl8192_rtx_disable(dev); + //rtl8192_irq_disable(dev); + + /* Tx related queue release */ + for(i = 0; i < MAX_QUEUE_SIZE; i++) { + skb_queue_purge(&priv->ieee80211->skb_waitQ [i]); + } + for(i = 0; i < MAX_QUEUE_SIZE; i++) { + skb_queue_purge(&priv->ieee80211->skb_aggQ [i]); + } + + for(i = 0; i < MAX_QUEUE_SIZE; i++) { + skb_queue_purge(&priv->ieee80211->skb_drv_aggQ [i]); + } + + //as cancel_delayed_work will del work->timer, so if work is not definedas struct delayed_work, it will corrupt +// flush_scheduled_work(); + rtl8192_cancel_deferred_work(priv); + deinit_hal_dm(dev); + del_timer_sync(&priv->watch_dog_timer); + + + ieee80211_softmac_stop_protocol(priv->ieee80211); + memset(&priv->ieee80211->current_network, 0 , offsetof(struct ieee80211_network, list)); + RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__); + + return 0; +} + + +void rtl8192_commit(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + int reset_status = 0; + //u8 reset_times = 0; + if (priv->up == 0) return ; + priv->up = 0; + + rtl8192_cancel_deferred_work(priv); + del_timer_sync(&priv->watch_dog_timer); + //cancel_delayed_work(&priv->SwChnlWorkItem); + + ieee80211_softmac_stop_protocol(priv->ieee80211); + + //rtl8192_irq_disable(dev); + rtl8192_rtx_disable(dev); + reset_status = _rtl8192_up(dev); + +} + +/* +void rtl8192_restart(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); +*/ +void rtl8192_restart(struct work_struct *work) +{ + struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq); + struct net_device *dev = priv->ieee80211->dev; + + down(&priv->wx_sem); + + rtl8192_commit(dev); + + up(&priv->wx_sem); +} + +static void r8192_set_multicast(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + short promisc; + + //down(&priv->wx_sem); + + /* FIXME FIXME */ + + promisc = (dev->flags & IFF_PROMISC) ? 1:0; + + if (promisc != priv->promisc) + // rtl8192_commit(dev); + + priv->promisc = promisc; + + //schedule_work(&priv->reset_wq); + //up(&priv->wx_sem); +} + + +int r8192_set_mac_adr(struct net_device *dev, void *mac) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + struct sockaddr *addr = mac; + + down(&priv->wx_sem); + + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + + schedule_work(&priv->reset_wq); + up(&priv->wx_sem); + + return 0; +} + +/* based on ipw2200 driver */ +int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + struct iwreq *wrq = (struct iwreq *)rq; + int ret=-1; + struct ieee80211_device *ieee = priv->ieee80211; + u32 key[4]; + u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + struct iw_point *p = &wrq->u.data; + struct ieee_param *ipw = NULL;//(struct ieee_param *)wrq->u.data.pointer; + + down(&priv->wx_sem); + + + if (p->length < sizeof(struct ieee_param) || !p->pointer){ + ret = -EINVAL; + goto out; + } + + ipw = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL); + if (ipw == NULL){ + ret = -ENOMEM; + goto out; + } + if (copy_from_user(ipw, p->pointer, p->length)) { + kfree(ipw); + ret = -EFAULT; + goto out; + } + + switch (cmd) { + case RTL_IOCTL_WPA_SUPPLICANT: + //parse here for HW security + if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION) + { + if (ipw->u.crypt.set_tx) + { + if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) + ieee->pairwise_key_type = KEY_TYPE_CCMP; + else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) + ieee->pairwise_key_type = KEY_TYPE_TKIP; + else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) + { + if (ipw->u.crypt.key_len == 13) + ieee->pairwise_key_type = KEY_TYPE_WEP104; + else if (ipw->u.crypt.key_len == 5) + ieee->pairwise_key_type = KEY_TYPE_WEP40; + } + else + ieee->pairwise_key_type = KEY_TYPE_NA; + + if (ieee->pairwise_key_type) + { + memcpy((u8*)key, ipw->u.crypt.key, 16); + EnableHWSecurityConfig8192(dev); + //we fill both index entry and 4th entry for pairwise key as in IPW interface, adhoc will only get here, so we need index entry for its default key serching! + //added by WB. + setKey(dev, 4, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key); + if (ieee->auth_mode != 2) + setKey(dev, ipw->u.crypt.idx, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key); + } + } + else //if (ipw->u.crypt.idx) //group key use idx > 0 + { + memcpy((u8*)key, ipw->u.crypt.key, 16); + if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) + ieee->group_key_type= KEY_TYPE_CCMP; + else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) + ieee->group_key_type = KEY_TYPE_TKIP; + else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) + { + if (ipw->u.crypt.key_len == 13) + ieee->group_key_type = KEY_TYPE_WEP104; + else if (ipw->u.crypt.key_len == 5) + ieee->group_key_type = KEY_TYPE_WEP40; + } + else + ieee->group_key_type = KEY_TYPE_NA; + + if (ieee->group_key_type) + { + setKey( dev, + ipw->u.crypt.idx, + ipw->u.crypt.idx, //KeyIndex + ieee->group_key_type, //KeyType + broadcast_addr, //MacAddr + 0, //DefaultKey + key); //KeyContent + } + } + } +#ifdef JOHN_HWSEC_DEBUG + //john's test 0711 + printk("@@ wrq->u pointer = "); + for(i=0;iu.data.length;i++){ + if(i%10==0) printk("\n"); + printk( "%8x|", ((u32*)wrq->u.data.pointer)[i] ); + } + printk("\n"); +#endif /*JOHN_HWSEC_DEBUG*/ + ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data); + break; + + default: + ret = -EOPNOTSUPP; + break; + } + kfree(ipw); + ipw = NULL; +out: + up(&priv->wx_sem); + return ret; +} + +u8 HwRateToMRate90(bool bIsHT, u8 rate) +{ + u8 ret_rate = 0xff; + + if(!bIsHT) { + switch(rate) { + case DESC90_RATE1M: ret_rate = MGN_1M; break; + case DESC90_RATE2M: ret_rate = MGN_2M; break; + case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break; + case DESC90_RATE11M: ret_rate = MGN_11M; break; + case DESC90_RATE6M: ret_rate = MGN_6M; break; + case DESC90_RATE9M: ret_rate = MGN_9M; break; + case DESC90_RATE12M: ret_rate = MGN_12M; break; + case DESC90_RATE18M: ret_rate = MGN_18M; break; + case DESC90_RATE24M: ret_rate = MGN_24M; break; + case DESC90_RATE36M: ret_rate = MGN_36M; break; + case DESC90_RATE48M: ret_rate = MGN_48M; break; + case DESC90_RATE54M: ret_rate = MGN_54M; break; + + default: + ret_rate = 0xff; + RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT); + break; + } + + } else { + switch(rate) { + case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break; + case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break; + case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break; + case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break; + case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break; + case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break; + case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break; + case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break; + case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break; + case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break; + case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break; + case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break; + case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break; + case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break; + case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break; + case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break; + case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break; + + default: + ret_rate = 0xff; + RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n",rate, bIsHT); + break; + } + } + + return ret_rate; +} + +/** + * Function: UpdateRxPktTimeStamp + * Overview: Recored down the TSF time stamp when receiving a packet + * + * Input: + * PADAPTER Adapter + * PRT_RFD pRfd, + * + * Output: + * PRT_RFD pRfd + * (pRfd->Status.TimeStampHigh is updated) + * (pRfd->Status.TimeStampLow is updated) + * Return: + * None + */ +void UpdateRxPktTimeStamp8190 (struct net_device *dev, struct ieee80211_rx_stats *stats) +{ + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + + if(stats->bIsAMPDU && !stats->bFirstMPDU) { + stats->mac_time[0] = priv->LastRxDescTSFLow; + stats->mac_time[1] = priv->LastRxDescTSFHigh; + } else { + priv->LastRxDescTSFLow = stats->mac_time[0]; + priv->LastRxDescTSFHigh = stats->mac_time[1]; + } +} + +//by amy 080606 + +long rtl819x_translate_todbm(u8 signal_strength_index )// 0-100 index. +{ + long signal_power; // in dBm. + + // Translate to dBm (x=0.5y-95). + signal_power = (long)((signal_strength_index + 1) >> 1); + signal_power -= 95; + + return signal_power; +} + + +/* 2008/01/22 MH We can not delcare RSSI/EVM total value of sliding window to + be a local static. Otherwise, it may increase when we return from S3/S4. The + value will be kept in memory or disk. We must delcare the value in adapter + and it will be reinitialized when return from S3/S4. */ +void rtl8192_process_phyinfo(struct r8192_priv * priv,u8* buffer, struct ieee80211_rx_stats * pprevious_stats, struct ieee80211_rx_stats * pcurrent_stats) +{ + bool bcheck = false; + u8 rfpath; + u32 nspatial_stream, tmp_val; + //u8 i; + static u32 slide_rssi_index=0, slide_rssi_statistics=0; + static u32 slide_evm_index=0, slide_evm_statistics=0; + static u32 last_rssi=0, last_evm=0; + + static u32 slide_beacon_adc_pwdb_index=0, slide_beacon_adc_pwdb_statistics=0; + static u32 last_beacon_adc_pwdb=0; + + struct ieee80211_hdr_3addr *hdr; + u16 sc ; + unsigned int frag,seq; + hdr = (struct ieee80211_hdr_3addr *)buffer; + sc = le16_to_cpu(hdr->seq_ctl); + frag = WLAN_GET_SEQ_FRAG(sc); + seq = WLAN_GET_SEQ_SEQ(sc); + //cosa add 04292008 to record the sequence number + pcurrent_stats->Seq_Num = seq; + // + // Check whether we should take the previous packet into accounting + // + if(!pprevious_stats->bIsAMPDU) + { + // if previous packet is not aggregated packet + bcheck = true; + }else + { + } + + + if(slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX) + { + slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX; + last_rssi = priv->stats.slide_signal_strength[slide_rssi_index]; + priv->stats.slide_rssi_total -= last_rssi; + } + priv->stats.slide_rssi_total += pprevious_stats->SignalStrength; + + priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength; + if(slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX) + slide_rssi_index = 0; + + // <1> Showed on UI for user, in dbm + tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics; + priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val); + pcurrent_stats->rssi = priv->stats.signal_strength; + // + // If the previous packet does not match the criteria, neglect it + // + if(!pprevious_stats->bPacketMatchBSSID) + { + if(!pprevious_stats->bToSelfBA) + return; + } + + if(!bcheck) + return; + + + //rtl8190_process_cck_rxpathsel(priv,pprevious_stats);//only rtl8190 supported + + // + // Check RSSI + // + priv->stats.num_process_phyinfo++; + + /* record the general signal strength to the sliding window. */ + + + // <2> Showed on UI for engineering + // hardware does not provide rssi information for each rf path in CCK + if(!pprevious_stats->bIsCCK && (pprevious_stats->bPacketToSelf || pprevious_stats->bToSelfBA)) + { + for (rfpath = RF90_PATH_A; rfpath < priv->NumTotalRFPath; rfpath++) + { + if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath)) + continue; + + //Fixed by Jacken 2008-03-20 + if(priv->stats.rx_rssi_percentage[rfpath] == 0) + { + priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath]; + //DbgPrint("MIMO RSSI initialize \n"); + } + if(pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath]) + { + priv->stats.rx_rssi_percentage[rfpath] = + ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) + + (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor); + priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1; + } + else + { + priv->stats.rx_rssi_percentage[rfpath] = + ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) + + (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor); + } + RT_TRACE(COMP_DBG,"priv->stats.rx_rssi_percentage[rfPath] = %d \n" ,priv->stats.rx_rssi_percentage[rfpath] ); + } + } + + + // + // Check PWDB. + // + RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n", + pprevious_stats->bIsCCK? "CCK": "OFDM", + pprevious_stats->RxPWDBAll); + + if(pprevious_stats->bPacketBeacon) + { +/* record the beacon pwdb to the sliding window. */ + if(slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX) + { + slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX; + last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index]; + priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb; + //DbgPrint("slide_beacon_adc_pwdb_index = %d, last_beacon_adc_pwdb = %d, Adapter->RxStats.Slide_Beacon_Total = %d\n", + // slide_beacon_adc_pwdb_index, last_beacon_adc_pwdb, Adapter->RxStats.Slide_Beacon_Total); + } + priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll; + priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll; + //DbgPrint("slide_beacon_adc_pwdb_index = %d, pPreviousRfd->Status.RxPWDBAll = %d\n", slide_beacon_adc_pwdb_index, pPreviousRfd->Status.RxPWDBAll); + slide_beacon_adc_pwdb_index++; + if(slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX) + slide_beacon_adc_pwdb_index = 0; + pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics; + if(pprevious_stats->RxPWDBAll >= 3) + pprevious_stats->RxPWDBAll -= 3; + } + + RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n", + pprevious_stats->bIsCCK? "CCK": "OFDM", + pprevious_stats->RxPWDBAll); + + + if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) + { + if(priv->undecorated_smoothed_pwdb < 0) // initialize + { + priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll; + //DbgPrint("First pwdb initialize \n"); + } + if(pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) + { + priv->undecorated_smoothed_pwdb = + ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) + + (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor); + priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1; + } + else + { + priv->undecorated_smoothed_pwdb = + ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) + + (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor); + } + + } + + // + // Check EVM + // + /* record the general EVM to the sliding window. */ + if(pprevious_stats->SignalQuality == 0) + { + } + else + { + if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA){ + if(slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX){ + slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX; + last_evm = priv->stats.slide_evm[slide_evm_index]; + priv->stats.slide_evm_total -= last_evm; + } + + priv->stats.slide_evm_total += pprevious_stats->SignalQuality; + + priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality; + if(slide_evm_index >= PHY_RSSI_SLID_WIN_MAX) + slide_evm_index = 0; + + // <1> Showed on UI for user, in percentage. + tmp_val = priv->stats.slide_evm_total/slide_evm_statistics; + priv->stats.signal_quality = tmp_val; + //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality. + priv->stats.last_signal_strength_inpercent = tmp_val; + } + + // <2> Showed on UI for engineering + if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) + { + for(nspatial_stream = 0; nspatial_stream<2 ; nspatial_stream++) // 2 spatial stream + { + if(pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1) + { + if(priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize + { + priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream]; + } + priv->stats.rx_evm_percentage[nspatial_stream] = + ( (priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) + + (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor); + } + } + } + } + + +} + +/*----------------------------------------------------------------------------- + * Function: rtl819x_query_rxpwrpercentage() + * + * Overview: + * + * Input: char antpower + * + * Output: NONE + * + * Return: 0-100 percentage + * + * Revised History: + * When Who Remark + * 05/26/2008 amy Create Version 0 porting from windows code. + * + *---------------------------------------------------------------------------*/ +static u8 rtl819x_query_rxpwrpercentage( + char antpower + ) +{ + if ((antpower <= -100) || (antpower >= 20)) + { + return 0; + } + else if (antpower >= 0) + { + return 100; + } + else + { + return (100+antpower); + } + +} /* QueryRxPwrPercentage */ + +static u8 +rtl819x_evm_dbtopercentage( + char value + ) +{ + char ret_val; + + ret_val = value; + + if(ret_val >= 0) + ret_val = 0; + if(ret_val <= -33) + ret_val = -33; + ret_val = 0 - ret_val; + ret_val*=3; + if(ret_val == 99) + ret_val = 100; + return(ret_val); +} +// +// Description: +// We want good-looking for signal strength/quality +// 2007/7/19 01:09, by cosa. +// +long +rtl819x_signal_scale_mapping( + long currsig + ) +{ + long retsig; + + // Step 1. Scale mapping. + if(currsig >= 61 && currsig <= 100) + { + retsig = 90 + ((currsig - 60) / 4); + } + else if(currsig >= 41 && currsig <= 60) + { + retsig = 78 + ((currsig - 40) / 2); + } + else if(currsig >= 31 && currsig <= 40) + { + retsig = 66 + (currsig - 30); + } + else if(currsig >= 21 && currsig <= 30) + { + retsig = 54 + (currsig - 20); + } + else if(currsig >= 5 && currsig <= 20) + { + retsig = 42 + (((currsig - 5) * 2) / 3); + } + else if(currsig == 4) + { + retsig = 36; + } + else if(currsig == 3) + { + retsig = 27; + } + else if(currsig == 2) + { + retsig = 18; + } + else if(currsig == 1) + { + retsig = 9; + } + else + { + retsig = currsig; + } + + return retsig; +} + +static void rtl8192_query_rxphystatus( + struct r8192_priv * priv, + struct ieee80211_rx_stats * pstats, + rx_drvinfo_819x_usb * pdrvinfo, + struct ieee80211_rx_stats * precord_stats, + bool bpacket_match_bssid, + bool bpacket_toself, + bool bPacketBeacon, + bool bToSelfBA + ) +{ + //PRT_RFD_STATUS pRtRfdStatus = &(pRfd->Status); + phy_sts_ofdm_819xusb_t* pofdm_buf; + phy_sts_cck_819xusb_t * pcck_buf; + phy_ofdm_rx_status_rxsc_sgien_exintfflag* prxsc; + u8 *prxpkt; + u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg; + char rx_pwr[4], rx_pwr_all=0; + //long rx_avg_pwr = 0; + char rx_snrX, rx_evmX; + u8 evm, pwdb_all; + u32 RSSI, total_rssi=0;//, total_evm=0; +// long signal_strength_index = 0; + u8 is_cck_rate=0; + u8 rf_rx_num = 0; + + + priv->stats.numqry_phystatus++; + + is_cck_rate = rx_hal_is_cck_rate(pdrvinfo); + + // Record it for next packet processing + memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats)); + pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid; + pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself; + pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;//RX_HAL_IS_CCK_RATE(pDrvInfo); + pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon; + pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA; + + prxpkt = (u8*)pdrvinfo; + + /* Move pointer to the 16th bytes. Phy status start address. */ + prxpkt += sizeof(rx_drvinfo_819x_usb); + + /* Initial the cck and ofdm buffer pointer */ + pcck_buf = (phy_sts_cck_819xusb_t *)prxpkt; + pofdm_buf = (phy_sts_ofdm_819xusb_t *)prxpkt; + + pstats->RxMIMOSignalQuality[0] = -1; + pstats->RxMIMOSignalQuality[1] = -1; + precord_stats->RxMIMOSignalQuality[0] = -1; + precord_stats->RxMIMOSignalQuality[1] = -1; + + if(is_cck_rate) + { + // + // (1)Hardware does not provide RSSI for CCK + // + + // + // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) + // + u8 report;//, cck_agc_rpt; + + priv->stats.numqry_phystatusCCK++; + + if(!priv->bCckHighPower) + { + report = pcck_buf->cck_agc_rpt & 0xc0; + report = report>>6; + switch(report) + { + //Fixed by Jacken from Bryant 2008-03-20 + //Original value is -38 , -26 , -14 , -2 + //Fixed value is -35 , -23 , -11 , 6 + case 0x3: + rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e); + break; + case 0x2: + rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e); + break; + case 0x1: + rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e); + break; + case 0x0: + rx_pwr_all = 6 - (pcck_buf->cck_agc_rpt & 0x3e); + break; + } + } + else + { + report = pcck_buf->cck_agc_rpt & 0x60; + report = report>>5; + switch(report) + { + case 0x3: + rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ; + break; + case 0x2: + rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1); + break; + case 0x1: + rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ; + break; + case 0x0: + rx_pwr_all = 6 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ; + break; + } + } + + pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all); + pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all; + pstats->RecvSignalPower = pwdb_all; + + // + // (3) Get Signal Quality (EVM) + // + //if(bpacket_match_bssid) + { + u8 sq; + + if(pstats->RxPWDBAll > 40) + { + sq = 100; + }else + { + sq = pcck_buf->sq_rpt; + + if(pcck_buf->sq_rpt > 64) + sq = 0; + else if (pcck_buf->sq_rpt < 20) + sq = 100; + else + sq = ((64-sq) * 100) / 44; + } + pstats->SignalQuality = precord_stats->SignalQuality = sq; + pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq; + pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1; + } + } + else + { + priv->stats.numqry_phystatusHT++; + // + // (1)Get RSSI for HT rate + // + for(i=RF90_PATH_A; iNumTotalRFPath; i++) + { + // 2008/01/30 MH we will judge RF RX path now. + if (priv->brfpath_rxenable[i]) + rf_rx_num++; + else + continue; + + if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, i)) + continue; + + //Fixed by Jacken from Bryant 2008-03-20 + //Original value is 106 + rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106; + + //Get Rx snr value in DB + tmp_rxsnr = pofdm_buf->rxsnr_X[i]; + rx_snrX = (char)(tmp_rxsnr); + //rx_snrX >>= 1;; + rx_snrX /= 2; + priv->stats.rxSNRdB[i] = (long)rx_snrX; + + /* Translate DBM to percentage. */ + RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]); + total_rssi += RSSI; + + /* Record Signal Strength for next packet */ + //if(bpacket_match_bssid) + { + pstats->RxMIMOSignalStrength[i] =(u8) RSSI; + precord_stats->RxMIMOSignalStrength[i] =(u8) RSSI; + } + } + + + // + // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) + // + //Fixed by Jacken from Bryant 2008-03-20 + //Original value is 106 + rx_pwr_all = (((pofdm_buf->pwdb_all ) >> 1 )& 0x7f) -106; + pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all); + + pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all; + pstats->RxPower = precord_stats->RxPower = rx_pwr_all; + + // + // (3)EVM of HT rate + // + if(pdrvinfo->RxHT && pdrvinfo->RxRate>=DESC90_RATEMCS8 && + pdrvinfo->RxRate<=DESC90_RATEMCS15) + max_spatial_stream = 2; //both spatial stream make sense + else + max_spatial_stream = 1; //only spatial stream 1 makes sense + + for(i=0; irxevm_X[i]; + rx_evmX = (char)(tmp_rxevm); + + // Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment + // fill most significant bit to "zero" when doing shifting operation which may change a negative + // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore. + rx_evmX /= 2; //dbm + + evm = rtl819x_evm_dbtopercentage(rx_evmX); + //if(bpacket_match_bssid) + { + if(i==0) // Fill value in RFD, Get the first spatial stream only + pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff); + pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff); + } + } + + + /* record rx statistics for debug */ + rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg; + prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg; + if(pdrvinfo->BW) //40M channel + priv->stats.received_bwtype[1+prxsc->rxsc]++; + else //20M channel + priv->stats.received_bwtype[0]++; + } + + //UI BSS List signal strength(in percentage), make it good looking, from 0~100. + //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). + if(is_cck_rate) + { + pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));//PWDB_ALL; + + } + else + { + //pRfd->Status.SignalStrength = pRecordRfd->Status.SignalStrength = (u8)(SignalScaleMapping(total_rssi/=RF90_PATH_MAX));//(u8)(total_rssi/=RF90_PATH_MAX); + // We can judge RX path number now. + if (rf_rx_num != 0) + pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi/=rf_rx_num))); + } +} /* QueryRxPhyStatus8190Pci */ + +void +rtl8192_record_rxdesc_forlateruse( + struct ieee80211_rx_stats * psrc_stats, + struct ieee80211_rx_stats * ptarget_stats +) +{ + ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU; + ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU; + ptarget_stats->Seq_Num = psrc_stats->Seq_Num; +} + + +void TranslateRxSignalStuff819xUsb(struct sk_buff *skb, + struct ieee80211_rx_stats * pstats, + rx_drvinfo_819x_usb *pdrvinfo) +{ + // TODO: We must only check packet for current MAC address. Not finish + rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb; + struct net_device *dev=info->dev; + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + bool bpacket_match_bssid, bpacket_toself; + bool bPacketBeacon=FALSE, bToSelfBA=FALSE; + static struct ieee80211_rx_stats previous_stats; + struct ieee80211_hdr_3addr *hdr;//by amy + u16 fc,type; + + // Get Signal Quality for only RX data queue (but not command queue) + + u8* tmp_buf; + //u16 tmp_buf_len = 0; + u8 *praddr; + + /* Get MAC frame start address. */ + tmp_buf = (u8*)skb->data;// + get_rxpacket_shiftbytes_819xusb(pstats); + + hdr = (struct ieee80211_hdr_3addr *)tmp_buf; + fc = le16_to_cpu(hdr->frame_ctl); + type = WLAN_FC_GET_TYPE(fc); + praddr = hdr->addr1; + + /* Check if the received packet is acceptabe. */ + bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) && + (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS)? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS )? hdr->addr2 : hdr->addr3)) + && (!pstats->bHwError) && (!pstats->bCRC)&& (!pstats->bICV)); + bpacket_toself = bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr)); + + if(WLAN_FC_GET_FRAMETYPE(fc)== IEEE80211_STYPE_BEACON) + { + bPacketBeacon = true; + //DbgPrint("Beacon 2, MatchBSSID = %d, ToSelf = %d \n", bPacketMatchBSSID, bPacketToSelf); + } + if(WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK) + { + if((eqMacAddr(praddr,dev->dev_addr))) + bToSelfBA = true; + //DbgPrint("BlockAck, MatchBSSID = %d, ToSelf = %d \n", bPacketMatchBSSID, bPacketToSelf); + } + + + + if(bpacket_match_bssid) + { + priv->stats.numpacket_matchbssid++; + } + if(bpacket_toself){ + priv->stats.numpacket_toself++; + } + // + // Process PHY information for previous packet (RSSI/PWDB/EVM) + // + // Because phy information is contained in the last packet of AMPDU only, so driver + // should process phy information of previous packet + rtl8192_process_phyinfo(priv, tmp_buf, &previous_stats, pstats); + rtl8192_query_rxphystatus(priv, pstats, pdrvinfo, &previous_stats, bpacket_match_bssid,bpacket_toself,bPacketBeacon,bToSelfBA); + rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats); + +} + +/** +* Function: UpdateReceivedRateHistogramStatistics +* Overview: Recored down the received data rate +* +* Input: +* struct net_device *dev +* struct ieee80211_rx_stats *stats +* +* Output: +* +* (priv->stats.ReceivedRateHistogram[] is updated) +* Return: +* None +*/ +void +UpdateReceivedRateHistogramStatistics8190( + struct net_device *dev, + struct ieee80211_rx_stats *stats + ) +{ + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + u32 rcvType=1; //0: Total, 1:OK, 2:CRC, 3:ICV + u32 rateIndex; + u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI + + + if(stats->bCRC) + rcvType = 2; + else if(stats->bICV) + rcvType = 3; + + if(stats->bShortPreamble) + preamble_guardinterval = 1;// short + else + preamble_guardinterval = 0;// long + + switch(stats->rate) + { + // + // CCK rate + // + case MGN_1M: rateIndex = 0; break; + case MGN_2M: rateIndex = 1; break; + case MGN_5_5M: rateIndex = 2; break; + case MGN_11M: rateIndex = 3; break; + // + // Legacy OFDM rate + // + case MGN_6M: rateIndex = 4; break; + case MGN_9M: rateIndex = 5; break; + case MGN_12M: rateIndex = 6; break; + case MGN_18M: rateIndex = 7; break; + case MGN_24M: rateIndex = 8; break; + case MGN_36M: rateIndex = 9; break; + case MGN_48M: rateIndex = 10; break; + case MGN_54M: rateIndex = 11; break; + // + // 11n High throughput rate + // + case MGN_MCS0: rateIndex = 12; break; + case MGN_MCS1: rateIndex = 13; break; + case MGN_MCS2: rateIndex = 14; break; + case MGN_MCS3: rateIndex = 15; break; + case MGN_MCS4: rateIndex = 16; break; + case MGN_MCS5: rateIndex = 17; break; + case MGN_MCS6: rateIndex = 18; break; + case MGN_MCS7: rateIndex = 19; break; + case MGN_MCS8: rateIndex = 20; break; + case MGN_MCS9: rateIndex = 21; break; + case MGN_MCS10: rateIndex = 22; break; + case MGN_MCS11: rateIndex = 23; break; + case MGN_MCS12: rateIndex = 24; break; + case MGN_MCS13: rateIndex = 25; break; + case MGN_MCS14: rateIndex = 26; break; + case MGN_MCS15: rateIndex = 27; break; + default: rateIndex = 28; break; + } + priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++; + priv->stats.received_rate_histogram[0][rateIndex]++; //total + priv->stats.received_rate_histogram[rcvType][rateIndex]++; +} + + +void query_rxdesc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats, bool bIsRxAggrSubframe) +{ + rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb; + struct net_device *dev=info->dev; + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + //rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data; + rx_drvinfo_819x_usb *driver_info = NULL; + + // + //Get Rx Descriptor Information + // +#ifdef USB_RX_AGGREGATION_SUPPORT + if (bIsRxAggrSubframe) + { + rx_desc_819x_usb_aggr_subframe *desc = (rx_desc_819x_usb_aggr_subframe *)skb->data; + stats->Length = desc->Length ; + stats->RxDrvInfoSize = desc->RxDrvInfoSize; + stats->RxBufShift = 0; //RxBufShift = 2 in RxDesc, but usb didn't shift bytes in fact. + stats->bICV = desc->ICV; + stats->bCRC = desc->CRC32; + stats->bHwError = stats->bCRC|stats->bICV; + stats->Decrypted = !desc->SWDec;//RTL8190 set this bit to indicate that Hw does not decrypt packet + } else +#endif + { + rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data; + + stats->Length = desc->Length; + stats->RxDrvInfoSize = desc->RxDrvInfoSize; + stats->RxBufShift = 0;//desc->Shift&0x03; + stats->bICV = desc->ICV; + stats->bCRC = desc->CRC32; + stats->bHwError = stats->bCRC|stats->bICV; + //RTL8190 set this bit to indicate that Hw does not decrypt packet + stats->Decrypted = !desc->SWDec; + } + + if((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP)) + { + stats->bHwError = false; + } + else + { + stats->bHwError = stats->bCRC|stats->bICV; + } + + if(stats->Length < 24 || stats->Length > MAX_8192U_RX_SIZE) + stats->bHwError |= 1; + // + //Get Driver Info + // + // TODO: Need to verify it on FGPA platform + //Driver info are written to the RxBuffer following rx desc + if (stats->RxDrvInfoSize != 0) { + driver_info = (rx_drvinfo_819x_usb *)(skb->data + sizeof(rx_desc_819x_usb) + \ + stats->RxBufShift); + /* unit: 0.5M */ + /* TODO */ + if(!stats->bHwError){ + u8 ret_rate; + ret_rate = HwRateToMRate90(driver_info->RxHT, driver_info->RxRate); + if(ret_rate == 0xff) + { + // Abnormal Case: Receive CRC OK packet with Rx descriptor indicating non supported rate. + // Special Error Handling here, 2008.05.16, by Emily + + stats->bHwError = 1; + stats->rate = MGN_1M; //Set 1M rate by default + }else + { + stats->rate = ret_rate; + } + } + else + stats->rate = 0x02; + + stats->bShortPreamble = driver_info->SPLCP; + + + UpdateReceivedRateHistogramStatistics8190(dev, stats); + + stats->bIsAMPDU = (driver_info->PartAggr==1); + stats->bFirstMPDU = (driver_info->PartAggr==1) && (driver_info->FirstAGGR==1); + stats->TimeStampLow = driver_info->TSFL; + // xiong mask it, 070514 + //pRfd->Status.TimeStampHigh = PlatformEFIORead4Byte(Adapter, TSFR+4); + // stats->TimeStampHigh = read_nic_dword(dev, TSFR+4); + + UpdateRxPktTimeStamp8190(dev, stats); + + // + // Rx A-MPDU + // + if(driver_info->FirstAGGR==1 || driver_info->PartAggr == 1) + RT_TRACE(COMP_RXDESC, "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n", + driver_info->FirstAGGR, driver_info->PartAggr); + + } + + skb_pull(skb,sizeof(rx_desc_819x_usb)); + // + // Get Total offset of MPDU Frame Body + // + if((stats->RxBufShift + stats->RxDrvInfoSize) > 0) { + stats->bShift = 1; + skb_pull(skb,stats->RxBufShift + stats->RxDrvInfoSize); + } + +#ifdef USB_RX_AGGREGATION_SUPPORT + /* for the rx aggregated sub frame, the redundant space truelly contained in the packet */ + if(bIsRxAggrSubframe) { + skb_pull(skb, 8); + } +#endif + /* for debug 2008.5.29 */ + + //added by vivi, for MP, 20080108 + stats->RxIs40MHzPacket = driver_info->BW; + if(stats->RxDrvInfoSize != 0) + TranslateRxSignalStuff819xUsb(skb, stats, driver_info); + +} + +u32 GetRxPacketShiftBytes819xUsb(struct ieee80211_rx_stats *Status, bool bIsRxAggrSubframe) +{ +#ifdef USB_RX_AGGREGATION_SUPPORT + if (bIsRxAggrSubframe) + return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize + + Status->RxBufShift + 8); + else +#endif + return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize + + Status->RxBufShift); +} + +void rtl8192_rx_nomal(struct sk_buff* skb) +{ + rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb; + struct net_device *dev=info->dev; + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + struct ieee80211_rx_stats stats = { + .signal = 0, + .noise = -98, + .rate = 0, + // .mac_time = jiffies, + .freq = IEEE80211_24GHZ_BAND, + }; + u32 rx_pkt_len = 0; + struct ieee80211_hdr_1addr *ieee80211_hdr = NULL; + bool unicast_packet = false; +#ifdef USB_RX_AGGREGATION_SUPPORT + struct sk_buff *agg_skb = NULL; + u32 TotalLength = 0; + u32 TempDWord = 0; + u32 PacketLength = 0; + u32 PacketOccupiedLendth = 0; + u8 TempByte = 0; + u32 PacketShiftBytes = 0; + rx_desc_819x_usb_aggr_subframe *RxDescr = NULL; + u8 PaddingBytes = 0; + //add just for testing + u8 testing; + +#endif + + /* 20 is for ps-poll */ + if((skb->len >=(20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) { +#ifdef USB_RX_AGGREGATION_SUPPORT + TempByte = *(skb->data + sizeof(rx_desc_819x_usb)); +#endif + /* first packet should not contain Rx aggregation header */ + query_rxdesc_status(skb, &stats, false); + /* TODO */ + /* hardware related info */ +#ifdef USB_RX_AGGREGATION_SUPPORT + if (TempByte & BIT0) { + agg_skb = skb; + //TotalLength = agg_skb->len - 4; /*sCrcLng*/ + TotalLength = stats.Length - 4; /*sCrcLng*/ + //RT_TRACE(COMP_RECV, "%s:first aggregated packet!Length=%d\n",__FUNCTION__,TotalLength); + /* though the head pointer has passed this position */ + TempDWord = *(u32 *)(agg_skb->data - 4); + PacketLength = (u16)(TempDWord & 0x3FFF); /*sCrcLng*/ + skb = dev_alloc_skb(PacketLength); + memcpy(skb_put(skb,PacketLength),agg_skb->data,PacketLength); + PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, false); + } +#endif + /* Process the MPDU recevied */ + skb_trim(skb, skb->len - 4/*sCrcLng*/); + + rx_pkt_len = skb->len; + ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data; + unicast_packet = false; + if(is_broadcast_ether_addr(ieee80211_hdr->addr1)) { + //TODO + }else if(is_multicast_ether_addr(ieee80211_hdr->addr1)){ + //TODO + }else { + /* unicast packet */ + unicast_packet = true; + } + + if(!ieee80211_rx(priv->ieee80211,skb, &stats)) { + dev_kfree_skb_any(skb); + } else { + priv->stats.rxoktotal++; + if(unicast_packet) { + priv->stats.rxbytesunicast += rx_pkt_len; + } + } +#ifdef USB_RX_AGGREGATION_SUPPORT + testing = 1; + // (PipeIndex == 0) && (TempByte & BIT0) => TotalLength > 0. + if (TotalLength > 0) { + PacketOccupiedLendth = PacketLength + (PacketShiftBytes + 8); + if ((PacketOccupiedLendth & 0xFF) != 0) + PacketOccupiedLendth = (PacketOccupiedLendth & 0xFFFFFF00) + 256; + PacketOccupiedLendth -= 8; + TempDWord = PacketOccupiedLendth - PacketShiftBytes; /*- PacketLength */ + if (agg_skb->len > TempDWord) + skb_pull(agg_skb, TempDWord); + else + agg_skb->len = 0; + + while (agg_skb->len>=GetRxPacketShiftBytes819xUsb(&stats, true)) { + u8 tmpCRC = 0, tmpICV = 0; + //RT_TRACE(COMP_RECV,"%s:aggred pkt,total_len = %d\n",__FUNCTION__,agg_skb->len); + RxDescr = (rx_desc_819x_usb_aggr_subframe *)(agg_skb->data); + tmpCRC = RxDescr->CRC32; + tmpICV = RxDescr->ICV; + memcpy(agg_skb->data, &agg_skb->data[44], 2); + RxDescr->CRC32 = tmpCRC; + RxDescr->ICV = tmpICV; + + memset(&stats, 0, sizeof(struct ieee80211_rx_stats)); + stats.signal = 0; + stats.noise = -98; + stats.rate = 0; + stats.freq = IEEE80211_24GHZ_BAND; + query_rxdesc_status(agg_skb, &stats, true); + PacketLength = stats.Length; + + if(PacketLength > agg_skb->len) { + break; + } + /* Process the MPDU recevied */ + skb = dev_alloc_skb(PacketLength); + memcpy(skb_put(skb,PacketLength),agg_skb->data, PacketLength); + skb_trim(skb, skb->len - 4/*sCrcLng*/); + + rx_pkt_len = skb->len; + ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data; + unicast_packet = false; + if(is_broadcast_ether_addr(ieee80211_hdr->addr1)) { + //TODO + }else if(is_multicast_ether_addr(ieee80211_hdr->addr1)){ + //TODO + }else { + /* unicast packet */ + unicast_packet = true; + } + if(!ieee80211_rx(priv->ieee80211,skb, &stats)) { + dev_kfree_skb_any(skb); + } else { + priv->stats.rxoktotal++; + if(unicast_packet) { + priv->stats.rxbytesunicast += rx_pkt_len; + } + } + /* should trim the packet which has been copied to target skb */ + skb_pull(agg_skb, PacketLength); + PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, true); + PacketOccupiedLendth = PacketLength + PacketShiftBytes; + if ((PacketOccupiedLendth & 0xFF) != 0) { + PaddingBytes = 256 - (PacketOccupiedLendth & 0xFF); + if (agg_skb->len > PaddingBytes) + skb_pull(agg_skb, PaddingBytes); + else + agg_skb->len = 0; + } + } + dev_kfree_skb(agg_skb); + } +#endif + } else { + priv->stats.rxurberr++; + printk("actual_length:%d\n", skb->len); + dev_kfree_skb_any(skb); + } + +} + +void +rtl819xusb_process_received_packet( + struct net_device *dev, + struct ieee80211_rx_stats *pstats + ) +{ +// bool bfreerfd=false, bqueued=false; + u8* frame; + u16 frame_len=0; + struct r8192_priv *priv = ieee80211_priv(dev); +// u8 index = 0; +// u8 TID = 0; + //u16 seqnum = 0; + //PRX_TS_RECORD pts = NULL; + + // Get shifted bytes of Starting address of 802.11 header. 2006.09.28, by Emily + //porting by amy 080508 + pstats->virtual_address += get_rxpacket_shiftbytes_819xusb(pstats); + frame = pstats->virtual_address; + frame_len = pstats->packetlength; +#ifdef TODO // by amy about HCT + if(!Adapter->bInHctTest) + CountRxErrStatistics(Adapter, pRfd); +#endif + { + #ifdef ENABLE_PS //by amy for adding ps function in future + RT_RF_POWER_STATE rtState; + // When RF is off, we should not count the packet for hw/sw synchronize + // reason, ie. there may be a duration while sw switch is changed and hw + // switch is being changed. 2006.12.04, by shien chang. + Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_RF_STATE, (u8* )(&rtState)); + if (rtState == eRfOff) + { + return; + } + #endif + priv->stats.rxframgment++; + + } +#ifdef TODO + RmMonitorSignalStrength(Adapter, pRfd); +#endif + /* 2007/01/16 MH Add RX command packet handle here. */ + /* 2007/03/01 MH We have to release RFD and return if rx pkt is cmd pkt. */ + if (rtl819xusb_rx_command_packet(dev, pstats)) + { + return; + } + +#ifdef SW_CRC_CHECK + SwCrcCheck(); +#endif + + +} + +void query_rx_cmdpkt_desc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats) +{ +// rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb; +// struct net_device *dev=info->dev; +// struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data; +// rx_drvinfo_819x_usb *driver_info; + + // + //Get Rx Descriptor Information + // + stats->virtual_address = (u8*)skb->data; + stats->Length = desc->Length; + stats->RxDrvInfoSize = 0; + stats->RxBufShift = 0; + stats->packetlength = stats->Length-scrclng; + stats->fraglength = stats->packetlength; + stats->fragoffset = 0; + stats->ntotalfrag = 1; +} + + +void rtl8192_rx_cmd(struct sk_buff *skb) +{ + struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb; + struct net_device *dev = info->dev; + //int ret; +// struct urb *rx_urb = info->urb; + /* TODO */ + struct ieee80211_rx_stats stats = { + .signal = 0, + .noise = -98, + .rate = 0, + // .mac_time = jiffies, + .freq = IEEE80211_24GHZ_BAND, + }; + + if((skb->len >=(20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) + { + + query_rx_cmdpkt_desc_status(skb,&stats); + // this is to be done by amy 080508 prfd->queue_id = 1; + + + // + // Process the command packet received. + // + + rtl819xusb_process_received_packet(dev,&stats); + + dev_kfree_skb_any(skb); + } + else + ; + + +} + +void rtl8192_irq_rx_tasklet(struct r8192_priv *priv) +{ + struct sk_buff *skb; + struct rtl8192_rx_info *info; + + while (NULL != (skb = skb_dequeue(&priv->skb_queue))) { + info = (struct rtl8192_rx_info *)skb->cb; + switch (info->out_pipe) { + /* Nomal packet pipe */ + case 3: + //RT_TRACE(COMP_RECV, "normal in-pipe index(%d)\n",info->out_pipe); + priv->IrpPendingCount--; + rtl8192_rx_nomal(skb); + break; + + /* Command packet pipe */ + case 9: + RT_TRACE(COMP_RECV, "command in-pipe index(%d)\n",\ + info->out_pipe); + + rtl8192_rx_cmd(skb); + break; + + default: /* should never get here! */ + RT_TRACE(COMP_ERR, "Unknown in-pipe index(%d)\n",\ + info->out_pipe); + dev_kfree_skb(skb); + break; + + } + } +} + +static const struct net_device_ops rtl8192_netdev_ops = { + .ndo_open = rtl8192_open, + .ndo_stop = rtl8192_close, + .ndo_get_stats = rtl8192_stats, + .ndo_tx_timeout = tx_timeout, + .ndo_do_ioctl = rtl8192_ioctl, + .ndo_set_multicast_list = r8192_set_multicast, + .ndo_set_mac_address = r8192_set_mac_adr, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = eth_change_mtu, + .ndo_start_xmit = ieee80211_xmit, +}; + + +/**************************************************************************** + ---------------------------- USB_STUFF--------------------------- +*****************************************************************************/ + +static int __devinit rtl8192_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ +// unsigned long ioaddr = 0; + struct net_device *dev = NULL; + struct r8192_priv *priv= NULL; + struct usb_device *udev = interface_to_usbdev(intf); + RT_TRACE(COMP_INIT, "Oops: i'm coming\n"); + + dev = alloc_ieee80211(sizeof(struct r8192_priv)); + + + usb_set_intfdata(intf, dev); + SET_NETDEV_DEV(dev, &intf->dev); + priv = ieee80211_priv(dev); + priv->ieee80211 = netdev_priv(dev); + priv->udev=udev; + + dev->netdev_ops = &rtl8192_netdev_ops; + + //DMESG("Oops: i'm coming\n"); +#if WIRELESS_EXT >= 12 +#if WIRELESS_EXT < 17 + dev->get_wireless_stats = r8192_get_wireless_stats; +#endif + dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def; +#endif + dev->type=ARPHRD_ETHER; + + dev->watchdog_timeo = HZ*3; //modified by john, 0805 + + if (dev_alloc_name(dev, ifname) < 0){ + RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); + ifname = "wlan%d"; + dev_alloc_name(dev, ifname); + } + + RT_TRACE(COMP_INIT, "Driver probe completed1\n"); + if(rtl8192_init(dev)!=0){ + RT_TRACE(COMP_ERR, "Initialization failed"); + goto fail; + } + netif_carrier_off(dev); + netif_stop_queue(dev); + + register_netdev(dev); + RT_TRACE(COMP_INIT, "dev name=======> %s\n",dev->name); + rtl8192_proc_init_one(dev); + + + RT_TRACE(COMP_INIT, "Driver probe completed\n"); + return 0; + + +fail: + free_ieee80211(dev); + + RT_TRACE(COMP_ERR, "wlan driver load failed\n"); + return -ENODEV; + +} + +//detach all the work and timer structure declared or inititialize in r8192U_init function. +void rtl8192_cancel_deferred_work(struct r8192_priv* priv) +{ + + cancel_work_sync(&priv->reset_wq); + cancel_delayed_work(&priv->watch_dog_wq); + cancel_delayed_work(&priv->update_beacon_wq); + cancel_work_sync(&priv->qos_activate); + //cancel_work_sync(&priv->SetBWModeWorkItem); + //cancel_work_sync(&priv->SwChnlWorkItem); + +} + + +static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf) +{ + struct net_device *dev = usb_get_intfdata(intf); + + struct r8192_priv *priv = ieee80211_priv(dev); + if(dev){ + + unregister_netdev(dev); + + RT_TRACE(COMP_DOWN, "=============>wlan driver to be removed\n"); + rtl8192_proc_remove_one(dev); + + rtl8192_down(dev); + if (priv->pFirmware) + { + kfree(priv->pFirmware); + priv->pFirmware = NULL; + } + // priv->rf_close(dev); +// rtl8192_SetRFPowerState(dev, eRfOff); + rtl8192_usb_deleteendpoints(dev); + destroy_workqueue(priv->priv_wq); + //rtl8192_irq_disable(dev); + //rtl8192_reset(dev); + mdelay(10); + + } + free_ieee80211(dev); + RT_TRACE(COMP_DOWN, "wlan driver removed\n"); +} + +/* fun with the built-in ieee80211 stack... */ +extern int ieee80211_debug_init(void); +extern void ieee80211_debug_exit(void); +extern int ieee80211_crypto_init(void); +extern void ieee80211_crypto_deinit(void); +extern int ieee80211_crypto_tkip_init(void); +extern void ieee80211_crypto_tkip_exit(void); +extern int ieee80211_crypto_ccmp_init(void); +extern void ieee80211_crypto_ccmp_exit(void); +extern int ieee80211_crypto_wep_init(void); +extern void ieee80211_crypto_wep_exit(void); + +static int __init rtl8192_usb_module_init(void) +{ + int ret; + +#ifdef CONFIG_IEEE80211_DEBUG + ret = ieee80211_debug_init(); + if (ret) { + printk(KERN_ERR "ieee80211_debug_init() failed %d\n", ret); + return ret; + } +#endif + ret = ieee80211_crypto_init(); + if (ret) { + printk(KERN_ERR "ieee80211_crypto_init() failed %d\n", ret); + return ret; + } + + ret = ieee80211_crypto_tkip_init(); + if (ret) { + printk(KERN_ERR "ieee80211_crypto_tkip_init() failed %d\n", + ret); + return ret; + } + + ret = ieee80211_crypto_ccmp_init(); + if (ret) { + printk(KERN_ERR "ieee80211_crypto_ccmp_init() failed %d\n", + ret); + return ret; + } + + ret = ieee80211_crypto_wep_init(); + if (ret) { + printk(KERN_ERR "ieee80211_crypto_wep_init() failed %d\n", ret); + return ret; + } + + printk(KERN_INFO "\nLinux kernel driver for RTL8192 based WLAN cards\n"); + printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan\n"); + RT_TRACE(COMP_INIT, "Initializing module"); + RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT); + rtl8192_proc_module_init(); + return usb_register(&rtl8192_usb_driver); +} + + +static void __exit rtl8192_usb_module_exit(void) +{ + usb_deregister(&rtl8192_usb_driver); + + RT_TRACE(COMP_DOWN, "Exiting"); +// rtl8192_proc_module_remove(); +} + + +void rtl8192_try_wake_queue(struct net_device *dev, int pri) +{ + unsigned long flags; + short enough_desc; + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + + spin_lock_irqsave(&priv->tx_lock,flags); + enough_desc = check_nic_enough_desc(dev,pri); + spin_unlock_irqrestore(&priv->tx_lock,flags); + + if(enough_desc) + ieee80211_wake_queue(priv->ieee80211); +} + +void EnableHWSecurityConfig8192(struct net_device *dev) +{ + u8 SECR_value = 0x0; + struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); + struct ieee80211_device* ieee = priv->ieee80211; + SECR_value = SCR_TxEncEnable | SCR_RxDecEnable; + if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->ieee80211->auth_mode != 2)) + { + SECR_value |= SCR_RxUseDK; + SECR_value |= SCR_TxUseDK; + } + else if ((ieee->iw_mode == IW_MODE_ADHOC) && (ieee->pairwise_key_type & (KEY_TYPE_CCMP | KEY_TYPE_TKIP))) + { + SECR_value |= SCR_RxUseDK; + SECR_value |= SCR_TxUseDK; + } + //add HWSec active enable here. +//default using hwsec. when peer AP is in N mode only and pairwise_key_type is none_aes(which HT_IOT_ACT_PURE_N_MODE indicates it), use software security. when peer AP is in b,g,n mode mixed and pairwise_key_type is none_aes, use g mode hw security. WB on 2008.7.4 + + ieee->hwsec_active = 1; + + if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep)//!ieee->hwsec_support) //add hwsec_support flag to totol control hw_sec on/off + { + ieee->hwsec_active = 0; + SECR_value &= ~SCR_RxDecEnable; + } + RT_TRACE(COMP_SEC,"%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __FUNCTION__, \ + ieee->hwsec_active, ieee->pairwise_key_type, SECR_value); + { + write_nic_byte(dev, SECR, SECR_value);//SECR_value | SCR_UseDK ); + } +} + + +void setKey( struct net_device *dev, + u8 EntryNo, + u8 KeyIndex, + u16 KeyType, + u8 *MacAddr, + u8 DefaultKey, + u32 *KeyContent ) +{ + u32 TargetCommand = 0; + u32 TargetContent = 0; + u16 usConfig = 0; + u8 i; + if (EntryNo >= TOTAL_CAM_ENTRY) + RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n"); + + RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr"MAC_FMT"\n", dev,EntryNo, KeyIndex, KeyType, MAC_ARG(MacAddr)); + + if (DefaultKey) + usConfig |= BIT15 | (KeyType<<2); + else + usConfig |= BIT15 | (KeyType<<2) | KeyIndex; +// usConfig |= BIT15 | (KeyType<<2) | (DefaultKey<<5) | KeyIndex; + + + for(i=0 ; i Rate Adaptive +static void dm_check_rate_adaptive(struct net_device *dev); + +// DM --> Bandwidth switch +static void dm_init_bandwidth_autoswitch(struct net_device *dev); +static void dm_bandwidth_autoswitch( struct net_device *dev); + +// DM --> TX power control +//static void dm_initialize_txpower_tracking(struct net_device *dev); + +static void dm_check_txpower_tracking(struct net_device *dev); + + + +//static void dm_txpower_reset_recovery(struct net_device *dev); + + +// DM --> BB init gain restore +#ifndef RTL8192U +static void dm_bb_initialgain_restore(struct net_device *dev); + + +// DM --> BB init gain backup +static void dm_bb_initialgain_backup(struct net_device *dev); +#endif +// DM --> Dynamic Init Gain by RSSI +static void dm_dig_init(struct net_device *dev); +static void dm_ctrl_initgain_byrssi(struct net_device *dev); +static void dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev); +static void dm_ctrl_initgain_byrssi_by_driverrssi( struct net_device *dev); +static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(struct net_device *dev); +static void dm_initial_gain(struct net_device *dev); +static void dm_pd_th(struct net_device *dev); +static void dm_cs_ratio(struct net_device *dev); + +static void dm_init_ctstoself(struct net_device *dev); +// DM --> EDCA turboe mode control +static void dm_check_edca_turbo(struct net_device *dev); + +// DM --> HW RF control +static void dm_check_rfctrl_gpio(struct net_device *dev); + +#ifndef RTL8190P +//static void dm_gpio_change_rf(struct net_device *dev); +#endif +// DM --> Check PBC +static void dm_check_pbc_gpio(struct net_device *dev); + + +// DM --> Check current RX RF path state +static void dm_check_rx_path_selection(struct net_device *dev); +static void dm_init_rxpath_selection(struct net_device *dev); +static void dm_rxpath_sel_byrssi(struct net_device *dev); + + +// DM --> Fsync for broadcom ap +static void dm_init_fsync(struct net_device *dev); +static void dm_deInit_fsync(struct net_device *dev); + +//Added by vivi, 20080522 +static void dm_check_txrateandretrycount(struct net_device *dev); + +/*---------------------Define local function prototype-----------------------*/ + +/*---------------------Define of Tx Power Control For Near/Far Range --------*/ //Add by Jacken 2008/02/18 +static void dm_init_dynamic_txpower(struct net_device *dev); +static void dm_dynamic_txpower(struct net_device *dev); + + +// DM --> For rate adaptive and DIG, we must send RSSI to firmware +static void dm_send_rssi_tofw(struct net_device *dev); +static void dm_ctstoself(struct net_device *dev); +/*---------------------------Define function prototype------------------------*/ +//================================================================================ +// HW Dynamic mechanism interface. +//================================================================================ + +// +// Description: +// Prepare SW resource for HW dynamic mechanism. +// +// Assumption: +// This function is only invoked at driver intialization once. +// +// +extern void +init_hal_dm(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + // Undecorated Smoothed Signal Strength, it can utilized to dynamic mechanism. + priv->undecorated_smoothed_pwdb = -1; + + //Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code. + dm_init_dynamic_txpower(dev); + init_rate_adaptive(dev); + //dm_initialize_txpower_tracking(dev); + dm_dig_init(dev); + dm_init_edca_turbo(dev); + dm_init_bandwidth_autoswitch(dev); + dm_init_fsync(dev); + dm_init_rxpath_selection(dev); + dm_init_ctstoself(dev); + +} // InitHalDm + +extern void deinit_hal_dm(struct net_device *dev) +{ + + dm_deInit_fsync(dev); + +} + + +#ifdef USB_RX_AGGREGATION_SUPPORT +void dm_CheckRxAggregation(struct net_device *dev) { + struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev); + PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo; + static unsigned long lastTxOkCnt = 0; + static unsigned long lastRxOkCnt = 0; + unsigned long curTxOkCnt = 0; + unsigned long curRxOkCnt = 0; + +/* + if (pHalData->bForcedUsbRxAggr) { + if (pHalData->ForcedUsbRxAggrInfo == 0) { + if (pHalData->bCurrentRxAggrEnable) { + Adapter->HalFunc.HalUsbRxAggrHandler(Adapter, FALSE); + } + } else { + if (!pHalData->bCurrentRxAggrEnable || (pHalData->ForcedUsbRxAggrInfo != pHalData->LastUsbRxAggrInfoSetting)) { + Adapter->HalFunc.HalUsbRxAggrHandler(Adapter, TRUE); + } + } + return; + } + +*/ + curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; + curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; + + if((curTxOkCnt + curRxOkCnt) < 15000000) { + return; + } + + if(curTxOkCnt > 4*curRxOkCnt) { + if (priv->bCurrentRxAggrEnable) { + write_nic_dword(dev, 0x1a8, 0); + priv->bCurrentRxAggrEnable = false; + } + }else{ + if (!priv->bCurrentRxAggrEnable && !pHTInfo->bCurrentRT2RTAggregation) { + u32 ulValue; + ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) | + (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout); + /* + * If usb rx firmware aggregation is enabled, + * when anyone of three threshold conditions above is reached, + * firmware will send aggregated packet to driver. + */ + write_nic_dword(dev, 0x1a8, ulValue); + priv->bCurrentRxAggrEnable = true; + } + } + + lastTxOkCnt = priv->stats.txbytesunicast; + lastRxOkCnt = priv->stats.rxbytesunicast; +} // dm_CheckEdcaTurbo +#endif + + + +extern void hal_dm_watchdog(struct net_device *dev) +{ + //struct r8192_priv *priv = ieee80211_priv(dev); + + //static u8 previous_bssid[6] ={0}; + + /*Add by amy 2008/05/15 ,porting from windows code.*/ + dm_check_rate_adaptive(dev); + dm_dynamic_txpower(dev); + dm_check_txrateandretrycount(dev); + dm_check_txpower_tracking(dev); + dm_ctrl_initgain_byrssi(dev); + dm_check_edca_turbo(dev); + dm_bandwidth_autoswitch(dev); + dm_check_rfctrl_gpio(dev); + dm_check_rx_path_selection(dev); + dm_check_fsync(dev); + + // Add by amy 2008-05-15 porting from windows code. + dm_check_pbc_gpio(dev); + dm_send_rssi_tofw(dev); + dm_ctstoself(dev); +#ifdef USB_RX_AGGREGATION_SUPPORT + dm_CheckRxAggregation(dev); +#endif +} //HalDmWatchDog + + +/* + * Decide Rate Adaptive Set according to distance (signal strength) + * 01/11/2008 MHC Modify input arguments and RATR table level. + * 01/16/2008 MHC RF_Type is assigned in ReadAdapterInfo(). We must call + * the function after making sure RF_Type. + */ +extern void init_rate_adaptive(struct net_device * dev) +{ + + struct r8192_priv *priv = ieee80211_priv(dev); + prate_adaptive pra = (prate_adaptive)&priv->rate_adaptive; + + pra->ratr_state = DM_RATR_STA_MAX; + pra->high2low_rssi_thresh_for_ra = RateAdaptiveTH_High; + pra->low2high_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M+5; + pra->low2high_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M+5; + + pra->high_rssi_thresh_for_ra = RateAdaptiveTH_High+5; + pra->low_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M; + pra->low_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M; + + if(priv->CustomerID == RT_CID_819x_Netcore) + pra->ping_rssi_enable = 1; + else + pra->ping_rssi_enable = 0; + pra->ping_rssi_thresh_for_ra = 15; + + + if (priv->rf_type == RF_2T4R) + { + // 07/10/08 MH Modify for RA smooth scheme. + /* 2008/01/11 MH Modify 2T RATR table for different RSSI. 080515 porting by amy from windows code.*/ + pra->upper_rssi_threshold_ratr = 0x8f0f0000; + pra->middle_rssi_threshold_ratr = 0x8f0ff000; + pra->low_rssi_threshold_ratr = 0x8f0ff001; + pra->low_rssi_threshold_ratr_40M = 0x8f0ff005; + pra->low_rssi_threshold_ratr_20M = 0x8f0ff001; + pra->ping_rssi_ratr = 0x0000000d;//cosa add for test + } + else if (priv->rf_type == RF_1T2R) + { + pra->upper_rssi_threshold_ratr = 0x000f0000; + pra->middle_rssi_threshold_ratr = 0x000ff000; + pra->low_rssi_threshold_ratr = 0x000ff001; + pra->low_rssi_threshold_ratr_40M = 0x000ff005; + pra->low_rssi_threshold_ratr_20M = 0x000ff001; + pra->ping_rssi_ratr = 0x0000000d;//cosa add for test + } + +} // InitRateAdaptive + + +/*----------------------------------------------------------------------------- + * Function: dm_check_rate_adaptive() + * + * Overview: + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/26/08 amy Create version 0 proting from windows code. + * + *---------------------------------------------------------------------------*/ +static void dm_check_rate_adaptive(struct net_device * dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo; + prate_adaptive pra = (prate_adaptive)&priv->rate_adaptive; + u32 currentRATR, targetRATR = 0; + u32 LowRSSIThreshForRA = 0, HighRSSIThreshForRA = 0; + bool bshort_gi_enabled = false; + static u8 ping_rssi_state=0; + + + if(!priv->up) + { + RT_TRACE(COMP_RATE, "<---- dm_check_rate_adaptive(): driver is going to unload\n"); + return; + } + + if(pra->rate_adaptive_disabled)//this variable is set by ioctl. + return; + + // TODO: Only 11n mode is implemented currently, + if( !(priv->ieee80211->mode == WIRELESS_MODE_N_24G || + priv->ieee80211->mode == WIRELESS_MODE_N_5G)) + return; + + if( priv->ieee80211->state == IEEE80211_LINKED ) + { + // RT_TRACE(COMP_RATE, "dm_CheckRateAdaptive(): \t"); + + // + // Check whether Short GI is enabled + // + bshort_gi_enabled = (pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI40MHz) || + (!pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI20MHz); + + + pra->upper_rssi_threshold_ratr = + (pra->upper_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + + pra->middle_rssi_threshold_ratr = + (pra->middle_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + pra->low_rssi_threshold_ratr = + (pra->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + } + else + { + pra->low_rssi_threshold_ratr = + (pra->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + } + //cosa add for test + pra->ping_rssi_ratr = + (pra->ping_rssi_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + + /* 2007/10/08 MH We support RA smooth scheme now. When it is the first + time to link with AP. We will not change upper/lower threshold. If + STA stay in high or low level, we must change two different threshold + to prevent jumping frequently. */ + if (pra->ratr_state == DM_RATR_STA_HIGH) + { + HighRSSIThreshForRA = pra->high2low_rssi_thresh_for_ra; + LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M); + } + else if (pra->ratr_state == DM_RATR_STA_LOW) + { + HighRSSIThreshForRA = pra->high_rssi_thresh_for_ra; + LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + (pra->low2high_rssi_thresh_for_ra40M):(pra->low2high_rssi_thresh_for_ra20M); + } + else + { + HighRSSIThreshForRA = pra->high_rssi_thresh_for_ra; + LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M); + } + + //DbgPrint("[DM] THresh H/L=%d/%d\n\r", RATR.HighRSSIThreshForRA, RATR.LowRSSIThreshForRA); + if(priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA) + { + //DbgPrint("[DM] RSSI=%d STA=HIGH\n\r", pHalData->UndecoratedSmoothedPWDB); + pra->ratr_state = DM_RATR_STA_HIGH; + targetRATR = pra->upper_rssi_threshold_ratr; + }else if(priv->undecorated_smoothed_pwdb >= (long)LowRSSIThreshForRA) + { + //DbgPrint("[DM] RSSI=%d STA=Middle\n\r", pHalData->UndecoratedSmoothedPWDB); + pra->ratr_state = DM_RATR_STA_MIDDLE; + targetRATR = pra->middle_rssi_threshold_ratr; + }else + { + //DbgPrint("[DM] RSSI=%d STA=LOW\n\r", pHalData->UndecoratedSmoothedPWDB); + pra->ratr_state = DM_RATR_STA_LOW; + targetRATR = pra->low_rssi_threshold_ratr; + } + + //cosa add for test + if(pra->ping_rssi_enable) + { + //pHalData->UndecoratedSmoothedPWDB = 19; + if(priv->undecorated_smoothed_pwdb < (long)(pra->ping_rssi_thresh_for_ra+5)) + { + if( (priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) || + ping_rssi_state ) + { + //DbgPrint("TestRSSI = %d, set RATR to 0x%x \n", pHalData->UndecoratedSmoothedPWDB, pRA->TestRSSIRATR); + pra->ratr_state = DM_RATR_STA_LOW; + targetRATR = pra->ping_rssi_ratr; + ping_rssi_state = 1; + } + //else + // DbgPrint("TestRSSI is between the range. \n"); + } + else + { + //DbgPrint("TestRSSI Recover to 0x%x \n", targetRATR); + ping_rssi_state = 0; + } + } + + // 2008.04.01 + // For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7. + if(priv->ieee80211->GetHalfNmodeSupportByAPsHandler(dev)) + targetRATR &= 0xf00fffff; + + // + // Check whether updating of RATR0 is required + // + currentRATR = read_nic_dword(dev, RATR0); + if( targetRATR != currentRATR ) + { + u32 ratr_value; + ratr_value = targetRATR; + RT_TRACE(COMP_RATE,"currentRATR = %x, targetRATR = %x\n", currentRATR, targetRATR); + if(priv->rf_type == RF_1T2R) + { + ratr_value &= ~(RATE_ALL_OFDM_2SS); + } + write_nic_dword(dev, RATR0, ratr_value); + write_nic_byte(dev, UFWP, 1); + + pra->last_ratr = targetRATR; + } + + } + else + { + pra->ratr_state = DM_RATR_STA_MAX; + } + +} // dm_CheckRateAdaptive + + +static void dm_init_bandwidth_autoswitch(struct net_device * dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz = BW_AUTO_SWITCH_LOW_HIGH; + priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz = BW_AUTO_SWITCH_HIGH_LOW; + priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false; + priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable = false; + +} // dm_init_bandwidth_autoswitch + + +static void dm_bandwidth_autoswitch(struct net_device * dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ||!priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable){ + return; + }else{ + if(priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false){//If send packets in 40 Mhz in 20/40 + if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz) + priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true; + }else{//in force send packets in 20 Mhz in 20/40 + if(priv->undecorated_smoothed_pwdb >= priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz) + priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false; + + } + } +} // dm_BandwidthAutoSwitch + +//OFDM default at 0db, index=6. +static u32 OFDMSwingTable[OFDM_Table_Length] = { + 0x7f8001fe, // 0, +6db + 0x71c001c7, // 1, +5db + 0x65400195, // 2, +4db + 0x5a400169, // 3, +3db + 0x50800142, // 4, +2db + 0x47c0011f, // 5, +1db + 0x40000100, // 6, +0db ===> default, upper for higher temprature, lower for low temprature + 0x390000e4, // 7, -1db + 0x32c000cb, // 8, -2db + 0x2d4000b5, // 9, -3db + 0x288000a2, // 10, -4db + 0x24000090, // 11, -5db + 0x20000080, // 12, -6db + 0x1c800072, // 13, -7db + 0x19800066, // 14, -8db + 0x26c0005b, // 15, -9db + 0x24400051, // 16, -10db + 0x12000048, // 17, -11db + 0x10000040 // 18, -12db +}; + +static u8 CCKSwingTable_Ch1_Ch13[CCK_Table_length][8] = { + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, // 0, +0db ===> CCK40M default + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, // 1, -1db + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, // 2, -2db + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, // 3, -3db + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, // 4, -4db + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, // 5, -5db + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, // 6, -6db ===> CCK20M default + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, // 7, -7db + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, // 8, -8db + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, // 9, -9db + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, // 10, -10db + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01} // 11, -11db +}; + +static u8 CCKSwingTable_Ch14[CCK_Table_length][8] = { + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, // 0, +0db ===> CCK40M default + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, // 1, -1db + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, // 2, -2db + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, // 3, -3db + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, // 4, -4db + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, // 5, -5db + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, // 6, -6db ===> CCK20M default + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, // 7, -7db + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, // 8, -8db + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, // 9, -9db + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, // 10, -10db + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00} // 11, -11db +}; + +static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + bool bHighpowerstate, viviflag = FALSE; + DCMD_TXCMD_T tx_cmd; + u8 powerlevelOFDM24G; + int i =0, j = 0, k = 0; + u8 RF_Type, tmp_report[5]={0, 0, 0, 0, 0}; + u32 Value; + u8 Pwr_Flag; + u16 Avg_TSSI_Meas, TSSI_13dBm, Avg_TSSI_Meas_from_driver=0; + //RT_STATUS rtStatus = RT_STATUS_SUCCESS; + bool rtStatus = true; + u32 delta=0; + + write_nic_byte(dev, 0x1ba, 0); + + priv->ieee80211->bdynamic_txpower_enable = false; + bHighpowerstate = priv->bDynamicTxHighPower; + + powerlevelOFDM24G = (u8)(priv->Pwr_Track>>24); + RF_Type = priv->rf_type; + Value = (RF_Type<<8) | powerlevelOFDM24G; + + RT_TRACE(COMP_POWER_TRACKING, "powerlevelOFDM24G = %x\n", powerlevelOFDM24G); + + for(j = 0; j<=30; j++) +{ //fill tx_cmd + + tx_cmd.Op = TXCMD_SET_TX_PWR_TRACKING; + tx_cmd.Length = 4; + tx_cmd.Value = Value; +#ifdef RTL8192U + rtStatus = SendTxCommandPacket(dev, &tx_cmd, 12); + if (rtStatus == RT_STATUS_FAILURE) + { + RT_TRACE(COMP_POWER_TRACKING, "Set configuration with tx cmd queue fail!\n"); + } +#else + cmpk_message_handle_tx(dev, (u8*)&tx_cmd, + DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T)); +#endif + mdelay(1); + //DbgPrint("hi, vivi, strange\n"); + for(i = 0;i <= 30; i++) + { + Pwr_Flag = read_nic_byte(dev, 0x1ba); + + if (Pwr_Flag == 0) + { + mdelay(1); + continue; + } +#ifdef RTL8190P + Avg_TSSI_Meas = read_nic_word(dev, 0x1bc); +#else + Avg_TSSI_Meas = read_nic_word(dev, 0x13c); +#endif + if(Avg_TSSI_Meas == 0) + { + write_nic_byte(dev, 0x1ba, 0); + break; + } + + for(k = 0;k < 5; k++) + { +#ifdef RTL8190P + tmp_report[k] = read_nic_byte(dev, 0x1d8+k); +#else + if(k !=4) + tmp_report[k] = read_nic_byte(dev, 0x134+k); + else + tmp_report[k] = read_nic_byte(dev, 0x13e); +#endif + RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]); + } + + //check if the report value is right + for(k = 0;k < 5; k++) + { + if(tmp_report[k] <= 20) + { + viviflag =TRUE; + break; + } + } + if(viviflag ==TRUE) + { + write_nic_byte(dev, 0x1ba, 0); + viviflag = FALSE; + RT_TRACE(COMP_POWER_TRACKING, "we filted this data\n"); + for(k = 0;k < 5; k++) + tmp_report[k] = 0; + break; + } + + for(k = 0;k < 5; k++) + { + Avg_TSSI_Meas_from_driver += tmp_report[k]; + } + + Avg_TSSI_Meas_from_driver = Avg_TSSI_Meas_from_driver*100/5; + RT_TRACE(COMP_POWER_TRACKING, "Avg_TSSI_Meas_from_driver = %d\n", Avg_TSSI_Meas_from_driver); + TSSI_13dBm = priv->TSSI_13dBm; + RT_TRACE(COMP_POWER_TRACKING, "TSSI_13dBm = %d\n", TSSI_13dBm); + + //if(abs(Avg_TSSI_Meas_from_driver - TSSI_13dBm) <= E_FOR_TX_POWER_TRACK) + // For MacOS-compatible + if(Avg_TSSI_Meas_from_driver > TSSI_13dBm) + delta = Avg_TSSI_Meas_from_driver - TSSI_13dBm; + else + delta = TSSI_13dBm - Avg_TSSI_Meas_from_driver; + + if(delta <= E_FOR_TX_POWER_TRACK) + { + priv->ieee80211->bdynamic_txpower_enable = TRUE; + write_nic_byte(dev, 0x1ba, 0); + RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n"); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real); +#ifdef RTL8190P + RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex = %d\n", priv->rfc_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_real = %d\n", priv->rfc_txpowertrackingindex_real); +#endif + RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference); + RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation); + return; + } + else + { + if(Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK) + { + if((priv->rfa_txpowertrackingindex > 0) +#ifdef RTL8190P + &&(priv->rfc_txpowertrackingindex > 0) +#endif + ) + { + priv->rfa_txpowertrackingindex--; + if(priv->rfa_txpowertrackingindex_real > 4) + { + priv->rfa_txpowertrackingindex_real--; + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); + } +#ifdef RTL8190P + priv->rfc_txpowertrackingindex--; + if(priv->rfc_txpowertrackingindex_real > 4) + { + priv->rfc_txpowertrackingindex_real--; + rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value); + } +#endif + } + } + else + { + if((priv->rfa_txpowertrackingindex < 36) +#ifdef RTL8190P + &&(priv->rfc_txpowertrackingindex < 36) +#endif + ) + { + priv->rfa_txpowertrackingindex++; + priv->rfa_txpowertrackingindex_real++; + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); + +#ifdef RTL8190P + priv->rfc_txpowertrackingindex++; + priv->rfc_txpowertrackingindex_real++; + rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value); +#endif + } + } + priv->cck_present_attentuation_difference + = priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default; + + if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + priv->cck_present_attentuation + = priv->cck_present_attentuation_20Mdefault + priv->cck_present_attentuation_difference; + else + priv->cck_present_attentuation + = priv->cck_present_attentuation_40Mdefault + priv->cck_present_attentuation_difference; + + if(priv->cck_present_attentuation > -1&&priv->cck_present_attentuation <23) + { + if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) + { + priv->bcck_in_ch14 = TRUE; + dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + } + else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) + { + priv->bcck_in_ch14 = FALSE; + dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + } + else + dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + } + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real); +#ifdef RTL8190P + RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex = %d\n", priv->rfc_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_real = %d\n", priv->rfc_txpowertrackingindex_real); +#endif + RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference); + RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation); + + if (priv->cck_present_attentuation_difference <= -12||priv->cck_present_attentuation_difference >= 24) + { + priv->ieee80211->bdynamic_txpower_enable = TRUE; + write_nic_byte(dev, 0x1ba, 0); + RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n"); + return; + } + + + } + write_nic_byte(dev, 0x1ba, 0); + Avg_TSSI_Meas_from_driver = 0; + for(k = 0;k < 5; k++) + tmp_report[k] = 0; + break; + } +} + priv->ieee80211->bdynamic_txpower_enable = TRUE; + write_nic_byte(dev, 0x1ba, 0); +} + +static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev) +{ +#define ThermalMeterVal 9 + struct r8192_priv *priv = ieee80211_priv(dev); + u32 tmpRegA, TempCCk; + u8 tmpOFDMindex, tmpCCKindex, tmpCCK20Mindex, tmpCCK40Mindex, tmpval; + int i =0, CCKSwingNeedUpdate=0; + + if(!priv->btxpower_trackingInit) + { + //Query OFDM default setting + tmpRegA= rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord); + for(i=0; iOFDM_index= (u8)i; + RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, OFDM_index=0x%x\n", + rOFDM0_XATxIQImbalance, tmpRegA, priv->OFDM_index); + } + } + + //Query CCK default setting From 0xa22 + TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2); + for(i=0 ; iCCK_index =(u8) i; + RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, CCK_index=0x%x\n", + rCCK0_TxFilter1, TempCCk, priv->CCK_index); + break; + } + } + priv->btxpower_trackingInit = TRUE; + //pHalData->TXPowercount = 0; + return; + } + + //========================== + // this is only for test, should be masked + //========================== + + // read and filter out unreasonable value + tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078); // 0x12: RF Reg[10:7] + RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d \n", tmpRegA); + if(tmpRegA < 3 || tmpRegA > 13) + return; + if(tmpRegA >= 12) // if over 12, TP will be bad when high temprature + tmpRegA = 12; + RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d \n", tmpRegA); + priv->ThermalMeter[0] = ThermalMeterVal; //We use fixed value by Bryant's suggestion + priv->ThermalMeter[1] = ThermalMeterVal; //We use fixed value by Bryant's suggestion + + //Get current RF-A temprature index + if(priv->ThermalMeter[0] >= (u8)tmpRegA) //lower temprature + { + tmpOFDMindex = tmpCCK20Mindex = 6+(priv->ThermalMeter[0]-(u8)tmpRegA); + tmpCCK40Mindex = tmpCCK20Mindex - 6; + if(tmpOFDMindex >= OFDM_Table_Length) + tmpOFDMindex = OFDM_Table_Length-1; + if(tmpCCK20Mindex >= CCK_Table_length) + tmpCCK20Mindex = CCK_Table_length-1; + if(tmpCCK40Mindex >= CCK_Table_length) + tmpCCK40Mindex = CCK_Table_length-1; + } + else + { + tmpval = ((u8)tmpRegA - priv->ThermalMeter[0]); + if(tmpval >= 6) // higher temprature + tmpOFDMindex = tmpCCK20Mindex = 0; // max to +6dB + else + tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval; + tmpCCK40Mindex = 0; + } + //DbgPrint("%ddb, tmpOFDMindex = %d, tmpCCK20Mindex = %d, tmpCCK40Mindex = %d", + //((u1Byte)tmpRegA - pHalData->ThermalMeter[0]), + //tmpOFDMindex, tmpCCK20Mindex, tmpCCK40Mindex); + if(priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) //40M + tmpCCKindex = tmpCCK40Mindex; + else + tmpCCKindex = tmpCCK20Mindex; + + if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) + { + priv->bcck_in_ch14 = TRUE; + CCKSwingNeedUpdate = 1; + } + else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) + { + priv->bcck_in_ch14 = FALSE; + CCKSwingNeedUpdate = 1; + } + + if(priv->CCK_index != tmpCCKindex) + { + priv->CCK_index = tmpCCKindex; + CCKSwingNeedUpdate = 1; + } + + if(CCKSwingNeedUpdate) + { + //DbgPrint("Update CCK Swing, CCK_index = %d\n", pHalData->CCK_index); + dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + } + if(priv->OFDM_index != tmpOFDMindex) + { + priv->OFDM_index = tmpOFDMindex; + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[priv->OFDM_index]); + RT_TRACE(COMP_POWER_TRACKING, "Update OFDMSwing[%d] = 0x%x\n", + priv->OFDM_index, OFDMSwingTable[priv->OFDM_index]); + } + priv->txpower_count = 0; +} + +extern void dm_txpower_trackingcallback(struct work_struct *work) +{ + struct delayed_work *dwork = container_of(work,struct delayed_work,work); + struct r8192_priv *priv = container_of(dwork,struct r8192_priv,txpower_tracking_wq); + struct net_device *dev = priv->ieee80211->dev; + +#ifdef RTL8190P + dm_TXPowerTrackingCallback_TSSI(dev); +#else + if(priv->bDcut == TRUE) + dm_TXPowerTrackingCallback_TSSI(dev); + else + dm_TXPowerTrackingCallback_ThermalMeter(dev); +#endif +} + + +static void dm_InitializeTXPowerTracking_TSSI(struct net_device *dev) +{ + + struct r8192_priv *priv = ieee80211_priv(dev); + + //Initial the Tx BB index and mapping value + priv->txbbgain_table[0].txbb_iq_amplifygain = 12; + priv->txbbgain_table[0].txbbgain_value=0x7f8001fe; + priv->txbbgain_table[1].txbb_iq_amplifygain = 11; + priv->txbbgain_table[1].txbbgain_value=0x788001e2; + priv->txbbgain_table[2].txbb_iq_amplifygain = 10; + priv->txbbgain_table[2].txbbgain_value=0x71c001c7; + priv->txbbgain_table[3].txbb_iq_amplifygain = 9; + priv->txbbgain_table[3].txbbgain_value=0x6b8001ae; + priv->txbbgain_table[4].txbb_iq_amplifygain = 8; + priv->txbbgain_table[4].txbbgain_value=0x65400195; + priv->txbbgain_table[5].txbb_iq_amplifygain = 7; + priv->txbbgain_table[5].txbbgain_value=0x5fc0017f; + priv->txbbgain_table[6].txbb_iq_amplifygain = 6; + priv->txbbgain_table[6].txbbgain_value=0x5a400169; + priv->txbbgain_table[7].txbb_iq_amplifygain = 5; + priv->txbbgain_table[7].txbbgain_value=0x55400155; + priv->txbbgain_table[8].txbb_iq_amplifygain = 4; + priv->txbbgain_table[8].txbbgain_value=0x50800142; + priv->txbbgain_table[9].txbb_iq_amplifygain = 3; + priv->txbbgain_table[9].txbbgain_value=0x4c000130; + priv->txbbgain_table[10].txbb_iq_amplifygain = 2; + priv->txbbgain_table[10].txbbgain_value=0x47c0011f; + priv->txbbgain_table[11].txbb_iq_amplifygain = 1; + priv->txbbgain_table[11].txbbgain_value=0x43c0010f; + priv->txbbgain_table[12].txbb_iq_amplifygain = 0; + priv->txbbgain_table[12].txbbgain_value=0x40000100; + priv->txbbgain_table[13].txbb_iq_amplifygain = -1; + priv->txbbgain_table[13].txbbgain_value=0x3c8000f2; + priv->txbbgain_table[14].txbb_iq_amplifygain = -2; + priv->txbbgain_table[14].txbbgain_value=0x390000e4; + priv->txbbgain_table[15].txbb_iq_amplifygain = -3; + priv->txbbgain_table[15].txbbgain_value=0x35c000d7; + priv->txbbgain_table[16].txbb_iq_amplifygain = -4; + priv->txbbgain_table[16].txbbgain_value=0x32c000cb; + priv->txbbgain_table[17].txbb_iq_amplifygain = -5; + priv->txbbgain_table[17].txbbgain_value=0x300000c0; + priv->txbbgain_table[18].txbb_iq_amplifygain = -6; + priv->txbbgain_table[18].txbbgain_value=0x2d4000b5; + priv->txbbgain_table[19].txbb_iq_amplifygain = -7; + priv->txbbgain_table[19].txbbgain_value=0x2ac000ab; + priv->txbbgain_table[20].txbb_iq_amplifygain = -8; + priv->txbbgain_table[20].txbbgain_value=0x288000a2; + priv->txbbgain_table[21].txbb_iq_amplifygain = -9; + priv->txbbgain_table[21].txbbgain_value=0x26000098; + priv->txbbgain_table[22].txbb_iq_amplifygain = -10; + priv->txbbgain_table[22].txbbgain_value=0x24000090; + priv->txbbgain_table[23].txbb_iq_amplifygain = -11; + priv->txbbgain_table[23].txbbgain_value=0x22000088; + priv->txbbgain_table[24].txbb_iq_amplifygain = -12; + priv->txbbgain_table[24].txbbgain_value=0x20000080; + priv->txbbgain_table[25].txbb_iq_amplifygain = -13; + priv->txbbgain_table[25].txbbgain_value=0x1a00006c; + priv->txbbgain_table[26].txbb_iq_amplifygain = -14; + priv->txbbgain_table[26].txbbgain_value=0x1c800072; + priv->txbbgain_table[27].txbb_iq_amplifygain = -15; + priv->txbbgain_table[27].txbbgain_value=0x18000060; + priv->txbbgain_table[28].txbb_iq_amplifygain = -16; + priv->txbbgain_table[28].txbbgain_value=0x19800066; + priv->txbbgain_table[29].txbb_iq_amplifygain = -17; + priv->txbbgain_table[29].txbbgain_value=0x15800056; + priv->txbbgain_table[30].txbb_iq_amplifygain = -18; + priv->txbbgain_table[30].txbbgain_value=0x26c0005b; + priv->txbbgain_table[31].txbb_iq_amplifygain = -19; + priv->txbbgain_table[31].txbbgain_value=0x14400051; + priv->txbbgain_table[32].txbb_iq_amplifygain = -20; + priv->txbbgain_table[32].txbbgain_value=0x24400051; + priv->txbbgain_table[33].txbb_iq_amplifygain = -21; + priv->txbbgain_table[33].txbbgain_value=0x1300004c; + priv->txbbgain_table[34].txbb_iq_amplifygain = -22; + priv->txbbgain_table[34].txbbgain_value=0x12000048; + priv->txbbgain_table[35].txbb_iq_amplifygain = -23; + priv->txbbgain_table[35].txbbgain_value=0x11000044; + priv->txbbgain_table[36].txbb_iq_amplifygain = -24; + priv->txbbgain_table[36].txbbgain_value=0x10000040; + + //ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29 + //This Table is for CH1~CH13 + priv->cck_txbbgain_table[0].ccktxbb_valuearray[0] = 0x36; + priv->cck_txbbgain_table[0].ccktxbb_valuearray[1] = 0x35; + priv->cck_txbbgain_table[0].ccktxbb_valuearray[2] = 0x2e; + priv->cck_txbbgain_table[0].ccktxbb_valuearray[3] = 0x25; + priv->cck_txbbgain_table[0].ccktxbb_valuearray[4] = 0x1c; + priv->cck_txbbgain_table[0].ccktxbb_valuearray[5] = 0x12; + priv->cck_txbbgain_table[0].ccktxbb_valuearray[6] = 0x09; + priv->cck_txbbgain_table[0].ccktxbb_valuearray[7] = 0x04; + + priv->cck_txbbgain_table[1].ccktxbb_valuearray[0] = 0x33; + priv->cck_txbbgain_table[1].ccktxbb_valuearray[1] = 0x32; + priv->cck_txbbgain_table[1].ccktxbb_valuearray[2] = 0x2b; + priv->cck_txbbgain_table[1].ccktxbb_valuearray[3] = 0x23; + priv->cck_txbbgain_table[1].ccktxbb_valuearray[4] = 0x1a; + priv->cck_txbbgain_table[1].ccktxbb_valuearray[5] = 0x11; + priv->cck_txbbgain_table[1].ccktxbb_valuearray[6] = 0x08; + priv->cck_txbbgain_table[1].ccktxbb_valuearray[7] = 0x04; + + priv->cck_txbbgain_table[2].ccktxbb_valuearray[0] = 0x30; + priv->cck_txbbgain_table[2].ccktxbb_valuearray[1] = 0x2f; + priv->cck_txbbgain_table[2].ccktxbb_valuearray[2] = 0x29; + priv->cck_txbbgain_table[2].ccktxbb_valuearray[3] = 0x21; + priv->cck_txbbgain_table[2].ccktxbb_valuearray[4] = 0x19; + priv->cck_txbbgain_table[2].ccktxbb_valuearray[5] = 0x10; + priv->cck_txbbgain_table[2].ccktxbb_valuearray[6] = 0x08; + priv->cck_txbbgain_table[2].ccktxbb_valuearray[7] = 0x03; + + priv->cck_txbbgain_table[3].ccktxbb_valuearray[0] = 0x2d; + priv->cck_txbbgain_table[3].ccktxbb_valuearray[1] = 0x2d; + priv->cck_txbbgain_table[3].ccktxbb_valuearray[2] = 0x27; + priv->cck_txbbgain_table[3].ccktxbb_valuearray[3] = 0x1f; + priv->cck_txbbgain_table[3].ccktxbb_valuearray[4] = 0x18; + priv->cck_txbbgain_table[3].ccktxbb_valuearray[5] = 0x0f; + priv->cck_txbbgain_table[3].ccktxbb_valuearray[6] = 0x08; + priv->cck_txbbgain_table[3].ccktxbb_valuearray[7] = 0x03; + + priv->cck_txbbgain_table[4].ccktxbb_valuearray[0] = 0x2b; + priv->cck_txbbgain_table[4].ccktxbb_valuearray[1] = 0x2a; + priv->cck_txbbgain_table[4].ccktxbb_valuearray[2] = 0x25; + priv->cck_txbbgain_table[4].ccktxbb_valuearray[3] = 0x1e; + priv->cck_txbbgain_table[4].ccktxbb_valuearray[4] = 0x16; + priv->cck_txbbgain_table[4].ccktxbb_valuearray[5] = 0x0e; + priv->cck_txbbgain_table[4].ccktxbb_valuearray[6] = 0x07; + priv->cck_txbbgain_table[4].ccktxbb_valuearray[7] = 0x03; + + priv->cck_txbbgain_table[5].ccktxbb_valuearray[0] = 0x28; + priv->cck_txbbgain_table[5].ccktxbb_valuearray[1] = 0x28; + priv->cck_txbbgain_table[5].ccktxbb_valuearray[2] = 0x22; + priv->cck_txbbgain_table[5].ccktxbb_valuearray[3] = 0x1c; + priv->cck_txbbgain_table[5].ccktxbb_valuearray[4] = 0x15; + priv->cck_txbbgain_table[5].ccktxbb_valuearray[5] = 0x0d; + priv->cck_txbbgain_table[5].ccktxbb_valuearray[6] = 0x07; + priv->cck_txbbgain_table[5].ccktxbb_valuearray[7] = 0x03; + + priv->cck_txbbgain_table[6].ccktxbb_valuearray[0] = 0x26; + priv->cck_txbbgain_table[6].ccktxbb_valuearray[1] = 0x25; + priv->cck_txbbgain_table[6].ccktxbb_valuearray[2] = 0x21; + priv->cck_txbbgain_table[6].ccktxbb_valuearray[3] = 0x1b; + priv->cck_txbbgain_table[6].ccktxbb_valuearray[4] = 0x14; + priv->cck_txbbgain_table[6].ccktxbb_valuearray[5] = 0x0d; + priv->cck_txbbgain_table[6].ccktxbb_valuearray[6] = 0x06; + priv->cck_txbbgain_table[6].ccktxbb_valuearray[7] = 0x03; + + priv->cck_txbbgain_table[7].ccktxbb_valuearray[0] = 0x24; + priv->cck_txbbgain_table[7].ccktxbb_valuearray[1] = 0x23; + priv->cck_txbbgain_table[7].ccktxbb_valuearray[2] = 0x1f; + priv->cck_txbbgain_table[7].ccktxbb_valuearray[3] = 0x19; + priv->cck_txbbgain_table[7].ccktxbb_valuearray[4] = 0x13; + priv->cck_txbbgain_table[7].ccktxbb_valuearray[5] = 0x0c; + priv->cck_txbbgain_table[7].ccktxbb_valuearray[6] = 0x06; + priv->cck_txbbgain_table[7].ccktxbb_valuearray[7] = 0x03; + + priv->cck_txbbgain_table[8].ccktxbb_valuearray[0] = 0x22; + priv->cck_txbbgain_table[8].ccktxbb_valuearray[1] = 0x21; + priv->cck_txbbgain_table[8].ccktxbb_valuearray[2] = 0x1d; + priv->cck_txbbgain_table[8].ccktxbb_valuearray[3] = 0x18; + priv->cck_txbbgain_table[8].ccktxbb_valuearray[4] = 0x11; + priv->cck_txbbgain_table[8].ccktxbb_valuearray[5] = 0x0b; + priv->cck_txbbgain_table[8].ccktxbb_valuearray[6] = 0x06; + priv->cck_txbbgain_table[8].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[9].ccktxbb_valuearray[0] = 0x20; + priv->cck_txbbgain_table[9].ccktxbb_valuearray[1] = 0x20; + priv->cck_txbbgain_table[9].ccktxbb_valuearray[2] = 0x1b; + priv->cck_txbbgain_table[9].ccktxbb_valuearray[3] = 0x16; + priv->cck_txbbgain_table[9].ccktxbb_valuearray[4] = 0x11; + priv->cck_txbbgain_table[9].ccktxbb_valuearray[5] = 0x08; + priv->cck_txbbgain_table[9].ccktxbb_valuearray[6] = 0x05; + priv->cck_txbbgain_table[9].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[10].ccktxbb_valuearray[0] = 0x1f; + priv->cck_txbbgain_table[10].ccktxbb_valuearray[1] = 0x1e; + priv->cck_txbbgain_table[10].ccktxbb_valuearray[2] = 0x1a; + priv->cck_txbbgain_table[10].ccktxbb_valuearray[3] = 0x15; + priv->cck_txbbgain_table[10].ccktxbb_valuearray[4] = 0x10; + priv->cck_txbbgain_table[10].ccktxbb_valuearray[5] = 0x0a; + priv->cck_txbbgain_table[10].ccktxbb_valuearray[6] = 0x05; + priv->cck_txbbgain_table[10].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[11].ccktxbb_valuearray[0] = 0x1d; + priv->cck_txbbgain_table[11].ccktxbb_valuearray[1] = 0x1c; + priv->cck_txbbgain_table[11].ccktxbb_valuearray[2] = 0x18; + priv->cck_txbbgain_table[11].ccktxbb_valuearray[3] = 0x14; + priv->cck_txbbgain_table[11].ccktxbb_valuearray[4] = 0x0f; + priv->cck_txbbgain_table[11].ccktxbb_valuearray[5] = 0x0a; + priv->cck_txbbgain_table[11].ccktxbb_valuearray[6] = 0x05; + priv->cck_txbbgain_table[11].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[12].ccktxbb_valuearray[0] = 0x1b; + priv->cck_txbbgain_table[12].ccktxbb_valuearray[1] = 0x1a; + priv->cck_txbbgain_table[12].ccktxbb_valuearray[2] = 0x17; + priv->cck_txbbgain_table[12].ccktxbb_valuearray[3] = 0x13; + priv->cck_txbbgain_table[12].ccktxbb_valuearray[4] = 0x0e; + priv->cck_txbbgain_table[12].ccktxbb_valuearray[5] = 0x09; + priv->cck_txbbgain_table[12].ccktxbb_valuearray[6] = 0x04; + priv->cck_txbbgain_table[12].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[13].ccktxbb_valuearray[0] = 0x1a; + priv->cck_txbbgain_table[13].ccktxbb_valuearray[1] = 0x19; + priv->cck_txbbgain_table[13].ccktxbb_valuearray[2] = 0x16; + priv->cck_txbbgain_table[13].ccktxbb_valuearray[3] = 0x12; + priv->cck_txbbgain_table[13].ccktxbb_valuearray[4] = 0x0d; + priv->cck_txbbgain_table[13].ccktxbb_valuearray[5] = 0x09; + priv->cck_txbbgain_table[13].ccktxbb_valuearray[6] = 0x04; + priv->cck_txbbgain_table[13].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[14].ccktxbb_valuearray[0] = 0x18; + priv->cck_txbbgain_table[14].ccktxbb_valuearray[1] = 0x17; + priv->cck_txbbgain_table[14].ccktxbb_valuearray[2] = 0x15; + priv->cck_txbbgain_table[14].ccktxbb_valuearray[3] = 0x11; + priv->cck_txbbgain_table[14].ccktxbb_valuearray[4] = 0x0c; + priv->cck_txbbgain_table[14].ccktxbb_valuearray[5] = 0x08; + priv->cck_txbbgain_table[14].ccktxbb_valuearray[6] = 0x04; + priv->cck_txbbgain_table[14].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[15].ccktxbb_valuearray[0] = 0x17; + priv->cck_txbbgain_table[15].ccktxbb_valuearray[1] = 0x16; + priv->cck_txbbgain_table[15].ccktxbb_valuearray[2] = 0x13; + priv->cck_txbbgain_table[15].ccktxbb_valuearray[3] = 0x10; + priv->cck_txbbgain_table[15].ccktxbb_valuearray[4] = 0x0c; + priv->cck_txbbgain_table[15].ccktxbb_valuearray[5] = 0x08; + priv->cck_txbbgain_table[15].ccktxbb_valuearray[6] = 0x04; + priv->cck_txbbgain_table[15].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[16].ccktxbb_valuearray[0] = 0x16; + priv->cck_txbbgain_table[16].ccktxbb_valuearray[1] = 0x15; + priv->cck_txbbgain_table[16].ccktxbb_valuearray[2] = 0x12; + priv->cck_txbbgain_table[16].ccktxbb_valuearray[3] = 0x0f; + priv->cck_txbbgain_table[16].ccktxbb_valuearray[4] = 0x0b; + priv->cck_txbbgain_table[16].ccktxbb_valuearray[5] = 0x07; + priv->cck_txbbgain_table[16].ccktxbb_valuearray[6] = 0x04; + priv->cck_txbbgain_table[16].ccktxbb_valuearray[7] = 0x01; + + priv->cck_txbbgain_table[17].ccktxbb_valuearray[0] = 0x14; + priv->cck_txbbgain_table[17].ccktxbb_valuearray[1] = 0x14; + priv->cck_txbbgain_table[17].ccktxbb_valuearray[2] = 0x11; + priv->cck_txbbgain_table[17].ccktxbb_valuearray[3] = 0x0e; + priv->cck_txbbgain_table[17].ccktxbb_valuearray[4] = 0x0b; + priv->cck_txbbgain_table[17].ccktxbb_valuearray[5] = 0x07; + priv->cck_txbbgain_table[17].ccktxbb_valuearray[6] = 0x03; + priv->cck_txbbgain_table[17].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[18].ccktxbb_valuearray[0] = 0x13; + priv->cck_txbbgain_table[18].ccktxbb_valuearray[1] = 0x13; + priv->cck_txbbgain_table[18].ccktxbb_valuearray[2] = 0x10; + priv->cck_txbbgain_table[18].ccktxbb_valuearray[3] = 0x0d; + priv->cck_txbbgain_table[18].ccktxbb_valuearray[4] = 0x0a; + priv->cck_txbbgain_table[18].ccktxbb_valuearray[5] = 0x06; + priv->cck_txbbgain_table[18].ccktxbb_valuearray[6] = 0x03; + priv->cck_txbbgain_table[18].ccktxbb_valuearray[7] = 0x01; + + priv->cck_txbbgain_table[19].ccktxbb_valuearray[0] = 0x12; + priv->cck_txbbgain_table[19].ccktxbb_valuearray[1] = 0x12; + priv->cck_txbbgain_table[19].ccktxbb_valuearray[2] = 0x0f; + priv->cck_txbbgain_table[19].ccktxbb_valuearray[3] = 0x0c; + priv->cck_txbbgain_table[19].ccktxbb_valuearray[4] = 0x09; + priv->cck_txbbgain_table[19].ccktxbb_valuearray[5] = 0x06; + priv->cck_txbbgain_table[19].ccktxbb_valuearray[6] = 0x03; + priv->cck_txbbgain_table[19].ccktxbb_valuearray[7] = 0x01; + + priv->cck_txbbgain_table[20].ccktxbb_valuearray[0] = 0x11; + priv->cck_txbbgain_table[20].ccktxbb_valuearray[1] = 0x11; + priv->cck_txbbgain_table[20].ccktxbb_valuearray[2] = 0x0f; + priv->cck_txbbgain_table[20].ccktxbb_valuearray[3] = 0x0c; + priv->cck_txbbgain_table[20].ccktxbb_valuearray[4] = 0x09; + priv->cck_txbbgain_table[20].ccktxbb_valuearray[5] = 0x06; + priv->cck_txbbgain_table[20].ccktxbb_valuearray[6] = 0x03; + priv->cck_txbbgain_table[20].ccktxbb_valuearray[7] = 0x01; + + priv->cck_txbbgain_table[21].ccktxbb_valuearray[0] = 0x10; + priv->cck_txbbgain_table[21].ccktxbb_valuearray[1] = 0x10; + priv->cck_txbbgain_table[21].ccktxbb_valuearray[2] = 0x0e; + priv->cck_txbbgain_table[21].ccktxbb_valuearray[3] = 0x0b; + priv->cck_txbbgain_table[21].ccktxbb_valuearray[4] = 0x08; + priv->cck_txbbgain_table[21].ccktxbb_valuearray[5] = 0x05; + priv->cck_txbbgain_table[21].ccktxbb_valuearray[6] = 0x03; + priv->cck_txbbgain_table[21].ccktxbb_valuearray[7] = 0x01; + + priv->cck_txbbgain_table[22].ccktxbb_valuearray[0] = 0x0f; + priv->cck_txbbgain_table[22].ccktxbb_valuearray[1] = 0x0f; + priv->cck_txbbgain_table[22].ccktxbb_valuearray[2] = 0x0d; + priv->cck_txbbgain_table[22].ccktxbb_valuearray[3] = 0x0b; + priv->cck_txbbgain_table[22].ccktxbb_valuearray[4] = 0x08; + priv->cck_txbbgain_table[22].ccktxbb_valuearray[5] = 0x05; + priv->cck_txbbgain_table[22].ccktxbb_valuearray[6] = 0x03; + priv->cck_txbbgain_table[22].ccktxbb_valuearray[7] = 0x01; + + //ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29 + //This Table is for CH14 + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[0] = 0x36; + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[1] = 0x35; + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[2] = 0x2e; + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[3] = 0x1b; + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[0] = 0x33; + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[1] = 0x32; + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[2] = 0x2b; + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[3] = 0x19; + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[0] = 0x30; + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[1] = 0x2f; + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[2] = 0x29; + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[3] = 0x18; + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[0] = 0x2d; + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[1] = 0x2d; + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[2] = 0x27; + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[3] = 0x17; + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[0] = 0x2b; + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[1] = 0x2a; + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[2] = 0x25; + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[3] = 0x15; + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[0] = 0x28; + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[1] = 0x28; + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[2] = 0x22; + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[3] = 0x14; + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[0] = 0x26; + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[1] = 0x25; + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[2] = 0x21; + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[3] = 0x13; + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[0] = 0x24; + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[1] = 0x23; + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[2] = 0x1f; + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[3] = 0x12; + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[0] = 0x22; + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[1] = 0x21; + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[2] = 0x1d; + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[3] = 0x11; + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[0] = 0x20; + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[1] = 0x20; + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[2] = 0x1b; + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[3] = 0x10; + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[0] = 0x1f; + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[1] = 0x1e; + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[2] = 0x1a; + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[3] = 0x0f; + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[0] = 0x1d; + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[1] = 0x1c; + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[2] = 0x18; + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[3] = 0x0e; + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[0] = 0x1b; + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[1] = 0x1a; + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[2] = 0x17; + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[3] = 0x0e; + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[0] = 0x1a; + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[1] = 0x19; + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[2] = 0x16; + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[3] = 0x0d; + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[0] = 0x18; + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[1] = 0x17; + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[2] = 0x15; + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[3] = 0x0c; + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[0] = 0x17; + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[1] = 0x16; + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[2] = 0x13; + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[3] = 0x0b; + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[0] = 0x16; + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[1] = 0x15; + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[2] = 0x12; + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[3] = 0x0b; + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[0] = 0x14; + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[1] = 0x14; + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[2] = 0x11; + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[3] = 0x0a; + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[0] = 0x13; + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[1] = 0x13; + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[2] = 0x10; + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[3] = 0x0a; + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[0] = 0x12; + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[1] = 0x12; + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[2] = 0x0f; + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[3] = 0x09; + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[0] = 0x11; + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[1] = 0x11; + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[2] = 0x0f; + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[3] = 0x09; + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[0] = 0x10; + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[1] = 0x10; + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[2] = 0x0e; + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[3] = 0x08; + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[0] = 0x0f; + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[1] = 0x0f; + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[2] = 0x0d; + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[3] = 0x08; + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[7] = 0x00; + + priv->btxpower_tracking = TRUE; + priv->txpower_count = 0; + priv->btxpower_trackingInit = FALSE; + +} + +static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + // Tx Power tracking by Theremal Meter require Firmware R/W 3-wire. This mechanism + // can be enabled only when Firmware R/W 3-wire is enabled. Otherwise, frequent r/w + // 3-wire by driver cause RF goes into wrong state. + if(priv->ieee80211->FwRWRF) + priv->btxpower_tracking = TRUE; + else + priv->btxpower_tracking = FALSE; + priv->txpower_count = 0; + priv->btxpower_trackingInit = FALSE; +} + + +void dm_initialize_txpower_tracking(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); +#ifdef RTL8190P + dm_InitializeTXPowerTracking_TSSI(dev); +#else + if(priv->bDcut == TRUE) + dm_InitializeTXPowerTracking_TSSI(dev); + else + dm_InitializeTXPowerTracking_ThermalMeter(dev); +#endif +}// dm_InitializeTXPowerTracking + + +static void dm_CheckTXPowerTracking_TSSI(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + static u32 tx_power_track_counter = 0; + + if(!priv->btxpower_tracking) + return; + else + { + if((tx_power_track_counter % 30 == 0)&&(tx_power_track_counter != 0)) + { + queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0); + } + tx_power_track_counter++; + } + +} + + +static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + static u8 TM_Trigger=0; + //DbgPrint("dm_CheckTXPowerTracking() \n"); + if(!priv->btxpower_tracking) + return; + else + { + if(priv->txpower_count <= 2) + { + priv->txpower_count++; + return; + } + } + + if(!TM_Trigger) + { + //Attention!! You have to wirte all 12bits data to RF, or it may cause RF to crash + //actually write reg0x02 bit1=0, then bit1=1. + //DbgPrint("Trigger ThermalMeter, write RF reg0x2 = 0x4d to 0x4f\n"); + rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); + rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); + rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); + rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); + TM_Trigger = 1; + return; + } + else + { + //DbgPrint("Schedule TxPowerTrackingWorkItem\n"); + queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0); + TM_Trigger = 0; + } +} + + +static void dm_check_txpower_tracking(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + //static u32 tx_power_track_counter = 0; + +#ifdef RTL8190P + dm_CheckTXPowerTracking_TSSI(dev); +#else + if(priv->bDcut == TRUE) + dm_CheckTXPowerTracking_TSSI(dev); + else + dm_CheckTXPowerTracking_ThermalMeter(dev); +#endif + +} // dm_CheckTXPowerTracking + + +static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool bInCH14) +{ + u32 TempVal; + struct r8192_priv *priv = ieee80211_priv(dev); + //Write 0xa22 0xa23 + TempVal = 0; + if(!bInCH14){ + //Write 0xa22 0xa23 + TempVal = priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[0] + + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[1]<<8) ; + + rtl8192_setBBreg(dev, rCCK0_TxFilter1,bMaskHWord, TempVal); + //Write 0xa24 ~ 0xa27 + TempVal = 0; + TempVal = priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[2] + + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[3]<<8) + + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[4]<<16 )+ + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[5]<<24); + rtl8192_setBBreg(dev, rCCK0_TxFilter2,bMaskDWord, TempVal); + //Write 0xa28 0xa29 + TempVal = 0; + TempVal = priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[6] + + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[7]<<8) ; + + rtl8192_setBBreg(dev, rCCK0_DebugPort,bMaskLWord, TempVal); + } + else + { + TempVal = priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[0] + + (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[1]<<8) ; + + rtl8192_setBBreg(dev, rCCK0_TxFilter1,bMaskHWord, TempVal); + //Write 0xa24 ~ 0xa27 + TempVal = 0; + TempVal = priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[2] + + (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[3]<<8) + + (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[4]<<16 )+ + (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[5]<<24); + rtl8192_setBBreg(dev, rCCK0_TxFilter2,bMaskDWord, TempVal); + //Write 0xa28 0xa29 + TempVal = 0; + TempVal = priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[6] + + (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[7]<<8) ; + + rtl8192_setBBreg(dev, rCCK0_DebugPort,bMaskLWord, TempVal); + } + + +} + +static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH14) +{ + u32 TempVal; + struct r8192_priv *priv = ieee80211_priv(dev); + + TempVal = 0; + if(!bInCH14) + { + //Write 0xa22 0xa23 + TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] + + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8) ; + rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); + RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", + rCCK0_TxFilter1, TempVal); + //Write 0xa24 ~ 0xa27 + TempVal = 0; + TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][2] + + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][3]<<8) + + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][4]<<16 )+ + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][5]<<24); + rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); + RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", + rCCK0_TxFilter2, TempVal); + //Write 0xa28 0xa29 + TempVal = 0; + TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] + + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8) ; + + rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); + RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", + rCCK0_DebugPort, TempVal); + } + else + { +// priv->CCKTxPowerAdjustCntNotCh14++; //cosa add for debug. + //Write 0xa22 0xa23 + TempVal = CCKSwingTable_Ch14[priv->CCK_index][0] + + (CCKSwingTable_Ch14[priv->CCK_index][1]<<8) ; + + rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); + RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", + rCCK0_TxFilter1, TempVal); + //Write 0xa24 ~ 0xa27 + TempVal = 0; + TempVal = CCKSwingTable_Ch14[priv->CCK_index][2] + + (CCKSwingTable_Ch14[priv->CCK_index][3]<<8) + + (CCKSwingTable_Ch14[priv->CCK_index][4]<<16 )+ + (CCKSwingTable_Ch14[priv->CCK_index][5]<<24); + rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); + RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", + rCCK0_TxFilter2, TempVal); + //Write 0xa28 0xa29 + TempVal = 0; + TempVal = CCKSwingTable_Ch14[priv->CCK_index][6] + + (CCKSwingTable_Ch14[priv->CCK_index][7]<<8) ; + + rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); + RT_TRACE(COMP_POWER_TRACKING,"CCK chnl 14, reg 0x%x = 0x%x\n", + rCCK0_DebugPort, TempVal); + } +} + + + +extern void dm_cck_txpower_adjust( + struct net_device *dev, + bool binch14 +) +{ // dm_CCKTxPowerAdjust + + struct r8192_priv *priv = ieee80211_priv(dev); +#ifdef RTL8190P + dm_CCKTxPowerAdjust_TSSI(dev, binch14); +#else + if(priv->bDcut == TRUE) + dm_CCKTxPowerAdjust_TSSI(dev, binch14); + else + dm_CCKTxPowerAdjust_ThermalMeter(dev, binch14); +#endif +} + + +#ifndef RTL8192U +static void dm_txpower_reset_recovery( + struct net_device *dev +) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + RT_TRACE(COMP_POWER_TRACKING, "Start Reset Recovery ==>\n"); + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc80 is %08x\n",priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFA_txPowerTrackingIndex is %x\n",priv->rfa_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF A I/Q Amplify Gain is %ld\n",priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbb_iq_amplifygain); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: CCK Attenuation is %d dB\n",priv->cck_present_attentuation); + dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + + rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc90 is %08x\n",priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFC_txPowerTrackingIndex is %x\n",priv->rfc_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF C I/Q Amplify Gain is %ld\n",priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbb_iq_amplifygain); + +} // dm_TXPowerResetRecovery + +extern void dm_restore_dynamic_mechanism_state(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u32 reg_ratr = priv->rate_adaptive.last_ratr; + + if(!priv->up) + { + RT_TRACE(COMP_RATE, "<---- dm_restore_dynamic_mechanism_state(): driver is going to unload\n"); + return; + } + + // + // Restore previous state for rate adaptive + // + if(priv->rate_adaptive.rate_adaptive_disabled) + return; + // TODO: Only 11n mode is implemented currently, + if( !(priv->ieee80211->mode==WIRELESS_MODE_N_24G || + priv->ieee80211->mode==WIRELESS_MODE_N_5G)) + return; + { + /* 2007/11/15 MH Copy from 8190PCI. */ + u32 ratr_value; + ratr_value = reg_ratr; + if(priv->rf_type == RF_1T2R) // 1T2R, Spatial Stream 2 should be disabled + { + ratr_value &=~ (RATE_ALL_OFDM_2SS); + //DbgPrint("HW_VAR_TATR_0 from 0x%x ==> 0x%x\n", ((pu4Byte)(val))[0], ratr_value); + } + //DbgPrint("set HW_VAR_TATR_0 = 0x%x\n", ratr_value); + //cosa PlatformEFIOWrite4Byte(Adapter, RATR0, ((pu4Byte)(val))[0]); + write_nic_dword(dev, RATR0, ratr_value); + write_nic_byte(dev, UFWP, 1); + } + //Resore TX Power Tracking Index + if(priv->btxpower_trackingInit && priv->btxpower_tracking){ + dm_txpower_reset_recovery(dev); + } + + // + //Restore BB Initial Gain + // + dm_bb_initialgain_restore(dev); + +} // DM_RestoreDynamicMechanismState + +static void dm_bb_initialgain_restore(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u32 bit_mask = 0x7f; //Bit0~ Bit6 + + if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) + return; + + //Disable Initial Gain + //PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800); + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); // Only clear byte 1 and rewrite. + rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bit_mask, (u32)priv->initgain_backup.xaagccore1); + rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bit_mask, (u32)priv->initgain_backup.xbagccore1); + rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, bit_mask, (u32)priv->initgain_backup.xcagccore1); + rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, bit_mask, (u32)priv->initgain_backup.xdagccore1); + bit_mask = bMaskByte2; + rtl8192_setBBreg(dev, rCCK0_CCA, bit_mask, (u32)priv->initgain_backup.cca); + + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc50 is %x\n",priv->initgain_backup.xaagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc58 is %x\n",priv->initgain_backup.xbagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc60 is %x\n",priv->initgain_backup.xcagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc68 is %x\n",priv->initgain_backup.xdagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xa0a is %x\n",priv->initgain_backup.cca); + //Enable Initial Gain + //PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x100); + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); // Only clear byte 1 and rewrite. + +} // dm_BBInitialGainRestore + + +extern void dm_backup_dynamic_mechanism_state(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + // Fsync to avoid reset + priv->bswitch_fsync = false; + priv->bfsync_processing = false; + //Backup BB InitialGain + dm_bb_initialgain_backup(dev); + +} // DM_BackupDynamicMechanismState + + +static void dm_bb_initialgain_backup(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u32 bit_mask = bMaskByte0; //Bit0~ Bit6 + + if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) + return; + + //PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800); + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); // Only clear byte 1 and rewrite. + priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bit_mask); + priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, bit_mask); + priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, bit_mask); + priv->initgain_backup.xdagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1, bit_mask); + bit_mask = bMaskByte2; + priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev, rCCK0_CCA, bit_mask); + + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc50 is %x\n",priv->initgain_backup.xaagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc58 is %x\n",priv->initgain_backup.xbagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc60 is %x\n",priv->initgain_backup.xcagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc68 is %x\n",priv->initgain_backup.xdagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xa0a is %x\n",priv->initgain_backup.cca); + +} // dm_BBInitialGainBakcup + +#endif +/*----------------------------------------------------------------------------- + * Function: dm_change_dynamic_initgain_thresh() + * + * Overview: + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/29/2008 amy Create Version 0 porting from windows code. + * + *---------------------------------------------------------------------------*/ +extern void dm_change_dynamic_initgain_thresh(struct net_device *dev, + u32 dm_type, + u32 dm_value) +{ + if (dm_type == DIG_TYPE_THRESH_HIGH) + { + dm_digtable.rssi_high_thresh = dm_value; + } + else if (dm_type == DIG_TYPE_THRESH_LOW) + { + dm_digtable.rssi_low_thresh = dm_value; + } + else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) + { + dm_digtable.rssi_high_power_highthresh = dm_value; + } + else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) + { + dm_digtable.rssi_high_power_highthresh = dm_value; + } + else if (dm_type == DIG_TYPE_ENABLE) + { + dm_digtable.dig_state = DM_STA_DIG_MAX; + dm_digtable.dig_enable_flag = true; + } + else if (dm_type == DIG_TYPE_DISABLE) + { + dm_digtable.dig_state = DM_STA_DIG_MAX; + dm_digtable.dig_enable_flag = false; + } + else if (dm_type == DIG_TYPE_DBG_MODE) + { + if(dm_value >= DM_DBG_MAX) + dm_value = DM_DBG_OFF; + dm_digtable.dbg_mode = (u8)dm_value; + } + else if (dm_type == DIG_TYPE_RSSI) + { + if(dm_value > 100) + dm_value = 30; + dm_digtable.rssi_val = (long)dm_value; + } + else if (dm_type == DIG_TYPE_ALGORITHM) + { + if (dm_value >= DIG_ALGO_MAX) + dm_value = DIG_ALGO_BY_FALSE_ALARM; + if(dm_digtable.dig_algorithm != (u8)dm_value) + dm_digtable.dig_algorithm_switch = 1; + dm_digtable.dig_algorithm = (u8)dm_value; + } + else if (dm_type == DIG_TYPE_BACKOFF) + { + if(dm_value > 30) + dm_value = 30; + dm_digtable.backoff_val = (u8)dm_value; + } + else if(dm_type == DIG_TYPE_RX_GAIN_MIN) + { + if(dm_value == 0) + dm_value = 0x1; + dm_digtable.rx_gain_range_min = (u8)dm_value; + } + else if(dm_type == DIG_TYPE_RX_GAIN_MAX) + { + if(dm_value > 0x50) + dm_value = 0x50; + dm_digtable.rx_gain_range_max = (u8)dm_value; + } +} /* DM_ChangeDynamicInitGainThresh */ +extern void +dm_change_fsync_setting( + struct net_device *dev, + s32 DM_Type, + s32 DM_Value) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + if (DM_Type == 0) // monitor 0xc38 register + { + if(DM_Value > 1) + DM_Value = 1; + priv->framesyncMonitor = (u8)DM_Value; + //DbgPrint("pHalData->framesyncMonitor = %d", pHalData->framesyncMonitor); + } +} + +extern void +dm_change_rxpath_selection_setting( + struct net_device *dev, + s32 DM_Type, + s32 DM_Value) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + prate_adaptive pRA = (prate_adaptive)&(priv->rate_adaptive); + + + if(DM_Type == 0) + { + if(DM_Value > 1) + DM_Value = 1; + DM_RxPathSelTable.Enable = (u8)DM_Value; + } + else if(DM_Type == 1) + { + if(DM_Value > 1) + DM_Value = 1; + DM_RxPathSelTable.DbgMode = (u8)DM_Value; + } + else if(DM_Type == 2) + { + if(DM_Value > 40) + DM_Value = 40; + DM_RxPathSelTable.SS_TH_low = (u8)DM_Value; + } + else if(DM_Type == 3) + { + if(DM_Value > 25) + DM_Value = 25; + DM_RxPathSelTable.diff_TH = (u8)DM_Value; + } + else if(DM_Type == 4) + { + if(DM_Value >= CCK_Rx_Version_MAX) + DM_Value = CCK_Rx_Version_1; + DM_RxPathSelTable.cck_method= (u8)DM_Value; + } + else if(DM_Type == 10) + { + if(DM_Value > 100) + DM_Value = 50; + DM_RxPathSelTable.rf_rssi[0] = (u8)DM_Value; + } + else if(DM_Type == 11) + { + if(DM_Value > 100) + DM_Value = 50; + DM_RxPathSelTable.rf_rssi[1] = (u8)DM_Value; + } + else if(DM_Type == 12) + { + if(DM_Value > 100) + DM_Value = 50; + DM_RxPathSelTable.rf_rssi[2] = (u8)DM_Value; + } + else if(DM_Type == 13) + { + if(DM_Value > 100) + DM_Value = 50; + DM_RxPathSelTable.rf_rssi[3] = (u8)DM_Value; + } + else if(DM_Type == 20) + { + if(DM_Value > 1) + DM_Value = 1; + pRA->ping_rssi_enable = (u8)DM_Value; + } + else if(DM_Type == 21) + { + if(DM_Value > 30) + DM_Value = 30; + pRA->ping_rssi_thresh_for_ra = DM_Value; + } +} + + +/*----------------------------------------------------------------------------- + * Function: dm_dig_init() + * + * Overview: Set DIG scheme init value. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/15/2008 amy Create Version 0 porting from windows code. + * + *---------------------------------------------------------------------------*/ +static void dm_dig_init(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + /* 2007/10/05 MH Disable DIG scheme now. Not tested. */ + dm_digtable.dig_enable_flag = true; + dm_digtable.dig_algorithm = DIG_ALGO_BY_RSSI; + dm_digtable.dbg_mode = DM_DBG_OFF; //off=by real rssi value, on=by DM_DigTable.Rssi_val for new dig + dm_digtable.dig_algorithm_switch = 0; + + /* 2007/10/04 MH Define init gain threshol. */ + dm_digtable.dig_state = DM_STA_DIG_MAX; + dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX; + dm_digtable.initialgain_lowerbound_state = false; + + dm_digtable.rssi_low_thresh = DM_DIG_THRESH_LOW; + dm_digtable.rssi_high_thresh = DM_DIG_THRESH_HIGH; + + dm_digtable.rssi_high_power_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW; + dm_digtable.rssi_high_power_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH; + + dm_digtable.rssi_val = 50; //for new dig debug rssi value + dm_digtable.backoff_val = DM_DIG_BACKOFF; + dm_digtable.rx_gain_range_max = DM_DIG_MAX; + if(priv->CustomerID == RT_CID_819x_Netcore) + dm_digtable.rx_gain_range_min = DM_DIG_MIN_Netcore; + else + dm_digtable.rx_gain_range_min = DM_DIG_MIN; + +} /* dm_dig_init */ + + +/*----------------------------------------------------------------------------- + * Function: dm_ctrl_initgain_byrssi() + * + * Overview: Driver must monitor RSSI and notify firmware to change initial + * gain according to different threshold. BB team provide the + * suggested solution. + * + * Input: struct net_device *dev + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/27/2008 amy Create Version 0 porting from windows code. + *---------------------------------------------------------------------------*/ +static void dm_ctrl_initgain_byrssi(struct net_device *dev) +{ + + if (dm_digtable.dig_enable_flag == false) + return; + + if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM) + dm_ctrl_initgain_byrssi_by_fwfalse_alarm(dev); + else if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) + dm_ctrl_initgain_byrssi_by_driverrssi(dev); +// ; + else + return; +} + + +static void dm_ctrl_initgain_byrssi_by_driverrssi( + struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u8 i; + static u8 fw_dig=0; + + if (dm_digtable.dig_enable_flag == false) + return; + + //DbgPrint("Dig by Sw Rssi \n"); + if(dm_digtable.dig_algorithm_switch) // if swithed algorithm, we have to disable FW Dig. + fw_dig = 0; + if(fw_dig <= 3) // execute several times to make sure the FW Dig is disabled + {// FW DIG Off + for(i=0; i<3; i++) + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); // Only clear byte 1 and rewrite. + fw_dig++; + dm_digtable.dig_state = DM_STA_DIG_OFF; //fw dig off. + } + + if(priv->ieee80211->state == IEEE80211_LINKED) + dm_digtable.cur_connect_state = DIG_CONNECT; + else + dm_digtable.cur_connect_state = DIG_DISCONNECT; + + //DbgPrint("DM_DigTable.PreConnectState = %d, DM_DigTable.CurConnectState = %d \n", + //DM_DigTable.PreConnectState, DM_DigTable.CurConnectState); + + if(dm_digtable.dbg_mode == DM_DBG_OFF) + dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb; + //DbgPrint("DM_DigTable.Rssi_val = %d \n", DM_DigTable.Rssi_val); + dm_initial_gain(dev); + dm_pd_th(dev); + dm_cs_ratio(dev); + if(dm_digtable.dig_algorithm_switch) + dm_digtable.dig_algorithm_switch = 0; + dm_digtable.pre_connect_state = dm_digtable.cur_connect_state; + +} /* dm_CtrlInitGainByRssi */ + +static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( + struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + static u32 reset_cnt = 0; + u8 i; + + if (dm_digtable.dig_enable_flag == false) + return; + + if(dm_digtable.dig_algorithm_switch) + { + dm_digtable.dig_state = DM_STA_DIG_MAX; + // Fw DIG On. + for(i=0; i<3; i++) + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); // Only clear byte 1 and rewrite. + dm_digtable.dig_algorithm_switch = 0; + } + + if (priv->ieee80211->state != IEEE80211_LINKED) + return; + + // For smooth, we can not change DIG state. + if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_low_thresh) && + (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_thresh)) + { + return; + } + //DbgPrint("Dig by Fw False Alarm\n"); + //if (DM_DigTable.Dig_State == DM_STA_DIG_OFF) + /*DbgPrint("DIG Check\n\r RSSI=%d LOW=%d HIGH=%d STATE=%d", + pHalData->UndecoratedSmoothedPWDB, DM_DigTable.RssiLowThresh, + DM_DigTable.RssiHighThresh, DM_DigTable.Dig_State);*/ + /* 1. When RSSI decrease, We have to judge if it is smaller than a treshold + and then execute below step. */ + if ((priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh)) + { + /* 2008/02/05 MH When we execute silent reset, the DIG PHY parameters + will be reset to init value. We must prevent the condition. */ + if (dm_digtable.dig_state == DM_STA_DIG_OFF && + (priv->reset_count == reset_cnt)) + { + return; + } + else + { + reset_cnt = priv->reset_count; + } + + // If DIG is off, DIG high power state must reset. + dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX; + dm_digtable.dig_state = DM_STA_DIG_OFF; + + // 1.1 DIG Off. + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); // Only clear byte 1 and rewrite. + + // 1.2 Set initial gain. + write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x17); + write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x17); + write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x17); + write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x17); + + // 1.3 Lower PD_TH for OFDM. + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */ + // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector1, 0x40); + #else + write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00); + #endif + /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) + write_nic_byte(pAdapter, rOFDM0_RxDetector1, 0x40); + */ + //else if (pAdapter->HardwareType == HARDWARE_TYPE_RTL8192E) + + + //else + //PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x40); + } + else + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + + // 1.4 Lower CS ratio for CCK. + write_nic_byte(dev, 0xa0a, 0x08); + + // 1.5 Higher EDCCA. + //PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x325); + return; + + } + + /* 2. When RSSI increase, We have to judge if it is larger than a treshold + and then execute below step. */ + if ((priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) ) + { + u8 reset_flag = 0; + + if (dm_digtable.dig_state == DM_STA_DIG_ON && + (priv->reset_count == reset_cnt)) + { + dm_ctrl_initgain_byrssi_highpwr(dev); + return; + } + else + { + if (priv->reset_count != reset_cnt) + reset_flag = 1; + + reset_cnt = priv->reset_count; + } + + dm_digtable.dig_state = DM_STA_DIG_ON; + //DbgPrint("DIG ON\n\r"); + + // 2.1 Set initial gain. + // 2008/02/26 MH SD3-Jerry suggest to prevent dirty environment. + if (reset_flag == 1) + { + write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x2c); + write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x2c); + write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x2c); + write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x2c); + } + else + { + write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x20); + write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x20); + write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x20); + write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x20); + } + + // 2.2 Higher PD_TH for OFDM. + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */ + // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + #else + write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); + #endif + /* + else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + */ + //else if (pAdapter->HardwareType == HARDWARE_TYPE_RTL8192E) + + //else + //PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x42); + } + else + write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); + + // 2.3 Higher CS ratio for CCK. + write_nic_byte(dev, 0xa0a, 0xcd); + + // 2.4 Lower EDCCA. + /* 2008/01/11 MH 90/92 series are the same. */ + //PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x346); + + // 2.5 DIG On. + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); // Only clear byte 1 and rewrite. + + } + + dm_ctrl_initgain_byrssi_highpwr(dev); + +} /* dm_CtrlInitGainByRssi */ + + +/*----------------------------------------------------------------------------- + * Function: dm_ctrl_initgain_byrssi_highpwr() + * + * Overview: + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/28/2008 amy Create Version 0 porting from windows code. + * + *---------------------------------------------------------------------------*/ +static void dm_ctrl_initgain_byrssi_highpwr( + struct net_device * dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + static u32 reset_cnt_highpwr = 0; + + // For smooth, we can not change high power DIG state in the range. + if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_high_power_lowthresh) && + (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_highthresh)) + { + return; + } + + /* 3. When RSSI >75% or <70%, it is a high power issue. We have to judge if + it is larger than a treshold and then execute below step. */ + // 2008/02/05 MH SD3-Jerry Modify PD_TH for high power issue. + if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh) + { + if (dm_digtable.dig_highpwr_state == DM_STA_DIG_ON && + (priv->reset_count == reset_cnt_highpwr)) + return; + else + dm_digtable.dig_highpwr_state = DM_STA_DIG_ON; + + // 3.1 Higher PD_TH for OFDM for high power state. + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector1, 0x41); + #else + write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10); + #endif + + /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) + write_nic_byte(dev, rOFDM0_RxDetector1, 0x41); + */ + + } + else + write_nic_byte(dev, rOFDM0_RxDetector1, 0x43); + } + else + { + if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF&& + (priv->reset_count == reset_cnt_highpwr)) + return; + else + dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF; + + if (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_lowthresh && + priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) + { + // 3.2 Recover PD_TH for OFDM for normal power region. + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + #else + write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); + #endif + /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + */ + + } + else + write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); + } + } + + reset_cnt_highpwr = priv->reset_count; + +} /* dm_CtrlInitGainByRssiHighPwr */ + + +static void dm_initial_gain( + struct net_device * dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u8 initial_gain=0; + static u8 initialized=0, force_write=0; + static u32 reset_cnt=0; + + if(dm_digtable.dig_algorithm_switch) + { + initialized = 0; + reset_cnt = 0; + } + + if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) + { + if(dm_digtable.cur_connect_state == DIG_CONNECT) + { + if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) > dm_digtable.rx_gain_range_max) + dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_max; + else if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min) + dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_min; + else + dm_digtable.cur_ig_value = dm_digtable.rssi_val+10-dm_digtable.backoff_val; + } + else //current state is disconnected + { + if(dm_digtable.cur_ig_value == 0) + dm_digtable.cur_ig_value = priv->DefaultInitialGain[0]; + else + dm_digtable.cur_ig_value = dm_digtable.pre_ig_value; + } + } + else // disconnected -> connected or connected -> disconnected + { + dm_digtable.cur_ig_value = priv->DefaultInitialGain[0]; + dm_digtable.pre_ig_value = 0; + } + //DbgPrint("DM_DigTable.CurIGValue = 0x%x, DM_DigTable.PreIGValue = 0x%x\n", DM_DigTable.CurIGValue, DM_DigTable.PreIGValue); + + // if silent reset happened, we should rewrite the values back + if(priv->reset_count != reset_cnt) + { + force_write = 1; + reset_cnt = priv->reset_count; + } + + if(dm_digtable.pre_ig_value != read_nic_byte(dev, rOFDM0_XAAGCCore1)) + force_write = 1; + + { + if((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value) + || !initialized || force_write) + { + initial_gain = (u8)dm_digtable.cur_ig_value; + //DbgPrint("Write initial gain = 0x%x\n", initial_gain); + // Set initial gain. + write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain); + write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain); + write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain); + write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain); + dm_digtable.pre_ig_value = dm_digtable.cur_ig_value; + initialized = 1; + force_write = 0; + } + } +} + +static void dm_pd_th( + struct net_device * dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + static u8 initialized=0, force_write=0; + static u32 reset_cnt = 0; + + if(dm_digtable.dig_algorithm_switch) + { + initialized = 0; + reset_cnt = 0; + } + + if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) + { + if(dm_digtable.cur_connect_state == DIG_CONNECT) + { + if (dm_digtable.rssi_val >= dm_digtable.rssi_high_power_highthresh) + dm_digtable.curpd_thstate = DIG_PD_AT_HIGH_POWER; + else if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)) + dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; + else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) && + (dm_digtable.rssi_val < dm_digtable.rssi_high_power_lowthresh)) + dm_digtable.curpd_thstate = DIG_PD_AT_NORMAL_POWER; + else + dm_digtable.curpd_thstate = dm_digtable.prepd_thstate; + } + else + { + dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; + } + } + else // disconnected -> connected or connected -> disconnected + { + dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; + } + + // if silent reset happened, we should rewrite the values back + if(priv->reset_count != reset_cnt) + { + force_write = 1; + reset_cnt = priv->reset_count; + } + + { + if((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) || + (initialized<=3) || force_write) + { + //DbgPrint("Write PD_TH state = %d\n", DM_DigTable.CurPD_THState); + if(dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) + { + // Lower PD_TH for OFDM. + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */ + // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector1, 0x40); + #else + write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00); + #endif + /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) + write_nic_byte(dev, rOFDM0_RxDetector1, 0x40); + */ + } + else + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + } + else if(dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER) + { + // Higher PD_TH for OFDM. + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */ + // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + #else + write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); + #endif + /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + */ + } + else + write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); + } + else if(dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) + { + // Higher PD_TH for OFDM for high power state. + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector1, 0x41); + #else + write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10); + #endif + /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) + write_nic_byte(dev, rOFDM0_RxDetector1, 0x41); + */ + } + else + write_nic_byte(dev, rOFDM0_RxDetector1, 0x43); + } + dm_digtable.prepd_thstate = dm_digtable.curpd_thstate; + if(initialized <= 3) + initialized++; + force_write = 0; + } + } +} + +static void dm_cs_ratio( + struct net_device * dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + static u8 initialized=0,force_write=0; + static u32 reset_cnt = 0; + + if(dm_digtable.dig_algorithm_switch) + { + initialized = 0; + reset_cnt = 0; + } + + if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) + { + if(dm_digtable.cur_connect_state == DIG_CONNECT) + { + if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)) + dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; + else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) ) + dm_digtable.curcs_ratio_state = DIG_CS_RATIO_HIGHER; + else + dm_digtable.curcs_ratio_state = dm_digtable.precs_ratio_state; + } + else + { + dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; + } + } + else // disconnected -> connected or connected -> disconnected + { + dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; + } + + // if silent reset happened, we should rewrite the values back + if(priv->reset_count != reset_cnt) + { + force_write = 1; + reset_cnt = priv->reset_count; + } + + + { + if((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) || + !initialized || force_write) + { + //DbgPrint("Write CS_ratio state = %d\n", DM_DigTable.CurCS_ratioState); + if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER) + { + // Lower CS ratio for CCK. + write_nic_byte(dev, 0xa0a, 0x08); + } + else if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER) + { + // Higher CS ratio for CCK. + write_nic_byte(dev, 0xa0a, 0xcd); + } + dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state; + initialized = 1; + force_write = 0; + } + } +} + +extern void dm_init_edca_turbo(struct net_device * dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + priv->bcurrent_turbo_EDCA = false; + priv->ieee80211->bis_any_nonbepkts = false; + priv->bis_cur_rdlstate = false; +} // dm_init_edca_turbo + +static void dm_check_edca_turbo( + struct net_device * dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo; + //PSTA_QOS pStaQos = pMgntInfo->pStaQos; + + // Keep past Tx/Rx packet count for RT-to-RT EDCA turbo. + static unsigned long lastTxOkCnt = 0; + static unsigned long lastRxOkCnt = 0; + unsigned long curTxOkCnt = 0; + unsigned long curRxOkCnt = 0; + + // + // Do not be Turbo if it's under WiFi config and Qos Enabled, because the EDCA parameters + // should follow the settings from QAP. By Bruce, 2007-12-07. + // + if(priv->ieee80211->state != IEEE80211_LINKED) + goto dm_CheckEdcaTurbo_EXIT; + // We do not turn on EDCA turbo mode for some AP that has IOT issue + if(priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO) + goto dm_CheckEdcaTurbo_EXIT; + +// printk("========>%s():bis_any_nonbepkts is %d\n",__FUNCTION__,priv->bis_any_nonbepkts); + // Check the status for current condition. + if(!priv->ieee80211->bis_any_nonbepkts) + { + curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; + curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; + // For RT-AP, we needs to turn it on when Rx>Tx + if(curRxOkCnt > 4*curTxOkCnt) + { + //printk("%s():curRxOkCnt > 4*curTxOkCnt\n"); + if(!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) + { + write_nic_dword(dev, EDCAPARA_BE, edca_setting_DL[pHTInfo->IOTPeer]); + priv->bis_cur_rdlstate = true; + } + } + else + { + + //printk("%s():curRxOkCnt < 4*curTxOkCnt\n"); + if(priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) + { + write_nic_dword(dev, EDCAPARA_BE, edca_setting_UL[pHTInfo->IOTPeer]); + priv->bis_cur_rdlstate = false; + } + + } + + priv->bcurrent_turbo_EDCA = true; + } + else + { + // + // Turn Off EDCA turbo here. + // Restore original EDCA according to the declaration of AP. + // + if(priv->bcurrent_turbo_EDCA) + { + + { + u8 u1bAIFS; + u32 u4bAcParam; + struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters; + u8 mode = priv->ieee80211->mode; + + // For Each time updating EDCA parameter, reset EDCA turbo mode status. + dm_init_edca_turbo(dev); + u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime; + u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[0]))<< AC_PARAM_TXOP_LIMIT_OFFSET)| + (((u32)(qos_parameters->cw_max[0]))<< AC_PARAM_ECW_MAX_OFFSET)| + (((u32)(qos_parameters->cw_min[0]))<< AC_PARAM_ECW_MIN_OFFSET)| + ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET)); + //write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam); + write_nic_dword(dev, EDCAPARA_BE, u4bAcParam); + + // Check ACM bit. + // If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13. + { + // TODO: Modified this part and try to set acm control in only 1 IO processing!! + + PACI_AIFSN pAciAifsn = (PACI_AIFSN)&(qos_parameters->aifs[0]); + u8 AcmCtrl = read_nic_byte( dev, AcmHwCtrl ); + if( pAciAifsn->f.ACM ) + { // ACM bit is 1. + AcmCtrl |= AcmHw_BeqEn; + } + else + { // ACM bit is 0. + AcmCtrl &= (~AcmHw_BeqEn); + } + + RT_TRACE( COMP_QOS,"SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl ) ; + write_nic_byte(dev, AcmHwCtrl, AcmCtrl ); + } + } + priv->bcurrent_turbo_EDCA = false; + } + } + + +dm_CheckEdcaTurbo_EXIT: + // Set variables for next time. + priv->ieee80211->bis_any_nonbepkts = false; + lastTxOkCnt = priv->stats.txbytesunicast; + lastRxOkCnt = priv->stats.rxbytesunicast; +} // dm_CheckEdcaTurbo + +extern void DM_CTSToSelfSetting(struct net_device * dev,u32 DM_Type, u32 DM_Value) +{ + struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev); + + if (DM_Type == 0) // CTS to self disable/enable + { + if(DM_Value > 1) + DM_Value = 1; + priv->ieee80211->bCTSToSelfEnable = (bool)DM_Value; + //DbgPrint("pMgntInfo->bCTSToSelfEnable = %d\n", pMgntInfo->bCTSToSelfEnable); + } + else if(DM_Type == 1) //CTS to self Th + { + if(DM_Value >= 50) + DM_Value = 50; + priv->ieee80211->CTSToSelfTH = (u8)DM_Value; + //DbgPrint("pMgntInfo->CTSToSelfTH = %d\n", pMgntInfo->CTSToSelfTH); + } +} + +static void dm_init_ctstoself(struct net_device * dev) +{ + struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev); + + priv->ieee80211->bCTSToSelfEnable = TRUE; + priv->ieee80211->CTSToSelfTH = CTSToSelfTHVal; +} + +static void dm_ctstoself(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev); + PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo; + static unsigned long lastTxOkCnt = 0; + static unsigned long lastRxOkCnt = 0; + unsigned long curTxOkCnt = 0; + unsigned long curRxOkCnt = 0; + + if(priv->ieee80211->bCTSToSelfEnable != TRUE) + { + pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF; + return; + } + /* + 1. Uplink + 2. Linksys350/Linksys300N + 3. <50 disable, >55 enable + */ + + if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) + { + curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; + curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; + if(curRxOkCnt > 4*curTxOkCnt) //downlink, disable CTS to self + { + pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF; + //DbgPrint("dm_CTSToSelf() ==> CTS to self disabled -- downlink\n"); + } + else //uplink + { + pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF; + } + + lastTxOkCnt = priv->stats.txbytesunicast; + lastRxOkCnt = priv->stats.rxbytesunicast; + } +} + + +/*----------------------------------------------------------------------------- + * Function: dm_check_rfctrl_gpio() + * + * Overview: Copy 8187B template for 9xseries. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/28/2008 amy Create Version 0 porting from windows code. + * + *---------------------------------------------------------------------------*/ +static void dm_check_rfctrl_gpio(struct net_device * dev) +{ + //struct r8192_priv *priv = ieee80211_priv(dev); + + // Walk around for DTM test, we will not enable HW - radio on/off because r/w + // page 1 register before Lextra bus is enabled cause system fails when resuming + // from S4. 20080218, Emily + + // Stop to execute workitem to prevent S3/S4 bug. +#ifdef RTL8190P + return; +#endif +#ifdef RTL8192U + return; +#endif +#ifdef RTL8192E + queue_delayed_work(priv->priv_wq,&priv->gpio_change_rf_wq,0); +#endif + +} /* dm_CheckRfCtrlGPIO */ + +/*----------------------------------------------------------------------------- + * Function: dm_check_pbc_gpio() + * + * Overview: Check if PBC button is pressed. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/28/2008 amy Create Version 0 porting from windows code. + * + *---------------------------------------------------------------------------*/ +static void dm_check_pbc_gpio(struct net_device *dev) +{ +#ifdef RTL8192U + struct r8192_priv *priv = ieee80211_priv(dev); + u8 tmp1byte; + + + tmp1byte = read_nic_byte(dev,GPI); + if(tmp1byte == 0xff) + return; + + if (tmp1byte&BIT6 || tmp1byte&BIT0) + { + // Here we only set bPbcPressed to TRUE + // After trigger PBC, the variable will be set to FALSE + RT_TRACE(COMP_IO, "CheckPbcGPIO - PBC is pressed\n"); + priv->bpbc_pressed = true; + } +#endif + +} + +#ifdef RTL8192E + +/*----------------------------------------------------------------------------- + * Function: dm_GPIOChangeRF + * Overview: PCI will not support workitem call back HW radio on-off control. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 02/21/2008 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +extern void dm_gpio_change_rf_callback(struct work_struct *work) +{ + struct delayed_work *dwork = container_of(work,struct delayed_work,work); + struct r8192_priv *priv = container_of(dwork,struct r8192_priv,gpio_change_rf_wq); + struct net_device *dev = priv->ieee80211->dev; + u8 tmp1byte; + RT_RF_POWER_STATE eRfPowerStateToSet; + bool bActuallySet = false; + + do{ + bActuallySet=false; + + if(!priv->up) + { + RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF),"dm_gpio_change_rf_callback(): Callback function breaks out!!\n"); + } + else + { + // 0x108 GPIO input register is read only + //set 0x108 B1= 1: RF-ON; 0: RF-OFF. + tmp1byte = read_nic_byte(dev,GPI); + + eRfPowerStateToSet = (tmp1byte&BIT1) ? eRfOn : eRfOff; + + if( (priv->bHwRadioOff == true) && (eRfPowerStateToSet == eRfOn)) + { + RT_TRACE(COMP_RF, "gpiochangeRF - HW Radio ON\n"); + + priv->bHwRadioOff = false; + bActuallySet = true; + } + else if ( (priv->bHwRadioOff == false) && (eRfPowerStateToSet == eRfOff)) + { + RT_TRACE(COMP_RF, "gpiochangeRF - HW Radio OFF\n"); + priv->bHwRadioOff = true; + bActuallySet = true; + } + + if(bActuallySet) + { + #ifdef TO_DO + MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW); + //DrvIFIndicateCurrentPhyStatus(pAdapter); + #endif + } + else + { + msleep(2000); + } + + } + }while(TRUE) + +} /* dm_GPIOChangeRF */ + +#endif +/*----------------------------------------------------------------------------- + * Function: DM_RFPathCheckWorkItemCallBack() + * + * Overview: Check if Current RF RX path is enabled + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 01/30/2008 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +extern void dm_rf_pathcheck_workitemcallback(struct work_struct *work) +{ + struct delayed_work *dwork = container_of(work,struct delayed_work,work); + struct r8192_priv *priv = container_of(dwork,struct r8192_priv,rfpath_check_wq); + struct net_device *dev =priv->ieee80211->dev; + //bool bactually_set = false; + u8 rfpath = 0, i; + + + /* 2008/01/30 MH After discussing with SD3 Jerry, 0xc04/0xd04 register will + always be the same. We only read 0xc04 now. */ + rfpath = read_nic_byte(dev, 0xc04); + + // Check Bit 0-3, it means if RF A-D is enabled. + for (i = 0; i < RF90_PATH_MAX; i++) + { + if (rfpath & (0x01<brfpath_rxenable[i] = 1; + else + priv->brfpath_rxenable[i] = 0; + } + if(!DM_RxPathSelTable.Enable) + return; + + dm_rxpath_sel_byrssi(dev); +} /* DM_RFPathCheckWorkItemCallBack */ + +static void dm_init_rxpath_selection(struct net_device * dev) +{ + u8 i; + struct r8192_priv *priv = ieee80211_priv(dev); + DM_RxPathSelTable.Enable = 1; //default enabled + DM_RxPathSelTable.SS_TH_low = RxPathSelection_SS_TH_low; + DM_RxPathSelTable.diff_TH = RxPathSelection_diff_TH; + if(priv->CustomerID == RT_CID_819x_Netcore) + DM_RxPathSelTable.cck_method = CCK_Rx_Version_2; + else + DM_RxPathSelTable.cck_method = CCK_Rx_Version_1; + DM_RxPathSelTable.DbgMode = DM_DBG_OFF; + DM_RxPathSelTable.disabledRF = 0; + for(i=0; i<4; i++) + { + DM_RxPathSelTable.rf_rssi[i] = 50; + DM_RxPathSelTable.cck_pwdb_sta[i] = -64; + DM_RxPathSelTable.rf_enable_rssi_th[i] = 100; + } +} + +static void dm_rxpath_sel_byrssi(struct net_device * dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u8 i, max_rssi_index=0, min_rssi_index=0, sec_rssi_index=0, rf_num=0; + u8 tmp_max_rssi=0, tmp_min_rssi=0, tmp_sec_rssi=0; + u8 cck_default_Rx=0x2; //RF-C + u8 cck_optional_Rx=0x3;//RF-D + long tmp_cck_max_pwdb=0, tmp_cck_min_pwdb=0, tmp_cck_sec_pwdb=0; + u8 cck_rx_ver2_max_index=0, cck_rx_ver2_min_index=0, cck_rx_ver2_sec_index=0; + u8 cur_rf_rssi; + long cur_cck_pwdb; + static u8 disabled_rf_cnt=0, cck_Rx_Path_initialized=0; + u8 update_cck_rx_path; + + if(priv->rf_type != RF_2T4R) + return; + + if(!cck_Rx_Path_initialized) + { + DM_RxPathSelTable.cck_Rx_path = (read_nic_byte(dev, 0xa07)&0xf); + cck_Rx_Path_initialized = 1; + } + + DM_RxPathSelTable.disabledRF = 0xf; + DM_RxPathSelTable.disabledRF &=~ (read_nic_byte(dev, 0xc04)); + + if(priv->ieee80211->mode == WIRELESS_MODE_B) + { + DM_RxPathSelTable.cck_method = CCK_Rx_Version_2; //pure B mode, fixed cck version2 + //DbgPrint("Pure B mode, use cck rx version2 \n"); + } + + //decide max/sec/min rssi index + for (i=0; istats.rx_rssi_percentage[i]; + + if(priv->brfpath_rxenable[i]) + { + rf_num++; + cur_rf_rssi = DM_RxPathSelTable.rf_rssi[i]; + + if(rf_num == 1) // find first enabled rf path and the rssi values + { //initialize, set all rssi index to the same one + max_rssi_index = min_rssi_index = sec_rssi_index = i; + tmp_max_rssi = tmp_min_rssi = tmp_sec_rssi = cur_rf_rssi; + } + else if(rf_num == 2) + { // we pick up the max index first, and let sec and min to be the same one + if(cur_rf_rssi >= tmp_max_rssi) + { + tmp_max_rssi = cur_rf_rssi; + max_rssi_index = i; + } + else + { + tmp_sec_rssi = tmp_min_rssi = cur_rf_rssi; + sec_rssi_index = min_rssi_index = i; + } + } + else + { + if(cur_rf_rssi > tmp_max_rssi) + { + tmp_sec_rssi = tmp_max_rssi; + sec_rssi_index = max_rssi_index; + tmp_max_rssi = cur_rf_rssi; + max_rssi_index = i; + } + else if(cur_rf_rssi == tmp_max_rssi) + { // let sec and min point to the different index + tmp_sec_rssi = cur_rf_rssi; + sec_rssi_index = i; + } + else if((cur_rf_rssi < tmp_max_rssi) &&(cur_rf_rssi > tmp_sec_rssi)) + { + tmp_sec_rssi = cur_rf_rssi; + sec_rssi_index = i; + } + else if(cur_rf_rssi == tmp_sec_rssi) + { + if(tmp_sec_rssi == tmp_min_rssi) + { // let sec and min point to the different index + tmp_sec_rssi = cur_rf_rssi; + sec_rssi_index = i; + } + else + { + // This case we don't need to set any index + } + } + else if((cur_rf_rssi < tmp_sec_rssi) && (cur_rf_rssi > tmp_min_rssi)) + { + // This case we don't need to set any index + } + else if(cur_rf_rssi == tmp_min_rssi) + { + if(tmp_sec_rssi == tmp_min_rssi) + { // let sec and min point to the different index + tmp_min_rssi = cur_rf_rssi; + min_rssi_index = i; + } + else + { + // This case we don't need to set any index + } + } + else if(cur_rf_rssi < tmp_min_rssi) + { + tmp_min_rssi = cur_rf_rssi; + min_rssi_index = i; + } + } + } + } + + rf_num = 0; + // decide max/sec/min cck pwdb index + if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) + { + for (i=0; ibrfpath_rxenable[i]) + { + rf_num++; + cur_cck_pwdb = DM_RxPathSelTable.cck_pwdb_sta[i]; + + if(rf_num == 1) // find first enabled rf path and the rssi values + { //initialize, set all rssi index to the same one + cck_rx_ver2_max_index = cck_rx_ver2_min_index = cck_rx_ver2_sec_index = i; + tmp_cck_max_pwdb = tmp_cck_min_pwdb = tmp_cck_sec_pwdb = cur_cck_pwdb; + } + else if(rf_num == 2) + { // we pick up the max index first, and let sec and min to be the same one + if(cur_cck_pwdb >= tmp_cck_max_pwdb) + { + tmp_cck_max_pwdb = cur_cck_pwdb; + cck_rx_ver2_max_index = i; + } + else + { + tmp_cck_sec_pwdb = tmp_cck_min_pwdb = cur_cck_pwdb; + cck_rx_ver2_sec_index = cck_rx_ver2_min_index = i; + } + } + else + { + if(cur_cck_pwdb > tmp_cck_max_pwdb) + { + tmp_cck_sec_pwdb = tmp_cck_max_pwdb; + cck_rx_ver2_sec_index = cck_rx_ver2_max_index; + tmp_cck_max_pwdb = cur_cck_pwdb; + cck_rx_ver2_max_index = i; + } + else if(cur_cck_pwdb == tmp_cck_max_pwdb) + { // let sec and min point to the different index + tmp_cck_sec_pwdb = cur_cck_pwdb; + cck_rx_ver2_sec_index = i; + } + else if((cur_cck_pwdb < tmp_cck_max_pwdb) &&(cur_cck_pwdb > tmp_cck_sec_pwdb)) + { + tmp_cck_sec_pwdb = cur_cck_pwdb; + cck_rx_ver2_sec_index = i; + } + else if(cur_cck_pwdb == tmp_cck_sec_pwdb) + { + if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb) + { // let sec and min point to the different index + tmp_cck_sec_pwdb = cur_cck_pwdb; + cck_rx_ver2_sec_index = i; + } + else + { + // This case we don't need to set any index + } + } + else if((cur_cck_pwdb < tmp_cck_sec_pwdb) && (cur_cck_pwdb > tmp_cck_min_pwdb)) + { + // This case we don't need to set any index + } + else if(cur_cck_pwdb == tmp_cck_min_pwdb) + { + if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb) + { // let sec and min point to the different index + tmp_cck_min_pwdb = cur_cck_pwdb; + cck_rx_ver2_min_index = i; + } + else + { + // This case we don't need to set any index + } + } + else if(cur_cck_pwdb < tmp_cck_min_pwdb) + { + tmp_cck_min_pwdb = cur_cck_pwdb; + cck_rx_ver2_min_index = i; + } + } + + } + } + } + + + // Set CCK Rx path + // reg0xA07[3:2]=cck default rx path, reg0xa07[1:0]=cck optional rx path. + update_cck_rx_path = 0; + if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) + { + cck_default_Rx = cck_rx_ver2_max_index; + cck_optional_Rx = cck_rx_ver2_sec_index; + if(tmp_cck_max_pwdb != -64) + update_cck_rx_path = 1; + } + + if(tmp_min_rssi < DM_RxPathSelTable.SS_TH_low && disabled_rf_cnt < 2) + { + if((tmp_max_rssi - tmp_min_rssi) >= DM_RxPathSelTable.diff_TH) + { + //record the enabled rssi threshold + DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] = tmp_max_rssi+5; + //disable the BB Rx path, OFDM + rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<>i) & 0x1) //disabled rf + { + if(tmp_max_rssi >= DM_RxPathSelTable.rf_enable_rssi_th[i]) + { + //enable the BB Rx path + //DbgPrint("RF-%d is enabled. \n", 0x1<priv_wq,&priv->rfpath_check_wq,0); +} /* dm_CheckRxRFPath */ + + +static void dm_init_fsync (struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + priv->ieee80211->fsync_time_interval = 500; + priv->ieee80211->fsync_rate_bitmap = 0x0f000800; + priv->ieee80211->fsync_rssi_threshold = 30; +#ifdef RTL8190P + priv->ieee80211->bfsync_enable = true; +#else + priv->ieee80211->bfsync_enable = false; +#endif + priv->ieee80211->fsync_multiple_timeinterval = 3; + priv->ieee80211->fsync_firstdiff_ratethreshold= 100; + priv->ieee80211->fsync_seconddiff_ratethreshold= 200; + priv->ieee80211->fsync_state = Default_Fsync; + priv->framesyncMonitor = 1; // current default 0xc38 monitor on + + init_timer(&priv->fsync_timer); + priv->fsync_timer.data = (unsigned long)dev; + priv->fsync_timer.function = dm_fsync_timer_callback; +} + + +static void dm_deInit_fsync(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + del_timer_sync(&priv->fsync_timer); +} + +extern void dm_fsync_timer_callback(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + struct r8192_priv *priv = ieee80211_priv((struct net_device *)data); + u32 rate_index, rate_count = 0, rate_count_diff=0; + bool bSwitchFromCountDiff = false; + bool bDoubleTimeInterval = false; + + if( priv->ieee80211->state == IEEE80211_LINKED && + priv->ieee80211->bfsync_enable && + (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) + { + // Count rate 54, MCS [7], [12, 13, 14, 15] + u32 rate_bitmap; + for(rate_index = 0; rate_index <= 27; rate_index++) + { + rate_bitmap = 1 << rate_index; + if(priv->ieee80211->fsync_rate_bitmap & rate_bitmap) + rate_count+= priv->stats.received_rate_histogram[1][rate_index]; + } + + if(rate_count < priv->rate_record) + rate_count_diff = 0xffffffff - rate_count + priv->rate_record; + else + rate_count_diff = rate_count - priv->rate_record; + if(rate_count_diff < priv->rateCountDiffRecord) + { + + u32 DiffNum = priv->rateCountDiffRecord - rate_count_diff; + // Contiune count + if(DiffNum >= priv->ieee80211->fsync_seconddiff_ratethreshold) + priv->ContiuneDiffCount++; + else + priv->ContiuneDiffCount = 0; + + // Contiune count over + if(priv->ContiuneDiffCount >=2) + { + bSwitchFromCountDiff = true; + priv->ContiuneDiffCount = 0; + } + } + else + { + // Stop contiune count + priv->ContiuneDiffCount = 0; + } + + //If Count diff <= FsyncRateCountThreshold + if(rate_count_diff <= priv->ieee80211->fsync_firstdiff_ratethreshold) + { + bSwitchFromCountDiff = true; + priv->ContiuneDiffCount = 0; + } + priv->rate_record = rate_count; + priv->rateCountDiffRecord = rate_count_diff; + RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync); + // if we never receive those mcs rate and rssi > 30 % then switch fsyn + if(priv->undecorated_smoothed_pwdb > priv->ieee80211->fsync_rssi_threshold && bSwitchFromCountDiff) + { + bDoubleTimeInterval = true; + priv->bswitch_fsync = !priv->bswitch_fsync; + if(priv->bswitch_fsync) + { + #ifdef RTL8190P + write_nic_byte(dev, 0xC36, 0x00); + #else + write_nic_byte(dev,0xC36, 0x1c); + #endif + write_nic_byte(dev, 0xC3e, 0x90); + } + else + { + #ifdef RTL8190P + write_nic_byte(dev, 0xC36, 0x40); + #else + write_nic_byte(dev, 0xC36, 0x5c); + #endif + write_nic_byte(dev, 0xC3e, 0x96); + } + } + else if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->fsync_rssi_threshold) + { + if(priv->bswitch_fsync) + { + priv->bswitch_fsync = false; + #ifdef RTL8190P + write_nic_byte(dev, 0xC36, 0x40); + #else + write_nic_byte(dev, 0xC36, 0x5c); + #endif + write_nic_byte(dev, 0xC3e, 0x96); + } + } + if(bDoubleTimeInterval){ + if(timer_pending(&priv->fsync_timer)) + del_timer_sync(&priv->fsync_timer); + priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval*priv->ieee80211->fsync_multiple_timeinterval); + add_timer(&priv->fsync_timer); + } + else{ + if(timer_pending(&priv->fsync_timer)) + del_timer_sync(&priv->fsync_timer); + priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval); + add_timer(&priv->fsync_timer); + } + } + else + { + // Let Register return to default value; + if(priv->bswitch_fsync) + { + priv->bswitch_fsync = false; + #ifdef RTL8190P + write_nic_byte(dev, 0xC36, 0x40); + #else + write_nic_byte(dev, 0xC36, 0x5c); + #endif + write_nic_byte(dev, 0xC3e, 0x96); + } + priv->ContiuneDiffCount = 0; + #ifdef RTL8190P + write_nic_dword(dev, rOFDM0_RxDetector2, 0x164052cd); + #else + write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd); + #endif + } + RT_TRACE(COMP_HALDM, "ContiuneDiffCount %d\n", priv->ContiuneDiffCount); + RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync); +} + +static void dm_StartHWFsync(struct net_device *dev) +{ + RT_TRACE(COMP_HALDM, "%s\n", __FUNCTION__); + write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cf); + write_nic_byte(dev, 0xc3b, 0x41); +} + +static void dm_EndSWFsync(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + RT_TRACE(COMP_HALDM, "%s\n", __FUNCTION__); + del_timer_sync(&(priv->fsync_timer)); + + // Let Register return to default value; + if(priv->bswitch_fsync) + { + priv->bswitch_fsync = false; + + #ifdef RTL8190P + write_nic_byte(dev, 0xC36, 0x40); + #else + write_nic_byte(dev, 0xC36, 0x5c); + #endif + + write_nic_byte(dev, 0xC3e, 0x96); + } + + priv->ContiuneDiffCount = 0; +#ifndef RTL8190P + write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd); +#endif + +} + +static void dm_StartSWFsync(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u32 rateIndex; + u32 rateBitmap; + + RT_TRACE(COMP_HALDM,"%s\n", __FUNCTION__); + // Initial rate record to zero, start to record. + priv->rate_record = 0; + // Initial contiune diff count to zero, start to record. + priv->ContiuneDiffCount = 0; + priv->rateCountDiffRecord = 0; + priv->bswitch_fsync = false; + + if(priv->ieee80211->mode == WIRELESS_MODE_N_24G) + { + priv->ieee80211->fsync_firstdiff_ratethreshold= 600; + priv->ieee80211->fsync_seconddiff_ratethreshold = 0xffff; + } + else + { + priv->ieee80211->fsync_firstdiff_ratethreshold= 200; + priv->ieee80211->fsync_seconddiff_ratethreshold = 200; + } + for(rateIndex = 0; rateIndex <= 27; rateIndex++) + { + rateBitmap = 1 << rateIndex; + if(priv->ieee80211->fsync_rate_bitmap & rateBitmap) + priv->rate_record += priv->stats.received_rate_histogram[1][rateIndex]; + } + if(timer_pending(&priv->fsync_timer)) + del_timer_sync(&priv->fsync_timer); + priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval); + add_timer(&priv->fsync_timer); + +#ifndef RTL8190P + write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd); +#endif + +} + +static void dm_EndHWFsync(struct net_device *dev) +{ + RT_TRACE(COMP_HALDM,"%s\n", __FUNCTION__); + write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd); + write_nic_byte(dev, 0xc3b, 0x49); + +} + +void dm_check_fsync(struct net_device *dev) +{ +#define RegC38_Default 0 +#define RegC38_NonFsync_Other_AP 1 +#define RegC38_Fsync_AP_BCM 2 + struct r8192_priv *priv = ieee80211_priv(dev); + //u32 framesyncC34; + static u8 reg_c38_State=RegC38_Default; + static u32 reset_cnt=0; + + RT_TRACE(COMP_HALDM, "RSSI %d TimeInterval %d MultipleTimeInterval %d\n", priv->ieee80211->fsync_rssi_threshold, priv->ieee80211->fsync_time_interval, priv->ieee80211->fsync_multiple_timeinterval); + RT_TRACE(COMP_HALDM, "RateBitmap 0x%x FirstDiffRateThreshold %d SecondDiffRateThreshold %d\n", priv->ieee80211->fsync_rate_bitmap, priv->ieee80211->fsync_firstdiff_ratethreshold, priv->ieee80211->fsync_seconddiff_ratethreshold); + + if( priv->ieee80211->state == IEEE80211_LINKED && + (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) + { + if(priv->ieee80211->bfsync_enable == 0) + { + switch(priv->ieee80211->fsync_state) + { + case Default_Fsync: + dm_StartHWFsync(dev); + priv->ieee80211->fsync_state = HW_Fsync; + break; + case SW_Fsync: + dm_EndSWFsync(dev); + dm_StartHWFsync(dev); + priv->ieee80211->fsync_state = HW_Fsync; + break; + case HW_Fsync: + default: + break; + } + } + else + { + switch(priv->ieee80211->fsync_state) + { + case Default_Fsync: + dm_StartSWFsync(dev); + priv->ieee80211->fsync_state = SW_Fsync; + break; + case HW_Fsync: + dm_EndHWFsync(dev); + dm_StartSWFsync(dev); + priv->ieee80211->fsync_state = SW_Fsync; + break; + case SW_Fsync: + default: + break; + + } + } + if(priv->framesyncMonitor) + { + if(reg_c38_State != RegC38_Fsync_AP_BCM) + { //For broadcom AP we write different default value + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector3, 0x15); + #else + write_nic_byte(dev, rOFDM0_RxDetector3, 0x95); + #endif + + reg_c38_State = RegC38_Fsync_AP_BCM; + } + } + } + else + { + switch(priv->ieee80211->fsync_state) + { + case HW_Fsync: + dm_EndHWFsync(dev); + priv->ieee80211->fsync_state = Default_Fsync; + break; + case SW_Fsync: + dm_EndSWFsync(dev); + priv->ieee80211->fsync_state = Default_Fsync; + break; + case Default_Fsync: + default: + break; + } + + if(priv->framesyncMonitor) + { + if(priv->ieee80211->state == IEEE80211_LINKED) + { + if(priv->undecorated_smoothed_pwdb <= RegC38_TH) + { + if(reg_c38_State != RegC38_NonFsync_Other_AP) + { + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector3, 0x10); + #else + write_nic_byte(dev, rOFDM0_RxDetector3, 0x90); + #endif + + reg_c38_State = RegC38_NonFsync_Other_AP; + } + } + else if(priv->undecorated_smoothed_pwdb >= (RegC38_TH+5)) + { + if(reg_c38_State) + { + write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); + reg_c38_State = RegC38_Default; + //DbgPrint("Fsync is idle, rssi>=40, write 0xc38 = 0x%x \n", pHalData->framesync); + } + } + } + else + { + if(reg_c38_State) + { + write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); + reg_c38_State = RegC38_Default; + //DbgPrint("Fsync is idle, not connected, write 0xc38 = 0x%x \n", pHalData->framesync); + } + } + } + } + if(priv->framesyncMonitor) + { + if(priv->reset_count != reset_cnt) + { //After silent reset, the reg_c38_State will be returned to default value + write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); + reg_c38_State = RegC38_Default; + reset_cnt = priv->reset_count; + //DbgPrint("reg_c38_State = 0 for silent reset. \n"); + } + } + else + { + if(reg_c38_State) + { + write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); + reg_c38_State = RegC38_Default; + //DbgPrint("framesync no monitor, write 0xc38 = 0x%x \n", pHalData->framesync); + } + } +} + + +/*----------------------------------------------------------------------------- + * Function: dm_shadow_init() + * + * Overview: Store all NIC MAC/BB register content. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/29/2008 amy Create Version 0 porting from windows code. + * + *---------------------------------------------------------------------------*/ +extern void dm_shadow_init(struct net_device *dev) +{ + u8 page; + u16 offset; + + for (page = 0; page < 5; page++) + for (offset = 0; offset < 256; offset++) + { + dm_shadow[page][offset] = read_nic_byte(dev, offset+page*256); + //DbgPrint("P-%d/O-%02x=%02x\r\n", page, offset, DM_Shadow[page][offset]); + } + + for (page = 8; page < 11; page++) + for (offset = 0; offset < 256; offset++) + dm_shadow[page][offset] = read_nic_byte(dev, offset+page*256); + + for (page = 12; page < 15; page++) + for (offset = 0; offset < 256; offset++) + dm_shadow[page][offset] = read_nic_byte(dev, offset+page*256); + +} /* dm_shadow_init */ + +/*---------------------------Define function prototype------------------------*/ +/*----------------------------------------------------------------------------- + * Function: DM_DynamicTxPower() + * + * Overview: Detect Signal strength to control TX Registry + Tx Power Control For Near/Far Range + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 03/06/2008 Jacken Create Version 0. + * + *---------------------------------------------------------------------------*/ +static void dm_init_dynamic_txpower(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + //Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code. + priv->ieee80211->bdynamic_txpower_enable = true; //Default to enable Tx Power Control + priv->bLastDTPFlag_High = false; + priv->bLastDTPFlag_Low = false; + priv->bDynamicTxHighPower = false; + priv->bDynamicTxLowPower = false; +} + +static void dm_dynamic_txpower(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + unsigned int txhipower_threshhold=0; + unsigned int txlowpower_threshold=0; + if(priv->ieee80211->bdynamic_txpower_enable != true) + { + priv->bDynamicTxHighPower = false; + priv->bDynamicTxLowPower = false; + return; + } + //printk("priv->ieee80211->current_network.unknown_cap_exist is %d ,priv->ieee80211->current_network.broadcom_cap_exist is %d\n",priv->ieee80211->current_network.unknown_cap_exist,priv->ieee80211->current_network.broadcom_cap_exist); + if((priv->ieee80211->current_network.atheros_cap_exist ) && (priv->ieee80211->mode == IEEE_G)){ + txhipower_threshhold = TX_POWER_ATHEROAP_THRESH_HIGH; + txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW; + } + else + { + txhipower_threshhold = TX_POWER_NEAR_FIELD_THRESH_HIGH; + txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW; + } + +// printk("=======>%s(): txhipower_threshhold is %d,txlowpower_threshold is %d\n",__FUNCTION__,txhipower_threshhold,txlowpower_threshold); + RT_TRACE(COMP_TXAGC,"priv->undecorated_smoothed_pwdb = %ld \n" , priv->undecorated_smoothed_pwdb); + + if(priv->ieee80211->state == IEEE80211_LINKED) + { + if(priv->undecorated_smoothed_pwdb >= txhipower_threshhold) + { + priv->bDynamicTxHighPower = true; + priv->bDynamicTxLowPower = false; + } + else + { + // high power state check + if(priv->undecorated_smoothed_pwdb < txlowpower_threshold && priv->bDynamicTxHighPower == true) + { + priv->bDynamicTxHighPower = false; + } + // low power state check + if(priv->undecorated_smoothed_pwdb < 35) + { + priv->bDynamicTxLowPower = true; + } + else if(priv->undecorated_smoothed_pwdb >= 40) + { + priv->bDynamicTxLowPower = false; + } + } + } + else + { + //pHalData->bTXPowerCtrlforNearFarRange = !pHalData->bTXPowerCtrlforNearFarRange; + priv->bDynamicTxHighPower = false; + priv->bDynamicTxLowPower = false; + } + + if( (priv->bDynamicTxHighPower != priv->bLastDTPFlag_High ) || + (priv->bDynamicTxLowPower != priv->bLastDTPFlag_Low ) ) + { + RT_TRACE(COMP_TXAGC,"SetTxPowerLevel8190() channel = %d \n" , priv->ieee80211->current_network.channel); + +#if defined(RTL8190P) || defined(RTL8192E) + SetTxPowerLevel8190(Adapter,pHalData->CurrentChannel); +#endif + +#ifdef RTL8192U + rtl8192_phy_setTxPower(dev,priv->ieee80211->current_network.channel); + //pHalData->bStartTxCtrlByTPCNFR = FALSE; //Clear th flag of Set TX Power from Sitesurvey +#endif + } + priv->bLastDTPFlag_High = priv->bDynamicTxHighPower; + priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower; + +} /* dm_dynamic_txpower */ + +//added by vivi, for read tx rate and retrycount +static void dm_check_txrateandretrycount(struct net_device * dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + struct ieee80211_device* ieee = priv->ieee80211; + //for 11n tx rate +// priv->stats.CurrentShowTxate = read_nic_byte(dev, Current_Tx_Rate_Reg); + ieee->softmac_stats.CurrentShowTxate = read_nic_byte(dev, Current_Tx_Rate_Reg); + //printk("=============>tx_rate_reg:%x\n", ieee->softmac_stats.CurrentShowTxate); + //for initial tx rate +// priv->stats.last_packet_rate = read_nic_byte(dev, Initial_Tx_Rate_Reg); + ieee->softmac_stats.last_packet_rate = read_nic_byte(dev ,Initial_Tx_Rate_Reg); + //for tx tx retry count +// priv->stats.txretrycount = read_nic_dword(dev, Tx_Retry_Count_Reg); + ieee->softmac_stats.txretrycount = read_nic_dword(dev, Tx_Retry_Count_Reg); +} + +static void dm_send_rssi_tofw(struct net_device *dev) +{ + DCMD_TXCMD_T tx_cmd; + struct r8192_priv *priv = ieee80211_priv(dev); + + // If we test chariot, we should stop the TX command ? + // Because 92E will always silent reset when we send tx command. We use register + // 0x1e0(byte) to botify driver. + write_nic_byte(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb); + return; + tx_cmd.Op = TXCMD_SET_RX_RSSI; + tx_cmd.Length = 4; + tx_cmd.Value = priv->undecorated_smoothed_pwdb; + + cmpk_message_handle_tx(dev, (u8*)&tx_cmd, + DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T)); +} + +/*---------------------------Define function prototype------------------------*/ + diff --git a/drivers/staging/rtl8192u/r8192U_dm.h b/drivers/staging/rtl8192u/r8192U_dm.h new file mode 100644 index 0000000000000000000000000000000000000000..3ceb59b9eca78a5c4ddc611afb830ffa26a1fc05 --- /dev/null +++ b/drivers/staging/rtl8192u/r8192U_dm.h @@ -0,0 +1,254 @@ +/***************************************************************************** + * Copyright(c) 2007, RealTEK Technology Inc. All Right Reserved. + * + * Module: Hal819xUsbDM.h (RTL8192 Header H File) + * + * + * Note: For dynamic control definition constant structure. + * + * + * Export: + * + * Abbrev: + * + * History: + * Data Who Remark + * 10/04/2007 MHC Create initial version. + * + *****************************************************************************/ + /* Check to see if the file has been included already. */ +#ifndef __R8192UDM_H__ +#define __R8192UDM_H__ + + +/*--------------------------Define Parameters-------------------------------*/ +#define DM_DIG_THRESH_HIGH 40 +#define DM_DIG_THRESH_LOW 35 + +#define DM_DIG_HIGH_PWR_THRESH_HIGH 75 +#define DM_DIG_HIGH_PWR_THRESH_LOW 70 + +#define BW_AUTO_SWITCH_HIGH_LOW 25 +#define BW_AUTO_SWITCH_LOW_HIGH 30 + +#define DM_check_fsync_time_interval 500 + + +#define DM_DIG_BACKOFF 12 +#define DM_DIG_MAX 0x36 +#define DM_DIG_MIN 0x1c +#define DM_DIG_MIN_Netcore 0x12 + +#define RxPathSelection_SS_TH_low 30 +#define RxPathSelection_diff_TH 18 + +#define RateAdaptiveTH_High 50 +#define RateAdaptiveTH_Low_20M 30 +#define RateAdaptiveTH_Low_40M 10 +#define VeryLowRSSI 15 +#define CTSToSelfTHVal 30 + +//defined by vivi, for tx power track +#define E_FOR_TX_POWER_TRACK 300 +//Dynamic Tx Power Control Threshold +#define TX_POWER_NEAR_FIELD_THRESH_HIGH 68 +#define TX_POWER_NEAR_FIELD_THRESH_LOW 62 +//added by amy for atheros AP +#define TX_POWER_ATHEROAP_THRESH_HIGH 78 +#define TX_POWER_ATHEROAP_THRESH_LOW 72 + +//defined by vivi, for showing on UI +#define Current_Tx_Rate_Reg 0x1b8 +#define Initial_Tx_Rate_Reg 0x1b9 +#define Tx_Retry_Count_Reg 0x1ac +#define RegC38_TH 20 +/*--------------------------Define Parameters-------------------------------*/ + + +/*------------------------------Define structure----------------------------*/ +/* 2007/10/04 MH Define upper and lower threshold of DIG enable or disable. */ +typedef struct _dynamic_initial_gain_threshold_ +{ + u8 dig_enable_flag; + u8 dig_algorithm; + u8 dbg_mode; + u8 dig_algorithm_switch; + + long rssi_low_thresh; + long rssi_high_thresh; + + long rssi_high_power_lowthresh; + long rssi_high_power_highthresh; + + u8 dig_state; + u8 dig_highpwr_state; + u8 cur_connect_state; + u8 pre_connect_state; + + u8 curpd_thstate; + u8 prepd_thstate; + u8 curcs_ratio_state; + u8 precs_ratio_state; + + u32 pre_ig_value; + u32 cur_ig_value; + + u8 backoff_val; + u8 rx_gain_range_max; + u8 rx_gain_range_min; + bool initialgain_lowerbound_state; + + long rssi_val; +}dig_t; + +typedef enum tag_dynamic_init_gain_state_definition +{ + DM_STA_DIG_OFF = 0, + DM_STA_DIG_ON, + DM_STA_DIG_MAX +}dm_dig_sta_e; + + +/* 2007/10/08 MH Define RATR state. */ +typedef enum tag_dynamic_ratr_state_definition +{ + DM_RATR_STA_HIGH = 0, + DM_RATR_STA_MIDDLE = 1, + DM_RATR_STA_LOW = 2, + DM_RATR_STA_MAX +}dm_ratr_sta_e; + +/* 2007/10/11 MH Define DIG operation type. */ +typedef enum tag_dynamic_init_gain_operation_type_definition +{ + DIG_TYPE_THRESH_HIGH = 0, + DIG_TYPE_THRESH_LOW = 1, + DIG_TYPE_THRESH_HIGHPWR_HIGH = 2, + DIG_TYPE_THRESH_HIGHPWR_LOW = 3, + DIG_TYPE_DBG_MODE = 4, + DIG_TYPE_RSSI = 5, + DIG_TYPE_ALGORITHM = 6, + DIG_TYPE_BACKOFF = 7, + DIG_TYPE_PWDB_FACTOR = 8, + DIG_TYPE_RX_GAIN_MIN = 9, + DIG_TYPE_RX_GAIN_MAX = 10, + DIG_TYPE_ENABLE = 20, + DIG_TYPE_DISABLE = 30, + DIG_OP_TYPE_MAX +}dm_dig_op_e; + +typedef enum tag_dig_algorithm_definition +{ + DIG_ALGO_BY_FALSE_ALARM = 0, + DIG_ALGO_BY_RSSI = 1, + DIG_ALGO_MAX +}dm_dig_alg_e; + +typedef enum tag_dig_dbgmode_definition +{ + DIG_DBG_OFF = 0, + DIG_DBG_ON = 1, + DIG_DBG_MAX +}dm_dig_dbg_e; + +typedef enum tag_dig_connect_definition +{ + DIG_DISCONNECT = 0, + DIG_CONNECT = 1, + DIG_CONNECT_MAX +}dm_dig_connect_e; + +typedef enum tag_dig_packetdetection_threshold_definition +{ + DIG_PD_AT_LOW_POWER = 0, + DIG_PD_AT_NORMAL_POWER = 1, + DIG_PD_AT_HIGH_POWER = 2, + DIG_PD_MAX +}dm_dig_pd_th_e; + +typedef enum tag_dig_cck_cs_ratio_state_definition +{ + DIG_CS_RATIO_LOWER = 0, + DIG_CS_RATIO_HIGHER = 1, + DIG_CS_MAX +}dm_dig_cs_ratio_e; +typedef struct _Dynamic_Rx_Path_Selection_ +{ + u8 Enable; + u8 DbgMode; + u8 cck_method; + u8 cck_Rx_path; + + u8 SS_TH_low; + u8 diff_TH; + u8 disabledRF; + u8 reserved; + + u8 rf_rssi[4]; + u8 rf_enable_rssi_th[4]; + long cck_pwdb_sta[4]; +}DRxPathSel; + +typedef enum tag_CCK_Rx_Path_Method_Definition +{ + CCK_Rx_Version_1 = 0, + CCK_Rx_Version_2= 1, + CCK_Rx_Version_MAX +}DM_CCK_Rx_Path_Method; + +typedef enum tag_DM_DbgMode_Definition +{ + DM_DBG_OFF = 0, + DM_DBG_ON = 1, + DM_DBG_MAX +}DM_DBG_E; + +typedef struct tag_Tx_Config_Cmd_Format +{ + u32 Op; /* Command packet type. */ + u32 Length; /* Command packet length. */ + u32 Value; +}DCMD_TXCMD_T, *PDCMD_TXCMD_T; +/*------------------------------Define structure----------------------------*/ + + +/*------------------------Export global variable----------------------------*/ +extern dig_t dm_digtable; +extern u8 dm_shadow[16][256]; +extern DRxPathSel DM_RxPathSelTable; +/*------------------------Export global variable----------------------------*/ + + +/*------------------------Export Marco Definition---------------------------*/ + +/*------------------------Export Marco Definition---------------------------*/ + + +/*--------------------------Exported Function prototype---------------------*/ +extern void init_hal_dm(struct net_device *dev); +extern void deinit_hal_dm(struct net_device *dev); + +extern void hal_dm_watchdog(struct net_device *dev); + +extern void init_rate_adaptive(struct net_device *dev); +extern void dm_txpower_trackingcallback(struct work_struct *work); +extern void dm_restore_dynamic_mechanism_state(struct net_device *dev); +extern void dm_backup_dynamic_mechanism_state(struct net_device *dev); +extern void dm_change_dynamic_initgain_thresh(struct net_device *dev, + u32 dm_type, u32 dm_value); +extern void dm_force_tx_fw_info(struct net_device *dev,u32 force_type, u32 force_value); +extern void dm_init_edca_turbo(struct net_device *dev); +extern void dm_rf_operation_test_callback(unsigned long data); +extern void dm_rf_pathcheck_workitemcallback(struct work_struct *work); +extern void dm_fsync_timer_callback(unsigned long data); +extern void dm_cck_txpower_adjust(struct net_device *dev,bool binch14); +extern void dm_shadow_init(struct net_device *dev); +extern void dm_initialize_txpower_tracking(struct net_device *dev); +/*--------------------------Exported Function prototype---------------------*/ + + +#endif /*__R8192UDM_H__ */ + + +/* End of r8192U_dm.h */ + diff --git a/drivers/staging/rtl8192u/r8192U_hw.h b/drivers/staging/rtl8192u/r8192U_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..e89aaf70143bbf0b6fa1b0cfd9a3659b0ed8074e --- /dev/null +++ b/drivers/staging/rtl8192u/r8192U_hw.h @@ -0,0 +1,411 @@ +/* + This is part of rtl8187 OpenSource driver. + Copyright (C) Andrea Merello 2004-2005 + Released under the terms of GPL (General Public Licence) + + Parts of this driver are based on the GPL part of the + official Realtek driver. + Parts of this driver are based on the rtl8180 driver skeleton + from Patric Schenke & Andres Salomon. + Parts of this driver are based on the Intel Pro Wireless + 2100 GPL driver. + + We want to tanks the Authors of those projects + and the Ndiswrapper project Authors. +*/ + +/* Mariusz Matuszek added full registers definition with Realtek's name */ + +/* this file contains register definitions for the rtl8187 MAC controller */ +#ifndef R8192_HW +#define R8192_HW + +typedef enum _VERSION_819xU{ + VERSION_819xU_A, // A-cut + VERSION_819xU_B, // B-cut + VERSION_819xU_C,// C-cut +}VERSION_819xU,*PVERSION_819xU; +//added for different RF type +typedef enum _RT_RF_TYPE_DEF +{ + RF_1T2R = 0, + RF_2T4R, + + RF_819X_MAX_TYPE +}RT_RF_TYPE_DEF; + + +typedef enum _BaseBand_Config_Type{ + BaseBand_Config_PHY_REG = 0, //Radio Path A + BaseBand_Config_AGC_TAB = 1, //Radio Path B +}BaseBand_Config_Type, *PBaseBand_Config_Type; +#define RTL8187_REQT_READ 0xc0 +#define RTL8187_REQT_WRITE 0x40 +#define RTL8187_REQ_GET_REGS 0x05 +#define RTL8187_REQ_SET_REGS 0x05 + +#define MAX_TX_URB 5 +#define MAX_RX_URB 16 + +#define R8180_MAX_RETRY 255 +//#define MAX_RX_NORMAL_URB 3 +//#define MAX_RX_COMMAND_URB 2 +#define RX_URB_SIZE 9100 + +#define BB_ANTATTEN_CHAN14 0x0c +#define BB_ANTENNA_B 0x40 + +#define BB_HOST_BANG (1<<30) +#define BB_HOST_BANG_EN (1<<2) +#define BB_HOST_BANG_CLK (1<<1) +#define BB_HOST_BANG_RW (1<<3) +#define BB_HOST_BANG_DATA 1 + +//#if (RTL819X_FPGA_VER & RTL819X_FPGA_VIVI_070920) +#define AFR 0x010 +#define AFR_CardBEn (1<<0) +#define AFR_CLKRUN_SEL (1<<1) +#define AFR_FuncRegEn (1<<2) +#define RTL8190_EEPROM_ID 0x8129 +#define EEPROM_VID 0x02 +#define EEPROM_PID 0x04 +#define EEPROM_NODE_ADDRESS_BYTE_0 0x0C + +#define EEPROM_TxPowerDiff 0x1F +#define EEPROM_ThermalMeter 0x20 +#define EEPROM_PwDiff 0x21 //0x21 +#define EEPROM_CrystalCap 0x22 //0x22 + +#define EEPROM_TxPwIndex_CCK 0x23 //0x23 +#define EEPROM_TxPwIndex_OFDM_24G 0x24 //0x24~0x26 +#define EEPROM_TxPwIndex_CCK_V1 0x29 //0x29~0x2B +#define EEPROM_TxPwIndex_OFDM_24G_V1 0x2C //0x2C~0x2E +#define EEPROM_TxPwIndex_Ver 0x27 //0x27 + +#define EEPROM_Default_TxPowerDiff 0x0 +#define EEPROM_Default_ThermalMeter 0x7 +#define EEPROM_Default_PwDiff 0x4 +#define EEPROM_Default_CrystalCap 0x5 +#define EEPROM_Default_TxPower 0x1010 +#define EEPROM_Customer_ID 0x7B //0x7B:CustomerID +#define EEPROM_ChannelPlan 0x16 //0x7C +#define EEPROM_IC_VER 0x7d //0x7D +#define EEPROM_CRC 0x7e //0x7E~0x7F + +#define EEPROM_CID_DEFAULT 0x0 +#define EEPROM_CID_CAMEO 0x1 +#define EEPROM_CID_RUNTOP 0x2 +#define EEPROM_CID_Senao 0x3 +#define EEPROM_CID_TOSHIBA 0x4 // Toshiba setting, Merge by Jacken, 2008/01/31 +#define EEPROM_CID_NetCore 0x5 +#define EEPROM_CID_Nettronix 0x6 +#define EEPROM_CID_Pronet 0x7 +#define EEPROM_CID_DLINK 0x8 + +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 +#define AC_PARAM_ECW_MAX_OFFSET 12 +#define AC_PARAM_ECW_MIN_OFFSET 8 +#define AC_PARAM_AIFS_OFFSET 0 + +//#endif +enum _RTL8192Usb_HW { + + PCIF = 0x009, // PCI Function Register 0x0009h~0x000bh +#define BB_GLOBAL_RESET_BIT 0x1 + BB_GLOBAL_RESET = 0x020, // BasebandGlobal Reset Register + BSSIDR = 0x02E, // BSSID Register + CMDR = 0x037, // Command register +#define CR_RST 0x10 +#define CR_RE 0x08 +#define CR_TE 0x04 +#define CR_MulRW 0x01 + SIFS = 0x03E, // SIFS register + TCR = 0x040, // Transmit Configuration Register + +#define TCR_MXDMA_2048 7 +#define TCR_LRL_OFFSET 0 +#define TCR_SRL_OFFSET 8 +#define TCR_MXDMA_OFFSET 21 +#define TCR_SAT BIT24 // Enable Rate depedent ack timeout timer + RCR = 0x044, // Receive Configuration Register +#define MAC_FILTER_MASK ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<5) | \ + (1<<12) | (1<<18) | (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23)) +#define RX_FIFO_THRESHOLD_MASK ((1<<13) | (1<<14) | (1<<15)) +#define RX_FIFO_THRESHOLD_SHIFT 13 +#define RX_FIFO_THRESHOLD_128 3 +#define RX_FIFO_THRESHOLD_256 4 +#define RX_FIFO_THRESHOLD_512 5 +#define RX_FIFO_THRESHOLD_1024 6 +#define RX_FIFO_THRESHOLD_NONE 7 +#define MAX_RX_DMA_MASK ((1<<8) | (1<<9) | (1<<10)) +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 +#define RCR_ONLYERLPKT BIT31 // Early Receiving based on Packet Size. +#define RCR_ENCS2 BIT30 // Enable Carrier Sense Detection Method 2 +#define RCR_ENCS1 BIT29 // Enable Carrier Sense Detection Method 1 +#define RCR_ENMBID BIT27 // Enable Multiple BssId. +#define RCR_ACKTXBW (BIT24|BIT25) // TXBW Setting of ACK frames +#define RCR_CBSSID BIT23 // Accept BSSID match packet +#define RCR_APWRMGT BIT22 // Accept power management packet +#define RCR_ADD3 BIT21 // Accept address 3 match packet +#define RCR_AMF BIT20 // Accept management type frame +#define RCR_ACF BIT19 // Accept control type frame +#define RCR_ADF BIT18 // Accept data type frame +#define RCR_RXFTH BIT13 // Rx FIFO Threshold +#define RCR_AICV BIT12 // Accept ICV error packet +#define RCR_ACRC32 BIT5 // Accept CRC32 error packet +#define RCR_AB BIT3 // Accept broadcast packet +#define RCR_AM BIT2 // Accept multicast packet +#define RCR_APM BIT1 // Accept physical match packet +#define RCR_AAP BIT0 // Accept all unicast packet + SLOT_TIME = 0x049, // Slot Time Register + ACK_TIMEOUT = 0x04c, // Ack Timeout Register + PIFS_TIME = 0x04d, // PIFS time + USTIME = 0x04e, // Microsecond Tuning Register, Sets the microsecond time unit used by MAC clock. + EDCAPARA_BE = 0x050, // EDCA Parameter of AC BE + EDCAPARA_BK = 0x054, // EDCA Parameter of AC BK + EDCAPARA_VO = 0x058, // EDCA Parameter of AC VO + EDCAPARA_VI = 0x05C, // EDCA Parameter of AC VI + RFPC = 0x05F, // Rx FIFO Packet Count + CWRR = 0x060, // Contention Window Report Register + BCN_TCFG = 0x062, // Beacon Time Configuration +#define BCN_TCFG_CW_SHIFT 8 +#define BCN_TCFG_IFS 0 + BCN_INTERVAL = 0x070, // Beacon Interval (TU) + ATIMWND = 0x072, // ATIM Window Size (TU) + BCN_DRV_EARLY_INT = 0x074, // Driver Early Interrupt Time (TU). Time to send interrupt to notify to change beacon content before TBTT + BCN_DMATIME = 0x076, // Beacon DMA and ATIM interrupt time (US). Indicates the time before TBTT to perform beacon queue DMA + BCN_ERR_THRESH = 0x078, // Beacon Error Threshold + RWCAM = 0x0A0, //IN 8190 Data Sheet is called CAMcmd + WCAMI = 0x0A4, // Software write CAM input content + RCAMO = 0x0A8, // Software read/write CAM config + SECR = 0x0B0, //Security Configuration Register +#define SCR_TxUseDK BIT0 //Force Tx Use Default Key +#define SCR_RxUseDK BIT1 //Force Rx Use Default Key +#define SCR_TxEncEnable BIT2 //Enable Tx Encryption +#define SCR_RxDecEnable BIT3 //Enable Rx Decryption +#define SCR_SKByA2 BIT4 //Search kEY BY A2 +#define SCR_NoSKMC BIT5 //No Key Search for Multicast +#define SCR_UseDK 0x01 +#define SCR_TxSecEnable 0x02 +#define SCR_RxSecEnable 0x04 + TPPoll = 0x0fd, // Transmit priority polling register + PSR = 0x0ff, // Page Select Register +#define CPU_CCK_LOOPBACK 0x00030000 +#define CPU_GEN_SYSTEM_RESET 0x00000001 +#define CPU_GEN_FIRMWARE_RESET 0x00000008 +#define CPU_GEN_BOOT_RDY 0x00000010 +#define CPU_GEN_FIRM_RDY 0x00000020 +#define CPU_GEN_PUT_CODE_OK 0x00000080 +#define CPU_GEN_BB_RST 0x00000100 +#define CPU_GEN_PWR_STB_CPU 0x00000004 +#define CPU_GEN_NO_LOOPBACK_MSK 0xFFF8FFFF // Set bit18,17,16 to 0. Set bit19 +#define CPU_GEN_NO_LOOPBACK_SET 0x00080000 // Set BIT19 to 1 + +//---------------------------------------------------------------------------- +// 8190 CPU General Register (offset 0x100, 4 byte) +//---------------------------------------------------------------------------- +#define CPU_CCK_LOOPBACK 0x00030000 +#define CPU_GEN_SYSTEM_RESET 0x00000001 +#define CPU_GEN_FIRMWARE_RESET 0x00000008 +#define CPU_GEN_BOOT_RDY 0x00000010 +#define CPU_GEN_FIRM_RDY 0x00000020 +#define CPU_GEN_PUT_CODE_OK 0x00000080 +#define CPU_GEN_BB_RST 0x00000100 +#define CPU_GEN_PWR_STB_CPU 0x00000004 +#define CPU_GEN_NO_LOOPBACK_MSK 0xFFF8FFFF // Set bit18,17,16 to 0. Set bit19 +#define CPU_GEN_NO_LOOPBACK_SET 0x00080000 // Set BIT19 to 1 + CPU_GEN = 0x100, // CPU Reset Register + LED1Cfg = 0x154,// LED1 Configuration Register + LED0Cfg = 0x155,// LED0 Configuration Register + + AcmAvg = 0x170, // ACM Average Period Register + AcmHwCtrl = 0x171, // ACM Hardware Control Register +//---------------------------------------------------------------------------- +//// +//// 8190 AcmHwCtrl bits (offset 0x171, 1 byte) +////---------------------------------------------------------------------------- +// +#define AcmHw_HwEn BIT0 +#define AcmHw_BeqEn BIT1 +#define AcmHw_ViqEn BIT2 +#define AcmHw_VoqEn BIT3 +#define AcmHw_BeqStatus BIT4 +#define AcmHw_ViqStatus BIT5 +#define AcmHw_VoqStatus BIT6 + + AcmFwCtrl = 0x172, // ACM Firmware Control Register + AES_11N_FIX = 0x173, + VOAdmTime = 0x174, // VO Queue Admitted Time Register + VIAdmTime = 0x178, // VI Queue Admitted Time Register + BEAdmTime = 0x17C, // BE Queue Admitted Time Register + RQPN1 = 0x180, // Reserved Queue Page Number , Vo Vi, Be, Bk + RQPN2 = 0x184, // Reserved Queue Page Number, HCCA, Cmd, Mgnt, High + RQPN3 = 0x188, // Reserved Queue Page Number, Bcn, Public, +// QPRR = 0x1E0, // Queue Page Report per TID + QPNR = 0x1D0, //0x1F0, // Queue Packet Number report per TID + BQDA = 0x200, // Beacon Queue Descriptor Address + HQDA = 0x204, // High Priority Queue Descriptor Address + CQDA = 0x208, // Command Queue Descriptor Address + MQDA = 0x20C, // Management Queue Descriptor Address + HCCAQDA = 0x210, // HCCA Queue Descriptor Address + VOQDA = 0x214, // VO Queue Descriptor Address + VIQDA = 0x218, // VI Queue Descriptor Address + BEQDA = 0x21C, // BE Queue Descriptor Address + BKQDA = 0x220, // BK Queue Descriptor Address + RCQDA = 0x224, // Receive command Queue Descriptor Address + RDQDA = 0x228, // Receive Queue Descriptor Start Address + + MAR0 = 0x240, // Multicast filter. + MAR4 = 0x244, + + CCX_PERIOD = 0x250, // CCX Measurement Period Register, in unit of TU. + CLM_RESULT = 0x251, // CCA Busy fraction register. + NHM_PERIOD = 0x252, // NHM Measurement Period register, in unit of TU. + + NHM_THRESHOLD0 = 0x253, // Noise Histogram Meashorement0. + NHM_THRESHOLD1 = 0x254, // Noise Histogram Meashorement1. + NHM_THRESHOLD2 = 0x255, // Noise Histogram Meashorement2. + NHM_THRESHOLD3 = 0x256, // Noise Histogram Meashorement3. + NHM_THRESHOLD4 = 0x257, // Noise Histogram Meashorement4. + NHM_THRESHOLD5 = 0x258, // Noise Histogram Meashorement5. + NHM_THRESHOLD6 = 0x259, // Noise Histogram Meashorement6 + + MCTRL = 0x25A, // Measurement Control + + NHM_RPI_COUNTER0 = 0x264, // Noise Histogram RPI counter0, the fraction of signal strength < NHM_THRESHOLD0. + NHM_RPI_COUNTER1 = 0x265, // Noise Histogram RPI counter1, the fraction of signal strength in (NHM_THRESHOLD0, NHM_THRESHOLD1]. + NHM_RPI_COUNTER2 = 0x266, // Noise Histogram RPI counter2, the fraction of signal strength in (NHM_THRESHOLD1, NHM_THRESHOLD2]. + NHM_RPI_COUNTER3 = 0x267, // Noise Histogram RPI counter3, the fraction of signal strength in (NHM_THRESHOLD2, NHM_THRESHOLD3]. + NHM_RPI_COUNTER4 = 0x268, // Noise Histogram RPI counter4, the fraction of signal strength in (NHM_THRESHOLD3, NHM_THRESHOLD4]. + NHM_RPI_COUNTER5 = 0x269, // Noise Histogram RPI counter5, the fraction of signal strength in (NHM_THRESHOLD4, NHM_THRESHOLD5]. + NHM_RPI_COUNTER6 = 0x26A, // Noise Histogram RPI counter6, the fraction of signal strength in (NHM_THRESHOLD5, NHM_THRESHOLD6]. + NHM_RPI_COUNTER7 = 0x26B, // Noise Histogram RPI counter7, the fraction of signal strength in (NHM_THRESHOLD6, NHM_THRESHOLD7]. +#define BW_OPMODE_11J BIT0 +#define BW_OPMODE_5G BIT1 +#define BW_OPMODE_20MHZ BIT2 + BW_OPMODE = 0x300, // Bandwidth operation mode + MSR = 0x303, // Media Status register +#define MSR_LINK_MASK ((1<<0)|(1<<1)) +#define MSR_LINK_MANAGED 2 +#define MSR_LINK_NONE 0 +#define MSR_LINK_SHIFT 0 +#define MSR_LINK_ADHOC 1 +#define MSR_LINK_MASTER 3 +#define MSR_LINK_ENEDCA (1<<4) + RETRY_LIMIT = 0x304, // Retry Limit [15:8]-short, [7:0]-long +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_LONG_SHIFT 0 + TSFR = 0x308, + RRSR = 0x310, // Response Rate Set +#define RRSR_RSC_OFFSET 21 +#define RRSR_SHORT_OFFSET 23 +#define RRSR_RSC_DUPLICATE 0x600000 +#define RRSR_RSC_LOWSUBCHNL 0x400000 +#define RRSR_RSC_UPSUBCHANL 0x200000 +#define RRSR_SHORT 0x800000 +#define RRSR_1M BIT0 +#define RRSR_2M BIT1 +#define RRSR_5_5M BIT2 +#define RRSR_11M BIT3 +#define RRSR_6M BIT4 +#define RRSR_9M BIT5 +#define RRSR_12M BIT6 +#define RRSR_18M BIT7 +#define RRSR_24M BIT8 +#define RRSR_36M BIT9 +#define RRSR_48M BIT10 +#define RRSR_54M BIT11 +#define RRSR_MCS0 BIT12 +#define RRSR_MCS1 BIT13 +#define RRSR_MCS2 BIT14 +#define RRSR_MCS3 BIT15 +#define RRSR_MCS4 BIT16 +#define RRSR_MCS5 BIT17 +#define RRSR_MCS6 BIT18 +#define RRSR_MCS7 BIT19 +#define BRSR_AckShortPmb BIT23 // CCK ACK: use Short Preamble or not. + RATR0 = 0x320, // Rate Adaptive Table register1 + UFWP = 0x318, + DRIVER_RSSI = 0x32c, // Driver tell Firmware current RSSI +//---------------------------------------------------------------------------- +// 8190 Rate Adaptive Table Register (offset 0x320, 4 byte) +//---------------------------------------------------------------------------- +//CCK +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +//OFDM +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +//MCS 1 Spatial Stream +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +//MCS 2 Spatial Stream +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 +// ALL CCK Rate +#define RATE_ALL_CCK RATR_1M|RATR_2M|RATR_55M|RATR_11M +#define RATE_ALL_OFDM_AG RATR_6M|RATR_9M|RATR_12M|RATR_18M|RATR_24M\ + |RATR_36M|RATR_48M|RATR_54M +#define RATE_ALL_OFDM_1SS RATR_MCS0|RATR_MCS1|RATR_MCS2|RATR_MCS3 | \ + RATR_MCS4|RATR_MCS5|RATR_MCS6|RATR_MCS7 +#define RATE_ALL_OFDM_2SS RATR_MCS8|RATR_MCS9 |RATR_MCS10|RATR_MCS11| \ + RATR_MCS12|RATR_MCS13|RATR_MCS14|RATR_MCS15 + + MCS_TXAGC = 0x340, // MCS AGC + CCK_TXAGC = 0x348, // CCK AGC +// ISR = 0x350, // Interrupt Status Register +// IMR = 0x354, // Interrupt Mask Register +// IMR_POLL = 0x360, + MacBlkCtrl = 0x403, // Mac block on/off control register + + EPROM_CMD = 0xfe58, +#define Cmd9346CR_9356SEL (1<<4) +#define EPROM_CMD_RESERVED_MASK (1<<5) +#define EPROM_CMD_OPERATING_MODE_SHIFT 6 +#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) +#define EPROM_CMD_CONFIG 0x3 +#define EPROM_CMD_NORMAL 0 +#define EPROM_CMD_LOAD 1 +#define EPROM_CMD_PROGRAM 2 +#define EPROM_CS_SHIFT 3 +#define EPROM_CK_SHIFT 2 +#define EPROM_W_SHIFT 1 +#define EPROM_R_SHIFT 0 + MAC0 = 0x000, + MAC1 = 0x001, + MAC2 = 0x002, + MAC3 = 0x003, + MAC4 = 0x004, + MAC5 = 0x005, + +}; +//---------------------------------------------------------------------------- +// 818xB AnaParm & AnaParm2 Register +//---------------------------------------------------------------------------- +//#define ANAPARM_ASIC_ON 0x45090658 +//#define ANAPARM2_ASIC_ON 0x727f3f52 +#define GPI 0x108 +#define GPO 0x109 +#define GPE 0x10a +#endif diff --git a/drivers/staging/rtl8192u/r8192U_wx.c b/drivers/staging/rtl8192u/r8192U_wx.c new file mode 100644 index 0000000000000000000000000000000000000000..25d5c870b0fb126a3669793d2f95b1b6f2fc17d5 --- /dev/null +++ b/drivers/staging/rtl8192u/r8192U_wx.c @@ -0,0 +1,1228 @@ +/* + This file contains wireless extension handlers. + + This is part of rtl8180 OpenSource driver. + Copyright (C) Andrea Merello 2004-2005 + Released under the terms of GPL (General Public Licence) + + Parts of this driver are based on the GPL part + of the official realtek driver. + + Parts of this driver are based on the rtl8180 driver skeleton + from Patric Schenke & Andres Salomon. + + Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver. + + We want to tanks the Authors of those projects and the Ndiswrapper + project Authors. +*/ + +#include +#include "r8192U.h" +#include "r8192U_hw.h" + +#ifdef ENABLE_DOT11D +#include "dot11d.h" +#endif + +#define RATE_COUNT 12 +u32 rtl8180_rates[] = {1000000,2000000,5500000,11000000, + 6000000,9000000,12000000,18000000,24000000,36000000,48000000,54000000}; + + +#ifndef ENETDOWN +#define ENETDOWN 1 +#endif + +static int r8192_wx_get_freq(struct net_device *dev, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + return ieee80211_wx_get_freq(priv->ieee80211,a,wrqu,b); +} + + +static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + struct r8192_priv *priv=ieee80211_priv(dev); + + return ieee80211_wx_get_mode(priv->ieee80211,a,wrqu,b); +} + + + +static int r8192_wx_get_rate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + return ieee80211_wx_get_rate(priv->ieee80211,info,wrqu,extra); +} + + + +static int r8192_wx_set_rate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + struct r8192_priv *priv = ieee80211_priv(dev); + + down(&priv->wx_sem); + + ret = ieee80211_wx_set_rate(priv->ieee80211,info,wrqu,extra); + + up(&priv->wx_sem); + + return ret; +} + + +static int r8192_wx_set_rts(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + struct r8192_priv *priv = ieee80211_priv(dev); + + down(&priv->wx_sem); + + ret = ieee80211_wx_set_rts(priv->ieee80211,info,wrqu,extra); + + up(&priv->wx_sem); + + return ret; +} + +static int r8192_wx_get_rts(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + return ieee80211_wx_get_rts(priv->ieee80211,info,wrqu,extra); +} + +static int r8192_wx_set_power(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + struct r8192_priv *priv = ieee80211_priv(dev); + + down(&priv->wx_sem); + + ret = ieee80211_wx_set_power(priv->ieee80211,info,wrqu,extra); + + up(&priv->wx_sem); + + return ret; +} + +static int r8192_wx_get_power(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + return ieee80211_wx_get_power(priv->ieee80211,info,wrqu,extra); +} + +#ifdef JOHN_IOCTL +u16 read_rtl8225(struct net_device *dev, u8 addr); +void write_rtl8225(struct net_device *dev, u8 adr, u16 data); +u32 john_read_rtl8225(struct net_device *dev, u8 adr); +void _write_rtl8225(struct net_device *dev, u8 adr, u16 data); + +static int r8192_wx_read_regs(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u8 addr; + u16 data1; + + down(&priv->wx_sem); + + + get_user(addr,(u8*)wrqu->data.pointer); + data1 = read_rtl8225(dev, addr); + wrqu->data.length = data1; + + up(&priv->wx_sem); + return 0; + +} + +static int r8192_wx_write_regs(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u8 addr; + + down(&priv->wx_sem); + + get_user(addr, (u8*)wrqu->data.pointer); + write_rtl8225(dev, addr, wrqu->data.length); + + up(&priv->wx_sem); + return 0; + +} + +void rtl8187_write_phy(struct net_device *dev, u8 adr, u32 data); +u8 rtl8187_read_phy(struct net_device *dev,u8 adr, u32 data); + +static int r8192_wx_read_bb(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u8 databb; + + down(&priv->wx_sem); + + databb = rtl8187_read_phy(dev, (u8)wrqu->data.length, 0x00000000); + wrqu->data.length = databb; + + up(&priv->wx_sem); + return 0; +} + +void rtl8187_write_phy(struct net_device *dev, u8 adr, u32 data); +static int r8192_wx_write_bb(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u8 databb; + + down(&priv->wx_sem); + + get_user(databb, (u8*)wrqu->data.pointer); + rtl8187_write_phy(dev, wrqu->data.length, databb); + + up(&priv->wx_sem); + return 0; + +} + + +static int r8192_wx_write_nicb(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u32 addr; + + down(&priv->wx_sem); + + get_user(addr, (u32*)wrqu->data.pointer); + write_nic_byte(dev, addr, wrqu->data.length); + + up(&priv->wx_sem); + return 0; + +} +static int r8192_wx_read_nicb(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u32 addr; + u16 data1; + + down(&priv->wx_sem); + + get_user(addr,(u32*)wrqu->data.pointer); + data1 = read_nic_byte(dev, addr); + wrqu->data.length = data1; + + up(&priv->wx_sem); + return 0; +} + +static int r8192_wx_get_ap_status(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee80211; + struct ieee80211_network *target; + int name_len; + + down(&priv->wx_sem); + + //count the length of input ssid + for(name_len=0 ; ((char*)wrqu->data.pointer)[name_len]!='\0' ; name_len++); + + //search for the correspoding info which is received + list_for_each_entry(target, &ieee->network_list, list) { + if ( (target->ssid_len == name_len) && + (strncmp(target->ssid, (char*)wrqu->data.pointer, name_len)==0)){ + if(target->wpa_ie_len>0 || target->rsn_ie_len>0 ) + //set flags=1 to indicate this ap is WPA + wrqu->data.flags = 1; + else wrqu->data.flags = 0; + + + break; + } + } + + up(&priv->wx_sem); + return 0; +} + + + +#endif +static int r8192_wx_force_reset(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + down(&priv->wx_sem); + + printk("%s(): force reset ! extra is %d\n",__FUNCTION__, *extra); + priv->force_reset = *extra; + up(&priv->wx_sem); + return 0; + +} + + +static int r8192_wx_set_rawtx(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + int ret; + + down(&priv->wx_sem); + + ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra); + + up(&priv->wx_sem); + + return ret; + +} + +static int r8192_wx_set_crcmon(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + int *parms = (int *)extra; + int enable = (parms[0] > 0); + short prev = priv->crcmon; + + down(&priv->wx_sem); + + if(enable) + priv->crcmon=1; + else + priv->crcmon=0; + + DMESG("bad CRC in monitor mode are %s", + priv->crcmon ? "accepted" : "rejected"); + + if(prev != priv->crcmon && priv->up){ + //rtl8180_down(dev); + //rtl8180_up(dev); + } + + up(&priv->wx_sem); + + return 0; +} + +static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + int ret; + down(&priv->wx_sem); + + ret = ieee80211_wx_set_mode(priv->ieee80211,a,wrqu,b); + + rtl8192_set_rxconf(dev); + + up(&priv->wx_sem); + return ret; +} + +struct iw_range_with_scan_capa +{ + /* Informative stuff (to choose between different interface) */ + __u32 throughput; /* To give an idea... */ + /* In theory this value should be the maximum benchmarked + * TCP/IP throughput, because with most of these devices the + * bit rate is meaningless (overhead an co) to estimate how + * fast the connection will go and pick the fastest one. + * I suggest people to play with Netperf or any benchmark... + */ + + /* NWID (or domain id) */ + __u32 min_nwid; /* Minimal NWID we are able to set */ + __u32 max_nwid; /* Maximal NWID we are able to set */ + + /* Old Frequency (backward compat - moved lower ) */ + __u16 old_num_channels; + __u8 old_num_frequency; + + /* Scan capabilities */ + __u8 scan_capa; +}; +static int rtl8180_wx_get_range(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_range *range = (struct iw_range *)extra; + struct iw_range_with_scan_capa* tmp = (struct iw_range_with_scan_capa*)range; + struct r8192_priv *priv = ieee80211_priv(dev); + u16 val; + int i; + + wrqu->data.length = sizeof(*range); + memset(range, 0, sizeof(*range)); + + /* Let's try to keep this struct in the same order as in + * linux/include/wireless.h + */ + + /* TODO: See what values we can set, and remove the ones we can't + * set, or fill them with some default data. + */ + + /* ~5 Mb/s real (802.11b) */ + range->throughput = 5 * 1000 * 1000; + + // TODO: Not used in 802.11b? +// range->min_nwid; /* Minimal NWID we are able to set */ + // TODO: Not used in 802.11b? +// range->max_nwid; /* Maximal NWID we are able to set */ + + /* Old Frequency (backward compat - moved lower ) */ +// range->old_num_channels; +// range->old_num_frequency; +// range->old_freq[6]; /* Filler to keep "version" at the same offset */ + if(priv->rf_set_sens != NULL) + range->sensitivity = priv->max_sens; /* signal level threshold range */ + + range->max_qual.qual = 100; + /* TODO: Find real max RSSI and stick here */ + range->max_qual.level = 0; + range->max_qual.noise = -98; + range->max_qual.updated = 7; /* Updated all three */ + + range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */ + /* TODO: Find real 'good' to 'bad' threshol value for RSSI */ + range->avg_qual.level = 20 + -98; + range->avg_qual.noise = 0; + range->avg_qual.updated = 7; /* Updated all three */ + + range->num_bitrates = RATE_COUNT; + + for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) { + range->bitrate[i] = rtl8180_rates[i]; + } + + range->min_frag = MIN_FRAG_THRESHOLD; + range->max_frag = MAX_FRAG_THRESHOLD; + + range->min_pmp=0; + range->max_pmp = 5000000; + range->min_pmt = 0; + range->max_pmt = 65535*1000; + range->pmp_flags = IW_POWER_PERIOD; + range->pmt_flags = IW_POWER_TIMEOUT; + range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; + + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 16; + +// range->retry_capa; /* What retry options are supported */ +// range->retry_flags; /* How to decode max/min retry limit */ +// range->r_time_flags; /* How to decode max/min retry life */ +// range->min_retry; /* Minimal number of retries */ +// range->max_retry; /* Maximal number of retries */ +// range->min_r_time; /* Minimal retry lifetime */ +// range->max_r_time; /* Maximal retry lifetime */ + + + for (i = 0, val = 0; i < 14; i++) { + + // Include only legal frequencies for some countries +#ifdef ENABLE_DOT11D + if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) { +#else + if ((priv->ieee80211->channel_map)[i+1]) { +#endif + range->freq[val].i = i + 1; + range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000; + range->freq[val].e = 1; + val++; + } else { + // FIXME: do we need to set anything for channels + // we don't use ? + } + + if (val == IW_MAX_FREQUENCIES) + break; + } + range->num_frequency = val; + range->num_channels = val; +#if WIRELESS_EXT > 17 + range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2| + IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP; +#endif + tmp->scan_capa = 0x01; + return 0; +} + + +static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + struct ieee80211_device* ieee = priv->ieee80211; + int ret = 0; + + if(!priv->up) return -ENETDOWN; + + if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true) + return -EAGAIN; + if (wrqu->data.flags & IW_SCAN_THIS_ESSID) + { + struct iw_scan_req* req = (struct iw_scan_req*)b; + if (req->essid_len) + { + //printk("==**&*&*&**===>scan set ssid:%s\n", req->essid); + ieee->current_network.ssid_len = req->essid_len; + memcpy(ieee->current_network.ssid, req->essid, req->essid_len); + //printk("=====>network ssid:%s\n", ieee->current_network.ssid); + } + } + + down(&priv->wx_sem); + if(priv->ieee80211->state != IEEE80211_LINKED){ + priv->ieee80211->scanning = 0; + ieee80211_softmac_scan_syncro(priv->ieee80211); + ret = 0; + } + else + ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b); + up(&priv->wx_sem); + return ret; +} + + +static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + + int ret; + struct r8192_priv *priv = ieee80211_priv(dev); + + if(!priv->up) return -ENETDOWN; + + down(&priv->wx_sem); + + ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b); + + up(&priv->wx_sem); + + return ret; +} + +static int r8192_wx_set_essid(struct net_device *dev, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + int ret; + down(&priv->wx_sem); + + ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b); + + up(&priv->wx_sem); + + return ret; +} + + + + +static int r8192_wx_get_essid(struct net_device *dev, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + int ret; + struct r8192_priv *priv = ieee80211_priv(dev); + + down(&priv->wx_sem); + + ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b); + + up(&priv->wx_sem); + + return ret; +} + + +static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + int ret; + struct r8192_priv *priv = ieee80211_priv(dev); + + down(&priv->wx_sem); + + ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b); + + up(&priv->wx_sem); + return ret; +} + +static int r8192_wx_get_name(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra); +} + + +static int r8192_wx_set_frag(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + if (wrqu->frag.disabled) + priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD; + else { + if (wrqu->frag.value < MIN_FRAG_THRESHOLD || + wrqu->frag.value > MAX_FRAG_THRESHOLD) + return -EINVAL; + + priv->ieee80211->fts = wrqu->frag.value & ~0x1; + } + + return 0; +} + + +static int r8192_wx_get_frag(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + wrqu->frag.value = priv->ieee80211->fts; + wrqu->frag.fixed = 0; /* no auto select */ + wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); + + return 0; +} + + +static int r8192_wx_set_wap(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *awrq, + char *extra) +{ + + int ret; + struct r8192_priv *priv = ieee80211_priv(dev); +// struct sockaddr *temp = (struct sockaddr *)awrq; + down(&priv->wx_sem); + + ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra); + + up(&priv->wx_sem); + + return ret; + +} + + +static int r8192_wx_get_wap(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra); +} + + +static int r8192_wx_get_enc(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key); +} + +static int r8192_wx_set_enc(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee80211; + int ret; + + //u32 TargetContent; + u32 hwkey[4]={0,0,0,0}; + u8 mask=0xff; + u32 key_idx=0; + //u8 broadcast_addr[6] ={ 0xff,0xff,0xff,0xff,0xff,0xff}; + u8 zero_addr[4][6] ={ {0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x01}, + {0x00,0x00,0x00,0x00,0x00,0x02}, + {0x00,0x00,0x00,0x00,0x00,0x03} }; + int i; + + if(!priv->up) return -ENETDOWN; + + down(&priv->wx_sem); + + RT_TRACE(COMP_SEC, "Setting SW wep key"); + ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key); + + up(&priv->wx_sem); + + + + //sometimes, the length is zero while we do not type key value + if(wrqu->encoding.length!=0){ + + for(i=0 ; i<4 ; i++){ + hwkey[i] |= key[4*i+0]&mask; + if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00; + if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00; + hwkey[i] |= (key[4*i+1]&mask)<<8; + hwkey[i] |= (key[4*i+2]&mask)<<16; + hwkey[i] |= (key[4*i+3]&mask)<<24; + } + + #define CONF_WEP40 0x4 + #define CONF_WEP104 0x14 + + switch(wrqu->encoding.flags & IW_ENCODE_INDEX){ + case 0: key_idx = ieee->tx_keyidx; break; + case 1: key_idx = 0; break; + case 2: key_idx = 1; break; + case 3: key_idx = 2; break; + case 4: key_idx = 3; break; + default: break; + } + + if(wrqu->encoding.length==0x5){ + ieee->pairwise_key_type = KEY_TYPE_WEP40; + EnableHWSecurityConfig8192(dev); + + setKey( dev, + key_idx, //EntryNo + key_idx, //KeyIndex + KEY_TYPE_WEP40, //KeyType + zero_addr[key_idx], + 0, //DefaultKey + hwkey); //KeyContent + + } + + else if(wrqu->encoding.length==0xd){ + ieee->pairwise_key_type = KEY_TYPE_WEP104; + EnableHWSecurityConfig8192(dev); + + setKey( dev, + key_idx, //EntryNo + key_idx, //KeyIndex + KEY_TYPE_WEP104, //KeyType + zero_addr[key_idx], + 0, //DefaultKey + hwkey); //KeyContent + + } + else printk("wrong type in WEP, not WEP40 and WEP104\n"); + + } + + return ret; +} + + +static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union + iwreq_data *wrqu, char *p){ + + struct r8192_priv *priv = ieee80211_priv(dev); + int *parms=(int*)p; + int mode=parms[0]; + + priv->ieee80211->active_scan = mode; + + return 1; +} + + + +static int r8192_wx_set_retry(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + int err = 0; + + down(&priv->wx_sem); + + if (wrqu->retry.flags & IW_RETRY_LIFETIME || + wrqu->retry.disabled){ + err = -EINVAL; + goto exit; + } + if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){ + err = -EINVAL; + goto exit; + } + + if(wrqu->retry.value > R8180_MAX_RETRY){ + err= -EINVAL; + goto exit; + } + if (wrqu->retry.flags & IW_RETRY_MAX) { + priv->retry_rts = wrqu->retry.value; + DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value); + + }else { + priv->retry_data = wrqu->retry.value; + DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value); + } + + /* FIXME ! + * We might try to write directly the TX config register + * or to restart just the (R)TX process. + * I'm unsure if whole reset is really needed + */ + + rtl8192_commit(dev); + /* + if(priv->up){ + rtl8180_rtx_disable(dev); + rtl8180_rx_enable(dev); + rtl8180_tx_enable(dev); + + } + */ +exit: + up(&priv->wx_sem); + + return err; +} + +static int r8192_wx_get_retry(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + + wrqu->retry.disabled = 0; /* can't be disabled */ + + if ((wrqu->retry.flags & IW_RETRY_TYPE) == + IW_RETRY_LIFETIME) + return -EINVAL; + + if (wrqu->retry.flags & IW_RETRY_MAX) { + wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; + wrqu->retry.value = priv->retry_rts; + } else { + wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; + wrqu->retry.value = priv->retry_data; + } + //printk("returning %d",wrqu->retry.value); + + + return 0; +} + +static int r8192_wx_get_sens(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + if(priv->rf_set_sens == NULL) + return -1; /* we have not this support for this radio */ + wrqu->sens.value = priv->sens; + return 0; +} + + +static int r8192_wx_set_sens(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + struct r8192_priv *priv = ieee80211_priv(dev); + + short err = 0; + down(&priv->wx_sem); + //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value); + if(priv->rf_set_sens == NULL) { + err= -1; /* we have not this support for this radio */ + goto exit; + } + if(priv->rf_set_sens(dev, wrqu->sens.value) == 0) + priv->sens = wrqu->sens.value; + else + err= -EINVAL; + +exit: + up(&priv->wx_sem); + + return err; +} + +#if (WIRELESS_EXT >= 18) +//hw security need to reorganized. +static int r8192_wx_set_enc_ext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret=0; + struct r8192_priv *priv = ieee80211_priv(dev); + struct ieee80211_device* ieee = priv->ieee80211; + //printk("===>%s()\n", __FUNCTION__); + + + down(&priv->wx_sem); + ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra); + + { + u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + u8 zero[6] = {0}; + u32 key[4] = {0}; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + struct iw_point *encoding = &wrqu->encoding; + u8 idx = 0, alg = 0, group = 0; + if ((encoding->flags & IW_ENCODE_DISABLED) || + ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01 + goto end_hw_sec; + + alg = (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; // as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4; + idx = encoding->flags & IW_ENCODE_INDEX; + if (idx) + idx --; + group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY; + + if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40)) + { + if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) ) + alg = KEY_TYPE_WEP104; + ieee->pairwise_key_type = alg; + EnableHWSecurityConfig8192(dev); + } + memcpy((u8*)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1 + + if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) ) + { + + setKey( dev, + idx,//EntryNo + idx, //KeyIndex + alg, //KeyType + zero, //MacAddr + 0, //DefaultKey + key); //KeyContent + } + else if (group) + { + ieee->group_key_type = alg; + setKey( dev, + idx,//EntryNo + idx, //KeyIndex + alg, //KeyType + broadcast_addr, //MacAddr + 0, //DefaultKey + key); //KeyContent + } + else //pairwise key + { + setKey( dev, + 4,//EntryNo + idx, //KeyIndex + alg, //KeyType + (u8*)ieee->ap_mac_addr, //MacAddr + 0, //DefaultKey + key); //KeyContent + } + + + } + +end_hw_sec: + + up(&priv->wx_sem); + return ret; + +} +static int r8192_wx_set_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + int ret=0; + //printk("====>%s()\n", __FUNCTION__); + struct r8192_priv *priv = ieee80211_priv(dev); + down(&priv->wx_sem); + ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra); + up(&priv->wx_sem); + return ret; +} + +static int r8192_wx_set_mlme(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + //printk("====>%s()\n", __FUNCTION__); + + int ret=0; + struct r8192_priv *priv = ieee80211_priv(dev); + down(&priv->wx_sem); + ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra); + + up(&priv->wx_sem); + return ret; +} +#endif +static int r8192_wx_set_gen_ie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + //printk("====>%s(), len:%d\n", __FUNCTION__, data->length); + int ret=0; + struct r8192_priv *priv = ieee80211_priv(dev); + down(&priv->wx_sem); + ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length); + up(&priv->wx_sem); + //printk("<======%s(), ret:%d\n", __FUNCTION__, ret); + return ret; + + +} + +static int dummy(struct net_device *dev, struct iw_request_info *a, + union iwreq_data *wrqu,char *b) +{ + return -1; +} + + +static iw_handler r8192_wx_handlers[] = +{ + NULL, /* SIOCSIWCOMMIT */ + r8192_wx_get_name, /* SIOCGIWNAME */ + dummy, /* SIOCSIWNWID */ + dummy, /* SIOCGIWNWID */ + r8192_wx_set_freq, /* SIOCSIWFREQ */ + r8192_wx_get_freq, /* SIOCGIWFREQ */ + r8192_wx_set_mode, /* SIOCSIWMODE */ + r8192_wx_get_mode, /* SIOCGIWMODE */ + r8192_wx_set_sens, /* SIOCSIWSENS */ + r8192_wx_get_sens, /* SIOCGIWSENS */ + NULL, /* SIOCSIWRANGE */ + rtl8180_wx_get_range, /* SIOCGIWRANGE */ + NULL, /* SIOCSIWPRIV */ + NULL, /* SIOCGIWPRIV */ + NULL, /* SIOCSIWSTATS */ + NULL, /* SIOCGIWSTATS */ + dummy, /* SIOCSIWSPY */ + dummy, /* SIOCGIWSPY */ + NULL, /* SIOCGIWTHRSPY */ + NULL, /* SIOCWIWTHRSPY */ + r8192_wx_set_wap, /* SIOCSIWAP */ + r8192_wx_get_wap, /* SIOCGIWAP */ +#if (WIRELESS_EXT >= 18) + r8192_wx_set_mlme, /* MLME-- */ +#else + NULL, +#endif + dummy, /* SIOCGIWAPLIST -- depricated */ + r8192_wx_set_scan, /* SIOCSIWSCAN */ + r8192_wx_get_scan, /* SIOCGIWSCAN */ + r8192_wx_set_essid, /* SIOCSIWESSID */ + r8192_wx_get_essid, /* SIOCGIWESSID */ + dummy, /* SIOCSIWNICKN */ + dummy, /* SIOCGIWNICKN */ + NULL, /* -- hole -- */ + NULL, /* -- hole -- */ + r8192_wx_set_rate, /* SIOCSIWRATE */ + r8192_wx_get_rate, /* SIOCGIWRATE */ + r8192_wx_set_rts, /* SIOCSIWRTS */ + r8192_wx_get_rts, /* SIOCGIWRTS */ + r8192_wx_set_frag, /* SIOCSIWFRAG */ + r8192_wx_get_frag, /* SIOCGIWFRAG */ + dummy, /* SIOCSIWTXPOW */ + dummy, /* SIOCGIWTXPOW */ + r8192_wx_set_retry, /* SIOCSIWRETRY */ + r8192_wx_get_retry, /* SIOCGIWRETRY */ + r8192_wx_set_enc, /* SIOCSIWENCODE */ + r8192_wx_get_enc, /* SIOCGIWENCODE */ + r8192_wx_set_power, /* SIOCSIWPOWER */ + r8192_wx_get_power, /* SIOCGIWPOWER */ + NULL, /*---hole---*/ + NULL, /*---hole---*/ + r8192_wx_set_gen_ie,//NULL, /* SIOCSIWGENIE */ + NULL, /* SIOCSIWGENIE */ + +#if (WIRELESS_EXT >= 18) + r8192_wx_set_auth,//NULL, /* SIOCSIWAUTH */ + NULL,//r8192_wx_get_auth,//NULL, /* SIOCSIWAUTH */ + r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */ + NULL,//r8192_wx_get_enc_ext,//NULL, /* SIOCSIWENCODEEXT */ +#else + NULL, + NULL, + NULL, + NULL, +#endif + NULL, /* SIOCSIWPMKSA */ + NULL, /*---hole---*/ + +}; + + +static const struct iw_priv_args r8192_private_args[] = { + + { + SIOCIWFIRSTPRIV + 0x0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc" + }, + + { + SIOCIWFIRSTPRIV + 0x1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan" + + }, + { + SIOCIWFIRSTPRIV + 0x2, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx" + } +#ifdef JOHN_IOCTL + , + { + SIOCIWFIRSTPRIV + 0x3, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readRF" + } + , + { + SIOCIWFIRSTPRIV + 0x4, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeRF" + } + , + { + SIOCIWFIRSTPRIV + 0x5, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readBB" + } + , + { + SIOCIWFIRSTPRIV + 0x6, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeBB" + } + , + { + SIOCIWFIRSTPRIV + 0x7, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readnicb" + } + , + { + SIOCIWFIRSTPRIV + 0x8, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writenicb" + } + , + { + SIOCIWFIRSTPRIV + 0x9, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo" + } + +#endif + , + { + SIOCIWFIRSTPRIV + 0x3, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset" + + } + +}; + + +static iw_handler r8192_private_handler[] = { +// r8192_wx_set_monitor, /* SIOCIWFIRSTPRIV */ + r8192_wx_set_crcmon, /*SIOCIWSECONDPRIV*/ +// r8192_wx_set_forceassociate, +// r8192_wx_set_beaconinterval, +// r8192_wx_set_monitor_type, + r8192_wx_set_scan_type, + r8192_wx_set_rawtx, +#ifdef JOHN_IOCTL + r8192_wx_read_regs, + r8192_wx_write_regs, + r8192_wx_read_bb, + r8192_wx_write_bb, + r8192_wx_read_nicb, + r8192_wx_write_nicb, + r8192_wx_get_ap_status, +#endif + //r8192_wx_null, + r8192_wx_force_reset, +}; + +//#if WIRELESS_EXT >= 17 +struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + struct ieee80211_device* ieee = priv->ieee80211; + struct iw_statistics* wstats = &priv->wstats; + int tmp_level = 0; + int tmp_qual = 0; + int tmp_noise = 0; + if(ieee->state < IEEE80211_LINKED) + { + wstats->qual.qual = 0; + wstats->qual.level = 0; + wstats->qual.noise = 0; + wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; + return wstats; + } + + tmp_level = (&ieee->current_network)->stats.rssi; + tmp_qual = (&ieee->current_network)->stats.signal; + tmp_noise = (&ieee->current_network)->stats.noise; + //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise); + + wstats->qual.level = tmp_level; + wstats->qual.qual = tmp_qual; + wstats->qual.noise = tmp_noise; + wstats->qual.updated = IW_QUAL_ALL_UPDATED| IW_QUAL_DBM; + return wstats; +} +//#endif + + +struct iw_handler_def r8192_wx_handlers_def={ + .standard = r8192_wx_handlers, + .num_standard = sizeof(r8192_wx_handlers) / sizeof(iw_handler), + .private = r8192_private_handler, + .num_private = sizeof(r8192_private_handler) / sizeof(iw_handler), + .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args), +#if WIRELESS_EXT >= 17 + .get_wireless_stats = r8192_get_wireless_stats, +#endif + .private_args = (struct iw_priv_args *)r8192_private_args, +}; diff --git a/drivers/staging/rtl8192u/r8192U_wx.h b/drivers/staging/rtl8192u/r8192U_wx.h new file mode 100644 index 0000000000000000000000000000000000000000..b2f7a571b1c8ffbf361694d9e936b0093e9d5f76 --- /dev/null +++ b/drivers/staging/rtl8192u/r8192U_wx.h @@ -0,0 +1,23 @@ +/* + This is part of rtl8180 OpenSource driver - v 0.3 + Copyright (C) Andrea Merello 2004 + Released under the terms of GPL (General Public Licence) + + Parts of this driver are based on the GPL part of the official realtek driver + Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon + Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver + + We want to tanks the Authors of such projects and the Ndiswrapper project Authors. +*/ + +/* this file (will) contains wireless extension handlers*/ + +#ifndef R8180_WX_H +#define R8180_WX_H +//#include +//#include "ieee80211.h" +extern struct iw_handler_def r8192_wx_handlers_def; +/* Enable the rtl819x_core.c to share this function, david 2008.9.22 */ +extern struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev); + +#endif diff --git a/drivers/staging/rtl8192u/r819xU_HTGen.h b/drivers/staging/rtl8192u/r819xU_HTGen.h new file mode 100644 index 0000000000000000000000000000000000000000..f37b6d69b4046cf11fe53cd31021c8df97c0b0e0 --- /dev/null +++ b/drivers/staging/rtl8192u/r819xU_HTGen.h @@ -0,0 +1,13 @@ +// +// IOT Action for different AP +// +typedef enum _HT_IOT_ACTION{ + HT_IOT_ACT_TX_USE_AMSDU_4K = 0x00000001, + HT_IOT_ACT_TX_USE_AMSDU_8K = 0x00000002, + HT_IOT_ACT_DECLARE_MCS13 = 0x00000004, + HT_IOT_ACT_DISABLE_EDCA_TURBO = 0x00000008, + HT_IOT_ACT_MGNT_USE_CCK_6M = 0x00000010, + HT_IOT_ACT_CDD_FSYNC = 0x00000020, + HT_IOT_ACT_PURE_N_MODE = 0x00000040, +}HT_IOT_ACTION_E, *PHT_IOT_ACTION_E; + diff --git a/drivers/staging/rtl8192u/r819xU_HTType.h b/drivers/staging/rtl8192u/r819xU_HTType.h new file mode 100644 index 0000000000000000000000000000000000000000..01f58b902028b1e216e118c5eb02771f214b684c --- /dev/null +++ b/drivers/staging/rtl8192u/r819xU_HTType.h @@ -0,0 +1,391 @@ +#ifndef _R819XU_HTTYPE_H_ +#define _R819XU_HTTYPE_H_ + + +//------------------------------------------------------------ +// The HT Capability element is present in beacons, association request, +// reassociation request and probe response frames +//------------------------------------------------------------ + +// +// Operation mode value +// +#define HT_OPMODE_NO_PROTECT 0 +#define HT_OPMODE_OPTIONAL 1 +#define HT_OPMODE_40MHZ_PROTECT 2 +#define HT_OPMODE_MIXED 3 + +// +// MIMO Power Save Setings +// +#define MIMO_PS_STATIC 0 +#define MIMO_PS_DYNAMIC 1 +#define MIMO_PS_NOLIMIT 3 + + +// +// There should be 128 bits to cover all of the MCS rates. However, since +// 8190 does not support too much rates, one integer is quite enough. +// + +#define sHTCLng 4 + + +#define HT_SUPPORTED_MCS_1SS_BITMAP 0x000000ff +#define HT_SUPPORTED_MCS_2SS_BITMAP 0x0000ff00 +#define HT_SUPPORTED_MCS_1SS_2SS_BITMAP HT_MCS_1SS_BITMAP|HT_MCS_1SS_2SS_BITMAP + + +typedef enum _HT_MCS_RATE{ + HT_MCS0 = 0x00000001, + HT_MCS1 = 0x00000002, + HT_MCS2 = 0x00000004, + HT_MCS3 = 0x00000008, + HT_MCS4 = 0x00000010, + HT_MCS5 = 0x00000020, + HT_MCS6 = 0x00000040, + HT_MCS7 = 0x00000080, + HT_MCS8 = 0x00000100, + HT_MCS9 = 0x00000200, + HT_MCS10 = 0x00000400, + HT_MCS11 = 0x00000800, + HT_MCS12 = 0x00001000, + HT_MCS13 = 0x00002000, + HT_MCS14 = 0x00004000, + HT_MCS15 = 0x00008000, + // Do not define MCS32 here although 8190 support MCS32 +}HT_MCS_RATE,*PHT_MCS_RATE; + +// +// Represent Channel Width in HT Capabilities +// +typedef enum _HT_CHANNEL_WIDTH{ + HT_CHANNEL_WIDTH_20 = 0, + HT_CHANNEL_WIDTH_20_40 = 1, +}HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH; + +// +// Represent Extention Channel Offset in HT Capabilities +// This is available only in 40Mhz mode. +// +typedef enum _HT_EXTCHNL_OFFSET{ + HT_EXTCHNL_OFFSET_NO_EXT = 0, + HT_EXTCHNL_OFFSET_UPPER = 1, + HT_EXTCHNL_OFFSET_NO_DEF = 2, + HT_EXTCHNL_OFFSET_LOWER = 3, +}HT_EXTCHNL_OFFSET, *PHT_EXTCHNL_OFFSET; + +typedef enum _CHNLOP{ + CHNLOP_NONE = 0, // No Action now + CHNLOP_SCAN = 1, // Scan in progress + CHNLOP_SWBW = 2, // Bandwidth switching in progress + CHNLOP_SWCHNL = 3, // Software Channel switching in progress +} CHNLOP, *PCHNLOP; + +// Determine if the Channel Operation is in progress +#define CHHLOP_IN_PROGRESS(_pHTInfo) \ + ((_pHTInfo)->ChnlOp > CHNLOP_NONE) ? TRUE : FALSE + + +typedef enum _HT_ACTION{ + ACT_RECOMMAND_WIDTH = 0, + ACT_MIMO_PWR_SAVE = 1, + ACT_PSMP = 2, + ACT_SET_PCO_PHASE = 3, + ACT_MIMO_CHL_MEASURE = 4, + ACT_RECIPROCITY_CORRECT = 5, + ACT_MIMO_CSI_MATRICS = 6, + ACT_MIMO_NOCOMPR_STEER = 7, + ACT_MIMO_COMPR_STEER = 8, + ACT_ANTENNA_SELECT = 9, +} HT_ACTION, *PHT_ACTION; + + +/* 2007/06/07 MH Define sub-carrier mode for 40MHZ. */ +typedef enum _HT_Bandwidth_40MHZ_Sub_Carrier{ + SC_MODE_DUPLICATE = 0, + SC_MODE_LOWER = 1, + SC_MODE_UPPER = 2, + SC_MODE_FULL40MHZ = 3, +}HT_BW40_SC_E; + +typedef struct _HT_CAPABILITY_ELE{ + + //HT capability info + u8 AdvCoding:1; + u8 ChlWidth:1; + u8 MimoPwrSave:2; + u8 GreenField:1; + u8 ShortGI20Mhz:1; + u8 ShortGI40Mhz:1; + u8 TxSTBC:1; + u8 RxSTBC:2; + u8 DelayBA:1; + u8 MaxAMSDUSize:1; + u8 DssCCk:1; + u8 PSMP:1; + u8 Rsvd1:1; + u8 LSigTxopProtect:1; + + //MAC HT parameters info + u8 MaxRxAMPDUFactor:2; + u8 MPDUDensity:3; + u8 Rsvd2:3; + + //Supported MCS set + u8 MCS[16]; + + + //Extended HT Capability Info + u16 ExtHTCapInfo; + + //TXBF Capabilities + u8 TxBFCap[4]; + + //Antenna Selection Capabilities + u8 ASCap; + +}__attribute__((packed)) HT_CAPABILITY_ELE, *PHT_CAPABILITY_ELE; + +//------------------------------------------------------------ +// The HT Information element is present in beacons +// Only AP is required to include this element +//------------------------------------------------------------ + +typedef struct _HT_INFORMATION_ELE{ + u8 ControlChl; + + u8 ExtChlOffset:2; + u8 RecommemdedTxWidth:1; + u8 RIFS:1; + u8 PSMPAccessOnly:1; + u8 SrvIntGranularity:3; + + u8 OptMode:2; + u8 NonGFDevPresent:1; + u8 Revd1:5; + u8 Revd2:8; + + u8 Rsvd3:6; + u8 DualBeacon:1; + u8 DualCTSProtect:1; + + u8 SecondaryBeacon:1; + u8 LSigTxopProtectFull:1; + u8 PcoActive:1; + u8 PcoPhase:1; + u8 Rsvd4:4; + + u8 BasicMSC[16]; +}__attribute__((packed)) HT_INFORMATION_ELE, *PHT_INFORMATION_ELE; + +// +// MIMO Power Save control field. +// This is appear in MIMO Power Save Action Frame +// +typedef struct _MIMOPS_CTRL{ + u8 MimoPsEnable:1; + u8 MimoPsMode:1; + u8 Reserved:6; +} MIMOPS_CTRL, *PMIMOPS_CTRL; + +typedef enum _HT_SPEC_VER{ + HT_SPEC_VER_IEEE = 0, + HT_SPEC_VER_EWC = 1, +}HT_SPEC_VER, *PHT_SPEC_VER; + +typedef enum _HT_AGGRE_MODE_E{ + HT_AGG_AUTO = 0, + HT_AGG_FORCE_ENABLE = 1, + HT_AGG_FORCE_DISABLE = 2, +}HT_AGGRE_MODE_E, *PHT_AGGRE_MODE_E; + +//------------------------------------------------------------ +// The Data structure is used to keep HT related variables when card is +// configured as non-AP STA mode. **Note** Current_xxx should be set +// to default value in HTInitializeHTInfo() +//------------------------------------------------------------ + +typedef struct _RT_HIGH_THROUGHPUT{ +// DECLARE_RT_OBJECT(_RT_HIGH_THROUGHPUT); + u8 bEnableHT; + u8 bCurrentHTSupport; + + u8 bRegBW40MHz; // Tx 40MHz channel capablity + u8 bCurBW40MHz; // Tx 40MHz channel capability + + u8 bRegShortGI40MHz; // Tx Short GI for 40Mhz + u8 bCurShortGI40MHz; // Tx Short GI for 40MHz + + u8 bRegShortGI20MHz; // Tx Short GI for 20MHz + u8 bCurShortGI20MHz; // Tx Short GI for 20MHz + + u8 bRegSuppCCK; // Tx CCK rate capability + u8 bCurSuppCCK; // Tx CCK rate capability + + // 802.11n spec version for "peer" + HT_SPEC_VER ePeerHTSpecVer; + + + // HT related information for "Self" + HT_CAPABILITY_ELE SelfHTCap; // This is HT cap element sent to peer STA, which also indicate HT Rx capabilities. + HT_INFORMATION_ELE SelfHTInfo; // This is HT info element sent to peer STA, which also indicate HT Rx capabilities. + + // HT related information for "Peer" + u8 PeerHTCapBuf[32]; + u8 PeerHTInfoBuf[32]; + + + // A-MSDU related + u8 bAMSDU_Support; // This indicates Tx A-MSDU capability + u16 nAMSDU_MaxSize; // This indicates Tx A-MSDU capability + u8 bCurrent_AMSDU_Support; // This indicates Tx A-MSDU capability + u16 nCurrent_AMSDU_MaxSize; // This indicates Tx A-MSDU capability + + + // AMPDU related <2006.08.10 Emily> + u8 bAMPDUEnable; // This indicate Tx A-MPDU capability + u8 bCurrentAMPDUEnable; // This indicate Tx A-MPDU capability + u8 AMPDU_Factor; // This indicate Tx A-MPDU capability + u8 CurrentAMPDUFactor; // This indicate Tx A-MPDU capability + u8 MPDU_Density; // This indicate Tx A-MPDU capability + u8 CurrentMPDUDensity; // This indicate Tx A-MPDU capability + + // Forced A-MPDU enable + HT_AGGRE_MODE_E ForcedAMPDUMode; + u8 ForcedAMPDUFactor; + u8 ForcedMPDUDensity; + + // Forced A-MSDU enable + HT_AGGRE_MODE_E ForcedAMSDUMode; + u16 ForcedAMSDUMaxSize; + + u8 bForcedShortGI; + + u8 CurrentOpMode; + + // MIMO PS related + u8 SelfMimoPs; + u8 PeerMimoPs; + + // 40MHz Channel Offset settings. + HT_EXTCHNL_OFFSET CurSTAExtChnlOffset; + u8 bCurTxBW40MHz; // If we use 40 MHz to Tx + u8 PeerBandwidth; + + // For Bandwidth Switching + u8 bSwBwInProgress; + CHNLOP ChnlOp; // software switching channel in progress. By Bruce, 2008-02-15. + u8 SwBwStep; + //RT_TIMER SwBwTimer; + struct timer_list SwBwTimer; + + // For Realtek proprietary A-MPDU factor for aggregation + u8 bRegRT2RTAggregation; + u8 bCurrentRT2RTAggregation; + u8 bCurrentRT2RTLongSlotTime; + u8 szRT2RTAggBuffer[10]; + + // Rx Reorder control + u8 bRegRxReorderEnable; + u8 bCurRxReorderEnable; + u8 RxReorderWinSize; + u8 RxReorderPendingTime; + u16 RxReorderDropCounter; + +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + u8 UsbTxAggrNum; +#endif +#ifdef USB_RX_AGGREGATION_SUPPORT + u8 UsbRxFwAggrEn; + u8 UsbRxFwAggrPageNum; + u8 UsbRxFwAggrPacketNum; + u8 UsbRxFwAggrTimeout; +#endif + + // Add for Broadcom(Linksys) IOT. Joseph + u8 bIsPeerBcm; + + // For IOT issue. + u32 IOTAction; +}RT_HIGH_THROUGHPUT, *PRT_HIGH_THROUGHPUT; + + +//------------------------------------------------------------ +// The Data structure is used to keep HT related variable for "each Sta" +// when card is configured as "AP mode" +//------------------------------------------------------------ + +typedef struct _RT_HTINFO_STA_ENTRY{ + u8 bEnableHT; + + u8 bSupportCck; + + u16 AMSDU_MaxSize; + + u8 AMPDU_Factor; + u8 MPDU_Density; + + u8 HTHighestOperaRate; + + u8 bBw40MHz; + + u8 MimoPs; + + u8 McsRateSet[16]; + + +}RT_HTINFO_STA_ENTRY, *PRT_HTINFO_STA_ENTRY; + + + + + +//------------------------------------------------------------ +// The Data structure is used to keep HT related variable for "each AP" +// when card is configured as "STA mode" +//------------------------------------------------------------ + +typedef struct _BSS_HT{ + + u8 bdSupportHT; + + // HT related elements + u8 bdHTCapBuf[32]; + u16 bdHTCapLen; + u8 bdHTInfoBuf[32]; + u16 bdHTInfoLen; + + HT_SPEC_VER bdHTSpecVer; + //HT_CAPABILITY_ELE bdHTCapEle; + //HT_INFORMATION_ELE bdHTInfoEle; + + u8 bdRT2RTAggregation; + u8 bdRT2RTLongSlotTime; +}BSS_HT, *PBSS_HT; + +typedef struct _MIMO_RSSI{ + u32 EnableAntenna; + u32 AntennaA; + u32 AntennaB; + u32 AntennaC; + u32 AntennaD; + u32 Average; +}MIMO_RSSI, *PMIMO_RSSI; + +typedef struct _MIMO_EVM{ + u32 EVM1; + u32 EVM2; +}MIMO_EVM, *PMIMO_EVM; + +typedef struct _FALSE_ALARM_STATISTICS{ + u32 Cnt_Parity_Fail; + u32 Cnt_Rate_Illegal; + u32 Cnt_Crc8_fail; + u32 Cnt_all; +}FALSE_ALARM_STATISTICS, *PFALSE_ALARM_STATISTICS; + + + +#endif //__INC_HTTYPE_H + diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c new file mode 100644 index 0000000000000000000000000000000000000000..fd19a85297a9052ab070b1d395be7b24650e8b7d --- /dev/null +++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c @@ -0,0 +1,791 @@ +/****************************************************************************** + + (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved. + + Module: r819xusb_cmdpkt.c (RTL8190 TX/RX command packet handler Source C File) + + Note: The module is responsible for handling TX and RX command packet. + 1. TX : Send set and query configuration command packet. + 2. RX : Receive tx feedback, beacon state, query configuration + command packet. + + Function: + + Export: + + Abbrev: + + History: + Data Who Remark + + 05/06/2008 amy Create initial version porting from windows driver. + +******************************************************************************/ +#include "r8192U.h" +#include "r819xU_cmdpkt.h" +/*---------------------------Define Local Constant---------------------------*/ +/* Debug constant*/ +#define CMPK_DEBOUNCE_CNT 1 +/* 2007/10/24 MH Add for printing a range of data. */ +#define CMPK_PRINT(Address)\ +{\ + unsigned char i;\ + u32 temp[10];\ + \ + memcpy(temp, Address, 40);\ + for (i = 0; i <40; i+=4)\ + printk("\r\n %08x", temp[i]);\ +}\ +/*---------------------------Define functions---------------------------------*/ + +rt_status +SendTxCommandPacket( + struct net_device *dev, + void* pData, + u32 DataLen + ) +{ + rt_status rtStatus = RT_STATUS_SUCCESS; + struct r8192_priv *priv = ieee80211_priv(dev); + struct sk_buff *skb; + cb_desc *tcb_desc; + unsigned char *ptr_buf; + //bool bLastInitPacket = false; + + //PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK); + + //Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ) + skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4); + memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); + tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE); + tcb_desc->queue_index = TXCMD_QUEUE; + tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL; + tcb_desc->bLastIniPkt = 0; + skb_reserve(skb, USB_HWDESC_HEADER_LEN); + ptr_buf = skb_put(skb, DataLen); + memset(ptr_buf,0,DataLen); + memcpy(ptr_buf,pData,DataLen); + tcb_desc->txbuf_size= (u16)DataLen; + + if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)|| + (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\ + (priv->ieee80211->queue_stop) ) { + RT_TRACE(COMP_FIRMWARE,"===================NULL packet==================================> tx full!\n"); + skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); + } else { + priv->ieee80211->softmac_hard_start_xmit(skb,dev); + } + + //PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK); + return rtStatus; +} + +/*----------------------------------------------------------------------------- + * Function: cmpk_message_handle_tx() + * + * Overview: Driver internal module can call the API to send message to + * firmware side. For example, you can send a debug command packet. + * Or you can send a request for FW to modify RLX4181 LBUS HW bank. + * Otherwise, you can change MAC/PHT/RF register by firmware at + * run time. We do not support message more than one segment now. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/06/2008 amy porting from windows code. + * + *---------------------------------------------------------------------------*/ + extern rt_status cmpk_message_handle_tx( + struct net_device *dev, + u8* codevirtualaddress, + u32 packettype, + u32 buffer_len) +{ + + bool rt_status = true; +#ifdef RTL8192U + return rt_status; +#else + struct r8192_priv *priv = ieee80211_priv(dev); + u16 frag_threshold; + u16 frag_length, frag_offset = 0; + //u16 total_size; + //int i; + + rt_firmware *pfirmware = priv->pFirmware; + struct sk_buff *skb; + unsigned char *seg_ptr; + cb_desc *tcb_desc; + u8 bLastIniPkt; + + firmware_init_param(dev); + //Fragmentation might be required + frag_threshold = pfirmware->cmdpacket_frag_thresold; + do { + if((buffer_len - frag_offset) > frag_threshold) { + frag_length = frag_threshold ; + bLastIniPkt = 0; + + } else { + frag_length = buffer_len - frag_offset; + bLastIniPkt = 1; + + } + + /* Allocate skb buffer to contain firmware info and tx descriptor info + * add 4 to avoid packet appending overflow. + * */ + #ifdef RTL8192U + skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4); + #else + skb = dev_alloc_skb(frag_length + 4); + #endif + memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); + tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE); + tcb_desc->queue_index = TXCMD_QUEUE; + tcb_desc->bCmdOrInit = packettype; + tcb_desc->bLastIniPkt = bLastIniPkt; + + #ifdef RTL8192U + skb_reserve(skb, USB_HWDESC_HEADER_LEN); + #endif + + seg_ptr = skb_put(skb, buffer_len); + /* + * Transform from little endian to big endian + * and pending zero + */ + memcpy(seg_ptr,codevirtualaddress,buffer_len); + tcb_desc->txbuf_size= (u16)buffer_len; + + + if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)|| + (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\ + (priv->ieee80211->queue_stop) ) { + RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n"); + skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); + } else { + priv->ieee80211->softmac_hard_start_xmit(skb,dev); + } + + codevirtualaddress += frag_length; + frag_offset += frag_length; + + }while(frag_offset < buffer_len); + + return rt_status; + + +#endif +} /* CMPK_Message_Handle_Tx */ + +/*----------------------------------------------------------------------------- + * Function: cmpk_counttxstatistic() + * + * Overview: + * + * Input: PADAPTER pAdapter - . + * CMPK_TXFB_T *psTx_FB - . + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/12/2008 amy Create Version 0 porting from windows code. + * + *---------------------------------------------------------------------------*/ +static void +cmpk_count_txstatistic( + struct net_device *dev, + cmpk_txfb_t *pstx_fb) +{ + struct r8192_priv *priv = ieee80211_priv(dev); +#ifdef ENABLE_PS + RT_RF_POWER_STATE rtState; + + pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState)); + + // When RF is off, we should not count the packet for hw/sw synchronize + // reason, ie. there may be a duration while sw switch is changed and hw + // switch is being changed. 2006.12.04, by shien chang. + if (rtState == eRfOff) + { + return; + } +#endif + +#ifdef TODO + if(pAdapter->bInHctTest) + return; +#endif + /* We can not know the packet length and transmit type: broadcast or uni + or multicast. So the relative statistics must be collected in tx + feedback info. */ + if (pstx_fb->tok) + { + priv->stats.txfeedbackok++; + priv->stats.txoktotal++; + priv->stats.txokbytestotal += pstx_fb->pkt_length; + priv->stats.txokinperiod++; + + /* We can not make sure broadcast/multicast or unicast mode. */ + if (pstx_fb->pkt_type == PACKET_MULTICAST) + { + priv->stats.txmulticast++; + priv->stats.txbytesmulticast += pstx_fb->pkt_length; + } + else if (pstx_fb->pkt_type == PACKET_BROADCAST) + { + priv->stats.txbroadcast++; + priv->stats.txbytesbroadcast += pstx_fb->pkt_length; + } + else + { + priv->stats.txunicast++; + priv->stats.txbytesunicast += pstx_fb->pkt_length; + } + } + else + { + priv->stats.txfeedbackfail++; + priv->stats.txerrtotal++; + priv->stats.txerrbytestotal += pstx_fb->pkt_length; + + /* We can not make sure broadcast/multicast or unicast mode. */ + if (pstx_fb->pkt_type == PACKET_MULTICAST) + { + priv->stats.txerrmulticast++; + } + else if (pstx_fb->pkt_type == PACKET_BROADCAST) + { + priv->stats.txerrbroadcast++; + } + else + { + priv->stats.txerrunicast++; + } + } + + priv->stats.txretrycount += pstx_fb->retry_cnt; + priv->stats.txfeedbackretry += pstx_fb->retry_cnt; + +} /* cmpk_CountTxStatistic */ + + + +/*----------------------------------------------------------------------------- + * Function: cmpk_handle_tx_feedback() + * + * Overview: The function is responsible for extract the message inside TX + * feedbck message from firmware. It will contain dedicated info in + * ws-06-0063-rtl8190-command-packet-specification. Please + * refer to chapter "TX Feedback Element". We have to read 20 bytes + * in the command packet. + * + * Input: struct net_device * dev + * u8 * pmsg - Msg Ptr of the command packet. + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/08/2008 amy Create Version 0 porting from windows code. + * + *---------------------------------------------------------------------------*/ +static void +cmpk_handle_tx_feedback( + struct net_device *dev, + u8 * pmsg) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + cmpk_txfb_t rx_tx_fb; /* */ + + priv->stats.txfeedback++; + + /* 0. Display received message. */ + //cmpk_Display_Message(CMPK_RX_TX_FB_SIZE, pMsg); + + /* 1. Extract TX feedback info from RFD to temp structure buffer. */ + /* It seems that FW use big endian(MIPS) and DRV use little endian in + windows OS. So we have to read the content byte by byte or transfer + endian type before copy the message copy. */ + /* 2007/07/05 MH Use pointer to transfer structure memory. */ + //memcpy((UINT8 *)&rx_tx_fb, pMsg, sizeof(CMPK_TXFB_T)); + memcpy((u8*)&rx_tx_fb, pmsg, sizeof(cmpk_txfb_t)); + /* 2. Use tx feedback info to count TX statistics. */ + cmpk_count_txstatistic(dev, &rx_tx_fb); + /* 2007/01/17 MH Comment previous method for TX statistic function. */ + /* Collect info TX feedback packet to fill TCB. */ + /* We can not know the packet length and transmit type: broadcast or uni + or multicast. */ + //CountTxStatistics( pAdapter, &tcb ); + +} /* cmpk_Handle_Tx_Feedback */ + +void +cmdpkt_beacontimerinterrupt_819xusb( + struct net_device *dev +) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u16 tx_rate; + { + // + // 070117, rcnjko: 87B have to S/W beacon for DTM encryption_cmn. + // + if(priv->ieee80211->current_network.mode == IEEE_A || + priv->ieee80211->current_network.mode == IEEE_N_5G || + (priv->ieee80211->current_network.mode == IEEE_N_24G && (!priv->ieee80211->pHTInfo->bCurSuppCCK))) + { + tx_rate = 60; + DMESG("send beacon frame tx rate is 6Mbpm\n"); + } + else + { + tx_rate =10; + DMESG("send beacon frame tx rate is 1Mbpm\n"); + } + + rtl819xusb_beacon_tx(dev,tx_rate); // HW Beacon + + } + +} + + + + +/*----------------------------------------------------------------------------- + * Function: cmpk_handle_interrupt_status() + * + * Overview: The function is responsible for extract the message from + * firmware. It will contain dedicated info in + * ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc. + * Please refer to chapter "Interrupt Status Element". + * + * Input: struct net_device *dev, + * u8* pmsg - Message Pointer of the command packet. + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/12/2008 amy Add this for rtl8192 porting from windows code. + * + *---------------------------------------------------------------------------*/ +static void +cmpk_handle_interrupt_status( + struct net_device *dev, + u8* pmsg) +{ + cmpk_intr_sta_t rx_intr_status; /* */ + struct r8192_priv *priv = ieee80211_priv(dev); + + DMESG("---> cmpk_Handle_Interrupt_Status()\n"); + + /* 0. Display received message. */ + //cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg); + + /* 1. Extract TX feedback info from RFD to temp structure buffer. */ + /* It seems that FW use big endian(MIPS) and DRV use little endian in + windows OS. So we have to read the content byte by byte or transfer + endian type before copy the message copy. */ + //rx_bcn_state.Element_ID = pMsg[0]; + //rx_bcn_state.Length = pMsg[1]; + rx_intr_status.length = pmsg[1]; + if (rx_intr_status.length != (sizeof(cmpk_intr_sta_t) - 2)) + { + DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n"); + return; + } + + + // Statistics of beacon for ad-hoc mode. + if( priv->ieee80211->iw_mode == IW_MODE_ADHOC) + { + //2 maybe need endian transform? + rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4)); + //rx_intr_status.InterruptStatus = N2H4BYTE(*((UINT32 *)(pMsg + 4))); + + DMESG("interrupt status = 0x%x\n", rx_intr_status.interrupt_status); + + if (rx_intr_status.interrupt_status & ISR_TxBcnOk) + { + priv->ieee80211->bibsscoordinator = true; + priv->stats.txbeaconokint++; + } + else if (rx_intr_status.interrupt_status & ISR_TxBcnErr) + { + priv->ieee80211->bibsscoordinator = false; + priv->stats.txbeaconerr++; + } + + if (rx_intr_status.interrupt_status & ISR_BcnTimerIntr) + { + cmdpkt_beacontimerinterrupt_819xusb(dev); + } + + } + + // Other informations in interrupt status we need? + + + DMESG("<---- cmpk_handle_interrupt_status()\n"); + +} /* cmpk_handle_interrupt_status */ + + +/*----------------------------------------------------------------------------- + * Function: cmpk_handle_query_config_rx() + * + * Overview: The function is responsible for extract the message from + * firmware. It will contain dedicated info in + * ws-06-0063-rtl8190-command-packet-specification. Please + * refer to chapter "Beacon State Element". + * + * Input: u8 * pmsg - Message Pointer of the command packet. + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/12/2008 amy Create Version 0 porting from windows code. + * + *---------------------------------------------------------------------------*/ +static void +cmpk_handle_query_config_rx( + struct net_device *dev, + u8* pmsg) +{ + cmpk_query_cfg_t rx_query_cfg; /* */ + + /* 0. Display received message. */ + //cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg); + + /* 1. Extract TX feedback info from RFD to temp structure buffer. */ + /* It seems that FW use big endian(MIPS) and DRV use little endian in + windows OS. So we have to read the content byte by byte or transfer + endian type before copy the message copy. */ + //rx_query_cfg.Element_ID = pMsg[0]; + //rx_query_cfg.Length = pMsg[1]; + rx_query_cfg.cfg_action = (pmsg[4] & 0x80000000)>>31; + rx_query_cfg.cfg_type = (pmsg[4] & 0x60) >> 5; + rx_query_cfg.cfg_size = (pmsg[4] & 0x18) >> 3; + rx_query_cfg.cfg_page = (pmsg[6] & 0x0F) >> 0; + rx_query_cfg.cfg_offset = pmsg[7]; + rx_query_cfg.value = (pmsg[8] << 24) | (pmsg[9] << 16) | + (pmsg[10] << 8) | (pmsg[11] << 0); + rx_query_cfg.mask = (pmsg[12] << 24) | (pmsg[13] << 16) | + (pmsg[14] << 8) | (pmsg[15] << 0); + +} /* cmpk_Handle_Query_Config_Rx */ + + +/*----------------------------------------------------------------------------- + * Function: cmpk_count_tx_status() + * + * Overview: Count aggregated tx status from firmwar of one type rx command + * packet element id = RX_TX_STATUS. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/12/2008 amy Create Version 0 porting from windows code. + * + *---------------------------------------------------------------------------*/ +static void cmpk_count_tx_status( struct net_device *dev, + cmpk_tx_status_t *pstx_status) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + +#ifdef ENABLE_PS + + RT_RF_POWER_STATE rtstate; + + pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState)); + + // When RF is off, we should not count the packet for hw/sw synchronize + // reason, ie. there may be a duration while sw switch is changed and hw + // switch is being changed. 2006.12.04, by shien chang. + if (rtState == eRfOff) + { + return; + } +#endif + + priv->stats.txfeedbackok += pstx_status->txok; + priv->stats.txoktotal += pstx_status->txok; + + priv->stats.txfeedbackfail += pstx_status->txfail; + priv->stats.txerrtotal += pstx_status->txfail; + + priv->stats.txretrycount += pstx_status->txretry; + priv->stats.txfeedbackretry += pstx_status->txretry; + + //pAdapter->TxStats.NumTxOkBytesTotal += psTx_FB->pkt_length; + //pAdapter->TxStats.NumTxErrBytesTotal += psTx_FB->pkt_length; + //pAdapter->MgntInfo.LinkDetectInfo.NumTxOkInPeriod++; + + priv->stats.txmulticast += pstx_status->txmcok; + priv->stats.txbroadcast += pstx_status->txbcok; + priv->stats.txunicast += pstx_status->txucok; + + priv->stats.txerrmulticast += pstx_status->txmcfail; + priv->stats.txerrbroadcast += pstx_status->txbcfail; + priv->stats.txerrunicast += pstx_status->txucfail; + + priv->stats.txbytesmulticast += pstx_status->txmclength; + priv->stats.txbytesbroadcast += pstx_status->txbclength; + priv->stats.txbytesunicast += pstx_status->txuclength; + + priv->stats.last_packet_rate = pstx_status->rate; +} /* cmpk_CountTxStatus */ + + + +/*----------------------------------------------------------------------------- + * Function: cmpk_handle_tx_status() + * + * Overview: Firmware add a new tx feedback status to reduce rx command + * packet buffer operation load. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/12/2008 amy Create Version 0 porting from windows code. + * + *---------------------------------------------------------------------------*/ +static void +cmpk_handle_tx_status( + struct net_device *dev, + u8* pmsg) +{ + cmpk_tx_status_t rx_tx_sts; /* */ + + memcpy((void*)&rx_tx_sts, (void*)pmsg, sizeof(cmpk_tx_status_t)); + /* 2. Use tx feedback info to count TX statistics. */ + cmpk_count_tx_status(dev, &rx_tx_sts); + +} /* cmpk_Handle_Tx_Status */ + + +/*----------------------------------------------------------------------------- + * Function: cmpk_handle_tx_rate_history() + * + * Overview: Firmware add a new tx rate history + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/12/2008 amy Create Version 0 porting from windows code. + * + *---------------------------------------------------------------------------*/ +static void +cmpk_handle_tx_rate_history( + struct net_device *dev, + u8* pmsg) +{ + cmpk_tx_rahis_t *ptxrate; +// RT_RF_POWER_STATE rtState; + u8 i, j; + u16 length = sizeof(cmpk_tx_rahis_t); + u32 *ptemp; + struct r8192_priv *priv = ieee80211_priv(dev); + + +#ifdef ENABLE_PS + pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState)); + + // When RF is off, we should not count the packet for hw/sw synchronize + // reason, ie. there may be a duration while sw switch is changed and hw + // switch is being changed. 2006.12.04, by shien chang. + if (rtState == eRfOff) + { + return; + } +#endif + + ptemp = (u32 *)pmsg; + + // + // Do endian transfer to word alignment(16 bits) for windows system. + // You must do different endian transfer for linux and MAC OS + // + for (i = 0; i < (length/4); i++) + { + u16 temp1, temp2; + + temp1 = ptemp[i]&0x0000FFFF; + temp2 = ptemp[i]>>16; + ptemp[i] = (temp1<<16)|temp2; + } + + ptxrate = (cmpk_tx_rahis_t *)pmsg; + + if (ptxrate == NULL ) + { + return; + } + + for (i = 0; i < 16; i++) + { + // Collect CCK rate packet num + if (i < 4) + priv->stats.txrate.cck[i] += ptxrate->cck[i]; + + // Collect OFDM rate packet num + if (i< 8) + priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i]; + + for (j = 0; j < 4; j++) + priv->stats.txrate.ht_mcs[j][i] += ptxrate->ht_mcs[j][i]; + } + +} /* cmpk_Handle_Tx_Rate_History */ + + +/*----------------------------------------------------------------------------- + * Function: cmpk_message_handle_rx() + * + * Overview: In the function, we will capture different RX command packet + * info. Every RX command packet element has different message + * length and meaning in content. We only support three type of RX + * command packet now. Please refer to document + * ws-06-0063-rtl8190-command-packet-specification. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/06/2008 amy Create Version 0 porting from windows code. + * + *---------------------------------------------------------------------------*/ +extern u32 +cmpk_message_handle_rx( + struct net_device *dev, + struct ieee80211_rx_stats *pstats) +{ +// u32 debug_level = DBG_LOUD; + struct r8192_priv *priv = ieee80211_priv(dev); + int total_length; + u8 cmd_length, exe_cnt = 0; + u8 element_id; + u8 *pcmd_buff; + + /* 0. Check inpt arguments. If is is a command queue message or pointer is + null. */ + if (/*(prfd->queue_id != CMPK_RX_QUEUE_ID) || */(pstats== NULL)) + { + /* Print error message. */ + /*RT_TRACE(COMP_SEND, DebugLevel, + ("\n\r[CMPK]-->Err queue id or pointer"));*/ + return 0; /* This is not a command packet. */ + } + + /* 1. Read received command packet message length from RFD. */ + total_length = pstats->Length; + + /* 2. Read virtual address from RFD. */ + pcmd_buff = pstats->virtual_address; + + /* 3. Read command pakcet element id and length. */ + element_id = pcmd_buff[0]; + /*RT_TRACE(COMP_SEND, DebugLevel, + ("\n\r[CMPK]-->element ID=%d Len=%d", element_id, total_length));*/ + + /* 4. Check every received command packet conent according to different + element type. Because FW may aggregate RX command packet to minimize + transmit time between DRV and FW.*/ + // Add a counter to prevent to locked in the loop too long + while (total_length > 0 || exe_cnt++ >100) + { + /* 2007/01/17 MH We support aggregation of different cmd in the same packet. */ + element_id = pcmd_buff[0]; + + switch(element_id) + { + case RX_TX_FEEDBACK: + cmpk_handle_tx_feedback (dev, pcmd_buff); + cmd_length = CMPK_RX_TX_FB_SIZE; + break; + + case RX_INTERRUPT_STATUS: + cmpk_handle_interrupt_status(dev, pcmd_buff); + cmd_length = sizeof(cmpk_intr_sta_t); + break; + + case BOTH_QUERY_CONFIG: + cmpk_handle_query_config_rx(dev, pcmd_buff); + cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE; + break; + + case RX_TX_STATUS: + cmpk_handle_tx_status(dev, pcmd_buff); + cmd_length = CMPK_RX_TX_STS_SIZE; + break; + + case RX_TX_PER_PKT_FEEDBACK: + // You must at lease add a switch case element here, + // Otherwise, we will jump to default case. + //DbgPrint("CCX Test\r\n"); + cmd_length = CMPK_RX_TX_FB_SIZE; + break; + + case RX_TX_RATE_HISTORY: + //DbgPrint(" rx tx rate history\r\n"); + cmpk_handle_tx_rate_history(dev, pcmd_buff); + cmd_length = CMPK_TX_RAHIS_SIZE; + break; + + default: + + RT_TRACE(COMP_ERR, "---->cmpk_message_handle_rx():unknow CMD Element\n"); + return 1; /* This is a command packet. */ + } + // 2007/01/22 MH Display received rx command packet info. + //cmpk_Display_Message(cmd_length, pcmd_buff); + + // 2007/01/22 MH Add to display tx statistic. + //cmpk_DisplayTxStatistic(pAdapter); + + /* 2007/03/09 MH Collect sidderent cmd element pkt num. */ + priv->stats.rxcmdpkt[element_id]++; + + total_length -= cmd_length; + pcmd_buff += cmd_length; + } /* while (total_length > 0) */ + return 1; /* This is a command packet. */ + +} /* CMPK_Message_Handle_Rx */ diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.h b/drivers/staging/rtl8192u/r819xU_cmdpkt.h new file mode 100644 index 0000000000000000000000000000000000000000..a8855e61b0e53756fadcfeeb26014f7edad254c1 --- /dev/null +++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.h @@ -0,0 +1,207 @@ +#ifndef R819XUSB_CMDPKT_H +#define R819XUSB_CMDPKT_H +/* Different command packet have dedicated message length and definition. */ +#define CMPK_RX_TX_FB_SIZE sizeof(cmpk_txfb_t) //20 +#define CMPK_TX_SET_CONFIG_SIZE sizeof(cmpk_set_cfg_t) //16 +#define CMPK_BOTH_QUERY_CONFIG_SIZE sizeof(cmpk_set_cfg_t) //16 +#define CMPK_RX_TX_STS_SIZE sizeof(cmpk_tx_status_t)// +#define CMPK_RX_DBG_MSG_SIZE sizeof(cmpk_rx_dbginfo_t)// +#define CMPK_TX_RAHIS_SIZE sizeof(cmpk_tx_rahis_t) + +/* 2008/05/08 amy For USB constant. */ +#define ISR_TxBcnOk BIT27 // Transmit Beacon OK +#define ISR_TxBcnErr BIT26 // Transmit Beacon Error +#define ISR_BcnTimerIntr BIT13 // Beacon Timer Interrupt + + +/* Define element ID of command packet. */ + +/*------------------------------Define structure----------------------------*/ +/* Define different command packet structure. */ +/* 1. RX side: TX feedback packet. */ +typedef struct tag_cmd_pkt_tx_feedback +{ + // DWORD 0 + u8 element_id; /* Command packet type. */ + u8 length; /* Command packet length. */ + /* 2007/07/05 MH Change tx feedback info field. */ + /*------TX Feedback Info Field */ + u8 TID:4; /* */ + u8 fail_reason:3; /* */ + u8 tok:1; /* Transmit ok. */ + u8 reserve1:4; /* */ + u8 pkt_type:2; /* */ + u8 bandwidth:1; /* */ + u8 qos_pkt:1; /* */ + + // DWORD 1 + u8 reserve2; /* */ + /*------TX Feedback Info Field */ + u8 retry_cnt; /* */ + u16 pkt_id; /* */ + + // DWORD 3 + u16 seq_num; /* */ + u8 s_rate; /* Start rate. */ + u8 f_rate; /* Final rate. */ + + // DWORD 4 + u8 s_rts_rate; /* */ + u8 f_rts_rate; /* */ + u16 pkt_length; /* */ + + // DWORD 5 + u16 reserve3; /* */ + u16 duration; /* */ +}cmpk_txfb_t; + +/* 2. RX side: Interrupt status packet. It includes Beacon State, + Beacon Timer Interrupt and other useful informations in MAC ISR Reg. */ +typedef struct tag_cmd_pkt_interrupt_status +{ + u8 element_id; /* Command packet type. */ + u8 length; /* Command packet length. */ + u16 reserve; + u32 interrupt_status; /* Interrupt Status. */ +}cmpk_intr_sta_t; + + +/* 3. TX side: Set configuration packet. */ +typedef struct tag_cmd_pkt_set_configuration +{ + u8 element_id; /* Command packet type. */ + u8 length; /* Command packet length. */ + u16 reserve1; /* */ + u8 cfg_reserve1:3; + u8 cfg_size:2; /* Configuration info. */ + u8 cfg_type:2; /* Configuration info. */ + u8 cfg_action:1; /* Configuration info. */ + u8 cfg_reserve2; /* Configuration info. */ + u8 cfg_page:4; /* Configuration info. */ + u8 cfg_reserve3:4; /* Configuration info. */ + u8 cfg_offset; /* Configuration info. */ + u32 value; /* */ + u32 mask; /* */ +}cmpk_set_cfg_t; + +/* 4. Both side : TX/RX query configuraton packet. The query structure is the + same as set configuration. */ +#define cmpk_query_cfg_t cmpk_set_cfg_t + +/* 5. Multi packet feedback status. */ +typedef struct tag_tx_stats_feedback // PJ quick rxcmd 09042007 +{ + // For endian transfer --> Driver will not the same as firmware structure. + // DW 0 + u16 reserve1; + u8 length; // Command packet length + u8 element_id; // Command packet type + + // DW 1 + u16 txfail; // Tx Fail count + u16 txok; // Tx ok count + + // DW 2 + u16 txmcok; // tx multicast + u16 txretry; // Tx Retry count + + // DW 3 + u16 txucok; // tx unicast + u16 txbcok; // tx broadcast + + // DW 4 + u16 txbcfail; // + u16 txmcfail; // + + // DW 5 + u16 reserve2; // + u16 txucfail; // + + // DW 6-8 + u32 txmclength; + u32 txbclength; + u32 txuclength; + + // DW 9 + u16 reserve3_23; + u8 reserve3_1; + u8 rate; +}__attribute__((packed)) cmpk_tx_status_t; + +/* 6. Debug feedback message. */ +/* 2007/10/23 MH Define RX debug message */ +typedef struct tag_rx_debug_message_feedback +{ + // For endian transfer --> for driver + // DW 0 + u16 reserve1; + u8 length; // Command packet length + u8 element_id; // Command packet type + + // DW 1-?? + // Variable debug message. + +}cmpk_rx_dbginfo_t; + +/* 2008/03/20 MH Define transmit rate history. For big endian format. */ +typedef struct tag_tx_rate_history +{ + // For endian transfer --> for driver + // DW 0 + u8 element_id; // Command packet type + u8 length; // Command packet length + u16 reserved1; + + // DW 1-2 CCK rate counter + u16 cck[4]; + + // DW 3-6 + u16 ofdm[8]; + + // DW 7-14 + //UINT16 MCS_BW0_SG0[16]; + + // DW 15-22 + //UINT16 MCS_BW1_SG0[16]; + + // DW 23-30 + //UINT16 MCS_BW0_SG1[16]; + + // DW 31-38 + //UINT16 MCS_BW1_SG1[16]; + + // DW 7-14 BW=0 SG=0 + // DW 15-22 BW=1 SG=0 + // DW 23-30 BW=0 SG=1 + // DW 31-38 BW=1 SG=1 + u16 ht_mcs[4][16]; + +}__attribute__((packed)) cmpk_tx_rahis_t; + +typedef enum tag_command_packet_directories +{ + RX_TX_FEEDBACK = 0, + RX_INTERRUPT_STATUS = 1, + TX_SET_CONFIG = 2, + BOTH_QUERY_CONFIG = 3, + RX_TX_STATUS = 4, + RX_DBGINFO_FEEDBACK = 5, + RX_TX_PER_PKT_FEEDBACK = 6, + RX_TX_RATE_HISTORY = 7, + RX_CMD_ELE_MAX +}cmpk_element_e; + +typedef enum _rt_status{ + RT_STATUS_SUCCESS, + RT_STATUS_FAILURE, + RT_STATUS_PENDING, + RT_STATUS_RESOURCE +}rt_status,*prt_status; + +extern rt_status cmpk_message_handle_tx(struct net_device *dev, u8* codevirtualaddress, u32 packettype, u32 buffer_len); + +extern u32 cmpk_message_handle_rx(struct net_device *dev, struct ieee80211_rx_stats * pstats); +extern rt_status SendTxCommandPacket( struct net_device *dev, void* pData, u32 DataLen); + + +#endif diff --git a/drivers/staging/rtl8192u/r819xU_firmware.c b/drivers/staging/rtl8192u/r819xU_firmware.c new file mode 100644 index 0000000000000000000000000000000000000000..3cc2d571f9bd491a6d56357e3bfcc2b9e5efa9b5 --- /dev/null +++ b/drivers/staging/rtl8192u/r819xU_firmware.c @@ -0,0 +1,434 @@ +/************************************************************************************************** + * Procedure: Init boot code/firmware code/data session + * + * Description: This routine will intialize firmware. If any error occurs during the initialization + * process, the routine shall terminate immediately and return fail. + * NIC driver should call NdisOpenFile only from MiniportInitialize. + * + * Arguments: The pointer of the adapter + + * Returns: + * NDIS_STATUS_FAILURE - the following initialization process should be terminated + * NDIS_STATUS_SUCCESS - if firmware initialization process success +**************************************************************************************************/ +//#include "ieee80211.h" +#include "r8192U.h" +#include "r8192U_hw.h" +#include "r819xU_firmware_img.h" +#include "r819xU_firmware.h" +#include +void firmware_init_param(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + rt_firmware *pfirmware = priv->pFirmware; + + pfirmware->cmdpacket_frag_thresold = GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE); +} + +/* + * segment the img and use the ptr and length to remember info on each segment + * + */ +bool fw_download_code(struct net_device *dev, u8 *code_virtual_address, u32 buffer_len) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + bool rt_status = true; + u16 frag_threshold; + u16 frag_length, frag_offset = 0; + //u16 total_size; + int i; + + rt_firmware *pfirmware = priv->pFirmware; + struct sk_buff *skb; + unsigned char *seg_ptr; + cb_desc *tcb_desc; + u8 bLastIniPkt; + + firmware_init_param(dev); + //Fragmentation might be required + frag_threshold = pfirmware->cmdpacket_frag_thresold; + do { + if((buffer_len - frag_offset) > frag_threshold) { + frag_length = frag_threshold ; + bLastIniPkt = 0; + + } else { + frag_length = buffer_len - frag_offset; + bLastIniPkt = 1; + + } + + /* Allocate skb buffer to contain firmware info and tx descriptor info + * add 4 to avoid packet appending overflow. + * */ + #ifdef RTL8192U + skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4); + #else + skb = dev_alloc_skb(frag_length + 4); + #endif + memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); + tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE); + tcb_desc->queue_index = TXCMD_QUEUE; + tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT; + tcb_desc->bLastIniPkt = bLastIniPkt; + + #ifdef RTL8192U + skb_reserve(skb, USB_HWDESC_HEADER_LEN); + #endif + seg_ptr = skb->data; + /* + * Transform from little endian to big endian + * and pending zero + */ + for(i=0 ; i < frag_length; i+=4) { + *seg_ptr++ = ((i+0)txbuf_size= (u16)i; + skb_put(skb, i); + + if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)|| + (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\ + (priv->ieee80211->queue_stop) ) { + RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n"); + skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); + } else { + priv->ieee80211->softmac_hard_start_xmit(skb,dev); + } + + code_virtual_address += frag_length; + frag_offset += frag_length; + + }while(frag_offset < buffer_len); + + return rt_status; + +} + +bool +fwSendNullPacket( + struct net_device *dev, + u32 Length +) +{ + bool rtStatus = true; + struct r8192_priv *priv = ieee80211_priv(dev); + struct sk_buff *skb; + cb_desc *tcb_desc; + unsigned char *ptr_buf; + bool bLastInitPacket = false; + + //PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK); + + //Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ) + skb = dev_alloc_skb(Length+ 4); + memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); + tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE); + tcb_desc->queue_index = TXCMD_QUEUE; + tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT; + tcb_desc->bLastIniPkt = bLastInitPacket; + ptr_buf = skb_put(skb, Length); + memset(ptr_buf,0,Length); + tcb_desc->txbuf_size= (u16)Length; + + if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)|| + (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\ + (priv->ieee80211->queue_stop) ) { + RT_TRACE(COMP_FIRMWARE,"===================NULL packet==================================> tx full!\n"); + skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); + } else { + priv->ieee80211->softmac_hard_start_xmit(skb,dev); + } + + //PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK); + return rtStatus; +} + + +//----------------------------------------------------------------------------- +// Procedure: Check whether main code is download OK. If OK, turn on CPU +// +// Description: CPU register locates in different page against general register. +// Switch to CPU register in the begin and switch back before return +// +// +// Arguments: The pointer of the adapter +// +// Returns: +// NDIS_STATUS_FAILURE - the following initialization process should be terminated +// NDIS_STATUS_SUCCESS - if firmware initialization process success +//----------------------------------------------------------------------------- +bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev) +{ + bool rt_status = true; + int check_putcodeOK_time = 200000, check_bootOk_time = 200000; + u32 CPU_status = 0; + + /* Check whether put code OK */ + do { + CPU_status = read_nic_dword(dev, CPU_GEN); + + if(CPU_status&CPU_GEN_PUT_CODE_OK) + break; + + }while(check_putcodeOK_time--); + + if(!(CPU_status&CPU_GEN_PUT_CODE_OK)) { + RT_TRACE(COMP_ERR, "Download Firmware: Put code fail!\n"); + goto CPUCheckMainCodeOKAndTurnOnCPU_Fail; + } else { + RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n"); + } + + /* Turn On CPU */ + CPU_status = read_nic_dword(dev, CPU_GEN); + write_nic_byte(dev, CPU_GEN, (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff)); + mdelay(1000); + + /* Check whether CPU boot OK */ + do { + CPU_status = read_nic_dword(dev, CPU_GEN); + + if(CPU_status&CPU_GEN_BOOT_RDY) + break; + }while(check_bootOk_time--); + + if(!(CPU_status&CPU_GEN_BOOT_RDY)) { + goto CPUCheckMainCodeOKAndTurnOnCPU_Fail; + } else { + RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n"); + } + + return rt_status; + +CPUCheckMainCodeOKAndTurnOnCPU_Fail: + RT_TRACE(COMP_ERR, "ERR in %s()\n", __FUNCTION__); + rt_status = FALSE; + return rt_status; +} + +bool CPUcheck_firmware_ready(struct net_device *dev) +{ + + bool rt_status = true; + int check_time = 200000; + u32 CPU_status = 0; + + /* Check Firmware Ready */ + do { + CPU_status = read_nic_dword(dev, CPU_GEN); + + if(CPU_status&CPU_GEN_FIRM_RDY) + break; + + }while(check_time--); + + if(!(CPU_status&CPU_GEN_FIRM_RDY)) + goto CPUCheckFirmwareReady_Fail; + else + RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n"); + + return rt_status; + +CPUCheckFirmwareReady_Fail: + RT_TRACE(COMP_ERR, "ERR in %s()\n", __FUNCTION__); + rt_status = false; + return rt_status; + +} + +bool init_firmware(struct net_device *dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + bool rt_status = TRUE; + + u8 *firmware_img_buf[3] = { &rtl8190_fwboot_array[0], + &rtl8190_fwmain_array[0], + &rtl8190_fwdata_array[0]}; + + u32 firmware_img_len[3] = { sizeof(rtl8190_fwboot_array), + sizeof(rtl8190_fwmain_array), + sizeof(rtl8190_fwdata_array)}; + u32 file_length = 0; + u8 *mapped_file = NULL; + u32 init_step = 0; + opt_rst_type_e rst_opt = OPT_SYSTEM_RESET; + firmware_init_step_e starting_state = FW_INIT_STEP0_BOOT; + + rt_firmware *pfirmware = priv->pFirmware; + const struct firmware *fw_entry; + const char *fw_name[3] = { "RTL8192U/boot.img", + "RTL8192U/main.img", + "RTL8192U/data.img"}; + int rc; + + RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n"); + + if (pfirmware->firmware_status == FW_STATUS_0_INIT ) { + /* it is called by reset */ + rst_opt = OPT_SYSTEM_RESET; + starting_state = FW_INIT_STEP0_BOOT; + // TODO: system reset + + }else if(pfirmware->firmware_status == FW_STATUS_5_READY) { + /* it is called by Initialize */ + rst_opt = OPT_FIRMWARE_RESET; + starting_state = FW_INIT_STEP2_DATA; + }else { + RT_TRACE(COMP_FIRMWARE, "PlatformInitFirmware: undefined firmware state\n"); + } + + /* + * Download boot, main, and data image for System reset. + * Download data image for firmware reseta + */ + priv->firmware_source = FW_SOURCE_IMG_FILE; + for(init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; init_step++) { + /* + * Open Image file, and map file to contineous memory if open file success. + * or read image file from array. Default load from IMG file + */ + if(rst_opt == OPT_SYSTEM_RESET) { + switch(priv->firmware_source) { + case FW_SOURCE_IMG_FILE: + rc = request_firmware(&fw_entry, fw_name[init_step],&priv->udev->dev); + if(rc < 0 ) { + RT_TRACE(COMP_ERR, "request firmware fail!\n"); + goto download_firmware_fail; + } + + if(fw_entry->size > sizeof(pfirmware->firmware_buf)) { + RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n"); + goto download_firmware_fail; + } + + if(init_step != FW_INIT_STEP1_MAIN) { + memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size); + mapped_file = pfirmware->firmware_buf; + file_length = fw_entry->size; + } else { + #ifdef RTL8190P + memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size); + mapped_file = pfirmware->firmware_buf; + file_length = fw_entry->size; + #else + memset(pfirmware->firmware_buf,0,128); + memcpy(&pfirmware->firmware_buf[128],fw_entry->data,fw_entry->size); + mapped_file = pfirmware->firmware_buf; + file_length = fw_entry->size + 128; + #endif + } + pfirmware->firmware_buf_size = file_length; + break; + + case FW_SOURCE_HEADER_FILE: + mapped_file = firmware_img_buf[init_step]; + file_length = firmware_img_len[init_step]; + if(init_step == FW_INIT_STEP2_DATA) { + memcpy(pfirmware->firmware_buf, mapped_file, file_length); + pfirmware->firmware_buf_size = file_length; + } + break; + + default: + break; + } + + + }else if(rst_opt == OPT_FIRMWARE_RESET ) { + /* we only need to download data.img here */ + mapped_file = pfirmware->firmware_buf; + file_length = pfirmware->firmware_buf_size; + } + + /* Download image file */ + /* The firmware download process is just as following, + * 1. that is each packet will be segmented and inserted to the wait queue. + * 2. each packet segment will be put in the skb_buff packet. + * 3. each skb_buff packet data content will already include the firmware info + * and Tx descriptor info + * */ + rt_status = fw_download_code(dev,mapped_file,file_length); + if(rst_opt == OPT_SYSTEM_RESET) { + release_firmware(fw_entry); + } + + if(rt_status != TRUE) { + goto download_firmware_fail; + } + + switch(init_step) { + case FW_INIT_STEP0_BOOT: + /* Download boot + * initialize command descriptor. + * will set polling bit when firmware code is also configured + */ + pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE; +#ifdef RTL8190P + // To initialize IMEM, CPU move code from 0x80000080, hence, we send 0x80 byte packet + rt_status = fwSendNullPacket(dev, RTL8190_CPU_START_OFFSET); + if(rt_status != true) + { + RT_TRACE(COMP_INIT, "fwSendNullPacket() fail ! \n"); + goto download_firmware_fail; + } +#endif + //mdelay(1000); + /* + * To initialize IMEM, CPU move code from 0x80000080, + * hence, we send 0x80 byte packet + */ + break; + + case FW_INIT_STEP1_MAIN: + /* Download firmware code. Wait until Boot Ready and Turn on CPU */ + pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE; + + /* Check Put Code OK and Turn On CPU */ + rt_status = CPUcheck_maincodeok_turnonCPU(dev); + if(rt_status != TRUE) { + RT_TRACE(COMP_ERR, "CPUcheck_maincodeok_turnonCPU fail!\n"); + goto download_firmware_fail; + } + + pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU; + break; + + case FW_INIT_STEP2_DATA: + /* download initial data code */ + pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE; + mdelay(1); + + rt_status = CPUcheck_firmware_ready(dev); + if(rt_status != TRUE) { + RT_TRACE(COMP_ERR, "CPUcheck_firmware_ready fail(%d)!\n",rt_status); + goto download_firmware_fail; + } + + /* wait until data code is initialized ready.*/ + pfirmware->firmware_status = FW_STATUS_5_READY; + break; + } + } + + RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n"); + //assert(pfirmware->firmware_status == FW_STATUS_5_READY, ("Firmware Download Fail\n")); + + return rt_status; + +download_firmware_fail: + RT_TRACE(COMP_ERR, "ERR in %s()\n", __FUNCTION__); + rt_status = FALSE; + return rt_status; + +} + + + + + + + + diff --git a/drivers/staging/rtl8192u/r819xU_firmware.h b/drivers/staging/rtl8192u/r819xU_firmware.h new file mode 100644 index 0000000000000000000000000000000000000000..a4bceeef33d31cfbf24efe9fb29700451d030948 --- /dev/null +++ b/drivers/staging/rtl8192u/r819xU_firmware.h @@ -0,0 +1,27 @@ +#ifndef __INC_FIRMWARE_H +#define __INC_FIRMWARE_H + +#define RTL8190_CPU_START_OFFSET 0x80 +/* TODO: this definition is TBD */ +//#define USB_HWDESC_HEADER_LEN 0 + +/* It should be double word alignment */ +//#if DEV_BUS_TYPE==PCI_INTERFACE +//#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) 4*(v/4) - 8 +//#else +#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4*(v/4) - 8 - USB_HWDESC_HEADER_LEN) +//#endif + +typedef enum _firmware_init_step{ + FW_INIT_STEP0_BOOT = 0, + FW_INIT_STEP1_MAIN = 1, + FW_INIT_STEP2_DATA = 2, +}firmware_init_step_e; + +typedef enum _opt_rst_type{ + OPT_SYSTEM_RESET = 0, + OPT_FIRMWARE_RESET = 1, +}opt_rst_type_e; + +#endif + diff --git a/drivers/staging/rtl8192u/r819xU_firmware_img.c b/drivers/staging/rtl8192u/r819xU_firmware_img.c new file mode 100644 index 0000000000000000000000000000000000000000..29b656d7d82bc5bce5cf57f6ed6373b03e1cec36 --- /dev/null +++ b/drivers/staging/rtl8192u/r819xU_firmware_img.c @@ -0,0 +1,3447 @@ +/*Created on 2008/ 7/16, 5:31*/ +#include + +u8 rtl8190_fwboot_array[] = { +0x10,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x3c,0x08,0xbf,0xc0,0x25,0x08,0x00,0x08, +0x3c,0x09,0xb0,0x03,0xad,0x28,0x00,0x20,0x40,0x80,0x68,0x00,0x00,0x00,0x00,0x00, +0x3c,0x0a,0xd0,0x00,0x40,0x8a,0x60,0x00,0x00,0x00,0x00,0x00,0x3c,0x08,0x80,0x01, +0x25,0x08,0xb0,0x50,0x24,0x09,0x00,0x01,0x3c,0x01,0x7f,0xff,0x34,0x21,0xff,0xff, +0x01,0x01,0x50,0x24,0x00,0x09,0x48,0x40,0x35,0x29,0x00,0x01,0x01,0x2a,0x10,0x2b, +0x14,0x40,0xff,0xfc,0x00,0x00,0x00,0x00,0x3c,0x0a,0x00,0x00,0x25,0x4a,0x00,0x00, +0x4c,0x8a,0x00,0x00,0x4c,0x89,0x08,0x00,0x00,0x00,0x00,0x00,0x3c,0x08,0x80,0x01, +0x25,0x08,0xb0,0x50,0x3c,0x01,0x80,0x00,0x01,0x21,0x48,0x25,0x3c,0x0a,0xbf,0xc0, +0x25,0x4a,0x00,0x7c,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20,0xad,0x00,0x00,0x00, +0x21,0x08,0x00,0x04,0x01,0x09,0x10,0x2b,0x14,0x40,0xff,0xf8,0x00,0x00,0x00,0x00, +0x3c,0x08,0x80,0x01,0x25,0x08,0x7f,0xff,0x24,0x09,0x00,0x01,0x3c,0x01,0x7f,0xff, +0x34,0x21,0xff,0xff,0x01,0x01,0x50,0x24,0x00,0x09,0x48,0x40,0x35,0x29,0x00,0x01, +0x01,0x2a,0x10,0x2b,0x14,0x40,0xff,0xfc,0x00,0x00,0x00,0x00,0x3c,0x0a,0x80,0x01, +0x25,0x4a,0x00,0x00,0x3c,0x01,0x7f,0xff,0x34,0x21,0xff,0xff,0x01,0x41,0x50,0x24, +0x3c,0x09,0x00,0x01,0x35,0x29,0x7f,0xff,0x4c,0x8a,0x20,0x00,0x4c,0x89,0x28,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x08,0x04,0x10, +0x00,0x00,0x00,0x00,0x40,0x88,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x3c,0x08,0xbf,0xc0,0x00,0x00,0x00,0x00,0x8d,0x09,0x00,0x00,0x00,0x00,0x00,0x00, +0x3c,0x0a,0xbf,0xc0,0x25,0x4a,0x01,0x20,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20, +0x3c,0x08,0xb0,0x03,0x8d,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x29,0x00,0x10, +0xad,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x08,0x80,0x00,0x25,0x08,0x4b,0x84, +0x01,0x00,0x00,0x08,0x00,0x00,0x00,0x00,}; + +u8 rtl8190_fwmain_array[] = { +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x40,0x04,0x68,0x00,0x40,0x05,0x70,0x00,0x40,0x06,0x40,0x00,0x0c,0x00,0x12,0x94, +0x00,0x00,0x00,0x00,0x40,0x1a,0x68,0x00,0x33,0x5b,0x00,0x3c,0x17,0x60,0x00,0x09, +0x00,0x00,0x00,0x00,0x40,0x1b,0x60,0x00,0x00,0x00,0x00,0x00,0x03,0x5b,0xd0,0x24, +0x40,0x1a,0x70,0x00,0x03,0x40,0x00,0x08,0x42,0x00,0x00,0x10,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x3c,0x02,0xff,0xff,0x34,0x42,0xff,0xff,0x8c,0x43,0x00,0x00, +0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x00,0xd0, +0xac,0x62,0x00,0x00,0x00,0x00,0x20,0x21,0x27,0x85,0x8b,0x60,0x00,0x85,0x18,0x21, +0x24,0x84,0x00,0x01,0x28,0x82,0x00,0x0a,0x14,0x40,0xff,0xfc,0xa0,0x60,0x00,0x00, +0x27,0x82,0x8b,0x6a,0x24,0x04,0x00,0x06,0x24,0x84,0xff,0xff,0xa4,0x40,0x00,0x00, +0x04,0x81,0xff,0xfd,0x24,0x42,0x00,0x02,0x24,0x02,0x00,0x03,0xa3,0x82,0x8b,0x60, +0x24,0x02,0x09,0xc4,0x24,0x03,0x01,0x00,0xa7,0x82,0x8b,0x76,0x24,0x02,0x04,0x00, +0xaf,0x83,0x8b,0x78,0xaf,0x82,0x8b,0x7c,0x24,0x03,0x00,0x0a,0x24,0x02,0x00,0x04, +0x24,0x05,0x00,0x02,0x24,0x04,0x00,0x01,0xa3,0x83,0x8b,0x62,0xa3,0x82,0x8b,0x68, +0x24,0x03,0x00,0x01,0x24,0x02,0x02,0x00,0xa3,0x84,0x8b,0x66,0xa3,0x85,0x8b,0x69, +0xa7,0x82,0x8b,0x6a,0xa7,0x83,0x8b,0x6c,0xa3,0x84,0x8b,0x61,0xa3,0x80,0x8b,0x63, +0xa3,0x80,0x8b,0x64,0xa3,0x80,0x8b,0x65,0xa3,0x85,0x8b,0x67,0x03,0xe0,0x00,0x08, +0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x24,0x42,0x01,0x84, +0x34,0x63,0x00,0x20,0xac,0x62,0x00,0x00,0x27,0x84,0x8b,0x88,0x00,0x00,0x10,0x21, +0x24,0x42,0x00,0x01,0x00,0x02,0x16,0x00,0x00,0x02,0x16,0x03,0x28,0x43,0x00,0x03, +0xac,0x80,0xff,0xfc,0xa0,0x80,0x00,0x00,0x14,0x60,0xff,0xf9,0x24,0x84,0x00,0x0c, +0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00, +0x34,0x63,0x00,0x20,0x24,0x42,0x01,0xc8,0x3c,0x08,0xb0,0x03,0xac,0x62,0x00,0x00, +0x35,0x08,0x00,0x70,0x8d,0x02,0x00,0x00,0x00,0xa0,0x48,0x21,0x00,0x04,0x26,0x00, +0x00,0x02,0x2a,0x43,0x00,0x06,0x36,0x00,0x00,0x07,0x3e,0x00,0x00,0x02,0x12,0x03, +0x29,0x23,0x00,0x03,0x00,0x04,0x56,0x03,0x00,0x06,0x36,0x03,0x00,0x07,0x3e,0x03, +0x30,0x48,0x00,0x01,0x10,0x60,0x00,0x11,0x30,0xa5,0x00,0x07,0x24,0x02,0x00,0x02, +0x00,0x49,0x10,0x23,0x00,0x45,0x10,0x07,0x30,0x42,0x00,0x01,0x10,0x40,0x00,0x66, +0x00,0x00,0x00,0x00,0x8f,0xa2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x02,0x21,0x43, +0x11,0x00,0x00,0x10,0x00,0x07,0x20,0x0b,0x15,0x20,0x00,0x06,0x24,0x02,0x00,0x01, +0x3c,0x02,0xb0,0x05,0x34,0x42,0x01,0x20,0xa4,0x44,0x00,0x00,0x03,0xe0,0x00,0x08, +0x00,0x00,0x00,0x00,0x11,0x22,0x00,0x04,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x05, +0x08,0x00,0x00,0x96,0x34,0x42,0x01,0x24,0x3c,0x02,0xb0,0x05,0x08,0x00,0x00,0x96, +0x34,0x42,0x01,0x22,0x15,0x20,0x00,0x54,0x24,0x02,0x00,0x01,0x3c,0x02,0xb0,0x03, +0x34,0x42,0x00,0x74,0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0x83,0x8b,0x84, +0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x70,0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x6b,0x00,0x08,0x11,0x60,0x00,0x18,0x00,0x09,0x28,0x40,0x00,0x00,0x40,0x21, +0x27,0x85,0x8b,0x80,0x8c,0xa3,0x00,0x00,0x8c,0xa2,0x00,0x04,0x00,0x00,0x00,0x00, +0x00,0x62,0x38,0x23,0x00,0x43,0x10,0x2a,0x10,0x40,0x00,0x3d,0x00,0x00,0x00,0x00, +0xac,0xa7,0x00,0x00,0x25,0x02,0x00,0x01,0x00,0x02,0x16,0x00,0x00,0x02,0x46,0x03, +0x29,0x03,0x00,0x03,0x14,0x60,0xff,0xf3,0x24,0xa5,0x00,0x0c,0x3c,0x03,0xb0,0x03, +0x34,0x63,0x00,0x70,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4b,0x10,0x23, +0xa0,0x62,0x00,0x00,0x00,0x09,0x28,0x40,0x00,0xa9,0x10,0x21,0x00,0x02,0x10,0x80, +0x27,0x83,0x8b,0x88,0x00,0x0a,0x20,0x0b,0x00,0x43,0x18,0x21,0x10,0xc0,0x00,0x05, +0x00,0x00,0x38,0x21,0x80,0x62,0x00,0x01,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x05, +0x00,0x00,0x00,0x00,0x80,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x03, +0x00,0xa9,0x10,0x21,0x24,0x07,0x00,0x01,0x00,0xa9,0x10,0x21,0x00,0x02,0x30,0x80, +0x27,0x82,0x8b,0x88,0xa0,0x67,0x00,0x01,0x00,0xc2,0x38,0x21,0x80,0xe3,0x00,0x01, +0x00,0x00,0x00,0x00,0x10,0x60,0x00,0x07,0x00,0x00,0x00,0x00,0x27,0x83,0x8b,0x80, +0x00,0xc3,0x18,0x21,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x10,0x21, +0xac,0x62,0x00,0x00,0x27,0x85,0x8b,0x84,0x27,0x82,0x8b,0x80,0x00,0xc5,0x28,0x21, +0x00,0xc2,0x10,0x21,0x8c,0x43,0x00,0x00,0x8c,0xa4,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x64,0x18,0x2a,0x14,0x60,0x00,0x03,0x24,0x02,0x00,0x01,0x03,0xe0,0x00,0x08, +0xa0,0xe2,0x00,0x00,0xa0,0xe0,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +0x08,0x00,0x00,0xb9,0xac,0xa0,0x00,0x00,0x11,0x22,0x00,0x08,0x00,0x00,0x00,0x00, +0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x7c,0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00, +0xaf,0x83,0x8b,0x9c,0x08,0x00,0x00,0xa9,0x3c,0x02,0xb0,0x03,0x3c,0x02,0xb0,0x03, +0x34,0x42,0x00,0x78,0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0x83,0x8b,0x90, +0x08,0x00,0x00,0xa9,0x3c,0x02,0xb0,0x03,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00, +0x34,0x63,0x00,0x20,0x24,0x42,0x04,0x18,0x3c,0x05,0xb0,0x03,0xac,0x62,0x00,0x00, +0x34,0xa5,0x00,0x70,0x8c,0xa2,0x00,0x00,0x90,0x84,0x00,0x08,0x3c,0x06,0xb0,0x03, +0x00,0x02,0x16,0x00,0x2c,0x83,0x00,0x03,0x34,0xc6,0x00,0x72,0x24,0x07,0x00,0x01, +0x10,0x60,0x00,0x11,0x00,0x02,0x2f,0xc2,0x90,0xc2,0x00,0x00,0x00,0x00,0x18,0x21, +0x00,0x02,0x16,0x00,0x10,0xa7,0x00,0x09,0x00,0x02,0x16,0x03,0x14,0x80,0x00,0x0c, +0x30,0x43,0x00,0x03,0x83,0x82,0x8b,0x88,0x00,0x00,0x00,0x00,0x00,0x02,0x10,0x80, +0x00,0x43,0x10,0x21,0x00,0x02,0x16,0x00,0x00,0x02,0x1e,0x03,0x3c,0x02,0xb0,0x03, +0x34,0x42,0x00,0x72,0xa0,0x43,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +0x30,0x45,0x00,0x05,0x10,0x87,0x00,0x04,0x30,0x43,0x00,0x06,0x93,0x82,0x8b,0xa0, +0x08,0x00,0x01,0x21,0x00,0x43,0x10,0x21,0x83,0x82,0x8b,0x94,0x00,0x00,0x00,0x00, +0x00,0x02,0x10,0x40,0x08,0x00,0x01,0x21,0x00,0x45,0x10,0x21,0x10,0x80,0x00,0x05, +0x00,0x00,0x18,0x21,0x24,0x63,0x00,0x01,0x00,0x64,0x10,0x2b,0x14,0x40,0xff,0xfd, +0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03, +0x3c,0x02,0x80,0x00,0x24,0x42,0x04,0xec,0x3c,0x04,0xb0,0x02,0x34,0x63,0x00,0x20, +0xac,0x62,0x00,0x00,0x34,0x84,0x00,0x08,0x24,0x02,0x00,0x01,0xaf,0x84,0x8b,0xb0, +0xa3,0x82,0x8b,0xc0,0xa7,0x80,0x8b,0xb4,0xa7,0x80,0x8b,0xb6,0xaf,0x80,0x8b,0xb8, +0xaf,0x80,0x8b,0xbc,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03, +0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x05,0x2c,0x3c,0x04,0xb0,0x03, +0xac,0x62,0x00,0x00,0x34,0x84,0x00,0xac,0x80,0xa2,0x00,0x15,0x8c,0x83,0x00,0x00, +0x27,0xbd,0xff,0xf0,0x00,0x43,0x10,0x21,0xac,0x82,0x00,0x00,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x10,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x00,0x34,0x42,0x00,0x20, +0x24,0x63,0x05,0x64,0x27,0xbd,0xff,0xe0,0xac,0x43,0x00,0x00,0xaf,0xb1,0x00,0x14, +0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x18,0x8f,0x90,0x8b,0xb0,0x0c,0x00,0x02,0x9a, +0x00,0x80,0x88,0x21,0x14,0x40,0x00,0x2a,0x3c,0x02,0x00,0x80,0x16,0x20,0x00,0x02, +0x34,0x42,0x02,0x01,0x24,0x02,0x02,0x01,0xae,0x02,0x00,0x00,0x97,0x84,0x8b,0xb4, +0x97,0x82,0x8b,0xb6,0x3c,0x03,0xb0,0x02,0x00,0x83,0x20,0x21,0x24,0x42,0x00,0x04, +0xa7,0x82,0x8b,0xb6,0xa4,0x82,0x00,0x00,0x8f,0x84,0x8b,0xb8,0x8f,0x82,0x8b,0xb0, +0x93,0x85,0x8b,0x62,0x24,0x84,0x00,0x01,0x24,0x42,0x00,0x04,0x24,0x03,0x8f,0xff, +0x3c,0x07,0xb0,0x06,0x3c,0x06,0xb0,0x03,0x00,0x43,0x10,0x24,0x00,0x85,0x28,0x2a, +0x34,0xe7,0x80,0x18,0xaf,0x82,0x8b,0xb0,0xaf,0x84,0x8b,0xb8,0x10,0xa0,0x00,0x08, +0x34,0xc6,0x01,0x08,0x8f,0x83,0x8b,0xbc,0x8f,0x84,0x8b,0x7c,0x8c,0xc2,0x00,0x00, +0x00,0x64,0x18,0x21,0x00,0x43,0x10,0x2b,0x14,0x40,0x00,0x09,0x00,0x00,0x00,0x00, +0x8c,0xe2,0x00,0x00,0x3c,0x03,0x0f,0x00,0x3c,0x04,0x04,0x00,0x00,0x43,0x10,0x24, +0x10,0x44,0x00,0x03,0x00,0x00,0x00,0x00,0x0c,0x00,0x04,0x98,0x00,0x00,0x00,0x00, +0x8f,0xbf,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20, +0x27,0xbd,0xff,0xd8,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x00,0x24,0x63,0x06,0x50, +0xaf,0xb0,0x00,0x10,0x34,0x42,0x00,0x20,0x8f,0x90,0x8b,0xb0,0xac,0x43,0x00,0x00, +0xaf,0xb3,0x00,0x1c,0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xbf,0x00,0x20, +0x00,0x80,0x88,0x21,0x00,0xa0,0x90,0x21,0x0c,0x00,0x02,0x9a,0x00,0xc0,0x98,0x21, +0x24,0x07,0x8f,0xff,0x14,0x40,0x00,0x19,0x26,0x03,0x00,0x04,0x24,0x02,0x0e,0x03, +0xae,0x02,0x00,0x00,0x00,0x67,0x80,0x24,0x26,0x02,0x00,0x04,0xae,0x11,0x00,0x00, +0x00,0x47,0x80,0x24,0x97,0x86,0x8b,0xb4,0x26,0x03,0x00,0x04,0xae,0x12,0x00,0x00, +0x00,0x67,0x80,0x24,0xae,0x13,0x00,0x00,0x8f,0x84,0x8b,0xb0,0x3c,0x02,0xb0,0x02, +0x97,0x85,0x8b,0xb6,0x00,0xc2,0x30,0x21,0x8f,0x82,0x8b,0xb8,0x24,0x84,0x00,0x10, +0x24,0xa5,0x00,0x10,0x00,0x87,0x20,0x24,0x24,0x42,0x00,0x01,0xa7,0x85,0x8b,0xb6, +0xaf,0x84,0x8b,0xb0,0xaf,0x82,0x8b,0xb8,0xa4,0xc5,0x00,0x00,0x8f,0xbf,0x00,0x20, +0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28, +0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x10,0x94,0x82,0x00,0x04,0x00,0x00,0x00,0x00, +0x30,0x42,0xe0,0x00,0x14,0x40,0x00,0x14,0x00,0x00,0x00,0x00,0x90,0x82,0x00,0x02, +0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xfc,0x00,0x82,0x28,0x21,0x8c,0xa4,0x00,0x00, +0x3c,0x02,0x00,0x70,0x8c,0xa6,0x00,0x08,0x00,0x82,0x10,0x21,0x2c,0x43,0x00,0x06, +0x10,0x60,0x00,0x09,0x3c,0x03,0x80,0x01,0x00,0x02,0x10,0x80,0x24,0x63,0x01,0xe8, +0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x08, +0x00,0x00,0x00,0x00,0xaf,0x86,0x80,0x14,0x8f,0xbf,0x00,0x10,0x00,0x00,0x00,0x00, +0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x8c,0xa4,0x00,0x00,0x0c,0x00,0x17,0xb3, +0x00,0x00,0x00,0x00,0x08,0x00,0x01,0xde,0x00,0x00,0x00,0x00,0x0c,0x00,0x24,0xaa, +0x00,0xc0,0x20,0x21,0x08,0x00,0x01,0xde,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03, +0x34,0x42,0x01,0x08,0x8c,0x44,0x00,0x00,0x8f,0x82,0x80,0x18,0x3c,0x03,0x00,0x0f, +0x34,0x63,0x42,0x40,0x00,0x43,0x10,0x21,0x00,0x82,0x20,0x2b,0x10,0x80,0x00,0x09, +0x24,0x03,0x00,0x05,0x8f,0x82,0x83,0x30,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01, +0xaf,0x82,0x83,0x30,0x10,0x43,0x00,0x03,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08, +0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x8c,0x63,0x01,0x08,0x24,0x02,0x00,0x01, +0xa3,0x82,0x80,0x11,0xaf,0x80,0x83,0x30,0xaf,0x83,0x80,0x18,0x08,0x00,0x01,0xfb, +0x00,0x00,0x00,0x00,0x30,0x84,0x00,0xff,0x14,0x80,0x00,0x2f,0x00,0x00,0x00,0x00, +0x8f,0x82,0x80,0x14,0xa3,0x85,0x83,0x63,0x10,0x40,0x00,0x2b,0x2c,0xa2,0x00,0x04, +0x14,0x40,0x00,0x06,0x00,0x05,0x10,0x40,0x24,0xa2,0xff,0xfc,0x2c,0x42,0x00,0x08, +0x10,0x40,0x00,0x09,0x24,0xa2,0xff,0xf0,0x00,0x05,0x10,0x40,0x27,0x84,0x83,0x6c, +0x00,0x44,0x10,0x21,0x94,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x63,0x00,0x01, +0x03,0xe0,0x00,0x08,0xa4,0x43,0x00,0x00,0x2c,0x42,0x00,0x10,0x14,0x40,0x00,0x0a, +0x00,0x05,0x10,0x40,0x24,0xa2,0xff,0xe0,0x2c,0x42,0x00,0x10,0x14,0x40,0x00,0x06, +0x00,0x05,0x10,0x40,0x24,0xa2,0xff,0xd0,0x2c,0x42,0x00,0x10,0x10,0x40,0x00,0x09, +0x24,0xa2,0xff,0xc0,0x00,0x05,0x10,0x40,0x27,0x84,0x83,0x6c,0x00,0x44,0x10,0x21, +0x94,0x43,0xff,0xf8,0x00,0x00,0x00,0x00,0x24,0x63,0x00,0x01,0x03,0xe0,0x00,0x08, +0xa4,0x43,0xff,0xf8,0x2c,0x42,0x00,0x10,0x10,0x40,0x00,0x07,0x00,0x05,0x10,0x40, +0x27,0x84,0x83,0x6c,0x00,0x44,0x10,0x21,0x94,0x43,0xff,0xf8,0x00,0x00,0x00,0x00, +0x24,0x63,0x00,0x01,0xa4,0x43,0xff,0xf8,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +0x8f,0x86,0x8b,0xb0,0x8f,0x82,0x80,0x14,0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x10, +0x10,0x40,0x00,0x2a,0x00,0xc0,0x38,0x21,0x24,0x02,0x00,0x07,0x24,0x03,0xff,0x9c, +0xa3,0x82,0x83,0x6b,0xa3,0x83,0x83,0x6a,0x27,0x8a,0x83,0x68,0x00,0x00,0x20,0x21, +0x24,0x09,0x8f,0xff,0x00,0x04,0x10,0x80,0x00,0x4a,0x28,0x21,0x8c,0xa2,0x00,0x00, +0x24,0xe3,0x00,0x04,0x24,0x88,0x00,0x01,0xac,0xe2,0x00,0x00,0x10,0x80,0x00,0x02, +0x00,0x69,0x38,0x24,0xac,0xa0,0x00,0x00,0x31,0x04,0x00,0xff,0x2c,0x82,0x00,0x27, +0x14,0x40,0xff,0xf5,0x00,0x04,0x10,0x80,0x97,0x83,0x8b,0xb6,0x97,0x85,0x8b,0xb4, +0x3c,0x02,0xb0,0x02,0x24,0x63,0x00,0x9c,0x00,0xa2,0x28,0x21,0x3c,0x04,0xb0,0x06, +0xa7,0x83,0x8b,0xb6,0x34,0x84,0x80,0x18,0xa4,0xa3,0x00,0x00,0x8c,0x85,0x00,0x00, +0x24,0x02,0x8f,0xff,0x24,0xc6,0x00,0x9c,0x3c,0x03,0x0f,0x00,0x00,0xc2,0x30,0x24, +0x00,0xa3,0x28,0x24,0x3c,0x02,0x04,0x00,0xaf,0x86,0x8b,0xb0,0x10,0xa2,0x00,0x03, +0x00,0x00,0x00,0x00,0x0c,0x00,0x04,0x98,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x10, +0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x8f,0x86,0x8b,0xb0, +0x27,0xbd,0xff,0xc8,0x24,0x02,0x00,0x08,0x24,0x03,0x00,0x20,0xaf,0xbf,0x00,0x30, +0xa3,0xa2,0x00,0x13,0xa3,0xa3,0x00,0x12,0xa7,0xa4,0x00,0x10,0x00,0xc0,0x28,0x21, +0x27,0xa9,0x00,0x10,0x00,0x00,0x38,0x21,0x24,0x08,0x8f,0xff,0x00,0x07,0x10,0x80, +0x00,0x49,0x10,0x21,0x8c,0x44,0x00,0x00,0x24,0xe3,0x00,0x01,0x30,0x67,0x00,0xff, +0x24,0xa2,0x00,0x04,0x2c,0xe3,0x00,0x08,0xac,0xa4,0x00,0x00,0x14,0x60,0xff,0xf7, +0x00,0x48,0x28,0x24,0x97,0x83,0x8b,0xb6,0x97,0x85,0x8b,0xb4,0x3c,0x02,0xb0,0x02, +0x24,0x63,0x00,0x20,0x00,0xa2,0x28,0x21,0x3c,0x04,0xb0,0x06,0xa7,0x83,0x8b,0xb6, +0x34,0x84,0x80,0x18,0xa4,0xa3,0x00,0x00,0x8c,0x85,0x00,0x00,0x24,0x02,0x8f,0xff, +0x24,0xc6,0x00,0x20,0x3c,0x03,0x0f,0x00,0x00,0xc2,0x30,0x24,0x00,0xa3,0x28,0x24, +0x3c,0x02,0x04,0x00,0xaf,0x86,0x8b,0xb0,0x10,0xa2,0x00,0x03,0x00,0x00,0x00,0x00, +0x0c,0x00,0x04,0x98,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x30,0x00,0x00,0x00,0x00, +0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x38,0x93,0x82,0x8b,0xc0,0x00,0x00,0x00,0x00, +0x10,0x40,0x00,0x11,0x24,0x06,0x00,0x01,0x8f,0x82,0x8b,0xb8,0x3c,0x05,0xb0,0x06, +0x3c,0x04,0xb0,0x03,0x34,0xa5,0x80,0x18,0x34,0x84,0x01,0x08,0x14,0x40,0x00,0x09, +0x00,0x00,0x30,0x21,0x97,0x82,0x8b,0xb4,0x8c,0x84,0x00,0x00,0x3c,0x03,0xb0,0x02, +0x00,0x43,0x10,0x21,0xaf,0x84,0x8b,0xbc,0xa7,0x80,0x8b,0xb6,0xac,0x40,0x00,0x00, +0xac,0x40,0x00,0x04,0x8c,0xa2,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0xc0,0x10,0x21, +0x8f,0x86,0x8b,0xb0,0x8f,0x82,0x8b,0xb8,0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x10, +0x00,0xc0,0x40,0x21,0x14,0x40,0x00,0x0a,0x00,0x40,0x50,0x21,0x00,0x00,0x38,0x21, +0x27,0x89,0x83,0x38,0x24,0xe2,0x00,0x01,0x00,0x07,0x18,0x80,0x30,0x47,0x00,0xff, +0x00,0x69,0x18,0x21,0x2c,0xe2,0x00,0x0a,0x14,0x40,0xff,0xfa,0xac,0x60,0x00,0x00, +0x3c,0x02,0x00,0x80,0x10,0x82,0x00,0x6f,0x00,0x00,0x00,0x00,0x97,0x82,0x83,0x3e, +0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01,0xa7,0x82,0x83,0x3e,0x90,0xa3,0x00,0x15, +0x97,0x82,0x83,0x40,0x00,0x03,0x1e,0x00,0x00,0x03,0x1e,0x03,0x00,0x43,0x10,0x21, +0xa7,0x82,0x83,0x40,0x8c,0xa4,0x00,0x20,0x3c,0x02,0x00,0x60,0x3c,0x03,0x00,0x20, +0x00,0x82,0x20,0x24,0x10,0x83,0x00,0x54,0x00,0x00,0x00,0x00,0x14,0x80,0x00,0x47, +0x00,0x00,0x00,0x00,0x97,0x82,0x83,0x44,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01, +0xa7,0x82,0x83,0x44,0x84,0xa3,0x00,0x06,0x8f,0x82,0x83,0x54,0x00,0x00,0x00,0x00, +0x00,0x43,0x10,0x21,0xaf,0x82,0x83,0x54,0x25,0x42,0x00,0x01,0x28,0x43,0x27,0x10, +0xaf,0x82,0x8b,0xb8,0x10,0x60,0x00,0x09,0x24,0x02,0x00,0x04,0x93,0x83,0x80,0x11, +0x24,0x02,0x00,0x01,0x10,0x62,0x00,0x05,0x24,0x02,0x00,0x04,0x8f,0xbf,0x00,0x10, +0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x24,0x03,0x00,0x28, +0xa3,0x83,0x83,0x3a,0xa3,0x82,0x83,0x3b,0x90,0xa2,0x00,0x18,0x93,0x83,0x83,0x63, +0x00,0x00,0x38,0x21,0x00,0x02,0x16,0x00,0x00,0x02,0x16,0x03,0xa7,0x82,0x83,0x4e, +0xa3,0x83,0x83,0x5c,0x27,0x89,0x83,0x38,0x24,0x05,0x8f,0xff,0x00,0x07,0x10,0x80, +0x00,0x49,0x10,0x21,0x8c,0x44,0x00,0x00,0x24,0xe3,0x00,0x01,0x30,0x67,0x00,0xff, +0x25,0x02,0x00,0x04,0x2c,0xe3,0x00,0x0a,0xad,0x04,0x00,0x00,0x14,0x60,0xff,0xf7, +0x00,0x45,0x40,0x24,0x97,0x83,0x8b,0xb6,0x97,0x85,0x8b,0xb4,0x3c,0x02,0xb0,0x02, +0x24,0x63,0x00,0x28,0x00,0xa2,0x28,0x21,0x3c,0x04,0xb0,0x06,0xa7,0x83,0x8b,0xb6, +0x34,0x84,0x80,0x18,0xa4,0xa3,0x00,0x00,0x8c,0x85,0x00,0x00,0x24,0x02,0x8f,0xff, +0x24,0xc6,0x00,0x28,0x3c,0x03,0x0f,0x00,0x00,0xc2,0x30,0x24,0x00,0xa3,0x28,0x24, +0x3c,0x02,0x04,0x00,0xaf,0x86,0x8b,0xb0,0x10,0xa2,0x00,0x03,0x00,0x00,0x00,0x00, +0x0c,0x00,0x04,0x98,0x00,0x00,0x00,0x00,0x0c,0x00,0x02,0x38,0x00,0x00,0x00,0x00, +0xa3,0x80,0x80,0x11,0x08,0x00,0x02,0xe7,0x00,0x00,0x00,0x00,0x97,0x82,0x83,0x46, +0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01,0xa7,0x82,0x83,0x46,0x84,0xa3,0x00,0x06, +0x8f,0x82,0x83,0x58,0x00,0x00,0x00,0x00,0x00,0x43,0x10,0x21,0xaf,0x82,0x83,0x58, +0x08,0x00,0x02,0xdf,0x25,0x42,0x00,0x01,0x97,0x82,0x83,0x42,0x00,0x00,0x00,0x00, +0x24,0x42,0x00,0x01,0xa7,0x82,0x83,0x42,0x84,0xa3,0x00,0x06,0x8f,0x82,0x83,0x50, +0x00,0x00,0x00,0x00,0x00,0x43,0x10,0x21,0xaf,0x82,0x83,0x50,0x08,0x00,0x02,0xdf, +0x25,0x42,0x00,0x01,0x97,0x82,0x83,0x3c,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01, +0xa7,0x82,0x83,0x3c,0x08,0x00,0x02,0xc7,0x00,0x00,0x00,0x00,0x27,0xbd,0xff,0xd0, +0xaf,0xbf,0x00,0x28,0x8c,0xa3,0x00,0x20,0x8f,0x8a,0x8b,0xb0,0x3c,0x02,0x00,0x10, +0x00,0x62,0x10,0x24,0x00,0xa0,0x38,0x21,0x01,0x40,0x48,0x21,0x10,0x40,0x00,0x3d, +0x00,0x80,0x28,0x21,0x8c,0xe4,0x00,0x1c,0x34,0xa5,0x12,0x06,0xaf,0xa5,0x00,0x10, +0x8c,0x82,0x00,0x08,0x00,0x03,0x1c,0x42,0x30,0x63,0x00,0x30,0x00,0x02,0x13,0x02, +0x30,0x42,0x00,0x40,0x00,0x43,0x10,0x25,0x90,0xe6,0x00,0x10,0x90,0xe4,0x00,0x13, +0x94,0xe8,0x00,0x0c,0x94,0xe3,0x00,0x1a,0x00,0x02,0x16,0x00,0x90,0xe7,0x00,0x12, +0x00,0xa2,0x28,0x25,0x24,0x02,0x12,0x34,0xa7,0xa2,0x00,0x1c,0x24,0x02,0x56,0x78, +0xaf,0xa5,0x00,0x10,0xa3,0xa6,0x00,0x18,0xa3,0xa7,0x00,0x1f,0xa7,0xa3,0x00,0x1a, +0xa3,0xa4,0x00,0x19,0xa7,0xa8,0x00,0x20,0xa7,0xa2,0x00,0x22,0x00,0x00,0x28,0x21, +0x27,0xa7,0x00,0x10,0x24,0x06,0x8f,0xff,0x00,0x05,0x10,0x80,0x00,0x47,0x10,0x21, +0x8c,0x44,0x00,0x00,0x24,0xa3,0x00,0x01,0x30,0x65,0x00,0xff,0x25,0x22,0x00,0x04, +0x2c,0xa3,0x00,0x05,0xad,0x24,0x00,0x00,0x14,0x60,0xff,0xf7,0x00,0x46,0x48,0x24, +0x97,0x83,0x8b,0xb6,0x97,0x85,0x8b,0xb4,0x3c,0x02,0xb0,0x02,0x24,0x63,0x00,0x14, +0x00,0xa2,0x28,0x21,0x3c,0x04,0xb0,0x06,0xa7,0x83,0x8b,0xb6,0x34,0x84,0x80,0x18, +0xa4,0xa3,0x00,0x00,0x8c,0x85,0x00,0x00,0x24,0x02,0x8f,0xff,0x25,0x46,0x00,0x14, +0x3c,0x03,0x0f,0x00,0x00,0xc2,0x50,0x24,0x00,0xa3,0x28,0x24,0x3c,0x02,0x04,0x00, +0xaf,0x8a,0x8b,0xb0,0x10,0xa2,0x00,0x03,0x00,0x00,0x00,0x00,0x0c,0x00,0x04,0x98, +0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x28,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x30,0x3c,0x05,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xc8, +0x00,0x04,0x22,0x00,0x34,0xa5,0x00,0x20,0x24,0x42,0x0e,0x04,0x3c,0x03,0xb0,0x00, +0xaf,0xb5,0x00,0x24,0xaf,0xb4,0x00,0x20,0xaf,0xb2,0x00,0x18,0xaf,0xb0,0x00,0x10, +0xaf,0xbf,0x00,0x30,0x00,0x83,0x80,0x21,0xaf,0xb7,0x00,0x2c,0xaf,0xb6,0x00,0x28, +0xaf,0xb3,0x00,0x1c,0xaf,0xb1,0x00,0x14,0xac,0xa2,0x00,0x00,0x8e,0x09,0x00,0x00, +0x00,0x00,0x90,0x21,0x26,0x10,0x00,0x08,0x00,0x09,0xa6,0x02,0x12,0x80,0x00,0x13, +0x00,0x00,0xa8,0x21,0x24,0x13,0x00,0x02,0x3c,0x16,0x00,0xff,0x3c,0x17,0xff,0x00, +0x8e,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x12,0x02,0x24,0x42,0x00,0x02, +0x31,0x25,0x00,0xff,0x10,0xb3,0x00,0x76,0x30,0x51,0x00,0xff,0x24,0x02,0x00,0x03, +0x10,0xa2,0x00,0x18,0x00,0x00,0x00,0x00,0x02,0x51,0x10,0x21,0x30,0x52,0xff,0xff, +0x02,0x54,0x18,0x2b,0x14,0x60,0xff,0xf2,0x02,0x11,0x80,0x21,0x12,0xa0,0x00,0x0a, +0x3c,0x02,0xb0,0x06,0x34,0x42,0x80,0x18,0x8c,0x43,0x00,0x00,0x3c,0x04,0x0f,0x00, +0x3c,0x02,0x04,0x00,0x00,0x64,0x18,0x24,0x10,0x62,0x00,0x03,0x00,0x00,0x00,0x00, +0x0c,0x00,0x04,0x98,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x30,0x7b,0xb6,0x01,0x7c, +0x7b,0xb4,0x01,0x3c,0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x38,0x8e,0x09,0x00,0x04,0x24,0x15,0x00,0x01,0x8e,0x06,0x00,0x0c, +0x00,0x09,0x11,0x42,0x00,0x09,0x18,0xc2,0x30,0x48,0x00,0x03,0x00,0x09,0x14,0x02, +0x30,0x6c,0x00,0x03,0x00,0x09,0x26,0x02,0x11,0x15,0x00,0x45,0x30,0x43,0x00,0x0f, +0x29,0x02,0x00,0x02,0x14,0x40,0x00,0x26,0x00,0x00,0x00,0x00,0x11,0x13,0x00,0x0f, +0x00,0x00,0x38,0x21,0x00,0x07,0x22,0x02,0x30,0x84,0xff,0x00,0x3c,0x03,0x00,0xff, +0x00,0x07,0x2e,0x02,0x00,0x07,0x12,0x00,0x00,0x43,0x10,0x24,0x00,0xa4,0x28,0x25, +0x00,0xa2,0x28,0x25,0x00,0x07,0x1e,0x00,0x00,0xa3,0x28,0x25,0x0c,0x00,0x01,0x94, +0x01,0x20,0x20,0x21,0x08,0x00,0x03,0xa7,0x02,0x51,0x10,0x21,0x11,0x95,0x00,0x0f, +0x00,0x00,0x00,0x00,0x11,0x88,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x80, +0x27,0x83,0x8b,0x60,0x00,0x43,0x10,0x21,0x8c,0x47,0x00,0x18,0x08,0x00,0x03,0xce, +0x00,0x07,0x22,0x02,0x00,0x04,0x10,0x40,0x27,0x83,0x8b,0x68,0x00,0x43,0x10,0x21, +0x94,0x47,0x00,0x02,0x08,0x00,0x03,0xce,0x00,0x07,0x22,0x02,0x27,0x82,0x8b,0x60, +0x00,0x82,0x10,0x21,0x90,0x47,0x00,0x00,0x08,0x00,0x03,0xce,0x00,0x07,0x22,0x02, +0x15,0x00,0xff,0xdc,0x00,0x00,0x38,0x21,0x10,0x75,0x00,0x05,0x00,0x80,0x38,0x21, +0x00,0x65,0x18,0x26,0x24,0x82,0x01,0x00,0x00,0x00,0x38,0x21,0x00,0x43,0x38,0x0a, +0x24,0x02,0x00,0x01,0x11,0x82,0x00,0x0e,0x3c,0x02,0xb0,0x03,0x24,0x02,0x00,0x02, +0x11,0x82,0x00,0x06,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x00,0xe2,0x10,0x21, +0x8c,0x47,0x00,0x00,0x08,0x00,0x03,0xce,0x00,0x07,0x22,0x02,0x3c,0x02,0xb0,0x03, +0x00,0xe2,0x10,0x21,0x94,0x43,0x00,0x00,0x08,0x00,0x03,0xcd,0x30,0x67,0xff,0xff, +0x00,0xe2,0x10,0x21,0x90,0x43,0x00,0x00,0x08,0x00,0x03,0xcd,0x30,0x67,0x00,0xff, +0x30,0x62,0x00,0x03,0x00,0x02,0x12,0x00,0x11,0x95,0x00,0x07,0x00,0x44,0x38,0x21, +0x11,0x93,0x00,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0x03,0xff,0x3c,0x02,0xb0,0x0a, +0x08,0x00,0x04,0x04,0x3c,0x02,0xb0,0x0a,0x08,0x00,0x04,0x08,0x3c,0x02,0xb0,0x0a, +0x8e,0x09,0x00,0x04,0x8e,0x02,0x00,0x08,0x8e,0x03,0x00,0x0c,0x00,0x09,0x41,0x42, +0x00,0x02,0x22,0x02,0x00,0x03,0x3a,0x02,0x30,0x84,0xff,0x00,0x30,0xe7,0xff,0x00, +0x00,0x02,0x5e,0x02,0x00,0x02,0x32,0x00,0x00,0x03,0x56,0x02,0x00,0x03,0x2a,0x00, +0x01,0x64,0x58,0x25,0x00,0xd6,0x30,0x24,0x01,0x47,0x50,0x25,0x00,0x02,0x16,0x00, +0x00,0xb6,0x28,0x24,0x00,0x03,0x1e,0x00,0x01,0x66,0x58,0x25,0x01,0x45,0x50,0x25, +0x00,0x57,0x10,0x24,0x00,0x77,0x18,0x24,0x01,0x62,0x38,0x25,0x01,0x43,0x30,0x25, +0x00,0x09,0x10,0xc2,0x00,0x09,0x1c,0x02,0x31,0x08,0x00,0x03,0x30,0x4c,0x00,0x03, +0x30,0x63,0x00,0x0f,0x00,0x09,0x26,0x02,0x00,0xe0,0x58,0x21,0x15,0x00,0x00,0x28, +0x00,0xc0,0x50,0x21,0x24,0x02,0x00,0x01,0x10,0x62,0x00,0x06,0x00,0x80,0x28,0x21, +0x24,0x02,0x00,0x03,0x14,0x62,0xff,0x69,0x02,0x51,0x10,0x21,0x24,0x85,0x01,0x00, +0x24,0x02,0x00,0x01,0x11,0x82,0x00,0x15,0x24,0x02,0x00,0x02,0x11,0x82,0x00,0x0a, +0x3c,0x03,0xb0,0x03,0x00,0xa3,0x18,0x21,0x8c,0x62,0x00,0x00,0x00,0x0a,0x20,0x27, +0x01,0x6a,0x28,0x24,0x00,0x44,0x10,0x24,0x00,0x45,0x10,0x25,0xac,0x62,0x00,0x00, +0x08,0x00,0x03,0xa7,0x02,0x51,0x10,0x21,0x00,0xa3,0x18,0x21,0x94,0x62,0x00,0x00, +0x00,0x0a,0x20,0x27,0x01,0x6a,0x28,0x24,0x00,0x44,0x10,0x24,0x00,0x45,0x10,0x25, +0xa4,0x62,0x00,0x00,0x08,0x00,0x03,0xa7,0x02,0x51,0x10,0x21,0x3c,0x03,0xb0,0x03, +0x00,0xa3,0x18,0x21,0x90,0x62,0x00,0x00,0x00,0x0a,0x20,0x27,0x01,0x6a,0x28,0x24, +0x00,0x44,0x10,0x24,0x00,0x45,0x10,0x25,0x08,0x00,0x03,0xa6,0xa0,0x62,0x00,0x00, +0x24,0x02,0x00,0x01,0x11,0x02,0x00,0x21,0x00,0x00,0x00,0x00,0x15,0x13,0xff,0x42, +0x00,0x00,0x00,0x00,0x11,0x82,0x00,0x17,0x00,0x00,0x00,0x00,0x11,0x88,0x00,0x0b, +0x00,0x00,0x00,0x00,0x27,0x83,0x8b,0x60,0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21, +0x8c,0x82,0x00,0x18,0x00,0x06,0x18,0x27,0x00,0xe6,0x28,0x24,0x00,0x43,0x10,0x24, +0x00,0x45,0x10,0x25,0x08,0x00,0x03,0xa6,0xac,0x82,0x00,0x18,0x27,0x83,0x8b,0x68, +0x00,0x04,0x20,0x40,0x00,0x83,0x20,0x21,0x94,0x82,0x00,0x02,0x00,0x06,0x18,0x27, +0x00,0xe6,0x28,0x24,0x00,0x43,0x10,0x24,0x00,0x45,0x10,0x25,0x08,0x00,0x03,0xa6, +0xa4,0x82,0x00,0x02,0x27,0x83,0x8b,0x60,0x00,0x83,0x18,0x21,0x90,0x62,0x00,0x00, +0x00,0x06,0x20,0x27,0x08,0x00,0x04,0x5c,0x00,0xe6,0x28,0x24,0x30,0x62,0x00,0x07, +0x00,0x02,0x12,0x00,0x11,0x88,0x00,0x0f,0x00,0x44,0x10,0x21,0x11,0x93,0x00,0x07, +0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x0a,0x00,0x43,0x18,0x21,0x8c,0x62,0x00,0x00, +0x00,0x06,0x20,0x27,0x08,0x00,0x04,0x49,0x00,0xe6,0x28,0x24,0x3c,0x03,0xb0,0x0a, +0x00,0x43,0x18,0x21,0x94,0x62,0x00,0x00,0x00,0x06,0x20,0x27,0x08,0x00,0x04,0x52, +0x00,0xe6,0x28,0x24,0x3c,0x03,0xb0,0x0a,0x08,0x00,0x04,0x7f,0x00,0x43,0x18,0x21, +0x97,0x85,0x8b,0xb4,0x3c,0x07,0xb0,0x02,0x3c,0x04,0xb0,0x03,0x3c,0x02,0x80,0x00, +0x00,0xa7,0x28,0x21,0x34,0x84,0x00,0x20,0x24,0x42,0x12,0x60,0x24,0x03,0xff,0x80, +0xac,0x82,0x00,0x00,0xa0,0xa3,0x00,0x07,0x97,0x82,0x8b,0xb6,0x97,0x85,0x8b,0xb4, +0x3c,0x06,0xb0,0x06,0x30,0x42,0xff,0xf8,0x24,0x42,0x00,0x10,0x00,0xa2,0x10,0x21, +0x30,0x42,0x0f,0xff,0x24,0x44,0x00,0x08,0x30,0x84,0x0f,0xff,0x00,0x05,0x28,0xc2, +0x3c,0x03,0x00,0x40,0x00,0xa3,0x28,0x25,0x00,0x87,0x20,0x21,0x34,0xc6,0x80,0x18, +0xac,0xc5,0x00,0x00,0xaf,0x84,0x8b,0xb0,0xa7,0x82,0x8b,0xb4,0xa7,0x80,0x8b,0xb6, +0xaf,0x80,0x8b,0xb8,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0xa5,0x00,0xff, +0x30,0x84,0x00,0xff,0x24,0x02,0x00,0x01,0x00,0xe0,0x48,0x21,0x30,0xc6,0x00,0xff, +0x8f,0xa7,0x00,0x10,0x10,0x82,0x00,0x07,0x00,0xa0,0x40,0x21,0x24,0x02,0x00,0x03, +0x10,0x82,0x00,0x03,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +0x24,0xa8,0x01,0x00,0x3c,0x03,0xb0,0x03,0x24,0x02,0x00,0x01,0x00,0x07,0x20,0x27, +0x01,0x27,0x28,0x24,0x10,0xc2,0x00,0x14,0x01,0x03,0x18,0x21,0x24,0x02,0x00,0x02, +0x10,0xc2,0x00,0x09,0x00,0x07,0x50,0x27,0x3c,0x03,0xb0,0x03,0x01,0x03,0x18,0x21, +0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x10,0x24,0x00,0x45,0x10,0x25, +0x08,0x00,0x04,0xe3,0xac,0x62,0x00,0x00,0x3c,0x03,0xb0,0x03,0x01,0x03,0x18,0x21, +0x94,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x10,0x24,0x00,0x45,0x10,0x25, +0x03,0xe0,0x00,0x08,0xa4,0x62,0x00,0x00,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x44,0x10,0x24,0x00,0x45,0x10,0x25,0xa0,0x62,0x00,0x00,0x03,0xe0,0x00,0x08, +0x00,0x00,0x00,0x00,0x30,0x84,0x00,0x07,0x00,0x04,0x22,0x00,0x30,0xa5,0x00,0xff, +0x00,0x85,0x28,0x21,0x3c,0x02,0xb0,0x0a,0x00,0xa2,0x40,0x21,0x30,0xc6,0x00,0xff, +0x24,0x02,0x00,0x01,0x8f,0xa4,0x00,0x10,0x10,0xc2,0x00,0x14,0x24,0x02,0x00,0x02, +0x00,0x04,0x50,0x27,0x10,0xc2,0x00,0x09,0x00,0xe4,0x48,0x24,0x3c,0x03,0xb0,0x0a, +0x00,0xa3,0x18,0x21,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x10,0x24, +0x00,0x49,0x10,0x25,0x03,0xe0,0x00,0x08,0xac,0x62,0x00,0x00,0x3c,0x03,0xb0,0x0a, +0x00,0xa3,0x18,0x21,0x94,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x10,0x24, +0x00,0x49,0x10,0x25,0x03,0xe0,0x00,0x08,0xa4,0x62,0x00,0x00,0x91,0x02,0x00,0x00, +0x00,0x04,0x18,0x27,0x00,0xe4,0x20,0x24,0x00,0x43,0x10,0x24,0x00,0x44,0x10,0x25, +0x03,0xe0,0x00,0x08,0xa1,0x02,0x00,0x00,0x30,0xa9,0x00,0xff,0x27,0x83,0x8b,0x60, +0x30,0x85,0x00,0xff,0x24,0x02,0x00,0x01,0x00,0x07,0x50,0x27,0x00,0xc7,0x40,0x24, +0x11,0x22,0x00,0x17,0x00,0xa3,0x18,0x21,0x00,0x05,0x20,0x40,0x27,0x82,0x8b,0x60, +0x00,0x05,0x28,0x80,0x27,0x83,0x8b,0x68,0x00,0x83,0x50,0x21,0x00,0xa2,0x20,0x21, +0x24,0x02,0x00,0x02,0x00,0x07,0x40,0x27,0x11,0x22,0x00,0x07,0x00,0xc7,0x28,0x24, +0x8c,0x82,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x48,0x10,0x24,0x00,0x45,0x10,0x25, +0x03,0xe0,0x00,0x08,0xac,0x82,0x00,0x18,0x95,0x42,0x00,0x02,0x00,0x00,0x00,0x00, +0x00,0x48,0x10,0x24,0x00,0x45,0x10,0x25,0x03,0xe0,0x00,0x08,0xa5,0x42,0x00,0x02, +0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x10,0x24,0x00,0x48,0x10,0x25, +0x03,0xe0,0x00,0x08,0xa0,0x62,0x00,0x00,0x00,0x04,0x32,0x02,0x30,0xc6,0xff,0x00, +0x00,0x04,0x16,0x02,0x00,0x04,0x1a,0x00,0x3c,0x05,0x00,0xff,0x00,0x65,0x18,0x24, +0x00,0x46,0x10,0x25,0x00,0x43,0x10,0x25,0x00,0x04,0x26,0x00,0x03,0xe0,0x00,0x08, +0x00,0x44,0x10,0x25,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xe8, +0x34,0x63,0x00,0x20,0x24,0x42,0x14,0xe4,0x3c,0x04,0xb0,0x03,0xaf,0xbf,0x00,0x14, +0xac,0x62,0x00,0x00,0xaf,0xb0,0x00,0x10,0x34,0x84,0x00,0x2c,0x8c,0x83,0x00,0x00, +0xa7,0x80,0xbb,0xf0,0x00,0x03,0x12,0x02,0x00,0x03,0x2d,0x02,0x30,0x42,0x0f,0xff, +0xa3,0x83,0xbb,0xf8,0xa7,0x85,0xbb,0xfc,0xa7,0x82,0xbb,0xfa,0xa7,0x80,0xbb,0xf2, +0xa7,0x80,0xbb,0xf4,0xa7,0x80,0xbb,0xf6,0x0c,0x00,0x06,0xce,0x24,0x04,0x05,0x00, +0x3c,0x05,0x08,0x00,0x00,0x45,0x28,0x25,0x24,0x04,0x05,0x00,0x0c,0x00,0x06,0xc1, +0x00,0x40,0x80,0x21,0x3c,0x02,0xf7,0xff,0x34,0x42,0xff,0xff,0x02,0x02,0x80,0x24, +0x02,0x00,0x28,0x21,0x0c,0x00,0x06,0xc1,0x24,0x04,0x05,0x00,0x3c,0x02,0xb0,0x03, +0x3c,0x03,0xb0,0x03,0x34,0x42,0x01,0x08,0x34,0x63,0x01,0x18,0x8c,0x45,0x00,0x00, +0x8c,0x64,0x00,0x00,0x3c,0x02,0x00,0x0f,0x3c,0x03,0x00,0x4c,0x30,0x84,0x02,0x00, +0x34,0x63,0x4b,0x40,0xaf,0x85,0xbc,0x00,0x10,0x80,0x00,0x06,0x34,0x42,0x42,0x40, +0xaf,0x83,0xbc,0x04,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x18,0xaf,0x82,0xbc,0x04,0x08,0x00,0x05,0x69,0x00,0x00,0x00,0x00, +0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xc8,0x34,0x63,0x00,0x20, +0x24,0x42,0x15,0xc0,0x30,0x84,0x00,0xff,0xaf,0xbf,0x00,0x30,0xaf,0xb7,0x00,0x2c, +0xaf,0xb6,0x00,0x28,0xaf,0xb5,0x00,0x24,0xaf,0xb4,0x00,0x20,0xaf,0xb3,0x00,0x1c, +0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0xac,0x62,0x00,0x00, +0x10,0x80,0x00,0x1c,0x24,0x02,0x00,0x02,0x10,0x82,0x00,0x08,0x00,0x00,0x00,0x00, +0x8f,0xbf,0x00,0x30,0x7b,0xb6,0x01,0x7c,0x7b,0xb4,0x01,0x3c,0x7b,0xb2,0x00,0xfc, +0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x38,0xa7,0x80,0xbb,0xf0, +0xa7,0x80,0xbb,0xf2,0xa7,0x80,0xbb,0xf4,0xa7,0x80,0xbb,0xf6,0x0c,0x00,0x06,0xce, +0x24,0x04,0x05,0x00,0x3c,0x05,0x08,0x00,0x00,0x45,0x28,0x25,0x24,0x04,0x05,0x00, +0x0c,0x00,0x06,0xc1,0x00,0x40,0x80,0x21,0x3c,0x05,0xf7,0xff,0x34,0xa5,0xff,0xff, +0x02,0x05,0x28,0x24,0x0c,0x00,0x06,0xc1,0x24,0x04,0x05,0x00,0x08,0x00,0x05,0x84, +0x00,0x00,0x00,0x00,0x0c,0x00,0x06,0xce,0x24,0x04,0x05,0xa0,0x24,0x04,0x05,0xa4, +0x0c,0x00,0x06,0xce,0x00,0x02,0xbc,0x02,0x24,0x04,0x05,0xa8,0x00,0x02,0xb4,0x02, +0x0c,0x00,0x06,0xce,0x30,0x55,0xff,0xff,0x00,0x40,0x80,0x21,0x97,0x84,0xbb,0xf0, +0x97,0x82,0xbb,0xf2,0x97,0x83,0xbb,0xf6,0x02,0xe4,0x20,0x23,0x02,0xa2,0x10,0x23, +0x00,0x82,0x20,0x21,0x97,0x82,0xbb,0xf4,0x32,0x14,0xff,0xff,0x02,0x83,0x18,0x23, +0x02,0xc2,0x10,0x23,0x00,0x82,0x20,0x21,0x93,0x82,0xbb,0xf8,0x00,0x83,0x20,0x21, +0x30,0x84,0xff,0xff,0x00,0x82,0x10,0x2b,0x14,0x40,0x00,0xaa,0x00,0x00,0x00,0x00, +0x97,0x82,0xbb,0xfc,0x00,0x00,0x00,0x00,0x00,0x44,0x10,0x2b,0x14,0x40,0x00,0x7f, +0x00,0x00,0x00,0x00,0x97,0x82,0xbb,0xfa,0x00,0x00,0x00,0x00,0x00,0x44,0x10,0x2b, +0x10,0x40,0x00,0x3a,0x00,0x00,0x00,0x00,0x0c,0x00,0x06,0xce,0x24,0x04,0x04,0x50, +0x30,0x51,0x00,0x7f,0x00,0x40,0x80,0x21,0x2e,0x22,0x00,0x32,0x10,0x40,0x00,0x13, +0x24,0x02,0x00,0x20,0x12,0x22,0x00,0x17,0x24,0x02,0xff,0x80,0x02,0x02,0x10,0x24, +0x26,0x31,0x00,0x01,0x00,0x51,0x80,0x25,0x02,0x00,0x28,0x21,0x0c,0x00,0x06,0xc1, +0x24,0x04,0x04,0x50,0x02,0x00,0x28,0x21,0x0c,0x00,0x06,0xc1,0x24,0x04,0x04,0x58, +0x02,0x00,0x28,0x21,0x0c,0x00,0x06,0xc1,0x24,0x04,0x04,0x60,0x02,0x00,0x28,0x21, +0x24,0x04,0x04,0x68,0x0c,0x00,0x06,0xc1,0x00,0x00,0x00,0x00,0xa7,0x97,0xbb,0xf0, +0xa7,0x95,0xbb,0xf2,0xa7,0x96,0xbb,0xf4,0xa7,0x94,0xbb,0xf6,0x08,0x00,0x05,0x84, +0x00,0x00,0x00,0x00,0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x08,0x3c,0x04,0x00,0xc0, +0x00,0x40,0x28,0x21,0x00,0x44,0x10,0x24,0x00,0x02,0x15,0x82,0x24,0x03,0x00,0x03, +0x10,0x43,0x00,0x07,0x00,0x00,0x00,0x00,0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff, +0x00,0xa2,0x10,0x24,0x00,0x44,0x28,0x25,0x0c,0x00,0x06,0xc1,0x24,0x04,0x02,0x08, +0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x2c,0x00,0x40,0x90,0x21,0x3c,0x02,0xff,0xff, +0x34,0x42,0x3f,0xff,0x02,0x42,0x90,0x24,0x02,0x40,0x28,0x21,0x0c,0x00,0x06,0xc1, +0x24,0x04,0x02,0x2c,0x08,0x00,0x05,0xcb,0x24,0x02,0xff,0x80,0x0c,0x00,0x06,0xce, +0x24,0x04,0x04,0x50,0x30,0x51,0x00,0x7f,0x24,0x02,0x00,0x20,0x16,0x22,0xff,0xdb, +0x00,0x00,0x00,0x00,0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x2c,0x34,0x52,0x40,0x00, +0x02,0x40,0x28,0x21,0x0c,0x00,0x06,0xc1,0x24,0x04,0x02,0x2c,0x0c,0x00,0x06,0xce, +0x24,0x04,0x02,0x58,0x24,0x04,0x02,0x5c,0x0c,0x00,0x06,0xce,0x00,0x02,0x9e,0x02, +0x30,0x43,0x00,0xff,0x00,0x13,0x12,0x00,0x00,0x43,0x10,0x25,0x2c,0x43,0x00,0x04, +0x14,0x60,0x00,0x1d,0x2c,0x42,0x00,0x11,0x10,0x40,0x00,0x0b,0x00,0x00,0x00,0x00, +0x3c,0x02,0xff,0xff,0x34,0x42,0x3f,0xff,0x02,0x42,0x90,0x24,0x02,0x40,0x28,0x21, +0x24,0x04,0x02,0x2c,0x0c,0x00,0x06,0xc1,0x36,0x52,0x80,0x00,0x02,0x40,0x28,0x21, +0x08,0x00,0x05,0xd9,0x24,0x04,0x02,0x2c,0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x08, +0x3c,0x04,0x00,0xc0,0x00,0x40,0x28,0x21,0x00,0x44,0x10,0x24,0x00,0x02,0x15,0x82, +0x24,0x03,0x00,0x02,0x14,0x43,0xff,0xee,0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff, +0x00,0xa2,0x10,0x24,0x00,0x44,0x28,0x25,0x0c,0x00,0x06,0xc1,0x24,0x04,0x02,0x08, +0x08,0x00,0x06,0x15,0x3c,0x02,0xff,0xff,0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x08, +0x00,0x40,0x28,0x21,0x00,0x02,0x15,0x82,0x30,0x42,0x00,0x03,0x24,0x03,0x00,0x03, +0x14,0x43,0xff,0xdf,0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff,0x00,0xa2,0x10,0x24, +0x3c,0x03,0x00,0x80,0x08,0x00,0x06,0x2a,0x00,0x43,0x28,0x25,0x0c,0x00,0x06,0xce, +0x24,0x04,0x04,0x50,0x30,0x51,0x00,0x7f,0x00,0x40,0x80,0x21,0x2e,0x22,0x00,0x32, +0x10,0x40,0xff,0x9a,0x24,0x02,0x00,0x20,0x12,0x22,0x00,0x04,0x24,0x02,0xff,0x80, +0x02,0x02,0x10,0x24,0x08,0x00,0x05,0xcd,0x26,0x31,0x00,0x02,0x0c,0x00,0x06,0xce, +0x24,0x04,0x02,0x08,0x3c,0x04,0x00,0xc0,0x00,0x40,0x28,0x21,0x00,0x44,0x10,0x24, +0x00,0x02,0x15,0x82,0x24,0x03,0x00,0x03,0x10,0x43,0x00,0x07,0x00,0x00,0x00,0x00, +0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff,0x00,0xa2,0x10,0x24,0x00,0x44,0x28,0x25, +0x0c,0x00,0x06,0xc1,0x24,0x04,0x02,0x08,0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x2c, +0x00,0x40,0x90,0x21,0x3c,0x02,0xff,0xff,0x34,0x42,0x3f,0xff,0x02,0x42,0x90,0x24, +0x02,0x40,0x28,0x21,0x0c,0x00,0x06,0xc1,0x24,0x04,0x02,0x2c,0x08,0x00,0x06,0x44, +0x24,0x02,0xff,0x80,0x0c,0x00,0x06,0xce,0x24,0x04,0x04,0x50,0x00,0x40,0x80,0x21, +0x30,0x51,0x00,0x7f,0x24,0x02,0x00,0x20,0x12,0x22,0x00,0x1d,0x2e,0x22,0x00,0x21, +0x14,0x40,0xff,0x72,0x24,0x02,0xff,0x80,0x02,0x02,0x10,0x24,0x26,0x31,0xff,0xff, +0x00,0x51,0x80,0x25,0x24,0x04,0x04,0x50,0x0c,0x00,0x06,0xc1,0x02,0x00,0x28,0x21, +0x24,0x04,0x04,0x58,0x0c,0x00,0x06,0xc1,0x02,0x00,0x28,0x21,0x24,0x04,0x04,0x60, +0x0c,0x00,0x06,0xc1,0x02,0x00,0x28,0x21,0x02,0x00,0x28,0x21,0x0c,0x00,0x06,0xc1, +0x24,0x04,0x04,0x68,0x24,0x02,0x00,0x20,0x16,0x22,0xff,0x60,0x00,0x00,0x00,0x00, +0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x2c,0x00,0x40,0x90,0x21,0x3c,0x02,0xff,0xff, +0x34,0x42,0x3f,0xff,0x02,0x42,0x10,0x24,0x08,0x00,0x06,0x1b,0x34,0x52,0x80,0x00, +0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x2c,0x34,0x52,0x40,0x00,0x02,0x40,0x28,0x21, +0x0c,0x00,0x06,0xc1,0x24,0x04,0x02,0x2c,0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x58, +0x24,0x04,0x02,0x5c,0x0c,0x00,0x06,0xce,0x00,0x02,0x9e,0x02,0x30,0x43,0x00,0xff, +0x00,0x13,0x12,0x00,0x00,0x43,0x10,0x25,0x2c,0x43,0x00,0x04,0x14,0x60,0x00,0x20, +0x2c,0x42,0x00,0x11,0x10,0x40,0x00,0x0d,0x00,0x00,0x00,0x00,0x3c,0x02,0xff,0xff, +0x34,0x42,0x3f,0xff,0x02,0x42,0x90,0x24,0x02,0x40,0x28,0x21,0x24,0x04,0x02,0x2c, +0x0c,0x00,0x06,0xc1,0x36,0x52,0x80,0x00,0x02,0x40,0x28,0x21,0x0c,0x00,0x06,0xc1, +0x24,0x04,0x02,0x2c,0x08,0x00,0x06,0x68,0x2e,0x22,0x00,0x21,0x0c,0x00,0x06,0xce, +0x24,0x04,0x02,0x08,0x3c,0x04,0x00,0xc0,0x00,0x40,0x28,0x21,0x00,0x44,0x10,0x24, +0x00,0x02,0x15,0x82,0x24,0x03,0x00,0x02,0x14,0x43,0xff,0xec,0x00,0x00,0x00,0x00, +0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff,0x00,0xa2,0x10,0x24,0x00,0x44,0x28,0x25, +0x0c,0x00,0x06,0xc1,0x24,0x04,0x02,0x08,0x08,0x00,0x06,0x98,0x3c,0x02,0xff,0xff, +0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x08,0x00,0x40,0x28,0x21,0x00,0x02,0x15,0x82, +0x30,0x42,0x00,0x03,0x24,0x03,0x00,0x03,0x14,0x43,0xff,0xdc,0x3c,0x03,0x00,0x80, +0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff,0x00,0xa2,0x10,0x24,0x08,0x00,0x06,0xb0, +0x00,0x43,0x28,0x25,0x30,0x83,0x00,0x03,0x00,0x04,0x20,0x40,0x00,0x83,0x20,0x23, +0x3c,0x02,0xb0,0x0a,0x00,0x82,0x20,0x21,0xac,0x85,0x00,0x00,0x00,0x00,0x18,0x21, +0x24,0x63,0x00,0x01,0x2c,0x62,0x00,0x0a,0x14,0x40,0xff,0xfe,0x24,0x63,0x00,0x01, +0x03,0xe0,0x00,0x08,0x24,0x63,0xff,0xff,0x30,0x86,0x00,0x03,0x00,0x04,0x28,0x40, +0x3c,0x03,0xb0,0x0a,0x00,0xa6,0x10,0x23,0x00,0x43,0x10,0x21,0x24,0x04,0xff,0xff, +0xac,0x44,0x10,0x00,0x00,0x00,0x18,0x21,0x24,0x63,0x00,0x01,0x2c,0x62,0x00,0x0a, +0x14,0x40,0xff,0xfe,0x24,0x63,0x00,0x01,0x24,0x63,0xff,0xff,0x00,0xa6,0x18,0x23, +0x3c,0x02,0xb0,0x0a,0x00,0x62,0x18,0x21,0x8c,0x62,0x00,0x00,0x03,0xe0,0x00,0x08, +0x00,0x00,0x00,0x00,0x3c,0x05,0xb0,0x03,0x3c,0x02,0x80,0x00,0x24,0x42,0x1b,0x84, +0x24,0x03,0x00,0x01,0x34,0xa5,0x00,0x20,0x3c,0x06,0xb0,0x03,0xac,0xa2,0x00,0x00, +0x34,0xc6,0x01,0x04,0xa0,0x83,0x00,0x48,0xa0,0x80,0x00,0x04,0xa0,0x80,0x00,0x05, +0xa0,0x80,0x00,0x06,0xa0,0x80,0x00,0x07,0xa0,0x80,0x00,0x08,0xa0,0x80,0x00,0x09, +0xa0,0x80,0x00,0x0a,0xa0,0x80,0x00,0x11,0xa0,0x80,0x00,0x13,0xa0,0x80,0x00,0x49, +0x94,0xc2,0x00,0x00,0xac,0x80,0x00,0x00,0xa0,0x80,0x00,0x4e,0x00,0x02,0x14,0x00, +0x00,0x02,0x14,0x03,0x30,0x43,0x00,0xff,0x30,0x42,0xff,0x00,0xa4,0x82,0x00,0x44, +0xa4,0x83,0x00,0x46,0xac,0x80,0x00,0x24,0xac,0x80,0x00,0x28,0xac,0x80,0x00,0x2c, +0xac,0x80,0x00,0x30,0xac,0x80,0x00,0x34,0xac,0x80,0x00,0x38,0xac,0x80,0x00,0x3c, +0x03,0xe0,0x00,0x08,0xac,0x80,0x00,0x40,0x84,0x83,0x00,0x0c,0x3c,0x07,0xb0,0x03, +0x34,0xe7,0x00,0x20,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80, +0x27,0x83,0x8f,0xf4,0x00,0x43,0x10,0x21,0x8c,0x48,0x00,0x18,0x3c,0x02,0x80,0x00, +0x24,0x42,0x1c,0x18,0xac,0xe2,0x00,0x00,0x8d,0x03,0x00,0x08,0x80,0x82,0x00,0x13, +0x00,0x05,0x2c,0x00,0x00,0x03,0x1e,0x02,0x00,0x02,0x12,0x00,0x30,0x63,0x00,0x7e, +0x00,0x62,0x18,0x21,0x00,0x65,0x18,0x21,0x3c,0x02,0xc0,0x00,0x3c,0x05,0xb0,0x05, +0x34,0x42,0x04,0x00,0x24,0x63,0x00,0x01,0x3c,0x07,0xb0,0x05,0x3c,0x08,0xb0,0x05, +0x34,0xa5,0x04,0x20,0xac,0xa3,0x00,0x00,0x00,0xc2,0x30,0x21,0x34,0xe7,0x04,0x24, +0x35,0x08,0x02,0x28,0x24,0x02,0x00,0x01,0x24,0x03,0x00,0x20,0xac,0xe6,0x00,0x00, +0xac,0x82,0x00,0x3c,0x03,0xe0,0x00,0x08,0xa1,0x03,0x00,0x00,0x27,0xbd,0xff,0xa8, +0x00,0x07,0x60,0x80,0x27,0x82,0xb3,0xf0,0xaf,0xbe,0x00,0x50,0xaf,0xb7,0x00,0x4c, +0xaf,0xb5,0x00,0x44,0xaf,0xb4,0x00,0x40,0xaf,0xbf,0x00,0x54,0xaf,0xb6,0x00,0x48, +0xaf,0xb3,0x00,0x3c,0xaf,0xb2,0x00,0x38,0xaf,0xb1,0x00,0x34,0xaf,0xb0,0x00,0x30, +0x01,0x82,0x10,0x21,0x8c,0x43,0x00,0x00,0x00,0xe0,0x70,0x21,0x3c,0x02,0x80,0x00, +0x94,0x73,0x00,0x14,0x3c,0x07,0xb0,0x03,0x34,0xe7,0x00,0x20,0x24,0x42,0x1c,0xac, +0x3c,0x03,0xb0,0x05,0xac,0xe2,0x00,0x00,0x34,0x63,0x01,0x28,0x90,0x67,0x00,0x00, +0x00,0x13,0xa8,0xc0,0x02,0xb3,0x18,0x21,0x27,0x82,0x8f,0xf4,0x00,0x03,0x18,0x80, +0x00,0x62,0x18,0x21,0x00,0x05,0x2c,0x00,0x00,0x07,0x3e,0x00,0x28,0xc2,0x00,0x03, +0x00,0xc0,0xa0,0x21,0x00,0x80,0x78,0x21,0x00,0x05,0xbc,0x03,0x8c,0x68,0x00,0x18, +0x02,0xa0,0x58,0x21,0x10,0x40,0x01,0x81,0x00,0x07,0xf6,0x03,0x00,0xde,0x10,0x07, +0x30,0x5e,0x00,0x01,0x01,0x73,0x10,0x21,0x27,0x83,0x8f,0xf8,0x00,0x02,0x10,0x80, +0x00,0x43,0x10,0x21,0x80,0x4d,0x00,0x06,0x8d,0x03,0x00,0x00,0x8d,0x02,0x00,0x04, +0x8d,0x0a,0x00,0x08,0x8d,0x03,0x00,0x0c,0xaf,0xa2,0x00,0x20,0x11,0xa0,0x01,0x71, +0xaf,0xa3,0x00,0x18,0x27,0x82,0xb3,0xf0,0x01,0x82,0x10,0x21,0x8c,0x44,0x00,0x00, +0x00,0x00,0x00,0x00,0x90,0x83,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x04, +0x14,0x60,0x00,0x12,0x00,0x00,0xb0,0x21,0x3c,0x02,0xb0,0x09,0x34,0x42,0x01,0x46, +0x90,0x43,0x00,0x00,0x2a,0x84,0x00,0x04,0x10,0x80,0x01,0x56,0x30,0x65,0x00,0x01, +0x91,0xe2,0x00,0x09,0x00,0x00,0x00,0x00,0x12,0x82,0x00,0x02,0x00,0x00,0x00,0x00, +0x00,0x00,0x28,0x21,0x14,0xa0,0x00,0x03,0x00,0x00,0x38,0x21,0x13,0xc0,0x00,0x03, +0x38,0xf6,0x00,0x01,0x24,0x07,0x00,0x01,0x38,0xf6,0x00,0x01,0x01,0x73,0x10,0x21, +0x00,0x02,0x30,0x80,0x27,0x83,0x90,0x00,0x00,0xc3,0x48,0x21,0x91,0x25,0x00,0x00, +0x8f,0xa4,0x00,0x20,0x2c,0xa3,0x00,0x04,0x00,0x04,0x11,0xc3,0x30,0x42,0x00,0x01, +0x00,0x03,0xb0,0x0b,0x12,0xc0,0x00,0xd8,0xaf,0xa2,0x00,0x24,0x93,0x90,0xbb,0xda, +0x00,0x0a,0x16,0x42,0x30,0x52,0x00,0x3f,0x2e,0x06,0x00,0x0c,0x10,0xc0,0x00,0xc0, +0x00,0xa0,0x20,0x21,0x2c,0xa2,0x00,0x10,0x14,0x40,0x00,0x04,0x00,0x90,0x10,0x2b, +0x30,0xa2,0x00,0x07,0x24,0x44,0x00,0x04,0x00,0x90,0x10,0x2b,0x10,0x40,0x00,0x0b, +0x01,0x73,0x10,0x21,0x27,0x85,0xbb,0x0c,0x00,0x10,0x10,0x40,0x00,0x50,0x10,0x21, +0x00,0x45,0x10,0x21,0x90,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x18,0x2b, +0x14,0x60,0xff,0xfa,0x00,0x10,0x10,0x40,0x01,0x73,0x10,0x21,0x00,0x02,0x10,0x80, +0x27,0x83,0x8f,0xf8,0x00,0x43,0x10,0x21,0x31,0xa4,0x00,0x01,0x10,0x80,0x00,0xa5, +0xa0,0x50,0x00,0x07,0x3c,0x04,0xb0,0x05,0x34,0x84,0x00,0x08,0x24,0x02,0x00,0x01, +0x3c,0x03,0x80,0x00,0xa1,0xe2,0x00,0x4e,0xac,0x83,0x00,0x00,0x8c,0x85,0x00,0x00, +0x3c,0x02,0x00,0xf0,0x3c,0x03,0x40,0xf0,0x34,0x42,0xf0,0x00,0x34,0x63,0xf0,0x00, +0x24,0x17,0x00,0x0e,0x24,0x13,0x01,0x06,0xac,0x82,0x00,0x00,0xac,0x83,0x00,0x00, +0x27,0x82,0xb3,0xf0,0x01,0x82,0x10,0x21,0x8c,0x43,0x00,0x00,0x24,0x05,0x00,0x01, +0xaf,0xa5,0x00,0x1c,0x90,0x62,0x00,0x16,0x00,0x13,0xa8,0xc0,0x32,0x51,0x00,0x02, +0x34,0x42,0x00,0x04,0xa0,0x62,0x00,0x16,0x8f,0xa3,0x00,0x20,0x8f,0xa4,0x00,0x18, +0x00,0x03,0x13,0x43,0x00,0x04,0x1a,0x02,0x30,0x47,0x00,0x01,0x12,0x20,0x00,0x04, +0x30,0x64,0x07,0xff,0x2e,0x03,0x00,0x04,0x32,0x42,0x00,0x33,0x00,0x43,0x90,0x0b, +0x8f,0xa5,0x00,0x24,0x8f,0xa6,0x00,0x1c,0x00,0x12,0x10,0x40,0x00,0x05,0x19,0xc0, +0x00,0x47,0x10,0x21,0x00,0x06,0x2a,0x80,0x00,0x43,0x10,0x21,0x00,0x10,0x32,0x00, +0x00,0x04,0x24,0x80,0x02,0x65,0x28,0x21,0x00,0xa4,0x28,0x21,0x00,0x46,0x10,0x21, +0x00,0x17,0x1c,0x00,0x3c,0x04,0xc0,0x00,0x00,0x43,0x30,0x21,0x16,0x80,0x00,0x29, +0x00,0xa4,0x28,0x21,0x3c,0x02,0xb0,0x05,0x34,0x42,0x04,0x00,0x3c,0x03,0xb0,0x05, +0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00,0x34,0x63,0x04,0x04,0x34,0x84,0x02,0x28, +0x24,0x02,0x00,0x01,0xac,0x65,0x00,0x00,0xa0,0x82,0x00,0x00,0x3c,0x02,0xb0,0x09, +0x34,0x42,0x01,0x46,0x90,0x44,0x00,0x00,0x91,0xe3,0x00,0x09,0x30,0x86,0x00,0x01, +0x02,0x83,0x18,0x26,0x00,0x03,0x30,0x0b,0x14,0xc0,0x00,0x03,0x00,0x00,0x28,0x21, +0x13,0xc0,0x00,0x03,0x02,0xb3,0x10,0x21,0x24,0x05,0x00,0x01,0x02,0xb3,0x10,0x21, +0x27,0x83,0x8f,0xf8,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x84,0x48,0x00,0x04, +0x00,0xa0,0x30,0x21,0x00,0xe0,0x20,0x21,0x02,0x80,0x28,0x21,0x02,0xc0,0x38,0x21, +0x0c,0x00,0x00,0x72,0xaf,0xa8,0x00,0x10,0x7b,0xbe,0x02,0xbc,0x7b,0xb6,0x02,0x7c, +0x7b,0xb4,0x02,0x3c,0x7b,0xb2,0x01,0xfc,0x7b,0xb0,0x01,0xbc,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x58,0x24,0x02,0x00,0x01,0x12,0x82,0x00,0x3d,0x3c,0x02,0xb0,0x05, +0x24,0x02,0x00,0x02,0x12,0x82,0x00,0x31,0x3c,0x02,0xb0,0x05,0x24,0x02,0x00,0x03, +0x12,0x82,0x00,0x25,0x3c,0x02,0xb0,0x05,0x24,0x02,0x00,0x10,0x12,0x82,0x00,0x19, +0x3c,0x02,0xb0,0x05,0x24,0x02,0x00,0x11,0x12,0x82,0x00,0x0d,0x3c,0x02,0xb0,0x05, +0x24,0x02,0x00,0x12,0x16,0x82,0xff,0xd1,0x3c,0x02,0xb0,0x05,0x3c,0x03,0xb0,0x05, +0x34,0x42,0x04,0x20,0x3c,0x04,0xb0,0x05,0x34,0x63,0x04,0x24,0xac,0x46,0x00,0x00, +0x34,0x84,0x02,0x28,0xac,0x65,0x00,0x00,0x08,0x00,0x07,0xe2,0x24,0x02,0x00,0x20, +0x34,0x42,0x04,0x40,0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00, +0x34,0x63,0x04,0x44,0x34,0x84,0x02,0x28,0x24,0x02,0x00,0x40,0x08,0x00,0x07,0xe2, +0xac,0x65,0x00,0x00,0x34,0x42,0x04,0x28,0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05, +0xac,0x46,0x00,0x00,0x34,0x63,0x04,0x2c,0x34,0x84,0x02,0x28,0x24,0x02,0xff,0x80, +0x08,0x00,0x07,0xe2,0xac,0x65,0x00,0x00,0x34,0x42,0x04,0x18,0x3c,0x03,0xb0,0x05, +0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00,0x34,0x63,0x04,0x1c,0x34,0x84,0x02,0x28, +0x24,0x02,0x00,0x08,0x08,0x00,0x07,0xe2,0xac,0x65,0x00,0x00,0x34,0x42,0x04,0x10, +0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00,0x34,0x63,0x04,0x14, +0x34,0x84,0x02,0x28,0x24,0x02,0x00,0x04,0x08,0x00,0x07,0xe2,0xac,0x65,0x00,0x00, +0x34,0x42,0x04,0x08,0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00, +0x34,0x63,0x04,0x0c,0x34,0x84,0x02,0x28,0x24,0x02,0x00,0x02,0x08,0x00,0x07,0xe2, +0xac,0x65,0x00,0x00,0x24,0x17,0x00,0x14,0x08,0x00,0x07,0xb4,0x24,0x13,0x01,0x02, +0x30,0xa2,0x00,0x07,0x24,0x44,0x00,0x0c,0x00,0x90,0x18,0x2b,0x10,0x60,0x00,0x0c, +0x26,0x02,0x00,0x04,0x27,0x85,0xbb,0x0c,0x00,0x10,0x10,0x40,0x00,0x50,0x10,0x21, +0x00,0x45,0x10,0x21,0x90,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x18,0x2b, +0x14,0x60,0xff,0xfa,0x00,0x10,0x10,0x40,0x2e,0x06,0x00,0x0c,0x26,0x02,0x00,0x04, +0x08,0x00,0x07,0x9e,0x00,0x46,0x80,0x0a,0x27,0x82,0xb3,0xf0,0x01,0x82,0x20,0x21, +0x8c,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0xe2,0x00,0x19,0x00,0x00,0x00,0x00, +0x14,0x40,0x00,0x07,0x00,0x00,0x00,0x00,0x27,0x82,0x90,0x10,0x00,0xc2,0x10,0x21, +0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x60,0x00,0x14,0x00,0x00,0x00,0x00, +0x90,0xe3,0x00,0x16,0x27,0x82,0x8f,0xf8,0x00,0xc2,0x10,0x21,0x34,0x63,0x00,0x20, +0x90,0x50,0x00,0x07,0xa0,0xe3,0x00,0x16,0x8c,0x84,0x00,0x00,0x00,0x0a,0x1e,0x42, +0x24,0x06,0x00,0x01,0x90,0x82,0x00,0x16,0x30,0x71,0x00,0x02,0x30,0x72,0x00,0x3f, +0x30,0x42,0x00,0xfb,0x24,0x17,0x00,0x18,0x24,0x13,0x01,0x03,0x24,0x15,0x08,0x18, +0xaf,0xa6,0x00,0x1c,0x08,0x00,0x07,0xbe,0xa0,0x82,0x00,0x16,0x8d,0x02,0x00,0x04, +0x00,0x0a,0x1c,0x42,0x30,0x42,0x00,0x10,0x14,0x40,0x00,0x15,0x30,0x72,0x00,0x3f, +0x81,0x22,0x00,0x05,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x11,0x30,0x72,0x00,0x3e, +0x27,0x83,0x90,0x08,0x00,0xc3,0x18,0x21,0x80,0x64,0x00,0x00,0x27,0x83,0xb5,0x68, +0x00,0x04,0x11,0x00,0x00,0x44,0x10,0x23,0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x23, +0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x90,0x44,0x00,0x05,0x90,0x43,0x00,0x04, +0x00,0x00,0x00,0x00,0x00,0x64,0x18,0x24,0x30,0x63,0x00,0x01,0x02,0x43,0x90,0x25, +0x27,0x85,0xb3,0xf0,0x01,0x85,0x28,0x21,0x8c,0xa6,0x00,0x00,0x01,0x73,0x10,0x21, +0x27,0x83,0x90,0x00,0x90,0xc4,0x00,0x16,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21, +0x30,0x84,0x00,0xdf,0x90,0x50,0x00,0x00,0xa0,0xc4,0x00,0x16,0x80,0xc6,0x00,0x12, +0x8c,0xa3,0x00,0x00,0x2d,0xc4,0x00,0x02,0xaf,0xa6,0x00,0x1c,0x90,0x62,0x00,0x16, +0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xfb,0x14,0x80,0x00,0x06,0xa0,0x62,0x00,0x16, +0x24,0x02,0x00,0x06,0x11,0xc2,0x00,0x03,0x24,0x02,0x00,0x04,0x15,0xc2,0xff,0x0e, +0x32,0x51,0x00,0x02,0x32,0x51,0x00,0x02,0x2e,0x02,0x00,0x0c,0x14,0x40,0x00,0x0f, +0x00,0x11,0x18,0x2b,0x32,0x02,0x00,0x0f,0x34,0x42,0x00,0x10,0x00,0x03,0x19,0x00, +0x00,0x43,0x18,0x21,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xb8,0xa0,0x43,0x00,0x00, +0x00,0x00,0x20,0x21,0x02,0x00,0x28,0x21,0x0c,0x00,0x02,0x05,0xaf,0xaf,0x00,0x28, +0x8f,0xaf,0x00,0x28,0x08,0x00,0x07,0xbe,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0xb9, +0x32,0x03,0x00,0xff,0x3c,0x03,0xb0,0x05,0x34,0x63,0x02,0x42,0x90,0x62,0x00,0x00, +0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x0f,0x14,0x40,0xfe,0xaa,0x00,0x00,0x00,0x00, +0x91,0xe2,0x00,0x09,0x00,0x00,0x00,0x00,0x02,0x82,0x10,0x26,0x08,0x00,0x07,0x75, +0x00,0x02,0x28,0x0b,0x08,0x00,0x07,0x7b,0x00,0x00,0xb0,0x21,0x24,0x02,0x00,0x10, +0x10,0xc2,0x00,0x08,0x24,0x02,0x00,0x11,0x10,0xc2,0xfe,0x7d,0x00,0x07,0x17,0x83, +0x24,0x02,0x00,0x12,0x14,0xc2,0xfe,0x7b,0x00,0x07,0x17,0x43,0x08,0x00,0x07,0x55, +0x30,0x5e,0x00,0x01,0x08,0x00,0x07,0x55,0x00,0x07,0xf7,0xc2,0x00,0x04,0x10,0x40, +0x27,0x83,0x80,0x1c,0x00,0x43,0x10,0x21,0x00,0x80,0x40,0x21,0x94,0x44,0x00,0x00, +0x2d,0x07,0x00,0x04,0x24,0xc2,0x00,0x03,0x00,0x47,0x30,0x0a,0x00,0x86,0x00,0x18, +0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x23,0x7c, +0xac,0x62,0x00,0x00,0x2d,0x06,0x00,0x10,0x00,0x00,0x20,0x12,0x00,0x04,0x22,0x42, +0x24,0x84,0x00,0x01,0x24,0x83,0x00,0xc0,0x10,0xe0,0x00,0x0b,0x24,0x82,0x00,0x60, +0x00,0x40,0x20,0x21,0x00,0x65,0x20,0x0a,0x3c,0x03,0xb0,0x03,0x34,0x63,0x01,0x00, +0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x00,0x44,0x20,0x04, +0x03,0xe0,0x00,0x08,0x00,0x80,0x10,0x21,0x24,0x85,0x00,0x28,0x24,0x83,0x00,0x24, +0x31,0x02,0x00,0x08,0x14,0xc0,0xff,0xf4,0x24,0x84,0x00,0x14,0x00,0x60,0x20,0x21, +0x08,0x00,0x08,0xf6,0x00,0xa2,0x20,0x0b,0x27,0xbd,0xff,0xe0,0x3c,0x03,0xb0,0x03, +0x3c,0x02,0x80,0x00,0xaf,0xb0,0x00,0x10,0x24,0x42,0x24,0x18,0x00,0x80,0x80,0x21, +0x34,0x63,0x00,0x20,0x3c,0x04,0xb0,0x03,0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14, +0xaf,0xbf,0x00,0x1c,0x83,0xb1,0x00,0x33,0x83,0xa8,0x00,0x37,0x34,0x84,0x01,0x10, +0xac,0x62,0x00,0x00,0x2e,0x02,0x00,0x10,0x00,0xe0,0x90,0x21,0x8c,0x87,0x00,0x00, +0x14,0x40,0x00,0x0c,0x2e,0x02,0x00,0x0c,0x3c,0x02,0x00,0x0f,0x34,0x42,0xf0,0x00, +0x00,0xe2,0x10,0x24,0x14,0x40,0x00,0x37,0x32,0x02,0x00,0x08,0x32,0x02,0x00,0x07, +0x27,0x83,0x80,0xcc,0x00,0x43,0x10,0x21,0x90,0x50,0x00,0x00,0x00,0x00,0x00,0x00, +0x2e,0x02,0x00,0x0c,0x14,0x40,0x00,0x03,0x02,0x00,0x20,0x21,0x32,0x02,0x00,0x0f, +0x24,0x44,0x00,0x0c,0x00,0x87,0x10,0x06,0x30,0x42,0x00,0x01,0x14,0x40,0x00,0x07, +0x2c,0x82,0x00,0x0c,0x00,0x04,0x10,0x80,0x27,0x83,0xb4,0x40,0x00,0x43,0x10,0x21, +0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0x82,0x00,0x0c,0x14,0x40,0x00,0x05, +0x00,0x05,0x10,0x40,0x00,0x46,0x10,0x21,0x00,0x02,0x11,0x00,0x00,0x82,0x10,0x21, +0x24,0x44,0x00,0x04,0x15,0x00,0x00,0x02,0x24,0x06,0x00,0x20,0x24,0x06,0x00,0x0e, +0x0c,0x00,0x08,0xdf,0x00,0x00,0x00,0x00,0x00,0x40,0x30,0x21,0x3c,0x02,0xb0,0x03, +0x34,0x42,0x01,0x00,0x90,0x43,0x00,0x00,0x2e,0x04,0x00,0x04,0x24,0x02,0x00,0x10, +0x24,0x05,0x00,0x0a,0x00,0x44,0x28,0x0a,0x30,0x63,0x00,0x01,0x14,0x60,0x00,0x02, +0x00,0x05,0x10,0x40,0x00,0xa0,0x10,0x21,0x30,0x45,0x00,0xff,0x00,0xc5,0x10,0x21, +0x24,0x46,0x00,0x46,0x02,0x26,0x18,0x04,0xa6,0x43,0x00,0x00,0x8f,0xbf,0x00,0x1c, +0x8f,0xb2,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x00,0xc0,0x10,0x21,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x20,0x10,0x40,0xff,0xcf,0x2e,0x02,0x00,0x0c,0x32,0x02,0x00,0x07, +0x27,0x83,0x80,0xc4,0x00,0x43,0x10,0x21,0x90,0x44,0x00,0x00,0x08,0x00,0x09,0x24, +0x02,0x04,0x80,0x23,0x27,0xbd,0xff,0xb8,0x00,0x05,0x38,0x80,0x27,0x82,0xb3,0xf0, +0xaf,0xbe,0x00,0x40,0xaf,0xb6,0x00,0x38,0xaf,0xb3,0x00,0x2c,0xaf,0xbf,0x00,0x44, +0xaf,0xb7,0x00,0x3c,0xaf,0xb5,0x00,0x34,0xaf,0xb4,0x00,0x30,0xaf,0xb2,0x00,0x28, +0xaf,0xb1,0x00,0x24,0xaf,0xb0,0x00,0x20,0x00,0xe2,0x38,0x21,0x8c,0xe6,0x00,0x00, +0xaf,0xa5,0x00,0x4c,0x3c,0x02,0x80,0x00,0x3c,0x05,0xb0,0x03,0x34,0xa5,0x00,0x20, +0x24,0x42,0x25,0x74,0x24,0x03,0x00,0x01,0xac,0xa2,0x00,0x00,0xa0,0xc3,0x00,0x12, +0x8c,0xe5,0x00,0x00,0x94,0xc3,0x00,0x06,0x90,0xa2,0x00,0x16,0xa4,0xc3,0x00,0x14, +0x27,0x83,0x8f,0xf0,0x34,0x42,0x00,0x08,0xa0,0xa2,0x00,0x16,0x8c,0xe8,0x00,0x00, +0xaf,0xa4,0x00,0x48,0x27,0x82,0x8f,0xf4,0x95,0x11,0x00,0x14,0x00,0x00,0x00,0x00, +0x00,0x11,0x98,0xc0,0x02,0x71,0x20,0x21,0x00,0x04,0x20,0x80,0x00,0x82,0x10,0x21, +0x8c,0x52,0x00,0x18,0x00,0x83,0x18,0x21,0x84,0x75,0x00,0x06,0x8e,0x45,0x00,0x08, +0x8e,0x46,0x00,0x04,0x8e,0x47,0x00,0x04,0x00,0x05,0x1c,0x82,0x00,0x06,0x31,0x42, +0x27,0x82,0x90,0x00,0x30,0x63,0x00,0x01,0x30,0xc6,0x00,0x01,0x00,0x82,0x20,0x21, +0xa5,0x15,0x00,0x1a,0x00,0x05,0x14,0x42,0xaf,0xa3,0x00,0x18,0xaf,0xa6,0x00,0x1c, +0x30,0xe7,0x00,0x10,0x30,0x56,0x00,0x01,0x80,0x97,0x00,0x06,0x14,0xe0,0x00,0x47, +0x00,0x05,0xf7,0xc2,0x80,0x82,0x00,0x05,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x44, +0x02,0x71,0x10,0x21,0x93,0x90,0xbb,0xd9,0x00,0x00,0x00,0x00,0x2e,0x02,0x00,0x0c, +0x14,0x40,0x00,0x06,0x02,0x00,0x20,0x21,0x00,0x16,0x10,0x40,0x00,0x43,0x10,0x21, +0x00,0x02,0x11,0x00,0x02,0x02,0x10,0x21,0x24,0x44,0x00,0x04,0x02,0x71,0x10,0x21, +0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0x00,0x80,0x80,0x21, +0xa0,0x44,0x00,0x03,0xa0,0x44,0x00,0x00,0x02,0x00,0x20,0x21,0x02,0xc0,0x28,0x21, +0x0c,0x00,0x08,0xdf,0x02,0xa0,0x30,0x21,0x02,0x71,0x18,0x21,0x00,0x03,0x88,0x80, +0x00,0x40,0xa0,0x21,0x27,0x82,0x90,0x10,0x02,0x22,0x10,0x21,0x8c,0x44,0x00,0x00, +0x26,0xe3,0x00,0x02,0x00,0x03,0x17,0xc2,0x00,0x62,0x18,0x21,0x00,0x04,0x25,0xc2, +0x00,0x03,0x18,0x43,0x30,0x84,0x00,0x01,0x00,0x03,0x18,0x40,0x03,0xc4,0x20,0x24, +0x14,0x80,0x00,0x15,0x02,0x43,0x38,0x21,0x3c,0x08,0xb0,0x03,0x35,0x08,0x00,0x28, +0x8d,0x03,0x00,0x00,0x8f,0xa6,0x00,0x4c,0x8f,0xa4,0x00,0x48,0x27,0x82,0x8f,0xf8, +0x02,0x22,0x10,0x21,0x24,0x63,0x00,0x01,0x02,0xa0,0x28,0x21,0xa4,0x54,0x00,0x04, +0x00,0xc0,0x38,0x21,0x0c,0x00,0x07,0x2b,0xad,0x03,0x00,0x00,0x7b,0xbe,0x02,0x3c, +0x7b,0xb6,0x01,0xfc,0x7b,0xb4,0x01,0xbc,0x7b,0xb2,0x01,0x7c,0x7b,0xb0,0x01,0x3c, +0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x48,0x8f,0xa2,0x00,0x1c,0x8f,0xa6,0x00,0x18, +0x02,0x00,0x20,0x21,0x02,0xc0,0x28,0x21,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0x06, +0xaf,0xa0,0x00,0x14,0x08,0x00,0x09,0xc2,0x02,0x82,0xa0,0x21,0x02,0x71,0x10,0x21, +0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0x90,0x50,0x00,0x00, +0x08,0x00,0x09,0xae,0xa0,0x50,0x00,0x03,0x27,0xbd,0xff,0xb8,0xaf,0xb1,0x00,0x24, +0x8f,0xb1,0x00,0x5c,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20, +0x24,0x42,0x27,0x98,0xaf,0xbe,0x00,0x40,0xaf,0xb7,0x00,0x3c,0xaf,0xb6,0x00,0x38, +0xaf,0xb5,0x00,0x34,0xaf,0xb4,0x00,0x30,0xaf,0xa5,0x00,0x4c,0x8f,0xb5,0x00,0x58, +0xaf,0xbf,0x00,0x44,0xaf,0xb3,0x00,0x2c,0xaf,0xb2,0x00,0x28,0xaf,0xb0,0x00,0x20, +0x00,0xe0,0xb0,0x21,0xac,0x62,0x00,0x00,0x00,0x80,0xf0,0x21,0x00,0x00,0xb8,0x21, +0x16,0x20,0x00,0x2b,0x00,0x00,0xa0,0x21,0x27,0x85,0xb3,0xf0,0x00,0x07,0x10,0x80, +0x00,0x45,0x10,0x21,0x8c,0x53,0x00,0x00,0x00,0x15,0x18,0x80,0x00,0x65,0x18,0x21, +0x92,0x62,0x00,0x16,0x8c,0x72,0x00,0x00,0x30,0x42,0x00,0x03,0x14,0x40,0x00,0x2d, +0x00,0x00,0x00,0x00,0x92,0x42,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x03, +0x14,0x40,0x00,0x28,0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x34,0x00,0x00,0x00,0x00, +0x14,0x40,0x00,0x18,0x02,0x20,0x10,0x21,0x8c,0x82,0x00,0x38,0x00,0x00,0x00,0x00, +0x14,0x40,0x00,0x14,0x02,0x20,0x10,0x21,0x8c,0x82,0x00,0x3c,0x00,0x00,0x00,0x00, +0x14,0x40,0x00,0x0f,0x3c,0x03,0xb0,0x09,0x3c,0x05,0xb0,0x05,0x34,0x63,0x01,0x44, +0x34,0xa5,0x02,0x52,0x94,0x66,0x00,0x00,0x90,0xa2,0x00,0x00,0x8f,0xa3,0x00,0x4c, +0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x06,0x30,0x42,0x00,0x01,0x10,0x40,0x00,0x04, +0x30,0xc6,0xff,0xff,0x2c,0xc2,0x00,0x41,0x10,0x40,0x00,0x09,0x24,0x05,0x00,0x14, +0x02,0x20,0x10,0x21,0x7b,0xbe,0x02,0x3c,0x7b,0xb6,0x01,0xfc,0x7b,0xb4,0x01,0xbc, +0x7b,0xb2,0x01,0x7c,0x7b,0xb0,0x01,0x3c,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x48, +0x0c,0x00,0x07,0x06,0x24,0x06,0x01,0x07,0x24,0x02,0x00,0x01,0x08,0x00,0x0a,0x28, +0xa3,0xc2,0x00,0x11,0x10,0xc0,0x00,0x1c,0x24,0x02,0x00,0x01,0x10,0xc2,0x00,0x17, +0x00,0xc0,0x88,0x21,0x96,0x54,0x00,0x1a,0x02,0xa0,0xb8,0x21,0x12,0x20,0xff,0xed, +0x02,0x20,0x10,0x21,0x27,0x83,0xb3,0xf0,0x00,0x17,0x10,0x80,0x00,0x43,0x10,0x21, +0x8c,0x44,0x00,0x00,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0x28,0x80,0x86,0x00,0x12, +0x8c,0x62,0x00,0x00,0x00,0x14,0x2c,0x00,0x00,0x05,0x2c,0x03,0x00,0x46,0x10,0x21, +0x8f,0xa6,0x00,0x4c,0x02,0xe0,0x38,0x21,0x03,0xc0,0x20,0x21,0x0c,0x00,0x07,0x2b, +0xac,0x62,0x00,0x00,0x08,0x00,0x0a,0x28,0xaf,0xd1,0x00,0x40,0x96,0x74,0x00,0x1a, +0x08,0x00,0x0a,0x3b,0x02,0xc0,0xb8,0x21,0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x08, +0x8c,0x50,0x00,0x00,0x02,0x60,0x20,0x21,0x0c,0x00,0x1f,0x11,0x02,0x00,0x28,0x21, +0x30,0x42,0x00,0xff,0x02,0x00,0x28,0x21,0x02,0x40,0x20,0x21,0x0c,0x00,0x1f,0x11, +0xaf,0xa2,0x00,0x18,0x8f,0xa4,0x00,0x18,0x00,0x00,0x00,0x00,0x10,0x80,0x00,0xed, +0x30,0x50,0x00,0xff,0x12,0x00,0x00,0x18,0x24,0x11,0x00,0x01,0x96,0x63,0x00,0x14, +0x96,0x44,0x00,0x14,0x27,0x85,0x8f,0xf0,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +0x00,0x02,0x10,0x80,0x00,0x45,0x10,0x21,0x00,0x04,0x18,0xc0,0x8c,0x46,0x00,0x08, +0x00,0x64,0x18,0x21,0x00,0x03,0x18,0x80,0x00,0x65,0x18,0x21,0x00,0x06,0x17,0x02, +0x24,0x04,0x00,0xff,0x8c,0x63,0x00,0x08,0x10,0x44,0x00,0xd6,0x00,0x03,0x17,0x02, +0x10,0x44,0x00,0xd5,0x3c,0x02,0x80,0x00,0x00,0x66,0x18,0x2b,0x24,0x11,0x00,0x02, +0x24,0x02,0x00,0x01,0x00,0x43,0x88,0x0a,0x24,0x02,0x00,0x01,0x12,0x22,0x00,0x5a, +0x24,0x02,0x00,0x02,0x16,0x22,0xff,0xbd,0x00,0x00,0x00,0x00,0x96,0x49,0x00,0x14, +0x27,0x82,0x8f,0xf4,0x02,0xa0,0xb8,0x21,0x00,0x09,0x50,0xc0,0x01,0x49,0x18,0x21, +0x00,0x03,0x40,0x80,0x01,0x02,0x10,0x21,0x8c,0x43,0x00,0x18,0x00,0x00,0x00,0x00, +0x8c,0x65,0x00,0x08,0x8c,0x62,0x00,0x0c,0x8c,0x62,0x00,0x04,0x00,0x05,0x24,0x42, +0x00,0x05,0x1c,0x82,0x30,0x42,0x00,0x10,0x30,0x66,0x00,0x01,0x14,0x40,0x00,0x41, +0x30,0x87,0x00,0x01,0x27,0x82,0x90,0x08,0x01,0x02,0x10,0x21,0x80,0x44,0x00,0x00, +0x27,0x82,0xb5,0x68,0x00,0x04,0x19,0x00,0x00,0x64,0x18,0x23,0x00,0x03,0x18,0x80, +0x00,0x64,0x18,0x23,0x00,0x03,0x18,0x80,0x00,0x62,0x10,0x21,0x90,0x45,0x00,0x05, +0x27,0x84,0xb4,0x90,0x00,0x64,0x18,0x21,0x90,0x63,0x00,0x00,0x10,0xa0,0x00,0x2b, +0x2c,0x64,0x00,0x0c,0x14,0x80,0x00,0x04,0x00,0x60,0x10,0x21,0x00,0x06,0x11,0x00, +0x00,0x62,0x10,0x21,0x24,0x42,0x00,0x24,0x3c,0x01,0xb0,0x03,0xa0,0x22,0x00,0xb9, +0x14,0x80,0x00,0x06,0x00,0x60,0x28,0x21,0x00,0x07,0x10,0x40,0x00,0x46,0x10,0x21, +0x00,0x02,0x11,0x00,0x00,0x62,0x10,0x21,0x24,0x45,0x00,0x04,0x01,0x49,0x10,0x21, +0x27,0x83,0x90,0x00,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x00,0xa0,0x18,0x21, +0xa0,0x45,0x00,0x03,0xa0,0x45,0x00,0x00,0x24,0x02,0x00,0x08,0x12,0x02,0x00,0x0b, +0x24,0x02,0x00,0x01,0x00,0x60,0x28,0x21,0x02,0x40,0x20,0x21,0x0c,0x00,0x1f,0x8d, +0xaf,0xa2,0x00,0x10,0x30,0x54,0xff,0xff,0x92,0x42,0x00,0x16,0x00,0x00,0x00,0x00, +0x02,0x02,0x10,0x25,0x08,0x00,0x0a,0x3b,0xa2,0x42,0x00,0x16,0x00,0x60,0x28,0x21, +0x02,0x40,0x20,0x21,0x0c,0x00,0x1f,0x3e,0xaf,0xa0,0x00,0x10,0x08,0x00,0x0a,0xbe, +0x30,0x54,0xff,0xff,0x08,0x00,0x0a,0xa6,0x00,0x60,0x10,0x21,0x14,0x80,0xff,0xfd, +0x00,0x00,0x00,0x00,0x00,0x06,0x11,0x00,0x00,0x62,0x10,0x21,0x08,0x00,0x0a,0xa6, +0x24,0x42,0x00,0x04,0x27,0x82,0x90,0x00,0x01,0x02,0x10,0x21,0x90,0x43,0x00,0x00, +0x08,0x00,0x0a,0xb6,0xa0,0x43,0x00,0x03,0x96,0x69,0x00,0x14,0x02,0xc0,0xb8,0x21, +0x24,0x0b,0x00,0x01,0x00,0x09,0x10,0xc0,0x00,0x49,0x18,0x21,0x00,0x03,0x40,0x80, +0x00,0x40,0x50,0x21,0x27,0x82,0x8f,0xf4,0x01,0x02,0x10,0x21,0x8c,0x43,0x00,0x18, +0x00,0x00,0x00,0x00,0x8c,0x65,0x00,0x08,0x8c,0x62,0x00,0x0c,0x8c,0x62,0x00,0x04, +0x00,0x05,0x24,0x42,0x00,0x05,0x1c,0x82,0x30,0x42,0x00,0x10,0x30,0x66,0x00,0x01, +0x10,0x40,0x00,0x0d,0x30,0x87,0x00,0x01,0x27,0x82,0x90,0x08,0x01,0x02,0x10,0x21, +0x80,0x43,0x00,0x00,0x00,0x00,0x58,0x21,0x00,0x03,0x11,0x00,0x00,0x43,0x10,0x23, +0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x23,0x00,0x02,0x10,0x80,0x27,0x83,0xb5,0x60, +0x00,0x43,0x10,0x21,0xa0,0x40,0x00,0x04,0x11,0x60,0x00,0x4f,0x00,0x00,0x00,0x00, +0x01,0x49,0x10,0x21,0x00,0x02,0x20,0x80,0x27,0x85,0x90,0x00,0x00,0x85,0x10,0x21, +0x80,0x43,0x00,0x05,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x42,0x01,0x49,0x10,0x21, +0x27,0x82,0x90,0x08,0x00,0x82,0x10,0x21,0x80,0x44,0x00,0x00,0x27,0x82,0xb5,0x68, +0x00,0x04,0x19,0x00,0x00,0x64,0x18,0x23,0x00,0x03,0x18,0x80,0x00,0x64,0x18,0x23, +0x00,0x03,0x18,0x80,0x00,0x62,0x10,0x21,0x90,0x45,0x00,0x05,0x27,0x84,0xb4,0x90, +0x00,0x64,0x18,0x21,0x90,0x63,0x00,0x00,0x10,0xa0,0x00,0x2c,0x2c,0x64,0x00,0x0c, +0x14,0x80,0x00,0x04,0x00,0x60,0x10,0x21,0x00,0x06,0x11,0x00,0x00,0x62,0x10,0x21, +0x24,0x42,0x00,0x24,0x3c,0x01,0xb0,0x03,0xa0,0x22,0x00,0xb9,0x14,0x80,0x00,0x06, +0x00,0x60,0x28,0x21,0x00,0x07,0x10,0x40,0x00,0x46,0x10,0x21,0x00,0x02,0x11,0x00, +0x00,0x62,0x10,0x21,0x24,0x45,0x00,0x04,0x01,0x49,0x10,0x21,0x27,0x83,0x90,0x00, +0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x00,0xa0,0x18,0x21,0xa0,0x45,0x00,0x03, +0xa0,0x45,0x00,0x00,0x8f,0xa4,0x00,0x18,0x24,0x02,0x00,0x08,0x10,0x82,0x00,0x0c, +0x00,0x60,0x28,0x21,0x24,0x02,0x00,0x01,0x02,0x60,0x20,0x21,0x0c,0x00,0x1f,0x8d, +0xaf,0xa2,0x00,0x10,0x8f,0xa3,0x00,0x18,0x30,0x54,0xff,0xff,0x92,0x62,0x00,0x16, +0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x25,0x08,0x00,0x0a,0x3b,0xa2,0x62,0x00,0x16, +0x02,0x60,0x20,0x21,0x0c,0x00,0x1f,0x3e,0xaf,0xa0,0x00,0x10,0x08,0x00,0x0b,0x2d, +0x00,0x00,0x00,0x00,0x08,0x00,0x0b,0x15,0x00,0x60,0x10,0x21,0x14,0x80,0xff,0xfd, +0x00,0x00,0x00,0x00,0x00,0x06,0x11,0x00,0x00,0x62,0x10,0x21,0x08,0x00,0x0b,0x15, +0x24,0x42,0x00,0x04,0x00,0x02,0x10,0x80,0x00,0x45,0x10,0x21,0x90,0x43,0x00,0x00, +0x08,0x00,0x0b,0x25,0xa0,0x43,0x00,0x03,0x27,0x85,0x90,0x00,0x08,0x00,0x0b,0x41, +0x01,0x49,0x10,0x21,0x3c,0x02,0x80,0x00,0x00,0x62,0x18,0x26,0x08,0x00,0x0a,0x76, +0x00,0xc2,0x30,0x26,0x12,0x00,0xff,0x2d,0x24,0x02,0x00,0x01,0x08,0x00,0x0a,0x7b, +0x24,0x11,0x00,0x02,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xd0, +0x24,0x42,0x2d,0x44,0x34,0x63,0x00,0x20,0x3c,0x05,0xb0,0x05,0xaf,0xb3,0x00,0x24, +0xaf,0xb2,0x00,0x20,0xaf,0xb1,0x00,0x1c,0xaf,0xbf,0x00,0x28,0xaf,0xb0,0x00,0x18, +0xac,0x62,0x00,0x00,0x34,0xa5,0x02,0x42,0x90,0xa2,0x00,0x00,0x00,0x80,0x90,0x21, +0x24,0x11,0x00,0x10,0x30,0x53,0x00,0xff,0x24,0x02,0x00,0x10,0x12,0x22,0x00,0xcf, +0x00,0x00,0x18,0x21,0x24,0x02,0x00,0x11,0x12,0x22,0x00,0xc1,0x24,0x02,0x00,0x12, +0x12,0x22,0x00,0xb4,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0xad,0xae,0x43,0x00,0x40, +0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2c,0x8c,0x44,0x00,0x00,0x3c,0x03,0x00,0x02, +0x34,0x63,0x00,0xff,0x00,0x83,0x80,0x24,0x00,0x10,0x14,0x43,0x10,0x40,0x00,0x05, +0x00,0x00,0x00,0x00,0x8e,0x42,0x00,0x34,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x92, +0x00,0x00,0x00,0x00,0x93,0x83,0x8b,0x61,0x00,0x00,0x00,0x00,0x30,0x62,0x00,0x02, +0x10,0x40,0x00,0x04,0x32,0x10,0x00,0xff,0x00,0x10,0x11,0xc3,0x14,0x40,0x00,0x86, +0x00,0x00,0x00,0x00,0x16,0x00,0x00,0x15,0x02,0x00,0x10,0x21,0x26,0x22,0x00,0x01, +0x30,0x51,0x00,0xff,0x2e,0x23,0x00,0x13,0x14,0x60,0xff,0xdb,0x24,0x03,0x00,0x02, +0x12,0x63,0x00,0x73,0x24,0x02,0x00,0x05,0x2a,0x62,0x00,0x03,0x10,0x40,0x00,0x58, +0x24,0x02,0x00,0x04,0x24,0x02,0x00,0x01,0x12,0x62,0x00,0x4b,0x02,0x40,0x20,0x21, +0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2c,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x70,0x00,0xff,0x12,0x00,0x00,0x06,0x02,0x00,0x10,0x21,0x8f,0xbf,0x00,0x28, +0x7b,0xb2,0x01,0x3c,0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x30, +0x92,0x46,0x00,0x04,0x8e,0x43,0x00,0x24,0x24,0x02,0x00,0x07,0x02,0x40,0x20,0x21, +0x00,0x00,0x28,0x21,0x24,0x07,0x00,0x06,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xe6, +0xaf,0xa3,0x00,0x14,0xae,0x42,0x00,0x24,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x02,0x2c, +0x00,0x00,0x00,0x00,0x30,0x50,0x00,0xff,0x16,0x00,0xff,0xec,0x02,0x00,0x10,0x21, +0x92,0x46,0x00,0x05,0x8e,0x43,0x00,0x28,0x24,0x02,0x00,0x05,0x02,0x40,0x20,0x21, +0x24,0x05,0x00,0x01,0x24,0x07,0x00,0x04,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xe6, +0xaf,0xa3,0x00,0x14,0xae,0x42,0x00,0x28,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x02,0x2c, +0x00,0x00,0x00,0x00,0x30,0x50,0x00,0xff,0x16,0x00,0xff,0xdc,0x02,0x00,0x10,0x21, +0x92,0x46,0x00,0x06,0x8e,0x43,0x00,0x2c,0x24,0x02,0x00,0x03,0x02,0x40,0x20,0x21, +0x24,0x05,0x00,0x02,0x00,0x00,0x38,0x21,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xe6, +0xaf,0xa3,0x00,0x14,0xae,0x42,0x00,0x2c,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x02,0x2c, +0x00,0x00,0x00,0x00,0x30,0x50,0x00,0xff,0x16,0x00,0xff,0xcc,0x02,0x00,0x10,0x21, +0x92,0x46,0x00,0x07,0x8e,0x43,0x00,0x30,0x24,0x02,0x00,0x02,0x02,0x40,0x20,0x21, +0x24,0x05,0x00,0x03,0x24,0x07,0x00,0x01,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xe6, +0xaf,0xa3,0x00,0x14,0xae,0x42,0x00,0x30,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x02,0x2c, +0x08,0x00,0x0b,0x97,0x30,0x42,0x00,0xff,0x92,0x46,0x00,0x04,0x8e,0x43,0x00,0x24, +0x24,0x02,0x00,0x07,0x00,0x00,0x28,0x21,0x24,0x07,0x00,0x06,0xaf,0xa2,0x00,0x10, +0x0c,0x00,0x09,0xe6,0xaf,0xa3,0x00,0x14,0x08,0x00,0x0b,0x90,0xae,0x42,0x00,0x24, +0x12,0x62,0x00,0x0d,0x24,0x02,0x00,0x03,0x24,0x02,0x00,0x08,0x16,0x62,0xff,0xa8, +0x02,0x40,0x20,0x21,0x92,0x46,0x00,0x07,0x8e,0x42,0x00,0x30,0x24,0x05,0x00,0x03, +0x24,0x07,0x00,0x01,0xaf,0xa3,0x00,0x10,0x0c,0x00,0x09,0xe6,0xaf,0xa2,0x00,0x14, +0x08,0x00,0x0b,0x90,0xae,0x42,0x00,0x30,0x92,0x46,0x00,0x06,0x8e,0x43,0x00,0x2c, +0x02,0x40,0x20,0x21,0x24,0x05,0x00,0x02,0x00,0x00,0x38,0x21,0xaf,0xa2,0x00,0x10, +0x0c,0x00,0x09,0xe6,0xaf,0xa3,0x00,0x14,0x08,0x00,0x0b,0x90,0xae,0x42,0x00,0x2c, +0x92,0x46,0x00,0x05,0x8e,0x43,0x00,0x28,0x02,0x40,0x20,0x21,0x24,0x05,0x00,0x01, +0x24,0x07,0x00,0x04,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xe6,0xaf,0xa3,0x00,0x14, +0x08,0x00,0x0b,0x90,0xae,0x42,0x00,0x28,0x0c,0x00,0x01,0x59,0x24,0x04,0x00,0x01, +0x08,0x00,0x0b,0x81,0x00,0x00,0x00,0x00,0x8f,0x84,0xb4,0x30,0xae,0x40,0x00,0x34, +0x94,0x85,0x00,0x14,0x0c,0x00,0x1b,0x84,0x00,0x00,0x00,0x00,0x93,0x83,0x8b,0x61, +0x00,0x00,0x00,0x00,0x30,0x62,0x00,0x02,0x10,0x40,0xff,0x69,0x00,0x00,0x00,0x00, +0x0c,0x00,0x01,0x59,0x00,0x00,0x20,0x21,0x08,0x00,0x0b,0x79,0x00,0x00,0x00,0x00, +0x02,0x40,0x20,0x21,0x0c,0x00,0x09,0x5d,0x02,0x20,0x28,0x21,0x08,0x00,0x0b,0x6d, +0x3c,0x02,0xb0,0x05,0x8e,0x42,0x00,0x3c,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x4a, +0x00,0x00,0x00,0x00,0x8f,0x82,0xb4,0x38,0x00,0x00,0x00,0x00,0x90,0x42,0x00,0x0a, +0x00,0x00,0x00,0x00,0x00,0x02,0x18,0x2b,0x08,0x00,0x0b,0x6a,0xae,0x43,0x00,0x3c, +0x8e,0x42,0x00,0x38,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x3d,0x24,0x02,0x00,0x12, +0x8f,0x82,0xb4,0x34,0x00,0x00,0x00,0x00,0x90,0x42,0x00,0x0a,0x00,0x00,0x00,0x00, +0x00,0x02,0x18,0x2b,0x08,0x00,0x0b,0x6a,0xae,0x43,0x00,0x38,0x8e,0x42,0x00,0x34, +0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x30,0x24,0x02,0x00,0x11,0x8f,0x82,0xb4,0x30, +0x00,0x00,0x00,0x00,0x90,0x42,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x02,0x18,0x2b, +0x08,0x00,0x0b,0x6a,0xae,0x43,0x00,0x34,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00, +0x27,0xbd,0xff,0xe0,0x34,0x63,0x00,0x20,0x24,0x42,0x30,0xf8,0x3c,0x08,0xb0,0x03, +0xaf,0xb1,0x00,0x14,0xac,0x62,0x00,0x00,0x35,0x08,0x01,0x00,0xaf,0xbf,0x00,0x18, +0xaf,0xb0,0x00,0x10,0x91,0x03,0x00,0x00,0x00,0xa0,0x48,0x21,0x24,0x11,0x00,0x0a, +0x2c,0xa5,0x00,0x04,0x24,0x02,0x00,0x10,0x00,0x45,0x88,0x0a,0x30,0x63,0x00,0x01, +0x00,0xc0,0x28,0x21,0x14,0x60,0x00,0x02,0x00,0x11,0x40,0x40,0x02,0x20,0x40,0x21, +0x84,0x83,0x00,0x0c,0x31,0x11,0x00,0xff,0x01,0x20,0x20,0x21,0x00,0x03,0x10,0xc0, +0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x83,0x8f,0xf8,0x00,0x43,0x10,0x21, +0x84,0x43,0x00,0x04,0x24,0x06,0x00,0x0e,0x10,0xe0,0x00,0x06,0x02,0x23,0x80,0x21, +0x02,0x00,0x10,0x21,0x8f,0xbf,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x20,0x0c,0x00,0x08,0xdf,0x00,0x00,0x00,0x00,0x02,0x11,0x18,0x21, +0x08,0x00,0x0c,0x60,0x00,0x62,0x80,0x21,0x27,0xbd,0xff,0xd0,0xaf,0xbf,0x00,0x28, +0xaf,0xb4,0x00,0x20,0xaf,0xb3,0x00,0x1c,0xaf,0xb2,0x00,0x18,0xaf,0xb5,0x00,0x24, +0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0x84,0x82,0x00,0x0c,0x3c,0x06,0xb0,0x03, +0x34,0xc6,0x00,0x20,0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21,0x00,0x03,0x18,0x80, +0x27,0x82,0x8f,0xf4,0x00,0x62,0x10,0x21,0x8c,0x55,0x00,0x18,0x3c,0x02,0x80,0x00, +0x24,0x42,0x31,0xa8,0xac,0xc2,0x00,0x00,0x8e,0xb0,0x00,0x08,0x27,0x82,0x8f,0xf8, +0x00,0x62,0x18,0x21,0x90,0x71,0x00,0x07,0x00,0x10,0x86,0x43,0x32,0x10,0x00,0x01, +0x00,0xa0,0x38,0x21,0x02,0x00,0x30,0x21,0x00,0xa0,0x98,0x21,0x02,0x20,0x28,0x21, +0x0c,0x00,0x0c,0x3e,0x00,0x80,0x90,0x21,0x02,0x20,0x20,0x21,0x02,0x00,0x28,0x21, +0x24,0x06,0x00,0x14,0x0c,0x00,0x08,0xdf,0x00,0x40,0xa0,0x21,0x86,0x43,0x00,0x0c, +0x3c,0x09,0xb0,0x09,0x3c,0x08,0xb0,0x09,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0x80,0x43,0x00,0x06, +0x3c,0x07,0xb0,0x09,0x3c,0x05,0xb0,0x09,0x28,0x62,0x00,0x00,0x24,0x64,0x00,0x03, +0x00,0x82,0x18,0x0b,0x00,0x03,0x18,0x83,0x3c,0x02,0xb0,0x09,0x00,0x03,0x18,0x80, +0x34,0x42,0x01,0x02,0x35,0x29,0x01,0x10,0x35,0x08,0x01,0x14,0x34,0xe7,0x01,0x20, +0x34,0xa5,0x01,0x24,0xa4,0x54,0x00,0x00,0x12,0x60,0x00,0x11,0x02,0xa3,0xa8,0x21, +0x8e,0xa2,0x00,0x0c,0x8e,0xa3,0x00,0x08,0x00,0x02,0x14,0x00,0x00,0x03,0x1c,0x02, +0x00,0x43,0x10,0x21,0xad,0x22,0x00,0x00,0x8e,0xa3,0x00,0x0c,0x00,0x00,0x00,0x00, +0x00,0x03,0x1c,0x02,0xa5,0x03,0x00,0x00,0x8f,0xbf,0x00,0x28,0x7b,0xb4,0x01,0x3c, +0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x30, +0x8e,0xa2,0x00,0x04,0x00,0x00,0x00,0x00,0xad,0x22,0x00,0x00,0x8e,0xa4,0x00,0x08, +0x00,0x00,0x00,0x00,0xa5,0x04,0x00,0x00,0x7a,0xa2,0x00,0x7c,0x00,0x00,0x00,0x00, +0x00,0x03,0x1c,0x00,0x00,0x02,0x14,0x02,0x00,0x62,0x18,0x21,0xac,0xe3,0x00,0x00, +0x8e,0xa2,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x02,0x08,0x00,0x0c,0xb2, +0xa4,0xa2,0x00,0x00,0x27,0xbd,0xff,0xe0,0xaf,0xb2,0x00,0x18,0xaf,0xb0,0x00,0x10, +0xaf,0xbf,0x00,0x1c,0xaf,0xb1,0x00,0x14,0x84,0x82,0x00,0x0c,0x00,0x80,0x90,0x21, +0x3c,0x05,0xb0,0x03,0x00,0x02,0x20,0xc0,0x00,0x82,0x20,0x21,0x00,0x04,0x20,0x80, +0x27,0x82,0x8f,0xf4,0x00,0x82,0x10,0x21,0x8c,0x51,0x00,0x18,0x3c,0x02,0x80,0x00, +0x34,0xa5,0x00,0x20,0x24,0x42,0x33,0x24,0x27,0x83,0x8f,0xf8,0xac,0xa2,0x00,0x00, +0x00,0x83,0x20,0x21,0x3c,0x02,0xb0,0x03,0x90,0x86,0x00,0x07,0x34,0x42,0x01,0x00, +0x8e,0x23,0x00,0x08,0x90,0x44,0x00,0x00,0x2c,0xc5,0x00,0x04,0x24,0x02,0x00,0x10, +0x24,0x10,0x00,0x0a,0x00,0x45,0x80,0x0a,0x00,0x03,0x1e,0x43,0x30,0x84,0x00,0x01, +0x30,0x65,0x00,0x01,0x14,0x80,0x00,0x02,0x00,0x10,0x10,0x40,0x02,0x00,0x10,0x21, +0x00,0xc0,0x20,0x21,0x24,0x06,0x00,0x20,0x0c,0x00,0x08,0xdf,0x30,0x50,0x00,0xff, +0x86,0x44,0x00,0x0c,0x27,0x85,0x90,0x00,0x3c,0x06,0xb0,0x09,0x00,0x04,0x18,0xc0, +0x00,0x64,0x18,0x21,0x00,0x03,0x18,0x80,0x00,0x65,0x18,0x21,0x80,0x64,0x00,0x06, +0x00,0x50,0x10,0x21,0x34,0xc6,0x01,0x02,0x24,0x85,0x00,0x03,0x28,0x83,0x00,0x00, +0x00,0xa3,0x20,0x0b,0x00,0x04,0x20,0x83,0x00,0x04,0x20,0x80,0xa4,0xc2,0x00,0x00, +0x02,0x24,0x20,0x21,0x8c,0x83,0x00,0x04,0x3c,0x02,0xb0,0x09,0x34,0x42,0x01,0x10, +0xac,0x43,0x00,0x00,0x8c,0x86,0x00,0x08,0x3c,0x02,0xb0,0x09,0x34,0x42,0x01,0x14, +0xa4,0x46,0x00,0x00,0x8c,0x85,0x00,0x0c,0x8c,0x82,0x00,0x08,0x3c,0x06,0xb0,0x09, +0x00,0x05,0x2c,0x00,0x00,0x02,0x14,0x02,0x00,0xa2,0x28,0x21,0x34,0xc6,0x01,0x20, +0xac,0xc5,0x00,0x00,0x8c,0x83,0x00,0x0c,0x3c,0x05,0xb0,0x09,0x34,0xa5,0x01,0x24, +0x00,0x03,0x1c,0x02,0xa4,0xa3,0x00,0x00,0x92,0x42,0x00,0x0a,0x3c,0x03,0xb0,0x09, +0x34,0x63,0x01,0x30,0x00,0x02,0x13,0x00,0x24,0x42,0x00,0x04,0x30,0x42,0xff,0xff, +0xa4,0x62,0x00,0x00,0x86,0x44,0x00,0x0c,0x27,0x83,0x90,0x08,0x8f,0xbf,0x00,0x1c, +0x00,0x04,0x10,0xc0,0x00,0x44,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21, +0x94,0x44,0x00,0x02,0x8f,0xb2,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x3c,0x05,0xb0,0x09, +0x34,0xa5,0x01,0x32,0xa4,0xa4,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20, +0x27,0xbd,0xff,0xe0,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x00,0xaf,0xb0,0x00,0x10, +0x34,0x42,0x00,0x20,0x00,0xa0,0x80,0x21,0x24,0x63,0x34,0xb0,0x00,0x05,0x2c,0x43, +0xaf,0xb1,0x00,0x14,0xaf,0xbf,0x00,0x18,0xac,0x43,0x00,0x00,0x10,0xa0,0x00,0x05, +0x00,0x80,0x88,0x21,0x8c,0x82,0x00,0x34,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0xb6, +0x00,0x00,0x00,0x00,0x32,0x10,0x00,0xff,0x12,0x00,0x00,0x4c,0x00,0x00,0x10,0x21, +0x24,0x02,0x00,0x08,0x12,0x02,0x00,0xa3,0x2a,0x02,0x00,0x09,0x10,0x40,0x00,0x89, +0x24,0x02,0x00,0x40,0x24,0x04,0x00,0x02,0x12,0x04,0x00,0x79,0x2a,0x02,0x00,0x03, +0x10,0x40,0x00,0x69,0x24,0x02,0x00,0x04,0x24,0x02,0x00,0x01,0x12,0x02,0x00,0x5a, +0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x05,0x34,0x42,0x00,0x08,0x3c,0x03,0x80,0x00, +0xa2,0x20,0x00,0x4e,0xac,0x43,0x00,0x00,0x82,0x24,0x00,0x11,0x92,0x27,0x00,0x11, +0x10,0x80,0x00,0x4e,0x00,0x00,0x00,0x00,0x92,0x26,0x00,0x0a,0x24,0x02,0x00,0x12, +0x10,0x46,0x00,0x09,0x30,0xc2,0x00,0xff,0x27,0x83,0xb3,0xf0,0x00,0x02,0x10,0x80, +0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x83,0x00,0x14, +0x00,0x00,0x00,0x00,0xa6,0x23,0x00,0x0c,0x3c,0x02,0xb0,0x09,0x34,0x42,0x00,0x40, +0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x03,0xa2,0x23,0x00,0x10, +0x14,0x60,0x00,0x2b,0x30,0x65,0x00,0x01,0x30,0xc2,0x00,0xff,0x27,0x83,0xb3,0xf0, +0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x82,0x23,0x00,0x12, +0x90,0x82,0x00,0x16,0x00,0x00,0x00,0x00,0x00,0x02,0x11,0x42,0x30,0x42,0x00,0x01, +0x00,0x62,0x18,0x21,0x00,0x03,0x26,0x00,0x14,0x80,0x00,0x18,0xa2,0x23,0x00,0x12, +0x00,0x07,0x16,0x00,0x14,0x40,0x00,0x11,0x24,0x02,0x00,0x01,0x96,0x23,0x00,0x0c, +0x27,0x84,0x90,0x00,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80, +0x00,0x44,0x10,0x21,0x80,0x45,0x00,0x06,0x00,0x03,0x1a,0x00,0x3c,0x02,0xb0,0x00, +0x00,0x65,0x18,0x21,0x00,0x62,0x18,0x21,0x90,0x64,0x00,0x00,0x90,0x62,0x00,0x04, +0xa2,0x20,0x00,0x15,0xa3,0x80,0x8b,0xc4,0x24,0x02,0x00,0x01,0x8f,0xbf,0x00,0x18, +0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x0c,0x00,0x0c,0xc9, +0x02,0x20,0x20,0x21,0x92,0x27,0x00,0x11,0x08,0x00,0x0d,0x79,0x00,0x07,0x16,0x00, +0x0c,0x00,0x0c,0x6a,0x02,0x20,0x20,0x21,0x86,0x23,0x00,0x0c,0x27,0x84,0x8f,0xf8, +0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x44,0x20,0x21, +0x90,0x85,0x00,0x07,0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0xa2,0x25,0x00,0x13, +0x90,0x83,0x00,0x07,0x08,0x00,0x0d,0x91,0xa0,0x43,0x00,0x02,0x92,0x26,0x00,0x0a, +0x08,0x00,0x0d,0x5a,0x30,0xc2,0x00,0xff,0x8e,0x22,0x00,0x24,0x00,0x00,0x00,0x00, +0x10,0x50,0x00,0x07,0xa2,0x20,0x00,0x08,0x24,0x02,0x00,0x07,0xa2,0x22,0x00,0x0a, +0x92,0x22,0x00,0x27,0xae,0x20,0x00,0x24,0x08,0x00,0x0d,0x4d,0xa2,0x22,0x00,0x04, +0x08,0x00,0x0d,0xab,0x24,0x02,0x00,0x06,0x16,0x02,0xff,0x9b,0x3c,0x02,0xb0,0x05, +0x8e,0x23,0x00,0x2c,0x24,0x02,0x00,0x01,0x10,0x62,0x00,0x07,0xa2,0x24,0x00,0x08, +0x24,0x02,0x00,0x03,0xa2,0x22,0x00,0x0a,0x92,0x22,0x00,0x2f,0xae,0x20,0x00,0x2c, +0x08,0x00,0x0d,0x4d,0xa2,0x22,0x00,0x06,0x08,0x00,0x0d,0xba,0xa2,0x20,0x00,0x0a, +0x8e,0x22,0x00,0x28,0x24,0x03,0x00,0x01,0x24,0x04,0x00,0x01,0x10,0x44,0x00,0x07, +0xa2,0x23,0x00,0x08,0x24,0x02,0x00,0x05,0xa2,0x22,0x00,0x0a,0x92,0x22,0x00,0x2b, +0xae,0x20,0x00,0x28,0x08,0x00,0x0d,0x4d,0xa2,0x22,0x00,0x05,0x08,0x00,0x0d,0xc6, +0x24,0x02,0x00,0x04,0x12,0x02,0x00,0x12,0x2a,0x02,0x00,0x41,0x10,0x40,0x00,0x09, +0x24,0x02,0x00,0x80,0x24,0x02,0x00,0x20,0x16,0x02,0xff,0x7b,0x3c,0x02,0xb0,0x05, +0x24,0x02,0x00,0x12,0xa2,0x22,0x00,0x0a,0xa2,0x22,0x00,0x08,0x08,0x00,0x0d,0x4d, +0xae,0x20,0x00,0x3c,0x16,0x02,0xff,0x74,0x3c,0x02,0xb0,0x05,0x24,0x02,0x00,0x10, +0xa2,0x22,0x00,0x0a,0xa2,0x22,0x00,0x08,0x08,0x00,0x0d,0x4d,0xae,0x20,0x00,0x34, +0x24,0x02,0x00,0x11,0xa2,0x22,0x00,0x0a,0xa2,0x22,0x00,0x08,0x08,0x00,0x0d,0x4d, +0xae,0x20,0x00,0x38,0x8e,0x24,0x00,0x30,0x24,0x02,0x00,0x03,0x24,0x03,0x00,0x01, +0x10,0x83,0x00,0x07,0xa2,0x22,0x00,0x08,0x24,0x02,0x00,0x02,0xa2,0x22,0x00,0x0a, +0x92,0x22,0x00,0x33,0xae,0x20,0x00,0x30,0x08,0x00,0x0d,0x4d,0xa2,0x22,0x00,0x07, +0x08,0x00,0x0d,0xec,0xa2,0x24,0x00,0x0a,0x8f,0x84,0xb4,0x30,0xae,0x20,0x00,0x34, +0x94,0x85,0x00,0x14,0x0c,0x00,0x1b,0x84,0x32,0x10,0x00,0xff,0x08,0x00,0x0d,0x3e, +0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x24,0x42,0x37,0xe4, +0x34,0x63,0x00,0x20,0xac,0x62,0x00,0x00,0x80,0xa2,0x00,0x15,0x3c,0x06,0xb0,0x05, +0x10,0x40,0x00,0x0a,0x34,0xc6,0x02,0x54,0x83,0x83,0x8b,0xc4,0x00,0x00,0x00,0x00, +0xac,0x83,0x00,0x24,0x8c,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x17,0x42, +0x30,0x42,0x00,0x01,0x03,0xe0,0x00,0x08,0xac,0x82,0x00,0x28,0x8c,0x82,0x00,0x2c, +0x3c,0x06,0xb0,0x05,0x34,0xc6,0x04,0x50,0x00,0x02,0x18,0x43,0x30,0x63,0x00,0x01, +0x10,0x40,0x00,0x04,0x30,0x45,0x00,0x01,0xac,0x83,0x00,0x28,0x03,0xe0,0x00,0x08, +0xac,0x85,0x00,0x24,0x90,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff, +0x30,0x43,0x00,0x02,0x30,0x42,0x00,0x01,0xac,0x83,0x00,0x28,0x03,0xe0,0x00,0x08, +0xac,0x82,0x00,0x24,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xd8, +0x34,0x63,0x00,0x20,0x24,0x42,0x38,0x74,0xac,0x62,0x00,0x00,0xaf,0xb1,0x00,0x1c, +0xaf,0xbf,0x00,0x20,0xaf,0xb0,0x00,0x18,0x90,0xa6,0x00,0x0a,0x27,0x83,0xb3,0xf0, +0x00,0xa0,0x88,0x21,0x00,0x06,0x10,0x80,0x00,0x43,0x10,0x21,0x8c,0x50,0x00,0x00, +0x80,0xa5,0x00,0x11,0x92,0x03,0x00,0x12,0x10,0xa0,0x00,0x04,0xa2,0x20,0x00,0x15, +0x24,0x02,0x00,0x12,0x10,0xc2,0x00,0xda,0x00,0x00,0x00,0x00,0x82,0x22,0x00,0x12, +0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x67,0x00,0x00,0x00,0x00,0xa2,0x20,0x00,0x12, +0xa2,0x00,0x00,0x19,0x86,0x23,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0xc0, +0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x10,0x00,0x43,0x10,0x21, +0xa0,0x40,0x00,0x00,0x92,0x03,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0xdf, +0xa2,0x03,0x00,0x16,0x82,0x02,0x00,0x12,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x20, +0x00,0x00,0x00,0x00,0x92,0x23,0x00,0x08,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x45, +0x24,0x02,0x00,0x01,0xa2,0x20,0x00,0x04,0x92,0x08,0x00,0x04,0x00,0x00,0x00,0x00, +0x15,0x00,0x00,0x1e,0x24,0x02,0x00,0x01,0x92,0x07,0x00,0x0a,0xa2,0x02,0x00,0x17, +0x92,0x02,0x00,0x16,0x30,0xe3,0x00,0xff,0x30,0x42,0x00,0xe4,0x10,0x60,0x00,0x03, +0xa2,0x02,0x00,0x16,0x34,0x42,0x00,0x01,0xa2,0x02,0x00,0x16,0x11,0x00,0x00,0x05, +0x00,0x00,0x00,0x00,0x92,0x02,0x00,0x16,0x00,0x00,0x00,0x00,0x34,0x42,0x00,0x02, +0xa2,0x02,0x00,0x16,0x92,0x02,0x00,0x17,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x08, +0x00,0x00,0x00,0x00,0x96,0x02,0x00,0x06,0x00,0x00,0x00,0x00,0xa6,0x02,0x00,0x14, +0x8f,0xbf,0x00,0x20,0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28, +0x96,0x02,0x00,0x00,0x08,0x00,0x0e,0x68,0xa6,0x02,0x00,0x14,0x92,0x07,0x00,0x0a, +0x00,0x00,0x00,0x00,0x14,0xe0,0x00,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0x0e,0x54, +0xa2,0x00,0x00,0x17,0x96,0x04,0x00,0x00,0x96,0x05,0x00,0x06,0x27,0x86,0x8f,0xf0, +0x00,0x04,0x18,0xc0,0x00,0x64,0x18,0x21,0x00,0x05,0x10,0xc0,0x00,0x45,0x10,0x21, +0x00,0x03,0x18,0x80,0x00,0x66,0x18,0x21,0x00,0x02,0x10,0x80,0x00,0x46,0x10,0x21, +0x8c,0x66,0x00,0x08,0x8c,0x45,0x00,0x08,0x3c,0x03,0x80,0x00,0x00,0xc3,0x20,0x24, +0x10,0x80,0x00,0x08,0x00,0xa3,0x10,0x24,0x10,0x40,0x00,0x04,0x00,0x00,0x18,0x21, +0x10,0x80,0x00,0x02,0x24,0x03,0x00,0x01,0x00,0xa6,0x18,0x2b,0x08,0x00,0x0e,0x54, +0xa2,0x03,0x00,0x17,0x10,0x40,0xff,0xfd,0x00,0xa6,0x18,0x2b,0x08,0x00,0x0e,0x88, +0x00,0x00,0x00,0x00,0x10,0x62,0x00,0x09,0x24,0x02,0x00,0x02,0x10,0x62,0x00,0x05, +0x24,0x02,0x00,0x03,0x14,0x62,0xff,0xb8,0x00,0x00,0x00,0x00,0x08,0x00,0x0e,0x4e, +0xa2,0x20,0x00,0x07,0x08,0x00,0x0e,0x4e,0xa2,0x20,0x00,0x06,0x08,0x00,0x0e,0x4e, +0xa2,0x20,0x00,0x05,0x82,0x22,0x00,0x10,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x69, +0x2c,0x62,0x00,0x02,0x10,0x40,0x00,0x49,0x3c,0x02,0xb0,0x09,0x92,0x25,0x00,0x08, +0x00,0x00,0x00,0x00,0x30,0xa6,0x00,0xff,0x2c,0xc2,0x00,0x04,0x10,0x40,0x00,0x3b, +0x2c,0xc2,0x00,0x10,0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00, +0x24,0x02,0x00,0x01,0x00,0xc2,0x10,0x04,0x00,0x02,0x10,0x27,0x00,0x62,0x18,0x24, +0xa0,0x83,0x00,0x00,0x86,0x23,0x00,0x0c,0x96,0x26,0x00,0x0c,0x00,0x03,0x10,0xc0, +0x00,0x43,0x10,0x21,0x00,0x02,0x28,0x80,0x27,0x83,0x8f,0xf4,0x00,0xa3,0x18,0x21, +0x8c,0x64,0x00,0x18,0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x04,0x00,0x00,0x00,0x00, +0x30,0x42,0x00,0x10,0x10,0x40,0x00,0x18,0x24,0x07,0x00,0x01,0x93,0x82,0x8b,0x61, +0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x14,0x40,0x00,0x0a,0x24,0x05,0x00,0x24, +0x00,0x06,0x2c,0x00,0x00,0x05,0x2c,0x03,0x0c,0x00,0x1b,0x84,0x02,0x00,0x20,0x21, +0x92,0x02,0x00,0x16,0xa2,0x00,0x00,0x12,0x30,0x42,0x00,0xe7,0x08,0x00,0x0e,0x45, +0xa2,0x02,0x00,0x16,0xf0,0xc5,0x00,0x06,0x00,0x00,0x28,0x12,0x27,0x82,0x8f,0xf0, +0x00,0xa2,0x28,0x21,0x0c,0x00,0x01,0x4b,0x3c,0x04,0x00,0x80,0x96,0x26,0x00,0x0c, +0x08,0x00,0x0e,0xc5,0x00,0x06,0x2c,0x00,0x27,0x83,0x90,0x00,0x27,0x82,0x90,0x08, +0x00,0xa2,0x10,0x21,0x00,0xa3,0x18,0x21,0x90,0x44,0x00,0x00,0x90,0x65,0x00,0x05, +0x93,0x82,0x80,0x10,0x00,0x00,0x30,0x21,0x0c,0x00,0x21,0xf5,0xaf,0xa2,0x00,0x10, +0x96,0x26,0x00,0x0c,0x08,0x00,0x0e,0xbf,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0xcd, +0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x30,0xa5,0x00,0x0f, +0x24,0x02,0x00,0x80,0x08,0x00,0x0e,0xae,0x00,0xa2,0x10,0x07,0x86,0x26,0x00,0x0c, +0x3c,0x03,0xb0,0x09,0x34,0x42,0x01,0x72,0x34,0x63,0x01,0x78,0x94,0x47,0x00,0x00, +0x8c,0x65,0x00,0x00,0x00,0x06,0x10,0xc0,0x00,0x46,0x10,0x21,0x3c,0x04,0xb0,0x09, +0xae,0x25,0x00,0x1c,0x34,0x84,0x01,0x7c,0x27,0x83,0x8f,0xf4,0x00,0x02,0x10,0x80, +0x8c,0x85,0x00,0x00,0x00,0x43,0x10,0x21,0x8c,0x43,0x00,0x18,0xae,0x25,0x00,0x20, +0xa6,0x27,0x00,0x18,0x8c,0x66,0x00,0x08,0x02,0x20,0x20,0x21,0x0c,0x00,0x0f,0x15, +0x00,0x00,0x28,0x21,0x86,0x25,0x00,0x18,0x8e,0x26,0x00,0x1c,0x8e,0x27,0x00,0x20, +0x02,0x20,0x20,0x21,0x0c,0x00,0x1c,0x86,0xaf,0xa2,0x00,0x10,0x08,0x00,0x0e,0x45, +0xa2,0x02,0x00,0x12,0x92,0x22,0x00,0x08,0x08,0x00,0x0e,0x45,0xa2,0x22,0x00,0x09, +0xa2,0x20,0x00,0x11,0x80,0x82,0x00,0x50,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x03, +0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xd0,0xac,0x40,0x00,0x00,0x08,0x00,0x0e,0x45, +0xa0,0x80,0x00,0x50,0x94,0x8a,0x00,0x0c,0x24,0x03,0x00,0x24,0x00,0x80,0x70,0x21, +0x3c,0x02,0x80,0x00,0x3c,0x04,0xb0,0x03,0x24,0x42,0x3c,0x54,0xf1,0x43,0x00,0x06, +0x34,0x84,0x00,0x20,0x00,0x00,0x18,0x12,0x00,0xa0,0x68,0x21,0xac,0x82,0x00,0x00, +0x27,0x85,0x90,0x00,0x27,0x82,0x8f,0xff,0x27,0xbd,0xff,0xf8,0x00,0x62,0x60,0x21, +0x00,0x65,0x58,0x21,0x00,0x00,0xc0,0x21,0x11,0xa0,0x00,0xcc,0x00,0x00,0x78,0x21, +0x00,0x0a,0x1c,0x00,0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +0x00,0x02,0x10,0x80,0x00,0x45,0x10,0x21,0x91,0x87,0x00,0x00,0x80,0x48,0x00,0x04, +0x03,0xa0,0x60,0x21,0x00,0x0a,0x1c,0x00,0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0, +0x00,0x43,0x10,0x21,0x00,0x02,0x48,0x80,0x27,0x83,0x8f,0xf4,0xa3,0xa7,0x00,0x00, +0x01,0x23,0x18,0x21,0x8c,0x64,0x00,0x18,0x25,0x02,0xff,0xff,0x00,0x48,0x40,0x0b, +0x8c,0x83,0x00,0x04,0x2d,0x05,0x00,0x07,0x24,0x02,0x00,0x06,0x30,0x63,0x00,0x08, +0x14,0x60,0x00,0x35,0x00,0x45,0x40,0x0a,0x93,0xa7,0x00,0x00,0x27,0x82,0x90,0x08, +0x01,0x22,0x10,0x21,0x30,0xe3,0x00,0xf0,0x38,0x63,0x00,0x50,0x30,0xe5,0x00,0xff, +0x00,0x05,0x20,0x2b,0x00,0x03,0x18,0x2b,0x00,0x64,0x18,0x24,0x90,0x49,0x00,0x00, +0x10,0x60,0x00,0x16,0x30,0xe4,0x00,0x0f,0x24,0x02,0x00,0x04,0x10,0xa2,0x00,0x9d, +0x00,0x00,0x00,0x00,0x11,0xa0,0x00,0x3a,0x2c,0xa2,0x00,0x0c,0x10,0x40,0x00,0x02, +0x24,0x84,0x00,0x0c,0x00,0xe0,0x20,0x21,0x30,0x84,0x00,0xff,0x00,0x04,0x10,0x40, +0x27,0x83,0xbb,0x0c,0x00,0x44,0x10,0x21,0x00,0x43,0x10,0x21,0x90,0x47,0x00,0x00, +0x00,0x00,0x00,0x00,0x2c,0xe3,0x00,0x0c,0xa3,0xa7,0x00,0x00,0x10,0x60,0x00,0x02, +0x24,0xe2,0x00,0x04,0x00,0xe0,0x10,0x21,0xa3,0xa2,0x00,0x00,0x91,0x65,0x00,0x00, +0x91,0x82,0x00,0x00,0x30,0xa3,0x00,0xff,0x00,0x62,0x10,0x2b,0x10,0x40,0x00,0x0e, +0x2c,0x62,0x00,0x0c,0x14,0x40,0x00,0x03,0x00,0x60,0x20,0x21,0x30,0xa2,0x00,0x0f, +0x24,0x44,0x00,0x0c,0x00,0x04,0x10,0x40,0x00,0x44,0x20,0x21,0x27,0x83,0xbb,0x0c, +0x00,0x83,0x18,0x21,0x90,0x62,0x00,0x02,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x05, +0x00,0x09,0x11,0x00,0xa1,0x85,0x00,0x00,0x93,0xa2,0x00,0x00,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x08,0x00,0x49,0x10,0x23,0x00,0x02,0x10,0x80,0x00,0x49,0x10,0x23, +0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x21,0x27,0x83,0xb4,0x98,0x00,0x43,0x10,0x21, +0x90,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0x83,0x00,0x0c,0x14,0x60,0x00,0x06, +0x00,0x80,0x10,0x21,0x00,0x18,0x10,0x40,0x00,0x4f,0x10,0x21,0x00,0x02,0x11,0x00, +0x00,0x82,0x10,0x21,0x24,0x42,0x00,0x04,0x08,0x00,0x0f,0x76,0xa1,0x82,0x00,0x00, +0x8f,0x8d,0x81,0x5c,0x00,0x00,0x00,0x00,0x01,0xa8,0x10,0x21,0x90,0x43,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x60,0xff,0xd1,0x00,0x00,0x28,0x21,0x00,0x06,0x74,0x82, +0x30,0xe2,0x00,0xff,0x2c,0x42,0x00,0x0c,0x14,0x40,0x00,0x03,0x00,0xe0,0x10,0x21, +0x30,0xe2,0x00,0x0f,0x24,0x42,0x00,0x0c,0x30,0x44,0x00,0xff,0xa3,0xa2,0x00,0x00, +0x24,0x02,0x00,0x0c,0x10,0x82,0x00,0x0d,0x00,0x09,0x11,0x00,0x00,0x49,0x10,0x23, +0x00,0x02,0x10,0x80,0x00,0x04,0x18,0x40,0x00,0x49,0x10,0x23,0x00,0x64,0x18,0x21, +0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x27,0x84,0xb4,0x98,0x00,0x44,0x10,0x21, +0x90,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xa7,0x00,0x00,0x00,0x0a,0x1c,0x00, +0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80, +0x27,0x83,0x8f,0xf4,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x18,0x00,0x00,0x00,0x00, +0x8c,0x83,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x10,0x14,0x60,0x00,0x33, +0x00,0x06,0x14,0x42,0x00,0x09,0x11,0x00,0x00,0x49,0x10,0x23,0x00,0x02,0x10,0x80, +0x00,0x49,0x10,0x23,0x27,0x83,0xb5,0x68,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21, +0x90,0x44,0x00,0x04,0x90,0x43,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x64,0xc0,0x24, +0x93,0xa7,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0xe2,0x00,0x0f,0x10,0x40,0x00,0x0f, +0x31,0xcf,0x00,0x01,0x00,0x0a,0x1c,0x00,0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0, +0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x84,0x8f,0xf0,0x00,0x44,0x10,0x21, +0x84,0x43,0x00,0x06,0x00,0x00,0x00,0x00,0x28,0x63,0x06,0x41,0x14,0x60,0x00,0x04, +0x30,0xe2,0x00,0xff,0x24,0x07,0x00,0x0f,0xa3,0xa7,0x00,0x00,0x30,0xe2,0x00,0xff, +0x2c,0x42,0x00,0x0c,0x14,0x40,0x00,0x06,0x00,0xe0,0x10,0x21,0x00,0x18,0x10,0x40, +0x00,0x4f,0x10,0x21,0x00,0x02,0x11,0x00,0x00,0x47,0x10,0x21,0x24,0x42,0x00,0x04, +0xa3,0xa2,0x00,0x00,0x00,0x40,0x38,0x21,0x01,0xa8,0x10,0x21,0x90,0x43,0x00,0x00, +0x24,0xa4,0x00,0x01,0x30,0x85,0xff,0xff,0x00,0xa3,0x18,0x2b,0x14,0x60,0xff,0xad, +0x30,0xe2,0x00,0xff,0x08,0x00,0x0f,0x63,0x00,0x00,0x00,0x00,0x08,0x00,0x0f,0xc4, +0x30,0x58,0x00,0x01,0x81,0xc2,0x00,0x48,0x00,0x00,0x00,0x00,0x10,0x40,0xff,0x73, +0x00,0x00,0x00,0x00,0x08,0x00,0x0f,0x51,0x00,0x00,0x00,0x00,0x00,0x0a,0x1c,0x00, +0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80, +0x00,0x45,0x10,0x21,0x80,0x48,0x00,0x05,0x91,0x67,0x00,0x00,0x08,0x00,0x0f,0x31, +0x03,0xa0,0x58,0x21,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20, +0x24,0x42,0x3f,0xf4,0x03,0xe0,0x00,0x08,0xac,0x62,0x00,0x00,0x27,0xbd,0xff,0xc0, +0xaf,0xb7,0x00,0x34,0xaf,0xb6,0x00,0x30,0xaf,0xb5,0x00,0x2c,0xaf,0xb4,0x00,0x28, +0xaf,0xb3,0x00,0x24,0xaf,0xb2,0x00,0x20,0xaf,0xbf,0x00,0x3c,0xaf,0xbe,0x00,0x38, +0xaf,0xb1,0x00,0x1c,0xaf,0xb0,0x00,0x18,0x84,0x82,0x00,0x0c,0x27,0x93,0x8f,0xf4, +0x3c,0x05,0xb0,0x03,0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21,0x00,0x03,0x18,0x80, +0x00,0x73,0x10,0x21,0x8c,0x5e,0x00,0x18,0x3c,0x02,0x80,0x00,0x34,0xa5,0x00,0x20, +0x24,0x42,0x40,0x0c,0xac,0xa2,0x00,0x00,0x8f,0xd0,0x00,0x08,0x27,0x95,0x90,0x00, +0x00,0x75,0x18,0x21,0x00,0x00,0x28,0x21,0x02,0x00,0x30,0x21,0x90,0x71,0x00,0x00, +0x0c,0x00,0x0f,0x15,0x00,0x80,0xb0,0x21,0x00,0x40,0x90,0x21,0x00,0x10,0x14,0x42, +0x30,0x54,0x00,0x01,0x02,0x40,0x20,0x21,0x00,0x10,0x14,0x82,0x02,0x80,0x28,0x21, +0x12,0x51,0x00,0x23,0x00,0x10,0xbf,0xc2,0x86,0xc3,0x00,0x0c,0x30,0x50,0x00,0x01, +0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x55,0x10,0x21, +0xa0,0x52,0x00,0x00,0x86,0xc3,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0xc0, +0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x53,0x30,0x21,0x8c,0xc7,0x00,0x18, +0x27,0x83,0x8f,0xf0,0x00,0x43,0x10,0x21,0x8c,0xe3,0x00,0x04,0x84,0x46,0x00,0x06, +0x00,0x03,0x19,0x42,0x0c,0x00,0x08,0xdf,0x30,0x73,0x00,0x01,0x00,0x40,0x88,0x21, +0x02,0x40,0x20,0x21,0x02,0x80,0x28,0x21,0x16,0xe0,0x00,0x10,0x02,0x00,0x30,0x21, +0x86,0xc2,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21, +0x00,0x03,0x18,0x80,0x27,0x82,0x8f,0xf8,0x00,0x62,0x18,0x21,0xa4,0x71,0x00,0x04, +0x7b,0xbe,0x01,0xfc,0x7b,0xb6,0x01,0xbc,0x7b,0xb4,0x01,0x7c,0x7b,0xb2,0x01,0x3c, +0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x40,0x86,0xc3,0x00,0x0c, +0xaf,0xb3,0x00,0x10,0xaf,0xa0,0x00,0x14,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +0x00,0x02,0x10,0x80,0x00,0x55,0x10,0x21,0x80,0x47,0x00,0x06,0x00,0x00,0x00,0x00, +0x24,0xe7,0x00,0x02,0x00,0x07,0x17,0xc2,0x00,0xe2,0x38,0x21,0x00,0x07,0x38,0x43, +0x00,0x07,0x38,0x40,0x0c,0x00,0x09,0x06,0x03,0xc7,0x38,0x21,0x08,0x00,0x10,0x44, +0x02,0x22,0x88,0x21,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xd0, +0x34,0x63,0x00,0x20,0x24,0x42,0x41,0x94,0xaf,0xb2,0x00,0x20,0xac,0x62,0x00,0x00, +0xaf,0xbf,0x00,0x28,0xaf,0xb3,0x00,0x24,0xaf,0xb1,0x00,0x1c,0xaf,0xb0,0x00,0x18, +0x3c,0x02,0xb0,0x03,0x90,0x83,0x00,0x0a,0x34,0x42,0x01,0x04,0x94,0x45,0x00,0x00, +0x00,0x03,0x18,0x80,0x27,0x82,0xb3,0xf0,0x00,0x62,0x18,0x21,0x30,0xa6,0xff,0xff, +0x8c,0x71,0x00,0x00,0x80,0x85,0x00,0x12,0x30,0xc9,0x00,0xff,0x00,0x06,0x32,0x02, +0xa4,0x86,0x00,0x44,0xa4,0x89,0x00,0x46,0x82,0x22,0x00,0x12,0x00,0x80,0x90,0x21, +0x10,0xa0,0x00,0x1b,0xa0,0x80,0x00,0x15,0x00,0xc5,0x10,0x2a,0x10,0x40,0x00,0x14, +0x00,0x00,0x00,0x00,0xa2,0x20,0x00,0x19,0x84,0x83,0x00,0x0c,0x00,0x00,0x00,0x00, +0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x10, +0x00,0x43,0x10,0x21,0xa0,0x40,0x00,0x00,0xa0,0x80,0x00,0x12,0x92,0x22,0x00,0x16, +0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xdf,0xa2,0x22,0x00,0x16,0x8f,0xbf,0x00,0x28, +0x7b,0xb2,0x01,0x3c,0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x30, +0x0c,0x00,0x0f,0xfd,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x93,0x00,0x00,0x00,0x00, +0x28,0x42,0x00,0x02,0x10,0x40,0x01,0x76,0x00,0x00,0x28,0x21,0x94,0x87,0x00,0x0c, +0x00,0x00,0x00,0x00,0x00,0xe0,0x10,0x21,0x00,0x02,0x14,0x00,0x00,0x02,0x14,0x03, +0x00,0x07,0x24,0x00,0x00,0x04,0x24,0x03,0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21, +0x00,0x04,0x28,0xc0,0x00,0xa4,0x28,0x21,0x27,0x82,0x90,0x10,0x00,0x03,0x18,0x80, +0x00,0x62,0x18,0x21,0x00,0x05,0x28,0x80,0x27,0x82,0x8f,0xf8,0x00,0xa2,0x10,0x21, +0x8c,0x68,0x00,0x00,0x80,0x44,0x00,0x06,0x27,0x82,0x90,0x00,0x00,0x08,0x1d,0x02, +0x00,0xa2,0x28,0x21,0x38,0x84,0x00,0x00,0x30,0x63,0x00,0x01,0x01,0x24,0x30,0x0b, +0x80,0xaa,0x00,0x04,0x80,0xa9,0x00,0x05,0x10,0x60,0x00,0x02,0x00,0x08,0x14,0x02, +0x30,0x46,0x00,0x0f,0x15,0x20,0x00,0x28,0x01,0x49,0x10,0x21,0x15,0x40,0x00,0x11, +0x30,0xe3,0xff,0xff,0x92,0x45,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0xa8,0x00,0xff, +0x2d,0x02,0x00,0x04,0x10,0x40,0x01,0x46,0x2d,0x02,0x00,0x10,0x3c,0x04,0xb0,0x05, +0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x24,0x02,0x00,0x01,0x01,0x02,0x10,0x04, +0x00,0x62,0x18,0x25,0xa0,0x83,0x00,0x00,0x96,0x47,0x00,0x0c,0x00,0x00,0x00,0x00, +0x30,0xe3,0xff,0xff,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x27,0x84,0x90,0x00, +0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x21,0x80,0x45,0x00,0x06,0x00,0x03,0x1a,0x00, +0x3c,0x04,0xb0,0x00,0x00,0x65,0x18,0x21,0x00,0x64,0x20,0x21,0x94,0x82,0x00,0x00, +0x82,0x43,0x00,0x10,0x00,0x02,0x14,0x00,0x14,0x60,0x00,0x06,0x00,0x02,0x3c,0x03, +0x30,0xe2,0x00,0x04,0x14,0x40,0x00,0x04,0x01,0x49,0x10,0x21,0x34,0xe2,0x08,0x00, +0xa4,0x82,0x00,0x00,0x01,0x49,0x10,0x21,0x00,0x02,0x16,0x00,0x00,0x02,0x16,0x03, +0x00,0x46,0x10,0x2a,0x10,0x40,0x00,0x7c,0x00,0x00,0x00,0x00,0x82,0x42,0x00,0x10, +0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0e,0x00,0x00,0x00,0x00,0x86,0x43,0x00,0x0c, +0x25,0x44,0x00,0x01,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80, +0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0xa0,0x44,0x00,0x04,0x92,0x23,0x00,0x16, +0x02,0x40,0x20,0x21,0x30,0x63,0x00,0xfb,0x08,0x00,0x10,0x98,0xa2,0x23,0x00,0x16, +0x86,0x43,0x00,0x0c,0x25,0x24,0x00,0x01,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0xa0,0x44,0x00,0x05, +0x86,0x45,0x00,0x0c,0x0c,0x00,0x1f,0x08,0x02,0x20,0x20,0x21,0x10,0x40,0x00,0x5a, +0x00,0x00,0x00,0x00,0x92,0x45,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0xa6,0x00,0xff, +0x2c,0xc2,0x00,0x04,0x10,0x40,0x00,0x4c,0x2c,0xc2,0x00,0x10,0x3c,0x04,0xb0,0x05, +0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x24,0x02,0x00,0x01,0x00,0xc2,0x10,0x04, +0x00,0x02,0x10,0x27,0x00,0x62,0x18,0x24,0xa0,0x83,0x00,0x00,0x92,0x45,0x00,0x08, +0x00,0x00,0x00,0x00,0x30,0xa5,0x00,0xff,0x14,0xa0,0x00,0x33,0x24,0x02,0x00,0x01, +0xa2,0x40,0x00,0x04,0x92,0x22,0x00,0x04,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x0c, +0x24,0x02,0x00,0x01,0xa2,0x22,0x00,0x17,0x92,0x22,0x00,0x17,0x00,0x00,0x00,0x00, +0x10,0x40,0x00,0x04,0x00,0x00,0x00,0x00,0x96,0x22,0x00,0x06,0x08,0x00,0x10,0x93, +0xa6,0x22,0x00,0x14,0x96,0x22,0x00,0x00,0x08,0x00,0x10,0x93,0xa6,0x22,0x00,0x14, +0x92,0x22,0x00,0x0a,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x03,0x00,0x00,0x00,0x00, +0x08,0x00,0x11,0x22,0xa2,0x20,0x00,0x17,0x96,0x24,0x00,0x00,0x96,0x25,0x00,0x06, +0x27,0x86,0x8f,0xf0,0x00,0x04,0x18,0xc0,0x00,0x64,0x18,0x21,0x00,0x05,0x10,0xc0, +0x00,0x45,0x10,0x21,0x00,0x03,0x18,0x80,0x00,0x66,0x18,0x21,0x00,0x02,0x10,0x80, +0x00,0x46,0x10,0x21,0x8c,0x65,0x00,0x08,0x8c,0x44,0x00,0x08,0x3c,0x03,0x80,0x00, +0x00,0xa3,0x30,0x24,0x10,0xc0,0x00,0x08,0x00,0x83,0x10,0x24,0x10,0x40,0x00,0x04, +0x00,0x00,0x18,0x21,0x10,0xc0,0x00,0x02,0x24,0x03,0x00,0x01,0x00,0x85,0x18,0x2b, +0x08,0x00,0x11,0x22,0xa2,0x23,0x00,0x17,0x10,0x40,0xff,0xfd,0x00,0x85,0x18,0x2b, +0x08,0x00,0x11,0x45,0x00,0x00,0x00,0x00,0x10,0xa2,0x00,0x09,0x24,0x02,0x00,0x02, +0x10,0xa2,0x00,0x05,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xca,0x00,0x00,0x00,0x00, +0x08,0x00,0x11,0x1d,0xa2,0x40,0x00,0x07,0x08,0x00,0x11,0x1d,0xa2,0x40,0x00,0x06, +0x08,0x00,0x11,0x1d,0xa2,0x40,0x00,0x05,0x14,0x40,0xff,0xbe,0x3c,0x04,0xb0,0x05, +0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x30,0xa5,0x00,0x0f,0x24,0x02,0x00,0x80, +0x08,0x00,0x11,0x14,0x00,0xa2,0x10,0x07,0x0c,0x00,0x10,0x03,0x02,0x40,0x20,0x21, +0x08,0x00,0x10,0x93,0x00,0x00,0x00,0x00,0x92,0x45,0x00,0x08,0x00,0x00,0x00,0x00, +0x30,0xa6,0x00,0xff,0x2c,0xc2,0x00,0x04,0x10,0x40,0x00,0x99,0x2c,0xc2,0x00,0x10, +0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x24,0x02,0x00,0x01, +0x00,0xc2,0x10,0x04,0x00,0x02,0x10,0x27,0x00,0x62,0x18,0x24,0xa0,0x83,0x00,0x00, +0x92,0x45,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0xa5,0x00,0xff,0x14,0xa0,0x00,0x80, +0x24,0x02,0x00,0x01,0xa2,0x40,0x00,0x04,0x86,0x43,0x00,0x0c,0x27,0x93,0x8f,0xf4, +0x96,0x47,0x00,0x0c,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x28,0x80, +0x00,0xb3,0x18,0x21,0x8c,0x64,0x00,0x18,0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x04, +0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x10,0x10,0x40,0x00,0x64,0x00,0x00,0x30,0x21, +0x00,0x07,0x1c,0x00,0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +0x00,0x02,0x10,0x80,0x00,0x53,0x10,0x21,0x8c,0x43,0x00,0x18,0x93,0x82,0x8b,0x61, +0x8c,0x64,0x00,0x04,0x30,0x42,0x00,0x01,0x00,0x04,0x21,0x42,0x14,0x40,0x00,0x4d, +0x30,0x90,0x00,0x01,0x00,0x07,0x2c,0x00,0x00,0x05,0x2c,0x03,0x0c,0x00,0x1b,0x84, +0x02,0x20,0x20,0x21,0x96,0x26,0x00,0x06,0x12,0x00,0x00,0x14,0x30,0xc5,0xff,0xff, +0x02,0x60,0x90,0x21,0x00,0x05,0x10,0xc0,0x00,0x45,0x10,0x21,0x00,0x02,0x10,0x80, +0x00,0x52,0x18,0x21,0x92,0x22,0x00,0x0a,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0b, +0x02,0x20,0x20,0x21,0x8c,0x63,0x00,0x18,0x00,0x00,0x00,0x00,0x8c,0x62,0x00,0x04, +0x00,0x00,0x00,0x00,0x00,0x02,0x11,0x42,0x0c,0x00,0x1b,0x84,0x30,0x50,0x00,0x01, +0x96,0x26,0x00,0x06,0x16,0x00,0xff,0xef,0x30,0xc5,0xff,0xff,0x92,0x22,0x00,0x04, +0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x0d,0x24,0x02,0x00,0x01,0xa2,0x22,0x00,0x17, +0x92,0x22,0x00,0x17,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x05,0x00,0x00,0x00,0x00, +0xa6,0x26,0x00,0x14,0x92,0x22,0x00,0x16,0x08,0x00,0x10,0x92,0x30,0x42,0x00,0xc3, +0x96,0x22,0x00,0x00,0x08,0x00,0x11,0xb9,0xa6,0x22,0x00,0x14,0x92,0x22,0x00,0x0a, +0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0x11,0xb4, +0xa2,0x20,0x00,0x17,0x96,0x24,0x00,0x00,0x30,0xc5,0xff,0xff,0x00,0x05,0x18,0xc0, +0x00,0x04,0x10,0xc0,0x00,0x44,0x10,0x21,0x00,0x65,0x18,0x21,0x27,0x84,0x8f,0xf0, +0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x21,0x00,0x03,0x18,0x80,0x8c,0x45,0x00,0x08, +0x00,0x64,0x18,0x21,0x8c,0x64,0x00,0x08,0x3c,0x02,0x80,0x00,0x00,0xa2,0x38,0x24, +0x10,0xe0,0x00,0x08,0x00,0x82,0x10,0x24,0x10,0x40,0x00,0x04,0x00,0x00,0x18,0x21, +0x10,0xe0,0x00,0x02,0x24,0x03,0x00,0x01,0x00,0x85,0x18,0x2b,0x08,0x00,0x11,0xb4, +0xa2,0x23,0x00,0x17,0x10,0x40,0xff,0xfd,0x00,0x85,0x18,0x2b,0x08,0x00,0x11,0xd8, +0x00,0x00,0x00,0x00,0x24,0x05,0x00,0x24,0xf0,0xe5,0x00,0x06,0x00,0x00,0x28,0x12, +0x27,0x82,0x8f,0xf0,0x00,0xa2,0x28,0x21,0x0c,0x00,0x01,0x4b,0x00,0x00,0x20,0x21, +0x96,0x47,0x00,0x0c,0x08,0x00,0x11,0x96,0x00,0x07,0x2c,0x00,0x27,0x83,0x90,0x00, +0x27,0x82,0x90,0x08,0x00,0xa2,0x10,0x21,0x00,0xa3,0x18,0x21,0x90,0x44,0x00,0x00, +0x90,0x65,0x00,0x05,0x93,0x82,0x80,0x10,0x24,0x07,0x00,0x01,0x0c,0x00,0x21,0xf5, +0xaf,0xa2,0x00,0x10,0x96,0x47,0x00,0x0c,0x08,0x00,0x11,0x89,0x00,0x07,0x1c,0x00, +0x10,0xa2,0x00,0x09,0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x05,0x24,0x02,0x00,0x03, +0x14,0xa2,0xff,0x7d,0x00,0x00,0x00,0x00,0x08,0x00,0x11,0x7a,0xa2,0x40,0x00,0x07, +0x08,0x00,0x11,0x7a,0xa2,0x40,0x00,0x06,0x08,0x00,0x11,0x7a,0xa2,0x40,0x00,0x05, +0x14,0x40,0xff,0x71,0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00, +0x30,0xa5,0x00,0x0f,0x24,0x02,0x00,0x80,0x08,0x00,0x11,0x71,0x00,0xa2,0x10,0x07, +0x14,0x40,0xfe,0xc3,0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00, +0x30,0xa5,0x00,0x0f,0x24,0x02,0x00,0x80,0x08,0x00,0x10,0xcc,0x00,0xa2,0x10,0x07, +0x84,0x83,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +0x00,0x02,0x10,0x80,0x27,0x83,0x8f,0xf4,0x00,0x43,0x10,0x21,0x8c,0x47,0x00,0x18, +0x00,0x00,0x00,0x00,0x8c,0xe6,0x00,0x08,0x0c,0x00,0x0f,0x15,0x00,0x00,0x00,0x00, +0x02,0x40,0x20,0x21,0x00,0x00,0x28,0x21,0x00,0x00,0x30,0x21,0x00,0x00,0x38,0x21, +0x0c,0x00,0x1c,0x86,0xaf,0xa2,0x00,0x10,0x00,0x02,0x1e,0x00,0x14,0x60,0xfe,0x6b, +0xa2,0x22,0x00,0x12,0x92,0x43,0x00,0x08,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x40, +0x24,0x02,0x00,0x01,0xa2,0x40,0x00,0x04,0x92,0x28,0x00,0x04,0x00,0x00,0x00,0x00, +0x15,0x00,0x00,0x19,0x24,0x02,0x00,0x01,0x92,0x27,0x00,0x0a,0xa2,0x22,0x00,0x17, +0x92,0x22,0x00,0x17,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x10,0x00,0x00,0x00,0x00, +0x96,0x22,0x00,0x06,0x00,0x00,0x00,0x00,0xa6,0x22,0x00,0x14,0x92,0x22,0x00,0x16, +0x30,0xe3,0x00,0xff,0x30,0x42,0x00,0xc0,0x10,0x60,0x00,0x03,0xa2,0x22,0x00,0x16, +0x34,0x42,0x00,0x01,0xa2,0x22,0x00,0x16,0x11,0x00,0xfe,0x50,0x00,0x00,0x00,0x00, +0x92,0x22,0x00,0x16,0x08,0x00,0x10,0x92,0x34,0x42,0x00,0x02,0x96,0x22,0x00,0x00, +0x08,0x00,0x12,0x3b,0xa6,0x22,0x00,0x14,0x92,0x27,0x00,0x0a,0x00,0x00,0x00,0x00, +0x14,0xe0,0x00,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0x12,0x34,0xa2,0x20,0x00,0x17, +0x96,0x24,0x00,0x00,0x96,0x25,0x00,0x06,0x27,0x86,0x8f,0xf0,0x00,0x04,0x18,0xc0, +0x00,0x64,0x18,0x21,0x00,0x05,0x10,0xc0,0x00,0x45,0x10,0x21,0x00,0x03,0x18,0x80, +0x00,0x66,0x18,0x21,0x00,0x02,0x10,0x80,0x00,0x46,0x10,0x21,0x8c,0x65,0x00,0x08, +0x8c,0x44,0x00,0x08,0x3c,0x03,0x80,0x00,0x00,0xa3,0x30,0x24,0x10,0xc0,0x00,0x08, +0x00,0x83,0x10,0x24,0x10,0x40,0x00,0x04,0x00,0x00,0x18,0x21,0x10,0xc0,0x00,0x02, +0x24,0x03,0x00,0x01,0x00,0x85,0x18,0x2b,0x08,0x00,0x12,0x34,0xa2,0x23,0x00,0x17, +0x10,0x40,0xff,0xfd,0x00,0x85,0x18,0x2b,0x08,0x00,0x12,0x63,0x00,0x00,0x00,0x00, +0x10,0x62,0x00,0x09,0x24,0x02,0x00,0x02,0x10,0x62,0x00,0x05,0x24,0x02,0x00,0x03, +0x14,0x62,0xff,0xbd,0x00,0x00,0x00,0x00,0x08,0x00,0x12,0x2e,0xa2,0x40,0x00,0x07, +0x08,0x00,0x12,0x2e,0xa2,0x40,0x00,0x06,0x08,0x00,0x12,0x2e,0xa2,0x40,0x00,0x05, +0x3c,0x02,0x80,0x00,0x00,0x82,0x30,0x24,0x10,0xc0,0x00,0x08,0x00,0xa2,0x18,0x24, +0x10,0x60,0x00,0x04,0x00,0x00,0x10,0x21,0x10,0xc0,0x00,0x02,0x24,0x02,0x00,0x01, +0x00,0xa4,0x10,0x2b,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x10,0x60,0xff,0xfd, +0x00,0xa4,0x10,0x2b,0x08,0x00,0x12,0x7e,0x00,0x00,0x00,0x00,0x30,0x82,0xff,0xff, +0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21,0x27,0x84,0x90,0x00,0x00,0x03,0x18,0x80, +0x00,0x64,0x18,0x21,0x80,0x66,0x00,0x06,0x00,0x02,0x12,0x00,0x3c,0x03,0xb0,0x00, +0x00,0x46,0x10,0x21,0x00,0x45,0x10,0x21,0x03,0xe0,0x00,0x08,0x00,0x43,0x10,0x21, +0x27,0xbd,0xff,0xe0,0x30,0x82,0x00,0x7c,0x30,0x84,0xff,0x00,0xaf,0xbf,0x00,0x1c, +0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0x14,0x40,0x00,0x41, +0x00,0x04,0x22,0x03,0x24,0x02,0x00,0x04,0x3c,0x10,0xb0,0x03,0x8e,0x10,0x00,0x00, +0x10,0x82,0x00,0x32,0x24,0x02,0x00,0x08,0x10,0x82,0x00,0x03,0x32,0x02,0x00,0x20, +0x08,0x00,0x12,0xa4,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x17,0x3c,0x02,0xb0,0x06, +0x34,0x42,0x80,0x24,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x67,0x00,0xff, +0x10,0xe0,0x00,0x23,0x00,0x00,0x88,0x21,0x8f,0x85,0x8f,0xd0,0x00,0x40,0x30,0x21, +0x94,0xa2,0x00,0x08,0x8c,0xc3,0x00,0x00,0x26,0x31,0x00,0x01,0x24,0x42,0x00,0x02, +0x30,0x42,0x01,0xff,0x34,0x63,0x01,0x00,0x02,0x27,0x20,0x2a,0xa4,0xa2,0x00,0x08, +0x14,0x80,0xff,0xf7,0xac,0xc3,0x00,0x00,0x84,0xa3,0x00,0x08,0x3c,0x02,0xb0,0x03, +0x34,0x42,0x00,0x30,0xac,0x43,0x00,0x00,0x27,0x92,0xb3,0xf0,0x24,0x11,0x00,0x12, +0x8e,0x44,0x00,0x00,0x26,0x31,0xff,0xff,0x90,0x82,0x00,0x10,0x00,0x00,0x00,0x00, +0x10,0x40,0x00,0x03,0x26,0x52,0x00,0x04,0x0c,0x00,0x20,0xd0,0x00,0x00,0x00,0x00, +0x06,0x21,0xff,0xf7,0x24,0x02,0xff,0xdf,0x02,0x02,0x80,0x24,0x3c,0x01,0xb0,0x03, +0x0c,0x00,0x13,0x18,0xac,0x30,0x00,0x00,0x08,0x00,0x12,0xa4,0x00,0x00,0x00,0x00, +0x8f,0x85,0x8f,0xd0,0x08,0x00,0x12,0xba,0x00,0x00,0x00,0x00,0x24,0x02,0xff,0x95, +0x3c,0x03,0xb0,0x03,0x02,0x02,0x80,0x24,0x34,0x63,0x00,0x30,0x3c,0x01,0xb0,0x03, +0xac,0x30,0x00,0x00,0x0c,0x00,0x12,0xe1,0xac,0x60,0x00,0x00,0x08,0x00,0x12,0xa4, +0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x50,0x08,0x00,0x12,0xa4, +0xac,0x46,0x00,0x00,0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4b,0x84,0x3c,0x0b,0xb0,0x03, +0xad,0x6a,0x00,0x20,0x3c,0x08,0x80,0x01,0x25,0x08,0x00,0x00,0x3c,0x09,0x80,0x01, +0x25,0x29,0x03,0x1c,0x11,0x09,0x00,0x10,0x00,0x00,0x00,0x00,0x3c,0x0a,0x80,0x00, +0x25,0x4a,0x4b,0xac,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20,0x3c,0x08,0xb0,0x06, +0x35,0x08,0x80,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8d,0x09,0x00,0x00, +0x00,0x00,0x00,0x00,0x31,0x29,0x00,0x01,0x00,0x00,0x00,0x00,0x24,0x01,0x00,0x01, +0x15,0x21,0xff,0xf2,0x00,0x00,0x00,0x00,0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4b,0xe8, +0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20,0x3c,0x02,0xb0,0x03,0x8c,0x43,0x00,0x00, +0x00,0x00,0x00,0x00,0x34,0x63,0x00,0x40,0x00,0x00,0x00,0x00,0xac,0x43,0x00,0x00, +0x00,0x00,0x00,0x00,0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4c,0x14,0x3c,0x0b,0xb0,0x03, +0xad,0x6a,0x00,0x20,0x3c,0x02,0x80,0x01,0x24,0x42,0x00,0x00,0x3c,0x03,0x80,0x01, +0x24,0x63,0x03,0x1c,0x3c,0x04,0xb0,0x00,0x8c,0x85,0x00,0x00,0x00,0x00,0x00,0x00, +0xac,0x45,0x00,0x00,0x24,0x42,0x00,0x04,0x24,0x84,0x00,0x04,0x00,0x43,0x08,0x2a, +0x14,0x20,0xff,0xf9,0x00,0x00,0x00,0x00,0x0c,0x00,0x13,0x18,0x00,0x00,0x00,0x00, +0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4c,0x60,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20, +0x3c,0x02,0x80,0x01,0x24,0x42,0x03,0x20,0x3c,0x03,0x80,0x01,0x24,0x63,0x3f,0x14, +0xac,0x40,0x00,0x00,0xac,0x40,0x00,0x04,0xac,0x40,0x00,0x08,0xac,0x40,0x00,0x0c, +0x24,0x42,0x00,0x10,0x00,0x43,0x08,0x2a,0x14,0x20,0xff,0xf9,0x00,0x00,0x00,0x00, +0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4c,0xa0,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20, +0x3c,0x1c,0x80,0x01,0x27,0x9c,0x7f,0xf0,0x27,0x9d,0x8b,0xd0,0x00,0x00,0x00,0x00, +0x27,0x9d,0x8f,0xb8,0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4c,0xc4,0x3c,0x0b,0xb0,0x03, +0xad,0x6a,0x00,0x20,0x40,0x80,0x68,0x00,0x40,0x08,0x60,0x00,0x00,0x00,0x00,0x00, +0x35,0x08,0xff,0x01,0x40,0x88,0x60,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x15,0x65, +0x00,0x00,0x00,0x00,0x24,0x84,0xf8,0x00,0x30,0x87,0x00,0x03,0x00,0x04,0x30,0x40, +0x00,0xc7,0x20,0x23,0x3c,0x02,0xb0,0x0a,0x27,0xbd,0xff,0xe0,0x24,0x03,0xff,0xff, +0x00,0x82,0x20,0x21,0xaf,0xb1,0x00,0x14,0xac,0x83,0x10,0x00,0xaf,0xbf,0x00,0x18, +0xaf,0xb0,0x00,0x10,0x00,0xa0,0x88,0x21,0x24,0x03,0x00,0x01,0x8c,0x82,0x10,0x00, +0x00,0x00,0x00,0x00,0x14,0x43,0xff,0xfd,0x00,0xc7,0x10,0x23,0x3c,0x03,0xb0,0x0a, +0x00,0x43,0x10,0x21,0x8c,0x50,0x00,0x00,0x0c,0x00,0x13,0x95,0x02,0x20,0x20,0x21, +0x02,0x11,0x80,0x24,0x00,0x50,0x80,0x06,0x02,0x00,0x10,0x21,0x8f,0xbf,0x00,0x18, +0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x27,0xbd,0xff,0xd8, +0xaf,0xb2,0x00,0x18,0x00,0xa0,0x90,0x21,0x24,0x05,0xff,0xff,0xaf,0xb3,0x00,0x1c, +0xaf,0xbf,0x00,0x20,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0x00,0xc0,0x98,0x21, +0x12,0x45,0x00,0x23,0x24,0x84,0xf8,0x00,0x30,0x83,0x00,0x03,0x00,0x04,0x10,0x40, +0x00,0x40,0x88,0x21,0x00,0x60,0x20,0x21,0x00,0x43,0x10,0x23,0x3c,0x03,0xb0,0x0a, +0x00,0x43,0x10,0x21,0xac,0x45,0x10,0x00,0x00,0x40,0x18,0x21,0x24,0x05,0x00,0x01, +0x8c,0x62,0x10,0x00,0x00,0x00,0x00,0x00,0x14,0x45,0xff,0xfd,0x3c,0x02,0xb0,0x0a, +0x02,0x24,0x88,0x23,0x02,0x22,0x88,0x21,0x8e,0x30,0x00,0x00,0x0c,0x00,0x13,0x95, +0x02,0x40,0x20,0x21,0x00,0x12,0x18,0x27,0x02,0x03,0x80,0x24,0x00,0x53,0x10,0x04, +0x02,0x02,0x80,0x25,0xae,0x30,0x00,0x00,0x24,0x03,0x00,0x01,0x8e,0x22,0x10,0x00, +0x00,0x00,0x00,0x00,0x14,0x43,0xff,0xfd,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x20, +0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28, +0x30,0x82,0x00,0x03,0x00,0x04,0x18,0x40,0x00,0x62,0x18,0x23,0x3c,0x04,0xb0,0x0a, +0x00,0x64,0x18,0x21,0xac,0x66,0x00,0x00,0x24,0x04,0x00,0x01,0x8c,0x62,0x10,0x00, +0x00,0x00,0x00,0x00,0x14,0x44,0xff,0xfd,0x00,0x00,0x00,0x00,0x08,0x00,0x13,0x83, +0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x21,0x00,0x64,0x10,0x06,0x30,0x42,0x00,0x01, +0x14,0x40,0x00,0x05,0x00,0x00,0x00,0x00,0x24,0x63,0x00,0x01,0x2c,0x62,0x00,0x20, +0x14,0x40,0xff,0xf9,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x60,0x10,0x21, +0x27,0xbd,0xff,0xe0,0x3c,0x03,0xb0,0x05,0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14, +0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x1c,0x00,0x80,0x90,0x21,0x00,0xa0,0x80,0x21, +0x00,0xc0,0x88,0x21,0x34,0x63,0x02,0x2e,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x42,0x00,0x01,0x14,0x40,0xff,0xfc,0x24,0x04,0x08,0x24,0x3c,0x05,0x00,0xc0, +0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x03,0x24,0x04,0x08,0x34,0x3c,0x05,0x00,0xc0, +0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x03,0x3c,0x02,0xc0,0x00,0x00,0x10,0x1c,0x00, +0x34,0x42,0x04,0x00,0x3c,0x04,0xb0,0x05,0x3c,0x05,0xb0,0x05,0x24,0x63,0x16,0x09, +0x02,0x22,0x10,0x21,0x34,0x84,0x04,0x20,0x34,0xa5,0x04,0x24,0x3c,0x06,0xb0,0x05, +0xac,0x83,0x00,0x00,0x24,0x07,0x00,0x01,0xac,0xa2,0x00,0x00,0x34,0xc6,0x02,0x28, +0x24,0x02,0x00,0x20,0xae,0x47,0x00,0x3c,0x24,0x04,0x08,0x24,0xa0,0xc2,0x00,0x00, +0x3c,0x05,0x00,0xc0,0xa2,0x47,0x00,0x11,0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x01, +0x24,0x04,0x08,0x34,0x3c,0x05,0x00,0xc0,0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x01, +0x8f,0xbf,0x00,0x1c,0x8f,0xb2,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x20,0x24,0x02,0x00,0x06,0xac,0x82,0x00,0x0c,0xa0,0x80,0x00,0x50, +0xac,0x80,0x00,0x00,0xac,0x80,0x00,0x04,0xac,0x80,0x00,0x08,0xac,0x80,0x00,0x14, +0xac,0x80,0x00,0x18,0xac,0x80,0x00,0x1c,0xa4,0x80,0x00,0x20,0xac,0x80,0x00,0x24, +0xac,0x80,0x00,0x28,0xac,0x80,0x00,0x2c,0xa0,0x80,0x00,0x30,0xa0,0x80,0x00,0x31, +0xac,0x80,0x00,0x34,0xac,0x80,0x00,0x38,0xa0,0x80,0x00,0x3c,0xac,0x82,0x00,0x10, +0xa0,0x80,0x00,0x44,0xac,0x80,0x00,0x48,0x03,0xe0,0x00,0x08,0xac,0x80,0x00,0x4c, +0x3c,0x04,0xb0,0x06,0x34,0x84,0x80,0x00,0x8c,0x83,0x00,0x00,0x3c,0x02,0x12,0x00, +0x3c,0x05,0xb0,0x03,0x00,0x62,0x18,0x25,0x34,0xa5,0x00,0x8b,0x24,0x02,0xff,0x80, +0xac,0x83,0x00,0x00,0x03,0xe0,0x00,0x08,0xa0,0xa2,0x00,0x00,0x3c,0x04,0xb0,0x03, +0x34,0x84,0x00,0x0b,0x24,0x02,0x00,0x22,0x3c,0x05,0xb0,0x01,0x3c,0x06,0x45,0x67, +0x3c,0x0a,0xb0,0x09,0xa0,0x82,0x00,0x00,0x34,0xa5,0x00,0x04,0x34,0xc6,0x89,0xaa, +0x35,0x4a,0x00,0x04,0x24,0x02,0x01,0x23,0x3c,0x0b,0xb0,0x09,0x3c,0x07,0x01,0x23, +0x3c,0x0c,0xb0,0x09,0x3c,0x01,0xb0,0x01,0xac,0x20,0x00,0x00,0x27,0xbd,0xff,0xe0, +0xac,0xa0,0x00,0x00,0x35,0x6b,0x00,0x08,0x3c,0x01,0xb0,0x09,0xac,0x26,0x00,0x00, +0x34,0xe7,0x45,0x66,0xa5,0x42,0x00,0x00,0x35,0x8c,0x00,0x0c,0x24,0x02,0xcd,0xef, +0x3c,0x0d,0xb0,0x09,0x3c,0x08,0xcd,0xef,0x3c,0x0e,0xb0,0x09,0xad,0x67,0x00,0x00, +0xaf,0xb7,0x00,0x1c,0xa5,0x82,0x00,0x00,0xaf,0xb6,0x00,0x18,0xaf,0xb5,0x00,0x14, +0xaf,0xb4,0x00,0x10,0xaf,0xb3,0x00,0x0c,0xaf,0xb2,0x00,0x08,0xaf,0xb1,0x00,0x04, +0xaf,0xb0,0x00,0x00,0x35,0xad,0x00,0x10,0x35,0x08,0x01,0x22,0x35,0xce,0x00,0x14, +0x24,0x02,0x89,0xab,0x3c,0x0f,0xb0,0x09,0x3c,0x09,0x89,0xab,0x3c,0x10,0xb0,0x09, +0x3c,0x11,0xb0,0x09,0x3c,0x12,0xb0,0x09,0x3c,0x13,0xb0,0x09,0x3c,0x14,0xb0,0x09, +0x3c,0x15,0xb0,0x09,0x3c,0x16,0xb0,0x09,0x3c,0x17,0xb0,0x09,0xad,0xa8,0x00,0x00, +0x24,0x03,0xff,0xff,0xa5,0xc2,0x00,0x00,0x35,0xef,0x00,0x18,0x35,0x29,0xcd,0xee, +0x36,0x10,0x00,0x1c,0x36,0x31,0x00,0x20,0x36,0x52,0x00,0x24,0x36,0x73,0x00,0x28, +0x36,0x94,0x00,0x2c,0x36,0xb5,0x00,0x30,0x36,0xd6,0x00,0x34,0x36,0xf7,0x00,0x38, +0x24,0x02,0x45,0x67,0xad,0xe9,0x00,0x00,0xa6,0x02,0x00,0x00,0xae,0x23,0x00,0x00, +0x8f,0xb0,0x00,0x00,0xa6,0x43,0x00,0x00,0x8f,0xb1,0x00,0x04,0xae,0x63,0x00,0x00, +0x8f,0xb2,0x00,0x08,0xa6,0x83,0x00,0x00,0x8f,0xb3,0x00,0x0c,0xae,0xa3,0x00,0x00, +0x8f,0xb4,0x00,0x10,0xa6,0xc3,0x00,0x00,0x8f,0xb5,0x00,0x14,0xae,0xe3,0x00,0x00, +0x7b,0xb6,0x00,0xfc,0x3c,0x18,0xb0,0x09,0x37,0x18,0x00,0x3c,0xa7,0x03,0x00,0x00, +0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00, +0x34,0x63,0x00,0x20,0x24,0x42,0x51,0x38,0xac,0x62,0x00,0x00,0x8c,0x83,0x00,0x34, +0x34,0x02,0xff,0xff,0x00,0x43,0x10,0x2a,0x14,0x40,0x01,0x0b,0x00,0x80,0x30,0x21, +0x8c,0x84,0x00,0x08,0x24,0x02,0x00,0x03,0x10,0x82,0x00,0xfe,0x00,0x00,0x00,0x00, +0x8c,0xc2,0x00,0x2c,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x47,0x24,0x02,0x00,0x06, +0x3c,0x03,0xb0,0x05,0x34,0x63,0x04,0x50,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x42,0x00,0xff,0x14,0x40,0x00,0xe4,0xac,0xc2,0x00,0x2c,0x24,0x02,0x00,0x01, +0x10,0x82,0x00,0xe3,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0x82,0x00,0xd1, +0x00,0x00,0x00,0x00,0x8c,0xc7,0x00,0x04,0x24,0x02,0x00,0x02,0x10,0xe2,0x00,0xc7, +0x00,0x00,0x00,0x00,0x8c,0xc2,0x00,0x14,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x09, +0x24,0x02,0x00,0x01,0x3c,0x03,0xb0,0x09,0x34,0x63,0x01,0x60,0x90,0x62,0x00,0x00, +0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0x10,0x40,0x00,0x05,0xac,0xc2,0x00,0x14, +0x24,0x02,0x00,0x01,0xac,0xc2,0x00,0x00,0x03,0xe0,0x00,0x08,0xac,0xc0,0x00,0x14, +0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xd0,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00, +0x04,0x61,0x00,0x16,0x3c,0x03,0xb0,0x05,0x34,0x63,0x02,0x2e,0x90,0x62,0x00,0x00, +0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x14,0x40,0x00,0x10,0x3c,0x02,0xb0,0x05, +0x34,0x42,0x02,0x42,0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x0b, +0x00,0x00,0x00,0x00,0x80,0xc2,0x00,0x50,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x07, +0x00,0x00,0x00,0x00,0x14,0x80,0x00,0x05,0x24,0x02,0x00,0x0e,0x24,0x03,0x00,0x01, +0xac,0xc2,0x00,0x00,0x03,0xe0,0x00,0x08,0xa0,0xc3,0x00,0x50,0x80,0xc2,0x00,0x31, +0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0a,0x3c,0x02,0xb0,0x06,0x34,0x42,0x80,0x18, +0x8c,0x43,0x00,0x00,0x3c,0x04,0xf0,0x00,0x3c,0x02,0x80,0x00,0x00,0x64,0x18,0x24, +0x10,0x62,0x00,0x03,0x24,0x02,0x00,0x09,0x03,0xe0,0x00,0x08,0xac,0xc2,0x00,0x00, +0x8c,0xc2,0x00,0x40,0x00,0x00,0x00,0x00,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00, +0x10,0x60,0x00,0x09,0x3c,0x03,0xb0,0x03,0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2c, +0x8c,0x43,0x00,0x00,0x3c,0x04,0x00,0x02,0x00,0x64,0x18,0x24,0x14,0x60,0xff,0xf2, +0x24,0x02,0x00,0x10,0x3c,0x03,0xb0,0x03,0x34,0x63,0x02,0x01,0x90,0x62,0x00,0x00, +0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x80,0x10,0x40,0x00,0x0e,0x00,0x00,0x00,0x00, +0x8c,0xc3,0x00,0x0c,0x00,0x00,0x00,0x00,0xac,0xc3,0x00,0x10,0x3c,0x02,0xb0,0x03, +0x90,0x42,0x02,0x01,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x0f,0xac,0xc2,0x00,0x0c, +0x90,0xc3,0x00,0x0f,0x24,0x02,0x00,0x0d,0x3c,0x01,0xb0,0x03,0x08,0x00,0x14,0xa6, +0xa0,0x23,0x02,0x01,0x3c,0x02,0xb0,0x09,0x34,0x42,0x01,0x80,0x90,0x44,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x04,0x1e,0x00,0x00,0x03,0x1e,0x03,0x10,0x60,0x00,0x15, +0xa0,0xc4,0x00,0x44,0x24,0x02,0x00,0x01,0x10,0x62,0x00,0x0b,0x24,0x02,0x00,0x02, +0x10,0x62,0x00,0x03,0x24,0x03,0x00,0x0d,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +0x8c,0xc2,0x00,0x0c,0xac,0xc3,0x00,0x00,0x24,0x03,0x00,0x04,0xac,0xc2,0x00,0x10, +0x03,0xe0,0x00,0x08,0xac,0xc3,0x00,0x0c,0x24,0x02,0x00,0x0d,0xac,0xc2,0x00,0x00, +0x24,0x03,0x00,0x04,0x24,0x02,0x00,0x06,0xac,0xc3,0x00,0x10,0x03,0xe0,0x00,0x08, +0xac,0xc2,0x00,0x0c,0x8c,0xc3,0x00,0x38,0x00,0x00,0x00,0x00,0x2c,0x62,0x00,0x06, +0x10,0x40,0x00,0x2e,0x00,0x03,0x10,0x80,0x3c,0x03,0x80,0x01,0x24,0x63,0x02,0x00, +0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x08, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xe2,0x00,0x06,0x24,0x02,0x00,0x03, +0x8c,0xa2,0x02,0xbc,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x06,0x3c,0x03,0xb0,0x06, +0x24,0x02,0x00,0x02,0xac,0xc2,0x00,0x00,0x24,0x02,0x00,0x01,0x03,0xe0,0x00,0x08, +0xac,0xc2,0x00,0x38,0x34,0x63,0x80,0x24,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x42,0x00,0xff,0x10,0x40,0x00,0x05,0xac,0xc2,0x00,0x18,0x24,0x02,0x00,0x02, +0xac,0xc2,0x00,0x00,0x08,0x00,0x14,0xfa,0xac,0xc0,0x00,0x18,0x08,0x00,0x14,0xfa, +0xac,0xc0,0x00,0x00,0x24,0x02,0x00,0x02,0x24,0x03,0x00,0x0b,0xac,0xc2,0x00,0x38, +0x03,0xe0,0x00,0x08,0xac,0xc3,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xe2,0x00,0x05, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x0c,0xac,0xc2,0x00,0x00,0x08,0x00,0x14,0xfb, +0x24,0x02,0x00,0x04,0x08,0x00,0x15,0x12,0x24,0x02,0x00,0x03,0xac,0xc0,0x00,0x38, +0x03,0xe0,0x00,0x08,0xac,0xc0,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xe2,0x00,0x05, +0x24,0x02,0x00,0x03,0x80,0xc2,0x00,0x30,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x08, +0x24,0x02,0x00,0x04,0xac,0xc2,0x00,0x00,0x93,0x82,0x86,0x3c,0x00,0x00,0x00,0x00, +0x14,0x40,0xff,0xd6,0x24,0x02,0x00,0x05,0x03,0xe0,0x00,0x08,0xac,0xc0,0x00,0x38, +0x08,0x00,0x15,0x22,0xac,0xc0,0x00,0x00,0x3c,0x02,0xb0,0x06,0x34,0x42,0x80,0x18, +0x8c,0x43,0x00,0x00,0x3c,0x04,0xf0,0x00,0x3c,0x02,0x80,0x00,0x00,0x64,0x18,0x24, +0x10,0x62,0x00,0x03,0x24,0x02,0x00,0x09,0x08,0x00,0x15,0x26,0xac,0xc2,0x00,0x00, +0x24,0x02,0x00,0x05,0x08,0x00,0x15,0x18,0xac,0xc2,0x00,0x38,0x80,0xc2,0x00,0x30, +0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x37,0x24,0x02,0x00,0x04,0x08,0x00,0x14,0xa6, +0x00,0x00,0x00,0x00,0x84,0xc2,0x00,0x20,0x00,0x00,0x00,0x00,0x10,0x40,0xff,0x66, +0x24,0x02,0x00,0x06,0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2e,0x90,0x43,0x00,0x00, +0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x01,0x30,0x63,0x00,0xff,0x00,0x60,0x10,0x21, +0x14,0x40,0xff,0x24,0xa4,0xc3,0x00,0x20,0x08,0x00,0x14,0xa6,0x24,0x02,0x00,0x06, +0x8c,0xc2,0x00,0x1c,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x57,0x24,0x02,0x00,0x05, +0x3c,0x03,0xb0,0x05,0x34,0x63,0x02,0x2c,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x42,0x00,0xff,0x10,0x40,0xff,0x14,0xac,0xc2,0x00,0x1c,0x08,0x00,0x14,0xa6, +0x24,0x02,0x00,0x05,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x02,0x17,0x42,0x30,0x42,0x00,0x01,0x14,0x40,0xff,0x47,0x24,0x02,0x00,0x06, +0x08,0x00,0x14,0x5c,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x0a,0x03,0xe0,0x00,0x08, +0xac,0x82,0x00,0x00,0x27,0xbd,0xff,0xd8,0xaf,0xb0,0x00,0x10,0x27,0x90,0x86,0x48, +0xaf,0xbf,0x00,0x20,0xaf,0xb3,0x00,0x1c,0xaf,0xb2,0x00,0x18,0x0c,0x00,0x2b,0xe8, +0xaf,0xb1,0x00,0x14,0xaf,0x90,0x8f,0xd0,0x48,0x02,0x00,0x00,0x0c,0x00,0x13,0xec, +0x00,0x00,0x00,0x00,0x0c,0x00,0x18,0x4e,0x02,0x00,0x20,0x21,0x0c,0x00,0x00,0x34, +0x00,0x00,0x00,0x00,0x0c,0x00,0x13,0xf7,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x68, +0x0c,0x00,0x27,0xc1,0x00,0x00,0x00,0x00,0x93,0x84,0x80,0x10,0x0c,0x00,0x21,0x9a, +0x00,0x00,0x00,0x00,0x27,0x84,0x89,0x08,0x0c,0x00,0x06,0xe1,0x00,0x00,0x00,0x00, +0x0c,0x00,0x01,0x3b,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x10,0x0c,0x00,0x13,0xd5, +0x00,0x00,0x00,0x00,0x27,0x82,0x89,0x3c,0xaf,0x82,0x84,0x50,0x0c,0x00,0x00,0x61, +0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x34,0x63,0x01,0x08,0x3c,0x04,0xb0,0x09, +0x3c,0x05,0xb0,0x09,0x8c,0x66,0x00,0x00,0x34,0x84,0x01,0x68,0x24,0x02,0xc8,0x80, +0x34,0xa5,0x01,0x40,0x24,0x03,0x00,0x0a,0xa4,0x82,0x00,0x00,0xa4,0xa3,0x00,0x00, +0x3c,0x04,0xb0,0x03,0x8c,0x82,0x00,0x00,0x8f,0x87,0x84,0x10,0xaf,0x86,0x84,0x08, +0x34,0x42,0x00,0x20,0xac,0x82,0x00,0x00,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x58, +0x8c,0x43,0x00,0x00,0x2c,0xe4,0x00,0x11,0x34,0x63,0x01,0x00,0xac,0x43,0x00,0x00, +0x10,0x80,0xff,0xfa,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x00,0x07,0x10,0x80, +0x24,0x63,0x02,0x18,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x80,0x00,0x08,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x68,0x0c,0x00,0x26,0xe5, +0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x10,0x27,0x85,0x86,0x48,0x0c,0x00,0x14,0x4e, +0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x09,0x34,0x42,0x00,0x07,0x3c,0x03,0xb0,0x06, +0x90,0x44,0x00,0x00,0x34,0x63,0x80,0x18,0x8c,0x65,0x00,0x00,0x3c,0x02,0xb0,0x03, +0x34,0x42,0x00,0xec,0x3c,0x03,0xb0,0x03,0x30,0x86,0x00,0xff,0xa0,0x46,0x00,0x00, +0x00,0x05,0x2f,0x02,0x34,0x63,0x00,0xed,0x24,0x02,0x00,0x01,0x10,0xc2,0x00,0x2c, +0xa0,0x65,0x00,0x00,0xa3,0x80,0x81,0x58,0x93,0x83,0x81,0xf1,0x24,0x02,0x00,0x01, +0x10,0x62,0x00,0x08,0x00,0x00,0x00,0x00,0x8f,0x87,0x84,0x10,0x8f,0x82,0x84,0x44, +0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01,0xaf,0x82,0x84,0x44,0x08,0x00,0x15,0x9b, +0x3c,0x02,0xb0,0x03,0x8f,0x87,0x84,0x10,0x00,0x00,0x00,0x00,0x24,0xe2,0xff,0xfc, +0x2c,0x42,0x00,0x03,0x14,0x40,0x00,0x0a,0x3c,0x03,0xb0,0x06,0x93,0x82,0x86,0x3c, +0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x07,0x34,0x63,0x80,0x18,0x27,0x84,0x84,0x68, +0x0c,0x00,0x27,0x75,0x00,0x00,0x00,0x00,0x8f,0x87,0x84,0x10,0x3c,0x03,0xb0,0x06, +0x34,0x63,0x80,0x18,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x17,0x02, +0x10,0x40,0xff,0xe6,0x00,0x00,0x00,0x00,0x8f,0x82,0xbc,0x10,0x8f,0x84,0xbc,0x18, +0x3c,0x05,0xb0,0x01,0x00,0x45,0x10,0x21,0xac,0x44,0x00,0x00,0x8f,0x83,0xbc,0x10, +0x8f,0x82,0xbc,0x14,0x00,0x65,0x18,0x21,0x08,0x00,0x15,0xc7,0xac,0x62,0x00,0x04, +0x14,0xa0,0xff,0xd4,0x3c,0x02,0xb0,0x03,0x93,0x83,0x81,0x58,0x34,0x42,0x00,0xee, +0x24,0x63,0x00,0x01,0x30,0x64,0x00,0xff,0x2c,0x84,0x00,0xf1,0xa0,0x43,0x00,0x00, +0xa3,0x83,0x81,0x58,0x14,0x80,0xff,0xcc,0x00,0x00,0x00,0x00,0xaf,0x86,0x84,0x24, +0xa3,0x86,0x86,0x23,0x08,0x00,0x15,0xc1,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x68, +0x0c,0x00,0x29,0x6e,0x00,0x00,0x00,0x00,0xa3,0x82,0x84,0x41,0x8f,0x82,0x84,0x44, +0xaf,0x80,0x84,0x10,0x24,0x42,0x00,0x01,0xaf,0x82,0x84,0x44,0x08,0x00,0x15,0x9a, +0x00,0x00,0x38,0x21,0x27,0x84,0x86,0x48,0x0c,0x00,0x19,0x19,0x00,0x00,0x00,0x00, +0x30,0x42,0x00,0xff,0x14,0x40,0x00,0x05,0x3c,0x03,0xb0,0x05,0xaf,0x80,0x84,0x10, +0xaf,0x80,0x84,0x14,0x08,0x00,0x15,0xc6,0x00,0x00,0x00,0x00,0x34,0x63,0x04,0x50, +0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0xaf,0x82,0x84,0x3c, +0x14,0x40,0x00,0x20,0x24,0x02,0x00,0x01,0x8f,0x84,0x84,0x18,0x00,0x00,0x00,0x00, +0x10,0x82,0x00,0x20,0x3c,0x03,0xb0,0x09,0x34,0x63,0x01,0x60,0x90,0x62,0x00,0x00, +0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0xaf,0x82,0x84,0x24,0x14,0x40,0x00,0x15, +0x24,0x02,0x00,0x01,0x24,0x02,0x00,0x02,0x10,0x82,0x00,0x07,0x00,0x00,0x00,0x00, +0x24,0x07,0x00,0x03,0x24,0x02,0x00,0x01,0xaf,0x82,0x84,0x14,0xaf,0x87,0x84,0x10, +0x08,0x00,0x15,0xc6,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2e, +0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x01,0x30,0x63,0x00,0xff, +0x00,0x60,0x10,0x21,0xa7,0x83,0x84,0x30,0x14,0x40,0xff,0xf1,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x01,0xaf,0x82,0x84,0x14,0xaf,0x80,0x84,0x10,0x08,0x00,0x15,0xc6, +0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x05,0x34,0x63,0x02,0x2c,0x8c,0x62,0x00,0x00, +0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0xaf,0x82,0x84,0x2c,0x14,0x40,0xff,0xf5, +0x24,0x02,0x00,0x01,0x08,0x00,0x16,0x1a,0x3c,0x03,0xb0,0x09,0x27,0x84,0x86,0x48, +0x0c,0x00,0x1a,0xde,0x00,0x00,0x00,0x00,0x83,0x82,0x84,0x40,0x00,0x00,0x00,0x00, +0x14,0x40,0xff,0xec,0x24,0x02,0x00,0x02,0x3c,0x03,0xb0,0x05,0x34,0x63,0x04,0x50, +0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0xaf,0x82,0x84,0x3c, +0x14,0x40,0xff,0xe4,0x24,0x02,0x00,0x02,0x8f,0x84,0x84,0x18,0x24,0x02,0x00,0x01, +0x10,0x82,0x00,0x12,0x24,0x02,0x00,0x02,0x10,0x82,0x00,0x04,0x00,0x00,0x00,0x00, +0x24,0x07,0x00,0x04,0x08,0x00,0x16,0x26,0x24,0x02,0x00,0x02,0x3c,0x02,0xb0,0x05, +0x34,0x42,0x02,0x2e,0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x01, +0x30,0x63,0x00,0xff,0x00,0x60,0x10,0x21,0xa7,0x83,0x84,0x30,0x14,0x40,0xff,0xf4, +0x00,0x00,0x00,0x00,0x08,0x00,0x16,0x35,0x24,0x02,0x00,0x02,0x3c,0x03,0xb0,0x05, +0x34,0x63,0x02,0x2c,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff, +0xaf,0x82,0x84,0x2c,0x14,0x40,0xff,0xf7,0x00,0x00,0x00,0x00,0x08,0x00,0x16,0x56, +0x24,0x02,0x00,0x02,0x27,0x84,0x89,0x08,0x0c,0x00,0x0b,0x51,0x00,0x00,0x00,0x00, +0x8f,0x83,0x84,0x14,0xaf,0x82,0x84,0x2c,0x38,0x64,0x00,0x02,0x00,0x04,0x18,0x0a, +0xaf,0x83,0x84,0x14,0x14,0x40,0xff,0xad,0x24,0x07,0x00,0x05,0x8f,0x82,0x89,0x48, +0xaf,0x80,0x84,0x10,0x10,0x40,0x00,0x02,0x24,0x04,0x00,0x01,0xaf,0x84,0x84,0x18, +0x93,0x82,0x89,0x56,0x00,0x00,0x00,0x00,0x10,0x40,0xff,0x43,0x00,0x00,0x00,0x00, +0x3c,0x02,0xb0,0x05,0x34,0x42,0x00,0x08,0x8c,0x43,0x00,0x00,0x3c,0x04,0x20,0x00, +0x00,0x64,0x18,0x24,0x10,0x60,0xff,0x3c,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03, +0x34,0x42,0x00,0xa0,0x8c,0x43,0x00,0x00,0x3c,0x04,0x80,0x00,0xaf,0x80,0x89,0x30, +0x24,0x63,0x00,0x01,0xac,0x43,0x00,0x00,0x3c,0x01,0xb0,0x05,0xac,0x24,0x00,0x08, +0xaf,0x80,0x89,0x2c,0xaf,0x80,0x89,0x34,0xaf,0x80,0x89,0x38,0xaf,0x80,0x89,0x44, +0xaf,0x80,0x89,0x3c,0x08,0x00,0x15,0xc6,0x00,0x00,0x00,0x00,0x83,0x82,0x84,0x60, +0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x02,0x24,0x02,0x00,0x20,0xaf,0x82,0x84,0x2c, +0x8f,0x85,0x84,0x2c,0x27,0x84,0x89,0x08,0x0c,0x00,0x0d,0x2c,0x00,0x00,0x00,0x00, +0x00,0x02,0x1e,0x00,0xa3,0x82,0x84,0x40,0xaf,0x80,0x84,0x2c,0x10,0x60,0xff,0x8e, +0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2e,0x90,0x43,0x00,0x00, +0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x01,0x30,0x63,0x00,0xff,0x00,0x60,0x10,0x21, +0xa7,0x83,0x84,0x30,0x10,0x40,0x00,0x04,0x24,0x04,0x00,0x02,0xaf,0x84,0x84,0x18, +0x08,0x00,0x16,0x36,0x00,0x00,0x00,0x00,0x08,0x00,0x16,0x27,0x24,0x07,0x00,0x06, +0x27,0x84,0x84,0x10,0x27,0x85,0x89,0x08,0x0c,0x00,0x0d,0xf9,0x00,0x00,0x00,0x00, +0x8f,0x82,0x84,0x34,0xaf,0x80,0x84,0x3c,0x14,0x40,0x00,0x19,0x00,0x40,0x18,0x21, +0x8f,0x82,0x84,0x38,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x15,0x24,0x02,0x00,0x02, +0x8f,0x83,0x84,0x18,0x00,0x00,0x00,0x00,0x10,0x62,0x00,0x0b,0x3c,0x02,0x40,0x00, +0x8f,0x83,0x84,0x14,0x24,0x02,0x00,0x01,0x10,0x62,0x00,0x02,0x24,0x07,0x00,0x03, +0x24,0x07,0x00,0x06,0xaf,0x87,0x84,0x10,0x24,0x04,0x00,0x03,0xaf,0x84,0x84,0x18, +0x08,0x00,0x15,0xc6,0x00,0x00,0x00,0x00,0x34,0x42,0x00,0x14,0x3c,0x01,0xb0,0x05, +0xac,0x22,0x00,0x00,0xaf,0x80,0x84,0x10,0x08,0x00,0x16,0xcf,0x24,0x04,0x00,0x03, +0x10,0x60,0x00,0x10,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x10,0x27,0x85,0x89,0x08, +0x0c,0x00,0x0e,0x1d,0x00,0x00,0x00,0x00,0x8f,0x83,0x84,0x14,0x24,0x02,0x00,0x01, +0xa3,0x80,0x84,0x40,0xaf,0x80,0x84,0x18,0x10,0x62,0x00,0x02,0x24,0x07,0x00,0x03, +0x24,0x07,0x00,0x04,0xaf,0x87,0x84,0x10,0xaf,0x80,0x84,0x34,0x08,0x00,0x15,0xc6, +0x00,0x00,0x00,0x00,0x83,0x82,0x84,0x60,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x04, +0x00,0x00,0x00,0x00,0x27,0x84,0x89,0x08,0x0c,0x00,0x10,0x65,0x00,0x00,0x00,0x00, +0x8f,0x82,0x84,0x14,0xa3,0x80,0x84,0x40,0xaf,0x80,0x84,0x10,0xaf,0x80,0x84,0x18, +0x14,0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0xaf,0x82,0x84,0x14, +0xaf,0x80,0x84,0x38,0x08,0x00,0x15,0xc6,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x10, +0x27,0x85,0x89,0x08,0x0c,0x00,0x0e,0x1d,0x00,0x00,0x00,0x00,0x8f,0x82,0x84,0x14, +0xa3,0x80,0x84,0x40,0xaf,0x80,0x84,0x10,0xaf,0x80,0x84,0x18,0x14,0x40,0xfe,0xc2, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0xaf,0x82,0x84,0x14,0x08,0x00,0x15,0xc6, +0x00,0x00,0x00,0x00,0x27,0x84,0x89,0x08,0x0c,0x00,0x10,0x65,0x00,0x00,0x00,0x00, +0x08,0x00,0x16,0xff,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x68,0x0c,0x00,0x2a,0x96, +0x00,0x00,0x00,0x00,0x08,0x00,0x15,0xfe,0x00,0x00,0x00,0x00,0x0c,0x00,0x24,0x66, +0x00,0x00,0x00,0x00,0x0c,0x00,0x27,0x56,0x00,0x00,0x00,0x00,0x0c,0x00,0x18,0x40, +0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x68,0x0c,0x00,0x27,0x64,0x00,0x00,0x00,0x00, +0x93,0x83,0xbc,0x08,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x2b,0x3c,0x02,0xb0,0x03, +0x34,0x42,0x01,0x08,0x8c,0x44,0x00,0x00,0x8f,0x83,0xbc,0x00,0x8f,0x82,0xbc,0x04, +0x00,0x83,0x18,0x23,0x00,0x43,0x10,0x2b,0x10,0x40,0x00,0x23,0x3c,0x02,0xb0,0x03, +0x24,0x04,0x05,0xa0,0x34,0x42,0x01,0x18,0x8c,0x42,0x00,0x00,0x0c,0x00,0x06,0xce, +0x00,0x00,0x00,0x00,0x24,0x04,0x05,0xa4,0x0c,0x00,0x06,0xce,0x00,0x02,0x84,0x02, +0x30,0x51,0xff,0xff,0x24,0x04,0x05,0xa8,0x00,0x02,0x94,0x02,0x0c,0x00,0x06,0xce, +0x3a,0x10,0xff,0xff,0x3a,0x31,0xff,0xff,0x30,0x42,0xff,0xff,0x2e,0x10,0x00,0x01, +0x2e,0x31,0x00,0x01,0x3a,0x52,0xff,0xff,0x02,0x11,0x80,0x25,0x2e,0x52,0x00,0x01, +0x38,0x42,0xff,0xff,0x02,0x12,0x80,0x25,0x2c,0x42,0x00,0x01,0x02,0x02,0x80,0x25, +0x16,0x00,0x00,0x02,0x24,0x04,0x00,0x02,0x00,0x00,0x20,0x21,0x0c,0x00,0x05,0x70, +0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x08,0x8c,0x43,0x00,0x00, +0x00,0x00,0x00,0x00,0xaf,0x83,0xbc,0x00,0x0c,0x00,0x01,0xeb,0x00,0x00,0x00,0x00, +0xaf,0x80,0x84,0x10,0xaf,0x80,0x84,0x44,0x08,0x00,0x15,0x9a,0x00,0x00,0x38,0x21, +0x27,0x90,0xb3,0xf0,0x24,0x11,0x00,0x12,0x8e,0x04,0x00,0x00,0x00,0x00,0x00,0x00, +0x90,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x03,0x00,0x00,0x00,0x00, +0x0c,0x00,0x20,0xd0,0x00,0x00,0x00,0x00,0x26,0x31,0xff,0xff,0x06,0x21,0xff,0xf6, +0x26,0x10,0x00,0x04,0xaf,0x80,0x84,0x10,0x08,0x00,0x15,0xc7,0x00,0x00,0x38,0x21, +0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x08,0x8c,0x44,0x00,0x00,0x8f,0x82,0x84,0x08, +0x00,0x04,0x19,0xc2,0x00,0x02,0x11,0xc2,0x10,0x62,0xff,0xf6,0x00,0x00,0x00,0x00, +0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x02,0x90,0x43,0x00,0x00,0x3c,0x12,0xb0,0x05, +0xaf,0x84,0x84,0x08,0x30,0x63,0x00,0xff,0x00,0x03,0x11,0x40,0x00,0x43,0x10,0x23, +0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x00,0x02,0x99,0x00,0x00,0x00,0x88,0x21, +0x36,0x52,0x02,0x2c,0x27,0x90,0xb3,0xf0,0x8e,0x04,0x00,0x00,0x00,0x00,0x00,0x00, +0x90,0x83,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x62,0x00,0x03,0x10,0x40,0x00,0x06, +0x30,0x62,0x00,0x1c,0x14,0x40,0x00,0x04,0x00,0x00,0x00,0x00,0x8f,0x85,0x84,0x08, +0x0c,0x00,0x1e,0xb2,0x02,0x60,0x30,0x21,0x8e,0x42,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x42,0x00,0xff,0x14,0x40,0xff,0xd7,0x00,0x00,0x00,0x00,0x26,0x31,0x00,0x01, +0x2a,0x22,0x00,0x13,0x14,0x40,0xff,0xec,0x26,0x10,0x00,0x04,0x08,0x00,0x17,0x5d, +0x00,0x00,0x00,0x00,0x8f,0x84,0x84,0x1c,0x27,0x85,0x89,0x08,0x0c,0x00,0x17,0xd3, +0x00,0x00,0x00,0x00,0x8f,0x83,0x84,0x1c,0x24,0x02,0x00,0x04,0x14,0x62,0xfe,0xa2, +0x00,0x00,0x00,0x00,0x08,0x00,0x16,0x27,0x24,0x07,0x00,0x05,0x27,0x84,0x89,0x08, +0x0c,0x00,0x24,0x8d,0x00,0x00,0x00,0x00,0x24,0x07,0x00,0x05,0xaf,0x87,0x84,0x10, +0x08,0x00,0x15,0xc7,0x00,0x00,0x00,0x00,0x8f,0x82,0x89,0x3c,0x00,0x00,0x00,0x00, +0x10,0x40,0x00,0x0d,0x00,0x00,0x00,0x00,0x8f,0x84,0xb4,0x30,0xaf,0x80,0x89,0x3c, +0x94,0x85,0x00,0x14,0x0c,0x00,0x1b,0x84,0x00,0x00,0x00,0x00,0x93,0x82,0x8b,0x61, +0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x02,0x10,0x40,0x00,0x03,0x00,0x00,0x00,0x00, +0x0c,0x00,0x01,0x59,0x00,0x00,0x20,0x21,0x8f,0x84,0xb4,0x30,0x0c,0x00,0x20,0xd0, +0x00,0x00,0x00,0x00,0x08,0x00,0x17,0x5d,0x00,0x00,0x00,0x00,0x3c,0x02,0xff,0x90, +0x27,0xbd,0xff,0xe8,0x00,0x80,0x18,0x21,0x34,0x42,0x00,0x01,0x27,0x84,0x89,0x08, +0x10,0x62,0x00,0x05,0xaf,0xbf,0x00,0x10,0x8f,0xbf,0x00,0x10,0x00,0x00,0x00,0x00, +0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x0c,0x00,0x06,0xe1,0x00,0x00,0x00,0x00, +0x27,0x84,0x86,0x48,0x0c,0x00,0x18,0x4e,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x10, +0x0c,0x00,0x13,0xd5,0x00,0x00,0x00,0x00,0x08,0x00,0x17,0xba,0x00,0x00,0x00,0x00, +0x8f,0x82,0x89,0x48,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x05,0x00,0x00,0x18,0x21, +0x8f,0x82,0x84,0x18,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x02,0x00,0x00,0x00,0x00, +0x24,0x03,0x00,0x01,0x03,0xe0,0x00,0x08,0x00,0x60,0x10,0x21,0x27,0xbd,0xff,0xe0, +0x3c,0x06,0xb0,0x03,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0x34,0xc6,0x00,0x5f, +0xaf,0xbf,0x00,0x18,0x90,0xc3,0x00,0x00,0x3c,0x07,0xb0,0x03,0x34,0xe7,0x00,0x5d, +0x34,0x63,0x00,0x01,0x3c,0x09,0xb0,0x03,0x24,0x02,0x00,0x01,0xa0,0xc3,0x00,0x00, +0x00,0x80,0x80,0x21,0xa0,0xe2,0x00,0x00,0x00,0xa0,0x88,0x21,0x35,0x29,0x00,0x5e, +0x00,0xe0,0x40,0x21,0x24,0x04,0x00,0x01,0x91,0x22,0x00,0x00,0x91,0x03,0x00,0x00, +0x30,0x42,0x00,0x01,0x14,0x83,0x00,0x03,0x30,0x42,0x00,0x01,0x14,0x40,0xff,0xfa, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x04,0x12,0x02,0x00,0x2c,0x24,0x05,0x0f,0x00, +0x24,0x02,0x00,0x06,0x12,0x02,0x00,0x08,0x24,0x05,0x00,0x0f,0x3c,0x02,0xb0,0x03, +0x34,0x42,0x02,0x00,0xa0,0x50,0x00,0x00,0x8f,0xbf,0x00,0x18,0x7b,0xb0,0x00,0xbc, +0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x24,0x04,0x0c,0x04,0x0c,0x00,0x13,0x5b, +0x24,0x06,0x00,0x0f,0x24,0x04,0x0d,0x04,0x24,0x05,0x00,0x0f,0x0c,0x00,0x13,0x5b, +0x24,0x06,0x00,0x0f,0x24,0x04,0x08,0x80,0x24,0x05,0x1e,0x00,0x0c,0x00,0x13,0x5b, +0x24,0x06,0x00,0x0f,0x24,0x04,0x08,0x8c,0x24,0x05,0x0f,0x00,0x0c,0x00,0x13,0x5b, +0x24,0x06,0x00,0x0f,0x24,0x04,0x08,0x24,0x3c,0x05,0x00,0x30,0x0c,0x00,0x13,0x5b, +0x24,0x06,0x00,0x02,0x24,0x04,0x08,0x2c,0x3c,0x05,0x00,0x30,0x0c,0x00,0x13,0x5b, +0x24,0x06,0x00,0x02,0x24,0x04,0x08,0x34,0x3c,0x05,0x00,0x30,0x0c,0x00,0x13,0x5b, +0x24,0x06,0x00,0x02,0x24,0x04,0x08,0x3c,0x3c,0x05,0x00,0x30,0x0c,0x00,0x13,0x5b, +0x24,0x06,0x00,0x02,0x08,0x00,0x17,0xf4,0x3c,0x02,0xb0,0x03,0x24,0x04,0x08,0x8c, +0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x04,0x24,0x04,0x08,0x80,0x24,0x05,0x1e,0x00, +0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x04,0x24,0x04,0x0c,0x04,0x24,0x05,0x00,0x0f, +0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x04,0x24,0x04,0x0d,0x04,0x24,0x05,0x00,0x0f, +0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x04,0x24,0x04,0x08,0x24,0x3c,0x05,0x00,0x30, +0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x03,0x24,0x04,0x08,0x2c,0x3c,0x05,0x00,0x30, +0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x03,0x24,0x04,0x08,0x34,0x3c,0x05,0x00,0x30, +0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x02,0x3c,0x05,0x00,0x30,0x24,0x06,0x00,0x03, +0x0c,0x00,0x13,0x5b,0x24,0x04,0x08,0x3c,0x02,0x20,0x20,0x21,0x24,0x05,0x00,0x14, +0x0c,0x00,0x13,0xa0,0x24,0x06,0x01,0x07,0x08,0x00,0x17,0xf4,0x3c,0x02,0xb0,0x03, +0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0x73,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x42,0x00,0x02,0x14,0x40,0x00,0x04,0x00,0x00,0x00,0x00,0xa3,0x80,0x81,0x59, +0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0xa3,0x82,0x81,0x59, +0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00, +0x00,0x80,0x70,0x21,0x34,0x63,0x00,0x20,0x24,0x42,0x61,0x38,0x3c,0x04,0xb0,0x03, +0xac,0x62,0x00,0x00,0x34,0x84,0x00,0x30,0xad,0xc0,0x02,0xbc,0xad,0xc0,0x02,0xb8, +0x8c,0x83,0x00,0x00,0x24,0x02,0x00,0xff,0xa5,0xc0,0x00,0x0a,0x00,0x00,0x30,0x21, +0xa7,0x82,0x8f,0xe0,0x27,0x88,0x8f,0xf0,0xa5,0xc3,0x00,0x08,0x3c,0x07,0xb0,0x08, +0x30,0xc2,0xff,0xff,0x00,0x02,0x20,0xc0,0x24,0xc3,0x00,0x01,0x00,0x82,0x10,0x21, +0x00,0x60,0x30,0x21,0x00,0x02,0x10,0x80,0x30,0x63,0xff,0xff,0x00,0x48,0x10,0x21, +0x00,0x87,0x20,0x21,0x28,0xc5,0x00,0xff,0xac,0x83,0x00,0x00,0x14,0xa0,0xff,0xf4, +0xa4,0x43,0x00,0x00,0x3c,0x02,0xb0,0x08,0x34,0x03,0xff,0xff,0x25,0xc4,0x00,0x0c, +0x24,0x0a,0x00,0x02,0x34,0x42,0x07,0xf8,0x3c,0x06,0xb0,0x03,0xa7,0x83,0xb3,0xcc, +0xac,0x43,0x00,0x00,0xaf,0x84,0xb3,0xf0,0x34,0xc6,0x00,0x64,0xa0,0x8a,0x00,0x18, +0x94,0xc5,0x00,0x00,0x8f,0x82,0xb3,0xf0,0x25,0xc4,0x00,0x30,0x24,0x08,0x00,0x03, +0x3c,0x03,0xb0,0x03,0xa0,0x45,0x00,0x21,0x34,0x63,0x00,0x66,0xaf,0x84,0xb3,0xf4, +0xa0,0x88,0x00,0x18,0x94,0x65,0x00,0x00,0x8f,0x82,0xb3,0xf4,0x25,0xc4,0x00,0x54, +0x25,0xc7,0x00,0x78,0xa0,0x45,0x00,0x21,0xaf,0x84,0xb3,0xf8,0xa0,0x88,0x00,0x18, +0x94,0x65,0x00,0x00,0x8f,0x82,0xb3,0xf8,0x25,0xc8,0x00,0x9c,0x24,0x09,0x00,0x01, +0xa0,0x45,0x00,0x21,0xaf,0x87,0xb3,0xfc,0xa0,0xea,0x00,0x18,0x94,0xc4,0x00,0x00, +0x8f,0x82,0xb3,0xfc,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0x62,0xa0,0x44,0x00,0x21, +0xaf,0x88,0xb4,0x00,0xa1,0x09,0x00,0x18,0x94,0x65,0x00,0x00,0x8f,0x82,0xb4,0x00, +0x25,0xc4,0x00,0xc0,0x3c,0x06,0xb0,0x03,0xa0,0x45,0x00,0x21,0xaf,0x84,0xb4,0x04, +0xa0,0x89,0x00,0x18,0x94,0x65,0x00,0x00,0x8f,0x82,0xb4,0x04,0x25,0xc4,0x00,0xe4, +0x34,0xc6,0x00,0x60,0xa0,0x45,0x00,0x21,0xaf,0x84,0xb4,0x08,0xa0,0x80,0x00,0x18, +0x94,0xc5,0x00,0x00,0x8f,0x82,0xb4,0x08,0x25,0xc3,0x01,0x08,0x25,0xc7,0x01,0x2c, +0xa0,0x45,0x00,0x21,0xaf,0x83,0xb4,0x0c,0xa0,0x60,0x00,0x18,0x94,0xc8,0x00,0x00, +0x8f,0x82,0xb4,0x0c,0x25,0xc4,0x01,0x50,0x25,0xc5,0x01,0x74,0xa0,0x48,0x00,0x21, +0x25,0xc6,0x01,0x98,0x25,0xc9,0x01,0xbc,0x25,0xca,0x01,0xe0,0x25,0xcb,0x02,0x04, +0x25,0xcc,0x02,0x28,0x25,0xcd,0x02,0x4c,0x24,0x02,0x00,0x10,0x3c,0x03,0xb0,0x03, +0xaf,0x87,0xb4,0x10,0x34,0x63,0x00,0x38,0xa0,0xe0,0x00,0x18,0xaf,0x84,0xb4,0x14, +0xa0,0x80,0x00,0x18,0xaf,0x85,0xb4,0x18,0xa0,0xa0,0x00,0x18,0xaf,0x86,0xb4,0x1c, +0xa0,0xc0,0x00,0x18,0xaf,0x89,0xb4,0x20,0xa1,0x20,0x00,0x18,0xaf,0x8a,0xb4,0x24, +0xa1,0x40,0x00,0x18,0xaf,0x8b,0xb4,0x28,0xa1,0x60,0x00,0x18,0xaf,0x8c,0xb4,0x2c, +0xa1,0x80,0x00,0x18,0xaf,0x8d,0xb4,0x30,0xa1,0xa2,0x00,0x18,0x94,0x64,0x00,0x00, +0x8f,0x82,0xb4,0x30,0x25,0xc5,0x02,0x70,0x3c,0x03,0xb0,0x03,0xa0,0x44,0x00,0x21, +0x24,0x02,0x00,0x11,0xaf,0x85,0xb4,0x34,0x34,0x63,0x00,0x6e,0xa0,0xa2,0x00,0x18, +0x94,0x64,0x00,0x00,0x8f,0x82,0xb4,0x34,0x25,0xc5,0x02,0x94,0x3c,0x03,0xb0,0x03, +0xa0,0x44,0x00,0x21,0x24,0x02,0x00,0x12,0xaf,0x85,0xb4,0x38,0x34,0x63,0x00,0x6c, +0xa0,0xa2,0x00,0x18,0x94,0x64,0x00,0x00,0x8f,0x82,0xb4,0x38,0x24,0x05,0xff,0xff, +0x24,0x07,0x00,0x01,0xa0,0x44,0x00,0x21,0x24,0x06,0x00,0x12,0x27,0x84,0xb3,0xf0, +0x8c,0x82,0x00,0x00,0x24,0xc6,0xff,0xff,0xa0,0x40,0x00,0x04,0x8c,0x83,0x00,0x00, +0xa4,0x45,0x00,0x00,0xa4,0x45,0x00,0x02,0xa0,0x60,0x00,0x0a,0x8c,0x82,0x00,0x00, +0xa4,0x65,0x00,0x06,0xa4,0x65,0x00,0x08,0xa0,0x40,0x00,0x10,0x8c,0x83,0x00,0x00, +0xa4,0x45,0x00,0x0c,0xa4,0x45,0x00,0x0e,0xa0,0x60,0x00,0x12,0x8c,0x82,0x00,0x00, +0x00,0x00,0x00,0x00,0xa0,0x40,0x00,0x16,0x8c,0x83,0x00,0x00,0xa4,0x45,0x00,0x14, +0xa0,0x67,0x00,0x17,0x8c,0x82,0x00,0x00,0x24,0x84,0x00,0x04,0xa0,0x40,0x00,0x20, +0x04,0xc1,0xff,0xe7,0xac,0x40,0x00,0x1c,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x64,0x00, +0x00,0x05,0x28,0x40,0xac,0x62,0x00,0x00,0x00,0xa6,0x28,0x21,0x2c,0xe2,0x00,0x10, +0x14,0x80,0x00,0x06,0x00,0x00,0x18,0x21,0x10,0x40,0x00,0x02,0x00,0x00,0x00,0x00, +0x00,0xe0,0x18,0x21,0x03,0xe0,0x00,0x08,0x00,0x60,0x10,0x21,0x24,0x02,0x00,0x20, +0x10,0xe2,0x00,0x06,0x2c,0xe4,0x00,0x10,0x24,0xa2,0x00,0x01,0x10,0x80,0xff,0xf9, +0x00,0x02,0x11,0x00,0x08,0x00,0x19,0x0d,0x00,0x47,0x18,0x21,0x08,0x00,0x19,0x0d, +0x24,0xa3,0x00,0x50,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xc8, +0x34,0x63,0x00,0x20,0x24,0x42,0x64,0x64,0xaf,0xb2,0x00,0x18,0xaf,0xbf,0x00,0x34, +0xaf,0xbe,0x00,0x30,0xaf,0xb7,0x00,0x2c,0xaf,0xb6,0x00,0x28,0xaf,0xb5,0x00,0x24, +0xaf,0xb4,0x00,0x20,0xaf,0xb3,0x00,0x1c,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10, +0xac,0x62,0x00,0x00,0x8c,0x86,0x02,0xbc,0x00,0x80,0x90,0x21,0x14,0xc0,0x01,0x66, +0x00,0xc0,0x38,0x21,0x84,0x82,0x00,0x08,0x3c,0x03,0xb0,0x06,0x94,0x84,0x00,0x08, +0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x8c,0x45,0x00,0x00,0x8c,0x43,0x00,0x00, +0x24,0x84,0x00,0x02,0x30,0x84,0x01,0xff,0x30,0xb1,0xff,0xff,0x00,0x03,0x44,0x02, +0xa6,0x44,0x00,0x08,0x14,0xe0,0x00,0x08,0x3c,0x03,0xb0,0x06,0x34,0x63,0x80,0x24, +0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x42,0x01,0x00,0xac,0x62,0x00,0x00, +0x8e,0x46,0x02,0xbc,0x00,0x00,0x00,0x00,0x14,0xc0,0x01,0x4c,0x00,0x11,0x98,0xc0, +0x00,0x11,0x3a,0x00,0x3c,0x04,0xb0,0x00,0x00,0xe4,0x20,0x21,0x8c,0x83,0x00,0x0c, +0x00,0x11,0x98,0xc0,0x02,0x71,0x10,0x21,0x00,0x03,0x1b,0x82,0x30,0x63,0x00,0x1f, +0x00,0x02,0x10,0x80,0x27,0x9e,0x8f,0xf4,0x00,0x5e,0x10,0x21,0x00,0x60,0x30,0x21, +0xac,0x44,0x00,0x18,0xae,0x43,0x02,0xbc,0x14,0xc0,0x00,0x10,0x3c,0x02,0xb0,0x00, +0x00,0x08,0x10,0xc0,0x00,0x48,0x10,0x21,0x27,0x84,0x8f,0xf0,0x00,0x02,0x10,0x80, +0x00,0x44,0x10,0x21,0x94,0x45,0x00,0x00,0x02,0x71,0x18,0x21,0x00,0x03,0x18,0x80, +0x00,0x64,0x18,0x21,0x24,0x02,0xff,0xff,0xa4,0x62,0x00,0x02,0xa4,0x68,0x00,0x04, +0xae,0x51,0x02,0xb8,0xa6,0x45,0x00,0x0a,0x3c,0x02,0xb0,0x00,0x00,0xe2,0x40,0x21, +0x8d,0x16,0x00,0x00,0x8d,0x14,0x00,0x04,0x02,0x71,0x10,0x21,0x00,0x02,0x38,0x80, +0x00,0x14,0x1a,0x02,0x27,0x84,0x90,0x00,0x30,0x63,0x00,0x1f,0x24,0x02,0x00,0x10, +0x00,0xe4,0x20,0x21,0xa6,0x43,0x00,0x06,0x8d,0x10,0x00,0x08,0xa0,0x82,0x00,0x06, +0x86,0x45,0x00,0x06,0x00,0xfe,0x10,0x21,0x24,0x03,0x00,0x13,0x10,0xa3,0x01,0x15, +0xac,0x48,0x00,0x18,0x3c,0x03,0xb0,0x03,0x34,0x63,0x01,0x00,0xa6,0x40,0x00,0x02, +0x3c,0x02,0xb0,0x03,0x90,0x64,0x00,0x00,0x34,0x42,0x01,0x08,0x8c,0x45,0x00,0x00, +0x00,0x10,0x1b,0xc2,0x27,0x82,0x8f,0xf0,0x00,0x04,0x20,0x82,0x00,0xe2,0x10,0x21, +0x30,0x63,0x00,0x01,0xac,0x45,0x00,0x08,0x10,0x60,0x00,0xec,0x30,0x97,0x00,0x01, +0x00,0x10,0x16,0x82,0x30,0x46,0x00,0x01,0x00,0x10,0x12,0x02,0x00,0x10,0x19,0xc2, +0x00,0x10,0x26,0x02,0x00,0x10,0x2e,0x42,0x30,0x47,0x00,0x7f,0x24,0x02,0x00,0x01, +0x30,0x75,0x00,0x01,0x30,0x84,0x00,0x01,0x10,0xc2,0x00,0xd9,0x30,0xa3,0x00,0x01, +0x0c,0x00,0x19,0x00,0x00,0x60,0x28,0x21,0x02,0x71,0x18,0x21,0x00,0x03,0x18,0x80, +0x2c,0x46,0x00,0x54,0x27,0x85,0x90,0x00,0x27,0x84,0x8f,0xf8,0x00,0x06,0x10,0x0a, +0x00,0x65,0x28,0x21,0x26,0xa6,0x00,0x02,0x00,0x64,0x18,0x21,0xa0,0xa2,0x00,0x02, +0xa0,0x66,0x00,0x06,0xa0,0x62,0x00,0x07,0xa0,0xa2,0x00,0x01,0x02,0x71,0x20,0x21, +0x00,0x04,0x20,0x80,0x00,0x9e,0x60,0x21,0x8d,0x85,0x00,0x18,0x00,0x10,0x15,0xc2, +0x30,0x42,0x00,0x01,0x8c,0xa3,0x00,0x0c,0xa6,0x42,0x00,0x00,0x27,0x82,0x90,0x10, +0x00,0x82,0x50,0x21,0xa6,0x56,0x00,0x04,0x8d,0x45,0x00,0x00,0x00,0x03,0x19,0x42, +0x3c,0x02,0xff,0xef,0x34,0x42,0xff,0xff,0x30,0x63,0x00,0x01,0x00,0xa2,0x48,0x24, +0x00,0x03,0x1d,0x00,0x01,0x23,0x48,0x25,0x00,0x09,0x15,0x02,0x26,0xc5,0x00,0x10, +0x00,0x14,0x19,0x82,0x00,0x14,0x25,0x82,0x00,0x10,0x34,0x02,0x00,0x10,0x3c,0x42, +0x00,0x10,0x44,0x82,0x30,0x42,0x00,0x01,0x30,0xb5,0xff,0xff,0x30,0xce,0x00,0x01, +0x30,0xe5,0x00,0x01,0x30,0x6d,0x00,0x01,0x30,0x8b,0x00,0x03,0x32,0x94,0x00,0x07, +0x31,0x06,0x00,0x01,0xad,0x49,0x00,0x00,0x10,0x40,0x00,0x0b,0x32,0x07,0x00,0x7f, +0x8d,0x84,0x00,0x18,0x3c,0x03,0xff,0xf0,0x34,0x63,0xff,0xff,0x8c,0x82,0x00,0x0c, +0x01,0x23,0x18,0x24,0x00,0x02,0x13,0x82,0x30,0x42,0x00,0x0f,0x00,0x02,0x14,0x00, +0x00,0x62,0x18,0x25,0xad,0x43,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xc2,0x00,0x90, +0x00,0x00,0x00,0x00,0x15,0xa0,0x00,0x03,0x00,0x00,0x00,0x00,0x15,0x60,0x00,0x81, +0x24,0x02,0x00,0x01,0x96,0x42,0x00,0x04,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x04, +0xa6,0x42,0x00,0x04,0x0c,0x00,0x19,0x00,0x01,0xc0,0x20,0x21,0x02,0x71,0x18,0x21, +0x00,0x03,0x38,0x80,0x2c,0x45,0x00,0x54,0x27,0x84,0x90,0x00,0x00,0xe4,0x20,0x21, +0x00,0x05,0x10,0x0a,0xa0,0x82,0x00,0x00,0xa0,0x80,0x00,0x04,0xa0,0x80,0x00,0x05, +0x96,0x45,0x00,0x04,0x27,0x82,0x8f,0xf0,0x00,0xe2,0x10,0x21,0xa4,0x45,0x00,0x06, +0x00,0xfe,0x18,0x21,0x92,0x45,0x00,0x01,0x8c,0x66,0x00,0x18,0x27,0x82,0x90,0x10, +0x00,0xe2,0x10,0x21,0xa0,0x40,0x00,0x00,0xa0,0x85,0x00,0x07,0x94,0xc3,0x00,0x10, +0x24,0x02,0x00,0x04,0x30,0x63,0x00,0x0f,0x10,0x62,0x00,0x5e,0x24,0xc6,0x00,0x10, +0x94,0xc3,0x00,0x16,0x27,0x85,0x90,0x08,0x00,0xe5,0x10,0x21,0xa4,0x43,0x00,0x02, +0x94,0xc2,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x14,0x40,0x00,0x4c, +0x02,0x71,0x20,0x21,0x94,0xc2,0x00,0x00,0x24,0x03,0x00,0xa4,0x30,0x42,0x00,0xff, +0x10,0x43,0x00,0x47,0x00,0x00,0x00,0x00,0x94,0xc2,0x00,0x00,0x24,0x03,0x00,0x88, +0x30,0x42,0x00,0x88,0x10,0x43,0x00,0x3c,0x02,0x71,0x18,0x21,0x27,0x84,0x90,0x10, +0x00,0x03,0x18,0x80,0x00,0x64,0x18,0x21,0x8c,0x62,0x00,0x00,0x3c,0x04,0x00,0x80, +0x00,0x44,0x10,0x25,0xac,0x62,0x00,0x00,0x02,0x71,0x10,0x21,0x00,0x02,0x10,0x80, +0x00,0x45,0x10,0x21,0xa0,0x54,0x00,0x00,0x92,0x43,0x02,0xbf,0x3c,0x02,0xb0,0x03, +0x34,0x42,0x00,0xc3,0xa0,0x43,0x00,0x00,0x8e,0x4b,0x02,0xbc,0x00,0x00,0x00,0x00, +0x11,0x60,0x00,0x1c,0x32,0xa2,0x00,0xff,0x00,0x15,0x1a,0x02,0x30,0x64,0xff,0xff, +0x38,0x42,0x00,0x00,0x24,0x65,0x00,0x01,0x00,0x82,0x28,0x0a,0x02,0x20,0x30,0x21, +0x10,0xa0,0x00,0x12,0x00,0x00,0x38,0x21,0x02,0x71,0x10,0x21,0x00,0x02,0x10,0x80, +0x27,0x83,0x8f,0xf0,0x00,0x43,0x20,0x21,0x24,0xa9,0xff,0xff,0x3c,0x0a,0xb0,0x08, +0x24,0x0c,0xff,0xff,0x00,0x06,0x10,0xc0,0x00,0x4a,0x10,0x21,0x8c,0x43,0x00,0x00, +0x24,0xe8,0x00,0x01,0x10,0xe9,0x00,0x0f,0x30,0x63,0x00,0xff,0x31,0x07,0xff,0xff, +0x00,0xe5,0x10,0x2b,0x14,0x40,0xff,0xf7,0x00,0x60,0x30,0x21,0x25,0x62,0xff,0xff, +0xae,0x42,0x02,0xbc,0x7b,0xbe,0x01,0xbc,0x7b,0xb6,0x01,0x7c,0x7b,0xb4,0x01,0x3c, +0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x24,0x02,0x00,0x01,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x38,0xa4,0x86,0x00,0x04,0xa4,0x8c,0x00,0x02,0xae,0x51,0x02,0xb8, +0x08,0x00,0x1a,0x2f,0xa6,0x43,0x00,0x0a,0x94,0xc2,0x00,0x18,0x00,0x00,0x00,0x00, +0x30,0x42,0x00,0x60,0x10,0x40,0xff,0xc1,0x02,0x71,0x18,0x21,0x02,0x71,0x20,0x21, +0x27,0x82,0x90,0x10,0x00,0x04,0x20,0x80,0x00,0x82,0x20,0x21,0x8c,0x83,0x00,0x00, +0x3c,0x02,0xff,0x7f,0x34,0x42,0xff,0xff,0x00,0x62,0x18,0x24,0x08,0x00,0x1a,0x0e, +0xac,0x83,0x00,0x00,0x27,0x85,0x90,0x08,0x00,0xe5,0x10,0x21,0x08,0x00,0x19,0xf8, +0xa4,0x40,0x00,0x02,0x11,0x62,0x00,0x07,0x00,0x00,0x00,0x00,0x2d,0x62,0x00,0x02, +0x14,0x40,0xff,0x80,0x00,0x00,0x00,0x00,0x96,0x42,0x00,0x04,0x08,0x00,0x19,0xd8, +0x24,0x42,0x00,0x0c,0x96,0x42,0x00,0x04,0x08,0x00,0x19,0xd8,0x24,0x42,0x00,0x08, +0x16,0xe6,0xff,0x70,0x3c,0x02,0xff,0xfb,0x8d,0x83,0x00,0x18,0x34,0x42,0xff,0xff, +0x02,0x02,0x10,0x24,0xac,0x62,0x00,0x08,0x08,0x00,0x19,0xd1,0x00,0x00,0x30,0x21, +0x16,0xe6,0xff,0x27,0x3c,0x02,0xfb,0xff,0x34,0x42,0xff,0xff,0x02,0x02,0x10,0x24, +0xad,0x02,0x00,0x08,0x08,0x00,0x19,0x90,0x00,0x00,0x30,0x21,0x93,0x88,0xbb,0x04, +0x00,0x10,0x1e,0x42,0x00,0x10,0x26,0x82,0x27,0x82,0x8f,0xf8,0x2d,0x05,0x00,0x0c, +0x00,0xe2,0x48,0x21,0x30,0x63,0x00,0x01,0x30,0x86,0x00,0x01,0x14,0xa0,0x00,0x06, +0x01,0x00,0x38,0x21,0x00,0x03,0x10,0x40,0x00,0x46,0x10,0x21,0x00,0x02,0x11,0x00, +0x01,0x02,0x10,0x21,0x24,0x47,0x00,0x04,0x02,0x71,0x10,0x21,0x00,0x02,0x10,0x80, +0x27,0x84,0x90,0x00,0x27,0x83,0x8f,0xf8,0x00,0x44,0x20,0x21,0x00,0x43,0x10,0x21, +0xa1,0x27,0x00,0x07,0xa0,0x40,0x00,0x06,0xa0,0x80,0x00,0x02,0x08,0x00,0x19,0x9f, +0xa0,0x80,0x00,0x01,0x24,0x02,0x00,0x01,0xa6,0x42,0x00,0x02,0x0c,0x00,0x01,0xc4, +0x01,0x00,0x20,0x21,0x08,0x00,0x1a,0x35,0x00,0x00,0x00,0x00,0x27,0x9e,0x8f,0xf4, +0x08,0x00,0x19,0x52,0x00,0x11,0x3a,0x00,0x94,0x91,0x00,0x0a,0x08,0x00,0x19,0x39, +0x00,0x00,0x00,0x00,0x30,0xa9,0xff,0xff,0x00,0x09,0x18,0xc0,0x00,0x69,0x18,0x21, +0x3c,0x06,0xb0,0x03,0x3c,0x02,0x80,0x00,0x24,0x42,0x6a,0x54,0x00,0x03,0x18,0x80, +0x34,0xc6,0x00,0x20,0x27,0x85,0x90,0x00,0xac,0xc2,0x00,0x00,0x00,0x65,0x18,0x21, +0x80,0x62,0x00,0x07,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x32,0x24,0x88,0x00,0x06, +0x90,0x82,0x00,0x16,0x00,0x80,0x40,0x21,0x34,0x42,0x00,0x02,0x30,0x43,0x00,0x01, +0x14,0x60,0x00,0x02,0xa0,0x82,0x00,0x16,0xa0,0x80,0x00,0x17,0x95,0x03,0x00,0x02, +0x00,0x00,0x00,0x00,0x10,0x69,0x00,0x22,0x3c,0x02,0x34,0x34,0x91,0x02,0x00,0x04, +0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x06,0x00,0x03,0x20,0xc0,0x24,0x02,0x00,0x01, +0xa1,0x02,0x00,0x04,0xa5,0x09,0x00,0x02,0x03,0xe0,0x00,0x08,0xa5,0x09,0x00,0x00, +0x00,0x83,0x20,0x21,0x27,0x87,0x8f,0xf0,0x00,0x04,0x20,0x80,0x00,0x87,0x20,0x21, +0x94,0x83,0x00,0x04,0x3c,0x02,0xb0,0x08,0x3c,0x06,0xb0,0x03,0x00,0x03,0x28,0xc0, +0x00,0xa3,0x18,0x21,0x00,0x03,0x18,0x80,0x00,0xa2,0x28,0x21,0x3c,0x02,0x80,0x01, +0x24,0x42,0x82,0xe4,0x00,0x67,0x18,0x21,0x34,0xc6,0x00,0x20,0xac,0xc2,0x00,0x00, +0xa4,0x69,0x00,0x00,0xa4,0x89,0x00,0x02,0xac,0xa9,0x00,0x00,0x91,0x02,0x00,0x04, +0xa5,0x09,0x00,0x02,0x24,0x42,0x00,0x01,0x03,0xe0,0x00,0x08,0xa1,0x02,0x00,0x04, +0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0xb0,0x34,0x42,0x34,0x34,0x03,0xe0,0x00,0x08, +0xac,0x62,0x00,0x00,0x90,0x82,0x00,0x16,0x00,0x00,0x00,0x00,0x34,0x42,0x00,0x01, +0x30,0x43,0x00,0x02,0x14,0x60,0xff,0xd1,0xa0,0x82,0x00,0x16,0x24,0x02,0x00,0x01, +0x08,0x00,0x1a,0xab,0xa0,0x82,0x00,0x17,0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x10, +0x00,0x80,0x38,0x21,0x84,0x84,0x00,0x02,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00, +0x3c,0x0a,0xb0,0x06,0x34,0x63,0x00,0x20,0x24,0x42,0x6b,0x78,0x3c,0x0b,0xb0,0x08, +0x27,0x89,0x8f,0xf0,0x34,0x0c,0xff,0xff,0x35,0x4a,0x80,0x20,0x10,0x80,0x00,0x30, +0xac,0x62,0x00,0x00,0x97,0x82,0x8f,0xe0,0x94,0xe6,0x02,0xba,0x00,0x02,0x18,0xc0, +0x00,0x6b,0x28,0x21,0xac,0xa6,0x00,0x00,0x8c,0xe4,0x02,0xb8,0x00,0x62,0x18,0x21, +0x00,0x03,0x18,0x80,0x00,0x04,0x10,0xc0,0x00,0x44,0x10,0x21,0x00,0x02,0x10,0x80, +0x00,0x49,0x10,0x21,0x94,0x48,0x00,0x04,0x00,0x69,0x18,0x21,0xa4,0x66,0x00,0x00, +0x00,0x08,0x28,0xc0,0x00,0xab,0x10,0x21,0xac,0x4c,0x00,0x00,0x8c,0xe4,0x02,0xb8, +0x27,0x82,0x8f,0xf4,0x00,0xa8,0x28,0x21,0x00,0x04,0x18,0xc0,0x00,0x64,0x18,0x21, +0x00,0x03,0x18,0x80,0x00,0x62,0x10,0x21,0x8c,0x46,0x00,0x18,0x27,0x84,0x90,0x00, +0x00,0x64,0x18,0x21,0x8c,0xc2,0x00,0x00,0x80,0x67,0x00,0x06,0x00,0x05,0x28,0x80, +0x30,0x42,0xff,0xff,0x00,0x47,0x10,0x21,0x30,0x43,0x00,0xff,0x00,0x03,0x18,0x2b, +0x00,0x02,0x12,0x02,0x00,0x43,0x10,0x21,0x3c,0x04,0x00,0x04,0x00,0xa9,0x28,0x21, +0x00,0x44,0x10,0x25,0xa4,0xac,0x00,0x00,0xad,0x42,0x00,0x00,0xa7,0x88,0x8f,0xe0, +0x8f,0xbf,0x00,0x10,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18, +0x84,0xe3,0x00,0x06,0x27,0x82,0xb3,0xf0,0x94,0xe5,0x02,0xba,0x00,0x03,0x18,0x80, +0x00,0x62,0x18,0x21,0x8c,0x64,0x00,0x00,0x0c,0x00,0x1a,0x95,0x00,0x00,0x00,0x00, +0x08,0x00,0x1b,0x18,0x00,0x00,0x00,0x00,0x94,0x88,0x00,0x00,0x00,0x80,0x58,0x21, +0x27,0x8a,0x8f,0xf0,0x00,0x08,0x18,0xc0,0x00,0x68,0x18,0x21,0x3c,0x04,0xb0,0x03, +0x00,0x03,0x18,0x80,0x3c,0x02,0x80,0x00,0x00,0x6a,0x18,0x21,0x34,0x84,0x00,0x20, +0x24,0x42,0x6c,0x98,0x30,0xa5,0xff,0xff,0xac,0x82,0x00,0x00,0x94,0x67,0x00,0x02, +0x11,0x05,0x00,0x35,0x24,0x04,0x00,0x01,0x91,0x66,0x00,0x04,0x00,0x00,0x00,0x00, +0x00,0x86,0x10,0x2a,0x10,0x40,0x00,0x10,0x00,0xc0,0x48,0x21,0x3c,0x0d,0xb0,0x03, +0x01,0x40,0x60,0x21,0x35,0xad,0x00,0x20,0x10,0xe5,0x00,0x0d,0x24,0x84,0x00,0x01, +0x00,0x07,0x10,0xc0,0x00,0x47,0x10,0x21,0x00,0x02,0x10,0x80,0x01,0x20,0x30,0x21, +0x00,0x4a,0x10,0x21,0x00,0x86,0x18,0x2a,0x00,0xe0,0x40,0x21,0x94,0x47,0x00,0x02, +0x14,0x60,0xff,0xf5,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x10,0x21, +0x00,0x08,0x20,0xc0,0x00,0x88,0x20,0x21,0x24,0xc2,0xff,0xff,0x00,0x04,0x20,0x80, +0xa1,0x62,0x00,0x04,0x00,0x8c,0x20,0x21,0x94,0x83,0x00,0x04,0x00,0x07,0x10,0xc0, +0x00,0x47,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x4c,0x10,0x21,0x00,0x03,0x28,0xc0, +0x94,0x46,0x00,0x02,0x00,0xa3,0x18,0x21,0x00,0x03,0x18,0x80,0x00,0x6c,0x18,0x21, +0xa4,0x66,0x00,0x00,0xa4,0x86,0x00,0x02,0x95,0x64,0x00,0x02,0x3c,0x03,0xb0,0x08, +0x3c,0x02,0x80,0x01,0x00,0xa3,0x28,0x21,0x24,0x42,0x82,0xe4,0xad,0xa2,0x00,0x00, +0x10,0x87,0x00,0x03,0xac,0xa6,0x00,0x00,0x03,0xe0,0x00,0x08,0x24,0x02,0x00,0x01, +0x08,0x00,0x1b,0x66,0xa5,0x68,0x00,0x02,0x91,0x62,0x00,0x04,0xa5,0x67,0x00,0x00, +0x24,0x42,0xff,0xff,0x30,0x43,0x00,0xff,0x14,0x60,0x00,0x03,0xa1,0x62,0x00,0x04, +0x24,0x02,0xff,0xff,0xa5,0x62,0x00,0x02,0x91,0x65,0x00,0x04,0x00,0x00,0x00,0x00, +0x10,0xa0,0xff,0xf1,0x00,0x00,0x00,0x00,0x95,0x66,0x00,0x00,0x34,0x02,0xff,0xff, +0x14,0xc2,0xff,0xed,0x3c,0x03,0xb0,0x03,0x95,0x64,0x00,0x02,0x3c,0x02,0xee,0xee, +0x00,0xa2,0x10,0x25,0x34,0x63,0x00,0xbc,0xac,0x62,0x00,0x00,0x10,0x86,0xff,0xe6, +0xa1,0x60,0x00,0x04,0x24,0x02,0xff,0xff,0x08,0x00,0x1b,0x66,0xa5,0x62,0x00,0x02, +0x00,0x05,0x40,0xc0,0x01,0x05,0x30,0x21,0x27,0xbd,0xff,0xd8,0x00,0x06,0x30,0x80, +0x27,0x82,0x8f,0xf4,0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xbf,0x00,0x20, +0xaf,0xb3,0x00,0x1c,0xaf,0xb0,0x00,0x10,0x00,0xc2,0x10,0x21,0x8c,0x47,0x00,0x18, +0x00,0xa0,0x90,0x21,0x3c,0x02,0x80,0x00,0x3c,0x05,0xb0,0x03,0x34,0xa5,0x00,0x20, +0x24,0x42,0x6e,0x10,0xac,0xa2,0x00,0x00,0x27,0x83,0x90,0x00,0x00,0xc3,0x30,0x21, +0x8c,0xe2,0x00,0x00,0x80,0xc5,0x00,0x06,0x00,0x80,0x88,0x21,0x30,0x42,0xff,0xff, +0x00,0x45,0x10,0x21,0x30,0x43,0x00,0xff,0x10,0x60,0x00,0x02,0x00,0x02,0x12,0x02, +0x24,0x42,0x00,0x01,0x30,0x53,0x00,0xff,0x01,0x12,0x10,0x21,0x00,0x02,0x10,0x80, +0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0x80,0x44,0x00,0x07,0x00,0x00,0x00,0x00, +0x10,0x80,0x00,0x4b,0x26,0x24,0x00,0x06,0x32,0x50,0xff,0xff,0x02,0x20,0x20,0x21, +0x0c,0x00,0x1b,0x26,0x02,0x00,0x28,0x21,0x92,0x22,0x00,0x10,0x00,0x00,0x00,0x00, +0x14,0x40,0x00,0x2e,0x3c,0x03,0xb0,0x08,0x3c,0x09,0x80,0x01,0x27,0x88,0x8f,0xf0, +0xa6,0x32,0x00,0x0c,0x00,0x10,0x20,0xc0,0x00,0x90,0x20,0x21,0x00,0x04,0x20,0x80, +0x00,0x88,0x20,0x21,0x94,0x82,0x00,0x04,0x3c,0x03,0xb0,0x08,0x3c,0x07,0xb0,0x03, +0x00,0x02,0x28,0xc0,0x00,0xa2,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x48,0x10,0x21, +0x00,0xa3,0x28,0x21,0x25,0x26,0x82,0xe4,0x34,0x03,0xff,0xff,0x34,0xe7,0x00,0x20, +0xac,0xe6,0x00,0x00,0xa4,0x83,0x00,0x02,0xa4,0x43,0x00,0x00,0xac,0xa3,0x00,0x00, +0x92,0x22,0x00,0x10,0x92,0x23,0x00,0x0a,0xa6,0x32,0x00,0x0e,0x02,0x62,0x10,0x21, +0x14,0x60,0x00,0x05,0xa2,0x22,0x00,0x10,0x92,0x22,0x00,0x16,0x00,0x00,0x00,0x00, +0x30,0x42,0x00,0xfe,0xa2,0x22,0x00,0x16,0x92,0x22,0x00,0x04,0x00,0x00,0x00,0x00, +0x14,0x40,0x00,0x05,0x00,0x00,0x00,0x00,0x92,0x22,0x00,0x16,0x00,0x00,0x00,0x00, +0x30,0x42,0x00,0xfd,0xa2,0x22,0x00,0x16,0x8f,0xbf,0x00,0x20,0x7b,0xb2,0x00,0xfc, +0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28,0x96,0x22,0x00,0x0e, +0x27,0x88,0x8f,0xf0,0x00,0x02,0x20,0xc0,0x00,0x82,0x20,0x21,0x00,0x04,0x20,0x80, +0x00,0x88,0x20,0x21,0x94,0x82,0x00,0x04,0x3c,0x06,0xb0,0x03,0x3c,0x09,0x80,0x01, +0x00,0x02,0x28,0xc0,0x00,0xa2,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0xa3,0x28,0x21, +0x00,0x48,0x10,0x21,0x34,0xc6,0x00,0x20,0x25,0x23,0x82,0xe4,0xac,0xc3,0x00,0x00, +0xa4,0x50,0x00,0x00,0xac,0xb0,0x00,0x00,0x08,0x00,0x1b,0xb5,0xa4,0x90,0x00,0x02, +0x08,0x00,0x1b,0xac,0x32,0x50,0xff,0xff,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00, +0x24,0x42,0x6f,0xd8,0x34,0x63,0x00,0x20,0xac,0x62,0x00,0x00,0x90,0x82,0x00,0x04, +0x97,0xaa,0x00,0x12,0x00,0x80,0x60,0x21,0x30,0xa8,0xff,0xff,0x00,0x4a,0x20,0x23, +0x34,0x09,0xff,0xff,0x30,0xcf,0xff,0xff,0x30,0xee,0xff,0xff,0x11,0x09,0x00,0x73, +0xa1,0x84,0x00,0x04,0x00,0x0e,0xc0,0xc0,0x00,0x08,0x10,0xc0,0x00,0x48,0x10,0x21, +0x03,0x0e,0x20,0x21,0x27,0x8d,0x8f,0xf0,0x00,0x04,0x20,0x80,0x00,0x02,0x10,0x80, +0x00,0x4d,0x10,0x21,0x00,0x8d,0x20,0x21,0x94,0x86,0x00,0x02,0x94,0x43,0x00,0x04, +0x3c,0x19,0x80,0x01,0xa4,0x46,0x00,0x02,0x00,0x03,0x28,0xc0,0x00,0xa3,0x18,0x21, +0x94,0x87,0x00,0x02,0x3c,0x02,0xb0,0x08,0x00,0x03,0x18,0x80,0x00,0xa2,0x28,0x21, +0x00,0x6d,0x18,0x21,0x27,0x22,0x82,0xe4,0x3c,0x01,0xb0,0x03,0xac,0x22,0x00,0x20, +0xa4,0x66,0x00,0x00,0x10,0xe9,0x00,0x57,0xac,0xa6,0x00,0x00,0x01,0xe0,0x30,0x21, +0x11,0x40,0x00,0x1d,0x00,0x00,0x48,0x21,0x01,0x40,0x38,0x21,0x27,0x8b,0x8f,0xf4, +0x27,0x8a,0x90,0x00,0x00,0x06,0x40,0xc0,0x01,0x06,0x18,0x21,0x00,0x03,0x18,0x80, +0x00,0x6b,0x10,0x21,0x8c,0x44,0x00,0x18,0x00,0x6a,0x18,0x21,0x80,0x65,0x00,0x06, +0x8c,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0xff,0xff,0x00,0x45,0x10,0x21, +0x30,0x44,0x00,0xff,0x00,0x02,0x12,0x02,0x01,0x22,0x18,0x21,0x24,0x62,0x00,0x01, +0x14,0x80,0x00,0x02,0x30,0x49,0x00,0xff,0x30,0x69,0x00,0xff,0x01,0x06,0x10,0x21, +0x00,0x02,0x10,0x80,0x00,0x4d,0x10,0x21,0x24,0xe7,0xff,0xff,0x94,0x46,0x00,0x02, +0x14,0xe0,0xff,0xe9,0x00,0x06,0x40,0xc0,0x91,0x82,0x00,0x10,0x00,0x00,0x00,0x00, +0x14,0x40,0x00,0x20,0x3c,0x06,0xb0,0x03,0xa5,0x8f,0x00,0x0c,0x03,0x0e,0x20,0x21, +0x00,0x04,0x20,0x80,0x00,0x8d,0x20,0x21,0x94,0x82,0x00,0x04,0x3c,0x03,0xb0,0x08, +0x3c,0x07,0xb0,0x03,0x00,0x02,0x28,0xc0,0x00,0xa2,0x10,0x21,0x00,0x02,0x10,0x80, +0x00,0x4d,0x10,0x21,0x00,0xa3,0x28,0x21,0x27,0x26,0x82,0xe4,0x34,0x03,0xff,0xff, +0x34,0xe7,0x00,0x20,0xac,0xe6,0x00,0x00,0xa4,0x83,0x00,0x02,0xa4,0x43,0x00,0x00, +0xac,0xa3,0x00,0x00,0x91,0x82,0x00,0x10,0x91,0x83,0x00,0x04,0xa5,0x8e,0x00,0x0e, +0x01,0x22,0x10,0x21,0x14,0x60,0x00,0x05,0xa1,0x82,0x00,0x10,0x91,0x82,0x00,0x16, +0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xfd,0xa1,0x82,0x00,0x16,0x03,0xe0,0x00,0x08, +0x00,0x00,0x00,0x00,0x95,0x82,0x00,0x0e,0x3c,0x03,0xb0,0x08,0x00,0x02,0x20,0xc0, +0x00,0x82,0x20,0x21,0x00,0x04,0x20,0x80,0x00,0x8d,0x20,0x21,0x94,0x82,0x00,0x04, +0x34,0xc6,0x00,0x20,0x27,0x27,0x82,0xe4,0x00,0x02,0x28,0xc0,0x00,0xa2,0x10,0x21, +0x00,0x02,0x10,0x80,0x00,0xa3,0x28,0x21,0x00,0x4d,0x10,0x21,0xac,0xc7,0x00,0x00, +0xa4,0x8f,0x00,0x02,0xa4,0x4f,0x00,0x00,0xac,0xaf,0x00,0x00,0x08,0x00,0x1c,0x44, +0x03,0x0e,0x20,0x21,0x08,0x00,0x1c,0x1f,0xa5,0x88,0x00,0x02,0x00,0x0e,0xc0,0xc0, +0x03,0x0e,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x8d,0x8f,0xf0,0x00,0x4d,0x10,0x21, +0x94,0x43,0x00,0x02,0x30,0x84,0x00,0xff,0x14,0x80,0x00,0x05,0xa5,0x83,0x00,0x00, +0x24,0x02,0xff,0xff,0x3c,0x19,0x80,0x01,0x08,0x00,0x1c,0x1f,0xa5,0x82,0x00,0x02, +0x08,0x00,0x1c,0x1f,0x3c,0x19,0x80,0x01,0x3c,0x08,0xb0,0x03,0x3c,0x02,0x80,0x00, +0x27,0xbd,0xff,0x78,0x35,0x08,0x00,0x20,0x24,0x42,0x72,0x18,0xaf,0xb2,0x00,0x68, +0xaf,0xb1,0x00,0x64,0xaf,0xb0,0x00,0x60,0xad,0x02,0x00,0x00,0xaf,0xbf,0x00,0x84, +0xaf,0xbe,0x00,0x80,0xaf,0xb7,0x00,0x7c,0xaf,0xb6,0x00,0x78,0xaf,0xb5,0x00,0x74, +0xaf,0xb4,0x00,0x70,0xaf,0xb3,0x00,0x6c,0xaf,0xa4,0x00,0x88,0x90,0x83,0x00,0x0a, +0x27,0x82,0xb3,0xf0,0xaf,0xa6,0x00,0x90,0x00,0x03,0x18,0x80,0x00,0x62,0x18,0x21, +0x8c,0x63,0x00,0x00,0xaf,0xa7,0x00,0x94,0x27,0x86,0x8f,0xf4,0xaf,0xa3,0x00,0x1c, +0x94,0x63,0x00,0x14,0x30,0xb1,0xff,0xff,0x24,0x08,0x00,0x01,0x00,0x03,0x20,0xc0, +0xaf,0xa3,0x00,0x18,0x00,0x83,0x18,0x21,0xaf,0xa4,0x00,0x54,0x00,0x03,0x18,0x80, +0x27,0x84,0x90,0x00,0x00,0x64,0x20,0x21,0x80,0x82,0x00,0x06,0x00,0x66,0x18,0x21, +0x8c,0x66,0x00,0x18,0x24,0x42,0x00,0x02,0x00,0x02,0x1f,0xc2,0x8c,0xc4,0x00,0x08, +0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x43,0x00,0x02,0x10,0x40,0x00,0x04,0x2f,0xc2, +0x00,0x04,0x1c,0x82,0x00,0xc2,0x38,0x21,0x00,0x04,0x24,0x42,0x8f,0xa2,0x00,0x1c, +0x30,0x63,0x00,0x01,0x30,0x84,0x00,0x01,0xaf,0xa5,0x00,0x3c,0xaf,0xa3,0x00,0x34, +0xaf,0xa4,0x00,0x38,0xaf,0xa0,0x00,0x40,0xaf,0xa0,0x00,0x44,0xaf,0xa0,0x00,0x50, +0xaf,0xa8,0x00,0x20,0x80,0x42,0x00,0x12,0x8f,0xb2,0x00,0x18,0xaf,0xa2,0x00,0x28, +0x8c,0xd0,0x00,0x0c,0x14,0xa0,0x01,0xe4,0x00,0x60,0x30,0x21,0x00,0x10,0x10,0x82, +0x30,0x45,0x00,0x07,0x10,0xa0,0x00,0x11,0xaf,0xa0,0x00,0x30,0x8f,0xa4,0x00,0x98, +0x27,0x82,0x80,0x1c,0x00,0x04,0x18,0x40,0x00,0x62,0x18,0x21,0x24,0xa2,0x00,0x06, +0x8f,0xa5,0x00,0x20,0x94,0x64,0x00,0x00,0x00,0x45,0x10,0x04,0x00,0x44,0x00,0x1a, +0x14,0x80,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0d,0x00,0x00,0x10,0x12, +0x24,0x42,0x00,0x20,0x30,0x42,0xff,0xfc,0xaf,0xa2,0x00,0x30,0x8f,0xa3,0x00,0x18, +0x8f,0xa4,0x00,0x28,0x34,0x02,0xff,0xff,0xaf,0xa0,0x00,0x2c,0xaf,0xa2,0x00,0x48, +0xaf,0xa3,0x00,0x4c,0x00,0x60,0xf0,0x21,0x00,0x00,0xb8,0x21,0x18,0x80,0x00,0x48, +0xaf,0xa0,0x00,0x24,0x00,0x11,0x89,0x02,0xaf,0xb1,0x00,0x58,0x00,0x80,0xa8,0x21, +0x00,0x12,0x10,0xc0,0x00,0x52,0x18,0x21,0x00,0x03,0x80,0x80,0x27,0x85,0x8f,0xf0, +0x02,0x40,0x20,0x21,0x00,0x40,0xa0,0x21,0x02,0x05,0x10,0x21,0x94,0x56,0x00,0x02, +0x0c,0x00,0x12,0x87,0x00,0x00,0x28,0x21,0x90,0x42,0x00,0x00,0x24,0x03,0x00,0x08, +0x30,0x42,0x00,0x0c,0x10,0x43,0x01,0x9e,0x24,0x04,0x00,0x01,0x24,0x02,0x00,0x01, +0x10,0x82,0x01,0x7c,0x3c,0x02,0xb0,0x03,0x8f,0xa6,0x00,0x88,0x34,0x42,0x01,0x04, +0x84,0xc5,0x00,0x0c,0x02,0x92,0x18,0x21,0x94,0x46,0x00,0x00,0x00,0x05,0x20,0xc0, +0x00,0x85,0x20,0x21,0x00,0x03,0x18,0x80,0x27,0x82,0x90,0x00,0x27,0x85,0x8f,0xf8, +0x00,0x65,0x28,0x21,0x00,0x62,0x18,0x21,0x80,0x71,0x00,0x05,0x80,0x73,0x00,0x04, +0x8f,0xa3,0x00,0x88,0x30,0xd0,0xff,0xff,0x00,0x10,0x3a,0x03,0x32,0x08,0x00,0xff, +0x27,0x82,0x90,0x10,0x00,0x04,0x20,0x80,0x80,0xa6,0x00,0x06,0x00,0x82,0x20,0x21, +0xa4,0x67,0x00,0x44,0xa4,0x68,0x00,0x46,0x8c,0x84,0x00,0x00,0x38,0xc6,0x00,0x00, +0x01,0x00,0x80,0x21,0x00,0x04,0x15,0x02,0x30,0x42,0x00,0x01,0x10,0x40,0x00,0x03, +0x00,0xe6,0x80,0x0a,0x00,0x04,0x14,0x02,0x30,0x50,0x00,0x0f,0x12,0x20,0x01,0x50, +0x02,0x40,0x20,0x21,0x02,0x71,0x10,0x21,0x00,0x50,0x10,0x2a,0x14,0x40,0x00,0xed, +0x02,0x92,0x10,0x21,0x93,0x82,0x8b,0x61,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01, +0x14,0x40,0x00,0xe0,0x02,0x92,0x28,0x21,0x26,0xe2,0x00,0x01,0x30,0x57,0xff,0xff, +0x02,0x40,0xf0,0x21,0x26,0xb5,0xff,0xff,0x16,0xa0,0xff,0xbd,0x02,0xc0,0x90,0x21, +0x16,0xe0,0x00,0xd0,0x00,0x00,0x00,0x00,0x8f,0xa3,0x00,0x98,0x00,0x00,0x00,0x00, +0x2c,0x62,0x00,0x10,0x10,0x40,0x00,0x2e,0x00,0x00,0x00,0x00,0x8f,0xa4,0x00,0x24, +0x00,0x00,0x00,0x00,0x18,0x80,0x00,0x2a,0x24,0x03,0x00,0x01,0x8f,0xa5,0x00,0x1c, +0x27,0x84,0x8f,0xf4,0x94,0xb2,0x00,0x14,0xa0,0xa3,0x00,0x12,0x8f,0xa6,0x00,0x3c, +0x00,0x12,0x10,0xc0,0x00,0x52,0x10,0x21,0x00,0x02,0x80,0x80,0x27,0x82,0x90,0x00, +0x02,0x02,0x10,0x21,0x80,0x43,0x00,0x06,0x02,0x04,0x20,0x21,0x8c,0x85,0x00,0x18, +0x24,0x63,0x00,0x02,0x00,0x03,0x17,0xc2,0x00,0x62,0x18,0x21,0x00,0x03,0x18,0x43, +0x00,0x03,0x18,0x40,0x14,0xc0,0x00,0x0e,0x00,0xa3,0x38,0x21,0x27,0x82,0x8f,0xf0, +0x02,0x02,0x10,0x21,0x94,0x43,0x00,0x06,0x8f,0xa8,0x00,0x1c,0x24,0x02,0x00,0x01, +0xa5,0x03,0x00,0x1a,0x7b,0xbe,0x04,0x3c,0x7b,0xb6,0x03,0xfc,0x7b,0xb4,0x03,0xbc, +0x7b,0xb2,0x03,0x7c,0x7b,0xb0,0x03,0x3c,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x88, +0x8f,0xa4,0x00,0x98,0x8f,0xa5,0x00,0x38,0x8f,0xa6,0x00,0x34,0xaf,0xa0,0x00,0x10, +0x0c,0x00,0x09,0x06,0xaf,0xa0,0x00,0x14,0x08,0x00,0x1d,0x4b,0x00,0x00,0x00,0x00, +0x8f,0xa3,0x00,0x44,0x93,0x82,0x81,0x59,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x61, +0x30,0x69,0x00,0x03,0x8f,0xa4,0x00,0x24,0x8f,0xa5,0x00,0x28,0x00,0x00,0x00,0x00, +0x00,0x85,0x10,0x2a,0x10,0x40,0x00,0x8f,0x00,0x00,0x00,0x00,0x8f,0xa6,0x00,0x1c, +0x00,0x00,0x00,0x00,0x90,0xc4,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x83,0x00,0xff, +0x00,0xa3,0x10,0x2a,0x10,0x40,0x00,0x87,0x00,0x00,0x00,0x00,0x8f,0xa8,0x00,0x24, +0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x83,0x00,0x65,0x10,0x23,0x00,0xa8,0x18,0x23, +0x00,0x62,0x10,0x2a,0x14,0x40,0x00,0x7d,0x30,0x63,0x00,0xff,0x00,0x85,0x10,0x23, +0x30,0x42,0x00,0xff,0xaf,0xa2,0x00,0x50,0x8f,0xa2,0x00,0x50,0x00,0x00,0x00,0x00, +0x10,0x40,0x00,0x73,0x00,0x00,0xa8,0x21,0x27,0x8c,0x8f,0xf0,0x3c,0x0b,0x80,0xff, +0x24,0x10,0x00,0x04,0x27,0x91,0x8f,0xf4,0x35,0x6b,0xff,0xff,0x3c,0x0d,0x7f,0x00, +0x27,0x8e,0x90,0x00,0x01,0x80,0x78,0x21,0x00,0x12,0x30,0xc0,0x00,0xd2,0x10,0x21, +0x00,0x02,0x10,0x80,0x00,0x4c,0x10,0x21,0x94,0x42,0x00,0x06,0x8f,0xa3,0x00,0x2c, +0x8f,0xa4,0x00,0x30,0xaf,0xa2,0x00,0x44,0x8f,0xa5,0x00,0x44,0x30,0x49,0x00,0x03, +0x02,0x09,0x10,0x23,0x30,0x42,0x00,0x03,0x00,0xa2,0x10,0x21,0x8f,0xa8,0x00,0x30, +0x24,0x42,0x00,0x04,0x30,0x42,0xff,0xff,0x00,0x64,0x38,0x21,0x01,0x02,0x28,0x23, +0x00,0x62,0x18,0x21,0x00,0x48,0x10,0x2b,0x10,0x40,0x00,0x52,0x00,0x00,0x20,0x21, +0x30,0xe7,0xff,0xff,0x30,0xa4,0xff,0xff,0xaf,0xa7,0x00,0x2c,0x00,0xd2,0x10,0x21, +0x00,0x02,0x10,0x80,0x00,0x51,0x18,0x21,0x8c,0x65,0x00,0x18,0x00,0x04,0x25,0x40, +0x00,0x8d,0x20,0x24,0x8c,0xa8,0x00,0x04,0x00,0x4e,0x18,0x21,0x00,0x4f,0x50,0x21, +0x01,0x0b,0x40,0x24,0x01,0x04,0x40,0x25,0xac,0xa8,0x00,0x04,0x8f,0xa4,0x00,0x98, +0x8f,0xa2,0x00,0x50,0x26,0xb5,0x00,0x01,0xa0,0x64,0x00,0x00,0x8c,0xa4,0x00,0x08, +0x00,0x00,0x00,0x00,0x04,0x81,0x00,0x0c,0x02,0xa2,0x30,0x2a,0x80,0x62,0x00,0x06, +0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x02,0x00,0x02,0x1f,0xc2,0x00,0x43,0x10,0x21, +0x00,0x02,0x10,0x43,0x00,0x02,0x10,0x40,0x00,0xa2,0x38,0x21,0x8f,0xa5,0x00,0x40, +0x00,0x00,0x00,0x00,0xa4,0xe5,0x00,0x00,0x95,0x52,0x00,0x02,0x14,0xc0,0xff,0xc7, +0x00,0x12,0x30,0xc0,0x8f,0xa4,0x00,0x24,0x8f,0xa5,0x00,0x50,0x8f,0xa6,0x00,0x1c, +0x8f,0xa3,0x00,0x2c,0x00,0x85,0x80,0x21,0xa0,0xd0,0x00,0x12,0x00,0x09,0x10,0x23, +0x30,0x42,0x00,0x03,0x8f,0xa8,0x00,0x88,0x00,0x62,0x10,0x23,0xa4,0xc2,0x00,0x1a, +0x85,0x03,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +0x00,0x02,0x10,0x80,0x27,0x83,0x8f,0xf4,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x18, +0x00,0x00,0x00,0x00,0x8c,0x83,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x10, +0x14,0x60,0xff,0x74,0x02,0x00,0x10,0x21,0x8f,0xa3,0x00,0x54,0x8f,0xa4,0x00,0x18, +0x8f,0xa5,0x00,0x24,0x00,0x64,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x08, +0x00,0x43,0x10,0x21,0x90,0x44,0x00,0x00,0x10,0xa0,0x00,0x03,0x00,0x00,0x30,0x21, +0x08,0x00,0x1d,0x51,0x02,0x00,0x10,0x21,0x93,0x82,0x80,0x10,0x00,0x00,0x28,0x21, +0x00,0x00,0x38,0x21,0x0c,0x00,0x21,0xf5,0xaf,0xa2,0x00,0x10,0x08,0x00,0x1d,0x51, +0x02,0x00,0x10,0x21,0x30,0x63,0xff,0xff,0x08,0x00,0x1d,0xa3,0xaf,0xa3,0x00,0x2c, +0x8f,0xa8,0x00,0x44,0x08,0x00,0x1d,0xc5,0x31,0x09,0x00,0x03,0x08,0x00,0x1d,0x7e, +0xaf,0xa3,0x00,0x50,0x8f,0xa6,0x00,0x44,0xaf,0xa0,0x00,0x50,0x08,0x00,0x1d,0xc5, +0x30,0xc9,0x00,0x03,0x8f,0xa5,0x00,0x48,0x8f,0xa6,0x00,0x4c,0x8f,0xa4,0x00,0x1c, +0x03,0xc0,0x38,0x21,0x0c,0x00,0x1b,0xf6,0xaf,0xb7,0x00,0x10,0x08,0x00,0x1d,0x2e, +0x00,0x00,0x00,0x00,0x00,0x05,0x28,0x80,0x27,0x82,0x8f,0xf0,0x00,0xa2,0x28,0x21, +0x00,0x00,0x20,0x21,0x0c,0x00,0x01,0x4b,0x00,0x00,0x00,0x00,0x08,0x00,0x1d,0x27, +0x26,0xe2,0x00,0x01,0x00,0x02,0x80,0x80,0x27,0x83,0x90,0x00,0x8f,0xa4,0x00,0x1c, +0x02,0x03,0x18,0x21,0x26,0x31,0x00,0x01,0x02,0x40,0x28,0x21,0x0c,0x00,0x1f,0x08, +0xa0,0x71,0x00,0x05,0x14,0x40,0xff,0x13,0x00,0x00,0x00,0x00,0x16,0xe0,0x00,0x4d, +0x03,0xc0,0x38,0x21,0x8f,0xa4,0x00,0x24,0x8f,0xa5,0x00,0x20,0x24,0x02,0x00,0x01, +0x24,0x84,0x00,0x01,0xaf,0xb2,0x00,0x48,0xaf,0xb6,0x00,0x4c,0x02,0xc0,0xf0,0x21, +0x10,0xa2,0x00,0x41,0xaf,0xa4,0x00,0x24,0x27,0x82,0x8f,0xf0,0x02,0x02,0x10,0x21, +0x94,0x42,0x00,0x06,0x8f,0xa4,0x00,0x30,0xaf,0xa0,0x00,0x20,0xaf,0xa2,0x00,0x44, +0x30,0x49,0x00,0x03,0x8f,0xa8,0x00,0x44,0x00,0x09,0x10,0x23,0x30,0x42,0x00,0x03, +0x01,0x02,0x10,0x21,0x24,0x42,0x00,0x04,0x30,0x42,0xff,0xff,0x00,0x44,0x18,0x2b, +0x10,0x60,0x00,0x2b,0x00,0x00,0x00,0x00,0x8f,0xa5,0x00,0x2c,0x00,0x82,0x10,0x23, +0x00,0xa4,0x18,0x21,0x30,0x63,0xff,0xff,0x30,0x44,0xff,0xff,0xaf,0xa3,0x00,0x2c, +0x02,0x92,0x28,0x21,0x00,0x05,0x28,0x80,0x27,0x82,0x8f,0xf4,0x00,0xa2,0x10,0x21, +0x8c,0x46,0x00,0x18,0x3c,0x03,0x80,0xff,0x3c,0x02,0x7f,0x00,0x8c,0xc8,0x00,0x04, +0x00,0x04,0x25,0x40,0x34,0x63,0xff,0xff,0x00,0x82,0x20,0x24,0x01,0x03,0x40,0x24, +0x01,0x04,0x40,0x25,0xac,0xc8,0x00,0x04,0x8f,0xa8,0x00,0x98,0x27,0x82,0x90,0x00, +0x00,0xa2,0x10,0x21,0xa0,0x48,0x00,0x00,0x8c,0xc4,0x00,0x08,0x00,0x00,0x00,0x00, +0x00,0x04,0x27,0xc2,0x10,0x80,0xfe,0xdb,0xaf,0xa4,0x00,0x3c,0x80,0x42,0x00,0x06, +0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x02,0x00,0x02,0x1f,0xc2,0x00,0x43,0x10,0x21, +0x00,0x02,0x10,0x43,0x00,0x02,0x10,0x40,0x00,0xc2,0x38,0x21,0x8f,0xa2,0x00,0x40, +0x00,0x00,0x00,0x00,0xa4,0xe2,0x00,0x00,0x08,0x00,0x1d,0x2a,0x26,0xb5,0xff,0xff, +0x8f,0xa6,0x00,0x2c,0x00,0x00,0x20,0x21,0x00,0xc2,0x10,0x21,0x30,0x42,0xff,0xff, +0x08,0x00,0x1e,0x38,0xaf,0xa2,0x00,0x2c,0x8f,0xa6,0x00,0x1c,0x08,0x00,0x1e,0x22, +0xa4,0xd2,0x00,0x14,0x8f,0xa5,0x00,0x48,0x8f,0xa6,0x00,0x4c,0x8f,0xa4,0x00,0x1c, +0x0c,0x00,0x1b,0xf6,0xaf,0xb7,0x00,0x10,0x08,0x00,0x1e,0x19,0x00,0x00,0xb8,0x21, +0x0c,0x00,0x12,0x87,0x00,0x00,0x28,0x21,0x00,0x40,0x18,0x21,0x94,0x42,0x00,0x00, +0x00,0x00,0x00,0x00,0x34,0x42,0x08,0x00,0xa4,0x62,0x00,0x00,0x08,0x00,0x1d,0x1e, +0x02,0x71,0x10,0x21,0x02,0x92,0x18,0x21,0x00,0x03,0x80,0x80,0x27,0x82,0x8f,0xf4, +0x02,0x02,0x10,0x21,0x8c,0x44,0x00,0x18,0x00,0x00,0x00,0x00,0x8c,0x83,0x00,0x04, +0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x10,0x10,0x60,0x00,0x09,0x24,0x06,0x00,0x01, +0x93,0x82,0x8b,0x61,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x10,0x40,0xfe,0xa2, +0x3c,0x04,0x00,0x80,0x27,0x85,0x8f,0xf0,0x08,0x00,0x1e,0x09,0x02,0x05,0x28,0x21, +0x27,0x83,0x90,0x08,0x27,0x82,0x90,0x00,0x02,0x03,0x18,0x21,0x02,0x02,0x10,0x21, +0x90,0x64,0x00,0x00,0x90,0x45,0x00,0x05,0x93,0x83,0x80,0x10,0x00,0x00,0x38,0x21, +0x0c,0x00,0x21,0xf5,0xaf,0xa3,0x00,0x10,0x08,0x00,0x1e,0x80,0x00,0x00,0x00,0x00, +0x27,0x82,0x90,0x08,0x02,0x02,0x10,0x21,0x94,0x43,0x00,0x02,0x8f,0xa6,0x00,0x58, +0x00,0x03,0x19,0x02,0x00,0x66,0x18,0x23,0x30,0x63,0x0f,0xff,0x28,0x62,0x00,0x20, +0x10,0x40,0x00,0x06,0x28,0x62,0x00,0x40,0x8f,0xa8,0x00,0x90,0x00,0x00,0x00,0x00, +0x00,0x68,0x10,0x06,0x08,0x00,0x1c,0xf7,0x30,0x44,0x00,0x01,0x10,0x40,0x00,0x04, +0x00,0x00,0x00,0x00,0x8f,0xa4,0x00,0x94,0x08,0x00,0x1e,0xa1,0x00,0x64,0x10,0x06, +0x08,0x00,0x1c,0xf7,0x00,0x00,0x20,0x21,0x8f,0xa4,0x00,0x98,0x8f,0xa5,0x00,0x38, +0xaf,0xa0,0x00,0x10,0x0c,0x00,0x09,0x06,0xaf,0xa8,0x00,0x14,0x30,0x42,0xff,0xff, +0x08,0x00,0x1c,0xc7,0xaf,0xa2,0x00,0x40,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x00, +0x27,0xbd,0xff,0xe0,0x34,0x42,0x00,0x20,0x24,0x63,0x7a,0xc8,0xaf,0xb1,0x00,0x14, +0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x18,0xac,0x43,0x00,0x00,0x90,0x82,0x00,0x0a, +0x00,0x80,0x80,0x21,0x14,0x40,0x00,0x45,0x00,0x00,0x88,0x21,0x92,0x02,0x00,0x04, +0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x3c,0x00,0x00,0x00,0x00,0x12,0x20,0x00,0x18, +0x00,0x00,0x00,0x00,0x92,0x02,0x00,0x16,0x92,0x05,0x00,0x0a,0x30,0x42,0x00,0xfc, +0x10,0xa0,0x00,0x03,0xa2,0x02,0x00,0x16,0x34,0x42,0x00,0x01,0xa2,0x02,0x00,0x16, +0x92,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x83,0x00,0xff,0x10,0x60,0x00,0x05, +0x00,0x00,0x00,0x00,0x92,0x02,0x00,0x16,0x00,0x00,0x00,0x00,0x34,0x42,0x00,0x02, +0xa2,0x02,0x00,0x16,0x10,0x60,0x00,0x0a,0x00,0x00,0x00,0x00,0x14,0xa0,0x00,0x08, +0x00,0x00,0x00,0x00,0x96,0x02,0x00,0x00,0xa2,0x00,0x00,0x17,0xa6,0x02,0x00,0x14, +0x8f,0xbf,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20, +0x14,0x80,0x00,0x05,0x24,0x02,0x00,0x01,0x96,0x03,0x00,0x06,0xa2,0x02,0x00,0x17, +0x08,0x00,0x1e,0xdc,0xa6,0x03,0x00,0x14,0x96,0x04,0x00,0x00,0x96,0x05,0x00,0x06, +0x27,0x86,0x8f,0xf0,0x00,0x04,0x10,0xc0,0x00,0x05,0x18,0xc0,0x00,0x44,0x10,0x21, +0x00,0x65,0x18,0x21,0x00,0x02,0x10,0x80,0x00,0x03,0x18,0x80,0x00,0x66,0x18,0x21, +0x00,0x46,0x10,0x21,0x8c,0x65,0x00,0x08,0x8c,0x44,0x00,0x08,0x0c,0x00,0x12,0x78, +0x00,0x00,0x00,0x00,0x30,0x43,0x00,0xff,0x10,0x60,0x00,0x04,0xa2,0x02,0x00,0x17, +0x96,0x02,0x00,0x06,0x08,0x00,0x1e,0xdc,0xa6,0x02,0x00,0x14,0x96,0x02,0x00,0x00, +0x08,0x00,0x1e,0xdc,0xa6,0x02,0x00,0x14,0x96,0x05,0x00,0x00,0x0c,0x00,0x1f,0x08, +0x02,0x00,0x20,0x21,0x08,0x00,0x1e,0xc3,0x02,0x22,0x88,0x21,0x94,0x85,0x00,0x06, +0x0c,0x00,0x1f,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0x1e,0xbf,0x00,0x40,0x88,0x21, +0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x7c,0x20, +0x27,0xbd,0xff,0xf0,0xac,0x62,0x00,0x00,0x00,0x00,0x10,0x21,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x10,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20, +0x24,0x42,0x7c,0x44,0xac,0x62,0x00,0x00,0x90,0x89,0x00,0x0a,0x00,0x80,0x30,0x21, +0x11,0x20,0x00,0x05,0x00,0xa0,0x50,0x21,0x90,0x82,0x00,0x17,0x00,0x00,0x00,0x00, +0x14,0x40,0x00,0x1b,0x00,0x00,0x00,0x00,0x90,0xc7,0x00,0x04,0x00,0x00,0x00,0x00, +0x10,0xe0,0x00,0x1b,0x00,0x00,0x00,0x00,0x94,0xc8,0x00,0x00,0x27,0x83,0x8f,0xf0, +0x93,0x85,0x8b,0x60,0x00,0x08,0x10,0xc0,0x00,0x48,0x10,0x21,0x00,0x02,0x10,0x80, +0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x08,0x00,0xe5,0x28,0x2b,0x10,0xa0,0x00,0x06, +0x01,0x44,0x18,0x23,0x8f,0x82,0x8b,0x78,0x00,0x00,0x00,0x00,0x00,0x43,0x10,0x2b, +0x10,0x40,0x00,0x05,0x00,0x00,0x00,0x00,0x24,0x03,0x00,0x10,0xa4,0xc8,0x00,0x14, +0x03,0xe0,0x00,0x08,0x00,0x60,0x10,0x21,0x11,0x20,0x00,0x05,0x00,0x00,0x00,0x00, +0x94,0xc2,0x00,0x06,0x24,0x03,0x00,0x08,0x08,0x00,0x1f,0x34,0xa4,0xc2,0x00,0x14, +0x08,0x00,0x1f,0x34,0x00,0x00,0x18,0x21,0x27,0xbd,0xff,0xc8,0xaf,0xb5,0x00,0x2c, +0xaf,0xb4,0x00,0x28,0xaf,0xb3,0x00,0x24,0xaf,0xb0,0x00,0x18,0xaf,0xbf,0x00,0x30, +0xaf,0xb2,0x00,0x20,0xaf,0xb1,0x00,0x1c,0x94,0x91,0x00,0x06,0x00,0x80,0xa0,0x21, +0x3c,0x02,0x80,0x00,0x3c,0x04,0xb0,0x03,0x00,0x11,0xa8,0xc0,0x34,0x84,0x00,0x20, +0x24,0x42,0x7c,0xf8,0x02,0xb1,0x48,0x21,0xac,0x82,0x00,0x00,0x00,0x09,0x48,0x80, +0x24,0x03,0x00,0x01,0x27,0x82,0x90,0x00,0xa2,0x83,0x00,0x12,0x01,0x22,0x10,0x21, +0x27,0x84,0x8f,0xf4,0x01,0x24,0x20,0x21,0x80,0x48,0x00,0x06,0x8c,0x8a,0x00,0x18, +0x27,0x83,0x90,0x10,0x01,0x23,0x48,0x21,0x8d,0x24,0x00,0x00,0x25,0x08,0x00,0x02, +0x8d,0x42,0x00,0x00,0x8d,0x49,0x00,0x04,0x00,0x08,0x17,0xc2,0x8d,0x43,0x00,0x08, +0x01,0x02,0x40,0x21,0x00,0x04,0x25,0xc2,0x00,0x08,0x40,0x43,0x30,0x84,0x00,0x01, +0x00,0x03,0x1f,0xc2,0x00,0x08,0x40,0x40,0x00,0xe0,0x80,0x21,0x00,0x64,0x18,0x24, +0x00,0x09,0x49,0x42,0x01,0x48,0x10,0x21,0x00,0xa0,0x98,0x21,0x00,0xa0,0x20,0x21, +0x00,0x40,0x38,0x21,0x02,0x00,0x28,0x21,0x14,0x60,0x00,0x19,0x31,0x29,0x00,0x01, +0x94,0x42,0x00,0x00,0x02,0xb1,0x88,0x21,0x02,0x00,0x28,0x21,0x00,0x11,0x88,0x80, +0x27,0x90,0x8f,0xf0,0x02,0x30,0x80,0x21,0x96,0x03,0x00,0x06,0x30,0x52,0xff,0xff, +0x02,0x60,0x20,0x21,0x00,0x60,0x30,0x21,0xa6,0x83,0x00,0x1a,0x27,0x82,0x8f,0xf8, +0x0c,0x00,0x08,0xdf,0x02,0x22,0x88,0x21,0x00,0x52,0x10,0x21,0x96,0x03,0x00,0x06, +0xa6,0x22,0x00,0x04,0x8f,0xbf,0x00,0x30,0x7b,0xb4,0x01,0x7c,0x7b,0xb2,0x01,0x3c, +0x7b,0xb0,0x00,0xfc,0x00,0x60,0x10,0x21,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x38, +0xaf,0xa9,0x00,0x10,0x0c,0x00,0x09,0x06,0xaf,0xa0,0x00,0x14,0x08,0x00,0x1f,0x72, +0x02,0xb1,0x88,0x21,0x27,0xbd,0xff,0xc0,0xaf,0xbe,0x00,0x38,0xaf,0xb7,0x00,0x34, +0xaf,0xb6,0x00,0x30,0xaf,0xb5,0x00,0x2c,0xaf,0xb3,0x00,0x24,0xaf,0xb1,0x00,0x1c, +0xaf,0xbf,0x00,0x3c,0xaf,0xb4,0x00,0x28,0xaf,0xb2,0x00,0x20,0xaf,0xb0,0x00,0x18, +0x94,0x90,0x00,0x00,0x3c,0x08,0xb0,0x03,0x35,0x08,0x00,0x20,0x00,0x10,0x10,0xc0, +0x00,0x50,0x18,0x21,0x00,0x40,0x88,0x21,0x3c,0x02,0x80,0x00,0x00,0x03,0x48,0x80, +0x24,0x42,0x7e,0x34,0x00,0x80,0x98,0x21,0x27,0x84,0x90,0x00,0x01,0x24,0x20,0x21, +0x93,0xb7,0x00,0x53,0xad,0x02,0x00,0x00,0x80,0x83,0x00,0x06,0x27,0x82,0x8f,0xf4, +0x01,0x22,0x10,0x21,0x8c,0x44,0x00,0x18,0x24,0x63,0x00,0x02,0x00,0x03,0x17,0xc2, +0x8c,0x88,0x00,0x08,0x00,0x62,0x18,0x21,0x00,0x03,0x18,0x43,0x00,0x03,0x18,0x40, +0xaf,0xa7,0x00,0x4c,0x2c,0xa2,0x00,0x10,0x00,0xa0,0xa8,0x21,0x00,0x83,0x50,0x21, +0x00,0x08,0x47,0xc2,0x00,0xc0,0x58,0x21,0x00,0x00,0xb0,0x21,0x8c,0x92,0x00,0x0c, +0x14,0x40,0x00,0x13,0x00,0x00,0xf0,0x21,0x92,0x67,0x00,0x04,0x24,0x14,0x00,0x01, +0x12,0x87,0x00,0x10,0x02,0x30,0x10,0x21,0x27,0x83,0x90,0x08,0x01,0x23,0x18,0x21, +0x80,0x64,0x00,0x00,0x27,0x83,0xb5,0x60,0x00,0x04,0x11,0x00,0x00,0x44,0x10,0x23, +0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x23,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21, +0x90,0x44,0x00,0x04,0x00,0x00,0x00,0x00,0x10,0x80,0x00,0x23,0x00,0x00,0x00,0x00, +0x02,0x30,0x10,0x21,0x00,0x02,0x80,0x80,0x24,0x04,0x00,0x01,0x27,0x83,0x90,0x10, +0xa2,0x64,0x00,0x12,0x02,0x03,0x18,0x21,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x02,0x15,0xc2,0x30,0x42,0x00,0x01,0x01,0x02,0x10,0x24,0x14,0x40,0x00,0x0e, +0x02,0xa0,0x20,0x21,0x27,0x82,0x8f,0xf0,0x02,0x02,0x10,0x21,0x94,0x43,0x00,0x06, +0x00,0x00,0x00,0x00,0xa6,0x63,0x00,0x1a,0x94,0x42,0x00,0x06,0x7b,0xbe,0x01,0xfc, +0x7b,0xb6,0x01,0xbc,0x7b,0xb4,0x01,0x7c,0x7b,0xb2,0x01,0x3c,0x7b,0xb0,0x00,0xfc, +0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x40,0x8f,0xa5,0x00,0x4c,0x01,0x60,0x30,0x21, +0x01,0x40,0x38,0x21,0xaf,0xa0,0x00,0x10,0x0c,0x00,0x09,0x06,0xaf,0xa0,0x00,0x14, +0x08,0x00,0x1f,0xd9,0x00,0x00,0x00,0x00,0x27,0x83,0x90,0x10,0x01,0x23,0x18,0x21, +0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0xc2,0x30,0x42,0x00,0x01, +0x01,0x02,0x10,0x24,0x14,0x40,0x00,0xaf,0x00,0xa0,0x20,0x21,0x32,0x4f,0x00,0x03, +0x00,0x12,0x10,0x82,0x25,0xe3,0x00,0x0d,0x30,0x45,0x00,0x07,0x00,0x74,0x78,0x04, +0x10,0xa0,0x00,0x0e,0x00,0x00,0x90,0x21,0x27,0x82,0x80,0x1c,0x00,0x15,0x18,0x40, +0x00,0x62,0x18,0x21,0x94,0x64,0x00,0x00,0x24,0xa2,0x00,0x06,0x00,0x54,0x10,0x04, +0x00,0x44,0x00,0x1a,0x14,0x80,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0d, +0x00,0x00,0x10,0x12,0x24,0x42,0x00,0x20,0x30,0x52,0xff,0xfc,0x02,0x30,0x10,0x21, +0x27,0x83,0x90,0x00,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x90,0x44,0x00,0x03, +0x00,0x00,0x00,0x00,0x30,0x83,0x00,0xff,0x2c,0x62,0x00,0x0c,0x14,0x40,0x00,0x04, +0x2c,0x62,0x00,0x19,0x30,0x82,0x00,0x0f,0x24,0x43,0x00,0x0c,0x2c,0x62,0x00,0x19, +0x10,0x40,0x00,0x19,0x24,0x0e,0x00,0x20,0x24,0x62,0xff,0xe9,0x2c,0x42,0x00,0x02, +0x14,0x40,0x00,0x15,0x24,0x0e,0x00,0x10,0x24,0x62,0xff,0xeb,0x2c,0x42,0x00,0x02, +0x14,0x40,0x00,0x11,0x24,0x0e,0x00,0x08,0x24,0x02,0x00,0x14,0x10,0x62,0x00,0x0e, +0x24,0x0e,0x00,0x02,0x24,0x62,0xff,0xef,0x2c,0x42,0x00,0x03,0x14,0x40,0x00,0x0a, +0x24,0x0e,0x00,0x10,0x24,0x62,0xff,0xf1,0x2c,0x42,0x00,0x02,0x14,0x40,0x00,0x06, +0x24,0x0e,0x00,0x08,0x24,0x62,0xff,0xf3,0x2c,0x42,0x00,0x02,0x24,0x0e,0x00,0x04, +0x24,0x03,0x00,0x02,0x00,0x62,0x70,0x0a,0x30,0xe2,0x00,0xff,0x00,0x00,0x48,0x21, +0x00,0x00,0x68,0x21,0x10,0x40,0x00,0x6d,0x00,0x00,0x58,0x21,0x3c,0x14,0x80,0xff, +0x27,0x99,0x8f,0xf0,0x01,0xf2,0xc0,0x23,0x36,0x94,0xff,0xff,0x01,0xc9,0x10,0x2a, +0x14,0x40,0x00,0x64,0x24,0x03,0x00,0x04,0x00,0x10,0x28,0xc0,0x00,0xb0,0x10,0x21, +0x00,0x02,0x10,0x80,0x00,0x59,0x10,0x21,0x94,0x56,0x00,0x06,0x00,0x00,0x00,0x00, +0x32,0xcc,0x00,0x03,0x00,0x6c,0x10,0x23,0x30,0x42,0x00,0x03,0x02,0xc2,0x10,0x21, +0x24,0x42,0x00,0x04,0x30,0x51,0xff,0xff,0x02,0x32,0x18,0x2b,0x10,0x60,0x00,0x4d, +0x01,0xf1,0x10,0x23,0x02,0x51,0x10,0x23,0x01,0x78,0x18,0x2b,0x10,0x60,0x00,0x34, +0x30,0x44,0xff,0xff,0x29,0x22,0x00,0x40,0x10,0x40,0x00,0x31,0x01,0x72,0x18,0x21, +0x25,0x22,0x00,0x01,0x00,0x02,0x16,0x00,0x00,0x02,0x4e,0x03,0x00,0xb0,0x10,0x21, +0x00,0x02,0x30,0x80,0x27,0x82,0x8f,0xf4,0x30,0x6b,0xff,0xff,0x00,0xc2,0x18,0x21, +0x8c,0x67,0x00,0x18,0x00,0x04,0x25,0x40,0x3c,0x03,0x7f,0x00,0x8c,0xe2,0x00,0x04, +0x00,0x83,0x20,0x24,0x27,0x83,0x90,0x00,0x00,0x54,0x10,0x24,0x00,0xc3,0x28,0x21, +0x00,0x44,0x10,0x25,0xac,0xe2,0x00,0x04,0x16,0xe0,0x00,0x02,0xa0,0xb5,0x00,0x00, +0xa0,0xb5,0x00,0x03,0x27,0x84,0x90,0x10,0x00,0xc4,0x18,0x21,0x8c,0x62,0x00,0x00, +0x8c,0xe8,0x00,0x08,0x00,0x02,0x15,0xc2,0x00,0x08,0x47,0xc2,0x30,0x42,0x00,0x01, +0x01,0x02,0x10,0x24,0x10,0x40,0x00,0x0a,0x00,0x00,0x00,0x00,0x80,0xa2,0x00,0x06, +0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x02,0x00,0x02,0x1f,0xc2,0x00,0x43,0x10,0x21, +0x00,0x02,0x10,0x43,0x00,0x02,0x10,0x40,0x00,0xe2,0x50,0x21,0xa5,0x5e,0x00,0x00, +0x92,0x62,0x00,0x04,0x25,0xad,0x00,0x01,0x27,0x84,0x8f,0xf0,0x00,0xc4,0x18,0x21, +0x01,0xa2,0x10,0x2a,0x94,0x70,0x00,0x02,0x14,0x40,0xff,0xb8,0x00,0x00,0x00,0x00, +0x96,0x63,0x00,0x14,0x00,0x0c,0x10,0x23,0xa2,0x69,0x00,0x12,0x30,0x42,0x00,0x03, +0x01,0x62,0x10,0x23,0x00,0x03,0x80,0xc0,0x8f,0xa5,0x00,0x4c,0x30,0x4b,0xff,0xff, +0x02,0x03,0x80,0x21,0x27,0x82,0x8f,0xf8,0x00,0x10,0x80,0x80,0xa6,0x6b,0x00,0x1a, +0x02,0xa0,0x20,0x21,0x01,0x60,0x30,0x21,0x01,0x60,0x88,0x21,0x0c,0x00,0x08,0xdf, +0x02,0x02,0x80,0x21,0x00,0x5e,0x10,0x21,0xa6,0x02,0x00,0x04,0x08,0x00,0x1f,0xdf, +0x02,0x20,0x10,0x21,0x01,0x62,0x10,0x2b,0x10,0x40,0xff,0xe9,0x00,0x00,0x20,0x21, +0x29,0x22,0x00,0x40,0x10,0x40,0xff,0xe6,0x01,0x71,0x18,0x21,0x08,0x00,0x20,0x55, +0x25,0x22,0x00,0x01,0x08,0x00,0x20,0x84,0x32,0xcc,0x00,0x03,0x08,0x00,0x20,0x84, +0x00,0x00,0x60,0x21,0x8f,0xa5,0x00,0x4c,0x01,0x40,0x38,0x21,0xaf,0xa0,0x00,0x10, +0x0c,0x00,0x09,0x06,0xaf,0xb4,0x00,0x14,0x92,0x67,0x00,0x04,0x08,0x00,0x1f,0xf7, +0x30,0x5e,0xff,0xff,0x30,0x84,0xff,0xff,0x00,0x04,0x30,0xc0,0x00,0xc4,0x20,0x21, +0x00,0x04,0x20,0x80,0x27,0x82,0x8f,0xf0,0x3c,0x03,0xb0,0x08,0x30,0xa5,0xff,0xff, +0x00,0x82,0x20,0x21,0x00,0xc3,0x30,0x21,0xac,0xc5,0x00,0x00,0x03,0xe0,0x00,0x08, +0xa4,0x85,0x00,0x00,0x30,0x84,0xff,0xff,0x00,0x04,0x30,0xc0,0x00,0xc4,0x30,0x21, +0x27,0x88,0x8f,0xf0,0x00,0x06,0x30,0x80,0x00,0xc8,0x30,0x21,0x94,0xc3,0x00,0x04, +0x3c,0x02,0xb0,0x08,0x3c,0x07,0xb0,0x03,0x00,0x03,0x20,0xc0,0x00,0x83,0x18,0x21, +0x00,0x03,0x18,0x80,0x00,0x82,0x20,0x21,0x3c,0x02,0x80,0x01,0x30,0xa5,0xff,0xff, +0x00,0x68,0x18,0x21,0x34,0xe7,0x00,0x20,0x24,0x42,0x82,0xe4,0xac,0xe2,0x00,0x00, +0xa4,0xc5,0x00,0x02,0xa4,0x65,0x00,0x00,0x03,0xe0,0x00,0x08,0xac,0x85,0x00,0x00, +0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x34,0x42,0x00,0x20,0x24,0x63,0x83,0x40, +0xac,0x43,0x00,0x00,0x90,0x82,0x00,0x10,0x3c,0x08,0xb0,0x03,0x3c,0x09,0xb0,0x06, +0x27,0x87,0x8f,0xf0,0x3c,0x0d,0xb0,0x08,0x34,0x0e,0xff,0xff,0x35,0x08,0x00,0x62, +0x00,0x80,0x30,0x21,0x24,0x0c,0xff,0xff,0x10,0x40,0x00,0x2c,0x35,0x29,0x80,0x20, +0x97,0x82,0x8f,0xe0,0x94,0x85,0x00,0x0c,0x3c,0x0b,0xb0,0x03,0x00,0x02,0x18,0xc0, +0x00,0x62,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x47,0x10,0x21,0xa4,0x45,0x00,0x00, +0x94,0x84,0x00,0x0e,0x00,0x6d,0x18,0x21,0xac,0x65,0x00,0x00,0x00,0x04,0x10,0xc0, +0x00,0x44,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x47,0x10,0x21,0x94,0x45,0x00,0x04, +0x3c,0x0a,0x77,0x77,0x35,0x6b,0x00,0xb4,0x00,0x05,0x10,0xc0,0x00,0x45,0x18,0x21, +0x00,0x03,0x18,0x80,0x00,0x67,0x18,0x21,0x00,0x4d,0x10,0x21,0xac,0x4e,0x00,0x00, +0xa4,0x6e,0x00,0x00,0x95,0x04,0x00,0x00,0x90,0xc3,0x00,0x10,0x24,0x02,0x00,0xff, +0x00,0x44,0x10,0x23,0x00,0x43,0x10,0x2a,0xa7,0x85,0x8f,0xe0,0x10,0x40,0x00,0x04, +0x35,0x4a,0x88,0x88,0xad,0x6a,0x00,0x00,0x90,0xc3,0x00,0x10,0x00,0x00,0x00,0x00, +0x30,0x63,0x00,0xff,0x3c,0x02,0x00,0x40,0x00,0x62,0x18,0x25,0xad,0x23,0x00,0x00, +0xa4,0xcc,0x00,0x0e,0xa4,0xcc,0x00,0x0c,0xa0,0xc0,0x00,0x10,0x03,0xe0,0x00,0x08, +0x00,0x00,0x00,0x00,0x30,0x84,0xff,0xff,0x00,0x04,0x10,0xc0,0x00,0x44,0x10,0x21, +0x27,0x89,0x8f,0xf0,0x00,0x02,0x10,0x80,0x00,0x49,0x10,0x21,0x97,0x83,0x8f,0xe0, +0x94,0x4a,0x00,0x04,0x3c,0x02,0xb0,0x08,0x00,0x03,0x38,0xc0,0x00,0x0a,0x40,0xc0, +0x00,0xe3,0x18,0x21,0x01,0x0a,0x28,0x21,0x00,0xe2,0x38,0x21,0x01,0x02,0x40,0x21, +0x00,0x03,0x18,0x80,0x00,0x05,0x28,0x80,0x3c,0x06,0xb0,0x03,0x3c,0x02,0x80,0x01, +0x00,0xa9,0x28,0x21,0x00,0x69,0x18,0x21,0x34,0xc6,0x00,0x20,0x34,0x09,0xff,0xff, +0x24,0x42,0x84,0x34,0xac,0xc2,0x00,0x00,0xa4,0x64,0x00,0x00,0xac,0xe4,0x00,0x00, +0xa4,0xa9,0x00,0x00,0xad,0x09,0x00,0x00,0xa7,0x8a,0x8f,0xe0,0x03,0xe0,0x00,0x08, +0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x01,0x34,0x63,0x00,0x20, +0x24,0x42,0x84,0xb4,0x3c,0x04,0xb0,0x03,0xac,0x62,0x00,0x00,0x34,0x84,0x01,0x10, +0x8c,0x82,0x00,0x00,0x97,0x83,0x81,0x60,0x30,0x42,0xff,0xff,0x10,0x62,0x00,0x16, +0x24,0x0a,0x00,0x01,0xa7,0x82,0x81,0x60,0xaf,0x80,0xb4,0x40,0x00,0x40,0x28,0x21, +0x24,0x06,0x00,0x01,0x27,0x84,0xb4,0x44,0x25,0x43,0xff,0xff,0x00,0x66,0x10,0x04, +0x00,0xa2,0x10,0x24,0x14,0x40,0x00,0x07,0x00,0x00,0x00,0x00,0x8c,0x83,0xff,0xfc, +0x00,0x00,0x00,0x00,0x00,0x66,0x10,0x04,0x00,0xa2,0x10,0x24,0x38,0x42,0x00,0x00, +0x01,0x42,0x18,0x0a,0x25,0x4a,0x00,0x01,0x2d,0x42,0x00,0x14,0xac,0x83,0x00,0x00, +0x14,0x40,0xff,0xf1,0x24,0x84,0x00,0x04,0x3c,0x0b,0xb0,0x03,0x00,0x00,0x50,0x21, +0x3c,0x0c,0x80,0x00,0x27,0x89,0xb4,0x90,0x35,0x6b,0x01,0x20,0x8d,0x68,0x00,0x00, +0x8d,0x23,0x00,0x04,0x01,0x0c,0x10,0x24,0x00,0x02,0x17,0xc2,0x11,0x03,0x00,0x37, +0xa1,0x22,0x00,0xdc,0xa1,0x20,0x00,0xd5,0xa1,0x20,0x00,0xd6,0x01,0x20,0x30,0x21, +0x00,0x00,0x38,0x21,0x00,0x00,0x28,0x21,0x01,0x20,0x20,0x21,0x00,0xa8,0x10,0x06, +0x30,0x42,0x00,0x01,0x10,0xe0,0x00,0x10,0xa0,0x82,0x00,0x0a,0x90,0x82,0x00,0x07, +0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x31,0x24,0xa2,0xff,0xff,0xa0,0x82,0x00,0x08, +0x90,0x82,0x00,0x0a,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x09,0x00,0x00,0x00,0x00, +0x90,0x83,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0x40,0x00,0x43,0x10,0x21, +0x00,0x46,0x10,0x21,0xa0,0x45,0x00,0x09,0x90,0x82,0x00,0x0a,0x00,0x00,0x00,0x00, +0x10,0x40,0x00,0x07,0x00,0x00,0x00,0x00,0x14,0xe0,0x00,0x04,0x00,0x00,0x00,0x00, +0xa0,0xc5,0x00,0xd5,0x24,0x07,0x00,0x01,0xa0,0x85,0x00,0x08,0xa0,0xc5,0x00,0xd6, +0x24,0xa5,0x00,0x01,0x2c,0xa2,0x00,0x1c,0x14,0x40,0xff,0xe0,0x24,0x84,0x00,0x03, +0x90,0xc4,0x00,0xd5,0x00,0x00,0x28,0x21,0x00,0xa4,0x10,0x2b,0x10,0x40,0x00,0x0b, +0x00,0x00,0x00,0x00,0x00,0xc0,0x18,0x21,0xa0,0x64,0x00,0x08,0x90,0xc2,0x00,0xd5, +0x24,0xa5,0x00,0x01,0xa0,0x62,0x00,0x09,0x90,0xc4,0x00,0xd5,0x00,0x00,0x00,0x00, +0x00,0xa4,0x10,0x2b,0x14,0x40,0xff,0xf8,0x24,0x63,0x00,0x03,0x25,0x4a,0x00,0x01, +0x2d,0x42,0x00,0x08,0xad,0x28,0x00,0x04,0x25,0x6b,0x00,0x04,0x14,0x40,0xff,0xbf, +0x25,0x29,0x00,0xec,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x90,0x82,0x00,0x05, +0x08,0x00,0x21,0x68,0xa0,0x82,0x00,0x08,0x97,0x85,0x8b,0x6a,0x3c,0x03,0xb0,0x03, +0x3c,0x02,0x80,0x01,0x27,0xbd,0xff,0xe8,0x34,0x63,0x00,0x20,0x24,0x42,0x86,0x68, +0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,0xac,0x62,0x00,0x00,0x30,0x90,0x00,0xff, +0x00,0x05,0x28,0x42,0x00,0x00,0x48,0x21,0x27,0x8f,0xb4,0x94,0x00,0x00,0x50,0x21, +0x00,0x00,0x58,0x21,0x27,0x98,0xb5,0x74,0x27,0x99,0xb5,0x70,0x27,0x8e,0xb5,0x6e, +0x27,0x8c,0xb4,0x98,0x27,0x8d,0xb4,0xf0,0x27,0x88,0xb5,0x68,0x00,0x0a,0x18,0x80, +0x01,0x6f,0x10,0x21,0xac,0x40,0x00,0x00,0xac,0x45,0x00,0x58,0x00,0x6e,0x20,0x21, +0x00,0x78,0x10,0x21,0xa1,0x00,0xff,0xfc,0xad,0x00,0x00,0x00,0xa1,0x00,0x00,0x04, +0xa1,0x00,0x00,0x05,0xad,0x00,0xff,0xf8,0x00,0x79,0x18,0x21,0x24,0x06,0x00,0x01, +0x24,0xc6,0xff,0xff,0xa0,0x80,0x00,0x00,0xa4,0x60,0x00,0x00,0xac,0x40,0x00,0x00, +0x24,0x63,0x00,0x02,0x24,0x42,0x00,0x04,0x04,0xc1,0xff,0xf9,0x24,0x84,0x00,0x01, +0x00,0x0a,0x10,0x80,0x00,0x4d,0x20,0x21,0x00,0x00,0x30,0x21,0x00,0x4c,0x18,0x21, +0x27,0x87,0x81,0x64,0x8c,0xe2,0x00,0x00,0x24,0xe7,0x00,0x04,0xac,0x82,0x00,0x00, +0xa0,0x66,0x00,0x00,0xa0,0x66,0x00,0x01,0x24,0xc6,0x00,0x01,0x28,0xc2,0x00,0x1c, +0xa0,0x60,0x00,0x02,0x24,0x84,0x00,0x04,0x14,0x40,0xff,0xf6,0x24,0x63,0x00,0x03, +0x25,0x29,0x00,0x01,0x29,0x22,0x00,0x08,0x25,0x4a,0x00,0x3b,0x25,0x08,0x00,0xec, +0x14,0x40,0xff,0xd6,0x25,0x6b,0x00,0xec,0xa7,0x80,0x81,0x60,0x00,0x00,0x48,0x21, +0x27,0x83,0xb4,0x40,0xac,0x69,0x00,0x00,0x25,0x29,0x00,0x01,0x29,0x22,0x00,0x0c, +0x14,0x40,0xff,0xfc,0x24,0x63,0x00,0x04,0x0c,0x00,0x21,0x2d,0x00,0x00,0x00,0x00, +0x2e,0x04,0x00,0x14,0x27,0x83,0xb4,0x90,0x24,0x09,0x00,0x07,0x10,0x80,0x00,0x0a, +0x00,0x00,0x00,0x00,0x90,0x62,0x00,0xd5,0x25,0x29,0xff,0xff,0xa0,0x62,0x00,0x00, +0x05,0x21,0xff,0xfa,0x24,0x63,0x00,0xec,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10, +0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x90,0x62,0x00,0xd6,0x08,0x00,0x21,0xeb, +0x25,0x29,0xff,0xff,0x30,0x84,0x00,0xff,0x00,0x04,0x11,0x00,0x00,0x44,0x10,0x23, +0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x23,0x00,0x02,0x10,0x80,0x27,0x83,0xb4,0x90, +0x00,0x43,0x60,0x21,0x3c,0x04,0xb0,0x03,0x3c,0x02,0x80,0x01,0x34,0x84,0x00,0x20, +0x24,0x42,0x87,0xd4,0x30,0xc6,0x00,0xff,0x93,0xa9,0x00,0x13,0x30,0xa5,0x00,0xff, +0x30,0xe7,0x00,0xff,0xac,0x82,0x00,0x00,0x10,0xc0,0x00,0xeb,0x25,0x8f,0x00,0xd0, +0x91,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x42,0xff,0xfc,0x2c,0x43,0x00,0x18, +0x10,0x60,0x00,0xcf,0x3c,0x03,0x80,0x01,0x00,0x02,0x10,0x80,0x24,0x63,0x02,0x5c, +0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x08, +0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x2d,0x10,0x40,0x00,0x14,0x00,0x00,0x00,0x00, +0x10,0xa0,0x00,0x0f,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0x00,0x09, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x06,0x00,0x00,0x00,0x00, +0x8d,0x82,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x42,0xff,0xd0,0x03,0xe0,0x00,0x08, +0xad,0x82,0x00,0xd0,0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23,0x24,0x42,0xff,0xe0, +0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23,0x24,0x42,0x00,0x01,0x10,0xa0,0x00,0x0f, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xf9,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x07,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x03, +0x14,0xa2,0xff,0xf0,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23, +0x24,0x42,0xff,0xe8,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0, +0x08,0x00,0x22,0x23,0x24,0x42,0x00,0x02,0x10,0xa0,0xff,0xfc,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xe6,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02, +0x10,0xa2,0xff,0xf4,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xef,0x00,0x00,0x00,0x00, +0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23,0x24,0x42,0xff,0xf8,0x2d,0x22,0x00,0x19, +0x14,0x40,0xff,0xde,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xec,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xd6,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02, +0x10,0xa2,0xff,0xe4,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0xf1,0x00,0x00,0x00,0x00, +0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23,0x24,0x42,0xff,0xf0,0x2d,0x22,0x00,0x1b, +0x10,0x40,0xff,0xf1,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xdc,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xc6,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02, +0x14,0xa2,0xff,0xce,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23, +0x24,0x42,0xff,0xf4,0x2d,0x22,0x00,0x1e,0x10,0x40,0xff,0xe3,0x00,0x00,0x00,0x00, +0x10,0xa0,0xff,0xce,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xc9, +0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xd6,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x34, +0x24,0x02,0x00,0x03,0x2d,0x22,0x00,0x23,0x10,0x40,0xff,0xd7,0x00,0x00,0x00,0x00, +0x10,0xa0,0xff,0xaf,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xbd, +0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xda,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x03, +0x14,0xa2,0xff,0x9f,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x25,0x00,0x00,0x00,0x00, +0x2d,0x22,0x00,0x25,0x10,0x40,0xff,0xc8,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xa0, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0x00,0x06,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x97,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x80, +0x24,0x02,0x00,0x03,0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23,0x24,0x42,0xff,0xfc, +0x2d,0x22,0x00,0x16,0x14,0x40,0x00,0x0e,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xa3, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x8d,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x9b,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xa8, +0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23,0x24,0x42,0xff,0xfa, +0x10,0xa0,0xff,0x96,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x80, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x8e,0x00,0x00,0x00,0x00, +0x08,0x00,0x22,0x48,0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x17,0x14,0x40,0xff,0x9e, +0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x97,0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x19, +0x10,0x40,0xff,0xe2,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0x84,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x6e,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02, +0x10,0xa2,0xff,0x7c,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0x89,0x00,0x00,0x00,0x00, +0x08,0x00,0x22,0x25,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0xb4,0x2d,0x22,0x00,0x1b, +0x2d,0x22,0x00,0x1e,0x10,0x40,0xff,0xde,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0x73, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x5d,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x6b,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0x88, +0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x25,0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x23, +0x14,0x40,0xff,0xf2,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x4e,0x00,0x00,0x00,0x00, +0x08,0x00,0x22,0x4c,0x2d,0x22,0x00,0x25,0x08,0x00,0x22,0x85,0x2d,0x22,0x00,0x27, +0x10,0xa0,0xff,0x5e,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x48, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x56,0x24,0x02,0x00,0x03, +0x14,0xa2,0xff,0x63,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x91,0x00,0x00,0x00,0x00, +0x2d,0x22,0x00,0x27,0x14,0x40,0xff,0x8e,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x3e, +0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x29,0x14,0x40,0xff,0x89,0x00,0x00,0x00,0x00, +0x08,0x00,0x22,0x2b,0x00,0x00,0x00,0x00,0x91,0x86,0x00,0x00,0x91,0x83,0x00,0xd4, +0x25,0x8d,0x00,0x5c,0x30,0xc4,0x00,0xff,0x00,0x04,0x10,0x40,0x00,0x44,0x10,0x21, +0x00,0x04,0x50,0x80,0x01,0x82,0x58,0x21,0x01,0x8a,0x40,0x21,0x25,0x78,0x00,0x08, +0x10,0x60,0x00,0x37,0x25,0x0e,0x00,0x60,0x2c,0xa2,0x00,0x03,0x14,0x40,0x00,0x25, +0x00,0x00,0x00,0x00,0x91,0x82,0x00,0xdd,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x1e, +0x00,0x00,0x00,0x00,0x27,0x87,0x81,0x64,0x01,0x47,0x10,0x21,0x8c,0x43,0x00,0x00, +0x00,0x00,0x00,0x00,0xad,0x03,0x00,0x60,0x91,0x62,0x00,0x08,0x00,0x00,0x00,0x00, +0x00,0x40,0x30,0x21,0xa1,0x82,0x00,0x00,0x30,0xc2,0x00,0xff,0x00,0x02,0x10,0x80, +0x00,0x47,0x10,0x21,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x18,0x42, +0xad,0xa3,0x00,0x00,0x91,0x84,0x00,0x00,0x8d,0xc5,0x00,0x00,0x00,0x04,0x20,0x80, +0x00,0x87,0x10,0x21,0x8c,0x43,0x00,0x00,0x00,0x05,0x28,0x40,0x00,0x8c,0x20,0x21, +0x00,0x03,0x18,0x80,0x00,0xa3,0x10,0x2b,0x00,0x62,0x28,0x0a,0xac,0x85,0x00,0x60, +0x03,0xe0,0x00,0x08,0xa1,0x80,0x00,0xd4,0x27,0x87,0x81,0x64,0x08,0x00,0x23,0x0e, +0xa1,0x80,0x00,0xdd,0x27,0x82,0x81,0xd4,0x8d,0x83,0x00,0xd8,0x00,0x82,0x10,0x21, +0x90,0x44,0x00,0x00,0x24,0x63,0x00,0x01,0x00,0x64,0x20,0x2b,0x14,0x80,0xff,0x0d, +0xad,0x83,0x00,0xd8,0x8d,0x02,0x00,0x60,0xa1,0x80,0x00,0xd4,0x00,0x02,0x1f,0xc2, +0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x43,0x03,0xe0,0x00,0x08,0xad,0x82,0x00,0x5c, +0x10,0xe0,0x00,0x1a,0x24,0x83,0xff,0xfc,0x2c,0x62,0x00,0x18,0x10,0x40,0x01,0x18, +0x00,0x03,0x10,0x80,0x3c,0x03,0x80,0x01,0x24,0x63,0x02,0xbc,0x00,0x43,0x10,0x21, +0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x08,0x00,0x00,0x00,0x00, +0x2d,0x22,0x00,0x2d,0x10,0x40,0x00,0x5f,0x00,0x00,0x00,0x00,0x10,0xa0,0x00,0x5a, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0x00,0x54,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x51,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0, +0x00,0x00,0x00,0x00,0x24,0x42,0xff,0xd0,0xad,0x82,0x00,0xd0,0x8d,0xe3,0x00,0x00, +0x8d,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x10,0x21,0xad,0xa2,0x00,0x00, +0xad,0xe0,0x00,0x00,0x8d,0xa3,0x00,0x00,0x8d,0xc4,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x83,0x10,0x2a,0x10,0x40,0x00,0x22,0x00,0x00,0x00,0x00,0x93,0x05,0x00,0x01, +0x91,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x45,0x00,0x05,0x24,0x02,0x00,0x01, +0xa1,0x85,0x00,0x00,0xa1,0x82,0x00,0xd4,0x03,0xe0,0x00,0x08,0xad,0x80,0x00,0xd8, +0x91,0x82,0x00,0xdd,0x24,0x03,0x00,0x01,0x10,0x43,0x00,0x05,0x00,0x00,0x00,0x00, +0xa1,0x83,0x00,0xd4,0xad,0x80,0x00,0xd8,0x03,0xe0,0x00,0x08,0xa1,0x83,0x00,0xdd, +0x00,0x04,0x17,0xc2,0x00,0x82,0x10,0x21,0x00,0x02,0x10,0x43,0xad,0xa2,0x00,0x00, +0x91,0x83,0x00,0x00,0x27,0x82,0x81,0x64,0x8d,0xc5,0x00,0x00,0x00,0x03,0x18,0x80, +0x00,0x62,0x18,0x21,0x8c,0x64,0x00,0x00,0x00,0x05,0x28,0x40,0x00,0x04,0x18,0x80, +0x00,0xa3,0x10,0x2b,0x00,0x62,0x28,0x0a,0x08,0x00,0x23,0x20,0xad,0xc5,0x00,0x00, +0x97,0x82,0x8b,0x6c,0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x2a,0x10,0x40,0xfe,0xb9, +0x00,0x00,0x00,0x00,0x91,0x82,0x00,0xdd,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x15, +0x00,0x00,0x00,0x00,0x91,0x83,0x00,0x00,0x27,0x82,0x81,0x64,0x00,0x03,0x18,0x80, +0x00,0x62,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x6c,0x18,0x21,0xac,0x64,0x00,0x60, +0x93,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x10,0x80,0x01,0x82,0x10,0x21, +0x24,0x4e,0x00,0x60,0xa1,0x85,0x00,0x00,0x8d,0xc2,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x02,0x1f,0xc2,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x43,0x03,0xe0,0x00,0x08, +0xad,0xa2,0x00,0x00,0x08,0x00,0x23,0x92,0xa1,0x80,0x00,0xdd,0x8d,0x82,0x00,0xd0, +0x08,0x00,0x23,0x4e,0x24,0x42,0xff,0xe0,0x8d,0x82,0x00,0xd0,0x08,0x00,0x23,0x4e, +0x24,0x42,0x00,0x01,0x10,0xa0,0x00,0x0d,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01, +0x10,0xa2,0xff,0xf9,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xa7, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xf0,0x00,0x00,0x00,0x00, +0x8d,0x82,0x00,0xd0,0x08,0x00,0x23,0x4e,0x24,0x42,0xff,0xe8,0x8d,0x82,0x00,0xd0, +0x08,0x00,0x23,0x4e,0x24,0x42,0x00,0x02,0x10,0xa0,0xff,0xfc,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xe8,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02, +0x10,0xa2,0xff,0x96,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xf1,0x00,0x00,0x00,0x00, +0x8d,0x82,0x00,0xd0,0x08,0x00,0x23,0x4e,0x24,0x42,0xff,0xf8,0x2d,0x22,0x00,0x19, +0x14,0x40,0xff,0xe0,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xec,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xd8,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02, +0x10,0xa2,0xff,0x86,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0xf1,0x00,0x00,0x00,0x00, +0x8d,0x82,0x00,0xd0,0x08,0x00,0x23,0x4e,0x24,0x42,0xff,0xf0,0x2d,0x22,0x00,0x1b, +0x10,0x40,0xff,0xf1,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xdc,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xc8,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02, +0x14,0xa2,0xff,0xd0,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,0x08,0x00,0x23,0x4e, +0x24,0x42,0xff,0xf4,0x2d,0x22,0x00,0x1e,0x10,0x40,0xff,0xe3,0x00,0x00,0x00,0x00, +0x10,0xa0,0xff,0xce,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x6b, +0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xd6,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0xaa, +0x24,0x02,0x00,0x03,0x2d,0x22,0x00,0x23,0x10,0x40,0xff,0xd7,0x00,0x00,0x00,0x00, +0x10,0xa0,0xff,0xb1,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x5f, +0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xda,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x03, +0x14,0xa2,0xff,0x56,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0x9b,0x00,0x00,0x00,0x00, +0x2d,0x22,0x00,0x25,0x10,0x40,0xff,0xc8,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xa2, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0x00,0x06,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x99,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0xf4, +0x24,0x02,0x00,0x03,0x8d,0x82,0x00,0xd0,0x08,0x00,0x23,0x4e,0x24,0x42,0xff,0xfc, +0x2d,0x22,0x00,0x16,0x14,0x40,0x00,0x0e,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xa3, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x8f,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x3d,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xa8, +0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,0x08,0x00,0x23,0x4e,0x24,0x42,0xff,0xfa, +0x10,0xa0,0xff,0x96,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x82, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x30,0x00,0x00,0x00,0x00, +0x08,0x00,0x23,0xbc,0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x17,0x14,0x40,0xff,0x9e, +0x00,0x00,0x00,0x00,0x08,0x00,0x24,0x0b,0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x19, +0x10,0x40,0xff,0xe2,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0x84,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x70,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02, +0x10,0xa2,0xff,0x1e,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0x89,0x00,0x00,0x00,0x00, +0x08,0x00,0x23,0x9b,0x00,0x00,0x00,0x00,0x08,0x00,0x24,0x28,0x2d,0x22,0x00,0x1b, +0x2d,0x22,0x00,0x1e,0x10,0x40,0xff,0xde,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0x73, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x5f,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x0d,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0x88, +0x00,0x00,0x00,0x00,0x08,0x00,0x23,0x9b,0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x23, +0x14,0x40,0xff,0xf2,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0xc2,0x00,0x00,0x00,0x00, +0x08,0x00,0x23,0xc0,0x2d,0x22,0x00,0x25,0x08,0x00,0x23,0xf9,0x2d,0x22,0x00,0x27, +0x10,0xa0,0xff,0x5e,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x4a, +0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xfe,0xf8,0x24,0x02,0x00,0x03, +0x14,0xa2,0xff,0x63,0x00,0x00,0x00,0x00,0x08,0x00,0x24,0x05,0x00,0x00,0x00,0x00, +0x2d,0x22,0x00,0x27,0x14,0x40,0xff,0x8e,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0xb2, +0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x29,0x14,0x40,0xff,0x89,0x00,0x00,0x00,0x00, +0x08,0x00,0x23,0xa1,0x00,0x00,0x00,0x00,0x27,0xbd,0xff,0xe8,0x3c,0x02,0xb0,0x03, +0xaf,0xbf,0x00,0x14,0xaf,0xb0,0x00,0x10,0x34,0x42,0x01,0x18,0x3c,0x03,0xb0,0x03, +0x8c,0x50,0x00,0x00,0x34,0x63,0x01,0x2c,0x90,0x62,0x00,0x00,0x32,0x05,0x00,0x01, +0xa3,0x82,0x80,0x10,0x14,0xa0,0x00,0x14,0x30,0x44,0x00,0xff,0x32,0x02,0x01,0x00, +0x14,0x40,0x00,0x09,0x00,0x00,0x00,0x00,0x32,0x02,0x08,0x00,0x10,0x40,0x00,0x02, +0x24,0x02,0x00,0x01,0xa3,0x82,0xbc,0x08,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10, +0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x0c,0x00,0x05,0x39,0x00,0x00,0x00,0x00, +0x26,0x02,0xff,0x00,0xa3,0x80,0xbc,0x08,0x3c,0x01,0xb0,0x03,0xac,0x22,0x01,0x18, +0x08,0x00,0x24,0x77,0x32,0x02,0x08,0x00,0x0c,0x00,0x21,0x9a,0x00,0x00,0x00,0x00, +0x26,0x02,0xff,0xff,0x3c,0x01,0xb0,0x03,0xac,0x22,0x01,0x18,0x08,0x00,0x24,0x74, +0x32,0x02,0x01,0x00,0x27,0xbd,0xff,0xe0,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xd0, +0xaf,0xbf,0x00,0x18,0x8c,0x43,0x00,0x00,0x3c,0x02,0x00,0x40,0x24,0x07,0x0f,0xff, +0x00,0x03,0x33,0x02,0x00,0x03,0x2d,0x02,0x00,0x03,0x43,0x02,0x30,0x69,0x0f,0xff, +0x00,0x62,0x18,0x24,0x30,0xa5,0x00,0x03,0x30,0xc6,0x00,0xff,0x10,0x60,0x00,0x08, +0x31,0x08,0x00,0xff,0x01,0x00,0x30,0x21,0x0c,0x00,0x25,0x38,0xaf,0xa9,0x00,0x10, +0x8f,0xbf,0x00,0x18,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20, +0x0c,0x00,0x25,0x8a,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0xd4, +0x08,0x00,0x24,0xa0,0xac,0x62,0x00,0x00,0x27,0xbd,0xff,0xc0,0xaf,0xb6,0x00,0x30, +0xaf,0xb3,0x00,0x24,0xaf,0xb1,0x00,0x1c,0xaf,0xb0,0x00,0x18,0xaf,0xbf,0x00,0x3c, +0xaf,0xbe,0x00,0x38,0xaf,0xb7,0x00,0x34,0xaf,0xb5,0x00,0x2c,0xaf,0xb4,0x00,0x28, +0xaf,0xb2,0x00,0x20,0x0c,0x00,0x17,0xc8,0x00,0x80,0x80,0x21,0x00,0x00,0xb0,0x21, +0x00,0x00,0x88,0x21,0x10,0x40,0x00,0x12,0x00,0x00,0x98,0x21,0x3c,0x02,0xb0,0x03, +0x3c,0x03,0xb0,0x03,0x3c,0x04,0xb0,0x03,0x24,0x05,0x00,0x01,0x34,0x42,0x00,0xbc, +0x34,0x63,0x00,0xbb,0x34,0x84,0x00,0xba,0xa4,0x40,0x00,0x00,0xa0,0x65,0x00,0x00, +0xa0,0x85,0x00,0x00,0x7b,0xbe,0x01,0xfc,0x7b,0xb6,0x01,0xbc,0x7b,0xb4,0x01,0x7c, +0x7b,0xb2,0x01,0x3c,0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x40, +0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x47,0x90,0x44,0x00,0x00,0x00,0x10,0x1a,0x02, +0x3c,0x15,0xfd,0xff,0x30,0x84,0x00,0xff,0xa0,0x50,0x00,0x00,0x30,0x74,0x00,0x0f, +0xaf,0xa4,0x00,0x10,0x00,0x00,0x90,0x21,0x3c,0x17,0x02,0x00,0x36,0xb5,0xff,0xff, +0x3c,0x1e,0xb0,0x03,0x0c,0x00,0x06,0xce,0x24,0x04,0x04,0x00,0x00,0x57,0x10,0x25, +0x00,0x40,0x28,0x21,0x0c,0x00,0x06,0xc1,0x24,0x04,0x04,0x00,0x00,0x00,0x80,0x21, +0x0c,0x00,0x26,0x52,0x00,0x00,0x00,0x00,0x26,0x03,0x00,0x01,0x30,0x70,0x00,0xff, +0x10,0x40,0x00,0x47,0x2e,0x03,0x00,0x02,0x14,0x60,0xff,0xf9,0x00,0x00,0x00,0x00, +0x0c,0x00,0x06,0xce,0x24,0x04,0x04,0x00,0x00,0x55,0x10,0x24,0x00,0x40,0x28,0x21, +0x0c,0x00,0x06,0xc1,0x24,0x04,0x04,0x00,0x24,0x02,0x00,0x01,0x12,0x82,0x00,0x38, +0x00,0x00,0x00,0x00,0x12,0x80,0x00,0x36,0x00,0x00,0x00,0x00,0x32,0x22,0x00,0x60, +0x32,0x23,0x0c,0x00,0x00,0x03,0x1a,0x02,0x3c,0x05,0x00,0x60,0x00,0x02,0x11,0x42, +0x02,0x25,0x20,0x24,0x00,0x43,0x10,0x25,0x3c,0x03,0x04,0x00,0x02,0x23,0x28,0x24, +0x00,0x04,0x24,0x42,0x00,0x44,0x10,0x25,0x00,0x05,0x2d,0x02,0x00,0x45,0x88,0x25, +0x12,0x20,0x00,0x05,0x26,0x42,0x00,0x01,0x26,0xc2,0x00,0x01,0x30,0x56,0x00,0xff, +0x02,0x71,0x98,0x21,0x26,0x42,0x00,0x01,0x02,0x5e,0x20,0x21,0x30,0x52,0x00,0xff, +0x2e,0x43,0x00,0x05,0xa0,0x91,0x00,0xd8,0x14,0x60,0xff,0xce,0x3c,0x02,0xb0,0x03, +0x8f,0xa5,0x00,0x10,0x34,0x42,0x01,0x47,0xa0,0x45,0x00,0x00,0x12,0x60,0x00,0x0e, +0x3c,0x02,0xb0,0x03,0x12,0xc0,0x00,0x0d,0x34,0x42,0x00,0xbc,0x00,0x13,0x10,0x40, +0x00,0x53,0x10,0x21,0x00,0x02,0x10,0xc0,0x00,0x53,0x10,0x21,0x00,0x02,0x98,0x80, +0x02,0x76,0x00,0x1b,0x16,0xc0,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0d, +0x00,0x00,0x98,0x12,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xbc,0x3c,0x03,0xb0,0x03, +0x3c,0x04,0xb0,0x03,0xa4,0x53,0x00,0x00,0x34,0x63,0x00,0xbb,0x34,0x84,0x00,0xba, +0x24,0x02,0x00,0x01,0xa0,0x60,0x00,0x00,0x08,0x00,0x24,0xc5,0xa0,0x82,0x00,0x00, +0x0c,0x00,0x06,0xce,0x24,0x04,0x04,0xfc,0x08,0x00,0x24,0xf3,0x00,0x40,0x88,0x21, +0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0xbc,0x3c,0x04,0xb0,0x03,0x3c,0x05,0xb0,0x03, +0xa4,0x60,0x00,0x00,0x34,0x84,0x00,0xbb,0x34,0xa5,0x00,0xba,0x24,0x02,0x00,0x02, +0x24,0x03,0x00,0x01,0xa0,0x82,0x00,0x00,0x08,0x00,0x24,0xc5,0xa0,0xa3,0x00,0x00, +0x27,0xbd,0xff,0xd8,0xaf,0xb0,0x00,0x10,0x30,0xd0,0x00,0xff,0x2e,0x02,0x00,0x2e, +0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xbf,0x00,0x20,0xaf,0xb3,0x00,0x1c, +0x30,0xb1,0x00,0xff,0x14,0x40,0x00,0x06,0x00,0x80,0x90,0x21,0x8f,0xbf,0x00,0x20, +0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28, +0x2e,0x13,0x00,0x10,0x24,0x05,0x00,0x14,0x0c,0x00,0x13,0xa0,0x24,0x06,0x01,0x07, +0x12,0x60,0x00,0x38,0x02,0x00,0x30,0x21,0x8f,0xa2,0x00,0x38,0x30,0xc3,0x00,0x3f, +0x3c,0x04,0xb0,0x09,0x00,0x02,0x14,0x00,0x00,0x43,0x30,0x25,0x34,0x84,0x01,0x60, +0x90,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0xfd,0x24,0x02,0x00,0x01, +0x12,0x22,0x00,0x2a,0x2a,0x22,0x00,0x02,0x14,0x40,0x00,0x24,0x24,0x02,0x00,0x02, +0x12,0x22,0x00,0x20,0x24,0x02,0x00,0x03,0x12,0x22,0x00,0x19,0x00,0x00,0x00,0x00, +0x16,0x60,0xff,0xe2,0x24,0x02,0x00,0x01,0x12,0x22,0x00,0x13,0x2a,0x22,0x00,0x02, +0x14,0x40,0x00,0x0d,0x24,0x02,0x00,0x02,0x12,0x22,0x00,0x09,0x24,0x02,0x00,0x03, +0x16,0x22,0xff,0xda,0x00,0x00,0x00,0x00,0x24,0x04,0x08,0x4c,0x24,0x05,0xff,0xff, +0x0c,0x00,0x13,0x5b,0x3c,0x06,0x0c,0xb8,0x08,0x00,0x25,0x43,0x00,0x00,0x00,0x00, +0x08,0x00,0x25,0x6b,0x24,0x04,0x08,0x48,0x16,0x20,0xff,0xd0,0x00,0x00,0x00,0x00, +0x08,0x00,0x25,0x6b,0x24,0x04,0x08,0x40,0x08,0x00,0x25,0x6b,0x24,0x04,0x08,0x44, +0x24,0x04,0x08,0x4c,0x0c,0x00,0x13,0x5b,0x24,0x05,0xff,0xff,0x08,0x00,0x25,0x60, +0x00,0x00,0x00,0x00,0x08,0x00,0x25,0x79,0x24,0x04,0x08,0x48,0x16,0x20,0xff,0xe0, +0x00,0x00,0x00,0x00,0x08,0x00,0x25,0x79,0x24,0x04,0x08,0x40,0x08,0x00,0x25,0x79, +0x24,0x04,0x08,0x44,0x02,0x40,0x20,0x21,0x0c,0x00,0x25,0xca,0x02,0x20,0x28,0x21, +0x08,0x00,0x25,0x4e,0x00,0x40,0x30,0x21,0x27,0xbd,0xff,0xd8,0x2c,0xc2,0x00,0x2e, +0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x20, +0xaf,0xb3,0x00,0x1c,0x00,0xc0,0x80,0x21,0x30,0xb1,0x00,0xff,0x00,0x80,0x90,0x21, +0x14,0x40,0x00,0x07,0x00,0x00,0x18,0x21,0x8f,0xbf,0x00,0x20,0x7b,0xb2,0x00,0xfc, +0x7b,0xb0,0x00,0xbc,0x00,0x60,0x10,0x21,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28, +0x2e,0x13,0x00,0x10,0x24,0x05,0x00,0x14,0x0c,0x00,0x13,0xa0,0x24,0x06,0x01,0x07, +0x12,0x60,0x00,0x24,0x02,0x00,0x30,0x21,0x3c,0x03,0xb0,0x09,0x34,0x63,0x01,0x60, +0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0xfd,0x30,0xc5,0x00,0x3f, +0x0c,0x00,0x26,0x07,0x02,0x20,0x20,0x21,0x16,0x60,0x00,0x0a,0x00,0x40,0x80,0x21, +0x24,0x02,0x00,0x01,0x12,0x22,0x00,0x15,0x2a,0x22,0x00,0x02,0x14,0x40,0x00,0x0f, +0x24,0x02,0x00,0x02,0x12,0x22,0x00,0x0b,0x24,0x02,0x00,0x03,0x12,0x22,0x00,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0x25,0x96,0x02,0x00,0x18,0x21,0x24,0x04,0x08,0x4c, +0x24,0x05,0xff,0xff,0x0c,0x00,0x13,0x5b,0x3c,0x06,0x0c,0xb8,0x08,0x00,0x25,0x96, +0x02,0x00,0x18,0x21,0x08,0x00,0x25,0xb8,0x24,0x04,0x08,0x48,0x16,0x20,0xff,0xf5, +0x00,0x00,0x00,0x00,0x08,0x00,0x25,0xb8,0x24,0x04,0x08,0x40,0x08,0x00,0x25,0xb8, +0x24,0x04,0x08,0x44,0x02,0x40,0x20,0x21,0x0c,0x00,0x25,0xca,0x02,0x20,0x28,0x21, +0x08,0x00,0x25,0xa2,0x00,0x40,0x30,0x21,0x27,0xbd,0xff,0xe8,0x2c,0xc2,0x00,0x1f, +0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,0x00,0xc0,0x80,0x21,0x14,0x40,0x00,0x1d, +0x30,0xa5,0x00,0xff,0x24,0x02,0x00,0x01,0x10,0xa2,0x00,0x18,0x28,0xa2,0x00,0x02, +0x14,0x40,0x00,0x12,0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x0e,0x24,0x02,0x00,0x03, +0x10,0xa2,0x00,0x07,0x24,0x04,0x08,0x4c,0x26,0x10,0xff,0xe2,0x02,0x00,0x10,0x21, +0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18, +0x24,0x05,0xff,0xff,0x0c,0x00,0x13,0x5b,0x3c,0x06,0x0d,0xf8,0x08,0x00,0x25,0xdb, +0x26,0x10,0xff,0xe2,0x08,0x00,0x25,0xe0,0x24,0x04,0x08,0x48,0x14,0xa0,0xff,0xf2, +0x24,0x04,0x08,0x40,0x08,0x00,0x25,0xe1,0x24,0x05,0xff,0xff,0x08,0x00,0x25,0xe0, +0x24,0x04,0x08,0x44,0x2c,0xc2,0x00,0x10,0x14,0x40,0xff,0xec,0x24,0x02,0x00,0x01, +0x10,0xa2,0x00,0x14,0x28,0xa2,0x00,0x02,0x14,0x40,0x00,0x0e,0x24,0x02,0x00,0x02, +0x10,0xa2,0x00,0x0a,0x24,0x02,0x00,0x03,0x10,0xa2,0x00,0x03,0x24,0x04,0x08,0x4c, +0x08,0x00,0x25,0xdb,0x26,0x10,0xff,0xf1,0x24,0x05,0xff,0xff,0x0c,0x00,0x13,0x5b, +0x3c,0x06,0x0d,0xb8,0x08,0x00,0x25,0xdb,0x26,0x10,0xff,0xf1,0x08,0x00,0x25,0xfa, +0x24,0x04,0x08,0x48,0x14,0xa0,0xff,0xf6,0x24,0x04,0x08,0x40,0x08,0x00,0x25,0xfb, +0x24,0x05,0xff,0xff,0x08,0x00,0x25,0xfa,0x24,0x04,0x08,0x44,0x27,0xbd,0xff,0xe8, +0x30,0x84,0x00,0xff,0x24,0x02,0x00,0x01,0x10,0x82,0x00,0x39,0xaf,0xbf,0x00,0x10, +0x28,0x82,0x00,0x02,0x14,0x40,0x00,0x27,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02, +0x10,0x82,0x00,0x17,0x00,0xa0,0x30,0x21,0x24,0x02,0x00,0x03,0x10,0x82,0x00,0x05, +0x24,0x04,0x08,0x3c,0x8f,0xbf,0x00,0x10,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x18,0x0c,0x00,0x13,0x5b,0x3c,0x05,0x3f,0x00,0x24,0x04,0x08,0x3c, +0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5b,0x00,0x00,0x30,0x21,0x24,0x04,0x08,0x3c, +0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x01,0x24,0x04,0x08,0xac, +0x0c,0x00,0x13,0x3d,0x24,0x05,0x0f,0xff,0x08,0x00,0x26,0x15,0x00,0x00,0x00,0x00, +0x24,0x04,0x08,0x34,0x0c,0x00,0x13,0x5b,0x3c,0x05,0x3f,0x00,0x24,0x04,0x08,0x34, +0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5b,0x00,0x00,0x30,0x21,0x24,0x04,0x08,0x34, +0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x01,0x08,0x00,0x26,0x24, +0x24,0x04,0x08,0xa8,0x14,0x80,0xff,0xdf,0x00,0xa0,0x30,0x21,0x24,0x04,0x08,0x24, +0x0c,0x00,0x13,0x5b,0x3c,0x05,0x3f,0x00,0x24,0x04,0x08,0x24,0x3c,0x05,0x80,0x00, +0x0c,0x00,0x13,0x5b,0x00,0x00,0x30,0x21,0x24,0x04,0x08,0x24,0x3c,0x05,0x80,0x00, +0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x01,0x08,0x00,0x26,0x24,0x24,0x04,0x08,0xa0, +0x00,0xa0,0x30,0x21,0x24,0x04,0x08,0x2c,0x0c,0x00,0x13,0x5b,0x3c,0x05,0x3f,0x00, +0x24,0x04,0x08,0x2c,0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5b,0x00,0x00,0x30,0x21, +0x24,0x04,0x08,0x2c,0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x01, +0x08,0x00,0x26,0x24,0x24,0x04,0x08,0xa4,0x3c,0x05,0x00,0x14,0x3c,0x02,0xb0,0x05, +0x34,0x42,0x04,0x20,0x3c,0x06,0xc0,0x00,0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05, +0x34,0xa5,0x17,0x09,0xac,0x45,0x00,0x00,0x34,0xc6,0x05,0x07,0x34,0x63,0x04,0x24, +0x34,0x84,0x02,0x28,0x3c,0x07,0xb0,0x05,0x24,0x02,0x00,0x20,0xac,0x66,0x00,0x00, +0x34,0xe7,0x04,0x50,0xa0,0x82,0x00,0x00,0x90,0xe2,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x42,0x00,0x03,0x10,0x40,0xff,0xfc,0x24,0x02,0x00,0x01,0x03,0xe0,0x00,0x08, +0x00,0x00,0x00,0x00,0x93,0x85,0x81,0xf1,0x24,0x02,0x00,0x01,0x14,0xa2,0x00,0x51, +0x00,0x80,0x40,0x21,0x8c,0x89,0x00,0x04,0x3c,0x03,0xb0,0x01,0x01,0x23,0x30,0x21, +0x8c,0xc2,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x08,0x10,0x45,0x00,0x59, +0x00,0x00,0x00,0x00,0x94,0xc2,0x00,0x38,0x24,0x03,0x00,0xb4,0x30,0x44,0x00,0xff, +0x10,0x83,0x00,0x61,0x24,0x02,0x00,0xc4,0x10,0x82,0x00,0x54,0x24,0x02,0x00,0x94, +0x10,0x82,0x00,0x45,0x00,0x00,0x00,0x00,0x94,0xc2,0x00,0x38,0x00,0x00,0x00,0x00, +0x30,0x47,0xff,0xff,0x30,0xe3,0x40,0xff,0x24,0x02,0x40,0x88,0x14,0x62,0x00,0x39, +0x30,0xe3,0x03,0x00,0x24,0x02,0x03,0x00,0x10,0x62,0x00,0x38,0x00,0x00,0x00,0x00, +0x94,0xc2,0x00,0x56,0x00,0x00,0x00,0x00,0x30,0x47,0xff,0xff,0x30,0xe2,0x00,0x80, +0x14,0x40,0x00,0x30,0x3c,0x02,0xb0,0x01,0x01,0x22,0x30,0x21,0x94,0xc3,0x00,0x60, +0x24,0x02,0x00,0x08,0x14,0x43,0x00,0x3b,0x00,0x00,0x00,0x00,0x90,0xc2,0x00,0x62, +0x24,0x03,0x00,0x04,0x00,0x02,0x39,0x02,0x10,0xe3,0x00,0x15,0x24,0x02,0x00,0x06, +0x14,0xe2,0x00,0x34,0x00,0x00,0x00,0x00,0x8d,0x05,0x01,0xac,0x94,0xc4,0x00,0x66, +0x27,0x82,0x89,0x58,0x00,0x05,0x28,0x80,0x30,0x87,0xff,0xff,0x00,0xa2,0x28,0x21, +0x00,0x07,0x1a,0x00,0x8c,0xa4,0x00,0x00,0x00,0x07,0x12,0x02,0x00,0x43,0x10,0x25, +0x24,0x42,0x00,0x5e,0x24,0x03,0xc0,0x00,0x30,0x47,0xff,0xff,0x00,0x83,0x20,0x24, +0x00,0x87,0x20,0x25,0xac,0xa4,0x00,0x00,0x08,0x00,0x26,0xcd,0xad,0x07,0x00,0x10, +0x8d,0x05,0x01,0xac,0x94,0xc4,0x00,0x64,0x27,0x82,0x89,0x58,0x00,0x05,0x28,0x80, +0x30,0x87,0xff,0xff,0x00,0xa2,0x28,0x21,0x00,0x07,0x1a,0x00,0x8c,0xa4,0x00,0x00, +0x00,0x07,0x12,0x02,0x00,0x43,0x10,0x25,0x24,0x42,0x00,0x36,0x3c,0x03,0xff,0xff, +0x30,0x47,0xff,0xff,0x00,0x83,0x20,0x24,0x00,0x87,0x20,0x25,0xac,0xa4,0x00,0x00, +0xad,0x07,0x00,0x10,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x94,0xc2,0x00,0x50, +0x08,0x00,0x26,0x8b,0x30,0x47,0xff,0xff,0x8d,0x04,0x01,0xac,0x27,0x83,0x89,0x58, +0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21,0x8c,0x82,0x00,0x00,0x3c,0x03,0xff,0xff, +0x00,0x43,0x10,0x24,0x34,0x42,0x00,0x2e,0xac,0x82,0x00,0x00,0x24,0x03,0x00,0x2e, +0xad,0x03,0x00,0x10,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x8d,0x04,0x01,0xac, +0x27,0x83,0x89,0x58,0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21,0x8c,0x82,0x00,0x00, +0x3c,0x03,0xff,0xff,0x00,0x43,0x10,0x24,0x34,0x42,0x00,0x0e,0x24,0x03,0x00,0x0e, +0x08,0x00,0x26,0xcc,0xac,0x82,0x00,0x00,0x8d,0x04,0x01,0xac,0x27,0x83,0x89,0x58, +0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21,0x8c,0x82,0x00,0x00,0x3c,0x03,0xff,0xff, +0x00,0x43,0x10,0x24,0x34,0x42,0x00,0x14,0x24,0x03,0x00,0x14,0x08,0x00,0x26,0xcc, +0xac,0x82,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0xc6,0x00,0xff, +0x00,0x06,0x48,0x40,0x01,0x26,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x8b,0xbc,0x20, +0x27,0x83,0xbc,0x26,0x00,0x4b,0x40,0x21,0x00,0x43,0x10,0x21,0x94,0x47,0x00,0x00, +0x30,0xa2,0x3f,0xff,0x10,0xe2,0x00,0x29,0x30,0x8a,0xff,0xff,0x95,0x02,0x00,0x02, +0x24,0x03,0x00,0x01,0x00,0x02,0x11,0x82,0x30,0x42,0x00,0x01,0x10,0x43,0x00,0x18, +0x00,0x00,0x00,0x00,0x01,0x26,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x4b,0x30,0x21, +0x94,0xc4,0x00,0x02,0x27,0x83,0xbc,0x26,0x27,0x85,0xbc,0x24,0x00,0x45,0x28,0x21, +0x30,0x84,0xff,0xdf,0x00,0x43,0x10,0x21,0xa4,0xc4,0x00,0x02,0xa4,0x40,0x00,0x00, +0xa4,0xa0,0x00,0x00,0x94,0xc3,0x00,0x02,0x3c,0x04,0xb0,0x01,0x01,0x44,0x20,0x21, +0x30,0x63,0xff,0xbf,0xa4,0xc3,0x00,0x02,0xa0,0xc0,0x00,0x00,0x8c,0x82,0x00,0x04, +0x24,0x03,0xf0,0xff,0x00,0x43,0x10,0x24,0x03,0xe0,0x00,0x08,0xac,0x82,0x00,0x04, +0x24,0x02,0xc0,0x00,0x91,0x04,0x00,0x01,0x00,0xa2,0x10,0x24,0x00,0x47,0x28,0x25, +0x3c,0x03,0xb0,0x01,0x24,0x02,0x00,0x02,0x14,0x82,0xff,0xe2,0x01,0x43,0x18,0x21, +0xac,0x65,0x00,0x00,0x08,0x00,0x26,0xfa,0x01,0x26,0x10,0x21,0x08,0x00,0x26,0xfa, +0x01,0x26,0x10,0x21,0x93,0x83,0x81,0xf1,0x24,0x02,0x00,0x01,0x14,0x62,0x00,0x0d, +0x3c,0x02,0xb0,0x01,0x8c,0x84,0x00,0x04,0x3c,0x06,0xb0,0x09,0x00,0x82,0x20,0x21, +0x8c,0x85,0x00,0x08,0x8c,0x83,0x00,0x04,0x3c,0x02,0x01,0x00,0x34,0xc6,0x01,0x00, +0x00,0x62,0x18,0x24,0x14,0x60,0x00,0x05,0x30,0xa5,0x20,0x00,0x24,0x02,0x00,0x06, +0xa0,0xc2,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x09, +0x10,0xa0,0xff,0xfc,0x34,0x63,0x01,0x00,0x24,0x02,0x00,0x0e,0x08,0x00,0x27,0x2d, +0xa0,0x62,0x00,0x00,0x3c,0x02,0xb0,0x01,0x30,0xa5,0xff,0xff,0x00,0xa2,0x28,0x21, +0x8c,0xa3,0x00,0x00,0x3c,0x02,0x10,0x00,0x00,0x80,0x30,0x21,0x00,0x62,0x18,0x24, +0x8c,0xa2,0x00,0x04,0x10,0x60,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x42,0x80,0x00, +0x10,0x40,0x00,0x13,0x00,0x00,0x00,0x00,0x8c,0xc2,0x01,0xa8,0x00,0x00,0x00,0x00, +0x24,0x44,0x00,0x01,0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x40,0x00,0x83,0x10,0x0a, +0x93,0x83,0x81,0xf0,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x00,0x82,0x20,0x23, +0x24,0x63,0xff,0xff,0xac,0xc4,0x01,0xa8,0xa3,0x83,0x81,0xf0,0x8c,0xc4,0x01,0xac, +0x8c,0xc2,0x01,0xa8,0x00,0x00,0x00,0x00,0x00,0x44,0x10,0x26,0x00,0x02,0x10,0x2b, +0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0x73, +0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x14,0x40,0x00,0x04, +0x00,0x00,0x00,0x00,0xa3,0x80,0x81,0xf1,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x01,0xa3,0x82,0x81,0xf1,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xa8,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x62,0x00,0xff,0x00,0x03,0x2e,0x02,0x00,0x02,0x39,0x80,0x2c,0xa2,0x00,0x02, +0x00,0x03,0x34,0x02,0x10,0x40,0x00,0x05,0x00,0x03,0x1a,0x02,0xa4,0x87,0x01,0xd8, +0xa0,0x85,0x01,0xd4,0xa0,0x86,0x01,0xd5,0xa0,0x83,0x01,0xd6,0x03,0xe0,0x00,0x08, +0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x04,0x3c,0x05,0xb0,0x01,0x00,0x80,0x50,0x21, +0x00,0x45,0x10,0x21,0x8c,0x43,0x00,0x04,0x24,0x02,0x00,0x05,0x00,0x03,0x1a,0x02, +0x30,0x69,0x00,0x0f,0x11,0x22,0x00,0x0b,0x24,0x02,0x00,0x07,0x11,0x22,0x00,0x09, +0x24,0x02,0x00,0x0a,0x11,0x22,0x00,0x07,0x24,0x02,0x00,0x0b,0x11,0x22,0x00,0x05, +0x24,0x02,0x00,0x01,0x93,0x83,0x81,0xf0,0x3c,0x04,0xb0,0x06,0x10,0x62,0x00,0x03, +0x34,0x84,0x80,0x18,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x02,0x17,0x02,0x14,0x40,0xff,0xfa,0x00,0x00,0x00,0x00, +0x8d,0x43,0x01,0xa8,0x27,0x82,0x89,0x58,0x00,0x03,0x18,0x80,0x00,0x6a,0x20,0x21, +0x8c,0x87,0x00,0xa8,0x00,0x62,0x18,0x21,0x8c,0x68,0x00,0x00,0x00,0xe5,0x28,0x21, +0x8c,0xa9,0x00,0x00,0x3c,0x02,0xff,0xff,0x27,0x83,0x8a,0x58,0x01,0x22,0x10,0x24, +0x00,0x48,0x10,0x25,0xac,0xa2,0x00,0x00,0x8d,0x44,0x01,0xa8,0x00,0x07,0x30,0xc2, +0x3c,0x02,0x00,0x80,0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21,0x00,0x06,0x32,0x00, +0x8c,0xa9,0x00,0x04,0x00,0xc2,0x30,0x25,0x8c,0x82,0x00,0x00,0x3c,0x03,0x80,0x00, +0x01,0x22,0x10,0x25,0x00,0x43,0x10,0x25,0xac,0xa2,0x00,0x04,0xaf,0x87,0xbc,0x10, +0x8c,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0x82,0xbc,0x18,0x8c,0xa3,0x00,0x04, +0x3c,0x01,0xb0,0x07,0xac,0x26,0x80,0x18,0x8d,0x42,0x01,0xa8,0xaf,0x83,0xbc,0x14, +0x93,0x85,0x81,0xf0,0x24,0x44,0x00,0x01,0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x40, +0x00,0x83,0x10,0x0a,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x24,0xa5,0xff,0xff, +0x00,0x82,0x20,0x23,0xad,0x44,0x01,0xa8,0xa3,0x85,0x81,0xf0,0x08,0x00,0x27,0x89, +0x00,0x00,0x00,0x00,0x3c,0x05,0xb0,0x03,0x3c,0x02,0x80,0x01,0x24,0x42,0x9f,0x04, +0x34,0xa5,0x00,0x20,0xac,0xa2,0x00,0x00,0x24,0x02,0x00,0x02,0x24,0x03,0x00,0x20, +0xac,0x82,0x00,0x64,0x3c,0x02,0x80,0x01,0xac,0x83,0x00,0x60,0x00,0x80,0x38,0x21, +0xac,0x80,0x00,0x00,0xac,0x80,0x00,0x04,0xac,0x80,0x00,0x08,0xac,0x80,0x00,0x4c, +0xac,0x80,0x00,0x50,0xac,0x80,0x00,0x54,0xac,0x80,0x00,0x0c,0xac,0x80,0x00,0x58, +0xa0,0x80,0x00,0x5c,0x24,0x83,0x00,0x68,0x24,0x42,0xa0,0x14,0x24,0x04,0x00,0x0f, +0x24,0x84,0xff,0xff,0xac,0x62,0x00,0x00,0x04,0x81,0xff,0xfd,0x24,0x63,0x00,0x04, +0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xa8,0xac,0xe0,0x01,0xa8,0xac,0xe0,0x01,0xac, +0xac,0xe0,0x01,0xb0,0xac,0xe0,0x01,0xb4,0xa0,0xe0,0x01,0xb8,0xa0,0xe0,0x01,0xb9, +0xa0,0xe0,0x01,0xba,0xa0,0xe0,0x01,0xc0,0xa0,0xe0,0x01,0xc1,0xac,0xe0,0x01,0xc4, +0xac,0xe0,0x01,0xc8,0xac,0xe0,0x01,0xcc,0xac,0xe0,0x01,0xd0,0x8c,0x44,0x00,0x00, +0x3c,0x02,0x80,0x01,0x24,0x42,0xa0,0xfc,0x30,0x83,0x00,0xff,0x00,0x03,0x19,0x80, +0xa4,0xe3,0x01,0xd8,0xac,0xe2,0x00,0x78,0x3c,0x03,0x80,0x01,0x3c,0x02,0x80,0x01, +0x24,0x63,0xa2,0x88,0x24,0x42,0xa1,0xf4,0xac,0xe3,0x00,0x88,0xac,0xe2,0x00,0x98, +0x3c,0x03,0x80,0x01,0x3c,0x02,0x80,0x01,0x00,0x04,0x2e,0x03,0x00,0x04,0x34,0x03, +0x24,0x63,0xa3,0x30,0x00,0x04,0x22,0x03,0x24,0x42,0xa4,0x74,0xac,0xe3,0x00,0xa0, +0xac,0xe2,0x00,0xa4,0xa0,0xe5,0x01,0xd4,0xa0,0xe6,0x01,0xd5,0x03,0xe0,0x00,0x08, +0xa0,0xe4,0x01,0xd6,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x01,0x34,0x63,0x00,0x20, +0x24,0x42,0xa0,0x14,0x03,0xe0,0x00,0x08,0xac,0x62,0x00,0x00,0x3c,0x02,0xb0,0x03, +0x3c,0x03,0x80,0x01,0x34,0x42,0x00,0x20,0x24,0x63,0xa0,0x2c,0xac,0x43,0x00,0x00, +0x8c,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x11,0x00,0x80,0x28,0x21, +0x8c,0x82,0x00,0x14,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0d,0x00,0x00,0x00,0x00, +0x8c,0x84,0x00,0x10,0x8c,0xa3,0x00,0x14,0x8c,0xa2,0x00,0x04,0x00,0x83,0x20,0x21, +0x00,0x44,0x10,0x21,0x30,0x43,0x00,0xff,0x00,0x03,0x18,0x2b,0x00,0x02,0x12,0x02, +0x00,0x43,0x10,0x21,0x00,0x02,0x12,0x00,0x30,0x42,0x3f,0xff,0xac,0xa2,0x00,0x04, +0xac,0xa0,0x00,0x00,0xac,0xa0,0x00,0x4c,0xac,0xa0,0x00,0x50,0xac,0xa0,0x00,0x54, +0x03,0xe0,0x00,0x08,0xac,0xa0,0x00,0x0c,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x01, +0x34,0x63,0x00,0x20,0x24,0x42,0xa0,0xa8,0xac,0x62,0x00,0x00,0x8c,0x86,0x00,0x04, +0x3c,0x02,0xb0,0x01,0x24,0x03,0x00,0x01,0x00,0xc2,0x10,0x21,0x8c,0x45,0x00,0x00, +0xac,0x83,0x00,0x4c,0x00,0x05,0x14,0x02,0x30,0xa3,0x3f,0xff,0x30,0x42,0x00,0xff, +0xac,0x83,0x00,0x10,0xac,0x82,0x00,0x14,0x8c,0x83,0x00,0x14,0xac,0x85,0x00,0x40, +0x00,0xc3,0x30,0x21,0x03,0xe0,0x00,0x08,0xac,0x86,0x00,0x08,0x3c,0x02,0xb0,0x03, +0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8,0x34,0x42,0x00,0x20,0x24,0x63,0xa0,0xfc, +0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,0xac,0x43,0x00,0x00,0x8c,0x82,0x00,0x4c, +0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0a,0x00,0x80,0x80,0x21,0xae,0x00,0x00,0x00, +0xae,0x00,0x00,0x4c,0xae,0x00,0x00,0x50,0xae,0x00,0x00,0x54,0xae,0x00,0x00,0x0c, +0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18, +0x0c,0x00,0x28,0x2a,0x00,0x00,0x00,0x00,0x08,0x00,0x28,0x4c,0xae,0x00,0x00,0x00, +0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8,0x34,0x42,0x00,0x20, +0x24,0x63,0xa1,0x60,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,0xac,0x43,0x00,0x00, +0x8c,0x82,0x00,0x4c,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x16,0x00,0x80,0x80,0x21, +0x8e,0x03,0x00,0x08,0x3c,0x02,0xb0,0x01,0x8e,0x04,0x00,0x44,0x00,0x62,0x18,0x21, +0x90,0x65,0x00,0x00,0x24,0x02,0x00,0x01,0xae,0x02,0x00,0x50,0x30,0xa3,0x00,0xff, +0x00,0x03,0x10,0x82,0x00,0x04,0x23,0x02,0x30,0x84,0x00,0x0f,0x30,0x42,0x00,0x03, +0x00,0x03,0x19,0x02,0xae,0x04,0x00,0x34,0xae,0x02,0x00,0x2c,0xae,0x03,0x00,0x30, +0xa2,0x05,0x00,0x48,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x18,0x0c,0x00,0x28,0x2a,0x00,0x00,0x00,0x00,0x08,0x00,0x28,0x64, +0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8, +0x34,0x42,0x00,0x20,0x24,0x63,0xa1,0xf4,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14, +0xac,0x43,0x00,0x00,0x8c,0x82,0x00,0x50,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x16, +0x00,0x80,0x80,0x21,0x92,0x03,0x00,0x44,0x8e,0x02,0x00,0x40,0x83,0x85,0x8b,0xc4, +0x92,0x04,0x00,0x41,0x30,0x63,0x00,0x01,0x00,0x02,0x16,0x02,0xae,0x04,0x00,0x14, +0x00,0x00,0x30,0x21,0xae,0x02,0x00,0x18,0x10,0xa0,0x00,0x04,0xae,0x03,0x00,0x3c, +0x10,0x60,0x00,0x03,0x24,0x02,0x00,0x01,0x24,0x06,0x00,0x01,0x24,0x02,0x00,0x01, +0xa3,0x86,0x8b,0xc4,0x8f,0xbf,0x00,0x14,0xae,0x02,0x00,0x54,0x8f,0xb0,0x00,0x10, +0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x0c,0x00,0x28,0x58,0x00,0x00,0x00,0x00, +0x08,0x00,0x28,0x89,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01, +0x27,0xbd,0xff,0xe8,0x34,0x42,0x00,0x20,0x24,0x63,0xa2,0x88,0xaf,0xb0,0x00,0x10, +0xaf,0xbf,0x00,0x14,0xac,0x43,0x00,0x00,0x8c,0x82,0x00,0x50,0x00,0x00,0x00,0x00, +0x10,0x40,0x00,0x1b,0x00,0x80,0x80,0x21,0x3c,0x02,0xb0,0x03,0x8c,0x42,0x00,0x00, +0x92,0x04,0x00,0x44,0x8e,0x03,0x00,0x40,0x83,0x86,0x8b,0xc4,0x92,0x05,0x00,0x41, +0x30,0x42,0x08,0x00,0x30,0x84,0x00,0x01,0x00,0x02,0x12,0xc2,0x00,0x03,0x1e,0x02, +0x00,0x82,0x20,0x25,0xae,0x05,0x00,0x14,0x00,0x00,0x38,0x21,0xae,0x03,0x00,0x18, +0x10,0xc0,0x00,0x04,0xae,0x04,0x00,0x3c,0x10,0x80,0x00,0x03,0x24,0x02,0x00,0x01, +0x24,0x07,0x00,0x01,0x24,0x02,0x00,0x01,0xa3,0x87,0x8b,0xc4,0x8f,0xbf,0x00,0x14, +0xae,0x02,0x00,0x54,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18, +0x0c,0x00,0x28,0x58,0x00,0x00,0x00,0x00,0x08,0x00,0x28,0xae,0x00,0x00,0x00,0x00, +0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8,0x34,0x42,0x00,0x20, +0x24,0x63,0xa3,0x30,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,0xac,0x43,0x00,0x00, +0x8c,0x82,0x00,0x54,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x42,0x00,0x80,0x80,0x21, +0x8e,0x04,0x00,0x04,0x8e,0x03,0x00,0x44,0x3c,0x02,0x80,0x00,0x3c,0x08,0xb0,0x01, +0x34,0x42,0x00,0x10,0x00,0x88,0x20,0x21,0x00,0x62,0x18,0x25,0xac,0x83,0x00,0x04, +0x8e,0x02,0x00,0x04,0x8e,0x03,0x01,0xac,0x27,0x89,0x89,0x58,0x00,0x48,0x10,0x21, +0x8c,0x45,0x00,0x00,0x00,0x03,0x18,0x80,0x00,0x69,0x18,0x21,0xac,0x65,0x00,0x00, +0x8e,0x02,0x00,0x04,0x8e,0x03,0x01,0xac,0x27,0x87,0x8a,0x58,0x00,0x48,0x10,0x21, +0x8c,0x45,0x00,0x04,0x00,0x03,0x18,0x80,0x00,0x67,0x18,0x21,0xac,0x65,0x00,0x00, +0x8e,0x02,0x01,0xac,0x8e,0x06,0x00,0x04,0x02,0x00,0x20,0x21,0x00,0x02,0x10,0x80, +0x00,0x47,0x38,0x21,0x94,0xe3,0x00,0x02,0x00,0x49,0x10,0x21,0x90,0x45,0x00,0x00, +0x00,0x03,0x1a,0x00,0x00,0xc8,0x30,0x21,0x00,0xa3,0x28,0x25,0x0c,0x00,0x26,0x69, +0xa4,0xc5,0x00,0x2e,0x8e,0x03,0x01,0xac,0x8e,0x07,0x00,0x04,0x3c,0x06,0xb0,0x03, +0x24,0x65,0x00,0x01,0x28,0xa4,0x00,0x00,0x24,0x62,0x00,0x40,0x00,0xa4,0x10,0x0a, +0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x00,0x03,0x18,0x80,0x00,0xa2,0x28,0x23, +0x00,0x70,0x18,0x21,0xae,0x05,0x01,0xac,0xac,0x67,0x00,0xa8,0x34,0xc6,0x00,0x30, +0x8c,0xc3,0x00,0x00,0x93,0x82,0x81,0xf0,0x02,0x00,0x20,0x21,0x24,0x63,0x00,0x01, +0x24,0x42,0x00,0x01,0xac,0xc3,0x00,0x00,0xa3,0x82,0x81,0xf0,0x0c,0x00,0x28,0x0b, +0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x18,0x0c,0x00,0x28,0xa2,0x00,0x00,0x00,0x00,0x08,0x00,0x28,0xd8, +0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8, +0x34,0x42,0x00,0x20,0x24,0x63,0xa4,0x74,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14, +0xac,0x43,0x00,0x00,0x8c,0x82,0x00,0x54,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x42, +0x00,0x80,0x80,0x21,0x8e,0x04,0x00,0x04,0x8e,0x03,0x00,0x44,0x3c,0x02,0x80,0x00, +0x3c,0x08,0xb0,0x01,0x34,0x42,0x00,0x10,0x00,0x88,0x20,0x21,0x00,0x62,0x18,0x25, +0xac,0x83,0x00,0x04,0x8e,0x02,0x00,0x04,0x8e,0x03,0x01,0xac,0x27,0x89,0x89,0x58, +0x00,0x48,0x10,0x21,0x8c,0x45,0x00,0x00,0x00,0x03,0x18,0x80,0x00,0x69,0x18,0x21, +0xac,0x65,0x00,0x00,0x8e,0x02,0x00,0x04,0x8e,0x03,0x01,0xac,0x27,0x87,0x8a,0x58, +0x00,0x48,0x10,0x21,0x8c,0x45,0x00,0x04,0x00,0x03,0x18,0x80,0x00,0x67,0x18,0x21, +0xac,0x65,0x00,0x00,0x8e,0x02,0x01,0xac,0x8e,0x06,0x00,0x04,0x02,0x00,0x20,0x21, +0x00,0x02,0x10,0x80,0x00,0x47,0x38,0x21,0x94,0xe3,0x00,0x02,0x00,0x49,0x10,0x21, +0x90,0x45,0x00,0x00,0x00,0x03,0x1a,0x00,0x00,0xc8,0x30,0x21,0x00,0xa3,0x28,0x25, +0x0c,0x00,0x26,0x69,0xa4,0xc5,0x00,0x2e,0x8e,0x03,0x01,0xac,0x8e,0x07,0x00,0x04, +0x3c,0x06,0xb0,0x03,0x24,0x65,0x00,0x01,0x28,0xa4,0x00,0x00,0x24,0x62,0x00,0x40, +0x00,0xa4,0x10,0x0a,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x00,0x03,0x18,0x80, +0x00,0xa2,0x28,0x23,0x00,0x70,0x18,0x21,0xae,0x05,0x01,0xac,0xac,0x67,0x00,0xa8, +0x34,0xc6,0x00,0x30,0x8c,0xc3,0x00,0x00,0x93,0x82,0x81,0xf0,0x02,0x00,0x20,0x21, +0x24,0x63,0x00,0x01,0x24,0x42,0x00,0x01,0xac,0xc3,0x00,0x00,0xa3,0x82,0x81,0xf0, +0x0c,0x00,0x28,0x0b,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10, +0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x0c,0x00,0x28,0xa2,0x00,0x00,0x00,0x00, +0x08,0x00,0x29,0x29,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01, +0x27,0xbd,0xff,0xd8,0x34,0x42,0x00,0x20,0x24,0x63,0xa5,0xb8,0xaf,0xb2,0x00,0x18, +0xac,0x43,0x00,0x00,0x3c,0x12,0xb0,0x03,0x3c,0x02,0x80,0x01,0xaf,0xb4,0x00,0x20, +0xaf,0xb3,0x00,0x1c,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x24, +0x00,0x80,0x80,0x21,0x24,0x54,0xa0,0x14,0x00,0x00,0x88,0x21,0x3c,0x13,0xb0,0x01, +0x36,0x52,0x00,0xef,0x3c,0x02,0xb0,0x09,0x34,0x42,0x00,0x06,0x90,0x43,0x00,0x00, +0x8e,0x04,0x00,0x04,0x92,0x02,0x01,0xbb,0x30,0x69,0x00,0xff,0x00,0x04,0x42,0x02, +0x10,0x40,0x00,0x1e,0x00,0x00,0x38,0x21,0x8e,0x03,0x01,0xa8,0x3c,0x06,0x28,0x38, +0x34,0xc6,0x00,0x20,0x24,0x64,0x00,0x3d,0x28,0x82,0x00,0x00,0x24,0x63,0x00,0x7c, +0x00,0x82,0x18,0x0a,0x00,0x03,0x19,0x83,0x00,0x03,0x19,0x80,0x00,0x83,0x20,0x23, +0x00,0x04,0x10,0x80,0x00,0x50,0x10,0x21,0x8c,0x45,0x00,0xa8,0xae,0x04,0x01,0xac, +0xae,0x04,0x01,0xa8,0x00,0xb3,0x18,0x21,0xae,0x05,0x00,0x04,0xac,0x66,0x00,0x00, +0x8e,0x02,0x00,0x04,0x3c,0x03,0x80,0x00,0x34,0x63,0x4e,0x00,0x00,0x53,0x10,0x21, +0xac,0x43,0x00,0x04,0xa2,0x00,0x01,0xbb,0x93,0x83,0x81,0xf7,0x00,0x00,0x00,0x00, +0x24,0x62,0x00,0x01,0xa3,0x82,0x81,0xf7,0xa2,0x43,0x00,0x00,0x01,0x28,0x10,0x23, +0x24,0x44,0x00,0x40,0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x7f,0x00,0x83,0x10,0x0a, +0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x24,0x84,0xff,0xff,0x10,0x44,0x00,0x6b, +0x3c,0x02,0xb0,0x01,0x8e,0x03,0x00,0x04,0x3c,0x04,0x7c,0x00,0x00,0x62,0x18,0x21, +0x8c,0x65,0x00,0x04,0x34,0x84,0x00,0xf0,0x00,0x00,0x30,0x21,0xae,0x05,0x00,0x44, +0x00,0xa4,0x20,0x24,0x8c,0x63,0x00,0x00,0x10,0x80,0x00,0x6b,0x3c,0x02,0xff,0xff, +0x3c,0x09,0xb0,0x03,0x3c,0x05,0x7c,0x00,0x35,0x29,0x00,0x99,0x3c,0x0a,0xb0,0x01, +0x24,0x08,0x00,0x40,0x34,0xa5,0x00,0xf0,0x3c,0x0b,0xff,0xff,0x3c,0x0c,0x28,0x38, +0x16,0x20,0x00,0x06,0x24,0xe7,0x00,0x01,0x93,0x82,0x81,0xf6,0x24,0x11,0x00,0x01, +0x24,0x42,0x00,0x01,0xa1,0x22,0x00,0x00,0xa3,0x82,0x81,0xf6,0x8e,0x02,0x00,0x04, +0x24,0x06,0x00,0x01,0x24,0x42,0x01,0x00,0x30,0x42,0x3f,0xff,0xae,0x02,0x00,0x04, +0x00,0x4a,0x10,0x21,0x8c,0x43,0x00,0x04,0x00,0x00,0x00,0x00,0xae,0x03,0x00,0x44, +0x00,0x65,0x20,0x24,0x8c,0x43,0x00,0x00,0x10,0xe8,0x00,0x2d,0x00,0x00,0x00,0x00, +0x14,0x80,0xff,0xeb,0x00,0x6b,0x10,0x24,0x14,0x4c,0xff,0xe9,0x24,0x02,0x00,0x01, +0x10,0xc2,0x00,0x30,0x3c,0x03,0xb0,0x09,0x8e,0x02,0x00,0x44,0x8e,0x04,0x00,0x60, +0x00,0x02,0x1e,0x42,0x00,0x02,0x12,0x02,0x30,0x42,0x00,0x0f,0x30,0x63,0x00,0x01, +0xae,0x02,0x00,0x00,0x10,0x44,0x00,0x1a,0xae,0x03,0x00,0x58,0x8e,0x02,0x00,0x64, +0x8e,0x04,0x00,0x58,0x00,0x00,0x00,0x00,0x10,0x82,0x00,0x05,0x00,0x00,0x00,0x00, +0xae,0x00,0x00,0x4c,0xae,0x00,0x00,0x50,0xae,0x00,0x00,0x54,0xae,0x00,0x00,0x0c, +0x8e,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0x80,0x00,0x50,0x10,0x21, +0x8c,0x42,0x00,0x68,0x00,0x00,0x00,0x00,0x10,0x54,0x00,0x06,0x00,0x00,0x00,0x00, +0x00,0x40,0xf8,0x09,0x02,0x00,0x20,0x21,0x8e,0x04,0x00,0x58,0x8e,0x03,0x00,0x00, +0x00,0x00,0x00,0x00,0xae,0x03,0x00,0x60,0x08,0x00,0x29,0x81,0xae,0x04,0x00,0x64, +0x8e,0x02,0x00,0x64,0x00,0x00,0x00,0x00,0x14,0x62,0xff,0xe5,0x00,0x00,0x00,0x00, +0x7a,0x02,0x0d,0x7c,0x8f,0xbf,0x00,0x24,0x8f,0xb4,0x00,0x20,0x7b,0xb2,0x00,0xfc, +0x7b,0xb0,0x00,0xbc,0x00,0x43,0x10,0x26,0x00,0x02,0x10,0x2b,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x28,0x8e,0x04,0x00,0x04,0x34,0x63,0x00,0x06,0x90,0x62,0x00,0x00, +0x00,0x04,0x42,0x02,0x00,0x48,0x10,0x23,0x24,0x44,0x00,0x40,0x28,0x83,0x00,0x00, +0x24,0x42,0x00,0x7f,0x00,0x83,0x10,0x0a,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80, +0x00,0x82,0x20,0x23,0x14,0x86,0xff,0xc4,0x00,0x00,0x00,0x00,0x8e,0x03,0x00,0x00, +0x00,0x00,0x00,0x00,0x2c,0x62,0x00,0x03,0x14,0x40,0x00,0x05,0x24,0x02,0x00,0x0d, +0x10,0x62,0x00,0x03,0x24,0x02,0x00,0x01,0x08,0x00,0x2a,0x04,0xa2,0x02,0x00,0x5c, +0x08,0x00,0x2a,0x04,0xa2,0x00,0x00,0x5c,0x00,0x62,0x10,0x24,0x3c,0x03,0x28,0x38, +0x14,0x43,0xff,0x93,0x24,0x02,0x00,0x01,0x08,0x00,0x29,0xdc,0x00,0x00,0x00,0x00, +0x3c,0x02,0xb0,0x01,0x00,0xa2,0x40,0x21,0x00,0xa0,0x48,0x21,0x8d,0x05,0x00,0x00, +0x24,0x02,0xc0,0x00,0x00,0x09,0x38,0xc2,0x00,0xa2,0x28,0x24,0x24,0xc2,0xff,0xff, +0x00,0x07,0x3a,0x00,0x3c,0x0a,0xb0,0x06,0x3c,0x03,0x00,0x80,0x00,0xa6,0x28,0x25, +0x2c,0x42,0x1f,0xff,0x00,0xe3,0x38,0x25,0x35,0x4a,0x80,0x18,0x10,0x40,0x00,0x0e, +0xad,0x05,0x00,0x00,0xaf,0x89,0xbc,0x10,0x8d,0x02,0x00,0x00,0x00,0x00,0x00,0x00, +0xaf,0x82,0xbc,0x18,0x8d,0x03,0x00,0x04,0xad,0x47,0x00,0x00,0xaf,0x83,0xbc,0x14, +0xac,0x80,0x01,0xd0,0xac,0x80,0x01,0xc4,0xa0,0x80,0x01,0xc0,0xa0,0x80,0x01,0xc1, +0xac,0x80,0x01,0xc8,0xac,0x80,0x01,0xcc,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x10,0x8c,0x83,0x01,0xc4,0x00,0x80,0x38,0x21, +0x90,0x84,0x01,0xc0,0x00,0x03,0x18,0x80,0x00,0x67,0x18,0x21,0x8c,0x65,0x00,0xa8, +0x3c,0x02,0xb0,0x01,0x24,0x03,0x00,0x01,0x00,0xa2,0x10,0x21,0x8c,0x42,0x00,0x00, +0x10,0x83,0x00,0x18,0x00,0x02,0x14,0x02,0x8c,0xe9,0x01,0xcc,0x8c,0xea,0x01,0xc8, +0x30,0x46,0x00,0xff,0x01,0x2a,0x18,0x21,0x30,0x64,0x00,0xff,0x00,0x03,0x1a,0x02, +0x24,0x62,0x00,0x01,0x14,0x80,0x00,0x02,0x30,0x48,0x00,0xff,0x30,0x68,0x00,0xff, +0x90,0xe2,0x01,0xc1,0x00,0x00,0x00,0x00,0x00,0x48,0x10,0x23,0x00,0x02,0x12,0x00, +0x00,0x49,0x10,0x21,0x00,0x4a,0x10,0x21,0x00,0x46,0x30,0x23,0x0c,0x00,0x2a,0x2c, +0x00,0xe0,0x20,0x21,0x8f,0xbf,0x00,0x10,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x18,0x8c,0xe6,0x01,0xc8,0x08,0x00,0x2a,0x6b,0x00,0x00,0x00,0x00, +0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x14,0xaf,0xb0,0x00,0x10,0x8c,0x82,0x01,0xc4, +0x90,0x87,0x01,0xc1,0x00,0x80,0x80,0x21,0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x21, +0x8c,0x48,0x00,0xa8,0x3c,0x02,0xb0,0x01,0x00,0x07,0x3a,0x00,0x01,0x02,0x10,0x21, +0x8c,0x43,0x00,0x00,0x00,0xe5,0x38,0x21,0x00,0xe6,0x38,0x21,0x00,0x03,0x1c,0x02, +0x30,0x63,0x00,0xff,0x00,0xe3,0x38,0x23,0x01,0x00,0x28,0x21,0x0c,0x00,0x2a,0x2c, +0x00,0xe0,0x30,0x21,0x8e,0x02,0x01,0xa8,0x8f,0xbf,0x00,0x14,0x24,0x44,0x00,0x01, +0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x40,0x00,0x83,0x10,0x0a,0x00,0x02,0x11,0x83, +0x00,0x02,0x11,0x80,0x00,0x82,0x20,0x23,0xae,0x04,0x01,0xa8,0x8f,0xb0,0x00,0x10, +0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01, +0x27,0xbd,0xff,0xe8,0x34,0x42,0x00,0x20,0x24,0x63,0xaa,0x58,0xaf,0xb0,0x00,0x10, +0xaf,0xbf,0x00,0x14,0xac,0x43,0x00,0x00,0x90,0x82,0x01,0xd4,0x00,0x00,0x00,0x00, +0x14,0x40,0x00,0x6a,0x00,0x80,0x80,0x21,0x90,0x82,0x01,0xc0,0x00,0x00,0x00,0x00, +0x14,0x40,0x00,0x61,0x00,0x00,0x00,0x00,0x8c,0x83,0x01,0xa8,0x8c,0x82,0x01,0xac, +0x00,0x00,0x00,0x00,0x10,0x62,0x00,0x22,0x00,0x00,0x28,0x21,0x93,0x82,0x81,0xf1, +0x00,0x03,0x30,0x80,0x00,0xc4,0x18,0x21,0x24,0x04,0x00,0x01,0x8c,0x67,0x00,0xa8, +0x10,0x44,0x00,0x20,0x3c,0x04,0xb0,0x01,0xaf,0x87,0xbc,0x10,0x00,0xe4,0x20,0x21, +0x8c,0x86,0x00,0x00,0x00,0x07,0x18,0xc2,0x3c,0x02,0x00,0x80,0xaf,0x86,0xbc,0x18, +0x8c,0x86,0x00,0x04,0x00,0x03,0x1a,0x00,0x3c,0x05,0xb0,0x06,0x00,0x62,0x18,0x25, +0x34,0xa5,0x80,0x18,0xac,0xa3,0x00,0x00,0x8e,0x02,0x01,0xa8,0x8e,0x09,0x01,0xac, +0xaf,0x86,0xbc,0x14,0x24,0x44,0x00,0x01,0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x40, +0x00,0x83,0x10,0x0a,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x00,0x82,0x20,0x23, +0x00,0x80,0x30,0x21,0xae,0x04,0x01,0xa8,0x00,0xc9,0x10,0x26,0x00,0x02,0x28,0x2b, +0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x00,0xa0,0x10,0x21,0x03,0xe0,0x00,0x08, +0x27,0xbd,0x00,0x18,0x93,0x82,0x81,0xf0,0x00,0x00,0x00,0x00,0x2c,0x42,0x00,0x02, +0x14,0x40,0xff,0xf7,0x00,0x00,0x28,0x21,0x3c,0x05,0xb0,0x01,0x00,0xe5,0x28,0x21, +0x27,0x83,0x89,0x58,0x00,0xc3,0x18,0x21,0x8c,0xa6,0x00,0x00,0x8c,0x64,0x00,0x00, +0x24,0x02,0xc0,0x00,0x00,0xc2,0x10,0x24,0x00,0x44,0x10,0x25,0xac,0xa2,0x00,0x00, +0x8e,0x03,0x01,0xa8,0x27,0x84,0x8a,0x58,0x8c,0xa6,0x00,0x04,0x00,0x03,0x18,0x80, +0x00,0x64,0x18,0x21,0x8c,0x62,0x00,0x00,0x3c,0x03,0x80,0x00,0x00,0x07,0x20,0xc2, +0x00,0xc2,0x10,0x25,0x00,0x43,0x10,0x25,0xac,0xa2,0x00,0x04,0xaf,0x87,0xbc,0x10, +0x8c,0xa6,0x00,0x00,0x3c,0x02,0x00,0x80,0x00,0x04,0x22,0x00,0x3c,0x03,0xb0,0x06, +0xaf,0x86,0xbc,0x18,0x00,0x82,0x20,0x25,0x34,0x63,0x80,0x18,0x8c,0xa6,0x00,0x04, +0xac,0x64,0x00,0x00,0x8e,0x02,0x01,0xa8,0xaf,0x86,0xbc,0x14,0x24,0x44,0x00,0x01, +0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x40,0x00,0x83,0x10,0x0a,0x93,0x83,0x81,0xf0, +0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x00,0x82,0x20,0x23,0x24,0x63,0xff,0xff, +0xae,0x04,0x01,0xa8,0xa3,0x83,0x81,0xf0,0x8e,0x04,0x01,0xac,0x8e,0x02,0x01,0xa8, +0x08,0x00,0x2a,0xcb,0x00,0x44,0x10,0x26,0x0c,0x00,0x2a,0x4c,0x00,0x00,0x00,0x00, +0x7a,0x02,0x0d,0x7c,0x08,0x00,0x2a,0xcb,0x00,0x43,0x10,0x26,0x8c,0x86,0x01,0xa8, +0x8c,0x89,0x01,0xac,0x00,0x00,0x00,0x00,0x10,0xc9,0x00,0xb4,0x00,0xc0,0x68,0x21, +0x00,0x06,0x10,0x80,0x27,0x83,0x89,0x58,0x00,0x43,0x18,0x21,0x00,0x44,0x10,0x21, +0x8c,0x47,0x00,0xa8,0x94,0x65,0x00,0x02,0x3c,0x02,0xb0,0x01,0x00,0xe2,0x10,0x21, +0x30,0xa5,0x3f,0xff,0xa4,0x45,0x00,0x2c,0x90,0x8a,0x01,0xc0,0x00,0x00,0x00,0x00, +0x11,0x40,0x00,0x0c,0x00,0x07,0x32,0x02,0x8c,0x83,0x01,0xc4,0x90,0x85,0x01,0xc1, +0x00,0x03,0x18,0x80,0x00,0x64,0x18,0x21,0x8c,0x62,0x00,0xa8,0x00,0x00,0x00,0x00, +0x00,0x02,0x12,0x02,0x00,0x45,0x10,0x21,0x30,0x42,0x00,0x3f,0x14,0xc2,0xff,0xde, +0x00,0x00,0x00,0x00,0x3c,0x04,0xb0,0x01,0x00,0xe4,0x40,0x21,0x8d,0x06,0x00,0x00, +0x00,0x0d,0x28,0x80,0x00,0x06,0x14,0x02,0x30,0x4b,0x00,0xff,0x00,0xeb,0x70,0x21, +0x01,0xc4,0x20,0x21,0x90,0x83,0x00,0x00,0x27,0x82,0x89,0x58,0x00,0xa2,0x28,0x21, +0x8c,0xa4,0x00,0x00,0x00,0x03,0x18,0x82,0x30,0x63,0x00,0x03,0x2c,0x62,0x00,0x02, +0x14,0x40,0x00,0x66,0x30,0x8c,0x3f,0xff,0x24,0x02,0x00,0x02,0x10,0x62,0x00,0x61, +0x2d,0x82,0x08,0x00,0x15,0x40,0x00,0x36,0x01,0x6c,0x10,0x21,0x01,0x6c,0x18,0x21, +0x30,0x62,0x00,0xff,0x00,0x02,0x10,0x2b,0x00,0x03,0x1a,0x02,0x3c,0x04,0xb0,0x01, +0x00,0x62,0x18,0x21,0x00,0xe4,0x20,0x21,0x24,0x02,0x00,0x01,0xa2,0x03,0x01,0xc1, +0xa0,0x82,0x00,0x08,0x8e,0x06,0x01,0xa8,0x3c,0x03,0xb0,0x00,0x34,0x63,0xff,0xf4, +0x24,0xc5,0x00,0x01,0x28,0xa4,0x00,0x00,0x24,0xc2,0x00,0x40,0x00,0xa4,0x10,0x0a, +0x01,0xc3,0x18,0x21,0xa4,0x6c,0x00,0x00,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80, +0x92,0x04,0x01,0xc0,0x00,0xa2,0x38,0x23,0x3c,0x03,0xb0,0x03,0xae,0x0b,0x01,0xcc, +0xae,0x0c,0x01,0xc8,0xae,0x06,0x01,0xc4,0xae,0x07,0x01,0xa8,0x34,0x63,0x01,0x08, +0x92,0x05,0x01,0xd6,0x8c,0x66,0x00,0x00,0x24,0x84,0x00,0x01,0x30,0x82,0x00,0xff, +0x00,0x45,0x10,0x2b,0xae,0x06,0x01,0xd0,0x10,0x40,0x00,0x07,0xa2,0x04,0x01,0xc0, +0x92,0x02,0x01,0xd5,0x92,0x03,0x01,0xc1,0x24,0x42,0xff,0xfc,0x00,0x62,0x18,0x2a, +0x14,0x60,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x00,0x20,0x21,0x0c,0x00,0x2a,0x4c, +0x00,0x00,0x00,0x00,0x8e,0x09,0x01,0xac,0x8e,0x06,0x01,0xa8,0x08,0x00,0x2a,0xcb, +0x00,0xc9,0x10,0x26,0x8e,0x09,0x01,0xac,0x08,0x00,0x2a,0xca,0x00,0xe0,0x30,0x21, +0x30,0x43,0x00,0xff,0x92,0x07,0x01,0xc1,0x00,0x02,0x12,0x02,0x30,0x44,0x00,0xff, +0x38,0x63,0x00,0x00,0x24,0x46,0x00,0x01,0x92,0x05,0x01,0xd5,0x00,0x83,0x30,0x0a, +0x00,0xc7,0x18,0x21,0x00,0xa3,0x10,0x2a,0x14,0x40,0xff,0xeb,0x00,0x00,0x00,0x00, +0x24,0xa2,0xff,0xfc,0x00,0x62,0x10,0x2a,0x10,0x40,0x00,0x07,0x01,0x80,0x28,0x21, +0x92,0x03,0x01,0xd6,0x25,0x42,0x00,0x01,0x00,0x43,0x10,0x2a,0x14,0x40,0x00,0x07, +0x25,0xa4,0x00,0x01,0x01,0x80,0x28,0x21,0x01,0x60,0x30,0x21,0x0c,0x00,0x2a,0x74, +0x02,0x00,0x20,0x21,0x08,0x00,0x2b,0x6d,0x00,0x00,0x00,0x00,0x28,0x83,0x00,0x00, +0x25,0xa2,0x00,0x40,0x00,0x83,0x10,0x0a,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80, +0x00,0x82,0x20,0x23,0x00,0xc7,0x18,0x21,0x25,0x42,0x00,0x01,0x00,0x80,0x30,0x21, +0xa2,0x03,0x01,0xc1,0xae,0x0b,0x01,0xcc,0xae,0x0c,0x01,0xc8,0x08,0x00,0x2a,0xc9, +0xa2,0x02,0x01,0xc0,0x14,0x40,0xff,0x9f,0x00,0x00,0x00,0x00,0x15,0x40,0x00,0x14, +0x24,0x02,0xc0,0x00,0x00,0xc2,0x10,0x24,0x00,0x4c,0x10,0x25,0xad,0x02,0x00,0x00, +0xaf,0x87,0xbc,0x10,0x8d,0x05,0x00,0x00,0x00,0x07,0x18,0xc2,0x3c,0x02,0x00,0x80, +0x00,0x03,0x1a,0x00,0x3c,0x04,0xb0,0x06,0xaf,0x85,0xbc,0x18,0x00,0x62,0x18,0x25, +0x34,0x84,0x80,0x18,0x8d,0x05,0x00,0x04,0xac,0x83,0x00,0x00,0x8e,0x02,0x01,0xa8, +0x8e,0x09,0x01,0xac,0xaf,0x85,0xbc,0x14,0x08,0x00,0x2a,0xc2,0x24,0x44,0x00,0x01, +0x01,0x6c,0x10,0x21,0x30,0x45,0x00,0xff,0x92,0x04,0x01,0xc1,0x00,0x02,0x12,0x02, +0x30,0x46,0x00,0xff,0x38,0xa5,0x00,0x00,0x24,0x42,0x00,0x01,0x92,0x03,0x01,0xd5, +0x00,0xc5,0x10,0x0a,0x00,0x82,0x20,0x21,0x00,0x64,0x18,0x2a,0x10,0x60,0xff,0xca, +0x01,0x80,0x28,0x21,0x08,0x00,0x2b,0x6b,0x02,0x00,0x20,0x21,0x90,0x87,0x01,0xc0, +0x00,0x00,0x00,0x00,0x10,0xe0,0xff,0x06,0x00,0x00,0x28,0x21,0x3c,0x02,0xb0,0x03, +0x34,0x42,0x01,0x08,0x94,0x83,0x01,0xd8,0x8c,0x88,0x01,0xd0,0x8c,0x45,0x00,0x00, +0x01,0x03,0x18,0x21,0x00,0xa3,0x10,0x2b,0x10,0x40,0x00,0x0b,0x2c,0xe2,0x00,0x02, +0x00,0xa8,0x10,0x2b,0x10,0x40,0xfe,0xf9,0x00,0xc9,0x10,0x26,0x3c,0x02,0x80,0x00, +0x00,0x62,0x18,0x21,0x00,0xa2,0x10,0x21,0x00,0x43,0x10,0x2b,0x14,0x40,0xfe,0xf3, +0x00,0xc9,0x10,0x26,0x2c,0xe2,0x00,0x02,0x10,0x40,0xff,0x90,0x00,0x00,0x00,0x00, +0x24,0x02,0x00,0x01,0x14,0xe2,0xfe,0xed,0x00,0xc9,0x10,0x26,0x3c,0x03,0xb0,0x06, +0x34,0x63,0x80,0x18,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x17,0x02, +0x14,0x40,0xfe,0xe5,0x00,0x00,0x00,0x00,0x08,0x00,0x2b,0x6b,0x00,0x00,0x00,0x00, +0x3c,0x04,0xb0,0x03,0x3c,0x06,0xb0,0x07,0x3c,0x02,0x80,0x01,0x34,0xc6,0x00,0x18, +0x34,0x84,0x00,0x20,0x24,0x42,0xaf,0xa0,0x24,0x03,0xff,0x83,0xac,0x82,0x00,0x00, +0xa0,0xc3,0x00,0x00,0x90,0xc4,0x00,0x00,0x27,0xbd,0xff,0xf8,0x3c,0x03,0xb0,0x07, +0x24,0x02,0xff,0x82,0xa3,0xa4,0x00,0x00,0xa0,0x62,0x00,0x00,0x90,0x64,0x00,0x00, +0x3c,0x02,0xb0,0x07,0x34,0x42,0x00,0x08,0xa3,0xa4,0x00,0x01,0xa0,0x40,0x00,0x00, +0x90,0x43,0x00,0x00,0x24,0x02,0x00,0x03,0x3c,0x05,0xb0,0x07,0xa3,0xa3,0x00,0x00, +0xa0,0xc2,0x00,0x00,0x90,0xc4,0x00,0x00,0x34,0xa5,0x00,0x10,0x24,0x02,0x00,0x06, +0x3c,0x03,0xb0,0x07,0xa3,0xa4,0x00,0x00,0x34,0x63,0x00,0x38,0xa0,0xa2,0x00,0x00, +0x90,0x64,0x00,0x00,0x3c,0x02,0xb0,0x07,0x34,0x42,0x00,0x20,0xa3,0xa4,0x00,0x00, +0xa0,0xa0,0x00,0x00,0x90,0xa3,0x00,0x00,0xaf,0x82,0xbf,0x20,0xa3,0xa3,0x00,0x00, +0xa0,0x40,0x00,0x00,0x90,0x43,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x08, +}; + +u8 rtl8190_fwdata_array[] ={ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00, +0x02,0xe9,0x01,0x74,0x02,0xab,0x01,0xc7,0x01,0x55,0x00,0xe4,0x00,0xab,0x00,0x72, +0x00,0x55,0x00,0x4c,0x00,0x4c,0x00,0x4c,0x00,0x4c,0x00,0x4c,0x02,0x76,0x01,0x3b, +0x00,0xd2,0x00,0x9e,0x00,0x69,0x00,0x4f,0x00,0x46,0x00,0x3f,0x01,0x3b,0x00,0x9e, +0x00,0x69,0x00,0x4f,0x00,0x35,0x00,0x27,0x00,0x23,0x00,0x20,0x01,0x2f,0x00,0x98, +0x00,0x65,0x00,0x4c,0x00,0x33,0x00,0x26,0x00,0x22,0x00,0x1e,0x00,0x98,0x00,0x4c, +0x00,0x33,0x00,0x26,0x00,0x19,0x00,0x13,0x00,0x11,0x00,0x0f,0x02,0x39,0x01,0x1c, +0x00,0xbd,0x00,0x8e,0x00,0x5f,0x00,0x47,0x00,0x3f,0x00,0x39,0x01,0x1c,0x00,0x8e, +0x00,0x5f,0x00,0x47,0x00,0x2f,0x00,0x23,0x00,0x20,0x00,0x1c,0x01,0x11,0x00,0x89, +0x00,0x5b,0x00,0x44,0x00,0x2e,0x00,0x22,0x00,0x1e,0x00,0x1b,0x00,0x89,0x00,0x44, +0x00,0x2e,0x00,0x22,0x00,0x17,0x00,0x11,0x00,0x0f,0x00,0x0e,0x02,0xab,0x02,0xab, +0x02,0x66,0x02,0x66,0x07,0x06,0x06,0x06,0x05,0x06,0x07,0x08,0x04,0x06,0x07,0x08, +0x09,0x0a,0x0b,0x0b,0x49,0x6e,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x54,0x4c, +0x42,0x4d,0x4f,0x44,0x00,0x00,0x00,0x00,0x54,0x4c,0x42,0x4c,0x5f,0x64,0x61,0x74, +0x61,0x00,0x54,0x4c,0x42,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x64,0x45,0x4c, +0x5f,0x64,0x61,0x74,0x61,0x00,0x41,0x64,0x45,0x53,0x00,0x00,0x00,0x00,0x00,0x00, +0x45,0x78,0x63,0x43,0x6f,0x64,0x65,0x36,0x00,0x00,0x45,0x78,0x63,0x43,0x6f,0x64, +0x65,0x37,0x00,0x00,0x53,0x79,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x70, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x49,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x43,0x70,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0x76,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x0b,0x53, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x2c, +0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x60, +0x00,0x00,0x00,0x90,0x00,0x00,0x00,0xc0,0x00,0x00,0x01,0x20,0x00,0x00,0x01,0x80, +0x00,0x00,0x01,0xb0,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x9c, +0x00,0x00,0x00,0xd0,0x00,0x00,0x01,0x38,0x00,0x00,0x01,0xa0,0x00,0x00,0x01,0xd4, +0x00,0x00,0x02,0x08,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0xd0,0x00,0x00,0x01,0x38, +0x00,0x00,0x01,0xa0,0x00,0x00,0x02,0x6f,0x00,0x00,0x03,0x40,0x00,0x00,0x03,0xa8, +0x00,0x00,0x04,0x10,0x01,0x01,0x01,0x02,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04, +0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x07,0x74,0x80,0x00,0x07,0x88, +0x80,0x00,0x07,0x88,0x80,0x00,0x07,0x78,0x80,0x00,0x07,0x78,0x80,0x00,0x07,0x9c, +0x80,0x00,0x53,0xc4,0x80,0x00,0x54,0x24,0x80,0x00,0x54,0x38,0x80,0x00,0x54,0x5c, +0x80,0x00,0x54,0x68,0x80,0x00,0x54,0xa8,0x80,0x00,0x56,0xa8,0x80,0x00,0x57,0xec, +0x80,0x00,0x58,0x14,0x80,0x00,0x59,0x0c,0x80,0x00,0x59,0xc4,0x80,0x00,0x5a,0x6c, +0x80,0x00,0x5a,0xe0,0x80,0x00,0x5b,0xec,0x80,0x00,0x5c,0x24,0x80,0x00,0x5c,0x38, +0x80,0x00,0x5c,0x4c,0x80,0x00,0x5d,0x40,0x80,0x00,0x5d,0x80,0x80,0x00,0x5e,0x34, +0x80,0x00,0x5e,0x5c,0x80,0x00,0x56,0x68,0x80,0x00,0x5e,0x78,0x80,0x00,0x88,0xf8, +0x80,0x00,0x88,0xf8,0x80,0x00,0x88,0xf8,0x80,0x00,0x89,0x2c,0x80,0x00,0x89,0x6c, +0x80,0x00,0x89,0xa4,0x80,0x00,0x89,0xd4,0x80,0x00,0x8a,0x10,0x80,0x00,0x8a,0x50, +0x80,0x00,0x8a,0xb8,0x80,0x00,0x8a,0xcc,0x80,0x00,0x8b,0x08,0x80,0x00,0x8b,0x10, +0x80,0x00,0x8b,0x4c,0x80,0x00,0x8b,0x60,0x80,0x00,0x8b,0x68,0x80,0x00,0x8b,0x70, +0x80,0x00,0x8b,0x70,0x80,0x00,0x8b,0x70,0x80,0x00,0x8b,0x70,0x80,0x00,0x8a,0x90, +0x80,0x00,0x8b,0xa0,0x80,0x00,0x8b,0xb4,0x80,0x00,0x88,0x54,0x80,0x00,0x8e,0xc8, +0x80,0x00,0x8e,0xc8,0x80,0x00,0x8e,0xc8,0x80,0x00,0x8e,0xfc,0x80,0x00,0x8f,0x3c, +0x80,0x00,0x8f,0x74,0x80,0x00,0x8f,0xa4,0x80,0x00,0x8f,0xe0,0x80,0x00,0x90,0x20, +0x80,0x00,0x90,0x88,0x80,0x00,0x90,0x9c,0x80,0x00,0x90,0xd8,0x80,0x00,0x90,0xe0, +0x80,0x00,0x91,0x1c,0x80,0x00,0x91,0x30,0x80,0x00,0x91,0x38,0x80,0x00,0x91,0x40, +0x80,0x00,0x91,0x40,0x80,0x00,0x91,0x40,0x80,0x00,0x91,0x40,0x80,0x00,0x90,0x60, +0x80,0x00,0x91,0x70,0x80,0x00,0x91,0x84,0x80,0x00,0x8d,0x00,}; + +u32 Rtl8192UsbPHY_REGArray[] = { +0x0, }; + +u32 Rtl8192UsbPHY_REG_1T2RArray[] = { +0x800,0x00000000, +0x804,0x00000001, +0x808,0x0000fc00, +0x80c,0x0000001c, +0x810,0x801010aa, +0x814,0x008514d0, +0x818,0x00000040, +0x81c,0x00000000, +0x820,0x00000004, +0x824,0x00690000, +0x828,0x00000004, +0x82c,0x00e90000, +0x830,0x00000004, +0x834,0x00690000, +0x838,0x00000004, +0x83c,0x00e90000, +0x840,0x00000000, +0x844,0x00000000, +0x848,0x00000000, +0x84c,0x00000000, +0x850,0x00000000, +0x854,0x00000000, +0x858,0x65a965a9, +0x85c,0x65a965a9, +0x860,0x001f0010, +0x864,0x007f0010, +0x868,0x001f0010, +0x86c,0x007f0010, +0x870,0x0f100f70, +0x874,0x0f100f70, +0x878,0x00000000, +0x87c,0x00000000, +0x880,0x6870e36c, +0x884,0xe3573600, +0x888,0x4260c340, +0x88c,0x0000ff00, +0x890,0x00000000, +0x894,0xfffffffe, +0x898,0x4c42382f, +0x89c,0x00656056, +0x8b0,0x00000000, +0x8e0,0x00000000, +0x8e4,0x00000000, +0x900,0x00000000, +0x904,0x00000023, +0x908,0x00000000, +0x90c,0x31121311, +0xa00,0x00d0c7d8, +0xa04,0x811f0008, +0xa08,0x80cd8300, +0xa0c,0x2e62740f, +0xa10,0x95009b78, +0xa14,0x11145008, +0xa18,0x00881117, +0xa1c,0x89140fa0, +0xa20,0x1a1b0000, +0xa24,0x090e1317, +0xa28,0x00000204, +0xa2c,0x00000000, +0xc00,0x00000040, +0xc04,0x00005433, +0xc08,0x000000e4, +0xc0c,0x6c6c6c6c, +0xc10,0x08800000, +0xc14,0x40000100, +0xc18,0x08000000, +0xc1c,0x40000100, +0xc20,0x08000000, +0xc24,0x40000100, +0xc28,0x08000000, +0xc2c,0x40000100, +0xc30,0x6de9ac44, +0xc34,0x465c52cd, +0xc38,0x497f5994, +0xc3c,0x0a969764, +0xc40,0x1f7c403f, +0xc44,0x000100b7, +0xc48,0xec020000, +0xc4c,0x00000300, +0xc50,0x69543420, +0xc54,0x433c0094, +0xc58,0x69543420, +0xc5c,0x433c0094, +0xc60,0x69543420, +0xc64,0x433c0094, +0xc68,0x69543420, +0xc6c,0x433c0094, +0xc70,0x2c7f000d, +0xc74,0x0186175b, +0xc78,0x0000001f, +0xc7c,0x00b91612, +0xc80,0x40000100, +0xc84,0x20000000, +0xc88,0x40000100, +0xc8c,0x20200000, +0xc90,0x40000100, +0xc94,0x00000000, +0xc98,0x40000100, +0xc9c,0x00000000, +0xca0,0x00492492, +0xca4,0x00000000, +0xca8,0x00000000, +0xcac,0x00000000, +0xcb0,0x00000000, +0xcb4,0x00000000, +0xcb8,0x00000000, +0xcbc,0x00492492, +0xcc0,0x00000000, +0xcc4,0x00000000, +0xcc8,0x00000000, +0xccc,0x00000000, +0xcd0,0x00000000, +0xcd4,0x00000000, +0xcd8,0x64b22427, +0xcdc,0x00766932, +0xce0,0x00222222, +0xd00,0x00000750, +0xd04,0x00000403, +0xd08,0x0000907f, +0xd0c,0x00000001, +0xd10,0xa0633333, +0xd14,0x33333c63, +0xd18,0x6a8f5b6b, +0xd1c,0x00000000, +0xd20,0x00000000, +0xd24,0x00000000, +0xd28,0x00000000, +0xd2c,0xcc979975, +0xd30,0x00000000, +0xd34,0x00000000, +0xd38,0x00000000, +0xd3c,0x00027293, +0xd40,0x00000000, +0xd44,0x00000000, +0xd48,0x00000000, +0xd4c,0x00000000, +0xd50,0x6437140a, +0xd54,0x024dbd02, +0xd58,0x00000000, +0xd5c,0x04032064, +0xe00,0x161a1a1a, +0xe04,0x12121416, +0xe08,0x00001800, +0xe0c,0x00000000, +0xe10,0x161a1a1a, +0xe14,0x12121416, +0xe18,0x161a1a1a, +0xe1c,0x12121416, +}; + +u32 Rtl8192UsbRadioA_Array[] = { +0x019,0x00000003, +0x000,0x000000bf, +0x001,0x00000ee0, +0x002,0x0000004c, +0x003,0x000007f1, +0x004,0x00000975, +0x005,0x00000c58, +0x006,0x00000ae6, +0x007,0x000000ca, +0x008,0x00000e1c, +0x009,0x000007f0, +0x00a,0x000009d0, +0x00b,0x000001ba, +0x00c,0x00000240, +0x00e,0x00000020, +0x00f,0x00000990, +0x012,0x00000806, +0x014,0x000005ab, +0x015,0x00000f80, +0x016,0x00000020, +0x017,0x00000597, +0x018,0x0000050a, +0x01a,0x00000f80, +0x01b,0x00000f5e, +0x01c,0x00000008, +0x01d,0x00000607, +0x01e,0x000006cc, +0x01f,0x00000000, +0x020,0x000001a5, +0x01f,0x00000001, +0x020,0x00000165, +0x01f,0x00000002, +0x020,0x000000c6, +0x01f,0x00000003, +0x020,0x00000086, +0x01f,0x00000004, +0x020,0x00000046, +0x01f,0x00000005, +0x020,0x000001e6, +0x01f,0x00000006, +0x020,0x000001a6, +0x01f,0x00000007, +0x020,0x00000166, +0x01f,0x00000008, +0x020,0x000000c7, +0x01f,0x00000009, +0x020,0x00000087, +0x01f,0x0000000a, +0x020,0x000000f7, +0x01f,0x0000000b, +0x020,0x000000d7, +0x01f,0x0000000c, +0x020,0x000000b7, +0x01f,0x0000000d, +0x020,0x00000097, +0x01f,0x0000000e, +0x020,0x00000077, +0x01f,0x0000000f, +0x020,0x00000057, +0x01f,0x00000010, +0x020,0x00000037, +0x01f,0x00000011, +0x020,0x000000fb, +0x01f,0x00000012, +0x020,0x000000db, +0x01f,0x00000013, +0x020,0x000000bb, +0x01f,0x00000014, +0x020,0x000000ff, +0x01f,0x00000015, +0x020,0x000000e3, +0x01f,0x00000016, +0x020,0x000000c3, +0x01f,0x00000017, +0x020,0x000000a3, +0x01f,0x00000018, +0x020,0x00000083, +0x01f,0x00000019, +0x020,0x00000063, +0x01f,0x0000001a, +0x020,0x00000043, +0x01f,0x0000001b, +0x020,0x00000023, +0x01f,0x0000001c, +0x020,0x00000003, +0x01f,0x0000001d, +0x020,0x000001e3, +0x01f,0x0000001e, +0x020,0x000001c3, +0x01f,0x0000001f, +0x020,0x000001a3, +0x01f,0x00000020, +0x020,0x00000183, +0x01f,0x00000021, +0x020,0x00000163, +0x01f,0x00000022, +0x020,0x00000143, +0x01f,0x00000023, +0x020,0x00000123, +0x01f,0x00000024, +0x020,0x00000103, +0x023,0x00000203, +0x024,0x00000200, +0x00b,0x000001ba, +0x02c,0x000003d7, +0x02d,0x00000ff0, +0x000,0x00000037, +0x004,0x00000160, +0x007,0x00000080, +0x002,0x0000088d, +0x0fe,0x00000000, +0x0fe,0x00000000, +0x016,0x00000200, +0x016,0x00000380, +0x016,0x00000020, +0x016,0x000001a0, +0x000,0x000000bf, +0x00d,0x0000001f, +0x00d,0x00000c9f, +0x002,0x0000004d, +0x000,0x00000cbf, +0x004,0x00000975, +0x007,0x00000700, +}; + +u32 Rtl8192UsbRadioB_Array[] = { +0x019,0x00000003, +0x000,0x000000bf, +0x001,0x000006e0, +0x002,0x0000004c, +0x003,0x000007f1, +0x004,0x00000975, +0x005,0x00000c58, +0x006,0x00000ae6, +0x007,0x000000ca, +0x008,0x00000e1c, +0x000,0x000000b7, +0x00a,0x00000850, +0x000,0x000000bf, +0x00b,0x000001ba, +0x00c,0x00000240, +0x00e,0x00000020, +0x015,0x00000f80, +0x016,0x00000020, +0x017,0x00000597, +0x018,0x0000050a, +0x01a,0x00000e00, +0x01b,0x00000f5e, +0x01d,0x00000607, +0x01e,0x000006cc, +0x00b,0x000001ba, +0x023,0x00000203, +0x024,0x00000200, +0x000,0x00000037, +0x004,0x00000160, +0x016,0x00000200, +0x016,0x00000380, +0x016,0x00000020, +0x016,0x000001a0, +0x00d,0x00000ccc, +0x000,0x000000bf, +0x002,0x0000004d, +0x000,0x00000cbf, +0x004,0x00000975, +0x007,0x00000700, +}; + +u32 Rtl8192UsbRadioC_Array[] = { +0x0, }; + +u32 Rtl8192UsbRadioD_Array[] = { +0x0, }; + +u32 Rtl8192UsbMACPHY_Array[] = { +0x03c,0xffff0000,0x00000f0f, +0x340,0xffffffff,0x161a1a1a, +0x344,0xffffffff,0x12121416, +0x348,0x0000ffff,0x00001818, +0x12c,0xffffffff,0x04000802, +0x318,0x00000fff,0x00000100, +}; + +u32 Rtl8192UsbMACPHY_Array_PG[] = { +0x03c,0xffff0000,0x00000f0f, +0xe00,0xffffffff,0x06090909, +0xe04,0xffffffff,0x00030306, +0xe08,0x0000ff00,0x00000000, +0xe10,0xffffffff,0x0a0c0d0f, +0xe14,0xffffffff,0x06070809, +0xe18,0xffffffff,0x0a0c0d0f, +0xe1c,0xffffffff,0x06070809, +0x12c,0xffffffff,0x04000802, +0x318,0x00000fff,0x00000800, +}; + +u32 Rtl8192UsbAGCTAB_Array[] = { +0xc78,0x7d000001, +0xc78,0x7d010001, +0xc78,0x7d020001, +0xc78,0x7d030001, +0xc78,0x7d040001, +0xc78,0x7d050001, +0xc78,0x7c060001, +0xc78,0x7b070001, +0xc78,0x7a080001, +0xc78,0x79090001, +0xc78,0x780a0001, +0xc78,0x770b0001, +0xc78,0x760c0001, +0xc78,0x750d0001, +0xc78,0x740e0001, +0xc78,0x730f0001, +0xc78,0x72100001, +0xc78,0x71110001, +0xc78,0x70120001, +0xc78,0x6f130001, +0xc78,0x6e140001, +0xc78,0x6d150001, +0xc78,0x6c160001, +0xc78,0x6b170001, +0xc78,0x6a180001, +0xc78,0x69190001, +0xc78,0x681a0001, +0xc78,0x671b0001, +0xc78,0x661c0001, +0xc78,0x651d0001, +0xc78,0x641e0001, +0xc78,0x491f0001, +0xc78,0x48200001, +0xc78,0x47210001, +0xc78,0x46220001, +0xc78,0x45230001, +0xc78,0x44240001, +0xc78,0x43250001, +0xc78,0x28260001, +0xc78,0x27270001, +0xc78,0x26280001, +0xc78,0x25290001, +0xc78,0x242a0001, +0xc78,0x232b0001, +0xc78,0x222c0001, +0xc78,0x212d0001, +0xc78,0x202e0001, +0xc78,0x0a2f0001, +0xc78,0x08300001, +0xc78,0x06310001, +0xc78,0x05320001, +0xc78,0x04330001, +0xc78,0x03340001, +0xc78,0x02350001, +0xc78,0x01360001, +0xc78,0x00370001, +0xc78,0x00380001, +0xc78,0x00390001, +0xc78,0x003a0001, +0xc78,0x003b0001, +0xc78,0x003c0001, +0xc78,0x003d0001, +0xc78,0x003e0001, +0xc78,0x003f0001, +0xc78,0x7d400001, +0xc78,0x7d410001, +0xc78,0x7d420001, +0xc78,0x7d430001, +0xc78,0x7d440001, +0xc78,0x7d450001, +0xc78,0x7c460001, +0xc78,0x7b470001, +0xc78,0x7a480001, +0xc78,0x79490001, +0xc78,0x784a0001, +0xc78,0x774b0001, +0xc78,0x764c0001, +0xc78,0x754d0001, +0xc78,0x744e0001, +0xc78,0x734f0001, +0xc78,0x72500001, +0xc78,0x71510001, +0xc78,0x70520001, +0xc78,0x6f530001, +0xc78,0x6e540001, +0xc78,0x6d550001, +0xc78,0x6c560001, +0xc78,0x6b570001, +0xc78,0x6a580001, +0xc78,0x69590001, +0xc78,0x685a0001, +0xc78,0x675b0001, +0xc78,0x665c0001, +0xc78,0x655d0001, +0xc78,0x645e0001, +0xc78,0x495f0001, +0xc78,0x48600001, +0xc78,0x47610001, +0xc78,0x46620001, +0xc78,0x45630001, +0xc78,0x44640001, +0xc78,0x43650001, +0xc78,0x28660001, +0xc78,0x27670001, +0xc78,0x26680001, +0xc78,0x25690001, +0xc78,0x246a0001, +0xc78,0x236b0001, +0xc78,0x226c0001, +0xc78,0x216d0001, +0xc78,0x206e0001, +0xc78,0x0a6f0001, +0xc78,0x08700001, +0xc78,0x06710001, +0xc78,0x05720001, +0xc78,0x04730001, +0xc78,0x03740001, +0xc78,0x02750001, +0xc78,0x01760001, +0xc78,0x00770001, +0xc78,0x00780001, +0xc78,0x00790001, +0xc78,0x007a0001, +0xc78,0x007b0001, +0xc78,0x007c0001, +0xc78,0x007d0001, +0xc78,0x007e0001, +0xc78,0x007f0001, +0xc78,0x2e00001e, +0xc78,0x2e01001e, +0xc78,0x2e02001e, +0xc78,0x2e03001e, +0xc78,0x2e04001e, +0xc78,0x2e05001e, +0xc78,0x3006001e, +0xc78,0x3407001e, +0xc78,0x3908001e, +0xc78,0x3c09001e, +0xc78,0x3f0a001e, +0xc78,0x420b001e, +0xc78,0x440c001e, +0xc78,0x450d001e, +0xc78,0x460e001e, +0xc78,0x460f001e, +0xc78,0x4710001e, +0xc78,0x4811001e, +0xc78,0x4912001e, +0xc78,0x4a13001e, +0xc78,0x4b14001e, +0xc78,0x4b15001e, +0xc78,0x4c16001e, +0xc78,0x4d17001e, +0xc78,0x4e18001e, +0xc78,0x4f19001e, +0xc78,0x4f1a001e, +0xc78,0x501b001e, +0xc78,0x511c001e, +0xc78,0x521d001e, +0xc78,0x521e001e, +0xc78,0x531f001e, +0xc78,0x5320001e, +0xc78,0x5421001e, +0xc78,0x5522001e, +0xc78,0x5523001e, +0xc78,0x5624001e, +0xc78,0x5725001e, +0xc78,0x5726001e, +0xc78,0x5827001e, +0xc78,0x5828001e, +0xc78,0x5929001e, +0xc78,0x592a001e, +0xc78,0x5a2b001e, +0xc78,0x5b2c001e, +0xc78,0x5c2d001e, +0xc78,0x5c2e001e, +0xc78,0x5d2f001e, +0xc78,0x5e30001e, +0xc78,0x5f31001e, +0xc78,0x6032001e, +0xc78,0x6033001e, +0xc78,0x6134001e, +0xc78,0x6235001e, +0xc78,0x6336001e, +0xc78,0x6437001e, +0xc78,0x6438001e, +0xc78,0x6539001e, +0xc78,0x663a001e, +0xc78,0x673b001e, +0xc78,0x673c001e, +0xc78,0x683d001e, +0xc78,0x693e001e, +0xc78,0x6a3f001e, +}; diff --git a/drivers/staging/rtl8192u/r819xU_firmware_img.h b/drivers/staging/rtl8192u/r819xU_firmware_img.h new file mode 100644 index 0000000000000000000000000000000000000000..d9d9515a1e617eac125c9ce6495876ff03d81393 --- /dev/null +++ b/drivers/staging/rtl8192u/r819xU_firmware_img.h @@ -0,0 +1,35 @@ +#ifndef IMG_H +#define IMG_H + +#define BOOT_ARR_LEN 344 +#define MAIN_ARR_LEN 45136 +#define DATA_ARR_LEN 796 +#define MACPHY_Array_PGLength 30 +#define PHY_REG_1T2RArrayLength 296 +#define AGCTAB_ArrayLength 384 +#define MACPHY_ArrayLength 18 + +#define RadioA_ArrayLength 246 +#define RadioB_ArrayLength 78 +#define RadioC_ArrayLength 1 +#define RadioD_ArrayLength 1 +#define PHY_REGArrayLength 1 + + +extern u8 rtl8190_fwboot_array[BOOT_ARR_LEN]; +extern u8 rtl8190_fwmain_array[MAIN_ARR_LEN]; +extern u8 rtl8190_fwdata_array[DATA_ARR_LEN]; + +extern u32 Rtl8192UsbPHY_REGArray[]; +extern u32 Rtl8192UsbPHY_REG_1T2RArray[]; +extern u32 Rtl8192UsbRadioA_Array[]; +extern u32 Rtl8192UsbRadioB_Array[]; +extern u32 Rtl8192UsbRadioC_Array[]; +extern u32 Rtl8192UsbRadioD_Array[]; +extern u32 Rtl8192UsbMACPHY_Array[]; +extern u32 Rtl8192UsbMACPHY_Array_PG[]; +extern u32 Rtl8192UsbAGCTAB_Array[]; + + + +#endif diff --git a/drivers/staging/rtl8192u/r819xU_phy.c b/drivers/staging/rtl8192u/r819xU_phy.c new file mode 100644 index 0000000000000000000000000000000000000000..a3adaedece9a7a8d6140f4368b794238d1dc80a4 --- /dev/null +++ b/drivers/staging/rtl8192u/r819xU_phy.c @@ -0,0 +1,1777 @@ +#include "r8192U.h" +#include "r8192U_hw.h" +#include "r819xU_phy.h" +#include "r819xU_phyreg.h" +#include "r8190_rtl8256.h" +#include "r8192U_dm.h" +#include "r819xU_firmware_img.h" + +#ifdef ENABLE_DOT11D +#include "dot11d.h" +#endif +static u32 RF_CHANNEL_TABLE_ZEBRA[] = { + 0, + 0x085c, //2412 1 + 0x08dc, //2417 2 + 0x095c, //2422 3 + 0x09dc, //2427 4 + 0x0a5c, //2432 5 + 0x0adc, //2437 6 + 0x0b5c, //2442 7 + 0x0bdc, //2447 8 + 0x0c5c, //2452 9 + 0x0cdc, //2457 10 + 0x0d5c, //2462 11 + 0x0ddc, //2467 12 + 0x0e5c, //2472 13 + 0x0f72, //2484 +}; + + +#define rtl819XPHY_REG_1T2RArray Rtl8192UsbPHY_REG_1T2RArray +#define rtl819XMACPHY_Array_PG Rtl8192UsbMACPHY_Array_PG +#define rtl819XMACPHY_Array Rtl8192UsbMACPHY_Array +#define rtl819XRadioA_Array Rtl8192UsbRadioA_Array +#define rtl819XRadioB_Array Rtl8192UsbRadioB_Array +#define rtl819XRadioC_Array Rtl8192UsbRadioC_Array +#define rtl819XRadioD_Array Rtl8192UsbRadioD_Array +#define rtl819XAGCTAB_Array Rtl8192UsbAGCTAB_Array + +/****************************************************************************** + *function: This function read BB parameters from Header file we gen, + * and do register read/write + * input: u32 dwBitMask //taget bit pos in the addr to be modified + * output: none + * return: u32 return the shift bit bit position of the mask + * ****************************************************************************/ +u32 rtl8192_CalculateBitShift(u32 dwBitMask) +{ + u32 i; + for (i=0; i<=31; i++) + { + if (((dwBitMask>>i)&0x1) == 1) + break; + } + return i; +} +/****************************************************************************** + *function: This function check different RF type to execute legal judgement. If RF Path is illegal, we will return false. + * input: none + * output: none + * return: 0(illegal, false), 1(legal,true) + * ***************************************************************************/ +u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device* dev, u32 eRFPath) +{ + u8 ret = 1; + struct r8192_priv *priv = ieee80211_priv(dev); + if (priv->rf_type == RF_2T4R) + ret = 0; + else if (priv->rf_type == RF_1T2R) + { + if (eRFPath == RF90_PATH_A || eRFPath == RF90_PATH_B) + ret = 1; + else if (eRFPath == RF90_PATH_C || eRFPath == RF90_PATH_D) + ret = 0; + } + return ret; +} +/****************************************************************************** + *function: This function set specific bits to BB register + * input: net_device dev + * u32 dwRegAddr //target addr to be modified + * u32 dwBitMask //taget bit pos in the addr to be modified + * u32 dwData //value to be write + * output: none + * return: none + * notice: + * ****************************************************************************/ +void rtl8192_setBBreg(struct net_device* dev, u32 dwRegAddr, u32 dwBitMask, u32 dwData) +{ + + u32 OriginalValue, BitShift, NewValue; + + if(dwBitMask!= bMaskDWord) + {//if not "double word" write + OriginalValue = read_nic_dword(dev, dwRegAddr); + BitShift = rtl8192_CalculateBitShift(dwBitMask); + NewValue = (((OriginalValue) & (~dwBitMask)) | (dwData << BitShift)); + write_nic_dword(dev, dwRegAddr, NewValue); + }else + write_nic_dword(dev, dwRegAddr, dwData); + return; +} +/****************************************************************************** + *function: This function reads specific bits from BB register + * input: net_device dev + * u32 dwRegAddr //target addr to be readback + * u32 dwBitMask //taget bit pos in the addr to be readback + * output: none + * return: u32 Data //the readback register value + * notice: + * ****************************************************************************/ +u32 rtl8192_QueryBBReg(struct net_device* dev, u32 dwRegAddr, u32 dwBitMask) +{ + u32 Ret = 0, OriginalValue, BitShift; + + OriginalValue = read_nic_dword(dev, dwRegAddr); + BitShift = rtl8192_CalculateBitShift(dwBitMask); + Ret =(OriginalValue & dwBitMask) >> BitShift; + + return (Ret); +} +static u32 phy_FwRFSerialRead( struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset ); + +static void phy_FwRFSerialWrite( struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data); + +/****************************************************************************** + *function: This function read register from RF chip + * input: net_device dev + * RF90_RADIO_PATH_E eRFPath //radio path of A/B/C/D + * u32 Offset //target address to be read + * output: none + * return: u32 readback value + * notice: There are three types of serial operations:(1) Software serial write.(2)Hardware LSSI-Low Speed Serial Interface.(3)Hardware HSSI-High speed serial write. Driver here need to implement (1) and (2)---need more spec for this information. + * ****************************************************************************/ +u32 rtl8192_phy_RFSerialRead(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u32 ret = 0; + u32 NewOffset = 0; + BB_REGISTER_DEFINITION_T* pPhyReg = &priv->PHYRegDef[eRFPath]; + rtl8192_setBBreg(dev, pPhyReg->rfLSSIReadBack, bLSSIReadBackData, 0); + //make sure RF register offset is correct + Offset &= 0x3f; + + //switch page for 8256 RF IC + if (priv->rf_chip == RF_8256) + { + if (Offset >= 31) + { + priv->RfReg0Value[eRFPath] |= 0x140; + //Switch to Reg_Mode2 for Reg 31-45 + rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath]<<16) ); + //modify offset + NewOffset = Offset -30; + } + else if (Offset >= 16) + { + priv->RfReg0Value[eRFPath] |= 0x100; + priv->RfReg0Value[eRFPath] &= (~0x40); + //Switch to Reg_Mode 1 for Reg16-30 + rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath]<<16) ); + + NewOffset = Offset - 15; + } + else + NewOffset = Offset; + } + else + { + RT_TRACE((COMP_PHY|COMP_ERR), "check RF type here, need to be 8256\n"); + NewOffset = Offset; + } + //put desired read addr to LSSI control Register + rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadAddress, NewOffset); + //Issue a posedge trigger + // + rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x0); + rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x1); + + + // TODO: we should not delay such a long time. Ask help from SD3 + msleep(1); + + ret = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBack, bLSSIReadBackData); + + + // Switch back to Reg_Mode0; + if(priv->rf_chip == RF_8256) + { + priv->RfReg0Value[eRFPath] &= 0xebf; + + rtl8192_setBBreg( + dev, + pPhyReg->rf3wireOffset, + bMaskDWord, + (priv->RfReg0Value[eRFPath] << 16)); + } + + return ret; + +} + +/****************************************************************************** + *function: This function write data to RF register + * input: net_device dev + * RF90_RADIO_PATH_E eRFPath //radio path of A/B/C/D + * u32 Offset //target address to be written + * u32 Data //The new register data to be written + * output: none + * return: none + * notice: For RF8256 only. + =========================================================== + *Reg Mode RegCTL[1] RegCTL[0] Note + * (Reg00[12]) (Reg00[10]) + *=========================================================== + *Reg_Mode0 0 x Reg 0 ~15(0x0 ~ 0xf) + *------------------------------------------------------------------ + *Reg_Mode1 1 0 Reg 16 ~30(0x1 ~ 0xf) + *------------------------------------------------------------------ + * Reg_Mode2 1 1 Reg 31 ~ 45(0x1 ~ 0xf) + *------------------------------------------------------------------ + * ****************************************************************************/ +void rtl8192_phy_RFSerialWrite(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u32 DataAndAddr = 0, NewOffset = 0; + BB_REGISTER_DEFINITION_T *pPhyReg = &priv->PHYRegDef[eRFPath]; + + Offset &= 0x3f; + //spin_lock_irqsave(&priv->rf_lock, flags); +// down(&priv->rf_sem); + if (priv->rf_chip == RF_8256) + { + + if (Offset >= 31) + { + priv->RfReg0Value[eRFPath] |= 0x140; + rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath] << 16)); + NewOffset = Offset - 30; + } + else if (Offset >= 16) + { + priv->RfReg0Value[eRFPath] |= 0x100; + priv->RfReg0Value[eRFPath] &= (~0x40); + rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath]<<16)); + NewOffset = Offset - 15; + } + else + NewOffset = Offset; + } + else + { + RT_TRACE((COMP_PHY|COMP_ERR), "check RF type here, need to be 8256\n"); + NewOffset = Offset; + } + + // Put write addr in [5:0] and write data in [31:16] + DataAndAddr = (Data<<16) | (NewOffset&0x3f); + + // Write Operation + rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr); + + + if(Offset==0x0) + priv->RfReg0Value[eRFPath] = Data; + + // Switch back to Reg_Mode0; + if(priv->rf_chip == RF_8256) + { + if(Offset != 0) + { + priv->RfReg0Value[eRFPath] &= 0xebf; + rtl8192_setBBreg( + dev, + pPhyReg->rf3wireOffset, + bMaskDWord, + (priv->RfReg0Value[eRFPath] << 16)); + } + } + //spin_unlock_irqrestore(&priv->rf_lock, flags); +// up(&priv->rf_sem); + return; +} + +/****************************************************************************** + *function: This function set specific bits to RF register + * input: net_device dev + * RF90_RADIO_PATH_E eRFPath //radio path of A/B/C/D + * u32 RegAddr //target addr to be modified + * u32 BitMask //taget bit pos in the addr to be modified + * u32 Data //value to be write + * output: none + * return: none + * notice: + * ****************************************************************************/ +void rtl8192_phy_SetRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask, u32 Data) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u32 Original_Value, BitShift, New_Value; +// u8 time = 0; + + if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) + return; + + if (priv->Rf_Mode == RF_OP_By_FW) + { + if (BitMask != bMask12Bits) // RF data is 12 bits only + { + Original_Value = phy_FwRFSerialRead(dev, eRFPath, RegAddr); + BitShift = rtl8192_CalculateBitShift(BitMask); + New_Value = ((Original_Value) & (~BitMask)) | (Data<< BitShift); + + phy_FwRFSerialWrite(dev, eRFPath, RegAddr, New_Value); + }else + phy_FwRFSerialWrite(dev, eRFPath, RegAddr, Data); + + udelay(200); + + } + else + { + if (BitMask != bMask12Bits) // RF data is 12 bits only + { + Original_Value = rtl8192_phy_RFSerialRead(dev, eRFPath, RegAddr); + BitShift = rtl8192_CalculateBitShift(BitMask); + New_Value = (((Original_Value) & (~BitMask)) | (Data<< BitShift)); + + rtl8192_phy_RFSerialWrite(dev, eRFPath, RegAddr, New_Value); + }else + rtl8192_phy_RFSerialWrite(dev, eRFPath, RegAddr, Data); + } + return; +} + +/****************************************************************************** + *function: This function reads specific bits from RF register + * input: net_device dev + * u32 RegAddr //target addr to be readback + * u32 BitMask //taget bit pos in the addr to be readback + * output: none + * return: u32 Data //the readback register value + * notice: + * ****************************************************************************/ +u32 rtl8192_phy_QueryRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask) +{ + u32 Original_Value, Readback_Value, BitShift; + struct r8192_priv *priv = ieee80211_priv(dev); + + + if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) + return 0; + if (priv->Rf_Mode == RF_OP_By_FW) + { + Original_Value = phy_FwRFSerialRead(dev, eRFPath, RegAddr); + BitShift = rtl8192_CalculateBitShift(BitMask); + Readback_Value = (Original_Value & BitMask) >> BitShift; + udelay(200); + return (Readback_Value); + } + else + { + Original_Value = rtl8192_phy_RFSerialRead(dev, eRFPath, RegAddr); + BitShift = rtl8192_CalculateBitShift(BitMask); + Readback_Value = (Original_Value & BitMask) >> BitShift; + return (Readback_Value); + } +} +/****************************************************************************** + *function: We support firmware to execute RF-R/W. + * input: dev + * output: none + * return: none + * notice: + * ***************************************************************************/ +static u32 +phy_FwRFSerialRead( + struct net_device* dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset ) +{ + u32 retValue = 0; + u32 Data = 0; + u8 time = 0; + //DbgPrint("FW RF CTRL\n\r"); + /* 2007/11/02 MH Firmware RF Write control. By Francis' suggestion, we can + not execute the scheme in the initial step. Otherwise, RF-R/W will waste + much time. This is only for site survey. */ + // 1. Read operation need not insert data. bit 0-11 + //Data &= bMask12Bits; + // 2. Write RF register address. Bit 12-19 + Data |= ((Offset&0xFF)<<12); + // 3. Write RF path. bit 20-21 + Data |= ((eRFPath&0x3)<<20); + // 4. Set RF read indicator. bit 22=0 + //Data |= 0x00000; + // 5. Trigger Fw to operate the command. bit 31 + Data |= 0x80000000; + // 6. We can not execute read operation if bit 31 is 1. + while (read_nic_dword(dev, QPNR)&0x80000000) + { + // If FW can not finish RF-R/W for more than ?? times. We must reset FW. + if (time++ < 100) + { + //DbgPrint("FW not finish RF-R Time=%d\n\r", time); + udelay(10); + } + else + break; + } + // 7. Execute read operation. + write_nic_dword(dev, QPNR, Data); + // 8. Check if firmawre send back RF content. + while (read_nic_dword(dev, QPNR)&0x80000000) + { + // If FW can not finish RF-R/W for more than ?? times. We must reset FW. + if (time++ < 100) + { + //DbgPrint("FW not finish RF-W Time=%d\n\r", time); + udelay(10); + } + else + return (0); + } + retValue = read_nic_dword(dev, RF_DATA); + + return (retValue); + +} /* phy_FwRFSerialRead */ + +/****************************************************************************** + *function: We support firmware to execute RF-R/W. + * input: dev + * output: none + * return: none + * notice: + * ***************************************************************************/ +static void +phy_FwRFSerialWrite( + struct net_device* dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset, + u32 Data ) +{ + u8 time = 0; + + //DbgPrint("N FW RF CTRL RF-%d OF%02x DATA=%03x\n\r", eRFPath, Offset, Data); + /* 2007/11/02 MH Firmware RF Write control. By Francis' suggestion, we can + not execute the scheme in the initial step. Otherwise, RF-R/W will waste + much time. This is only for site survey. */ + + // 1. Set driver write bit and 12 bit data. bit 0-11 + //Data &= bMask12Bits; // Done by uper layer. + // 2. Write RF register address. bit 12-19 + Data |= ((Offset&0xFF)<<12); + // 3. Write RF path. bit 20-21 + Data |= ((eRFPath&0x3)<<20); + // 4. Set RF write indicator. bit 22=1 + Data |= 0x400000; + // 5. Trigger Fw to operate the command. bit 31=1 + Data |= 0x80000000; + + // 6. Write operation. We can not write if bit 31 is 1. + while (read_nic_dword(dev, QPNR)&0x80000000) + { + // If FW can not finish RF-R/W for more than ?? times. We must reset FW. + if (time++ < 100) + { + //DbgPrint("FW not finish RF-W Time=%d\n\r", time); + udelay(10); + } + else + break; + } + // 7. No matter check bit. We always force the write. Because FW will + // not accept the command. + write_nic_dword(dev, QPNR, Data); + /* 2007/11/02 MH Acoording to test, we must delay 20us to wait firmware + to finish RF write operation. */ + /* 2008/01/17 MH We support delay in firmware side now. */ + //delay_us(20); + +} /* phy_FwRFSerialWrite */ + + +/****************************************************************************** + *function: This function read BB parameters from Header file we gen, + * and do register read/write + * input: dev + * output: none + * return: none + * notice: BB parameters may change all the time, so please make + * sure it has been synced with the newest. + * ***************************************************************************/ +void rtl8192_phy_configmac(struct net_device* dev) +{ + u32 dwArrayLen = 0, i; + u32* pdwArray = NULL; + struct r8192_priv *priv = ieee80211_priv(dev); + + if(priv->btxpowerdata_readfromEEPORM) + { + RT_TRACE(COMP_PHY, "Rtl819XMACPHY_Array_PG\n"); + dwArrayLen = MACPHY_Array_PGLength; + pdwArray = rtl819XMACPHY_Array_PG; + + } + else + { + RT_TRACE(COMP_PHY, "Rtl819XMACPHY_Array\n"); + dwArrayLen = MACPHY_ArrayLength; + pdwArray = rtl819XMACPHY_Array; + } + for(i = 0; ibInHctTest) + { + PHY_REGArrayLen = PHY_REGArrayLengthDTM; + AGCTAB_ArrayLen = AGCTAB_ArrayLengthDTM; + Rtl8190PHY_REGArray_Table = Rtl819XPHY_REGArrayDTM; + Rtl8190AGCTAB_Array_Table = Rtl819XAGCTAB_ArrayDTM; + } +#endif + if (ConfigType == BaseBand_Config_PHY_REG) + { + for (i=0; iPHYRegDef[RF90_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; // 16 LSBs if read 32-bit from 0x870 + priv->PHYRegDef[RF90_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; // 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) + priv->PHYRegDef[RF90_PATH_C].rfintfs = rFPGA0_XCD_RFInterfaceSW;// 16 LSBs if read 32-bit from 0x874 + priv->PHYRegDef[RF90_PATH_D].rfintfs = rFPGA0_XCD_RFInterfaceSW;// 16 MSBs if read 32-bit from 0x874 (16-bit for 0x876) + + // RF Interface Readback Value + priv->PHYRegDef[RF90_PATH_A].rfintfi = rFPGA0_XAB_RFInterfaceRB; // 16 LSBs if read 32-bit from 0x8E0 + priv->PHYRegDef[RF90_PATH_B].rfintfi = rFPGA0_XAB_RFInterfaceRB;// 16 MSBs if read 32-bit from 0x8E0 (16-bit for 0x8E2) + priv->PHYRegDef[RF90_PATH_C].rfintfi = rFPGA0_XCD_RFInterfaceRB;// 16 LSBs if read 32-bit from 0x8E4 + priv->PHYRegDef[RF90_PATH_D].rfintfi = rFPGA0_XCD_RFInterfaceRB;// 16 MSBs if read 32-bit from 0x8E4 (16-bit for 0x8E6) + + // RF Interface Output (and Enable) + priv->PHYRegDef[RF90_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE; // 16 LSBs if read 32-bit from 0x860 + priv->PHYRegDef[RF90_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE; // 16 LSBs if read 32-bit from 0x864 + priv->PHYRegDef[RF90_PATH_C].rfintfo = rFPGA0_XC_RFInterfaceOE;// 16 LSBs if read 32-bit from 0x868 + priv->PHYRegDef[RF90_PATH_D].rfintfo = rFPGA0_XD_RFInterfaceOE;// 16 LSBs if read 32-bit from 0x86C + + // RF Interface (Output and) Enable + priv->PHYRegDef[RF90_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE; // 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) + priv->PHYRegDef[RF90_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE; // 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) + priv->PHYRegDef[RF90_PATH_C].rfintfe = rFPGA0_XC_RFInterfaceOE;// 16 MSBs if read 32-bit from 0x86A (16-bit for 0x86A) + priv->PHYRegDef[RF90_PATH_D].rfintfe = rFPGA0_XD_RFInterfaceOE;// 16 MSBs if read 32-bit from 0x86C (16-bit for 0x86E) + + //Addr of LSSI. Wirte RF register by driver + priv->PHYRegDef[RF90_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; //LSSI Parameter + priv->PHYRegDef[RF90_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter; + priv->PHYRegDef[RF90_PATH_C].rf3wireOffset = rFPGA0_XC_LSSIParameter; + priv->PHYRegDef[RF90_PATH_D].rf3wireOffset = rFPGA0_XD_LSSIParameter; + + // RF parameter + priv->PHYRegDef[RF90_PATH_A].rfLSSI_Select = rFPGA0_XAB_RFParameter; //BB Band Select + priv->PHYRegDef[RF90_PATH_B].rfLSSI_Select = rFPGA0_XAB_RFParameter; + priv->PHYRegDef[RF90_PATH_C].rfLSSI_Select = rFPGA0_XCD_RFParameter; + priv->PHYRegDef[RF90_PATH_D].rfLSSI_Select = rFPGA0_XCD_RFParameter; + + // Tx AGC Gain Stage (same for all path. Should we remove this?) + priv->PHYRegDef[RF90_PATH_A].rfTxGainStage = rFPGA0_TxGainStage; //Tx gain stage + priv->PHYRegDef[RF90_PATH_B].rfTxGainStage = rFPGA0_TxGainStage; //Tx gain stage + priv->PHYRegDef[RF90_PATH_C].rfTxGainStage = rFPGA0_TxGainStage; //Tx gain stage + priv->PHYRegDef[RF90_PATH_D].rfTxGainStage = rFPGA0_TxGainStage; //Tx gain stage + + // Tranceiver A~D HSSI Parameter-1 + priv->PHYRegDef[RF90_PATH_A].rfHSSIPara1 = rFPGA0_XA_HSSIParameter1; //wire control parameter1 + priv->PHYRegDef[RF90_PATH_B].rfHSSIPara1 = rFPGA0_XB_HSSIParameter1; //wire control parameter1 + priv->PHYRegDef[RF90_PATH_C].rfHSSIPara1 = rFPGA0_XC_HSSIParameter1; //wire control parameter1 + priv->PHYRegDef[RF90_PATH_D].rfHSSIPara1 = rFPGA0_XD_HSSIParameter1; //wire control parameter1 + + // Tranceiver A~D HSSI Parameter-2 + priv->PHYRegDef[RF90_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2; //wire control parameter2 + priv->PHYRegDef[RF90_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2; //wire control parameter2 + priv->PHYRegDef[RF90_PATH_C].rfHSSIPara2 = rFPGA0_XC_HSSIParameter2; //wire control parameter2 + priv->PHYRegDef[RF90_PATH_D].rfHSSIPara2 = rFPGA0_XD_HSSIParameter2; //wire control parameter1 + + // RF switch Control + priv->PHYRegDef[RF90_PATH_A].rfSwitchControl = rFPGA0_XAB_SwitchControl; //TR/Ant switch control + priv->PHYRegDef[RF90_PATH_B].rfSwitchControl = rFPGA0_XAB_SwitchControl; + priv->PHYRegDef[RF90_PATH_C].rfSwitchControl = rFPGA0_XCD_SwitchControl; + priv->PHYRegDef[RF90_PATH_D].rfSwitchControl = rFPGA0_XCD_SwitchControl; + + // AGC control 1 + priv->PHYRegDef[RF90_PATH_A].rfAGCControl1 = rOFDM0_XAAGCCore1; + priv->PHYRegDef[RF90_PATH_B].rfAGCControl1 = rOFDM0_XBAGCCore1; + priv->PHYRegDef[RF90_PATH_C].rfAGCControl1 = rOFDM0_XCAGCCore1; + priv->PHYRegDef[RF90_PATH_D].rfAGCControl1 = rOFDM0_XDAGCCore1; + + // AGC control 2 + priv->PHYRegDef[RF90_PATH_A].rfAGCControl2 = rOFDM0_XAAGCCore2; + priv->PHYRegDef[RF90_PATH_B].rfAGCControl2 = rOFDM0_XBAGCCore2; + priv->PHYRegDef[RF90_PATH_C].rfAGCControl2 = rOFDM0_XCAGCCore2; + priv->PHYRegDef[RF90_PATH_D].rfAGCControl2 = rOFDM0_XDAGCCore2; + + // RX AFE control 1 + priv->PHYRegDef[RF90_PATH_A].rfRxIQImbalance = rOFDM0_XARxIQImbalance; + priv->PHYRegDef[RF90_PATH_B].rfRxIQImbalance = rOFDM0_XBRxIQImbalance; + priv->PHYRegDef[RF90_PATH_C].rfRxIQImbalance = rOFDM0_XCRxIQImbalance; + priv->PHYRegDef[RF90_PATH_D].rfRxIQImbalance = rOFDM0_XDRxIQImbalance; + + // RX AFE control 1 + priv->PHYRegDef[RF90_PATH_A].rfRxAFE = rOFDM0_XARxAFE; + priv->PHYRegDef[RF90_PATH_B].rfRxAFE = rOFDM0_XBRxAFE; + priv->PHYRegDef[RF90_PATH_C].rfRxAFE = rOFDM0_XCRxAFE; + priv->PHYRegDef[RF90_PATH_D].rfRxAFE = rOFDM0_XDRxAFE; + + // Tx AFE control 1 + priv->PHYRegDef[RF90_PATH_A].rfTxIQImbalance = rOFDM0_XATxIQImbalance; + priv->PHYRegDef[RF90_PATH_B].rfTxIQImbalance = rOFDM0_XBTxIQImbalance; + priv->PHYRegDef[RF90_PATH_C].rfTxIQImbalance = rOFDM0_XCTxIQImbalance; + priv->PHYRegDef[RF90_PATH_D].rfTxIQImbalance = rOFDM0_XDTxIQImbalance; + + // Tx AFE control 2 + priv->PHYRegDef[RF90_PATH_A].rfTxAFE = rOFDM0_XATxAFE; + priv->PHYRegDef[RF90_PATH_B].rfTxAFE = rOFDM0_XBTxAFE; + priv->PHYRegDef[RF90_PATH_C].rfTxAFE = rOFDM0_XCTxAFE; + priv->PHYRegDef[RF90_PATH_D].rfTxAFE = rOFDM0_XDTxAFE; + + // Tranceiver LSSI Readback + priv->PHYRegDef[RF90_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack; + priv->PHYRegDef[RF90_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack; + priv->PHYRegDef[RF90_PATH_C].rfLSSIReadBack = rFPGA0_XC_LSSIReadBack; + priv->PHYRegDef[RF90_PATH_D].rfLSSIReadBack = rFPGA0_XD_LSSIReadBack; + +} +/****************************************************************************** + *function: This function is to write register and then readback to make sure whether BB and RF is OK + * input: net_device dev + * HW90_BLOCK_E CheckBlock + * RF90_RADIO_PATH_E eRFPath //only used when checkblock is HW90_BLOCK_RF + * output: none + * return: return whether BB and RF is ok(0:OK; 1:Fail) + * notice: This function may be removed in the ASIC + * ***************************************************************************/ +u8 rtl8192_phy_checkBBAndRF(struct net_device* dev, HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath) +{ +// struct r8192_priv *priv = ieee80211_priv(dev); +// BB_REGISTER_DEFINITION_T *pPhyReg = &priv->PHYRegDef[eRFPath]; + u8 ret = 0; + u32 i, CheckTimes = 4, dwRegRead = 0; + u32 WriteAddr[4]; + u32 WriteData[] = {0xfffff027, 0xaa55a02f, 0x00000027, 0x55aa502f}; + // Initialize register address offset to be checked + WriteAddr[HW90_BLOCK_MAC] = 0x100; + WriteAddr[HW90_BLOCK_PHY0] = 0x900; + WriteAddr[HW90_BLOCK_PHY1] = 0x800; + WriteAddr[HW90_BLOCK_RF] = 0x3; + RT_TRACE(COMP_PHY, "=======>%s(), CheckBlock:%d\n", __FUNCTION__, CheckBlock); + for(i=0 ; i < CheckTimes ; i++) + { + + // + // Write Data to register and readback + // + switch(CheckBlock) + { + case HW90_BLOCK_MAC: + RT_TRACE(COMP_ERR, "PHY_CheckBBRFOK(): Never Write 0x100 here!"); + break; + + case HW90_BLOCK_PHY0: + case HW90_BLOCK_PHY1: + write_nic_dword(dev, WriteAddr[CheckBlock], WriteData[i]); + dwRegRead = read_nic_dword(dev, WriteAddr[CheckBlock]); + break; + + case HW90_BLOCK_RF: + WriteData[i] &= 0xfff; + rtl8192_phy_SetRFReg(dev, eRFPath, WriteAddr[HW90_BLOCK_RF], bMask12Bits, WriteData[i]); + // TODO: we should not delay for such a long time. Ask SD3 + msleep(1); + dwRegRead = rtl8192_phy_QueryRFReg(dev, eRFPath, WriteAddr[HW90_BLOCK_RF], bMask12Bits); + msleep(1); + break; + + default: + ret = 1; + break; + } + + + // + // Check whether readback data is correct + // + if(dwRegRead != WriteData[i]) + { + RT_TRACE((COMP_PHY|COMP_ERR), "====>error=====dwRegRead: %x, WriteData: %x \n", dwRegRead, WriteData[i]); + ret = 1; + break; + } + } + + return ret; +} + + +/****************************************************************************** + *function: This function initialize BB&RF + * input: net_device dev + * output: none + * return: none + * notice: Initialization value may change all the time, so please make + * sure it has been synced with the newest. + * ***************************************************************************/ +void rtl8192_BB_Config_ParaFile(struct net_device* dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u8 bRegValue = 0, eCheckItem = 0, rtStatus = 0; + u32 dwRegValue = 0; + /************************************** + //<1>Initialize BaseBand + **************************************/ + + /*--set BB Global Reset--*/ + bRegValue = read_nic_byte(dev, BB_GLOBAL_RESET); + write_nic_byte(dev, BB_GLOBAL_RESET,(bRegValue|BB_GLOBAL_RESET_BIT)); + mdelay(50); + /*---set BB reset Active---*/ + dwRegValue = read_nic_dword(dev, CPU_GEN); + write_nic_dword(dev, CPU_GEN, (dwRegValue&(~CPU_GEN_BB_RST))); + + /*----Ckeck FPGAPHY0 and PHY1 board is OK----*/ + // TODO: this function should be removed on ASIC , Emily 2007.2.2 + for(eCheckItem=(HW90_BLOCK_E)HW90_BLOCK_PHY0; eCheckItem<=HW90_BLOCK_PHY1; eCheckItem++) + { + rtStatus = rtl8192_phy_checkBBAndRF(dev, (HW90_BLOCK_E)eCheckItem, (RF90_RADIO_PATH_E)0); //don't care RF path + if(rtStatus != 0) + { + RT_TRACE((COMP_ERR | COMP_PHY), "PHY_RF8256_Config():Check PHY%d Fail!!\n", eCheckItem-1); + return ; + } + } + /*---- Set CCK and OFDM Block "OFF"----*/ + rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn|bOFDMEn, 0x0); + /*----BB Register Initilazation----*/ + //==m==>Set PHY REG From Header<==m== + rtl8192_phyConfigBB(dev, BaseBand_Config_PHY_REG); + + /*----Set BB reset de-Active----*/ + dwRegValue = read_nic_dword(dev, CPU_GEN); + write_nic_dword(dev, CPU_GEN, (dwRegValue|CPU_GEN_BB_RST)); + + /*----BB AGC table Initialization----*/ + //==m==>Set PHY REG From Header<==m== + rtl8192_phyConfigBB(dev, BaseBand_Config_AGC_TAB); + + /*----Enable XSTAL ----*/ + write_nic_byte_E(dev, 0x5e, 0x00); + if (priv->card_8192_version == (u8)VERSION_819xU_A) + { + //Antenna gain offset from B/C/D to A + dwRegValue = (priv->AntennaTxPwDiff[1]<<4 | priv->AntennaTxPwDiff[0]); + rtl8192_setBBreg(dev, rFPGA0_TxGainStage, (bXBTxAGC|bXCTxAGC), dwRegValue); + + //XSTALLCap + dwRegValue = priv->CrystalCap & 0xf; + rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, bXtalCap, dwRegValue); + } + + // Check if the CCK HighPower is turned ON. + // This is used to calculate PWDB. + priv->bCckHighPower = (u8)(rtl8192_QueryBBReg(dev, rFPGA0_XA_HSSIParameter2, 0x200)); + return; +} +/****************************************************************************** + *function: This function initialize BB&RF + * input: net_device dev + * output: none + * return: none + * notice: Initialization value may change all the time, so please make + * sure it has been synced with the newest. + * ***************************************************************************/ +void rtl8192_BBConfig(struct net_device* dev) +{ + rtl8192_InitBBRFRegDef(dev); + //config BB&RF. As hardCode based initialization has not been well + //implemented, so use file first.FIXME:should implement it for hardcode? + rtl8192_BB_Config_ParaFile(dev); + return; +} + +/****************************************************************************** + *function: This function obtains the initialization value of Tx power Level offset + * input: net_device dev + * output: none + * return: none + * ***************************************************************************/ +void rtl8192_phy_getTxPower(struct net_device* dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + priv->MCSTxPowerLevelOriginalOffset[0] = + read_nic_dword(dev, rTxAGC_Rate18_06); + priv->MCSTxPowerLevelOriginalOffset[1] = + read_nic_dword(dev, rTxAGC_Rate54_24); + priv->MCSTxPowerLevelOriginalOffset[2] = + read_nic_dword(dev, rTxAGC_Mcs03_Mcs00); + priv->MCSTxPowerLevelOriginalOffset[3] = + read_nic_dword(dev, rTxAGC_Mcs07_Mcs04); + priv->MCSTxPowerLevelOriginalOffset[4] = + read_nic_dword(dev, rTxAGC_Mcs11_Mcs08); + priv->MCSTxPowerLevelOriginalOffset[5] = + read_nic_dword(dev, rTxAGC_Mcs15_Mcs12); + + // read rx initial gain + priv->DefaultInitialGain[0] = read_nic_byte(dev, rOFDM0_XAAGCCore1); + priv->DefaultInitialGain[1] = read_nic_byte(dev, rOFDM0_XBAGCCore1); + priv->DefaultInitialGain[2] = read_nic_byte(dev, rOFDM0_XCAGCCore1); + priv->DefaultInitialGain[3] = read_nic_byte(dev, rOFDM0_XDAGCCore1); + RT_TRACE(COMP_INIT, "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x) \n", + priv->DefaultInitialGain[0], priv->DefaultInitialGain[1], + priv->DefaultInitialGain[2], priv->DefaultInitialGain[3]); + + // read framesync + priv->framesync = read_nic_byte(dev, rOFDM0_RxDetector3); + priv->framesyncC34 = read_nic_byte(dev, rOFDM0_RxDetector2); + RT_TRACE(COMP_INIT, "Default framesync (0x%x) = 0x%x \n", + rOFDM0_RxDetector3, priv->framesync); + + // read SIFS (save the value read fome MACPHY_REG.txt) + priv->SifsTime = read_nic_word(dev, SIFS); + + return; +} + +/****************************************************************************** + *function: This function obtains the initialization value of Tx power Level offset + * input: net_device dev + * output: none + * return: none + * ***************************************************************************/ +void rtl8192_phy_setTxPower(struct net_device* dev, u8 channel) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u8 powerlevel = priv->TxPowerLevelCCK[channel-1]; + u8 powerlevelOFDM24G = priv->TxPowerLevelOFDM24G[channel-1]; + + switch(priv->rf_chip) + { + case RF_8256: + PHY_SetRF8256CCKTxPower(dev, powerlevel); //need further implement + PHY_SetRF8256OFDMTxPower(dev, powerlevelOFDM24G); + break; + default: +// case RF_8225: +// case RF_8258: + RT_TRACE((COMP_PHY|COMP_ERR), "error RF chipID(8225 or 8258) in function %s()\n", __FUNCTION__); + break; + } + return; +} + +/****************************************************************************** + *function: This function check Rf chip to do RF config + * input: net_device dev + * output: none + * return: only 8256 is supported + * ***************************************************************************/ +void rtl8192_phy_RFConfig(struct net_device* dev) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + switch(priv->rf_chip) + { + case RF_8256: + PHY_RF8256_Config(dev); + break; + // case RF_8225: + // case RF_8258: + default: + RT_TRACE(COMP_ERR, "error chip id\n"); + break; + } + return; +} + +/****************************************************************************** + *function: This function update Initial gain + * input: net_device dev + * output: none + * return: As Windows has not implemented this, wait for complement + * ***************************************************************************/ +void rtl8192_phy_updateInitGain(struct net_device* dev) +{ + return; +} + +/****************************************************************************** + *function: This function read RF parameters from general head file, and do RF 3-wire + * input: net_device dev + * output: none + * return: return code show if RF configuration is successful(0:pass, 1:fail) + * Note: Delay may be required for RF configuration + * ***************************************************************************/ +u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev, RF90_RADIO_PATH_E eRFPath) +{ + + int i; + //u32* pRFArray; + u8 ret = 0; + + switch(eRFPath){ + case RF90_PATH_A: + for(i = 0;iTxPowerLevelCCK[channel-1]; + u8 powerlevelOFDM24G = priv->TxPowerLevelOFDM24G[channel-1]; + + switch(priv->rf_chip) + { + case RF_8225: +#ifdef TO_DO_LIST + PHY_SetRF8225CckTxPower(Adapter, powerlevel); + PHY_SetRF8225OfdmTxPower(Adapter, powerlevelOFDM24G); +#endif + break; + + case RF_8256: + PHY_SetRF8256CCKTxPower(dev, powerlevel); + PHY_SetRF8256OFDMTxPower(dev, powerlevelOFDM24G); + break; + + case RF_8258: + break; + default: + RT_TRACE(COMP_ERR, "unknown rf chip ID in rtl8192_SetTxPowerLevel()\n"); + break; + } + return; +} + +/****************************************************************************** + *function: This function set RF state on or off + * input: struct net_device *dev + * RT_RF_POWER_STATE eRFPowerState //Power State to set + * output: none + * return: none + * Note: + * ***************************************************************************/ +bool rtl8192_SetRFPowerState(struct net_device *dev, RT_RF_POWER_STATE eRFPowerState) +{ + bool bResult = true; +// u8 eRFPath; + struct r8192_priv *priv = ieee80211_priv(dev); + + if(eRFPowerState == priv->ieee80211->eRFPowerState) + return false; + + if(priv->SetRFPowerStateInProgress == true) + return false; + + priv->SetRFPowerStateInProgress = true; + + switch(priv->rf_chip) + { + case RF_8256: + switch( eRFPowerState ) + { + case eRfOn: + //RF-A, RF-B + //enable RF-Chip A/B + rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x1); // 0x860[4] + //analog to digital on + rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);// 0x88c[9:8] + //digital to analog on + rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x3); // 0x880[4:3] + //rx antenna on + rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0] + //rx antenna on + rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0] + //analog to digital part2 on + rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x3); // 0x880[6:5] + + break; + + case eRfSleep: + + break; + + case eRfOff: + //RF-A, RF-B + //disable RF-Chip A/B + rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0); // 0x860[4] + //analog to digital off, for power save + rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8] + //digital to analog off, for power save + rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0); // 0x880[4:3] + //rx antenna off + rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0);// 0xc04[3:0] + //rx antenna off + rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0);// 0xd04[3:0] + //analog to digital part2 off, for power save + rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0); // 0x880[6:5] + + break; + + default: + bResult = false; + RT_TRACE(COMP_ERR, "SetRFPowerState819xUsb(): unknow state to set: 0x%X!!!\n", eRFPowerState); + break; + } + break; + default: + RT_TRACE(COMP_ERR, "Not support rf_chip(%x)\n", priv->rf_chip); + break; + } +#ifdef TO_DO_LIST + if(bResult) + { + // Update current RF state variable. + pHalData->eRFPowerState = eRFPowerState; + switch(pHalData->RFChipID ) + { + case RF_8256: + switch(pHalData->eRFPowerState) + { + case eRfOff: + // + //If Rf off reason is from IPS, Led should blink with no link, by Maddest 071015 + // + if(pMgntInfo->RfOffReason==RF_CHANGE_BY_IPS ) + { + Adapter->HalFunc.LedControlHandler(Adapter,LED_CTL_NO_LINK); + } + else + { + // Turn off LED if RF is not ON. + Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_POWER_OFF); + } + break; + + case eRfOn: + // Turn on RF we are still linked, which might happen when + // we quickly turn off and on HW RF. 2006.05.12, by rcnjko. + if( pMgntInfo->bMediaConnect == TRUE ) + { + Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_LINK); + } + else + { + // Turn off LED if RF is not ON. + Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_NO_LINK); + } + break; + + default: + // do nothing. + break; + }// Switch RF state + break; + + default: + RT_TRACE(COMP_RF, DBG_LOUD, ("SetRFPowerState8190(): Unknown RF type\n")); + break; + } + + } +#endif + priv->SetRFPowerStateInProgress = false; + + return bResult; +} + +/**************************************************************************************** + *function: This function set command table variable(struct SwChnlCmd). + * input: SwChnlCmd* CmdTable //table to be set. + * u32 CmdTableIdx //variable index in table to be set + * u32 CmdTableSz //table size. + * SwChnlCmdID CmdID //command ID to set. + * u32 Para1 + * u32 Para2 + * u32 msDelay + * output: + * return: true if finished, false otherwise + * Note: + * ************************************************************************************/ +u8 rtl8192_phy_SetSwChnlCmdArray( + SwChnlCmd* CmdTable, + u32 CmdTableIdx, + u32 CmdTableSz, + SwChnlCmdID CmdID, + u32 Para1, + u32 Para2, + u32 msDelay + ) +{ + SwChnlCmd* pCmd; + + if(CmdTable == NULL) + { + RT_TRACE(COMP_ERR, "phy_SetSwChnlCmdArray(): CmdTable cannot be NULL.\n"); + return false; + } + if(CmdTableIdx >= CmdTableSz) + { + RT_TRACE(COMP_ERR, "phy_SetSwChnlCmdArray(): Access invalid index, please check size of the table, CmdTableIdx:%d, CmdTableSz:%d\n", + CmdTableIdx, CmdTableSz); + return false; + } + + pCmd = CmdTable + CmdTableIdx; + pCmd->CmdID = CmdID; + pCmd->Para1 = Para1; + pCmd->Para2 = Para2; + pCmd->msDelay = msDelay; + + return true; +} +/****************************************************************************** + *function: This function set channel step by step + * input: struct net_device *dev + * u8 channel + * u8* stage //3 stages + * u8* step // + * u32* delay //whether need to delay + * output: store new stage, step and delay for next step(combine with function above) + * return: true if finished, false otherwise + * Note: Wait for simpler function to replace it //wb + * ***************************************************************************/ +u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel, u8* stage, u8* step, u32* delay) +{ + struct r8192_priv *priv = ieee80211_priv(dev); +// PCHANNEL_ACCESS_SETTING pChnlAccessSetting; + SwChnlCmd PreCommonCmd[MAX_PRECMD_CNT]; + u32 PreCommonCmdCnt; + SwChnlCmd PostCommonCmd[MAX_POSTCMD_CNT]; + u32 PostCommonCmdCnt; + SwChnlCmd RfDependCmd[MAX_RFDEPENDCMD_CNT]; + u32 RfDependCmdCnt; + SwChnlCmd *CurrentCmd = NULL; + //RF90_RADIO_PATH_E eRFPath; + u8 eRFPath; +// u32 RfRetVal; +// u8 RetryCnt; + + RT_TRACE(COMP_CH, "====>%s()====stage:%d, step:%d, channel:%d\n", __FUNCTION__, *stage, *step, channel); +// RT_ASSERT(IsLegalChannel(Adapter, channel), ("illegal channel: %d\n", channel)); +#ifdef ENABLE_DOT11D + if (!IsLegalChannel(priv->ieee80211, channel)) + { + RT_TRACE(COMP_ERR, "=============>set to illegal channel:%d\n", channel); + return true; //return true to tell upper caller function this channel setting is finished! Or it will in while loop. + } +#endif +//FIXME:need to check whether channel is legal or not here.WB + + + //for(eRFPath = RF90_PATH_A; eRFPath NumTotalRFPath; eRFPath++) +// for(eRFPath = 0; eRFPath Fill up pre common command. + PreCommonCmdCnt = 0; + rtl8192_phy_SetSwChnlCmdArray(PreCommonCmd, PreCommonCmdCnt++, MAX_PRECMD_CNT, + CmdID_SetTxPowerLevel, 0, 0, 0); + rtl8192_phy_SetSwChnlCmdArray(PreCommonCmd, PreCommonCmdCnt++, MAX_PRECMD_CNT, + CmdID_End, 0, 0, 0); + + // <2> Fill up post common command. + PostCommonCmdCnt = 0; + + rtl8192_phy_SetSwChnlCmdArray(PostCommonCmd, PostCommonCmdCnt++, MAX_POSTCMD_CNT, + CmdID_End, 0, 0, 0); + + // <3> Fill up RF dependent command. + RfDependCmdCnt = 0; + switch( priv->rf_chip ) + { + case RF_8225: + if (!(channel >= 1 && channel <= 14)) + { + RT_TRACE(COMP_ERR, "illegal channel for Zebra 8225: %d\n", channel); + return true; + } + rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, + CmdID_RF_WriteReg, rZebra1_Channel, RF_CHANNEL_TABLE_ZEBRA[channel], 10); + rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, + CmdID_End, 0, 0, 0); + break; + + case RF_8256: + // TEST!! This is not the table for 8256!! + if (!(channel >= 1 && channel <= 14)) + { + RT_TRACE(COMP_ERR, "illegal channel for Zebra 8256: %d\n", channel); + return true; + } + rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, + CmdID_RF_WriteReg, rZebra1_Channel, channel, 10); + rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, + CmdID_End, 0, 0, 0); + break; + + case RF_8258: + break; + + default: + RT_TRACE(COMP_ERR, "Unknown RFChipID: %d\n", priv->rf_chip); + return true; + break; + } + + + do{ + switch(*stage) + { + case 0: + CurrentCmd=&PreCommonCmd[*step]; + break; + case 1: + CurrentCmd=&RfDependCmd[*step]; + break; + case 2: + CurrentCmd=&PostCommonCmd[*step]; + break; + } + + if(CurrentCmd->CmdID==CmdID_End) + { + if((*stage)==2) + { + (*delay)=CurrentCmd->msDelay; + return true; + } + else + { + (*stage)++; + (*step)=0; + continue; + } + } + + switch(CurrentCmd->CmdID) + { + case CmdID_SetTxPowerLevel: + if(priv->card_8192_version == (u8)VERSION_819xU_A) //xiong: consider it later! + rtl8192_SetTxPowerLevel(dev,channel); + break; + case CmdID_WritePortUlong: + write_nic_dword(dev, CurrentCmd->Para1, CurrentCmd->Para2); + break; + case CmdID_WritePortUshort: + write_nic_word(dev, CurrentCmd->Para1, (u16)CurrentCmd->Para2); + break; + case CmdID_WritePortUchar: + write_nic_byte(dev, CurrentCmd->Para1, (u8)CurrentCmd->Para2); + break; + case CmdID_RF_WriteReg: + for(eRFPath = 0; eRFPath < RF90_PATH_MAX; eRFPath++) + { + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, CurrentCmd->Para1, bZebra1_ChannelNum, CurrentCmd->Para2); + } + break; + default: + break; + } + + break; + }while(true); +// }/*for(Number of RF paths)*/ + + (*delay)=CurrentCmd->msDelay; + (*step)++; + return false; +} + +/****************************************************************************** + *function: This function does acturally set channel work + * input: struct net_device *dev + * u8 channel + * output: none + * return: noin + * Note: We should not call this function directly + * ***************************************************************************/ +void rtl8192_phy_FinishSwChnlNow(struct net_device *dev, u8 channel) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + u32 delay = 0; + + while(!rtl8192_phy_SwChnlStepByStep(dev,channel,&priv->SwChnlStage,&priv->SwChnlStep,&delay)) + { + // if(delay>0) + // msleep(delay);//or mdelay? need further consideration + if(!priv->up) + break; + } +} +/****************************************************************************** + *function: Callback routine of the work item for switch channel. + * input: + * + * output: none + * return: noin + * ***************************************************************************/ +void rtl8192_SwChnl_WorkItem(struct net_device *dev) +{ + + struct r8192_priv *priv = ieee80211_priv(dev); + + RT_TRACE(COMP_CH, "==> SwChnlCallback819xUsbWorkItem(), chan:%d\n", priv->chan); + + + rtl8192_phy_FinishSwChnlNow(dev , priv->chan); + + RT_TRACE(COMP_CH, "<== SwChnlCallback819xUsbWorkItem()\n"); +} + +/****************************************************************************** + *function: This function scheduled actural workitem to set channel + * input: net_device dev + * u8 channel //channel to set + * output: none + * return: return code show if workitem is scheduled(1:pass, 0:fail) + * Note: Delay may be required for RF configuration + * ***************************************************************************/ +u8 rtl8192_phy_SwChnl(struct net_device* dev, u8 channel) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + RT_TRACE(COMP_CH, "=====>%s(), SwChnlInProgress:%d\n", __FUNCTION__, priv->SwChnlInProgress); + if(!priv->up) + return false; + if(priv->SwChnlInProgress) + return false; + +// if(pHalData->SetBWModeInProgress) +// return; +if (0) //to test current channel from RF reg 0x7. +{ + u8 eRFPath; + for(eRFPath = 0; eRFPath < 2; eRFPath++){ + printk("====>set channel:%x\n",rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x7, bZebra1_ChannelNum)); + udelay(10); + } +} + //-------------------------------------------- + switch(priv->ieee80211->mode) + { + case WIRELESS_MODE_A: + case WIRELESS_MODE_N_5G: + if (channel<=14){ + RT_TRACE(COMP_ERR, "WIRELESS_MODE_A but channel<=14"); + return false; + } + break; + case WIRELESS_MODE_B: + if (channel>14){ + RT_TRACE(COMP_ERR, "WIRELESS_MODE_B but channel>14"); + return false; + } + break; + case WIRELESS_MODE_G: + case WIRELESS_MODE_N_24G: + if (channel>14){ + RT_TRACE(COMP_ERR, "WIRELESS_MODE_G but channel>14"); + return false; + } + break; + } + //-------------------------------------------- + + priv->SwChnlInProgress = true; + if(channel == 0) + channel = 1; + + priv->chan=channel; + + priv->SwChnlStage=0; + priv->SwChnlStep=0; +// schedule_work(&(priv->SwChnlWorkItem)); +// rtl8192_SwChnl_WorkItem(dev); + if(priv->up) { +// queue_work(priv->priv_wq,&(priv->SwChnlWorkItem)); + rtl8192_SwChnl_WorkItem(dev); + } + + priv->SwChnlInProgress = false; + return true; +} + + +// +/****************************************************************************** + *function: Callback routine of the work item for set bandwidth mode. + * input: struct net_device *dev + * HT_CHANNEL_WIDTH Bandwidth //20M or 40M + * HT_EXTCHNL_OFFSET Offset //Upper, Lower, or Don't care + * output: none + * return: none + * Note: I doubt whether SetBWModeInProgress flag is necessary as we can + * test whether current work in the queue or not.//do I? + * ***************************************************************************/ +void rtl8192_SetBWModeWorkItem(struct net_device *dev) +{ + + struct r8192_priv *priv = ieee80211_priv(dev); + u8 regBwOpMode; + + RT_TRACE(COMP_SWBW, "==>rtl8192_SetBWModeWorkItem() Switch to %s bandwidth\n", \ + priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20?"20MHz":"40MHz") + + + if(priv->rf_chip == RF_PSEUDO_11N) + { + priv->SetBWModeInProgress= false; + return; + } + + //<1>Set MAC register + regBwOpMode = read_nic_byte(dev, BW_OPMODE); + + switch(priv->CurrentChannelBW) + { + case HT_CHANNEL_WIDTH_20: + regBwOpMode |= BW_OPMODE_20MHZ; + // 2007/02/07 Mark by Emily becasue we have not verify whether this register works + write_nic_byte(dev, BW_OPMODE, regBwOpMode); + break; + + case HT_CHANNEL_WIDTH_20_40: + regBwOpMode &= ~BW_OPMODE_20MHZ; + // 2007/02/07 Mark by Emily becasue we have not verify whether this register works + write_nic_byte(dev, BW_OPMODE, regBwOpMode); + break; + + default: + RT_TRACE(COMP_ERR, "SetChannelBandwidth819xUsb(): unknown Bandwidth: %#X\n",priv->CurrentChannelBW); + break; + } + + //<2>Set PHY related register + switch(priv->CurrentChannelBW) + { + case HT_CHANNEL_WIDTH_20: + // Add by Vivi 20071119 + rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x0); + rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x0); + rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 1); + + // Correct the tx power for CCK rate in 20M. Suggest by YN, 20071207 + priv->cck_present_attentuation = + priv->cck_present_attentuation_20Mdefault + priv->cck_present_attentuation_difference; + + if(priv->cck_present_attentuation > 22) + priv->cck_present_attentuation= 22; + if(priv->cck_present_attentuation< 0) + priv->cck_present_attentuation = 0; + RT_TRACE(COMP_INIT, "20M, pHalData->CCKPresentAttentuation = %d\n", priv->cck_present_attentuation); + + if(priv->chan == 14 && !priv->bcck_in_ch14) + { + priv->bcck_in_ch14 = TRUE; + dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + } + else if(priv->chan != 14 && priv->bcck_in_ch14) + { + priv->bcck_in_ch14 = FALSE; + dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + } + else + dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + + break; + case HT_CHANNEL_WIDTH_20_40: + // Add by Vivi 20071119 + rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x1); + rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x1); + rtl8192_setBBreg(dev, rCCK0_System, bCCKSideBand, (priv->nCur40MhzPrimeSC>>1)); + rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 0); + rtl8192_setBBreg(dev, rOFDM1_LSTF, 0xC00, priv->nCur40MhzPrimeSC); + priv->cck_present_attentuation = + priv->cck_present_attentuation_40Mdefault + priv->cck_present_attentuation_difference; + + if(priv->cck_present_attentuation > 22) + priv->cck_present_attentuation = 22; + if(priv->cck_present_attentuation < 0) + priv->cck_present_attentuation = 0; + + RT_TRACE(COMP_INIT, "40M, pHalData->CCKPresentAttentuation = %d\n", priv->cck_present_attentuation); + if(priv->chan == 14 && !priv->bcck_in_ch14) + { + priv->bcck_in_ch14 = true; + dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + } + else if(priv->chan!= 14 && priv->bcck_in_ch14) + { + priv->bcck_in_ch14 = false; + dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + } + else + dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + + break; + default: + RT_TRACE(COMP_ERR, "SetChannelBandwidth819xUsb(): unknown Bandwidth: %#X\n" ,priv->CurrentChannelBW); + break; + + } + //Skip over setting of J-mode in BB register here. Default value is "None J mode". Emily 20070315 + + //<3>Set RF related register + switch( priv->rf_chip ) + { + case RF_8225: +#ifdef TO_DO_LIST + PHY_SetRF8225Bandwidth(Adapter, pHalData->CurrentChannelBW); +#endif + break; + + case RF_8256: + PHY_SetRF8256Bandwidth(dev, priv->CurrentChannelBW); + break; + + case RF_8258: + // PHY_SetRF8258Bandwidth(); + break; + + case RF_PSEUDO_11N: + // Do Nothing + break; + + default: + RT_TRACE(COMP_ERR, "Unknown RFChipID: %d\n", priv->rf_chip); + break; + } + priv->SetBWModeInProgress= false; + + RT_TRACE(COMP_SWBW, "<==SetBWMode819xUsb(), %d", atomic_read(&(priv->ieee80211->atm_swbw)) ); +} + +/****************************************************************************** + *function: This function schedules bandwith switch work. + * input: struct net_device *dev + * HT_CHANNEL_WIDTH Bandwidth //20M or 40M + * HT_EXTCHNL_OFFSET Offset //Upper, Lower, or Don't care + * output: none + * return: none + * Note: I doubt whether SetBWModeInProgress flag is necessary as we can + * test whether current work in the queue or not.//do I? + * ***************************************************************************/ +void rtl8192_SetBWMode(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + if(priv->SetBWModeInProgress) + return; + priv->SetBWModeInProgress= true; + + priv->CurrentChannelBW = Bandwidth; + + if(Offset==HT_EXTCHNL_OFFSET_LOWER) + priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_UPPER; + else if(Offset==HT_EXTCHNL_OFFSET_UPPER) + priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_LOWER; + else + priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_DONT_CARE; + + //queue_work(priv->priv_wq, &(priv->SetBWModeWorkItem)); + // schedule_work(&(priv->SetBWModeWorkItem)); + rtl8192_SetBWModeWorkItem(dev); + +} + +void InitialGain819xUsb(struct net_device *dev, u8 Operation) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + + priv->InitialGainOperateType = Operation; + + if(priv->up) + { + queue_delayed_work(priv->priv_wq,&priv->initialgain_operate_wq,0); + } +} + +extern void InitialGainOperateWorkItemCallBack(struct work_struct *work) +{ + struct delayed_work *dwork = container_of(work,struct delayed_work,work); + struct r8192_priv *priv = container_of(dwork,struct r8192_priv,initialgain_operate_wq); + struct net_device *dev = priv->ieee80211->dev; +#define SCAN_RX_INITIAL_GAIN 0x17 +#define POWER_DETECTION_TH 0x08 + u32 BitMask; + u8 initial_gain; + u8 Operation; + + Operation = priv->InitialGainOperateType; + + switch(Operation) + { + case IG_Backup: + RT_TRACE(COMP_SCAN, "IG_Backup, backup the initial gain.\n"); + initial_gain = SCAN_RX_INITIAL_GAIN;//priv->DefaultInitialGain[0];// + BitMask = bMaskByte0; + if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM) + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); // FW DIG OFF + priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, BitMask); + priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, BitMask); + priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, BitMask); + priv->initgain_backup.xdagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1, BitMask); + BitMask = bMaskByte2; + priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev, rCCK0_CCA, BitMask); + + RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xc50 is %x\n",priv->initgain_backup.xaagccore1); + RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xc58 is %x\n",priv->initgain_backup.xbagccore1); + RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xc60 is %x\n",priv->initgain_backup.xcagccore1); + RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xc68 is %x\n",priv->initgain_backup.xdagccore1); + RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xa0a is %x\n",priv->initgain_backup.cca); + + RT_TRACE(COMP_SCAN, "Write scan initial gain = 0x%x \n", initial_gain); + write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain); + write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain); + write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain); + write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain); + RT_TRACE(COMP_SCAN, "Write scan 0xa0a = 0x%x \n", POWER_DETECTION_TH); + write_nic_byte(dev, 0xa0a, POWER_DETECTION_TH); + break; + case IG_Restore: + RT_TRACE(COMP_SCAN, "IG_Restore, restore the initial gain.\n"); + BitMask = 0x7f; //Bit0~ Bit6 + if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM) + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); // FW DIG OFF + + rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, BitMask, (u32)priv->initgain_backup.xaagccore1); + rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, BitMask, (u32)priv->initgain_backup.xbagccore1); + rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, BitMask, (u32)priv->initgain_backup.xcagccore1); + rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, BitMask, (u32)priv->initgain_backup.xdagccore1); + BitMask = bMaskByte2; + rtl8192_setBBreg(dev, rCCK0_CCA, BitMask, (u32)priv->initgain_backup.cca); + + RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc50 is %x\n",priv->initgain_backup.xaagccore1); + RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc58 is %x\n",priv->initgain_backup.xbagccore1); + RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc60 is %x\n",priv->initgain_backup.xcagccore1); + RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc68 is %x\n",priv->initgain_backup.xdagccore1); + RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xa0a is %x\n",priv->initgain_backup.cca); + +#ifdef RTL8190P + SetTxPowerLevel8190(Adapter,priv->CurrentChannel); +#endif +#ifdef RTL8192E + SetTxPowerLevel8190(Adapter,priv->CurrentChannel); +#endif +//#ifdef RTL8192U + rtl8192_phy_setTxPower(dev,priv->ieee80211->current_network.channel); +//#endif + + if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM) + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); // FW DIG ON + break; + default: + RT_TRACE(COMP_SCAN, "Unknown IG Operation. \n"); + break; + } +} + diff --git a/drivers/staging/rtl8192u/r819xU_phy.h b/drivers/staging/rtl8192u/r819xU_phy.h new file mode 100644 index 0000000000000000000000000000000000000000..3e3bc577e6c3dae233f9a0f2691bf05d38ea5d0e --- /dev/null +++ b/drivers/staging/rtl8192u/r819xU_phy.h @@ -0,0 +1,90 @@ +#ifndef _R819XU_PHY_H +#define _R819XU_PHY_H + +/* Channel switch:The size of command tables for switch channel*/ +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 + +typedef enum _SwChnlCmdID{ + CmdID_End, + CmdID_SetTxPowerLevel, + CmdID_BBRegWrite10, + CmdID_WritePortUlong, + CmdID_WritePortUshort, + CmdID_WritePortUchar, + CmdID_RF_WriteReg, +}SwChnlCmdID; + +/*--------------------------------Define structure--------------------------------*/ +/* 1. Switch channel related */ +typedef struct _SwChnlCmd{ + SwChnlCmdID CmdID; + u32 Para1; + u32 Para2; + u32 msDelay; +}__attribute__ ((packed)) SwChnlCmd; + +extern u32 rtl819XMACPHY_Array_PG[]; +extern u32 rtl819XPHY_REG_1T2RArray[]; +extern u32 rtl819XAGCTAB_Array[]; +extern u32 rtl819XRadioA_Array[]; +extern u32 rtl819XRadioB_Array[]; +extern u32 rtl819XRadioC_Array[]; +extern u32 rtl819XRadioD_Array[]; + +typedef enum _HW90_BLOCK{ + HW90_BLOCK_MAC = 0, + HW90_BLOCK_PHY0 = 1, + HW90_BLOCK_PHY1 = 2, + HW90_BLOCK_RF = 3, + HW90_BLOCK_MAXIMUM = 4, // Never use this +}HW90_BLOCK_E, *PHW90_BLOCK_E; + +typedef enum _RF90_RADIO_PATH{ + RF90_PATH_A = 0, //Radio Path A + RF90_PATH_B = 1, //Radio Path B + RF90_PATH_C = 2, //Radio Path C + RF90_PATH_D = 3, //Radio Path D + RF90_PATH_MAX //Max RF number 92 support +}RF90_RADIO_PATH_E, *PRF90_RADIO_PATH_E; + +#define bMaskByte0 0xff +#define bMaskByte1 0xff00 +#define bMaskByte2 0xff0000 +#define bMaskByte3 0xff000000 +#define bMaskHWord 0xffff0000 +#define bMaskLWord 0x0000ffff +#define bMaskDWord 0xffffffff + +//extern u32 rtl8192_CalculateBitShift(u32 dwBitMask); +extern u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device* dev, u32 eRFPath); +extern void rtl8192_setBBreg(struct net_device* dev, u32 dwRegAddr, u32 dwBitMask, u32 dwData); +extern u32 rtl8192_QueryBBReg(struct net_device* dev, u32 dwRegAddr, u32 dwBitMask); +//extern u32 rtl8192_phy_RFSerialRead(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset); +//extern void rtl8192_phy_RFSerialWrite(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data); +extern void rtl8192_phy_SetRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask, u32 Data); +extern u32 rtl8192_phy_QueryRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask); +extern void rtl8192_phy_configmac(struct net_device* dev); +extern void rtl8192_phyConfigBB(struct net_device* dev, u8 ConfigType); +//extern void rtl8192_InitBBRFRegDef(struct net_device* dev); +extern u8 rtl8192_phy_checkBBAndRF(struct net_device* dev, HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath); +//extern void rtl8192_BB_Config_ParaFile(struct net_device* dev); +extern void rtl8192_BBConfig(struct net_device* dev); +extern void rtl8192_phy_getTxPower(struct net_device* dev); +extern void rtl8192_phy_setTxPower(struct net_device* dev, u8 channel); +extern void rtl8192_phy_RFConfig(struct net_device* dev); +extern void rtl8192_phy_updateInitGain(struct net_device* dev); +extern u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev, RF90_RADIO_PATH_E eRFPath); + +extern u8 rtl8192_phy_SwChnl(struct net_device* dev, u8 channel); +extern void rtl8192_SetBWMode(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset); +extern void rtl8192_SwChnl_WorkItem(struct net_device *dev); +void rtl8192_SetBWModeWorkItem(struct net_device *dev); +extern bool rtl8192_SetRFPowerState(struct net_device *dev, RT_RF_POWER_STATE eRFPowerState); +//added by amy +extern void InitialGain819xUsb(struct net_device *dev, u8 Operation); + +extern void InitialGainOperateWorkItemCallBack(struct work_struct *work); + +#endif diff --git a/drivers/staging/rtl8192u/r819xU_phyreg.h b/drivers/staging/rtl8192u/r819xU_phyreg.h new file mode 100644 index 0000000000000000000000000000000000000000..06b0b539e1bc5d3bdeb023593392db8a938a21e2 --- /dev/null +++ b/drivers/staging/rtl8192u/r819xU_phyreg.h @@ -0,0 +1,871 @@ +#ifndef _R819XU_PHYREG_H +#define _R819XU_PHYREG_H + + +#define RF_DATA 0x1d4 // FW will write RF data in the register. + +//Register //duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF +//page 1 +#define rPMAC_Reset 0x100 +#define rPMAC_TxStart 0x104 +#define rPMAC_TxLegacySIG 0x108 +#define rPMAC_TxHTSIG1 0x10c +#define rPMAC_TxHTSIG2 0x110 +#define rPMAC_PHYDebug 0x114 +#define rPMAC_TxPacketNum 0x118 +#define rPMAC_TxIdle 0x11c +#define rPMAC_TxMACHeader0 0x120 +#define rPMAC_TxMACHeader1 0x124 +#define rPMAC_TxMACHeader2 0x128 +#define rPMAC_TxMACHeader3 0x12c +#define rPMAC_TxMACHeader4 0x130 +#define rPMAC_TxMACHeader5 0x134 +#define rPMAC_TxDataType 0x138 +#define rPMAC_TxRandomSeed 0x13c +#define rPMAC_CCKPLCPPreamble 0x140 +#define rPMAC_CCKPLCPHeader 0x144 +#define rPMAC_CCKCRC16 0x148 +#define rPMAC_OFDMRxCRC32OK 0x170 +#define rPMAC_OFDMRxCRC32Er 0x174 +#define rPMAC_OFDMRxParityEr 0x178 +#define rPMAC_OFDMRxCRC8Er 0x17c +#define rPMAC_CCKCRxRC16Er 0x180 +#define rPMAC_CCKCRxRC32Er 0x184 +#define rPMAC_CCKCRxRC32OK 0x188 +#define rPMAC_TxStatus 0x18c + +//page8 +#define rFPGA0_RFMOD 0x800 //RF mode & CCK TxSC +#define rFPGA0_TxInfo 0x804 +#define rFPGA0_PSDFunction 0x808 +#define rFPGA0_TxGainStage 0x80c +#define rFPGA0_RFTiming1 0x810 +#define rFPGA0_RFTiming2 0x814 +//#define rFPGA0_XC_RFTiming 0x818 +//#define rFPGA0_XD_RFTiming 0x81c +#define rFPGA0_XA_HSSIParameter1 0x820 +#define rFPGA0_XA_HSSIParameter2 0x824 +#define rFPGA0_XB_HSSIParameter1 0x828 +#define rFPGA0_XB_HSSIParameter2 0x82c +#define rFPGA0_XC_HSSIParameter1 0x830 +#define rFPGA0_XC_HSSIParameter2 0x834 +#define rFPGA0_XD_HSSIParameter1 0x838 +#define rFPGA0_XD_HSSIParameter2 0x83c +#define rFPGA0_XA_LSSIParameter 0x840 +#define rFPGA0_XB_LSSIParameter 0x844 +#define rFPGA0_XC_LSSIParameter 0x848 +#define rFPGA0_XD_LSSIParameter 0x84c +#define rFPGA0_RFWakeUpParameter 0x850 +#define rFPGA0_RFSleepUpParameter 0x854 +#define rFPGA0_XAB_SwitchControl 0x858 +#define rFPGA0_XCD_SwitchControl 0x85c +#define rFPGA0_XA_RFInterfaceOE 0x860 +#define rFPGA0_XB_RFInterfaceOE 0x864 +#define rFPGA0_XC_RFInterfaceOE 0x868 +#define rFPGA0_XD_RFInterfaceOE 0x86c +#define rFPGA0_XAB_RFInterfaceSW 0x870 +#define rFPGA0_XCD_RFInterfaceSW 0x874 +#define rFPGA0_XAB_RFParameter 0x878 +#define rFPGA0_XCD_RFParameter 0x87c +#define rFPGA0_AnalogParameter1 0x880 +#define rFPGA0_AnalogParameter2 0x884 +#define rFPGA0_AnalogParameter3 0x888 +#define rFPGA0_AnalogParameter4 0x88c +#define rFPGA0_XA_LSSIReadBack 0x8a0 +#define rFPGA0_XB_LSSIReadBack 0x8a4 +#define rFPGA0_XC_LSSIReadBack 0x8a8 +#define rFPGA0_XD_LSSIReadBack 0x8ac +#define rFPGA0_PSDReport 0x8b4 +#define rFPGA0_XAB_RFInterfaceRB 0x8e0 +#define rFPGA0_XCD_RFInterfaceRB 0x8e4 + +//page 9 +#define rFPGA1_RFMOD 0x900 //RF mode & OFDM TxSC +#define rFPGA1_TxBlock 0x904 +#define rFPGA1_DebugSelect 0x908 +#define rFPGA1_TxInfo 0x90c + +//page a +#define rCCK0_System 0xa00 +#define rCCK0_AFESetting 0xa04 +#define rCCK0_CCA 0xa08 +#define rCCK0_RxAGC1 0xa0c //AGC default value, saturation level +#define rCCK0_RxAGC2 0xa10 //AGC & DAGC +#define rCCK0_RxHP 0xa14 +#define rCCK0_DSPParameter1 0xa18 //Timing recovery & Channel estimation threshold +#define rCCK0_DSPParameter2 0xa1c //SQ threshold +#define rCCK0_TxFilter1 0xa20 +#define rCCK0_TxFilter2 0xa24 +#define rCCK0_DebugPort 0xa28 //debug port and Tx filter3 +#define rCCK0_FalseAlarmReport 0xa2c //0xa2d +#define rCCK0_TRSSIReport 0xa50 +#define rCCK0_RxReport 0xa54 //0xa57 +#define rCCK0_FACounterLower 0xa5c //0xa5b +#define rCCK0_FACounterUpper 0xa58 //0xa5c + +//page c +#define rOFDM0_LSTF 0xc00 +#define rOFDM0_TRxPathEnable 0xc04 +#define rOFDM0_TRMuxPar 0xc08 +#define rOFDM0_TRSWIsolation 0xc0c +#define rOFDM0_XARxAFE 0xc10 //RxIQ DC offset, Rx digital filter, DC notch filter +#define rOFDM0_XARxIQImbalance 0xc14 //RxIQ imblance matrix +#define rOFDM0_XBRxAFE 0xc18 +#define rOFDM0_XBRxIQImbalance 0xc1c +#define rOFDM0_XCRxAFE 0xc20 +#define rOFDM0_XCRxIQImbalance 0xc24 +#define rOFDM0_XDRxAFE 0xc28 +#define rOFDM0_XDRxIQImbalance 0xc2c +#define rOFDM0_RxDetector1 0xc30 //PD,BW & SBD +#define rOFDM0_RxDetector2 0xc34 //SBD & Fame Sync. +#define rOFDM0_RxDetector3 0xc38 //Frame Sync. +#define rOFDM0_RxDetector4 0xc3c //PD, SBD, Frame Sync & Short-GI +#define rOFDM0_RxDSP 0xc40 //Rx Sync Path +#define rOFDM0_CFOandDAGC 0xc44 //CFO & DAGC +#define rOFDM0_CCADropThreshold 0xc48 //CCA Drop threshold +#define rOFDM0_ECCAThreshold 0xc4c // energy CCA +#define rOFDM0_XAAGCCore1 0xc50 +#define rOFDM0_XAAGCCore2 0xc54 +#define rOFDM0_XBAGCCore1 0xc58 +#define rOFDM0_XBAGCCore2 0xc5c +#define rOFDM0_XCAGCCore1 0xc60 +#define rOFDM0_XCAGCCore2 0xc64 +#define rOFDM0_XDAGCCore1 0xc68 +#define rOFDM0_XDAGCCore2 0xc6c +#define rOFDM0_AGCParameter1 0xc70 +#define rOFDM0_AGCParameter2 0xc74 +#define rOFDM0_AGCRSSITable 0xc78 +#define rOFDM0_HTSTFAGC 0xc7c +#define rOFDM0_XATxIQImbalance 0xc80 +#define rOFDM0_XATxAFE 0xc84 +#define rOFDM0_XBTxIQImbalance 0xc88 +#define rOFDM0_XBTxAFE 0xc8c +#define rOFDM0_XCTxIQImbalance 0xc90 +#define rOFDM0_XCTxAFE 0xc94 +#define rOFDM0_XDTxIQImbalance 0xc98 +#define rOFDM0_XDTxAFE 0xc9c +#define rOFDM0_RxHPParameter 0xce0 +#define rOFDM0_TxPseudoNoiseWgt 0xce4 +#define rOFDM0_FrameSync 0xcf0 +#define rOFDM0_DFSReport 0xcf4 +#define rOFDM0_TxCoeff1 0xca4 +#define rOFDM0_TxCoeff2 0xca8 +#define rOFDM0_TxCoeff3 0xcac +#define rOFDM0_TxCoeff4 0xcb0 +#define rOFDM0_TxCoeff5 0xcb4 +#define rOFDM0_TxCoeff6 0xcb8 + + +//page d +#define rOFDM1_LSTF 0xd00 +#define rOFDM1_TRxPathEnable 0xd04 +#define rOFDM1_CFO 0xd08 +#define rOFDM1_CSI1 0xd10 +#define rOFDM1_SBD 0xd14 +#define rOFDM1_CSI2 0xd18 +#define rOFDM1_CFOTracking 0xd2c +#define rOFDM1_TRxMesaure1 0xd34 +#define rOFDM1_IntfDet 0xd3c +#define rOFDM1_PseudoNoiseStateAB 0xd50 +#define rOFDM1_PseudoNoiseStateCD 0xd54 +#define rOFDM1_RxPseudoNoiseWgt 0xd58 +#define rOFDM_PHYCounter1 0xda0 //cca, parity fail +#define rOFDM_PHYCounter2 0xda4 //rate illegal, crc8 fail +#define rOFDM_PHYCounter3 0xda8 //MCS not support +#define rOFDM_ShortCFOAB 0xdac +#define rOFDM_ShortCFOCD 0xdb0 +#define rOFDM_LongCFOAB 0xdb4 +#define rOFDM_LongCFOCD 0xdb8 +#define rOFDM_TailCFOAB 0xdbc +#define rOFDM_TailCFOCD 0xdc0 +#define rOFDM_PWMeasure1 0xdc4 +#define rOFDM_PWMeasure2 0xdc8 +#define rOFDM_BWReport 0xdcc +#define rOFDM_AGCReport 0xdd0 +#define rOFDM_RxSNR 0xdd4 +#define rOFDM_RxEVMCSI 0xdd8 +#define rOFDM_SIGReport 0xddc + +//page e +#define rTxAGC_Rate18_06 0xe00 +#define rTxAGC_Rate54_24 0xe04 +#define rTxAGC_CCK_Mcs32 0xe08 +#define rTxAGC_Mcs03_Mcs00 0xe10 +#define rTxAGC_Mcs07_Mcs04 0xe14 +#define rTxAGC_Mcs11_Mcs08 0xe18 +#define rTxAGC_Mcs15_Mcs12 0xe1c + + +//RF +//Zebra1 +#define rZebra1_HSSIEnable 0x0 +#define rZebra1_TRxEnable1 0x1 +#define rZebra1_TRxEnable2 0x2 +#define rZebra1_AGC 0x4 +#define rZebra1_ChargePump 0x5 +#define rZebra1_Channel 0x7 +#define rZebra1_TxGain 0x8 +#define rZebra1_TxLPF 0x9 +#define rZebra1_RxLPF 0xb +#define rZebra1_RxHPFCorner 0xc + +//Zebra4 +#define rGlobalCtrl 0 +#define rRTL8256_TxLPF 19 +#define rRTL8256_RxLPF 11 + +//RTL8258 +#define rRTL8258_TxLPF 0x11 +#define rRTL8258_RxLPF 0x13 +#define rRTL8258_RSSILPF 0xa + +//Bit Mask +//page-1 +#define bBBResetB 0x100 +#define bGlobalResetB 0x200 +#define bOFDMTxStart 0x4 +#define bCCKTxStart 0x8 +#define bCRC32Debug 0x100 +#define bPMACLoopback 0x10 +#define bTxLSIG 0xffffff +#define bOFDMTxRate 0xf +#define bOFDMTxReserved 0x10 +#define bOFDMTxLength 0x1ffe0 +#define bOFDMTxParity 0x20000 +#define bTxHTSIG1 0xffffff +#define bTxHTMCSRate 0x7f +#define bTxHTBW 0x80 +#define bTxHTLength 0xffff00 +#define bTxHTSIG2 0xffffff +#define bTxHTSmoothing 0x1 +#define bTxHTSounding 0x2 +#define bTxHTReserved 0x4 +#define bTxHTAggreation 0x8 +#define bTxHTSTBC 0x30 +#define bTxHTAdvanceCoding 0x40 +#define bTxHTShortGI 0x80 +#define bTxHTNumberHT_LTF 0x300 +#define bTxHTCRC8 0x3fc00 +#define bCounterReset 0x10000 +#define bNumOfOFDMTx 0xffff +#define bNumOfCCKTx 0xffff0000 +#define bTxIdleInterval 0xffff +#define bOFDMService 0xffff0000 +#define bTxMACHeader 0xffffffff +#define bTxDataInit 0xff +#define bTxHTMode 0x100 +#define bTxDataType 0x30000 +#define bTxRandomSeed 0xffffffff +#define bCCKTxPreamble 0x1 +#define bCCKTxSFD 0xffff0000 +#define bCCKTxSIG 0xff +#define bCCKTxService 0xff00 +#define bCCKLengthExt 0x8000 +#define bCCKTxLength 0xffff0000 +#define bCCKTxCRC16 0xffff +#define bCCKTxStatus 0x1 +#define bOFDMTxStatus 0x2 + +//page-8 +#define bRFMOD 0x1 +#define bJapanMode 0x2 +#define bCCKTxSC 0x30 +#define bCCKEn 0x1000000 +#define bOFDMEn 0x2000000 +#define bOFDMRxADCPhase 0x10000 +#define bOFDMTxDACPhase 0x40000 +#define bXATxAGC 0x3f +#define bXBTxAGC 0xf00 +#define bXCTxAGC 0xf000 +#define bXDTxAGC 0xf0000 +#define bPAStart 0xf0000000 +#define bTRStart 0x00f00000 +#define bRFStart 0x0000f000 +#define bBBStart 0x000000f0 +#define bBBCCKStart 0x0000000f +#define bPAEnd 0xf //Reg0x814 +#define bTREnd 0x0f000000 +#define bRFEnd 0x000f0000 +#define bCCAMask 0x000000f0 //T2R +#define bR2RCCAMask 0x00000f00 +#define bHSSI_R2TDelay 0xf8000000 +#define bHSSI_T2RDelay 0xf80000 +#define bContTxHSSI 0x400 //chane gain at continue Tx +#define bIGFromCCK 0x200 +#define bAGCAddress 0x3f +#define bRxHPTx 0x7000 +#define bRxHPT2R 0x38000 +#define bRxHPCCKIni 0xc0000 +#define bAGCTxCode 0xc00000 +#define bAGCRxCode 0x300000 +#define b3WireDataLength 0x800 +#define b3WireAddressLength 0x400 +#define b3WireRFPowerDown 0x1 +//#define bHWSISelect 0x8 +#define b5GPAPEPolarity 0x40000000 +#define b2GPAPEPolarity 0x80000000 +#define bRFSW_TxDefaultAnt 0x3 +#define bRFSW_TxOptionAnt 0x30 +#define bRFSW_RxDefaultAnt 0x300 +#define bRFSW_RxOptionAnt 0x3000 +#define bRFSI_3WireData 0x1 +#define bRFSI_3WireClock 0x2 +#define bRFSI_3WireLoad 0x4 +#define bRFSI_3WireRW 0x8 +#define bRFSI_3Wire 0xf //3-wire total control +#define bRFSI_RFENV 0x10 +#define bRFSI_TRSW 0x20 +#define bRFSI_TRSWB 0x40 +#define bRFSI_ANTSW 0x100 +#define bRFSI_ANTSWB 0x200 +#define bRFSI_PAPE 0x400 +#define bRFSI_PAPE5G 0x800 +#define bBandSelect 0x1 +#define bHTSIG2_GI 0x80 +#define bHTSIG2_Smoothing 0x01 +#define bHTSIG2_Sounding 0x02 +#define bHTSIG2_Aggreaton 0x08 +#define bHTSIG2_STBC 0x30 +#define bHTSIG2_AdvCoding 0x40 +#define bHTSIG2_NumOfHTLTF 0x300 +#define bHTSIG2_CRC8 0x3fc +#define bHTSIG1_MCS 0x7f +#define bHTSIG1_BandWidth 0x80 +#define bHTSIG1_HTLength 0xffff +#define bLSIG_Rate 0xf +#define bLSIG_Reserved 0x10 +#define bLSIG_Length 0x1fffe +#define bLSIG_Parity 0x20 +#define bCCKRxPhase 0x4 +#define bLSSIReadAddress 0x3f000000 //LSSI "Read" Address +#define bLSSIReadEdge 0x80000000 //LSSI "Read" edge signal +#define bLSSIReadBackData 0xfff +#define bLSSIReadOKFlag 0x1000 +#define bCCKSampleRate 0x8 //0: 44MHz, 1:88MHz + +#define bRegulator0Standby 0x1 +#define bRegulatorPLLStandby 0x2 +#define bRegulator1Standby 0x4 +#define bPLLPowerUp 0x8 +#define bDPLLPowerUp 0x10 +#define bDA10PowerUp 0x20 +#define bAD7PowerUp 0x200 +#define bDA6PowerUp 0x2000 +#define bXtalPowerUp 0x4000 +#define b40MDClkPowerUP 0x8000 +#define bDA6DebugMode 0x20000 +#define bDA6Swing 0x380000 +#define bADClkPhase 0x4000000 +#define b80MClkDelay 0x18000000 +#define bAFEWatchDogEnable 0x20000000 +#define bXtalCap 0x0f000000 +#define bIntDifClkEnable 0x400 +#define bExtSigClkEnable 0x800 +#define bBandgapMbiasPowerUp 0x10000 +#define bAD11SHGain 0xc0000 +#define bAD11InputRange 0x700000 +#define bAD11OPCurrent 0x3800000 +#define bIPathLoopback 0x4000000 +#define bQPathLoopback 0x8000000 +#define bAFELoopback 0x10000000 +#define bDA10Swing 0x7e0 +#define bDA10Reverse 0x800 +#define bDAClkSource 0x1000 +#define bAD7InputRange 0x6000 +#define bAD7Gain 0x38000 +#define bAD7OutputCMMode 0x40000 +#define bAD7InputCMMode 0x380000 +#define bAD7Current 0xc00000 +#define bRegulatorAdjust 0x7000000 +#define bAD11PowerUpAtTx 0x1 +#define bDA10PSAtTx 0x10 +#define bAD11PowerUpAtRx 0x100 +#define bDA10PSAtRx 0x1000 + +#define bCCKRxAGCFormat 0x200 + +#define bPSDFFTSamplepPoint 0xc000 +#define bPSDAverageNum 0x3000 +#define bIQPathControl 0xc00 +#define bPSDFreq 0x3ff +#define bPSDAntennaPath 0x30 +#define bPSDIQSwitch 0x40 +#define bPSDRxTrigger 0x400000 +#define bPSDTxTrigger 0x80000000 +#define bPSDSineToneScale 0x7f000000 +#define bPSDReport 0xffff + +//page-9 +#define bOFDMTxSC 0x30000000 +#define bCCKTxOn 0x1 +#define bOFDMTxOn 0x2 +#define bDebugPage 0xfff //reset debug page and also HWord, LWord +#define bDebugItem 0xff //reset debug page and LWord +#define bAntL 0x10 +#define bAntNonHT 0x100 +#define bAntHT1 0x1000 +#define bAntHT2 0x10000 +#define bAntHT1S1 0x100000 +#define bAntNonHTS1 0x1000000 + +//page-a +#define bCCKBBMode 0x3 +#define bCCKTxPowerSaving 0x80 +#define bCCKRxPowerSaving 0x40 +#define bCCKSideBand 0x10 +#define bCCKScramble 0x8 +#define bCCKAntDiversity 0x8000 +#define bCCKCarrierRecovery 0x4000 +#define bCCKTxRate 0x3000 +#define bCCKDCCancel 0x0800 +#define bCCKISICancel 0x0400 +#define bCCKMatchFilter 0x0200 +#define bCCKEqualizer 0x0100 +#define bCCKPreambleDetect 0x800000 +#define bCCKFastFalseCCA 0x400000 +#define bCCKChEstStart 0x300000 +#define bCCKCCACount 0x080000 +#define bCCKcs_lim 0x070000 +#define bCCKBistMode 0x80000000 +#define bCCKCCAMask 0x40000000 +#define bCCKTxDACPhase 0x4 +#define bCCKRxADCPhase 0x20000000 //r_rx_clk +#define bCCKr_cp_mode0 0x0100 +#define bCCKTxDCOffset 0xf0 +#define bCCKRxDCOffset 0xf +#define bCCKCCAMode 0xc000 +#define bCCKFalseCS_lim 0x3f00 +#define bCCKCS_ratio 0xc00000 +#define bCCKCorgBit_sel 0x300000 +#define bCCKPD_lim 0x0f0000 +#define bCCKNewCCA 0x80000000 +#define bCCKRxHPofIG 0x8000 +#define bCCKRxIG 0x7f00 +#define bCCKLNAPolarity 0x800000 +#define bCCKRx1stGain 0x7f0000 +#define bCCKRFExtend 0x20000000 //CCK Rx Iinital gain polarity +#define bCCKRxAGCSatLevel 0x1f000000 +#define bCCKRxAGCSatCount 0xe0 +#define bCCKRxRFSettle 0x1f //AGCsamp_dly +#define bCCKFixedRxAGC 0x8000 +//#define bCCKRxAGCFormat 0x4000 //remove to HSSI register 0x824 +#define bCCKAntennaPolarity 0x2000 +#define bCCKTxFilterType 0x0c00 +#define bCCKRxAGCReportType 0x0300 +#define bCCKRxDAGCEn 0x80000000 +#define bCCKRxDAGCPeriod 0x20000000 +#define bCCKRxDAGCSatLevel 0x1f000000 +#define bCCKTimingRecovery 0x800000 +#define bCCKTxC0 0x3f0000 +#define bCCKTxC1 0x3f000000 +#define bCCKTxC2 0x3f +#define bCCKTxC3 0x3f00 +#define bCCKTxC4 0x3f0000 +#define bCCKTxC5 0x3f000000 +#define bCCKTxC6 0x3f +#define bCCKTxC7 0x3f00 +#define bCCKDebugPort 0xff0000 +#define bCCKDACDebug 0x0f000000 +#define bCCKFalseAlarmEnable 0x8000 +#define bCCKFalseAlarmRead 0x4000 +#define bCCKTRSSI 0x7f +#define bCCKRxAGCReport 0xfe +#define bCCKRxReport_AntSel 0x80000000 +#define bCCKRxReport_MFOff 0x40000000 +#define bCCKRxRxReport_SQLoss 0x20000000 +#define bCCKRxReport_Pktloss 0x10000000 +#define bCCKRxReport_Lockedbit 0x08000000 +#define bCCKRxReport_RateError 0x04000000 +#define bCCKRxReport_RxRate 0x03000000 +#define bCCKRxFACounterLower 0xff +#define bCCKRxFACounterUpper 0xff000000 +#define bCCKRxHPAGCStart 0xe000 +#define bCCKRxHPAGCFinal 0x1c00 + +#define bCCKRxFalseAlarmEnable 0x8000 +#define bCCKFACounterFreeze 0x4000 + +#define bCCKTxPathSel 0x10000000 +#define bCCKDefaultRxPath 0xc000000 +#define bCCKOptionRxPath 0x3000000 + +//page c +#define bNumOfSTF 0x3 +#define bShift_L 0xc0 +#define bGI_TH 0xc +#define bRxPathA 0x1 +#define bRxPathB 0x2 +#define bRxPathC 0x4 +#define bRxPathD 0x8 +#define bTxPathA 0x1 +#define bTxPathB 0x2 +#define bTxPathC 0x4 +#define bTxPathD 0x8 +#define bTRSSIFreq 0x200 +#define bADCBackoff 0x3000 +#define bDFIRBackoff 0xc000 +#define bTRSSILatchPhase 0x10000 +#define bRxIDCOffset 0xff +#define bRxQDCOffset 0xff00 +#define bRxDFIRMode 0x1800000 +#define bRxDCNFType 0xe000000 +#define bRXIQImb_A 0x3ff +#define bRXIQImb_B 0xfc00 +#define bRXIQImb_C 0x3f0000 +#define bRXIQImb_D 0xffc00000 +#define bDC_dc_Notch 0x60000 +#define bRxNBINotch 0x1f000000 +#define bPD_TH 0xf +#define bPD_TH_Opt2 0xc000 +#define bPWED_TH 0x700 +#define bIfMF_Win_L 0x800 +#define bPD_Option 0x1000 +#define bMF_Win_L 0xe000 +#define bBW_Search_L 0x30000 +#define bwin_enh_L 0xc0000 +#define bBW_TH 0x700000 +#define bED_TH2 0x3800000 +#define bBW_option 0x4000000 +#define bRatio_TH 0x18000000 +#define bWindow_L 0xe0000000 +#define bSBD_Option 0x1 +#define bFrame_TH 0x1c +#define bFS_Option 0x60 +#define bDC_Slope_check 0x80 +#define bFGuard_Counter_DC_L 0xe00 +#define bFrame_Weight_Short 0x7000 +#define bSub_Tune 0xe00000 +#define bFrame_DC_Length 0xe000000 +#define bSBD_start_offset 0x30000000 +#define bFrame_TH_2 0x7 +#define bFrame_GI2_TH 0x38 +#define bGI2_Sync_en 0x40 +#define bSarch_Short_Early 0x300 +#define bSarch_Short_Late 0xc00 +#define bSarch_GI2_Late 0x70000 +#define bCFOAntSum 0x1 +#define bCFOAcc 0x2 +#define bCFOStartOffset 0xc +#define bCFOLookBack 0x70 +#define bCFOSumWeight 0x80 +#define bDAGCEnable 0x10000 +#define bTXIQImb_A 0x3ff +#define bTXIQImb_B 0xfc00 +#define bTXIQImb_C 0x3f0000 +#define bTXIQImb_D 0xffc00000 +#define bTxIDCOffset 0xff +#define bTxQDCOffset 0xff00 +#define bTxDFIRMode 0x10000 +#define bTxPesudoNoiseOn 0x4000000 +#define bTxPesudoNoise_A 0xff +#define bTxPesudoNoise_B 0xff00 +#define bTxPesudoNoise_C 0xff0000 +#define bTxPesudoNoise_D 0xff000000 +#define bCCADropOption 0x20000 +#define bCCADropThres 0xfff00000 +#define bEDCCA_H 0xf +#define bEDCCA_L 0xf0 +#define bLambda_ED 0x300 +#define bRxInitialGain 0x7f +#define bRxAntDivEn 0x80 +#define bRxAGCAddressForLNA 0x7f00 +#define bRxHighPowerFlow 0x8000 +#define bRxAGCFreezeThres 0xc0000 +#define bRxFreezeStep_AGC1 0x300000 +#define bRxFreezeStep_AGC2 0xc00000 +#define bRxFreezeStep_AGC3 0x3000000 +#define bRxFreezeStep_AGC0 0xc000000 +#define bRxRssi_Cmp_En 0x10000000 +#define bRxQuickAGCEn 0x20000000 +#define bRxAGCFreezeThresMode 0x40000000 +#define bRxOverFlowCheckType 0x80000000 +#define bRxAGCShift 0x7f +#define bTRSW_Tri_Only 0x80 +#define bPowerThres 0x300 +#define bRxAGCEn 0x1 +#define bRxAGCTogetherEn 0x2 +#define bRxAGCMin 0x4 +#define bRxHP_Ini 0x7 +#define bRxHP_TRLNA 0x70 +#define bRxHP_RSSI 0x700 +#define bRxHP_BBP1 0x7000 +#define bRxHP_BBP2 0x70000 +#define bRxHP_BBP3 0x700000 +#define bRSSI_H 0x7f0000 //the threshold for high power +#define bRSSI_Gen 0x7f000000 //the threshold for ant diversity +#define bRxSettle_TRSW 0x7 +#define bRxSettle_LNA 0x38 +#define bRxSettle_RSSI 0x1c0 +#define bRxSettle_BBP 0xe00 +#define bRxSettle_RxHP 0x7000 +#define bRxSettle_AntSW_RSSI 0x38000 +#define bRxSettle_AntSW 0xc0000 +#define bRxProcessTime_DAGC 0x300000 +#define bRxSettle_HSSI 0x400000 +#define bRxProcessTime_BBPPW 0x800000 +#define bRxAntennaPowerShift 0x3000000 +#define bRSSITableSelect 0xc000000 +#define bRxHP_Final 0x7000000 +#define bRxHTSettle_BBP 0x7 +#define bRxHTSettle_HSSI 0x8 +#define bRxHTSettle_RxHP 0x70 +#define bRxHTSettle_BBPPW 0x80 +#define bRxHTSettle_Idle 0x300 +#define bRxHTSettle_Reserved 0x1c00 +#define bRxHTRxHPEn 0x8000 +#define bRxHTAGCFreezeThres 0x30000 +#define bRxHTAGCTogetherEn 0x40000 +#define bRxHTAGCMin 0x80000 +#define bRxHTAGCEn 0x100000 +#define bRxHTDAGCEn 0x200000 +#define bRxHTRxHP_BBP 0x1c00000 +#define bRxHTRxHP_Final 0xe0000000 +#define bRxPWRatioTH 0x3 +#define bRxPWRatioEn 0x4 +#define bRxMFHold 0x3800 +#define bRxPD_Delay_TH1 0x38 +#define bRxPD_Delay_TH2 0x1c0 +#define bRxPD_DC_COUNT_MAX 0x600 +//#define bRxMF_Hold 0x3800 +#define bRxPD_Delay_TH 0x8000 +#define bRxProcess_Delay 0xf0000 +#define bRxSearchrange_GI2_Early 0x700000 +#define bRxFrame_Guard_Counter_L 0x3800000 +#define bRxSGI_Guard_L 0xc000000 +#define bRxSGI_Search_L 0x30000000 +#define bRxSGI_TH 0xc0000000 +#define bDFSCnt0 0xff +#define bDFSCnt1 0xff00 +#define bDFSFlag 0xf0000 + +#define bMFWeightSum 0x300000 +#define bMinIdxTH 0x7f000000 + +#define bDAFormat 0x40000 + +#define bTxChEmuEnable 0x01000000 + +#define bTRSWIsolation_A 0x7f +#define bTRSWIsolation_B 0x7f00 +#define bTRSWIsolation_C 0x7f0000 +#define bTRSWIsolation_D 0x7f000000 + +#define bExtLNAGain 0x7c00 + +//page d +#define bSTBCEn 0x4 +#define bAntennaMapping 0x10 +#define bNss 0x20 +#define bCFOAntSumD 0x200 +#define bPHYCounterReset 0x8000000 +#define bCFOReportGet 0x4000000 +#define bOFDMContinueTx 0x10000000 +#define bOFDMSingleCarrier 0x20000000 +#define bOFDMSingleTone 0x40000000 +//#define bRxPath1 0x01 +//#define bRxPath2 0x02 +//#define bRxPath3 0x04 +//#define bRxPath4 0x08 +//#define bTxPath1 0x10 +//#define bTxPath2 0x20 +#define bHTDetect 0x100 +#define bCFOEn 0x10000 +#define bCFOValue 0xfff00000 +#define bSigTone_Re 0x3f +#define bSigTone_Im 0x7f00 +#define bCounter_CCA 0xffff +#define bCounter_ParityFail 0xffff0000 +#define bCounter_RateIllegal 0xffff +#define bCounter_CRC8Fail 0xffff0000 +#define bCounter_MCSNoSupport 0xffff +#define bCounter_FastSync 0xffff +#define bShortCFO 0xfff +#define bShortCFOTLength 12 //total +#define bShortCFOFLength 11 //fraction +#define bLongCFO 0x7ff +#define bLongCFOTLength 11 +#define bLongCFOFLength 11 +#define bTailCFO 0x1fff +#define bTailCFOTLength 13 +#define bTailCFOFLength 12 + +#define bmax_en_pwdB 0xffff +#define bCC_power_dB 0xffff0000 +#define bnoise_pwdB 0xffff +#define bPowerMeasTLength 10 +#define bPowerMeasFLength 3 +#define bRx_HT_BW 0x1 +#define bRxSC 0x6 +#define bRx_HT 0x8 + +#define bNB_intf_det_on 0x1 +#define bIntf_win_len_cfg 0x30 +#define bNB_Intf_TH_cfg 0x1c0 + +#define bRFGain 0x3f +#define bTableSel 0x40 +#define bTRSW 0x80 + +#define bRxSNR_A 0xff +#define bRxSNR_B 0xff00 +#define bRxSNR_C 0xff0000 +#define bRxSNR_D 0xff000000 +#define bSNREVMTLength 8 +#define bSNREVMFLength 1 + +#define bCSI1st 0xff +#define bCSI2nd 0xff00 +#define bRxEVM1st 0xff0000 +#define bRxEVM2nd 0xff000000 + +#define bSIGEVM 0xff +#define bPWDB 0xff00 +#define bSGIEN 0x10000 + +#define bSFactorQAM1 0xf +#define bSFactorQAM2 0xf0 +#define bSFactorQAM3 0xf00 +#define bSFactorQAM4 0xf000 +#define bSFactorQAM5 0xf0000 +#define bSFactorQAM6 0xf0000 +#define bSFactorQAM7 0xf00000 +#define bSFactorQAM8 0xf000000 +#define bSFactorQAM9 0xf0000000 +#define bCSIScheme 0x100000 + +#define bNoiseLvlTopSet 0x3 +#define bChSmooth 0x4 +#define bChSmoothCfg1 0x38 +#define bChSmoothCfg2 0x1c0 +#define bChSmoothCfg3 0xe00 +#define bChSmoothCfg4 0x7000 +#define bMRCMode 0x800000 +#define bTHEVMCfg 0x7000000 + +#define bLoopFitType 0x1 +#define bUpdCFO 0x40 +#define bUpdCFOOffData 0x80 +#define bAdvUpdCFO 0x100 +#define bAdvTimeCtrl 0x800 +#define bUpdClko 0x1000 +#define bFC 0x6000 +#define bTrackingMode 0x8000 +#define bPhCmpEnable 0x10000 +#define bUpdClkoLTF 0x20000 +#define bComChCFO 0x40000 +#define bCSIEstiMode 0x80000 +#define bAdvUpdEqz 0x100000 +#define bUChCfg 0x7000000 +#define bUpdEqz 0x8000000 + +//page e +#define bTxAGCRate18_06 0x7f7f7f7f +#define bTxAGCRate54_24 0x7f7f7f7f +#define bTxAGCRateMCS32 0x7f +#define bTxAGCRateCCK 0x7f00 +#define bTxAGCRateMCS3_MCS0 0x7f7f7f7f +#define bTxAGCRateMCS7_MCS4 0x7f7f7f7f +#define bTxAGCRateMCS11_MCS8 0x7f7f7f7f +#define bTxAGCRateMCS15_MCS12 0x7f7f7f7f + + +//Rx Pseduo noise +#define bRxPesudoNoiseOn 0x20000000 +#define bRxPesudoNoise_A 0xff +#define bRxPesudoNoise_B 0xff00 +#define bRxPesudoNoise_C 0xff0000 +#define bRxPesudoNoise_D 0xff000000 +#define bPesudoNoiseState_A 0xffff +#define bPesudoNoiseState_B 0xffff0000 +#define bPesudoNoiseState_C 0xffff +#define bPesudoNoiseState_D 0xffff0000 + +//RF +//Zebra1 +#define bZebra1_HSSIEnable 0x8 +#define bZebra1_TRxControl 0xc00 +#define bZebra1_TRxGainSetting 0x07f +#define bZebra1_RxCorner 0xc00 +#define bZebra1_TxChargePump 0x38 +#define bZebra1_RxChargePump 0x7 +#define bZebra1_ChannelNum 0xf80 +#define bZebra1_TxLPFBW 0x400 +#define bZebra1_RxLPFBW 0x600 + +//Zebra4 +#define bRTL8256RegModeCtrl1 0x100 +#define bRTL8256RegModeCtrl0 0x40 +#define bRTL8256_TxLPFBW 0x18 +#define bRTL8256_RxLPFBW 0x600 + +//RTL8258 +#define bRTL8258_TxLPFBW 0xc +#define bRTL8258_RxLPFBW 0xc00 +#define bRTL8258_RSSILPFBW 0xc0 + +//byte endable for sb_write +#define bByte0 0x1 +#define bByte1 0x2 +#define bByte2 0x4 +#define bByte3 0x8 +#define bWord0 0x3 +#define bWord1 0xc +#define bDWord 0xf + +//for PutRegsetting & GetRegSetting BitMask +#define bMaskByte0 0xff +#define bMaskByte1 0xff00 +#define bMaskByte2 0xff0000 +#define bMaskByte3 0xff000000 +#define bMaskHWord 0xffff0000 +#define bMaskLWord 0x0000ffff +#define bMaskDWord 0xffffffff + +//for PutRFRegsetting & GetRFRegSetting BitMask +#define bMask12Bits 0xfff + +#define bEnable 0x1 +#define bDisable 0x0 + +#define LeftAntenna 0x0 +#define RightAntenna 0x1 + +#define tCheckTxStatus 500 //500ms +#define tUpdateRxCounter 100 //100ms + +#define rateCCK 0 +#define rateOFDM 1 +#define rateHT 2 + +//define Register-End +#define bPMAC_End 0x1ff +#define bFPGAPHY0_End 0x8ff +#define bFPGAPHY1_End 0x9ff +#define bCCKPHY0_End 0xaff +#define bOFDMPHY0_End 0xcff +#define bOFDMPHY1_End 0xdff + +//define max debug item in each debug page +//#define bMaxItem_FPGA_PHY0 0x9 +//#define bMaxItem_FPGA_PHY1 0x3 +//#define bMaxItem_PHY_11B 0x16 +//#define bMaxItem_OFDM_PHY0 0x29 +//#define bMaxItem_OFDM_PHY1 0x0 + +#define bPMACControl 0x0 +#define bWMACControl 0x1 +#define bWNICControl 0x2 + +#define PathA 0x0 +#define PathB 0x1 +#define PathC 0x2 +#define PathD 0x3 + +#define rRTL8256RxMixerPole 0xb +#define bZebraRxMixerPole 0x6 +#define rRTL8256TxBBOPBias 0x9 +#define bRTL8256TxBBOPBias 0x400 +#define rRTL8256TxBBBW 19 +#define bRTL8256TxBBBW 0x18 + +#endif //__INC_HAL8190PCIPHYREG_H diff --git a/drivers/staging/samsung-laptop/Kconfig b/drivers/staging/samsung-laptop/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..f27c60864c26aae20a5eb4bcbc2c5c10e192a6a2 --- /dev/null +++ b/drivers/staging/samsung-laptop/Kconfig @@ -0,0 +1,10 @@ +config SAMSUNG_LAPTOP + tristate "Samsung Laptop driver" + default n + depends on RFKILL && BACKLIGHT_CLASS_DEVICE && X86 + help + This module implements a driver for the N128 Samsung Laptop + providing control over the Wireless LED and the LCD backlight + + To compile this driver as a module, choose + M here: the module will be called samsung-laptop. diff --git a/drivers/staging/samsung-laptop/Makefile b/drivers/staging/samsung-laptop/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3c6f42045211bed24ba086ee2fee297164e080f1 --- /dev/null +++ b/drivers/staging/samsung-laptop/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o diff --git a/drivers/staging/samsung-laptop/TODO b/drivers/staging/samsung-laptop/TODO new file mode 100644 index 0000000000000000000000000000000000000000..f7a6d589916e1db87a38ea328562825608ecb621 --- /dev/null +++ b/drivers/staging/samsung-laptop/TODO @@ -0,0 +1,5 @@ +TODO: + - review from other developers + - figure out ACPI video issues + +Please send patches to Greg Kroah-Hartman diff --git a/drivers/staging/samsung-laptop/samsung-laptop.c b/drivers/staging/samsung-laptop/samsung-laptop.c new file mode 100644 index 0000000000000000000000000000000000000000..4877138a9f96bb8756de408f9f55ae94be8fac4a --- /dev/null +++ b/drivers/staging/samsung-laptop/samsung-laptop.c @@ -0,0 +1,542 @@ +/* + * Samsung N130 Laptop driver + * + * Copyright (C) 2009 Greg Kroah-Hartman (gregkh@suse.de) + * Copyright (C) 2009 Novell Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This driver is needed because a number of Samsung laptops do not hook + * their control settings through ACPI. So we have to poke around in the + * BIOS to do things like brightness values, and "special" key controls. + */ + +/* + * We have 0 - 8 as valid brightness levels. The specs say that level 0 should + * be reserved by the BIOS (which really doesn't make much sense), we tell + * userspace that the value is 0 - 7 and then just tell the hardware 1 - 8 + */ +#define MAX_BRIGHT 0x07 + +/* Brightness is 0 - 8, as described above. Value 0 is for the BIOS to use */ +#define GET_BRIGHTNESS 0x00 +#define SET_BRIGHTNESS 0x01 + +/* first byte: + * 0x00 - wireless is off + * 0x01 - wireless is on + * second byte: + * 0x02 - 3G is off + * 0x03 - 3G is on + * TODO, verify 3G is correct, that doesn't seem right... + */ +#define GET_WIRELESS_BUTTON 0x02 +#define SET_WIRELESS_BUTTON 0x03 + +/* 0 is off, 1 is on */ +#define GET_BACKLIGHT 0x04 +#define SET_BACKLIGHT 0x05 + +/* + * 0x80 or 0x00 - no action + * 0x81 - recovery key pressed + */ +#define GET_RECOVERY_METHOD 0x06 +#define SET_RECOVERY_METHOD 0x07 + +/* 0 is low, 1 is high */ +#define GET_PERFORMANCE_LEVEL 0x08 +#define SET_PERFORMANCE_LEVEL 0x09 + +/* + * Tell the BIOS that Linux is running on this machine. + * 81 is on, 80 is off + */ +#define SET_LINUX 0x0a + + +#define MAIN_FUNCTION 0x4c49 + +#define SABI_HEADER_PORT 0x00 +#define SABI_HEADER_RE_MEM 0x02 +#define SABI_HEADER_IFACEFUNC 0x03 +#define SABI_HEADER_EN_MEM 0x04 +#define SABI_HEADER_DATA_OFFSET 0x05 +#define SABI_HEADER_DATA_SEGMENT 0x07 + +#define SABI_IFACE_MAIN 0x00 +#define SABI_IFACE_SUB 0x02 +#define SABI_IFACE_COMPLETE 0x04 +#define SABI_IFACE_DATA 0x05 + +/* Structure to get data back to the calling function */ +struct sabi_retval { + u8 retval[20]; +}; + +static void __iomem *sabi; +static void __iomem *sabi_iface; +static void __iomem *f0000_segment; +static struct backlight_device *backlight_device; +static struct mutex sabi_mutex; +static struct platform_device *sdev; +static struct rfkill *rfk; + +static int force; +module_param(force, bool, 0); +MODULE_PARM_DESC(force, "Disable the DMI check and forces the driver to be loaded"); + +static int debug; +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); + +static int sabi_get_command(u8 command, struct sabi_retval *sretval) +{ + int retval = 0; + u16 port = readw(sabi + SABI_HEADER_PORT); + + mutex_lock(&sabi_mutex); + + /* enable memory to be able to write to it */ + outb(readb(sabi + SABI_HEADER_EN_MEM), port); + + /* write out the command */ + writew(MAIN_FUNCTION, sabi_iface + SABI_IFACE_MAIN); + writew(command, sabi_iface + SABI_IFACE_SUB); + writeb(0, sabi_iface + SABI_IFACE_COMPLETE); + outb(readb(sabi + SABI_HEADER_IFACEFUNC), port); + + /* write protect memory to make it safe */ + outb(readb(sabi + SABI_HEADER_RE_MEM), port); + + /* see if the command actually succeeded */ + if (readb(sabi_iface + SABI_IFACE_COMPLETE) == 0xaa && + readb(sabi_iface + SABI_IFACE_DATA) != 0xff) { + /* + * It did! + * Save off the data into a structure so the caller use it. + * Right now we only care about the first 4 bytes, + * I suppose there are commands that need more, but I don't + * know about them. + */ + sretval->retval[0] = readb(sabi_iface + SABI_IFACE_DATA); + sretval->retval[1] = readb(sabi_iface + SABI_IFACE_DATA + 1); + sretval->retval[2] = readb(sabi_iface + SABI_IFACE_DATA + 2); + sretval->retval[3] = readb(sabi_iface + SABI_IFACE_DATA + 3); + goto exit; + } + + /* Something bad happened, so report it and error out */ + printk(KERN_WARNING "SABI command 0x%02x failed with completion flag 0x%02x and output 0x%02x\n", + command, readb(sabi_iface + SABI_IFACE_COMPLETE), + readb(sabi_iface + SABI_IFACE_DATA)); + retval = -EINVAL; +exit: + mutex_unlock(&sabi_mutex); + return retval; + +} + +static int sabi_set_command(u8 command, u8 data) +{ + int retval = 0; + u16 port = readw(sabi + SABI_HEADER_PORT); + + mutex_lock(&sabi_mutex); + + /* enable memory to be able to write to it */ + outb(readb(sabi + SABI_HEADER_EN_MEM), port); + + /* write out the command */ + writew(MAIN_FUNCTION, sabi_iface + SABI_IFACE_MAIN); + writew(command, sabi_iface + SABI_IFACE_SUB); + writeb(0, sabi_iface + SABI_IFACE_COMPLETE); + writeb(data, sabi_iface + SABI_IFACE_DATA); + outb(readb(sabi + SABI_HEADER_IFACEFUNC), port); + + /* write protect memory to make it safe */ + outb(readb(sabi + SABI_HEADER_RE_MEM), port); + + /* see if the command actually succeeded */ + if (readb(sabi_iface + SABI_IFACE_COMPLETE) == 0xaa && + readb(sabi_iface + SABI_IFACE_DATA) != 0xff) { + /* it did! */ + goto exit; + } + + /* Something bad happened, so report it and error out */ + printk(KERN_WARNING "SABI command 0x%02x failed with completion flag 0x%02x and output 0x%02x\n", + command, readb(sabi_iface + SABI_IFACE_COMPLETE), + readb(sabi_iface + SABI_IFACE_DATA)); + retval = -EINVAL; +exit: + mutex_unlock(&sabi_mutex); + return retval; +} + +static void test_backlight(void) +{ + struct sabi_retval sretval; + + sabi_get_command(GET_BACKLIGHT, &sretval); + printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]); + + sabi_set_command(SET_BACKLIGHT, 0); + printk(KERN_DEBUG "backlight should be off\n"); + + sabi_get_command(GET_BACKLIGHT, &sretval); + printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]); + + msleep(1000); + + sabi_set_command(SET_BACKLIGHT, 1); + printk(KERN_DEBUG "backlight should be on\n"); + + sabi_get_command(GET_BACKLIGHT, &sretval); + printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]); +} + +static void test_wireless(void) +{ + struct sabi_retval sretval; + + sabi_get_command(GET_WIRELESS_BUTTON, &sretval); + printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]); + + sabi_set_command(SET_WIRELESS_BUTTON, 0); + printk(KERN_DEBUG "wireless led should be off\n"); + + sabi_get_command(GET_WIRELESS_BUTTON, &sretval); + printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]); + + msleep(1000); + + sabi_set_command(SET_WIRELESS_BUTTON, 1); + printk(KERN_DEBUG "wireless led should be on\n"); + + sabi_get_command(GET_WIRELESS_BUTTON, &sretval); + printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]); +} + +static u8 read_brightness(void) +{ + struct sabi_retval sretval; + int user_brightness = 0; + int retval; + + retval = sabi_get_command(GET_BRIGHTNESS, &sretval); + if (!retval) + user_brightness = sretval.retval[0]; + if (user_brightness != 0) + --user_brightness; + return user_brightness; +} + +static void set_brightness(u8 user_brightness) +{ + sabi_set_command(SET_BRIGHTNESS, user_brightness + 1); +} + +static int get_brightness(struct backlight_device *bd) +{ + return (int)read_brightness(); +} + +static int update_status(struct backlight_device *bd) +{ + set_brightness(bd->props.brightness); + + if (bd->props.power == FB_BLANK_UNBLANK) + sabi_set_command(SET_BACKLIGHT, 1); + else + sabi_set_command(SET_BACKLIGHT, 0); + return 0; +} + +static struct backlight_ops backlight_ops = { + .get_brightness = get_brightness, + .update_status = update_status, +}; + +static int rfkill_set(void *data, bool blocked) +{ + /* Do something with blocked...*/ + /* + * blocked == false is on + * blocked == true is off + */ + if (blocked) + sabi_set_command(SET_WIRELESS_BUTTON, 0); + else + sabi_set_command(SET_WIRELESS_BUTTON, 1); + + return 0; +} + +static struct rfkill_ops rfkill_ops = { + .set_block = rfkill_set, +}; + +static int init_wireless(struct platform_device *sdev) +{ + int retval; + + rfk = rfkill_alloc("samsung-wifi", &sdev->dev, RFKILL_TYPE_WLAN, + &rfkill_ops, NULL); + if (!rfk) + return -ENOMEM; + + retval = rfkill_register(rfk); + if (retval) { + rfkill_destroy(rfk); + return -ENODEV; + } + + return 0; +} + +static void destroy_wireless(void) +{ + rfkill_unregister(rfk); + rfkill_destroy(rfk); +} + +static ssize_t get_silent_state(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct sabi_retval sretval; + int retval; + + /* Read the state */ + retval = sabi_get_command(GET_PERFORMANCE_LEVEL, &sretval); + if (retval) + return retval; + + /* The logic is backwards, yeah, lots of fun... */ + if (sretval.retval[0] == 0) + retval = 1; + else + retval = 0; + return sprintf(buf, "%d\n", retval); +} + +static ssize_t set_silent_state(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + char value; + + if (count >= 1) { + value = buf[0]; + if ((value == '0') || (value == 'n') || (value == 'N')) { + /* Turn speed up */ + sabi_set_command(SET_PERFORMANCE_LEVEL, 0x01); + } else if ((value == '1') || (value == 'y') || (value == 'Y')) { + /* Turn speed down */ + sabi_set_command(SET_PERFORMANCE_LEVEL, 0x00); + } else { + return -EINVAL; + } + } + return count; +} +static DEVICE_ATTR(silent, S_IWUGO | S_IRUGO, + get_silent_state, set_silent_state); + + +static int __init dmi_check_cb(const struct dmi_system_id *id) +{ + printk(KERN_INFO KBUILD_MODNAME ": found laptop model '%s'\n", + id->ident); + return 0; +} + +static struct dmi_system_id __initdata samsung_dmi_table[] = { + { + .ident = "N128", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "N128"), + DMI_MATCH(DMI_BOARD_NAME, "N128"), + }, + .callback = dmi_check_cb, + }, + { + .ident = "N130", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "N130"), + DMI_MATCH(DMI_BOARD_NAME, "N130"), + }, + .callback = dmi_check_cb, + }, + { }, +}; +MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); + +static int __init samsung_init(void) +{ + struct sabi_retval sretval; + const char *testStr = "SECLINUX"; + void __iomem *memcheck; + unsigned int ifaceP; + int pStr; + int loca; + int retval; + + mutex_init(&sabi_mutex); + + if (!force && !dmi_check_system(samsung_dmi_table)) + return -ENODEV; + + f0000_segment = ioremap(0xf0000, 0xffff); + if (!f0000_segment) { + printk(KERN_ERR "Can't map the segment at 0xf0000\n"); + return -EINVAL; + } + + /* Try to find the signature "SECLINUX" in memory to find the header */ + pStr = 0; + memcheck = f0000_segment; + for (loca = 0; loca < 0xffff; loca++) { + char temp = readb(memcheck + loca); + + if (temp == testStr[pStr]) { + if (pStr == strlen(testStr)-1) + break; + ++pStr; + } else { + pStr = 0; + } + } + if (loca == 0xffff) { + printk(KERN_ERR "This computer does not support SABI\n"); + goto error_no_signature; + } + + /* point to the SMI port Number */ + loca += 1; + sabi = (memcheck + loca); + + if (debug) { + printk(KERN_DEBUG "This computer supports SABI==%x\n", + loca + 0xf0000 - 6); + printk(KERN_DEBUG "SABI header:\n"); + printk(KERN_DEBUG " SMI Port Number = 0x%04x\n", + readw(sabi + SABI_HEADER_PORT)); + printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n", + readb(sabi + SABI_HEADER_IFACEFUNC)); + printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n", + readb(sabi + SABI_HEADER_EN_MEM)); + printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n", + readb(sabi + SABI_HEADER_RE_MEM)); + printk(KERN_DEBUG " SABI data offset = 0x%04x\n", + readw(sabi + SABI_HEADER_DATA_OFFSET)); + printk(KERN_DEBUG " SABI data segment = 0x%04x\n", + readw(sabi + SABI_HEADER_DATA_SEGMENT)); + } + + /* Get a pointer to the SABI Interface */ + ifaceP = (readw(sabi + SABI_HEADER_DATA_SEGMENT) & 0x0ffff) << 4; + ifaceP += readw(sabi + SABI_HEADER_DATA_OFFSET) & 0x0ffff; + sabi_iface = ioremap(ifaceP, 16); + if (!sabi_iface) { + printk(KERN_ERR "Can't remap %x\n", ifaceP); + goto exit; + } + if (debug) { + printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP); + printk(KERN_DEBUG "sabi_iface = %p\n", sabi_iface); + + test_backlight(); + test_wireless(); + + retval = sabi_get_command(GET_BRIGHTNESS, &sretval); + printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]); + } + + /* Turn on "Linux" mode in the BIOS */ + retval = sabi_set_command(SET_LINUX, 0x81); + if (retval) { + printk(KERN_ERR KBUILD_MODNAME ": Linux mode was not set!\n"); + goto error_no_platform; + } + + /* knock up a platform device to hang stuff off of */ + sdev = platform_device_register_simple("samsung", -1, NULL, 0); + if (IS_ERR(sdev)) + goto error_no_platform; + + /* create a backlight device to talk to this one */ + backlight_device = backlight_device_register("samsung", &sdev->dev, + NULL, &backlight_ops); + if (IS_ERR(backlight_device)) + goto error_no_backlight; + + backlight_device->props.max_brightness = MAX_BRIGHT; + backlight_device->props.brightness = read_brightness(); + backlight_device->props.power = FB_BLANK_UNBLANK; + backlight_update_status(backlight_device); + + retval = init_wireless(sdev); + if (retval) + goto error_no_rfk; + + retval = device_create_file(&sdev->dev, &dev_attr_silent); + if (retval) + goto error_file_create; + +exit: + return 0; + +error_file_create: + destroy_wireless(); + +error_no_rfk: + backlight_device_unregister(backlight_device); + +error_no_backlight: + platform_device_unregister(sdev); + +error_no_platform: + iounmap(sabi_iface); + +error_no_signature: + iounmap(f0000_segment); + return -EINVAL; +} + +static void __exit samsung_exit(void) +{ + /* Turn off "Linux" mode in the BIOS */ + sabi_set_command(SET_LINUX, 0x80); + + device_remove_file(&sdev->dev, &dev_attr_silent); + backlight_device_unregister(backlight_device); + destroy_wireless(); + iounmap(sabi_iface); + iounmap(f0000_segment); + platform_device_unregister(sdev); +} + +module_init(samsung_init); +module_exit(samsung_exit); + +MODULE_AUTHOR("Greg Kroah-Hartman "); +MODULE_DESCRIPTION("Samsung Backlight driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c index f890a16096c0c628f04b8cdfa098626b0d8473c3..e7bc9ec63a8c7efecb8c9ea260a580cd6231118d 100644 --- a/drivers/staging/sep/sep_driver.c +++ b/drivers/staging/sep/sep_driver.c @@ -273,7 +273,8 @@ static dma_addr_t sep_shared_virt_to_bus(struct sep_device *sep, void *virt_address) { dma_addr_t pa = sep->shared_bus + (virt_address - sep->shared_addr); - edbg("sep: virt to bus b %08llx v %p\n", pa, virt_address); + edbg("sep: virt to bus b %08llx v %p\n", + (unsigned long long)pa, virt_address); return pa; } @@ -1788,6 +1789,7 @@ static int sep_create_flow_dma_tables_handler(struct sep_device *sep, first_table_data.physical_address = 0xffffffff; /* find the free structure for flow data */ + error = -EINVAL; flow_context_ptr = sep_find_flow_context(sep, SEP_FREE_FLOW_ID); if (flow_context_ptr == NULL) goto end_function; @@ -2447,7 +2449,7 @@ static void sep_configure_dma_burst(struct sep_device *sep) #endif /* - Function that is activaed on the succesful probe of the SEP device + Function that is activated on the successful probe of the SEP device */ static int __devinit sep_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c index 52af44cfbe83a66dd45b1b65034247362648cebe..060e9de3b065d1300cbe8dded0dd3a009e003af2 100644 --- a/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/drivers/staging/serqt_usb2/serqt_usb2.c @@ -929,7 +929,7 @@ static int qt_open(struct tty_struct *tty, dbg(__FILE__ "qt_setuart completed.\n"); /* - * Put this here to make it responsive to stty and defauls set by + * Put this here to make it responsive to stty and defaults set by * the tty layer */ /* FIXME: is this needed? */ diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index e67a130f9e46eab61d3e1d571e1dca7b7a798eb2..5b191afc144262681145c57999647d0f06954529 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -354,7 +354,6 @@ static const struct net_device_ops slic_netdev_ops = { .ndo_get_stats = slic_get_stats, .ndo_set_multicast_list = slic_mcast_set_list, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, }; diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index 6e91fc2bd850a2bf9c3e2f11f40fb935b93df873..ef4371358dbe9fe0a4bb0e837fe4acecf05a9e16 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -56,7 +56,7 @@ static void vhci_stop(struct usb_hcd *hcd); static int vhci_get_frame_number(struct usb_hcd *hcd); static const char driver_name[] = "vhci_hcd"; -static const char driver_desc[] = "USB/IP Virtual Host Contoroller"; +static const char driver_desc[] = "USB/IP Virtual Host Controller"; struct vhci_hcd *the_controller; diff --git a/drivers/staging/vme/TODO b/drivers/staging/vme/TODO index adc5fca42afd64b3c9ccd54d5e392e8c3e2f02b1..2201ff6f74d1ef4ae811eefc8965457725e1643e 100644 --- a/drivers/staging/vme/TODO +++ b/drivers/staging/vme/TODO @@ -11,7 +11,7 @@ The current DMA resource Allocation provides no means of selecting the suitability of a DMA controller based on it's supported modes of operation, as opposed to the resource allocation mechanisms for master and slave windows: - struct vme_resource *vme_request_dma(struct device *dev); + struct vme_resource *vme_dma_request(struct device *dev); As opposed to: diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c index e139eaeaa174f6158ee82aecd302bbddb8ab5d6f..1cf3e91db59de3455d22717a379116df841eb1ac 100644 --- a/drivers/staging/vme/bridges/vme_ca91cx42.c +++ b/drivers/staging/vme/bridges/vme_ca91cx42.c @@ -15,7 +15,6 @@ * option) any later version. */ -#include #include #include #include @@ -54,9 +53,6 @@ struct mutex vme_int; /* * Only one VME interrupt can be * generated at a time, provide locking */ -struct mutex vme_irq; /* Locking for VME irq callback configuration */ - - static char driver_name[] = "vme_ca91cx42"; @@ -158,23 +154,13 @@ static u32 ca91cx42_LERR_irqhandler(void) static u32 ca91cx42_VIRQ_irqhandler(int stat) { int vec, i, serviced = 0; - void (*call)(int, int, void *); - void *priv_data; for (i = 7; i > 0; i--) { if (stat & (1 << i)) { vec = ioread32(ca91cx42_bridge->base + CA91CX42_V_STATID[i]) & 0xff; - call = ca91cx42_bridge->irq[i - 1].callback[vec].func; - priv_data = - ca91cx42_bridge->irq[i - 1].callback[vec].priv_data; - - if (call != NULL) - call(i, vec, priv_data); - else - printk("Spurilous VME interrupt, level:%x, " - "vector:%x\n", i, vec); + vme_irq_handler(ca91cx42_bridge, i, vec); serviced |= (1 << i); } @@ -235,6 +221,8 @@ static int ca91cx42_irq_init(struct vme_bridge *bridge) /* Initialise list for VME bus errors */ INIT_LIST_HEAD(&(bridge->vme_errors)); + mutex_init(&(bridge->irq_mtx)); + /* Disable interrupts from PCI to VME */ iowrite32(0, bridge->base + VINT_EN); @@ -282,66 +270,31 @@ static void ca91cx42_irq_exit(struct pci_dev *pdev) /* * Set up an VME interrupt */ -int ca91cx42_request_irq(int level, int statid, - void (*callback)(int level, int vector, void *priv_data), - void *priv_data) +void ca91cx42_irq_set(int level, int state, int sync) + { + struct pci_dev *pdev; u32 tmp; - mutex_lock(&(vme_irq)); - - if (ca91cx42_bridge->irq[level - 1].callback[statid].func) { - mutex_unlock(&(vme_irq)); - printk("VME Interrupt already taken\n"); - return -EBUSY; - } - - - ca91cx42_bridge->irq[level - 1].count++; - ca91cx42_bridge->irq[level - 1].callback[statid].priv_data = priv_data; - ca91cx42_bridge->irq[level - 1].callback[statid].func = callback; - /* Enable IRQ level */ tmp = ioread32(ca91cx42_bridge->base + LINT_EN); - tmp |= CA91CX42_LINT_VIRQ[level]; - iowrite32(tmp, ca91cx42_bridge->base + LINT_EN); - - mutex_unlock(&(vme_irq)); - - return 0; -} -/* - * Free VME interrupt - */ -void ca91cx42_free_irq(int level, int statid) -{ - u32 tmp; - struct pci_dev *pdev; - - mutex_lock(&(vme_irq)); - - ca91cx42_bridge->irq[level - 1].count--; - - /* Disable IRQ level if no more interrupts attached at this level*/ - if (ca91cx42_bridge->irq[level - 1].count == 0) { - tmp = ioread32(ca91cx42_bridge->base + LINT_EN); + if (state == 0) tmp &= ~CA91CX42_LINT_VIRQ[level]; - iowrite32(tmp, ca91cx42_bridge->base + LINT_EN); + else + tmp |= CA91CX42_LINT_VIRQ[level]; + + iowrite32(tmp, ca91cx42_bridge->base + LINT_EN); + if ((state == 0) && (sync != 0)) { pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); synchronize_irq(pdev->irq); } - - ca91cx42_bridge->irq[level - 1].callback[statid].func = NULL; - ca91cx42_bridge->irq[level - 1].callback[statid].priv_data = NULL; - - mutex_unlock(&(vme_irq)); } -int ca91cx42_generate_irq(int level, int statid) +int ca91cx42_irq_generate(int level, int statid) { u32 tmp; @@ -1065,7 +1018,6 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) init_waitqueue_head(&dma_queue); init_waitqueue_head(&iack_queue); mutex_init(&(vme_int)); - mutex_init(&(vme_irq)); mutex_init(&(vme_rmw)); ca91cx42_bridge->parent = &(pdev->dev); @@ -1182,9 +1134,8 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec; ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty; #endif - ca91cx42_bridge->request_irq = ca91cx42_request_irq; - ca91cx42_bridge->free_irq = ca91cx42_free_irq; - ca91cx42_bridge->generate_irq = ca91cx42_generate_irq; + ca91cx42_bridge->irq_set = ca91cx42_irq_set; + ca91cx42_bridge->irq_generate = ca91cx42_irq_generate; #if 0 ca91cx42_bridge->lm_set = ca91cx42_lm_set; ca91cx42_bridge->lm_get = ca91cx42_lm_get; @@ -1220,7 +1171,9 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) vme_unregister_bridge(ca91cx42_bridge); err_reg: ca91cx42_crcsr_exit(pdev); +#if 0 err_crcsr: +#endif err_lm: /* resources are stored in link list */ list_for_each(pos, &(ca91cx42_bridge->lm_resources)) { @@ -1275,7 +1228,6 @@ void ca91cx42_remove(struct pci_dev *pdev) struct vme_slave_resource *slave_image; struct vme_dma_resource *dma_ctrlr; struct vme_lm_resource *lm; - int i; /* Turn off Ints */ iowrite32(0, ca91cx42_bridge->base + LINT_EN); diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c index 00fe0803c21c3e0f31243866dea1c4d7c4483f9a..89a7dccb934fc9bf1119d661aee666da179abf3c 100644 --- a/drivers/staging/vme/bridges/vme_tsi148.c +++ b/drivers/staging/vme/bridges/vme_tsi148.c @@ -13,7 +13,6 @@ * option) any later version. */ -#include #include #include #include @@ -78,8 +77,6 @@ struct mutex vme_int; /* * Only one VME interrupt can be * generated at a time, provide locking */ -struct mutex vme_irq; /* Locking for VME irq callback configuration */ - static char driver_name[] = "vme_tsi148"; @@ -240,7 +237,6 @@ static u32 tsi148_VERR_irqhandler(void) */ static u32 tsi148_IACK_irqhandler(void) { - printk("tsi148_IACK_irqhandler\n"); wake_up(&iack_queue); return TSI148_LCSR_INTC_IACKC; @@ -252,8 +248,6 @@ static u32 tsi148_IACK_irqhandler(void) static u32 tsi148_VIRQ_irqhandler(u32 stat) { int vec, i, serviced = 0; - void (*call)(int, int, void *); - void *priv_data; for (i = 7; i > 0; i--) { if (stat & (1 << i)) { @@ -266,15 +260,7 @@ static u32 tsi148_VIRQ_irqhandler(u32 stat) vec = ioread8(tsi148_bridge->base + TSI148_LCSR_VIACK[i] + 3); - call = tsi148_bridge->irq[i - 1].callback[vec].func; - priv_data = - tsi148_bridge->irq[i-1].callback[vec].priv_data; - - if (call != NULL) - call(i, vec, priv_data); - else - printk("Spurilous VME interrupt, level:%x, " - "vector:%x\n", i, vec); + vme_irq_handler(tsi148_bridge, i, vec); serviced |= (1 << i); } @@ -354,6 +340,8 @@ static int tsi148_irq_init(struct vme_bridge *bridge) /* Initialise list for VME bus errors */ INIT_LIST_HEAD(&(bridge->vme_errors)); + mutex_init(&(bridge->irq_mtx)); + result = request_irq(pdev->irq, tsi148_irqhandler, IRQF_SHARED, @@ -433,55 +421,15 @@ int tsi148_iack_received(void) } /* - * Set up an VME interrupt + * Configure VME interrupt */ -int tsi148_request_irq(int level, int statid, - void (*callback)(int level, int vector, void *priv_data), - void *priv_data) +void tsi148_irq_set(int level, int state, int sync) { - u32 tmp; - - mutex_lock(&(vme_irq)); - - if(tsi148_bridge->irq[level - 1].callback[statid].func) { - mutex_unlock(&(vme_irq)); - printk("VME Interrupt already taken\n"); - return -EBUSY; - } - - - tsi148_bridge->irq[level - 1].count++; - tsi148_bridge->irq[level - 1].callback[statid].priv_data = priv_data; - tsi148_bridge->irq[level - 1].callback[statid].func = callback; - - /* Enable IRQ level */ - tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO); - tmp |= TSI148_LCSR_INTEO_IRQEO[level - 1]; - iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO); - - tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN); - tmp |= TSI148_LCSR_INTEN_IRQEN[level - 1]; - iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN); - - mutex_unlock(&(vme_irq)); - - return 0; -} - -/* - * Free VME interrupt - */ -void tsi148_free_irq(int level, int statid) -{ - u32 tmp; struct pci_dev *pdev; + u32 tmp; - mutex_lock(&(vme_irq)); - - tsi148_bridge->irq[level - 1].count--; - - /* Disable IRQ level if no more interrupts attached at this level*/ - if (tsi148_bridge->irq[level - 1].count == 0) { + /* We need to do the ordering differently for enabling and disabling */ + if (state == 0) { tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN); tmp &= ~TSI148_LCSR_INTEN_IRQEN[level - 1]; iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN); @@ -490,22 +438,28 @@ void tsi148_free_irq(int level, int statid) tmp &= ~TSI148_LCSR_INTEO_IRQEO[level - 1]; iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO); - pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); - - synchronize_irq(pdev->irq); - } + if (sync != 0) { + pdev = container_of(tsi148_bridge->parent, + struct pci_dev, dev); - tsi148_bridge->irq[level - 1].callback[statid].func = NULL; - tsi148_bridge->irq[level - 1].callback[statid].priv_data = NULL; + synchronize_irq(pdev->irq); + } + } else { + tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO); + tmp |= TSI148_LCSR_INTEO_IRQEO[level - 1]; + iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO); - mutex_unlock(&(vme_irq)); + tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN); + tmp |= TSI148_LCSR_INTEN_IRQEN[level - 1]; + iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN); + } } /* * Generate a VME bus interrupt at the requested level & vector. Wait for * interrupt to be acked. */ -int tsi148_generate_irq(int level, int statid) +int tsi148_irq_generate(int level, int statid) { u32 tmp; @@ -891,7 +845,7 @@ static int tsi148_alloc_resource(struct vme_master_resource *image, image->pci_resource.start); /* If the existing size is OK, return */ - if (existing_size == (size - 1)) + if ((size != 0) && (existing_size == (size - 1))) return 0; if (existing_size != 0) { @@ -903,6 +857,11 @@ static int tsi148_alloc_resource(struct vme_master_resource *image, memset(&(image->pci_resource), 0, sizeof(struct resource)); } + /* Exit here if size is zero */ + if (size == 0) { + return 0; + } + if (image->pci_resource.name == NULL) { image->pci_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL); if (image->pci_resource.name == NULL) { @@ -981,12 +940,13 @@ int tsi148_master_set( struct vme_master_resource *image, int enabled, /* Verify input data */ if (vme_base & 0xFFFF) { - printk("Invalid VME Window alignment\n"); + printk(KERN_ERR "Invalid VME Window alignment\n"); retval = -EINVAL; goto err_window; } - if (size < 0x10000) { - printk("Invalid VME Window size\n"); + + if ((size == 0) && (enabled != 0)) { + printk(KERN_ERR "Size must be non-zero for enabled windows\n"); retval = -EINVAL; goto err_window; } @@ -994,26 +954,31 @@ int tsi148_master_set( struct vme_master_resource *image, int enabled, spin_lock(&(image->lock)); /* Let's allocate the resource here rather than further up the stack as - * it avoids pushing loads of bus dependant stuff up the stack + * it avoids pushing loads of bus dependant stuff up the stack. If size + * is zero, any existing resource will be freed. */ retval = tsi148_alloc_resource(image, size); if (retval) { spin_unlock(&(image->lock)); - printk(KERN_ERR "Unable to allocate memory for resource " - "name\n"); - retval = -ENOMEM; + printk(KERN_ERR "Unable to allocate memory for " + "resource\n"); goto err_res; } - pci_base = (unsigned long long)image->pci_resource.start; - + if (size == 0) { + pci_base = 0; + pci_bound = 0; + vme_offset = 0; + } else { + pci_base = (unsigned long long)image->pci_resource.start; - /* - * Bound address is a valid address for the window, adjust - * according to window granularity. - */ - pci_bound = pci_base + (size - 0x10000); - vme_offset = vme_base - pci_base; + /* + * Bound address is a valid address for the window, adjust + * according to window granularity. + */ + pci_bound = pci_base + (size - 0x10000); + vme_offset = vme_base - pci_base; + } /* Convert 64-bit variables to 2x 32-bit variables */ reg_split(pci_base, &pci_base_high, &pci_base_low); @@ -1022,19 +987,19 @@ int tsi148_master_set( struct vme_master_resource *image, int enabled, if (pci_base_low & 0xFFFF) { spin_unlock(&(image->lock)); - printk("Invalid PCI base alignment\n"); + printk(KERN_ERR "Invalid PCI base alignment\n"); retval = -EINVAL; goto err_gran; } if (pci_bound_low & 0xFFFF) { spin_unlock(&(image->lock)); - printk("Invalid PCI bound alignment\n"); + printk(KERN_ERR "Invalid PCI bound alignment\n"); retval = -EINVAL; goto err_gran; } if (vme_offset_low & 0xFFFF) { spin_unlock(&(image->lock)); - printk("Invalid VME Offset alignment\n"); + printk(KERN_ERR "Invalid VME Offset alignment\n"); retval = -EINVAL; goto err_gran; } @@ -1094,7 +1059,8 @@ int tsi148_master_set( struct vme_master_resource *image, int enabled, temp_ctl |= TSI148_LCSR_OTAT_TM_2eSST; } if (cycle & VME_2eSSTB) { - printk("Currently not setting Broadcast Select Registers\n"); + printk(KERN_WARNING "Currently not setting Broadcast Select " + "Registers\n"); temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; temp_ctl |= TSI148_LCSR_OTAT_TM_2eSSTB; } @@ -1110,7 +1076,7 @@ int tsi148_master_set( struct vme_master_resource *image, int enabled, break; default: spin_unlock(&(image->lock)); - printk("Invalid data width\n"); + printk(KERN_ERR "Invalid data width\n"); retval = -EINVAL; goto err_dwidth; } @@ -1147,7 +1113,7 @@ int tsi148_master_set( struct vme_master_resource *image, int enabled, break; default: spin_unlock(&(image->lock)); - printk("Invalid address space\n"); + printk(KERN_ERR "Invalid address space\n"); retval = -EINVAL; goto err_aspace; break; @@ -2154,7 +2120,7 @@ int tsi148_lm_detach(struct vme_lm_resource *lm, int monitor) iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO); iowrite32be(TSI148_LCSR_INTC_LMC[monitor], - tsi148_bridge->base + TSI148_LCSR_INTEO); + tsi148_bridge->base + TSI148_LCSR_INTC); /* Detach callback */ lm_callback[monitor] = NULL; @@ -2334,7 +2300,6 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) init_waitqueue_head(&dma_queue[1]); init_waitqueue_head(&iack_queue); mutex_init(&(vme_int)); - mutex_init(&(vme_irq)); mutex_init(&(vme_rmw)); tsi148_bridge->parent = &(pdev->dev); @@ -2482,9 +2447,8 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) tsi148_bridge->dma_list_add = tsi148_dma_list_add; tsi148_bridge->dma_list_exec = tsi148_dma_list_exec; tsi148_bridge->dma_list_empty = tsi148_dma_list_empty; - tsi148_bridge->request_irq = tsi148_request_irq; - tsi148_bridge->free_irq = tsi148_free_irq; - tsi148_bridge->generate_irq = tsi148_generate_irq; + tsi148_bridge->irq_set = tsi148_irq_set; + tsi148_bridge->irq_generate = tsi148_irq_generate; tsi148_bridge->lm_set = tsi148_lm_set; tsi148_bridge->lm_get = tsi148_lm_get; tsi148_bridge->lm_attach = tsi148_lm_attach; @@ -2616,13 +2580,6 @@ static void tsi148_remove(struct pci_dev *pdev) iowrite32be(0x8000, tsi148_bridge->base + TSI148_LCSR_VICR); } - /* - * Disable and clear all interrupts. - */ - iowrite32be(0x0, tsi148_bridge->base + TSI148_LCSR_INTEO); - iowrite32be(0xFFFFFFFF, tsi148_bridge->base + TSI148_LCSR_INTC); - iowrite32be(0xFFFFFFFF, tsi148_bridge->base + TSI148_LCSR_INTEN); - /* * Map all Interrupts to PCI INTA */ diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c index 78912883d1533d38e6c085b651cd09c4615e1444..e228942ee081deec0e705c67605d015b301e8a4e 100644 --- a/drivers/staging/vme/devices/vme_user.c +++ b/drivers/staging/vme/devices/vme_user.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -625,7 +624,7 @@ err_nocard: static int __init vme_user_probe(struct device *dev, int cur_bus, int cur_slot) { int i, err; - char name[8]; + char name[12]; /* Save pointer to the bridge device */ if (vme_user_bridge != NULL) { diff --git a/drivers/staging/vme/vme.c b/drivers/staging/vme/vme.c index 477a1adfd0e90e84e8b42c66eb12c73e44dc5efe..994fdb9b212754ae706bc31b73a37eafa7d019b3 100644 --- a/drivers/staging/vme/vme.c +++ b/drivers/staging/vme/vme.c @@ -13,7 +13,6 @@ * option) any later version. */ -#include #include #include #include @@ -644,7 +643,7 @@ EXPORT_SYMBOL(vme_master_free); * Request a DMA controller with specific attributes, return some unique * identifier. */ -struct vme_resource *vme_request_dma(struct device *dev) +struct vme_resource *vme_dma_request(struct device *dev) { struct vme_bridge *bridge; struct list_head *dma_pos = NULL; @@ -705,7 +704,7 @@ err_ctrlr: err_bus: return NULL; } -EXPORT_SYMBOL(vme_request_dma); +EXPORT_SYMBOL(vme_dma_request); /* * Start new list @@ -880,7 +879,7 @@ int vme_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src, return -EINVAL; } - if (mutex_trylock(&(list->mtx))) { + if (!mutex_trylock(&(list->mtx))) { printk("Link List already submitted\n"); return -EINVAL; } @@ -923,7 +922,7 @@ int vme_dma_list_free(struct vme_dma_list *list) return -EINVAL; } - if (mutex_trylock(&(list->mtx))) { + if (!mutex_trylock(&(list->mtx))) { printk("Link List in use\n"); return -EINVAL; } @@ -956,7 +955,7 @@ int vme_dma_free(struct vme_resource *resource) ctrlr = list_entry(resource->entry, struct vme_dma_resource, list); - if (mutex_trylock(&(ctrlr->mtx))) { + if (!mutex_trylock(&(ctrlr->mtx))) { printk("Resource busy, can't free\n"); return -EBUSY; } @@ -975,7 +974,23 @@ int vme_dma_free(struct vme_resource *resource) } EXPORT_SYMBOL(vme_dma_free); -int vme_request_irq(struct device *dev, int level, int statid, +void vme_irq_handler(struct vme_bridge *bridge, int level, int statid) +{ + void (*call)(int, int, void *); + void *priv_data; + + call = bridge->irq[level - 1].callback[statid].func; + priv_data = bridge->irq[level - 1].callback[statid].priv_data; + + if (call != NULL) + call(level, statid, priv_data); + else + printk(KERN_WARNING "Spurilous VME interrupt, level:%x, " + "vector:%x\n", level, statid); +} +EXPORT_SYMBOL(vme_irq_handler); + +int vme_irq_request(struct device *dev, int level, int statid, void (*callback)(int level, int vector, void *priv_data), void *priv_data) { @@ -988,20 +1003,37 @@ int vme_request_irq(struct device *dev, int level, int statid, } if((level < 1) || (level > 7)) { - printk(KERN_WARNING "Invalid interrupt level\n"); + printk(KERN_ERR "Invalid interrupt level\n"); return -EINVAL; } - if (bridge->request_irq == NULL) { - printk("Registering interrupts not supported\n"); + if (bridge->irq_set == NULL) { + printk(KERN_ERR "Configuring interrupts not supported\n"); return -EINVAL; } - return bridge->request_irq(level, statid, callback, priv_data); + mutex_lock(&(bridge->irq_mtx)); + + if (bridge->irq[level - 1].callback[statid].func) { + mutex_unlock(&(bridge->irq_mtx)); + printk(KERN_WARNING "VME Interrupt already taken\n"); + return -EBUSY; + } + + bridge->irq[level - 1].count++; + bridge->irq[level - 1].callback[statid].priv_data = priv_data; + bridge->irq[level - 1].callback[statid].func = callback; + + /* Enable IRQ level */ + bridge->irq_set(level, 1, 1); + + mutex_unlock(&(bridge->irq_mtx)); + + return 0; } -EXPORT_SYMBOL(vme_request_irq); +EXPORT_SYMBOL(vme_irq_request); -void vme_free_irq(struct device *dev, int level, int statid) +void vme_irq_free(struct device *dev, int level, int statid) { struct vme_bridge *bridge; @@ -1012,20 +1044,31 @@ void vme_free_irq(struct device *dev, int level, int statid) } if((level < 1) || (level > 7)) { - printk(KERN_WARNING "Invalid interrupt level\n"); + printk(KERN_ERR "Invalid interrupt level\n"); return; } - if (bridge->free_irq == NULL) { - printk("Freeing interrupts not supported\n"); + if (bridge->irq_set == NULL) { + printk(KERN_ERR "Configuring interrupts not supported\n"); return; } - bridge->free_irq(level, statid); + mutex_lock(&(bridge->irq_mtx)); + + bridge->irq[level - 1].count--; + + /* Disable IRQ level if no more interrupts attached at this level*/ + if (bridge->irq[level - 1].count == 0) + bridge->irq_set(level, 0, 1); + + bridge->irq[level - 1].callback[statid].func = NULL; + bridge->irq[level - 1].callback[statid].priv_data = NULL; + + mutex_unlock(&(bridge->irq_mtx)); } -EXPORT_SYMBOL(vme_free_irq); +EXPORT_SYMBOL(vme_irq_free); -int vme_generate_irq(struct device *dev, int level, int statid) +int vme_irq_generate(struct device *dev, int level, int statid) { struct vme_bridge *bridge; @@ -1040,14 +1083,14 @@ int vme_generate_irq(struct device *dev, int level, int statid) return -EINVAL; } - if (bridge->generate_irq == NULL) { + if (bridge->irq_generate == NULL) { printk("Interrupt generation not supported\n"); return -EINVAL; } - return bridge->generate_irq(level, statid); + return bridge->irq_generate(level, statid); } -EXPORT_SYMBOL(vme_generate_irq); +EXPORT_SYMBOL(vme_irq_generate); /* * Request the location monitor, return resource or NULL @@ -1148,7 +1191,7 @@ int vme_lm_set(struct vme_resource *resource, unsigned long long lm_base, /* XXX Check parameters */ - return lm->parent->lm_set(lm, lm_base, aspace, cycle); + return bridge->lm_set(lm, lm_base, aspace, cycle); } EXPORT_SYMBOL(vme_lm_set); @@ -1228,16 +1271,18 @@ void vme_lm_free(struct vme_resource *resource) lm = list_entry(resource->entry, struct vme_lm_resource, list); - if (mutex_trylock(&(lm->mtx))) { - printk(KERN_ERR "Resource busy, can't free\n"); - return; - } + mutex_lock(&(lm->mtx)); - /* XXX Check to see that there aren't any callbacks still attached */ + /* XXX + * Check to see that there aren't any callbacks still attached, if + * there are we should probably be detaching them! + */ lm->locked = 0; mutex_unlock(&(lm->mtx)); + + kfree(resource); } EXPORT_SYMBOL(vme_lm_free); diff --git a/drivers/staging/vme/vme.h b/drivers/staging/vme/vme.h index 6206e91d19926e3c6e066cc9b479bf3abb422532..97dc22e34caf4fe06724e8ef3ccafdc81264986c 100644 --- a/drivers/staging/vme/vme.h +++ b/drivers/staging/vme/vme.h @@ -123,7 +123,7 @@ unsigned int vme_master_rmw (struct vme_resource *, unsigned int, unsigned int, unsigned int, loff_t); void vme_master_free(struct vme_resource *); -struct vme_resource *vme_request_dma(struct device *); +struct vme_resource *vme_dma_request(struct device *); struct vme_dma_list *vme_new_dma_list(struct vme_resource *); struct vme_dma_attr *vme_dma_pattern_attribute(u32, vme_pattern_t); struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t); @@ -136,10 +136,10 @@ int vme_dma_list_exec(struct vme_dma_list *); int vme_dma_list_free(struct vme_dma_list *); int vme_dma_free(struct vme_resource *); -int vme_request_irq(struct device *, int, int, +int vme_irq_request(struct device *, int, int, void (*callback)(int, int, void *), void *); -void vme_free_irq(struct device *, int, int); -int vme_generate_irq(struct device *, int, int); +void vme_irq_free(struct device *, int, int); +int vme_irq_generate(struct device *, int, int); struct vme_resource * vme_lm_request(struct device *); int vme_lm_count(struct vme_resource *); diff --git a/drivers/staging/vme/vme_api.txt b/drivers/staging/vme/vme_api.txt index 591eba5c903640ff8d07561ae7f305054d50583e..a5c1b1cd5fcc54c6fa72d091b3bc7a2ca60cdd39 100644 --- a/drivers/staging/vme/vme_api.txt +++ b/drivers/staging/vme/vme_api.txt @@ -77,7 +77,7 @@ driver in question: struct vme_resource * vme_slave_request(struct device *dev, vme_address_t aspace, vme_cycle_t cycle); - struct vme_resource *vme_request_dma(struct device *dev); + struct vme_resource *vme_dma_request(struct device *dev); For slave windows these attributes are split into those of type 'vme_address_t' and 'vme_cycle_t'. Master windows add a further set of attributes 'vme_cycle_t'. @@ -290,10 +290,10 @@ status ID combination. Any given combination can only be assigned a single callback function. A void pointer parameter is provided, the value of which is passed to the callback function, the use of this pointer is user undefined: - int vme_request_irq(struct device *dev, int level, int statid, + int vme_irq_request(struct device *dev, int level, int statid, void (*callback)(int, int, void *), void *priv); - void vme_free_irq(struct device *dev, int level, int statid); + void vme_irq_free(struct device *dev, int level, int statid); The callback parameters are as follows. Care must be taken in writing a callback function, callback functions run in interrupt context: @@ -307,7 +307,7 @@ Interrupt Generation The following function can be used to generate a VME interrupt at a given VME level and VME status ID: - int vme_generate_irq(struct device *dev, int level, int statid); + int vme_irq_generate(struct device *dev, int level, int statid); Location monitors diff --git a/drivers/staging/vme/vme_bridge.h b/drivers/staging/vme/vme_bridge.h index e43cc19103b32b4294880c215e55bc281fc435a2..851fa92559f6aac10e43588b348d9ea3ee4582a0 100644 --- a/drivers/staging/vme/vme_bridge.h +++ b/drivers/staging/vme/vme_bridge.h @@ -120,6 +120,8 @@ struct vme_bridge { /* Interrupt callbacks */ struct vme_irq irq[7]; + /* Locking for VME irq callback configuration */ + struct mutex irq_mtx; /* Slave Functions */ int (*slave_get) (struct vme_slave_resource *, int *, @@ -149,9 +151,8 @@ struct vme_bridge { int (*dma_list_empty) (struct vme_dma_list *); /* Interrupt Functions */ - int (*request_irq) (int, int, void (*cback)(int, int, void*), void *); - void (*free_irq) (int, int); - int (*generate_irq) (int, int); + void (*irq_set) (int, int, int); + int (*irq_generate) (int, int); /* Location monitor functions */ int (*lm_set) (struct vme_lm_resource *, unsigned long long, @@ -175,6 +176,8 @@ struct vme_bridge { #endif }; +void vme_irq_handler(struct vme_bridge *, int, int); + int vme_register_bridge (struct vme_bridge *); void vme_unregister_bridge (struct vme_bridge *); diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index fa7f0fcad33bf5a43073e0b8aaace449d26ced35..cde44d21b75cf65fe127b86f14fc42a4024a0869 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include @@ -79,7 +78,6 @@ // device specific // -#include "kcompat.h" #include "device_cfg.h" #include "ttype.h" #include "80211hdr.h" diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 53450b48eaa6e615ae4626f7aa4192003bbc3447..0db8d7b6e79cc8a7eedeaa6783e8fead7bb94197 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -661,7 +661,7 @@ else if(zonetype!=pDevice->abyEEPROM[EEP_OFS_ZONETYPE]) printk("zonetype in file[%02x] mismatch with in EEPROM[%02x]\n",zonetype,pDevice->abyEEPROM[EEP_OFS_ZONETYPE]); else - printk("Read Zonetype file sucess,use default zonetype setting[%02x]\n",zonetype); + printk("Read Zonetype file success,use default zonetype setting[%02x]\n",zonetype); } } else diff --git a/drivers/staging/vt6655/ioctl.c b/drivers/staging/vt6655/ioctl.c index fc9cbe0acd64d17d9e3d530fd74c42d30ff10b4e..d9a5fd21ab31d305b1896052177ed5f2cb43c48c 100644 --- a/drivers/staging/vt6655/ioctl.c +++ b/drivers/staging/vt6655/ioctl.c @@ -159,7 +159,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) { else if(zonetype == 0x02) { //Europe sZoneTypeCmd.ZoneType = ZoneType_Europe; } - else { //Unknow ZoneType + else { //Unknown ZoneType printk("Error:ZoneType[%x] Unknown ???\n",zonetype); result = -EFAULT; break; @@ -692,7 +692,7 @@ if(wpa_Result.authenticated==TRUE) { wireless_send_event(pDevice->dev, IWEVCUSTOM, &wrqu, pItemSSID->abySSID); } #endif - pDevice->fWPA_Authened = TRUE; //is sucessful peer to wpa_Result.authenticated? + pDevice->fWPA_Authened = TRUE; //is successful peer to wpa_Result.authenticated? } //printk("get private wpa_supplicant announce WPA SM\n"); diff --git a/drivers/staging/vt6655/kcompat.h b/drivers/staging/vt6655/kcompat.h deleted file mode 100644 index 2cf634ca67d6ebba7d9d2d5e5624293c6ba5e961..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/kcompat.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1996, 2003 VIA Networking, 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You 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. - * - * - * File: kcompat.h - * - * Purpose: define kernel compatibility header - * - * Author: Lyndon Chen - * - * Date: Apr 8, 2002 - * - */ - -#ifndef _KCOMPAT_H -#define _KCOMPAT_H - -#include - -#ifndef HAVE_NETDEV_PRIV -#define netdev_priv(dev) (dev->priv) -#endif - -#endif - diff --git a/drivers/staging/vt6655/mib.h b/drivers/staging/vt6655/mib.h index 69e04f70b6c109a2ea747b787e1bd4bdd12bc642..2aa2b91de72b335d343338e18192b5ae58282aa1 100644 --- a/drivers/staging/vt6655/mib.h +++ b/drivers/staging/vt6655/mib.h @@ -325,10 +325,10 @@ typedef struct tagSStatCounter { #ifdef Calcu_LinkQual //Tx count: ULONG TxNoRetryOkCount; //success tx no retry ! - ULONG TxRetryOkCount; //sucess tx but retry ! + ULONG TxRetryOkCount; //success tx but retry ! ULONG TxFailCount; //fail tx ? //Rx count: - ULONG RxOkCnt; //sucess rx ! + ULONG RxOkCnt; //success rx ! ULONG RxFcsErrCnt; //fail rx ? //statistic ULONG SignalStren; diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h index 17bd1b1f40e6d67d95e636bccee68efb72aa4602..5da815efe70bf243ef5bbfb8e4eae9aa8791d233 100644 --- a/drivers/staging/vt6655/rxtx.h +++ b/drivers/staging/vt6655/rxtx.h @@ -35,17 +35,10 @@ /*--------------------- Export Definitions -------------------------*/ -/*--------------------- Export Classes ----------------------------*/ - /*--------------------- Export Variables --------------------------*/ /*--------------------- Export Functions --------------------------*/ - -#ifdef __cplusplus -extern "C" { /* Assume C declarations for C++ */ -#endif /* __cplusplus */ - /* VOID vGenerateMACHeader( IN PSDevice pDevice, @@ -111,14 +104,4 @@ VOID vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, UINT c CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket); CMD_STATUS csBeacon_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket); -#ifdef __cplusplus -} /* End of extern "C" { */ -#endif /* __cplusplus */ - - - - #endif // __RXTX_H__ - - - diff --git a/drivers/staging/vt6655/wcmd.c b/drivers/staging/vt6655/wcmd.c index d81f5b79a157fdf1a136e5cd929e09871a3e0ae6..c9eabf9995dfd740f4ff6b221f4a247d6056f3ee 100644 --- a/drivers/staging/vt6655/wcmd.c +++ b/drivers/staging/vt6655/wcmd.c @@ -48,7 +48,6 @@ #include "wmgr.h" #include "power.h" #include "wctl.h" -#include "card.h" #include "baseband.h" #include "rxtx.h" #include "rf.h" diff --git a/drivers/staging/vt6655/wpa.c b/drivers/staging/vt6655/wpa.c index f92d33ffe775c340aeb10a44865bcc06476ee8ae..5da671418b523da7b88355624060e733cf97d9f4 100644 --- a/drivers/staging/vt6655/wpa.c +++ b/drivers/staging/vt6655/wpa.c @@ -147,7 +147,7 @@ WPA_ParseRSN ( if (pRSN->len >= 12) //oui1(4)+ver(2)+GKS(4)+PKSCnt(2) { j = 0; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wPKCount: %d, sizeof(pBSSList->abyPKType): %ld\n", pRSN->wPKCount, sizeof(pBSSList->abyPKType)); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wPKCount: %d, sizeof(pBSSList->abyPKType): %zu\n", pRSN->wPKCount, sizeof(pBSSList->abyPKType)); for(i = 0; (i < pRSN->wPKCount) && (j < sizeof(pBSSList->abyPKType)/sizeof(BYTE)); i++) { if(pRSN->len >= 12+i*4+4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*i) if ( !memcmp(pRSN->PKSList[i].abyOUI, abyOUI00, 4)) @@ -178,7 +178,7 @@ WPA_ParseRSN ( // overlay IE_RSN_Auth structure into correct place pIE_RSN_Auth = (PWLAN_IE_RSN_AUTH) pRSN->PKSList[m].abyOUI; j = 0; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAuthCount: %d, sizeof(pBSSList->abyAuthType): %ld\n", + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAuthCount: %d, sizeof(pBSSList->abyAuthType): %zu\n", pIE_RSN_Auth->wAuthCount, sizeof(pBSSList->abyAuthType)); for(i = 0; (i < pIE_RSN_Auth->wAuthCount) && (j < sizeof(pBSSList->abyAuthType)/sizeof(BYTE)); i++) { if(pRSN->len >= 14+4+(m+i)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*i) diff --git a/drivers/staging/vt6655/wroute.c b/drivers/staging/vt6655/wroute.c index ab991618a2983222e897bf67b3c4007320c0153e..1d02040e80e0496cb786cd678e2afd11a4976f13 100644 --- a/drivers/staging/vt6655/wroute.c +++ b/drivers/staging/vt6655/wroute.c @@ -113,7 +113,7 @@ BOOL ROUTEbRelay (PSDevice pDevice, PBYTE pbySkbData, UINT uDataLen, UINT uNodeI } if (pDevice->bEnableHostWEP) { - if (uNodeIndex >= 0) { + if (uNodeIndex < MAX_NODE_NUM + 1) { pTransmitKey = &STempKey; pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite; pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex; diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c index 820a7b8e6fb82dfcedbca8ed355383fd40ec8195..7dc01dbfc6ff2453a67053a1196724f7be84fbc7 100644 --- a/drivers/staging/vt6656/baseband.c +++ b/drivers/staging/vt6656/baseband.c @@ -46,7 +46,6 @@ #include "control.h" #include "datarate.h" #include "rndis.h" -#include "control.h" /*--------------------- Static Definitions -------------------------*/ static int msglevel =MSG_LEVEL_INFO; @@ -1041,7 +1040,7 @@ else { if(pDevice->config_file.ZoneType !=pDevice->abyEEPROM[EEP_OFS_ZONETYPE]) printk("zonetype in file[%02x] mismatch with in EEPROM[%02x]\n",pDevice->config_file.ZoneType,pDevice->abyEEPROM[EEP_OFS_ZONETYPE]); else - printk("Read Zonetype file sucess,use default zonetype setting[%02x]\n",pDevice->config_file.ZoneType); + printk("Read Zonetype file success,use default zonetype setting[%02x]\n",pDevice->config_file.ZoneType); } } diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c index e49796f7b814733101ab4561c0136c98a08301c9..f7136b0073bb9ee373e82be23fffa2cb9ad20e54 100644 --- a/drivers/staging/vt6656/channel.c +++ b/drivers/staging/vt6656/channel.c @@ -19,7 +19,7 @@ * * File: channel.c * - * Purpose: Channel number maping + * Purpose: Channel number mapping * * Author: Lucas Lin * diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index b02ca2d66feedb645817305d2d8268eaec89ecc0..8b541d1d0e23b15948bdac6944d9b68d45b44975 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include @@ -88,7 +87,6 @@ // device specific // -#include "kcompat.h" #include "device_cfg.h" #include "ttype.h" #include "80211hdr.h" @@ -103,7 +101,7 @@ #include "card.h" /*--------------------- Export Definitions -------------------------*/ -#define VNT_USB_VENDOR_ID 0x160A +#define VNT_USB_VENDOR_ID 0x160a #define VNT_USB_PRODUCT_ID 0x3184 #define MAC_MAX_CONTEXT_REG (256+128) diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c index 52daa3bda739802eae13f0c402b3d03c9c98d0d2..585b6b12c5baefc21bfb0642358473d860db0aa5 100644 --- a/drivers/staging/vt6656/firmware.c +++ b/drivers/staging/vt6656/firmware.c @@ -801,7 +801,7 @@ FIRMWAREbDownload( &(pBuffer[ii]) ); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Download firmware...%d %ld\n", ii, sizeof(abyFirmware)); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Download firmware...%d %zu\n", ii, sizeof(abyFirmware)); if (NdisStatus != STATUS_SUCCESS) { if (pBuffer) kfree(pBuffer); diff --git a/drivers/staging/vt6656/hostap.c b/drivers/staging/vt6656/hostap.c index 0c8267a10078cdfd9c161b1f8a8fcb970be23ab0..1078d616c4974257ba1814fa9cbc0ebc710dacbc 100644 --- a/drivers/staging/vt6656/hostap.c +++ b/drivers/staging/vt6656/hostap.c @@ -37,7 +37,6 @@ #include "baseband.h" #include "wpactl.h" #include "key.h" -#include "mac.h" #include "datarate.h" #define VIAWGET_HOSTAPD_MAX_BUF_SIZE 1024 diff --git a/drivers/staging/vt6656/ioctl.c b/drivers/staging/vt6656/ioctl.c index d94131fe52434b8bc5364a4db3596ae5517c3317..6f33005a615fb31bda7dd221f156b6cc40c3475d 100644 --- a/drivers/staging/vt6656/ioctl.c +++ b/drivers/staging/vt6656/ioctl.c @@ -152,7 +152,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) { else if(zonetype == 0x02) { //Europe sZoneTypeCmd.ZoneType = ZoneType_Europe; } - else { //Unknow ZoneType + else { //Unknown ZoneType printk("Error:ZoneType[%x] Unknown ???\n",zonetype); result = -EFAULT; break; @@ -679,7 +679,7 @@ if(wpa_Result.authenticated==TRUE) { wireless_send_event(pDevice->dev, IWEVCUSTOM, &wrqu, pItemSSID->abySSID); } #endif - pDevice->fWPA_Authened = TRUE; //is sucessful peer to wpa_Result.authenticated? + pDevice->fWPA_Authened = TRUE; //is successful peer to wpa_Result.authenticated? } //printk("get private wpa_supplicant announce WPA SM\n"); diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index aa8d1a2394a4b25f3c00a081d3bffa75e6e08eec..b7c6a22fe32191fe931d8d2aa565c846523c3e1c 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -1724,7 +1724,7 @@ int iwctl_siwauth(struct net_device *dev, case IW_AUTH_WPA_ENABLED: //pDevice->bWPADEVUp = !! wrq->value; //if(pDevice->bWPADEVUp==TRUE) - // printk("iwctl_siwauth:set WPADEV to enable sucessful*******\n"); + // printk("iwctl_siwauth:set WPADEV to enable successful*******\n"); //else // printk("iwctl_siwauth:set WPADEV to enable fail?????\n"); break; diff --git a/drivers/staging/vt6656/kcompat.h b/drivers/staging/vt6656/kcompat.h deleted file mode 100644 index 2cf634ca67d6ebba7d9d2d5e5624293c6ba5e961..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/kcompat.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1996, 2003 VIA Networking, 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You 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. - * - * - * File: kcompat.h - * - * Purpose: define kernel compatibility header - * - * Author: Lyndon Chen - * - * Date: Apr 8, 2002 - * - */ - -#ifndef _KCOMPAT_H -#define _KCOMPAT_H - -#include - -#ifndef HAVE_NETDEV_PRIV -#define netdev_priv(dev) (dev->priv) -#endif - -#endif - diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 05186110c0294ce3218074a57216ed923754da3d..ef17c4958c67afa1a2f2ed4330bbcb42b2cf47eb 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -64,11 +64,9 @@ #include "ioctl.h" #include "iwctl.h" #include "dpc.h" -#include "iocmd.h" #include "datarate.h" #include "rf.h" #include "firmware.h" -#include "mac.h" #include "rndis.h" #include "control.h" #include "channel.h" @@ -809,12 +807,6 @@ vntwusb_found1(struct usb_interface *intf, const struct usb_device_id *id) kfree(pDevice); return -ENODEV; } - //2008-0623-02by MikeLiu - //2007-0821-01by MikeLiu - //#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) - //usb_set_intfdata(intf, pDevice); - //SET_NETDEV_DEV(netdev, &intf->dev); - //#endif //2008-07-21-01by MikeLiu //register wpadev @@ -1545,7 +1537,7 @@ if(result!=0) { return buffer; } -//return --->-1:fail; >=0:sucessful +//return --->-1:fail; >=0:successful static int Read_config_file(PSDevice pDevice) { int result=0; UCHAR tmpbuffer[100]; diff --git a/drivers/staging/vt6656/mib.h b/drivers/staging/vt6656/mib.h index b806b4d297174ec8f76274e33c23b9ab1e085bc0..ac996d2cd91134aafeed1a3c5eb25217dab1f50a 100644 --- a/drivers/staging/vt6656/mib.h +++ b/drivers/staging/vt6656/mib.h @@ -357,10 +357,10 @@ typedef struct tagSStatCounter { #ifdef Calcu_LinkQual //Tx count: ULONG TxNoRetryOkCount; //success tx no retry ! - ULONG TxRetryOkCount; //sucess tx but retry ! + ULONG TxRetryOkCount; //success tx but retry ! ULONG TxFailCount; //fail tx ? //Rx count: - ULONG RxOkCnt; //sucess rx ! + ULONG RxOkCnt; //success rx ! ULONG RxFcsErrCnt; //fail rx ? //statistic ULONG SignalStren; diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 94ddf8bab62be9aa05bdb90dbe8c52da29f7574e..d9fa36c95230da95c61d3fcbd59b5a7680ef259c 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -3153,7 +3153,7 @@ bRelayPacketSend ( } if (pDevice->bEnableHostWEP) { - if (uNodeIndex >= 0) { + if (uNodeIndex < MAX_NODE_NUM + 1) { pTransmitKey = &STempKey; pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite; pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex; diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index 6912344fdfae436401e5dbcbb36cd51915e6d80c..51b2dcfbab9131fabe49ca9da64d8b39e229ca3f 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -48,7 +48,6 @@ #include "wmgr.h" #include "power.h" #include "wctl.h" -#include "card.h" #include "baseband.h" #include "control.h" #include "rxtx.h" @@ -1332,7 +1331,7 @@ BSSvSecondTxData( } spin_lock_irq(&pDevice->lock); - //is wap_supplicant running sucessful OR only open && sharekey mode! + //is wap_supplicant running successful OR only open && sharekey mode! #if 1 if(((pDevice->bLinkPass ==TRUE)&&(pMgmt->eAuthenMode < WMAC_AUTH_WPA)) || //open && sharekey linking (pDevice->fWPA_Authened == TRUE)) { //wpa linking diff --git a/drivers/staging/vt6656/wpa.c b/drivers/staging/vt6656/wpa.c index f92d33ffe775c340aeb10a44865bcc06476ee8ae..5da671418b523da7b88355624060e733cf97d9f4 100644 --- a/drivers/staging/vt6656/wpa.c +++ b/drivers/staging/vt6656/wpa.c @@ -147,7 +147,7 @@ WPA_ParseRSN ( if (pRSN->len >= 12) //oui1(4)+ver(2)+GKS(4)+PKSCnt(2) { j = 0; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wPKCount: %d, sizeof(pBSSList->abyPKType): %ld\n", pRSN->wPKCount, sizeof(pBSSList->abyPKType)); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wPKCount: %d, sizeof(pBSSList->abyPKType): %zu\n", pRSN->wPKCount, sizeof(pBSSList->abyPKType)); for(i = 0; (i < pRSN->wPKCount) && (j < sizeof(pBSSList->abyPKType)/sizeof(BYTE)); i++) { if(pRSN->len >= 12+i*4+4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*i) if ( !memcmp(pRSN->PKSList[i].abyOUI, abyOUI00, 4)) @@ -178,7 +178,7 @@ WPA_ParseRSN ( // overlay IE_RSN_Auth structure into correct place pIE_RSN_Auth = (PWLAN_IE_RSN_AUTH) pRSN->PKSList[m].abyOUI; j = 0; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAuthCount: %d, sizeof(pBSSList->abyAuthType): %ld\n", + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAuthCount: %d, sizeof(pBSSList->abyAuthType): %zu\n", pIE_RSN_Auth->wAuthCount, sizeof(pBSSList->abyAuthType)); for(i = 0; (i < pIE_RSN_Auth->wAuthCount) && (j < sizeof(pBSSList->abyAuthType)/sizeof(BYTE)); i++) { if(pRSN->len >= 14+4+(m+i)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*i) diff --git a/drivers/staging/wlags49_h2/Kconfig b/drivers/staging/wlags49_h2/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..92053fe70130b9fa37a7b14bca84a3a57b8d377d --- /dev/null +++ b/drivers/staging/wlags49_h2/Kconfig @@ -0,0 +1,9 @@ +config WLAGS49_H2 + tristate "Agere Systems HERMES II Wireless PC Card Model 0110" + depends on WLAN_80211 && WIRELESS_EXT && PCMCIA + select WEXT_SPY + ---help--- + Driver for wireless cards using Agere's HERMES II chipset + which are identified with Manufacture ID: 0156,0003 + The software is a modified version of wl_lkm_722_abg.tar.gz + from the Agere Systems website, addapted for Ubuntu 9.04. diff --git a/drivers/staging/wlags49_h2/Makefile b/drivers/staging/wlags49_h2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..25d0a8a9ce30ddbed6caa8274d18ebd5c17f8e81 --- /dev/null +++ b/drivers/staging/wlags49_h2/Makefile @@ -0,0 +1,81 @@ +# +# Makefile for wlags49_h2_cs.ko and wlags49_h25_cs.ko +# +# Default build for Hermes-II base cards (possibly identified with +# "manfid: 0x0156, 0x0003" in "pccardctl ident" output), comment +# -DHERMES25 below +# +# If you want to build for Hermes-II.5 base cards (possibly identified with +# "manfid: 0x0156, 0x0004" in "pccardctl ident" output), uncomment +# -DHERMES25 below +# +# If you want to build AP support (untested), comment out -DSTA_ONLY + +INSTALLDIR := /lib/modules/$(shell uname -r)/kernel/drivers/net/wireless +EXTRA_CFLAGS += -I$(KERNELDIR)/include +EXTRA_CFLAGS += -I$(src) \ + -DBUS_PCMCIA \ + -DUSE_WPA \ + -DUSE_WEXT \ + -DSTA_ONLY \ + -DWVLAN_49 \ +# -DHERMES25 \ +# -DDBG \ +# -DDBG_LVL=5 \ +# -DUSE_UIL \ +# -DUSE_PROFILE \ + +ifeq ($(findstring HERMES25,$(EXTRA_CFLAGS)),) +WLNAME := wlags49_h2_cs +$(WLNAME)-y := sta_h2.o +ifeq ($(findstring STA_ONLY,$(EXTRA_CFLAGS)),) +$(WLNAME)-y += ap_h2.o +endif +else +WLNAME=wlags49_h25_cs +$(WLNAME)-y := sta_h25.o +ifeq ($(findstring STA_ONLY,$(EXTRA_CFLAGS)),) +$(WLNAME)-y += ap_h25.o +endif +endif + +# If KERNELRELEASE is defined, we've been invoked from the +# kernel build system and can use its language. +ifneq ($(KERNELRELEASE),) + +obj-m += $(WLNAME).o + +$(WLNAME)-y += wl_profile.o \ + wl_wext.o \ + wl_priv.o \ + wl_main.o \ + wl_enc.o \ + wl_util.o \ + wl_netdev.o \ + wl_cs.o \ + mmd.o \ + hcf.o \ + dhf.o + +$(WLNAME)-$(CONFIG_SYSFS) += wl_sysfs.o + +# Otherwise we were called directly from the command +# line; invoke the kernel build system. +else + KERNELDIR ?= /lib/modules/$(shell uname -r)/build + PWD := $(shell pwd) + +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +endif + +clean: + rm -fr *.o *.ko *.mod.c *.mod.o .*.*.cmd Module.symvers \ + Module.markers modules.order .tmp_versions + +install: default + -rmmod $(WLNAME) + install -d $(INSTALLDIR) + install -m 0644 -o root -g root $(WLNAME).ko $(INSTALLDIR) + /sbin/depmod -aq + diff --git a/drivers/staging/wlags49_h2/README.ubuntu b/drivers/staging/wlags49_h2/README.ubuntu new file mode 100644 index 0000000000000000000000000000000000000000..47beaec86e4a7168fa4eceabbf7847f8f1f6f7b6 --- /dev/null +++ b/drivers/staging/wlags49_h2/README.ubuntu @@ -0,0 +1,180 @@ +======================================================================= +WLAN driver for cards using the HERMES II and HERMES II.5 chipset + +HERMES II Card + +PCMCIA Info: "Agere Systems" "Wireless PC Card Model 0110" + Manufacture ID: 0156,0003 + +HERMES II.5 Card + +PCMCIA Info: "Linksys" "WCF54G_Wireless-G_CompactFlash_Card" + Manufacture ID: 0156,0004 + +Based on Agere Systems Linux LKM Wireless Driver Source Code, +Version 7.22; complies with Open Source BSD License. +======================================================================= + +DESCRIPTION + +The software is a modified version of wl_lkm_722_abg.tar.gz from the +Agere Systems website, addapted for Ubuntu 9.04. + +Modified for kernel 2.6 by Henk de Groot +Based on 7.18 version by Andrey Borzenkov $Revision: 39 $ + +INSTALLATION + +Unpack in a new directory. + +Open a terminal screen. + +Change directory to the source directory + +Type command + +make + +and wait until it is finshed. Now you have build the module +wlags49_h2_cs; this module is meant for a HERMES II card. + +The driver is tested with a Thomson SpeedTouch 110 Wireless PC Card. +For the test Station mode was used with WEP. The driver is supposed +to support WAP and as accesspoint that is NOT tested. + +If you have a card using the HERMES II.5 chip you have to make +changes to the Makefile and uncomment -DHERMES25. This will build +driver wlags49_h25_cs. + +Note: You can detemine the type with command "pccardctrl info" + MANIFID: 0156,0002 = HERMES - not supported by this driver + MANIFID: 0156,0003 = HERMES II (Wireless B) + MANIFID: 0156,0004 = HERMES II.5 (Wireless B/G) + +After succesfull compile type command + +sudo make install + +to install the module. + +Now the card should be recognized. It should be able to configure +and use the card with NetworkManager. Wpa_supplicant also works, as does +manual configuration using the iwconfig/iwlist programs. + +Note: I only tested Station mode with WEP but if I didn't break anything +WPA and AP mode should also work; note however that WPA was experimental +in the original Agere driver! + +Note: to compile as AP change the makefile and remove the line +-DSTA_ONLY \ + +(or comment it, but in that case make sure to move it after all the + flags you want to use) + +CHANGES + +The HCF functions to control the card are virtually unchanged, the only +changes are meant to fix compiler warnings. The only real change is in +HCF_WAIT_WHILE which now has a udelay(2) added to give a small delay. + +The linux driver files (wl_xxxx.c) are changed in the following ways: +- Addaptations of Andrey Borzenkov applied to 7.22 source +- Alterations to avoid most HCF_ASSERTs +-- Switching interrupts off and on in the HCF +-- Bugfixes, things that were aparently wrong like reporting link status + change which checked a variable that was not changed in HCF anymore. +-- Used on WEP but setting keys via SIOCSIWENCODEEXT was not supported +-- Recovery actions added + +The major problem was the order in which calls can be made. The original +looks like a traditonal UNIX driver. To call an "ioctl" function you +have to "open" the device first to get a handle and after "close" no +"ioctl" function can be called anymore. With the 2.6 driver this all +changed; the former ioctl functions are now called before "open" and +after "close", which was not expected. One of the problems was enable/ +disable of interrupts in the HCF. Interrupt handling starts at "open" +so if a former "ioctl" routinge is called before "open" or after "close" +then nothing should be done with interrupt switching in the HCF. Once +this was solved most HCF_ASSERTS went away. + +The last point, recovery actions added, needs some clarification. +Starting the card works most of the time, but unfortunately not always. +At a few times recovery code was added; when the card starts to +misbehave or the communication between the HCF and the card is +out of sync and the HCF enters DEFUNCT mode everything is reset and +reinitialized. Note, hcf.c contains a lot of documentation. It takes +some time but slowly some things become clear. Also some unresolved +issues are mentioned in hcf.c, so there are still unknown bugs. + +The card problems are almost in all cases when starting up and before +the first association with an AP, once the card is in operation it +seems to stay that way; when debugging no HCF_ASSERTS appear anymore. +Note: some HCF_ASSERTS still appear, in a number of cases it is a real +error, for example at card removal the missing card is detected. + +LICENSE + +The Agere Systems license applies. This is why I include the original +README.wlags49. The instructions in that file are bogus now. I also +include the man page. Eventhough setting parameters on the module +does not work anymore but it provides some information about all the +settings. + +I have not have personal contact with Agere, but others have. Agere +agreed to make their software available under the BSD licence. +This driver is based on the 7.22 version. + +The following was mailed by Agere to Andrey Borzenkov about this: + + --- Begin Message --- + + * From: TJ + * Date: Mon, 05 Feb 2007 19:28:59 +0000 + + Hi Andrey, + + I've got some good news for you/us/the world of Hermes :) + + I got a reply from the legal representative at Agere confirming that + their source-code is BSD licensed, and I've included the contents of the + email here. + + I hope this re-assures you so that your excellent work on the drivers + can be made widely available for other hackers to work with. + + Regards, + + TJ. + + --------- + On Mon, 2007-02-05 at 13:54 -0500, Pathare, Viren M (Viren) wrote: + + + "I would like to confirm that the two drivers; Linux LKM Wireless Driver + Source Code, Version 7.18 and Linux LKM Wireless Driver Source Code, + Version 7.22 comply with Open Source BSD License. Therefore the source + code can be distributed in unmodified or modified form consistent with + the terms of the license. + + The Linux driver architecture was based on two modules, the MSF (Module + specific functions) and the HCF (Hardware Control Functions). Included + in the HCF is run-time firmware (binary format) which is downloaded into + the RAM of the Hermes 1/2/2.5 WMAC. + + This hex coded firmware is not based on any open source software and + hence it is not subject to any Open Source License. The firmware was + developed by Agere and runs on the DISC processor embedded within the + Hermes 1/2/2.5 Wireless MAC devices. + + Hope this helps. + + Sincerely, + + Viren Pathare + Intellectual Property Licensing Manager + Agere" + + + + --- End Message --- + diff --git a/drivers/staging/wlags49_h2/README.wlags49 b/drivers/staging/wlags49_h2/README.wlags49 new file mode 100644 index 0000000000000000000000000000000000000000..7586fd09adc9bccb67e889c3c899ccdd87e66173 --- /dev/null +++ b/drivers/staging/wlags49_h2/README.wlags49 @@ -0,0 +1,641 @@ +============================================================================== +Agere Systems Inc. July 2004 +Readme for Linux Driver Source for Wavelan Version: 7.22-abg +============================================================================== + +This text file includes update information, installation instructions, +limitations to the current version of the product, and suggestions to solve +known issues or problems. + + +TABLE OF CONTENTS. + +1. DESCRIPTION +2. SYSTEM REQUIREMENTS +3. NEW IN THIS RELEASE +4. INSTALLATION NOTES +5. TECHNICAL CONSTRAINTS +6. KNOWN ISSUES +7. TECHNICAL SUPPORT + +------------------------------------------------------------------------------ +1. DESCRIPTION + + With this package, you can build and install a Wireless driver for a + specific Linux kernel. + + The driver in this package supports the network interface cards based on: + - WL60010, a.k.a. Hermes-II + - WL60040, a.k.a. Hermes-II.5 + + Although derived from the Hermes-I/II Linux driver, this release ONLY + Supports Hermes-II/II.5 chipsets. Hermes-I is no longer supported. + + The software is distributed in a compressed source file archive: + - wl_lkm_7_22_abg.tar.gz + + Because this release supports more than one Hermes CPU and bus + architecture, a naming convention is used for the resulting binaries that + can be built from this source code. Driver binaries are named as follows: + + wlags49__.o + + where 'wlags49' denotes an Agere WaveLan Linux build, + + is: 'h2' for Hermes-II, 'h25' for Hermes-II.5 + + is: 'cs' for Card Services (PCMCIA, Compact Flash), PCI for + PCI or MiniPCI. + + For example, a driver built for Hermes-II Card Services (PCMCIA/Compact + Flash) is named wlags49_h2_cs.o, whereas a driver built for Hermes-II + MiniPCI is named wlags49_h2_pci.o. + The following software is included with this distribution: + + General information: + * README.wlags49 This file + * LICENSE.wlags49 License + * wlags49.mk Top level Makefile + * Build Script to build driver + * Install Script to install driver + + Driver source: + * wireless/ MSF source + * hcf/ HCF and F/W source + * wireless/wlags49_cs.mk Driver Makefile, PC Card + * wireless/wlags49_pci.mk Driver Makefile, PCI + * include/hcf/debug.h Driver debug support + * include/hcf/hcfcfg.h Header to configure HCF + * include/wireless/*.h Driver source headers + + Driver online manual page: + * man/wlags49.4 Driver manual page + + PCMCIA configuration update: + * etc/wlags49.conf Add-on config file + * etc/wlags49.mk config update Makefile + * etc/wlags49.patch config update patch file + + The driver is build up of 2 modules: + - a higher module called Module Specific Functions (MSF), which contains + the functions of the driver that are network driver interface and + Operating System specific. + - a lower module called Hardware Control Functions (HCF), which contains + the functions to interface to the Network Interface Card (NIC). The HCF + provides for all WaveLAN NIC types one standard interface to the MSF. + This I/F is called the Wireless Connection Interface (WCI) and is the + subject of a seperate document (025726). + + The HCF directory contains firmware images to allow the card to operate in + either station (STA) or Access Point (AP) mode. In the build process, the + files fw_h2.c and fw_h25.c are used for Hermes-II and Hermes-II.5 + respectively. The firmware images in this release are identified as: + - HII Station F/W: fw_h2.c.sta + - HII.5 Station F/W: fw_h25.c.sta + - HII AccesPoint F/W: fw_h2.c.ap + - HII.5 AccesPoint F/W: fw_h25.c.ap + To build a STA or AP mode driver, the suffix .sta or .ap must be removed. + The files as distributed by this release build STA drivers by default. + +------------------------------------------------------------------------------ +2. SYSTEM REQUIREMENTS + +2.1 Operating System + + This software can be compiled and installed with Linux kernel versions + 2.4.x. Although this driver should compile for other CPUs as well, as of + the date of this release, no CPU architectures other than x86 have been + verified. + + wl_lkm_7_22_abg is tested with the following Linux Distributions: + * Red Hat version 9.0 + * Suse version 9.0 + + If you're building for PC Card or Compact Flash, you need the Card Services + from David Hinds. + + wl_lkm_7_22_abg is tested with: + * pcmcia-cs-3.2.7.tar.gz + +2.2 Free Disk Space + + To compile the software you need to have the full set of Linux kernel + source files installed, as well as a sane build environment which includes + all tools necessary for compiling and linking code. Depending on the exact + version of the kernel, you need approximately 150 MB of free disk space. + Once compiled, the driver uses about 150-200 KB. Please note, this size is + approximate and can vary depending on which version of the driver is built. + In addition, adding debug tracing support increases this size. + +------------------------------------------------------------------------------ +3. NEW IN THIS RELEASE + +Version 7.22 abg - July 28, 2004 + +------------------------------------------------------------------------------ +4. INSTALLATION NOTES + + The driver files for the Linux driver are not "ready" for direct + installation onto any Linux computer. To build and install the driver you + need some expertise on the Linux operating system in general and the type + and version installed of the kernel installed on your computer. With this + knowledge you can use the driver source files provided to build your own + Linux driver for your specific computer and kernel. + +4.1 Before you start + + 1) Determine the type and version of the Linux kernel of your computer and + check whether it meets the system requirements listed in section 2 of this + README. + + 2) If you're building for PC Card or Compact Flash, read the Linux + PCMCIA-HOWTO by David Hinds. This document is probably provided on the + CD-ROM of your Linux distribution. You can download the latest version + from: + + http://pcmcia-cs.sourceforge.net + + Please read the section titled "Prerequisites and kernel setup" of the + PCMCIA-HOWTO. + +4.2 Build the driver for PC Card / Compact Flash + + 1) Obtain a copy of the Linux PCMCIA package from a CD-ROM of your Linux + distribution or download the latest version. + For your convenience, the Agere Systems Wireless CD-ROM contains a copy of + the PCMCIA package in sub-directory: Xtras/Linux/PCMCIA + + 2) To unpack the Linux PCMCIA package, copy it to the current working + directory and type: + % tar xzvf pcmcia-cs-x.y.z.tar.gz + % mv pcmcia-cs-x.y.z pcmcia-cs + + Note: If you use the archive supplied on the CDROM, use archive name + "pc3_2_1.tgz" instead of "pcmcia-cs-3.2.7.tar.gz". + + Note: even though PCMCIA code exists in the kernel source tree, the PCMCIA + Card Services package needs to be unpacked locally to build drivers based + on it. + + 3) Extract the wlags49 distribution archive on top of the Linux PCMCIA + package. + % cd pcmcia-cs + % tar xzvf ../wl_lkm_7_22_abg.tar.gz + + 4) To build and install the driver, follow the procedure below: + % ./Configure + + Answer the presented questions. Usually the default answers are OK and + pressing "Enter" is enough. + On newer RedHat systems, however, you should specify "/usr/src/linux-2.4" + as the Linux source directory instead of the default "/usr/src/linux". + + For more detailed information on configuration, building and installing, + see the PCMCIA-HOWTO. + + To build the default drivers, which support Hermes-II in station mode, run + the Build script: + % ./Build + + This script determines whether your system uses in-kernel PCMCIA and either + builds the full PCMCIA package or just the driver. + + Before installing the driver with the Install script, you must become + 'root': + % su + .. + % ./Install + + This script determines whether your system uses in-kernel PCMCIA and either + installs the full PCMCIA package or just the driver. + + 5) If it becomes necessary to clean the build, issue the following + commands: + % make clean + % make -C lib clean + +4.3 Build the driver for PCI + + 1) Extract the wlags49 to the current working directory. + % tar xzvf wl_lkm_7_22.tar.gz + + Note: there is no need to unpack the driver source into a PCMCIA build + directory. + + 2) To build the PCI driver: + % make -f wlags49.mk wlags49_h2_pci + or + % make -f wlags49.mk wlags49_h25_pci + + 3) Install the driver. + % insmod ./wireless/wlags49_h25.o + + 4) If it becomes necessary to clean the build. + % make -f wlags49.mk pci_clean + +4.4 Configure your Wireless PC Card + + There are 3 ways to configure the driver + - module parameters (/etc/pcmcia/config.opts) + - wireless extension (/etc/pcmcia/wireless.opts) + - Agere configuration file (/etc/agere/iwconfig-eth#) + + +4.4.1 Configure through /etc/pcmcia/config.opts + + To use this method, make sure that /etc/pcmcia/wireless.opts file is either + absent or contains blank parameter values as shown below. + + *,*,*,00:60:1D:*|*,*,*,00:02:2D:*) + INFO="" + ESSID="" + MODE="" + KEY="" + ;; + + 1) To configure the Wireless PC Card, please refer to: + * The online manual page (wlags49.4) + % man wlags49 + * The network adapter sections of the PCMCIA documentation. + % more PCMCIA-HOWTO + + 2) Use an editor to configure the module parameters: + # vi /etc/pcmcia/config.opts + + a) To connect your computer to a wireless infrastructure that includes + access points such as the AP-1000 or AP-500, you need to identify the + network name of the wireless infrastructure. + + For example if your infrastructure uses the network name "My Network", + edit the config.opts file to include the following: + + module "" opts "network_name=My\ Network" + + Notice that the space character needs to be escaped with a backslash. + + b) To connect your computer to a Residential Gateway RG-1000, you need + to know the RG ID (=network_name) and the encryption key. You can find + the RG ID on a small label on the rear of the unit. + + For example if your RG-1000 has ID 225ccf and you did not change the + encryption key yet, edit the config.opts file to include the following: + + module "" opts "network_name=\"225ccf\" key_1=\"25ccf\" + enable_encryption=Y" + + If you changed your encryption key, you should specify this key as key_1 + on the parameter line. + + c) To connect your computer to a peer-to-peer network, in an environment + without access points, the IBSS mode is recommended. + + For example to connect to a peer-to-peer network called "My Network", + enter the following in the config.opts file: + + module "" opts "create_ibss=Y network_name=My\ Network" + + d) Optionally you can also include a "Station Name" value that can be + used to indentify your computer on the wireless network. + + For example if you wish to name your computer "Wave1" when connecting it + to a wireless infrastructure, edit the config.opts file to include the + following: + + module "" opts "network_name=Ocean station_name=Wave1" + + e) To connect your computer to an Ad-Hoc workgroup of wireless + computers, enter the following in the config.opts file: + + module "" opts "port_type=3" + + Note that the "Ad-Hoc Demo Mode" is not the recommended mode for a + peer-to-peer network. The configuration of this non-interoperable mode + is only explained here for special applications (e.g. research, or + compatibility with other / previous WaveLAN/IEEE products). + + The IBSS mode described in c) is the preferred and interoperable mode + for creating a peer-to-peer network. + + 3) Use an editor to modify the network options for your adapter. + # vi /etc/pcmcia/network.opts + + The parameters need to be correct for the connected network. Check with + your system administrator for the correct network information. Refer to + the PCMCIA-HOWTO for more configuration information. + + For example: + *,*,*,*) + IF_PORT="" + BOOTP="n" + IPADDR="10.0.0.5" + NETMASK="255.255.255.0" + NETWORK="10.0.0.0" + BROADCAST="10.0.0.255" + GATEWAY="10.0.0.1" + DOMAIN="domain.org" + DNS_1="dns1.domain.org" + ;; + + RedHat and Suse do not use the network.opts to configure the driver. + Instead RedHat uses a GUI-based tool called 'neat' ('net.cfg' in older + versions) and SuSE Linux uses 'YaST'. These tools creates scripts, like + ifcfg-eth0, in the directory /etc/sysconfig/network-scripts. Using the + default GNOME menu, you can start netcfg from: Programs->System->Network + Configuration. + + 4) Restart the PCMCIA services. + # /etc/rc.d/rc.pcmcia restart + or + # /etc/rc.d/init.d/pcmcia restart + + + For a more detailed description about the various configuration options and + definitions, please consult the Wireless documentation. + +4.4.2 Configure through /etc/pcmcia/wireless.opts + + This driver has support for the "Wireless Extensions". This interface + allows the "Wireless Tools" to get statistics from the driver and allows to + change the configuration of the driver on the fly. + + The latest versions of the PCMCIA package contain scripts that use the + wireless extension to configure the driver as an alternative to the + configuration through module parameters as described in section 4.4.1. + Read the /etc/pcmcia/wireless.opts file for the theory of operation. When + the driver is configured, go to section 4.4.1 step 3 to configure the + network parameters. + + For more information, refer to the following WEB pages: + http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Linux.Wireless.Extensions.html + http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html + +4.4.3 Configure through /etc/agere/iwconfig-eth# + + In addition to using either the module options or the wireless extensions + methods to configure a wireless device, this version of the software also + supports an Agere specific implementation. This was done because: + * Module options configures multiple devices the same. + * Wireless extensions parameters do not cover all of the available options + in the driver. + + For each wireless ethernet device (identified by eth, where n is a + positive integer), a file /etc/agere/iwconfig-eth can be created which + contains configuration information for a wireless device. For example, the + file /etc/agere/iwconfig-eth1 is the config file for eth1. This file should + contain Key/Value pairs in the format: + + = + + where is the parameter to configure and is the value to + assign it. For example, if the config file /etc/agere/iwconfig-eth1 + described above contains the following: + + DesiredSSID=some_network + EnableEncryption=Y + Key1=net01 + TxKey=1 + + this configures eth1 to associate to the ESSID 'some_network' with + encryption on, where the the first encryption key is 'net01' and the key to + use for encryption is Key 1. + + Note that this only works on Agere hardware which uses this driver. For + other wireless drivers, or non-wireless devices, this file can be present, + but has no effect. + + Please refer to the man page for more information on this configuration + file and the parameters that can be set. + + +4.5 Configuring your Wireless PCI card + + Note that the above method of configuring the card using + /etc/pcmcia/config.opts is only valid for PCMCIA/CF cards. For [mini]PCI + and CardBus cards, refer to your system's documentation on modules.conf to + load the driver with the proper options for a given wireless ethernet + interface. In addition, network configuration tools like 'netcfg', 'neat', + or 'YaST' (see Section 4.4.1, Step 3) can be used to configure the miniPCI + card. Lastly, the Agere configuration file described in Section 4.4.3 may + also be used for [mini]PCI and CardBus devices. + +4.6 Troubleshooting + + When the Wireless PC Card is inserted, the card manager emit beeps in + different tones to indicate success or failure of particular configuration + steps. + a) Two high beeps + - The card was identified and configured successfully. + b) One high beep followed by a low beep + - The card was identified, but could not be configured. + - Examine the system log (dmesg) for PCMCIA error or warning messages. + c) One low beep + - The card could not be identified. + - Execute "cardctl ident" to display the adapter PnP information. + Verify the PnP information matches an entry in the PCMCIA + configuration file (/etc/pcmcia/config). + - Examine the system log (dmesg) for PCMCIA error or warning messages. + + The Wireless PC Card has two LEDs that indicate the state of the adapter + and network. + * Power LED (toward the middle of the adapter) + - This LED indicates power has been applied, and the card is + functional. In normal operation mode with Card Power Management + disabled, it is steady-on. With Card Power Management enabled, it + blinks rapidly (several times per second). + * Transmit/Receive LED (closer to the edge of the adapter) + - This LED flashes when it detects transmit or receive packets. + + * Both LEDs blink at the same time every 10 seconds. + - The adapter was unable to make contact with the named wireless + network. Verify the network_name, in the config.opts file matches the + network name of the access point. + * LEDs indicate normal operation with the Power LED + steady-on or blinking rapidly and Transmit/Receive LED flashing, but no + traffic. + - If the network is operating in normal mode (ie. port_type = 0 or not + specified), and a network_name has been specified, verify the + workstation network parameters (ifconfig, route, etc.) are correct + for the wireless network. + - If the network is operating in Ad-Hoc (peer-to-peer) mode (ie. + port_type = 3), the adapter needs another workstation/adapter to + communicate with. Verify the network parameters on both of the + workstations (ifconfig, route, etc.) are correct. + + Refer to the online manual page for additional configuration, feature and + support information. + % man wlags49 + or + % man 4 wlags49 + or + % nroff -man wlags49.4 | more + +4.7 Identifying the software + + This section explains how to identify the version of this software once it + is unpacked or installed. + + The Linux Driver Source/Library distribution consist of two main + components, the driver source and the HCF module. + + * To quickly identify the version of the source, type: + % grep DRV.*VERSION include/wireless/wl_version.h + #define DRV_MAJOR_VERSION 7 + #define DRV_MINOR_VERSION 22 + + * To identify the revision of the HCF library contained in the driver, + type: + % grep HCF.Revision hcf/hcf.c + #define HCF_VERSION TEXT( "HCF$Revision: 1.8 $" ) + + To identify a compiled wlags49 driver, go to the directory where the driver + is located. Card Services drivers (wlags49_h2_cs.o and wlags49_h25_cs.o) + are located in: + /lib/modules//pcmcia + + PCI drivers (wlags49_h2.o) are located in: + /lib/modules//kernel/drivers/net + + * To retrieve the version of the source used to compile the driver, type: + % strings .o | grep Agere + v7.22-abg-Beta for PCMCIA + v7.22-abg-Beta for PCI + + * Likewise, to retrieve the revision of the HCF used to compile the driver, + type: + % strings .o | grep Revision + HCF$Revision: 5.15 + + At startup the wlags49 driver reports its version in the system log file + (/var/log/messages). + +------------------------------------------------------------------------------ +5. TECHNICAL CONSTRAINTS + + At the time of release of this software, the following constraints are + identified: + +5.1 Using the ISA adapter + + Description: To allow operation in desktop computers Agere also provides an + optional ISA bus to PC Card adapter (also referred to as "swapbox"). + + This ISA Adapter can be configured for two different I/O Address values: + * 3E2 (factory-set default) + * 3E0 + + Impact: By default the i82365 module of the Linux pcmcia package only + probes at 3E0. + + Actions: + 1) Read the manual page on the probing of the i82365 module, by typing the + command: + man i82365 + + 2) Apply one of the two following options: + a) Change the I/O address strapping of the ISA adapter by replacing the + jumper on the ISA adapter. The correct jumper setting is pictured in + the electronic "Wireless ISA Adapter, Getting Started Guide" provided + on the Wireless Software CD-ROM. This guide is provided in Adobe's + Acrobat PDF format. + + b) Alternatively, you can load the i82365 module with the + "extra_sockets" parameter set to 1. + + On a RedHat 5.x thru 7.x, system, put this in the file + "/etc/sysconfig/pcmcia": + PCMCIA=yes + PCIC=i82365 + PCIC_OPTS="extra_sockets=1" + CORE_OPTS= + CARDMGR_OPTS= + + For other Linux distributions, you are advised to consult the + "PCMCIA-HOWTO" notes for information about changing the I/O Address + probing. + +5.2 Using the PCI Adapter + + Description: To allow operation in desktop computers Agere also provides an + optional PCI bus to PC Card adapter (also referred to as "swapbox"). + + For correct interrupt assignment, the system should support PCIBIOS 2.2. + It is recommended to use PCMCIA package version 3.2.7 or higher. + + The default configuration of the interrupt routing method of the PCI + Adapter's TI CardBus Controller is incorrect. + + Actions: + 1) Read the manual page on the "Options specific for TI CardBus + Controllers" of the i82365 module, by typing the command: + man i82365 + + 2) Load the i82365 module with the "irq_mode" parameter set to 0. + On a RedHat 5.x thru 7.x system, put this in the file + "/etc/sysconfig/pcmcia": + PCMCIA=yes + PCIC=i82365 + PCIC_OPTS="irq_mode=0" + CORE_OPTS= + CARDMGR_OPTS= + + For the location of the PCMCIA scripts on other Linux distributions, you + are advised to consult the "PCMCIA-HOWTO", "Notes about specific Linux + distributions". + +------------------------------------------------------------------------------ +6. KNOWN ISSUES + + This is the current list of known issues for this release, and will be + addressed in the near future: + + 1. This driver release contains a version of Hermes-II.5 firmware which + REQUIRES calibrated cards. If there is no calibration data present in the + PDA of the hardware, the firmware does not operate. + + 2. WDS is not yet supported. + + 3. DMA is not yet supported. + + 4. WPA is not yet supported. + + 5. 32-bits I/O is not yet supported. + + 6. The current Build script also builds the PCI drivers. + + 7. The current Install script also copies the PCI drivers to the lib + directory. + + 8. If F/W files are required from outside this release, the entry points + inside these F/W files have to be renamed from "ap" and "station" to + "fw_image" and they have to be renamed to fw_h2.c and fw_h25.c for + Hermes-II and Hermes-II.5. + +------------------------------------------------------------------------------ +7. TECHNICAL SUPPORT + +7.1 Finding Information + + On the Agere Systems Web Site you can find the most recent device drivers, + software updates and user documentation. + + World Wide Web: http://www.agere.com + +7.2 Contact Technical Support + + If you encounter problems when installing or using this product, or would + like information about our other "Wireless" products, please contact your + local Authorized "Wireless" Reseller or Agere Systems sales office. + + Addresses and telephone numbers of the Agere Systems sales offices are + listed on our Agere Systems web site. + + When contacting Technical Support, please use the Problem Report Form and + send it to us by Fax or E-Mail. The Problem Report Form 'REPORT.TXT' + (Plain text format) is included on the disk. Alternatively, you can + download the Problem Report Form from the Agere Systems web site. + + Include Product Name, Serial Number and software version number with each + request to help the Support Group helping you. + +============================================================================== + END OF FILE diff --git a/drivers/staging/wlags49_h2/TODO b/drivers/staging/wlags49_h2/TODO new file mode 100644 index 0000000000000000000000000000000000000000..14aa415b1a82acfd238f4b6f760d2d4e838619f0 --- /dev/null +++ b/drivers/staging/wlags49_h2/TODO @@ -0,0 +1,33 @@ +First of all, the best thing would be that this driver becomes obsolte by +adding support for Hermes II and Hermes II.5 cards to the existing orinoco +driver. The orinoco driver currently only supports Hermes I based cards. +Since this will not happen by magic and has not happend until now this +driver provides a stop-gap solution for these type of cards. + +Having said that, the following wishlist comes to mind to make the driver +suitable as fully supported kernel driver. Feel free to expand/enhance the +list. + +TODO: + - verify against a Hermes II.5 card + - verify with WPA encription (both with H2 and H2.5 cards) + - sometimes the card does not initialize correctly, retry mechanisms + are build in to catch most cases but not all + - once the driver runs it is very stable, but I have the impression + some the crittical sections take to long + - the driver is split into a Hermes II and a Hermes II.5 part, it + would be nice to handle both with one module instead of two + - review by the wireless developer community + - verify the code against the coding standards for a propper linux + driver + - resolve license issues (?) + +DONE: + - verified against a Hermes II card (Thomson Speedtouch 110 PCMCIA + card) + - verified with WEP encription + +Please send any patches or complaints about this driver to Greg +Kroah-Hartman and Cc: Henk de Groot +Don't bother the upstream wireless kernel developers about it, they +want nothing to do with it. diff --git a/drivers/staging/wlags49_h2/WARNING.txt b/drivers/staging/wlags49_h2/WARNING.txt new file mode 100644 index 0000000000000000000000000000000000000000..5d12973ba19cf78d85ff3ccdd0e8e372d3174ea2 --- /dev/null +++ b/drivers/staging/wlags49_h2/WARNING.txt @@ -0,0 +1,3 @@ +These sources are shared with the wlags49_h25 driver. Some files are even +exclusively used by that driver. Do not delete them here without looking +at that other driver. diff --git a/drivers/staging/wlags49_h2/ap_h2.c b/drivers/staging/wlags49_h2/ap_h2.c new file mode 100644 index 0000000000000000000000000000000000000000..f5123d2cb4c1bc33f20b1ab02fb13bdb505decc4 --- /dev/null +++ b/drivers/staging/wlags49_h2/ap_h2.c @@ -0,0 +1,3337 @@ +/* + * File: ap_h24.236 + * + * Abstract: This file contains memory image 'fw_image'. + * + * Contents: Total size of the memory image: 51010 bytes. + * Total number of blocks: 4 blocks. + * Block 1 : load address 00000060, 326 bytes. + * Block 2 : load address 00000C16, 6424 bytes. + * Block 3 : load address 001E252E, 444 bytes. + * Block 4 : load address 001F4000, 43816 bytes. + * + * Identity: component id: 32 (variant 2) version 2.36 + * + * Compatibility: + * supplying interface 8 (variant 2) : 2 - 4 + * acting on interface 1 (variant 4) : 6 - 7 + * acting on interface 1 (variant 5) : 6 - 7 + * acting on interface 1 (variant 6) : 6 - 7 + * acting on interface 2 (variant 2) : 1 - 2 + * + * Generated: by g:\fw\fupu3.exe version 4.26 + * + * Commandline: g:\fw\fupu3.exe /f=4 /n=fw_image /i=t2023600.hex + */ + + +#include "hcfcfg.h" // to get hcf_16 etc defined as well as + // possible settings which inluence mdd.h or dhf.h +#include "mdd.h" //to get COMP_ID_STA etc defined +#include "dhf.h" //used to be "fhfmem.h", to get memblock,plugrecord, + +static const hcf_8 fw_image_1_data[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x0D, 0x00, 0x00, + 0x3A, 0x0C, 0x00, 0x00, 0x3A, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, + 0x0A, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xEA, 0x00, 0x00, 0xFF, 0x07, 0x02, 0x00, 0x64, 0x00, 0x64, 0x00, 0x10, 0x27, 0x10, 0x27, + 0x14, 0x00, 0xD0, 0x07, 0xD0, 0x07, 0x10, 0x27, 0x2F, 0x00, 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x10, 0x27, 0x05, 0x00, 0x00, 0x02, 0x00, 0x02, 0x13, 0x00, 0x0A, 0x00, + 0x07, 0x00, 0x03, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x09, 0x2B, 0x09, 0x2B, 0x09, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x14, 0x01, 0x00, 0x40, 0x00, 0x32, 0x00, 0x32, 0x00, + 0x0A, 0x00, 0x02, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +}; /* fw_image_1_data */ + +static const hcf_8 fw_image_2_data[] = { + 0x9B, 0xA7, 0x00, 0x0A, 0x10, 0x01, 0x68, 0xA4, 0xB0, 0x01, 0x84, 0x01, 0x30, 0x33, 0x31, 0x33, + 0x44, 0x44, 0x30, 0x33, 0x31, 0x33, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, 0x32, 0x33, 0x90, 0x00, + 0x78, 0x04, 0xAE, 0xE4, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x84, 0xF8, 0x99, 0xEE, + 0x8D, 0xF6, 0x0D, 0xFF, 0xBD, 0xD6, 0xB1, 0xDE, 0x54, 0x91, 0x50, 0x60, 0x03, 0x02, 0xA9, 0xCE, + 0x7D, 0x56, 0x19, 0xE7, 0x62, 0xB5, 0xE6, 0x4D, 0x9A, 0xEC, 0x45, 0x8F, 0x9D, 0x1F, 0x40, 0x89, + 0x87, 0xFA, 0x15, 0xEF, 0xEB, 0xB2, 0xC9, 0x8E, 0x0B, 0xFB, 0xEC, 0x41, 0x67, 0xB3, 0xFD, 0x5F, + 0xEA, 0x45, 0xBF, 0x23, 0xF7, 0x53, 0x96, 0xE4, 0x5B, 0x9B, 0xC2, 0x75, 0x1C, 0xE1, 0xAE, 0x3D, + 0x6A, 0x4C, 0x5A, 0x6C, 0x41, 0x7E, 0x02, 0xF5, 0x4F, 0x83, 0x5C, 0x68, 0xF4, 0x51, 0x34, 0xD1, + 0x08, 0xF9, 0x93, 0xE2, 0x73, 0xAB, 0x53, 0x62, 0x3F, 0x2A, 0x0C, 0x08, 0x52, 0x95, 0x65, 0x46, + 0x5E, 0x9D, 0x28, 0x30, 0xA1, 0x37, 0x0F, 0x0A, 0xB5, 0x2F, 0x09, 0x0E, 0x36, 0x24, 0x9B, 0x1B, + 0x3D, 0xDF, 0x26, 0xCD, 0x69, 0x4E, 0xCD, 0x7F, 0x9F, 0xEA, 0x1B, 0x12, 0x9E, 0x1D, 0x74, 0x58, + 0x2E, 0x34, 0x2D, 0x36, 0xB2, 0xDC, 0xEE, 0xB4, 0xFB, 0x5B, 0xF6, 0xA4, 0x4D, 0x76, 0x61, 0xB7, + 0xCE, 0x7D, 0x7B, 0x52, 0x3E, 0xDD, 0x71, 0x5E, 0x97, 0x13, 0xF5, 0xA6, 0x68, 0xB9, 0x00, 0x00, + 0x2C, 0xC1, 0x60, 0x40, 0x1F, 0xE3, 0xC8, 0x79, 0xED, 0xB6, 0xBE, 0xD4, 0x46, 0x8D, 0xD9, 0x67, + 0x4B, 0x72, 0xDE, 0x94, 0xD4, 0x98, 0xE8, 0xB0, 0x4A, 0x85, 0x6B, 0xBB, 0x2A, 0xC5, 0xE5, 0x4F, + 0x16, 0xED, 0xC5, 0x86, 0xD7, 0x9A, 0x55, 0x66, 0x94, 0x11, 0xCF, 0x8A, 0x10, 0xE9, 0x06, 0x04, + 0x81, 0xFE, 0xF0, 0xA0, 0x44, 0x78, 0xBA, 0x25, 0xE3, 0x4B, 0xF3, 0xA2, 0xFE, 0x5D, 0xC0, 0x80, + 0x8A, 0x05, 0xAD, 0x3F, 0xBC, 0x21, 0x48, 0x70, 0x04, 0xF1, 0xDF, 0x63, 0xC1, 0x77, 0x75, 0xAF, + 0x63, 0x42, 0x30, 0x20, 0x1A, 0xE5, 0x0E, 0xFD, 0x6D, 0xBF, 0x4C, 0x81, 0x14, 0x18, 0x35, 0x26, + 0x2F, 0xC3, 0xE1, 0xBE, 0xA2, 0x35, 0xCC, 0x88, 0x39, 0x2E, 0x57, 0x93, 0xF2, 0x55, 0x82, 0xFC, + 0x47, 0x7A, 0xAC, 0xC8, 0xE7, 0xBA, 0x2B, 0x32, 0x95, 0xE6, 0xA0, 0xC0, 0x98, 0x19, 0xD1, 0x9E, + 0x7F, 0xA3, 0x66, 0x44, 0x7E, 0x54, 0xAB, 0x3B, 0x83, 0x0B, 0xCA, 0x8C, 0x29, 0xC7, 0xD3, 0x6B, + 0x3C, 0x28, 0x79, 0xA7, 0xE2, 0xBC, 0x1D, 0x16, 0x76, 0xAD, 0x3B, 0xDB, 0x56, 0x64, 0x4E, 0x74, + 0x1E, 0x14, 0xDB, 0x92, 0x0A, 0x0C, 0x6C, 0x48, 0xE4, 0xB8, 0x5D, 0x9F, 0x6E, 0xBD, 0xEF, 0x43, + 0xA6, 0xC4, 0xA8, 0x39, 0xA4, 0x31, 0x37, 0xD3, 0x8B, 0xF2, 0x32, 0xD5, 0x43, 0x8B, 0x59, 0x6E, + 0xB7, 0xDA, 0x8C, 0x01, 0x64, 0xB1, 0xD2, 0x9C, 0xE0, 0x49, 0xB4, 0xD8, 0xFA, 0xAC, 0x07, 0xF3, + 0x25, 0xCF, 0xAF, 0xCA, 0x8E, 0xF4, 0xE9, 0x47, 0x18, 0x10, 0xD5, 0x6F, 0x88, 0xF0, 0x6F, 0x4A, + 0x72, 0x5C, 0x24, 0x38, 0xF1, 0x57, 0xC7, 0x73, 0x51, 0x97, 0x23, 0xCB, 0x7C, 0xA1, 0x9C, 0xE8, + 0x21, 0x3E, 0xDD, 0x96, 0xDC, 0x61, 0x86, 0x0D, 0x85, 0x0F, 0x90, 0xE0, 0x42, 0x7C, 0xC4, 0x71, + 0xAA, 0xCC, 0xD8, 0x90, 0x05, 0x06, 0x01, 0xF7, 0x12, 0x1C, 0xA3, 0xC2, 0x5F, 0x6A, 0xF9, 0xAE, + 0xD0, 0x69, 0x91, 0x17, 0x58, 0x99, 0x27, 0x3A, 0xB9, 0x27, 0x38, 0xD9, 0x13, 0xEB, 0xB3, 0x2B, + 0x33, 0x22, 0xBB, 0xD2, 0x70, 0xA9, 0x89, 0x07, 0xA7, 0x33, 0xB6, 0x2D, 0x22, 0x3C, 0x92, 0x15, + 0x20, 0xC9, 0x49, 0x87, 0xFF, 0xAA, 0x78, 0x50, 0x7A, 0xA5, 0x8F, 0x03, 0xF8, 0x59, 0x80, 0x09, + 0x17, 0x1A, 0xDA, 0x65, 0x31, 0xD7, 0xC6, 0x84, 0xB8, 0xD0, 0xC3, 0x82, 0xB0, 0x29, 0x77, 0x5A, + 0x11, 0x1E, 0xCB, 0x7B, 0xFC, 0xA8, 0xD6, 0x6D, 0x3A, 0x2C, 0x00, 0x30, 0x00, 0x31, 0x00, 0x33, + 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x38, 0x00, 0x3A, 0x00, 0x3B, + 0x00, 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, 0x3F, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x02, 0x14, + 0x05, 0x32, 0x0B, 0x37, 0x08, 0x50, 0x0B, 0x6E, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x3F, 0x00, + 0x0C, 0x00, 0x30, 0x00, 0x03, 0x00, 0x0F, 0x00, 0x3E, 0x00, 0x3C, 0x00, 0x02, 0x00, 0x04, 0x00, + 0x0A, 0x00, 0x0B, 0x00, 0x10, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x63, 0x00, 0x20, 0x00, 0x63, 0x00, 0x63, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x10, + 0x9E, 0x10, 0x56, 0x10, 0x98, 0x10, 0x5C, 0x10, 0x92, 0x10, 0x62, 0x10, 0x8C, 0x10, 0x68, 0x10, + 0x86, 0x10, 0x6E, 0x10, 0x80, 0x10, 0x74, 0x10, 0x7A, 0x10, 0x07, 0x01, 0x00, 0x00, 0x0A, 0x22, + 0x00, 0x04, 0x08, 0x01, 0x00, 0x00, 0x0A, 0x26, 0x00, 0x04, 0x09, 0x01, 0x00, 0x00, 0x0A, 0x2A, + 0x00, 0x04, 0x0A, 0x01, 0x00, 0x00, 0x0A, 0x2E, 0x00, 0x04, 0x0B, 0x01, 0x00, 0x00, 0x10, 0x24, + 0x04, 0x04, 0x0C, 0x01, 0x00, 0x00, 0x10, 0x28, 0x04, 0x04, 0x0D, 0x01, 0x00, 0x00, 0x10, 0x2C, + 0x04, 0x04, 0x0E, 0x01, 0x00, 0x00, 0x10, 0x30, 0x04, 0x04, 0x0F, 0x01, 0x00, 0x00, 0x16, 0x34, + 0x08, 0x04, 0x10, 0x01, 0x00, 0x00, 0x16, 0x38, 0x08, 0x04, 0x11, 0x01, 0x00, 0x00, 0x16, 0x3C, + 0x08, 0x04, 0x12, 0x01, 0x00, 0x00, 0x16, 0x40, 0x08, 0x04, 0x13, 0x01, 0x00, 0x00, 0x17, 0x64, + 0x0C, 0x0B, 0x14, 0x01, 0x00, 0x00, 0x17, 0x68, 0x0C, 0x0B, 0x15, 0x01, 0x00, 0x00, 0x17, 0x6C, + 0x0C, 0x0B, 0x16, 0x01, 0x00, 0x00, 0x17, 0x70, 0x0C, 0x0B, 0x17, 0x01, 0x00, 0x00, 0x17, 0x74, + 0x0C, 0x0B, 0x18, 0x01, 0x00, 0x00, 0x17, 0x78, 0x0C, 0x0B, 0x19, 0x01, 0x00, 0x00, 0x17, 0x7C, + 0x0C, 0x0B, 0x1A, 0x01, 0x00, 0x00, 0x17, 0x80, 0x0C, 0x0B, 0x1B, 0x01, 0x00, 0x00, 0x17, 0x84, + 0x0C, 0x0B, 0x1C, 0x01, 0x00, 0x00, 0x17, 0x88, 0x0C, 0x0B, 0x1D, 0x01, 0x00, 0x00, 0x17, 0x8C, + 0x0C, 0x0B, 0x1E, 0x01, 0x00, 0x00, 0x1D, 0x95, 0x17, 0x04, 0x1F, 0x01, 0x00, 0x00, 0x1D, 0x99, + 0x17, 0x04, 0x20, 0x01, 0x00, 0x00, 0x1D, 0x9D, 0x17, 0x04, 0x21, 0x01, 0x00, 0x00, 0x1D, 0xA1, + 0x17, 0x04, 0x22, 0x01, 0x00, 0x00, 0x0E, 0xA5, 0x00, 0x00, 0xC0, 0x10, 0xE0, 0x10, 0x00, 0x11, + 0x20, 0x11, 0x78, 0x11, 0xC8, 0x10, 0xE8, 0x10, 0x08, 0x11, 0x28, 0x11, 0x80, 0x11, 0xD0, 0x10, + 0xF0, 0x10, 0x10, 0x11, 0x30, 0x11, 0x88, 0x11, 0xD8, 0x10, 0xF8, 0x10, 0x18, 0x11, 0x38, 0x11, + 0x90, 0x11, 0x40, 0x11, 0x48, 0x11, 0x50, 0x11, 0x58, 0x11, 0x60, 0x11, 0x68, 0x11, 0x70, 0x11, + 0x98, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD2, 0x14, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xEB, 0xBA, 0xEB, + 0xDF, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, + 0x57, 0xEB, 0x90, 0xF1, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0xD6, 0xED, + 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, + 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x2F, 0xEE, + 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, + 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0xA4, 0xED, 0xBE, 0xED, + 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x7F, 0xF4, 0x19, 0xEC, + 0x2C, 0xEC, 0xDC, 0xEC, 0xE0, 0xEC, 0x57, 0xEB, 0x57, 0xEB, 0x8F, 0xED, 0x84, 0xE3, 0x59, 0xE3, + 0xD7, 0xE3, 0x28, 0xE4, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xEB, 0xF6, 0xEB, 0x72, 0xF0, 0x72, 0xF0, + 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC, 0x89, 0xEE, 0x45, 0xF0, 0x5A, 0x00, 0x02, 0x00, 0xF9, 0xFF, + 0x89, 0xEE, 0x9F, 0xEE, 0xCC, 0x00, 0x02, 0x00, 0xF7, 0xFF, 0x89, 0xEE, 0x9F, 0xEE, 0xB6, 0x1F, + 0x06, 0x00, 0xF0, 0xFF, 0x89, 0xEE, 0x73, 0xEE, 0x00, 0x00, 0x00, 0x02, 0xF6, 0xFF, 0x89, 0xEE, + 0x9F, 0xEE, 0x6C, 0x00, 0x02, 0x00, 0xF4, 0xFF, 0x89, 0xEE, 0x9F, 0xEE, 0x6A, 0x01, 0x02, 0x00, + 0xF5, 0xFF, 0x89, 0xEE, 0x4E, 0xF0, 0xA8, 0x1F, 0x02, 0x00, 0xE0, 0xFF, 0x89, 0xEE, 0x9F, 0xEE, + 0xEE, 0x21, 0x02, 0x00, 0xE1, 0xFF, 0x89, 0xEE, 0x9F, 0xEE, 0xF0, 0x21, 0x02, 0x00, 0xE2, 0xFF, + 0x89, 0xEE, 0x9F, 0xEE, 0xF2, 0x21, 0x02, 0x00, 0xE3, 0xFF, 0x89, 0xEE, 0x9F, 0xEE, 0xEA, 0x21, + 0x02, 0x00, 0x03, 0xFC, 0x89, 0xEE, 0xE5, 0xEF, 0x7C, 0x21, 0x02, 0x00, 0x04, 0xFC, 0x89, 0xEE, + 0x99, 0xEE, 0xBE, 0x1F, 0x22, 0x00, 0x06, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0xA6, 0x1F, 0x02, 0x00, + 0x07, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x02, 0x20, 0x02, 0x00, 0x0E, 0xFC, 0x89, 0xEE, 0xF7, 0xEF, + 0x0C, 0x20, 0x22, 0x00, 0xB1, 0xFC, 0x89, 0xEE, 0x58, 0xF2, 0x2C, 0x21, 0x02, 0x00, 0x20, 0xFC, + 0x89, 0xEE, 0x9F, 0xEE, 0x32, 0x20, 0x02, 0x00, 0x25, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x3C, 0x20, + 0x02, 0x00, 0x26, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x3E, 0x20, 0x02, 0x00, 0x27, 0xFC, 0x89, 0xEE, + 0x9F, 0xEE, 0x40, 0x20, 0x02, 0x00, 0xB2, 0xFC, 0x89, 0xEE, 0x99, 0xEE, 0x50, 0x21, 0x22, 0x00, + 0xC1, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x98, 0x21, 0x20, 0x00, 0xB0, 0xFC, 0x69, 0xEE, 0x5D, 0xF2, + 0x00, 0x00, 0x00, 0x00, 0xC4, 0xFC, 0x69, 0xEE, 0x68, 0xF0, 0x00, 0x00, 0x08, 0x00, 0xC8, 0xFC, + 0x69, 0xEE, 0x63, 0xF0, 0x00, 0x00, 0x08, 0x00, 0xB4, 0xFC, 0x69, 0xEE, 0x9B, 0xF2, 0x00, 0x00, + 0x00, 0x00, 0xB6, 0xFC, 0x69, 0xEE, 0x4E, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xFC, 0x69, 0xEE, + 0x90, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xFC, 0x69, 0xEE, 0xED, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0xB5, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0xE6, 0x21, 0x02, 0x00, 0xB9, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, + 0xE8, 0x21, 0x02, 0x00, 0x90, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0xEC, 0x21, 0x02, 0x00, 0x23, 0xFC, + 0x89, 0xEE, 0x9F, 0xEE, 0x38, 0x20, 0x02, 0x00, 0x29, 0xFC, 0x48, 0xEF, 0xF5, 0xEE, 0x00, 0x00, + 0x00, 0x00, 0xC2, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x74, 0x21, 0x02, 0x00, 0x32, 0xFC, 0x89, 0xEE, + 0x9F, 0xEE, 0x60, 0x01, 0x02, 0x00, 0x33, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x62, 0x01, 0x02, 0x00, + 0x10, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0xAE, 0x1F, 0x02, 0x00, 0x11, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, + 0x46, 0x20, 0x06, 0x00, 0x12, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x4C, 0x20, 0x06, 0x00, 0x13, 0xFC, + 0x89, 0xEE, 0x9F, 0xEE, 0x52, 0x20, 0x06, 0x00, 0x14, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x58, 0x20, + 0x06, 0x00, 0x15, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x5E, 0x20, 0x06, 0x00, 0x16, 0xFC, 0x89, 0xEE, + 0x9F, 0xEE, 0x64, 0x20, 0x06, 0x00, 0x17, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x2E, 0x20, 0x02, 0x00, + 0x83, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x6E, 0x01, 0x02, 0x00, 0x97, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, + 0x6C, 0x01, 0x02, 0x00, 0x98, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE4, 0x00, 0x02, 0x00, 0x99, 0xFC, + 0x31, 0xF0, 0x1F, 0xF0, 0xE4, 0x02, 0x02, 0x00, 0x9A, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE4, 0x04, + 0x02, 0x00, 0x9B, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE4, 0x06, 0x02, 0x00, 0x9C, 0xFC, 0x31, 0xF0, + 0x1F, 0xF0, 0xE4, 0x08, 0x02, 0x00, 0x9D, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE4, 0x0A, 0x02, 0x00, + 0x18, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x30, 0x20, 0x02, 0x00, 0x22, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, + 0x36, 0x20, 0x02, 0x00, 0x24, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x3A, 0x20, 0x02, 0x00, 0xC0, 0xFC, + 0x69, 0xEE, 0x61, 0xF0, 0x00, 0x00, 0x06, 0x00, 0x9E, 0xFC, 0x89, 0xEE, 0x17, 0xF0, 0x70, 0x01, + 0x02, 0x00, 0x9F, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE6, 0x00, 0x02, 0x00, 0xA0, 0xFC, 0x31, 0xF0, + 0x1F, 0xF0, 0xE6, 0x02, 0x02, 0x00, 0xA1, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE6, 0x04, 0x02, 0x00, + 0xA2, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE6, 0x06, 0x02, 0x00, 0xA3, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, + 0xE6, 0x08, 0x02, 0x00, 0xA4, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE6, 0x0A, 0x02, 0x00, 0x20, 0xFD, + 0xBA, 0xEE, 0x73, 0xEE, 0x53, 0xF5, 0x08, 0x00, 0x21, 0xFD, 0xBA, 0xEE, 0x73, 0xEE, 0x57, 0xF5, + 0x0A, 0x00, 0x22, 0xFD, 0xBA, 0xEE, 0x73, 0xEE, 0x5C, 0xF5, 0x16, 0x00, 0x23, 0xFD, 0xBA, 0xEE, + 0x73, 0xEE, 0x67, 0xF5, 0x0A, 0x00, 0x10, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0x34, 0x01, 0x02, 0x00, + 0x45, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0xCC, 0x00, 0x02, 0x00, 0x47, 0xFD, 0x89, 0xEE, 0x73, 0xEE, + 0x38, 0x01, 0x02, 0x00, 0x48, 0xFD, 0x9E, 0xEF, 0x73, 0xEE, 0x60, 0x01, 0x02, 0x00, 0x49, 0xFD, + 0x9E, 0xEF, 0x73, 0xEE, 0x62, 0x01, 0x02, 0x00, 0x4A, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0x58, 0x01, + 0x02, 0x00, 0x4B, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0x5A, 0x01, 0x02, 0x00, 0x4D, 0xFD, 0xBA, 0xEE, + 0x73, 0xEE, 0x6C, 0xF5, 0x04, 0x00, 0x4F, 0xFD, 0xB2, 0xEF, 0x73, 0xEE, 0x80, 0x21, 0x02, 0x00, + 0xC0, 0xFD, 0xBA, 0xEE, 0x73, 0xEE, 0x6E, 0xF5, 0x02, 0x00, 0xC2, 0xFD, 0xA8, 0xEF, 0x73, 0xEE, + 0x00, 0x00, 0x02, 0x00, 0xC3, 0xFD, 0xBA, 0xEE, 0x73, 0xEE, 0x6F, 0xF5, 0x02, 0x00, 0x40, 0xFD, + 0xB2, 0xEE, 0x73, 0xEE, 0x78, 0x01, 0x02, 0x00, 0x24, 0xFD, 0xD8, 0xEF, 0x73, 0xEE, 0x00, 0x00, + 0x02, 0x00, 0x91, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0x86, 0x1B, 0x02, 0x00, 0x93, 0xFD, 0x89, 0xEE, + 0x73, 0xEE, 0x8C, 0x1B, 0x02, 0x00, 0xC1, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0xCA, 0x00, 0x02, 0x00, + 0xC6, 0xFD, 0xE7, 0xEE, 0x73, 0xEE, 0x8E, 0x21, 0x0A, 0x00, 0x89, 0xFD, 0x5F, 0xEF, 0x73, 0xEE, + 0x00, 0x00, 0x00, 0x00, 0x8A, 0xFD, 0xD7, 0xEE, 0x73, 0xEE, 0xC0, 0x21, 0x24, 0x00, 0x46, 0xFD, + 0x89, 0xEE, 0x73, 0xEE, 0x7A, 0x01, 0x06, 0x00, 0x86, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0xB6, 0x1F, + 0x06, 0x00, 0x87, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0xB8, 0x21, 0x06, 0x00, 0x8B, 0xFD, 0x7A, 0xF3, + 0x73, 0xEE, 0x00, 0x00, 0x12, 0x00, 0x8E, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0xB8, 0x12, 0x02, 0x00, + 0x80, 0xFD, 0xBC, 0xEF, 0x73, 0xEE, 0x1C, 0x00, 0x02, 0x00, 0x81, 0xFD, 0xBC, 0xEF, 0x73, 0xEE, + 0x1C, 0x02, 0x02, 0x00, 0x82, 0xFD, 0xBC, 0xEF, 0x73, 0xEE, 0x1C, 0x04, 0x02, 0x00, 0x83, 0xFD, + 0xBC, 0xEF, 0x73, 0xEE, 0x1C, 0x06, 0x02, 0x00, 0x84, 0xFD, 0xBC, 0xEF, 0x73, 0xEE, 0x1C, 0x08, + 0x02, 0x00, 0x85, 0xFD, 0xBC, 0xEF, 0x73, 0xEE, 0x1C, 0x0A, 0x02, 0x00, 0x00, 0xF1, 0x46, 0x00, + 0x2D, 0xEE, 0xF8, 0x00, 0x00, 0x03, 0x8A, 0xEA, 0x1F, 0x00, 0x36, 0x01, 0xCA, 0x00, 0x96, 0x01, + 0xCE, 0x00, 0xFC, 0x00, 0x78, 0x01, 0xDA, 0x1E, 0x1A, 0x01, 0x86, 0x1B, 0xC8, 0x00, 0x00, 0x00, + 0xCE, 0x12, 0x00, 0x00, 0xD2, 0x14, 0x14, 0x01, 0x03, 0x00, 0xAE, 0x00, 0xE4, 0x00, 0x3C, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x77, 0xB4, 0xEA, 0xB3, 0x26, 0xB5, 0x2F, 0xB5, 0xFB, 0xB3, 0xA4, 0xB4, 0x69, 0xB4, 0xE7, 0xC5, + 0x4A, 0xC5, 0xE7, 0xC5, 0xBE, 0xC5, 0x54, 0xC5, 0x48, 0xC5, 0x06, 0xC6, 0x17, 0xC6, 0x17, 0xC6, + 0x17, 0xC6, 0x20, 0xC6, 0x3B, 0xC6, 0x98, 0xC6, 0xB4, 0xC6, 0xBF, 0xC5, 0xD2, 0xC5, 0xA6, 0xC5, + 0x10, 0x00, 0x12, 0x00, 0x13, 0x00, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x30, 0x00, 0x31, 0x00, + 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, + 0x3A, 0x00, 0x00, 0x00, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, + 0x14, 0x01, 0x14, 0x01, 0xF3, 0x02, 0xAD, 0x03, 0x60, 0x04, 0x04, 0x05, 0x07, 0x06, 0x08, 0x07, + 0x0A, 0x08, 0x16, 0x09, 0x44, 0x0A, 0x04, 0x0B, 0x40, 0x0C, 0x80, 0x0D, 0x00, 0x0E, 0x84, 0x0F, + 0x01, 0x10, 0x10, 0x11, 0x02, 0x14, 0x40, 0x20, 0x32, 0x21, 0x32, 0x22, 0x04, 0x23, 0x01, 0x24, + 0x0F, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x28, 0x00, 0x29, 0x00, 0x2A, 0x01, 0x2B, 0x06, 0x2C, + 0x00, 0x38, 0x00, 0x39, 0xD6, 0x3A, 0x00, 0x3B, 0x00, 0x3C, 0x14, 0x3D, 0x7F, 0x3E, 0x00, 0x3F, + 0x68, 0x40, 0x75, 0x41, 0x07, 0x42, 0x07, 0x43, 0x00, 0x45, 0x3B, 0x4A, 0x00, 0x4B, 0x00, 0x4C, + 0x0F, 0x4D, 0x02, 0x75, 0x00, 0x76, 0x80, 0x00, 0x08, 0x01, 0x09, 0x01, 0x09, 0x01, 0x0A, 0x01, + 0x0A, 0x01, 0x0B, 0x01, 0x0B, 0x01, 0x0C, 0x01, 0x0C, 0x01, 0x0D, 0x01, 0x0D, 0x01, 0x0E, 0x01, + 0x0E, 0x01, 0x0F, 0x01, 0x0F, 0x01, 0x10, 0x01, 0x10, 0x01, 0x11, 0x01, 0x11, 0x01, 0x12, 0x01, + 0x12, 0x01, 0x13, 0x01, 0x13, 0x01, 0x14, 0x01, 0x14, 0x01, 0x15, 0x01, 0x15, 0x01, 0x16, 0x01, + 0x16, 0x01, 0x17, 0x01, 0x17, 0x01, 0x18, 0x01, 0x18, 0x01, 0x19, 0x01, 0x19, 0x01, 0x4D, 0x01, + 0x4D, 0x01, 0x4E, 0x01, 0x4E, 0x01, 0x4F, 0x01, 0x4F, 0x01, 0x50, 0x01, 0x50, 0x01, 0x51, 0x01, + 0x51, 0x01, 0x52, 0x01, 0x52, 0x01, 0x53, 0x01, 0x53, 0x01, 0x54, 0x01, 0x54, 0x01, 0x65, 0x01, + 0x65, 0x01, 0x66, 0x01, 0x66, 0x01, 0x67, 0x01, 0x67, 0x01, 0x68, 0x01, 0x68, 0x01, 0x69, 0x01, + 0x69, 0x01, 0x6A, 0x01, 0x6A, 0x01, 0x6B, 0x01, 0x6B, 0x01, 0x6C, 0x01, 0x6C, 0x01, 0x6D, 0x01, + 0x6D, 0x01, 0x6E, 0x01, 0x6E, 0x01, 0x6F, 0x01, 0x6F, 0x01, 0x70, 0x01, 0x70, 0x01, 0x71, 0x01, + 0x71, 0x01, 0x72, 0x01, 0x72, 0x01, 0x73, 0x01, 0x73, 0x01, 0x74, 0x01, 0x74, 0x01, 0x75, 0x01, + 0x75, 0x01, 0x76, 0x01, 0x76, 0x01, 0x77, 0x01, 0x77, 0x01, 0x78, 0x01, 0x78, 0x01, 0x79, 0x01, + 0x79, 0x01, 0x7A, 0x01, 0x7A, 0x01, 0x7B, 0x01, 0x7B, 0x01, 0x7C, 0x01, 0x7C, 0x01, 0x7D, 0x01, + 0x7D, 0x01, 0x7E, 0x01, 0x7E, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, + 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, + 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, + 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, + 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, + 0x80, 0x12, 0x80, 0x12, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, + 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, + 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, + 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x22, 0x46, 0x22, 0x46, + 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, + 0x22, 0x46, 0x23, 0x46, 0x23, 0x46, 0x23, 0x46, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, + 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, + 0x1C, 0x47, 0x1D, 0x47, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0xDA, 0x48, + 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0x33, 0x48, + 0x78, 0x49, 0x78, 0x49, 0x79, 0x49, 0x79, 0x49, 0x79, 0x49, 0x79, 0x49, 0x7A, 0x49, 0x7A, 0x49, + 0x7A, 0x49, 0x7A, 0x49, 0x7B, 0x49, 0x7B, 0x49, 0x7B, 0x49, 0x7C, 0x49, 0x32, 0x00, 0x46, 0x00, + 0x5A, 0x00, 0x6E, 0x00, 0x82, 0x00, 0x96, 0x00, 0xAA, 0x00, 0xBE, 0x00, 0xD2, 0x00, 0xE6, 0x00, + 0xFA, 0x00, 0x0E, 0x01, 0x22, 0x01, 0x52, 0x01, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x15, 0x00, 0x6E, 0x6F, 0x6E, 0x2D, 0x73, 0x70, + 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x21, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x48, 0x45, 0x52, 0x4D, 0x45, 0x53, 0x20, 0x32, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x15, 0x00, 0x6E, 0x6F, 0x6E, 0x2D, 0x73, 0x70, + 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x21, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x48, 0x45, 0x52, 0x4D, 0x45, 0x53, 0x20, 0x32, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x69, 0x72, 0x73, 0x74, 0x20, + 0x57, 0x61, 0x76, 0x65, 0x4C, 0x41, 0x4E, 0x20, 0x49, 0x49, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x02, 0x01, 0x82, 0x84, 0x8B, 0x96, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xDD, 0x00, 0x50, 0xF2, 0x01, + 0x01, 0x00, 0x00, 0x50, 0xF2, 0x05, 0x02, 0x00, 0x00, 0x50, 0xF2, 0x02, 0x00, 0x50, 0xF2, 0x04, + 0x02, 0x00, 0x00, 0x50, 0xF2, 0x00, 0x00, 0x50, 0xF2, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, + 0x15, 0x00, 0x02, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x04, 0x00, 0x10, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x04, 0x00, 0x15, 0x00, 0x20, 0x00, 0x11, 0x00, 0x20, 0x00, 0x1E, 0x1F, 0x8E, 0x21, + 0x00, 0x23, 0xDA, 0x22, 0x04, 0x23, 0xC0, 0x21, 0xFF, 0xFF, 0xFF, 0xFF, 0x34, 0x23, 0x00, 0x00, + 0x50, 0x21, 0x8E, 0x21, 0xFF, 0xFF, 0x00, 0x00, 0x1E, 0x1F, 0x8E, 0x21, 0x00, 0x23, 0xFF, 0xFF, + 0x04, 0x23, 0xC0, 0x21, 0xFF, 0xFF, 0xFF, 0xFF, 0x34, 0x23, 0x00, 0x00, 0x8E, 0x21, 0x3C, 0x23, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00, 0x06, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, + 0x00, 0x60, 0x1D, 0x00, 0x00, 0x00, 0x0D, 0x81, 0x00, 0x60, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + +}; /* fw_image_2_data */ + +static const hcf_8 fw_image_3_data[] = { + 0x3F, 0x41, 0xA5, 0x4C, 0x50, 0x37, 0x04, 0x00, 0x01, 0xB9, 0x41, 0x5F, 0xB5, 0x60, 0x55, 0xE0, + 0x0C, 0x60, 0x10, 0x62, 0xA2, 0xD3, 0x01, 0x60, 0x01, 0x65, 0xD4, 0x80, 0x5A, 0xD1, 0x0F, 0x02, + 0x5A, 0xD3, 0x3E, 0x60, 0x00, 0x66, 0xE0, 0x87, 0x40, 0x4A, 0xEA, 0x60, 0x88, 0x61, 0x64, 0x44, + 0xC8, 0x84, 0x0C, 0x63, 0xAA, 0x46, 0x58, 0xD0, 0xAA, 0x46, 0x59, 0xD8, 0xFB, 0x1F, 0x08, 0x60, + 0x00, 0x63, 0xFA, 0x60, 0x00, 0x65, 0xBD, 0xD3, 0xA3, 0xD3, 0x02, 0xA8, 0xD4, 0x80, 0x61, 0x02, + 0x60, 0x02, 0x26, 0x60, 0x6A, 0x61, 0x3C, 0x60, 0x00, 0x66, 0x41, 0x4B, 0x2B, 0x41, 0x26, 0x60, + 0xB2, 0x7C, 0xD1, 0x80, 0xA1, 0xD2, 0x25, 0x05, 0x59, 0xD0, 0x60, 0x45, 0x59, 0xD2, 0x44, 0x47, + 0xE0, 0x87, 0x40, 0x4A, 0x59, 0xD2, 0x59, 0x8B, 0x40, 0x4C, 0x08, 0x60, 0x00, 0x63, 0xBE, 0xD3, + 0xBD, 0xD1, 0xEC, 0x18, 0xD4, 0x80, 0xEA, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, + 0x67, 0x44, 0xC0, 0x84, 0xE0, 0x85, 0x2C, 0x44, 0xD4, 0x80, 0x63, 0x41, 0x01, 0x06, 0x65, 0x44, + 0xC8, 0x83, 0xAA, 0x46, 0x59, 0xD1, 0x27, 0xD8, 0x5A, 0x87, 0xFC, 0x1F, 0xAA, 0x46, 0x2B, 0x41, + 0xD5, 0x01, 0x26, 0x60, 0xB2, 0x61, 0x41, 0x4B, 0x2B, 0x41, 0x26, 0x60, 0xEA, 0x7C, 0xD1, 0x80, + 0xA1, 0xD2, 0x27, 0x05, 0x59, 0xD0, 0x60, 0x45, 0x59, 0xD2, 0x44, 0x47, 0xE0, 0x87, 0x40, 0x4A, + 0x59, 0xD2, 0x59, 0x8B, 0x40, 0x4C, 0x08, 0x60, 0x00, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, 0xEC, 0x18, + 0xD4, 0x80, 0xEA, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x04, 0xA3, 0xA3, 0xD1, + 0x5A, 0x88, 0x2C, 0x43, 0xD3, 0x80, 0xFF, 0xFF, 0x01, 0x06, 0x64, 0x43, 0xCF, 0x83, 0xAA, 0x46, + 0x60, 0xFE, 0x28, 0xD1, 0x5E, 0x88, 0x27, 0xD8, 0x5A, 0x87, 0xFB, 0x1F, 0x20, 0xFE, 0xAA, 0x46, + 0xD3, 0x01, 0xB8, 0xFE, 0xB9, 0xFE, 0xBA, 0xFE, 0xBB, 0xFE, 0xBD, 0xFE, 0xBF, 0xFE, 0x21, 0x60, + 0x80, 0x62, 0xA2, 0xD3, 0x12, 0x63, 0x60, 0x40, 0x01, 0x27, 0x05, 0x00, 0x0B, 0x60, 0xEA, 0x62, + 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0xA2, 0x60, 0x49, 0x78, 0xFF, 0xFF, 0xF1, 0xFF, 0x94, 0x48, + 0x1F, 0x00, 0x04, 0x00, 0xF2, 0xFF, 0x98, 0x48, 0x1F, 0x00, 0x04, 0x00, 0xFB, 0xFF, 0xA0, 0x48, + 0x1F, 0x00, 0x04, 0x00, 0xF1, 0xFF, 0xF2, 0x4D, 0x1F, 0x00, 0x04, 0x00, 0xF2, 0xFF, 0xF6, 0x4D, + 0x1F, 0x00, 0x04, 0x00, 0xFB, 0xFF, 0xFE, 0x4D, 0x1F, 0x00, 0x04, 0x00, 0x86, 0xFD, 0xB6, 0x1F, + 0x00, 0x00, 0x06, 0x00, 0x10, 0xFD, 0x34, 0x01, 0x00, 0x00, 0x02, 0x00, 0x14, 0xFD, 0x7E, 0x21, + 0x00, 0x00, 0x0A, 0x00, 0x20, 0xFA, 0xFA, 0x1D, 0x00, 0x00, 0x0E, 0x00, 0x21, 0xFA, 0xDE, 0x1D, + 0x00, 0x00, 0x0E, 0x00, 0x22, 0xFA, 0x16, 0x1E, 0x00, 0x00, 0x0E, 0x00, 0x23, 0xFA, 0xCA, 0x1C, + 0x00, 0x00, 0x01, 0x00, 0x24, 0xFA, 0xBE, 0x1E, 0x00, 0x00, 0x0E, 0x00, 0x25, 0xFA, 0xDE, 0x1C, + 0x00, 0x00, 0x80, 0x00, 0x26, 0xFA, 0xC4, 0x1C, 0x00, 0x00, 0x01, 0x00, + +}; /* fw_image_3_data */ + +static const hcf_8 fw_image_4_data[] = { + 0xA6, 0x60, 0x25, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA6, 0x60, 0x0B, 0x78, 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA6, 0x60, 0x11, 0x78, 0xC4, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA5, 0x60, 0x61, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x44, 0xFF, 0x20, 0x54, 0xCD, 0xE2, 0xA6, 0x60, 0x23, 0x78, 0x08, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA6, 0x60, 0x25, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA6, 0x60, 0x25, 0x78, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA6, 0x60, 0x25, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAC, 0x60, 0x81, 0x78, 0x4C, 0x4E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAC, 0x60, 0x18, 0x78, 0x4C, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC4, 0xE2, 0x84, 0xFF, 0x22, 0x58, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA7, 0x60, 0xC4, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0xE2, 0xAC, 0x60, 0x31, 0x78, 0x95, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBF, 0x60, 0x76, 0x78, 0x64, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAC, 0x60, 0x8C, 0x78, 0xA4, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAC, 0x60, 0x72, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB2, 0x60, 0xD1, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB2, 0x60, 0xFE, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB1, 0x60, 0x90, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB1, 0x60, 0xC0, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB1, 0x60, 0xC0, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB4, 0x60, 0x73, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB1, 0x60, 0xC3, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x60, 0x83, 0x64, 0x80, 0x29, 0x09, 0xFB, 0xB2, 0x60, 0x99, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC0, 0x60, 0x29, 0x78, 0x40, 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, + 0xBF, 0x60, 0xB4, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBE, 0x60, 0x78, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBD, 0x60, 0xE8, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB5, 0x60, 0x96, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA1, 0xFF, 0xFF, 0xFF, 0x83, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC0, 0x60, 0x9F, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xB0, 0xFF, 0xB1, 0xFF, 0x40, 0xFF, 0x43, 0xFF, 0xC0, 0x60, 0x9A, 0x78, 0x44, 0xFF, 0xFF, 0x01, + 0xC0, 0x60, 0x9F, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xC6, 0x60, 0x66, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xC0, 0x60, 0x9A, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xC0, 0x60, 0x99, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xC7, 0x60, 0x26, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE5, 0x60, 0x0E, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC7, 0x60, 0x2E, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC7, 0x60, 0x2E, 0x78, 0x24, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE3, 0x60, 0x45, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC7, 0x60, 0x2E, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC7, 0x60, 0x2E, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC7, 0x60, 0x2E, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xEB, 0x60, 0x5B, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xEB, 0x60, 0x87, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xEB, 0x60, 0xA0, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xEB, 0x60, 0x84, 0x78, 0x28, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xEB, 0x60, 0x84, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xEB, 0x60, 0x84, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xEB, 0x60, 0x84, 0x78, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x60, 0x87, 0x64, 0x80, 0x29, 0x09, 0xFB, 0x47, 0xFF, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x87, 0xF3, 0x88, 0xF3, 0xDC, 0x81, 0x00, 0x7C, 0x01, 0x00, 0x00, 0xFA, 0x60, 0x46, 0xFE, 0x63, + 0xA3, 0xD8, 0xFE, 0x1F, 0xCD, 0x81, 0xD8, 0x84, 0xF8, 0x02, 0x87, 0xF3, 0x88, 0xF5, 0xDC, 0x81, + 0x80, 0x67, 0x40, 0x4A, 0x14, 0x60, 0x02, 0x65, 0x01, 0x7C, 0x07, 0x18, 0x2A, 0x43, 0x02, 0xFC, + 0x5F, 0x8A, 0x8E, 0xF8, 0x70, 0xF8, 0x00, 0xF4, 0xF8, 0x01, 0x2E, 0x58, 0xFF, 0xFF, 0x89, 0xF5, + 0x06, 0x64, 0x66, 0x43, 0x00, 0x7C, 0x63, 0x46, 0xFE, 0x63, 0xA3, 0xD8, 0xFE, 0x1F, 0xCC, 0x84, + 0x66, 0x43, 0xDB, 0x83, 0xF8, 0x02, 0x14, 0x60, 0x02, 0x65, 0x09, 0x60, 0x2B, 0x7C, 0x89, 0xF3, + 0x06, 0x61, 0x60, 0x46, 0x01, 0x63, 0x72, 0xF8, 0x00, 0xFC, 0x63, 0x47, 0x06, 0xFA, 0x72, 0xF8, + 0x8E, 0xF8, 0xDF, 0x83, 0x66, 0x44, 0xCD, 0x81, 0x02, 0xA6, 0xF5, 0x02, 0x89, 0xF3, 0x06, 0x61, + 0x60, 0x46, 0x03, 0x7C, 0x73, 0xF8, 0x66, 0x44, 0xCD, 0x81, 0x02, 0xA6, 0xFB, 0x02, 0x2E, 0x58, + 0xFF, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x0A, 0x00, 0x42, 0x60, 0x09, 0xE0, 0x3F, 0x40, 0x01, 0x2A, + 0x03, 0x00, 0x60, 0x60, 0x1C, 0xE0, 0x02, 0x00, 0x80, 0x60, 0x1C, 0xE0, 0x40, 0xEC, 0x00, 0xED, + 0x02, 0xEE, 0x80, 0x60, 0x58, 0xEC, 0x80, 0x60, 0x00, 0xED, 0x80, 0x60, 0x82, 0xEE, 0xC0, 0x60, + 0x59, 0xEC, 0xC0, 0x60, 0x07, 0xED, 0xAD, 0x4F, 0xFE, 0xB4, 0xA0, 0x5D, 0x00, 0xF3, 0x28, 0xFB, + 0x40, 0x44, 0xA4, 0x60, 0x5D, 0x7C, 0x20, 0xF9, 0xA5, 0x60, 0x48, 0x7C, 0x21, 0xF9, 0xA7, 0x60, + 0x30, 0x7C, 0x22, 0xF9, 0xB0, 0x60, 0xCD, 0x7C, 0x23, 0xF9, 0xB5, 0x60, 0x6C, 0x7C, 0x24, 0xF9, + 0xC0, 0x60, 0x88, 0x7C, 0x25, 0xF9, 0xC6, 0x60, 0xE0, 0x7C, 0x26, 0xF9, 0x91, 0x60, 0x00, 0xE8, + 0x28, 0xE8, 0x44, 0x60, 0x02, 0xE6, 0x00, 0x64, 0x40, 0x52, 0x10, 0x60, 0x04, 0xE6, 0x08, 0x60, + 0x00, 0x63, 0xFA, 0x60, 0x00, 0x65, 0xBD, 0xD3, 0xBD, 0xD3, 0x02, 0xA8, 0xD4, 0x80, 0x47, 0x02, + 0x46, 0x02, 0xDB, 0x83, 0xFA, 0x60, 0x27, 0x65, 0x5B, 0xD3, 0xBF, 0xD1, 0x1A, 0x18, 0xC3, 0x83, + 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xDB, 0x83, 0xD3, 0x83, 0xD3, 0x86, 0x64, 0x41, 0xCD, 0x81, + 0xA6, 0xD1, 0xDA, 0x86, 0x1C, 0x60, 0x68, 0x65, 0x00, 0x60, 0x72, 0x63, 0xA5, 0xD3, 0xDA, 0x85, + 0x90, 0x84, 0xFF, 0x27, 0x02, 0x00, 0xA2, 0xD9, 0x01, 0x00, 0xF8, 0x1F, 0xCD, 0x81, 0xFF, 0xFF, + 0xEF, 0x02, 0x08, 0x60, 0x06, 0x63, 0xFA, 0x60, 0x28, 0x65, 0x5B, 0xD3, 0xBF, 0xD1, 0x0B, 0x18, + 0xC3, 0x83, 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xBF, 0xD3, 0x21, 0x60, 0x72, 0x62, 0x0E, 0xB4, + 0xE0, 0x84, 0xE0, 0x84, 0xA2, 0xDB, 0x08, 0x60, 0x06, 0x63, 0xFD, 0x60, 0x0C, 0x65, 0x5B, 0xD3, + 0xBF, 0xD1, 0x0D, 0x18, 0xC3, 0x83, 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xFA, 0xA3, 0xA3, 0xD3, + 0x02, 0x60, 0x00, 0x65, 0xF7, 0xA0, 0xFC, 0xA0, 0x0A, 0x05, 0x01, 0x05, 0x00, 0x00, 0x21, 0x60, + 0x00, 0x65, 0x3F, 0x43, 0x3F, 0x43, 0x21, 0x60, 0x00, 0x65, 0xC0, 0x60, 0x8F, 0xEE, 0xB7, 0x84, + 0x40, 0x5F, 0x00, 0x60, 0x30, 0xE2, 0x00, 0x60, 0x50, 0xE2, 0x00, 0x60, 0x79, 0xE2, 0x00, 0x60, + 0x90, 0xE2, 0x01, 0x60, 0xD0, 0xE2, 0x01, 0x60, 0xF0, 0xE2, 0x01, 0x60, 0xB0, 0xE2, 0x26, 0x64, + 0x35, 0xFB, 0x01, 0x60, 0x30, 0x64, 0x0A, 0xA4, 0x38, 0xFB, 0x60, 0x45, 0x00, 0x60, 0xF8, 0x64, + 0x0A, 0xA4, 0x39, 0xFB, 0x35, 0xF1, 0x0A, 0x64, 0xC4, 0x84, 0x36, 0xFB, 0xC0, 0x84, 0x0A, 0xA4, + 0x37, 0xFB, 0x09, 0x60, 0x2A, 0x64, 0x99, 0xFB, 0x82, 0xFF, 0x92, 0xFF, 0x5C, 0x41, 0x5C, 0x46, + 0x5C, 0x47, 0x00, 0xE1, 0xA7, 0x60, 0x9B, 0x63, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x87, 0xFF, + 0x97, 0xFF, 0x0C, 0x60, 0x02, 0x64, 0x40, 0x5A, 0x06, 0xA4, 0x40, 0x5B, 0x5C, 0x5E, 0x5C, 0x51, + 0x1F, 0x60, 0xAA, 0x62, 0xA2, 0xD3, 0x65, 0xFB, 0x21, 0x60, 0xEC, 0x61, 0x27, 0x7C, 0xA1, 0xD9, + 0x25, 0x60, 0x2E, 0x63, 0x7F, 0xA3, 0xE3, 0x87, 0x00, 0x7F, 0x8A, 0xFB, 0x02, 0x60, 0x80, 0x66, + 0x22, 0x60, 0x22, 0x64, 0x77, 0x60, 0x77, 0x63, 0x00, 0xFA, 0x01, 0xFC, 0x00, 0xF0, 0x01, 0xF0, + 0xD0, 0x80, 0xD3, 0x80, 0x1E, 0x02, 0x1D, 0x02, 0x06, 0x60, 0x80, 0x65, 0x45, 0x4A, 0xAA, 0x46, + 0x00, 0xFC, 0x01, 0xFA, 0xAA, 0x46, 0x00, 0xF0, 0x2A, 0x41, 0x50, 0x65, 0xD3, 0x80, 0xCD, 0x84, + 0x13, 0x03, 0x0A, 0x60, 0x80, 0x65, 0x45, 0x4A, 0xAA, 0x46, 0x00, 0xFC, 0x01, 0xFA, 0xAA, 0x46, + 0x00, 0xF0, 0x65, 0x41, 0xC8, 0x65, 0xD3, 0x80, 0xCD, 0x84, 0x06, 0x03, 0x12, 0x60, 0x7F, 0x64, + 0x03, 0x00, 0x10, 0x65, 0x02, 0x60, 0x7F, 0x64, 0x65, 0x43, 0x87, 0xFD, 0x1B, 0x60, 0x72, 0x62, + 0xA2, 0xDD, 0x07, 0x61, 0xC5, 0x81, 0xE1, 0x85, 0xD4, 0x84, 0x8B, 0xFB, 0xDC, 0x84, 0x89, 0xFB, + 0x0C, 0xA4, 0x88, 0xFB, 0x1B, 0x60, 0x74, 0x62, 0xA2, 0xDB, 0xA2, 0x60, 0x58, 0x4E, 0x1F, 0x78, + 0xFF, 0xFF, 0xA2, 0x60, 0x58, 0x4E, 0x00, 0x78, 0xFF, 0xFF, 0x8B, 0xF1, 0x8A, 0xF3, 0x7C, 0x63, + 0x8D, 0xFB, 0x60, 0x46, 0x01, 0xFC, 0xDC, 0x84, 0xD0, 0x80, 0x00, 0xFA, 0xFA, 0x04, 0x8E, 0xFB, + 0x60, 0x46, 0x00, 0x64, 0x00, 0xFA, 0x63, 0x44, 0x80, 0x7F, 0x01, 0xFA, 0x8B, 0xF3, 0x8A, 0xF1, + 0xDC, 0x84, 0xD0, 0x84, 0x8C, 0xFB, 0x03, 0x60, 0x26, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x64, 0x78, + 0xFF, 0xFF, 0x66, 0x44, 0x2E, 0xFB, 0x82, 0xFF, 0x40, 0x42, 0x87, 0xFF, 0x8C, 0xF3, 0x94, 0xFB, + 0x00, 0x64, 0x12, 0x60, 0xC8, 0x63, 0xA3, 0xDB, 0x00, 0x64, 0x40, 0x50, 0x63, 0xFF, 0x66, 0xFF, + 0x65, 0xFF, 0x64, 0xFF, 0x61, 0xFF, 0x62, 0xFF, 0x49, 0x60, 0x02, 0xE1, 0x52, 0x60, 0x02, 0xE1, + 0x5B, 0x60, 0x02, 0xE1, 0x65, 0x60, 0x02, 0xE1, 0x6C, 0x60, 0x02, 0xE1, 0x76, 0x60, 0x02, 0xE1, + 0x41, 0x60, 0x02, 0xE1, 0x04, 0x65, 0x21, 0x60, 0x7E, 0x64, 0x44, 0xD3, 0xEA, 0x60, 0x58, 0x4E, + 0x78, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0x04, 0x65, 0x0C, 0x64, 0xA5, 0xDB, 0xA3, 0x60, 0xED, 0x64, + 0x80, 0xFB, 0x2D, 0xFF, 0x0A, 0x61, 0x41, 0x4B, 0x09, 0x60, 0x08, 0x61, 0xB3, 0x60, 0x58, 0x4D, + 0x64, 0x78, 0xFF, 0xFF, 0xF0, 0x67, 0x0E, 0xFA, 0x1B, 0x60, 0xE0, 0x62, 0x1B, 0x60, 0xC4, 0x64, + 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x2B, 0x41, + 0x4D, 0x8B, 0xFF, 0xFF, 0xE9, 0x02, 0x0A, 0x61, 0x41, 0x4B, 0x09, 0x60, 0x08, 0x61, 0xB3, 0x60, + 0x58, 0x4D, 0x64, 0x78, 0xFF, 0xFF, 0x1B, 0x60, 0xE0, 0x62, 0x1B, 0x60, 0xB8, 0x64, 0xA2, 0xDB, + 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x2B, 0x41, 0x4D, 0x8B, + 0xFF, 0xFF, 0xEB, 0x02, 0xEB, 0x60, 0x4E, 0x78, 0xFF, 0xFF, 0x00, 0xEA, 0x00, 0xEB, 0x50, 0x60, + 0x03, 0xEA, 0x51, 0x60, 0x13, 0xEA, 0x52, 0x60, 0x30, 0xEA, 0x53, 0x60, 0x40, 0xEA, 0x54, 0x60, + 0x52, 0xEA, 0x55, 0x60, 0x6D, 0xEA, 0x56, 0x60, 0x71, 0xEA, 0x57, 0x60, 0x8B, 0xEA, 0x58, 0x60, + 0x47, 0xEA, 0x59, 0x60, 0xA0, 0xEA, 0x5A, 0x60, 0xB2, 0xEA, 0x5B, 0x60, 0xC1, 0xEA, 0x5C, 0x60, + 0xD7, 0xEA, 0x5D, 0x60, 0xEB, 0xEA, 0x5E, 0x60, 0xA0, 0xEA, 0x50, 0x60, 0x36, 0xEB, 0x51, 0x60, + 0x37, 0xEB, 0x52, 0x60, 0x20, 0xEB, 0x53, 0x60, 0xE4, 0xEB, 0x54, 0x60, 0x34, 0xEB, 0x55, 0x60, + 0x58, 0xEB, 0x56, 0x60, 0x48, 0xEB, 0x57, 0x60, 0xD0, 0xEB, 0x58, 0x60, 0xC3, 0xEB, 0x59, 0x60, + 0xFC, 0xEB, 0x5A, 0x60, 0x34, 0xEB, 0x5B, 0x60, 0x58, 0xEB, 0x5C, 0x60, 0xC0, 0xEB, 0x5D, 0x60, + 0xD0, 0xEB, 0x5E, 0x60, 0x91, 0xEB, 0x00, 0xEA, 0x00, 0xEB, 0xE0, 0x60, 0x02, 0xEA, 0xE0, 0x60, + 0x03, 0xEB, 0xA0, 0x60, 0x00, 0xEB, 0xB0, 0x60, 0x00, 0xEB, 0xAB, 0x48, 0x40, 0x3B, 0x01, 0x00, + 0xFC, 0x01, 0x00, 0xEB, 0x03, 0x60, 0x02, 0x62, 0x62, 0x44, 0xA2, 0xDB, 0x0F, 0x64, 0x60, 0x7F, + 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x3F, 0x40, + 0x40, 0x26, 0x08, 0x00, 0x00, 0x60, 0x18, 0x64, 0x00, 0x60, 0x00, 0x65, 0x94, 0x84, 0xA0, 0x50, + 0x1D, 0x60, 0x19, 0xE2, 0x24, 0x44, 0xFF, 0xB4, 0x04, 0xFB, 0x50, 0x60, 0x00, 0x64, 0x05, 0xFB, + 0x10, 0x60, 0x10, 0x75, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, 0x80, 0xFF, 0x90, 0xFF, 0x98, 0xFF, + 0x23, 0x60, 0x5C, 0x63, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, + 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, + 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, + 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, + 0x2F, 0x44, 0xBD, 0xDB, 0x23, 0x60, 0x50, 0x64, 0xA0, 0xDD, 0x24, 0x60, 0x7C, 0x63, 0x23, 0x60, + 0x52, 0x64, 0xA0, 0xDD, 0x23, 0x60, 0x54, 0x63, 0x30, 0x44, 0xA3, 0xDB, 0x23, 0x60, 0x56, 0x63, + 0x31, 0x44, 0xA3, 0xDB, 0x23, 0x60, 0x58, 0x63, 0x32, 0x44, 0xA3, 0xDB, 0x23, 0x60, 0x5A, 0x63, + 0x33, 0x44, 0xA3, 0xDB, 0x81, 0xFF, 0x91, 0xFF, 0x58, 0x51, 0x48, 0x00, 0x82, 0xFF, 0x92, 0xFF, + 0x58, 0x51, 0x44, 0x00, 0x83, 0xFF, 0x93, 0xFF, 0x58, 0x51, 0x40, 0x00, 0x84, 0xFF, 0x94, 0xFF, + 0x58, 0x51, 0x3C, 0x00, 0x85, 0xFF, 0x95, 0xFF, 0x58, 0x51, 0x38, 0x00, 0x86, 0xFF, 0x96, 0xFF, + 0x58, 0x51, 0x34, 0x00, 0x87, 0xFF, 0x97, 0xFF, 0x58, 0x51, 0x30, 0x00, 0x80, 0xFF, 0x90, 0xFF, + 0x99, 0xFF, 0x23, 0x60, 0x50, 0x64, 0xA0, 0xD1, 0x30, 0x44, 0x64, 0x43, 0xBD, 0xDB, 0x31, 0x44, + 0xBD, 0xDB, 0x32, 0x44, 0xBD, 0xDB, 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, 0x35, 0x44, + 0xBD, 0xDB, 0x36, 0x44, 0xBD, 0xDB, 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, 0x39, 0x44, + 0xBD, 0xDB, 0x3A, 0x44, 0xBD, 0xDB, 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, 0x3D, 0x44, + 0xBD, 0xDB, 0x3E, 0x44, 0xBD, 0xDB, 0x3F, 0x44, 0xBD, 0xDB, 0xE3, 0x60, 0x50, 0x64, 0x0A, 0xFB, + 0x40, 0x21, 0xFE, 0x01, 0xA1, 0xFF, 0xFF, 0xFF, 0x78, 0x01, 0xFF, 0xFF, 0x42, 0x50, 0x40, 0x53, + 0x23, 0x60, 0x52, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x52, 0x33, 0x44, 0x32, 0x42, 0xA2, 0xDB, + 0xDA, 0x82, 0xA2, 0xDD, 0xDA, 0x83, 0x65, 0x44, 0xBD, 0xDB, 0x61, 0x44, 0xBD, 0xDB, 0x66, 0x44, + 0xBD, 0xDB, 0xBD, 0xD9, 0x30, 0x44, 0xBD, 0xDB, 0x99, 0xFF, 0xA4, 0x4C, 0xBD, 0xDB, 0xA5, 0x4C, + 0xBD, 0xDB, 0xA0, 0x4C, 0xBD, 0xDB, 0xA1, 0x4C, 0xBD, 0xDB, 0x98, 0xFF, 0x23, 0x60, 0x52, 0x64, + 0xA0, 0xDD, 0x23, 0x60, 0x54, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x50, 0x23, 0x60, 0x58, 0x62, + 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x52, 0x23, 0x60, 0x5A, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x53, + 0x31, 0x41, 0x23, 0x60, 0x56, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x51, 0x23, 0x60, 0x50, 0x62, + 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x43, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, + 0xBD, 0xDB, 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, + 0xBD, 0xDB, 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, + 0xBD, 0xDB, 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, + 0xBD, 0xDB, 0x2F, 0x44, 0xBD, 0xDB, 0x23, 0x60, 0x50, 0x64, 0xA0, 0xDD, 0x61, 0x58, 0xFF, 0xFF, + 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x07, 0x02, 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, + 0x66, 0xFF, 0xBF, 0xFE, 0xA1, 0xFF, 0x82, 0xFF, 0x88, 0xFF, 0x6C, 0x40, 0x41, 0xFF, 0xC4, 0xE2, + 0x43, 0xFF, 0x5C, 0x49, 0x08, 0xE1, 0xA5, 0x60, 0x5E, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, 0x98, 0xFF, + 0x80, 0x3E, 0x9F, 0xFE, 0x03, 0x04, 0xA6, 0x60, 0x28, 0x78, 0xFF, 0xFF, 0xE2, 0xFE, 0x40, 0x05, + 0xE0, 0xFE, 0x5B, 0x05, 0xE1, 0xFE, 0xF2, 0x04, 0x29, 0x40, 0x08, 0x26, 0xEF, 0x01, 0x72, 0x44, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x95, 0xF3, 0xE8, 0x85, 0xFF, 0xB7, + 0xE0, 0x84, 0xE0, 0x84, 0xB4, 0x85, 0x73, 0x44, 0xD4, 0x84, 0x10, 0x65, 0xD4, 0x80, 0xFF, 0xFF, + 0x26, 0x04, 0x3F, 0x40, 0x40, 0x26, 0x13, 0x00, 0x0B, 0x60, 0xF8, 0x62, 0xA2, 0xD1, 0x00, 0x60, + 0x10, 0x64, 0x90, 0x84, 0xA0, 0x50, 0xF8, 0xA2, 0xA2, 0xD1, 0x0A, 0x60, 0x19, 0x64, 0x90, 0x84, + 0xA0, 0x52, 0x06, 0xA2, 0xA2, 0xD1, 0x46, 0x60, 0x09, 0x64, 0x90, 0x84, 0xA0, 0x50, 0xD2, 0xF4, + 0x25, 0x60, 0x16, 0x7C, 0x63, 0x40, 0x01, 0x26, 0x08, 0x00, 0xA4, 0xD3, 0xFF, 0xFF, 0x01, 0xB4, + 0xFF, 0xFF, 0x03, 0x02, 0xAD, 0x4F, 0xFE, 0xB4, 0xA0, 0x5D, 0x02, 0xEE, 0xBD, 0xFE, 0xBE, 0x01, + 0x21, 0x46, 0x5E, 0x62, 0x9A, 0xFF, 0x07, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x06, 0x25, 0x10, 0x00, + 0xA2, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x62, 0x62, 0x01, 0x5D, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, + 0x7A, 0xDC, 0x44, 0xFF, 0x06, 0x25, 0x04, 0x00, 0x0E, 0xE1, 0x02, 0x60, 0x01, 0xE1, 0x9E, 0x01, + 0x62, 0xFF, 0xC4, 0xE2, 0x41, 0xFF, 0x0A, 0xE1, 0x99, 0x01, 0xC8, 0x74, 0xCD, 0xE2, 0x29, 0x44, + 0x08, 0xBC, 0x40, 0x49, 0x05, 0xE1, 0x25, 0x60, 0x18, 0x63, 0xA3, 0xD3, 0xD2, 0xF3, 0x06, 0x18, + 0x28, 0x40, 0x08, 0x2A, 0x05, 0x00, 0x28, 0x40, 0x48, 0x36, 0x02, 0x00, 0x02, 0xBC, 0xD2, 0xFB, + 0x3F, 0x40, 0x01, 0x2B, 0xFF, 0xFF, 0xA1, 0xFF, 0x67, 0x4C, 0x06, 0x61, 0xCD, 0x81, 0x04, 0x25, + 0x30, 0x00, 0x87, 0x4C, 0xFB, 0x02, 0x28, 0x40, 0x40, 0x2B, 0x02, 0x00, 0x15, 0x60, 0x6F, 0x6B, + 0xF3, 0x60, 0xA0, 0x64, 0x04, 0x25, 0x25, 0x00, 0x80, 0x4C, 0x30, 0x64, 0x3A, 0xDB, 0x44, 0xFF, + 0x04, 0x25, 0x1F, 0x00, 0x04, 0x60, 0x00, 0x65, 0x25, 0x44, 0x37, 0x36, 0xB4, 0x84, 0x6E, 0x36, + 0xB4, 0x84, 0x80, 0x4E, 0x24, 0x41, 0x04, 0x25, 0x14, 0x00, 0x61, 0x4C, 0x64, 0xA1, 0x61, 0x54, + 0xA1, 0xFF, 0xFF, 0xFF, 0x04, 0x25, 0x0D, 0x00, 0x67, 0x4E, 0x07, 0x64, 0x1C, 0xFB, 0x00, 0xE1, + 0x02, 0x60, 0x01, 0xE1, 0x53, 0x01, 0x33, 0xF3, 0xFD, 0x11, 0xFC, 0x18, 0x40, 0x64, 0x3A, 0xDB, + 0x0A, 0x00, 0xC4, 0xE2, 0x27, 0x44, 0x20, 0x2A, 0x04, 0x00, 0x42, 0x64, 0x3A, 0xDB, 0x67, 0x4C, + 0x02, 0x00, 0x41, 0x64, 0x3A, 0xDB, 0x62, 0xFF, 0x08, 0xE1, 0xE2, 0xFE, 0x72, 0x52, 0x5C, 0x49, + 0x32, 0x7B, 0x4D, 0xE2, 0x3B, 0x01, 0x08, 0xE1, 0x39, 0x01, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, + 0x00, 0x60, 0x46, 0x74, 0xCD, 0xE2, 0x04, 0xE1, 0x02, 0x60, 0x00, 0xE1, 0x3F, 0x44, 0x40, 0x26, + 0x0B, 0x00, 0x01, 0x2A, 0x05, 0x00, 0x42, 0x60, 0x09, 0xE0, 0x60, 0x60, 0x1C, 0xE0, 0x04, 0x00, + 0x42, 0x60, 0x09, 0xE0, 0x80, 0x60, 0x1C, 0xE0, 0x04, 0x29, 0xFE, 0x01, 0xC4, 0xE2, 0x43, 0x64, + 0x3A, 0xDB, 0x83, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x3F, 0x44, 0x02, 0x27, 0x84, 0x00, 0x20, 0x2B, + 0xFF, 0x01, 0x80, 0xE1, 0x95, 0x60, 0x80, 0xE7, 0x61, 0x40, 0x40, 0x2B, 0x0D, 0x00, 0x05, 0x63, + 0xA7, 0x60, 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, 0x28, 0x63, 0xFF, 0xFF, 0xFE, 0x1F, 0x01, 0x63, + 0xA7, 0x60, 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, 0xFF, 0xB1, 0xCD, 0x81, 0xE1, 0x85, 0x1E, 0x60, + 0xA2, 0x64, 0x44, 0xD1, 0xFF, 0xFF, 0x64, 0x43, 0xA7, 0x60, 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, + 0x00, 0x60, 0x00, 0x63, 0xA7, 0x60, 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xBE, 0x61, + 0x21, 0x60, 0x72, 0x62, 0xA2, 0xD3, 0x45, 0xD1, 0x47, 0xBC, 0xE0, 0x84, 0x62, 0x45, 0x64, 0x5F, + 0xE8, 0x83, 0xA7, 0x60, 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, 0x82, 0xF3, 0xCD, 0xE2, 0x60, 0x54, + 0x04, 0xE1, 0x04, 0x29, 0xFE, 0x01, 0xC4, 0xE2, 0x15, 0x60, 0xA2, 0xE7, 0x38, 0x69, 0xFF, 0xFF, + 0x68, 0x44, 0x01, 0x16, 0xFD, 0x01, 0x01, 0x2A, 0x36, 0x00, 0x03, 0x60, 0x80, 0x7C, 0xA3, 0x83, + 0x21, 0x60, 0x72, 0x62, 0xA2, 0xD1, 0x43, 0xBB, 0xB3, 0x83, 0x95, 0x60, 0x80, 0xE7, 0xA7, 0x60, + 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, 0xE3, 0x83, 0x15, 0x60, 0xA2, 0xE7, 0x38, 0x69, 0xFF, 0xFF, + 0x68, 0x41, 0x01, 0x16, 0xFD, 0x01, 0x63, 0x47, 0x61, 0x40, 0x01, 0x2A, 0x03, 0x00, 0x00, 0x3A, + 0xCC, 0x84, 0x02, 0x00, 0x07, 0x3A, 0xDC, 0x84, 0xFF, 0xB4, 0xA5, 0xDB, 0x60, 0x47, 0xE8, 0x84, + 0x47, 0x65, 0x21, 0x60, 0x72, 0x62, 0xA2, 0xD3, 0xB4, 0x85, 0xB4, 0x83, 0x80, 0xE1, 0x95, 0x60, + 0x80, 0xE7, 0xA7, 0x60, 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, 0x82, 0xF3, 0xCD, 0xE2, 0x60, 0x54, + 0x04, 0x29, 0xFE, 0x01, 0xC4, 0xE2, 0x83, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x2B, 0x04, 0x00, + 0xA6, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0xFF, 0x01, 0x83, 0xF3, 0x80, 0xE1, 0xCC, 0x84, 0xE0, 0x85, + 0x15, 0x60, 0xA2, 0xE7, 0x1D, 0x60, 0xDE, 0x64, 0x58, 0x4F, 0x4F, 0x00, 0x1D, 0x60, 0xFA, 0x64, + 0x58, 0x4F, 0x4B, 0x00, 0x1E, 0x60, 0x16, 0x64, 0x58, 0x4F, 0x47, 0x00, 0x1E, 0x60, 0x32, 0x64, + 0x58, 0x4F, 0x43, 0x00, 0x1E, 0x60, 0x4E, 0x64, 0x58, 0x4F, 0x3F, 0x00, 0x1E, 0x60, 0x6A, 0x64, + 0x58, 0x4F, 0x3B, 0x00, 0x1E, 0x60, 0x86, 0x64, 0x58, 0x4F, 0x37, 0x00, 0x01, 0x68, 0xFF, 0x6A, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x3F, 0x44, 0x20, 0x27, 0x00, 0x00, 0x3F, 0x40, 0x40, 0x26, + 0x08, 0x00, 0x00, 0x60, 0x18, 0x64, 0x00, 0x60, 0x00, 0x65, 0x94, 0x84, 0xA0, 0x50, 0x1D, 0x60, + 0x19, 0xE2, 0xC4, 0xE2, 0x00, 0x63, 0x82, 0xFD, 0x32, 0x7B, 0x4D, 0xE2, 0xBF, 0xFE, 0xC4, 0xE2, + 0x41, 0xFF, 0xE0, 0xFE, 0xE1, 0xFE, 0xE2, 0xFE, 0x43, 0xFF, 0x44, 0xFF, 0x46, 0xFF, 0x84, 0xF3, + 0x62, 0xFF, 0x60, 0x40, 0x05, 0x36, 0x2D, 0xFF, 0x07, 0x36, 0xD5, 0xFE, 0x08, 0xE1, 0x88, 0x60, + 0x85, 0x71, 0x8D, 0xE2, 0xA5, 0x60, 0x5E, 0x78, 0xFF, 0xFF, 0x50, 0xEC, 0x63, 0x4A, 0xFF, 0xFF, + 0x01, 0x16, 0xFE, 0x01, 0x40, 0xEC, 0x2F, 0x58, 0xFF, 0xFF, 0x44, 0xD3, 0x80, 0x7C, 0x60, 0x48, + 0x60, 0x47, 0x00, 0x7F, 0xB0, 0x8A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x2F, 0x58, 0xFF, 0xFF, + 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x02, 0x02, 0xA1, 0xFF, 0xFF, 0xFF, 0x82, 0xFF, 0x88, 0xFF, + 0x48, 0xE2, 0x01, 0x70, 0xAE, 0xF1, 0x00, 0x6B, 0x89, 0xFF, 0x64, 0x54, 0x88, 0xFF, 0x9F, 0xFE, + 0x02, 0x05, 0x64, 0x44, 0x60, 0x54, 0xCD, 0xE2, 0xC2, 0x64, 0x3A, 0xDB, 0xBC, 0xFF, 0xB5, 0xFF, + 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xB4, 0x40, 0x46, 0x3C, 0x44, 0x00, 0xBC, 0xFF, 0xFF, 0x06, 0x03, + 0x27, 0x40, 0x26, 0x22, 0x03, 0x00, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x27, 0x44, 0x20, 0x2A, + 0x04, 0x00, 0xA0, 0x60, 0x00, 0xEA, 0xB0, 0x60, 0x00, 0xEA, 0x5C, 0x4D, 0x27, 0x44, 0x18, 0xB4, + 0x40, 0x47, 0x00, 0xE1, 0x6C, 0x40, 0x44, 0xE2, 0xC4, 0xE2, 0x47, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, + 0x32, 0xF1, 0x08, 0x29, 0x09, 0x00, 0x64, 0x40, 0x07, 0x22, 0x06, 0x00, 0x43, 0xFF, 0x27, 0x44, + 0x10, 0xBC, 0x40, 0x47, 0x00, 0x64, 0x32, 0xFB, 0x31, 0x41, 0x3C, 0x44, 0x01, 0xB1, 0x00, 0xBC, + 0x0A, 0x02, 0x09, 0x03, 0x32, 0xF3, 0x00, 0x7C, 0x01, 0xB4, 0xFF, 0xFF, 0x04, 0x03, 0x32, 0xF9, + 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x00, 0x64, + 0x33, 0xFB, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x32, 0xF3, 0x08, 0x29, + 0x0A, 0x00, 0x60, 0x40, 0x07, 0x22, 0x07, 0x00, 0xFE, 0xB4, 0x32, 0xFB, 0x27, 0x44, 0x10, 0xBC, + 0xF7, 0xB4, 0x40, 0x47, 0x43, 0xFF, 0x00, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x08, 0xE1, 0x31, 0x40, + 0x01, 0x2A, 0x04, 0x00, 0x00, 0x64, 0x33, 0xFB, 0x01, 0x60, 0x0A, 0xE1, 0xE5, 0xFE, 0x13, 0x05, + 0x27, 0x44, 0x10, 0x26, 0x13, 0x00, 0x9F, 0xFE, 0x02, 0x04, 0x02, 0xE1, 0x06, 0x00, 0x3E, 0xE1, + 0x31, 0x44, 0x01, 0x2A, 0x02, 0x00, 0x04, 0x0A, 0xBF, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, + 0xAF, 0x60, 0x19, 0x78, 0xFF, 0xFF, 0xA8, 0x60, 0x09, 0x78, 0xFF, 0xFF, 0x27, 0x44, 0x08, 0x26, + 0xFF, 0xFF, 0xBF, 0x60, 0x2A, 0x78, 0xFF, 0xFF, 0x48, 0xF3, 0x32, 0xF1, 0x00, 0x63, 0x64, 0x40, + 0x03, 0x22, 0x3D, 0x00, 0x31, 0x40, 0x08, 0x26, 0xF4, 0x01, 0xCD, 0xE2, 0x84, 0xE1, 0x70, 0x41, + 0xAD, 0x80, 0x71, 0x40, 0x80, 0x27, 0xED, 0x12, 0x03, 0x03, 0xBF, 0x60, 0x7C, 0x78, 0xFF, 0xFF, + 0xA1, 0xFF, 0xFF, 0xFF, 0xC4, 0xE2, 0x32, 0xFD, 0x60, 0x40, 0x01, 0x2A, 0xDF, 0x01, 0x00, 0x63, + 0x32, 0xFD, 0x6C, 0x40, 0x3C, 0x46, 0x3E, 0xF2, 0x2A, 0xF0, 0x27, 0x41, 0x44, 0x48, 0x20, 0xB9, + 0x01, 0xB4, 0xF7, 0xB1, 0x0A, 0x03, 0x64, 0x40, 0x08, 0x27, 0x07, 0x00, 0x0F, 0x60, 0x92, 0x63, + 0x00, 0x64, 0x45, 0xFB, 0x46, 0xFB, 0xBD, 0xDB, 0xA3, 0xDB, 0xCB, 0x0A, 0x41, 0x47, 0x3F, 0x40, + 0x01, 0x2B, 0x04, 0x00, 0xF6, 0xFE, 0x67, 0x4C, 0x05, 0x60, 0x69, 0x6B, 0x02, 0xE1, 0x01, 0x60, + 0x08, 0xE1, 0xF0, 0xFE, 0x84, 0xFF, 0xBF, 0x60, 0xAD, 0x64, 0x40, 0x42, 0x82, 0xFF, 0xE5, 0xFE, + 0x03, 0x04, 0xAC, 0x60, 0x41, 0x78, 0xFF, 0xFF, 0xE4, 0xFE, 0x0A, 0x04, 0x1D, 0xFF, 0x00, 0xEB, + 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, + 0x43, 0xFF, 0xE6, 0xFE, 0x03, 0x05, 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, 0x3C, 0x44, 0x60, 0x46, + 0x0F, 0xF0, 0x40, 0x42, 0x64, 0x40, 0x01, 0x2A, 0x03, 0x00, 0xAB, 0x60, 0x03, 0x78, 0xFF, 0xFF, + 0x0B, 0x64, 0x3A, 0xDB, 0x1C, 0x42, 0x22, 0x46, 0x13, 0xF2, 0xFF, 0x65, 0x60, 0x47, 0x2A, 0xF2, + 0x40, 0x45, 0x40, 0x48, 0x04, 0x2B, 0x17, 0x00, 0x16, 0xF2, 0x1D, 0xF2, 0x40, 0x43, 0x0F, 0xF2, + 0x40, 0x44, 0x25, 0x5E, 0x3F, 0x40, 0x01, 0x27, 0x40, 0x45, 0x0F, 0x64, 0x14, 0xF0, 0x35, 0xF2, + 0xA0, 0x82, 0x0F, 0xB4, 0xCA, 0x85, 0xD4, 0x80, 0x10, 0xF2, 0x01, 0x02, 0x2B, 0xFA, 0x27, 0x44, + 0x40, 0xBC, 0x40, 0x47, 0x13, 0x00, 0x17, 0xF2, 0x2C, 0xF0, 0x40, 0x43, 0x1B, 0xF2, 0x1D, 0xFA, + 0x40, 0x44, 0x64, 0x40, 0x01, 0x2A, 0x02, 0x00, 0xAB, 0xFC, 0x05, 0x00, 0x28, 0x40, 0xA4, 0x36, + 0x02, 0x00, 0x11, 0xF2, 0x2B, 0xFA, 0x27, 0x44, 0xBF, 0xB4, 0x40, 0x47, 0x28, 0x40, 0x40, 0x2B, + 0xFF, 0xFF, 0xAF, 0x60, 0x2E, 0x78, 0xFF, 0xFF, 0x22, 0x46, 0x2C, 0xF0, 0x27, 0x44, 0xDF, 0xB4, + 0x40, 0x47, 0xB5, 0xFF, 0xBC, 0xFF, 0x47, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, + 0x08, 0x60, 0x00, 0x6B, 0x64, 0x40, 0x01, 0x2A, 0x01, 0x00, 0x13, 0x00, 0x2A, 0xF0, 0x01, 0x65, + 0x64, 0x40, 0xA4, 0x3A, 0x04, 0x65, 0x27, 0x44, 0x34, 0x87, 0x36, 0xF3, 0xB4, 0xFF, 0x60, 0x5B, + 0x4D, 0xE2, 0x04, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x0A, 0xE1, 0x2B, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, + 0x81, 0x3E, 0x06, 0x64, 0x3A, 0xDB, 0x22, 0x46, 0x01, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xBF, 0x60, + 0x85, 0x78, 0xFF, 0xFF, 0xB5, 0xFF, 0xA1, 0xFF, 0x6C, 0x40, 0x3F, 0x40, 0x01, 0x2B, 0x03, 0x00, + 0x67, 0x4C, 0x05, 0x60, 0x69, 0x6B, 0x02, 0xE1, 0x01, 0x60, 0x08, 0xE1, 0xC4, 0xE2, 0x08, 0x64, + 0x3A, 0xDB, 0xF0, 0xFE, 0x25, 0x46, 0x01, 0xF2, 0x61, 0x45, 0xD4, 0x9E, 0x21, 0x46, 0x16, 0xFA, + 0x2A, 0x44, 0x72, 0x45, 0x24, 0xFA, 0x95, 0xF3, 0x06, 0x04, 0xE4, 0xE2, 0xDC, 0x9C, 0x29, 0x40, + 0x01, 0x26, 0x64, 0x44, 0x95, 0xF9, 0x25, 0xFA, 0x96, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x96, 0xFB, + 0x28, 0xFA, 0x97, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x97, 0xFB, 0x29, 0xFA, 0x2D, 0x44, 0x04, 0x2A, + 0x06, 0x00, 0x28, 0x40, 0xA4, 0x36, 0x03, 0x00, 0xA9, 0x60, 0xC9, 0x78, 0xFF, 0xFF, 0x94, 0xFC, + 0x1F, 0x60, 0x9A, 0x65, 0xA5, 0xD1, 0x28, 0x44, 0x08, 0x2A, 0x51, 0x00, 0x03, 0x2B, 0x01, 0x00, + 0x4E, 0x00, 0x64, 0x40, 0x00, 0x36, 0x4B, 0x00, 0x32, 0xF2, 0x2F, 0xF0, 0x50, 0xFE, 0x01, 0x2A, + 0x03, 0x00, 0x01, 0x61, 0x8F, 0xF3, 0x31, 0x00, 0xD0, 0x80, 0x33, 0xF2, 0x30, 0xF0, 0x34, 0xF2, + 0xD0, 0x80, 0x31, 0xF0, 0xFF, 0xFF, 0xD0, 0x80, 0x60, 0x47, 0x34, 0x0C, 0xFF, 0xB4, 0x12, 0x60, + 0xCE, 0x65, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0xFF, 0xFF, 0x31, 0x18, 0x60, 0x43, 0x50, 0xFE, + 0x66, 0x41, 0x32, 0xF0, 0x63, 0x46, 0x03, 0xF2, 0x61, 0x46, 0xD0, 0x80, 0x33, 0xF0, 0x63, 0x46, + 0x04, 0xF2, 0x61, 0x46, 0xD0, 0x80, 0x34, 0xF0, 0x63, 0x46, 0x05, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, + 0xFF, 0xFF, 0x04, 0x0C, 0x00, 0xF2, 0x61, 0x46, 0x1A, 0x18, 0xE8, 0x01, 0x06, 0xF0, 0x8F, 0xF3, + 0x61, 0x46, 0x02, 0x61, 0x64, 0x40, 0x02, 0x2A, 0x12, 0x00, 0xFC, 0xA0, 0xFF, 0xFF, 0x04, 0x0E, + 0x61, 0x44, 0x14, 0xFA, 0x11, 0xFC, 0x0B, 0x00, 0x2C, 0xF2, 0x2F, 0xFA, 0x2D, 0xF2, 0x30, 0xFA, + 0x2E, 0xF2, 0x31, 0xFA, 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xBC, 0x40, 0x46, 0x20, 0x00, 0x26, 0x43, + 0x84, 0xBB, 0xFC, 0xB3, 0x21, 0x46, 0x01, 0x5D, 0x0F, 0xFC, 0x5C, 0x46, 0x25, 0x44, 0x06, 0xFA, + 0x05, 0xFF, 0x27, 0x44, 0x01, 0x2A, 0x13, 0x00, 0x50, 0xFE, 0x28, 0x40, 0x08, 0x3A, 0x12, 0x00, + 0x2F, 0xF2, 0x30, 0xF0, 0x60, 0x43, 0x31, 0xF2, 0x22, 0x46, 0x64, 0x41, 0x2C, 0xF0, 0x2D, 0xF0, + 0xD3, 0x80, 0x2E, 0xF0, 0xD1, 0x80, 0xD0, 0x80, 0x27, 0x44, 0x09, 0x0C, 0x03, 0x00, 0x27, 0x44, + 0x06, 0x22, 0x05, 0x00, 0xB8, 0xB4, 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xD4, 0x64, + 0x40, 0x48, 0x0D, 0x64, 0x3A, 0xDB, 0x21, 0x46, 0x1C, 0xF2, 0x62, 0xF1, 0xFF, 0xB4, 0xD0, 0x80, + 0xFF, 0xFF, 0x01, 0x06, 0x64, 0x44, 0x40, 0x45, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, + 0x37, 0x3A, 0x03, 0x00, 0x04, 0x7F, 0x40, 0x45, 0x15, 0x64, 0x6E, 0x3A, 0x03, 0x00, 0x84, 0x7F, + 0x40, 0x45, 0x0B, 0x64, 0x40, 0x44, 0x00, 0x63, 0x28, 0x44, 0xA4, 0x36, 0x07, 0x00, 0x04, 0x2B, + 0x05, 0x00, 0x30, 0xF3, 0x24, 0x45, 0xD4, 0x84, 0xCA, 0x65, 0xD4, 0x83, 0xD4, 0x64, 0x1A, 0x00, + 0x0F, 0x64, 0x3A, 0xDB, 0x21, 0x46, 0x70, 0x63, 0x1C, 0xF2, 0xCA, 0x65, 0x40, 0x45, 0x0A, 0x36, + 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, 0x37, 0x3A, 0x03, 0x00, 0x04, 0x7F, 0x40, 0x45, 0x15, 0x64, + 0x6E, 0x3A, 0x03, 0x00, 0x84, 0x7F, 0x40, 0x45, 0x0B, 0x64, 0x40, 0x44, 0x2B, 0xF2, 0xC4, 0x85, + 0xD4, 0x83, 0xC4, 0x64, 0x40, 0x48, 0x2F, 0xF0, 0xB0, 0xF0, 0xB1, 0xF2, 0x00, 0xE1, 0xA1, 0xFF, + 0xFF, 0xFF, 0x80, 0x4E, 0x83, 0x4C, 0x9A, 0xFF, 0x84, 0x4C, 0x85, 0x4C, 0x81, 0x4C, 0xA1, 0xFF, + 0x98, 0xFF, 0x87, 0x4F, 0x87, 0x4C, 0x87, 0x4F, 0x87, 0x4D, 0x87, 0x4C, 0x01, 0x08, 0x01, 0x00, + 0xFF, 0xFF, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x44, + 0xBC, 0xFF, 0xC4, 0xE2, 0x0C, 0x74, 0x04, 0xE1, 0xA1, 0xFF, 0x35, 0xF3, 0xC4, 0xE2, 0x60, 0x54, + 0x89, 0xFF, 0x13, 0x74, 0x88, 0xFF, 0xB5, 0xFF, 0x47, 0xFF, 0x29, 0x44, 0xF7, 0xB4, 0x40, 0x49, + 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x27, 0x44, 0x01, 0x2A, + 0x05, 0x00, 0xFE, 0xB4, 0x40, 0x47, 0xA8, 0x60, 0x89, 0x78, 0xFF, 0xFF, 0xA7, 0x60, 0x8E, 0x78, + 0xFF, 0xFF, 0x28, 0x40, 0xB4, 0x3A, 0x09, 0x00, 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, + 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x9B, 0x01, 0x28, 0x44, 0xD4, 0x36, 0x03, 0x00, + 0xAA, 0x60, 0xEA, 0x78, 0xFF, 0xFF, 0x48, 0xE2, 0x27, 0x44, 0xFB, 0xB4, 0x40, 0x47, 0x21, 0x60, + 0x98, 0x63, 0xA3, 0xD3, 0xB5, 0x60, 0x58, 0x4D, 0xE3, 0x78, 0xFF, 0xFF, 0x34, 0xFB, 0x1C, 0x42, + 0x22, 0x46, 0x2A, 0xF0, 0xF7, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDA, 0x60, 0x40, 0x40, 0x2B, + 0xCC, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x22, 0x26, 0x42, 0x00, 0x01, 0x26, 0x03, 0x00, + 0x04, 0x26, 0x07, 0x00, 0xC2, 0x00, 0x04, 0x2B, 0xC0, 0x00, 0x88, 0xF3, 0xFF, 0xFF, 0x60, 0x46, + 0x01, 0x00, 0x07, 0xF4, 0x47, 0xF2, 0xFF, 0xFF, 0xDC, 0x84, 0x47, 0xFA, 0x0D, 0x60, 0x3E, 0x62, + 0x80, 0xFF, 0xC4, 0x60, 0x78, 0x44, 0x02, 0xA4, 0xA2, 0xDB, 0x7D, 0x78, 0xFF, 0xFF, 0x82, 0xFF, + 0x88, 0xF3, 0x66, 0x5C, 0xD0, 0x80, 0x00, 0x7C, 0x07, 0x03, 0x66, 0x43, 0x22, 0x46, 0x22, 0xF2, + 0x63, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x01, 0x00, 0x3C, 0xF1, 0x47, 0xF0, 0x64, 0x41, 0x64, 0x47, + 0xFF, 0xB4, 0x60, 0x5F, 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, 0x60, 0x47, 0x22, 0x46, 0x3A, 0xFA, + 0x64, 0x44, 0x20, 0x7F, 0x34, 0x94, 0x3B, 0xFA, 0x08, 0x60, 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, + 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x85, 0x00, + 0x2A, 0xF2, 0x00, 0x60, 0x7C, 0x62, 0x60, 0x40, 0x40, 0x2B, 0x27, 0x00, 0xA2, 0xD3, 0x00, 0x61, + 0x60, 0xFE, 0xA0, 0xD3, 0xDE, 0x82, 0xA2, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0xDC, 0x84, + 0xF1, 0x81, 0xC0, 0x2B, 0x04, 0x00, 0x80, 0x2A, 0x02, 0x00, 0x7F, 0xA4, 0xDC, 0x84, 0xFF, 0x3B, + 0x03, 0x00, 0x60, 0x47, 0xDC, 0x87, 0x01, 0x61, 0xC0, 0x80, 0x00, 0x36, 0xDC, 0x84, 0x4E, 0xDB, + 0x60, 0xFE, 0xDA, 0x82, 0xA2, 0xD1, 0xFF, 0xFF, 0xC1, 0x84, 0xF0, 0x22, 0x10, 0xA4, 0xF0, 0x2A, + 0x01, 0x00, 0x00, 0x64, 0xA2, 0xDB, 0xFF, 0xFF, 0x20, 0xFE, 0x00, 0x60, 0x7C, 0x62, 0xA2, 0xD3, + 0xFF, 0xFF, 0xA0, 0xD3, 0x5A, 0xD1, 0x3A, 0xFA, 0x3B, 0xF8, 0x74, 0x62, 0xA2, 0xD0, 0xFF, 0xFF, + 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5A, 0x64, 0x44, + 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, 0x80, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0xD1, 0x5A, 0xD1, + 0x64, 0x45, 0x64, 0x44, 0xE3, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, + 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, + 0xE7, 0x7F, 0xA0, 0x5A, 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, + 0xA0, 0x5A, 0x64, 0x44, 0xE9, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, + 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, + 0xED, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEF, 0x7F, + 0xA0, 0x5A, 0x08, 0x60, 0x00, 0xEA, 0x65, 0x44, 0x02, 0xA4, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, + 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x0B, 0xF2, 0xFF, 0xFF, 0x7F, 0xB4, + 0x0C, 0xF0, 0x04, 0x02, 0x64, 0x46, 0x00, 0xF0, 0x04, 0x64, 0x22, 0x46, 0x03, 0xFA, 0x60, 0x41, + 0x64, 0x46, 0x01, 0xF2, 0xFC, 0xA1, 0x61, 0x45, 0xD4, 0x84, 0xFF, 0xFF, 0x08, 0x02, 0x00, 0xF0, + 0x04, 0x63, 0x64, 0x46, 0x01, 0xF2, 0x22, 0x46, 0x1A, 0xFA, 0x03, 0xFC, 0x02, 0x00, 0x22, 0x46, + 0x1A, 0xFA, 0x35, 0xF2, 0x04, 0xF8, 0xDC, 0x84, 0x35, 0xFA, 0x14, 0xF2, 0x0F, 0xB5, 0x0F, 0xB4, + 0xCC, 0x84, 0x94, 0x80, 0x04, 0x60, 0x00, 0x65, 0x2A, 0xF2, 0x01, 0x02, 0x94, 0x84, 0x2A, 0xFA, + 0x95, 0xFC, 0x06, 0x00, 0xC4, 0x3A, 0x07, 0x00, 0x27, 0x44, 0xFD, 0xB4, 0x40, 0x47, 0x48, 0xE2, + 0xA8, 0x60, 0x28, 0x78, 0xFF, 0xFF, 0x28, 0x44, 0x04, 0x26, 0x05, 0x00, 0x68, 0x3A, 0x03, 0x00, + 0x32, 0x44, 0x00, 0x27, 0x03, 0x00, 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, 0x0A, 0x64, 0x3A, 0xDB, + 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, 0x0E, 0x64, 0x3A, 0xDB, 0x10, 0x60, 0x00, 0x65, 0x3C, 0x46, + 0x2A, 0xF2, 0x13, 0xF0, 0xA4, 0x84, 0xB4, 0xBC, 0x40, 0x48, 0x62, 0xF1, 0x64, 0x47, 0xFF, 0xB4, + 0x60, 0x45, 0xD0, 0x80, 0x70, 0x61, 0x01, 0x06, 0x64, 0x44, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, + 0x38, 0x64, 0x37, 0x36, 0x15, 0x64, 0x6E, 0x36, 0x0B, 0x64, 0x40, 0x4E, 0xA0, 0x63, 0x0A, 0x64, + 0x65, 0x40, 0x0A, 0x36, 0x03, 0x00, 0x38, 0x61, 0x14, 0x64, 0xEB, 0x83, 0x40, 0x45, 0x43, 0x44, + 0x02, 0x60, 0x5E, 0x65, 0x2A, 0xF2, 0x2B, 0xF2, 0x60, 0x40, 0x04, 0x2B, 0x04, 0x00, 0x2E, 0x45, + 0xD4, 0x85, 0xC5, 0x84, 0x05, 0x00, 0x1B, 0xF0, 0xC5, 0x84, 0xC0, 0x84, 0x2E, 0x45, 0xC4, 0x84, + 0x60, 0x43, 0x28, 0x44, 0x00, 0xE1, 0xA1, 0xFF, 0x80, 0x4E, 0x83, 0x4C, 0x9A, 0xFF, 0x56, 0x62, + 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x5C, 0x62, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0xA1, 0xFF, + 0x98, 0xFF, 0x87, 0x4F, 0x87, 0x4C, 0x87, 0x4F, 0x87, 0x4D, 0x87, 0x4C, 0x01, 0x08, 0x01, 0x00, + 0xFF, 0xFF, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x44, + 0xBC, 0xFF, 0xB5, 0xFF, 0x47, 0xFF, 0x27, 0x44, 0x02, 0xBC, 0x40, 0x47, 0x36, 0xF3, 0xB7, 0xFF, + 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x60, 0x5B, 0x4D, 0xE2, 0xA8, 0x60, + 0x81, 0x78, 0xFF, 0xFF, 0x21, 0x46, 0xB5, 0xFF, 0xBC, 0xFF, 0x47, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, + 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x26, 0x43, 0x25, 0x44, 0x06, 0xFA, 0x2A, 0x44, + 0x72, 0x45, 0x24, 0xFA, 0x95, 0xF3, 0x06, 0x04, 0xE4, 0xE2, 0xDC, 0x9C, 0x29, 0x40, 0x01, 0x26, + 0x64, 0x44, 0x95, 0xF9, 0x25, 0xFA, 0x96, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x96, 0xFB, 0x28, 0xFA, + 0x97, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x97, 0xFB, 0x29, 0xFA, 0x2D, 0x40, 0x01, 0x2A, 0x0E, 0x00, + 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xBC, 0x40, 0x46, 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, + 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x30, 0xF1, 0x50, 0x00, 0xFC, 0xB3, 0x32, 0x40, + 0x01, 0x2A, 0x06, 0x00, 0x0A, 0xBB, 0x0F, 0xFC, 0xCB, 0xFE, 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, + 0x2D, 0x44, 0x04, 0x26, 0x02, 0x00, 0x0F, 0xFC, 0x05, 0xFF, 0x30, 0xF1, 0x27, 0x44, 0x05, 0x22, + 0x2D, 0x00, 0xFA, 0xB4, 0x40, 0x47, 0x2D, 0x44, 0x10, 0x2A, 0x24, 0x00, 0x28, 0x40, 0xD4, 0x3A, + 0x21, 0x00, 0x31, 0x40, 0x08, 0x26, 0x00, 0x7C, 0x2B, 0x44, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, + 0x64, 0x44, 0xC4, 0x84, 0xFF, 0xFF, 0x04, 0x24, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, + 0x20, 0x29, 0x6D, 0xE2, 0x12, 0x60, 0xC0, 0x63, 0x1D, 0xF0, 0xC0, 0x64, 0xC0, 0x84, 0xA3, 0xD1, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, 0xA3, 0xDB, 0xA8, 0x60, + 0x89, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x07, 0x00, 0x02, 0x2A, 0x05, 0x00, + 0xFD, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x05, 0x64, 0x3A, 0xDB, 0x28, 0x44, + 0xA4, 0x3A, 0x04, 0x00, 0x39, 0xF1, 0x25, 0x44, 0x0A, 0x36, 0x38, 0xF1, 0x31, 0x40, 0x08, 0x26, + 0x00, 0x7C, 0x2B, 0x44, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, 0x64, 0x44, 0xC4, 0x84, 0xFF, 0xFF, + 0x04, 0x24, 0x00, 0xB4, 0x28, 0x40, 0xE4, 0x36, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, + 0x20, 0x29, 0x6D, 0xE2, 0xA7, 0x60, 0x8E, 0x78, 0xFF, 0xFF, 0x21, 0x46, 0xB5, 0xFF, 0xBC, 0xFF, + 0x47, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x27, 0x44, + 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xEA, 0x01, + 0x27, 0x44, 0x05, 0x22, 0x09, 0x00, 0xBA, 0xB4, 0x40, 0x47, 0x3C, 0x46, 0x02, 0x64, 0x31, 0xFB, + 0xC0, 0xFE, 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, 0x27, 0x44, 0x02, 0x2A, 0x06, 0x00, 0xFD, 0xB4, + 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xF4, 0x01, 0xF3, 0x0A, 0x7C, 0x50, 0x6D, 0xE2, + 0xF0, 0x01, 0x72, 0x45, 0xDC, 0x84, 0x95, 0xFB, 0x11, 0x64, 0x3A, 0xDB, 0x96, 0xF3, 0x06, 0x04, + 0xDC, 0x84, 0x96, 0xFB, 0x97, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x97, 0xFB, 0xA7, 0x60, 0xA6, 0x78, + 0xFF, 0xFF, 0x00, 0x61, 0x12, 0x64, 0x3A, 0xDB, 0x16, 0x60, 0xBA, 0x63, 0xBD, 0xD3, 0x72, 0x45, + 0x44, 0x8A, 0x02, 0x28, 0x02, 0x00, 0xE4, 0xE2, 0xDD, 0x81, 0x02, 0x28, 0x02, 0x00, 0xE4, 0xE2, + 0xDD, 0x81, 0xBD, 0xD3, 0x95, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, + 0xC4, 0x84, 0x60, 0x55, 0x2A, 0x52, 0x95, 0xFB, 0x02, 0x24, 0x01, 0xB9, 0xBD, 0xD3, 0x96, 0xF1, + 0x61, 0x45, 0xC0, 0x84, 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, 0xC4, 0x84, 0x96, 0xFB, 0x02, 0x24, + 0x01, 0xB9, 0xBD, 0xD3, 0x97, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0xC4, 0x84, 0x97, 0xFB, 0xA8, 0x60, + 0x0C, 0x78, 0xFF, 0xFF, 0xAE, 0x01, 0xA1, 0xFF, 0xFF, 0xFF, 0x01, 0x25, 0x09, 0x00, 0x04, 0x25, + 0x03, 0x00, 0x47, 0xFF, 0x32, 0x74, 0xA5, 0x01, 0xC4, 0xE2, 0xAF, 0x60, 0x19, 0x78, 0xFF, 0xFF, + 0x4C, 0x4E, 0x47, 0xFF, 0x32, 0x74, 0xCD, 0xE2, 0xAC, 0x60, 0x8F, 0x78, 0x00, 0x61, 0x10, 0x64, + 0x3A, 0xDB, 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, 0x5C, 0x4D, + 0x26, 0x44, 0x02, 0x26, 0x0C, 0x00, 0x3E, 0x46, 0x09, 0xF2, 0x1E, 0x41, 0x03, 0x1B, 0xAE, 0x60, + 0xCB, 0x78, 0xFF, 0xFF, 0x40, 0x5E, 0xFD, 0xFB, 0x21, 0x44, 0x02, 0x64, 0x40, 0x46, 0x41, 0x5D, + 0x21, 0x46, 0x00, 0xF2, 0x46, 0x45, 0x87, 0xFC, 0x4C, 0xE2, 0x01, 0x64, 0x33, 0xFB, 0x01, 0x60, + 0x0E, 0xE1, 0x03, 0xE1, 0x3F, 0x40, 0x01, 0x27, 0x00, 0x00, 0x21, 0x69, 0xB6, 0xFF, 0xA1, 0xFF, + 0x6C, 0x5E, 0xB6, 0xFF, 0xB7, 0xFF, 0x60, 0x5C, 0x20, 0x64, 0x3A, 0xDB, 0x68, 0x43, 0x26, 0xFC, + 0x22, 0x69, 0x64, 0x44, 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x5F, 0x60, 0x43, 0x26, 0xF2, 0xFF, 0xFF, + 0x68, 0x5F, 0x26, 0xFA, 0x3A, 0x69, 0x1D, 0xFC, 0x2E, 0x44, 0x36, 0xF1, 0x1C, 0xFA, 0xC3, 0x94, + 0xCD, 0xE2, 0x2E, 0x44, 0x14, 0x36, 0x12, 0x00, 0x0A, 0x36, 0x0F, 0x00, 0x63, 0x45, 0xE3, 0x83, + 0xE3, 0x83, 0xC7, 0x83, 0xE3, 0x83, 0xC7, 0x83, 0xFF, 0xFF, 0x37, 0x36, 0x05, 0x00, 0x6E, 0x36, + 0x04, 0x00, 0xAE, 0x60, 0xE3, 0x78, 0xFF, 0xFF, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, + 0xFF, 0xFF, 0x80, 0x27, 0xCF, 0x83, 0x1B, 0xFC, 0x01, 0x64, 0x4F, 0xFB, 0xA1, 0xFF, 0x1C, 0xF2, + 0x29, 0x41, 0xF9, 0x81, 0x52, 0x4A, 0x71, 0x89, 0x68, 0x5F, 0x27, 0xFA, 0x6C, 0x40, 0x03, 0x15, + 0xAE, 0x60, 0xF4, 0x78, 0xFF, 0xFF, 0x88, 0x60, 0x85, 0x71, 0x8D, 0xE2, 0x99, 0xF1, 0xFC, 0xA3, + 0xD3, 0x80, 0x43, 0x43, 0x03, 0x04, 0xAE, 0x60, 0xEB, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x01, 0x2A, + 0x4C, 0x00, 0x9A, 0xFF, 0x23, 0x43, 0x18, 0x61, 0xA1, 0xFF, 0x8C, 0x44, 0xCB, 0x83, 0x2A, 0xFA, + 0x40, 0x48, 0x40, 0x27, 0x04, 0xA1, 0x60, 0x40, 0x03, 0x2B, 0x01, 0x00, 0x06, 0xA1, 0x88, 0xB0, + 0x88, 0x36, 0xD9, 0x81, 0x62, 0x45, 0x23, 0x44, 0x54, 0x94, 0x28, 0x40, 0x04, 0x26, 0x00, 0x64, + 0x3F, 0xFA, 0xC9, 0x81, 0x65, 0x42, 0x7A, 0xDC, 0x00, 0xB9, 0xFD, 0x1C, 0x00, 0xF4, 0x6E, 0x61, + 0x10, 0x62, 0x14, 0x02, 0x05, 0x1D, 0x12, 0x1E, 0x0C, 0x00, 0x00, 0xF4, 0x7C, 0x61, 0x02, 0x62, + 0x7A, 0xDC, 0x63, 0x40, 0xFD, 0x1C, 0xF9, 0x1D, 0xFF, 0xB1, 0x08, 0x1E, 0x02, 0x02, 0x00, 0xF4, + 0x02, 0x62, 0xB6, 0xFF, 0xB7, 0xFF, 0xA1, 0xFF, 0x6C, 0x44, 0x5A, 0xDA, 0x98, 0xFF, 0x01, 0x60, + 0x08, 0xE1, 0x81, 0xE1, 0xA1, 0xFF, 0x6C, 0x40, 0xA1, 0xFF, 0x47, 0xFF, 0x26, 0x44, 0xFD, 0xB4, + 0x84, 0xBC, 0x01, 0x15, 0x7F, 0xB4, 0x40, 0x46, 0xA1, 0xFF, 0x6C, 0x40, 0x14, 0x63, 0x01, 0x11, + 0x01, 0x00, 0xFD, 0x1F, 0xAE, 0x60, 0x61, 0x78, 0xFF, 0xFF, 0x9A, 0xFF, 0x54, 0x63, 0x12, 0x64, + 0x40, 0x46, 0x00, 0x64, 0x0F, 0xFA, 0xA1, 0xFF, 0xCB, 0xF1, 0x12, 0x61, 0x50, 0xFE, 0x8C, 0x44, + 0xCC, 0xF0, 0xBD, 0xDA, 0x40, 0x48, 0x04, 0x26, 0x40, 0x00, 0xA1, 0xFF, 0x8C, 0x44, 0xBD, 0xDA, + 0x30, 0xFB, 0x6C, 0x44, 0xBD, 0xDA, 0xFF, 0xFF, 0x01, 0x26, 0x24, 0x00, 0xD0, 0x80, 0xA1, 0xFF, + 0x8C, 0x44, 0x6C, 0x5C, 0xF2, 0xFE, 0xBD, 0xDA, 0xCD, 0xF3, 0xD4, 0x80, 0xD0, 0x80, 0xBD, 0xD8, + 0x2D, 0x44, 0x15, 0x0C, 0x32, 0x40, 0x02, 0x2A, 0x07, 0x00, 0x28, 0x42, 0x0C, 0xB2, 0x08, 0x3A, + 0x03, 0x00, 0x10, 0xBC, 0x40, 0x4D, 0x4D, 0x00, 0x03, 0x0A, 0xAE, 0x60, 0xF9, 0x78, 0xFF, 0xFF, + 0x11, 0xBC, 0x40, 0x4D, 0x28, 0x45, 0xBF, 0x60, 0xFF, 0x64, 0x24, 0x88, 0x42, 0x00, 0x30, 0xBC, + 0x40, 0x4D, 0x3F, 0x00, 0x20, 0xB9, 0x5C, 0x8E, 0xA1, 0xFF, 0x8C, 0x44, 0xBD, 0xDA, 0xDC, 0x9C, + 0x6C, 0x44, 0xF2, 0xFE, 0xBD, 0xDA, 0x08, 0x28, 0x44, 0x4E, 0xDC, 0x84, 0x2E, 0x5C, 0xB0, 0x84, + 0xEF, 0xB1, 0x08, 0x24, 0x40, 0xB9, 0x41, 0x46, 0x2C, 0x00, 0x8C, 0x44, 0x04, 0x61, 0xBD, 0xDA, + 0x50, 0xFE, 0x80, 0x27, 0x00, 0x64, 0x30, 0xFB, 0x8C, 0x44, 0xBD, 0xDA, 0xD0, 0x80, 0x8C, 0x44, + 0xBD, 0xDA, 0xD4, 0x80, 0x00, 0x65, 0x8C, 0x44, 0xCD, 0xF1, 0xBD, 0xDA, 0xD0, 0x80, 0x28, 0x44, + 0x03, 0x0C, 0xA0, 0x2A, 0x0A, 0x00, 0x11, 0x00, 0x10, 0x65, 0x60, 0x40, 0xC4, 0x36, 0x04, 0x00, + 0xD4, 0x3A, 0x08, 0x00, 0x27, 0x40, 0x40, 0x26, 0x30, 0x65, 0x00, 0x64, 0x3F, 0xFA, 0x46, 0x4E, + 0x35, 0x8D, 0x5F, 0x00, 0x40, 0x26, 0xF9, 0x01, 0x30, 0x65, 0x9D, 0xDC, 0x9D, 0xDC, 0x9D, 0xDC, + 0xF4, 0x01, 0x00, 0xE1, 0x23, 0x43, 0xE8, 0xA3, 0x6A, 0x62, 0x9A, 0xFF, 0xA1, 0xFF, 0x28, 0x44, + 0x03, 0x2B, 0x04, 0x00, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x28, 0x44, 0x88, 0xB0, 0x88, 0x2A, + 0x03, 0x00, 0x70, 0x62, 0x7A, 0xDC, 0x28, 0x44, 0x40, 0x2B, 0x13, 0x00, 0x72, 0x62, 0x7A, 0xDC, + 0x04, 0xE6, 0x7A, 0xDC, 0x3B, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x2B, 0x02, 0x00, 0x7A, 0xDC, + 0x7A, 0xDC, 0x08, 0x60, 0x00, 0xEB, 0xFC, 0xA3, 0x25, 0xFF, 0x3F, 0xFC, 0x04, 0xA3, 0xB0, 0xFF, + 0x01, 0x00, 0x3F, 0xFC, 0xCF, 0x83, 0xDF, 0x83, 0x04, 0x02, 0x00, 0xF4, 0x10, 0x62, 0x6C, 0x61, + 0x1F, 0x00, 0x27, 0x03, 0xCB, 0x83, 0xFF, 0x60, 0xFE, 0x65, 0x0E, 0xA3, 0xA7, 0x84, 0xF2, 0xA3, + 0x00, 0xF4, 0x10, 0x62, 0x6C, 0x61, 0x7A, 0xDC, 0xFE, 0x1C, 0x03, 0x1D, 0x7C, 0xA8, 0xD9, 0x81, + 0x0A, 0x02, 0x00, 0xF4, 0x02, 0x62, 0xA7, 0x84, 0x7A, 0x61, 0x7A, 0xDC, 0xFE, 0x1C, 0xF9, 0x1D, + 0x7C, 0xA8, 0xD9, 0x81, 0xF6, 0x03, 0xFF, 0xB1, 0x0C, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, + 0xA1, 0xFF, 0x01, 0x60, 0x0C, 0xE1, 0xB6, 0xFF, 0xB7, 0xFF, 0xA1, 0xFF, 0xCD, 0x81, 0x6C, 0x44, + 0x5A, 0xDA, 0x98, 0xFF, 0x00, 0xE6, 0x7C, 0x44, 0x33, 0xFB, 0x01, 0x60, 0x0C, 0xE1, 0x83, 0xE1, + 0xA1, 0xFF, 0x8C, 0x44, 0x46, 0x45, 0xA1, 0xFF, 0x14, 0x63, 0x01, 0x10, 0xFE, 0x1F, 0x01, 0x60, + 0x08, 0xE1, 0x0A, 0x64, 0x60, 0x54, 0x47, 0xFF, 0x50, 0x4B, 0x67, 0x50, 0x69, 0xE2, 0x6A, 0x40, + 0x40, 0x2B, 0x01, 0x15, 0x29, 0x00, 0x6C, 0x40, 0x28, 0x40, 0x03, 0x26, 0x15, 0x00, 0x31, 0x40, + 0x20, 0x2A, 0x03, 0x00, 0x28, 0x40, 0x50, 0x3A, 0x0F, 0x00, 0x2D, 0x44, 0x20, 0x2A, 0x0C, 0x00, + 0x2B, 0x44, 0xAC, 0x80, 0x28, 0x40, 0xB4, 0x3A, 0x03, 0x00, 0x02, 0x03, 0x30, 0xFB, 0x04, 0x00, + 0x2B, 0x50, 0xA8, 0x60, 0x92, 0x78, 0x04, 0xE1, 0x04, 0xE1, 0xA1, 0xFF, 0x35, 0xF1, 0x26, 0x44, + 0x64, 0x54, 0xCD, 0xE2, 0x84, 0xBC, 0x2D, 0x40, 0x0C, 0x22, 0xFD, 0xB4, 0x40, 0x46, 0x23, 0x64, + 0x3A, 0xDB, 0xAB, 0x60, 0x6A, 0x78, 0xFF, 0xFF, 0x27, 0x40, 0x26, 0x22, 0x04, 0x00, 0x02, 0x64, + 0x31, 0xFB, 0xC0, 0xFE, 0xFF, 0xFF, 0x6C, 0x40, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, + 0x08, 0x60, 0x00, 0x6B, 0x37, 0xF3, 0x2B, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x02, 0x28, 0x65, 0x44, + 0x60, 0x50, 0xA0, 0x4C, 0x20, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0x35, 0xF1, 0x74, 0x44, 0xC0, 0x94, + 0x32, 0x40, 0x02, 0x2A, 0x18, 0x00, 0x28, 0x44, 0xA4, 0x36, 0x04, 0x00, 0x0C, 0xB4, 0xFF, 0xFF, + 0x04, 0x36, 0x11, 0x00, 0x26, 0x43, 0xFD, 0xB3, 0x04, 0xBB, 0x43, 0x46, 0x01, 0x2A, 0x03, 0x00, + 0x28, 0x47, 0x40, 0xBF, 0x40, 0x48, 0x0A, 0xBB, 0x0F, 0xFC, 0x50, 0x4B, 0x67, 0x50, 0x00, 0x64, + 0x30, 0xFB, 0x05, 0xFF, 0xC6, 0x01, 0x24, 0x64, 0x3A, 0xDB, 0x28, 0x44, 0x04, 0x2A, 0x03, 0x00, + 0xA7, 0x60, 0x8E, 0x78, 0xFF, 0xFF, 0x1D, 0xFF, 0x48, 0xE2, 0x27, 0x44, 0x06, 0x22, 0x05, 0x00, + 0xF9, 0xB4, 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x26, 0x40, 0x10, 0x2A, 0x18, 0x00, + 0x26, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0xFF, 0xB4, 0xC0, 0xA0, 0xFF, 0xFF, 0x11, 0x0E, 0x98, 0xF1, + 0x1E, 0x60, 0xF8, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, + 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, + 0xAC, 0x60, 0x05, 0x78, 0xFF, 0xFF, 0x98, 0xF1, 0x1E, 0x60, 0xFA, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, + 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, + 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x2A, 0x64, 0x3A, 0xDB, 0x5C, 0x41, 0x87, 0xE1, + 0xA1, 0xFF, 0x6C, 0x40, 0x02, 0x00, 0x29, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x08, 0xE1, 0x87, 0xE1, + 0xA1, 0xFF, 0x6C, 0x40, 0x11, 0x00, 0x1F, 0x60, 0x0C, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, + 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0xF1, 0x01, 0x01, 0x60, 0x08, 0xE1, 0x21, 0x64, 0x3A, 0xDB, + 0x03, 0x00, 0x01, 0x60, 0x08, 0xE1, 0x6C, 0x40, 0x00, 0x64, 0x33, 0xFB, 0x32, 0x74, 0x40, 0x63, + 0x01, 0x16, 0xFE, 0x01, 0x01, 0x68, 0x01, 0x11, 0x09, 0x00, 0xA7, 0x6A, 0x22, 0x64, 0x3A, 0xDB, + 0x03, 0x60, 0xC9, 0x63, 0x01, 0x11, 0x02, 0x00, 0x6C, 0x40, 0xFC, 0x1F, 0x6C, 0x40, 0xB5, 0xFF, + 0x6C, 0x40, 0xBC, 0xFF, 0x6C, 0x40, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, + 0x00, 0x6B, 0x03, 0x0A, 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x4F, 0xFB, 0x27, 0x44, + 0x06, 0x22, 0x06, 0x00, 0xF9, 0xB4, 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x48, 0xE2, + 0x27, 0x64, 0x3A, 0xDB, 0xB3, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x54, 0x62, 0x22, 0x46, + 0xA2, 0xD0, 0x16, 0x63, 0x7C, 0x41, 0x44, 0x48, 0x80, 0x36, 0x04, 0x61, 0x28, 0x40, 0x50, 0x36, + 0x04, 0x61, 0x41, 0x4E, 0x28, 0x44, 0xA4, 0x36, 0x0E, 0x63, 0x12, 0x60, 0xC2, 0x62, 0xA2, 0xD1, + 0x24, 0x44, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, 0xA2, 0xDB, + 0x9A, 0xFF, 0xA1, 0xFF, 0x54, 0x62, 0xA2, 0xD2, 0xFF, 0xFF, 0x6A, 0x40, 0x80, 0x4E, 0x7A, 0xD4, + 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0xFF, 0xFF, 0x01, 0x1D, + 0x78, 0x00, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x28, 0x40, 0x03, 0x2B, 0x04, 0x00, + 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x6A, 0x40, 0x70, 0x62, 0x28, 0x44, 0x88, 0xB0, 0x88, 0x36, + 0x7A, 0xD4, 0x28, 0x40, 0x40, 0x2B, 0x0B, 0x00, 0x72, 0x62, 0x7A, 0xD4, 0x7A, 0xD4, 0xA2, 0xD2, + 0xFF, 0xFF, 0x60, 0x40, 0x20, 0x2B, 0x02, 0x00, 0x7A, 0xD4, 0x7A, 0xD4, 0x46, 0x00, 0x23, 0x43, + 0xCF, 0x83, 0xDF, 0x83, 0x02, 0x03, 0x55, 0x03, 0x04, 0x00, 0x03, 0xF0, 0x04, 0xF4, 0x64, 0x42, + 0x37, 0x00, 0x2E, 0x40, 0x04, 0x2A, 0x21, 0x00, 0xA1, 0xFF, 0x02, 0xFE, 0x10, 0x25, 0x42, 0xFE, + 0x72, 0x45, 0x65, 0x4C, 0x95, 0xF3, 0x03, 0x04, 0xE4, 0xE2, 0xDC, 0x84, 0x95, 0xFB, 0xA1, 0xFF, + 0x80, 0x4C, 0x96, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x96, 0xFB, 0x80, 0x4C, 0x97, 0xF3, 0x02, 0x04, + 0xDC, 0x84, 0x97, 0xFB, 0x80, 0x4C, 0x5C, 0x4E, 0xF8, 0xA3, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, + 0xFF, 0xB1, 0xF8, 0xA1, 0x06, 0xA4, 0x60, 0x42, 0x09, 0x00, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, + 0xC8, 0x82, 0xFF, 0xB1, 0x03, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0xFF, 0xB1, 0x7A, 0xD4, 0xFF, 0xFF, + 0xFD, 0x1C, 0xF9, 0x1D, 0xFF, 0xB1, 0x17, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0xDA, 0x82, 0xDA, 0x82, + 0xA2, 0xD2, 0xA1, 0xFF, 0x09, 0x74, 0x80, 0x4D, 0x0E, 0x00, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, + 0x23, 0x43, 0xA1, 0xFF, 0xA0, 0xD2, 0xFE, 0xA1, 0xCB, 0x83, 0x80, 0x4E, 0xAF, 0x83, 0x02, 0x1D, + 0x02, 0x03, 0xED, 0x01, 0xE3, 0x01, 0xA1, 0xFF, 0x28, 0x40, 0x40, 0x2B, 0x02, 0x00, 0x9C, 0x4E, + 0x9C, 0x4C, 0xA1, 0xFF, 0xDA, 0x83, 0x66, 0x44, 0x22, 0x46, 0x0C, 0xFA, 0x0B, 0xFC, 0x87, 0x4F, + 0x87, 0x4C, 0x87, 0x4F, 0x87, 0x4D, 0x87, 0x4C, 0x01, 0x08, 0x01, 0x00, 0xFF, 0xFF, 0x87, 0x4C, + 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x44, 0xBC, 0xFF, 0x01, 0x60, + 0x08, 0xE1, 0x0C, 0x74, 0x04, 0xE1, 0xA1, 0xFF, 0x35, 0xF3, 0xC4, 0xE2, 0x60, 0x54, 0x89, 0xFF, + 0x13, 0x74, 0x88, 0xFF, 0x29, 0x44, 0xF7, 0xB4, 0x40, 0x49, 0x34, 0x64, 0x3A, 0xDB, 0x06, 0xE1, + 0x47, 0xFF, 0xA8, 0x60, 0x64, 0x78, 0xFF, 0xFF, 0xFF, 0x01, 0x08, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, + 0x43, 0xFF, 0x01, 0x60, 0x00, 0xE1, 0x28, 0xF3, 0x47, 0xFF, 0x60, 0x40, 0x07, 0x37, 0x4B, 0x00, + 0x05, 0x3B, 0x04, 0x00, 0xFF, 0x0A, 0x80, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x29, 0xF5, 0x2A, 0xF3, + 0x47, 0xFF, 0x3F, 0xF0, 0x01, 0x1B, 0x01, 0x64, 0x60, 0x56, 0xAD, 0xE2, 0xB5, 0xFF, 0x6C, 0x40, + 0x40, 0xE1, 0xA1, 0xFF, 0x00, 0xF4, 0x6E, 0x61, 0x12, 0x62, 0x64, 0x43, 0x01, 0xE1, 0x03, 0x64, + 0xE2, 0xD0, 0xC9, 0x81, 0x64, 0x4C, 0xCC, 0x84, 0xDA, 0x82, 0xFA, 0x02, 0x01, 0x60, 0x00, 0x6B, + 0x9A, 0xFF, 0xCA, 0x82, 0x03, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0xFF, 0xFF, 0x7A, 0xD0, 0xA1, 0xFF, + 0x64, 0x4C, 0xFC, 0x1C, 0xF8, 0x1D, 0x00, 0xB9, 0x06, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0xDA, 0x82, + 0x5A, 0xD2, 0xA1, 0xFF, 0x60, 0x4D, 0x3F, 0x40, 0x02, 0x2B, 0x08, 0x00, 0x28, 0xF3, 0xA5, 0x60, + 0xC4, 0x65, 0x60, 0x40, 0x0E, 0x3B, 0x02, 0x00, 0x80, 0x4C, 0xFE, 0x01, 0xA1, 0xFF, 0x87, 0x4E, + 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x67, 0x4C, 0xFF, 0xFF, 0xBC, 0xFF, 0x00, 0xE1, + 0xD5, 0xFE, 0xA1, 0xFF, 0xFF, 0xFF, 0x00, 0x64, 0x40, 0x46, 0x60, 0x41, 0xB5, 0xFF, 0xB7, 0xFF, + 0xB4, 0xFF, 0x29, 0xF5, 0x3F, 0xF0, 0x24, 0xF2, 0x44, 0x43, 0x40, 0x44, 0x00, 0xF4, 0xF3, 0x60, + 0xA0, 0x65, 0x10, 0x62, 0x5A, 0xD2, 0xD9, 0x81, 0xD4, 0x80, 0xFF, 0xFF, 0xFB, 0x02, 0x61, 0x45, + 0x24, 0x44, 0xD4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xFD, 0xA5, 0x48, 0x60, 0x00, 0x64, + 0xC4, 0x9D, 0x0D, 0x60, 0x00, 0x6B, 0x24, 0x44, 0xC0, 0x83, 0xBB, 0xFF, 0x29, 0xF5, 0x01, 0xE1, + 0x00, 0xF4, 0x6C, 0x61, 0x10, 0x62, 0x05, 0x00, 0x00, 0xF4, 0x01, 0xF2, 0xFF, 0xFF, 0x60, 0x41, + 0x04, 0x62, 0xA1, 0xFF, 0xFF, 0xFF, 0x01, 0x10, 0x1A, 0x00, 0x26, 0x44, 0x01, 0x26, 0x0C, 0x00, + 0x24, 0x44, 0xC8, 0x84, 0x40, 0x44, 0x02, 0x03, 0x6C, 0x45, 0xF3, 0x01, 0x03, 0x15, 0x01, 0x64, + 0x05, 0xFA, 0x15, 0x00, 0x6C, 0x45, 0xED, 0x01, 0x23, 0x44, 0xC8, 0x84, 0x40, 0x43, 0x02, 0x03, + 0x6C, 0x45, 0xE7, 0x01, 0x00, 0x64, 0x01, 0x15, 0x01, 0x64, 0x6C, 0x45, 0x05, 0xFB, 0xE2, 0xD2, + 0xDA, 0x82, 0xC9, 0x81, 0x60, 0x4C, 0xDD, 0x1C, 0xD7, 0x03, 0xBC, 0xFF, 0xDA, 0x01, 0x00, 0xE1, + 0xD5, 0xFE, 0xA1, 0xFF, 0xFF, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, 0x67, 0x4C, 0x43, 0xFF, 0xAD, 0x4F, + 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0x01, 0xE1, 0x01, 0x60, 0x69, 0x6B, 0xA5, 0x60, 0xC4, 0x64, + 0x60, 0x4C, 0xBB, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x60, 0x4C, 0xA1, 0xFF, 0xFF, 0xFF, 0x60, 0x4C, + 0xFC, 0x01, 0x29, 0xF3, 0x2A, 0xF1, 0x07, 0xB5, 0x04, 0xE1, 0x65, 0x41, 0x64, 0x54, 0xCD, 0xE2, + 0x95, 0x81, 0xA1, 0x5D, 0xA1, 0xFF, 0xFF, 0xFF, 0xF9, 0x01, 0x00, 0xE1, 0x30, 0x40, 0x02, 0x36, + 0xA1, 0xFF, 0x83, 0xFF, 0x8D, 0xFF, 0x5C, 0x44, 0x5C, 0x43, 0x5C, 0x42, 0x5C, 0x41, 0x5C, 0x40, + 0xAC, 0xFF, 0xAD, 0xFF, 0xE7, 0xE1, 0xB1, 0x60, 0xC0, 0x78, 0xFF, 0xFF, 0x10, 0x61, 0x7F, 0x60, + 0xC0, 0x64, 0xA0, 0x80, 0x7F, 0x67, 0x02, 0x63, 0x26, 0x02, 0x98, 0xFE, 0x1A, 0x05, 0x1B, 0x60, + 0xB8, 0x62, 0xA2, 0xD5, 0x0E, 0xF2, 0x15, 0x18, 0x02, 0x18, 0x09, 0xF4, 0xFB, 0x01, 0x23, 0x44, + 0x00, 0xA8, 0x08, 0x7E, 0x0A, 0x02, 0x66, 0x44, 0x11, 0xFB, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, + 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x08, 0xB9, 0x10, 0x7E, 0x00, 0x7F, 0x0E, 0xFA, 0x00, 0x67, + 0x0A, 0x00, 0x20, 0x44, 0xDC, 0x85, 0x0F, 0xB4, 0xF6, 0xA0, 0x7F, 0x67, 0x07, 0x63, 0x03, 0x05, + 0x45, 0x40, 0x00, 0x67, 0xD8, 0xFE, 0xFF, 0x27, 0x05, 0xFD, 0x0A, 0x7E, 0x04, 0xFB, 0x61, 0x55, + 0x4A, 0x00, 0x28, 0xFB, 0x01, 0xF3, 0x29, 0xFB, 0x44, 0x46, 0x40, 0x45, 0x10, 0x61, 0x7E, 0x60, + 0xC0, 0x64, 0xA0, 0x80, 0x7F, 0x67, 0x02, 0x63, 0x31, 0x02, 0xB3, 0x60, 0x58, 0x4F, 0x22, 0x78, + 0xFF, 0xFF, 0x7F, 0x67, 0x03, 0x63, 0x2A, 0x02, 0x26, 0x40, 0x01, 0x2B, 0x24, 0x00, 0x98, 0xFE, + 0x19, 0x05, 0x1B, 0x60, 0xB8, 0x62, 0xA2, 0xD5, 0x0E, 0xF2, 0x14, 0x18, 0x02, 0x18, 0x09, 0xF4, + 0xFB, 0x01, 0x23, 0x44, 0x00, 0xA8, 0x08, 0x7E, 0x0A, 0x02, 0x66, 0x44, 0x11, 0xFB, 0x46, 0x43, + 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x08, 0xB9, 0x10, 0x7E, 0x00, 0x7F, + 0x0E, 0xFA, 0x09, 0x00, 0x20, 0x44, 0xDC, 0x85, 0x0F, 0xB4, 0xF6, 0xA0, 0x7F, 0x67, 0x07, 0x63, + 0x05, 0x05, 0x45, 0x40, 0xD8, 0xFE, 0x00, 0x67, 0xD0, 0xFE, 0xD9, 0xFE, 0xFF, 0x27, 0x05, 0xFD, + 0x0B, 0x7E, 0x04, 0xFB, 0x12, 0x60, 0xC8, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB0, 0x80, 0xBC, + 0x08, 0x28, 0xA3, 0xDB, 0x61, 0x55, 0x63, 0x00, 0x04, 0xB5, 0x82, 0xB5, 0x25, 0x02, 0x04, 0x03, + 0x20, 0x44, 0x7F, 0xB4, 0x40, 0x40, 0xA3, 0xD3, 0x99, 0xFE, 0x04, 0x04, 0x02, 0xBC, 0xFE, 0xB4, + 0xA3, 0xDB, 0x56, 0x00, 0xBC, 0xF3, 0x20, 0x40, 0x80, 0x26, 0x52, 0x00, 0xA3, 0xD3, 0xFF, 0xA0, + 0xF8, 0xB4, 0x02, 0x02, 0xA3, 0xDB, 0x1C, 0x00, 0x04, 0xBC, 0xBF, 0xB4, 0xA3, 0xDB, 0x08, 0xB0, + 0x01, 0x64, 0x08, 0x24, 0x02, 0x64, 0x28, 0xFB, 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, 0xD0, 0xFE, + 0x3F, 0x00, 0xBF, 0xB4, 0xA3, 0xDB, 0x3C, 0x00, 0x40, 0xB0, 0xFF, 0xFF, 0xFA, 0x02, 0xF8, 0xB4, + 0xA3, 0xDB, 0x08, 0xB5, 0x07, 0x7C, 0x01, 0x02, 0xBC, 0xF9, 0x20, 0x44, 0x7F, 0xB4, 0x40, 0x40, + 0x12, 0x60, 0xC8, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB5, 0x07, 0xB5, 0x08, 0x28, 0xC4, 0x02, + 0x99, 0xFE, 0x26, 0x05, 0x20, 0x44, 0x80, 0x26, 0x23, 0x00, 0x20, 0x2A, 0x00, 0x00, 0x40, 0x2A, + 0x1F, 0x00, 0xBF, 0xB4, 0x40, 0x40, 0x09, 0x00, 0xA8, 0xFF, 0x20, 0x44, 0x99, 0xFE, 0x02, 0x05, + 0x80, 0x2A, 0x03, 0x00, 0x40, 0xBC, 0x40, 0x40, 0x13, 0x00, 0x00, 0xF1, 0x80, 0xBC, 0x40, 0x40, + 0x64, 0x44, 0xE0, 0x84, 0xE8, 0x84, 0x0A, 0x36, 0x29, 0x01, 0x0B, 0x36, 0x5A, 0x01, 0x28, 0xFB, + 0x01, 0xF1, 0x29, 0xF9, 0x02, 0xF1, 0x2A, 0xF9, 0x03, 0xF1, 0x2B, 0xF9, 0xD0, 0xFE, 0xAE, 0xFF, + 0xA1, 0xFF, 0xFF, 0xFF, 0x82, 0x3E, 0x75, 0x44, 0x02, 0xB0, 0x01, 0xB0, 0x28, 0x02, 0xDC, 0x02, + 0x04, 0xB0, 0x08, 0xB0, 0x0B, 0x02, 0x20, 0x02, 0x40, 0x26, 0xA7, 0xFF, 0x8C, 0xFF, 0x75, 0x40, + 0x80, 0x2B, 0x01, 0x00, 0xAB, 0xFF, 0x75, 0x44, 0x8D, 0xFF, 0xEA, 0x01, 0x0A, 0xF3, 0xAA, 0xFF, + 0x60, 0x40, 0x20, 0x2B, 0x02, 0x00, 0x60, 0xFF, 0x0D, 0x00, 0x01, 0x26, 0x0C, 0x00, 0xC0, 0x60, + 0x00, 0x7C, 0xA0, 0x84, 0x80, 0x3B, 0x02, 0x00, 0xC0, 0x67, 0x03, 0x00, 0x40, 0x3B, 0x02, 0x00, + 0x00, 0x67, 0x0A, 0xFB, 0xD5, 0x01, 0xD4, 0x01, 0xAB, 0xFF, 0x00, 0x00, 0xD1, 0x01, 0x79, 0x63, + 0xFF, 0xFF, 0xFF, 0x1F, 0xA9, 0xFF, 0x77, 0x44, 0x60, 0x57, 0x10, 0x60, 0x00, 0x75, 0x40, 0x4A, + 0x01, 0x2A, 0x1C, 0x00, 0x24, 0x44, 0xAC, 0x86, 0x08, 0xF2, 0x18, 0x03, 0x1B, 0x60, 0xBE, 0x65, + 0xD4, 0x80, 0x0E, 0xF2, 0x02, 0x03, 0xA5, 0xD5, 0x04, 0x00, 0x01, 0xBC, 0x0E, 0xFA, 0x09, 0xF4, + 0xD1, 0xFE, 0x46, 0x44, 0x0B, 0x18, 0x66, 0x44, 0x10, 0xFB, 0x66, 0x47, 0x20, 0xBF, 0x3B, 0x42, + 0x04, 0xA2, 0xA2, 0xDB, 0x0E, 0xF2, 0x01, 0x75, 0x10, 0xBC, 0x0E, 0xFA, 0x2A, 0x44, 0x08, 0x2A, + 0x18, 0x00, 0x23, 0x44, 0x00, 0xA8, 0x5C, 0x43, 0x14, 0x03, 0x1B, 0x60, 0xB8, 0x62, 0xA2, 0xD5, + 0x01, 0x00, 0x09, 0xF4, 0x0E, 0xF2, 0x0D, 0x18, 0x08, 0xB0, 0x18, 0xAC, 0xFA, 0x03, 0x0E, 0xFA, + 0x66, 0x43, 0x11, 0xFD, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, + 0x08, 0x75, 0x2A, 0x44, 0x06, 0x22, 0x2D, 0x00, 0x22, 0x44, 0x00, 0xA8, 0x60, 0x46, 0x0E, 0xF2, + 0x28, 0x03, 0x10, 0xB0, 0x01, 0xBC, 0x03, 0x02, 0x00, 0x64, 0x40, 0x42, 0x22, 0x00, 0x0E, 0xFA, + 0xD1, 0xFE, 0x1B, 0x60, 0xB2, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x80, 0x00, 0x46, 0x42, 0x19, 0x02, + 0x22, 0x47, 0x40, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x23, 0xF2, 0x66, 0x43, 0x00, 0xA8, + 0x0E, 0xF2, 0x08, 0x02, 0x60, 0x40, 0x02, 0x2A, 0xE4, 0x01, 0x12, 0xFD, 0x10, 0x64, 0x0E, 0xFA, + 0x02, 0x75, 0x07, 0x00, 0x60, 0x40, 0x04, 0x2A, 0xDC, 0x01, 0x12, 0xFD, 0x10, 0x64, 0x0E, 0xFA, + 0x04, 0x75, 0x2A, 0x44, 0x80, 0x2A, 0x19, 0x00, 0x21, 0x44, 0xAC, 0x86, 0x0E, 0xF2, 0x15, 0x03, + 0x01, 0xBC, 0x0E, 0xFA, 0xD1, 0xFE, 0x1B, 0x60, 0xCA, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x56, 0x00, + 0x46, 0x41, 0x0B, 0x02, 0x21, 0x47, 0x10, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x0E, 0xF2, + 0x66, 0x43, 0x08, 0xFD, 0x10, 0xBC, 0x0E, 0xFA, 0x80, 0x75, 0x2A, 0x44, 0x10, 0xB0, 0x20, 0x44, + 0x15, 0x03, 0x7F, 0xB4, 0x40, 0x40, 0x12, 0x60, 0xC8, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB0, + 0x80, 0xB0, 0x09, 0x03, 0x08, 0x03, 0x40, 0xBC, 0x7F, 0xB4, 0x04, 0xB0, 0xA3, 0xDB, 0x03, 0x03, + 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, 0xB1, 0x60, 0x90, 0x78, 0xFF, 0xFF, 0xB1, 0x60, 0xC0, 0x78, + 0xFF, 0xFF, 0xE8, 0xFE, 0x14, 0x05, 0xEA, 0xFE, 0x24, 0x05, 0xE9, 0xFE, 0x1C, 0x05, 0xE7, 0xFE, + 0x09, 0x05, 0x47, 0xFF, 0x20, 0x44, 0x0F, 0x22, 0x03, 0x00, 0xCC, 0x84, 0x40, 0x40, 0x0F, 0x22, + 0xB8, 0xFE, 0xEC, 0x01, 0x23, 0x41, 0x00, 0xB9, 0x5C, 0x4A, 0xE8, 0x02, 0x6E, 0x01, 0x24, 0x41, + 0x00, 0xB9, 0x1B, 0x60, 0xBE, 0x65, 0x45, 0x47, 0xE1, 0x02, 0x58, 0x4F, 0x0F, 0x00, 0xDE, 0x02, + 0x5C, 0x4A, 0x46, 0x44, 0x50, 0x01, 0x22, 0x41, 0x00, 0xB9, 0x5C, 0x4A, 0x08, 0x24, 0x81, 0x01, + 0xD5, 0x01, 0x21, 0x41, 0x00, 0xB9, 0x5C, 0x4A, 0xA6, 0x03, 0xD0, 0x01, 0x27, 0xD3, 0x03, 0x00, + 0x10, 0xB0, 0x09, 0xF2, 0x04, 0x03, 0xAC, 0x86, 0x0E, 0xF2, 0xFA, 0x02, 0x08, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x0E, 0xF3, 0x0F, 0x60, 0xFE, 0x65, 0x0C, 0xF3, 0x24, 0x86, 0x24, 0x46, 0x60, 0x40, + 0xFB, 0x3B, 0x07, 0x00, 0x80, 0x26, 0x02, 0x00, 0x23, 0x46, 0x03, 0x4C, 0x46, 0x61, 0x3A, 0x65, + 0x0C, 0x00, 0x2E, 0xF3, 0x40, 0x45, 0xF8, 0x2B, 0x02, 0x00, 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, + 0x39, 0x00, 0x07, 0x02, 0x58, 0x4F, 0x45, 0x00, 0x04, 0x05, 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, + 0x09, 0x00, 0x26, 0x47, 0x00, 0xBF, 0x0E, 0xFB, 0x2E, 0xF5, 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, + 0x00, 0x72, 0x7E, 0x71, 0xAC, 0xFF, 0xB1, 0x60, 0xC0, 0x78, 0xFF, 0xFF, 0x8E, 0xFF, 0x0F, 0xF3, + 0x0F, 0x60, 0xFE, 0x65, 0x24, 0x86, 0x0D, 0xF3, 0x2E, 0xF3, 0x40, 0x45, 0xF8, 0x2B, 0x02, 0x00, + 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, 0x16, 0x00, 0x07, 0x02, 0x58, 0x4F, 0x22, 0x00, 0x04, 0x05, + 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, 0x09, 0x00, 0x26, 0x47, 0x00, 0xBF, 0x0F, 0xFB, 0x2E, 0xF5, + 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, 0x00, 0x72, 0x7E, 0x71, 0x8D, 0xFF, 0xAD, 0xFF, 0xB1, 0x60, + 0xC0, 0x78, 0xFF, 0xFF, 0x25, 0x44, 0x8A, 0xF1, 0x8B, 0xF1, 0xD0, 0x80, 0xD0, 0x80, 0x07, 0x04, + 0x01, 0x06, 0x05, 0x00, 0x25, 0x46, 0x01, 0xF0, 0x03, 0x67, 0xA0, 0x85, 0x94, 0x80, 0x2F, 0x58, + 0xFF, 0xFF, 0x25, 0x46, 0x26, 0x41, 0x46, 0x63, 0x01, 0xF2, 0xFF, 0xFF, 0xFF, 0xB5, 0xD5, 0x81, + 0x00, 0xF2, 0x05, 0x04, 0x04, 0x63, 0x60, 0x46, 0xF7, 0x1B, 0x42, 0xFE, 0x0D, 0x00, 0x61, 0x44, + 0xC5, 0x81, 0x63, 0x45, 0xC5, 0x81, 0x9C, 0x84, 0xDC, 0x84, 0x01, 0xF2, 0xF0, 0x85, 0xF0, 0x80, + 0x65, 0x44, 0xF8, 0x85, 0xFF, 0xFF, 0x02, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, 0x1B, 0x60, + 0xD0, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xAC, 0x86, 0x0E, 0xF2, 0x07, 0x03, 0x00, 0xA8, 0x09, 0xF2, + 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, 0x08, 0xFE, 0x17, 0x00, 0x8C, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, + 0x00, 0xB4, 0x12, 0x06, 0x09, 0x60, 0x08, 0x61, 0x41, 0x4A, 0x7C, 0xA1, 0x0E, 0xA1, 0xA2, 0xFF, + 0xB3, 0x60, 0x58, 0x4E, 0x97, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x06, 0x03, 0x2A, 0x43, 0xB3, 0x60, + 0x58, 0x4E, 0xB8, 0x78, 0xFF, 0xFF, 0x08, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0x41, 0x4A, + 0x7C, 0xA1, 0x0E, 0xA1, 0xA2, 0xFF, 0xB3, 0x60, 0x58, 0x4E, 0x97, 0x78, 0xFF, 0xFF, 0x07, 0x03, + 0x2A, 0x43, 0xB3, 0x60, 0x58, 0x4E, 0xB8, 0x78, 0xFF, 0xFF, 0x08, 0xFE, 0x0D, 0x00, 0x1B, 0x60, + 0xD0, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xAC, 0x86, 0x0E, 0xF2, 0x06, 0x03, 0x00, 0xA8, 0x09, 0xF2, + 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, 0x08, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0x8D, 0xF3, + 0x7C, 0x63, 0x00, 0xBE, 0x40, 0x45, 0x1A, 0x03, 0x00, 0x65, 0x65, 0x44, 0xDC, 0x85, 0x84, 0xA1, + 0x00, 0xF2, 0x06, 0x06, 0x01, 0xFC, 0x00, 0xA8, 0x60, 0x46, 0xF7, 0x02, 0x40, 0x45, 0x0E, 0x00, + 0x8C, 0xF3, 0x00, 0x63, 0xD4, 0x84, 0x8C, 0xFB, 0x80, 0x60, 0x7C, 0x64, 0x01, 0xFA, 0x00, 0xF0, + 0x00, 0xFC, 0xD3, 0x80, 0x8D, 0xF9, 0x02, 0x02, 0x8E, 0xF9, 0x08, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, + 0x66, 0x44, 0x25, 0x46, 0x05, 0xFA, 0x06, 0xFA, 0x01, 0xF0, 0x03, 0x67, 0x02, 0xFC, 0xB0, 0x84, + 0x3A, 0x7E, 0x01, 0xFA, 0x12, 0x64, 0x03, 0xFA, 0x00, 0xF0, 0x04, 0xF8, 0x00, 0x64, 0x0C, 0x61, + 0x10, 0x63, 0x59, 0xDA, 0xFE, 0x1F, 0x2E, 0x58, 0xFF, 0xFF, 0x27, 0x43, 0xE3, 0x81, 0xE9, 0x81, + 0x03, 0x05, 0x16, 0x03, 0x00, 0x61, 0x01, 0x00, 0xE4, 0x63, 0x61, 0x46, 0xBF, 0xD2, 0x27, 0x45, + 0xDC, 0x84, 0xA2, 0xDA, 0xBE, 0xD2, 0x25, 0x46, 0x88, 0xF8, 0x04, 0x1B, 0x25, 0x44, 0x61, 0x46, + 0xA3, 0xDA, 0x04, 0x00, 0x0A, 0xFA, 0x60, 0x46, 0x25, 0x44, 0x09, 0xFA, 0x61, 0x46, 0xBE, 0xDA, + 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x44, 0x00, 0xA8, 0x07, 0x4B, 0x0C, 0x03, 0x58, 0x4F, 0x33, 0x00, + 0x0B, 0x47, 0x1B, 0x60, 0xC4, 0x65, 0x27, 0x44, 0xD4, 0x80, 0x00, 0x64, 0x01, 0x02, 0x0F, 0xFA, + 0x58, 0x4F, 0xD3, 0x01, 0x70, 0x00, 0x25, 0x43, 0xE3, 0x84, 0x7C, 0x41, 0x02, 0x04, 0xE8, 0x81, + 0xE4, 0x63, 0x61, 0x46, 0xA3, 0xD2, 0x00, 0x7C, 0x40, 0x45, 0xBF, 0xD8, 0xA3, 0xD8, 0xBE, 0xD8, + 0x27, 0x42, 0x5A, 0xD3, 0x25, 0x5C, 0x60, 0x41, 0x02, 0x1B, 0x27, 0xD9, 0x05, 0x00, 0x25, 0x46, + 0x0A, 0xFA, 0x61, 0x46, 0x25, 0x44, 0x09, 0xFA, 0x25, 0x44, 0x27, 0x43, 0x00, 0x61, 0x60, 0x46, + 0x09, 0xF2, 0x08, 0xFC, 0x00, 0xA8, 0xDD, 0x81, 0xFA, 0x02, 0xBF, 0xD1, 0x66, 0x44, 0xBE, 0xDB, + 0xC1, 0x84, 0xBF, 0xDB, 0x48, 0x00, 0x25, 0x46, 0xE4, 0x63, 0x08, 0xF2, 0x89, 0xF2, 0x1E, 0x18, + 0x40, 0x47, 0xE0, 0x84, 0xE8, 0x85, 0x02, 0x05, 0xE8, 0x83, 0x00, 0x65, 0x65, 0x46, 0xBF, 0xD2, + 0x61, 0x5C, 0xCC, 0x84, 0xA2, 0xDA, 0x25, 0x46, 0x0A, 0xF2, 0x00, 0xB9, 0x65, 0x46, 0x08, 0x24, + 0xBE, 0xDA, 0x02, 0x1B, 0xA3, 0xD8, 0x02, 0x00, 0x60, 0x46, 0x89, 0xFA, 0x00, 0xB9, 0x61, 0x46, + 0x08, 0x28, 0x0A, 0xFA, 0x25, 0x46, 0x89, 0xFC, 0x8A, 0xFC, 0x88, 0xFC, 0x2F, 0x58, 0xFF, 0xFF, + 0x00, 0x61, 0x28, 0x65, 0x25, 0x43, 0x8E, 0xF3, 0xAF, 0x83, 0x00, 0xBE, 0x18, 0x03, 0x02, 0x03, + 0x00, 0xFC, 0x01, 0x00, 0x8D, 0xFD, 0x63, 0x46, 0x65, 0x44, 0xCC, 0x85, 0x00, 0xF2, 0x07, 0x02, + 0x8E, 0xF5, 0x00, 0x64, 0x00, 0xFA, 0xDE, 0x60, 0xAF, 0x64, 0x09, 0xFB, 0x08, 0x00, 0x66, 0x43, + 0x00, 0xBE, 0xDD, 0x81, 0xF1, 0x02, 0x8C, 0xF1, 0x8E, 0xFD, 0xC1, 0x84, 0x8C, 0xFB, 0x2E, 0x58, + 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x45, 0x29, 0x43, 0xFC, 0xA3, 0x66, 0x44, 0xBD, 0xDB, 0x25, 0x44, + 0xBD, 0xDB, 0x00, 0x64, 0xBD, 0xDB, 0x03, 0x61, 0x0E, 0x65, 0x1B, 0x60, 0xD8, 0x63, 0x43, 0x49, + 0xA3, 0xD3, 0x06, 0xA3, 0x00, 0xA8, 0xCD, 0x81, 0x04, 0x02, 0xF9, 0x02, 0xB1, 0x60, 0xC0, 0x78, + 0xFF, 0xFF, 0x01, 0x26, 0xE6, 0x01, 0xD4, 0x80, 0x60, 0x45, 0xE3, 0x05, 0xF6, 0xA3, 0xBD, 0xD1, + 0xBD, 0xD1, 0x44, 0x47, 0x44, 0x48, 0x44, 0x45, 0x1C, 0x60, 0x16, 0x64, 0x44, 0xD7, 0xFF, 0xFF, + 0xFF, 0xFF, 0x48, 0xFE, 0x8D, 0xF5, 0x8C, 0xF3, 0x0D, 0x18, 0xCC, 0x84, 0x8C, 0xFB, 0x80, 0x60, + 0x7C, 0x64, 0x01, 0xFA, 0x00, 0x64, 0x00, 0xF0, 0x00, 0xFA, 0xD0, 0x80, 0x8D, 0xF9, 0x02, 0x02, + 0x8E, 0xF9, 0x08, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x1B, 0x60, 0x88, 0x63, 0x0D, 0x65, 0x00, 0x61, + 0x41, 0x48, 0xA3, 0xD3, 0x06, 0xA3, 0xAC, 0x86, 0x00, 0x61, 0x09, 0x03, 0x00, 0xF2, 0x09, 0xF0, + 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x64, 0x44, 0xAC, 0x86, 0xF6, 0x01, 0x61, 0x44, + 0x25, 0x46, 0x27, 0xDA, 0x65, 0x44, 0x28, 0x45, 0x45, 0x88, 0xCC, 0x85, 0x5A, 0x87, 0xE9, 0x02, + 0x00, 0x64, 0x27, 0xDA, 0x5A, 0xDA, 0x5A, 0x87, 0x88, 0xF3, 0x87, 0xF1, 0x02, 0xA4, 0x60, 0x46, + 0x60, 0x45, 0x00, 0x61, 0x1E, 0xF2, 0xFF, 0xFF, 0xAC, 0x86, 0x00, 0xF2, 0x04, 0x03, 0xAC, 0x86, + 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x65, 0x44, 0x02, 0xA5, 0x65, 0x46, 0x64, 0x44, 0xCC, 0x9C, + 0xFF, 0xFF, 0xF0, 0x02, 0x61, 0x44, 0x25, 0x46, 0x27, 0xDA, 0x5A, 0x87, 0x28, 0x45, 0x45, 0x88, + 0x88, 0xF3, 0x87, 0xF1, 0x02, 0xA4, 0x60, 0x46, 0x60, 0x45, 0x00, 0x61, 0x72, 0xF2, 0xFF, 0xFF, + 0xAC, 0x86, 0x00, 0xF2, 0x09, 0x03, 0x00, 0xF2, 0x09, 0xF0, 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, + 0xFC, 0x02, 0x64, 0x44, 0xAC, 0x86, 0xF6, 0x01, 0x65, 0x44, 0x02, 0xA5, 0x65, 0x46, 0x64, 0x44, + 0xCC, 0x9C, 0x61, 0x44, 0xEB, 0x02, 0x25, 0x46, 0x27, 0xDA, 0x5A, 0x87, 0x28, 0x45, 0x45, 0x88, + 0x06, 0x60, 0x40, 0x65, 0x8D, 0xF3, 0x01, 0x61, 0xAC, 0x86, 0x00, 0xF2, 0x03, 0x03, 0xD5, 0x80, + 0xDD, 0x81, 0xFA, 0x04, 0xCD, 0x84, 0x25, 0x46, 0x27, 0xDA, 0x28, 0x45, 0xC4, 0x84, 0x5A, 0xDA, + 0xDA, 0x81, 0x8C, 0xF1, 0x59, 0xD8, 0x1B, 0x60, 0x86, 0x64, 0x18, 0x63, 0xA0, 0xD1, 0x06, 0xA4, + 0x59, 0xD8, 0xFC, 0x1F, 0x00, 0x64, 0x59, 0xDA, 0x59, 0xDA, 0x01, 0x60, 0x1C, 0x64, 0x0A, 0x63, + 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, 0x7E, 0xF1, 0x59, 0xD8, 0x45, 0x01, 0x07, 0x4B, 0xB4, 0x60, + 0x58, 0x4F, 0x23, 0x78, 0xFF, 0xFF, 0x0B, 0x47, 0x58, 0x4F, 0x21, 0x00, 0x3C, 0x01, 0x07, 0x4B, + 0xB4, 0x60, 0x58, 0x4F, 0x23, 0x78, 0xFF, 0xFF, 0x0B, 0x47, 0x27, 0x44, 0x00, 0xBE, 0x08, 0xF0, + 0x15, 0x03, 0x64, 0x42, 0x4A, 0xD3, 0x09, 0xF2, 0xDC, 0x83, 0xA2, 0xDD, 0x25, 0x43, 0x09, 0xFC, + 0x63, 0x46, 0x27, 0x43, 0x0A, 0xFC, 0x09, 0xFA, 0x08, 0xF8, 0x00, 0xA8, 0x66, 0x43, 0x03, 0x02, + 0x64, 0x44, 0x58, 0xDD, 0x03, 0x00, 0x60, 0x46, 0x25, 0x44, 0x0A, 0xFA, 0x1C, 0x01, 0x27, 0x43, + 0xE3, 0x81, 0xE9, 0x81, 0x03, 0x05, 0x16, 0x03, 0x00, 0x61, 0x01, 0x00, 0xE4, 0x63, 0x61, 0x46, + 0xBF, 0xD2, 0x27, 0x45, 0xDC, 0x84, 0xA2, 0xDA, 0xA3, 0xD2, 0x25, 0x46, 0x88, 0xF8, 0x04, 0x1B, + 0x25, 0x44, 0x61, 0x46, 0xBE, 0xDA, 0x04, 0x00, 0x09, 0xFA, 0x60, 0x46, 0x25, 0x44, 0x0A, 0xFA, + 0x61, 0x46, 0xA3, 0xDA, 0x2F, 0x58, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x03, 0x02, + 0x28, 0xE2, 0x40, 0xFF, 0xA1, 0xFF, 0x84, 0xFF, 0xBF, 0x60, 0xAD, 0x64, 0x40, 0x42, 0xB5, 0x60, + 0xA2, 0x64, 0x40, 0x40, 0x9D, 0xF3, 0x66, 0xFB, 0x0F, 0x60, 0x9A, 0x63, 0xAA, 0xF3, 0xBD, 0xDB, + 0x00, 0x60, 0x9A, 0x64, 0xBD, 0xDB, 0x02, 0x64, 0xBD, 0xDB, 0x04, 0x64, 0xA3, 0xDB, 0x5C, 0x49, + 0x0A, 0x64, 0x40, 0x4B, 0x5C, 0x5C, 0x01, 0x60, 0x39, 0xE2, 0x04, 0x60, 0x00, 0x7A, 0x89, 0xFF, + 0x03, 0x60, 0xFF, 0x73, 0x88, 0xFF, 0xB5, 0x60, 0xA2, 0x78, 0xFF, 0xFF, 0xA0, 0xFE, 0x07, 0x05, + 0xA3, 0xFE, 0x07, 0x05, 0xA1, 0xFE, 0x50, 0x05, 0x60, 0x64, 0x3B, 0xDB, 0x10, 0x00, 0x20, 0x58, + 0xFF, 0xFF, 0xFA, 0x01, 0x12, 0x60, 0xCC, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0xFB, 0xB4, 0xA3, 0xDB, + 0xA0, 0x4C, 0x59, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0xA0, 0x4C, 0x7D, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, + 0xFF, 0xFF, 0x83, 0x3E, 0x40, 0x60, 0x0B, 0x65, 0x2B, 0x44, 0x00, 0x63, 0xE8, 0x80, 0xF8, 0x84, + 0x02, 0x24, 0x94, 0x84, 0xF3, 0x83, 0xCD, 0x81, 0xFF, 0xFF, 0xF8, 0x02, 0xDF, 0x83, 0x2F, 0x58, + 0x40, 0x4B, 0x00, 0x62, 0x01, 0x64, 0xD4, 0x80, 0xE0, 0x84, 0x1A, 0x03, 0xD4, 0x80, 0xE0, 0x84, + 0x15, 0x03, 0x61, 0x44, 0x11, 0x61, 0xE0, 0x84, 0xCD, 0x81, 0xFD, 0x04, 0x01, 0x00, 0xE0, 0x84, + 0xF2, 0x82, 0xFF, 0xFF, 0x02, 0x24, 0xC6, 0x82, 0x02, 0x28, 0xD6, 0x82, 0xE2, 0x80, 0xCD, 0x81, + 0x02, 0x28, 0x01, 0xBC, 0xF4, 0x02, 0x01, 0x2A, 0xC6, 0x82, 0x03, 0x00, 0xE9, 0x81, 0xF2, 0x82, + 0x61, 0x44, 0x2D, 0x58, 0xFF, 0xFF, 0x00, 0xA8, 0x10, 0x61, 0x04, 0x03, 0xF0, 0x84, 0xCD, 0x81, + 0xFD, 0x04, 0x61, 0x44, 0x2D, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x3B, 0xDB, 0x16, 0x60, 0xA8, 0x63, + 0xBD, 0xD3, 0xA3, 0xD1, 0x60, 0x40, 0x04, 0x3A, 0x2D, 0x00, 0x00, 0x64, 0x4A, 0xDB, 0x1B, 0x60, + 0x88, 0x63, 0xA3, 0xD3, 0x46, 0x43, 0xAC, 0x86, 0x3C, 0x45, 0x23, 0x03, 0xD4, 0x80, 0x07, 0xF2, + 0x02, 0x02, 0x09, 0xF2, 0xF8, 0x01, 0xD0, 0x80, 0x09, 0xF2, 0xF5, 0x02, 0x60, 0x43, 0x80, 0x67, + 0xB0, 0x81, 0x1B, 0x60, 0xDA, 0x62, 0x61, 0x44, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x09, 0x60, 0x08, 0x65, 0x0E, 0xF2, 0x02, 0xF2, 0x60, 0x40, + 0xF0, 0x37, 0x05, 0x00, 0x90, 0xF3, 0xD4, 0x80, 0xCC, 0x84, 0x01, 0x02, 0x90, 0xFB, 0x63, 0x44, + 0xDA, 0x01, 0x23, 0x46, 0x3C, 0x44, 0xAC, 0x80, 0xFF, 0xFF, 0x89, 0x02, 0x6A, 0xF3, 0x6B, 0xF3, + 0x02, 0xA8, 0x02, 0xA8, 0x08, 0x02, 0x00, 0x64, 0x6C, 0xFB, 0x6A, 0xFB, 0x6B, 0xFB, 0x00, 0x64, + 0x6D, 0xFB, 0xCA, 0xFE, 0x97, 0x00, 0x03, 0x02, 0x00, 0x64, 0x6B, 0xFB, 0xCA, 0xFE, 0x01, 0x64, + 0x3B, 0xDB, 0x1B, 0x60, 0x8E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x35, 0x03, + 0x2C, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x8A, 0x00, 0x2E, 0xF2, 0x12, 0x60, 0xCE, 0x65, + 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, + 0x16, 0x18, 0x61, 0x46, 0x2E, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, + 0x2D, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2C, 0xF0, 0x63, 0x46, + 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x88, 0xF3, + 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x63, 0x02, 0x66, 0x45, 0x63, 0x46, 0x06, 0xF2, 0x65, 0x46, + 0x80, 0xB0, 0x09, 0xF2, 0x5C, 0x03, 0xAC, 0x86, 0xCA, 0x01, 0x6B, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, + 0xFF, 0xFF, 0x50, 0x02, 0x1B, 0x60, 0xA0, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, + 0x0F, 0x03, 0x77, 0xF1, 0x07, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, 0x09, 0xF2, 0x03, 0x02, 0xAC, 0x86, + 0x07, 0xF2, 0xFA, 0x02, 0x03, 0x02, 0x00, 0x64, 0x77, 0xFB, 0xEC, 0x01, 0x46, 0x5C, 0x3F, 0x00, + 0x1B, 0x60, 0xA6, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x01, 0x03, 0x37, 0x02, + 0x6C, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, 0x14, 0x02, 0x1B, 0x60, 0x94, 0x62, 0xA2, 0xD3, + 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x0B, 0x03, 0x2A, 0xF0, 0x20, 0x67, 0x09, 0xF2, 0xB0, 0x83, + 0x00, 0xA8, 0x00, 0x64, 0x02, 0x03, 0x2A, 0xFC, 0x01, 0x00, 0x6C, 0xFB, 0x20, 0x00, 0x00, 0x64, + 0x6C, 0xFB, 0x1B, 0x60, 0x88, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x12, 0x03, + 0x2A, 0xF0, 0x08, 0x67, 0xA0, 0x80, 0xFF, 0xFF, 0x12, 0x03, 0x77, 0xF1, 0x07, 0xF2, 0xFF, 0xFF, + 0xD0, 0x80, 0x09, 0xF2, 0x03, 0x02, 0xAC, 0x86, 0x07, 0xF2, 0xFA, 0x02, 0x08, 0x02, 0x00, 0x64, + 0x77, 0xFB, 0xE7, 0x01, 0x00, 0x64, 0x77, 0xFB, 0xB5, 0x60, 0xA2, 0x78, 0xFF, 0xFF, 0x66, 0x44, + 0xFC, 0xFB, 0x46, 0x5C, 0x21, 0x60, 0x98, 0x63, 0xA3, 0xD3, 0xB5, 0x60, 0x58, 0x4D, 0xE3, 0x78, + 0xFF, 0xFF, 0x0D, 0xF2, 0x60, 0x5C, 0x64, 0x5F, 0x0D, 0xFA, 0x07, 0xF0, 0x2A, 0xF2, 0xFF, 0xFF, + 0x77, 0xF9, 0x60, 0x40, 0x08, 0x2B, 0x05, 0x00, 0x00, 0x64, 0x48, 0xFB, 0xB8, 0x60, 0x2D, 0x78, + 0xFF, 0xFF, 0x00, 0x64, 0xD0, 0x80, 0x88, 0xF3, 0x07, 0x02, 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, + 0xA2, 0xDA, 0xBD, 0x60, 0x28, 0x78, 0xFF, 0xFF, 0xD0, 0x80, 0xB8, 0xF3, 0x03, 0x03, 0x60, 0x40, + 0x03, 0x3A, 0x00, 0x00, 0x2A, 0xF2, 0x00, 0x63, 0x40, 0x47, 0x50, 0x36, 0x01, 0x00, 0x01, 0x63, + 0x48, 0xFD, 0x4A, 0xF3, 0x35, 0xFA, 0x10, 0xA4, 0x4A, 0xFB, 0x00, 0x64, 0x15, 0xFA, 0x16, 0xFA, + 0x0F, 0xFA, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x0E, 0xF0, 0x63, 0x46, 0x00, 0x7F, + 0x64, 0x5E, 0x4B, 0xFB, 0x64, 0x44, 0x00, 0x7E, 0xBB, 0xFB, 0x07, 0xF0, 0x88, 0xF3, 0xFF, 0xFF, + 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0xBB, 0xF3, 0xBA, 0xFB, 0x60, 0x41, 0x03, 0xF2, 0x00, 0xF4, + 0x01, 0xF2, 0xFC, 0xA5, 0x00, 0x7F, 0xD4, 0x84, 0x27, 0x45, 0x3C, 0x46, 0x1A, 0xFA, 0x22, 0x63, + 0x7B, 0x60, 0xFF, 0x64, 0xA4, 0x84, 0x03, 0x2B, 0x1C, 0x63, 0x2A, 0xFA, 0x60, 0x40, 0xA4, 0x36, + 0x14, 0x63, 0x43, 0x4C, 0x00, 0x7C, 0x22, 0xF8, 0x64, 0x41, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, + 0x36, 0xF2, 0x63, 0x46, 0xFF, 0xB4, 0x22, 0xFA, 0x60, 0x40, 0x00, 0x36, 0x8E, 0x00, 0x2A, 0xF2, + 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x3A, 0x89, 0x00, 0x03, 0xF2, 0x00, 0xF4, 0xA0, 0xD2, 0xAA, 0x60, + 0xAA, 0x65, 0x5A, 0xD0, 0xD4, 0x80, 0x03, 0x64, 0x0A, 0x02, 0xD0, 0x80, 0x00, 0x64, 0x5A, 0xD0, + 0x06, 0x02, 0xD0, 0x80, 0xF8, 0x7F, 0xD0, 0x80, 0x01, 0x03, 0x01, 0x02, 0x01, 0x61, 0x62, 0x43, + 0x46, 0x43, 0x3C, 0x46, 0x07, 0xF4, 0x36, 0xF2, 0xFF, 0xFF, 0xA3, 0x46, 0x60, 0x40, 0x22, 0x26, + 0x45, 0x00, 0x60, 0x45, 0x63, 0x42, 0x5A, 0xD0, 0xCD, 0x81, 0x3C, 0x46, 0x14, 0x02, 0x64, 0x44, + 0x88, 0x3A, 0x11, 0x00, 0x8E, 0x3B, 0x0F, 0x00, 0x65, 0x44, 0x01, 0x26, 0x5E, 0x00, 0x04, 0x26, + 0x03, 0x00, 0x10, 0x26, 0x01, 0x00, 0x2D, 0x00, 0xA3, 0x46, 0x37, 0xF2, 0xFF, 0xFF, 0x60, 0x40, + 0x80, 0x2B, 0x53, 0x00, 0x3A, 0x00, 0xA3, 0x46, 0x65, 0x44, 0x01, 0x26, 0x0B, 0x00, 0x04, 0x26, + 0x03, 0x00, 0x10, 0x26, 0x01, 0x00, 0x1D, 0x00, 0x37, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x27, + 0x2C, 0x00, 0x17, 0x00, 0x88, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0x36, 0xF2, 0x66, 0x43, 0xFF, 0xB4, + 0x3C, 0x46, 0x22, 0xF0, 0x60, 0x47, 0xB0, 0x84, 0x22, 0xFA, 0x63, 0x46, 0x37, 0xF0, 0x60, 0x40, + 0x04, 0x27, 0x03, 0x00, 0x10, 0x27, 0x01, 0x00, 0x04, 0x00, 0x64, 0x40, 0x80, 0x27, 0x15, 0x00, + 0x00, 0x00, 0x3C, 0x46, 0x02, 0x65, 0xBC, 0x60, 0x58, 0x78, 0xFF, 0xFF, 0xCD, 0x81, 0x63, 0x42, + 0x5A, 0xD0, 0x3C, 0x46, 0x0A, 0x02, 0x64, 0x44, 0x88, 0x3A, 0x07, 0x00, 0x77, 0x37, 0x1D, 0x00, + 0x78, 0x37, 0x1B, 0x00, 0x8E, 0x37, 0x19, 0x00, 0xF1, 0x01, 0x3C, 0x46, 0x22, 0xF0, 0x80, 0x67, + 0xB0, 0x84, 0xA2, 0xDA, 0xFF, 0xFF, 0x3F, 0xF2, 0x3E, 0xF0, 0x08, 0xA4, 0x60, 0x41, 0x22, 0xF2, + 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, 0x03, 0x00, 0x06, 0x00, 0x04, 0x2B, + 0x04, 0x00, 0x61, 0x44, 0x64, 0x40, 0x10, 0x26, 0x3F, 0xFA, 0x3C, 0x46, 0x2C, 0xF2, 0x27, 0x40, + 0x01, 0x27, 0x32, 0xF2, 0xB5, 0xF1, 0x60, 0x40, 0x01, 0x26, 0x53, 0x00, 0x09, 0x60, 0x00, 0x64, + 0xD0, 0x80, 0x3F, 0xF2, 0x09, 0x06, 0x2C, 0x45, 0xC4, 0x84, 0xD0, 0x80, 0x40, 0x4A, 0x40, 0x06, + 0x60, 0x43, 0x64, 0x44, 0x54, 0x88, 0x18, 0x00, 0x60, 0x45, 0x1F, 0x60, 0x9C, 0x64, 0xA0, 0xD3, + 0xBB, 0xF3, 0x00, 0xBC, 0x60, 0x47, 0xEC, 0xA0, 0x33, 0x03, 0x32, 0x07, 0x2C, 0x44, 0xC4, 0x81, + 0x02, 0x60, 0x1C, 0x65, 0x45, 0x4A, 0xD5, 0x80, 0x2C, 0x45, 0x2A, 0x06, 0x27, 0x40, 0x04, 0x27, + 0x30, 0x00, 0x2A, 0x43, 0xD7, 0x85, 0x45, 0x48, 0xB6, 0xF1, 0x0F, 0xF2, 0xD3, 0x80, 0x01, 0x65, + 0x01, 0x07, 0x00, 0x65, 0xB4, 0x84, 0x0F, 0xFA, 0x00, 0x63, 0x3F, 0xF2, 0x28, 0x45, 0x60, 0x41, + 0xD4, 0x84, 0xDF, 0x83, 0xFC, 0x07, 0x14, 0xFC, 0x61, 0x44, 0x01, 0x36, 0x02, 0x00, 0x09, 0x3A, + 0x06, 0x00, 0x28, 0x44, 0x48, 0x88, 0x2A, 0x44, 0xC8, 0x83, 0x43, 0x4A, 0xE5, 0x01, 0x17, 0xFA, + 0x04, 0x60, 0x00, 0x64, 0x27, 0x45, 0xB4, 0x84, 0x2A, 0xFA, 0x28, 0x43, 0x16, 0xFC, 0x0D, 0x00, + 0x3F, 0xF2, 0x2C, 0x45, 0xB6, 0xF1, 0xC4, 0x81, 0xD1, 0x80, 0x0F, 0xF2, 0x01, 0x06, 0x01, 0xBC, + 0x0F, 0xFA, 0x3F, 0xF2, 0x17, 0xFA, 0x01, 0x64, 0x14, 0xFA, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, + 0x0E, 0xF0, 0x63, 0x46, 0x00, 0x7F, 0x64, 0x5E, 0x4B, 0xFB, 0x64, 0x44, 0x00, 0x7E, 0xBB, 0xFB, + 0x62, 0xF1, 0x60, 0x43, 0x60, 0x47, 0xD0, 0x80, 0xC0, 0x65, 0x01, 0x06, 0x64, 0x44, 0x0A, 0x36, + 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, 0x37, 0x36, 0x15, 0x64, 0x6E, 0x36, 0x0B, 0x64, 0x44, 0x86, + 0x2A, 0xF2, 0x07, 0xF0, 0x60, 0x40, 0xB0, 0x3A, 0x03, 0x00, 0x40, 0x3B, 0x01, 0x00, 0x12, 0x00, + 0x0C, 0xB4, 0x08, 0x3A, 0x55, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, 0x50, 0x00, + 0x17, 0xF2, 0x22, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x22, 0x22, 0x04, 0x00, 0x00, 0xA8, 0x01, 0xA8, + 0x47, 0x03, 0x46, 0x03, 0x3C, 0x46, 0x2A, 0xF0, 0x40, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x60, 0x45, + 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x43, 0x60, 0x40, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, 0x0A, 0x00, + 0x02, 0x00, 0x04, 0x27, 0x07, 0x00, 0x65, 0x44, 0x2A, 0x65, 0x60, 0x40, 0x03, 0x2B, 0x24, 0x65, + 0x45, 0x4C, 0x2E, 0x00, 0x65, 0x44, 0x2E, 0x65, 0x60, 0x40, 0x03, 0x2B, 0x28, 0x65, 0x45, 0x4C, + 0x07, 0xF0, 0x88, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0x00, 0x7C, 0x03, 0x03, 0x63, 0x40, 0x01, 0x2A, + 0x01, 0x00, 0x3D, 0xF1, 0x2A, 0xF2, 0xFF, 0xFF, 0x08, 0xB0, 0x3E, 0xF2, 0x19, 0x03, 0x60, 0x47, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x03, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, 0x11, 0x03, 0x1B, 0x60, + 0xD4, 0x62, 0x1B, 0x60, 0xAC, 0x64, 0xA2, 0xDB, 0x3C, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0x5C, 0x5C, 0xFC, 0xFC, 0xCE, 0xFE, 0xB5, 0x60, 0xEC, 0x78, 0xFF, 0xFF, + 0xBB, 0xF1, 0x2C, 0x45, 0x64, 0x43, 0x17, 0xF2, 0x4B, 0xF1, 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x81, 0x63, 0x40, 0x37, 0x37, 0xE1, 0x81, 0x64, 0x45, 0xB5, 0x60, 0x58, 0x4D, 0xC1, 0x78, + 0xFF, 0xFF, 0xAE, 0x82, 0xFC, 0xA2, 0x0A, 0x03, 0x63, 0x40, 0x6E, 0x3B, 0x06, 0x00, 0x60, 0x41, + 0x04, 0x0D, 0x63, 0x44, 0x80, 0x7E, 0xBB, 0xFB, 0x61, 0x44, 0xDC, 0x84, 0x2B, 0xF0, 0x1B, 0xFA, + 0x64, 0x44, 0x80, 0x27, 0x34, 0x00, 0x16, 0xF2, 0x0F, 0xF0, 0xAC, 0x84, 0x2C, 0x45, 0x29, 0x03, + 0x4B, 0xF1, 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, 0x63, 0x40, 0x37, 0x37, 0xE1, 0x81, + 0x64, 0x45, 0x0F, 0xF0, 0xB5, 0x60, 0x58, 0x4D, 0xC1, 0x78, 0xFF, 0xFF, 0xAE, 0x82, 0xFC, 0xA2, + 0x0A, 0x03, 0x63, 0x40, 0x6E, 0x3B, 0x06, 0x00, 0x60, 0x41, 0x04, 0x0D, 0x80, 0x67, 0xB0, 0x84, + 0x0F, 0xFA, 0x61, 0x44, 0xDC, 0x84, 0x1D, 0xFA, 0xDE, 0x65, 0xC4, 0x85, 0x26, 0x41, 0xE1, 0x81, + 0xC5, 0x84, 0x2B, 0xFA, 0x1B, 0xF0, 0xDE, 0x64, 0xC0, 0x85, 0x26, 0x44, 0xE0, 0x84, 0xC4, 0x84, + 0x10, 0xFA, 0x26, 0x44, 0x2C, 0xF0, 0x0A, 0xA4, 0x64, 0x40, 0x01, 0x26, 0x00, 0x64, 0x11, 0xFA, + 0xBB, 0xF3, 0x13, 0xFA, 0xFF, 0xFF, 0x0D, 0xF2, 0x3E, 0xF0, 0x60, 0x47, 0xFF, 0xB4, 0x64, 0x41, + 0x01, 0xB1, 0x01, 0x63, 0x1D, 0x02, 0x60, 0x41, 0xFF, 0x22, 0x04, 0x00, 0xB5, 0x60, 0x58, 0x4F, + 0xB2, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0x92, 0x64, 0xA0, 0xDD, 0x21, 0x60, 0x98, 0x62, 0xA2, 0xD3, + 0xB5, 0x60, 0x58, 0x4D, 0xE3, 0x78, 0xFF, 0xFF, 0x60, 0x41, 0x01, 0x63, 0x61, 0x40, 0xFF, 0x22, + 0x04, 0x00, 0xB5, 0x60, 0x58, 0x4F, 0xB2, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0x94, 0x64, 0xA0, 0xDD, + 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x27, 0x03, 0x00, 0xBA, 0x60, 0x4A, 0x78, 0xFF, 0xFF, + 0x22, 0xF2, 0x46, 0x43, 0x60, 0x40, 0x22, 0x26, 0x8B, 0x00, 0x01, 0x26, 0x05, 0x00, 0x04, 0x26, + 0x0C, 0x00, 0xBA, 0x60, 0x4A, 0x78, 0xFF, 0xFF, 0x04, 0x27, 0x03, 0x00, 0xBA, 0x60, 0x4A, 0x78, + 0xFF, 0xFF, 0x88, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0x02, 0x00, 0x07, 0xF4, 0xFF, 0xFF, 0xA3, 0x46, + 0x2A, 0xF2, 0xA3, 0x46, 0x60, 0x40, 0x08, 0x27, 0x3B, 0x00, 0x88, 0xF3, 0x66, 0x5C, 0xD0, 0x80, + 0x37, 0xF0, 0x08, 0x03, 0x64, 0x40, 0x10, 0x2A, 0x12, 0x00, 0xFF, 0x60, 0xEF, 0x64, 0xA0, 0x84, + 0x37, 0xFA, 0x24, 0x00, 0x3D, 0xF3, 0x01, 0x61, 0x60, 0x43, 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, + 0xE9, 0x81, 0xA1, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0x91, 0x84, 0x37, 0xFA, 0x17, 0x00, 0x47, 0xF2, + 0xFF, 0xFF, 0x10, 0xA0, 0xFF, 0xFF, 0x02, 0x04, 0xFF, 0x60, 0xFF, 0x64, 0xDC, 0x84, 0x47, 0xFA, + 0x46, 0xF2, 0x16, 0x04, 0xDC, 0x84, 0x46, 0xFA, 0x45, 0xF2, 0x08, 0x04, 0xDC, 0x84, 0x45, 0xFA, + 0x05, 0x04, 0x37, 0xF2, 0xFF, 0xFF, 0xE0, 0x84, 0xE8, 0x84, 0x37, 0xFA, 0x0D, 0x60, 0x3E, 0x62, + 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC4, 0x60, 0x05, 0x78, 0xFF, 0xFF, 0x84, 0xFF, + 0x0D, 0x60, 0x3E, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC4, 0x60, 0x7D, 0x78, + 0xFF, 0xFF, 0x84, 0xFF, 0x88, 0xF3, 0x66, 0x5C, 0xD0, 0x80, 0x00, 0x7C, 0x07, 0x03, 0x66, 0x43, + 0x3C, 0x46, 0x22, 0xF2, 0x63, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x01, 0x00, 0x3C, 0xF1, 0x47, 0xF0, + 0x64, 0x41, 0x64, 0x47, 0xFF, 0xB4, 0x60, 0x5F, 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, 0x60, 0x47, + 0xA3, 0x46, 0x3A, 0xFA, 0x64, 0x44, 0x20, 0x7F, 0x34, 0x94, 0x3B, 0xFA, 0xA3, 0x46, 0x46, 0xF2, + 0x45, 0xF0, 0xA3, 0x46, 0x3C, 0xFA, 0x3D, 0xF8, 0x08, 0x60, 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, + 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x8A, 0x00, + 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x27, 0x35, 0x00, 0x2A, 0xF2, 0x00, 0x60, 0x7C, 0x62, + 0x60, 0x40, 0x40, 0x2B, 0x27, 0x00, 0xA2, 0xD3, 0x00, 0x61, 0x60, 0xFE, 0xA0, 0xD3, 0xDE, 0x82, + 0xA2, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0xDC, 0x84, 0xF1, 0x81, 0xC0, 0x2B, 0x04, 0x00, + 0x80, 0x2A, 0x02, 0x00, 0x7F, 0xA4, 0xDC, 0x84, 0xFF, 0x3B, 0x03, 0x00, 0x60, 0x47, 0xDC, 0x87, + 0x01, 0x61, 0xC0, 0x80, 0x00, 0x36, 0xDC, 0x84, 0x4E, 0xDB, 0x60, 0xFE, 0xDA, 0x82, 0xA2, 0xD1, + 0xFF, 0xFF, 0xC1, 0x84, 0xF0, 0x22, 0x10, 0xA4, 0xF0, 0x2A, 0x01, 0x00, 0x00, 0x64, 0xA2, 0xDB, + 0xFF, 0xFF, 0x20, 0xFE, 0x00, 0x60, 0x7C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0xD3, 0x5A, 0xD1, + 0x3A, 0xFA, 0x3B, 0xF8, 0x74, 0x62, 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5A, + 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, + 0x80, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0xD1, 0x5A, 0xD1, 0x64, 0x45, 0x64, 0x44, 0xE3, 0x7F, + 0xA0, 0x5A, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5A, + 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5A, 0x65, 0x40, + 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE9, 0x7F, + 0xA0, 0x5A, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5A, + 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5A, 0x64, 0x47, + 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEF, 0x7F, 0xA0, 0x5A, 0x08, 0x60, 0x00, 0xEA, + 0x65, 0x44, 0x02, 0xA4, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, + 0xD1, 0x60, 0x00, 0xEA, 0x02, 0x64, 0x3B, 0xDB, 0xBD, 0x60, 0xEB, 0x78, 0xFF, 0xFF, 0x66, 0x44, + 0xFC, 0xFB, 0x07, 0xF0, 0x00, 0x64, 0xD0, 0x80, 0x88, 0xF3, 0x17, 0x03, 0xD0, 0x80, 0x66, 0x41, + 0x64, 0x46, 0x6F, 0xF2, 0x61, 0x46, 0x6D, 0x03, 0x60, 0x40, 0x00, 0x36, 0x6A, 0x00, 0x47, 0xF1, + 0x07, 0xF0, 0x64, 0x40, 0x02, 0x26, 0x01, 0x00, 0x0B, 0x00, 0x03, 0x12, 0xBB, 0x60, 0x4E, 0x78, + 0xFF, 0xFF, 0xFC, 0x0A, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, + 0x3E, 0xF2, 0x60, 0x45, 0x60, 0x47, 0x07, 0xB0, 0x00, 0x3A, 0x01, 0x00, 0xA6, 0x00, 0x65, 0x44, + 0x60, 0x40, 0x01, 0x36, 0x4E, 0x00, 0x02, 0x36, 0x4F, 0x00, 0x03, 0x36, 0x2D, 0x00, 0x04, 0x36, + 0x3E, 0x00, 0x52, 0x00, 0x00, 0x64, 0x4C, 0xFB, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, + 0x05, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x00, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, + 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, + 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, + 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, + 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, 0x1D, 0x00, 0x4C, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x4C, 0xFB, + 0xAB, 0xF3, 0x60, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x14, 0x02, 0x1C, 0x60, 0x0C, 0x62, 0x0F, 0x60, + 0x96, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xC3, 0x01, 0x4C, 0xF3, + 0x66, 0x41, 0xDC, 0x84, 0x4C, 0xFB, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x03, 0x7E, 0x6F, 0xFA, + 0x61, 0x46, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, + 0x01, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0xF5, 0x01, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0x8C, 0xFA, + 0x60, 0x47, 0x70, 0xF2, 0xFF, 0xB5, 0x08, 0x18, 0xE4, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x03, 0x02, + 0xFB, 0x04, 0x01, 0x64, 0x01, 0x00, 0x00, 0x64, 0x0C, 0xF4, 0x00, 0xA8, 0xFF, 0xFF, 0xE4, 0x02, + 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x70, 0xF2, 0xFF, 0xB5, 0x61, 0x46, + 0x00, 0xA8, 0xFF, 0xFF, 0x29, 0x03, 0xE0, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0x66, 0x41, + 0x64, 0x46, 0x70, 0xFA, 0x61, 0x46, 0x01, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, + 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, + 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, + 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, + 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, 0xA3, 0x01, 0xA2, 0x01, 0x65, 0x44, 0x60, 0x40, 0x01, 0x36, + 0xA8, 0x01, 0x02, 0x36, 0x01, 0x00, 0xA5, 0x01, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, + 0x01, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x00, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, + 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, + 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, + 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, + 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0x3E, 0xF2, 0x60, 0x45, + 0x60, 0x47, 0x07, 0xB0, 0x00, 0x3A, 0x01, 0x00, 0xA3, 0x00, 0x65, 0x44, 0x60, 0x40, 0x01, 0x36, + 0x0B, 0x00, 0x02, 0x36, 0x14, 0x00, 0x03, 0x36, 0x47, 0x00, 0x04, 0x36, 0x5E, 0x00, 0x05, 0x36, + 0x0E, 0x00, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, + 0xFF, 0xFF, 0x02, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0x07, 0xF0, + 0x01, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, + 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, + 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, + 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, + 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0x00, 0x63, 0x03, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x4C, 0xFD, + 0x1C, 0x60, 0x0C, 0x62, 0x0F, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x4C, 0xF3, + 0x02, 0xB0, 0x61, 0x46, 0xCC, 0x84, 0x05, 0x03, 0x04, 0x28, 0x4C, 0xFB, 0xBC, 0x60, 0x48, 0x78, + 0xFF, 0xFF, 0x04, 0x28, 0x4C, 0xFB, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x04, 0x7E, + 0x6F, 0xFA, 0x61, 0x46, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, + 0xFF, 0xFF, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x61, 0x46, 0xFF, 0xA0, 0xFF, 0xFF, 0x2F, 0x06, + 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x29, 0x00, 0x64, 0x46, 0x70, 0xFA, + 0x01, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, + 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, + 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, + 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, + 0x6F, 0xF2, 0x00, 0x63, 0x03, 0x7E, 0x6F, 0xFA, 0x3C, 0x46, 0x4C, 0xFD, 0x51, 0x00, 0x50, 0x00, + 0x65, 0x44, 0x60, 0x40, 0x01, 0x36, 0x03, 0x00, 0x02, 0x36, 0x12, 0x00, 0x49, 0x00, 0x66, 0x41, + 0x64, 0x46, 0x70, 0xF2, 0x61, 0x46, 0x01, 0xB0, 0xFF, 0xFF, 0x42, 0x02, 0x07, 0xF0, 0x66, 0x41, + 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x02, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x39, 0x00, 0x38, 0x00, + 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, 0x6F, 0xFA, 0x60, 0x47, + 0xFF, 0xB5, 0x70, 0xF2, 0x61, 0x46, 0xFF, 0xA0, 0xFF, 0xFF, 0xF1, 0x06, 0xE8, 0x84, 0xA4, 0x80, + 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0xEB, 0x01, 0x66, 0x41, 0x64, 0x46, 0x70, 0xFA, 0x61, 0x46, + 0x00, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, + 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, + 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, + 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, + 0x03, 0x64, 0x3B, 0xDB, 0xCA, 0xFE, 0x47, 0xF1, 0x01, 0x65, 0x32, 0x40, 0x04, 0x27, 0x08, 0x00, + 0x2C, 0xF2, 0x64, 0x45, 0x02, 0x22, 0x04, 0x00, 0x60, 0x40, 0x01, 0x26, 0x01, 0x00, 0xEC, 0x00, + 0x14, 0xF2, 0x65, 0x40, 0x01, 0x26, 0x1D, 0x00, 0x60, 0x45, 0x05, 0x64, 0x3B, 0xDB, 0x65, 0x44, + 0xCC, 0x85, 0x98, 0xF1, 0x1E, 0x60, 0xDE, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, + 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, + 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, + 0xAF, 0x00, 0x60, 0x41, 0x2A, 0xF0, 0x00, 0x60, 0x0C, 0x64, 0xA0, 0x84, 0x04, 0x36, 0x02, 0x00, + 0x0C, 0x3A, 0x01, 0x00, 0xA5, 0x00, 0x61, 0x45, 0x60, 0x41, 0x98, 0xF1, 0x1E, 0x60, 0xDE, 0x64, + 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, + 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, + 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x61, 0x40, 0x08, 0x36, 0x01, 0x00, 0x88, 0x00, + 0x14, 0xF2, 0x1C, 0x65, 0x60, 0x41, 0x00, 0x63, 0xCD, 0x81, 0xC7, 0x83, 0xFD, 0x02, 0x3F, 0xF0, + 0x2C, 0xF2, 0xC3, 0x83, 0x60, 0x40, 0x01, 0x2A, 0x29, 0x00, 0x98, 0xF1, 0x1E, 0x60, 0xDC, 0x64, + 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, + 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x98, 0xF1, 0x1E, 0x60, + 0xE2, 0x64, 0xA0, 0xD3, 0x63, 0x45, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, + 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, + 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x52, 0x00, 0x98, 0xF1, 0x1E, 0x60, + 0xDA, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, + 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x98, 0xF1, + 0x1E, 0x60, 0xE0, 0x64, 0xA0, 0xD3, 0x63, 0x45, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, + 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, + 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x15, 0xF2, 0xFF, 0xFF, + 0x0F, 0xB4, 0x00, 0xA8, 0x01, 0xA8, 0x24, 0x03, 0x12, 0x03, 0x98, 0xF1, 0x1E, 0x60, 0xE8, 0x64, + 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, + 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x11, 0x00, 0x98, 0xF1, + 0x1E, 0x60, 0xE6, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, + 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, + 0x04, 0x64, 0x3B, 0xDB, 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x06, 0xF0, 0xFF, 0x60, 0x5F, 0x64, + 0xA0, 0x84, 0x06, 0xFA, 0x61, 0x46, 0x1B, 0x60, 0xD4, 0x62, 0x1B, 0x60, 0xAC, 0x64, 0xA2, 0xDB, + 0x3C, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x5C, 0x5C, 0xFC, 0xFC, + 0xCE, 0xFE, 0xB5, 0x60, 0xEC, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0x64, 0x62, 0xA2, 0xD3, 0x07, 0xF4, + 0x06, 0xF2, 0x02, 0xA8, 0x3C, 0x46, 0x10, 0x03, 0x10, 0xB0, 0x2A, 0xF2, 0x0D, 0x03, 0x0E, 0xF2, + 0x0C, 0xB0, 0x60, 0x40, 0xF0, 0x37, 0x20, 0xBC, 0x02, 0x03, 0xFE, 0x7F, 0x0E, 0xFA, 0x23, 0xF0, + 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xCC, 0x01, 0x0F, 0xF0, 0x15, 0xF2, 0x64, 0x41, 0x01, 0x2A, + 0x02, 0x00, 0xB1, 0xF1, 0x09, 0x00, 0x03, 0x65, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x06, 0xF0, + 0x63, 0x46, 0xB0, 0xF1, 0x64, 0x40, 0x10, 0x2A, 0x64, 0x45, 0xDC, 0x84, 0xD4, 0x80, 0x15, 0xFA, + 0x3B, 0x07, 0x61, 0x40, 0x01, 0x2A, 0x09, 0x00, 0x1F, 0x60, 0x0E, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, + 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x08, 0x00, 0x1F, 0x60, 0x10, 0x64, 0xA0, 0xD3, + 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x2A, 0xF0, 0x08, 0x67, 0xB0, 0x84, + 0xA2, 0xDA, 0x08, 0xF0, 0x1B, 0x60, 0x8E, 0x64, 0xD0, 0x80, 0x07, 0xF2, 0x46, 0x43, 0x88, 0xF1, + 0x06, 0x03, 0x60, 0x46, 0x86, 0xF4, 0xD0, 0x80, 0x80, 0xBB, 0x01, 0x03, 0x06, 0xFC, 0x23, 0x46, + 0x3E, 0xF2, 0x00, 0x63, 0x01, 0xB0, 0x43, 0x5C, 0xFC, 0xFC, 0x0B, 0x03, 0x1B, 0x60, 0xDA, 0x62, + 0x1B, 0x60, 0xA6, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xB5, 0x60, 0xEC, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x49, 0xFB, 0x98, 0xF1, 0x1E, 0x60, + 0xE8, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, + 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x98, 0xF1, + 0x1E, 0x60, 0xEA, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, + 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, + 0x21, 0x60, 0x98, 0x63, 0xA3, 0xD3, 0xB5, 0x60, 0x58, 0x4D, 0xE3, 0x78, 0xFF, 0xFF, 0x0D, 0xF2, + 0x60, 0x5C, 0x64, 0x5F, 0x0D, 0xFA, 0x23, 0xF0, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x07, 0xF0, + 0x66, 0x41, 0x64, 0x46, 0x06, 0xF2, 0x7F, 0x65, 0xA4, 0x9E, 0x06, 0xFA, 0x61, 0x46, 0x40, 0x01, + 0xBE, 0x60, 0x70, 0x78, 0xFF, 0xFF, 0x21, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0x01, 0x63, 0xC4, 0xB4, + 0x31, 0xFB, 0x32, 0xFD, 0xBE, 0x60, 0x1C, 0x62, 0x42, 0x40, 0xA0, 0x4C, 0x40, 0xBC, 0x7D, 0xB4, + 0xA0, 0x51, 0xA0, 0xFE, 0x1A, 0xFF, 0x1B, 0x60, 0xA0, 0x64, 0x08, 0xF0, 0x07, 0xF0, 0xD0, 0x80, + 0x1B, 0x60, 0xA6, 0x62, 0x14, 0x02, 0xA2, 0xD3, 0x01, 0x63, 0xAC, 0x86, 0x07, 0xF2, 0x0F, 0x03, + 0xD0, 0x80, 0x09, 0xF2, 0xFA, 0x02, 0x23, 0xFC, 0x1B, 0x60, 0xD4, 0x62, 0x1B, 0x60, 0xAC, 0x64, + 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x3C, 0x46, + 0x06, 0x64, 0xA1, 0xFF, 0x49, 0xFB, 0x83, 0x3E, 0x31, 0xF3, 0x87, 0x60, 0x80, 0x61, 0x1D, 0xF0, + 0x60, 0x40, 0x01, 0x2A, 0x15, 0x00, 0xFE, 0xB4, 0x31, 0xFB, 0x00, 0x64, 0x49, 0xFB, 0x01, 0x64, + 0x47, 0xFB, 0x21, 0x60, 0x98, 0x63, 0xA3, 0xD3, 0xB5, 0x60, 0x58, 0x4D, 0xE3, 0x78, 0xFF, 0xFF, + 0x00, 0x71, 0x64, 0x5F, 0x0D, 0xFA, 0x40, 0x64, 0x3B, 0xDB, 0xBE, 0x60, 0x70, 0x78, 0xFF, 0xFF, + 0x02, 0x2A, 0x1B, 0x00, 0xD1, 0x91, 0x8D, 0xE2, 0x41, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0x21, 0x60, + 0xA0, 0x63, 0xFD, 0xB4, 0x31, 0xFB, 0xA3, 0xD3, 0xB5, 0x60, 0x58, 0x4D, 0xE3, 0x78, 0xFF, 0xFF, + 0x02, 0x63, 0x60, 0x5C, 0x0D, 0xF2, 0x47, 0xFD, 0xFF, 0xB5, 0x60, 0x47, 0xD0, 0x80, 0xDC, 0x84, + 0x1F, 0x03, 0x60, 0x47, 0xB4, 0x84, 0x0D, 0xFA, 0x1B, 0x00, 0x08, 0x2A, 0x07, 0x00, 0x42, 0x64, + 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, 0xF7, 0xB4, 0x31, 0xFB, 0x12, 0x00, 0x10, 0x2A, 0x09, 0x00, + 0x43, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, 0xEF, 0xB4, 0x31, 0xFB, 0xBD, 0x60, 0xEB, 0x78, + 0xFF, 0xFF, 0x44, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, 0xDF, 0xB4, 0x31, 0xFB, 0x00, 0x00, + 0x2A, 0x64, 0x3B, 0xDB, 0xB5, 0x60, 0xA2, 0x64, 0x40, 0x40, 0xBA, 0x60, 0x4F, 0x78, 0xFF, 0xFF, + 0x12, 0x60, 0xCC, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x02, 0xB5, 0x04, 0xB5, 0x04, 0x03, 0x03, 0x03, + 0xBE, 0x60, 0xF7, 0x78, 0xFF, 0xFF, 0xEB, 0x60, 0x58, 0x4E, 0x24, 0x78, 0xFF, 0xFF, 0x31, 0x40, + 0x01, 0x2A, 0x29, 0x00, 0x9D, 0xFE, 0x27, 0x04, 0x26, 0x0A, 0x9F, 0xFE, 0x24, 0x05, 0x85, 0xFF, + 0x20, 0x44, 0x84, 0xFF, 0x40, 0x26, 0x1F, 0x00, 0x3F, 0x40, 0x20, 0x2B, 0x1C, 0x00, 0x38, 0x69, + 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x16, 0xFD, 0x01, 0x01, 0x2A, 0x15, 0x00, 0x1F, 0x60, 0x1A, 0x64, + 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x65, 0xF1, 0x02, 0x60, + 0xEE, 0x64, 0x82, 0xFB, 0xFF, 0xFF, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0x83, 0xFB, 0x04, 0x64, + 0x84, 0xFB, 0xDF, 0xFE, 0x19, 0xFF, 0x10, 0x64, 0x3B, 0xDB, 0x66, 0xF3, 0x73, 0x45, 0xE0, 0x84, + 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x93, 0x75, 0xF1, 0xC9, 0xFE, 0x64, 0x40, 0x01, 0x26, 0x3D, 0x00, + 0x49, 0xF3, 0x3C, 0x46, 0x33, 0x18, 0xCC, 0x84, 0x49, 0xFB, 0x30, 0x02, 0xBF, 0x60, 0xAD, 0x64, + 0x40, 0x42, 0xFC, 0xFC, 0x00, 0x64, 0x5C, 0x5C, 0x32, 0xFB, 0x82, 0xFF, 0x5C, 0x47, 0x84, 0xFF, + 0x62, 0xFF, 0x1F, 0x60, 0x0A, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, + 0xA2, 0xDB, 0x2A, 0xF2, 0x07, 0xF0, 0x0C, 0xB4, 0x08, 0x3A, 0x07, 0x00, 0x66, 0x41, 0x64, 0x46, + 0x06, 0xF0, 0xFF, 0x60, 0xDF, 0x64, 0xA0, 0x84, 0x06, 0xFA, 0x23, 0xF0, 0x01, 0x64, 0xB0, 0x84, + 0xA2, 0xDA, 0x1B, 0x60, 0xD4, 0x62, 0x1B, 0x60, 0xAC, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xCE, 0xFE, 0x06, 0x00, 0x66, 0xF3, + 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x93, 0x12, 0x60, 0xC8, 0x63, 0xA3, 0xD3, + 0xAD, 0x49, 0x20, 0xB5, 0x08, 0xB1, 0x23, 0x03, 0xE1, 0x81, 0x10, 0xB5, 0x95, 0x81, 0x60, 0x41, + 0x18, 0x02, 0x12, 0x60, 0xCA, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA4, 0xDB, 0x17, 0x02, + 0x0A, 0x64, 0xA4, 0xDB, 0x61, 0x44, 0x07, 0xB4, 0xFF, 0xFF, 0x11, 0x02, 0x08, 0xB1, 0xE1, 0x81, + 0x95, 0x81, 0xA3, 0xD3, 0x0C, 0x03, 0x08, 0xAC, 0x01, 0xBC, 0xA3, 0xDB, 0xFF, 0xFF, 0x13, 0xFF, + 0x06, 0x00, 0x10, 0xAC, 0xA3, 0xDB, 0x12, 0x60, 0xCA, 0x63, 0x0A, 0x7C, 0xA3, 0xD9, 0xB5, 0x60, + 0xAF, 0x78, 0xFF, 0xFF, 0x46, 0xF3, 0x45, 0xF1, 0x05, 0x1B, 0x64, 0x44, 0x03, 0x1B, 0x0F, 0x60, + 0x92, 0x62, 0xA2, 0xD3, 0x45, 0xFB, 0x00, 0x63, 0x46, 0xFD, 0x60, 0x41, 0x25, 0x64, 0x3B, 0xDB, + 0x27, 0x44, 0xEF, 0xB4, 0x40, 0x47, 0x00, 0xB9, 0x71, 0x40, 0x80, 0x27, 0x01, 0x12, 0x19, 0x03, + 0xBF, 0x60, 0x4D, 0x62, 0x84, 0xFF, 0x42, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, + 0xA0, 0x51, 0x1F, 0x0A, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, 0x19, 0x0A, + 0x71, 0x40, 0x80, 0x27, 0xF7, 0x12, 0x45, 0xF3, 0x27, 0x02, 0x03, 0x18, 0xCC, 0x84, 0x45, 0xFB, + 0xF1, 0x02, 0x06, 0x0A, 0xA0, 0x4C, 0xFB, 0xB4, 0xA0, 0x51, 0xA7, 0x60, 0xDF, 0x78, 0xFF, 0xFF, + 0x84, 0xFF, 0xBF, 0x60, 0x2A, 0x64, 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, + 0xA0, 0x51, 0xAF, 0x60, 0x19, 0x78, 0xFF, 0xFF, 0x3C, 0x44, 0xAC, 0x80, 0x32, 0xF1, 0x12, 0x03, + 0x64, 0x40, 0x07, 0x22, 0x0F, 0x00, 0xA7, 0x60, 0xC1, 0x78, 0xFF, 0xFF, 0xA0, 0x4C, 0x1C, 0xBC, + 0xDF, 0xB4, 0xA0, 0x51, 0xF1, 0x01, 0x06, 0x00, 0x28, 0x64, 0x3A, 0xDB, 0xA0, 0x4C, 0x30, 0xBC, + 0xF3, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x28, 0x64, 0x3B, 0xDB, 0x0F, 0x60, + 0x94, 0x62, 0xA2, 0xD3, 0x32, 0x40, 0x02, 0x27, 0x16, 0x00, 0x46, 0xFB, 0x14, 0x18, 0xBF, 0x60, + 0x9B, 0x64, 0x84, 0xFF, 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xF7, 0xB4, 0xA0, 0x51, + 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, 0x46, 0xF3, 0xCA, 0x0A, 0xDC, 0x02, + 0xCC, 0x84, 0x46, 0xFB, 0xF5, 0x02, 0x84, 0xFF, 0xBF, 0x60, 0xAD, 0x64, 0x40, 0x42, 0x82, 0xFF, + 0x27, 0x44, 0x08, 0xBC, 0x40, 0x47, 0xBB, 0xE1, 0x04, 0x00, 0x3A, 0xE1, 0x31, 0x40, 0x01, 0x26, + 0xBB, 0xE1, 0xA7, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0x24, 0xE2, 0x2D, 0xF3, 0x2C, 0xF3, 0x00, 0xBD, + 0xCC, 0x84, 0x08, 0x03, 0x2C, 0xFB, 0x06, 0x02, 0x65, 0x44, 0x2C, 0xFB, 0x8A, 0xFF, 0x80, 0x60, + 0x00, 0x75, 0x88, 0xFF, 0xD2, 0xF3, 0x31, 0x40, 0x01, 0x2A, 0x44, 0x00, 0x60, 0x43, 0x04, 0xB0, + 0x02, 0xB0, 0x08, 0x24, 0x16, 0x02, 0x29, 0x44, 0xFF, 0xFF, 0x00, 0xA8, 0xCC, 0x81, 0x0E, 0x03, + 0x41, 0x49, 0x37, 0x02, 0x63, 0x40, 0x08, 0x2A, 0x09, 0x00, 0xF7, 0xB3, 0x25, 0x60, 0x1C, 0x7C, + 0xA4, 0xD1, 0xAD, 0x4F, 0xFD, 0xB4, 0xA0, 0x5D, 0x44, 0x49, 0x2B, 0x00, 0x63, 0x40, 0x02, 0x2A, + 0x14, 0x00, 0x25, 0x60, 0x1E, 0x64, 0xA0, 0xD3, 0x25, 0x60, 0x1A, 0x7C, 0xA4, 0xDB, 0x40, 0x49, + 0x25, 0x60, 0x20, 0x64, 0xA0, 0xD3, 0x25, 0x60, 0x1C, 0x7C, 0xA4, 0xDB, 0x0C, 0xBB, 0xFD, 0xB3, + 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0x14, 0x00, 0x25, 0x60, 0x22, 0x64, 0xA0, 0xD3, + 0x25, 0x60, 0x1A, 0x7C, 0x0E, 0x18, 0xA4, 0xDB, 0x40, 0x49, 0x25, 0x60, 0x24, 0x64, 0xA0, 0xD3, + 0x25, 0x60, 0x1C, 0x7C, 0xA4, 0xDB, 0x08, 0xBB, 0xFB, 0xB3, 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, + 0xA0, 0x5D, 0xD2, 0xFD, 0x01, 0x60, 0x0C, 0x61, 0xA1, 0xD3, 0x61, 0x43, 0x17, 0x18, 0x58, 0xD3, + 0x62, 0x41, 0x03, 0x18, 0xCC, 0x84, 0xA1, 0xDB, 0x11, 0x00, 0x49, 0xD3, 0xA3, 0xDB, 0x06, 0xA1, + 0xA1, 0xD3, 0x59, 0xD1, 0x60, 0x45, 0xA5, 0xD3, 0x59, 0xD1, 0xB0, 0x84, 0xA5, 0xDB, 0x64, 0x44, + 0x06, 0x36, 0xCD, 0xFE, 0x07, 0x36, 0xD6, 0xFE, 0xE5, 0x01, 0x23, 0x46, 0xB5, 0x60, 0xAF, 0x78, + 0xFF, 0xFF, 0x46, 0x43, 0x1C, 0x60, 0x0A, 0x61, 0xA1, 0xD3, 0x59, 0xD1, 0x06, 0x1B, 0x59, 0xD3, + 0x59, 0xD1, 0x03, 0x1B, 0x59, 0xD3, 0x59, 0xD1, 0xF0, 0x18, 0x00, 0x63, 0x49, 0xDD, 0x60, 0x40, + 0x02, 0x36, 0x11, 0x00, 0x03, 0x36, 0x32, 0x00, 0x01, 0x36, 0x08, 0x00, 0x05, 0x3A, 0xEA, 0x01, + 0xA4, 0xD3, 0x5A, 0xD3, 0x9C, 0x85, 0xA4, 0x84, 0xA2, 0xDB, 0xE4, 0x01, 0x01, 0x60, 0x0C, 0x61, + 0x00, 0x64, 0xA1, 0xDB, 0xDF, 0x01, 0xC0, 0x60, 0x4F, 0x64, 0x40, 0x45, 0x22, 0x00, 0x01, 0x60, + 0x0C, 0x66, 0xA6, 0xD3, 0x04, 0xA1, 0x60, 0x43, 0xA1, 0xD3, 0xC9, 0x81, 0x60, 0x45, 0x00, 0xBB, + 0xA1, 0xDB, 0xBE, 0xD3, 0x09, 0x03, 0xD4, 0x84, 0x9C, 0x84, 0xDC, 0x84, 0xFF, 0xFF, 0x04, 0x0E, + 0xA3, 0xD1, 0x63, 0x46, 0x64, 0x43, 0xF2, 0x01, 0x9C, 0x84, 0xDC, 0x85, 0x49, 0xDD, 0x61, 0x44, + 0x00, 0xBB, 0xA6, 0xDB, 0x02, 0x03, 0x65, 0x44, 0xBE, 0xDB, 0xBC, 0x01, 0xC0, 0x60, 0x2A, 0x64, + 0x40, 0x45, 0x01, 0x60, 0x0C, 0x66, 0xA6, 0xD3, 0xFF, 0xFF, 0xD0, 0x80, 0x0F, 0x18, 0x02, 0x03, + 0x60, 0x46, 0xF9, 0x01, 0x58, 0xD3, 0xA4, 0xD3, 0x60, 0x45, 0x00, 0x63, 0xA4, 0xDD, 0x05, 0x18, + 0x58, 0xD3, 0xFF, 0xFF, 0xC4, 0x83, 0xA2, 0xDD, 0xCA, 0x84, 0xA6, 0xDB, 0x25, 0x58, 0x64, 0x41, + 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x06, 0x02, 0x40, 0xFF, 0x42, 0xFF, 0x43, 0xFF, 0x44, 0xFF, + 0x45, 0xFF, 0xA1, 0xFF, 0x88, 0xFF, 0x85, 0xFF, 0x21, 0xE1, 0x5C, 0x40, 0xC0, 0x60, 0x9A, 0x78, + 0xFF, 0xFF, 0x43, 0xFF, 0x39, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x84, 0x3E, 0xFB, 0x01, 0xA0, 0x4C, + 0x3D, 0x46, 0x2A, 0xF2, 0x46, 0x4D, 0x10, 0x25, 0x0E, 0x00, 0x09, 0xE1, 0xA1, 0xFF, 0x66, 0x40, + 0x0F, 0xF2, 0x01, 0x29, 0x02, 0x00, 0x40, 0xFF, 0x0A, 0xBC, 0xA2, 0xDA, 0x08, 0x25, 0xE9, 0x01, + 0xCB, 0xFE, 0x5C, 0x5D, 0xE7, 0x01, 0x44, 0xFF, 0x03, 0x2B, 0x21, 0x00, 0x89, 0xF3, 0x06, 0x61, + 0x60, 0x43, 0x66, 0x45, 0x31, 0xF0, 0x63, 0x46, 0x05, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0x30, 0xF0, + 0x0F, 0x02, 0x63, 0x46, 0x04, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0x2F, 0xF0, 0x09, 0x02, 0x63, 0x46, + 0x03, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0xFF, 0xFF, 0x48, 0xFE, 0x06, 0x00, + 0xCD, 0x81, 0x02, 0xA3, 0xE7, 0x02, 0x88, 0xF1, 0x08, 0xFE, 0x64, 0x43, 0x26, 0x03, 0x31, 0xF2, + 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, + 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, + 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, + 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, + 0xE8, 0x1B, 0x88, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x07, 0xFC, 0x3F, 0xF2, 0x09, 0x60, + 0xB0, 0x65, 0xD4, 0x80, 0x2A, 0xF2, 0xA1, 0x05, 0x08, 0x25, 0x93, 0x01, 0x00, 0x64, 0x0D, 0x60, + 0x2C, 0x61, 0x40, 0x4B, 0xA1, 0xDB, 0x2D, 0x46, 0x3B, 0xF2, 0x88, 0xF1, 0x87, 0xF4, 0x60, 0x40, + 0x20, 0x2B, 0x12, 0x00, 0xD3, 0x80, 0x2C, 0xF0, 0x90, 0x03, 0x07, 0xF4, 0x64, 0x40, 0x01, 0x26, + 0x88, 0xF5, 0xB6, 0xF4, 0x2D, 0x46, 0x04, 0x64, 0x04, 0xB3, 0x22, 0xFA, 0x04, 0x03, 0xC2, 0x60, + 0x11, 0x78, 0xFF, 0xFF, 0x01, 0x00, 0xE0, 0x00, 0x74, 0x62, 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, + 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5B, 0x64, 0x44, 0xE2, 0x7F, + 0xA0, 0x5B, 0x64, 0x47, 0x7C, 0x5F, 0xE8, 0x84, 0xE8, 0x85, 0x0C, 0x60, 0x3A, 0x64, 0x44, 0xD3, + 0x5A, 0xD1, 0x03, 0x1B, 0xC2, 0x60, 0x04, 0x78, 0xFF, 0xFF, 0x60, 0x45, 0x64, 0x44, 0xE3, 0x7F, + 0xA0, 0x5B, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5B, + 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5B, 0x65, 0x40, + 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xE9, 0x7F, + 0xA0, 0x5B, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5B, + 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5B, 0x64, 0x47, + 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xEF, 0x7F, 0xA0, 0x5B, 0x65, 0x44, 0xD8, 0x84, + 0x08, 0x25, 0x78, 0x00, 0x60, 0x7F, 0xA0, 0x5B, 0x80, 0x60, 0x00, 0xEB, 0xA0, 0x60, 0x00, 0xEB, + 0xD1, 0x60, 0x00, 0xEB, 0x3F, 0xF2, 0x04, 0x65, 0xC4, 0x83, 0x0A, 0xE1, 0xB3, 0xFF, 0x9A, 0xFF, + 0xCB, 0x83, 0x00, 0xF4, 0x10, 0x62, 0x6C, 0x61, 0x0E, 0xA3, 0xAB, 0x84, 0xF2, 0xA3, 0xA1, 0xFF, + 0x08, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0x02, 0x62, 0xC9, 0x81, 0xAB, 0x84, 0xA1, 0xFF, 0x01, 0x00, + 0xA2, 0xDC, 0x7A, 0xD4, 0xFD, 0x1C, 0xA2, 0xDC, 0x08, 0x25, 0x54, 0x00, 0xF2, 0x1D, 0x7C, 0xA8, + 0xD9, 0x81, 0xEF, 0x03, 0xFF, 0xB1, 0x09, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, 0x5A, 0xD2, + 0x89, 0xFF, 0x80, 0x4F, 0x6F, 0x44, 0xA2, 0xDA, 0x88, 0xFF, 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, + 0x3D, 0x46, 0x08, 0x25, 0x3F, 0x00, 0x40, 0xFF, 0x0F, 0xF0, 0x0A, 0x64, 0xB0, 0x84, 0x18, 0x14, + 0xF7, 0xB4, 0xA2, 0xDA, 0x0D, 0x60, 0x2C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, + 0x0C, 0x00, 0xD1, 0xF5, 0xD0, 0xF4, 0x0D, 0x60, 0x2C, 0x61, 0x59, 0xD1, 0x37, 0xF8, 0x05, 0x64, + 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, 0xFC, 0x02, 0x2D, 0x46, 0xC0, 0x60, 0xB0, 0x78, 0xFF, 0xFF, + 0xA2, 0xDA, 0x2D, 0x46, 0x3B, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x20, 0x2B, 0x18, 0x00, 0xD1, 0xF5, + 0xB7, 0xF0, 0x2A, 0x44, 0xA4, 0x84, 0xFF, 0xFF, 0x2F, 0x26, 0x10, 0x00, 0x2D, 0x46, 0x64, 0x44, + 0x3A, 0xF0, 0xBC, 0xF0, 0x64, 0x5F, 0x3D, 0xF0, 0x07, 0xF4, 0xD0, 0xF4, 0xFF, 0xFF, 0x08, 0xA3, + 0x5B, 0xD8, 0x65, 0x5C, 0x5B, 0xD8, 0x5B, 0xDA, 0x2D, 0x46, 0x01, 0x00, 0x2D, 0x46, 0xC0, 0x60, + 0xB0, 0x78, 0xFF, 0xFF, 0x98, 0xFF, 0x43, 0xFF, 0x40, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, 0x2D, 0x46, + 0x0D, 0x60, 0x2C, 0x61, 0xA1, 0xD3, 0x2D, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x0A, 0x00, 0xD1, 0xF5, + 0xD0, 0xF4, 0x59, 0xD1, 0x37, 0xF8, 0x05, 0x64, 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, 0xFC, 0x02, + 0x2D, 0x46, 0xC0, 0x60, 0x9A, 0x78, 0xFF, 0xFF, 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, 0x3D, 0x46, + 0x08, 0x25, 0xE0, 0x01, 0x0F, 0xF2, 0x40, 0xFF, 0x02, 0xBC, 0xA2, 0xDA, 0xC0, 0x60, 0xB0, 0x78, + 0xFF, 0xFF, 0x00, 0x64, 0x0D, 0x60, 0x2C, 0x62, 0xA2, 0xDB, 0x04, 0x64, 0x22, 0xFA, 0x87, 0xF4, + 0x88, 0xF1, 0xFF, 0xFF, 0xD3, 0x80, 0x3B, 0xF2, 0xE7, 0x03, 0x60, 0x47, 0xC0, 0xB7, 0x02, 0xFE, + 0xF0, 0x84, 0xF0, 0x84, 0xF0, 0x84, 0x00, 0xA8, 0x40, 0x4A, 0x16, 0x03, 0xE0, 0x81, 0x61, 0x43, + 0x42, 0xFE, 0x00, 0x64, 0xF0, 0x84, 0xFE, 0x1F, 0x40, 0x4A, 0xE1, 0x84, 0xE0, 0x84, 0x2D, 0x46, + 0x07, 0xF4, 0xE0, 0x81, 0x37, 0xF0, 0x2A, 0x47, 0x0C, 0x60, 0x7A, 0x63, 0xA0, 0x84, 0x47, 0x9C, + 0x10, 0x03, 0x7C, 0x44, 0xA0, 0x63, 0x11, 0x00, 0x20, 0x64, 0x40, 0x4A, 0x63, 0x46, 0x37, 0xF0, + 0x66, 0x44, 0x64, 0x40, 0x80, 0x2B, 0x05, 0x00, 0x00, 0x60, 0x70, 0x7C, 0x00, 0x60, 0x90, 0x63, + 0x04, 0x00, 0x2D, 0x46, 0xC2, 0x60, 0x04, 0x78, 0xFF, 0xFF, 0x2D, 0x46, 0xCE, 0xFB, 0xCF, 0xF9, + 0xD0, 0xFD, 0x07, 0xF2, 0xD1, 0xFB, 0x60, 0x46, 0x37, 0xF0, 0x2A, 0x44, 0x0D, 0x60, 0x2C, 0x62, + 0x5A, 0xD9, 0x00, 0x65, 0x45, 0x4B, 0xA0, 0x84, 0xFF, 0xFF, 0x3F, 0x22, 0x05, 0x00, 0x90, 0x84, + 0x37, 0xFA, 0x01, 0x64, 0x40, 0x4B, 0x21, 0x00, 0xAD, 0x46, 0x0A, 0xA3, 0x3D, 0xF2, 0xAD, 0x46, + 0xA3, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3C, 0xF2, 0xAD, 0x46, 0x02, 0x03, 0x16, 0x07, 0x14, 0x04, + 0x5B, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3B, 0xF2, 0x03, 0x03, 0xAD, 0x46, 0x0E, 0x07, 0x0C, 0x04, + 0x3A, 0xF0, 0xAD, 0x46, 0x5B, 0xD0, 0x64, 0x5F, 0xD0, 0x80, 0x2B, 0x44, 0x18, 0x07, 0x04, 0x03, + 0xD0, 0x84, 0x10, 0xA4, 0xFF, 0xFF, 0x13, 0x07, 0x7F, 0x01, 0x01, 0x64, 0x0D, 0x60, 0x2C, 0x62, + 0xA2, 0xDB, 0x2D, 0x46, 0x0D, 0x60, 0x3C, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, + 0xC2, 0x60, 0xAA, 0x78, 0xFF, 0xFF, 0x85, 0xFF, 0x2D, 0x46, 0x08, 0x25, 0x53, 0x01, 0x2D, 0x46, + 0x0D, 0x60, 0x3C, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC3, 0x60, 0x33, 0x78, + 0xFF, 0xFF, 0x85, 0xFF, 0x2D, 0x46, 0x08, 0x25, 0x45, 0x01, 0x00, 0x60, 0x0F, 0x64, 0xC1, 0x60, + 0x70, 0x78, 0xFF, 0xFF, 0x07, 0xF4, 0x66, 0x41, 0x03, 0xF2, 0x04, 0xF2, 0x40, 0x42, 0x05, 0xF2, + 0x40, 0x43, 0x40, 0x44, 0x61, 0x46, 0x3C, 0xF2, 0x3D, 0xF2, 0x40, 0x40, 0x40, 0x41, 0x0D, 0x60, + 0x70, 0x65, 0x00, 0x61, 0xCF, 0xF1, 0xCE, 0xF5, 0x44, 0x4C, 0x2C, 0x5C, 0xE9, 0x80, 0x00, 0x64, + 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, 0x24, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x20, 0x44, 0x40, 0x80, 0xDB, 0x83, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x21, 0x44, 0x40, 0x81, 0xDB, 0x83, 0xBD, 0xD2, 0x21, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x22, 0x44, 0x40, 0x82, 0xDB, 0x83, 0xBD, 0xD2, 0x22, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x23, 0x44, 0x40, 0x83, 0xF2, 0xA3, 0xBD, 0xD2, 0x23, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x24, 0x44, 0xC0, 0x9C, 0x41, 0x84, 0xDD, 0x81, 0x08, 0x2A, 0xA7, 0x01, 0x0D, 0x60, 0x2E, 0x61, + 0x05, 0x64, 0xD0, 0xF4, 0xD1, 0xF5, 0xFE, 0xA3, 0x5B, 0xD0, 0xCC, 0x84, 0x59, 0xD9, 0xFC, 0x02, + 0xD0, 0xF3, 0xD1, 0xF5, 0x60, 0x42, 0x20, 0x44, 0xA2, 0xDA, 0x21, 0x44, 0x5A, 0xDA, 0x22, 0x44, + 0x5A, 0xDA, 0x23, 0x44, 0x5A, 0xDA, 0x24, 0x44, 0x5A, 0xDA, 0x61, 0x46, 0x0D, 0x60, 0x3C, 0x62, + 0xA2, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x41, 0xD0, 0xF3, 0xD1, 0xF5, 0xA0, 0xD2, 0x5A, 0xD0, + 0x40, 0x40, 0x44, 0x41, 0x5A, 0xD2, 0x5A, 0xD0, 0x40, 0x42, 0x5A, 0xD0, 0x44, 0x43, 0x61, 0x46, + 0xBA, 0xF0, 0x3B, 0xF2, 0x44, 0x44, 0x65, 0x5F, 0x40, 0x85, 0xCF, 0xF4, 0xCE, 0xF5, 0x43, 0x4C, + 0x0D, 0x60, 0x70, 0x65, 0xBD, 0xD2, 0x25, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x20, 0x44, + 0x40, 0x80, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x21, 0x44, 0x40, 0x81, + 0xBD, 0xD2, 0x21, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x22, 0x44, 0x40, 0x82, 0xBD, 0xD2, + 0x22, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x23, 0x44, 0x40, 0x83, 0xBD, 0xD2, 0x23, 0x5C, + 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x24, 0x44, 0x40, 0x84, 0xBD, 0xD2, 0x24, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x25, 0x44, 0x40, 0x85, 0x61, 0x46, 0x3A, 0xF0, 0xFF, 0xFF, 0x64, 0x44, + 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5B, 0x64, 0x44, 0xE2, 0x7F, + 0xA0, 0x5B, 0x64, 0x47, 0xCE, 0xF5, 0xBD, 0xD2, 0x25, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, + 0x20, 0x5C, 0x40, 0x80, 0x20, 0x44, 0xE4, 0x7F, 0xA0, 0x5B, 0x20, 0x47, 0xE5, 0x7F, 0xA0, 0x5B, + 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x21, 0x5C, 0x40, 0x81, 0x21, 0x44, + 0xE6, 0x7F, 0xA0, 0x5B, 0x21, 0x47, 0xE7, 0x7F, 0xA0, 0x5B, 0x21, 0x44, 0xE8, 0x80, 0xF8, 0x84, + 0x22, 0x5C, 0x40, 0x82, 0x22, 0x44, 0xE8, 0x7F, 0xA0, 0x5B, 0x22, 0x47, 0xE9, 0x7F, 0xA0, 0x5B, + 0x22, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x23, 0x5C, 0x40, 0x83, 0x23, 0x44, 0xEA, 0x7F, 0xA0, 0x5B, + 0x23, 0x47, 0xEB, 0x7F, 0xA0, 0x5B, 0x23, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x24, 0x5C, 0x40, 0x84, + 0x24, 0x44, 0xEC, 0x7F, 0xA0, 0x5B, 0x24, 0x47, 0xED, 0x7F, 0xA0, 0x5B, 0x24, 0x44, 0xE8, 0x80, + 0xF8, 0x84, 0x25, 0x5C, 0x40, 0x85, 0x25, 0x44, 0xEE, 0x7F, 0xA0, 0x5B, 0x25, 0x47, 0xEF, 0x7F, + 0xA0, 0x5B, 0x2C, 0x43, 0xA3, 0xD2, 0x25, 0x5C, 0x90, 0x81, 0xE9, 0x84, 0xE3, 0x7F, 0xA0, 0x5B, + 0x0D, 0x60, 0x3C, 0x62, 0xA2, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0xF3, 0x5A, 0xD3, 0x40, 0x48, + 0x5A, 0xD3, 0x40, 0x49, 0x40, 0x4A, 0x00, 0x60, 0x70, 0x7C, 0x44, 0x4D, 0x45, 0xF2, 0x46, 0xF2, + 0x40, 0x47, 0x40, 0x46, 0x0D, 0x60, 0x70, 0x65, 0x00, 0x61, 0x2D, 0x5C, 0xE9, 0x80, 0x00, 0x64, + 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, 0x2A, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x26, 0x44, 0x40, 0x86, 0xDB, 0x83, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x27, 0x44, 0x40, 0x87, 0xDB, 0x83, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x28, 0x44, 0x40, 0x88, 0xDB, 0x83, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x29, 0x44, 0x40, 0x89, 0xF2, 0xA3, 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x2A, 0x44, 0xC0, 0x9C, 0x41, 0x8A, 0xDD, 0x81, 0x08, 0x2A, 0xA7, 0x01, 0x26, 0x44, 0x40, 0xFA, + 0x27, 0x44, 0x41, 0xFA, 0x28, 0x44, 0x42, 0xFA, 0x29, 0x44, 0x43, 0xFA, 0x2A, 0x44, 0x44, 0xFA, + 0x0D, 0x60, 0x3E, 0x62, 0xA2, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x80, 0x7C, 0x44, 0x4D, + 0x2D, 0x42, 0xA2, 0xD2, 0x5A, 0xD0, 0x40, 0x46, 0x44, 0x47, 0x5A, 0xD2, 0x5A, 0xD0, 0x40, 0x48, + 0x5A, 0xD0, 0x44, 0x49, 0x47, 0xF2, 0x44, 0x4A, 0x40, 0x8B, 0x60, 0x5C, 0x64, 0x47, 0xE0, 0x7F, + 0xA0, 0x5A, 0xFF, 0xB4, 0x20, 0xBC, 0x7F, 0xB4, 0xE1, 0x7F, 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, + 0xA0, 0x5A, 0x00, 0x60, 0x70, 0x63, 0x0D, 0x60, 0x70, 0x65, 0xBD, 0xD2, 0x2B, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x26, 0x44, 0x40, 0x86, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x27, 0x44, 0x40, 0x87, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x28, 0x44, 0x40, 0x88, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x29, 0x44, + 0x40, 0x89, 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2A, 0x44, 0x40, 0x8A, + 0xBD, 0xD2, 0x2A, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2B, 0x44, 0x40, 0x8B, 0xBD, 0xD2, + 0x2B, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x26, 0x5C, 0x40, 0x86, 0x26, 0x44, 0xE4, 0x7F, + 0xA0, 0x5A, 0x26, 0x47, 0xE5, 0x7F, 0xA0, 0x5A, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x84, 0xE8, 0x80, + 0xF8, 0x84, 0x27, 0x5C, 0x40, 0x87, 0x27, 0x44, 0xE6, 0x7F, 0xA0, 0x5A, 0x27, 0x47, 0xE7, 0x7F, + 0xA0, 0x5A, 0x27, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x28, 0x5C, 0x40, 0x88, 0x28, 0x44, 0xE8, 0x7F, + 0xA0, 0x5A, 0x28, 0x47, 0xE9, 0x7F, 0xA0, 0x5A, 0x28, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x29, 0x5C, + 0x40, 0x89, 0x29, 0x44, 0xEA, 0x7F, 0xA0, 0x5A, 0x29, 0x47, 0xEB, 0x7F, 0xA0, 0x5A, 0x29, 0x44, + 0xE8, 0x80, 0xF8, 0x84, 0x2A, 0x5C, 0x40, 0x8A, 0x2A, 0x44, 0xEC, 0x7F, 0xA0, 0x5A, 0x2A, 0x47, + 0xED, 0x7F, 0xA0, 0x5A, 0x2A, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x2B, 0x5C, 0x40, 0x8B, 0x2B, 0x44, + 0xEE, 0x7F, 0xA0, 0x5A, 0x2B, 0x47, 0xEF, 0x7F, 0xA0, 0x5A, 0x38, 0xF0, 0x2B, 0x44, 0x90, 0x84, + 0xE8, 0x84, 0xE3, 0x7F, 0xA0, 0x5A, 0x0D, 0x60, 0x3E, 0x62, 0xA2, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, + 0x42, 0xFF, 0x40, 0xFF, 0xDD, 0xFE, 0xAD, 0x4F, 0x00, 0x7F, 0x01, 0xBC, 0xA0, 0x5D, 0x00, 0xEE, + 0x19, 0x61, 0xCD, 0x81, 0xFF, 0xFF, 0xFD, 0x02, 0x43, 0x45, 0x20, 0x44, 0x60, 0xBC, 0x40, 0x40, + 0x02, 0x60, 0xEE, 0x63, 0x65, 0xF3, 0x82, 0xFD, 0x40, 0x7F, 0x83, 0xFB, 0x05, 0x64, 0x84, 0xFB, + 0xDF, 0xFE, 0x19, 0xFF, 0xC5, 0x60, 0x6D, 0x64, 0x3F, 0x40, 0x01, 0x2B, 0x02, 0x00, 0xC5, 0x60, + 0x6D, 0x64, 0x85, 0xFB, 0xC0, 0x60, 0x9A, 0x78, 0xFF, 0xFF, 0x04, 0xEE, 0xAD, 0x4F, 0x00, 0x7F, + 0x01, 0xBC, 0xA0, 0x5D, 0x19, 0x61, 0xCD, 0x81, 0xFF, 0xFF, 0xFD, 0x02, 0xAD, 0x4F, 0x00, 0x7F, + 0x01, 0xBC, 0xA0, 0x5D, 0x00, 0xEE, 0x15, 0x60, 0xA2, 0xE7, 0x1C, 0x60, 0x68, 0x63, 0x1C, 0x60, + 0xDC, 0x65, 0xDF, 0xFE, 0x80, 0xE1, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x48, 0x60, 0x47, 0x80, 0xBC, + 0x00, 0x7F, 0x60, 0x4A, 0xD7, 0x80, 0xA1, 0xFF, 0xFF, 0xFF, 0xF5, 0x02, 0x1C, 0x60, 0xDC, 0x63, + 0x1D, 0x60, 0xDE, 0x65, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x48, 0x60, 0x47, 0x80, 0xBC, 0x00, 0x7F, + 0x60, 0x4A, 0xD7, 0x80, 0xA1, 0xFF, 0xFF, 0xFF, 0xF5, 0x02, 0x3F, 0x40, 0x20, 0x2B, 0x00, 0x00, + 0x01, 0x68, 0xFF, 0x6A, 0xBF, 0xFE, 0xC6, 0x60, 0x55, 0x78, 0xFF, 0xFF, 0x3F, 0x40, 0x20, 0x2B, + 0xAD, 0x00, 0x01, 0x16, 0xFE, 0x01, 0x38, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x2A, + 0xA5, 0x00, 0x1F, 0x60, 0x1A, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, + 0xA2, 0xDB, 0x65, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x9C, 0x01, 0x00, 0x65, 0xF1, 0xDD, 0xFE, + 0xAD, 0x4F, 0x00, 0x7F, 0x01, 0xBC, 0xA0, 0x5D, 0x00, 0xEE, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, + 0x40, 0x40, 0x02, 0x60, 0xEE, 0x64, 0x82, 0xFB, 0x83, 0xF9, 0x05, 0x64, 0x84, 0xFB, 0xDF, 0xFE, + 0x19, 0xFF, 0x83, 0x00, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x43, 0x45, 0xA4, 0xD1, 0xDA, 0x83, + 0xC3, 0x85, 0x80, 0xE1, 0xDF, 0xFE, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x48, 0x60, 0x47, 0x80, 0xBC, + 0x00, 0x7F, 0x60, 0x4A, 0xD7, 0x80, 0xA1, 0xFF, 0xF6, 0x02, 0xBF, 0xFE, 0x6E, 0x00, 0x3F, 0x40, + 0x40, 0x26, 0x13, 0x00, 0x0B, 0x60, 0xF8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x10, 0x64, 0x90, 0x84, + 0xA0, 0x50, 0xF8, 0xA2, 0xA2, 0xD1, 0x0A, 0x60, 0x19, 0x64, 0x90, 0x84, 0xA0, 0x52, 0x06, 0xA2, + 0xA2, 0xD1, 0x46, 0x60, 0x09, 0x64, 0x90, 0x84, 0xA0, 0x50, 0xAD, 0x4F, 0xFE, 0xB4, 0xA0, 0x5D, + 0xAD, 0x4F, 0xFD, 0xB4, 0xA0, 0x5D, 0x02, 0xEE, 0xBD, 0xFE, 0x50, 0x00, 0x80, 0xE1, 0x01, 0x16, + 0xFE, 0x01, 0x64, 0x48, 0x92, 0x6A, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x40, 0x1F, 0x60, 0x08, 0x64, + 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x3F, 0x00, 0x80, 0xE1, + 0x01, 0x16, 0xFE, 0x01, 0x01, 0x68, 0xA7, 0x6A, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x40, 0x36, 0x00, + 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x80, 0xE1, 0x64, 0x46, 0x01, 0x16, 0xFE, 0x01, 0x21, 0x69, + 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x5E, 0x01, 0x16, 0xFE, 0x01, 0x22, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, + 0x68, 0x5F, 0x26, 0xFA, 0x1C, 0xF2, 0x01, 0x16, 0xFE, 0x01, 0x3A, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, + 0x68, 0x5F, 0x27, 0xFA, 0x1B, 0x00, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x43, 0x45, 0xBE, 0xD5, + 0xA4, 0xD2, 0x5A, 0x86, 0xEF, 0xA0, 0x11, 0x61, 0x01, 0x06, 0x60, 0x41, 0x1C, 0x60, 0x46, 0x63, + 0x80, 0xE1, 0xBD, 0xD3, 0x26, 0x42, 0x01, 0x16, 0xFE, 0x01, 0x60, 0x49, 0xA1, 0xFF, 0xFF, 0xFF, + 0x68, 0x44, 0xCD, 0x81, 0xA2, 0xDA, 0x5A, 0x86, 0xF4, 0x02, 0x25, 0x43, 0x21, 0xE1, 0x00, 0x64, + 0xBF, 0xDB, 0x20, 0x44, 0x20, 0x2A, 0x07, 0x00, 0x07, 0xB4, 0x04, 0x36, 0xC3, 0xFE, 0x06, 0x36, + 0xCC, 0xFE, 0x07, 0x36, 0xD5, 0xFE, 0x20, 0x44, 0xD8, 0xB4, 0x40, 0x40, 0x20, 0x44, 0x40, 0x2A, + 0x07, 0x00, 0x9F, 0xFE, 0x1E, 0x05, 0xBF, 0xB4, 0x40, 0x40, 0x85, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, + 0x1B, 0x60, 0xE6, 0x63, 0xBD, 0xD3, 0x02, 0x61, 0x17, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x02, 0x61, + 0x13, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x02, 0x61, 0x0F, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x04, 0x61, + 0x0B, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x06, 0x61, 0x07, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x07, 0x61, + 0x03, 0x1B, 0xC0, 0x60, 0x9A, 0x78, 0xFF, 0xFF, 0xA3, 0xD1, 0x40, 0x44, 0x20, 0x44, 0x07, 0xB5, + 0xD4, 0x85, 0x35, 0x80, 0x24, 0x45, 0x1C, 0x60, 0x22, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, + 0x80, 0xE1, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x64, 0x43, 0xBD, 0xD3, 0xBD, 0xD1, + 0x40, 0x44, 0x10, 0x27, 0x10, 0x00, 0xFF, 0x60, 0x7F, 0x65, 0x15, 0x60, 0xA2, 0x64, 0x24, 0x40, + 0x08, 0x2B, 0xA4, 0x84, 0xA0, 0x57, 0xFF, 0xFF, 0x64, 0x49, 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x16, + 0xFD, 0x01, 0x00, 0x7F, 0xA3, 0xDB, 0xA1, 0x01, 0x80, 0xE1, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, + 0x40, 0x40, 0x64, 0x43, 0xBD, 0xD3, 0xBD, 0xD1, 0x40, 0x44, 0x10, 0x2B, 0x11, 0x00, 0xA3, 0xD3, + 0xFF, 0xFF, 0x15, 0x60, 0x80, 0xE7, 0x24, 0x40, 0x07, 0x27, 0x02, 0x00, 0x50, 0xEC, 0x00, 0x00, + 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x24, 0x40, 0x20, 0x2B, 0x40, 0xEC, 0x0F, 0x00, + 0x15, 0x60, 0x22, 0x64, 0x24, 0x40, 0x08, 0x27, 0x80, 0xBC, 0xA3, 0xD3, 0xA0, 0x57, 0x60, 0x48, + 0x64, 0x44, 0x80, 0xBC, 0xFF, 0xB4, 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x75, 0x01, + 0xA2, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x01, 0x02, 0xA1, 0xFF, 0x86, 0xFF, 0x88, 0xFF, + 0x5C, 0x46, 0x5C, 0x49, 0x5C, 0x40, 0xDE, 0x60, 0x58, 0x4F, 0xE2, 0x78, 0xFF, 0xFF, 0xCE, 0x60, + 0x58, 0x4F, 0x00, 0x78, 0xFF, 0xFF, 0xE7, 0x60, 0x58, 0x4F, 0xBE, 0x78, 0xFF, 0xFF, 0xDB, 0x60, + 0x58, 0x4F, 0x3B, 0x78, 0xFF, 0xFF, 0x13, 0xE1, 0xA3, 0xFF, 0xC7, 0x60, 0x2E, 0x78, 0xFF, 0xFF, + 0xDC, 0x60, 0x87, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xCE, 0x62, 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x22, 0x00, 0x75, 0xF3, 0x31, 0x40, 0x01, 0x2A, 0x1E, 0x00, + 0xDC, 0x84, 0x01, 0xB4, 0x75, 0xFB, 0x09, 0x02, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x00, 0x60, + 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x11, 0x00, 0x0F, 0x60, 0xDC, 0x62, 0xA2, 0xD1, + 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x08, 0x00, 0xA9, 0xFE, 0xE4, 0x05, + 0xAB, 0xFE, 0x07, 0x05, 0xA8, 0xFE, 0xD4, 0x05, 0xAA, 0xFE, 0xD5, 0x05, 0xA1, 0xFF, 0xFF, 0xFF, + 0x85, 0x3E, 0x1B, 0x60, 0xC4, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x03, 0x02, + 0xC7, 0x60, 0x2E, 0x78, 0xFF, 0xFF, 0x26, 0x45, 0xD4, 0x80, 0x0F, 0xF0, 0xF9, 0x03, 0x64, 0x44, + 0x70, 0xB0, 0x70, 0x2A, 0x14, 0x00, 0x1F, 0x60, 0x18, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, + 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0xA2, 0xFF, 0x8F, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0xFE, 0xA0, + 0x8F, 0xFB, 0x01, 0x07, 0xD4, 0xFE, 0xA3, 0xFF, 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0x64, 0x40, + 0x02, 0x26, 0x09, 0x00, 0x66, 0x45, 0x09, 0xF4, 0x0F, 0xF2, 0x02, 0x18, 0x65, 0x46, 0xE3, 0x1B, + 0x00, 0x64, 0x40, 0x46, 0xCB, 0x01, 0xA2, 0xFF, 0x8F, 0xF3, 0x46, 0x46, 0xCC, 0x84, 0xFE, 0xA0, + 0x8F, 0xFB, 0x01, 0x07, 0xD4, 0xFE, 0xA3, 0xFF, 0x0F, 0xF0, 0xA3, 0xFC, 0x64, 0x44, 0x80, 0x26, + 0x22, 0x00, 0x98, 0xF1, 0x1E, 0x60, 0xF8, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, + 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, + 0x00, 0x75, 0x88, 0xFF, 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, 0x07, 0x60, 0x01, 0x64, 0x04, 0x00, + 0x02, 0x2A, 0x06, 0x00, 0x00, 0x60, 0x01, 0x64, 0x23, 0xFA, 0xCB, 0x60, 0xC8, 0x78, 0xFF, 0xFF, + 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0x08, 0x26, 0x3F, 0x00, 0x2A, 0xF2, 0x60, 0x63, 0x60, 0x40, + 0x02, 0x2B, 0x66, 0x63, 0xBE, 0xD2, 0x69, 0xF1, 0xA3, 0xD2, 0xD0, 0x80, 0x68, 0xF1, 0x18, 0x02, + 0xBF, 0xD2, 0xD0, 0x80, 0x67, 0xF1, 0x14, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x11, 0x02, 0x98, 0xF1, + 0x1F, 0x60, 0x04, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, + 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, + 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, 0x07, 0x60, 0x02, 0x64, 0x04, 0x00, 0x02, 0x2A, 0x06, 0x00, + 0x00, 0x60, 0x02, 0x64, 0x23, 0xFA, 0xCB, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, + 0x60, 0x40, 0xB0, 0x3A, 0x06, 0x00, 0x00, 0x60, 0x02, 0x64, 0x23, 0xFA, 0xC8, 0x60, 0x6D, 0x78, + 0xFF, 0xFF, 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0x32, 0x44, 0x01, 0x2A, 0x4A, 0x00, 0x20, 0x60, + 0x6C, 0x63, 0xBF, 0xD3, 0x00, 0x65, 0xB4, 0x81, 0xDB, 0x83, 0x3D, 0x03, 0xBF, 0xD3, 0xA3, 0xD3, + 0x40, 0x48, 0xBE, 0xD3, 0x40, 0x4A, 0x2E, 0xF0, 0x40, 0x4C, 0xD0, 0x80, 0x2D, 0xF0, 0x08, 0x02, + 0x2A, 0x44, 0xD0, 0x80, 0x2C, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x2B, 0x03, + 0x31, 0xF0, 0x2C, 0x44, 0xD0, 0x80, 0x30, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x2F, 0xF0, + 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x1E, 0x03, 0x34, 0xF0, 0x2C, 0x44, 0xD0, 0x80, + 0x33, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x32, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, + 0xFF, 0xFF, 0x11, 0x03, 0x38, 0xF0, 0x2C, 0x44, 0xD0, 0x80, 0x37, 0xF0, 0x08, 0x02, 0x2A, 0x44, + 0xD0, 0x80, 0x36, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x04, 0x03, 0xFA, 0xA1, + 0x06, 0xA3, 0xB7, 0x03, 0xC3, 0x01, 0x07, 0x60, 0x00, 0x64, 0x23, 0xFA, 0xCB, 0x60, 0xC8, 0x78, + 0xFF, 0xFF, 0x2A, 0xF2, 0x0F, 0xF0, 0x60, 0x45, 0xA4, 0x36, 0x08, 0x00, 0x0C, 0xB4, 0x04, 0x36, + 0x02, 0x00, 0x0C, 0x3A, 0x06, 0x00, 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0xC9, 0x60, 0x42, 0x78, + 0xFF, 0xFF, 0x26, 0xF2, 0x50, 0xF1, 0x60, 0x47, 0x00, 0x7E, 0xD0, 0x84, 0x1F, 0xA4, 0x06, 0x0E, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x07, 0x00, 0xC2, 0xA4, 0xE8, 0x84, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x87, 0xF8, 0xBF, 0xC0, 0x84, 0xA2, 0xDB, 0x0F, 0xF0, + 0x65, 0x40, 0x40, 0x2B, 0x22, 0x00, 0x32, 0x40, 0x08, 0x26, 0x1F, 0x00, 0x07, 0xF4, 0x36, 0xF2, + 0xFF, 0xFF, 0x37, 0xB4, 0x26, 0x46, 0x19, 0x02, 0x2C, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, + 0x11, 0x00, 0x98, 0xF1, 0x1E, 0x60, 0xFE, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, + 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, + 0x00, 0x75, 0x88, 0xFF, 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x64, 0x40, 0x60, 0x26, + 0x03, 0x00, 0xC9, 0x60, 0x1A, 0x78, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x3A, 0xF3, 0x01, 0x98, 0xF1, + 0x1E, 0x60, 0xF2, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, + 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, + 0x27, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x3B, 0x12, 0x00, 0x98, 0xF1, 0x1F, 0x60, 0x00, 0x64, + 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, + 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x13, 0x00, 0x02, 0x3B, + 0x11, 0x00, 0x98, 0xF1, 0x1F, 0x60, 0x02, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, + 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, + 0x00, 0x75, 0x88, 0xFF, 0x2A, 0xF2, 0x28, 0x41, 0x40, 0xA8, 0x01, 0xB1, 0x02, 0x02, 0x5F, 0x02, + 0x89, 0x00, 0x60, 0x40, 0x08, 0x2A, 0x2B, 0x00, 0x98, 0xF1, 0x1E, 0x60, 0xF0, 0x64, 0xA0, 0xD3, + 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, + 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, + 0x98, 0xF1, 0x1E, 0x60, 0xF6, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, + 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, + 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x0F, 0xF2, + 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x26, 0x28, 0x00, 0x32, 0x44, 0x02, 0x26, 0x25, 0x00, 0x10, 0x2B, + 0x26, 0x00, 0x20, 0x60, 0x6C, 0x63, 0xBF, 0xD3, 0x2C, 0xF0, 0x00, 0xA8, 0x60, 0x41, 0x0D, 0x03, + 0x50, 0xFE, 0xBD, 0xD3, 0x2D, 0xF0, 0xD0, 0x80, 0xBD, 0xD3, 0x2E, 0xF0, 0xD0, 0x80, 0xBD, 0xD3, + 0x2C, 0xF0, 0xD0, 0x80, 0xFA, 0xA1, 0x10, 0x0C, 0xF3, 0x02, 0x50, 0xFE, 0x60, 0x60, 0x01, 0x64, + 0xD0, 0x80, 0x2D, 0xF0, 0x1D, 0x64, 0xD0, 0x80, 0x2E, 0xF0, 0x01, 0x64, 0xD0, 0x80, 0xFF, 0xFF, + 0x03, 0x0C, 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x40, 0x2A, 0x00, 0x00, 0xCB, 0x60, + 0xB6, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x40, 0x26, 0xFA, 0x01, 0x2A, 0xF0, 0xFF, 0xFF, 0x64, 0x40, + 0x08, 0x2A, 0x20, 0x00, 0x32, 0x40, 0x02, 0x2A, 0x1D, 0x00, 0x03, 0x67, 0xA0, 0x84, 0x00, 0x37, + 0x64, 0x63, 0x60, 0x40, 0x02, 0x37, 0x5E, 0x63, 0x60, 0x40, 0x01, 0x37, 0x58, 0x63, 0x60, 0x40, + 0x03, 0x37, 0x0D, 0x00, 0xBD, 0xD2, 0x67, 0xF1, 0xBD, 0xD2, 0xD0, 0x80, 0x68, 0xF1, 0x07, 0x02, + 0xD0, 0x80, 0xBD, 0xD2, 0x69, 0xF1, 0x03, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0xCB, 0x60, + 0xBC, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x87, 0xF4, 0x60, 0x40, 0x03, 0x2B, 0x31, 0x00, 0x89, 0xF3, + 0x06, 0x61, 0x60, 0x43, 0x66, 0x45, 0x31, 0xF0, 0x63, 0x46, 0x05, 0xF2, 0x65, 0x46, 0xD0, 0x80, + 0x30, 0xF0, 0x0F, 0x02, 0x63, 0x46, 0x04, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0x2F, 0xF0, 0x09, 0x02, + 0x63, 0x46, 0x03, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0xFF, 0xFF, 0x48, 0xFE, + 0x06, 0x00, 0xCD, 0x81, 0x02, 0xA3, 0xE7, 0x02, 0x88, 0xF1, 0x08, 0xFE, 0x64, 0x43, 0x03, 0x03, + 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0x43, 0x43, 0x23, 0x46, 0x06, 0xF0, 0x26, 0x46, 0x07, 0x67, + 0xA0, 0x84, 0x23, 0xFA, 0x64, 0x40, 0x02, 0x26, 0x2B, 0x00, 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, + 0x26, 0x1B, 0x31, 0xF2, 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, + 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, + 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, + 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, + 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x88, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x43, 0x43, + 0x07, 0xFC, 0x43, 0x43, 0x02, 0xFE, 0x1D, 0xF0, 0x12, 0x60, 0xC0, 0x62, 0xC0, 0x64, 0xC0, 0x84, + 0xA2, 0xD1, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, 0xA2, 0xDB, + 0x63, 0x45, 0x2A, 0xF2, 0x35, 0xF0, 0x60, 0x40, 0xA4, 0x36, 0x0B, 0x00, 0x08, 0x2B, 0x0C, 0x00, + 0x23, 0x46, 0x22, 0xF2, 0x26, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x06, 0x02, 0xCB, 0x60, 0xBC, 0x78, + 0xFF, 0xFF, 0xCB, 0x60, 0xB6, 0x78, 0xFF, 0xFF, 0x23, 0x46, 0x1E, 0xF2, 0x26, 0x46, 0x44, 0x4C, + 0x0F, 0x26, 0x19, 0x00, 0x00, 0xBC, 0x40, 0x45, 0x0B, 0x03, 0x00, 0x64, 0x23, 0x46, 0x1E, 0xFA, + 0x26, 0x46, 0xA2, 0xFF, 0xB4, 0x60, 0x58, 0x4E, 0x48, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x26, 0x46, + 0x2A, 0xF0, 0x2C, 0x44, 0x64, 0x40, 0x04, 0x27, 0x06, 0x00, 0x23, 0x46, 0x22, 0xFA, 0x26, 0x46, + 0xCA, 0x60, 0xB6, 0x78, 0xFF, 0xFF, 0x3F, 0xF2, 0x02, 0xFA, 0xA2, 0xFF, 0x16, 0xF0, 0xFF, 0xFF, + 0x64, 0x44, 0x01, 0x26, 0xDC, 0x9C, 0x93, 0xF3, 0x2A, 0xF2, 0xDC, 0x83, 0x93, 0xFD, 0x06, 0xF4, + 0x01, 0xF8, 0x26, 0x46, 0x60, 0x40, 0x40, 0x2B, 0x18, 0x00, 0x64, 0x44, 0x00, 0x65, 0xFF, 0xB4, + 0xFC, 0xA4, 0x06, 0xF0, 0x03, 0x03, 0x64, 0x46, 0x0C, 0x0D, 0x02, 0x65, 0x26, 0x46, 0x00, 0xF2, + 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x60, 0x46, 0xF9, 0x01, 0x01, 0xF2, 0xFF, 0xFF, + 0xD4, 0x84, 0x01, 0xFA, 0x66, 0x44, 0x26, 0x46, 0x06, 0xFA, 0x06, 0xF4, 0x00, 0xF2, 0x80, 0xFC, + 0x40, 0x45, 0xB4, 0x60, 0x58, 0x4E, 0x48, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x26, 0x46, 0x2C, 0x44, + 0x0F, 0x26, 0x10, 0x00, 0x23, 0x46, 0x22, 0xFA, 0x26, 0x44, 0x1E, 0xFA, 0x26, 0x46, 0x1B, 0x60, + 0xDA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0x6F, 0x00, 0xA3, 0x46, 0x22, 0xF2, 0x60, 0x45, 0xDC, 0x84, 0xD4, 0x80, 0x22, 0xFA, + 0xA3, 0x46, 0x6C, 0x02, 0x2A, 0xF0, 0xA3, 0x46, 0x1E, 0xF2, 0xA3, 0x46, 0x00, 0xBC, 0x00, 0xF2, + 0x01, 0x02, 0x64, 0x00, 0x44, 0x4C, 0x3F, 0xF0, 0x60, 0x43, 0x23, 0x46, 0x1E, 0xF4, 0x09, 0x60, + 0x00, 0x65, 0x3F, 0xF2, 0x26, 0x46, 0xC0, 0x84, 0xD4, 0x80, 0x60, 0x45, 0x57, 0x07, 0x80, 0xFC, + 0x1B, 0xF2, 0x06, 0xF2, 0x60, 0x41, 0x23, 0x46, 0x1E, 0xF4, 0x1B, 0xF0, 0x06, 0xF0, 0xC1, 0x81, + 0x06, 0xFA, 0x05, 0xFA, 0x9B, 0xFA, 0x65, 0x44, 0x3F, 0xFA, 0x64, 0x46, 0x00, 0xFC, 0x63, 0x46, + 0x01, 0xF2, 0x10, 0x61, 0xF2, 0xA4, 0x01, 0xFA, 0xC8, 0x83, 0x02, 0x64, 0x59, 0xD0, 0x58, 0xD8, + 0xFD, 0x1F, 0x06, 0x45, 0x1B, 0x60, 0xDA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x25, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA2, 0xFF, 0x00, 0xF4, 0x01, 0xF0, 0x0A, 0x18, + 0x70, 0x67, 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, 0xC0, 0x84, 0x01, 0xFA, 0x25, 0x46, 0x25, 0x44, + 0x80, 0xFC, 0x05, 0xFA, 0xB4, 0x60, 0x58, 0x4E, 0x48, 0x78, 0xFF, 0xFF, 0xD4, 0xFE, 0xA3, 0xFF, + 0x2C, 0x44, 0x04, 0x27, 0x16, 0x00, 0x23, 0x46, 0x1E, 0xF2, 0x9E, 0xFC, 0x60, 0x46, 0x46, 0x46, + 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, 0x26, 0x46, 0x2C, 0x43, 0x2A, 0xFC, 0x06, 0xF4, + 0x00, 0x64, 0x00, 0xFA, 0x01, 0xF0, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0x01, 0xFA, 0x26, 0x46, + 0x1D, 0x00, 0x00, 0x66, 0x46, 0x46, 0xC7, 0x60, 0x31, 0x78, 0xFF, 0xFF, 0xA3, 0x46, 0x1E, 0xF0, + 0x9E, 0xFC, 0x00, 0x63, 0x33, 0x85, 0xA3, 0x46, 0x0D, 0x03, 0xA3, 0x46, 0x22, 0xF2, 0x0F, 0x65, + 0xA4, 0x85, 0xD4, 0x84, 0x22, 0xFA, 0xA3, 0x46, 0xA2, 0xFF, 0xB4, 0x60, 0x58, 0x4E, 0x48, 0x78, + 0xFF, 0xFF, 0xA3, 0xFF, 0x26, 0x46, 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x88, 0xF3, + 0xFF, 0xFF, 0xD0, 0x80, 0x64, 0x46, 0x6F, 0xF2, 0x26, 0x46, 0x50, 0x03, 0x60, 0x40, 0x00, 0x36, + 0x4D, 0x00, 0x64, 0x46, 0x0E, 0xF2, 0x26, 0x46, 0x60, 0x47, 0xFF, 0xB5, 0x27, 0xF2, 0xFF, 0xFF, + 0xFF, 0xB4, 0xD4, 0x80, 0xFF, 0xFF, 0x42, 0x06, 0x64, 0x46, 0x6F, 0xF2, 0x26, 0x46, 0x60, 0x47, + 0xFF, 0xB5, 0x65, 0x41, 0x0F, 0x60, 0xA2, 0x65, 0x00, 0x64, 0xE9, 0x81, 0xD8, 0x84, 0xFD, 0x02, + 0xC8, 0x84, 0x60, 0x43, 0x44, 0xD1, 0xFF, 0xFF, 0x64, 0x47, 0xFF, 0xB5, 0x27, 0xF2, 0xFF, 0xFF, + 0xFF, 0xB4, 0xD4, 0x80, 0x64, 0x44, 0x06, 0x06, 0x07, 0xF0, 0xFF, 0xFF, 0x64, 0x46, 0x0E, 0xFA, + 0x26, 0x46, 0x19, 0x00, 0x00, 0x61, 0x27, 0xF0, 0x0F, 0x60, 0xA2, 0x65, 0x61, 0x43, 0x45, 0xD3, + 0x64, 0x41, 0xFF, 0xB1, 0x61, 0x45, 0x60, 0x47, 0xFF, 0xB4, 0xDB, 0x83, 0xD4, 0x80, 0x63, 0x41, + 0xF3, 0x02, 0xCB, 0x83, 0x63, 0x41, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x07, 0xF0, 0xFF, 0xFF, + 0x64, 0x46, 0x0E, 0xFA, 0x26, 0x46, 0xAF, 0x84, 0xE8, 0x81, 0x05, 0x03, 0x00, 0x60, 0x01, 0x64, + 0xCD, 0x81, 0xE0, 0x84, 0xFD, 0x02, 0x64, 0x46, 0x70, 0xFA, 0x26, 0x46, 0x2A, 0xF2, 0x32, 0xF0, + 0x60, 0x40, 0x08, 0x2A, 0x5C, 0x00, 0x01, 0x2B, 0x2F, 0x00, 0x64, 0x40, 0x01, 0x2A, 0x2C, 0x00, + 0x98, 0xF1, 0x1E, 0x60, 0xF0, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, + 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, + 0x88, 0xFF, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, 0x98, 0xF1, 0x1E, 0x60, 0xF6, 0x64, 0xA0, 0xD3, + 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, + 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, + 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x2B, 0x00, 0x98, 0xF1, 0x1E, 0x60, 0xEE, 0x64, 0xA0, 0xD3, + 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, + 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, + 0x98, 0xF1, 0x1E, 0x60, 0xF4, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, + 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, + 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x07, 0xF4, + 0xFF, 0xFF, 0x22, 0xF2, 0x26, 0x46, 0x0F, 0xB4, 0xDC, 0x85, 0x98, 0xF1, 0x1E, 0x60, 0xF2, 0x64, + 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, + 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, + 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x27, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x3B, + 0x12, 0x00, 0x98, 0xF1, 0x1F, 0x60, 0x00, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, + 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, + 0x00, 0x75, 0x88, 0xFF, 0x13, 0x00, 0x02, 0x3B, 0x11, 0x00, 0x98, 0xF1, 0x1F, 0x60, 0x02, 0x64, + 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, + 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xCC, 0x60, 0x06, 0x78, + 0xFF, 0xFF, 0xC7, 0x60, 0x31, 0x78, 0xFF, 0xFF, 0x1B, 0x60, 0xDA, 0x64, 0x40, 0x4B, 0xF0, 0x60, + 0x58, 0x4D, 0x75, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xC7, 0x60, 0x31, 0x78, 0xFF, 0xFF, + 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xBE, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0x00, 0x66, 0x46, 0x46, 0xC7, 0x60, 0x31, 0x78, + 0xFF, 0xFF, 0x2A, 0xF2, 0x58, 0x63, 0x60, 0x47, 0x01, 0x27, 0x64, 0x63, 0x25, 0x60, 0x26, 0x62, + 0x61, 0x5C, 0xA2, 0xD9, 0xBD, 0xD0, 0xBD, 0xD0, 0x64, 0x45, 0x64, 0x41, 0xBD, 0xD0, 0x00, 0xF4, + 0x04, 0xF8, 0x83, 0xFA, 0x82, 0xF8, 0xA6, 0x46, 0x02, 0xB0, 0x5E, 0x63, 0x04, 0x03, 0x64, 0x63, + 0x03, 0xB0, 0x02, 0x3A, 0x6C, 0x63, 0x3F, 0xF2, 0xBD, 0xD0, 0xBD, 0xD0, 0x64, 0x45, 0x64, 0x41, + 0xBD, 0xD0, 0xA6, 0x46, 0x07, 0xF8, 0x86, 0xFA, 0x85, 0xF8, 0x60, 0x47, 0x08, 0xFA, 0x25, 0x60, + 0x26, 0x62, 0xA2, 0xD1, 0x26, 0x46, 0x64, 0x41, 0x2F, 0x58, 0xFF, 0xFF, 0x2A, 0xF2, 0x2C, 0xF0, + 0x31, 0x40, 0x20, 0x26, 0x09, 0x00, 0x60, 0x40, 0xA4, 0x36, 0x21, 0x00, 0x08, 0x26, 0x07, 0x00, + 0x7E, 0xF1, 0xCC, 0x60, 0xCF, 0x78, 0xFF, 0xFF, 0xCC, 0x60, 0xFF, 0x78, 0xFF, 0xFF, 0x64, 0x40, + 0x01, 0x26, 0x12, 0x00, 0x3F, 0xF0, 0x32, 0x40, 0x10, 0x2A, 0x0A, 0x00, 0x64, 0x41, 0x60, 0x40, + 0x40, 0x27, 0x06, 0x00, 0xCD, 0x81, 0xDD, 0x81, 0x03, 0x03, 0x02, 0x03, 0x01, 0x61, 0x01, 0x00, + 0x00, 0x61, 0x60, 0x40, 0x18, 0x3A, 0x03, 0x00, 0xCD, 0x60, 0x3B, 0x78, 0xFF, 0xFF, 0x07, 0xF2, + 0x88, 0xF1, 0x66, 0x45, 0xD0, 0x80, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x03, 0x03, 0xFF, 0xFF, + 0x02, 0x26, 0x07, 0x00, 0xDA, 0x60, 0x58, 0x4F, 0xDB, 0x78, 0xFF, 0xFF, 0xCD, 0x60, 0x37, 0x78, + 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0xA4, 0x3A, 0x07, 0x00, 0xDD, 0x60, 0x58, 0x4F, + 0x45, 0x78, 0xFF, 0xFF, 0xCD, 0x60, 0x37, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0xCB, 0x60, 0x58, 0x4F, + 0xD9, 0x78, 0xFF, 0xFF, 0x3F, 0xF2, 0x06, 0x65, 0xD4, 0x80, 0x60, 0x43, 0x52, 0x04, 0x00, 0xF4, + 0xAA, 0x60, 0xAA, 0x65, 0x09, 0xF2, 0x0A, 0xF0, 0xD4, 0x80, 0x03, 0x64, 0x4A, 0x02, 0xD0, 0x80, + 0x00, 0x64, 0x0B, 0xF0, 0x46, 0x02, 0x64, 0x45, 0xD4, 0x80, 0xF8, 0x7F, 0x08, 0x02, 0x0C, 0xF0, + 0x26, 0x46, 0x64, 0x45, 0x23, 0xF0, 0x20, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x0B, 0x00, 0xD4, 0x80, + 0x1D, 0x60, 0x60, 0x64, 0x11, 0x02, 0x0C, 0xF0, 0x26, 0x46, 0x64, 0x45, 0x23, 0xF0, 0x40, 0x67, + 0xB0, 0x84, 0xA2, 0xDA, 0x65, 0x44, 0x88, 0x3A, 0x2C, 0x00, 0x77, 0x37, 0x03, 0x00, 0x78, 0x37, + 0x01, 0x00, 0x8E, 0x37, 0x00, 0x61, 0x25, 0x00, 0xD4, 0x80, 0x08, 0x65, 0x22, 0x02, 0xD7, 0x80, + 0x01, 0x60, 0x00, 0x64, 0x0C, 0xF0, 0x1D, 0x04, 0xD0, 0x80, 0x0D, 0xF0, 0x1A, 0x02, 0x26, 0x46, + 0x14, 0xF2, 0x01, 0x63, 0x02, 0xA8, 0x64, 0x47, 0x14, 0x03, 0x7F, 0xB4, 0xFD, 0xA0, 0x06, 0x03, + 0x10, 0x07, 0x23, 0xF0, 0x60, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x6A, 0x00, 0xD2, 0xF3, 0xFF, 0xFF, + 0x02, 0xBC, 0xD2, 0xFB, 0xE5, 0x60, 0x58, 0x4F, 0x94, 0x78, 0xFF, 0xFF, 0xCD, 0x60, 0x37, 0x78, + 0xFF, 0xFF, 0x26, 0x46, 0x61, 0x40, 0x01, 0x2A, 0x12, 0x00, 0x98, 0xF1, 0x1F, 0x60, 0x06, 0x64, + 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, + 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x7C, 0x00, 0xDD, 0x60, + 0x58, 0x4F, 0x45, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, 0x36, 0x73, 0x00, + 0xCD, 0x60, 0x58, 0x4F, 0x48, 0x78, 0xFF, 0xFF, 0xCD, 0x60, 0x37, 0x78, 0xFF, 0xFF, 0x60, 0x40, + 0x0C, 0x26, 0x69, 0x00, 0x64, 0x40, 0x01, 0x2A, 0x66, 0x00, 0xB0, 0x3A, 0x05, 0x00, 0xD1, 0x60, + 0x58, 0x4F, 0x80, 0x78, 0xFF, 0xFF, 0x5B, 0x00, 0x00, 0x3A, 0x05, 0x00, 0xD4, 0x60, 0x58, 0x4F, + 0xF3, 0x78, 0xFF, 0xFF, 0x54, 0x00, 0x20, 0x3A, 0x05, 0x00, 0xD4, 0x60, 0x58, 0x4F, 0xF3, 0x78, + 0xFF, 0xFF, 0x4D, 0x00, 0xC0, 0x3A, 0x05, 0x00, 0xDA, 0x60, 0x58, 0x4F, 0x48, 0x78, 0xFF, 0xFF, + 0x46, 0x00, 0xA0, 0x3A, 0x05, 0x00, 0xDA, 0x60, 0x58, 0x4F, 0xA6, 0x78, 0xFF, 0xFF, 0x3F, 0x00, + 0x40, 0x3A, 0x0D, 0x00, 0xE1, 0x60, 0x58, 0x4F, 0x10, 0x78, 0xFF, 0xFF, 0x38, 0x00, 0x60, 0x40, + 0x50, 0x3A, 0x05, 0x00, 0xEA, 0x60, 0x58, 0x4F, 0xF5, 0x78, 0xFF, 0xFF, 0x30, 0x00, 0x33, 0x00, + 0xD2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xD2, 0xFB, 0x2A, 0xF2, 0x3B, 0xF0, 0x60, 0x40, 0x40, 0x2B, + 0x19, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x04, 0xB4, 0xFF, 0xFF, 0x14, 0x03, 0xC0, 0x60, 0x00, 0x64, + 0x64, 0x40, 0x20, 0x2B, 0x0F, 0x00, 0xA0, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x23, 0xF2, + 0x10, 0xBD, 0xB4, 0x9C, 0x3F, 0xF2, 0x23, 0xF8, 0xF8, 0xA4, 0x3F, 0xFA, 0x00, 0xF4, 0x60, 0x47, + 0x08, 0xFA, 0x26, 0x46, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xBE, 0x64, 0xA2, 0xDB, 0x26, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0x0C, 0x00, 0x66, 0x44, + 0x00, 0xA8, 0xFF, 0xFF, 0x0A, 0x03, 0x26, 0x46, 0x1B, 0x60, 0xDA, 0x64, 0x40, 0x4B, 0xF0, 0x60, + 0x58, 0x4D, 0x75, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xCB, 0x60, 0xB9, 0x78, 0xFF, 0xFF, + 0x14, 0xF2, 0x00, 0x7C, 0x3E, 0xF8, 0xCC, 0x84, 0xCC, 0x84, 0x19, 0x03, 0x60, 0x02, 0x11, 0xF2, + 0x07, 0xFA, 0xAC, 0xF3, 0x19, 0xFA, 0xCD, 0x60, 0x58, 0x4E, 0xE4, 0x78, 0xFF, 0xFF, 0x1B, 0x60, + 0xDA, 0x62, 0x1B, 0x60, 0x9A, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, 0xF2, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x79, 0x00, 0xA2, 0xFF, + 0x46, 0x45, 0xB4, 0x60, 0x58, 0x4E, 0x91, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x11, 0x03, 0x7E, 0x63, + 0x46, 0x4B, 0x25, 0x46, 0xA3, 0xD0, 0x2B, 0x46, 0xA3, 0xD8, 0xFB, 0x1F, 0x89, 0xFC, 0x8A, 0xFC, + 0x88, 0xFC, 0x05, 0x18, 0x64, 0x46, 0x01, 0xF0, 0x10, 0x67, 0xC0, 0x84, 0x01, 0xFA, 0x08, 0xFE, + 0x2B, 0x46, 0x46, 0x46, 0x25, 0x46, 0xCD, 0x60, 0x58, 0x4E, 0xE4, 0x78, 0xFF, 0xFF, 0x1F, 0x60, + 0x8E, 0x62, 0xA2, 0xD3, 0x88, 0xF3, 0x00, 0xA8, 0x07, 0xFA, 0x0F, 0x03, 0x1B, 0x60, 0xDA, 0x62, + 0x1B, 0x60, 0x94, 0x64, 0xA2, 0xDB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xF3, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x0E, 0x00, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, + 0x88, 0x64, 0xA2, 0xDB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xF4, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x26, 0x44, 0x00, 0xA8, 0xC1, 0xFE, 0x31, 0x03, 0xD2, 0xF3, + 0xFF, 0xFF, 0x02, 0xBC, 0xD2, 0xFB, 0x26, 0x46, 0x2A, 0xF2, 0x3B, 0xF0, 0x60, 0x40, 0x40, 0x2B, + 0x18, 0x00, 0x64, 0x40, 0x20, 0x2B, 0x15, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x04, 0xB4, 0xFF, 0xFF, + 0x10, 0x03, 0xC0, 0x67, 0xA0, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x23, 0xF2, 0x10, 0xBD, + 0xB4, 0x9C, 0x3F, 0xF2, 0x23, 0xF8, 0xF8, 0xA4, 0x3F, 0xFA, 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, + 0x26, 0x46, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xBE, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0xF1, 0x64, 0x3B, 0x42, 0x4A, 0xDB, + 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x2A, 0xF2, 0x82, 0x60, 0xFF, 0x65, 0xA4, 0x87, + 0x02, 0xBF, 0x2A, 0xFA, 0x1C, 0xF2, 0x13, 0xFA, 0x32, 0xF2, 0x2C, 0xFA, 0x33, 0xF2, 0x2D, 0xFA, + 0x34, 0xF2, 0x2E, 0xFA, 0x2F, 0xF2, 0x32, 0xFA, 0x30, 0xF2, 0x33, 0xFA, 0x31, 0xF2, 0x34, 0xFA, + 0x67, 0xF3, 0x2F, 0xFA, 0x68, 0xF3, 0x30, 0xFA, 0x69, 0xF3, 0x31, 0xFA, 0x2E, 0x58, 0xFF, 0xFF, + 0x0F, 0x60, 0xF8, 0x62, 0xD0, 0x60, 0x7B, 0x64, 0xA2, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x1F, 0x60, + 0x62, 0x63, 0x20, 0x60, 0x02, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1E, 0x63, 0x1F, 0x60, 0x6C, 0x61, + 0x20, 0x60, 0x0C, 0x64, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0x1F, 0x60, 0x8E, 0x63, 0x20, 0x60, + 0x2E, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1F, 0x60, 0x90, 0x63, 0x20, 0x60, 0x30, 0x62, 0xA2, 0xD3, + 0xA3, 0xDB, 0x1F, 0x60, 0x9A, 0x63, 0x20, 0x60, 0x3A, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1F, 0x60, + 0x9C, 0x63, 0x20, 0x60, 0x3C, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1F, 0x60, 0x9E, 0x63, 0x20, 0x60, + 0x3E, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1F, 0x60, 0xA0, 0x63, 0x20, 0x60, 0x40, 0x62, 0xA2, 0xD3, + 0xA3, 0xDB, 0x1F, 0x60, 0x92, 0x63, 0x20, 0x60, 0x32, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1F, 0x60, + 0x94, 0x63, 0x20, 0x60, 0x34, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1F, 0x60, 0x96, 0x63, 0x20, 0x60, + 0x36, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1F, 0x60, 0xB6, 0x63, 0xBD, 0xD1, 0xCB, 0xF9, 0x67, 0xF9, + 0xBD, 0xD1, 0xCC, 0xF9, 0x68, 0xF9, 0xA3, 0xD1, 0xCD, 0xF9, 0x69, 0xF9, 0x01, 0x64, 0x6B, 0xFB, + 0x1F, 0x60, 0xA8, 0x62, 0xA2, 0xD3, 0xC4, 0xFB, 0x00, 0x63, 0x4A, 0xFD, 0x5A, 0xFD, 0x6C, 0xFD, + 0x6D, 0xFD, 0x21, 0x60, 0x82, 0x64, 0xA0, 0xD3, 0xEA, 0x60, 0x58, 0x4E, 0x78, 0x78, 0xFF, 0xFF, + 0x21, 0x60, 0x80, 0x64, 0xA0, 0xD1, 0x1F, 0x60, 0x92, 0x62, 0xA2, 0xD3, 0xFF, 0x60, 0xE7, 0x65, + 0x32, 0x41, 0xA5, 0x81, 0xFF, 0xA0, 0xFF, 0xFF, 0x01, 0x03, 0x0B, 0x00, 0x08, 0x65, 0xB5, 0x81, + 0x1F, 0x60, 0x96, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x02, 0x00, 0x10, 0x65, + 0xB5, 0x81, 0x41, 0x52, 0x88, 0xF5, 0x32, 0x44, 0x10, 0xB0, 0xFF, 0xFF, 0x0B, 0x03, 0x21, 0x60, + 0x2C, 0x62, 0xA2, 0xD3, 0x06, 0xF0, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x80, 0xBF, + 0xB0, 0x84, 0x06, 0xFA, 0x1F, 0x60, 0x92, 0x62, 0xA2, 0xD3, 0x22, 0x7C, 0xFF, 0xA0, 0xFD, 0xA0, + 0x05, 0x06, 0x03, 0x03, 0xFE, 0xA0, 0x04, 0x7C, 0x01, 0x02, 0x36, 0xF8, 0x0E, 0xF0, 0x0F, 0x60, + 0xA2, 0x65, 0x20, 0x60, 0x38, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xFE, 0xA0, 0x03, 0xA8, 0x11, 0x06, + 0x5F, 0xF1, 0x06, 0x02, 0x64, 0x44, 0x08, 0x2A, 0x09, 0x00, 0x06, 0x64, 0x44, 0xD3, 0x0D, 0x00, + 0x64, 0x44, 0x20, 0x2A, 0x03, 0x00, 0x0A, 0x64, 0x44, 0xD3, 0x07, 0x00, 0x01, 0x64, 0x44, 0xD3, + 0x04, 0x00, 0xE8, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x00, 0x00, 0x0E, 0xFA, 0x1F, 0x60, 0x9E, 0x62, + 0xA2, 0xD1, 0x20, 0x44, 0x20, 0xB5, 0x64, 0x41, 0x00, 0xB9, 0xD4, 0x84, 0x08, 0x28, 0x20, 0xBC, + 0x40, 0x40, 0x11, 0x60, 0xF0, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x00, 0xB8, 0x10, 0x60, 0x0C, 0x65, + 0x0D, 0x03, 0x11, 0x60, 0xF8, 0x63, 0xC5, 0xF3, 0xA3, 0xD1, 0xE0, 0x84, 0xC4, 0x84, 0xA0, 0xD3, + 0xFF, 0xFF, 0x01, 0xB0, 0xFF, 0xFF, 0x02, 0x02, 0xC5, 0xF9, 0x65, 0xF9, 0xC5, 0xF3, 0x01, 0x61, + 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, 0xE1, 0x81, 0xFB, 0x01, 0x9A, 0xF3, 0x61, 0x45, 0xA4, 0x80, + 0xFF, 0xFF, 0x0B, 0x02, 0x00, 0xB8, 0x01, 0x63, 0x08, 0x03, 0xE8, 0x84, 0xFF, 0xFF, 0x02, 0x24, + 0x02, 0x00, 0xDF, 0x83, 0xFA, 0x01, 0xC5, 0xFD, 0x65, 0xFD, 0x0A, 0x64, 0x25, 0x60, 0x1E, 0x63, + 0xA3, 0xDB, 0x01, 0x64, 0x25, 0x60, 0x20, 0x63, 0xA3, 0xDB, 0xB6, 0xF1, 0x09, 0x60, 0x2A, 0x64, + 0xD0, 0x80, 0x03, 0x64, 0x01, 0x06, 0x06, 0x64, 0xB0, 0xFB, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xD8, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, + 0xCF, 0x60, 0x05, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD6, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x65, 0xF1, 0x1C, 0x60, 0x00, 0x62, 0xA2, 0xD9, 0x08, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCF, 0x60, + 0x2D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xCE, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x20, 0x44, 0x01, 0x65, 0x34, 0x80, 0x1F, 0x60, 0xA6, 0x64, 0xA0, 0xD3, + 0xC3, 0xFB, 0x60, 0x40, 0x05, 0x3A, 0x03, 0x00, 0xEB, 0x60, 0x1A, 0x61, 0x11, 0x00, 0x04, 0x3A, + 0x03, 0x00, 0xEB, 0x60, 0x0E, 0x61, 0x0C, 0x00, 0x03, 0x3A, 0x03, 0x00, 0xEB, 0x60, 0x02, 0x61, + 0x07, 0x00, 0x02, 0x3A, 0x03, 0x00, 0xEA, 0x60, 0xF6, 0x61, 0x02, 0x00, 0xEA, 0x60, 0xEA, 0x61, + 0x3E, 0x60, 0x00, 0x66, 0x01, 0x60, 0x78, 0x64, 0x0A, 0x63, 0x59, 0xD0, 0x58, 0xD9, 0xFD, 0x1F, + 0x00, 0x66, 0xC4, 0xF3, 0x60, 0x41, 0x00, 0xA8, 0xFA, 0xA1, 0x01, 0x03, 0xA1, 0xDB, 0x01, 0x60, + 0x7A, 0x63, 0x16, 0x60, 0xC4, 0x61, 0xBD, 0xD3, 0xFF, 0xFF, 0x20, 0x7F, 0xA1, 0xDB, 0xBD, 0xD3, + 0xFF, 0xFF, 0x21, 0x7F, 0x59, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0x22, 0x7F, 0x59, 0xDB, 0x0F, 0x60, + 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xD8, 0x62, 0x40, 0x60, + 0x00, 0x64, 0xA2, 0xDB, 0xCF, 0x60, 0x77, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x1C, 0x60, 0x00, 0x62, 0x16, 0x60, 0xC2, 0x64, 0xA2, 0xDB, 0x20, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x2D, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCF, 0x60, 0x9C, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x65, 0xF1, 0x1C, 0x60, 0x00, 0x62, 0xA2, 0xD9, 0x08, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, + 0x0F, 0x60, 0xD8, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCF, 0x60, 0xB3, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, + 0x0F, 0x60, 0xCE, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x20, 0x40, 0x20, 0x2A, 0x04, 0x00, 0xEB, 0x60, 0x58, 0x4E, 0x16, 0x78, 0xFF, 0xFF, 0x0F, 0x60, + 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x4E, 0xF3, 0xFF, 0xFF, 0x13, 0x1B, 0x1F, 0x60, 0xAE, 0x64, + 0xA0, 0xD3, 0xC7, 0xFB, 0x1F, 0x60, 0x1E, 0x65, 0x1F, 0x60, 0xBC, 0x61, 0x1F, 0x60, 0x1C, 0x64, + 0x20, 0x63, 0x59, 0xD1, 0x58, 0xD9, 0xA5, 0xD9, 0xDA, 0x85, 0xFB, 0x1F, 0xD0, 0x60, 0x62, 0x78, + 0xFF, 0xFF, 0x20, 0x60, 0x40, 0x63, 0xE0, 0x84, 0xE0, 0x85, 0xC4, 0x85, 0xC7, 0x83, 0xFE, 0xA5, + 0x89, 0xF3, 0xFF, 0xFF, 0xC4, 0x84, 0x66, 0x45, 0x60, 0x46, 0x60, 0x41, 0xBD, 0xD1, 0x03, 0xF8, + 0xBD, 0xD1, 0x04, 0xF8, 0xA3, 0xD1, 0x05, 0xF8, 0x06, 0xF2, 0xFF, 0xFF, 0x02, 0x7E, 0x06, 0xFA, + 0x5F, 0xF3, 0x60, 0xFB, 0x73, 0xF0, 0x63, 0xF9, 0x66, 0x43, 0x21, 0x60, 0x2C, 0x62, 0x32, 0x40, + 0x08, 0x2A, 0x09, 0x00, 0xA2, 0xD3, 0x06, 0xF0, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, + 0x80, 0xBF, 0xB0, 0x84, 0x06, 0xFA, 0x63, 0x44, 0x63, 0xF3, 0x60, 0x45, 0x66, 0x41, 0x65, 0x46, + 0x8C, 0xFA, 0x60, 0x40, 0x01, 0x36, 0x06, 0x00, 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, + 0x05, 0x3A, 0x02, 0x00, 0x00, 0x64, 0x01, 0x00, 0x01, 0x64, 0x6F, 0xFA, 0x5F, 0xF3, 0x60, 0xF1, + 0xFF, 0xFF, 0xA0, 0x84, 0x65, 0x43, 0x02, 0x02, 0x5F, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, + 0xAE, 0x65, 0x63, 0xF3, 0xFF, 0xFF, 0xE0, 0x84, 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, + 0x04, 0x02, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x61, 0xFB, 0x6F, 0xF0, + 0x60, 0x47, 0x90, 0x84, 0x6F, 0xFA, 0x60, 0x47, 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, + 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x70, 0xF0, 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, + 0x02, 0x05, 0xDD, 0x81, 0xFB, 0x01, 0xE1, 0x81, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, + 0x66, 0x43, 0x0C, 0xF4, 0xC5, 0xFE, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, + 0xD8, 0x62, 0x00, 0x60, 0x30, 0x64, 0xA2, 0xDB, 0xCF, 0x60, 0xC7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x4E, 0xDF, 0x60, 0x58, 0x4F, 0x13, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, + 0x0F, 0x4E, 0xDC, 0x60, 0x58, 0x4F, 0x6B, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x4E, 0xDB, 0x60, + 0x58, 0x4F, 0xE8, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x4E, 0xDB, 0x60, 0x58, 0x4F, 0x42, 0x78, + 0xFF, 0xFF, 0x0E, 0x4F, 0xD7, 0x01, 0x4E, 0xF3, 0x7E, 0xF5, 0x60, 0x40, 0xFF, 0x22, 0x0A, 0x00, + 0x89, 0xF1, 0xCC, 0x84, 0xE0, 0x84, 0xC0, 0x86, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, + 0x7E, 0xF5, 0x08, 0x00, 0x0F, 0x60, 0xF4, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x11, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x4E, 0xF3, 0x66, 0x40, 0xFF, 0x22, 0x05, 0x00, 0xFF, 0x22, 0x37, 0x00, + 0xD1, 0x60, 0x30, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x6A, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x6A, 0xF3, + 0x00, 0x65, 0xD4, 0x80, 0x4E, 0xF3, 0x0F, 0x03, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x0F, 0x60, 0xD8, 0x62, 0x80, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD0, 0x60, 0x9F, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, + 0x0B, 0x04, 0x0F, 0x60, 0xD8, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD0, 0x60, 0xB3, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0x00, 0x62, 0x06, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x44, 0x01, 0xB5, 0x54, 0x80, 0xDA, 0xFE, 0xBE, 0xFE, 0x88, 0xF1, + 0x02, 0x64, 0x87, 0xF3, 0xC0, 0x83, 0x40, 0x48, 0x76, 0xFD, 0xE4, 0x60, 0x58, 0x4E, 0x9D, 0x78, + 0xFF, 0xFF, 0x28, 0x44, 0x4C, 0x88, 0x76, 0xF3, 0x02, 0x65, 0xC4, 0x83, 0xF5, 0x02, 0xA2, 0x60, + 0x58, 0x4E, 0x00, 0x78, 0xFF, 0xFF, 0x14, 0x60, 0xD0, 0x62, 0x14, 0x60, 0xD2, 0x64, 0xA2, 0xDB, + 0x00, 0x64, 0x4A, 0xDB, 0x01, 0x60, 0xFE, 0x63, 0x12, 0x60, 0xCC, 0x61, 0x00, 0x64, 0x59, 0xDB, + 0xFE, 0x1F, 0x7E, 0xF1, 0x1B, 0x60, 0x9A, 0x61, 0x64, 0x40, 0xFF, 0x26, 0x39, 0x00, 0xD1, 0x60, + 0x58, 0x4E, 0x33, 0x78, 0xFF, 0xFF, 0x1B, 0x60, 0x88, 0x61, 0xD1, 0x60, 0x58, 0x4E, 0x33, 0x78, + 0xFF, 0xFF, 0x1B, 0x60, 0x8E, 0x61, 0xD1, 0x60, 0x58, 0x4E, 0x33, 0x78, 0xFF, 0xFF, 0x1B, 0x60, + 0xA0, 0x61, 0xD1, 0x60, 0x58, 0x4E, 0x33, 0x78, 0xFF, 0xFF, 0x1B, 0x60, 0xA6, 0x61, 0xD1, 0x60, + 0x58, 0x4E, 0x33, 0x78, 0xFF, 0xFF, 0x1B, 0x60, 0xB2, 0x61, 0xD1, 0x60, 0x58, 0x4E, 0x33, 0x78, + 0xFF, 0xFF, 0x1B, 0x60, 0xBE, 0x61, 0xD1, 0x60, 0x58, 0x4E, 0x33, 0x78, 0xFF, 0xFF, 0x1B, 0x60, + 0xAC, 0x61, 0xD1, 0x60, 0x58, 0x4E, 0x33, 0x78, 0xFF, 0xFF, 0x1B, 0x60, 0x94, 0x61, 0xD1, 0x60, + 0x58, 0x4E, 0x5F, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, + 0xC5, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xA1, 0xD3, 0x0E, 0x57, 0x24, 0x00, 0x0E, 0xF2, 0x44, 0x4C, + 0x80, 0xB0, 0x10, 0xB0, 0x0B, 0x03, 0x1B, 0x60, 0xDA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x13, 0x00, 0x12, 0x02, 0xF0, 0x37, + 0x09, 0x00, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, 0x90, 0xF3, 0x02, 0x02, + 0xCC, 0x84, 0x90, 0xFB, 0x1B, 0x60, 0xDA, 0x64, 0x40, 0x4B, 0xF0, 0x60, 0x58, 0x4D, 0x75, 0x78, + 0xFF, 0xFF, 0x2C, 0x44, 0xAC, 0x86, 0x09, 0xF0, 0xD9, 0x02, 0x37, 0x58, 0xFF, 0xFF, 0xA1, 0xD3, + 0x0E, 0x57, 0x19, 0x00, 0x0E, 0xF2, 0x44, 0x4C, 0x80, 0xB0, 0x10, 0xB0, 0x0B, 0x03, 0x1B, 0x60, + 0xDA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0x08, 0x00, 0x07, 0x02, 0x1B, 0x60, 0xDA, 0x64, 0x40, 0x4B, 0xF0, 0x60, 0x58, 0x4D, + 0x75, 0x78, 0xFF, 0xFF, 0x2C, 0x44, 0xAC, 0x86, 0x09, 0xF0, 0xE4, 0x02, 0x37, 0x58, 0xFF, 0xFF, + 0x00, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xB0, 0x64, 0x2A, 0xFA, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, + 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0xCD, 0xF3, + 0x31, 0xFA, 0x67, 0xF3, 0x32, 0xFA, 0x68, 0xF3, 0x33, 0xFA, 0x69, 0xF3, 0x34, 0xFA, 0xAC, 0xF1, + 0x19, 0xF8, 0x06, 0x63, 0x3F, 0xFC, 0x1C, 0xF2, 0x13, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0x07, 0xF2, + 0x88, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x0C, 0x03, 0x60, 0x46, 0x06, 0xF2, 0x26, 0x46, + 0x01, 0xB0, 0xFF, 0xFF, 0x03, 0x02, 0xD3, 0x60, 0x64, 0x78, 0xFF, 0xFF, 0xD4, 0x60, 0xBA, 0x78, + 0xFF, 0xFF, 0x00, 0xF4, 0x0A, 0xF2, 0x09, 0xF2, 0xFF, 0xA0, 0x00, 0xA0, 0x13, 0x02, 0xFF, 0xA0, + 0x04, 0x03, 0x08, 0x03, 0xD1, 0x60, 0xD5, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x55, 0xFB, 0xD1, 0x60, + 0xE0, 0x78, 0xFF, 0xFF, 0x01, 0x63, 0x32, 0x40, 0x08, 0x2A, 0x0F, 0x00, 0x55, 0xFD, 0xD1, 0x60, + 0xE0, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x0A, 0xF2, 0x0E, 0x63, 0x01, 0xA4, 0x0A, 0xFA, + 0x0B, 0xFC, 0x43, 0x59, 0xD4, 0x60, 0x93, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x0A, 0xF2, + 0x0D, 0x63, 0x01, 0xA4, 0x0A, 0xFA, 0x0B, 0xFC, 0x43, 0x59, 0xD4, 0x60, 0x93, 0x78, 0xFF, 0xFF, + 0x88, 0xF5, 0x00, 0xF2, 0x26, 0x46, 0x00, 0xA0, 0x2E, 0xF0, 0x37, 0x03, 0x66, 0x41, 0x12, 0x60, + 0xCE, 0x65, 0x64, 0x47, 0x00, 0x7F, 0x88, 0xF1, 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, + 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, + 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, + 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, + 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, 0x87, 0xF1, 0x14, 0x60, 0xCE, 0x61, + 0xA1, 0xD3, 0xDA, 0x81, 0xD0, 0x80, 0xDC, 0x9C, 0x05, 0x05, 0xA1, 0xD3, 0x4A, 0xD9, 0xA0, 0xDD, + 0xDA, 0x9C, 0xA1, 0xD9, 0xD3, 0x60, 0x2D, 0x78, 0xFF, 0xFF, 0x14, 0x60, 0xCE, 0x64, 0xA0, 0xD3, + 0xFF, 0xFF, 0x62, 0x18, 0x14, 0x60, 0xCE, 0x64, 0x04, 0xA5, 0xA0, 0xD1, 0x72, 0x44, 0xFF, 0xB4, + 0x64, 0x40, 0xE0, 0x22, 0x1F, 0xB4, 0x64, 0x40, 0xF8, 0x22, 0x07, 0xB4, 0x02, 0x00, 0x03, 0x04, + 0xD0, 0x84, 0xD0, 0x80, 0xFC, 0x01, 0xE0, 0x84, 0x44, 0xD3, 0xFF, 0xFF, 0x60, 0x43, 0x66, 0x41, + 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, + 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, + 0x00, 0xF8, 0x88, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, + 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, + 0x61, 0x46, 0x2E, 0xF0, 0x66, 0x41, 0x12, 0x60, 0xCE, 0x65, 0x64, 0x47, 0x00, 0x7F, 0x88, 0xF1, + 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, + 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, + 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, + 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, + 0x61, 0x46, 0xD3, 0x60, 0x2D, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x02, 0x61, 0xB3, 0x60, 0x58, 0x4D, + 0x77, 0x78, 0xFF, 0xFF, 0x87, 0xF1, 0x72, 0x44, 0xFF, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x04, + 0xD0, 0x84, 0xFB, 0x01, 0xE0, 0x83, 0x88, 0xF3, 0x02, 0xA3, 0x43, 0x93, 0x66, 0x44, 0x00, 0xA8, + 0x56, 0xFD, 0x37, 0x03, 0x00, 0x64, 0x2B, 0xFA, 0x00, 0x60, 0xC0, 0x64, 0x2A, 0xFA, 0x66, 0x45, + 0x63, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x85, 0xF2, 0x65, 0x46, 0x2C, 0xFA, 0x2D, 0xF8, 0xAE, 0xFA, + 0xCB, 0xF3, 0x2F, 0xFA, 0x32, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0x33, 0xFA, 0xCD, 0xF3, 0x31, 0xFA, + 0x34, 0xFA, 0xAC, 0xF1, 0x19, 0xF8, 0xFF, 0x67, 0x0E, 0xFA, 0x66, 0x45, 0x63, 0x46, 0x0E, 0xF2, + 0x65, 0x46, 0x02, 0x63, 0x00, 0x7E, 0x13, 0xFA, 0x3F, 0xFC, 0x00, 0x64, 0x3E, 0xFA, 0x88, 0xF3, + 0x07, 0xFA, 0x66, 0x41, 0x00, 0xF4, 0x05, 0x64, 0x09, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, + 0x8E, 0x64, 0xA2, 0xDB, 0x61, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xC1, 0xFE, 0x56, 0xF3, 0xA3, 0xFF, 0x60, 0x43, 0xE4, 0x60, 0x58, 0x4E, 0x9D, 0x78, 0xFF, 0xFF, + 0x56, 0xF3, 0xFF, 0xFF, 0x40, 0x58, 0x03, 0x65, 0xE2, 0x60, 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, + 0x56, 0xF3, 0x26, 0x46, 0x60, 0x43, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, + 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0x88, 0xF3, 0x63, 0x45, 0x60, 0x46, + 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, + 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x2E, 0xF0, 0x66, 0x41, 0x12, 0x60, + 0xCE, 0x65, 0x64, 0x47, 0x00, 0x7F, 0x88, 0xF1, 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, + 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, + 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, + 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, + 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, 0x2C, 0xF2, 0x2D, 0xF0, 0xAE, 0xF2, + 0x66, 0x45, 0x63, 0x46, 0x03, 0xFA, 0x04, 0xF8, 0x55, 0xF3, 0x85, 0xFA, 0xFF, 0xA0, 0x65, 0x46, + 0x03, 0x03, 0xD4, 0x60, 0xD6, 0x78, 0xFF, 0xFF, 0x95, 0xF3, 0x66, 0x45, 0x63, 0x46, 0x1B, 0xFA, + 0x65, 0x46, 0xBA, 0x65, 0x60, 0x44, 0xC4, 0x85, 0x01, 0x60, 0xFE, 0x61, 0x00, 0x64, 0x80, 0x63, + 0xC7, 0x85, 0x94, 0x84, 0x59, 0xDB, 0xFC, 0x1F, 0x00, 0x60, 0x88, 0x64, 0x3F, 0xFA, 0x00, 0xF4, + 0x02, 0x64, 0x0A, 0xFA, 0x00, 0x64, 0x0B, 0xFA, 0x80, 0x7F, 0x10, 0x7E, 0x0C, 0xFA, 0x1A, 0x65, + 0x80, 0x61, 0x02, 0x60, 0x00, 0x63, 0x0F, 0x4E, 0xF2, 0x60, 0x58, 0x4F, 0x4A, 0x78, 0xFF, 0xFF, + 0x0E, 0x4F, 0xD4, 0x60, 0xA7, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x23, 0xF0, 0x00, 0x60, 0x02, 0x64, + 0xA0, 0x80, 0x00, 0xF4, 0x03, 0x03, 0xD4, 0x60, 0x50, 0x78, 0xFF, 0xFF, 0x09, 0xF2, 0xFF, 0xFF, + 0xFF, 0xA0, 0x00, 0xA0, 0x0C, 0x03, 0x03, 0x03, 0xD3, 0x60, 0xCC, 0x78, 0xFF, 0xFF, 0x0A, 0xF2, + 0x26, 0x46, 0xFF, 0xA0, 0x87, 0xF4, 0x10, 0x02, 0xD4, 0x60, 0xD6, 0x78, 0xFF, 0xFF, 0x0A, 0xF2, + 0xFF, 0xFF, 0xFF, 0xA0, 0xFD, 0xA0, 0x02, 0x03, 0x04, 0x03, 0x06, 0x00, 0xD4, 0x60, 0x0C, 0x78, + 0xFF, 0xFF, 0xD4, 0x60, 0x17, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x87, 0xF4, 0x66, 0x41, 0x63, 0x46, + 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x12, 0x60, + 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, + 0x88, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, + 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, + 0x14, 0x60, 0xD0, 0x62, 0xA2, 0xD3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, + 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, + 0xA1, 0xDB, 0x14, 0x60, 0xD0, 0x62, 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, + 0xA2, 0xDB, 0xD1, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x87, 0xF4, 0x66, 0x41, 0x63, 0x46, + 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x12, 0x60, + 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, + 0x88, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, + 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, + 0x14, 0x60, 0xD0, 0x62, 0xA2, 0xD3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, + 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, + 0xA1, 0xDB, 0x14, 0x60, 0xD0, 0x62, 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, + 0xA2, 0xDB, 0xD1, 0x60, 0xD5, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x32, 0x44, 0x08, 0xB0, 0x87, 0xF4, + 0x03, 0x02, 0xD1, 0x60, 0xD5, 0x78, 0xFF, 0xFF, 0xD3, 0x60, 0x3C, 0x78, 0xFF, 0xFF, 0x32, 0x44, + 0x26, 0x46, 0x08, 0xB0, 0x07, 0xF2, 0x03, 0x02, 0xD1, 0x60, 0xD5, 0x78, 0xFF, 0xFF, 0x60, 0x46, + 0x1B, 0xF2, 0x26, 0x46, 0xBA, 0x65, 0x60, 0x44, 0xC4, 0x85, 0x01, 0x60, 0xFE, 0x61, 0x00, 0x64, + 0x80, 0x63, 0xC7, 0x85, 0x94, 0x84, 0x59, 0xDB, 0xFC, 0x1F, 0x00, 0xF4, 0x01, 0x60, 0xFE, 0x61, + 0x7E, 0x65, 0x18, 0x63, 0x5B, 0xD2, 0x59, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, 0xD7, 0x80, 0x18, 0x02, + 0xF9, 0x02, 0x00, 0xF4, 0x02, 0x63, 0x0E, 0x65, 0x5B, 0xD2, 0x59, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, + 0xD7, 0x80, 0x0E, 0x02, 0xF9, 0x02, 0x26, 0x46, 0x07, 0xF4, 0x06, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, + 0x06, 0xFA, 0x26, 0x46, 0x00, 0xF4, 0x04, 0x64, 0x0A, 0xFA, 0x00, 0x64, 0x0B, 0xFA, 0x57, 0x00, + 0x26, 0x46, 0x87, 0xF4, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, + 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0x88, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, + 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, + 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x14, 0x60, 0xD0, 0x62, 0xA2, 0xD3, 0xDA, 0x81, + 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0xC9, 0x81, + 0xC8, 0x85, 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, 0x14, 0x60, 0xD0, 0x62, 0x65, 0x44, + 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, 0x00, 0xF4, 0x04, 0x64, 0x0A, 0xFA, + 0x0F, 0x64, 0x0B, 0xFA, 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x41, 0x58, 0x26, 0x46, 0x2C, 0xF2, + 0xA1, 0xDB, 0x2D, 0xF2, 0x59, 0xDB, 0x2E, 0xF2, 0x59, 0xDB, 0x03, 0x65, 0xE2, 0x60, 0x58, 0x4E, + 0x5B, 0x78, 0xFF, 0xFF, 0x03, 0x65, 0xE2, 0x60, 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0x88, 0xF3, 0x07, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x26, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, + 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0xF4, 0x0A, 0xF2, 0x09, 0xF2, 0xFF, 0xA0, 0x00, 0xA0, 0x06, 0x02, + 0xFF, 0xA0, 0x07, 0x03, 0x09, 0x03, 0xD3, 0x60, 0xCC, 0x78, 0xFF, 0xFF, 0xD3, 0x60, 0x8C, 0x78, + 0xFF, 0xFF, 0xD4, 0x60, 0xDB, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x07, 0xF4, 0x06, 0xF2, 0x66, 0x43, + 0x00, 0x7E, 0x06, 0xFA, 0x26, 0x46, 0xD3, 0x60, 0x3C, 0x78, 0xFF, 0xFF, 0x63, 0x46, 0x06, 0xF2, + 0xFF, 0xFF, 0x01, 0x7E, 0x06, 0xFA, 0x26, 0x46, 0x88, 0xF3, 0x07, 0xFA, 0x00, 0xF4, 0x02, 0x64, + 0x0A, 0xFA, 0x00, 0x64, 0x0B, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, + 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, + 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x16, 0x60, 0xAC, 0x7C, 0x2A, 0xF2, 0xA4, 0xDB, 0x22, 0x60, + 0x2A, 0x63, 0xFF, 0xB4, 0x01, 0x61, 0x00, 0x60, 0x10, 0x7C, 0xA3, 0xDB, 0x60, 0x40, 0x00, 0x36, + 0x03, 0x00, 0x02, 0x61, 0x00, 0x60, 0x30, 0x7C, 0x41, 0x47, 0x2A, 0xF8, 0x2F, 0xF2, 0x2C, 0xFA, + 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, + 0xCD, 0xF3, 0x31, 0xFA, 0x67, 0xF3, 0x32, 0xFA, 0x68, 0xF3, 0x33, 0xFA, 0x69, 0xF3, 0x34, 0xFA, + 0xAC, 0xF1, 0x19, 0xF8, 0x00, 0x7C, 0x3E, 0xF8, 0x1C, 0xF0, 0x13, 0xF8, 0x07, 0xF2, 0x88, 0xF1, + 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0xD9, 0x60, 0xA3, 0x78, 0xFF, 0xFF, 0x40, 0x4B, + 0xAB, 0x46, 0x06, 0xF2, 0xAB, 0x46, 0x00, 0xF4, 0x01, 0xB0, 0xFF, 0xFF, 0x03, 0x02, 0xD9, 0x60, + 0xA3, 0x78, 0xFF, 0xFF, 0x22, 0x60, 0x2C, 0x63, 0x09, 0xF2, 0xBD, 0xDB, 0x43, 0x44, 0x10, 0xB0, + 0x80, 0x60, 0x00, 0x63, 0x0D, 0x03, 0x1F, 0x60, 0x92, 0x62, 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x44, + 0xFE, 0x26, 0x08, 0x00, 0x32, 0x40, 0x08, 0x26, 0x06, 0x00, 0xDA, 0x60, 0x02, 0x78, 0xFF, 0xFF, + 0x32, 0x40, 0x10, 0x2A, 0x00, 0x63, 0xAB, 0x46, 0x06, 0xF0, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, + 0x63, 0x45, 0xB4, 0x84, 0x06, 0xFA, 0xAB, 0x46, 0x0A, 0xF0, 0x56, 0xF9, 0x24, 0x43, 0xBD, 0xD9, + 0x43, 0x44, 0x01, 0x63, 0x32, 0x40, 0x10, 0x26, 0x10, 0xBB, 0x1F, 0x60, 0x92, 0x62, 0xA2, 0xD3, + 0xFF, 0xFF, 0x60, 0x40, 0xFE, 0x26, 0x10, 0xBB, 0x09, 0xFC, 0x27, 0x44, 0xFE, 0xA0, 0xFF, 0xFF, + 0x03, 0x03, 0xD5, 0x60, 0xFE, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0xA2, 0x64, 0x24, 0x43, 0x0B, 0xF0, + 0xA0, 0xD9, 0xBD, 0xD9, 0x0C, 0xF0, 0x58, 0xD9, 0xBD, 0xD9, 0x0D, 0xF0, 0x58, 0xD9, 0xBD, 0xD9, + 0x43, 0x44, 0x1C, 0x65, 0x2D, 0x61, 0x02, 0x60, 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x64, 0x44, + 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, + 0xF4, 0x02, 0x02, 0x60, 0x02, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0xE0, 0x84, 0x04, 0xA5, 0xC5, 0x81, + 0xA1, 0xD3, 0x00, 0x65, 0x60, 0x43, 0x59, 0xD3, 0xFF, 0xFF, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, + 0x01, 0x64, 0x15, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x02, 0x64, 0x11, 0x00, 0x0A, 0x3A, 0x02, 0x00, + 0x04, 0x64, 0x0D, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x08, 0x64, 0x09, 0x00, 0x10, 0x3A, 0x02, 0x00, + 0x10, 0x64, 0x05, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x20, 0x64, 0x01, 0x00, 0x00, 0x64, 0xCF, 0x83, + 0xB4, 0x85, 0xE1, 0x02, 0x65, 0x44, 0x60, 0xFB, 0xB8, 0xF3, 0x2B, 0x45, 0x66, 0x41, 0x65, 0x46, + 0x8C, 0xFA, 0x60, 0x40, 0x01, 0x36, 0x06, 0x00, 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, + 0x05, 0x3A, 0x02, 0x00, 0x00, 0x64, 0x01, 0x00, 0x01, 0x64, 0x6F, 0xFA, 0x5F, 0xF3, 0x60, 0xF1, + 0xFF, 0xFF, 0xA0, 0x84, 0x65, 0x43, 0x02, 0x02, 0x5F, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, + 0xAE, 0x65, 0xB8, 0xF3, 0xFF, 0xFF, 0xE0, 0x84, 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, + 0x04, 0x02, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x61, 0xFB, 0x6F, 0xF0, + 0x60, 0x47, 0x90, 0x84, 0x6F, 0xFA, 0x60, 0x47, 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, + 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x70, 0xF0, 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, + 0x02, 0x05, 0xDD, 0x81, 0xFB, 0x01, 0xE1, 0x81, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, + 0x66, 0x43, 0x0C, 0xF4, 0xFF, 0xFF, 0xD6, 0x60, 0x80, 0x78, 0xFF, 0xFF, 0x16, 0x65, 0x2D, 0x61, + 0x02, 0x60, 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x64, 0x44, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, + 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0xF4, 0x02, 0x02, 0x60, 0x02, 0x61, + 0xA1, 0xD3, 0xFF, 0xFF, 0xE0, 0x84, 0x04, 0xA5, 0xC5, 0x81, 0xA1, 0xD3, 0x00, 0x65, 0x60, 0x43, + 0x59, 0xD3, 0xFF, 0xFF, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, 0x01, 0x64, 0x15, 0x00, 0x04, 0x3A, + 0x02, 0x00, 0x02, 0x64, 0x11, 0x00, 0x0A, 0x3A, 0x02, 0x00, 0x04, 0x64, 0x0D, 0x00, 0x0B, 0x3A, + 0x02, 0x00, 0x08, 0x64, 0x09, 0x00, 0x10, 0x3A, 0x02, 0x00, 0x10, 0x64, 0x05, 0x00, 0x16, 0x3A, + 0x02, 0x00, 0x20, 0x64, 0x01, 0x00, 0x00, 0x64, 0xCF, 0x83, 0xB4, 0x85, 0xE1, 0x02, 0x65, 0x44, + 0x60, 0xFB, 0xB8, 0xF3, 0x2B, 0x45, 0x66, 0x41, 0x65, 0x46, 0x8C, 0xFA, 0x60, 0x40, 0x01, 0x36, + 0x06, 0x00, 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x64, + 0x01, 0x00, 0x01, 0x64, 0x6F, 0xFA, 0x5F, 0xF3, 0x60, 0xF1, 0xFF, 0xFF, 0xA0, 0x84, 0x65, 0x43, + 0x02, 0x02, 0x5F, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, 0xAE, 0x65, 0xB8, 0xF3, 0xFF, 0xFF, + 0xE0, 0x84, 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x04, 0x02, 0xE8, 0x84, 0xA4, 0x80, + 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x61, 0xFB, 0x6F, 0xF0, 0x60, 0x47, 0x90, 0x84, 0x6F, 0xFA, + 0x60, 0x47, 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, + 0x70, 0xF0, 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, 0x02, 0x05, 0xDD, 0x81, 0xFB, 0x01, + 0xE1, 0x81, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x66, 0x43, 0x0C, 0xF4, 0xFF, 0xFF, + 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x16, 0x65, 0x27, 0x40, 0x02, 0x3A, 0x03, 0x00, 0x1C, 0x65, + 0xF6, 0xA4, 0x01, 0x00, 0xFC, 0xA4, 0x24, 0x43, 0x22, 0x60, 0x82, 0x61, 0x5D, 0x91, 0x51, 0x90, + 0xFF, 0xFF, 0x04, 0x28, 0x60, 0x41, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, + 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, + 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x22, 0x60, 0x28, 0x7C, 0x03, 0x1E, + 0x60, 0xFE, 0xBD, 0xDF, 0x20, 0xFE, 0x22, 0x60, 0x2C, 0x64, 0x53, 0x93, 0xA4, 0xDD, 0x26, 0x46, + 0x00, 0xF4, 0x1F, 0x60, 0x90, 0x64, 0xA0, 0xD3, 0x00, 0x63, 0x00, 0xB8, 0x0A, 0xFC, 0x03, 0x02, + 0xD7, 0x60, 0x14, 0x78, 0xFF, 0xFF, 0x0B, 0xF2, 0x27, 0x40, 0x02, 0x3A, 0x02, 0x00, 0x0E, 0xF2, + 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x3A, 0x26, 0x00, 0x60, 0x41, 0x00, 0x36, 0x23, 0x00, 0xE0, 0xA0, + 0xDA, 0x85, 0x20, 0x07, 0x1F, 0x60, 0x1E, 0x63, 0xA3, 0xD1, 0x65, 0x42, 0xD1, 0x80, 0x1F, 0x60, + 0x20, 0x63, 0x18, 0x02, 0x50, 0xFE, 0x61, 0x40, 0xFE, 0x22, 0x08, 0x00, 0x62, 0x45, 0xBD, 0xD3, + 0xA5, 0xD0, 0xDA, 0x82, 0xD0, 0x80, 0xC9, 0x81, 0xF6, 0x0C, 0x0C, 0x00, 0x61, 0x40, 0x00, 0x36, + 0x33, 0x00, 0x62, 0x45, 0xA3, 0xD3, 0xA5, 0xD0, 0xFF, 0xFF, 0x90, 0x80, 0xFF, 0x26, 0x02, 0x00, + 0xDE, 0x82, 0x2A, 0x00, 0x0C, 0x63, 0x0A, 0xFC, 0x00, 0x64, 0x09, 0xFA, 0x0B, 0xFA, 0x01, 0x7E, + 0x0C, 0xFA, 0x26, 0x46, 0x08, 0x64, 0x3F, 0xFA, 0x07, 0xF2, 0x88, 0xF1, 0x40, 0x58, 0x07, 0xF8, + 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xDA, 0x60, 0x1E, 0x78, 0xFF, 0xFF, 0x20, 0xFE, + 0x21, 0x60, 0xE2, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x22, 0xB0, 0xFF, 0xFF, 0x03, 0x03, 0xD8, 0x60, + 0x9F, 0x78, 0xFF, 0xFF, 0x01, 0x63, 0xD7, 0x01, 0x1F, 0x60, 0x92, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, + 0xFF, 0xA4, 0xFF, 0xFF, 0x0C, 0x20, 0x0D, 0x00, 0xD8, 0x60, 0x9F, 0x78, 0xFF, 0xFF, 0x20, 0xFE, + 0x28, 0x46, 0x2A, 0x41, 0xFF, 0xB1, 0x60, 0xFE, 0x82, 0x64, 0xA1, 0xDA, 0xFF, 0xFF, 0x20, 0xFE, + 0x15, 0x00, 0x21, 0x60, 0xEE, 0x61, 0xA1, 0xDF, 0xD9, 0x81, 0xA1, 0xDF, 0xD9, 0x81, 0xA1, 0xDF, + 0x04, 0xA1, 0xA1, 0xDF, 0xD9, 0x81, 0xA1, 0xDF, 0xD9, 0x81, 0xA1, 0xDF, 0xD9, 0x81, 0xA1, 0xDF, + 0x2B, 0x46, 0x37, 0xF2, 0x7F, 0x60, 0xCF, 0x65, 0xA4, 0x84, 0xA2, 0xDA, 0x26, 0x46, 0x3F, 0xF2, + 0x00, 0xF4, 0x27, 0x40, 0x02, 0x3A, 0x40, 0x00, 0x60, 0x43, 0xF6, 0xA3, 0x00, 0x60, 0x1B, 0x61, + 0x00, 0x60, 0xDD, 0x65, 0x60, 0xFE, 0x81, 0xA1, 0x7F, 0xA1, 0x02, 0x06, 0x00, 0xF4, 0x03, 0x61, + 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, 0xD4, 0x80, 0x2D, 0x03, 0x17, 0x03, 0xCF, 0x83, 0x61, 0x44, + 0x80, 0xA0, 0x28, 0x03, 0x02, 0x02, 0x00, 0xF4, 0x03, 0x61, 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, + 0x81, 0xA1, 0x20, 0x03, 0x05, 0x07, 0x7F, 0xA1, 0xCC, 0x84, 0xDD, 0x81, 0xE4, 0x03, 0xF7, 0x01, + 0x00, 0xF4, 0x00, 0xB8, 0x04, 0x61, 0xE4, 0x03, 0xF2, 0x01, 0x01, 0x60, 0xFF, 0x63, 0x46, 0x48, + 0x41, 0x4A, 0xDD, 0x81, 0xA1, 0xD0, 0xDF, 0x83, 0xA3, 0xD9, 0x64, 0x44, 0xDD, 0x81, 0xA1, 0xD0, + 0xDF, 0x83, 0xA3, 0xD9, 0xCC, 0x84, 0x81, 0xA1, 0x05, 0x03, 0x7F, 0xA1, 0xF7, 0x04, 0x00, 0xF4, + 0x03, 0x61, 0xF4, 0x01, 0x20, 0xFE, 0x3F, 0x00, 0x60, 0x43, 0xFC, 0xA3, 0x00, 0x60, 0x15, 0x61, + 0x00, 0x60, 0xDD, 0x65, 0x60, 0xFE, 0x81, 0xA1, 0x7F, 0xA1, 0x02, 0x06, 0x00, 0xF4, 0x03, 0x61, + 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, 0xD4, 0x80, 0x2D, 0x03, 0x17, 0x03, 0xCF, 0x83, 0x61, 0x44, + 0x80, 0xA0, 0x28, 0x03, 0x02, 0x02, 0x00, 0xF4, 0x03, 0x61, 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, + 0x81, 0xA1, 0x20, 0x03, 0x05, 0x07, 0x7F, 0xA1, 0xCC, 0x84, 0xDD, 0x81, 0xE4, 0x03, 0xF7, 0x01, + 0x00, 0xF4, 0x00, 0xB8, 0x04, 0x61, 0xE4, 0x03, 0xF2, 0x01, 0x01, 0x60, 0xFF, 0x63, 0x46, 0x48, + 0x41, 0x4A, 0xDD, 0x81, 0xA1, 0xD0, 0xDF, 0x83, 0xA3, 0xD9, 0x64, 0x44, 0xDD, 0x81, 0xA1, 0xD0, + 0xDF, 0x83, 0xA3, 0xD9, 0xCC, 0x84, 0x81, 0xA1, 0x05, 0x03, 0x7F, 0xA1, 0xF7, 0x04, 0x00, 0xF4, + 0x03, 0x61, 0xF4, 0x01, 0x20, 0xFE, 0x00, 0xBB, 0x02, 0x60, 0x00, 0x61, 0x08, 0x24, 0xD7, 0x00, + 0x60, 0xFE, 0xA1, 0xD3, 0xFF, 0xFF, 0xFA, 0xA4, 0xFF, 0xFF, 0x01, 0x05, 0x50, 0x01, 0xDD, 0x81, + 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x3A, 0x4A, 0x01, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, + 0x64, 0x40, 0x50, 0x3A, 0x44, 0x01, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0xF2, 0x3A, + 0x3E, 0x01, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x3A, 0x20, 0x01, 0xDD, 0x81, + 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x3A, 0x1A, 0x01, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, + 0x64, 0x40, 0x00, 0x3A, 0x14, 0x01, 0x60, 0x5C, 0x00, 0x36, 0x30, 0x00, 0x00, 0x64, 0xD8, 0x60, + 0x58, 0x4E, 0xC4, 0x78, 0xFF, 0xFF, 0x21, 0x60, 0xF6, 0x62, 0xA2, 0xDB, 0x64, 0x40, 0x00, 0x36, + 0x2B, 0x00, 0xDD, 0x81, 0xA1, 0xD3, 0xDD, 0x81, 0xD8, 0x60, 0x58, 0x4E, 0xC4, 0x78, 0xFF, 0xFF, + 0x21, 0x60, 0xF8, 0x62, 0xA2, 0xDB, 0x64, 0x40, 0x00, 0x36, 0x24, 0x00, 0xDD, 0x81, 0xA1, 0xD3, + 0xDD, 0x81, 0xD8, 0x60, 0x58, 0x4E, 0xC4, 0x78, 0xFF, 0xFF, 0x21, 0x60, 0xFA, 0x62, 0xA2, 0xDB, + 0x64, 0x40, 0x00, 0x36, 0x1D, 0x00, 0xDD, 0x81, 0xA1, 0xD1, 0x21, 0x60, 0xFC, 0x62, 0xA2, 0xD9, + 0xDD, 0x81, 0xA1, 0xD1, 0x21, 0x60, 0xFD, 0x62, 0xA2, 0xD9, 0x19, 0x00, 0x20, 0xFE, 0x21, 0x60, + 0xF6, 0x62, 0x00, 0x60, 0x04, 0x64, 0xA2, 0xDB, 0x20, 0xFE, 0x21, 0x60, 0xF8, 0x62, 0x00, 0x60, + 0x04, 0x64, 0xA2, 0xDB, 0x20, 0xFE, 0x21, 0x60, 0xFA, 0x62, 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, + 0x20, 0xFE, 0x21, 0x60, 0xFC, 0x62, 0x00, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x00, 0x20, 0xFE, + 0x21, 0x60, 0xE2, 0x62, 0xA2, 0xD1, 0x21, 0x60, 0xF6, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0x84, + 0xFF, 0xFF, 0x10, 0x26, 0x09, 0x00, 0x04, 0x26, 0x09, 0x00, 0x20, 0x26, 0x09, 0x00, 0x02, 0x26, + 0x09, 0x00, 0xD7, 0x60, 0x07, 0x78, 0xFF, 0xFF, 0x10, 0x7C, 0x05, 0x00, 0x04, 0x7C, 0x03, 0x00, + 0x20, 0x7C, 0x01, 0x00, 0x02, 0x7C, 0x21, 0x60, 0xEE, 0x61, 0xA1, 0xD9, 0x21, 0x60, 0xE4, 0x61, + 0xA1, 0xD1, 0x21, 0x60, 0xF8, 0x61, 0xA1, 0xD3, 0x21, 0x60, 0xEE, 0x61, 0xA0, 0x84, 0xA1, 0xD1, + 0xFF, 0xFF, 0x10, 0x26, 0x07, 0x00, 0x04, 0x26, 0x07, 0x00, 0x01, 0x26, 0x0D, 0x00, 0xD7, 0x60, + 0x07, 0x78, 0xFF, 0xFF, 0x10, 0x7C, 0x09, 0x00, 0x64, 0x40, 0x10, 0x22, 0x03, 0x00, 0xD7, 0x60, + 0x07, 0x78, 0xFF, 0xFF, 0x04, 0x7C, 0x01, 0x00, 0x01, 0x7C, 0x21, 0x60, 0xF0, 0x61, 0xA1, 0xD9, + 0x21, 0x60, 0xE6, 0x61, 0xA1, 0xD1, 0x21, 0x60, 0xFA, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0xA0, 0x84, + 0x02, 0x26, 0x07, 0x00, 0x04, 0x26, 0x07, 0x00, 0x01, 0x26, 0x07, 0x00, 0xD7, 0x60, 0x07, 0x78, + 0xFF, 0xFF, 0x02, 0x7C, 0x03, 0x00, 0x04, 0x7C, 0x01, 0x00, 0x20, 0x7C, 0x21, 0x60, 0xF2, 0x61, + 0xA1, 0xD9, 0x21, 0x60, 0xFC, 0x61, 0xA1, 0xD1, 0x21, 0x60, 0xF4, 0x61, 0xA1, 0xD9, 0x21, 0x60, + 0xF2, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x21, 0x60, 0xF0, 0x61, 0xA1, 0xD1, 0xFF, 0xFF, + 0xB0, 0x84, 0x1F, 0x60, 0x92, 0x62, 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x22, 0xBC, + 0xAB, 0x46, 0x36, 0xFA, 0xAB, 0x46, 0x21, 0x60, 0xEE, 0x61, 0xA1, 0xD3, 0x1F, 0x60, 0x92, 0x62, + 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x22, 0xBC, 0x88, 0xF1, 0x66, 0x41, 0x64, 0x46, + 0x36, 0xFA, 0xFF, 0xFF, 0x61, 0x46, 0x50, 0x00, 0x21, 0x60, 0xFE, 0x62, 0xA2, 0xDB, 0xE0, 0x84, + 0xE0, 0x84, 0x03, 0x02, 0x01, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x02, 0xA5, 0x64, 0x44, 0xD4, 0x9C, + 0x22, 0x60, 0x00, 0x62, 0xA2, 0xD9, 0x22, 0x60, 0x02, 0x62, 0xA2, 0xDF, 0xDD, 0x81, 0xA1, 0xD1, + 0x00, 0x65, 0x64, 0x40, 0x00, 0x3A, 0x01, 0x65, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, + 0x50, 0x3A, 0x01, 0x65, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0xF2, 0x3A, 0x01, 0x65, + 0xDD, 0x81, 0xA1, 0xD1, 0x65, 0x40, 0x00, 0x3A, 0x18, 0x00, 0x00, 0x60, 0x00, 0x65, 0x64, 0x40, + 0x00, 0x36, 0x01, 0x65, 0x64, 0x40, 0x01, 0x36, 0x02, 0x65, 0x64, 0x40, 0x02, 0x36, 0x04, 0x65, + 0x64, 0x40, 0x04, 0x36, 0x10, 0x65, 0x64, 0x40, 0x05, 0x36, 0x20, 0x65, 0x65, 0x5C, 0x22, 0x60, + 0x02, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xB0, 0x84, 0xA2, 0xDB, 0x21, 0x60, 0xFE, 0x62, 0xA2, 0xD3, + 0xFF, 0xFF, 0xFF, 0xA4, 0xA2, 0xDB, 0xCA, 0x02, 0x22, 0x60, 0x02, 0x62, 0xA2, 0xD3, 0x22, 0x60, + 0x00, 0x62, 0xA2, 0xD1, 0x2E, 0x58, 0xFF, 0xFF, 0xAB, 0x46, 0x82, 0xF0, 0xC0, 0x67, 0xB4, 0x84, + 0xAB, 0x46, 0x0B, 0xFA, 0x1F, 0x60, 0xA0, 0x64, 0xA0, 0xD1, 0x22, 0x60, 0xD4, 0x7C, 0x04, 0x1B, + 0xFF, 0x60, 0xFF, 0x63, 0xA4, 0xDD, 0x29, 0x00, 0x23, 0x60, 0x3C, 0x63, 0xA4, 0xDD, 0xDB, 0x83, + 0x60, 0xFE, 0x00, 0x64, 0xBD, 0xDB, 0x60, 0x64, 0xBD, 0xDB, 0x1D, 0x64, 0xBD, 0xDB, 0xC3, 0xF3, + 0xBD, 0xDB, 0xFF, 0xFF, 0x20, 0xFE, 0x01, 0x60, 0x78, 0x64, 0x06, 0x61, 0x58, 0xD1, 0xFF, 0xFF, + 0x60, 0xFE, 0xBD, 0xD9, 0x20, 0xFE, 0xCD, 0x81, 0x61, 0x40, 0x08, 0x28, 0xF7, 0x01, 0xB7, 0xF1, + 0xFF, 0xFF, 0x64, 0x47, 0x60, 0xFE, 0xBD, 0xD9, 0xBD, 0xDB, 0x20, 0xFE, 0x1F, 0x60, 0x9C, 0x64, + 0xA0, 0xD1, 0x60, 0xFE, 0xBD, 0xD9, 0xFF, 0xFF, 0x20, 0xFE, 0x22, 0x60, 0xD2, 0x64, 0x40, 0x48, + 0x18, 0x61, 0x26, 0x46, 0x00, 0xF4, 0xFF, 0x60, 0xF2, 0x64, 0xE1, 0x60, 0x58, 0x4D, 0xE5, 0x78, + 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xFC, 0x2B, 0x46, 0x56, 0xF1, 0x16, 0x60, 0xAC, 0x61, 0x1B, 0xF8, + 0xA1, 0xD1, 0x10, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x06, 0xF2, 0x0C, 0x03, 0x10, 0xBC, 0x06, 0xFA, + 0x87, 0xF3, 0x00, 0x60, 0xE2, 0x62, 0xA2, 0xD3, 0x60, 0x45, 0xD4, 0x80, 0xDC, 0x84, 0x07, 0x07, + 0xA2, 0xDB, 0x05, 0x00, 0x10, 0xB5, 0xFF, 0xFF, 0x02, 0x03, 0xD4, 0x84, 0x06, 0xFA, 0x07, 0xF2, + 0x66, 0x45, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x02, 0xB0, 0xFF, 0xFF, 0x12, 0x03, 0x26, 0x46, + 0x88, 0xF3, 0x07, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x26, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, + 0x4C, 0x00, 0x26, 0x46, 0x88, 0xF3, 0x07, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, + 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, + 0x00, 0x66, 0x46, 0x46, 0x1A, 0x00, 0x00, 0x60, 0xC0, 0x64, 0x2A, 0xFA, 0x02, 0x64, 0x3F, 0xFA, + 0x88, 0xF3, 0x07, 0xFA, 0x00, 0xF4, 0x09, 0x64, 0x09, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, + 0x8E, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x2B, 0x43, 0x14, 0x60, 0xD0, 0x62, + 0xA2, 0xD3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, 0xD9, 0x81, + 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, 0x14, 0x60, + 0xD0, 0x62, 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, 0xAB, 0x46, + 0x06, 0xF2, 0xFF, 0xFF, 0x02, 0xBC, 0x06, 0xFA, 0xAB, 0x46, 0xAB, 0x46, 0x0F, 0x60, 0xFF, 0x64, + 0x02, 0xF0, 0x72, 0xF1, 0xA0, 0x84, 0xD0, 0x80, 0x02, 0xFA, 0xAB, 0x46, 0x01, 0x06, 0x72, 0xFB, + 0x27, 0x41, 0x01, 0xB1, 0xFF, 0xFF, 0x08, 0x03, 0x2B, 0x46, 0x0B, 0x58, 0x01, 0x65, 0xE2, 0x60, + 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x0A, 0x00, 0x2B, 0x46, 0x0B, 0x58, 0x16, 0x60, 0xA2, 0x64, + 0x40, 0x59, 0x02, 0x65, 0xE2, 0x60, 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, + 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x00, 0x64, 0x09, 0xFA, 0x0B, 0xFA, 0x01, 0x7E, + 0x0C, 0xFA, 0x0A, 0x64, 0x0A, 0xFA, 0x26, 0x46, 0x08, 0x64, 0x3F, 0xFA, 0x07, 0xF2, 0x88, 0xF1, + 0x40, 0x58, 0x07, 0xF8, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x26, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xFF, 0x60, 0xFD, 0x65, + 0x38, 0x46, 0x06, 0xF2, 0xFF, 0xFF, 0xA4, 0x83, 0x06, 0xFC, 0x02, 0xB0, 0x26, 0x46, 0x1C, 0x03, + 0x38, 0x43, 0x87, 0xF1, 0x14, 0x60, 0xCE, 0x61, 0xA1, 0xD3, 0xDA, 0x81, 0xD0, 0x80, 0xDC, 0x9C, + 0x05, 0x05, 0xA1, 0xD3, 0x4A, 0xD9, 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, 0x02, 0x60, 0x00, 0x61, + 0x2C, 0xF2, 0xA1, 0xDB, 0x2D, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x2E, 0xF2, 0x59, 0xDB, 0x03, 0x65, + 0xE2, 0x60, 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, + 0x07, 0xF2, 0x88, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, + 0x40, 0x47, 0x07, 0xF2, 0x66, 0x45, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x02, 0xB0, 0xFF, 0xFF, + 0x1B, 0x02, 0x27, 0x43, 0x14, 0x60, 0xD0, 0x62, 0xA2, 0xD3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, + 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, + 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, 0x14, 0x60, 0xD0, 0x62, 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, + 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, 0x0C, 0x00, 0x27, 0x44, 0x40, 0x58, 0x03, 0x65, 0xE2, 0x60, + 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x27, 0x43, 0xE4, 0x60, 0x58, 0x4E, 0x9D, 0x78, 0xFF, 0xFF, + 0x26, 0x46, 0x87, 0xF4, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, + 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0x88, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, + 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, + 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x07, 0xF2, 0x88, 0xF1, + 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, 0x40, 0x47, 0x07, 0xF2, + 0x66, 0x45, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x02, 0xB0, 0xFF, 0xFF, 0x02, 0x02, 0x2F, 0x58, + 0xFF, 0xFF, 0x27, 0x46, 0x06, 0xF0, 0xFF, 0x60, 0xED, 0x64, 0xA0, 0x84, 0x06, 0xFA, 0x27, 0x43, + 0x87, 0xF1, 0x14, 0x60, 0xCE, 0x61, 0xA1, 0xD3, 0xDA, 0x81, 0xD0, 0x80, 0xDC, 0x9C, 0x05, 0x05, + 0xA1, 0xD3, 0x4A, 0xD9, 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, 0x07, 0x58, 0x03, 0x65, 0xE2, 0x60, + 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x27, 0x43, 0xE4, 0x60, 0x58, 0x4E, 0x9D, 0x78, 0xFF, 0xFF, + 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, + 0x31, 0xF2, 0x2E, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0xCD, 0xF3, 0x31, 0xFA, + 0x67, 0xF3, 0x32, 0xFA, 0x68, 0xF3, 0x33, 0xFA, 0x69, 0xF3, 0x34, 0xFA, 0xAC, 0xF1, 0x19, 0xF8, + 0x1C, 0xF2, 0x13, 0xFA, 0x02, 0x63, 0x3F, 0xFC, 0x00, 0x64, 0x3E, 0xFA, 0x02, 0x60, 0x00, 0x61, + 0x2C, 0xF2, 0xA1, 0xDB, 0x2D, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x2E, 0xF2, 0x59, 0xDB, 0x06, 0x63, + 0x07, 0xF2, 0x88, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x0D, 0x02, 0x43, 0x59, 0x02, 0x65, + 0xE2, 0x60, 0x58, 0x4E, 0x5B, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0xC0, 0x64, 0x2A, 0xFA, 0x00, 0xF4, + 0x06, 0x64, 0x09, 0xFA, 0x15, 0x00, 0x07, 0xF2, 0x66, 0x45, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, + 0x02, 0xB0, 0xFF, 0xFF, 0x1E, 0x02, 0x07, 0x63, 0x43, 0x59, 0x01, 0x65, 0xE2, 0x60, 0x58, 0x4E, + 0x5B, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0xA0, 0x64, 0x2A, 0xFA, 0x00, 0xF4, 0x07, 0x64, 0x09, 0xFA, + 0x26, 0x46, 0x88, 0xF3, 0x07, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, + 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, + 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xFE, 0x62, 0xDB, 0x60, 0xB0, 0x64, 0xA2, 0xDB, + 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x60, 0x03, 0x64, 0xA2, 0xDB, 0xDB, 0x60, + 0x4D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xE8, 0x62, 0xA2, 0xD1, + 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x5A, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x72, 0xF3, + 0x88, 0xF5, 0xDC, 0x81, 0x66, 0x43, 0x02, 0xA3, 0x63, 0x46, 0xCD, 0x81, 0x06, 0xF2, 0xED, 0x03, + 0x60, 0x40, 0x08, 0x2A, 0xF7, 0x01, 0x0C, 0xAC, 0x06, 0xFA, 0x46, 0x49, 0x00, 0x60, 0x02, 0x61, + 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, 0xE0, 0x03, 0x25, 0x60, 0x2C, 0x61, 0xA1, 0xD3, + 0xFF, 0xFF, 0x03, 0x1B, 0x00, 0x60, 0xA0, 0x64, 0x02, 0x00, 0x00, 0x60, 0xC0, 0x64, 0x2A, 0xFA, + 0xAB, 0xFC, 0x66, 0x45, 0x29, 0x44, 0x07, 0xFA, 0x29, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x85, 0xF2, + 0x65, 0x46, 0x2C, 0xFA, 0x2D, 0xF8, 0xAE, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0x32, 0xFA, 0xCC, 0xF3, + 0x30, 0xFA, 0x33, 0xFA, 0xCD, 0xF3, 0x31, 0xFA, 0x34, 0xFA, 0xAC, 0xF1, 0x19, 0xF8, 0x18, 0x67, + 0x0E, 0xFA, 0x66, 0x45, 0x63, 0x46, 0x0E, 0xF2, 0x65, 0x46, 0x00, 0x7E, 0x13, 0xFA, 0x02, 0x63, + 0x3F, 0xFC, 0x00, 0x64, 0x3E, 0xFA, 0x66, 0x41, 0x00, 0xF4, 0x25, 0x60, 0x28, 0x62, 0xA2, 0xD3, + 0xFF, 0xFF, 0x09, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x9A, 0x64, 0xA2, 0xDB, 0x61, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, 0x9E, 0x01, 0x92, 0x01, + 0x0F, 0x60, 0xE8, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x07, 0xF0, + 0xFF, 0xFF, 0x64, 0x43, 0x14, 0x60, 0xD0, 0x62, 0xA2, 0xD3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, + 0xA1, 0xD1, 0x04, 0x03, 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0x09, 0x00, 0xA1, 0xDD, 0x14, 0x60, + 0xD0, 0x62, 0xD9, 0x84, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xA2, 0xDB, 0x66, 0x45, + 0x63, 0x46, 0x06, 0xF2, 0xFF, 0x60, 0x01, 0x7C, 0xA0, 0x9C, 0x06, 0xF8, 0x65, 0x46, 0x71, 0xF3, + 0x60, 0x40, 0x10, 0x2A, 0x03, 0x00, 0xCC, 0x84, 0x80, 0x2B, 0x71, 0xFB, 0x0F, 0x60, 0xE8, 0x62, + 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x0F, 0x60, 0xDC, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xDE, 0x62, 0x00, 0x60, 0x02, 0x64, + 0xA2, 0xDB, 0xDB, 0x60, 0xF7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x71, 0xF3, + 0x72, 0xF3, 0x00, 0xA8, 0x60, 0x88, 0x50, 0x03, 0xE0, 0x83, 0x6C, 0x03, 0xCB, 0x83, 0x88, 0xF3, + 0x73, 0xF1, 0x02, 0xA4, 0x40, 0x47, 0x64, 0x45, 0x27, 0x46, 0x72, 0xF4, 0x12, 0xF2, 0x40, 0x18, + 0xD4, 0x80, 0x02, 0x64, 0x3D, 0x07, 0x23, 0xFA, 0x2A, 0xF2, 0x0E, 0xF2, 0x0C, 0xB0, 0x02, 0xF0, + 0x0D, 0x02, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xE6, 0x01, 0x60, 0x40, 0xF0, 0x37, + 0x08, 0x00, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, 0x90, 0xF3, 0x02, 0x02, 0xDC, 0x84, + 0x90, 0xFB, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xAC, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA3, 0xFF, 0xCE, 0xFE, 0x98, 0xF1, 0x1E, 0x60, + 0xEC, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, + 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xBC, 0x01, + 0x27, 0x44, 0x02, 0xA4, 0x40, 0x47, 0xB8, 0x1F, 0x28, 0x43, 0xCB, 0x83, 0x88, 0xF3, 0x1A, 0x0E, + 0x02, 0xA4, 0x40, 0x4C, 0x43, 0x48, 0x2C, 0x46, 0x1E, 0xF2, 0x73, 0xF1, 0xAC, 0x86, 0x12, 0xF2, + 0x0C, 0x03, 0xD0, 0x80, 0xFF, 0xFF, 0x09, 0x07, 0x1B, 0x60, 0xDA, 0x64, 0x40, 0x4B, 0xF0, 0x60, + 0x58, 0x4D, 0x75, 0x78, 0xFF, 0xFF, 0x2C, 0x46, 0x9E, 0xFC, 0x2C, 0x44, 0x02, 0xA4, 0x28, 0x43, + 0x40, 0x4C, 0xE8, 0x1F, 0x7D, 0x01, 0x01, 0x63, 0x66, 0xF3, 0xAC, 0xF3, 0x00, 0xBD, 0xAC, 0x81, + 0x06, 0x03, 0x05, 0x03, 0xB5, 0x60, 0x58, 0x4D, 0xC1, 0x78, 0xFF, 0xFF, 0x60, 0x43, 0x5B, 0xFD, + 0x3E, 0x63, 0x16, 0x60, 0x60, 0x61, 0x00, 0x64, 0x59, 0xDB, 0xFE, 0x1F, 0x71, 0xFB, 0x72, 0xFB, + 0x16, 0x60, 0xA8, 0x65, 0x00, 0x64, 0xA5, 0xDB, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x1B, 0x60, + 0x9A, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x03, 0x02, 0xC7, 0x60, 0x2E, 0x78, + 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x45, 0x64, 0x46, 0x1B, 0xF2, 0x65, 0x46, 0x64, 0x45, 0x5B, 0xF1, + 0xE0, 0x84, 0x73, 0xF1, 0xC0, 0x84, 0xC0, 0x84, 0x12, 0xFA, 0x2C, 0xF2, 0x71, 0xF3, 0x60, 0x40, + 0x01, 0x2A, 0x36, 0x00, 0x00, 0xA8, 0x1F, 0x60, 0x8E, 0x62, 0xA2, 0xD3, 0x37, 0x03, 0x00, 0xA8, + 0xFF, 0xFF, 0x34, 0x03, 0xDE, 0x60, 0x58, 0x4D, 0x6B, 0x78, 0xFF, 0xFF, 0x25, 0x46, 0x09, 0x60, + 0x08, 0x61, 0xA2, 0xFF, 0x0E, 0xF2, 0x02, 0xF0, 0x60, 0x40, 0xF0, 0x37, 0x0D, 0x00, 0x92, 0xF3, + 0x90, 0xF3, 0xDC, 0x83, 0xD1, 0x80, 0x92, 0xFD, 0x0C, 0x03, 0x8C, 0xF3, 0xCC, 0x83, 0xD8, 0xA0, + 0x90, 0xFD, 0x07, 0x04, 0xD4, 0xFE, 0x05, 0x00, 0xD1, 0x80, 0x93, 0xF3, 0x02, 0x03, 0xDC, 0x84, + 0x93, 0xFB, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x94, 0x64, 0xA2, 0xDB, 0x25, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA3, 0xFF, 0xDC, 0x60, 0x87, 0x78, 0xFF, 0xFF, + 0x66, 0x41, 0x65, 0x46, 0x06, 0xF2, 0x61, 0x46, 0x60, 0x40, 0x10, 0x2A, 0x4C, 0x00, 0x80, 0x67, + 0xB4, 0x81, 0x1B, 0x60, 0xDA, 0x62, 0x61, 0x44, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xDE, 0x60, 0x58, 0x4D, 0x6B, 0x78, 0xFF, 0xFF, 0x25, 0x46, + 0x2A, 0xF2, 0x09, 0x60, 0x08, 0x61, 0x0C, 0xB0, 0xA2, 0xFF, 0x17, 0x03, 0x0E, 0xF2, 0x02, 0xF0, + 0x60, 0x40, 0xF0, 0x37, 0x0D, 0x00, 0x90, 0xF3, 0x92, 0xF3, 0xCC, 0x83, 0xD1, 0x80, 0x90, 0xFD, + 0x0C, 0x03, 0x8C, 0xF3, 0xDC, 0x83, 0xD8, 0xA0, 0x92, 0xFD, 0x07, 0x04, 0xD4, 0xFE, 0x05, 0x00, + 0xD1, 0x80, 0x93, 0xF3, 0x02, 0x03, 0xDC, 0x84, 0x93, 0xFB, 0x07, 0xF0, 0x0A, 0xF2, 0xA3, 0xFF, + 0x64, 0x45, 0x30, 0x1B, 0x66, 0x41, 0x65, 0x46, 0x02, 0xF0, 0x61, 0x46, 0x0F, 0x60, 0xFF, 0x61, + 0xA1, 0x84, 0x60, 0x41, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, 0x01, 0x61, + 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x16, 0x60, 0x62, 0x65, 0x46, 0xD1, 0x61, 0x44, + 0xB0, 0x84, 0xA2, 0xDB, 0x17, 0x00, 0x1B, 0x60, 0x8E, 0x61, 0x2A, 0xF2, 0x3E, 0xF2, 0x0C, 0xB0, + 0x01, 0xB0, 0x05, 0x03, 0x1B, 0x60, 0xA0, 0x61, 0x02, 0x02, 0x1B, 0x60, 0x88, 0x61, 0x1B, 0x60, + 0xDA, 0x62, 0x61, 0x44, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xC1, 0xFE, 0xDC, 0x60, 0x87, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x2B, 0xF2, 0x2A, 0xF2, + 0x60, 0x41, 0x44, 0x49, 0x60, 0x45, 0xA4, 0x3A, 0x0D, 0x00, 0x61, 0x40, 0xC0, 0x3B, 0x7B, 0x00, + 0xA9, 0x46, 0x06, 0xF2, 0xA9, 0x46, 0x60, 0x40, 0x20, 0x26, 0x75, 0x00, 0x20, 0xBC, 0xA9, 0x46, + 0x06, 0xFA, 0xA9, 0x46, 0xA9, 0x46, 0x06, 0xF0, 0xA9, 0x46, 0x65, 0x40, 0x10, 0x2B, 0x6E, 0x00, + 0x64, 0x40, 0x10, 0x2A, 0x36, 0x00, 0x65, 0x40, 0xA4, 0x3A, 0x65, 0x00, 0x29, 0x45, 0x65, 0x46, + 0x72, 0xF2, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x04, 0x02, 0x78, 0x00, 0xDE, 0x60, 0x51, 0x78, + 0xFF, 0xFF, 0x09, 0xF2, 0x2A, 0xF0, 0x00, 0xA8, 0x20, 0x67, 0x02, 0x03, 0xB0, 0x84, 0x2A, 0xFA, + 0x0E, 0xF2, 0x02, 0xF0, 0x60, 0x40, 0xF0, 0x37, 0x08, 0x00, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, + 0xA2, 0xFF, 0x90, 0xF3, 0x02, 0x02, 0xDC, 0x84, 0x90, 0xFB, 0x3E, 0xF2, 0xA3, 0xFF, 0x01, 0xB0, + 0x1B, 0x60, 0xA0, 0x61, 0x02, 0x02, 0x1B, 0x60, 0x8E, 0x61, 0x1B, 0x60, 0xDA, 0x62, 0x61, 0x44, + 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, + 0x17, 0x00, 0x10, 0x64, 0xB0, 0x84, 0xDF, 0x65, 0xA4, 0x9E, 0xA9, 0x46, 0x06, 0xFA, 0xA9, 0x46, + 0xA2, 0xFF, 0x16, 0x60, 0xA8, 0x62, 0x04, 0x64, 0xA2, 0xDB, 0x29, 0x44, 0x5A, 0xDB, 0x71, 0xF3, + 0xC1, 0xFE, 0xD4, 0xFE, 0x87, 0xF1, 0xA3, 0xFF, 0xD0, 0x80, 0xDC, 0x84, 0x01, 0x07, 0x71, 0xFB, + 0xA9, 0x46, 0x72, 0xF2, 0xA9, 0x46, 0x65, 0x18, 0xA9, 0x46, 0x02, 0xF0, 0xA9, 0x46, 0x0F, 0x60, + 0xFF, 0x61, 0xA1, 0x84, 0x60, 0x41, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, + 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x16, 0x60, 0x62, 0x65, 0x46, 0xD1, + 0xFF, 0xFF, 0xB1, 0x84, 0xA2, 0xDB, 0xDE, 0x60, 0x68, 0x78, 0xFF, 0xFF, 0x64, 0x40, 0x10, 0x2A, + 0xFA, 0x01, 0xFF, 0x60, 0xEF, 0x64, 0xA0, 0x84, 0xA9, 0x46, 0x06, 0xFA, 0xA9, 0x46, 0x65, 0x41, + 0x71, 0xF3, 0x29, 0x45, 0xCC, 0x84, 0x80, 0x2B, 0x71, 0xFB, 0x65, 0x46, 0x72, 0xF2, 0xFF, 0xFF, + 0x00, 0xA8, 0x60, 0x46, 0x37, 0x02, 0x61, 0x40, 0xA4, 0x3A, 0xE5, 0x01, 0x00, 0x60, 0x3A, 0x61, + 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, 0x81, 0x03, 0x02, 0x60, 0x48, 0x64, 0x2A, 0xFA, + 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0x67, 0xF1, 0x32, 0xF8, + 0x68, 0xF1, 0x33, 0xF8, 0x69, 0xF1, 0x34, 0xF8, 0xA9, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x85, 0xF0, + 0xA9, 0x46, 0x2C, 0xFA, 0x2D, 0xF8, 0xAE, 0xF8, 0xAC, 0xF1, 0x19, 0xF8, 0xFF, 0x67, 0x0E, 0xFA, + 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x29, 0x44, 0x07, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, + 0x8E, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xC1, 0xFE, 0x37, 0x00, 0x80, 0x67, 0xB4, 0x83, 0x2A, 0xF2, 0x09, 0x60, 0x08, 0x65, 0x0C, 0xB0, + 0x09, 0xF0, 0x0D, 0x02, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x9D, 0x18, 0x64, 0x46, 0x3E, 0xF2, + 0xA2, 0xFF, 0x01, 0xB0, 0x1B, 0x60, 0xA0, 0x61, 0x02, 0x02, 0x1B, 0x60, 0x88, 0x61, 0x02, 0xF2, + 0x0E, 0xF0, 0xD4, 0x80, 0x09, 0xF4, 0x06, 0x02, 0x90, 0xF3, 0x64, 0x40, 0xF0, 0x37, 0x02, 0x00, + 0xDC, 0x84, 0x90, 0xFB, 0x66, 0x44, 0x00, 0xA8, 0xFF, 0xFF, 0xF1, 0x02, 0x1B, 0x60, 0xDA, 0x62, + 0x61, 0x44, 0xA2, 0xDB, 0x5A, 0xDD, 0x08, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, + 0xA3, 0xFF, 0xA9, 0x46, 0x02, 0xF0, 0xA9, 0x46, 0x0F, 0x60, 0xFF, 0x61, 0xA1, 0x84, 0x60, 0x41, + 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, + 0xE1, 0x81, 0xFD, 0x02, 0x16, 0x60, 0x62, 0x65, 0x46, 0xD3, 0x9D, 0x85, 0xA4, 0x84, 0xA2, 0xDB, + 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x46, 0x45, 0x3F, 0xF2, 0x05, 0x48, 0x00, 0xA8, 0x60, 0x41, + 0x66, 0x44, 0x0B, 0x03, 0x0E, 0xA1, 0x00, 0xF2, 0x42, 0xFE, 0xAC, 0x86, 0x01, 0xF2, 0x1F, 0x03, + 0x7F, 0xB5, 0xD5, 0x81, 0x66, 0x44, 0xF7, 0x07, 0x25, 0x46, 0x05, 0xF0, 0x06, 0xFA, 0x05, 0xFA, + 0xD0, 0x80, 0x64, 0x43, 0x13, 0x03, 0x60, 0x46, 0x01, 0xF0, 0x80, 0x67, 0xB0, 0x84, 0x01, 0xFA, + 0x00, 0xF0, 0x00, 0x64, 0x00, 0xFA, 0x44, 0x45, 0xA2, 0xFF, 0xB4, 0x60, 0x58, 0x4E, 0x48, 0x78, + 0xFF, 0xFF, 0xA3, 0xFF, 0x08, 0x45, 0x25, 0x46, 0x01, 0x64, 0x02, 0xFA, 0x02, 0xFE, 0x2D, 0x58, + 0xFF, 0xFF, 0x23, 0xF2, 0x07, 0xF0, 0x10, 0xB0, 0x10, 0xAC, 0x3B, 0x03, 0x23, 0xFA, 0x80, 0x67, + 0xB0, 0x81, 0x1B, 0x60, 0xDA, 0x62, 0x61, 0x44, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x04, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x46, 0x45, 0x64, 0x46, 0x02, 0xF0, 0x0F, 0x60, 0xFF, 0x61, + 0xA1, 0x84, 0x60, 0x41, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, 0x01, 0x61, + 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x16, 0x60, 0x62, 0x65, 0x46, 0xD1, 0xFF, 0xFF, + 0xB1, 0x84, 0xA2, 0xDB, 0x9B, 0xF2, 0x25, 0x46, 0xE1, 0x81, 0x5B, 0xF1, 0x73, 0xF1, 0xC1, 0x81, + 0xC1, 0x81, 0x92, 0xFA, 0xA2, 0xFF, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x61, 0xD1, 0x80, 0x0E, 0xF2, + 0x05, 0x02, 0x90, 0xF3, 0x20, 0xB0, 0xCC, 0x84, 0x01, 0x02, 0x90, 0xFB, 0xA3, 0xFF, 0x48, 0xFE, + 0x07, 0x00, 0x0E, 0xF2, 0x08, 0xFE, 0xF0, 0x7F, 0x60, 0x40, 0x20, 0x2A, 0x00, 0x7F, 0x0E, 0xFA, + 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0xA0, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, + 0x66, 0x44, 0x57, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x80, 0x64, 0x2A, 0xFA, 0xAC, 0xF1, 0x19, 0xF8, + 0x00, 0x64, 0x3E, 0xFA, 0x00, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0x88, 0xF1, 0x07, 0xF8, 0x67, 0x44, + 0x2C, 0xFA, 0x2D, 0xFA, 0x2E, 0xFA, 0x0F, 0x60, 0xF6, 0x62, 0xE1, 0x60, 0x9E, 0x64, 0xA2, 0xDB, + 0x10, 0x60, 0x02, 0x62, 0xE0, 0x60, 0x0D, 0x64, 0xA2, 0xDB, 0x16, 0x60, 0xB2, 0x63, 0x65, 0x44, + 0xBD, 0xDB, 0x10, 0x60, 0x04, 0x64, 0xBD, 0xDB, 0x02, 0x64, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, + 0xE6, 0x60, 0x5A, 0x78, 0xFF, 0xFF, 0xE6, 0x60, 0x58, 0x4D, 0x66, 0x78, 0xFF, 0xFF, 0x57, 0xF5, + 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0x67, 0xF1, 0x32, 0xF8, + 0x68, 0xF1, 0x33, 0xF8, 0x69, 0xF1, 0x34, 0xF8, 0x1F, 0x60, 0x92, 0x62, 0xA2, 0xD1, 0x01, 0x64, + 0x64, 0x40, 0xFE, 0x26, 0x10, 0xBC, 0x32, 0x40, 0x10, 0x26, 0x10, 0xBC, 0x23, 0x60, 0x4C, 0x62, + 0xA2, 0xDB, 0x1F, 0x60, 0x90, 0x62, 0xA2, 0xD1, 0x1F, 0x60, 0x1E, 0x64, 0x02, 0x18, 0x1F, 0x60, + 0x40, 0x64, 0x22, 0x60, 0xA2, 0x62, 0xA2, 0xDB, 0x22, 0x60, 0xBE, 0x62, 0xA2, 0xDB, 0x21, 0x60, + 0xC6, 0x61, 0x20, 0x60, 0x32, 0x62, 0xA2, 0xD3, 0x22, 0x60, 0x82, 0x65, 0xFE, 0xA4, 0xE0, 0x84, + 0x02, 0x05, 0x67, 0x44, 0x99, 0x00, 0xE0, 0x84, 0xC4, 0x85, 0x21, 0x60, 0xEC, 0x62, 0xA2, 0xD3, + 0xA5, 0xD1, 0xDA, 0x85, 0x21, 0x60, 0xE4, 0x62, 0xA0, 0x83, 0xA2, 0xDD, 0xA5, 0xD1, 0x21, 0x60, + 0xE2, 0x62, 0xA0, 0x83, 0xA2, 0xDD, 0x21, 0x60, 0xC0, 0x61, 0xDD, 0x60, 0x06, 0x64, 0xA1, 0xDB, + 0x06, 0xA1, 0x21, 0x60, 0xEA, 0x62, 0xA2, 0xD3, 0x21, 0x60, 0xE2, 0x62, 0x60, 0x40, 0xFD, 0xA0, + 0xA2, 0xD3, 0x74, 0x03, 0x50, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, + 0xF2, 0x63, 0x0E, 0x00, 0x04, 0x2A, 0x03, 0x00, 0x02, 0x60, 0xF2, 0x63, 0x09, 0x00, 0x10, 0x2A, + 0x03, 0x00, 0x04, 0x60, 0xF2, 0x63, 0x04, 0x00, 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, 0xF2, 0x63, + 0x59, 0xD9, 0x59, 0xDD, 0x21, 0x60, 0xEA, 0x62, 0xA2, 0xD3, 0x21, 0x60, 0xE4, 0x62, 0xFE, 0xA0, + 0xA2, 0xD3, 0x54, 0x03, 0x00, 0x60, 0x00, 0x63, 0x59, 0xDD, 0x61, 0x45, 0x60, 0x40, 0x01, 0x2A, + 0x04, 0x00, 0x00, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x02, 0x2A, 0x04, 0x00, + 0x01, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x04, 0x2A, 0x04, 0x00, 0x02, 0x60, + 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x10, 0x2A, 0x04, 0x00, 0x04, 0x60, 0xF2, 0x63, + 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, 0xF2, 0x63, 0x59, 0xD9, + 0x59, 0xDD, 0xD5, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xA5, 0xDD, 0x21, 0x60, 0xEA, 0x62, 0xA2, 0xD3, + 0x21, 0x60, 0xE6, 0x62, 0xFF, 0xA0, 0xA2, 0xD3, 0x21, 0x03, 0x00, 0x60, 0x00, 0x63, 0x59, 0xDD, + 0x61, 0x45, 0x60, 0x40, 0x01, 0x2A, 0x04, 0x00, 0x00, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, + 0x60, 0x40, 0x02, 0x2A, 0x04, 0x00, 0x01, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, + 0x04, 0x2A, 0x04, 0x00, 0x02, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0xD5, 0x83, 0xEB, 0x83, + 0xEB, 0x83, 0xA5, 0xDD, 0x21, 0x60, 0xE8, 0x62, 0xA2, 0xD1, 0x59, 0xD9, 0x21, 0x60, 0xC0, 0x65, + 0xD5, 0x84, 0xDD, 0x7F, 0xA5, 0xDB, 0x65, 0x44, 0x22, 0x60, 0xAC, 0x62, 0xA2, 0xDB, 0x22, 0x60, + 0xC8, 0x62, 0xA2, 0xDB, 0x57, 0xF5, 0xCB, 0xF3, 0xCC, 0xF1, 0x00, 0x63, 0xC0, 0x87, 0xCD, 0xF1, + 0x5A, 0xFD, 0xC0, 0x85, 0x65, 0x47, 0xC4, 0x84, 0x07, 0xB5, 0x1C, 0x60, 0x10, 0x62, 0x16, 0x60, + 0xAE, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xD0, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xD2, 0x62, 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, 0xE0, 0x60, + 0x17, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, + 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, + 0xD0, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x57, 0xF5, 0x00, 0x64, 0x95, 0xFB, 0x96, 0xFB, 0x97, 0xFB, + 0x75, 0xFB, 0x66, 0xF3, 0x00, 0x75, 0x00, 0x72, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x93, 0xC7, 0xF3, + 0xED, 0xE2, 0xCC, 0x84, 0x5A, 0xFB, 0x0F, 0x60, 0xD2, 0x62, 0x00, 0x60, 0x04, 0x64, 0xA2, 0xDB, + 0xE0, 0x60, 0x36, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD0, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x65, 0xF1, 0x23, 0x60, 0x02, 0x62, 0xA2, 0xD9, 0x22, 0x60, 0xAA, 0x65, + 0xE2, 0x60, 0x58, 0x4D, 0x2F, 0x78, 0xFF, 0xFF, 0xE1, 0x60, 0x58, 0x4D, 0xA8, 0x78, 0xFF, 0xFF, + 0xE2, 0x60, 0x58, 0x4D, 0x49, 0x78, 0xFF, 0xFF, 0x57, 0xF5, 0x00, 0xF4, 0x66, 0xF1, 0x06, 0xF8, + 0x23, 0x60, 0x4C, 0x62, 0xA2, 0xD3, 0x07, 0xFA, 0x22, 0x60, 0xA2, 0x64, 0x40, 0x48, 0x10, 0x61, + 0x00, 0x60, 0x00, 0x64, 0xE1, 0x60, 0x58, 0x4D, 0xE5, 0x78, 0xFF, 0xFF, 0x57, 0xF5, 0x3F, 0xFC, + 0x5A, 0xF3, 0xC7, 0xF1, 0xAC, 0x83, 0x01, 0x64, 0x02, 0x02, 0x6C, 0xFB, 0x64, 0x43, 0x1B, 0x60, + 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x04, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xCF, 0x83, 0x73, 0xF3, 0x5A, 0xFD, 0xDC, 0x84, 0x73, 0xFB, + 0x5C, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0x5C, 0xFB, 0x03, 0x03, 0xE1, 0x60, 0x0A, 0x78, 0xFF, 0xFF, + 0x0A, 0x64, 0x5C, 0xFB, 0xA2, 0x4C, 0x20, 0x27, 0xF8, 0x01, 0x46, 0x60, 0x50, 0x65, 0x72, 0x44, + 0xD4, 0x80, 0xFF, 0xFF, 0xF2, 0x04, 0x5D, 0xFB, 0x40, 0x48, 0x95, 0xF3, 0x5E, 0xFB, 0x40, 0x4A, + 0x96, 0xF3, 0x97, 0xF3, 0x40, 0x4C, 0x60, 0x41, 0x66, 0xF1, 0x40, 0x63, 0xAD, 0x80, 0xF0, 0xA3, + 0x09, 0x02, 0x3C, 0x03, 0x2C, 0x41, 0x2A, 0x44, 0x40, 0x4C, 0x28, 0x44, 0x40, 0x4A, 0x00, 0x64, + 0x40, 0x48, 0xF4, 0x01, 0xD1, 0x80, 0x01, 0x02, 0x31, 0x04, 0x10, 0xA3, 0x80, 0x60, 0x00, 0x65, + 0xA5, 0x80, 0xCF, 0x83, 0x08, 0x02, 0x28, 0x44, 0x60, 0x88, 0x2A, 0x44, 0x70, 0x8A, 0x2C, 0x44, + 0x70, 0x8C, 0xF1, 0x81, 0xF5, 0x01, 0xE7, 0xA3, 0x64, 0x44, 0x00, 0xA0, 0x00, 0x62, 0x02, 0x02, + 0x00, 0x61, 0x1C, 0x00, 0xE0, 0x84, 0xDE, 0x82, 0xFD, 0x04, 0x42, 0xFE, 0xF8, 0x84, 0x62, 0x45, + 0xC7, 0x83, 0x60, 0x45, 0x02, 0xFE, 0xD5, 0x84, 0x02, 0x05, 0x01, 0x05, 0x61, 0x44, 0xCF, 0x83, + 0x60, 0x41, 0x08, 0x03, 0x28, 0x44, 0x60, 0x88, 0x2A, 0x44, 0x70, 0x8A, 0x2C, 0x44, 0x70, 0x8C, + 0xF1, 0x81, 0xF1, 0x01, 0xCE, 0x82, 0xE9, 0x81, 0xFD, 0x02, 0xF1, 0x81, 0x61, 0x44, 0x00, 0xA8, + 0xFF, 0xFF, 0x30, 0x03, 0x73, 0x40, 0x5D, 0xF3, 0xFF, 0xFF, 0x60, 0x47, 0xE8, 0x84, 0xE8, 0x84, + 0x5E, 0xF3, 0x3F, 0xB5, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, + 0xB4, 0x84, 0x61, 0x45, 0xD4, 0x84, 0xC0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, + 0x64, 0x44, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x85, 0x61, 0x44, 0xD4, 0x80, + 0xFF, 0xFF, 0x10, 0x03, 0x60, 0x53, 0xD4, 0x84, 0xFF, 0xFF, 0x75, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, + 0x01, 0xB4, 0x75, 0xFB, 0x1F, 0x60, 0x14, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, + 0x08, 0x28, 0xA2, 0xDB, 0xE6, 0x60, 0xA3, 0x78, 0xFF, 0xFF, 0xC1, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x04, 0x64, 0x03, 0xFA, 0x00, 0xF4, 0x09, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x3A, 0x1C, 0x00, + 0x60, 0x43, 0x00, 0x36, 0x1C, 0x00, 0xE0, 0xA0, 0xDA, 0x85, 0x16, 0x07, 0x1F, 0x60, 0x1E, 0x61, + 0xA1, 0xD1, 0xFF, 0xFF, 0xD3, 0x80, 0xCB, 0x83, 0x0F, 0x02, 0x07, 0x0E, 0x59, 0xD3, 0xA5, 0xD0, + 0xDA, 0x85, 0xD0, 0x80, 0xFF, 0xFF, 0x08, 0x02, 0xF9, 0x1F, 0x13, 0x1E, 0xA5, 0xD0, 0x59, 0xD3, + 0xFF, 0xFF, 0x90, 0x80, 0xFF, 0x22, 0x0D, 0x00, 0xE1, 0x60, 0x9C, 0x78, 0xFF, 0xFF, 0x1F, 0x60, + 0x90, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x03, 0x00, 0x1F, 0x60, 0x40, 0x64, + 0x02, 0x00, 0x1F, 0x60, 0x1E, 0x64, 0x22, 0x60, 0xBE, 0x62, 0xA2, 0xDB, 0x26, 0x46, 0x2F, 0xF2, + 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, + 0x30, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0x67, 0xF1, 0x32, 0xF8, 0x68, 0xF1, 0x33, 0xF8, 0x69, 0xF1, + 0x34, 0xF8, 0x50, 0x63, 0x2A, 0xFC, 0xAC, 0xF3, 0x19, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0x88, 0xF3, + 0x07, 0xFA, 0x00, 0xF4, 0x66, 0xF1, 0x06, 0xF8, 0x23, 0x60, 0x4C, 0x62, 0xA2, 0xD3, 0x07, 0xFA, + 0x22, 0x60, 0xC6, 0x65, 0xE2, 0x60, 0x58, 0x4D, 0x2F, 0x78, 0xFF, 0xFF, 0x22, 0x60, 0xBE, 0x64, + 0x40, 0x48, 0x10, 0x61, 0x00, 0x60, 0x00, 0x64, 0xE1, 0x60, 0x58, 0x4D, 0xE5, 0x78, 0xFF, 0xFF, + 0x26, 0x46, 0x3F, 0xFC, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x26, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x20, 0x44, 0x80, 0x26, + 0x11, 0x00, 0x80, 0xBC, 0x40, 0x40, 0x00, 0x64, 0x95, 0xFB, 0x96, 0xFB, 0x97, 0xFB, 0x75, 0xFB, + 0x66, 0xF3, 0x00, 0x75, 0x00, 0x72, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x93, 0xC7, 0xF3, 0xED, 0xE2, + 0xCC, 0x84, 0x5A, 0xFB, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD0, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x00, 0x64, 0x73, 0xFB, 0x75, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, + 0x3E, 0x63, 0x16, 0x60, 0x60, 0x61, 0x59, 0xD1, 0x61, 0x46, 0x08, 0x1B, 0xFC, 0x1F, 0x22, 0x60, + 0xDE, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x65, 0x00, 0x61, 0x17, 0x00, 0x16, 0x60, 0xA2, 0x61, + 0x49, 0xD1, 0xCB, 0x83, 0xFD, 0x18, 0x63, 0x41, 0x04, 0xA1, 0x61, 0x45, 0x66, 0x43, 0x22, 0x60, + 0xDE, 0x64, 0xDC, 0x84, 0x60, 0xFE, 0xA3, 0xD1, 0xDF, 0x83, 0xA0, 0xD9, 0xCD, 0x81, 0x20, 0xFE, + 0xF8, 0x02, 0x66, 0x44, 0x16, 0x60, 0x62, 0x7C, 0xD0, 0x81, 0x5A, 0xF3, 0xC7, 0xF1, 0x22, 0x60, + 0xDC, 0x63, 0x00, 0xA0, 0x64, 0x5F, 0xBD, 0xDB, 0x1B, 0x60, 0x94, 0x66, 0xA6, 0xD1, 0x02, 0x02, + 0x01, 0x18, 0x01, 0xB9, 0x61, 0x44, 0x60, 0xFE, 0xA3, 0xDB, 0xFC, 0xA3, 0x65, 0x44, 0x03, 0xA4, + 0xA3, 0xDB, 0xFF, 0xFF, 0x20, 0xFE, 0x2D, 0x58, 0xFF, 0xFF, 0x23, 0x60, 0x4E, 0x62, 0xA2, 0xDB, + 0xCD, 0x81, 0x28, 0xD3, 0x5A, 0x88, 0xDC, 0x83, 0x39, 0x18, 0xFB, 0x03, 0x61, 0x40, 0x7F, 0x3A, + 0x07, 0x00, 0x23, 0x60, 0x4E, 0x62, 0xA2, 0xD3, 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x00, 0xF4, + 0x60, 0xFE, 0xA3, 0xD1, 0xDD, 0x81, 0xA1, 0xD8, 0x61, 0x40, 0x7F, 0x3A, 0x09, 0x00, 0x20, 0xFE, + 0x23, 0x60, 0x4E, 0x62, 0xA2, 0xD3, 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x00, 0xF4, 0x60, 0xFE, + 0xCF, 0x83, 0xA3, 0xD3, 0xDD, 0x81, 0xA1, 0xDA, 0xFF, 0xB4, 0x00, 0x7F, 0x15, 0x03, 0xDB, 0x83, + 0x61, 0x40, 0x7F, 0x3A, 0x0B, 0x00, 0x20, 0xFE, 0x60, 0x45, 0x23, 0x60, 0x4E, 0x62, 0xA2, 0xD3, + 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x65, 0x44, 0x00, 0xF4, 0x60, 0xFE, 0xA3, 0xD1, 0xDF, 0x83, + 0xDD, 0x81, 0xCC, 0x84, 0xA1, 0xD8, 0xEC, 0x02, 0x20, 0xFE, 0xC3, 0x01, 0x23, 0x60, 0x4E, 0x62, + 0xA2, 0xD1, 0xFD, 0xA1, 0xFF, 0xB1, 0xC1, 0x83, 0xA2, 0xDD, 0x2D, 0x58, 0xFF, 0xFF, 0x67, 0x5C, + 0x11, 0x60, 0xF0, 0x61, 0xA1, 0xD3, 0xA5, 0xD9, 0x12, 0x18, 0x60, 0x43, 0x23, 0x60, 0x04, 0x64, + 0xA5, 0xDB, 0x60, 0xFE, 0xA0, 0xDD, 0xFF, 0xFF, 0x20, 0xFE, 0xDC, 0x84, 0xCF, 0x83, 0xE3, 0x83, + 0x59, 0xD1, 0xDC, 0x84, 0x60, 0xFE, 0xA0, 0xD9, 0xFF, 0xFF, 0x20, 0xFE, 0xF9, 0x1F, 0x2D, 0x58, + 0xFF, 0xFF, 0x20, 0x40, 0x20, 0x2A, 0x0D, 0x00, 0x12, 0x60, 0xB8, 0x62, 0xA2, 0xD1, 0x50, 0xF3, + 0x23, 0x60, 0x39, 0x63, 0x60, 0xFE, 0xA3, 0xD9, 0xDF, 0x83, 0x60, 0x47, 0xA3, 0xDB, 0xFF, 0xFF, + 0x20, 0xFE, 0x2D, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, 0x40, 0x26, 0x25, 0x00, 0x45, 0x48, + 0x00, 0x60, 0x10, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, 0x1D, 0x03, 0xF2, 0x60, + 0x02, 0x64, 0x24, 0xFA, 0x00, 0x60, 0x48, 0x61, 0x28, 0x44, 0x59, 0xDA, 0x03, 0x64, 0x38, 0x43, + 0xBD, 0xD1, 0xCC, 0x84, 0x59, 0xD8, 0xFC, 0x02, 0x39, 0x44, 0x59, 0xDA, 0x06, 0x64, 0x23, 0xFA, + 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xCA, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, + 0x40, 0x26, 0x51, 0x00, 0x45, 0x48, 0x00, 0x60, 0x68, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, + 0xFF, 0xFF, 0x49, 0x03, 0xF2, 0x60, 0x01, 0x64, 0x24, 0xFA, 0x02, 0x60, 0x00, 0x61, 0x46, 0x4A, + 0x38, 0x44, 0x54, 0x94, 0x03, 0x64, 0x01, 0x02, 0x09, 0x00, 0x06, 0x63, 0x4A, 0x61, 0x38, 0x46, + 0xBD, 0xD0, 0xCC, 0x84, 0x2A, 0x46, 0x59, 0xD8, 0xFA, 0x02, 0x06, 0x00, 0xDA, 0x81, 0x38, 0x43, + 0xBD, 0xD1, 0xCC, 0x84, 0x59, 0xD8, 0xFC, 0x02, 0x05, 0x63, 0x28, 0x44, 0x02, 0xA8, 0x25, 0xFA, + 0x07, 0x02, 0x03, 0x64, 0x39, 0x43, 0xBD, 0xD1, 0xCC, 0x84, 0x59, 0xD8, 0xFC, 0x02, 0x08, 0x63, + 0x22, 0x60, 0x28, 0x7C, 0x28, 0x44, 0x03, 0xA8, 0xA4, 0xD3, 0x0F, 0x03, 0xE8, 0x85, 0xC7, 0x85, + 0x60, 0x43, 0xFE, 0xA3, 0x22, 0x60, 0x2A, 0x64, 0x58, 0xD1, 0xD9, 0x81, 0xA1, 0xD8, 0x7E, 0x2A, + 0x02, 0x00, 0x00, 0xF4, 0x02, 0x61, 0xF8, 0x1F, 0x65, 0x43, 0x2A, 0x46, 0x23, 0xFC, 0x1B, 0x60, + 0xDA, 0x62, 0x1B, 0x60, 0xCA, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, 0x40, 0x26, + 0x1C, 0x00, 0x45, 0x48, 0x00, 0x60, 0x06, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, + 0x14, 0x03, 0x02, 0x64, 0x23, 0xFA, 0xF2, 0x60, 0x00, 0x64, 0x5A, 0xDA, 0x28, 0x44, 0x5A, 0xDA, + 0xFF, 0xFF, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xCA, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, + 0x32, 0x40, 0x40, 0x26, 0x3E, 0x00, 0x7C, 0xF3, 0x67, 0x43, 0xDC, 0x84, 0xCC, 0x84, 0x39, 0x03, + 0x60, 0x46, 0x0A, 0x02, 0x7C, 0xFD, 0x00, 0x60, 0x46, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, + 0xFF, 0xFF, 0x66, 0x44, 0x7C, 0xFB, 0x2E, 0x03, 0x46, 0x4B, 0x1E, 0x60, 0xD8, 0x61, 0x18, 0x64, + 0x23, 0xFA, 0xF1, 0x60, 0x00, 0x64, 0x24, 0xFA, 0x4A, 0x65, 0xA2, 0xFF, 0x2C, 0x63, 0x00, 0x64, + 0x59, 0xD1, 0xA2, 0xDB, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, + 0xF7, 0x1F, 0x12, 0x63, 0x59, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, + 0x04, 0x65, 0xF8, 0x1F, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xCA, 0x64, 0xA2, 0xDB, 0x2B, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0xA6, 0xFE, 0x00, 0x64, + 0x7C, 0xFB, 0xA3, 0xFF, 0xC7, 0x60, 0x2E, 0x78, 0xFF, 0xFF, 0xA6, 0xFE, 0xB8, 0x05, 0xA7, 0xFE, + 0x0A, 0x05, 0xA5, 0xFE, 0x03, 0x04, 0xE3, 0x60, 0xD3, 0x78, 0xFF, 0xFF, 0xA4, 0xFE, 0xF2, 0x04, + 0xE4, 0x60, 0x69, 0x78, 0xFF, 0xFF, 0x36, 0x45, 0x17, 0x60, 0x52, 0x64, 0x44, 0xD7, 0xFF, 0xFF, + 0xFF, 0xFF, 0x28, 0xF3, 0x7E, 0xF1, 0x60, 0x47, 0x07, 0xB4, 0x4E, 0xFB, 0x01, 0x61, 0x03, 0x03, + 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x9D, 0x84, 0xA1, 0x80, 0xA0, 0x83, 0x1A, 0x03, 0x7E, 0xFD, + 0x0F, 0x60, 0xF4, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x7E, 0xF1, 0x31, 0x44, 0x64, 0x40, 0xFF, 0x26, 0x09, 0x00, 0xFE, 0xB4, 0x40, 0x51, 0x01, 0x7C, + 0xBC, 0xF9, 0x49, 0xF3, 0x01, 0x63, 0x60, 0x40, 0xFF, 0x26, 0x49, 0xFD, 0xC7, 0x60, 0x2E, 0x78, + 0xFF, 0xFF, 0xE3, 0x60, 0xD3, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0xB6, 0x63, 0xBD, 0xD3, 0xBD, 0xD1, + 0xBD, 0xD1, 0xB0, 0x84, 0xB0, 0x84, 0xFF, 0xFF, 0x07, 0x02, 0x6B, 0xFB, 0x31, 0x44, 0xFE, 0xB4, + 0x40, 0x51, 0x0D, 0x64, 0x05, 0xFB, 0x3F, 0x00, 0x28, 0xF3, 0x7E, 0xF1, 0x60, 0x47, 0x64, 0x41, + 0x07, 0xB1, 0x07, 0xB4, 0x08, 0x24, 0x67, 0x4C, 0x4E, 0xFB, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, + 0xE1, 0x81, 0xFD, 0x02, 0xA1, 0x80, 0xB1, 0x83, 0x2E, 0x02, 0x7E, 0xFD, 0x1F, 0x60, 0xAA, 0x62, + 0xA2, 0xD3, 0xC5, 0xFB, 0x65, 0xFB, 0x7E, 0xF3, 0xFF, 0xFF, 0xCC, 0x85, 0xA4, 0x80, 0x7E, 0xFB, + 0x17, 0x02, 0x1B, 0x60, 0xC4, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x46, 0x5E, + 0x31, 0x44, 0x01, 0xBC, 0x40, 0x51, 0xED, 0xE2, 0x0F, 0x4E, 0xCE, 0x60, 0x58, 0x4F, 0x07, 0x78, + 0xFF, 0xFF, 0x0E, 0x4F, 0x01, 0x65, 0xE2, 0x60, 0x58, 0x4E, 0xDD, 0x78, 0xFF, 0xFF, 0x08, 0x00, + 0x0F, 0x60, 0xD6, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0xE5, 0x60, 0x16, 0x78, 0xFF, 0xFF, 0xD7, 0xFE, 0xC7, 0x60, 0x2E, 0x78, 0xFF, 0xFF, 0x2E, 0xF5, + 0x27, 0xF2, 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, + 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, + 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, + 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, + 0x63, 0x46, 0xE8, 0x1B, 0x88, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x28, 0x02, 0x14, 0x60, + 0xD0, 0x62, 0xA2, 0xD3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x04, 0x03, 0xD3, 0x80, + 0xD9, 0x81, 0xFA, 0x02, 0x09, 0x00, 0xA1, 0xDD, 0x14, 0x60, 0xD0, 0x62, 0xD9, 0x84, 0xA2, 0xDB, + 0x4A, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xA2, 0xDB, 0x66, 0x45, 0x63, 0x46, 0x06, 0xF2, 0xFF, 0x60, + 0x01, 0x7C, 0xA0, 0x9C, 0x06, 0xF8, 0x65, 0x46, 0x71, 0xF3, 0x60, 0x40, 0x10, 0x2A, 0x03, 0x00, + 0xCC, 0x84, 0x80, 0x2B, 0x71, 0xFB, 0xE4, 0x60, 0x58, 0x4E, 0x9D, 0x78, 0xFF, 0xFF, 0xAB, 0x01, + 0x2E, 0xF5, 0x25, 0x60, 0x28, 0x61, 0x28, 0xF0, 0xFF, 0xFF, 0xA1, 0xD9, 0x27, 0xF2, 0x12, 0x60, + 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, + 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, + 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, + 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, + 0x88, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x13, 0x02, 0x63, 0x46, 0x06, 0xF2, 0xFF, 0xFF, + 0x02, 0xB0, 0x08, 0xBC, 0x0D, 0x03, 0x06, 0xFA, 0xE4, 0x60, 0x58, 0x4E, 0x9D, 0x78, 0xFF, 0xFF, + 0x0F, 0x60, 0xE8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x6A, 0x01, 0x7E, 0xF1, 0xFF, 0xFF, 0x64, 0x41, 0x07, 0xB1, 0xFF, 0xFF, 0x08, 0x24, 0x67, 0x4C, + 0x1B, 0x60, 0xC4, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x46, 0x5E, 0x1F, 0x60, + 0xAA, 0x62, 0xA2, 0xD3, 0xC5, 0xFB, 0x65, 0xFB, 0x1F, 0x60, 0xB6, 0x63, 0xBD, 0xD1, 0xCB, 0xF9, + 0x67, 0xF9, 0xBD, 0xD1, 0xCC, 0xF9, 0x68, 0xF9, 0xA3, 0xD1, 0xCD, 0xF9, 0x69, 0xF9, 0x01, 0x64, + 0x6B, 0xFB, 0x31, 0x44, 0x21, 0xBC, 0x40, 0x51, 0x20, 0x44, 0x01, 0x65, 0x34, 0x80, 0x01, 0x64, + 0x51, 0xFB, 0x21, 0x60, 0x50, 0x64, 0x52, 0xFB, 0x0F, 0x4E, 0xE8, 0x60, 0x58, 0x4F, 0x02, 0x78, + 0xFF, 0xFF, 0x0E, 0x4F, 0xC7, 0x60, 0x2E, 0x78, 0xFF, 0xFF, 0x0E, 0x57, 0x63, 0x46, 0x43, 0x47, + 0x1E, 0xF2, 0x72, 0xF2, 0x02, 0x1B, 0x01, 0x1B, 0x0C, 0x00, 0x60, 0x46, 0x1B, 0x60, 0xDA, 0x64, + 0x40, 0x4B, 0xF0, 0x60, 0x58, 0x4D, 0x75, 0x78, 0xFF, 0xFF, 0x27, 0x46, 0x72, 0xF2, 0xFF, 0xFF, + 0xF4, 0x1B, 0x37, 0x58, 0xFF, 0xFF, 0x1B, 0x60, 0xAC, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, + 0x60, 0x46, 0x0E, 0xF2, 0x5B, 0x03, 0x60, 0x40, 0xF0, 0x37, 0x48, 0x00, 0xFF, 0x37, 0x3D, 0x00, + 0xFD, 0x37, 0x35, 0x00, 0x18, 0x37, 0x29, 0x00, 0xFE, 0x37, 0x2C, 0x00, 0xF8, 0x37, 0x0A, 0x00, + 0x60, 0x47, 0xFF, 0xB5, 0x0F, 0x60, 0xD0, 0x62, 0x46, 0xD1, 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x1B, 0x60, 0xDA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xD6, 0x01, 0x06, 0xB4, 0xFD, 0x7F, 0x0E, 0xFA, + 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xB2, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF9, 0xFE, 0xC6, 0x01, 0xDB, 0x60, 0x58, 0x4F, 0xB7, 0x78, + 0xFF, 0xFF, 0x14, 0x00, 0xDE, 0x60, 0x58, 0x4F, 0x99, 0x78, 0xFF, 0xFF, 0xBC, 0x03, 0x23, 0xF0, + 0x60, 0x40, 0x04, 0x26, 0xE2, 0x1B, 0x02, 0x26, 0xE0, 0x18, 0xA2, 0xFF, 0x02, 0xF0, 0x09, 0x60, + 0x08, 0x64, 0xD0, 0x80, 0x90, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0x90, 0xFB, 0x1B, 0x60, 0xDA, 0x64, + 0x40, 0x4B, 0xF0, 0x60, 0x58, 0x4D, 0x75, 0x78, 0xFF, 0xFF, 0xA5, 0x01, 0xAC, 0xFE, 0x09, 0x05, + 0xAD, 0xFE, 0x10, 0x05, 0xAE, 0xFE, 0x9F, 0x05, 0xAF, 0xFE, 0x3A, 0x05, 0xC7, 0x60, 0x2E, 0x78, + 0xFF, 0xFF, 0x0F, 0x60, 0xCE, 0x62, 0xA2, 0xD1, 0x20, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0xF4, 0x01, 0x10, 0x60, 0x02, 0x65, 0x03, 0x61, 0x07, 0x00, 0xA2, 0xDD, 0x58, 0x4F, + 0x64, 0x58, 0xFF, 0xFF, 0x00, 0xB9, 0xFF, 0xFF, 0x08, 0x03, 0x00, 0x63, 0xA5, 0xD1, 0x5A, 0xD3, + 0xDA, 0x85, 0x00, 0xA8, 0xCD, 0x81, 0xF2, 0x02, 0xF8, 0x02, 0xE0, 0x01, 0x0F, 0x60, 0xCC, 0x62, + 0x0F, 0x60, 0xF2, 0x65, 0xE5, 0x60, 0x4E, 0x63, 0x00, 0x64, 0x5A, 0xDB, 0xD6, 0x80, 0xFF, 0xFF, + 0x04, 0x03, 0x5A, 0xDB, 0x5A, 0xDB, 0x5A, 0xDD, 0xF9, 0x01, 0x10, 0x60, 0x00, 0x65, 0x00, 0x64, + 0x5A, 0xDB, 0xD6, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x5A, 0xDD, 0xFB, 0x01, 0x2F, 0x58, 0xFF, 0xFF, + 0x0F, 0x60, 0xD0, 0x64, 0x40, 0x41, 0x0F, 0x60, 0xCE, 0x63, 0xA3, 0xD1, 0x00, 0x64, 0xD0, 0x80, + 0x06, 0x61, 0x08, 0x03, 0xBD, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0xB0, 0x84, 0xCD, 0x81, 0xA3, 0xDB, + 0x06, 0xA3, 0xF9, 0x02, 0x0F, 0x60, 0xF4, 0x63, 0xA3, 0xD1, 0x00, 0x64, 0xD0, 0x80, 0x07, 0x61, + 0x19, 0x03, 0xBD, 0xDB, 0x64, 0x44, 0xFE, 0xA3, 0x02, 0xA3, 0xCD, 0x81, 0xE8, 0x84, 0xE3, 0x03, + 0x02, 0x05, 0xE1, 0x03, 0xF9, 0x01, 0x78, 0xFB, 0x7A, 0xFD, 0x61, 0x5C, 0xA3, 0xD3, 0x79, 0xF9, + 0x03, 0x18, 0x58, 0x4F, 0x60, 0x58, 0xFF, 0xFF, 0x7A, 0xF3, 0x79, 0xF1, 0x60, 0x43, 0x78, 0xF3, + 0x64, 0x41, 0xEA, 0x01, 0x21, 0x43, 0x0F, 0x60, 0xF4, 0x65, 0xD7, 0x80, 0xBD, 0xD1, 0xBD, 0xD3, + 0x03, 0x02, 0xC7, 0x60, 0x2E, 0x78, 0xFF, 0xFF, 0xA0, 0x84, 0xBD, 0xD1, 0x43, 0x41, 0xF5, 0x03, + 0xE5, 0x60, 0x53, 0x64, 0x64, 0x58, 0x40, 0x4F, 0x2A, 0xF0, 0x83, 0x60, 0xFF, 0x65, 0x64, 0x47, + 0x03, 0x2B, 0x01, 0x00, 0x17, 0x00, 0x03, 0x26, 0x03, 0xAC, 0x60, 0x47, 0xA4, 0x84, 0x2A, 0xFA, + 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0x64, 0x41, 0xCB, 0xF3, + 0x2F, 0xFA, 0x60, 0x43, 0xCC, 0xF3, 0x30, 0xFA, 0xCD, 0xF1, 0x31, 0xF8, 0x32, 0xFC, 0x33, 0xFA, + 0x34, 0xF8, 0x19, 0x00, 0x60, 0x47, 0xA4, 0x84, 0x2A, 0xFA, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, + 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0x36, 0xF2, 0x32, 0xFA, 0x37, 0xF2, 0x33, 0xFA, 0x38, 0xF2, + 0x34, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0x36, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0x37, 0xFA, 0xCD, 0xF3, + 0x31, 0xFA, 0x38, 0xFA, 0x64, 0x41, 0x1C, 0xF2, 0x13, 0xFA, 0x00, 0xF4, 0x0D, 0xF2, 0xFF, 0xFF, + 0x60, 0x40, 0x80, 0x2B, 0x29, 0x00, 0x26, 0x46, 0x04, 0x63, 0x03, 0xFC, 0x00, 0xF4, 0x0D, 0xF2, + 0x06, 0xFA, 0xE6, 0x60, 0x58, 0x4E, 0xF4, 0x78, 0xFF, 0xFF, 0xFF, 0xA0, 0x59, 0xF5, 0x1A, 0x02, + 0x39, 0xF2, 0x26, 0x46, 0x3F, 0xFA, 0x00, 0xF4, 0x00, 0x60, 0x81, 0x67, 0x0D, 0xFA, 0x7C, 0x64, + 0x01, 0xFA, 0x26, 0x46, 0x00, 0x64, 0x3E, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x9A, 0x64, + 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, + 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xF0, 0x42, 0x64, 0xD0, 0x80, + 0xFF, 0xFF, 0x01, 0x04, 0x3F, 0xFA, 0x1C, 0xF2, 0x13, 0xFA, 0x26, 0xF2, 0x27, 0xF0, 0x60, 0x47, + 0x00, 0xF4, 0x1F, 0xFA, 0x64, 0x47, 0x20, 0xFA, 0x61, 0x44, 0x21, 0xFA, 0x01, 0x67, 0x0D, 0xFA, + 0x10, 0x61, 0x1F, 0x60, 0x6C, 0x64, 0x1E, 0x63, 0x58, 0xD1, 0xCD, 0x81, 0xBD, 0xD8, 0xFC, 0x02, + 0x9B, 0xF1, 0xB8, 0xF1, 0x64, 0x5E, 0x64, 0x5F, 0x44, 0x63, 0xBD, 0xDA, 0x1F, 0x60, 0x66, 0x62, + 0xA2, 0xD3, 0xFF, 0xFF, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x09, 0xBC, 0x4A, 0xD3, 0x60, 0x45, + 0x60, 0x40, 0x01, 0x36, 0x03, 0x64, 0x02, 0x36, 0x01, 0x64, 0xB4, 0x84, 0x06, 0xA2, 0xA2, 0xD1, + 0xBD, 0xDA, 0x64, 0x47, 0xBD, 0xDA, 0xB5, 0xF3, 0xB6, 0xF1, 0x60, 0x47, 0xBD, 0xDA, 0x64, 0x47, + 0xC3, 0xF1, 0xBD, 0xDA, 0x64, 0x44, 0xBD, 0xDA, 0x26, 0x46, 0x00, 0x64, 0x23, 0xF0, 0x3B, 0xF0, + 0x64, 0x40, 0x10, 0x2A, 0x06, 0x00, 0xC0, 0x67, 0xA0, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, + 0x10, 0xBC, 0x3E, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x9A, 0x64, 0xA2, 0xDB, 0x26, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, 0x00, 0x66, 0x46, 0x46, + 0x2F, 0x58, 0xFF, 0xFF, 0x04, 0x60, 0x5C, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, + 0x66, 0x44, 0x59, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x2F, 0x58, 0xFF, 0xFF, 0x59, 0xF5, 0xAC, 0xF1, + 0x19, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x08, 0x64, 0x2A, 0xFA, 0x80, 0x7E, 0xF8, 0x7F, 0x0E, 0xFA, + 0x88, 0xF1, 0x07, 0xF8, 0x01, 0x60, 0x60, 0x67, 0x2C, 0xFA, 0x1D, 0x60, 0x00, 0x67, 0x2D, 0xFA, + 0x01, 0x60, 0x00, 0x67, 0x2E, 0xFA, 0xCB, 0xF1, 0x2F, 0xF8, 0x32, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, + 0x33, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0x34, 0xF8, 0x00, 0x63, 0x3B, 0xFC, 0x3D, 0xFC, 0x01, 0x64, + 0x3A, 0xFA, 0x66, 0x64, 0x39, 0xFA, 0x3C, 0xFC, 0xAA, 0x60, 0xAA, 0x64, 0x00, 0xF4, 0x02, 0xFA, + 0x00, 0x60, 0x03, 0x64, 0x5A, 0xDA, 0x1D, 0x60, 0x60, 0x64, 0x5A, 0xDA, 0x01, 0x60, 0x00, 0x64, + 0x5A, 0xDA, 0x82, 0x7F, 0x24, 0x7E, 0x08, 0xFA, 0x01, 0x60, 0x01, 0x64, 0x0A, 0xFA, 0x00, 0x64, + 0x0E, 0xFA, 0x2D, 0x58, 0xFF, 0xFF, 0x59, 0xF5, 0x3D, 0xF2, 0x3C, 0xF2, 0xCC, 0x83, 0x00, 0xA8, + 0x03, 0x03, 0x08, 0x28, 0x3D, 0xFC, 0x45, 0x00, 0x3D, 0xFA, 0x3A, 0xF2, 0x3B, 0xF0, 0x00, 0x63, + 0x00, 0xF4, 0x07, 0xFC, 0x01, 0xB0, 0x0B, 0xFA, 0x1A, 0x03, 0x1F, 0xF8, 0xFF, 0xFF, 0x1B, 0x60, + 0xDA, 0x62, 0x18, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0x1F, 0xF2, 0x1E, 0xF0, 0x59, 0xF5, 0x00, 0xA8, 0x3B, 0xF8, 0xD0, 0x80, 0x06, 0x03, + 0x05, 0x03, 0x04, 0x60, 0x5C, 0x63, 0x0F, 0x64, 0x3A, 0xFA, 0x39, 0xFC, 0x00, 0xF4, 0x00, 0x64, + 0x06, 0xFA, 0xE6, 0x60, 0x58, 0x4E, 0xF4, 0x78, 0xFF, 0xFF, 0x59, 0xF5, 0x00, 0xF4, 0x81, 0x60, + 0x00, 0x64, 0x06, 0xFA, 0x32, 0x47, 0x04, 0xBC, 0x07, 0xFA, 0xB8, 0xF1, 0x00, 0x7F, 0x64, 0x5E, + 0x09, 0xFA, 0x59, 0xF5, 0x00, 0x64, 0x15, 0xFA, 0x39, 0xF2, 0x3F, 0xFA, 0x1B, 0x60, 0xDA, 0x62, + 0x1B, 0x60, 0x88, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xE1, 0x60, 0x0D, 0x78, 0xFF, 0xFF, 0x66, 0x45, 0x0E, 0xF2, 0x0F, 0xF0, 0x10, 0xF0, + 0x64, 0x41, 0x01, 0xA8, 0x59, 0xF5, 0x09, 0x02, 0xAD, 0x83, 0x64, 0x44, 0xAC, 0x84, 0x08, 0x24, + 0x0A, 0x63, 0x3C, 0xFC, 0x3D, 0xFC, 0x1A, 0x02, 0x2D, 0x00, 0x03, 0x3A, 0x03, 0x00, 0x00, 0x64, + 0x3C, 0xFA, 0x29, 0x00, 0x04, 0x3A, 0x09, 0x00, 0x0A, 0x64, 0x3C, 0xFA, 0x01, 0x64, 0x3A, 0xFA, + 0x00, 0xF4, 0x00, 0x64, 0x1F, 0xFA, 0x1E, 0xFA, 0x1E, 0x00, 0x02, 0x3A, 0x1E, 0x00, 0x64, 0x44, + 0xAD, 0x83, 0xAC, 0x84, 0x02, 0x03, 0x3C, 0xFC, 0x3D, 0xFC, 0x15, 0x03, 0x3A, 0xFA, 0xF8, 0x65, + 0x52, 0x63, 0x64, 0x44, 0x01, 0x36, 0x0D, 0x00, 0x12, 0xA3, 0x64, 0x40, 0x02, 0x2A, 0x02, 0x00, + 0xC7, 0x83, 0xC7, 0x83, 0x64, 0x40, 0x08, 0x2A, 0x01, 0x00, 0xC7, 0x83, 0x64, 0x40, 0x04, 0x26, + 0xC7, 0x83, 0x39, 0xFC, 0x00, 0x64, 0x2E, 0x58, 0xFF, 0xFF, 0x3B, 0xF0, 0x3A, 0xF2, 0x65, 0x46, + 0x06, 0xF2, 0x40, 0x47, 0x1D, 0x18, 0x32, 0x47, 0x07, 0xFA, 0x24, 0x7E, 0x82, 0x7F, 0x08, 0xFA, + 0x01, 0x60, 0x01, 0x63, 0xB8, 0xF3, 0x0A, 0xFC, 0x00, 0x7F, 0x09, 0xFA, 0x27, 0x40, 0x01, 0x2A, + 0x0F, 0x00, 0x1F, 0xF8, 0x1B, 0x60, 0xDA, 0x62, 0x18, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, + 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x1E, 0xF0, 0x59, 0xF5, 0x3B, 0xF8, 0x65, 0x46, + 0x27, 0x40, 0x02, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x13, 0x00, 0x6E, 0x61, 0xFF, 0x60, 0xFE, 0x64, + 0x00, 0x60, 0x0E, 0x63, 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, 0x01, 0x60, 0xEE, 0x63, 0x00, 0xF4, + 0x02, 0x61, 0x58, 0xD1, 0x59, 0xD8, 0x7E, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x02, 0x61, 0xF9, 0x1F, + 0x27, 0x40, 0x04, 0x26, 0x1B, 0x00, 0x46, 0x4B, 0x1B, 0x60, 0x88, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, + 0x00, 0xA8, 0x60, 0x46, 0x0E, 0x03, 0x89, 0xF0, 0xE7, 0x60, 0x58, 0x4D, 0xAE, 0x78, 0xFF, 0xFF, + 0x65, 0x44, 0xAC, 0x86, 0xFF, 0xFF, 0x08, 0x03, 0xE7, 0x60, 0x58, 0x4D, 0xAE, 0x78, 0xFF, 0xFF, + 0x04, 0x00, 0x2B, 0x46, 0x82, 0xFC, 0x00, 0xF4, 0x82, 0xFC, 0x00, 0xF4, 0x27, 0x40, 0x08, 0x26, + 0x1A, 0x00, 0x46, 0x4B, 0x1B, 0x60, 0xC4, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, + 0x0E, 0x03, 0x89, 0xF0, 0xE7, 0x60, 0x58, 0x4D, 0xAE, 0x78, 0xFF, 0xFF, 0x65, 0x44, 0xAC, 0x86, + 0xFF, 0xFF, 0x08, 0x03, 0xE7, 0x60, 0x58, 0x4D, 0xAE, 0x78, 0xFF, 0xFF, 0x04, 0x00, 0x65, 0x46, + 0x02, 0xFA, 0x00, 0xF4, 0x82, 0xFC, 0x01, 0x64, 0x2E, 0x58, 0xFF, 0xFF, 0x01, 0x61, 0x02, 0x64, + 0x7A, 0x63, 0x58, 0xD0, 0xAB, 0x46, 0xA0, 0xD8, 0xAB, 0x46, 0xFB, 0x1F, 0xAB, 0x46, 0x00, 0xF4, + 0xCD, 0x81, 0xAB, 0x46, 0x00, 0xF4, 0xF3, 0x02, 0x2D, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0x2A, 0x61, + 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x58, 0xFB, 0x04, 0x64, 0x03, 0xFA, + 0x67, 0x44, 0x2C, 0xFA, 0x2D, 0xFA, 0x2E, 0xFA, 0x32, 0xFA, 0x33, 0xFA, 0x34, 0xFA, 0x12, 0x60, + 0x80, 0x64, 0x88, 0xF1, 0x0E, 0xFA, 0x07, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x11, 0x60, 0xD8, 0x63, + 0xA3, 0xDB, 0x06, 0xA3, 0x10, 0x60, 0x08, 0x64, 0xBD, 0xDB, 0x04, 0x64, 0xBD, 0xDB, 0x06, 0x64, + 0xA3, 0xDB, 0x10, 0x60, 0x06, 0x62, 0xEA, 0x60, 0x08, 0x64, 0xA2, 0xDB, 0x11, 0x60, 0xE4, 0x63, + 0x00, 0x64, 0xA3, 0xDB, 0x06, 0xA3, 0x10, 0x60, 0x0C, 0x64, 0xBD, 0xDB, 0x08, 0x64, 0xBD, 0xDB, + 0x06, 0x64, 0xA3, 0xDB, 0x10, 0x60, 0x0A, 0x62, 0xEA, 0x60, 0x12, 0x64, 0xA2, 0xDB, 0x0F, 0x60, + 0xFC, 0x62, 0xE9, 0x60, 0xF2, 0x64, 0xA2, 0xDB, 0x00, 0x64, 0x25, 0x60, 0x2A, 0x62, 0xA2, 0xDB, + 0x2F, 0x58, 0xFF, 0xFF, 0x58, 0xF5, 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, + 0x31, 0xF8, 0xAC, 0xF1, 0x19, 0xF8, 0xEA, 0x60, 0x58, 0x4E, 0x1C, 0x78, 0xFF, 0xFF, 0x30, 0x64, + 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xE2, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x16, 0x60, 0xCC, 0x61, + 0xA1, 0xD3, 0xFF, 0xFF, 0x59, 0x18, 0x58, 0xF5, 0x40, 0x64, 0x2A, 0xFA, 0x52, 0xF3, 0x00, 0xF4, + 0x60, 0x43, 0xBD, 0xD1, 0x04, 0x65, 0x64, 0x47, 0xA5, 0xDA, 0x64, 0x41, 0xDD, 0x81, 0xE9, 0x81, + 0x62, 0x44, 0x04, 0x03, 0xBD, 0xD1, 0xCD, 0x81, 0x58, 0xD8, 0xFC, 0x02, 0x58, 0x8B, 0x21, 0x60, + 0x8E, 0x63, 0xA3, 0xD1, 0x2B, 0x44, 0xC8, 0x84, 0x64, 0x41, 0xFF, 0xB1, 0x61, 0x45, 0x03, 0xA1, + 0xE9, 0x81, 0x41, 0x4C, 0xBD, 0xD1, 0xCD, 0x81, 0x58, 0xD8, 0xFC, 0x02, 0x2B, 0xD2, 0x2B, 0x43, + 0x60, 0x47, 0x01, 0x7E, 0x52, 0xF1, 0xA3, 0xDA, 0xA4, 0xD3, 0xCB, 0x83, 0x44, 0x8B, 0xF8, 0x84, + 0x2C, 0x41, 0x0C, 0x04, 0xBE, 0xD2, 0xFF, 0xFF, 0x60, 0x47, 0xBE, 0xDA, 0x00, 0x7E, 0xA3, 0xD2, + 0x60, 0x45, 0x00, 0x7F, 0xB4, 0x84, 0xCD, 0x81, 0xBD, 0xDA, 0xF4, 0x02, 0x58, 0xF5, 0x2B, 0x44, + 0x04, 0xA4, 0x3F, 0xFA, 0x65, 0xF3, 0x64, 0xFB, 0x16, 0x60, 0xCE, 0x61, 0x01, 0x64, 0x52, 0xF1, + 0xA1, 0xDB, 0x65, 0xFB, 0xA4, 0xD3, 0x04, 0x65, 0x51, 0xF3, 0x01, 0x18, 0x0C, 0x65, 0xF3, 0xB4, + 0xB4, 0x84, 0x51, 0xFB, 0x02, 0xB0, 0xFF, 0xFF, 0x16, 0x03, 0x65, 0xF3, 0xFF, 0xFF, 0x60, 0x47, + 0x0F, 0xB4, 0x65, 0xFB, 0x01, 0x03, 0x0F, 0x00, 0xE9, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0x51, 0xF1, + 0x65, 0xF3, 0x64, 0x40, 0x02, 0x26, 0xF8, 0x01, 0xF3, 0xA0, 0x04, 0xA4, 0x01, 0x04, 0xF1, 0xA4, + 0x10, 0x36, 0xF2, 0x01, 0x65, 0xFB, 0x65, 0xF3, 0x16, 0x60, 0xCC, 0x61, 0xA1, 0xD1, 0xCC, 0x84, + 0x01, 0x61, 0x08, 0x24, 0x03, 0x00, 0xE1, 0x81, 0xCC, 0x84, 0xFB, 0x01, 0xA1, 0x84, 0x51, 0xF1, + 0xE7, 0x03, 0x16, 0x60, 0xCE, 0x61, 0xA1, 0xDB, 0x00, 0x00, 0x65, 0xF3, 0x01, 0x61, 0xCC, 0x84, + 0xFF, 0xFF, 0x02, 0x03, 0xE1, 0x81, 0xFB, 0x01, 0x9A, 0xF3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, + 0xD7, 0x03, 0x31, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xE2, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xE4, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xE8, 0x60, + 0x95, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x65, 0xF1, 0x1C, 0x60, 0x00, 0x62, + 0xA2, 0xD9, 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xE4, 0x62, 0x20, 0x60, + 0x00, 0x64, 0xA2, 0xDB, 0xE8, 0x60, 0xC8, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0xBE, 0xFE, 0x0F, 0x60, 0xCE, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x0F, 0x60, 0xE2, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x58, 0xF5, 0x1B, 0x60, 0xDA, 0x62, + 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0x00, 0x64, 0x4F, 0xFB, 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x60, 0x01, 0x64, 0xA2, 0xDB, + 0xE8, 0x60, 0xF2, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, 0x33, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x2F, 0x58, 0xFF, 0xFF, 0x34, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xE2, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0xA6, 0xF1, 0x11, 0x60, 0xDC, 0x62, 0xA2, 0xD9, 0x1C, 0x60, 0x10, 0x62, 0x11, 0x60, + 0xD8, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xA7, 0xF1, 0x11, 0x60, + 0xE8, 0x62, 0xA2, 0xD9, 0x1C, 0x60, 0x0E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xFD, 0x1B, 0x1C, 0x60, + 0x10, 0x62, 0x11, 0x60, 0xE4, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x60, 0x08, 0x64, 0xA2, 0xDB, 0xE9, 0x60, 0x23, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x4F, 0xF1, 0x0F, 0x60, 0xE2, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x64, 0x40, 0xFF, 0x26, 0x03, 0x00, 0xE8, 0x60, 0x77, 0x78, 0xFF, 0xFF, 0x02, 0x0A, 0x00, 0x64, + 0x4F, 0xFB, 0xA8, 0xF1, 0x11, 0x60, 0xE8, 0x62, 0xA2, 0xD9, 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x60, + 0x0C, 0x64, 0xA2, 0xDB, 0xE9, 0x60, 0x49, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x1C, 0x60, 0x10, 0x62, + 0x11, 0x60, 0xE4, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x2F, 0x58, + 0xFF, 0xFF, 0x0F, 0x60, 0xE2, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x0C, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x10, 0x62, 0x11, 0x60, 0xE4, 0x64, 0xA2, 0xDB, + 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x14, 0x00, 0xFF, 0x60, 0xF7, 0x64, 0xA0, 0x84, + 0xA2, 0xDB, 0x4F, 0xF3, 0xDB, 0x0A, 0x00, 0xA0, 0x00, 0x64, 0x02, 0x03, 0x4F, 0xFB, 0xD6, 0x01, + 0x1C, 0x60, 0x10, 0x62, 0x11, 0x60, 0xD8, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0xE8, 0x60, 0x77, 0x78, 0xFF, 0xFF, 0x35, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x1C, 0x60, + 0x10, 0x62, 0x11, 0x60, 0xD8, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0x51, 0xF3, 0xFF, 0xFF, 0xE3, 0xB4, 0x51, 0xFB, 0x16, 0x60, 0xCA, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, + 0xFE, 0xB4, 0xA2, 0xDB, 0x00, 0x64, 0x25, 0x60, 0x2A, 0x62, 0xA2, 0xDB, 0x0F, 0x60, 0xE2, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0E, 0x04, 0x32, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, + 0xE4, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xE9, 0x60, 0x8E, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x64, 0xF1, 0x65, 0xF9, 0x1C, 0x60, 0x00, 0x62, 0xA2, 0xD9, 0x1E, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xE4, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, + 0xE9, 0x60, 0xB6, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x0F, 0x60, + 0xCE, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, + 0xCE, 0x62, 0xA2, 0xD1, 0x10, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x60, + 0x04, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x23, 0xFA, 0xF1, 0x60, + 0x02, 0x64, 0x24, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xCA, 0x64, 0xA2, 0xDB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0xEA, 0x60, 0x58, 0x4E, + 0x2E, 0x78, 0xFF, 0xFF, 0x20, 0x44, 0x01, 0xB5, 0x54, 0x80, 0x31, 0x44, 0xDE, 0xB4, 0x40, 0x51, + 0x0F, 0x60, 0xE2, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x3E, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x2F, 0x58, 0xFF, 0xFF, 0x3F, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x1C, 0x60, 0x10, 0x62, 0x11, 0x60, + 0xD8, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x51, 0xFB, + 0x0F, 0x60, 0xE2, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0xBE, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x0F, 0x60, 0xE2, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xE2, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x66, 0x01, 0x60, 0x7A, 0x61, 0x16, 0x60, + 0xC4, 0x63, 0xA1, 0xD3, 0xFF, 0xFF, 0x20, 0x7F, 0xBD, 0xDB, 0x21, 0x60, 0x32, 0x64, 0xBD, 0xDB, + 0x04, 0xA1, 0xA1, 0xD3, 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x10, 0x00, 0x01, 0x60, 0x7A, 0x61, + 0x16, 0x60, 0xC4, 0x63, 0xA1, 0xD3, 0x00, 0x66, 0x20, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, + 0x21, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x0F, 0x60, 0xE2, 0x62, + 0xA2, 0xD1, 0x9F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, + 0xE4, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xEA, 0x60, 0x3E, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0x00, 0x62, 0x16, 0x60, 0xC2, 0x64, 0xA2, 0xDB, 0x20, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xE4, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, + 0xEA, 0x60, 0x66, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xE2, 0x62, + 0xA2, 0xD1, 0x9F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xCE, 0x62, + 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, + 0x5F, 0xFB, 0xAC, 0x85, 0x60, 0x41, 0x20, 0x03, 0x01, 0x60, 0x00, 0x63, 0x08, 0x64, 0xE9, 0x81, + 0xCC, 0x84, 0x02, 0x24, 0xDF, 0x83, 0xFB, 0x02, 0x21, 0x60, 0x8E, 0x64, 0xA0, 0xDD, 0x65, 0x41, + 0x21, 0x60, 0x90, 0x63, 0x0F, 0x60, 0xC0, 0x64, 0xE9, 0x81, 0x58, 0xD1, 0xFD, 0x04, 0xA3, 0xD9, + 0x0B, 0x03, 0x58, 0xD1, 0xE9, 0x81, 0x60, 0x45, 0xFC, 0x04, 0xA3, 0xD1, 0x64, 0x47, 0xB0, 0x84, + 0xBD, 0xDB, 0x00, 0xB9, 0x65, 0x44, 0xF0, 0x02, 0x20, 0x60, 0x38, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, + 0x01, 0xA8, 0x01, 0x60, 0x70, 0x62, 0x06, 0x02, 0xA2, 0xD3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, + 0x01, 0x03, 0x02, 0x64, 0x60, 0x41, 0x21, 0x60, 0x8E, 0x63, 0xBD, 0xD3, 0xA3, 0xD3, 0xFF, 0xB5, + 0x80, 0xBF, 0xCD, 0x81, 0x65, 0x5C, 0x0F, 0x03, 0x80, 0xBF, 0xBD, 0xDB, 0x65, 0x44, 0xC8, 0x84, + 0xFF, 0xFF, 0x0C, 0x03, 0x60, 0x45, 0xCD, 0x81, 0xA3, 0xD3, 0x08, 0x03, 0x80, 0xBF, 0xCD, 0x81, + 0xFF, 0xFF, 0x01, 0x03, 0x80, 0xBC, 0x60, 0x47, 0xBD, 0xDB, 0x00, 0x65, 0x64, 0x41, 0x21, 0x60, + 0x90, 0x63, 0xBD, 0xD3, 0xFF, 0xFF, 0x80, 0xB0, 0xFF, 0xFF, 0x01, 0x03, 0x60, 0x45, 0x60, 0x47, + 0x80, 0xB0, 0xFF, 0xFF, 0x01, 0x03, 0x60, 0x45, 0xCD, 0x81, 0xFF, 0xFF, 0xF2, 0x02, 0x65, 0x44, + 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, 0x0A, 0x64, 0x15, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x14, 0x64, + 0x11, 0x00, 0x0A, 0x3A, 0x02, 0x00, 0x32, 0x64, 0x0D, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x37, 0x64, + 0x09, 0x00, 0x10, 0x3A, 0x02, 0x00, 0x50, 0x64, 0x05, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x6E, 0x64, + 0x01, 0x00, 0x14, 0x64, 0x62, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x3C, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x31, 0x40, 0x20, 0x2A, 0x18, 0x00, 0x3F, 0xF2, 0x47, 0x65, 0xC4, 0x84, 0xE8, 0x84, 0x23, 0xFA, + 0xF1, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xCA, 0x64, 0xA2, 0xDB, + 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x00, 0x66, + 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x0C, 0x63, 0x12, 0x60, + 0xB6, 0x62, 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0x53, 0xFB, 0x54, 0xFB, 0x12, 0x60, 0xBA, 0x63, + 0x02, 0x64, 0xA3, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0x12, 0x60, 0xBE, 0x62, 0xA2, 0xD3, 0x00, 0x63, + 0xF0, 0xA0, 0x01, 0xA4, 0x03, 0x03, 0xA2, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0xA2, 0xDD, 0x12, 0x60, + 0xC0, 0x62, 0xA2, 0xD1, 0xA2, 0xDD, 0x5A, 0xD3, 0xA2, 0xDD, 0xC0, 0x81, 0x61, 0x44, 0x02, 0x24, + 0xFF, 0xFF, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0x5A, 0xD3, 0xE9, 0x81, 0xE8, 0x83, + 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x85, 0xD4, 0x85, 0xC5, 0x83, 0xA2, 0xDD, 0x12, 0x60, + 0xB8, 0x62, 0x63, 0x47, 0x00, 0x7F, 0xA2, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0x03, 0xE1, 0xA3, 0xFF, + 0x1B, 0x60, 0x5A, 0x63, 0x17, 0xFD, 0xAE, 0xFF, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, 0x7F, 0x67, + 0x01, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0xB1, 0xFE, 0x05, 0x05, 0xB0, 0xFE, 0x06, 0x05, 0xB2, 0xFE, + 0xB3, 0xFE, 0x22, 0x00, 0xF0, 0x60, 0xFA, 0x78, 0xFF, 0xFF, 0x28, 0xF3, 0x29, 0xF1, 0x40, 0x44, + 0x44, 0x45, 0x2A, 0xF1, 0x2B, 0xF1, 0x44, 0x46, 0x44, 0x47, 0x3F, 0xB4, 0xE0, 0x85, 0x16, 0x60, + 0xD2, 0x64, 0x44, 0xD7, 0x58, 0x43, 0xFF, 0xFF, 0x60, 0x45, 0x12, 0x60, 0xC8, 0x7C, 0xA4, 0xD3, + 0x61, 0x43, 0x04, 0xB4, 0x24, 0x44, 0x02, 0x03, 0x13, 0xFF, 0x06, 0x00, 0x3F, 0xB4, 0xB4, 0x84, + 0xFF, 0x27, 0x05, 0xFD, 0x04, 0xFB, 0x10, 0x75, 0xA1, 0xFF, 0xFF, 0xFF, 0x86, 0x3E, 0xB4, 0xFE, + 0x09, 0x05, 0xB5, 0xFE, 0x02, 0x24, 0x80, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0xFE, 0x05, 0x05, + 0xB6, 0xFE, 0xF2, 0x01, 0xF1, 0x60, 0x35, 0x78, 0xFF, 0xFF, 0x36, 0x44, 0x00, 0x7F, 0xF4, 0xA0, + 0x60, 0x45, 0x05, 0x05, 0x17, 0x60, 0x5E, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xE4, 0x01, + 0xE3, 0x01, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x10, 0x02, + 0x10, 0x64, 0x40, 0x40, 0x02, 0x64, 0x40, 0x50, 0x61, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x04, 0x00, + 0x10, 0xE0, 0x46, 0x60, 0x09, 0xE0, 0x00, 0x00, 0x27, 0xF1, 0x00, 0x66, 0x20, 0x78, 0x42, 0xFE, + 0x23, 0x58, 0xFF, 0xFF, 0x78, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, + 0x1C, 0x02, 0x12, 0x60, 0xC8, 0x63, 0xA3, 0xD3, 0x07, 0x7C, 0x20, 0xB5, 0x0C, 0xB5, 0x04, 0x03, + 0x03, 0x02, 0xBC, 0xF9, 0x00, 0x67, 0x11, 0x00, 0x00, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0xB4, 0x01, + 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x06, 0x00, 0x04, 0x7C, + 0xBC, 0xF9, 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x78, 0x60, + 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x31, 0x02, 0x12, 0x60, 0xC8, 0x63, + 0xA3, 0xD3, 0x01, 0x7C, 0x20, 0xB5, 0x0C, 0xB5, 0x03, 0x03, 0x02, 0x02, 0xBC, 0xF9, 0xFF, 0xFF, + 0x02, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, 0x7E, 0xF1, 0x20, 0x44, + 0x64, 0x40, 0xFF, 0x26, 0x1B, 0x00, 0x7F, 0xB4, 0x40, 0x40, 0x5C, 0x5E, 0x82, 0xFF, 0x26, 0x44, + 0xFD, 0xB4, 0x40, 0x46, 0x5C, 0x41, 0x87, 0xFF, 0x62, 0xFF, 0x00, 0x63, 0x1B, 0x60, 0xC4, 0x62, + 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x04, 0x03, 0x09, 0xF2, 0x0F, 0xFC, 0xAC, 0x86, + 0xFB, 0x01, 0x1C, 0x60, 0x04, 0x62, 0x06, 0x64, 0xA2, 0xDB, 0x2D, 0xFF, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x25, 0x46, 0x01, 0xF2, 0x08, 0xF0, 0x60, 0x47, 0x03, 0xB4, 0x03, 0xAC, 0x7F, 0x67, + 0x03, 0x61, 0x08, 0x02, 0x1B, 0x60, 0xE0, 0x64, 0x40, 0x4B, 0xF0, 0x60, 0x58, 0x4D, 0x75, 0x78, + 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x24, 0x40, 0x01, 0x2B, 0x49, 0x00, 0x25, 0x44, + 0x1F, 0xB4, 0xE0, 0x85, 0xEC, 0x60, 0x36, 0x64, 0xC4, 0x98, 0xFF, 0xFF, 0xC0, 0xFE, 0x3D, 0x00, + 0xC1, 0xFE, 0x3B, 0x00, 0xC2, 0xFE, 0x39, 0x00, 0xC3, 0xFE, 0x37, 0x00, 0xC4, 0xFE, 0x35, 0x00, + 0xC5, 0xFE, 0x33, 0x00, 0xC6, 0xFE, 0x31, 0x00, 0xC7, 0xFE, 0x2F, 0x00, 0xC8, 0xFE, 0x2D, 0x00, + 0xC9, 0xFE, 0x2B, 0x00, 0xCA, 0xFE, 0x29, 0x00, 0xCB, 0xFE, 0x27, 0x00, 0xCC, 0xFE, 0x25, 0x00, + 0xCD, 0xFE, 0x23, 0x00, 0xCE, 0xFE, 0x21, 0x00, 0xCF, 0xFE, 0x1F, 0x00, 0xD0, 0xFE, 0x1D, 0x00, + 0xD1, 0xFE, 0x1B, 0x00, 0xD2, 0xFE, 0x19, 0x00, 0xD3, 0xFE, 0x17, 0x00, 0xD4, 0xFE, 0x15, 0x00, + 0xD5, 0xFE, 0x13, 0x00, 0xD6, 0xFE, 0x11, 0x00, 0xD7, 0xFE, 0x0F, 0x00, 0xD8, 0xFE, 0x0D, 0x00, + 0xD9, 0xFE, 0x0B, 0x00, 0xDA, 0xFE, 0x09, 0x00, 0xDB, 0xFE, 0x07, 0x00, 0xDC, 0xFE, 0x05, 0x00, + 0xDD, 0xFE, 0x03, 0x00, 0xDE, 0xFE, 0x01, 0x00, 0xDF, 0xFE, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x00, 0x64, 0x9F, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9D, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x9C, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x9A, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x99, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x98, 0xFE, 0xF0, 0x84, + 0xFF, 0xFF, 0x97, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x96, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x95, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x94, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x93, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x92, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x91, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x90, 0xFE, 0xF0, 0x84, + 0x06, 0xFB, 0x8F, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8D, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x8C, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x8A, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x89, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x88, 0xFE, 0xF0, 0x84, + 0xFF, 0xFF, 0x87, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x86, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x85, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x84, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x83, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x82, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x81, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x80, 0xFE, 0xF0, 0x84, + 0x05, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x5C, 0x5C, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x24, 0x40, 0x01, 0x27, 0x55, 0x00, 0x05, 0x60, 0x00, 0x63, 0x05, 0xFD, 0x30, 0x44, 0xBD, 0xDB, + 0x31, 0x44, 0xBD, 0xDB, 0x32, 0x44, 0xBD, 0xDB, 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, + 0x35, 0x44, 0xBD, 0xDB, 0x36, 0x44, 0xBD, 0xDB, 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, + 0x39, 0x44, 0xBD, 0xDB, 0x3A, 0x44, 0xBD, 0xDB, 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, + 0x3D, 0x44, 0xBD, 0xDB, 0x3E, 0x44, 0xBD, 0xDB, 0x3F, 0x44, 0xBD, 0xDB, 0x02, 0x61, 0x61, 0x44, + 0x02, 0x36, 0x82, 0xFF, 0x03, 0x36, 0x83, 0xFF, 0x04, 0x36, 0x84, 0xFF, 0x05, 0x36, 0x85, 0xFF, + 0x06, 0x36, 0x86, 0xFF, 0x07, 0x36, 0x87, 0xFF, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, + 0x22, 0x44, 0xBD, 0xDB, 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, + 0x26, 0x44, 0xBD, 0xDB, 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, + 0x2A, 0x44, 0xBD, 0xDB, 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, + 0x2E, 0x44, 0xBD, 0xDB, 0x2F, 0x44, 0xBD, 0xDB, 0xDD, 0x81, 0x08, 0x3A, 0xD0, 0x01, 0x54, 0x00, + 0x27, 0x40, 0x10, 0x26, 0x30, 0x00, 0x26, 0x44, 0x01, 0x36, 0x2D, 0x00, 0x02, 0x36, 0x82, 0xFF, + 0x03, 0x36, 0x83, 0xFF, 0x04, 0x36, 0x84, 0xFF, 0x05, 0x36, 0x85, 0xFF, 0x06, 0x36, 0x86, 0xFF, + 0x25, 0x44, 0x00, 0x36, 0x44, 0x40, 0x01, 0x36, 0x44, 0x41, 0x02, 0x36, 0x44, 0x42, 0x03, 0x36, + 0x44, 0x43, 0x04, 0x36, 0x44, 0x44, 0x05, 0x36, 0x44, 0x45, 0x06, 0x36, 0x44, 0x46, 0x07, 0x36, + 0x44, 0x47, 0x08, 0x36, 0x44, 0x48, 0x09, 0x36, 0x44, 0x49, 0x0A, 0x36, 0x44, 0x4A, 0x0B, 0x36, + 0x44, 0x4B, 0x0C, 0x36, 0x44, 0x4C, 0x0D, 0x36, 0x44, 0x4D, 0x0E, 0x36, 0x44, 0x4E, 0x0F, 0x36, + 0x44, 0x4F, 0x87, 0xFF, 0x21, 0x00, 0x25, 0x44, 0x10, 0x36, 0x44, 0x50, 0x11, 0x36, 0x44, 0x51, + 0x12, 0x36, 0x44, 0x52, 0x13, 0x36, 0x44, 0x53, 0x14, 0x36, 0x44, 0x54, 0x15, 0x36, 0x44, 0x55, + 0x16, 0x36, 0x44, 0x56, 0x17, 0x36, 0x44, 0x57, 0x18, 0x36, 0x44, 0x58, 0x19, 0x36, 0x44, 0x59, + 0x1A, 0x36, 0x44, 0x5A, 0x1B, 0x36, 0x44, 0x5B, 0x1C, 0x36, 0x44, 0x5C, 0x1D, 0x36, 0x44, 0x5D, + 0x1E, 0x36, 0x44, 0x5E, 0x1F, 0x36, 0x44, 0x5F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0x46, + 0xB3, 0x60, 0x58, 0x4F, 0x22, 0x78, 0xFF, 0xFF, 0x03, 0x61, 0x7F, 0x67, 0x0B, 0x02, 0x00, 0xF0, + 0x1B, 0x60, 0xE0, 0x62, 0x04, 0x64, 0xA2, 0xDB, 0x5A, 0xD9, 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, + 0x7F, 0x67, 0x02, 0x61, 0x11, 0x02, 0x1C, 0x60, 0x04, 0x62, 0x1A, 0x64, 0xA2, 0xDB, 0x00, 0x60, + 0x50, 0x63, 0x5A, 0xDD, 0xED, 0x60, 0xB9, 0x64, 0x80, 0xFB, 0x2D, 0xFF, 0xEB, 0x60, 0x84, 0x78, + 0xFF, 0xFF, 0x2A, 0xF3, 0x05, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, 0xC0, 0x64, + 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x0F, 0x02, 0x1C, 0x60, 0x04, 0x62, 0x1C, 0x64, + 0xA2, 0xDB, 0x00, 0x60, 0x50, 0x63, 0x5A, 0xDD, 0xED, 0x60, 0xD3, 0x64, 0x80, 0xFB, 0x2D, 0xFF, + 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, + 0x24, 0x45, 0xA4, 0x80, 0x02, 0x61, 0x34, 0x02, 0x25, 0x45, 0x20, 0x44, 0x80, 0x2A, 0x35, 0x00, + 0xF1, 0x60, 0x00, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x01, 0x03, 0x29, 0x00, 0x21, 0x60, 0x74, 0x62, + 0xA2, 0xD1, 0x9A, 0xF3, 0x16, 0x60, 0xCC, 0x61, 0xA0, 0x84, 0xA1, 0xDB, 0x25, 0x45, 0x1B, 0x60, + 0x52, 0x63, 0x01, 0x61, 0xBD, 0xD3, 0xBD, 0xD1, 0xD4, 0x80, 0xBD, 0xD3, 0xBD, 0xD5, 0xCD, 0x81, + 0x02, 0x03, 0x15, 0x03, 0xF7, 0x01, 0xA2, 0xFF, 0xA6, 0xD3, 0x40, 0x4C, 0x00, 0xA8, 0x67, 0x43, + 0x0C, 0x02, 0xA2, 0xDD, 0x42, 0x48, 0x64, 0x41, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, + 0x66, 0x44, 0x28, 0xDB, 0x02, 0x03, 0x2C, 0x58, 0xA3, 0xFF, 0x0C, 0x61, 0x03, 0x00, 0x04, 0x61, + 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xF1, 0x60, 0x02, 0x64, 0xD4, 0x80, + 0x7F, 0x67, 0x06, 0x63, 0xF8, 0x02, 0x31, 0x40, 0x20, 0x26, 0xF5, 0x01, 0x21, 0x60, 0x74, 0x62, + 0xA2, 0xD1, 0x9A, 0xF3, 0x16, 0x60, 0xCC, 0x61, 0xA0, 0x84, 0xA1, 0xDB, 0x16, 0x60, 0xD0, 0x61, + 0x01, 0x64, 0xA1, 0xDB, 0xFF, 0xFF, 0xC4, 0xFE, 0xE5, 0x01, 0xC6, 0xFE, 0xE3, 0x01, 0x7E, 0x60, + 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x02, 0x61, 0x3F, 0x02, 0x25, 0x45, 0xF8, 0x2B, 0x3B, 0x00, + 0x2E, 0xF5, 0x67, 0x44, 0xD4, 0x80, 0x17, 0x60, 0x6A, 0x63, 0x39, 0x03, 0x64, 0x61, 0x24, 0x44, + 0x01, 0x27, 0x29, 0x00, 0xA3, 0xFC, 0xA4, 0xF8, 0xBD, 0xD3, 0xA3, 0xD1, 0xD4, 0x80, 0xCD, 0x81, + 0x08, 0x24, 0x64, 0x58, 0x08, 0xA3, 0xF8, 0x02, 0x08, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xA3, 0xD1, + 0xFE, 0xA0, 0xFA, 0x60, 0x00, 0x64, 0xD0, 0x80, 0x14, 0x02, 0x13, 0x02, 0x04, 0xA3, 0xBE, 0xD3, + 0xBD, 0xD1, 0x0F, 0x18, 0xD4, 0x80, 0x0D, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, + 0x64, 0x41, 0xDD, 0x81, 0xE1, 0x81, 0xCB, 0x83, 0x46, 0x65, 0xF2, 0x60, 0x58, 0x4F, 0x4A, 0x78, + 0xFF, 0xFF, 0x00, 0x67, 0x0A, 0x00, 0xBD, 0xD3, 0xBE, 0xD1, 0xD4, 0x80, 0xCD, 0x81, 0x08, 0x24, + 0x64, 0x58, 0x08, 0xA3, 0xF8, 0x02, 0x04, 0x61, 0x7F, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x0F, 0x64, + 0x23, 0xFA, 0x67, 0x44, 0x24, 0xFA, 0x62, 0x41, 0x3E, 0x60, 0x00, 0x65, 0x1A, 0x63, 0xEA, 0x60, + 0x88, 0x64, 0x65, 0x46, 0x58, 0xD0, 0x2E, 0xF5, 0x59, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x4B, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0xE8, 0x84, 0xDC, 0x84, 0x23, 0xFA, 0xBF, 0xD1, + 0x4A, 0x65, 0x64, 0x43, 0xF2, 0x60, 0x58, 0x4F, 0x4A, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xE0, 0xA0, 0x20, 0x64, 0x01, 0x06, 0x25, 0xFA, 0x23, 0xF2, + 0xDF, 0xD1, 0xCC, 0x84, 0xE0, 0x85, 0x0B, 0x06, 0xBF, 0xD1, 0x64, 0x41, 0xD5, 0x80, 0x64, 0x43, + 0x01, 0x06, 0x65, 0x41, 0x4A, 0x65, 0xEF, 0x60, 0x58, 0x4F, 0x87, 0x78, 0xFF, 0xFF, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0xBC, 0xF3, 0x02, 0x63, 0x23, 0xFC, 0x07, 0xB4, 0x25, 0xFA, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x4B, 0xD3, 0xBF, 0xD3, 0x60, 0x41, 0xC9, 0x83, 0xE9, 0x81, 0xDD, 0x81, + 0xA3, 0xFA, 0xE0, 0x81, 0x3C, 0x60, 0x00, 0x67, 0x02, 0x24, 0x02, 0xA4, 0x60, 0x47, 0x40, 0x4B, + 0xC9, 0x81, 0x4A, 0x65, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, + 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF6, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, + 0xA3, 0xD1, 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, 0x60, 0x47, 0x25, 0xFA, 0x00, 0x7E, 0x60, 0x47, + 0x01, 0x26, 0xDC, 0x84, 0x60, 0x41, 0xE8, 0x84, 0xD8, 0x84, 0x23, 0xFA, 0xAB, 0x01, 0xFC, 0xA3, + 0xA3, 0xD1, 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, 0x00, 0x7F, 0x25, 0xFA, 0x60, 0x41, 0x01, 0x26, + 0xDD, 0x81, 0xE9, 0x84, 0xD8, 0x84, 0x23, 0xFA, 0x9D, 0x01, 0x23, 0xF2, 0x12, 0x60, 0xB8, 0x65, + 0x60, 0x41, 0x12, 0x60, 0x54, 0x63, 0xA3, 0xDB, 0xFF, 0xA1, 0x48, 0x64, 0x58, 0xD0, 0x7E, 0xA8, + 0x5B, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xFF, 0xA1, 0xD7, 0x80, 0x02, 0x03, 0x01, 0x03, + 0xF5, 0x01, 0x2E, 0xF5, 0x00, 0x60, 0x2F, 0x65, 0x25, 0xF2, 0x00, 0x63, 0xCC, 0x84, 0x03, 0xA3, + 0xFD, 0x05, 0x4A, 0x64, 0xD7, 0x80, 0x11, 0x60, 0xF0, 0x61, 0x2F, 0x05, 0xA1, 0xDD, 0xE3, 0x83, + 0xFE, 0xA3, 0x58, 0xD0, 0x7E, 0xA8, 0x59, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, + 0x00, 0x63, 0x59, 0xDD, 0x2E, 0xF5, 0x11, 0x60, 0xF0, 0x64, 0x25, 0xF0, 0xA0, 0xD3, 0xD3, 0x80, + 0x01, 0xB0, 0x04, 0x03, 0x01, 0xA4, 0x03, 0x03, 0xA2, 0xDB, 0x01, 0x00, 0xA2, 0xDD, 0x11, 0x60, + 0xF8, 0x63, 0x10, 0x60, 0x0A, 0x65, 0xBD, 0xD3, 0xBD, 0xD1, 0xE0, 0x84, 0xC4, 0x82, 0x10, 0x60, + 0x2A, 0x65, 0x07, 0x64, 0x64, 0x41, 0x5A, 0xDB, 0xD6, 0x80, 0xCD, 0x81, 0x06, 0x03, 0xFB, 0x02, + 0x25, 0xF2, 0x02, 0xA3, 0xCC, 0x84, 0xA2, 0xDA, 0xEC, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x12, 0x60, 0x54, 0x61, 0xA1, 0xD3, 0x23, 0xFA, 0xE0, 0x83, 0x4A, 0x65, 0x04, 0x02, 0x02, 0x63, + 0x23, 0xFC, 0xA5, 0xFC, 0x09, 0x00, 0xDB, 0x83, 0x59, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, + 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x11, 0x60, + 0xF0, 0x62, 0xA2, 0xD3, 0x00, 0x61, 0x02, 0xA4, 0xFE, 0xA0, 0x23, 0xFA, 0x1B, 0x03, 0xFA, 0xA4, + 0xFD, 0xA4, 0x01, 0xA1, 0xFD, 0x07, 0x61, 0x43, 0x23, 0xF2, 0x25, 0xFC, 0xE0, 0x83, 0x02, 0xA3, + 0x11, 0x60, 0xF0, 0x61, 0x00, 0x60, 0x4A, 0x64, 0x59, 0xD1, 0x58, 0xD8, 0x7E, 0x3A, 0x02, 0x00, + 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x25, 0xF2, 0x23, 0xF2, 0x01, 0xB0, 0xCC, 0x84, 0x04, 0x02, + 0x23, 0xFA, 0x02, 0x00, 0x00, 0x64, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x41, 0x4B, + 0x65, 0x42, 0x80, 0x64, 0xD4, 0x85, 0x2B, 0x41, 0x00, 0xA1, 0x55, 0x8B, 0x0D, 0x03, 0x02, 0x04, + 0x65, 0x41, 0x02, 0x00, 0x00, 0x64, 0x40, 0x4B, 0xCA, 0x84, 0x58, 0xD0, 0xC9, 0x81, 0xBD, 0xD9, + 0xFC, 0x02, 0x00, 0xF4, 0x04, 0x65, 0xEC, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD3, + 0x02, 0x7C, 0xA0, 0xD3, 0x23, 0xF8, 0xDC, 0x84, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x02, 0x64, 0x23, 0xFA, 0x01, 0x64, 0x9D, 0xFE, 0x02, 0x28, 0x02, 0x64, 0x25, 0xFA, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x21, 0x60, 0x80, 0x62, 0xA2, 0xD3, 0x02, 0x7C, 0x23, 0xF8, 0x01, 0xB4, + 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD1, 0x02, 0x64, 0x23, 0xFA, + 0x64, 0x44, 0x7C, 0x5F, 0x60, 0x45, 0x64, 0x47, 0x7C, 0x5F, 0x89, 0xF1, 0x66, 0x41, 0xC0, 0x86, + 0xA5, 0xD2, 0x61, 0x46, 0x00, 0x63, 0x60, 0x40, 0x0A, 0x37, 0x01, 0x63, 0x14, 0x37, 0x02, 0x63, + 0x37, 0x37, 0x06, 0x63, 0x6E, 0x37, 0x0B, 0x63, 0x25, 0xFC, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x02, 0x64, 0x23, 0xFA, 0x88, 0xFF, 0x75, 0x44, 0x8D, 0xFF, 0xE8, 0x87, 0xE8, 0x84, 0xE8, 0x84, + 0x03, 0xB4, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF0, 0x21, 0x60, 0x7C, 0x65, + 0x23, 0xF2, 0xA5, 0xD9, 0x02, 0xA8, 0x64, 0x44, 0x07, 0x02, 0x00, 0xBC, 0xF2, 0xA4, 0x04, 0x03, + 0x03, 0x07, 0x1F, 0x60, 0xAA, 0x62, 0xA2, 0xD9, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x20, 0x63, + 0x20, 0x60, 0x0A, 0x61, 0x48, 0x64, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x25, 0xF0, 0x20, 0x64, + 0xD0, 0x81, 0xFF, 0xFF, 0x02, 0x07, 0x25, 0xFA, 0x0F, 0x00, 0x20, 0x60, 0x0E, 0x63, 0xC3, 0x83, + 0x01, 0x2A, 0x06, 0x00, 0xCF, 0x83, 0xA3, 0xD3, 0xCD, 0x81, 0x00, 0x7F, 0xBD, 0xDB, 0x04, 0x03, + 0x00, 0x64, 0xC9, 0x81, 0xBD, 0xDB, 0xFD, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, + 0x25, 0xF0, 0x01, 0x60, 0x70, 0x63, 0xA3, 0xD9, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, + 0xA5, 0xF0, 0xA3, 0xD1, 0xFF, 0xFF, 0x64, 0x5E, 0x00, 0x7F, 0x60, 0x41, 0x64, 0x47, 0x7C, 0x5F, + 0x89, 0xF1, 0x66, 0x43, 0xC0, 0x86, 0x65, 0x44, 0xA1, 0xDA, 0x63, 0x46, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD1, 0xFF, 0xFF, 0x64, 0x5E, 0x00, 0x7F, 0x60, 0x45, 0x64, 0x47, + 0x7C, 0x5F, 0x89, 0xF1, 0x66, 0x41, 0xC0, 0x86, 0x65, 0x44, 0xA0, 0xD2, 0x61, 0x46, 0x25, 0xFA, + 0x02, 0x64, 0x23, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, + 0x00, 0x67, 0x02, 0x02, 0x2D, 0xF9, 0x2C, 0xF9, 0x23, 0x58, 0xFF, 0xFF, 0x1F, 0x60, 0xA8, 0x61, + 0x23, 0xF2, 0x25, 0xF2, 0x02, 0xA8, 0x00, 0xA8, 0x09, 0x02, 0x07, 0x03, 0xD0, 0xA0, 0x30, 0x65, + 0x03, 0x04, 0xA7, 0xA0, 0x59, 0x65, 0x01, 0x06, 0x65, 0x44, 0xA1, 0xDB, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x04, 0x61, 0x0A, 0x00, 0x25, 0x60, 0x2C, 0x61, 0x01, 0x64, 0xA1, 0xDB, 0x04, 0x00, + 0x25, 0x60, 0x2C, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x06, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0xEB, 0x60, + 0x84, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, 0x46, 0x45, 0x02, 0xF0, + 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0x00, 0xF4, 0x01, 0xF2, 0x66, 0x5C, 0x25, 0x46, 0x56, 0x02, + 0x70, 0x27, 0x54, 0x00, 0x12, 0x64, 0x03, 0xFA, 0x04, 0xF8, 0x0E, 0xF2, 0x87, 0xFC, 0x8D, 0xFC, + 0x8E, 0xFC, 0xDA, 0x82, 0x16, 0x61, 0x00, 0x63, 0xC9, 0x81, 0x5A, 0xDC, 0xFD, 0x02, 0x60, 0x40, + 0xF0, 0x3B, 0x16, 0x00, 0x32, 0x44, 0x8F, 0xF3, 0x01, 0xB0, 0xF6, 0xA0, 0x08, 0x24, 0x2C, 0x05, + 0xDC, 0x83, 0xF0, 0x67, 0x0E, 0xFA, 0x1B, 0x60, 0xC4, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0x8F, 0xFD, 0x2B, 0xFF, 0xFE, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x4F, 0x00, + 0x90, 0xF3, 0x0A, 0x65, 0xD4, 0x80, 0xDC, 0x83, 0x17, 0x05, 0x90, 0xFD, 0x98, 0xFE, 0x04, 0x04, + 0x00, 0x7F, 0x08, 0x7E, 0x0E, 0xFA, 0x3B, 0xFF, 0x1B, 0x60, 0xB8, 0x64, 0x2B, 0xDB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0x0E, 0xF2, 0x2B, 0xFF, 0x60, 0x40, 0x08, 0x26, 0xF7, 0xFE, + 0xFD, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x32, 0x00, 0x8C, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, 0xFF, 0xFF, + 0x0D, 0x04, 0x1B, 0x60, 0xD0, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xFC, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x21, 0x00, 0x46, 0x45, 0x00, 0x64, + 0x2B, 0xDB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA2, 0xFF, + 0x00, 0xF4, 0x01, 0xF0, 0x0A, 0x18, 0x70, 0x67, 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, 0xC0, 0x84, + 0x01, 0xFA, 0x25, 0x46, 0x25, 0x44, 0x80, 0xFC, 0x05, 0xFA, 0xB4, 0x60, 0x58, 0x4E, 0x48, 0x78, + 0xFF, 0xFF, 0xD4, 0xFE, 0xA3, 0xFF, 0xFF, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0xD4, 0xFE, 0xA3, 0xFF, + 0x2D, 0x58, 0xFF, 0xFF, 0x1B, 0x60, 0xBE, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x0D, 0x00, 0x1B, 0x60, + 0xB2, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x18, 0x00, 0x1B, 0x60, 0xCA, 0x64, 0x40, 0x47, 0x58, 0x4F, + 0x03, 0x00, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, 0x27, 0xD5, 0x0E, 0xF2, 0x0B, 0x18, 0x60, 0x40, + 0x01, 0x2A, 0x08, 0x00, 0x1B, 0x60, 0xE0, 0x64, 0x40, 0x4B, 0xF0, 0x60, 0x58, 0x4D, 0x75, 0x78, + 0xFF, 0xFF, 0xF2, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0xD5, 0x0E, 0xF2, 0x14, 0x18, 0x60, 0x40, + 0x01, 0x2A, 0x11, 0x00, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, 0x90, 0xF3, + 0x02, 0x02, 0xCC, 0x84, 0x90, 0xFB, 0x1B, 0x60, 0xE0, 0x64, 0x40, 0x4B, 0xF0, 0x60, 0x58, 0x4D, + 0x75, 0x78, 0xFF, 0xFF, 0xE9, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xFB, 0x64, 0x3A, 0x42, 0x4A, 0xDB, + 0xA2, 0xFF, 0x93, 0xF3, 0x8F, 0xF3, 0xCC, 0x80, 0xFA, 0xA0, 0x01, 0x14, 0x1E, 0x05, 0xB3, 0x60, + 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, 0x18, 0x03, 0xF0, 0x67, 0x0E, 0xFA, 0x1B, 0x60, + 0xE0, 0x62, 0x1B, 0x60, 0xC4, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xF6, 0x64, 0x3A, 0x42, 0x4A, 0xDB, 0x93, 0xF3, 0x8F, 0xF3, 0xCC, 0x83, + 0xDC, 0x84, 0x01, 0x15, 0x93, 0xFD, 0x8F, 0xFB, 0xD4, 0xFE, 0x92, 0xF3, 0x90, 0xF3, 0x00, 0xA8, + 0x91, 0xF1, 0x03, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x27, 0x05, 0xB3, 0x60, 0x58, 0x4D, 0x4E, 0x78, + 0xFF, 0xFF, 0xA2, 0xFF, 0x21, 0x03, 0x00, 0x63, 0x92, 0xF3, 0x0E, 0xFC, 0xCC, 0x84, 0xFF, 0x3A, + 0x92, 0xFB, 0x98, 0xFE, 0x03, 0x04, 0x08, 0xBB, 0x0E, 0xFC, 0x3B, 0xFF, 0x1B, 0x60, 0xE0, 0x62, + 0x1B, 0x60, 0xB8, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xF7, 0x64, 0x3A, 0x42, 0x4A, 0xDB, 0x90, 0xF3, 0x0E, 0xF2, 0xDC, 0x83, 0x08, 0xB0, + 0x90, 0xFD, 0x08, 0x28, 0xF7, 0xFE, 0xD4, 0xFE, 0xA3, 0xFF, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, + 0xB9, 0xFE, 0x13, 0xFF, 0x24, 0x40, 0x80, 0x2B, 0x0B, 0x00, 0xA2, 0xFF, 0x25, 0x46, 0x09, 0xF4, + 0x0E, 0xF2, 0x05, 0x18, 0x08, 0xBC, 0x0E, 0xFA, 0xFF, 0xFF, 0xF7, 0xFE, 0x01, 0x00, 0xD8, 0xFE, + 0xA3, 0xFF, 0x25, 0x46, 0x3E, 0xF2, 0x00, 0xF4, 0x08, 0xF0, 0x25, 0x46, 0x06, 0xB4, 0xFF, 0x7F, + 0x10, 0xBC, 0x06, 0x26, 0xFD, 0x7F, 0x0E, 0xFA, 0x3E, 0xF2, 0x3F, 0xF2, 0x60, 0x41, 0x08, 0x2A, + 0x64, 0x47, 0x3F, 0xFA, 0x60, 0x45, 0x1F, 0x60, 0x62, 0x62, 0xA2, 0xD3, 0xA3, 0xFC, 0xAB, 0xFC, + 0x91, 0xFC, 0xD4, 0x80, 0xE0, 0x60, 0xC1, 0x65, 0xA5, 0x80, 0x01, 0x04, 0x07, 0x03, 0x23, 0xF0, + 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xF2, 0x60, 0x25, 0x78, 0xFF, 0xFF, 0xF4, 0x60, 0x58, 0x4F, + 0x2D, 0x78, 0xFF, 0xFF, 0x14, 0x04, 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x98, 0xF1, + 0x1E, 0x60, 0xFC, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, + 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x02, 0x00, 0x20, 0x60, 0x00, 0x75, 0x46, 0x00, 0x3E, 0xF0, + 0x89, 0xF1, 0x64, 0x47, 0x07, 0xB4, 0x07, 0x36, 0x3B, 0x00, 0x04, 0x03, 0xCC, 0x84, 0xE0, 0x84, + 0xC0, 0x83, 0x2D, 0x00, 0x2C, 0xF2, 0x88, 0xF1, 0x01, 0xB0, 0x64, 0x43, 0x35, 0x02, 0x2E, 0xF2, + 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, + 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x2E, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, + 0x0C, 0x02, 0x61, 0x46, 0x2D, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, + 0x2C, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, + 0xE8, 0x1B, 0x88, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x09, 0x00, 0x66, 0x45, + 0x63, 0x46, 0x06, 0xF0, 0x65, 0x46, 0x64, 0x44, 0x0C, 0x26, 0x02, 0x00, 0x02, 0x26, 0x04, 0x00, + 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x07, 0xFC, 0x23, 0xF2, 0xFF, 0xFF, 0x10, 0x1B, + 0x1B, 0x60, 0xE0, 0x62, 0x1B, 0x60, 0x9A, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xC8, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0x0F, 0x00, + 0x1B, 0x60, 0xE0, 0x62, 0x1B, 0x60, 0xAC, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xCE, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0xEB, 0x60, + 0x84, 0x78, 0xFF, 0xFF, 0xCB, 0x84, 0xC9, 0x83, 0xFF, 0xFF, 0x08, 0x04, 0x58, 0xD1, 0xA5, 0xD8, + 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x2F, 0x58, 0xFF, 0xFF, + 0x25, 0xF0, 0x21, 0x60, 0x2C, 0x62, 0xA2, 0xD9, 0x19, 0x00, 0x21, 0x60, 0x80, 0x64, 0xA0, 0xD1, + 0x7F, 0xF9, 0x0C, 0x60, 0x38, 0x62, 0x40, 0x63, 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0x64, 0x40, + 0x01, 0x2A, 0x0C, 0x00, 0x04, 0x65, 0x0C, 0x60, 0x38, 0x61, 0x48, 0x64, 0x3E, 0x63, 0x7C, 0xA8, + 0x58, 0xD0, 0x59, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x21, 0x60, 0x2C, 0x62, + 0xA2, 0xD1, 0x0D, 0x60, 0x1C, 0x65, 0x02, 0xFE, 0x64, 0x44, 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x87, + 0x60, 0x41, 0x64, 0x44, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x84, 0x3E, 0xFB, 0x60, 0x42, 0x61, 0x44, + 0x03, 0xA2, 0x60, 0xFE, 0xA2, 0xDB, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x44, 0x0C, 0x60, 0x3A, 0x65, + 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x84, 0x40, 0xFB, 0xFF, 0xFF, 0x00, 0x67, + 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x21, 0x60, 0x80, 0x64, 0xA0, 0xD1, 0x7F, 0xF9, 0x00, 0x64, + 0x40, 0x41, 0x64, 0x40, 0x01, 0x2A, 0xA6, 0x00, 0x4A, 0x64, 0xA0, 0xD2, 0xFF, 0xFF, 0x40, 0x42, + 0x80, 0x2B, 0x04, 0x00, 0xFF, 0xB4, 0x40, 0x42, 0x01, 0x64, 0x40, 0x41, 0x88, 0xF3, 0x46, 0x4B, + 0x87, 0xF3, 0x60, 0x46, 0xE0, 0x83, 0xAB, 0x46, 0x26, 0xF0, 0xAB, 0x46, 0x55, 0xF8, 0xAB, 0x46, + 0x27, 0xF0, 0xAB, 0x46, 0x56, 0xF8, 0xAB, 0x46, 0x28, 0xF0, 0xAB, 0x46, 0x57, 0xF8, 0x66, 0x44, + 0x02, 0xA6, 0xF1, 0x1F, 0x88, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xAB, 0x46, 0x0C, 0x60, 0x7A, 0x65, + 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x81, 0xC9, 0x81, + 0x52, 0x64, 0x0E, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, + 0xAB, 0x46, 0xF0, 0xA1, 0x6E, 0x64, 0x0E, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, + 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x0C, 0x60, 0xDC, 0x65, 0xC4, 0x81, + 0x60, 0x45, 0xC9, 0x81, 0x62, 0x64, 0x06, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, + 0x01, 0x2A, 0x08, 0x00, 0xAB, 0x46, 0xF8, 0xA1, 0xAE, 0x64, 0x06, 0x63, 0x59, 0xD1, 0x58, 0xD8, + 0xFD, 0x1F, 0xAB, 0x46, 0x65, 0x44, 0x0C, 0x60, 0xFC, 0x65, 0xC4, 0x81, 0xC9, 0x81, 0x6A, 0x64, + 0x06, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x85, + 0xC4, 0x84, 0x0C, 0x60, 0xC2, 0x65, 0xC4, 0x81, 0x72, 0x64, 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, + 0xFD, 0x1F, 0xAB, 0x46, 0x21, 0x44, 0x01, 0x2A, 0x06, 0x00, 0xFA, 0xA1, 0x88, 0x64, 0x04, 0x63, + 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0x37, 0xF0, 0x21, 0x44, 0x01, 0x2A, 0x13, 0x00, 0x22, 0x44, + 0x3D, 0xFB, 0x60, 0x41, 0x02, 0xFE, 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x84, 0x3C, 0xFB, 0x0C, 0x60, + 0xBE, 0x63, 0x88, 0xFF, 0xCD, 0x81, 0x06, 0xA3, 0xFD, 0x0D, 0x8D, 0xFF, 0x3B, 0xFD, 0x64, 0x47, + 0x80, 0xBF, 0x60, 0x5C, 0x22, 0x43, 0x80, 0x61, 0x88, 0xFF, 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, + 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, 0xB1, 0x84, 0x37, 0xFA, 0x87, 0xF3, 0xFF, 0xFF, 0xCC, 0x83, + 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0x37, 0xF0, 0x66, 0x44, 0xB1, 0x9C, 0x37, 0xF8, 0x02, 0xA6, + 0xFA, 0x1F, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, + 0x02, 0xA8, 0x00, 0x67, 0x24, 0x02, 0x3D, 0xF1, 0x64, 0x44, 0x03, 0xB4, 0x40, 0x42, 0xD0, 0x80, + 0x88, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xB7, 0xF4, 0x80, 0x61, 0x02, 0x02, 0xE3, 0x83, 0xEB, 0x83, + 0x22, 0x44, 0x88, 0xFF, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, + 0x9D, 0x85, 0xA7, 0x83, 0x37, 0xFC, 0x87, 0xF3, 0xFF, 0xFF, 0xCC, 0x83, 0xE3, 0x83, 0x66, 0x44, + 0x02, 0xA6, 0xB7, 0xF2, 0x66, 0x44, 0xA5, 0x81, 0xB7, 0xFA, 0x02, 0xA6, 0xFA, 0x1F, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x11, 0x64, 0x23, 0xFA, 0x25, 0x44, 0x24, 0xFA, 0x04, 0x64, 0x40, 0x4B, + 0x62, 0x41, 0x0C, 0x60, 0xC2, 0x64, 0x04, 0x63, 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, 0x2B, 0x43, + 0x00, 0x7C, 0x59, 0xD8, 0x4F, 0x8B, 0x06, 0xA4, 0xF6, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x21, 0x60, 0x80, 0x64, 0xA0, 0xD1, 0x7F, 0xF9, 0x64, 0x40, 0x01, 0x2A, 0x4E, 0x00, 0x27, 0xF2, + 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, + 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, + 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, + 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, + 0xE8, 0x1B, 0x88, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x2A, 0x00, 0x43, 0x4B, + 0xAB, 0x46, 0x37, 0xF2, 0x80, 0x60, 0x30, 0x7C, 0xB0, 0x84, 0xA2, 0xDA, 0x4E, 0x61, 0x6E, 0x64, + 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x88, 0x64, 0x04, 0x63, + 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0xD9, 0x81, 0x98, 0x64, 0x04, 0x63, + 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0xD9, 0x81, 0xAE, 0x64, 0x0E, 0x63, + 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, + 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x21, 0x60, 0x80, 0x64, 0xA0, 0xD1, + 0x7F, 0xF9, 0x64, 0x40, 0x01, 0x2A, 0x31, 0x00, 0x27, 0xF2, 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, + 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, + 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, + 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x88, 0xF3, 0x08, 0xFE, + 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x0D, 0x00, 0x43, 0x4B, 0xAB, 0x46, 0x37, 0xF2, 0x80, 0x60, + 0x30, 0x61, 0x9D, 0x85, 0xA4, 0x84, 0xA2, 0xDA, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, + 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x3E, 0xF2, 0xAC, 0xF1, 0x08, 0xB0, + 0x19, 0xF8, 0x4A, 0x02, 0x07, 0x23, 0x2B, 0x00, 0x60, 0x47, 0x07, 0xB4, 0x89, 0xF1, 0xCC, 0x84, + 0xE0, 0x84, 0x40, 0x8A, 0xAA, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x05, 0xF2, 0x60, 0x43, 0xAA, 0x46, + 0x2C, 0xFC, 0x2D, 0xF8, 0x2E, 0xFA, 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, + 0x31, 0xF8, 0x46, 0x4A, 0x00, 0xF4, 0x02, 0xF2, 0x03, 0xF0, 0x04, 0xF2, 0x60, 0x43, 0xAA, 0x46, + 0x32, 0xFC, 0x33, 0xF8, 0x34, 0xFA, 0xAA, 0x46, 0x05, 0xF2, 0x06, 0xF0, 0x07, 0xF2, 0x60, 0x43, + 0xAA, 0x46, 0x36, 0xFC, 0x37, 0xF8, 0x38, 0xFA, 0x03, 0x60, 0x08, 0x64, 0x1C, 0x00, 0x67, 0xF1, + 0x2F, 0xF8, 0x68, 0xF1, 0x30, 0xF8, 0x69, 0xF1, 0x31, 0xF8, 0x46, 0x4A, 0x00, 0xF4, 0x02, 0xF2, + 0x03, 0xF0, 0x04, 0xF2, 0x60, 0x43, 0xAA, 0x46, 0x2C, 0xFC, 0x2D, 0xF8, 0x2E, 0xFA, 0xAA, 0x46, + 0x05, 0xF2, 0x06, 0xF0, 0x07, 0xF2, 0x60, 0x43, 0xAA, 0x46, 0x32, 0xFC, 0x33, 0xF8, 0x34, 0xFA, + 0x02, 0x60, 0x08, 0x64, 0x00, 0x00, 0x2A, 0xFA, 0x02, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x28, 0xF3, + 0xFF, 0xFF, 0x60, 0x47, 0x0F, 0xB4, 0x59, 0x00, 0xFF, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x1C, 0x60, + 0x04, 0x65, 0x04, 0x64, 0xA5, 0xDB, 0x12, 0x00, 0x1C, 0x60, 0x04, 0x65, 0x0C, 0x64, 0xA5, 0xDB, + 0x0D, 0x00, 0x1C, 0x60, 0x04, 0x65, 0x06, 0x64, 0xA5, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0x04, 0x65, 0x08, 0x64, 0xA5, 0xDB, 0xF4, 0x60, 0xD9, 0x64, + 0x80, 0xFB, 0xFF, 0xFF, 0x2D, 0xFF, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, 0x29, 0xF3, 0x65, 0xFB, + 0x83, 0xFB, 0x02, 0x60, 0xEE, 0x64, 0x82, 0xFB, 0x07, 0x64, 0x84, 0xFB, 0xF4, 0x60, 0xD9, 0x64, + 0x80, 0xFB, 0xFF, 0xFF, 0xDF, 0xFE, 0x00, 0x64, 0x19, 0xFF, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, + 0xAF, 0x60, 0xFD, 0x63, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0xF4, 0x60, 0xC6, 0x63, + 0x80, 0xFD, 0xFF, 0xFF, 0x1A, 0xFF, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, 0xA7, 0x60, 0x9B, 0x63, + 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0x29, 0xF5, 0x1B, 0x60, 0xE0, 0x63, 0x1B, 0x60, + 0xB2, 0x64, 0xBD, 0xDB, 0x66, 0x44, 0xBD, 0xDB, 0x02, 0x64, 0xA3, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xF9, 0xFE, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xA7, 0x01, 0x00, 0x36, 0xA8, 0x01, 0x01, 0x36, + 0xAB, 0x01, 0x02, 0x36, 0xAE, 0x01, 0x03, 0x36, 0xB5, 0x01, 0x04, 0x36, 0xD1, 0x01, 0x05, 0x36, + 0xCF, 0x01, 0x06, 0x36, 0xF1, 0x01, 0x07, 0x36, 0xCB, 0x01, 0x08, 0x36, 0xB7, 0x01, 0x09, 0x36, + 0x0C, 0x00, 0x0A, 0x36, 0x0D, 0x00, 0x0B, 0x36, 0x0E, 0x00, 0x0C, 0x36, 0x17, 0x00, 0x0D, 0x36, + 0x0D, 0x00, 0x0E, 0x36, 0x1E, 0x00, 0x0F, 0x36, 0x32, 0x00, 0x02, 0x60, 0x00, 0x64, 0x08, 0x00, + 0x04, 0x60, 0x00, 0x64, 0x05, 0x00, 0x00, 0x60, 0x01, 0x64, 0x02, 0x00, 0x20, 0x60, 0x00, 0x64, + 0x32, 0x45, 0xB4, 0x85, 0x45, 0x52, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xB0, 0x60, 0xC1, 0x63, + 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x3F, 0x40, 0x02, 0x2B, 0x05, 0x00, 0x90, 0x60, 0x00, 0xE8, 0xAF, 0x60, 0xFD, 0x63, + 0x04, 0x00, 0x91, 0x60, 0x00, 0xE8, 0xB0, 0x60, 0xAB, 0x63, 0x28, 0xE8, 0x0C, 0x60, 0x16, 0x64, + 0xA0, 0xDD, 0x62, 0xFF, 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x91, 0x60, + 0x00, 0xE8, 0x28, 0xE8, 0xD9, 0x60, 0xFE, 0x64, 0x32, 0x45, 0xA4, 0x85, 0x45, 0x52, 0x99, 0xFF, + 0xA5, 0x4F, 0xFF, 0xB4, 0x07, 0xFB, 0x98, 0xFF, 0xA7, 0x60, 0x9B, 0x63, 0x0C, 0x60, 0x16, 0x64, + 0xA0, 0xDD, 0x62, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x42, 0x6F, 0x6F, 0x74, 0x63, 0x6F, + 0x64, 0x65, 0x20, 0x21, 0x21, 0x20, 0x20, 0x00, 0x53, 0x54, 0x41, 0x2F, 0x41, 0x50, 0x20, 0x46, + 0x75, 0x6E, 0x63, 0x27, 0x73, 0x00, 0x20, 0x00, 0x02, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x06, 0x00, + 0x07, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x07, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x40, 0x00, 0x32, 0x00, 0x32, 0x00, 0x0A, 0x00, 0x02, 0x00, 0x06, 0x00, 0x40, 0x00, 0x32, 0x00, + 0x36, 0x00, 0x0A, 0x00, 0x02, 0x00, 0x06, 0x00, 0x40, 0x00, 0x3B, 0x00, 0x40, 0x00, 0x17, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x4A, 0x00, 0x40, 0x00, 0x4A, 0x00, 0x1E, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x57, 0x00, 0x4D, 0x00, 0x57, 0x00, 0x2B, 0x00, 0x19, 0x00, 0x08, 0x00, 0x5D, 0x00, 0x53, 0x00, + 0x5D, 0x00, 0x31, 0x00, 0x1F, 0x00, 0x08, 0x00, + +}; /* fw_image_4_data */ + +static const CFG_IDENTITY_STRCT fw_image_infoidentity[] = { + { + sizeof( CFG_IDENTITY_STRCT ) / sizeof(hcf_16) - 1, + CFG_FW_IDENTITY, + COMP_ID_FW_AP, + 2, //Variant + 2, //Major + 36 //Minor + }, + { 0000, 0000, 0000, 0000, 0000, 0000 } //endsentinel +}; + +static const CFG_PROG_STRCT fw_image_code[] = { + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0x0146, // sizeof(fw_image_1_data), + 0x00000060, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_1_data + }, + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0x1918, // sizeof(fw_image_2_data), + 0x00000C16, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_2_data + }, + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0x01bc, // sizeof(fw_image_3_data), + 0x001E252E, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_3_data + }, + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0xab28, // sizeof(fw_image_4_data), + 0x001F4000, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_4_data + }, + { + 5, + CFG_PROG, + CFG_PROG_STOP, // mode + 0000, + 0x000F1297, // Start execution address + }, + { 0000, 0000, 0000, 0000, 00000000, 0000, 00000000} +}; + +static const CFG_RANGE20_STRCT fw_image_infocompat[] = { + { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), + CFG_FW_SUP_RANGE, + COMP_ROLE_SUPL, + COMP_ID_APF, + { + { 2, 2, 4 } //variant, bottom, top + } + }, + { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), + CFG_MFI_ACT_RANGES_STA, + COMP_ROLE_ACT, + COMP_ID_MFI, + { + { 4, 6, 7 }, //variant, bottom, top + { 5, 6, 7 }, //variant, bottom, top + { 6, 6, 7 } //variant, bottom, top + } + }, + { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), + CFG_CFI_ACT_RANGES_STA, + COMP_ROLE_ACT, + COMP_ID_CFI, + { + { 2, 1, 2 } //variant, bottom, top + } + }, + { 0000, 0000, 0000, 0000, { { 0000, 0000, 0000 } } } //endsentinel +}; + +memimage fw_image = { + "FUPU7D37dhfwci\001C", //signature, , C/Bin type + (CFG_PROG_STRCT *) fw_image_code, + 0x000F1297, + 00000000, //(dummy) pdaplug + 00000000, //(dummy) priplug + (CFG_RANGE20_STRCT *) fw_image_infocompat, + (CFG_IDENTITY_STRCT *) fw_image_infoidentity, +}; + diff --git a/drivers/staging/wlags49_h2/ap_h25.c b/drivers/staging/wlags49_h2/ap_h25.c new file mode 100644 index 0000000000000000000000000000000000000000..f4491cbd08d35e615d55ac76c3c2e7f23b09ce51 --- /dev/null +++ b/drivers/staging/wlags49_h2/ap_h25.c @@ -0,0 +1,4094 @@ +/* + * File: ap_h54.124 + * + * Abstract: This file contains memory image 'fw_image'. + * + * Contents: Total size of the memory image: 63146 bytes. + * Total number of blocks: 4 blocks. + * Block 1 : load address 00000060, 328 bytes. + * Block 2 : load address 00000C16, 9266 bytes. + * Block 3 : load address 001E3048, 6476 bytes. + * Block 4 : load address 001F4000, 47076 bytes. + * + * Identity: component id: 32 (variant 3) version 1.24 + * + * Compatibility: + * supplying interface 8 (variant 4) : 1 - 1 + * acting on interface 1 (variant 7) : 3 - 3 + * acting on interface 1 (variant 8) : 1 - 1 + * acting on interface 2 (variant 4) : 1 - 2 + * + * Generated: by g:\fw\fupu3.exe version 4.26 + * + * Commandline: g:\fw\fupu3.exe /f=4 /n=fw_image /i=t3012400.hex + */ + + +#include "hcfcfg.h" // to get hcf_16 etc defined as well as + // possible settings which inluence mdd.h or dhf.h +#include "mdd.h" //to get COMP_ID_STA etc defined +#include "dhf.h" //used to be "fhfmem.h", to get memblock,plugrecord, + +static const hcf_8 fw_image_1_data[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x0C, 0x00, 0x00, + 0x02, 0x0D, 0x00, 0x00, 0x02, 0x0D, 0xD6, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x09, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, + 0x00, 0x00, 0xFF, 0x07, 0x02, 0x00, 0x64, 0x00, 0x64, 0x00, 0x10, 0x27, 0x10, 0x27, 0x14, 0x00, + 0xD0, 0x07, 0xD0, 0x07, 0x10, 0x27, 0x2F, 0x00, 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x10, 0x27, 0x05, 0x00, 0x00, 0x02, 0x00, 0x02, 0x13, 0x00, 0x07, 0x00, 0x03, 0x00, + 0x32, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x09, 0x2B, 0x09, 0x2B, 0x09, 0xFF, 0x0F, + 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x40, 0x00, 0x32, 0x00, 0x32, 0x00, + 0x0A, 0x00, 0x02, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +}; /* fw_image_1_data */ + +static const hcf_8 fw_image_2_data[] = { + 0x7C, 0xA4, 0x00, 0x16, 0x08, 0x40, 0x0F, 0xD2, 0xE1, 0x28, 0xA5, 0x7C, 0x50, 0x30, 0xF1, 0x84, + 0x44, 0x08, 0xAB, 0xAE, 0xA5, 0xB8, 0xFC, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x84, 0xF8, + 0x99, 0xEE, 0x8D, 0xF6, 0x0D, 0xFF, 0xBD, 0xD6, 0xB1, 0xDE, 0x54, 0x91, 0x50, 0x60, 0x03, 0x02, + 0xA9, 0xCE, 0x7D, 0x56, 0x19, 0xE7, 0x62, 0xB5, 0xE6, 0x4D, 0x9A, 0xEC, 0x45, 0x8F, 0x9D, 0x1F, + 0x40, 0x89, 0x87, 0xFA, 0x15, 0xEF, 0xEB, 0xB2, 0xC9, 0x8E, 0x0B, 0xFB, 0xEC, 0x41, 0x67, 0xB3, + 0xFD, 0x5F, 0xEA, 0x45, 0xBF, 0x23, 0xF7, 0x53, 0x96, 0xE4, 0x5B, 0x9B, 0xC2, 0x75, 0x1C, 0xE1, + 0xAE, 0x3D, 0x6A, 0x4C, 0x5A, 0x6C, 0x41, 0x7E, 0x02, 0xF5, 0x4F, 0x83, 0x5C, 0x68, 0xF4, 0x51, + 0x34, 0xD1, 0x08, 0xF9, 0x93, 0xE2, 0x73, 0xAB, 0x53, 0x62, 0x3F, 0x2A, 0x0C, 0x08, 0x52, 0x95, + 0x65, 0x46, 0x5E, 0x9D, 0x28, 0x30, 0xA1, 0x37, 0x0F, 0x0A, 0xB5, 0x2F, 0x09, 0x0E, 0x36, 0x24, + 0x9B, 0x1B, 0x3D, 0xDF, 0x26, 0xCD, 0x69, 0x4E, 0xCD, 0x7F, 0x9F, 0xEA, 0x1B, 0x12, 0x9E, 0x1D, + 0x74, 0x58, 0x2E, 0x34, 0x2D, 0x36, 0xB2, 0xDC, 0xEE, 0xB4, 0xFB, 0x5B, 0xF6, 0xA4, 0x4D, 0x76, + 0x61, 0xB7, 0xCE, 0x7D, 0x7B, 0x52, 0x3E, 0xDD, 0x71, 0x5E, 0x97, 0x13, 0xF5, 0xA6, 0x68, 0xB9, + 0x00, 0x00, 0x2C, 0xC1, 0x60, 0x40, 0x1F, 0xE3, 0xC8, 0x79, 0xED, 0xB6, 0xBE, 0xD4, 0x46, 0x8D, + 0xD9, 0x67, 0x4B, 0x72, 0xDE, 0x94, 0xD4, 0x98, 0xE8, 0xB0, 0x4A, 0x85, 0x6B, 0xBB, 0x2A, 0xC5, + 0xE5, 0x4F, 0x16, 0xED, 0xC5, 0x86, 0xD7, 0x9A, 0x55, 0x66, 0x94, 0x11, 0xCF, 0x8A, 0x10, 0xE9, + 0x06, 0x04, 0x81, 0xFE, 0xF0, 0xA0, 0x44, 0x78, 0xBA, 0x25, 0xE3, 0x4B, 0xF3, 0xA2, 0xFE, 0x5D, + 0xC0, 0x80, 0x8A, 0x05, 0xAD, 0x3F, 0xBC, 0x21, 0x48, 0x70, 0x04, 0xF1, 0xDF, 0x63, 0xC1, 0x77, + 0x75, 0xAF, 0x63, 0x42, 0x30, 0x20, 0x1A, 0xE5, 0x0E, 0xFD, 0x6D, 0xBF, 0x4C, 0x81, 0x14, 0x18, + 0x35, 0x26, 0x2F, 0xC3, 0xE1, 0xBE, 0xA2, 0x35, 0xCC, 0x88, 0x39, 0x2E, 0x57, 0x93, 0xF2, 0x55, + 0x82, 0xFC, 0x47, 0x7A, 0xAC, 0xC8, 0xE7, 0xBA, 0x2B, 0x32, 0x95, 0xE6, 0xA0, 0xC0, 0x98, 0x19, + 0xD1, 0x9E, 0x7F, 0xA3, 0x66, 0x44, 0x7E, 0x54, 0xAB, 0x3B, 0x83, 0x0B, 0xCA, 0x8C, 0x29, 0xC7, + 0xD3, 0x6B, 0x3C, 0x28, 0x79, 0xA7, 0xE2, 0xBC, 0x1D, 0x16, 0x76, 0xAD, 0x3B, 0xDB, 0x56, 0x64, + 0x4E, 0x74, 0x1E, 0x14, 0xDB, 0x92, 0x0A, 0x0C, 0x6C, 0x48, 0xE4, 0xB8, 0x5D, 0x9F, 0x6E, 0xBD, + 0xEF, 0x43, 0xA6, 0xC4, 0xA8, 0x39, 0xA4, 0x31, 0x37, 0xD3, 0x8B, 0xF2, 0x32, 0xD5, 0x43, 0x8B, + 0x59, 0x6E, 0xB7, 0xDA, 0x8C, 0x01, 0x64, 0xB1, 0xD2, 0x9C, 0xE0, 0x49, 0xB4, 0xD8, 0xFA, 0xAC, + 0x07, 0xF3, 0x25, 0xCF, 0xAF, 0xCA, 0x8E, 0xF4, 0xE9, 0x47, 0x18, 0x10, 0xD5, 0x6F, 0x88, 0xF0, + 0x6F, 0x4A, 0x72, 0x5C, 0x24, 0x38, 0xF1, 0x57, 0xC7, 0x73, 0x51, 0x97, 0x23, 0xCB, 0x7C, 0xA1, + 0x9C, 0xE8, 0x21, 0x3E, 0xDD, 0x96, 0xDC, 0x61, 0x86, 0x0D, 0x85, 0x0F, 0x90, 0xE0, 0x42, 0x7C, + 0xC4, 0x71, 0xAA, 0xCC, 0xD8, 0x90, 0x05, 0x06, 0x01, 0xF7, 0x12, 0x1C, 0xA3, 0xC2, 0x5F, 0x6A, + 0xF9, 0xAE, 0xD0, 0x69, 0x91, 0x17, 0x58, 0x99, 0x27, 0x3A, 0xB9, 0x27, 0x38, 0xD9, 0x13, 0xEB, + 0xB3, 0x2B, 0x33, 0x22, 0xBB, 0xD2, 0x70, 0xA9, 0x89, 0x07, 0xA7, 0x33, 0xB6, 0x2D, 0x22, 0x3C, + 0x92, 0x15, 0x20, 0xC9, 0x49, 0x87, 0xFF, 0xAA, 0x78, 0x50, 0x7A, 0xA5, 0x8F, 0x03, 0xF8, 0x59, + 0x80, 0x09, 0x17, 0x1A, 0xDA, 0x65, 0x31, 0xD7, 0xC6, 0x84, 0xB8, 0xD0, 0xC3, 0x82, 0xB0, 0x29, + 0x77, 0x5A, 0x11, 0x1E, 0xCB, 0x7B, 0xFC, 0xA8, 0xD6, 0x6D, 0x3A, 0x2C, 0x00, 0x30, 0x00, 0x31, + 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x38, 0x00, 0x3A, + 0x00, 0x3B, 0x00, 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, 0x3F, 0x59, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x21, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x20, 0x03, 0xE0, 0x01, 0x40, 0x01, 0x20, 0x03, 0xE0, 0x01, + 0x40, 0x01, 0x18, 0x08, 0xF0, 0x3F, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x02, 0x14, 0x05, 0x32, 0x0B, 0x37, + 0x08, 0x50, 0x0B, 0x6E, 0x02, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x16, 0x00, 0x0C, 0x00, 0x12, 0x00, + 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x48, 0x00, 0x60, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x39, 0x00, 0x20, 0x00, 0x39, 0x00, + 0x39, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xA4, 0x10, 0xF2, 0x10, 0xAA, 0x10, 0xEC, 0x10, 0xB0, 0x10, 0xE6, 0x10, 0xB6, 0x10, + 0xE0, 0x10, 0xBC, 0x10, 0xDA, 0x10, 0xC2, 0x10, 0xD4, 0x10, 0xC8, 0x10, 0xCE, 0x10, 0x07, 0x01, + 0x00, 0x00, 0x16, 0x22, 0x00, 0x04, 0x08, 0x01, 0x00, 0x00, 0x16, 0x26, 0x00, 0x04, 0x09, 0x01, + 0x00, 0x00, 0x16, 0x2A, 0x00, 0x04, 0x0A, 0x01, 0x00, 0x00, 0x16, 0x2E, 0x00, 0x04, 0x0B, 0x01, + 0x00, 0x00, 0x10, 0x24, 0x04, 0x04, 0x0C, 0x01, 0x00, 0x00, 0x10, 0x28, 0x04, 0x04, 0x0D, 0x01, + 0x00, 0x00, 0x10, 0x2C, 0x04, 0x04, 0x0E, 0x01, 0x00, 0x00, 0x10, 0x30, 0x04, 0x04, 0x0F, 0x01, + 0x00, 0x00, 0x14, 0x34, 0x08, 0x84, 0x10, 0x01, 0x00, 0x00, 0x14, 0x38, 0x08, 0x84, 0x11, 0x01, + 0x00, 0x00, 0x14, 0x3C, 0x08, 0x84, 0x12, 0x01, 0x00, 0x00, 0x14, 0x40, 0x08, 0x84, 0x13, 0x01, + 0x00, 0x00, 0x17, 0x64, 0x0C, 0x8B, 0x14, 0x01, 0x00, 0x00, 0x17, 0x68, 0x0C, 0x8B, 0x15, 0x01, + 0x00, 0x00, 0x17, 0x6C, 0x0C, 0x8B, 0x16, 0x01, 0x00, 0x00, 0x17, 0x70, 0x0C, 0x8B, 0x17, 0x01, + 0x00, 0x00, 0x17, 0x74, 0x0C, 0x8B, 0x18, 0x01, 0x00, 0x00, 0x17, 0x78, 0x0C, 0x8B, 0x19, 0x01, + 0x00, 0x00, 0x17, 0x7C, 0x0C, 0x8B, 0x1A, 0x01, 0x00, 0x00, 0x17, 0x80, 0x0C, 0x8B, 0x1B, 0x01, + 0x00, 0x00, 0x17, 0x84, 0x0C, 0x8B, 0x1C, 0x01, 0x00, 0x00, 0x17, 0x88, 0x0C, 0x8B, 0x1D, 0x01, + 0x00, 0x00, 0x17, 0x8C, 0x0C, 0x8B, 0x1E, 0x01, 0x00, 0x00, 0x0E, 0x95, 0x17, 0x04, 0x1F, 0x01, + 0x00, 0x00, 0x0E, 0x99, 0x17, 0x04, 0x20, 0x01, 0x00, 0x00, 0x0E, 0x9D, 0x17, 0x04, 0x21, 0x01, + 0x00, 0x00, 0x0E, 0xA1, 0x17, 0x04, 0x22, 0x01, 0x00, 0x00, 0x0E, 0xA5, 0x00, 0x00, 0x14, 0x11, + 0x34, 0x11, 0x54, 0x11, 0x74, 0x11, 0xCC, 0x11, 0x1C, 0x11, 0x3C, 0x11, 0x5C, 0x11, 0x7C, 0x11, + 0xD4, 0x11, 0x24, 0x11, 0x44, 0x11, 0x64, 0x11, 0x84, 0x11, 0xDC, 0x11, 0x2C, 0x11, 0x4C, 0x11, + 0x6C, 0x11, 0x8C, 0x11, 0xE4, 0x11, 0x94, 0x11, 0x9C, 0x11, 0xA4, 0x11, 0xAC, 0x11, 0xB4, 0x11, + 0xBC, 0x11, 0xC4, 0x11, 0xEC, 0x11, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x0A, 0x0A, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0A, 0x0A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x10, 0x10, 0x10, 0x10, + 0x17, 0x17, 0x17, 0x17, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x11, 0x11, 0x11, 0x11, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x16, 0x16, 0x16, 0x16, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x0A, 0x0A, 0x0A, + 0x0A, 0x7F, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x10, 0x10, 0x10, 0x10, 0x7F, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x0A, 0x0A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x9D, 0x9D, 0xA1, 0xAA, 0x10, 0x10, + 0x9D, 0x9D, 0x08, 0x02, 0x06, 0x00, 0xA5, 0xA5, 0xAA, 0xAA, 0x17, 0x17, 0xA2, 0xA2, 0x15, 0x05, + 0x07, 0x00, 0xAA, 0xAA, 0xB4, 0xB4, 0x1C, 0x1C, 0xA7, 0xA7, 0x1C, 0x0A, 0x08, 0x00, 0xB7, 0xB7, + 0xC1, 0xC1, 0x09, 0x09, 0xB4, 0xB4, 0x29, 0x17, 0x08, 0x00, 0xBD, 0xBD, 0xC7, 0xC7, 0x0F, 0x0F, + 0xBA, 0xBA, 0x2F, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE4, 0xF0, 0xFD, 0xF0, 0x1F, 0xF1, 0x60, 0xF6, 0x9B, 0xF0, 0x79, 0xF6, 0x9B, 0xF0, 0x9B, 0xF0, + 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0xCC, 0xF7, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, + 0x9B, 0xF0, 0x15, 0xF3, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, + 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, + 0x9B, 0xF0, 0x66, 0xF3, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, + 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, + 0xE3, 0xF2, 0xFE, 0xF2, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, + 0xB4, 0x1C, 0x59, 0xF1, 0x6C, 0xF1, 0x1C, 0xF2, 0x20, 0xF2, 0x9B, 0xF0, 0x9B, 0xF0, 0xCF, 0xF2, + 0x64, 0xE6, 0x3E, 0xE6, 0x92, 0xE6, 0xE1, 0xE6, 0xA9, 0xE7, 0xCF, 0xE7, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x12, 0xF1, 0x35, 0xF1, 0x5D, 0xF6, 0x5D, 0xF6, 0x6D, 0xF6, 0x86, 0xF6, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC, 0xC0, 0xF3, 0xF2, 0xF5, 0x5A, 0x00, 0x02, 0x00, 0xF9, 0xFF, + 0xC0, 0xF3, 0xD6, 0xF3, 0xCA, 0x00, 0x02, 0x00, 0xF7, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0xB0, 0x26, + 0x06, 0x00, 0xF0, 0xFF, 0xC0, 0xF3, 0xAA, 0xF3, 0x00, 0x00, 0x00, 0x02, 0xF6, 0xFF, 0xC0, 0xF3, + 0xD6, 0xF3, 0x6C, 0x00, 0x02, 0x00, 0xF4, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0x68, 0x01, 0x02, 0x00, + 0xF5, 0xFF, 0xC0, 0xF3, 0xFB, 0xF5, 0xA2, 0x26, 0x02, 0x00, 0xED, 0xFF, 0xC0, 0xF3, 0x0D, 0xF6, + 0x9E, 0x2B, 0x02, 0x00, 0xEC, 0xFF, 0xC0, 0xF3, 0x3B, 0xF6, 0xA0, 0x2B, 0x02, 0x00, 0xEB, 0xFF, + 0xC0, 0xF3, 0x41, 0xF6, 0xA2, 0x2B, 0x02, 0x00, 0xEE, 0xFF, 0xC0, 0xF3, 0x47, 0xF6, 0xD6, 0x2B, + 0x02, 0x00, 0xDA, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0xD0, 0x13, 0x0C, 0x00, 0xEA, 0xFF, 0xC0, 0xF3, + 0xAA, 0xF3, 0xEC, 0x2B, 0x06, 0x00, 0xE9, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0xF2, 0x2B, 0x02, 0x00, + 0xE8, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0xF4, 0x2B, 0x02, 0x00, 0xE7, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, + 0xF6, 0x2B, 0x02, 0x00, 0xE6, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0xF8, 0x2B, 0x02, 0x00, 0xE5, 0xFF, + 0xC0, 0xF3, 0xD6, 0xF3, 0xFA, 0x2B, 0x10, 0x00, 0xE4, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0x0A, 0x2C, + 0x18, 0x00, 0xDB, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0x22, 0x2C, 0x02, 0x00, 0xDC, 0xFF, 0xC0, 0xF3, + 0xD6, 0xF3, 0x24, 0x2C, 0x02, 0x00, 0xE1, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0xC6, 0x2C, 0x02, 0x00, + 0xE0, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0xC4, 0x2C, 0x02, 0x00, 0xE3, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, + 0xA8, 0x2C, 0x02, 0x00, 0xE2, 0xFF, 0x0E, 0xF4, 0xAA, 0xF3, 0x7E, 0x2C, 0x24, 0x00, 0x03, 0xFC, + 0xC0, 0xF3, 0x3A, 0xF5, 0x92, 0x2B, 0x02, 0x00, 0x04, 0xFC, 0xC0, 0xF3, 0xD0, 0xF3, 0xBA, 0x26, + 0x22, 0x00, 0x06, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0xA0, 0x26, 0x02, 0x00, 0x07, 0xFC, 0xC0, 0xF3, + 0xD6, 0xF3, 0xFE, 0x26, 0x02, 0x00, 0x0E, 0xFC, 0xC0, 0xF3, 0x63, 0xF5, 0x08, 0x27, 0x22, 0x00, + 0xB1, 0xFC, 0xC0, 0xF3, 0x88, 0xF8, 0x2A, 0x28, 0x02, 0x00, 0x20, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, + 0x2E, 0x27, 0x02, 0x00, 0x25, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x3A, 0x27, 0x02, 0x00, 0x26, 0xFC, + 0xC0, 0xF3, 0xD6, 0xF3, 0x3C, 0x27, 0x02, 0x00, 0x27, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x3E, 0x27, + 0x02, 0x00, 0xB2, 0xFC, 0xC0, 0xF3, 0xD0, 0xF3, 0x4E, 0x28, 0x22, 0x00, 0xC1, 0xFC, 0xC0, 0xF3, + 0xD6, 0xF3, 0x56, 0x2C, 0x20, 0x00, 0xB0, 0xFC, 0xA0, 0xF3, 0x8C, 0xF8, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0xFC, 0xA0, 0xF3, 0x54, 0xF6, 0x00, 0x00, 0x08, 0x00, 0xC8, 0xFC, 0xA0, 0xF3, 0x52, 0xF6, + 0x00, 0x00, 0x08, 0x00, 0xB4, 0xFC, 0xA0, 0xF3, 0xC0, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xB6, 0xFC, + 0xA0, 0xF3, 0x6A, 0xF9, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xFC, 0xA0, 0xF3, 0xAC, 0xF9, 0x00, 0x00, + 0x00, 0x00, 0xB8, 0xFC, 0xA0, 0xF3, 0x02, 0xFA, 0x00, 0x00, 0x00, 0x00, 0xBC, 0xFC, 0xA0, 0xF3, + 0x3B, 0xFA, 0x00, 0x00, 0x00, 0x00, 0xBD, 0xFC, 0xA0, 0xF3, 0xC3, 0xFA, 0x00, 0x00, 0x00, 0x00, + 0xBE, 0xFC, 0xA0, 0xF3, 0xEF, 0xFA, 0x00, 0x00, 0x00, 0x00, 0xBF, 0xFC, 0xA0, 0xF3, 0x3C, 0xFB, + 0x00, 0x00, 0x00, 0x00, 0xB3, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0xA2, 0x0F, 0x10, 0x00, 0xB5, 0xFC, + 0xC0, 0xF3, 0xD6, 0xF3, 0xA4, 0x2C, 0x02, 0x00, 0xB9, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0xA6, 0x2C, + 0x02, 0x00, 0x90, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0xAA, 0x2C, 0x02, 0x00, 0x88, 0xFC, 0xC0, 0xF3, + 0xD6, 0xF3, 0x78, 0x2B, 0x04, 0x00, 0x89, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x7C, 0x2B, 0x04, 0x00, + 0xC5, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x80, 0x2B, 0x04, 0x00, 0x23, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, + 0x34, 0x27, 0x04, 0x00, 0x2A, 0xFC, 0xC0, 0xF3, 0x2C, 0xF4, 0xB6, 0x26, 0x02, 0x00, 0xC7, 0xFD, + 0xC0, 0xF3, 0xAA, 0xF3, 0xA6, 0x2B, 0x0A, 0x00, 0x29, 0xFC, 0x7F, 0xF4, 0x43, 0xF4, 0x00, 0x00, + 0x00, 0x00, 0xC2, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x86, 0x2B, 0x08, 0x00, 0x32, 0xFC, 0xC0, 0xF3, + 0xD6, 0xF3, 0x5C, 0x01, 0x02, 0x00, 0x33, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x5E, 0x01, 0x02, 0x00, + 0x35, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x8E, 0x2B, 0x02, 0x00, 0xC7, 0xFC, 0xC0, 0xF3, 0xEB, 0xF5, + 0x90, 0x2B, 0x02, 0x00, 0x10, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0xA8, 0x26, 0x02, 0x00, 0x11, 0xFC, + 0xC0, 0xF3, 0xD6, 0xF3, 0x44, 0x27, 0x06, 0x00, 0x12, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x4A, 0x27, + 0x06, 0x00, 0x13, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x50, 0x27, 0x06, 0x00, 0x14, 0xFC, 0xC0, 0xF3, + 0xD6, 0xF3, 0x56, 0x27, 0x06, 0x00, 0x15, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x5C, 0x27, 0x06, 0x00, + 0x16, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x62, 0x27, 0x06, 0x00, 0x17, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, + 0x2A, 0x27, 0x02, 0x00, 0x83, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x6C, 0x01, 0x02, 0x00, 0x97, 0xFC, + 0xC0, 0xF3, 0xD6, 0xF3, 0x6A, 0x01, 0x02, 0x00, 0x98, 0xFC, 0xD7, 0xF5, 0xC5, 0xF5, 0xEC, 0x00, + 0x02, 0x00, 0x99, 0xFC, 0xD7, 0xF5, 0xC5, 0xF5, 0xEC, 0x02, 0x02, 0x00, 0x9A, 0xFC, 0xD7, 0xF5, + 0xC5, 0xF5, 0xEC, 0x04, 0x02, 0x00, 0x9B, 0xFC, 0xD7, 0xF5, 0xC5, 0xF5, 0xEC, 0x06, 0x02, 0x00, + 0x9C, 0xFC, 0xD7, 0xF5, 0xC5, 0xF5, 0xEC, 0x08, 0x02, 0x00, 0x9D, 0xFC, 0xD7, 0xF5, 0xC5, 0xF5, + 0xEC, 0x0A, 0x02, 0x00, 0x18, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x2C, 0x27, 0x02, 0x00, 0x22, 0xFC, + 0xC0, 0xF3, 0xD6, 0xF3, 0x32, 0x27, 0x02, 0x00, 0x24, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x38, 0x27, + 0x02, 0x00, 0xC0, 0xFC, 0xA0, 0xF3, 0x50, 0xF6, 0x00, 0x00, 0x06, 0x00, 0x9E, 0xFC, 0xC0, 0xF3, + 0x83, 0xF5, 0x6E, 0x01, 0x04, 0x00, 0x9F, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x3E, 0x2C, 0x04, 0x00, + 0xA0, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x42, 0x2C, 0x04, 0x00, 0xA1, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, + 0x46, 0x2C, 0x04, 0x00, 0xA2, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x4A, 0x2C, 0x04, 0x00, 0xA3, 0xFC, + 0xC0, 0xF3, 0xD6, 0xF3, 0x4E, 0x2C, 0x04, 0x00, 0xA4, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x52, 0x2C, + 0x04, 0x00, 0x20, 0xFD, 0xF1, 0xF3, 0xAA, 0xF3, 0xD5, 0xFB, 0x08, 0x00, 0x21, 0xFD, 0xF1, 0xF3, + 0xAA, 0xF3, 0xD9, 0xFB, 0x0A, 0x00, 0x22, 0xFD, 0xF1, 0xF3, 0xAA, 0xF3, 0xDE, 0xFB, 0x16, 0x00, + 0x23, 0xFD, 0xF1, 0xF3, 0xAA, 0xF3, 0xE9, 0xFB, 0x0A, 0x00, 0x45, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, + 0xCA, 0x00, 0x02, 0x00, 0x47, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0x36, 0x01, 0x02, 0x00, 0x48, 0xFD, + 0xD4, 0xF4, 0xAA, 0xF3, 0x5C, 0x01, 0x02, 0x00, 0x49, 0xFD, 0xD4, 0xF4, 0xAA, 0xF3, 0x5E, 0x01, + 0x02, 0x00, 0x4A, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0x56, 0x01, 0x02, 0x00, 0x4B, 0xFD, 0xC0, 0xF3, + 0xAA, 0xF3, 0x58, 0x01, 0x02, 0x00, 0x4D, 0xFD, 0xF1, 0xF3, 0xAA, 0xF3, 0xEE, 0xFB, 0x08, 0x00, + 0x4F, 0xFD, 0xE8, 0xF4, 0xAA, 0xF3, 0x96, 0x2B, 0x02, 0x00, 0xC2, 0xFD, 0xDE, 0xF4, 0xAA, 0xF3, + 0x00, 0x00, 0x02, 0x00, 0x40, 0xFD, 0xE9, 0xF3, 0xAA, 0xF3, 0x78, 0x01, 0x02, 0x00, 0x24, 0xFD, + 0x01, 0xF5, 0xAA, 0xF3, 0x00, 0x00, 0x02, 0x00, 0x91, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0xCC, 0x1E, + 0x02, 0x00, 0x93, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0xD2, 0x1E, 0x02, 0x00, 0x8F, 0xFD, 0x0E, 0xF5, + 0xAA, 0xF3, 0x00, 0x00, 0x08, 0x00, 0xC1, 0xFD, 0x92, 0xF6, 0xAA, 0xF3, 0xC8, 0x00, 0x02, 0x00, + 0xC6, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0x20, 0x30, 0x04, 0x00, 0x25, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, + 0x62, 0x01, 0x02, 0x00, 0x89, 0xFD, 0x96, 0xF4, 0xAA, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xFD, + 0x0E, 0xF4, 0xAA, 0xF3, 0x7E, 0x2C, 0x24, 0x00, 0x46, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0x7A, 0x01, + 0x06, 0x00, 0x86, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0xB0, 0x26, 0x06, 0x00, 0x87, 0xFD, 0xC0, 0xF3, + 0xAA, 0xF3, 0x76, 0x2C, 0x06, 0x00, 0x8B, 0xFD, 0x96, 0xF9, 0xAA, 0xF3, 0x00, 0x00, 0x12, 0x00, + 0x8B, 0xFD, 0x96, 0xF9, 0xAA, 0xF3, 0x00, 0x00, 0x12, 0x00, 0x8E, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, + 0xEE, 0x14, 0x02, 0x00, 0x80, 0xFD, 0xEF, 0xF4, 0xAA, 0xF3, 0x22, 0x00, 0x02, 0x00, 0x81, 0xFD, + 0xEF, 0xF4, 0xAA, 0xF3, 0x22, 0x02, 0x02, 0x00, 0x82, 0xFD, 0xEF, 0xF4, 0xAA, 0xF3, 0x22, 0x04, + 0x02, 0x00, 0x83, 0xFD, 0xEF, 0xF4, 0xAA, 0xF3, 0x22, 0x06, 0x02, 0x00, 0x84, 0xFD, 0xEF, 0xF4, + 0xAA, 0xF3, 0x22, 0x08, 0x02, 0x00, 0x85, 0xFD, 0xEF, 0xF4, 0xAA, 0xF3, 0x22, 0x0A, 0x02, 0x00, + 0x00, 0xF1, 0x46, 0x00, 0x64, 0xF3, 0xF6, 0x00, 0x00, 0x03, 0x8E, 0xF7, 0x1F, 0x00, 0x34, 0x01, + 0xC8, 0x00, 0x96, 0x01, 0xCC, 0x00, 0xFA, 0x00, 0x78, 0x01, 0xD2, 0x25, 0x18, 0x01, 0xCC, 0x1E, + 0xC8, 0x00, 0x00, 0x00, 0x02, 0x15, 0x00, 0x00, 0x06, 0x17, 0x12, 0x01, 0x03, 0x00, 0xAE, 0x00, + 0xEC, 0x00, 0x44, 0x00, 0xDC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x09, 0x08, 0x24, 0x28, 0x06, + 0x0C, 0x18, 0x08, 0x30, 0x14, 0x0C, 0x08, 0x36, 0x10, 0x12, 0xA1, 0xB6, 0x14, 0xB6, 0x50, 0xB7, + 0x59, 0xB7, 0x25, 0xB6, 0xCE, 0xB6, 0x93, 0xB6, 0x15, 0x1C, 0xD0, 0x1A, 0x15, 0x1C, 0x8B, 0x1B, + 0xEE, 0x1A, 0xCB, 0x1A, 0xD2, 0x1B, 0xF1, 0x1B, 0x06, 0x1C, 0x48, 0x1C, 0x74, 0x1C, 0x74, 0x1B, + 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, + 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x23, 0x46, 0x23, 0x46, 0x23, 0x46, 0x1C, 0x47, 0x1C, 0x47, + 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, + 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1D, 0x47, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, + 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, + 0x9A, 0x48, 0x33, 0x48, 0x78, 0x49, 0x78, 0x49, 0x79, 0x49, 0x79, 0x49, 0x79, 0x49, 0x79, 0x49, + 0x7A, 0x49, 0x7A, 0x49, 0x7A, 0x49, 0x7A, 0x49, 0x7B, 0x49, 0x7B, 0x49, 0x7B, 0x49, 0x7C, 0x49, + 0xD8, 0x03, 0xDC, 0x03, 0xE0, 0x03, 0xE4, 0x03, 0xF0, 0x03, 0xF4, 0x03, 0xF8, 0x03, 0x0A, 0x04, + 0x0E, 0x04, 0x12, 0x04, 0x16, 0x04, 0x0C, 0x04, 0x10, 0x04, 0x14, 0x04, 0x18, 0x04, 0x1C, 0x04, + 0x20, 0x04, 0x24, 0x04, 0x28, 0x04, 0x4C, 0x04, 0x50, 0x04, 0x54, 0x04, 0x58, 0x04, 0x5C, 0x04, + 0x60, 0x04, 0x64, 0x04, 0x68, 0x04, 0x6C, 0x04, 0x70, 0x04, 0x74, 0x04, 0x7D, 0x04, 0x81, 0x04, + 0x85, 0x04, 0x89, 0x04, 0x8D, 0x04, 0x10, 0x00, 0x8E, 0x19, 0xAC, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x3C, 0x0C, 0x00, 0x00, 0xFF, 0x3F, 0x44, 0x04, 0x00, 0x00, 0xD3, 0x22, 0x44, 0x04, + 0x9C, 0x02, 0xCB, 0x54, 0x44, 0x04, 0x00, 0x00, 0x01, 0x00, 0x44, 0x04, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x0C, 0x71, 0x00, 0x30, 0x50, 0x20, 0x00, 0x80, 0xBF, 0x1F, 0xA6, 0x28, 0x00, 0x0B, 0x02, + 0x60, 0x84, 0x4C, 0x00, 0x02, 0x00, 0x4B, 0x1C, 0x98, 0x00, 0x00, 0x00, 0x20, 0x0B, 0x34, 0x04, + 0xFD, 0x34, 0x34, 0x00, 0x38, 0x04, 0xFD, 0x34, 0x34, 0x00, 0x3C, 0x04, 0x01, 0x00, 0x10, 0x00, + 0x00, 0x08, 0x00, 0x52, 0x14, 0x00, 0x04, 0x08, 0x0E, 0x32, 0x00, 0xA6, 0x10, 0x08, 0xC4, 0x03, + 0x50, 0x60, 0x18, 0x08, 0xF0, 0x3F, 0xFC, 0x01, 0x10, 0x0C, 0x00, 0x00, 0x80, 0x04, 0x14, 0x0C, + 0x00, 0x00, 0x00, 0x41, 0x20, 0x0C, 0xB0, 0x00, 0xB0, 0xB8, 0x24, 0x0C, 0x00, 0x00, 0xAB, 0x05, + 0x2C, 0x0C, 0x80, 0x05, 0x00, 0xFF, 0x30, 0x0C, 0x00, 0x00, 0xB0, 0x04, 0x34, 0x0C, 0x03, 0x00, + 0x00, 0xE8, 0x44, 0x0C, 0x04, 0x00, 0xFF, 0x0F, 0x00, 0x10, 0x2E, 0x00, 0x0C, 0xE3, 0x44, 0x04, + 0x00, 0x00, 0x01, 0x04, 0x44, 0x04, 0x00, 0x00, 0x01, 0x01, 0x44, 0x04, 0x00, 0x00, 0x01, 0x00, + 0x44, 0x04, 0x00, 0x00, 0x01, 0x04, 0x44, 0x04, 0x00, 0x00, 0x80, 0x03, 0x48, 0x0C, 0x00, 0x00, + 0x7F, 0x00, 0x04, 0x04, 0x08, 0x48, 0x00, 0x00, 0x04, 0x04, 0x08, 0x40, 0x00, 0x00, 0x00, 0x0C, + 0x71, 0x00, 0x30, 0x30, 0x00, 0x00, 0x5E, 0x40, 0x01, 0x00, 0x18, 0x00, 0x36, 0xC0, 0xE8, 0x0E, + 0x1C, 0x00, 0x78, 0xC8, 0xA5, 0x40, 0x24, 0x00, 0x9E, 0xB0, 0xB9, 0x95, 0x08, 0x08, 0x00, 0xEA, + 0x40, 0x01, 0x0C, 0x08, 0x00, 0xEA, 0x00, 0x00, 0x1C, 0x08, 0x00, 0x00, 0x42, 0x07, 0x20, 0x08, + 0x7B, 0x00, 0xD4, 0x09, 0x2C, 0x04, 0x14, 0x00, 0x50, 0x14, 0x30, 0x04, 0x28, 0x0F, 0x28, 0x7F, + 0x18, 0x08, 0x20, 0x00, 0xFC, 0x01, 0x04, 0x10, 0x69, 0x00, 0xFD, 0xC3, 0x08, 0x10, 0x69, 0x00, + 0xFD, 0xC3, 0x08, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0C, + 0x00, 0x00, 0x7F, 0x00, 0x04, 0x04, 0x08, 0x48, 0x02, 0x00, 0x00, 0x00, 0x5E, 0x48, 0x00, 0x00, + 0x04, 0x04, 0x08, 0x40, 0x02, 0x00, 0x00, 0x0C, 0x71, 0x00, 0x30, 0x50, 0x00, 0x00, 0x5E, 0x48, + 0x01, 0x00, 0x18, 0x00, 0x3A, 0xC0, 0xE8, 0x04, 0x1C, 0x00, 0x78, 0xD0, 0xA5, 0x40, 0x24, 0x00, + 0x9E, 0xB0, 0xB9, 0x85, 0x2C, 0x04, 0x14, 0x00, 0x50, 0x14, 0x30, 0x04, 0x28, 0x0F, 0x28, 0x7F, + 0x08, 0x08, 0x00, 0xEA, 0x40, 0x01, 0x0C, 0x08, 0x00, 0xEA, 0x00, 0x00, 0x1C, 0x08, 0x00, 0x00, + 0x42, 0x07, 0x20, 0x08, 0x7B, 0x00, 0xD4, 0x09, 0x18, 0x08, 0xF0, 0x3F, 0xFC, 0x01, 0x04, 0x10, + 0x69, 0x00, 0xDD, 0xCD, 0x08, 0x10, 0x69, 0x00, 0xDD, 0xCD, 0x08, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x40, 0x01, 0x41, 0x01, 0x0C, 0x04, 0x40, 0x04, + 0x41, 0x04, 0x10, 0x04, 0xD6, 0x08, 0x56, 0x0A, 0x14, 0x04, 0x42, 0x02, 0x56, 0x0A, 0x18, 0x04, + 0x56, 0x0A, 0x40, 0x02, 0x1C, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x20, 0x04, 0xC2, 0x00, 0xD6, 0x08, + 0x24, 0x04, 0xD6, 0x08, 0xC0, 0x00, 0x28, 0x04, 0xC2, 0x08, 0xC2, 0x28, 0x08, 0x04, 0x40, 0x01, + 0x41, 0x01, 0x0C, 0x04, 0x00, 0x01, 0x01, 0x01, 0x10, 0x04, 0x56, 0x0A, 0x56, 0x0A, 0x14, 0x04, + 0x42, 0x02, 0x56, 0x0A, 0x18, 0x04, 0x56, 0x0A, 0x40, 0x02, 0x1C, 0x04, 0x42, 0x0A, 0x42, 0x2A, + 0x20, 0x04, 0x42, 0x02, 0x56, 0x0A, 0x24, 0x04, 0x56, 0x0A, 0x40, 0x02, 0x28, 0x04, 0x42, 0x0A, + 0x42, 0x2A, 0x08, 0x04, 0x40, 0x01, 0x41, 0x01, 0x0C, 0x04, 0x40, 0x04, 0x41, 0x04, 0x10, 0x04, + 0xCE, 0x08, 0x4E, 0x0A, 0x14, 0x04, 0x42, 0x02, 0x4E, 0x0A, 0x18, 0x04, 0x4E, 0x0A, 0x40, 0x02, + 0x1C, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x20, 0x04, 0xC2, 0x00, 0xCE, 0x08, 0x24, 0x04, 0xCE, 0x08, + 0xC0, 0x00, 0x28, 0x04, 0xC2, 0x08, 0xC2, 0x28, 0x08, 0x04, 0x40, 0x01, 0x41, 0x01, 0x0C, 0x04, + 0x00, 0x01, 0x01, 0x01, 0x10, 0x04, 0x4E, 0x0A, 0x4E, 0x0A, 0x14, 0x04, 0x42, 0x02, 0x4E, 0x0A, + 0x18, 0x04, 0x4E, 0x0A, 0x40, 0x02, 0x1C, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x20, 0x04, 0x42, 0x02, + 0x4E, 0x0A, 0x24, 0x04, 0x4E, 0x0A, 0x40, 0x02, 0x28, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x05, 0x00, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, + 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, + 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, + 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x17, 0xA0, 0x17, 0xA0, 0x17, + 0xA0, 0x18, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, + 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, + 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, + 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, + 0xFF, 0x06, 0x00, 0x00, 0x65, 0x00, 0x65, 0x00, 0x65, 0x00, 0x65, 0x00, 0x5D, 0x00, 0x52, 0x00, + 0x48, 0x00, 0x40, 0x00, 0x38, 0x00, 0x31, 0x00, 0x2C, 0x00, 0x27, 0x00, 0x23, 0x00, 0x1F, 0x00, + 0x00, 0x00, 0x65, 0x00, 0x65, 0x00, 0x65, 0x00, 0x65, 0x00, 0x5D, 0x00, 0x52, 0x00, 0x48, 0x00, + 0x40, 0x00, 0x38, 0x00, 0x31, 0x00, 0x2C, 0x00, 0x27, 0x00, 0x23, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, + 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x15, 0x00, 0x6E, 0x6F, 0x6E, 0x2D, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, + 0x53, 0x53, 0x49, 0x44, 0x20, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x01, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x48, 0x45, 0x52, 0x4D, 0x45, 0x53, 0x20, 0x32, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x03, 0x00, 0x15, 0x00, 0x6E, 0x6F, 0x6E, 0x2D, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, + 0x69, 0x65, 0x64, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x48, 0x45, 0x52, 0x4D, 0x45, 0x53, 0x20, 0x32, 0x00, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, + 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x69, 0x72, 0x73, 0x74, 0x20, 0x57, 0x61, + 0x76, 0x65, 0x4C, 0x41, 0x4E, 0x20, 0x49, 0x49, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x0F, 0xF0, 0x0F, 0x0F, 0x00, 0x50, 0x01, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x14, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x30, 0x00, 0xFF, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, + 0x0A, 0x00, 0x0A, 0x00, 0x0B, 0x00, 0x0B, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x0A, 0x00, + 0x00, 0x00, 0x02, 0x01, 0x02, 0x04, 0x0B, 0x16, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x82, 0x84, + 0x8B, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, 0x1B, 0x00, 0x17, 0x00, 0x11, 0x00, 0x10, 0x00, 0x0B, 0x00, + 0x0B, 0x00, 0x09, 0x00, 0x17, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0D, 0x00, 0x0B, 0x00, 0x09, 0x00, + 0x08, 0x00, 0x07, 0x00, 0x0D, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x08, 0x00, 0x05, 0x00, 0x05, 0x00, + 0xD8, 0x0C, 0xC0, 0x08, 0x90, 0x0D, 0x60, 0x09, 0x48, 0x0E, 0x30, 0x0A, 0x24, 0x0F, 0x18, 0x0B, + 0x0B, 0x6E, 0x0B, 0x37, 0x02, 0x14, 0x01, 0x0A, 0xFF, 0x0F, 0xF0, 0x0F, 0xFF, 0x0F, 0xF0, 0x0F, + 0xFF, 0x0F, 0xF0, 0x0F, 0xFF, 0x0F, 0xF0, 0x0F, 0xFF, 0x0F, 0xF0, 0x0F, 0xFF, 0x0F, 0xF0, 0x0F, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xDD, 0x00, 0x50, 0xF2, 0x01, 0x01, 0x00, + 0x00, 0x50, 0xF2, 0x05, 0x02, 0x00, 0x00, 0x50, 0xF2, 0x02, 0x00, 0x50, 0xF2, 0x04, 0x02, 0x00, + 0x00, 0x50, 0xF2, 0x00, 0x00, 0x50, 0xF2, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x15, 0x00, 0x02, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x04, 0x00, 0x10, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x15, 0x00, 0x20, 0x00, 0x11, 0x00, 0x20, 0x00, 0x16, 0x26, 0xE2, 0x2B, 0xEA, 0x2D, 0xC4, 0x2D, + 0xEE, 0x2D, 0x7E, 0x2C, 0x1E, 0x2E, 0x22, 0x2E, 0xFF, 0xFF, 0x2C, 0x2E, 0x00, 0x00, 0x4E, 0x28, + 0xD8, 0x2B, 0x22, 0x2E, 0xFF, 0xFF, 0x00, 0x00, 0x16, 0x26, 0xE2, 0x2B, 0xEA, 0x2D, 0xFF, 0xFF, + 0xEE, 0x2D, 0x7E, 0x2C, 0x1E, 0x2E, 0x22, 0x2E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x2C, 0x2E, 0x00, 0x00, 0xE2, 0x2B, 0x34, 0x2E, 0x22, 0x2E, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2A, 0x00, 0x00, 0x08, 0x32, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x00, 0x60, 0x1D, 0x00, 0x00, 0x00, 0x0D, 0x81, + 0x00, 0x60, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0xDD, 0x00, 0xFF, 0xFF, 0x97, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x19, 0x0A, 0x09, 0x46, 0x1C, 0x60, 0x18, 0x00, 0x19, 0x1D, 0x09, 0x42, + 0x1C, 0x60, + +}; /* fw_image_2_data */ + +static const hcf_8 fw_image_3_data[] = { + 0x00, 0x60, 0x46, 0x74, 0xCD, 0xE2, 0x04, 0xE1, 0x02, 0x60, 0x00, 0xE1, 0x82, 0xF3, 0x21, 0x60, + 0xCE, 0x61, 0x60, 0x40, 0x01, 0x2B, 0x02, 0x00, 0x21, 0x60, 0x56, 0x61, 0x0F, 0x60, 0xE8, 0x64, + 0x59, 0xD1, 0x58, 0xD9, 0x59, 0xD1, 0x58, 0xD9, 0x3F, 0x44, 0x40, 0x26, 0x05, 0x00, 0x18, 0x60, + 0x22, 0xF3, 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x50, 0x3F, 0x40, 0x02, 0x2B, 0x03, 0x00, 0x18, 0x60, + 0x74, 0x78, 0xFF, 0xFF, 0x04, 0x29, 0xFE, 0x01, 0xC4, 0xE2, 0x43, 0x64, 0x3A, 0xDB, 0x82, 0xF3, + 0xFF, 0xFF, 0x60, 0x41, 0x3F, 0x44, 0xFF, 0x01, 0x3F, 0x40, 0x40, 0x26, 0x05, 0x00, 0x18, 0x60, + 0x20, 0xF3, 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x52, 0xC4, 0xE2, 0x00, 0x63, 0x81, 0xFD, 0x32, 0x7B, + 0x4D, 0xE2, 0xBF, 0xFE, 0xC4, 0xE2, 0x41, 0xFF, 0xE0, 0xFE, 0xE1, 0xFE, 0xE2, 0xFE, 0x43, 0xFF, + 0x44, 0xFF, 0x46, 0xFF, 0x83, 0xF3, 0x62, 0xFF, 0x60, 0x40, 0x05, 0x36, 0x2D, 0xFF, 0x07, 0x36, + 0xD5, 0xFE, 0x08, 0xE1, 0x88, 0x60, 0x85, 0x71, 0x8D, 0xE2, 0xA3, 0x60, 0x30, 0x78, 0xFF, 0xFF, + 0x00, 0x60, 0x10, 0x62, 0x1A, 0x60, 0x58, 0x4D, 0xB4, 0x78, 0xFF, 0xFF, 0x64, 0x41, 0xA9, 0x9C, + 0x60, 0x45, 0x1A, 0x60, 0x58, 0x4D, 0x88, 0x78, 0xFF, 0xFF, 0x82, 0xF1, 0x09, 0x60, 0xB4, 0x61, + 0x64, 0x44, 0x01, 0x27, 0x24, 0x00, 0x60, 0x40, 0x0E, 0x3A, 0x0D, 0x00, 0x01, 0x7C, 0x10, 0x60, + 0xF2, 0xF9, 0x44, 0x60, 0x08, 0x7C, 0x10, 0x60, 0xC4, 0xF9, 0x12, 0x60, 0xE5, 0xF1, 0x02, 0x60, + 0xB0, 0x61, 0xB1, 0x9C, 0x26, 0x00, 0x00, 0x7C, 0x10, 0x60, 0xF2, 0xF9, 0x40, 0x60, 0x08, 0x7C, + 0x10, 0x60, 0xC4, 0xF9, 0x12, 0x60, 0xE5, 0xF1, 0x02, 0x60, 0x90, 0x61, 0xB1, 0x9C, 0x09, 0x60, + 0x67, 0x65, 0xFF, 0xB4, 0xC4, 0x85, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x81, 0x12, 0x00, 0xFF, 0xB4, + 0xED, 0xA0, 0x25, 0x60, 0xCC, 0x61, 0x04, 0x04, 0xE2, 0xA0, 0xD9, 0x81, 0x01, 0x04, 0xD9, 0x81, + 0xA1, 0xD1, 0x02, 0x60, 0x50, 0x61, 0x1F, 0x60, 0xF6, 0x65, 0xE0, 0x84, 0x44, 0xD3, 0xB1, 0x9C, + 0xC8, 0x81, 0x61, 0x47, 0x00, 0x7E, 0xE9, 0x81, 0x07, 0x60, 0xF0, 0x65, 0xA5, 0x81, 0x0B, 0xB9, + 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x85, 0xB5, 0x85, 0x04, 0x60, 0x44, 0x62, 0x1A, 0x60, 0x58, 0x4D, + 0x88, 0x78, 0xFF, 0xFF, 0x82, 0xF3, 0xC8, 0x61, 0x61, 0x54, 0xCD, 0xE2, 0x60, 0x40, 0x01, 0x27, + 0x2E, 0x00, 0xCC, 0x84, 0xE0, 0x85, 0x15, 0x60, 0xA2, 0xE7, 0x1F, 0x60, 0x86, 0x64, 0x1A, 0x60, + 0x58, 0x4F, 0x7D, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0xA2, 0x64, 0x1A, 0x60, 0x58, 0x4F, 0x7D, 0x78, + 0xFF, 0xFF, 0x1F, 0x60, 0xBE, 0x64, 0x1A, 0x60, 0x58, 0x4F, 0x7D, 0x78, 0xFF, 0xFF, 0x1F, 0x60, + 0xDA, 0x64, 0x1A, 0x60, 0x58, 0x4F, 0x7D, 0x78, 0xFF, 0xFF, 0x75, 0x64, 0x06, 0x61, 0x61, 0x48, + 0x60, 0x44, 0x80, 0xBC, 0xFF, 0xB4, 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x21, 0x60, + 0xEC, 0x7C, 0x07, 0x60, 0xE9, 0xF9, 0x21, 0x60, 0x74, 0x63, 0x14, 0x61, 0x21, 0x00, 0x11, 0x60, + 0x62, 0xF1, 0xFF, 0xB4, 0xED, 0xA0, 0x64, 0x41, 0x04, 0x04, 0xE2, 0xA0, 0xD9, 0x81, 0x01, 0x04, + 0xD9, 0x81, 0xA1, 0xD1, 0x10, 0x60, 0x91, 0xF3, 0x64, 0x41, 0xFF, 0xB1, 0xFF, 0x60, 0x00, 0x65, + 0xA4, 0x84, 0x34, 0x94, 0xA2, 0xDB, 0x5A, 0xD3, 0x64, 0x41, 0xA5, 0x81, 0xFF, 0xB4, 0x34, 0x94, + 0xA2, 0xDB, 0x22, 0x60, 0x58, 0x7C, 0x07, 0x60, 0xE9, 0xF9, 0x21, 0x60, 0x02, 0x63, 0x13, 0x61, + 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0x07, 0x60, 0xE9, 0xF3, 0x31, 0x40, 0x80, 0x26, + 0x36, 0xA4, 0x07, 0x60, 0xE9, 0xFB, 0x60, 0x43, 0x09, 0x61, 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, + 0xFF, 0xFF, 0x82, 0xF3, 0x22, 0x60, 0xC4, 0x61, 0x00, 0x7C, 0x7E, 0x63, 0x59, 0xD9, 0xFE, 0x1F, + 0x60, 0x40, 0x01, 0x27, 0x03, 0x00, 0x23, 0x60, 0x46, 0x65, 0x15, 0x00, 0xFF, 0xB4, 0xF9, 0xA0, + 0x23, 0x60, 0x68, 0x65, 0x01, 0x7C, 0x0D, 0x04, 0xED, 0xA0, 0x23, 0x60, 0x8A, 0x65, 0x11, 0x7C, + 0x08, 0x04, 0xE2, 0xA0, 0x23, 0x60, 0xAC, 0x65, 0x21, 0x7C, 0x03, 0x04, 0x23, 0x60, 0xCE, 0x65, + 0x31, 0x7C, 0x64, 0x5F, 0x64, 0xFB, 0xA5, 0xD3, 0xDA, 0x85, 0xF0, 0xA0, 0x22, 0x60, 0xC4, 0x61, + 0x08, 0x06, 0x40, 0x54, 0x58, 0x53, 0x08, 0xFF, 0xA2, 0x60, 0xE7, 0x64, 0x43, 0xFB, 0x08, 0xFF, + 0xFF, 0x01, 0x60, 0x43, 0x60, 0x46, 0xA5, 0xD1, 0xDA, 0x85, 0xA5, 0xD3, 0xDA, 0x85, 0x59, 0xD9, + 0x59, 0xDB, 0x59, 0xD9, 0x59, 0xDB, 0xFB, 0x1F, 0x0C, 0x63, 0xA5, 0xD1, 0xDA, 0x85, 0xA5, 0xD3, + 0xDA, 0x85, 0x59, 0xD9, 0x59, 0xDB, 0x59, 0xD9, 0x59, 0xDB, 0xF7, 0x1F, 0x66, 0x44, 0x0E, 0x63, + 0x53, 0x93, 0x60, 0x40, 0x10, 0x36, 0x07, 0x00, 0x65, 0x44, 0x48, 0xD3, 0x59, 0xD9, 0x59, 0xDB, + 0x59, 0xD9, 0x59, 0xDB, 0xFB, 0x1F, 0x12, 0x60, 0xBC, 0xF1, 0x64, 0xF3, 0x64, 0x43, 0xDB, 0x81, + 0x25, 0x60, 0x5A, 0x65, 0x60, 0x40, 0x01, 0x37, 0x12, 0x00, 0x11, 0x37, 0x17, 0x00, 0x21, 0x37, + 0x1D, 0x00, 0x31, 0x37, 0x22, 0x00, 0xA3, 0xD1, 0x12, 0x60, 0xB7, 0xF5, 0x64, 0x44, 0xFF, 0xB4, + 0x12, 0x60, 0xB6, 0xFB, 0x64, 0x47, 0xFF, 0xB4, 0x12, 0x60, 0xAD, 0xF1, 0x1D, 0x00, 0xA1, 0xD3, + 0x12, 0x60, 0xB8, 0xF5, 0xFF, 0xB4, 0x12, 0x60, 0xAE, 0xF1, 0x16, 0x00, 0xA1, 0xD3, 0x12, 0x60, + 0xB9, 0xF5, 0x60, 0x47, 0xFF, 0xB4, 0x12, 0x60, 0xAF, 0xF1, 0x0E, 0x00, 0x59, 0xD3, 0x12, 0x60, + 0xBA, 0xF5, 0xFF, 0xB4, 0x12, 0x60, 0xB0, 0xF1, 0x07, 0x00, 0x59, 0xD3, 0x12, 0x60, 0xBB, 0xF5, + 0x60, 0x47, 0xFF, 0xB4, 0x12, 0x60, 0xB1, 0xF1, 0x12, 0x60, 0xB5, 0xFB, 0x12, 0x60, 0xB2, 0xF9, + 0x66, 0x42, 0xFC, 0xA2, 0xA2, 0xD3, 0x24, 0x60, 0x48, 0x63, 0xCC, 0x84, 0xE8, 0x84, 0xCC, 0x81, + 0x63, 0x45, 0xA6, 0xD3, 0xDA, 0x82, 0xFF, 0xB4, 0xFF, 0xFF, 0x03, 0x03, 0x60, 0x40, 0x80, 0x2B, + 0x03, 0x00, 0xDA, 0x86, 0xCD, 0x81, 0xF5, 0x01, 0x00, 0xB9, 0xA6, 0xD3, 0x0B, 0x03, 0x5A, 0xD1, + 0xDA, 0x86, 0xFF, 0xB4, 0xE0, 0x84, 0xC4, 0x84, 0x5C, 0x90, 0xBD, 0xD9, 0xFD, 0x02, 0xCD, 0x81, + 0x66, 0x42, 0xF2, 0x02, 0x5A, 0xD3, 0x24, 0x60, 0x86, 0x65, 0xD7, 0x80, 0xBD, 0xDB, 0xFD, 0x02, + 0x64, 0xF3, 0x15, 0x60, 0xDD, 0xF1, 0x60, 0x40, 0x01, 0x27, 0x09, 0x00, 0x64, 0x40, 0x10, 0x26, + 0x06, 0x00, 0x13, 0x64, 0xAD, 0xFB, 0x01, 0x60, 0x67, 0x64, 0x37, 0xFB, 0x09, 0x00, 0x08, 0x64, + 0xAD, 0xFB, 0x82, 0xF3, 0x01, 0x60, 0x67, 0x7C, 0x60, 0x40, 0x01, 0x27, 0x5B, 0x7C, 0x37, 0xF9, + 0x13, 0x60, 0x5B, 0xF1, 0x64, 0xF3, 0x15, 0x60, 0xD2, 0xF9, 0x15, 0x60, 0xD6, 0xF9, 0x60, 0x40, + 0x01, 0x27, 0x0A, 0x00, 0xFF, 0xB5, 0x10, 0x60, 0xA8, 0x63, 0x65, 0x41, 0xCD, 0x81, 0x06, 0xA3, + 0xFD, 0x02, 0xFA, 0xA3, 0xA3, 0xD3, 0x0F, 0x00, 0x01, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x11, 0x60, + 0x14, 0x61, 0xA1, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, 0x08, 0xA1, 0xFB, 0x02, 0xFC, 0xA1, 0xA1, 0xD3, + 0x15, 0x60, 0xD2, 0xF1, 0xFF, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, 0x04, 0x07, 0x15, 0x60, 0xD2, 0xFB, + 0x15, 0x60, 0xD6, 0xFB, 0x25, 0x60, 0x7A, 0x63, 0x24, 0x60, 0x08, 0x65, 0x12, 0x60, 0xB6, 0xF1, + 0x23, 0x60, 0xF0, 0x61, 0x25, 0x60, 0x68, 0x64, 0x40, 0x4F, 0x04, 0x64, 0xC3, 0x60, 0x58, 0x4D, + 0x25, 0x78, 0xFF, 0xFF, 0x25, 0x60, 0x82, 0x63, 0x12, 0x60, 0xB5, 0xF1, 0x24, 0x60, 0x48, 0x65, + 0x25, 0x60, 0x66, 0x64, 0x40, 0x4F, 0x08, 0x64, 0xC3, 0x60, 0x58, 0x4D, 0x25, 0x78, 0xFF, 0xFF, + 0x64, 0xF3, 0x08, 0x7C, 0x38, 0xF9, 0x24, 0x60, 0xE0, 0x61, 0x60, 0x40, 0x01, 0x2B, 0x0E, 0x00, + 0x01, 0x37, 0x06, 0x00, 0x11, 0x37, 0x03, 0x00, 0x21, 0x3B, 0x1E, 0xA1, 0x1E, 0xA1, 0x1E, 0xA1, + 0x1C, 0x63, 0x24, 0x60, 0xC2, 0x64, 0x59, 0xD1, 0x58, 0xD9, 0xFD, 0x1F, 0x12, 0x60, 0xB2, 0xF3, + 0x00, 0x7C, 0x60, 0x45, 0x70, 0x62, 0x1A, 0x60, 0x58, 0x4D, 0x88, 0x78, 0xFF, 0xFF, 0x04, 0x29, + 0xFE, 0x01, 0x00, 0x60, 0x10, 0x62, 0x1A, 0x60, 0x58, 0x4D, 0xB4, 0x78, 0xFF, 0xFF, 0x01, 0x61, + 0xB1, 0x9C, 0x60, 0x45, 0x1A, 0x60, 0x58, 0x4D, 0x88, 0x78, 0xFF, 0xFF, 0x18, 0x60, 0x50, 0x78, + 0xFF, 0xFF, 0x44, 0xD3, 0x80, 0x7C, 0x60, 0x48, 0x60, 0x47, 0x00, 0x7F, 0xB0, 0x8A, 0xFF, 0xFF, + 0x01, 0x16, 0xFE, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xD5, 0x60, 0x84, 0xE7, 0x62, 0x47, 0x80, 0xBF, + 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x64, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, + 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x2D, 0x58, 0xFF, 0xFF, + 0x00, 0x7C, 0xBD, 0xD3, 0xD5, 0x60, 0x84, 0xE7, 0x60, 0x47, 0x80, 0xBF, 0x60, 0x4A, 0xBD, 0xD3, + 0x01, 0x16, 0xFE, 0x01, 0x90, 0x8A, 0xBD, 0xD3, 0x01, 0x16, 0xFE, 0x01, 0x90, 0x8A, 0xFF, 0xFF, + 0x01, 0x16, 0xFE, 0x01, 0xCD, 0x81, 0x95, 0x60, 0x84, 0xE7, 0xEB, 0x02, 0x2D, 0x58, 0xFF, 0xFF, + 0xD5, 0x60, 0x84, 0xE7, 0x62, 0x4A, 0x02, 0x64, 0x01, 0x16, 0xFE, 0x01, 0xCC, 0x84, 0xFF, 0xFF, + 0xFD, 0x02, 0x7C, 0x49, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x68, 0x5C, 0x7C, 0x49, 0xFF, 0xFF, + 0x01, 0x16, 0xFE, 0x01, 0x68, 0x44, 0x95, 0x60, 0x84, 0xE7, 0x2D, 0x58, 0xFF, 0xFF, 0x42, 0xFF, + 0x40, 0xFF, 0x3F, 0x40, 0x02, 0x27, 0x33, 0x00, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, + 0x3F, 0x40, 0x02, 0x27, 0x1B, 0x00, 0x60, 0xBC, 0x40, 0x40, 0xDD, 0xFE, 0x18, 0x60, 0x07, 0xF1, + 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x64, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, + 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x00, 0xEE, 0x19, 0x61, 0xCD, 0x81, + 0xFF, 0xFF, 0xFD, 0x02, 0x43, 0x45, 0x3F, 0x40, 0x02, 0x27, 0x11, 0x00, 0xAE, 0x4F, 0xFD, 0xB4, + 0x04, 0xBC, 0xA0, 0x5E, 0x00, 0x60, 0x02, 0x71, 0x8D, 0xE2, 0x40, 0xE1, 0xA1, 0xFF, 0x04, 0xAC, + 0xA0, 0x5E, 0x0F, 0x60, 0xA0, 0x71, 0x8D, 0xE2, 0xA1, 0xFF, 0xDD, 0xFE, 0x1E, 0x00, 0x43, 0x45, + 0x20, 0x44, 0x60, 0xBC, 0x40, 0x40, 0xAE, 0x4F, 0xFD, 0xB4, 0x04, 0xBC, 0xA0, 0x5E, 0xDD, 0xFE, + 0x00, 0x60, 0x02, 0x71, 0x8D, 0xE2, 0x40, 0xE1, 0xA1, 0xFF, 0x04, 0xAC, 0xA0, 0x5E, 0x00, 0x60, + 0xC8, 0x71, 0x8D, 0xE2, 0xA1, 0xFF, 0x0C, 0x60, 0x00, 0x62, 0x00, 0x60, 0x71, 0x7C, 0x10, 0x60, + 0x00, 0x65, 0x1A, 0x60, 0x58, 0x4D, 0x88, 0x78, 0xFF, 0xFF, 0x20, 0x60, 0x3C, 0x63, 0x1E, 0x61, + 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x14, 0x71, 0x8D, 0xE2, 0xA1, 0xFF, + 0x31, 0x44, 0x40, 0x26, 0x02, 0x00, 0x80, 0x26, 0x17, 0x00, 0x21, 0x60, 0xEC, 0x63, 0x07, 0x60, + 0xE9, 0xFD, 0x09, 0x61, 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0x31, 0x44, 0x40, 0x2A, + 0x14, 0x00, 0x31, 0x44, 0x7F, 0xB4, 0x40, 0x51, 0xAE, 0x4C, 0x10, 0x26, 0x0E, 0x00, 0x07, 0x60, + 0xEA, 0xFB, 0x31, 0x44, 0x80, 0xBC, 0x40, 0x51, 0x22, 0x60, 0x22, 0x63, 0x07, 0x60, 0xE9, 0xFD, + 0x09, 0x61, 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0x20, 0x60, 0xF0, 0x63, 0x03, 0x61, + 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x62, 0x19, 0x60, 0x8F, 0x7C, + 0x00, 0x60, 0xAC, 0x65, 0x1A, 0x60, 0x58, 0x4D, 0x88, 0x78, 0xFF, 0xFF, 0x80, 0xE1, 0xBF, 0xFE, + 0xA1, 0x4F, 0x70, 0xB4, 0x50, 0x36, 0xAF, 0x00, 0x20, 0x36, 0x03, 0x00, 0x18, 0x60, 0x24, 0x78, + 0xFF, 0xFF, 0x01, 0x60, 0x1A, 0xE1, 0xDF, 0xFE, 0x19, 0xFF, 0x00, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, + 0x3F, 0x40, 0x20, 0x2B, 0xA1, 0x00, 0x01, 0x16, 0xFE, 0x01, 0x38, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, + 0x68, 0x44, 0x01, 0x2A, 0x99, 0x00, 0x13, 0x60, 0x09, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, + 0x00, 0x3B, 0xA2, 0xDB, 0x64, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x9C, 0x47, 0x00, 0x43, 0x45, + 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x18, 0x60, 0x22, 0xF3, 0x3F, 0x40, 0x40, 0x26, 0x01, 0x00, + 0xA0, 0x50, 0x3F, 0x40, 0x02, 0x2B, 0x29, 0x00, 0xAE, 0x4F, 0xFD, 0xB4, 0xA0, 0x5E, 0xDD, 0xFE, + 0xAC, 0x4F, 0x10, 0xBC, 0xA0, 0x5C, 0xFF, 0xFF, 0x10, 0xAC, 0xA0, 0x5C, 0x00, 0x60, 0xC8, 0x71, + 0x8D, 0xE2, 0x40, 0xE1, 0x40, 0x29, 0xFE, 0x01, 0x0C, 0x60, 0x00, 0x62, 0x00, 0x60, 0x71, 0x7C, + 0x10, 0x60, 0x00, 0x65, 0x1A, 0x60, 0x58, 0x4D, 0x88, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0xC8, 0x71, + 0x8D, 0xE2, 0x40, 0xE1, 0x40, 0x29, 0xFE, 0x01, 0x01, 0x60, 0x08, 0xE1, 0x64, 0xF1, 0x82, 0xF9, + 0x05, 0x7C, 0x83, 0xF9, 0xDF, 0xFE, 0x19, 0xFF, 0xFF, 0xFF, 0x18, 0x60, 0x07, 0xF1, 0xAD, 0x4F, + 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x64, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, 0x64, 0x40, + 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0xBF, 0xFE, 0x45, 0x00, 0x18, 0x60, 0x07, 0xF1, + 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x64, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, + 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, + 0x40, 0x40, 0x02, 0x60, 0xEE, 0x64, 0x3F, 0x40, 0x02, 0x27, 0xC8, 0x64, 0x81, 0xFB, 0x82, 0xF9, + 0x05, 0x64, 0x83, 0xFB, 0xDF, 0xFE, 0x19, 0xFF, 0x26, 0x00, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, + 0x43, 0x45, 0xA4, 0xD1, 0xDA, 0x83, 0xC3, 0x85, 0x80, 0xE1, 0xDF, 0xFE, 0xBD, 0xD3, 0xFF, 0xFF, + 0x60, 0x48, 0x60, 0x47, 0x80, 0xBC, 0x00, 0x7F, 0x60, 0x4A, 0xD7, 0x80, 0xA1, 0xFF, 0xF6, 0x02, + 0xBF, 0xFE, 0x11, 0x00, 0x43, 0x45, 0xA4, 0xD1, 0xDA, 0x83, 0x0D, 0x18, 0x64, 0x44, 0x00, 0x61, + 0xFA, 0xA4, 0xDD, 0x81, 0xFD, 0x02, 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0xBF, 0xFE, + 0x02, 0x00, 0xF1, 0xFE, 0x01, 0x00, 0x25, 0x43, 0x21, 0xE1, 0x00, 0x64, 0xBF, 0xDB, 0x20, 0x44, + 0x20, 0x2A, 0x07, 0x00, 0x07, 0xB4, 0x04, 0x36, 0xC3, 0xFE, 0x06, 0x36, 0xCC, 0xFE, 0x07, 0x36, + 0xD5, 0xFE, 0x20, 0x44, 0xD8, 0xB4, 0x40, 0x40, 0x1F, 0x60, 0x2C, 0x63, 0xBD, 0xD3, 0x03, 0x61, + 0x0F, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x04, 0x61, 0x0B, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x06, 0x61, + 0x07, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x07, 0x61, 0x03, 0x1B, 0xC3, 0x60, 0x53, 0x78, 0xFF, 0xFF, + 0xA3, 0xD1, 0x40, 0x44, 0x20, 0x44, 0x07, 0xB5, 0xD4, 0x85, 0x35, 0x80, 0x24, 0x45, 0x1F, 0x60, + 0x6C, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, + 0x64, 0x43, 0xBD, 0xD3, 0xBD, 0xD1, 0x40, 0x44, 0x10, 0x27, 0x19, 0x00, 0x3F, 0x40, 0x02, 0x2B, + 0x06, 0x00, 0x24, 0x47, 0x08, 0x2B, 0x13, 0x00, 0x07, 0xB4, 0x01, 0x36, 0x11, 0x00, 0xFF, 0x60, + 0x7F, 0x65, 0x15, 0x60, 0xA2, 0x64, 0x24, 0x40, 0x08, 0x2B, 0xA4, 0x84, 0xA0, 0x57, 0xFF, 0xFF, + 0x64, 0x49, 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x16, 0xFD, 0x01, 0x00, 0x7F, 0xA3, 0xDB, 0xAB, 0x01, + 0x64, 0x42, 0x1A, 0x60, 0x58, 0x4D, 0xB4, 0x78, 0xFF, 0xFF, 0xBD, 0xD9, 0xA3, 0xDB, 0xA3, 0x01, + 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x64, 0x43, 0xBD, 0xD3, 0xA3, 0xD1, 0x40, 0x44, + 0x10, 0x2B, 0x16, 0x00, 0xBE, 0xD1, 0xFF, 0xFF, 0x15, 0x60, 0x80, 0xE7, 0x24, 0x40, 0x07, 0x27, + 0x04, 0x00, 0xAC, 0x4F, 0x10, 0xBC, 0x00, 0x7F, 0xA0, 0x5C, 0x64, 0x4A, 0xFF, 0xFF, 0x01, 0x16, + 0xFE, 0x01, 0x24, 0x40, 0x20, 0x27, 0x1D, 0x00, 0xAC, 0x4F, 0xEF, 0xB4, 0xA0, 0x5C, 0x19, 0x00, + 0x3F, 0x40, 0x02, 0x2B, 0x06, 0x00, 0x24, 0x47, 0x08, 0x2B, 0x13, 0x00, 0x07, 0xB4, 0x01, 0x36, + 0x11, 0x00, 0x15, 0x60, 0x22, 0x64, 0x24, 0x40, 0x08, 0x27, 0x80, 0xBC, 0x7C, 0x48, 0xBE, 0xD3, + 0xA0, 0x57, 0x60, 0x48, 0x64, 0x44, 0x80, 0xBC, 0xFF, 0xB4, 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, + 0xFE, 0x01, 0x69, 0x01, 0x01, 0x61, 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0x63, 0x01, + 0x28, 0xF3, 0xFF, 0xFF, 0x60, 0x47, 0x0F, 0xB4, 0x9A, 0x00, 0xFF, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x04, 0x64, 0x0F, 0x60, 0x9F, 0xFB, 0x27, 0x00, 0x0C, 0x64, 0x3F, 0x40, 0x02, 0x2B, 0x23, 0x00, + 0x29, 0xF1, 0x0F, 0x60, 0x9F, 0xFB, 0x5A, 0xD9, 0x1C, 0x60, 0xD0, 0x64, 0x7F, 0xFB, 0xFF, 0xFF, + 0x2D, 0xFF, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x22, 0x60, 0x22, 0x63, 0x09, 0x61, 0x1A, 0x60, + 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0x77, 0x00, 0xD3, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xD3, 0xFB, + 0x06, 0x64, 0x0F, 0x60, 0x9F, 0xFB, 0xFF, 0xFF, 0x2D, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x08, 0x64, 0x0F, 0x60, 0x9F, 0xFB, 0x1D, 0x60, 0x4F, 0x64, 0x7F, 0xFB, 0xFF, 0xFF, 0x2D, 0xFF, + 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x29, 0xF3, 0x11, 0x60, 0xF9, 0x65, 0x60, 0x5C, 0x3F, 0x40, + 0x02, 0x2B, 0x13, 0x00, 0x00, 0x37, 0x11, 0x00, 0x01, 0x3B, 0x55, 0x00, 0x11, 0x60, 0x19, 0x63, + 0xFF, 0xB7, 0x60, 0x5C, 0xA3, 0xD3, 0x08, 0xA3, 0x00, 0x7E, 0xD0, 0x80, 0xD7, 0x80, 0x02, 0x03, + 0xF9, 0x02, 0x49, 0x00, 0xF4, 0xA3, 0xA3, 0xD3, 0x05, 0x00, 0x00, 0xBC, 0xF2, 0xA4, 0x43, 0x03, + 0x42, 0x07, 0x64, 0x44, 0x64, 0xFB, 0x82, 0xFB, 0xC8, 0x64, 0x81, 0xFB, 0x07, 0x64, 0x83, 0xFB, + 0x1D, 0x60, 0x4F, 0x64, 0x7F, 0xFB, 0xFF, 0xFF, 0xDF, 0xFE, 0x00, 0x64, 0x19, 0xFF, 0xF0, 0x60, + 0xC7, 0x78, 0xFF, 0xFF, 0x88, 0xFF, 0xBA, 0x60, 0x98, 0x71, 0x8D, 0xE2, 0x01, 0x11, 0x09, 0x00, + 0x71, 0x40, 0x80, 0x27, 0xFB, 0x01, 0x88, 0xE2, 0xBA, 0x60, 0xD0, 0x64, 0x03, 0xFB, 0x8D, 0xFF, + 0x15, 0x00, 0x8D, 0xFF, 0xB1, 0x60, 0xED, 0x63, 0x06, 0x60, 0x0B, 0xFD, 0xFF, 0xFF, 0x62, 0xFF, + 0x1D, 0x60, 0x3C, 0x63, 0x7F, 0xFD, 0xFF, 0xFF, 0x1A, 0xFF, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, + 0xA4, 0x60, 0x7C, 0x63, 0x06, 0x60, 0x0B, 0xFD, 0xFF, 0xFF, 0x62, 0xFF, 0x29, 0xF5, 0x1F, 0x60, + 0x26, 0x63, 0x1E, 0x60, 0xF8, 0x64, 0xBD, 0xDB, 0x66, 0x44, 0xBD, 0xDB, 0x02, 0x64, 0xA3, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xF9, 0xFE, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x66, 0x01, 0x00, 0x36, + 0x67, 0x01, 0x01, 0x36, 0x69, 0x01, 0x02, 0x36, 0x7F, 0x01, 0x03, 0x36, 0x89, 0x01, 0x04, 0x36, + 0xC1, 0x01, 0x05, 0x36, 0xBF, 0x01, 0x06, 0x36, 0xF1, 0x01, 0x07, 0x36, 0xBB, 0x01, 0x08, 0x36, + 0x8A, 0x01, 0x09, 0x36, 0x0C, 0x00, 0x0A, 0x36, 0x0D, 0x00, 0x0B, 0x36, 0x0E, 0x00, 0x0C, 0x36, + 0x17, 0x00, 0x0D, 0x36, 0x0D, 0x00, 0x0E, 0x36, 0x1D, 0x00, 0x0F, 0x36, 0x41, 0x00, 0x02, 0x60, + 0x00, 0x64, 0x08, 0x00, 0x04, 0x60, 0x00, 0x64, 0x05, 0x00, 0x00, 0x60, 0x01, 0x64, 0x02, 0x00, + 0x20, 0x60, 0x00, 0x64, 0x32, 0x45, 0xB4, 0x85, 0x45, 0x52, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0xB2, 0x60, 0xD0, 0x63, 0x06, 0x60, 0x0B, 0xFD, 0x62, 0xFF, 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x3F, 0x40, 0x02, 0x2B, 0x15, 0x00, 0x88, 0xFF, 0xBA, 0x60, 0x98, 0x71, + 0x8D, 0xE2, 0x01, 0x11, 0x09, 0x00, 0x71, 0x40, 0x80, 0x27, 0xFB, 0x01, 0x88, 0xE2, 0xBA, 0x60, + 0xD0, 0x64, 0x03, 0xFB, 0x8D, 0xFF, 0x11, 0x00, 0x8D, 0xFF, 0x90, 0x60, 0x00, 0xE8, 0xB1, 0x60, + 0xED, 0x63, 0x04, 0x00, 0x91, 0x60, 0x00, 0xE8, 0xB2, 0x60, 0xB6, 0x63, 0x2A, 0xE8, 0x06, 0x60, + 0x0B, 0xFD, 0xFF, 0xFF, 0x62, 0xFF, 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0xD2, 0xF3, 0xFF, 0xFF, 0xEF, 0xB4, 0xD2, 0xFB, 0xAD, 0x4F, 0xFD, 0xB4, 0xA0, 0x5D, 0xD0, 0x60, + 0x00, 0xE8, 0x2A, 0xE8, 0xD9, 0x60, 0xFE, 0x64, 0x32, 0x45, 0xA4, 0x85, 0x45, 0x52, 0x99, 0xFF, + 0xA5, 0x4F, 0xFF, 0xB4, 0x07, 0xFB, 0x98, 0xFF, 0xA4, 0x60, 0x7C, 0x63, 0x06, 0x60, 0x0B, 0xFD, + 0x62, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x07, 0x02, + 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, 0x66, 0xFF, 0xBF, 0xFE, 0xA1, 0xFF, 0x82, 0xFF, + 0x88, 0xFF, 0x6C, 0x40, 0x41, 0xFF, 0xC4, 0xE2, 0x43, 0xFF, 0x5C, 0x49, 0x08, 0xE1, 0xA3, 0x60, + 0x30, 0x78, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x02, 0x02, 0xA1, 0xFF, 0xFF, 0xFF, + 0x82, 0xFF, 0x88, 0xFF, 0xA8, 0xE2, 0x01, 0x70, 0xAD, 0xF1, 0x00, 0x6B, 0x89, 0xFF, 0x64, 0x54, + 0x88, 0xFF, 0x9F, 0xFE, 0x02, 0x05, 0x64, 0x44, 0x60, 0x54, 0xCD, 0xE2, 0xC2, 0x64, 0x3A, 0xDB, + 0xBC, 0xFF, 0xB5, 0xFF, 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xB4, 0x40, 0x46, 0x3C, 0x44, 0x00, 0xBC, + 0xFF, 0xFF, 0x06, 0x03, 0x27, 0x40, 0x26, 0x22, 0x03, 0x00, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, + 0x27, 0x44, 0x20, 0x2A, 0x04, 0x00, 0xA0, 0x60, 0x00, 0xEA, 0xB0, 0x60, 0x00, 0xEA, 0x5C, 0x44, + 0x27, 0x44, 0x18, 0xB4, 0x40, 0x47, 0x00, 0xE1, 0xA4, 0xE2, 0xC4, 0xE2, 0x47, 0xFF, 0xB6, 0xFF, + 0xB7, 0xFF, 0xB4, 0xFF, 0x32, 0xF1, 0x08, 0x29, 0x09, 0x00, 0x64, 0x40, 0x07, 0x22, 0x06, 0x00, + 0x43, 0xFF, 0x27, 0x44, 0x10, 0xBC, 0x40, 0x47, 0x00, 0x64, 0x32, 0xFB, 0x31, 0x41, 0x3C, 0x44, + 0x01, 0xB1, 0x00, 0xBC, 0x0A, 0x02, 0x09, 0x03, 0x32, 0xF3, 0x00, 0x7C, 0x01, 0xB4, 0xFF, 0xFF, + 0x04, 0x03, 0x32, 0xF9, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xC8, 0x60, 0x09, 0x7D, 0x00, 0x60, + 0x00, 0x6B, 0x00, 0x64, 0x33, 0xFB, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xE1, 0x30, 0x40, 0x02, 0x36, 0xA1, 0xFF, 0x83, 0xFF, 0x8D, 0xFF, 0x5C, 0x44, 0x5C, 0x43, + 0x5C, 0x42, 0x5C, 0x41, 0x5C, 0x40, 0xAC, 0xFF, 0xAD, 0xFF, 0xE7, 0xE1, 0xB3, 0x60, 0xBE, 0x78, + 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x03, 0x02, 0x28, 0xE2, 0x40, 0xFF, 0xA1, 0xFF, + 0x84, 0xFF, 0xC1, 0x60, 0x6B, 0x64, 0x40, 0x42, 0xB7, 0x60, 0xA2, 0x64, 0x40, 0x40, 0x9C, 0xF3, + 0x65, 0xFB, 0x0F, 0x60, 0xF6, 0x63, 0xA9, 0xF3, 0xBD, 0xDB, 0x00, 0x60, 0x9A, 0x64, 0xBD, 0xDB, + 0x02, 0x64, 0xBD, 0xDB, 0x04, 0x64, 0xA3, 0xDB, 0x5C, 0x49, 0x0A, 0x64, 0x40, 0x4B, 0x5C, 0x5C, + 0x01, 0x60, 0x39, 0xE2, 0x04, 0x60, 0x00, 0x7A, 0x89, 0xFF, 0x03, 0x60, 0xFF, 0x73, 0x88, 0xFF, + 0xB7, 0x60, 0xA2, 0x78, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x06, 0x02, 0x40, 0xFF, + 0x42, 0xFF, 0x43, 0xFF, 0x44, 0xFF, 0x45, 0xFF, 0xA1, 0xFF, 0x88, 0xFF, 0x85, 0xFF, 0x21, 0xE1, + 0x5C, 0x40, 0xC3, 0x60, 0x53, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, + 0x01, 0x02, 0xA1, 0xFF, 0x86, 0xFF, 0x88, 0xFF, 0x5C, 0x46, 0x5C, 0x49, 0x5C, 0x40, 0xE1, 0x60, + 0x58, 0x4F, 0x7A, 0x78, 0xFF, 0xFF, 0xD0, 0x60, 0x58, 0x4F, 0xA2, 0x78, 0xFF, 0xFF, 0xEB, 0x60, + 0x58, 0x4F, 0x10, 0x78, 0xFF, 0xFF, 0xDD, 0x60, 0x58, 0x4F, 0xF5, 0x78, 0xFF, 0xFF, 0x1F, 0xE1, + 0xA3, 0xFF, 0xCA, 0x60, 0x7E, 0x78, 0xFF, 0xFF, 0x03, 0xE1, 0xA3, 0xFF, 0x1E, 0x60, 0x9E, 0x63, + 0x17, 0xFD, 0xAE, 0xFF, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x86, 0xF3, 0x87, 0xF3, 0xDC, 0x81, + 0x00, 0x7C, 0x01, 0x00, 0x00, 0xFA, 0x60, 0x46, 0xFE, 0x63, 0xA3, 0xD8, 0xFE, 0x1F, 0xCD, 0x81, + 0xD8, 0x84, 0xF8, 0x02, 0x86, 0xF3, 0x87, 0xF5, 0xDC, 0x81, 0x80, 0x67, 0x40, 0x4A, 0x05, 0x18, + 0x2A, 0x43, 0x02, 0xFC, 0x5F, 0x8A, 0x00, 0xF4, 0xFA, 0x01, 0x2E, 0x58, 0xFF, 0xFF, 0x88, 0xF3, + 0x06, 0x61, 0x00, 0x7C, 0x60, 0x46, 0xFE, 0x63, 0xA3, 0xD8, 0xFE, 0x1F, 0xCD, 0x81, 0x66, 0x44, + 0xD8, 0x84, 0xF8, 0x02, 0x09, 0x60, 0x2B, 0x7C, 0x88, 0xF3, 0x06, 0x61, 0x60, 0x46, 0x01, 0x63, + 0x76, 0xF8, 0x00, 0xFC, 0x63, 0x47, 0x06, 0xFA, 0x76, 0xF8, 0x03, 0x64, 0x77, 0xFA, 0xDF, 0x83, + 0x66, 0x44, 0xCD, 0x81, 0x02, 0xA6, 0xF4, 0x02, 0x2E, 0x58, 0xFF, 0xFF, 0x8A, 0xF1, 0x89, 0xF3, + 0x7C, 0x63, 0x8C, 0xFB, 0x60, 0x46, 0x01, 0xFC, 0xDC, 0x84, 0xD0, 0x80, 0x00, 0xFA, 0xFA, 0x04, + 0x8D, 0xFB, 0x60, 0x46, 0x00, 0x64, 0x00, 0xFA, 0x63, 0x44, 0x80, 0x7F, 0x01, 0xFA, 0x8A, 0xF3, + 0x89, 0xF1, 0xDC, 0x84, 0xD0, 0x84, 0x8B, 0xFB, 0x03, 0x60, 0x26, 0x61, 0xB5, 0x60, 0x58, 0x4D, + 0x8C, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x2E, 0xFB, 0x82, 0xFF, 0x40, 0x42, 0x87, 0xFF, 0x8B, 0xF3, + 0x93, 0xFB, 0x00, 0x64, 0x40, 0x50, 0x63, 0xFF, 0x60, 0xFF, 0x66, 0xFF, 0x65, 0xFF, 0x64, 0xFF, + 0x61, 0xFF, 0x62, 0xFF, 0x49, 0x60, 0x02, 0xE1, 0x52, 0x60, 0x02, 0xE1, 0x5C, 0x60, 0x02, 0xE1, + 0x65, 0x60, 0x02, 0xE1, 0x6B, 0x60, 0x02, 0xE1, 0x76, 0x60, 0x02, 0xE1, 0x41, 0x60, 0x02, 0xE1, + 0x04, 0x64, 0x0F, 0x60, 0x9F, 0xFB, 0x1F, 0x60, 0x64, 0x64, 0x7F, 0xFB, 0x2D, 0xFF, 0x0A, 0x61, + 0x41, 0x4B, 0x09, 0x60, 0x08, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0x8C, 0x78, 0xFF, 0xFF, 0xF0, 0x67, + 0x0E, 0xFA, 0x1F, 0x60, 0x0A, 0x64, 0x0F, 0x60, 0x93, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x2B, 0x41, 0x4D, 0x8B, 0xFF, 0xFF, 0xEA, 0x02, 0x09, 0x61, + 0x41, 0x4B, 0x09, 0x60, 0x08, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0x8C, 0x78, 0xFF, 0xFF, 0x1E, 0x60, + 0xFE, 0x64, 0x0F, 0x60, 0x93, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0x2B, 0x41, 0x4D, 0x8B, 0xFF, 0xFF, 0xEC, 0x02, 0x1E, 0x60, 0xB0, 0x78, 0xFF, 0xFF, + 0x00, 0xEA, 0x00, 0xEB, 0x50, 0x60, 0x03, 0xEA, 0x51, 0x60, 0x13, 0xEA, 0x52, 0x60, 0x30, 0xEA, + 0x53, 0x60, 0x40, 0xEA, 0x54, 0x60, 0x52, 0xEA, 0x55, 0x60, 0x6D, 0xEA, 0x56, 0x60, 0x71, 0xEA, + 0x57, 0x60, 0x8B, 0xEA, 0x58, 0x60, 0x47, 0xEA, 0x59, 0x60, 0xA0, 0xEA, 0x5A, 0x60, 0xB2, 0xEA, + 0x5B, 0x60, 0xC1, 0xEA, 0x5C, 0x60, 0xD7, 0xEA, 0x5D, 0x60, 0xEB, 0xEA, 0x5E, 0x60, 0xA0, 0xEA, + 0x50, 0x60, 0x36, 0xEB, 0x51, 0x60, 0x37, 0xEB, 0x52, 0x60, 0x20, 0xEB, 0x53, 0x60, 0xE4, 0xEB, + 0x54, 0x60, 0x34, 0xEB, 0x55, 0x60, 0x58, 0xEB, 0x56, 0x60, 0x48, 0xEB, 0x57, 0x60, 0xD0, 0xEB, + 0x58, 0x60, 0xC3, 0xEB, 0x59, 0x60, 0xFC, 0xEB, 0x5A, 0x60, 0x34, 0xEB, 0x5B, 0x60, 0x58, 0xEB, + 0x5C, 0x60, 0xC0, 0xEB, 0x5D, 0x60, 0xD0, 0xEB, 0x5E, 0x60, 0x91, 0xEB, 0x00, 0xEA, 0x00, 0xEB, + 0xE0, 0x60, 0x02, 0xEA, 0xE0, 0x60, 0x03, 0xEB, 0xA0, 0x60, 0x00, 0xEB, 0xB0, 0x60, 0x00, 0xEB, + 0xAB, 0x48, 0x40, 0x3B, 0x01, 0x00, 0xFC, 0x01, 0x00, 0xEB, 0x03, 0x60, 0x02, 0x64, 0xA0, 0xDB, + 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, + 0x00, 0xEA, 0x24, 0x44, 0xFF, 0xB4, 0x04, 0xFB, 0x50, 0x60, 0x00, 0x64, 0x05, 0xFB, 0x10, 0x60, + 0x10, 0x75, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x40, 0x00, 0x05, 0x60, + 0xF9, 0xF1, 0x42, 0x60, 0x08, 0x64, 0x09, 0x60, 0x19, 0x63, 0x64, 0x40, 0x01, 0x2B, 0x04, 0x00, + 0x42, 0x60, 0x09, 0x64, 0x0A, 0x60, 0x19, 0x63, 0x18, 0x60, 0x22, 0xFB, 0x04, 0x60, 0x00, 0xBC, + 0x18, 0x60, 0x1E, 0xFB, 0x18, 0x60, 0x1D, 0xFD, 0x1D, 0x60, 0x19, 0x63, 0x18, 0x60, 0x21, 0xFD, + 0x80, 0x60, 0x1C, 0x64, 0x3F, 0x40, 0x01, 0x2A, 0x02, 0x00, 0x60, 0x60, 0x1C, 0x64, 0x18, 0x60, + 0x23, 0xFB, 0x18, 0x60, 0x1F, 0xFB, 0x18, 0x60, 0x22, 0xF3, 0xA0, 0x50, 0xA0, 0x50, 0x0B, 0x60, + 0xF8, 0x63, 0xA3, 0xD1, 0x30, 0x60, 0x38, 0x61, 0xA1, 0xD3, 0xF8, 0xA3, 0x90, 0x84, 0xA2, 0xDB, + 0xA3, 0xD1, 0x59, 0xD3, 0x06, 0xA3, 0x90, 0x84, 0xA2, 0xDB, 0xA3, 0xD1, 0x59, 0xD3, 0xFE, 0xA3, + 0x90, 0x84, 0xA2, 0xDB, 0xA3, 0xD1, 0x59, 0xD3, 0xFF, 0xFF, 0x90, 0x84, 0xA2, 0xDB, 0x80, 0x60, + 0x58, 0xEC, 0x80, 0x60, 0x00, 0xED, 0x80, 0x60, 0x80, 0xEE, 0x40, 0xEC, 0x00, 0xED, 0x00, 0xEE, + 0xC0, 0x60, 0x59, 0xEC, 0xC0, 0x60, 0x07, 0xED, 0xC0, 0x60, 0x8F, 0xEE, 0xAD, 0x4F, 0xFA, 0xB4, + 0xA0, 0x5D, 0x00, 0xF3, 0x28, 0xFB, 0x40, 0x44, 0xA2, 0x60, 0xE8, 0x7C, 0x20, 0xF9, 0x1D, 0x60, + 0xD0, 0x7C, 0x21, 0xF9, 0x1D, 0x60, 0xE6, 0x7C, 0x22, 0xF9, 0x1E, 0x60, 0x44, 0x7C, 0x23, 0xF9, + 0x1E, 0x60, 0x55, 0x7C, 0x24, 0xF9, 0x1E, 0x60, 0x7F, 0x7C, 0x25, 0xF9, 0x1E, 0x60, 0x90, 0x7C, + 0x26, 0xF9, 0xD0, 0x60, 0x00, 0xE8, 0x28, 0xE8, 0x44, 0x60, 0x01, 0xE6, 0x00, 0x64, 0x40, 0x52, + 0x10, 0x60, 0x04, 0xE6, 0x08, 0x60, 0x06, 0x63, 0xFD, 0x60, 0x0C, 0x65, 0x5B, 0xD3, 0xBF, 0xD1, + 0x0C, 0x18, 0xC3, 0x83, 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xFA, 0xA3, 0xA3, 0xD3, 0x02, 0x60, + 0x00, 0x65, 0xF9, 0xA0, 0xFC, 0xA0, 0x09, 0x05, 0x00, 0x05, 0x21, 0x60, 0x00, 0x65, 0x3F, 0x43, + 0x21, 0x60, 0x00, 0x65, 0xC0, 0x60, 0x8F, 0xEE, 0x08, 0x00, 0x02, 0x60, 0x00, 0x65, 0x00, 0x60, + 0x00, 0x64, 0x18, 0xFB, 0x3F, 0x43, 0x11, 0x60, 0x10, 0xE6, 0xB7, 0x84, 0x40, 0x5F, 0x30, 0x60, + 0x20, 0x63, 0x3F, 0x40, 0x20, 0x27, 0x06, 0x00, 0x0F, 0x60, 0xFF, 0x64, 0xBD, 0xDB, 0x0F, 0x60, + 0xF0, 0x64, 0x03, 0x00, 0x0F, 0x64, 0xBD, 0xDB, 0x00, 0x64, 0xA3, 0xDB, 0x00, 0x60, 0x30, 0xE2, + 0x00, 0x60, 0x50, 0xE2, 0x00, 0x60, 0x79, 0xE2, 0x00, 0x60, 0x90, 0xE2, 0x01, 0x60, 0xD0, 0xE2, + 0x01, 0x60, 0xF0, 0xE2, 0x01, 0x60, 0xB0, 0xE2, 0x13, 0x64, 0xAD, 0xFB, 0x01, 0x60, 0x67, 0x64, + 0x37, 0xFB, 0x00, 0x60, 0x50, 0x64, 0x36, 0xFB, 0x09, 0x60, 0x2A, 0x64, 0x98, 0xFB, 0x82, 0xFF, + 0x92, 0xFF, 0x5C, 0x41, 0x5C, 0x46, 0x5C, 0x47, 0x00, 0xE1, 0xA4, 0x60, 0x7C, 0x63, 0x0C, 0x60, + 0x16, 0x64, 0xA0, 0xDD, 0x87, 0xFF, 0x97, 0xFF, 0x0C, 0x60, 0x02, 0x64, 0x40, 0x5A, 0x06, 0xA4, + 0x40, 0x5B, 0x5C, 0x5E, 0x13, 0x60, 0x52, 0xF3, 0x64, 0xFB, 0x3F, 0x40, 0x01, 0x22, 0x03, 0x00, + 0x80, 0x60, 0x37, 0x7C, 0x02, 0x00, 0x80, 0x60, 0x27, 0x7C, 0x16, 0x60, 0x55, 0xF9, 0x00, 0x60, + 0x80, 0x64, 0x89, 0xFB, 0x02, 0x60, 0x80, 0x66, 0x22, 0x60, 0x22, 0x64, 0x77, 0x60, 0x77, 0x63, + 0x00, 0xFA, 0x01, 0xFC, 0x00, 0xF0, 0x01, 0xF0, 0xD0, 0x80, 0xD3, 0x80, 0x1E, 0x02, 0x1D, 0x02, + 0x06, 0x60, 0x80, 0x65, 0x45, 0x4A, 0xAA, 0x46, 0x00, 0xFC, 0x01, 0xFA, 0xAA, 0x46, 0x00, 0xF0, + 0x2A, 0x41, 0x50, 0x65, 0xD3, 0x80, 0xCD, 0x84, 0x13, 0x03, 0x0A, 0x60, 0x80, 0x65, 0x45, 0x4A, + 0xAA, 0x46, 0x00, 0xFC, 0x01, 0xFA, 0xAA, 0x46, 0x00, 0xF0, 0x65, 0x41, 0xC8, 0x65, 0xD3, 0x80, + 0xCD, 0x84, 0x06, 0x03, 0x12, 0x60, 0x7F, 0x64, 0x03, 0x00, 0x10, 0x65, 0x02, 0x60, 0x7F, 0x64, + 0x65, 0x43, 0x86, 0xFD, 0x0F, 0x60, 0x5B, 0xFD, 0x07, 0x61, 0xC5, 0x81, 0xE1, 0x85, 0xD4, 0x84, + 0x8A, 0xFB, 0xDC, 0x84, 0x88, 0xFB, 0x0C, 0xA4, 0x87, 0xFB, 0x0F, 0x60, 0x5C, 0xFB, 0x1E, 0x60, + 0x58, 0x4E, 0xD3, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0x58, 0x4E, 0xB9, 0x78, 0xFF, 0xFF, 0x3F, 0x40, + 0x40, 0x26, 0x05, 0x00, 0x18, 0x60, 0x20, 0xF3, 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x52, 0x00, 0x64, + 0x0A, 0x60, 0x7E, 0xFB, 0x1E, 0x60, 0xF2, 0x78, 0xFF, 0xFF, 0x5C, 0x51, 0x3F, 0x41, 0xA5, 0x4C, + 0x50, 0x37, 0x0B, 0x00, 0x01, 0xB9, 0x41, 0x5F, 0xB5, 0x60, 0x55, 0xE0, 0x05, 0x60, 0xF9, 0xF1, + 0xC0, 0x67, 0x90, 0x84, 0x3F, 0x40, 0x01, 0x26, 0xA0, 0x50, 0x06, 0x60, 0x08, 0xF3, 0x01, 0x60, + 0x01, 0x65, 0x01, 0x60, 0x02, 0x7C, 0xD4, 0x80, 0xD0, 0x80, 0x01, 0x03, 0x10, 0x02, 0x5A, 0xD1, + 0x5A, 0xD3, 0x3E, 0x60, 0x00, 0x66, 0xE0, 0x87, 0x40, 0x4A, 0xF7, 0x60, 0x8C, 0x61, 0x64, 0x44, + 0xC8, 0x84, 0x0C, 0x63, 0xAA, 0x46, 0x58, 0xD0, 0xAA, 0x46, 0x59, 0xD8, 0xFB, 0x1F, 0x08, 0x60, + 0x00, 0x63, 0xFA, 0x60, 0x00, 0x65, 0xBD, 0xD3, 0xA3, 0xD3, 0x02, 0xA8, 0xD4, 0x80, 0x07, 0x02, + 0x06, 0x02, 0x49, 0x60, 0x4C, 0x61, 0x3C, 0x60, 0x00, 0x66, 0x41, 0x4B, 0x03, 0x00, 0x24, 0x60, + 0x84, 0x78, 0xFF, 0xFF, 0x2B, 0x41, 0x49, 0x60, 0x94, 0x7C, 0xD1, 0x80, 0xA1, 0xD2, 0x25, 0x05, + 0x59, 0xD0, 0x60, 0x45, 0x59, 0xD2, 0x44, 0x47, 0xE0, 0x87, 0x40, 0x4A, 0x59, 0xD2, 0x59, 0x8B, + 0x40, 0x4C, 0x08, 0x60, 0x00, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, 0xEC, 0x18, 0xD4, 0x80, 0xEA, 0x18, + 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x67, 0x44, 0xC0, 0x84, 0xE0, 0x85, 0x2C, 0x44, + 0xD4, 0x80, 0x63, 0x41, 0x01, 0x06, 0x65, 0x44, 0xC8, 0x83, 0xAA, 0x46, 0x59, 0xD1, 0x27, 0xD8, + 0x5A, 0x87, 0xFC, 0x1F, 0xAA, 0x46, 0x2B, 0x41, 0xD5, 0x01, 0x49, 0x60, 0x94, 0x61, 0x41, 0x4B, + 0x2B, 0x41, 0x49, 0x60, 0x94, 0x7C, 0xD1, 0x80, 0xA1, 0xD2, 0x27, 0x05, 0x59, 0xD0, 0x60, 0x45, + 0x59, 0xD2, 0x44, 0x47, 0xE0, 0x87, 0x40, 0x4A, 0x59, 0xD2, 0x59, 0x8B, 0x40, 0x4C, 0x08, 0x60, + 0x00, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, 0xEC, 0x18, 0xD4, 0x80, 0xEA, 0x18, 0x03, 0x03, 0xC3, 0x83, + 0xC3, 0x83, 0xF7, 0x01, 0x04, 0xA3, 0xA3, 0xD1, 0x5A, 0x88, 0x2C, 0x43, 0xD3, 0x80, 0xFF, 0xFF, + 0x01, 0x06, 0x64, 0x43, 0xCF, 0x83, 0xAA, 0x46, 0x60, 0xFE, 0x28, 0xD1, 0x5E, 0x88, 0x27, 0xD8, + 0x5A, 0x87, 0xFB, 0x1F, 0x20, 0xFE, 0xAA, 0x46, 0xD3, 0x01, 0xFA, 0x60, 0x39, 0x65, 0x24, 0x60, + 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x03, 0x03, 0xBE, 0xD1, 0x07, 0x60, 0xED, 0xF9, 0x07, 0x60, + 0xED, 0xF3, 0x20, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x10, 0x2A, 0x05, 0x00, 0x07, 0x60, 0xEC, 0xF9, + 0x07, 0x60, 0xEB, 0xF9, 0x12, 0x00, 0x04, 0xB0, 0x10, 0x60, 0x55, 0xF3, 0x0E, 0x03, 0x02, 0xBC, + 0xA2, 0xDB, 0x07, 0x60, 0xF5, 0xFB, 0x10, 0x60, 0xE8, 0xF3, 0x10, 0x60, 0xAC, 0xF3, 0x02, 0xBD, + 0x02, 0xBC, 0xA2, 0xDB, 0x65, 0x44, 0x10, 0x60, 0xE8, 0xFB, 0x07, 0x60, 0xED, 0xF3, 0x31, 0x41, + 0x60, 0x40, 0x20, 0x2A, 0x40, 0xB9, 0x40, 0x26, 0x03, 0x00, 0x60, 0x40, 0x01, 0x26, 0x80, 0xB9, + 0x41, 0x51, 0xFA, 0x60, 0x3A, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x03, 0x02, + 0x23, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x5B, 0xD3, 0xF8, 0x60, 0x3F, 0x65, 0x00, 0x7F, 0xE0, 0x84, + 0xE0, 0x84, 0x10, 0x60, 0xF7, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, + 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0xE0, 0x84, 0x10, 0x60, 0xFA, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, + 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x21, 0x60, 0xFA, 0x61, 0xA3, 0xD3, + 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0xA1, 0xD3, 0xE0, 0x9C, 0xA4, 0x84, + 0xB0, 0x84, 0xA1, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x59, 0xD3, + 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA1, 0xDB, 0x11, 0x60, 0x00, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, + 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x11, 0x60, + 0x03, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, + 0xB0, 0x84, 0xA2, 0xDB, 0x11, 0x60, 0x06, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, + 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x11, 0x60, 0x09, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, + 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x11, 0x60, 0x0C, 0xF3, + 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, + 0xA2, 0xDB, 0x11, 0x60, 0x0F, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, + 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x02, 0xA3, 0xA3, 0xD3, 0xF8, 0x60, 0x3F, 0x65, + 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x11, 0x60, 0x12, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, + 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0xBD, 0xD3, 0xFF, 0xFF, + 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x11, 0x60, 0x15, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, + 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x22, 0x60, + 0x30, 0x61, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0xA1, 0xD3, + 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA1, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0x00, 0x7F, 0xE0, 0x84, + 0xE0, 0x84, 0x59, 0xD3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA1, 0xDB, 0x11, 0x60, 0x1B, 0xF3, + 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, + 0xA2, 0xDB, 0x11, 0x60, 0x1E, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, + 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x11, 0x60, 0x21, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, + 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0xA3, 0xD3, + 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x11, 0x60, 0x24, 0xF3, 0xE0, 0x9C, + 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, + 0x11, 0x60, 0x27, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, + 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x11, 0x60, 0x2A, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, + 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x00, 0x60, 0x6A, 0x63, + 0x22, 0x60, 0x56, 0x61, 0x21, 0x60, 0xEA, 0x64, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0x11, 0x60, + 0x33, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, + 0x11, 0x60, 0x37, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, 0x39, 0xF3, 0xFF, 0xFF, + 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, 0x40, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, + 0x42, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, 0x4E, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, + 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, 0x52, 0xF3, 0xFF, 0xFF, + 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, 0x54, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, + 0x5B, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, 0x5D, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, + 0xA2, 0xDB, 0xFA, 0x60, 0x2C, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x0E, 0x03, + 0x63, 0x45, 0x23, 0x60, 0xF0, 0x63, 0x06, 0x61, 0xA5, 0xD1, 0xDA, 0x85, 0x64, 0x44, 0x0F, 0xB4, + 0xBD, 0xDB, 0x64, 0x47, 0x0F, 0xB4, 0xCD, 0x81, 0xBD, 0xDB, 0xF6, 0x02, 0xFA, 0x60, 0x30, 0x65, + 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x14, 0x03, 0xBD, 0xD3, 0x63, 0x46, 0x24, 0x60, + 0x88, 0x63, 0x12, 0x60, 0x53, 0xFB, 0xDA, 0x85, 0xBD, 0xDB, 0x0E, 0x61, 0xA6, 0xD1, 0xDA, 0x86, + 0x64, 0x44, 0xFF, 0xB4, 0xA5, 0xDB, 0xDA, 0x85, 0x64, 0x47, 0xFF, 0xB4, 0xCD, 0x81, 0xBD, 0xDB, + 0xF5, 0x02, 0xFA, 0x60, 0x31, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x22, 0x03, + 0xBD, 0xD3, 0x12, 0x60, 0x71, 0xFB, 0x5A, 0x81, 0x12, 0x60, 0x80, 0xFB, 0x5A, 0x82, 0x12, 0x60, + 0x8F, 0xFB, 0x5A, 0x83, 0x12, 0x60, 0x9E, 0xFB, 0x5A, 0x84, 0x0E, 0x61, 0xBD, 0xD1, 0xBD, 0xD5, + 0x64, 0x44, 0xFF, 0xB4, 0x21, 0xDB, 0x5A, 0x81, 0x64, 0x47, 0xFF, 0xB4, 0x22, 0xDB, 0x5A, 0x82, + 0x66, 0x44, 0xFF, 0xB4, 0x23, 0xDB, 0x5A, 0x83, 0x66, 0x47, 0xFF, 0xB4, 0x24, 0xDB, 0xCD, 0x81, + 0x5A, 0x84, 0xEC, 0x02, 0xFA, 0x60, 0x47, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, + 0x11, 0x03, 0x63, 0x45, 0x25, 0x60, 0x5A, 0x63, 0xA5, 0xD1, 0xDA, 0x85, 0xBD, 0xD9, 0x02, 0x61, + 0xA5, 0xD1, 0xDA, 0x85, 0x64, 0x47, 0x00, 0x7E, 0xBD, 0xDB, 0x64, 0x44, 0x00, 0x7E, 0xCD, 0x81, + 0xBD, 0xDB, 0xF6, 0x02, 0xFA, 0x60, 0x2E, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, + 0x1F, 0x03, 0x63, 0x46, 0xFC, 0xA3, 0xA3, 0xD3, 0x24, 0x60, 0x08, 0x63, 0xCC, 0x84, 0xE8, 0x84, + 0xCC, 0x81, 0x00, 0x36, 0x0D, 0x00, 0x63, 0x45, 0xA6, 0xD3, 0x5A, 0xD1, 0xDA, 0x86, 0xFF, 0xB4, + 0xE0, 0x84, 0xC4, 0x84, 0x5C, 0x90, 0xBD, 0xD9, 0xFD, 0x02, 0xCD, 0x81, 0x66, 0x42, 0xF4, 0x02, + 0x66, 0x42, 0x5A, 0xD3, 0x24, 0x60, 0x48, 0x65, 0xBD, 0xDB, 0xD7, 0x80, 0xFF, 0xFF, 0xFC, 0x02, + 0x25, 0x60, 0x6E, 0x61, 0xFA, 0x60, 0x46, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, + 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, 0x2F, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, + 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, 0x3E, 0x65, 0x24, 0x60, 0x58, 0x4D, + 0x97, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, 0x3F, 0x65, 0x24, 0x60, + 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, 0x40, 0x65, + 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, + 0x3B, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xFA, 0x60, + 0x48, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x10, 0x03, 0xBD, 0xD3, 0x25, 0x60, + 0xCA, 0x61, 0x0E, 0xB4, 0xBD, 0xD1, 0xA1, 0xDB, 0x64, 0x47, 0x0E, 0xB4, 0xA3, 0xD1, 0x59, 0xDB, + 0x64, 0x44, 0x0E, 0xB4, 0x59, 0xDB, 0x64, 0x47, 0x0E, 0xB4, 0x59, 0xDB, 0xFA, 0x60, 0x29, 0x65, + 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x07, 0x03, 0x04, 0xA3, 0xA3, 0xD3, 0x20, 0x60, + 0x00, 0x65, 0xB4, 0x84, 0x10, 0x60, 0x29, 0xFB, 0xFA, 0x60, 0x2A, 0x65, 0x24, 0x60, 0x58, 0x4D, + 0x97, 0x78, 0xFF, 0xFF, 0x39, 0x03, 0x04, 0xA3, 0xBD, 0xD1, 0x10, 0x60, 0xCD, 0xF3, 0x64, 0x41, + 0x64, 0x5E, 0xA2, 0xDB, 0x64, 0x47, 0x5A, 0xD3, 0x60, 0x5C, 0x64, 0x5F, 0xA2, 0xDB, 0x10, 0x60, + 0xE3, 0xF3, 0xFF, 0x60, 0xC0, 0xB5, 0x61, 0x40, 0x80, 0x27, 0x05, 0x00, 0xE9, 0x87, 0x3F, 0xB4, + 0xB4, 0x84, 0xA2, 0xDB, 0x1E, 0x00, 0x65, 0x44, 0xA2, 0xDB, 0x10, 0x60, 0xDC, 0xF1, 0xE1, 0x80, + 0xF9, 0x81, 0xE1, 0x80, 0xF9, 0x84, 0xFF, 0x60, 0x80, 0xB4, 0xC0, 0x9C, 0xA2, 0xD9, 0x10, 0x60, + 0xDF, 0xF1, 0xFF, 0xFF, 0xC0, 0x9C, 0xA2, 0xD9, 0x10, 0x60, 0xE6, 0xF1, 0x01, 0x7E, 0x60, 0x47, + 0x60, 0x41, 0x64, 0x44, 0xFE, 0x60, 0x00, 0xB5, 0xC1, 0x84, 0x01, 0x60, 0xFF, 0xB4, 0xB4, 0x84, + 0xA2, 0xDB, 0xDB, 0x83, 0x11, 0x60, 0x62, 0xFD, 0xFA, 0x60, 0x2B, 0x65, 0x24, 0x60, 0x58, 0x4D, + 0x97, 0x78, 0xFF, 0xFF, 0x07, 0x03, 0x04, 0xA3, 0xBD, 0xD3, 0x10, 0x60, 0xD0, 0xFB, 0xA3, 0xD3, + 0x10, 0x60, 0x94, 0xFB, 0xFA, 0x60, 0x3C, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, + 0x1F, 0x03, 0xA3, 0xD3, 0xFC, 0x60, 0xFC, 0x65, 0xA4, 0x84, 0x60, 0x5C, 0x00, 0x7E, 0xC0, 0x60, + 0x00, 0xA0, 0x60, 0x43, 0x07, 0x04, 0x10, 0x60, 0xD4, 0xF3, 0xFF, 0xFF, 0x03, 0x60, 0xFF, 0xB4, + 0x3C, 0x94, 0xA2, 0xDB, 0x21, 0x60, 0x30, 0x61, 0x64, 0x44, 0x00, 0x7F, 0xC0, 0xA0, 0x60, 0x47, + 0x07, 0x04, 0x60, 0x43, 0xA1, 0xD3, 0xFF, 0xFF, 0x03, 0x60, 0xFF, 0xB4, 0x3C, 0x94, 0xA1, 0xDB, + 0xB8, 0xFE, 0xB9, 0xFE, 0xBA, 0xFE, 0xBB, 0xFE, 0xBD, 0xFE, 0xBF, 0xFE, 0x15, 0x60, 0xCB, 0xF3, + 0x12, 0x63, 0x60, 0x40, 0x01, 0x27, 0x04, 0x00, 0x0B, 0x60, 0xEA, 0x62, 0x5A, 0xDF, 0xFE, 0x1F, + 0x1F, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x06, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, 0x07, 0x18, + 0xD4, 0x80, 0x05, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0xDB, 0x83, 0x00, 0xBC, + 0x2D, 0x58, 0xFF, 0xFF, 0x86, 0xFD, 0xB0, 0x26, 0x00, 0x00, 0x06, 0x00, 0x10, 0xFD, 0x32, 0x01, + 0x00, 0x00, 0x02, 0x00, 0x14, 0xFD, 0x94, 0x2B, 0x00, 0x00, 0x0A, 0x00, 0x41, 0xFA, 0x46, 0x23, + 0x00, 0x00, 0x22, 0x00, 0x42, 0xFA, 0x68, 0x23, 0x00, 0x00, 0x22, 0x00, 0x43, 0xFA, 0x8A, 0x23, + 0x00, 0x00, 0x22, 0x00, 0x44, 0xFA, 0xAC, 0x23, 0x00, 0x00, 0x22, 0x00, 0x45, 0xFA, 0xCE, 0x23, + 0x00, 0x00, 0x22, 0x00, 0x25, 0xFD, 0x62, 0x01, 0x00, 0x00, 0x02, 0x00, + +}; /* fw_image_3_data */ + +static const hcf_8 fw_image_4_data[] = { + 0x6C, 0x40, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x41, 0xFF, 0x33, 0xF3, 0x32, 0x11, 0x31, 0x18, 0x40, 0x64, 0x3A, 0xDB, 0x1C, 0x00, 0xFF, 0xFF, + 0xC4, 0xE2, 0x27, 0x44, 0x20, 0x2A, 0x01, 0x00, 0xFF, 0xFF, 0x42, 0x64, 0x3A, 0xDB, 0x23, 0x00, + 0x41, 0xFF, 0xA3, 0x60, 0x34, 0x78, 0xE2, 0xFE, 0x40, 0x49, 0x02, 0x60, 0x01, 0xE1, 0x1D, 0x00, + 0x44, 0xFF, 0x1B, 0x09, 0x29, 0x44, 0x10, 0x2A, 0x04, 0x74, 0xCD, 0xE2, 0x10, 0x65, 0x0B, 0x00, + 0xA4, 0x60, 0x49, 0x78, 0xA4, 0xE2, 0x29, 0x44, 0x20, 0x2A, 0x0D, 0x00, 0x20, 0xAC, 0xEC, 0x01, + 0xA4, 0x60, 0x49, 0x78, 0x46, 0xFF, 0xB4, 0x84, 0x40, 0x49, 0xA1, 0xFF, 0xFF, 0xFF, 0x80, 0x3E, + 0xA4, 0x60, 0x49, 0x78, 0xFF, 0xFF, 0x62, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, + 0xAA, 0x60, 0xF4, 0x78, 0x4C, 0x4E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAA, 0x60, 0xFB, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC4, 0xE2, 0x84, 0xFF, 0x22, 0x58, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA4, 0x60, 0xB9, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0xE1, 0x01, 0xFF, 0xFF, + 0x10, 0x29, 0xFA, 0x01, 0xE4, 0xE2, 0xAA, 0x60, 0xB0, 0x78, 0x94, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC1, 0x60, 0x35, 0x78, 0x64, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAA, 0x60, 0x97, 0x78, 0xAC, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x80, 0x29, 0xE2, 0x01, 0xAA, 0x60, 0xF3, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB4, 0x60, 0xEF, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB5, 0x60, 0x1C, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB3, 0x60, 0x8B, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB3, 0x60, 0xBE, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB3, 0x60, 0xBE, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB6, 0x60, 0x9D, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB3, 0x60, 0xC1, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x60, 0x83, 0x64, 0x80, 0x29, 0x09, 0xFB, 0xB4, 0x60, 0xB7, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, + 0x98, 0xFF, 0xC2, 0x60, 0x69, 0x78, 0x40, 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, + 0xC1, 0x60, 0xE0, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC0, 0x60, 0x3D, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBF, 0x60, 0xB8, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB7, 0x60, 0x96, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA1, 0xFF, 0x98, 0xFF, 0x83, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC3, 0x60, 0x58, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xB0, 0xFF, 0xB1, 0xFF, 0x40, 0xFF, 0x43, 0xFF, 0xC3, 0x60, 0x53, 0x78, 0x44, 0xFF, 0xFF, 0x01, + 0xC3, 0x60, 0x58, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0x1C, 0x60, 0x28, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xC3, 0x60, 0x53, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xC3, 0x60, 0x52, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xCA, 0x60, 0x76, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE8, 0x60, 0x6C, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x42, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x85, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xCA, 0x60, 0x7E, 0x78, 0x24, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE6, 0x60, 0x2A, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xCA, 0x60, 0x7E, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xCA, 0x60, 0x7E, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xCA, 0x60, 0x7E, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x60, 0x9F, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x60, 0xE3, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x60, 0xC7, 0x78, 0x28, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x60, 0xC7, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x60, 0xC7, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x60, 0xC7, 0x78, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x60, 0x87, 0x64, 0x80, 0x29, 0x09, 0xFB, 0x47, 0xFF, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xF7, 0xA7, 0xFF, 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xA2, 0x60, 0x00, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x2E, 0x60, 0x54, 0x63, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, + 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, + 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, + 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, + 0x2F, 0x44, 0xBD, 0xDB, 0x17, 0x60, 0x24, 0xFD, 0x2F, 0x60, 0x74, 0x63, 0x17, 0x60, 0x25, 0xFD, + 0x30, 0x44, 0x17, 0x60, 0x26, 0xFB, 0x31, 0x44, 0x17, 0x60, 0x27, 0xFB, 0x32, 0x44, 0x17, 0x60, + 0x28, 0xFB, 0x33, 0x44, 0x17, 0x60, 0x29, 0xFB, 0x81, 0xFF, 0x91, 0xFF, 0x58, 0x51, 0x44, 0x00, + 0x82, 0xFF, 0x92, 0xFF, 0x58, 0x51, 0x40, 0x00, 0x83, 0xFF, 0x93, 0xFF, 0x58, 0x51, 0x3C, 0x00, + 0x84, 0xFF, 0x94, 0xFF, 0x58, 0x51, 0x38, 0x00, 0x85, 0xFF, 0x95, 0xFF, 0x58, 0x51, 0x34, 0x00, + 0x86, 0xFF, 0x96, 0xFF, 0x58, 0x51, 0x30, 0x00, 0x87, 0xFF, 0x97, 0xFF, 0x58, 0x51, 0x2C, 0x00, + 0x80, 0xFF, 0x90, 0xFF, 0x99, 0xFF, 0x17, 0x60, 0x24, 0xF1, 0x30, 0x44, 0x64, 0x43, 0xBD, 0xDB, + 0x31, 0x44, 0xBD, 0xDB, 0x32, 0x44, 0xBD, 0xDB, 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, + 0x35, 0x44, 0xBD, 0xDB, 0x36, 0x44, 0xBD, 0xDB, 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, + 0x39, 0x44, 0xBD, 0xDB, 0x3A, 0x44, 0xBD, 0xDB, 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, + 0x3D, 0x44, 0xBD, 0xDB, 0x3E, 0x44, 0xBD, 0xDB, 0x3F, 0x44, 0xBD, 0xDB, 0xEE, 0x60, 0x48, 0x64, + 0x0A, 0xFB, 0x40, 0x21, 0xFE, 0x01, 0x70, 0x00, 0x42, 0x50, 0x40, 0x53, 0x17, 0x60, 0x25, 0xF3, + 0xFF, 0xFF, 0x40, 0x52, 0x33, 0x44, 0x32, 0x42, 0xA2, 0xDB, 0xDA, 0x82, 0xA2, 0xDD, 0xDA, 0x83, + 0x65, 0x44, 0xBD, 0xDB, 0x61, 0x44, 0xBD, 0xDB, 0x66, 0x44, 0xBD, 0xDB, 0xBD, 0xD9, 0x30, 0x44, + 0xBD, 0xDB, 0x99, 0xFF, 0xA4, 0x4C, 0xBD, 0xDB, 0xA5, 0x4C, 0xBD, 0xDB, 0xA0, 0x4C, 0xBD, 0xDB, + 0xA1, 0x4C, 0xBD, 0xDB, 0x98, 0xFF, 0x17, 0x60, 0x25, 0xFD, 0x17, 0x60, 0x26, 0xF3, 0xFF, 0xFF, + 0x40, 0x50, 0x17, 0x60, 0x28, 0xF3, 0xFF, 0xFF, 0x40, 0x52, 0x17, 0x60, 0x29, 0xF3, 0xFF, 0xFF, + 0x40, 0x53, 0x31, 0x41, 0x17, 0x60, 0x27, 0xF3, 0xFF, 0xFF, 0x40, 0x51, 0x17, 0x60, 0x24, 0xF3, + 0xFF, 0xFF, 0x60, 0x43, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, + 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, + 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, + 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, + 0x2F, 0x44, 0xBD, 0xDB, 0x17, 0x60, 0x24, 0xFD, 0x61, 0x58, 0xFF, 0xFF, 0x28, 0x60, 0x76, 0x63, + 0xA3, 0xD3, 0x33, 0x5C, 0x02, 0xA4, 0xBD, 0xDB, 0xFE, 0xB4, 0xE0, 0x85, 0xC4, 0x85, 0x47, 0xD9, + 0x34, 0x44, 0x5B, 0xDB, 0x44, 0xF3, 0x5B, 0xDB, 0xA1, 0xFF, 0xFF, 0xFF, 0x87, 0x3E, 0xFF, 0x01, + 0x82, 0xE1, 0x80, 0xFF, 0x90, 0xFF, 0x88, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x87, 0x3E, 0x41, 0xFF, + 0x00, 0x60, 0x03, 0xE1, 0x21, 0x46, 0x66, 0x45, 0x00, 0xF4, 0x2E, 0x44, 0x09, 0xFA, 0x6A, 0x61, + 0x7F, 0x60, 0xFE, 0x63, 0xA1, 0xFF, 0x9A, 0xFF, 0x05, 0x11, 0x0A, 0x00, 0x00, 0xF4, 0x01, 0xF2, + 0x17, 0x18, 0x7A, 0x61, 0x02, 0x25, 0x04, 0x00, 0x6C, 0x44, 0x7A, 0xDA, 0xFB, 0x1C, 0xF6, 0x11, + 0xD9, 0x81, 0x41, 0xFF, 0x02, 0x1C, 0x00, 0xF4, 0xDA, 0x82, 0x41, 0xFF, 0xC9, 0x81, 0xCB, 0x83, + 0x6C, 0x44, 0x5A, 0xDA, 0x02, 0x1C, 0x00, 0xF4, 0x81, 0xF2, 0x6C, 0x44, 0x5A, 0xDA, 0xCB, 0x83, + 0x02, 0x74, 0x02, 0x60, 0x04, 0xE1, 0x80, 0x60, 0x00, 0x61, 0x5D, 0x93, 0xB5, 0xFF, 0x98, 0xFF, + 0x26, 0x44, 0xFD, 0xB4, 0x84, 0xBC, 0x40, 0x46, 0x65, 0x46, 0x00, 0x64, 0x23, 0xFA, 0x3F, 0xFC, + 0x63, 0x47, 0x0A, 0x63, 0x0F, 0xFC, 0x00, 0xF4, 0x08, 0xFA, 0xCB, 0xFE, 0x18, 0xE1, 0x44, 0xFF, + 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0xE2, 0xFE, 0x03, 0x04, 0xA3, 0x60, 0x99, 0x78, 0xFF, 0xFF, + 0xE0, 0xFE, 0x03, 0x04, 0xA3, 0x60, 0xAF, 0x78, 0xFF, 0xFF, 0xE1, 0xFE, 0x07, 0x05, 0x9F, 0xFE, + 0x03, 0x04, 0x18, 0x60, 0x24, 0x78, 0xFF, 0xFF, 0x43, 0xFF, 0xA9, 0x01, 0xD3, 0xF3, 0xFF, 0xFF, + 0x01, 0xB4, 0xFF, 0xFF, 0x08, 0x24, 0x15, 0x00, 0x29, 0x44, 0x08, 0x26, 0xE1, 0x01, 0x72, 0x44, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x94, 0xF3, 0xE8, 0x85, 0xFF, 0xB7, + 0xE0, 0x84, 0xE0, 0x84, 0xB4, 0x85, 0x73, 0x44, 0xD4, 0x84, 0x10, 0x65, 0xD4, 0x80, 0xFF, 0xFF, + 0x37, 0x04, 0x3F, 0x40, 0x40, 0x26, 0x09, 0x00, 0x18, 0x60, 0x1C, 0xF3, 0x5A, 0xD1, 0xA0, 0x50, + 0xA4, 0x52, 0x5A, 0xD3, 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x50, 0xBC, 0xF3, 0xD2, 0xF1, 0x01, 0xA8, + 0x07, 0xA8, 0x0A, 0x03, 0x09, 0x03, 0x64, 0x40, 0x01, 0x26, 0x09, 0x00, 0x18, 0x60, 0x07, 0xF3, + 0xFF, 0xFF, 0x01, 0xB4, 0xFF, 0xFF, 0x03, 0x02, 0xAD, 0x4F, 0xFA, 0xB4, 0xA0, 0x5D, 0xAE, 0x4F, + 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x3F, 0x40, 0x02, 0x2B, 0x11, 0x00, 0x0C, 0x60, 0x00, 0x62, + 0x00, 0x60, 0x71, 0x7C, 0x00, 0x60, 0xB1, 0x65, 0x1A, 0x60, 0x58, 0x4D, 0x88, 0x78, 0xFF, 0xFF, + 0x08, 0xE1, 0x62, 0xFF, 0xA3, 0xFF, 0xFF, 0xFF, 0xA2, 0xFF, 0x02, 0x60, 0x08, 0xE1, 0xBD, 0xFE, + 0x97, 0x01, 0x21, 0x46, 0x01, 0x5D, 0x5C, 0x62, 0x03, 0xE1, 0x44, 0xFF, 0xA1, 0xFF, 0x9A, 0xFF, + 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x62, 0x62, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0xA1, 0xFF, + 0x5A, 0xDC, 0x12, 0xE1, 0x02, 0x60, 0x01, 0xE1, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x28, 0x40, + 0x40, 0x2B, 0x03, 0x00, 0x29, 0x40, 0x20, 0x27, 0x97, 0x00, 0xC8, 0x74, 0xCD, 0xE2, 0x29, 0x44, + 0x08, 0xBC, 0x40, 0x49, 0x44, 0xFF, 0x05, 0xE1, 0x28, 0x40, 0x08, 0x2A, 0x07, 0x00, 0x28, 0x40, + 0x48, 0x36, 0x04, 0x00, 0xD2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xD2, 0xFB, 0x29, 0x44, 0xFF, 0x60, + 0xEF, 0x65, 0x24, 0x89, 0x40, 0x27, 0x3F, 0x00, 0x00, 0x00, 0x29, 0x40, 0x80, 0x27, 0x0B, 0x00, + 0x07, 0x61, 0xA1, 0xFF, 0xCD, 0x81, 0x04, 0x25, 0x61, 0x00, 0x87, 0x4C, 0xFB, 0x02, 0xF3, 0x60, + 0xA0, 0x64, 0x80, 0x4C, 0x07, 0x00, 0xA1, 0xFF, 0x9C, 0x4C, 0x9C, 0x4C, 0x9C, 0x4D, 0x05, 0x60, + 0xCF, 0x64, 0x80, 0x4C, 0x28, 0x40, 0x40, 0x2B, 0x05, 0x00, 0x29, 0x40, 0x20, 0x27, 0x02, 0x00, + 0x15, 0x60, 0x6F, 0x6B, 0x04, 0x25, 0x4A, 0x00, 0x30, 0x64, 0x3A, 0xDB, 0x44, 0xFF, 0x04, 0x25, + 0x45, 0x00, 0x04, 0x60, 0x00, 0x65, 0x25, 0x44, 0xB4, 0x84, 0x80, 0x4E, 0x2D, 0x41, 0x04, 0x25, + 0x3D, 0x00, 0x61, 0x4C, 0x00, 0x60, 0x8A, 0x65, 0xC5, 0x81, 0x61, 0x54, 0xA1, 0xFF, 0xFF, 0xFF, + 0x04, 0x25, 0x34, 0x00, 0x67, 0x4E, 0x07, 0x64, 0x1C, 0xFB, 0x00, 0xE1, 0x02, 0x60, 0x05, 0xE1, + 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x28, 0x40, 0x40, 0x27, 0x0A, 0x00, 0x1C, 0x65, 0x28, 0x40, + 0xA4, 0x36, 0x14, 0x65, 0x23, 0x44, 0xC4, 0x84, 0x28, 0x40, 0x08, 0x2A, 0x0C, 0x00, 0x07, 0x00, + 0x23, 0x44, 0x1C, 0xA4, 0x29, 0x40, 0x20, 0x27, 0x02, 0x00, 0x11, 0x60, 0x0F, 0x6B, 0x3C, 0x46, + 0x98, 0xF0, 0x23, 0x44, 0xC4, 0x84, 0x06, 0x74, 0x25, 0x5C, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0xB0, 0x84, 0x80, 0x4C, 0x9C, 0x4C, 0x44, 0xFF, 0x18, 0xE1, 0x0A, 0x64, 0x1E, 0x74, + 0x02, 0x60, 0x05, 0xE1, 0x40, 0x40, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0xC4, 0xE2, 0x27, 0x44, + 0x20, 0x2A, 0x06, 0x00, 0x42, 0x64, 0x3A, 0xDB, 0x67, 0x4C, 0xB0, 0x60, 0x80, 0x78, 0xFF, 0xFF, + 0x41, 0x64, 0x3A, 0xDB, 0x62, 0xFF, 0x08, 0xE1, 0xE2, 0xFE, 0x72, 0x52, 0xA1, 0xFF, 0x98, 0xFF, + 0x80, 0x3E, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x28, 0x40, 0x08, 0x27, 0x66, 0x01, 0x3C, 0x46, + 0x8B, 0xFF, 0x84, 0x60, 0x00, 0xE4, 0x0F, 0x60, 0x92, 0x64, 0xC9, 0x60, 0x58, 0x4F, 0x10, 0x78, + 0xFF, 0xFF, 0x3F, 0xF2, 0x00, 0x60, 0x18, 0x70, 0x18, 0x71, 0x20, 0x72, 0x00, 0xF2, 0x60, 0x53, + 0x20, 0xE1, 0xA1, 0xFF, 0x88, 0x75, 0x00, 0xE1, 0xFF, 0xFF, 0x60, 0x50, 0x75, 0x44, 0x12, 0x71, + 0x6E, 0x72, 0x81, 0x75, 0xFF, 0xFF, 0x88, 0xFF, 0xA3, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0x32, 0xF3, + 0x08, 0x29, 0x0A, 0x00, 0x60, 0x40, 0x07, 0x22, 0x07, 0x00, 0xFE, 0xB4, 0x32, 0xFB, 0x27, 0x44, + 0x10, 0xBC, 0xF7, 0xB4, 0x40, 0x47, 0x43, 0xFF, 0x00, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x08, 0xE1, + 0x31, 0x40, 0x01, 0x2A, 0x04, 0x00, 0x00, 0x64, 0x33, 0xFB, 0x01, 0x60, 0x0A, 0xE1, 0xE5, 0xFE, + 0x27, 0x05, 0x9F, 0xFE, 0x12, 0x05, 0x31, 0x41, 0x40, 0x2A, 0x0F, 0x00, 0x07, 0x60, 0xEA, 0xF1, + 0xAE, 0x4C, 0x90, 0x80, 0x10, 0x2A, 0x09, 0x00, 0x7F, 0xB1, 0x07, 0x60, 0xEA, 0xFB, 0x60, 0x40, + 0x10, 0x2A, 0x80, 0xB9, 0x41, 0x51, 0xDF, 0xFE, 0x19, 0xFF, 0x27, 0x44, 0x10, 0x26, 0x13, 0x00, + 0x9F, 0xFE, 0x02, 0x04, 0x40, 0xE1, 0x06, 0x00, 0x7C, 0xE1, 0x31, 0x44, 0x01, 0x2A, 0x02, 0x00, + 0x04, 0x0A, 0xFD, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0xAF, 0x60, 0x7B, 0x78, 0xFF, 0xFF, + 0xAA, 0x60, 0xC0, 0x78, 0xFF, 0xFF, 0x27, 0x44, 0x08, 0x26, 0xFF, 0xFF, 0xC0, 0x60, 0xEA, 0x78, + 0xFF, 0xFF, 0x48, 0xF3, 0x32, 0xF1, 0x00, 0x63, 0x64, 0x40, 0x07, 0x26, 0x03, 0x00, 0xA5, 0x60, + 0x6C, 0x78, 0xFF, 0xFF, 0x31, 0x40, 0x08, 0x26, 0xF1, 0x01, 0xCD, 0xE2, 0x84, 0xE1, 0x70, 0x41, + 0xAD, 0x80, 0x71, 0x40, 0x80, 0x27, 0xEA, 0x12, 0x03, 0x03, 0xC1, 0x60, 0x3B, 0x78, 0xFF, 0xFF, + 0xA1, 0xFF, 0xFF, 0xFF, 0xC4, 0xE2, 0x32, 0xFD, 0x60, 0x40, 0x01, 0x2A, 0xDC, 0x01, 0x3C, 0x46, + 0x3E, 0xF2, 0x2A, 0xF0, 0x27, 0x41, 0x44, 0x48, 0x20, 0xB9, 0x01, 0xB4, 0xF7, 0xB1, 0x0A, 0x03, + 0x64, 0x40, 0x08, 0x27, 0x07, 0x00, 0x0F, 0x60, 0xEE, 0x63, 0x00, 0x64, 0x45, 0xFB, 0x46, 0xFB, + 0xBD, 0xDB, 0xA3, 0xDB, 0xCB, 0x0A, 0xCA, 0x11, 0x41, 0x47, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, + 0x10, 0x26, 0x04, 0x00, 0x01, 0x2A, 0x05, 0x00, 0x10, 0x2B, 0x03, 0x00, 0x29, 0x47, 0x20, 0xBF, + 0x40, 0x49, 0x05, 0xE1, 0x01, 0x60, 0x08, 0xE1, 0x2A, 0xE8, 0x3C, 0x46, 0x00, 0x63, 0x32, 0xFD, + 0x43, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x2A, 0x03, 0x00, 0xA8, 0x60, 0x76, 0x78, + 0xFF, 0xFF, 0x64, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, 0x0E, 0x00, 0x1F, 0xF2, 0xFF, 0xFF, + 0x60, 0x40, 0x40, 0x2B, 0x09, 0x00, 0x15, 0x60, 0xDD, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x2A, + 0x03, 0x00, 0xA9, 0x60, 0x81, 0x78, 0xFF, 0xFF, 0x1F, 0xF2, 0xC0, 0x60, 0x00, 0x65, 0xA4, 0x9C, + 0x3F, 0x60, 0xCF, 0x65, 0x29, 0x44, 0xA4, 0x84, 0x30, 0x89, 0x15, 0x60, 0xD9, 0xF3, 0xFF, 0xFF, + 0x15, 0x60, 0xD8, 0xFB, 0x1F, 0xF2, 0x39, 0xF1, 0xE0, 0x60, 0xFF, 0xB5, 0x0A, 0x18, 0x60, 0x47, + 0x1F, 0xB4, 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, + 0x60, 0x47, 0xB4, 0x81, 0x07, 0x60, 0xEB, 0xF1, 0xFF, 0xFF, 0xB1, 0x8C, 0x29, 0x40, 0x40, 0x2B, + 0x10, 0x00, 0x22, 0x60, 0xC6, 0x65, 0x60, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, + 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x01, 0x60, 0x09, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, + 0x14, 0x00, 0x22, 0x60, 0xC6, 0x65, 0x60, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, + 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, + 0x7C, 0x44, 0x29, 0x40, 0x80, 0x2B, 0x67, 0x44, 0x60, 0x4C, 0x00, 0xE1, 0x84, 0xFF, 0xC1, 0x60, + 0x6B, 0x64, 0x40, 0x42, 0x82, 0xFF, 0x0D, 0x00, 0xE5, 0xFE, 0x03, 0x04, 0xAA, 0x60, 0xC0, 0x78, + 0xFF, 0xFF, 0x32, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x07, 0x22, 0x43, 0xFF, 0xA4, 0x60, 0x7C, 0x78, + 0xFF, 0xFF, 0x3C, 0x44, 0x0B, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x0A, 0xE1, 0x1C, 0x42, 0x22, 0x46, + 0x13, 0xF2, 0xFF, 0x65, 0x60, 0x47, 0x2A, 0xF2, 0x40, 0x45, 0x40, 0x48, 0x04, 0x2B, 0x13, 0x00, + 0x16, 0xF2, 0x1D, 0xF2, 0x40, 0x43, 0x0F, 0xF2, 0x40, 0x4D, 0x0F, 0x64, 0x14, 0xF0, 0x35, 0xF2, + 0xA0, 0x82, 0x0F, 0xB4, 0xCA, 0x85, 0xD4, 0x80, 0x10, 0xF2, 0x01, 0x02, 0x2B, 0xFA, 0x27, 0x44, + 0x40, 0xBC, 0x40, 0x47, 0x13, 0x00, 0x17, 0xF2, 0x2C, 0xF0, 0x40, 0x43, 0x1B, 0xF2, 0x1D, 0xFA, + 0x40, 0x4D, 0x64, 0x40, 0x01, 0x2A, 0x02, 0x00, 0xAB, 0xFC, 0x05, 0x00, 0x28, 0x40, 0xA4, 0x36, + 0x02, 0x00, 0x11, 0xF2, 0x2B, 0xFA, 0x27, 0x44, 0xBF, 0xB4, 0x40, 0x47, 0xF0, 0xFE, 0xAF, 0x60, + 0x85, 0x78, 0xFF, 0xFF, 0x22, 0x46, 0x2C, 0xF0, 0x27, 0x44, 0xDF, 0xB4, 0x40, 0x47, 0x64, 0x40, + 0x01, 0x26, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x2A, 0xF0, 0x01, 0x65, 0x64, 0x40, 0xA4, 0x3A, + 0x04, 0x65, 0x27, 0x44, 0x34, 0x87, 0x36, 0xF3, 0xFF, 0xFF, 0x60, 0x56, 0xAD, 0xE2, 0x04, 0x64, + 0x3A, 0xDB, 0x69, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x06, 0x64, 0x3A, 0xDB, 0x22, 0x46, + 0x01, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xC1, 0x60, 0x44, 0x78, 0xFF, 0xFF, 0x28, 0x40, 0xC4, 0x3A, + 0x0C, 0x00, 0x27, 0x44, 0xFD, 0xB4, 0x40, 0x47, 0xA8, 0xE2, 0x05, 0xE1, 0x01, 0x60, 0x08, 0xE1, + 0x2A, 0xE8, 0x3C, 0x46, 0xA5, 0x60, 0x1C, 0x78, 0xFF, 0xFF, 0x3F, 0x40, 0x01, 0x2B, 0x05, 0x00, + 0x67, 0x4C, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, 0x07, 0x60, 0xEC, 0xF1, 0x1F, 0xF2, + 0x2A, 0xE8, 0xB0, 0x81, 0x29, 0x40, 0x40, 0x2B, 0x14, 0x00, 0x61, 0x4C, 0x22, 0x60, 0xC6, 0x65, + 0x61, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, + 0x01, 0x60, 0x09, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0xFF, 0x60, 0xF2, 0x64, 0x64, 0x4C, 0x40, 0x43, + 0x18, 0x00, 0x29, 0x47, 0x80, 0xB7, 0x34, 0x94, 0x60, 0x4C, 0x22, 0x60, 0xC6, 0x65, 0x61, 0x47, + 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, + 0x69, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, 0x7C, 0x44, 0x29, 0x40, 0x80, 0x2B, 0x67, 0x44, + 0x60, 0x4C, 0x40, 0xE1, 0x01, 0x60, 0x08, 0xE1, 0x28, 0x45, 0xBF, 0x60, 0xFF, 0x64, 0x24, 0x88, + 0xC4, 0xE2, 0x08, 0x64, 0x3A, 0xDB, 0x21, 0x46, 0x2A, 0x44, 0x72, 0x45, 0x24, 0xFA, 0x94, 0xF3, + 0x06, 0x04, 0xE4, 0xE2, 0xDC, 0x9C, 0x29, 0x40, 0x01, 0x26, 0x64, 0x44, 0x94, 0xF9, 0x25, 0xFA, + 0x95, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x95, 0xFB, 0x28, 0xFA, 0x96, 0xF3, 0x02, 0x04, 0xDC, 0x84, + 0x96, 0xFB, 0x29, 0xFA, 0x24, 0x44, 0x04, 0x2A, 0x06, 0x00, 0x28, 0x40, 0xA4, 0x36, 0x03, 0x00, + 0xA7, 0x60, 0x46, 0x78, 0xFF, 0xFF, 0x94, 0xFC, 0x13, 0x60, 0x4A, 0xF1, 0x28, 0x44, 0x08, 0x2A, + 0x51, 0x00, 0x03, 0x2B, 0x01, 0x00, 0x4E, 0x00, 0x64, 0x40, 0x00, 0x36, 0x4B, 0x00, 0x32, 0xF2, + 0x2F, 0xF0, 0x50, 0xFE, 0x01, 0x2A, 0x03, 0x00, 0x01, 0x61, 0x8E, 0xF3, 0x31, 0x00, 0xD0, 0x80, + 0x33, 0xF2, 0x30, 0xF0, 0x34, 0xF2, 0xD0, 0x80, 0x31, 0xF0, 0xFF, 0xFF, 0xD0, 0x80, 0x60, 0x47, + 0x34, 0x0C, 0xFF, 0xB4, 0x15, 0x60, 0x02, 0x65, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0xFF, 0xFF, + 0x31, 0x18, 0x60, 0x43, 0x50, 0xFE, 0x66, 0x41, 0x32, 0xF0, 0x63, 0x46, 0x03, 0xF2, 0x61, 0x46, + 0xD0, 0x80, 0x33, 0xF0, 0x63, 0x46, 0x04, 0xF2, 0x61, 0x46, 0xD0, 0x80, 0x34, 0xF0, 0x63, 0x46, + 0x05, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x04, 0x0C, 0x00, 0xF2, 0x61, 0x46, 0x1A, 0x18, + 0xE8, 0x01, 0x06, 0xF0, 0x8E, 0xF3, 0x61, 0x46, 0x02, 0x61, 0x64, 0x40, 0x02, 0x2A, 0x12, 0x00, + 0xFC, 0xA0, 0xFF, 0xFF, 0x04, 0x0E, 0x61, 0x44, 0x14, 0xFA, 0x11, 0xFC, 0x0B, 0x00, 0x2C, 0xF2, + 0x2F, 0xFA, 0x2D, 0xF2, 0x30, 0xFA, 0x2E, 0xF2, 0x31, 0xFA, 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xBC, + 0x40, 0x46, 0x1E, 0x00, 0x26, 0x43, 0x84, 0xBB, 0xFC, 0xB3, 0x21, 0x46, 0x01, 0x5D, 0x0F, 0xFC, + 0x5C, 0x46, 0x05, 0xFF, 0x27, 0x44, 0x01, 0x2A, 0x13, 0x00, 0x50, 0xFE, 0x28, 0x40, 0x08, 0x3A, + 0x12, 0x00, 0x2F, 0xF2, 0x30, 0xF0, 0x60, 0x43, 0x31, 0xF2, 0x22, 0x46, 0x64, 0x41, 0x2C, 0xF0, + 0x2D, 0xF0, 0xD3, 0x80, 0x2E, 0xF0, 0xD1, 0x80, 0xD0, 0x80, 0x27, 0x44, 0x09, 0x0C, 0x03, 0x00, + 0x27, 0x44, 0x06, 0x22, 0x05, 0x00, 0xB8, 0xB4, 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, + 0xD4, 0x64, 0x40, 0x48, 0x0D, 0x64, 0x3A, 0xDB, 0x21, 0x46, 0x1C, 0xF2, 0x00, 0xE1, 0xF0, 0xFE, + 0x00, 0x63, 0x28, 0x44, 0xA4, 0x36, 0x07, 0x00, 0x04, 0x2B, 0x05, 0x00, 0x30, 0xF3, 0x2D, 0x45, + 0xD4, 0x84, 0xCA, 0x65, 0xD4, 0x83, 0xD4, 0x64, 0x35, 0x00, 0x0F, 0x64, 0x3A, 0xDB, 0x21, 0x46, + 0x29, 0x40, 0x40, 0x27, 0x15, 0x00, 0x80, 0x27, 0x02, 0x00, 0xCA, 0x65, 0x01, 0x00, 0x6A, 0x65, + 0x1C, 0xF2, 0xFF, 0xFF, 0x04, 0x7F, 0x40, 0x45, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, + 0x37, 0x36, 0x15, 0x64, 0x6E, 0x3A, 0x17, 0x00, 0x84, 0x7F, 0x40, 0x45, 0x0B, 0x64, 0x13, 0x00, + 0x1C, 0xF2, 0x1E, 0x65, 0x40, 0x45, 0x0B, 0x36, 0x1E, 0x64, 0x0F, 0x36, 0x16, 0x64, 0x0A, 0x36, + 0x12, 0x64, 0x0E, 0x36, 0x0E, 0x64, 0x09, 0x36, 0x0E, 0x64, 0x0D, 0x36, 0x0A, 0x64, 0x08, 0x36, + 0x0A, 0x64, 0x0C, 0x36, 0x0A, 0x64, 0x40, 0x4D, 0x00, 0xE1, 0xF0, 0xFE, 0x2B, 0xF2, 0xC4, 0x85, + 0xD4, 0x83, 0xC4, 0x64, 0x40, 0x48, 0x2F, 0xF0, 0xB0, 0xF0, 0xB1, 0xF2, 0xA1, 0xFF, 0x12, 0x74, + 0xCD, 0xE2, 0x80, 0x4E, 0x12, 0x74, 0x83, 0x4C, 0x12, 0x74, 0x9A, 0xFF, 0x84, 0x4C, 0x12, 0x74, + 0x85, 0x4C, 0x12, 0x74, 0x81, 0x4C, 0x12, 0x74, 0xA1, 0xFF, 0x98, 0xFF, 0xB1, 0x60, 0x58, 0x4F, + 0x00, 0x78, 0xFF, 0xFF, 0x01, 0x60, 0x18, 0xE1, 0x78, 0x44, 0x03, 0xA4, 0x35, 0xFB, 0xB1, 0x60, + 0x43, 0x78, 0xFF, 0xFF, 0x29, 0x44, 0xF7, 0xB4, 0x40, 0x49, 0x27, 0x44, 0x01, 0x2A, 0x05, 0x00, + 0xFE, 0xB4, 0x40, 0x47, 0xA5, 0x60, 0xCD, 0x78, 0xFF, 0xFF, 0x13, 0x60, 0x2E, 0xF3, 0xFF, 0xFF, + 0x60, 0x40, 0x02, 0x36, 0xC1, 0xFE, 0xA4, 0x60, 0x6F, 0x78, 0xFF, 0xFF, 0x28, 0x40, 0xB4, 0x3A, + 0x0B, 0x00, 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, + 0xC0, 0xFE, 0xA6, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0x28, 0x44, 0xD4, 0x36, 0x03, 0x00, 0xA8, 0x60, + 0x5D, 0x78, 0xFF, 0xFF, 0xA8, 0xE2, 0x27, 0x44, 0xFB, 0xB4, 0x40, 0x47, 0x1C, 0x42, 0x22, 0x46, + 0x16, 0x60, 0x2B, 0xF3, 0xFF, 0xFF, 0x34, 0xFB, 0x2A, 0xF0, 0xF7, 0x60, 0xFF, 0x64, 0xA0, 0x84, + 0xA2, 0xDA, 0x60, 0x40, 0x40, 0x2B, 0xC4, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x22, 0x26, + 0x3F, 0x00, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, 0x05, 0x00, 0xBA, 0x00, 0x04, 0x2B, 0xB8, 0x00, + 0x87, 0xF5, 0x01, 0x00, 0x07, 0xF4, 0x4B, 0xF2, 0xFF, 0xFF, 0xDC, 0x84, 0x4B, 0xFA, 0x0C, 0x60, + 0xFE, 0x62, 0x80, 0xFF, 0xC8, 0x60, 0x78, 0x44, 0x02, 0xA4, 0xA2, 0xDB, 0x46, 0x78, 0xFF, 0xFF, + 0x82, 0xFF, 0x87, 0xF3, 0x66, 0x5C, 0xD0, 0x80, 0x00, 0x7C, 0x07, 0x03, 0x66, 0x43, 0x22, 0x46, + 0x22, 0xF2, 0x63, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x01, 0x00, 0x3C, 0xF1, 0x4B, 0xF0, 0x64, 0x41, + 0x64, 0x47, 0x60, 0x5F, 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, 0x60, 0x47, 0x22, 0x46, 0x3A, 0xFA, + 0x64, 0x44, 0x20, 0x7F, 0x34, 0x94, 0x3B, 0xFA, 0x08, 0x60, 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, + 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x80, 0x00, + 0x2A, 0xF2, 0x00, 0x60, 0x7C, 0x62, 0x60, 0x40, 0x40, 0x2B, 0x24, 0x00, 0xA2, 0xD3, 0x00, 0x61, + 0x60, 0xFE, 0xA0, 0xD3, 0x5E, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0xDC, 0x84, 0xF1, 0x81, + 0xC0, 0x2B, 0x04, 0x00, 0x80, 0x2A, 0x02, 0x00, 0x7F, 0xA4, 0xDC, 0x84, 0xFF, 0x3B, 0x03, 0x00, + 0x60, 0x47, 0xDC, 0x87, 0x01, 0x61, 0xC0, 0x80, 0x00, 0x36, 0xDC, 0x84, 0x4E, 0xDB, 0x60, 0xFE, + 0x5A, 0xD1, 0xFF, 0xFF, 0xC1, 0x84, 0xF0, 0x22, 0x10, 0xA4, 0xF0, 0x2A, 0x01, 0x00, 0x00, 0x64, + 0xA2, 0xDB, 0x20, 0xFE, 0x00, 0x60, 0x3E, 0xF3, 0xFF, 0xFF, 0xA0, 0xD3, 0x5A, 0xD1, 0x3A, 0xFA, + 0x3B, 0xF8, 0x74, 0x62, 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5A, 0x64, 0x47, + 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, 0x40, 0xF3, + 0xFF, 0xFF, 0xA0, 0xD1, 0x5A, 0xD1, 0x64, 0x45, 0x64, 0x44, 0xE3, 0x7F, 0xA0, 0x5A, 0x64, 0x47, + 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE6, 0x7F, + 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5A, 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, + 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE9, 0x7F, 0xA0, 0x5A, 0x64, 0x47, + 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEC, 0x7F, + 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, + 0xA0, 0x5A, 0x64, 0x44, 0xEF, 0x7F, 0xA0, 0x5A, 0x08, 0x60, 0x00, 0xEA, 0x65, 0x44, 0x02, 0xA4, + 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, + 0x0B, 0xF2, 0xFF, 0xFF, 0x7F, 0xB4, 0x0C, 0xF0, 0x04, 0x02, 0x64, 0x46, 0x00, 0xF0, 0x04, 0x64, + 0x22, 0x46, 0x03, 0xFA, 0x60, 0x41, 0x64, 0x46, 0x01, 0xF2, 0xFC, 0xA1, 0x61, 0x45, 0xD4, 0x84, + 0xFF, 0xFF, 0x08, 0x02, 0x00, 0xF0, 0x04, 0x63, 0x64, 0x46, 0x01, 0xF2, 0x22, 0x46, 0x1A, 0xFA, + 0x03, 0xFC, 0x02, 0x00, 0x22, 0x46, 0x1A, 0xFA, 0x35, 0xF2, 0x04, 0xF8, 0xDC, 0x84, 0x35, 0xFA, + 0x14, 0xF2, 0x0F, 0xB5, 0x0F, 0xB4, 0xCC, 0x84, 0x94, 0x80, 0x04, 0x60, 0x00, 0x65, 0x2A, 0xF2, + 0x01, 0x02, 0x94, 0x84, 0x2A, 0xFA, 0x95, 0xFC, 0x06, 0x00, 0xC4, 0x3A, 0x07, 0x00, 0x27, 0x44, + 0xFD, 0xB4, 0x40, 0x47, 0xA8, 0xE2, 0xA5, 0x60, 0x7A, 0x78, 0xFF, 0xFF, 0x28, 0x44, 0x04, 0x26, + 0x05, 0x00, 0x68, 0x3A, 0x03, 0x00, 0x32, 0x44, 0x00, 0x27, 0x03, 0x00, 0xA4, 0x60, 0x7C, 0x78, + 0xFF, 0xFF, 0x0A, 0x64, 0x3A, 0xDB, 0xA4, 0x60, 0x7C, 0x78, 0xFF, 0xFF, 0x0E, 0x64, 0x3A, 0xDB, + 0x3C, 0x44, 0x60, 0x46, 0x1E, 0xF0, 0x40, 0x42, 0x64, 0x40, 0x40, 0x27, 0x48, 0x00, 0x1F, 0xF2, + 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x27, 0x3C, 0x00, 0x80, 0x2B, 0x0B, 0x00, 0xBF, 0x60, 0xFF, 0x65, + 0x29, 0x44, 0x24, 0x89, 0x80, 0x60, 0x00, 0x65, 0x29, 0x44, 0x34, 0x89, 0x80, 0x60, 0x00, 0x63, + 0x05, 0x00, 0x3F, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x00, 0x63, 0x1E, 0xF2, 0x39, 0xF1, + 0xC0, 0x60, 0xFF, 0xB5, 0x0A, 0x18, 0x60, 0x47, 0x1F, 0xB4, 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, + 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, 0xB4, 0x84, 0x07, 0x60, 0xEB, 0xF1, + 0x3C, 0x94, 0xB0, 0x84, 0x60, 0x4C, 0x22, 0x60, 0xC6, 0x65, 0x60, 0x47, 0x1F, 0xB4, 0xE0, 0x84, + 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, 0x60, 0x4C, + 0xB5, 0xFF, 0x64, 0x4C, 0x7C, 0x44, 0x29, 0x40, 0x80, 0x2B, 0x67, 0x44, 0x60, 0x4C, 0x32, 0x00, + 0x15, 0x60, 0xDD, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x04, 0x26, 0xCB, 0x01, 0xBF, 0x01, 0x40, 0x60, + 0x00, 0x65, 0x29, 0x44, 0x34, 0x89, 0x40, 0x60, 0x00, 0x63, 0x9F, 0xF2, 0x1E, 0xF2, 0x39, 0xF1, + 0xC0, 0x60, 0xFF, 0xB5, 0x0A, 0x18, 0x60, 0x47, 0x1F, 0xB4, 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, + 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, 0xB4, 0x84, 0x07, 0x60, 0xEB, 0xF1, + 0x3C, 0x94, 0xB0, 0x81, 0x61, 0x4C, 0x22, 0x60, 0xC6, 0x65, 0x61, 0x47, 0x1F, 0xB4, 0xE0, 0x84, + 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x01, 0x60, 0x09, 0x6B, 0x60, 0x4C, + 0xB5, 0xFF, 0x64, 0x4C, 0x40, 0xE1, 0x01, 0x60, 0x08, 0xE1, 0x84, 0xFF, 0xC1, 0x60, 0x6B, 0x64, + 0x40, 0x42, 0x82, 0xFF, 0x2A, 0xF2, 0x10, 0x60, 0x00, 0x65, 0xA4, 0x84, 0xB4, 0xBC, 0x1E, 0xF0, + 0x40, 0x48, 0x64, 0x40, 0x40, 0x27, 0x17, 0x00, 0x1C, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x0A, 0x36, + 0x06, 0x00, 0x14, 0x36, 0x07, 0x00, 0x37, 0x36, 0x08, 0x00, 0x6E, 0x36, 0x09, 0x00, 0x70, 0x7C, + 0xA0, 0x63, 0x0F, 0x00, 0x38, 0x7C, 0x50, 0x63, 0x0C, 0x00, 0x15, 0x7C, 0x1E, 0x63, 0x09, 0x00, + 0x0B, 0x7C, 0x0F, 0x63, 0x06, 0x00, 0x9C, 0xF4, 0xFF, 0x65, 0x63, 0x47, 0xA4, 0x9C, 0xA7, 0x84, + 0x23, 0x00, 0x40, 0x45, 0x43, 0x4D, 0x00, 0xE1, 0xF0, 0xFE, 0x29, 0x40, 0x80, 0x2B, 0x03, 0x00, + 0x00, 0x60, 0x6A, 0x65, 0x02, 0x00, 0x00, 0x60, 0xCA, 0x65, 0x1F, 0xF2, 0xFF, 0xFF, 0x60, 0x40, + 0x40, 0x27, 0x0E, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x04, 0x27, 0x03, 0x00, 0x65, 0x44, + 0xE0, 0x85, 0x12, 0x00, 0x2B, 0xF2, 0x11, 0xF0, 0xC0, 0x84, 0xD0, 0x84, 0xC4, 0x83, 0x11, 0x00, + 0x1E, 0x64, 0xC4, 0x84, 0x60, 0x45, 0x08, 0x00, 0x40, 0x45, 0xFF, 0x60, 0xF8, 0x64, 0x40, 0x43, + 0x00, 0xE1, 0xF0, 0xFE, 0x00, 0x60, 0x3C, 0x65, 0x91, 0xF4, 0x1B, 0xF0, 0xC3, 0x84, 0xC4, 0x84, + 0xC0, 0x83, 0x28, 0x44, 0xA1, 0xFF, 0x12, 0x74, 0x80, 0x4E, 0x12, 0x74, 0x83, 0x4C, 0x9A, 0xFF, + 0x12, 0x74, 0x56, 0x62, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, + 0x5C, 0x62, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0xA1, 0xFF, + 0x98, 0xFF, 0xB1, 0x60, 0x58, 0x4F, 0x00, 0x78, 0xFF, 0xFF, 0xBC, 0xFF, 0xB5, 0xFF, 0x01, 0x60, + 0x18, 0xE1, 0x47, 0xFF, 0x27, 0x44, 0x02, 0xBC, 0x40, 0x47, 0x36, 0xF3, 0xB6, 0xFF, 0xB7, 0xFF, + 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, 0x60, 0x56, 0xAD, 0xE2, 0xA5, 0x60, 0xC7, 0x78, + 0xFF, 0xFF, 0x15, 0x60, 0xDD, 0xF3, 0x15, 0x60, 0xBE, 0xF3, 0x60, 0x40, 0x04, 0x26, 0x0B, 0x00, + 0x07, 0xB4, 0x60, 0x40, 0x01, 0x36, 0x07, 0x00, 0x29, 0x44, 0xBF, 0x60, 0xFF, 0xB7, 0x80, 0xBF, + 0x40, 0x49, 0x80, 0x67, 0x05, 0x00, 0x3F, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x00, 0x64, + 0x12, 0x60, 0xD3, 0xF1, 0xFF, 0xFF, 0x15, 0x60, 0xD8, 0xF9, 0x39, 0xF1, 0x12, 0x60, 0xBF, 0xF1, + 0x64, 0x41, 0x64, 0x5E, 0x60, 0x45, 0x64, 0x47, 0x1F, 0xB4, 0x54, 0x94, 0xE0, 0xA0, 0x02, 0x0D, + 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, 0x07, 0x60, 0xEB, 0xF1, 0xB4, 0x84, + 0xB0, 0x8C, 0x22, 0x60, 0xC6, 0x7C, 0x60, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x40, 0xD3, + 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, + 0x7C, 0x44, 0x29, 0x40, 0x80, 0x2B, 0x67, 0x44, 0x60, 0x4C, 0x40, 0xE1, 0x01, 0x60, 0x08, 0xE1, + 0x84, 0xFF, 0xC1, 0x60, 0x6B, 0x64, 0x40, 0x42, 0x82, 0xFF, 0x3C, 0x44, 0x60, 0x46, 0x40, 0x42, + 0x13, 0x64, 0x3A, 0xDB, 0x10, 0x60, 0x00, 0x65, 0x3C, 0x46, 0x2A, 0xF2, 0x15, 0x60, 0xBE, 0xF1, + 0xA4, 0x84, 0xC4, 0xBC, 0x40, 0x48, 0x64, 0x44, 0x04, 0x26, 0x09, 0x00, 0x02, 0x26, 0x0A, 0x00, + 0x01, 0x26, 0x0B, 0x00, 0x08, 0x2A, 0x03, 0x00, 0x0B, 0x63, 0x6E, 0x64, 0x08, 0x00, 0x15, 0x63, + 0x37, 0x64, 0x05, 0x00, 0x38, 0x63, 0x14, 0x64, 0x02, 0x00, 0x70, 0x63, 0x0A, 0x64, 0x43, 0x4D, + 0x40, 0x45, 0x00, 0xE1, 0xF0, 0xFE, 0x00, 0x60, 0x1E, 0x64, 0x1B, 0xF0, 0x11, 0xF0, 0xC0, 0x84, + 0xC0, 0x84, 0x60, 0x43, 0x28, 0x44, 0xA1, 0xFF, 0x12, 0x74, 0x80, 0x4E, 0x12, 0x74, 0x83, 0x4C, + 0x9A, 0xFF, 0x12, 0x74, 0x5C, 0x62, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, + 0x12, 0x74, 0xA1, 0xFF, 0x98, 0xFF, 0xB1, 0x60, 0x58, 0x4F, 0x00, 0x78, 0xFF, 0xFF, 0x01, 0x60, + 0x18, 0xE1, 0x78, 0x44, 0x03, 0xA4, 0x35, 0xFB, 0xB1, 0x60, 0x43, 0x78, 0xFF, 0xFF, 0xC4, 0xE2, + 0x08, 0x64, 0x3A, 0xDB, 0xA5, 0x60, 0x1C, 0x78, 0xFF, 0xFF, 0x24, 0x40, 0x01, 0x2A, 0x0E, 0x00, + 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xBC, 0x40, 0x46, 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, + 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x30, 0xF1, 0x52, 0x00, 0xFC, 0xB3, 0x32, 0x40, + 0x01, 0x2A, 0x06, 0x00, 0x0A, 0xBB, 0x0F, 0xFC, 0xCB, 0xFE, 0xA4, 0x60, 0x7C, 0x78, 0xFF, 0xFF, + 0x24, 0x44, 0x04, 0x26, 0x02, 0x00, 0x0F, 0xFC, 0x05, 0xFF, 0x30, 0xF1, 0x27, 0x44, 0x05, 0x22, + 0x2C, 0x00, 0xFA, 0xB4, 0x40, 0x47, 0x24, 0x44, 0x10, 0x2A, 0x23, 0x00, 0x28, 0x40, 0xD4, 0x3A, + 0x20, 0x00, 0x31, 0x40, 0x08, 0x26, 0x00, 0x7C, 0x2B, 0x44, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, + 0x64, 0x44, 0xC4, 0x84, 0xFF, 0xFF, 0x04, 0x24, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, + 0x20, 0x29, 0x6D, 0xE2, 0x1D, 0xF0, 0xC0, 0x64, 0xC0, 0x84, 0x0A, 0x60, 0x7B, 0xF1, 0xE8, 0x84, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, 0xA2, 0xDB, 0xA5, 0x60, 0xCD, 0x78, + 0xFF, 0xFF, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x07, 0x00, 0x02, 0x2A, 0x05, 0x00, 0xFD, 0xB4, + 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x05, 0x64, 0x3A, 0xDB, 0x28, 0x44, 0xA4, 0x3A, + 0x07, 0x00, 0x01, 0x60, 0x02, 0x7C, 0x25, 0x44, 0x0A, 0x3A, 0x02, 0x00, 0x01, 0x60, 0x3A, 0x7C, + 0x31, 0x40, 0x08, 0x26, 0x00, 0x7C, 0x2B, 0x44, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, 0x64, 0x44, + 0xC4, 0x84, 0xFF, 0xFF, 0x04, 0x24, 0x00, 0xB4, 0x28, 0x40, 0xE4, 0x36, 0x00, 0xB4, 0x60, 0x50, + 0x08, 0x28, 0x01, 0x00, 0x20, 0x29, 0x6D, 0xE2, 0xA4, 0x60, 0x6F, 0x78, 0xFF, 0xFF, 0x27, 0x44, + 0x05, 0x22, 0x09, 0x00, 0xBA, 0xB4, 0x40, 0x47, 0x3C, 0x46, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, + 0xA4, 0x60, 0x7C, 0x78, 0xFF, 0xFF, 0x27, 0x44, 0x02, 0x2A, 0x06, 0x00, 0xFD, 0xB4, 0x40, 0x47, + 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xF4, 0x01, 0xF3, 0x0A, 0x7C, 0x50, 0x6D, 0xE2, 0xF0, 0x01, + 0x72, 0x45, 0xDC, 0x84, 0x94, 0xFB, 0x11, 0x64, 0x3A, 0xDB, 0x95, 0xF3, 0x06, 0x04, 0xDC, 0x84, + 0x95, 0xFB, 0x96, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x96, 0xFB, 0xA4, 0x60, 0x87, 0x78, 0xFF, 0xFF, + 0x00, 0x61, 0x12, 0x64, 0x3A, 0xDB, 0x18, 0x60, 0xEE, 0x63, 0xBD, 0xD3, 0x72, 0x45, 0x44, 0x8A, + 0x02, 0x28, 0x03, 0x00, 0xE4, 0xE2, 0xDD, 0x81, 0x04, 0x00, 0x02, 0x28, 0x02, 0x00, 0xE4, 0xE2, + 0xDD, 0x81, 0xBD, 0xD3, 0x94, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, + 0xC4, 0x84, 0x60, 0x55, 0x2A, 0x52, 0xE4, 0xE2, 0x94, 0xFB, 0x02, 0x24, 0x01, 0xB9, 0xBD, 0xD3, + 0x95, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, 0xC4, 0x84, 0x95, 0xFB, + 0x02, 0x24, 0x01, 0xB9, 0xBD, 0xD3, 0x96, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0xC4, 0x84, 0x96, 0xFB, + 0xA5, 0x60, 0x71, 0x78, 0xFF, 0xFF, 0xAC, 0x01, 0x47, 0xFF, 0x44, 0xFF, 0xC8, 0x74, 0xCD, 0xE2, + 0xAA, 0x60, 0xFE, 0x78, 0x00, 0x61, 0xA4, 0x60, 0x7C, 0x78, 0xFF, 0xFF, 0x5C, 0x44, 0x26, 0x44, + 0x02, 0x26, 0x0C, 0x00, 0x3E, 0x46, 0x09, 0xF2, 0x1E, 0x41, 0x03, 0x1B, 0xAC, 0x60, 0x14, 0x78, + 0xFF, 0xFF, 0x40, 0x5E, 0xFD, 0xFB, 0x21, 0x44, 0x02, 0x64, 0x40, 0x46, 0x41, 0x5D, 0x21, 0x46, + 0x00, 0x64, 0x31, 0xFA, 0x00, 0xF2, 0x46, 0x45, 0x87, 0xFC, 0xAC, 0xE2, 0x01, 0x64, 0x33, 0xFB, + 0x32, 0x40, 0x01, 0x2A, 0x21, 0x00, 0x19, 0xF3, 0x01, 0x60, 0x1E, 0xE1, 0x1D, 0x18, 0x80, 0x64, + 0x40, 0x49, 0x00, 0xE1, 0x19, 0xFF, 0x08, 0x64, 0x2A, 0xFA, 0x5A, 0xDA, 0x2C, 0xFA, 0x5A, 0xDA, + 0x5A, 0xDA, 0xD2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xD2, 0xFB, 0x72, 0x44, 0x24, 0xFA, 0x94, 0xF3, + 0x25, 0xFA, 0xA1, 0xFF, 0xFF, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, + 0x7C, 0x4B, 0xA4, 0x60, 0x7C, 0x78, 0xFF, 0xFF, 0x01, 0xE1, 0x01, 0x60, 0x1A, 0xE1, 0x3F, 0x60, + 0xCF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x2E, 0x44, 0x00, 0x36, 0x41, 0x00, 0x01, 0x3A, 0xC9, 0x00, + 0x88, 0xFF, 0x40, 0x67, 0x29, 0x45, 0x34, 0x89, 0x04, 0x64, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, + 0xA1, 0xFF, 0x6C, 0x45, 0x65, 0x44, 0x0F, 0xB4, 0x40, 0x45, 0x1C, 0xFA, 0x65, 0x44, 0x29, 0x41, + 0xF9, 0x81, 0x52, 0x4A, 0x71, 0x89, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x83, 0x1D, 0xFC, + 0x1B, 0xFC, 0x98, 0xF1, 0xFC, 0xA3, 0xD3, 0x80, 0x43, 0x43, 0x03, 0x04, 0xAC, 0x60, 0x0A, 0x78, + 0xFF, 0xFF, 0x09, 0x7C, 0xD3, 0x80, 0x9A, 0xFF, 0x03, 0x07, 0xAC, 0x60, 0x0A, 0x78, 0xFF, 0xFF, + 0x25, 0x44, 0x01, 0x26, 0x0F, 0xAC, 0x1F, 0x60, 0x50, 0x65, 0x44, 0xD3, 0x12, 0x65, 0x45, 0x46, + 0x60, 0x47, 0x40, 0x7F, 0x27, 0xFA, 0x8F, 0xFC, 0x18, 0x61, 0xCB, 0xF1, 0xA1, 0xFF, 0x6C, 0x44, + 0xDC, 0x80, 0xFF, 0xFF, 0x21, 0x03, 0x50, 0xFE, 0xAC, 0x60, 0x20, 0x78, 0xFF, 0xFF, 0xC8, 0x60, + 0x0B, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0xB5, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xAA, 0x74, 0xCD, 0xE2, + 0x02, 0x64, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0x01, 0x60, 0x08, 0xE1, 0x05, 0xE1, 0xA1, 0xFF, + 0xFF, 0xFF, 0x04, 0x25, 0x76, 0x00, 0x6C, 0x44, 0x0A, 0x36, 0x07, 0x00, 0x14, 0x36, 0x05, 0x00, + 0x37, 0x36, 0x03, 0x00, 0x6E, 0x36, 0x01, 0x00, 0x6C, 0x00, 0x40, 0x45, 0x32, 0x74, 0xA1, 0xFF, + 0x1C, 0xFA, 0x40, 0x4E, 0x8C, 0x44, 0x60, 0x43, 0x1D, 0xFA, 0x01, 0xE1, 0x20, 0x64, 0x3A, 0xDB, + 0x2E, 0x44, 0x14, 0x36, 0x12, 0x00, 0x0A, 0x36, 0x0F, 0x00, 0x63, 0x45, 0xE3, 0x83, 0xE3, 0x83, + 0xC7, 0x83, 0xE3, 0x83, 0xC7, 0x83, 0xFF, 0xFF, 0x37, 0x36, 0x05, 0x00, 0x6E, 0x36, 0x04, 0x00, + 0xAC, 0x60, 0x1E, 0x78, 0xFF, 0xFF, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xFF, 0xFF, + 0x80, 0x27, 0xCF, 0x83, 0x1B, 0xFC, 0x01, 0x64, 0x4F, 0xFB, 0xA1, 0xFF, 0x29, 0x41, 0xF9, 0x81, + 0x52, 0x4A, 0x71, 0x89, 0x2E, 0x44, 0x27, 0xFA, 0x98, 0xF1, 0xFC, 0xA3, 0xD3, 0x80, 0x43, 0x43, + 0x03, 0x04, 0xAC, 0x60, 0x0A, 0x78, 0xFF, 0xFF, 0x9A, 0xFF, 0x54, 0x63, 0x12, 0x64, 0x40, 0x46, + 0x8F, 0xFC, 0x18, 0x61, 0xCB, 0xF1, 0x50, 0xFE, 0x6C, 0x40, 0x9E, 0x15, 0x01, 0x60, 0x08, 0xE1, + 0x80, 0xE1, 0x00, 0x64, 0x33, 0xFB, 0x01, 0x60, 0x18, 0xE1, 0x01, 0x11, 0x0F, 0x00, 0x29, 0x44, + 0x20, 0xBC, 0x40, 0x49, 0x01, 0x64, 0x33, 0xFB, 0xB6, 0xFF, 0x00, 0xE1, 0x01, 0x60, 0x1A, 0xE1, + 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x40, 0xFC, 0x11, 0x01, 0x60, 0x18, 0xE1, 0xB5, 0xFF, 0xB6, 0xFF, + 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, 0x35, 0xE1, 0xAC, 0xE2, 0xAA, 0x60, + 0x97, 0x78, 0xFF, 0xFF, 0x13, 0x60, 0x02, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, + 0xA2, 0xDB, 0x21, 0x64, 0x3A, 0xDB, 0xD2, 0x01, 0x25, 0x60, 0xF2, 0x64, 0xE5, 0x60, 0x78, 0x41, + 0xC7, 0x78, 0x97, 0xF1, 0x2A, 0x64, 0x3A, 0xDB, 0x5C, 0x41, 0xC8, 0x01, 0x29, 0x64, 0x3A, 0xDB, + 0x88, 0x60, 0x85, 0x71, 0x8D, 0xE2, 0xA2, 0xFC, 0x32, 0x40, 0x01, 0x2A, 0xA8, 0x00, 0x01, 0x60, + 0x1A, 0xE1, 0x23, 0x43, 0xA1, 0xFF, 0xEC, 0x44, 0x2A, 0xFA, 0x40, 0x48, 0xA1, 0xFF, 0x7A, 0xDC, + 0x7E, 0x36, 0x04, 0xA2, 0xFC, 0x1C, 0x03, 0x1D, 0x00, 0x64, 0x3F, 0xFA, 0x2E, 0x00, 0x03, 0x2B, + 0x04, 0x00, 0xA1, 0xFF, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x8F, 0xB0, 0x88, 0x3A, 0x03, 0x00, + 0x70, 0x62, 0xA1, 0xFF, 0x7A, 0xDC, 0x28, 0x40, 0x40, 0x2B, 0x06, 0x00, 0x72, 0x62, 0xA1, 0xFF, + 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x3F, 0xFC, 0x00, 0xF4, 0x10, 0x62, 0x6E, 0x61, + 0xA1, 0xFF, 0x05, 0x1D, 0x12, 0x1E, 0x0C, 0x00, 0x00, 0xF4, 0x7C, 0x61, 0x02, 0x62, 0x7A, 0xDC, + 0x63, 0x40, 0xFD, 0x1C, 0xF9, 0x1D, 0xFF, 0xB1, 0x08, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, + 0xB6, 0xFF, 0xB7, 0xFF, 0xA1, 0xFF, 0x6C, 0x44, 0x5A, 0xDA, 0x98, 0xFF, 0xA1, 0xFF, 0x6C, 0x40, + 0xA1, 0xFF, 0x47, 0xFF, 0x7C, 0x44, 0x33, 0xFB, 0x26, 0x44, 0xFD, 0xB4, 0x84, 0xBC, 0x01, 0x15, + 0x7F, 0xB4, 0x40, 0x46, 0x6C, 0x40, 0xB6, 0xFF, 0xB7, 0xFF, 0xA1, 0xFF, 0x6C, 0x45, 0xA1, 0xFF, + 0x7F, 0x60, 0x7F, 0x7C, 0x6C, 0x44, 0xA0, 0x84, 0x15, 0xA7, 0x15, 0xA4, 0x21, 0x46, 0x26, 0xFA, + 0x29, 0x40, 0x40, 0x2B, 0x07, 0x00, 0xB6, 0xFF, 0x40, 0x60, 0x00, 0x65, 0xA1, 0xFF, 0x6C, 0x44, + 0x1A, 0xFA, 0x09, 0x00, 0x65, 0x44, 0x0F, 0xB4, 0x06, 0xA8, 0x80, 0x60, 0x00, 0x65, 0x08, 0x28, + 0x7C, 0x45, 0x29, 0x44, 0x34, 0x89, 0x27, 0xF0, 0x65, 0x44, 0x64, 0x5E, 0x27, 0xFA, 0x81, 0xE1, + 0x01, 0x60, 0x18, 0xE1, 0x01, 0x11, 0x0F, 0x00, 0x29, 0x44, 0x20, 0xBC, 0x40, 0x49, 0x01, 0x64, + 0x33, 0xFB, 0xB6, 0xFF, 0x00, 0xE1, 0x01, 0x60, 0x1A, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x40, + 0xFC, 0x11, 0x01, 0x60, 0x18, 0xE1, 0x21, 0x46, 0xB5, 0xFF, 0xBC, 0xFF, 0x47, 0xFF, 0xB6, 0xFF, + 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, 0x26, 0x43, 0x2A, 0x44, 0x72, 0x45, + 0x24, 0xFA, 0x94, 0xF3, 0x06, 0x04, 0xE4, 0xE2, 0xDC, 0x9C, 0x29, 0x40, 0x01, 0x26, 0x64, 0x44, + 0x94, 0xF9, 0x25, 0xFA, 0x95, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x95, 0xFB, 0x28, 0xFA, 0x96, 0xF3, + 0x02, 0x04, 0xDC, 0x84, 0x96, 0xFB, 0x29, 0xFA, 0xAA, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, + 0x12, 0x61, 0x8C, 0x44, 0xCC, 0xF0, 0x2A, 0xFA, 0x40, 0x48, 0x04, 0x26, 0x43, 0x00, 0xA1, 0xFF, + 0x8C, 0x44, 0x5A, 0xDA, 0x30, 0xFB, 0x6C, 0x44, 0x2C, 0xFA, 0xFF, 0xFF, 0x01, 0x26, 0x26, 0x00, + 0xD0, 0x80, 0xA1, 0xFF, 0x8C, 0x44, 0x6C, 0x5C, 0x00, 0xE1, 0xF2, 0xFE, 0x2D, 0xFA, 0xCD, 0xF3, + 0xD4, 0x80, 0xD0, 0x80, 0x2E, 0xF8, 0x24, 0x44, 0x16, 0x0C, 0x32, 0x40, 0x02, 0x2A, 0x07, 0x00, + 0x28, 0x42, 0x0C, 0xB2, 0x08, 0x3A, 0x03, 0x00, 0x10, 0xBC, 0x40, 0x44, 0x5C, 0x00, 0x04, 0x0A, + 0xA1, 0xFF, 0xAC, 0x60, 0x13, 0x78, 0xFF, 0xFF, 0x11, 0xBC, 0x40, 0x44, 0x28, 0x45, 0xBF, 0x60, + 0xFF, 0x64, 0x24, 0x88, 0x50, 0x00, 0x30, 0xBC, 0x40, 0x44, 0x4D, 0x00, 0x20, 0xB9, 0x5C, 0x8E, + 0xA1, 0xFF, 0x8C, 0x44, 0x2D, 0xFA, 0xDC, 0x9C, 0x6C, 0x44, 0x00, 0xE1, 0xF2, 0xFE, 0x2E, 0xFA, + 0x08, 0x28, 0x44, 0x4E, 0xDC, 0x84, 0x2E, 0x5C, 0xB0, 0x84, 0xEF, 0xB1, 0x08, 0x24, 0x40, 0xB9, + 0x41, 0x46, 0x39, 0x00, 0x23, 0x41, 0x13, 0x64, 0x51, 0x90, 0x56, 0x63, 0x03, 0x04, 0xAC, 0x60, + 0x0A, 0x78, 0xFF, 0xFF, 0x8C, 0x44, 0x04, 0x61, 0x2B, 0xFA, 0x50, 0xFE, 0x80, 0x27, 0x00, 0x64, + 0x30, 0xFB, 0x8C, 0x44, 0x2C, 0xFA, 0xD0, 0x80, 0x8C, 0x44, 0x2D, 0xFA, 0xD4, 0x80, 0x00, 0x65, + 0x8C, 0x44, 0xCD, 0xF1, 0x2E, 0xFA, 0xD0, 0x80, 0x28, 0x44, 0x03, 0x0C, 0xA0, 0x2A, 0x0A, 0x00, + 0x11, 0x00, 0x10, 0x65, 0x60, 0x40, 0xC4, 0x36, 0x04, 0x00, 0xD4, 0x3A, 0x08, 0x00, 0x27, 0x40, + 0x40, 0x26, 0x30, 0x65, 0x00, 0x64, 0x3F, 0xFA, 0x46, 0x4E, 0x35, 0x84, 0x66, 0x00, 0x40, 0x26, + 0xF9, 0x01, 0x30, 0x65, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x04, 0x61, 0xF3, 0x01, 0xA1, 0xFF, + 0xAB, 0x60, 0xE6, 0x78, 0xFF, 0xFF, 0xFF, 0x60, 0xFE, 0x65, 0x23, 0x43, 0xE8, 0xA3, 0x80, 0x27, + 0xF6, 0x01, 0x20, 0xE6, 0x08, 0x60, 0x00, 0xEB, 0x28, 0x44, 0x03, 0x2B, 0x05, 0x00, 0x6A, 0x62, + 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x28, 0x44, 0x8F, 0xB0, 0x88, 0x3A, 0x03, 0x00, 0x70, 0x62, + 0x7A, 0xDC, 0x28, 0x44, 0x40, 0x2B, 0x0D, 0x00, 0x72, 0x62, 0x7A, 0xDC, 0xA1, 0xFF, 0x6C, 0x5C, + 0x5A, 0xD8, 0xE4, 0x40, 0x20, 0x2B, 0x03, 0x00, 0x7A, 0xDC, 0x7A, 0xDC, 0xF8, 0xA3, 0x25, 0xFF, + 0xB0, 0xFF, 0x3F, 0xFC, 0x00, 0xF4, 0x10, 0x62, 0x10, 0x61, 0x57, 0x90, 0x6C, 0x61, 0xA1, 0xFF, + 0x09, 0x07, 0x02, 0x1D, 0x2A, 0x1E, 0x21, 0x00, 0xCB, 0x83, 0x7A, 0xDC, 0xFE, 0x1C, 0xD9, 0x81, + 0x24, 0x1E, 0x1B, 0x00, 0xCB, 0x83, 0x0E, 0xA3, 0xA7, 0x84, 0xF2, 0xA3, 0x7A, 0xDC, 0xFE, 0x1C, + 0x05, 0x1D, 0x01, 0x60, 0x18, 0xE1, 0x7C, 0xA8, 0xD9, 0x81, 0x0A, 0x02, 0x00, 0xF4, 0x02, 0x62, + 0xA7, 0x84, 0x7A, 0x61, 0x7A, 0xDC, 0xFE, 0x1C, 0xF9, 0x1D, 0x7C, 0xA8, 0xD9, 0x81, 0xF6, 0x03, + 0xFF, 0xB1, 0x0B, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, 0xA1, 0xFF, 0xFF, 0xFF, 0xB6, 0xFF, + 0xB7, 0xFF, 0x6C, 0x44, 0x5A, 0xDA, 0xCD, 0x81, 0x64, 0x40, 0x46, 0x45, 0x28, 0x44, 0x40, 0x2B, + 0x0E, 0x00, 0x64, 0x40, 0x20, 0x2B, 0x0B, 0x00, 0x01, 0xA2, 0x62, 0x44, 0x46, 0x45, 0x21, 0x46, + 0x00, 0xF4, 0x02, 0x62, 0x9A, 0xFF, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x98, 0xFF, + 0x00, 0xE6, 0x01, 0xF2, 0x61, 0x45, 0xD4, 0x9E, 0x21, 0x46, 0x16, 0xFA, 0x25, 0x44, 0x06, 0xFA, + 0xA1, 0xFF, 0x8C, 0x44, 0xA1, 0xFF, 0x47, 0xFF, 0x50, 0x4B, 0x67, 0x50, 0x69, 0xE2, 0x25, 0x46, + 0x01, 0xF2, 0x61, 0x45, 0xD4, 0x9E, 0x21, 0x46, 0x16, 0xFA, 0x25, 0x45, 0x86, 0xF8, 0xFF, 0xFF, + 0x6A, 0x44, 0x40, 0x2B, 0x03, 0x15, 0xAF, 0x60, 0x10, 0x78, 0xFF, 0xFF, 0x29, 0x40, 0x10, 0x26, + 0x04, 0x00, 0x04, 0x74, 0xCD, 0xE2, 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x44, 0xB6, 0xFF, 0xB7, 0xFF, + 0xC4, 0xE2, 0x01, 0x60, 0x18, 0xE1, 0x05, 0x76, 0xAD, 0xE2, 0x41, 0xE1, 0xA1, 0xFF, 0x6C, 0x45, + 0xA1, 0xFF, 0x65, 0x41, 0x7F, 0x60, 0x7F, 0x7C, 0x6C, 0x44, 0xA0, 0x84, 0x15, 0xA7, 0x15, 0xA4, + 0x21, 0x46, 0x26, 0xFA, 0x22, 0x46, 0x10, 0xFA, 0x21, 0x46, 0x29, 0x40, 0x40, 0x2B, 0x07, 0x00, + 0xB6, 0xFF, 0xA1, 0xFF, 0x40, 0x60, 0x00, 0x65, 0x6C, 0x44, 0x1A, 0xFA, 0x09, 0x00, 0x65, 0x44, + 0x0F, 0xB4, 0x06, 0xA8, 0x80, 0x60, 0x00, 0x65, 0x08, 0x28, 0x7C, 0x45, 0x29, 0x44, 0x34, 0x89, + 0x27, 0xF0, 0x65, 0x47, 0x1F, 0xB1, 0x34, 0x97, 0x64, 0x5E, 0x07, 0x60, 0xF5, 0xF1, 0x29, 0x40, + 0x40, 0x2B, 0x04, 0x00, 0x64, 0x40, 0x02, 0x26, 0x10, 0x60, 0x00, 0xBC, 0x27, 0xFA, 0x01, 0x60, + 0x18, 0xE1, 0x00, 0x64, 0x33, 0xFB, 0xA8, 0xE2, 0x05, 0xE1, 0x28, 0x40, 0x03, 0x26, 0xCE, 0x00, + 0x31, 0x40, 0x20, 0x2A, 0x03, 0x00, 0x28, 0x40, 0x50, 0x3A, 0xC8, 0x00, 0x24, 0x44, 0x20, 0x2A, + 0xC5, 0x00, 0x2B, 0x44, 0xAC, 0x80, 0x28, 0x40, 0xB4, 0x3A, 0x03, 0x00, 0x02, 0x03, 0x30, 0xFB, + 0xBD, 0x00, 0x28, 0x44, 0xBF, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x40, 0x48, 0x2B, 0x50, 0xA1, 0xFF, + 0xFF, 0xFF, 0x01, 0x60, 0x08, 0xE1, 0x1C, 0xF2, 0xC4, 0xE2, 0x40, 0x45, 0x28, 0x40, 0xC4, 0x36, + 0x9D, 0x00, 0x29, 0x40, 0x40, 0x2B, 0x49, 0x00, 0x2B, 0x60, 0xBE, 0x63, 0x60, 0x40, 0x0B, 0x36, + 0x20, 0x00, 0x0F, 0x36, 0x1B, 0x00, 0x0A, 0x36, 0x16, 0x00, 0x0E, 0x36, 0x11, 0x00, 0x09, 0x36, + 0x0C, 0x00, 0x0D, 0x36, 0x07, 0x00, 0x08, 0x36, 0x02, 0x00, 0xA3, 0xD3, 0x15, 0x00, 0x02, 0xA3, + 0xA3, 0xD3, 0x12, 0x00, 0x04, 0xA3, 0xA3, 0xD3, 0x0F, 0x00, 0x06, 0xA3, 0xA3, 0xD3, 0x0C, 0x00, + 0x08, 0xA3, 0xA3, 0xD3, 0x09, 0x00, 0x0A, 0xA3, 0xA3, 0xD3, 0x06, 0x00, 0x0C, 0xA3, 0xA3, 0xD3, + 0x03, 0x00, 0x0E, 0xA3, 0xA3, 0xD3, 0xFF, 0xFF, 0x25, 0x60, 0x82, 0x63, 0x60, 0x40, 0x0C, 0x36, + 0x19, 0x00, 0x08, 0x36, 0x15, 0x00, 0x0D, 0x36, 0x11, 0x00, 0x09, 0x36, 0x0D, 0x00, 0x0E, 0x36, + 0x09, 0x00, 0x0A, 0x36, 0x05, 0x00, 0x0F, 0x36, 0x01, 0x00, 0x3A, 0x00, 0x02, 0xA3, 0x38, 0x00, + 0x04, 0xA3, 0x36, 0x00, 0x06, 0xA3, 0x34, 0x00, 0x08, 0xA3, 0x32, 0x00, 0x0A, 0xA3, 0x30, 0x00, + 0x0C, 0xA3, 0x2E, 0x00, 0x0E, 0xA3, 0x2C, 0x00, 0x2B, 0x00, 0x2B, 0x60, 0xCE, 0x63, 0x25, 0x44, + 0x0A, 0x36, 0x0C, 0x00, 0x14, 0x36, 0x07, 0x00, 0x37, 0x36, 0x02, 0x00, 0xA3, 0xD3, 0x09, 0x00, + 0x02, 0xA3, 0xA3, 0xD3, 0x06, 0x00, 0x04, 0xA3, 0xA3, 0xD3, 0x03, 0x00, 0x06, 0xA3, 0xA3, 0xD3, + 0xFF, 0xFF, 0x40, 0x45, 0x0A, 0x36, 0x0D, 0x00, 0x14, 0x36, 0x38, 0x64, 0x37, 0x3A, 0x03, 0x00, + 0x04, 0x7F, 0x40, 0x45, 0x15, 0x64, 0x6E, 0x3A, 0x09, 0x00, 0x84, 0x7F, 0x40, 0x45, 0x0B, 0x64, + 0x05, 0x00, 0x29, 0x44, 0x7F, 0x60, 0xFF, 0xB4, 0x40, 0x49, 0x70, 0x64, 0x40, 0x4D, 0x02, 0x00, + 0x40, 0x45, 0x0A, 0x00, 0x25, 0x60, 0x7A, 0x63, 0x0A, 0x36, 0x06, 0x00, 0x14, 0x36, 0x02, 0xA3, + 0x37, 0x36, 0x04, 0xA3, 0x6E, 0x36, 0x06, 0xA3, 0x28, 0xA3, 0xA3, 0xD1, 0xD8, 0xA3, 0x15, 0x60, + 0xD8, 0xF9, 0x39, 0xF1, 0xA3, 0xD1, 0x64, 0x41, 0x64, 0x5E, 0x60, 0x45, 0x64, 0x47, 0x1F, 0xB4, + 0x54, 0x94, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, + 0xB4, 0x85, 0x29, 0x44, 0xC0, 0x60, 0x00, 0xB4, 0xB4, 0x84, 0x1F, 0xFA, 0xB5, 0xFF, 0xA1, 0xFF, + 0xAD, 0xF3, 0xC4, 0xE2, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0xDC, 0x84, 0xE0, 0x94, 0xFF, 0x60, + 0xCF, 0x65, 0x29, 0x44, 0x24, 0x89, 0xA5, 0x60, 0xD6, 0x78, 0x04, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, + 0xC4, 0xE2, 0xA1, 0xFF, 0xFF, 0x60, 0xCF, 0x65, 0x29, 0x44, 0x24, 0x89, 0xAD, 0xF3, 0xC4, 0xE2, + 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0xDC, 0x84, 0xE0, 0x94, 0x26, 0x44, 0x84, 0xBC, 0x24, 0x40, + 0x0C, 0x22, 0xFD, 0xB4, 0x40, 0x46, 0x23, 0x64, 0x3A, 0xDB, 0xAC, 0x60, 0xAB, 0x78, 0xFF, 0xFF, + 0x27, 0x40, 0x26, 0x22, 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, + 0x29, 0x40, 0x10, 0x26, 0x02, 0x00, 0x04, 0x74, 0xCD, 0xE2, 0x01, 0x60, 0x18, 0xE1, 0x01, 0x60, + 0x18, 0xE1, 0x01, 0x11, 0x0F, 0x00, 0x29, 0x44, 0x20, 0xBC, 0x40, 0x49, 0x01, 0x64, 0x33, 0xFB, + 0xB6, 0xFF, 0x00, 0xE1, 0x01, 0x60, 0x1A, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x40, 0xFC, 0x11, + 0x01, 0x60, 0x18, 0xE1, 0xB5, 0xFF, 0x47, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, + 0x09, 0x7D, 0x7C, 0x4B, 0x37, 0xF3, 0x2B, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x02, 0x28, 0x65, 0x44, + 0x60, 0x50, 0xA0, 0x4C, 0x20, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0x00, 0x60, 0x2E, 0x7C, 0x74, 0x44, + 0xC0, 0x94, 0x32, 0x40, 0x02, 0x2A, 0x19, 0x00, 0x28, 0x44, 0xA4, 0x36, 0x03, 0x00, 0x0C, 0xB4, + 0x04, 0x36, 0x13, 0x00, 0x26, 0x43, 0xFD, 0xB3, 0x04, 0xBB, 0x43, 0x46, 0x01, 0x2A, 0x03, 0x00, + 0x28, 0x47, 0x40, 0xBF, 0x40, 0x48, 0x0A, 0xBB, 0x0F, 0xFC, 0x50, 0x4B, 0x67, 0x50, 0x00, 0x64, + 0x30, 0xFB, 0x05, 0xFF, 0xAC, 0x60, 0xAB, 0x78, 0xFF, 0xFF, 0x24, 0x64, 0x3A, 0xDB, 0x28, 0x44, + 0x04, 0x2A, 0x03, 0x00, 0xA4, 0x60, 0x6F, 0x78, 0xFF, 0xFF, 0x1D, 0xFF, 0xA8, 0xE2, 0x26, 0x40, + 0x10, 0x2A, 0x06, 0x00, 0x25, 0x60, 0xF0, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, + 0xA4, 0x60, 0x6F, 0x78, 0xFF, 0xFF, 0x03, 0x0A, 0xA4, 0x60, 0x7C, 0x78, 0xFF, 0xFF, 0x01, 0x64, + 0x4F, 0xFB, 0xE1, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x54, 0x62, 0x22, 0x46, 0xA2, 0xD0, + 0x16, 0x63, 0x7C, 0x41, 0x44, 0x48, 0x80, 0x36, 0x04, 0x61, 0x28, 0x40, 0x50, 0x36, 0x04, 0x61, + 0x41, 0x4E, 0x28, 0x44, 0xA4, 0x36, 0x0E, 0x63, 0x0A, 0x60, 0x7C, 0xF1, 0x2D, 0x44, 0xE8, 0x84, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, 0xA2, 0xDB, 0x9A, 0xFF, 0xA1, 0xFF, + 0x12, 0x74, 0xCD, 0xE2, 0x54, 0x62, 0xA2, 0xD2, 0xFF, 0xFF, 0x6A, 0x40, 0x80, 0x4E, 0x12, 0x74, + 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, + 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0xFF, 0xFF, 0x01, 0x1D, + 0xB2, 0x00, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, + 0x12, 0x74, 0x28, 0x40, 0x03, 0x2B, 0x06, 0x00, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, + 0x7A, 0xD4, 0x12, 0x74, 0x70, 0x62, 0x28, 0x44, 0x8F, 0xB0, 0x88, 0x3A, 0x02, 0x00, 0x7A, 0xD4, + 0x12, 0x74, 0x28, 0x40, 0x40, 0x2B, 0x16, 0x00, 0x72, 0x62, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD2, + 0x12, 0x74, 0x80, 0x4C, 0x20, 0x2B, 0x05, 0x00, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, + 0x12, 0x74, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x10, 0x26, 0x04, 0x00, 0x26, 0x26, 0x4D, 0x00, + 0x26, 0x27, 0x4B, 0x00, 0x23, 0x43, 0xFF, 0xFF, 0x06, 0x1D, 0x2E, 0x1E, 0x00, 0x00, 0x03, 0xF0, + 0x04, 0xF4, 0x64, 0x42, 0x3D, 0x00, 0x2E, 0x40, 0x04, 0x2A, 0x27, 0x00, 0xA1, 0xFF, 0x02, 0xFE, + 0x10, 0x25, 0x42, 0xFE, 0x12, 0x74, 0x72, 0x45, 0x65, 0x4C, 0x94, 0xF3, 0x03, 0x04, 0xE4, 0xE2, + 0xDC, 0x84, 0x94, 0xFB, 0xA1, 0xFF, 0x12, 0x74, 0x80, 0x4C, 0x12, 0x74, 0x95, 0xF3, 0x02, 0x04, + 0xDC, 0x84, 0x95, 0xFB, 0x80, 0x4C, 0x12, 0x74, 0x96, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x96, 0xFB, + 0x80, 0x4C, 0x12, 0x74, 0x5C, 0x4E, 0xF8, 0xA3, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, 0xFF, 0xB1, + 0xF8, 0xA1, 0x06, 0xA4, 0x60, 0x42, 0x0A, 0x00, 0x4E, 0x00, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, + 0xC8, 0x82, 0xFF, 0xB1, 0x03, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0xFF, 0xB1, 0x7A, 0xD4, 0x12, 0x74, + 0xFD, 0x1C, 0xF9, 0x1D, 0xFF, 0xB1, 0x1B, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0xDA, 0x82, 0xDA, 0x82, + 0xA2, 0xD2, 0xA1, 0xFF, 0x09, 0x74, 0x60, 0x4D, 0x12, 0x00, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, + 0x23, 0x43, 0xA1, 0xFF, 0x12, 0x74, 0xA0, 0xD2, 0xFE, 0xA1, 0xCB, 0x83, 0x60, 0x4E, 0xAF, 0x83, + 0x03, 0x1D, 0x05, 0x03, 0x12, 0x74, 0xEB, 0x01, 0xA1, 0xFF, 0x12, 0x74, 0xDF, 0x01, 0x12, 0x74, + 0xDA, 0x83, 0x66, 0x44, 0x22, 0x46, 0x0C, 0xFA, 0x22, 0xF2, 0x0B, 0xFC, 0x28, 0x40, 0x40, 0x2B, + 0x1A, 0x00, 0x10, 0x26, 0x04, 0x00, 0x26, 0x26, 0x0F, 0x00, 0x26, 0x27, 0x0D, 0x00, 0x00, 0xF4, + 0x02, 0x62, 0xA1, 0xFF, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, + 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x07, 0x00, 0xA1, 0xFF, 0x12, 0x74, 0x9C, 0x4E, 0x12, 0x74, + 0x9C, 0x4C, 0x12, 0x74, 0x00, 0x00, 0x88, 0xFF, 0xA1, 0xFF, 0xB1, 0x60, 0x58, 0x4F, 0x00, 0x78, + 0xFF, 0xFF, 0x01, 0x60, 0x18, 0xE1, 0x78, 0x44, 0x02, 0xA4, 0x35, 0xFB, 0xCC, 0x00, 0x29, 0x44, + 0xF7, 0xB4, 0x40, 0x49, 0x34, 0x64, 0x3A, 0xDB, 0x44, 0xE1, 0xA5, 0x60, 0xB2, 0x78, 0xFF, 0xFF, + 0x00, 0x6B, 0xBC, 0xFF, 0x15, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x15, 0xFB, 0x78, 0x5C, 0x07, 0x00, + 0x78, 0x5C, 0x2F, 0x00, 0x62, 0xFF, 0xFF, 0xFF, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x80, 0x60, + 0x01, 0xE0, 0xD5, 0x60, 0x84, 0xE7, 0x82, 0xF3, 0x40, 0x60, 0x60, 0x40, 0x01, 0x23, 0x48, 0x60, + 0x5E, 0x65, 0x80, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, + 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x80, 0x60, + 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, + 0x00, 0x60, 0x01, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x64, 0x58, + 0xFF, 0xFF, 0x80, 0x60, 0x01, 0xE0, 0xD5, 0x60, 0x84, 0xE7, 0x82, 0xF3, 0x7C, 0x45, 0x60, 0x40, + 0x01, 0x23, 0x02, 0x65, 0x8C, 0x60, 0x48, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, + 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x7F, 0x6A, 0xFF, 0xFF, 0x01, 0x16, + 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x48, 0x60, 0x08, 0x6A, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x84, 0x60, + 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x40, 0x60, 0x08, 0x6A, 0xFF, 0xFF, 0x01, 0x16, + 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x8C, 0x60, 0x48, 0x6A, 0xFF, 0xFF, + 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, + 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x64, 0x58, 0xFF, 0xFF, + 0x12, 0x74, 0x6A, 0x40, 0x87, 0x4F, 0x12, 0x74, 0x87, 0x4C, 0x12, 0x74, 0x29, 0x40, 0x40, 0x2B, + 0x08, 0x00, 0x0A, 0x64, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0x87, 0x4D, 0x12, 0x74, 0x87, 0x4D, + 0x09, 0x00, 0x03, 0x64, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0x87, 0x4F, 0x12, 0x74, 0x87, 0x4D, + 0x12, 0x74, 0x87, 0x4D, 0x7C, 0x44, 0x01, 0x08, 0x01, 0x00, 0x67, 0x44, 0x12, 0x74, 0x87, 0x4C, + 0x12, 0x74, 0x87, 0x4C, 0x12, 0x74, 0x87, 0x4C, 0x12, 0x74, 0x87, 0x4D, 0x12, 0x74, 0x87, 0x4D, + 0x12, 0x74, 0x87, 0x4D, 0x12, 0x74, 0x04, 0x21, 0x04, 0x00, 0xFF, 0x2A, 0x01, 0x00, 0x04, 0x00, + 0x03, 0x00, 0xFF, 0x2A, 0x0D, 0x00, 0x0C, 0x00, 0xBC, 0xFF, 0x61, 0xFF, 0x78, 0x5C, 0x57, 0x01, + 0x78, 0x5C, 0x7F, 0x01, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, + 0x6A, 0x44, 0x2F, 0x58, 0xFF, 0xFF, 0x04, 0x74, 0xC4, 0xE2, 0x04, 0xE1, 0x29, 0x40, 0x40, 0x2B, + 0x05, 0x00, 0xA1, 0xFF, 0xFF, 0xFF, 0xBC, 0xFF, 0x14, 0x74, 0x01, 0x00, 0x04, 0x74, 0xC4, 0xE2, + 0x04, 0xE1, 0xBC, 0xFF, 0xB5, 0xFF, 0x47, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, + 0x09, 0x7D, 0x7C, 0x4B, 0x29, 0x40, 0x40, 0x27, 0x04, 0x00, 0xC2, 0x60, 0x58, 0x4F, 0xC8, 0x78, + 0xFF, 0xFF, 0xA1, 0xFF, 0x29, 0x40, 0x10, 0x26, 0x6D, 0x00, 0x80, 0x60, 0x01, 0xE0, 0xD5, 0x60, + 0x84, 0xE7, 0x82, 0xF3, 0x40, 0x60, 0x60, 0x40, 0x01, 0x23, 0x48, 0x60, 0x5E, 0x65, 0x80, 0x60, + 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, + 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x80, 0x60, 0x00, 0x6A, 0xFF, 0xFF, + 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x01, 0x6A, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x80, 0x60, 0x01, 0xE0, 0xD5, 0x60, + 0x84, 0xE7, 0x82, 0xF3, 0x7C, 0x45, 0x60, 0x40, 0x01, 0x23, 0x02, 0x65, 0x8C, 0x60, 0x48, 0x6A, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, + 0x00, 0x60, 0x7F, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, + 0x01, 0x16, 0xFE, 0x01, 0x48, 0x60, 0x08, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, + 0x40, 0x60, 0x08, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, + 0xFE, 0x01, 0x8C, 0x60, 0x48, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, + 0x95, 0x60, 0x84, 0xE7, 0x01, 0x60, 0x08, 0xE1, 0xFF, 0xFF, 0xC4, 0xE2, 0x29, 0x40, 0x40, 0x2B, + 0x04, 0x00, 0xC2, 0x60, 0x58, 0x4F, 0xC8, 0x78, 0xFF, 0xFF, 0xC2, 0x60, 0x58, 0x4F, 0xD0, 0x78, + 0xFF, 0xFF, 0xA1, 0xFF, 0xAD, 0xF3, 0xC4, 0xE2, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0xDC, 0x84, + 0xE0, 0x94, 0x35, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x08, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, + 0x43, 0xFF, 0x01, 0x60, 0x00, 0xE1, 0x28, 0xF3, 0x47, 0xFF, 0x60, 0x40, 0x07, 0x37, 0x66, 0x00, + 0x05, 0x3B, 0x04, 0x00, 0xFF, 0x0A, 0x80, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x18, 0x60, 0x07, 0xF1, + 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x64, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, + 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x29, 0xF5, 0x2A, 0xF3, 0x47, 0xFF, + 0x3F, 0xF0, 0x01, 0x1B, 0x01, 0x64, 0x60, 0x56, 0xAD, 0xE2, 0xB5, 0xFF, 0x6C, 0x40, 0x40, 0xE1, + 0xA1, 0xFF, 0x00, 0xF4, 0x6E, 0x61, 0x12, 0x62, 0x64, 0x43, 0x01, 0xE1, 0x03, 0x64, 0xE2, 0xD0, + 0xC9, 0x81, 0x64, 0x4C, 0xCC, 0x84, 0xDA, 0x82, 0xFA, 0x02, 0x01, 0x60, 0x00, 0x6B, 0x9A, 0xFF, + 0xCA, 0x82, 0x03, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0xFF, 0xFF, 0x7A, 0xD0, 0xA1, 0xFF, 0x64, 0x4C, + 0xFC, 0x1C, 0xF8, 0x1D, 0x00, 0xB9, 0x06, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0xDA, 0x82, 0x5A, 0xD2, + 0xA1, 0xFF, 0x60, 0x4D, 0x3F, 0x40, 0x02, 0x2B, 0x10, 0x00, 0x28, 0xF3, 0xA5, 0x60, 0xC4, 0x65, + 0x60, 0x40, 0x0E, 0x3B, 0x0A, 0x00, 0xD2, 0xF3, 0xFF, 0xFF, 0x10, 0xBC, 0xD2, 0xFB, 0xAD, 0x4F, + 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0x85, 0x4C, 0xFE, 0x01, 0xD2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, + 0xD2, 0xFB, 0xA1, 0xFF, 0x87, 0x4E, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x67, 0x4C, + 0xFF, 0xFF, 0xBC, 0xFF, 0x00, 0xE1, 0xD5, 0xFE, 0xA1, 0xFF, 0xFF, 0xFF, 0x00, 0x64, 0x40, 0x46, + 0x60, 0x41, 0xB5, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0x29, 0xF5, 0x3F, 0xF0, 0x24, 0xF2, 0x44, 0x43, + 0x40, 0x4D, 0x00, 0xF4, 0xF3, 0x60, 0xA0, 0x65, 0x10, 0x62, 0x5A, 0xD2, 0xD9, 0x81, 0xD4, 0x80, + 0xFF, 0xFF, 0xFB, 0x02, 0x61, 0x45, 0x2D, 0x44, 0xD4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, + 0xFD, 0xA5, 0x48, 0x60, 0x00, 0x64, 0xC4, 0x9D, 0x0D, 0x60, 0x00, 0x6B, 0x2D, 0x44, 0xC0, 0x83, + 0xBB, 0xFF, 0x29, 0xF5, 0x01, 0xE1, 0x00, 0xF4, 0x6C, 0x61, 0x10, 0x62, 0x05, 0x00, 0x00, 0xF4, + 0x01, 0xF2, 0xFF, 0xFF, 0x60, 0x41, 0x04, 0x62, 0xA1, 0xFF, 0xFF, 0xFF, 0x01, 0x10, 0x1A, 0x00, + 0x26, 0x44, 0x01, 0x26, 0x0C, 0x00, 0x2D, 0x44, 0xC8, 0x84, 0x40, 0x4D, 0x02, 0x03, 0x6C, 0x45, + 0xF3, 0x01, 0x03, 0x15, 0x01, 0x64, 0x05, 0xFA, 0x15, 0x00, 0x6C, 0x45, 0xED, 0x01, 0x23, 0x44, + 0xC8, 0x84, 0x40, 0x43, 0x02, 0x03, 0x6C, 0x45, 0xE7, 0x01, 0x00, 0x64, 0x01, 0x15, 0x01, 0x64, + 0x6C, 0x45, 0x05, 0xFB, 0xE2, 0xD2, 0xDA, 0x82, 0xC9, 0x81, 0x60, 0x4C, 0xDD, 0x1C, 0xD7, 0x03, + 0xBC, 0xFF, 0xDA, 0x01, 0x00, 0xE1, 0xD5, 0xFE, 0xA1, 0xFF, 0xFF, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, + 0x67, 0x4C, 0x43, 0xFF, 0xD2, 0xF3, 0xFF, 0xFF, 0x10, 0xBC, 0xD2, 0xFB, 0xAD, 0x4F, 0x02, 0xBC, + 0x00, 0x7F, 0xA0, 0x5D, 0x01, 0xE1, 0x01, 0x60, 0x69, 0x6B, 0xA5, 0x60, 0xC4, 0x64, 0x60, 0x4C, + 0xBB, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x60, 0x4C, 0xA1, 0xFF, 0xFF, 0xFF, 0x60, 0x4C, 0xFC, 0x01, + 0x29, 0xF3, 0x2A, 0xF1, 0x07, 0xB5, 0x04, 0xE1, 0x65, 0x41, 0x64, 0x54, 0xCD, 0xE2, 0x95, 0x81, + 0xA1, 0x5D, 0xA1, 0xFF, 0xFF, 0xFF, 0xF9, 0x01, 0x10, 0x61, 0x7F, 0x60, 0xC0, 0x64, 0xA0, 0x80, + 0x7F, 0x67, 0x02, 0x63, 0x25, 0x02, 0x98, 0xFE, 0x19, 0x05, 0x0F, 0x60, 0x7F, 0xF5, 0x0E, 0xF2, + 0x15, 0x18, 0x02, 0x18, 0x09, 0xF4, 0xFB, 0x01, 0x23, 0x44, 0x00, 0xA8, 0x08, 0x7E, 0x0A, 0x02, + 0x66, 0x44, 0x11, 0xFB, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, + 0x28, 0xB9, 0x10, 0x7E, 0x00, 0x7F, 0x0E, 0xFA, 0x00, 0x67, 0x0A, 0x00, 0x20, 0x44, 0xDC, 0x85, + 0x0F, 0xB4, 0xF7, 0xA0, 0x7F, 0x67, 0x07, 0x63, 0x03, 0x05, 0x45, 0x40, 0x00, 0x67, 0xD8, 0xFE, + 0xFF, 0x27, 0x05, 0xFD, 0x0A, 0x7E, 0x04, 0xFB, 0x61, 0x55, 0x48, 0x00, 0x28, 0xFB, 0x01, 0xF3, + 0x29, 0xFB, 0x44, 0x46, 0x40, 0x45, 0x10, 0x61, 0x7E, 0x60, 0xC0, 0x64, 0xA0, 0x80, 0x7F, 0x67, + 0x02, 0x63, 0x30, 0x02, 0xB5, 0x60, 0x58, 0x4F, 0x4B, 0x78, 0xFF, 0xFF, 0x7F, 0x67, 0x03, 0x63, + 0x29, 0x02, 0x26, 0x40, 0x01, 0x2B, 0x23, 0x00, 0x98, 0xFE, 0x18, 0x05, 0x0F, 0x60, 0x7F, 0xF5, + 0x0E, 0xF2, 0x14, 0x18, 0x02, 0x18, 0x09, 0xF4, 0xFB, 0x01, 0x23, 0x44, 0x00, 0xA8, 0x08, 0x7E, + 0x0A, 0x02, 0x66, 0x44, 0x11, 0xFB, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, + 0xA2, 0xDB, 0x08, 0xB9, 0x10, 0x7E, 0x00, 0x7F, 0x0E, 0xFA, 0x09, 0x00, 0x20, 0x44, 0xDC, 0x85, + 0x0F, 0xB4, 0xF7, 0xA0, 0x7F, 0x67, 0x07, 0x63, 0x05, 0x05, 0x45, 0x40, 0xD8, 0xFE, 0x00, 0x67, + 0xD0, 0xFE, 0xD9, 0xFE, 0xFF, 0x27, 0x05, 0xFD, 0x0B, 0x7E, 0x04, 0xFB, 0x0A, 0x60, 0x7E, 0xF3, + 0xFF, 0xFF, 0x20, 0xB0, 0x80, 0xBC, 0x08, 0x28, 0xA2, 0xDB, 0x61, 0x55, 0x66, 0x00, 0x04, 0xB5, + 0x82, 0xB5, 0x25, 0x02, 0x04, 0x03, 0x20, 0x44, 0x7F, 0xB4, 0x40, 0x40, 0xA3, 0xD3, 0x99, 0xFE, + 0x04, 0x04, 0x02, 0xBC, 0xFE, 0xB4, 0xA3, 0xDB, 0x59, 0x00, 0xBC, 0xF3, 0x20, 0x40, 0x80, 0x26, + 0x55, 0x00, 0xA3, 0xD3, 0xFF, 0xA0, 0xF8, 0xB4, 0x02, 0x02, 0xA3, 0xDB, 0x1C, 0x00, 0x04, 0xBC, + 0xBF, 0xB4, 0xA3, 0xDB, 0x08, 0xB0, 0x01, 0x64, 0x08, 0x24, 0x02, 0x64, 0x28, 0xFB, 0x20, 0x44, + 0x80, 0xBC, 0x40, 0x40, 0xD0, 0xFE, 0x42, 0x00, 0xBF, 0xB4, 0xA3, 0xDB, 0x3F, 0x00, 0x40, 0xB0, + 0xFF, 0xFF, 0xFA, 0x02, 0xF8, 0xB4, 0xA3, 0xDB, 0x08, 0xB5, 0x07, 0x7C, 0x01, 0x02, 0xBC, 0xF9, + 0x20, 0x44, 0x7F, 0xB4, 0x40, 0x40, 0x14, 0x60, 0xFC, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB5, + 0x07, 0xB5, 0x08, 0x28, 0xC4, 0x02, 0x99, 0xFE, 0x29, 0x05, 0x20, 0x44, 0x80, 0x26, 0x26, 0x00, + 0x20, 0x2A, 0x03, 0x00, 0xDF, 0xB4, 0x40, 0x40, 0x6A, 0x00, 0x40, 0x2A, 0x1F, 0x00, 0xBF, 0xB4, + 0x40, 0x40, 0x09, 0x00, 0xA8, 0xFF, 0x20, 0x44, 0x99, 0xFE, 0x02, 0x05, 0x80, 0x2A, 0x03, 0x00, + 0x40, 0xBC, 0x40, 0x40, 0x13, 0x00, 0x00, 0xF1, 0x80, 0xBC, 0x40, 0x40, 0x64, 0x44, 0xE0, 0x84, + 0xE8, 0x84, 0x0A, 0x36, 0x29, 0x01, 0x0B, 0x36, 0x59, 0x01, 0x28, 0xFB, 0x01, 0xF1, 0x29, 0xF9, + 0x02, 0xF1, 0x2A, 0xF9, 0x03, 0xF1, 0x2B, 0xF9, 0xD0, 0xFE, 0xAE, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, + 0x82, 0x3E, 0x75, 0x44, 0x02, 0xB0, 0x01, 0xB0, 0x4A, 0x02, 0xDC, 0x02, 0x04, 0xB0, 0x08, 0xB0, + 0x0B, 0x02, 0x20, 0x02, 0x40, 0x26, 0xA7, 0xFF, 0x8C, 0xFF, 0x75, 0x40, 0x80, 0x2B, 0x01, 0x00, + 0xAB, 0xFF, 0x75, 0x44, 0x8D, 0xFF, 0xEA, 0x01, 0x0A, 0xF3, 0xAA, 0xFF, 0x60, 0x40, 0x20, 0x2B, + 0x02, 0x00, 0x38, 0xFF, 0x0D, 0x00, 0x01, 0x26, 0x0C, 0x00, 0xC0, 0x60, 0x00, 0x7C, 0xA0, 0x84, + 0x80, 0x3B, 0x02, 0x00, 0xC0, 0x67, 0x03, 0x00, 0x40, 0x3B, 0x02, 0x00, 0x00, 0x67, 0x0A, 0xFB, + 0xD5, 0x01, 0xD4, 0x01, 0x0B, 0xF1, 0xAB, 0xFF, 0x64, 0x44, 0xFF, 0x27, 0x1F, 0x00, 0x20, 0x26, + 0x03, 0x00, 0x02, 0x60, 0x00, 0x75, 0x1A, 0x00, 0x19, 0xF3, 0xFF, 0xFF, 0x03, 0x1B, 0x04, 0x60, + 0x00, 0x75, 0x0A, 0x64, 0xCC, 0x84, 0x19, 0xFB, 0x01, 0x60, 0x00, 0x75, 0x64, 0x40, 0x03, 0x22, + 0x0D, 0x00, 0x20, 0x44, 0x80, 0x2A, 0x03, 0x00, 0x20, 0xBC, 0x40, 0x40, 0x07, 0x00, 0xD9, 0xFE, + 0x81, 0x60, 0x0B, 0x64, 0x28, 0xFB, 0x2C, 0x44, 0x29, 0xFB, 0xD0, 0xFE, 0xAF, 0x01, 0xA9, 0xFF, + 0x77, 0x44, 0x60, 0x57, 0x40, 0x4A, 0x01, 0x2A, 0x20, 0x00, 0x24, 0x44, 0xAC, 0x86, 0x08, 0xF2, + 0x1C, 0x03, 0x1F, 0x60, 0x04, 0x65, 0xD4, 0x80, 0x0E, 0xF2, 0x02, 0x03, 0xA5, 0xD5, 0x04, 0x00, + 0x01, 0xBC, 0x0E, 0xFA, 0x09, 0xF4, 0xD1, 0xFE, 0x46, 0x44, 0x0F, 0x18, 0x3F, 0xF2, 0x48, 0x65, + 0xC4, 0x84, 0x13, 0xFB, 0x66, 0x44, 0x10, 0xFB, 0x66, 0x47, 0x20, 0xBF, 0x3B, 0x42, 0x04, 0xA2, + 0xA2, 0xDB, 0x0E, 0xF2, 0x41, 0x75, 0x10, 0xBC, 0x0E, 0xFA, 0x2A, 0x44, 0x08, 0x2A, 0x17, 0x00, + 0x23, 0x44, 0x00, 0xA8, 0x5C, 0x43, 0x13, 0x03, 0x0F, 0x60, 0x7F, 0xF5, 0x01, 0x00, 0x09, 0xF4, + 0x0E, 0xF2, 0x0D, 0x18, 0x08, 0xB0, 0x18, 0xAC, 0xFA, 0x03, 0x0E, 0xFA, 0x66, 0x43, 0x11, 0xFD, + 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x28, 0x75, 0x2A, 0x44, + 0x06, 0x22, 0x2D, 0x00, 0x22, 0x44, 0x00, 0xA8, 0x60, 0x46, 0x0E, 0xF2, 0x28, 0x03, 0x10, 0xB0, + 0x01, 0xBC, 0x03, 0x02, 0x00, 0x64, 0x40, 0x42, 0x22, 0x00, 0x0E, 0xFA, 0xD1, 0xFE, 0x1E, 0x60, + 0xF8, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x80, 0x00, 0x46, 0x42, 0x19, 0x02, 0x22, 0x47, 0x40, 0xBF, + 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x23, 0xF2, 0x66, 0x43, 0x00, 0xA8, 0x0E, 0xF2, 0x08, 0x02, + 0x60, 0x40, 0x02, 0x2A, 0xE4, 0x01, 0x12, 0xFD, 0x10, 0x64, 0x0E, 0xFA, 0x02, 0x75, 0x07, 0x00, + 0x60, 0x40, 0x04, 0x2A, 0xDC, 0x01, 0x12, 0xFD, 0x10, 0x64, 0x0E, 0xFA, 0x04, 0x75, 0x2A, 0x44, + 0x80, 0x2A, 0x19, 0x00, 0x21, 0x44, 0xAC, 0x86, 0x0E, 0xF2, 0x15, 0x03, 0x01, 0xBC, 0x0E, 0xFA, + 0xD1, 0xFE, 0x1F, 0x60, 0x10, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x56, 0x00, 0x46, 0x41, 0x0B, 0x02, + 0x21, 0x47, 0x10, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x0E, 0xF2, 0x66, 0x43, 0x08, 0xFD, + 0x10, 0xBC, 0x0E, 0xFA, 0x80, 0x75, 0x2A, 0x44, 0x10, 0xB0, 0x20, 0x44, 0x15, 0x03, 0x7F, 0xB4, + 0x40, 0x40, 0x14, 0x60, 0xFC, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB0, 0x80, 0xB0, 0x09, 0x03, + 0x08, 0x03, 0x40, 0xBC, 0x7F, 0xB4, 0x04, 0xB0, 0xA3, 0xDB, 0x03, 0x03, 0x20, 0x44, 0x80, 0xBC, + 0x40, 0x40, 0xB3, 0x60, 0x8B, 0x78, 0xFF, 0xFF, 0xB3, 0x60, 0xBE, 0x78, 0xFF, 0xFF, 0xE8, 0xFE, + 0x14, 0x05, 0xEA, 0xFE, 0x24, 0x05, 0xE9, 0xFE, 0x1C, 0x05, 0xE7, 0xFE, 0x09, 0x05, 0x47, 0xFF, + 0x20, 0x44, 0x0F, 0x22, 0x03, 0x00, 0xCC, 0x84, 0x40, 0x40, 0x0F, 0x22, 0xB8, 0xFE, 0xEC, 0x01, + 0x23, 0x41, 0x00, 0xB9, 0x5C, 0x4A, 0xE8, 0x02, 0x6F, 0x01, 0x24, 0x41, 0x00, 0xB9, 0x1F, 0x60, + 0x04, 0x65, 0x45, 0x47, 0xE1, 0x02, 0x58, 0x4F, 0x0F, 0x00, 0xDE, 0x02, 0x5C, 0x4A, 0x46, 0x44, + 0x4D, 0x01, 0x22, 0x41, 0x00, 0xB9, 0x5C, 0x4A, 0x08, 0x24, 0x81, 0x01, 0xD5, 0x01, 0x21, 0x41, + 0x00, 0xB9, 0x5C, 0x4A, 0xA6, 0x03, 0xD0, 0x01, 0x27, 0xD3, 0x03, 0x00, 0x10, 0xB0, 0x09, 0xF2, + 0x04, 0x03, 0xAC, 0x86, 0x0E, 0xF2, 0xFA, 0x02, 0x08, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0E, 0xF3, + 0x0F, 0x60, 0xFE, 0x65, 0x0C, 0xF3, 0x24, 0x86, 0x24, 0x46, 0x60, 0x40, 0xFB, 0x3B, 0x07, 0x00, + 0x80, 0x26, 0x02, 0x00, 0x23, 0x46, 0x03, 0x4C, 0x46, 0x61, 0x3A, 0x65, 0x0C, 0x00, 0x2E, 0xF3, + 0x40, 0x45, 0xF8, 0x2B, 0x02, 0x00, 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, 0x44, 0x00, 0x07, 0x02, + 0x58, 0x4F, 0x50, 0x00, 0x04, 0x05, 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, 0x09, 0x00, 0x26, 0x47, + 0x00, 0xBF, 0x0E, 0xFB, 0x2E, 0xF5, 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, 0x00, 0x72, 0x7E, 0x71, + 0xAC, 0xFF, 0xB3, 0x60, 0xBE, 0x78, 0xFF, 0xFF, 0x8E, 0xFF, 0x0F, 0xF3, 0x0F, 0x60, 0xFE, 0x65, + 0x24, 0x86, 0x0D, 0xF3, 0x24, 0x46, 0x60, 0x40, 0xFB, 0x3B, 0x07, 0x00, 0x80, 0x26, 0x02, 0x00, + 0x23, 0x46, 0x03, 0x4C, 0x46, 0x61, 0x3A, 0x65, 0x0C, 0x00, 0x2E, 0xF3, 0x40, 0x45, 0xF8, 0x2B, + 0x02, 0x00, 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, 0x16, 0x00, 0x07, 0x02, 0x58, 0x4F, 0x22, 0x00, + 0x04, 0x05, 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, 0x09, 0x00, 0x26, 0x47, 0x00, 0xBF, 0x0F, 0xFB, + 0x2E, 0xF5, 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, 0x00, 0x72, 0x7E, 0x71, 0x8D, 0xFF, 0xAD, 0xFF, + 0xB3, 0x60, 0xBE, 0x78, 0xFF, 0xFF, 0x25, 0x44, 0x89, 0xF1, 0x8A, 0xF1, 0xD0, 0x80, 0xD0, 0x80, + 0x07, 0x04, 0x01, 0x06, 0x05, 0x00, 0x25, 0x46, 0x01, 0xF0, 0x03, 0x67, 0xA0, 0x85, 0x94, 0x80, + 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x46, 0x26, 0x41, 0x46, 0x63, 0x01, 0xF2, 0xFF, 0xFF, 0xFF, 0xB5, + 0xD5, 0x81, 0x00, 0xF2, 0x05, 0x04, 0x04, 0x63, 0x60, 0x46, 0xF7, 0x1B, 0x42, 0xFE, 0x0D, 0x00, + 0x61, 0x44, 0xC5, 0x81, 0x63, 0x45, 0xC5, 0x81, 0x9C, 0x84, 0xDC, 0x84, 0x01, 0xF2, 0xF0, 0x85, + 0xF0, 0x80, 0x65, 0x44, 0xF8, 0x85, 0xFF, 0xFF, 0x02, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, + 0x0F, 0x60, 0x8B, 0xF3, 0xFF, 0xFF, 0xAC, 0x86, 0x0E, 0xF2, 0x07, 0x03, 0x00, 0xA8, 0x09, 0xF2, + 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, 0x08, 0xFE, 0x17, 0x00, 0x8B, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, + 0x00, 0xB4, 0x12, 0x06, 0x09, 0x60, 0x08, 0x61, 0x41, 0x4A, 0x7C, 0xA1, 0x0E, 0xA1, 0xA2, 0xFF, + 0xB5, 0x60, 0x58, 0x4E, 0xC1, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x06, 0x03, 0x2A, 0x43, 0xB5, 0x60, + 0x58, 0x4E, 0xE2, 0x78, 0xFF, 0xFF, 0x08, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0x41, 0x4A, + 0x42, 0xA1, 0x03, 0x00, 0x41, 0x4A, 0x7C, 0xA1, 0x0E, 0xA1, 0xA2, 0xFF, 0xB5, 0x60, 0x58, 0x4E, + 0xC1, 0x78, 0xFF, 0xFF, 0x07, 0x03, 0x2A, 0x43, 0xB5, 0x60, 0x58, 0x4E, 0xE2, 0x78, 0xFF, 0xFF, + 0x08, 0xFE, 0x0C, 0x00, 0x0F, 0x60, 0x8B, 0xF3, 0xFF, 0xFF, 0xAC, 0x86, 0x0E, 0xF2, 0x06, 0x03, + 0x00, 0xA8, 0x09, 0xF2, 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, 0x08, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, + 0xFF, 0xFF, 0x8C, 0xF3, 0x7C, 0x63, 0x00, 0xBE, 0x40, 0x45, 0x1A, 0x03, 0x00, 0x65, 0x65, 0x44, + 0xDC, 0x85, 0x84, 0xA1, 0x00, 0xF2, 0x06, 0x06, 0x01, 0xFC, 0x00, 0xA8, 0x60, 0x46, 0xF7, 0x02, + 0x40, 0x45, 0x0E, 0x00, 0x8B, 0xF3, 0x00, 0x63, 0xD4, 0x84, 0x8B, 0xFB, 0x80, 0x60, 0x7C, 0x64, + 0x01, 0xFA, 0x00, 0xF0, 0x00, 0xFC, 0xD3, 0x80, 0x8C, 0xF9, 0x02, 0x02, 0x8D, 0xF9, 0x08, 0xFE, + 0x2E, 0x58, 0xFF, 0xFF, 0x66, 0x44, 0x25, 0x46, 0x05, 0xFA, 0x06, 0xFA, 0x01, 0xF0, 0x03, 0x67, + 0x02, 0xFC, 0xB0, 0x84, 0x3A, 0x7E, 0x01, 0xFA, 0x12, 0x64, 0x03, 0xFA, 0x00, 0xF0, 0x04, 0xF8, + 0x00, 0x64, 0x0C, 0x61, 0x10, 0x63, 0x59, 0xDA, 0xFE, 0x1F, 0x2E, 0x58, 0xFF, 0xFF, 0x27, 0x43, + 0xE3, 0x81, 0xE9, 0x81, 0x03, 0x05, 0x16, 0x03, 0x00, 0x61, 0x01, 0x00, 0xEC, 0x63, 0x61, 0x46, + 0xBF, 0xD2, 0x27, 0x45, 0xDC, 0x84, 0xA2, 0xDA, 0xBE, 0xD2, 0x25, 0x46, 0x88, 0xF8, 0x04, 0x1B, + 0x25, 0x44, 0x61, 0x46, 0xA3, 0xDA, 0x04, 0x00, 0x0A, 0xFA, 0x60, 0x46, 0x25, 0x44, 0x09, 0xFA, + 0x61, 0x46, 0xBE, 0xDA, 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x44, 0x00, 0xA8, 0x07, 0x4B, 0x0C, 0x03, + 0x58, 0x4F, 0x33, 0x00, 0x0B, 0x47, 0x1F, 0x60, 0x0A, 0x65, 0x27, 0x44, 0xD4, 0x80, 0x00, 0x64, + 0x01, 0x02, 0x0F, 0xFA, 0x58, 0x4F, 0xD3, 0x01, 0x70, 0x00, 0x25, 0x43, 0xE3, 0x84, 0x7C, 0x41, + 0x02, 0x04, 0xE8, 0x81, 0xEC, 0x63, 0x61, 0x46, 0xA3, 0xD2, 0x00, 0x7C, 0x40, 0x45, 0xBF, 0xD8, + 0xA3, 0xD8, 0xBE, 0xD8, 0x27, 0x42, 0x5A, 0xD3, 0x25, 0x5C, 0x60, 0x41, 0x02, 0x1B, 0x27, 0xD9, + 0x05, 0x00, 0x25, 0x46, 0x0A, 0xFA, 0x61, 0x46, 0x25, 0x44, 0x09, 0xFA, 0x25, 0x44, 0x27, 0x43, + 0x00, 0x61, 0x60, 0x46, 0x09, 0xF2, 0x08, 0xFC, 0x00, 0xA8, 0xDD, 0x81, 0xFA, 0x02, 0xBF, 0xD1, + 0x66, 0x44, 0xBE, 0xDB, 0xC1, 0x84, 0xBF, 0xDB, 0x48, 0x00, 0x25, 0x46, 0xEC, 0x63, 0x08, 0xF2, + 0x89, 0xF2, 0x1E, 0x18, 0x40, 0x47, 0xE0, 0x84, 0xE8, 0x85, 0x02, 0x05, 0xE8, 0x83, 0x00, 0x65, + 0x65, 0x46, 0xBF, 0xD2, 0x61, 0x5C, 0xCC, 0x84, 0xA2, 0xDA, 0x25, 0x46, 0x0A, 0xF2, 0x00, 0xB9, + 0x65, 0x46, 0x08, 0x24, 0xBE, 0xDA, 0x02, 0x1B, 0xA3, 0xD8, 0x02, 0x00, 0x60, 0x46, 0x89, 0xFA, + 0x00, 0xB9, 0x61, 0x46, 0x08, 0x28, 0x0A, 0xFA, 0x25, 0x46, 0x89, 0xFC, 0x8A, 0xFC, 0x88, 0xFC, + 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x61, 0x28, 0x65, 0x25, 0x43, 0x8D, 0xF3, 0xAF, 0x83, 0x00, 0xBE, + 0x18, 0x03, 0x02, 0x03, 0x00, 0xFC, 0x01, 0x00, 0x8C, 0xFD, 0x63, 0x46, 0x65, 0x44, 0xCC, 0x85, + 0x00, 0xF2, 0x07, 0x02, 0x8D, 0xF5, 0x00, 0x64, 0x00, 0xFA, 0xDE, 0x60, 0xAF, 0x64, 0x09, 0xFB, + 0x08, 0x00, 0x66, 0x43, 0x00, 0xBE, 0xDD, 0x81, 0xF1, 0x02, 0x8B, 0xF1, 0x8D, 0xFD, 0xC1, 0x84, + 0x8B, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x45, 0x29, 0x43, 0xFC, 0xA3, 0x66, 0x44, + 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x00, 0x64, 0xBD, 0xDB, 0x03, 0x61, 0x0E, 0x65, 0x1F, 0x60, + 0x1E, 0x63, 0x43, 0x49, 0xA3, 0xD3, 0x06, 0xA3, 0x00, 0xA8, 0xCD, 0x81, 0x04, 0x02, 0xF9, 0x02, + 0xB3, 0x60, 0xBE, 0x78, 0xFF, 0xFF, 0x01, 0x26, 0xE6, 0x01, 0xD4, 0x80, 0x60, 0x45, 0xE3, 0x05, + 0xF6, 0xA3, 0xBD, 0xD1, 0xBD, 0xD1, 0x44, 0x47, 0x44, 0x48, 0x44, 0x45, 0x1F, 0x60, 0x60, 0x64, + 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, 0xFE, 0x8C, 0xF5, 0x8B, 0xF3, 0x0D, 0x18, 0xCC, 0x84, + 0x8B, 0xFB, 0x80, 0x60, 0x7C, 0x64, 0x01, 0xFA, 0x00, 0x64, 0x00, 0xF0, 0x00, 0xFA, 0xD0, 0x80, + 0x8C, 0xF9, 0x02, 0x02, 0x8D, 0xF9, 0x08, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x1E, 0x60, 0xCE, 0x63, + 0x0D, 0x65, 0x00, 0x61, 0x41, 0x48, 0xA3, 0xD3, 0x06, 0xA3, 0xAC, 0x86, 0x00, 0x61, 0x09, 0x03, + 0x00, 0xF2, 0x09, 0xF0, 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x64, 0x44, 0xAC, 0x86, + 0xF6, 0x01, 0x61, 0x44, 0x25, 0x46, 0x27, 0xDA, 0x65, 0x44, 0x28, 0x45, 0x45, 0x88, 0xCC, 0x85, + 0x5A, 0x87, 0xE9, 0x02, 0x00, 0x64, 0x27, 0xDA, 0x5A, 0xDA, 0x5A, 0x87, 0x87, 0xF3, 0x86, 0xF1, + 0x02, 0xA4, 0x60, 0x46, 0x60, 0x45, 0x00, 0x61, 0x22, 0xF2, 0xFF, 0xFF, 0xAC, 0x86, 0x00, 0xF2, + 0x04, 0x03, 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x65, 0x44, 0x02, 0xA5, 0x65, 0x46, + 0x64, 0x44, 0xCC, 0x9C, 0xFF, 0xFF, 0xF0, 0x02, 0x61, 0x44, 0x25, 0x46, 0x27, 0xDA, 0x5A, 0x87, + 0x28, 0x45, 0x45, 0x88, 0x87, 0xF3, 0x86, 0xF1, 0x02, 0xA4, 0x60, 0x46, 0x60, 0x45, 0x00, 0x61, + 0x76, 0xF2, 0xFF, 0xFF, 0xAC, 0x86, 0x00, 0xF2, 0x09, 0x03, 0x00, 0xF2, 0x09, 0xF0, 0xAC, 0x86, + 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x64, 0x44, 0xAC, 0x86, 0xF6, 0x01, 0x65, 0x44, 0x02, 0xA5, + 0x65, 0x46, 0x64, 0x44, 0xCC, 0x9C, 0x61, 0x44, 0xEB, 0x02, 0x25, 0x46, 0x27, 0xDA, 0x5A, 0x87, + 0x28, 0x45, 0x45, 0x88, 0x06, 0x60, 0x40, 0x65, 0x8C, 0xF3, 0x01, 0x61, 0xAC, 0x86, 0x00, 0xF2, + 0x03, 0x03, 0xD5, 0x80, 0xDD, 0x81, 0xFA, 0x04, 0xCD, 0x84, 0x25, 0x46, 0x27, 0xDA, 0x28, 0x45, + 0xC4, 0x84, 0x5A, 0xDA, 0xDA, 0x81, 0x8B, 0xF1, 0x59, 0xD8, 0x1E, 0x60, 0xCC, 0x64, 0x18, 0x63, + 0xA0, 0xD1, 0x06, 0xA4, 0x59, 0xD8, 0xFC, 0x1F, 0x00, 0x64, 0x59, 0xDA, 0x59, 0xDA, 0x01, 0x60, + 0x1A, 0x64, 0x0A, 0x63, 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, 0x7D, 0xF1, 0x59, 0xD8, 0x45, 0x01, + 0x07, 0x4B, 0xB6, 0x60, 0x58, 0x4F, 0x4D, 0x78, 0xFF, 0xFF, 0x0B, 0x47, 0x58, 0x4F, 0x21, 0x00, + 0x3C, 0x01, 0x07, 0x4B, 0xB6, 0x60, 0x58, 0x4F, 0x4D, 0x78, 0xFF, 0xFF, 0x0B, 0x47, 0x27, 0x44, + 0x00, 0xBE, 0x08, 0xF0, 0x15, 0x03, 0x64, 0x42, 0x4A, 0xD3, 0x09, 0xF2, 0xDC, 0x83, 0xA2, 0xDD, + 0x25, 0x43, 0x09, 0xFC, 0x63, 0x46, 0x27, 0x43, 0x0A, 0xFC, 0x09, 0xFA, 0x08, 0xF8, 0x00, 0xA8, + 0x66, 0x43, 0x03, 0x02, 0x64, 0x44, 0x58, 0xDD, 0x03, 0x00, 0x60, 0x46, 0x25, 0x44, 0x0A, 0xFA, + 0x1C, 0x01, 0x27, 0x43, 0xE3, 0x81, 0xE9, 0x81, 0x03, 0x05, 0x16, 0x03, 0x00, 0x61, 0x01, 0x00, + 0xEC, 0x63, 0x61, 0x46, 0xBF, 0xD2, 0x27, 0x45, 0xDC, 0x84, 0xA2, 0xDA, 0xA3, 0xD2, 0x25, 0x46, + 0x88, 0xF8, 0x04, 0x1B, 0x25, 0x44, 0x61, 0x46, 0xBE, 0xDA, 0x04, 0x00, 0x09, 0xFA, 0x60, 0x46, + 0x25, 0x44, 0x0A, 0xFA, 0x61, 0x46, 0xA3, 0xDA, 0x2F, 0x58, 0xFF, 0xFF, 0xA0, 0xFE, 0x07, 0x05, + 0xA3, 0xFE, 0x07, 0x05, 0xA1, 0xFE, 0x46, 0x05, 0x60, 0x64, 0x3B, 0xDB, 0x0F, 0x00, 0x20, 0x58, + 0xFF, 0xFF, 0xFA, 0x01, 0x0A, 0x60, 0x80, 0xF3, 0xFF, 0xFF, 0xFB, 0xB4, 0xA2, 0xDB, 0xA0, 0x4C, + 0x59, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0xA0, 0x4C, 0x7D, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, + 0x83, 0x3E, 0x40, 0x60, 0x0B, 0x65, 0x2B, 0x44, 0x00, 0x63, 0xE8, 0x80, 0xF8, 0x84, 0x02, 0x24, + 0x94, 0x84, 0xF3, 0x83, 0xCD, 0x81, 0xFF, 0xFF, 0xF8, 0x02, 0xDF, 0x83, 0x2F, 0x58, 0x40, 0x4B, + 0x00, 0x62, 0x01, 0x64, 0xD4, 0x80, 0xE0, 0x84, 0x1A, 0x03, 0xD4, 0x80, 0xE0, 0x84, 0x15, 0x03, + 0x61, 0x44, 0x11, 0x61, 0xE0, 0x84, 0xCD, 0x81, 0xFD, 0x04, 0x01, 0x00, 0xE0, 0x84, 0xF2, 0x82, + 0xFF, 0xFF, 0x02, 0x24, 0xC6, 0x82, 0x02, 0x28, 0xD6, 0x82, 0xE2, 0x80, 0xCD, 0x81, 0x02, 0x28, + 0x01, 0xBC, 0xF4, 0x02, 0x01, 0x2A, 0xC6, 0x82, 0x03, 0x00, 0xE9, 0x81, 0xF2, 0x82, 0x61, 0x44, + 0x2D, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x3B, 0xDB, 0x0C, 0x60, 0x6E, 0xF3, 0x5A, 0xD1, 0x60, 0x40, + 0x04, 0x3A, 0x2C, 0x00, 0x00, 0x64, 0x4A, 0xDB, 0x1E, 0x60, 0xCE, 0x63, 0xA3, 0xD3, 0x46, 0x43, + 0xAC, 0x86, 0x3C, 0x45, 0x22, 0x03, 0xD4, 0x80, 0x07, 0xF2, 0x02, 0x02, 0x09, 0xF2, 0xF8, 0x01, + 0xD0, 0x80, 0x09, 0xF2, 0xF5, 0x02, 0x60, 0x43, 0x80, 0x67, 0xB0, 0x81, 0x61, 0x44, 0x0F, 0x60, + 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x09, 0x60, + 0x08, 0x65, 0x0E, 0xF2, 0x02, 0xF2, 0x60, 0x40, 0xF0, 0x37, 0x05, 0x00, 0x8F, 0xF3, 0xD4, 0x80, + 0xCC, 0x84, 0x01, 0x02, 0x8F, 0xFB, 0x63, 0x44, 0xDB, 0x01, 0x23, 0x46, 0x3C, 0x44, 0xAC, 0x80, + 0xFF, 0xFF, 0x94, 0x02, 0x69, 0xF3, 0x6A, 0xF3, 0x02, 0xA8, 0x02, 0xA8, 0x08, 0x02, 0x00, 0x64, + 0x6B, 0xFB, 0x69, 0xFB, 0x6A, 0xFB, 0x00, 0x64, 0x6C, 0xFB, 0xCA, 0xFE, 0x92, 0x00, 0x03, 0x02, + 0x00, 0x64, 0x6A, 0xFB, 0xCA, 0xFE, 0x01, 0x64, 0x3B, 0xDB, 0x0F, 0x60, 0x6A, 0xF3, 0xFF, 0xFF, + 0x00, 0xA8, 0x60, 0x46, 0x35, 0x03, 0x2C, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x86, 0x00, + 0x2E, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, + 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x2E, 0xF0, 0x63, 0x46, 0xD0, 0x80, + 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x2D, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, + 0x61, 0x46, 0x2C, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, + 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x5F, 0x02, 0x66, 0x45, + 0x63, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x80, 0xB0, 0x09, 0xF2, 0x58, 0x03, 0xAC, 0x86, 0xCA, 0x01, + 0x6A, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, 0x4C, 0x02, 0x0F, 0x60, 0x73, 0xF3, 0xFF, 0xFF, + 0x00, 0xA8, 0x60, 0x46, 0x0F, 0x03, 0x76, 0xF1, 0x07, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, 0x09, 0xF2, + 0x03, 0x02, 0xAC, 0x86, 0x07, 0xF2, 0xFA, 0x02, 0x03, 0x02, 0x00, 0x64, 0x76, 0xFB, 0xED, 0x01, + 0x46, 0x5C, 0x3C, 0x00, 0x0F, 0x60, 0x76, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x01, 0x03, + 0x35, 0x02, 0x6B, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, 0x13, 0x02, 0x0F, 0x60, 0x6D, 0xF3, + 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x0B, 0x03, 0x2A, 0xF0, 0x20, 0x67, 0x09, 0xF2, 0xB0, 0x83, + 0x00, 0xA8, 0x00, 0x64, 0x02, 0x03, 0x2A, 0xFC, 0x01, 0x00, 0x6B, 0xFB, 0x1F, 0x00, 0x00, 0x64, + 0x6B, 0xFB, 0x0F, 0x60, 0x67, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x12, 0x03, 0x2A, 0xF0, + 0x08, 0x67, 0xA0, 0x80, 0xFF, 0xFF, 0x12, 0x03, 0x76, 0xF1, 0x07, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, + 0x09, 0xF2, 0x03, 0x02, 0xAC, 0x86, 0x07, 0xF2, 0xFA, 0x02, 0x08, 0x02, 0x00, 0x64, 0x76, 0xFB, + 0xE8, 0x01, 0x00, 0x64, 0x76, 0xFB, 0xB7, 0x60, 0xA2, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0xFC, 0xFB, + 0x46, 0x5C, 0x16, 0x60, 0x2B, 0xF3, 0x0D, 0xF2, 0x60, 0x5C, 0x64, 0x5F, 0x0D, 0xFA, 0x07, 0xF0, + 0x2A, 0xF2, 0xFF, 0xFF, 0x76, 0xF9, 0x60, 0x40, 0x08, 0x2B, 0x05, 0x00, 0x00, 0x64, 0x48, 0xFB, + 0xBA, 0x60, 0x03, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x02, 0x23, 0xF0, + 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xBF, 0x60, 0x16, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x00, 0x63, + 0x40, 0x47, 0x50, 0x36, 0x01, 0x00, 0x01, 0x63, 0x48, 0xFD, 0x4A, 0xF3, 0x35, 0xFA, 0x10, 0xA4, + 0x4A, 0xFB, 0x00, 0x64, 0x15, 0xFA, 0x16, 0xFA, 0x0F, 0xFA, 0x07, 0xF0, 0x87, 0xF3, 0xFF, 0xFF, + 0xD0, 0x80, 0xFF, 0xFF, 0x05, 0x03, 0x66, 0x43, 0x64, 0x46, 0x11, 0xF2, 0xBA, 0xFB, 0x63, 0x46, + 0x03, 0xF2, 0x00, 0xF4, 0x01, 0xF2, 0xFC, 0xA5, 0x00, 0x7F, 0xD4, 0x84, 0x27, 0x45, 0x3C, 0x46, + 0x1A, 0xFA, 0x22, 0x63, 0x7B, 0x60, 0xFF, 0x64, 0xA4, 0x84, 0x03, 0x2B, 0x1C, 0x63, 0x2A, 0xFA, + 0x8F, 0xB0, 0x88, 0x36, 0x02, 0xA3, 0x60, 0x40, 0xA4, 0x36, 0x14, 0x63, 0x43, 0x4C, 0x18, 0xFC, + 0x00, 0x7C, 0x22, 0xF8, 0x64, 0x41, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x3A, 0xF2, 0x63, 0x46, + 0xFF, 0xB4, 0x22, 0xFA, 0x60, 0x40, 0x00, 0x36, 0x92, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x0C, 0xB0, + 0x08, 0x3A, 0x8D, 0x00, 0x60, 0x40, 0x40, 0x26, 0x8A, 0x00, 0x03, 0xF2, 0x00, 0xF4, 0xA0, 0xD2, + 0xAA, 0x60, 0xAA, 0x65, 0x5A, 0xD0, 0xD4, 0x80, 0x03, 0x64, 0x0A, 0x02, 0xD0, 0x80, 0x00, 0x64, + 0x5A, 0xD0, 0x06, 0x02, 0xD0, 0x80, 0xF8, 0x7F, 0xD0, 0x80, 0x01, 0x03, 0x01, 0x02, 0x01, 0x61, + 0x62, 0x43, 0x46, 0x43, 0x3C, 0x46, 0x07, 0xF4, 0x3A, 0xF2, 0xFF, 0xFF, 0xA3, 0x46, 0x60, 0x40, + 0x22, 0x26, 0x49, 0x00, 0x60, 0x45, 0x63, 0x42, 0x5A, 0xD0, 0xCD, 0x81, 0x3C, 0x46, 0x18, 0x02, + 0x64, 0x44, 0x88, 0x3A, 0x15, 0x00, 0x8E, 0x37, 0x00, 0x00, 0x65, 0x44, 0x01, 0x26, 0x5F, 0x00, + 0x04, 0x26, 0x03, 0x00, 0x10, 0x26, 0x01, 0x00, 0x31, 0x00, 0xA3, 0x46, 0x3B, 0xF2, 0xFF, 0xFF, + 0x60, 0x40, 0x80, 0x27, 0x3E, 0x00, 0xA3, 0x46, 0x00, 0x7C, 0x22, 0xF8, 0xA3, 0x46, 0x4F, 0x00, + 0xA3, 0x46, 0x65, 0x44, 0x01, 0x26, 0x0B, 0x00, 0x04, 0x26, 0x03, 0x00, 0x10, 0x26, 0x01, 0x00, + 0x1D, 0x00, 0x3B, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x27, 0x2B, 0x00, 0x17, 0x00, 0x87, 0xF3, + 0xFF, 0xFF, 0x60, 0x46, 0x3A, 0xF2, 0x66, 0x43, 0xFF, 0xB4, 0x3C, 0x46, 0x22, 0xF0, 0x60, 0x47, + 0xB0, 0x84, 0x22, 0xFA, 0x63, 0x46, 0x3B, 0xF0, 0x60, 0x40, 0x04, 0x27, 0x03, 0x00, 0x10, 0x27, + 0x01, 0x00, 0x04, 0x00, 0x64, 0x40, 0x80, 0x27, 0x14, 0x00, 0x00, 0x00, 0x3C, 0x46, 0x02, 0x65, + 0xBE, 0x60, 0xB6, 0x78, 0xFF, 0xFF, 0xCD, 0x81, 0x63, 0x42, 0x5A, 0xD0, 0x3C, 0x46, 0x09, 0x02, + 0x64, 0x44, 0x88, 0x3A, 0x06, 0x00, 0x77, 0x37, 0x1A, 0x00, 0x78, 0x37, 0x18, 0x00, 0x8E, 0x37, + 0x16, 0x00, 0x3C, 0x46, 0x22, 0xF0, 0x80, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0xFF, 0xFF, 0x3F, 0xF2, + 0x3E, 0xF0, 0x08, 0xA4, 0x60, 0x41, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x03, 0x00, + 0x04, 0x26, 0x03, 0x00, 0x04, 0x00, 0x04, 0x2B, 0x02, 0x00, 0x61, 0x44, 0x3F, 0xFA, 0x3C, 0x46, + 0x2C, 0xF2, 0x27, 0x40, 0x01, 0x27, 0x32, 0xF2, 0xB4, 0xF1, 0x60, 0x40, 0x01, 0x26, 0x47, 0x00, + 0x09, 0x60, 0x00, 0x64, 0xD0, 0x80, 0x3F, 0xF2, 0x09, 0x06, 0x2C, 0x45, 0xC4, 0x84, 0xD0, 0x80, + 0x40, 0x4A, 0x34, 0x06, 0x60, 0x43, 0x64, 0x44, 0x54, 0x88, 0x17, 0x00, 0x60, 0x45, 0x13, 0x60, + 0x4B, 0xF3, 0xBB, 0xF3, 0x00, 0xBC, 0x60, 0x47, 0xEC, 0xA0, 0x28, 0x03, 0x27, 0x07, 0x2C, 0x44, + 0xC4, 0x81, 0x02, 0x60, 0x1C, 0x65, 0x45, 0x4A, 0xD5, 0x80, 0x2C, 0x45, 0x1F, 0x06, 0x27, 0x40, + 0x04, 0x27, 0x25, 0x00, 0x2A, 0x43, 0xD7, 0x85, 0x45, 0x48, 0xB5, 0xF1, 0x0F, 0xF2, 0xD3, 0x80, + 0x01, 0x65, 0x01, 0x07, 0x00, 0x65, 0xB4, 0x84, 0x0F, 0xFA, 0x00, 0x63, 0x3F, 0xF2, 0x28, 0x45, + 0x60, 0x41, 0xD4, 0x84, 0xDF, 0x83, 0xFC, 0x07, 0x14, 0xFC, 0x17, 0xFA, 0x04, 0x60, 0x00, 0x64, + 0x27, 0x45, 0xB4, 0x84, 0x2A, 0xFA, 0x28, 0x43, 0x16, 0xFC, 0x0D, 0x00, 0x3F, 0xF2, 0x2C, 0x45, + 0xB5, 0xF1, 0xC4, 0x81, 0xD1, 0x80, 0x0F, 0xF2, 0x01, 0x06, 0x01, 0xBC, 0x0F, 0xFA, 0x3F, 0xF2, + 0x17, 0xFA, 0x01, 0x64, 0x14, 0xFA, 0x0F, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x2A, 0x6F, 0x00, + 0x64, 0xF1, 0x15, 0x60, 0xDD, 0xF3, 0x64, 0x40, 0x01, 0x27, 0x03, 0x00, 0x60, 0x40, 0x02, 0x26, + 0x14, 0x00, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x12, 0xF0, 0x15, 0x60, 0xDE, 0xF3, 0x63, 0x46, + 0x64, 0x40, 0x10, 0x2A, 0x20, 0x00, 0x60, 0x40, 0x02, 0x26, 0x07, 0x00, 0x01, 0x26, 0x08, 0x00, + 0x04, 0x26, 0x09, 0x00, 0x06, 0x61, 0x6E, 0x63, 0x08, 0x00, 0x02, 0x61, 0x14, 0x63, 0x05, 0x00, + 0x00, 0x61, 0x0A, 0x63, 0x02, 0x00, 0x04, 0x61, 0x37, 0x63, 0x00, 0x64, 0x25, 0x60, 0xA2, 0x65, + 0x45, 0xD1, 0xD5, 0x81, 0x15, 0x60, 0xDA, 0xF9, 0x25, 0x60, 0x7A, 0x65, 0x45, 0xD1, 0x1C, 0xFC, + 0xB0, 0x84, 0x1E, 0xFA, 0x3C, 0x00, 0x60, 0x40, 0x10, 0x2A, 0x04, 0x00, 0x08, 0x61, 0x1E, 0x60, + 0x0B, 0x63, 0x27, 0x00, 0x20, 0x2A, 0x04, 0x00, 0x0A, 0x61, 0x16, 0x60, 0x0F, 0x63, 0x21, 0x00, + 0x40, 0x2A, 0x04, 0x00, 0x0C, 0x61, 0x12, 0x60, 0x0A, 0x63, 0x1B, 0x00, 0x80, 0x2A, 0x04, 0x00, + 0x0E, 0x61, 0x0E, 0x60, 0x0E, 0x63, 0x15, 0x00, 0x01, 0x2B, 0x04, 0x00, 0x10, 0x61, 0x0E, 0x60, + 0x09, 0x63, 0x0F, 0x00, 0x02, 0x2B, 0x04, 0x00, 0x12, 0x61, 0x0A, 0x60, 0x0D, 0x63, 0x09, 0x00, + 0x04, 0x2B, 0x04, 0x00, 0x14, 0x61, 0x0A, 0x60, 0x08, 0x63, 0x03, 0x00, 0x16, 0x61, 0x0A, 0x60, + 0x0C, 0x63, 0x1E, 0xF0, 0x40, 0x67, 0x25, 0x60, 0xA2, 0x65, 0x45, 0xD1, 0xD5, 0x81, 0x15, 0x60, + 0xDA, 0xF9, 0x25, 0x60, 0x7A, 0x65, 0x45, 0xD1, 0x1C, 0xFC, 0xB0, 0x84, 0x1E, 0xFA, 0xAA, 0xF2, + 0x15, 0x60, 0xC2, 0xF3, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x44, 0x44, 0x61, 0x40, 0x08, 0x26, + 0x02, 0x00, 0x61, 0x40, 0x80, 0x36, 0x12, 0xF2, 0x63, 0x46, 0x2C, 0x60, 0x26, 0x61, 0x00, 0x7F, + 0x60, 0x45, 0x45, 0xD3, 0xFF, 0xFF, 0x60, 0x45, 0x00, 0x7F, 0x4B, 0xFB, 0x65, 0x44, 0x00, 0x7E, + 0xBB, 0xFB, 0x62, 0xF1, 0x60, 0x43, 0x60, 0x47, 0xD0, 0x80, 0xC0, 0x65, 0x01, 0x06, 0x64, 0x44, + 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, 0x37, 0x36, 0x15, 0x64, 0x6E, 0x36, 0x0B, 0x64, + 0x44, 0x86, 0x2A, 0xF2, 0x07, 0xF0, 0x60, 0x40, 0xB0, 0x3A, 0x03, 0x00, 0x40, 0x3B, 0x01, 0x00, + 0x12, 0x00, 0x0C, 0xB4, 0x08, 0x3A, 0x44, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, + 0x3F, 0x00, 0x17, 0xF2, 0x22, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x22, 0x22, 0x04, 0x00, 0x00, 0xA8, + 0x01, 0xA8, 0x36, 0x03, 0x35, 0x03, 0x3C, 0x46, 0x2A, 0xF0, 0x40, 0x67, 0xB0, 0x84, 0xA2, 0xDA, + 0x60, 0x45, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x43, 0x60, 0x40, 0x01, 0x26, 0x05, 0x00, 0x04, 0x26, + 0x1D, 0x00, 0x10, 0x26, 0x10, 0x00, 0x04, 0x00, 0x04, 0x27, 0x18, 0x00, 0x10, 0x27, 0x0B, 0x00, + 0x65, 0x44, 0x2A, 0x61, 0x60, 0x40, 0x03, 0x2B, 0x24, 0x61, 0x8F, 0xB0, 0x88, 0x36, 0x02, 0xA1, + 0x41, 0x4C, 0x98, 0xFA, 0x15, 0x00, 0x65, 0x44, 0x32, 0x61, 0x60, 0x40, 0x03, 0x2B, 0x2C, 0x61, + 0x8F, 0xB0, 0x88, 0x36, 0x02, 0xA1, 0x41, 0x4C, 0x98, 0xFA, 0x0A, 0x00, 0x65, 0x44, 0x2E, 0x61, + 0x60, 0x40, 0x03, 0x2B, 0x28, 0x61, 0x8F, 0xB0, 0x88, 0x36, 0x02, 0xA1, 0x41, 0x4C, 0x98, 0xFA, + 0xBB, 0x60, 0xFB, 0x78, 0xFF, 0xFF, 0x66, 0x45, 0xAA, 0xF2, 0x15, 0x60, 0xC2, 0xF3, 0x24, 0x46, + 0x61, 0x40, 0x08, 0x26, 0x02, 0x00, 0x61, 0x40, 0x80, 0x36, 0x12, 0xF2, 0x65, 0x46, 0x60, 0x40, + 0x10, 0x26, 0x34, 0x00, 0x2C, 0x45, 0x17, 0xF2, 0x4B, 0xF1, 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x81, 0x64, 0x45, 0x16, 0xA1, 0xB7, 0x60, 0x58, 0x4D, 0xC0, 0x78, 0xFF, 0xFF, 0x64, 0xF1, + 0x01, 0xA4, 0xE0, 0x84, 0xE0, 0x84, 0x64, 0x40, 0x01, 0x2B, 0x06, 0xA4, 0x1B, 0xFA, 0xBB, 0xF3, + 0x25, 0x60, 0x82, 0x65, 0x60, 0x40, 0x0B, 0x37, 0x00, 0x63, 0x0F, 0x37, 0x02, 0x63, 0x0A, 0x37, + 0x04, 0x63, 0x0E, 0x37, 0x06, 0x63, 0x09, 0x37, 0x08, 0x63, 0x0D, 0x37, 0x0A, 0x63, 0x08, 0x37, + 0x0C, 0x63, 0x0C, 0x37, 0x0E, 0x63, 0x28, 0xA3, 0x47, 0xD1, 0xD8, 0xA3, 0xD7, 0x83, 0x15, 0x60, + 0xD9, 0xF9, 0x47, 0xD1, 0x40, 0x67, 0xB0, 0x84, 0x1F, 0xFA, 0x56, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, + 0x60, 0x40, 0x80, 0x36, 0x17, 0x00, 0x50, 0x36, 0x15, 0x00, 0x10, 0x36, 0x13, 0x00, 0x30, 0x36, + 0x11, 0x00, 0xA0, 0x36, 0x0F, 0x00, 0xB0, 0x36, 0x0D, 0x00, 0xC0, 0x36, 0x0B, 0x00, 0xBB, 0xF3, + 0xFF, 0xFF, 0x60, 0x40, 0x0A, 0x37, 0x06, 0x00, 0x15, 0x60, 0xDD, 0xF3, 0x80, 0x60, 0x00, 0x61, + 0x60, 0x40, 0x04, 0x26, 0x00, 0x61, 0xBB, 0xF3, 0x25, 0x60, 0x7A, 0x65, 0x60, 0x40, 0x0A, 0x37, + 0x00, 0x63, 0x14, 0x37, 0x02, 0x63, 0x37, 0x37, 0x04, 0x63, 0x6E, 0x37, 0x06, 0x63, 0x28, 0xA3, + 0x47, 0xD1, 0xD8, 0xA3, 0xD7, 0x83, 0x15, 0x60, 0xD9, 0xF9, 0x47, 0xD1, 0xFF, 0xFF, 0xB1, 0x84, + 0x1F, 0xFA, 0xBB, 0xF1, 0x2C, 0x45, 0x64, 0x43, 0x17, 0xF2, 0x4B, 0xF1, 0xC4, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0xE0, 0x81, 0x63, 0x40, 0x37, 0x37, 0xE1, 0x81, 0x64, 0x45, 0xB7, 0x60, 0x58, 0x4D, + 0xC0, 0x78, 0xFF, 0xFF, 0xAE, 0x82, 0xFC, 0xA2, 0x0A, 0x03, 0x63, 0x40, 0x6E, 0x3B, 0x06, 0x00, + 0x60, 0x41, 0x04, 0x0D, 0x63, 0x44, 0x80, 0x7E, 0xBB, 0xFB, 0x61, 0x44, 0xDC, 0x84, 0x2B, 0xF0, + 0x1B, 0xFA, 0x64, 0x44, 0x80, 0x27, 0x47, 0x00, 0x07, 0xF0, 0x66, 0x45, 0x64, 0x46, 0x12, 0xF2, + 0x65, 0x46, 0x60, 0x40, 0x10, 0x2A, 0x2E, 0x00, 0x16, 0xF2, 0x0F, 0xF0, 0xAC, 0x84, 0x2C, 0x45, + 0x29, 0x03, 0x4B, 0xF1, 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, 0x63, 0x40, 0x37, 0x37, + 0xE1, 0x81, 0x64, 0x45, 0x0F, 0xF0, 0xB7, 0x60, 0x58, 0x4D, 0xC0, 0x78, 0xFF, 0xFF, 0xAE, 0x82, + 0xFC, 0xA2, 0x0A, 0x03, 0x63, 0x40, 0x6E, 0x3B, 0x06, 0x00, 0x60, 0x41, 0x04, 0x0D, 0x80, 0x67, + 0xB0, 0x84, 0x0F, 0xFA, 0x61, 0x44, 0xDC, 0x84, 0x1D, 0xFA, 0xDE, 0x65, 0xC4, 0x85, 0x26, 0x41, + 0xE1, 0x81, 0xC5, 0x84, 0x2B, 0xFA, 0x1B, 0xF0, 0xDE, 0x64, 0xC0, 0x85, 0x26, 0x44, 0xE0, 0x84, + 0xC4, 0x84, 0x10, 0xFA, 0x26, 0x44, 0x2C, 0xF0, 0x0A, 0xA4, 0x66, 0x45, 0x24, 0x46, 0x92, 0xF2, + 0x65, 0x46, 0x9F, 0xF0, 0x61, 0x40, 0x10, 0x2A, 0x03, 0x00, 0x65, 0x40, 0x80, 0x27, 0xA0, 0xA4, + 0x64, 0x40, 0x01, 0x26, 0x00, 0x64, 0x11, 0xFA, 0xBB, 0xF3, 0x13, 0xFA, 0x7C, 0x44, 0x1D, 0xFA, + 0xFF, 0xFF, 0x0D, 0xF2, 0x3E, 0xF0, 0x60, 0x47, 0xFF, 0xB4, 0x64, 0x41, 0x01, 0xB1, 0x01, 0x63, + 0x17, 0x02, 0x60, 0x41, 0xFF, 0x22, 0x04, 0x00, 0xB7, 0x60, 0x58, 0x4F, 0xB1, 0x78, 0xFF, 0xFF, + 0x07, 0x60, 0xF7, 0xFD, 0x16, 0x60, 0x2B, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x01, 0x63, 0x61, 0x40, + 0xFF, 0x22, 0x04, 0x00, 0xB7, 0x60, 0x58, 0x4F, 0xB1, 0x78, 0xFF, 0xFF, 0x07, 0x60, 0xF8, 0xFD, + 0xBD, 0x60, 0x7A, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x27, 0x03, 0x00, + 0xBD, 0x60, 0x75, 0x78, 0xFF, 0xFF, 0x22, 0xF2, 0x46, 0x43, 0x60, 0x40, 0x22, 0x26, 0x09, 0x00, + 0x01, 0x26, 0x0A, 0x00, 0x04, 0x26, 0x4B, 0x00, 0x10, 0x26, 0x10, 0x00, 0xBD, 0x60, 0x75, 0x78, + 0xFF, 0xFF, 0xBC, 0x60, 0xF0, 0x78, 0xFF, 0xFF, 0x04, 0x27, 0x3D, 0x00, 0x10, 0x27, 0x03, 0x00, + 0xBD, 0x60, 0x75, 0x78, 0xFF, 0xFF, 0x87, 0xF3, 0x3C, 0xF1, 0x02, 0x00, 0x07, 0xF2, 0x00, 0x7C, + 0x40, 0x43, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x27, 0x21, 0x00, 0xA3, 0x46, 0x4B, 0xF2, + 0xFF, 0xFF, 0xDC, 0x84, 0x4B, 0xFA, 0x4A, 0xF2, 0x08, 0x04, 0xDC, 0x84, 0x4A, 0xFA, 0x49, 0xF2, + 0x04, 0x04, 0xDC, 0x84, 0x49, 0xFA, 0x01, 0x04, 0xFF, 0xFF, 0x87, 0xF3, 0x66, 0x5C, 0xD0, 0x80, + 0x00, 0x7C, 0x01, 0x02, 0x3C, 0xF1, 0x4B, 0xF0, 0x64, 0x47, 0x20, 0xBF, 0xA3, 0x46, 0x3A, 0xF8, + 0x3B, 0xFA, 0xA3, 0x46, 0x4A, 0xF2, 0x49, 0xF0, 0xA3, 0x46, 0x3C, 0xFA, 0x3D, 0xF8, 0x0F, 0x60, + 0xA0, 0x64, 0xA3, 0x46, 0x76, 0x61, 0x0E, 0x63, 0x59, 0xD0, 0x58, 0xD9, 0xFD, 0x1F, 0xA3, 0x46, + 0xBD, 0x60, 0x75, 0x78, 0xFF, 0xFF, 0x87, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0x02, 0x00, 0x07, 0xF4, + 0xFF, 0xFF, 0xA3, 0x46, 0x2A, 0xF2, 0xA3, 0x46, 0x60, 0x40, 0x08, 0x27, 0x48, 0x00, 0x87, 0xF3, + 0x66, 0x5C, 0xD0, 0x80, 0x3B, 0xF0, 0x08, 0x03, 0x64, 0x40, 0x10, 0x2A, 0x12, 0x00, 0xFF, 0x60, + 0xEF, 0x64, 0xA0, 0x84, 0x3B, 0xFA, 0x24, 0x00, 0x3D, 0xF3, 0x01, 0x61, 0x60, 0x43, 0xCF, 0x83, + 0xE1, 0x81, 0xFD, 0x0D, 0xE9, 0x81, 0xA1, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0x91, 0x84, 0x3B, 0xFA, + 0x17, 0x00, 0x4B, 0xF2, 0xFF, 0xFF, 0x10, 0xA0, 0xFF, 0xFF, 0x02, 0x04, 0xFF, 0x60, 0xFF, 0x64, + 0xDC, 0x84, 0x4B, 0xFA, 0x4A, 0xF2, 0x16, 0x04, 0xDC, 0x84, 0x4A, 0xFA, 0x49, 0xF2, 0x08, 0x04, + 0xDC, 0x84, 0x49, 0xFA, 0x05, 0x04, 0x3B, 0xF2, 0xFF, 0xFF, 0xE0, 0x84, 0xE8, 0x84, 0x3B, 0xFA, + 0x0C, 0x60, 0xFE, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC7, 0x60, 0xCF, 0x78, + 0xFF, 0xFF, 0x84, 0xFF, 0x06, 0x60, 0x17, 0xE1, 0x77, 0x40, 0x8B, 0xFF, 0x02, 0x60, 0x00, 0x75, + 0xC9, 0x60, 0x58, 0x4F, 0x67, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x06, 0x60, 0x80, 0xFB, 0x0C, 0x60, + 0xFE, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC8, 0x60, 0x46, 0x78, 0xFF, 0xFF, + 0x84, 0xFF, 0x00, 0x7C, 0x06, 0x60, 0x80, 0xF3, 0xA2, 0xD9, 0x60, 0x40, 0x01, 0x2A, 0x04, 0x00, + 0xC9, 0x60, 0x58, 0x4F, 0xAF, 0x78, 0xFF, 0xFF, 0x3C, 0x46, 0x07, 0xF4, 0x87, 0xF3, 0x66, 0x5C, + 0xD0, 0x80, 0x00, 0x7C, 0x07, 0x03, 0x66, 0x43, 0x3C, 0x46, 0x22, 0xF2, 0x63, 0x46, 0x60, 0x40, + 0x01, 0x2A, 0x01, 0x00, 0x3C, 0xF1, 0x4B, 0xF0, 0x64, 0x41, 0x64, 0x47, 0xFF, 0xB4, 0x60, 0x5F, + 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, 0x60, 0x47, 0xA3, 0x46, 0x3A, 0xFA, 0x64, 0x44, 0x20, 0x7F, + 0x34, 0x94, 0x3B, 0xFA, 0xA3, 0x46, 0x4A, 0xF2, 0x49, 0xF0, 0xA3, 0x46, 0x3C, 0xFA, 0x3D, 0xF8, + 0x80, 0x60, 0x10, 0xE0, 0x08, 0x60, 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, + 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0xBD, 0x60, 0x75, 0x78, 0xFF, 0xFF, + 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x27, 0x31, 0x00, 0x2A, 0xF2, 0x00, 0x60, 0x7C, 0x62, + 0x60, 0x40, 0x40, 0x2B, 0x24, 0x00, 0xA2, 0xD3, 0x00, 0x61, 0x60, 0xFE, 0xA0, 0xD3, 0x5E, 0xD1, + 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0xDC, 0x84, 0xF1, 0x81, 0xC0, 0x2B, 0x04, 0x00, 0x80, 0x2A, + 0x02, 0x00, 0x7F, 0xA4, 0xDC, 0x84, 0xFF, 0x3B, 0x03, 0x00, 0x60, 0x47, 0xDC, 0x87, 0x01, 0x61, + 0xC0, 0x80, 0x00, 0x36, 0xDC, 0x84, 0x4E, 0xDB, 0x60, 0xFE, 0x5A, 0xD1, 0xFF, 0xFF, 0xC1, 0x84, + 0xF0, 0x22, 0x10, 0xA4, 0xF0, 0x2A, 0x01, 0x00, 0x00, 0x64, 0xA2, 0xDB, 0x20, 0xFE, 0x00, 0x60, + 0x3E, 0xF3, 0xFF, 0xFF, 0xA0, 0xD3, 0x5A, 0xD1, 0x3A, 0xFA, 0x3B, 0xF8, 0x74, 0x62, 0xA2, 0xD0, + 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5A, + 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, 0x40, 0xF3, 0xFF, 0xFF, 0xA0, 0xD1, 0x5A, 0xD1, + 0x64, 0x45, 0x64, 0x44, 0xE3, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, + 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, + 0xE7, 0x7F, 0xA0, 0x5A, 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, + 0xA0, 0x5A, 0x64, 0x44, 0xE9, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, + 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, + 0xED, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEF, 0x7F, + 0xA0, 0x5A, 0x08, 0x60, 0x00, 0xEA, 0x65, 0x44, 0x02, 0xA4, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, + 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x02, 0x64, 0x3B, 0xDB, 0xBA, 0x60, + 0xF3, 0x78, 0xFF, 0xFF, 0xBF, 0x60, 0xBB, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0xFC, 0xFB, 0x07, 0xF0, + 0x00, 0x64, 0xD0, 0x80, 0x87, 0xF3, 0x0E, 0x03, 0xD0, 0x80, 0xFF, 0xFF, 0x0B, 0x03, 0x47, 0xF1, + 0x07, 0xF0, 0x64, 0x40, 0x02, 0x26, 0x01, 0x00, 0x08, 0x00, 0x03, 0x12, 0xBE, 0x60, 0x46, 0x78, + 0xFF, 0xFF, 0xFC, 0x0A, 0xBE, 0x60, 0xA6, 0x78, 0xFF, 0xFF, 0x87, 0xF0, 0x87, 0xF3, 0x10, 0xF0, + 0xD4, 0x80, 0xFF, 0xFF, 0x3D, 0x03, 0x66, 0x43, 0x65, 0x46, 0xFF, 0x67, 0x20, 0x85, 0x64, 0x5F, + 0x40, 0x44, 0x15, 0xF0, 0x25, 0x44, 0xD0, 0x84, 0x03, 0xA4, 0x03, 0x0E, 0xE8, 0x84, 0xE8, 0x84, + 0x04, 0x00, 0xFA, 0xA4, 0xE8, 0x84, 0xE8, 0x87, 0xC0, 0xBF, 0xC0, 0x84, 0x15, 0xFA, 0x40, 0x45, + 0x14, 0xF0, 0x24, 0x44, 0xD0, 0x84, 0x1F, 0xA4, 0x06, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, + 0xE8, 0x84, 0xE8, 0x84, 0x07, 0x00, 0xC2, 0xA4, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, + 0xE8, 0x87, 0xF8, 0xBF, 0xC0, 0x84, 0x14, 0xFA, 0x60, 0x5C, 0x2F, 0x67, 0xD0, 0x80, 0x60, 0x45, + 0x02, 0x28, 0x64, 0x45, 0x25, 0x5C, 0x8B, 0x67, 0xD0, 0x80, 0x60, 0x41, 0x02, 0x24, 0x64, 0x41, + 0xD5, 0x84, 0x80, 0x65, 0xC4, 0x87, 0x01, 0x05, 0x00, 0x64, 0xFF, 0xB4, 0x0E, 0xFA, 0x63, 0x46, + 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x17, 0xF2, 0x63, 0x46, 0x60, 0x40, 0x00, 0x36, 0x2E, 0x00, + 0x01, 0x36, 0x1E, 0x00, 0x03, 0x3A, 0x25, 0x00, 0x64, 0x46, 0x10, 0xF2, 0x11, 0xFA, 0x12, 0xF2, + 0x00, 0x61, 0x60, 0x47, 0x00, 0x7F, 0x12, 0xFA, 0x97, 0xFA, 0x46, 0x44, 0x63, 0x46, 0xC1, 0x60, + 0x58, 0x4E, 0x72, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x00, 0x3A, 0x04, 0x00, 0xC1, 0x60, 0x58, 0x4E, + 0xBC, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x96, 0xFC, 0x63, 0x46, 0x43, 0x00, + 0x64, 0x46, 0x16, 0xF2, 0x00, 0x61, 0x20, 0x28, 0xFF, 0xA4, 0x97, 0xFA, 0x16, 0xFA, 0x63, 0x46, + 0x3A, 0x00, 0x64, 0x46, 0x00, 0x61, 0x97, 0xFA, 0x63, 0x46, 0x35, 0x00, 0x07, 0xF0, 0x66, 0x41, + 0x64, 0x46, 0x16, 0xF2, 0xFF, 0xFF, 0x20, 0x28, 0xFF, 0xA4, 0x16, 0xFA, 0x93, 0xF4, 0x12, 0xF2, + 0x20, 0x28, 0xFF, 0xA3, 0x13, 0xFC, 0x61, 0x46, 0x63, 0x40, 0x00, 0x3A, 0x24, 0x00, 0xC1, 0x60, + 0x58, 0x4E, 0x93, 0x78, 0xFF, 0xFF, 0x61, 0x40, 0xFF, 0x36, 0x1D, 0x00, 0x66, 0x41, 0x64, 0x46, + 0x12, 0xF2, 0x93, 0xF4, 0x61, 0x46, 0x20, 0x28, 0x16, 0x00, 0x44, 0x44, 0xC1, 0x60, 0x58, 0x4E, + 0x72, 0x78, 0xFF, 0xFF, 0x24, 0x5C, 0x65, 0x40, 0x00, 0x36, 0x06, 0x00, 0x66, 0x41, 0x64, 0x46, + 0x01, 0x64, 0x17, 0xFA, 0x61, 0x46, 0x07, 0x00, 0x66, 0x43, 0x64, 0x46, 0xC1, 0x60, 0x58, 0x4E, + 0xBC, 0x78, 0xFF, 0xFF, 0x63, 0x46, 0xBE, 0x60, 0xA6, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x43, + 0x64, 0x46, 0x17, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0xFF, 0x27, 0xFF, 0xFF, 0x00, 0x36, 0x07, 0x00, + 0x01, 0x36, 0x1C, 0x00, 0x02, 0x36, 0x24, 0x00, 0x03, 0x36, 0x43, 0x00, 0xFF, 0xFF, 0x15, 0x60, + 0xF9, 0xF1, 0x16, 0xF2, 0x43, 0x44, 0xD0, 0x80, 0x2C, 0x60, 0x24, 0x61, 0x09, 0x03, 0xA1, 0xD1, + 0x2C, 0x60, 0x22, 0x63, 0xC0, 0x84, 0x16, 0xFA, 0xA3, 0xD3, 0xFF, 0xFF, 0x13, 0xFA, 0x39, 0x00, + 0x96, 0xFC, 0xC1, 0x60, 0x58, 0x4E, 0xBC, 0x78, 0xFF, 0xFF, 0x33, 0x00, 0x43, 0x44, 0xC1, 0x60, + 0x58, 0x4E, 0xBC, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0x11, 0xF3, 0x96, 0xFC, 0x13, 0xFA, 0x29, 0x00, + 0x63, 0x46, 0x2B, 0x60, 0xF4, 0x63, 0xA3, 0xD3, 0x15, 0xF2, 0x60, 0x45, 0xD4, 0x80, 0x07, 0xF0, + 0x0C, 0x03, 0x66, 0x41, 0x44, 0x44, 0x64, 0x46, 0x12, 0xF2, 0x61, 0x46, 0xC1, 0x60, 0x58, 0x4E, + 0x72, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x00, 0x3A, 0x19, 0x00, 0x66, 0x43, 0x24, 0x46, 0xC1, 0x60, + 0x58, 0x4E, 0xBC, 0x78, 0xFF, 0xFF, 0x12, 0xF2, 0x91, 0xF2, 0x90, 0xFA, 0x60, 0x5F, 0x12, 0xFA, + 0x04, 0x00, 0xC1, 0x60, 0x58, 0x4E, 0xBC, 0x78, 0xFF, 0xFF, 0x03, 0x64, 0x17, 0xFA, 0x63, 0x46, + 0x05, 0x00, 0x24, 0x43, 0x02, 0x64, 0x17, 0xFA, 0x63, 0x46, 0x00, 0x00, 0x03, 0x64, 0x3B, 0xDB, + 0xCA, 0xFE, 0x47, 0xF1, 0x01, 0x65, 0x32, 0x40, 0x04, 0x27, 0x08, 0x00, 0x2C, 0xF2, 0x64, 0x45, + 0x02, 0x22, 0x04, 0x00, 0x60, 0x40, 0x01, 0x26, 0x01, 0x00, 0x7B, 0x00, 0x14, 0xF2, 0x65, 0x40, + 0x01, 0x26, 0x0C, 0x00, 0x60, 0x45, 0x05, 0x64, 0x3B, 0xDB, 0x65, 0x44, 0xCC, 0x85, 0x25, 0x60, + 0xD6, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xD3, 0x78, 0x97, 0xF1, 0x50, 0x00, 0x60, 0x41, 0x2A, 0xF0, + 0x00, 0x60, 0x0C, 0x64, 0xA0, 0x84, 0x04, 0x36, 0x02, 0x00, 0x0C, 0x3A, 0x01, 0x00, 0x46, 0x00, + 0x61, 0x45, 0x60, 0x43, 0x25, 0x60, 0xD6, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xD3, 0x78, 0x97, 0xF1, + 0x63, 0x40, 0x08, 0x36, 0x01, 0x00, 0x3A, 0x00, 0x14, 0xF2, 0x1C, 0x65, 0x60, 0x41, 0x00, 0x63, + 0xCD, 0x81, 0xC7, 0x83, 0xFD, 0x02, 0x3F, 0xF0, 0x2C, 0xF2, 0xC3, 0x83, 0x60, 0x40, 0x01, 0x2A, + 0x0D, 0x00, 0x25, 0x60, 0xD4, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x25, 0x60, + 0xDA, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xD2, 0x78, 0x63, 0x45, 0x20, 0x00, 0x25, 0x60, 0xD2, 0x64, + 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x25, 0x60, 0xD8, 0x64, 0xE5, 0x60, 0x78, 0x41, + 0xD2, 0x78, 0x63, 0x45, 0x15, 0xF2, 0xFF, 0xFF, 0x0F, 0xB4, 0x00, 0xA8, 0x01, 0xA8, 0x0E, 0x03, + 0x07, 0x03, 0x25, 0x60, 0xE0, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x06, 0x00, + 0x25, 0x60, 0xDE, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x04, 0x64, 0x3B, 0xDB, + 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x06, 0xF0, 0xFF, 0x60, 0x5F, 0x64, 0xA0, 0x84, 0x06, 0xFA, + 0x61, 0x46, 0x1E, 0x60, 0xF2, 0x64, 0x0F, 0x60, 0x8D, 0xFB, 0x3C, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x5C, 0x5C, 0xFC, 0xFC, 0xCE, 0xFE, 0xB7, 0x60, 0xE2, 0x78, + 0xFF, 0xFF, 0x13, 0x60, 0x2E, 0xF3, 0x07, 0xF4, 0x06, 0xF2, 0x02, 0xA8, 0x3C, 0x46, 0x10, 0x03, + 0x10, 0xB0, 0x2A, 0xF2, 0x0D, 0x03, 0x0E, 0xF2, 0x0C, 0xB0, 0x60, 0x40, 0xF0, 0x37, 0x20, 0xBC, + 0x02, 0x03, 0xFE, 0x7F, 0x0E, 0xFA, 0x23, 0xF0, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xCE, 0x01, + 0x2A, 0xF2, 0xFF, 0xFF, 0x50, 0xA8, 0x02, 0x7C, 0x10, 0x03, 0x0F, 0xF0, 0x15, 0xF2, 0x64, 0x41, + 0x01, 0x2A, 0x02, 0x00, 0xAF, 0xF1, 0x09, 0x00, 0x03, 0x65, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, + 0x06, 0xF0, 0x63, 0x46, 0xAE, 0xF1, 0x64, 0x40, 0x10, 0x2A, 0x64, 0x45, 0xDC, 0x84, 0xD4, 0x80, + 0x15, 0xFA, 0x38, 0x07, 0x61, 0x40, 0x01, 0x2A, 0x08, 0x00, 0x13, 0x60, 0x03, 0xF3, 0xFF, 0xFF, + 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, 0x07, 0x00, 0x13, 0x60, 0x04, 0xF3, 0xFF, 0xFF, + 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, 0x2A, 0xF0, 0x08, 0x67, 0xB0, 0x84, 0xA2, 0xDA, + 0x08, 0xF0, 0x1E, 0x60, 0xD4, 0x64, 0xD0, 0x80, 0x07, 0xF2, 0x46, 0x43, 0x87, 0xF1, 0x06, 0x03, + 0x60, 0x46, 0x86, 0xF4, 0xD0, 0x80, 0x80, 0xBB, 0x01, 0x03, 0x06, 0xFC, 0x23, 0x46, 0x3E, 0xF2, + 0x00, 0x63, 0x01, 0xB0, 0x43, 0x5C, 0xFC, 0xFC, 0x0A, 0x03, 0x1E, 0x60, 0xEC, 0x64, 0x0F, 0x60, + 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xB7, 0x60, + 0xE2, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x49, 0xFB, 0x25, 0x60, 0xE0, 0x64, 0xE5, 0x60, 0x78, 0x41, + 0xC7, 0x78, 0x97, 0xF1, 0x25, 0x60, 0xE2, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, + 0x27, 0x44, 0xF7, 0xB4, 0x40, 0x47, 0x23, 0xF0, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x07, 0xF0, + 0x66, 0x41, 0x64, 0x46, 0x06, 0xF2, 0x7F, 0x65, 0xA4, 0x9E, 0x06, 0xFA, 0x61, 0x46, 0x5E, 0x01, + 0xC0, 0x60, 0x35, 0x78, 0xFF, 0xFF, 0x21, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0x01, 0x63, 0xC4, 0xB4, + 0x31, 0xFB, 0x32, 0xFD, 0xBF, 0x60, 0xEB, 0x62, 0x42, 0x40, 0xA0, 0x4C, 0x40, 0xBC, 0x7D, 0xB4, + 0xA0, 0x51, 0xA0, 0xFE, 0x1A, 0xFF, 0x1E, 0x60, 0xE6, 0x64, 0x08, 0xF0, 0x07, 0xF0, 0xD0, 0x80, + 0x1E, 0x60, 0xEC, 0x62, 0x13, 0x02, 0xA2, 0xD3, 0x01, 0x63, 0xAC, 0x86, 0x07, 0xF2, 0x0E, 0x03, + 0xD0, 0x80, 0x09, 0xF2, 0xFA, 0x02, 0x23, 0xFC, 0x1E, 0x60, 0xF2, 0x64, 0x0F, 0x60, 0x8D, 0xFB, + 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x3C, 0x46, 0x06, 0x64, + 0xA1, 0xFF, 0x49, 0xFB, 0x83, 0x3E, 0x31, 0xF3, 0x87, 0x60, 0x80, 0x61, 0x1D, 0xF0, 0x60, 0x40, + 0x01, 0x2A, 0x0F, 0x00, 0xFE, 0xB4, 0x31, 0xFB, 0x00, 0x64, 0x49, 0xFB, 0x01, 0x64, 0x47, 0xFB, + 0x00, 0x71, 0x05, 0x64, 0x64, 0x5F, 0x0D, 0xFA, 0x40, 0x64, 0x3B, 0xDB, 0xC0, 0x60, 0x35, 0x78, + 0xFF, 0xFF, 0x02, 0x2A, 0x17, 0x00, 0xD1, 0x91, 0x8D, 0xE2, 0x41, 0x64, 0x3B, 0xDB, 0x31, 0xF3, + 0x2C, 0x60, 0x5E, 0x63, 0xFD, 0xB4, 0x31, 0xFB, 0xA3, 0xD3, 0x02, 0x63, 0x60, 0x5C, 0x0D, 0xF2, + 0x47, 0xFD, 0xFF, 0xB5, 0x60, 0x47, 0xD0, 0x80, 0xDC, 0x84, 0x1F, 0x03, 0x60, 0x47, 0xB4, 0x84, + 0x0D, 0xFA, 0x1B, 0x00, 0x08, 0x2A, 0x07, 0x00, 0x42, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, + 0xF7, 0xB4, 0x31, 0xFB, 0x12, 0x00, 0x10, 0x2A, 0x09, 0x00, 0x43, 0x64, 0x3B, 0xDB, 0x31, 0xF3, + 0xFF, 0xFF, 0xEF, 0xB4, 0x31, 0xFB, 0xBF, 0x60, 0xBB, 0x78, 0xFF, 0xFF, 0x44, 0x64, 0x3B, 0xDB, + 0x31, 0xF3, 0xFF, 0xFF, 0xDF, 0xB4, 0x31, 0xFB, 0x00, 0x00, 0x2A, 0x64, 0x3B, 0xDB, 0xB7, 0x60, + 0xA2, 0x64, 0x40, 0x40, 0xBD, 0x60, 0x7D, 0x78, 0xFF, 0xFF, 0x0A, 0x60, 0x80, 0xF3, 0xFF, 0xFF, + 0x02, 0xB5, 0x04, 0xB5, 0x04, 0x03, 0x03, 0x03, 0xC0, 0x60, 0xB8, 0x78, 0xFF, 0xFF, 0xF0, 0x60, + 0x58, 0x4E, 0x74, 0x78, 0xFF, 0xFF, 0x31, 0x40, 0x01, 0x2A, 0x28, 0x00, 0x9D, 0xFE, 0x26, 0x04, + 0x25, 0x0A, 0x9F, 0xFE, 0x23, 0x05, 0x85, 0xFF, 0x20, 0x44, 0x84, 0xFF, 0x40, 0x26, 0x1E, 0x00, + 0x3F, 0x40, 0x20, 0x2B, 0x1B, 0x00, 0x38, 0x69, 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x16, 0xFD, 0x01, + 0x01, 0x2A, 0x14, 0x00, 0x13, 0x60, 0x09, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, + 0xA2, 0xDB, 0x64, 0xF1, 0x02, 0x60, 0xEE, 0x64, 0x81, 0xFB, 0xFF, 0xFF, 0x80, 0x60, 0x00, 0x64, + 0xB0, 0x84, 0x82, 0xFB, 0x04, 0x64, 0x83, 0xFB, 0xDF, 0xFE, 0x19, 0xFF, 0x10, 0x64, 0x3B, 0xDB, + 0x65, 0xF3, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x93, 0x74, 0xF1, 0xC9, 0xFE, + 0x64, 0x40, 0x01, 0x26, 0x3B, 0x00, 0x49, 0xF3, 0x3C, 0x46, 0x31, 0x18, 0xCC, 0x84, 0x49, 0xFB, + 0x2E, 0x02, 0xC1, 0x60, 0x6B, 0x64, 0x40, 0x42, 0xFC, 0xFC, 0x00, 0x64, 0x5C, 0x5C, 0x32, 0xFB, + 0x82, 0xFF, 0x5C, 0x47, 0x84, 0xFF, 0x62, 0xFF, 0x13, 0x60, 0x01, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, + 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, 0x2A, 0xF2, 0x07, 0xF0, 0x0C, 0xB4, 0x08, 0x3A, 0x07, 0x00, + 0x66, 0x41, 0x64, 0x46, 0x06, 0xF0, 0xFF, 0x60, 0xDF, 0x64, 0xA0, 0x84, 0x06, 0xFA, 0x23, 0xF0, + 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x1E, 0x60, 0xF2, 0x64, 0x0F, 0x60, 0x8D, 0xFB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xCE, 0xFE, 0x06, 0x00, + 0x65, 0xF3, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x93, 0x14, 0x60, 0xFC, 0x63, + 0xA3, 0xD3, 0xAD, 0x49, 0x20, 0xB5, 0x08, 0xB1, 0x22, 0x03, 0xE1, 0x81, 0x10, 0xB5, 0x95, 0x81, + 0x60, 0x41, 0x18, 0x02, 0x14, 0x60, 0xFE, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA4, 0xDB, + 0x16, 0x02, 0x0A, 0x64, 0xA4, 0xDB, 0x61, 0x44, 0x07, 0xB4, 0xFF, 0xFF, 0x10, 0x02, 0x08, 0xB1, + 0xE1, 0x81, 0x95, 0x81, 0xA3, 0xD3, 0x0B, 0x03, 0x08, 0xAC, 0x01, 0xBC, 0xA3, 0xDB, 0xFF, 0xFF, + 0x13, 0xFF, 0x05, 0x00, 0x10, 0xAC, 0xA3, 0xDB, 0x0A, 0x7C, 0x0A, 0x60, 0x7F, 0xF9, 0xB7, 0x60, + 0xAE, 0x78, 0xFF, 0xFF, 0x46, 0xF3, 0x45, 0xF1, 0x04, 0x1B, 0x64, 0x44, 0x02, 0x1B, 0x07, 0x60, + 0xF7, 0xF3, 0x45, 0xFB, 0x00, 0x63, 0x46, 0xFD, 0x60, 0x41, 0x25, 0x64, 0x3B, 0xDB, 0x27, 0x44, + 0xEF, 0xB4, 0x40, 0x47, 0x00, 0xB9, 0x71, 0x40, 0x80, 0x27, 0x01, 0x12, 0x19, 0x03, 0xC1, 0x60, + 0x0C, 0x62, 0x84, 0xFF, 0x42, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, + 0x1F, 0x0A, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, 0x19, 0x0A, 0x71, 0x40, + 0x80, 0x27, 0xF7, 0x12, 0x45, 0xF3, 0x27, 0x02, 0x03, 0x18, 0xCC, 0x84, 0x45, 0xFB, 0xF1, 0x02, + 0x06, 0x0A, 0xA0, 0x4C, 0xFB, 0xB4, 0xA0, 0x51, 0xA4, 0x60, 0xD7, 0x78, 0xFF, 0xFF, 0x84, 0xFF, + 0xC0, 0x60, 0xEA, 0x64, 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, + 0xAF, 0x60, 0x7B, 0x78, 0xFF, 0xFF, 0x3C, 0x44, 0xAC, 0x80, 0x32, 0xF1, 0x12, 0x03, 0x64, 0x40, + 0x07, 0x22, 0x0F, 0x00, 0xA4, 0x60, 0xB6, 0x78, 0xFF, 0xFF, 0xA0, 0x4C, 0x1C, 0xBC, 0xDF, 0xB4, + 0xA0, 0x51, 0xF1, 0x01, 0x06, 0x00, 0x28, 0x64, 0x3A, 0xDB, 0xA0, 0x4C, 0x30, 0xBC, 0xF3, 0xB4, + 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x28, 0x64, 0x3B, 0xDB, 0x07, 0x60, 0xF8, 0xF3, + 0x32, 0x40, 0x02, 0x27, 0x16, 0x00, 0x46, 0xFB, 0x14, 0x18, 0xC1, 0x60, 0x59, 0x64, 0x84, 0xFF, + 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x15, 0xBC, 0xF7, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, + 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, 0x46, 0xF3, 0xCB, 0x0A, 0xDD, 0x02, 0xCC, 0x84, 0x46, 0xFB, + 0xF5, 0x02, 0x84, 0xFF, 0xC1, 0x60, 0x6B, 0x64, 0x40, 0x42, 0x82, 0xFF, 0x27, 0x44, 0x08, 0xBC, + 0x40, 0x47, 0xF9, 0xE1, 0x04, 0x00, 0x78, 0xE1, 0x31, 0x40, 0x01, 0x26, 0xF9, 0xE1, 0xA4, 0x60, + 0xAA, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xFB, 0xF1, 0x60, 0x45, 0x2C, 0x60, 0x0A, 0x61, 0xC5, 0x83, + 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0x66, 0x45, 0x24, 0x46, 0x0E, 0xF2, 0x65, 0x46, 0x64, 0x45, + 0xD5, 0x81, 0x61, 0x45, 0x00, 0x7F, 0xD4, 0x80, 0x64, 0x43, 0x08, 0x04, 0xE3, 0x83, 0x63, 0x45, + 0xC5, 0x81, 0x61, 0x45, 0xD4, 0x80, 0x02, 0x65, 0x03, 0x07, 0x03, 0x00, 0x00, 0x65, 0x01, 0x00, + 0x01, 0x65, 0x2E, 0x58, 0xFF, 0xFF, 0x66, 0x43, 0x64, 0x46, 0x8F, 0xF0, 0x12, 0xF2, 0x91, 0xF2, + 0x60, 0x40, 0x10, 0x36, 0x05, 0x00, 0x12, 0x36, 0x08, 0x00, 0x0C, 0x36, 0x0B, 0x00, 0x0F, 0x00, + 0x40, 0x61, 0xA5, 0x80, 0x0A, 0x64, 0x13, 0x02, 0xF3, 0x01, 0x10, 0x61, 0xA5, 0x80, 0x0E, 0x64, + 0x0E, 0x02, 0xEE, 0x01, 0x08, 0x61, 0xA5, 0x80, 0x10, 0x64, 0x09, 0x02, 0xE9, 0x01, 0xE1, 0x81, + 0xA5, 0x80, 0x03, 0x05, 0xC8, 0x84, 0x03, 0x02, 0xE3, 0x01, 0xFF, 0x61, 0x02, 0x00, 0x12, 0xFA, + 0x91, 0xFA, 0x63, 0x46, 0x2E, 0x58, 0xFF, 0xFF, 0x8F, 0xF0, 0x12, 0xF2, 0x91, 0xF2, 0x60, 0x40, + 0x0A, 0x36, 0x05, 0x00, 0x0E, 0x36, 0x08, 0x00, 0x10, 0x36, 0x0B, 0x00, 0x0F, 0x00, 0x08, 0x61, + 0xA5, 0x80, 0x10, 0x7E, 0x11, 0x02, 0xF3, 0x01, 0x04, 0x61, 0xA5, 0x80, 0x12, 0x7E, 0x0C, 0x02, + 0xEE, 0x01, 0x20, 0x61, 0xA5, 0x80, 0x0C, 0x7E, 0x07, 0x02, 0xE9, 0x01, 0xE9, 0x81, 0xA5, 0x80, + 0x05, 0x05, 0xD8, 0x84, 0x01, 0x02, 0xE3, 0x01, 0x12, 0xFA, 0x91, 0xFA, 0x2E, 0x58, 0xFF, 0xFF, + 0x24, 0xE2, 0x2D, 0xF3, 0x2C, 0xF3, 0x00, 0xBD, 0xCC, 0x84, 0x08, 0x03, 0x2C, 0xFB, 0x06, 0x02, + 0x65, 0x44, 0x2C, 0xFB, 0x8A, 0xFF, 0x80, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x44, 0xF3, 0xFF, 0xFF, + 0xDC, 0x84, 0x44, 0xFB, 0x28, 0x60, 0x72, 0x65, 0x28, 0x60, 0x70, 0x61, 0xA5, 0xD3, 0xA1, 0xD3, + 0x11, 0x18, 0xCC, 0x84, 0xA1, 0xDB, 0x0E, 0x02, 0xA5, 0xD3, 0xA1, 0xDB, 0x14, 0x60, 0x3B, 0xF3, + 0x14, 0x60, 0x3A, 0xF1, 0xA2, 0xDB, 0xD0, 0x80, 0xFF, 0xFF, 0x04, 0x03, 0x8A, 0xFF, 0x20, 0x60, + 0x00, 0x75, 0x88, 0xFF, 0xD2, 0xF3, 0x31, 0x40, 0x01, 0x2A, 0x3D, 0x00, 0x60, 0x43, 0x04, 0xB0, + 0x02, 0xB0, 0x08, 0x24, 0x16, 0x02, 0x10, 0xB0, 0x29, 0x44, 0x34, 0x02, 0x00, 0xA8, 0xCC, 0x81, + 0x0D, 0x03, 0x41, 0x49, 0x2F, 0x02, 0x63, 0x40, 0x08, 0x2A, 0x08, 0x00, 0xF7, 0xB3, 0x18, 0x60, + 0x0A, 0xF1, 0xAD, 0x4F, 0xFD, 0xB4, 0xA0, 0x5D, 0x44, 0x49, 0x24, 0x00, 0x63, 0x40, 0x02, 0x2A, + 0x10, 0x00, 0x18, 0x60, 0x0B, 0xF3, 0x18, 0x60, 0x09, 0xFB, 0x40, 0x49, 0x18, 0x60, 0x0C, 0xF3, + 0x18, 0x60, 0x0A, 0xFB, 0x0C, 0xBB, 0xFD, 0xB3, 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, + 0x11, 0x00, 0x18, 0x60, 0x0D, 0xF3, 0x30, 0x60, 0x12, 0x7C, 0x0C, 0x18, 0xA4, 0xDB, 0x40, 0x49, + 0x18, 0x60, 0x0E, 0xF3, 0x18, 0x60, 0x0A, 0xFB, 0x08, 0xBB, 0xFB, 0xB3, 0xAD, 0x4F, 0x02, 0xBC, + 0x00, 0x7F, 0xA0, 0x5D, 0xD2, 0xFD, 0x00, 0x60, 0x85, 0xF3, 0x62, 0x43, 0x17, 0x18, 0x58, 0xD3, + 0x62, 0x41, 0x03, 0x18, 0xCC, 0x84, 0xA1, 0xDB, 0x11, 0x00, 0x49, 0xD3, 0xA3, 0xDB, 0x06, 0xA1, + 0xA1, 0xD3, 0x59, 0xD1, 0x60, 0x45, 0xA5, 0xD3, 0x59, 0xD1, 0xB0, 0x84, 0xA5, 0xDB, 0x64, 0x44, + 0x06, 0x36, 0xCD, 0xFE, 0x07, 0x36, 0xD6, 0xFE, 0xE6, 0x01, 0x23, 0x46, 0xB7, 0x60, 0xAE, 0x78, + 0xFF, 0xFF, 0x46, 0x43, 0x1F, 0x60, 0x44, 0x61, 0xA1, 0xD3, 0x59, 0xD1, 0x06, 0x1B, 0x59, 0xD3, + 0x59, 0xD1, 0x03, 0x1B, 0x59, 0xD3, 0x59, 0xD1, 0xF0, 0x18, 0x00, 0x63, 0x49, 0xDD, 0x60, 0x40, + 0x02, 0x36, 0x11, 0x00, 0x03, 0x36, 0x32, 0x00, 0x01, 0x36, 0x08, 0x00, 0x05, 0x3A, 0xEA, 0x01, + 0xA4, 0xD3, 0x5A, 0xD3, 0x9C, 0x85, 0xA4, 0x84, 0xA2, 0xDB, 0xE4, 0x01, 0x01, 0x60, 0x0A, 0x61, + 0x00, 0x64, 0xA1, 0xDB, 0xDF, 0x01, 0xC2, 0x60, 0x8F, 0x64, 0x40, 0x45, 0x22, 0x00, 0x01, 0x60, + 0x0A, 0x66, 0xA6, 0xD3, 0x04, 0xA1, 0x60, 0x43, 0xA1, 0xD3, 0xC9, 0x81, 0x60, 0x45, 0x00, 0xBB, + 0xA1, 0xDB, 0xBE, 0xD3, 0x09, 0x03, 0xD4, 0x84, 0x9C, 0x84, 0xDC, 0x84, 0xFF, 0xFF, 0x04, 0x0E, + 0xA3, 0xD1, 0x63, 0x46, 0x64, 0x43, 0xF2, 0x01, 0x9C, 0x84, 0xDC, 0x85, 0x49, 0xDD, 0x61, 0x44, + 0x00, 0xBB, 0xA6, 0xDB, 0x02, 0x03, 0x65, 0x44, 0xBE, 0xDB, 0xBC, 0x01, 0xC2, 0x60, 0x6A, 0x64, + 0x40, 0x45, 0x01, 0x60, 0x0A, 0x66, 0xA6, 0xD3, 0xFF, 0xFF, 0xD0, 0x80, 0x0F, 0x18, 0x02, 0x03, + 0x60, 0x46, 0xF9, 0x01, 0x58, 0xD3, 0xA4, 0xD3, 0x60, 0x45, 0x00, 0x63, 0xA4, 0xDD, 0x05, 0x18, + 0x58, 0xD3, 0xFF, 0xFF, 0xC4, 0x83, 0xA2, 0xDD, 0xCA, 0x84, 0xA6, 0xDB, 0x25, 0x58, 0x64, 0x41, + 0x04, 0x60, 0x40, 0x62, 0x1A, 0x60, 0x58, 0x4D, 0xB4, 0x78, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, + 0x64, 0x40, 0x01, 0x2B, 0x50, 0x00, 0x28, 0x40, 0x08, 0x3A, 0x4D, 0x00, 0xE8, 0x84, 0xE8, 0x84, + 0xE8, 0x84, 0xE8, 0x84, 0x15, 0x60, 0xD5, 0xFB, 0x64, 0xF1, 0x24, 0x60, 0x88, 0x63, 0x64, 0x40, + 0x01, 0x27, 0x3C, 0xA3, 0x29, 0x40, 0x40, 0x2B, 0x1E, 0xA3, 0xBD, 0xD1, 0x63, 0x45, 0x44, 0x4E, + 0x0E, 0x61, 0xBD, 0xD1, 0xCD, 0x81, 0xD0, 0x80, 0x01, 0x03, 0xFB, 0x04, 0xCB, 0x83, 0x15, 0x60, + 0xD8, 0xF3, 0x39, 0xF1, 0xD7, 0x83, 0xEB, 0x83, 0x2E, 0x41, 0x5D, 0x93, 0xDF, 0x83, 0x15, 0x60, + 0xD4, 0xFD, 0x15, 0x60, 0xD3, 0xFB, 0x53, 0x93, 0xDF, 0x80, 0x10, 0x03, 0x38, 0xF3, 0xCF, 0x83, + 0x08, 0x03, 0xDF, 0x83, 0x0B, 0x02, 0xDF, 0x83, 0xDC, 0x84, 0xF0, 0xA0, 0x38, 0xFB, 0x06, 0x03, + 0x03, 0x00, 0xCC, 0x84, 0x38, 0xFB, 0x02, 0x03, 0x00, 0x63, 0x02, 0x00, 0x08, 0x64, 0x38, 0xFB, + 0xE3, 0x80, 0xFB, 0x83, 0xC3, 0x83, 0x63, 0x44, 0xFC, 0xA0, 0x02, 0x0E, 0x08, 0x07, 0x08, 0x00, + 0x04, 0xA4, 0xFF, 0xFF, 0x05, 0x0D, 0xFC, 0x64, 0xFF, 0x7F, 0x60, 0x43, 0x01, 0x00, 0x04, 0x63, + 0x39, 0xFD, 0x15, 0x60, 0xD7, 0xFD, 0x2F, 0x58, 0xFF, 0xFF, 0x15, 0x60, 0xD2, 0xF3, 0x40, 0x4E, + 0x60, 0x46, 0x2F, 0xDB, 0x44, 0x44, 0xA1, 0xD3, 0xD9, 0x81, 0x48, 0x94, 0x24, 0x5C, 0xD0, 0x9C, + 0x66, 0x42, 0x04, 0x06, 0xD2, 0x9C, 0x2F, 0xD9, 0x64, 0x46, 0x24, 0x44, 0xE0, 0x84, 0x44, 0xD3, + 0xA3, 0xDB, 0xFF, 0xB4, 0x60, 0x5C, 0x66, 0x44, 0x22, 0xA4, 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, + 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0xA2, 0xD3, 0x60, 0x5C, 0x64, 0x5E, 0x60, 0x47, + 0x2F, 0xD1, 0x28, 0xA3, 0xA3, 0xD9, 0xD8, 0xA3, 0x2E, 0x42, 0x4E, 0x8E, 0xBD, 0xDB, 0xDB, 0x02, + 0x2D, 0x58, 0xFF, 0xFF, 0x43, 0xFF, 0x39, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x84, 0x3E, 0xFB, 0x01, + 0x3D, 0x44, 0x00, 0xA8, 0xFF, 0xFF, 0x03, 0x02, 0x40, 0xFF, 0x44, 0xFF, 0xF4, 0x01, 0xA0, 0x4C, + 0x3D, 0x46, 0x2A, 0xF2, 0x46, 0x4D, 0x10, 0x25, 0x12, 0x00, 0x09, 0xE1, 0xA1, 0xFF, 0x2D, 0x46, + 0x0F, 0xF2, 0x01, 0x29, 0x06, 0x00, 0x2A, 0xF0, 0x40, 0xFF, 0x64, 0x40, 0x40, 0x2B, 0x08, 0xBC, + 0x02, 0xBC, 0x0F, 0xFA, 0x08, 0x25, 0xDE, 0x01, 0xCB, 0xFE, 0x5C, 0x5D, 0xDC, 0x01, 0x44, 0xFF, + 0x03, 0x2B, 0x21, 0x00, 0x88, 0xF3, 0x06, 0x61, 0x60, 0x43, 0x66, 0x45, 0x31, 0xF0, 0x63, 0x46, + 0x05, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0x30, 0xF0, 0x0F, 0x02, 0x63, 0x46, 0x04, 0xF2, 0x65, 0x46, + 0xD0, 0x80, 0x2F, 0xF0, 0x09, 0x02, 0x63, 0x46, 0x03, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0xFF, 0xFF, + 0x03, 0x02, 0xFF, 0xFF, 0x48, 0xFE, 0x06, 0x00, 0xCD, 0x81, 0x02, 0xA3, 0xE7, 0x02, 0x87, 0xF1, + 0x08, 0xFE, 0x64, 0x43, 0x26, 0x03, 0x31, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, + 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, + 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, + 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, 0x60, 0x43, + 0x61, 0x46, 0x07, 0xFC, 0x3F, 0xF2, 0x09, 0x60, 0xB0, 0x65, 0xD4, 0x80, 0x2A, 0xF2, 0x9D, 0x05, + 0x08, 0x25, 0x88, 0x01, 0x5C, 0x4B, 0x0C, 0x60, 0xEC, 0x61, 0xA1, 0xDF, 0x2D, 0x46, 0x3B, 0xF2, + 0x87, 0xF1, 0x87, 0xF4, 0x60, 0x40, 0x20, 0x2B, 0xB7, 0x00, 0xD3, 0x80, 0x2C, 0xF0, 0x8D, 0x03, + 0x07, 0xF4, 0x64, 0x40, 0x01, 0x26, 0x87, 0xF5, 0xBA, 0xF4, 0x2D, 0x46, 0x04, 0x64, 0x04, 0xB3, + 0x22, 0xF0, 0x04, 0x03, 0xC5, 0x60, 0xBD, 0x78, 0xFF, 0xFF, 0xA6, 0x00, 0x10, 0x64, 0xB0, 0x9C, + 0x3B, 0xF2, 0x22, 0xF8, 0x60, 0x47, 0xC0, 0xB7, 0x02, 0xFE, 0xF0, 0x84, 0xF0, 0x84, 0xF0, 0x84, + 0x00, 0xA8, 0x40, 0x4A, 0x17, 0x03, 0xE0, 0x81, 0x61, 0x43, 0x42, 0xFE, 0x00, 0x64, 0xF0, 0x84, + 0xFE, 0x1F, 0x40, 0x4A, 0xE1, 0x84, 0xE0, 0x84, 0x2D, 0x46, 0x07, 0xF4, 0xE0, 0x81, 0x3B, 0xF0, + 0x2A, 0x47, 0x0C, 0x60, 0x3A, 0x63, 0xA0, 0x84, 0x47, 0x9C, 0x10, 0x03, 0x7C, 0x44, 0x00, 0x60, + 0xB2, 0x63, 0x14, 0x00, 0x07, 0xF4, 0x3B, 0xF0, 0x66, 0x44, 0x64, 0x40, 0x80, 0x2B, 0x06, 0x00, + 0x00, 0x60, 0x78, 0x7C, 0x00, 0x60, 0xA2, 0x63, 0x43, 0x4C, 0x08, 0x00, 0x2D, 0x46, 0xC5, 0x60, + 0xB0, 0x78, 0xFF, 0xFF, 0x2D, 0x46, 0xC5, 0x60, 0xB0, 0x78, 0xFF, 0xFF, 0xCE, 0xFB, 0xCF, 0xF9, + 0xD0, 0xFD, 0xAD, 0x46, 0x3D, 0xF2, 0xAD, 0x46, 0xA3, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3C, 0xF2, + 0xAD, 0x46, 0x02, 0x03, 0x15, 0x07, 0xEE, 0x04, 0x5B, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3A, 0xF2, + 0x03, 0x03, 0xAD, 0x46, 0x0D, 0x07, 0xE6, 0x04, 0x3A, 0xF0, 0xAD, 0x46, 0x5B, 0xD0, 0x64, 0x44, + 0xD0, 0x80, 0x2B, 0x44, 0x05, 0x07, 0xDE, 0x03, 0xD0, 0x84, 0x10, 0xA4, 0xFF, 0xFF, 0x00, 0x07, + 0xCF, 0xF3, 0xCE, 0xF5, 0xFE, 0xA4, 0x0F, 0x60, 0xC0, 0x61, 0x0E, 0x63, 0x58, 0xD0, 0x59, 0xD9, + 0xFD, 0x1F, 0x2D, 0x46, 0x8B, 0xFF, 0x2D, 0x46, 0x0F, 0x60, 0xB2, 0x64, 0xC9, 0x60, 0x58, 0x4F, + 0x10, 0x78, 0xFF, 0xFF, 0x3F, 0xF2, 0x00, 0x60, 0x18, 0x70, 0x18, 0x71, 0x20, 0x72, 0x60, 0x53, + 0x88, 0x75, 0x00, 0xF2, 0x09, 0xE1, 0x60, 0x50, 0x12, 0x71, 0x6E, 0x72, 0x83, 0x75, 0xA1, 0xFF, + 0xFF, 0xFF, 0x08, 0x25, 0x1F, 0x00, 0x40, 0xFF, 0x02, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x75, 0x40, + 0x03, 0x2A, 0x03, 0x00, 0x80, 0x75, 0x0A, 0x64, 0x0B, 0x00, 0x80, 0x75, 0x1B, 0xF3, 0x8B, 0xFF, + 0x02, 0x60, 0x00, 0x75, 0xFF, 0xFF, 0x02, 0x60, 0x00, 0x75, 0xDC, 0x84, 0xA2, 0xDB, 0x02, 0x64, + 0x98, 0xFF, 0x2D, 0x46, 0x0F, 0xF0, 0xFF, 0xFF, 0xB0, 0x84, 0xA2, 0xDA, 0x88, 0xFF, 0xC3, 0x60, + 0x74, 0x78, 0xFF, 0xFF, 0x8B, 0xFF, 0x02, 0x60, 0x00, 0x75, 0xFF, 0xFF, 0x02, 0x60, 0x00, 0x75, + 0x88, 0xFF, 0xC5, 0x60, 0x96, 0x78, 0xFF, 0xFF, 0x22, 0xF0, 0x22, 0x64, 0xB0, 0x84, 0x22, 0xFA, + 0x3A, 0xF0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, + 0xA0, 0x5B, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0x7C, 0x5F, 0xE8, 0x84, 0xE8, 0x85, + 0x0D, 0x60, 0x02, 0x64, 0x44, 0xD3, 0x5A, 0xD1, 0x03, 0x1B, 0xC5, 0x60, 0xB0, 0x78, 0xFF, 0xFF, + 0x60, 0x45, 0x64, 0x44, 0xE3, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, + 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, + 0xE7, 0x7F, 0xA0, 0x5B, 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, + 0xA0, 0x5B, 0x64, 0x44, 0xE9, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, + 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, + 0xED, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xEF, 0x7F, + 0xA0, 0x5B, 0x65, 0x44, 0xD8, 0x84, 0x08, 0x25, 0xB9, 0x00, 0x60, 0x7F, 0xA0, 0x5B, 0x80, 0x60, + 0x00, 0xEB, 0xA0, 0x60, 0x00, 0xEB, 0xD1, 0x60, 0x00, 0xEB, 0x3F, 0xF2, 0x3B, 0xF0, 0x60, 0x43, + 0xFC, 0xA4, 0x64, 0x40, 0x20, 0x2B, 0x03, 0x00, 0x08, 0xA4, 0x3F, 0xFA, 0x08, 0xA3, 0xF8, 0xA3, + 0x3F, 0xFA, 0x0A, 0xE1, 0xB3, 0xFF, 0x9A, 0xFF, 0xCB, 0x83, 0x00, 0xF4, 0x10, 0x62, 0x6C, 0x61, + 0x0E, 0xA3, 0xAB, 0x84, 0xF2, 0xA3, 0xA1, 0xFF, 0x08, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0x6C, 0x18, + 0x02, 0x62, 0xC9, 0x81, 0xAB, 0x84, 0x01, 0x00, 0xA2, 0xDC, 0x7A, 0xD4, 0xFD, 0x1C, 0xA2, 0xDC, + 0x08, 0x25, 0x8C, 0x00, 0xF2, 0x1D, 0x41, 0x44, 0x7C, 0xA8, 0xD9, 0x81, 0xEE, 0x03, 0xFF, 0xB1, + 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x08, 0x25, 0x80, 0x00, 0x40, 0xFF, 0x42, 0x42, + 0x46, 0x43, 0x06, 0x1E, 0x04, 0x02, 0x00, 0xF4, 0x02, 0x62, 0x42, 0x42, 0x46, 0x43, 0x01, 0xA2, + 0x63, 0x45, 0x01, 0xA2, 0x62, 0x43, 0x46, 0x4C, 0xC6, 0x60, 0x58, 0x4F, 0x4B, 0x78, 0xFF, 0xFF, + 0x0A, 0xE1, 0x9A, 0xFF, 0x24, 0x41, 0x02, 0xA1, 0x65, 0x43, 0x08, 0xA3, 0x23, 0x46, 0x22, 0x42, + 0x7E, 0x3A, 0x0A, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0x37, 0x18, 0x02, 0x62, 0xC9, 0x81, 0xAB, 0x84, + 0x03, 0x00, 0xA2, 0xDC, 0x7E, 0x36, 0xF6, 0x01, 0x7A, 0xD4, 0xFF, 0xFF, 0xFA, 0x1C, 0xA2, 0xDC, + 0xF1, 0x1D, 0xD9, 0x81, 0xFF, 0xB1, 0x0B, 0x1E, 0x62, 0x40, 0x7E, 0x3A, 0x02, 0x00, 0x00, 0xF4, + 0x02, 0x62, 0x5A, 0xD2, 0x89, 0xFF, 0x80, 0x4F, 0x6F, 0x44, 0xA2, 0xDA, 0x88, 0xFF, 0x98, 0xFF, + 0x3D, 0x46, 0x0F, 0xF0, 0x0A, 0x64, 0xB0, 0x84, 0x18, 0x14, 0xF7, 0xB4, 0xA2, 0xDA, 0x06, 0x60, + 0x76, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x0C, 0x00, 0xD1, 0xF5, 0xD0, 0xF4, 0x0C, 0x60, + 0xEC, 0x61, 0x59, 0xD1, 0x3B, 0xF8, 0x05, 0x64, 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, 0xFC, 0x02, + 0x2D, 0x46, 0xC3, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0x28, 0x00, 0xA2, 0xDA, 0x2D, 0x46, 0x3B, 0xF0, + 0xFF, 0xFF, 0x64, 0x40, 0x20, 0x2B, 0x1E, 0x00, 0x07, 0xF4, 0xBB, 0xF0, 0x2A, 0x44, 0xA4, 0x84, + 0xFF, 0xFF, 0x2F, 0x26, 0x16, 0x00, 0x2D, 0x46, 0x64, 0x44, 0x3A, 0xF0, 0xBC, 0xF0, 0x64, 0x5F, + 0x3D, 0xF0, 0x07, 0xF4, 0xD0, 0xF4, 0xFF, 0xFF, 0x08, 0xA3, 0x5B, 0xD8, 0x65, 0x5C, 0x5B, 0xD8, + 0x5B, 0xDA, 0x2D, 0x46, 0xCE, 0xF3, 0x3C, 0xFA, 0xCF, 0xF3, 0x3D, 0xFA, 0x2A, 0x44, 0x23, 0xFA, + 0x01, 0x00, 0x2D, 0x46, 0xC3, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0x98, 0xFF, 0x43, 0xFF, + 0x40, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, 0x2D, 0x46, 0x0C, 0x60, 0xEC, 0x61, 0xA1, 0xD3, 0x2D, 0x46, + 0x60, 0x40, 0x01, 0x2A, 0x0A, 0x00, 0xD1, 0xF5, 0xD0, 0xF4, 0x59, 0xD1, 0x3B, 0xF8, 0x05, 0x64, + 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, 0xFC, 0x02, 0x2D, 0x46, 0xC3, 0x60, 0x53, 0x78, 0xFF, 0xFF, + 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, 0x3D, 0x46, 0x08, 0x25, 0xE0, 0x01, 0x0F, 0xF2, 0x40, 0xFF, + 0x02, 0xBC, 0xA2, 0xDA, 0xC3, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0xB0, 0x84, 0x22, 0xFA, 0x00, 0x63, + 0x3B, 0xF2, 0x06, 0x60, 0x76, 0xFD, 0x60, 0x47, 0xC0, 0xB7, 0x02, 0xFE, 0xF0, 0x84, 0xF0, 0x84, + 0xF0, 0x84, 0x00, 0xA8, 0x40, 0x4A, 0x16, 0x03, 0xE0, 0x81, 0x61, 0x43, 0x42, 0xFE, 0x00, 0x64, + 0xF0, 0x84, 0xFE, 0x1F, 0x40, 0x4A, 0xE1, 0x84, 0xE0, 0x84, 0x2D, 0x46, 0x07, 0xF4, 0xE0, 0x81, + 0x3B, 0xF0, 0x2A, 0x47, 0x0C, 0x60, 0x3A, 0x63, 0xA0, 0x84, 0x47, 0x9C, 0x10, 0x03, 0x7C, 0x44, + 0xA8, 0x63, 0x0F, 0x00, 0x07, 0xF4, 0x20, 0x64, 0x40, 0x4A, 0x3B, 0xF0, 0x66, 0x44, 0x64, 0x40, + 0x80, 0x2B, 0x05, 0x00, 0x00, 0x60, 0x78, 0x7C, 0x00, 0x60, 0x98, 0x63, 0x02, 0x00, 0x2D, 0x46, + 0xBF, 0x01, 0x2D, 0x46, 0xCE, 0xFB, 0xCF, 0xF9, 0xD0, 0xFD, 0x07, 0xF2, 0xD1, 0xFB, 0x60, 0x46, + 0x3B, 0xF0, 0x2A, 0x44, 0x06, 0x60, 0x77, 0xF9, 0x5C, 0x4B, 0xA0, 0x84, 0xFF, 0xFF, 0x3F, 0x22, + 0x05, 0x00, 0x90, 0x84, 0x3B, 0xFA, 0x01, 0x64, 0x40, 0x4B, 0x21, 0x00, 0xAD, 0x46, 0x0A, 0xA3, + 0x3D, 0xF2, 0xAD, 0x46, 0xA3, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3C, 0xF2, 0xAD, 0x46, 0x02, 0x03, + 0x16, 0x07, 0x14, 0x04, 0x5B, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3B, 0xF2, 0x03, 0x03, 0xAD, 0x46, + 0x0E, 0x07, 0x0C, 0x04, 0x3A, 0xF0, 0xAD, 0x46, 0x5B, 0xD0, 0x64, 0x5F, 0xD0, 0x80, 0x2B, 0x44, + 0x17, 0x07, 0x04, 0x03, 0xD0, 0x84, 0x10, 0xA4, 0xFF, 0xFF, 0x12, 0x07, 0x89, 0x01, 0x01, 0x64, + 0x06, 0x60, 0x76, 0xFB, 0x2D, 0x46, 0x0C, 0x60, 0xFC, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, + 0xA2, 0xDB, 0xC6, 0x60, 0x76, 0x78, 0xFF, 0xFF, 0x85, 0xFF, 0x2D, 0x46, 0x08, 0x25, 0x5E, 0x01, + 0x2D, 0x46, 0x0C, 0x60, 0xFC, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC6, 0x60, + 0xFE, 0x78, 0xFF, 0xFF, 0x85, 0xFF, 0x2D, 0x46, 0x08, 0x25, 0x50, 0x01, 0x00, 0x60, 0x0F, 0x64, + 0xC4, 0x60, 0xDB, 0x78, 0xFF, 0xFF, 0x2D, 0x46, 0x3B, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x20, 0x2B, + 0x23, 0x00, 0x00, 0xF4, 0x08, 0x61, 0x2D, 0x46, 0x00, 0xF4, 0x0A, 0x62, 0x56, 0x92, 0x5A, 0xD0, + 0x2C, 0x46, 0x64, 0x47, 0x63, 0x40, 0x7F, 0x2A, 0x03, 0x00, 0x00, 0xF4, 0x03, 0x63, 0x46, 0x4C, + 0x60, 0xFE, 0xDE, 0xD8, 0x7F, 0x3A, 0x03, 0x00, 0x00, 0xF4, 0x03, 0x63, 0x46, 0x4C, 0xDE, 0xDA, + 0xFE, 0xA1, 0x20, 0xFE, 0xE8, 0x02, 0x63, 0x41, 0xFD, 0xA1, 0x46, 0x4C, 0x01, 0xF2, 0x2D, 0x46, + 0x61, 0x5E, 0x16, 0xFA, 0x2C, 0x44, 0x06, 0xFA, 0x2F, 0x58, 0xFF, 0xFF, 0x07, 0xF4, 0x66, 0x41, + 0x03, 0xF2, 0x04, 0xF2, 0x40, 0x42, 0x05, 0xF2, 0x40, 0x43, 0x40, 0x44, 0x61, 0x46, 0x3C, 0xF2, + 0x3D, 0xF2, 0x40, 0x40, 0x40, 0x41, 0x0D, 0x60, 0x72, 0x65, 0x00, 0x61, 0xCF, 0xF1, 0xCE, 0xF5, + 0x44, 0x4C, 0x2C, 0x5C, 0xE9, 0x80, 0x00, 0x64, 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, + 0x24, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x20, 0x44, 0x40, 0x80, 0xDB, 0x83, 0xBD, 0xD2, + 0x20, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x21, 0x44, 0x40, 0x81, 0xDB, 0x83, 0xBD, 0xD2, + 0x21, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x22, 0x44, 0x40, 0x82, 0xDB, 0x83, 0xBD, 0xD2, + 0x22, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x23, 0x44, 0x40, 0x83, 0xF2, 0xA3, 0xBD, 0xD2, + 0x23, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x24, 0x44, 0xC0, 0x9C, 0x41, 0x84, 0xDD, 0x81, + 0x08, 0x2A, 0xA7, 0x01, 0x0C, 0x60, 0xEE, 0x61, 0x05, 0x64, 0xD0, 0xF4, 0xD1, 0xF5, 0xFE, 0xA3, + 0x5B, 0xD0, 0xCC, 0x84, 0x59, 0xD9, 0xFC, 0x02, 0xD0, 0xF3, 0xD1, 0xF5, 0x60, 0x42, 0x20, 0x44, + 0xA2, 0xDA, 0x21, 0x44, 0x5A, 0xDA, 0x22, 0x44, 0x5A, 0xDA, 0x23, 0x44, 0x5A, 0xDA, 0x24, 0x44, + 0x5A, 0xDA, 0x61, 0x46, 0x06, 0x60, 0x7E, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x41, 0xD0, 0xF3, + 0xD1, 0xF5, 0xA0, 0xD2, 0x5A, 0xD0, 0x40, 0x40, 0x44, 0x41, 0x5A, 0xD2, 0x5A, 0xD0, 0x40, 0x42, + 0x5A, 0xD0, 0x44, 0x43, 0x61, 0x46, 0xBA, 0xF0, 0x3B, 0xF2, 0x44, 0x44, 0x65, 0x5F, 0x40, 0x85, + 0xCF, 0xF4, 0xCE, 0xF5, 0x43, 0x4C, 0x0D, 0x60, 0x72, 0x65, 0xBD, 0xD2, 0x25, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x20, 0x44, 0x40, 0x80, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x21, 0x44, 0x40, 0x81, 0xBD, 0xD2, 0x21, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x22, 0x44, 0x40, 0x82, 0xBD, 0xD2, 0x22, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x23, 0x44, + 0x40, 0x83, 0xBD, 0xD2, 0x23, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x24, 0x44, 0x40, 0x84, + 0xBD, 0xD2, 0x24, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x25, 0x44, 0x40, 0x85, 0x61, 0x46, + 0x3A, 0xF0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, + 0xA0, 0x5B, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xCE, 0xF5, 0xBD, 0xD2, 0x25, 0x5C, + 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x20, 0x5C, 0x40, 0x80, 0x20, 0x44, 0xE4, 0x7F, 0xA0, 0x5B, + 0x20, 0x47, 0xE5, 0x7F, 0xA0, 0x5B, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, + 0x21, 0x5C, 0x40, 0x81, 0x21, 0x44, 0xE6, 0x7F, 0xA0, 0x5B, 0x21, 0x47, 0xE7, 0x7F, 0xA0, 0x5B, + 0x21, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x22, 0x5C, 0x40, 0x82, 0x22, 0x44, 0xE8, 0x7F, 0xA0, 0x5B, + 0x22, 0x47, 0xE9, 0x7F, 0xA0, 0x5B, 0x22, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x23, 0x5C, 0x40, 0x83, + 0x23, 0x44, 0xEA, 0x7F, 0xA0, 0x5B, 0x23, 0x47, 0xEB, 0x7F, 0xA0, 0x5B, 0x23, 0x44, 0xE8, 0x80, + 0xF8, 0x84, 0x24, 0x5C, 0x40, 0x84, 0x24, 0x44, 0xEC, 0x7F, 0xA0, 0x5B, 0x24, 0x47, 0xED, 0x7F, + 0xA0, 0x5B, 0x24, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x25, 0x5C, 0x40, 0x85, 0x25, 0x44, 0xEE, 0x7F, + 0xA0, 0x5B, 0x25, 0x47, 0xEF, 0x7F, 0xA0, 0x5B, 0x2C, 0x43, 0xA3, 0xD2, 0x25, 0x5C, 0x90, 0x81, + 0xE9, 0x84, 0xE3, 0x7F, 0xA0, 0x5B, 0x06, 0x60, 0x7E, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0xF3, + 0x5A, 0xD3, 0x40, 0x48, 0x5A, 0xD3, 0x40, 0x49, 0x40, 0x4A, 0x00, 0x60, 0x78, 0x7C, 0x44, 0x4D, + 0x49, 0xF2, 0x4A, 0xF2, 0x40, 0x47, 0x40, 0x46, 0x0D, 0x60, 0x72, 0x65, 0x00, 0x61, 0x2D, 0x5C, + 0xE9, 0x80, 0x00, 0x64, 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, 0x2A, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x26, 0x44, 0x40, 0x86, 0xDB, 0x83, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x27, 0x44, 0x40, 0x87, 0xDB, 0x83, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x28, 0x44, 0x40, 0x88, 0xDB, 0x83, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x29, 0x44, 0x40, 0x89, 0xF2, 0xA3, 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x2A, 0x44, 0xC0, 0x9C, 0x41, 0x8A, 0xDD, 0x81, 0x08, 0x2A, 0xA7, 0x01, + 0x26, 0x44, 0x44, 0xFA, 0x27, 0x44, 0x45, 0xFA, 0x28, 0x44, 0x46, 0xFA, 0x29, 0x44, 0x47, 0xFA, + 0x2A, 0x44, 0x48, 0xFA, 0x06, 0x60, 0x7F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x88, 0x7C, + 0x44, 0x4D, 0x2D, 0x42, 0xA2, 0xD2, 0x5A, 0xD0, 0x40, 0x46, 0x44, 0x47, 0x5A, 0xD2, 0x5A, 0xD0, + 0x40, 0x48, 0x5A, 0xD0, 0x44, 0x49, 0x4B, 0xF2, 0x44, 0x4A, 0x40, 0x8B, 0x60, 0x5C, 0x64, 0x47, + 0xE0, 0x7F, 0xA0, 0x5A, 0xFF, 0xB4, 0x20, 0xBC, 0x7F, 0xB4, 0xE1, 0x7F, 0xA0, 0x5A, 0x64, 0x44, + 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, 0x78, 0x63, 0x0D, 0x60, 0x72, 0x65, 0xBD, 0xD2, 0x2B, 0x5C, + 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x26, 0x44, 0x40, 0x86, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x27, 0x44, 0x40, 0x87, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x28, 0x44, 0x40, 0x88, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x29, 0x44, 0x40, 0x89, 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2A, 0x44, + 0x40, 0x8A, 0xBD, 0xD2, 0x2A, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2B, 0x44, 0x40, 0x8B, + 0xBD, 0xD2, 0x2B, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x26, 0x5C, 0x40, 0x86, 0x26, 0x44, + 0xE4, 0x7F, 0xA0, 0x5A, 0x26, 0x47, 0xE5, 0x7F, 0xA0, 0x5A, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x84, + 0xE8, 0x80, 0xF8, 0x84, 0x27, 0x5C, 0x40, 0x87, 0x27, 0x44, 0xE6, 0x7F, 0xA0, 0x5A, 0x27, 0x47, + 0xE7, 0x7F, 0xA0, 0x5A, 0x27, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x28, 0x5C, 0x40, 0x88, 0x28, 0x44, + 0xE8, 0x7F, 0xA0, 0x5A, 0x28, 0x47, 0xE9, 0x7F, 0xA0, 0x5A, 0x28, 0x44, 0xE8, 0x80, 0xF8, 0x84, + 0x29, 0x5C, 0x40, 0x89, 0x29, 0x44, 0xEA, 0x7F, 0xA0, 0x5A, 0x29, 0x47, 0xEB, 0x7F, 0xA0, 0x5A, + 0x29, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x2A, 0x5C, 0x40, 0x8A, 0x2A, 0x44, 0xEC, 0x7F, 0xA0, 0x5A, + 0x2A, 0x47, 0xED, 0x7F, 0xA0, 0x5A, 0x2A, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x2B, 0x5C, 0x40, 0x8B, + 0x2B, 0x44, 0xEE, 0x7F, 0xA0, 0x5A, 0x2B, 0x47, 0xEF, 0x7F, 0xA0, 0x5A, 0x3C, 0xF0, 0x2B, 0x44, + 0x90, 0x84, 0xE8, 0x84, 0xE3, 0x7F, 0xA0, 0x5A, 0x06, 0x60, 0x7F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, + 0x60, 0x45, 0x00, 0xF0, 0x84, 0x60, 0x00, 0xE3, 0x04, 0x71, 0x64, 0x50, 0x01, 0x2A, 0x04, 0x71, + 0x5C, 0x61, 0x04, 0x63, 0x59, 0xD0, 0x58, 0xD9, 0xFD, 0x1F, 0x3D, 0xF2, 0x60, 0x43, 0x60, 0x47, + 0x5B, 0xDB, 0x3C, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x5B, 0xDB, 0x3A, 0xF2, 0xFF, 0xFF, 0x60, 0x47, + 0x5B, 0xDB, 0x3F, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x5B, 0xDB, 0x81, 0x60, 0x18, 0xE3, 0x65, 0x43, + 0xE3, 0x84, 0x60, 0x47, 0x00, 0x7F, 0x60, 0x50, 0x7F, 0x64, 0x23, 0x94, 0x60, 0x51, 0x7C, 0x72, + 0x04, 0x75, 0x0C, 0x60, 0x16, 0x61, 0x16, 0x60, 0x00, 0x63, 0x59, 0xDD, 0x2A, 0xF2, 0x87, 0x60, + 0x8F, 0x65, 0xA4, 0x87, 0x40, 0xBF, 0x59, 0xDB, 0x56, 0x64, 0x0A, 0x63, 0x58, 0xD0, 0x59, 0xD9, + 0xFD, 0x1F, 0x62, 0x64, 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x35, 0xF2, 0x0F, 0x65, + 0xA4, 0x9C, 0x59, 0xD9, 0x06, 0x63, 0x59, 0xDF, 0xFE, 0x1F, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x45, + 0x03, 0x2B, 0x05, 0x00, 0x6A, 0x64, 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x65, 0x40, + 0x8F, 0xB0, 0x88, 0x3A, 0x02, 0x00, 0x39, 0xF0, 0x59, 0xD9, 0x2F, 0x58, 0xFF, 0xFF, 0x0C, 0x60, + 0x16, 0x61, 0xA3, 0x46, 0x00, 0xF4, 0x02, 0x64, 0x0A, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, + 0x59, 0xDF, 0x59, 0xDF, 0xA0, 0x4C, 0x04, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0x23, 0x44, 0x01, 0xA7, + 0x80, 0xBF, 0x60, 0x50, 0x80, 0x60, 0x38, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x01, 0x76, 0xFF, 0xFF, + 0x76, 0x44, 0x01, 0x3A, 0xFD, 0x01, 0x40, 0x76, 0x42, 0xFF, 0xFF, 0xFF, 0x40, 0x76, 0x80, 0x60, + 0x18, 0x70, 0x80, 0x60, 0x18, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x80, 0x60, 0x10, 0x73, 0x02, 0x76, + 0x76, 0x44, 0xFF, 0xFF, 0x76, 0x44, 0x02, 0x3A, 0xFD, 0x01, 0x40, 0x76, 0x42, 0xFF, 0x3C, 0x46, + 0x00, 0xF2, 0x80, 0x60, 0x00, 0xBC, 0x60, 0x50, 0x80, 0x60, 0x12, 0x71, 0x80, 0x60, 0x6E, 0x72, + 0x3F, 0xF2, 0xFF, 0xFF, 0xF8, 0xA7, 0x80, 0xBF, 0x60, 0x53, 0x04, 0x76, 0xFF, 0xFF, 0x88, 0xFF, + 0x3C, 0x46, 0x07, 0xF2, 0xFF, 0xFF, 0x40, 0x43, 0xA3, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x77, 0x40, + 0x8B, 0xFF, 0xA0, 0x4C, 0x04, 0xE1, 0xFF, 0xFF, 0x76, 0x44, 0x04, 0x3A, 0xFD, 0x01, 0x40, 0x76, + 0x42, 0xFF, 0xFF, 0xFF, 0x10, 0x76, 0xFF, 0xFF, 0x76, 0x44, 0x20, 0x3A, 0xFD, 0x01, 0x40, 0x76, + 0x42, 0xFF, 0xA0, 0x48, 0x00, 0x7F, 0xA0, 0x51, 0x02, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xA0, 0x4C, + 0xFB, 0xB4, 0xA0, 0x51, 0x06, 0x60, 0x1F, 0xE1, 0x16, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, + 0x3F, 0xF2, 0xFF, 0xFF, 0xF8, 0xA4, 0x3F, 0xFA, 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, 0xA0, 0x48, + 0x08, 0x26, 0x07, 0x00, 0xA0, 0x4C, 0x04, 0xE1, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, + 0xA0, 0x51, 0x42, 0xFF, 0x26, 0x46, 0x8B, 0xFF, 0x02, 0x60, 0x00, 0x75, 0x3C, 0xF2, 0x40, 0x76, + 0x14, 0x1B, 0x26, 0x46, 0x3B, 0xF2, 0x0C, 0x60, 0xBC, 0x63, 0x60, 0x47, 0xC0, 0xB4, 0xE8, 0x84, + 0xE8, 0x84, 0xE8, 0x84, 0x43, 0x93, 0xE3, 0x9C, 0x64, 0x47, 0x80, 0x7C, 0x64, 0x5F, 0x60, 0x50, + 0x7F, 0x64, 0x23, 0x97, 0x80, 0xBF, 0x60, 0x51, 0x07, 0x00, 0x01, 0xA7, 0x80, 0xBF, 0x60, 0x50, + 0x80, 0x60, 0x40, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x01, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, + 0x0C, 0x21, 0xFC, 0x01, 0x04, 0x25, 0xD5, 0x01, 0x40, 0x76, 0x43, 0xFF, 0x0C, 0x60, 0x22, 0x61, + 0x26, 0x46, 0x00, 0xF4, 0x02, 0x64, 0x0A, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x59, 0xDF, + 0x59, 0xDF, 0x80, 0x60, 0x18, 0x70, 0x80, 0x60, 0x24, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x80, 0x60, + 0x10, 0x73, 0x02, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x0C, 0x21, 0xFC, 0x01, 0x04, 0x25, + 0xB8, 0x01, 0x40, 0x76, 0x43, 0xFF, 0x26, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x80, 0xBF, + 0x60, 0x50, 0x80, 0x60, 0x12, 0x71, 0x3F, 0xF2, 0x80, 0x60, 0x6E, 0x72, 0x60, 0x47, 0x80, 0xBF, + 0x60, 0x53, 0x04, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x0C, 0x21, 0xFC, 0x01, 0x04, 0x25, + 0xA0, 0x01, 0x40, 0x76, 0x43, 0xFF, 0x08, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x0C, 0x21, + 0xFC, 0x01, 0x04, 0x25, 0x96, 0x01, 0x76, 0x5C, 0xFF, 0xFF, 0x40, 0x76, 0x43, 0xFF, 0x88, 0xFF, + 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0xDF, 0x60, 0x2A, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x11, 0xF1, + 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x20, 0x00, 0x74, 0xF3, 0x31, 0x40, + 0x01, 0x2A, 0x1C, 0x00, 0xDC, 0x84, 0x01, 0xB4, 0x74, 0xFB, 0x08, 0x02, 0x08, 0x60, 0x12, 0xF1, + 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x00, 0x08, 0x60, 0x18, 0xF1, + 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x08, 0x00, 0xA9, 0xFE, 0xE6, 0x05, + 0xAB, 0xFE, 0x07, 0x05, 0xA8, 0xFE, 0xD7, 0x05, 0xAA, 0xFE, 0xD8, 0x05, 0xA1, 0xFF, 0xFF, 0xFF, + 0x85, 0x3E, 0x0F, 0x60, 0x85, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x03, 0x02, 0xCA, 0x60, + 0x7E, 0x78, 0xFF, 0xFF, 0x26, 0x45, 0xD4, 0x80, 0x0F, 0xF0, 0xF9, 0x03, 0x64, 0x44, 0x70, 0xB0, + 0x70, 0x2A, 0x13, 0x00, 0x13, 0x60, 0x08, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, + 0xA2, 0xDB, 0xA2, 0xFF, 0x8E, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0xFE, 0xA0, 0x8E, 0xFB, 0x01, 0x07, + 0xD4, 0xFE, 0xA3, 0xFF, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x64, 0x40, 0x02, 0x26, 0x09, 0x00, + 0x66, 0x45, 0x09, 0xF4, 0x0F, 0xF2, 0x02, 0x18, 0x65, 0x46, 0xE4, 0x1B, 0x00, 0x64, 0x40, 0x46, + 0xCD, 0x01, 0xA2, 0xFF, 0x8E, 0xF3, 0x46, 0x46, 0xCC, 0x84, 0xFE, 0xA0, 0x8E, 0xFB, 0x01, 0x07, + 0xD4, 0xFE, 0xA3, 0xFF, 0x0F, 0xF0, 0xA3, 0xFC, 0x64, 0x44, 0x80, 0x26, 0x17, 0x00, 0x25, 0x60, + 0xF0, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, + 0x07, 0x60, 0x01, 0x64, 0x04, 0x00, 0x02, 0x2A, 0x06, 0x00, 0x00, 0x60, 0x01, 0x64, 0x23, 0xFA, + 0xCE, 0x60, 0x44, 0x78, 0xFF, 0xFF, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, + 0x64, 0x44, 0x08, 0x26, 0x34, 0x00, 0x2A, 0xF2, 0x60, 0x63, 0x60, 0x40, 0x02, 0x2B, 0x66, 0x63, + 0xBE, 0xD2, 0x68, 0xF1, 0xA3, 0xD2, 0xD0, 0x80, 0x67, 0xF1, 0x0D, 0x02, 0xBF, 0xD2, 0xD0, 0x80, + 0x66, 0xF1, 0x09, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x06, 0x02, 0x25, 0x60, 0xFC, 0x64, 0xE5, 0x60, + 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, 0x07, 0x60, 0x02, 0x64, + 0x04, 0x00, 0x02, 0x2A, 0x06, 0x00, 0x00, 0x60, 0x02, 0x64, 0x23, 0xFA, 0xCE, 0x60, 0x44, 0x78, + 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0xB0, 0x3A, 0x06, 0x00, 0x00, 0x60, 0x02, 0x64, + 0x23, 0xFA, 0xCB, 0x60, 0x9D, 0x78, 0xFF, 0xFF, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x32, 0x44, + 0x01, 0x2A, 0x4A, 0x00, 0x27, 0x60, 0x6A, 0x63, 0xBF, 0xD3, 0x00, 0x65, 0xB4, 0x81, 0xDB, 0x83, + 0x3D, 0x03, 0xBF, 0xD3, 0xA3, 0xD3, 0x40, 0x48, 0xBE, 0xD3, 0x40, 0x4A, 0x2E, 0xF0, 0x40, 0x4C, + 0xD0, 0x80, 0x2D, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x2C, 0xF0, 0x04, 0x02, 0x28, 0x44, + 0xD0, 0x80, 0xFF, 0xFF, 0x2B, 0x03, 0x31, 0xF0, 0x2C, 0x44, 0xD0, 0x80, 0x30, 0xF0, 0x08, 0x02, + 0x2A, 0x44, 0xD0, 0x80, 0x2F, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x1E, 0x03, + 0x34, 0xF0, 0x2C, 0x44, 0xD0, 0x80, 0x33, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x32, 0xF0, + 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x11, 0x03, 0x38, 0xF0, 0x2C, 0x44, 0xD0, 0x80, + 0x37, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x36, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, + 0xFF, 0xFF, 0x04, 0x03, 0xFA, 0xA1, 0x06, 0xA3, 0xB7, 0x03, 0xC3, 0x01, 0x07, 0x60, 0x00, 0x64, + 0x23, 0xFA, 0xCE, 0x60, 0x44, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x0F, 0xF0, 0x60, 0x45, 0xA4, 0x36, + 0x08, 0x00, 0x0C, 0xB4, 0x04, 0x36, 0x02, 0x00, 0x0C, 0x3A, 0x06, 0x00, 0xCE, 0x60, 0x38, 0x78, + 0xFF, 0xFF, 0xCC, 0x60, 0x35, 0x78, 0xFF, 0xFF, 0x26, 0xF2, 0x50, 0xF1, 0x60, 0x47, 0x00, 0x7E, + 0xD0, 0x84, 0x1F, 0xA4, 0x06, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, + 0x07, 0x00, 0xC2, 0xA4, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x87, 0xF8, 0xBF, + 0xC0, 0x84, 0xA2, 0xDB, 0x0F, 0xF0, 0x65, 0x40, 0x40, 0x2B, 0x17, 0x00, 0x32, 0x40, 0x08, 0x26, + 0x14, 0x00, 0x07, 0xF4, 0x3A, 0xF2, 0xFF, 0xFF, 0x37, 0xB4, 0x26, 0x46, 0x0E, 0x02, 0x2C, 0xF2, + 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x06, 0x00, 0x25, 0x60, 0xF6, 0x64, 0xE5, 0x60, 0x78, 0x41, + 0xC7, 0x78, 0x97, 0xF1, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x64, 0x40, 0x60, 0x26, + 0x03, 0x00, 0xCC, 0x60, 0x0D, 0x78, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x3A, 0xF3, 0x01, 0x25, 0x60, + 0xEA, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x27, 0xF2, 0xFF, 0xFF, 0x60, 0x40, + 0x01, 0x3B, 0x07, 0x00, 0x25, 0x60, 0xF8, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, + 0x08, 0x00, 0x02, 0x3B, 0x06, 0x00, 0x25, 0x60, 0xFA, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, + 0x97, 0xF1, 0x2A, 0xF2, 0x28, 0x41, 0x40, 0xA8, 0x01, 0xB1, 0x02, 0x02, 0x43, 0x02, 0x6D, 0x00, + 0x60, 0x40, 0x08, 0x2A, 0x0F, 0x00, 0x25, 0x60, 0xE8, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, + 0x97, 0xF1, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, 0x25, 0x60, 0xEE, 0x64, 0xE5, 0x60, 0x78, 0x41, + 0xD3, 0x78, 0x97, 0xF1, 0x0F, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x26, 0x28, 0x00, 0x32, 0x44, + 0x02, 0x26, 0x25, 0x00, 0x10, 0x2B, 0x26, 0x00, 0x27, 0x60, 0x6A, 0x63, 0xBF, 0xD3, 0x2C, 0xF0, + 0x00, 0xA8, 0x60, 0x41, 0x0D, 0x03, 0x50, 0xFE, 0xBD, 0xD3, 0x2D, 0xF0, 0xD0, 0x80, 0xBD, 0xD3, + 0x2E, 0xF0, 0xD0, 0x80, 0xBD, 0xD3, 0x2C, 0xF0, 0xD0, 0x80, 0xFA, 0xA1, 0x10, 0x0C, 0xF3, 0x02, + 0x50, 0xFE, 0x60, 0x60, 0x01, 0x64, 0xD0, 0x80, 0x2D, 0xF0, 0x1D, 0x64, 0xD0, 0x80, 0x2E, 0xF0, + 0x01, 0x64, 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x0C, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x32, 0x40, + 0x40, 0x2A, 0x00, 0x00, 0xCD, 0x60, 0xEE, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x40, 0x26, 0xFA, 0x01, + 0x2A, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x08, 0x2A, 0x20, 0x00, 0x32, 0x40, 0x02, 0x2A, 0x1D, 0x00, + 0x03, 0x67, 0xA0, 0x84, 0x00, 0x37, 0x64, 0x63, 0x60, 0x40, 0x02, 0x37, 0x5E, 0x63, 0x60, 0x40, + 0x01, 0x37, 0x58, 0x63, 0x60, 0x40, 0x03, 0x37, 0x0D, 0x00, 0xBD, 0xD2, 0x66, 0xF1, 0xBD, 0xD2, + 0xD0, 0x80, 0x67, 0xF1, 0x07, 0x02, 0xD0, 0x80, 0xBD, 0xD2, 0x68, 0xF1, 0x03, 0x02, 0xD0, 0x80, + 0xFF, 0xFF, 0x03, 0x03, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x87, 0xF4, 0x60, 0x40, + 0x03, 0x2B, 0x31, 0x00, 0x88, 0xF3, 0x06, 0x61, 0x60, 0x43, 0x66, 0x45, 0x31, 0xF0, 0x63, 0x46, + 0x05, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0x30, 0xF0, 0x0F, 0x02, 0x63, 0x46, 0x04, 0xF2, 0x65, 0x46, + 0xD0, 0x80, 0x2F, 0xF0, 0x09, 0x02, 0x63, 0x46, 0x03, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0xFF, 0xFF, + 0x03, 0x02, 0xFF, 0xFF, 0x48, 0xFE, 0x06, 0x00, 0xCD, 0x81, 0x02, 0xA3, 0xE7, 0x02, 0x87, 0xF1, + 0x08, 0xFE, 0x64, 0x43, 0x03, 0x03, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x43, 0x43, 0x23, 0x46, + 0x06, 0xF0, 0x26, 0x46, 0x07, 0x67, 0xA0, 0x84, 0x23, 0xFA, 0x64, 0x40, 0x02, 0x26, 0x2B, 0x00, + 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x26, 0x1B, 0x31, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, + 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, + 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, + 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, + 0x60, 0x43, 0x61, 0x46, 0x43, 0x43, 0x07, 0xFC, 0x43, 0x43, 0x1D, 0xF0, 0xC0, 0x64, 0xC0, 0x84, + 0x0A, 0x60, 0x7B, 0xF1, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, + 0xA2, 0xDB, 0x63, 0x45, 0x2A, 0xF2, 0x35, 0xF0, 0x60, 0x40, 0xA4, 0x36, 0x0B, 0x00, 0x08, 0x2B, + 0x0C, 0x00, 0x23, 0x46, 0x26, 0xF2, 0x26, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x06, 0x02, 0xCE, 0x60, + 0x38, 0x78, 0xFF, 0xFF, 0xCD, 0x60, 0xEE, 0x78, 0xFF, 0xFF, 0x23, 0x46, 0x22, 0xF2, 0x26, 0x46, + 0x44, 0x4C, 0x0F, 0x26, 0x19, 0x00, 0x00, 0xBC, 0x40, 0x45, 0x0B, 0x03, 0x00, 0x64, 0x23, 0x46, + 0x22, 0xFA, 0x26, 0x46, 0xA2, 0xFF, 0xB6, 0x60, 0x58, 0x4E, 0x72, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, + 0x26, 0x46, 0x2A, 0xF0, 0x2C, 0x44, 0x64, 0x40, 0x04, 0x27, 0x06, 0x00, 0x23, 0x46, 0x26, 0xFA, + 0x26, 0x46, 0xCD, 0x60, 0xA5, 0x78, 0xFF, 0xFF, 0x3F, 0xF2, 0x02, 0xFA, 0xA2, 0xFF, 0x16, 0xF0, + 0xFF, 0xFF, 0x64, 0x44, 0x01, 0x26, 0xDC, 0x9C, 0x92, 0xF3, 0x2A, 0xF2, 0xDC, 0x83, 0x92, 0xFD, + 0x06, 0xF4, 0x01, 0xF8, 0x26, 0x46, 0x60, 0x40, 0x40, 0x2B, 0x18, 0x00, 0x64, 0x44, 0x00, 0x65, + 0xFF, 0xB4, 0xFC, 0xA4, 0x06, 0xF0, 0x03, 0x03, 0x64, 0x46, 0x0C, 0x0D, 0x02, 0x65, 0x26, 0x46, + 0x00, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x60, 0x46, 0xF9, 0x01, 0x01, 0xF2, + 0xFF, 0xFF, 0xD4, 0x84, 0x01, 0xFA, 0x66, 0x44, 0x26, 0x46, 0x06, 0xFA, 0x06, 0xF4, 0x00, 0xF2, + 0x80, 0xFC, 0x40, 0x45, 0xB6, 0x60, 0x58, 0x4E, 0x72, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x26, 0x46, + 0x2C, 0x44, 0x0F, 0x26, 0x0F, 0x00, 0x23, 0x46, 0x26, 0xFA, 0x26, 0x44, 0x22, 0xFA, 0x26, 0x46, + 0x00, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0x6E, 0x00, 0xA3, 0x46, 0x26, 0xF2, 0x60, 0x45, 0xDC, 0x84, 0xD4, 0x80, 0x26, 0xFA, + 0xA3, 0x46, 0x6B, 0x02, 0x2A, 0xF0, 0xA3, 0x46, 0x22, 0xF2, 0xA3, 0x46, 0x00, 0xBC, 0x00, 0xF2, + 0x01, 0x02, 0x63, 0x00, 0x44, 0x4C, 0x3F, 0xF0, 0x60, 0x43, 0x23, 0x46, 0x22, 0xF4, 0x09, 0x60, + 0x00, 0x65, 0x3F, 0xF2, 0x26, 0x46, 0xC0, 0x84, 0xD4, 0x80, 0x60, 0x45, 0x56, 0x07, 0x80, 0xFC, + 0x1B, 0xF2, 0x06, 0xF2, 0x60, 0x41, 0x23, 0x46, 0x22, 0xF4, 0x1B, 0xF0, 0x06, 0xF0, 0xC1, 0x81, + 0x06, 0xFA, 0x05, 0xFA, 0x9B, 0xFA, 0x65, 0x44, 0x3F, 0xFA, 0x64, 0x46, 0x00, 0xFC, 0x63, 0x46, + 0x01, 0xF2, 0x10, 0x61, 0xF2, 0xA4, 0x01, 0xFA, 0xC8, 0x83, 0x02, 0x64, 0x59, 0xD0, 0x58, 0xD8, + 0xFD, 0x1F, 0x06, 0x45, 0x00, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA2, 0xFF, 0x00, 0xF4, 0x01, 0xF0, 0x0A, 0x18, 0x70, 0x67, + 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, 0xC0, 0x84, 0x01, 0xFA, 0x25, 0x46, 0x25, 0x44, 0x80, 0xFC, + 0x05, 0xFA, 0xB6, 0x60, 0x58, 0x4E, 0x72, 0x78, 0xFF, 0xFF, 0xD4, 0xFE, 0xA3, 0xFF, 0x2C, 0x44, + 0x04, 0x27, 0x16, 0x00, 0x23, 0x46, 0x22, 0xF2, 0xA2, 0xFC, 0x60, 0x46, 0x46, 0x46, 0x3F, 0xF2, + 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, 0x26, 0x46, 0x2C, 0x43, 0x2A, 0xFC, 0x06, 0xF4, 0x00, 0x64, + 0x00, 0xFA, 0x01, 0xF0, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0x01, 0xFA, 0x26, 0x46, 0x1D, 0x00, + 0x00, 0x66, 0x46, 0x46, 0xCA, 0x60, 0x81, 0x78, 0xFF, 0xFF, 0xA3, 0x46, 0x22, 0xF0, 0xA2, 0xFC, + 0x00, 0x63, 0x33, 0x85, 0xA3, 0x46, 0x0D, 0x03, 0xA3, 0x46, 0x26, 0xF2, 0x0F, 0x65, 0xA4, 0x85, + 0xD4, 0x84, 0x26, 0xFA, 0xA3, 0x46, 0xA2, 0xFF, 0xB6, 0x60, 0x58, 0x4E, 0x72, 0x78, 0xFF, 0xFF, + 0xA3, 0xFF, 0x26, 0x46, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x32, 0xF0, 0x60, 0x40, + 0x08, 0x2A, 0x24, 0x00, 0x01, 0x2B, 0x13, 0x00, 0x64, 0x40, 0x01, 0x2A, 0x10, 0x00, 0x25, 0x60, + 0xE8, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, + 0x25, 0x60, 0xEE, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xD3, 0x78, 0x97, 0xF1, 0x0F, 0x00, 0x25, 0x60, + 0xE6, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, + 0x25, 0x60, 0xEC, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xD3, 0x78, 0x97, 0xF1, 0x07, 0xF4, 0xFF, 0xFF, + 0x26, 0xF2, 0x26, 0x46, 0x0F, 0xB4, 0xDC, 0x85, 0x25, 0x60, 0xEA, 0x64, 0xE5, 0x60, 0x78, 0x41, + 0xD3, 0x78, 0x97, 0xF1, 0x27, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x3B, 0x07, 0x00, 0x25, 0x60, + 0xF8, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x08, 0x00, 0x02, 0x3B, 0x06, 0x00, + 0x25, 0x60, 0xFA, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x07, 0xF2, 0x26, 0xF0, + 0x41, 0x18, 0x60, 0x46, 0xFF, 0x67, 0x20, 0x88, 0x64, 0x5F, 0x40, 0x4A, 0x15, 0xF0, 0x28, 0x44, + 0xD0, 0x84, 0x03, 0xA4, 0x03, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0x04, 0x00, 0xFA, 0xA4, 0xE8, 0x84, + 0xE8, 0x87, 0xC0, 0xBF, 0xC0, 0x84, 0x15, 0xFA, 0x40, 0x48, 0x14, 0xF0, 0x2A, 0x44, 0xD0, 0x84, + 0x1F, 0xA4, 0x06, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x07, 0x00, + 0xC2, 0xA4, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x87, 0xF8, 0xBF, 0xC0, 0x84, + 0x14, 0xFA, 0x2B, 0x60, 0xEC, 0x63, 0xBD, 0xDB, 0x60, 0x5C, 0x2F, 0x67, 0xD0, 0x80, 0x60, 0x45, + 0x02, 0x28, 0x64, 0x45, 0x28, 0x5C, 0xBD, 0xD9, 0x8B, 0x67, 0xD0, 0x80, 0x60, 0x41, 0x02, 0x24, + 0x64, 0x41, 0xD5, 0x84, 0x80, 0x65, 0xC4, 0x87, 0x01, 0x05, 0x00, 0x64, 0xFF, 0xB4, 0x0E, 0xFA, + 0xA3, 0xDB, 0x26, 0x46, 0xCE, 0x60, 0x7F, 0x78, 0xFF, 0xFF, 0xCA, 0x60, 0x81, 0x78, 0xFF, 0xFF, + 0x1F, 0x60, 0x20, 0x64, 0x40, 0x4B, 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, 0xFF, 0xFF, 0x00, 0x66, + 0x46, 0x46, 0xCA, 0x60, 0x81, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0x04, 0x64, 0x0F, 0x60, 0x90, 0xFB, + 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0x00, 0x66, + 0x46, 0x46, 0xCA, 0x60, 0x81, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x58, 0x63, 0x60, 0x47, 0x01, 0x27, + 0x64, 0x63, 0x61, 0x5C, 0x18, 0x60, 0x0F, 0xF9, 0xBD, 0xD0, 0xBD, 0xD0, 0x64, 0x45, 0x64, 0x41, + 0xBD, 0xD0, 0x00, 0xF4, 0x04, 0xF8, 0x83, 0xFA, 0x82, 0xF8, 0xA6, 0x46, 0x02, 0xB0, 0x5E, 0x63, + 0x04, 0x03, 0x64, 0x63, 0x03, 0xB0, 0x02, 0x3A, 0x6C, 0x63, 0x3F, 0xF2, 0xBD, 0xD0, 0xBD, 0xD0, + 0x64, 0x45, 0x64, 0x41, 0xBD, 0xD0, 0xA6, 0x46, 0x07, 0xF8, 0x86, 0xFA, 0x85, 0xF8, 0x60, 0x47, + 0x08, 0xFA, 0x18, 0x60, 0x0F, 0xF1, 0x26, 0x46, 0x64, 0x41, 0x2F, 0x58, 0xFF, 0xFF, 0x2A, 0xF2, + 0x2C, 0xF0, 0x31, 0x40, 0x20, 0x26, 0x09, 0x00, 0x60, 0x40, 0xA4, 0x36, 0x21, 0x00, 0x08, 0x26, + 0x07, 0x00, 0x7D, 0xF1, 0xCF, 0x60, 0x47, 0x78, 0xFF, 0xFF, 0xCF, 0x60, 0x77, 0x78, 0xFF, 0xFF, + 0x64, 0x40, 0x01, 0x26, 0x12, 0x00, 0x3F, 0xF0, 0x32, 0x40, 0x10, 0x2A, 0x0A, 0x00, 0x64, 0x41, + 0x60, 0x40, 0x40, 0x27, 0x06, 0x00, 0xCD, 0x81, 0xDD, 0x81, 0x03, 0x03, 0x02, 0x03, 0x01, 0x61, + 0x01, 0x00, 0x00, 0x61, 0x60, 0x40, 0x18, 0x3A, 0x03, 0x00, 0xCF, 0x60, 0xC9, 0x78, 0xFF, 0xFF, + 0x07, 0xF2, 0x87, 0xF1, 0x66, 0x45, 0xD0, 0x80, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x03, 0x03, + 0xFF, 0xFF, 0x02, 0x26, 0x07, 0x00, 0xDD, 0x60, 0x58, 0x4F, 0x90, 0x78, 0xFF, 0xFF, 0xCF, 0x60, + 0xC5, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0xA4, 0x3A, 0x07, 0x00, 0xDF, 0x60, + 0x58, 0x4F, 0xE3, 0x78, 0xFF, 0xFF, 0xCF, 0x60, 0xC5, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0xCE, 0x60, + 0x58, 0x4F, 0x54, 0x78, 0xFF, 0xFF, 0x3F, 0xF2, 0x06, 0x65, 0xD4, 0x80, 0x60, 0x43, 0x5B, 0x04, + 0x00, 0xF4, 0xAA, 0x60, 0xAA, 0x65, 0x09, 0xF2, 0x0A, 0xF0, 0xD4, 0x80, 0x03, 0x64, 0x53, 0x02, + 0xD0, 0x80, 0x00, 0x64, 0x0B, 0xF0, 0x4F, 0x02, 0x64, 0x45, 0xD4, 0x80, 0xF8, 0x7F, 0x08, 0x02, + 0x0C, 0xF0, 0x26, 0x46, 0x64, 0x45, 0x23, 0xF0, 0x20, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x0B, 0x00, + 0xD4, 0x80, 0x1D, 0x60, 0x60, 0x64, 0x11, 0x02, 0x0C, 0xF0, 0x26, 0x46, 0x64, 0x45, 0x23, 0xF0, + 0x40, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x65, 0x44, 0x88, 0x3A, 0x35, 0x00, 0x77, 0x37, 0x03, 0x00, + 0x78, 0x37, 0x01, 0x00, 0x8E, 0x37, 0x00, 0x61, 0x2E, 0x00, 0xD4, 0x80, 0x08, 0x65, 0x2B, 0x02, + 0xD7, 0x80, 0x01, 0x60, 0x00, 0x64, 0x0C, 0xF0, 0x26, 0x04, 0xD0, 0x80, 0x0D, 0xF0, 0x23, 0x02, + 0x26, 0x46, 0x14, 0xF2, 0x01, 0x63, 0x02, 0xA8, 0x64, 0x47, 0x1D, 0x03, 0x7F, 0xB4, 0xFD, 0xA0, + 0x06, 0x03, 0x19, 0x07, 0x23, 0xF0, 0x60, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x6B, 0x00, 0x26, 0x46, + 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x2A, 0x07, 0x00, 0x60, 0x40, 0x48, 0x36, 0x04, 0x00, + 0xD2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xD2, 0xFB, 0xE8, 0x60, 0x58, 0x4F, 0xEF, 0x78, 0xFF, 0xFF, + 0xCF, 0x60, 0xC5, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x61, 0x40, 0x01, 0x2A, 0x09, 0x00, 0x25, 0x60, + 0xFE, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0xCF, 0x60, 0xC9, 0x78, 0xFF, 0xFF, + 0xDF, 0x60, 0x58, 0x4F, 0xE3, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, 0x36, + 0x88, 0x00, 0xCF, 0x60, 0xD6, 0x78, 0xFF, 0xFF, 0xCF, 0x60, 0xC5, 0x78, 0xFF, 0xFF, 0x60, 0x40, + 0x0C, 0x26, 0x7F, 0x00, 0x64, 0x40, 0x01, 0x2A, 0x7C, 0x00, 0xB0, 0x3A, 0x05, 0x00, 0xD4, 0x60, + 0x58, 0x4F, 0x5A, 0x78, 0xFF, 0xFF, 0x71, 0x00, 0x00, 0x3A, 0x05, 0x00, 0xD7, 0x60, 0x58, 0x4F, + 0xCA, 0x78, 0xFF, 0xFF, 0x6A, 0x00, 0x20, 0x3A, 0x05, 0x00, 0xD7, 0x60, 0x58, 0x4F, 0xCA, 0x78, + 0xFF, 0xFF, 0x63, 0x00, 0xC0, 0x3A, 0x05, 0x00, 0xDC, 0x60, 0x58, 0x4F, 0xFE, 0x78, 0xFF, 0xFF, + 0x5C, 0x00, 0xA0, 0x3A, 0x05, 0x00, 0xDD, 0x60, 0x58, 0x4F, 0x5B, 0x78, 0xFF, 0xFF, 0x55, 0x00, + 0x40, 0x3A, 0x0D, 0x00, 0xE3, 0x60, 0x58, 0x4F, 0xC3, 0x78, 0xFF, 0xFF, 0x4E, 0x00, 0x60, 0x40, + 0x50, 0x3A, 0x05, 0x00, 0xED, 0x60, 0x58, 0x4F, 0xEB, 0x78, 0xFF, 0xFF, 0x46, 0x00, 0xCF, 0x60, + 0xC9, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x2A, 0x07, 0x00, + 0x60, 0x40, 0x48, 0x36, 0x04, 0x00, 0xD2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xD2, 0xFB, 0x2A, 0xF2, + 0x3B, 0xF0, 0x60, 0x40, 0x40, 0x2B, 0x04, 0x00, 0x64, 0x40, 0x20, 0x2B, 0x01, 0x00, 0x03, 0x00, + 0xCF, 0x60, 0xB9, 0x78, 0xFF, 0xFF, 0x22, 0xF2, 0xFF, 0xFF, 0x04, 0xB4, 0xFF, 0xFF, 0xF8, 0x03, + 0x23, 0xF2, 0x07, 0xF4, 0xBB, 0xF0, 0x26, 0x46, 0xA4, 0x84, 0xFF, 0xFF, 0x60, 0x40, 0x2F, 0x26, + 0x20, 0x00, 0xC9, 0x60, 0x58, 0x4F, 0xCF, 0x78, 0xFF, 0xFF, 0x64, 0x40, 0x18, 0x36, 0x09, 0x00, + 0x04, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0xCF, 0x60, 0xC9, 0x78, + 0xFF, 0xFF, 0x1F, 0x60, 0x04, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0x0C, 0x00, 0x66, 0x44, 0x00, 0xA8, 0xFF, 0xFF, + 0x0A, 0x03, 0x26, 0x46, 0x1F, 0x60, 0x20, 0x64, 0x40, 0x4B, 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, + 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xCE, 0x60, 0x35, 0x78, 0xFF, 0xFF, 0x14, 0xF2, 0x00, 0x7C, + 0x3E, 0xF8, 0xCC, 0x84, 0xCC, 0x84, 0x18, 0x03, 0x5C, 0x02, 0x11, 0xF2, 0x07, 0xFA, 0xAB, 0xF3, + 0x19, 0xFA, 0xD0, 0x60, 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xE0, 0x64, 0x0F, 0x60, + 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, + 0xF2, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x8D, 0x00, 0xA2, 0xFF, 0x46, 0x45, 0xB6, 0x60, 0x58, 0x4E, + 0xBB, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x11, 0x03, 0x7E, 0x63, 0x46, 0x4B, 0x25, 0x46, 0xA3, 0xD0, + 0x2B, 0x46, 0xA3, 0xD8, 0xFB, 0x1F, 0x89, 0xFC, 0x8A, 0xFC, 0x88, 0xFC, 0x05, 0x18, 0x64, 0x46, + 0x01, 0xF0, 0x10, 0x67, 0xC0, 0x84, 0x01, 0xFA, 0x08, 0xFE, 0x2B, 0x46, 0x46, 0x46, 0x25, 0x46, + 0xD0, 0x60, 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x13, 0x60, 0x43, 0xF3, 0x87, 0xF3, 0x00, 0xA8, + 0x07, 0xFA, 0x0E, 0x03, 0x1E, 0x60, 0xDA, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x25, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF3, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x0D, 0x00, + 0x1E, 0x60, 0xCE, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xF4, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x26, 0x44, 0x00, 0xA8, 0xC1, 0xFE, + 0x48, 0x03, 0x26, 0x46, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x2A, 0x07, 0x00, 0x60, 0x40, + 0x48, 0x36, 0x04, 0x00, 0xD2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xD2, 0xFB, 0x26, 0x46, 0x2A, 0xF2, + 0x3B, 0xF0, 0x60, 0x40, 0x40, 0x2B, 0x06, 0x00, 0xC0, 0x60, 0x00, 0x64, 0x64, 0x40, 0x20, 0x2B, + 0x01, 0x00, 0x03, 0x00, 0xD0, 0x60, 0x73, 0x78, 0xFF, 0xFF, 0x22, 0xF2, 0xFF, 0xFF, 0x04, 0xB4, + 0xFF, 0xFF, 0xF8, 0x03, 0x23, 0xF2, 0x07, 0xF4, 0xBB, 0xF0, 0x26, 0x46, 0xA4, 0x84, 0xFF, 0xFF, + 0x60, 0x40, 0x2F, 0x26, 0x07, 0x00, 0xC9, 0x60, 0x58, 0x4F, 0xCF, 0x78, 0xFF, 0xFF, 0x64, 0x40, + 0x18, 0x36, 0x09, 0x00, 0x04, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0xCF, 0x60, 0xC9, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0x04, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0xF1, 0x64, 0x3B, 0x42, + 0x4A, 0xDB, 0x00, 0x66, 0x46, 0x46, 0xCF, 0x60, 0xC5, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x82, 0x60, + 0xFF, 0x65, 0xA4, 0x87, 0x02, 0xBF, 0x2A, 0xFA, 0x1C, 0xF2, 0x13, 0xFA, 0x32, 0xF2, 0x2C, 0xFA, + 0x33, 0xF2, 0x2D, 0xFA, 0x34, 0xF2, 0x2E, 0xFA, 0x2F, 0xF2, 0x32, 0xFA, 0x30, 0xF2, 0x33, 0xFA, + 0x31, 0xF2, 0x34, 0xFA, 0x66, 0xF3, 0x2F, 0xFA, 0x67, 0xF3, 0x30, 0xFA, 0x68, 0xF3, 0x31, 0xFA, + 0x2E, 0x58, 0xFF, 0xFF, 0xD3, 0x60, 0x59, 0x64, 0x08, 0x60, 0x26, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, + 0xB1, 0xF3, 0x12, 0x60, 0x2C, 0x63, 0xF7, 0xA0, 0xFF, 0xFF, 0x02, 0x06, 0x00, 0x64, 0xB1, 0xFB, + 0xB1, 0xF3, 0xB1, 0xFB, 0x01, 0xA4, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, 0x2A, 0xA3, 0xFB, 0x01, + 0x63, 0x46, 0x10, 0x60, 0xA6, 0x63, 0x0E, 0x61, 0x60, 0xFE, 0xA6, 0xD1, 0xDE, 0x86, 0x01, 0x64, + 0x64, 0x40, 0x7F, 0x36, 0x00, 0x64, 0xA3, 0xDB, 0xDB, 0x83, 0xA3, 0xD9, 0xCD, 0x81, 0x04, 0xA3, + 0xF4, 0x02, 0x11, 0x60, 0x16, 0x63, 0x1C, 0x61, 0xA6, 0xD1, 0xDE, 0x86, 0x01, 0x64, 0x64, 0x40, + 0x7F, 0x36, 0x00, 0x64, 0xA3, 0xDB, 0xDB, 0x83, 0xA3, 0xD9, 0xCD, 0x81, 0x06, 0xA3, 0xF4, 0x02, + 0x20, 0xFE, 0x13, 0x60, 0x7F, 0xF3, 0x13, 0x60, 0x2D, 0xFB, 0x1E, 0x63, 0x26, 0x60, 0x64, 0x61, + 0x27, 0x60, 0x08, 0x64, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0x13, 0x60, 0x95, 0xF3, 0x13, 0x60, + 0x43, 0xFB, 0x13, 0x60, 0x96, 0xF3, 0x13, 0x60, 0x44, 0xFB, 0x13, 0x60, 0x9C, 0xF3, 0x13, 0x60, + 0x4A, 0xFB, 0x13, 0x60, 0x9D, 0xF3, 0x13, 0x60, 0x4B, 0xFB, 0x13, 0x60, 0x9E, 0xF3, 0x13, 0x60, + 0x4C, 0xFB, 0x13, 0x60, 0x9F, 0xF3, 0x13, 0x60, 0x4D, 0xFB, 0x13, 0x60, 0x97, 0xF3, 0x13, 0x60, + 0x45, 0xFB, 0x13, 0x60, 0x98, 0xF3, 0x13, 0x60, 0x46, 0xFB, 0x13, 0x60, 0x99, 0xF3, 0x13, 0x60, + 0x47, 0xFB, 0x26, 0x60, 0xB0, 0x63, 0xBD, 0xD1, 0xCB, 0xF9, 0x66, 0xF9, 0xBD, 0xD1, 0xCC, 0xF9, + 0x67, 0xF9, 0xA3, 0xD1, 0xCD, 0xF9, 0x68, 0xF9, 0x01, 0x64, 0x6A, 0xFB, 0x13, 0x60, 0x51, 0xF3, + 0xC4, 0xFB, 0x00, 0x63, 0x4A, 0xFD, 0x5A, 0xFD, 0x6B, 0xFD, 0x6C, 0xFD, 0x13, 0x60, 0x45, 0xF3, + 0x15, 0x60, 0xCB, 0xF1, 0xFF, 0x60, 0xE7, 0x65, 0x32, 0x41, 0xA5, 0x81, 0xFF, 0xA0, 0xFF, 0xFF, + 0x01, 0x03, 0x06, 0x00, 0x13, 0x60, 0x47, 0xF3, 0x08, 0xB9, 0x60, 0x40, 0x01, 0x26, 0x10, 0xB9, + 0x41, 0x52, 0x87, 0xF5, 0x32, 0x44, 0x10, 0xB0, 0xFF, 0xFF, 0x0A, 0x03, 0x14, 0x60, 0x15, 0xF3, + 0x06, 0xF0, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x80, 0xBF, 0xB0, 0x84, 0x06, 0xFA, + 0x13, 0x60, 0x45, 0xF3, 0x22, 0x7C, 0xFF, 0xA0, 0xFD, 0xA0, 0x05, 0x06, 0x03, 0x03, 0xFE, 0xA0, + 0x04, 0x7C, 0x01, 0x02, 0x3A, 0xF8, 0x13, 0x60, 0x4C, 0xF1, 0x20, 0x44, 0x20, 0xB5, 0x64, 0x41, + 0x00, 0xB9, 0xD4, 0x84, 0x08, 0x28, 0x20, 0xBC, 0x40, 0x40, 0x15, 0x60, 0xCB, 0xF3, 0x30, 0x60, + 0x0E, 0x63, 0xF0, 0x84, 0xF0, 0x84, 0xF0, 0x84, 0x02, 0xB5, 0xF0, 0x84, 0xF0, 0x84, 0x03, 0xB4, + 0x65, 0x5C, 0xA3, 0xD9, 0x02, 0xA8, 0x18, 0x60, 0x08, 0xFB, 0x15, 0x02, 0x00, 0x60, 0xC8, 0x64, + 0x18, 0x60, 0x09, 0xFB, 0x18, 0x60, 0x0D, 0xFB, 0x07, 0x60, 0xD0, 0x64, 0x18, 0x60, 0x0A, 0xFB, + 0x18, 0x60, 0x0E, 0xFB, 0x01, 0x60, 0x90, 0x64, 0x18, 0x60, 0x0B, 0xFB, 0x00, 0x60, 0x64, 0x64, + 0x18, 0x60, 0x0C, 0xFB, 0x06, 0x00, 0x64, 0x64, 0x18, 0x60, 0x0B, 0xFB, 0x64, 0x64, 0x18, 0x60, + 0x0C, 0xFB, 0xB1, 0xF1, 0x10, 0x60, 0xA0, 0x63, 0x2F, 0x18, 0x60, 0x40, 0x01, 0x27, 0x12, 0x00, + 0xCC, 0x84, 0x06, 0xA3, 0xFD, 0x02, 0xA3, 0xD3, 0x10, 0x60, 0xA6, 0x63, 0x25, 0x1B, 0x10, 0x60, + 0xF8, 0x65, 0xA3, 0xD3, 0x06, 0xA3, 0xD7, 0x80, 0x02, 0x1B, 0xFB, 0x04, 0x1D, 0x00, 0xF8, 0xA3, + 0xA3, 0xD3, 0x18, 0x00, 0x11, 0x60, 0x14, 0x63, 0x11, 0x60, 0xF4, 0x65, 0xA3, 0xD1, 0x08, 0xA3, + 0xD0, 0x80, 0xD7, 0x80, 0x02, 0x03, 0xFA, 0x04, 0x0F, 0x00, 0xFA, 0xA3, 0xA3, 0xD3, 0x11, 0x60, + 0x16, 0x63, 0x0A, 0x1B, 0xA3, 0xD3, 0x08, 0xA3, 0xD7, 0x80, 0x02, 0x1B, 0xFB, 0x04, 0x04, 0x00, + 0xF6, 0xA3, 0xA3, 0xD3, 0xC5, 0xFB, 0x64, 0xFB, 0x27, 0x60, 0x34, 0x64, 0x26, 0x60, 0x90, 0x63, + 0xA0, 0xD1, 0xA3, 0xD9, 0x64, 0x41, 0x58, 0xD1, 0x5B, 0xD9, 0x64, 0xF3, 0xFF, 0xFF, 0x60, 0x40, + 0x01, 0x2B, 0x03, 0x00, 0xD1, 0x60, 0xE9, 0x78, 0xFF, 0xFF, 0x91, 0xFA, 0x61, 0x44, 0xEF, 0x60, + 0x58, 0x4E, 0xAB, 0x78, 0xFF, 0xFF, 0x12, 0xFA, 0x15, 0x60, 0xBC, 0xF3, 0x3F, 0x40, 0x01, 0x27, + 0x08, 0x00, 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xEE, 0x60, 0x58, 0x4E, 0x26, 0x78, 0xFF, 0xFF, + 0x06, 0x00, 0x0F, 0x65, 0xA4, 0x84, 0xEE, 0x60, 0x58, 0x4E, 0x26, 0x78, 0xFF, 0xFF, 0x00, 0x65, + 0xEE, 0x60, 0x58, 0x4E, 0xC6, 0x78, 0xFF, 0xFF, 0xEF, 0x60, 0x58, 0x4E, 0x10, 0x78, 0xFF, 0xFF, + 0x15, 0x00, 0x11, 0xF8, 0x64, 0x44, 0xEF, 0x60, 0x58, 0x4E, 0xAB, 0x78, 0xFF, 0xFF, 0x12, 0xFA, + 0x15, 0x60, 0xBD, 0xF3, 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xEE, 0x60, 0x58, 0x4E, 0x26, 0x78, + 0xFF, 0xFF, 0xFF, 0x65, 0xEE, 0x60, 0x58, 0x4E, 0xC6, 0x78, 0xFF, 0xFF, 0xB5, 0xF1, 0x09, 0x60, + 0x2A, 0x64, 0xD0, 0x80, 0x03, 0x64, 0x01, 0x06, 0x06, 0x64, 0xAE, 0xFB, 0x46, 0x48, 0xC3, 0xF3, + 0xFF, 0xFF, 0x60, 0x40, 0x05, 0x3A, 0x03, 0x00, 0x14, 0x60, 0x00, 0x66, 0x11, 0x00, 0x04, 0x3A, + 0x03, 0x00, 0x13, 0x60, 0xF4, 0x66, 0x0C, 0x00, 0x03, 0x3A, 0x03, 0x00, 0x13, 0x60, 0xE8, 0x66, + 0x07, 0x00, 0x02, 0x3A, 0x03, 0x00, 0x13, 0x60, 0xDC, 0x66, 0x02, 0x00, 0x13, 0x60, 0xD0, 0x66, + 0x60, 0xFE, 0xA6, 0xD3, 0xDE, 0x86, 0x10, 0x60, 0x5F, 0xFB, 0xA6, 0xD3, 0xDE, 0x86, 0x21, 0x60, + 0x2F, 0x63, 0xA3, 0xDB, 0x21, 0x60, 0xA7, 0x63, 0xA3, 0xDB, 0xA6, 0xD3, 0xDE, 0x86, 0x10, 0x60, + 0x5E, 0xFB, 0xA6, 0xD3, 0xDE, 0x86, 0x20, 0x60, 0xBF, 0x63, 0xA3, 0xDB, 0x20, 0xFE, 0xA6, 0xD3, + 0xDA, 0x86, 0x60, 0x43, 0x1F, 0xB3, 0x63, 0x5C, 0x1F, 0x60, 0x00, 0xB4, 0xE8, 0x84, 0xE8, 0x84, + 0xE8, 0x84, 0xB0, 0x85, 0x10, 0x60, 0x95, 0xF3, 0xFF, 0xFF, 0xFC, 0x60, 0x00, 0xB4, 0xB4, 0x84, + 0xA2, 0xDB, 0x10, 0x60, 0xD1, 0xFB, 0x21, 0x60, 0xCA, 0x63, 0xA3, 0xD3, 0xA6, 0xD1, 0xDE, 0x86, + 0x80, 0x60, 0x7F, 0xB5, 0x64, 0x44, 0xE8, 0x84, 0x7F, 0x60, 0x80, 0xB4, 0xB4, 0x84, 0xA3, 0xDB, + 0x60, 0xFE, 0xA6, 0xD3, 0xDE, 0x86, 0x10, 0x60, 0x62, 0xFB, 0x20, 0xFE, 0x10, 0x60, 0x2A, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, + 0xD2, 0x60, 0x5E, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x64, 0xF1, 0x0F, 0x60, + 0x9D, 0xF9, 0x0C, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x44, 0x01, 0x65, 0x34, 0x80, + 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD2, 0x60, 0x82, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x64, 0xF1, 0x0F, 0x60, + 0x9D, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, + 0x16, 0xFB, 0xD2, 0x60, 0x97, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, + 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x08, 0x60, 0x11, 0xF1, 0x40, 0x60, 0x00, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xBE, 0xFE, 0x08, 0x60, 0x11, 0xF1, 0x40, 0x60, 0x00, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x20, 0x40, 0x20, 0x2A, 0x04, 0x00, 0xF0, 0x60, 0x58, 0x4E, + 0x66, 0x78, 0xFF, 0xFF, 0x36, 0x40, 0x08, 0x3A, 0x6A, 0x00, 0x36, 0x40, 0x08, 0x3A, 0x05, 0x00, + 0x10, 0x60, 0x42, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x04, 0x00, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x4E, 0xF3, 0xFF, 0xFF, 0x1D, 0x1B, 0x13, 0x60, 0x54, 0xF3, 0xC7, 0xFB, 0x26, 0x60, + 0x16, 0x65, 0x26, 0x60, 0xB8, 0x61, 0x26, 0x60, 0x14, 0x64, 0x20, 0x63, 0x59, 0xD1, 0x58, 0xD9, + 0xA5, 0xD9, 0xDA, 0x85, 0xFB, 0x1F, 0x00, 0x60, 0x01, 0x64, 0x08, 0x60, 0x22, 0xFB, 0xD3, 0x60, + 0x3C, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x36, 0x40, 0x08, 0x3A, 0x41, 0x00, 0xE7, 0x60, 0xC5, 0x78, + 0xFF, 0xFF, 0x27, 0x60, 0x3E, 0x63, 0x60, 0x41, 0x00, 0x62, 0xCD, 0x81, 0x04, 0xA2, 0xFD, 0x02, + 0x2C, 0x60, 0x3E, 0x61, 0xFC, 0xA2, 0x62, 0x45, 0xC5, 0x81, 0xE0, 0x84, 0xE0, 0x85, 0xC4, 0x85, + 0xC7, 0x83, 0xFE, 0xA5, 0x88, 0xF3, 0xFF, 0xFF, 0xC4, 0x84, 0x66, 0x45, 0x60, 0x46, 0xBD, 0xD1, + 0x03, 0xF8, 0xBD, 0xD1, 0x04, 0xF8, 0xA3, 0xD1, 0x05, 0xF8, 0x06, 0xF2, 0xFF, 0xFF, 0x02, 0x7E, + 0x06, 0xFA, 0x64, 0xF3, 0x61, 0x43, 0x60, 0x40, 0x01, 0x27, 0x02, 0xA3, 0xA3, 0xD1, 0x0F, 0xF8, + 0x16, 0x64, 0x12, 0xFA, 0x01, 0x64, 0x11, 0xFA, 0x66, 0x5C, 0xC1, 0x60, 0x58, 0x4E, 0x93, 0x78, + 0xFF, 0xFF, 0x66, 0x43, 0x32, 0x40, 0x08, 0x2A, 0x0A, 0x00, 0x14, 0x60, 0x15, 0xF3, 0x06, 0xF0, + 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x80, 0xBF, 0xB0, 0x84, 0x06, 0xFA, 0xC5, 0xFE, + 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x30, 0x64, 0x08, 0x60, 0x16, 0xFB, + 0xD2, 0x60, 0xB5, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x03, 0x64, 0x08, 0x60, 0x22, 0xFB, 0xD2, 0x60, 0xB5, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x42, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x0F, 0x4E, 0xE1, 0x60, 0x58, 0x4F, 0xA9, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x4E, 0xDF, 0x60, + 0x58, 0x4F, 0x0F, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x4E, 0xDE, 0x60, 0x58, 0x4F, 0x9A, 0x78, + 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x4E, 0xDD, 0x60, 0x58, 0x4F, 0xFB, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, + 0xD5, 0x01, 0x4E, 0xF3, 0x7D, 0xF5, 0x60, 0x40, 0xFF, 0x22, 0x0A, 0x00, 0x88, 0xF1, 0xCC, 0x84, + 0xE0, 0x84, 0xC0, 0x86, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x7D, 0xF5, 0x07, 0x00, + 0x08, 0x60, 0x24, 0xF1, 0x00, 0x60, 0x11, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x4E, 0xF3, + 0x66, 0x40, 0xFF, 0x22, 0x05, 0x00, 0xFF, 0x22, 0x39, 0x00, 0xD4, 0x60, 0x0C, 0x78, 0xFF, 0xFF, + 0x02, 0x64, 0x69, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x69, 0xF3, 0x00, 0x65, 0xD4, 0x80, 0x4E, 0xF3, + 0x0E, 0x03, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, + 0x16, 0xFB, 0xD3, 0x60, 0x7C, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, + 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, + 0x16, 0xFB, 0xD3, 0x60, 0x8F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xD3, 0xF3, + 0xFF, 0xFF, 0xFE, 0xB4, 0xD3, 0xFB, 0x1F, 0x60, 0x3A, 0x62, 0x06, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x2D, 0xFF, 0x20, 0x44, 0x01, 0xB5, 0x54, 0x80, 0xDA, 0xFE, 0xBE, 0xFE, 0x87, 0xF1, 0x02, 0x64, + 0x86, 0xF3, 0xC0, 0x83, 0x40, 0x48, 0x75, 0xFD, 0xE7, 0x60, 0x58, 0x4E, 0x81, 0x78, 0xFF, 0xFF, + 0x28, 0x44, 0x4C, 0x88, 0x75, 0xF3, 0x02, 0x65, 0xC4, 0x83, 0xF5, 0x02, 0x1E, 0x60, 0x58, 0x4E, + 0xB9, 0x78, 0xFF, 0xFF, 0x17, 0x60, 0x06, 0x64, 0x0B, 0x60, 0x82, 0xFB, 0x4A, 0xDF, 0x01, 0x60, + 0xFE, 0x63, 0x15, 0x60, 0x00, 0x61, 0x00, 0x64, 0x59, 0xDB, 0xFE, 0x1F, 0x7D, 0xF1, 0x1E, 0x60, + 0xE0, 0x61, 0x64, 0x40, 0xFF, 0x26, 0x38, 0x00, 0xD4, 0x60, 0x58, 0x4E, 0x0F, 0x78, 0xFF, 0xFF, + 0x1E, 0x60, 0xCE, 0x61, 0xD4, 0x60, 0x58, 0x4E, 0x0F, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xD4, 0x61, + 0xD4, 0x60, 0x58, 0x4E, 0x0F, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xE6, 0x61, 0xD4, 0x60, 0x58, 0x4E, + 0x0F, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xEC, 0x61, 0xD4, 0x60, 0x58, 0x4E, 0x0F, 0x78, 0xFF, 0xFF, + 0x1E, 0x60, 0xF8, 0x61, 0xD4, 0x60, 0x58, 0x4E, 0x0F, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0x04, 0x61, + 0xD4, 0x60, 0x58, 0x4E, 0x0F, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xF2, 0x61, 0xD4, 0x60, 0x58, 0x4E, + 0x0F, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xDA, 0x61, 0xD4, 0x60, 0x58, 0x4E, 0x3A, 0x78, 0xFF, 0xFF, + 0x00, 0x64, 0x08, 0x60, 0x15, 0xFB, 0x5A, 0xDB, 0xC5, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xA1, 0xD3, + 0x0E, 0x57, 0x23, 0x00, 0x0E, 0xF2, 0x44, 0x4C, 0x80, 0xB0, 0x10, 0xB0, 0x0A, 0x03, 0x00, 0x64, + 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0x13, 0x00, 0x12, 0x02, 0xF0, 0x37, 0x09, 0x00, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, + 0xA2, 0xFF, 0x8F, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0x8F, 0xFB, 0x1F, 0x60, 0x20, 0x64, 0x40, 0x4B, + 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, 0xFF, 0xFF, 0x2C, 0x44, 0xAC, 0x86, 0x09, 0xF0, 0xDA, 0x02, + 0x37, 0x58, 0xFF, 0xFF, 0xA1, 0xD3, 0x0E, 0x57, 0x18, 0x00, 0x0E, 0xF2, 0x44, 0x4C, 0x80, 0xB0, + 0x10, 0xB0, 0x0A, 0x03, 0x00, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x08, 0x00, 0x07, 0x02, 0x1F, 0x60, 0x20, 0x64, 0x40, 0x4B, + 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, 0xFF, 0xFF, 0x2C, 0x44, 0xAC, 0x86, 0x09, 0xF0, 0xE5, 0x02, + 0x37, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xB0, 0x64, 0x2A, 0xFA, 0x2F, 0xF2, + 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0xCC, 0xF3, + 0x30, 0xFA, 0xCD, 0xF3, 0x31, 0xFA, 0x66, 0xF3, 0x32, 0xFA, 0x67, 0xF3, 0x33, 0xFA, 0x68, 0xF3, + 0x34, 0xFA, 0xAB, 0xF1, 0x19, 0xF8, 0x06, 0x63, 0x3F, 0xFC, 0x1C, 0xF2, 0x13, 0xFA, 0x00, 0x64, + 0x3E, 0xFA, 0x07, 0xF2, 0x87, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x0C, 0x03, 0x60, 0x46, + 0x06, 0xF2, 0x26, 0x46, 0x01, 0xB0, 0xFF, 0xFF, 0x03, 0x02, 0xD6, 0x60, 0x40, 0x78, 0xFF, 0xFF, + 0xD7, 0x60, 0x92, 0x78, 0xFF, 0xFF, 0x00, 0xF4, 0x0A, 0xF2, 0x09, 0xF2, 0xFF, 0xA0, 0x00, 0xA0, + 0x13, 0x02, 0xFF, 0xA0, 0x04, 0x03, 0x08, 0x03, 0xD4, 0x60, 0xAF, 0x78, 0xFF, 0xFF, 0x02, 0x64, + 0x55, 0xFB, 0xD4, 0x60, 0xBA, 0x78, 0xFF, 0xFF, 0x01, 0x63, 0x32, 0x40, 0x08, 0x2A, 0x0F, 0x00, + 0x55, 0xFD, 0xD4, 0x60, 0xBA, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x0A, 0xF2, 0x0E, 0x63, + 0x01, 0xA4, 0x0A, 0xFA, 0x0B, 0xFC, 0x43, 0x59, 0xD7, 0x60, 0x6C, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0x00, 0xF4, 0x0A, 0xF2, 0x0D, 0x63, 0x01, 0xA4, 0x0A, 0xFA, 0x0B, 0xFC, 0x43, 0x59, 0xD7, 0x60, + 0x6C, 0x78, 0xFF, 0xFF, 0x87, 0xF5, 0x00, 0xF2, 0x26, 0x46, 0x00, 0xA0, 0x2E, 0xF0, 0x37, 0x03, + 0x66, 0x41, 0x15, 0x60, 0x02, 0x65, 0x64, 0x47, 0x00, 0x7F, 0x87, 0xF1, 0xE0, 0x84, 0x44, 0xD3, + 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, + 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, + 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, + 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, 0x86, 0xF1, + 0x17, 0x60, 0x02, 0x61, 0xA1, 0xD3, 0xDA, 0x81, 0xD0, 0x80, 0xDC, 0x9C, 0x05, 0x05, 0xA1, 0xD3, + 0x4A, 0xD9, 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, 0xD6, 0x60, 0x09, 0x78, 0xFF, 0xFF, 0x0B, 0x60, + 0x81, 0xF3, 0xFF, 0xFF, 0x62, 0x18, 0x17, 0x60, 0x02, 0x64, 0x04, 0xA5, 0xA0, 0xD1, 0x72, 0x44, + 0xFF, 0xB4, 0x64, 0x40, 0xE0, 0x22, 0x1F, 0xB4, 0x64, 0x40, 0xF8, 0x22, 0x07, 0xB4, 0x02, 0x00, + 0x03, 0x04, 0xD0, 0x84, 0xD0, 0x80, 0xFC, 0x01, 0xE0, 0x84, 0x44, 0xD3, 0xFF, 0xFF, 0x60, 0x43, + 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, + 0x07, 0x1B, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, + 0x65, 0x46, 0x00, 0xF8, 0x87, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, + 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, + 0x06, 0xFA, 0x61, 0x46, 0x2E, 0xF0, 0x66, 0x41, 0x15, 0x60, 0x02, 0x65, 0x64, 0x47, 0x00, 0x7F, + 0x87, 0xF1, 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, + 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, + 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, + 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, + 0x60, 0x43, 0x61, 0x46, 0xD6, 0x60, 0x09, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x02, 0x61, 0xB5, 0x60, + 0x58, 0x4D, 0xA2, 0x78, 0xFF, 0xFF, 0x86, 0xF1, 0x72, 0x44, 0xFF, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, + 0x02, 0x04, 0xD0, 0x84, 0xFB, 0x01, 0xE0, 0x83, 0x87, 0xF3, 0x02, 0xA3, 0x43, 0x93, 0x66, 0x44, + 0x00, 0xA8, 0x56, 0xFD, 0x3A, 0x03, 0x00, 0x64, 0x2B, 0xFA, 0x00, 0x60, 0xC0, 0x64, 0x2A, 0xFA, + 0x66, 0x45, 0x63, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x85, 0xF2, 0x65, 0x46, 0x2C, 0xFA, 0x2D, 0xF8, + 0xAE, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0x32, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0x33, 0xFA, 0xCD, 0xF3, + 0x31, 0xFA, 0x34, 0xFA, 0xAB, 0xF1, 0x19, 0xF8, 0xFF, 0x67, 0x0E, 0xFA, 0x66, 0x41, 0x43, 0x49, + 0x29, 0x46, 0x92, 0xF0, 0x2C, 0x60, 0x26, 0x63, 0x47, 0xD3, 0x61, 0x46, 0x02, 0x63, 0x00, 0x7E, + 0x13, 0xFA, 0x3F, 0xFC, 0x00, 0x64, 0x3E, 0xFA, 0x87, 0xF3, 0x07, 0xFA, 0x66, 0x41, 0x00, 0xF4, + 0x05, 0x64, 0x09, 0xFA, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x61, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x56, 0xF3, 0xA3, 0xFF, 0x60, 0x43, + 0xE7, 0x60, 0x58, 0x4E, 0x81, 0x78, 0xFF, 0xFF, 0x56, 0xF3, 0xFF, 0xFF, 0x40, 0x58, 0x03, 0x65, + 0xE5, 0x60, 0x58, 0x4E, 0x51, 0x78, 0xFF, 0xFF, 0x56, 0xF3, 0x26, 0x46, 0x60, 0x43, 0x66, 0x41, + 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, + 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, + 0x00, 0xF8, 0x87, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, + 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, + 0x61, 0x46, 0x2E, 0xF0, 0x66, 0x41, 0x15, 0x60, 0x02, 0x65, 0x64, 0x47, 0x00, 0x7F, 0x87, 0xF1, + 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, + 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, + 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, + 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, + 0x61, 0x46, 0x2C, 0xF2, 0x2D, 0xF0, 0xAE, 0xF2, 0x66, 0x45, 0x63, 0x46, 0x03, 0xFA, 0x04, 0xF8, + 0x55, 0xF3, 0x85, 0xFA, 0xFF, 0xA0, 0x65, 0x46, 0x03, 0x03, 0xD7, 0x60, 0xAE, 0x78, 0xFF, 0xFF, + 0x94, 0xF3, 0x66, 0x45, 0x63, 0x46, 0x1F, 0xFA, 0x65, 0x46, 0xBA, 0x65, 0x60, 0x44, 0xC4, 0x85, + 0x01, 0x60, 0xFE, 0x61, 0x00, 0x64, 0x80, 0x63, 0xC7, 0x85, 0x94, 0x84, 0x59, 0xDB, 0xFC, 0x1F, + 0x00, 0x60, 0x88, 0x64, 0x3F, 0xFA, 0x00, 0xF4, 0x02, 0x64, 0x0A, 0xFA, 0x00, 0x64, 0x0B, 0xFA, + 0x80, 0x7F, 0x10, 0x7E, 0x0C, 0xFA, 0x1A, 0x65, 0x80, 0x61, 0x02, 0x60, 0x00, 0x63, 0x0F, 0x4E, + 0xF8, 0x60, 0x58, 0x4F, 0x7A, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0xD7, 0x60, 0x80, 0x78, 0xFF, 0xFF, + 0x26, 0x46, 0x23, 0xF0, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x00, 0xF4, 0x03, 0x03, 0xD7, 0x60, + 0x2A, 0x78, 0xFF, 0xFF, 0x09, 0xF2, 0xFF, 0xFF, 0xFF, 0xA0, 0x00, 0xA0, 0x0C, 0x03, 0x03, 0x03, + 0xD6, 0x60, 0xA7, 0x78, 0xFF, 0xFF, 0x0A, 0xF2, 0x26, 0x46, 0xFF, 0xA0, 0x87, 0xF4, 0x10, 0x02, + 0xD7, 0x60, 0xAE, 0x78, 0xFF, 0xFF, 0x0A, 0xF2, 0xFF, 0xFF, 0xFF, 0xA0, 0xFD, 0xA0, 0x02, 0x03, + 0x04, 0x03, 0x06, 0x00, 0xD6, 0x60, 0xE6, 0x78, 0xFF, 0xFF, 0xD6, 0x60, 0xF1, 0x78, 0xFF, 0xFF, + 0x26, 0x46, 0x87, 0xF4, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, + 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0x87, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, + 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, + 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x0B, 0x60, 0x82, 0xF3, 0xDA, 0x81, 0x60, 0x45, + 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, + 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, 0x17, 0x60, 0x04, 0x62, 0x65, 0x44, 0xA2, 0xDB, + 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, 0xD4, 0x60, 0xA4, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0x87, 0xF4, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, + 0x81, 0xF8, 0x07, 0x1B, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, + 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0x87, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, + 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, + 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x0B, 0x60, 0x82, 0xF3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, + 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, + 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, 0x17, 0x60, 0x04, 0x62, 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, + 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, 0xD4, 0x60, 0xAF, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x32, 0x44, + 0x08, 0xB0, 0x87, 0xF4, 0x03, 0x02, 0xD4, 0x60, 0xAF, 0x78, 0xFF, 0xFF, 0xD6, 0x60, 0x18, 0x78, + 0xFF, 0xFF, 0x32, 0x44, 0x26, 0x46, 0x08, 0xB0, 0x07, 0xF2, 0x03, 0x02, 0xD4, 0x60, 0xAF, 0x78, + 0xFF, 0xFF, 0x60, 0x46, 0x1F, 0xF2, 0x26, 0x46, 0xBA, 0x65, 0x60, 0x44, 0xC4, 0x85, 0x01, 0x60, + 0xFE, 0x61, 0x00, 0x64, 0x80, 0x63, 0xC7, 0x85, 0x94, 0x84, 0x59, 0xDB, 0xFC, 0x1F, 0x00, 0xF4, + 0x01, 0x60, 0xFE, 0x61, 0x7E, 0x65, 0x18, 0x63, 0x5B, 0xD2, 0x59, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, + 0xD7, 0x80, 0x18, 0x02, 0xF9, 0x02, 0x00, 0xF4, 0x02, 0x63, 0x0E, 0x65, 0x5B, 0xD2, 0x59, 0xD1, + 0xFF, 0xFF, 0xD0, 0x80, 0xD7, 0x80, 0x0E, 0x02, 0xF9, 0x02, 0x26, 0x46, 0x07, 0xF4, 0x06, 0xF2, + 0xFF, 0xFF, 0x01, 0x7E, 0x06, 0xFA, 0x26, 0x46, 0x00, 0xF4, 0x04, 0x64, 0x0A, 0xFA, 0x00, 0x64, + 0x0B, 0xFA, 0x56, 0x00, 0x26, 0x46, 0x87, 0xF4, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, + 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0x87, 0xF3, 0x63, 0x45, + 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, + 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x0B, 0x60, 0x82, 0xF3, + 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, + 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, 0x17, 0x60, 0x04, 0x62, + 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, 0x00, 0xF4, 0x04, 0x64, + 0x0A, 0xFA, 0x0F, 0x64, 0x0B, 0xFA, 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x41, 0x58, 0x26, 0x46, + 0x2C, 0xF2, 0xA1, 0xDB, 0x2D, 0xF2, 0x59, 0xDB, 0x2E, 0xF2, 0x59, 0xDB, 0x03, 0x65, 0xE5, 0x60, + 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x03, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x51, 0x78, 0xFF, 0xFF, + 0x26, 0x46, 0x87, 0xF3, 0x07, 0xFA, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, + 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0xF4, 0x0A, 0xF2, 0x09, 0xF2, 0xFF, 0xA0, 0x00, 0xA0, 0x06, 0x02, + 0xFF, 0xA0, 0x07, 0x03, 0x09, 0x03, 0xD6, 0x60, 0xA7, 0x78, 0xFF, 0xFF, 0xD6, 0x60, 0x68, 0x78, + 0xFF, 0xFF, 0xD7, 0x60, 0xB3, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x07, 0xF4, 0x06, 0xF2, 0x66, 0x43, + 0x00, 0x7E, 0x06, 0xFA, 0x26, 0x46, 0xD6, 0x60, 0x18, 0x78, 0xFF, 0xFF, 0x63, 0x46, 0x06, 0xF2, + 0xFF, 0xFF, 0x01, 0x7E, 0x06, 0xFA, 0x26, 0x46, 0x87, 0xF3, 0x07, 0xFA, 0x00, 0xF4, 0x02, 0x64, + 0x0A, 0xFA, 0x00, 0x64, 0x0B, 0xFA, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, + 0x2F, 0x58, 0xFF, 0xFF, 0x01, 0x61, 0x00, 0x60, 0x10, 0x7C, 0x2A, 0xF2, 0x0C, 0x60, 0x70, 0xFB, + 0xFF, 0xB4, 0x16, 0x60, 0x83, 0xFB, 0x60, 0x40, 0x00, 0x36, 0x03, 0x00, 0x02, 0x61, 0x00, 0x60, + 0x30, 0x7C, 0x41, 0x47, 0x2A, 0xF8, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, + 0x2E, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0xCD, 0xF3, 0x31, 0xFA, 0x66, 0xF3, + 0x32, 0xFA, 0x67, 0xF3, 0x33, 0xFA, 0x68, 0xF3, 0x34, 0xFA, 0xAB, 0xF1, 0x19, 0xF8, 0x00, 0x7C, + 0x3E, 0xF8, 0x1C, 0xF0, 0x13, 0xF8, 0x07, 0xF2, 0x87, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, + 0x03, 0x02, 0xDC, 0x60, 0x55, 0x78, 0xFF, 0xFF, 0x40, 0x4B, 0x01, 0x65, 0xEF, 0x60, 0x58, 0x4E, + 0xDC, 0x78, 0xFF, 0xFF, 0xAB, 0x46, 0x06, 0xF2, 0xAB, 0x46, 0x00, 0xF4, 0x01, 0xB0, 0xFF, 0xFF, + 0x03, 0x02, 0xDC, 0x60, 0x55, 0x78, 0xFF, 0xFF, 0x09, 0xF2, 0x16, 0x60, 0x84, 0xFB, 0x5A, 0x84, + 0x00, 0x63, 0x60, 0x40, 0x20, 0x26, 0x02, 0xBB, 0x60, 0x40, 0x04, 0x27, 0x04, 0xBB, 0xAB, 0x46, + 0x78, 0xFC, 0xAB, 0x46, 0xFF, 0xFF, 0x10, 0xB0, 0x80, 0x60, 0x00, 0x63, 0x0C, 0x03, 0x13, 0x60, + 0x45, 0xF1, 0xFF, 0xFF, 0x64, 0x44, 0xFE, 0x26, 0x08, 0x00, 0x32, 0x40, 0x08, 0x26, 0x06, 0x00, + 0xDC, 0x60, 0xB9, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x10, 0x2A, 0x00, 0x63, 0xAB, 0x46, 0x06, 0xF0, + 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0x63, 0x45, 0xB4, 0x84, 0x06, 0xFA, 0xAB, 0x46, 0x0A, 0xF0, + 0x56, 0xF9, 0x24, 0xD9, 0x5A, 0x84, 0x01, 0x63, 0x32, 0x40, 0x10, 0x26, 0x10, 0xBB, 0x13, 0x60, + 0x45, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0xFE, 0x26, 0x10, 0xBB, 0x15, 0x60, 0xDD, 0xF1, 0x63, 0x44, + 0x20, 0xBC, 0xFB, 0x60, 0xFF, 0xB7, 0x64, 0x40, 0x10, 0x26, 0x04, 0xBC, 0x60, 0x47, 0x60, 0x43, + 0x09, 0xFC, 0x27, 0x44, 0xFE, 0xA0, 0xFF, 0xFF, 0x03, 0x03, 0xD8, 0x60, 0xC8, 0x78, 0xFF, 0xFF, + 0x18, 0x60, 0xD6, 0x64, 0x24, 0x43, 0x0B, 0xF0, 0xA0, 0xD9, 0xBD, 0xD9, 0x0C, 0xF0, 0x58, 0xD9, + 0xBD, 0xD9, 0x0D, 0xF0, 0x58, 0xD9, 0xBD, 0xD9, 0x43, 0x44, 0x26, 0x46, 0x87, 0xF2, 0x3F, 0xF2, + 0x41, 0x4B, 0x00, 0xF4, 0x60, 0x43, 0xF6, 0xA3, 0x00, 0x60, 0x1B, 0x61, 0x00, 0x60, 0x01, 0x65, + 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xEF, 0x60, 0x58, 0x4E, 0x79, 0x78, 0xFF, 0xFF, 0x00, 0xBB, + 0xFF, 0xFF, 0x00, 0x02, 0x00, 0x64, 0x40, 0x4A, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, + 0xBD, 0xD3, 0x60, 0x41, 0xF0, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x20, 0xFE, 0x26, 0x46, + 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xF6, 0xA3, 0x00, 0x60, 0x1B, 0x61, 0x00, 0x60, 0x32, 0x65, + 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xEF, 0x60, 0x58, 0x4E, 0x79, 0x78, 0xFF, 0xFF, 0x00, 0xBB, + 0xFF, 0xFF, 0x0B, 0x03, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, + 0xF0, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0xFE, 0x30, 0x60, 0x20, 0x61, + 0xA1, 0xD1, 0x82, 0xF3, 0x01, 0x60, 0x6E, 0x63, 0x60, 0x45, 0x2A, 0x44, 0x60, 0xFB, 0xA3, 0xD5, + 0x65, 0x40, 0x01, 0x27, 0x5B, 0xD5, 0x65, 0x40, 0x01, 0x27, 0x59, 0xD1, 0x66, 0x41, 0xA0, 0x84, + 0x24, 0x94, 0x2B, 0x46, 0x0F, 0xFA, 0x61, 0xFB, 0x16, 0x64, 0x12, 0xFA, 0x01, 0x64, 0x11, 0xFA, + 0x66, 0x5C, 0xC1, 0x60, 0x58, 0x4E, 0x93, 0x78, 0xFF, 0xFF, 0xD9, 0x60, 0x28, 0x78, 0xFF, 0xFF, + 0x26, 0x46, 0x87, 0xF2, 0x3F, 0xF2, 0x41, 0x4B, 0x00, 0xF4, 0x60, 0x43, 0xFC, 0xA3, 0x00, 0x60, + 0x15, 0x61, 0x00, 0x60, 0x01, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xEF, 0x60, 0x58, 0x4E, + 0x79, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x00, 0x02, 0x00, 0x64, 0x40, 0x4A, 0x60, 0xFE, + 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xF0, 0x60, 0x58, 0x4E, 0x27, 0x78, + 0xFF, 0xFF, 0x20, 0xFE, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xFC, 0xA3, 0x00, 0x60, + 0x15, 0x61, 0x00, 0x60, 0x32, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xEF, 0x60, 0x58, 0x4E, + 0x79, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x0B, 0x03, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, + 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xF0, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x00, 0x00, + 0x20, 0xFE, 0x30, 0x60, 0x20, 0x61, 0xA1, 0xD1, 0x82, 0xF3, 0x01, 0x60, 0x6E, 0x63, 0x60, 0x45, + 0x2A, 0x44, 0x60, 0xFB, 0xA3, 0xD5, 0x65, 0x40, 0x01, 0x27, 0x5B, 0xD5, 0x65, 0x40, 0x01, 0x27, + 0x59, 0xD1, 0x66, 0x41, 0xA0, 0x84, 0x24, 0x94, 0x2B, 0x46, 0x0F, 0xFA, 0x61, 0xFB, 0x16, 0x64, + 0x12, 0xFA, 0x01, 0x64, 0x11, 0xFA, 0x66, 0x5C, 0xC1, 0x60, 0x58, 0x4E, 0x93, 0x78, 0xFF, 0xFF, + 0x2B, 0x46, 0x0F, 0xF2, 0x12, 0x63, 0x7C, 0x18, 0x26, 0x46, 0x87, 0xF2, 0x01, 0x65, 0x41, 0x4B, + 0xAB, 0x46, 0x0F, 0xF2, 0xFF, 0xFF, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xFF, 0x22, + 0x00, 0x65, 0x78, 0xF2, 0xFF, 0xFF, 0xB4, 0x84, 0x78, 0xFA, 0xAB, 0x46, 0xFF, 0xFF, 0x26, 0x46, + 0x3F, 0xF2, 0x00, 0xF4, 0x16, 0x65, 0x27, 0x40, 0x02, 0x3A, 0x03, 0x00, 0x1C, 0x65, 0xF6, 0xA4, + 0x01, 0x00, 0xFC, 0xA4, 0x24, 0x43, 0x2D, 0x60, 0x5E, 0x61, 0x5D, 0x91, 0x51, 0x90, 0xFF, 0xFF, + 0x04, 0x28, 0x60, 0x41, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, + 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, + 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x2D, 0x60, 0x04, 0x7C, 0x03, 0x1E, 0x60, 0xFE, + 0xBD, 0xDF, 0x20, 0xFE, 0x2D, 0x60, 0x08, 0x64, 0x53, 0x93, 0xA4, 0xDD, 0x26, 0x46, 0x00, 0xF4, + 0x13, 0x60, 0x44, 0xF3, 0x00, 0x63, 0x00, 0xB8, 0x0A, 0xFC, 0x03, 0x02, 0xD9, 0x60, 0xCF, 0x78, + 0xFF, 0xFF, 0x0B, 0xF2, 0x27, 0x40, 0x02, 0x3A, 0x02, 0x00, 0x0E, 0xF2, 0xFF, 0xFF, 0x60, 0x47, + 0x00, 0x3A, 0x25, 0x00, 0x60, 0x41, 0x00, 0x36, 0x22, 0x00, 0xE0, 0xA0, 0xDA, 0x85, 0x1F, 0x07, + 0x13, 0x60, 0x0B, 0xF1, 0x65, 0x42, 0xD1, 0x80, 0x26, 0x60, 0x18, 0x63, 0x18, 0x02, 0x50, 0xFE, + 0x61, 0x40, 0xFE, 0x22, 0x08, 0x00, 0x62, 0x45, 0xBD, 0xD3, 0xA5, 0xD0, 0xDA, 0x82, 0xD0, 0x80, + 0xC9, 0x81, 0xF6, 0x0C, 0x0C, 0x00, 0x61, 0x40, 0x00, 0x36, 0x31, 0x00, 0x62, 0x45, 0xA3, 0xD3, + 0xA5, 0xD0, 0xFF, 0xFF, 0x90, 0x80, 0xFF, 0x26, 0x02, 0x00, 0xDE, 0x82, 0x28, 0x00, 0x0C, 0x63, + 0x0A, 0xFC, 0x00, 0x64, 0x09, 0xFA, 0x0B, 0xFA, 0x01, 0x7E, 0x0C, 0xFA, 0x26, 0x46, 0x08, 0x64, + 0x3F, 0xFA, 0x07, 0xF2, 0x87, 0xF1, 0x40, 0x58, 0x07, 0xF8, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, + 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, + 0xDC, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0x20, 0xFE, 0x16, 0x60, 0x50, 0xF3, 0xFF, 0xFF, 0x22, 0xB0, + 0xFF, 0xFF, 0x03, 0x03, 0xDB, 0x60, 0xB1, 0x78, 0xFF, 0xFF, 0x01, 0x63, 0xD9, 0x01, 0x13, 0x60, + 0x45, 0xF3, 0xFF, 0xFF, 0xFF, 0xA4, 0xFF, 0xFF, 0x0C, 0x20, 0x03, 0x00, 0xDB, 0x60, 0xB1, 0x78, + 0xFF, 0xFF, 0x00, 0x64, 0x16, 0x60, 0x56, 0xFB, 0x16, 0x60, 0x57, 0xFB, 0x16, 0x60, 0x58, 0xFB, + 0x16, 0x60, 0x5A, 0xFB, 0x16, 0x60, 0x5B, 0xFB, 0x16, 0x60, 0x5C, 0xFB, 0x16, 0x60, 0x5D, 0xFB, + 0x18, 0x60, 0x17, 0xFB, 0x2B, 0x46, 0x3B, 0xF2, 0x7F, 0x60, 0xCF, 0x65, 0xA4, 0x84, 0xA2, 0xDA, + 0x26, 0x46, 0x00, 0xF4, 0x0B, 0xF2, 0x27, 0x40, 0x02, 0x3A, 0x02, 0x00, 0x0E, 0xF2, 0xFF, 0xFF, + 0xCE, 0x81, 0x20, 0xFE, 0x30, 0x60, 0x28, 0x64, 0x40, 0x4A, 0xDA, 0x60, 0x58, 0x4D, 0x62, 0x78, + 0xFF, 0xFF, 0x20, 0xFE, 0x18, 0x60, 0x17, 0xF3, 0xFF, 0xFF, 0x08, 0x18, 0x18, 0x60, 0x19, 0xF3, + 0x18, 0x60, 0x1A, 0xF5, 0x60, 0x41, 0x30, 0x60, 0x2E, 0x62, 0xA2, 0xDF, 0x2A, 0xD1, 0xDA, 0x85, + 0x64, 0x44, 0x01, 0xA0, 0xFF, 0xFF, 0x01, 0x02, 0x75, 0x00, 0x45, 0x4A, 0x7C, 0x44, 0x60, 0xFE, + 0xA1, 0xD2, 0xFF, 0xFF, 0xD0, 0x80, 0x20, 0xFE, 0x01, 0x03, 0xE3, 0x01, 0x30, 0x60, 0x2E, 0x62, + 0xA2, 0xDF, 0x60, 0xFE, 0x5D, 0xD2, 0xFF, 0xFF, 0x60, 0x5C, 0x41, 0x94, 0x81, 0xA0, 0x20, 0xFE, + 0x2D, 0x04, 0x01, 0x64, 0x18, 0x60, 0x17, 0xFB, 0xC1, 0x84, 0x84, 0xA4, 0x18, 0x60, 0x19, 0xFB, + 0x00, 0xF2, 0x18, 0x60, 0x1A, 0xFB, 0x18, 0x60, 0x18, 0xFD, 0x02, 0x60, 0x00, 0x63, 0xCD, 0x85, + 0x64, 0x44, 0xD8, 0x81, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, + 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, + 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x00, 0x60, 0x01, 0x61, 0x02, 0x60, 0x00, 0x64, + 0xE0, 0x87, 0x60, 0x46, 0x18, 0x60, 0x18, 0xF3, 0xFF, 0xFF, 0x60, 0x43, 0x60, 0xFE, 0xCD, 0x81, + 0x20, 0xFE, 0x2A, 0x44, 0x00, 0x60, 0x02, 0x65, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xDB, 0x60, + 0x5C, 0x78, 0xFF, 0xFF, 0x18, 0x60, 0x17, 0xF3, 0xFF, 0xFF, 0x08, 0x18, 0x18, 0x60, 0x19, 0xF3, + 0x18, 0x60, 0x1A, 0xF5, 0x60, 0x41, 0x30, 0x60, 0x2E, 0x62, 0xA2, 0xDF, 0x66, 0x5C, 0x26, 0x46, + 0x00, 0xF2, 0x64, 0x46, 0x58, 0x90, 0xFF, 0xFF, 0x03, 0x02, 0x61, 0x44, 0x0B, 0xA5, 0x04, 0x00, + 0x61, 0x44, 0xFC, 0xA4, 0x8B, 0x7C, 0xC0, 0x85, 0xDD, 0x81, 0x66, 0x44, 0x18, 0x60, 0x1A, 0xFB, + 0x26, 0x46, 0x1B, 0xF0, 0x18, 0x60, 0x1A, 0xF5, 0x64, 0x44, 0xD4, 0x80, 0xFF, 0xFF, 0xD7, 0x06, + 0x2D, 0x58, 0xFF, 0xFF, 0x60, 0xFE, 0x5D, 0xD2, 0xFF, 0xFF, 0x20, 0xFE, 0xFF, 0xB4, 0x41, 0x94, + 0x81, 0xA0, 0xFF, 0xFF, 0x02, 0x04, 0x00, 0xF4, 0x84, 0xA4, 0x60, 0x41, 0x62, 0x01, 0x60, 0xFE, + 0x5D, 0xD2, 0xFF, 0xFF, 0xFA, 0xA4, 0xFF, 0xFF, 0x04, 0x20, 0x02, 0x00, 0xFF, 0xA1, 0x61, 0x01, + 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x36, 0x02, 0x00, 0xC9, 0x81, 0x5A, 0x01, 0x5D, 0xD0, + 0xFF, 0xFF, 0x64, 0x40, 0x50, 0x36, 0x02, 0x00, 0xFD, 0xA1, 0x53, 0x01, 0x5D, 0xD0, 0xFF, 0xFF, + 0x64, 0x40, 0xF2, 0x36, 0x04, 0x00, 0xFC, 0xA1, 0xDA, 0x60, 0x01, 0x78, 0xFF, 0xFF, 0x5D, 0xD0, + 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x04, 0x00, 0xFB, 0xA1, 0xDA, 0x60, 0x01, 0x78, 0xFF, 0xFF, + 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x04, 0x00, 0xFA, 0xA1, 0xDA, 0x60, 0x01, 0x78, + 0xFF, 0xFF, 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x36, 0x04, 0x00, 0xF9, 0xA1, 0xDA, 0x60, + 0x01, 0x78, 0xFF, 0xFF, 0x60, 0x5C, 0x00, 0x36, 0x2A, 0x00, 0x00, 0x64, 0xDB, 0x60, 0x58, 0x4E, + 0x16, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0x5A, 0xFB, 0x64, 0x40, 0x00, 0x36, 0x25, 0x00, 0x5D, 0xD2, + 0xDD, 0x81, 0xDB, 0x60, 0x58, 0x4E, 0x16, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0x5B, 0xFB, 0x64, 0x40, + 0x00, 0x36, 0x1F, 0x00, 0x5D, 0xD2, 0xDD, 0x81, 0xDB, 0x60, 0x58, 0x4E, 0x16, 0x78, 0xFF, 0xFF, + 0x16, 0x60, 0x5C, 0xFB, 0x64, 0x40, 0x00, 0x36, 0x19, 0x00, 0x5D, 0xD0, 0x16, 0x60, 0x5D, 0xF9, + 0x5D, 0xD0, 0x2C, 0x60, 0xBB, 0x62, 0xA2, 0xD9, 0xD9, 0x60, 0xF9, 0x78, 0xFF, 0xFF, 0x20, 0xFE, + 0x00, 0x60, 0x04, 0x64, 0x16, 0x60, 0x5A, 0xFB, 0x20, 0xFE, 0x00, 0x60, 0x04, 0x64, 0x16, 0x60, + 0x5B, 0xFB, 0x20, 0xFE, 0x00, 0x60, 0x02, 0x64, 0x16, 0x60, 0x5C, 0xFB, 0x20, 0xFE, 0x00, 0x60, + 0x00, 0x64, 0x16, 0x60, 0x5D, 0xFB, 0xD9, 0x60, 0xF9, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0x5E, 0xFB, + 0xE0, 0x84, 0xE0, 0x84, 0x03, 0x02, 0x01, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x02, 0xA5, 0x64, 0x44, + 0xD4, 0x9C, 0x16, 0x60, 0x5F, 0xF9, 0x2C, 0x60, 0xC0, 0x62, 0xA2, 0xDF, 0x5D, 0xD0, 0x00, 0x65, + 0x64, 0x40, 0x00, 0x3A, 0x01, 0x65, 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x50, 0x3A, 0x01, 0x65, + 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0xF2, 0x3A, 0x01, 0x65, 0x5D, 0xD0, 0x65, 0x40, 0x00, 0x3A, + 0x17, 0x00, 0x00, 0x60, 0x00, 0x65, 0x64, 0x40, 0x00, 0x36, 0x01, 0x65, 0x64, 0x40, 0x01, 0x36, + 0x02, 0x65, 0x64, 0x40, 0x02, 0x36, 0x04, 0x65, 0x64, 0x40, 0x04, 0x36, 0x10, 0x65, 0x64, 0x40, + 0x05, 0x36, 0x20, 0x65, 0x65, 0x5C, 0x16, 0x60, 0x60, 0xF3, 0xFF, 0xFF, 0xB0, 0x84, 0xA2, 0xDB, + 0x16, 0x60, 0x5E, 0xF3, 0xFF, 0xFF, 0xFF, 0xA4, 0xA2, 0xDB, 0xD0, 0x02, 0x16, 0x60, 0x60, 0xF3, + 0x16, 0x60, 0x5F, 0xF1, 0x2E, 0x58, 0xFF, 0xFF, 0x20, 0xFE, 0x16, 0x60, 0x50, 0xF1, 0x16, 0x60, + 0x5A, 0xF3, 0xFF, 0xFF, 0xA0, 0x84, 0xFF, 0xFF, 0x10, 0x26, 0x09, 0x00, 0x04, 0x26, 0x09, 0x00, + 0x20, 0x26, 0x09, 0x00, 0x02, 0x26, 0x09, 0x00, 0xD9, 0x60, 0xC3, 0x78, 0xFF, 0xFF, 0x10, 0x7C, + 0x05, 0x00, 0x04, 0x7C, 0x03, 0x00, 0x20, 0x7C, 0x01, 0x00, 0x02, 0x7C, 0x16, 0x60, 0x56, 0xF9, + 0x16, 0x60, 0x51, 0xF1, 0x16, 0x60, 0x5B, 0xF3, 0x2C, 0x60, 0xAC, 0x62, 0xA0, 0x84, 0xA2, 0xD1, + 0xFF, 0xFF, 0x10, 0x26, 0x07, 0x00, 0x04, 0x26, 0x07, 0x00, 0x01, 0x26, 0x0D, 0x00, 0xD9, 0x60, + 0xC3, 0x78, 0xFF, 0xFF, 0x10, 0x7C, 0x09, 0x00, 0x64, 0x40, 0x10, 0x22, 0x03, 0x00, 0xD9, 0x60, + 0xC3, 0x78, 0xFF, 0xFF, 0x04, 0x7C, 0x01, 0x00, 0x01, 0x7C, 0x16, 0x60, 0x57, 0xF9, 0x16, 0x60, + 0x52, 0xF1, 0x16, 0x60, 0x5C, 0xF3, 0xFF, 0xFF, 0xA0, 0x84, 0x02, 0x26, 0x07, 0x00, 0x04, 0x26, + 0x07, 0x00, 0x01, 0x26, 0x07, 0x00, 0xD9, 0x60, 0xC3, 0x78, 0xFF, 0xFF, 0x02, 0x7C, 0x03, 0x00, + 0x04, 0x7C, 0x01, 0x00, 0x20, 0x7C, 0x16, 0x60, 0x58, 0xF9, 0x16, 0x60, 0x5D, 0xF1, 0x16, 0x60, + 0x59, 0xF9, 0x16, 0x60, 0x58, 0xF3, 0x16, 0x60, 0x57, 0xF1, 0x60, 0x47, 0xB0, 0x84, 0x13, 0x60, + 0x45, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x22, 0xBC, 0xAB, 0x46, 0x3A, 0xFA, 0xAB, 0x46, + 0x16, 0x60, 0x56, 0xF3, 0x13, 0x60, 0x45, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x22, 0xBC, + 0x87, 0xF1, 0x66, 0x41, 0x64, 0x46, 0x3A, 0xFA, 0xFF, 0xFF, 0x61, 0x46, 0xAB, 0x46, 0x82, 0xF0, + 0xC0, 0x67, 0xB4, 0x84, 0xAB, 0x46, 0x0B, 0xFA, 0x13, 0x60, 0x4D, 0xF1, 0x2D, 0x60, 0xBE, 0x7C, + 0x04, 0x1B, 0xFF, 0x60, 0xFF, 0x63, 0xA4, 0xDD, 0x26, 0x00, 0x2E, 0x60, 0x34, 0x63, 0xA4, 0xDD, + 0xDB, 0x83, 0x60, 0xFE, 0x00, 0x64, 0xBD, 0xDB, 0x60, 0x64, 0xBD, 0xDB, 0x1D, 0x64, 0xBD, 0xDB, + 0xC3, 0xF3, 0xBD, 0xDB, 0x20, 0xFE, 0x01, 0x60, 0x78, 0x64, 0x06, 0x61, 0x58, 0xD1, 0xFF, 0xFF, + 0x60, 0xFE, 0xBD, 0xD9, 0x20, 0xFE, 0xCD, 0x81, 0x61, 0x40, 0x08, 0x28, 0xF7, 0x01, 0xB6, 0xF1, + 0xFF, 0xFF, 0x64, 0x47, 0x60, 0xFE, 0xBD, 0xD9, 0xBD, 0xDB, 0x20, 0xFE, 0x13, 0x60, 0x4B, 0xF1, + 0x60, 0xFE, 0xBD, 0xD9, 0x20, 0xFE, 0x2D, 0x60, 0xBC, 0x64, 0x40, 0x48, 0x18, 0x61, 0x26, 0x46, + 0x00, 0xF4, 0xFF, 0x60, 0xF2, 0x64, 0xE4, 0x60, 0x58, 0x4D, 0xA7, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0x3F, 0xFC, 0x2B, 0x46, 0x56, 0xF1, 0x1F, 0xF8, 0x0C, 0x60, 0x70, 0xF1, 0x10, 0x60, 0x00, 0x64, + 0xA0, 0x80, 0x06, 0xF2, 0x0B, 0x03, 0x10, 0xBC, 0x06, 0xFA, 0x86, 0xF3, 0x00, 0x60, 0x70, 0xF3, + 0x60, 0x45, 0xD4, 0x80, 0xDC, 0x84, 0x07, 0x07, 0xA2, 0xDB, 0x05, 0x00, 0x10, 0xB5, 0xFF, 0xFF, + 0x02, 0x03, 0xD4, 0x84, 0x06, 0xFA, 0x07, 0xF2, 0x66, 0x45, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, + 0x02, 0xB0, 0xFF, 0xFF, 0x11, 0x03, 0x26, 0x46, 0x87, 0xF3, 0x07, 0xFA, 0x1E, 0x60, 0xD4, 0x64, + 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x50, 0x00, 0x26, 0x46, 0x87, 0xF3, 0x07, 0xFA, 0x1E, 0x60, + 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x19, 0x00, 0x00, 0x60, 0xC0, 0x64, 0x2A, 0xFA, + 0x02, 0x64, 0x3F, 0xFA, 0x87, 0xF3, 0x07, 0xFA, 0x00, 0xF4, 0x09, 0x64, 0x09, 0xFA, 0x1E, 0x60, + 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x2B, 0x43, 0x0B, 0x60, + 0x82, 0xF3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, 0xD9, 0x81, + 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, 0x17, 0x60, + 0x04, 0x62, 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, 0xAB, 0x46, + 0x06, 0xF2, 0xFF, 0xFF, 0x02, 0xBC, 0x06, 0xFA, 0x78, 0xF2, 0x15, 0x60, 0xDC, 0xF3, 0x60, 0x45, + 0xA4, 0x84, 0x15, 0x60, 0xDC, 0xFB, 0xAB, 0x46, 0xAB, 0x46, 0x0F, 0x60, 0xFF, 0x64, 0x02, 0xF0, + 0x71, 0xF1, 0xA0, 0x84, 0xD0, 0x80, 0x02, 0xFA, 0xAB, 0x46, 0x01, 0x06, 0x71, 0xFB, 0x27, 0x41, + 0x01, 0xB1, 0xFF, 0xFF, 0x08, 0x03, 0x2B, 0x46, 0x0B, 0x58, 0x01, 0x65, 0xE5, 0x60, 0x58, 0x4E, + 0x51, 0x78, 0xFF, 0xFF, 0x0A, 0x00, 0x2B, 0x46, 0x0B, 0x58, 0x18, 0x60, 0xD6, 0x64, 0x40, 0x59, + 0x02, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x51, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, + 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x00, 0x64, 0x09, 0xFA, 0x0B, 0xFA, 0x01, 0x7E, 0x0C, 0xFA, + 0x0A, 0x64, 0x0A, 0xFA, 0x26, 0x46, 0x08, 0x64, 0x3F, 0xFA, 0x07, 0xF2, 0x87, 0xF1, 0x40, 0x58, + 0x07, 0xF8, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xFF, 0x60, 0xFD, 0x65, 0x38, 0x46, 0x06, 0xF2, + 0xFF, 0xFF, 0xA4, 0x83, 0x06, 0xFC, 0x02, 0xB0, 0x26, 0x46, 0x1C, 0x03, 0x38, 0x43, 0x86, 0xF1, + 0x17, 0x60, 0x02, 0x61, 0xA1, 0xD3, 0xDA, 0x81, 0xD0, 0x80, 0xDC, 0x9C, 0x05, 0x05, 0xA1, 0xD3, + 0x4A, 0xD9, 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, 0x02, 0x60, 0x00, 0x61, 0x2C, 0xF2, 0xA1, 0xDB, + 0x2D, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x2E, 0xF2, 0x59, 0xDB, 0x03, 0x65, 0xE5, 0x60, 0x58, 0x4E, + 0x51, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x07, 0xF2, 0x87, 0xF1, + 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, 0x40, 0x47, 0x07, 0xF2, + 0x66, 0x45, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x02, 0xB0, 0xFF, 0xFF, 0x1A, 0x02, 0x27, 0x43, + 0x0B, 0x60, 0x82, 0xF3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, + 0xD9, 0x81, 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, + 0x17, 0x60, 0x04, 0x62, 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, + 0x0C, 0x00, 0x27, 0x44, 0x40, 0x58, 0x03, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x51, 0x78, 0xFF, 0xFF, + 0x27, 0x43, 0xE7, 0x60, 0x58, 0x4E, 0x81, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x87, 0xF4, 0x66, 0x41, + 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, + 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, + 0x00, 0xF8, 0x87, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, + 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, + 0x61, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x07, 0xF2, 0x87, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, + 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, 0x40, 0x47, 0x07, 0xF2, 0x66, 0x45, 0x60, 0x46, 0x06, 0xF2, + 0x65, 0x46, 0x02, 0xB0, 0xFF, 0xFF, 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0x46, 0x06, 0xF0, + 0xFF, 0x60, 0xED, 0x64, 0xA0, 0x84, 0x06, 0xFA, 0x27, 0x43, 0x86, 0xF1, 0x17, 0x60, 0x02, 0x61, + 0xA1, 0xD3, 0xDA, 0x81, 0xD0, 0x80, 0xDC, 0x9C, 0x05, 0x05, 0xA1, 0xD3, 0x4A, 0xD9, 0xA0, 0xDD, + 0xDA, 0x9C, 0xA1, 0xD9, 0x07, 0x58, 0x03, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x51, 0x78, 0xFF, 0xFF, + 0x27, 0x43, 0xE7, 0x60, 0x58, 0x4E, 0x81, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, + 0x26, 0x46, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0xCB, 0xF3, + 0x2F, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0xCD, 0xF3, 0x31, 0xFA, 0x66, 0xF3, 0x32, 0xFA, 0x67, 0xF3, + 0x33, 0xFA, 0x68, 0xF3, 0x34, 0xFA, 0xAB, 0xF1, 0x19, 0xF8, 0x00, 0x65, 0xEF, 0x60, 0x58, 0x4E, + 0xDC, 0x78, 0xFF, 0xFF, 0x61, 0x44, 0x15, 0x60, 0xC2, 0xFB, 0x02, 0x63, 0x3F, 0xFC, 0x00, 0x64, + 0x3E, 0xFA, 0x02, 0x60, 0x00, 0x61, 0x2C, 0xF2, 0xA1, 0xDB, 0x2D, 0xF2, 0x41, 0x58, 0x59, 0xDB, + 0x2E, 0xF2, 0x59, 0xDB, 0x06, 0x63, 0x07, 0xF2, 0x87, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, + 0x0D, 0x02, 0x43, 0x59, 0x02, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0xC0, 0x64, 0x2A, 0xFA, 0x00, 0xF4, 0x06, 0x64, 0x09, 0xFA, 0x15, 0x00, 0x07, 0xF2, 0x66, 0x45, + 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x02, 0xB0, 0xFF, 0xFF, 0x1D, 0x02, 0x07, 0x63, 0x43, 0x59, + 0x01, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0xA0, 0x64, 0x2A, 0xFA, + 0x00, 0xF4, 0x07, 0x64, 0x09, 0xFA, 0x26, 0x46, 0x87, 0xF3, 0x07, 0xFA, 0x1E, 0x60, 0xD4, 0x64, + 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0xDE, 0x60, 0x66, 0x64, 0x08, 0x60, + 0x29, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0x03, 0x64, 0x08, 0x60, 0x1F, 0xFB, 0xDE, 0x60, + 0x05, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1E, 0xF1, 0x00, 0x60, + 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x59, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x71, 0xF3, 0x87, 0xF5, + 0xDC, 0x81, 0x66, 0x43, 0x02, 0xA3, 0x63, 0x46, 0xCD, 0x81, 0x06, 0xF2, 0xEE, 0x03, 0x60, 0x40, + 0x08, 0x2A, 0xF7, 0x01, 0x0C, 0xAC, 0x06, 0xFA, 0x46, 0x49, 0x00, 0x60, 0x02, 0x61, 0xB5, 0x60, + 0x58, 0x4D, 0xA2, 0x78, 0xFF, 0xFF, 0xE1, 0x03, 0x18, 0x60, 0x13, 0xF3, 0xFF, 0xFF, 0x03, 0x1B, + 0x00, 0x60, 0xA0, 0x64, 0x02, 0x00, 0x00, 0x60, 0xC0, 0x64, 0x2A, 0xFA, 0xAB, 0xFC, 0x66, 0x45, + 0x29, 0x44, 0x07, 0xFA, 0x29, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x85, 0xF2, 0x65, 0x46, 0x2C, 0xFA, + 0x2D, 0xF8, 0xAE, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0x32, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0x33, 0xFA, + 0xCD, 0xF3, 0x31, 0xFA, 0x34, 0xFA, 0xAB, 0xF1, 0x19, 0xF8, 0x18, 0x67, 0x0E, 0xFA, 0x66, 0x41, + 0x29, 0x46, 0x92, 0xF0, 0x2C, 0x60, 0x26, 0x63, 0x47, 0xD3, 0x61, 0x46, 0x00, 0x7E, 0x13, 0xFA, + 0x02, 0x63, 0x3F, 0xFC, 0x00, 0x64, 0x3E, 0xFA, 0x66, 0x41, 0x00, 0xF4, 0x18, 0x60, 0x12, 0xF3, + 0x09, 0xFA, 0x1E, 0x60, 0xE0, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x61, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, 0xA0, 0x01, 0x95, 0x01, 0x00, 0x64, 0x08, 0x60, + 0x1E, 0xFB, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x07, 0xF0, 0xFF, 0xFF, 0x64, 0x43, 0x0B, 0x60, + 0x82, 0xF3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x04, 0x03, 0xD3, 0x80, 0xD9, 0x81, + 0xFA, 0x02, 0x08, 0x00, 0xA1, 0xDD, 0xD9, 0x84, 0x0B, 0x60, 0x82, 0xFB, 0x4A, 0xD3, 0xFF, 0xFF, + 0xDC, 0x84, 0xA2, 0xDB, 0x66, 0x45, 0x63, 0x46, 0x06, 0xF2, 0xFF, 0x60, 0x01, 0x7C, 0xA0, 0x9C, + 0x06, 0xF8, 0x65, 0x46, 0x70, 0xF3, 0x60, 0x40, 0x10, 0x2A, 0x03, 0x00, 0xCC, 0x84, 0x80, 0x2B, + 0x70, 0xFB, 0x08, 0x60, 0x1E, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x30, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x02, 0x64, + 0x08, 0x60, 0x19, 0xFB, 0xDE, 0x60, 0xA8, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x70, 0xF3, 0x71, 0xF3, 0x00, 0xA8, 0x60, 0x88, 0x43, 0x03, 0xE0, 0x83, 0x5F, 0x03, 0xCB, 0x83, + 0x87, 0xF3, 0x72, 0xF1, 0x02, 0xA4, 0x40, 0x47, 0x64, 0x45, 0x27, 0x46, 0x76, 0xF4, 0x12, 0xF2, + 0x33, 0x18, 0xD4, 0x80, 0x02, 0x64, 0x30, 0x07, 0x23, 0xFA, 0x2A, 0xF2, 0x0E, 0xF2, 0x0C, 0xB0, + 0x02, 0xF0, 0x0C, 0x02, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xE7, 0x01, 0x60, 0x40, 0xF0, 0x37, + 0x08, 0x00, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, 0x8F, 0xF3, 0x02, 0x02, 0xDC, 0x84, + 0x8F, 0xFB, 0x1E, 0x60, 0xF2, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA3, 0xFF, 0xCE, 0xFE, 0x25, 0x60, 0xE4, 0x64, 0xE5, 0x60, + 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0xC9, 0x01, 0x27, 0x44, 0x02, 0xA4, 0x40, 0x47, 0xC5, 0x1F, + 0x28, 0x43, 0xCB, 0x83, 0x87, 0xF3, 0x1A, 0x0E, 0x02, 0xA4, 0x40, 0x4C, 0x43, 0x48, 0x2C, 0x46, + 0x22, 0xF2, 0x72, 0xF1, 0xAC, 0x86, 0x12, 0xF2, 0x0C, 0x03, 0xD0, 0x80, 0xFF, 0xFF, 0x09, 0x07, + 0x1F, 0x60, 0x20, 0x64, 0x40, 0x4B, 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, 0xFF, 0xFF, 0x2C, 0x46, + 0xA2, 0xFC, 0x2C, 0x44, 0x02, 0xA4, 0x28, 0x43, 0x40, 0x4C, 0xE8, 0x1F, 0x8B, 0x01, 0x01, 0x63, + 0x65, 0xF3, 0xAB, 0xF3, 0x00, 0xBD, 0xAC, 0x81, 0x06, 0x03, 0x05, 0x03, 0xB7, 0x60, 0x58, 0x4D, + 0xC0, 0x78, 0xFF, 0xFF, 0x60, 0x43, 0x5B, 0xFD, 0x3E, 0x63, 0x18, 0x60, 0x94, 0x61, 0x00, 0x64, + 0x59, 0xDB, 0xFE, 0x1F, 0x70, 0xFB, 0x71, 0xFB, 0x18, 0x60, 0xDC, 0x65, 0xA5, 0xDF, 0x5A, 0xDF, + 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0x70, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x03, 0x02, + 0xCA, 0x60, 0x7E, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x45, 0x64, 0x46, 0x1F, 0xF2, 0x65, 0x46, + 0x64, 0x45, 0x5B, 0xF1, 0xE0, 0x84, 0x72, 0xF1, 0xC0, 0x84, 0xC0, 0x84, 0x12, 0xFA, 0x2C, 0xF2, + 0x70, 0xF3, 0x60, 0x40, 0x01, 0x2A, 0x34, 0x00, 0x00, 0xA8, 0x13, 0x60, 0x43, 0xF3, 0x36, 0x03, + 0x00, 0xA8, 0xFF, 0xFF, 0x33, 0x03, 0xE1, 0x60, 0x58, 0x4D, 0x04, 0x78, 0xFF, 0xFF, 0x25, 0x46, + 0x09, 0x60, 0x08, 0x61, 0xA2, 0xFF, 0x0E, 0xF2, 0x02, 0xF0, 0x60, 0x40, 0xF0, 0x37, 0x0D, 0x00, + 0x91, 0xF3, 0x8F, 0xF3, 0xDC, 0x83, 0xD1, 0x80, 0x91, 0xFD, 0x0C, 0x03, 0x8B, 0xF3, 0xCC, 0x83, + 0xD8, 0xA0, 0x8F, 0xFD, 0x07, 0x04, 0xD4, 0xFE, 0x05, 0x00, 0xD1, 0x80, 0x92, 0xF3, 0x02, 0x03, + 0xDC, 0x84, 0x92, 0xFB, 0x1E, 0x60, 0xDA, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x25, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA3, 0xFF, 0xDF, 0x60, 0x2A, 0x78, 0xFF, 0xFF, + 0x66, 0x41, 0x65, 0x46, 0x06, 0xF2, 0x61, 0x46, 0x60, 0x40, 0x10, 0x2A, 0x4B, 0x00, 0x80, 0x67, + 0xB4, 0x81, 0x61, 0x44, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xE1, 0x60, 0x58, 0x4D, 0x04, 0x78, 0xFF, 0xFF, 0x25, 0x46, 0x2A, 0xF2, + 0x09, 0x60, 0x08, 0x61, 0x0C, 0xB0, 0xA2, 0xFF, 0x17, 0x03, 0x0E, 0xF2, 0x02, 0xF0, 0x60, 0x40, + 0xF0, 0x37, 0x0D, 0x00, 0x8F, 0xF3, 0x91, 0xF3, 0xCC, 0x83, 0xD1, 0x80, 0x8F, 0xFD, 0x0C, 0x03, + 0x8B, 0xF3, 0xDC, 0x83, 0xD8, 0xA0, 0x91, 0xFD, 0x07, 0x04, 0xD4, 0xFE, 0x05, 0x00, 0xD1, 0x80, + 0x92, 0xF3, 0x02, 0x03, 0xDC, 0x84, 0x92, 0xFB, 0x07, 0xF0, 0x0A, 0xF2, 0xA3, 0xFF, 0x64, 0x45, + 0x2F, 0x1B, 0x66, 0x41, 0x65, 0x46, 0x02, 0xF0, 0x61, 0x46, 0x0F, 0x60, 0xFF, 0x61, 0xA1, 0x84, + 0x60, 0x41, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, + 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x18, 0x60, 0x96, 0x65, 0x46, 0xD1, 0x61, 0x44, 0xB0, 0x84, + 0xA2, 0xDB, 0x16, 0x00, 0x1E, 0x60, 0xD4, 0x61, 0x2A, 0xF2, 0x3E, 0xF2, 0x0C, 0xB0, 0x01, 0xB0, + 0x05, 0x03, 0x1E, 0x60, 0xE6, 0x61, 0x02, 0x02, 0x1E, 0x60, 0xCE, 0x61, 0x61, 0x44, 0x0F, 0x60, + 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, + 0xDF, 0x60, 0x2A, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x2B, 0xF2, 0x2A, 0xF2, 0x60, 0x41, 0x44, 0x49, + 0x60, 0x45, 0xA4, 0x3A, 0x0D, 0x00, 0x61, 0x40, 0xC0, 0x3B, 0x79, 0x00, 0xA9, 0x46, 0x06, 0xF2, + 0xA9, 0x46, 0x60, 0x40, 0x20, 0x26, 0x73, 0x00, 0x20, 0xBC, 0xA9, 0x46, 0x06, 0xFA, 0xA9, 0x46, + 0xA9, 0x46, 0x06, 0xF0, 0xA9, 0x46, 0x65, 0x40, 0x10, 0x2B, 0x6C, 0x00, 0x64, 0x40, 0x10, 0x2A, + 0x35, 0x00, 0x65, 0x40, 0xA4, 0x3A, 0x63, 0x00, 0x29, 0x45, 0x65, 0x46, 0x76, 0xF2, 0xFF, 0xFF, + 0x00, 0xA8, 0x60, 0x46, 0x04, 0x02, 0x76, 0x00, 0xE0, 0x60, 0xEA, 0x78, 0xFF, 0xFF, 0x09, 0xF2, + 0x2A, 0xF0, 0x00, 0xA8, 0x20, 0x67, 0x02, 0x03, 0xB0, 0x84, 0x2A, 0xFA, 0x0E, 0xF2, 0x02, 0xF0, + 0x60, 0x40, 0xF0, 0x37, 0x08, 0x00, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, 0x8F, 0xF3, + 0x02, 0x02, 0xDC, 0x84, 0x8F, 0xFB, 0x3E, 0xF2, 0xA3, 0xFF, 0x01, 0xB0, 0x1E, 0x60, 0xE6, 0x61, + 0x02, 0x02, 0x1E, 0x60, 0xD4, 0x61, 0x61, 0x44, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x16, 0x00, 0x10, 0x64, 0xB0, 0x84, + 0xDF, 0x65, 0xA4, 0x9E, 0xA9, 0x46, 0x06, 0xFA, 0xA9, 0x46, 0xA2, 0xFF, 0x04, 0x64, 0x0C, 0x60, + 0x6E, 0xFB, 0x29, 0x44, 0x5A, 0xDB, 0x70, 0xF3, 0xC1, 0xFE, 0xD4, 0xFE, 0x86, 0xF1, 0xA3, 0xFF, + 0xD0, 0x80, 0xDC, 0x84, 0x01, 0x07, 0x70, 0xFB, 0xA9, 0x46, 0x76, 0xF2, 0xA9, 0x46, 0x64, 0x18, + 0xA9, 0x46, 0x02, 0xF0, 0xA9, 0x46, 0x0F, 0x60, 0xFF, 0x61, 0xA1, 0x84, 0x60, 0x41, 0xE9, 0x81, + 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, + 0xFD, 0x02, 0x18, 0x60, 0x96, 0x65, 0x46, 0xD1, 0xFF, 0xFF, 0xB1, 0x84, 0xA2, 0xDB, 0xE1, 0x60, + 0x01, 0x78, 0xFF, 0xFF, 0x64, 0x40, 0x10, 0x2A, 0xFA, 0x01, 0xFF, 0x60, 0xEF, 0x64, 0xA0, 0x84, + 0xA9, 0x46, 0x06, 0xFA, 0xA9, 0x46, 0x65, 0x41, 0x70, 0xF3, 0x29, 0x45, 0xCC, 0x84, 0x80, 0x2B, + 0x70, 0xFB, 0x65, 0x46, 0x76, 0xF2, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x36, 0x02, 0x61, 0x40, + 0xA4, 0x3A, 0xE5, 0x01, 0x00, 0x60, 0x3A, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0x9F, 0x78, 0xFF, 0xFF, + 0x83, 0x03, 0x02, 0x60, 0x48, 0x64, 0x2A, 0xFA, 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, + 0xCD, 0xF1, 0x31, 0xF8, 0x66, 0xF1, 0x32, 0xF8, 0x67, 0xF1, 0x33, 0xF8, 0x68, 0xF1, 0x34, 0xF8, + 0xA9, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x85, 0xF0, 0xA9, 0x46, 0x2C, 0xFA, 0x2D, 0xF8, 0xAE, 0xF8, + 0xAB, 0xF1, 0x19, 0xF8, 0xFF, 0x67, 0x0E, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x29, 0x44, + 0x07, 0xFA, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x35, 0x00, 0x80, 0x67, 0xB4, 0x83, 0x2A, 0xF2, + 0x09, 0x60, 0x08, 0x65, 0x0C, 0xB0, 0x09, 0xF0, 0x0C, 0x02, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, + 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x9F, 0x18, + 0x64, 0x46, 0x3E, 0xF2, 0xA2, 0xFF, 0x01, 0xB0, 0x1E, 0x60, 0xE6, 0x61, 0x02, 0x02, 0x1E, 0x60, + 0xCE, 0x61, 0x02, 0xF2, 0x0E, 0xF0, 0xD4, 0x80, 0x09, 0xF4, 0x06, 0x02, 0x8F, 0xF3, 0x64, 0x40, + 0xF0, 0x37, 0x02, 0x00, 0xDC, 0x84, 0x8F, 0xFB, 0x66, 0x44, 0x00, 0xA8, 0xFF, 0xFF, 0xF1, 0x02, + 0x61, 0x44, 0x0F, 0x60, 0x90, 0xFB, 0x5A, 0xDD, 0x08, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xC1, 0xFE, 0xA3, 0xFF, 0xA9, 0x46, 0x02, 0xF0, 0xA9, 0x46, 0x0F, 0x60, 0xFF, 0x61, 0xA1, 0x84, + 0x60, 0x41, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, + 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x18, 0x60, 0x96, 0x65, 0x46, 0xD3, 0x9D, 0x85, 0xA4, 0x84, + 0xA2, 0xDB, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x46, 0x45, 0x3F, 0xF2, 0x05, 0x48, 0x00, 0xA8, + 0x60, 0x41, 0x66, 0x44, 0x0B, 0x03, 0x0E, 0xA1, 0x00, 0xF2, 0x42, 0xFE, 0xAC, 0x86, 0x01, 0xF2, + 0x1F, 0x03, 0x7F, 0xB5, 0xD5, 0x81, 0x66, 0x44, 0xF7, 0x07, 0x25, 0x46, 0x05, 0xF0, 0x06, 0xFA, + 0x05, 0xFA, 0xD0, 0x80, 0x64, 0x43, 0x13, 0x03, 0x60, 0x46, 0x01, 0xF0, 0x80, 0x67, 0xB0, 0x84, + 0x01, 0xFA, 0x00, 0xF0, 0x00, 0x64, 0x00, 0xFA, 0x44, 0x45, 0xA2, 0xFF, 0xB6, 0x60, 0x58, 0x4E, + 0x72, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x08, 0x45, 0x25, 0x46, 0x01, 0x64, 0x02, 0xFA, 0x02, 0xFE, + 0x2D, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x07, 0xF0, 0x10, 0xB0, 0x10, 0xAC, 0x3A, 0x03, 0x23, 0xFA, + 0x80, 0x67, 0xB0, 0x81, 0x61, 0x44, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x04, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x46, 0x45, 0x64, 0x46, 0x02, 0xF0, 0x0F, 0x60, 0xFF, 0x61, + 0xA1, 0x84, 0x60, 0x41, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, 0x01, 0x61, + 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x18, 0x60, 0x96, 0x65, 0x46, 0xD1, 0xFF, 0xFF, + 0xB1, 0x84, 0xA2, 0xDB, 0x9F, 0xF2, 0x25, 0x46, 0xE1, 0x81, 0x5B, 0xF1, 0x72, 0xF1, 0xC1, 0x81, + 0xC1, 0x81, 0x92, 0xFA, 0xA2, 0xFF, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x61, 0xD1, 0x80, 0x0E, 0xF2, + 0x05, 0x02, 0x8F, 0xF3, 0x20, 0xB0, 0xCC, 0x84, 0x01, 0x02, 0x8F, 0xFB, 0xA3, 0xFF, 0x48, 0xFE, + 0x07, 0x00, 0x0E, 0xF2, 0x08, 0xFE, 0xF0, 0x7F, 0x60, 0x40, 0x20, 0x2A, 0x00, 0x7F, 0x0E, 0xFA, + 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0xC5, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0xA2, 0x78, 0xFF, 0xFF, + 0x66, 0x44, 0x57, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x80, 0x64, 0x2A, 0xFA, 0xAB, 0xF1, 0x19, 0xF8, + 0x00, 0x64, 0x3E, 0xFA, 0x00, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0x87, 0xF1, 0x07, 0xF8, 0x67, 0x44, + 0x2C, 0xFA, 0x2D, 0xFA, 0x2E, 0xFA, 0xE4, 0x60, 0x65, 0x64, 0x08, 0x60, 0x25, 0xFB, 0xE2, 0x60, + 0xA0, 0x64, 0x08, 0x60, 0x2B, 0xFB, 0x18, 0x60, 0xE6, 0x63, 0x65, 0x44, 0xBD, 0xDB, 0x10, 0x60, + 0x58, 0x64, 0xBD, 0xDB, 0x02, 0x64, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, 0xE9, 0x60, 0xB2, 0x78, + 0xFF, 0xFF, 0xE9, 0x60, 0x58, 0x4D, 0xBE, 0x78, 0xFF, 0xFF, 0x57, 0xF5, 0xCB, 0xF1, 0x2F, 0xF8, + 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0x66, 0xF1, 0x32, 0xF8, 0x67, 0xF1, 0x33, 0xF8, + 0x68, 0xF1, 0x34, 0xF8, 0x13, 0x60, 0x45, 0xF1, 0x01, 0x64, 0x64, 0x40, 0xFE, 0x26, 0x10, 0xBC, + 0x32, 0x40, 0x10, 0x26, 0x10, 0xBC, 0x20, 0xBC, 0x04, 0x60, 0x00, 0x65, 0x60, 0x44, 0xB4, 0x84, + 0x17, 0x60, 0x22, 0xFB, 0x13, 0x60, 0x44, 0xF1, 0x26, 0x60, 0x16, 0x64, 0x02, 0x18, 0x26, 0x60, + 0x38, 0x64, 0x16, 0x60, 0xBF, 0xFB, 0x16, 0x60, 0xCF, 0xFB, 0x2C, 0x60, 0x84, 0x61, 0x13, 0x60, + 0x97, 0xF3, 0x2D, 0x60, 0x5E, 0x65, 0xFE, 0xA4, 0xE0, 0x84, 0x02, 0x05, 0x67, 0x44, 0x21, 0x00, + 0xE0, 0x84, 0xC4, 0x85, 0x16, 0x60, 0x55, 0xF3, 0xA5, 0xD1, 0xDA, 0x85, 0xA0, 0x83, 0x16, 0x60, + 0x51, 0xFD, 0xA5, 0xD1, 0x2C, 0x60, 0xA0, 0x62, 0xA0, 0x83, 0xA2, 0xDD, 0x2C, 0x60, 0x84, 0x61, + 0x50, 0x60, 0x00, 0x7C, 0x00, 0x60, 0xF2, 0x65, 0xE2, 0x60, 0x58, 0x4D, 0x06, 0x78, 0xFF, 0xFF, + 0x16, 0x60, 0x53, 0xF1, 0x59, 0xD9, 0x2C, 0x60, 0x7E, 0x65, 0xD5, 0x84, 0xDD, 0x7F, 0xA5, 0xDB, + 0x65, 0x44, 0x16, 0x60, 0xC4, 0xFB, 0x16, 0x60, 0xD4, 0xFB, 0x79, 0x00, 0x16, 0x60, 0x54, 0xF3, + 0x2C, 0x60, 0xA0, 0x62, 0xFD, 0xA0, 0xA2, 0xD3, 0xEE, 0x03, 0x60, 0x40, 0x02, 0x2A, 0x02, 0x00, + 0x01, 0x63, 0x0B, 0x00, 0x04, 0x2A, 0x02, 0x00, 0x02, 0x63, 0x07, 0x00, 0x10, 0x2A, 0x02, 0x00, + 0x04, 0x63, 0x03, 0x00, 0x20, 0x2A, 0x01, 0x00, 0x05, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, + 0x59, 0xDD, 0x16, 0x60, 0x54, 0xF3, 0x16, 0x60, 0x51, 0xF3, 0xFE, 0xA0, 0x40, 0x4C, 0xD3, 0x03, + 0x00, 0x60, 0x00, 0x63, 0x59, 0xDD, 0x41, 0x4A, 0x2C, 0x40, 0x01, 0x2A, 0x05, 0x00, 0x00, 0x63, + 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x63, + 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x04, 0x2A, 0x05, 0x00, 0x02, 0x63, 0x63, 0x47, 0xB4, 0x83, + 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x10, 0x2A, 0x05, 0x00, 0x04, 0x63, 0x63, 0x47, 0xB4, 0x83, + 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x20, 0x2A, 0x05, 0x00, 0x05, 0x63, 0x63, 0x47, 0xB4, 0x83, + 0x59, 0xD9, 0x59, 0xDD, 0x2A, 0x44, 0x51, 0x93, 0xEB, 0x83, 0xEB, 0x83, 0xA0, 0xDD, 0x16, 0x60, + 0x54, 0xF3, 0x16, 0x60, 0x52, 0xF3, 0xFF, 0xA0, 0x40, 0x4C, 0x9D, 0x03, 0x59, 0xDF, 0x41, 0x4A, + 0x2C, 0x40, 0x01, 0x2A, 0x05, 0x00, 0x00, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, + 0x2C, 0x40, 0x02, 0x2A, 0x05, 0x00, 0x01, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, + 0x2C, 0x40, 0x04, 0x2A, 0x05, 0x00, 0x02, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, + 0x2A, 0x44, 0x51, 0x93, 0xEB, 0x83, 0xEB, 0x83, 0xA0, 0xDD, 0x2D, 0x58, 0xFF, 0xFF, 0x57, 0xF5, + 0xCB, 0xF3, 0xCC, 0xF1, 0x00, 0x63, 0xC0, 0x87, 0xCD, 0xF1, 0x5A, 0xFD, 0xC0, 0x85, 0x65, 0x47, + 0xC4, 0x84, 0x07, 0xB5, 0x18, 0x60, 0xE2, 0x64, 0x0F, 0x60, 0xA5, 0xFB, 0x02, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0x10, 0x60, 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x02, 0x64, + 0x08, 0x60, 0x13, 0xFB, 0xE2, 0x60, 0xA9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x10, 0x60, 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x57, 0xF5, 0x00, 0x64, 0x94, 0xFB, + 0x95, 0xFB, 0x96, 0xFB, 0x74, 0xFB, 0x65, 0xF3, 0x00, 0x75, 0x00, 0x72, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x93, 0xC7, 0xF3, 0xED, 0xE2, 0xCC, 0x84, 0x5A, 0xFB, 0x00, 0x60, 0x04, 0x64, 0x08, 0x60, + 0x13, 0xFB, 0xE2, 0x60, 0xC7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, + 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x64, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x2B, 0x05, 0x00, + 0x67, 0x44, 0x16, 0x60, 0xC1, 0xFB, 0x16, 0x60, 0xD1, 0xFB, 0x16, 0x60, 0xF6, 0xF9, 0x2D, 0x60, + 0x86, 0x65, 0xE4, 0x60, 0x58, 0x4D, 0xE7, 0x78, 0xFF, 0xFF, 0x64, 0xF3, 0xFF, 0xFF, 0x60, 0x40, + 0x01, 0x2B, 0x05, 0x00, 0xFF, 0x60, 0xFF, 0x63, 0x16, 0x60, 0xC5, 0xFD, 0x08, 0x00, 0x2E, 0x60, + 0x1E, 0x63, 0x16, 0x60, 0xC5, 0xFD, 0xE4, 0x60, 0x58, 0x4D, 0xFF, 0x78, 0xFF, 0xFF, 0xE4, 0x60, + 0x58, 0x4D, 0x6E, 0x78, 0xFF, 0xFF, 0xE5, 0x60, 0x58, 0x4D, 0x18, 0x78, 0xFF, 0xFF, 0x57, 0xF5, + 0x00, 0xF4, 0x65, 0xF1, 0x06, 0xF8, 0x17, 0x60, 0x22, 0xF3, 0x15, 0x60, 0xDD, 0xF1, 0xFB, 0x60, + 0xFF, 0x65, 0x60, 0x44, 0xA4, 0x84, 0x60, 0x47, 0x64, 0x40, 0x10, 0x26, 0x04, 0xBC, 0x60, 0x47, + 0x07, 0xFA, 0x2D, 0x60, 0x7E, 0x64, 0x40, 0x48, 0x10, 0x61, 0x00, 0x60, 0x00, 0x64, 0xE4, 0x60, + 0x58, 0x4D, 0xA7, 0x78, 0xFF, 0xFF, 0x57, 0xF5, 0x3F, 0xFC, 0x5A, 0xF3, 0xC7, 0xF1, 0xAC, 0x83, + 0x01, 0x64, 0x02, 0x02, 0x6B, 0xFB, 0x64, 0x43, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, + 0x66, 0x44, 0x5A, 0xDB, 0x04, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xCF, 0x83, + 0x72, 0xF3, 0x5A, 0xFD, 0xDC, 0x84, 0x72, 0xFB, 0x5C, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0x5C, 0xFB, + 0x03, 0x03, 0xE3, 0x60, 0xBD, 0x78, 0xFF, 0xFF, 0x0A, 0x64, 0x5C, 0xFB, 0xA2, 0x4C, 0x20, 0x27, + 0xF8, 0x01, 0x46, 0x60, 0x50, 0x65, 0x72, 0x44, 0xD4, 0x80, 0xFF, 0xFF, 0xF2, 0x04, 0x5D, 0xFB, + 0x40, 0x48, 0x94, 0xF3, 0x5E, 0xFB, 0x40, 0x4A, 0x95, 0xF3, 0x96, 0xF3, 0x40, 0x4C, 0x60, 0x41, + 0x65, 0xF1, 0x40, 0x63, 0xAD, 0x80, 0xF0, 0xA3, 0x09, 0x02, 0x3C, 0x03, 0x2C, 0x41, 0x2A, 0x44, + 0x40, 0x4C, 0x28, 0x44, 0x40, 0x4A, 0x00, 0x64, 0x40, 0x48, 0xF4, 0x01, 0xD1, 0x80, 0x01, 0x02, + 0x31, 0x04, 0x10, 0xA3, 0x80, 0x60, 0x00, 0x65, 0xA5, 0x80, 0xCF, 0x83, 0x08, 0x02, 0x28, 0x44, + 0x60, 0x88, 0x2A, 0x44, 0x70, 0x8A, 0x2C, 0x44, 0x70, 0x8C, 0xF1, 0x81, 0xF5, 0x01, 0xE7, 0xA3, + 0x64, 0x44, 0x00, 0xA0, 0x00, 0x62, 0x02, 0x02, 0x00, 0x61, 0x1C, 0x00, 0xE0, 0x84, 0xDE, 0x82, + 0xFD, 0x04, 0x42, 0xFE, 0xF8, 0x84, 0x62, 0x45, 0xC7, 0x83, 0x60, 0x45, 0x02, 0xFE, 0xD5, 0x84, + 0x02, 0x05, 0x01, 0x05, 0x61, 0x44, 0xCF, 0x83, 0x60, 0x41, 0x08, 0x03, 0x28, 0x44, 0x60, 0x88, + 0x2A, 0x44, 0x70, 0x8A, 0x2C, 0x44, 0x70, 0x8C, 0xF1, 0x81, 0xF1, 0x01, 0xCE, 0x82, 0xE9, 0x81, + 0xFD, 0x02, 0xF1, 0x81, 0x61, 0x44, 0x00, 0xA8, 0xFF, 0xFF, 0x2F, 0x03, 0x73, 0x40, 0x5D, 0xF3, + 0xFF, 0xFF, 0x60, 0x47, 0xE8, 0x84, 0xE8, 0x84, 0x5E, 0xF3, 0x3F, 0xB5, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xB4, 0x84, 0x61, 0x45, 0xD4, 0x84, 0xC0, 0x84, + 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, 0x64, 0x44, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0xC4, 0x85, 0x61, 0x44, 0xD4, 0x80, 0xFF, 0xFF, 0x0F, 0x03, 0x60, 0x53, 0xD4, 0x84, + 0xFF, 0xFF, 0x74, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x01, 0xB4, 0x74, 0xFB, 0x13, 0x60, 0x06, 0xF3, + 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, 0xE9, 0x60, 0xFB, 0x78, 0xFF, 0xFF, + 0xC1, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x04, 0x64, 0x03, 0xFA, 0x00, 0xF4, 0x09, 0xF2, 0xFF, 0xFF, + 0x60, 0x47, 0x00, 0x3A, 0x1C, 0x00, 0x60, 0x43, 0x00, 0x36, 0x1C, 0x00, 0xE0, 0xA0, 0xDA, 0x85, + 0x16, 0x07, 0x26, 0x60, 0x16, 0x61, 0xA1, 0xD1, 0xFF, 0xFF, 0xD3, 0x80, 0xCB, 0x83, 0x0F, 0x02, + 0x07, 0x0E, 0x59, 0xD3, 0xA5, 0xD0, 0xDA, 0x85, 0xD0, 0x80, 0xFF, 0xFF, 0x08, 0x02, 0xF9, 0x1F, + 0x12, 0x1E, 0xA5, 0xD0, 0x59, 0xD3, 0xFF, 0xFF, 0x90, 0x80, 0xFF, 0x22, 0x0C, 0x00, 0xE4, 0x60, + 0x63, 0x78, 0xFF, 0xFF, 0x13, 0x60, 0x44, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x03, 0x00, + 0x26, 0x60, 0x38, 0x64, 0x02, 0x00, 0x26, 0x60, 0x16, 0x64, 0x16, 0x60, 0xCF, 0xFB, 0x26, 0x46, + 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0xCB, 0xF1, 0x2F, 0xF8, + 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0x66, 0xF1, 0x32, 0xF8, 0x67, 0xF1, 0x33, 0xF8, + 0x68, 0xF1, 0x34, 0xF8, 0x00, 0x65, 0xEF, 0x60, 0x58, 0x4E, 0xDC, 0x78, 0xFF, 0xFF, 0x61, 0x44, + 0x15, 0x60, 0xC2, 0xFB, 0x50, 0x63, 0x2A, 0xFC, 0xAB, 0xF3, 0x19, 0xFA, 0x00, 0x64, 0x3E, 0xFA, + 0x87, 0xF3, 0x07, 0xFA, 0x00, 0xF4, 0x65, 0xF1, 0x06, 0xF8, 0x17, 0x60, 0x22, 0xF3, 0x15, 0x60, + 0xDD, 0xF1, 0xFB, 0x60, 0xFF, 0xB7, 0x64, 0x40, 0x10, 0x26, 0x04, 0xBC, 0x60, 0x47, 0x07, 0xFA, + 0x2D, 0x60, 0xA6, 0x65, 0xE4, 0x60, 0x58, 0x4D, 0xE7, 0x78, 0xFF, 0xFF, 0x64, 0xF3, 0x2E, 0x60, + 0x1E, 0x63, 0x60, 0x40, 0x01, 0x27, 0x67, 0x43, 0x16, 0x60, 0xD5, 0xFD, 0x2D, 0x60, 0x9E, 0x64, + 0x40, 0x48, 0x10, 0x61, 0x00, 0x60, 0x00, 0x64, 0xE4, 0x60, 0x58, 0x4D, 0xA7, 0x78, 0xFF, 0xFF, + 0x26, 0x46, 0x3F, 0xFC, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x20, 0x44, 0x80, 0x26, 0x11, 0x00, + 0x80, 0xBC, 0x40, 0x40, 0x00, 0x64, 0x94, 0xFB, 0x95, 0xFB, 0x96, 0xFB, 0x74, 0xFB, 0x65, 0xF3, + 0x00, 0x75, 0x00, 0x72, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x93, 0xC7, 0xF3, 0xED, 0xE2, 0xCC, 0x84, + 0x5A, 0xFB, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x08, 0x60, 0x12, 0xFB, + 0x5A, 0xDB, 0x00, 0x64, 0x72, 0xFB, 0x74, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x3E, 0x63, 0x18, 0x60, + 0x94, 0x61, 0x59, 0xD1, 0x61, 0x46, 0x07, 0x1B, 0xFC, 0x1F, 0x2D, 0x60, 0xC8, 0x62, 0xA2, 0xDF, + 0x01, 0x65, 0x00, 0x61, 0x16, 0x00, 0x18, 0x60, 0xD6, 0x61, 0x49, 0xD1, 0xCB, 0x83, 0xFD, 0x18, + 0x63, 0x41, 0x04, 0xA1, 0x61, 0x45, 0x66, 0x43, 0x2D, 0x60, 0xC8, 0x64, 0xDC, 0x84, 0x60, 0xFE, + 0xBD, 0xD1, 0xA0, 0xD9, 0xCD, 0x81, 0x20, 0xFE, 0xF9, 0x02, 0x66, 0x44, 0x18, 0x60, 0x96, 0x7C, + 0xD0, 0x81, 0x5A, 0xF3, 0xC7, 0xF1, 0x2D, 0x60, 0xC6, 0x63, 0x00, 0xA0, 0x64, 0x5F, 0xBD, 0xDB, + 0x0F, 0x60, 0x6D, 0xF1, 0x02, 0x02, 0x01, 0x18, 0x01, 0xB9, 0x61, 0x44, 0x60, 0xFE, 0xA3, 0xDB, + 0xFC, 0xA3, 0x65, 0x44, 0x03, 0xA4, 0xA3, 0xDB, 0x20, 0xFE, 0x2D, 0x58, 0xFF, 0xFF, 0x17, 0x60, + 0x23, 0xFB, 0xCD, 0x81, 0x28, 0xD3, 0x5A, 0x88, 0xDC, 0x83, 0x31, 0x18, 0xFB, 0x03, 0x61, 0x40, + 0x7F, 0x3A, 0x06, 0x00, 0x17, 0x60, 0x23, 0xF3, 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x00, 0xF4, + 0x60, 0xFE, 0xA3, 0xD1, 0x5D, 0xD8, 0x61, 0x40, 0x7F, 0x3A, 0x08, 0x00, 0x20, 0xFE, 0x17, 0x60, + 0x23, 0xF3, 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x00, 0xF4, 0x60, 0xFE, 0xBF, 0xD3, 0x5D, 0xDA, + 0xFF, 0xB4, 0x00, 0x7F, 0x12, 0x03, 0xDF, 0x83, 0x61, 0x40, 0x7F, 0x3A, 0x0A, 0x00, 0x20, 0xFE, + 0x60, 0x45, 0x17, 0x60, 0x23, 0xF3, 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x65, 0x44, 0x00, 0xF4, + 0x60, 0xFE, 0xBD, 0xD1, 0xCC, 0x84, 0x5D, 0xD8, 0xEF, 0x02, 0x20, 0xFE, 0xCB, 0x01, 0x17, 0x60, + 0x23, 0xF1, 0xFD, 0xA1, 0xFF, 0xB1, 0xC1, 0x83, 0xA2, 0xDD, 0x2D, 0x58, 0xFF, 0xFF, 0x67, 0x5C, + 0x14, 0x60, 0x26, 0x61, 0xA1, 0xD3, 0xA5, 0xD9, 0x10, 0x18, 0x60, 0x43, 0x2D, 0x60, 0xEE, 0x64, + 0xA5, 0xDB, 0x60, 0xFE, 0xA0, 0xDD, 0x20, 0xFE, 0xDC, 0x84, 0xCF, 0x83, 0xE3, 0x83, 0x59, 0xD1, + 0xDC, 0x84, 0x60, 0xFE, 0xA0, 0xD9, 0x20, 0xFE, 0xFA, 0x1F, 0x2D, 0x58, 0xFF, 0xFF, 0x15, 0x60, + 0xDC, 0xF1, 0x15, 0x60, 0xDD, 0xF3, 0x64, 0x40, 0x01, 0x2A, 0x02, 0xBC, 0x64, 0x40, 0x02, 0x2A, + 0x04, 0xBC, 0x64, 0x40, 0x04, 0x2A, 0xEF, 0xB4, 0x15, 0x60, 0xDD, 0xFB, 0x07, 0xB4, 0x60, 0xFE, + 0x17, 0x60, 0x10, 0xFB, 0x20, 0xFE, 0x07, 0x7C, 0x15, 0x60, 0xDC, 0xF9, 0x2D, 0x58, 0xFF, 0xFF, + 0x20, 0x40, 0x20, 0x2A, 0x0A, 0x00, 0x0A, 0x60, 0x77, 0xF1, 0x50, 0xF3, 0x2E, 0x60, 0x31, 0x63, + 0x60, 0xFE, 0xBD, 0xD9, 0x60, 0x47, 0xA3, 0xDB, 0x20, 0xFE, 0x2D, 0x58, 0xFF, 0xFF, 0x0E, 0x57, + 0x32, 0x40, 0x40, 0x26, 0x24, 0x00, 0x45, 0x48, 0x00, 0x60, 0x10, 0x61, 0xB5, 0x60, 0x58, 0x4D, + 0x9F, 0x78, 0xFF, 0xFF, 0x1C, 0x03, 0xF2, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x00, 0x60, 0x48, 0x61, + 0x28, 0x44, 0x59, 0xDA, 0x03, 0x64, 0x38, 0x43, 0xBD, 0xD1, 0xCC, 0x84, 0x59, 0xD8, 0xFC, 0x02, + 0x39, 0x44, 0x59, 0xDA, 0x06, 0x64, 0x23, 0xFA, 0x1F, 0x60, 0x10, 0x64, 0x0F, 0x60, 0x90, 0xFB, + 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, + 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, 0x40, 0x26, 0x4F, 0x00, 0x45, 0x48, 0x00, 0x60, 0x68, 0x61, + 0xB5, 0x60, 0x58, 0x4D, 0x9F, 0x78, 0xFF, 0xFF, 0x47, 0x03, 0xF2, 0x60, 0x01, 0x64, 0x24, 0xFA, + 0x02, 0x60, 0x00, 0x61, 0x46, 0x4A, 0x38, 0x44, 0x54, 0x94, 0x03, 0x64, 0x01, 0x02, 0x09, 0x00, + 0x06, 0x63, 0x4A, 0x61, 0x38, 0x46, 0xBD, 0xD0, 0xCC, 0x84, 0x2A, 0x46, 0x59, 0xD8, 0xFA, 0x02, + 0x06, 0x00, 0xDA, 0x81, 0x38, 0x43, 0xBD, 0xD1, 0xCC, 0x84, 0x59, 0xD8, 0xFC, 0x02, 0x05, 0x63, + 0x28, 0x44, 0x02, 0xA8, 0x25, 0xFA, 0x07, 0x02, 0x03, 0x64, 0x39, 0x43, 0xBD, 0xD1, 0xCC, 0x84, + 0x59, 0xD8, 0xFC, 0x02, 0x08, 0x63, 0x28, 0x44, 0x03, 0xA8, 0x16, 0x60, 0x82, 0xF3, 0x0F, 0x03, + 0xE8, 0x85, 0xC7, 0x85, 0x60, 0x43, 0xFE, 0xA3, 0x2D, 0x60, 0x06, 0x64, 0x58, 0xD1, 0xD9, 0x81, + 0xA1, 0xD8, 0x7E, 0x2A, 0x02, 0x00, 0x00, 0xF4, 0x02, 0x61, 0xF8, 0x1F, 0x65, 0x43, 0x2A, 0x46, + 0x23, 0xFC, 0x1F, 0x60, 0x10, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, + 0x40, 0x26, 0x1B, 0x00, 0x45, 0x48, 0x00, 0x60, 0x06, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0x9F, 0x78, + 0xFF, 0xFF, 0x13, 0x03, 0x02, 0x64, 0x23, 0xFA, 0xF2, 0x60, 0x00, 0x64, 0x5A, 0xDA, 0x28, 0x44, + 0x5A, 0xDA, 0xFF, 0xFF, 0x1F, 0x60, 0x10, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0xA0, 0xD3, + 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x03, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, + 0xDD, 0x98, 0xFF, 0xFF, 0x97, 0xF1, 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0C, 0x03, + 0x08, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x05, 0x03, 0xA2, 0xDB, 0x02, 0x24, 0xC6, 0xFE, 0xDD, 0x98, + 0xFF, 0xFF, 0xFF, 0x60, 0xFE, 0x64, 0xA2, 0xDB, 0xDD, 0x98, 0xFF, 0xFF, 0xA2, 0xFF, 0x32, 0x40, + 0x40, 0x26, 0x3C, 0x00, 0x7B, 0xF3, 0x67, 0x43, 0xDC, 0x84, 0xCC, 0x84, 0x37, 0x03, 0x60, 0x46, + 0x0A, 0x02, 0x7B, 0xFD, 0x00, 0x60, 0x46, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0x9F, 0x78, 0xFF, 0xFF, + 0x66, 0x44, 0x7B, 0xFB, 0x2C, 0x03, 0x46, 0x4B, 0x25, 0x60, 0xD0, 0x61, 0x18, 0x64, 0x23, 0xFA, + 0xF1, 0x60, 0x00, 0x64, 0x24, 0xFA, 0x4A, 0x65, 0xA2, 0xFF, 0x2C, 0x63, 0x59, 0xD1, 0xA2, 0xDF, + 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF7, 0x1F, 0x12, 0x63, + 0x59, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, + 0x1F, 0x60, 0x10, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x2B, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0xA6, 0xFE, 0x00, 0x64, 0x7B, 0xFB, 0xA3, 0xFF, 0xCA, 0x60, + 0x7E, 0x78, 0xFF, 0xFF, 0xA6, 0xFE, 0xBA, 0x05, 0xA7, 0xFE, 0x0A, 0x05, 0xA5, 0xFE, 0x03, 0x04, + 0xE6, 0x60, 0x8E, 0x78, 0xFF, 0xFF, 0xA4, 0xFE, 0xF2, 0x04, 0xE7, 0x60, 0x1F, 0x78, 0xFF, 0xFF, + 0x36, 0x45, 0x19, 0x60, 0x86, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0xF3, 0x7D, 0xF1, + 0x60, 0x47, 0x07, 0xB4, 0x4E, 0xFB, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, + 0x9D, 0x84, 0xA1, 0x80, 0xA0, 0x83, 0x15, 0x03, 0x7D, 0xFD, 0x08, 0x60, 0x24, 0xF1, 0x00, 0x60, + 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x31, 0x44, 0xDE, 0xB4, 0x40, 0x51, 0x01, 0x7C, + 0xBC, 0xF9, 0x49, 0xF3, 0x01, 0x63, 0x60, 0x40, 0xFF, 0x26, 0x49, 0xFD, 0xCA, 0x60, 0x7E, 0x78, + 0xFF, 0xFF, 0xE6, 0x60, 0x8E, 0x78, 0xFF, 0xFF, 0x26, 0x60, 0xB0, 0x63, 0xBD, 0xD3, 0xBD, 0xD1, + 0xBD, 0xD1, 0xB0, 0x84, 0xB0, 0x84, 0xFF, 0xFF, 0x07, 0x02, 0x6A, 0xFB, 0x31, 0x44, 0xFE, 0xB4, + 0x40, 0x51, 0x0D, 0x64, 0x05, 0xFB, 0x1A, 0x00, 0x28, 0xF3, 0xFF, 0xFF, 0x13, 0x60, 0x52, 0xF3, + 0xC5, 0xFB, 0x64, 0xFB, 0x0F, 0x60, 0x85, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x46, 0x5E, + 0x31, 0x44, 0x21, 0xBC, 0x40, 0x51, 0xED, 0xE2, 0x0F, 0x4E, 0xD0, 0x60, 0x58, 0x4F, 0xA8, 0x78, + 0xFF, 0xFF, 0x0E, 0x4F, 0x00, 0x00, 0xE8, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0xD7, 0xFE, 0xCA, 0x60, + 0x7E, 0x78, 0xFF, 0xFF, 0x2E, 0xF5, 0x27, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, + 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, + 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, + 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, 0x60, 0x43, + 0x61, 0x46, 0x26, 0x02, 0x0B, 0x60, 0x82, 0xF3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, + 0x04, 0x03, 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0x08, 0x00, 0xA1, 0xDD, 0xD9, 0x84, 0x0B, 0x60, + 0x82, 0xFB, 0x4A, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xA2, 0xDB, 0x66, 0x45, 0x63, 0x46, 0x06, 0xF2, + 0xFF, 0x60, 0x01, 0x7C, 0xA0, 0x9C, 0x06, 0xF8, 0x65, 0x46, 0x70, 0xF3, 0x60, 0x40, 0x10, 0x2A, + 0x03, 0x00, 0xCC, 0x84, 0x80, 0x2B, 0x70, 0xFB, 0xE7, 0x60, 0x58, 0x4E, 0x81, 0x78, 0xFF, 0xFF, + 0xAD, 0x01, 0x2E, 0xF5, 0x28, 0xF0, 0x18, 0x60, 0x12, 0xF9, 0x27, 0xF2, 0x15, 0x60, 0x02, 0x65, + 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, + 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, + 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, + 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, + 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x12, 0x02, 0x63, 0x46, 0x06, 0xF2, 0xFF, 0xFF, 0x02, 0xB0, + 0x08, 0xBC, 0x0C, 0x03, 0x06, 0xFA, 0xE7, 0x60, 0x58, 0x4E, 0x81, 0x78, 0xFF, 0xFF, 0x08, 0x60, + 0x1E, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x6F, 0x01, 0x01, 0x64, + 0x51, 0xFB, 0x28, 0x60, 0x4E, 0x64, 0x52, 0xFB, 0x15, 0x60, 0xC3, 0xF3, 0xFF, 0xFF, 0x15, 0x18, + 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x10, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE7, 0x60, + 0x3D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2B, 0x60, 0x88, 0x61, 0xFF, 0x60, + 0x80, 0x65, 0xA1, 0xD3, 0xFF, 0xFF, 0xA4, 0x80, 0x59, 0xD3, 0x05, 0x02, 0x04, 0x1B, 0x59, 0xD3, + 0xFF, 0xFF, 0x01, 0x1B, 0x15, 0x00, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x08, 0x60, + 0x1B, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, + 0x08, 0x60, 0x16, 0xFB, 0xE7, 0x60, 0x60, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x00, 0x60, 0x04, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0x9F, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x23, 0xFA, + 0xF1, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x1F, 0x60, 0x10, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x00, 0x60, 0x30, 0x64, + 0x08, 0x60, 0x16, 0xFB, 0xD2, 0x60, 0xB5, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0xCA, 0x60, 0x7E, 0x78, + 0xFF, 0xFF, 0x0E, 0x57, 0x63, 0x46, 0x43, 0x47, 0x22, 0xF2, 0x76, 0xF2, 0x02, 0x1B, 0x01, 0x1B, + 0x0C, 0x00, 0x60, 0x46, 0x1F, 0x60, 0x20, 0x64, 0x40, 0x4B, 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, + 0xFF, 0xFF, 0x27, 0x46, 0x76, 0xF2, 0xFF, 0xFF, 0xF4, 0x1B, 0x37, 0x58, 0xFF, 0xFF, 0xE7, 0x60, + 0x9F, 0x64, 0x08, 0x60, 0x2A, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, + 0x08, 0x60, 0x21, 0xFB, 0x5A, 0xDB, 0x10, 0x60, 0x42, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x2F, 0x58, + 0xFF, 0xFF, 0x28, 0xF3, 0x7D, 0xF1, 0x60, 0x47, 0x07, 0xB4, 0x4E, 0xFB, 0x01, 0x61, 0x03, 0x03, + 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0xA1, 0x80, 0xB1, 0x83, 0x16, 0x02, 0xCF, 0x85, 0xA7, 0x80, + 0x7D, 0xFD, 0x0B, 0x02, 0x01, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0xA6, 0x78, 0xFF, 0xFF, 0x31, 0x44, + 0xDF, 0xB4, 0x40, 0x51, 0xD0, 0x60, 0xD9, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x21, 0xF1, 0x00, 0x60, + 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xE6, 0x60, 0x8E, 0x78, 0xFF, 0xFF, 0x28, 0xF3, + 0x7D, 0xF1, 0x60, 0x47, 0x07, 0xB4, 0x4E, 0xFB, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, + 0xFD, 0x02, 0x9D, 0x84, 0xA1, 0x80, 0xA0, 0x83, 0x13, 0x03, 0x7D, 0xFD, 0x08, 0x60, 0x24, 0xF1, + 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x7D, 0xF1, 0x31, 0x44, 0x64, 0x40, + 0xFF, 0x26, 0x03, 0x00, 0x21, 0xBC, 0x40, 0x51, 0x03, 0x00, 0xCA, 0x60, 0x7E, 0x78, 0xFF, 0xFF, + 0xE6, 0x60, 0x8E, 0x78, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, 0x40, 0x26, 0x1B, 0x00, 0x45, 0x48, + 0x00, 0x60, 0x06, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0x9F, 0x78, 0xFF, 0xFF, 0x13, 0x03, 0x02, 0x64, + 0x23, 0xFA, 0xF2, 0x60, 0x04, 0x64, 0x5A, 0xDA, 0x28, 0x44, 0x5A, 0xDA, 0xFF, 0xFF, 0x1F, 0x60, + 0x10, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0x79, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, + 0x60, 0x46, 0x0E, 0xF2, 0x59, 0x03, 0x60, 0x40, 0xF0, 0x37, 0x46, 0x00, 0xFF, 0x37, 0x3B, 0x00, + 0xFD, 0x37, 0x33, 0x00, 0x18, 0x37, 0x27, 0x00, 0xFE, 0x37, 0x2A, 0x00, 0xF8, 0x37, 0x0A, 0x00, + 0x60, 0x47, 0xFF, 0xB5, 0x10, 0x60, 0x24, 0x62, 0x46, 0xD1, 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xD8, 0x01, 0x06, 0xB4, 0xFD, 0x7F, 0x0E, 0xFA, 0x1E, 0x60, + 0xF8, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xF9, 0xFE, 0xC9, 0x01, 0xDE, 0x60, 0x58, 0x4F, 0x6C, 0x78, 0xFF, 0xFF, 0x14, 0x00, + 0xE1, 0x60, 0x58, 0x4F, 0x32, 0x78, 0xFF, 0xFF, 0xBF, 0x03, 0x23, 0xF0, 0x60, 0x40, 0x04, 0x26, + 0xE3, 0x1B, 0x02, 0x26, 0xE1, 0x18, 0xA2, 0xFF, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, + 0x8F, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0x8F, 0xFB, 0x1F, 0x60, 0x20, 0x64, 0x40, 0x4B, 0xF6, 0x60, + 0x58, 0x4D, 0xB3, 0x78, 0xFF, 0xFF, 0xA8, 0x01, 0xAC, 0xFE, 0x09, 0x05, 0xAD, 0xFE, 0x0F, 0x05, + 0xAE, 0xFE, 0xA2, 0x05, 0xAF, 0xFE, 0x37, 0x05, 0xCA, 0x60, 0x7E, 0x78, 0xFF, 0xFF, 0x08, 0x60, + 0x11, 0xF1, 0x20, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xF5, 0x01, 0x10, 0x60, + 0x56, 0x65, 0x03, 0x61, 0x07, 0x00, 0xA2, 0xDD, 0x58, 0x4F, 0x64, 0x58, 0xFF, 0xFF, 0x00, 0xB9, + 0xFF, 0xFF, 0x08, 0x03, 0x00, 0x63, 0xA5, 0xD1, 0x5A, 0xD3, 0xDA, 0x85, 0x00, 0xA8, 0xCD, 0x81, + 0xF2, 0x02, 0xF8, 0x02, 0xE1, 0x01, 0x10, 0x60, 0x20, 0x62, 0x10, 0x60, 0x46, 0x65, 0xE8, 0x60, + 0xA9, 0x63, 0x5A, 0xDF, 0xD6, 0x80, 0xFF, 0xFF, 0x04, 0x03, 0x5A, 0xDF, 0x5A, 0xDF, 0x5A, 0xDD, + 0xF9, 0x01, 0x10, 0x60, 0x54, 0x65, 0x5A, 0xDF, 0xD6, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x5A, 0xDD, + 0xFB, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x24, 0x64, 0x40, 0x41, 0x10, 0x60, 0x22, 0x63, + 0xA3, 0xD1, 0x00, 0x64, 0xD0, 0x80, 0x06, 0x61, 0x08, 0x03, 0xBD, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, + 0xB0, 0x84, 0xCD, 0x81, 0xA3, 0xDB, 0x06, 0xA3, 0xF9, 0x02, 0x10, 0x60, 0x48, 0x63, 0xA3, 0xD1, + 0x00, 0x64, 0xD0, 0x80, 0x07, 0x61, 0x19, 0x03, 0xBD, 0xDB, 0x64, 0x44, 0xFE, 0xA3, 0x02, 0xA3, + 0xCD, 0x81, 0xE8, 0x84, 0xE3, 0x03, 0x02, 0x05, 0xE1, 0x03, 0xF9, 0x01, 0x77, 0xFB, 0x79, 0xFD, + 0x61, 0x5C, 0xA3, 0xD3, 0x78, 0xF9, 0x03, 0x18, 0x58, 0x4F, 0x60, 0x58, 0xFF, 0xFF, 0x79, 0xF3, + 0x78, 0xF1, 0x60, 0x43, 0x77, 0xF3, 0x64, 0x41, 0xEA, 0x01, 0x21, 0x43, 0x10, 0x60, 0x48, 0x65, + 0xD7, 0x80, 0xBD, 0xD1, 0xBD, 0xD3, 0x03, 0x02, 0xCA, 0x60, 0x7E, 0x78, 0xFF, 0xFF, 0xA0, 0x84, + 0xBD, 0xD1, 0x43, 0x41, 0xF5, 0x03, 0xE8, 0x60, 0xAE, 0x64, 0x64, 0x58, 0x40, 0x4F, 0x2A, 0xF0, + 0x83, 0x60, 0xFF, 0x65, 0x64, 0x47, 0x03, 0x2B, 0x01, 0x00, 0x17, 0x00, 0x03, 0x26, 0x03, 0xAC, + 0x60, 0x47, 0xA4, 0x84, 0x2A, 0xFA, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, + 0x2E, 0xFA, 0x64, 0x41, 0xCB, 0xF3, 0x2F, 0xFA, 0x60, 0x43, 0xCC, 0xF3, 0x30, 0xFA, 0xCD, 0xF1, + 0x31, 0xF8, 0x32, 0xFC, 0x33, 0xFA, 0x34, 0xF8, 0x19, 0x00, 0x60, 0x47, 0xA4, 0x84, 0x2A, 0xFA, + 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0x36, 0xF2, 0x32, 0xFA, + 0x37, 0xF2, 0x33, 0xFA, 0x38, 0xF2, 0x34, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0x36, 0xFA, 0xCC, 0xF3, + 0x30, 0xFA, 0x37, 0xFA, 0xCD, 0xF3, 0x31, 0xFA, 0x38, 0xFA, 0x64, 0x41, 0x1C, 0xF2, 0x13, 0xFA, + 0x00, 0xF4, 0x0D, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, 0x28, 0x00, 0x26, 0x46, 0x04, 0x63, + 0x03, 0xFC, 0x00, 0xF4, 0x0D, 0xF2, 0x06, 0xFA, 0xEA, 0x60, 0x58, 0x4E, 0x49, 0x78, 0xFF, 0xFF, + 0xFF, 0xA0, 0x59, 0xF5, 0x19, 0x02, 0x39, 0xF2, 0x26, 0x46, 0x3F, 0xFA, 0x00, 0xF4, 0x00, 0x60, + 0x81, 0x67, 0x0D, 0xFA, 0x7C, 0x64, 0x01, 0xFA, 0x26, 0x46, 0x00, 0x64, 0x3E, 0xFA, 0x1E, 0x60, + 0xE0, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xC8, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xF0, + 0x42, 0x64, 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x04, 0x3F, 0xFA, 0x1C, 0xF2, 0x13, 0xFA, 0x26, 0xF2, + 0x27, 0xF0, 0x60, 0x47, 0x00, 0xF4, 0x1F, 0xFA, 0x64, 0x47, 0x20, 0xFA, 0x61, 0x44, 0x21, 0xFA, + 0x01, 0x67, 0x0D, 0xFA, 0x10, 0x61, 0x26, 0x60, 0x64, 0x64, 0x1E, 0x63, 0x58, 0xD1, 0xCD, 0x81, + 0xBD, 0xD8, 0xFC, 0x02, 0x9A, 0xF1, 0xB7, 0xF1, 0x64, 0x5E, 0x64, 0x5F, 0x44, 0x63, 0xBD, 0xDA, + 0x13, 0x60, 0x2F, 0xF3, 0xFF, 0xFF, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x09, 0xBC, 0x4A, 0xD3, + 0x60, 0x45, 0x60, 0x40, 0x01, 0x36, 0x03, 0x64, 0x02, 0x36, 0x01, 0x64, 0xB4, 0x84, 0x06, 0xA2, + 0xA2, 0xD1, 0xBD, 0xDA, 0x64, 0x47, 0xBD, 0xDA, 0xB4, 0xF3, 0xB5, 0xF1, 0x60, 0x47, 0xBD, 0xDA, + 0x64, 0x47, 0xC3, 0xF1, 0xBD, 0xDA, 0x64, 0x44, 0xBD, 0xDA, 0x26, 0x46, 0x00, 0x64, 0x23, 0xF0, + 0x3B, 0xF0, 0x64, 0x40, 0x10, 0x2A, 0x06, 0x00, 0xC0, 0x67, 0xA0, 0x84, 0xE8, 0x84, 0xE8, 0x84, + 0xE8, 0x84, 0x10, 0xBC, 0x3E, 0xFA, 0x1E, 0x60, 0xE0, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, 0x00, 0x66, 0x46, 0x46, + 0x2F, 0x58, 0xFF, 0xFF, 0x04, 0x60, 0x5C, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0xA2, 0x78, 0xFF, 0xFF, + 0x66, 0x44, 0x59, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x2F, 0x58, 0xFF, 0xFF, 0x59, 0xF5, 0xAB, 0xF1, + 0x19, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x08, 0x64, 0x2A, 0xFA, 0x80, 0x7E, 0xF8, 0x7F, 0x0E, 0xFA, + 0x87, 0xF1, 0x07, 0xF8, 0x01, 0x60, 0x60, 0x67, 0x2C, 0xFA, 0x1D, 0x60, 0x00, 0x67, 0x2D, 0xFA, + 0x01, 0x60, 0x00, 0x67, 0x2E, 0xFA, 0xCB, 0xF1, 0x2F, 0xF8, 0x32, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, + 0x33, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0x34, 0xF8, 0x00, 0x63, 0x3B, 0xFC, 0x3D, 0xFC, 0x01, 0x64, + 0x3A, 0xFA, 0x66, 0x64, 0x39, 0xFA, 0x3C, 0xFC, 0xAA, 0x60, 0xAA, 0x64, 0x00, 0xF4, 0x02, 0xFA, + 0x00, 0x60, 0x03, 0x64, 0x5A, 0xDA, 0x1D, 0x60, 0x60, 0x64, 0x5A, 0xDA, 0x01, 0x60, 0x00, 0x64, + 0x5A, 0xDA, 0x81, 0x7F, 0x18, 0x7E, 0x08, 0xFA, 0x01, 0x60, 0x01, 0x64, 0x0A, 0xFA, 0x00, 0x64, + 0x0E, 0xFA, 0x2D, 0x58, 0xFF, 0xFF, 0x59, 0xF5, 0x3D, 0xF2, 0x3C, 0xF2, 0xCC, 0x83, 0x00, 0xA8, + 0x03, 0x03, 0x08, 0x28, 0x3D, 0xFC, 0x42, 0x00, 0x3D, 0xFA, 0x3A, 0xF2, 0x3B, 0xF0, 0x00, 0x63, + 0x00, 0xF4, 0x07, 0xFC, 0x01, 0xB0, 0x0B, 0xFA, 0x19, 0x03, 0x1F, 0xF8, 0xFF, 0xFF, 0x18, 0x64, + 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0x1F, 0xF2, 0x1E, 0xF0, 0x59, 0xF5, 0x00, 0xA8, 0x3B, 0xF8, 0xD0, 0x80, 0x06, 0x03, 0x05, 0x03, + 0x04, 0x60, 0x5C, 0x63, 0x0F, 0x64, 0x3A, 0xFA, 0x39, 0xFC, 0x00, 0xF4, 0x00, 0x64, 0x06, 0xFA, + 0xEA, 0x60, 0x58, 0x4E, 0x49, 0x78, 0xFF, 0xFF, 0x59, 0xF5, 0x00, 0xF4, 0x81, 0x60, 0x00, 0x64, + 0x06, 0xFA, 0x32, 0x47, 0x07, 0xFA, 0xB7, 0xF1, 0x00, 0x7F, 0x64, 0x5E, 0x09, 0xFA, 0x59, 0xF5, + 0x00, 0x64, 0x15, 0xFA, 0x39, 0xF2, 0x3F, 0xFA, 0x1E, 0x60, 0xCE, 0x64, 0x0F, 0x60, 0x90, 0xFB, + 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xE3, 0x60, 0xC0, 0x78, + 0xFF, 0xFF, 0x66, 0x45, 0x0E, 0xF2, 0x0F, 0xF0, 0x10, 0xF0, 0x64, 0x41, 0x01, 0xA8, 0x59, 0xF5, + 0x09, 0x02, 0xAD, 0x83, 0x64, 0x44, 0xAC, 0x84, 0x08, 0x24, 0x0A, 0x63, 0x3C, 0xFC, 0x3D, 0xFC, + 0x1A, 0x02, 0x2D, 0x00, 0x03, 0x3A, 0x03, 0x00, 0x00, 0x64, 0x3C, 0xFA, 0x29, 0x00, 0x04, 0x3A, + 0x09, 0x00, 0x0A, 0x64, 0x3C, 0xFA, 0x01, 0x64, 0x3A, 0xFA, 0x00, 0xF4, 0x00, 0x64, 0x1F, 0xFA, + 0x1E, 0xFA, 0x1E, 0x00, 0x02, 0x3A, 0x1E, 0x00, 0x64, 0x44, 0xAD, 0x83, 0xAC, 0x84, 0x02, 0x03, + 0x3C, 0xFC, 0x3D, 0xFC, 0x15, 0x03, 0x3A, 0xFA, 0xF8, 0x65, 0x52, 0x63, 0x64, 0x44, 0x01, 0x36, + 0x0D, 0x00, 0x12, 0xA3, 0x64, 0x40, 0x02, 0x2A, 0x02, 0x00, 0xC7, 0x83, 0xC7, 0x83, 0x64, 0x40, + 0x08, 0x2A, 0x01, 0x00, 0xC7, 0x83, 0x64, 0x40, 0x04, 0x26, 0xC7, 0x83, 0x39, 0xFC, 0x00, 0x64, + 0x2E, 0x58, 0xFF, 0xFF, 0x3B, 0xF0, 0x3A, 0xF2, 0x65, 0x46, 0x06, 0xF2, 0x40, 0x47, 0x1C, 0x18, + 0x32, 0x47, 0x07, 0xFA, 0x18, 0x7E, 0x81, 0x7F, 0x08, 0xFA, 0x01, 0x60, 0x01, 0x63, 0xB7, 0xF3, + 0x0A, 0xFC, 0x00, 0x7F, 0x09, 0xFA, 0x27, 0x40, 0x01, 0x2A, 0x0E, 0x00, 0x1F, 0xF8, 0x18, 0x64, + 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0x1E, 0xF0, 0x59, 0xF5, 0x3B, 0xF8, 0x65, 0x46, 0x27, 0x40, 0x02, 0x26, 0x02, 0x00, 0x00, 0xF4, + 0x13, 0x00, 0x6E, 0x61, 0xFF, 0x60, 0xFE, 0x64, 0x00, 0x60, 0x0E, 0x63, 0x58, 0xD1, 0x59, 0xD8, + 0xFD, 0x1F, 0x01, 0x60, 0xEE, 0x63, 0x00, 0xF4, 0x02, 0x61, 0x58, 0xD1, 0x59, 0xD8, 0x7E, 0x3A, + 0x02, 0x00, 0x00, 0xF4, 0x02, 0x61, 0xF9, 0x1F, 0x27, 0x40, 0x04, 0x26, 0x1A, 0x00, 0x46, 0x4B, + 0x0F, 0x60, 0x67, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x0E, 0x03, 0x89, 0xF0, 0xEB, 0x60, + 0x58, 0x4D, 0x00, 0x78, 0xFF, 0xFF, 0x65, 0x44, 0xAC, 0x86, 0xFF, 0xFF, 0x08, 0x03, 0xEB, 0x60, + 0x58, 0x4D, 0x00, 0x78, 0xFF, 0xFF, 0x04, 0x00, 0x2B, 0x46, 0x82, 0xFC, 0x00, 0xF4, 0x82, 0xFC, + 0x00, 0xF4, 0x27, 0x40, 0x08, 0x26, 0x19, 0x00, 0x46, 0x4B, 0x0F, 0x60, 0x85, 0xF3, 0xFF, 0xFF, + 0x00, 0xA8, 0x60, 0x46, 0x0E, 0x03, 0x89, 0xF0, 0xEB, 0x60, 0x58, 0x4D, 0x00, 0x78, 0xFF, 0xFF, + 0x65, 0x44, 0xAC, 0x86, 0xFF, 0xFF, 0x08, 0x03, 0xEB, 0x60, 0x58, 0x4D, 0x00, 0x78, 0xFF, 0xFF, + 0x04, 0x00, 0x65, 0x46, 0x02, 0xFA, 0x00, 0xF4, 0x82, 0xFC, 0x01, 0x64, 0x2E, 0x58, 0xFF, 0xFF, + 0x01, 0x61, 0x02, 0x64, 0x7A, 0x63, 0x58, 0xD0, 0xAB, 0x46, 0xA0, 0xD8, 0xAB, 0x46, 0xFB, 0x1F, + 0xAB, 0x46, 0x00, 0xF4, 0xCD, 0x81, 0xAB, 0x46, 0x00, 0xF4, 0xF3, 0x02, 0x2D, 0x58, 0xFF, 0xFF, + 0x00, 0x60, 0x2A, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0xA2, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x58, 0xFB, + 0x04, 0x64, 0x03, 0xFA, 0x67, 0x44, 0x2C, 0xFA, 0x2D, 0xFA, 0x2E, 0xFA, 0x32, 0xFA, 0x33, 0xFA, + 0x34, 0xFA, 0x12, 0x60, 0x80, 0x64, 0x87, 0xF1, 0x0E, 0xFA, 0x07, 0xF8, 0x00, 0x64, 0x3E, 0xFA, + 0x0A, 0x60, 0x07, 0xFB, 0x06, 0xA2, 0x10, 0x60, 0x5C, 0x64, 0xA2, 0xDB, 0x04, 0x64, 0x5A, 0xDB, + 0x06, 0x64, 0x5A, 0xDB, 0xED, 0x60, 0xD9, 0x64, 0x08, 0x60, 0x2D, 0xFB, 0x00, 0x64, 0x0A, 0x60, + 0x0D, 0xFB, 0x06, 0xA2, 0x10, 0x60, 0x60, 0x64, 0xA2, 0xDB, 0x08, 0x64, 0x5A, 0xDB, 0x06, 0x64, + 0x5A, 0xDB, 0xED, 0x60, 0xE2, 0x64, 0x08, 0x60, 0x2F, 0xFB, 0xED, 0x60, 0xBE, 0x64, 0x08, 0x60, + 0x28, 0xFB, 0x00, 0x60, 0x30, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEB, 0x60, 0x58, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0xED, 0x60, 0x70, 0x78, 0xFF, 0xFF, + 0x58, 0xF5, 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0xAB, 0xF1, + 0x19, 0xF8, 0x58, 0xF5, 0x40, 0x64, 0x2A, 0xFA, 0x64, 0xF3, 0x63, 0xFB, 0x08, 0x60, 0x1B, 0xF1, + 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x03, 0x00, + 0xEC, 0x60, 0xCB, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xC0, 0xF3, 0xEF, 0x60, 0x58, 0x4E, 0xAB, 0x78, + 0xFF, 0xFF, 0x15, 0x60, 0xC2, 0xFB, 0x15, 0x60, 0xBC, 0xF3, 0x3F, 0x40, 0x01, 0x27, 0x08, 0x00, + 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xEE, 0x60, 0x58, 0x4E, 0x26, 0x78, 0xFF, 0xFF, 0x05, 0x00, + 0x0F, 0xB4, 0xEE, 0x60, 0x58, 0x4E, 0x26, 0x78, 0xFF, 0xFF, 0x58, 0xF5, 0x2D, 0x60, 0x94, 0x64, + 0x00, 0xF4, 0x40, 0x48, 0x28, 0x60, 0x4E, 0x64, 0x20, 0x40, 0x10, 0x27, 0x02, 0x00, 0x28, 0x60, + 0x2C, 0x64, 0x28, 0xDB, 0x04, 0x61, 0x00, 0x60, 0x00, 0x64, 0xE4, 0x60, 0x58, 0x4D, 0xA7, 0x78, + 0xFF, 0xFF, 0x58, 0xF5, 0x3F, 0xFC, 0x01, 0x64, 0x52, 0xF1, 0x0C, 0x60, 0x81, 0xFB, 0x64, 0xFB, + 0xA4, 0xD3, 0x04, 0x65, 0x51, 0xF3, 0x01, 0x18, 0x0C, 0x65, 0xF3, 0xB4, 0xB4, 0x84, 0x51, 0xFB, + 0x0D, 0x00, 0xED, 0x60, 0x70, 0x78, 0xFF, 0xFF, 0x51, 0xF1, 0x64, 0xF3, 0xFF, 0xFF, 0xF3, 0xA0, + 0x04, 0xA4, 0x01, 0x04, 0xF1, 0xA4, 0x10, 0x36, 0xF4, 0x01, 0x64, 0xFB, 0x64, 0xF3, 0x15, 0x60, + 0xC3, 0xF1, 0xCC, 0x84, 0x01, 0x61, 0x08, 0x24, 0x03, 0x00, 0xE1, 0x81, 0xCC, 0x84, 0xFB, 0x01, + 0xA1, 0x84, 0x51, 0xF1, 0xEA, 0x03, 0x0C, 0x60, 0x81, 0xFB, 0x9D, 0xFE, 0x3D, 0x05, 0xBA, 0xFE, + 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, + 0x08, 0x60, 0x1C, 0xFB, 0xEB, 0x60, 0xD0, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x64, 0xF1, 0x0F, 0x60, 0x9D, 0xF9, 0x08, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEB, 0x60, + 0xF5, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x08, 0x60, 0x11, 0xF1, + 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x18, 0x60, 0x07, 0xF1, 0xAD, 0x4F, + 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x64, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, 0x64, 0x40, + 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEB, 0x60, 0xCD, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x64, 0xF1, 0x0F, 0x60, 0x9D, 0xF9, 0x0E, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEC, 0x60, + 0x2D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x08, 0x60, 0x11, 0xF1, + 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x58, 0xF5, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x64, 0x4F, 0xFB, 0x00, 0x60, 0x01, 0x64, + 0x08, 0x60, 0x1C, 0xFB, 0xEC, 0x60, 0x51, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xA5, 0xF1, 0x0A, 0x60, 0x09, 0xF9, + 0x14, 0x60, 0x0E, 0x64, 0x0F, 0x60, 0xA5, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0xA6, 0xF1, 0x0A, 0x60, 0x0F, 0xF9, 0x1F, 0x60, 0x48, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xFD, 0x1B, + 0x14, 0x60, 0x1A, 0x64, 0x0F, 0x60, 0xA5, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0x00, 0x60, 0x08, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEC, 0x60, 0x7A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x4F, 0xF1, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x64, 0x40, + 0xFF, 0x26, 0x0B, 0x00, 0x51, 0xF3, 0xFF, 0xFF, 0x80, 0xB0, 0xFF, 0xFF, 0x03, 0x03, 0xED, 0x60, + 0x6A, 0x78, 0xFF, 0xFF, 0xEB, 0x60, 0xB4, 0x78, 0xFF, 0xFF, 0x02, 0x0A, 0x00, 0x64, 0x4F, 0xFB, + 0xA7, 0xF1, 0x0A, 0x60, 0x0F, 0xF9, 0x00, 0x60, 0x0C, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEC, 0x60, + 0xA5, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x14, 0x60, 0x1A, 0x64, 0x0F, 0x60, 0xA5, 0xFB, 0x02, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, + 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0B, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0x1A, 0x64, + 0x0F, 0x60, 0xA5, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x13, 0x00, 0xFF, 0x60, + 0xF7, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x4F, 0xF3, 0xDE, 0x0A, 0x00, 0xA0, 0x00, 0x64, 0x02, 0x03, + 0x4F, 0xFB, 0xD9, 0x01, 0x14, 0x60, 0x0E, 0x64, 0x0F, 0x60, 0xA5, 0xFB, 0x03, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0xB7, 0x01, 0x15, 0x60, 0xC1, 0xF3, 0xEF, 0x60, 0x58, 0x4E, 0xAB, 0x78, + 0xFF, 0xFF, 0x15, 0x60, 0xC2, 0xFB, 0x15, 0x60, 0xBD, 0xF3, 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, + 0xEE, 0x60, 0x58, 0x4E, 0x26, 0x78, 0xFF, 0xFF, 0x58, 0xF5, 0x2D, 0x60, 0x94, 0x64, 0x00, 0xF4, + 0x40, 0x48, 0x28, 0x60, 0x4E, 0x64, 0x20, 0x40, 0x10, 0x27, 0x02, 0x00, 0x28, 0x60, 0x2C, 0x64, + 0x28, 0xDB, 0x04, 0x61, 0x00, 0x60, 0x00, 0x64, 0xE4, 0x60, 0x58, 0x4D, 0xA7, 0x78, 0xFF, 0xFF, + 0x58, 0xF5, 0x3F, 0xFC, 0x51, 0xF3, 0x20, 0x40, 0x10, 0x23, 0x02, 0x00, 0x20, 0xBC, 0x04, 0x00, + 0x60, 0x40, 0x01, 0x22, 0x40, 0xBC, 0x04, 0xBC, 0x80, 0xBC, 0x51, 0xFB, 0x11, 0x60, 0x16, 0x64, + 0x08, 0x60, 0x46, 0xFB, 0x06, 0x64, 0x08, 0x60, 0x4D, 0xFB, 0x15, 0x60, 0xC6, 0xF3, 0xFF, 0xFF, + 0x07, 0xB4, 0xA2, 0xDB, 0x51, 0xF3, 0x08, 0x60, 0x46, 0xF1, 0x60, 0x40, 0x20, 0x26, 0x03, 0x00, + 0x01, 0x26, 0x32, 0x00, 0x45, 0x00, 0x08, 0x60, 0x4D, 0xF3, 0xFF, 0xFF, 0xDD, 0xA0, 0x01, 0xA4, + 0x57, 0x03, 0xA2, 0xDB, 0x2B, 0x60, 0x88, 0x61, 0xE0, 0xA0, 0xF0, 0xA0, 0x05, 0x05, 0x01, 0x05, + 0x05, 0x00, 0x02, 0xA1, 0xF0, 0xA4, 0x02, 0x00, 0x04, 0xA1, 0xE0, 0xA4, 0xA1, 0xD1, 0x01, 0x61, + 0xDC, 0x84, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, 0xE1, 0x81, 0xFB, 0x01, 0xA1, 0x80, 0x10, 0x60, + 0x9A, 0x64, 0x01, 0x02, 0xE0, 0x01, 0xA0, 0xD3, 0x11, 0x60, 0x0E, 0x63, 0xFA, 0xA4, 0xCC, 0x84, + 0x08, 0xA3, 0xFD, 0x02, 0xB1, 0xF1, 0xA3, 0xD3, 0x01, 0x18, 0xD5, 0x18, 0xFE, 0xA3, 0xA3, 0xD3, + 0x64, 0xFB, 0xEB, 0x60, 0xCD, 0x78, 0xFF, 0xFF, 0x11, 0x60, 0xF4, 0x65, 0x64, 0x41, 0xA1, 0xD3, + 0xD5, 0x80, 0x00, 0xB8, 0x25, 0x07, 0x02, 0x02, 0x08, 0xA1, 0xF9, 0x01, 0x61, 0x44, 0x08, 0x60, + 0x46, 0xFB, 0x01, 0x64, 0xA1, 0xDB, 0x49, 0xD3, 0x64, 0xFB, 0xEB, 0x60, 0xCD, 0x78, 0xFF, 0xFF, + 0x11, 0x60, 0xF4, 0x65, 0x64, 0x41, 0xA1, 0xD3, 0xD5, 0x80, 0x04, 0xB0, 0x11, 0x07, 0x02, 0x02, + 0x08, 0xA1, 0xF9, 0x01, 0x61, 0x44, 0x08, 0x60, 0x46, 0xFB, 0x49, 0xD3, 0x64, 0xFB, 0xEB, 0x60, + 0xCD, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x46, 0xF3, 0xFF, 0xFF, 0x08, 0xA4, 0xA2, 0xDB, 0x9A, 0x01, + 0x14, 0x60, 0x0E, 0x64, 0x0F, 0x60, 0xA5, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0x51, 0xF3, 0xFF, 0xFF, 0xE3, 0xB4, 0x51, 0xFB, 0x0C, 0x60, 0x7F, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, + 0xA2, 0xDB, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, + 0x00, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xED, 0x60, 0x81, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x63, 0xF1, 0x64, 0xF9, 0x0F, 0x60, 0x9D, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xED, 0x60, 0xA3, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x08, 0x60, 0x11, 0xF1, 0x40, 0x60, 0x00, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x08, 0x60, 0x11, 0xF1, 0x10, 0x60, 0x00, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x60, 0x30, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEB, 0x60, 0x58, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x14, 0x60, 0x0E, 0x64, + 0x0F, 0x60, 0xA5, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x51, 0xFB, + 0x00, 0x64, 0x08, 0x60, 0x1B, 0xFB, 0x5A, 0xDB, 0xBE, 0xFE, 0x00, 0x60, 0x30, 0x64, 0x08, 0x60, + 0x1C, 0xFB, 0xEB, 0x60, 0x58, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, + 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x31, 0x40, 0x20, 0x2A, 0x35, 0x00, 0x3F, 0xF2, 0x47, 0x65, + 0xC4, 0x84, 0xE8, 0x84, 0x23, 0xFA, 0xF1, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x64, 0xF3, 0x01, 0x60, + 0xFF, 0x65, 0xA4, 0x84, 0x01, 0x23, 0x14, 0x00, 0x11, 0x60, 0x14, 0x61, 0x11, 0x60, 0xF4, 0x65, + 0xA1, 0xD1, 0xD5, 0x80, 0xD0, 0x80, 0x0B, 0x03, 0x02, 0x03, 0x08, 0xA1, 0xF9, 0x01, 0x04, 0xA1, + 0xA1, 0xD3, 0x01, 0x60, 0x00, 0x65, 0x60, 0x47, 0xFF, 0xB4, 0xB4, 0x84, 0x01, 0x00, 0x01, 0x64, + 0x00, 0xF4, 0x08, 0xFA, 0xFF, 0xFF, 0x26, 0x46, 0x1F, 0x60, 0x10, 0x64, 0x0F, 0x60, 0x90, 0xFB, + 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x00, 0x66, + 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x5F, 0xFB, 0xAC, 0x85, + 0x60, 0x41, 0x2E, 0x60, 0x22, 0x63, 0x16, 0x60, 0xC6, 0xFD, 0x16, 0x60, 0xCC, 0xFD, 0x16, 0x60, + 0xD6, 0xFD, 0x16, 0x60, 0xE0, 0xFD, 0x5C, 0x03, 0x61, 0x5C, 0x00, 0x63, 0xE9, 0x81, 0xFF, 0xFF, + 0x02, 0x24, 0xDF, 0x83, 0xFB, 0x02, 0x08, 0x64, 0x53, 0x90, 0x64, 0x41, 0x03, 0x04, 0x01, 0x60, + 0x08, 0x63, 0x0C, 0x00, 0x01, 0x60, 0x00, 0x63, 0x10, 0x64, 0xE9, 0x81, 0xFF, 0xFF, 0x02, 0x24, + 0xDF, 0x83, 0x08, 0x36, 0x03, 0x00, 0xCC, 0x84, 0xFF, 0xFF, 0xF7, 0x02, 0x15, 0x60, 0xEC, 0xFD, + 0x43, 0x48, 0x65, 0x41, 0x2B, 0x60, 0xDA, 0x63, 0x28, 0x44, 0xFF, 0xB5, 0x10, 0x60, 0x08, 0x64, + 0xE9, 0x81, 0x58, 0xD1, 0xFD, 0x04, 0xA3, 0xD9, 0x0C, 0x03, 0x58, 0xD1, 0xE9, 0x81, 0x40, 0x4A, + 0xFC, 0x04, 0xA3, 0xD1, 0x64, 0x47, 0xB0, 0x84, 0xBD, 0xDB, 0x65, 0x44, 0xC8, 0x85, 0x2A, 0x44, + 0xEF, 0x02, 0x28, 0x43, 0x08, 0x3A, 0x24, 0x00, 0x60, 0x45, 0x04, 0x64, 0x32, 0x60, 0x00, 0x63, + 0x41, 0x48, 0xE9, 0x81, 0xCC, 0x84, 0x02, 0x24, 0xDF, 0x83, 0xFB, 0x02, 0x63, 0x40, 0x00, 0x36, + 0x17, 0x00, 0x17, 0x60, 0x11, 0xFD, 0x2E, 0x60, 0x24, 0x63, 0x65, 0x44, 0x28, 0x41, 0xE9, 0x81, + 0x58, 0xD1, 0xFD, 0x04, 0xA3, 0xD9, 0x15, 0x03, 0x58, 0xD1, 0xE9, 0x81, 0x60, 0x45, 0xFC, 0x04, + 0xA3, 0xD1, 0x64, 0x47, 0xB0, 0x84, 0xBD, 0xDB, 0x00, 0xB9, 0x65, 0x44, 0xF0, 0x02, 0x09, 0x00, + 0x67, 0x43, 0x16, 0x60, 0xC6, 0xFD, 0x16, 0x60, 0xCC, 0xFD, 0x16, 0x60, 0xD6, 0xFD, 0x16, 0x60, + 0xE0, 0xFD, 0x20, 0x40, 0x10, 0x27, 0x0D, 0x00, 0x2B, 0x60, 0xE2, 0x61, 0x15, 0x60, 0xEC, 0xF3, + 0xA1, 0xDB, 0xFF, 0xB4, 0xCC, 0x84, 0xA8, 0x83, 0x2B, 0x60, 0xD8, 0x64, 0x58, 0xD1, 0x59, 0xD9, + 0xFD, 0x1F, 0x2B, 0x60, 0xE4, 0x63, 0x15, 0x60, 0xBE, 0xF3, 0x08, 0x61, 0x60, 0xFE, 0xA3, 0xD1, + 0xFF, 0xFF, 0x20, 0xFE, 0x00, 0xA8, 0xE8, 0x84, 0x0F, 0x03, 0x60, 0xFE, 0x02, 0x28, 0xF6, 0x01, + 0x80, 0x62, 0xB2, 0x9C, 0xBD, 0xD9, 0x62, 0xF9, 0xCD, 0x81, 0x00, 0x36, 0x01, 0x00, 0xEE, 0x01, + 0x2E, 0x60, 0x24, 0x63, 0x08, 0x61, 0xEA, 0x01, 0x2E, 0x58, 0xFF, 0xFF, 0x2B, 0x60, 0x7C, 0x63, + 0x65, 0x40, 0xFF, 0x36, 0x02, 0xA3, 0xA3, 0xD3, 0xFF, 0xFF, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, + 0xE8, 0x84, 0x40, 0x26, 0x7F, 0xB4, 0x20, 0x26, 0x3F, 0xB4, 0x60, 0x45, 0x80, 0x63, 0xEF, 0x60, + 0x58, 0x4D, 0x33, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xDF, 0xFB, 0x40, 0x63, 0xEF, 0x60, 0x58, 0x4D, + 0x33, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xE0, 0xFB, 0x20, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x33, 0x78, + 0xFF, 0xFF, 0x15, 0x60, 0xE1, 0xFB, 0x10, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x33, 0x78, 0xFF, 0xFF, + 0x15, 0x60, 0xE2, 0xFB, 0x08, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x33, 0x78, 0xFF, 0xFF, 0x15, 0x60, + 0xE3, 0xFB, 0x04, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x33, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xE4, 0xFB, + 0x02, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x33, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xE5, 0xFB, 0x01, 0x63, + 0xEF, 0x60, 0x58, 0x4D, 0x33, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xE6, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, + 0x15, 0x60, 0xBE, 0xF3, 0xFF, 0xFF, 0x0F, 0xB4, 0x60, 0x45, 0x08, 0x63, 0xEF, 0x60, 0x58, 0x4D, + 0x5E, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xE7, 0xFB, 0x04, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x5E, 0x78, + 0xFF, 0xFF, 0x15, 0x60, 0xE8, 0xFB, 0x02, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x5E, 0x78, 0xFF, 0xFF, + 0x15, 0x60, 0xE9, 0xFB, 0x01, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x5E, 0x78, 0xFF, 0xFF, 0x15, 0x60, + 0xEA, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x63, 0x5C, 0xA7, 0x84, 0xEB, 0x83, 0x14, 0x02, 0x01, 0x03, + 0xFB, 0x01, 0x64, 0x44, 0x01, 0x36, 0x0B, 0x64, 0x02, 0x36, 0x0B, 0x64, 0x04, 0x36, 0x0A, 0x64, + 0x08, 0x36, 0x0A, 0x64, 0x10, 0x36, 0x09, 0x64, 0x20, 0x36, 0x09, 0x64, 0x40, 0x36, 0x09, 0x64, + 0x80, 0x36, 0x09, 0x64, 0x11, 0x00, 0x60, 0x40, 0x01, 0x36, 0x0B, 0x64, 0x02, 0x36, 0x0F, 0x64, + 0x04, 0x36, 0x0A, 0x64, 0x08, 0x36, 0x0E, 0x64, 0x10, 0x36, 0x09, 0x64, 0x20, 0x36, 0x0D, 0x64, + 0x40, 0x36, 0x08, 0x64, 0x80, 0x36, 0x0C, 0x64, 0x2D, 0x58, 0xFF, 0xFF, 0x63, 0x5C, 0xA7, 0x84, + 0xEB, 0x83, 0x0C, 0x02, 0x01, 0x03, 0xFB, 0x01, 0x64, 0x44, 0x01, 0x36, 0x0A, 0x64, 0x02, 0x36, + 0x14, 0x64, 0x04, 0x36, 0x37, 0x64, 0x08, 0x36, 0x6E, 0x64, 0x09, 0x00, 0x60, 0x40, 0x01, 0x36, + 0x0A, 0x64, 0x02, 0x36, 0x14, 0x64, 0x04, 0x36, 0x37, 0x64, 0x08, 0x36, 0x6E, 0x64, 0x2D, 0x58, + 0xFF, 0xFF, 0x60, 0xFE, 0x81, 0xA1, 0x7F, 0xA1, 0x02, 0x06, 0x00, 0xF4, 0x03, 0x61, 0x5D, 0xD2, + 0xCF, 0x83, 0xD4, 0x80, 0x25, 0x03, 0x16, 0x03, 0xCF, 0x83, 0x61, 0x44, 0x80, 0xA0, 0x20, 0x03, + 0x02, 0x02, 0x00, 0xF4, 0x03, 0x61, 0x5D, 0xD2, 0xCF, 0x83, 0x81, 0xA1, 0x19, 0x03, 0x05, 0x07, + 0x7F, 0xA1, 0xCC, 0x84, 0xDD, 0x81, 0xE6, 0x03, 0xF7, 0x01, 0x00, 0xF4, 0x00, 0xB8, 0x04, 0x61, + 0xE6, 0x03, 0xF2, 0x01, 0x2C, 0x43, 0x5D, 0xD0, 0xDE, 0xD9, 0x64, 0x44, 0x5D, 0xD0, 0xDE, 0xD9, + 0xCC, 0x84, 0x81, 0xA1, 0x05, 0x03, 0x7F, 0xA1, 0xF9, 0x04, 0x00, 0xF4, 0x03, 0x61, 0xF6, 0x01, + 0x20, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x01, 0x3A, 0x02, 0x00, 0x16, 0x64, 0x2B, 0x00, 0x02, 0x3A, + 0x02, 0x00, 0x14, 0x64, 0x27, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x12, 0x64, 0x23, 0x00, 0x08, 0x3A, + 0x02, 0x00, 0x10, 0x64, 0x1F, 0x00, 0x10, 0x3A, 0x02, 0x00, 0x0E, 0x64, 0x1B, 0x00, 0x20, 0x3A, + 0x02, 0x00, 0x0C, 0x64, 0x17, 0x00, 0x40, 0x3A, 0x02, 0x00, 0x0A, 0x64, 0x13, 0x00, 0x80, 0x3A, + 0x02, 0x00, 0x08, 0x64, 0x0F, 0x00, 0x01, 0x3B, 0x02, 0x00, 0x06, 0x64, 0x0B, 0x00, 0x02, 0x3B, + 0x02, 0x00, 0x04, 0x64, 0x07, 0x00, 0x04, 0x3B, 0x02, 0x00, 0x02, 0x64, 0x03, 0x00, 0x08, 0x3B, + 0xFF, 0x01, 0x00, 0x64, 0x2E, 0x58, 0xFF, 0xFF, 0x27, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x36, 0x3A, + 0x02, 0x00, 0x00, 0x61, 0x2C, 0x00, 0x30, 0x3A, 0x02, 0x00, 0x02, 0x61, 0x28, 0x00, 0x24, 0x3A, + 0x02, 0x00, 0x04, 0x61, 0x24, 0x00, 0x18, 0x3A, 0x02, 0x00, 0x06, 0x61, 0x20, 0x00, 0x12, 0x3A, + 0x02, 0x00, 0x08, 0x61, 0x1C, 0x00, 0x0C, 0x3A, 0x02, 0x00, 0x0A, 0x61, 0x18, 0x00, 0x09, 0x3A, + 0x02, 0x00, 0x0C, 0x61, 0x14, 0x00, 0x06, 0x3A, 0x02, 0x00, 0x0E, 0x61, 0x10, 0x00, 0x6E, 0x3A, + 0x02, 0x00, 0x10, 0x61, 0x0C, 0x00, 0x37, 0x3A, 0x02, 0x00, 0x12, 0x61, 0x08, 0x00, 0x14, 0x3A, + 0x02, 0x00, 0x14, 0x61, 0x04, 0x00, 0x0A, 0x3A, 0xFF, 0xFF, 0x16, 0x61, 0x00, 0x00, 0x65, 0x40, + 0x01, 0x3A, 0x13, 0x00, 0x66, 0x45, 0x2B, 0x46, 0x92, 0xFA, 0x65, 0x46, 0x26, 0xF2, 0xFF, 0xFF, + 0x60, 0x41, 0x00, 0x7F, 0x60, 0x45, 0x61, 0x47, 0x00, 0x7F, 0xD4, 0x84, 0x66, 0x41, 0x2B, 0x46, + 0x0E, 0xF2, 0x60, 0x45, 0x65, 0x5E, 0x0E, 0xFA, 0x61, 0x46, 0x2E, 0x58, 0xFF, 0xFF, 0xCD, 0x81, + 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, 0x01, 0x64, 0x2E, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x02, 0x64, + 0x2A, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x04, 0x64, 0x26, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x08, 0x64, + 0x22, 0x00, 0x0C, 0x3A, 0x02, 0x00, 0x10, 0x64, 0x1E, 0x00, 0x12, 0x3A, 0x02, 0x00, 0x20, 0x64, + 0x1A, 0x00, 0x18, 0x3A, 0x02, 0x00, 0x40, 0x64, 0x16, 0x00, 0x24, 0x3A, 0x02, 0x00, 0x80, 0x64, + 0x12, 0x00, 0x30, 0x3A, 0x02, 0x00, 0x01, 0x7F, 0x0E, 0x00, 0x48, 0x3A, 0x02, 0x00, 0x02, 0x7F, + 0x0A, 0x00, 0x60, 0x3A, 0x02, 0x00, 0x04, 0x7F, 0x06, 0x00, 0x6C, 0x3A, 0x02, 0x00, 0x08, 0x7F, + 0x02, 0x00, 0x00, 0x64, 0x00, 0x00, 0x20, 0xFE, 0x2A, 0x45, 0x34, 0x8A, 0x60, 0xFE, 0x61, 0x40, + 0x00, 0x36, 0x02, 0x00, 0xBD, 0xD3, 0xC3, 0x01, 0x2E, 0x58, 0xFF, 0xFF, 0x53, 0xFB, 0x54, 0xFB, + 0x00, 0x60, 0x0C, 0x63, 0x14, 0x60, 0xEC, 0x62, 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0x02, 0x64, + 0x0A, 0x60, 0x78, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x0A, 0x60, 0x7A, 0xF3, 0x00, 0x63, 0xF0, 0xA0, + 0x01, 0xA4, 0x03, 0x03, 0xA2, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0xA2, 0xDD, 0x0A, 0x60, 0x7B, 0xF1, + 0xA2, 0xDD, 0x5A, 0xD3, 0xA2, 0xDD, 0xC0, 0x81, 0x61, 0x44, 0x02, 0x24, 0xFF, 0xFF, 0xE9, 0x81, + 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0x5A, 0xD3, 0xE9, 0x81, 0xE8, 0x83, 0xEB, 0x83, 0xEB, 0x83, + 0xEB, 0x83, 0xEB, 0x85, 0xD4, 0x85, 0xC5, 0x83, 0xA2, 0xDD, 0x63, 0x47, 0x00, 0x7F, 0x0A, 0x60, + 0x77, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x7F, 0x67, 0x01, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0xB1, 0xFE, + 0x05, 0x05, 0xB0, 0xFE, 0x06, 0x05, 0xB2, 0xFE, 0xB3, 0xFE, 0x21, 0x00, 0xF7, 0x60, 0x38, 0x78, + 0xFF, 0xFF, 0x28, 0xF3, 0x29, 0xF1, 0x40, 0x44, 0x44, 0x45, 0x2A, 0xF1, 0x2B, 0xF1, 0x44, 0x46, + 0x44, 0x47, 0x3F, 0xB4, 0xE0, 0x85, 0x19, 0x60, 0x06, 0x64, 0x44, 0xD7, 0x58, 0x43, 0xFF, 0xFF, + 0x60, 0x45, 0x0A, 0x60, 0x7E, 0xF3, 0x61, 0x43, 0x04, 0xB4, 0x24, 0x44, 0x02, 0x03, 0x13, 0xFF, + 0x06, 0x00, 0x3F, 0xB4, 0xB4, 0x84, 0xFF, 0x27, 0x05, 0xFD, 0x04, 0xFB, 0x10, 0x75, 0xA1, 0xFF, + 0xFF, 0xFF, 0x86, 0x3E, 0xB4, 0xFE, 0x09, 0x05, 0xB5, 0xFE, 0x02, 0x24, 0x7F, 0xF7, 0xFF, 0xFF, + 0xFF, 0xFF, 0xB7, 0xFE, 0x05, 0x05, 0xB6, 0xFE, 0xF2, 0x01, 0xF7, 0x60, 0x73, 0x78, 0xFF, 0xFF, + 0x36, 0x44, 0x00, 0x7F, 0xEE, 0xA0, 0x60, 0x45, 0x05, 0x05, 0x19, 0x60, 0x98, 0x64, 0x44, 0xD7, + 0xFF, 0xFF, 0xFF, 0xFF, 0xE4, 0x01, 0xE3, 0x01, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, + 0x7F, 0x67, 0x02, 0x61, 0x10, 0x02, 0x10, 0x64, 0x40, 0x40, 0x02, 0x64, 0x40, 0x50, 0x61, 0xFF, + 0x3F, 0x40, 0x40, 0x26, 0x04, 0x00, 0x10, 0xE0, 0x46, 0x60, 0x09, 0xE0, 0x00, 0x00, 0x27, 0xF1, + 0x00, 0x66, 0x20, 0x78, 0x42, 0xFE, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, + 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x19, 0x02, 0x0A, 0x60, 0x7E, 0xF3, 0x07, 0x7C, 0x20, 0xB5, + 0x0C, 0xB5, 0x04, 0x03, 0x03, 0x02, 0xBC, 0xF9, 0x00, 0x67, 0x0F, 0x00, 0x00, 0x61, 0x41, 0x56, + 0xC7, 0xFE, 0xB5, 0x01, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, + 0x04, 0x00, 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, + 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x31, 0x02, 0x0A, 0x60, 0x7E, 0xF3, + 0x01, 0x7C, 0x20, 0xB5, 0x0C, 0xB5, 0x03, 0x03, 0x02, 0x02, 0xBC, 0xF9, 0xFF, 0xFF, 0x02, 0x61, + 0x41, 0x56, 0xC7, 0xFE, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x7D, 0xF1, 0x20, 0x44, 0x64, 0x40, + 0xFF, 0x26, 0x1C, 0x00, 0x7F, 0xB4, 0x40, 0x40, 0x5C, 0x5E, 0x82, 0xFF, 0x26, 0x44, 0xFD, 0xB4, + 0x40, 0x46, 0x5C, 0x41, 0x87, 0xFF, 0x62, 0xFF, 0x0F, 0x60, 0x85, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, + 0x60, 0x46, 0x04, 0x03, 0x09, 0xF2, 0x8F, 0xFC, 0xAC, 0x86, 0xFB, 0x01, 0xD3, 0xF3, 0xFF, 0xFF, + 0xFE, 0xB4, 0xD3, 0xFB, 0x06, 0x64, 0x0F, 0x60, 0x9F, 0xFB, 0x2D, 0xFF, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x25, 0x46, 0x01, 0xF2, 0x08, 0xF0, 0x60, 0x47, 0x03, 0xB4, 0x03, 0xAC, 0x7F, 0x67, + 0x03, 0x61, 0x08, 0x02, 0x1F, 0x60, 0x26, 0x64, 0x40, 0x4B, 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, + 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x24, 0x40, 0x01, 0x2B, 0x49, 0x00, 0x25, 0x44, + 0x1F, 0xB4, 0xE0, 0x85, 0xF1, 0x60, 0x76, 0x64, 0xC4, 0x98, 0xFF, 0xFF, 0xC0, 0xFE, 0x3D, 0x00, + 0xC1, 0xFE, 0x3B, 0x00, 0xC2, 0xFE, 0x39, 0x00, 0xC3, 0xFE, 0x37, 0x00, 0xC4, 0xFE, 0x35, 0x00, + 0xC5, 0xFE, 0x33, 0x00, 0xC6, 0xFE, 0x31, 0x00, 0xC7, 0xFE, 0x2F, 0x00, 0xC8, 0xFE, 0x2D, 0x00, + 0xC9, 0xFE, 0x2B, 0x00, 0xCA, 0xFE, 0x29, 0x00, 0xCB, 0xFE, 0x27, 0x00, 0xCC, 0xFE, 0x25, 0x00, + 0xCD, 0xFE, 0x23, 0x00, 0xCE, 0xFE, 0x21, 0x00, 0xCF, 0xFE, 0x1F, 0x00, 0xD0, 0xFE, 0x1D, 0x00, + 0xD1, 0xFE, 0x1B, 0x00, 0xD2, 0xFE, 0x19, 0x00, 0xD3, 0xFE, 0x17, 0x00, 0xD4, 0xFE, 0x15, 0x00, + 0xD5, 0xFE, 0x13, 0x00, 0xD6, 0xFE, 0x11, 0x00, 0xD7, 0xFE, 0x0F, 0x00, 0xD8, 0xFE, 0x0D, 0x00, + 0xD9, 0xFE, 0x0B, 0x00, 0xDA, 0xFE, 0x09, 0x00, 0xDB, 0xFE, 0x07, 0x00, 0xDC, 0xFE, 0x05, 0x00, + 0xDD, 0xFE, 0x03, 0x00, 0xDE, 0xFE, 0x01, 0x00, 0xDF, 0xFE, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x00, 0x64, 0x9F, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9D, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x9C, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x9A, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x99, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x98, 0xFE, 0xF0, 0x84, + 0xFF, 0xFF, 0x97, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x96, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x95, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x94, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x93, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x92, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x91, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x90, 0xFE, 0xF0, 0x84, + 0x06, 0xFB, 0x8F, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8D, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x8C, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x8A, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x89, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x88, 0xFE, 0xF0, 0x84, + 0xFF, 0xFF, 0x87, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x86, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x85, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x84, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x83, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x82, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x81, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x80, 0xFE, 0xF0, 0x84, + 0x05, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x5C, 0x5C, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x24, 0x40, 0x01, 0x27, 0x55, 0x00, 0x05, 0x60, 0x00, 0x63, 0x05, 0xFD, 0x30, 0x44, 0xBD, 0xDB, + 0x31, 0x44, 0xBD, 0xDB, 0x32, 0x44, 0xBD, 0xDB, 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, + 0x35, 0x44, 0xBD, 0xDB, 0x36, 0x44, 0xBD, 0xDB, 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, + 0x39, 0x44, 0xBD, 0xDB, 0x3A, 0x44, 0xBD, 0xDB, 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, + 0x3D, 0x44, 0xBD, 0xDB, 0x3E, 0x44, 0xBD, 0xDB, 0x3F, 0x44, 0xBD, 0xDB, 0x02, 0x61, 0x61, 0x44, + 0x02, 0x36, 0x82, 0xFF, 0x03, 0x36, 0x83, 0xFF, 0x04, 0x36, 0x84, 0xFF, 0x05, 0x36, 0x85, 0xFF, + 0x06, 0x36, 0x86, 0xFF, 0x07, 0x36, 0x87, 0xFF, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, + 0x22, 0x44, 0xBD, 0xDB, 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, + 0x26, 0x44, 0xBD, 0xDB, 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, + 0x2A, 0x44, 0xBD, 0xDB, 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, + 0x2E, 0x44, 0xBD, 0xDB, 0x2F, 0x44, 0xBD, 0xDB, 0xDD, 0x81, 0x08, 0x3A, 0xD0, 0x01, 0x54, 0x00, + 0x27, 0x40, 0x10, 0x26, 0x30, 0x00, 0x26, 0x44, 0x01, 0x36, 0x2D, 0x00, 0x02, 0x36, 0x82, 0xFF, + 0x03, 0x36, 0x83, 0xFF, 0x04, 0x36, 0x84, 0xFF, 0x05, 0x36, 0x85, 0xFF, 0x06, 0x36, 0x86, 0xFF, + 0x25, 0x44, 0x00, 0x36, 0x44, 0x40, 0x01, 0x36, 0x44, 0x41, 0x02, 0x36, 0x44, 0x42, 0x03, 0x36, + 0x44, 0x43, 0x04, 0x36, 0x44, 0x44, 0x05, 0x36, 0x44, 0x45, 0x06, 0x36, 0x44, 0x46, 0x07, 0x36, + 0x44, 0x47, 0x08, 0x36, 0x44, 0x48, 0x09, 0x36, 0x44, 0x49, 0x0A, 0x36, 0x44, 0x4A, 0x0B, 0x36, + 0x44, 0x4B, 0x0C, 0x36, 0x44, 0x4C, 0x0D, 0x36, 0x44, 0x4D, 0x0E, 0x36, 0x44, 0x4E, 0x0F, 0x36, + 0x44, 0x4F, 0x87, 0xFF, 0x21, 0x00, 0x25, 0x44, 0x10, 0x36, 0x44, 0x50, 0x11, 0x36, 0x44, 0x51, + 0x12, 0x36, 0x44, 0x52, 0x13, 0x36, 0x44, 0x53, 0x14, 0x36, 0x44, 0x54, 0x15, 0x36, 0x44, 0x55, + 0x16, 0x36, 0x44, 0x56, 0x17, 0x36, 0x44, 0x57, 0x18, 0x36, 0x44, 0x58, 0x19, 0x36, 0x44, 0x59, + 0x1A, 0x36, 0x44, 0x5A, 0x1B, 0x36, 0x44, 0x5B, 0x1C, 0x36, 0x44, 0x5C, 0x1D, 0x36, 0x44, 0x5D, + 0x1E, 0x36, 0x44, 0x5E, 0x1F, 0x36, 0x44, 0x5F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0x46, + 0xB5, 0x60, 0x58, 0x4F, 0x4B, 0x78, 0xFF, 0xFF, 0x03, 0x61, 0x7F, 0x67, 0x0A, 0x02, 0x00, 0xF0, + 0x04, 0x64, 0x0F, 0x60, 0x93, 0xFB, 0x5A, 0xD9, 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, + 0x02, 0x61, 0x12, 0x02, 0x14, 0x64, 0x0F, 0x60, 0x9F, 0xFB, 0x00, 0x60, 0x50, 0x63, 0x5A, 0xDD, + 0xF2, 0x60, 0xF7, 0x64, 0x7F, 0xFB, 0x2D, 0xFF, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x2A, 0xF3, + 0x05, 0xFB, 0x2B, 0xF3, 0x06, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, 0xC0, 0x64, + 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x0E, 0x02, 0x16, 0x64, 0x0F, 0x60, 0x9F, 0xFB, + 0x00, 0x60, 0x50, 0x63, 0x5A, 0xDD, 0xF3, 0x60, 0x12, 0x64, 0x7F, 0xFB, 0x2D, 0xFF, 0xF0, 0x60, + 0xC7, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, + 0xA4, 0x80, 0x02, 0x61, 0x35, 0x02, 0x25, 0x45, 0xF1, 0x60, 0x02, 0x64, 0xD4, 0x80, 0xFF, 0xFF, + 0x34, 0x03, 0xF1, 0x60, 0x00, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x01, 0x03, 0x28, 0x00, 0x15, 0x60, + 0xC3, 0xF1, 0x99, 0xF3, 0x19, 0x60, 0x00, 0x61, 0xA0, 0x84, 0xA1, 0xDB, 0x25, 0x45, 0x1E, 0x60, + 0x96, 0x63, 0x01, 0x61, 0xBD, 0xD3, 0xBD, 0xD1, 0xD4, 0x80, 0xBD, 0xD3, 0xBD, 0xD5, 0xCD, 0x81, + 0x02, 0x03, 0x15, 0x03, 0xF7, 0x01, 0xA2, 0xFF, 0xA6, 0xD3, 0x40, 0x4C, 0x00, 0xA8, 0x67, 0x43, + 0x0C, 0x02, 0xA2, 0xDD, 0x42, 0x48, 0x64, 0x41, 0xB5, 0x60, 0x58, 0x4D, 0xA2, 0x78, 0xFF, 0xFF, + 0x66, 0x44, 0x28, 0xDB, 0x02, 0x03, 0x2C, 0x58, 0xA3, 0xFF, 0x0C, 0x61, 0x03, 0x00, 0x04, 0x61, + 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xF1, 0x60, 0x02, 0x64, 0xD4, 0x80, + 0x7F, 0x67, 0x06, 0x63, 0xF8, 0x02, 0x31, 0x40, 0x21, 0x2A, 0xF5, 0x01, 0x01, 0x64, 0x0C, 0x60, + 0x82, 0xFB, 0xFF, 0xFF, 0xC4, 0xFE, 0xEE, 0x01, 0xC6, 0xFE, 0xEC, 0x01, 0x7E, 0x60, 0xC0, 0x64, + 0x24, 0x45, 0xA4, 0x80, 0x02, 0x61, 0x3F, 0x02, 0x25, 0x45, 0xF8, 0x2B, 0x3B, 0x00, 0x2E, 0xF5, + 0x67, 0x44, 0xD4, 0x80, 0x19, 0x60, 0xAA, 0x63, 0x39, 0x03, 0x7E, 0x61, 0x24, 0x44, 0x01, 0x27, + 0x29, 0x00, 0xA3, 0xFC, 0xA4, 0xF8, 0xBD, 0xD3, 0xA3, 0xD1, 0xD4, 0x80, 0xCD, 0x81, 0x08, 0x24, + 0x64, 0x58, 0x08, 0xA3, 0xF8, 0x02, 0x08, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xA3, 0xD1, 0xFE, 0xA0, + 0xFA, 0x60, 0x00, 0x64, 0xD0, 0x80, 0x14, 0x02, 0x13, 0x02, 0x04, 0xA3, 0xBE, 0xD3, 0xBD, 0xD1, + 0x0F, 0x18, 0xD4, 0x80, 0x0D, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x64, 0x41, + 0xDD, 0x81, 0xE1, 0x81, 0xCB, 0x83, 0x46, 0x65, 0xF8, 0x60, 0x58, 0x4F, 0x7A, 0x78, 0xFF, 0xFF, + 0x00, 0x67, 0x0A, 0x00, 0xBD, 0xD3, 0xBE, 0xD1, 0xD4, 0x80, 0xCD, 0x81, 0x08, 0x24, 0x64, 0x58, + 0x08, 0xA3, 0xF8, 0x02, 0x04, 0x61, 0x7F, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x0F, 0x64, 0x23, 0xFA, + 0x67, 0x44, 0x24, 0xFA, 0x62, 0x41, 0x3E, 0x60, 0x00, 0x65, 0x1A, 0x63, 0xF7, 0x60, 0x8C, 0x64, + 0x65, 0x46, 0x58, 0xD0, 0x2E, 0xF5, 0x59, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x4B, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0xE8, 0x84, 0xDC, 0x84, 0x23, 0xFA, 0xBF, 0xD1, 0x4A, 0x65, + 0x64, 0x43, 0xF8, 0x60, 0x58, 0x4F, 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x25, 0xF2, 0xFF, 0xFF, 0xE0, 0xA0, 0x20, 0x64, 0x01, 0x06, 0x25, 0xFA, 0x23, 0xF2, 0xDF, 0xD1, + 0xCC, 0x84, 0xE0, 0x85, 0x0B, 0x06, 0xBF, 0xD1, 0x64, 0x41, 0xD5, 0x80, 0x64, 0x43, 0x01, 0x06, + 0x65, 0x41, 0x4A, 0x65, 0xF4, 0x60, 0x58, 0x4F, 0xBD, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0xBC, 0xF3, 0x02, 0x63, 0x23, 0xFC, 0x07, 0xB4, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x4B, 0xD3, 0xBF, 0xD3, 0x60, 0x41, 0xC9, 0x83, 0xE9, 0x81, 0xDD, 0x81, 0xA3, 0xFA, + 0xE0, 0x81, 0x3C, 0x60, 0x00, 0x67, 0x02, 0x24, 0x02, 0xA4, 0x60, 0x47, 0x40, 0x4B, 0xC9, 0x81, + 0x4A, 0x65, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, + 0x00, 0xF4, 0x04, 0x65, 0xF6, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD1, + 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, 0x60, 0x47, 0x25, 0xFA, 0x00, 0x7E, 0x60, 0x47, 0x01, 0x26, + 0xDC, 0x84, 0x60, 0x41, 0xE8, 0x84, 0xD8, 0x84, 0x23, 0xFA, 0xAB, 0x01, 0xFC, 0xA3, 0xA3, 0xD1, + 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, 0x00, 0x7F, 0x25, 0xFA, 0x60, 0x41, 0x01, 0x26, 0xDD, 0x81, + 0xE9, 0x84, 0xD8, 0x84, 0x23, 0xFA, 0x9D, 0x01, 0x23, 0xF2, 0x25, 0xF2, 0x02, 0xA8, 0xF8, 0xA0, + 0x0F, 0x02, 0xEC, 0xA0, 0x0D, 0x04, 0x0C, 0x07, 0x15, 0x60, 0xD2, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, + 0xFF, 0xFF, 0x04, 0x07, 0x15, 0x60, 0xD2, 0xFB, 0x15, 0x60, 0xD6, 0xFB, 0x13, 0x60, 0x5B, 0xFB, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x14, 0x60, 0xEE, 0x65, 0x60, 0x41, 0x14, 0x60, + 0x8A, 0x63, 0xA3, 0xDB, 0xFF, 0xA1, 0x48, 0x64, 0x58, 0xD0, 0x7E, 0xA8, 0x5B, 0xD9, 0x02, 0x02, + 0x00, 0xF4, 0x02, 0x64, 0xFF, 0xA1, 0xD7, 0x80, 0x02, 0x03, 0x01, 0x03, 0xF5, 0x01, 0x2E, 0xF5, + 0x00, 0x60, 0x2F, 0x65, 0x25, 0xF2, 0x00, 0x63, 0xCC, 0x84, 0x03, 0xA3, 0xFD, 0x05, 0x4A, 0x64, + 0xD7, 0x80, 0x14, 0x60, 0x26, 0x61, 0x18, 0x05, 0xA1, 0xDD, 0xE3, 0x83, 0xFE, 0xA3, 0x58, 0xD0, + 0x7E, 0xA8, 0x59, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x00, 0x63, 0x59, 0xDD, + 0x2E, 0xF5, 0x25, 0xF0, 0x0A, 0x60, 0x13, 0xF3, 0xD3, 0x80, 0x01, 0xB0, 0x04, 0x03, 0x01, 0xA4, + 0x03, 0x03, 0xA2, 0xDB, 0x01, 0x00, 0xA2, 0xDD, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x14, 0x60, + 0x8A, 0x61, 0xA1, 0xD3, 0x23, 0xFA, 0xE0, 0x83, 0x4A, 0x65, 0x04, 0x02, 0x02, 0x63, 0x23, 0xFC, + 0xA5, 0xFC, 0x09, 0x00, 0xDB, 0x83, 0x59, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, + 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x0A, 0x60, 0x13, 0xF3, + 0x00, 0x61, 0x02, 0xA4, 0xFE, 0xA0, 0x23, 0xFA, 0x1B, 0x03, 0xFA, 0xA4, 0xFD, 0xA4, 0x01, 0xA1, + 0xFD, 0x07, 0x61, 0x43, 0x23, 0xF2, 0x25, 0xFC, 0xE0, 0x83, 0x02, 0xA3, 0x14, 0x60, 0x26, 0x61, + 0x00, 0x60, 0x4A, 0x64, 0x59, 0xD1, 0x58, 0xD8, 0x7E, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x02, 0x64, + 0xF9, 0x1F, 0x25, 0xF2, 0x23, 0xF2, 0x01, 0xB0, 0xCC, 0x84, 0x04, 0x02, 0x23, 0xFA, 0x02, 0x00, + 0x00, 0x64, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x41, 0x4B, 0x65, 0x42, 0x80, 0x64, + 0xD4, 0x85, 0x2B, 0x41, 0x00, 0xA1, 0x55, 0x8B, 0x0D, 0x03, 0x02, 0x04, 0x65, 0x41, 0x02, 0x00, + 0x00, 0x64, 0x40, 0x4B, 0xCA, 0x84, 0x58, 0xD0, 0xC9, 0x81, 0xBD, 0xD9, 0xFC, 0x02, 0x00, 0xF4, + 0x04, 0x65, 0xEC, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD3, 0x02, 0x7C, 0xA0, 0xD3, + 0x23, 0xF8, 0xDC, 0x84, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x02, 0x64, 0x23, 0xFA, + 0x01, 0x64, 0x9D, 0xFE, 0x02, 0x28, 0x02, 0x64, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x02, 0x7C, 0x23, 0xF8, 0x01, 0x64, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, + 0xA3, 0xD1, 0x02, 0x64, 0x23, 0xFA, 0x64, 0x44, 0x7C, 0x5F, 0x60, 0x45, 0x64, 0x47, 0x7C, 0x5F, + 0x88, 0xF1, 0x66, 0x41, 0xC0, 0x86, 0xA5, 0xD2, 0x61, 0x46, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x02, 0x64, 0x23, 0xFA, 0x88, 0xFF, 0x75, 0x44, 0x8D, 0xFF, 0xE8, 0x87, 0xE8, 0x84, + 0xE8, 0x84, 0x03, 0xB4, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x05, 0x64, 0x23, 0xFA, + 0x52, 0x63, 0x96, 0xF3, 0x4B, 0xDA, 0x95, 0xF3, 0x4B, 0xDA, 0x94, 0xF3, 0x4B, 0xDA, 0x60, 0x41, + 0x88, 0xFF, 0x72, 0x5C, 0x89, 0xFF, 0x4A, 0xD8, 0xA2, 0x48, 0x20, 0x23, 0x0E, 0x00, 0x64, 0x40, + 0x80, 0x27, 0x15, 0x00, 0xDC, 0x84, 0xBD, 0xDA, 0xBD, 0xD2, 0x11, 0x04, 0xDC, 0x84, 0xA2, 0xDA, + 0xA3, 0xD2, 0x0D, 0x04, 0xDC, 0x84, 0xA3, 0xDA, 0x0A, 0x00, 0x52, 0x63, 0x96, 0xF3, 0x4B, 0xDA, + 0x95, 0xF3, 0x4B, 0xDA, 0x94, 0xF3, 0x4B, 0xDA, 0x54, 0x90, 0x4C, 0x63, 0xE0, 0x02, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF0, 0x23, 0xF2, 0x15, 0x60, 0xC9, 0xF9, 0x02, 0xA8, 0x64, 0x44, + 0x1F, 0x02, 0x3F, 0x40, 0x02, 0x2B, 0x16, 0x00, 0x00, 0x37, 0x14, 0x00, 0x01, 0x3B, 0x18, 0x00, + 0x11, 0x60, 0xF9, 0x65, 0x11, 0x60, 0x19, 0x63, 0xFF, 0xB7, 0x60, 0x5C, 0xA3, 0xD3, 0x08, 0xA3, + 0x00, 0x7E, 0xD0, 0x80, 0xD7, 0x80, 0x03, 0x03, 0xF9, 0x02, 0x7F, 0x67, 0x0A, 0x00, 0xF4, 0xA3, + 0xA3, 0xD1, 0x04, 0x00, 0x00, 0xBC, 0xF2, 0xA4, 0x03, 0x03, 0x02, 0x07, 0x13, 0x60, 0x52, 0xF9, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x20, 0x63, 0x27, 0x60, 0x06, 0x61, 0x48, 0x64, 0x58, 0xD0, + 0x59, 0xD9, 0xFD, 0x1F, 0x25, 0xF0, 0x20, 0x64, 0xD0, 0x81, 0xFF, 0xFF, 0x02, 0x07, 0x25, 0xFA, + 0x0F, 0x00, 0x27, 0x60, 0x0A, 0x63, 0xC3, 0x83, 0x01, 0x2A, 0x06, 0x00, 0xCF, 0x83, 0xA3, 0xD3, + 0xCD, 0x81, 0x00, 0x7F, 0xBD, 0xDB, 0x04, 0x03, 0x00, 0x64, 0xC9, 0x81, 0xBD, 0xDB, 0xFD, 0x02, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x01, 0x60, 0x6E, 0x63, 0x7F, 0x67, + 0x3A, 0x18, 0xA3, 0xD9, 0x26, 0xF0, 0x7F, 0x67, 0x36, 0x18, 0x5B, 0xD9, 0x13, 0x60, 0x0A, 0xF3, + 0x25, 0xF0, 0x60, 0x40, 0x03, 0x3A, 0x2E, 0x00, 0x86, 0xF3, 0x87, 0xF3, 0x60, 0x43, 0xE3, 0x83, + 0x60, 0x46, 0x0F, 0xF8, 0x30, 0x61, 0x94, 0xFA, 0x01, 0x61, 0x91, 0xFA, 0x16, 0x64, 0x12, 0xFA, + 0x60, 0x40, 0x10, 0x36, 0x05, 0x00, 0x12, 0x36, 0x08, 0x00, 0x0C, 0x36, 0x0B, 0x00, 0x0F, 0x00, + 0x40, 0x61, 0xA1, 0x80, 0x0A, 0x64, 0x11, 0x02, 0xF3, 0x01, 0x10, 0x61, 0xA1, 0x80, 0x0E, 0x64, + 0x0C, 0x02, 0xEE, 0x01, 0x08, 0x61, 0xA1, 0x80, 0x10, 0x64, 0x07, 0x02, 0xE9, 0x01, 0xE1, 0x81, + 0xA1, 0x80, 0x05, 0x05, 0xC8, 0x84, 0x01, 0x02, 0xE3, 0x01, 0x12, 0xFA, 0x91, 0xFA, 0x66, 0x44, + 0x02, 0xA6, 0xD7, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA5, 0xF0, 0xA3, 0xD1, + 0xFF, 0xFF, 0x64, 0x5E, 0x00, 0x7F, 0x60, 0x41, 0x64, 0x47, 0x7C, 0x5F, 0x88, 0xF1, 0x66, 0x43, + 0xC0, 0x86, 0x65, 0x44, 0xA1, 0xDA, 0x63, 0x46, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, + 0xA3, 0xD1, 0xFF, 0xFF, 0x64, 0x5E, 0x00, 0x7F, 0x60, 0x45, 0x64, 0x47, 0x7C, 0x5F, 0x88, 0xF1, + 0x66, 0x41, 0xC0, 0x86, 0x65, 0x44, 0xA0, 0xD2, 0x61, 0x46, 0x25, 0xFA, 0x02, 0x64, 0x23, 0xFA, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0x15, 0x60, 0xC8, 0xFB, 0xFF, 0xFF, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x00, 0x67, 0x02, 0x02, 0x2D, 0xF9, + 0x2C, 0xF9, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF2, 0x02, 0xA8, 0x00, 0xA8, 0x0A, 0x02, + 0x07, 0x03, 0xD0, 0xA0, 0x30, 0x65, 0x03, 0x04, 0xA7, 0xA0, 0x59, 0x65, 0x01, 0x06, 0x65, 0x44, + 0x13, 0x60, 0x51, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0x15, 0x60, 0xCF, 0xFB, + 0xFF, 0xFF, 0x08, 0x2A, 0x25, 0x00, 0x15, 0x60, 0xDD, 0xF3, 0xFF, 0xFF, 0xE9, 0xB4, 0x60, 0x44, + 0x15, 0x60, 0xCF, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x26, 0x02, 0xBC, 0x64, 0x40, 0x02, 0x2A, + 0x04, 0xBC, 0x64, 0x40, 0x04, 0x26, 0x08, 0x00, 0x15, 0x60, 0xDD, 0xFB, 0x13, 0x64, 0xAD, 0xFB, + 0x01, 0x60, 0x67, 0x64, 0x37, 0xFB, 0x0C, 0x00, 0x10, 0xBC, 0x15, 0x60, 0xDD, 0xFB, 0x08, 0x64, + 0xAD, 0xFB, 0x82, 0xF3, 0x01, 0x60, 0x67, 0x7C, 0x60, 0x40, 0x01, 0x27, 0x5B, 0x7C, 0x37, 0xF9, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0x15, 0x60, 0xD0, 0xFB, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x25, 0xF2, 0x15, 0x60, 0xD1, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, + 0x15, 0x60, 0xEB, 0xFB, 0xFF, 0xFF, 0x0F, 0x22, 0x41, 0x75, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x04, 0x61, 0x06, 0x00, 0x01, 0x64, 0x01, 0x00, 0x00, 0x64, 0x18, 0x60, 0x13, 0xFB, 0x06, 0x61, + 0x41, 0x56, 0xC7, 0xFE, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x78, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x10, 0x02, 0x08, 0x61, + 0x41, 0x56, 0xC7, 0xFE, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, + 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x03, 0x00, 0x04, 0x7C, 0xBC, 0xF9, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x78, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x10, 0x02, + 0x0A, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, + 0x04, 0x00, 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x03, 0x00, 0x01, 0x7C, 0xBC, 0xF9, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x02, 0x63, 0x64, 0xF3, 0x23, 0xFC, 0x60, 0x40, 0x01, 0x23, 0x17, 0x00, + 0x01, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x11, 0x60, 0x14, 0x61, 0x11, 0x60, 0xF4, 0x65, 0xA1, 0xD1, + 0xD5, 0x80, 0xD0, 0x80, 0x0B, 0x03, 0x02, 0x03, 0x08, 0xA1, 0xF9, 0x01, 0x04, 0xA1, 0xA1, 0xD3, + 0x01, 0x60, 0x00, 0x65, 0x60, 0x47, 0xFF, 0xB4, 0xB4, 0x84, 0x01, 0x00, 0xFF, 0x64, 0x25, 0xFA, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, 0x46, 0x45, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, + 0xD0, 0x80, 0x00, 0xF4, 0x01, 0xF2, 0x66, 0x5C, 0x25, 0x46, 0x56, 0x02, 0x70, 0x27, 0x54, 0x00, + 0x12, 0x64, 0x03, 0xFA, 0x04, 0xF8, 0x0E, 0xF2, 0x87, 0xFC, 0x8D, 0xFC, 0x8E, 0xFC, 0xDA, 0x82, + 0x16, 0x61, 0x00, 0x63, 0xC9, 0x81, 0x5A, 0xDC, 0xFD, 0x02, 0x60, 0x40, 0xF0, 0x3B, 0x16, 0x00, + 0x32, 0x44, 0x8E, 0xF3, 0x01, 0xB0, 0xF6, 0xA0, 0x08, 0x24, 0x2C, 0x05, 0xDC, 0x83, 0xF0, 0x67, + 0x0E, 0xFA, 0x1F, 0x60, 0x0A, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0x8E, 0xFD, 0x2B, 0xFF, 0xFE, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x4F, 0x00, 0x8F, 0xF3, 0x09, 0x65, + 0xD4, 0x80, 0xDC, 0x83, 0x17, 0x05, 0x8F, 0xFD, 0x98, 0xFE, 0x04, 0x04, 0x00, 0x7F, 0x08, 0x7E, + 0x0E, 0xFA, 0x3B, 0xFF, 0x1E, 0x60, 0xFE, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0x0E, 0xF2, 0x2B, 0xFF, 0x60, 0x40, 0x08, 0x26, 0xF7, 0xFE, 0xFD, 0x64, 0x3B, 0x42, + 0x4A, 0xDB, 0x32, 0x00, 0x8B, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, 0xFF, 0xFF, 0x0D, 0x04, 0x1F, 0x60, + 0x16, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xFC, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x21, 0x00, 0x46, 0x45, 0x00, 0x64, 0x2B, 0xDB, 0x25, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA2, 0xFF, 0x00, 0xF4, 0x01, 0xF0, + 0x0A, 0x18, 0x70, 0x67, 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, 0xC0, 0x84, 0x01, 0xFA, 0x25, 0x46, + 0x25, 0x44, 0x80, 0xFC, 0x05, 0xFA, 0xB6, 0x60, 0x58, 0x4E, 0x72, 0x78, 0xFF, 0xFF, 0xD4, 0xFE, + 0xA3, 0xFF, 0xFF, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0xD4, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, + 0x1F, 0x60, 0x04, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x0D, 0x00, 0x1E, 0x60, 0xF8, 0x64, 0x40, 0x47, + 0x58, 0x4F, 0x18, 0x00, 0x1F, 0x60, 0x10, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x03, 0x00, 0xF0, 0x60, + 0xC7, 0x78, 0xFF, 0xFF, 0x27, 0xD5, 0x0E, 0xF2, 0x0B, 0x18, 0x60, 0x40, 0x01, 0x2A, 0x08, 0x00, + 0x1F, 0x60, 0x26, 0x64, 0x40, 0x4B, 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, 0xFF, 0xFF, 0xF2, 0x01, + 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0xD5, 0x0E, 0xF2, 0x14, 0x18, 0x60, 0x40, 0x01, 0x2A, 0x11, 0x00, + 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, 0x8F, 0xF3, 0x02, 0x02, 0xCC, 0x84, + 0x8F, 0xFB, 0x1F, 0x60, 0x26, 0x64, 0x40, 0x4B, 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, 0xFF, 0xFF, + 0xE9, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xFB, 0x64, 0x3A, 0x42, 0x4A, 0xDB, 0xA2, 0xFF, 0x92, 0xF3, + 0x8E, 0xF3, 0xCC, 0x80, 0xFA, 0xA0, 0x01, 0x14, 0x1D, 0x05, 0xB5, 0x60, 0x58, 0x4D, 0x77, 0x78, + 0xFF, 0xFF, 0xA2, 0xFF, 0x17, 0x03, 0xF0, 0x67, 0x0E, 0xFA, 0x1F, 0x60, 0x0A, 0x64, 0x0F, 0x60, + 0x93, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF6, 0x64, + 0x3A, 0x42, 0x4A, 0xDB, 0x92, 0xF3, 0x8E, 0xF3, 0xCC, 0x83, 0xDC, 0x84, 0x01, 0x15, 0x92, 0xFD, + 0x8E, 0xFB, 0xD4, 0xFE, 0x91, 0xF3, 0x8F, 0xF3, 0x00, 0xA8, 0x90, 0xF1, 0x03, 0x02, 0xD0, 0x80, + 0xFF, 0xFF, 0x26, 0x05, 0xB5, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, 0x20, 0x03, + 0x00, 0x63, 0x91, 0xF3, 0x0E, 0xFC, 0xCC, 0x84, 0xFF, 0x3A, 0x91, 0xFB, 0x98, 0xFE, 0x03, 0x04, + 0x08, 0xBB, 0x0E, 0xFC, 0x3B, 0xFF, 0x1E, 0x60, 0xFE, 0x64, 0x0F, 0x60, 0x93, 0xFB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF7, 0x64, 0x3A, 0x42, 0x4A, 0xDB, + 0x8F, 0xF3, 0x0E, 0xF2, 0xDC, 0x83, 0x08, 0xB0, 0x8F, 0xFD, 0x08, 0x28, 0xF7, 0xFE, 0xD4, 0xFE, + 0xA3, 0xFF, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0xB9, 0xFE, 0x13, 0xFF, 0x24, 0x40, 0x80, 0x2B, + 0x0B, 0x00, 0xA2, 0xFF, 0x25, 0x46, 0x09, 0xF4, 0x0E, 0xF2, 0x05, 0x18, 0x08, 0xBC, 0x0E, 0xFA, + 0xFF, 0xFF, 0xF7, 0xFE, 0x01, 0x00, 0xD8, 0xFE, 0xA3, 0xFF, 0x25, 0x46, 0x3E, 0xF2, 0x00, 0xF4, + 0x08, 0xF0, 0x25, 0x46, 0x06, 0xB4, 0xFF, 0x7F, 0x10, 0xBC, 0x06, 0x26, 0xFD, 0x7F, 0x0E, 0xFA, + 0x3E, 0xF2, 0x3F, 0xF2, 0x60, 0x41, 0x08, 0x2A, 0x64, 0x47, 0x3F, 0xFA, 0x60, 0x45, 0x13, 0x60, + 0x2D, 0xF3, 0xA3, 0xFC, 0xAB, 0xFC, 0x91, 0xFC, 0xD4, 0x80, 0x38, 0x60, 0xC1, 0x65, 0xA5, 0x80, + 0x01, 0x04, 0x07, 0x03, 0x23, 0xF0, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xF8, 0x60, 0x57, 0x78, + 0xFF, 0xFF, 0xFB, 0x60, 0x58, 0x4F, 0x75, 0x78, 0xFF, 0xFF, 0x0B, 0x04, 0x23, 0xF0, 0x04, 0x64, + 0xB0, 0x84, 0xA2, 0xDA, 0x25, 0x60, 0xF4, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, + 0x46, 0x00, 0x3E, 0xF0, 0x88, 0xF1, 0x64, 0x47, 0x07, 0xB4, 0x07, 0x36, 0x3B, 0x00, 0x04, 0x03, + 0xCC, 0x84, 0xE0, 0x84, 0xC0, 0x83, 0x2D, 0x00, 0x2C, 0xF2, 0x87, 0xF1, 0x01, 0xB0, 0x64, 0x43, + 0x35, 0x02, 0x2E, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, + 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x2E, 0xF0, 0x63, 0x46, + 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x2D, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, + 0x06, 0x02, 0x61, 0x46, 0x2C, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, + 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, + 0x09, 0x00, 0x66, 0x45, 0x63, 0x46, 0x06, 0xF0, 0x65, 0x46, 0x64, 0x44, 0x0C, 0x26, 0x02, 0x00, + 0x02, 0x26, 0x04, 0x00, 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x07, 0xFC, 0x23, 0xF2, + 0xFF, 0xFF, 0x0F, 0x1B, 0x1E, 0x60, 0xE0, 0x64, 0x0F, 0x60, 0x93, 0xFB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xC8, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, + 0x0E, 0x00, 0x1E, 0x60, 0xF2, 0x64, 0x0F, 0x60, 0x93, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xCE, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0xF0, 0x60, + 0xC7, 0x78, 0xFF, 0xFF, 0xCB, 0x84, 0xC9, 0x83, 0xFF, 0xFF, 0x08, 0x04, 0x58, 0xD1, 0xA5, 0xD8, + 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x2F, 0x58, 0xFF, 0xFF, + 0x25, 0xF0, 0x14, 0x60, 0x15, 0xF9, 0x11, 0x00, 0x0D, 0x60, 0x00, 0x62, 0x40, 0x63, 0x5A, 0xDF, + 0xFE, 0x1F, 0x04, 0x65, 0x0D, 0x60, 0x00, 0x61, 0x48, 0x64, 0x3E, 0x63, 0x7C, 0xA8, 0x58, 0xD0, + 0x59, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x14, 0x60, 0x15, 0xF1, 0x0C, 0x60, + 0xDC, 0x65, 0x02, 0xFE, 0x64, 0x44, 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x87, 0x60, 0x41, 0x64, 0x44, + 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x84, 0x3E, 0xFB, 0x60, 0x42, 0x61, 0x44, 0x03, 0xA2, 0x60, 0xFE, + 0xA2, 0xDB, 0x20, 0xFE, 0x64, 0x44, 0x0D, 0x60, 0x02, 0x65, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0xC4, 0x84, 0x40, 0xFB, 0xFF, 0xFF, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, + 0x5C, 0x41, 0x25, 0xF2, 0xFF, 0xFF, 0x40, 0x42, 0x80, 0x2B, 0x04, 0x00, 0xFF, 0xB4, 0x40, 0x42, + 0x01, 0x64, 0x40, 0x41, 0x87, 0xF3, 0x46, 0x4B, 0x86, 0xF3, 0x60, 0x46, 0xE0, 0x83, 0xAB, 0x46, + 0x26, 0xF0, 0xAB, 0x46, 0x59, 0xF8, 0xAB, 0x46, 0x27, 0xF0, 0xAB, 0x46, 0x5A, 0xF8, 0xAB, 0x46, + 0x28, 0xF0, 0xAB, 0x46, 0x5B, 0xF8, 0x66, 0x44, 0x02, 0xA6, 0xF1, 0x1F, 0x87, 0xF3, 0xFF, 0xFF, + 0x60, 0x46, 0xAB, 0x46, 0x0C, 0x60, 0x3A, 0x65, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x81, 0xC9, 0x81, 0x52, 0x64, 0x0E, 0x63, 0x58, 0xD0, 0x59, 0xD9, + 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, 0xAB, 0x46, 0xF0, 0xA1, 0x76, 0x64, 0x0E, 0x63, + 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0x0C, 0x60, 0x9C, 0x65, 0xC4, 0x81, 0x60, 0x45, 0xC9, 0x81, 0x62, 0x64, 0x06, 0x63, + 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, 0xAB, 0x46, 0xF8, 0xA1, + 0xB6, 0x64, 0x06, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, 0x65, 0x44, 0x0C, 0x60, + 0xBC, 0x65, 0xC4, 0x81, 0xC9, 0x81, 0x6A, 0x64, 0x06, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, + 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x85, 0xC4, 0x84, 0x0C, 0x60, 0x82, 0x65, 0xC4, 0x81, + 0x72, 0x64, 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0xAB, 0x46, 0x21, 0x44, 0x01, 0x2A, + 0x06, 0x00, 0xFA, 0xA1, 0x90, 0x64, 0x04, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0x3B, 0xF0, + 0x21, 0x44, 0x01, 0x2A, 0x13, 0x00, 0x22, 0x44, 0x3D, 0xFB, 0x60, 0x41, 0x02, 0xFE, 0xF8, 0x84, + 0xF8, 0x84, 0xF8, 0x84, 0x3C, 0xFB, 0x0C, 0x60, 0x7E, 0x63, 0x88, 0xFF, 0xCD, 0x81, 0x06, 0xA3, + 0xFD, 0x0D, 0x8D, 0xFF, 0x3B, 0xFD, 0x64, 0x47, 0x80, 0xBF, 0x60, 0x5C, 0x22, 0x43, 0x80, 0x61, + 0x88, 0xFF, 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, 0xB1, 0x84, + 0x3B, 0xFA, 0x86, 0xF3, 0xFF, 0xFF, 0xCC, 0x83, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0x3B, 0xF0, + 0x66, 0x44, 0xB1, 0x9C, 0x3B, 0xF8, 0x02, 0xA6, 0xFA, 0x1F, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, + 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x00, 0x67, 0x24, 0x02, 0x3D, 0xF1, + 0x64, 0x44, 0x03, 0xB4, 0x40, 0x42, 0xD0, 0x80, 0x87, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xBB, 0xF4, + 0x80, 0x61, 0x02, 0x02, 0xE3, 0x83, 0xEB, 0x83, 0x22, 0x44, 0x88, 0xFF, 0xCC, 0x84, 0xE1, 0x81, + 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, 0x9D, 0x85, 0xA7, 0x83, 0x3B, 0xFC, 0x86, 0xF3, + 0xFF, 0xFF, 0xCC, 0x83, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0xBB, 0xF2, 0x66, 0x44, 0xA5, 0x81, + 0xBB, 0xFA, 0x02, 0xA6, 0xFA, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x11, 0x64, 0x23, 0xFA, + 0x25, 0x44, 0x24, 0xFA, 0x04, 0x64, 0x40, 0x4B, 0x62, 0x41, 0x0C, 0x60, 0x82, 0x64, 0x04, 0x63, + 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, 0x2B, 0x43, 0x00, 0x7C, 0x59, 0xD8, 0x4F, 0x8B, 0x06, 0xA4, + 0xF6, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x27, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, + 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, + 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, + 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, + 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x2A, 0x00, 0x43, 0x4B, 0xAB, 0x46, 0x3B, 0xF2, 0x80, 0x60, + 0x30, 0x7C, 0xB0, 0x84, 0xA2, 0xDA, 0x4E, 0x61, 0x76, 0x64, 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, + 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x90, 0x64, 0x04, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, + 0x58, 0xD8, 0xFB, 0x1F, 0xD9, 0x81, 0xA0, 0x64, 0x04, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, + 0x58, 0xD8, 0xFB, 0x1F, 0xD9, 0x81, 0xB6, 0x64, 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, + 0x58, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, + 0x23, 0x58, 0xFF, 0xFF, 0x27, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, + 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, + 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, + 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, + 0x01, 0x03, 0x0D, 0x00, 0x43, 0x4B, 0xAB, 0x46, 0x3B, 0xF2, 0x80, 0x60, 0x30, 0x61, 0x9D, 0x85, + 0xA4, 0x84, 0xA2, 0xDA, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x67, + 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x40, 0x41, 0x4A, 0x64, 0xA0, 0xD2, 0xFF, 0xFF, + 0x40, 0x42, 0x80, 0x2B, 0x04, 0x00, 0xFF, 0xB4, 0x40, 0x42, 0x01, 0x64, 0x40, 0x41, 0x87, 0xF3, + 0x46, 0x4B, 0x86, 0xF3, 0x60, 0x46, 0xE0, 0x83, 0xAB, 0x46, 0x32, 0xF0, 0xAB, 0x46, 0x59, 0xF8, + 0xAB, 0x46, 0x33, 0xF0, 0xAB, 0x46, 0x5A, 0xF8, 0xAB, 0x46, 0x34, 0xF0, 0xAB, 0x46, 0x5B, 0xF8, + 0x66, 0x44, 0x02, 0xA6, 0xF1, 0x1F, 0x87, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xAB, 0x46, 0x0C, 0x60, + 0x3A, 0x65, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x81, + 0xC9, 0x81, 0x4A, 0x64, 0x0E, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, + 0x08, 0x00, 0xAB, 0x46, 0xF0, 0xA1, 0x76, 0x64, 0x0E, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, + 0xAB, 0x46, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x85, 0xC4, 0x84, 0x0C, 0x60, 0x82, 0x65, + 0xC4, 0x81, 0x5A, 0x64, 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0xAB, 0x46, 0x21, 0x44, + 0x01, 0x2A, 0x06, 0x00, 0xFA, 0xA1, 0x90, 0x64, 0x04, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, + 0x3B, 0xF0, 0x21, 0x44, 0x01, 0x2A, 0x13, 0x00, 0x22, 0x44, 0x3D, 0xFB, 0x60, 0x41, 0x02, 0xFE, + 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x84, 0x3C, 0xFB, 0x0C, 0x60, 0x7E, 0x63, 0x88, 0xFF, 0xCD, 0x81, + 0x06, 0xA3, 0xFD, 0x0D, 0x8D, 0xFF, 0x3B, 0xFD, 0x64, 0x47, 0x80, 0xBF, 0x60, 0x5C, 0x22, 0x43, + 0x80, 0x61, 0x88, 0xFF, 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, + 0xB1, 0x84, 0x3B, 0xFA, 0x86, 0xF3, 0xFF, 0xFF, 0xCC, 0x83, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, + 0x3B, 0xF0, 0x66, 0x44, 0xB1, 0x9C, 0x3B, 0xF8, 0x02, 0xA6, 0xFA, 0x1F, 0xAB, 0x46, 0x00, 0x67, + 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x00, 0x67, 0x24, 0x02, + 0x3D, 0xF1, 0x64, 0x44, 0x03, 0xB4, 0x40, 0x42, 0xD0, 0x80, 0x87, 0xF3, 0xFF, 0xFF, 0x60, 0x46, + 0xBB, 0xF4, 0x80, 0x61, 0x02, 0x02, 0xE3, 0x83, 0xEB, 0x83, 0x22, 0x44, 0x88, 0xFF, 0xCC, 0x84, + 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, 0x9D, 0x85, 0xA7, 0x83, 0x3B, 0xFC, + 0x86, 0xF3, 0xFF, 0xFF, 0xCC, 0x83, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0xBB, 0xF2, 0x66, 0x44, + 0xA5, 0x81, 0xBB, 0xFA, 0x02, 0xA6, 0xFA, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x27, 0xF2, + 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, + 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, + 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, + 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, + 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x21, 0x00, 0x43, 0x4B, + 0xAB, 0x46, 0x3B, 0xF2, 0x80, 0x60, 0x30, 0x7C, 0xB0, 0x84, 0xA2, 0xDA, 0x4E, 0x61, 0x76, 0x64, + 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x90, 0x64, 0x04, 0x63, + 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0xA0, 0x64, 0x04, 0x63, 0xAB, 0x46, + 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, + 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x27, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, + 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, + 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, + 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, + 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x0D, 0x00, 0x43, 0x4B, 0xAB, 0x46, 0x3B, 0xF2, 0x80, 0x60, + 0x30, 0x61, 0x9D, 0x85, 0xA4, 0x84, 0xA2, 0xDA, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, + 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x3E, 0xF2, 0xAB, 0xF1, 0x08, 0xB0, + 0x19, 0xF8, 0x4A, 0x02, 0x07, 0x23, 0x2B, 0x00, 0x60, 0x47, 0x07, 0xB4, 0x88, 0xF1, 0xCC, 0x84, + 0xE0, 0x84, 0x40, 0x8A, 0xAA, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x05, 0xF2, 0x60, 0x43, 0xAA, 0x46, + 0x2C, 0xFC, 0x2D, 0xF8, 0x2E, 0xFA, 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, + 0x31, 0xF8, 0x46, 0x4A, 0x00, 0xF4, 0x02, 0xF2, 0x03, 0xF0, 0x04, 0xF2, 0x60, 0x43, 0xAA, 0x46, + 0x32, 0xFC, 0x33, 0xF8, 0x34, 0xFA, 0xAA, 0x46, 0x05, 0xF2, 0x06, 0xF0, 0x07, 0xF2, 0x60, 0x43, + 0xAA, 0x46, 0x36, 0xFC, 0x37, 0xF8, 0x38, 0xFA, 0x03, 0x60, 0x08, 0x64, 0x1C, 0x00, 0x66, 0xF1, + 0x2F, 0xF8, 0x67, 0xF1, 0x30, 0xF8, 0x68, 0xF1, 0x31, 0xF8, 0x46, 0x4A, 0x00, 0xF4, 0x02, 0xF2, + 0x03, 0xF0, 0x04, 0xF2, 0x60, 0x43, 0xAA, 0x46, 0x2C, 0xFC, 0x2D, 0xF8, 0x2E, 0xFA, 0xAA, 0x46, + 0x05, 0xF2, 0x06, 0xF0, 0x07, 0xF2, 0x60, 0x43, 0xAA, 0x46, 0x32, 0xFC, 0x33, 0xF8, 0x34, 0xFA, + 0x02, 0x60, 0x08, 0x64, 0x00, 0x00, 0x2A, 0xFA, 0x02, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x42, 0x6F, + 0x6F, 0x74, 0x63, 0x6F, 0x64, 0x65, 0x20, 0x21, 0x21, 0x20, 0x20, 0x00, 0x53, 0x54, 0x41, 0x2F, + 0x41, 0x50, 0x20, 0x46, 0x75, 0x6E, 0x63, 0x27, 0x73, 0x00, 0x20, 0x00, 0x03, 0x00, 0x01, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x04, 0x00, 0x06, 0x00, 0x07, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x07, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, + +}; /* fw_image_4_data */ + +static const CFG_IDENTITY_STRCT fw_image_infoidentity[] = { + { + sizeof( CFG_IDENTITY_STRCT ) / sizeof(hcf_16) - 1, + CFG_FW_IDENTITY, + COMP_ID_FW_AP, + 3, //Variant + 1, //Major + 24 //Minor + }, + { 0000, 0000, 0000, 0000, 0000, 0000 } //endsentinel +}; + +static const CFG_PROG_STRCT fw_image_code[] = { + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0x0148, // sizeof(fw_image_1_data), + 0x00000060, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_1_data + }, + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0x2432, // sizeof(fw_image_2_data), + 0x00000C16, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_2_data + }, + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0x194c, // sizeof(fw_image_3_data), + 0x001E3048, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_3_data + }, + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0xb7e4, // sizeof(fw_image_4_data), + 0x001F4000, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_4_data + }, + { + 5, + CFG_PROG, + CFG_PROG_STOP, // mode + 0000, + 0x000F2101, // Start execution address + }, + { 0000, 0000, 0000, 0000, 00000000, 0000, 00000000} +}; + +static const CFG_RANGE20_STRCT fw_image_infocompat[] = { + { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), + CFG_FW_SUP_RANGE, + COMP_ROLE_SUPL, + COMP_ID_APF, + { + { 4, 1, 1 } //variant, bottom, top + } + }, + { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), + CFG_MFI_ACT_RANGES_STA, + COMP_ROLE_ACT, + COMP_ID_MFI, + { + { 7, 3, 3 }, //variant, bottom, top + { 8, 1, 1 } //variant, bottom, top + } + }, + { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), + CFG_CFI_ACT_RANGES_STA, + COMP_ROLE_ACT, + COMP_ID_CFI, + { + { 4, 1, 2 } //variant, bottom, top + } + }, + { 0000, 0000, 0000, 0000, { { 0000, 0000, 0000 } } } //endsentinel +}; + +memimage fw_image = { + "FUPU7D37dhfwci\001C", //signature, , C/Bin type + (CFG_PROG_STRCT *) fw_image_code, + 0x000F2101, + 00000000, //(dummy) pdaplug + 00000000, //(dummy) priplug + (CFG_RANGE20_STRCT *) fw_image_infocompat, + (CFG_IDENTITY_STRCT *) fw_image_infoidentity, +}; + diff --git a/drivers/staging/wlags49_h2/debug.h b/drivers/staging/wlags49_h2/debug.h new file mode 100644 index 0000000000000000000000000000000000000000..0b52e17b3011230a2bd5ba619d0cd98b5b1be6a7 --- /dev/null +++ b/drivers/staging/wlags49_h2/debug.h @@ -0,0 +1,212 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * This file contains definitions and macros for debugging. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +#ifndef _DEBUG_H +#define _DEBUG_H + + + + +/* Turn on debugging here if not done with a preprocessor define */ +#ifndef DBG +#define DBG 0 +#else +#undef DBG +#define DBG 1 +#endif //DBG + + + + +#if DBG +/****************************************************************************/ + +/* Set the level of debugging if not done with a preprocessor define. See + wl_main.c, init_module() for how the debug level translates into the + the types of messages displayed */ +#ifndef DBG_LVL +#define DBG_LVL 5 /* yields nothing via init_module, + original value of 5 yields DBG_TRACE_ON and DBG_VERBOSE_ON */ +#endif // DBG_LVL + + +#define DBG_ERROR_ON 0x00000001L +#define DBG_WARNING_ON 0x00000002L +#define DBG_NOTICE_ON 0x00000004L +#define DBG_TRACE_ON 0x00000008L +#define DBG_VERBOSE_ON 0x00000010L +#define DBG_PARAM_ON 0x00000020L +#define DBG_BREAK_ON 0x00000040L +#define DBG_RX_ON 0x00000100L +#define DBG_TX_ON 0x00000200L +#define DBG_DS_ON 0x00000400L + +#define DBG_DEFAULTS (DBG_ERROR_ON | DBG_WARNING_ON | DBG_BREAK_ON) + +#define DBG_FLAGS(A) (A)->DebugFlag +#define DBG_NAME(A) (A)->dbgName +#define DBG_LEVEL(A) (A)->dbgLevel + + +#ifndef PRINTK +# define PRINTK(S...) printk(S) +#endif // PRINTK + + +#ifndef DBG_PRINT +# define DBG_PRINT(S...) PRINTK(KERN_DEBUG S) +#endif // DBG_PRINT + + +#ifndef DBG_PRINTC +# define DBG_PRINTC(S...) PRINTK(S) +#endif // DBG_PRINTC + + +#ifndef DBG_TRAP +# define DBG_TRAP {} +#endif // DBG_TRAP + + +#define _ENTER_STR ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" +#define _LEAVE_STR "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" + + +#define _DBG_ENTER(A) DBG_PRINT("%s:%.*s:%s\n",DBG_NAME(A),++DBG_LEVEL(A),_ENTER_STR,__FUNC__) +#define _DBG_LEAVE(A) DBG_PRINT("%s:%.*s:%s\n",DBG_NAME(A),DBG_LEVEL(A)--,_LEAVE_STR,__FUNC__) + + +#define DBG_FUNC(F) static const char *__FUNC__ = F; + +#define DBG_ENTER(A) {if (DBG_FLAGS(A) & DBG_TRACE_ON) _DBG_ENTER(A);} + +#define DBG_LEAVE(A) {if (DBG_FLAGS(A) & DBG_TRACE_ON) _DBG_LEAVE(A);} + +#define DBG_PARAM(A,N,F,S...) {if (DBG_FLAGS(A) & DBG_PARAM_ON) \ + DBG_PRINT(" %s -- "F"\n",N,S);} + + +#define DBG_ERROR(A,S...) {if (DBG_FLAGS(A) & DBG_ERROR_ON) \ + {DBG_PRINT("%s:ERROR:%s ",DBG_NAME(A),__FUNC__);DBG_PRINTC(S);DBG_TRAP;}} + + +#define DBG_WARNING(A,S...) {if (DBG_FLAGS(A) & DBG_WARNING_ON) \ + {DBG_PRINT("%s:WARNING:%s ",DBG_NAME(A),__FUNC__);DBG_PRINTC(S);}} + + +#define DBG_NOTICE(A,S...) {if (DBG_FLAGS(A) & DBG_NOTICE_ON) \ + {DBG_PRINT("%s:NOTICE:%s ",DBG_NAME(A),__FUNC__);DBG_PRINTC(S);}} + + +#define DBG_TRACE(A,S...) do {if (DBG_FLAGS(A) & DBG_TRACE_ON) \ + {DBG_PRINT("%s:%s ",DBG_NAME(A),__FUNC__);DBG_PRINTC(S);}} while (0) + + +#define DBG_RX(A,S...) {if (DBG_FLAGS(A) & DBG_RX_ON) \ + {DBG_PRINT(S);}} + + +#define DBG_TX(A,S...) {if (DBG_FLAGS(A) & DBG_TX_ON) \ + {DBG_PRINT(S);}} + +#define DBG_DS(A,S...) {if (DBG_FLAGS(A) & DBG_DS_ON) \ + {DBG_PRINT(S);}} + + +#define DBG_ASSERT(C) {if (!(C)) \ + {DBG_PRINT("ASSERT(%s) -- %s#%d (%s)\n", \ + #C,__FILE__,__LINE__,__FUNC__); \ + DBG_TRAP;}} + +typedef struct { + char *dbgName; + int dbgLevel; + unsigned long DebugFlag; +} dbg_info_t; + + +/****************************************************************************/ +#else // DBG +/****************************************************************************/ + +#define DBG_DEFN +#define DBG_TRAP +#define DBG_FUNC(F) +#define DBG_PRINT(S...) +#define DBG_ENTER(A) +#define DBG_LEAVE(A) +#define DBG_PARAM(A,N,F,S...) +#define DBG_ERROR(A,S...) +#define DBG_WARNING(A,S...) +#define DBG_NOTICE(A,S...) +#define DBG_TRACE(A,S...) +#define DBG_RX(A,S...) +#define DBG_TX(A,S...) +#define DBG_DS(A,S...) +#define DBG_ASSERT(C) + +#endif // DBG +/****************************************************************************/ + + + + +#endif // _DEBUG_H + diff --git a/drivers/staging/wlags49_h2/dhf.c b/drivers/staging/wlags49_h2/dhf.c new file mode 100644 index 0000000000000000000000000000000000000000..b6f5834b1affbc24aa1bb60fe991b6f3ee08f32e --- /dev/null +++ b/drivers/staging/wlags49_h2/dhf.c @@ -0,0 +1,390 @@ + +// vim:tw=110:ts=4: +/************************************************************************************************************** +* +* FILE : DHF.C +* +* DATE : $Date: 2004/07/19 08:16:14 $ $Revision: 1.2 $ +* Original : 2004/05/28 14:05:34 Revision: 1.36 Tag: hcf7_t20040602_01 +* Original : 2004/05/11 06:22:57 Revision: 1.32 Tag: hcf7_t7_20040513_01 +* Original : 2004/04/15 09:24:42 Revision: 1.28 Tag: hcf7_t7_20040415_01 +* Original : 2004/04/08 15:18:16 Revision: 1.27 Tag: t7_20040413_01 +* Original : 2004/04/01 15:32:55 Revision: 1.25 Tag: t7_20040401_01 +* Original : 2004/03/10 15:39:28 Revision: 1.21 Tag: t20040310_01 +* Original : 2004/03/04 11:03:37 Revision: 1.19 Tag: t20040304_01 +* Original : 2004/03/02 09:27:11 Revision: 1.17 Tag: t20040302_03 +* Original : 2004/02/24 13:00:28 Revision: 1.15 Tag: t20040224_01 +* Original : 2004/02/19 10:57:28 Revision: 1.14 Tag: t20040219_01 +* Original : 2003/11/27 09:00:09 Revision: 1.3 Tag: t20021216_01 +* +* AUTHOR : John Meertens +* Nico Valster +* +* SPECIFICATION: ........ +* +* DESC : generic functions to handle the download of NIC firmware +* Local Support Routines for above procedures +* +* Customizable via HCFCFG.H, which is included by HCF.H +* +* +* DHF is (intended to be) platform-independent. +* DHF is a module that provides a number of routines to download firmware +* images (the names primary, station, access point, secondary and tertiary +* are used or have been used) to volatile or nonvolatile memory +* in WaveLAN/IEEE NICs. To achieve this DHF makes use of the WaveLAN/IEEE +* WCI as implemented by the HCF-module. +* +* Download to non-volatile memory is used to update a WaveLAN/IEEE NIC to new +* firmware. Normally this will be an upgrade to newer firmware, although +* downgrading to older firmware is possible too. +* +* Note: relative to Asserts, the following can be observed: +* Since the IFB is not known inside the routine, the macro HCFASSERT is replaced with MMDASSERT. +* Also the line number reported in the assert is raised by FILE_NAME_OFFSET (10000) to discriminate the +* DHF Asserts from HCF and MMD asserts. +* +*************************************************************************************************************** +* +* +* SOFTWARE LICENSE +* +* This software is provided subject to the following terms and conditions, +* which you should read carefully before using the software. Using this +* software indicates your acceptance of these terms and conditions. If you do +* not agree with these terms and conditions, do not use the software. +* +* COPYRIGHT © 1999 - 2000 by Lucent Technologies. All Rights Reserved +* COPYRIGHT © 2001 - 2004 by Agere Systems Inc. All Rights Reserved +* All rights reserved. +* +* Redistribution and use in source or binary forms, with or without +* modifications, 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 as comments in the code as +* well as in the documentation and/or other materials provided with the +* distribution. +* +* . 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. +* +* . Neither the name of Agere Systems Inc. nor the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* Disclaimer +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY +* USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN +* RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. +* +* +**************************************************************************************************************/ + +#include "hcf.h" +#include "hcfdef.h" +#include "dhf.h" +#include "mmd.h" + +//to distinguish MMD from HCF asserts by means of line number +#undef FILE_NAME_OFFSET +#define FILE_NAME_OFFSET MMD_FILE_NAME_OFFSET +/*----------------------------------------------------------------------------- + * + * Defines, data structures, and global variables + * + *---------------------------------------------------------------------------*/ + +// 12345678901234 +char signature[14] = "FUPU7D37dhfwci"; + +//The binary download function "relocates" the image using constructions like: +// fw->identity = (CFG_IDENTITY_STRCT FAR *)((char FAR *)fw->identity + (hcf_32)fw ); +//under some of the memory models under MSVC 1.52 these constructions degrade to 16-bits pointer arithmetic. +//fw->identity is limited, such that adding it to fw, does not need to carry over from offset to segment. +//However the segment is not set at all. +//As a workaround the PSEUDO_CHARP macro is introduced which is a char pointer except for MSVC 1.52, in +//which case we know that a 32-bit quantity is adequate as a pointer. +//Note that other platforms may experience comparable problems when using the binary download feature. +#if defined(_MSC_VER) && _MSC_VER == 800 // Visual C++ 1.5 +#define PSEUDO_CHARP hcf_32 +#else +#define PSEUDO_CHARP hcf_8* +#endif + +/*----------------------------------------------------------------------------- + * + * LTV-records retrieved from the NIC to: + * - determine compatibility between NIC and image + * - ((setup the buffer size dynamically for non-volatile download (see note below) )) + * - supply plugging information contained in the PDA (H-I only) + * + *---------------------------------------------------------------------------*/ + +// for USB/H1 we needed a smaller value than the CFG_DL_BUF_STRCT reported 8192 +// for the time being it seems simpler to always use 2000 for USB/H1 as well as all other cases rather than +// using the "fixed anyway" CFG_DL_BUF_STRCT. +#define DL_SIZE 2000 + +//CFG_IDENTITY_STRCT pri_identity = { LOF(CFG_IDENTITY_STRCT), CFG_PRI_IDENTITY }; +CFG_SUP_RANGE_STRCT mfi_sup = { LOF(CFG_SUP_RANGE_STRCT), CFG_NIC_MFI_SUP_RANGE }; +CFG_SUP_RANGE_STRCT cfi_sup = { LOF(CFG_SUP_RANGE_STRCT), CFG_NIC_CFI_SUP_RANGE }; +/* Note: could be used rather than the above explained and defined DL_SIZE if need arises + * CFG_DL_BUF_STRCT dl_buf = { LOF(CFG_DL_BUF_STRCT), CFG_DL_BUF }; +*/ + +/*----------------------------------------------------------------------------- + * Array ltv_info stores NIC information (in the form of LTV-records) + * needed for download. A NULL record indicates the end of the array. + *---------------------------------------------------------------------------*/ + +/* The LTV_INFO_STRUCT is needed to save the sizes of the structs, because after a GET_INFO() + * the len field is changed to the real len of the RID by the called routine. + * This is only relevant if the DHF used without reloading the driver/utility. + */ + +LTV_INFO_STRUCT ltv_info[] = { + { (LTVP)&mfi_sup, LOF(CFG_SUP_RANGE_STRCT) } , + { (LTVP)&cfi_sup, LOF(CFG_SUP_RANGE_STRCT) } , + { (LTVP) NULL, 0 } +}; + + +/***********************************************************************************************************/ +/*************************************** PROTOTYPES ******************************************************/ +/***********************************************************************************************************/ +static int check_comp_fw( memimage *fw ); + + +/************************************************************************************************************ +*.SUBMODULE int check_comp_fw( memimage *fw ) +*.PURPOSE Checks compatibility of CFI and MFI, NIC as supplier, station/AP firmware image as supplier. +* +*.ARGUMENTS +* fw F/W image to be downloaded +* +*.RETURNS +* HFC_SUCCESS - firmware OK +* DHF_ERR_INCOMP_FW +* +*.DESCRIPTION +* This function uses compatibility and identity information that has been +* retrieved from the card which is currently inserted to check whether the +* station firmware image to be downloaded is compatible. +*.ENDDOC END DOCUMENTATION +*************************************************************************************************************/ +int +check_comp_fw( memimage *fw ) +{ +CFG_RANGE20_STRCT *p; +int rc = HCF_SUCCESS; +CFG_RANGE_SPEC_STRCT* i; + + switch( fw->identity->typ ) { + case CFG_FW_IDENTITY: //Station F/W + case COMP_ID_FW_AP_FAKE: //;?is this useful (used to be: CFG_AP_IDENTITY) + break; + default: + MMDASSERT( DO_ASSERT, fw->identity->typ ) //unknown/unsupported firmware_type: + rc = DHF_ERR_INCOMP_FW; + return rc; /* ;? how useful is this anyway, + * till that is sorted out might as well violate my own single exit principle + */ + } + p = fw->compat; + i = NULL; + while( p->len && i == NULL ) { // check the MFI ranges + if ( p->typ == CFG_MFI_ACT_RANGES_STA ) { + i = mmd_check_comp( (void*)p, &mfi_sup ); + } + p++; + } + MMDASSERT( i, 0 ) //MFI: NIC Supplier not compatible with F/W image Actor + if ( i ) { + p = fw->compat; + i = NULL; + while ( p->len && i == NULL ) { // check the CFI ranges + if ( p->typ == CFG_CFI_ACT_RANGES_STA ) { + i = mmd_check_comp( (void*)p, &cfi_sup ); + } + p++; + } + MMDASSERT( i, 0 ) //CFI: NIC Supplier not compatible with F/W image Actor + } + if ( i == NULL ) { + rc = DHF_ERR_INCOMP_FW; + } + return rc; +} // check_comp_fw + + + + + +/*----------------------------------------------------------------------------- + * + * Exported functions + * + *---------------------------------------------------------------------------*/ + + + +/************************************************************************************************************* +* +*.MODULE int dhf_download_binary( void *ifbp, memimage *fw ) +*.PURPOSE Downloads a complete (primary, station, or access point) firmware image to the NIC. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* fw F/W image to be downloaded +* +*.RETURNS +* HCF_SUCCESS - download completed successfully. +* DHF_ERR_INCOMP_FW - firmware not compatible +* +*.DESCRIPTION +* Initialize global variables +* Connect to the DHF +* Check the compatibility of the image (For primary firmware images it is checked first +* whether download is necessary). +* If everything's download the firmware. +* Disconnect from the DHF. +* +* +*.DIAGRAM +* +*.NOTICE: + MMDASSERT is unacceptable because some drivers call dhf_download_binary before hcf_connect + +* The old comment was: +*.ENDDOC END DOCUMENTATION +*************************************************************************************************************/ +int +dhf_download_binary( memimage *fw ) +{ +int rc = HCF_SUCCESS; +CFG_PROG_STRCT *p; +int i; + + //validate the image + for ( i = 0; i < sizeof(signature) && fw->signature[i] == signature[i]; i++ ) /*NOP*/; + if ( i != sizeof(signature) || + fw->signature[i] != 0x01 || + //test for Little/Big Endian Binary flag + fw->signature[i+1] != ( /*HCF_BIG_ENDIAN ? 'B' : */ 'L' ) ) rc = DHF_ERR_INCOMP_FW; + else { //Little Endian Binary format + fw->codep = (CFG_PROG_STRCT FAR *)((PSEUDO_CHARP)fw->codep + (hcf_32)fw ); + fw->identity = (CFG_IDENTITY_STRCT FAR *)((PSEUDO_CHARP)fw->identity + (hcf_32)fw ); + fw->compat = (CFG_RANGE20_STRCT FAR *)((PSEUDO_CHARP)fw->compat + (hcf_32)fw ); + for ( i = 0; fw->p[i]; i++ ) fw->p[i] = ((PSEUDO_CHARP)fw->p[i] + (hcf_32)fw ); + p = fw->codep; + while ( p->len ) { + p->host_addr = (PSEUDO_CHARP)p->host_addr + (hcf_32)fw; + p++; + } + } + return rc; +} // dhf_download_binary + + +/************************************************************************************************************* +* +*.MODULE int dhf_download_fw( void *ifbp, memimage *fw ) +*.PURPOSE Downloads a complete (primary or tertiary) firmware image to the NIC. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* fw F/W image to be downloaded +* +*.RETURNS +* HCF_SUCCESS - download completed successfully. +* HCF_ERR_NO_NIC - no NIC present +* DHF_ERR_INCOMP_FW - firmware not compatible +* +*.DESCRIPTION +* - check the signature of the image +* - get the compatibility information from the components on the NIC +* - Primary Firmware Identity +* - Modem - Firmware I/F +* - Controller - Firmware I/F +*!! - if necessary ( i.e. H-I) get the PDA contents from the NIC +* - check the compatibility of the MFI and CFI of the NIC with the F/W image +* Note: the Primary F/W compatibility is only relevant for the "running" HCF and is already verified in +* hcf_connect +*!! - if necessary ( i.e. H-I) +*!! - verify the sumcheck of the PDA +*!! - plug the image (based on the PDA and the default plug records) +* - loop over all the download LTVs in the image which consists of a sequence of +* - CFG_PROG_VOLATILE/CFG_PROG_NON_VOLATILE +* - 1 or more sequences of CFG_PROG_ADDR, CFG_PROG_DATA,....,CFG_PROG_DATA +* - CFG_PROG_STOP +* +*.DIAGRAM +* +*.NOTICE +* The old comment was: +* // Download primary firmware if necessary and allowed. This is done silently (without telling +* // the user) and only if the firmware in the download image is newer than the firmware in the +* // card. In Major version 4 of the primary firmware functions of Hermes and Shark were +* // combined. Prior to that two separate versions existed. We only have to download primary +* // firmware if major version of primary firmware in the NIC < 4. +* // download = pri_identity.version_major < 4; +* // if ( download ) { +* // rc = check_comp_primary( fw ); +* // } +* It is my understanding that Pri Variant 1 must be updated by Pri Variant 2. The test on +* major version < 4 should amount to the same result but be "principally" less correct +* In deliberation with the Architecture team, it was decided that this upgrade for old H-I +* NICs, is an aspect which belongs on the WSU level not on the DHF level +* +*.ENDDOC END DOCUMENTATION +*************************************************************************************************************/ +int +dhf_download_fw( void *ifbp, memimage *fw ) +{ +int rc = HCF_SUCCESS; +LTV_INFO_STRUCT_PTR pp = ltv_info; +CFG_PROG_STRCT *p = fw->codep; +LTVP ltvp; +int i; + + MMDASSERT( fw != NULL, 0 ) + //validate the image + for ( i = 0; i < sizeof(signature) && fw->signature[i] == signature[i]; i++ ) /*NOP*/; + if ( i != sizeof(signature) || + fw->signature[i] != 0x01 || + //check for binary image + ( fw->signature[i+1] != 'C' && fw->signature[i+1] != ( /*HCF_BIG_ENDIAN ? 'B' : */ 'L' ) ) ) + rc = DHF_ERR_INCOMP_FW; + +// Retrieve all information needed for download from the NIC + while ( ( rc == HCF_SUCCESS ) && ( ( ltvp = pp->ltvp) != NULL ) ) { + ltvp->len = pp++->len; // Set len to original len. This len is changed to real len by GET_INFO() + rc = GET_INFO( ltvp ); + MMDASSERT( rc == HCF_SUCCESS, rc ) + MMDASSERT( rc == HCF_SUCCESS, ltvp->typ ) + MMDASSERT( rc == HCF_SUCCESS, ltvp->len ) + } + if ( rc == HCF_SUCCESS ) rc = check_comp_fw( fw ); + if ( rc == HCF_SUCCESS ) { + while ( rc == HCF_SUCCESS && p->len ) { + rc = PUT_INFO( p ); + p++; + } + } + MMDASSERT( rc == HCF_SUCCESS, rc ) + return rc; +} // dhf_download_fw + + diff --git a/drivers/staging/wlags49_h2/dhf.h b/drivers/staging/wlags49_h2/dhf.h new file mode 100644 index 0000000000000000000000000000000000000000..c071f342a65598c161e2e4db970a375bfce14a1d --- /dev/null +++ b/drivers/staging/wlags49_h2/dhf.h @@ -0,0 +1,226 @@ + +// vim:tw=110:ts=4: +#ifndef DHF_H +#define DHF_H + +/************************************************************************************************************** +* +* FILE : DHF.H +* +* DATE : $Date: 2004/07/19 08:16:14 $ $Revision: 1.2 $ +* Original : 2004/05/17 07:33:13 Revision: 1.25 Tag: hcf7_t20040602_01 +* Original : 2004/05/11 06:03:14 Revision: 1.24 Tag: hcf7_t7_20040513_01 +* Original : 2004/04/15 09:24:42 Revision: 1.22 Tag: hcf7_t7_20040415_01 +* Original : 2004/04/09 14:35:52 Revision: 1.21 Tag: t7_20040413_01 +* Original : 2004/04/01 15:32:55 Revision: 1.18 Tag: t7_20040401_01 +* Original : 2004/03/10 15:39:28 Revision: 1.15 Tag: t20040310_01 +* Original : 2004/03/04 11:03:38 Revision: 1.13 Tag: t20040304_01 +* Original : 2004/02/25 14:14:37 Revision: 1.11 Tag: t20040302_03 +* Original : 2004/02/24 13:00:28 Revision: 1.10 Tag: t20040224_01 +* Original : 2004/02/19 10:57:28 Revision: 1.8 Tag: t20040219_01 +* +* AUTHOR : John Meertens +* Nico Valster +* +* SPECIFICATION: ......... +* +* DESC : structure definitions and function prototypes for unit DHF. +* +* Customizable via HCFCFG.H, which is included indirectly via HCF.H +* +*************************************************************************************************************** +* +* +* SOFTWARE LICENSE +* +* This software is provided subject to the following terms and conditions, +* which you should read carefully before using the software. Using this +* software indicates your acceptance of these terms and conditions. If you do +* not agree with these terms and conditions, do not use the software. +* +* COPYRIGHT © 1994 - 1995 by AT&T. All Rights Reserved +* COPYRIGHT © 1999 - 2000 by Lucent Technologies. All Rights Reserved +* COPYRIGHT © 2001 - 2004 by Agere Systems Inc. All Rights Reserved +* All rights reserved. +* +* Redistribution and use in source or binary forms, with or without +* modifications, 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 as comments in the code as +* well as in the documentation and/or other materials provided with the +* distribution. +* +* . 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. +* +* . Neither the name of Agere Systems Inc. nor the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* Disclaimer +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY +* USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN +* RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. +* +* +**************************************************************************************************************/ + + +#ifdef _WIN32_WCE +#include +#endif + +#include "hcf.h" // includes HCFCFG.H too + +#ifdef DHF_UIL +#define GET_INFO( pp ) uil_get_info( (LTVP)pp ) +#define PUT_INFO( pp ) uil_put_info( (LTVP)pp ) +#else +#define GET_INFO( pp ) hcf_get_info( ifbp, (LTVP)pp ) +#define PUT_INFO( pp ) hcf_put_info( ifbp, (LTVP)pp ) +#endif + + +/*---- Defines --------------------------------------------------------------*/ +#define CODEMASK 0x0000FFFFL // Codemask for plug records + +/*---- Error numbers --------------------------------------------------------*/ + +#define DHF_ERR_INCOMP_FW 0x40 //Image not compatible with NIC + +/*---- Type definitions -----------------------------------------------------*/ +//* needed by dhf_wrap.c +// +typedef struct { + LTVP ltvp; + hcf_16 len; +} LTV_INFO_STRUCT , *LTV_INFO_STRUCT_PTR; + + +/* + * Type: plugrecord + * + * Abstract: This structure represents a Plug Data Record. + * + * Description: + * This structure is used to overlay the plug records in the firmware memory image. + */ + +typedef struct { + hcf_32 code; // Code to plug + hcf_32 addr; // Address within the memory image to plug it in + hcf_32 len; // The # of bytes which are available to store it +} plugrecord; + +/* + * Type: stringrecord + * + * Abstract: This structure represents a Firmware debug/assert string + * + * Description: + * This structure is used to get assert and debug outputs in the driver and/or utility to be + * able to get more visability of the FW. + */ + +#define MAX_DEBUGSTRINGS 1024 +#define MAX_DEBUGSTRING_LEN 82 + +typedef struct { + hcf_32 id; + char str[MAX_DEBUGSTRING_LEN]; +} stringrecord; + +/* + * Type: exportrecord + * + * Abstract: This structure represents a Firmware export of a variable + * + * Description: + * This structure is used to get the address and name of a FW variable. + */ + +#define MAX_DEBUGEXPORTS 2048 +#define MAX_DEBUGEXPORT_LEN 12 + +typedef struct { + hcf_32 id; + char str[MAX_DEBUGEXPORT_LEN]; +} exportrecord; + +// Offsets in memimage array p[] +#define FWSTRINGS_FUNCTION 0 +#define FWEXPORTS_FUNCTION 1 + +/* + * Type: memimage + * + * Abstract: The "root" description of a complete memory image + * + * Description: + * This type represents an entire memory image. The image is built up of several + * segments. These segments need not be contiguous areas in memory, in other words + * the image may contain 'holes'. + * + * The 'codep' field points to an array of segment_descriptor structures. + * The end of the array is indicated by a segment_descriptor of which all fields are zero. + * The 'execution' field is a 32-bit address representing the execution address + * of the firmware within the memory image. This address is zero in case of non-volatile + * memory download. + * The 'compat' field points to an array of TODO + * The end of the array is indicated by a plug record of which all fields are zero. + * The 'identity' field points to an array of TODO + * The end of the array is indicated by a plug record of which all fields are zero. + * The Hermes-I specific 'pdaplug' field points to an array of Production Data Plug record structures. + * The end of the array is indicated by a plug record of which all fields are zero. + * The Hermes-I specific 'priplug' field points to an array of Primary Information Plug record structures. + * The end of the array is indicated by a plug record of which all fields are zero. + */ +typedef struct { + char signature[14+1+1]; // signature (see DHF.C) + C/LE-Bin/BE-Bin-flag + format version + CFG_PROG_STRCT FAR *codep; // + hcf_32 execution; // Execution address of the firmware + void FAR *place_holder_1; + void FAR *place_holder_2; + CFG_RANGE20_STRCT FAR *compat; // Pointer to the compatibility info records + CFG_IDENTITY_STRCT FAR *identity; // Pointer to the identity info records + void FAR *p[2]; /* (Up to 9) pointers for (future) expansion + * currently in use: + * - F/W printf information + */ +} memimage; + + + +/*----------------------------------------------------------------------------- + * + * DHF function prototypes + * + *---------------------------------------------------------------------------*/ + +EXTERN_C int dhf_download_fw( void *ifbp, memimage *fw ); // ifbp, ignored when using the UIL +EXTERN_C int dhf_download_binary( memimage *fw ); + + +/*----------------------------------------------------------------------------- + * + * Functions to be provided by the user of the DHF module. + * + *---------------------------------------------------------------------------*/ + +// defined in DHF.C; see there for comments +EXTERN_C hcf_16 *find_record_in_pda( hcf_16 *pdap, hcf_16 code ); + +#endif // DHF_H + diff --git a/drivers/staging/wlags49_h2/dhfcfg.h b/drivers/staging/wlags49_h2/dhfcfg.h new file mode 100644 index 0000000000000000000000000000000000000000..a0c26c678c59361b3480736d49e5f1dfdaecd2ee --- /dev/null +++ b/drivers/staging/wlags49_h2/dhfcfg.h @@ -0,0 +1,158 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * This file contains DHF configuration info. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +#ifndef DHFCFG_H +#define DHFCFG_H +/*----------------------------------------------------------------------------- + * File DHFCFG.H + * + * Contents: #defines for the DHF module + * + * Comments: + * Some combinations of the #defines in this file are illegal (as noted below). + * If an illegal combinations of #defines is specified a compile error is + * generated. See document DHFUG.DOC for more information. + * + * Author: John Meertens + * Date: 11-01-2000 + * + * Change history: + *---------------------------------------------------------------------------*/ + + +// Define DHF_WCI if you want to use the WCI to access the ORiNOCO card. +// Define DHF_UIL if you want to use the UIL to access the ORiNOCO card. +// You must define either DHF_WCI or DHF_UIL. If neither of the two is defined +// or both a compile error is generated. +#define DHF_WCI +//!!!#define DHF_UIL + +// Define DHF_BIG_ENDIAN if you are working on a big endian platform. +// Define DHF_LITTLE_ENDIAN if you are working on a little endian platform. +// You must define either DHF_BIG_ENDIAN or DHF_LITTLE_ENDIAN. If neither of +// the two is defined or both a compile error is generated. +#ifdef USE_BIG_ENDIAN +#define DHF_BIG_ENDIAN +#else +#define DHF_LITTLE_ENDIAN +#endif /* USE_BIG_ENDIAN */ + +// Define DHF_WIN if you are working on Windows platform. +// Define DHF_DOS if you are working on DOS. +// You must define either DHF_WIN or DHF_DOS. If neither of +// the two is defined or both a compile error is generated. +//!!!#define DHF_WIN +//!!!#define DHF_DOS + +// Define if you want the DHF to users. Not defining DHF_GET_RES_MSG +// leads to a decrease in code size as message strings are not included. +//!!!#define DHF_GET_RES_MSG + +// Linux driver specific +// Prevent inclusion of stdlib.h and string.h +#define _INC_STDLIB +#define _INC_STRING + +//----------------------------------------------------------------------------- +// Define one or more of the following DSF #defines if you want to implement +// the related DSF-function. Function dsf_callback must allways be implemented. +// See file DHF.H for prototypes of the functions. + +// Define DSF_ALLOC if you want to manage memory allocation and de-allocation +// for the DHF. If DSF_ALLOC is defined you must implement dsf_alloc and dsf_free. +//!!!#define DSF_ALLOC + +// Define DSF_CONFIRM if you want the DHF to ask the user for confirmation in a +// number of situations. If DSF_CONFIRM is defined you must implement dsf_confirm. +// Not defining DSF_CONFIRM leads to a decrease in code size as confirmation +// strings are not included. +//!!!#define DSF_CONFIRM + +// Define DSF_DEBUG_MESSAGE if you want debug messages added to your output. +// If you define DSF_DEBUG_MESSAGE then you must implement function +// dsf_debug_message. +//#define DSF_DEBUG_MESSAGE + +// Define DSF_ASSERT if you want asserts to be activated. +// If you define DSF_ASSERT then you must implement function dsf_assert. +//#define DBG 1 +//#define DSF_ASSERT + +// Define DSF_DBWIN if you want asserts and debug messages to be send to a debug +// window like SOFTICE or DebugView from SysInternals. +//!!!#define DSF_DBWIN +//!!! Not implemented yet! + +// Define DSF_VOLATILE_ONLY if you only wants to use valatile functions +// This is a typical setting for a AP and a driver. +#define DSF_VOLATILE_ONLY + +// Define DSF_HERMESII if you want to use the DHF for the Hermes-II +#ifdef HERMES2 +#define DSF_HERMESII +#else +#undef DSF_HERMESII +#endif // HERMES2 + +// Define DSF_BINARY_FILE if you want to use the DHF in combination with +// reading the Firmware from a separate binary file. +//!!!#define DSF_BINARY_FILE + +#endif // DHFCFG_H diff --git a/drivers/staging/wlags49_h2/hcf.c b/drivers/staging/wlags49_h2/hcf.c new file mode 100644 index 0000000000000000000000000000000000000000..6e39f5081e27469a229e11495d6d07db19917056 --- /dev/null +++ b/drivers/staging/wlags49_h2/hcf.c @@ -0,0 +1,4881 @@ +// vim:tw=110:ts=4: +/************************************************************************************************************ +* +* FILE : HCF.C +* +* DATE : $Date: 2004/08/05 11:47:10 $ $Revision: 1.10 $ +* Original: 2004/06/02 10:22:22 Revision: 1.85 Tag: hcf7_t20040602_01 +* Original: 2004/04/15 09:24:41 Revision: 1.63 Tag: hcf7_t7_20040415_01 +* Original: 2004/04/13 14:22:44 Revision: 1.62 Tag: t7_20040413_01 +* Original: 2004/04/01 15:32:55 Revision: 1.59 Tag: t7_20040401_01 +* Original: 2004/03/10 15:39:27 Revision: 1.55 Tag: t20040310_01 +* Original: 2004/03/04 11:03:37 Revision: 1.53 Tag: t20040304_01 +* Original: 2004/03/02 14:51:21 Revision: 1.50 Tag: t20040302_03 +* Original: 2004/02/24 13:00:27 Revision: 1.43 Tag: t20040224_01 +* Original: 2004/02/19 10:57:25 Revision: 1.39 Tag: t20040219_01 +* +* AUTHOR : Nico Valster +* +* SPECIFICATION: ........ +* +* DESCRIPTION : HCF Routines for Hermes-II (callable via the Wireless Connection I/F or WCI) +* Local Support Routines for above procedures +* +* Customizable via HCFCFG.H, which is included by HCF.H +* +************************************************************************************************************* +* +* +* SOFTWARE LICENSE +* +* This software is provided subject to the following terms and conditions, +* which you should read carefully before using the software. Using this +* software indicates your acceptance of these terms and conditions. If you do +* not agree with these terms and conditions, do not use the software. +* +* COPYRIGHT © 1994 - 1995 by AT&T. All Rights Reserved +* COPYRIGHT © 1996 - 2000 by Lucent Technologies. All Rights Reserved +* COPYRIGHT © 2001 - 2004 by Agere Systems Inc. All Rights Reserved +* All rights reserved. +* +* Redistribution and use in source or binary forms, with or without +* modifications, 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 as comments in the code as +* well as in the documentation and/or other materials provided with the +* distribution. +* +* . 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. +* +* . Neither the name of Agere Systems Inc. nor the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* Disclaimer +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY +* USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN +* RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. +* +* +************************************************************************************************************/ + + +/************************************************************************************************************ +** +** Implementation Notes +** +* - a leading marker of //! is used. The purpose of such a sequence is to help to understand the flow +* An example is: //!rc = HCF_SUCCESS; +* if this is superfluous because rc is already guaranteed to be 0 but it shows to the (maintenance) +* programmer it is an intentional omission at the place where someone could consider it most appropriate at +* first glance +* - using near pointers in a model where ss!=ds is an invitation for disaster, so be aware of how you specify +* your model and how you define variables which are used at interrupt time +* - remember that sign extension on 32 bit platforms may cause problems unless code is carefully constructed, +* e.g. use "(hcf_16)~foo" rather than "~foo" +* +************************************************************************************************************/ + +#include "hcf.h" // HCF and MSF common include file +#include "hcfdef.h" // HCF specific include file +#include "mmd.h" // MoreModularDriver common include file + +#if ! defined offsetof +#define offsetof(s,m) ((unsigned int)&(((s *)0)->m)) +#endif // offsetof + + +/***********************************************************************************************************/ +/*************************************** PROTOTYPES ******************************************************/ +/***********************************************************************************************************/ +HCF_STATIC int cmd_exe( IFBP ifbp, hcf_16 cmd_code, hcf_16 par_0 ); +HCF_STATIC int init( IFBP ifbp ); +HCF_STATIC int put_info( IFBP ifbp, LTVP ltvp ); +#if (HCF_EXT) & HCF_EXT_MB +HCF_STATIC int put_info_mb( IFBP ifbp, CFG_MB_INFO_STRCT FAR * ltvp ); +#endif // HCF_EXT_MB +#if (HCF_TYPE) & HCF_TYPE_WPA +HCF_STATIC void calc_mic( hcf_32* p, hcf_32 M ); +void calc_mic_rx_frag( IFBP ifbp, wci_bufp p, int len ); +void calc_mic_tx_frag( IFBP ifbp, wci_bufp p, int len ); +HCF_STATIC int check_mic( IFBP ifbp ); +#endif // HCF_TYPE_WPA + +HCF_STATIC void calibrate( IFBP ifbp ); +HCF_STATIC int cmd_cmpl( IFBP ifbp ); +HCF_STATIC hcf_16 get_fid( IFBP ifbp ); +HCF_STATIC void isr_info( IFBP ifbp ); +#if HCF_DMA +HCF_STATIC DESC_STRCT* get_frame_lst(IFBP ifbp, int tx_rx_flag); +#endif // HCF_DMA +HCF_STATIC void get_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) ); //char*, byte count (usually even) +#if HCF_DMA +HCF_STATIC void put_frame_lst( IFBP ifbp, DESC_STRCT *descp, int tx_rx_flag ); +#endif // HCF_DMA +HCF_STATIC void put_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) ); +HCF_STATIC void put_frag_finalize( IFBP ifbp ); +HCF_STATIC int setup_bap( IFBP ifbp, hcf_16 fid, int offset, int type ); +#if (HCF_ASSERT) & HCF_ASSERT_PRINTF +static int fw_printf(IFBP ifbp, CFG_FW_PRINTF_STRCT FAR *ltvp); +#endif // HCF_ASSERT_PRINTF + +HCF_STATIC int download( IFBP ifbp, CFG_PROG_STRCT FAR *ltvp ); +#if (HCF_ENCAP) & HCF_ENC +HCF_STATIC hcf_8 hcf_encap( wci_bufp type ); +#endif // HCF_ENCAP +HCF_STATIC hcf_8 null_addr[4] = { 0, 0, 0, 0 }; +#if ! defined IN_PORT_WORD //replace I/O Macros with logging facility +extern FILE *log_file; + +#define IN_PORT_WORD(port) in_port_word( (hcf_io)(port) ) + +static hcf_16 in_port_word( hcf_io port ) { +hcf_16 i = (hcf_16)_inpw( port ); + if ( log_file ) { + fprintf( log_file, "\nR %2.2x %4.4x", (port)&0xFF, i); + } + return i; +} // in_port_word + +#define OUT_PORT_WORD(port, value) out_port_word( (hcf_io)(port), (hcf_16)(value) ) + +static void out_port_word( hcf_io port, hcf_16 value ) { + _outpw( port, value ); + if ( log_file ) { + fprintf( log_file, "\nW %2.02x %4.04x", (port)&0xFF, value ); + } +} + +void IN_PORT_STRING_32( hcf_io prt, hcf_32 FAR * dst, int n) { + int i = 0; + hcf_16 FAR * p; + if ( log_file ) { + fprintf( log_file, "\nread string_32 length %04x (%04d) at port %02.2x to addr %lp", + (hcf_16)n, (hcf_16)n, (hcf_16)(prt)&0xFF, dst); + } + while ( n-- ) { + p = (hcf_16 FAR *)dst; + *p++ = (hcf_16)_inpw( prt ); + *p = (hcf_16)_inpw( prt ); + if ( log_file ) { + fprintf( log_file, "%s%08lx ", i++ % 0x08 ? " " : "\n", *dst); + } + dst++; + } +} // IN_PORT_STRING_32 + +void IN_PORT_STRING_8_16( hcf_io prt, hcf_8 FAR * dst, int n) { //also handles byte alignment problems + hcf_16 FAR * p = (hcf_16 FAR *)dst; //this needs more elaborate code in non-x86 platforms + int i = 0; + if ( log_file ) { + fprintf( log_file, "\nread string_16 length %04x (%04d) at port %02.2x to addr %lp", + (hcf_16)n, (hcf_16)n, (hcf_16)(prt)&0xFF, dst ); + } + while ( n-- ) { + *p =(hcf_16)_inpw( prt); + if ( log_file ) { + if ( i++ % 0x10 ) { + fprintf( log_file, "%04x ", *p); + } else { + fprintf( log_file, "\n%04x ", *p); + } + } + p++; + } +} // IN_PORT_STRING_8_16 + +void OUT_PORT_STRING_32( hcf_io prt, hcf_32 FAR * src, int n) { + int i = 0; + hcf_16 FAR * p; + if ( log_file ) { + fprintf( log_file, "\nwrite string_32 length %04x (%04d) at port %02.2x", + (hcf_16)n, (hcf_16)n, (hcf_16)(prt)&0xFF); + } + while ( n-- ) { + p = (hcf_16 FAR *)src; + _outpw( prt, *p++ ); + _outpw( prt, *p ); + if ( log_file ) { + fprintf( log_file, "%s%08lx ", i++ % 0x08 ? " " : "\n", *src); + } + src++; + } +} // OUT_PORT_STRING_32 + +void OUT_PORT_STRING_8_16( hcf_io prt, hcf_8 FAR * src, int n) { //also handles byte alignment problems + hcf_16 FAR * p = (hcf_16 FAR *)src; //this needs more elaborate code in non-x86 platforms + int i = 0; + if ( log_file ) { + fprintf( log_file, "\nwrite string_16 length %04x (%04d) at port %04x", n, n, (hcf_16)prt); + } + while ( n-- ) { + (void)_outpw( prt, *p); + if ( log_file ) { + if ( i++ % 0x10 ) { + fprintf( log_file, "%04x ", *p); + } else { + fprintf( log_file, "\n%04x ", *p); + } + } + p++; + } +} // OUT_PORT_STRING_8_16 + +#endif // IN_PORT_WORD + +/************************************************************************************************************ +******************************* D A T A D E F I N I T I O N S ******************************************** +************************************************************************************************************/ + +#if HCF_ASSERT +IFBP BASED assert_ifbp = NULL; //to make asserts easily work under MMD and DHF +#endif // HCF_ASSERT + +#if HCF_ENCAP +/* SNAP header to be inserted in Ethernet-II frames */ +HCF_STATIC hcf_8 BASED snap_header[] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, //5 bytes signature + + 0 }; //1 byte protocol identifier +#endif // HCF_ENCAP + +#if (HCF_TYPE) & HCF_TYPE_WPA +HCF_STATIC hcf_8 BASED mic_pad[8] = { 0x5A, 0, 0, 0, 0, 0, 0, 0 }; //MIC padding of message +#endif // HCF_TYPE_WPA + +#if defined MSF_COMPONENT_ID +CFG_IDENTITY_STRCT BASED cfg_drv_identity = { + sizeof(cfg_drv_identity)/sizeof(hcf_16) - 1, //length of RID + CFG_DRV_IDENTITY, // (0x0826) + MSF_COMPONENT_ID, + MSF_COMPONENT_VAR, + MSF_COMPONENT_MAJOR_VER, + MSF_COMPONENT_MINOR_VER +} ; + +CFG_RANGES_STRCT BASED cfg_drv_sup_range = { + sizeof(cfg_drv_sup_range)/sizeof(hcf_16) - 1, //length of RID + CFG_DRV_SUP_RANGE, // (0x0827) + + COMP_ROLE_SUPL, + COMP_ID_DUI, + {{ DUI_COMPAT_VAR, + DUI_COMPAT_BOT, + DUI_COMPAT_TOP + }} +} ; + +struct CFG_RANGE3_STRCT BASED cfg_drv_act_ranges_pri = { + sizeof(cfg_drv_act_ranges_pri)/sizeof(hcf_16) - 1, //length of RID + CFG_DRV_ACT_RANGES_PRI, // (0x0828) + + COMP_ROLE_ACT, + COMP_ID_PRI, + { + { 0, 0, 0 }, // HCF_PRI_VAR_1 not supported by HCF 7 + { 0, 0, 0 }, // HCF_PRI_VAR_2 not supported by HCF 7 + { 3, //var_rec[2] - Variant number + CFG_DRV_ACT_RANGES_PRI_3_BOTTOM, // - Bottom Compatibility + CFG_DRV_ACT_RANGES_PRI_3_TOP // - Top Compatibility + } + } +} ; + + +struct CFG_RANGE4_STRCT BASED cfg_drv_act_ranges_sta = { + sizeof(cfg_drv_act_ranges_sta)/sizeof(hcf_16) - 1, //length of RID + CFG_DRV_ACT_RANGES_STA, // (0x0829) + + COMP_ROLE_ACT, + COMP_ID_STA, + { +#if defined HCF_STA_VAR_1 + { 1, //var_rec[1] - Variant number + CFG_DRV_ACT_RANGES_STA_1_BOTTOM, // - Bottom Compatibility + CFG_DRV_ACT_RANGES_STA_1_TOP // - Top Compatibility + }, +#else + { 0, 0, 0 }, +#endif // HCF_STA_VAR_1 +#if defined HCF_STA_VAR_2 + { 2, //var_rec[1] - Variant number + CFG_DRV_ACT_RANGES_STA_2_BOTTOM, // - Bottom Compatibility + CFG_DRV_ACT_RANGES_STA_2_TOP // - Top Compatibility + }, +#else + { 0, 0, 0 }, +#endif // HCF_STA_VAR_2 +// For Native_USB (Not used!) +#if defined HCF_STA_VAR_3 + { 3, //var_rec[1] - Variant number + CFG_DRV_ACT_RANGES_STA_3_BOTTOM, // - Bottom Compatibility + CFG_DRV_ACT_RANGES_STA_3_TOP // - Top Compatibility + }, +#else + { 0, 0, 0 }, +#endif // HCF_STA_VAR_3 +// Warp +#if defined HCF_STA_VAR_4 + { 4, //var_rec[1] - Variant number + CFG_DRV_ACT_RANGES_STA_4_BOTTOM, // - Bottom Compatibility + CFG_DRV_ACT_RANGES_STA_4_TOP // - Top Compatibility + } +#else + { 0, 0, 0 } +#endif // HCF_STA_VAR_4 + } +} ; + + +struct CFG_RANGE6_STRCT BASED cfg_drv_act_ranges_hsi = { + sizeof(cfg_drv_act_ranges_hsi)/sizeof(hcf_16) - 1, //length of RID + CFG_DRV_ACT_RANGES_HSI, // (0x082A) + COMP_ROLE_ACT, + COMP_ID_HSI, + { +#if defined HCF_HSI_VAR_0 // Controlled deployment + { 0, // var_rec[1] - Variant number + CFG_DRV_ACT_RANGES_HSI_0_BOTTOM, // - Bottom Compatibility + CFG_DRV_ACT_RANGES_HSI_0_TOP // - Top Compatibility + }, +#else + { 0, 0, 0 }, +#endif // HCF_HSI_VAR_0 + { 0, 0, 0 }, // HCF_HSI_VAR_1 not supported by HCF 7 + { 0, 0, 0 }, // HCF_HSI_VAR_2 not supported by HCF 7 + { 0, 0, 0 }, // HCF_HSI_VAR_3 not supported by HCF 7 +#if defined HCF_HSI_VAR_4 // Hermes-II all types + { 4, // var_rec[1] - Variant number + CFG_DRV_ACT_RANGES_HSI_4_BOTTOM, // - Bottom Compatibility + CFG_DRV_ACT_RANGES_HSI_4_TOP // - Top Compatibility + }, +#else + { 0, 0, 0 }, +#endif // HCF_HSI_VAR_4 +#if defined HCF_HSI_VAR_5 // WARP Hermes-2.5 + { 5, // var_rec[1] - Variant number + CFG_DRV_ACT_RANGES_HSI_5_BOTTOM, // - Bottom Compatibility + CFG_DRV_ACT_RANGES_HSI_5_TOP // - Top Compatibility + } +#else + { 0, 0, 0 } +#endif // HCF_HSI_VAR_5 + } +} ; + + +CFG_RANGE4_STRCT BASED cfg_drv_act_ranges_apf = { + sizeof(cfg_drv_act_ranges_apf)/sizeof(hcf_16) - 1, //length of RID + CFG_DRV_ACT_RANGES_APF, // (0x082B) + + COMP_ROLE_ACT, + COMP_ID_APF, + { +#if defined HCF_APF_VAR_1 //(Fake) Hermes-I + { 1, //var_rec[1] - Variant number + CFG_DRV_ACT_RANGES_APF_1_BOTTOM, // - Bottom Compatibility + CFG_DRV_ACT_RANGES_APF_1_TOP // - Top Compatibility + }, +#else + { 0, 0, 0 }, +#endif // HCF_APF_VAR_1 +#if defined HCF_APF_VAR_2 //Hermes-II + { 2, // var_rec[1] - Variant number + CFG_DRV_ACT_RANGES_APF_2_BOTTOM, // - Bottom Compatibility + CFG_DRV_ACT_RANGES_APF_2_TOP // - Top Compatibility + }, +#else + { 0, 0, 0 }, +#endif // HCF_APF_VAR_2 +#if defined HCF_APF_VAR_3 // Native_USB + { 3, // var_rec[1] - Variant number + CFG_DRV_ACT_RANGES_APF_3_BOTTOM, // - Bottom Compatibility !!!!!see note below!!!!!!! + CFG_DRV_ACT_RANGES_APF_3_TOP // - Top Compatibility + }, +#else + { 0, 0, 0 }, +#endif // HCF_APF_VAR_3 +#if defined HCF_APF_VAR_4 // WARP Hermes 2.5 + { 4, // var_rec[1] - Variant number + CFG_DRV_ACT_RANGES_APF_4_BOTTOM, // - Bottom Compatibility !!!!!see note below!!!!!!! + CFG_DRV_ACT_RANGES_APF_4_TOP // - Top Compatibility + } +#else + { 0, 0, 0 } +#endif // HCF_APF_VAR_4 + } +} ; +#define HCF_VERSION TEXT( "HCF$Revision: 1.10 $" ) + +static struct /*CFG_HCF_OPT_STRCT*/ { + hcf_16 len; //length of cfg_hcf_opt struct + hcf_16 typ; //type 0x082C + hcf_16 v0; //offset HCF_VERSION + hcf_16 v1; // MSF_COMPONENT_ID + hcf_16 v2; // HCF_ALIGN + hcf_16 v3; // HCF_ASSERT + hcf_16 v4; // HCF_BIG_ENDIAN + hcf_16 v5; // /* HCF_DLV | HCF_DLNV */ + hcf_16 v6; // HCF_DMA + hcf_16 v7; // HCF_ENCAP + hcf_16 v8; // HCF_EXT + hcf_16 v9; // HCF_INT_ON + hcf_16 v10; // HCF_IO + hcf_16 v11; // HCF_LEGACY + hcf_16 v12; // HCF_MAX_LTV + hcf_16 v13; // HCF_PROT_TIME + hcf_16 v14; // HCF_SLEEP + hcf_16 v15; // HCF_TALLIES + hcf_16 v16; // HCF_TYPE + hcf_16 v17; // HCF_NIC_TAL_CNT + hcf_16 v18; // HCF_HCF_TAL_CNT + hcf_16 v19; // offset tallies + TCHAR val[sizeof(HCF_VERSION)]; +} BASED cfg_hcf_opt = { + sizeof(cfg_hcf_opt)/sizeof(hcf_16) -1, + CFG_HCF_OPT, // (0x082C) + ( sizeof(cfg_hcf_opt) - sizeof(HCF_VERSION) - 4 )/sizeof(hcf_16), +#if defined MSF_COMPONENT_ID + MSF_COMPONENT_ID, +#else + 0, +#endif // MSF_COMPONENT_ID + HCF_ALIGN, + HCF_ASSERT, + HCF_BIG_ENDIAN, + 0, // /* HCF_DLV | HCF_DLNV*/, + HCF_DMA, + HCF_ENCAP, + HCF_EXT, + HCF_INT_ON, + HCF_IO, + HCF_LEGACY, + HCF_MAX_LTV, + HCF_PROT_TIME, + HCF_SLEEP, + HCF_TALLIES, + HCF_TYPE, +#if (HCF_TALLIES) & ( HCF_TALLIES_NIC | HCF_TALLIES_HCF ) + HCF_NIC_TAL_CNT, + HCF_HCF_TAL_CNT, + offsetof(IFB_STRCT, IFB_TallyLen ), +#else + 0, 0, 0, +#endif // HCF_TALLIES_NIC / HCF_TALLIES_HCF + HCF_VERSION +}; // cfg_hcf_opt +#endif // MSF_COMPONENT_ID + +#if defined HCF_TALLIES_EXTRA + replaced by HCF_EXT_TALLIES_FW ; +#endif // HCF_TALLIES_EXTRA + +#if defined MSF_COMPONENT_ID || (HCF_EXT) & HCF_EXT_MB +#if (HCF_EXT) & HCF_EXT_MB +HCF_STATIC LTV_STRCT BASED cfg_null = { 1, CFG_NULL, {0} }; +#endif // HCF_EXT_MB +HCF_STATIC hcf_16* BASED xxxx[ ] = { +#if (HCF_EXT) & HCF_EXT_MB + &cfg_null.len, //CFG_NULL 0x0820 +#endif // HCF_EXT_MB +#if defined MSF_COMPONENT_ID + &cfg_drv_identity.len, //CFG_DRV_IDENTITY 0x0826 + &cfg_drv_sup_range.len, //CFG_DRV_SUP_RANGE 0x0827 + &cfg_drv_act_ranges_pri.len, //CFG_DRV_ACT_RANGES_PRI 0x0828 + &cfg_drv_act_ranges_sta.len, //CFG_DRV_ACT_RANGES_STA 0x0829 + &cfg_drv_act_ranges_hsi.len, //CFG_DRV_ACT_RANGES_HSI 0x082A + &cfg_drv_act_ranges_apf.len, //CFG_DRV_ACT_RANGES_APF 0x082B + &cfg_hcf_opt.len, //CFG_HCF_OPT 0x082C + NULL, //IFB_PRIIdentity placeholder 0xFD02 + NULL, //IFB_PRISup placeholder 0xFD03 +#endif // MSF_COMPONENT_ID + NULL //endsentinel + }; +#define xxxx_PRI_IDENTITY_OFFSET (sizeof(xxxx)/sizeof(xxxx[0]) - 3) + +#endif // MSF_COMPONENT_ID / HCF_EXT_MB + + +/************************************************************************************************************ +************************** T O P L E V E L H C F R O U T I N E S ************************************** +************************************************************************************************************/ + +#if (HCF_DL_ONLY) == 0 +/************************************************************************************************************ +* +*.MODULE int hcf_action( IFBP ifbp, hcf_16 action ) +*.PURPOSE Changes the run-time Card behavior. +* Performs Miscellanuous actions. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* action number identifying the type of change +* - HCF_ACT_CCX_OFF disable CKIP +* - HCF_ACT_CCX_ON enable CKIP +* - HCF_ACT_INT_FORCE_ON enable interrupt generation by WaveLAN NIC +* - HCF_ACT_INT_OFF disable interrupt generation by WaveLAN NIC +* - HCF_ACT_INT_ON compensate 1 HCF_ACT_INT_OFF, enable interrupt generation if balance reached +* - HCF_ACT_PRS_SCAN Hermes Probe Respons Scan (F102) command +* - HCF_ACT_RX_ACK acknowledge non-DMA receiver to Hermes +* - HCF_ACT_SCAN Hermes Inquire Scan (F101) command (non-WARP only) +* - HCF_ACT_SLEEP DDS Sleep request +* - HCF_ACT_TALLIES Hermes Inquire Tallies (F100) command +* +*.RETURNS +* HCF_SUCCESS all (including invalid) +* HCF_INT_PENDING HCF_ACT_INT_OFF, interrupt pending +* HCF_ERR_NO_NIC HCF_ACT_INT_OFF, NIC presence check fails +* +*.CONDITIONS +* Except for hcf_action with HCF_ACT_INT_FORCE_ON or HCF_ACT_INT_OFF as parameter or hcf_connect with an I/O +* address (i.e. not HCF_DISCONNECT), all hcf-function calls MUST be preceeded by a call of hcf_action with +* HCF_ACT_INT_OFF as parameter. +* Note that hcf_connect defaults to NIC interrupt disabled mode, i.e. as if hcf_action( HCF_ACT_INT_OFF ) +* was called. +* +*.DESCRIPTION +* hcf_action supports the following mode changing action-code pairs that are antonyms +* - HCF_ACT_CCX_OFF / HCF_ACT_CCX_ON +* - HCF_ACT_INT_[FORCE_]ON / HCF_ACT_INT_OFF +* +* Additionally hcf_action can start the following actions in the NIC: +* - HCF_ACT_PRS_SCAN +* - HCF_ACT_RX_ACK +* - HCF_ACT_SCAN +* - HCF_ACT_SLEEP +* - HCF_ACT_TALLIES +* +* o HCF_ACT_INT_OFF: Sets NIC Interrupts mode Disabled. +* This command, and the associated [Force] Enable NIC interrupts command, are only available if the HCF_INT_ON +* compile time option is not set at 0x0000. +* +* o HCF_ACT_INT_ON: Sets NIC Interrupts mode Enabled. +* Enable NIC Interrupts, depending on the number of preceding Disable NIC Interrupt calls. +* +* o HCF_ACT_INT_FORCE_ON: Force NIC Interrupts mode Enabled. +* Sets NIC Interrupts mode Enabled, regardless off the number of preceding Disable NIC Interrupt calls. +* +* The disabling and enabling of interrupts are antonyms. +* These actions must be balanced. +* For each "disable interrupts" there must be a matching "enable interrupts". +* The disable interrupts may be executed multiple times in a row without intervening enable interrupts, in +* other words, the disable interrupts may be nested. +* The interrupt generation mechanism is disabled at the first call with HCF_ACT_INT_OFF. +* The interrupt generation mechanism is re-enabled when the number of calls with HCF_ACT_INT_ON matches the +* number of calls with INT_OFF. +* +* It is not allowed to have more Enable NIC Interrupts calls than Disable NIC Interrupts calls. +* The interrupt generation mechanism is initially (i.e. after hcf_connect) disabled. +* An MSF based on a interrupt strategy must call hcf_action with INT_ON in its initialization logic. +* +*! The INT_OFF/INT_ON housekeeping is initialized at 0x0000 by hcf_connect, causing the interrupt generation +* mechanism to be disabled at first. This suits MSF implementation based on a polling strategy. +* +* o HCF_ACT_CCX_OFF / HCF_ACT_CCX_ON +*!! This can use some more explanation;? +* Disables and Enables support in the HCF runtime code for the CCX feature. Each time one of these action +* codes is used, the effects of the preceding use cease. +* +* o HCF_ACT_SLEEP: Initiates the Disconnected DeepSleep process +* This command is only available if the HCF_DDS compile time option is set. It triggers the F/W to start the +* sleep handshaking. Regardless whether the Host initiates a Disconnected DeepSleep (DDS) or the F/W initiates +* a Connected DeepSleep (CDS), the Host-F/W sleep handshaking is completed when the NIC Interrupts mode is +* enabled (by means of the balancing HCF_ACT_INT_ON), i.e. at that moment the F/W really goes into sleep mode. +* The F/W is wokenup by the HCF when the NIC Interrupts mode are disabled, i.e. at the first HCF_ACT_INT_OFF +* after going into sleep. +* +* The following Miscellanuous actions are defined: +* +* o HCF_ACT_RX_ACK: Receiver Acknowledgement (non-DMA, non-USB mode only) +* Acking the receiver, frees the NIC memory used to hold the Rx frame and allows the F/W to +* report the existence of the next Rx frame. +* If the MSF does not need access (any longer) to the current frame, e.g. because it is rejected based on the +* look ahead or copied to another buffer, the receiver may be acked. Acking earlier is assumed to have the +* potential of improving the performance. +* If the MSF does not explitly ack te receiver, the acking is done implicitly if: +* - the received frame fits in the look ahead buffer, by the hcf_service_nic call that reported the Rx frame +* - if not in the above step, by hcf_rcv_msg (assuming hcf_rcv_msg is called) +* - if neither of the above implicit acks nor an explicit ack by the MSF, by the first hcf_service_nic after +* the hcf_service_nic that reported the Rx frame. +* Note: If an Rx frame is already acked, an explicit ACK by the MSF acts as a NoOperation. +* +* o HCF_ACT_TALLIES: Inquire Tallies command +* This command is only operational if the F/W is enabled. +* The Inquire Tallies command requests the F/W to provide its current set of tallies. +* See also hcf_get_info with CFG_TALLIES as parameter. +* +* o HCF_ACT_PRS_SCAN: Inquire Probe Respons Scan command +* This command is only operational if the F/W is enabled. +* The Probe Respons Scan command starts a scan sequence. +* The HCF puts the result of this action in an MSF defined buffer (see CFG_RID_LOG_STRCT). +* +* o HCF_ACT_SCAN: Inquire Scan command +* This command is only supported for HII F/W (i.e. pre-WARP) and it is operational if the F/W is enabled. +* The Inquire Scan command starts a scan sequence. +* The HCF puts the result of this action in an MSF defined buffer (see CFG_RID_LOG_STRCT). +* +* Assert fails if +* - ifbp has a recognizable out-of-range value. +* - NIC interrupts are not disabled while required by parameter action. +* - an invalid code is specified in parameter action. +* - HCF_ACT_INT_ON commands outnumber the HCF_ACT_INT_OFF commands. +* - reentrancy, may be caused by calling hcf_functions without adequate protection against NIC interrupts or +* multi-threading +* +* - Since the HCF does not maintain status information relative to the F/W enabled state, it is not asserted +* whether HCF_ACT_SCAN, HCF_ACT_PRS_SCAN or HCF_ACT_TALLIES are only used while F/W is enabled. +* +*.DIAGRAM +* 0: The assert embedded in HCFLOGENTRY checks against re-entrancy. Re-entrancy could be caused by a MSF logic +* at task-level calling hcf_functions without shielding with HCF_ACT_ON/_OFF. However the HCF_ACT_INT_OFF +* action itself can per definition not be protected this way. Based on code inspection, it can be concluded, +* that there is no re-entrancy PROBLEM in this particular flow. It does not seem worth the trouble to +* explicitly check for this condition (although there was a report of an MSF which ran into this assert. +* 2:IFB_IntOffCnt is used to balance the INT_OFF and INT_ON calls. Disabling of the interrupts is achieved by +* writing a zero to the Hermes IntEn register. In a shared interrupt environment (e.g. the mini-PCI NDIS +* driver) it is considered more correct to return the status HCF_INT_PENDING if and only if, the current +* invocation of hcf_service_nic is (apparently) called in the ISR when the ISR was activated as result of a +* change in HREG_EV_STAT matching a bit in HREG_INT_EN, i.e. not if invoked as result of another device +* generating an interrupt on the shared interrupt line. +* Note 1: it has been observed that under certain adverse conditions on certain platforms the writing of +* HREG_INT_EN can apparently fail, therefor it is paramount that HREG_INT_EN is written again with 0 for +* each and every call to HCF_ACT_INT_OFF. +* Note 2: it has been observed that under certain H/W & S/W architectures this logic is called when there is +* no NIC at all. To cater for this, the value of HREG_INT_EN is validated. If the unused bit 0x0100 is set, +* it is assumed there is no NIC. +* Note 3: During the download process, some versions of the F/W reset HREG_SW_0, hence checking this +* register for HCF_MAGIC (the classical NIC presence test) when HCF_ACT_INT_OFF is called due to another +* card interrupting via a shared IRQ during a download, fails. +*4: The construction "if ( ifbp->IFB_IntOffCnt-- == 0 )" is optimal (in the sense of shortest/quickest +* path in error free flows) but NOT fail safe in case of too many INT_ON invocations compared to INT_OFF). +* Enabling of the interrupts is achieved by writing the Hermes IntEn register. +* - If the HCF is in Defunct mode, the interrupts stay disabled. +* - Under "normal" conditions, the HCF is only interested in Info Events, Rx Events and Notify Events. +* - When the HCF is out of Tx/Notify resources, the HCF is also interested in Alloc Events. +* - via HCF_EXT, the MSF programmer can also request HREG_EV_TICK and/or HREG_EV_TX_EXC interrupts. +* For DMA operation, the DMA hardware handles the alloc events. The DMA engine will generate a 'TxDmaDone' +* event as soon as it has pumped a frame from host ram into NIC-RAM (note that the frame does not have to be +* transmitted then), and a 'RxDmaDone' event as soon as a received frame has been pumped from NIC-RAM into +* host ram. Note that the 'alloc' event has been removed from the event-mask, because the DMA engine will +* react to and acknowledge this event. +*6: ack the "old" Rx-event. See "Rx Buffer free strategy" in hcf_service_nic above for more explanation. +* IFB_RxFID and IFB_RxLen must be cleared to bring both the internal HCF house keeping and the information +* supplied to the MSF in the state "no frame received". +*8: The HCF_ACT_SCAN, HCF_ACT_PRS_SCAN and HCF_ACT_TALLIES activity are merged by "clever" algebraic +* manipulations of the RID-values and action codes, so foregoing robustness against migration problems for +* ease of implementation. The assumptions about numerical relationships between CFG_TALLIES etc and +* HCF_ACT_TALLIES etc are checked by the "#if" statements just prior to the body of this routine, resulting +* in: err "maintenance" during compilation if the assumptions are no longer met. The writing of HREG_PARAM_1 +* with 0x3FFF in case of an PRS scan, is a kludge to get around lack of specification, hence different +* implementation in F/W and Host. +* When there is no NIC RAM available, some versions of the Hermes F/W do report 0x7F00 as error in the +* Result field of the Status register and some F/W versions don't. To mask this difference to the MSF all +* return codes of the Hermes are ignored ("best" and "most simple" solution to these types of analomies with +* an acceptable loss due to ignoring all error situations as well). +* The "No inquire space" is reported via the Hermes tallies. +*30: do not HCFASSERT( rc, rc ) since rc == HCF_INT_PENDING is no error +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +#if ( (HCF_TYPE) & HCF_TYPE_HII5 ) == 0 +#if CFG_SCAN != CFG_TALLIES - HCF_ACT_TALLIES + HCF_ACT_SCAN +err: "maintenance" apparently inviolated the underlying assumption about the numerical values of these macros +#endif +#endif // HCF_TYPE_HII5 +#if CFG_PRS_SCAN != CFG_TALLIES - HCF_ACT_TALLIES + HCF_ACT_PRS_SCAN +err: "maintenance" apparently inviolated the underlying assumption about the numerical values of these macros +#endif +int +hcf_action( IFBP ifbp, hcf_16 action ) +{ +int rc = HCF_SUCCESS; + + HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic ) +#if HCF_INT_ON + HCFLOGENTRY( action == HCF_ACT_INT_FORCE_ON ? HCF_TRACE_ACTION_KLUDGE : HCF_TRACE_ACTION, action ) /* 0 */ +#if (HCF_SLEEP) + HCFASSERT( ifbp->IFB_IntOffCnt != 0xFFFE || action == HCF_ACT_INT_OFF, + MERGE_2( action, ifbp->IFB_IntOffCnt ) ) +#else + HCFASSERT( ifbp->IFB_IntOffCnt != 0xFFFE, action ) +#endif // HCF_SLEEP + HCFASSERT( ifbp->IFB_IntOffCnt != 0xFFFF || + action == HCF_ACT_INT_OFF || action == HCF_ACT_INT_FORCE_ON, action ) + HCFASSERT( ifbp->IFB_IntOffCnt <= 16 || ifbp->IFB_IntOffCnt >= 0xFFFE, + MERGE_2( action, ifbp->IFB_IntOffCnt ) ) //nesting more than 16 deep seems unreasonable +#endif // HCF_INT_ON + + switch (action) { +#if HCF_INT_ON +hcf_16 i; + case HCF_ACT_INT_OFF: // Disable Interrupt generation +#if HCF_SLEEP + if ( ifbp->IFB_IntOffCnt == 0xFFFE ) { // WakeUp test ;?tie this to the "new" super-LinkStat + ifbp->IFB_IntOffCnt++; // restore conventional I/F + OPW(HREG_IO, HREG_IO_WAKEUP_ASYNC ); // set wakeup bit + OPW(HREG_IO, HREG_IO_WAKEUP_ASYNC ); // set wakeup bit to counteract the clearing by F/W + // 800 us latency before FW switches to high power + MSF_WAIT(800); // MSF-defined function to wait n microseconds. +//OOR if ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_DS_OOR ) { // OutOfRange +// printk( "<5>ACT_INT_OFF: Deepsleep phase terminated, enable and go to AwaitConnection\n" ); //;?remove me 1 day +// hcf_cntl( ifbp, HCF_CNTL_ENABLE ); +// } +// ifbp->IFB_DSLinkStat &= ~( CFG_LINK_STAT_DS_IR | CFG_LINK_STAT_DS_OOR); //clear IR/OOR state + } +#endif // HCF_SLEEP +/*2*/ ifbp->IFB_IntOffCnt++; +//! rc = 0; + i = IPW( HREG_INT_EN ); + OPW( HREG_INT_EN, 0 ); + if ( i & 0x1000 ) { + rc = HCF_ERR_NO_NIC; + } else { + if ( i & IPW( HREG_EV_STAT ) ) { + rc = HCF_INT_PENDING; + } + } + break; + + case HCF_ACT_INT_FORCE_ON: // Enforce Enable Interrupt generation + ifbp->IFB_IntOffCnt = 0; + //Fall through in HCF_ACT_INT_ON + + case HCF_ACT_INT_ON: // Enable Interrupt generation +/*4*/ if ( ifbp->IFB_IntOffCnt-- == 0 && ifbp->IFB_CardStat == 0 ) { + //determine Interrupt Event mask +#if HCF_DMA + if ( ifbp->IFB_CntlOpt & USE_DMA ) { + i = HREG_EV_INFO | HREG_EV_RDMAD | HREG_EV_TDMAD | HREG_EV_TX_EXT; //mask when DMA active + } else +#endif // HCF_DMA + { + i = HREG_EV_INFO | HREG_EV_RX | HREG_EV_TX_EXT; //mask when DMA not active + if ( ifbp->IFB_RscInd == 0 ) { + i |= HREG_EV_ALLOC; //mask when no TxFID available + } + } +#if HCF_SLEEP + if ( ( IPW(HREG_EV_STAT) & ( i | HREG_EV_SLEEP_REQ ) ) == HREG_EV_SLEEP_REQ ) { + // firmware indicates it would like to go into sleep modus + // only acknowledge this request if no other events that can cause an interrupt are pending + ifbp->IFB_IntOffCnt--; //becomes 0xFFFE + OPW( HREG_INT_EN, i | HREG_EV_TICK ); + OPW( HREG_EV_ACK, HREG_EV_SLEEP_REQ | HREG_EV_TICK | HREG_EV_ACK_REG_READY ); + } else +#endif // HCF_SLEEP + { + OPW( HREG_INT_EN, i | HREG_EV_SLEEP_REQ ); + } + } + break; +#endif // HCF_INT_ON + +#if (HCF_SLEEP) & HCF_DDS + case HCF_ACT_SLEEP: // DDS Sleep request + hcf_cntl( ifbp, HCF_CNTL_DISABLE ); + cmd_exe( ifbp, HCMD_SLEEP, 0 ); + break; +// case HCF_ACT_WAKEUP: // DDS Wakeup request +// HCFASSERT( ifbp->IFB_IntOffCnt == 0xFFFE, ifbp->IFB_IntOffCnt ) +// ifbp->IFB_IntOffCnt++; // restore conventional I/F +// OPW( HREG_IO, HREG_IO_WAKEUP_ASYNC ); +// MSF_WAIT(800); // MSF-defined function to wait n microseconds. +// rc = hcf_action( ifbp, HCF_ACT_INT_OFF ); /*bogus, IFB_IntOffCnt == 0xFFFF, so if you carefully look +// *at the #if HCF_DDS statements, HCF_ACT_INT_OFF is empty +// *for DDS. "Much" better would be to merge the flows for +// *DDS and DEEP_SLEEP +// */ +// break; +#endif // HCF_DDS + +#if (HCF_TYPE) & HCF_TYPE_CCX + case HCF_ACT_CCX_ON: // enable CKIP + case HCF_ACT_CCX_OFF: // disable CKIP + ifbp->IFB_CKIPStat = action; + break; +#endif // HCF_TYPE_CCX + + case HCF_ACT_RX_ACK: //Receiver ACK +/*6*/ if ( ifbp->IFB_RxFID ) { + DAWA_ACK( HREG_EV_RX ); + } + ifbp->IFB_RxFID = ifbp->IFB_RxLen = 0; + break; + +/*8*/ case HCF_ACT_PRS_SCAN: // Hermes PRS Scan (F102) + OPW( HREG_PARAM_1, 0x3FFF ); + //Fall through in HCF_ACT_TALLIES + case HCF_ACT_TALLIES: // Hermes Inquire Tallies (F100) +#if ( (HCF_TYPE) & HCF_TYPE_HII5 ) == 0 + case HCF_ACT_SCAN: // Hermes Inquire Scan (F101) +#endif // HCF_TYPE_HII5 + /*!! the assumptions about numerical relationships between CFG_TALLIES etc and HCF_ACT_TALLIES etc + * are checked by #if statements just prior to this routine resulting in: err "maintenance" */ + cmd_exe( ifbp, HCMD_INQUIRE, action - HCF_ACT_TALLIES + CFG_TALLIES ); + break; + + default: + HCFASSERT( DO_ASSERT, action ) + break; + } + //! do not HCFASSERT( rc == HCF_SUCCESS, rc ) /* 30*/ + HCFLOGEXIT( HCF_TRACE_ACTION ) + return rc; +} // hcf_action +#endif // HCF_DL_ONLY + + +/************************************************************************************************************ +* +*.MODULE int hcf_cntl( IFBP ifbp, hcf_16 cmd ) +*.PURPOSE Connect or disconnect a specific port to a specific network. +*!! ;???????????????? continue needs more explanation +* recovers by means of "continue" when the connect proces in CCX mode fails +* Enables or disables data transmission and reception for the NIC. +* Activates static NIC configuration for a specific port at connect. +* Activates static configuration for all ports at enable. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* cmd 0x001F: Hermes command (disable, enable, connect, disconnect, continue) +* HCF_CNTL_ENABLE Enable +* HCF_CNTL_DISABLE Disable +* HCF_CNTL_CONTINUE Continue +* HCF_CNTL_CONNECT Connect +* HCF_CNTL_DISCONNECT Disconnect +* 0x0100: command qualifier (continue) +* HCMD_RETRY retry flag +* 0x0700: port number (connect/disconnect) +* HCF_PORT_0 MAC Port 0 +* HCF_PORT_1 MAC Port 1 +* HCF_PORT_2 MAC Port 2 +* HCF_PORT_3 MAC Port 3 +* HCF_PORT_4 MAC Port 4 +* HCF_PORT_5 MAC Port 5 +* HCF_PORT_6 MAC Port 6 +* +*.RETURNS +* HCF_SUCCESS +*!! via cmd_exe +* HCF_ERR_NO_NIC +* HCF_ERR_DEFUNCT_... +* HCF_ERR_TIME_OUT +* +*.DESCRIPTION +* The parameter cmd contains a number of subfields. +* The actual value for cmd is created by logical or-ing the appropriate mnemonics for the subfields. +* The field 0x001F contains the command code +* - HCF_CNTL_ENABLE +* - HCF_CNTL_DISABLE +* - HCF_CNTL_CONNECT +* - HCF_CNTL_DISCONNECT +* - HCF_CNTL_CONTINUE +* +* For HCF_CNTL_CONTINUE, the field 0x0100 contains the retry flag HCMD_RETRY. +* For HCF_CNTL_CONNECT and HCF_CNTL_DISCONNECT, the field 0x0700 contains the port number as HCF_PORT_#. +* For Station as well as AccessPoint F/W, MAC Port 0 is the "normal" communication channel. +* For AccessPoint F/W, MAC Port 1 through 6 control the WDS links. +* +* Note that despite the names HCF_CNTL_DISABLE and HCF_CNTL_ENABLE, hcf_cntl does not influence the NIC +* Interrupts mode. +* +* The Connect is used by the MSF to bring a particular port in an inactive state as far as data transmission +* and reception are concerned. +* When a particular port is disconnected: +* - the F/W disables the receiver for that port. +* - the F/W ignores send commands for that port. +* - all frames (Receive as well as pending Transmit) for that port on the NIC are discarded. +* +* When the NIC is disabled, above list applies to all ports, i.e. the result is like all ports are +* disconnected. +* +* When a particular port is connected: +* - the F/W effectuates the static configuration for that port. +* - enables the receiver for that port. +* - accepts send commands for that port. +* +* Enabling has the following effects: +* - the F/W effectuates the static configuration for all ports. +* The F/W only updates its static configuration at a transition from disabled to enabled or from +* disconnected to connected. +* In order to enforce the static configuration, the MSF must assure that such a transition takes place. +* Due to such a disable/enable or disconnect/connect sequence, Rx/Tx frames may be lost, in other words, +* configuration may impact communication. +* - The DMA Engine (if applicable) is enabled. +* Note that the Enable Function by itself only enables data transmission and reception, it +* does not enable the Interrupt Generation mechanism. This is done by hcf_action. +* +* Disabling has the following effects: +*!! ;?????is the following statement really true +* - it acts as a disconnect on all ports. +* - The DMA Engine (if applicable) is disabled. +* +* For impact of the disable command on the behavior of hcf_dma_tx/rx_get see the appropriate sections. +* +* Although the Enable/Disable and Connect/Disconnect are antonyms, there is no restriction on their sequencing, +* in other words, they may be called multiple times in arbitrary sequence without being paired or balanced. +* Each time one of these functions is called, the effects of the preceding calls cease. +* +* Assert fails if +* - ifbp has a recognizable out-of-range value. +* - NIC interrupts are not disabled. +* - A command other than Continue, Enable, Disable, Connect or Disconnect is given. +* - An invalid combination of the subfields is given or a bit outside the subfields is given. +* - any return code besides HCF_SUCCESS. +* - reentrancy, may be caused by calling a hcf_function without adequate protection against NIC interrupts or +* multi-threading +* +*.DIAGRAM +* hcf_cntl takes successively the following actions: +*2: If the HCF is in Defunct mode or incompatible with the Primary or Station Supplier in the Hermes, +* hcf_cntl() returns immediately with HCF_ERR_NO_NIC;? as status. +*8: when the port is disabled, the DMA engine needs to be de-activated, so the host can safely reclaim tx +* packets from the tx descriptor chain. +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +int +hcf_cntl( IFBP ifbp, hcf_16 cmd ) +{ +int rc = HCF_ERR_INCOMP_FW; +#if HCF_ASSERT +{ int x = cmd & HCMD_CMD_CODE; + if ( x == HCF_CNTL_CONTINUE ) x &= ~HCMD_RETRY; + else if ( (x == HCMD_DISABLE || x == HCMD_ENABLE) && ifbp->IFB_FWIdentity.comp_id == COMP_ID_FW_AP ) { + x &= ~HFS_TX_CNTL_PORT; + } + HCFASSERT( x==HCF_CNTL_ENABLE || x==HCF_CNTL_DISABLE || HCF_CNTL_CONTINUE || + x==HCF_CNTL_CONNECT || x==HCF_CNTL_DISCONNECT, cmd ) +} +#endif // HCF_ASSERT +// #if (HCF_SLEEP) & HCF_DDS +// HCFASSERT( ifbp->IFB_IntOffCnt != 0xFFFE, cmd ) +// #endif // HCF_DDS + HCFLOGENTRY( HCF_TRACE_CNTL, cmd ) + if ( ifbp->IFB_CardStat == 0 ) { /*2*/ +/*6*/ rc = cmd_exe( ifbp, cmd, 0 ); +#if (HCF_SLEEP) & HCF_DDS + ifbp->IFB_TickCnt = 0; //start 2 second period (with 1 tick uncertanty) +#endif // HCF_DDS + } +#if HCF_DMA + //!rlav : note that this piece of code is always executed, regardless of the DEFUNCT bit in IFB_CardStat. + // The reason behind this is that the MSF should be able to get all its DMA resources back from the HCF, + // even if the hardware is disfunctional. Practical example under Windows : surprise removal. + if ( ifbp->IFB_CntlOpt & USE_DMA ) { + hcf_io io_port = ifbp->IFB_IOBase; + DESC_STRCT *p; + if ( cmd == HCF_CNTL_DISABLE || cmd == HCF_CNTL_ENABLE ) { + OUT_PORT_DWORD( (io_port + HREG_DMA_CTRL), DMA_CTRLSTAT_RESET); /*8*/ + ifbp->IFB_CntlOpt &= ~DMA_ENABLED; + } + if ( cmd == HCF_CNTL_ENABLE ) { + OUT_PORT_DWORD( (io_port + HREG_DMA_CTRL), DMA_CTRLSTAT_GO); + /* ;? by rewriting hcf_dma_rx_put you can probably just call hcf_dma_rx_put( ifbp->IFB_FirstDesc[DMA_RX] ) + * as additional beneficiary side effect, the SOP and EOP bits will also be cleared + */ + ifbp->IFB_CntlOpt |= DMA_ENABLED; + HCFASSERT( NT_ASSERT, NEVER_TESTED ) + // make the entire rx descriptor chain DMA-owned, so the DMA engine can (re-)use it. + if ( ( p = ifbp->IFB_FirstDesc[DMA_RX] ) != NULL ) { //;? Think this over again in the light of the new chaining strategy + if ( 1 ) { //begin alternative + HCFASSERT( NT_ASSERT, NEVER_TESTED ) + put_frame_lst( ifbp, ifbp->IFB_FirstDesc[DMA_RX], DMA_RX ); + if ( ifbp->IFB_FirstDesc[DMA_RX] ) { + put_frame_lst( ifbp, ifbp->IFB_FirstDesc[DMA_RX]->next_desc_addr, DMA_RX ); + } + } else { + while ( p ) { + //p->buf_cntl.cntl_stat |= DESC_DMA_OWNED; + p->BUF_CNT |= DESC_DMA_OWNED; + p = p->next_desc_addr; + } + // a rx chain is available so hand it over to the DMA engine + p = ifbp->IFB_FirstDesc[DMA_RX]; + OUT_PORT_DWORD( (io_port + HREG_RXDMA_PTR32), p->desc_phys_addr); + } //end alternative + } + } + } +#endif // HCF_DMA + HCFASSERT( rc == HCF_SUCCESS, rc ) + HCFLOGEXIT( HCF_TRACE_CNTL ) + return rc; +} // hcf_cntl + + +/************************************************************************************************************ +* +*.MODULE int hcf_connect( IFBP ifbp, hcf_io io_base ) +*.PURPOSE Grants access right for the HCF to the IFB. +* Initializes Card and HCF housekeeping. +* +*.ARGUMENTS +* ifbp (near) address of the Interface Block +* io_base non-USB: I/O Base address of the NIC (connect) +* non-USB: HCF_DISCONNECT +* USB: HCF_CONNECT, HCF_DISCONNECT +* +*.RETURNS +* HCF_SUCCESS +* HCF_ERR_INCOMP_PRI +* HCF_ERR_INCOMP_FW +* HCF_ERR_DEFUNCT_CMD_SEQ +*!! HCF_ERR_NO_NIC really returned ;? +* HCF_ERR_NO_NIC +* HCF_ERR_TIME_OUT +* +* MSF-accessible fields of Result Block: +* IFB_IOBase entry parameter io_base +* IFB_IORange HREG_IO_RANGE (0x40/0x80) +* IFB_Version version of the IFB layout +* IFB_FWIdentity CFG_FW_IDENTITY_STRCT, specifies the identity of the +* "running" F/W, i.e. tertiary F/W under normal conditions +* IFB_FWSup CFG_SUP_RANGE_STRCT, specifies the supplier range of +* the "running" F/W, i.e. tertiary F/W under normal conditions +* IFB_HSISup CFG_SUP_RANGE_STRCT, specifies the HW/SW I/F range of the NIC +* IFB_PRIIdentity CFG_PRI_IDENTITY_STRCT, specifies the Identity of the Primary F/W +* IFB_PRISup CFG_SUP_RANGE_STRCT, specifies the supplier range of the Primary F/W +* all other all MSF accessible fields, which are not specified above, are zero-filled +* +*.CONDITIONS +* It is the responsibility of the MSF to assure the correctness of the I/O Base address. +* +* Note: hcf_connect defaults to NIC interrupt disabled mode, i.e. as if hcf_action( HCF_ACT_INT_OFF ) +* was called. +* +*.DESCRIPTION +* hcf_connect passes the MSF-defined location of the IFB to the HCF and grants or revokes access right for the +* HCF to the IFB. Revoking is done by specifying HCF_DISCONNECT rather than an I/O address for the parameter +* io_base. Every call of hcf_connect in "connect" mode, must eventually be followed by a call of hcf_connect +* in "disconnect" mode. Clalling hcf_connect in "connect"/"disconnect" mode can not be nested. +* The IFB address must be used as a handle with all subsequent HCF-function calls and the HCF uses the IFB +* address as a handle when it performs a call(back) of an MSF-function (i.e. msf_assert). +* +* Note that not only the MSF accessible fields are cleared, but also all internal housekeeping +* information is re-initialized. +* This implies that all settings which are done via hcf_action and hcf_put_info (e.g. CFG_MB_ASSERT, CFG_REG_MB, +* CFG_REG_INFO_LOG) must be done again. The only field which is not cleared, is IFB_MSFSup. +* +* If HCF_INT_ON is selected as compile option, NIC interrupts are disabled. +* +* Assert fails if +* - ifbp is not properly aligned ( ref chapter HCF_ALIGN in 4.1.1) +* - I/O Base Address is not a multiple of 0x40 (note: 0x0000 is explicitly allowed). +* +*.DIAGRAM +* +*0: Throughout hcf_connect you need to distinguish the connect from the disconnect case, which requires +* some attention about what to use as "I/O" address when for which purpose. +*2: +*2a: Reset H-II by toggling reset bit in IO-register on and off. +* The HCF_TYPE_PRELOADED caters for the DOS environment where H-II is loaded by a separate program to +* overcome the 64k size limit posed on DOS drivers. +* The macro OPW is not yet useable because the IFB_IOBase field is not set. +* Note 1: hopefully the clearing and initializing of the IFB (see below) acts as a delay which meets the +* specification for S/W reset +* Note 2: it turns out that on some H/W constellations, the clock to access the EEProm is not lowered +* to an appropriate frequency by HREG_IO_SRESET. By giving an HCMD_INI first, this problem is worked around. +*2b: Experimentally it is determined over a wide range of F/W versions that waiting for the for Cmd bit in +* Ev register gives a workable strategy. The available documentation does not give much clues. +*4: clear and initialize the IFB +* The HCF house keeping info is designed such that zero is the appropriate initial value for as much as +* feasible IFB-items. +* The readable fields mentioned in the description section and some HCF specific fields are given their +* actual value. +* IFB_TickIni is initialized at best guess before calibration +* Hcf_connect defaults to "no interrupt generation" (implicitly achieved by the zero-filling). +*6: Register compile-time linked MSF Routine and set default filter level +* cast needed to get around the "near" problem in DOS COM model +* er C2446: no conversion from void (__near __cdecl *)(unsigned char __far *,unsigned int,unsigned short,int) +* to void (__far __cdecl *)(unsigned char __far *,unsigned int,unsigned short,int) +*8: If a command is apparently still active (as indicated by the Busy bit in Cmd register) this may indicate a +* blocked cmd pipe line. To unblock the following actions are done: +* - Ack everything +* - Wait for Busy bit drop in Cmd register +* - Wait for Cmd bit raise in Ev register +* The two waits are combined in a single HCF_WAIT_WHILE to optimize memory size. If either of these waits +* fail (prot_cnt becomes 0), then something is serious wrong. Rather than PANICK, the assumption is that the +* next cmd_exe will fail, causing the HCF to go into DEFUNCT mode +*10: Ack everything to unblock a (possibly blocked) cmd pipe line +* Note 1: it is very likely that an Alloc event is pending and very well possible that a (Send) Cmd event is +* pending on non-initial calls +* Note 2: it is assumed that this strategy takes away the need to ack every conceivable event after an +* Hermes Initialize +*12: Only H-II NEEDS the Hermes Initialize command. Due to the different semantics for H-I and H-II +* Initialize command, init() does not (and can not, since it is called e.g. after a download) execute the +* Hermes Initialize command. Executing the Hermes Initialize command for H-I would not harm but not do +* anything useful either, so it is skipped. +* The return status of cmd_exe is ignored. It is assumed that if cmd_exe fails, init fails too +*14: use io_base as a flag to merge hcf_connect and hcf_disconnect into 1 routine +* the call to init and its subsequent call of cmd_exe will return HCF_ERR_NO_NIC if appropriate. This status +* is (badly) needed by some legacy combination of NT4 and card services which do not yield an I/O address in +* time. +* +*.NOTICE +* On platforms where the NULL-pointer is not a bit-pattern of all zeros, the zero-filling of the IFB results +* in an incorrect initialization of pointers. +* The implementation of the MailBox manipulation in put_mb_info protects against the absence of a MailBox +* based on IFB_MBSize, IFB_MBWp and ifbp->IFB_MBRp. This has ramifications on the initialization of the +* MailBox via hcf_put_info with the CFG_REG_MB type, but it prevents dependency on the "NULL-"ness of +* IFB_MBp. +* +*.NOTICE +* There are a number of problems when asserting and logging hcf_connect, e.g. +* - Asserting on re-entrancy of hcf_connect by means of +* "HCFASSERT( (ifbp->IFB_AssertTrace & HCF_ASSERT_CONNECT) == 0, 0 )" is not useful because IFB contents +* are undefined +* - Asserting before the IFB is cleared will cause mdd_assert() to interpret the garbage in IFB_AssertRtn +* as a routine address +* Therefore HCFTRACE nor HCFLOGENTRY is called by hcf_connect. +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +int +hcf_connect( IFBP ifbp, hcf_io io_base ) +{ +int rc = HCF_SUCCESS; +hcf_io io_addr; +hcf_32 prot_cnt; +hcf_8 *q; +LTV_STRCT x; +#if HCF_ASSERT + hcf_16 xa = ifbp->IFB_FWIdentity.typ; + /* is assumed to cause an assert later on if hcf_connect is called without intervening hcf_disconnect. + * xa == CFG_FW_IDENTITY in subsequent calls without preceding hcf_disconnect, + * xa == 0 in subsequent calls with preceding hcf_disconnect, + * xa == "garbage" (any value except CFG_FW_IDENTITY is acceptable) in the initial call + */ +#endif // HCF_ASSERT + + if ( io_base == HCF_DISCONNECT ) { //disconnect + io_addr = ifbp->IFB_IOBase; + OPW( HREG_INT_EN, 0 ); //;?workaround against dying F/W on subsequent hcf_connect calls + } else { //connect /* 0 */ + io_addr = io_base; + } + +#if 0 //;? if a subsequent hcf_connect is preceeded by an hcf_disconnect the wakeup is not needed !! +#if HCF_SLEEP + OUT_PORT_WORD( .....+HREG_IO, HREG_IO_WAKEUP_ASYNC ); //OPW not yet useable + MSF_WAIT(800); // MSF-defined function to wait n microseconds. + note that MSF_WAIT uses not yet defined!!!! IFB_IOBase and IFB_TickIni (via PROT_CNT_INI) + so be carefull if this code is restored +#endif // HCF_SLEEP +#endif // 0 + +#if ( (HCF_TYPE) & HCF_TYPE_PRELOADED ) == 0 //switch clock back for SEEPROM access !!! + OUT_PORT_WORD( io_addr + HREG_CMD, HCMD_INI ); //OPW not yet useable + prot_cnt = INI_TICK_INI; + HCF_WAIT_WHILE( (IN_PORT_WORD( io_addr + HREG_EV_STAT) & HREG_EV_CMD) == 0 ); + OUT_PORT_WORD( (io_addr + HREG_IO), HREG_IO_SRESET ); //OPW not yet useable /* 2a*/ +#endif // HCF_TYPE_PRELOADED + for ( q = (hcf_8*)(&ifbp->IFB_Magic); q > (hcf_8*)ifbp; *--q = 0 ) /*NOP*/; /* 4 */ + ifbp->IFB_Magic = HCF_MAGIC; + ifbp->IFB_Version = IFB_VERSION; +#if defined MSF_COMPONENT_ID //a new IFB demonstrates how dirty the solution is + xxxx[xxxx_PRI_IDENTITY_OFFSET] = NULL; //IFB_PRIIdentity placeholder 0xFD02 + xxxx[xxxx_PRI_IDENTITY_OFFSET+1] = NULL; //IFB_PRISup placeholder 0xFD03 +#endif // MSF_COMPONENT_ID +#if (HCF_TALLIES) & ( HCF_TALLIES_NIC | HCF_TALLIES_HCF ) + ifbp->IFB_TallyLen = 1 + 2 * (HCF_NIC_TAL_CNT + HCF_HCF_TAL_CNT); //convert # of Tallies to L value for LTV + ifbp->IFB_TallyTyp = CFG_TALLIES; //IFB_TallyTyp: set T value +#endif // HCF_TALLIES_NIC / HCF_TALLIES_HCF + ifbp->IFB_IOBase = io_addr; //set IO_Base asap, so asserts via HREG_SW_2 don't harm + ifbp->IFB_IORange = HREG_IO_RANGE; + ifbp->IFB_CntlOpt = USE_16BIT; +#if HCF_ASSERT + assert_ifbp = ifbp; + ifbp->IFB_AssertLvl = 1; +#if (HCF_ASSERT) & HCF_ASSERT_LNK_MSF_RTN + if ( io_base != HCF_DISCONNECT ) { + ifbp->IFB_AssertRtn = (MSF_ASSERT_RTNP)msf_assert; /* 6 */ + } +#endif // HCF_ASSERT_LNK_MSF_RTN +#if (HCF_ASSERT) & HCF_ASSERT_MB //build the structure to pass the assert info to hcf_put_info + ifbp->IFB_AssertStrct.len = sizeof(ifbp->IFB_AssertStrct)/sizeof(hcf_16) - 1; + ifbp->IFB_AssertStrct.typ = CFG_MB_INFO; + ifbp->IFB_AssertStrct.base_typ = CFG_MB_ASSERT; + ifbp->IFB_AssertStrct.frag_cnt = 1; + ifbp->IFB_AssertStrct.frag_buf[0].frag_len = + ( offsetof(IFB_STRCT, IFB_AssertLvl) - offsetof(IFB_STRCT, IFB_AssertLine) ) / sizeof(hcf_16); + ifbp->IFB_AssertStrct.frag_buf[0].frag_addr = &ifbp->IFB_AssertLine; +#endif // HCF_ASSERT_MB +#endif // HCF_ASSERT + IF_PROT_TIME( prot_cnt = ifbp->IFB_TickIni = INI_TICK_INI; ) +#if ( (HCF_TYPE) & HCF_TYPE_PRELOADED ) == 0 + //!! No asserts before Reset-bit in HREG_IO is cleared + OPW( HREG_IO, 0x0000 ); //OPW useable /* 2b*/ + HCF_WAIT_WHILE( (IPW( HREG_EV_STAT) & HREG_EV_CMD) == 0 ); + IF_PROT_TIME( HCFASSERT( prot_cnt, IPW( HREG_EV_STAT) ) ) + IF_PROT_TIME( if ( prot_cnt ) prot_cnt = ifbp->IFB_TickIni; ) +#endif // HCF_TYPE_PRELOADED + //!! No asserts before Reset-bit in HREG_IO is cleared + HCFASSERT( DO_ASSERT, MERGE_2( HCF_ASSERT, 0xCAF0 ) ) //just to proof that the complete assert machinery is working + HCFASSERT( xa != CFG_FW_IDENTITY, 0 ) // assert if hcf_connect is called without intervening hcf_disconnect. + HCFASSERT( ((hcf_32)(void*)ifbp & (HCF_ALIGN-1) ) == 0, (hcf_32)(void*)ifbp ) + HCFASSERT( (io_addr & 0x003F) == 0, io_addr ) + //if Busy bit in Cmd register + if (IPW( HREG_CMD ) & HCMD_BUSY ) { /* 8 */ + //. Ack all to unblock a (possibly) blocked cmd pipe line + OPW( HREG_EV_ACK, ~HREG_EV_SLEEP_REQ ); + //. Wait for Busy bit drop in Cmd register + //. Wait for Cmd bit raise in Ev register + HCF_WAIT_WHILE( ( IPW( HREG_CMD ) & HCMD_BUSY ) && (IPW( HREG_EV_STAT) & HREG_EV_CMD) == 0 ); + IF_PROT_TIME( HCFASSERT( prot_cnt, IPW( HREG_EV_STAT) ) ) /* if prot_cnt == 0, cmd_exe will fail, causing DEFUNCT */ + } + OPW( HREG_EV_ACK, ~HREG_EV_SLEEP_REQ ); +#if ( (HCF_TYPE) & HCF_TYPE_PRELOADED ) == 0 /*12*/ + (void)cmd_exe( ifbp, HCMD_INI, 0 ); +#endif // HCF_TYPE_PRELOADED +if ( io_base != HCF_DISCONNECT ) { + rc = init( ifbp ); /*14*/ + if ( rc == HCF_SUCCESS ) { + x.len = 2; + x.typ = CFG_NIC_BUS_TYPE; + (void)hcf_get_info( ifbp, &x ); + ifbp->IFB_BusType = x.val[0]; + //CFG_NIC_BUS_TYPE not supported -> default 32 bits/DMA, MSF has to overrule via CFG_CNTL_OPT + if ( x.len == 0 || x.val[0] == 0x0002 || x.val[0] == 0x0003 ) { +#if (HCF_IO) & HCF_IO_32BITS + ifbp->IFB_CntlOpt &= ~USE_16BIT; //reset USE_16BIT +#endif // HCF_IO_32BITS +#if HCF_DMA + ifbp->IFB_CntlOpt |= USE_DMA; //SET DMA +#else + ifbp->IFB_IORange = 0x40 /*i.s.o. HREG_IO_RANGE*/; +#endif // HCF_DMA + } + } + } else HCFASSERT( ( ifbp->IFB_Magic ^= HCF_MAGIC ) == 0, ifbp->IFB_Magic ) /*NOP*/; + /* of above HCFASSERT only the side effect is needed, NOP in case HCFASSERT is dummy */ + ifbp->IFB_IOBase = io_base; /* 0*/ + return rc; +} // hcf_connect + +#if HCF_DMA +/************************************************************************************************************ +* Function get_frame_lst +* - resolve the "last host-owned descriptor" problems when a descriptor list is reclaimed by the MSF. +* +* The FrameList to be reclaimed as well as the DescriptorList always start in IFB_FirstDesc[tx_rx_flag] +* and this is always the "current" DELWA Descriptor. +* +* If a FrameList is available, the last descriptor of the FrameList to turned into a new DELWA Descriptor: +* - a copy is made from the information in the last descriptor of the FrameList into the current +* DELWA Descriptor +* - the remainder of the DescriptorList is detached from the copy by setting the next_desc_addr at NULL +* - the DMA control bits of the copy are cleared to do not confuse the MSF +* - the copy of the last descriptor (i.e. the "old" DELWA Descriptor) is chained to the prev Descriptor +* of the FrameList, thus replacing the original last Descriptor of the FrameList. +* - IFB_FirstDesc is changed to the address of that replaced (original) last descriptor of the FrameList, +* i.e. the "new" DELWA Descriptor. +* +* This function makes a copy of that last host-owned descriptor, so the MSF will get a copy of the descriptor. +* On top of that, it adjusts DMA related fields in the IFB structure. + // perform a copying-scheme to circumvent the 'last host owned descriptor cannot be reclaimed' limitation imposed by H2.5's DMA hardware design + // a 'reclaim descriptor' should be available in the HCF: +* +* Returns: address of the first descriptor of the FrameList +* + 8: Be careful once you start re-ordering the steps in the copy process, that it still works for cases +* of FrameLists of 1, 2 and more than 2 descriptors +* +* Input parameters: +* tx_rx_flag : specifies 'transmit' or 'receive' descriptor. +* +************************************************************************************************************/ +HCF_STATIC DESC_STRCT* +get_frame_lst( IFBP ifbp, int tx_rx_flag ) +{ + +DESC_STRCT *head = ifbp->IFB_FirstDesc[tx_rx_flag]; +DESC_STRCT *copy, *p, *prev; + + HCFASSERT( tx_rx_flag == DMA_RX || tx_rx_flag == DMA_TX, tx_rx_flag ) + //if FrameList + if ( head ) { + //. search for last descriptor of first FrameList + p = prev = head; + while ( ( p->BUF_SIZE & DESC_EOP ) == 0 && p->next_desc_addr ) { + if ( ( ifbp->IFB_CntlOpt & DMA_ENABLED ) == 0 ) { //clear control bits when disabled + p->BUF_CNT &= DESC_CNT_MASK; + } + prev = p; + p = p->next_desc_addr; + } + //. if DMA enabled + if ( ifbp->IFB_CntlOpt & DMA_ENABLED ) { + //. . if last descriptor of FrameList is DMA owned + //. . or if FrameList is single (DELWA) Descriptor + if ( p->BUF_CNT & DESC_DMA_OWNED || head->next_desc_addr == NULL ) { + //. . . refuse to return FrameList to caller + head = NULL; + } + } + } + //if returnable FrameList found + if ( head ) { + //. if FrameList is single (DELWA) Descriptor (implies DMA disabled) + if ( head->next_desc_addr == NULL ) { + //. . clear DescriptorList + /*;?ifbp->IFB_LastDesc[tx_rx_flag] =*/ ifbp->IFB_FirstDesc[tx_rx_flag] = NULL; + //. else + } else { + //. . strip hardware-related bits from last descriptor + //. . remove DELWA Descriptor from head of DescriptorList + copy = head; + head = head->next_desc_addr; + //. . exchange first (Confined) and last (possibly imprisoned) Descriptor + copy->buf_phys_addr = p->buf_phys_addr; + copy->buf_addr = p->buf_addr; + copy->BUF_SIZE = p->BUF_SIZE &= DESC_CNT_MASK; //get rid of DESC_EOP and possibly DESC_SOP + copy->BUF_CNT = p->BUF_CNT &= DESC_CNT_MASK; //get rid of DESC_DMA_OWNED +#if (HCF_EXT) & HCF_DESC_STRCT_EXT + copy->DESC_MSFSup = p->DESC_MSFSup; +#endif // HCF_DESC_STRCT_EXT + //. . turn into a DELWA Descriptor + p->buf_addr = NULL; + //. . chain copy to prev /* 8*/ + prev->next_desc_addr = copy; + //. . detach remainder of the DescriptorList from FrameList + copy->next_desc_addr = NULL; + copy->next_desc_phys_addr = 0xDEAD0000; //! just to be nice, not really needed + //. . save the new start (i.e. DELWA Descriptor) in IFB_FirstDesc + ifbp->IFB_FirstDesc[tx_rx_flag] = p; + } + //. strip DESC_SOP from first descriptor + head->BUF_SIZE &= DESC_CNT_MASK; + //head->BUF_CNT &= DESC_CNT_MASK; get rid of DESC_DMA_OWNED + head->next_desc_phys_addr = 0xDEAD0000; //! just to be nice, not really needed + } + //return the just detached FrameList (if any) + return head; +} // get_frame_lst + + +/************************************************************************************************************ +* Function put_frame_lst +* +* This function +* +* Returns: address of the first descriptor of the FrameList +* +* Input parameters: +* tx_rx_flag : specifies 'transmit' or 'receive' descriptor. +* +* The following list should be kept in sync with hcf_dma_tx/rx_put, in order to get them in the WCI-spec !!!! +* Assert fails if +* - DMA is not enabled +* - descriptor list is NULL +* - a descriptor in the descriptor list is not double word aligned +* - a count of size field of a descriptor contains control bits, i.e. bits in the high order nibble. +* - the DELWA descriptor is not a "singleton" DescriptorList. +* - the DELWA descriptor is not the first Descriptor supplied +* - a non_DMA descriptor is supplied before the DELWA Descriptor is supplied +* - Possibly more checks could be added !!!!!!!!!!!!! + +*.NOTICE +* The asserts marked with *sc* are really sanity checks for the HCF, they can (supposedly) not be influenced +* by incorrect MSF behavior + + // The MSF is required to supply the HCF with a single descriptor for MSF tx reclaim purposes. + // This 'reclaim descriptor' can be recognized by the fact that its buf_addr field is zero. + ********************************************************************************************* + * Although not required from a hardware perspective: + * - make each descriptor in this rx-chain DMA-owned. + * - Also set the count to zero. EOP and SOP bits are also cleared. + *********************************************************************************************/ +HCF_STATIC void +put_frame_lst( IFBP ifbp, DESC_STRCT *descp, int tx_rx_flag ) +{ + DESC_STRCT *p = descp; + hcf_16 port; + + HCFASSERT( ifbp->IFB_CntlOpt & USE_DMA, ifbp->IFB_CntlOpt) //only hcf_dma_tx_put must also be DMA_ENABLED + HCFASSERT( tx_rx_flag == DMA_RX || tx_rx_flag == DMA_TX, tx_rx_flag ) + HCFASSERT( p , 0 ) + + while ( p ) { + HCFASSERT( ((hcf_32)p & 3 ) == 0, (hcf_32)p ) + HCFASSERT( (p->BUF_CNT & ~DESC_CNT_MASK) == 0, p->BUF_CNT ) + HCFASSERT( (p->BUF_SIZE & ~DESC_CNT_MASK) == 0, p->BUF_SIZE ) + p->BUF_SIZE &= DESC_CNT_MASK; //!!this SHOULD be superfluous in case of correct MSF + p->BUF_CNT &= tx_rx_flag == DMA_RX ? 0 : DESC_CNT_MASK; //!!this SHOULD be superfluous in case of correct MSF + p->BUF_CNT |= DESC_DMA_OWNED; + if ( p->next_desc_addr ) { +// HCFASSERT( p->buf_addr && p->buf_phys_addr && p->BUF_SIZE && +/- p->BUF_SIZE, ... ) + HCFASSERT( p->next_desc_addr->desc_phys_addr, (hcf_32)p->next_desc_addr ) + p->next_desc_phys_addr = p->next_desc_addr->desc_phys_addr; + } else { // + p->next_desc_phys_addr = 0; + if ( p->buf_addr == NULL ) { // DELWA Descriptor + HCFASSERT( descp == p, (hcf_32)descp ) //singleton DescriptorList + HCFASSERT( ifbp->IFB_FirstDesc[tx_rx_flag] == NULL, (hcf_32)ifbp->IFB_FirstDesc[tx_rx_flag]) + HCFASSERT( ifbp->IFB_LastDesc[tx_rx_flag] == NULL, (hcf_32)ifbp->IFB_LastDesc[tx_rx_flag]) + descp->BUF_CNT = 0; //&= ~DESC_DMA_OWNED; + ifbp->IFB_FirstDesc[tx_rx_flag] = descp; +// part of alternative ifbp->IFB_LastDesc[tx_rx_flag] = ifbp->IFB_FirstDesc[tx_rx_flag] = descp; + // if "recycling" a FrameList + // (e.g. called from hcf_cntl( HCF_CNTL_ENABLE ) + // . prepare for activation DMA controller +// part of alternative descp = descp->next_desc_addr; + } else { //a "real" FrameList, hand it over to the DMA engine + HCFASSERT( ifbp->IFB_FirstDesc[tx_rx_flag], (hcf_32)descp ) + HCFASSERT( ifbp->IFB_LastDesc[tx_rx_flag], (hcf_32)descp ) + HCFASSERT( ifbp->IFB_LastDesc[tx_rx_flag]->next_desc_addr == NULL, + (hcf_32)ifbp->IFB_LastDesc[tx_rx_flag]->next_desc_addr) +// p->buf_cntl.cntl_stat |= DESC_DMA_OWNED; + ifbp->IFB_LastDesc[tx_rx_flag]->next_desc_addr = descp; + ifbp->IFB_LastDesc[tx_rx_flag]->next_desc_phys_addr = descp->desc_phys_addr; + port = HREG_RXDMA_PTR32; + if ( tx_rx_flag ) { + p->BUF_SIZE |= DESC_EOP; // p points at the last descriptor in the caller-supplied descriptor chain + descp->BUF_SIZE |= DESC_SOP; + port = HREG_TXDMA_PTR32; + } + OUT_PORT_DWORD( (ifbp->IFB_IOBase + port), descp->desc_phys_addr ); + } + ifbp->IFB_LastDesc[tx_rx_flag] = p; + } + p = p->next_desc_addr; + } +} // put_frame_lst + + +/************************************************************************************************************ +* +*.MODULE DESC_STRCT* hcf_dma_rx_get( IFBP ifbp ) +*.PURPOSE decapsulate a message and provides that message to the MSF. +* reclaim all descriptors in the rx descriptor chain. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* +*.RETURNS +* pointer to a FrameList +* +*.DESCRIPTION +* hcf_dma_rx_get is intended to return a received frame when such a frame is deposited in Host memory by the +* DMA engine. In addition hcf_dma_rx_get can be used to reclaim all descriptors in the rx descriptor chain +* when the DMA Engine is disabled, e.g. as part of a driver unloading strategy. +* hcf_dma_rx_get must be called repeatedly by the MSF when hcf_service_nic signals availability of a rx frame +* through the HREG_EV_RDMAD flag of IFB_DmaPackets. The calling must stop when a NULL pointer is returned, at +* which time the HREG_EV_RDMAD flag is also cleared by the HCF to arm the mechanism for the next frame +* reception. +* Regardless whether the DMA Engine is currently enabled (as controlled via hcf_cntl), if the DMA controller +* deposited an Rx-frame in the Rx-DescriptorList, this frame is detached from the Rx-DescriptorList, +* transformed into a FrameList (i.e. updating the housekeeping fields in the descriptors) and returned to the +* caller. +* If no such Rx-frame is available in the Rx-DescriptorList, the behavior of hcf_dma_rx_get depends on the +* status of the DMA Engine. +* If the DMA Engine is enabled, a NULL pointer is returned. +* If the DMA Engine is disabled, the following strategy is used: +* - the complete Rx-DescriptorList is returned. The DELWA Descriptor is not part of the Rx-DescriptorList. +* - If there is no Rx-DescriptorList, the DELWA Descriptor is returned. +* - If there is no DELWA Descriptor, a NULL pointer is returned. +* +* If the MSF performs an disable/enable sequence without exhausting the Rx-DescriptorList as described above, +* the enable command will reset all house keeping information, i.e. already received but not yet by the MSF +* retrieved frames are lost and the next frame will be received starting with the oldest descriptor. +* +* The HCF can be used in 2 fashions: with and without decapsulation for data transfer. +* This is controlled at compile time by the HCF_ENC bit of the HCF_ENCAP system constant. +* If appropriate, decapsulation is done by moving some data inside the buffers and updating the descriptors +* accordingly. +*!! ;?????where did I describe why a simple manipulation with the count values does not suffice? +* +*.DIAGRAM +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ + +DESC_STRCT* +hcf_dma_rx_get (IFBP ifbp) +{ +DESC_STRCT *descp; // pointer to start of FrameList + + descp = get_frame_lst( ifbp, DMA_RX ); + if ( descp && descp->buf_addr ) //!be aware of the missing curly bracket + + //skip decapsulation at confined descriptor +#if (HCF_ENCAP) == HCF_ENC +#if (HCF_TYPE) & HCF_TYPE_CCX + if ( ifbp->IFB_CKIPStat == HCF_ACT_CCX_OFF ) +#endif // HCF_TYPE_CCX + { +int i; +DESC_STRCT *p = descp->next_desc_addr; //pointer to 2nd descriptor of frame + HCFASSERT(p, 0) + // The 2nd descriptor contains (maybe) a SNAP header plus part or whole of the payload. + //determine decapsulation sub-flag in RxFS + i = *(wci_recordp)&descp->buf_addr[HFS_STAT] & ( HFS_STAT_MSG_TYPE | HFS_STAT_ERR ); + if ( i == HFS_STAT_TUNNEL || + ( i == HFS_STAT_1042 && hcf_encap( (wci_bufp)&p->buf_addr[HCF_DASA_SIZE] ) != ENC_TUNNEL )) { + // The 2nd descriptor contains a SNAP header plus part or whole of the payload. + HCFASSERT( p->BUF_CNT == (p->buf_addr[5] + (p->buf_addr[4]<<8) + 2*6 + 2 - 8), p->BUF_CNT ) + // perform decapsulation + HCFASSERT(p->BUF_SIZE >=8, p->BUF_SIZE) + // move SA[2:5] in the second buffer to replace part of the SNAP header + for ( i=3; i >= 0; i--) p->buf_addr[i+8] = p->buf_addr[i]; + // copy DA[0:5], SA[0:1] from first buffer to second buffer + for ( i=0; i<8; i++) p->buf_addr[i] = descp->buf_addr[HFS_ADDR_DEST + i]; + // make first buffer shorter in count + descp->BUF_CNT = HFS_ADDR_DEST; + } + } +#endif // HCF_ENC + if ( descp == NULL ) ifbp->IFB_DmaPackets &= (hcf_16)~HREG_EV_RDMAD; //;?could be integrated into get_frame_lst + HCFLOGEXIT( HCF_TRACE_DMA_RX_GET ) + return descp; +} // hcf_dma_rx_get + + +/************************************************************************************************************ +* +*.MODULE void hcf_dma_rx_put( IFBP ifbp, DESC_STRCT *descp ) +*.PURPOSE supply buffers for receive purposes. +* supply the Rx-DELWA descriptor. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* descp address of a DescriptorList +* +*.RETURNS N.A. +* +*.DESCRIPTION +* This function is called by the MSF to supply the HCF with new/more buffers for receive purposes. +* The HCF can be used in 2 fashions: with and without encapsulation for data transfer. +* This is controlled at compile time by the HCF_ENC bit of the HCF_ENCAP system constant. +* As a consequence, some additional constaints apply to the number of descriptor and the buffers associated +* with the first 2 descriptors. Independent of the encapsulation feature, the COUNT fields are ignored. +* A special case is the supplying of the DELWA descriptor, which must be supplied as the first descriptor. +* +* Assert fails if +* - ifbp has a recognizable out-of-range value. +* - NIC interrupts are not disabled while required by parameter action. +* - in case decapsulation by the HCF is selected: +* - The first databuffer does not have the exact size corresponding with the RxFS up to the 802.3 DestAddr +* field (== 29 words). +* - The FrameList does not consists of at least 2 Descriptors. +* - The second databuffer does not have the minimum size of 8 bytes. +*!! The 2nd part of the list of asserts should be kept in sync with put_frame_lst, in order to get +*!! them in the WCI-spec !!!! +* - DMA is not enabled +* - descriptor list is NULL +* - a descriptor in the descriptor list is not double word aligned +* - a count of size field of a descriptor contains control bits, i.e. bits in the high order nibble. +* - the DELWA descriptor is not a "singleton" DescriptorList. +* - the DELWA descriptor is not the first Descriptor supplied +* - a non_DMA descriptor is supplied before the DELWA Descriptor is supplied +*!! - Possibly more checks could be added !!!!!!!!!!!!! +* +*.DIAGRAM +* +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +void +hcf_dma_rx_put( IFBP ifbp, DESC_STRCT *descp ) +{ + + HCFLOGENTRY( HCF_TRACE_DMA_RX_PUT, 0xDA01 ) + HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic ) + HCFASSERT_INT + + put_frame_lst( ifbp, descp, DMA_RX ); +#if HCF_ASSERT && (HCF_ENCAP) == HCF_ENC + if ( descp->buf_addr ) { + HCFASSERT( descp->BUF_SIZE == HCF_DMA_RX_BUF1_SIZE, descp->BUF_SIZE ) + HCFASSERT( descp->next_desc_addr, 0 ) // first descriptor should be followed by another descriptor + // The second DB is for SNAP and payload purposes. It should be a minimum of 12 bytes in size. + HCFASSERT( descp->next_desc_addr->BUF_SIZE >= 12, descp->next_desc_addr->BUF_SIZE ) + } +#endif // HCFASSERT / HCF_ENC + HCFLOGEXIT( HCF_TRACE_DMA_RX_PUT ) +} // hcf_dma_rx_put + + +/************************************************************************************************************ +* +*.MODULE DESC_STRCT* hcf_dma_tx_get( IFBP ifbp ) +*.PURPOSE DMA mode: reclaims and decapsulates packets in the tx descriptor chain if: +* - A Tx packet has been copied from host-RAM into NIC-RAM by the DMA engine +* - The Hermes/DMAengine have been disabled +* +*.ARGUMENTS +* ifbp address of the Interface Block +* +*.RETURNS +* pointer to a reclaimed Tx packet. +* +*.DESCRIPTION +* impact of the disable command: +* When a non-empty pool of Tx descriptors exists (created by means of hcf_dma_put_tx), the MSF +* is supposed to empty that pool by means of hcf_dma_tx_get calls after the disable in an +* disable/enable sequence. +* +*.DIAGRAM +* +*.NOTICE +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +DESC_STRCT* +hcf_dma_tx_get( IFBP ifbp ) +{ +DESC_STRCT *descp; // pointer to start of FrameList + + descp = get_frame_lst( ifbp, DMA_TX ); + if ( descp && descp->buf_addr ) //!be aware of the missing curly bracket + //skip decapsulation at confined descriptor +#if (HCF_ENCAP) == HCF_ENC + if ( ( descp->BUF_CNT == HFS_TYPE ) +#if (HCF_TYPE) & HCF_TYPE_CCX + || ( descp->BUF_CNT == HFS_DAT ) +#endif // HCF_TYPE_CCX + ) { // perform decapsulation if needed + descp->next_desc_addr->buf_phys_addr -= HCF_DASA_SIZE; + descp->next_desc_addr->BUF_CNT += HCF_DASA_SIZE; + } +#endif // HCF_ENC + if ( descp == NULL ) { //;?could be integrated into get_frame_lst + ifbp->IFB_DmaPackets &= (hcf_16)~HREG_EV_TDMAD; + } + HCFLOGEXIT( HCF_TRACE_DMA_TX_GET ) + return descp; +} // hcf_dma_tx_get + + +/************************************************************************************************************ +* +*.MODULE void hcf_dma_tx_put( IFBP ifbp, DESC_STRCT *descp, hcf_16 tx_cntl ) +*.PURPOSE puts a packet in the Tx DMA queue in host ram and kicks off the TxDma engine. +* supply the Tx-DELWA descriptor. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* descp address of Tx Descriptor Chain (i.e. a single Tx frame) +* tx_cntl indicates MAC-port and (Hermes) options +* +*.RETURNS N.A. +* +*.DESCRIPTION +* The HCF can be used in 2 fashions: with and without encapsulation for data transfer. +* This is controlled at compile time by the HCF_ENC bit of the HCF_ENCAP system constant. +* +* Regardless of the HCF_ENCAP system constant, the descriptor list created to describe the frame to be +* transmitted, must supply space to contain the 802.11 header, preceding the actual frame to be transmitted. +* Basically, this only supplies working storage to the HCF which passes this on to the DMA engine. +* As a consequence the contents of this space do not matter. +* Nevertheless BUF_CNT must take in account this storage. +* This working space to contain the 802.11 header may not be fragmented, the first buffer must be +* sufficiently large to contain at least the 802.11 header, i.e. HFS_ADDR_DEST (29 words or 0x3A bytes). +* This way, the HCF can simply, regardless whether or not the HCF encapsulates the frame, write the parameter +* tx_cntl at offset 0x36 (HFS_TX_CNTL) in the first buffer. +* Note that it is allowed to have part or all of the actual frame represented by the first descriptor as long +* as the requirement for storage for the 802.11 header is met, i.e. the 802.3 frame starts at offset +* HFS_ADDR_DEST. +* Except for the Assert on the 1st buffer in case of Encapsualtion, the SIZE fields are ignored. +* +* In case the encapsulation feature is compiled in, there are the following additional requirements. +* o The BUF_CNT of the first buffer changes from a minimum of 0x3A bytes to exactly 0x3A, i.e. the workspace +* to store the 802.11 header +* o The BUF_SIZE of the first buffer is at least the space needed to store the +* - 802.11 header (29 words) +* - 802.3 header, i.e. 12 bytes addressing information and 2 bytes length field +* - 6 bytes SNAP-header +* This results in 39 words or 0x4E bytes or HFS_TYPE. +* Note that if the BUF_SIZE is larger than 0x4E, this surplus is not used. +* o The actual frame begins in the 2nd descriptor (which is already implied by the BUF_CNT == 0x3A requirement) and the associated buffer contains at least the 802.3 header, i.e. the 14 bytes representing addressing information and length/type field +* +* When the HCF does not encapsulates (i.e. length/type field <= 1500), no changes are made to descriptors +* or buffers. +* +* When the HCF actually encapsulates (i.e. length/type field > 1500), it successively writes, starting at +* offset HFS_ADDR_DEST (0x3A) in the first buffer: +* - the 802.3 addressing information, copied from the begin of the second buffer +* - the frame length, derived from the total length of the individual fragments, corrected for the SNAP +* header length and Type field and ignoring the Destination Address, Source Address and Length field +* - the appropriate snap header (Tunnel or 1042, depending on the value of the type field). +* +* The information in the first two descriptors is adjusted accordingly: +* - the first descriptor count is changed from 0x3A to 0x4E (HFS_TYPE), which matches 0x3A + 12 + 2 + 6 +* - the second descriptor count is decreased by 12, being the moved addressing information +* - the second descriptor (physical) buffer address is increased by 12. +* +* When the descriptors are returned by hcf_dma_tx_get, the transformation of the first two descriptors is +* undone. +* +* Under any of the above scenarios, the assert BUF_CNT <= BUF_SIZE must be true for all descriptors +* In case of encapsulation, BUF_SIZE of the 1st descriptor is asserted to be at least HFS_TYPE (0x4E), so it is NOT tested. +* +* Assert fails if +* - ifbp has a recognizable out-of-range value. +* - tx_cntl has a recognizable out-of-range value. +* - NIC interrupts are not disabled while required by parameter action. +* - in case encapsulation by the HCF is selected: +* - The FrameList does not consists of at least 2 Descriptors. +* - The first databuffer does not contain exactly the (space for) the 802.11 header (== 28 words) +* - The first databuffer does not have a size to additionally accomodate the 802.3 header and the +* SNAP header of the frame after encapsulation (== 39 words). +* - The second databuffer does not contain at least DA, SA and 'type/length' (==14 bytes or 7 words) +*!! The 2nd part of the list of asserts should be kept in sync with put_frame_lst, in order to get +*!! them in the WCI-spec !!!! +* - DMA is not enabled +* - descriptor list is NULL +* - a descriptor in the descriptor list is not double word aligned +* - a count of size field of a descriptor contains control bits, i.e. bits in the high order nibble. +* - the DELWA descriptor is not a "singleton" DescriptorList. +* - the DELWA descriptor is not the first Descriptor supplied +* - a non_DMA descriptor is supplied before the DELWA Descriptor is supplied +*!! - Possibly more checks could be added !!!!!!!!!!!!! +*.DIAGRAM +* +*.NOTICE +* +*.ENDDOC END DOCUMENTATION +* +* +*1: Write tx_cntl parameter to HFS_TX_CNTL field into the Hermes-specific header in buffer 1 +*4: determine whether encapsulation is needed and write the type (tunnel or 1042) already at the appropriate +* offset in the 1st buffer +*6: Build the encapsualtion enveloppe in the free space at the end of the 1st buffer +* - Copy DA/SA fields from the 2nd buffer +* - Calculate total length of the message (snap-header + type-field + the length of all buffer fragments +* associated with the 802.3 frame (i.e all descriptors except the first), but not the DestinationAddress, +* SourceAddress and lenght-field) +* Assert the message length +* Write length. Note that the message is in BE format, hence on LE platforms the length must be converted +* ;? THIS IS NOT WHAT CURRENTLY IS IMPLEMENTED +* - Write snap header. Note that the last byte of the snap header is NOT copied, that byte is already in +* place as result of the call to hcf_encap. +* Note that there are many ways to skin a cat. To express the offsets in the 1st buffer while writing +* the snap header, HFS_TYPE is choosen as a reference point to make it easier to grasp that the snap header +* and encapsualtion type are at least relative in the right. +*8: modify 1st descriptor to reflect moved part of the 802.3 header + Snap-header +* modify 2nd descriptor to skip the moved part of the 802.3 header (DA/SA +*10: set each descriptor to 'DMA owned', clear all other control bits. +* Set SOP bit on first descriptor. Set EOP bit on last descriptor. +*12: Either append the current frame to an existing descriptor list or +*14: create a list beginning with the current frame +*16: remember the new end of the list +*20: hand the frame over to the DMA engine +************************************************************************************************************/ +void +hcf_dma_tx_put( IFBP ifbp, DESC_STRCT *descp, hcf_16 tx_cntl ) +{ +DESC_STRCT *p = descp->next_desc_addr; +int i; + +#if HCF_ASSERT + int x = ifbp->IFB_FWIdentity.comp_id == COMP_ID_FW_AP ? tx_cntl & ~HFS_TX_CNTL_PORT : tx_cntl; + HCFASSERT( (x & ~HCF_TX_CNTL_MASK ) == 0, tx_cntl ) +#endif // HCF_ASSERT + HCFLOGENTRY( HCF_TRACE_DMA_TX_PUT, 0xDA03 ) + HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic ) + HCFASSERT_INT + HCFASSERT( ( ifbp->IFB_CntlOpt & (USE_DMA|DMA_ENABLED) ) == (USE_DMA|DMA_ENABLED), ifbp->IFB_CntlOpt) + + if ( descp->buf_addr ) { + *(hcf_16*)(descp->buf_addr + HFS_TX_CNTL) = tx_cntl; /*1*/ +#if (HCF_ENCAP) == HCF_ENC + HCFASSERT( descp->next_desc_addr, 0 ) //at least 2 descripors + HCFASSERT( descp->BUF_CNT == HFS_ADDR_DEST, descp->BUF_CNT ) //exact length required for 1st buffer + HCFASSERT( descp->BUF_SIZE >= HCF_DMA_TX_BUF1_SIZE, descp->BUF_SIZE ) //minimal storage for encapsulation + HCFASSERT( p->BUF_CNT >= 14, p->BUF_CNT ); //at least DA, SA and 'type' in 2nd buffer + +#if (HCF_TYPE) & HCF_TYPE_CCX + /* if we are doing PPK +/- CMIC, or we are sending a DDP frame */ + if ( ( ifbp->IFB_CKIPStat == HCF_ACT_CCX_ON ) || + ( ( p->BUF_CNT >= 20 ) && ( ifbp->IFB_CKIPStat == HCF_ACT_CCX_OFF ) && + ( p->buf_addr[12] == 0xAA ) && ( p->buf_addr[13] == 0xAA ) && + ( p->buf_addr[14] == 0x03 ) && ( p->buf_addr[15] == 0x00 ) && + ( p->buf_addr[16] == 0x40 ) && ( p->buf_addr[17] == 0x96 ) && + ( p->buf_addr[18] == 0x00 ) && ( p->buf_addr[19] == 0x00 ))) + { + /* copy the DA/SA to the first buffer */ + for ( i = 0; i < HCF_DASA_SIZE; i++ ) { + descp->buf_addr[i + HFS_ADDR_DEST] = p->buf_addr[i]; + } + /* calculate the length of the second fragment only */ + i = 0; + do { i += p->BUF_CNT; } while( p = p->next_desc_addr ); + i -= HCF_DASA_SIZE ; + /* convert the length field to big endian, using the endian friendly macros */ + i = CNV_SHORT_TO_BIG(i); //!! this converts ONLY on LE platforms, how does that relate to the non-CCX code + *(hcf_16*)(&descp->buf_addr[HFS_LEN]) = (hcf_16)i; + descp->BUF_CNT = HFS_DAT; + // modify 2nd descriptor to skip the 'Da/Sa' fields + descp->next_desc_addr->buf_phys_addr += HCF_DASA_SIZE; + descp->next_desc_addr->BUF_CNT -= HCF_DASA_SIZE; + } + else +#endif // HCF_TYPE_CCX + { + descp->buf_addr[HFS_TYPE-1] = hcf_encap(&descp->next_desc_addr->buf_addr[HCF_DASA_SIZE]); /*4*/ + if ( descp->buf_addr[HFS_TYPE-1] != ENC_NONE ) { + for ( i=0; i < HCF_DASA_SIZE; i++ ) { /*6*/ + descp->buf_addr[i + HFS_ADDR_DEST] = descp->next_desc_addr->buf_addr[i]; + } + i = sizeof(snap_header) + 2 - ( 2*6 + 2 ); + do { i += p->BUF_CNT; } while ( ( p = p->next_desc_addr ) != NULL ); + *(hcf_16*)(&descp->buf_addr[HFS_LEN]) = CNV_END_SHORT(i); //!! this converts on ALL platforms, how does that relate to the CCX code + for ( i=0; i < sizeof(snap_header) - 1; i++) { + descp->buf_addr[HFS_TYPE - sizeof(snap_header) + i] = snap_header[i]; + } + descp->BUF_CNT = HFS_TYPE; /*8*/ + descp->next_desc_addr->buf_phys_addr += HCF_DASA_SIZE; + descp->next_desc_addr->BUF_CNT -= HCF_DASA_SIZE; + } + } +#endif // HCF_ENC + } + put_frame_lst( ifbp, descp, DMA_TX ); + HCFLOGEXIT( HCF_TRACE_DMA_TX_PUT ) +} // hcf_dma_tx_put + +#endif // HCF_DMA + +#if (HCF_DL_ONLY) == 0 +/************************************************************************************************************ +* +*.MODULE hcf_8 hcf_encap( wci_bufp type ) +*.PURPOSE test whether RFC1042 or Bridge-Tunnel encapsulation is needed. +* +*.ARGUMENTS +* type (Far) pointer to the (Big Endian) Type/Length field in the message +* +*.RETURNS +* ENC_NONE len/type is "len" ( (BIG_ENDIAN)type <= 1500 ) +* ENC_TUNNEL len/type is "type" and 0x80F3 or 0x8137 +* ENC_1042 len/type is "type" but not 0x80F3 or 0x8137 +* +*.CONDITIONS +* NIC Interrupts d.c +* +*.DESCRIPTION +* Type must point to the Len/Type field of the message, this is the 2-byte field immediately after the 6 byte +* Destination Address and 6 byte Source Address. The 2 successive bytes addressed by type are interpreted as +* a Big Endian value. If that value is less than or equal to 1500, the message is assumed to be in 802.3 +* format. Otherwise the message is assumed to be in Ethernet-II format. Depending on the value of Len/Typ, +* Bridge Tunnel or RFC1042 encapsulation is needed. +* +*.DIAGRAM +* +* 1: presume 802.3, hence preset return value at ENC_NONE +* 2: convert type from "network" Endian format to native Endian +* 4: the litmus test to distinguish type and len. +* The hard code "magic" value of 1500 is intentional and should NOT be replaced by a mnemonic because it is +* not related at all to the maximum frame size supported by the Hermes. +* 6: check type against: +* 0x80F3 //AppleTalk Address Resolution Protocol (AARP) +* 0x8137 //IPX +* to determine the type of encapsulation +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +#if HCF_ENCAP //i.e HCF_ENC or HCF_ENC_SUP +#if ! ( (HCF_ENCAP) & HCF_ENC_SUP ) +HCF_STATIC +#endif // HCF_ENCAP +hcf_8 +hcf_encap( wci_bufp type ) +{ + +hcf_8 rc = ENC_NONE; /* 1 */ +hcf_16 t = (hcf_16)(*type<<8) + *(type+1); /* 2 */ + + if ( t > 1500 ) { /* 4 */ + if ( t == 0x8137 || t == 0x80F3 ) { + rc = ENC_TUNNEL; /* 6 */ + } else { + rc = ENC_1042; + } + } + return rc; +} // hcf_encap +#endif // HCF_ENCAP +#endif // HCF_DL_ONLY + + +/************************************************************************************************************ +* +*.MODULE int hcf_get_info( IFBP ifbp, LTVP ltvp ) +*.PURPOSE Obtains transient and persistent configuration information from the Card and from the HCF. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* ltvp address of LengthTypeValue structure specifying the "what" and the "how much" of the +* information to be collected from the HCF or from the Hermes +* +*.RETURNS +* HCF_ERR_LEN The provided buffer was too small +* HCF_SUCCESS Success +*!! via cmd_exe ( type >= CFG_RID_FW_MIN ) +* HCF_ERR_NO_NIC NIC removed during retrieval +* HCF_ERR_TIME_OUT Expected Hermes event did not occure in expected time +*!! via cmd_exe and setup_bap (type >= CFG_RID_FW_MIN ) +* HCF_ERR_DEFUNCT_... HCF is in defunct mode (bits 0x7F reflect cause) +* +*.DESCRIPTION +* The T-field of the LTV-record (provided by the MSF in parameter ltvp) specifies the RID wanted. The RID +* information identified by the T-field is copied into the V-field. +* On entry, the L-field specifies the size of the buffer, also called the "Initial DataLength". The L-value +* includes the size of the T-field, but not the size of the L-field itself. +* On return, the L-field indicates the number of words actually contained by the Type and Value fields. +* As the size of the Type field in the LTV-record is included in the "Initial DataLength" of the record, the +* V-field can contain at most "Initial DataLength" - 1 words of data. +* Copying stops if either the complete Information is copied or if the number of words indicated by the +* "Initial DataLength" were copied. The "Initial DataLength" acts as a safe guard against Configuration +* Information blocks that have different sizes for different F/W versions, e.g. when later versions support +* more tallies than earlier versions. +* If the size of Value field of the RID exceeds the size of the "Initial DataLength" -1, as much data +* as fits is copied, and an error status of HCF_ERR_LEN is returned. +* +* It is the responsibility of the MSF to detect card removal and re-insertion and not call the HCF when the +* NIC is absent. The MSF cannot, however, timely detect a Card removal if the Card is removed while +* hcf_get_info is in progress. Therefore, the HCF performs its own check on Card presence after the read +* operation of the NIC data. If the Card is not present or removed during the execution of hcf_get_info, +* HCF_ERR_NO_NIC is returned and the content of the Data Buffer is unpredictable. This check is not performed +* in case of the "HCF embedded" pseudo RIDs like CFG_TALLIES. +* +* Assert fails if +* - ifbp has a recognizable out-of-range value. +* - reentrancy, may be caused by calling hcf_functions without adequate protection +* against NIC interrupts or multi-threading. +* - ltvp is a NULL pointer. +* - length field of the LTV-record at entry is 0 or 1 or has an excessive value (i.e. exceeds HCF_MAX_LTV). +* - type field of the LTV-record is invalid. +* +*.DIAGRAM +* Hcf_get_mb_info copies the contents of the oldest MailBox Info block in the MailBox to PC RAM. If len is +* less than the size of the MailBox Info block, only as much as fits in the PC RAM buffer is copied. After +* the copying the MailBox Read pointer is updated to point to the next MailBox Info block, hence the +* remainder of an "oversized" MailBox Info block is lost. The truncation of the MailBox Info block is NOT +* reflected in the return status. Note that hcf_get_info guarantees the length of the PC RAM buffer meets +* the minimum requirements of at least 2, so no PC RAM buffer overrun. +* +* Calling hcf_get_mb_info when their is no MailBox Info block available or when there is no MailBox at all, +* results in a "NULL" MailBox Info block. +* +*12: see NOTICE +*17: The return status of cmd_wait and the first hcfio_in_string can be ignored, because when one fails, the +* other fails via the IFB_DefunctStat mechanism +*20: "HCFASSERT( rc == HCF_SUCCESS, rc )" is not suitable because this will always trigger as side effect of +* the HCFASSERT in hcf_put_info which calls hcf_get_info to figure out whether the RID exists at all. + +*.NOTICE +* +* "HCF embedded" pseudo RIDs: +* CFG_MB_INFO, CFG_TALLIES, CFG_DRV_IDENTITY, CFG_DRV_SUP_RANGE, CFG_DRV_ACT_RANGES_PRI, +* CFG_DRV_ACT_RANGES_STA, CFG_DRV_ACT_RANGES_HSI +* Note the HCF_ERR_LEN is NOT adequately set, when L >= 2 but less than needed +* +* Remarks: Transfers operation information and transient and persistent configuration information from the +* Card and from the HCF to the MSF. +* The exact layout of the provided data structure depends on the action code. Copying stops if either the +* complete Configuration Information is copied or if the number of bytes indicated by len is copied. Len +* acts as a safe guard against Configuration Information blocks which have different sizes for different +* Hermes versions, e.g. when later versions support more tallies than earlier versions. It is a conscious +* decision that unused parts of the PC RAM buffer are not cleared. +* +* Remarks: The only error against which is protected is the "Read error" as result of Card removal. Only the +* last hcf_io_string need to be protected because if the first fails the second will fail as well. Checking +* for cmd_exe errors is supposed superfluous because problems in cmd_exe are already caught or will be +* caught by hcf_enable. +* +* CFG_MB_INFO: copy the oldest MailBox Info Block or the "null" block if none available. +* +* The mechanism to HCF_ASSERT on invalid typ-codes in the LTV record is based on the following strategy: +* - during the pseudo-asynchronous Hermes commands (diagnose, download) only CFG_MB_INFO is acceptable +* - some codes (e.g. CFG_TALLIES) are explicitly handled by the HCF which implies that these codes +* are valid +* - all other codes in the range 0xFC00 through 0xFFFF are passed to the Hermes. The Hermes returns an +* LTV record with a zero value in the L-field for all Typ-codes it does not recognize. This is +* defined and intended behavior, so HCF_ASSERT does not catch on this phenomena. +* - all remaining codes are invalid and cause an ASSERT. +* +*.CONDITIONS +* In case of USB, HCF_MAX_MSG ;?USED;? to limit the amount of data that can be retrieved via hcf_get_info. +* +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +int +hcf_get_info( IFBP ifbp, LTVP ltvp ) +{ + +int rc = HCF_SUCCESS; +hcf_16 len = ltvp->len; +hcf_16 type = ltvp->typ; +wci_recordp p = <vp->len; //destination word pointer (in LTV record) +hcf_16 *q = NULL; /* source word pointer Note!! DOS COM can't cope with FAR + * as a consequence MailBox must be near which is usually true anyway + */ +int i; + + HCFLOGENTRY( HCF_TRACE_GET_INFO, ltvp->typ ) + HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic ) + HCFASSERT_INT + HCFASSERT( ltvp, 0 ) + HCFASSERT( 1 < ltvp->len && ltvp->len <= HCF_MAX_LTV + 1, MERGE_2( ltvp->typ, ltvp->len ) ) + + ltvp->len = 0; //default to: No Info Available +#if defined MSF_COMPONENT_ID || (HCF_EXT) & HCF_EXT_MB //filter out all specials + for ( i = 0; ( q = xxxx[i] ) != NULL && q[1] != type; i++ ) /*NOP*/; +#endif // MSF_COMPONENT_ID / HCF_EXT_MB +#if HCF_TALLIES + if ( type == CFG_TALLIES ) { /*3*/ + (void)hcf_action( ifbp, HCF_ACT_TALLIES ); + q = (hcf_16*)&ifbp->IFB_TallyLen; + } +#endif // HCF_TALLIES +#if (HCF_EXT) & HCF_EXT_MB + if ( type == CFG_MB_INFO ) { + if ( ifbp->IFB_MBInfoLen ) { + if ( ifbp->IFB_MBp[ifbp->IFB_MBRp] == 0xFFFF ) { + ifbp->IFB_MBRp = 0; //;?Probably superfluous + } + q = &ifbp->IFB_MBp[ifbp->IFB_MBRp]; + ifbp->IFB_MBRp += *q + 1; //update read pointer + if ( ifbp->IFB_MBp[ifbp->IFB_MBRp] == 0xFFFF ) { + ifbp->IFB_MBRp = 0; + } + ifbp->IFB_MBInfoLen = ifbp->IFB_MBp[ifbp->IFB_MBRp]; + } + } +#endif // HCF_EXT_MB + if ( q != NULL ) { //a special or CFG_TALLIES or CFG_MB_INFO + i = min( len, *q ) + 1; //total size of destination (including T-field) + while ( i-- ) { + *p++ = *q; +#if (HCF_TALLIES) & HCF_TALLIES_RESET + if ( q > &ifbp->IFB_TallyTyp && type == CFG_TALLIES ) { + *q = 0; + } +#endif // HCF_TALLIES_RESET + q++; + } + } else { // not a special nor CFG_TALLIES nor CFG_MB_INFO + if ( type == CFG_CNTL_OPT ) { //read back effective options + ltvp->len = 2; + ltvp->val[0] = ifbp->IFB_CntlOpt; +#if (HCF_EXT) & HCF_EXT_NIC_ACCESS + } else if ( type == CFG_PROD_DATA ) { //only needed for some test tool on top of H-II NDIS driver +hcf_io io_port; +wci_bufp pt; //pointer with the "right" type, just to help ease writing macros with embedded assembly + OPW( HREG_AUX_PAGE, (hcf_16)(PLUG_DATA_OFFSET >> 7) ); + OPW( HREG_AUX_OFFSET, (hcf_16)(PLUG_DATA_OFFSET & 0x7E) ); + io_port = ifbp->IFB_IOBase + HREG_AUX_DATA; //to prevent side effects of the MSF-defined macro + p = ltvp->val; //destination char pointer (in LTV record) + if ( ( i = len - 1 ) > 0 ) { + pt = (wci_bufp)p; //just to help ease writing macros with embedded assembly + IN_PORT_STRING_8_16( io_port, pt, i ); //space used by T: -1 + } + } else if ( type == CFG_CMD_HCF ) { +#define P ((CFG_CMD_HCF_STRCT FAR *)ltvp) + HCFASSERT( P->cmd == CFG_CMD_HCF_REG_ACCESS, P->cmd ) //only Hermes register access supported + if ( P->cmd == CFG_CMD_HCF_REG_ACCESS ) { + HCFASSERT( P->mode < ifbp->IFB_IOBase, P->mode ) //Check Register space + ltvp->len = min( len, 4 ); //RESTORE ltv length + P->add_info = IPW( P->mode ); + } +#undef P +#endif // HCF_EXT_NIC_ACCESS +#if (HCF_ASSERT) & HCF_ASSERT_PRINTF + } else if (type == CFG_FW_PRINTF) { + rc = fw_printf(ifbp, (CFG_FW_PRINTF_STRCT*)ltvp); +#endif // HCF_ASSERT_PRINTF + } else if ( type >= CFG_RID_FW_MIN ) { +//;? by using HCMD_BUSY option when calling cmd_exe, using a get_frag with length 0 just to set up the +//;? BAP and calling cmd_cmpl, you could merge the 2 Busy waits. Whether this really helps (and what +//;? would be the optimal sequence in cmd_exe and get_frag) would have to be MEASURED +/*17*/ if ( ( rc = cmd_exe( ifbp, HCMD_ACCESS, type ) ) == HCF_SUCCESS && + ( rc = setup_bap( ifbp, type, 0, IO_IN ) ) == HCF_SUCCESS ) { + get_frag( ifbp, (wci_bufp)<vp->len, 2*len+2 BE_PAR(2) ); + if ( IPW( HREG_STAT ) == 0xFFFF ) { //NIC removal test + ltvp->len = 0; + HCFASSERT( DO_ASSERT, type ) + } + } +/*12*/ } else HCFASSERT( DO_ASSERT, type ) /*NOP*/; //NOP in case HCFASSERT is dummy + } + if ( len < ltvp->len ) { + ltvp->len = len; + if ( rc == HCF_SUCCESS ) { + rc = HCF_ERR_LEN; + } + } + HCFASSERT( rc == HCF_SUCCESS || ( rc == HCF_ERR_LEN && ifbp->IFB_AssertTrace & 1<typ ) + HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic ) + HCFASSERT_INT + HCFASSERT( ltvp, 0 ) + HCFASSERT( 1 < ltvp->len && ltvp->len <= HCF_MAX_LTV + 1, ltvp->len ) + + //all codes between 0xFA00 and 0xFCFF are passed to Hermes +#if (HCF_TYPE) & HCF_TYPE_WPA + { hcf_16 i; + hcf_32 FAR * key_p; + + if ( ltvp->typ == CFG_ADD_TKIP_DEFAULT_KEY || ltvp->typ == CFG_ADD_TKIP_MAPPED_KEY ) { + key_p = (hcf_32*)((CFG_ADD_TKIP_MAPPED_KEY_STRCT FAR *)ltvp)->tx_mic_key; + i = TX_KEY; //i.e. TxKeyIndicator == 1, KeyID == 0 + if ( ltvp->typ == CFG_ADD_TKIP_DEFAULT_KEY ) { + key_p = (hcf_32*)((CFG_ADD_TKIP_DEFAULT_KEY_STRCT FAR *)ltvp)->tx_mic_key; + i = CNV_LITTLE_TO_SHORT(((CFG_ADD_TKIP_DEFAULT_KEY_STRCT FAR *)ltvp)->tkip_key_id_info); + } + if ( i & TX_KEY ) { /* TxKeyIndicator == 1 + (either really set by MSF in case of DEFAULT or faked by HCF in case of MAPPED ) */ + ifbp->IFB_MICTxCntl = (hcf_16)( HFS_TX_CNTL_MIC | (i & KEY_ID )<<8 ); + ifbp->IFB_MICTxKey[0] = CNV_LONGP_TO_LITTLE( key_p ); + ifbp->IFB_MICTxKey[1] = CNV_LONGP_TO_LITTLE( (key_p+1) ); + } + i = ( i & KEY_ID ) * 2; + ifbp->IFB_MICRxKey[i] = CNV_LONGP_TO_LITTLE( (key_p+2) ); + ifbp->IFB_MICRxKey[i+1] = CNV_LONGP_TO_LITTLE( (key_p+3) ); + } +#define P ((CFG_REMOVE_TKIP_DEFAULT_KEY_STRCT FAR *)ltvp) + if ( ( ltvp->typ == CFG_REMOVE_TKIP_MAPPED_KEY ) || + ( ltvp->typ == CFG_REMOVE_TKIP_DEFAULT_KEY && + ( (ifbp->IFB_MICTxCntl >> 8) & KEY_ID ) == CNV_SHORT_TO_LITTLE(P->tkip_key_id ) + ) + ) { ifbp->IFB_MICTxCntl = 0; } //disable MIC-engine +#undef P + } +#endif // HCF_TYPE_WPA + + if ( ltvp->typ == CFG_PROG ) { + rc = download( ifbp, (CFG_PROG_STRCT FAR *)ltvp ); + } else switch (ltvp->typ) { +#if (HCF_ASSERT) & HCF_ASSERT_RT_MSF_RTN + case CFG_REG_ASSERT_RTNP: //Register MSF Routines +#define P ((CFG_REG_ASSERT_RTNP_STRCT FAR *)ltvp) + ifbp->IFB_AssertRtn = P->rtnp; +// ifbp->IFB_AssertLvl = P->lvl; //TODO not yet supported so default is set in hcf_connect + HCFASSERT( DO_ASSERT, MERGE_2( HCF_ASSERT, 0xCAF1 ) ) //just to proof that the complete assert machinery is working +#undef P + break; +#endif // HCF_ASSERT_RT_MSF_RTN +#if (HCF_EXT) & HCF_EXT_INFO_LOG + case CFG_REG_INFO_LOG: //Register Log filter + ifbp->IFB_RIDLogp = ((CFG_RID_LOG_STRCT FAR*)ltvp)->recordp; + break; +#endif // HCF_EXT_INFO_LOG + case CFG_CNTL_OPT: //overrule option + HCFASSERT( ( ltvp->val[0] & ~(USE_DMA | USE_16BIT) ) == 0, ltvp->val[0] ) + if ( ( ltvp->val[0] & USE_DMA ) == 0 ) ifbp->IFB_CntlOpt &= ~USE_DMA; + ifbp->IFB_CntlOpt |= ltvp->val[0] & USE_16BIT; + break; +#if (HCF_EXT) & HCF_EXT_MB + case CFG_REG_MB: //Register MailBox +#define P ((CFG_REG_MB_STRCT FAR *)ltvp) + HCFASSERT( ( (hcf_32)P->mb_addr & 0x0001 ) == 0, (hcf_32)P->mb_addr ) + HCFASSERT( (P)->mb_size >= 60, (P)->mb_size ) + ifbp->IFB_MBp = P->mb_addr; + /* if no MB present, size must be 0 for ;?the old;? put_info_mb to work correctly */ + ifbp->IFB_MBSize = ifbp->IFB_MBp == NULL ? 0 : P->mb_size; + ifbp->IFB_MBWp = ifbp->IFB_MBRp = 0; + ifbp->IFB_MBp[0] = 0; //flag the MailBox as empty + ifbp->IFB_MBInfoLen = 0; + HCFASSERT( ifbp->IFB_MBSize >= 60 || ifbp->IFB_MBp == NULL, ifbp->IFB_MBSize ) +#undef P + break; + case CFG_MB_INFO: //store MailBoxInfoBlock + rc = put_info_mb( ifbp, (CFG_MB_INFO_STRCT FAR *)ltvp ); + break; +#endif // HCF_EXT_MB + +#if (HCF_EXT) & HCF_EXT_NIC_ACCESS + case CFG_CMD_NIC: +#define P ((CFG_CMD_NIC_STRCT FAR *)ltvp) + OPW( HREG_PARAM_2, P->parm2 ); + OPW( HREG_PARAM_1, P->parm1 ); + rc = cmd_exe( ifbp, P->cmd, P->parm0 ); + P->hcf_stat = (hcf_16)rc; + P->stat = IPW( HREG_STAT ); + P->resp0 = IPW( HREG_RESP_0 ); + P->resp1 = IPW( HREG_RESP_1 ); + P->resp2 = IPW( HREG_RESP_2 ); + P->ifb_err_cmd = ifbp->IFB_ErrCmd; + P->ifb_err_qualifier = ifbp->IFB_ErrQualifier; +#undef P + break; + case CFG_CMD_HCF: +#define P ((CFG_CMD_HCF_STRCT FAR *)ltvp) + HCFASSERT( P->cmd == CFG_CMD_HCF_REG_ACCESS, P->cmd ) //only Hermes register access supported + if ( P->cmd == CFG_CMD_HCF_REG_ACCESS ) { + HCFASSERT( P->mode < ifbp->IFB_IOBase, P->mode ) //Check Register space + OPW( P->mode, P->add_info); + } +#undef P + break; +#endif // HCF_EXT_NIC_ACCESS + +#if (HCF_ASSERT) & HCF_ASSERT_PRINTF + case CFG_FW_PRINTF_BUFFER_LOCATION: + ifbp->IFB_FwPfBuff = *(CFG_FW_PRINTF_BUFFER_LOCATION_STRCT*)ltvp; + break; +#endif // HCF_ASSERT_PRINTF + + default: //pass everything unknown above the "FID" range to the Hermes or Dongle + rc = put_info( ifbp, ltvp ); + } + //DO NOT !!! HCFASSERT( rc == HCF_SUCCESS, rc ) /* 20 */ + HCFLOGEXIT( HCF_TRACE_PUT_INFO ) + return rc; +} // hcf_put_info + + +#if (HCF_DL_ONLY) == 0 +/************************************************************************************************************ +* +*.MODULE int hcf_rcv_msg( IFBP ifbp, DESC_STRCT *descp, unsigned int offset ) +*.PURPOSE All: decapsulate a message. +* pre-HermesII.5: verify MIC. +* non-USB, non-DMA mode: Transfer a message from the NIC to the Host and acknowledge reception. +* USB: Transform a message from proprietary USB format to 802.3 format +* +*.ARGUMENTS +* ifbp address of the Interface Block +* descp Pointer to the Descriptor List location. +* offset USB: not used +* non-USB: specifies the beginning of the data to be obtained (0 corresponds with DestAddr field +* of frame). +* +*.RETURNS +* HCF_SUCCESS No SSN error ( or HCF_ERR_MIC already reported by hcf_service_nic) +* HCF_ERR_MIC message contains an erroneous MIC ( HCF_SUCCESS is reported if HCF_ERR_MIC is already +* reported by hcf_service_nic) +* HCF_ERR_NO_NIC NIC removed during data retrieval +* HCF_ERR_DEFUNCT... +* +*.DESCRIPTION +* The Receive Message Function can be executed by the MSF to obtain the Data Info fields of the message that +* is reported to be available by the Service NIC Function. +* +* The Receive Message Function copies the message data available in the Card memory into a buffer structure +* provided by the MSF. +* Only data of the message indicated by the Service NIC Function can be obtained. +* Execution of the Service NIC function may result in the availability of a new message, but it definitely +* makes the message reported by the preceding Service NIC function, unavailable. +* +* in non-USB/non-DMA mode, hcf_rcv_msg starts the copy process at the (non-negative) offset requested by the +* parameter offset, relative to HFS_ADDR_DEST, e.g offset 0 starts copying from the Destination Address, the +* very begin of the 802.3 frame message. Offset must either lay within the part of the 802.3 frame as stored +* by hcf_service_nic in the lookahead buffer or be just behind it, i.e. the first byte not yet read. +* When offset is within lookahead, data is copied from lookahead. +* When offset is beyond lookahead, data is read directly from RxFS in NIC with disregard of the actual value +* of offset +* +*.NOTICE: +* o at entry: look ahead buffer as passed with hcf_service_nic is still accessible and unchanged +* o at exit: Receive Frame in NIC memory is released +* +* Description: +* Starting at the byte indicated by the Offset value, the bytes are copied from the Data Info +* Part of the current Receive Frame Structure to the Host memory data buffer structure +* identified by descp. +* The maximum value for Offset is the number of characters of the 802.3 frame read into the +* look ahead buffer by hcf_service_nic (i.e. the look ahead buffer size minus +* Control and 802.11 fields) +* If Offset is less than the maximum value, copying starts from the look ahead buffer till the +* end of that buffer is reached +* Then (or if the maximum value is specified for Offset), the +* message is directly copied from NIC memory to Host memory. +* If an invalid (i.e. too large) offset is specified, an assert catches but the buffer contents are +* undefined. +* Copying stops if either: +* o the end of the 802.3 frame is reached +* o the Descriptor with a NULL pointer in the next_desc_addr field is reached +* +* When the copying stops, the receiver is ack'ed, thus freeing the NIC memory where the frame is stored +* As a consequence, hcf_rcv_msg can only be called once for any particular Rx frame. +* +* For the time being (PCI Bus mastering not yet supported), only the following fields of each +* of the descriptors in the descriptor list must be set by the MSF: +* o buf_cntl.buf_dim[1] +* o *next_desc_addr +* o *buf_addr +* At return from hcf_rcv_msg, the field buf_cntl.buf_dim[0] of the used Descriptors reflects +* the number of bytes in the buffer corresponding with the Descriptor. +* On the last used Descriptor, buf_cntl.buf_dim[0] is less or equal to buf_cntl.buf_dim[1]. +* On all preceding Descriptors buf_cntl.buf_dim[0] is equal to buf_cntl.buf_dim[1]. +* On all succeeding (unused) Descriptors, buf_cntl.buf_dim[0] is zero. +* Note: this I/F is based on the assumptions how the I/F needed for PCI Bus mastering will +* be, so it may change. +* +* The most likely handling of HCF_ERR_NO_NIC by the MSF is to drop the already copied +* data as elegantly as possible under the constraints and requirements posed by the (N)OS. +* If no received Frame Structure is pending, "Success" rather than "Read error" is returned. +* This error constitutes a logic flaw in the MSF +* The HCF can only catch a minority of this +* type of errors +* Based on consistency ideas, the HCF catches none of these errors. +* +* Assert fails if +* - ifbp has a recognizable out-of-range value +* - there is no unacknowledged Rx-message available +* - offset is out of range (outside look ahead buffer) +* - descp is a NULL pointer +* - any of the descriptors is not double word aligned +* - reentrancy, may be caused by calling hcf_functions without adequate protection +* against NIC interrupts or multi-threading. +* - Interrupts are enabled. +* +*.DIAGRAM +* +*.NOTICE +* - by using unsigned int as type for offset, no need to worry about negative offsets +* - Asserting on being enabled/present is superfluous, since a non-zero IFB_lal implies that hcf_service_nic +* was called and detected a Rx-message. A zero IFB_lal will set the BUF_CNT field of at least the first +* descriptor to zero. +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +int +hcf_rcv_msg( IFBP ifbp, DESC_STRCT *descp, unsigned int offset ) +{ +int rc = HCF_SUCCESS; +wci_bufp cp; //char oriented working pointer +hcf_16 i; +int tot_len = ifbp->IFB_RxLen - offset; //total length +wci_bufp lap = ifbp->IFB_lap + offset; //start address in LookAhead Buffer +hcf_16 lal = ifbp->IFB_lal - offset; //available data within LookAhead Buffer +hcf_16 j; + + HCFLOGENTRY( HCF_TRACE_RCV_MSG, offset ) + HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic ) + HCFASSERT_INT + HCFASSERT( descp, HCF_TRACE_RCV_MSG ) + HCFASSERT( ifbp->IFB_RxLen, HCF_TRACE_RCV_MSG ) + HCFASSERT( ifbp->IFB_RxLen >= offset, MERGE_2( offset, ifbp->IFB_RxLen ) ) + HCFASSERT( ifbp->IFB_lal >= offset, offset ) + HCFASSERT( (ifbp->IFB_CntlOpt & USE_DMA) == 0, 0xDADA ) + + if ( tot_len < 0 ) { + lal = 0; tot_len = 0; //suppress all copying activity in the do--while loop + } + do { //loop over all available fragments + // obnoxious hcf.c(1480) : warning C4769: conversion of near pointer to long integer + HCFASSERT( ((hcf_32)descp & 3 ) == 0, (hcf_32)descp ) + cp = descp->buf_addr; + j = min( (hcf_16)tot_len, descp->BUF_SIZE ); //minimum of "what's` available" and fragment size + descp->BUF_CNT = j; + tot_len -= j; //adjust length still to go + if ( lal ) { //if lookahead Buffer not yet completely copied + i = min( lal, j ); //minimum of "what's available" in LookAhead and fragment size + lal -= i; //adjust length still available in LookAhead + j -= i; //adjust length still available in current fragment + /*;? while loop could be improved by moving words but that is complicated on platforms with + * alignment requirements*/ + while ( i-- ) *cp++ = *lap++; + } + if ( j ) { //if LookAhead Buffer exhausted but still space in fragment, copy directly from NIC RAM + get_frag( ifbp, cp, j BE_PAR(0) ); + CALC_RX_MIC( cp, j ); + } + } while ( ( descp = descp->next_desc_addr ) != NULL ); +#if (HCF_TYPE) & HCF_TYPE_WPA + if ( ifbp->IFB_RxFID ) { + rc = check_mic( ifbp ); //prevents MIC error report if hcf_service_nic already consumed all + } +#endif // HCF_TYPE_WPA + (void)hcf_action( ifbp, HCF_ACT_RX_ACK ); //only 1 shot to get the data, so free the resources in the NIC + HCFASSERT( rc == HCF_SUCCESS, rc ) + HCFLOGEXIT( HCF_TRACE_RCV_MSG ) + return rc; +} // hcf_rcv_msg +#endif // HCF_DL_ONLY + + +#if (HCF_DL_ONLY) == 0 +/************************************************************************************************************ +* +*.MODULE int hcf_send_msg( IFBP ifbp, DESC_STRCT *descp, hcf_16 tx_cntl ) +*.PURPOSE Encapsulate a message and append padding and MIC. +* non-USB: Transfers the resulting message from Host to NIC and initiates transmission. +* USB: Transfer resulting message into a flat buffer. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* descp pointer to the DescriptorList or NULL +* tx_cntl indicates MAC-port and (Hermes) options +* HFS_TX_CNTL_SPECTRALINK +* HFS_TX_CNTL_PRIO +* HFS_TX_CNTL_TX_OK +* HFS_TX_CNTL_TX_EX +* HFS_TX_CNTL_TX_DELAY +* HFS_TX_CNTL_TX_CONT +* HCF_PORT_0 MAC Port 0 (default) +* HCF_PORT_1 (AP only) MAC Port 1 +* HCF_PORT_2 (AP only) MAC Port 2 +* HCF_PORT_3 (AP only) MAC Port 3 +* HCF_PORT_4 (AP only) MAC Port 4 +* HCF_PORT_5 (AP only) MAC Port 5 +* HCF_PORT_6 (AP only) MAC Port 6 +* +*.RETURNS +* HCF_SUCCESS +* HCF_ERR_DEFUNCT_.. +* HCF_ERR_TIME_OUT +* +*.DESCRIPTION: +* The Send Message Function embodies 2 functions: +* o transfers a message (including MAC header) from the provided buffer structure in Host memory to the Transmit +* Frame Structure (TxFS) in NIC memory. +* o Issue a send command to the F/W to actually transmit the contents of the TxFS. +* +* Control is based on the Resource Indicator IFB_RscInd. +* The Resource Indicator is maintained by the HCF and should only be interpreted but not changed by the MSF. +* The MSF must check IFB_RscInd to be non-zero before executing the call to the Send Message Function. +* When no resources are available, the MSF must handle the queuing of the Transmit frame and check the +* Resource Indicator periodically after calling hcf_service_nic. +* +* The Send Message Functions transfers a message to NIC memory when it is called with a non-NULL descp. +* Before the Send Message Function is invoked this way, the Resource Indicator (IFB_RscInd) must be checked. +* If the Resource is not available, Send Message Function execution must be postponed until after processing of +* a next hcf_service_nic it appears that the Resource has become available. +* The message is copied from the buffer structure identified by descp to the NIC. +* Copying stops if a NULL pointer in the next_desc_addr field is reached. +* Hcf_send_msg does not check for transmit buffer overflow, because the F/W does this protection. +* In case of a transmit buffer overflow, the surplus which does not fit in the buffer is simply dropped. +* +* The Send Message Function activates the F/W to actually send the message to the medium when the +* HFS_TX_CNTL_TX_DELAY bit of the tx_cntl parameter is not set. +* If the descp parameter of the current call is non-NULL, the message as represented by descp is send. +* If the descp parameter of the current call is NULL, and if the preceding call of the Send Message Function had +* a non-NULL descp and the preceding call had the HFS_TX_CNTL_TX_DELAY bit of tx_cntl set, then the message as +* represented by the descp of the preceding call is send. +* +* Hcf_send_msg supports encapsulation (see HCF_ENCAP) of Ethernet-II frames. +* An Ethernet-II frame is transferred to the Transmit Frame structure as an 802.3 frame. +* Hcf_send_msg distinguishes between an 802.3 and an Ethernet-II frame by looking at the data length/type field +* of the frame. If this field contains a value larger than 1514, the frame is considered to be an Ethernet-II +* frame, otherwise it is treated as an 802.3 frame. +* To ease implementation of the HCF, this type/type field must be located in the first descriptor structure, +* i.e. the 1st fragment must have a size of at least 14 (to contain DestAddr, SrcAddr and Len/Type field). +* An Ethernet-II frame is encapsulated by inserting a SNAP header between the addressing information and the +* type field. This insertion is transparent for the MSF. +* The HCF contains a fixed table that stores a number of types. If the value specified by the type/type field +* occurs in this table, Bridge Tunnel Encapsulation is used, otherwise RFC1042 encapsulation is used. +* Bridge Tunnel uses AA AA 03 00 00 F8 as SNAP header, +* RFC1042 uses AA AA 03 00 00 00 as SNAP header. +* The table currently contains: +* 0 0x80F3 AppleTalk Address Resolution Protocol (AARP) +* 0 0x8137 IPX +* +* The algorithm to distinguish between 802.3 and Ethernet-II frames limits the maximum length for frames of +* 802.3 frames to 1514 bytes. +* Encapsulation can be suppressed by means of the system constant HCF_ENCAP, e.g. to support proprietary +* protocols with 802.3 like frames with a size larger than 1514 bytes. +* +* In case the HCF encapsulates the frame, the number of bytes that is actually transmitted is determined by the +* cumulative value of the buf_cntl.buf_dim[0] fields. +* In case the HCF does not encapsulate the frame, the number of bytes that is actually transmitted is not +* determined by the cumulative value of the buf_cntl.buf_dim[DESC_CNTL_CNT] fields of the desc_strct's but by +* the Length field of the 802.3 frame. +* If there is a conflict between the cumulative value of the buf_cntl.buf_dim[0] fields and the +* 802.3 Length field the 802.3 Length field determines the number of bytes actually transmitted by the NIC while +* the cumulative value of the buf_cntl.buf_dim[0] fields determines the position of the MIC, hence a mismatch +* will result in MIC errors on the Receiving side. +* Currently this problem is flagged on the Transmit side by an Assert. +* The following fields of each of the descriptors in the descriptor list must be set by the MSF: +* o buf_cntl.buf_dim[0] +* o *next_desc_addr +* o *buf_addr +* +* All bits of the tx_cntl parameter except HFS_TX_CNTL_TX_DELAY and the HCF_PORT# bits are passed to the F/W via +* the HFS_TX_CNTL field of the TxFS. +* +* Note that hcf_send_msg does not detect NIC absence. The MSF is supposed to have its own -platform dependent- +* way to recognize card removal/insertion. +* The total system must be robust against card removal and there is no principal difference between card removal +* just after hcf_send_msg returns but before the actual transmission took place or sometime earlier. +* +* Assert fails if +* - ifbp has a recognizable out-of-range value +* - descp is a NULL pointer +* - no resources for PIF available. +* - Interrupts are enabled. +* - reentrancy, may be caused by calling hcf_functions without adequate protection +* against NIC interrupts or multi-threading. +* +*.DIAGRAM +*4: for the normal case (i.e. no HFS_TX_CNTL_TX_DELAY option active), a fid is acquired via the +* routine get_fid. If no FID is acquired, the remainder is skipped without an error notification. After +* all, the MSF is not supposed to call hcf_send_msg when no Resource is available. +*7: The ControlField of the TxFS is written. Since put_frag can only return the fatal Defunct or "No NIC", the +* return status can be ignored because when it fails, cmd_wait will fail as well. (see also the note on the +* need for a return code below). +* Note that HFS_TX_CNTL has different values for H-I, H-I/SSN and H-II and HFS_ADDR_DEST has different +* values for H-I (regardless of SSN) and H-II. +* By writing 17, 1 or 2 ( implying 16, 0 or 1 garbage word after HFS_TX_CNTL) the BAP just gets to +* HFS_ADDR_DEST for H-I, H-I/SSN and H-II respectively. +*10: if neither encapsulation nor MIC calculation is needed, splitting the first fragment in two does not +* really help but it makes the flow easier to follow to do not optimize on this difference +* +* hcf_send_msg checks whether the frame is an Ethernet-II rather than an "official" 802.3 frame. +* The E-II check is based on the length/type field in the MAC header. If this field has a value larger than +* 1500, E-II is assumed. The implementation of this test fails if the length/type field is not in the first +* descriptor. If E-II is recognized, a SNAP header is inserted. This SNAP header represents either RFC1042 +* or Bridge-Tunnel encapsulation, depending on the return status of the support routine hcf_encap. +* +*.NOTICE +* hcf_send_msg leaves the responsibility to only send messages on enabled ports at the MSF level. +* This is considered the strategy which is sufficiently adequate for all "robust" MSFs, have the least +* processor utilization and being still acceptable robust at the WCI !!!!! +* +* hcf_send_msg does not NEED a return value to report NIC absence or removal during the execution of +* hcf_send_msg(), because the MSF and higher layers must be able to cope anyway with the NIC being removed +* after a successful completion of hcf_send_msg() but before the actual transmission took place. +* To accommodate user expectations the current implementation does report NIC absence. +* Defunct blocks all NIC access and will (also) be reported on a number of other calls. +* +* hcf_send_msg does not check for transmit buffer overflow because the Hermes does this protection. +* In case of a transmit buffer overflow, the surplus which does not fit in the buffer is simply dropped. +* Note that this possibly results in the transmission of incomplete frames. +* +* After some deliberation with F/W team, it is decided that - being in the twilight zone of not knowing +* whether the problem at hand is an MSF bug, HCF buf, F/W bug, H/W malfunction or even something else - there +* is no "best thing to do" in case of a failing send, hence the HCF considers the TxFID ownership to be taken +* over by the F/W and hopes for an Allocate event in due time +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +int +hcf_send_msg( IFBP ifbp, DESC_STRCT *descp, hcf_16 tx_cntl ) +{ +int rc = HCF_SUCCESS; +DESC_STRCT *p /* = descp*/; //working pointer +hcf_16 len; // total byte count +hcf_16 i; + +hcf_16 fid = 0; + + HCFASSERT( ifbp->IFB_RscInd || descp == NULL, ifbp->IFB_RscInd ) + HCFASSERT( (ifbp->IFB_CntlOpt & USE_DMA) == 0, 0xDADB ) + + HCFLOGENTRY( HCF_TRACE_SEND_MSG, tx_cntl ) + HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic ) + HCFASSERT_INT + /* obnoxious c:/hcf/hcf.c(1480) : warning C4769: conversion of near pointer to long integer, + * so skip */ + HCFASSERT( ((hcf_32)descp & 3 ) == 0, (hcf_32)descp ) +#if HCF_ASSERT +{ int x = ifbp->IFB_FWIdentity.comp_id == COMP_ID_FW_AP ? tx_cntl & ~HFS_TX_CNTL_PORT : tx_cntl; + HCFASSERT( (x & ~HCF_TX_CNTL_MASK ) == 0, tx_cntl ) +} +#endif // HCF_ASSERT + + if ( descp ) ifbp->IFB_TxFID = 0; //cancel a pre-put message + +#if (HCF_EXT) & HCF_EXT_TX_CONT // Continuous transmit test + if ( tx_cntl == HFS_TX_CNTL_TX_CONT ) { + if ( ( fid = get_fid( ifbp ) ) != 0 ) { + //setup BAP to begin of TxFS + (void)setup_bap( ifbp, fid, 0, IO_OUT ); + //copy all the fragments in a transparent fashion + for ( p = descp; p; p = p->next_desc_addr ) { + /* obnoxious warning C4769: conversion of near pointer to long integer */ + HCFASSERT( ((hcf_32)p & 3 ) == 0, (hcf_32)p ) + put_frag( ifbp, p->buf_addr, p->BUF_CNT BE_PAR(0) ); + } + rc = cmd_exe( ifbp, HCMD_THESEUS | HCMD_BUSY | HCMD_STARTPREAMBLE, fid ); + if ( ifbp->IFB_RscInd == 0 ) { + ifbp->IFB_RscInd = get_fid( ifbp ); + } + } + // een slecht voorbeeld doet goed volgen ;? + HCFLOGEXIT( HCF_TRACE_SEND_MSG ) + return rc; + } +#endif // HCF_EXT_TX_CONT + /* the following initialization code is redundant for a pre-put message + * but moving it inside the "if fid" logic makes the merging with the + * USB flow awkward + */ +#if (HCF_TYPE) & HCF_TYPE_WPA + tx_cntl |= ifbp->IFB_MICTxCntl; +#endif // HCF_TYPE_WPA + if ( (fid = ifbp->IFB_TxFID) == 0 && ( fid = get_fid( ifbp ) ) != 0 ) /* 4 */ + /* skip the next compound statement if: + - pre-put message or + - no fid available (which should never occur if the MSF adheres to the WCI) + */ + { // to match the closing curly bracket of above "if" in case of HCF_TYPE_USB + //calculate total length ;? superfluous unless CCX or Encapsulation + len = 0; + p = descp; + do len += p->BUF_CNT; while ( ( p = p->next_desc_addr ) != NULL ); + p = descp; +//;? HCFASSERT( len <= HCF_MAX_MSG, len ) +/*7*/ (void)setup_bap( ifbp, fid, HFS_TX_CNTL, IO_OUT ); +#if (HCF_TYPE) & HCF_TYPE_TX_DELAY + HCFASSERT( ( descp != NULL ) ^ ( tx_cntl & HFS_TX_CNTL_TX_DELAY ), tx_cntl ) + if ( tx_cntl & HFS_TX_CNTL_TX_DELAY ) { + tx_cntl &= ~HFS_TX_CNTL_TX_DELAY; //!!HFS_TX_CNTL_TX_DELAY no longer available + ifbp->IFB_TxFID = fid; + fid = 0; //!!fid no longer available, be careful when modifying code + } +#endif // HCF_TYPE_TX_DELAY + OPW( HREG_DATA_1, tx_cntl ) ; + OPW( HREG_DATA_1, 0 ); +#if ! ( (HCF_TYPE) & HCF_TYPE_CCX ) + HCFASSERT( p->BUF_CNT >= 14, p->BUF_CNT ) + /* assume DestAddr/SrcAddr/Len/Type ALWAYS contained in 1st fragment + * otherwise life gets too cumbersome for MIC and Encapsulation !!!!!!!! + if ( p->BUF_CNT >= 14 ) { alternatively: add a safety escape !!!!!!!!!!!! } */ +#endif // HCF_TYPE_CCX + CALC_TX_MIC( NULL, -1 ); //initialize MIC +/*10*/ put_frag( ifbp, p->buf_addr, HCF_DASA_SIZE BE_PAR(0) ); //write DA, SA with MIC calculation + CALC_TX_MIC( p->buf_addr, HCF_DASA_SIZE ); //MIC over DA, SA + CALC_TX_MIC( null_addr, 4 ); //MIC over (virtual) priority field +#if (HCF_TYPE) & HCF_TYPE_CCX + //!!be careful do not use positive test on HCF_ACT_CCX_OFF, because IFB_CKIPStat is initially 0 + if(( ifbp->IFB_CKIPStat == HCF_ACT_CCX_ON ) || + ((GET_BUF_CNT(p) >= 20 ) && ( ifbp->IFB_CKIPStat == HCF_ACT_CCX_OFF ) && + (p->buf_addr[12] == 0xAA) && (p->buf_addr[13] == 0xAA) && + (p->buf_addr[14] == 0x03) && (p->buf_addr[15] == 0x00) && + (p->buf_addr[16] == 0x40) && (p->buf_addr[17] == 0x96) && + (p->buf_addr[18] == 0x00) && (p->buf_addr[19] == 0x00))) + { + i = HCF_DASA_SIZE; + + OPW( HREG_DATA_1, CNV_SHORT_TO_BIG( len - i )); + + /* need to send out the remainder of the fragment */ + put_frag( ifbp, &p->buf_addr[i], GET_BUF_CNT(p) - i BE_PAR(0) ); + } + else +#endif // HCF_TYPE_CCX + { + //if encapsulation needed +#if (HCF_ENCAP) == HCF_ENC + //write length (with SNAP-header,Type, without //DA,SA,Length ) no MIC calc. + if ( ( snap_header[sizeof(snap_header)-1] = hcf_encap( &p->buf_addr[HCF_DASA_SIZE] ) ) != ENC_NONE ) { + OPW( HREG_DATA_1, CNV_END_SHORT( len + (sizeof(snap_header) + 2) - ( 2*6 + 2 ) ) ); + //write splice with MIC calculation + put_frag( ifbp, snap_header, sizeof(snap_header) BE_PAR(0) ); + CALC_TX_MIC( snap_header, sizeof(snap_header) ); //MIC over 6 byte SNAP + i = HCF_DASA_SIZE; + } else +#endif // HCF_ENC + { + OPW( HREG_DATA_1, *(wci_recordp)&p->buf_addr[HCF_DASA_SIZE] ); + i = 14; + } + //complete 1st fragment starting with Type with MIC calculation + put_frag( ifbp, &p->buf_addr[i], p->BUF_CNT - i BE_PAR(0) ); + CALC_TX_MIC( &p->buf_addr[i], p->BUF_CNT - i ); + } + //do the remaining fragments with MIC calculation + while ( ( p = p->next_desc_addr ) != NULL ) { + /* obnoxious c:/hcf/hcf.c(1480) : warning C4769: conversion of near pointer to long integer, + * so skip */ + HCFASSERT( ((hcf_32)p & 3 ) == 0, (hcf_32)p ) + put_frag( ifbp, p->buf_addr, p->BUF_CNT BE_PAR(0) ); + CALC_TX_MIC( p->buf_addr, p->BUF_CNT ); + } + //pad message, finalize MIC calculation and write MIC to NIC + put_frag_finalize( ifbp ); + } + if ( fid ) { +/*16*/ rc = cmd_exe( ifbp, HCMD_BUSY | HCMD_TX | HCMD_RECL, fid ); + ifbp->IFB_TxFID = 0; + /* probably this (i.e. no RscInd AND "HREG_EV_ALLOC") at this point in time occurs so infrequent, + * that it might just as well be acceptable to skip this + * "optimization" code and handle that additional interrupt once in a while + */ +// 180 degree error in logic ;? #if ALLOC_15 +/*20*/ if ( ifbp->IFB_RscInd == 0 ) { + ifbp->IFB_RscInd = get_fid( ifbp ); + } +// #endif // ALLOC_15 + } +// HCFASSERT( level::ifbp->IFB_RscInd, ifbp->IFB_RscInd ) + HCFLOGEXIT( HCF_TRACE_SEND_MSG ) + return rc; +} // hcf_send_msg +#endif // HCF_DL_ONLY + + +#if (HCF_DL_ONLY) == 0 +/************************************************************************************************************ +* +*.MODULE int hcf_service_nic( IFBP ifbp, wci_bufp bufp, unsigned int len ) +*.PURPOSE Services (most) NIC events. +* Provides received message +* Provides status information. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* In non-DMA mode: +* bufp address of char buffer, sufficiently large to hold the first part of the RxFS up through HFS_TYPE +* len length in bytes of buffer specified by bufp +* value between HFS_TYPE + 2 and HFS_ADDR_DEST + HCF_MAX_MSG +* +*.RETURNS +* HCF_SUCCESS +* HCF_ERR_MIC message contains an erroneous MIC (only if frame fits completely in bufp) +* +*.DESCRIPTION +* +* MSF-accessible fields of Result Block +* - IFB_RxLen 0 or Frame size. +* - IFB_MBInfoLen 0 or the L-field of the oldest MBIB. +* - IFB_RscInd +* - IFB_HCF_Tallies updated if a corresponding event occurred. +* - IFB_NIC_Tallies updated if a Tally Info frame received from the NIC. +* - IFB_DmaPackets +* - IFB_TxFsStat +* - IFB_TxFsSwSup +* - IFB_LinkStat reflects new link status or 0x0000 if no change relative to previous hcf_service_nic call. +or +* - IFB_LinkStat link status, 0x8000 reflects change relative to previous hcf_service_nic call. +* +* When IFB_MBInfoLen is non-zero, at least one MBIB is available. +* +* IFB_RxLen reflects the number of received bytes in 802.3 view (Including DestAddr, SrcAddr and Length, +* excluding MIC-padding, MIC and sum check) of active Rx Frame Structure. If no Rx Data s available, IFB_RxLen +* equals 0x0000. +* Repeated execution causes the Service NIC Function to provide information about subsequently received +* messages, irrespective whether a hcf_rcv_msg or hcf_action(HCF_ACT_RX) is performed in between. +* +* When IFB_RxLen is non-zero, a Received Frame Structure is available to be routed to the protocol stack. +* When Monitor Mode is not active, this is guaranteed to be an error-free non-WMP frame. +* In case of Monitor Mode, it may also be a frame with an error or a WMP frame. +* Erroneous frames have a non-zero error-sub field in the HFS_STAT field in the look ahead buffer. +* +* If a Receive message is available in NIC RAM, the Receive Frame Structure is (partly) copied from the NIC to +* the buffer identified by bufp. +* Copying stops either after len bytes or when the complete 802.3 frame is copied. +* During the copying the message is decapsulated (if appropriate). +* If the frame is read completely by hcf_service_nic (i.e. the frame fits completely in the lookahead buffer), +* the frame is automatically ACK'ed to the F/W and still available via the look ahead buffer and hcf_rcv_msg. +* Only if the frame is read completely by hcf_service_nic, hcf_service_nic checks the MIC and sets the return +* status accordingly. In this case, hcf_rcv_msg does not check the MIC. +* +* The MIC calculation algorithm works more efficient if the length of the look ahead buffer is +* such that it fits exactly 4 n bytes of the 802.3 frame, i.e. len == HFS_ADDR_DEST + 4*n. +* +* The Service NIC Function supports the NIC event service handling process. +* It performs the appropriate actions to service the NIC, such that the event cause is eliminated and related +* information is saved. +* The Service NIC Function is executed by the MSF ISR or polling routine as first step to determine the event +* cause(s). It is the responsibility of the MSF to perform all not directly NIC related interrupt service +* actions, e.g. in a PC environment this includes servicing the PIC, and managing the Processor Interrupt +* Enabling/Disabling. +* In case of a polled based system, the Service NIC Function must be executed "frequently". +* The Service NIC Function may have side effects related to the Mailbox and Resource Indicator (IFB_RscInd). +* +* hcf_service_nic returns: +* - The length of the data in the available MBIB (IFB_MBInfoLen) +* - Changes in the link status (IFB_LinkStat) +* - The length of the data in the available Receive Frame Structure (IFB_RxLen) +* - updated IFB_RscInd +* - Updated Tallies +* +* hcf_service_nic is presumed to neither interrupt other HCF-tasks nor to be interrupted by other HCF-tasks. +* A way to achieve this is to precede hcf_service_nic as well as all other HCF-tasks with a call to +* hcf_action to disable the card interrupts and, after all work is completed, with a call to hcf_action to +* restore (which is not necessarily the same as enabling) the card interrupts. +* In case of a polled environment, it is assumed that the MSF programmer is sufficiently familiar with the +* specific requirements of that environment to translate the interrupt strategy to a polled strategy. +* +* hcf_service_nic services the following Hermes events: +* - HREG_EV_INFO Asynchronous Information Frame +* - HREG_EV_INFO_DROP WMAC did not have sufficient RAM to build Unsolicited Information Frame +* - HREG_EV_TX_EXC (if applicable, i.e. selected via HCF_EXT_INT_TX_EX bit of HCF_EXT) +* - HREG_EV_SLEEP_REQ (if applicable, i.e. selected via HCF_DDS/HCF_CDS bit of HCF_SLEEP) +* ** in non_DMA mode +* - HREG_EV_ALLOC Asynchronous part of Allocation/Reclaim completed while out of resources at +* completion of hcf_send_msg/notify +* - HREG_EV_RX the detection of the availability of received messages +* including WaveLAN Management Protocol (WMP) message processing +* ** in DMA mode +* - HREG_EV_RDMAD +* - HREG_EV_TDMAD +*!! hcf_service_nic does not service the following Hermes events: +*!! HREG_EV_TX (the "OK" Tx Event) is no longer supported by the WCI, if it occurs it is unclear +*!! what the cause is, so no meaningful strategy is available. Not acking the bit is +*!! probably the best help that can be given to the debugger. +*!! HREG_EV_CMD handled in cmd_wait. +*!! HREG_EV_FW_DMA (i.e. HREG_EV_RXDMA, HREG_EV_TXDMA and_EV_LPESC) are either not used or used +*!! between the F/W and the DMA engine. +*!! HREG_EV_ACK_REG_READY is only applicable for H-II (i.e. not HII.5 and up, see DAWA) +* +* If, in non-DMA mode, a Rx message is available, its length is reflected by the IFB_RxLen field of the IFB. +* This length reflects the data itself and the Destination Address, Source Address and DataLength/Type field +* but not the SNAP-header in case of decapsulation by the HCF. If no message is available, IFB_RxLen is +* zero. Former versions of the HCF handled WMP messages and supported a "monitor" mode in hcf_service_nic, +* which deposited certain or all Rx messages in the MailBox. The responsibility to handle these frames is +* moved to the MSF. The HCF offers as supports hcf_put_info with CFG_MB_INFO as parameter to emulate the old +* implementation under control of the MSF. +* +* **Rx Buffer free strategy +* When hcf_service_nic reports the availability of a non-DMA message, the MSF can access that message by +* means of hcf_rcv_msg. It must be prevented that the LAN Controller writes new data in the NIC buffer +* before the MSF is finished with the current message. The NIC buffer is returned to the LAN Controller +* when: +* - the complete frame fits in the lookahead buffer or +* - hcf_rcv_msg is called or +* - hcf_action with HCF_ACT_RX is called or +* - hcf_service_nic is called again +* It can be reasoned that hcf_action( INT_ON ) should not be given before the MSF has completely processed +* a reported Rx-frame. The reason is that the INT_ON action is guaranteed to cause a (Rx-)interrupt (the +* MSF is processing a Rx-frame, hence the Rx-event bit in the Hermes register must be active). This +* interrupt will cause hcf_service_nic to be called, which will cause the ack-ing of the "last" Rx-event +* to the Hermes, causing the Hermes to discard the associated NIC RAM buffer. +* Assert fails if +* - ifbp is zero or other recognizable out-of-range value. +* - hcf_service_nic is called without a prior call to hcf_connect. +* - interrupts are enabled. +* - reentrancy, may be caused by calling hcf_functions without adequate protection +* against NIC interrupts or multi-threading. +* +* +*.DIAGRAM +*1: IFB_LinkStat is cleared, if a LinkStatus frame is received, IFB_LinkStat will be updated accordingly +* by isr_info. +or +*1: IFB_LinkStat change indication is cleared. If a LinkStatus frame is received, IFB_LinkStat will be updated +* accordingly by isr_info. +*2: IFB_RxLen must be cleared before the NIC presence check otherwise: +* - this value may stay non-zero if the NIC is pulled out at an inconvenient moment. +* - the RxAck on a zero-FID needs a zero-value for IFB_RxLen to work +* Note that as side-effect of the hcf_action call, the remainder of Rx related info is re-initialized as +* well. +*4: In case of Defunct mode, the information supplied by Hermes is unreliable, so the body of +* hcf_service_nic is skipped. Since hcf_cntl turns into a NOP if Primary or Station F/W is incompatible, +* hcf_service_nic is also skipped in those cases. +* To prevent that hcf_service_nic reports bogus information to the MSF with all - possibly difficult to +* debug - undesirable side effects, it is paramount to check the NIC presence. In former days the presence +* test was based on the Hermes register HREG_SW_0. Since in HCF_ACT_INT_OFF is choosen for strategy based on +* HREG_EV_STAT, this is now also used in hcf_service_nic. The motivation to change strategy is partly +* due to inconsistent F/W implementations with respect to HREG_SW_0 manipulation around reset and download. +* Note that in polled environments Card Removal is not detected by INT_OFF which makes the check in +* hcf_service_nic even more important. +*8: The event status register of the Hermes is sampled +* The assert checks for unexpected events ;?????????????????????????????????????. +* - HREG_EV_INFO_DROP is explicitly excluded from the acceptable HREG_EV_STAT bits because it indicates +* a too heavily loaded system. +* - HREG_EV_ACK_REG_READY is 0x0000 for H-I (and hopefully H-II.5) +* +* +* HREG_EV_TX_EXC is accepted (via HREG_EV_TX_EXT) if and only if HCF_EXT_INT_TX_EX set in the HCF_EXT +* definition at compile time. +* The following activities are handled: +* - Alloc events are handled by hcf_send_msg (and notify). Only if there is no "spare" resource, the +* alloc event is superficially serviced by hcf_service_nic to create a pseudo-resource with value +* 0x001. This value is recognized by get_fid (called by hcf_send_msg and notify) where the real +* TxFid is retrieved and the Hermes is acked and - hopefully - the "normal" case with a spare TxFid +* in IFB_RscInd is restored. +* - Info drop events are handled by incrementing a tally +* - LinkEvent (including solicited and unsolicited tallies) are handled by procedure isr_info. +* - TxEx (if selected at compile time) is handled by copying the significant part of the TxFS +* into the IFB for further processing by the MSF. +* Note the complication of the zero-FID protection sub-scheme in DAWA. +* Note, the Ack of all of above events is handled at the end of hcf_service_nic +*16: In case of non-DMA ( either not compiled in or due to a run-time choice): +* If an Rx-frame is available, first the FID of that frame is read, including the complication of the +* zero-FID protection sub-scheme in DAWA. Note that such a zero-FID is acknowledged at the end of +* hcf_service_nic and that this depends on the IFB_RxLen initialization in the begin of hcf_service_nic. +* The Assert validates the HCF assumption about Hermes implementation upon which the range of +* Pseudo-RIDs is based. +* Then the control fields up to the start of the 802.3 frame are read from the NIC into the lookahead buffer. +* The status field is converted to native Endianess. +* The length is, after implicit Endianess conversion if needed, and adjustment for the 14 bytes of the +* 802.3 MAC header, stored in IFB_RxLen. +* In MAC Monitor mode, 802.11 control frames with a TOTAL length of 14 are received, so without this +* length adjustment, IFB_RxLen could not be used to distinguish these frames from "no frame". +* No MIC calculation processes are associated with the reading of these Control fields. +*26: This length test feels like superfluous robustness against malformed frames, but it turned out to be +* needed in the real (hostile) world. +* The decapsulation check needs sufficient data to represent DA, SA, L, SNAP and Type which amounts to +* 22 bytes. In MAC Monitor mode, 802.11 control frames with a smaller length are received. To prevent +* that the implementation goes haywire, a check on the length is needed. +* The actual decapsulation takes place on the fly in the copying process by overwriting the SNAP header. +* Note that in case of decapsulation the SNAP header is not passed to the MSF, hence IFB_RxLen must be +* compensated for the SNAP header length. +* The 22 bytes needed for decapsulation are (more than) sufficient for the exceptional handling of the +* MIC algorithm of the L-field (replacing the 2 byte L-field with 4 0x00 bytes). +*30: The 12 in the no-SSN branch corresponds with the get_frag, the 2 with the IPW of the SSN branch +*32: If Hermes reported MIC-presence, than the MIC engine is initialized with the non-dummy MIC calculation +* routine address and appropriate key. +*34: The 8 bytes after the DA, SA, L are read and it is checked whether decapsulation is needed i.e.: +* - the Hermes reported Tunnel encapsulation or +* - the Hermes reported 1042 Encapsulation and hcf_encap reports that the HCF would not have used +* 1042 as the encapsulation mechanism +* Note that the first field of the RxFS in bufp has Native Endianess due to the conversion done by the +* BE_PAR in get_frag. +*36: The Type field is the only word kept (after moving) of the just read 8 bytes, it is moved to the +* L-field. The original L-field and 6 byte SNAP header are discarded, so IFB_RxLen and buf_addr must +* be adjusted by 8. +*40: Determine how much of the frame (starting with DA) fits in the Lookahead buffer, then read the not-yet +* read data into the lookahead buffer. +* If the lookahead buffer contains the complete message, check the MIC. The majority considered this +* I/F more appropriate then have the MSF call hcf_get_data only to check the MIC. +*44: Since the complete message is copied from NIC RAM to PC RAM, the Rx can be acknowledged to the Hermes +* to optimize the flow ( a better chance to get new Rx data in the next pass through hcf_service_nic ). +* This acknowledgement can not be done via hcf_action( HCF_ACT_RX_ACK ) because this also clears +* IFB_RxLEN thus corrupting the I/F to the MSF. +*;?: In case of DMA (compiled in and activated): + + +*54: Limiting the number of places where the F/W is acked (e.g. the merging of the Rx-ACK with the other +* ACKs), is supposed to diminish the potential of race conditions in the F/W. +* Note 1: The CMD event is acknowledged in cmd_cmpl +* Note 2: HREG_EV_ACK_REG_READY is 0x0000 for H-I (and hopefully H-II.5) +* Note 3: The ALLOC event is acknowledged in get_fid (except for the initialization flow) +* +*.NOTICE +* The Non-DMA HREG_EV_RX is handled different compared with the other F/W events. +* The HREG_EV_RX event is acknowledged by the first hcf_service_nic call after the +* hcf_service_nic call that reported the occurrence of this event. +* This acknowledgment +* makes the next Receive Frame Structure (if any) available. +* An updated IFB_RxLen +* field reflects this availability. +* +*.NOTICE +* The minimum size for Len must supply space for: +* - an F/W dependent number of bytes of Control Info field including the 802.11 Header field +* - Destination Address +* - Source Address +* - Length field +* - [ SNAP Header] +* - [ Ethernet-II Type] +* This results in 68 for Hermes-I and 80 for Hermes-II +* This way the minimum amount of information is available needed by the HCF to determine whether the frame +* must be decapsulated. +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +int +hcf_service_nic( IFBP ifbp, wci_bufp bufp, unsigned int len ) +{ + +int rc = HCF_SUCCESS; +hcf_16 stat; +wci_bufp buf_addr; +hcf_16 i; + + HCFLOGENTRY( HCF_TRACE_SERVICE_NIC, ifbp->IFB_IntOffCnt ) + HCFASSERT( ifbp->IFB_Magic == HCF_MAGIC, ifbp->IFB_Magic ) + HCFASSERT_INT + + ifbp->IFB_LinkStat = 0; // ;? to be obsoleted ASAP /* 1*/ + ifbp->IFB_DSLinkStat &= ~CFG_LINK_STAT_CHANGE; /* 1*/ + (void)hcf_action( ifbp, HCF_ACT_RX_ACK ); /* 2*/ + if ( ifbp->IFB_CardStat == 0 && ( stat = IPW( HREG_EV_STAT ) ) != 0xFFFF ) { /* 4*/ +/* IF_NOT_DMA( HCFASSERT( !( stat & ~HREG_EV_BASIC_MASK, stat ) ) + * IF_NOT_USE_DMA( HCFASSERT( !( stat & ~HREG_EV_BASIC_MASK, stat ) ) + * IF_USE_DMA( HCFASSERT( !( stat & ~( HREG_EV_BASIC_MASK ^ ( HREG_EV_...DMA.... ), stat ) ) + */ + /* 8*/ + if ( ifbp->IFB_RscInd == 0 && stat & HREG_EV_ALLOC ) { //Note: IFB_RscInd is ALWAYS 1 for DMA + ifbp->IFB_RscInd = 1; + } + IF_TALLY( if ( stat & HREG_EV_INFO_DROP ) ifbp->IFB_HCF_Tallies.NoBufInfo++; ) +#if (HCF_EXT) & HCF_EXT_INT_TICK + if ( stat & HREG_EV_TICK ) { + ifbp->IFB_TickCnt++; + } +#if 0 // (HCF_SLEEP) & HCF_DDS + if ( ifbp->IFB_TickCnt == 3 && ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_CONNECTED ) == 0 ) { +CFG_DDS_TICK_TIME_STRCT ltv; + // 2 second period (with 1 tick uncertanty) in not-connected mode -->go into DS_OOR + hcf_action( ifbp, HCF_ACT_SLEEP ); + ifbp->IFB_DSLinkStat |= CFG_LINK_STAT_DS_OOR; //set OutOfRange + ltv.len = 2; + ltv.typ = CFG_DDS_TICK_TIME; + ltv.tick_time = ( ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_TIMER ) + 0x10 ) *64; //78 is more right + hcf_put_info( ifbp, (LTVP)<v ); + printk( "<5>Preparing for sleep, link_status: %04X, timer : %d\n", + ifbp->IFB_DSLinkStat, ltv.tick_time );//;?remove me 1 day + ifbp->IFB_TickCnt++; //;?just to make sure we do not keep on printing above message + if ( ltv.tick_time < 300 * 125 ) ifbp->IFB_DSLinkStat += 0x0010; + + } +#endif // HCF_DDS +#endif // HCF_EXT_INT_TICK + if ( stat & HREG_EV_INFO ) { + isr_info( ifbp ); + } +#if (HCF_EXT) & HCF_EXT_INT_TX_EX + if ( stat & HREG_EV_TX_EXT && ( i = IPW( HREG_TX_COMPL_FID ) ) != 0 /*DAWA*/ ) { + DAWA_ZERO_FID( HREG_TX_COMPL_FID ) + (void)setup_bap( ifbp, i, 0, IO_IN ); + get_frag( ifbp, &ifbp->IFB_TxFsStat, HFS_SWSUP BE_PAR(1) ); + } +#endif // HCF_EXT_INT_TX_EX +//!rlav DMA engine will handle the rx event, not the driver +#if HCF_DMA + if ( !( ifbp->IFB_CntlOpt & USE_DMA ) ) //!! be aware of the logical indentations +#endif // HCF_DMA +/*16*/ if ( stat & HREG_EV_RX && ( ifbp->IFB_RxFID = IPW( HREG_RX_FID ) ) != 0 ) { //if 0 then DAWA_ACK + HCFASSERT( bufp, len ) + HCFASSERT( len >= HFS_DAT + 2, len ) + DAWA_ZERO_FID( HREG_RX_FID ) + HCFASSERT( ifbp->IFB_RxFID < CFG_PROD_DATA, ifbp->IFB_RxFID) + (void)setup_bap( ifbp, ifbp->IFB_RxFID, 0, IO_IN ); + get_frag( ifbp, bufp, HFS_ADDR_DEST BE_PAR(1) ); + ifbp->IFB_lap = buf_addr = bufp + HFS_ADDR_DEST; + ifbp->IFB_RxLen = (hcf_16)(bufp[HFS_DAT_LEN] + (bufp[HFS_DAT_LEN+1]<<8) + 2*6 + 2); +/*26*/ if ( ifbp->IFB_RxLen >= 22 ) { // convenient for MIC calculation (5 DWs + 1 "skipped" W) + //. get DA,SA,Len/Type and (SNAP,Type or 8 data bytes) +/*30*/ get_frag( ifbp, buf_addr, 22 BE_PAR(0) ); +/*32*/ CALC_RX_MIC( bufp, -1 ); //. initialize MIC + CALC_RX_MIC( buf_addr, HCF_DASA_SIZE ); //. MIC over DA, SA + CALC_RX_MIC( null_addr, 4 ); //. MIC over (virtual) priority field + CALC_RX_MIC( buf_addr+14, 8 ); //. skip Len, MIC over SNAP,Type or 8 data bytes) + buf_addr += 22; +#if (HCF_TYPE) & HCF_TYPE_CCX +//!!be careful do not use positive test on HCF_ACT_CCX_OFF, because IFB_CKIPStat is initially 0 + if( ifbp->IFB_CKIPStat != HCF_ACT_CCX_ON ) +#endif // HCF_TYPE_CCX + { +#if (HCF_ENCAP) == HCF_ENC + HCFASSERT( len >= HFS_DAT + 2 + sizeof(snap_header), len ) +/*34*/ i = *(wci_recordp)&bufp[HFS_STAT] & ( HFS_STAT_MSG_TYPE | HFS_STAT_ERR ); + if ( i == HFS_STAT_TUNNEL || + ( i == HFS_STAT_1042 && hcf_encap( (wci_bufp)&bufp[HFS_TYPE] ) != ENC_TUNNEL ) ) { + //. copy E-II Type to 802.3 LEN field +/*36*/ bufp[HFS_LEN ] = bufp[HFS_TYPE ]; + bufp[HFS_LEN+1] = bufp[HFS_TYPE+1]; + //. discard Snap by overwriting with data + ifbp->IFB_RxLen -= (HFS_TYPE - HFS_LEN); + buf_addr -= ( HFS_TYPE - HFS_LEN ); // this happens to bring us at a DW boundary of 36 + } +#endif // HCF_ENC + } + } +/*40*/ ifbp->IFB_lal = min( (hcf_16)(len - HFS_ADDR_DEST), ifbp->IFB_RxLen ); + i = ifbp->IFB_lal - ( buf_addr - ( bufp + HFS_ADDR_DEST ) ); + get_frag( ifbp, buf_addr, i BE_PAR(0) ); + CALC_RX_MIC( buf_addr, i ); +#if (HCF_TYPE) & HCF_TYPE_WPA + if ( ifbp->IFB_lal == ifbp->IFB_RxLen ) { + rc = check_mic( ifbp ); + } +#endif // HCF_TYPE_WPA +/*44*/ if ( len - HFS_ADDR_DEST >= ifbp->IFB_RxLen ) { + ifbp->IFB_RxFID = 0; + } else { /* IFB_RxFID is cleared, so you do not get another Rx_Ack at next entry of hcf_service_nic */ + stat &= (hcf_16)~HREG_EV_RX; //don't ack Rx if processing not yet completed + } + } + // in case of DMA: signal availability of rx and/or tx packets to MSF + IF_USE_DMA( ifbp->IFB_DmaPackets |= stat & ( HREG_EV_RDMAD | HREG_EV_TDMAD ); ) + // rlav : pending HREG_EV_RDMAD or HREG_EV_TDMAD events get acknowledged here. +/*54*/ stat &= (hcf_16)~( HREG_EV_SLEEP_REQ | HREG_EV_CMD | HREG_EV_ACK_REG_READY | HREG_EV_ALLOC | HREG_EV_FW_DMA ); +//a positive mask would be easier to understand /*54*/ stat &= (hcf_16)~( HREG_EV_SLEEP_REQ | HREG_EV_CMD | HREG_EV_ACK_REG_READY | HREG_EV_ALLOC | HREG_EV_FW_DMA ); + IF_USE_DMA( stat &= (hcf_16)~HREG_EV_RX; ) + if ( stat ) { + DAWA_ACK( stat ); /*DAWA*/ + } + } + HCFLOGEXIT( HCF_TRACE_SERVICE_NIC ) + return rc; +} // hcf_service_nic +#endif // HCF_DL_ONLY + + +/************************************************************************************************************ +************************** H C F S U P P O R T R O U T I N E S ****************************************** +************************************************************************************************************/ + + +/************************************************************************************************************ +* +*.SUBMODULE void calc_mic( hcf_32* p, hcf_32 m ) +*.PURPOSE calculate MIC on a quad byte. +* +*.ARGUMENTS +* p address of the MIC +* m 32 bit value to be processed by the MIC calculation engine +* +*.RETURNS N.A. +* +*.DESCRIPTION +* calc_mic is the implementation of the MIC algorithm. It is a monkey-see monkey-do copy of +* Michael::appendByte() +* of Appendix C of .......... +* +* +*.DIAGRAM +* +*.NOTICE +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ + +#if (HCF_TYPE) & HCF_TYPE_WPA + +#define ROL32( A, n ) ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) ) +#define ROR32( A, n ) ROL32( (A), 32-(n) ) + +#define L *p +#define R *(p+1) + +void +calc_mic( hcf_32* p, hcf_32 m ) +{ +#if HCF_BIG_ENDIAN + m = (m >> 16) | (m << 16); +#endif // HCF_BIG_ENDIAN + L ^= m; + R ^= ROL32( L, 17 ); + L += R; + R ^= ((L & 0xff00ff00) >> 8) | ((L & 0x00ff00ff) << 8); + L += R; + R ^= ROL32( L, 3 ); + L += R; + R ^= ROR32( L, 2 ); + L += R; +} // calc_mic +#undef R +#undef L +#endif // HCF_TYPE_WPA + + + +#if (HCF_TYPE) & HCF_TYPE_WPA +/************************************************************************************************************ +* +*.SUBMODULE void calc_mic_rx_frag( IFBP ifbp, wci_bufp p, int len ) +*.PURPOSE calculate MIC on a single fragment. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* bufp (byte) address of buffer +* len length in bytes of buffer specified by bufp +* +*.RETURNS N.A. +* +*.DESCRIPTION +* calc_mic_rx_frag ........ +* +* The MIC is located in the IFB. +* The MIC is separate for Tx and Rx, thus allowing hcf_send_msg to occur between hcf_service_nic and +* hcf_rcv_msg. +* +* +*.DIAGRAM +* +*.NOTICE +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +void +calc_mic_rx_frag( IFBP ifbp, wci_bufp p, int len ) +{ +static union { hcf_32 x32; hcf_16 x16[2]; hcf_8 x8[4]; } x; //* area to accumulate 4 bytes input for MIC engine +int i; + + if ( len == -1 ) { //initialize MIC housekeeping + i = *(wci_recordp)&p[HFS_STAT]; + /* i = CNV_SHORTP_TO_LITTLE(&p[HFS_STAT]); should not be neede to prevent alignment poroblems + * since len == -1 if and only if p is lookahaead buffer which MUST be word aligned + * to be re-investigated by NvR + */ + + if ( ( i & HFS_STAT_MIC ) == 0 ) { + ifbp->IFB_MICRxCarry = 0xFFFF; //suppress MIC calculation + } else { + ifbp->IFB_MICRxCarry = 0; +//* Note that "coincidentally" the bit positions used in HFS_STAT +//* correspond with the offset of the key in IFB_MICKey + i = ( i & HFS_STAT_MIC_KEY_ID ) >> 10; /* coincidentally no shift needed for i itself */ + ifbp->IFB_MICRx[0] = CNV_LONG_TO_LITTLE(ifbp->IFB_MICRxKey[i ]); + ifbp->IFB_MICRx[1] = CNV_LONG_TO_LITTLE(ifbp->IFB_MICRxKey[i+1]); + } + } else { + if ( ifbp->IFB_MICRxCarry == 0 ) { + x.x32 = CNV_LONGP_TO_LITTLE(p); + p += 4; + if ( len < 4 ) { + ifbp->IFB_MICRxCarry = (hcf_16)len; + } else { + ifbp->IFB_MICRxCarry = 4; + len -= 4; + } + } else while ( ifbp->IFB_MICRxCarry < 4 && len ) { //note for hcf_16 applies: 0xFFFF > 4 + x.x8[ifbp->IFB_MICRxCarry++] = *p++; + len--; + } + while ( ifbp->IFB_MICRxCarry == 4 ) { //contrived so we have only 1 call to calc_mic so we could bring it in-line + calc_mic( ifbp->IFB_MICRx, x.x32 ); + x.x32 = CNV_LONGP_TO_LITTLE(p); + p += 4; + if ( len < 4 ) { + ifbp->IFB_MICRxCarry = (hcf_16)len; + } + len -= 4; + } + } +} // calc_mic_rx_frag +#endif // HCF_TYPE_WPA + + +#if (HCF_TYPE) & HCF_TYPE_WPA +/************************************************************************************************************ +* +*.SUBMODULE void calc_mic_tx_frag( IFBP ifbp, wci_bufp p, int len ) +*.PURPOSE calculate MIC on a single fragment. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* bufp (byte) address of buffer +* len length in bytes of buffer specified by bufp +* +*.RETURNS N.A. +* +*.DESCRIPTION +* calc_mic_tx_frag ........ +* +* The MIC is located in the IFB. +* The MIC is separate for Tx and Rx, thus allowing hcf_send_msg to occur between hcf_service_nic and +* hcf_rcv_msg. +* +* +*.DIAGRAM +* +*.NOTICE +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +void +calc_mic_tx_frag( IFBP ifbp, wci_bufp p, int len ) +{ +static union { hcf_32 x32; hcf_16 x16[2]; hcf_8 x8[4]; } x; //* area to accumulate 4 bytes input for MIC engine + + //if initialization request + if ( len == -1 ) { + //. presume MIC calculation disabled + ifbp->IFB_MICTxCarry = 0xFFFF; + //. if MIC calculation enabled + if ( ifbp->IFB_MICTxCntl ) { + //. . clear MIC carry + ifbp->IFB_MICTxCarry = 0; + //. . initialize MIC-engine + ifbp->IFB_MICTx[0] = CNV_LONG_TO_LITTLE(ifbp->IFB_MICTxKey[0]); /*Tx always uses Key 0 */ + ifbp->IFB_MICTx[1] = CNV_LONG_TO_LITTLE(ifbp->IFB_MICTxKey[1]); + } + //else + } else { + //. if MIC enabled (Tx) / if MIC present (Rx) + //. and no carry from previous calc_mic_frag + if ( ifbp->IFB_MICTxCarry == 0 ) { + //. . preset accu with 4 bytes from buffer + x.x32 = CNV_LONGP_TO_LITTLE(p); + //. . adjust pointer accordingly + p += 4; + //. . if buffer contained less then 4 bytes + if ( len < 4 ) { + //. . . promote valid bytes in accu to carry + //. . . flag accu to contain incomplete double word + ifbp->IFB_MICTxCarry = (hcf_16)len; + //. . else + } else { + //. . . flag accu to contain complete double word + ifbp->IFB_MICTxCarry = 4; + //. . adjust remaining buffer length + len -= 4; + } + //. else if MIC enabled + //. and if carry bytes from previous calc_mic_tx_frag + //. . move (1-3) bytes from carry into accu + } else while ( ifbp->IFB_MICTxCarry < 4 && len ) { /* note for hcf_16 applies: 0xFFFF > 4 */ + x.x8[ifbp->IFB_MICTxCarry++] = *p++; + len--; + } + //. while accu contains complete double word + //. and MIC enabled + while ( ifbp->IFB_MICTxCarry == 4 ) { + //. . pass accu to MIC engine + calc_mic( ifbp->IFB_MICTx, x.x32 ); + //. . copy next 4 bytes from buffer to accu + x.x32 = CNV_LONGP_TO_LITTLE(p); + //. . adjust buffer pointer + p += 4; + //. . if buffer contained less then 4 bytes + //. . . promote valid bytes in accu to carry + //. . . flag accu to contain incomplete double word + if ( len < 4 ) { + ifbp->IFB_MICTxCarry = (hcf_16)len; + } + //. . adjust remaining buffer length + len -= 4; + } + } +} // calc_mic_tx_frag +#endif // HCF_TYPE_WPA + + +#if HCF_PROT_TIME +/************************************************************************************************************ +* +*.SUBMODULE void calibrate( IFBP ifbp ) +*.PURPOSE calibrates the S/W protection counter against the Hermes Timer tick. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* +*.RETURNS N.A. +* +*.DESCRIPTION +* calibrates the S/W protection counter against the Hermes Timer tick +* IFB_TickIni is the value used to initialize the S/W protection counter such that the expiration period +* more or less independent of the processor speed. If IFB_TickIni is not yet calibrated, it is done now. +* This calibration is "reasonably" accurate because the Hermes is in a quiet state as a result of the +* Initialize command. +* +* +*.DIAGRAM +* +*1: IFB_TickIni is initialized at INI_TICK_INI by hcf_connect. If calibrate succeeds, IFB_TickIni is +* guaranteed to be changed. As a consequence there will be only 1 shot at calibration (regardless of the +* number of init calls) under normal circumstances. +*2: Calibration is done HCF_PROT_TIME_CNT times. This diminish the effects of jitter and interference, +* especially in a pre-emptive environment. HCF_PROT_TIME_CNT is in the range of 16 through 32 and derived +* from the HCF_PROT_TIME specified by the MSF programmer. The divisor needed to scale HCF_PROT_TIME into the +* 16-32 range, is used as a multiplicator after the calibration, to scale the found value back to the +* requested range. This way a compromise is achieved between accuracy and duration of the calibration +* process. +*3: Acknowledge the Timer Tick Event. +* Each cycle is limited to at most INI_TICK_INI samples of the TimerTick status of the Hermes. +* Since the start of calibrate is unrelated to the Hermes Internal Timer, the first interval may last from 0 +* to the normal interval, all subsequent intervals should be the full length of the Hermes Tick interval. +* The Hermes Timer Tick is not reprogrammed by the HCF, hence it is running at the default of 10 k +* microseconds. +*4: If the Timer Tick Event is continuously up (prot_cnt still has the value INI_TICK_INI) or no Timer Tick +* Event occurred before the protection counter expired, reset IFB_TickIni to INI_TICK_INI, +* set the defunct bit of IFB_CardStat (thus rendering the Hermes inoperable) and exit the calibrate routine. +*8: ifbp->IFB_TickIni is multiplied to scale the found value back to the requested range as explained under 2. +* +*.NOTICE +* o Although there are a number of viewpoints possible, calibrate() uses as error strategy that a single +* failure of the Hermes TimerTick is considered fatal. +* o There is no hard and concrete time-out value defined for Hermes activities. The default 1 seconds is +* believed to be sufficiently "relaxed" for real life and to be sufficiently short to be still useful in an +* environment with humans. +* o Note that via IFB_DefunctStat time outs in cmd_wait and in hcfio_string block all Hermes access till the +* next init so functions which call a mix of cmd_wait and hcfio_string only need to check the return status +* of the last call +* o The return code is preset at Time out. +* The additional complication that no calibrated value for the protection count can be assumed since +* calibrate() does not yet have determined a calibrated value (a catch 22), is handled by setting the +* initial value at INI_TICK_INI (by hcf_connect). This approach is considered safe, because: +* - the HCF does not use the pipeline mechanism of Hermes commands. +* - the likelihood of failure (the only time when protection count is relevant) is small. +* - the time will be sufficiently large on a fast machine (busy bit drops on good NIC before counter +* expires) +* - the time will be sufficiently small on a slow machine (counter expires on bad NIC before the end user +* switches the power off in despair +* The time needed to wrap a 32 bit counter around is longer than many humans want to wait, hence the more or +* less arbitrary value of 0x40000L is chosen, assuming it does not take too long on an XT and is not too +* short on a scream-machine. +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +HCF_STATIC void +calibrate( IFBP ifbp ) +{ +int cnt = HCF_PROT_TIME_CNT; +hcf_32 prot_cnt; + + HCFTRACE( ifbp, HCF_TRACE_CALIBRATE ); + if ( ifbp->IFB_TickIni == INI_TICK_INI ) { /*1*/ + ifbp->IFB_TickIni = 0; /*2*/ + while ( cnt-- ) { + prot_cnt = INI_TICK_INI; + OPW( HREG_EV_ACK, HREG_EV_TICK ); /*3*/ + while ( (IPW( HREG_EV_STAT ) & HREG_EV_TICK) == 0 && --prot_cnt ) { + ifbp->IFB_TickIni++; + } + if ( prot_cnt == 0 || prot_cnt == INI_TICK_INI ) { /*4*/ + ifbp->IFB_TickIni = INI_TICK_INI; + ifbp->IFB_DefunctStat = HCF_ERR_DEFUNCT_TIMER; + ifbp->IFB_CardStat |= CARD_STAT_DEFUNCT; + HCFASSERT( DO_ASSERT, prot_cnt ) + } + } + ifbp->IFB_TickIni <<= HCF_PROT_TIME_SHFT; /*8*/ + } + HCFTRACE( ifbp, HCF_TRACE_CALIBRATE | HCF_TRACE_EXIT ); +} // calibrate +#endif // HCF_PROT_TIME + + +#if (HCF_DL_ONLY) == 0 +#if (HCF_TYPE) & HCF_TYPE_WPA +/************************************************************************************************************ +* +*.SUBMODULE int check_mic( IFBP ifbp ) +*.PURPOSE verifies the MIC of a received non-USB frame. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* +*.RETURNS +* HCF_SUCCESS +* HCF_ERR_MIC +* +*.DESCRIPTION +* +* +*.DIAGRAM +* +*4: test whether or not a MIC is reported by the Hermes +*14: the calculated MIC and the received MIC are compared, the return status is set when there is a mismatch +* +*.NOTICE +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +int +check_mic( IFBP ifbp ) +{ +int rc = HCF_SUCCESS; +hcf_32 x32[2]; //* area to save rcvd 8 bytes MIC + + //if MIC present in RxFS + if ( *(wci_recordp)&ifbp->IFB_lap[-HFS_ADDR_DEST] & HFS_STAT_MIC ) { + //or if ( ifbp->IFB_MICRxCarry != 0xFFFF ) + CALC_RX_MIC( mic_pad, 8 ); //. process up to 3 remaining bytes of data and append 5 to 8 bytes of padding to MIC calculation + get_frag( ifbp, (wci_bufp)x32, 8 BE_PAR(0));//. get 8 byte MIC from NIC + //. if calculated and received MIC do not match + //. . set status at HCF_ERR_MIC +/*14*/ if ( x32[0] != CNV_LITTLE_TO_LONG(ifbp->IFB_MICRx[0]) || + x32[1] != CNV_LITTLE_TO_LONG(ifbp->IFB_MICRx[1]) ) { + rc = HCF_ERR_MIC; + } + } + //return status + return rc; +} // check_mic +#endif // HCF_TYPE_WPA +#endif // HCF_DL_ONLY + + +/************************************************************************************************************ +* +*.SUBMODULE int cmd_cmpl( IFBP ifbp ) +*.PURPOSE waits for Hermes Command Completion. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* +*.RETURNS +* IFB_DefunctStat +* HCF_ERR_TIME_OUT +* HCF_ERR_DEFUNCT_CMD_SEQ +* HCF_SUCCESS +* +*.DESCRIPTION +* +* +*.DIAGRAM +* +*2: Once cmd_cmpl is called, the Busy option bit in IFB_Cmd must be cleared +*4: If Status register and command code don't match either: +* - the Hermes and Host are out of sync ( a fatal error) +* - error bits are reported via the Status Register. +* Out of sync is considered fatal and brings the HCF in Defunct mode +* Errors reported via the Status Register should be caused by sequence violations in Hermes command +* sequences and hence these bugs should have been found during engineering testing. Since there is no +* strategy to cope with this problem, it might as well be ignored at run time. Note that for any particular +* situation where a strategy is formulated to handle the consequences of a particular bug causing a +* particular Error situation reported via the Status Register, the bug should be removed rather than adding +* logic to cope with the consequences of the bug. +* There have been HCF versions where an error report via the Status Register even brought the HCF in defunct +* mode (although it was not yet named like that at that time). This is particular undesirable behavior for a +* general library. +* Simply reporting the error (as "interesting") is debatable. There also have been HCF versions with this +* strategy using the "vague" HCF_FAILURE code. +* The error is reported via: +* - MiscErr tally of the HCF Tally set +* - the (informative) fields IFB_ErrCmd and IFB_ErrQualifier +* - the assert mechanism +*8: Here the Defunct case and the Status error are separately treated +* +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +HCF_STATIC int +cmd_cmpl( IFBP ifbp ) +{ + +PROT_CNT_INI +int rc = HCF_SUCCESS; +hcf_16 stat; + + HCFLOGENTRY( HCF_TRACE_CMD_CPL, ifbp->IFB_Cmd ) + ifbp->IFB_Cmd &= ~HCMD_BUSY; /* 2 */ + HCF_WAIT_WHILE( (IPW( HREG_EV_STAT) & HREG_EV_CMD) == 0 ); /* 4 */ + stat = IPW( HREG_STAT ); +#if HCF_PROT_TIME + if ( prot_cnt == 0 ) { + IF_TALLY( ifbp->IFB_HCF_Tallies.MiscErr++; ) + rc = HCF_ERR_TIME_OUT; + HCFASSERT( DO_ASSERT, ifbp->IFB_Cmd ) + } else +#endif // HCF_PROT_TIME + { + DAWA_ACK( HREG_EV_CMD ); +/*4*/ if ( stat != (ifbp->IFB_Cmd & HCMD_CMD_CODE) ) { +/*8*/ if ( ( (stat ^ ifbp->IFB_Cmd ) & HCMD_CMD_CODE) != 0 ) { + rc = ifbp->IFB_DefunctStat = HCF_ERR_DEFUNCT_CMD_SEQ; + ifbp->IFB_CardStat |= CARD_STAT_DEFUNCT; + } + IF_TALLY( ifbp->IFB_HCF_Tallies.MiscErr++; ) + ifbp->IFB_ErrCmd = stat; + ifbp->IFB_ErrQualifier = IPW( HREG_RESP_0 ); + HCFASSERT( DO_ASSERT, MERGE_2( IPW( HREG_PARAM_0 ), ifbp->IFB_Cmd ) ) + HCFASSERT( DO_ASSERT, MERGE_2( ifbp->IFB_ErrQualifier, ifbp->IFB_ErrCmd ) ) + } + } + HCFASSERT( rc == HCF_SUCCESS, rc) + HCFLOGEXIT( HCF_TRACE_CMD_CPL ) + return rc; +} // cmd_cmpl + + +/************************************************************************************************************ +* +*.SUBMODULE int cmd_exe( IFBP ifbp, int cmd_code, int par_0 ) +*.PURPOSE Executes synchronous part of Hermes Command and - optionally - waits for Command Completion. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* cmd_code +* par_0 +* +*.RETURNS +* IFB_DefunctStat +* HCF_ERR_DEFUNCT_CMD_SEQ +* HCF_SUCCESS +* HCF_ERR_TO_BE_ADDED <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +* +*.DESCRIPTION +* Executes synchronous Hermes Command and waits for Command Completion +* +* The general HCF strategy is to wait for command completion. As a consequence: +* - the read of the busy bit before writing the command register is superfluous +* - the Hermes requirement that no Inquiry command may be executed if there is still an unacknowledged +* Inquiry command outstanding, is automatically met. +* The Tx command uses the "Busy" bit in the cmd_code parameter to deviate from this general HCF strategy. +* The idea is that by not busy-waiting on completion of this frequently used command the processor +* utilization is diminished while using the busy-wait on all other seldom used commands the flow is kept +* simple. +* +* +* +*.DIAGRAM +* +*1: skip the body of cmd_exe when in defunct mode or when - based on the S/W Support register write and +* read back test - there is apparently no NIC. +* Note: we gave up on the "old" strategy to write the S/W Support register at magic only when needed. Due to +* the intricateness of Hermes F/W varieties ( which behave differently as far as corruption of the S/W +* Support register is involved), the increasing number of Hermes commands which do an implicit initialize +* (thus modifying the S/W Support register) and the workarounds of some OS/Support S/W induced aspects (e.g. +* the System Soft library at WinNT which postpones the actual mapping of I/O space up to 30 seconds after +* giving the go-ahead), the "magic" strategy is now reduced to a simple write and read back. This means that +* problems like a bug tramping over the memory mapped Hermes registers will no longer be noticed as side +* effect of the S/W Support register check. +*2: check whether the preceding command skipped the busy wait and if so, check for command completion +* +*.NOTICE +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ + +HCF_STATIC int +cmd_exe( IFBP ifbp, hcf_16 cmd_code, hcf_16 par_0 ) //if HCMD_BUSY of cmd_code set, then do NOT wait for completion +{ +int rc; + + HCFLOGENTRY( HCF_TRACE_CMD_EXE, cmd_code ) + HCFASSERT( (cmd_code & HCMD_CMD_CODE) != HCMD_TX || cmd_code & HCMD_BUSY, cmd_code ) //Tx must have Busy bit set + OPW( HREG_SW_0, HCF_MAGIC ); + if ( IPW( HREG_SW_0 ) == HCF_MAGIC ) { /* 1 */ + rc = ifbp->IFB_DefunctStat; + } + else rc = HCF_ERR_NO_NIC; + if ( rc == HCF_SUCCESS ) { + //;?is this a hot idea, better MEASURE performance impact +/*2*/ if ( ifbp->IFB_Cmd & HCMD_BUSY ) { + rc = cmd_cmpl( ifbp ); + } + OPW( HREG_PARAM_0, par_0 ); + OPW( HREG_CMD, cmd_code &~HCMD_BUSY ); + ifbp->IFB_Cmd = cmd_code; + if ( (cmd_code & HCMD_BUSY) == 0 ) { //;?is this a hot idea, better MEASURE performance impact + rc = cmd_cmpl( ifbp ); + } + } + HCFASSERT( rc == HCF_SUCCESS, MERGE_2( rc, cmd_code ) ) + HCFLOGEXIT( HCF_TRACE_CMD_EXE ) + return rc; +} // cmd_exe + + +/************************************************************************************************************ +* +*.SUBMODULE int download( IFBP ifbp, CFG_PROG_STRCT FAR *ltvp ) +*.PURPOSE downloads F/W image into NIC and initiates execution of the downloaded F/W. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* ltvp specifies the pseudo-RID (as defined by WCI) +* +*.RETURNS +* +*.DESCRIPTION +* +* +*.DIAGRAM +*1: First, Ack everything to unblock a (possibly) blocked cmd pipe line +* Note 1: it is very likely that an Alloc event is pending and very well possible that a (Send) Cmd event is +* pending +* Note 2: it is assumed that this strategy takes away the need to ack every conceivable event after an +* Hermes Initialize +* +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +HCF_STATIC int +download( IFBP ifbp, CFG_PROG_STRCT FAR *ltvp ) //Hermes-II download (volatile only) +{ +hcf_16 i; +int rc = HCF_SUCCESS; +wci_bufp cp; +hcf_io io_port = ifbp->IFB_IOBase + HREG_AUX_DATA; + + HCFLOGENTRY( HCF_TRACE_DL, ltvp->typ ) +#if (HCF_TYPE) & HCF_TYPE_PRELOADED + HCFASSERT( DO_ASSERT, ltvp->mode ) +#else + //if initial "program" LTV + if ( ifbp->IFB_DLMode == CFG_PROG_STOP && ltvp->mode == CFG_PROG_VOLATILE) { + //. switch Hermes to initial mode +/*1*/ OPW( HREG_EV_ACK, ~HREG_EV_SLEEP_REQ ); + rc = cmd_exe( ifbp, HCMD_INI, 0 ); /* HCMD_INI can not be part of init() because that is called on + * other occasions as well */ + rc = init( ifbp ); + } + //if final "program" LTV + if ( ltvp->mode == CFG_PROG_STOP && ifbp->IFB_DLMode == CFG_PROG_VOLATILE) { + //. start tertiary (or secondary) + OPW( HREG_PARAM_1, (hcf_16)(ltvp->nic_addr >> 16) ); + rc = cmd_exe( ifbp, HCMD_EXECUTE, (hcf_16) ltvp->nic_addr ); + if (rc == HCF_SUCCESS) { + rc = init( ifbp ); /*;? do we really want to skip init if cmd_exe failed, i.e. + * IFB_FW_Comp_Id is than possibly incorrect */ + } + //else (non-final) + } else { + //. if mode == Readback SEEPROM +#if 0 //;? as long as the next if contains a hard coded 0, might as well leave it out even more obvious + if ( 0 /*len is definitely not want we want;?*/ && ltvp->mode == CFG_PROG_SEEPROM_READBACK ) { + OPW( HREG_PARAM_1, (hcf_16)(ltvp->nic_addr >> 16) ); + OPW( HREG_PARAM_2, MUL_BY_2(ltvp->len - 4)); + //. . perform Hermes prog cmd with appropriate mode bits + rc = cmd_exe( ifbp, HCMD_PROGRAM | ltvp->mode, (hcf_16)ltvp->nic_addr ); + //. . set up NIC RAM addressability according Resp0-1 + OPW( HREG_AUX_PAGE, IPW( HREG_RESP_1) ); + OPW( HREG_AUX_OFFSET, IPW( HREG_RESP_0) ); + //. . set up L-field of LTV according Resp2 + i = ( IPW( HREG_RESP_2 ) + 1 ) / 2; // i contains max buffer size in words, a probably not very useful piece of information ;? +/*Nico's code based on i is the "real amount of data available" + if ( ltvp->len - 4 < i ) rc = HCF_ERR_LEN; + else ltvp->len = i + 4; +*/ +/* Rolands code based on the idea that a MSF should not ask for more than is available + // check if number of bytes requested exceeds max buffer size + if ( ltvp->len - 4 > i ) { + rc = HCF_ERR_LEN; + ltvp->len = i + 4; + } +*/ + //. . copy data from NIC via AUX port to LTV + cp = (wci_bufp)ltvp->host_addr; /*IN_PORT_STRING_8_16 macro may modify its parameters*/ + i = ltvp->len - 4; + IN_PORT_STRING_8_16( io_port, cp, i ); //!!!WORD length, cp MUST be a char pointer // $$ char + //. else (non-final programming) + } else +#endif //;? as long as the above if contains a hard coded 0, might as well leave it out even more obvious + { //. . get number of words to program + HCFASSERT( ltvp->segment_size, *ltvp->host_addr ) + i = ltvp->segment_size/2; + //. . copy data (words) from LTV via AUX port to NIC + cp = (wci_bufp)ltvp->host_addr; //OUT_PORT_STRING_8_16 macro may modify its parameters + //. . if mode == volatile programming + if ( ltvp->mode == CFG_PROG_VOLATILE ) { + //. . . set up NIC RAM addressability via AUX port + OPW( HREG_AUX_PAGE, (hcf_16)(ltvp->nic_addr >> 16 << 9 | (ltvp->nic_addr & 0xFFFF) >> 7 ) ); + OPW( HREG_AUX_OFFSET, (hcf_16)(ltvp->nic_addr & 0x007E) ); + OUT_PORT_STRING_8_16( io_port, cp, i ); //!!!WORD length, cp MUST be a char pointer + } + } + } + ifbp->IFB_DLMode = ltvp->mode; //save state in IFB_DLMode +#endif // HCF_TYPE_PRELOADED + HCFASSERT( rc == HCF_SUCCESS, rc ) + HCFLOGEXIT( HCF_TRACE_DL ) + return rc; +} // download + + +#if (HCF_ASSERT) & HCF_ASSERT_PRINTF +/************************************************** +* Certain Hermes-II firmware versions can generate +* debug information. This debug information is +* contained in a buffer in nic-RAM, and can be read +* via the aux port. +**************************************************/ +HCF_STATIC int +fw_printf(IFBP ifbp, CFG_FW_PRINTF_STRCT FAR *ltvp) +{ + int rc = HCF_SUCCESS; + hcf_16 fw_cnt; +// hcf_32 DbMsgBuffer = 0x29D2, DbMsgCount= 0x000029D0; +// hcf_16 DbMsgSize=0x00000080; + hcf_32 DbMsgBuffer; + CFG_FW_PRINTF_BUFFER_LOCATION_STRCT *p = &ifbp->IFB_FwPfBuff; + ltvp->len = 1; + if ( p->DbMsgSize != 0 ) { + // first, check the counter in nic-RAM and compare it to the latest counter value of the HCF + OPW( HREG_AUX_PAGE, (hcf_16)(p->DbMsgCount >> 7) ); + OPW( HREG_AUX_OFFSET, (hcf_16)(p->DbMsgCount & 0x7E) ); + fw_cnt = ((IPW( HREG_AUX_DATA) >>1 ) & ((hcf_16)p->DbMsgSize - 1)); + if ( fw_cnt != ifbp->IFB_DbgPrintF_Cnt ) { +// DbgPrint("fw_cnt=%d IFB_DbgPrintF_Cnt=%d\n", fw_cnt, ifbp->IFB_DbgPrintF_Cnt); + DbMsgBuffer = p->DbMsgBuffer + ifbp->IFB_DbgPrintF_Cnt * 6; // each entry is 3 words + OPW( HREG_AUX_PAGE, (hcf_16)(DbMsgBuffer >> 7) ); + OPW( HREG_AUX_OFFSET, (hcf_16)(DbMsgBuffer & 0x7E) ); + ltvp->msg_id = IPW(HREG_AUX_DATA); + ltvp->msg_par = IPW(HREG_AUX_DATA); + ltvp->msg_tstamp = IPW(HREG_AUX_DATA); + ltvp->len = 4; + ifbp->IFB_DbgPrintF_Cnt++; + ifbp->IFB_DbgPrintF_Cnt &= (p->DbMsgSize - 1); + } + } + return rc; +}; +#endif // HCF_ASSERT_PRINTF + + +#if (HCF_DL_ONLY) == 0 +/************************************************************************************************************ +* +*.SUBMODULE hcf_16 get_fid( IFBP ifbp ) +*.PURPOSE get allocated FID for either transmit or notify. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* +*.RETURNS +* 0 no FID available +* <>0 FID number +* +*.DESCRIPTION +* +* +*.DIAGRAM +* The preference is to use a "pending" alloc. If no alloc is pending, then - if available - the "spare" FID +* is used. +* If the spare FID is used, IFB_RscInd (representing the spare FID) must be cleared +* If the pending alloc is used, the alloc event must be acknowledged to the Hermes. +* In case the spare FID was depleted and the IFB_RscInd has been "faked" as pseudo resource with a 0x0001 +* value by hcf_service_nic, IFB_RscInd has to be "corrected" again to its 0x0000 value. +* +* Note that due to the Hermes-II H/W problems which are intended to be worked around by DAWA, the Alloc bit +* in the Event register is no longer a reliable indication of the presence/absence of a FID. The "Clear FID" +* part of the DAWA logic, together with the choice of the definition of the return information from get_fid, +* handle this automatically, i.e. without additional code in get_fid. +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +HCF_STATIC hcf_16 +get_fid( IFBP ifbp ) +{ + +hcf_16 fid = 0; +#if ( (HCF_TYPE) & HCF_TYPE_HII5 ) == 0 +PROT_CNT_INI +#endif // HCF_TYPE_HII5 + + IF_DMA( HCFASSERT(!(ifbp->IFB_CntlOpt & USE_DMA), ifbp->IFB_CntlOpt) ) + + if ( IPW( HREG_EV_STAT) & HREG_EV_ALLOC) { + fid = IPW( HREG_ALLOC_FID ); + HCFASSERT( fid, ifbp->IFB_RscInd ) + DAWA_ZERO_FID( HREG_ALLOC_FID ) +#if ( (HCF_TYPE) & HCF_TYPE_HII5 ) == 0 + HCF_WAIT_WHILE( ( IPW( HREG_EV_STAT ) & HREG_EV_ACK_REG_READY ) == 0 ); + HCFASSERT( prot_cnt, IPW( HREG_EV_STAT ) ) +#endif // HCF_TYPE_HII5 + DAWA_ACK( HREG_EV_ALLOC ); //!!note that HREG_EV_ALLOC is written only once +// 180 degree error in logic ;? #if ALLOC_15 + if ( ifbp->IFB_RscInd == 1 ) { + ifbp->IFB_RscInd = 0; + } +//#endif // ALLOC_15 + } else { +// 180 degree error in logic ;? #if ALLOC_15 + fid = ifbp->IFB_RscInd; +//#endif // ALLOC_15 + ifbp->IFB_RscInd = 0; + } + return fid; +} // get_fid +#endif // HCF_DL_ONLY + + +/************************************************************************************************************ +* +*.SUBMODULE void get_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) ) +*.PURPOSE reads with 16/32 bit I/O via BAP1 port from NIC RAM to Host memory. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* bufp (byte) address of buffer +* len length in bytes of buffer specified by bufp +* word_len Big Endian only: number of leading bytes to swap in pairs +* +*.RETURNS N.A. +* +*.DESCRIPTION +* process the single byte (if applicable) read by the previous get_frag and copy len (or len-1) bytes from +* NIC to bufp. +* On a Big Endian platform, the parameter word_len controls the number of leading bytes whose endianess is +* converted (i.e. byte swapped) +* +* +*.DIAGRAM +*10: The PCMCIA card can be removed in the middle of the transfer. By depositing a "magic number" in the +* HREG_SW_0 register of the Hermes at initialization time and by verifying this register, it can be +* determined whether the card is still present. The return status is set accordingly. +* Clearing the buffer is a (relative) cheap way to prevent that failing I/O results in run-away behavior +* because the garbage in the buffer is interpreted by the caller irrespective of the return status (e.g. +* hcf_service_nic has this behavior). +* +*.NOTICE +* It turns out DOS ODI uses zero length fragments. The HCF code can cope with it, but as a consequence, no +* Assert on len is possible +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +HCF_STATIC void +get_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) ) +{ +hcf_io io_port = ifbp->IFB_IOBase + HREG_DATA_1; //BAP data register +wci_bufp p = bufp; //working pointer +int i; //prevent side effects from macro +int j; + + HCFASSERT( ((hcf_32)bufp & (HCF_ALIGN-1) ) == 0, (hcf_32)bufp ) + +/*1: here recovery logic for intervening BAP access between hcf_service_nic and hcf_rcv_msg COULD be added + * if current access is RxInitial + * . persistent_offset += len + */ + + i = len; + //if buffer length > 0 and carry from previous get_frag + if ( i && ifbp->IFB_CarryIn ) { + //. move carry to buffer + //. adjust buffer length and pointer accordingly + *p++ = (hcf_8)(ifbp->IFB_CarryIn>>8); + i--; + //. clear carry flag + ifbp->IFB_CarryIn = 0; + } +#if (HCF_IO) & HCF_IO_32BITS + //skip zero-length I/O, single byte I/O and I/O not worthwhile (i.e. less than 6 bytes)for DW logic + //if buffer length >= 6 and 32 bits I/O support + if ( !(ifbp->IFB_CntlOpt & USE_16BIT) && i >= 6 ) { +hcf_32 FAR *p4; //prevent side effects from macro + if ( ( (hcf_32)p & 0x1 ) == 0 ) { //. if buffer at least word aligned + if ( (hcf_32)p & 0x2 ) { //. . if buffer not double word aligned + //. . . read single word to get double word aligned + *(wci_recordp)p = IN_PORT_WORD( io_port ); + //. . . adjust buffer length and pointer accordingly + p += 2; + i -= 2; + } + //. . read as many double word as possible + p4 = (hcf_32 FAR *)p; + j = i/4; + IN_PORT_STRING_32( io_port, p4, j ); + //. . adjust buffer length and pointer accordingly + p += i & ~0x0003; + i &= 0x0003; + } + } +#endif // HCF_IO_32BITS + //if no 32-bit support OR byte aligned OR 1-3 bytes left + if ( i ) { + //. read as many word as possible in "alignment safe" way + j = i/2; + IN_PORT_STRING_8_16( io_port, p, j ); + //. if 1 byte left + if ( i & 0x0001 ) { + //. . read 1 word + ifbp->IFB_CarryIn = IN_PORT_WORD( io_port ); + //. . store LSB in last char of buffer + bufp[len-1] = (hcf_8)ifbp->IFB_CarryIn; + //. . save MSB in carry, set carry flag + ifbp->IFB_CarryIn |= 0x1; + } + } +#if HCF_BIG_ENDIAN + HCFASSERT( word_len == 0 || word_len == 2 || word_len == 4, word_len ) + HCFASSERT( word_len == 0 || ((hcf_32)bufp & 1 ) == 0, (hcf_32)bufp ) + HCFASSERT( word_len <= len, MERGE2( word_len, len ) ) + //see put_frag for an alternative implementation, but be carefull about what are int's and what are + //hcf_16's + if ( word_len ) { //. if there is anything to convert +hcf_8 c; + c = bufp[1]; //. . convert the 1st hcf_16 + bufp[1] = bufp[0]; + bufp[0] = c; + if ( word_len > 1 ) { //. . if there is to convert more than 1 word ( i.e 2 ) + c = bufp[3]; //. . . convert the 2nd hcf_16 + bufp[3] = bufp[2]; + bufp[2] = c; + } + } +#endif // HCF_BIG_ENDIAN +} // get_frag + +/************************************************************************************************************ +* +*.SUBMODULE int init( IFBP ifbp ) +*.PURPOSE Handles common initialization aspects (H-I init, calibration, config.mngmt, allocation). +* +*.ARGUMENTS +* ifbp address of the Interface Block +* +*.RETURNS +* HCF_ERR_INCOMP_PRI +* HCF_ERR_INCOMP_FW +* HCF_ERR_TIME_OUT +* >>hcf_get_info +* HCF_ERR_NO_NIC +* HCF_ERR_LEN +* +*.DESCRIPTION +* init will successively: +* - in case of a (non-preloaded) H-I, initialize the NIC +* - calibrate the S/W protection timer against the Hermes Timer +* - collect HSI, "active" F/W Configuration Management Information +* - in case active F/W is Primary F/W: collect Primary F/W Configuration Management Information +* - check HSI and Primary F/W compatibility with the HCF +* - in case active F/W is Station or AP F/W: check Station or AP F/W compatibility with the HCF +* - in case active F/W is not Primary F/W: allocate FIDs to be used in transmit/notify process +* +* +*.DIAGRAM +*2: drop all error status bits in IFB_CardStat since they are expected to be re-evaluated. +*4: Ack everything except HREG_EV_SLEEP_REQ. It is very likely that an Alloc event is pending and +* very well possible that a Send Cmd event is pending. Acking HREG_EV_SLEEP_REQ is handled by hcf_action( +* HCF_ACT_INT_ON ) !!! +*10: Calibrate the S/W time-out protection mechanism by calling calibrate(). Note that possible errors +* in the calibration process are nor reported by init but will show up via the defunct mechanism in +* subsequent hcf-calls. +*14: usb_check_comp() is called to have the minimal visual clutter for the legacy H-I USB dongle +* compatibility check. +*16: The following configuration management related information is retrieved from the NIC: +* - HSI supplier +* - F/W Identity +* - F/W supplier +* if appropriate: +* - PRI Identity +* - PRI supplier +* appropriate means on H-I: always +* and on H-II if F/W supplier reflects a primary (i.e. only after an Hermes Reset or Init +* command). +* QUESTION ;? !!!!!! should, For each of the above RIDs the Endianess is converted to native Endianess. +* Only the return code of the first hcf_get_info is used. All hcf_get_info calls are made, regardless of +* the success or failure of the 1st hcf_get_info. The assumptions are: +* - if any call fails, they all fail, so remembering the result of the 1st call is adequate +* - a failing call will overwrite the L-field with a 0x0000 value, which services both as an +* error indication for the values cached in the IFB as making mmd_check_comp fail. +* In case of H-I, when getting the F/W identity fails, the F/W is assumed to be H-I AP F/W pre-dating +* version 9.0 and the F/W Identity and Supplier are faked accordingly. +* In case of H-II, the Primary, Station and AP Identity are merged into a single F/W Identity. +* The same applies to the Supplier information. As a consequence the PRI information can no longer be +* retrieved when a Tertiary runs. To accommodate MSFs and Utilities who depend on PRI information being +* available at any time, this information is cached in the IFB. In this cache the generic "F/W" value of +* the typ-fields is overwritten with the specific (legacy) "PRI" values. To actually re-route the (legacy) +* PRI request via hcf_get_info, the xxxx-table must be set. In case of H-I, this caching, modifying and +* re-routing is not needed because PRI information is always available directly from the NIC. For +* consistency the caching fields in the IFB are filled with the PRI information anyway. +*18: mdd_check_comp() is called to check the Supplier Variant and Range of the Host-S/W I/F (HSI) and the +* Primary Firmware Variant and Range against the Top and Bottom level supported by this HCF. If either of +* these tests fails, the CARD_STAT_INCOMP_PRI bit of IFB_CardStat is set +* Note: There should always be a primary except during production, so this makes the HCF in its current form +* unsuitable for manufacturing test systems like the FTS. This can be remedied by an adding a test like +* ifbp->IFB_PRISup.id == COMP_ID_PRI +*20: In case there is Tertiary F/W and this F/W is Station F/W, the Supplier Variant and Range of the Station +* Firmware function as retrieved from the Hermes is checked against the Top and Bottom level supported by +* this HCF. +* Note: ;? the tertiary F/W compatibility checks could be moved to the DHF, which already has checked the +* CFI and MFI compatibility of the image with the NIC before the image was downloaded. +*28: In case of non-Primary F/W: allocates and acknowledge a (TX or Notify) FID and allocates without +* acknowledge another (TX or Notify) FID (the so-called 1.5 alloc scheme) with the following steps: +* - execute the allocate command by calling cmd_exe +* - wait till either the alloc event or a time-out occurs +* - regardless whether the alloc event occurs, call get_fid to +* - read the FID and save it in IFB_RscInd to be used as "spare FID" +* - acknowledge the alloc event +* - do another "half" allocate to complete the "1.5 Alloc scheme" +* Note that above 3 steps do not harm and thus give the "cheapest" acceptable strategy. +* If a time-out occurred, then report time out status (after all) +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +HCF_STATIC int +init( IFBP ifbp ) +{ + +int rc = HCF_SUCCESS; + + HCFLOGENTRY( HCF_TRACE_INIT, 0 ) + + ifbp->IFB_CardStat = 0; /* 2*/ + OPW( HREG_EV_ACK, ~HREG_EV_SLEEP_REQ ); /* 4*/ + IF_PROT_TIME( calibrate( ifbp ); ) /*10*/ +#if 0 // OOR + ifbp->IFB_FWIdentity.len = 2; //misuse the IFB space for a put + ifbp->IFB_FWIdentity.typ = CFG_TICK_TIME; + ifbp->IFB_FWIdentity.comp_id = (1000*1000)/1024 + 1; //roughly 1 second + hcf_put_info( ifbp, (LTVP)&ifbp->IFB_FWIdentity.len ); +#endif // OOR + ifbp->IFB_FWIdentity.len = sizeof(CFG_FW_IDENTITY_STRCT)/sizeof(hcf_16) - 1; + ifbp->IFB_FWIdentity.typ = CFG_FW_IDENTITY; + rc = hcf_get_info( ifbp, (LTVP)&ifbp->IFB_FWIdentity.len ); +/* ;? conversion should not be needed for mmd_check_comp */ +#if HCF_BIG_ENDIAN + ifbp->IFB_FWIdentity.comp_id = CNV_LITTLE_TO_SHORT( ifbp->IFB_FWIdentity.comp_id ); + ifbp->IFB_FWIdentity.variant = CNV_LITTLE_TO_SHORT( ifbp->IFB_FWIdentity.variant ); + ifbp->IFB_FWIdentity.version_major = CNV_LITTLE_TO_SHORT( ifbp->IFB_FWIdentity.version_major ); + ifbp->IFB_FWIdentity.version_minor = CNV_LITTLE_TO_SHORT( ifbp->IFB_FWIdentity.version_minor ); +#endif // HCF_BIG_ENDIAN +#if defined MSF_COMPONENT_ID /*14*/ + if ( rc == HCF_SUCCESS ) { /*16*/ + ifbp->IFB_HSISup.len = sizeof(CFG_SUP_RANGE_STRCT)/sizeof(hcf_16) - 1; + ifbp->IFB_HSISup.typ = CFG_NIC_HSI_SUP_RANGE; + rc = hcf_get_info( ifbp, (LTVP)&ifbp->IFB_HSISup.len ); +/* ;? conversion should not be needed for mmd_check_comp , BUT according to a report of a BE-user it is + * should be resolved in the WARP release + * since some compilers make ugly but unnecessary code of these instructions even for LE, + * it is conditionally compiled */ +#if HCF_BIG_ENDIAN + ifbp->IFB_HSISup.role = CNV_LITTLE_TO_SHORT( ifbp->IFB_HSISup.role ); + ifbp->IFB_HSISup.id = CNV_LITTLE_TO_SHORT( ifbp->IFB_HSISup.id ); + ifbp->IFB_HSISup.variant = CNV_LITTLE_TO_SHORT( ifbp->IFB_HSISup.variant ); + ifbp->IFB_HSISup.bottom = CNV_LITTLE_TO_SHORT( ifbp->IFB_HSISup.bottom ); + ifbp->IFB_HSISup.top = CNV_LITTLE_TO_SHORT( ifbp->IFB_HSISup.top ); +#endif // HCF_BIG_ENDIAN + ifbp->IFB_FWSup.len = sizeof(CFG_SUP_RANGE_STRCT)/sizeof(hcf_16) - 1; + ifbp->IFB_FWSup.typ = CFG_FW_SUP_RANGE; + (void)hcf_get_info( ifbp, (LTVP)&ifbp->IFB_FWSup.len ); +/* ;? conversion should not be needed for mmd_check_comp */ +#if HCF_BIG_ENDIAN + ifbp->IFB_FWSup.role = CNV_LITTLE_TO_SHORT( ifbp->IFB_FWSup.role ); + ifbp->IFB_FWSup.id = CNV_LITTLE_TO_SHORT( ifbp->IFB_FWSup.id ); + ifbp->IFB_FWSup.variant = CNV_LITTLE_TO_SHORT( ifbp->IFB_FWSup.variant ); + ifbp->IFB_FWSup.bottom = CNV_LITTLE_TO_SHORT( ifbp->IFB_FWSup.bottom ); + ifbp->IFB_FWSup.top = CNV_LITTLE_TO_SHORT( ifbp->IFB_FWSup.top ); +#endif // HCF_BIG_ENDIAN + + if ( ifbp->IFB_FWSup.id == COMP_ID_PRI ) { /* 20*/ +int i = sizeof( CFG_FW_IDENTITY_STRCT) + sizeof(CFG_SUP_RANGE_STRCT ); + while ( i-- ) ((hcf_8*)(&ifbp->IFB_PRIIdentity))[i] = ((hcf_8*)(&ifbp->IFB_FWIdentity))[i]; + ifbp->IFB_PRIIdentity.typ = CFG_PRI_IDENTITY; + ifbp->IFB_PRISup.typ = CFG_PRI_SUP_RANGE; + xxxx[xxxx_PRI_IDENTITY_OFFSET] = &ifbp->IFB_PRIIdentity.len; + xxxx[xxxx_PRI_IDENTITY_OFFSET+1] = &ifbp->IFB_PRISup.len; + } + if ( !mmd_check_comp( (void*)&cfg_drv_act_ranges_hsi, &ifbp->IFB_HSISup) /* 22*/ +#if ( (HCF_TYPE) & HCF_TYPE_PRELOADED ) == 0 +//;? the PRI compatibility check is only relevant for DHF + || !mmd_check_comp( (void*)&cfg_drv_act_ranges_pri, &ifbp->IFB_PRISup) +#endif // HCF_TYPE_PRELOADED + ) { + ifbp->IFB_CardStat = CARD_STAT_INCOMP_PRI; + rc = HCF_ERR_INCOMP_PRI; + } + if ( ( ifbp->IFB_FWSup.id == COMP_ID_STA && !mmd_check_comp( (void*)&cfg_drv_act_ranges_sta, &ifbp->IFB_FWSup) ) || + ( ifbp->IFB_FWSup.id == COMP_ID_APF && !mmd_check_comp( (void*)&cfg_drv_act_ranges_apf, &ifbp->IFB_FWSup) ) + ) { /* 24 */ + ifbp->IFB_CardStat |= CARD_STAT_INCOMP_FW; + rc = HCF_ERR_INCOMP_FW; + } + } +#endif // MSF_COMPONENT_ID +#if (HCF_DL_ONLY) == 0 /* 28 */ + if ( rc == HCF_SUCCESS && ifbp->IFB_FWIdentity.comp_id >= COMP_ID_FW_STA ) { +PROT_CNT_INI + /************************************************************************************** + * rlav: the DMA engine needs the host to cause a 'hanging alloc event' for it to consume. + * not sure if this is the right spot in the HCF, thinking about hcf_enable... + **************************************************************************************/ + rc = cmd_exe( ifbp, HCMD_ALLOC, 0 ); +// 180 degree error in logic ;? #if ALLOC_15 +// ifbp->IFB_RscInd = 1; //let's hope that by the time hcf_send_msg isa called, there will be a FID +//#else + if ( rc == HCF_SUCCESS ) { + HCF_WAIT_WHILE( (IPW( HREG_EV_STAT ) & HREG_EV_ALLOC) == 0 ); + IF_PROT_TIME( HCFASSERT(prot_cnt, IPW( HREG_EV_STAT ) ) /*NOP*/;) +#if HCF_DMA + if ( ! ( ifbp->IFB_CntlOpt & USE_DMA ) ) +#endif // HCF_DMA + { + ifbp->IFB_RscInd = get_fid( ifbp ); + HCFASSERT( ifbp->IFB_RscInd, 0 ) + cmd_exe( ifbp, HCMD_ALLOC, 0 ); + IF_PROT_TIME( if ( prot_cnt == 0 ) rc = HCF_ERR_TIME_OUT; ) + } + } +//#endif // ALLOC_15 + } +#endif // HCF_DL_ONLY + HCFASSERT( rc == HCF_SUCCESS, rc ) + HCFLOGEXIT( HCF_TRACE_INIT ) + return rc; +} // init + +#if (HCF_DL_ONLY) == 0 +/************************************************************************************************************ +* +*.SUBMODULE void isr_info( IFBP ifbp ) +*.PURPOSE handles link events. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* +*.RETURNS N.A. +* +*.DESCRIPTION +* +* +*.DIAGRAM +*1: First the FID number corresponding with the InfoEvent is determined. +* Note the complication of the zero-FID protection sub-scheme in DAWA. +* Next the L-field and the T-field are fetched into scratch buffer info. +*2: In case of tallies, the 16 bits Hermes values are accumulated in the IFB into 32 bits values. Info[0] +* is (expected to be) HCF_NIC_TAL_CNT + 1. The contraption "while ( info[0]-- >1 )" rather than +* "while ( --info[0] )" is used because it is dangerous to determine the length of the Value field by +* decrementing info[0]. As a result of a bug in some version of the F/W, info[0] may be 0, resulting +* in a very long loop in the pre-decrement logic. +*4: In case of a link status frame, the information is copied to the IFB field IFB_linkStat +*6: All other than Tallies (including "unknown" ones) are checked against the selection set by the MSF +* via CFG_RID_LOG. If a match is found or the selection set has the wild-card type (i.e non-NULL buffer +* pointer at the terminating zero-type), the frame is copied to the (type-specific) log buffer. +* Note that to accumulate tallies into IFB AND to log them or to log a frame when a specific match occures +* AND based on the wild-card selection, you have to call setup_bap again after the 1st copy. +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +HCF_STATIC void +isr_info( IFBP ifbp ) +{ +hcf_16 info[2], fid; +#if (HCF_EXT) & HCF_EXT_INFO_LOG +RID_LOGP ridp = ifbp->IFB_RIDLogp; //NULL or pointer to array of RID_LOG structures (terminated by zero typ) +#endif // HCF_EXT_INFO_LOG + + HCFTRACE( ifbp, HCF_TRACE_ISR_INFO ); /* 1 */ + fid = IPW( HREG_INFO_FID ); + DAWA_ZERO_FID( HREG_INFO_FID ) + if ( fid ) { + (void)setup_bap( ifbp, fid, 0, IO_IN ); + get_frag( ifbp, (wci_bufp)info, 4 BE_PAR(2) ); + HCFASSERT( info[0] <= HCF_MAX_LTV + 1, MERGE_2( info[1], info[0] ) ) //;? a smaller value makes more sense +#if (HCF_TALLIES) & HCF_TALLIES_NIC //Hermes tally support + if ( info[1] == CFG_TALLIES ) { +hcf_32 *p; +/*2*/ if ( info[0] > HCF_NIC_TAL_CNT ) { + info[0] = HCF_NIC_TAL_CNT + 1; + } + p = (hcf_32*)&ifbp->IFB_NIC_Tallies; + while ( info[0]-- >1 ) *p++ += IPW( HREG_DATA_1 ); //request may return zero length + } + else +#endif // HCF_TALLIES_NIC + { +/*4*/ if ( info[1] == CFG_LINK_STAT ) { + ifbp->IFB_LinkStat = IPW( HREG_DATA_1 ); + } +#if (HCF_EXT) & HCF_EXT_INFO_LOG +/*6*/ while ( 1 ) { + if ( ridp->typ == 0 || ridp->typ == info[1] ) { + if ( ridp->bufp ) { + HCFASSERT( ridp->len >= 2, ridp->typ ) + ridp->bufp[0] = min((hcf_16)(ridp->len - 1), info[0] ); //save L + ridp->bufp[1] = info[1]; //save T + get_frag( ifbp, (wci_bufp)&ridp->bufp[2], (ridp->bufp[0] - 1)*2 BE_PAR(0) ); + } + break; + } + ridp++; + } +#endif // HCF_EXT_INFO_LOG + } + HCFTRACE( ifbp, HCF_TRACE_ISR_INFO | HCF_TRACE_EXIT ); + } + return; +} // isr_info +#endif // HCF_DL_ONLY + +// +// +// #endif // HCF_TALLIES_NIC +// /*4*/ if ( info[1] == CFG_LINK_STAT ) { +// ifbp->IFB_DSLinkStat = IPW( HREG_DATA_1 ) | CFG_LINK_STAT_CHANGE; //corrupts BAP !! ;? +// ifbp->IFB_LinkStat = ifbp->IFB_DSLinkStat & CFG_LINK_STAT_FW; //;? to be obsoleted +// printk( "<4>linkstatus: %04x\n", ifbp->IFB_DSLinkStat ); //;?remove me 1 day +// #if (HCF_SLEEP) & HCF_DDS +// if ( ( ifbp->IFB_DSLinkStat & CFG_LINK_STAT_CONNECTED ) == 0 ) { //even values are disconnected etc. +// ifbp->IFB_TickCnt = 0; //start 2 second period (with 1 tick uncertanty) +// printk( "<5>isr_info: AwaitConnection phase started, IFB_TickCnt = 0\n" ); //;?remove me 1 day +// } +// #endif // HCF_DDS +// } +// #if (HCF_EXT) & HCF_EXT_INFO_LOG +// /*6*/ while ( 1 ) { +// if ( ridp->typ == 0 || ridp->typ == info[1] ) { +// if ( ridp->bufp ) { +// HCFASSERT( ridp->len >= 2, ridp->typ ) +// (void)setup_bap( ifbp, fid, 2, IO_IN ); //restore BAP for tallies, linkstat and specific type followed by wild card +// ridp->bufp[0] = min( ridp->len - 1, info[0] ); //save L +// get_frag( ifbp, (wci_bufp)&ridp->bufp[1], ridp->bufp[0]*2 BE_PAR(0) ); +// } +// break; //;?this break is no longer needed due to setup_bap but lets concentrate on DDS first +// } +// ridp++; +// } +// #endif // HCF_EXT_INFO_LOG +// } +// HCFTRACE( ifbp, HCF_TRACE_ISR_INFO | HCF_TRACE_EXIT ); +// +// +// +// +// return; +//} // isr_info +//#endif // HCF_DL_ONLY + + +/************************************************************************************************************ +* +*.SUBMODULE void mdd_assert( IFBP ifbp, unsigned int line_number, hcf_32 q ) +*.PURPOSE filters assert on level and interfaces to the MSF supplied msf_assert routine. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* line_number line number of the line which caused the assert +* q qualifier, additional information which may give a clue about the problem +* +*.RETURNS N.A. +* +*.DESCRIPTION +* +* +*.DIAGRAM +* +*.NOTICE +* mdd_assert has been through a turmoil, renaming hcf_assert to assert and hcf_assert again and supporting off +* and on being called from the MSF level and other ( immature ) ModularDriverDevelopment modules like DHF and +* MMD. + * !!!! The assert routine is not an hcf_..... routine in the sense that it may be called by the MSF, + * however it is called from mmd.c and dhf.c, so it must be external. + * To prevent namespace pollution it needs a prefix, to prevent that MSF programmers think that + * they are allowed to call the assert logic, the prefix HCF can't be used, so MDD is selected!!!! + * +* When called from the DHF module the line number is incremented by DHF_FILE_NAME_OFFSET and when called from +* the MMD module by MMD_FILE_NAME_OFFSET. +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +#if HCF_ASSERT +void +mdd_assert( IFBP ifbp, unsigned int line_number, hcf_32 q ) +{ +hcf_16 run_time_flag = ifbp->IFB_AssertLvl; + + if ( run_time_flag /* > ;?????? */ ) { //prevent recursive behavior, later to be extended to level filtering + ifbp->IFB_AssertQualifier = q; + ifbp->IFB_AssertLine = (hcf_16)line_number; +#if (HCF_ASSERT) & ( HCF_ASSERT_LNK_MSF_RTN | HCF_ASSERT_RT_MSF_RTN ) + if ( ifbp->IFB_AssertRtn ) { + ifbp->IFB_AssertRtn( line_number, ifbp->IFB_AssertTrace, q ); + } +#endif // HCF_ASSERT_LNK_MSF_RTN / HCF_ASSERT_RT_MSF_RTN +#if (HCF_ASSERT) & HCF_ASSERT_SW_SUP + OPW( HREG_SW_2, line_number ); + OPW( HREG_SW_2, ifbp->IFB_AssertTrace ); + OPW( HREG_SW_2, (hcf_16)q ); + OPW( HREG_SW_2, (hcf_16)(q >> 16 ) ); +#endif // HCF_ASSERT_SW_SUP + +#if (HCF_EXT) & HCF_EXT_MB && (HCF_ASSERT) & HCF_ASSERT_MB + ifbp->IFB_AssertLvl = 0; // prevent recursive behavior + hcf_put_info( ifbp, (LTVP)&ifbp->IFB_AssertStrct ); + ifbp->IFB_AssertLvl = run_time_flag; // restore appropriate filter level +#endif // HCF_EXT_MB / HCF_ASSERT_MB + } +} // mdd_assert +#endif // HCF_ASSERT + + +/************************************************************************************************************ +* +*.SUBMODULE void put_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) ) +*.PURPOSE writes with 16/32 bit I/O via BAP1 port from Host memory to NIC RAM. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* bufp (byte) address of buffer +* len length in bytes of buffer specified by bufp +* word_len Big Endian only: number of leading bytes to swap in pairs +* +*.RETURNS N.A. +* +*.DESCRIPTION +* process the single byte (if applicable) not yet written by the previous put_frag and copy len +* (or len-1) bytes from bufp to NIC. +* +* +*.DIAGRAM +* +*.NOTICE +* It turns out DOS ODI uses zero length fragments. The HCF code can cope with it, but as a consequence, no +* Assert on len is possible +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +HCF_STATIC void +put_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) ) +{ +hcf_io io_port = ifbp->IFB_IOBase + HREG_DATA_1; //BAP data register +int i; //prevent side effects from macro +hcf_16 j; + HCFASSERT( ((hcf_32)bufp & (HCF_ALIGN-1) ) == 0, (hcf_32)bufp ) +#if HCF_BIG_ENDIAN + HCFASSERT( word_len == 0 || word_len == 2 || word_len == 4, word_len ) + HCFASSERT( word_len == 0 || ((hcf_32)bufp & 1 ) == 0, (hcf_32)bufp ) + HCFASSERT( word_len <= len, MERGE_2( word_len, len ) ) + + if ( word_len ) { //if there is anything to convert + //. convert and write the 1st hcf_16 + j = bufp[1] | bufp[0]<<8; + OUT_PORT_WORD( io_port, j ); + //. update pointer and counter accordingly + len -= 2; + bufp += 2; + if ( word_len > 1 ) { //. if there is to convert more than 1 word ( i.e 2 ) + //. . convert and write the 2nd hcf_16 + j = bufp[1] | bufp[0]<<8; /*bufp is already incremented by 2*/ + OUT_PORT_WORD( io_port, j ); + //. . update pointer and counter accordingly + len -= 2; + bufp += 2; + } + } +#endif // HCF_BIG_ENDIAN + i = len; + if ( i && ifbp->IFB_CarryOut ) { //skip zero-length + j = ((*bufp)<<8) + ( ifbp->IFB_CarryOut & 0xFF ); + OUT_PORT_WORD( io_port, j ); + bufp++; i--; + ifbp->IFB_CarryOut = 0; + } +#if (HCF_IO) & HCF_IO_32BITS + //skip zero-length I/O, single byte I/O and I/O not worthwhile (i.e. less than 6 bytes)for DW logic + //if buffer length >= 6 and 32 bits I/O support + if ( !(ifbp->IFB_CntlOpt & USE_16BIT) && i >= 6 ) { +hcf_32 FAR *p4; //prevent side effects from macro + if ( ( (hcf_32)bufp & 0x1 ) == 0 ) { //. if buffer at least word aligned + if ( (hcf_32)bufp & 0x2 ) { //. . if buffer not double word aligned + //. . . write a single word to get double word aligned + j = *(wci_recordp)bufp; //just to help ease writing macros with embedded assembly + OUT_PORT_WORD( io_port, j ); + //. . . adjust buffer length and pointer accordingly + bufp += 2; i -= 2; + } + //. . write as many double word as possible + p4 = (hcf_32 FAR *)bufp; + j = (hcf_16)i/4; + OUT_PORT_STRING_32( io_port, p4, j ); + //. . adjust buffer length and pointer accordingly + bufp += i & ~0x0003; + i &= 0x0003; + } + } +#endif // HCF_IO_32BITS + //if no 32-bit support OR byte aligned OR 1 word left + if ( i ) { + //. if odd number of bytes left + if ( i & 0x0001 ) { + //. . save left over byte (before bufp is corrupted) in carry, set carry flag + ifbp->IFB_CarryOut = (hcf_16)bufp[i-1] | 0x0100; //note that i and bufp are always simultaneously modified, &bufp[i-1] is invariant + } + //. write as many word as possible in "alignment safe" way + j = (hcf_16)i/2; + OUT_PORT_STRING_8_16( io_port, bufp, j ); + } +} // put_frag + + +/************************************************************************************************************ +* +*.SUBMODULE void put_frag_finalize( IFBP ifbp ) +*.PURPOSE cleanup after put_frag for trailing odd byte and MIC transfer to NIC. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* +*.RETURNS N.A. +* +*.DESCRIPTION +* finalize the MIC calculation with the padding pattern, output the last byte (if applicable) +* of the message and the MIC to the TxFS +* +* +*.DIAGRAM +*2: 1 byte of the last put_frag may be still in IFB_CarryOut ( the put_frag carry holder ), so ........ +* 1 - 3 bytes of the last put_frag may be still in IFB_tx_32 ( the MIC engine carry holder ), so ........ +* The call to the MIC calculation routine feeds these remaining bytes (if any) of put_frag and the +* just as many bytes of the padding as needed to the MIC calculation engine. Note that the "unneeded" pad +* bytes simply end up in the MIC engine carry holder and are never used. +*8: write the remainder of the MIC and possible some garbage to NIC RAM +* Note: i is always 4 (a loop-invariant of the while in point 2) +* +*.NOTICE +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +HCF_STATIC void +put_frag_finalize( IFBP ifbp ) +{ +#if (HCF_TYPE) & HCF_TYPE_WPA + if ( ifbp->IFB_MICTxCarry != 0xFFFF) { //if MIC calculation active + CALC_TX_MIC( mic_pad, 8); //. feed (up to 8 bytes of) virtual padding to MIC engine + //. write (possibly) trailing byte + (most of) MIC + put_frag( ifbp, (wci_bufp)ifbp->IFB_MICTx, 8 BE_PAR(0) ); + } +#endif // HCF_TYPE_WPA + put_frag( ifbp, null_addr, 1 BE_PAR(0) ); //write (possibly) trailing data or MIC byte +} // put_frag_finalize + + +/************************************************************************************************************ +* +*.SUBMODULE int put_info( IFBP ifbp, LTVP ltvp ) +*.PURPOSE support routine to handle the "basic" task of hcf_put_info to pass RIDs to the NIC. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* ltvp address in NIC RAM where LVT-records are located +* +*.RETURNS +* HCF_SUCCESS +* >>put_frag +* >>cmd_wait +* +*.DESCRIPTION +* +* +*.DIAGRAM +*20: do not write RIDs to NICs which have incompatible Firmware +*24: If the RID does not exist, the L-field is set to zero. +* Note that some RIDs can not be read, e.g. the pseudo RIDs for direct Hermes commands and CFG_DEFAULT_KEYS +*28: If the RID is written successful, pass it to the NIC by means of an Access Write command +* +*.NOTICE +* The mechanism to HCF_ASSERT on invalid typ-codes in the LTV record is based on the following strategy: +* - some codes (e.g. CFG_REG_MB) are explicitly handled by the HCF which implies that these codes +* are valid. These codes are already consumed by hcf_put_info. +* - all other codes are passed to the Hermes. Before the put action is executed, hcf_get_info is called +* with an LTV record with a value of 1 in the L-field and the intended put action type in the Typ-code +* field. If the put action type is valid, it is also valid as a get action type code - except +* for CFG_DEFAULT_KEYS and CFG_ADD_TKIP_DEFAULT_KEY - so the HCF_ASSERT logic of hcf_get_info should +* not catch. +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +HCF_STATIC int +put_info( IFBP ifbp, LTVP ltvp ) +{ + +int rc = HCF_SUCCESS; + + HCFASSERT( ifbp->IFB_CardStat == 0, MERGE_2( ltvp->typ, ifbp->IFB_CardStat ) ) + HCFASSERT( CFG_RID_CFG_MIN <= ltvp->typ && ltvp->typ <= CFG_RID_CFG_MAX, ltvp->typ ) + + if ( ifbp->IFB_CardStat == 0 && /* 20*/ + ( ( CFG_RID_CFG_MIN <= ltvp->typ && ltvp->typ <= CFG_RID_CFG_MAX ) || + ( CFG_RID_ENG_MIN <= ltvp->typ /* && ltvp->typ <= 0xFFFF */ ) ) ) { +#if HCF_ASSERT //FCC8, FCB0, FCB4, FCB6, FCB7, FCB8, FCC0, FCC4, FCBC, FCBD, FCBE, FCBF + { + hcf_16 t = ltvp->typ; + LTV_STRCT x = { 2, t, {0} }; /*24*/ + hcf_get_info( ifbp, (LTVP)&x ); + if ( x.len == 0 && + ( t != CFG_DEFAULT_KEYS && t != CFG_ADD_TKIP_DEFAULT_KEY && t != CFG_REMOVE_TKIP_DEFAULT_KEY && + t != CFG_ADD_TKIP_MAPPED_KEY && t != CFG_REMOVE_TKIP_MAPPED_KEY && + t != CFG_HANDOVER_ADDR && t != CFG_DISASSOCIATE_ADDR && + t != CFG_FCBC && t != CFG_FCBD && t != CFG_FCBE && t != CFG_FCBF && + t != CFG_DEAUTHENTICATE_ADDR + ) + ) { + HCFASSERT( DO_ASSERT, ltvp->typ ) + } + } +#endif // HCF_ASSERT + + rc = setup_bap( ifbp, ltvp->typ, 0, IO_OUT ); + put_frag( ifbp, (wci_bufp)ltvp, 2*ltvp->len + 2 BE_PAR(2) ); +/*28*/ if ( rc == HCF_SUCCESS ) { + rc = cmd_exe( ifbp, HCMD_ACCESS + HCMD_ACCESS_WRITE, ltvp->typ ); + } + } + return rc; +} // put_info + + +#if (HCF_DL_ONLY) == 0 +/************************************************************************************************************ +* +*.SUBMODULE int put_info_mb( IFBP ifbp, CFG_MB_INFO_STRCT FAR * ltvp ) +*.PURPOSE accumulates a ( series of) buffers into a single Info block into the MailBox. +* +*.ARGUMENTS +* ifbp address of the Interface Block +* ltvp address of structure specifying the "type" and the fragments of the information to be synthesized +* as an LTV into the MailBox +* +*.RETURNS +* +*.DESCRIPTION +* If the data does not fit (including no MailBox is available), the IFB_MBTally is incremented and an +* error status is returned. +* HCF_ASSERT does not catch. +* Calling put_info_mb when their is no MailBox available, is considered a design error in the MSF. +* +* Note that there is always at least 1 word of unused space in the mail box. +* As a consequence: +* - no problem in pointer arithmetic (MB_RP == MB_WP means unambiguously mail box is completely empty +* - There is always free space to write an L field with a value of zero after each MB_Info block. This +* allows for an easy scan mechanism in the "get MB_Info block" logic. +* +* +*.DIAGRAM +*1: Calculate L field of the MBIB, i.e. 1 for the T-field + the cumulative length of the fragments. +*2: The free space in the MailBox is calculated (2a: free part from Write Ptr to Read Ptr, 2b: free part +* turns out to wrap around) . If this space suffices to store the number of words reflected by len (T-field +* + Value-field) plus the additional MailBox Info L-field + a trailing 0 to act as the L-field of a trailing +* dummy or empty LTV record, then a MailBox Info block is build in the MailBox consisting of +* - the value len in the first word +* - type in the second word +* - a copy of the contents of the fragments in the second and higher word +* +*4: Since put_info_mb() can more or less directly be called from the MSF level, the I/F must be robust +* against out-of-range variables. As failsafe coding, the MB update is skipped by changing tlen to 0 if +* len == 0; This will indirectly cause an assert as result of the violation of the next if clause. +*6: Check whether the free space in MailBox suffices (this covers the complete absence of the MailBox). +* Note that len is unsigned, so even MSF I/F violation works out O.K. +* The '2' in the expression "len+2" is used because 1 word is needed for L itself and 1 word is needed +* for the zero-sentinel +*8: update MailBox Info length report to MSF with "oldest" MB Info Block size. Be carefull here, if you get +* here before the MailBox is registered, you can't read from the buffer addressed by IFB_MBp (it is the +* Null buffer) so don't move this code till the end of this routine but keep it where there is garuanteed +* a buffer. +* +*.NOTICE +* boundary testing depends on the fact that IFB_MBSize is guaranteed to be zero if no MailBox is present, +* and to a lesser degree, that IFB_MBWp = IFB_MBRp = 0 +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +#if (HCF_EXT) & HCF_EXT_MB + +HCF_STATIC int +put_info_mb( IFBP ifbp, CFG_MB_INFO_STRCT FAR * ltvp ) +{ + +int rc = HCF_SUCCESS; +hcf_16 i; //work counter +hcf_16 *dp; //destination pointer (in MailBox) +wci_recordp sp; //source pointer +hcf_16 len; //total length to copy to MailBox +hcf_16 tlen; //free length/working length/offset in WMP frame + + if ( ifbp->IFB_MBp == NULL ) return rc; //;?not sufficient + HCFASSERT( ifbp->IFB_MBp != NULL, 0 ) //!!!be careful, don't get into an endless recursion + HCFASSERT( ifbp->IFB_MBSize, 0 ) + + len = 1; /* 1 */ + for ( i = 0; i < ltvp->frag_cnt; i++ ) { + len += ltvp->frag_buf[i].frag_len; + } + if ( ifbp->IFB_MBRp > ifbp->IFB_MBWp ) { + tlen = ifbp->IFB_MBRp - ifbp->IFB_MBWp; /* 2a*/ + } else { + if ( ifbp->IFB_MBRp == ifbp->IFB_MBWp ) { + ifbp->IFB_MBRp = ifbp->IFB_MBWp = 0; // optimize Wrapping + } + tlen = ifbp->IFB_MBSize - ifbp->IFB_MBWp; /* 2b*/ + if ( ( tlen <= len + 2 ) && ( len + 2 < ifbp->IFB_MBRp ) ) { //if trailing space is too small but + // leading space is sufficiently large + ifbp->IFB_MBp[ifbp->IFB_MBWp] = 0xFFFF; //flag dummy LTV to fill the trailing space + ifbp->IFB_MBWp = 0; //reset WritePointer to begin of MailBox + tlen = ifbp->IFB_MBRp; //get new available space size + } + } + dp = &ifbp->IFB_MBp[ifbp->IFB_MBWp]; + if ( len == 0 ) { + tlen = 0; //;? what is this good for + } + if ( len + 2 >= tlen ){ /* 6 */ + //Do Not ASSERT, this is a normal condition + IF_TALLY( ifbp->IFB_HCF_Tallies.NoBufMB++; ) /*NOP to cover against analomies with empty compound*/; + rc = HCF_ERR_LEN; + } else { + *dp++ = len; //write Len (= size of T+V in words to MB_Info block + *dp++ = ltvp->base_typ; //write Type to MB_Info block + ifbp->IFB_MBWp += len + 1; //update WritePointer of MailBox + for ( i = 0; i < ltvp->frag_cnt; i++ ) { // process each of the fragments + sp = ltvp->frag_buf[i].frag_addr; + len = ltvp->frag_buf[i].frag_len; + while ( len-- ) *dp++ = *sp++; + } + ifbp->IFB_MBp[ifbp->IFB_MBWp] = 0; //to assure get_info for CFG_MB_INFO stops + ifbp->IFB_MBInfoLen = ifbp->IFB_MBp[ifbp->IFB_MBRp]; /* 8 */ + } + return rc; +} // put_info_mb + +#endif // HCF_EXT_MB +#endif // HCF_DL_ONLY + + +/************************************************************************************************************ +* +*.SUBMODULE int setup_bap( IFBP ifbp, hcf_16 fid, int offset, int type ) +*.PURPOSE set up data access to NIC RAM via BAP_1. +* +*.ARGUMENTS +* ifbp address of I/F Block +* fid FID/RID +* offset !!even!! offset in FID/RID +* type IO_IN, IO_OUT +* +*.RETURNS +* HCF_SUCCESS O.K +* HCF_ERR_NO_NIC card is removed +* HCF_ERR_DEFUNCT_TIME_OUT Fatal malfunction detected +* HCF_ERR_DEFUNCT_..... if and only if IFB_DefunctStat <> 0 +* +*.DESCRIPTION +* +* A non-zero return status indicates: +* - the NIC is considered nonoperational, e.g. due to a time-out of some Hermes activity in the past +* - BAP_1 could not properly be initialized +* - the card is removed before completion of the data transfer +* In all other cases, a zero is returned. +* BAP Initialization failure indicates an H/W error which is very likely to signal complete H/W failure. +* Once a BAP Initialization failure has occurred all subsequent interactions with the Hermes will return a +* "defunct" status till the Hermes is re-initialized by means of an hcf_connect. +* +* A BAP is a set of registers (Offset, Select and Data) offering read/write access to a particular FID or +* RID. This access is based on a auto-increment feature. +* There are two BAPs but these days the HCF uses only BAP_1 and leaves BAP_0 to the PCI Busmastering H/W. +* +* The BAP-mechanism is based on the Busy bit in the Offset register (see the Hermes definition). The waiting +* for Busy must occur between writing the Offset register and accessing the Data register. The +* implementation to wait for the Busy bit drop after each write to the Offset register, implies that the +* requirement that the Busy bit is low before the Select register is written, is automatically met. +* BAP-setup may be time consuming (e.g. 380 usec for large offsets occurs frequently). The wait for Busy bit +* drop is protected by a loop counter, which is initialized with IFB_TickIni, which is calibrated in init. +* +* The NIC I/F is optimized for word transfer and can only handle word transfer at a word boundary in NIC +* RAM. The intended solution for transfer of a single byte has multiple H/W flaws. There have been different +* S/W Workaround strategies. RID access is hcf_16 based by "nature", so no byte access problems. For Tx/Rx +* FID access, the byte logic became obsolete by absorbing it in the double word oriented nature of the MIC +* feature. +* +* +*.DIAGRAM +* +*2: the test on rc checks whether the HCF went into "defunct" mode ( e.g. BAP initialization or a call to +* cmd_wait did ever fail). +*4: the select register and offset register are set +* the offset register is monitored till a successful condition (no busy bit) is detected or till the +* (calibrated) protection counter expires +* If the counter expires, this is reflected in IFB_DefunctStat, so all subsequent calls to setup_bap fail +* immediately ( see 2) +*6: initialization of the carry as used by pet/get_frag +*8: HREG_OFFSET_ERR is ignored as error because: +* a: the Hermes is robust against it +* b: it is not known what causes it (probably a bug), hence no strategy can be specified which level is +* to handle this error in which way. In the past, it could be induced by the MSF level, e.g. by calling +* hcf_rcv_msg while there was no Rx-FID available. Since this is an MSF-error which is caught by ASSERT, +* there is no run-time action required by the HCF. +* Lumping the Offset error in with the Busy bit error, as has been done in the past turns out to be a +* disaster or a life saver, just depending on what the cause of the error is. Since no prediction can be +* done about the future, it is "felt" to be the best strategy to ignore this error. One day the code was +* accompanied by the following comment: +* // ignore HREG_OFFSET_ERR, someone, supposedly the MSF programmer ;) made a bug. Since we don't know +* // what is going on, we might as well go on - under management pressure - by ignoring it +* +*.ENDDOC END DOCUMENTATION +* +************************************************************************************************************/ +HCF_STATIC int +setup_bap( IFBP ifbp, hcf_16 fid, int offset, int type ) +{ +PROT_CNT_INI +int rc; + + HCFTRACE( ifbp, HCF_TRACE_STRIO ); + if ( ( rc = ifbp->IFB_DefunctStat ) == HCF_SUCCESS ) { /*2*/ + OPW( HREG_SELECT_1, fid ); /*4*/ + OPW( HREG_OFFSET_1, offset ); + if ( type == IO_IN ) { + ifbp->IFB_CarryIn = 0; + } + else ifbp->IFB_CarryOut = 0; + HCF_WAIT_WHILE( IPW( HREG_OFFSET_1) & HCMD_BUSY ); + HCFASSERT( !( IPW( HREG_OFFSET_1) & HREG_OFFSET_ERR ), MERGE_2( fid, offset ) ) /*8*/ + if ( prot_cnt == 0 ) { + HCFASSERT( DO_ASSERT, MERGE_2( fid, offset ) ) + rc = ifbp->IFB_DefunctStat = HCF_ERR_DEFUNCT_TIME_OUT; + ifbp->IFB_CardStat |= CARD_STAT_DEFUNCT; + } + } + HCFTRACE( ifbp, HCF_TRACE_STRIO | HCF_TRACE_EXIT ); + return rc; +} // setup_bap + diff --git a/drivers/staging/wlags49_h2/hcf.h b/drivers/staging/wlags49_h2/hcf.h new file mode 100644 index 0000000000000000000000000000000000000000..2cd573944cdc7f56182833912c0ba7f61e02fa16 --- /dev/null +++ b/drivers/staging/wlags49_h2/hcf.h @@ -0,0 +1,405 @@ + +// vim:tw=110:ts=4: +#ifndef HCF_H +#define HCF_H 1 + +/************************************************************************************************************ +* +* FILE : hcf.h +* +* DATE : $Date: 2004/08/05 11:47:10 $ $Revision: 1.7 $ +* Original: 2004/05/19 07:26:01 Revision: 1.56 Tag: hcf7_t20040602_01 +* Original: 2004/05/12 08:47:23 Revision: 1.53 Tag: hcf7_t7_20040513_01 +* Original: 2004/04/15 09:24:42 Revision: 1.46 Tag: hcf7_t7_20040415_01 +* Original: 2004/04/08 15:18:16 Revision: 1.45 Tag: t7_20040413_01 +* Original: 2004/04/01 15:32:55 Revision: 1.43 Tag: t7_20040401_01 +* Original: 2004/03/10 15:39:28 Revision: 1.39 Tag: t20040310_01 +* Original: 2004/03/04 11:03:38 Revision: 1.37 Tag: t20040304_01 +* Original: 2004/03/02 14:51:21 Revision: 1.35 Tag: t20040302_03 +* Original: 2004/02/24 13:00:28 Revision: 1.28 Tag: t20040224_01 +* Original: 2004/02/09 14:50:14 Revision: 1.26 Tag: t20040219_01 +* +* AUTHOR : Nico Valster +* +* SPECIFICATION: .......... +* +* DESC : Definitions and Prototypes for MSF as well as HCF sources +* +* Customizable via HCFCFG.H +* +* +************************************************************************************************************** + +************************************************************************************************************** +* +* +* SOFTWARE LICENSE +* +* This software is provided subject to the following terms and conditions, +* which you should read carefully before using the software. Using this +* software indicates your acceptance of these terms and conditions. If you do +* not agree with these terms and conditions, do not use the software. +* +* COPYRIGHT © 1994 - 1995 by AT&T. All Rights Reserved +* COPYRIGHT © 1996 - 2000 by Lucent Technologies. All Rights Reserved +* COPYRIGHT © 2001 - 2004 by Agere Systems Inc. All Rights Reserved +* All rights reserved. +* +* Redistribution and use in source or binary forms, with or without +* modifications, 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 as comments in the code as +* well as in the documentation and/or other materials provided with the +* distribution. +* +* . 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. +* +* . Neither the name of Agere Systems Inc. nor the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* Disclaimer +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY +* USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN +* RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. +* +* +*************************************************************************************************************/ + + +#include "hcfcfg.h" // System Constants to be defined by the MSF-programmer to tailor the HCF +#include "mdd.h" // Include file common for HCF, MSF + + +/************************************************************************************************/ +/************************************** MACROS ************************************************/ +/************************************************************************************************/ + +#define LOF(x) (sizeof(x)/sizeof(hcf_16)-1) + +/* Endianess + * Little Endian (a.k.a. Intel), least significant byte first + * Big Endian (a.k.a. Motorola), most significant byte first + * + * The following macros are supplied + * o CNV_LITTLE_TO_SHORT(w) interprets the 16-bits input value as Little Endian, returns an hcf_16 + * o CNV_BIG_TO_SHORT(w) interprets the 16-bits input value as Big Endian, returns an hcf_16 + * + */ + +/* To increase portability, use unsigned char and unsigned char * when accessing parts of larger + * types to convert their Endianess + */ + +#define CNV_END_SHORT(w) (hcf_16)( ((hcf_16)(w) & 0x00FF) << 8 | ((hcf_16)(w) & 0xFF00) >> 8 ) +#define CNV_END_LONG(dw) (hcf_32)( (dw >> 24) | ((dw >> 8) & 0xff00) | ((dw << 8) & 0xff0000) | (dw << 24) ) + +#if HCF_BIG_ENDIAN +//******************************************** B I G E N D I A N ******************************************* +#define CNV_LITTLE_TO_SHORT(w) CNV_END_SHORT(w) // endianess conversion needed +#define CNV_BIG_TO_SHORT(w) (w) // no endianess conversion needed +#define CNV_LITTLE_TO_LONG(dw) CNV_END_LONG(dw) +#define CNV_LONG_TO_LITTLE(dw) CNV_END_LONG(dw) +#else +//****************************************** L I T T L E E N D I A N **************************************** +#define CNV_LITTLE_TO_SHORT(w) (w) // no endianess conversion needed +#define CNV_BIG_TO_SHORT(w) CNV_END_SHORT(w) // endianess conversion needed +#define CNV_LITTLE_TO_LONG(dw) (dw) +#define CNV_LONG_TO_LITTLE(dw) (dw) + +#if defined HCF_ALIGN && HCF_ALIGN > 1 +#define CNV_SHORTP_TO_LITTLE(pw) ((hcf_16)(*(hcf_8 *)pw)) | ((hcf_16)(*((hcf_8 *)pw+1)) << 8) +#define CNV_LONGP_TO_LITTLE(pdw) ((hcf_32)(*(hcf_8 *)pdw)) | ((hcf_32)(*((hcf_8 *)pdw+1)) << 8) | \ + ((hcf_32)(*((hcf_8 *)pdw+2)) << 16) | ((hcf_32)(*((hcf_8 *)pdw+3)) << 24) +#else +#define CNV_LONGP_TO_LITTLE(pdw) (*(hcf_32 *)pdw) +#define CNV_SHORTP_TO_LITTLE(pw) (*(hcf_16 *)pw) +#endif + +#endif // HCF_BIG_ENDIAN + +// conversion macros which can be expressed in other macros +#define CNV_SHORT_TO_LITTLE(w) CNV_LITTLE_TO_SHORT(w) +#define CNV_SHORT_TO_BIG(w) CNV_BIG_TO_SHORT(w) + +/************************************************************************************************/ +/************************************** END OF MACROS *****************************************/ +/************************************************************************************************/ + +/***********************************************************************************************************/ +/***************** ****************************************/ +/***********************************************************************************************************/ + +// offsets Transmit/Receive Frame Structure +#define HFS_STAT 0x0000 +#define HFS_SWSUP 0x0006 //SW Support +#define HFS_Q_INFO 0x0006 //Signal/Silence level +#define HFS_RATE 0x0008 //RxFlow/Rate +#define HFS_STAT_ERR RX_STAT_ERR //link "natural" HCF name to "natural" MSF name +#define HFS_TX_CNTL 0x0036 + // H-I H-II +#define HFS_DAT_LEN (HFS_ADDR_DEST - 2) // 0x002C 0x0038 +#define HFS_ADDR_DEST 0x003A // 0x002E 0x003A +#define HFS_ADDR_SRC (HFS_ADDR_DEST + 6) // 0x0034 0x0040 +#define HFS_LEN (HFS_ADDR_SRC + 6) // 0x003A 0x0046 +#define HFS_DAT (HFS_LEN + 2) // 0x003C 0x0048 +#define HFS_TYPE (HFS_DAT + 6) // 0x0042 0x004E + + +//============================= D E S C R I P T O R S T R U C T U R E ============================== +//;?MDD.H stuff ;? + +#if HCF_BIG_ENDIAN +#define DESC_STRCT_CNT 0 +#define DESC_STRCT_SIZE 1 +#else +#define DESC_STRCT_CNT 1 +#define DESC_STRCT_SIZE 0 +#endif // HCF_BIG_ENDIAN + +#define BUF_CNT buf_dim[DESC_STRCT_CNT] +#define BUF_SIZE buf_dim[DESC_STRCT_SIZE] + +typedef struct DESC_STRCT { + hcf_16 buf_dim[2]; + hcf_32 buf_phys_addr; + hcf_32 next_desc_phys_addr; // physical address of next descriptor + hcf_32 desc_phys_addr; // physical address of this descriptor + struct DESC_STRCT *next_desc_addr; + hcf_8 FAR *buf_addr; +#if (HCF_EXT) & HCF_EXT_DESC_STRCT + void FAR *DESC_MSFSup; // pointer for arbitrary use by the MSF +#endif // HCF_DESC_STRCT_EXT +} DESC_STRCT; + +#define HCF_DASA_SIZE 12 //size in bytes for DA/SA + +#define DESC_CNT_MASK 0x0FFF + +#define GET_BUF_SIZE(descp) ((descp)->BUF_SIZE) +#define GET_BUF_CNT(descp) ((descp)->BUF_CNT) +#define SET_BUF_SIZE(descp, size) (descp)->BUF_SIZE = size; +#define SET_BUF_CNT(descp, count) (descp)->BUF_CNT = count; + +//========================================= T A L L I E S =================================================== + +typedef struct { //Hermes Tallies (IFB substructure) + hcf_32 TxUnicastFrames; + hcf_32 TxMulticastFrames; + hcf_32 TxFragments; + hcf_32 TxUnicastOctets; + hcf_32 TxMulticastOctets; + hcf_32 TxDeferredTransmissions; + hcf_32 TxSingleRetryFrames; + hcf_32 TxMultipleRetryFrames; + hcf_32 TxRetryLimitExceeded; + hcf_32 TxDiscards; + hcf_32 RxUnicastFrames; + hcf_32 RxMulticastFrames; + hcf_32 RxFragments; + hcf_32 RxUnicastOctets; + hcf_32 RxMulticastOctets; + hcf_32 RxFCSErrors; + hcf_32 RxDiscardsNoBuffer; + hcf_32 TxDiscardsWrongSA; + hcf_32 RxWEPUndecryptable; + hcf_32 RxMsgInMsgFragments; + hcf_32 RxMsgInBadMsgFragments; + hcf_32 RxDiscardsWEPICVError; + hcf_32 RxDiscardsWEPExcluded; +#if (HCF_EXT) & HCF_EXT_TALLIES_FW + hcf_32 TalliesExtra[32]; +#endif // HCF_EXT_TALLIES_FW +} CFG_HERMES_TALLIES_STRCT; + +typedef struct { //HCF Tallies (IFB substructure) + hcf_32 NoBufInfo; //No buffer available for unsolicited Notify frame + hcf_32 NoBufMB; //No space available in MailBox + hcf_32 MiscErr; /* Command errors + * - time out on completion synchronous part Hermes Command + * - completed Hermes Command doesn't match original command + * - status of completed Hermes Command contains error bits + */ +#if (HCF_EXT) & HCF_EXT_TALLIES_FW + hcf_32 EngCnt[8]; +#endif // HCF_EXT_TALLIES_FW +} CFG_HCF_TALLIES_STRCT; + +//Note this way to define ..._TAL_CNT implies that all tallies must keep the same (hcf_32) size +#if (HCF_TALLIES) & ( HCF_TALLIES_NIC | HCF_TALLIES_HCF ) +#if (HCF_TALLIES) & HCF_TALLIES_NIC //Hermes tally support +#define HCF_NIC_TAL_CNT (sizeof(CFG_HERMES_TALLIES_STRCT)/ sizeof(hcf_32)) +#else +#define HCF_NIC_TAL_CNT 0 +#endif // HCF_TALLIES +#if (HCF_TALLIES) & HCF_TALLIES_HCF //HCF tally support +#define HCF_HCF_TAL_CNT (sizeof(CFG_HCF_TALLIES_STRCT) / sizeof(hcf_32)) +#else +#define HCF_HCF_TAL_CNT 0 +#endif // HCF_TALLIES +#define HCF_TOT_TAL_CNT ( HCF_NIC_TAL_CNT + HCF_NIC_TAL_CNT ) +#endif // HCF_TALLIES_NIC / HCF_TALLIES_HCF + + +/***********************************************************************************************************/ +/********************************** I N T E R F A C E B L O C K ******************************************/ +/***********************************************************************************************************/ + +#define IFB_VERSION 0x0E // initially 0, to be incremented by every IFB layout change + +typedef struct { + hcf_io IFB_IOBase; // I/O address of Hermes chip as passed by MSF at hcf_connect call + hcf_16 IFB_IORange; // I/O Range used by Hermes chip + hcf_16 IFB_DLMode; // Download Mode state + hcf_16 IFB_Cmd; // cmd in progress flag, to be ack-ed before next cmd can be issued + hcf_16 IFB_RxFID; // FID of "current" RxFS (non-DMA mode) +//;?#if tx_delay option + hcf_16 IFB_TxFID; // fid storage during "delayed" send +//;?#endif tx_delay option + hcf_16 IFB_RxLen; // + hcf_16 IFB_DefunctStat; // BAP initialization or Cmd Completion failed + hcf_16 IFB_ErrCmd; // contents Status reg when error bits and/or mismatch in cmd_wait + hcf_16 IFB_ErrQualifier; // contents Resp0 reg when error bits and/or mismatch in cmd_wait + hcf_16 IFB_lal; // LookAhead Length + wci_bufp IFB_lap; // LookAhead Buffer pointer + hcf_16 IFB_LinkStat; // Link Status + hcf_16 IFB_DSLinkStat; // Link Status, new strategy introduced for DeepSleep + hcf_16 IFB_CarryIn; // carry and carry-flag to move 1 byte from one get_frag to the next + hcf_16 IFB_CarryOut; // carry and carry-flag to move 1 byte from one put_frag to the next + hcf_16 IFB_Version; // IFB_VERSION, incremented by every SIGNIFICANT IFB layout change + hcf_16 IFB_CardStat; // NIC error / F/W incompatibility status + hcf_16 IFB_RscInd; // non-DMA: TxFID available, DMA: always 1 + hcf_16 IFB_CntlOpt; // flags: 32 bits I/O, DMA available, DMA enabled + hcf_16 IFB_BusType; // BusType, derived via CFG_NIC_BUS_TYPE + CFG_FW_IDENTITY_STRCT IFB_FWIdentity; /* keep FWIdentity/Sup and PRIIdentity/Sup in sequence + * because of the (dumb) copy in init() */ +#if defined MSF_COMPONENT_ID + CFG_SUP_RANGE_STRCT IFB_FWSup; + CFG_PRI_IDENTITY_STRCT IFB_PRIIdentity; + CFG_SUP_RANGE_STRCT IFB_PRISup; + CFG_SUP_RANGE_STRCT IFB_HSISup; +#endif // MSF_COMPONENT_ID +#if (HCF_EXT) & HCF_EXT_INFO_LOG + RID_LOGP IFB_RIDLogp; // pointer to RID_LOG structure +#endif // HCF_EXT_INFO_LOG +#if HCF_PROT_TIME + hcf_32 IFB_TickIni; // initialization of S/W counter based protection loop +#endif // HCF_PROT_TIME +#if (HCF_EXT) & HCF_EXT_INT_TICK + int IFB_TickCnt; // Hermes Timer Tick Counter +#endif // HCF_EXT_INT_TICK +#if (HCF_EXT) & HCF_EXT_MB + hcf_16 *IFB_MBp; // pointer to the MailBox + hcf_16 IFB_MBSize; // size of the MailBox + hcf_16 IFB_MBWp; // zero-based write index into the MailBox + hcf_16 IFB_MBRp; // zero-based read index into the MailBox + hcf_16 IFB_MBInfoLen; // contents of L-field of the oldest available MailBoxInfoBlock +#endif // HCF_EXT_MB +#if (HCF_TYPE) & HCF_TYPE_WPA + hcf_16 IFB_MICTxCntl; // MIC bit and Key index in TxControl field of TxFS + hcf_32 IFB_MICTxKey[2]; // calculating key + hcf_32 IFB_MICTx[2]; // Tx MIC calculation Engine state + hcf_16 IFB_MICTxCarry; // temp length, carries over from one Tx fragment to another + hcf_16 IFB_MICRxCarry; // temp length, carries over from one Rx fragment to another + hcf_32 IFB_MICRxKey[4*2]; // 4 checking keys + hcf_32 IFB_MICRx[2]; // Rx MIC calculation Engine state +#endif // HCF_TYPE_WPA +#if HCF_ASSERT +#if (HCF_ASSERT) & HCF_ASSERT_MB + CFG_MB_INFO_RANGE1_STRCT IFB_AssertStrct; // Add some complication to the HCF as prize for the new MSF I/F +#endif // HCF_ASSERT_MB + // target of above IFB_AssertStrct + hcf_16 IFB_AssertLine; // - line number ( + encoded module name ) + hcf_16 IFB_AssertTrace; // - bit based trace of all hcf_.... invocations + hcf_32 IFB_AssertQualifier; // - qualifier + hcf_16 IFB_AssertLvl; // Assert Filtering, Not yet implemented + hcf_16 IFB_AssertWhere; // Where parameter of the Assert macro +#if (HCF_ASSERT) & ( HCF_ASSERT_LNK_MSF_RTN | HCF_ASSERT_RT_MSF_RTN ) + MSF_ASSERT_RTNP IFB_AssertRtn; // MSF Assert Call back routine (inspired by GEF, DrDobbs Nov 1998 ) +#endif // HCF_ASSERT_LNK_MSF_RTN +#if (HCF_ASSERT) & HCF_ASSERT_PRINTF // engineering facilty intended as F/W debugging aid + hcf_16 IFB_DbgPrintF_Cnt; + CFG_FW_PRINTF_BUFFER_LOCATION_STRCT IFB_FwPfBuff; +#endif // HCF_ASSERT_PRINTF +#endif // HCF_ASSERT +#if ! defined HCF_INT_OFF + hcf_16 volatile IFB_IntOffCnt; // 0xFFFF based HCF_ACT_INT_OFF nesting counter, DeepSleep flag +#endif // HCF_INT_OFF +#if (HCF_TYPE) & HCF_TYPE_CCX + hcf_16 IFB_CKIPStat; // CKIP Status flag +#endif // HCF_TYPE_CCX +#if (HCF_TALLIES) & ( HCF_TALLIES_NIC | HCF_TALLIES_HCF ) //Hermes and/or HCF tally support + hcf_32 IFB_Silly_you_should_align; //;? + hcf_16 IFB_TallyLen; // Tally length (to build an LTV) + hcf_16 IFB_TallyTyp; // Tally Type (to build an LTV) +#endif // HCF_TALLIES_NIC / HCF_TALLIES_HCF +#if (HCF_TALLIES) & HCF_TALLIES_NIC //Hermes tally support + CFG_HERMES_TALLIES_STRCT IFB_NIC_Tallies; +#endif // HCF_TALLIES_NIC +#if (HCF_TALLIES) & HCF_TALLIES_HCF //HCF tally support + CFG_HCF_TALLIES_STRCT IFB_HCF_Tallies; +#endif // HCF_TALLIES_HCF +#if HCF_DMA + //used for a pool of destination_address descriptor/buffers, used during tx encapsulation points to the + //first/last descriptor in the descriptor chain, so we can easily remove and append a packet. + DESC_STRCT *IFB_FirstDesc[2]; + DESC_STRCT *IFB_LastDesc[2]; + DESC_STRCT *IFB_ConfinedDesc[2]; // pointers to descriptor used for host reclaim purposes. + hcf_16 IFB_DmaPackets; // HREG_EV_[TX/RX]DMA_DONE flags, reports DMA Frame availability to MSF +#endif // HCF_DMA +#if (HCF_EXT) & HCF_EXT_INT_TX_EX + hcf_16 IFB_TxFsStat; // Tx message monitoring + hcf_16 IFB_TxFsGap[2]; //;?make this robust + hcf_16 IFB_TxFsSwSup; +#endif // HCF_EXT_INT_TX_EX + hcf_16 IFB_Magic; /* "Magic" signature, to help the debugger interpret a memory dump + * also the last field cleared at hcf_connect + */ +#if (HCF_EXT) & HCF_EXT_IFB_STRCT // for usage by the MSF + void FAR *IFB_MSFSup; // pointer for arbitrary use by the MSF +#endif // HCF_EXT_IFB_STRCT_EXT +} IFB_STRCT; + +typedef IFB_STRCT* IFBP; + + +/***********************************************************************************************************/ +/********************** W C I F U N C T I O N S P R O T O T Y P E S ******************************/ +/***********************************************************************************************************/ + +EXTERN_C int hcf_action (IFBP ifbp, hcf_16 cmd ); +EXTERN_C int hcf_connect (IFBP ifbp, hcf_io io_base ); +#if (HCF_ENCAP) & HCF_ENC_SUP +EXTERN_C hcf_8 hcf_encap (wci_bufp type ); +#endif // HCF_ENC_SUP +EXTERN_C int hcf_get_info (IFBP ifbp, LTVP ltvp ); +EXTERN_C int hcf_service_nic (IFBP ifbp, wci_bufp bufp, unsigned int len ); +EXTERN_C int hcf_cntl (IFBP ifbp, hcf_16 cmd ); +EXTERN_C int hcf_put_info (IFBP ifbp, LTVP ltvp ); +EXTERN_C int hcf_rcv_msg (IFBP ifbp, DESC_STRCT *descp, unsigned int offset ); +EXTERN_C int hcf_send_msg (IFBP ifbp, DESC_STRCT *dp, hcf_16 tx_cntl ); +#if HCF_DMA +EXTERN_C void hcf_dma_tx_put (IFBP ifbp, DESC_STRCT *d, hcf_16 tx_cntl ); +EXTERN_C DESC_STRCT* hcf_dma_tx_get (IFBP ifbp ); +EXTERN_C DESC_STRCT* hcf_dma_rx_get (IFBP ifbp ); +EXTERN_C void hcf_dma_rx_put (IFBP ifbp, DESC_STRCT *d ); +#endif // HCF_DMA +#if (HCF_ASSERT) & HCF_ASSERT_LNK_MSF_RTN +EXTERN_C void msf_assert (unsigned int line_number, hcf_16 trace, hcf_32 qual ); +#endif // HCF_ASSERT_LNK_MSF_RTN + +#endif // HCF_H + diff --git a/drivers/staging/wlags49_h2/hcfcfg.h b/drivers/staging/wlags49_h2/hcfcfg.h new file mode 100644 index 0000000000000000000000000000000000000000..83475b1060a18c5652f057510545ed39da629878 --- /dev/null +++ b/drivers/staging/wlags49_h2/hcfcfg.h @@ -0,0 +1,2344 @@ + +// vim:tw=110:ts=4: +#ifndef HCFCFG_H +#define HCFCFG_H 1 + +/************************************************************************************************************* +* +* FILE : hcfcfg.tpl // hcfcfg.h +* +* DATE : $Date: 2004/08/05 11:47:10 $ $Revision: 1.6 $ +* Original: 2004/04/08 15:18:16 Revision: 1.40 Tag: t20040408_01 +* Original: 2004/04/01 15:32:55 Revision: 1.38 Tag: t7_20040401_01 +* Original: 2004/03/10 15:39:28 Revision: 1.34 Tag: t20040310_01 +* Original: 2004/03/03 14:10:12 Revision: 1.32 Tag: t20040304_01 +* Original: 2004/03/02 09:27:12 Revision: 1.30 Tag: t20040302_03 +* Original: 2004/02/24 13:00:28 Revision: 1.25 Tag: t20040224_01 +* Original: 2004/02/18 17:13:57 Revision: 1.23 Tag: t20040219_01 +* +* AUTHOR : Nico Valster +* +* DESC : HCF Customization Macros +* hcfcfg.tpl list all #defines which must be specified to: +* adjust the HCF functions defined in HCF.C to the characteristics of a specific environment +* o maximum sizes for messages +* o Endianess +* Compiler specific macros +* o port I/O macros +* o type definitions +* +* By copying HCFCFG.TPL to HCFCFG.H and -if needed- modifying the #defines the WCI functionality can be +* tailored +* +* Supported environments: +* WVLAN_41 Miniport NDIS 3.1 +* WVLAN_42 Packet Microsoft Visual C 1.5 +* WVLAN_43 16 bits DOS ODI Microsoft Visual C 1.5 +* WVLAN_44 32 bits ODI (__NETWARE_386__) WATCOM +* WVLAN_45 MAC_OS MPW?, Symantec? +* WVLAN_46 Windows CE (_WIN32_WCE) Microsoft ? +* WVLAN_47 LINUX (__LINUX__) GCC, discarded, based on GPL'ed HCF-light +* WVLAN_48 Miniport NDIS 5 +* WVLAN_49 LINUX (__LINUX__) GCC, originally based on pre-compiled HCF_library +* migrated to use the HCF sources when Lucent Technologies +* brought the HCF module under GPL +* WVLAN_51 Miniport USB NDIS 5 +* WVLAN_52 Miniport NDIS 4 +* WVLAN_53 VxWorks END Station driver +* WVLAN_54 VxWorks END Access Point driver +* WVLAN_81 WavePoint BORLAND C +* WCITST Inhouse test tool Microsoft Visual C 1.5 +* WSU WaveLAN Station Update Microsoft Visual C ?? +* SCO UNIX not yet actually used ? ? +* __ppc OEM supplied ? +* _AM29K OEM supplied ? +* ? OEM supplied Microtec Research 80X86 Compiler +* +************************************************************************************************************** +* +* +* SOFTWARE LICENSE +* +* This software is provided subject to the following terms and conditions, +* which you should read carefully before using the software. Using this +* software indicates your acceptance of these terms and conditions. If you do +* not agree with these terms and conditions, do not use the software. +* +* COPYRIGHT © 1994 - 1995 by AT&T. All Rights Reserved +* COPYRIGHT © 1996 - 2000 by Lucent Technologies. All Rights Reserved +* COPYRIGHT © 2001 - 2004 by Agere Systems Inc. All Rights Reserved +* All rights reserved. +* +* Redistribution and use in source or binary forms, with or without +* modifications, 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 as comments in the code as +* well as in the documentation and/or other materials provided with the +* distribution. +* +* . 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. +* +* . Neither the name of Agere Systems Inc. nor the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* Disclaimer +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY +* USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN +* RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. +* +* +*************************************************************************************************************/ + +/* Alignment +* Some platforms can access words on odd boundaries (with possibly an performance impact), at other +* platforms such an access may result in a memory access violation. +* It is assumed that everywhere where the HCF casts a char pointer into a word pointer, the alignment +* criteria are met. This put some restrictions on the MSF, which are assumed to be "automatically" fulfilled +* at the applicable platforms +* To assert this assumption, the macro HCF_ALIGN can be defined. The default value is 1, meaning byte +* alignment (or no alignment), a value of 2 means word alignment, a value of 4 means double word alignment +*/ + +/***************************** IN_PORT_STRING_8_16 S a m p l e s ***************************************** + + // C implementation which let the processor handle the word-at-byte-boundary problem +#define IN_PORT_STRING_8_16( port, addr, n) while ( n-- ) \ + { *(hcf_16 FAR*)addr = IN_PORT_WORD( port ); ((hcf_8 FAR*)addr)+=2; } + + // C implementation which handles the word-at-byte-boundary problem +#define IN_PORT_STRING_8_16( port, addr, n) while ( n-- ) \ + { hcf_16 i = IN_PORT_WORD(port); *((hcf_8 FAR*)addr)++ = (hcf_8)i; *((hcf_8 FAR*)addr)++ = (hcf_8)(i>>8);} + + // Assembler implementation +#define IN_PORT_STRING_8_16( port, addr, len) __asm \ +{ \ + __asm push di \ + __asm push es \ + __asm mov cx,len \ + __asm les di,addr \ + __asm mov dx,port \ + __asm rep insw \ + __asm pop es \ + __asm pop di \ +} + + +***************************** OUT_PORT_STRING_8_16 S a m p l e s ****************************************** + + // C implementation which let the processor handle the word-at-byte-boundary problem +#define OUT_PORT_STRING_8_16( port, addr, n) while ( n-- ) \ + { OUT_PORT_WORD( port, *(hcf_16 FAR*)addr ) ; ((hcf_8 FAR*)addr)+=2; } + + // C implementation which handles the word-at-byte-boundary problem +#define OUT_PORT_STRING_8_16( port, addr, n) while ( n-- ) \ + { OUT_PORT_WORD( port, *((hcf_8 FAR*)addr) | *(((hcf_8 FAR*)addr)+1)<<8 ); (hcf_8 FAR*)addr+=2; } + + // Assembler implementation +#define OUT_PORT_STRING_8_16( port, addr, len) __asm \ +{ \ + __asm push si \ + __asm push ds \ + __asm mov cx,len \ + __asm lds si,addr \ + __asm mov dx,port \ + __asm rep outsw \ + __asm pop ds \ + __asm pop si \ +} + +*************************************************************************************************************/ + + +/************************************************************************************************/ +/****************** C O M P I L E R S P E C I F I C M A C R O S ***************************/ +/************************************************************************************************/ +/************************************************************************************************* +* +* !!!!!!!!!!!!!!!!!!!!!!!!! Note to the HCF-implementor !!!!!!!!!!!!!!!!!!!!!!!!! +* !!!! Do not call these macros with parameters which introduce side effects !!!! +* !!!!!!!!!!!!!!!!!!!!!!!!! Note to the HCF-implementor !!!!!!!!!!!!!!!!!!!!!!!!! +* +* +* By selecting the appropriate Macro definitions by means of modifying the "#ifdef 0/1" lines, the HCF can be +* adjusted for the I/O characteristics of a specific compiler +* +* If needed the macros can be modified or replaced with definitions appropriate for your personal platform. +* If you need to make such changes it is appreciated if you inform Agere Systems +* That way the changes can become part of the next release of the WCI +* +* For convenience of the MSF-programmer, all macros are allowed to modify their parameters (although some +* might argue that this would constitute bad coding practice). This has its implications on the HCF, e.g. as a +* consequence these macros should not be called with parameters which have side effects, e.g auto-increment. +* +* in the Microsoft implementation of inline assembly it is O.K. to corrupt all flags except the direction flag +* and to corrupt all registers except the segment registers and EDI, ESI, ESP and EBP (or their 16 bits +* equivalents). Other environments may have other constraints +* +* in the Intel environment it is O.K to have a word (as a 16 bits quantity) at a byte boundary, hence +* IN_/OUT_PORT_STRING_8_16 can move words between PC-memory and NIC-memory with as only constraint that the +* words are on a word boundary in NIC-memory. This does not hold true for all conceivable environments, e.g. +* an Motorola 68xxx does not allow this. Probably/hopefully the boundary conditions imposed by these type of +* platforms prevent this case from materializing. If this is not the case, OUT_PORT_STRING_8_16 must be coded +* by combining two Host memory hcf_8 values at a time to a single hcf_16 value to be passed to the NIC and +* IN_PORT_STRING_8_16 the single hcf_16 retrieved from the NIC must be split in two hcf_8 values to be stored +* in Host memory (see the sample code above) +* +* The prototypes and functional description of the macros are: +* +* hcf_16 IN_PORT_WORD( hcf_16 port ) +* Reads a word (16 bits) from the specified port +* +* void OUT_PORT_WORD( hcf_16 port, hcf_16 value) +* Writes a word (16 bits) to the specified port +* +* hcf_16 IN_PORT_DWORD( hcf_16 port ) +* Reads a dword (32 bits) from the specified port +* +* void OUT_PORT_DWORD( hcf_16 port, hcf_32 value) +* Writes a dword (32 bits) to the specified port +* +* void IN_PORT_STRING_8_16( port, addr, len) +* Reads len number of words (16 bits) from NIC memory via the specified port to the (FAR) +* byte-pointer addr in PC-RAM +* Note that len specifies the number of words, NOT the number of bytes +* !!!NOTE, although len specifies the number of words, addr MUST be a char pointer NOTE!!! +* See also the common notes for IN_PORT_STRING_8_16 and OUT_PORT_STRING_8_16 +* +* void OUT_PORT_STRING_8_16( port, addr, len) +* Writes len number of words (16 bits) from the (FAR) byte-pointer addr in PC-RAM via the specified +* port to NIC memory +* Note that len specifies the number of words, NOT the number of bytes. +* !!!NOTE, although len specifies the number of words, addr MUST be a char pointer NOTE!!! +* +* The peculiar combination of word-length and char pointers for IN_PORT_STRING_8_16 as well as +* OUT_PORT_STRING_8_16 is justified by the assumption that it offers a more optimal algorithm +* +* void IN_PORT_STRING_32( port, addr, len) +* Reads len number of double-words (32 bits) from NIC memory via the specified port to the (FAR) +* double-word address addr in PC-RAM +* +* void OUT_PORT_STRING_32( port, addr, len) +* Writes len number of double-words (32 bits) from the (FAR) double-word address addr in PC-RAM via +* the specified port to NIC memory +* +* !!!!!!!!!!!!!!!!!!!!!!!!! Note to the HCF-implementor !!!!!!!!!!!!!!!!!!!!!!!!! +* !!!! Do not call these macros with parameters which introduce side effects !!!! +* !!!!!!!!!!!!!!!!!!!!!!!!! Note to the HCF-implementor !!!!!!!!!!!!!!!!!!!!!!!!! +* +*************************************************************************************************/ + +/**************************** define INT Types ******************************/ +typedef unsigned char hcf_8; +typedef unsigned short hcf_16; +typedef unsigned long hcf_32; + +/**************************** define I/O Types ******************************/ +#define HCF_IO_MEM 0x0001 // memory mapped I/O ( 0: Port I/O ) +#define HCF_IO_32BITS 0x0002 // 32Bits support ( 0: only 16 Bits I/O) + +/****************************** #define HCF_TYPE ********************************/ +#define HCF_TYPE_NONE 0x0000 // No type +#define HCF_TYPE_WPA 0x0001 // WPA support +#define HCF_TYPE_USB 0x0002 // reserved (USB Dongle driver support) +//#define HCF_TYPE_HII 0x0004 // Hermes-II, to discriminate H-I and H-II CFG_HCF_OPT_STRCT +#define HCF_TYPE_WARP 0x0008 // WARP F/W +#define HCF_TYPE_PRELOADED 0x0040 // pre-loaded F/W +#define HCF_TYPE_HII5 0x0080 // Hermes-2.5 H/W +#define HCF_TYPE_CCX 0x0100 // CKIP +#define HCF_TYPE_BEAGLE_HII5 0x0200 // Beagle Hermes-2.5 H/W +#define HCF_TYPE_TX_DELAY 0x4000 // Delayed transmission ( non-DMA only) + +/****************************** #define HCF_ASSERT ******************************/ +#define HCF_ASSERT_NONE 0x0000 // No assert support +#define HCF_ASSERT_PRINTF 0x0001 // Hermes generated debug info +#define HCF_ASSERT_SW_SUP 0x0002 // logging via Hermes support register +#define HCF_ASSERT_MB 0x0004 // logging via Mailbox +#define HCF_ASSERT_RT_MSF_RTN 0x4000 // dynamically binding of msf_assert routine +#define HCF_ASSERT_LNK_MSF_RTN 0x8000 // statically binding of msf_assert routine + +/****************************** #define HCF_ENCAP *******************************/ +#define HCF_ENC_NONE 0x0000 // No encapsulation support +#define HCF_ENC 0x0001 // HCF handles En-/Decapsulation +#define HCF_ENC_SUP 0x0002 // HCF supports MSF to handle En-/Decapsulation + +/****************************** #define HCF_EXT *********************************/ +#define HCF_EXT_NONE 0x0000 // No expanded features +#define HCF_EXT_INFO_LOG 0x0001 // logging of Hermes Info frames +//#define HCF_EXT_INT_TX_OK 0x0002 // RESERVED!!! monitoring successful Tx message +#define HCF_EXT_INT_TX_EX 0x0004 // monitoring unsuccessful Tx message +//#define HCF_EXT_MON_MODE 0x0008 // LEGACY +#define HCF_EXT_TALLIES_FW 0x0010 // support for up to 32 Hermes Engineering tallies +#define HCF_EXT_TALLIES_HCF 0x0020 // support for up to 8 HCF Engineering tallies +#define HCF_EXT_NIC_ACCESS 0x0040 // direct access via Aux-ports and to Hermes registers and commands +#define HCF_EXT_MB 0x0080 // MailBox code expanded +#define HCF_EXT_IFB_STRCT 0x0100 // MSF custom pointer in IFB +#define HCF_EXT_DESC_STRCT 0x0200 // MSF custom pointer in Descriptor +#define HCF_EXT_TX_CONT 0x4000 // Continuous transmit test +#define HCF_EXT_INT_TICK 0x8000 // enables TimerTick interrupt generation + +/****************************** #define HCF_SLEEP *******************************/ +#define HCF_DDS 0x0001 // Disconnected Deep Sleep +#define HCF_CDS 0x0002 // Connected Deep Sleep + +/****************************** #define HCF_TALLIES ******************************/ +#define HCF_TALLIES_NONE 0x0000 // No tally support +#define HCF_TALLIES_NIC 0x0001 // Hermes Tallies accumulated in IFB +#define HCF_TALLIES_HCF 0x0002 // HCF Tallies accumulated in IFB +#define HCF_TALLIES_RESET 0x8000 // Tallies in IFB are reset when reported via hcf_get_info + + +/************************************************************************************************/ +/****************************** M I N I P O R T N D I S *************************************/ +/************************************************************************************************/ + +#if defined WVLAN_41 || defined WVLAN_48 || defined WVLAN_52 || defined _WIN32_WCE + +#ifndef WVLAN_46 +#define HCF_EXT (HCF_EXT_INFO_LOG | HCF_EXT_MB | HCF_EXT_NIC_ACCESS ) +#else +#define HCF_EXT ( HCF_EXT_TX_CONT | HCF_EXT_INFO_LOG | HCF_EXT_MB | HCF_EXT_NIC_ACCESS ) +#endif +#define HCF_DLV 1 //H-I legacy, superfluous for H-II + +#ifdef _WIN32_WCE +#define HCF_IO HCF_IO_MEM +#define HCF_DMA 0 // To enable DMA +#endif + +#if _VARIANT == 7 +#define HCF_SLEEP HCF_CDS +#endif // _VARIANT == 7 + +#if _VARIANT == 5 || _VARIANT == 6 +#define _WARP +#define _AES +#define HCF_SLEEP HCF_CDS +#if _VARIANT == 6 +//! #define _RSN +#endif // _VARIANT == 6 +#ifndef _WIN32_WCE +#define HCF_IO HCF_IO_32BITS +#define HCF_DMA 1 // To enable DMA +#endif +#endif // _VARIANT == 5 || _VARIANT == 6 + + +//HWi for migration purposes I defined a define which will be TRUE for ALL drivers +//Meaning that _CCX defined code which we think will get a all driver OK flag can be defined from _CCX to _CCX_OK +#if defined WVLAN_48 // && !defined _WIN32_WCE +#if _VARIANT == 4 || _VARIANT == 6 +#define _CCX_OK 1 +#endif // _VARIANT == 4 || _VARIANT == 6 +#endif // WVLAN_48 + +//#if !defined WVLAN_46 +#if defined WVLAN_48 +#if _VARIANT == 4 || _VARIANT == 6 +#define _CCX +#define HCF_MAX_MSG_CKIP_PADDING 86 //, use 86 for rx fragmentation. 28 is enuf for MIC+PPK encapsulation +#define HCF_MAX_MSG ( 1514 + HCF_MAX_MSG_CKIP_PADDING ) // need extra padding for CKIP (need to subtract 28 for NDIS) +#endif // _VARIANT == 4 || _VARIANT == 6 +#endif // WVLAN_48 +//#endif // WVLAN_46 + +#if !defined WVLAN_46 +#define _PEEK +#endif + +#ifndef _WIN32_WCE +// ASSERT already used by WinCE... +#ifdef ASSERT +#undef ASSERT +#define ASSERT(x) ASSERTDEBUGMSG((x), (TEXT("SIMULATE ASSERT:"))) +#endif +#endif + + +#if defined WVLAN_41 +#define MSF_COMPONENT_ID COMP_ID_MINIPORT_NDIS_31 +#endif // WVLAN_41 +#if defined WVLAN_48 && !defined _WIN32_WCE +#define MSF_COMPONENT_ID COMP_ID_MINIPORT_NDIS_50 +#endif // WVLAN_48 / _WIN32_WCE +#if defined WVLAN_52 && !defined _WIN32_WCE +#define MSF_COMPONENT_ID COMP_ID_MINIPORT_NDIS_40 +#endif // WVLAN_52 / _WIN32_WCE +#if defined WVLAN_46 +#define MSF_COMPONENT_ID COMP_ID_WIN_CE +#endif // _WIN32_WCE + +#define MSF_COMPONENT_VAR _VARIANT + +#define T1__HCF_TYPE (HCF_TYPE_NONE) + +#define T2__HCF_TYPE (T1__HCF_TYPE) + +#ifdef _WARP +#define T3__HCF_TYPE (T2__HCF_TYPE | HCF_TYPE_HII5 | HCF_TYPE_WARP ) +#else +#if _VARIANT == 7 +#define T3__HCF_TYPE (T2__HCF_TYPE | HCF_TYPE_HII5) +#else // _VARIANT == 7 +#define T3__HCF_TYPE (T2__HCF_TYPE) +#endif // _VARIANT == 7 +#endif // _WARP + +#ifdef _CCX_OK +#define T4__HCF_TYPE (T3__HCF_TYPE | HCF_TYPE_CCX) +#else +#define T4__HCF_TYPE (T3__HCF_TYPE) +#endif // _CCX_OK + +//not suitable for H-II #define HCF_CFG_STA_1_BOTTOM 16 + +// Default WPA in ON for all drivers except for WARP driver +#ifdef _WARP +#define T5__HCF_TYPE (T4__HCF_TYPE) +#else // _WARP +#define T5__HCF_TYPE (T4__HCF_TYPE | HCF_TYPE_WPA) +#endif // _WARP + +#define HCF_TYPE (T5__HCF_TYPE) + +// This is needed to get aux_ctrl() from the HCF for WlFreezeAndDump() +#if (defined DBG && DBG != 0) +#ifndef STATIC +#define STATIC +#endif +#endif + +#if !defined SOFTRONICS_CODE && !defined _APIDLL && !defined _WIN32_WCE +#include +#endif // SOFTRONICS_CODE / _APIDLL / _WIN32_WCE +#if defined _WIN32_WCE +#include +#include +#endif // _WIN32_WCE +#include "version.h" + +#define MSF_COMPONENT_MAJOR_VER TPI_MAJOR_VERSION +#define MSF_COMPONENT_MINOR_VER TPI_MINOR_VERSION + +#if !defined _APIDLL && !defined _WIN32_WCE + +__inline UCHAR NDIS_IN_BYTE( ULONG port ) +{ + UCHAR value; + NdisRawReadPortUchar(port , &value); + return (value); +} + +__inline ULONG NDIS_IN_LONG( ULONG port ) +{ + ULONG value; + NdisRawReadPortUlong(port , &value); + return (value); +} +__inline USHORT NDIS_IN_WORD( ULONG port ) +{ + USHORT value; + NdisRawReadPortUshort(port , &value); + return (value); +} + +#define IN_PORT_DWORD(port) NDIS_IN_LONG( (ULONG) (port) ) +#define IN_PORT_WORD(port) NDIS_IN_WORD( (ULONG) (port) ) +#define OUT_PORT_DWORD(port, value) NdisRawWritePortUlong((ULONG) (port) , value) +#define OUT_PORT_WORD(port, value) NdisRawWritePortUshort((ULONG) (port) , (USHORT) (value)) + +#define IN_PORT_STRING_8_16(port, addr, len) IN_PORT_STRING_16(port, addr, len) +#define OUT_PORT_STRING_8_16(port, addr, len) OUT_PORT_STRING_16(port, addr, len) + +#define IN_PORT_STRING_32(port, addr, len) { \ + NdisRawReadPortBufferUlong(port, addr, (len)); \ +} + +#define OUT_PORT_STRING_32(port, addr, len) { \ + NdisRawWritePortBufferUlong(port, addr, (len)); \ +} + +#define IN_PORT_STRING_16(port, addr, len) NdisRawReadPortBufferUshort(port, addr, (len)); +#define OUT_PORT_STRING_16(port, addr, len) NdisRawWritePortBufferUshort(port, addr, (len)); + +#endif // _APIDLL / _WIN32_WCE + +#if defined _WIN32_WCE + +#define HCF_ALIGN 2 +#define HCF_MEM_IO 1 // overrule standard Port I/O with Memory mapped I/O +#define HCF_PROT_TIME 49 + +#define IN_PORT_BYTE CE_IN_PORT_BYTE +#define OUT_PORT_BYTE CE_OUT_PORT_BYTE +#define IN_PORT_WORD CE_IN_PORT_WORD +#define OUT_PORT_WORD CE_OUT_PORT_WORD +#define IN_PORT_STRING_16 CE_IN_PORT_STRING +#define OUT_PORT_STRING_16 CE_OUT_PORT_STRING + +extern hcf_8 CE_IN_PORT_BYTE(hcf_32 port); +extern void CE_OUT_PORT_BYTE(hcf_32 port, hcf_8 value); +extern hcf_16 CE_IN_PORT_WORD(hcf_32 port); +extern void CE_OUT_PORT_WORD(hcf_32 port, hcf_16 value); +extern void CE_IN_PORT_STRING(hcf_32 port, void *addr, hcf_16 len); +extern void CE_OUT_PORT_STRING(hcf_32 port, void *addr, hcf_16 len); + + +#endif + +#if defined _DEBUG || (defined DBG && DBG != 0) +#define HCF_ASSERT ( HCF_ASSERT_LNK_MSF_RTN | HCF_ASSERT_RT_MSF_RTN | HCF_ASSERT_PRINTF ) //0xC001 +//#define HCF_ASSERT ( HCF_ASSERT_LNK_MSF_RTN | HCF_ASSERT_RT_MSF_RTN | HCF_ASSERT_PRINTF | HCF_ASSERT_MB ) //just to test +#endif // _DEBUG || DBG + +#if defined DEBUG || defined _DEBUG || (defined DBG && DBG != 0) +#ifdef _WIN32_WCE +#define DBGA2W(DBGSTR) CeConvertAnsiToUnicodeLen((char*)DBGSTR) +#define OUTPUTDEBUGMSG(dprintf_exp) ((void)((! ZONE_DEBUG) ? 0:ce_debug_out dprintf_exp)) +#define ASSERTDEBUGMSG(cond, dprintf_exp) ((void)((cond) ? 0:ce_debug_out dprintf_exp)) + +#define ZONE_ERROR DEBUGZONE(0) +#define ZONE_WARN DEBUGZONE(1) +#define ZONE_FUNCTION DEBUGZONE(2) +#define ZONE_INIT DEBUGZONE(3) +#define ZONE_INTR DEBUGZONE(4) +#define ZONE_RCV DEBUGZONE(5) +#define ZONE_XMIT DEBUGZONE(6) +#define ZONE_ASSERT DEBUGZONE(7) +#define ZONE_DEBUG DEBUGZONE(8) +#define ZONE_OEM DEBUGZONE(9) +#define ZONE_HCF DEBUGZONE(10) +#define ZONE_PORTIO DEBUGZONE(11) +#define ZONE_LOGTOFILE DEBUGZONE(15) + +#else // !(_WIN32_WCE) + +#define OUTPUTDEBUGMSG(dprintf_exp) ((void) (DbgPrint dprintf_exp)) +// the assertdebugmsg macro will print filename, line followed by a caller-defined text, when cond == 0 +#define ASSERTDEBUGMSG(cond, print) ((void)((cond) ? 0: (DbgPrint("%s %s:%d - ", print, __FILE__, __LINE__)))) + +#define ZONE_ERROR 1 +#define ZONE_WARN 1 +#define ZONE_FUNCTION 1 +#define ZONE_INIT 1 +#define ZONE_INTR 1 +#define ZONE_RCV 1 +#define ZONE_XMIT 1 +#define ZONE_ASSERT 1 +#define ZONE_DEBUG 1 +#define ZONE_OEM 1 +#define ZONE_HCF 1 +#define ZONE_PORTIO 1 +#define ZONE_LOGTOFILE 1 + +#endif // _WIN32_WCE +#ifndef DBGA2W +#define DBGA2W +#endif // DBGA2W + +#else // !(defined DEBUG || defined _DEBUG || (defined DBG && DBG != 0) ) +#define OUTPUTDEBUGMSG(dprintf_exp) +#define ASSERTDEBUGMSG(cond, dprintf_exp) +#endif // DEBUG / DBG + +#if !defined HCF_MAX_MSG_CKIP_PADDING +#define HCF_MAX_MSG_CKIP_PADDING 0 +#endif // HCF_MAX_MSG_CKIP_PADDING + +#if !defined HCF_MAX_MSG +#define HCF_MAX_MSG 1514 +#endif // HCF_MAX_MSG + +#define HCF_LEGACY 1 //;?nv je moet wat + +#endif //WVLAN_41 / WVLAN_48 / WVLAN_52 / _WIN32_WCE + + +/************************************************************************************************/ +/**************************** P A C K E T D R I V E R ***************************************/ +/********************************** D O S O D I *********************************************/ +/************************************************************************************************/ + +#if defined WVLAN_42 || defined WVLAN_43 + +#pragma warning ( disable: 4001 ) +#define FAR __far //segmented 16 bits mode +#define BASED __based(__segname("_CODE")) //force all the "const" structures in the CODE segment + +//#define HCF_IO 0 //no DMA, no 32 bits + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To ease testing the different options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define HCF_EXT HCF_EXT_MB +#define HCF_PROT_TIME 49 //49*10240 microseconds H/W failure protection timer + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To ease testing the different options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +/******************************** CONFIGURATION MANAGEMENT *****************************************/ +#ifdef WVLAN_42 +#define MSF_COMPONENT_ID COMP_ID_PACKET +#define MSF_COMPONENT_VAR 1 +#define MSF_COMPONENT_MAJOR_VER 6 +#define MSF_COMPONENT_MINOR_VER 12 +#endif // WVLAN_42 + +#ifdef WVLAN_43 +#define MSF_COMPONENT_ID COMP_ID_ODI_16 +#define MSF_COMPONENT_VAR 1 +#define MSF_COMPONENT_MAJOR_VER 6 +#define MSF_COMPONENT_MINOR_VER 10 +#endif // WVLAN_43 + +/************************************** INPUT / OUTPUT **********************************************/ +#ifndef H_2_INC +#include +#include +#if 1 //temorary use functions defined in hcf.c +#ifndef _DEBUG +#pragma intrinsic( _inp, _inpw, _outp, _outpw ) +#endif // _DEBUG + +#define IN_PORT_WORD(port) ((hcf_16)_inpw( (hcf_io)(port) )) +#define OUT_PORT_WORD(port, value) ((void)_outpw( (hcf_io)(port), value )) + +#if 1 // C implementation which let the processor handle the word-at-byte-boundary problem +#define IN_PORT_STRING_8_16( port, addr, n) while (n--) \ + { *(hcf_16 FAR*)addr = IN_PORT_WORD( port ); ((hcf_8 FAR*)addr)+=2; } +#define OUT_PORT_STRING_8_16( port, addr, n) while (n--) \ + { OUT_PORT_WORD( port, *(hcf_16 FAR*)addr ) ; ((hcf_8 FAR*)addr)+=2; } +#elif 0 // C implementation which handles the word-at-byte-boundary problem +#define IN_PORT_STRING_8_16( port, addr, n) while ( n-- ) \ + { hcf_16 i = IN_PORT_WORD(port); *((hcf_8 FAR*)addr)++ = (hcf_8)i; *((hcf_8 FAR*)addr)++ = (hcf_8)(i>>8);} +#define OUT_PORT_STRING_8_16( port, addr, n) while ( n-- ) \ + { OUT_PORT_WORD( port, *((hcf_8 FAR*)addr) | *(((hcf_8 FAR*)addr)+1)<<8 ); (hcf_8 FAR*)addr+=2; } +#else // Assembler implementation +#define IN_PORT_STRING_8_16( port, addr, n) __asm \ +{ \ + __asm push di \ + __asm push es \ + __asm mov cx,n \ + __asm les di,addr \ + __asm mov dx,port \ + __asm rep insw \ + __asm pop es \ + __asm pop di \ +} + +#define OUT_PORT_STRING_8_16( port, addr, n) __asm \ +{ \ + __asm push si \ + __asm push ds \ + __asm mov cx,n \ + __asm lds si,addr \ + __asm mov dx,port \ + __asm rep outsw \ + __asm pop ds \ + __asm pop si \ +} + +#endif // Asm or C implementation +#define IN_PORT_STRING_32( port, addr, n) { int n2 = 2*n; IN_PORT_STRING_8_16(port, addr, n2) } +#define OUT_PORT_STRING_32( port, addr, n) { int n2 = 2*n; OUT_PORT_STRING_8_16(port, addr, n2) } +#endif // 0 //temorary use functions defined in hcf.c +#endif // H_2_INC + +#endif // WVLAN_42 / WVLAN_43 + + + +/************************************************************************************************/ +/**************************** D O S H - I / II L O A D E R **********************************/ +/************************************************************************************************/ + +#if defined H0_LDR || defined H1_LDR || defined H2_LDR || defined H5_LDR + +#if defined H0_LDR //implies H-I +#define HCF_DLV 0 //H-I legacy, meaningless under H-II +#define HCF_DLNV 1 //H-I legacy, meaningless under H-II +#endif // H0_LDR + +#if defined H1_LDR //implies H-I +#define HCF_DLV 1 //H-I legacy, meaningless under H-II +#define HCF_DLNV 0 //H-I legacy, meaningless under H-II +#endif // H1_LDR / H2_LDR + +//#if defined H2_LDR : not needed, H-II defaults are O.K for H2_LDR + +#ifdef H5_LDR +#define HCF_TYPE (HCF_TYPE_HII5 | HCF_TYPE_WARP ) +//;? why does only this subset of the H_LDRs need HCF_TYPE to be defined here +#endif + +#define HCF_ASSERT HCF_ASSERT_LNK_MSF_RTN //support dynamic linking of msf_assert routine +#define HCF_ENCAP 0 +#define HCF_INT_ON 0 +#define HCF_TALLIES 0 + +#define MSF_COMPONENT_ID COMP_ID_ODI_16 //;?By lack of any better +#define MSF_COMPONENT_VAR 1 +#define MSF_COMPONENT_MAJOR_VER 0 +#define MSF_COMPONENT_MINOR_VER 0 + +#include +#include +#if defined NDEBUG +#pragma intrinsic( _inp, _inpw, _outp, _outpw ) +#endif // NDEBUG + +#if 0 //use 0 to replace I/O Macros with logging facility +#define IN_PORT_WORD(port) ((hcf_16)_inpw( (hcf_io)(port) )) +#define OUT_PORT_WORD(port, value) ((void)_outpw( (hcf_io)(port), value )) +#define IN_PORT_STRING_16( port, addr, n) \ + while ( n-- ) { *(hcf_16 FAR*)addr = IN_PORT_WORD( port ); (cast)addr += 2; } +#define OUT_PORT_STRING_16( port, addr, n) \ + while ( n-- ) { OUT_PORT_WORD( port, *(hcf_16 FAR*)addr ) ; (cast)addr += 2; } +#endif //use 0 to replace I/O Macros with logging facility + +#endif // H0_LDR / H1_LDR / H2_LDR + + + +/************************************************************************************************/ +/**************************** H C F D E M O P R O G R A M ***********************************/ +/************************************************************************************************/ + +#if defined HCF_DEMO + +#define HCF_DLV 1 //;?should become the default !defaults to 1 anyway for H-II +//#define HCF_DLNV 0 //defaults to 0 anyway for H-II + +#define HCF_ASSERT HCF_ASSERT_LNK_MSF_RTN //support dynamic linking of msf_assert routine + +#define HCF_ENCAP 0 +#define HCF_INT_ON 0 +#define HCF_TALLIES ( HCF_TALLIES_NIC | HCF_TALLIES_HCF ) + +//#define MSF_COMPONENT_ID NO configuration management + +#include +#include +#if defined NDEBUG +#pragma intrinsic( _inp, _inpw, _outp, _outpw ) +#endif // NDEBUG + +#if 0 //use 0 to replace I/O Macros with logging facility +#define IN_PORT_WORD(port) ((hcf_16)_inpw( (hcf_io)(port) )) +#define OUT_PORT_WORD(port, value) ((void)_outpw( (hcf_io)(port), value )) +#define IN_PORT_STRING_16( port, addr, n) \ + while ( n-- ) { *(hcf_16 FAR*)addr = IN_PORT_WORD( port ); (cast)addr += 2; } +#define OUT_PORT_STRING_16( port, addr, n) \ + while ( n-- ) { OUT_PORT_WORD( port, *(hcf_16 FAR*)addr ) ; (cast)addr += 2; } +#endif //use 0 to replace I/O Macros with logging facility + +#endif // HCF_DEMO + + + +/************************************************************************************************/ +/*********************************** M A C O S **********************************************/ +/************************************************************************************************/ + +#if defined WVLAN_45 + +#include "Version.h" + +#define MSF_COMPONENT_ID COMP_ID_MAC_OS +#define MSF_COMPONENT_VAR VARIANT +#define MSF_COMPONENT_MAJOR_VER VERSION_MAJOR +#define MSF_COMPONENT_MINOR_VER VERSION_MINOR + +#define MAC_OS 1 + +#define HCF_BIG_ENDIAN 1 // selects Big Endian (a.k.a. Motorola), most significant byte first + +#if defined DEBUG +#define HCF_ASSERT HCF_ASSERT_MB // logging via Mailbox +#endif // DEBUG + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus +extern volatile unsigned char *MacIOaddr; +extern hcf_16 IN_PORT_WORD(hcf_16 port); +extern void OUT_PORT_WORD(hcf_16 port, hcf_16 value); +extern void IN_PORT_STRING_16(hcf_16 port, void *addr, hcf_16 len); +extern void OUT_PORT_STRING_16(hcf_16 port, void *addr, hcf_16 len); + +#define SwapBytes(t) (((t) >> 8) + (((t) & 0xff) << 8)) + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // WVLAN_45 + + + +/************************************************************************************************/ +/****************************************** L I N U X *****************************************/ +/************************************************************************************************/ + +#ifdef WVLAN_49 +#include +//#include +#include + +/* The following macro ensures that no symbols are exported, minimizing the chance of a symbol + collision in the kernel */ +//EXPORT_NO_SYMBOLS; //;?this place seems not appropriately to me + +//#define HCF_SLEEP (HCF_CDS | HCF_DDS ) +#define HCF_SLEEP (HCF_CDS) + +//#define HCF_TYPE (HCF_TYPE_HII5|HCF_TYPE_STA|HCF_TYPE_AP) +#ifdef HERMES25 +#ifdef WARP +#define HCF_TYPE ( HCF_TYPE_WARP | HCF_TYPE_HII5 ) +#else +#define HCF_TYPE HCF_TYPE_HII5 +#endif // WARP +#else +#define HCF_TYPE HCF_TYPE_NONE +#endif // HERMES25 + +#ifdef ENABLE_DMA +#define HCF_DMA 1 +#endif // ENABLE_DMA + +/* We now need a switch to include support for the Mailbox and other necessary extensions */ +#define HCF_EXT ( HCF_EXT_MB | HCF_EXT_INFO_LOG | HCF_EXT_INT_TICK )//get deepsleep exercise going + +/* ;? The Linux MSF still uses these definitions; define it here until it's removed */ +#ifndef HCF_TYPE_HII +#define HCF_TYPE_HII 0x0004 +#endif + +#ifndef HCF_TYPE_AP +#define HCF_TYPE_AP 0x0010 +#endif + +#ifndef HCF_TYPE_STA +#define HCF_TYPE_STA 0x0020 +#endif // HCF_TYPE_STA + +/* Guarantees word alignment */ +#define HCF_ALIGN 2 + +/* Endian macros CNV_INT_TO_LITTLE() and CNV_LITTLE_TO_INT() were renamed to + CNV_SHORT_TO_LITTLE() and CNV_LITTLE_TO_SHORT() */ +#ifndef CNV_INT_TO_LITTLE +#define CNV_INT_TO_LITTLE CNV_SHORT_TO_LITTLE +#endif + +#ifndef CNV_LITTLE_TO_INT +#define CNV_LITTLE_TO_INT CNV_LITTLE_TO_SHORT +#endif + +#define HCF_ERR_BUSY 0x06 + +/* UIL defines were removed from the HCF */ +#define UIL_SUCCESS HCF_SUCCESS +#define UIL_ERR_TIME_OUT HCF_ERR_TIME_OUT +#define UIL_ERR_NO_NIC HCF_ERR_NO_NIC +#define UIL_ERR_LEN HCF_ERR_LEN +#define UIL_ERR_MIN HCF_ERR_MAX /*end of HCF errors which are passed through to UIL + *** ** *** ****** ***** *** ****** ******* ** *** */ +#define UIL_ERR_IN_USE 0x44 +#define UIL_ERR_WRONG_IFB 0x46 +#define UIL_ERR_MAX 0x7F /*upper boundary of UIL errors without HCF-pendant + ***** ******** ** *** ****** ******* *** ******* */ +#define UIL_ERR_BUSY HCF_ERR_BUSY +#define UIL_ERR_DIAG_1 HCF_ERR_DIAG_1 +#define UIL_FAILURE 0xFF /* 20010705 nv this relick should be eridicated */ +#define UIL_ERR_PIF_CONFLICT 0x40 //obsolete +#define UIL_ERR_INCOMP_DRV 0x41 //obsolete +#define UIL_ERR_DOS_CALL 0x43 //obsolete +#define UIL_ERR_NO_DRV 0x42 //obsolete +#define UIL_ERR_NSTL 0x45 //obsolete + + + +#if 0 //;? #ifdef get this going LATER HERMES25 +#define HCF_IO HCF_IO_32BITS +#define HCF_DMA 1 +#define HCF_DESC_STRCT_EXT 4 + +/* Switch for BusMaster DMA support. Note that the above define includes the DMA-specific HCF + code in the build. This define sets the MSF to use DMA; if ENABLE_DMA is not defined, then + port I/O will be used in the build */ +#ifndef BUS_PCMCIA +#define ENABLE_DMA +#endif // USE_PCMCIA + +#endif // HERMES25 + + +/* Overrule standard WaveLAN Packet Size when in DMA mode */ +#ifdef ENABLE_DMA +#define HCF_MAX_PACKET_SIZE 2304 +#else +#define HCF_MAX_PACKET_SIZE 1514 +#endif // ENABLE_DMA + +/* The following sets the component ID, as well as the versioning. See also wl_version.h */ +#define MSF_COMPONENT_ID COMP_ID_LINUX + +#define MSF_COMPONENT_VAR DRV_VARIANT +#define MSF_COMPONENT_MAJOR_VER DRV_MAJOR_VERSION +#define MSF_COMPONENT_MINOR_VER DRV_MINOR_VERSION + +/* Define the following to turn on assertions in the HCF */ +//#define HCF_ASSERT 0x8000 +#define HCF_ASSERT HCF_ASSERT_LNK_MSF_RTN // statically binding of msf_assert routine + +#ifdef USE_BIG_ENDIAN +#define HCF_BIG_ENDIAN 1 +#else +#define HCF_BIG_ENDIAN 0 +#endif /* USE_BIG_ENDIAN */ + +/* Define the following if your system uses memory-mapped IO */ +//#define HCF_MEM_IO + +/* The following defines the standard macros required by the HCF to move data to/from the card */ +#define IN_PORT_BYTE(port) ((hcf_8)inb( (hcf_io)(port) )) +#define IN_PORT_WORD(port) ((hcf_16)inw( (hcf_io)(port) )) +#define OUT_PORT_BYTE(port, value) (outb( (hcf_8) (value), (hcf_io)(port) )) +#define OUT_PORT_WORD(port, value) (outw((hcf_16) (value), (hcf_io)(port) )) + +#define IN_PORT_STRING_16(port, dst, n) insw((hcf_io)(port), dst, n) +#define OUT_PORT_STRING_16(port, src, n) outsw((hcf_io)(port), src, n) +//#define IN_PORT_STRINGL(port, dst, n) insl((port), (dst), (n)) +//#define OUT_PORT_STRINGL(port, src, n) outsl((port), (src), (n)) +#define IN_PORT_STRING_32(port, dst, n) insl((port), (dst), (n)) +#define OUT_PORT_STRING_32(port, src, n) outsl((port), (src), (n)) +#define IN_PORT_HCF32(port) inl( (hcf_io)(port) ) +#define OUT_PORT_HCF32(port, value) outl((hcf_32)(value), (hcf_io)(port) ) + +#define IN_PORT_DWORD(port) IN_PORT_HCF32(port) +#define OUT_PORT_DWORD(port, value) OUT_PORT_HCF32(port, value) + +#define IN_PORT_STRING_8_16(port, addr, len) IN_PORT_STRING_16(port, addr, len) +#define OUT_PORT_STRING_8_16(port, addr, len) OUT_PORT_STRING_16(port, addr, len) + + +#ifndef OUTPUTDEBUGMSG +#define OUTPUTDEBUGMSG(dprintf_exp) +#endif + + +#ifndef ASSERTDEBUGMSG +#define ASSERTDEBUGMSG(cond, dprintf_exp) +#endif + +#ifndef CFG_SCAN_CHANNELS_2GHZ +#define CFG_SCAN_CHANNELS_2GHZ 0xFCC2 +#endif /* CFG_SCAN_CHANNELS_2GHZ */ + +#define HCF_MAX_MSG 1600 //get going ;? +#endif // WVLAN_49 + + + +/************************************************************************************************/ +/********************************************* Q N X ******************************************/ +/************************************************************************************************/ + +#if defined __QNX__ || defined WVLAN_50 + +#define MSF_COMPONENT_ID 0 //Although there is no DUI support, we need this to get ... +#define MSF_COMPONENT_VAR 0 //...compatibilty check to function +#define MSF_COMPONENT_MAJOR_VER 0 //...;?this is worth looking into to make this a more +#define MSF_COMPONENT_MINOR_VER 0 //..."defined" I/F so OEMers can figure out what to do + +#include + +#define IN_PORT_WORD(port) ((hcf_16)inpw( (hcf_io)(port) )) +#define OUT_PORT_WORD(port, value) (outpw( (hcf_io)(port), (hcf_16) (value) )) +/* +#define IN_PORT_STRING_16( port, addr, n) \ + while ( n-- ) { *(hcf_16*)addr = IN_PORT_WORD( port ); (cast)addr += 2; } +#define OUT_PORT_STRING_16( port, addr, n) \ + while ( n-- ) { OUT_PORT_WORD( port, *(hcf_16*)addr ) ; (cast)addr += 2; } +*/ + +#endif // QNX / WVLAN_50 + + + +/************************************************************************************************/ +/********************************************* B E O S ****************************************/ +/************************************************************************************************/ + +#if defined __BEOS__ + +#define MSF_COMPONENT_ID 0 //Although there is no DUI support, we need this to get ... +#define MSF_COMPONENT_VAR 0 //...compatibilty check to function +#define MSF_COMPONENT_MAJOR_VER 0 //...;?this is worth looking into to make this a more +#define MSF_COMPONENT_MINOR_VER 0 //..."defined" I/F so OEMers can figure out what to do + +#include +#include + +uint8 read_io_8 (int); +void write_io_8 (int, uint8); +uint16 read_io_16 (int); +void write_io_16 (int, uint16); + +#define IN_PORT_WORD(port) ((hcf_16)read_io_16( (hcf_io)(port) )) +#define OUT_PORT_WORD(port, value) (write_io_16( (hcf_io)(port), (hcf_16) (value) )) +/* +#define IN_PORT_STRING_16( port, addr, n) \ + while ( n-- ) { *(hcf_16*)addr = IN_PORT_WORD( port ); (cast)addr += 2; } +#define OUT_PORT_STRING_16( port, addr, n) \ + while ( n-- ) { OUT_PORT_WORD( port, *(hcf_16*)addr ) ; (cast)addr += 2; } +*/ +#endif // __BEOS__ + + + +/************************************************************************************************/ +/******************************** U S B D O N G L E *****************************************/ +/************************************************************************************************/ + +#if defined USB +#include "gpif.h" + +#define MSF_COMPONENT_MAJOR_VER 0 +#define MSF_COMPONENT_MINOR_VER 1 + +#define IN_PORT_WORD(port) (Hermes_IO_Read( (hcf_8)(port))) +#define OUT_PORT_WORD(port, value) (Hermes_IO_Write( (hcf_8)port, /*(hcf_16)*/(value) ) ) +/* !!!! NOTE USB supports only 16-bits I/O and no 8-bits I/O + * as a consequence the IN_/OUT_PORT_STRING_16 macros use hcf_16* rather than hcf_8 pointers + * to get more optimal code + * therefore the pointers are incremented by 1 (which means two "bytes") rather than by 2 + */ +//#define IN_PORT_STRING_16( port, addr, n) while ( n-- ) { *((hcf_16*)addr)++ = IN_PORT_WORD( port ); } +//#define OUT_PORT_STRING_16( port, addr, n) while ( n-- ) { OUT_PORT_WORD( port, *((hcf_16*)addr)++ ); } +#define IN_PORT_STRING_16( port, dst, n) while ( n-- ) { *dst++ = IN_PORT_WORD( port ); } +#define OUT_PORT_STRING_16( port, src, n) while ( n-- ) { OUT_PORT_WORD( port, *src++ ); } + +//#define HCF_TYPE ( HCF_TYPE_AP | HCF_TYPE_WPA ) +#define HCF_TYPE HCF_TYPE_WPA + +#endif // USB + + +/************************************************************************************************/ +/****************************************** FreeBSD *******************************************/ +/************************************************************************************************/ + +#if defined __FREE_BSD__ + +#define MSF_COMPONENT_ID COMP_ID_FreeBSD +#define MSF_COMPONENT_VAR 1 +#define MSF_COMPONENT_MAJOR_VER 1 +#define MSF_COMPONENT_MINOR_VER 0 + +#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O + +#include + +#define IN_PORT_WORD(port) ((hcf_16)inw( (hcf_io)(port) )) +#define OUT_PORT_WORD(port, value) (outw((hcf_io)(port), (hcf_16)(value))) + +/* +#define IN_PORT_STRING_16( port, addr, n) \ + while ( n-- ) { *(hcf_16*)addr = IN_PORT_WORD( port ); (cast)addr += 2; } +#define OUT_PORT_STRING_16( port, addr, n) \ + while ( n-- ) { OUT_PORT_WORD( port, *(hcf_16*)addr ) ; (cast)addr += 2; } +*/ +#endif // __FREE_BSD__ + + + +/************************************************************************************************/ +/********************************* W A V E P O I N T ******************************************/ +/************************************************************************************************/ + +#if defined WVLAN_81 /* BORLANDC */ + +#define EXTERN_C extern // needed because DHF uses this instead of 'extern' + +#define MSF_COMPONENT_ID COMP_ID_AP1 +#define MSF_COMPONENT_VAR 1 +#define MSF_COMPONENT_MAJOR_VER 4 +#define MSF_COMPONENT_MINOR_VER 0 + +#define HCF_PROT_TIME 49 //49*10240 microseconds H/W failure protection timer + +//#define HCF_ASSERT HCF_ASSERT_MB // logging via Mailbox /* debug build only */ + +#if !defined FAR +#define FAR far // segmented 16 bits mode +#endif // FAR + +#define IN_PORT_WORD(port) (inport( (hcf_io)(port) )) +#define OUT_PORT_WORD(port, value) (outport( (hcf_io)(port), value )) + +#define IN_PORT_STRING_16(port, addr, len) \ + asm { push di; push es; mov cx,len; les di,addr; mov dx,port; rep insw; pop es; pop di } + +#define OUT_PORT_STRING_16(port, addr, len) \ + asm { push si; push ds; mov cx,len; lds si,addr; mov dx,port; rep outsw; pop ds; pop si } + +#endif // WVLAN_81 + + +/************************************************************************************************/ +/******************************** W A V E L A U N C H *****************************************/ +/************************************************************************************************/ + +#if defined WVLAUNCH + +#include "DriverX.h" +extern HWDEVICE* g_pDevice; + +//#define MSF_COMPONENT_ID 0 //;? to get around browser problem + +#define IN_PORT_WORD(port) HwInpw( g_pDevice, port ) +#define OUT_PORT_WORD(port, value) HwOutpw( g_pDevice, port, value ) + + +// C implementation which let the processor handle the word-at-byte-boundary problem +/* +#define IN_PORT_STRING_16( port, addr, n) \ + while ( n-- ) { *(hcf_16 FAR*)addr = IN_PORT_WORD( port ); (cast)addr += 2; } +#define OUT_PORT_STRING_16( port, addr, n) \ + while ( n-- ) { OUT_PORT_WORD( port, *(hcf_16 FAR*)addr ) ; (cast)addr += 2; } +*/ +#endif // WVLAUNCH + + + +/************************************************************************************************/ +/************************************* W C I T S T *********************************************/ +/************************************************************************************************/ + +#if defined WCITST +#define MSF_COMPONENT_ID 0 //Although there is no DUI support, we need this to get ... +#define MSF_COMPONENT_VAR 0 //...compatibilty check to function +#define MSF_COMPONENT_MAJOR_VER 0 //...;?this is worth looking into to make this a more +#define MSF_COMPONENT_MINOR_VER 0 //..."defined" I/F so OEMers can figure out what to do + +//#define HCF_ENCAP HCF_ENC_NONE //to get going +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To ease testing the different options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +#define HCF_TYPE (HCF_TYPE_WPA | HCF_TYPE_PRELOADED) // Hermes-I for HCF6, II for HCF7 +#define HCF_DMA 1 +//#define LLB //!!!!MIC Debug Only +#if defined LLB && !((HCF_TYPE) & HCF_TYPE_WPA) +err: no LLB unless SSN; +#endif // LLB / HCF_TYPE_WPA +//#define HCF_ALIGN 2 +#define HCF_DLV 1 //just to change memory layout ????;? +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To ease testing the different options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define HCF_ASSERT HCF_ASSERT_SW_SUP // logging via Hermes support registerr +//#define HCF_ASSERT HCF_ASSERT_MB // logging via Mailbox + +#if defined __GNUC__ +#include "stdio.h" +//#include "unistd.h" //ioperm libc5 +#include "sys/io.h" //ioperm glibc +#define extern //see IO Port Programming mini-HOWTO +//#include "asm/io.h" // +#define IN_PORT_WORD(port) inw( (hcf_io)(port) ) +#define IN_PORT_DWORD(port) inl( (hcf_io)(port) ) +#define OUT_PORT_WORD(port, value) outw( (hcf_io)(port), (hcf_16)(value) ) +#define OUT_PORT_DWORD(port, value) outl( (hcf_io)(port), (hcf_16)(value) ) +#else +#pragma warning ( disable: 4001 ) +#define FAR __far // segmented 16 bits mode + +#include +#include +#ifndef _DEBUG +#pragma intrinsic( _inp, _inpw, _outp, _outpw ) +#endif // _DEBUG + +#ifdef LOG +extern FILE* utm_logfile; +hcf_16 ipw( hcf_16 port ); +hcf_8 ipb( hcf_16 port ); +void opw( hcf_16 port, hcf_16 value ); +void opb( hcf_16 port, hcf_8 value ); + +#define IN_PORT_WORD(port) ipw( (hcf_io)(port) ) +#define OUT_PORT_WORD(port, value) opw( (hcf_io)(port), (hcf_16)(value) ) +#else // LOG +#define IN_PORT_WORD(port) ((hcf_16)_inpw( (hcf_io)(port) )) +#define OUT_PORT_WORD(port, value) ((void)_outpw( (hcf_io)(port), value )) +#endif // LOG + +#if 1 //ASM example +#define IN_PORT_STRING_16( port, addr, len) __asm \ +{ \ + __asm push di \ + __asm push es \ + __asm mov cx,len \ + __asm les di,addr \ + __asm mov dx,port \ + __asm rep insw \ + __asm pop es \ + __asm pop di \ +} + +#define OUT_PORT_STRING_16( port, addr, len) __asm \ +{ \ + __asm push si \ + __asm push ds \ + __asm mov cx,len \ + __asm lds si,addr \ + __asm mov dx,port \ + __asm rep outsw \ + __asm pop ds \ + __asm pop si \ +} + +#endif // asm example + +#endif // __GCC__ + +#if ! defined IN_PORT_STRING_16 +#define IN_PORT_STRING_16( port, addr, n) while (n--) \ + { *(hcf_16 FAR*)addr = IN_PORT_WORD( port ); ((hcf_16 FAR*)addr)++; } +#define OUT_PORT_STRING_16( port, addr, n) while (n--) \ + { OUT_PORT_WORD( port, *(hcf_16 FAR*)addr ); ((hcf_16 FAR*)addr)++; } +#endif // IN_PORT_STRING_16 + +#endif // WCITST + + +/************************************************************************************************/ +/******************************* Motorola Power PC 800 family *********************************/ +/************************************************************************************************/ +/* known users: LH@I + */ + +#if defined I_MPC8XX + +#define MSF_COMPONENT_VAR 0 +#define MSF_COMPONENT_ID 0 +#define MSF_COMPONENT_MAJOR_VER 1 +#define MSF_COMPONENT_MINOR_VER 0 + +#define HCF_HSI_VAR 1 + +#define HCF_BIG_ENDIAN 1 +#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O + +#include "o_portbl.h" +#include "ipcmcia.h" +typedef o_uint8_t hcf_8; +typedef o_uint16_t hcf_16; +typedef o_uint32_t hcf_32; + +/***************************************************************************/ + + +#ifdef _lint +#else +asm hcf_16 IN_PORT_WORD(int port) +{ +% reg port + lhbrx r3,r0,port + eieio +} +#endif // _lint + + +#ifdef _lint +#else +asm void OUT_PORT_WORD(int port, hcf_16 value) +{ +% reg port, value + sthbrx value,r0,port + eieio +} +#endif // _lint + +/***************************************************************************/ + +#define IN_PORT_STRING_16(port, addr, len) \ + { \ + unsigned l = (len); \ + hcf_16 *d = (volatile hcf_16 *)(addr); \ + while (l--) \ + { \ + *d++ = *(volatile hcf_16 *)(port); \ + EIEIO(); \ + } \ + } + +#define OUT_PORT_STRING_16(port, addr, len) \ + { \ + unsigned l = (len); \ + hcf_16 *s = (volatile hcf_16 *)(addr); \ + while (l--) \ + { \ + *(volatile hcf_16 *)(port) = *s++; \ + EIEIO(); \ + } \ + } + +#endif // I_MPC8XX + + + +/************************************************************************************************/ +/********************************** Diab or High C 29K **************************************/ +/************************************************************************************************/ +/* known users: GK@C + */ + +#if defined _AM29K + +#define MSF_COMPONENT_VAR 0 +#define MSF_COMPONENT_ID COMP_ID_AP1 +#define MSF_COMPONENT_MAJOR_VER 1 +#define MSF_COMPONENT_MINOR_VER 0 + +#define HCF_BIG_ENDIAN 1 +#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O + +#define SwapBytes(t) /*lint -e572*/(((t) >> 8) + (((t) & 0xff) << 8))/*lint +e572*/ + +#if defined __ppc + #ifndef __GNUC__ + #define __asm__ asm + #endif + + #if ! defined _lint + #define EIEIO() __asm__(" eieio") + #else + #define EIEIO() + #endif + + static hcf_16 IN_PORT_WORD(int port) { + hcf_16 value = *(volatile hcf_16 *)(port); EIEIO(); + value = SwapBytes(value); + return value; + } + + #define OUT_PORT_WORD(port, value) \ + { *(volatile hcf_16 *)(port) = SwapBytes(value); EIEIO(); } +#else + #define IN_PORT_WORD(port) (*(volatile hcf_16 *)(port)) + #define OUT_PORT_WORD(port, value) (*(volatile hcf_16 *)(port) = (value)) +#endif // __ppc + +/***************************************************************************/ + +#define IN_PORT_STRING_16( port, addr, len) { \ + unsigned l = (len); \ + hcf_16 t, *d = (volatile hcf_16 *)(addr); \ + while (l--) { \ + t = IN_PORT_WORD(port); \ + *d++ = SwapBytes(t); \ + } \ + } + +#define OUT_PORT_STRING_16( port, addr, len) { \ + unsigned l = (len); \ + hcf_16 t, *s = (volatile hcf_16 *)(addr); \ + while (l--) { \ + t = *s++; \ + OUT_PORT_WORD(port, SwapBytes(t)); \ + } \ + } + +#if PRODUCT == 9150 + #define HCF_ASSERT HCF_ASSERT_MB // logging via Mailbox + #undef MSF_COMPONENT_ID +#endif // 9150 + +#endif // _AM29K + + + +/************************************************************************************************/ +/***************************************** MPC860 **********************************************/ +/************************************************************************************************/ +/* known users: RR + */ + +#if defined CPU +#if CPU == PPC860 + +#define MSF_COMPONENT_VAR 0 +#define MSF_COMPONENT_ID 0 +#define MSF_COMPONENT_MAJOR_VER 1 +#define MSF_COMPONENT_MINOR_VER 0 + +#define HCF_BIG_ENDIAN 1 +#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O + +#define SwapBytes(t) /*lint -e572*/(((t) >> 8) + (((t) & 0xff) << 8))/*lint +e572*/ + +#ifndef __GNUC__ + #define __asm__ asm +#endif + +#if ! defined _lint + #define EIEIO() __asm__(" eieio") +#else + #define EIEIO() +#endif + +static hcf_16 IN_PORT_WORD(int port) { + hcf_16 value = *(volatile hcf_16 *)(port); EIEIO(); + value = SwapBytes(value); + return value; + #ifdef __GNUC__ + /* the following serves to avoid the compiler warnings that + * IN_PORT_WORD() is not used in some files */ + (void)IN_PORT_WORD; + #endif +} + +#define OUT_PORT_WORD(port, value) \ + { *(volatile hcf_16 *)(port) = SwapBytes(value); EIEIO(); } + +/***************************************************************************/ + +#define IN_PORT_STRING_16( port, addr, len) { \ + unsigned l = (len); \ + hcf_16 t; \ + volatile hcf_16 *d = (volatile hcf_16 *)(addr); \ + while (l--) { \ + t = IN_PORT_WORD(port); \ + *d++ = SwapBytes(t); \ + } \ + } + +#define OUT_PORT_STRING_16( port, addr, len) { \ + unsigned l = (len); \ + hcf_16 t; \ + volatile hcf_16 *s = (volatile hcf_16 *)(addr); \ + while (l--) { \ + t = *s++; \ + OUT_PORT_WORD(port, SwapBytes(t)); \ + } \ + } + +#if PRODUCT == 9150 + #define HCF_ASSERT HCF_ASSERT_MB // logging via Mailbox + #undef MSF_COMPONENT_ID +#endif + +#endif /* PPC860 */ +#endif /* CPU */ + + + +/************************************************************************************************/ +/**************************** Microtec Research 80X86 Compiler *********************************/ +/************************************************************************************************/ + +#if 0 + +//#undef HCF_TYPE // Hermes-I Station F/W without SSN support + +#define MSF_COMPONENT_VAR 0 +#define MSF_COMPONENT_ID 0 +#define MSF_COMPONENT_MAJOR_VER 1 +#define MSF_COMPONENT_MINOR_VER 0 + +extern int far inp( int ); +extern void far outp( int, int ); +extern int far inpw( int ); +extern void far outpw( int, int ); + +#define IN_PORT_WORD(port) ((hcf_16)inpw( (hcf_io)(port) )) +#define OUT_PORT_WORD(port, value) ((void)outpw( (hcf_io)(port), value )) + +#define IN_PORT_STRING_16( port, addr, len) { \ + unsigned l = (len); \ + hcf_16 *d = (hcf_16 *)(addr); \ + while (l--) *d++ = IN_PORT_WORD(port); \ + } + +#define OUT_PORT_STRING_16( port, addr, len) { \ + unsigned l = (len); \ + hcf_16 *s = (hcf_16 *)(addr); \ + while (l--) OUT_PORT_WORD(port, *s++); \ + } +#endif /* Microtec 80X86 C Compiler */ + + + +/************************************************************************************************/ +/****************************** W A V E L A N E C ********************************************/ +/************************************************************************************************/ +/* known users: KM + */ + +#ifdef mc68302 + +#define MSF_COMPONENT_ID COMP_ID_EC + +#include + +#define MSF_COMPONENT_VAR 1 +#define MSF_COMPONENT_MAJOR_VER MAJOR_VERSION +#define MSF_COMPONENT_MINOR_VER MINOR_VERSION + +#define HCF_BIG_ENDIAN 1 +#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O + +#define SwapBytes(t) /*lint -e572*/(((t) >> 8) + (((t) & 0xff) << 8))/*lint +e572*/ + +#define PCMCIA_ADDRESS 0xc80000UL + +#define IN_PORT_2BYTES(port) (*(hcf_16 *)(port)) +#if 0 +static hcf_16 IN_PORT_WORD(hcf_32 port) // should be hcf_io, not hcf_32 +{ + hcf_16 word = IN_PORT_2BYTES(port); + return SwapBytes(word); +} +#else +static hcf_16 swap_var; +#define IN_PORT_WORD(port) \ + (((swap_var = IN_PORT_2BYTES(port)) >> 8) + (((swap_var) & 0xff) << 8)) +#endif +#define OUT_PORT_2BYTES(port, value) (*(hcf_16 *)(port) = (hcf_16)(value)) +#define OUT_PORT_WORD(port, value) OUT_PORT_2BYTES(port, SwapBytes(value)) + +/* +#define IN_PORT_STRING_16(port, addr, len) \ + while ((len)--) {*(hcf_16 *)(addr) = IN_PORT_2BYTES(port); ((cast)addr) += 2; } +#define OUT_PORT_STRING_16(port, addr, len) \ + while ((len)--) {OUT_PORT_2BYTES((port), *(hcf_16 *)(addr)) ; ((cast)addr) += 2; } +*/ + +#endif /* mc68302 */ + + + +/************************************************************************************************/ +/********************************* NGAP ***************************************/ +/************************************************************************************************/ + +#if defined __VX_WORKS__ /* VxWorks */ + +#if defined WLC_STATION +//#undef HCF_TYPE /* Hermes-I Station F/W without SSN support */ +#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_ENDSTA +#else +#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_ENDAP +#endif // WLC_STATION + +#define HCF_YIELD (taskDelay(0) == 0) + +#define MSF_COMPONENT_VAR 1 +#define MSF_COMPONENT_MAJOR_VER 1 +#define MSF_COMPONENT_MINOR_VER 0 + +// #define HCF_ASSERT HCF_ASSERT_MB // logging via Mailbox + +#if defined PC486BSP + +#define IN_PORT_WORD(port) (sysInWord ((hcf_io)(port))) +#define OUT_PORT_WORD(port, value) (sysOutWord ((hcf_io)(port), (hcf_16) (value))) +#define IN_PORT_STRING_16(port, addr, n) (sysInWordString ((hcf_io)(port), addr, n)) +#define OUT_PORT_STRING_16(port, addr, n) (sysOutWordString ((hcf_io)(port), addr, n)) + +#elif defined AS2000BSP + +#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O + +/* Define PCI stuff here. */ +unsigned short sysRead16( unsigned short *port ); +void sysWrite16( unsigned short *port, unsigned short value ); + +#define PCI_IN_BYTE( port ) \ + *(unsigned char *)( port ) + +#define PCI_IN_WORD( port ) \ + sysRead16( (unsigned short *)( port ) ) + +#define PCI_OUT_BYTE( port, value ) \ + *(unsigned char *)( port ) = (unsigned char)( value ) + +#define PCI_OUT_WORD( port, value ) \ + sysWrite16( (unsigned short *)( port ), (unsigned short)( value ) ) + +#define IN_PORT_WORD( port ) \ + PCI_IN_WORD( port ) + +#define OUT_PORT_WORD( port, value ) \ + PCI_OUT_WORD( port, value ) + +#define IN_PORT_STRING_16( port, buf, len ) \ + do { \ + hcf_16 *p; \ + \ + for ( p = (hcf_16 *)(buf); p < &( (hcf_16 *)(buf) )[ (int)len ]; p++ ) { \ + *p = PCI_IN_WORD( port ); \ + } \ + } while ( 0 ) + +#define OUT_PORT_STRING_16( port, buf, len ) \ + do { \ + const hcf_16 *p; \ + \ + for ( p = (const hcf_16 *)( buf ); p < &( (const hcf_16 *)(buf) )[ (int)len ]; p++ ) { \ + PCI_OUT_WORD( port, *p ); \ + } \ + } while ( 0 ) + +#elif defined FADS860BSP /* elif defined AS2000BSP */ + +#define HCF_BIG_ENDIAN 1 + +#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O + +#ifndef __GNUC__ + #define __asm__ asm +#endif + +#if ! defined _lint + #define EIEIO() __asm__(" eieio") +#else + #define EIEIO() +#endif + +static hcf_16 IN_PORT_WORD(int port) { + hcf_16 value = *(volatile hcf_16 *)(port); EIEIO(); + value = ((value & 0xff00) >> 8) + ((value & 0x00ff) << 8); +/* value = CNV_LITTLE_TO_SHORT(value); */ + return value; + #ifdef __GNUC__ + /* the following serves to avoid the compiler warnings that + * IN_PORT_WORD() is not used in some files */ + (void)IN_PORT_WORD; + #endif +} + +#define OUT_PORT_WORD(port, value) \ + { *(volatile hcf_16 *)(port) = CNV_SHORT_TO_LITTLE(value); EIEIO(); } + +/***********************************************************************/ + +#define IN_PORT_STRING_16( port, addr, len) { \ + unsigned l = (len); \ + volatile hcf_16 *d = (volatile hcf_16 *)(addr); \ + while (l--) { \ + *d++ = *(volatile hcf_16 *)(port); \ + EIEIO(); \ + } \ + } + +#define OUT_PORT_STRING_16( port, addr, len) { \ + unsigned l = (len); \ + volatile hcf_16 *s = (volatile hcf_16 *)(addr); \ + while (l--) { \ + *(volatile hcf_16 *)(port) = *s++; \ + EIEIO(); \ + } \ + } + +#elif defined DAYTONABSP + +#define HCF_BIG_ENDIAN 1 + +#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O + +#ifndef __GNUC__ + #define __asm__ asm +#endif + +#define IN_PORT_WORD(port) (sysOrinocoInWord((unsigned long)(port))) +#define OUT_PORT_WORD(port,value) (sysOrinocoOutWord((unsigned long)(port), (unsigned short)(value))) + +#define IN_PORT_STRING_16(port,addr,len) (sysOrinocoInString((port), (addr), (len))) +#define OUT_PORT_STRING_16(port,addr,len) (sysOrinocoOutString((port), (addr), (len))) + +extern unsigned char sysOrinocoInByte (unsigned long port); +extern unsigned short sysOrinocoInWord (unsigned long port); +extern void sysOrinocoInString (unsigned long port, void *addr, unsigned short len); + +extern void sysOrinocoOutByte (unsigned long port, unsigned char value); +extern void sysOrinocoOutWord (unsigned long port, unsigned short value); +extern void sysOrinocoOutString (unsigned long port, void *addr, unsigned short len); + +#elif defined ALPHA_BSP + +#define HCF_BIG_ENDIAN 1 + +#define HCF_IO HCF_IO_MEM // overrule standard Port I/O with Memory mapped I/O + +#ifndef __GNUC__ + #define __asm__ asm +#endif + +#define IN_PORT_WORD(port) (sysOrinocoInWord((unsigned long)(port))) +#define OUT_PORT_WORD(port,value) (sysOrinocoOutWord((unsigned long)(port), (unsigned short)(value))) + +#define IN_PORT_STRING_16(port,addr,len) (sysOrinocoInString((port), (addr), (len))) +#define OUT_PORT_STRING_16(port,addr,len) (sysOrinocoOutString((port), (addr), (len))) + +extern unsigned char sysOrinocoInByte (unsigned long port); +extern unsigned short sysOrinocoInWord (unsigned long port); +extern void sysOrinocoInString (unsigned long port, void *addr, unsigned short len); + +extern void sysOrinocoOutByte (unsigned long port, unsigned char value); +extern void sysOrinocoOutWord (unsigned long port, unsigned short value); +extern void sysOrinocoOutString (unsigned long port, void *addr, unsigned short len); + +#else + +err: /* commented here */ /* "BSP is not defined..." */ + +#endif /* else PC486BSP */ + +#endif // __VX_WORKS__ + + + +/************************************************************************************************/ +/****************************** VXWORKS. Motorola Sandpoint PowerPC 824X ***********************/ +/************************************************************************************************/ +#ifdef __VX_WORKS_SANDPOINT_824X__ + +#include +#include +#include + +#ifdef WVLAN_53 +#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_ENDSTA +#endif /* WVLAN_53 */ + +#ifdef WVLAN_54 +#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_ENDAP +#endif /* WVLAN_54 */ + +#ifdef WVLAN_56 +#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_END +#endif /* WVLAN_56 */ + +#if !defined MSF_COMPONENT_ID +#error "you must define an MSF component ID: WVLAN_53, WVLAN_54, WVLAN_56" +#endif + +#define MSF_COMPONENT_VAR 1 + +#define HCF_EXT HCF_EXT_INFO_LOG +#define HCF_SLEEP ( HCF_CDS | HCF_DDS ) +//#define HCF_SLEEP ( HCF_DDS ) + +#ifndef HCF_ACT_WAKEUP +#define HCF_ACT_WAKEUP 0x1D +#endif // HCF_ACT_WAKEUP + +#if defined FATNIC | defined BEAGLE_H253 +#define T1__HCF_TYPE HCF_TYPE_STA +#else +#define T1__HCF_TYPE HCF_TYPE_AP | HCF_TYPE_STA +#endif + +#ifdef HERMES_USB +#define T2__HCF_TYPE (T1__HCF_TYPE | HCF_TYPE_USB) +#else // HERMES_USB +#define T2__HCF_TYPE (T1__HCF_TYPE) +#endif // HERMES_USB + +#ifdef _WARP +#define T3__HCF_TYPE (T2__HCF_TYPE | HCF_TYPE_HII5) +#else // _WARP +#define T3__HCF_TYPE (T2__HCF_TYPE | HCF_TYPE_WPA | HCF_TYPE_HII) +#endif // WARP + +#ifdef _CCX +#define T4__HCF_TYPE (T3__HCF_TYPE | HCF_TYPE_CCX) +#else // _WARP +#define T4__HCF_TYPE (T3__HCF_TYPE) +#endif // _CCX + +#define T5__HCF_TYPE (T4__HCF_TYPE) + +// Default to TYPE_AP + SSN! +#define HCF_TYPE (T5__HCF_TYPE ) + + + +#define MSF_COMPONENT_MAJOR_VER 2 +#define MSF_COMPONENT_MINOR_VER 0 + +#define HCF_IO HCF_IO_MEM +#define HCF_DMA 0 +#define HCF_MEM_IO 1 +#define HCF_BIG_ENDIAN 1 + +//#define support_32bits 1 + +#define IN_PORT_WORD(port) (sysInWord( (hcf_io)(port) )) +#define OUT_PORT_WORD(port, value) (sysOutWord( (hcf_io)(port), (hcf_16)(value) )) +#define IN_PORT_DWORD(port) (sysInLong( (hcf_io)(port) )) +#define OUT_PORT_DWORD(port, value) (sysOutLong( (hcf_io)(port), (hcf_16)(value) )) +#define IN_PORT_STRING_16(port, dst, n) (sysInWordString((hcf_io)(port), (hcf_16 *)dst, n)) +#define OUT_PORT_STRING_16(port, src, n) (sysOutWordString((hcf_io)(port), (hcf_16 *)src, n)) + +#ifdef WVLAN_DEBUG +#define DBG 1 +#define _DEBUG 1 +#endif + +/* we'll need to add these prints someday */ +#define OUTPUTDEBUGMSG(dprintf_exp) +#define ASSERTDEBUGMSG(cond, dprintf_exp) + +#define HCF_INTERFACE_CONNECT(ifbp) +#define HCF_INTERFACE_DISCONNECT(ifbp) +#define HCF_ENTER_INTERFACE_FUNCT(ibfb) +#define HCF_LEAVE_INTERFACE_FUNCT(ifbp) + +#define CNV_END_INT(w) ( ((hcf_16)(w) & 0x00FF) << 8 | ((hcf_16)(w) & 0xFF00) >> 8 ) +#define CNV_LITTLE_TO_INT(w) CNV_END_INT(w) +#define CNV_INT_TO_LITTLE(w) CNV_LITTLE_TO_INT(w) + +#endif /* __VX_WORKS_SANDPOINT_824X__ */ + +/************************************************************************************************/ +/************************************* VXWORKS. ARM T8300 IPPhone *****************************/ +/************************************************************************************************/ +#if defined( IPT_T8300 ) || defined( IPT_T8307 ) + +#include +#include +#include + +#define HCF_ALIGN 4 /* default to 4 byte alignment */ + +#define BEAGLE_H253 /* Hermes 2.5.3 build, better to be in the project file */ +#define OOR_DDS /* Hermes 2.5.3 build, better to be in the project file */ +#define FATNIC + + +#ifdef WVLAN_53 +#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_ENDSTA +#endif /* WVLAN_53 */ + +#ifdef WVLAN_54 +#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_ENDAP +#endif /* WVLAN_54 */ + +#ifdef WVLAN_56 +#define MSF_COMPONENT_ID COMP_ID_VX_WORKS_END +#endif /* WVLAN_56 */ + +#if !defined MSF_COMPONENT_ID +#error "you must define an MSF component ID: WVLAN_53, WVLAN_54, WVLAN_56" +#endif + +#define MSF_COMPONENT_VAR 1 + +#define HCF_EXT HCF_EXT_INFO_LOG +//#define HCF_EXT HCF_EXT_INFO_LOG | HCF_EXT_MB +#define HCF_SLEEP ( HCF_CDS | HCF_DDS ) +//#define HCF_SLEEP ( HCF_DDS ) + +#ifndef HCF_ACT_WAKEUP +#define HCF_ACT_WAKEUP 0x1D +#endif // HCF_ACT_WAKEUP + +#if defined FATNIC || defined BEAGLE_H253 +#define T1__HCF_TYPE HCF_TYPE_STA +#else +//#define T1__HCF_TYPE HCF_TYPE_AP | HCF_TYPE_STA +#define T1__HCF_TYPE HCF_TYPE_STA /* dz, Station code only */ +#endif + +#ifdef HERMES_USB +#define T2__HCF_TYPE (T1__HCF_TYPE | HCF_TYPE_USB) +#else // HERMES_USB +#define T2__HCF_TYPE (T1__HCF_TYPE) +#endif // HERMES_USB + +#ifdef _WARP +#define T3__HCF_TYPE (T2__HCF_TYPE | HCF_TYPE_HII5) +#else // _WARP +#define T3__HCF_TYPE (T2__HCF_TYPE | HCF_TYPE_WPA | HCF_TYPE_HII) +//#define T3__HCF_TYPE (T2__HCF_TYPE | HCF_TYPE_HII) /* dz. no WPA support at this time, test code */ +#endif // WARP + +#ifdef _CCX +#define T4__HCF_TYPE (T3__HCF_TYPE | HCF_TYPE_CCX) +#else // _WARP +#define T4__HCF_TYPE (T3__HCF_TYPE) +#endif // _CCX + +#define T5__HCF_TYPE (T4__HCF_TYPE) + +// Default to TYPE_AP + SSN! +#define HCF_TYPE (T5__HCF_TYPE ) + + +#define MSF_COMPONENT_MAJOR_VER 2 +#define MSF_COMPONENT_MINOR_VER 0 + +#define HCF_IO HCF_IO_MEM +#define HCF_DMA 0 +#define HCF_MEM_IO 1 + + +/* Endian is determined by vxWorks project compile option */ +#if (_BYTE_ORDER == _BIG_ENDIAN) +#undef HCF_LITTLE_ENDIAN +#define HCF_BIG_ENDIAN 1 +#endif + + +#define CNV_END(w) ( ((hcf_16)(w) & 0x00FF) << 8 | ((hcf_16)(w) & 0xFF00) >> 8 ) +#if defined HCF_BIG_ENDIAN +//******************************************** B I G E N D I A N ******************************************* +#define CNV_LITTLE_TO_INT(w) CNV_END(w) // endianess conversion needed +#define CNV_BIG_TO_INT(w) (w) // no endianess conversion needed +#else +//****************************************** L I T T L E E N D I A N **************************************** +#define CNV_LITTLE_TO_INT(w) (w) // no endianess conversion needed +#define CNV_BIG_TO_INT(w) CNV_END(w) // endianess conversion needed +#endif // HCF_BIG_ENDIAN + +// conversion macros which can be expressed in other macros +#define CNV_INT_TO_LITTLE(w) CNV_LITTLE_TO_INT(w) +#define CNV_INT_TO_BIG(w) CNV_BIG_TO_INT(w) + + + +#define IN_PORT_WORD( port ) *((volatile hcf_16 *)( port )) +#define OUT_PORT_WORD( port, value ) *((volatile hcf_16 *)( port )) = ((hcf_16)( value )) +//#define IN_PORT_BYTE( port ) *((volatile hcf_8 *)( port )) + +#define IN_PORT_STRING( port, addr, len) { \ + unsigned l = len; \ + hcf_16 *d = (hcf_16 *)(addr); \ + hcf_16 t; \ + while (l--) { \ + t = IN_PORT_WORD(port); \ + *d++ = CNV_LITTLE_TO_INT(t); \ + } \ +} // IN_PORT_STRING + +#define OUT_PORT_STRING( port, addr, len) { \ + unsigned l = (len); \ + hcf_16 *s = (hcf_16 *)(addr); \ + hcf_16 t; \ + while (l--) { \ + t = *s++; \ + t = CNV_LITTLE_TO_INT(t); \ + OUT_PORT_WORD(port, t); \ + } \ +} // OUT_PORT_STRING + +#define IN_PORT_STRING_16(port, dst, n) { \ + unsigned l = (n); \ + hcf_16 *d = (hcf_16 *)(dst); \ + while (l--) { \ + *d++ = IN_PORT_WORD(port); \ + } \ +} // IN_PORT_STRING_16 + +#define OUT_PORT_STRING_16(port, src, n) { \ + hcf_16 t; \ + int l = (n); \ + hcf_16 *s = (hcf_16 *)(src); \ + while (l--) { \ + t = *s++; \ + OUT_PORT_WORD(port, t); \ + } \ +} // OUT_PORT_STRING_16 + +/* #define HCF_YIELD (taskDelay(0) == 0) */ + + + +#ifdef WVLAN_DEBUG +#define DBG 1 +#define _DEBUG 1 +#endif + +/* we'll need to add these prints someday */ +#define OUTPUTDEBUGMSG(dprintf_exp) +#define ASSERTDEBUGMSG(cond, dprintf_exp) + +#define HCF_INTERFACE_CONNECT(ifbp) +#define HCF_INTERFACE_DISCONNECT(ifbp) +#define HCF_ENTER_INTERFACE_FUNCT(ibfb) +#define HCF_LEAVE_INTERFACE_FUNCT(ifbp) + +#define sysInWord(offsetAddr) IN_PORT_WORD(offsetAddr) +#define sysInByte(offsetAddr) IN_PORT_BYTE(offsetAddr) +#define sysOutWord(addr, value) OUT_PORT_WORD(addr, value) + +#endif /*IPT_T8300 */ + +/************************************************************************************************************/ +/*********************************** **************************************/ +/************************************************************************************************************/ +#if ! defined HCF_ALIGN +#define HCF_ALIGN 1 //default to no alignment +#endif // HCF_ALIGN + +#if ! defined HCF_ASSERT +#define HCF_ASSERT 0 +#endif // HCF_ASSERT + +#if ! defined HCF_BIG_ENDIAN +#define HCF_BIG_ENDIAN 0 +#endif // HCF_BIG_ENDIAN + +#if ! defined HCF_DL_ONLY +#define HCF_DL_ONLY 0 +#endif // HCF_DL_ONLY + +#if ! defined HCF_DMA +#define HCF_DMA 0 +#endif // HCF_DMA + +#if ! defined HCF_ENCAP +#define HCF_ENCAP HCF_ENC +#endif // HCF_ENCAP + +#if ! defined HCF_ENTRY +#define HCF_ENTRY( ifbp ) +#endif // HCF_ENTRY + +#if ! defined HCF_EXIT +#define HCF_EXIT( ifbp ) +#endif // HCF_EXIT + +#if ! defined HCF_EXT +#define HCF_EXT 0 +#endif // HCF_EXT + +#if ! defined HCF_INT_ON +#define HCF_INT_ON 1 +#endif // HCF_INT_ON + +#if ! defined HCF_IO +#define HCF_IO 0 //default 16 bits support only, port I/O +#endif // HCF_IO + +#if ! defined HCF_LEGACY +#define HCF_LEGACY 0 +#endif // HCF_LEGACY + +#if ! defined HCF_MAX_LTV +#define HCF_MAX_LTV 1200 // sufficient for all known purposes +#endif // HCF_MAX_LTV + +#if ! defined HCF_PROT_TIME +#define HCF_PROT_TIME 100 // number of 10K microsec protection timer against H/W malfunction +#endif // HCF_PROT_TIME + +#if ! defined HCF_SLEEP +#define HCF_SLEEP 0 +#endif // HCF_SLEEP + +#if ! defined HCF_TALLIES +#define HCF_TALLIES ( HCF_TALLIES_NIC | HCF_TALLIES_HCF ) +#endif // HCF_TALLIES + +#if ! defined HCF_TYPE +#define HCF_TYPE 0 +#endif // HCF_TYPE + +#if HCF_BIG_ENDIAN +#undef HCF_BIG_ENDIAN +#define HCF_BIG_ENDIAN 1 //just for convenience of generating cfg_hcf_opt +#endif // HCF_BIG_ENDIAN + +#if HCF_DL_ONLY +#undef HCF_DL_ONLY +#define HCF_DL_ONLY 1 //just for convenience of generating cfg_hcf_opt +#endif // HCF_DL_ONLY + +#if HCF_DMA +#undef HCF_DMA +#define HCF_DMA 1 //just for convenience of generating cfg_hcf_opt +#endif // HCF_DMA + +#if HCF_INT_ON +#undef HCF_INT_ON +#define HCF_INT_ON 1 //just for convenience of generating cfg_hcf_opt +#endif // HCF_INT_ON + + +#if ! defined IN_PORT_STRING_8_16 +#define IN_PORT_STRING_8_16(port, addr, len) IN_PORT_STRING_16(port, addr, len) +#define OUT_PORT_STRING_8_16(port, addr, len) OUT_PORT_STRING_16(port, addr, len) +#endif // IN_PORT_STRING_8_16 + +/************************************************************************************************/ +/********** *************/ +/************************************************************************************************/ + +#if ! defined FAR +#define FAR // default to flat 32-bits code +#endif // FAR + +typedef hcf_8 FAR *wci_bufp; // segmented 16-bits or flat 32-bits pointer to 8 bits unit +typedef hcf_16 FAR *wci_recordp; // segmented 16-bits or flat 32-bits pointer to 16 bits unit + +/* I/O Address size +* Platforms which use port mapped I/O will (in general) have a 64k I/O space, conveniently expressed in a +* 16-bits quantity +* Platforms which use memory mapped I/O will (in general) have an I/O space much larger than 64k, and need a +* 32-bits quantity to express the I/O base +*/ + +#if HCF_IO & HCF_IO_MEM +typedef hcf_32 hcf_io; +#else +typedef hcf_16 hcf_io; +#endif //HCF_IO + +#if HCF_PROT_TIME > 128 +#define HCF_PROT_TIME_SHFT 3 +#define HCF_PROT_TIME_DIV 8 +#elif HCF_PROT_TIME > 64 +#define HCF_PROT_TIME_SHFT 2 +#define HCF_PROT_TIME_DIV 4 +#elif HCF_PROT_TIME > 32 +#define HCF_PROT_TIME_SHFT 1 +#define HCF_PROT_TIME_DIV 2 +#else //HCF_PROT_TIME >= 19 +#define HCF_PROT_TIME_SHFT 0 +#define HCF_PROT_TIME_DIV 1 +#endif + +#define HCF_PROT_TIME_CNT (HCF_PROT_TIME / HCF_PROT_TIME_DIV) + + +/************************************************************************************************************/ +/******************************************* . . . . . . . . . *********************************************/ +/************************************************************************************************************/ + +/* MSF_COMPONENT_ID is used to define the CFG_IDENTITY_STRCT in HCF.C +* CFG_IDENTITY_STRCT is defined in HCF.C purely based on convenience arguments. +* The HCF can not have the knowledge to determine the ComponentId field of the Identity record (aka as +* Version Record), therefore the MSF part of the Drivers must supply this value via the System Constant +* MSF_COMPONENT_ID. +* There is a set of values predefined in MDD.H (format COMP_ID_.....) +* +* Note that taking MSF_COMPONENT_ID as a default value for DUI_COMPAT_VAR is purely an implementation +* convenience, the numerical values of these two quantities have none functional relationship whatsoever. +*/ + +#if defined MSF_COMPONENT_ID + +#if ! defined DUI_COMPAT_VAR +#define DUI_COMPAT_VAR MSF_COMPONENT_ID +#endif // DUI_COMPAT_VAR + +#if ! defined DUI_COMPAT_BOT //;?this way utilities can lower as well raise the bottom +#define DUI_COMPAT_BOT 8 +#endif // DUI_COMPAT_BOT + +#if ! defined DUI_COMPAT_TOP //;?this way utilities can lower as well raise the top +#define DUI_COMPAT_TOP 8 +#endif // DUI_COMPAT_TOP + +#endif // MSF_COMPONENT_ID + +#if (HCF_TYPE) & HCF_TYPE_HII5 + +#if ! defined HCF_HSI_VAR_5 +#define HCF_HSI_VAR_5 +#endif // HCF_HSI_VAR_5 + +#if ! defined HCF_APF_VAR_4 +#define HCF_APF_VAR_4 +#endif // HCF_APF_VAR_4 + +#if (HCF_TYPE) & HCF_TYPE_WARP +#if ! defined HCF_STA_VAR_4 +#define HCF_STA_VAR_4 +#endif // HCF_STA_VAR_4 +#else +#if ! defined HCF_STA_VAR_2 +#define HCF_STA_VAR_2 +#endif // HCF_STA_VAR_2 +#endif + +#if defined HCF_HSI_VAR_4 +err: HSI variants 4 correspond with HII; +#endif // HCF_HSI_VAR_4 + +#else + +#if ! defined HCF_HSI_VAR_4 +#define HCF_HSI_VAR_4 //Hermes-II all types (for the time being!) +#endif // HCF_HSI_VAR_4 + +#if ! defined HCF_APF_VAR_2 +#define HCF_APF_VAR_2 +#endif // HCF_APF_VAR_2 + +#if ! defined HCF_STA_VAR_2 +#define HCF_STA_VAR_2 +#endif // HCF_STA_VAR_2 + +#endif // HCF_TYPE_HII5 + +#if ! defined HCF_PRI_VAR_3 +#define HCF_PRI_VAR_3 +#endif // HCF_PRI_VAR_3 + +#if defined HCF_HSI_VAR_1 || defined HCF_HSI_VAR_2 || defined HCF_HSI_VAR_3 +err: HSI variants 1, 2 and 3 correspond with H-I only; +#endif // HCF_HSI_VAR_1, HCF_HSI_VAR_2, HCF_HSI_VAR_3 + +#if defined HCF_PRI_VAR_1 || defined HCF_PRI_VAR_2 +err: primary variants 1 and 2 correspond with H-I only; +#endif // HCF_PRI_VAR_1 / HCF_PRI_VAR_2 + + +/************************************************************************************************************/ +/******************************************* . . . . . . . . . *********************************************/ +/************************************************************************************************************/ + + +/* The BASED customization macro is used to resolves the SS!=DS conflict for the Interrupt Service logic in + * DOS Drivers. Due to the cumbersomeness of mixing C and assembler local BASED variables still end up in the + * wrong segment. The workaround is that the HCF uses only global BASED variables or IFB-based variables. + * The "BASED" construction (supposedly) only amounts to something in the small memory model. + * + * Note that the whole BASED rigmarole is needlessly complicated because both the Microsoft Compiler and + * Linker are unnecessary restrictive in what far pointer manipulation they allow + */ + +#if ! defined BASED +#define BASED +#endif // BASED + +#if ! defined EXTERN_C +#ifdef __cplusplus +#define EXTERN_C extern "C" +#else +#define EXTERN_C +#endif // __cplusplus +#endif // EXTERN_C + +#if ! defined NULL +#define NULL ((void *) 0) +#endif // NULL + +#if ! defined TEXT +#define TEXT(x) x +#endif // TEXT + +#if !defined _TCHAR_DEFINED +#define TCHAR char +#endif // _TCHAR_DEFINED + +/************************************************************************************************************/ +/*********************** C O N F L I C T D E T E C T I O N & R E S O L U T I O N ************************/ +/************************************************************************************************************/ +#if defined HCF_LITTLE_ENDIAN +err: HCF_LITTLE_ENDIAN is obsolete; +#endif // HCF_LITTLE_ENDIAN + +#if defined HCF_INT_OFF +err: HCF_INT_OFF is obsolete; +#endif //HCF_INT_OFF + +#if HCF_ALIGN != 1 && HCF_ALIGN != 2 && HCF_ALIGN != 4 && HCF_ALIGN != 8 +err: invalid value for HCF_ALIGN; +#endif // HCF_ALIGN + +#if (HCF_ASSERT) & ~( HCF_ASSERT_PRINTF | HCF_ASSERT_SW_SUP | HCF_ASSERT_MB | HCF_ASSERT_RT_MSF_RTN | \ + HCF_ASSERT_LNK_MSF_RTN ) +err: invalid value for HCF_ASSERT; +#endif // HCF_ASSERT + +#if (HCF_ASSERT) & HCF_ASSERT_MB && ! ( (HCF_EXT) & HCF_EXT_MB ) //detect potential conflict +err: these macros are not used consistently; +#endif // HCF_ASSERT_MB / HCF_EXT_MB + +#if HCF_BIG_ENDIAN != 0 && HCF_BIG_ENDIAN != 1 +err: invalid value for HCF_BIG_ENDIAN; +#endif // HCF_BIG_ENDIAN + +#if HCF_DL_ONLY != 0 && HCF_DL_ONLY != 1 +err: invalid value for HCF_DL_ONLY; +#endif // HCF_DL_ONLY + +#if HCF_DMA != 0 && HCF_DMA != 1 +err: invalid value for HCF_DMA; +#endif // HCF_DMA + +#if (HCF_ENCAP) & ~( HCF_ENC | HCF_ENC_SUP ) +err: invalid value for HCF_ENCAP; +#endif // HCF_ENCAP + +#if (HCF_EXT) & ~( HCF_EXT_INFO_LOG | HCF_EXT_INT_TX_EX | HCF_EXT_TALLIES_FW | HCF_EXT_TALLIES_HCF | \ + HCF_EXT_NIC_ACCESS | HCF_EXT_MB | HCF_EXT_INT_TICK | \ + HCF_EXT_IFB_STRCT | HCF_EXT_DESC_STRCT | HCF_EXT_TX_CONT ) +err: invalid value for HCF_EXT; +#endif // HCF_EXT + +#if HCF_INT_ON != 0 && HCF_INT_ON != 1 +err: invalid value for HCF_INT_ON; +#endif // HCF_INT_ON + +#if (HCF_IO) & ~( HCF_IO_MEM | HCF_IO_32BITS ) +err: invalid value for HCF_IO; +#endif // HCF_IO + +#if HCF_LEGACY != 0 && HCF_LEGACY != 1 +err: invalid value for HCF_LEGACY; +#endif // HCF_LEGACY + +#if HCF_MAX_LTV < 16 || HCF_MAX_LTV > 2304 +err: invalid value for HCF_MAX_LTV; +#endif // HCF_MAX_LTV + +#if HCF_PROT_TIME != 0 && ( HCF_PROT_TIME < 19 || 256 < HCF_PROT_TIME ) +err: below minimum .08 second required by Hermes or possibly above hcf_32 capacity; +#endif // HCF_PROT_TIME + +#if (HCF_SLEEP) & ~( HCF_CDS | HCF_DDS ) +err: invalid value for HCF_SLEEP; +#endif // HCF_SLEEP + +#if (HCF_SLEEP) && ! (HCF_INT_ON) +err: these macros are not used consistently; +#endif // HCF_SLEEP / HCF_INT_ON + +#if (HCF_SLEEP) && ! ( (HCF_EXT) & HCF_EXT_INT_TICK ) +//;? err: these macros are not used consistently; +#endif // HCF_SLEEP / HCF_EXT_INT_TICK + +#if (HCF_TALLIES) & ~( HCF_TALLIES_HCF | HCF_TALLIES_NIC | HCF_TALLIES_RESET ) || \ + (HCF_TALLIES) == HCF_TALLIES_RESET +err: invalid value for HCF_TALLIES; +#endif // HCF_TALLIES + +#if (HCF_TYPE) & ~(HCF_TYPE_WPA | HCF_TYPE_USB | HCF_TYPE_PRELOADED | HCF_TYPE_HII5 | HCF_TYPE_WARP | \ + HCF_TYPE_CCX /* | HCF_TYPE_TX_DELAY */ ) +err: invalid value for HCF_TYPE; +#endif //HCF_TYPE + +#if (HCF_TYPE) & HCF_TYPE_WARP && (HCF_TYPE) & HCF_TYPE_WPA +err: at most 1 of these macros should be defined; +#endif //HCF_TYPE_WARP / HCF_TYPE_WPA + +#endif //HCFCFG_H + diff --git a/drivers/staging/wlags49_h2/hcfdef.h b/drivers/staging/wlags49_h2/hcfdef.h new file mode 100644 index 0000000000000000000000000000000000000000..f7e74bfbadfa647acbd28cd0c25d9b0f2f256159 --- /dev/null +++ b/drivers/staging/wlags49_h2/hcfdef.h @@ -0,0 +1,809 @@ + +// vim:tw=110:ts=4: +#ifndef HCFDEFC_H +#define HCFDEFC_H 1 + +/************************************************************************************************* +* +* FILE : HCFDEF.H +* +* DATE : $Date: 2004/08/05 11:47:10 $ $Revision: 1.8 $ +* Original: 2004/05/28 14:05:35 Revision: 1.59 Tag: hcf7_t20040602_01 +* Original: 2004/05/13 15:31:45 Revision: 1.53 Tag: hcf7_t7_20040513_01 +* Original: 2004/04/15 09:24:42 Revision: 1.44 Tag: hcf7_t7_20040415_01 +* Original: 2004/04/13 14:22:45 Revision: 1.43 Tag: t7_20040413_01 +* Original: 2004/04/01 15:32:55 Revision: 1.40 Tag: t7_20040401_01 +* Original: 2004/03/10 15:39:28 Revision: 1.36 Tag: t20040310_01 +* Original: 2004/03/03 14:10:12 Revision: 1.34 Tag: t20040304_01 +* Original: 2004/03/02 09:27:12 Revision: 1.32 Tag: t20040302_03 +* Original: 2004/02/24 13:00:29 Revision: 1.29 Tag: t20040224_01 +* Original: 2004/02/18 17:13:57 Revision: 1.26 Tag: t20040219_01 +* +* AUTHOR : Nico Valster +* +* SPECIFICATION: ........... +* +* DESC : Definitions and Prototypes for HCF only +* +************************************************************************************************** +* +* +* SOFTWARE LICENSE +* +* This software is provided subject to the following terms and conditions, +* which you should read carefully before using the software. Using this +* software indicates your acceptance of these terms and conditions. If you do +* not agree with these terms and conditions, do not use the software. +* +* COPYRIGHT © 1994 - 1995 by AT&T. All Rights Reserved +* COPYRIGHT © 1996 - 2000 by Lucent Technologies. All Rights Reserved +* COPYRIGHT © 2001 - 2004 by Agere Systems Inc. All Rights Reserved +* All rights reserved. +* +* Redistribution and use in source or binary forms, with or without +* modifications, 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 as comments in the code as +* well as in the documentation and/or other materials provided with the +* distribution. +* +* . 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. +* +* . Neither the name of Agere Systems Inc. nor the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* Disclaimer +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY +* USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN +* RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. +* +* +*************************************************************************************************/ + + +/************************************************************************************************/ +/********************************* P R E F I X E S ********************************************/ +/************************************************************************************************/ +//IFB_ Interface Block +//HCMD_ Hermes Command +//HFS_ Hermes (Transmit/Receive) Frame Structure +//HREG_ Hermes Register + +/*************************************************************************************************/ + +#if 0 // +#define BIT0 0x0001 +#define BIT1 0x0002 +#define BIT2 0x0004 +#define BIT3 0x0008 +#define BIT4 0x0010 +#define BIT5 0x0020 +#define BIT6 0x0040 +#define BIT7 0x0080 +#define BIT8 0x0100 +#define BIT9 0x0200 +#define BIT10 0x0400 +#define BIT11 0x0800 +#define BIT12 0x1000 +#define BIT13 0x2000 +#define BIT14 0x4000 +#define BIT15 0x8000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 +#endif // 0 + +/************************************************************************************************/ +/********************************* GENERAL EQUATES **********************************************/ +/************************************************************************************************/ + + +#define HCF_MAGIC 0x7D37 // "}7" Handle validation + +#define PLUG_DATA_OFFSET 0x00000800 //needed by some test tool on top of H-II NDIS driver + +#define INI_TICK_INI 0x00040000L + +#define IO_IN 0 //hcfio_in_string +#define IO_OUT 1 //hcfio_out_string + +//DO_ASSERT, create an artificial FALSE to force an ASSERT without the nasty compiler warning +#define DO_ASSERT ( assert_ifbp->IFB_Magic != HCF_MAGIC && assert_ifbp->IFB_Magic == HCF_MAGIC ) +#define NT_ASSERT 0x0000 //, NEVER_TESTED +#define NEVER_TESTED MERGE_2( 0xEFFE, 0xFEEF ) +#define SE_ASSERT 0x5EFF /* Side Effect, HCFASSERT invokation which are only called for the + * side effect and which should never trigger */ +#define DHF_FILE_NAME_OFFSET 10000 //to distinguish DHF from HCF asserts by means of line number +#define MMD_FILE_NAME_OFFSET 20000 //to distinguish MMD from HCF asserts by means of line number + +// trace codes used to +// 1: profile execution times via HCF_TRACE and HCF_TRACE_VALUE +// 2: hierarchical flow information via HCFLOGENTRY / HCFLOGEXIT + +//#define HCF_TRACE_CONNECT useless +//#define HCF_TRACE_DISCONNECT useless +#define HCF_TRACE_ACTION 0x0000 // 0x0001 +#define HCF_TRACE_CNTL 0x0001 // 0x0002 +#define HCF_TRACE_DMA_RX_GET 0x0002 // 0x0004 +#define HCF_TRACE_DMA_RX_PUT 0x0003 // 0x0008 +#define HCF_TRACE_DMA_TX_GET 0x0004 // 0x0010 +#define HCF_TRACE_DMA_TX_PUT 0x0005 // 0x0020 +#define HCF_TRACE_GET_INFO 0x0006 // 0x0040 +#define HCF_TRACE_PUT_INFO 0x0007 // 0x0080 +#define HCF_TRACE_RCV_MSG 0x0008 // 0x0100 +#define HCF_TRACE_SEND_MSG 0x0009 // 0x0200 +#define HCF_TRACE_SERVICE_NIC 0x000A // 0x0400 +// #define HCF_TRACE_ 0x000C // 0x1000 +// #define HCF_TRACE_ 0x000D // 0x2000 +// #define HCF_TRACE_ 0x000E // 0x4000 +// #define HCF_TRACE_ 0x000F // 0x8000 +// ============================================ HCF_TRACE_... codes below 0x0010 are asserted on re-entry +#define HCF_TRACE_ACTION_KLUDGE 0x0010 /* once you start introducing kludges there is no end to it + * this is an escape to do not assert on re-entrancy problem caused + * by HCF_ACT_INT_FORCE_ON used to get Microsofts NDIS drivers going + */ +#define HCF_TRACE_STRIO 0x0020 +#define HCF_TRACE_ALLOC 0X0021 +#define HCF_TRACE_DL 0X0023 +#define HCF_TRACE_ISR_INFO 0X0024 +#define HCF_TRACE_CALIBRATE 0x0026 + +#define HCF_TRACE_CMD_CPL 0x0040 +#define HCF_TRACE_CMD_EXE 0x0041 +#define HCF_TRACE_GET_FID 0x0042 +#define HCF_TRACE_GET_FRAG 0x0043 +#define HCF_TRACE_INIT 0x0044 +#define HCF_TRACE_PUT_FRAG 0x0045 +#define HCF_TRACE_SETUP_BAP 0x0046 + +#define HCF_TRACE_EXIT 0x8000 // Keil C warns "long constant truncated to int" + +//#define BAP_0 HREG_DATA_0 //Used by DMA controller to access NIC RAM +#define BAP_1 HREG_DATA_1 //Used by HCF to access NIC RAM + + +//************************* Hermes Receive/Transmit Frame Structures +//HFS_STAT +//see MMD.H for HFS_STAT_ERR +#define HFS_STAT_MSG_TYPE 0xE000 //Hermes reported Message Type +#define HFS_STAT_MIC_KEY_ID 0x1800 //MIC key used (if any) +#define HFS_STAT_1042 0x2000 //RFC1042 Encoded +#define HFS_STAT_TUNNEL 0x4000 //Bridge-Tunnel Encoded +#define HFS_STAT_WMP_MSG 0x6000 //WaveLAN-II Management Protocol Frame +#if (HCF_TYPE) & HCF_TYPE_WPA +#define HFS_STAT_MIC 0x0010 //Frame contains MIC //;? re-instate when F/W ready +#endif + +//************************* Hermes Register Offsets and Command bits +#define HREG_IO_RANGE 0x80 //I/O Range used by Hermes + + +//************************* Command/Status +#define HREG_CMD 0x00 // +#define HCMD_CMD_CODE 0x3F +#define HREG_PARAM_0 0x02 // +#define HREG_PARAM_1 0x04 // +#define HREG_PARAM_2 0x06 // +#define HREG_STAT 0x08 // +#define HREG_STAT_CMD_CODE 0x003F // +#define HREG_STAT_DIAG_ERR 0x0100 +#define HREG_STAT_INQUIRE_ERR 0x0500 +#define HREG_STAT_CMD_RESULT 0x7F00 // +#define HREG_RESP_0 0x0A // +#define HREG_RESP_1 0x0C // +#define HREG_RESP_2 0x0E // + + +//************************* FID Management +#define HREG_INFO_FID 0x10 // +#define HREG_RX_FID 0x20 // +#define HREG_ALLOC_FID 0x22 // +#define HREG_TX_COMPL_FID 0x24 // + + +//************************* BAP +//20031030 HWi Inserted this again because the dongle code uses this (GPIF.C) +//#define HREG_SELECT_0 0x18 // +//#define HREG_OFFSET_0 0x1C // +//#define HREG_DATA_0 0x36 // + +//#define HREG_OFFSET_BUSY 0x8000 // use HCMD_BUSY +#define HREG_OFFSET_ERR 0x4000 // +//rsrvd #define HREG_OFFSET_DATA_OFFSET 0x0FFF // + +#define HREG_SELECT_1 0x1A // +#define HREG_OFFSET_1 0x1E // +#define HREG_DATA_1 0x38 // + + +//************************* Event +#define HREG_EV_STAT 0x30 // +#define HREG_INT_EN 0x32 // +#define HREG_EV_ACK 0x34 // + +#define HREG_EV_TICK 0x8000 //Auxiliary Timer Tick +//#define HREG_EV_RES 0x4000 //H-I only: H/W error (Wait Time-out) +#define HREG_EV_INFO_DROP 0x2000 //WMAC did not have sufficient RAM to build Unsollicited Frame +#if (HCF_TYPE) & HCF_TYPE_HII5 +#define HREG_EV_ACK_REG_READY 0x0000 +#else +#define HREG_EV_ACK_REG_READY 0x1000 //Workaround Kludge bit for H-II (not H-II.5) +#endif // HCF_TYPE_HII5 +#if (HCF_SLEEP) & ( HCF_CDS | HCF_DDS ) +#define HREG_EV_SLEEP_REQ 0x0800 +#else +#define HREG_EV_SLEEP_REQ 0x0000 +#endif // HCF_CDS / HCF_DDS +#if HCF_DMA +//#define HREG_EV_LPESC 0x0400 // firmware sets this bit and clears it, not for host usage. +#define HREG_EV_RDMAD 0x0200 // rx frame in host memory +#define HREG_EV_TDMAD 0x0100 // tx frame in host memory processed +//#define HREG_EV_RXDMA 0x0040 // firmware kicks off DMA engine (bit is not for host usage) +//#define HREG_EV_TXDMA 0x0020 // firmware kicks off DMA engine (bit is not for host usage) +#define HREG_EV_FW_DMA 0x0460 // firmware / DMA engine I/F (bits are not for host usage) +#else +#define HREG_EV_FW_DMA 0x0000 +#endif // HCF_DMA +#define HREG_EV_INFO 0x0080 // Asynchronous Information Frame +#define HREG_EV_CMD 0x0010 // Command completed, Status and Response available +#define HREG_EV_ALLOC 0x0008 // Asynchronous part of Allocation/Reclaim completed +#define HREG_EV_TX_EXC 0x0004 // Asynchronous Transmission unsuccessful completed +#define HREG_EV_TX 0x0002 // Asynchronous Transmission successful completed +#define HREG_EV_RX 0x0001 // Asynchronous Receive Frame + +#define HREG_EV_TX_EXT ( (HCF_EXT) & (HCF_EXT_INT_TX_EX | HCF_EXT_INT_TICK ) ) + /* HREG_EV_TX_EXT := 0x0000 or HREG_EV_TX_EXC and/or HREG_EV_TICK + * could be extended with HREG_EV_TX */ +#if HCF_EXT_INT_TX_EX != HREG_EV_TX_EXC +err: these values should match; +#endif // HCF_EXT_INT_TX_EX / HREG_EV_TX_EXC + +#if HCF_EXT_INT_TICK != HREG_EV_TICK +err: these values should match; +#endif // HCF_EXT_INT_TICK / HREG_EV_TICK + +//************************* Host Software +#define HREG_SW_0 0x28 // +#define HREG_SW_1 0x2A // +#define HREG_SW_2 0x2C // +//rsrvd #define HREG_SW_3 0x2E // +//************************* Control and Auxiliary Port + +#define HREG_IO 0x12 +#define HREG_IO_SRESET 0x0001 +#define HREG_IO_WAKEUP_ASYNC 0x0002 +#define HREG_IO_WOKEN_UP 0x0004 +#define HREG_CNTL 0x14 // +//#define HREG_CNTL_WAKEUP_SYNC 0x0001 +#define HREG_CNTL_AUX_ENA_STAT 0xC000 +#define HREG_CNTL_AUX_DIS_STAT 0x0000 +#define HREG_CNTL_AUX_ENA_CNTL 0x8000 +#define HREG_CNTL_AUX_DIS_CNTL 0x4000 +#define HREG_CNTL_AUX_DSD 0x2000 +#define HREG_CNTL_AUX_ENA (HREG_CNTL_AUX_ENA_CNTL | HREG_CNTL_AUX_DIS_CNTL ) +#define HREG_SPARE 0x16 // +#define HREG_AUX_PAGE 0x3A // +#define HREG_AUX_OFFSET 0x3C // +#define HREG_AUX_DATA 0x3E // + +#if HCF_DMA +//************************* DMA (bus mastering) + // Be carefull to use these registers only at a genuine 32 bits NIC + // On 16 bits NICs, these addresses are mapped into the range 0x00 through 0x3F with all consequences + // thereof, e.g. HREG_DMA_CTRL register maps to HREG_CMD. +#define HREG_DMA_CTRL 0x0040 +#define HREG_TXDMA_PTR32 0x0044 +#define HREG_TXDMA_PRIO_PTR32 0x0048 +#define HREG_TXDMA_HIPRIO_PTR32 0x004C +#define HREG_RXDMA_PTR32 0x0050 +#define HREG_CARDDETECT_1 0x007C // contains 7D37 +#define HREG_CARDDETECT_2 0x007E // contains 7DE7 +#define HREG_FREETIMER 0x0058 +#define HREG_DMA_RX_CNT 0x0026 + +/****************************************************************************** +* Defines for the bits in the DmaControl register (@40h) +******************************************************************************/ +#define HREG_DMA_CTRL_RXHWEN 0x80000000 // high word enable bit +#define HREG_DMA_CTRL_RXRESET 0x40000000 // tx dma init bit +#define HREG_DMA_CTRL_RXBAP1 BIT29 +#define HREG_DMA_CTRL_RX_STALLED BIT28 +#define HREG_DMA_CTRL_RXAUTOACK_DMADONE BIT27 // no host involvement req. for TDMADONE event +#define HREG_DMA_CTRL_RXAUTOACK_INFO BIT26 // no host involvement req. for alloc event +#define HREG_DMA_CTRL_RXAUTOACK_DMAEN 0x02000000 // no host involvement req. for TxDMAen event +#define HREG_DMA_CTRL_RXAUTOACK_RX 0x01000000 // no host involvement req. for tx event +#define HREG_DMA_CTRL_RX_BUSY BIT23 // read only bit +//#define HREG_DMA_CTRL_RX_RBUFCONT_PLAIN 0 // bits 21..20 +//#define HREG_DMA_CTRL_RX_MODE_PLAIN_DMA 0 // mode 0 +#define HREG_DMA_CTRL_RX_MODE_SINGLE_PACKET 0x00010000 // mode 1 +#define HREG_DMA_CTRL_RX_MODE_MULTI_PACKET 0x00020000 // mode 2 +//#define HREG_DMA_CTRL_RX_MODE_DISABLE (0x00020000|0x00010000) // disable tx dma engine +#define HREG_DMA_CTRL_TXHWEN 0x8000 // low word enable bit +#define HREG_DMA_CTRL_TXRESET 0x4000 // rx dma init bit +#define HREG_DMA_CTRL_TXBAP1 BIT13 +#define HREG_DMA_CTRL_TXAUTOACK_DMADONE BIT11 // no host involvement req. for RxDMADONE event +#define HREG_DMA_CTRL_TXAUTOACK_DMAEN 0x00000400 // no host involvement req. for RxDMAen event +#define HREG_DMA_CTRL_TXAUTOACK_DMAALLOC 0x00000200 // no host involvement req. for info event +#define HREG_DMA_CTRL_TXAUTOACK_TX 0x00000100 // no host involvement req. for rx event +#define HREG_DMA_CTRL_TX_BUSY BIT7 // read only bit +//#define HREG_DMA_CTRL_TX_TBUFCONT_PLAIN 0 // bits 6..5 +//#define HREG_DMA_CTRL_TX_MODE_PLAIN_DMA 0 // mode 0 +#define HREG_DMA_CTRL_TX_MODE_SINGLE_PACKET BIT0 // mode 1 +#define HREG_DMA_CTRL_TX_MODE_MULTI_PACKET 0x00000002 // mode 2 +//#define HREG_DMA_CTRL_TX_MODE_DISABLE (0x00000001|0x00000002) // disable tx dma engine + +//configuration DWORD to configure DMA for mode2 operation, using BAP0 as the DMA BAP. +#define DMA_CTRLSTAT_GO (HREG_DMA_CTRL_RXHWEN | HREG_DMA_CTRL_RX_MODE_MULTI_PACKET | \ + HREG_DMA_CTRL_RXAUTOACK_DMAEN | HREG_DMA_CTRL_RXAUTOACK_RX | \ + HREG_DMA_CTRL_TXHWEN | /*;?HREG_DMA_CTRL_TX_TBUFCONT_PLAIN |*/ \ + HREG_DMA_CTRL_TX_MODE_MULTI_PACKET | HREG_DMA_CTRL_TXAUTOACK_DMAEN |\ + HREG_DMA_CTRL_TXAUTOACK_DMAALLOC) + +//configuration DWORD to reset both the Tx and Rx DMA engines +#define DMA_CTRLSTAT_RESET (HREG_DMA_CTRL_RXHWEN | HREG_DMA_CTRL_RXRESET | HREG_DMA_CTRL_TXHWEN | HREG_DMA_CTRL_TXRESET) + +//#define DESC_DMA_OWNED 0x80000000 // BIT31 +#define DESC_DMA_OWNED 0x8000 // BIT31 +#define DESC_SOP 0x8000 // BIT15 +#define DESC_EOP 0x4000 // BIT14 + +#define DMA_RX 0 +#define DMA_TX 1 + +// #define IFB_RxFirstDesc IFB_FirstDesc[DMA_RX] +// #define IFB_TxFirstDesc IFB_FirstDesc[DMA_TX] +// #define IFB_RxLastDesc IFB_LastDesc[DMA_RX] +// #define IFB_TxLastDesc IFB_LastDesc[DMA_TX] + +#endif // HCF_DMA +// +/************************************************************************************************/ +/********************************** EQUATES ***************************************************/ +/************************************************************************************************/ + + +// Hermes Command Codes and Qualifier bits +#define HCMD_BUSY 0x8000 // Busy bit, applicable for all commands +#define HCMD_INI 0x0000 // +#define HCMD_ENABLE HCF_CNTL_ENABLE // 0x0001 +#define HCMD_DISABLE HCF_CNTL_DISABLE // 0x0002 +#define HCMD_CONNECT HCF_CNTL_CONNECT // 0x0003 +#define HCMD_EXECUTE 0x0004 // +#define HCMD_DISCONNECT HCF_CNTL_DISCONNECT // 0x0005 +#define HCMD_SLEEP 0x0006 // +#define HCMD_CONTINUE HCF_CNTL_CONTINUE // 0x0007 +#define HCMD_RETRY 0x0100 // Retry bit +#define HCMD_ALLOC 0x000A // +#define HCMD_TX 0x000B // +#define HCMD_RECL 0x0100 // Reclaim bit, applicable for Tx and Inquire +#define HCMD_INQUIRE 0x0011 // +#define HCMD_ACCESS 0x0021 // +#define HCMD_ACCESS_WRITE 0x0100 // Write bit +#define HCMD_PROGRAM 0x0022 // +#define HCMD_READ_MIF 0x0030 +#define HCMD_WRITE_MIF 0x0031 +#define HCMD_THESEUS 0x0038 +#define HCMD_STARTPREAMBLE 0x0E00 // Start continuous preamble Tx +#define HCMD_STOP 0x0F00 // Stop Theseus test mode + + +//Configuration Management +// + +#define CFG_DRV_ACT_RANGES_PRI_3_BOTTOM 1 // Default Bottom Compatibility for Primary Firmware - driver I/F +#define CFG_DRV_ACT_RANGES_PRI_3_TOP 1 // Default Top Compatibility for Primary Firmware - driver I/F + +#define CFG_DRV_ACT_RANGES_HSI_4_BOTTOM 1 // Default Bottom Compatibility for H/W - driver I/F +#define CFG_DRV_ACT_RANGES_HSI_4_TOP 1 // Default Top Compatibility for H/W - driver I/F + +#define CFG_DRV_ACT_RANGES_HSI_5_BOTTOM 1 // Default Bottom Compatibility for H/W - driver I/F +#define CFG_DRV_ACT_RANGES_HSI_5_TOP 1 // Default Top Compatibility for H/W - driver I/F + +#if (HCF_TYPE) & HCF_TYPE_WPA +#define CFG_DRV_ACT_RANGES_APF_1_BOTTOM 16 // Default Bottom Compatibility for AP Firmware - driver I/F +#define CFG_DRV_ACT_RANGES_APF_1_TOP 16 // Default Top Compatibility for AP Firmware - driver I/F +#else //;? is this REALLY O.K. +#define CFG_DRV_ACT_RANGES_APF_1_BOTTOM 1 // Default Bottom Compatibility for AP Firmware - driver I/F +#define CFG_DRV_ACT_RANGES_APF_1_TOP 1 // Default Top Compatibility for AP Firmware - driver I/F +#endif // HCF_TYPE_WPA + +#define CFG_DRV_ACT_RANGES_APF_2_BOTTOM 2 // Default Bottom Compatibility for AP Firmware - driver I/F +#define CFG_DRV_ACT_RANGES_APF_2_TOP 2 // Default Top Compatibility for AP Firmware - driver I/F + +#define CFG_DRV_ACT_RANGES_APF_3_BOTTOM 1 // Default Bottom Compatibility for AP Firmware - driver I/F +#define CFG_DRV_ACT_RANGES_APF_3_TOP 1 // Default Top Compatibility for AP Firmware - driver I/F + +#define CFG_DRV_ACT_RANGES_APF_4_BOTTOM 1 // Default Bottom Compatibility for AP Firmware - driver I/F +#define CFG_DRV_ACT_RANGES_APF_4_TOP 1 // Default Top Compatibility for AP Firmware - driver I/F + +#if (HCF_TYPE) & HCF_TYPE_HII5 +#define CFG_DRV_ACT_RANGES_STA_2_BOTTOM 6 // Default Bottom Compatibility for Station Firmware - driver I/F +#define CFG_DRV_ACT_RANGES_STA_2_TOP 6 // Default Top Compatibility for Station Firmware - driver I/F +#else // (HCF_TYPE) & HCF_TYPE_HII5 +#define CFG_DRV_ACT_RANGES_STA_2_BOTTOM 1 // Default Bottom Compatibility for Station Firmware - driver I/F +#define CFG_DRV_ACT_RANGES_STA_2_TOP 2 // Default Top Compatibility for Station Firmware - driver I/F +#endif // (HCF_TYPE) & HCF_TYPE_HII5 + +#define CFG_DRV_ACT_RANGES_STA_3_BOTTOM 1 // Default Bottom Compatibility for Station Firmware - driver I/F +#define CFG_DRV_ACT_RANGES_STA_3_TOP 1 // Default Top Compatibility for Station Firmware - driver I/F + +#define CFG_DRV_ACT_RANGES_STA_4_BOTTOM 1 // Default Bottom Compatibility for Station Firmware - driver I/F +#define CFG_DRV_ACT_RANGES_STA_4_TOP 1 // Default Top Compatibility for Station Firmware - driver I/F + +//--------------------------------------------------------------------------------------------------------------------- +#if defined HCF_CFG_PRI_1_TOP || defined HCF_CFG_PRI_1_BOTTOM +err: PRI_1 not supported for H-I; // Compatibility for Primary Firmware - driver I/F +#endif // HCF_CFG_PRI_1_TOP / HCF_CFG_PRI_1_BOTTOM + +#if defined HCF_CFG_PRI_2_TOP || defined HCF_CFG_PRI_2_BOTTOM +err: PRI_2 not supported for H-I; // Compatibility for Primary Firmware - driver I/F +#endif // HCF_CFG_PRI_2_TOP / HCF_CFG_PRI_2_BOTTOM + +#ifdef HCF_CFG_PRI_3_TOP // Top Compatibility for Primary Firmware - driver I/F +#if HCF_CFG_PRI_3_TOP == 0 || \ + CFG_DRV_ACT_RANGES_PRI_3_BOTTOM <= HCF_CFG_PRI_3_TOP && HCF_CFG_PRI_3_TOP <= CFG_DRV_ACT_RANGES_PRI_3_TOP +#undef CFG_DRV_ACT_RANGES_PRI_3_TOP +#define CFG_DRV_ACT_RANGES_PRI_3_TOP HCF_CFG_PRI_3_TOP +#else +err: ; +#endif +#endif // HCF_CFG_PRI_3_TOP + +#ifdef HCF_CFG_PRI_3_BOTTOM // Bottom Compatibility for Primary Firmware - driver I/F +#if CFG_DRV_ACT_RANGES_PRI_3_BOTTOM <= HCF_CFG_PRI_3_BOTTOM && HCF_CFG_PRI_3_BOTTOM <= CFG_DRV_ACT_RANGES_PRI_3_TOP +#undef CFG_DRV_ACT_RANGES_PRI_3_BOTTOM +#define CFG_DRV_ACT_RANGES_PRI_3_BOTTOM HCF_CFG_PRI_3_BOTTOM +#else +err: ; +#endif +#endif // HCF_CFG_PRI_3_BOTTOM + + +//--------------------------------------------------------------------------------------------------------------------- +#if defined HCF_CFG_HSI_0_TOP || defined HCF_CFG_HSI_0_BOTTOM +err: HSI_0 not supported for H-I; // Compatibility for HSI I/F +#endif // HCF_CFG_HSI_0_TOP / HCF_CFG_HSI_0_BOTTOM + +#if defined HCF_CFG_HSI_1_TOP || defined HCF_CFG_HSI_1_BOTTOM +err: HSI_1 not supported for H-I; // Compatibility for HSI I/F +#endif // HCF_CFG_HSI_1_TOP / HCF_CFG_HSI_1_BOTTOM + +#if defined HCF_CFG_HSI_2_TOP || defined HCF_CFG_HSI_2_BOTTOM +err: HSI_2 not supported for H-I; // Compatibility for HSI I/F +#endif // HCF_CFG_HSI_2_TOP / HCF_CFG_HSI_2_BOTTOM + +#if defined HCF_CFG_HSI_3_TOP || defined HCF_CFG_HSI_3_BOTTOM +err: HSI_3 not supported for H-I; // Compatibility for HSI I/F +#endif // HCF_CFG_HSI_3_TOP / HCF_CFG_HSI_3_BOTTOM + +#ifdef HCF_CFG_HSI_4_TOP // Top Compatibility for HSI I/F +#if HCF_CFG_HSI_4_TOP == 0 || \ + CFG_DRV_ACT_RANGES_HSI_4_BOTTOM <= CF_CFG_HSI_4_TOP && HCF_CFG_HSI_4_TOP <= CFG_DRV_ACT_RANGES_HSI_4_TOP +#undef CFG_DRV_ACT_RANGES_HSI_4_TOP +#define CFG_DRV_ACT_RANGES_HSI_4_TOP HCF_CFG_HSI_4_TOP +#else +err: ; +#endif +#endif // HCF_CFG_HSI_4_TOP + +#ifdef HCF_CFG_HSI_4_BOTTOM // Bottom Compatibility for HSI I/F +#if CFG_DRV_ACT_RANGES_HSI_4_BOTTOM <= HCF_CFG_HSI_4_BOTTOM && HCF_CFG_HSI_4_BOTTOM <= CFG_DRV_ACT_RANGES_HSI_4_TOP +#undef CFG_DRV_ACT_RANGES_HSI_4_BOTTOM +#define CFG_DRV_ACT_RANGES_HSI_4_BOTTOM HCF_CFG_HSI_4_BOTTOM +#else +err: ; +#endif +#endif // HCF_CFG_HSI_4_BOTTOM + +#ifdef HCF_CFG_HSI_5_TOP // Top Compatibility for HSI I/F +#if HCF_CFG_HSI_5_TOP == 0 || \ + CFG_DRV_ACT_RANGES_HSI_5_BOTTOM <= CF_CFG_HSI_5_TOP && HCF_CFG_HSI_5_TOP <= CFG_DRV_ACT_RANGES_HSI_5_TOP +#undef CFG_DRV_ACT_RANGES_HSI_5_TOP +#define CFG_DRV_ACT_RANGES_HSI_5_TOP HCF_CFG_HSI_5_TOP +#else +err: ; +#endif +#endif // HCF_CFG_HSI_5_TOP + +#ifdef HCF_CFG_HSI_5_BOTTOM // Bottom Compatibility for HSI I/F +#if CFG_DRV_ACT_RANGES_HSI_5_BOTTOM <= HCF_CFG_HSI_5_BOTTOM && HCF_CFG_HSI_5_BOTTOM <= CFG_DRV_ACT_RANGES_HSI_5_TOP +#undef CFG_DRV_ACT_RANGES_HSI_5_BOTTOM +#define CFG_DRV_ACT_RANGES_HSI_5_BOTTOM HCF_CFG_HSI_5_BOTTOM +#else +err: ; +#endif +#endif // HCF_CFG_HSI_5_BOTTOM +//--------------------------------------------------------------------------------------------------------------------- +#if defined HCF_CFG_APF_1_TOP || defined HCF_CFG_APF_1_BOTTOM +err: APF_1 not supported for H-I; // Compatibility for AP Firmware - driver I/F +#endif // HCF_CFG_APF_1_TOP / HCF_CFG_APF_1_BOTTOM + +#ifdef HCF_CFG_APF_2_TOP // Top Compatibility for AP Firmware - driver I/F +#if HCF_CFG_APF_2_TOP == 0 || \ + CFG_DRV_ACT_RANGES_APF_2_BOTTOM <= HCF_CFG_APF_2_TOP && HCF_CFG_APF_2_TOP <= CFG_DRV_ACT_RANGES_APF_2_TOP +#undef CFG_DRV_ACT_RANGES_APF_2_TOP +#define CFG_DRV_ACT_RANGES_APF_2_TOP HCF_CFG_APF_2_TOP +#else +err: ; +#endif +#endif // HCF_CFG_APF_TOP + +#ifdef HCF_CFG_APF_2_BOTTOM // Bottom Compatibility for AP Firmware - driver I/F +#if CFG_DRV_ACT_RANGES_APF_2_BOTTOM <= HCF_CFG_APF_2_BOTTOM && HCF_CFG_APF_2_BOTTOM <= CFG_DRV_ACT_RANGES_APF_2_TOP +#undef CFG_DRV_ACT_RANGES_APF_2_BOTTOM +#define CFG_DRV_ACT_RANGES_APF_2_BOTTOM HCF_CFG_APF_2_BOTTOM +#else +err: ; +#endif +#endif // HCF_CFG_APF_BOTTOM + +//--------------------------------------------------------------------------------------------------------------------- +#if defined HCF_CFG_STA_1_TOP || defined HCF_CFG_STA_1_BOTTOM +err: STA_1 not supported for H-I; // Compatibility for Station Firmware - driver I/F +#endif // HCF_CFG_STA_1_TOP / HCF_CFG_STA_1_BOTTOM + +#ifdef HCF_CFG_STA_2_TOP // Top Compatibility for Station Firmware - driver I/F +#if HCF_CFG_STA_2_TOP == 0 || \ + CFG_DRV_ACT_RANGES_STA_2_BOTTOM <= HCF_CFG_STA_2_TOP && HCF_CFG_STA_2_TOP <= CFG_DRV_ACT_RANGES_STA_2_TOP +#undef CFG_DRV_ACT_RANGES_STA_2_TOP +#define CFG_DRV_ACT_RANGES_STA_2_TOP HCF_CFG_STA_2_TOP +#else +err: ; +#endif +#endif // HCF_CFG_STA_TOP + +#ifdef HCF_CFG_STA_2_BOTTOM // Bottom Compatibility for Station Firmware - driver I/F +#if CFG_DRV_ACT_RANGES_STA_2_BOTTOM <= HCF_CFG_STA_2_BOTTOM && HCF_CFG_STA_2_BOTTOM <= CFG_DRV_ACT_RANGES_STA_2_TOP +#undef CFG_DRV_ACT_RANGES_STA_2_BOTTOM +#define CFG_DRV_ACT_RANGES_STA_2_BOTTOM HCF_CFG_STA_2_BOTTOM +#else +err: ; +#endif +#endif // HCF_CFG_STA_BOTTOM + + +/************************************************************************************************/ +/************************************** MACROS ************************************************/ +/************************************************************************************************/ + +/* min and max macros */ +#if ! defined max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif +#if ! defined min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifdef HCF_SLEEP +#if defined MSF_WAIT +err: MSF should no longer supply this macro; +#else +#define MSF_WAIT(x) \ + { PROT_CNT_INI \ + HCF_WAIT_WHILE( ( IPW( HREG_IO ) & HREG_IO_WOKEN_UP ) == 0 ); \ + HCFASSERT( prot_cnt, IPW( HREG_IO ) ) \ + } +#endif // MSF_WAIT +#else +#define MSF_WAIT(x) /*NOP*/ +#endif // HCF_SLEEP + +#define LOF(x) (sizeof(x)/sizeof(hcf_16)-1) + +#define MUL_BY_2( x ) ( (x) << 1 ) //used to multiply by 2 +#define DIV_BY_2( x ) ( (x) >> 1 ) //used to divide by 2 + +//resolve problems on for some 16 bits compilers to create 32 bit values +#define MERGE_2( hw, lw ) ( ( ((hcf_32)(hw)) << 16 ) | ((hcf_16)(lw)) ) + +#if ! defined HCF_STATIC +#define HCF_STATIC static +#endif // HCF_STATIC + +#if ( (HCF_TYPE) & HCF_TYPE_HII5 ) == 0 +#define DAWA_ACK( mask) { \ + OPW( HREG_EV_ACK, mask | HREG_EV_ACK_REG_READY ); \ + OPW( HREG_EV_ACK, (mask & ~HREG_EV_ALLOC) | HREG_EV_ACK_REG_READY ); } +#define DAWA_ZERO_FID(reg) OPW( reg, 0 ); +#else +#define DAWA_ACK( mask) OPW( HREG_EV_ACK, mask ); +#define DAWA_ZERO_FID(reg) +#endif // HCF_TYPE_HII5 + +#if (HCF_TYPE) & HCF_TYPE_WPA +#define CALC_RX_MIC( p, len ) calc_mic_rx_frag( ifbp, p, len ) +#define CALC_TX_MIC( p, len ) calc_mic_tx_frag( ifbp, p, len ) +#define IF_SSN(x) x +#define IF_NOT_SSN(x) +#else +#define CALC_RX_MIC( p, len ) +#define CALC_TX_MIC( p, len ) +#define MIC_RX_RTN( mic, dw ) +#define MIC_TX_RTN( mic, dw ) +#define IF_SSN(x) +#define IF_NOT_SSN(x) x +#endif // HCF_TYPE_WPA + +#if HCF_TALLIES & HCF_TALLIES_HCF //HCF tally support +#define IF_TALLY(x) x +#else +#define IF_TALLY(x) +#endif // HCF_TALLIES_HCF + + +#if HCF_DMA +#define IF_DMA(x) x +#define IF_NOT_DMA(x) +#define IF_USE_DMA(x) if ( ifbp->IFB_CntlOpt & USE_DMA ) x +#define IF_NOT_USE_DMA(x) if ( !(ifbp->IFB_CntlOpt & USE_DMA) ) x +#else +#define IF_DMA(x) +#define IF_NOT_DMA(x) x +#define IF_USE_DMA(x) +#define IF_NOT_USE_DMA(x) x +#endif // HCF_DMA + + +#define IPW(x) ((hcf_16)IN_PORT_WORD( ifbp->IFB_IOBase + (x) ) ) +#define OPW(x, y) OUT_PORT_WORD( ifbp->IFB_IOBase + (x), y ) + /* make sure the implementation of HCF_WAIT_WHILE is such that there may be multiple HCF_WAIT_WHILE calls + * in a row and that when one fails all subsequent fail immediately without reinitialization of prot_cnt + */ +#if HCF_PROT_TIME == 0 +#define PROT_CNT_INI +#define IF_PROT_TIME(x) +#if defined HCF_YIELD +#define HCF_WAIT_WHILE( x ) while ( (x) && (HCF_YIELD) ) /*NOP*/; +#else +#define HCF_WAIT_WHILE( x ) while ( x ) /*NOP*/; +#endif // HCF_YIELD +#else +#define PROT_CNT_INI hcf_32 prot_cnt = ifbp->IFB_TickIni; +#define IF_PROT_TIME(x) x +#if defined HCF_YIELD +#define HCF_WAIT_WHILE( x ) while ( prot_cnt && (x) && (HCF_YIELD) ) prot_cnt--; +#else +#include +#define HCF_WAIT_WHILE( x ) while ( prot_cnt && (x) ) { udelay(2); prot_cnt--; } +#endif // HCF_YIELD +#endif // HCF_PROT_TIME + +#if defined HCF_EX_INT +//#if HCF_EX_INT & ~( HCF_EX_INT_TX_EX | HCF_EX_INT_TX_OK | HCF_EX_INT_TICK ) +;? out dated checking +err: you used an invalid bitmask; +// #endif // HCF_EX_INT validation +// #else +// #define HCF_EX_INT 0x000 +#endif // HCF_EX_INT + +#if 0 //get compiler going +#if HCF_EX_INT_TICK != HREG_EV_TICK +;? out dated checking +err: someone redefined these macros while the implemenation assumes they are equal; +#endif +#if HCF_EX_INT_TX_OK != HFS_TX_CNTL_TX_OK || HFS_TX_CNTL_TX_OK != HREG_EV_TX_OK +;? out dated checking +err: someone redefined these macros while the implemenation assumes they are equal; +#endif +#if HCF_EX_INT_TX_EX != HFS_TX_CNTL_TX_EX || HFS_TX_CNTL_TX_EX != HREG_EV_TX_EX +;? out dated checking +err: someone redefined these macros while the implemenation assumes they are equal; +#endif +#endif // 0 get compiler going + + +/* The assert in HCFLOGENTRY checks against re-entrancy. Re-entrancy could be caused by MSF logic at + * task-level calling hcf_functions without shielding with HCF_ACT_ON/_OFF. When an interrupt occurs, + * the ISR could (either directly or indirectly) cause re-entering of the interrupted HCF-routine. + * + * The "(ifbp->IFB_AssertWhere = where)" test in HCFLOGENTRY services ALSO as a statement to get around: + * #pragma warning: conditional expression is constant + * on the if-statement + */ +#if HCF_ASSERT +#define HCFASSERT(x,q) {if (!(x)) {mdd_assert( ifbp, __LINE__ , q );}} +#define MMDASSERT(x,q) {if (!(x)) {mdd_assert( assert_ifbp, __LINE__ + FILE_NAME_OFFSET, q );}} + +#define HCFLOGENTRY( where, what ) \ +{if ( (ifbp->IFB_AssertWhere = where) <= 15 ) { \ + HCF_ENTRY( ifbp ); \ + HCFASSERT( (ifbp->IFB_AssertTrace & 1<<((where)&0xF)) == 0, ifbp->IFB_AssertTrace ); \ + ifbp->IFB_AssertTrace |= 1<<((where)&0xF); \ + } \ +HCFTRACE(ifbp, where ) \ +HCFTRACEVALUE(ifbp, what ) \ +} + +#define HCFLOGEXIT( where ) \ +{if ( (ifbp->IFB_AssertWhere = where) <= 15 ) { \ + HCF_EXIT( ifbp ); \ + ifbp->IFB_AssertTrace &= ~(1<<((where)&0xF)); \ + } \ +HCFTRACE(ifbp, (where)|HCF_TRACE_EXIT ) \ +} + +#else // HCF_ASSERT +#define HCFASSERT( x, q ) +#define MMDASSERT( x, q ) +#define HCFLOGENTRY( where, what ) {HCF_ENTRY( ifbp );} +#define HCFLOGEXIT( where ) {HCF_EXIT( ifbp );} +#endif // HCF_ASSERT + +#if HCF_INT_ON +/* ;? HCFASSERT_INT + * #if (HCF_SLEEP) & HCF_DDS + * #define HCFASSERT_INT HCFASSERT( ifbp->IFB_IntOffCnt != 0xFFFF && ifbp->IFB_IntOffCnt != 0xFFFE, \ + * ifbp->IFB_IntOffCnt ) + * #else + */ +#define HCFASSERT_INT HCFASSERT( ifbp->IFB_IntOffCnt != 0xFFFF, ifbp->IFB_IntOffCnt ) +// #endif // HCF_DDS +#else +#define HCFASSERT_INT +#endif // HCF_INT_ON + + +#if defined HCF_TRACE +#define HCFTRACE(ifbp, where ) {OPW( HREG_SW_1, where );} +//#define HCFTRACE(ifbp, where ) {HCFASSERT( DO_ASSERT, where );} +#define HCFTRACEVALUE(ifbp, what ) {OPW( HREG_SW_2, what );} +//#define HCFTRACEVALUE(ifbp, what ) {HCFASSERT( DO_ASSERT, what );} +#else +#define HCFTRACE(ifbp, where ) +#define HCFTRACEVALUE(ifbp, what ) +#endif // HCF_TRACE + + +#if HCF_BIG_ENDIAN +#define BE_PAR(x) ,x +#else +#define BE_PAR(x) +#endif // HCF_BIG_ENDIAN + +/************************************************************************************************/ +/************************************** END OF MACROS *****************************************/ +/************************************************************************************************/ + +/************************************************************************************************/ +/*************************************** PROTOTYPES *******************************************/ +/************************************************************************************************/ + +#if HCF_ASSERT +extern IFBP BASED assert_ifbp; //to make asserts easily work under MMD and DHF +EXTERN_C void mdd_assert (IFBP ifbp, unsigned int line_number, hcf_32 q ); +#endif //HCF_ASSERT + +#if ! ( (HCF_IO) & HCF_IO_32BITS ) // defined 16 bits only +#undef OUT_PORT_STRING_32 +#undef IN_PORT_STRING_32 +#endif // HCF_IO +#endif //HCFDEFC_H + diff --git a/drivers/staging/wlags49_h2/man/wlags49.4 b/drivers/staging/wlags49_h2/man/wlags49.4 new file mode 100644 index 0000000000000000000000000000000000000000..a345885307405ce6f5f9db82a6d8eef4c5eb7693 --- /dev/null +++ b/drivers/staging/wlags49_h2/man/wlags49.4 @@ -0,0 +1,734 @@ +.\" vim:tw=78: +.\" Copyright (c) 1999-2003 Agere Systems Inc. -- http://www.agere.com +.\" wlags49.4 7.20-abg 04/28/2004 13:30:00 +.\" +.TH WLAGS49 4 "04/28/2004 13:30:00" "pcmcia-cs" +.SH NAME +wlags49 \- Agere Systems Wireless PC Card / PCI device drivers + +wlags49_h2_cs.o \- Hermes-II Card Services (PCMCIA/CF) driver +.br +wlags49_h2.o \- Hermes-II MiniPCI driver +.br +wlags49_h25.o \- Hermes-II.5 PCI/CardBus driver +.br +wlags49_h25_cs.o\- Hermes-II.5 Card Services (PCMCIA/CF) driver + +.SH SYNOPSIS +.nh +.fi +.B insmod wlags49_[h1,h2]_[cs].o +.br +.RB [ Authentication=n ] +.RB [ AuthKeyMngmtSuite=???? ] +.RB [ BRSC2GHz=b ]\p +.RB [ BRSC5GHz=b ] +.RB [ Coexistence=n ] +.RB [ Configured=???? ]\p +.RB [ ConnectionControl=???? ] +.RB [ CreateIBSS=s ] +.RB [ DebugFlag=n ]\p +.RB [ DesiredSSID=s ] +.RB [ DownloadFirmware=n ] +.RB [ DriverEnable=???? ]\p +.RB [ EnableEncryption=s ] +.RB [ Encryption=???? ] +.RB [ ExcludeUnencrypted=s ]\p +.RB [ IntraBSSRelay=s ] +.RB [ IrqList=i,j,... ] +.RB [ IrqMask=n ]\p +.RB [ Key1=s ] +.RB [ Key2=s ] +.RB [ Key3=s ] +.RB [ Key4=s ]\p +.RB [ LoadBalancing=s ] +.RB [ MaxSleepDuration=n ] +.RB [ MediumDistribution=s ]\p +.RB [ MicroWaveRobustness=s ] +.RB [ MulticastPMBuffering=s ] +.RB [ MulticastRate=n ]\p +.RB [ MulticastReceive=s ] +.RB [ NetworkAddress=n,n,n,n,n,n ] +.RB [ NetworkType=???? ]\p +.RB [ OwnATIMWindow=n ] +.RB [ OwnBeaconInterval=n ] +.RB [ OwnChannel=n ]\p +.RB [ OwnDTIMPeriod=n ] +.RB [ OwnName=s ] +.RB [ OwnSSID=s ]\p +.RB [ pc_debug=n ] +.RB [ PMEnabled=b ] +.RB [ PMHoldoverDuration=n ]\p +.RB [ PortType=n ] +.RB [ PowerMode=???? ] +.RB [ PromiscuousMode=s ]\p +.RB [ RejectANY=s ] +.RB [ RTSThreshold=n ]\p +.RB [ RTSThreshold1=n ] +.RB [ RTSThreshold2=n ] +.RB [ RTSThreshold3=n ]\p +.RB [ RTSThreshold4=n ] +.RB [ RTSThreshold5=n ] +.RB [ RTSThreshold6=n ]\p +.RB [ SRSC2GHz=b ] +.RB [ SRSC5GHz=b ] +.RB [ SystemScale=n ]\p +.RB [ TxKey=n ] +.RB [ TxRateControl=n ]\p +.RB [ TxRateControl1=n ] +.RB [ TxRateControl2=n ] +.RB [ TxRateControl3=n ]\p +.RB [ TxRateControl4=n ] +.RB [ TxRateControl5=n ] +.RB [ TxRateControl6=n ]\p +.RB [ WDSAddress=n,n,n,n,n,n ]\p +.RB [ WDSAddress1=n,n,n,n,n,n ] +.RB [ WDSAddress2=n,n,n,n,n,n ]\p +.RB [ WDSAddress3=n,n,n,n,n,n ] +.RB [ WDSAddress4=n,n,n,n,n,n ]\p +.RB [ WDSAddress5=n,n,n,n,n,n ] +.RB [ WDSAddress6=n,n,n,n,n,n ]\p +.fi + + + +.SH DESCRIPTION +.I wlags49 +is the low-level Card Services / PCI driver for the +.B Wireless PC Card, Wireless Integrated Card, Wireless Embedded Card +and other wireless adapters based on the Agere Systems Hermes-II, and Hermes-II.5 wireless MAC. When this driver is attached to a card, it +allocates the next available ethernet device (eth0..eth#). This +device name will be passed on to +.IR cardmgr (8), +or the PCI subsystem, for the card configuration, and reported in the kernel log file +with the I/O base address and MAC address used by the card. +.SH FEATURES + \- Hot plug/unplug + \- Access Point and peer-to-peer communication + \- Card power management + \- Support for Hermes-II & Hermes-II.5 based PCMCIA, Mini PCI, and CardBus cards + \- Wired Equivalent Privacy (WEP) + \- WPA-PSK support (EXPERIMENTAL) + \- Driver utility interface (UIL) + \- Wireless Extensions + \- Software AP mode +.SH PARAMETERS +.TP +.B Authentication=n +Algorithm used for Authentication. +.BR + 1 \- Open System +.BR + 2 \- Shared Key +.BR + Default: 1 +.TP +.B Auth_key_mgmt_suite +??????????????? +.TP +.B BRSC2GHz=b +Sets the card\'s Basic Rate Set in the 2.4GHz band. See SRSC2GHz +for the value\'s format. +.BR + Default: 15 (or 0x000F, only 11b rates to accept legacy 11b stations) +.TP +.B BRSC5GHz-b +Sets the card\'s Basic Rate Set in the 5.0GHz band. See SRSC2GHz for the +value\'s format +.BR + Default: 4080 (or 0x0FF0, all 11a rates) +.TP +.B Coexistence=n +Used to make the 802.11a/b/g coexistence behavior more strict. +.BR + Default \- 0 (Use standard behavior) +.TP +.B ConnectionControl=n +Configures the card\'s connection control process in dealing with multiple +bands (802.11b/g vs. 802.11a). +.BR + 0 \- Single Band operation in 2GHz +.BR + 1 \- Single Band operation in 5GHz +.BR + 2 \- Multiple Band operation starting with 2GHz +.BR + 3 \- Multiple Band operation starting with 5GHz +.BR + Default \- 2 +.TP +.B Configured +??????????????? +.TP +.B ConnectionControl +??????????????? +.TP +.B CreateIBSS=s +Enable or disable IBSS Creation. +For correct operation, specification of a OwnSSID is required. +This mode requires firmware 6.04 or higher. +.BR + N \- Disable +.BR + Y \- Enable +.BR + Default: N +.TP +.B DebugFlag=n +Selects the driver debugging level. This parameter is only available +if the module is compiled with debugging enabled. Refer to the +file +.B debug.h +in the source directory for information on the flag values. +.BR + 0x00000001L \- DBG_ERROR_ON +.BR + 0x00000002L \- DBG_WARNING_ON +.BR + 0x00000004L \- DBG_NOTICE_ON +.BR + 0x00000008L \- DBG_TRACE_ON +.BR + 0x00000010L \- DBG_VERBOSE_ON +.BR + 0x00000020L \- DBG_PARAM_ON +.BR + 0x00000040L \- DBG_BREAK_ON +.BR + 0x00000100L \- DBG_RX_ON +.BR + 0x00000200L \- DBG_TX_ON +.BR + 0x00000400L \- DBG_DS_ON +.BR +If the module is compiled with debugging enabled, DebugFlag +defaults to DBG_ERROR_ON, DBG_WARNING_ON and DBG_BREAK_ON. +DebugFlag overrules pc_debug. +.TP +.B DesiredSSID=s +Same as OwnSSID. +.TP +.B DownloadFirmware=n +This release of the driver introduces the ability to perform downloads of the STA/AP +firmware. In fact, this is required for Hermes-II based cards. This parameter tells +the driver which version of the firmware to download to the card. +.BR + 0 \- No download performed (Hermes-I only) +.BR + 1 \- Download STA firmware +.BR + 2 \- Download AP firmware +.BR + Default: 1, when STA mode functionality is + included in the build + 2, when code is built exclusively for + AP mode +.TP +.B DriverEnable +??????????????? +.TP +.B EnableEncryption=n +Set the method of Data encryption. +.BR + 0 \- Disable +.BR + 1 \- Enable WEP Encryption +.BR + 2 \- Enable WPA with TKIP encryption +.BR + Default: 0 +.TP +.B Encryption +??????????????? +.TP +.B ExcludeUnencrypted=s +Controls how the stations must communicate with the AP. +.BR + Y \- Stations must enable encryption and provide + the proper encryption key to communicate + with the AP. +.BR + N \- Stations do not need to enable encryption + to communicate with the AP. +.BR + Default: N +.TP +.B IntraBSSRelay=s +Controls the automatic relay of received messages that are destined for other +stations in the BSS. +.BR + Y \- Messages are relayed to the appropriate + station(s). +.BR + N \- Messages are passed up to the host. +.BR + Default: Y +.TP +.B IrqList=i,j,... +Specifies the set of interrupts (up to 4) that may be allocated by +this driver. This overrides the values set in the +.B IrqMask +parameter. NOTE: This parameter is for PCMCIA only. +.TP +.B IrqMask=n +Specifies a mask of valid interrupts that may be allocated by this driver. +If +.B IrqList +is also specified, the values in +.B IrqList +are used instead. NOTE: This parameter is for PCMCIA only. +.BR + Default: 0xdeb8 (IRQ 3,4,5,7,9,10,11,12,14,15) +.TP +.B Key1=s +Specifies one of 4 possible keys for the Data encryption. +One of these keys, identified by TxKey, +is used for the enciphering of Data that is transmitted by this station. +All keys specified can be used for the deciphering of Data that is received. +.BR +The key value can be an ASCII character string or a hexadecimal value. +The length of the key value can be 5 characters or 10 hexadecimal digits for +the standard encryption (Silver or Gold card), or 13 characters or 26 +hexadecimal digits for the encryption with extended keys (Gold card only). +The keys defined in the station must match the keys defined in the access +points; both on value and number (1 through 4). +.BR +In 2.0 series Linux kernel modules, values that begin with a number are +considered integers. In this case a hexadecimal value string or a character +string starting with a number, will need to be surrounded by escaped +double quotes (ie. Key1=\\"0x1122334455\\" Key2=\\"12xyz\\"). +.BR + 5 or 13, printable character string, or +.BR + 10 or 26 hex digits if preceded by "0x". +.BR + If this parameter is omitted, the default of the MAC is used ( = 0-length). +.TP +.B Key2=s +Same as Key1. +.TP +.B Key3=s +Same as Key1. +.TP +.B Key4=s +Same as Key1. +.TP +.B LoadBalancing=s +Control for the Load Balancing algorithm for both STAs and APs. The AP +includes a load balancing element in the Probe Response and Beacon frames. +The STA uses this info to select an AP, not only based on comms quality, but +also on the load of that AP. +.BR + Default: Y +.TP +.B MaxDataLength +??????????????? +.TP +.B MaxSleepDuration=n +Set the maximum Power Management sleep duration in milliseconds. +Valid values are 0 to 65535 milliseconds. +.BR + Default: 100 +.TP +.B MediumDistribution=s +Control for the distribution of medium parameters, like communication +thresholds, microwave robustness, RTS/CTS thresholds, by APs. The associated +stations replace their own values with the received values. +.BR + Default=Y +.TP +.B MicroWaveRobustness=s +Enable or disable Microwave Oven Robustness. +.BR + N \- Disable +.BR + Y \- Enable +.BR + Default: N +.TP +.B MulticastPMBuffering=s +Controls buffering of multicast MAC frames for transmission after DTIM. If no, +multicast MAC frames are directly placed in the output queue. +.BR + Default: Y +.TP +.B MulticastRate=n +Sets the data rate for multicast message transmission. +.BR + 1 \- Fixed 1Mb/s + 2 \- Fixed 2Mb/s + 3 \- Fixed 5.5Mb/s + 4 \- Fixed 11Mb/s +.BR + Default: 2 + +For Hermes-II.5, an INTEGER CONVERTED bit mask representing the +rate to multicast, where the rates supported are as follows: + +Bit : 15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00 +.br +------------------------------------------------------ +.br +Rate : XX|XX|XX|XX|54|48|36|24|18|12| 9| 6|11|5.5|2| 1 + + Default: 4 (Translates to 0x0004 = 5.5 Mb/sec) + +.TP +.B MulticastReceive=s +Enable or disable receiving of all multicast packets when Card Power Management +is enabled. When enabled, the station will wake up frequently +to receive the multicast frames. This causes less optimal power savings. +.BR + N \- Disable +.BR + Y \- Enable +.BR + Default: Y +.TP +.B NetworkAddress=n,n,n,n,n,n +Sets the adapter hardware ethernet address (MAC address) to the value +specified. Note that this is to be used to specify a Local MAC address. Do +not specify this parameter if the card\'s universal address is to be used. +Valid values are six hexadecimal digit-pairs (prefixed with 0x). +.BR + Default: +.TP +.B NetworkType +??????????????? +.TP +.B OwnATIMWindow=n +ATIM window time used for creating an IBSS. +.BR + Range: 0..100 +.BR + Default: 0 +.TP +.B OwnBeaconInterval=b +Beacon Interval in TU +.BR + Range 20..200 +.BR + Default \- 100 +.TP +.B channel=n +Same as OwnChannel. +.TP +.B OwnChannel=n +Sets the channel the Ad-Hoc or IBSS mode will use. +The default channel for Ad-Hoc mode is determined by the Wireless PC Card. +The default channel for IBSS is set to 10 by the driver. +This value has no effect when the adapter is used with an Access Point +(BSS network) since the Access Point automatically determines the channel. +Valid values are 0 to 14. However the channels allowed in +your region are subject to local regulations and are limited at +manufacturing time of the Wireless PC Card. When the provided value is +not allowed, the value remains unchanged. +.BR + 0 \- Use default channel +.BR + Default: 0 +.TP +.B OwnDTIMPeriod=n +The number of beacon intervals between successive Delivery Traffic Identification +Maps (DTIMs). +.BR + Range: 1..65535 +.BR + Default: 1 +.TP +.B OwnName=s +Sets the station name to the specified string value. This parameter +is used for diagnostic purposes, as a user\-friendly identification +of this system. This parameter accepts a maximum of 32 characters. +.BR + Default: Linux +.TP +.B OwnSSID=s +Sets the card network name to the specified string value. This parameter +accepts a maximum of 32 characters. Whitespace in the network name +will need to be escaped with a backslash (ie. OwnSSID=My\\ Network). +.BR + Default: ANY +.TP +.B pc_debug=n +Selects the PCMCIA debugging level. This parameter is only available +if the module is compiled with debugging enabled. A non\-zero value +enables debugging. Higher values yield more information, i.e. for any value all +lower values are implied. +.BR + 8 \- DBG_DS_ON +.BR + 7 \- DBG_RX_ON | DBG_TX_ON +.BR + 6 \- DBG_PARAM_ON +.BR + 5 \- DBG_TRACE_ON +.BR + 4 \- DBG_VERBOSE_ON +.BR +If the module is compiled with debugging enabled, pc_debug defaults to 5. +DebugFlag overrules pc_debug. +.BR +The name pc_debug rather than PcDebug, since pc_debug is used by many PCMCIA driver. +.TP +.B PMEnabled=b +Sets the card\'s Power Management state. +.BR + 0 \- Disable +.BR + 1 \- Enable Enhanced Mode +.BR + 2 \- Enabled Standard Mode +.BR + 0x8000 \- Enhanced?????? Mode (to be combined with 0x0001 or 0x0002) + + Default: 0 (Disabled) +.TP +.B PMHoldoverDuration=n +Time that the station remains in an awake state after a MAC frame transfer if +Enhanced Power Save is active. +.BR + Range: 1..1000 +.BR + Default: 100 +.TP +.B PowerMode +??????????????? +.TP +.B PortType=n +Selects the type of network operation. +.BR + 1 \- Normal Operation (BSS or IBSS) +.BR + 3 \- Ad-Hoc Demo Mode +.BR + Default: 1 +.TP +.B PromiscuousMode=s +Switch for promiscuous mode reception. +.BR + Default: N +.TP +.B RejectANY=s +Controls how stations associate to the device. +.BR + Y \- Stations must provide the correct SSID to + associate to the AP. +.BR + N \- Stations are not required to provide the + correct SSID to associate to the AP. + Known as an \'open\' network. +.BR + Default - N +.TP +.B RTSThreshold=n +Controls the RTS/CTS handshake threshold for transmissions in Station mode. +Valid values are 0 to 2347. +.BR + 500 \- Hidden Stations +.BR + 2347 \- No RTS/CTS +.BR + Default: 2347 +.TP +.B RTSThreshold1=n +Same as RTSThreshold, only for port 1 of in AccessPoint mode. +.TP +.B RTSThreshold2=n +Same as RTSThreshold1, only for port 2. +.TP +.B RTSThreshold3=n +Same as RTSThreshold1, only for port 3. +.TP +.B RTSThreshold4=n +Same as RTSThreshold1, only for port 4. +.TP +.B RTSThreshold5=n +Same as RTSThreshold1, only for port 5. +.TP +.B RTSThreshold6=n +Same as RTSThreshold1, only for port 6. +.TP +.B SRSC2GHz=b +Sets the card\'s Supported Rate Set in the 2.4GHz band. The value +is an INTEGER CONVERTED bit mask representing the rates to support, +where the rates supported are as follows: + +Bit : 15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00 +.br +------------------------------------------------------ +.br +Rate : XX|XX|XX|XX|54|48|36|24|18|12| 9| 6|11|5.5|2| 1 +.BR + Default: 4095 (or 0x0FFF, all 11b and 11g rates) +.TP +.B SRSC5GHz=b +Sets the card\'s Supported Rate Set in the 5.0GHz band. See SRSC2GHz +for the value\'s format. +.BR + Default: 4080 (or 0x0FF0, all 11a rates) +.TP +.B SystemScale=n +Sets the distance between Access Points in the network. This value +influences the Modem Thresholds (EnergyDetectThreshold, +CarrierDetectThreshold and DeferThreshold) and +the Roaming Thresholds (CellSearchThreshold and OutOfRangeThreshold). +.BR + 1 \- Large +.BR + 2 \- Medium +.BR + 3 \- Small +.BR + Default: 1 +.TP +.B TxRateControl=n +Sets the data rate to be used by the transmitter. For Hermes-II: +.BR + 1 \- Fixed Low (1 Mb/sec) +.BR + 2 \- Fixed Standard (2 Mb/sec) +.BR + 3 \- Auto Rate Select High (11, 5.5, 2, 1 Mb/sec) +.BR + 4 \- Fixed Medium (5.5 Mb/sec) +.BR + 5 \- Fixed High (11 Mb/sec) +.BR + 6 \- Auto Rate Select Standard (2, 1 Mb/sec) +.BR + 7 \- Auto Rate Select Medium (5.5, 2, 1 Mb/sec) +.BR + Default: 3 + +For Hermes-II.5, an INTEGER CONVERTED bit mask representing all of the +rates to support, where the rates supported are as follows: + +Bit : 15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00 +.br +------------------------------------------------------ +.br +Rate : XX|XX|XX|XX|54|48|36|24|18|12| 9| 6|11|5.5|2| 1 +.BR + Default: 4095 (Translates to 0xFFF, which is all rates) +.TP +.B RTSThreshold=n +Sets the number of octets in a message or fragment above which a +RTS/CTS handshake is performed. +Valid values are 0 to 2347. +.BR + 500 \- Hidden Stations +.BR + 2347 \- No RTS/CTS +.BR + Default: 2347 +.TP +.B TxKey=n +Designates which of the keys is to be used for the enciphering of data that is +transmitted by this station. +.BR + Integer in the range 1..4. +.BR + Default: 1 +.TP +.B TxPowLevel +??????????????? +.TP +.B TxRateControl=n +Sets the data rate to be used by the transmitter in Station mode. +.BR + 1 \- Fixed Low +.BR + 2 \- Fixed Standard +.BR + 3 \- Auto Rate Select (High) +.BR + 4 \- Fixed Medium +.BR + 5 \- Fixed High +.BR + 6 \- Auto Rate Select (Standard) +.BR + 7 \- Auto Rate Select (Medium) +.BR + Default: 3 + +For Hermes-II.5, an INTEGER CONVERTED bit mask representing all of the +rates to support, where the rates supported are as follows: + +Bit : 15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00 +.br +------------------------------------------------------ +.br +Rate : XX|XX|XX|XX|54|48|36|24|18|12| 9| 6|11|5.5|2| 1 +.BR + Default: 4095 (Translates to 0xFFF, which is all rates) + +.TP +.B TxRateControl1=n +Same as TxRateControl, only for port 1 in AccessPoint mode. +.TP +.B TxRateControl2=n +Same as TxRateControl1, only for port 2. +.TP +.B TxRateControl3=n +Same as TxRateControl1, only for port 3. +.TP +.B TxRateControl4=n +Same as TxRateControl1, only for port 4. +.TP +.B TxRateControl5=n +Same as TxRateControl1, only for port 5. +.TP +.B TxRateControl6=n +Same as TxRateControl1, only for port 6. +.TP +.B VendorDescription +??????????????? +.TP +.B WDSAddress=n,n,n,n,n,n +MAC address that identifies the corresponding node of the WDS port in Station mode. +Note that for WDS to work properly, a bridge interface must be setup between the device and +the wds network devices created by the driver. For more information on bridge +interfaces, please refer to the man page for \'brctl\'. +.BR + Default: 00:00:00:00:00:00 +.TP +.B WDSAddress1=n,n,n,n,n,n +Same as WDSAddress, only for port 1 in AccessPoint mode. +.TP +.B WDSAddress2=n,n,n,n,n,n +Same as WDSAddress1, only for port 2. +.TP +.B WDSAddress3=n,n,n,n,n,n +Same as WDSAddress1, only for port 3. +.TP +.B WDSAddress4=n,n,n,n,n,n +Same as WDSAddress1, only for port 4. +.TP +.B WDSAddress5=n,n,n,n,n,n +Same as WDSAddress1, only for port 5. +.TP +.B WDSAddress6=n,n,n,n,n,n +Same as WDSAddress1, only for port 6. +.SH SECURITY +On a multi-user system only the system administrator needs access to the WEP +encryption keys. In this case, consider removing the read permission for +normal users of the PCMCIA config.opts file, the system log file, and any +Agere proprietary iwconfig-eth scripts. +.SH CONTACT +If you encounter problems when installing or using this product, or would like +information about our other "Wireless" products, please contact your local +Authorized "Wireless" Reseller or Agere Systems sales office. + +Addresses and telephone numbers of the Agere Systems sales offices are +listed on our Agere Systems web site. +.TP +.B WWW +http://www.agere.com +.SH SEE ALSO +.BR cardmgr (8), +.BR pcmcia (5), +.BR ifconfig (8), +.BR insmod (8), +.BR brctl (8). diff --git a/drivers/staging/wlags49_h2/mdd.h b/drivers/staging/wlags49_h2/mdd.h new file mode 100644 index 0000000000000000000000000000000000000000..b45c7ddd92e29b10840a2053f87db63b07a49caa --- /dev/null +++ b/drivers/staging/wlags49_h2/mdd.h @@ -0,0 +1,1156 @@ + +// vim:tw=110:ts=4: +#ifndef MDD_H +#define MDD_H 1 + +/************************************************************************************************************* +* +* FILE : mdd.h +* +* DATE : $Date: 2004/08/05 11:47:10 $ $Revision: 1.6 $ +* Original : 2004/05/25 05:59:37 Revision: 1.57 Tag: hcf7_t20040602_01 +* Original : 2004/05/13 15:31:45 Revision: 1.54 Tag: hcf7_t7_20040513_01 +* Original : 2004/04/15 09:24:41 Revision: 1.47 Tag: hcf7_t7_20040415_01 +* Original : 2004/04/13 14:22:45 Revision: 1.46 Tag: t7_20040413_01 +* Original : 2004/04/01 15:32:55 Revision: 1.42 Tag: t7_20040401_01 +* Original : 2004/03/10 15:39:28 Revision: 1.38 Tag: t20040310_01 +* Original : 2004/03/04 11:03:37 Revision: 1.36 Tag: t20040304_01 +* Original : 2004/03/02 09:27:11 Revision: 1.34 Tag: t20040302_03 +* Original : 2004/02/24 13:00:27 Revision: 1.29 Tag: t20040224_01 +* Original : 2004/02/18 17:13:57 Revision: 1.26 Tag: t20040219_01 +* +* AUTHOR : Nico Valster +* +* DESC : Definitions and Prototypes for HCF, DHF, MMD and MSF +* +*************************************************************************************************************** +* +* +* SOFTWARE LICENSE +* +* This software is provided subject to the following terms and conditions, +* which you should read carefully before using the software. Using this +* software indicates your acceptance of these terms and conditions. If you do +* not agree with these terms and conditions, do not use the software. +* +* COPYRIGHT © 1994 - 1995 by AT&T. All Rights Reserved +* COPYRIGHT © 1996 - 2000 by Lucent Technologies. All Rights Reserved +* COPYRIGHT © 2001 - 2004 by Agere Systems Inc. All Rights Reserved +* All rights reserved. +* +* Redistribution and use in source or binary forms, with or without +* modifications, 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 as comments in the code as +* well as in the documentation and/or other materials provided with the +* distribution. +* +* . 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. +* +* . Neither the name of Agere Systems Inc. nor the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* Disclaimer +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY +* USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN +* RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. +* +* +************************************************************************************************************/ + + +/************************************************************************************************************ +* +* The macros Xn(...) and XXn(...) are used to define the LTV's (short for Length Type Value[ ]) , +* aka RIDs, processed by the Hermes. +* The n in Xn and XXn reflects the number of "Value" fields in these RIDs. +* +* Xn(...) : Macros used for RIDs which use only type hcf_16 for the "V" fields of the LTV. +* Xn takes as parameters a RID name and "n" name(s), one for each of the "V" fields of the LTV. +* +* XXn(...) : Macros used for RIDs which use at least one other type then hcf_16 for a "V" field +* of the LTV. +* XXn(..) takes as parameters a RID name and "n" pair(s) of type and name, one for each "V" field +* of the LTV + + ****************************************** e x a m p l e s *********************************************** + +* X1(RID_NAME, parameters...) : expands to : +* typedef struct RID_NAME_STRCT { +* hcf_16 len; +* hcf_16 typ; +* hcf_16 par1; +* } RID_NAME_STRCT; + +* X2(RID_NAME, parameters...) : expands to : +* typedef struct RID_NAME_STRCT { +* hcf_16 len; +* hcf_16 typ; +* hcf_16 par1; +* hcf_16 par2; +* } RID_NAME_STRCT; + + +* XX1(RID_NAME, par1type, par1name, ...) : expands to : +* typedef struct RID_NAME_STRCT { +* hcf_16 len; +* hcf_16 typ; +* par1type par1name; +* } RID_NAME_STRCT; + +************************************************************************************************************/ + +/******************************* XX Sub-macro definitions **************************************************/ + +#define XX1( name, type1, par1 ) \ +typedef struct { \ + hcf_16 len; \ + hcf_16 typ; \ + type1 par1; \ +} name##_STRCT; + +#define XX2( name, type1, par1, type2, par2 ) \ +typedef struct { \ + hcf_16 len; \ + hcf_16 typ; \ + type1 par1; \ + type2 par2; \ +} name##_STRCT; + +#define XX3( name, type1, par1, type2, par2, type3, par3 ) \ +typedef struct name##_STRCT { \ + hcf_16 len; \ + hcf_16 typ; \ + type1 par1; \ + type2 par2; \ + type3 par3; \ +} name##_STRCT; + +#define XX4( name, type1, par1, type2, par2, type3, par3, type4, par4 ) \ +typedef struct { \ + hcf_16 len; \ + hcf_16 typ; \ + type1 par1; \ + type2 par2; \ + type3 par3; \ + type4 par4; \ +} name##_STRCT; + +#define X1( name, par1 ) \ +typedef struct name##_STRCT { \ + hcf_16 len; \ + hcf_16 typ; \ + hcf_16 par1; \ +} name##_STRCT; + +#define X2( name, par1, par2 ) \ +typedef struct { \ + hcf_16 len; \ + hcf_16 typ; \ + hcf_16 par1; \ + hcf_16 par2; \ +} name##_STRCT; + +#define X3( name, par1, par2, par3 ) \ +typedef struct { \ + hcf_16 len; \ + hcf_16 typ; \ + hcf_16 par1; \ + hcf_16 par2; \ + hcf_16 par3; \ +} name##_STRCT; + +#define X4( name, par1, par2, par3, par4 ) \ +typedef struct { \ + hcf_16 len; \ + hcf_16 typ; \ + hcf_16 par1; \ + hcf_16 par2; \ + hcf_16 par3; \ + hcf_16 par4; \ +} name##_STRCT; + +#define X5( name, par1, par2, par3, par4, par5 ) \ +typedef struct { \ + hcf_16 len; \ + hcf_16 typ; \ + hcf_16 par1; \ + hcf_16 par2; \ + hcf_16 par3; \ + hcf_16 par4; \ + hcf_16 par5; \ +} name##_STRCT; + +#define X6( name, par1, par2, par3, par4, par5, par6 ) \ +typedef struct { \ + hcf_16 len; \ + hcf_16 typ; \ + hcf_16 par1; \ + hcf_16 par2; \ + hcf_16 par3; \ + hcf_16 par4; \ + hcf_16 par5; \ + hcf_16 par6; \ +} name##_STRCT; + +#define X8( name, par1, par2, par3, par4, par5, par6, par7, par8 ) \ +typedef struct { \ + hcf_16 len; \ + hcf_16 typ; \ + hcf_16 par1; \ + hcf_16 par2; \ + hcf_16 par3; \ + hcf_16 par4; \ + hcf_16 par5; \ + hcf_16 par6; \ + hcf_16 par7; \ + hcf_16 par8; \ +} name##_STRCT; + +#define X11( name, par1, par2, par3, par4, par5, par6, par7, par8, par9, par10, par11 ) \ +typedef struct { \ + hcf_16 len; \ + hcf_16 typ; \ + hcf_16 par1; \ + hcf_16 par2; \ + hcf_16 par3; \ + hcf_16 par4; \ + hcf_16 par5; \ + hcf_16 par6; \ + hcf_16 par7; \ + hcf_16 par8; \ + hcf_16 par9; \ + hcf_16 par10; \ + hcf_16 par11; \ +} name##_STRCT; + +/******************************* Substructure definitions **************************************************/ + +//apparently not needed (CFG_CNF_COUNTRY) +typedef struct CHANNEL_SET { //channel set structure used in the CFG_CNF_COUNTRY LTV + hcf_16 first_channel; + hcf_16 number_of_channels; + hcf_16 max_tx_output_level; +} CHANNEL_SET; + +typedef struct KEY_STRCT { // key structure used in the CFG_DEFAULT_KEYS LTV + hcf_16 len; //length of key + hcf_8 key[14]; //encryption key +} KEY_STRCT; + +typedef struct SCAN_RS_STRCT { // Scan Result structure used in the CFG_SCAN LTV + hcf_16 channel_id; + hcf_16 noise_level; + hcf_16 signal_level; + hcf_8 bssid[6]; + hcf_16 beacon_interval_time; + hcf_16 capability; + hcf_16 ssid_len; + hcf_8 ssid_val[32]; +} SCAN_RS_STRCT; + +typedef struct CFG_RANGE_SPEC_STRCT { // range specification structure used in CFG_RANGES, CFG_RANGE1 etc + hcf_16 variant; + hcf_16 bottom; + hcf_16 top; +} CFG_RANGE_SPEC_STRCT; + +typedef struct CFG_RANGE_SPEC_BYTE_STRCT { // byte oriented range specification structure used in CFG_RANGE_B LTV + hcf_8 variant[2]; + hcf_8 bottom[2]; + hcf_8 top[2]; +} CFG_RANGE_SPEC_BYTE_STRCT; + +//used to set up "T" functionality for Info frames, i.e. log info frames in MSF supplied buffer and MailBox +XX1( RID_LOG, unsigned short FAR*, bufp ) +typedef RID_LOG_STRCT FAR *RID_LOGP; +XX1( CFG_RID_LOG, RID_LOGP, recordp ) + + X1( LTV, val[1] ) /*minimum LTV proto typ */ + X1( LTV_MAX, val[HCF_MAX_LTV] ) /*maximum LTV proto typ */ +XX2( CFG_REG_MB, hcf_16* , mb_addr, hcf_16, mb_size ) + +typedef struct CFG_MB_INFO_FRAG { // specification of buffer fragment + unsigned short FAR* frag_addr; + hcf_16 frag_len; +} CFG_MB_INFO_FRAG; + +/* Mail Box Info Block structures, + * the base form: CFG_MB_INFO_STRCT + * and the derived forms: CFG_MB_INFO_RANGE_STRCT with n is 1, 2, 3 or 20 + * predefined for a payload of 1, and up to 2, 3 and 20 CFG_MB_INFO_FRAG elements */ +XX3( CFG_MB_INFO, hcf_16, base_typ, hcf_16, frag_cnt, CFG_MB_INFO_FRAG, frag_buf[ 1] ) +XX3( CFG_MB_INFO_RANGE1, hcf_16, base_typ, hcf_16, frag_cnt, CFG_MB_INFO_FRAG, frag_buf[ 1] ) +XX3( CFG_MB_INFO_RANGE2, hcf_16, base_typ, hcf_16, frag_cnt, CFG_MB_INFO_FRAG, frag_buf[ 2] ) +XX3( CFG_MB_INFO_RANGE3, hcf_16, base_typ, hcf_16, frag_cnt, CFG_MB_INFO_FRAG, frag_buf[ 3] ) +XX3( CFG_MB_INFO_RANGE20, hcf_16, base_typ, hcf_16, frag_cnt, CFG_MB_INFO_FRAG, frag_buf[20] ) + +XX3( CFG_MB_ASSERT, hcf_16, line, hcf_16, trace, hcf_32, qualifier ) /*MBInfoBlock for asserts */ +#if (HCF_ASSERT) & ( HCF_ASSERT_LNK_MSF_RTN | HCF_ASSERT_RT_MSF_RTN ) +typedef void (MSF_ASSERT_RTN)( unsigned int , hcf_16, hcf_32 ); +typedef MSF_ASSERT_RTN /*can't link FAR*/ * MSF_ASSERT_RTNP; +/* CFG_REG_ASSERT_RTNP (0x0832) (de-)register MSF Callback routines + * lvl: Assert level filtering (not yet implemented) + * rtnp: address of MSF_ASSERT_RTN (native Endian format) */ +XX2( CFG_REG_ASSERT_RTNP, hcf_16, lvl, MSF_ASSERT_RTNP, rtnp ) +#endif // HCF_ASSERT_LNK_MSF_RTN / HCF_ASSERT_RT_MSF_RTN + + X1( CFG_HCF_OPT, val[20] ) /*(Compile time) options */ + X3( CFG_CMD_HCF, cmd, mode, add_info ) /*HCF Engineering command */ + +typedef struct { + hcf_16 len; + hcf_16 typ; + hcf_16 mode; // PROG_STOP/VOLATILE [FLASH/SEEPROM/SEEPROM_READBACK] + hcf_16 segment_size; // size of the segment in bytes + hcf_32 nic_addr; // destination address (in NIC memory) + hcf_16 flags; // 0x0001 : CRC Yes/No +// hcf_32 flags; // 0x0001 : CRC Yes/No + /* ;? still not the whole story + * flags is extended from 16 to 32 bits to force that compiling FW.C produces the same structures + * in memory as FUPU4 BIN files. + * Note that the problem arises from the violation of the constraint to use packing at byte boundaries + * as was stipulated in the WCI-specification + * The Pack pragma can't resolve this issue, because that impacts all members of the structure with + * disregard of their actual size, so aligning host_addr under MSVC 1.5 at 4 bytes, also aligns + * len, typ etc on 4 bytes + * */ +// hcf_16 pad; //!! be careful alignment problems for Bin download versus C download + hcf_8 FAR *host_addr; // source address (in Host memory) +} CFG_PROG_STRCT; // segment_descp; + +// a structure used for transporting debug-related information from firmware +// via the HCF, into the MSF +typedef struct { + hcf_16 len; + hcf_16 typ; + hcf_16 msg_id, msg_par, msg_tstamp; +} CFG_FW_PRINTF_STRCT; + +// a structure used to define the location and size of a certain debug-related +// buffer in nic-ram. +typedef struct { + hcf_16 len; + hcf_16 typ; + hcf_32 DbMsgCount, // ds (nicram) address of a counter + DbMsgBuffer, // ds (nicram) address of the buffer + DbMsgSize, // number of entries (each 3 word in size) in this buffer + DbMsgIntrvl; // ds (nicram) address of interval for generating InfDrop event +} CFG_FW_PRINTF_BUFFER_LOCATION_STRCT; + +XX3( CFG_RANGES, hcf_16, role, hcf_16, id, CFG_RANGE_SPEC_STRCT, var_rec[ 1] ) /*Actor/Supplier range (1 variant)*/ +XX3( CFG_RANGE1, hcf_16, role, hcf_16, id, CFG_RANGE_SPEC_STRCT, var_rec[ 1] ) /*Actor/Supplier range (1 variant)*/ +XX3( CFG_RANGE2, hcf_16, role, hcf_16, id, CFG_RANGE_SPEC_STRCT, var_rec[ 2] ) /*Actor range ( 2 variants) */ +XX3( CFG_RANGE3, hcf_16, role, hcf_16, id, CFG_RANGE_SPEC_STRCT, var_rec[ 3] ) /*Actor range ( 3 variants) */ +XX3( CFG_RANGE4, hcf_16, role, hcf_16, id, CFG_RANGE_SPEC_STRCT, var_rec[ 4] ) /*Actor range ( 4 variants) */ +XX3( CFG_RANGE5, hcf_16, role, hcf_16, id, CFG_RANGE_SPEC_STRCT, var_rec[ 5] ) /*Actor range ( 5 variants) */ +XX3( CFG_RANGE6, hcf_16, role, hcf_16, id, CFG_RANGE_SPEC_STRCT, var_rec[ 6] ) /*Actor range ( 6 variants) */ +XX3( CFG_RANGE7, hcf_16, role, hcf_16, id, CFG_RANGE_SPEC_STRCT, var_rec[ 7] ) /*Actor range ( 7 variants) */ +XX3( CFG_RANGE20, hcf_16, role, hcf_16, id, CFG_RANGE_SPEC_STRCT, var_rec[20] ) /*Actor range (20 variants) */ + +/*Frames */ + X3( CFG_ASSOC_STAT, assoc_stat, station_addr[3], val[46] ) /*Association status, basic */ + X2( CFG_ASSOC_STAT3, assoc_stat, station_addr[3] ) /*assoc_stat:3 */ + X3( CFG_ASSOC_STAT1, assoc_stat, station_addr[3], frame_body[43] ) /*assoc_stat:1 */ + X4( CFG_ASSOC_STAT2, assoc_stat, station_addr[3], old_ap_addr[3], frame_body[43] ) /*assoc_stat:2 */ + +/*Static Configurations */ + X1( CFG_CNF_PORT_TYPE, port_type ) /*[STA] Connection control characteristics */ + X1( CFG_MAC_ADDR, mac_addr[3] ) /*general: FC01,FC08,FC11,FC12,FC13,FC14,FC15,FC16 */ + X1( CFG_CNF_OWN_MAC_ADDR, mac_addr[3] ) + X1( CFG_ID, ssid[17] ) /*0xFC02, 0xFC04, 0xFC0E */ +/* X1( CFG_DESIRED_SSID, ssid[17] ) see Dynamic Configurations */ + X1( CFG_CNF_OWN_CHANNEL, channel ) /*Communication channel for BSS creation */ + X1( CFG_CNF_OWN_SSID, ssid[17] ) + X1( CFG_CNF_OWN_ATIM_WINDOW, atim_window ) + X1( CFG_CNF_SYSTEM_SCALE, system_scale ) + X1( CFG_CNF_MAX_DATA_LEN, max_data_len ) + X1( CFG_CNF_WDS_ADDR, mac_addr[3] ) /*[STA] MAC Address of corresponding WDS Link node */ + X1( CFG_CNF_PM_ENABLED, pm_enabled ) /*[STA] Switch for ESS Power Management (PM) On/Off */ + X1( CFG_CNF_PM_EPS, pm_eps ) /*[STA] Switch for ESS PM EPS/PS Mode */ + X1( CFG_CNF_MCAST_RX, mcast_rx ) /*[STA] Switch for ESS PM Multicast reception On/Off */ + X1( CFG_CNF_MAX_SLEEP_DURATION, duration ) /*[STA] Maximum sleep time for ESS PM */ + X1( CFG_CNF_PM_HOLDOVER_DURATION, duration ) /*[STA] Holdover time for ESS PM */ + X1( CFG_CNF_OWN_NAME, ssid[17] ) /*Identification text for diagnostic purposes */ + X1( CFG_CNF_OWN_DTIM_PERIOD, period ) /*[AP] Beacon intervals between successive DTIMs */ + X1( CFG_CNF_WDS_ADDR1, mac_addr[3] ) /*[AP] Port 1 MAC Adrs of corresponding WDS Link node */ + X1( CFG_CNF_WDS_ADDR2, mac_addr[3] ) /*[AP] Port 2 MAC Adrs of corresponding WDS Link node */ + X1( CFG_CNF_WDS_ADDR3, mac_addr[3] ) /*[AP] Port 3 MAC Adrs of corresponding WDS Link node */ + X1( CFG_CNF_WDS_ADDR4, mac_addr[3] ) /*[AP] Port 4 MAC Adrs of corresponding WDS Link node */ + X1( CFG_CNF_WDS_ADDR5, mac_addr[3] ) /*[AP] Port 5 MAC Adrs of corresponding WDS Link node */ + X1( CFG_CNF_WDS_ADDR6, mac_addr[3] ) /*[AP] Port 6 MAC Adrs of corresponding WDS Link node */ + X1( CFG_CNF_MCAST_PM_BUF, mcast_pm_buf ) /*[AP] Switch for PM buffering of Multicast Messages */ + X1( CFG_CNF_REJECT_ANY, reject_any ) /*[AP] Switch for PM buffering of Multicast Messages */ +//X1( CFG_CNF_ENCRYPTION_ENABLED, encryption ) /*specify encryption type of Tx/Rx messages */ + X1( CFG_CNF_ENCRYPTION, encryption ) /*specify encryption type of Tx/Rx messages */ + X1( CFG_CNF_AUTHENTICATION, authentication ) /*selects Authentication algorithm */ + X1( CFG_CNF_EXCL_UNENCRYPTED, exclude_unencrypted ) /*[AP] Switch for 'clear-text' rx message acceptance */ + X1( CFG_CNF_MCAST_RATE, mcast_rate ) /*Transmit Data rate for Multicast frames */ + X1( CFG_CNF_INTRA_BSS_RELAY, intra_bss_relay ) /*[AP] Switch for IntraBBS relay */ + X1( CFG_CNF_MICRO_WAVE, micro_wave ) /*MicroWave (Robustness) */ + X1( CFG_CNF_LOAD_BALANCING, load_balancing ) /*Load Balancing (Boolean, 0=OFF, 1=ON, default=1) */ + X1( CFG_CNF_MEDIUM_DISTRIBUTION, medium_distribution ) /*Medium Distribution (Boolean, 0=OFF, 1=ON, default=1) */ + X1( CFG_CNF_GROUP_ADDR_FILTER, group_addr_filter ) /*Group Address Filter */ + X1( CFG_CNF_TX_POW_LVL, tx_pow_lvl ) /*Tx Power Level */ +XX4( CFG_CNF_COUNTRY_INFO, \ + hcf_16, n_channel_sets, hcf_16, country_code[2], \ + hcf_16, environment, CHANNEL_SET, channel_set[1] ) /*Current Country Info */ +XX4( CFG_CNF_COUNTRY_INFO_MAX, \ + hcf_16, n_channel_sets, hcf_16, country_code[2], \ + hcf_16, environment, CHANNEL_SET, channel_set[14]) /*Current Country Info */ + +/*Dynamic Configurations */ + X1( CFG_DESIRED_SSID, ssid[17] ) /*[STA] Service Set identification for connection */ +#define GROUP_ADDR_SIZE (32 * 6) //32 6-byte MAC-addresses + X1( CFG_GROUP_ADDR, mac_addr[GROUP_ADDR_SIZE/2] ) /*[STA] Multicast MAC Addresses for Rx-message */ + X1( CFG_CREATE_IBSS, create_ibss ) /*[STA] Switch for IBSS creation On/Off */ + X1( CFG_RTS_THRH, rts_thrh ) /*[STA] Frame length used for RTS/CTS handshake */ + X1( CFG_TX_RATE_CNTL, tx_rate_cntl ) /*[STA] Data rate control for message transmission */ + X1( CFG_PROMISCUOUS_MODE, promiscuous_mode ) /*[STA] Switch for Promiscuous mode reception On/Of */ + X1( CFG_WOL, wake_on_lan ) /*[STA] Switch for Wake-On-LAN mode */ + X1( CFG_RTS_THRH0, rts_thrh ) /*[AP] Port 0 frame length for RTS/CTS handshake */ + X1( CFG_RTS_THRH1, rts_thrh ) /*[AP] Port 1 frame length for RTS/CTS handshake */ + X1( CFG_RTS_THRH2, rts_thrh ) /*[AP] Port 2 frame length for RTS/CTS handshake */ + X1( CFG_RTS_THRH3, rts_thrh ) /*[AP] Port 3 frame length for RTS/CTS handshake */ + X1( CFG_RTS_THRH4, rts_thrh ) /*[AP] Port 4 frame length for RTS/CTS handshake */ + X1( CFG_RTS_THRH5, rts_thrh ) /*[AP] Port 5 frame length for RTS/CTS handshake */ + X1( CFG_RTS_THRH6, rts_thrh ) /*[AP] Port 6 frame length for RTS/CTS handshake */ + X1( CFG_TX_RATE_CNTL0, rate_cntl ) /*[AP] Port 0 data rate control for transmission */ + X1( CFG_TX_RATE_CNTL1, rate_cntl ) /*[AP] Port 1 data rate control for transmission */ + X1( CFG_TX_RATE_CNTL2, rate_cntl ) /*[AP] Port 2 data rate control for transmission */ + X1( CFG_TX_RATE_CNTL3, rate_cntl ) /*[AP] Port 3 data rate control for transmission */ + X1( CFG_TX_RATE_CNTL4, rate_cntl ) /*[AP] Port 4 data rate control for transmission */ + X1( CFG_TX_RATE_CNTL5, rate_cntl ) /*[AP] Port 5 data rate control for transmission */ + X1( CFG_TX_RATE_CNTL6, rate_cntl ) /*[AP] Port 6 data rate control for transmission */ +XX1( CFG_DEFAULT_KEYS, KEY_STRCT, key[4] ) /*defines set of encryption keys */ + X1( CFG_TX_KEY_ID, tx_key_id ) /*select key for encryption of Tx messages */ + X1( CFG_SCAN_SSID, ssid[17] ) /*identification for connection */ + X5( CFG_ADD_TKIP_DEFAULT_KEY, \ + tkip_key_id_info, tkip_key_iv_info[4], tkip_key[8], \ + tx_mic_key[4], rx_mic_key[4] ) /* */ + X6( CFG_ADD_TKIP_MAPPED_KEY, bssid[3], tkip_key[8], \ + tsc[4], rsc[4], tx_mic_key[4], rx_mic_key[4] ) /* */ + X1( CFG_SET_SSN_AUTHENTICATION_SUITE, \ + ssn_authentication_suite ) /* */ + X1( CFG_REMOVE_TKIP_DEFAULT_KEY,tkip_key_id ) /* */ + X1( CFG_TICK_TIME, tick_time ) /*Auxiliary Timer tick interval */ + X1( CFG_DDS_TICK_TIME, tick_time ) /*Disconnected DeepSleep Timer tick interval */ + +/********************************************************************** +* Added for Pattern-matching WakeOnLan. (See firmware design note WMDN281C) +**********************************************************************/ +#define WOL_PATTERNS 5 // maximum of 5 patterns in firmware +#define WOL_PATTERN_LEN 124 // maximum 124 bytes pattern length per pattern in firmware +#define WOL_MASK_LEN 30 // maximum 30 bytes mask length per pattern in firmware +#define WOL_BUF_SIZE (WOL_PATTERNS * (WOL_PATTERN_LEN + WOL_MASK_LEN + 6) / 2) +X2( CFG_WOL_PATTERNS, nPatterns, buffer[WOL_BUF_SIZE] ) /*[STA] WakeOnLan pattern match, room for 5 patterns*/ + + X5( CFG_SUP_RANGE, role, id, variant, bottom, top ) /*[PRI] Primary Supplier compatibility range */ +/* NIC Information */ + X4( CFG_IDENTITY, comp_id, variant, version_major, version_minor ) /*identification Prototype */ +#define CFG_DRV_IDENTITY_STRCT CFG_IDENTITY_STRCT +#define CFG_PRI_IDENTITY_STRCT CFG_IDENTITY_STRCT +#define CFG_NIC_IDENTITY_STRCT CFG_IDENTITY_STRCT +#define CFG_FW_IDENTITY_STRCT CFG_IDENTITY_STRCT + X1( CFG_RID_INF_MIN, y ) /*lowest value representing an Information RID */ + X1( CFG_MAX_LOAD_TIME, max_load_time ) /*[PRI] Max response time of the Download command */ + X3( CFG_DL_BUF, buf_page, buf_offset, buf_len ) /*[PRI] Download buffer location and size */ +// X5( CFG_PRI_SUP_RANGE, role, id, variant, bottom, top ) /*[PRI] Primary Supplier compatibility range */ + X5( CFG_CFI_ACT_RANGES_PRI,role, id, variant, bottom, top ) /*[PRI] Controller Actor compatibility ranges */ +// X5( CFG_NIC_HSI_SUP_RANGE, role, id, variant, bottom, top ) /*H/W - S/W I/F supplier range */ + X1( CFG_NIC_SERIAL_NUMBER, serial_number[17] ) /*[PRI] Network I/F Card serial number */ + X5( CFG_NIC_MFI_SUP_RANGE, role, id, variant, bottom, top ) /*[PRI] Modem I/F Supplier compatibility range */ + X5( CFG_NIC_CFI_SUP_RANGE, role, id, variant, bottom, top ) /*[PRI] Controller I/F Supplier compatibility range*/ +//H-I X1( CFG_CHANNEL_LIST, channel_list ) /*Allowed communication channels */ +//H-I XX2( CFG_REG_DOMAINS, hcf_16, num_domain, hcf_8, reg_domains[10] ) /*List of intended regulatory domains */ + X1( CFG_NIC_TEMP_TYPE, temp_type ) /*Hardware temperature range code */ +//H-I X1( CFG_CIS, cis[240] ) /*PC Card Standard Card Information Structure */ + X5( CFG_NIC_PROFILE, \ + profile_code, capability_options, allowed_data_rates, val4, val5 ) /*Card Profile */ +// X5( CFG_FW_SUP_RANGE, role, id, variant, bottom, top ) /*[STA] Station I/F Supplier compatibility range */ + X5( CFG_MFI_ACT_RANGES, role, id, variant, bottom, top ) /*[STA] Modem I/F Actor compatibility ranges */ + X5( CFG_CFI_ACT_RANGES_STA,role, id, variant, bottom, top ) /*[STA] Controller I/F Actor compatibility ranges */ + X5( CFG_MFI_ACT_RANGES_STA,role, id, variant, bottom, top ) /*[STA] Controller I/F Actor compatibility ranges */ + X1( CFG_NIC_BUS_TYPE, nic_bus_type ) /*NIC bustype derived from BUSSEL host I/F signals */ + +/* MAC INFORMATION */ + X1( CFG_PORT_STAT, port_stat ) /*[STA] Actual MAC Port connection control status */ + X1( CFG_CUR_SSID, ssid[17] ) /*[STA] Identification of the actually connected SS */ + X1( CFG_CUR_BSSID, mac_addr[3] ) /*[STA] Identification of the actually connected BSS */ + X3( CFG_COMMS_QUALITY, coms_qual, signal_lvl, noise_lvl ) /*[STA] Quality of the Basic Service Set connection */ + X1( CFG_CUR_TX_RATE, rate ) /*[STA] Actual transmit data rate */ + X1( CFG_CUR_BEACON_INTERVAL, interval ) /*Beacon transmit interval time for BSS creation */ +#if (HCF_TYPE) & HCF_TYPE_WARP + X11( CFG_CUR_SCALE_THRH, \ + carrier_detect_thrh_cck, carrier_detect_thrh_ofdm, defer_thrh, \ + energy_detect_thrh, rssi_on_thrh_deviation, \ + rssi_off_thrh_deviation, cck_drop_thrh, ofdm_drop_thrh, \ + cell_search_thrh, out_of_range_thrh, delta_snr ) +#else + X6( CFG_CUR_SCALE_THRH, \ + energy_detect_thrh, carrier_detect_thrh, defer_thrh, \ + cell_search_thrh, out_of_range_thrh, delta_snr ) /*Actual System Scale thresholds settings */ +#endif // HCF_TYPE_WARP + X1( CFG_PROTOCOL_RSP_TIME, time ) /*Max time to await a response to a request message */ + X1( CFG_CUR_SHORT_RETRY_LIMIT, limit ) /*Max number of transmit attempts for short frames */ + X1( CFG_CUR_LONG_RETRY_LIMIT, limit ) /*Max number of transmit attempts for long frames */ + X1( CFG_MAX_TX_LIFETIME, time ) /*Max transmit frame handling duration */ + X1( CFG_MAX_RX_LIFETIME, time ) /*Max received frame handling duration */ + X1( CFG_CF_POLLABLE, cf_pollable ) /*[STA] Contention Free pollable capability indication */ + X2( CFG_AUTHENTICATION_ALGORITHMS,authentication_type, type_enabled ) /*Authentication Algorithm */ + X1( CFG_PRIVACY_OPT_IMPLEMENTED,privacy_opt_implemented ) /*WEP Option availability indication */ + X1( CFG_CUR_REMOTE_RATES, rates ) /*CurrentRemoteRates */ + X1( CFG_CUR_USED_RATES, rates ) /*CurrentUsedRates */ + X1( CFG_CUR_SYSTEM_SCALE, current_system_scale ) /*CurrentUsedRates */ + X1( CFG_CUR_TX_RATE1, rate ) /*[AP] Actual Port 1 transmit data rate */ + X1( CFG_CUR_TX_RATE2, rate ) /*[AP] Actual Port 2 transmit data rate */ + X1( CFG_CUR_TX_RATE3, rate ) /*[AP] Actual Port 3 transmit data rate */ + X1( CFG_CUR_TX_RATE4, rate ) /*[AP] Actual Port 4 transmit data rate */ + X1( CFG_CUR_TX_RATE5, rate ) /*[AP] Actual Port 5 transmit data rate */ + X1( CFG_CUR_TX_RATE6, rate ) /*[AP] Actual Port 6 transmit data rate */ + X1( CFG_OWN_MAC_ADDR, mac_addr[3] ) /*[AP] Unique local node MAC Address */ + X3( CFG_PCF_INFO, medium_occupancy_limit, \ + cfp_period, cfp_max_duration ) /*[AP] Point Coordination Function capability info */ + X1( CFG_CUR_SSN_INFO_ELEMENT, ssn_info_element[1] ) /* */ + X4( CFG_CUR_TKIP_IV_INFO, \ + tkip_seq_cnt0[4], tkip_seq_cnt1[4], \ + tkip_seq_cnt2[4], tkip_seq_cnt3[4] ) /* */ + X2( CFG_CUR_ASSOC_REQ_INFO, frame_type, frame_body[1] ) /* 0xFD8C */ + X2( CFG_CUR_ASSOC_RESP_INFO, frame_type, frame_body[1] ) /* 0xFD8D */ + + +/* Modem INFORMATION */ + X1( CFG_PHY_TYPE, phy_type ) /*Physical layer type indication */ + X1( CFG_CUR_CHANNEL, current_channel ) /*Actual frequency channel used for transmission */ + X1( CFG_CUR_POWER_STATE, current_power_state ) /*Actual power consumption status */ + X1( CFG_CCAMODE, cca_mode ) /*Clear channel assessment mode indication */ + X1( CFG_SUPPORTED_DATA_RATES, rates[5] ) /*Data rates capability information */ + + +/* FRAMES */ +XX1( CFG_SCAN, SCAN_RS_STRCT, scan_result[32] ) /*Scan results */ + + + +//-------------------------------------------------------------------------------------- +// UIL management function to be passed to WaveLAN/IEEE Drivers in DUI_STRCT field fun +//-------------------------------------------------------------------------------------- + +// HCF and UIL Common +#define MDD_ACT_SCAN 0x06 // Hermes Inquire Scan (F101) command +#define MDD_ACT_PRS_SCAN 0x07 // Hermes Probe Response Scan (F102) command + +// UIL Specific +#define UIL_FUN_CONNECT 0x00 // Perform connect command +#define UIL_FUN_DISCONNECT 0x01 // Perform disconnect command +#define UIL_FUN_ACTION 0x02 // Perform UIL Action command. +#define UIL_FUN_SEND_DIAG_MSG 0x03 // Send a diagnostic message. +#define UIL_FUN_GET_INFO 0x04 // Retrieve information from NIC. +#define UIL_FUN_PUT_INFO 0x05 // Put information on NIC. + +/* UIL_ACT_TALLIES 0x05 * this should not be exported to the USF + * it is solely intended as a strategic choice for the MSF to either + * - use HCF_ACT_TALLIES and direct IFB access + * - use CFG_TALLIES + */ +#define UIL_ACT_SCAN MDD_ACT_SCAN +#define UIL_ACT_PRS_SCAN MDD_ACT_PRS_SCAN +#define UIL_ACT_BLOCK 0x0B +#define UIL_ACT_UNBLOCK 0x0C +#define UIL_ACT_RESET 0x80 +#define UIL_ACT_REBIND 0x81 +#define UIL_ACT_APPLY 0x82 +#define UIL_ACT_DISCONNECT 0x83 //;?040108 possibly obsolete //Special for WINCE + +// HCF Specific +/* Note that UIL_ACT-codes must match HCF_ACT-codes across a run-time bound I/F + * The initial matching is achieved by "#define HCF_ACT_xxx HCF_UIL_ACT_xxx" where appropriate + * In other words, these codes should never, ever change to minimize migration problems between + * combinations of old drivers and new utilities and vice versa + */ +#define HCF_DISCONNECT 0x01 //disconnect request for hcf_connect (invalid as IO Address) +#define HCF_ACT_TALLIES 0x05 // ! UIL_ACT_TALLIES does not exist ! Hermes Inquire Tallies (F100) cmd +#if ( (HCF_TYPE) & HCF_TYPE_WARP ) == 0 +#define HCF_ACT_SCAN MDD_ACT_SCAN +#endif // HCF_TYPE_WARP +#define HCF_ACT_PRS_SCAN MDD_ACT_PRS_SCAN +#if HCF_INT_ON +#define HCF_ACT_INT_OFF 0x0D // Disable Interrupt generation +#define HCF_ACT_INT_ON 0x0E // Enable Interrupt generation +#define HCF_ACT_INT_FORCE_ON 0x0F // Enforce Enable Interrupt generation +#endif // HCF_INT_ON +#define HCF_ACT_RX_ACK 0x15 // Receiever ACK (optimization) +#if (HCF_TYPE) & HCF_TYPE_CCX +#define HCF_ACT_CCX_ON 0x1A // enable CKIP +#define HCF_ACT_CCX_OFF 0x1B // disable CKIP +#endif // HCF_TYPE_CCX +#if (HCF_SLEEP) & HCF_DDS +#define HCF_ACT_SLEEP 0x1C // DDS Sleep request +//#define HCF_ACT_WAKEUP 0x1D // DDS Wakeup request +#endif // HCF_DDS + +/* HCF_ACT_MAX // xxxx: start value for UIL-range, NOT to be passed to HCF + * Too bad, there was originally no spare room created to use + * HCF_ACT_MAX as an equivalent of HCF_ERR_MAX. Since creating + * this room in retrospect would create a backward incompatibility + * we will just have to live with the haphazard sequence of + * UIL- and HCF specific codes. Theoretically this could be + * corrected when and if there will ever be an overall + * incompatibility introduced for another reason + */ + +/*============================================================= HERMES RECORDS ============================*/ +#define CFG_RID_FW_MIN 0xFA00 //lowest value representing a Hermes-II based RID +// #define CFG_PDA_BEGIN 0xFA // +// #define CFG_PDA_END 0xFA // +// #define CFG_PDA_NIC_TOP_LVL_ASSEMBLY_NUMBER 0xFA // +// #define CFG_PDA_PCB_TRACER_NUMBER 0xFA // +// #define CFG_PDA_RMM_TRACER_NUMBER 0xFA // +// #define CFG_PDA_RMM_COMP_ID 0xFA // +// #define CFG_PDA_ 0xFA // + +/*============================================================= CONFIGURATION RECORDS =====================*/ +/*============================================================= mask 0xFCxx =====================*/ +#define CFG_RID_CFG_MIN 0xFC00 //lowest value representing a Hermes configuration RID + +// NETWORK PARAMETERS, STATIC CONFIGURATION ENTITIES +//FC05, FC0B, FC0C, FC0D: SEE W2DN149 + +#define CFG_CNF_PORT_TYPE 0xFC00 //[STA] Connection control characteristics +#define CFG_CNF_OWN_MAC_ADDR 0xFC01 //[STA] MAC Address of this node +// 0xFC02 see DYNAMIC CONFIGURATION ENTITIES +#define CFG_CNF_OWN_CHANNEL 0xFC03 //Communication channel for BSS creation +#define CFG_CNF_OWN_SSID 0xFC04 //IBSS creation (STA) or ESS (AP) Service Set Ident +#define CFG_CNF_OWN_ATIM_WINDOW 0xFC05 //[STA] ATIM Window time for IBSS creation +#define CFG_CNF_SYSTEM_SCALE 0xFC06 //System Scale that specifies the AP density +#define CFG_CNF_MAX_DATA_LEN 0xFC07 //Maximum length of MAC Frame Body data +#define CFG_CNF_PM_ENABLED 0xFC09 //[STA] Switch for ESS Power Management (PM) +#define CFG_CNF_MCAST_RX 0xFC0B //[STA] Switch for ESS PM Multicast reception On/Off +#define CFG_CNF_MAX_SLEEP_DURATION 0xFC0C //[STA] Maximum sleep time for ESS PM +#define CFG_CNF_HOLDOVER_DURATION 0xFC0D //[STA] Holdover time for ESS PM +#define CFG_CNF_OWN_NAME 0xFC0E //Identification text for diagnostic purposes + +#define CFG_CNF_OWN_DTIM_PERIOD 0xFC10 //[AP] Beacon intervals between successive DTIMs +#define CFG_CNF_WDS_ADDR1 0xFC11 //[AP] Port 1 MAC Adrs of corresponding WDS Link node +#define CFG_CNF_WDS_ADDR2 0xFC12 //[AP] Port 2 MAC Adrs of corresponding WDS Link node +#define CFG_CNF_WDS_ADDR3 0xFC13 //[AP] Port 3 MAC Adrs of corresponding WDS Link node +#define CFG_CNF_WDS_ADDR4 0xFC14 //[AP] Port 4 MAC Adrs of corresponding WDS Link node +#define CFG_CNF_WDS_ADDR5 0xFC15 //[AP] Port 5 MAC Adrs of corresponding WDS Link node +#define CFG_CNF_WDS_ADDR6 0xFC16 //[AP] Port 6 MAC Adrs of corresponding WDS Link node +#define CFG_CNF_PM_MCAST_BUF 0xFC17 //[AP] Switch for PM buffereing of Multicast Messages +#define CFG_CNF_MCAST_PM_BUF CFG_CNF_PM_MCAST_BUF //name does not match H-II spec +#define CFG_CNF_REJECT_ANY 0xFC18 //[AP] Switch for PM buffereing of Multicast Messages + +#define CFG_CNF_ENCRYPTION 0xFC20 //select en/de-cryption of Tx/Rx messages +#define CFG_CNF_AUTHENTICATION 0xFC21 //[STA] selects Authentication algorithm +#define CFG_CNF_EXCL_UNENCRYPTED 0xFC22 //[AP] Switch for 'clear-text' rx message acceptance +#define CFG_CNF_MCAST_RATE 0xFC23 //Transmit Data rate for Multicast frames +#define CFG_CNF_INTRA_BSS_RELAY 0xFC24 //[AP] Switch for IntraBBS relay +#define CFG_CNF_MICRO_WAVE 0xFC25 //MicroWave (Robustness) +#define CFG_CNF_LOAD_BALANCING 0xFC26 //Load Balancing (Boolean, 0=OFF, 1=ON, default=1) +#define CFG_CNF_MEDIUM_DISTRIBUTION 0xFC27 //Medium Distribution (Boolean, 0=OFF, 1=ON, default=1) +#define CFG_CNF_RX_ALL_GROUP_ADDR 0xFC28 //[STA] Group Address Filter +#define CFG_CNF_COUNTRY_INFO 0xFC29 //Country Info +#if (HCF_TYPE) & HCF_TYPE_WARP +#define CFG_CNF_TX_POW_LVL 0xFC2A //TxPower Level +#define CFG_CNF_CONNECTION_CNTL 0xFC30 //[STA] Connection Control +#define CFG_CNF_OWN_BEACON_INTERVAL 0xFC31 //[AP] +#define CFG_CNF_SHORT_RETRY_LIMIT 0xFC32 // +#define CFG_CNF_LONG_RETRY_LIMIT 0xFC33 // +#define CFG_CNF_TX_EVENT_MODE 0xFC34 // +#define CFG_CNF_WIFI_COMPATIBLE 0xFC35 //[STA] Wifi compatible +#endif // HCF_TYPE_WARP +#if (HCF_TYPE) & HCF_TYPE_BEAGLE_HII5 +#define CFG_VOICE_RETRY_LIMIT 0xFC36 /* Voice frame retry limit. Range: 1-15, default: 4 */ +#define CFG_VOICE_CONTENTION_WINDOW 0xFC37 /* Contention window for voice frames. */ +#endif // BEAGLE_HII5 + +// NETWORK PARAMETERS, DYNAMIC CONFIGURATION ENTITIES +#define CFG_DESIRED_SSID 0xFC02 //[STA] Service Set identification for connection and scan + +#define CFG_GROUP_ADDR 0xFC80 //[STA] Multicast MAC Addresses for Rx-message +#define CFG_CREATE_IBSS 0xFC81 //[STA] Switch for IBSS creation On/Off +#define CFG_RTS_THRH 0xFC83 //Frame length used for RTS/CTS handshake +#define CFG_TX_RATE_CNTL 0xFC84 //[STA] Data rate control for message transmission +#define CFG_PROMISCUOUS_MODE 0xFC85 //[STA] Switch for Promiscuous mode reception On/Off +#define CFG_WOL 0xFC86 //[STA] Switch for Wake-On-LAN mode +#define CFG_WOL_PATTERNS 0xFC87 //[STA] Patterns for Wake-On-LAN +#define CFG_SUPPORTED_RATE_SET_CNTL 0xFC88 // +#define CFG_BASIC_RATE_SET_CNTL 0xFC89 // + +#define CFG_SOFTWARE_ACK_MODE 0xFC90 // +#define CFG_RTS_THRH0 0xFC97 //[AP] Port 0 frame length for RTS/CTS handshake +#define CFG_RTS_THRH1 0xFC98 //[AP] Port 1 frame length for RTS/CTS handshake +#define CFG_RTS_THRH2 0xFC99 //[AP] Port 2 frame length for RTS/CTS handshake +#define CFG_RTS_THRH3 0xFC9A //[AP] Port 3 frame length for RTS/CTS handshake +#define CFG_RTS_THRH4 0xFC9B //[AP] Port 4 frame length for RTS/CTS handshake +#define CFG_RTS_THRH5 0xFC9C //[AP] Port 5 frame length for RTS/CTS handshake +#define CFG_RTS_THRH6 0xFC9D //[AP] Port 6 frame length for RTS/CTS handshake + +#define CFG_TX_RATE_CNTL0 0xFC9E //[AP] Port 0 data rate control for transmission +#define CFG_TX_RATE_CNTL1 0xFC9F //[AP] Port 1 data rate control for transmission +#define CFG_TX_RATE_CNTL2 0xFCA0 //[AP] Port 2 data rate control for transmission +#define CFG_TX_RATE_CNTL3 0xFCA1 //[AP] Port 3 data rate control for transmission +#define CFG_TX_RATE_CNTL4 0xFCA2 //[AP] Port 4 data rate control for transmission +#define CFG_TX_RATE_CNTL5 0xFCA3 //[AP] Port 5 data rate control for transmission +#define CFG_TX_RATE_CNTL6 0xFCA4 //[AP] Port 6 data rate control for transmission + +#define CFG_DEFAULT_KEYS 0xFCB0 //defines set of encryption keys +#define CFG_TX_KEY_ID 0xFCB1 //select key for encryption of Tx messages +#define CFG_SCAN_SSID 0xFCB2 //Scan SSID +#define CFG_ADD_TKIP_DEFAULT_KEY 0xFCB4 //set KeyID and TxKey indication +#define KEY_ID 0x0003 //KeyID mask for tkip_key_id_info field +#define TX_KEY 0x8000 //Default Tx Key flag of tkip_key_id_info field +#define CFG_SET_WPA_AUTH_KEY_MGMT_SUITE 0xFCB5 //Authenticated Key Management Suite +#define CFG_REMOVE_TKIP_DEFAULT_KEY 0xFCB6 //invalidate KeyID and TxKey indication +#define CFG_ADD_TKIP_MAPPED_KEY 0xFCB7 //set MAC address pairwise station +#define CFG_REMOVE_TKIP_MAPPED_KEY 0xFCB8 //invalidate MAC address pairwise station +#define CFG_SET_WPA_CAPABILITIES_INFO 0xFCB9 //WPA Capabilities +#define CFG_CACHED_PMK_ADDR 0xFCBA //set MAC address of pre-authenticated AP +#define CFG_REMOVE_CACHED_PMK_ADDR 0xFCBB //invalidate MAC address of pre-authenticated AP +#define CFG_FCBC 0xFCBC //FW codes ahead of available documentation, so ??????? +#define CFG_FCBD 0xFCBD //FW codes ahead of available documentation, so ??????? +#define CFG_FCBE 0xFCBE //FW codes ahead of available documentation, so ??????? +#define CFG_FCBF 0xFCBF //FW codes ahead of available documentation, so ??????? + +#define CFG_HANDOVER_ADDR 0xFCC0 //[AP] Station MAC Adrress re-associated with other AP +#define CFG_SCAN_CHANNEL 0xFCC2 //Channel set for host requested scan +//;?#define CFG_SCAN_CHANNEL_MASK 0xFCC2 // contains +#define CFG_DISASSOCIATE_ADDR 0xFCC4 //[AP] Station MAC Adrress to be disassociated +#define CFG_PROBE_DATA_RATE 0xFCC5 //WARP connection control +#define CFG_FRAME_BURST_LIMIT 0xFCC6 // +#define CFG_COEXISTENSE_BEHAVIOUR 0xFCC7 //[AP] +#define CFG_DEAUTHENTICATE_ADDR 0xFCC8 //MAC address of Station to be deauthenticated + +// BEHAVIOR PARAMETERS +#define CFG_TICK_TIME 0xFCE0 //Auxiliary Timer tick interval +#define CFG_DDS_TICK_TIME 0xFCE1 //Disconnected DeepSleep Timer tick interval +//#define CFG_CNF_COUNTRY 0xFCFE apparently not needed ;? +#define CFG_RID_CFG_MAX 0xFCFF //highest value representing an Configuration RID + + +/*============================================================= INFORMATION RECORDS =====================*/ +/*============================================================= mask 0xFDxx =====================*/ +// NIC INFORMATION +#define CFG_RID_INF_MIN 0xFD00 //lowest value representing an Information RID +#define CFG_MAX_LOAD_TIME 0xFD00 //[INT] Maximum response time of the Download command. +#define CFG_DL_BUF 0xFD01 //[INT] Download buffer location and size. +#define CFG_PRI_IDENTITY 0xFD02 //[PRI] Primary Functions firmware identification. +#define CFG_PRI_SUP_RANGE 0xFD03 //[PRI] Primary Functions I/F Supplier compatibility range. +#define CFG_NIC_HSI_SUP_RANGE 0xFD09 //H/W - S/W I/F supplier range +#define CFG_NIC_SERIAL_NUMBER 0xFD0A //[PRI] Network Interface Card serial number. +#define CFG_NIC_IDENTITY 0xFD0B //[PRI] Network Interface Card identification. +#define CFG_NIC_MFI_SUP_RANGE 0xFD0C //[PRI] Modem I/F Supplier compatibility range. +#define CFG_NIC_CFI_SUP_RANGE 0xFD0D //[PRI] Controller I/F Supplier compatibility range. +#define CFG_CHANNEL_LIST 0xFD10 //Allowed communication channels. +#define CFG_NIC_TEMP_TYPE 0xFD12 //Hardware temperature range code. +#define CFG_CIS 0xFD13 //PC Card Standard Card Information Structure +#define CFG_NIC_PROFILE 0xFD14 //Card Profile +#define CFG_FW_IDENTITY 0xFD20 //firmware identification. +#define CFG_FW_SUP_RANGE 0xFD21 //firmware Supplier compatibility range. +#define CFG_MFI_ACT_RANGES_STA 0xFD22 //[STA] Modem I/F Actor compatibility ranges. +#define CFG_CFI_ACT_RANGES_STA 0xFD23 //[STA] Controller I/F Actor compatibility ranges. +#define CFG_NIC_BUS_TYPE 0xFD24 //Card Bustype +#define CFG_NIC_BUS_TYPE_PCCARD_CF 0x0000 //16 bit PC Card or Compact Flash +#define CFG_NIC_BUS_TYPE_USB 0x0001 //USB +#define CFG_NIC_BUS_TYPE_CARDBUS 0x0002 //CardBus +#define CFG_NIC_BUS_TYPE_PCI 0x0003 //(mini)PCI +#define CFG_DOMAIN_CODE 0xFD25 + +// MAC INFORMATION +#define CFG_PORT_STAT 0xFD40 //Actual MAC Port connection control status +#define CFG_CUR_SSID 0xFD41 //[STA] Identification of the actually connected SS +#define CFG_CUR_BSSID 0xFD42 //[STA] Identification of the actually connected BSS +#define CFG_COMMS_QUALITY 0xFD43 //[STA] Quality of the Basic Service Set connection +#define CFG_CUR_TX_RATE 0xFD44 //[STA] Actual transmit data rate +#define CFG_CUR_BEACON_INTERVAL 0xFD45 //Beacon transmit interval time for BSS creation +#define CFG_CUR_SCALE_THRH 0xFD46 //Actual System Scale thresholds settings +#define CFG_PROTOCOL_RSP_TIME 0xFD47 //Max time to await a response to a request message +#define CFG_CUR_SHORT_RETRY_LIMIT 0xFD48 //Max number of transmit attempts for short frames +#define CFG_CUR_LONG_RETRY_LIMIT 0xFD49 //Max number of transmit attempts for long frames +#define CFG_MAX_TX_LIFETIME 0xFD4A //Max transmit frame handling duration +#define CFG_MAX_RX_LIFETIME 0xFD4B //Max received frame handling duration +#define CFG_CF_POLLABLE 0xFD4C //[STA] Contention Free pollable capability indication +#define CFG_AUTHENTICATION_ALGORITHMS 0xFD4D //Available Authentication Algorithms indication +#define CFG_PRIVACY_OPT_IMPLEMENTED 0xFD4F //WEP Option availability indication + +#define CFG_CUR_REMOTE_RATES 0xFD50 //[STA] CurrentRemoteRates +#define CFG_CUR_USED_RATES 0xFD51 //[STA] CurrentUsedRates +#define CFG_CUR_SYSTEM_SCALE 0xFD52 //[STA] CurrentSystemScale + +#define CFG_CUR_TX_RATE1 0xFD80 //[AP] Actual Port 1 transmit data rate +#define CFG_CUR_TX_RATE2 0xFD81 //[AP] Actual Port 2 transmit data rate +#define CFG_CUR_TX_RATE3 0xFD82 //[AP] Actual Port 3 transmit data rate +#define CFG_CUR_TX_RATE4 0xFD83 //[AP] Actual Port 4 transmit data rate +#define CFG_CUR_TX_RATE5 0xFD84 //[AP] Actual Port 5 transmit data rate +#define CFG_CUR_TX_RATE6 0xFD85 //[AP] Actual Port 6 transmit data rate +#define CFG_NIC_MAC_ADDR 0xFD86 //Unique local node MAC Address +#define CFG_PCF_INFO 0xFD87 //[AP] Point Coordination Function capability info +//*RESERVED* #define CFG_HIGHEST_BASIC_RATE 0xFD88 // +#define CFG_CUR_COUNTRY_INFO 0xFD89 // +#define CFG_CUR_SSN_INFO_ELEMENT 0xFD8A // +#define CFG_CUR_TKIP_IV_INFO 0xFD8B // +#define CFG_CUR_ASSOC_REQ_INFO 0xFD8C // +#define CFG_CUR_ASSOC_RESP_INFO 0xFD8D // +#define CFG_CUR_LOAD 0xFD8E //[AP] current load on AP's channel + +#define CFG_SECURITY_CAPABILITIES 0xFD90 //Combined capabilities information + +// MODEM INFORMATION +#define CFG_PHY_TYPE 0xFDC0 //Physical layer type indication +#define CFG_CUR_CHANNEL 0xFDC1 //Actual frequency channel used for transmission +#define CFG_CUR_POWER_STATE 0xFDC2 //Actual power consumption status +#define CFG_CCA_MODE 0xFDC3 //Clear channel assessment mode indication +#define CFG_SUPPORTED_DATA_RATES 0xFDC6 //Data rates capability information + +#define CFG_RID_INF_MAX 0xFDFF //highest value representing an Information RID + +// ENGINEERING INFORMATION +#define CFG_RID_ENG_MIN 0xFFE0 //lowest value representing a Hermes engineering RID + + +/****************************** General define *************************************************************/ + + +//IFB field related +// IFB_CardStat +#define CARD_STAT_INCOMP_PRI 0x2000U // no compatible HSI / primary F/W +#define CARD_STAT_INCOMP_FW 0x1000U // no compatible station / tertiary F/W +#define CARD_STAT_DEFUNCT 0x0100U // HCF is in Defunct mode +// IFB_RxStat +#define RX_STAT_PRIO 0x00E0U //Priority subfield +#define RX_STAT_ERR 0x000FU //Error mask +#define RX_STAT_UNDECR 0x0002U //Non-decryptable encrypted message +#define RX_STAT_FCS_ERR 0x0001U //FCS error + +// SNAP header for E-II Encapsulation +#define ENC_NONE 0xFF +#define ENC_1042 0x00 +#define ENC_TUNNEL 0xF8 +/****************************** Xxxxxxxx *******************************************************************/ + + +#define HCF_SUCCESS 0x00 // OK +#define HCF_ERR_TIME_OUT 0x04 // Expected Hermes event did not occure in expected time +#define HCF_ERR_NO_NIC 0x05 /* card not found (usually yanked away during hcfio_in_string + * Also: card is either absent or disabled while it should be neither */ +#define HCF_ERR_LEN 0x08 /* buffer size insufficient + * - IFB_ConfigTable too small + * - hcf_get_info buffer has a size of 0 or 1 or less than needed + * to accomodate all data + * - hcf_put_info: CFG_DLNV_DATA exceeds intermediate + * buffer size */ +#define HCF_ERR_INCOMP_PRI 0x09 // primary functions are not compatible +#define HCF_ERR_INCOMP_FW 0x0A // station functions are compatible +#define HCF_ERR_MIC 0x0D // MIC check fails +#define HCF_ERR_SLEEP 0x0E // NIC in sleep mode +#define HCF_ERR_MAX 0x3F /* end of HCF range + *** ** *** ****** *** *************** */ +#define HCF_ERR_DEFUNCT 0x80 // BIT, reflecting that the HCF is in defunct mode (bits 0x7F reflect cause) +#define HCF_ERR_DEFUNCT_AUX 0x82 // Timeout on acknowledgement on en/disabling AUX registers +#define HCF_ERR_DEFUNCT_TIMER 0x83 // Timeout on timer calibration during initialization process +#define HCF_ERR_DEFUNCT_TIME_OUT 0x84 // Timeout on Busy bit drop during BAP setup +#define HCF_ERR_DEFUNCT_CMD_SEQ 0x86 // Hermes and HCF are out of sync in issuing/processing commands + +#define HCF_INT_PENDING 0x01 // return status of hcf_act( HCF_ACT_INT_OFF ) + +#define HCF_PORT_0 0x0000 // Station supports only single MAC Port +#define HCF_PORT_1 0x0100 // HCF_PORT_1 through HCF_PORT_6 are only supported by AP F/W +#define HCF_PORT_2 0x0200 +#define HCF_PORT_3 0x0300 +#define HCF_PORT_4 0x0400 +#define HCF_PORT_5 0x0500 +#define HCF_PORT_6 0x0600 + +#define HCF_CNTL_ENABLE 0x01 +#define HCF_CNTL_DISABLE 0x02 +#define HCF_CNTL_CONNECT 0x03 +#define HCF_CNTL_DISCONNECT 0x05 +#define HCF_CNTL_CONTINUE 0x07 + +#define USE_DMA 0x0001 +#define USE_16BIT 0x0002 +#define DMA_ENABLED 0x8000 //weak name, it really means: F/W enabled and DMA selected + +//#define HCF_DMA_FD_CNT (2*29) //size in bytes of one Tx/RxFS minus DA/SA +//;?the MSF ( H2PCI.C uses the next 2 mnemonics ) +#define HCF_DMA_RX_BUF1_SIZE (HFS_ADDR_DEST + 8) //extra bytes for LEN/SNAP if decapsulation +#define HCF_DMA_TX_BUF1_SIZE (HFS_ADDR_DEST + 2*6 + 8) //extra bytes for DA/SA/LEN/SNAP if encapsulation + +//HFS_TX_CNTL +/* Note that the HCF_.... System Constants influence the HFS_.... values below + * H-I H-I | H-II H-II H-II.5 + * WPA | WPA + * HFS_TX_CNTL_TX_OK 0002 0002 | 0002 0002 N/A <<<<<<<NULL pointer to matching CFG_RANGE_SPEC_STRCT substructure in actor-structure matching the supplier +* +*.NARRATIVE +* +* Parameters: +* actp address of the actor specification +* supp address of the supplier specification +* +* Description: mmd_check_comp is a support routine to check the compatibility between an actor and a +* supplier. mmd_check_comp is independent of the endianess of the actp and supp structures. This is +* achieved by checking the "bottom" or "role" fields of these structures. Since these fields are restricted +* to a limited range, comparing the contents to a value with a known endian-ess gives a clue to their actual +* endianess. +* +*.DIAGRAM +*1a: The role-field of the actor structure has a known non-zero, not "byte symmetric" value (namely +* COMP_ROLE_ACT or 0x0001), so if and only the contents of this field matches COMP_ROLE_ACT (in Native +* Endian format), the actor structure is Native Endian. +*2a: Since the role-field of the supplier structure is 0x0000, the test as used for the actor does not work +* for a supplier. A supplier has always exactly 1 variant,top,bottom record with (officially, but see the +* note below) each of these 3 values in the range 1 through 99, so one byte of the word value of variant, +* top and bottom words is 0x00 and the other byte is non-zero. Whether the lowest address byte or the +* highest address byte is non-zero depends on the Endianess of the LTV. If and only if the word value of +* bottom is less than 0x0100, the supplier is Native Endian. +* NOTE: the variant field of the supplier structure can not be used for the Endian Detection Algorithm, +* because a a zero-valued variant has been used as Controlled Deployment indication in the past. +* Note: An actor may have multiple sets of variant,top,bottom records, including dummy sets with variant, +* top and bottom fields with a zero-value. As a consequence the endianess of the actor can not be determined +* based on its variant,top,bottom values. +* +* Note: the L and T field of the structures are always in Native Endian format, so you can not draw +* conclusions concerning the Endianess of the structure based on these two fields. +* +*1b/2b +* The only purpose of the CFG_RANGE_SPEC_BYTE_STRCT is to give easy access to the non-zero byte of the word +* value of variant, top and bottom. The variables sup_endian and act_endian are used for the supplier and +* actor structure respectively. These variables must be 0 when the structure has LE format and 1 if the +* structure has BE format. This can be phrased as: +* the variable is false (i.e 0x0000) if either +* (the platform is LE and the LTV is the same as the platform) +* or +* (the platform is BE and the LTV differs from the platform). +* the variable is true (i.e 0x0001) if either +* (the platform is BE and the LTV is the same as the platform) +* or +* (the platform is LE and the LTV differs from the platform). +* +* Alternatively this can be phrased as: +* if the platform is LE +* if the LTV is LE (i.e the same as the platform), then the variable = 0 +* else (the LTV is BE (i.e. different from the platform) ), then the variable = 1 +* if the platform is BE +* if the LTV is BE (i.e the same as the platform), then the variable = 1 +* else (the LTV is LE (i.e. different from the platform) ), then the variable = 0 +* +* This is implemented as: +* #if HCF_BIG_ENDIAN == 0 //platform is LE +* sup/act_endian becomes reverse of structure-endianess as determined in 1a/1b +* #endif +*6: Each of the actor variant-bottom-top records is checked against the (single) supplier variant-bottom-top +* range till either an acceptable match is found or all actor records are tried. As explained above, due to +* the limited ranges of these values, checking a byte is acceptable and suitable. +*8: depending on whether a match was found or not (as reflected by the value of the control variable of the +* for loop), the NULL pointer or a pointer to the matching Number/Bottom/Top record of the Actor structure +* is returned. +* As an additional safety, checking the supplier length protects against invalid Supplier structures, which +* may be caused by failing hcf_get_info (in which case the len-field is zero). Note that the contraption +* "supp->len != sizeof(CFG_SUP_RANGE_STRCT)/sizeof(hcf_16) - 1" +* did turn out not to work for a compiler which padded the structure definition. +* +* Note: when consulting references like DesignNotes and Architecture specifications there is a confusing use +* of the notions number and variant. This resulted in an inconsistent use in the HCF nomenclature as well. +* This makes the logic hard to follow and one has to be very much aware of the context when walking through +* the code. +* NOTE: The Endian Detection Algorithm places limitations on future extensions of the fields, i.e. they should +* stay within the currently defined boundaries of 1 through 99 (although 1 through 255) would work as well +* and there should never be used a zero value for the bottom of a valid supplier. +* Note: relative to Asserts, the following can be observed: +* 1: Supplier variant 0x0000 has been used for Controlled Deployment +* 2: An actor may have one or more variant record specifications with a top of zero and a non-zero bottom +* to override the HCF default support of a particular variant by the MSF programmer via hcfcfg.h +* 3: An actor range can be specified as all zeros, e.g. as padding in the automatically generated firmware +* image files. +*.ENDDOC END DOCUMENTATION +*************************************************************************************************************/ +CFG_RANGE_SPEC_STRCT* +mmd_check_comp( CFG_RANGES_STRCT *actp, CFG_SUP_RANGE_STRCT *supp ) +{ + +CFG_RANGE_SPEC_BYTE_STRCT *actq = (CFG_RANGE_SPEC_BYTE_STRCT*)actp->var_rec; +CFG_RANGE_SPEC_BYTE_STRCT *supq = (CFG_RANGE_SPEC_BYTE_STRCT*)&(supp->variant); +hcf_16 i; +int act_endian; //actor endian flag +int sup_endian; //supplier endian flag + + act_endian = actp->role == COMP_ROLE_ACT; //true if native endian /* 1a */ + sup_endian = supp->bottom < 0x0100; //true if native endian /* 2a */ + +#if HCF_ASSERT + MMDASSERT( supp->len == 6, supp->len ) + MMDASSERT( actp->len >= 6 && actp->len%3 == 0, actp->len ) + + if ( act_endian ) { //native endian + MMDASSERT( actp->role == COMP_ROLE_ACT, actp->role ) + MMDASSERT( 1 <= actp->id && actp->id <= 99, actp->id ) + } else { //non-native endian + MMDASSERT( actp->role == CNV_END_SHORT(COMP_ROLE_ACT), actp->role ) + MMDASSERT( 1 <= CNV_END_SHORT(actp->id) && CNV_END_SHORT(actp->id) <= 99, actp->id ) + } + if ( sup_endian ) { //native endian + MMDASSERT( supp->role == COMP_ROLE_SUPL, supp->role ) + MMDASSERT( 1 <= supp->id && supp->id <= 99, supp->id ) + MMDASSERT( 1 <= supp->variant && supp->variant <= 99, supp->variant ) + MMDASSERT( 1 <= supp->bottom && supp->bottom <= 99, supp->bottom ) + MMDASSERT( 1 <= supp->top && supp->top <= 99, supp->top ) + MMDASSERT( supp->bottom <= supp->top, supp->bottom << 8 | supp->top ) + } else { //non-native endian + MMDASSERT( supp->role == CNV_END_SHORT(COMP_ROLE_SUPL), supp->role ) + MMDASSERT( 1 <= CNV_END_SHORT(supp->id) && CNV_END_SHORT(supp->id) <= 99, supp->id ) + MMDASSERT( 1 <= CNV_END_SHORT(supp->variant) && CNV_END_SHORT(supp->variant) <= 99, supp->variant ) + MMDASSERT( 1 <= CNV_END_SHORT(supp->bottom) && CNV_END_SHORT(supp->bottom) <=99, supp->bottom ) + MMDASSERT( 1 <= CNV_END_SHORT(supp->top) && CNV_END_SHORT(supp->top) <=99, supp->top ) + MMDASSERT( CNV_END_SHORT(supp->bottom) <= CNV_END_SHORT(supp->top), supp->bottom << 8 | supp->top ) + } +#endif // HCF_ASSERT + +#if HCF_BIG_ENDIAN == 0 + act_endian = !act_endian; /* 1b*/ + sup_endian = !sup_endian; /* 2b*/ +#endif // HCF_BIG_ENDIAN + + for ( i = actp->len ; i > 3; actq++, i -= 3 ) { /* 6 */ + MMDASSERT( actq->variant[act_endian] <= 99, i<<8 | actq->variant[act_endian] ) + MMDASSERT( actq->bottom[act_endian] <= 99 , i<<8 | actq->bottom[act_endian] ) + MMDASSERT( actq->top[act_endian] <= 99 , i<<8 | actq->top[act_endian] ) + MMDASSERT( actq->bottom[act_endian] <= actq->top[act_endian], i<<8 | actq->bottom[act_endian] ) + if ( actq->variant[act_endian] == supq->variant[sup_endian] && + actq->bottom[act_endian] <= supq->top[sup_endian] && + actq->top[act_endian] >= supq->bottom[sup_endian] + ) break; + } + if ( i <= 3 || supp->len != 6 /*sizeof(CFG_SUP_RANGE_STRCT)/sizeof(hcf_16) - 1 */ ) { + actq = NULL; /* 8 */ + } +#if HCF_ASSERT + if ( actq == NULL ) { + for ( i = 0; i <= supp->len; i += 2 ) { + MMDASSERT( DO_ASSERT, MERGE_2( ((hcf_16*)supp)[i], ((hcf_16*)supp)[i+1] ) ); + } + for ( i = 0; i <= actp->len; i += 2 ) { + MMDASSERT( DO_ASSERT, MERGE_2( ((hcf_16*)actp)[i], ((hcf_16*)actp)[i+1] ) ); + } + } +#endif // HCF_ASSERT + return (CFG_RANGE_SPEC_STRCT*)actq; +} // mmd_check_comp + diff --git a/drivers/staging/wlags49_h2/mmd.h b/drivers/staging/wlags49_h2/mmd.h new file mode 100644 index 0000000000000000000000000000000000000000..06890c1b30a4871ab8819463f383303a9c32ffd9 --- /dev/null +++ b/drivers/staging/wlags49_h2/mmd.h @@ -0,0 +1,78 @@ + +// vim:tw=110:ts=4: +#ifndef MMD_H +#define MMD_H 1 + +/************************************************************************************************************* +* +* FILE : mmd.h +* +* DATE : $Date: 2004/07/19 08:16:14 $ $Revision: 1.2 $ +* Original: 2004/05/17 07:33:14 Revision: 1.18 Tag: hcf7_t20040602_01 +* Original: 2004/05/11 06:22:59 Revision: 1.17 Tag: hcf7_t7_20040513_01 +* Original: 2004/04/15 09:24:42 Revision: 1.13 Tag: hcf7_t7_20040415_01 +* Original: 2004/04/08 15:18:17 Revision: 1.12 Tag: t7_20040413_01 +* Original: 2004/04/01 15:32:55 Revision: 1.10 Tag: t7_20040401_01 +* Original: 2004/03/04 16:47:50 Revision: 1.7 Tag: t20040310_01 +* Original: 2004/03/03 12:47:05 Revision: 1.6 Tag: t20040304_01 +* Original: 2004/02/25 14:14:39 Revision: 1.5 Tag: t20040302_03 +* Original: 2004/02/24 13:00:29 Revision: 1.4 Tag: t20040224_01 +* Original: 2004/01/30 09:59:33 Revision: 1.3 Tag: t20040219_01 +* +* AUTHOR : Nico Valster +* +* DESC : Definitions and Prototypes for HCF, MSF, UIL as well as USF sources +* +*************************************************************************************************************** +* +* +* SOFTWARE LICENSE +* +* This software is provided subject to the following terms and conditions, +* which you should read carefully before using the software. Using this +* software indicates your acceptance of these terms and conditions. If you do +* not agree with these terms and conditions, do not use the software. +* +* COPYRIGHT © 2001 - 2004 by Agere Systems Inc. All Rights Reserved +* All rights reserved. +* +* Redistribution and use in source or binary forms, with or without +* modifications, 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 as comments in the code as +* well as in the documentation and/or other materials provided with the +* distribution. +* +* . 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. +* +* . Neither the name of Agere Systems Inc. nor the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* Disclaimer +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY +* USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN +* RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. +* +* +**************************************************************************************************************/ +#ifndef HCF_H +#include "hcf.h" //just to get going with swig +#endif + +EXTERN_C CFG_RANGE_SPEC_STRCT* mmd_check_comp( CFG_RANGES_STRCT *actp, CFG_SUP_RANGE_STRCT *supp ); + +#endif // MMD_H diff --git a/drivers/staging/wlags49_h2/sta_h2.c b/drivers/staging/wlags49_h2/sta_h2.c new file mode 100644 index 0000000000000000000000000000000000000000..f9a38523724cf0718e7b8d3480a9a33b3e942834 --- /dev/null +++ b/drivers/staging/wlags49_h2/sta_h2.c @@ -0,0 +1,4480 @@ +/* + * File: sta_h24.236 + * + * Abstract: This file contains memory image 'fw_image'. + * + * Contents: Total size of the memory image: 69294 bytes. + * Total number of blocks: 4 blocks. + * Block 1 : load address 00000060, 390 bytes. + * Block 2 : load address 00000C16, 9496 bytes. + * Block 3 : load address 001E312E, 15786 bytes. + * Block 4 : load address 001F4000, 43622 bytes. + * + * Identity: component id: 31 (variant 3) version 2.36 + * + * Compatibility: + * supplying interface 4 (variant 2) : 2 - 5 + * acting on interface 1 (variant 4) : 6 - 7 + * acting on interface 1 (variant 5) : 6 - 7 + * acting on interface 1 (variant 6) : 6 - 7 + * acting on interface 2 (variant 2) : 1 - 2 + * + * Generated: by g:\fw\fupu3.exe version 4.26 + * + * Commandline: g:\fw\fupu3.exe /f=4 /n=fw_image /i=r3023600.hex + */ + + +#include "hcfcfg.h" // to get hcf_16 etc defined as well as + // possible settings which inluence mdd.h or dhf.h +#include "mdd.h" //to get COMP_ID_STA etc defined +#include "dhf.h" //used to be "fhfmem.h", to get memblock,plugrecord, + +static const hcf_8 fw_image_1_data[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x0D, 0x00, 0x00, + 0x3A, 0x0C, 0x00, 0x00, 0x3A, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x1B, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x86, 0x19, 0x86, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xEA, 0x00, 0x00, 0xFF, 0x07, 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, 0x10, 0x27, 0x10, 0x27, + 0x14, 0x00, 0xD0, 0x07, 0xD0, 0x07, 0x10, 0x27, 0x2F, 0x00, 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x10, 0x27, 0x05, 0x00, 0x00, 0x02, 0x00, 0x02, 0x13, 0x00, 0x0A, 0x00, + 0x07, 0x00, 0x03, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x09, 0x2B, 0x09, 0x2B, 0x09, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x14, 0x01, 0x00, 0x40, 0x00, 0x32, 0x00, 0x32, 0x00, + 0x0A, 0x00, 0x02, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +}; /* fw_image_1_data */ + +static const hcf_8 fw_image_2_data[] = { + 0x4B, 0xA3, 0x00, 0x0A, 0x10, 0x01, 0x68, 0xA4, 0xB0, 0x01, 0x84, 0x01, 0x30, 0x33, 0x31, 0x33, + 0x44, 0x44, 0x30, 0x33, 0x31, 0x33, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, 0x32, 0x33, 0x90, 0x00, + 0x78, 0x04, 0xAE, 0xE4, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x84, 0xF8, 0x99, 0xEE, + 0x8D, 0xF6, 0x0D, 0xFF, 0xBD, 0xD6, 0xB1, 0xDE, 0x54, 0x91, 0x50, 0x60, 0x03, 0x02, 0xA9, 0xCE, + 0x7D, 0x56, 0x19, 0xE7, 0x62, 0xB5, 0xE6, 0x4D, 0x9A, 0xEC, 0x45, 0x8F, 0x9D, 0x1F, 0x40, 0x89, + 0x87, 0xFA, 0x15, 0xEF, 0xEB, 0xB2, 0xC9, 0x8E, 0x0B, 0xFB, 0xEC, 0x41, 0x67, 0xB3, 0xFD, 0x5F, + 0xEA, 0x45, 0xBF, 0x23, 0xF7, 0x53, 0x96, 0xE4, 0x5B, 0x9B, 0xC2, 0x75, 0x1C, 0xE1, 0xAE, 0x3D, + 0x6A, 0x4C, 0x5A, 0x6C, 0x41, 0x7E, 0x02, 0xF5, 0x4F, 0x83, 0x5C, 0x68, 0xF4, 0x51, 0x34, 0xD1, + 0x08, 0xF9, 0x93, 0xE2, 0x73, 0xAB, 0x53, 0x62, 0x3F, 0x2A, 0x0C, 0x08, 0x52, 0x95, 0x65, 0x46, + 0x5E, 0x9D, 0x28, 0x30, 0xA1, 0x37, 0x0F, 0x0A, 0xB5, 0x2F, 0x09, 0x0E, 0x36, 0x24, 0x9B, 0x1B, + 0x3D, 0xDF, 0x26, 0xCD, 0x69, 0x4E, 0xCD, 0x7F, 0x9F, 0xEA, 0x1B, 0x12, 0x9E, 0x1D, 0x74, 0x58, + 0x2E, 0x34, 0x2D, 0x36, 0xB2, 0xDC, 0xEE, 0xB4, 0xFB, 0x5B, 0xF6, 0xA4, 0x4D, 0x76, 0x61, 0xB7, + 0xCE, 0x7D, 0x7B, 0x52, 0x3E, 0xDD, 0x71, 0x5E, 0x97, 0x13, 0xF5, 0xA6, 0x68, 0xB9, 0x00, 0x00, + 0x2C, 0xC1, 0x60, 0x40, 0x1F, 0xE3, 0xC8, 0x79, 0xED, 0xB6, 0xBE, 0xD4, 0x46, 0x8D, 0xD9, 0x67, + 0x4B, 0x72, 0xDE, 0x94, 0xD4, 0x98, 0xE8, 0xB0, 0x4A, 0x85, 0x6B, 0xBB, 0x2A, 0xC5, 0xE5, 0x4F, + 0x16, 0xED, 0xC5, 0x86, 0xD7, 0x9A, 0x55, 0x66, 0x94, 0x11, 0xCF, 0x8A, 0x10, 0xE9, 0x06, 0x04, + 0x81, 0xFE, 0xF0, 0xA0, 0x44, 0x78, 0xBA, 0x25, 0xE3, 0x4B, 0xF3, 0xA2, 0xFE, 0x5D, 0xC0, 0x80, + 0x8A, 0x05, 0xAD, 0x3F, 0xBC, 0x21, 0x48, 0x70, 0x04, 0xF1, 0xDF, 0x63, 0xC1, 0x77, 0x75, 0xAF, + 0x63, 0x42, 0x30, 0x20, 0x1A, 0xE5, 0x0E, 0xFD, 0x6D, 0xBF, 0x4C, 0x81, 0x14, 0x18, 0x35, 0x26, + 0x2F, 0xC3, 0xE1, 0xBE, 0xA2, 0x35, 0xCC, 0x88, 0x39, 0x2E, 0x57, 0x93, 0xF2, 0x55, 0x82, 0xFC, + 0x47, 0x7A, 0xAC, 0xC8, 0xE7, 0xBA, 0x2B, 0x32, 0x95, 0xE6, 0xA0, 0xC0, 0x98, 0x19, 0xD1, 0x9E, + 0x7F, 0xA3, 0x66, 0x44, 0x7E, 0x54, 0xAB, 0x3B, 0x83, 0x0B, 0xCA, 0x8C, 0x29, 0xC7, 0xD3, 0x6B, + 0x3C, 0x28, 0x79, 0xA7, 0xE2, 0xBC, 0x1D, 0x16, 0x76, 0xAD, 0x3B, 0xDB, 0x56, 0x64, 0x4E, 0x74, + 0x1E, 0x14, 0xDB, 0x92, 0x0A, 0x0C, 0x6C, 0x48, 0xE4, 0xB8, 0x5D, 0x9F, 0x6E, 0xBD, 0xEF, 0x43, + 0xA6, 0xC4, 0xA8, 0x39, 0xA4, 0x31, 0x37, 0xD3, 0x8B, 0xF2, 0x32, 0xD5, 0x43, 0x8B, 0x59, 0x6E, + 0xB7, 0xDA, 0x8C, 0x01, 0x64, 0xB1, 0xD2, 0x9C, 0xE0, 0x49, 0xB4, 0xD8, 0xFA, 0xAC, 0x07, 0xF3, + 0x25, 0xCF, 0xAF, 0xCA, 0x8E, 0xF4, 0xE9, 0x47, 0x18, 0x10, 0xD5, 0x6F, 0x88, 0xF0, 0x6F, 0x4A, + 0x72, 0x5C, 0x24, 0x38, 0xF1, 0x57, 0xC7, 0x73, 0x51, 0x97, 0x23, 0xCB, 0x7C, 0xA1, 0x9C, 0xE8, + 0x21, 0x3E, 0xDD, 0x96, 0xDC, 0x61, 0x86, 0x0D, 0x85, 0x0F, 0x90, 0xE0, 0x42, 0x7C, 0xC4, 0x71, + 0xAA, 0xCC, 0xD8, 0x90, 0x05, 0x06, 0x01, 0xF7, 0x12, 0x1C, 0xA3, 0xC2, 0x5F, 0x6A, 0xF9, 0xAE, + 0xD0, 0x69, 0x91, 0x17, 0x58, 0x99, 0x27, 0x3A, 0xB9, 0x27, 0x38, 0xD9, 0x13, 0xEB, 0xB3, 0x2B, + 0x33, 0x22, 0xBB, 0xD2, 0x70, 0xA9, 0x89, 0x07, 0xA7, 0x33, 0xB6, 0x2D, 0x22, 0x3C, 0x92, 0x15, + 0x20, 0xC9, 0x49, 0x87, 0xFF, 0xAA, 0x78, 0x50, 0x7A, 0xA5, 0x8F, 0x03, 0xF8, 0x59, 0x80, 0x09, + 0x17, 0x1A, 0xDA, 0x65, 0x31, 0xD7, 0xC6, 0x84, 0xB8, 0xD0, 0xC3, 0x82, 0xB0, 0x29, 0x77, 0x5A, + 0x11, 0x1E, 0xCB, 0x7B, 0xFC, 0xA8, 0xD6, 0x6D, 0x3A, 0x2C, 0x00, 0x30, 0x00, 0x31, 0x00, 0x33, + 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x38, 0x00, 0x3A, 0x00, 0x3B, + 0x00, 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, 0x3F, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x02, 0x14, + 0x05, 0x32, 0x0B, 0x37, 0x08, 0x50, 0x0B, 0x6E, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x3F, 0x00, + 0x0C, 0x00, 0x30, 0x00, 0x03, 0x00, 0x0F, 0x00, 0x3E, 0x00, 0x3C, 0x00, 0x02, 0x00, 0x04, 0x00, + 0x0A, 0x00, 0x0B, 0x00, 0x10, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x63, 0x00, 0x20, 0x00, 0x63, 0x00, 0x63, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x10, + 0xEE, 0x10, 0xA6, 0x10, 0xE8, 0x10, 0xAC, 0x10, 0xE2, 0x10, 0xB2, 0x10, 0xDC, 0x10, 0xB8, 0x10, + 0xD6, 0x10, 0xBE, 0x10, 0xD0, 0x10, 0xC4, 0x10, 0xCA, 0x10, 0x07, 0x01, 0x00, 0x00, 0x0A, 0x22, + 0x00, 0x04, 0x08, 0x01, 0x00, 0x00, 0x0A, 0x26, 0x00, 0x04, 0x09, 0x01, 0x00, 0x00, 0x0A, 0x2A, + 0x00, 0x04, 0x0A, 0x01, 0x00, 0x00, 0x0A, 0x2E, 0x00, 0x04, 0x0B, 0x01, 0x00, 0x00, 0x10, 0x24, + 0x04, 0x04, 0x0C, 0x01, 0x00, 0x00, 0x10, 0x28, 0x04, 0x04, 0x0D, 0x01, 0x00, 0x00, 0x10, 0x2C, + 0x04, 0x04, 0x0E, 0x01, 0x00, 0x00, 0x10, 0x30, 0x04, 0x04, 0x0F, 0x01, 0x00, 0x00, 0x16, 0x34, + 0x08, 0x04, 0x10, 0x01, 0x00, 0x00, 0x16, 0x38, 0x08, 0x04, 0x11, 0x01, 0x00, 0x00, 0x16, 0x3C, + 0x08, 0x04, 0x12, 0x01, 0x00, 0x00, 0x16, 0x40, 0x08, 0x04, 0x13, 0x01, 0x00, 0x00, 0x17, 0x64, + 0x0C, 0x0B, 0x14, 0x01, 0x00, 0x00, 0x17, 0x68, 0x0C, 0x0B, 0x15, 0x01, 0x00, 0x00, 0x17, 0x6C, + 0x0C, 0x0B, 0x16, 0x01, 0x00, 0x00, 0x17, 0x70, 0x0C, 0x0B, 0x17, 0x01, 0x00, 0x00, 0x17, 0x74, + 0x0C, 0x0B, 0x18, 0x01, 0x00, 0x00, 0x17, 0x78, 0x0C, 0x0B, 0x19, 0x01, 0x00, 0x00, 0x17, 0x7C, + 0x0C, 0x0B, 0x1A, 0x01, 0x00, 0x00, 0x17, 0x80, 0x0C, 0x0B, 0x1B, 0x01, 0x00, 0x00, 0x17, 0x84, + 0x0C, 0x0B, 0x1C, 0x01, 0x00, 0x00, 0x17, 0x88, 0x0C, 0x0B, 0x1D, 0x01, 0x00, 0x00, 0x17, 0x8C, + 0x0C, 0x0B, 0x1E, 0x01, 0x00, 0x00, 0x1D, 0x95, 0x17, 0x04, 0x1F, 0x01, 0x00, 0x00, 0x1D, 0x99, + 0x17, 0x04, 0x20, 0x01, 0x00, 0x00, 0x1D, 0x9D, 0x17, 0x04, 0x21, 0x01, 0x00, 0x00, 0x1D, 0xA1, + 0x17, 0x04, 0x22, 0x01, 0x00, 0x00, 0x0E, 0xA5, 0x00, 0x00, 0x10, 0x11, 0x30, 0x11, 0x50, 0x11, + 0x70, 0x11, 0xC8, 0x11, 0x18, 0x11, 0x38, 0x11, 0x58, 0x11, 0x78, 0x11, 0xD0, 0x11, 0x20, 0x11, + 0x40, 0x11, 0x60, 0x11, 0x80, 0x11, 0xD8, 0x11, 0x28, 0x11, 0x48, 0x11, 0x68, 0x11, 0x88, 0x11, + 0xE0, 0x11, 0x90, 0x11, 0x98, 0x11, 0xA0, 0x11, 0xA8, 0x11, 0xB0, 0x11, 0xB8, 0x11, 0xC0, 0x11, + 0xE8, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x36, 0x25, 0x4F, 0x25, 0x72, 0x25, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xAC, 0x25, + 0x02, 0x2B, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xF3, 0x2D, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, + 0xE1, 0x24, 0xE1, 0x24, 0x8B, 0x27, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, + 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, + 0xE1, 0x24, 0xE1, 0x24, 0xE5, 0x27, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, + 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, + 0xE1, 0x24, 0x59, 0x27, 0x73, 0x27, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, + 0xE1, 0x24, 0x47, 0x23, 0xCE, 0x25, 0xE1, 0x25, 0x91, 0x26, 0x95, 0x26, 0xE1, 0x24, 0xE1, 0x24, + 0x44, 0x27, 0x51, 0xEA, 0xFF, 0xE9, 0x00, 0x00, 0x48, 0xEA, 0x00, 0x00, 0x00, 0x00, 0xC9, 0xEA, + 0x65, 0x25, 0x89, 0x25, 0x00, 0x00, 0xF8, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x13, 0x2B, 0xE0, 0xFC, + 0x4C, 0x28, 0xC6, 0x2A, 0x5A, 0x00, 0x02, 0x00, 0xF9, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0x00, 0x01, + 0x02, 0x00, 0xF7, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0x50, 0x28, 0x06, 0x00, 0xF0, 0xFF, 0x4C, 0x28, + 0x29, 0x28, 0x00, 0x00, 0x00, 0x02, 0xF6, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0x6C, 0x00, 0x02, 0x00, + 0xF4, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0xAA, 0x01, 0x02, 0x00, 0xF5, 0xFF, 0x4C, 0x28, 0xCF, 0x2A, + 0x42, 0x28, 0x02, 0x00, 0xE0, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0xCE, 0x2D, 0x02, 0x00, 0xE1, 0xFF, + 0x4C, 0x28, 0x62, 0x28, 0xD0, 0x2D, 0x02, 0x00, 0xE2, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0xD2, 0x2D, + 0x02, 0x00, 0xE3, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0xCA, 0x2D, 0x02, 0x00, 0x03, 0xFC, 0x4C, 0x28, + 0x17, 0x2A, 0x16, 0x2D, 0x02, 0x00, 0x04, 0xFC, 0x4C, 0x28, 0x5C, 0x28, 0x58, 0x28, 0x22, 0x00, + 0x06, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0x40, 0x28, 0x02, 0x00, 0x07, 0xFC, 0x4C, 0x28, 0x62, 0x28, + 0x9C, 0x28, 0x02, 0x00, 0x0E, 0xFC, 0x4C, 0x28, 0x29, 0x2A, 0xA6, 0x28, 0x22, 0x00, 0xB1, 0xFC, + 0x4C, 0x28, 0x1D, 0x2B, 0xA2, 0x29, 0x02, 0x00, 0x20, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xCC, 0x28, + 0x02, 0x00, 0x25, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xD6, 0x28, 0x02, 0x00, 0x26, 0xFC, 0x4C, 0x28, + 0x62, 0x28, 0xD8, 0x28, 0x02, 0x00, 0x27, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xDA, 0x28, 0x02, 0x00, + 0xB2, 0xFC, 0x4C, 0x28, 0x5C, 0x28, 0xC6, 0x29, 0x22, 0x00, 0xC1, 0xFC, 0x4C, 0x28, 0x62, 0x28, + 0x5A, 0x2D, 0x20, 0x00, 0xB0, 0xFC, 0x1F, 0x28, 0x22, 0x2B, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xFC, + 0x1F, 0x28, 0xE7, 0x2A, 0x00, 0x00, 0x08, 0x00, 0xC8, 0xFC, 0x1F, 0x28, 0xE2, 0x2A, 0x00, 0x00, + 0x08, 0x00, 0xB4, 0xFC, 0x1F, 0x28, 0x60, 0x2B, 0x00, 0x00, 0x00, 0x00, 0xB6, 0xFC, 0x1F, 0x28, + 0x11, 0x2C, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xFC, 0x1F, 0x28, 0x3B, 0x2C, 0x00, 0x00, 0x00, 0x00, + 0xB8, 0xFC, 0x1F, 0x28, 0x98, 0x2C, 0x00, 0x00, 0x00, 0x00, 0xB5, 0xFC, 0x4C, 0x28, 0x62, 0x28, + 0xC6, 0x2D, 0x02, 0x00, 0xB9, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xC8, 0x2D, 0x02, 0x00, 0x90, 0xFD, + 0x4C, 0x28, 0x29, 0x28, 0xCC, 0x2D, 0x02, 0x00, 0x23, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xD2, 0x28, + 0x02, 0x00, 0x29, 0xFC, 0x44, 0x29, 0xF1, 0x28, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xFC, 0x4C, 0x28, + 0x62, 0x28, 0x0E, 0x2D, 0x02, 0x00, 0x32, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xA0, 0x01, 0x02, 0x00, + 0x33, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xA2, 0x01, 0x02, 0x00, 0x00, 0xFC, 0x4C, 0x28, 0x62, 0x28, + 0x56, 0x28, 0x02, 0x00, 0x01, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0x50, 0x28, 0x06, 0x00, 0x02, 0xFC, + 0x4C, 0x28, 0xDC, 0x28, 0xA4, 0x29, 0x22, 0x00, 0x05, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0x46, 0x28, + 0x02, 0x00, 0x08, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0x4A, 0x28, 0x06, 0x00, 0x09, 0xFC, 0x4C, 0x28, + 0x62, 0x28, 0x9E, 0x28, 0x02, 0x00, 0x0B, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xA0, 0x28, 0x02, 0x00, + 0x0C, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xA2, 0x28, 0x02, 0x00, 0x0D, 0xFC, 0x4C, 0x28, 0x62, 0x28, + 0xA4, 0x28, 0x02, 0x00, 0x21, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xCE, 0x28, 0x02, 0x00, 0x80, 0xFC, + 0xB8, 0x28, 0xC8, 0x28, 0xE2, 0x28, 0xC0, 0x00, 0x81, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xA8, 0x01, + 0x02, 0x00, 0x83, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xAC, 0x01, 0x02, 0x00, 0x85, 0xFC, 0x4C, 0x28, + 0x49, 0x2A, 0xA6, 0x01, 0x02, 0x00, 0x86, 0xFC, 0x4C, 0x28, 0x5B, 0x2A, 0xB2, 0x01, 0x02, 0x00, + 0x28, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xDC, 0x28, 0x02, 0x00, 0x87, 0xFC, 0x4C, 0x28, 0x62, 0x28, + 0xEC, 0x29, 0x22, 0x03, 0x84, 0xFC, 0x4C, 0x28, 0x70, 0x2A, 0xB0, 0x01, 0x02, 0x00, 0x2B, 0xFC, + 0x4C, 0x28, 0x62, 0x28, 0x14, 0x31, 0x02, 0x00, 0xF8, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0x0E, 0x31, + 0x02, 0x00, 0xF3, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0x16, 0x31, 0x02, 0x00, 0x20, 0xFD, 0x7D, 0x28, + 0x29, 0x28, 0x23, 0x34, 0x08, 0x00, 0x21, 0xFD, 0x7D, 0x28, 0x29, 0x28, 0x27, 0x34, 0x0A, 0x00, + 0x22, 0xFD, 0x7D, 0x28, 0x29, 0x28, 0x2C, 0x34, 0x16, 0x00, 0x23, 0xFD, 0x7D, 0x28, 0x29, 0x28, + 0x37, 0x34, 0x0A, 0x00, 0x10, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0x74, 0x01, 0x02, 0x00, 0x45, 0xFD, + 0x4C, 0x28, 0x29, 0x28, 0x00, 0x01, 0x02, 0x00, 0x47, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0x78, 0x01, + 0x02, 0x00, 0x48, 0xFD, 0x9A, 0x29, 0x29, 0x28, 0xA0, 0x01, 0x02, 0x00, 0x49, 0xFD, 0x9A, 0x29, + 0x29, 0x28, 0xA2, 0x01, 0x02, 0x00, 0x4A, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0x98, 0x01, 0x02, 0x00, + 0x4B, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0x9A, 0x01, 0x02, 0x00, 0x4D, 0xFD, 0x7D, 0x28, 0x29, 0x28, + 0x3C, 0x34, 0x04, 0x00, 0x4F, 0xFD, 0xAE, 0x29, 0x29, 0x28, 0x1A, 0x2D, 0x02, 0x00, 0xC0, 0xFD, + 0x7D, 0x28, 0x29, 0x28, 0x3E, 0x34, 0x02, 0x00, 0xC2, 0xFD, 0xA4, 0x29, 0x29, 0x28, 0x00, 0x00, + 0x02, 0x00, 0xC3, 0xFD, 0x7D, 0x28, 0x29, 0x28, 0x3F, 0x34, 0x02, 0x00, 0x40, 0xFD, 0x75, 0x28, + 0x29, 0x28, 0xB8, 0x01, 0x02, 0x00, 0x24, 0xFD, 0xCB, 0x29, 0x29, 0x28, 0x00, 0x00, 0x02, 0x00, + 0x91, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0x20, 0x24, 0x02, 0x00, 0x93, 0xFD, 0x4C, 0x28, 0x29, 0x28, + 0x26, 0x24, 0x02, 0x00, 0xC1, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0xFE, 0x00, 0x02, 0x00, 0xC6, 0xFD, + 0xAA, 0x28, 0x29, 0x28, 0x28, 0x2D, 0x0A, 0x00, 0x89, 0xFD, 0x5B, 0x29, 0x29, 0x28, 0x00, 0x00, + 0x00, 0x00, 0x8A, 0xFD, 0x9A, 0x28, 0x29, 0x28, 0xA0, 0x2D, 0x24, 0x00, 0x41, 0xFD, 0x4C, 0x28, + 0x29, 0x28, 0x7A, 0x2D, 0x22, 0x00, 0x42, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0x02, 0x01, 0x06, 0x00, + 0x43, 0xFD, 0xD8, 0x29, 0x29, 0x28, 0x00, 0x00, 0x06, 0x00, 0x44, 0xFD, 0xB8, 0x29, 0x29, 0x28, + 0xB4, 0x01, 0x02, 0x00, 0x46, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0xBA, 0x01, 0x0C, 0x00, 0x4C, 0xFD, + 0x4C, 0x28, 0x29, 0x28, 0xEA, 0x29, 0x02, 0x00, 0x50, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0xF4, 0x00, + 0x02, 0x00, 0x51, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0xF6, 0x00, 0x02, 0x00, 0x52, 0xFD, 0x4C, 0x28, + 0x29, 0x28, 0xC6, 0x01, 0x02, 0x00, 0x8F, 0xFD, 0xEB, 0x29, 0x29, 0x28, 0x00, 0x00, 0x08, 0x00, + 0x92, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0x54, 0x2D, 0x02, 0x00, 0x8C, 0xFD, 0x3F, 0x28, 0x29, 0x28, + 0x08, 0x2E, 0x56, 0x00, 0x8D, 0xFD, 0x3F, 0x28, 0x29, 0x28, 0x62, 0x2E, 0x14, 0x00, 0x00, 0xF1, + 0x46, 0x00, 0xE3, 0x27, 0x3A, 0x01, 0x01, 0xF1, 0x44, 0x07, 0xE1, 0x27, 0x3C, 0x01, 0x00, 0x03, + 0x2A, 0x68, 0x1E, 0x00, 0x76, 0x01, 0xFE, 0x00, 0xD6, 0x01, 0x02, 0x01, 0x3E, 0x01, 0xB8, 0x01, + 0x74, 0x27, 0x5A, 0x01, 0x20, 0x24, 0x20, 0x00, 0x00, 0x00, 0xBA, 0x1C, 0x00, 0x00, 0xBE, 0x1E, + 0x54, 0x01, 0x0B, 0x00, 0xBA, 0x00, 0xE4, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xAF, 0x37, 0xAF, 0x43, 0xB0, + 0x4C, 0xB0, 0x48, 0xAF, 0xDE, 0xAF, 0xB6, 0xAF, 0x1C, 0x33, 0x7F, 0x32, 0x1C, 0x33, 0xF3, 0x32, + 0x89, 0x32, 0x7D, 0x32, 0x3B, 0x33, 0x4C, 0x33, 0x4C, 0x33, 0x4C, 0x33, 0x55, 0x33, 0x70, 0x33, + 0xCD, 0x33, 0xE9, 0x33, 0xF4, 0x32, 0x07, 0x33, 0xDB, 0x32, 0x10, 0x00, 0x12, 0x00, 0x13, 0x00, + 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, + 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x14, 0x01, + 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0xF3, 0x02, + 0xAD, 0x03, 0x60, 0x04, 0x04, 0x05, 0x07, 0x06, 0x08, 0x07, 0x0A, 0x08, 0x16, 0x09, 0x44, 0x0A, + 0x04, 0x0B, 0x40, 0x0C, 0x80, 0x0D, 0x00, 0x0E, 0x84, 0x0F, 0x01, 0x10, 0x10, 0x11, 0x02, 0x14, + 0x40, 0x20, 0x32, 0x21, 0x32, 0x22, 0x04, 0x23, 0x01, 0x24, 0x0F, 0x25, 0x00, 0x26, 0x00, 0x27, + 0x00, 0x28, 0x00, 0x29, 0x00, 0x2A, 0x01, 0x2B, 0x06, 0x2C, 0x00, 0x38, 0x00, 0x39, 0xD6, 0x3A, + 0x00, 0x3B, 0x00, 0x3C, 0x14, 0x3D, 0x7F, 0x3E, 0x00, 0x3F, 0x68, 0x40, 0x75, 0x41, 0x07, 0x42, + 0x07, 0x43, 0x00, 0x45, 0x3B, 0x4A, 0x00, 0x4B, 0x00, 0x4C, 0x0F, 0x4D, 0x02, 0x75, 0x00, 0x76, + 0x80, 0x00, 0x08, 0x01, 0x09, 0x01, 0x09, 0x01, 0x0A, 0x01, 0x0A, 0x01, 0x0B, 0x01, 0x0B, 0x01, + 0x0C, 0x01, 0x0C, 0x01, 0x0D, 0x01, 0x0D, 0x01, 0x0E, 0x01, 0x0E, 0x01, 0x0F, 0x01, 0x0F, 0x01, + 0x10, 0x01, 0x10, 0x01, 0x11, 0x01, 0x11, 0x01, 0x12, 0x01, 0x12, 0x01, 0x13, 0x01, 0x13, 0x01, + 0x14, 0x01, 0x14, 0x01, 0x15, 0x01, 0x15, 0x01, 0x16, 0x01, 0x16, 0x01, 0x17, 0x01, 0x17, 0x01, + 0x18, 0x01, 0x18, 0x01, 0x19, 0x01, 0x19, 0x01, 0x4D, 0x01, 0x4D, 0x01, 0x4E, 0x01, 0x4E, 0x01, + 0x4F, 0x01, 0x4F, 0x01, 0x50, 0x01, 0x50, 0x01, 0x51, 0x01, 0x51, 0x01, 0x52, 0x01, 0x52, 0x01, + 0x53, 0x01, 0x53, 0x01, 0x54, 0x01, 0x54, 0x01, 0x65, 0x01, 0x65, 0x01, 0x66, 0x01, 0x66, 0x01, + 0x67, 0x01, 0x67, 0x01, 0x68, 0x01, 0x68, 0x01, 0x69, 0x01, 0x69, 0x01, 0x6A, 0x01, 0x6A, 0x01, + 0x6B, 0x01, 0x6B, 0x01, 0x6C, 0x01, 0x6C, 0x01, 0x6D, 0x01, 0x6D, 0x01, 0x6E, 0x01, 0x6E, 0x01, + 0x6F, 0x01, 0x6F, 0x01, 0x70, 0x01, 0x70, 0x01, 0x71, 0x01, 0x71, 0x01, 0x72, 0x01, 0x72, 0x01, + 0x73, 0x01, 0x73, 0x01, 0x74, 0x01, 0x74, 0x01, 0x75, 0x01, 0x75, 0x01, 0x76, 0x01, 0x76, 0x01, + 0x77, 0x01, 0x77, 0x01, 0x78, 0x01, 0x78, 0x01, 0x79, 0x01, 0x79, 0x01, 0x7A, 0x01, 0x7A, 0x01, + 0x7B, 0x01, 0x7B, 0x01, 0x7C, 0x01, 0x7C, 0x01, 0x7D, 0x01, 0x7D, 0x01, 0x7E, 0x01, 0x7E, 0x01, + 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, + 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, + 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, + 0x7F, 0x01, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, + 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x13, + 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, + 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, + 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, + 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, + 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x23, 0x46, 0x23, 0x46, + 0x23, 0x46, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, + 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1D, 0x47, 0x9A, 0x48, + 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, + 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0x33, 0x48, 0x78, 0x49, 0x78, 0x49, 0x79, 0x49, + 0x79, 0x49, 0x79, 0x49, 0x79, 0x49, 0x7A, 0x49, 0x7A, 0x49, 0x7A, 0x49, 0x7A, 0x49, 0x7B, 0x49, + 0x7B, 0x49, 0x7B, 0x49, 0x7C, 0x49, 0x32, 0x00, 0x46, 0x00, 0x5A, 0x00, 0x6E, 0x00, 0x82, 0x00, + 0x96, 0x00, 0xAA, 0x00, 0xBE, 0x00, 0xD2, 0x00, 0xE6, 0x00, 0xFA, 0x00, 0x0E, 0x01, 0x22, 0x01, + 0x52, 0x01, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x15, 0x00, 0x6E, 0x6F, 0x6E, 0x2D, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, + 0x64, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, + 0x00, 0x00, 0x48, 0x45, 0x52, 0x4D, 0x45, 0x53, 0x20, 0x32, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x15, 0x00, 0x6E, 0x6F, 0x6E, 0x2D, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, + 0x64, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, + 0x00, 0x00, 0x48, 0x45, 0x52, 0x4D, 0x45, 0x53, 0x20, 0x32, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x69, 0x72, 0x73, 0x74, 0x20, 0x57, 0x61, 0x76, 0x65, 0x4C, 0x41, 0x4E, 0x20, 0x49, 0x49, + 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x02, 0x01, 0x82, 0x84, 0x8B, 0x96, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x85, 0x00, 0x01, + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x20, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x53, 0x65, 0x74, 0x20, 0x49, 0x64, 0x65, 0x6E, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0xDD, 0x00, 0x50, 0xF2, 0x01, + 0x01, 0x00, 0x00, 0x50, 0xF2, 0x05, 0x02, 0x00, 0x00, 0x50, 0xF2, 0x02, 0x00, 0x50, 0xF2, 0x04, + 0x02, 0x00, 0x00, 0x50, 0xF2, 0x00, 0x00, 0x50, 0xF2, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x14, 0x00, 0x15, 0x00, 0x36, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x11, 0x00, 0x36, 0x00, 0x01, 0x00, 0x04, 0x00, 0x7A, 0x2D, 0x28, 0x2D, 0x0C, 0x2F, 0x10, 0x2F, + 0x14, 0x2F, 0xA0, 0x2D, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x29, 0x28, 0x2D, + 0xFF, 0xFF, 0x00, 0x00, 0x7A, 0x2D, 0x28, 0x2D, 0x0C, 0x2F, 0x10, 0x2F, 0x14, 0x2F, 0xA0, 0x2D, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x2D, 0x28, 0x2D, 0xFF, 0xFF, 0xE6, 0x2D, + 0x34, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00, 0x02, 0x06, 0x00, 0x00, 0x06, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +}; /* fw_image_2_data */ + +static const hcf_8 fw_image_3_data[] = { + 0x00, 0xE1, 0x30, 0x40, 0x02, 0x36, 0xA1, 0xFF, 0x83, 0xFF, 0x8D, 0xFF, 0x5C, 0x44, 0x5C, 0x43, + 0x5C, 0x42, 0x5C, 0x41, 0x5C, 0x40, 0xAC, 0xFF, 0xAD, 0xFF, 0xE7, 0xE1, 0xAD, 0x60, 0x08, 0x78, + 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x03, 0x02, 0x28, 0xE2, 0x40, 0xFF, 0xA1, 0xFF, + 0x84, 0xFF, 0xBB, 0x60, 0x18, 0x64, 0x40, 0x42, 0xB0, 0x60, 0x97, 0x64, 0x40, 0x40, 0xBD, 0xF3, + 0x80, 0xFB, 0x0F, 0x60, 0x9A, 0x63, 0xCA, 0xF3, 0xBD, 0xDB, 0x00, 0x60, 0x9A, 0x64, 0xBD, 0xDB, + 0x02, 0x64, 0xBD, 0xDB, 0x04, 0x64, 0xA3, 0xDB, 0x5C, 0x49, 0x0A, 0x64, 0x40, 0x4B, 0x5C, 0x5C, + 0x01, 0x60, 0x39, 0xE2, 0x04, 0x60, 0x00, 0x7A, 0x89, 0xFF, 0x03, 0x60, 0xFF, 0x73, 0x88, 0xFF, + 0xB0, 0x60, 0x97, 0x78, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x06, 0x02, 0x40, 0xFF, + 0x42, 0xFF, 0x43, 0xFF, 0x44, 0xFF, 0x45, 0xFF, 0xA1, 0xFF, 0x88, 0xFF, 0x85, 0xFF, 0x21, 0xE1, + 0x5C, 0x40, 0xBB, 0x60, 0x20, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, + 0x01, 0x02, 0xA1, 0xFF, 0x86, 0xFF, 0x88, 0xFF, 0x5C, 0x46, 0x5C, 0x49, 0x5C, 0x40, 0xE7, 0x60, + 0x58, 0x4F, 0x31, 0x78, 0xFF, 0xFF, 0xC7, 0x60, 0x58, 0x4F, 0xF6, 0x78, 0xFF, 0xFF, 0xCA, 0x60, + 0x58, 0x4F, 0x83, 0x78, 0xFF, 0xFF, 0xDD, 0x60, 0x58, 0x4F, 0x3D, 0x78, 0xFF, 0xFF, 0x1B, 0x60, + 0x58, 0x4F, 0x37, 0x78, 0xFF, 0xFF, 0xEC, 0x60, 0x58, 0x4F, 0x75, 0x78, 0xFF, 0xFF, 0xE0, 0x60, + 0x58, 0x4F, 0x1B, 0x78, 0xFF, 0xFF, 0xE4, 0x60, 0x58, 0x4F, 0xDC, 0x78, 0xFF, 0xFF, 0xF3, 0x60, + 0x58, 0x4F, 0xEB, 0x78, 0xFF, 0xFF, 0x13, 0xE1, 0xA3, 0xFF, 0xBF, 0x60, 0xE7, 0x78, 0xFF, 0xFF, + 0x03, 0xE1, 0xA3, 0xFF, 0xFE, 0xFC, 0xFF, 0xFC, 0x23, 0x60, 0xF4, 0x63, 0x17, 0xFD, 0xAE, 0xFF, + 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x26, 0x1A, 0x00, + 0x80, 0x3A, 0x15, 0x00, 0x81, 0xF1, 0x32, 0xF2, 0x33, 0xF2, 0xD0, 0x80, 0x82, 0xF1, 0x0F, 0x02, + 0xD0, 0x80, 0x34, 0xF2, 0x83, 0xF1, 0x0B, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x08, 0x02, 0xDF, 0x60, + 0x58, 0x4F, 0x28, 0x78, 0xFF, 0xFF, 0x20, 0x60, 0x58, 0x4F, 0xBF, 0x78, 0xFF, 0xFF, 0x19, 0x60, + 0xE8, 0x78, 0xFF, 0xFF, 0x00, 0xF4, 0xAA, 0x60, 0xAA, 0x65, 0x09, 0xF2, 0x5A, 0xD0, 0xD4, 0x80, + 0x03, 0x64, 0x12, 0x02, 0xD0, 0x80, 0x1D, 0x60, 0x60, 0x65, 0x0E, 0x02, 0x5A, 0xD2, 0xFF, 0xFF, + 0xD4, 0x80, 0x01, 0x60, 0x00, 0x65, 0x08, 0x02, 0x5A, 0xD2, 0xFF, 0xFF, 0xD4, 0x80, 0xFF, 0xFF, + 0x03, 0x02, 0x19, 0x60, 0xE8, 0x78, 0xFF, 0xFF, 0x01, 0x60, 0xD6, 0x65, 0xA5, 0xD1, 0x5A, 0xD1, + 0x44, 0x48, 0x5A, 0xD1, 0x44, 0x4A, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x44, 0x4C, 0xD8, 0x83, + 0x70, 0x61, 0x68, 0x65, 0xD7, 0x80, 0xFF, 0xFF, 0x07, 0x0E, 0x08, 0xF2, 0x08, 0x00, 0x68, 0x65, + 0xD7, 0x80, 0xFF, 0xFF, 0x01, 0x0E, 0x03, 0x00, 0x19, 0x60, 0xFE, 0x78, 0xFF, 0xFF, 0x58, 0x4F, + 0x79, 0x00, 0x9C, 0x80, 0x01, 0x65, 0x02, 0x02, 0x00, 0x65, 0x02, 0x00, 0xFF, 0x3B, 0xF7, 0x01, + 0x58, 0x4F, 0x70, 0x00, 0x9C, 0x80, 0x45, 0x42, 0xEA, 0x02, 0x58, 0x4F, 0x6B, 0x00, 0x9C, 0x80, + 0xFF, 0xFF, 0xE5, 0x02, 0x58, 0x4F, 0x66, 0x00, 0x9C, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0x00, 0x65, + 0x45, 0x42, 0xF8, 0x01, 0xFF, 0x3A, 0x29, 0x00, 0x60, 0x47, 0xFF, 0xB5, 0x28, 0x44, 0xFF, 0xB4, + 0x94, 0x80, 0xFF, 0xFF, 0xD4, 0x02, 0x60, 0x45, 0x28, 0x47, 0x2A, 0x5F, 0x40, 0x48, 0x2A, 0x47, + 0x2C, 0x5F, 0x40, 0x4A, 0x2C, 0x47, 0x65, 0x5F, 0x40, 0x4C, 0x10, 0x64, 0x40, 0x42, 0x28, 0x45, + 0x05, 0x00, 0x58, 0x4F, 0x47, 0x00, 0x94, 0x80, 0x28, 0x45, 0x26, 0x02, 0x58, 0x4F, 0x42, 0x00, + 0x94, 0x80, 0x2A, 0x45, 0x21, 0x02, 0x58, 0x4F, 0x3D, 0x00, 0x94, 0x80, 0xFF, 0xFF, 0x1C, 0x02, + 0x22, 0x44, 0x4C, 0x82, 0x2C, 0x45, 0x31, 0x03, 0xEC, 0x01, 0x10, 0x65, 0x45, 0x42, 0x28, 0x45, + 0x94, 0x80, 0x2A, 0x45, 0x21, 0x02, 0x58, 0x4F, 0x2D, 0x00, 0x94, 0x80, 0x2C, 0x45, 0x1C, 0x02, + 0x58, 0x4F, 0x28, 0x00, 0x94, 0x80, 0xFF, 0xFF, 0x17, 0x02, 0x22, 0x44, 0x4C, 0x82, 0x28, 0x45, + 0x1C, 0x03, 0x58, 0x4F, 0x1F, 0x00, 0xEC, 0x01, 0x40, 0x4B, 0x28, 0x47, 0x40, 0x48, 0x2A, 0x47, + 0x40, 0x4A, 0x2C, 0x47, 0x60, 0x45, 0x2A, 0x5E, 0x40, 0x4C, 0x2A, 0x44, 0x28, 0x5E, 0x40, 0x4A, + 0x28, 0x44, 0x65, 0x5E, 0x40, 0x48, 0x2B, 0x44, 0x68, 0x65, 0xD7, 0x80, 0xFF, 0xFF, 0x17, 0x0E, + 0x90, 0x01, 0x26, 0x46, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, 0xB9, 0xFF, 0x26, 0x46, 0xC5, 0x60, + 0x5B, 0x78, 0xFF, 0xFF, 0xC9, 0x81, 0xCB, 0x83, 0x07, 0x1C, 0x01, 0x1D, 0x08, 0x00, 0x00, 0xF4, + 0x01, 0xF2, 0xFF, 0xFF, 0xFF, 0xB4, 0xD8, 0x81, 0x5A, 0xD2, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, + 0xC5, 0x60, 0x58, 0x4F, 0x78, 0x78, 0xFF, 0xFF, 0x02, 0x60, 0x00, 0x63, 0x00, 0xF4, 0x84, 0x65, + 0x78, 0x61, 0xA5, 0xD0, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x64, 0x44, + 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, + 0xF0, 0x02, 0x1C, 0x60, 0xAC, 0x63, 0x29, 0x60, 0xEC, 0x64, 0x08, 0x65, 0xC4, 0x81, 0x61, 0x44, + 0xA3, 0xDB, 0x1C, 0x60, 0xAA, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x29, 0x60, 0xEC, 0x61, 0xA1, 0xD3, + 0xFF, 0xFF, 0x60, 0x43, 0x1C, 0x60, 0xB0, 0x61, 0xA1, 0xDD, 0x1C, 0x60, 0xB0, 0x61, 0xA1, 0xD3, + 0xFF, 0xFF, 0x60, 0x45, 0x1C, 0x60, 0xAA, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0xD4, 0x80, 0xFF, 0xFF, + 0x01, 0x03, 0x03, 0x00, 0x1A, 0x60, 0xD6, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xA8, 0x61, 0x01, 0x64, + 0xA1, 0xDB, 0x02, 0x60, 0x00, 0x61, 0x41, 0x4C, 0x03, 0x60, 0x00, 0x61, 0x41, 0x4A, 0x1C, 0x60, + 0xAC, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x40, 0x48, 0x1C, 0x60, 0xB2, 0x63, 0x28, 0x41, 0x06, 0x65, + 0xD5, 0x81, 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x01, 0xA4, 0x60, 0x41, 0xA3, 0xDB, + 0x2A, 0x43, 0x28, 0x45, 0xA5, 0xD1, 0xDA, 0x85, 0x64, 0x44, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, + 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0xF4, 0x02, 0x28, 0x41, 0x1C, 0x60, + 0xB2, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x45, 0x45, 0x8B, 0x1C, 0x60, 0xAE, 0x61, 0x2B, 0xD3, + 0xA1, 0xDB, 0x2C, 0x41, 0x28, 0x42, 0x4A, 0xD3, 0xFF, 0xFF, 0x60, 0x45, 0x45, 0x8C, 0x00, 0x7F, + 0x01, 0x7E, 0x40, 0x48, 0x1C, 0x60, 0xB2, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x45, 0x00, 0x64, + 0xD4, 0x80, 0xFF, 0xFF, 0x43, 0x03, 0x65, 0x44, 0xFF, 0xA4, 0xA1, 0xDB, 0x1C, 0x60, 0xAE, 0x61, + 0xA1, 0xD3, 0x28, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x2C, 0xD3, 0x2A, 0xD3, 0x60, 0x45, + 0xD4, 0x80, 0xFF, 0xFF, 0x01, 0x03, 0x14, 0x00, 0x28, 0x44, 0xE0, 0x84, 0xFF, 0xFF, 0x02, 0x24, + 0x01, 0x00, 0x08, 0x00, 0x2B, 0x44, 0x58, 0x8B, 0x1C, 0x60, 0xAE, 0x63, 0x2B, 0xD3, 0xA3, 0xDB, + 0x00, 0x7F, 0x01, 0x7E, 0x40, 0x48, 0x2A, 0x44, 0x58, 0x8A, 0x2C, 0x44, 0x58, 0x8C, 0xD2, 0x01, + 0x1C, 0x60, 0xA8, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x1C, 0x60, 0xAC, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, + 0x60, 0x45, 0xFA, 0xA4, 0x60, 0x41, 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0xC5, 0x81, 0x06, 0xA1, + 0x41, 0x48, 0x65, 0x41, 0xFC, 0xA1, 0xA1, 0xD3, 0x28, 0x41, 0x60, 0x40, 0x01, 0x26, 0x01, 0xA4, + 0x60, 0x45, 0xC5, 0x81, 0x61, 0x43, 0x1C, 0x60, 0xAC, 0x61, 0xA1, 0xDD, 0x1C, 0x60, 0xA8, 0x61, + 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x0D, 0x00, 0x1C, 0x60, 0xAA, 0x61, 0xA1, 0xD3, + 0xFF, 0xFF, 0x01, 0xA4, 0xA1, 0xDB, 0xFF, 0xFF, 0x1A, 0x60, 0x2C, 0x78, 0xFF, 0xFF, 0x19, 0x60, + 0xE8, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0xEC, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x01, 0x60, 0xBA, 0x61, + 0x1F, 0x60, 0x08, 0x63, 0xA1, 0xD3, 0x04, 0xA1, 0x20, 0x7F, 0xBD, 0xDB, 0x32, 0x7E, 0x21, 0x7F, + 0xBD, 0xDB, 0xA1, 0xD3, 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x10, 0x00, 0x01, 0x60, 0xBA, 0x61, + 0x1F, 0x60, 0x08, 0x63, 0xA1, 0xD3, 0x00, 0x66, 0x20, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, + 0x21, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x0F, 0x60, 0xD8, 0x62, + 0xA2, 0xD1, 0x9F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, + 0xDA, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0x1A, 0x60, 0xFD, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0x9A, 0x62, 0x1F, 0x60, 0x06, 0x64, 0xA2, 0xDB, 0x20, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xDA, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, + 0x1B, 0x60, 0x25, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, + 0xA2, 0xD1, 0x9F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, + 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, + 0x10, 0x60, 0x1E, 0x62, 0x1E, 0x60, 0xF4, 0x64, 0xA2, 0xDB, 0x1A, 0x60, 0x8A, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x06, 0xA2, 0x10, 0x60, 0x40, 0x64, 0xA2, 0xDB, 0x06, 0x64, 0x5A, 0xDB, 0x5A, 0xDB, + 0x1A, 0x60, 0x96, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x06, 0xA2, 0x10, 0x60, 0x44, 0x64, 0xA2, 0xDB, + 0x06, 0x64, 0x5A, 0xDB, 0x5A, 0xDB, 0x1A, 0x60, 0xA2, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x06, 0xA2, + 0x10, 0x60, 0x48, 0x64, 0xA2, 0xDB, 0x06, 0x64, 0x5A, 0xDB, 0x5A, 0xDB, 0xC0, 0xF1, 0x1A, 0x60, + 0xA6, 0x62, 0xA2, 0xD9, 0x10, 0x60, 0x3E, 0x62, 0x20, 0x60, 0x99, 0x64, 0xA2, 0xDB, 0x10, 0x60, + 0x42, 0x62, 0x20, 0x60, 0xA3, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x46, 0x62, 0x20, 0x60, 0xAD, 0x64, + 0xA2, 0xDB, 0x00, 0x60, 0x70, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, + 0x63, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0xA9, 0xF3, 0x07, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, + 0x0F, 0x60, 0xDA, 0x62, 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, 0x1B, 0x60, 0x8A, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x03, 0x64, + 0x6A, 0xFB, 0x0F, 0x4E, 0xE0, 0x60, 0x58, 0x4F, 0x8E, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x00, 0x64, + 0x6C, 0xFB, 0x63, 0xF5, 0xEB, 0xF3, 0x2F, 0xFA, 0xEC, 0xF3, 0x30, 0xFA, 0xED, 0xF3, 0x31, 0xFA, + 0x81, 0xF3, 0x2C, 0xFA, 0x32, 0xFA, 0x82, 0xF3, 0x2D, 0xFA, 0x33, 0xFA, 0x83, 0xF3, 0x2E, 0xFA, + 0x34, 0xFA, 0xBC, 0xF3, 0x19, 0xFA, 0x06, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0x20, 0x60, 0x58, 0x4E, + 0x71, 0x78, 0xFF, 0xFF, 0xF7, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, + 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xD8, 0x62, + 0xA2, 0xD1, 0xFF, 0x60, 0x8F, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xC1, 0xF1, 0x1A, 0x60, 0x9A, 0x62, + 0xA2, 0xD9, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x6C, 0xFB, 0x0F, 0x60, 0xDA, 0x62, 0x00, 0x60, 0x74, 0x64, + 0xA2, 0xDB, 0x1B, 0x60, 0xDE, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, + 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x1E, 0x60, 0xF4, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xE0, 0x01, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x11, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, 0x50, 0x27, 0xD6, 0x01, 0xAF, 0xF3, 0xFF, 0xFF, + 0xFE, 0xA0, 0xFF, 0xFF, 0xD1, 0x06, 0x6C, 0xF3, 0xFF, 0xFF, 0xF6, 0xA0, 0xDC, 0x84, 0x01, 0x05, + 0xA2, 0xDB, 0xCA, 0x01, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xCE, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x00, 0x00, 0xE0, 0xF3, 0x29, 0x45, 0xD4, 0x80, 0x6C, 0xF3, 0x03, 0x04, 0x1C, 0x60, + 0x55, 0x78, 0xFF, 0xFF, 0xF6, 0xA0, 0xFF, 0xFF, 0x03, 0x04, 0x1C, 0x60, 0x55, 0x78, 0xFF, 0xFF, + 0x0F, 0x60, 0xDA, 0x62, 0x00, 0x60, 0x64, 0x64, 0xA2, 0xDB, 0x1C, 0x60, 0x2A, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1E, 0x60, 0xF4, 0x78, 0xFF, 0xFF, + 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xD2, 0x01, + 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xE4, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, + 0x50, 0x27, 0xDF, 0x01, 0xAF, 0xF3, 0xFF, 0xFF, 0xFE, 0xA0, 0xFF, 0xFF, 0xC3, 0x06, 0x6C, 0xF3, + 0xFF, 0xFF, 0xF6, 0xA0, 0xDC, 0x84, 0x01, 0x05, 0xA2, 0xDB, 0xBC, 0x01, 0x0F, 0x60, 0xD8, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x20, 0x40, 0x40, 0x2B, 0x0B, 0x00, 0x0F, 0x60, 0xDA, 0x62, 0x80, 0x60, + 0x00, 0x64, 0xA2, 0xDB, 0x1C, 0x60, 0x55, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x1C, 0x60, 0x92, 0x65, 0x01, 0x64, 0xA5, 0xDB, 0xC2, 0xF1, 0x1A, 0x60, 0x9A, 0x62, 0xA2, 0xD9, + 0x0C, 0x64, 0x53, 0xFB, 0x1C, 0x60, 0x77, 0x64, 0x6B, 0xFB, 0x1F, 0x60, 0x72, 0x78, 0xFF, 0xFF, + 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0xA2, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xFF, 0x60, 0xDF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, + 0x88, 0xF1, 0x19, 0x60, 0x86, 0x63, 0xD3, 0x80, 0x68, 0xFD, 0x5F, 0x03, 0x68, 0xF3, 0xE2, 0xF1, + 0x60, 0x43, 0x29, 0x44, 0xA3, 0xD3, 0xC0, 0x85, 0xD4, 0x80, 0x5B, 0xD3, 0x56, 0x06, 0x60, 0x43, + 0x08, 0xA3, 0xBE, 0xD3, 0x83, 0xF1, 0xA3, 0xD3, 0xD0, 0x80, 0x82, 0xF1, 0x05, 0x02, 0xBF, 0xD3, + 0xD0, 0x80, 0x81, 0xF1, 0x01, 0x02, 0xD0, 0x80, 0xF8, 0xA3, 0x2B, 0x02, 0x1C, 0x60, 0xAB, 0x64, + 0x6B, 0xFB, 0x1F, 0x60, 0x29, 0x78, 0xFF, 0xFF, 0x01, 0xB0, 0x84, 0xF3, 0x3E, 0x03, 0x63, 0xF5, + 0x48, 0x7E, 0x2A, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x0F, 0x60, 0xDA, 0x62, + 0x00, 0x60, 0x01, 0x64, 0xA2, 0xDB, 0x1C, 0x60, 0xC8, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xFF, 0x60, 0xFE, 0x64, 0xA0, 0x84, 0xA2, 0xDB, + 0x1C, 0x00, 0x2D, 0x60, 0x7A, 0x65, 0xA5, 0xD3, 0x65, 0x41, 0x10, 0xA3, 0x01, 0xA4, 0xFE, 0xB4, + 0xC4, 0x85, 0xFE, 0xA1, 0xBD, 0xD3, 0x59, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, 0xD5, 0x80, 0x05, 0x02, + 0x01, 0x03, 0xF8, 0x01, 0x1E, 0x60, 0xE8, 0x78, 0xFF, 0xFF, 0x68, 0xF3, 0x88, 0xF1, 0x04, 0xA4, + 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x68, 0xFB, 0xA1, 0x01, 0xE0, 0xF3, 0x29, 0x45, 0xD4, 0x80, + 0xFF, 0xFF, 0x0C, 0x07, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x03, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x1B, 0x60, 0xB1, 0x78, 0xFF, 0xFF, 0xE1, 0xF3, 0x29, 0x45, + 0xD4, 0x80, 0xFF, 0xFF, 0x17, 0x06, 0x04, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, + 0x05, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, 0xF2, 0xFB, 0x24, 0x60, 0xAA, 0x62, + 0x1A, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x1D, 0x60, + 0x6D, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xDA, 0x62, 0x00, 0x60, 0x74, 0x64, 0xA2, 0xDB, 0x1D, 0x60, + 0x24, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, + 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1E, 0x60, + 0xF4, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x1C, 0x60, 0x87, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x17, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, 0x50, 0x27, 0xA7, 0x01, 0xAF, 0xF3, 0x6C, 0xF3, + 0xFE, 0xA0, 0xF6, 0xA0, 0x0A, 0x06, 0x03, 0x04, 0x00, 0x64, 0x55, 0xFB, 0x40, 0x49, 0x6C, 0xF3, + 0xFF, 0xFF, 0xF6, 0xA0, 0xDC, 0x84, 0x01, 0x05, 0xA2, 0xDB, 0x1C, 0x60, 0x87, 0x78, 0xFF, 0xFF, + 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xC6, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, + 0xAA, 0x62, 0x1A, 0x60, 0xA2, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0x1C, 0x60, 0x55, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xEC, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x20, 0x40, 0x40, 0x2B, 0x0B, 0x00, 0x0F, 0x60, 0xDA, 0x62, 0x80, 0x60, + 0x00, 0x64, 0xA2, 0xDB, 0x1D, 0x60, 0x6D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x1C, 0x60, 0x92, 0x65, 0x00, 0x64, 0xA5, 0xDB, 0xC3, 0xF1, 0x1A, 0x60, 0x9A, 0x62, 0xA2, 0xD9, + 0x1F, 0x60, 0x80, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0x08, 0xB4, 0x01, 0xBC, 0x29, 0x02, 0xA2, 0xDB, + 0x0F, 0x60, 0xD8, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x4E, 0xE4, 0x60, 0x58, 0x4F, 0xFB, 0x78, + 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x60, 0xDA, 0x62, 0x10, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0x1D, 0x60, + 0xA4, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1F, 0x60, 0x80, 0x64, 0xA0, 0xD3, + 0xFF, 0xFF, 0x60, 0x40, 0x0C, 0x26, 0x0C, 0x00, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x96, 0x64, + 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x1E, 0x60, 0x97, 0x78, 0xFF, 0xFF, + 0x01, 0x64, 0x31, 0x60, 0x2A, 0x62, 0xA2, 0xDB, 0x0D, 0x64, 0x53, 0xFB, 0x1D, 0x60, 0xC3, 0x64, + 0x6B, 0xFB, 0x1F, 0x60, 0x72, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0xA2, 0x64, + 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, + 0xFF, 0x60, 0xDF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x88, 0xF1, 0x19, 0x60, 0x86, 0x63, 0xD3, 0x80, + 0x68, 0xFD, 0x01, 0x02, 0x43, 0x00, 0x68, 0xF3, 0x29, 0x41, 0xA0, 0xD1, 0x58, 0xD3, 0xD1, 0x80, + 0x64, 0x45, 0x60, 0x43, 0x0F, 0x05, 0x08, 0xA3, 0xBE, 0xD3, 0x83, 0xF1, 0xA3, 0xD3, 0xD0, 0x80, + 0x82, 0xF1, 0x05, 0x02, 0xBF, 0xD3, 0xD0, 0x80, 0x81, 0xF1, 0x01, 0x02, 0xD0, 0x80, 0xF8, 0xA3, + 0x07, 0x02, 0x45, 0x49, 0x1E, 0x60, 0x2A, 0x64, 0x6B, 0xFB, 0x1F, 0x60, 0x29, 0x78, 0xFF, 0xFF, + 0x2D, 0x60, 0x7A, 0x65, 0xA5, 0xD3, 0x65, 0x41, 0x10, 0xA3, 0x01, 0xA4, 0xFE, 0xB4, 0xC4, 0x85, + 0xFE, 0xA1, 0xBD, 0xD3, 0x59, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, 0xD5, 0x80, 0x0F, 0x02, 0xF9, 0x02, + 0x05, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0x04, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, + 0xFF, 0xFF, 0xFE, 0xB4, 0xF2, 0xFB, 0x1E, 0x60, 0xE8, 0x78, 0xFF, 0xFF, 0x68, 0xF3, 0x88, 0xF1, + 0x04, 0xA4, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x68, 0xFB, 0xBD, 0x01, 0xE1, 0xF3, 0x29, 0x45, + 0xD4, 0x80, 0xFF, 0xFF, 0x75, 0x05, 0x1E, 0x60, 0x2A, 0x63, 0x6B, 0xFD, 0x1A, 0x60, 0x4C, 0x63, + 0x1F, 0x60, 0x29, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x96, 0x64, 0xA2, 0xDB, + 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x05, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, + 0xFF, 0xFF, 0x1F, 0x60, 0x52, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x04, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, + 0xFF, 0xFF, 0xFE, 0xB4, 0xF2, 0xFB, 0x84, 0xF3, 0x63, 0xF5, 0x48, 0x7E, 0x2A, 0xFA, 0x02, 0x60, + 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, + 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x0F, 0x60, + 0xDA, 0x62, 0x00, 0x60, 0x01, 0x64, 0xA2, 0xDB, 0x1E, 0x60, 0x61, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xFF, 0x60, 0xFE, 0x64, 0xA0, 0x84, + 0xA2, 0xDB, 0x1A, 0x60, 0x9A, 0x62, 0x00, 0x60, 0x32, 0x64, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, + 0x1A, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, + 0xDA, 0x62, 0x00, 0x60, 0x10, 0x64, 0xA2, 0xDB, 0x1E, 0x60, 0x81, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xFF, 0x60, 0xEF, 0x64, 0xA0, 0x84, + 0xA2, 0xDB, 0xFD, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, + 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x1B, 0x60, 0xB1, 0x78, 0xFF, 0xFF, + 0x0F, 0x60, 0xDA, 0x62, 0x00, 0x60, 0x74, 0x64, 0xA2, 0xDB, 0x1E, 0x60, 0xA2, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1E, 0x60, 0xF4, 0x78, 0xFF, 0xFF, + 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1D, 0x60, + 0xD3, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x17, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x20, 0x40, 0x50, 0x27, 0xDD, 0x01, 0xAF, 0xF3, 0x6C, 0xF3, 0xFE, 0xA0, 0xF6, 0xA0, + 0x0A, 0x06, 0x03, 0x04, 0x00, 0x64, 0x55, 0xFB, 0x40, 0x49, 0x6C, 0xF3, 0xFF, 0xFF, 0xF6, 0xA0, + 0xDC, 0x84, 0x01, 0x05, 0xA2, 0xDB, 0x1D, 0x60, 0xD3, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0xC6, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, + 0xA2, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x1D, 0x60, 0x6D, 0x78, + 0xFF, 0xFF, 0x08, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, + 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, + 0x8A, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x24, 0x60, 0xAA, 0x62, + 0x1A, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x24, 0x60, + 0xAA, 0x62, 0x1A, 0x60, 0xA2, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0x0F, 0x60, 0xD8, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x00, 0x64, 0x6A, 0xFB, 0x0F, 0x60, + 0xD0, 0x62, 0xA2, 0xD1, 0x02, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, + 0xDA, 0x62, 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, 0x1B, 0x60, 0x8A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0xA3, 0xD3, 0x7F, 0xF1, 0x7E, 0xFB, 0xD0, 0x80, 0x00, 0x64, 0x40, 0x03, + 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xBF, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xDE, 0xFE, + 0x0B, 0x04, 0x0F, 0x60, 0xDA, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0x1F, 0x60, 0x2F, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xDF, 0x60, + 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x7E, 0xF1, 0x7F, 0xF9, 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, + 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xDA, 0x62, 0x20, 0x60, 0x00, 0x64, + 0xA2, 0xDB, 0x1F, 0x60, 0x5E, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, + 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xDF, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x0F, 0x60, + 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x64, + 0x6B, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x0F, 0x60, + 0xD8, 0x62, 0xA2, 0xD1, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, 0x51, 0x23, + 0x0B, 0x00, 0x0F, 0x60, 0xDA, 0x62, 0x80, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0x1F, 0x60, 0x76, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x7F, 0x60, + 0xFF, 0x61, 0xA1, 0x84, 0x5A, 0xD1, 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x40, 0x60, 0x00, 0x65, + 0x20, 0x44, 0x34, 0x80, 0x02, 0x64, 0x8C, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x8C, 0xF3, 0x00, 0x65, + 0xD4, 0x80, 0xFF, 0xFF, 0x12, 0x03, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x7F, 0x60, 0xFF, 0x64, + 0xA0, 0x84, 0xA2, 0xDB, 0x0F, 0x60, 0xDA, 0x62, 0x80, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0x1F, 0x60, + 0x99, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2D, 0x60, 0x7A, 0x64, 0x54, 0xFB, + 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xEF, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x1A, 0x60, + 0x58, 0x4E, 0xDC, 0x78, 0xFF, 0xFF, 0x0F, 0x4E, 0xEC, 0x60, 0x58, 0x4F, 0xB9, 0x78, 0xFF, 0xFF, + 0x0E, 0x4F, 0x0F, 0x60, 0xDA, 0x62, 0x10, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0x1F, 0x60, 0xD3, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1A, 0x60, 0x58, 0x4E, 0xED, 0x78, 0xFF, 0xFF, + 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xEF, 0x60, 0xEF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, + 0x01, 0x64, 0x8C, 0xFB, 0xBF, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x01, 0x60, 0x14, 0x62, + 0xA2, 0xD1, 0x12, 0x60, 0x46, 0x63, 0xC3, 0x85, 0xC6, 0xA3, 0x3A, 0xA3, 0xD7, 0x80, 0xAF, 0xF3, + 0x09, 0x04, 0xFE, 0xA0, 0x6C, 0xF3, 0x3A, 0x06, 0xF6, 0xA0, 0x00, 0x64, 0x37, 0x04, 0x55, 0xFB, + 0x40, 0x49, 0x34, 0x00, 0x08, 0xA3, 0xBE, 0xD3, 0x83, 0xF1, 0xA3, 0xD3, 0xD0, 0x80, 0x82, 0xF1, + 0x05, 0x02, 0xBF, 0xD3, 0xD0, 0x80, 0x81, 0xF1, 0x01, 0x02, 0xD0, 0x80, 0xF8, 0xA3, 0xE5, 0x02, + 0xBE, 0xD3, 0x5A, 0xD1, 0x60, 0x47, 0x40, 0x4A, 0x64, 0x47, 0x40, 0x48, 0x20, 0x60, 0x58, 0x4E, + 0x45, 0x78, 0xFF, 0xFF, 0x0A, 0x48, 0x20, 0x60, 0x58, 0x4E, 0x55, 0x78, 0xFF, 0xFF, 0x20, 0x60, + 0x58, 0x4E, 0x71, 0x78, 0xFF, 0xFF, 0x01, 0x60, 0x2E, 0x65, 0x6C, 0xF3, 0xA5, 0xD3, 0xF6, 0xA0, + 0x40, 0xBC, 0x06, 0x04, 0xA5, 0xDB, 0x6A, 0xF1, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, 0x6A, 0xFB, + 0x6C, 0xF3, 0xFF, 0xFF, 0x00, 0xB8, 0xCC, 0x84, 0x01, 0x03, 0xA2, 0xDB, 0xFD, 0x60, 0xFF, 0x65, + 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, 0x6B, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0xF1, 0x28, 0x44, + 0xD0, 0x84, 0x03, 0xA4, 0x03, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0x04, 0x00, 0xFA, 0xA4, 0xE8, 0x84, + 0xE8, 0x87, 0xC0, 0xBF, 0xC0, 0x84, 0xA2, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0x56, 0xF1, 0x28, 0x44, + 0xD0, 0x84, 0x1F, 0xA4, 0x06, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, + 0x07, 0x00, 0xC2, 0xA4, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x87, 0xF8, 0xBF, + 0xC0, 0x84, 0x5C, 0xF1, 0x56, 0xFB, 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x05, 0x64, 0x44, 0x52, 0xFB, + 0x2E, 0x58, 0xFF, 0xFF, 0x52, 0xF1, 0x00, 0x65, 0x20, 0x40, 0x20, 0x2A, 0x06, 0x00, 0x5C, 0xF3, + 0xFF, 0xFF, 0xD0, 0x80, 0x64, 0x45, 0x01, 0x06, 0x60, 0x45, 0x2F, 0x67, 0xD4, 0x80, 0xFF, 0xFF, + 0x01, 0x06, 0x60, 0x45, 0x55, 0xF1, 0x8B, 0x67, 0xD0, 0x80, 0x60, 0x41, 0x02, 0x24, 0x64, 0x41, + 0xD5, 0x84, 0x80, 0x65, 0xC4, 0x87, 0x01, 0x05, 0x00, 0x64, 0xFF, 0xB4, 0x40, 0x49, 0x20, 0x40, + 0x20, 0x2A, 0x06, 0x00, 0x2E, 0x43, 0xF3, 0x60, 0x58, 0x4E, 0xA8, 0x78, 0xFF, 0xFF, 0x43, 0x4E, + 0x2E, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, + 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, + 0xA2, 0xD1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xF6, 0x62, + 0xA2, 0xD1, 0x00, 0x60, 0x40, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x26, 0x46, 0x27, 0xF2, 0x70, 0x63, 0x60, 0x40, 0x0A, 0x36, 0x06, 0x00, 0x14, 0x36, 0x0A, 0x00, + 0x37, 0x36, 0x04, 0x00, 0x6E, 0x36, 0x04, 0x00, 0xD0, 0x63, 0x04, 0x00, 0x33, 0x63, 0x02, 0x00, + 0x21, 0x63, 0x00, 0x00, 0x1F, 0x60, 0x5A, 0x61, 0xA1, 0xDD, 0x26, 0x46, 0xBF, 0xF2, 0x01, 0x60, + 0x00, 0x65, 0xF4, 0xA1, 0xD5, 0x80, 0x00, 0xF4, 0x02, 0x24, 0x65, 0x41, 0x41, 0x48, 0x1E, 0x65, + 0x02, 0x60, 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, + 0x64, 0x44, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, + 0xBD, 0xDB, 0xF0, 0x02, 0x02, 0x60, 0x00, 0x63, 0x28, 0x41, 0xBD, 0xD3, 0xBD, 0xD1, 0xFD, 0xA0, + 0xFF, 0xFF, 0x07, 0x03, 0x64, 0x44, 0xE0, 0x85, 0xD1, 0x81, 0xFE, 0xA1, 0xC7, 0x83, 0xF5, 0x0D, + 0x04, 0x00, 0x1A, 0x60, 0x4C, 0x61, 0xA3, 0xD3, 0xA1, 0xDB, 0x31, 0x40, 0x06, 0x26, 0x58, 0x00, + 0x00, 0x64, 0x70, 0xFB, 0x02, 0x60, 0x00, 0x63, 0x28, 0x41, 0xBD, 0xD3, 0xBD, 0xD1, 0xFC, 0xA0, + 0xFB, 0xA0, 0x08, 0x03, 0x28, 0x03, 0x64, 0x44, 0xE0, 0x85, 0xD1, 0x81, 0xFE, 0xA1, 0xC7, 0x83, + 0xF4, 0x0D, 0x46, 0x00, 0xBD, 0xD3, 0xBD, 0xD3, 0x00, 0xB8, 0x70, 0xFB, 0x6F, 0xFB, 0xBD, 0xD3, + 0x3F, 0x02, 0xA3, 0xD3, 0x60, 0x45, 0x60, 0x47, 0xB4, 0x84, 0x60, 0x41, 0x3F, 0xB5, 0xE8, 0x84, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x72, 0xFB, 0x65, 0x47, 0xE0, 0x84, + 0xE0, 0x84, 0x71, 0xFB, 0x64, 0x44, 0xE0, 0x85, 0xFA, 0xA3, 0xC7, 0x83, 0x1A, 0x60, 0x44, 0x62, + 0x61, 0x44, 0xA2, 0xDB, 0xD2, 0x01, 0xBD, 0xD3, 0xA3, 0xD3, 0x00, 0xB8, 0x6E, 0xFB, 0x74, 0xFB, + 0x1F, 0x02, 0x87, 0xF1, 0x70, 0xF3, 0x6D, 0xF9, 0x04, 0x65, 0x60, 0x40, 0x00, 0x3A, 0x06, 0x65, + 0x31, 0x44, 0xB4, 0x84, 0x40, 0x51, 0x02, 0x2A, 0x0B, 0x00, 0x08, 0xBC, 0x40, 0x51, 0x72, 0xF3, + 0x71, 0xF1, 0x00, 0xB8, 0x64, 0x45, 0x01, 0x03, 0x67, 0x45, 0x65, 0x50, 0xCC, 0x84, 0x73, 0xFB, + 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x0F, 0x60, 0xEC, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2A, 0x84, 0x00, 0x1F, 0x60, + 0x52, 0x61, 0x01, 0x64, 0xA1, 0xDB, 0x22, 0x60, 0x58, 0x4E, 0x3E, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0x00, 0xF4, 0x0D, 0xF2, 0x80, 0xFB, 0x00, 0x64, 0x86, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, + 0x00, 0x60, 0x80, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, + 0x1E, 0x65, 0xF4, 0xA4, 0xD4, 0xA0, 0x60, 0x41, 0x01, 0x06, 0x2C, 0x61, 0x41, 0x48, 0x02, 0x60, + 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x64, 0x44, + 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, + 0xF0, 0x02, 0x02, 0x60, 0x00, 0x63, 0x28, 0x41, 0xBD, 0xD3, 0xBD, 0xD1, 0x01, 0xA8, 0xC9, 0x81, + 0x06, 0x03, 0x64, 0x44, 0xD1, 0x81, 0xE0, 0x85, 0x42, 0x06, 0xC7, 0x83, 0xF5, 0x01, 0x43, 0x48, + 0x2D, 0x60, 0x2A, 0x63, 0x43, 0x4A, 0x64, 0x41, 0x28, 0x43, 0x00, 0x65, 0x45, 0x4C, 0x65, 0x5C, + 0xBD, 0xD3, 0x61, 0x40, 0x00, 0x36, 0x27, 0x00, 0xCD, 0x81, 0x60, 0x40, 0x02, 0x36, 0x60, 0x45, + 0x04, 0x36, 0x60, 0x45, 0x82, 0x36, 0x60, 0x45, 0x84, 0x36, 0x60, 0x45, 0x0B, 0x36, 0x60, 0x45, + 0x8B, 0x36, 0x60, 0x45, 0x16, 0x36, 0x60, 0x45, 0x96, 0x36, 0x60, 0x45, 0x65, 0x40, 0x00, 0x36, + 0xE7, 0x01, 0x64, 0x44, 0xDC, 0x9C, 0x2C, 0x44, 0x00, 0x3A, 0x02, 0x00, 0x45, 0x4C, 0xE0, 0x01, + 0x2C, 0x5E, 0x65, 0x5F, 0x00, 0x65, 0x45, 0x4C, 0x43, 0x48, 0x2A, 0x43, 0xBD, 0xDB, 0xFF, 0xFF, + 0x43, 0x4A, 0x28, 0x43, 0xD5, 0x01, 0x2D, 0x60, 0x28, 0x64, 0x60, 0xFE, 0xA0, 0xD9, 0xFF, 0xFF, + 0x20, 0xFE, 0x64, 0x40, 0x01, 0x3A, 0x39, 0x00, 0x2A, 0x43, 0x65, 0x44, 0xA3, 0xDB, 0x35, 0x00, + 0x23, 0x60, 0x34, 0x78, 0xFF, 0xFF, 0xDC, 0xF3, 0xFF, 0xFF, 0x03, 0xA8, 0x02, 0xA8, 0x02, 0x03, + 0x41, 0x02, 0xF6, 0x01, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, + 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0x26, 0x46, 0x1F, 0x60, 0x5A, 0x61, 0xA1, 0xD3, 0x25, 0xF2, 0x60, 0x45, + 0x24, 0xF0, 0x00, 0xF4, 0x64, 0x43, 0xC7, 0x83, 0x60, 0x41, 0x02, 0x24, 0x01, 0xA1, 0x0A, 0xF0, + 0x09, 0xF2, 0xD1, 0x80, 0xFF, 0xFF, 0x09, 0x07, 0x04, 0x04, 0x63, 0x45, 0xD4, 0x80, 0xFF, 0xFF, + 0x04, 0x06, 0x22, 0x60, 0x58, 0x4E, 0x3E, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x26, 0xF0, 0xFF, 0x67, + 0x20, 0x88, 0x64, 0x5F, 0x40, 0x4A, 0x20, 0x60, 0x58, 0x4E, 0x45, 0x78, 0xFF, 0xFF, 0x0A, 0x48, + 0x20, 0x60, 0x58, 0x4E, 0x55, 0x78, 0xFF, 0xFF, 0x20, 0x60, 0x58, 0x4E, 0x71, 0x78, 0xFF, 0xFF, + 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xDA, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x22, + 0xAF, 0x01, 0x01, 0x60, 0x2E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xBF, 0xB4, 0xA2, 0xDB, 0x1F, 0x60, + 0x5A, 0x61, 0xA1, 0xD3, 0x26, 0x46, 0x60, 0x45, 0x1E, 0x60, 0xFE, 0x63, 0x00, 0xF4, 0x09, 0xF2, + 0xBD, 0xDB, 0xFF, 0xFF, 0x0A, 0xF2, 0xBD, 0xDB, 0x0B, 0xF2, 0xFF, 0xFF, 0xBD, 0xDB, 0x0C, 0xF2, + 0xA3, 0xDB, 0xFA, 0xA3, 0x26, 0x46, 0xA3, 0xD3, 0x24, 0xF0, 0x00, 0x61, 0xD0, 0x84, 0xF1, 0x81, + 0xD4, 0x84, 0xF1, 0x81, 0xBD, 0xDB, 0xA3, 0xD3, 0x03, 0xB1, 0x03, 0xA9, 0x25, 0xF0, 0x42, 0xFE, + 0x05, 0x03, 0xFD, 0xA1, 0xCC, 0x84, 0x01, 0x02, 0xCC, 0x84, 0x00, 0x61, 0xF1, 0x81, 0xD0, 0x84, + 0xF1, 0x81, 0xBD, 0xDB, 0xA3, 0xD3, 0x03, 0xB1, 0x03, 0xA9, 0x28, 0xF0, 0x42, 0xFE, 0x01, 0x03, + 0xCC, 0x84, 0xF1, 0x81, 0xD0, 0x84, 0xF1, 0x81, 0xBD, 0xDB, 0xA3, 0xD3, 0x03, 0xB1, 0x03, 0xA9, + 0x29, 0xF0, 0x01, 0x03, 0xCC, 0x84, 0xD0, 0x84, 0xA3, 0xDB, 0x1F, 0x60, 0x52, 0x61, 0xA1, 0xD3, + 0xFF, 0xFF, 0x02, 0xA8, 0xFF, 0xFF, 0x02, 0x02, 0x2E, 0x58, 0xFF, 0xFF, 0xF5, 0xFE, 0x1E, 0x60, + 0xFE, 0x64, 0xA0, 0xD1, 0x06, 0xA4, 0xA0, 0xD3, 0x64, 0x45, 0x60, 0x40, 0x80, 0x2B, 0x03, 0x00, + 0xFF, 0x60, 0xFF, 0x64, 0x94, 0x85, 0x00, 0x60, 0x96, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x0B, 0x06, + 0x1F, 0x60, 0x52, 0x61, 0xA1, 0xD3, 0x6A, 0xF3, 0x00, 0xA8, 0x04, 0xB0, 0x04, 0x02, 0x03, 0x03, + 0x23, 0x60, 0x10, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x09, 0xF2, 0x5A, 0xD2, 0x40, 0x48, + 0x40, 0x4A, 0x5A, 0xD2, 0x5A, 0xD2, 0x40, 0x4C, 0x60, 0x41, 0x5A, 0xD0, 0x80, 0xF9, 0x40, 0x63, + 0xAD, 0x80, 0xF0, 0xA3, 0x09, 0x02, 0x3C, 0x03, 0x2C, 0x41, 0x2A, 0x44, 0x40, 0x4C, 0x28, 0x44, + 0x40, 0x4A, 0x00, 0x64, 0x40, 0x48, 0xF4, 0x01, 0xD1, 0x80, 0x01, 0x02, 0x31, 0x04, 0x10, 0xA3, + 0x80, 0x60, 0x00, 0x65, 0xA5, 0x80, 0xCF, 0x83, 0x08, 0x02, 0x28, 0x44, 0x60, 0x88, 0x2A, 0x44, + 0x70, 0x8A, 0x2C, 0x44, 0x70, 0x8C, 0xF1, 0x81, 0xF5, 0x01, 0xE7, 0xA3, 0x64, 0x44, 0x00, 0xA8, + 0x00, 0x62, 0x02, 0x02, 0x00, 0x61, 0x1C, 0x00, 0xE0, 0x84, 0xDE, 0x82, 0xFD, 0x04, 0x42, 0xFE, + 0xF8, 0x84, 0x62, 0x45, 0xC7, 0x83, 0x60, 0x45, 0x02, 0xFE, 0xD5, 0x84, 0x02, 0x05, 0x01, 0x05, + 0x61, 0x44, 0xCF, 0x83, 0x60, 0x41, 0x08, 0x03, 0x28, 0x44, 0x60, 0x88, 0x2A, 0x44, 0x70, 0x8A, + 0x2C, 0x44, 0x70, 0x8C, 0xF1, 0x81, 0xF1, 0x01, 0xCE, 0x82, 0xE9, 0x81, 0xFD, 0x02, 0xF1, 0x81, + 0x09, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0xE8, 0x84, 0xE8, 0x84, 0x5A, 0xD2, 0x3F, 0xB5, 0xE0, 0x84, + 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xB4, 0x84, 0x61, 0x45, 0xD4, 0x84, + 0xC0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x93, 0x1F, 0x60, 0x52, 0x61, 0xA1, 0xD3, + 0xFF, 0xFF, 0x00, 0xA8, 0xFF, 0xFF, 0x02, 0x03, 0x2E, 0x58, 0xFF, 0xFF, 0x10, 0x65, 0x73, 0x44, + 0xD4, 0x93, 0x6A, 0xF3, 0x26, 0x46, 0x04, 0xBC, 0xA2, 0xDB, 0x26, 0xF0, 0xFF, 0x67, 0x20, 0x88, + 0x64, 0x5F, 0x40, 0x4A, 0x20, 0x60, 0x58, 0x4E, 0x45, 0x78, 0xFF, 0xFF, 0x0A, 0x48, 0x20, 0x60, + 0x58, 0x4E, 0x55, 0x78, 0xFF, 0xFF, 0x20, 0x60, 0x58, 0x4E, 0x71, 0x78, 0xFF, 0xFF, 0x6C, 0xF3, + 0xFF, 0xFF, 0x00, 0xB8, 0xCC, 0x84, 0x01, 0x03, 0xA2, 0xDB, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, + 0x00, 0x60, 0x40, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, + 0xA2, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xD8, 0x62, + 0xA2, 0xD1, 0xFF, 0x60, 0xDF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, + 0x28, 0xF3, 0xFF, 0xFF, 0x60, 0x47, 0x0F, 0xB4, 0x59, 0x00, 0xFF, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x24, 0x60, 0x9E, 0x65, 0x04, 0x64, 0xA5, 0xDB, 0x12, 0x00, 0x24, 0x60, 0x9E, 0x65, 0x0C, 0x64, + 0xA5, 0xDB, 0x0D, 0x00, 0x24, 0x60, 0x9E, 0x65, 0x06, 0x64, 0xA5, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0x9E, 0x65, 0x08, 0x64, 0xA5, 0xDB, 0x23, 0x60, + 0xA1, 0x64, 0xA1, 0xFB, 0xFF, 0xFF, 0x2D, 0xFF, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0x29, 0xF3, + 0x7F, 0xFB, 0xA4, 0xFB, 0x02, 0x60, 0xEE, 0x64, 0xA3, 0xFB, 0x07, 0x64, 0xA5, 0xFB, 0x23, 0x60, + 0xA1, 0x64, 0xA1, 0xFB, 0xFF, 0xFF, 0xDF, 0xFE, 0x00, 0x64, 0x19, 0xFF, 0x25, 0x60, 0x11, 0x78, + 0xFF, 0xFF, 0x24, 0x60, 0x0D, 0x63, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0x23, 0x60, + 0x8E, 0x63, 0xA1, 0xFD, 0xFF, 0xFF, 0x1A, 0xFF, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0xA3, 0x60, + 0x4B, 0x63, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0x29, 0xF5, 0x24, 0x60, 0x7A, 0x63, + 0x24, 0x60, 0x4C, 0x64, 0xBD, 0xDB, 0x66, 0x44, 0xBD, 0xDB, 0x02, 0x64, 0xA3, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xF9, 0xFE, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xA7, 0x01, 0x00, 0x36, 0xA8, 0x01, + 0x01, 0x36, 0xAB, 0x01, 0x02, 0x36, 0xAE, 0x01, 0x03, 0x36, 0xB5, 0x01, 0x04, 0x36, 0xD1, 0x01, + 0x05, 0x36, 0xCF, 0x01, 0x06, 0x36, 0xF1, 0x01, 0x07, 0x36, 0xCB, 0x01, 0x08, 0x36, 0xB7, 0x01, + 0x09, 0x36, 0x0C, 0x00, 0x0A, 0x36, 0x0D, 0x00, 0x0B, 0x36, 0x0E, 0x00, 0x0C, 0x36, 0x17, 0x00, + 0x0D, 0x36, 0x0D, 0x00, 0x0E, 0x36, 0x1E, 0x00, 0x0F, 0x36, 0x32, 0x00, 0x02, 0x60, 0x00, 0x64, + 0x08, 0x00, 0x04, 0x60, 0x00, 0x64, 0x05, 0x00, 0x00, 0x60, 0x01, 0x64, 0x02, 0x00, 0x20, 0x60, + 0x00, 0x64, 0x32, 0x45, 0xB4, 0x85, 0x45, 0x52, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x24, 0x60, + 0xD1, 0x63, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x3F, 0x40, 0x02, 0x2B, 0x05, 0x00, 0x90, 0x60, 0x00, 0xE8, 0x24, 0x60, + 0x0D, 0x63, 0x04, 0x00, 0x91, 0x60, 0x00, 0xE8, 0x24, 0x60, 0xBB, 0x63, 0x28, 0xE8, 0x0C, 0x60, + 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x91, 0x60, 0x00, 0xE8, 0x28, 0xE8, 0xD9, 0x60, 0xFE, 0x64, 0x32, 0x45, 0xA4, 0x85, 0x45, 0x52, + 0x99, 0xFF, 0xA5, 0x4F, 0xFF, 0xB4, 0x07, 0xFB, 0x98, 0xFF, 0xA3, 0x60, 0x4B, 0x63, 0x0C, 0x60, + 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, + 0xFF, 0xFF, 0x43, 0xFF, 0x01, 0x60, 0x00, 0xE1, 0x28, 0xF3, 0x47, 0xFF, 0x60, 0x40, 0x07, 0x37, + 0x4B, 0x00, 0x05, 0x3B, 0x04, 0x00, 0xFF, 0x0A, 0x80, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x29, 0xF5, + 0x2A, 0xF3, 0x47, 0xFF, 0x3F, 0xF0, 0x01, 0x1B, 0x01, 0x64, 0x60, 0x56, 0xAD, 0xE2, 0xB5, 0xFF, + 0x6C, 0x40, 0x40, 0xE1, 0xA1, 0xFF, 0x00, 0xF4, 0x6E, 0x61, 0x12, 0x62, 0x64, 0x43, 0x01, 0xE1, + 0x03, 0x64, 0xE2, 0xD0, 0xC9, 0x81, 0x64, 0x4C, 0xCC, 0x84, 0xDA, 0x82, 0xFA, 0x02, 0x01, 0x60, + 0x00, 0x6B, 0x9A, 0xFF, 0xCA, 0x82, 0x03, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0xFF, 0xFF, 0x7A, 0xD0, + 0xA1, 0xFF, 0x64, 0x4C, 0xFC, 0x1C, 0xF8, 0x1D, 0x00, 0xB9, 0x06, 0x1E, 0x02, 0x02, 0x00, 0xF4, + 0xDA, 0x82, 0x5A, 0xD2, 0xA1, 0xFF, 0x60, 0x4D, 0x3F, 0x40, 0x02, 0x2B, 0x08, 0x00, 0x28, 0xF3, + 0xA5, 0x60, 0xC4, 0x65, 0x60, 0x40, 0x0E, 0x3B, 0x02, 0x00, 0x80, 0x4C, 0xFE, 0x01, 0xA1, 0xFF, + 0x87, 0x4E, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x67, 0x4C, 0xFF, 0xFF, 0xBC, 0xFF, + 0x00, 0xE1, 0xD5, 0xFE, 0xA1, 0xFF, 0xFF, 0xFF, 0x00, 0x64, 0x40, 0x46, 0x60, 0x41, 0xB5, 0xFF, + 0xB7, 0xFF, 0xB4, 0xFF, 0x29, 0xF5, 0x3F, 0xF0, 0x24, 0xF2, 0x44, 0x43, 0x40, 0x44, 0x00, 0xF4, + 0xF3, 0x60, 0xA0, 0x65, 0x10, 0x62, 0x5A, 0xD2, 0xD9, 0x81, 0xD4, 0x80, 0xFF, 0xFF, 0xFB, 0x02, + 0x61, 0x45, 0x24, 0x44, 0xD4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xFD, 0xA5, 0x48, 0x60, + 0x00, 0x64, 0xC4, 0x9D, 0x0D, 0x60, 0x00, 0x6B, 0x24, 0x44, 0xC0, 0x83, 0xBB, 0xFF, 0x29, 0xF5, + 0x01, 0xE1, 0x00, 0xF4, 0x6C, 0x61, 0x10, 0x62, 0x05, 0x00, 0x00, 0xF4, 0x01, 0xF2, 0xFF, 0xFF, + 0x60, 0x41, 0x04, 0x62, 0xA1, 0xFF, 0xFF, 0xFF, 0x01, 0x10, 0x1A, 0x00, 0x26, 0x44, 0x01, 0x26, + 0x0C, 0x00, 0x24, 0x44, 0xC8, 0x84, 0x40, 0x44, 0x02, 0x03, 0x6C, 0x45, 0xF3, 0x01, 0x03, 0x15, + 0x01, 0x64, 0x05, 0xFA, 0x15, 0x00, 0x6C, 0x45, 0xED, 0x01, 0x23, 0x44, 0xC8, 0x84, 0x40, 0x43, + 0x02, 0x03, 0x6C, 0x45, 0xE7, 0x01, 0x00, 0x64, 0x01, 0x15, 0x01, 0x64, 0x6C, 0x45, 0x05, 0xFB, + 0xE2, 0xD2, 0xDA, 0x82, 0xC9, 0x81, 0x60, 0x4C, 0xDD, 0x1C, 0xD7, 0x03, 0xBC, 0xFF, 0xDA, 0x01, + 0x00, 0xE1, 0xD5, 0xFE, 0xA1, 0xFF, 0xFF, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, 0x67, 0x4C, 0x43, 0xFF, + 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0x01, 0xE1, 0x01, 0x60, 0x69, 0x6B, 0xA5, 0x60, + 0xC4, 0x64, 0x60, 0x4C, 0xBB, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x60, 0x4C, 0xA1, 0xFF, 0xFF, 0xFF, + 0x60, 0x4C, 0xFC, 0x01, 0x29, 0xF3, 0x2A, 0xF1, 0x07, 0xB5, 0x04, 0xE1, 0x65, 0x41, 0x64, 0x54, + 0xCD, 0xE2, 0x95, 0x81, 0xA1, 0x5D, 0xA1, 0xFF, 0xFF, 0xFF, 0xF9, 0x01, 0x61, 0x44, 0xFE, 0xFB, + 0xFF, 0xFD, 0xFF, 0x01, 0x7F, 0x67, 0x01, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0xB1, 0xFE, 0x08, 0x05, + 0xB0, 0xFE, 0x09, 0x05, 0xB2, 0xFE, 0xB3, 0xFE, 0x78, 0x43, 0x01, 0x61, 0x24, 0x60, 0xDD, 0x78, + 0x2D, 0x60, 0x5D, 0x78, 0xFF, 0xFF, 0x28, 0xF3, 0x29, 0xF1, 0x40, 0x44, 0x44, 0x45, 0x2A, 0xF1, + 0x2B, 0xF1, 0x44, 0x46, 0x44, 0x47, 0x3F, 0xB4, 0xE0, 0x85, 0x1F, 0x60, 0x88, 0x64, 0x44, 0xD7, + 0x58, 0x43, 0xFF, 0xFF, 0x60, 0x45, 0x1C, 0x60, 0xB4, 0x7C, 0xA4, 0xD3, 0x61, 0x43, 0x04, 0xB4, + 0x24, 0x44, 0x02, 0x03, 0x13, 0xFF, 0x06, 0x00, 0x3F, 0xB4, 0xB4, 0x84, 0xFF, 0x27, 0x05, 0xFD, + 0x04, 0xFB, 0x10, 0x75, 0xA1, 0xFF, 0xFF, 0xFF, 0x86, 0x3E, 0xB4, 0xFE, 0x0B, 0x05, 0xB5, 0xFE, + 0x02, 0x24, 0xA1, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0xFE, 0x07, 0x05, 0x78, 0x43, 0x01, 0x61, + 0x24, 0x60, 0xDD, 0x78, 0x2D, 0x60, 0x98, 0x78, 0xFF, 0xFF, 0x36, 0x44, 0x00, 0x7F, 0xF2, 0xA0, + 0x60, 0x45, 0x05, 0x05, 0x20, 0x60, 0x16, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x78, 0x43, + 0x01, 0x61, 0x24, 0x60, 0xDD, 0x78, 0x78, 0x43, 0x01, 0x61, 0x24, 0x60, 0xDD, 0x78, 0x7F, 0x60, + 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x10, 0x02, 0x10, 0x64, 0x40, 0x40, + 0x02, 0x64, 0x40, 0x50, 0x61, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x04, 0x00, 0x10, 0xE0, 0x46, 0x60, + 0x09, 0xE0, 0x00, 0x00, 0x27, 0xF1, 0x00, 0x66, 0x20, 0x78, 0x42, 0xFE, 0x23, 0x58, 0xFF, 0xFF, + 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x1A, 0x02, 0x1C, 0x60, + 0xB4, 0x63, 0xA3, 0xD3, 0x07, 0x7C, 0x20, 0xB5, 0x0C, 0xB5, 0x04, 0x03, 0x03, 0x02, 0xDC, 0xF9, + 0x00, 0x67, 0x0F, 0x00, 0x00, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0xAC, 0x01, 0x36, 0x47, 0xFF, 0x23, + 0x04, 0x00, 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x04, 0x00, 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, + 0x02, 0x61, 0x31, 0x02, 0x1C, 0x60, 0xB4, 0x63, 0xA3, 0xD3, 0x01, 0x7C, 0x20, 0xB5, 0x0C, 0xB5, + 0x03, 0x03, 0x02, 0x02, 0xDC, 0xF9, 0xFF, 0xFF, 0x02, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0x25, 0x60, + 0x11, 0x78, 0xFF, 0xFF, 0x9F, 0xF1, 0x20, 0x44, 0x64, 0x40, 0xFF, 0x26, 0x1B, 0x00, 0x7F, 0xB4, + 0x40, 0x40, 0x5C, 0x5E, 0x82, 0xFF, 0x26, 0x44, 0xFD, 0xB4, 0x40, 0x46, 0x5C, 0x41, 0x87, 0xFF, + 0x62, 0xFF, 0x00, 0x63, 0x24, 0x60, 0x5E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, + 0x04, 0x03, 0x09, 0xF2, 0x0F, 0xFC, 0xAC, 0x86, 0xFB, 0x01, 0x24, 0x60, 0x9E, 0x62, 0x06, 0x64, + 0xA2, 0xDB, 0x2D, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x00, 0x67, 0x20, 0x40, 0x80, 0x2A, + 0x02, 0x00, 0x7F, 0x67, 0x06, 0x61, 0x60, 0x45, 0x1C, 0x60, 0xB4, 0x7C, 0xA4, 0xD3, 0x61, 0x43, + 0x04, 0xB4, 0x24, 0x44, 0x02, 0x03, 0x13, 0xFF, 0x55, 0x01, 0x3F, 0xB4, 0xB4, 0x84, 0xFF, 0x27, + 0x05, 0xFD, 0x04, 0xFB, 0x20, 0x40, 0x80, 0x2A, 0x02, 0x00, 0x10, 0x75, 0x07, 0x00, 0x2D, 0x60, + 0x9C, 0x62, 0x01, 0x64, 0xA2, 0xDB, 0xFF, 0xFF, 0x08, 0x60, 0x10, 0x75, 0x43, 0x01, 0x25, 0x46, + 0x01, 0xF2, 0x08, 0xF0, 0x60, 0x47, 0x03, 0xB4, 0x03, 0xAC, 0x7F, 0x67, 0x03, 0x61, 0x08, 0x02, + 0x24, 0x60, 0x7A, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x24, 0x40, 0x01, 0x2B, 0x49, 0x00, 0x25, 0x44, 0x1F, 0xB4, 0xE0, 0x85, + 0x25, 0x60, 0xEB, 0x64, 0xC4, 0x98, 0xFF, 0xFF, 0xC0, 0xFE, 0x3D, 0x00, 0xC1, 0xFE, 0x3B, 0x00, + 0xC2, 0xFE, 0x39, 0x00, 0xC3, 0xFE, 0x37, 0x00, 0xC4, 0xFE, 0x35, 0x00, 0xC5, 0xFE, 0x33, 0x00, + 0xC6, 0xFE, 0x31, 0x00, 0xC7, 0xFE, 0x2F, 0x00, 0xC8, 0xFE, 0x2D, 0x00, 0xC9, 0xFE, 0x2B, 0x00, + 0xCA, 0xFE, 0x29, 0x00, 0xCB, 0xFE, 0x27, 0x00, 0xCC, 0xFE, 0x25, 0x00, 0xCD, 0xFE, 0x23, 0x00, + 0xCE, 0xFE, 0x21, 0x00, 0xCF, 0xFE, 0x1F, 0x00, 0xD0, 0xFE, 0x1D, 0x00, 0xD1, 0xFE, 0x1B, 0x00, + 0xD2, 0xFE, 0x19, 0x00, 0xD3, 0xFE, 0x17, 0x00, 0xD4, 0xFE, 0x15, 0x00, 0xD5, 0xFE, 0x13, 0x00, + 0xD6, 0xFE, 0x11, 0x00, 0xD7, 0xFE, 0x0F, 0x00, 0xD8, 0xFE, 0x0D, 0x00, 0xD9, 0xFE, 0x0B, 0x00, + 0xDA, 0xFE, 0x09, 0x00, 0xDB, 0xFE, 0x07, 0x00, 0xDC, 0xFE, 0x05, 0x00, 0xDD, 0xFE, 0x03, 0x00, + 0xDE, 0xFE, 0x01, 0x00, 0xDF, 0xFE, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x9F, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x9E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9D, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x9C, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9A, 0xFE, 0xF0, 0x84, + 0xFF, 0xFF, 0x99, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x98, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x97, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x96, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x95, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x94, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x93, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x92, 0xFE, 0xF0, 0x84, + 0xFF, 0xFF, 0x91, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x90, 0xFE, 0xF0, 0x84, 0x06, 0xFB, 0x8F, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x8E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8D, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x8C, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8A, 0xFE, 0xF0, 0x84, + 0xFF, 0xFF, 0x89, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x88, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x87, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x86, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x85, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x84, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x83, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x82, 0xFE, 0xF0, 0x84, + 0xFF, 0xFF, 0x81, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x80, 0xFE, 0xF0, 0x84, 0x05, 0xFB, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x5C, 0x5C, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x24, 0x40, 0x01, 0x27, + 0x55, 0x00, 0x05, 0x60, 0x00, 0x63, 0x05, 0xFD, 0x30, 0x44, 0xBD, 0xDB, 0x31, 0x44, 0xBD, 0xDB, + 0x32, 0x44, 0xBD, 0xDB, 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, 0x35, 0x44, 0xBD, 0xDB, + 0x36, 0x44, 0xBD, 0xDB, 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, 0x39, 0x44, 0xBD, 0xDB, + 0x3A, 0x44, 0xBD, 0xDB, 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, 0x3D, 0x44, 0xBD, 0xDB, + 0x3E, 0x44, 0xBD, 0xDB, 0x3F, 0x44, 0xBD, 0xDB, 0x02, 0x61, 0x61, 0x44, 0x02, 0x36, 0x82, 0xFF, + 0x03, 0x36, 0x83, 0xFF, 0x04, 0x36, 0x84, 0xFF, 0x05, 0x36, 0x85, 0xFF, 0x06, 0x36, 0x86, 0xFF, + 0x07, 0x36, 0x87, 0xFF, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, + 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, + 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, + 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, + 0x2F, 0x44, 0xBD, 0xDB, 0xDD, 0x81, 0x08, 0x3A, 0xD0, 0x01, 0x54, 0x00, 0x27, 0x40, 0x10, 0x26, + 0x30, 0x00, 0x26, 0x44, 0x01, 0x36, 0x2D, 0x00, 0x02, 0x36, 0x82, 0xFF, 0x03, 0x36, 0x83, 0xFF, + 0x04, 0x36, 0x84, 0xFF, 0x05, 0x36, 0x85, 0xFF, 0x06, 0x36, 0x86, 0xFF, 0x25, 0x44, 0x00, 0x36, + 0x44, 0x40, 0x01, 0x36, 0x44, 0x41, 0x02, 0x36, 0x44, 0x42, 0x03, 0x36, 0x44, 0x43, 0x04, 0x36, + 0x44, 0x44, 0x05, 0x36, 0x44, 0x45, 0x06, 0x36, 0x44, 0x46, 0x07, 0x36, 0x44, 0x47, 0x08, 0x36, + 0x44, 0x48, 0x09, 0x36, 0x44, 0x49, 0x0A, 0x36, 0x44, 0x4A, 0x0B, 0x36, 0x44, 0x4B, 0x0C, 0x36, + 0x44, 0x4C, 0x0D, 0x36, 0x44, 0x4D, 0x0E, 0x36, 0x44, 0x4E, 0x0F, 0x36, 0x44, 0x4F, 0x87, 0xFF, + 0x21, 0x00, 0x25, 0x44, 0x10, 0x36, 0x44, 0x50, 0x11, 0x36, 0x44, 0x51, 0x12, 0x36, 0x44, 0x52, + 0x13, 0x36, 0x44, 0x53, 0x14, 0x36, 0x44, 0x54, 0x15, 0x36, 0x44, 0x55, 0x16, 0x36, 0x44, 0x56, + 0x17, 0x36, 0x44, 0x57, 0x18, 0x36, 0x44, 0x58, 0x19, 0x36, 0x44, 0x59, 0x1A, 0x36, 0x44, 0x5A, + 0x1B, 0x36, 0x44, 0x5B, 0x1C, 0x36, 0x44, 0x5C, 0x1D, 0x36, 0x44, 0x5D, 0x1E, 0x36, 0x44, 0x5E, + 0x1F, 0x36, 0x44, 0x5F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0x46, 0xAE, 0x60, 0x58, 0x4F, + 0x6F, 0x78, 0xFF, 0xFF, 0x03, 0x61, 0x7F, 0x67, 0x0B, 0x02, 0x00, 0xF0, 0x24, 0x60, 0x7A, 0x62, + 0x04, 0x64, 0xA2, 0xDB, 0x5A, 0xD9, 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, + 0x11, 0x02, 0x24, 0x60, 0x9E, 0x62, 0x1A, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x50, 0x63, 0x5A, 0xDD, + 0x27, 0x60, 0x6E, 0x64, 0xA1, 0xFB, 0x2D, 0xFF, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0x2A, 0xF3, + 0x05, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, + 0x7F, 0x67, 0x02, 0x61, 0x0F, 0x02, 0x24, 0x60, 0x9E, 0x62, 0x1C, 0x64, 0xA2, 0xDB, 0x00, 0x60, + 0x50, 0x63, 0x5A, 0xDD, 0x27, 0x60, 0x88, 0x64, 0xA1, 0xFB, 0x2D, 0xFF, 0x25, 0x60, 0x11, 0x78, + 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, + 0x02, 0x61, 0x3E, 0x02, 0x25, 0x45, 0x20, 0x44, 0x80, 0x2A, 0x3A, 0x00, 0xF1, 0x60, 0x00, 0x64, + 0xD4, 0x80, 0xFF, 0xFF, 0x0B, 0x03, 0xF1, 0x60, 0x01, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x06, 0x03, + 0xF1, 0x60, 0x02, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x30, 0x03, 0x29, 0x00, 0x2D, 0x60, 0x0E, 0x62, + 0xA2, 0xD1, 0xBA, 0xF3, 0x1F, 0x60, 0x82, 0x61, 0xA0, 0x84, 0xA1, 0xDB, 0x25, 0x45, 0x23, 0x60, + 0xE4, 0x63, 0x02, 0x61, 0xBD, 0xD3, 0xBD, 0xD1, 0xD4, 0x80, 0xBD, 0xD3, 0xBD, 0xD5, 0xCD, 0x81, + 0x02, 0x03, 0x15, 0x03, 0xF7, 0x01, 0xA2, 0xFF, 0xA6, 0xD3, 0x40, 0x4C, 0x00, 0xA8, 0x67, 0x43, + 0x0C, 0x02, 0xA2, 0xDD, 0x42, 0x48, 0x64, 0x41, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, + 0x66, 0x44, 0x28, 0xDB, 0x02, 0x03, 0x2C, 0x58, 0xA3, 0xFF, 0x0C, 0x61, 0x03, 0x00, 0x04, 0x61, + 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x2D, 0x60, 0x0E, 0x62, 0xA2, 0xD1, + 0xBA, 0xF3, 0x1F, 0x60, 0x82, 0x61, 0xA0, 0x84, 0xA1, 0xDB, 0x1F, 0x60, 0x86, 0x61, 0x01, 0x64, + 0xA1, 0xDB, 0xFF, 0xFF, 0xC4, 0xFE, 0xEE, 0x01, 0xC6, 0xFE, 0xEC, 0x01, 0x7E, 0x60, 0xC0, 0x64, + 0x24, 0x45, 0xA4, 0x80, 0x02, 0x61, 0x3F, 0x02, 0x25, 0x45, 0xF8, 0x2B, 0x3B, 0x00, 0x2E, 0xF5, + 0x67, 0x44, 0xD4, 0x80, 0x20, 0x60, 0x24, 0x63, 0x39, 0x03, 0x60, 0x61, 0x24, 0x44, 0x01, 0x27, + 0x29, 0x00, 0xA3, 0xFC, 0xA4, 0xF8, 0xBD, 0xD3, 0xA3, 0xD1, 0xD4, 0x80, 0xCD, 0x81, 0x08, 0x24, + 0x64, 0x58, 0x08, 0xA3, 0xF8, 0x02, 0x08, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xA3, 0xD1, 0xFE, 0xA0, + 0xFA, 0x60, 0x00, 0x64, 0xD0, 0x80, 0x14, 0x02, 0x13, 0x02, 0x04, 0xA3, 0xBE, 0xD3, 0xBD, 0xD1, + 0x0F, 0x18, 0xD4, 0x80, 0x0D, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x64, 0x41, + 0xDD, 0x81, 0xE1, 0x81, 0xCB, 0x83, 0x46, 0x65, 0x2F, 0x60, 0x58, 0x4F, 0x01, 0x78, 0xFF, 0xFF, + 0x00, 0x67, 0x0A, 0x00, 0xBD, 0xD3, 0xBE, 0xD1, 0xD4, 0x80, 0xCD, 0x81, 0x08, 0x24, 0x64, 0x58, + 0x08, 0xA3, 0xF8, 0x02, 0x04, 0x61, 0x7F, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x0F, 0x64, 0x23, 0xFA, + 0x67, 0x44, 0x24, 0xFA, 0x62, 0x41, 0x3C, 0x60, 0x00, 0x65, 0x1A, 0x63, 0x68, 0x60, 0x28, 0x64, + 0x65, 0x46, 0x58, 0xD0, 0x2E, 0xF5, 0x59, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0xCB, 0x83, 0xBF, 0xD1, 0x4A, 0x65, 0x64, 0x43, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0x01, 0x26, + 0xDC, 0x81, 0xE9, 0x84, 0xDC, 0x84, 0x23, 0xFA, 0x09, 0x00, 0x4B, 0xD3, 0xFF, 0xFF, 0x60, 0x41, + 0xE8, 0x84, 0xDC, 0x84, 0x23, 0xFA, 0xBF, 0xD1, 0x4A, 0x65, 0x64, 0x43, 0x2F, 0x60, 0x58, 0x4F, + 0x01, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xE0, 0xA0, + 0x20, 0x64, 0x01, 0x06, 0x25, 0xFA, 0x23, 0xF2, 0xDF, 0xD1, 0xCC, 0x84, 0xE0, 0x85, 0x0B, 0x06, + 0xBF, 0xD1, 0x64, 0x41, 0xD5, 0x80, 0x64, 0x43, 0x01, 0x06, 0x65, 0x41, 0x4A, 0x65, 0x29, 0x60, + 0x58, 0x4F, 0x83, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xDC, 0xF3, 0x02, 0x63, + 0x23, 0xFC, 0x07, 0xB4, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x4B, 0xD3, 0xBF, 0xD3, + 0x60, 0x41, 0xC9, 0x83, 0xE9, 0x81, 0xDD, 0x81, 0xA3, 0xFA, 0xE0, 0x81, 0x3C, 0x60, 0x00, 0x67, + 0x02, 0x24, 0x02, 0xA4, 0x60, 0x47, 0x40, 0x4B, 0xC9, 0x81, 0x4A, 0x65, 0xAB, 0x46, 0x59, 0xD0, + 0xAB, 0x46, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF6, 0x1F, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD1, 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, + 0x60, 0x47, 0x25, 0xFA, 0x00, 0x7E, 0x60, 0x47, 0x01, 0x26, 0xDC, 0x84, 0x60, 0x41, 0xE8, 0x84, + 0xD8, 0x84, 0x23, 0xFA, 0xAB, 0x01, 0xFC, 0xA3, 0xA3, 0xD1, 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, + 0x00, 0x7F, 0x25, 0xFA, 0x60, 0x41, 0x01, 0x26, 0xDD, 0x81, 0xE9, 0x84, 0xD8, 0x84, 0x23, 0xFA, + 0x9D, 0x01, 0x28, 0x60, 0xE2, 0x63, 0xBF, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0xE8, 0x84, 0xDC, 0x84, + 0x23, 0xFA, 0x4A, 0x65, 0x2F, 0x60, 0x58, 0x4F, 0x01, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x28, 0x60, 0xE2, 0x63, 0x23, 0xF2, 0xC0, 0x65, 0xCC, 0x84, 0xE0, 0x81, 0x0A, 0x04, + 0xBF, 0xDB, 0xD5, 0x80, 0x07, 0x03, 0x01, 0x06, 0x65, 0x41, 0x61, 0x44, 0xBF, 0xDB, 0x4A, 0x65, + 0x58, 0x4F, 0xAA, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x03, 0x4E, 0x28, 0x60, 0x58, 0x43, + 0x5C, 0x78, 0xFF, 0xFF, 0x29, 0x60, 0xC6, 0x61, 0x29, 0x60, 0xA4, 0x62, 0xA2, 0xD3, 0xA1, 0xDB, + 0xCC, 0x84, 0xA8, 0x83, 0x05, 0x04, 0x29, 0x60, 0xA4, 0x64, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, + 0x0E, 0x43, 0x81, 0x01, 0x23, 0xF2, 0x1C, 0x60, 0x8E, 0x65, 0x60, 0x41, 0x1C, 0x60, 0x2A, 0x63, + 0xA3, 0xDB, 0xFF, 0xA1, 0x48, 0x64, 0x58, 0xD0, 0x7E, 0xA8, 0x5B, 0xD9, 0x02, 0x02, 0x00, 0xF4, + 0x02, 0x64, 0xFF, 0xA1, 0xD7, 0x80, 0x02, 0x03, 0x01, 0x03, 0xF5, 0x01, 0x2E, 0xF5, 0x00, 0x60, + 0x2F, 0x65, 0x25, 0xF2, 0x00, 0x63, 0xCC, 0x84, 0x03, 0xA3, 0xFD, 0x05, 0x4A, 0x64, 0xD7, 0x80, + 0x1B, 0x60, 0xC6, 0x61, 0x2F, 0x05, 0xA1, 0xDD, 0xE3, 0x83, 0xFE, 0xA3, 0x58, 0xD0, 0x7E, 0xA8, + 0x59, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x00, 0x63, 0x59, 0xDD, 0x2E, 0xF5, + 0x1B, 0x60, 0xC6, 0x64, 0x25, 0xF0, 0xA0, 0xD3, 0xD3, 0x80, 0x01, 0xB0, 0x04, 0x03, 0x01, 0xA4, + 0x03, 0x03, 0xA2, 0xDB, 0x01, 0x00, 0xA2, 0xDD, 0x1B, 0x60, 0xCE, 0x63, 0x10, 0x60, 0x5A, 0x65, + 0xBD, 0xD3, 0xBD, 0xD1, 0xE0, 0x84, 0xC4, 0x82, 0x10, 0x60, 0x7A, 0x65, 0x07, 0x64, 0x64, 0x41, + 0x5A, 0xDB, 0xD6, 0x80, 0xCD, 0x81, 0x06, 0x03, 0xFB, 0x02, 0x25, 0xF2, 0x02, 0xA3, 0xCC, 0x84, + 0xA2, 0xDA, 0xEC, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0x2A, 0x61, 0xA1, 0xD3, + 0x23, 0xFA, 0xE0, 0x83, 0x4A, 0x65, 0x04, 0x02, 0x02, 0x63, 0x23, 0xFC, 0xA5, 0xFC, 0x09, 0x00, + 0xDB, 0x83, 0x59, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, + 0xF8, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x1B, 0x60, 0xC6, 0x62, 0xA2, 0xD3, 0x00, 0x61, + 0x02, 0xA4, 0xFE, 0xA0, 0x23, 0xFA, 0x1B, 0x03, 0xFA, 0xA4, 0xFD, 0xA4, 0x01, 0xA1, 0xFD, 0x07, + 0x61, 0x43, 0x23, 0xF2, 0x25, 0xFC, 0xE0, 0x83, 0x02, 0xA3, 0x1B, 0x60, 0xC6, 0x61, 0x00, 0x60, + 0x4A, 0x64, 0x59, 0xD1, 0x58, 0xD8, 0x7E, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, + 0x25, 0xF2, 0x23, 0xF2, 0x01, 0xB0, 0xCC, 0x84, 0x04, 0x02, 0x23, 0xFA, 0x02, 0x00, 0x00, 0x64, + 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x41, 0x4B, 0x65, 0x42, 0x80, 0x64, 0xD4, 0x85, + 0x2B, 0x41, 0x00, 0xA1, 0x55, 0x8B, 0x0D, 0x03, 0x02, 0x04, 0x65, 0x41, 0x02, 0x00, 0x00, 0x64, + 0x40, 0x4B, 0xCA, 0x84, 0x58, 0xD0, 0xC9, 0x81, 0xBD, 0xD9, 0xFC, 0x02, 0x00, 0xF4, 0x04, 0x65, + 0xEC, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD3, 0x02, 0x7C, 0xA0, 0xD3, 0x23, 0xF8, + 0xDC, 0x84, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x02, 0x64, 0x23, 0xFA, 0x01, 0x64, + 0x9D, 0xFE, 0x02, 0x28, 0x02, 0x64, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x2D, 0x60, + 0x1A, 0x62, 0xA2, 0xD3, 0x02, 0x7C, 0x23, 0xF8, 0x01, 0xB4, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD1, 0x02, 0x64, 0x23, 0xFA, 0xA4, 0xD3, 0x00, 0x63, 0x60, 0x40, + 0x0A, 0x37, 0x01, 0x63, 0x14, 0x37, 0x02, 0x63, 0x37, 0x37, 0x06, 0x63, 0x6E, 0x37, 0x0B, 0x63, + 0x25, 0xFC, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x02, 0x64, 0x23, 0xFA, 0x88, 0xFF, 0x75, 0x44, + 0x8D, 0xFF, 0xE8, 0x87, 0xE8, 0x84, 0xE8, 0x84, 0x03, 0xB4, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x04, 0x64, 0x23, 0xFA, 0x86, 0xFF, 0x29, 0x44, 0x87, 0xFF, 0x25, 0xFA, 0x55, 0xF3, + 0x52, 0xF1, 0x80, 0x65, 0xC4, 0x87, 0x00, 0x7F, 0x26, 0xFA, 0x64, 0x44, 0xC4, 0x87, 0x00, 0x7F, + 0x27, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x05, 0x64, 0x23, 0xFA, 0x52, 0x63, 0xB7, 0xF3, + 0x4B, 0xDA, 0xB6, 0xF3, 0x4B, 0xDA, 0xB5, 0xF3, 0x4B, 0xDA, 0x60, 0x41, 0x88, 0xFF, 0x72, 0x5C, + 0x89, 0xFF, 0x4A, 0xD8, 0xA2, 0x48, 0x20, 0x23, 0x0E, 0x00, 0x64, 0x40, 0x80, 0x27, 0x15, 0x00, + 0xDC, 0x84, 0xBD, 0xDA, 0xBD, 0xD2, 0x11, 0x04, 0xDC, 0x84, 0xA2, 0xDA, 0xA3, 0xD2, 0x0D, 0x04, + 0xDC, 0x84, 0xA3, 0xDA, 0x0A, 0x00, 0x52, 0x63, 0xB7, 0xF3, 0x4B, 0xDA, 0xB6, 0xF3, 0x4B, 0xDA, + 0xB5, 0xF3, 0x4B, 0xDA, 0x54, 0x90, 0x4C, 0x63, 0xE0, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x25, 0xF0, 0x2D, 0x60, 0x16, 0x65, 0x23, 0xF2, 0xA5, 0xD9, 0x02, 0xA8, 0x64, 0x44, 0x07, 0x02, + 0x00, 0xBC, 0xF2, 0xA4, 0x04, 0x03, 0x03, 0x07, 0x28, 0x60, 0x44, 0x62, 0xA2, 0xD9, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x20, 0x63, 0x28, 0x60, 0xA4, 0x61, 0x48, 0x64, 0x58, 0xD0, 0x59, 0xD9, + 0xFD, 0x1F, 0x25, 0xF0, 0x20, 0x64, 0xD0, 0x81, 0xFF, 0xFF, 0x02, 0x07, 0x25, 0xFA, 0x0F, 0x00, + 0x28, 0x60, 0xA8, 0x63, 0xC3, 0x83, 0x01, 0x2A, 0x06, 0x00, 0xCF, 0x83, 0xA3, 0xD3, 0xCD, 0x81, + 0x00, 0x7F, 0xBD, 0xDB, 0x04, 0x03, 0x00, 0x64, 0xC9, 0x81, 0xBD, 0xDB, 0xFD, 0x02, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x01, 0x60, 0xA6, 0x62, 0x09, 0x02, + 0xA2, 0xD9, 0x64, 0x41, 0x32, 0x44, 0x02, 0xB5, 0x00, 0xB9, 0xD4, 0x84, 0x08, 0x28, 0x02, 0xBC, + 0x40, 0x52, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x01, 0x60, + 0xB2, 0x62, 0x0C, 0x02, 0xA2, 0xD9, 0x64, 0x41, 0x32, 0x44, 0x40, 0xB5, 0x00, 0xB9, 0xD4, 0x84, + 0x08, 0x24, 0x03, 0x00, 0x40, 0xBC, 0x02, 0xB5, 0xD4, 0x84, 0x40, 0x52, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x01, 0x60, 0xB0, 0x63, 0xA3, 0xD9, 0xA9, 0xF1, 0x20, 0x61, + 0x41, 0x4B, 0x64, 0x43, 0xD8, 0xF3, 0x63, 0x45, 0x66, 0x41, 0x65, 0x46, 0x8C, 0xFA, 0x60, 0x40, + 0x01, 0x36, 0x06, 0x00, 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, 0x05, 0x3A, 0x02, 0x00, + 0x00, 0x64, 0x01, 0x00, 0x01, 0x64, 0x6F, 0xFA, 0x79, 0xF3, 0x7A, 0xF1, 0xFF, 0xFF, 0xA0, 0x84, + 0x65, 0x43, 0x02, 0x02, 0x79, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, 0xAE, 0x65, 0xD8, 0xF3, + 0xFF, 0xFF, 0xE0, 0x84, 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x04, 0x02, 0xE8, 0x84, + 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x7B, 0xFB, 0x6F, 0xF0, 0x60, 0x47, 0x90, 0x84, + 0x6F, 0xFA, 0x60, 0x47, 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, + 0xA4, 0x84, 0x70, 0xF0, 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, 0x02, 0x05, 0xDD, 0x81, + 0xFB, 0x01, 0xE1, 0x81, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x66, 0x43, 0x0C, 0xF4, + 0x2B, 0x41, 0x4D, 0x8B, 0x02, 0xA3, 0xB6, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, + 0x25, 0xF0, 0x02, 0xA8, 0x00, 0x67, 0x02, 0x02, 0x2D, 0xF9, 0x2C, 0xF9, 0x23, 0x58, 0xFF, 0xFF, + 0x28, 0x60, 0x42, 0x61, 0x23, 0xF2, 0x25, 0xF2, 0x02, 0xA8, 0x00, 0xA8, 0x09, 0x02, 0x07, 0x03, + 0xD0, 0xA0, 0x30, 0x65, 0x03, 0x04, 0xA7, 0xA0, 0x59, 0x65, 0x01, 0x06, 0x65, 0x44, 0xA1, 0xDB, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x31, 0x60, 0x2C, 0x61, 0x01, 0x64, 0xA1, 0xDB, 0x04, 0x00, + 0x31, 0x60, 0x2C, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x7E, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, + 0x7F, 0x67, 0x02, 0x61, 0x0E, 0x02, 0x06, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0x25, 0x60, 0x11, 0x78, + 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x01, 0x00, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7E, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, + 0x02, 0x61, 0x12, 0x02, 0x2D, 0x60, 0x58, 0x61, 0x65, 0x43, 0xA1, 0xDD, 0x0C, 0x61, 0x41, 0x56, + 0xC7, 0xFE, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, 0x00, 0x7F, + 0x60, 0x41, 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF0, 0x29, 0x60, + 0xA2, 0x62, 0xA2, 0xD9, 0x19, 0x00, 0x2D, 0x60, 0x1A, 0x64, 0xA0, 0xD1, 0xA0, 0xF9, 0x0C, 0x60, + 0x38, 0x62, 0x40, 0x63, 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0x64, 0x40, 0x01, 0x2A, 0x0C, 0x00, + 0x04, 0x65, 0x0C, 0x60, 0x38, 0x61, 0x48, 0x64, 0x3E, 0x63, 0x7C, 0xA8, 0x58, 0xD0, 0x59, 0xD9, + 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x29, 0x60, 0xA2, 0x62, 0xA2, 0xD1, 0x0D, 0x60, + 0x1C, 0x65, 0x02, 0xFE, 0x64, 0x44, 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x87, 0x60, 0x41, 0x64, 0x44, + 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x84, 0x3E, 0xFB, 0x60, 0x42, 0x61, 0x44, 0x03, 0xA2, 0x60, 0xFE, + 0xA2, 0xDB, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x44, 0x0C, 0x60, 0x3A, 0x65, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x84, 0x40, 0xFB, 0xFF, 0xFF, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, + 0xFF, 0xFF, 0x2D, 0x60, 0x1A, 0x64, 0xA0, 0xD1, 0xA0, 0xF9, 0x00, 0x64, 0x40, 0x41, 0x64, 0x40, + 0x01, 0x2A, 0xA4, 0x00, 0x4A, 0x64, 0xA0, 0xD2, 0xFF, 0xFF, 0x40, 0x42, 0x80, 0x2B, 0x04, 0x00, + 0xFF, 0xB4, 0x40, 0x42, 0x01, 0x64, 0x40, 0x41, 0xA9, 0xF3, 0x46, 0x4B, 0x60, 0x46, 0x20, 0x63, + 0xE3, 0x83, 0xAB, 0x46, 0x26, 0xF0, 0xAB, 0x46, 0x55, 0xF8, 0xAB, 0x46, 0x27, 0xF0, 0xAB, 0x46, + 0x56, 0xF8, 0xAB, 0x46, 0x28, 0xF0, 0xAB, 0x46, 0x57, 0xF8, 0x66, 0x44, 0x02, 0xA6, 0xF1, 0x1F, + 0xA9, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xAB, 0x46, 0x0C, 0x60, 0x7A, 0x65, 0x22, 0x44, 0xFF, 0xB4, + 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x81, 0xC9, 0x81, 0x52, 0x64, 0x0E, 0x63, + 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, 0xAB, 0x46, 0xF0, 0xA1, + 0x6E, 0x64, 0x0E, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, 0x22, 0x44, 0xFF, 0xB4, + 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x0C, 0x60, 0xDC, 0x65, 0xC4, 0x81, 0x60, 0x45, 0xC9, 0x81, + 0x62, 0x64, 0x06, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, + 0xAB, 0x46, 0xF8, 0xA1, 0xAE, 0x64, 0x06, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, + 0x65, 0x44, 0x0C, 0x60, 0xFC, 0x65, 0xC4, 0x81, 0xC9, 0x81, 0x6A, 0x64, 0x06, 0x63, 0x58, 0xD0, + 0x59, 0xD9, 0xFD, 0x1F, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x85, 0xC4, 0x84, 0x0C, 0x60, + 0xC2, 0x65, 0xC4, 0x81, 0x72, 0x64, 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0xAB, 0x46, + 0x21, 0x44, 0x01, 0x2A, 0x06, 0x00, 0xFA, 0xA1, 0x88, 0x64, 0x04, 0x63, 0x59, 0xD1, 0x58, 0xD8, + 0xFD, 0x1F, 0x37, 0xF0, 0x21, 0x44, 0x01, 0x2A, 0x13, 0x00, 0x22, 0x44, 0x3D, 0xFB, 0x60, 0x41, + 0x02, 0xFE, 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x84, 0x3C, 0xFB, 0x0C, 0x60, 0xBE, 0x63, 0x88, 0xFF, + 0xCD, 0x81, 0x06, 0xA3, 0xFD, 0x0D, 0x8D, 0xFF, 0x3B, 0xFD, 0x64, 0x47, 0x80, 0xBF, 0x60, 0x5C, + 0x22, 0x43, 0x80, 0x61, 0x88, 0xFF, 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, + 0x31, 0x91, 0xB1, 0x84, 0x37, 0xFA, 0x1F, 0x63, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0x37, 0xF0, + 0x66, 0x44, 0xB1, 0x9C, 0x37, 0xF8, 0x02, 0xA6, 0xFA, 0x1F, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, + 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x00, 0x67, 0x22, 0x02, 0x3D, 0xF1, + 0x64, 0x44, 0x03, 0xB4, 0x40, 0x42, 0xD0, 0x80, 0xA9, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xB7, 0xF4, + 0x80, 0x61, 0x02, 0x02, 0xE3, 0x83, 0xEB, 0x83, 0x22, 0x44, 0x88, 0xFF, 0xCC, 0x84, 0xE1, 0x81, + 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, 0x9D, 0x85, 0xA7, 0x83, 0x37, 0xFC, 0x1F, 0x63, + 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0xB7, 0xF2, 0x66, 0x44, 0xA5, 0x81, 0xB7, 0xFA, 0x02, 0xA6, + 0xFA, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x2D, 0x60, 0x1A, 0x64, 0xA0, 0xD1, 0xA0, 0xF9, + 0x64, 0x40, 0x01, 0x2A, 0x4E, 0x00, 0x27, 0xF2, 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, + 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, + 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, + 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA9, 0xF3, 0x08, 0xFE, 0x60, 0x43, + 0x61, 0x46, 0x01, 0x03, 0x2A, 0x00, 0x43, 0x4B, 0xAB, 0x46, 0x37, 0xF2, 0x80, 0x60, 0x30, 0x7C, + 0xB0, 0x84, 0xA2, 0xDA, 0x4E, 0x61, 0x6E, 0x64, 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, + 0x58, 0xD8, 0xFB, 0x1F, 0x88, 0x64, 0x04, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, + 0xFB, 0x1F, 0xD9, 0x81, 0x98, 0x64, 0x04, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, + 0xFB, 0x1F, 0xD9, 0x81, 0xAE, 0x64, 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, + 0xFB, 0x1F, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, + 0xFF, 0xFF, 0x2D, 0x60, 0x1A, 0x64, 0xA0, 0xD1, 0xA0, 0xF9, 0x64, 0x40, 0x01, 0x2A, 0x31, 0x00, + 0x27, 0xF2, 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, + 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, + 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, + 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, + 0x63, 0x46, 0xE8, 0x1B, 0xA9, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x0D, 0x00, + 0x43, 0x4B, 0xAB, 0x46, 0x37, 0xF2, 0x80, 0x60, 0x30, 0x61, 0x9D, 0x85, 0xA4, 0x84, 0xA2, 0xDA, + 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, + 0xFF, 0xFF, 0xA2, 0xFF, 0x46, 0x45, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0x00, 0xF4, + 0x01, 0xF2, 0x66, 0x5C, 0x25, 0x46, 0x56, 0x02, 0x70, 0x27, 0x54, 0x00, 0x12, 0x64, 0x03, 0xFA, + 0x04, 0xF8, 0x0E, 0xF2, 0x87, 0xFC, 0x8D, 0xFC, 0x8E, 0xFC, 0xDA, 0x82, 0x16, 0x61, 0x00, 0x63, + 0xC9, 0x81, 0x5A, 0xDC, 0xFD, 0x02, 0x60, 0x40, 0xF0, 0x3B, 0x16, 0x00, 0x32, 0x44, 0xAF, 0xF3, + 0x01, 0xB0, 0xFA, 0xA0, 0x08, 0x24, 0x2C, 0x05, 0xDC, 0x83, 0xF0, 0x67, 0x0E, 0xFA, 0x24, 0x60, + 0x5E, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xAF, 0xFD, 0x2B, 0xFF, + 0xFE, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x4F, 0x00, 0xB0, 0xF3, 0x06, 0x65, 0xD4, 0x80, 0xDC, 0x83, + 0x17, 0x05, 0xB0, 0xFD, 0x98, 0xFE, 0x04, 0x04, 0x00, 0x7F, 0x08, 0x7E, 0x0E, 0xFA, 0x3B, 0xFF, + 0x24, 0x60, 0x52, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0x0E, 0xF2, + 0x2B, 0xFF, 0x60, 0x40, 0x08, 0x26, 0xF7, 0xFE, 0xFD, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x32, 0x00, + 0xAC, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, 0xFF, 0xFF, 0x0D, 0x04, 0x24, 0x60, 0x6A, 0x64, 0x2B, 0xDB, + 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFC, 0x64, 0x3B, 0x42, + 0x4A, 0xDB, 0x21, 0x00, 0x46, 0x45, 0x00, 0x64, 0x2B, 0xDB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA2, 0xFF, 0x00, 0xF4, 0x01, 0xF0, 0x0A, 0x18, 0x70, 0x67, + 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, 0xC0, 0x84, 0x01, 0xFA, 0x25, 0x46, 0x25, 0x44, 0x80, 0xFC, + 0x05, 0xFA, 0xAF, 0x60, 0x58, 0x4E, 0x95, 0x78, 0xFF, 0xFF, 0xD4, 0xFE, 0xA3, 0xFF, 0xFF, 0x64, + 0x3B, 0x42, 0x4A, 0xDB, 0xD4, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0x58, 0x64, + 0x40, 0x47, 0x58, 0x4F, 0x0D, 0x00, 0x24, 0x60, 0x4C, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x18, 0x00, + 0x24, 0x60, 0x64, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x03, 0x00, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, + 0x27, 0xD5, 0x0E, 0xF2, 0x0B, 0x18, 0x60, 0x40, 0x01, 0x2A, 0x08, 0x00, 0x24, 0x60, 0x7A, 0x64, + 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0xF2, 0x01, 0x2F, 0x58, 0xFF, 0xFF, + 0x27, 0xD5, 0x0E, 0xF2, 0x14, 0x18, 0x60, 0x40, 0x01, 0x2A, 0x11, 0x00, 0x02, 0xF0, 0x09, 0x60, + 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, 0xB0, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0xB0, 0xFB, 0x24, 0x60, + 0x7A, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0xE9, 0x01, 0x2F, 0x58, + 0xFF, 0xFF, 0xFB, 0x64, 0x3A, 0x42, 0x4A, 0xDB, 0xA2, 0xFF, 0xB3, 0xF3, 0xAF, 0xF3, 0xCC, 0x80, + 0xFD, 0xA0, 0x01, 0x14, 0x1E, 0x05, 0xAE, 0x60, 0x58, 0x4D, 0x9B, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, + 0x18, 0x03, 0xF0, 0x67, 0x0E, 0xFA, 0x24, 0x60, 0x7A, 0x62, 0x24, 0x60, 0x5E, 0x64, 0xA2, 0xDB, + 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF6, 0x64, 0x3A, 0x42, + 0x4A, 0xDB, 0xB3, 0xF3, 0xAF, 0xF3, 0xCC, 0x83, 0xDC, 0x84, 0x01, 0x15, 0xB3, 0xFD, 0xAF, 0xFB, + 0xD4, 0xFE, 0xB2, 0xF3, 0xB0, 0xF3, 0x00, 0xA8, 0xB1, 0xF1, 0x03, 0x02, 0xD0, 0x80, 0xFF, 0xFF, + 0x27, 0x05, 0xAE, 0x60, 0x58, 0x4D, 0x9B, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, 0x21, 0x03, 0x00, 0x63, + 0xB2, 0xF3, 0x0E, 0xFC, 0xCC, 0x84, 0xFF, 0x3A, 0xB2, 0xFB, 0x98, 0xFE, 0x03, 0x04, 0x08, 0xBB, + 0x0E, 0xFC, 0x3B, 0xFF, 0x24, 0x60, 0x7A, 0x62, 0x24, 0x60, 0x52, 0x64, 0xA2, 0xDB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF7, 0x64, 0x3A, 0x42, 0x4A, 0xDB, + 0xB0, 0xF3, 0x0E, 0xF2, 0xDC, 0x83, 0x08, 0xB0, 0xB0, 0xFD, 0x08, 0x28, 0xF7, 0xFE, 0xD4, 0xFE, + 0xA3, 0xFF, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0xB9, 0xFE, 0x13, 0xFF, 0x24, 0x40, 0x80, 0x2B, + 0x0B, 0x00, 0xA2, 0xFF, 0x25, 0x46, 0x09, 0xF4, 0x0E, 0xF2, 0x05, 0x18, 0x08, 0xBC, 0x0E, 0xFA, + 0xFF, 0xFF, 0xF7, 0xFE, 0x01, 0x00, 0xD8, 0xFE, 0xA3, 0xFF, 0x25, 0x46, 0x3E, 0xF2, 0x00, 0xF4, + 0x08, 0xF0, 0x25, 0x46, 0x06, 0xB4, 0xFF, 0x7F, 0x10, 0xBC, 0x06, 0x26, 0xFD, 0x7F, 0x0E, 0xFA, + 0x3E, 0xF2, 0x3F, 0xF2, 0x60, 0x41, 0x08, 0x2A, 0x64, 0x47, 0x3F, 0xFA, 0x60, 0x45, 0x27, 0x60, + 0xFC, 0x62, 0xA2, 0xD3, 0xA3, 0xFC, 0xAB, 0xFC, 0x91, 0xFC, 0xD4, 0x80, 0xC0, 0x60, 0xE1, 0x65, + 0xA5, 0x80, 0x01, 0x04, 0x07, 0x03, 0x23, 0xF0, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x2E, 0x60, + 0xC5, 0x78, 0xFF, 0xFF, 0x2F, 0x60, 0x58, 0x4F, 0x0F, 0x78, 0xFF, 0xFF, 0x14, 0x04, 0x23, 0xF0, + 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xB8, 0xF1, 0x27, 0x60, 0x96, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, + 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x02, 0x00, + 0x20, 0x60, 0x00, 0x75, 0x83, 0x00, 0xDC, 0xF3, 0xA9, 0xF1, 0x07, 0xB4, 0x64, 0x43, 0xFD, 0xA0, + 0x2C, 0xF2, 0x71, 0x02, 0x01, 0xB0, 0x64, 0x43, 0x78, 0x02, 0x2E, 0xF2, 0x1C, 0x60, 0xBA, 0x65, + 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, + 0x16, 0x18, 0x61, 0x46, 0x2E, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, + 0x2D, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2C, 0xF0, 0x63, 0x46, + 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA9, 0xF3, + 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x51, 0x03, 0x63, 0x46, 0x80, 0xF6, 0x25, 0x46, 0x43, 0x18, + 0x2E, 0xF2, 0x66, 0x41, 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xA9, 0xF1, 0xE0, 0x84, + 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, + 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, + 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, + 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, + 0x43, 0x4B, 0x2C, 0xF0, 0xAD, 0xF0, 0x2E, 0xF2, 0xAB, 0x46, 0x03, 0xF8, 0x84, 0xF8, 0x05, 0xFA, + 0x03, 0x64, 0x06, 0xFA, 0xAB, 0x46, 0x1E, 0x60, 0xBC, 0x61, 0xA1, 0xD3, 0x1E, 0x60, 0xFE, 0x7C, + 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, 0x49, 0xD3, 0xFF, 0xFF, + 0xDC, 0x84, 0xA1, 0xDB, 0x0A, 0x00, 0xDC, 0xF3, 0x02, 0xA3, 0xFE, 0xA0, 0xF9, 0xA0, 0x01, 0x06, + 0x04, 0x02, 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x07, 0xFC, 0x23, 0xF2, 0xFF, 0xFF, + 0x27, 0x1B, 0x27, 0x60, 0xFE, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x00, 0x3A, 0x10, 0x00, + 0x24, 0x60, 0x7A, 0x62, 0x24, 0x60, 0x22, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xC1, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0x1F, 0x00, + 0x24, 0x60, 0x7A, 0x62, 0x24, 0x60, 0x34, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xC8, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0x0F, 0x00, + 0x24, 0x60, 0x7A, 0x62, 0x24, 0x60, 0x46, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xCE, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0x25, 0x60, + 0x11, 0x78, 0xFF, 0xFF, 0xCB, 0x84, 0xC9, 0x83, 0xFF, 0xFF, 0x08, 0x04, 0x58, 0xD1, 0xA5, 0xD8, + 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x2F, 0x58, 0xFF, 0xFF, + 0x3E, 0xF2, 0xCC, 0xF1, 0x08, 0xB0, 0x19, 0xF8, 0x3B, 0x02, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF3, + 0x30, 0xFA, 0x60, 0x45, 0xED, 0xF3, 0x31, 0xFA, 0x46, 0x4A, 0x00, 0xF4, 0x60, 0x43, 0x05, 0xF2, + 0x06, 0xF2, 0xD0, 0x80, 0x07, 0xF0, 0x05, 0x02, 0xD4, 0x80, 0xD3, 0x80, 0x02, 0x02, 0xDC, 0xF3, + 0x03, 0x03, 0xAA, 0x46, 0x42, 0xFE, 0x25, 0x00, 0x60, 0x40, 0x03, 0x2A, 0x10, 0x00, 0x02, 0xF2, + 0x03, 0xF0, 0x04, 0xF2, 0x60, 0x43, 0xAA, 0x46, 0x2C, 0xFC, 0x2D, 0xF8, 0x2E, 0xFA, 0x81, 0xF1, + 0x32, 0xF8, 0x82, 0xF1, 0x33, 0xF8, 0x83, 0xF1, 0x34, 0xF8, 0x08, 0x64, 0x10, 0x00, 0x02, 0xF2, + 0x03, 0xF0, 0x04, 0xF2, 0x60, 0x43, 0xAA, 0x46, 0x32, 0xFC, 0x33, 0xF8, 0x34, 0xFA, 0x81, 0xF1, + 0x2C, 0xF8, 0x82, 0xF1, 0x2D, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0x01, 0x60, 0x08, 0x64, 0x2A, 0xFA, + 0x02, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x03, 0x02, 0x42, 0xFF, + 0x47, 0xFF, 0xA1, 0xFF, 0x80, 0xFF, 0x90, 0xFF, 0x98, 0xFF, 0x88, 0xFF, 0x84, 0xE1, 0xFF, 0xFF, + 0x00, 0x00, 0xA1, 0xFF, 0xFF, 0xFF, 0x87, 0x3E, 0x2D, 0x60, 0x9C, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, + 0x01, 0x1B, 0xF7, 0x01, 0x87, 0xFF, 0x20, 0x44, 0x80, 0xFF, 0x60, 0x40, 0x80, 0x26, 0xF1, 0x01, + 0xC0, 0x60, 0x40, 0xEC, 0xC0, 0x60, 0x00, 0xED, 0xC0, 0x60, 0x80, 0xEE, 0xAC, 0x4F, 0xBF, 0xB4, + 0xA0, 0x5C, 0x2D, 0x60, 0x1A, 0x62, 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x02, 0x27, 0x06, 0x00, + 0x28, 0xE2, 0x24, 0xE2, 0xBF, 0xFF, 0xFF, 0xFF, 0x75, 0x40, 0x10, 0x00, 0x28, 0xE2, 0x24, 0xE2, + 0x00, 0x60, 0x00, 0x61, 0x00, 0x60, 0x94, 0xE0, 0xBF, 0xFF, 0xFF, 0xFF, 0xA1, 0x50, 0x75, 0x40, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0xE0, 0x2D, 0x60, 0x9C, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, 0x39, 0xE2, 0x04, 0x60, 0x00, 0x7A, 0xAC, 0x4F, 0x40, 0xBC, + 0x00, 0x7F, 0xA0, 0x5C, 0xC0, 0x60, 0xD9, 0xEC, 0xC0, 0x60, 0x0F, 0xED, 0xC0, 0x60, 0x8F, 0xEE, + 0xAE, 0x4F, 0x04, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x26, 0x61, 0xCD, 0x81, 0xFF, 0xFF, 0xFD, 0x02, + 0xAE, 0x4F, 0xFB, 0xB4, 0xA0, 0x5E, 0xAD, 0x01, 0x80, 0xFF, 0x90, 0xFF, 0x98, 0xFF, 0x2F, 0x60, + 0x54, 0x63, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, 0x23, 0x44, + 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, 0x27, 0x44, + 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, 0x2B, 0x44, + 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, 0x2F, 0x44, + 0xBD, 0xDB, 0x2F, 0x60, 0x48, 0x64, 0xA0, 0xDD, 0x30, 0x60, 0x74, 0x63, 0x2F, 0x60, 0x4A, 0x64, + 0xA0, 0xDD, 0x2F, 0x60, 0x4C, 0x63, 0x30, 0x44, 0xA3, 0xDB, 0x2F, 0x60, 0x4E, 0x63, 0x31, 0x44, + 0xA3, 0xDB, 0x2F, 0x60, 0x50, 0x63, 0x32, 0x44, 0xA3, 0xDB, 0x2F, 0x60, 0x52, 0x63, 0x33, 0x44, + 0xA3, 0xDB, 0x81, 0xFF, 0x91, 0xFF, 0x58, 0x51, 0x4B, 0x00, 0x82, 0xFF, 0x92, 0xFF, 0x58, 0x51, + 0x47, 0x00, 0x83, 0xFF, 0x93, 0xFF, 0x58, 0x51, 0x43, 0x00, 0x84, 0xFF, 0x94, 0xFF, 0x58, 0x51, + 0x3F, 0x00, 0x85, 0xFF, 0x95, 0xFF, 0x58, 0x51, 0x3B, 0x00, 0x86, 0xFF, 0x96, 0xFF, 0x58, 0x51, + 0x37, 0x00, 0x87, 0xFF, 0x97, 0xFF, 0x58, 0x51, 0x33, 0x00, 0x80, 0xFF, 0x90, 0xFF, 0x99, 0xFF, + 0x2F, 0x60, 0x48, 0x64, 0xA0, 0xD1, 0x30, 0x44, 0x64, 0x43, 0xBD, 0xDB, 0x31, 0x44, 0xBD, 0xDB, + 0x32, 0x44, 0xBD, 0xDB, 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, 0x35, 0x44, 0xBD, 0xDB, + 0x36, 0x44, 0xBD, 0xDB, 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, 0x39, 0x44, 0xBD, 0xDB, + 0x3A, 0x44, 0xBD, 0xDB, 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, 0x3D, 0x44, 0xBD, 0xDB, + 0x3E, 0x44, 0xBD, 0xDB, 0x3F, 0x44, 0xBD, 0xDB, 0xEF, 0x60, 0x48, 0x64, 0x0A, 0xFB, 0x40, 0x21, + 0xFE, 0x01, 0x80, 0xFF, 0x90, 0xFF, 0x98, 0xFF, 0x88, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x87, 0x3E, + 0x42, 0x50, 0x40, 0x53, 0x2F, 0x60, 0x4A, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x52, 0x33, 0x44, + 0x32, 0x42, 0xA2, 0xDB, 0xDA, 0x82, 0xA2, 0xDD, 0xDA, 0x83, 0x65, 0x44, 0xBD, 0xDB, 0x61, 0x44, + 0xBD, 0xDB, 0x66, 0x44, 0xBD, 0xDB, 0xBD, 0xD9, 0x30, 0x44, 0xBD, 0xDB, 0x99, 0xFF, 0xA4, 0x4C, + 0xBD, 0xDB, 0xA5, 0x4C, 0xBD, 0xDB, 0xA0, 0x4C, 0xBD, 0xDB, 0xA1, 0x4C, 0xBD, 0xDB, 0x98, 0xFF, + 0x2F, 0x60, 0x4A, 0x64, 0xA0, 0xDD, 0x2F, 0x60, 0x4C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x50, + 0x2F, 0x60, 0x50, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x52, 0x2F, 0x60, 0x52, 0x62, 0xA2, 0xD3, + 0xFF, 0xFF, 0x40, 0x53, 0x31, 0x41, 0x2F, 0x60, 0x4E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x51, + 0x2F, 0x60, 0x48, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x43, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, + 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, + 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, + 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, + 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, 0x2F, 0x44, 0xBD, 0xDB, 0x2F, 0x60, 0x48, 0x64, 0xA0, 0xDD, + 0x61, 0x58, 0xFF, 0xFF, 0x24, 0xE2, 0x2D, 0xF3, 0x2C, 0xF3, 0x00, 0xBD, 0xCC, 0x84, 0x08, 0x03, + 0x2C, 0xFB, 0x06, 0x02, 0x65, 0x44, 0x2C, 0xFB, 0x8A, 0xFF, 0x80, 0x60, 0x00, 0x75, 0x88, 0xFF, + 0xF2, 0xF3, 0x31, 0x40, 0x01, 0x2A, 0x44, 0x00, 0x60, 0x43, 0x04, 0xB0, 0x02, 0xB0, 0x08, 0x24, + 0x16, 0x02, 0x29, 0x44, 0xFF, 0xFF, 0x00, 0xA8, 0xCC, 0x81, 0x0E, 0x03, 0x41, 0x49, 0x37, 0x02, + 0x63, 0x40, 0x08, 0x2A, 0x09, 0x00, 0xF7, 0xB3, 0x31, 0x60, 0x1E, 0x7C, 0xA4, 0xD1, 0xAD, 0x4F, + 0xFD, 0xB4, 0xA0, 0x5D, 0x44, 0x49, 0x2B, 0x00, 0x63, 0x40, 0x02, 0x2A, 0x14, 0x00, 0x31, 0x60, + 0x20, 0x64, 0xA0, 0xD3, 0x31, 0x60, 0x1C, 0x7C, 0xA4, 0xDB, 0x40, 0x49, 0x31, 0x60, 0x22, 0x64, + 0xA0, 0xD3, 0x31, 0x60, 0x1E, 0x7C, 0xA4, 0xDB, 0x0C, 0xBB, 0xFD, 0xB3, 0xAD, 0x4F, 0x02, 0xBC, + 0x00, 0x7F, 0xA0, 0x5D, 0x14, 0x00, 0x31, 0x60, 0x24, 0x64, 0xA0, 0xD3, 0x31, 0x60, 0x1C, 0x7C, + 0x0E, 0x18, 0xA4, 0xDB, 0x40, 0x49, 0x31, 0x60, 0x26, 0x64, 0xA0, 0xD3, 0x31, 0x60, 0x1E, 0x7C, + 0xA4, 0xDB, 0x08, 0xBB, 0xFB, 0xB3, 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0xF2, 0xFD, + 0x01, 0x60, 0x4E, 0x61, 0xA1, 0xD3, 0x61, 0x43, 0x17, 0x18, 0x58, 0xD3, 0x62, 0x41, 0x03, 0x18, + 0xCC, 0x84, 0xA1, 0xDB, 0x11, 0x00, 0x49, 0xD3, 0xA3, 0xDB, 0x06, 0xA1, 0xA1, 0xD3, 0x59, 0xD1, + 0x60, 0x45, 0xA5, 0xD3, 0x59, 0xD1, 0xB0, 0x84, 0xA5, 0xDB, 0x64, 0x44, 0x06, 0x36, 0xCD, 0xFE, + 0x07, 0x36, 0xD6, 0xFE, 0xE5, 0x01, 0x23, 0x46, 0xB0, 0x60, 0xA4, 0x78, 0xFF, 0xFF, 0x46, 0x43, + 0x24, 0x60, 0xA4, 0x61, 0xA1, 0xD3, 0x59, 0xD1, 0x06, 0x1B, 0x59, 0xD3, 0x59, 0xD1, 0x03, 0x1B, + 0x59, 0xD3, 0x59, 0xD1, 0xF0, 0x18, 0x00, 0x63, 0x49, 0xDD, 0x60, 0x40, 0x02, 0x36, 0x11, 0x00, + 0x03, 0x36, 0x32, 0x00, 0x01, 0x36, 0x08, 0x00, 0x05, 0x3A, 0xEA, 0x01, 0xA4, 0xD3, 0x5A, 0xD3, + 0x9C, 0x85, 0xA4, 0x84, 0xA2, 0xDB, 0xE4, 0x01, 0x01, 0x60, 0x4E, 0x61, 0x00, 0x64, 0xA1, 0xDB, + 0xDF, 0x01, 0x31, 0x60, 0x3C, 0x64, 0x40, 0x45, 0x22, 0x00, 0x01, 0x60, 0x4E, 0x66, 0xA6, 0xD3, + 0x04, 0xA1, 0x60, 0x43, 0xA1, 0xD3, 0xC9, 0x81, 0x60, 0x45, 0x00, 0xBB, 0xA1, 0xDB, 0xBE, 0xD3, + 0x09, 0x03, 0xD4, 0x84, 0x9C, 0x84, 0xDC, 0x84, 0xFF, 0xFF, 0x04, 0x0E, 0xA3, 0xD1, 0x63, 0x46, + 0x64, 0x43, 0xF2, 0x01, 0x9C, 0x84, 0xDC, 0x85, 0x49, 0xDD, 0x61, 0x44, 0x00, 0xBB, 0xA6, 0xDB, + 0x02, 0x03, 0x65, 0x44, 0xBE, 0xDB, 0xBC, 0x01, 0x31, 0x60, 0x17, 0x64, 0x40, 0x45, 0x01, 0x60, + 0x4E, 0x66, 0xA6, 0xD3, 0xFF, 0xFF, 0xD0, 0x80, 0x0F, 0x18, 0x02, 0x03, 0x60, 0x46, 0xF9, 0x01, + 0x58, 0xD3, 0xA4, 0xD3, 0x60, 0x45, 0x00, 0x63, 0xA4, 0xDD, 0x05, 0x18, 0x58, 0xD3, 0xFF, 0xFF, + 0xC4, 0x83, 0xA2, 0xDD, 0xCA, 0x84, 0xA6, 0xDB, 0x25, 0x58, 0x64, 0x41, 0x00, 0x60, 0x46, 0x74, + 0xCD, 0xE2, 0x04, 0xE1, 0x02, 0x60, 0x00, 0xE1, 0x3F, 0x44, 0x40, 0x26, 0x0B, 0x00, 0x01, 0x2A, + 0x05, 0x00, 0x42, 0x60, 0x09, 0xE0, 0x60, 0x60, 0x1C, 0xE0, 0x04, 0x00, 0x42, 0x60, 0x09, 0xE0, + 0x80, 0x60, 0x1C, 0xE0, 0x04, 0x29, 0xFE, 0x01, 0xC4, 0xE2, 0x43, 0x64, 0x3A, 0xDB, 0xA4, 0xF3, + 0xFF, 0xFF, 0x60, 0x41, 0x3F, 0x44, 0x02, 0x27, 0x84, 0x00, 0x20, 0x2B, 0xFF, 0x01, 0x80, 0xE1, + 0x95, 0x60, 0x80, 0xE7, 0x61, 0x40, 0x40, 0x2B, 0x0D, 0x00, 0x05, 0x63, 0x32, 0x60, 0x58, 0x4F, + 0x6A, 0x78, 0xFF, 0xFF, 0x28, 0x63, 0xFF, 0xFF, 0xFE, 0x1F, 0x01, 0x63, 0x32, 0x60, 0x58, 0x4F, + 0x6A, 0x78, 0xFF, 0xFF, 0xFF, 0xB1, 0xCD, 0x81, 0xE1, 0x85, 0x27, 0x60, 0x3C, 0x64, 0x44, 0xD1, + 0xFF, 0xFF, 0x64, 0x43, 0x32, 0x60, 0x58, 0x4F, 0x6A, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x00, 0x63, + 0x32, 0x60, 0x58, 0x4F, 0x6A, 0x78, 0xFF, 0xFF, 0x27, 0x60, 0x58, 0x61, 0x29, 0x60, 0xE8, 0x62, + 0xA2, 0xD3, 0x45, 0xD1, 0x47, 0xBC, 0xE0, 0x84, 0x62, 0x45, 0x64, 0x5F, 0xE8, 0x83, 0x32, 0x60, + 0x58, 0x4F, 0x6A, 0x78, 0xFF, 0xFF, 0xA3, 0xF3, 0xCD, 0xE2, 0x60, 0x54, 0x04, 0xE1, 0x04, 0x29, + 0xFE, 0x01, 0xC4, 0xE2, 0x15, 0x60, 0xA2, 0xE7, 0x38, 0x69, 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x16, + 0xFD, 0x01, 0x01, 0x2A, 0x36, 0x00, 0x03, 0x60, 0x80, 0x7C, 0xA3, 0x83, 0x29, 0x60, 0xE8, 0x62, + 0xA2, 0xD1, 0x43, 0xBB, 0xB3, 0x83, 0x95, 0x60, 0x80, 0xE7, 0x32, 0x60, 0x58, 0x4F, 0x6A, 0x78, + 0xFF, 0xFF, 0xE3, 0x83, 0x15, 0x60, 0xA2, 0xE7, 0x38, 0x69, 0xFF, 0xFF, 0x68, 0x41, 0x01, 0x16, + 0xFD, 0x01, 0x63, 0x47, 0x61, 0x40, 0x01, 0x2A, 0x03, 0x00, 0x00, 0x3A, 0xCC, 0x84, 0x02, 0x00, + 0x07, 0x3A, 0xDC, 0x84, 0xFF, 0xB4, 0xA5, 0xDB, 0x60, 0x47, 0xE8, 0x84, 0x47, 0x65, 0x29, 0x60, + 0xE8, 0x62, 0xA2, 0xD3, 0xB4, 0x85, 0xB4, 0x83, 0x80, 0xE1, 0x95, 0x60, 0x80, 0xE7, 0x32, 0x60, + 0x58, 0x4F, 0x6A, 0x78, 0xFF, 0xFF, 0xA3, 0xF3, 0xCD, 0xE2, 0x60, 0x54, 0x04, 0x29, 0xFE, 0x01, + 0xC4, 0xE2, 0xA4, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x2B, 0x04, 0x00, 0x32, 0x60, 0x43, 0x78, + 0xFF, 0xFF, 0xFF, 0x01, 0xA4, 0xF3, 0x80, 0xE1, 0xCC, 0x84, 0xE0, 0x85, 0x15, 0x60, 0xA2, 0xE7, + 0x26, 0x60, 0x78, 0x64, 0x58, 0x4F, 0x4F, 0x00, 0x26, 0x60, 0x94, 0x64, 0x58, 0x4F, 0x4B, 0x00, + 0x26, 0x60, 0xB0, 0x64, 0x58, 0x4F, 0x47, 0x00, 0x26, 0x60, 0xCC, 0x64, 0x58, 0x4F, 0x43, 0x00, + 0x26, 0x60, 0xE8, 0x64, 0x58, 0x4F, 0x3F, 0x00, 0x27, 0x60, 0x04, 0x64, 0x58, 0x4F, 0x3B, 0x00, + 0x27, 0x60, 0x20, 0x64, 0x58, 0x4F, 0x37, 0x00, 0x01, 0x68, 0xFF, 0x6A, 0xFF, 0xFF, 0x01, 0x16, + 0xFE, 0x01, 0x3F, 0x44, 0x20, 0x27, 0x00, 0x00, 0x3F, 0x40, 0x40, 0x26, 0x08, 0x00, 0x00, 0x60, + 0x18, 0x64, 0x00, 0x60, 0x00, 0x65, 0x94, 0x84, 0xA0, 0x50, 0x1D, 0x60, 0x19, 0xE2, 0xC4, 0xE2, + 0x00, 0x63, 0xA3, 0xFD, 0x32, 0x7B, 0x4D, 0xE2, 0xBF, 0xFE, 0xC4, 0xE2, 0x41, 0xFF, 0xE0, 0xFE, + 0xE1, 0xFE, 0xE2, 0xFE, 0x43, 0xFF, 0x44, 0xFF, 0x46, 0xFF, 0xA5, 0xF3, 0x62, 0xFF, 0x60, 0x40, + 0x05, 0x36, 0x2D, 0xFF, 0x07, 0x36, 0xD5, 0xFE, 0x08, 0xE1, 0x88, 0x60, 0x85, 0x71, 0x8D, 0xE2, + 0xA2, 0x60, 0x16, 0x78, 0xFF, 0xFF, 0x50, 0xEC, 0x63, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, + 0x40, 0xEC, 0x2F, 0x58, 0xFF, 0xFF, 0x44, 0xD3, 0x80, 0x7C, 0x60, 0x48, 0x60, 0x47, 0x00, 0x7F, + 0xB0, 0x8A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0x42, 0xFF, 0x40, 0xFF, + 0xDD, 0xFE, 0xAD, 0x4F, 0x00, 0x7F, 0x01, 0xBC, 0xA0, 0x5D, 0x00, 0xEE, 0x19, 0x61, 0xCD, 0x81, + 0xFF, 0xFF, 0xFD, 0x02, 0x43, 0x45, 0x20, 0x44, 0x60, 0xBC, 0x40, 0x40, 0x02, 0x60, 0xEE, 0x63, + 0x7F, 0xF3, 0xA3, 0xFD, 0x40, 0x7F, 0xA4, 0xFB, 0x05, 0x64, 0xA5, 0xFB, 0xDF, 0xFE, 0x19, 0xFF, + 0x24, 0x60, 0xDD, 0x64, 0x3F, 0x40, 0x01, 0x2B, 0x02, 0x00, 0x32, 0x60, 0xA2, 0x64, 0xA6, 0xFB, + 0xBB, 0x60, 0x20, 0x78, 0xFF, 0xFF, 0x04, 0xEE, 0xAD, 0x4F, 0x00, 0x7F, 0x01, 0xBC, 0xA0, 0x5D, + 0x19, 0x61, 0xCD, 0x81, 0xFF, 0xFF, 0xFD, 0x02, 0xAD, 0x4F, 0x00, 0x7F, 0x01, 0xBC, 0xA0, 0x5D, + 0x00, 0xEE, 0x15, 0x60, 0xA2, 0xE7, 0x25, 0x60, 0x02, 0x63, 0x25, 0x60, 0x76, 0x65, 0xDF, 0xFE, + 0x80, 0xE1, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x48, 0x60, 0x47, 0x80, 0xBC, 0x00, 0x7F, 0x60, 0x4A, + 0xD7, 0x80, 0xA1, 0xFF, 0xFF, 0xFF, 0xF5, 0x02, 0x25, 0x60, 0x76, 0x63, 0x26, 0x60, 0x78, 0x65, + 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x48, 0x60, 0x47, 0x80, 0xBC, 0x00, 0x7F, 0x60, 0x4A, 0xD7, 0x80, + 0xA1, 0xFF, 0xFF, 0xFF, 0xF5, 0x02, 0x3F, 0x40, 0x20, 0x2B, 0x00, 0x00, 0x01, 0x68, 0xFF, 0x6A, + 0xBF, 0xFE, 0x33, 0x60, 0x8A, 0x78, 0xFF, 0xFF, 0x3F, 0x40, 0x20, 0x2B, 0xAD, 0x00, 0x01, 0x16, + 0xFE, 0x01, 0x38, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x2A, 0xA5, 0x00, 0x27, 0x60, + 0xB4, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x7F, 0xF1, + 0x80, 0x60, 0x00, 0x64, 0xB0, 0x9C, 0x01, 0x00, 0x7F, 0xF1, 0xDD, 0xFE, 0xAD, 0x4F, 0x00, 0x7F, + 0x01, 0xBC, 0xA0, 0x5D, 0x00, 0xEE, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x02, 0x60, + 0xEE, 0x64, 0xA3, 0xFB, 0xA4, 0xF9, 0x05, 0x64, 0xA5, 0xFB, 0xDF, 0xFE, 0x19, 0xFF, 0x83, 0x00, + 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x43, 0x45, 0xA4, 0xD1, 0xDA, 0x83, 0xC3, 0x85, 0x80, 0xE1, + 0xDF, 0xFE, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x48, 0x60, 0x47, 0x80, 0xBC, 0x00, 0x7F, 0x60, 0x4A, + 0xD7, 0x80, 0xA1, 0xFF, 0xF6, 0x02, 0xBF, 0xFE, 0x6E, 0x00, 0x3F, 0x40, 0x40, 0x26, 0x13, 0x00, + 0x0B, 0x60, 0xF8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x10, 0x64, 0x90, 0x84, 0xA0, 0x50, 0xF8, 0xA2, + 0xA2, 0xD1, 0x0A, 0x60, 0x19, 0x64, 0x90, 0x84, 0xA0, 0x52, 0x06, 0xA2, 0xA2, 0xD1, 0x46, 0x60, + 0x09, 0x64, 0x90, 0x84, 0xA0, 0x50, 0xAD, 0x4F, 0xFE, 0xB4, 0xA0, 0x5D, 0xAD, 0x4F, 0xFD, 0xB4, + 0xA0, 0x5D, 0x02, 0xEE, 0xBD, 0xFE, 0x50, 0x00, 0x80, 0xE1, 0x01, 0x16, 0xFE, 0x01, 0x64, 0x48, + 0x92, 0x6A, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x40, 0x27, 0x60, 0xA2, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, + 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x3F, 0x00, 0x80, 0xE1, 0x01, 0x16, 0xFE, 0x01, + 0x01, 0x68, 0xA7, 0x6A, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x40, 0x36, 0x00, 0x20, 0x44, 0x20, 0xBC, + 0x40, 0x40, 0x80, 0xE1, 0x64, 0x46, 0x01, 0x16, 0xFE, 0x01, 0x21, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, + 0x68, 0x5E, 0x01, 0x16, 0xFE, 0x01, 0x22, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x5F, 0x26, 0xFA, + 0x1C, 0xF2, 0x01, 0x16, 0xFE, 0x01, 0x3A, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x5F, 0x27, 0xFA, + 0x1B, 0x00, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x43, 0x45, 0xBE, 0xD5, 0xA4, 0xD2, 0x5A, 0x86, + 0xEF, 0xA0, 0x11, 0x61, 0x01, 0x06, 0x60, 0x41, 0x24, 0x60, 0xE0, 0x63, 0x80, 0xE1, 0xBD, 0xD3, + 0x26, 0x42, 0x01, 0x16, 0xFE, 0x01, 0x60, 0x49, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x44, 0xCD, 0x81, + 0xA2, 0xDA, 0x5A, 0x86, 0xF4, 0x02, 0x25, 0x43, 0x21, 0xE1, 0x00, 0x64, 0xBF, 0xDB, 0x20, 0x44, + 0x20, 0x2A, 0x07, 0x00, 0x07, 0xB4, 0x04, 0x36, 0xC3, 0xFE, 0x06, 0x36, 0xCC, 0xFE, 0x07, 0x36, + 0xD5, 0xFE, 0x20, 0x44, 0xD8, 0xB4, 0x40, 0x40, 0x20, 0x44, 0x40, 0x2A, 0x07, 0x00, 0x9F, 0xFE, + 0x1E, 0x05, 0xBF, 0xB4, 0x40, 0x40, 0xA6, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x24, 0x60, 0x80, 0x63, + 0xBD, 0xD3, 0x02, 0x61, 0x17, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x02, 0x61, 0x13, 0x1B, 0x04, 0xA3, + 0xBD, 0xD3, 0x02, 0x61, 0x0F, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x04, 0x61, 0x0B, 0x1B, 0x04, 0xA3, + 0xBD, 0xD3, 0x06, 0x61, 0x07, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x07, 0x61, 0x03, 0x1B, 0xBB, 0x60, + 0x20, 0x78, 0xFF, 0xFF, 0xA3, 0xD1, 0x40, 0x44, 0x20, 0x44, 0x07, 0xB5, 0xD4, 0x85, 0x35, 0x80, + 0x24, 0x45, 0x24, 0x60, 0xBC, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xE1, 0x43, 0x45, + 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x64, 0x43, 0xBD, 0xD3, 0xBD, 0xD1, 0x40, 0x44, 0x10, 0x27, + 0x10, 0x00, 0xFF, 0x60, 0x7F, 0x65, 0x15, 0x60, 0xA2, 0x64, 0x24, 0x40, 0x08, 0x2B, 0xA4, 0x84, + 0xA0, 0x57, 0xFF, 0xFF, 0x64, 0x49, 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x16, 0xFD, 0x01, 0x00, 0x7F, + 0xA3, 0xDB, 0xA1, 0x01, 0x80, 0xE1, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x64, 0x43, + 0xBD, 0xD3, 0xBD, 0xD1, 0x40, 0x44, 0x10, 0x2B, 0x11, 0x00, 0xA3, 0xD3, 0xFF, 0xFF, 0x15, 0x60, + 0x80, 0xE7, 0x24, 0x40, 0x07, 0x27, 0x02, 0x00, 0x50, 0xEC, 0x00, 0x00, 0x60, 0x4A, 0xFF, 0xFF, + 0x01, 0x16, 0xFE, 0x01, 0x24, 0x40, 0x20, 0x2B, 0x40, 0xEC, 0x0F, 0x00, 0x15, 0x60, 0x22, 0x64, + 0x24, 0x40, 0x08, 0x27, 0x80, 0xBC, 0xA3, 0xD3, 0xA0, 0x57, 0x60, 0x48, 0x64, 0x44, 0x80, 0xBC, + 0xFF, 0xB4, 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x75, 0x01, 0x42, 0x6F, 0x6F, 0x74, + 0x63, 0x6F, 0x64, 0x65, 0x20, 0x21, 0x21, 0x20, 0x20, 0x00, 0x53, 0x54, 0x41, 0x2F, 0x41, 0x50, + 0x20, 0x46, 0x75, 0x6E, 0x63, 0x27, 0x73, 0x00, 0x1F, 0x00, 0x03, 0x00, 0x02, 0x00, 0x24, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x07, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x07, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x40, 0x00, 0x32, 0x00, 0x32, 0x00, 0x0A, 0x00, 0x02, 0x00, 0x06, 0x00, 0x40, 0x00, + 0x32, 0x00, 0x36, 0x00, 0x0A, 0x00, 0x02, 0x00, 0x06, 0x00, 0x40, 0x00, 0x3B, 0x00, 0x40, 0x00, + 0x17, 0x00, 0x07, 0x00, 0x07, 0x00, 0x4A, 0x00, 0x40, 0x00, 0x4A, 0x00, 0x1E, 0x00, 0x0C, 0x00, + 0x08, 0x00, 0x57, 0x00, 0x4D, 0x00, 0x57, 0x00, 0x2B, 0x00, 0x19, 0x00, 0x08, 0x00, 0x5D, 0x00, + 0x53, 0x00, 0x5D, 0x00, 0x31, 0x00, 0x1F, 0x00, 0x08, 0x00, 0xA9, 0xF3, 0x21, 0x61, 0x00, 0x7C, + 0x01, 0x00, 0x00, 0xFA, 0x60, 0x46, 0xFE, 0x63, 0xA3, 0xD8, 0xFE, 0x1F, 0xCD, 0x81, 0xD8, 0x84, + 0xF8, 0x02, 0x21, 0x61, 0x80, 0x67, 0x40, 0x4A, 0xA9, 0xF5, 0x14, 0x60, 0x02, 0x65, 0x01, 0x7C, + 0x07, 0x18, 0x2A, 0x43, 0x02, 0xFC, 0x5F, 0x8A, 0x8E, 0xF8, 0x70, 0xF8, 0x00, 0xF4, 0xF8, 0x01, + 0x2E, 0x58, 0xFF, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x0A, 0x00, 0x42, 0x60, 0x09, 0xE0, 0x3F, 0x40, + 0x01, 0x2A, 0x03, 0x00, 0x60, 0x60, 0x1C, 0xE0, 0x02, 0x00, 0x80, 0x60, 0x1C, 0xE0, 0x40, 0xEC, + 0x00, 0xED, 0x02, 0xEE, 0x80, 0x60, 0x58, 0xEC, 0x80, 0x60, 0x00, 0xED, 0x80, 0x60, 0x82, 0xEE, + 0xC0, 0x60, 0x59, 0xEC, 0xC0, 0x60, 0x07, 0xED, 0xAD, 0x4F, 0xFE, 0xB4, 0xA0, 0x5D, 0x00, 0xF3, + 0x28, 0xFB, 0x40, 0x44, 0x2F, 0x60, 0x52, 0x7C, 0x20, 0xF9, 0xA2, 0x60, 0x00, 0x7C, 0x21, 0xF9, + 0xA2, 0x60, 0xE0, 0x7C, 0x22, 0xF9, 0x18, 0x60, 0x97, 0x7C, 0x23, 0xF9, 0x18, 0x60, 0xA8, 0x7C, + 0x24, 0xF9, 0x18, 0x60, 0xD2, 0x7C, 0x25, 0xF9, 0x18, 0x60, 0xE3, 0x7C, 0x26, 0xF9, 0x91, 0x60, + 0x00, 0xE8, 0x28, 0xE8, 0x44, 0x60, 0x02, 0xE6, 0x10, 0x67, 0x40, 0x52, 0x10, 0x60, 0x04, 0xE6, + 0x08, 0x60, 0x00, 0x63, 0xFA, 0x60, 0x00, 0x65, 0xBD, 0xD3, 0xBD, 0xD3, 0x02, 0xA8, 0xD4, 0x80, + 0x4A, 0x02, 0x49, 0x02, 0xDB, 0x83, 0xFA, 0x60, 0x27, 0x65, 0x5B, 0xD3, 0xBF, 0xD1, 0x1A, 0x18, + 0xC3, 0x83, 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xDB, 0x83, 0xD3, 0x83, 0xD3, 0x86, 0x64, 0x41, + 0xCD, 0x81, 0xA6, 0xD1, 0xDA, 0x86, 0x25, 0x60, 0x02, 0x65, 0x00, 0x60, 0x72, 0x63, 0xA5, 0xD3, + 0xDA, 0x85, 0x90, 0x84, 0xFF, 0x27, 0x02, 0x00, 0xA2, 0xD9, 0x01, 0x00, 0xF8, 0x1F, 0xCD, 0x81, + 0xFF, 0xFF, 0xEF, 0x02, 0x08, 0x60, 0x06, 0x63, 0xFA, 0x60, 0x28, 0x65, 0x5B, 0xD3, 0xBF, 0xD1, + 0x0B, 0x18, 0xC3, 0x83, 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xBF, 0xD3, 0x29, 0x60, 0xE8, 0x62, + 0x0E, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0xA2, 0xDB, 0x08, 0x60, 0x06, 0x63, 0xFD, 0x60, 0x0C, 0x65, + 0x5B, 0xD3, 0xBF, 0xD1, 0x10, 0x18, 0xC3, 0x83, 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xFA, 0xA3, + 0xA3, 0xD3, 0x02, 0x60, 0x00, 0x65, 0xF7, 0xA0, 0xFC, 0xA0, 0x0D, 0x05, 0x04, 0x05, 0x78, 0x43, + 0x02, 0x61, 0x24, 0x60, 0xDD, 0x78, 0x21, 0x60, 0x00, 0x65, 0x3F, 0x43, 0x3F, 0x43, 0x21, 0x60, + 0x00, 0x65, 0xC0, 0x60, 0x8F, 0xEE, 0xB7, 0x84, 0x40, 0x5F, 0x00, 0x60, 0x30, 0xE2, 0x00, 0x60, + 0x50, 0xE2, 0x00, 0x60, 0x79, 0xE2, 0x00, 0x60, 0x90, 0xE2, 0x01, 0x60, 0xD0, 0xE2, 0x01, 0x60, + 0xF0, 0xE2, 0x01, 0x60, 0xB0, 0xE2, 0x26, 0x64, 0x35, 0xFB, 0x01, 0x60, 0x30, 0x64, 0x0A, 0xA4, + 0x38, 0xFB, 0x60, 0x45, 0x00, 0x60, 0xF8, 0x64, 0x0A, 0xA4, 0x39, 0xFB, 0x35, 0xF1, 0x0A, 0x64, + 0xC4, 0x84, 0x36, 0xFB, 0xC0, 0x84, 0x0A, 0xA4, 0x37, 0xFB, 0x09, 0x60, 0x2A, 0x64, 0xB9, 0xFB, + 0x82, 0xFF, 0x92, 0xFF, 0x5C, 0x41, 0x5C, 0x46, 0x5C, 0x47, 0x00, 0xE1, 0xA3, 0x60, 0x4B, 0x63, + 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x87, 0xFF, 0x97, 0xFF, 0x0C, 0x60, 0x02, 0x64, 0x40, 0x5A, + 0x06, 0xA4, 0x40, 0x5B, 0x5C, 0x5E, 0x5C, 0x51, 0x28, 0x60, 0x44, 0x62, 0xA2, 0xD3, 0x7F, 0xFB, + 0x2D, 0x60, 0xCC, 0x61, 0x27, 0x7C, 0xA1, 0xD9, 0x6D, 0x60, 0x1C, 0x63, 0x7F, 0xA3, 0xE3, 0x87, + 0x00, 0x7F, 0xAA, 0xFB, 0x02, 0x60, 0x7F, 0x64, 0x00, 0x60, 0x42, 0x65, 0xD4, 0x84, 0xAB, 0xFB, + 0xDC, 0x84, 0xA9, 0xFB, 0x24, 0x60, 0x0E, 0x62, 0xA2, 0xDB, 0x34, 0x60, 0x58, 0x4E, 0x64, 0x78, + 0xFF, 0xFF, 0xAB, 0xF1, 0xAA, 0xF3, 0x7C, 0x63, 0xAD, 0xFB, 0x60, 0x46, 0x01, 0xFC, 0xDC, 0x84, + 0xD0, 0x80, 0x00, 0xFA, 0xFA, 0x04, 0xAE, 0xFB, 0x60, 0x46, 0x00, 0x64, 0x00, 0xFA, 0x63, 0x44, + 0x80, 0x7F, 0x01, 0xFA, 0xAB, 0xF3, 0xAA, 0xF1, 0xDC, 0x84, 0xD0, 0x84, 0xAC, 0xFB, 0x03, 0x60, + 0x26, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xB1, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x2E, 0xFB, 0x82, 0xFF, + 0x40, 0x42, 0x87, 0xFF, 0xAC, 0xF3, 0xB4, 0xFB, 0x08, 0x60, 0x00, 0x63, 0xFA, 0x60, 0x00, 0x65, + 0xBD, 0xD3, 0xA3, 0xD3, 0x02, 0xA8, 0xD4, 0x80, 0x24, 0x02, 0x23, 0x02, 0x2D, 0x60, 0x1A, 0x62, + 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x80, 0x26, 0x1C, 0x00, 0x04, 0xA3, 0xFD, 0x60, 0x0D, 0x65, + 0x5B, 0xD3, 0xBF, 0xD1, 0x16, 0x18, 0xC3, 0x83, 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xBF, 0xD3, + 0xAD, 0x49, 0xFE, 0xA0, 0x00, 0x64, 0x0E, 0x04, 0x08, 0xB1, 0x20, 0xBC, 0x08, 0x28, 0x18, 0xBC, + 0x1C, 0x60, 0xB8, 0x63, 0x07, 0x7C, 0xA3, 0xD9, 0x1C, 0x60, 0xB6, 0x63, 0x05, 0x7C, 0xA3, 0xD9, + 0x01, 0x00, 0x00, 0x64, 0x1C, 0x60, 0xB4, 0x63, 0xA3, 0xDB, 0x00, 0x64, 0x40, 0x50, 0x63, 0xFF, + 0x60, 0xFF, 0x66, 0xFF, 0x65, 0xFF, 0x64, 0xFF, 0x61, 0xFF, 0x62, 0xFF, 0x49, 0x60, 0x02, 0xE1, + 0x52, 0x60, 0x02, 0xE1, 0x5B, 0x60, 0x02, 0xE1, 0x65, 0x60, 0x02, 0xE1, 0x6C, 0x60, 0x02, 0xE1, + 0x76, 0x60, 0x02, 0xE1, 0x41, 0x60, 0x02, 0xE1, 0x04, 0x65, 0x2D, 0x60, 0x18, 0x64, 0x44, 0xD3, + 0xEF, 0x60, 0x58, 0x4E, 0xBD, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x9E, 0x65, 0x0C, 0x64, 0xA5, 0xDB, + 0x36, 0x60, 0x1E, 0x64, 0xA1, 0xFB, 0x2D, 0xFF, 0x06, 0x61, 0x41, 0x4B, 0x09, 0x60, 0x08, 0x61, + 0xAE, 0x60, 0x58, 0x4D, 0xB1, 0x78, 0xFF, 0xFF, 0xF0, 0x67, 0x0E, 0xFA, 0x24, 0x60, 0x7A, 0x62, + 0x24, 0x60, 0x5E, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0x2B, 0x41, 0x4D, 0x8B, 0xFF, 0xFF, 0xE9, 0x02, 0x06, 0x61, 0x41, 0x4B, 0x09, 0x60, + 0x08, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xB1, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x7A, 0x62, 0x24, 0x60, + 0x52, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0x2B, 0x41, 0x4D, 0x8B, 0xFF, 0xFF, 0xEB, 0x02, 0x19, 0x60, 0x17, 0x78, 0xFF, 0xFF, 0x00, 0xEA, + 0x00, 0xEB, 0x50, 0x60, 0x03, 0xEA, 0x51, 0x60, 0x13, 0xEA, 0x52, 0x60, 0x30, 0xEA, 0x53, 0x60, + 0x40, 0xEA, 0x54, 0x60, 0x52, 0xEA, 0x55, 0x60, 0x6D, 0xEA, 0x56, 0x60, 0x71, 0xEA, 0x57, 0x60, + 0x8B, 0xEA, 0x58, 0x60, 0x47, 0xEA, 0x59, 0x60, 0xA0, 0xEA, 0x5A, 0x60, 0xB2, 0xEA, 0x5B, 0x60, + 0xC1, 0xEA, 0x5C, 0x60, 0xD7, 0xEA, 0x5D, 0x60, 0xEB, 0xEA, 0x5E, 0x60, 0xA0, 0xEA, 0x50, 0x60, + 0x36, 0xEB, 0x51, 0x60, 0x37, 0xEB, 0x52, 0x60, 0x20, 0xEB, 0x53, 0x60, 0xE4, 0xEB, 0x54, 0x60, + 0x34, 0xEB, 0x55, 0x60, 0x58, 0xEB, 0x56, 0x60, 0x48, 0xEB, 0x57, 0x60, 0xD0, 0xEB, 0x58, 0x60, + 0xC3, 0xEB, 0x59, 0x60, 0xFC, 0xEB, 0x5A, 0x60, 0x34, 0xEB, 0x5B, 0x60, 0x58, 0xEB, 0x5C, 0x60, + 0xC0, 0xEB, 0x5D, 0x60, 0xD0, 0xEB, 0x5E, 0x60, 0x91, 0xEB, 0x00, 0xEA, 0x00, 0xEB, 0xE0, 0x60, + 0x02, 0xEA, 0xE0, 0x60, 0x03, 0xEB, 0xA0, 0x60, 0x00, 0xEB, 0xB0, 0x60, 0x00, 0xEB, 0xAB, 0x48, + 0x40, 0x3B, 0x01, 0x00, 0xFC, 0x01, 0x00, 0xEB, 0x03, 0x60, 0x02, 0x62, 0x62, 0x44, 0xA2, 0xDB, + 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, + 0x00, 0xEA, 0x3F, 0x40, 0x40, 0x26, 0x08, 0x00, 0x00, 0x60, 0x18, 0x64, 0x00, 0x60, 0x00, 0x65, + 0x94, 0x84, 0xA0, 0x50, 0x1D, 0x60, 0x19, 0xE2, 0x24, 0x44, 0xFF, 0xB4, 0x04, 0xFB, 0x50, 0x60, + 0x00, 0x64, 0x05, 0xFB, 0x10, 0x60, 0x10, 0x75, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0x3F, 0x41, + 0xA5, 0x4C, 0x50, 0x37, 0x04, 0x00, 0x01, 0xB9, 0x41, 0x5F, 0xB5, 0x60, 0x55, 0xE0, 0x0C, 0x60, + 0x10, 0x62, 0xA2, 0xD3, 0x01, 0x60, 0x01, 0x65, 0xD4, 0x80, 0x5A, 0xD1, 0x0F, 0x02, 0x5A, 0xD3, + 0x3C, 0x60, 0x00, 0x66, 0xE0, 0x87, 0x40, 0x4A, 0x68, 0x60, 0x28, 0x61, 0x64, 0x44, 0xC8, 0x84, + 0x0C, 0x63, 0xAA, 0x46, 0x58, 0xD0, 0xAA, 0x46, 0x59, 0xD8, 0xFB, 0x1F, 0x08, 0x60, 0x00, 0x63, + 0xFA, 0x60, 0x00, 0x65, 0xBD, 0xD3, 0xA3, 0xD3, 0x02, 0xA8, 0xD4, 0x80, 0x61, 0x02, 0x60, 0x02, + 0x6E, 0x60, 0x58, 0x61, 0x3C, 0x60, 0x00, 0x66, 0x41, 0x4B, 0x2B, 0x41, 0x6E, 0x60, 0xA0, 0x7C, + 0xD1, 0x80, 0xA1, 0xD2, 0x25, 0x05, 0x59, 0xD0, 0x60, 0x45, 0x59, 0xD2, 0x44, 0x47, 0xE0, 0x87, + 0x40, 0x4A, 0x59, 0xD2, 0x59, 0x8B, 0x40, 0x4C, 0x08, 0x60, 0x00, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, + 0xEC, 0x18, 0xD4, 0x80, 0xEA, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x67, 0x44, + 0xC0, 0x84, 0xE0, 0x85, 0x2C, 0x44, 0xD4, 0x80, 0x63, 0x41, 0x01, 0x06, 0x65, 0x44, 0xC8, 0x83, + 0xAA, 0x46, 0x59, 0xD1, 0x27, 0xD8, 0x5A, 0x87, 0xFC, 0x1F, 0xAA, 0x46, 0x2B, 0x41, 0xD5, 0x01, + 0x6E, 0x60, 0xA0, 0x61, 0x41, 0x4B, 0x2B, 0x41, 0x6E, 0x60, 0xD8, 0x7C, 0xD1, 0x80, 0xA1, 0xD2, + 0x27, 0x05, 0x59, 0xD0, 0x60, 0x45, 0x59, 0xD2, 0x44, 0x47, 0xE0, 0x87, 0x40, 0x4A, 0x59, 0xD2, + 0x59, 0x8B, 0x40, 0x4C, 0x08, 0x60, 0x00, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, 0xEC, 0x18, 0xD4, 0x80, + 0xEA, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x04, 0xA3, 0xA3, 0xD1, 0x5A, 0x88, + 0x2C, 0x43, 0xD3, 0x80, 0xFF, 0xFF, 0x01, 0x06, 0x64, 0x43, 0xCF, 0x83, 0xAA, 0x46, 0x60, 0xFE, + 0x28, 0xD1, 0x5E, 0x88, 0x27, 0xD8, 0x5A, 0x87, 0xFB, 0x1F, 0x20, 0xFE, 0xAA, 0x46, 0xD3, 0x01, + 0xB8, 0xFE, 0xB9, 0xFE, 0xBA, 0xFE, 0xBB, 0xFE, 0xBD, 0xFE, 0xBF, 0xFE, 0x2D, 0x60, 0x1A, 0x62, + 0xA2, 0xD3, 0x12, 0x63, 0x60, 0x40, 0x01, 0x27, 0x05, 0x00, 0x0B, 0x60, 0xEA, 0x62, 0x00, 0x64, + 0x5A, 0xDB, 0xFE, 0x1F, 0x34, 0x60, 0x81, 0x78, 0xFF, 0xFF, 0xF1, 0xFF, 0xF6, 0x6C, 0x1E, 0x00, + 0x04, 0x00, 0xF2, 0xFF, 0xFA, 0x6C, 0x1E, 0x00, 0x04, 0x00, 0xFB, 0xFF, 0x02, 0x6D, 0x1E, 0x00, + 0x04, 0x00, 0xF1, 0xFF, 0x8C, 0x64, 0x1E, 0x00, 0x04, 0x00, 0xF2, 0xFF, 0x90, 0x64, 0x1E, 0x00, + 0x04, 0x00, 0xFB, 0xFF, 0x98, 0x64, 0x1E, 0x00, 0x04, 0x00, 0x86, 0xFD, 0x50, 0x28, 0x00, 0x00, + 0x06, 0x00, 0x10, 0xFD, 0x74, 0x01, 0x00, 0x00, 0x02, 0x00, 0x14, 0xFD, 0x18, 0x2D, 0x00, 0x00, + 0x0A, 0x00, 0x20, 0xFA, 0x94, 0x26, 0x00, 0x00, 0x0E, 0x00, 0x21, 0xFA, 0x78, 0x26, 0x00, 0x00, + 0x0E, 0x00, 0x22, 0xFA, 0xB0, 0x26, 0x00, 0x00, 0x0E, 0x00, 0x23, 0xFA, 0x64, 0x25, 0x00, 0x00, + 0x01, 0x00, 0x24, 0xFA, 0x58, 0x27, 0x00, 0x00, 0x0E, 0x00, 0x25, 0xFA, 0x78, 0x25, 0x00, 0x00, + 0x80, 0x00, 0x26, 0xFA, 0x5E, 0x25, 0x00, 0x00, 0x01, 0x00, + +}; /* fw_image_3_data */ + +static const hcf_8 fw_image_4_data[] = { + 0xA2, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA2, 0x60, 0xC3, 0x78, 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA2, 0x60, 0xC9, 0x78, 0xC4, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA2, 0x60, 0x19, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x44, 0xFF, 0x20, 0x54, 0xCD, 0xE2, 0xA2, 0x60, 0xDB, 0x78, 0x08, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA2, 0x60, 0xDD, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA2, 0x60, 0xDD, 0x78, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA2, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA8, 0x60, 0x73, 0x78, 0x4C, 0x4E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA7, 0x60, 0xFB, 0x78, 0x4C, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC4, 0xE2, 0x84, 0xFF, 0x22, 0x58, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA3, 0x60, 0x7E, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0xE2, 0xA8, 0x60, 0x14, 0x78, 0xB5, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBA, 0x60, 0xCE, 0x78, 0x64, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA8, 0x60, 0x87, 0x78, 0xA4, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA8, 0x60, 0x55, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAE, 0x60, 0x1E, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAE, 0x60, 0x4B, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAC, 0x60, 0xD8, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0x60, 0x08, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0x60, 0x08, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAF, 0x60, 0xC0, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0x60, 0x0B, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x60, 0x83, 0x64, 0x80, 0x29, 0x09, 0xFB, 0xAD, 0x60, 0xE6, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, + 0x31, 0x60, 0x16, 0x78, 0x40, 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, + 0x30, 0x60, 0xA1, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB9, 0x60, 0x4B, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB8, 0x60, 0xBB, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB0, 0x60, 0x89, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA1, 0xFF, 0xFF, 0xFF, 0x83, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBB, 0x60, 0x25, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xB0, 0xFF, 0xB1, 0xFF, 0x40, 0xFF, 0x43, 0xFF, 0xBB, 0x60, 0x20, 0x78, 0x44, 0xFF, 0xFF, 0x01, + 0xBB, 0x60, 0x25, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0x33, 0x60, 0x9B, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xBB, 0x60, 0x20, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xBB, 0x60, 0x1F, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xBF, 0x60, 0xDB, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xEB, 0x60, 0x1F, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBF, 0x60, 0xE3, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBF, 0x60, 0xE3, 0x78, 0x24, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE9, 0x60, 0xE3, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBF, 0x60, 0xE3, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBF, 0x60, 0xE3, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBF, 0x60, 0xE3, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x24, 0x60, 0xE5, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x25, 0x60, 0x14, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x25, 0x60, 0x32, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x25, 0x60, 0x11, 0x78, 0x28, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x25, 0x60, 0x11, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x25, 0x60, 0x11, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x25, 0x60, 0x11, 0x78, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x60, 0x87, 0x64, 0x80, 0x29, 0x09, 0xFB, 0x47, 0xFF, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2F, 0x60, 0x63, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2F, 0x60, 0xB3, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x07, 0x02, 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, + 0x66, 0xFF, 0xBF, 0xFE, 0xA1, 0xFF, 0x82, 0xFF, 0x88, 0xFF, 0x6C, 0x40, 0x41, 0xFF, 0xC4, 0xE2, + 0x43, 0xFF, 0x5C, 0x49, 0x08, 0xE1, 0xA2, 0x60, 0x16, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, 0x98, 0xFF, + 0x80, 0x3E, 0x9F, 0xFE, 0x03, 0x04, 0x31, 0x60, 0x75, 0x78, 0xFF, 0xFF, 0xE2, 0xFE, 0x40, 0x05, + 0xE0, 0xFE, 0x5B, 0x05, 0xE1, 0xFE, 0xF2, 0x04, 0x29, 0x40, 0x08, 0x26, 0xEF, 0x01, 0x72, 0x44, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xB5, 0xF3, 0xE8, 0x85, 0xFF, 0xB7, + 0xE0, 0x84, 0xE0, 0x84, 0xB4, 0x85, 0x73, 0x44, 0xD4, 0x84, 0x10, 0x65, 0xD4, 0x80, 0xFF, 0xFF, + 0x26, 0x04, 0x3F, 0x40, 0x40, 0x26, 0x13, 0x00, 0x0B, 0x60, 0xF8, 0x62, 0xA2, 0xD1, 0x00, 0x60, + 0x10, 0x64, 0x90, 0x84, 0xA0, 0x50, 0xF8, 0xA2, 0xA2, 0xD1, 0x0A, 0x60, 0x19, 0x64, 0x90, 0x84, + 0xA0, 0x52, 0x06, 0xA2, 0xA2, 0xD1, 0x46, 0x60, 0x09, 0x64, 0x90, 0x84, 0xA0, 0x50, 0xF2, 0xF4, + 0x31, 0x60, 0x18, 0x7C, 0x63, 0x40, 0x01, 0x26, 0x08, 0x00, 0xA4, 0xD3, 0xFF, 0xFF, 0x01, 0xB4, + 0xFF, 0xFF, 0x03, 0x02, 0xAD, 0x4F, 0xFE, 0xB4, 0xA0, 0x5D, 0x02, 0xEE, 0xBD, 0xFE, 0xBE, 0x01, + 0x21, 0x46, 0x5E, 0x62, 0x9A, 0xFF, 0x07, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x06, 0x25, 0x10, 0x00, + 0xA2, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x62, 0x62, 0x01, 0x5D, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, + 0x7A, 0xDC, 0x44, 0xFF, 0x06, 0x25, 0x04, 0x00, 0x0E, 0xE1, 0x02, 0x60, 0x01, 0xE1, 0x9E, 0x01, + 0x62, 0xFF, 0xC4, 0xE2, 0x41, 0xFF, 0x0A, 0xE1, 0x99, 0x01, 0xC8, 0x74, 0xCD, 0xE2, 0x29, 0x44, + 0x08, 0xBC, 0x40, 0x49, 0x05, 0xE1, 0x31, 0x60, 0x1A, 0x63, 0xA3, 0xD3, 0xF2, 0xF3, 0x06, 0x18, + 0x28, 0x40, 0x08, 0x2A, 0x05, 0x00, 0x28, 0x40, 0x48, 0x36, 0x02, 0x00, 0x02, 0xBC, 0xF2, 0xFB, + 0x3F, 0x40, 0x01, 0x2B, 0xFF, 0xFF, 0xA1, 0xFF, 0x67, 0x4C, 0x06, 0x61, 0xCD, 0x81, 0x04, 0x25, + 0x30, 0x00, 0x87, 0x4C, 0xFB, 0x02, 0x28, 0x40, 0x40, 0x2B, 0x02, 0x00, 0x15, 0x60, 0x6F, 0x6B, + 0xF3, 0x60, 0xA0, 0x64, 0x04, 0x25, 0x25, 0x00, 0x80, 0x4C, 0x30, 0x64, 0x3A, 0xDB, 0x44, 0xFF, + 0x04, 0x25, 0x1F, 0x00, 0x04, 0x60, 0x00, 0x65, 0x25, 0x44, 0x37, 0x36, 0xB4, 0x84, 0x6E, 0x36, + 0xB4, 0x84, 0x80, 0x4E, 0x24, 0x41, 0x04, 0x25, 0x14, 0x00, 0x61, 0x4C, 0x64, 0xA1, 0x61, 0x54, + 0xA1, 0xFF, 0xFF, 0xFF, 0x04, 0x25, 0x0D, 0x00, 0x67, 0x4E, 0x07, 0x64, 0x1C, 0xFB, 0x00, 0xE1, + 0x02, 0x60, 0x01, 0xE1, 0x53, 0x01, 0x33, 0xF3, 0xFD, 0x11, 0xFC, 0x18, 0x40, 0x64, 0x3A, 0xDB, + 0x0A, 0x00, 0xC4, 0xE2, 0x27, 0x44, 0x20, 0x2A, 0x04, 0x00, 0x42, 0x64, 0x3A, 0xDB, 0x67, 0x4C, + 0x02, 0x00, 0x41, 0x64, 0x3A, 0xDB, 0x62, 0xFF, 0x08, 0xE1, 0xE2, 0xFE, 0x72, 0x52, 0x5C, 0x49, + 0x32, 0x7B, 0x4D, 0xE2, 0x3B, 0x01, 0x08, 0xE1, 0x39, 0x01, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, + 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x02, 0x02, 0xA1, 0xFF, 0xFF, 0xFF, 0x82, 0xFF, 0x88, 0xFF, + 0x48, 0xE2, 0x01, 0x70, 0xCE, 0xF1, 0x00, 0x6B, 0x89, 0xFF, 0x64, 0x54, 0x88, 0xFF, 0x9F, 0xFE, + 0x02, 0x05, 0x64, 0x44, 0x60, 0x54, 0xCD, 0xE2, 0xC2, 0x64, 0x3A, 0xDB, 0xBC, 0xFF, 0xB5, 0xFF, + 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xB4, 0x40, 0x46, 0x3C, 0x44, 0x00, 0xBC, 0xFF, 0xFF, 0x06, 0x03, + 0x27, 0x40, 0x26, 0x22, 0x03, 0x00, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x27, 0x44, 0x20, 0x2A, + 0x04, 0x00, 0xA0, 0x60, 0x00, 0xEA, 0xB0, 0x60, 0x00, 0xEA, 0x5C, 0x4D, 0x27, 0x44, 0x18, 0xB4, + 0x40, 0x47, 0x00, 0xE1, 0x6C, 0x40, 0x44, 0xE2, 0xC4, 0xE2, 0x47, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, + 0x32, 0xF1, 0x08, 0x29, 0x09, 0x00, 0x64, 0x40, 0x07, 0x22, 0x06, 0x00, 0x43, 0xFF, 0x27, 0x44, + 0x10, 0xBC, 0x40, 0x47, 0x00, 0x64, 0x32, 0xFB, 0x31, 0x41, 0x3C, 0x44, 0x01, 0xB1, 0x00, 0xBC, + 0x0A, 0x02, 0x09, 0x03, 0x32, 0xF3, 0x00, 0x7C, 0x01, 0xB4, 0xFF, 0xFF, 0x04, 0x03, 0x32, 0xF9, + 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x00, 0x64, + 0x33, 0xFB, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x32, 0xF3, 0x08, 0x29, + 0x0A, 0x00, 0x60, 0x40, 0x07, 0x22, 0x07, 0x00, 0xFE, 0xB4, 0x32, 0xFB, 0x27, 0x44, 0x10, 0xBC, + 0xF7, 0xB4, 0x40, 0x47, 0x43, 0xFF, 0x00, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x08, 0xE1, 0x31, 0x40, + 0x01, 0x2A, 0x04, 0x00, 0x00, 0x64, 0x33, 0xFB, 0x01, 0x60, 0x0A, 0xE1, 0xE5, 0xFE, 0x1D, 0x05, + 0x27, 0x44, 0x10, 0x26, 0x1D, 0x00, 0x9F, 0xFE, 0x02, 0x04, 0x02, 0xE1, 0x10, 0x00, 0x3E, 0xE1, + 0x31, 0x44, 0x01, 0x2A, 0x0C, 0x00, 0x0E, 0x0A, 0x28, 0x44, 0x04, 0x27, 0x07, 0x00, 0xD4, 0x36, + 0x05, 0x00, 0xC4, 0x36, 0x03, 0x00, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, 0xBF, 0xE1, 0xA1, 0xFF, + 0xFF, 0xFF, 0x81, 0x3E, 0xAB, 0x60, 0x2C, 0x78, 0xFF, 0xFF, 0xA3, 0x60, 0xEC, 0x78, 0xFF, 0xFF, + 0x27, 0x44, 0x08, 0x26, 0xFF, 0xFF, 0xBA, 0x60, 0x70, 0x78, 0xFF, 0xFF, 0x48, 0xF3, 0x32, 0xF1, + 0x00, 0x63, 0x64, 0x40, 0x03, 0x22, 0x66, 0x00, 0x31, 0x40, 0x08, 0x26, 0xF4, 0x01, 0xCD, 0xE2, + 0x84, 0xE1, 0x70, 0x41, 0xAD, 0x80, 0x71, 0x40, 0x80, 0x27, 0xED, 0x12, 0x03, 0x03, 0xBA, 0x60, + 0xE7, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0xC4, 0xE2, 0x32, 0xFD, 0x60, 0x40, 0x01, 0x2A, + 0xDF, 0x01, 0x00, 0x63, 0x32, 0xFD, 0x6C, 0x40, 0x3C, 0x46, 0x3E, 0xF2, 0x2A, 0xF0, 0x27, 0x41, + 0x44, 0x48, 0x20, 0xB9, 0x01, 0xB4, 0xF7, 0xB1, 0x0A, 0x03, 0x64, 0x40, 0x08, 0x27, 0x07, 0x00, + 0x0F, 0x60, 0x92, 0x63, 0x00, 0x64, 0x45, 0xFB, 0x46, 0xFB, 0xBD, 0xDB, 0xA3, 0xDB, 0xCB, 0x0A, + 0x31, 0x60, 0x0E, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0x17, 0x18, 0x28, 0x40, 0xD4, 0x36, 0x14, 0x00, + 0xAC, 0x4C, 0x80, 0x2A, 0x11, 0x00, 0x31, 0x60, 0x14, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0x0C, 0x18, + 0x31, 0x60, 0x16, 0x7C, 0xA4, 0xD3, 0x31, 0x60, 0x10, 0x7C, 0xA4, 0xD3, 0x60, 0x45, 0xD4, 0x80, + 0xDC, 0x84, 0x02, 0x03, 0xA4, 0xDB, 0xAF, 0x01, 0x31, 0x60, 0x10, 0x7C, 0x00, 0x64, 0xA4, 0xDB, + 0x41, 0x47, 0x3F, 0x40, 0x01, 0x2B, 0x0D, 0x00, 0xF6, 0xFE, 0x67, 0x4C, 0x05, 0x60, 0x69, 0x6B, + 0x31, 0x60, 0x0E, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0x04, 0x18, 0xAE, 0x4F, 0x08, 0xBC, 0x00, 0x7F, + 0xA0, 0x5E, 0x02, 0xE1, 0x01, 0x60, 0x08, 0xE1, 0xF0, 0xFE, 0x84, 0xFF, 0xBB, 0x60, 0x18, 0x64, + 0x40, 0x42, 0x82, 0xFF, 0xE5, 0xFE, 0x03, 0x04, 0xA8, 0x60, 0x24, 0x78, 0xFF, 0xFF, 0xE4, 0xFE, + 0x0A, 0x04, 0x1D, 0xFF, 0x00, 0xEB, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, + 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x43, 0xFF, 0xE6, 0xFE, 0x03, 0x05, 0xA3, 0x60, 0x4B, 0x78, + 0xFF, 0xFF, 0x3C, 0x44, 0x60, 0x46, 0x0F, 0xF0, 0x40, 0x42, 0x64, 0x40, 0x01, 0x2A, 0x03, 0x00, + 0xA6, 0x60, 0xB1, 0x78, 0xFF, 0xFF, 0x0B, 0x64, 0x3A, 0xDB, 0x1C, 0x42, 0x22, 0x46, 0x13, 0xF2, + 0xFF, 0x65, 0x60, 0x47, 0x2A, 0xF2, 0x40, 0x45, 0x40, 0x48, 0x04, 0x2B, 0x17, 0x00, 0x16, 0xF2, + 0x1D, 0xF2, 0x40, 0x43, 0x0F, 0xF2, 0x40, 0x44, 0x25, 0x5E, 0x3F, 0x40, 0x01, 0x27, 0x40, 0x45, + 0x0F, 0x64, 0x14, 0xF0, 0x35, 0xF2, 0xA0, 0x82, 0x0F, 0xB4, 0xCA, 0x85, 0xD4, 0x80, 0x10, 0xF2, + 0x01, 0x02, 0x2B, 0xFA, 0x27, 0x44, 0x40, 0xBC, 0x40, 0x47, 0x13, 0x00, 0x17, 0xF2, 0x2C, 0xF0, + 0x40, 0x43, 0x1B, 0xF2, 0x1D, 0xFA, 0x40, 0x44, 0x64, 0x40, 0x01, 0x2A, 0x02, 0x00, 0xAB, 0xFC, + 0x05, 0x00, 0x28, 0x40, 0xA4, 0x36, 0x02, 0x00, 0x11, 0xF2, 0x2B, 0xFA, 0x27, 0x44, 0xBF, 0xB4, + 0x40, 0x47, 0x28, 0x40, 0x40, 0x2B, 0xFF, 0xFF, 0xAB, 0x60, 0x4A, 0x78, 0xFF, 0xFF, 0x22, 0x46, + 0x2C, 0xF0, 0x27, 0x44, 0xDF, 0xB4, 0x40, 0x47, 0xB5, 0xFF, 0xBC, 0xFF, 0x47, 0xFF, 0xB7, 0xFF, + 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x64, 0x40, 0x01, 0x2A, 0x09, 0x00, + 0x28, 0x44, 0x04, 0x27, 0x05, 0x00, 0xD4, 0x3A, 0x03, 0x00, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, + 0x1B, 0x00, 0x2A, 0xF0, 0x01, 0x65, 0x64, 0x40, 0xA4, 0x3A, 0x04, 0x65, 0x27, 0x44, 0x34, 0x87, + 0x36, 0xF3, 0xB4, 0xFF, 0x60, 0x5B, 0x4D, 0xE2, 0x04, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x0A, 0xE1, + 0x28, 0x44, 0x04, 0x27, 0x05, 0x00, 0xD4, 0x3A, 0x03, 0x00, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, + 0x2B, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x06, 0x64, 0x3A, 0xDB, 0x22, 0x46, 0x01, 0x64, + 0x31, 0xFB, 0xC0, 0xFE, 0xBA, 0x60, 0xF0, 0x78, 0xFF, 0xFF, 0xB5, 0xFF, 0xA1, 0xFF, 0x6C, 0x40, + 0x3F, 0x40, 0x01, 0x2B, 0x03, 0x00, 0x67, 0x4C, 0x05, 0x60, 0x69, 0x6B, 0x02, 0xE1, 0x01, 0x60, + 0x08, 0xE1, 0xC4, 0xE2, 0x08, 0x64, 0x3A, 0xDB, 0xF0, 0xFE, 0x25, 0x46, 0x01, 0xF2, 0x61, 0x45, + 0xD4, 0x9E, 0x21, 0x46, 0x16, 0xFA, 0x2A, 0x44, 0x72, 0x45, 0x24, 0xFA, 0xB5, 0xF3, 0x06, 0x04, + 0xE4, 0xE2, 0xDC, 0x9C, 0x29, 0x40, 0x01, 0x26, 0x64, 0x44, 0xB5, 0xF9, 0x25, 0xFA, 0xB6, 0xF3, + 0x02, 0x04, 0xDC, 0x84, 0xB6, 0xFB, 0x28, 0xFA, 0xB7, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB7, 0xFB, + 0x29, 0xFA, 0x2D, 0x44, 0x04, 0x2A, 0x06, 0x00, 0x28, 0x40, 0xA4, 0x36, 0x03, 0x00, 0xA5, 0x60, + 0x77, 0x78, 0xFF, 0xFF, 0x26, 0x43, 0x84, 0xBB, 0xFC, 0xB3, 0x21, 0x46, 0x01, 0x5D, 0x0F, 0xFC, + 0x5C, 0x46, 0x25, 0x44, 0x06, 0xFA, 0x05, 0xFF, 0x27, 0x44, 0x01, 0x2A, 0x13, 0x00, 0x50, 0xFE, + 0x28, 0x40, 0x08, 0x3A, 0x12, 0x00, 0x2F, 0xF2, 0x30, 0xF0, 0x60, 0x43, 0x31, 0xF2, 0x22, 0x46, + 0x64, 0x41, 0x2C, 0xF0, 0x2D, 0xF0, 0xD3, 0x80, 0x2E, 0xF0, 0xD1, 0x80, 0xD0, 0x80, 0x27, 0x44, + 0x09, 0x0C, 0x03, 0x00, 0x27, 0x44, 0x06, 0x22, 0x05, 0x00, 0xB8, 0xB4, 0x40, 0x47, 0x02, 0x64, + 0x31, 0xFB, 0xC0, 0xFE, 0xD4, 0x64, 0x40, 0x48, 0x0D, 0x64, 0x3A, 0xDB, 0x31, 0x60, 0x12, 0x7C, + 0x7C, 0x44, 0xA4, 0xDB, 0x21, 0x46, 0x1C, 0xF2, 0x7C, 0xF1, 0xFF, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, + 0x01, 0x06, 0x64, 0x44, 0x40, 0x45, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, 0x37, 0x3A, + 0x03, 0x00, 0x04, 0x7F, 0x40, 0x45, 0x15, 0x64, 0x6E, 0x3A, 0x03, 0x00, 0x84, 0x7F, 0x40, 0x45, + 0x0B, 0x64, 0x40, 0x44, 0x00, 0x63, 0x28, 0x44, 0xA4, 0x36, 0x0B, 0x00, 0x04, 0x2B, 0x09, 0x00, + 0x30, 0xF3, 0x24, 0x45, 0xD4, 0x84, 0xCA, 0x65, 0xD4, 0x83, 0x31, 0x60, 0x12, 0x7C, 0x01, 0x64, + 0xA4, 0xDB, 0xD4, 0x64, 0x1A, 0x00, 0x0F, 0x64, 0x3A, 0xDB, 0x21, 0x46, 0x70, 0x63, 0x1C, 0xF2, + 0xCA, 0x65, 0x40, 0x45, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, 0x37, 0x3A, 0x03, 0x00, + 0x04, 0x7F, 0x40, 0x45, 0x15, 0x64, 0x6E, 0x3A, 0x03, 0x00, 0x84, 0x7F, 0x40, 0x45, 0x0B, 0x64, + 0x40, 0x44, 0x2B, 0xF2, 0xC4, 0x85, 0xD4, 0x83, 0xC4, 0x64, 0x40, 0x48, 0x2F, 0xF0, 0xB0, 0xF0, + 0xB1, 0xF2, 0x00, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x80, 0x4E, 0x83, 0x4C, 0x9A, 0xFF, 0x84, 0x4C, + 0x85, 0x4C, 0x81, 0x4C, 0xA1, 0xFF, 0x98, 0xFF, 0x87, 0x4F, 0x87, 0x4C, 0x87, 0x4F, 0x87, 0x4D, + 0x87, 0x4C, 0x01, 0x08, 0x01, 0x00, 0xFF, 0xFF, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, + 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x44, 0xBC, 0xFF, 0xC4, 0xE2, 0x0C, 0x74, 0x04, 0xE1, 0xA1, 0xFF, + 0x35, 0xF3, 0xC4, 0xE2, 0x60, 0x54, 0x89, 0xFF, 0x13, 0x74, 0x88, 0xFF, 0xB5, 0xFF, 0x47, 0xFF, + 0x29, 0x44, 0xF7, 0xB4, 0x40, 0x49, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, + 0x00, 0x6B, 0x28, 0x40, 0xC4, 0x36, 0x08, 0x00, 0x31, 0x60, 0x12, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, + 0x03, 0x1B, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, 0x27, 0x44, 0x01, 0x2A, 0x05, 0x00, 0xFE, 0xB4, + 0x40, 0x47, 0xA4, 0x60, 0x7C, 0x78, 0xFF, 0xFF, 0xA3, 0x60, 0x3E, 0x78, 0xFF, 0xFF, 0x28, 0x40, + 0xB4, 0x3A, 0x09, 0x00, 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, 0x02, 0x64, + 0x31, 0xFB, 0xC0, 0xFE, 0x90, 0x01, 0x28, 0x44, 0xD4, 0x36, 0x03, 0x00, 0xA6, 0x60, 0x98, 0x78, + 0xFF, 0xFF, 0x48, 0xE2, 0x27, 0x44, 0xFB, 0xB4, 0x40, 0x47, 0x2D, 0x60, 0x5A, 0x63, 0xA3, 0xD3, + 0xB0, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x34, 0xFB, 0x1C, 0x42, 0x22, 0x46, 0x2A, 0xF0, + 0xF7, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDA, 0x60, 0x40, 0x40, 0x2B, 0xCC, 0x00, 0x22, 0xF2, + 0xFF, 0xFF, 0x60, 0x40, 0x22, 0x26, 0x42, 0x00, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, 0x07, 0x00, + 0xC2, 0x00, 0x04, 0x2B, 0xC0, 0x00, 0xA9, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0x01, 0x00, 0x07, 0xF4, + 0x47, 0xF2, 0xFF, 0xFF, 0xDC, 0x84, 0x47, 0xFA, 0x0D, 0x60, 0x3E, 0x62, 0x80, 0xFF, 0xBE, 0x60, + 0x78, 0x44, 0x02, 0xA4, 0xA2, 0xDB, 0xDE, 0x78, 0xFF, 0xFF, 0x82, 0xFF, 0xA9, 0xF3, 0x66, 0x5C, + 0xD0, 0x80, 0x00, 0x7C, 0x07, 0x03, 0x66, 0x43, 0x22, 0x46, 0x22, 0xF2, 0x63, 0x46, 0x60, 0x40, + 0x01, 0x2A, 0x01, 0x00, 0x3C, 0xF1, 0x47, 0xF0, 0x64, 0x41, 0x64, 0x47, 0xFF, 0xB4, 0x60, 0x5F, + 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, 0x60, 0x47, 0x22, 0x46, 0x3A, 0xFA, 0x64, 0x44, 0x20, 0x7F, + 0x34, 0x94, 0x3B, 0xFA, 0x08, 0x60, 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, + 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x85, 0x00, 0x2A, 0xF2, 0x00, 0x60, + 0x7C, 0x62, 0x60, 0x40, 0x40, 0x2B, 0x27, 0x00, 0xA2, 0xD3, 0x00, 0x61, 0x60, 0xFE, 0xA0, 0xD3, + 0xDE, 0x82, 0xA2, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0xDC, 0x84, 0xF1, 0x81, 0xC0, 0x2B, + 0x04, 0x00, 0x80, 0x2A, 0x02, 0x00, 0x7F, 0xA4, 0xDC, 0x84, 0xFF, 0x3B, 0x03, 0x00, 0x60, 0x47, + 0xDC, 0x87, 0x01, 0x61, 0xC0, 0x80, 0x00, 0x36, 0xDC, 0x84, 0x4E, 0xDB, 0x60, 0xFE, 0xDA, 0x82, + 0xA2, 0xD1, 0xFF, 0xFF, 0xC1, 0x84, 0xF0, 0x22, 0x10, 0xA4, 0xF0, 0x2A, 0x01, 0x00, 0x00, 0x64, + 0xA2, 0xDB, 0xFF, 0xFF, 0x20, 0xFE, 0x00, 0x60, 0x7C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0xD3, + 0x5A, 0xD1, 0x3A, 0xFA, 0x3B, 0xF8, 0x74, 0x62, 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, + 0xA0, 0x5A, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5A, + 0x00, 0x60, 0x80, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0xD1, 0x5A, 0xD1, 0x64, 0x45, 0x64, 0x44, + 0xE3, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE5, 0x7F, + 0xA0, 0x5A, 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5A, + 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, + 0xE9, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEB, 0x7F, + 0xA0, 0x5A, 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5A, + 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEF, 0x7F, 0xA0, 0x5A, 0x08, 0x60, + 0x00, 0xEA, 0x65, 0x44, 0x02, 0xA4, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, + 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x0B, 0xF2, 0xFF, 0xFF, 0x7F, 0xB4, 0x0C, 0xF0, 0x04, 0x02, + 0x64, 0x46, 0x00, 0xF0, 0x04, 0x64, 0x22, 0x46, 0x03, 0xFA, 0x60, 0x41, 0x64, 0x46, 0x01, 0xF2, + 0xFC, 0xA1, 0x61, 0x45, 0xD4, 0x84, 0xFF, 0xFF, 0x08, 0x02, 0x00, 0xF0, 0x04, 0x63, 0x64, 0x46, + 0x01, 0xF2, 0x22, 0x46, 0x1A, 0xFA, 0x03, 0xFC, 0x02, 0x00, 0x22, 0x46, 0x1A, 0xFA, 0x35, 0xF2, + 0x04, 0xF8, 0xDC, 0x84, 0x35, 0xFA, 0x14, 0xF2, 0x0F, 0xB5, 0x0F, 0xB4, 0xCC, 0x84, 0x94, 0x80, + 0x04, 0x60, 0x00, 0x65, 0x2A, 0xF2, 0x01, 0x02, 0x94, 0x84, 0x2A, 0xFA, 0x95, 0xFC, 0x06, 0x00, + 0xC4, 0x3A, 0x07, 0x00, 0x27, 0x44, 0xFD, 0xB4, 0x40, 0x47, 0x48, 0xE2, 0xA4, 0x60, 0x0B, 0x78, + 0xFF, 0xFF, 0x28, 0x44, 0x04, 0x26, 0x05, 0x00, 0x68, 0x3A, 0x03, 0x00, 0x32, 0x44, 0x00, 0x27, + 0x03, 0x00, 0xA3, 0x60, 0x4B, 0x78, 0xFF, 0xFF, 0x0A, 0x64, 0x3A, 0xDB, 0xA3, 0x60, 0x4B, 0x78, + 0xFF, 0xFF, 0x0E, 0x64, 0x3A, 0xDB, 0x10, 0x60, 0x00, 0x65, 0x3C, 0x46, 0x2A, 0xF2, 0x13, 0xF0, + 0xA4, 0x84, 0xB4, 0xBC, 0x40, 0x48, 0x7C, 0xF1, 0x64, 0x47, 0xFF, 0xB4, 0x60, 0x45, 0xD0, 0x80, + 0x70, 0x61, 0x01, 0x06, 0x64, 0x44, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, 0x37, 0x36, + 0x15, 0x64, 0x6E, 0x36, 0x0B, 0x64, 0x40, 0x4E, 0xA0, 0x63, 0x0A, 0x64, 0x65, 0x40, 0x0A, 0x36, + 0x03, 0x00, 0x38, 0x61, 0x14, 0x64, 0xEB, 0x83, 0x40, 0x45, 0x43, 0x44, 0x02, 0x60, 0x5E, 0x65, + 0x2A, 0xF2, 0x2B, 0xF2, 0x60, 0x40, 0x04, 0x2B, 0x04, 0x00, 0x2E, 0x45, 0xD4, 0x85, 0xC5, 0x84, + 0x05, 0x00, 0x1B, 0xF0, 0xC5, 0x84, 0xC0, 0x84, 0x2E, 0x45, 0xC4, 0x84, 0x60, 0x43, 0x28, 0x44, + 0x00, 0xE1, 0xA1, 0xFF, 0x80, 0x4E, 0x83, 0x4C, 0x9A, 0xFF, 0x56, 0x62, 0x7A, 0xD4, 0x7A, 0xD4, + 0x7A, 0xD4, 0x5C, 0x62, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0xA1, 0xFF, 0x98, 0xFF, 0x87, 0x4F, + 0x87, 0x4C, 0x87, 0x4F, 0x87, 0x4D, 0x87, 0x4C, 0x01, 0x08, 0x01, 0x00, 0xFF, 0xFF, 0x87, 0x4C, + 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x44, 0xBC, 0xFF, 0xB5, 0xFF, + 0x47, 0xFF, 0x27, 0x44, 0x02, 0xBC, 0x40, 0x47, 0x36, 0xF3, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, + 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x60, 0x5B, 0x4D, 0xE2, 0xA4, 0x60, 0x6C, 0x78, 0xFF, 0xFF, + 0x21, 0x46, 0xB5, 0xFF, 0xBC, 0xFF, 0x47, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, + 0x08, 0x60, 0x00, 0x6B, 0x28, 0x44, 0x04, 0x27, 0x09, 0x00, 0xD4, 0x36, 0x04, 0x00, 0x0C, 0x22, + 0x02, 0x00, 0x0C, 0x3A, 0x03, 0x00, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, 0x26, 0x43, 0x25, 0x44, + 0x06, 0xFA, 0x2A, 0x44, 0x72, 0x45, 0x24, 0xFA, 0xB5, 0xF3, 0x06, 0x04, 0xE4, 0xE2, 0xDC, 0x9C, + 0x29, 0x40, 0x01, 0x26, 0x64, 0x44, 0xB5, 0xF9, 0x25, 0xFA, 0xB6, 0xF3, 0x02, 0x04, 0xDC, 0x84, + 0xB6, 0xFB, 0x28, 0xFA, 0xB7, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB7, 0xFB, 0x29, 0xFA, 0x2D, 0x40, + 0x01, 0x2A, 0x0E, 0x00, 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xBC, 0x40, 0x46, 0x27, 0x44, 0x07, 0x22, + 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x30, 0xF1, 0x76, 0x00, + 0xFC, 0xB3, 0x32, 0x40, 0x01, 0x2A, 0x06, 0x00, 0x0A, 0xBB, 0x0F, 0xFC, 0xCB, 0xFE, 0xA3, 0x60, + 0x4B, 0x78, 0xFF, 0xFF, 0x2D, 0x44, 0x04, 0x26, 0x28, 0x00, 0x0F, 0xFC, 0x05, 0xFF, 0xDC, 0xF3, + 0x28, 0x40, 0x80, 0x3A, 0x22, 0x00, 0x60, 0x40, 0x03, 0x3A, 0x1F, 0x00, 0x32, 0xF2, 0x81, 0xF1, + 0x33, 0xF2, 0xD0, 0x80, 0x82, 0xF1, 0x19, 0x02, 0xD0, 0x80, 0x34, 0xF2, 0x83, 0xF1, 0x15, 0x02, + 0xD0, 0x80, 0x3C, 0x44, 0x12, 0x02, 0xAC, 0x86, 0xBB, 0xFE, 0x0F, 0x03, 0x2A, 0xF2, 0x21, 0x46, + 0x60, 0x40, 0x80, 0x3A, 0x0A, 0x00, 0x01, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x00, 0x64, 0x32, 0xFB, + 0x84, 0xFF, 0xBB, 0x60, 0x18, 0x64, 0x40, 0x42, 0x82, 0xFF, 0x30, 0xF1, 0x27, 0x44, 0x05, 0x22, + 0x2D, 0x00, 0xFA, 0xB4, 0x40, 0x47, 0x2D, 0x44, 0x10, 0x2A, 0x24, 0x00, 0x28, 0x40, 0xD4, 0x3A, + 0x21, 0x00, 0x31, 0x40, 0x08, 0x26, 0x00, 0x7C, 0x2B, 0x44, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, + 0x64, 0x44, 0xC4, 0x84, 0xFF, 0xFF, 0x04, 0x24, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, + 0x20, 0x29, 0x6D, 0xE2, 0x1C, 0x60, 0x9A, 0x63, 0x1D, 0xF0, 0xC0, 0x64, 0xC0, 0x84, 0xA3, 0xD1, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, 0xA3, 0xDB, 0xA4, 0x60, + 0x7C, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x07, 0x00, 0x02, 0x2A, 0x05, 0x00, + 0xFD, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x05, 0x64, 0x3A, 0xDB, 0x28, 0x44, + 0xA4, 0x3A, 0x04, 0x00, 0x39, 0xF1, 0x25, 0x44, 0x0A, 0x36, 0x38, 0xF1, 0x31, 0x40, 0x08, 0x26, + 0x00, 0x7C, 0x2B, 0x44, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, 0x64, 0x44, 0xC4, 0x84, 0xFF, 0xFF, + 0x04, 0x24, 0x00, 0xB4, 0x28, 0x40, 0xE4, 0x36, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, + 0x20, 0x29, 0x6D, 0xE2, 0xA3, 0x60, 0x3E, 0x78, 0xFF, 0xFF, 0x21, 0x46, 0xB5, 0xFF, 0xBC, 0xFF, + 0x47, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0xAE, 0x4F, + 0xF7, 0xB4, 0xA0, 0x5E, 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, 0x06, 0x64, + 0x31, 0xFB, 0xC0, 0xFE, 0xE7, 0x01, 0x27, 0x44, 0x05, 0x22, 0x09, 0x00, 0xBA, 0xB4, 0x40, 0x47, + 0x3C, 0x46, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xA3, 0x60, 0x4B, 0x78, 0xFF, 0xFF, 0x27, 0x44, + 0x02, 0x2A, 0x06, 0x00, 0xFD, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xF4, 0x01, + 0xF3, 0x0A, 0x7C, 0x50, 0x6D, 0xE2, 0xF0, 0x01, 0x72, 0x45, 0xDC, 0x84, 0xB5, 0xFB, 0x11, 0x64, + 0x3A, 0xDB, 0xB6, 0xF3, 0x06, 0x04, 0xDC, 0x84, 0xB6, 0xFB, 0xB7, 0xF3, 0x02, 0x04, 0xDC, 0x84, + 0xB7, 0xFB, 0xA3, 0x60, 0x56, 0x78, 0xFF, 0xFF, 0x00, 0x61, 0x12, 0x64, 0x3A, 0xDB, 0x1E, 0x60, + 0xFE, 0x63, 0xBD, 0xD3, 0x72, 0x45, 0x44, 0x8A, 0x02, 0x28, 0x02, 0x00, 0xE4, 0xE2, 0xDD, 0x81, + 0x02, 0x28, 0x02, 0x00, 0xE4, 0xE2, 0xDD, 0x81, 0xBD, 0xD3, 0xB5, 0xF1, 0x61, 0x45, 0xC0, 0x84, + 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, 0xC4, 0x84, 0x60, 0x55, 0x2A, 0x52, 0xB5, 0xFB, 0x02, 0x24, + 0x01, 0xB9, 0xBD, 0xD3, 0xB6, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, + 0xC4, 0x84, 0xB6, 0xFB, 0x02, 0x24, 0x01, 0xB9, 0xBD, 0xD3, 0xB7, 0xF1, 0x61, 0x45, 0xC0, 0x84, + 0xC4, 0x84, 0xB7, 0xFB, 0xA3, 0x60, 0xEF, 0x78, 0xFF, 0xFF, 0x31, 0x40, 0x04, 0x0A, 0xAE, 0x4F, + 0xF7, 0xB4, 0xA0, 0x5E, 0x09, 0x00, 0x31, 0x60, 0x0E, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0x04, 0x18, + 0xAE, 0x4F, 0x08, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x9F, 0x01, 0xA1, 0xFF, 0xFF, 0xFF, 0x01, 0x25, + 0x09, 0x00, 0x04, 0x25, 0x03, 0x00, 0x47, 0xFF, 0x32, 0x74, 0x96, 0x01, 0xC4, 0xE2, 0xAB, 0x60, + 0x2C, 0x78, 0xFF, 0xFF, 0x4C, 0x4E, 0x47, 0xFF, 0x31, 0x60, 0x0E, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, + 0x04, 0x18, 0xAE, 0x4F, 0x08, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x32, 0x74, 0xCD, 0xE2, 0xA8, 0x60, + 0x8A, 0x78, 0x00, 0x61, 0x10, 0x64, 0x3A, 0xDB, 0xA3, 0x60, 0x4B, 0x78, 0xFF, 0xFF, 0xA3, 0x60, + 0x4B, 0x78, 0xFF, 0xFF, 0x5C, 0x4D, 0x26, 0x44, 0x02, 0x26, 0x0C, 0x00, 0x3E, 0x46, 0x09, 0xF2, + 0x1E, 0x41, 0x03, 0x1B, 0xAA, 0x60, 0xDB, 0x78, 0xFF, 0xFF, 0x40, 0x5E, 0xFD, 0xFB, 0x21, 0x44, + 0x02, 0x64, 0x40, 0x46, 0x41, 0x5D, 0x21, 0x46, 0x00, 0xF2, 0x46, 0x45, 0x87, 0xFC, 0x4C, 0xE2, + 0x01, 0x64, 0x33, 0xFB, 0x01, 0x60, 0x0E, 0xE1, 0x03, 0xE1, 0x3F, 0x40, 0x01, 0x27, 0x00, 0x00, + 0x21, 0x69, 0xB6, 0xFF, 0xA1, 0xFF, 0x6C, 0x5E, 0xB6, 0xFF, 0xB7, 0xFF, 0x60, 0x5C, 0x20, 0x64, + 0x3A, 0xDB, 0x68, 0x43, 0x26, 0xFC, 0x22, 0x69, 0x64, 0x44, 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x5F, + 0x60, 0x43, 0x26, 0xF2, 0xFF, 0xFF, 0x68, 0x5F, 0x26, 0xFA, 0x3A, 0x69, 0x1D, 0xFC, 0x2E, 0x44, + 0x36, 0xF1, 0x1C, 0xFA, 0xC3, 0x94, 0xCD, 0xE2, 0x2E, 0x44, 0x14, 0x36, 0x12, 0x00, 0x0A, 0x36, + 0x0F, 0x00, 0x63, 0x45, 0xE3, 0x83, 0xE3, 0x83, 0xC7, 0x83, 0xE3, 0x83, 0xC7, 0x83, 0xFF, 0xFF, + 0x37, 0x36, 0x05, 0x00, 0x6E, 0x36, 0x04, 0x00, 0xAA, 0x60, 0xF3, 0x78, 0xFF, 0xFF, 0xEB, 0x83, + 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xFF, 0xFF, 0x80, 0x27, 0xCF, 0x83, 0x1B, 0xFC, 0x01, 0x64, + 0x51, 0xFB, 0xA1, 0xFF, 0x1C, 0xF2, 0x29, 0x41, 0xF9, 0x81, 0x52, 0x4A, 0x71, 0x89, 0x68, 0x5F, + 0x27, 0xFA, 0x6C, 0x40, 0x03, 0x15, 0xAB, 0x60, 0x04, 0x78, 0xFF, 0xFF, 0x88, 0x60, 0x85, 0x71, + 0x8D, 0xE2, 0xB9, 0xF1, 0xFC, 0xA3, 0xD3, 0x80, 0x43, 0x43, 0x03, 0x04, 0xAA, 0x60, 0xFB, 0x78, + 0xFF, 0xFF, 0x32, 0x40, 0x01, 0x2A, 0x4C, 0x00, 0x9A, 0xFF, 0x23, 0x43, 0x18, 0x61, 0xA1, 0xFF, + 0x8C, 0x44, 0xCB, 0x83, 0x2A, 0xFA, 0x40, 0x48, 0x40, 0x27, 0x04, 0xA1, 0x60, 0x40, 0x03, 0x2B, + 0x01, 0x00, 0x06, 0xA1, 0x88, 0xB0, 0x88, 0x36, 0xD9, 0x81, 0x62, 0x45, 0x23, 0x44, 0x54, 0x94, + 0x28, 0x40, 0x04, 0x26, 0x00, 0x64, 0x3F, 0xFA, 0xC9, 0x81, 0x65, 0x42, 0x7A, 0xDC, 0x00, 0xB9, + 0xFD, 0x1C, 0x00, 0xF4, 0x6E, 0x61, 0x10, 0x62, 0x14, 0x02, 0x05, 0x1D, 0x12, 0x1E, 0x0C, 0x00, + 0x00, 0xF4, 0x7C, 0x61, 0x02, 0x62, 0x7A, 0xDC, 0x63, 0x40, 0xFD, 0x1C, 0xF9, 0x1D, 0xFF, 0xB1, + 0x08, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, 0xB6, 0xFF, 0xB7, 0xFF, 0xA1, 0xFF, 0x6C, 0x44, + 0x5A, 0xDA, 0x98, 0xFF, 0x01, 0x60, 0x08, 0xE1, 0x81, 0xE1, 0xA1, 0xFF, 0x6C, 0x40, 0xA1, 0xFF, + 0x47, 0xFF, 0x26, 0x44, 0xFD, 0xB4, 0x84, 0xBC, 0x01, 0x15, 0x7F, 0xB4, 0x40, 0x46, 0xA1, 0xFF, + 0x6C, 0x40, 0x14, 0x63, 0x01, 0x11, 0x01, 0x00, 0xFD, 0x1F, 0xAA, 0x60, 0x6E, 0x78, 0xFF, 0xFF, + 0x9A, 0xFF, 0x54, 0x63, 0x12, 0x64, 0x40, 0x46, 0x00, 0x64, 0x0F, 0xFA, 0xA1, 0xFF, 0xEB, 0xF1, + 0x12, 0x61, 0x50, 0xFE, 0x2D, 0x60, 0x52, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, + 0x0B, 0x00, 0x8C, 0x45, 0x98, 0xF8, 0x00, 0x64, 0x3A, 0xFA, 0x3B, 0xFA, 0x3C, 0xFA, 0x3D, 0xFA, + 0xBF, 0x60, 0xFF, 0x64, 0xA4, 0x84, 0x01, 0x00, 0x8C, 0x44, 0xEC, 0xF0, 0xBD, 0xDA, 0x40, 0x48, + 0x04, 0x26, 0x40, 0x00, 0xA1, 0xFF, 0x8C, 0x44, 0xBD, 0xDA, 0x30, 0xFB, 0x6C, 0x44, 0xBD, 0xDA, + 0xFF, 0xFF, 0x01, 0x26, 0x24, 0x00, 0xD0, 0x80, 0xA1, 0xFF, 0x8C, 0x44, 0x6C, 0x5C, 0xF2, 0xFE, + 0xBD, 0xDA, 0xED, 0xF3, 0xD4, 0x80, 0xD0, 0x80, 0xBD, 0xD8, 0x2D, 0x44, 0x15, 0x0C, 0x32, 0x40, + 0x02, 0x2A, 0x07, 0x00, 0x28, 0x42, 0x0C, 0xB2, 0x08, 0x3A, 0x03, 0x00, 0x10, 0xBC, 0x40, 0x4D, + 0x4D, 0x00, 0x03, 0x0A, 0xAB, 0x60, 0x09, 0x78, 0xFF, 0xFF, 0x11, 0xBC, 0x40, 0x4D, 0x28, 0x45, + 0xBF, 0x60, 0xFF, 0x64, 0x24, 0x88, 0x42, 0x00, 0x30, 0xBC, 0x40, 0x4D, 0x3F, 0x00, 0x20, 0xB9, + 0x5C, 0x8E, 0xA1, 0xFF, 0x8C, 0x44, 0xBD, 0xDA, 0xDC, 0x9C, 0x6C, 0x44, 0xF2, 0xFE, 0xBD, 0xDA, + 0x08, 0x28, 0x44, 0x4E, 0xDC, 0x84, 0x2E, 0x5C, 0xB0, 0x84, 0xEF, 0xB1, 0x08, 0x24, 0x40, 0xB9, + 0x41, 0x46, 0x2C, 0x00, 0x8C, 0x44, 0x04, 0x61, 0xBD, 0xDA, 0x50, 0xFE, 0x80, 0x27, 0x00, 0x64, + 0x30, 0xFB, 0x8C, 0x44, 0xBD, 0xDA, 0xD0, 0x80, 0x8C, 0x44, 0xBD, 0xDA, 0xD4, 0x80, 0x00, 0x65, + 0x8C, 0x44, 0xED, 0xF1, 0xBD, 0xDA, 0xD0, 0x80, 0x28, 0x44, 0x03, 0x0C, 0xA0, 0x2A, 0x0A, 0x00, + 0x11, 0x00, 0x10, 0x65, 0x60, 0x40, 0xC4, 0x36, 0x04, 0x00, 0xD4, 0x3A, 0x08, 0x00, 0x27, 0x40, + 0x40, 0x26, 0x30, 0x65, 0x00, 0x64, 0x3F, 0xFA, 0x46, 0x4E, 0x35, 0x8D, 0x5F, 0x00, 0x40, 0x26, + 0xF9, 0x01, 0x30, 0x65, 0x9D, 0xDC, 0x9D, 0xDC, 0x9D, 0xDC, 0xF4, 0x01, 0x00, 0xE1, 0x23, 0x43, + 0xE8, 0xA3, 0x6A, 0x62, 0x9A, 0xFF, 0xA1, 0xFF, 0x28, 0x44, 0x03, 0x2B, 0x04, 0x00, 0x7A, 0xDC, + 0x7A, 0xDC, 0x7A, 0xDC, 0x28, 0x44, 0x88, 0xB0, 0x88, 0x2A, 0x03, 0x00, 0x70, 0x62, 0x7A, 0xDC, + 0x28, 0x44, 0x40, 0x2B, 0x13, 0x00, 0x72, 0x62, 0x7A, 0xDC, 0x04, 0xE6, 0x7A, 0xDC, 0x3B, 0xF2, + 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x2B, 0x02, 0x00, 0x7A, 0xDC, 0x7A, 0xDC, 0x08, 0x60, 0x00, 0xEB, + 0xFC, 0xA3, 0x25, 0xFF, 0x3F, 0xFC, 0x04, 0xA3, 0xB0, 0xFF, 0x01, 0x00, 0x3F, 0xFC, 0xCF, 0x83, + 0xDF, 0x83, 0x04, 0x02, 0x00, 0xF4, 0x10, 0x62, 0x6C, 0x61, 0x1F, 0x00, 0x27, 0x03, 0xCB, 0x83, + 0xFF, 0x60, 0xFE, 0x65, 0x0E, 0xA3, 0xA7, 0x84, 0xF2, 0xA3, 0x00, 0xF4, 0x10, 0x62, 0x6C, 0x61, + 0x7A, 0xDC, 0xFE, 0x1C, 0x03, 0x1D, 0x7C, 0xA8, 0xD9, 0x81, 0x0A, 0x02, 0x00, 0xF4, 0x02, 0x62, + 0xA7, 0x84, 0x7A, 0x61, 0x7A, 0xDC, 0xFE, 0x1C, 0xF9, 0x1D, 0x7C, 0xA8, 0xD9, 0x81, 0xF6, 0x03, + 0xFF, 0xB1, 0x0C, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, 0xA1, 0xFF, 0x01, 0x60, 0x0C, 0xE1, + 0xB6, 0xFF, 0xB7, 0xFF, 0xA1, 0xFF, 0xCD, 0x81, 0x6C, 0x44, 0x5A, 0xDA, 0x98, 0xFF, 0x00, 0xE6, + 0x7C, 0x44, 0x33, 0xFB, 0x01, 0x60, 0x0C, 0xE1, 0x83, 0xE1, 0xA1, 0xFF, 0x8C, 0x44, 0x46, 0x45, + 0xA1, 0xFF, 0x14, 0x63, 0x01, 0x10, 0xFE, 0x1F, 0x01, 0x60, 0x08, 0xE1, 0x0A, 0x64, 0x60, 0x54, + 0x47, 0xFF, 0x50, 0x4B, 0x67, 0x50, 0x69, 0xE2, 0x6A, 0x40, 0x40, 0x2B, 0x01, 0x15, 0x29, 0x00, + 0x6C, 0x40, 0x28, 0x40, 0x03, 0x26, 0x15, 0x00, 0x31, 0x40, 0x20, 0x2A, 0x03, 0x00, 0x28, 0x40, + 0x50, 0x3A, 0x0F, 0x00, 0x2D, 0x44, 0x20, 0x2A, 0x0C, 0x00, 0x2B, 0x44, 0xAC, 0x80, 0x28, 0x40, + 0xB4, 0x3A, 0x03, 0x00, 0x02, 0x03, 0x30, 0xFB, 0x04, 0x00, 0x2B, 0x50, 0xA4, 0x60, 0x85, 0x78, + 0x04, 0xE1, 0x04, 0xE1, 0xA1, 0xFF, 0x35, 0xF1, 0x26, 0x44, 0x64, 0x54, 0xCD, 0xE2, 0x84, 0xBC, + 0x2D, 0x40, 0x0C, 0x22, 0xFD, 0xB4, 0x40, 0x46, 0x23, 0x64, 0x3A, 0xDB, 0xA7, 0x60, 0x18, 0x78, + 0xFF, 0xFF, 0x27, 0x40, 0x26, 0x22, 0x04, 0x00, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xFF, 0xFF, + 0x6C, 0x40, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x37, 0xF3, + 0x2B, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x02, 0x28, 0x65, 0x44, 0x60, 0x50, 0xA0, 0x4C, 0x20, 0xBC, + 0xFF, 0xB4, 0xA0, 0x51, 0x35, 0xF1, 0x74, 0x44, 0xC0, 0x94, 0x32, 0x40, 0x02, 0x2A, 0x18, 0x00, + 0x28, 0x44, 0xA4, 0x36, 0x04, 0x00, 0x0C, 0xB4, 0xFF, 0xFF, 0x04, 0x36, 0x11, 0x00, 0x26, 0x43, + 0xFD, 0xB3, 0x04, 0xBB, 0x43, 0x46, 0x01, 0x2A, 0x03, 0x00, 0x28, 0x47, 0x40, 0xBF, 0x40, 0x48, + 0x0A, 0xBB, 0x0F, 0xFC, 0x50, 0x4B, 0x67, 0x50, 0x00, 0x64, 0x30, 0xFB, 0x05, 0xFF, 0xC6, 0x01, + 0x24, 0x64, 0x3A, 0xDB, 0x28, 0x44, 0x04, 0x2A, 0x06, 0x00, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, + 0xA3, 0x60, 0x3E, 0x78, 0xFF, 0xFF, 0x1D, 0xFF, 0x48, 0xE2, 0x27, 0x44, 0x06, 0x22, 0x05, 0x00, + 0xF9, 0xB4, 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x26, 0x40, 0x10, 0x2A, 0x18, 0x00, + 0x26, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0xFF, 0xB4, 0xC0, 0xA0, 0xFF, 0xFF, 0x11, 0x0E, 0xB8, 0xF1, + 0x27, 0x60, 0x92, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, + 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, + 0xA7, 0x60, 0xE5, 0x78, 0xFF, 0xFF, 0xB8, 0xF1, 0x27, 0x60, 0x94, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, + 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, + 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x2A, 0x64, 0x3A, 0xDB, 0x5C, 0x41, 0x87, 0xE1, + 0xA1, 0xFF, 0x6C, 0x40, 0x02, 0x00, 0x29, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x08, 0xE1, 0x87, 0xE1, + 0xA1, 0xFF, 0x6C, 0x40, 0x11, 0x00, 0x27, 0x60, 0xA6, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, + 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0xF1, 0x01, 0x01, 0x60, 0x08, 0xE1, 0x21, 0x64, 0x3A, 0xDB, + 0x03, 0x00, 0x01, 0x60, 0x08, 0xE1, 0x6C, 0x40, 0x00, 0x64, 0x33, 0xFB, 0x32, 0x74, 0x40, 0x63, + 0x01, 0x16, 0xFE, 0x01, 0x01, 0x68, 0x01, 0x11, 0x09, 0x00, 0xA7, 0x6A, 0x22, 0x64, 0x3A, 0xDB, + 0x03, 0x60, 0xC9, 0x63, 0x01, 0x11, 0x02, 0x00, 0x6C, 0x40, 0xFC, 0x1F, 0x6C, 0x40, 0xB5, 0xFF, + 0x6C, 0x40, 0xBC, 0xFF, 0x6C, 0x40, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, + 0x00, 0x6B, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, 0x03, 0x0A, 0xA3, 0x60, 0x4B, 0x78, 0xFF, 0xFF, + 0x01, 0x64, 0x51, 0xFB, 0x31, 0x60, 0x0E, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0x04, 0x18, 0xAE, 0x4F, + 0x08, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x27, 0x44, 0x06, 0x22, 0x06, 0x00, 0xF9, 0xB4, 0x40, 0x47, + 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x48, 0xE2, 0x27, 0x64, 0x3A, 0xDB, 0xB3, 0xE1, 0xA1, 0xFF, + 0xFF, 0xFF, 0x81, 0x3E, 0x54, 0x62, 0x22, 0x46, 0xA2, 0xD0, 0x16, 0x63, 0x7C, 0x41, 0x44, 0x48, + 0x80, 0x36, 0x04, 0x61, 0x28, 0x40, 0x50, 0x36, 0x04, 0x61, 0x41, 0x4E, 0x28, 0x44, 0xA4, 0x36, + 0x0E, 0x63, 0x1C, 0x60, 0x9C, 0x62, 0xA2, 0xD1, 0x24, 0x44, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, + 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, 0xA2, 0xDB, 0x9A, 0xFF, 0xA1, 0xFF, 0x2D, 0x60, 0x52, 0x62, + 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x06, 0x00, 0x18, 0xF2, 0xAA, 0xF0, 0xFF, 0xFF, + 0xB4, 0x84, 0x08, 0x36, 0x2A, 0xFA, 0x54, 0x62, 0xA2, 0xD2, 0xFF, 0xFF, 0x6A, 0x40, 0x80, 0x4E, + 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0xFF, 0xFF, + 0x01, 0x1D, 0x78, 0x00, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x28, 0x40, 0x03, 0x2B, + 0x04, 0x00, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x6A, 0x40, 0x70, 0x62, 0x28, 0x44, 0x88, 0xB0, + 0x88, 0x36, 0x7A, 0xD4, 0x28, 0x40, 0x40, 0x2B, 0x0B, 0x00, 0x72, 0x62, 0x7A, 0xD4, 0x7A, 0xD4, + 0xA2, 0xD2, 0xFF, 0xFF, 0x60, 0x40, 0x20, 0x2B, 0x02, 0x00, 0x7A, 0xD4, 0x7A, 0xD4, 0x46, 0x00, + 0x23, 0x43, 0xCF, 0x83, 0xDF, 0x83, 0x02, 0x03, 0x55, 0x03, 0x04, 0x00, 0x03, 0xF0, 0x04, 0xF4, + 0x64, 0x42, 0x37, 0x00, 0x2E, 0x40, 0x04, 0x2A, 0x21, 0x00, 0xA1, 0xFF, 0x02, 0xFE, 0x10, 0x25, + 0x42, 0xFE, 0x72, 0x45, 0x65, 0x4C, 0xB5, 0xF3, 0x03, 0x04, 0xE4, 0xE2, 0xDC, 0x84, 0xB5, 0xFB, + 0xA1, 0xFF, 0x80, 0x4C, 0xB6, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB6, 0xFB, 0x80, 0x4C, 0xB7, 0xF3, + 0x02, 0x04, 0xDC, 0x84, 0xB7, 0xFB, 0x80, 0x4C, 0x5C, 0x4E, 0xF8, 0xA3, 0x03, 0xF2, 0x9A, 0xF2, + 0x04, 0xF4, 0xFF, 0xB1, 0xF8, 0xA1, 0x06, 0xA4, 0x60, 0x42, 0x09, 0x00, 0x03, 0xF2, 0x9A, 0xF2, + 0x04, 0xF4, 0xC8, 0x82, 0xFF, 0xB1, 0x03, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0xFF, 0xB1, 0x7A, 0xD4, + 0xFF, 0xFF, 0xFD, 0x1C, 0xF9, 0x1D, 0xFF, 0xB1, 0x17, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0xDA, 0x82, + 0xDA, 0x82, 0xA2, 0xD2, 0xA1, 0xFF, 0x09, 0x74, 0x80, 0x4D, 0x0E, 0x00, 0x03, 0xF2, 0x9A, 0xF2, + 0x04, 0xF4, 0x23, 0x43, 0xA1, 0xFF, 0xA0, 0xD2, 0xFE, 0xA1, 0xCB, 0x83, 0x80, 0x4E, 0xAF, 0x83, + 0x02, 0x1D, 0x02, 0x03, 0xED, 0x01, 0xE3, 0x01, 0xA1, 0xFF, 0x28, 0x40, 0x40, 0x2B, 0x02, 0x00, + 0x9C, 0x4E, 0x9C, 0x4C, 0xA1, 0xFF, 0xDA, 0x83, 0x66, 0x44, 0x22, 0x46, 0x0C, 0xFA, 0x0B, 0xFC, + 0x87, 0x4F, 0x87, 0x4C, 0x87, 0x4F, 0x87, 0x4D, 0x87, 0x4C, 0x01, 0x08, 0x01, 0x00, 0xFF, 0xFF, + 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x44, 0xBC, 0xFF, + 0x01, 0x60, 0x08, 0xE1, 0x0C, 0x74, 0x04, 0xE1, 0xA1, 0xFF, 0x35, 0xF3, 0xC4, 0xE2, 0x60, 0x54, + 0x89, 0xFF, 0x13, 0x74, 0x88, 0xFF, 0x29, 0x44, 0xF7, 0xB4, 0x40, 0x49, 0x34, 0x64, 0x3A, 0xDB, + 0x06, 0xE1, 0x47, 0xFF, 0xA4, 0x60, 0x47, 0x78, 0xFF, 0xFF, 0xFF, 0x01, 0x10, 0x61, 0x7F, 0x60, + 0xC0, 0x64, 0xA0, 0x80, 0x7F, 0x67, 0x02, 0x63, 0x26, 0x02, 0x98, 0xFE, 0x1A, 0x05, 0x24, 0x60, + 0x52, 0x62, 0xA2, 0xD5, 0x0E, 0xF2, 0x15, 0x18, 0x02, 0x18, 0x09, 0xF4, 0xFB, 0x01, 0x23, 0x44, + 0x00, 0xA8, 0x08, 0x7E, 0x0A, 0x02, 0x66, 0x44, 0x11, 0xFB, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, + 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x08, 0xB9, 0x10, 0x7E, 0x00, 0x7F, 0x0E, 0xFA, 0x00, 0x67, + 0x0A, 0x00, 0x20, 0x44, 0xDC, 0x85, 0x0F, 0xB4, 0xFA, 0xA0, 0x7F, 0x67, 0x07, 0x63, 0x03, 0x05, + 0x45, 0x40, 0x00, 0x67, 0xD8, 0xFE, 0xFF, 0x27, 0x05, 0xFD, 0x0A, 0x7E, 0x04, 0xFB, 0x61, 0x55, + 0x4A, 0x00, 0x28, 0xFB, 0x01, 0xF3, 0x29, 0xFB, 0x44, 0x46, 0x40, 0x45, 0x10, 0x61, 0x7E, 0x60, + 0xC0, 0x64, 0xA0, 0x80, 0x7F, 0x67, 0x02, 0x63, 0x31, 0x02, 0xAE, 0x60, 0x58, 0x4F, 0x6F, 0x78, + 0xFF, 0xFF, 0x7F, 0x67, 0x03, 0x63, 0x2A, 0x02, 0x26, 0x40, 0x01, 0x2B, 0x24, 0x00, 0x98, 0xFE, + 0x19, 0x05, 0x24, 0x60, 0x52, 0x62, 0xA2, 0xD5, 0x0E, 0xF2, 0x14, 0x18, 0x02, 0x18, 0x09, 0xF4, + 0xFB, 0x01, 0x23, 0x44, 0x00, 0xA8, 0x08, 0x7E, 0x0A, 0x02, 0x66, 0x44, 0x11, 0xFB, 0x46, 0x43, + 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x08, 0xB9, 0x10, 0x7E, 0x00, 0x7F, + 0x0E, 0xFA, 0x09, 0x00, 0x20, 0x44, 0xDC, 0x85, 0x0F, 0xB4, 0xFA, 0xA0, 0x7F, 0x67, 0x07, 0x63, + 0x05, 0x05, 0x45, 0x40, 0xD8, 0xFE, 0x00, 0x67, 0xD0, 0xFE, 0xD9, 0xFE, 0xFF, 0x27, 0x05, 0xFD, + 0x0B, 0x7E, 0x04, 0xFB, 0x1C, 0x60, 0xB4, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB0, 0x80, 0xBC, + 0x08, 0x28, 0xA3, 0xDB, 0x61, 0x55, 0x63, 0x00, 0x04, 0xB5, 0x82, 0xB5, 0x25, 0x02, 0x04, 0x03, + 0x20, 0x44, 0x7F, 0xB4, 0x40, 0x40, 0xA3, 0xD3, 0x99, 0xFE, 0x04, 0x04, 0x02, 0xBC, 0xFE, 0xB4, + 0xA3, 0xDB, 0x56, 0x00, 0xDC, 0xF3, 0x20, 0x40, 0x80, 0x26, 0x52, 0x00, 0xA3, 0xD3, 0xFF, 0xA0, + 0xF8, 0xB4, 0x02, 0x02, 0xA3, 0xDB, 0x1C, 0x00, 0x04, 0xBC, 0xBF, 0xB4, 0xA3, 0xDB, 0x08, 0xB0, + 0x01, 0x64, 0x08, 0x24, 0x02, 0x64, 0x28, 0xFB, 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, 0xD0, 0xFE, + 0x3F, 0x00, 0xBF, 0xB4, 0xA3, 0xDB, 0x3C, 0x00, 0x40, 0xB0, 0xFF, 0xFF, 0xFA, 0x02, 0xF8, 0xB4, + 0xA3, 0xDB, 0x08, 0xB5, 0x07, 0x7C, 0x01, 0x02, 0xDC, 0xF9, 0x20, 0x44, 0x7F, 0xB4, 0x40, 0x40, + 0x1C, 0x60, 0xB4, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB5, 0x07, 0xB5, 0x08, 0x28, 0xC4, 0x02, + 0x99, 0xFE, 0x26, 0x05, 0x20, 0x44, 0x80, 0x26, 0x23, 0x00, 0x20, 0x2A, 0x00, 0x00, 0x40, 0x2A, + 0x1F, 0x00, 0xBF, 0xB4, 0x40, 0x40, 0x09, 0x00, 0xA8, 0xFF, 0x20, 0x44, 0x99, 0xFE, 0x02, 0x05, + 0x80, 0x2A, 0x03, 0x00, 0x40, 0xBC, 0x40, 0x40, 0x13, 0x00, 0x00, 0xF1, 0x80, 0xBC, 0x40, 0x40, + 0x64, 0x44, 0xE0, 0x84, 0xE8, 0x84, 0x0A, 0x36, 0x29, 0x01, 0x0B, 0x36, 0x5A, 0x01, 0x28, 0xFB, + 0x01, 0xF1, 0x29, 0xF9, 0x02, 0xF1, 0x2A, 0xF9, 0x03, 0xF1, 0x2B, 0xF9, 0xD0, 0xFE, 0xAE, 0xFF, + 0xA1, 0xFF, 0xFF, 0xFF, 0x82, 0x3E, 0x75, 0x44, 0x02, 0xB0, 0x01, 0xB0, 0x29, 0x02, 0xDC, 0x02, + 0x04, 0xB0, 0x08, 0xB0, 0x0B, 0x02, 0x20, 0x02, 0x40, 0x26, 0xA7, 0xFF, 0x8C, 0xFF, 0x75, 0x40, + 0x80, 0x2B, 0x01, 0x00, 0xAB, 0xFF, 0x75, 0x44, 0x8D, 0xFF, 0xEA, 0x01, 0x0A, 0xF3, 0xAA, 0xFF, + 0x60, 0x40, 0x20, 0x2B, 0x02, 0x00, 0x60, 0xFF, 0x0D, 0x00, 0x01, 0x26, 0x0C, 0x00, 0xC0, 0x60, + 0x00, 0x7C, 0xA0, 0x84, 0x80, 0x3B, 0x02, 0x00, 0xC0, 0x67, 0x03, 0x00, 0x40, 0x3B, 0x02, 0x00, + 0x00, 0x67, 0x0A, 0xFB, 0xD5, 0x01, 0xD4, 0x01, 0xAB, 0xFF, 0x38, 0xFF, 0x00, 0x00, 0xD0, 0x01, + 0x79, 0x63, 0xFF, 0xFF, 0xFF, 0x1F, 0xA9, 0xFF, 0x77, 0x44, 0x60, 0x57, 0x10, 0x60, 0x00, 0x75, + 0x40, 0x4A, 0x01, 0x2A, 0x1C, 0x00, 0x24, 0x44, 0xAC, 0x86, 0x08, 0xF2, 0x18, 0x03, 0x24, 0x60, + 0x58, 0x65, 0xD4, 0x80, 0x0E, 0xF2, 0x02, 0x03, 0xA5, 0xD5, 0x04, 0x00, 0x01, 0xBC, 0x0E, 0xFA, + 0x09, 0xF4, 0xD1, 0xFE, 0x46, 0x44, 0x0B, 0x18, 0x66, 0x44, 0x10, 0xFB, 0x66, 0x47, 0x20, 0xBF, + 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x0E, 0xF2, 0x01, 0x75, 0x10, 0xBC, 0x0E, 0xFA, 0x2A, 0x44, + 0x08, 0x2A, 0x18, 0x00, 0x23, 0x44, 0x00, 0xA8, 0x5C, 0x43, 0x14, 0x03, 0x24, 0x60, 0x52, 0x62, + 0xA2, 0xD5, 0x01, 0x00, 0x09, 0xF4, 0x0E, 0xF2, 0x0D, 0x18, 0x08, 0xB0, 0x18, 0xAC, 0xFA, 0x03, + 0x0E, 0xFA, 0x66, 0x43, 0x11, 0xFD, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, + 0xA2, 0xDB, 0x08, 0x75, 0x2A, 0x44, 0x06, 0x22, 0x2D, 0x00, 0x22, 0x44, 0x00, 0xA8, 0x60, 0x46, + 0x0E, 0xF2, 0x28, 0x03, 0x10, 0xB0, 0x01, 0xBC, 0x03, 0x02, 0x00, 0x64, 0x40, 0x42, 0x22, 0x00, + 0x0E, 0xFA, 0xD1, 0xFE, 0x24, 0x60, 0x4C, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x84, 0x00, 0x46, 0x42, + 0x19, 0x02, 0x22, 0x47, 0x40, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x23, 0xF2, 0x66, 0x43, + 0x00, 0xA8, 0x0E, 0xF2, 0x08, 0x02, 0x60, 0x40, 0x02, 0x2A, 0xE4, 0x01, 0x12, 0xFD, 0x10, 0x64, + 0x0E, 0xFA, 0x02, 0x75, 0x07, 0x00, 0x60, 0x40, 0x04, 0x2A, 0xDC, 0x01, 0x12, 0xFD, 0x10, 0x64, + 0x0E, 0xFA, 0x04, 0x75, 0x2A, 0x44, 0x80, 0x2A, 0x19, 0x00, 0x21, 0x44, 0xAC, 0x86, 0x0E, 0xF2, + 0x15, 0x03, 0x01, 0xBC, 0x0E, 0xFA, 0xD1, 0xFE, 0x24, 0x60, 0x64, 0x64, 0x40, 0x47, 0x58, 0x4F, + 0x5A, 0x00, 0x46, 0x41, 0x0B, 0x02, 0x21, 0x47, 0x10, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, + 0x0E, 0xF2, 0x66, 0x43, 0x08, 0xFD, 0x10, 0xBC, 0x0E, 0xFA, 0x80, 0x75, 0x2A, 0x44, 0x10, 0xB0, + 0x20, 0x44, 0x15, 0x03, 0x7F, 0xB4, 0x40, 0x40, 0x1C, 0x60, 0xB4, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, + 0x20, 0xB0, 0x80, 0xB0, 0x09, 0x03, 0x08, 0x03, 0x40, 0xBC, 0x7F, 0xB4, 0x04, 0xB0, 0xA3, 0xDB, + 0x03, 0x03, 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, 0xAC, 0x60, 0xD8, 0x78, 0xFF, 0xFF, 0x2A, 0x40, + 0x08, 0x2B, 0x01, 0x00, 0x10, 0xFF, 0xAD, 0x60, 0x08, 0x78, 0xFF, 0xFF, 0xE8, 0xFE, 0x14, 0x05, + 0xEA, 0xFE, 0x24, 0x05, 0xE9, 0xFE, 0x1C, 0x05, 0xE7, 0xFE, 0x09, 0x05, 0x47, 0xFF, 0x20, 0x44, + 0x0F, 0x22, 0x03, 0x00, 0xCC, 0x84, 0x40, 0x40, 0x0F, 0x22, 0xB8, 0xFE, 0xEC, 0x01, 0x23, 0x41, + 0x00, 0xB9, 0x5C, 0x4A, 0xE8, 0x02, 0x6A, 0x01, 0x24, 0x41, 0x00, 0xB9, 0x24, 0x60, 0x58, 0x65, + 0x45, 0x47, 0xE1, 0x02, 0x58, 0x4F, 0x0F, 0x00, 0xDE, 0x02, 0x5C, 0x4A, 0x46, 0x44, 0x4C, 0x01, + 0x22, 0x41, 0x00, 0xB9, 0x5C, 0x4A, 0x08, 0x24, 0x7D, 0x01, 0xD5, 0x01, 0x21, 0x41, 0x00, 0xB9, + 0x5C, 0x4A, 0xA2, 0x03, 0xD0, 0x01, 0x27, 0xD3, 0x03, 0x00, 0x10, 0xB0, 0x09, 0xF2, 0x04, 0x03, + 0xAC, 0x86, 0x0E, 0xF2, 0xFA, 0x02, 0x08, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0E, 0xF3, 0x0F, 0x60, + 0xFE, 0x65, 0x0C, 0xF3, 0x24, 0x86, 0x24, 0x46, 0x60, 0x40, 0xFB, 0x3B, 0x07, 0x00, 0x80, 0x26, + 0x02, 0x00, 0x23, 0x46, 0x03, 0x4C, 0x46, 0x61, 0x3A, 0x65, 0x0C, 0x00, 0x2E, 0xF3, 0x40, 0x45, + 0xF8, 0x2B, 0x02, 0x00, 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, 0x39, 0x00, 0x07, 0x02, 0x58, 0x4F, + 0x45, 0x00, 0x04, 0x05, 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, 0x09, 0x00, 0x26, 0x47, 0x00, 0xBF, + 0x0E, 0xFB, 0x2E, 0xF5, 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, 0x00, 0x72, 0x7E, 0x71, 0xAC, 0xFF, + 0xAD, 0x60, 0x08, 0x78, 0xFF, 0xFF, 0x8E, 0xFF, 0x0F, 0xF3, 0x0F, 0x60, 0xFE, 0x65, 0x24, 0x86, + 0x0D, 0xF3, 0x2E, 0xF3, 0x40, 0x45, 0xF8, 0x2B, 0x02, 0x00, 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, + 0x16, 0x00, 0x07, 0x02, 0x58, 0x4F, 0x22, 0x00, 0x04, 0x05, 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, + 0x09, 0x00, 0x26, 0x47, 0x00, 0xBF, 0x0F, 0xFB, 0x2E, 0xF5, 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, + 0x00, 0x72, 0x7E, 0x71, 0x8D, 0xFF, 0xAD, 0xFF, 0xAD, 0x60, 0x08, 0x78, 0xFF, 0xFF, 0x25, 0x44, + 0xAA, 0xF1, 0xAB, 0xF1, 0xD0, 0x80, 0xD0, 0x80, 0x07, 0x04, 0x01, 0x06, 0x05, 0x00, 0x25, 0x46, + 0x01, 0xF0, 0x03, 0x67, 0xA0, 0x85, 0x94, 0x80, 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x46, 0x26, 0x41, + 0x46, 0x63, 0x01, 0xF2, 0xFF, 0xFF, 0xFF, 0xB5, 0xD5, 0x81, 0x00, 0xF2, 0x05, 0x04, 0x04, 0x63, + 0x60, 0x46, 0xF7, 0x1B, 0x42, 0xFE, 0x0D, 0x00, 0x61, 0x44, 0xC5, 0x81, 0x63, 0x45, 0xC5, 0x81, + 0x9C, 0x84, 0xDC, 0x84, 0x01, 0xF2, 0xF0, 0x85, 0xF0, 0x80, 0x65, 0x44, 0xF8, 0x85, 0xFF, 0xFF, + 0x02, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, 0x24, 0x60, 0x6A, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, + 0xAC, 0x86, 0x0E, 0xF2, 0x07, 0x03, 0x00, 0xA8, 0x09, 0xF2, 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, + 0x08, 0xFE, 0x17, 0x00, 0xAC, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, 0x00, 0xB4, 0x12, 0x06, 0x09, 0x60, + 0x08, 0x61, 0x41, 0x4A, 0x7C, 0xA1, 0x0E, 0xA1, 0xA2, 0xFF, 0xAE, 0x60, 0x58, 0x4E, 0xE4, 0x78, + 0xFF, 0xFF, 0xA3, 0xFF, 0x06, 0x03, 0x2A, 0x43, 0xAF, 0x60, 0x58, 0x4E, 0x05, 0x78, 0xFF, 0xFF, + 0x08, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0x41, 0x4A, 0x7C, 0xA1, 0x0E, 0xA1, 0xA2, 0xFF, + 0xAE, 0x60, 0x58, 0x4E, 0xE4, 0x78, 0xFF, 0xFF, 0x07, 0x03, 0x2A, 0x43, 0xAF, 0x60, 0x58, 0x4E, + 0x05, 0x78, 0xFF, 0xFF, 0x08, 0xFE, 0x0D, 0x00, 0x24, 0x60, 0x6A, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, + 0xAC, 0x86, 0x0E, 0xF2, 0x06, 0x03, 0x00, 0xA8, 0x09, 0xF2, 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, + 0x08, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0xAD, 0xF3, 0x7C, 0x63, 0x00, 0xBE, 0x40, 0x45, + 0x1A, 0x03, 0x00, 0x65, 0x65, 0x44, 0xDC, 0x85, 0x84, 0xA1, 0x00, 0xF2, 0x06, 0x06, 0x01, 0xFC, + 0x00, 0xA8, 0x60, 0x46, 0xF7, 0x02, 0x40, 0x45, 0x0E, 0x00, 0xAC, 0xF3, 0x00, 0x63, 0xD4, 0x84, + 0xAC, 0xFB, 0x80, 0x60, 0x7C, 0x64, 0x01, 0xFA, 0x00, 0xF0, 0x00, 0xFC, 0xD3, 0x80, 0xAD, 0xF9, + 0x02, 0x02, 0xAE, 0xF9, 0x08, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x66, 0x44, 0x25, 0x46, 0x05, 0xFA, + 0x06, 0xFA, 0x01, 0xF0, 0x03, 0x67, 0x02, 0xFC, 0xB0, 0x84, 0x3A, 0x7E, 0x01, 0xFA, 0x12, 0x64, + 0x03, 0xFA, 0x00, 0xF0, 0x04, 0xF8, 0x00, 0x64, 0x0C, 0x61, 0x10, 0x63, 0x59, 0xDA, 0xFE, 0x1F, + 0x2E, 0x58, 0xFF, 0xFF, 0x27, 0x43, 0xE3, 0x81, 0xE9, 0x81, 0x03, 0x05, 0x16, 0x03, 0x00, 0x61, + 0x01, 0x00, 0xE4, 0x63, 0x61, 0x46, 0xBF, 0xD2, 0x27, 0x45, 0xDC, 0x84, 0xA2, 0xDA, 0xBE, 0xD2, + 0x25, 0x46, 0x88, 0xF8, 0x04, 0x1B, 0x25, 0x44, 0x61, 0x46, 0xA3, 0xDA, 0x04, 0x00, 0x0A, 0xFA, + 0x60, 0x46, 0x25, 0x44, 0x09, 0xFA, 0x61, 0x46, 0xBE, 0xDA, 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x44, + 0x00, 0xA8, 0x07, 0x4B, 0x0C, 0x03, 0x58, 0x4F, 0x33, 0x00, 0x0B, 0x47, 0x24, 0x60, 0x5E, 0x65, + 0x27, 0x44, 0xD4, 0x80, 0x00, 0x64, 0x01, 0x02, 0x0F, 0xFA, 0x58, 0x4F, 0xD3, 0x01, 0x70, 0x00, + 0x25, 0x43, 0xE3, 0x84, 0x7C, 0x41, 0x02, 0x04, 0xE8, 0x81, 0xE4, 0x63, 0x61, 0x46, 0xA3, 0xD2, + 0x00, 0x7C, 0x40, 0x45, 0xBF, 0xD8, 0xA3, 0xD8, 0xBE, 0xD8, 0x27, 0x42, 0x5A, 0xD3, 0x25, 0x5C, + 0x60, 0x41, 0x02, 0x1B, 0x27, 0xD9, 0x05, 0x00, 0x25, 0x46, 0x0A, 0xFA, 0x61, 0x46, 0x25, 0x44, + 0x09, 0xFA, 0x25, 0x44, 0x27, 0x43, 0x00, 0x61, 0x60, 0x46, 0x09, 0xF2, 0x08, 0xFC, 0x00, 0xA8, + 0xDD, 0x81, 0xFA, 0x02, 0xBF, 0xD1, 0x66, 0x44, 0xBE, 0xDB, 0xC1, 0x84, 0xBF, 0xDB, 0x48, 0x00, + 0x25, 0x46, 0xE4, 0x63, 0x08, 0xF2, 0x89, 0xF2, 0x1E, 0x18, 0x40, 0x47, 0xE0, 0x84, 0xE8, 0x85, + 0x02, 0x05, 0xE8, 0x83, 0x00, 0x65, 0x65, 0x46, 0xBF, 0xD2, 0x61, 0x5C, 0xCC, 0x84, 0xA2, 0xDA, + 0x25, 0x46, 0x0A, 0xF2, 0x00, 0xB9, 0x65, 0x46, 0x08, 0x24, 0xBE, 0xDA, 0x02, 0x1B, 0xA3, 0xD8, + 0x02, 0x00, 0x60, 0x46, 0x89, 0xFA, 0x00, 0xB9, 0x61, 0x46, 0x08, 0x28, 0x0A, 0xFA, 0x25, 0x46, + 0x89, 0xFC, 0x8A, 0xFC, 0x88, 0xFC, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x61, 0x28, 0x65, 0x25, 0x43, + 0xAE, 0xF3, 0xAF, 0x83, 0x00, 0xBE, 0x18, 0x03, 0x02, 0x03, 0x00, 0xFC, 0x01, 0x00, 0xAD, 0xFD, + 0x63, 0x46, 0x65, 0x44, 0xCC, 0x85, 0x00, 0xF2, 0x07, 0x02, 0xAE, 0xF5, 0x00, 0x64, 0x00, 0xFA, + 0xDE, 0x60, 0xAF, 0x64, 0x09, 0xFB, 0x08, 0x00, 0x66, 0x43, 0x00, 0xBE, 0xDD, 0x81, 0xF1, 0x02, + 0xAC, 0xF1, 0xAE, 0xFD, 0xC1, 0x84, 0xAC, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x45, + 0x29, 0x43, 0xFC, 0xA3, 0x66, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x00, 0x64, 0xBD, 0xDB, + 0x03, 0x61, 0x0E, 0x65, 0x24, 0x60, 0x72, 0x63, 0x43, 0x49, 0xA3, 0xD3, 0x06, 0xA3, 0x00, 0xA8, + 0xCD, 0x81, 0x04, 0x02, 0xF9, 0x02, 0xAD, 0x60, 0x08, 0x78, 0xFF, 0xFF, 0x01, 0x26, 0xE6, 0x01, + 0xD4, 0x80, 0x60, 0x45, 0xE3, 0x05, 0xF6, 0xA3, 0xBD, 0xD1, 0xBD, 0xD1, 0x44, 0x47, 0x44, 0x48, + 0x44, 0x45, 0x24, 0x60, 0xB0, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x24, 0x60, 0x22, 0x63, + 0x0D, 0x65, 0x00, 0x61, 0x41, 0x48, 0xA3, 0xD3, 0x06, 0xA3, 0xAC, 0x86, 0x00, 0x61, 0x09, 0x03, + 0x00, 0xF2, 0x09, 0xF0, 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x64, 0x44, 0xAC, 0x86, + 0xF6, 0x01, 0x61, 0x44, 0x25, 0x46, 0x27, 0xDA, 0x65, 0x44, 0x28, 0x45, 0x45, 0x88, 0xCC, 0x85, + 0x5A, 0x87, 0xE9, 0x02, 0x00, 0x64, 0x27, 0xDA, 0x5A, 0xDA, 0x5A, 0x87, 0xA9, 0xF3, 0xA8, 0xF1, + 0x02, 0xA4, 0x60, 0x46, 0x60, 0x45, 0x00, 0x61, 0x1E, 0xF2, 0xFF, 0xFF, 0xAC, 0x86, 0x00, 0xF2, + 0x04, 0x03, 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x65, 0x44, 0x02, 0xA5, 0x65, 0x46, + 0x64, 0x44, 0xCC, 0x9C, 0xFF, 0xFF, 0xF0, 0x02, 0x61, 0x44, 0x25, 0x46, 0x27, 0xDA, 0x5A, 0x87, + 0x28, 0x45, 0x45, 0x88, 0x00, 0x64, 0x27, 0xDA, 0x5A, 0x87, 0x06, 0x60, 0x40, 0x65, 0xAD, 0xF3, + 0x01, 0x61, 0xAC, 0x86, 0x00, 0xF2, 0x03, 0x03, 0xD5, 0x80, 0xDD, 0x81, 0xFA, 0x04, 0xCD, 0x84, + 0x25, 0x46, 0x27, 0xDA, 0x28, 0x45, 0xC4, 0x84, 0x5A, 0xDA, 0xDA, 0x81, 0xAC, 0xF1, 0x59, 0xD8, + 0x24, 0x60, 0x20, 0x64, 0x18, 0x63, 0xA0, 0xD1, 0x06, 0xA4, 0x59, 0xD8, 0xFC, 0x1F, 0x00, 0x64, + 0x59, 0xDA, 0x59, 0xDA, 0x01, 0x60, 0x5C, 0x64, 0x0A, 0x63, 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, + 0xDC, 0xF1, 0x59, 0xD8, 0x75, 0x01, 0x07, 0x4B, 0xAF, 0x60, 0x58, 0x4F, 0x70, 0x78, 0xFF, 0xFF, + 0x0B, 0x47, 0x58, 0x4F, 0x21, 0x00, 0x6C, 0x01, 0x07, 0x4B, 0xAF, 0x60, 0x58, 0x4F, 0x70, 0x78, + 0xFF, 0xFF, 0x0B, 0x47, 0x27, 0x44, 0x00, 0xBE, 0x08, 0xF0, 0x15, 0x03, 0x64, 0x42, 0x4A, 0xD3, + 0x09, 0xF2, 0xDC, 0x83, 0xA2, 0xDD, 0x25, 0x43, 0x09, 0xFC, 0x63, 0x46, 0x27, 0x43, 0x0A, 0xFC, + 0x09, 0xFA, 0x08, 0xF8, 0x00, 0xA8, 0x66, 0x43, 0x03, 0x02, 0x64, 0x44, 0x58, 0xDD, 0x03, 0x00, + 0x60, 0x46, 0x25, 0x44, 0x0A, 0xFA, 0x4C, 0x01, 0x27, 0x43, 0xE3, 0x81, 0xE9, 0x81, 0x03, 0x05, + 0x16, 0x03, 0x00, 0x61, 0x01, 0x00, 0xE4, 0x63, 0x61, 0x46, 0xBF, 0xD2, 0x27, 0x45, 0xDC, 0x84, + 0xA2, 0xDA, 0xA3, 0xD2, 0x25, 0x46, 0x88, 0xF8, 0x04, 0x1B, 0x25, 0x44, 0x61, 0x46, 0xBE, 0xDA, + 0x04, 0x00, 0x09, 0xFA, 0x60, 0x46, 0x25, 0x44, 0x0A, 0xFA, 0x61, 0x46, 0xA3, 0xDA, 0x2F, 0x58, + 0xFF, 0xFF, 0xA0, 0xFE, 0x07, 0x05, 0xA3, 0xFE, 0x07, 0x05, 0xA1, 0xFE, 0x52, 0x05, 0x60, 0x64, + 0x3B, 0xDB, 0x12, 0x00, 0x20, 0x58, 0xFF, 0xFF, 0x4F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0x60, + 0xB8, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0xFB, 0xB4, 0xA3, 0xDB, 0xA0, 0x4C, 0x59, 0xBC, 0xFF, 0xB4, + 0xA0, 0x51, 0xA0, 0x4C, 0x7D, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, 0x83, 0x3E, 0x40, 0x60, + 0x0B, 0x65, 0x2B, 0x44, 0x00, 0x63, 0xE8, 0x80, 0xF8, 0x84, 0x02, 0x24, 0x94, 0x84, 0xF3, 0x83, + 0xCD, 0x81, 0xFF, 0xFF, 0xF8, 0x02, 0xDF, 0x83, 0x2F, 0x58, 0x40, 0x4B, 0x00, 0x62, 0x01, 0x64, + 0xD4, 0x80, 0xE0, 0x84, 0x1A, 0x03, 0xD4, 0x80, 0xE0, 0x84, 0x15, 0x03, 0x61, 0x44, 0x11, 0x61, + 0xE0, 0x84, 0xCD, 0x81, 0xFD, 0x04, 0x01, 0x00, 0xE0, 0x84, 0xF2, 0x82, 0xFF, 0xFF, 0x02, 0x24, + 0xC6, 0x82, 0x02, 0x28, 0xD6, 0x82, 0xE2, 0x80, 0xCD, 0x81, 0x02, 0x28, 0x01, 0xBC, 0xF4, 0x02, + 0x01, 0x2A, 0xC6, 0x82, 0x03, 0x00, 0xE9, 0x81, 0xF2, 0x82, 0x61, 0x44, 0x2D, 0x58, 0xFF, 0xFF, + 0x00, 0xA8, 0x10, 0x61, 0x04, 0x03, 0xF0, 0x84, 0xCD, 0x81, 0xFD, 0x04, 0x61, 0x44, 0x2D, 0x58, + 0xFF, 0xFF, 0x00, 0x64, 0x3B, 0xDB, 0x3C, 0x44, 0xAC, 0x80, 0xFF, 0xFF, 0xBD, 0x02, 0x8B, 0xF3, + 0x8C, 0xF3, 0x02, 0xA8, 0x02, 0xA8, 0x08, 0x02, 0x00, 0x64, 0x8D, 0xFB, 0x8B, 0xFB, 0x8C, 0xFB, + 0x00, 0x64, 0x8E, 0xFB, 0xCA, 0xFE, 0x2D, 0x00, 0x03, 0x02, 0x00, 0x64, 0x8C, 0xFB, 0xCA, 0xFE, + 0x01, 0x64, 0x3B, 0xDB, 0x24, 0x60, 0x28, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, + 0x14, 0x03, 0xDC, 0xF3, 0x2A, 0xF2, 0xFD, 0xA0, 0x60, 0x40, 0x80, 0x3A, 0x29, 0x00, 0x28, 0x02, + 0x9B, 0xFE, 0x26, 0x05, 0x24, 0x60, 0x6E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xE5, 0x01, 0x8C, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, + 0xFF, 0xFF, 0x07, 0x02, 0x24, 0x60, 0x22, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, + 0x0F, 0x02, 0x86, 0xFF, 0x20, 0x40, 0x52, 0x27, 0x07, 0x00, 0x9A, 0xFE, 0x05, 0x04, 0x9D, 0xFE, + 0x03, 0x04, 0xF1, 0xFE, 0x12, 0x64, 0x3B, 0xDB, 0x84, 0xFF, 0xB0, 0x60, 0x97, 0x78, 0xFF, 0xFF, + 0x66, 0x44, 0xFC, 0xFB, 0x46, 0x5C, 0x2D, 0x60, 0x5A, 0x63, 0xA3, 0xD3, 0xB0, 0x60, 0x58, 0x4D, + 0xD8, 0x78, 0xFF, 0xFF, 0x0D, 0xF2, 0x60, 0x5C, 0x64, 0x5F, 0x0D, 0xFA, 0x11, 0x64, 0x3B, 0xDB, + 0x9D, 0xFE, 0x0B, 0x05, 0x24, 0x60, 0x92, 0x65, 0x08, 0x64, 0xA5, 0xDB, 0xB1, 0x60, 0x4D, 0x64, + 0x4F, 0xFB, 0x2D, 0xFF, 0xB0, 0x60, 0xA4, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x00, 0x64, 0xD0, 0x80, + 0xA9, 0xF3, 0x07, 0x02, 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xB8, 0x60, 0x36, 0x78, + 0xFF, 0xFF, 0xD0, 0x80, 0xD8, 0xF3, 0x40, 0x03, 0x60, 0x40, 0x03, 0x3A, 0x3D, 0x00, 0x66, 0x41, + 0x64, 0x46, 0x6F, 0xF2, 0x61, 0x46, 0x64, 0x41, 0x4D, 0xF1, 0x60, 0x40, 0x03, 0x3A, 0x34, 0x00, + 0x64, 0x40, 0xFF, 0x22, 0x31, 0x00, 0x05, 0x7E, 0x66, 0x45, 0x61, 0x46, 0x6F, 0xFA, 0x65, 0x46, + 0x07, 0xF0, 0x00, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, + 0x6F, 0xF2, 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, + 0x0E, 0x06, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, + 0xE8, 0x84, 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, + 0xFF, 0xFF, 0x00, 0x64, 0x4D, 0xFB, 0x4C, 0xFB, 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, + 0x61, 0x46, 0xFF, 0xFF, 0xF0, 0x7E, 0x4E, 0xFB, 0x2A, 0xF2, 0x00, 0x63, 0x40, 0x47, 0x50, 0x36, + 0x05, 0x00, 0xA4, 0x36, 0x03, 0x00, 0x80, 0x36, 0x01, 0x00, 0x01, 0x63, 0x48, 0xFD, 0x40, 0x47, + 0x08, 0x2A, 0x0A, 0x00, 0x03, 0x2F, 0x08, 0x00, 0x81, 0xF1, 0x2C, 0xF8, 0x82, 0xF1, 0xFF, 0xFF, + 0x2D, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0xFF, 0xFF, 0x4A, 0xF3, 0x35, 0xFA, 0x10, 0xA4, 0x4A, 0xFB, + 0x00, 0x64, 0x15, 0xFA, 0x16, 0xFA, 0x0F, 0xFA, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, + 0x0E, 0xF0, 0x63, 0x46, 0x00, 0x7F, 0x64, 0x5E, 0x4B, 0xFB, 0x64, 0x44, 0x00, 0x7E, 0xDB, 0xFB, + 0x07, 0xF0, 0xA9, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0xDB, 0xF3, 0xDA, 0xFB, + 0x60, 0x41, 0x03, 0xF2, 0x00, 0xF4, 0x01, 0xF2, 0xFC, 0xA5, 0x00, 0x7F, 0xD4, 0x84, 0x27, 0x45, + 0x3C, 0x46, 0x1A, 0xFA, 0x22, 0x63, 0x7B, 0x60, 0xFF, 0x64, 0xA4, 0x84, 0x03, 0x2B, 0x1C, 0x63, + 0x2A, 0xFA, 0x60, 0x40, 0xA4, 0x36, 0x14, 0x63, 0x43, 0x4C, 0x00, 0x7C, 0x22, 0xF8, 0x64, 0x41, + 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x36, 0xF2, 0x63, 0x46, 0xFF, 0xB4, 0x22, 0xFA, 0x60, 0x40, + 0x00, 0x36, 0x76, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x3A, 0xA5, 0x00, 0x03, 0xF2, + 0x00, 0xF4, 0xA0, 0xD2, 0xAA, 0x60, 0xAA, 0x65, 0x5A, 0xD0, 0xD4, 0x80, 0x03, 0x64, 0x0A, 0x02, + 0xD0, 0x80, 0x00, 0x64, 0x5A, 0xD0, 0x06, 0x02, 0xD0, 0x80, 0xF8, 0x7F, 0xD0, 0x80, 0x01, 0x03, + 0x01, 0x02, 0x01, 0x61, 0x62, 0x43, 0x46, 0x43, 0x3C, 0x46, 0x07, 0xF4, 0x36, 0xF2, 0xFF, 0xFF, + 0xA3, 0x46, 0x60, 0x40, 0x22, 0x26, 0x5C, 0x00, 0x60, 0x45, 0x63, 0x42, 0x5A, 0xD0, 0xCD, 0x81, + 0x3C, 0x46, 0x14, 0x02, 0x64, 0x44, 0x88, 0x3A, 0x11, 0x00, 0x8E, 0x3B, 0x0F, 0x00, 0x65, 0x44, + 0x01, 0x26, 0x7A, 0x00, 0x04, 0x26, 0x03, 0x00, 0x10, 0x26, 0x01, 0x00, 0x2D, 0x00, 0xA3, 0x46, + 0x37, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, 0x6F, 0x00, 0x56, 0x00, 0xA3, 0x46, 0x65, 0x44, + 0x01, 0x26, 0x0B, 0x00, 0x04, 0x26, 0x03, 0x00, 0x10, 0x26, 0x01, 0x00, 0x1D, 0x00, 0x37, 0xF2, + 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x27, 0x48, 0x00, 0x17, 0x00, 0xA9, 0xF3, 0xFF, 0xFF, 0x60, 0x46, + 0x36, 0xF2, 0x66, 0x43, 0xFF, 0xB4, 0x3C, 0x46, 0x22, 0xF0, 0x60, 0x47, 0xB0, 0x84, 0x22, 0xFA, + 0x63, 0x46, 0x37, 0xF0, 0x60, 0x40, 0x04, 0x27, 0x03, 0x00, 0x10, 0x27, 0x01, 0x00, 0x04, 0x00, + 0x64, 0x40, 0x80, 0x27, 0x31, 0x00, 0x00, 0x00, 0x3C, 0x46, 0x02, 0x65, 0xB7, 0x60, 0x66, 0x78, + 0xFF, 0xFF, 0xCD, 0x81, 0x63, 0x42, 0x5A, 0xD0, 0x3C, 0x46, 0x26, 0x02, 0x64, 0x44, 0x88, 0x3A, + 0x23, 0x00, 0x77, 0x37, 0x39, 0x00, 0x78, 0x37, 0x37, 0x00, 0x8E, 0x37, 0x35, 0x00, 0xF1, 0x01, + 0x2D, 0x60, 0x52, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x2D, 0x00, 0x07, 0x00, + 0x2D, 0x60, 0x52, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0xE2, 0x01, 0x3C, 0x46, + 0x3E, 0xF2, 0x40, 0x60, 0x00, 0x65, 0xF0, 0x84, 0xA4, 0x84, 0x18, 0xFA, 0x2A, 0xF2, 0xBF, 0x60, + 0xFF, 0x65, 0xA4, 0x84, 0x2A, 0xFA, 0x18, 0x00, 0x3C, 0x46, 0x22, 0xF0, 0x80, 0x67, 0xB0, 0x84, + 0xA2, 0xDA, 0xFF, 0xFF, 0x3F, 0xF2, 0x3E, 0xF0, 0x08, 0xA4, 0x60, 0x41, 0x22, 0xF2, 0xFF, 0xFF, + 0x60, 0x40, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, 0x03, 0x00, 0x06, 0x00, 0x04, 0x2B, 0x04, 0x00, + 0x61, 0x44, 0x64, 0x40, 0x10, 0x26, 0x3F, 0xFA, 0x3C, 0x46, 0x2C, 0xF2, 0x27, 0x40, 0x01, 0x27, + 0x32, 0xF2, 0xD5, 0xF1, 0x60, 0x40, 0x01, 0x26, 0x53, 0x00, 0x09, 0x60, 0x00, 0x64, 0xD0, 0x80, + 0x3F, 0xF2, 0x09, 0x06, 0x2C, 0x45, 0xC4, 0x84, 0xD0, 0x80, 0x40, 0x4A, 0x40, 0x06, 0x60, 0x43, + 0x64, 0x44, 0x54, 0x88, 0x18, 0x00, 0x60, 0x45, 0x28, 0x60, 0x36, 0x64, 0xA0, 0xD3, 0xDB, 0xF3, + 0x00, 0xBC, 0x60, 0x47, 0xEC, 0xA0, 0x33, 0x03, 0x32, 0x07, 0x2C, 0x44, 0xC4, 0x81, 0x02, 0x60, + 0x1C, 0x65, 0x45, 0x4A, 0xD5, 0x80, 0x2C, 0x45, 0x2A, 0x06, 0x27, 0x40, 0x04, 0x27, 0x30, 0x00, + 0x2A, 0x43, 0xD7, 0x85, 0x45, 0x48, 0xD6, 0xF1, 0x0F, 0xF2, 0xD3, 0x80, 0x01, 0x65, 0x01, 0x07, + 0x00, 0x65, 0xB4, 0x84, 0x0F, 0xFA, 0x00, 0x63, 0x3F, 0xF2, 0x28, 0x45, 0x60, 0x41, 0xD4, 0x84, + 0xDF, 0x83, 0xFC, 0x07, 0x14, 0xFC, 0x61, 0x44, 0x01, 0x36, 0x02, 0x00, 0x09, 0x3A, 0x06, 0x00, + 0x28, 0x44, 0x48, 0x88, 0x2A, 0x44, 0xC8, 0x83, 0x43, 0x4A, 0xE5, 0x01, 0x17, 0xFA, 0x04, 0x60, + 0x00, 0x64, 0x27, 0x45, 0xB4, 0x84, 0x2A, 0xFA, 0x28, 0x43, 0x16, 0xFC, 0x0D, 0x00, 0x3F, 0xF2, + 0x2C, 0x45, 0xD6, 0xF1, 0xC4, 0x81, 0xD1, 0x80, 0x0F, 0xF2, 0x01, 0x06, 0x01, 0xBC, 0x0F, 0xFA, + 0x3F, 0xF2, 0x17, 0xFA, 0x01, 0x64, 0x14, 0xFA, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x0E, 0xF0, + 0x63, 0x46, 0x00, 0x7F, 0x64, 0x5E, 0x4B, 0xFB, 0x64, 0x44, 0x00, 0x7E, 0xDB, 0xFB, 0x7C, 0xF1, + 0x60, 0x43, 0x60, 0x47, 0xD0, 0x80, 0xC0, 0x65, 0x01, 0x06, 0x64, 0x44, 0x0A, 0x36, 0x70, 0x64, + 0x14, 0x36, 0x38, 0x64, 0x37, 0x36, 0x15, 0x64, 0x6E, 0x36, 0x0B, 0x64, 0x44, 0x86, 0x2A, 0xF2, + 0x07, 0xF0, 0x60, 0x40, 0xB0, 0x3A, 0x03, 0x00, 0x40, 0x3B, 0x01, 0x00, 0x12, 0x00, 0x0C, 0xB4, + 0x08, 0x3A, 0x55, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, 0x50, 0x00, 0x17, 0xF2, + 0x22, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x22, 0x22, 0x04, 0x00, 0x00, 0xA8, 0x01, 0xA8, 0x47, 0x03, + 0x46, 0x03, 0x3C, 0x46, 0x2A, 0xF0, 0x40, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x60, 0x45, 0x22, 0xF2, + 0xFF, 0xFF, 0x60, 0x43, 0x60, 0x40, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, 0x0A, 0x00, 0x02, 0x00, + 0x04, 0x27, 0x07, 0x00, 0x65, 0x44, 0x2A, 0x65, 0x60, 0x40, 0x03, 0x2B, 0x24, 0x65, 0x45, 0x4C, + 0x2E, 0x00, 0x65, 0x44, 0x2E, 0x65, 0x60, 0x40, 0x03, 0x2B, 0x28, 0x65, 0x45, 0x4C, 0x07, 0xF0, + 0xA9, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0x00, 0x7C, 0x03, 0x03, 0x63, 0x40, 0x01, 0x2A, 0x01, 0x00, + 0x3D, 0xF1, 0x2A, 0xF2, 0xFF, 0xFF, 0x08, 0xB0, 0x3E, 0xF2, 0x19, 0x03, 0x60, 0x47, 0xE8, 0x84, + 0xE8, 0x84, 0xE8, 0x84, 0x03, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, 0x11, 0x03, 0x24, 0x60, 0x6E, 0x62, + 0x24, 0x60, 0x46, 0x64, 0xA2, 0xDB, 0x3C, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0x5C, 0x5C, 0xFC, 0xFC, 0xCE, 0xFE, 0xB0, 0x60, 0xE1, 0x78, 0xFF, 0xFF, 0xDB, 0xF1, + 0x2C, 0x45, 0x64, 0x43, 0x17, 0xF2, 0x4B, 0xF1, 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, + 0x63, 0x40, 0x37, 0x37, 0xE1, 0x81, 0x64, 0x45, 0xB0, 0x60, 0x58, 0x4D, 0xB6, 0x78, 0xFF, 0xFF, + 0xAE, 0x82, 0xFC, 0xA2, 0x0A, 0x03, 0x63, 0x40, 0x6E, 0x3B, 0x06, 0x00, 0x60, 0x41, 0x04, 0x0D, + 0x63, 0x44, 0x80, 0x7E, 0xDB, 0xFB, 0x61, 0x44, 0xDC, 0x84, 0x2B, 0xF0, 0x1B, 0xFA, 0x64, 0x44, + 0x80, 0x27, 0x34, 0x00, 0x16, 0xF2, 0x0F, 0xF0, 0xAC, 0x84, 0x2C, 0x45, 0x29, 0x03, 0x4B, 0xF1, + 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, 0x63, 0x40, 0x37, 0x37, 0xE1, 0x81, 0x64, 0x45, + 0x0F, 0xF0, 0xB0, 0x60, 0x58, 0x4D, 0xB6, 0x78, 0xFF, 0xFF, 0xAE, 0x82, 0xFC, 0xA2, 0x0A, 0x03, + 0x63, 0x40, 0x6E, 0x3B, 0x06, 0x00, 0x60, 0x41, 0x04, 0x0D, 0x80, 0x67, 0xB0, 0x84, 0x0F, 0xFA, + 0x61, 0x44, 0xDC, 0x84, 0x1D, 0xFA, 0xDE, 0x65, 0xC4, 0x85, 0x26, 0x41, 0xE1, 0x81, 0xC5, 0x84, + 0x2B, 0xFA, 0x1B, 0xF0, 0xDE, 0x64, 0xC0, 0x85, 0x26, 0x44, 0xE0, 0x84, 0xC4, 0x84, 0x10, 0xFA, + 0x26, 0x44, 0x2C, 0xF0, 0x0A, 0xA4, 0x64, 0x40, 0x01, 0x26, 0x00, 0x64, 0x11, 0xFA, 0xDB, 0xF3, + 0x13, 0xFA, 0xFF, 0xFF, 0x0D, 0xF2, 0x3E, 0xF0, 0x60, 0x47, 0xFF, 0xB4, 0x64, 0x41, 0x01, 0xB1, + 0x01, 0x63, 0x1D, 0x02, 0x60, 0x41, 0xFF, 0x22, 0x04, 0x00, 0xB0, 0x60, 0x58, 0x4F, 0xA7, 0x78, + 0xFF, 0xFF, 0x0F, 0x60, 0x92, 0x64, 0xA0, 0xDD, 0x2D, 0x60, 0x5A, 0x62, 0xA2, 0xD3, 0xB0, 0x60, + 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x60, 0x41, 0x01, 0x63, 0x61, 0x40, 0xFF, 0x22, 0x04, 0x00, + 0xB0, 0x60, 0x58, 0x4F, 0xA7, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0x94, 0x64, 0xA0, 0xDD, 0x2A, 0xF2, + 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x27, 0x03, 0x00, 0xB5, 0x60, 0x19, 0x78, 0xFF, 0xFF, 0x22, 0xF2, + 0x46, 0x43, 0x60, 0x40, 0x22, 0x26, 0x8B, 0x00, 0x01, 0x26, 0x05, 0x00, 0x04, 0x26, 0x0C, 0x00, + 0xB5, 0x60, 0x19, 0x78, 0xFF, 0xFF, 0x04, 0x27, 0x03, 0x00, 0xB5, 0x60, 0x19, 0x78, 0xFF, 0xFF, + 0xA9, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0x02, 0x00, 0x07, 0xF4, 0xFF, 0xFF, 0xA3, 0x46, 0x2A, 0xF2, + 0xA3, 0x46, 0x60, 0x40, 0x08, 0x27, 0x3B, 0x00, 0xA9, 0xF3, 0x66, 0x5C, 0xD0, 0x80, 0x37, 0xF0, + 0x08, 0x03, 0x64, 0x40, 0x10, 0x2A, 0x12, 0x00, 0xFF, 0x60, 0xEF, 0x64, 0xA0, 0x84, 0x37, 0xFA, + 0x24, 0x00, 0x3D, 0xF3, 0x01, 0x61, 0x60, 0x43, 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, 0xE9, 0x81, + 0xA1, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0x91, 0x84, 0x37, 0xFA, 0x17, 0x00, 0x47, 0xF2, 0xFF, 0xFF, + 0x10, 0xA0, 0xFF, 0xFF, 0x02, 0x04, 0xFF, 0x60, 0xFF, 0x64, 0xDC, 0x84, 0x47, 0xFA, 0x46, 0xF2, + 0x16, 0x04, 0xDC, 0x84, 0x46, 0xFA, 0x45, 0xF2, 0x08, 0x04, 0xDC, 0x84, 0x45, 0xFA, 0x05, 0x04, + 0x37, 0xF2, 0xFF, 0xFF, 0xE0, 0x84, 0xE8, 0x84, 0x37, 0xFA, 0x0D, 0x60, 0x3E, 0x62, 0x80, 0xFF, + 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xBE, 0x60, 0x66, 0x78, 0xFF, 0xFF, 0x84, 0xFF, 0x0D, 0x60, + 0x3E, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xBE, 0x60, 0xDE, 0x78, 0xFF, 0xFF, + 0x84, 0xFF, 0xA9, 0xF3, 0x66, 0x5C, 0xD0, 0x80, 0x00, 0x7C, 0x07, 0x03, 0x66, 0x43, 0x3C, 0x46, + 0x22, 0xF2, 0x63, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x01, 0x00, 0x3C, 0xF1, 0x47, 0xF0, 0x64, 0x41, + 0x64, 0x47, 0xFF, 0xB4, 0x60, 0x5F, 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, 0x60, 0x47, 0xA3, 0x46, + 0x3A, 0xFA, 0x64, 0x44, 0x20, 0x7F, 0x34, 0x94, 0x3B, 0xFA, 0xA3, 0x46, 0x46, 0xF2, 0x45, 0xF0, + 0xA3, 0x46, 0x3C, 0xFA, 0x3D, 0xF8, 0x08, 0x60, 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, + 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x8A, 0x00, 0x2A, 0xF2, + 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x27, 0x35, 0x00, 0x2A, 0xF2, 0x00, 0x60, 0x7C, 0x62, 0x60, 0x40, + 0x40, 0x2B, 0x27, 0x00, 0xA2, 0xD3, 0x00, 0x61, 0x60, 0xFE, 0xA0, 0xD3, 0xDE, 0x82, 0xA2, 0xD1, + 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0xDC, 0x84, 0xF1, 0x81, 0xC0, 0x2B, 0x04, 0x00, 0x80, 0x2A, + 0x02, 0x00, 0x7F, 0xA4, 0xDC, 0x84, 0xFF, 0x3B, 0x03, 0x00, 0x60, 0x47, 0xDC, 0x87, 0x01, 0x61, + 0xC0, 0x80, 0x00, 0x36, 0xDC, 0x84, 0x4E, 0xDB, 0x60, 0xFE, 0xDA, 0x82, 0xA2, 0xD1, 0xFF, 0xFF, + 0xC1, 0x84, 0xF0, 0x22, 0x10, 0xA4, 0xF0, 0x2A, 0x01, 0x00, 0x00, 0x64, 0xA2, 0xDB, 0xFF, 0xFF, + 0x20, 0xFE, 0x00, 0x60, 0x7C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0xD3, 0x5A, 0xD1, 0x3A, 0xFA, + 0x3B, 0xF8, 0x74, 0x62, 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5A, 0x64, 0x47, + 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, 0x80, 0x62, + 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0xD1, 0x5A, 0xD1, 0x64, 0x45, 0x64, 0x44, 0xE3, 0x7F, 0xA0, 0x5A, + 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5A, 0x64, 0x47, + 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5A, 0x65, 0x40, 0x0D, 0x3A, + 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE9, 0x7F, 0xA0, 0x5A, + 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5A, 0x64, 0x47, + 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEE, 0x7F, + 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEF, 0x7F, 0xA0, 0x5A, 0x08, 0x60, 0x00, 0xEA, 0x65, 0x44, + 0x02, 0xA4, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, + 0x00, 0xEA, 0x02, 0x64, 0x3B, 0xDB, 0xB8, 0x60, 0xBE, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0xFC, 0xFB, + 0x07, 0xF0, 0x00, 0x64, 0xD0, 0x80, 0xA9, 0xF3, 0x17, 0x03, 0xD0, 0x80, 0x66, 0x41, 0x64, 0x46, + 0x6F, 0xF2, 0x61, 0x46, 0x7B, 0x03, 0x60, 0x40, 0x00, 0x36, 0x78, 0x00, 0x47, 0xF1, 0x07, 0xF0, + 0x64, 0x40, 0x02, 0x26, 0x01, 0x00, 0x0B, 0x00, 0x03, 0x12, 0xB6, 0x60, 0x38, 0x78, 0xFF, 0xFF, + 0xFC, 0x0A, 0xB7, 0x60, 0x56, 0x78, 0xFF, 0xFF, 0xB7, 0x60, 0x56, 0x78, 0xFF, 0xFF, 0x66, 0x41, + 0x64, 0x46, 0x0E, 0xF2, 0x60, 0x45, 0x61, 0x46, 0x10, 0x7E, 0x4E, 0xFB, 0x65, 0x44, 0x60, 0x40, + 0x01, 0x36, 0x5C, 0x00, 0x02, 0x36, 0x5D, 0x00, 0x03, 0x36, 0x34, 0x00, 0x04, 0x36, 0x45, 0x00, + 0x67, 0x00, 0x00, 0x64, 0x4C, 0xFB, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x05, 0x7E, + 0x6F, 0xFA, 0x61, 0x46, 0x00, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, + 0x00, 0xA8, 0x6F, 0xF2, 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, + 0x07, 0x03, 0x0E, 0x06, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, + 0xB9, 0x81, 0xE8, 0x84, 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, + 0x0C, 0xF4, 0xFF, 0xFF, 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xFF, 0xFF, 0xA0, 0x7E, + 0x4E, 0xFB, 0x24, 0x00, 0x4C, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x4C, 0xFB, 0xCB, 0xF3, 0x60, 0x45, + 0xD4, 0x80, 0xFF, 0xFF, 0x1B, 0x02, 0x24, 0x60, 0xA6, 0x62, 0x0F, 0x60, 0x96, 0x64, 0xA2, 0xDB, + 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xBC, 0x01, 0x4C, 0xF3, 0x66, 0x41, 0xDC, 0x84, + 0x4C, 0xFB, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x03, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x66, 0x41, + 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xFF, 0xFF, 0xA4, 0x7E, 0x4E, 0xFB, 0xB7, 0x60, 0x56, 0x78, + 0xFF, 0xFF, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, 0x6F, 0xFA, 0x61, 0x46, + 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xFF, 0xFF, 0xA8, 0x7E, 0x4E, 0xFB, 0xEE, 0x01, + 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0x8C, 0xFA, 0x60, 0x47, 0x70, 0xF2, 0xFF, 0xB5, 0x08, 0x18, + 0xE4, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0xFB, 0x04, 0x01, 0x64, 0x01, 0x00, 0x00, 0x64, + 0x0C, 0xF4, 0x00, 0xA8, 0xFF, 0xFF, 0xDD, 0x02, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, + 0x60, 0x47, 0x70, 0xF2, 0xFF, 0xB5, 0x61, 0x46, 0x00, 0xA8, 0xFF, 0xFF, 0x29, 0x03, 0xE0, 0x84, + 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0x66, 0x41, 0x64, 0x46, 0x70, 0xFA, 0x61, 0x46, 0x01, 0x65, + 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, 0x15, 0x03, + 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, 0xE8, 0x84, + 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, 0xD9, 0x81, + 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, 0x95, 0x01, + 0x94, 0x01, 0x65, 0x44, 0x60, 0x40, 0x01, 0x36, 0xA1, 0x01, 0x02, 0x36, 0x01, 0x00, 0x9E, 0x01, + 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x00, 0x65, + 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, 0x15, 0x03, + 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, 0xE8, 0x84, + 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, 0xD9, 0x81, + 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, 0x66, 0x41, + 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xD0, 0x7E, 0x4E, 0xFB, 0xB7, 0x60, 0x56, 0x78, 0xFF, 0xFF, + 0x60, 0x45, 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0x20, 0x7E, 0x4E, 0xFB, 0x65, 0x44, + 0x60, 0x40, 0x01, 0x36, 0x0B, 0x00, 0x02, 0x36, 0x1A, 0x00, 0x03, 0x36, 0x53, 0x00, 0x04, 0x36, + 0x70, 0x00, 0x05, 0x36, 0x14, 0x00, 0xB7, 0x60, 0x56, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x41, + 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x02, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x66, 0x41, 0x64, 0x46, + 0x0E, 0xF2, 0x61, 0x46, 0xB0, 0x7E, 0x4E, 0xFB, 0xB7, 0x60, 0x56, 0x78, 0xFF, 0xFF, 0x07, 0xF0, + 0x01, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, + 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, + 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, + 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, + 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0x00, 0x63, 0x03, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x4C, 0xFD, + 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xB4, 0x7E, 0x4E, 0xFB, 0x24, 0x60, 0xA6, 0x62, + 0x0F, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xB7, 0x60, + 0x56, 0x78, 0xFF, 0xFF, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x4C, 0xF3, 0x02, 0xB0, 0x61, 0x46, + 0xCC, 0x84, 0x05, 0x03, 0x04, 0x28, 0x4C, 0xFB, 0xB7, 0x60, 0x56, 0x78, 0xFF, 0xFF, 0x04, 0x28, + 0x4C, 0xFB, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x04, 0x7E, 0x6F, 0xFA, 0x61, 0x46, + 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xB8, 0x7E, 0x4E, 0xFB, 0xB7, 0x60, 0x56, 0x78, + 0xFF, 0xFF, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, + 0x61, 0x46, 0xFF, 0xA0, 0xFF, 0xFF, 0x35, 0x06, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, + 0xFB, 0x04, 0x2F, 0x00, 0x64, 0x46, 0x70, 0xFA, 0x01, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, + 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, + 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, + 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, + 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, 0x6F, 0xF2, 0x00, 0x63, 0x03, 0x7E, 0x6F, 0xFA, + 0x3C, 0x46, 0x4C, 0xFD, 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xC0, 0x7E, 0x4E, 0xFB, + 0x5D, 0x00, 0x5C, 0x00, 0x65, 0x44, 0x60, 0x40, 0x01, 0x36, 0x03, 0x00, 0x02, 0x36, 0x18, 0x00, + 0x55, 0x00, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x61, 0x46, 0x01, 0xB0, 0xFF, 0xFF, 0x4E, 0x02, + 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x02, 0x7E, 0x6F, 0xFA, 0x61, 0x46, + 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xE0, 0x7E, 0x4E, 0xFB, 0x3F, 0x00, 0x3E, 0x00, + 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, 0x6F, 0xFA, 0x60, 0x47, + 0xFF, 0xB5, 0x70, 0xF2, 0x61, 0x46, 0xFF, 0xA0, 0xFF, 0xFF, 0xF1, 0x06, 0xE8, 0x84, 0xA4, 0x80, + 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0xEB, 0x01, 0x66, 0x41, 0x64, 0x46, 0x70, 0xFA, 0x61, 0x46, + 0x00, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, + 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, + 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, + 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, + 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xE4, 0x7E, 0x4E, 0xFB, 0x03, 0x64, 0x3B, 0xDB, + 0xCA, 0xFE, 0x47, 0xF1, 0x01, 0x65, 0x32, 0x40, 0x04, 0x27, 0x08, 0x00, 0x2C, 0xF2, 0x64, 0x45, + 0x02, 0x22, 0x04, 0x00, 0x60, 0x40, 0x01, 0x26, 0x01, 0x00, 0xE3, 0x00, 0x14, 0xF2, 0x65, 0x40, + 0x01, 0x26, 0x1D, 0x00, 0x60, 0x45, 0x05, 0x64, 0x3B, 0xDB, 0x65, 0x44, 0xCC, 0x85, 0xB8, 0xF1, + 0x27, 0x60, 0x78, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, + 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, + 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xAF, 0x00, 0x60, 0x41, + 0x2A, 0xF0, 0x00, 0x60, 0x0C, 0x64, 0xA0, 0x84, 0x04, 0x36, 0x02, 0x00, 0x0C, 0x3A, 0x01, 0x00, + 0xA5, 0x00, 0x61, 0x45, 0x60, 0x41, 0xB8, 0xF1, 0x27, 0x60, 0x78, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, + 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, + 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, + 0x00, 0x75, 0x88, 0xFF, 0x61, 0x40, 0x08, 0x36, 0x01, 0x00, 0x88, 0x00, 0x14, 0xF2, 0x1C, 0x65, + 0x60, 0x41, 0x00, 0x63, 0xCD, 0x81, 0xC7, 0x83, 0xFD, 0x02, 0x3F, 0xF0, 0x2C, 0xF2, 0xC3, 0x83, + 0x60, 0x40, 0x01, 0x2A, 0x29, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x76, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, + 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, + 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xB8, 0xF1, 0x27, 0x60, 0x7C, 0x64, 0xA0, 0xD3, + 0x63, 0x45, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, + 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, + 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x52, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x74, 0x64, 0xA0, 0xD3, + 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, + 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xB8, 0xF1, 0x27, 0x60, 0x7A, 0x64, + 0xA0, 0xD3, 0x63, 0x45, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, + 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, + 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x15, 0xF2, 0xFF, 0xFF, 0x0F, 0xB4, 0x00, 0xA8, + 0x01, 0xA8, 0x24, 0x03, 0x12, 0x03, 0xB8, 0xF1, 0x27, 0x60, 0x82, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, + 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, + 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x11, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x80, 0x64, + 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, + 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x04, 0x64, 0x3B, 0xDB, + 0x24, 0x60, 0x6E, 0x62, 0x24, 0x60, 0x46, 0x64, 0xA2, 0xDB, 0x3C, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x5C, 0x5C, 0xFC, 0xFC, 0xCE, 0xFE, 0xB0, 0x60, 0xE1, 0x78, + 0xFF, 0xFF, 0x0F, 0xF0, 0x15, 0xF2, 0x64, 0x41, 0x01, 0x2A, 0x02, 0x00, 0xD1, 0xF1, 0x02, 0x00, + 0xD0, 0xF1, 0xFF, 0xFF, 0x64, 0x45, 0xDC, 0x84, 0xD4, 0x80, 0x15, 0xFA, 0x30, 0x07, 0x61, 0x40, + 0x01, 0x2A, 0x09, 0x00, 0x27, 0x60, 0xA8, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, + 0x08, 0x28, 0xA2, 0xDB, 0x08, 0x00, 0x27, 0x60, 0xAA, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, + 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x2A, 0xF0, 0x08, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x00, 0x64, + 0x48, 0xFB, 0x2D, 0x60, 0x52, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x0C, 0x00, + 0x3C, 0x46, 0x3E, 0xF2, 0x40, 0x60, 0x00, 0x65, 0xF0, 0x84, 0xA4, 0x84, 0x18, 0xFA, 0x2A, 0xF2, + 0xBF, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x2A, 0xFA, 0xB2, 0x60, 0xFC, 0x78, 0xFF, 0xFF, 0x00, 0x64, + 0x49, 0xFB, 0xB8, 0xF1, 0x27, 0x60, 0x82, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, + 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, + 0x00, 0x75, 0x88, 0xFF, 0xB8, 0xF1, 0x27, 0x60, 0x84, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, + 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, + 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x2D, 0x60, 0x5A, 0x63, 0xA3, 0xD3, 0xB0, 0x60, 0x58, 0x4D, + 0xD8, 0x78, 0xFF, 0xFF, 0x0D, 0xF2, 0x60, 0x5C, 0x64, 0x5F, 0x0D, 0xFA, 0x23, 0xF0, 0x01, 0x64, + 0xB0, 0x84, 0xA2, 0xDA, 0x7B, 0x01, 0xB9, 0x60, 0x43, 0x78, 0xFF, 0xFF, 0x21, 0x64, 0x3B, 0xDB, + 0x31, 0xF3, 0x01, 0x63, 0xC4, 0xB4, 0x31, 0xFB, 0x32, 0xFD, 0xB8, 0x60, 0xEF, 0x62, 0x42, 0x40, + 0xA0, 0x4C, 0x40, 0xBC, 0x7D, 0xB4, 0xA0, 0x51, 0xA0, 0xFE, 0x1A, 0xFF, 0x24, 0x60, 0x3A, 0x64, + 0x08, 0xF0, 0x07, 0xF0, 0xD0, 0x80, 0x24, 0x60, 0x40, 0x62, 0x14, 0x02, 0xA2, 0xD3, 0x01, 0x63, + 0xAC, 0x86, 0x07, 0xF2, 0x0F, 0x03, 0xD0, 0x80, 0x09, 0xF2, 0xFA, 0x02, 0x23, 0xFC, 0x24, 0x60, + 0x6E, 0x62, 0x24, 0x60, 0x46, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0x3C, 0x46, 0x06, 0x64, 0xA1, 0xFF, 0x49, 0xFB, 0x83, 0x3E, 0x31, 0xF3, + 0x87, 0x60, 0x80, 0x61, 0x1D, 0xF0, 0x60, 0x40, 0x01, 0x2A, 0x15, 0x00, 0xFE, 0xB4, 0x31, 0xFB, + 0x00, 0x64, 0x49, 0xFB, 0x01, 0x64, 0x47, 0xFB, 0x2D, 0x60, 0x5A, 0x63, 0xA3, 0xD3, 0xB0, 0x60, + 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x71, 0x64, 0x5F, 0x0D, 0xFA, 0x40, 0x64, 0x3B, 0xDB, + 0xB9, 0x60, 0x43, 0x78, 0xFF, 0xFF, 0x02, 0x2A, 0x1B, 0x00, 0xD1, 0x91, 0x8D, 0xE2, 0x41, 0x64, + 0x3B, 0xDB, 0x31, 0xF3, 0x2D, 0x60, 0x62, 0x63, 0xFD, 0xB4, 0x31, 0xFB, 0xA3, 0xD3, 0xB0, 0x60, + 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x02, 0x63, 0x60, 0x5C, 0x0D, 0xF2, 0x47, 0xFD, 0xFF, 0xB5, + 0x60, 0x47, 0xD0, 0x80, 0xDC, 0x84, 0x1F, 0x03, 0x60, 0x47, 0xB4, 0x84, 0x0D, 0xFA, 0x1B, 0x00, + 0x08, 0x2A, 0x07, 0x00, 0x42, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, 0xF7, 0xB4, 0x31, 0xFB, + 0x12, 0x00, 0x10, 0x2A, 0x09, 0x00, 0x43, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, 0xEF, 0xB4, + 0x31, 0xFB, 0xB8, 0x60, 0xBE, 0x78, 0xFF, 0xFF, 0x44, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, + 0xDF, 0xB4, 0x31, 0xFB, 0x00, 0x00, 0x2A, 0x64, 0x3B, 0xDB, 0xB0, 0x60, 0x97, 0x64, 0x40, 0x40, + 0xB5, 0x60, 0x1E, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xB8, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x02, 0xB5, + 0x04, 0xB5, 0x04, 0x03, 0x03, 0x03, 0xBA, 0x60, 0x3C, 0x78, 0xFF, 0xFF, 0x86, 0xFF, 0x20, 0x44, + 0x84, 0xFF, 0x20, 0x2A, 0x04, 0x00, 0xF3, 0x60, 0x58, 0x4E, 0x14, 0x78, 0xFF, 0xFF, 0x31, 0x40, + 0x01, 0x26, 0x17, 0x00, 0xA0, 0x4C, 0x49, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0x1C, 0x60, 0xB8, 0x63, + 0xA3, 0xD3, 0xFF, 0xFF, 0x02, 0xB5, 0x04, 0xBC, 0x09, 0x03, 0x60, 0x40, 0x01, 0x26, 0xED, 0xE2, + 0xFE, 0xB4, 0xA3, 0xDB, 0xA0, 0x4C, 0x7D, 0xB4, 0xA0, 0x51, 0x03, 0x00, 0xA0, 0x4C, 0x6D, 0xB4, + 0xA0, 0x51, 0xDC, 0xF3, 0xFF, 0xFF, 0xFD, 0xA0, 0xFF, 0xFF, 0x48, 0x03, 0x31, 0x40, 0x04, 0x2A, + 0x3E, 0x00, 0x6D, 0xF3, 0x74, 0xF3, 0xCC, 0x83, 0x6D, 0xFD, 0xCC, 0x84, 0x74, 0xFB, 0x1F, 0x02, + 0x31, 0x40, 0x02, 0x2A, 0x12, 0x00, 0x6F, 0xF3, 0x70, 0xF1, 0xCC, 0x84, 0x6F, 0xFB, 0x0D, 0x02, + 0x6F, 0xF9, 0x31, 0x44, 0x08, 0xBC, 0x40, 0x51, 0x72, 0xF3, 0x71, 0xF1, 0x00, 0xB8, 0x64, 0x45, + 0x01, 0x03, 0x67, 0x45, 0x65, 0x50, 0xCC, 0x84, 0x73, 0xFB, 0x28, 0x60, 0x00, 0x64, 0xA0, 0xD3, + 0x6E, 0xF1, 0x00, 0xB8, 0x74, 0xF9, 0x03, 0x03, 0x87, 0xF3, 0x6D, 0xFB, 0x04, 0x00, 0x6D, 0xF3, + 0x87, 0xF1, 0x15, 0x1B, 0x6D, 0xF9, 0x31, 0x40, 0x01, 0x2A, 0x11, 0x00, 0xDD, 0xFE, 0x0F, 0x05, + 0xBA, 0xFE, 0xAD, 0x4F, 0x00, 0x7F, 0x01, 0xBC, 0xA0, 0x5D, 0x00, 0xEE, 0x7F, 0xF1, 0x02, 0x60, + 0xEE, 0x64, 0xA3, 0xFB, 0xA4, 0xF9, 0x04, 0x64, 0xA5, 0xFB, 0xDF, 0xFE, 0x19, 0xFF, 0x1A, 0x60, + 0x42, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xFF, 0x2B, 0xA2, 0xDB, 0x31, 0x40, 0x01, 0x2A, + 0x29, 0x00, 0x9D, 0xFE, 0x27, 0x04, 0x26, 0x0A, 0x9F, 0xFE, 0x24, 0x05, 0x85, 0xFF, 0x20, 0x44, + 0x84, 0xFF, 0x40, 0x26, 0x1F, 0x00, 0x3F, 0x40, 0x20, 0x2B, 0x1C, 0x00, 0x38, 0x69, 0xFF, 0xFF, + 0x68, 0x44, 0x01, 0x16, 0xFD, 0x01, 0x01, 0x2A, 0x15, 0x00, 0x27, 0x60, 0xB4, 0x64, 0xA0, 0xD3, + 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x7F, 0xF1, 0x02, 0x60, 0xEE, 0x64, + 0xA3, 0xFB, 0xFF, 0xFF, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA4, 0xFB, 0x04, 0x64, 0xA5, 0xFB, + 0xDF, 0xFE, 0x19, 0xFF, 0x10, 0x64, 0x3B, 0xDB, 0x80, 0xF3, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x93, 0xC9, 0xFE, 0x49, 0xF3, 0x3C, 0x46, 0x27, 0x18, 0xCC, 0x84, + 0x49, 0xFB, 0x24, 0x02, 0xBB, 0x60, 0x18, 0x64, 0x40, 0x42, 0xFC, 0xFC, 0x00, 0x64, 0x5C, 0x5C, + 0x32, 0xFB, 0x82, 0xFF, 0x5C, 0x47, 0x84, 0xFF, 0x62, 0xFF, 0x27, 0x60, 0xA4, 0x64, 0xA0, 0xD3, + 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x23, 0xF0, 0x01, 0x64, 0xB0, 0x84, + 0xA2, 0xDA, 0x24, 0x60, 0x6E, 0x62, 0x24, 0x60, 0x46, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xCE, 0xFE, 0x6A, 0xF3, 0xFF, 0xFF, + 0x60, 0x41, 0xFD, 0xB4, 0xA2, 0xDB, 0x61, 0x44, 0x01, 0xB0, 0x02, 0xB0, 0x0C, 0x03, 0x0B, 0x02, + 0x9D, 0xFE, 0x09, 0x04, 0x24, 0x60, 0xA6, 0x62, 0x1A, 0x60, 0xA2, 0x64, 0xA2, 0xDB, 0x02, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x07, 0x00, 0x80, 0xF3, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x93, 0x1C, 0x60, 0xB4, 0x63, 0xA3, 0xD3, 0xAD, 0x49, 0x20, 0xB5, + 0x08, 0xB1, 0x23, 0x03, 0xE1, 0x81, 0x10, 0xB5, 0x95, 0x81, 0x60, 0x41, 0x18, 0x02, 0x1C, 0x60, + 0xB6, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA4, 0xDB, 0x17, 0x02, 0x05, 0x64, 0xA4, 0xDB, + 0x61, 0x44, 0x07, 0xB4, 0xFF, 0xFF, 0x11, 0x02, 0x08, 0xB1, 0xE1, 0x81, 0x95, 0x81, 0xA3, 0xD3, + 0x0C, 0x03, 0x08, 0xAC, 0x01, 0xBC, 0xA3, 0xDB, 0xFF, 0xFF, 0x13, 0xFF, 0x06, 0x00, 0x10, 0xAC, + 0xA3, 0xDB, 0x1C, 0x60, 0xB6, 0x63, 0x05, 0x7C, 0xA3, 0xD9, 0xB0, 0x60, 0xA4, 0x78, 0xFF, 0xFF, + 0x46, 0xF3, 0x45, 0xF1, 0x05, 0x1B, 0x64, 0x44, 0x03, 0x1B, 0x0F, 0x60, 0x92, 0x62, 0xA2, 0xD3, + 0x45, 0xFB, 0x00, 0x63, 0x46, 0xFD, 0x60, 0x41, 0x25, 0x64, 0x3B, 0xDB, 0x27, 0x44, 0xEF, 0xB4, + 0x40, 0x47, 0x00, 0xB9, 0x71, 0x40, 0x80, 0x27, 0x01, 0x12, 0x2B, 0x03, 0xBA, 0x60, 0x93, 0x62, + 0x84, 0xFF, 0x42, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0x31, 0x0A, + 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, 0x2B, 0x0A, 0x71, 0x40, 0x80, 0x27, + 0xF7, 0x12, 0x45, 0xF3, 0x4C, 0x02, 0x15, 0x18, 0x31, 0x60, 0x0E, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, + 0x0B, 0x18, 0x31, 0x60, 0x10, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0x06, 0x18, 0xAC, 0x4C, 0x80, 0x26, + 0x03, 0x00, 0x00, 0x64, 0x45, 0xFB, 0x05, 0x00, 0x45, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0x45, 0xFB, + 0xDF, 0x02, 0x06, 0x0A, 0xA0, 0x4C, 0xFB, 0xB4, 0xA0, 0x51, 0xA3, 0x60, 0x99, 0x78, 0xFF, 0xFF, + 0x84, 0xFF, 0xBA, 0x60, 0x70, 0x64, 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, + 0xA0, 0x51, 0xAB, 0x60, 0x2C, 0x78, 0xFF, 0xFF, 0x3C, 0x44, 0xAC, 0x80, 0x32, 0xF1, 0x25, 0x03, + 0x64, 0x40, 0x07, 0x22, 0x22, 0x00, 0xA3, 0x60, 0x7B, 0x78, 0xFF, 0xFF, 0xA0, 0x4C, 0x1C, 0xBC, + 0xDF, 0xB4, 0xA0, 0x51, 0x31, 0x40, 0x08, 0x2A, 0xEF, 0x01, 0x73, 0xF3, 0x71, 0xF1, 0x00, 0xA0, + 0xDC, 0x80, 0x05, 0x03, 0x08, 0x03, 0xCC, 0x84, 0x73, 0xFB, 0x67, 0x50, 0x08, 0x00, 0xCC, 0x84, + 0x73, 0xFB, 0x64, 0x50, 0x04, 0x00, 0x31, 0x44, 0xF7, 0xB4, 0x40, 0x51, 0x06, 0x00, 0x28, 0x64, + 0x3A, 0xDB, 0xA0, 0x4C, 0x30, 0xBC, 0xF3, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, + 0x28, 0x64, 0x3B, 0xDB, 0x0F, 0x60, 0x94, 0x62, 0xA2, 0xD3, 0x32, 0x40, 0x02, 0x27, 0x16, 0x00, + 0x46, 0xFB, 0x14, 0x18, 0xBB, 0x60, 0x06, 0x64, 0x84, 0xFF, 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, + 0x14, 0xBC, 0xF7, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, + 0x46, 0xF3, 0xB7, 0x0A, 0xDC, 0x02, 0xCC, 0x84, 0x46, 0xFB, 0xF5, 0x02, 0x84, 0xFF, 0xBB, 0x60, + 0x18, 0x64, 0x40, 0x42, 0x82, 0xFF, 0x27, 0x44, 0x08, 0xBC, 0x40, 0x47, 0xBB, 0xE1, 0x04, 0x00, + 0x3A, 0xE1, 0x31, 0x40, 0x01, 0x26, 0xBB, 0xE1, 0xA3, 0x60, 0x6F, 0x78, 0xFF, 0xFF, 0x43, 0xFF, + 0x39, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x84, 0x3E, 0xFB, 0x01, 0xA0, 0x4C, 0x3D, 0x46, 0x2A, 0xF2, + 0x46, 0x4D, 0x10, 0x25, 0x0E, 0x00, 0x09, 0xE1, 0xA1, 0xFF, 0x66, 0x40, 0x0F, 0xF2, 0x01, 0x29, + 0x02, 0x00, 0x40, 0xFF, 0x0A, 0xBC, 0xA2, 0xDA, 0x08, 0x25, 0xE9, 0x01, 0xCB, 0xFE, 0x5C, 0x5D, + 0xE7, 0x01, 0x44, 0xFF, 0x31, 0xF2, 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, + 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, + 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, + 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA9, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, + 0x07, 0xFC, 0x3F, 0xF2, 0x09, 0x60, 0xB0, 0x65, 0xD4, 0x80, 0x2A, 0xF2, 0xC4, 0x05, 0x08, 0x25, + 0xB6, 0x01, 0x00, 0x64, 0x0D, 0x60, 0x2C, 0x61, 0x40, 0x4B, 0xA1, 0xDB, 0x2D, 0x46, 0x3B, 0xF2, + 0xA9, 0xF1, 0x87, 0xF4, 0x60, 0x40, 0x20, 0x2B, 0x12, 0x00, 0xD3, 0x80, 0x2C, 0xF0, 0xB3, 0x03, + 0x07, 0xF4, 0x64, 0x40, 0x01, 0x26, 0xA9, 0xF5, 0xB6, 0xF4, 0x2D, 0x46, 0x04, 0x64, 0x04, 0xB3, + 0x22, 0xFA, 0x04, 0x03, 0xBC, 0x60, 0x72, 0x78, 0xFF, 0xFF, 0x01, 0x00, 0xDE, 0x00, 0x74, 0x62, + 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, + 0xA0, 0x5B, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0x7C, 0x5F, 0xE8, 0x84, 0xE8, 0x85, + 0x0C, 0x60, 0x3A, 0x64, 0x44, 0xD3, 0x5A, 0xD1, 0x03, 0x1B, 0xBC, 0x60, 0x65, 0x78, 0xFF, 0xFF, + 0x60, 0x45, 0x64, 0x44, 0xE3, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, + 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, + 0xE7, 0x7F, 0xA0, 0x5B, 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, + 0xA0, 0x5B, 0x64, 0x44, 0xE9, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, + 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, + 0xED, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xEF, 0x7F, + 0xA0, 0x5B, 0x65, 0x44, 0xD8, 0x84, 0x08, 0x25, 0x76, 0x00, 0x60, 0x7F, 0xA0, 0x5B, 0x80, 0x60, + 0x00, 0xEB, 0xA0, 0x60, 0x00, 0xEB, 0xD1, 0x60, 0x00, 0xEB, 0x3F, 0xF2, 0x04, 0x65, 0xC4, 0x83, + 0x0A, 0xE1, 0xB3, 0xFF, 0x9A, 0xFF, 0xCB, 0x83, 0x00, 0xF4, 0x10, 0x62, 0x6C, 0x61, 0x0E, 0xA3, + 0xAB, 0x84, 0xF2, 0xA3, 0xA1, 0xFF, 0x08, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0x02, 0x62, 0xC9, 0x81, + 0xAB, 0x84, 0xA1, 0xFF, 0x01, 0x00, 0xA2, 0xDC, 0x7A, 0xD4, 0xFD, 0x1C, 0xA2, 0xDC, 0x08, 0x25, + 0x52, 0x00, 0xF2, 0x1D, 0x7C, 0xA8, 0xD9, 0x81, 0xEF, 0x03, 0xFF, 0xB1, 0x09, 0x1E, 0x02, 0x02, + 0x00, 0xF4, 0x02, 0x62, 0x5A, 0xD2, 0x89, 0xFF, 0x80, 0x4F, 0x6F, 0x44, 0xA2, 0xDA, 0x88, 0xFF, + 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, 0x3D, 0x46, 0x08, 0x25, 0x3D, 0x00, 0x40, 0xFF, 0x0F, 0xF0, + 0x0A, 0x64, 0xB0, 0x84, 0x16, 0x14, 0xF7, 0xB4, 0xA2, 0xDA, 0x0D, 0x60, 0x2C, 0x62, 0xA2, 0xD3, + 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x0C, 0x00, 0xF1, 0xF5, 0xF0, 0xF4, 0x0D, 0x60, 0x2C, 0x61, + 0x59, 0xD1, 0x37, 0xF8, 0x05, 0x64, 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, 0xFC, 0x02, 0x2D, 0x46, + 0x0D, 0x01, 0xA2, 0xDA, 0x2D, 0x46, 0x3B, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x20, 0x2B, 0x18, 0x00, + 0xF1, 0xF5, 0xB7, 0xF0, 0x2A, 0x44, 0xA4, 0x84, 0xFF, 0xFF, 0x2F, 0x26, 0x10, 0x00, 0x2D, 0x46, + 0x64, 0x44, 0x3A, 0xF0, 0xBC, 0xF0, 0x64, 0x5F, 0x3D, 0xF0, 0x07, 0xF4, 0xF0, 0xF4, 0xFF, 0xFF, + 0x08, 0xA3, 0x5B, 0xD8, 0x65, 0x5C, 0x5B, 0xD8, 0x5B, 0xDA, 0x2D, 0x46, 0x01, 0x00, 0x2D, 0x46, + 0xBB, 0x60, 0x36, 0x78, 0xFF, 0xFF, 0x98, 0xFF, 0x43, 0xFF, 0x40, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, + 0x2D, 0x46, 0x0D, 0x60, 0x2C, 0x61, 0xA1, 0xD3, 0x2D, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x0A, 0x00, + 0xF1, 0xF5, 0xF0, 0xF4, 0x59, 0xD1, 0x37, 0xF8, 0x05, 0x64, 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, + 0xFC, 0x02, 0x2D, 0x46, 0xBB, 0x60, 0x20, 0x78, 0xFF, 0xFF, 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, + 0x3D, 0x46, 0x08, 0x25, 0xE0, 0x01, 0x0F, 0xF2, 0x40, 0xFF, 0x02, 0xBC, 0xA2, 0xDA, 0xBB, 0x60, + 0x36, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x0D, 0x60, 0x2C, 0x62, 0xA2, 0xDB, 0x04, 0x64, 0x22, 0xFA, + 0x87, 0xF4, 0xA9, 0xF1, 0xFF, 0xFF, 0xD3, 0x80, 0x3B, 0xF2, 0xE7, 0x03, 0x60, 0x47, 0xC0, 0xB7, + 0x02, 0xFE, 0xF0, 0x84, 0xF0, 0x84, 0xF0, 0x84, 0x00, 0xA8, 0x40, 0x4A, 0x16, 0x03, 0xE0, 0x81, + 0x61, 0x43, 0x42, 0xFE, 0x00, 0x64, 0xF0, 0x84, 0xFE, 0x1F, 0x40, 0x4A, 0xE1, 0x84, 0xE0, 0x84, + 0x2D, 0x46, 0x07, 0xF4, 0xE0, 0x81, 0x37, 0xF0, 0x2A, 0x47, 0x0C, 0x60, 0x7A, 0x63, 0xA0, 0x84, + 0x47, 0x9C, 0x10, 0x03, 0x7C, 0x44, 0xA0, 0x63, 0x11, 0x00, 0x20, 0x64, 0x40, 0x4A, 0x63, 0x46, + 0x37, 0xF0, 0x66, 0x44, 0x64, 0x40, 0x80, 0x2B, 0x05, 0x00, 0x00, 0x60, 0x70, 0x7C, 0x00, 0x60, + 0x90, 0x63, 0x04, 0x00, 0x2D, 0x46, 0xBC, 0x60, 0x65, 0x78, 0xFF, 0xFF, 0x2D, 0x46, 0xEE, 0xFB, + 0xEF, 0xF9, 0xF0, 0xFD, 0x07, 0xF2, 0xF1, 0xFB, 0x60, 0x46, 0x37, 0xF0, 0x2A, 0x44, 0x0D, 0x60, + 0x2C, 0x62, 0x5A, 0xD9, 0x00, 0x65, 0x45, 0x4B, 0xA0, 0x84, 0xFF, 0xFF, 0x3F, 0x22, 0x05, 0x00, + 0x90, 0x84, 0x37, 0xFA, 0x01, 0x64, 0x40, 0x4B, 0x21, 0x00, 0xAD, 0x46, 0x0A, 0xA3, 0x3D, 0xF2, + 0xAD, 0x46, 0xA3, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3C, 0xF2, 0xAD, 0x46, 0x02, 0x03, 0x16, 0x07, + 0x14, 0x04, 0x5B, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3B, 0xF2, 0x03, 0x03, 0xAD, 0x46, 0x0E, 0x07, + 0x0C, 0x04, 0x3A, 0xF0, 0xAD, 0x46, 0x5B, 0xD0, 0x64, 0x5F, 0xD0, 0x80, 0x2B, 0x44, 0x18, 0x07, + 0x04, 0x03, 0xD0, 0x84, 0x10, 0xA4, 0xFF, 0xFF, 0x13, 0x07, 0x7F, 0x01, 0x01, 0x64, 0x0D, 0x60, + 0x2C, 0x62, 0xA2, 0xDB, 0x2D, 0x46, 0x0D, 0x60, 0x3C, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, + 0xA2, 0xDB, 0xBD, 0x60, 0x0B, 0x78, 0xFF, 0xFF, 0x85, 0xFF, 0x2D, 0x46, 0x08, 0x25, 0x53, 0x01, + 0x2D, 0x46, 0x0D, 0x60, 0x3C, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xBD, 0x60, + 0x94, 0x78, 0xFF, 0xFF, 0x85, 0xFF, 0x2D, 0x46, 0x08, 0x25, 0x45, 0x01, 0x00, 0x60, 0x0F, 0x64, + 0xBB, 0x60, 0xD3, 0x78, 0xFF, 0xFF, 0x07, 0xF4, 0x66, 0x41, 0x03, 0xF2, 0x04, 0xF2, 0x40, 0x42, + 0x05, 0xF2, 0x40, 0x43, 0x40, 0x44, 0x61, 0x46, 0x3C, 0xF2, 0x3D, 0xF2, 0x40, 0x40, 0x40, 0x41, + 0x0D, 0x60, 0x70, 0x65, 0x00, 0x61, 0xEF, 0xF1, 0xEE, 0xF5, 0x44, 0x4C, 0x2C, 0x5C, 0xE9, 0x80, + 0x00, 0x64, 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, 0x24, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x20, 0x44, 0x40, 0x80, 0xDB, 0x83, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x21, 0x44, 0x40, 0x81, 0xDB, 0x83, 0xBD, 0xD2, 0x21, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x22, 0x44, 0x40, 0x82, 0xDB, 0x83, 0xBD, 0xD2, 0x22, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x23, 0x44, 0x40, 0x83, 0xF2, 0xA3, 0xBD, 0xD2, 0x23, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x24, 0x44, 0xC0, 0x9C, 0x41, 0x84, 0xDD, 0x81, 0x08, 0x2A, 0xA7, 0x01, 0x0D, 0x60, + 0x2E, 0x61, 0x05, 0x64, 0xF0, 0xF4, 0xF1, 0xF5, 0xFE, 0xA3, 0x5B, 0xD0, 0xCC, 0x84, 0x59, 0xD9, + 0xFC, 0x02, 0xF0, 0xF3, 0xF1, 0xF5, 0x60, 0x42, 0x20, 0x44, 0xA2, 0xDA, 0x21, 0x44, 0x5A, 0xDA, + 0x22, 0x44, 0x5A, 0xDA, 0x23, 0x44, 0x5A, 0xDA, 0x24, 0x44, 0x5A, 0xDA, 0x61, 0x46, 0x0D, 0x60, + 0x3C, 0x62, 0xA2, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x41, 0xF0, 0xF3, 0xF1, 0xF5, 0xA0, 0xD2, + 0x5A, 0xD0, 0x40, 0x40, 0x44, 0x41, 0x5A, 0xD2, 0x5A, 0xD0, 0x40, 0x42, 0x5A, 0xD0, 0x44, 0x43, + 0x61, 0x46, 0xBA, 0xF0, 0x3B, 0xF2, 0x44, 0x44, 0x65, 0x5F, 0x40, 0x85, 0xEF, 0xF4, 0xEE, 0xF5, + 0x43, 0x4C, 0x0D, 0x60, 0x70, 0x65, 0xBD, 0xD2, 0x25, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x20, 0x44, 0x40, 0x80, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x21, 0x44, + 0x40, 0x81, 0xBD, 0xD2, 0x21, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x22, 0x44, 0x40, 0x82, + 0xBD, 0xD2, 0x22, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x23, 0x44, 0x40, 0x83, 0xBD, 0xD2, + 0x23, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x24, 0x44, 0x40, 0x84, 0xBD, 0xD2, 0x24, 0x5C, + 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x25, 0x44, 0x40, 0x85, 0x61, 0x46, 0x3A, 0xF0, 0xFF, 0xFF, + 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5B, 0x64, 0x44, + 0xE2, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xEE, 0xF5, 0xBD, 0xD2, 0x25, 0x5C, 0x90, 0x84, 0xE8, 0x80, + 0xF8, 0x84, 0x20, 0x5C, 0x40, 0x80, 0x20, 0x44, 0xE4, 0x7F, 0xA0, 0x5B, 0x20, 0x47, 0xE5, 0x7F, + 0xA0, 0x5B, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x21, 0x5C, 0x40, 0x81, + 0x21, 0x44, 0xE6, 0x7F, 0xA0, 0x5B, 0x21, 0x47, 0xE7, 0x7F, 0xA0, 0x5B, 0x21, 0x44, 0xE8, 0x80, + 0xF8, 0x84, 0x22, 0x5C, 0x40, 0x82, 0x22, 0x44, 0xE8, 0x7F, 0xA0, 0x5B, 0x22, 0x47, 0xE9, 0x7F, + 0xA0, 0x5B, 0x22, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x23, 0x5C, 0x40, 0x83, 0x23, 0x44, 0xEA, 0x7F, + 0xA0, 0x5B, 0x23, 0x47, 0xEB, 0x7F, 0xA0, 0x5B, 0x23, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x24, 0x5C, + 0x40, 0x84, 0x24, 0x44, 0xEC, 0x7F, 0xA0, 0x5B, 0x24, 0x47, 0xED, 0x7F, 0xA0, 0x5B, 0x24, 0x44, + 0xE8, 0x80, 0xF8, 0x84, 0x25, 0x5C, 0x40, 0x85, 0x25, 0x44, 0xEE, 0x7F, 0xA0, 0x5B, 0x25, 0x47, + 0xEF, 0x7F, 0xA0, 0x5B, 0x2C, 0x43, 0xA3, 0xD2, 0x25, 0x5C, 0x90, 0x81, 0xE9, 0x84, 0xE3, 0x7F, + 0xA0, 0x5B, 0x0D, 0x60, 0x3C, 0x62, 0xA2, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0xF3, 0x5A, 0xD3, + 0x40, 0x48, 0x5A, 0xD3, 0x40, 0x49, 0x40, 0x4A, 0x00, 0x60, 0x70, 0x7C, 0x44, 0x4D, 0x45, 0xF2, + 0x46, 0xF2, 0x40, 0x47, 0x40, 0x46, 0x0D, 0x60, 0x70, 0x65, 0x00, 0x61, 0x2D, 0x5C, 0xE9, 0x80, + 0x00, 0x64, 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, 0x2A, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x26, 0x44, 0x40, 0x86, 0xDB, 0x83, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x27, 0x44, 0x40, 0x87, 0xDB, 0x83, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x28, 0x44, 0x40, 0x88, 0xDB, 0x83, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x29, 0x44, 0x40, 0x89, 0xF2, 0xA3, 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x2A, 0x44, 0xC0, 0x9C, 0x41, 0x8A, 0xDD, 0x81, 0x08, 0x2A, 0xA7, 0x01, 0x26, 0x44, + 0x40, 0xFA, 0x27, 0x44, 0x41, 0xFA, 0x28, 0x44, 0x42, 0xFA, 0x29, 0x44, 0x43, 0xFA, 0x2A, 0x44, + 0x44, 0xFA, 0x0D, 0x60, 0x3E, 0x62, 0xA2, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x80, 0x7C, + 0x44, 0x4D, 0x2D, 0x42, 0xA2, 0xD2, 0x5A, 0xD0, 0x40, 0x46, 0x44, 0x47, 0x5A, 0xD2, 0x5A, 0xD0, + 0x40, 0x48, 0x5A, 0xD0, 0x44, 0x49, 0x47, 0xF2, 0x44, 0x4A, 0x40, 0x8B, 0x60, 0x5C, 0x64, 0x47, + 0xE0, 0x7F, 0xA0, 0x5A, 0xFF, 0xB4, 0x20, 0xBC, 0x7F, 0xB4, 0xE1, 0x7F, 0xA0, 0x5A, 0x64, 0x44, + 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, 0x70, 0x63, 0x0D, 0x60, 0x70, 0x65, 0xBD, 0xD2, 0x2B, 0x5C, + 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x26, 0x44, 0x40, 0x86, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x27, 0x44, 0x40, 0x87, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x28, 0x44, 0x40, 0x88, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x29, 0x44, 0x40, 0x89, 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2A, 0x44, + 0x40, 0x8A, 0xBD, 0xD2, 0x2A, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2B, 0x44, 0x40, 0x8B, + 0xBD, 0xD2, 0x2B, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x26, 0x5C, 0x40, 0x86, 0x26, 0x44, + 0xE4, 0x7F, 0xA0, 0x5A, 0x26, 0x47, 0xE5, 0x7F, 0xA0, 0x5A, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x84, + 0xE8, 0x80, 0xF8, 0x84, 0x27, 0x5C, 0x40, 0x87, 0x27, 0x44, 0xE6, 0x7F, 0xA0, 0x5A, 0x27, 0x47, + 0xE7, 0x7F, 0xA0, 0x5A, 0x27, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x28, 0x5C, 0x40, 0x88, 0x28, 0x44, + 0xE8, 0x7F, 0xA0, 0x5A, 0x28, 0x47, 0xE9, 0x7F, 0xA0, 0x5A, 0x28, 0x44, 0xE8, 0x80, 0xF8, 0x84, + 0x29, 0x5C, 0x40, 0x89, 0x29, 0x44, 0xEA, 0x7F, 0xA0, 0x5A, 0x29, 0x47, 0xEB, 0x7F, 0xA0, 0x5A, + 0x29, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x2A, 0x5C, 0x40, 0x8A, 0x2A, 0x44, 0xEC, 0x7F, 0xA0, 0x5A, + 0x2A, 0x47, 0xED, 0x7F, 0xA0, 0x5A, 0x2A, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x2B, 0x5C, 0x40, 0x8B, + 0x2B, 0x44, 0xEE, 0x7F, 0xA0, 0x5A, 0x2B, 0x47, 0xEF, 0x7F, 0xA0, 0x5A, 0x38, 0xF0, 0x2B, 0x44, + 0x90, 0x84, 0xE8, 0x84, 0xE3, 0x7F, 0xA0, 0x5A, 0x0D, 0x60, 0x3E, 0x62, 0xA2, 0xD7, 0xFF, 0xFF, + 0xFF, 0xFF, 0xE4, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x80, 0x60, + 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x32, 0x00, 0xDC, 0xF3, 0x31, 0x41, 0x01, 0xB1, + 0x03, 0xA8, 0x2D, 0x03, 0x17, 0x02, 0x20, 0x40, 0x04, 0x2B, 0x0C, 0x00, 0xBB, 0xFE, 0xCA, 0xFE, + 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0x08, 0x00, 0x0F, 0x60, 0xD2, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x80, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x0C, 0x00, 0xA9, 0xFE, 0xD8, 0x05, 0xAB, 0xFE, 0x0C, 0x05, 0xA8, 0xFE, + 0xC8, 0x05, 0xAA, 0xFE, 0xC9, 0x05, 0x78, 0x43, 0x01, 0x61, 0x24, 0x60, 0xDD, 0x78, 0xA1, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x85, 0x3E, 0x24, 0x60, 0x5E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, + 0x60, 0x46, 0x03, 0x02, 0xBF, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0x26, 0x45, 0xD4, 0x80, 0x0F, 0xF0, + 0xF9, 0x03, 0x64, 0x44, 0x70, 0xB0, 0x70, 0x2A, 0x14, 0x00, 0x27, 0x60, 0xB2, 0x64, 0xA0, 0xD3, + 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0xA2, 0xFF, 0xAF, 0xF3, 0xFF, 0xFF, + 0xCC, 0x84, 0xFE, 0xA0, 0xAF, 0xFB, 0x01, 0x07, 0xD4, 0xFE, 0xA3, 0xFF, 0xC5, 0x60, 0x5B, 0x78, + 0xFF, 0xFF, 0x64, 0x40, 0x02, 0x26, 0x09, 0x00, 0x66, 0x45, 0x09, 0xF4, 0x0F, 0xF2, 0x02, 0x18, + 0x65, 0x46, 0xE3, 0x1B, 0x00, 0x64, 0x40, 0x46, 0xCA, 0x01, 0xA2, 0xFF, 0xAF, 0xF3, 0x46, 0x46, + 0xCC, 0x84, 0xFE, 0xA0, 0xAF, 0xFB, 0x01, 0x07, 0xD4, 0xFE, 0xA3, 0xFF, 0x0F, 0xF0, 0xA3, 0xFC, + 0x64, 0x44, 0x80, 0x26, 0x22, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x92, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, + 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, + 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, 0x07, 0x60, + 0x01, 0x64, 0x04, 0x00, 0x02, 0x2A, 0x06, 0x00, 0x00, 0x60, 0x01, 0x64, 0x23, 0xFA, 0xC5, 0x60, + 0x67, 0x78, 0xFF, 0xFF, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, 0x08, 0x26, 0x3F, 0x00, 0x2A, 0xF2, + 0x60, 0x63, 0x60, 0x40, 0x02, 0x2B, 0x66, 0x63, 0xBE, 0xD2, 0x83, 0xF1, 0xA3, 0xD2, 0xD0, 0x80, + 0x82, 0xF1, 0x18, 0x02, 0xBF, 0xD2, 0xD0, 0x80, 0x81, 0xF1, 0x14, 0x02, 0xD0, 0x80, 0xFF, 0xFF, + 0x11, 0x02, 0xB8, 0xF1, 0x27, 0x60, 0x9E, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, + 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, + 0x00, 0x75, 0x88, 0xFF, 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, 0x07, 0x60, 0x02, 0x64, 0x04, 0x00, + 0x02, 0x2A, 0x06, 0x00, 0x00, 0x60, 0x02, 0x64, 0x23, 0xFA, 0xC5, 0x60, 0x67, 0x78, 0xFF, 0xFF, + 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0xB0, 0x3A, 0x06, 0x00, 0x00, 0x60, 0x02, 0x64, 0x23, 0xFA, + 0xC1, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, 0x32, 0x44, 0x01, 0x2A, + 0x4A, 0x00, 0x28, 0x60, 0xE2, 0x63, 0xBF, 0xD3, 0x00, 0x65, 0xB4, 0x81, 0xDB, 0x83, 0x3D, 0x03, + 0xBF, 0xD3, 0xA3, 0xD3, 0x40, 0x48, 0xBE, 0xD3, 0x40, 0x4A, 0x2E, 0xF0, 0x40, 0x4C, 0xD0, 0x80, + 0x2D, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x2C, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, + 0xFF, 0xFF, 0x2B, 0x03, 0x31, 0xF0, 0x2C, 0x44, 0xD0, 0x80, 0x30, 0xF0, 0x08, 0x02, 0x2A, 0x44, + 0xD0, 0x80, 0x2F, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x1E, 0x03, 0x34, 0xF0, + 0x2C, 0x44, 0xD0, 0x80, 0x33, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x32, 0xF0, 0x04, 0x02, + 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x11, 0x03, 0x38, 0xF0, 0x2C, 0x44, 0xD0, 0x80, 0x37, 0xF0, + 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x36, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, + 0x04, 0x03, 0xFA, 0xA1, 0x06, 0xA3, 0xB7, 0x03, 0xC3, 0x01, 0x07, 0x60, 0x00, 0x64, 0x23, 0xFA, + 0xC5, 0x60, 0x67, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x0F, 0xF0, 0x60, 0x45, 0xA4, 0x36, 0x08, 0x00, + 0x0C, 0xB4, 0x04, 0x36, 0x02, 0x00, 0x0C, 0x3A, 0x06, 0x00, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, + 0xC2, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0x0F, 0xF0, 0x65, 0x40, 0x40, 0x2B, 0x22, 0x00, 0x32, 0x40, + 0x08, 0x26, 0x1F, 0x00, 0x07, 0xF4, 0x36, 0xF2, 0xFF, 0xFF, 0x37, 0xB4, 0x26, 0x46, 0x19, 0x02, + 0x2C, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x11, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x98, 0x64, + 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, + 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xC5, 0x60, 0x5B, 0x78, + 0xFF, 0xFF, 0x2A, 0xF2, 0x64, 0x40, 0x60, 0x26, 0x03, 0x00, 0xC2, 0x60, 0xAF, 0x78, 0xFF, 0xFF, + 0x60, 0x41, 0xA9, 0xF3, 0x07, 0xFA, 0x61, 0x44, 0x80, 0x3A, 0x06, 0x00, 0xE5, 0x60, 0x58, 0x4F, + 0xE7, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x10, 0x00, 0x60, 0x40, 0x40, 0x3A, 0x0D, 0x00, 0xDC, 0xF3, + 0xFF, 0xFF, 0x07, 0xB4, 0x03, 0x3A, 0xE2, 0x01, 0xC6, 0x60, 0x58, 0x4D, 0x4F, 0x78, 0xFF, 0xFF, + 0xDD, 0x02, 0xA9, 0xF3, 0x07, 0xFA, 0xD1, 0x00, 0x5E, 0x63, 0x60, 0x40, 0x02, 0x2B, 0x64, 0x63, + 0x50, 0xFE, 0xBD, 0xD2, 0x81, 0xF1, 0xBD, 0xD2, 0xD0, 0x80, 0x82, 0xF1, 0xBD, 0xD2, 0xD0, 0x80, + 0x83, 0xF1, 0x2A, 0xF2, 0xD0, 0x80, 0x60, 0x40, 0x08, 0x3A, 0x07, 0x00, 0x01, 0x0C, 0xC6, 0x01, + 0xDE, 0x60, 0x58, 0x4F, 0xFE, 0x78, 0xFF, 0xFF, 0xB8, 0x00, 0x26, 0x0C, 0xC6, 0x60, 0x58, 0x4D, + 0x4F, 0x78, 0xFF, 0xFF, 0xBB, 0x02, 0x1F, 0x60, 0x52, 0x61, 0x02, 0x64, 0xA1, 0xDB, 0x1F, 0x60, + 0x5A, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x22, 0x60, 0x58, 0x4E, 0x3E, 0x78, 0xFF, 0xFF, 0x1F, 0x60, + 0x04, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x27, 0x08, 0x00, 0x0F, 0x60, 0xEA, 0x62, + 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x1F, 0x60, 0x52, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x9B, 0x01, 0x91, 0x00, 0xC6, 0x60, 0x58, 0x4D, 0x4F, 0x78, 0xFF, 0xFF, + 0xFA, 0x02, 0x0F, 0x60, 0xCE, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x36, 0x07, 0x00, + 0x01, 0x64, 0xA1, 0xDB, 0x01, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0x31, 0xF2, 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, + 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, + 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, + 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, + 0x63, 0x46, 0xE8, 0x1B, 0xA9, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0xA9, 0xF1, 0x43, 0x43, + 0xD3, 0x80, 0xFF, 0xFF, 0x04, 0x02, 0xC5, 0x60, 0x58, 0x4F, 0xA5, 0x78, 0xFF, 0xFF, 0x32, 0x40, + 0x08, 0x2A, 0x05, 0x00, 0x63, 0x46, 0x80, 0x60, 0x02, 0x64, 0x06, 0xFA, 0x26, 0x46, 0xD8, 0xF3, + 0x63, 0x45, 0x66, 0x41, 0x65, 0x46, 0x8C, 0xFA, 0x60, 0x40, 0x01, 0x36, 0x06, 0x00, 0x02, 0x36, + 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x64, 0x01, 0x00, 0x01, 0x64, + 0x6F, 0xFA, 0x79, 0xF3, 0x7A, 0xF1, 0xFF, 0xFF, 0xA0, 0x84, 0x65, 0x43, 0x02, 0x02, 0x79, 0xF3, + 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, 0xAE, 0x65, 0xD8, 0xF3, 0xFF, 0xFF, 0xE0, 0x84, 0x44, 0xD3, + 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x04, 0x02, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, + 0xA4, 0x84, 0x7B, 0xFB, 0x6F, 0xF0, 0x60, 0x47, 0x90, 0x84, 0x6F, 0xFA, 0x60, 0x47, 0x60, 0x45, + 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x70, 0xF0, 0x70, 0xFA, + 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, 0x02, 0x05, 0xDD, 0x81, 0xFB, 0x01, 0xE1, 0x81, 0x0F, 0x60, + 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x66, 0x43, 0x0C, 0xF4, 0xB8, 0xF1, 0x27, 0x60, 0x8C, 0x64, + 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, + 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x27, 0xF2, 0xFF, 0xFF, + 0x60, 0x40, 0x01, 0x3B, 0x12, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x9A, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, + 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, + 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x13, 0x00, 0x02, 0x3B, 0x11, 0x00, 0xB8, 0xF1, + 0x27, 0x60, 0x9C, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, + 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, + 0x1B, 0xF2, 0xFF, 0xFF, 0xE4, 0xA4, 0x3E, 0xFA, 0x2A, 0xF2, 0x28, 0x41, 0x40, 0xA8, 0x01, 0xB1, + 0x02, 0x02, 0x62, 0x02, 0x92, 0x00, 0x60, 0x40, 0x08, 0x2A, 0x2B, 0x00, 0xB8, 0xF1, 0x27, 0x60, + 0x8A, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, + 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x1B, 0xF2, + 0xFF, 0xFF, 0x60, 0x45, 0xB8, 0xF1, 0x27, 0x60, 0x90, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, + 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, + 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, + 0x88, 0xFF, 0x0F, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x26, 0x28, 0x00, 0x32, 0x44, 0x02, 0x26, + 0x25, 0x00, 0x10, 0x2B, 0x29, 0x00, 0x28, 0x60, 0xE2, 0x63, 0xBF, 0xD3, 0x2C, 0xF0, 0x00, 0xA8, + 0x60, 0x41, 0x0D, 0x03, 0x50, 0xFE, 0xBD, 0xD3, 0x2D, 0xF0, 0xD0, 0x80, 0xBD, 0xD3, 0x2E, 0xF0, + 0xD0, 0x80, 0xBD, 0xD3, 0x2C, 0xF0, 0xD0, 0x80, 0xFA, 0xA1, 0x10, 0x0C, 0xF3, 0x02, 0x50, 0xFE, + 0x60, 0x60, 0x01, 0x64, 0xD0, 0x80, 0x2D, 0xF0, 0x1D, 0x64, 0xD0, 0x80, 0x2E, 0xF0, 0x01, 0x64, + 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x0C, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x40, 0x2A, + 0x03, 0x00, 0x19, 0x60, 0x22, 0x78, 0xFF, 0xFF, 0xC5, 0x60, 0x55, 0x78, 0xFF, 0xFF, 0x32, 0x40, + 0x40, 0x26, 0xF7, 0x01, 0x2A, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x08, 0x2A, 0x2A, 0x00, 0xDC, 0xF3, + 0xFF, 0xFF, 0x07, 0xB4, 0x03, 0xA8, 0xFF, 0xFF, 0x03, 0x03, 0x32, 0x40, 0x02, 0x2A, 0x1D, 0x00, + 0x03, 0x67, 0xA0, 0x84, 0x00, 0x37, 0x64, 0x63, 0x60, 0x40, 0x02, 0x37, 0x5E, 0x63, 0x60, 0x40, + 0x01, 0x37, 0x58, 0x63, 0x60, 0x40, 0x03, 0x37, 0x0D, 0x00, 0xBD, 0xD2, 0x81, 0xF1, 0xBD, 0xD2, + 0xD0, 0x80, 0x82, 0xF1, 0x07, 0x02, 0xD0, 0x80, 0xBD, 0xD2, 0x83, 0xF1, 0x03, 0x02, 0xD0, 0x80, + 0xFF, 0xFF, 0x03, 0x03, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, 0xDE, 0x60, 0x58, 0x4F, 0xFE, 0x78, + 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x26, 0x06, 0x00, 0x20, 0x40, 0x10, 0x2B, + 0x03, 0x00, 0xC5, 0x60, 0x55, 0x78, 0xFF, 0xFF, 0x87, 0xF4, 0xA9, 0xF1, 0x27, 0x1B, 0x31, 0xF2, + 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, + 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, + 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, + 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, + 0xE8, 0x1B, 0xA9, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x03, 0x00, 0xD3, 0x80, 0xFF, 0xFF, + 0xD6, 0x03, 0x43, 0x43, 0xDC, 0xF3, 0x32, 0x40, 0x02, 0x26, 0x04, 0x00, 0x07, 0xB4, 0x03, 0xA8, + 0x2A, 0xF2, 0x5F, 0x02, 0xA9, 0xF1, 0x23, 0x43, 0xD3, 0x80, 0xFF, 0xFF, 0x5A, 0x02, 0xC5, 0x60, + 0x58, 0x4F, 0xA5, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x02, 0x2A, 0x05, 0x00, 0x63, 0x46, 0x02, 0x64, + 0x06, 0xFA, 0x26, 0x46, 0x4E, 0x00, 0x32, 0x40, 0x08, 0x2A, 0x05, 0x00, 0x63, 0x46, 0x80, 0x60, + 0x02, 0x64, 0x06, 0xFA, 0x26, 0x46, 0xD8, 0xF3, 0x63, 0x45, 0x66, 0x41, 0x65, 0x46, 0x8C, 0xFA, + 0x60, 0x40, 0x01, 0x36, 0x06, 0x00, 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, 0x05, 0x3A, + 0x02, 0x00, 0x00, 0x64, 0x01, 0x00, 0x01, 0x64, 0x6F, 0xFA, 0x79, 0xF3, 0x7A, 0xF1, 0xFF, 0xFF, + 0xA0, 0x84, 0x65, 0x43, 0x02, 0x02, 0x79, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, 0xAE, 0x65, + 0xD8, 0xF3, 0xFF, 0xFF, 0xE0, 0x84, 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x04, 0x02, + 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x7B, 0xFB, 0x6F, 0xF0, 0x60, 0x47, + 0x90, 0x84, 0x6F, 0xFA, 0x60, 0x47, 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, + 0xFC, 0x03, 0xA4, 0x84, 0x70, 0xF0, 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, 0x02, 0x05, + 0xDD, 0x81, 0xFB, 0x01, 0xE1, 0x81, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x66, 0x43, + 0x0C, 0xF4, 0x07, 0xFC, 0x43, 0x43, 0x02, 0xFE, 0x1D, 0xF0, 0x1C, 0x60, 0x9A, 0x62, 0xC0, 0x64, + 0xC0, 0x84, 0xA2, 0xD1, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, + 0xA2, 0xDB, 0x2A, 0xF2, 0x63, 0x45, 0x0C, 0xB4, 0x08, 0x3A, 0x0A, 0x00, 0xDC, 0xF3, 0x23, 0x46, + 0x07, 0xB4, 0xFD, 0xA0, 0x06, 0xF2, 0x26, 0x46, 0x03, 0x03, 0x60, 0x40, 0x02, 0x2A, 0x0D, 0x00, + 0x2A, 0xF2, 0x35, 0xF0, 0x60, 0x40, 0xA4, 0x36, 0x0B, 0x00, 0x08, 0x2B, 0x0C, 0x00, 0x23, 0x46, + 0x22, 0xF2, 0x26, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x06, 0x02, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, + 0xC5, 0x60, 0x55, 0x78, 0xFF, 0xFF, 0x23, 0x46, 0x1E, 0xF2, 0x26, 0x46, 0x44, 0x4C, 0x0F, 0x26, + 0x1D, 0x00, 0x00, 0xBC, 0x40, 0x45, 0x0B, 0x03, 0x00, 0x64, 0x23, 0x46, 0x1E, 0xFA, 0x26, 0x46, + 0xA2, 0xFF, 0xAF, 0x60, 0x58, 0x4E, 0x95, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x26, 0x46, 0x2A, 0xF0, + 0x2C, 0x44, 0x64, 0x40, 0x04, 0x27, 0x0A, 0x00, 0x23, 0x46, 0x22, 0xFA, 0x26, 0x46, 0x1B, 0xF2, + 0xFF, 0xFF, 0xE4, 0xA4, 0x3E, 0xFA, 0xC4, 0x60, 0xAD, 0x78, 0xFF, 0xFF, 0x3F, 0xF2, 0x02, 0xFA, + 0xA2, 0xFF, 0x16, 0xF0, 0xFF, 0xFF, 0x64, 0x44, 0x01, 0x26, 0xDC, 0x9C, 0xB3, 0xF3, 0x2A, 0xF2, + 0xDC, 0x83, 0xB3, 0xFD, 0x06, 0xF4, 0x01, 0xF8, 0x26, 0x46, 0x60, 0x40, 0x40, 0x2B, 0x18, 0x00, + 0x64, 0x44, 0x00, 0x65, 0xFF, 0xB4, 0xFC, 0xA4, 0x06, 0xF0, 0x03, 0x03, 0x64, 0x46, 0x0C, 0x0D, + 0x02, 0x65, 0x26, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x60, 0x46, + 0xF9, 0x01, 0x01, 0xF2, 0xFF, 0xFF, 0xD4, 0x84, 0x01, 0xFA, 0x66, 0x44, 0x26, 0x46, 0x06, 0xFA, + 0x06, 0xF4, 0x00, 0xF2, 0x80, 0xFC, 0x40, 0x45, 0xAF, 0x60, 0x58, 0x4E, 0x95, 0x78, 0xFF, 0xFF, + 0xA3, 0xFF, 0x26, 0x46, 0x2C, 0x44, 0x0F, 0x26, 0x14, 0x00, 0x23, 0x46, 0x22, 0xFA, 0x26, 0x44, + 0x1E, 0xFA, 0x26, 0x46, 0x1B, 0xF2, 0xFF, 0xFF, 0xE4, 0xA4, 0x3E, 0xFA, 0x24, 0x60, 0x74, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0x6F, 0x00, 0xA3, 0x46, 0x22, 0xF2, 0x60, 0x45, 0xDC, 0x84, 0xD4, 0x80, 0x22, 0xFA, 0xA3, 0x46, + 0x6C, 0x02, 0x2A, 0xF0, 0xA3, 0x46, 0x1E, 0xF2, 0xA3, 0x46, 0x00, 0xBC, 0x00, 0xF2, 0x01, 0x02, + 0x64, 0x00, 0x44, 0x4C, 0x3F, 0xF0, 0x60, 0x43, 0x23, 0x46, 0x1E, 0xF4, 0x09, 0x60, 0x00, 0x65, + 0x3F, 0xF2, 0x26, 0x46, 0xC0, 0x84, 0xD4, 0x80, 0x60, 0x45, 0x57, 0x07, 0x80, 0xFC, 0x1B, 0xF2, + 0x06, 0xF2, 0x60, 0x41, 0x23, 0x46, 0x1E, 0xF4, 0x1B, 0xF0, 0x06, 0xF0, 0xC1, 0x81, 0x06, 0xFA, + 0x05, 0xFA, 0x9B, 0xFA, 0x65, 0x44, 0x3F, 0xFA, 0x64, 0x46, 0x00, 0xFC, 0x63, 0x46, 0x01, 0xF2, + 0x10, 0x61, 0xF2, 0xA4, 0x01, 0xFA, 0xC8, 0x83, 0x02, 0x64, 0x59, 0xD0, 0x58, 0xD8, 0xFD, 0x1F, + 0x06, 0x45, 0x24, 0x60, 0x74, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA2, 0xFF, 0x00, 0xF4, 0x01, 0xF0, 0x0A, 0x18, 0x70, 0x67, + 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, 0xC0, 0x84, 0x01, 0xFA, 0x25, 0x46, 0x25, 0x44, 0x80, 0xFC, + 0x05, 0xFA, 0xAF, 0x60, 0x58, 0x4E, 0x95, 0x78, 0xFF, 0xFF, 0xD4, 0xFE, 0xA3, 0xFF, 0x2C, 0x44, + 0x04, 0x27, 0x16, 0x00, 0x23, 0x46, 0x1E, 0xF2, 0x9E, 0xFC, 0x60, 0x46, 0x46, 0x46, 0x3F, 0xF2, + 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, 0x26, 0x46, 0x2C, 0x43, 0x2A, 0xFC, 0x06, 0xF4, 0x00, 0x64, + 0x00, 0xFA, 0x01, 0xF0, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0x01, 0xFA, 0x26, 0x46, 0x1D, 0x00, + 0x00, 0x66, 0x46, 0x46, 0xBF, 0x60, 0xEB, 0x78, 0xFF, 0xFF, 0xA3, 0x46, 0x1E, 0xF0, 0x9E, 0xFC, + 0x00, 0x63, 0x33, 0x85, 0xA3, 0x46, 0x0D, 0x03, 0xA3, 0x46, 0x22, 0xF2, 0x0F, 0x65, 0xA4, 0x85, + 0xD4, 0x84, 0x22, 0xFA, 0xA3, 0x46, 0xA2, 0xFF, 0xAF, 0x60, 0x58, 0x4E, 0x95, 0x78, 0xFF, 0xFF, + 0xA3, 0xFF, 0x26, 0x46, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x32, 0xF0, 0x60, 0x40, + 0x08, 0x2A, 0x5C, 0x00, 0x01, 0x2B, 0x2F, 0x00, 0x64, 0x40, 0x01, 0x2A, 0x2C, 0x00, 0xB8, 0xF1, + 0x27, 0x60, 0x8A, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, + 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, + 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, 0xB8, 0xF1, 0x27, 0x60, 0x90, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, + 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, + 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, + 0x00, 0x75, 0x88, 0xFF, 0x2B, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x88, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, + 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, + 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, 0xB8, 0xF1, + 0x27, 0x60, 0x8E, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, + 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, + 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x07, 0xF4, 0xFF, 0xFF, + 0x22, 0xF2, 0x26, 0x46, 0x0F, 0xB4, 0xDC, 0x85, 0xB8, 0xF1, 0x27, 0x60, 0x8C, 0x64, 0xA0, 0xD3, + 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, + 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, + 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x27, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x3B, 0x12, 0x00, + 0xB8, 0xF1, 0x27, 0x60, 0x9A, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, + 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, + 0x88, 0xFF, 0x13, 0x00, 0x02, 0x3B, 0x11, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x9C, 0x64, 0xA0, 0xD3, + 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, + 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xC6, 0x60, 0x85, 0x78, 0xFF, 0xFF, + 0xBF, 0x60, 0xEB, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, + 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xBF, 0x60, 0xEB, 0x78, 0xFF, 0xFF, 0x24, 0x60, + 0x74, 0x62, 0x24, 0x60, 0x58, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0x00, 0x66, 0x46, 0x46, 0xBF, 0x60, 0xEB, 0x78, 0xFF, 0xFF, + 0x2A, 0xF2, 0x58, 0x63, 0x60, 0x47, 0x01, 0x27, 0x64, 0x63, 0x31, 0x60, 0x28, 0x62, 0x61, 0x5C, + 0xA2, 0xD9, 0xBD, 0xD0, 0xBD, 0xD0, 0x64, 0x45, 0x64, 0x41, 0xBD, 0xD0, 0x00, 0xF4, 0x04, 0xF8, + 0x83, 0xFA, 0x82, 0xF8, 0xA6, 0x46, 0x02, 0xB0, 0x5E, 0x63, 0x04, 0x03, 0x64, 0x63, 0x03, 0xB0, + 0x02, 0x3A, 0x6C, 0x63, 0x3F, 0xF2, 0xBD, 0xD0, 0xBD, 0xD0, 0x64, 0x45, 0x64, 0x41, 0xBD, 0xD0, + 0xA6, 0x46, 0x07, 0xF8, 0x86, 0xFA, 0x85, 0xF8, 0x60, 0x47, 0x08, 0xFA, 0x31, 0x60, 0x28, 0x62, + 0xA2, 0xD1, 0x26, 0x46, 0x64, 0x41, 0x2F, 0x58, 0xFF, 0xFF, 0xA9, 0xF5, 0x00, 0xF2, 0x26, 0x46, + 0x31, 0xF0, 0x39, 0x18, 0x66, 0x41, 0x1C, 0x60, 0xBA, 0x65, 0x64, 0x47, 0x00, 0x7F, 0xA9, 0xF1, + 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, + 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, + 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, + 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, + 0x61, 0x46, 0x1E, 0x60, 0xBC, 0x61, 0xA1, 0xD3, 0x1E, 0x60, 0xFE, 0x7C, 0xD0, 0x80, 0xFF, 0xFF, + 0x07, 0x03, 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, 0x49, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xA1, 0xDB, + 0xC6, 0x60, 0x40, 0x78, 0xFF, 0xFF, 0x20, 0x7C, 0x72, 0x44, 0xFF, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, + 0x02, 0x04, 0xD0, 0x84, 0xFB, 0x01, 0xE0, 0x83, 0xA9, 0xF3, 0x02, 0xA3, 0x43, 0x93, 0xA9, 0xF3, + 0xFF, 0xFF, 0x02, 0xA5, 0xD7, 0x80, 0x04, 0xA5, 0x08, 0x24, 0x65, 0x43, 0x66, 0x41, 0x63, 0x46, + 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x1C, 0x60, + 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, + 0xA9, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, + 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, + 0x31, 0xF0, 0x66, 0x41, 0x1C, 0x60, 0xBA, 0x65, 0x64, 0x47, 0x00, 0x7F, 0xA9, 0xF1, 0xE0, 0x84, + 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, + 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, + 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, + 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, + 0x2F, 0xF2, 0x30, 0xF0, 0x31, 0xF0, 0x64, 0x45, 0x46, 0x43, 0x63, 0x46, 0x03, 0xFA, 0x06, 0xF2, + 0x84, 0xF8, 0x00, 0x7E, 0x06, 0xFA, 0x05, 0xF8, 0xA3, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0xDC, 0xF3, + 0x2A, 0xF2, 0x07, 0xB0, 0x03, 0x3A, 0x2A, 0x00, 0x00, 0xF4, 0x09, 0xF2, 0x60, 0x45, 0x80, 0x3A, + 0x05, 0x00, 0x0E, 0xF2, 0xFF, 0xFF, 0x02, 0xB0, 0x0F, 0xF2, 0x20, 0x03, 0x60, 0x47, 0x00, 0x3A, + 0x1D, 0x00, 0x60, 0x41, 0x00, 0x36, 0x13, 0x00, 0xDA, 0x85, 0x2D, 0x60, 0x7A, 0x63, 0xBD, 0xD1, + 0xFF, 0xFF, 0xD1, 0x80, 0xFF, 0xFF, 0x12, 0x02, 0x60, 0xFE, 0xBD, 0xD3, 0xA5, 0xD0, 0xDE, 0x85, + 0xD0, 0x80, 0xCD, 0x81, 0x0B, 0x02, 0xF9, 0x02, 0x20, 0xFE, 0x00, 0x64, 0x0A, 0x00, 0x26, 0x46, + 0x48, 0xFE, 0x65, 0x40, 0x40, 0x3A, 0x02, 0x00, 0x01, 0x64, 0x03, 0x00, 0x08, 0xFE, 0x20, 0xFE, + 0x00, 0x64, 0x40, 0x48, 0x26, 0x46, 0x2D, 0x58, 0xFF, 0xFF, 0x2D, 0x60, 0x52, 0x62, 0xA2, 0xD3, + 0x18, 0xF2, 0x60, 0x40, 0x01, 0x26, 0x2A, 0xFA, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x26, + 0x03, 0x00, 0xC7, 0x60, 0x6D, 0x78, 0xFF, 0xFF, 0x3F, 0xF0, 0x32, 0x40, 0x10, 0x2A, 0x20, 0x00, + 0x2C, 0xF0, 0x64, 0x41, 0x60, 0x40, 0x40, 0x27, 0x1B, 0x00, 0xCD, 0x81, 0xDD, 0x81, 0x18, 0x03, + 0x17, 0x03, 0x64, 0x40, 0x01, 0x26, 0x14, 0x00, 0x01, 0x61, 0x13, 0x00, 0xB8, 0xF1, 0x27, 0x60, + 0xA0, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, + 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x23, 0x00, + 0x00, 0x61, 0x60, 0x40, 0x18, 0x36, 0x1F, 0x00, 0xC5, 0x60, 0x58, 0x4F, 0x78, 0x78, 0xFF, 0xFF, + 0x0F, 0xF0, 0xEB, 0xF1, 0x64, 0x44, 0x60, 0x22, 0x19, 0x00, 0xDC, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, + 0xFD, 0xA0, 0x2A, 0xF2, 0x03, 0x02, 0x08, 0xB0, 0xFF, 0xFF, 0x10, 0x02, 0x32, 0xF2, 0x33, 0xF2, + 0xD0, 0x80, 0xEC, 0xF1, 0x0B, 0x02, 0xD0, 0x80, 0x34, 0xF2, 0x08, 0x02, 0xED, 0xF1, 0xFF, 0xFF, + 0xD0, 0x80, 0x0F, 0xF0, 0x03, 0x02, 0xC7, 0x60, 0xB9, 0x78, 0xFF, 0xFF, 0x00, 0xF4, 0xAA, 0x60, + 0xAA, 0x65, 0x09, 0xF2, 0x5A, 0xD0, 0xD4, 0x80, 0x03, 0x64, 0x4F, 0x02, 0xD0, 0x80, 0x00, 0x64, + 0x5A, 0xD0, 0x4B, 0x02, 0x64, 0x45, 0xD4, 0x80, 0xF8, 0x7F, 0x08, 0x02, 0x5A, 0xD0, 0x26, 0x46, + 0x64, 0x45, 0x23, 0xF0, 0x20, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x0B, 0x00, 0xD4, 0x80, 0x1D, 0x60, + 0x60, 0x64, 0x16, 0x02, 0x5A, 0xD0, 0x26, 0x46, 0x64, 0x45, 0x23, 0xF0, 0x40, 0x67, 0xB0, 0x84, + 0xA2, 0xDA, 0x65, 0x44, 0x88, 0x3A, 0x07, 0x00, 0x77, 0x37, 0x08, 0x00, 0x78, 0x37, 0x06, 0x00, + 0x8E, 0x37, 0x04, 0x00, 0x2A, 0x00, 0x81, 0x3A, 0x28, 0x00, 0x80, 0x37, 0x00, 0x61, 0x25, 0x00, + 0xD4, 0x80, 0x01, 0x60, 0x00, 0x64, 0x5A, 0xD0, 0x20, 0x02, 0xD0, 0x80, 0x5A, 0xD0, 0x1D, 0x02, + 0x26, 0x46, 0x64, 0x47, 0x7F, 0xB4, 0xFD, 0xA0, 0x09, 0x03, 0x17, 0x07, 0x32, 0x40, 0x02, 0x26, + 0x47, 0x00, 0x23, 0xF0, 0x60, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x42, 0x00, 0x0F, 0xF2, 0x32, 0x40, + 0x02, 0x26, 0x3E, 0x00, 0xF2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xF2, 0xFB, 0xEB, 0x60, 0x58, 0x4F, + 0xA5, 0x78, 0xFF, 0xFF, 0xC7, 0x60, 0xC3, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x61, 0x40, 0x01, 0x2A, + 0x12, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0xA0, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, + 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, + 0x00, 0x75, 0x88, 0xFF, 0x6E, 0x00, 0x0F, 0xF2, 0x81, 0xF1, 0x2A, 0xF2, 0x60, 0x40, 0x20, 0x2A, + 0x12, 0x00, 0x5E, 0x63, 0x60, 0x40, 0x02, 0x2B, 0x64, 0x63, 0xBD, 0xD2, 0xBD, 0xD2, 0xD0, 0x80, + 0x82, 0xF1, 0x08, 0x02, 0xD0, 0x80, 0xA3, 0xD2, 0x83, 0xF1, 0x04, 0x02, 0xD0, 0x80, 0xFF, 0xFF, + 0x01, 0x02, 0x06, 0x00, 0x56, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, 0x36, 0x51, 0x00, + 0xF2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xF2, 0xFB, 0x59, 0x00, 0x26, 0x46, 0x2A, 0xF2, 0xFF, 0xFF, + 0xFF, 0xFF, 0x0C, 0x26, 0x46, 0x00, 0xB0, 0x36, 0x15, 0x00, 0x10, 0x36, 0x13, 0x00, 0x30, 0x36, + 0x11, 0x00, 0xC0, 0x36, 0x02, 0x00, 0xA0, 0x3A, 0x12, 0x00, 0x81, 0xF1, 0x32, 0xF2, 0x33, 0xF2, + 0xD0, 0x80, 0x82, 0xF1, 0x36, 0x02, 0xD0, 0x80, 0x34, 0xF2, 0x83, 0xF1, 0x32, 0x02, 0xD0, 0x80, + 0xFF, 0xFF, 0x2F, 0x02, 0xDB, 0x60, 0x58, 0x4F, 0xD2, 0x78, 0xFF, 0xFF, 0x26, 0x00, 0x50, 0x3A, + 0x05, 0x00, 0xEF, 0x60, 0x58, 0x4F, 0xE3, 0x78, 0xFF, 0xFF, 0x1F, 0x00, 0x40, 0x3A, 0x05, 0x00, + 0xE8, 0x60, 0x58, 0x4F, 0x60, 0x78, 0xFF, 0xFF, 0x18, 0x00, 0x80, 0x3A, 0x15, 0x00, 0x81, 0xF1, + 0x32, 0xF2, 0x33, 0xF2, 0xD0, 0x80, 0x82, 0xF1, 0x14, 0x02, 0xD0, 0x80, 0x34, 0xF2, 0x83, 0xF1, + 0x10, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x0D, 0x02, 0xDF, 0x60, 0x58, 0x4F, 0x28, 0x78, 0xFF, 0xFF, + 0x20, 0x60, 0x58, 0x4F, 0xBF, 0x78, 0xFF, 0xFF, 0x04, 0x00, 0x66, 0x44, 0x00, 0xA8, 0xFF, 0xFF, + 0x0A, 0x03, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, + 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xC5, 0x60, 0x58, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x3B, 0xF0, + 0x60, 0x40, 0x40, 0x2B, 0x1E, 0x00, 0xC0, 0x60, 0x00, 0x64, 0x64, 0x40, 0x20, 0x2B, 0x19, 0x00, + 0x22, 0xF2, 0xFF, 0xFF, 0x04, 0xB4, 0xFF, 0xFF, 0x14, 0x03, 0xC0, 0x60, 0x00, 0x64, 0x26, 0x46, + 0xA0, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x23, 0xF2, 0x10, 0xBD, 0xB4, 0x9C, 0x3F, 0xF2, + 0x23, 0xF8, 0x3F, 0xF2, 0xFF, 0xFF, 0xF8, 0xA4, 0x3F, 0xFA, 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, + 0x26, 0x46, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x58, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0xCB, 0x01, 0x00, 0x60, 0x30, 0x61, + 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x60, 0xFB, 0x00, 0x60, 0x30, 0x61, + 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x5F, 0xFB, 0x00, 0x60, 0x02, 0x61, + 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x66, 0xFB, 0x10, 0x60, 0x26, 0x62, + 0xC9, 0x60, 0xC7, 0x64, 0xA2, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x01, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF2, 0xFB, 0x0F, 0x60, 0xF0, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x14, 0x63, 0x01, 0x60, 0xC4, 0x61, 0x28, 0x60, 0x3E, 0x64, + 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0x00, 0x60, 0x88, 0x63, 0x27, 0x60, 0xB4, 0x61, 0x28, 0x60, + 0x54, 0x64, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD1, 0xFF, 0xFF, + 0x64, 0x45, 0xA9, 0xF1, 0x66, 0x41, 0x64, 0x46, 0x36, 0xF2, 0xFF, 0xFF, 0x65, 0x40, 0x01, 0x36, + 0x22, 0x64, 0x36, 0xFA, 0x61, 0x46, 0x32, 0x45, 0x28, 0x60, 0x3C, 0x62, 0xA2, 0xD1, 0x10, 0x67, + 0xB4, 0x85, 0x64, 0x40, 0x01, 0x2A, 0x94, 0x85, 0x45, 0x52, 0xFF, 0x60, 0xE7, 0x65, 0x32, 0x41, + 0xA5, 0x81, 0x2D, 0x60, 0x1A, 0x62, 0xA2, 0xD1, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD3, 0x64, 0x40, + 0x01, 0x2A, 0x0D, 0x00, 0x08, 0x65, 0xFF, 0xA0, 0xFF, 0xFF, 0x01, 0x03, 0x08, 0x00, 0x28, 0x60, + 0x30, 0x62, 0xA2, 0xD3, 0xB5, 0x81, 0x10, 0x65, 0x60, 0x40, 0x01, 0x26, 0xB5, 0x81, 0x41, 0x52, + 0x2D, 0x60, 0x1A, 0x62, 0xA2, 0xD3, 0x31, 0x60, 0x18, 0x63, 0xF0, 0x84, 0xF0, 0x84, 0xF0, 0x84, + 0x01, 0xB5, 0xF0, 0x84, 0xF0, 0x84, 0x03, 0xB4, 0x65, 0x5C, 0xA3, 0xD9, 0x31, 0x60, 0x1A, 0x63, + 0x02, 0xA8, 0xA3, 0xDB, 0x1B, 0x02, 0x07, 0x60, 0xD0, 0x64, 0x31, 0x60, 0x1C, 0x63, 0xA3, 0xDB, + 0x31, 0x60, 0x24, 0x63, 0xA3, 0xDB, 0x00, 0x60, 0xC8, 0x64, 0x31, 0x60, 0x1E, 0x63, 0xA3, 0xDB, + 0x31, 0x60, 0x26, 0x63, 0xA3, 0xDB, 0x00, 0x60, 0x64, 0x64, 0x31, 0x60, 0x20, 0x63, 0xA3, 0xDB, + 0x01, 0x60, 0x90, 0x64, 0x31, 0x60, 0x22, 0x63, 0xA3, 0xDB, 0x08, 0x00, 0x0A, 0x64, 0x31, 0x60, + 0x20, 0x63, 0xA3, 0xDB, 0x01, 0x64, 0x31, 0x60, 0x22, 0x63, 0xA3, 0xDB, 0x2D, 0x60, 0x1A, 0x62, + 0xA2, 0xD1, 0x01, 0x64, 0x64, 0x40, 0x40, 0x2A, 0x03, 0x00, 0x31, 0x60, 0x0E, 0x7C, 0xA4, 0xDB, + 0x12, 0x60, 0x28, 0x63, 0xBA, 0xF3, 0x0E, 0x61, 0x60, 0x45, 0x65, 0x44, 0xE8, 0x85, 0x05, 0x64, + 0xCD, 0x81, 0x02, 0x28, 0x00, 0x64, 0xBD, 0xDB, 0xF8, 0x02, 0x2D, 0x60, 0x78, 0x61, 0x27, 0x60, + 0xB6, 0x64, 0x20, 0x63, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0xBD, 0xF1, 0x80, 0xF9, 0x1A, 0x63, + 0x01, 0x60, 0x00, 0x61, 0x00, 0x64, 0x59, 0xDB, 0xFE, 0x1F, 0x40, 0x40, 0x01, 0x64, 0x87, 0xFB, + 0x28, 0x60, 0xCC, 0x61, 0xA1, 0xD3, 0x2E, 0x60, 0x96, 0x61, 0xFE, 0xA4, 0xE0, 0x84, 0x04, 0x24, + 0x0F, 0x00, 0xE0, 0x84, 0x41, 0x91, 0x2D, 0x60, 0xCC, 0x62, 0xA2, 0xD3, 0xA1, 0xD1, 0x2D, 0x60, + 0xC4, 0x62, 0xA0, 0x83, 0xA2, 0xDD, 0x59, 0xD1, 0x2D, 0x60, 0xC2, 0x62, 0xA0, 0x83, 0xA2, 0xDD, + 0xE5, 0xF3, 0x7F, 0xFB, 0x1B, 0x60, 0xC6, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x00, 0xB8, 0x10, 0x60, + 0x5C, 0x65, 0x0D, 0x03, 0x1B, 0x60, 0xCE, 0x63, 0xE5, 0xF3, 0xA3, 0xD1, 0xE0, 0x84, 0xC4, 0x84, + 0xA0, 0xD3, 0xFF, 0xFF, 0x01, 0xB0, 0xFF, 0xFF, 0x02, 0x02, 0xE5, 0xF9, 0x7F, 0xF9, 0xE5, 0xF3, + 0x01, 0x61, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, 0xE1, 0x81, 0xFB, 0x01, 0xBA, 0xF3, 0x61, 0x45, + 0xA4, 0x80, 0xFF, 0xFF, 0x0B, 0x02, 0x00, 0xB8, 0x01, 0x63, 0x08, 0x03, 0xE8, 0x84, 0xFF, 0xFF, + 0x02, 0x24, 0x02, 0x00, 0xDF, 0x83, 0xFA, 0x01, 0xE5, 0xFD, 0x7F, 0xFD, 0x0F, 0x60, 0xF0, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xF2, 0x62, 0x40, 0x60, 0x00, 0x64, + 0xA2, 0xDB, 0xC8, 0x60, 0xF7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7F, 0xF1, + 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, 0x0C, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x07, 0x64, + 0xD0, 0xFB, 0x0F, 0x60, 0xF2, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xC9, 0x60, 0x34, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xF0, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x01, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xE3, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x05, 0x3A, + 0x03, 0x00, 0x68, 0x60, 0xBA, 0x61, 0x11, 0x00, 0x04, 0x3A, 0x03, 0x00, 0x68, 0x60, 0xAE, 0x61, + 0x0C, 0x00, 0x03, 0x3A, 0x03, 0x00, 0x68, 0x60, 0xA2, 0x61, 0x07, 0x00, 0x02, 0x3A, 0x03, 0x00, + 0x68, 0x60, 0x96, 0x61, 0x02, 0x00, 0x68, 0x60, 0x8A, 0x61, 0x3C, 0x60, 0x00, 0x66, 0x01, 0x60, + 0xB8, 0x64, 0x0A, 0x63, 0x59, 0xD0, 0x58, 0xD9, 0xFD, 0x1F, 0x01, 0x60, 0xBE, 0x61, 0xE4, 0xF3, + 0x00, 0x66, 0x00, 0xA8, 0x04, 0x65, 0x01, 0x03, 0xA1, 0xDB, 0x1F, 0x60, 0x08, 0x63, 0x55, 0xD3, + 0xFF, 0xFF, 0x20, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, 0x21, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, + 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x0F, 0x60, 0xF0, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, + 0x0B, 0x04, 0x0F, 0x60, 0xF2, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xC9, 0x60, 0x7B, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0x9A, 0x62, 0x1F, 0x60, 0x06, 0x64, + 0xA2, 0xDB, 0x20, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xF2, 0x62, 0x20, 0x60, + 0x00, 0x64, 0xA2, 0xDB, 0xC9, 0x60, 0xA0, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0xC5, 0xFE, 0x20, 0x40, 0x20, 0x2A, 0x08, 0x00, 0x10, 0x60, 0x02, 0x62, 0xA2, 0xD1, + 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, + 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xF0, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x5A, 0xDB, 0x0E, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x64, + 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xF0, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x8B, 0xFB, + 0xFF, 0xFF, 0xC1, 0xFE, 0x10, 0x60, 0x1A, 0x62, 0xA2, 0xD1, 0x01, 0x60, 0xDF, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x24, 0x60, 0xA8, 0x63, 0x01, 0x64, 0xBD, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0x0F, 0x60, 0xF0, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x0F, 0x60, 0xF2, 0x62, 0x00, 0x60, 0x08, 0x64, 0xA2, 0xDB, 0xC9, 0x60, 0xF3, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xF0, 0x62, + 0xA2, 0xD1, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x8B, 0xF3, 0x00, 0x65, 0xD4, 0x80, + 0xFF, 0xFF, 0x0B, 0x03, 0x0F, 0x60, 0xF2, 0x62, 0x80, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xC9, 0x60, + 0xF3, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xDE, 0xFE, 0x0E, 0x04, 0x09, 0x64, + 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xF2, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCA, 0x60, + 0x1D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0A, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x24, 0x60, 0x9A, 0x62, 0x06, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xF0, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0xBE, 0xFE, 0xDA, 0xFE, 0x24, 0x60, 0x34, 0x61, 0xCA, 0x60, + 0x58, 0x4E, 0x57, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x22, 0x61, 0xCA, 0x60, 0x58, 0x4E, 0x57, 0x78, + 0xFF, 0xFF, 0x24, 0x60, 0x28, 0x61, 0xCA, 0x60, 0x58, 0x4E, 0x57, 0x78, 0xFF, 0xFF, 0x24, 0x60, + 0x46, 0x61, 0xCA, 0x60, 0x58, 0x4E, 0x57, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x4C, 0x61, 0xCA, 0x60, + 0x58, 0x4E, 0x57, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x58, 0x61, 0xCA, 0x60, 0x58, 0x4E, 0x57, 0x78, + 0xFF, 0xFF, 0xC5, 0xFE, 0x0E, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0xA1, 0xD3, + 0x0E, 0x57, 0x24, 0x00, 0x0E, 0xF2, 0x44, 0x4C, 0x80, 0xB0, 0x10, 0xB0, 0x0B, 0x03, 0x24, 0x60, + 0x74, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0x13, 0x00, 0x12, 0x02, 0xF0, 0x37, 0x09, 0x00, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, + 0xD0, 0x80, 0xA2, 0xFF, 0xB0, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0xB0, 0xFB, 0x24, 0x60, 0x74, 0x64, + 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x2C, 0x44, 0xAC, 0x86, 0x09, 0xF0, + 0xD9, 0x02, 0x37, 0x58, 0xFF, 0xFF, 0x1A, 0x60, 0x66, 0x63, 0x00, 0x64, 0xA3, 0xDB, 0x06, 0xA3, + 0x10, 0x60, 0x4C, 0x64, 0xBD, 0xDB, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, 0x00, 0x63, 0x10, 0x60, + 0x9E, 0x62, 0xA2, 0xDD, 0x10, 0x60, 0x4A, 0x62, 0xCF, 0x60, 0x16, 0x64, 0xA2, 0xDB, 0x10, 0x60, + 0x24, 0x62, 0xCE, 0x60, 0xE2, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x02, 0x64, + 0xA2, 0xDB, 0xCA, 0x60, 0xFB, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x68, 0x60, + 0x7E, 0x61, 0x3C, 0x60, 0x00, 0x66, 0x01, 0x60, 0xB8, 0x64, 0x0A, 0x63, 0x59, 0xD0, 0x58, 0xD9, + 0xFD, 0x1F, 0x01, 0x60, 0xBE, 0x61, 0xE4, 0xF3, 0x00, 0x66, 0x00, 0xA8, 0x04, 0x65, 0x01, 0x03, + 0xA1, 0xDB, 0x1F, 0x60, 0x08, 0x63, 0x55, 0xD3, 0xFF, 0xFF, 0x20, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, + 0xFF, 0xFF, 0x21, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x0F, 0x60, + 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xEC, 0x62, 0x40, 0x60, + 0x00, 0x64, 0xA2, 0xDB, 0xCA, 0x60, 0xC7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x24, 0x60, 0x9A, 0x62, 0x1F, 0x60, 0x06, 0x64, 0xA2, 0xDB, 0x20, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCA, 0x60, 0xEC, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x10, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0xBA, 0xFE, 0x27, 0x60, 0xB6, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x03, 0xA8, + 0x02, 0xA8, 0x04, 0x03, 0x0F, 0x02, 0xCE, 0x60, 0xB3, 0x78, 0xFF, 0xFF, 0xCD, 0x60, 0xEF, 0x78, + 0xFF, 0xFF, 0x1F, 0x60, 0x80, 0x65, 0xA5, 0xD3, 0xFF, 0xFF, 0xF3, 0xB4, 0xA5, 0xDB, 0xCB, 0x60, + 0x22, 0x78, 0xFF, 0xFF, 0x01, 0x63, 0x1A, 0x60, 0x40, 0x64, 0xA0, 0xDD, 0x1F, 0x60, 0x80, 0x64, + 0x00, 0x63, 0xA0, 0xDD, 0x11, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0xBA, 0xFE, 0x02, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, 0xF2, 0xFB, + 0x44, 0x60, 0x44, 0x64, 0x81, 0xFB, 0x82, 0xFB, 0x83, 0xFB, 0xFF, 0xFF, 0x20, 0x40, 0x04, 0x2B, + 0x19, 0x00, 0x9B, 0xFE, 0x09, 0x04, 0xBB, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x80, 0x60, + 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x12, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, + 0xEC, 0x62, 0x80, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCB, 0x60, 0x36, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x0D, 0x64, 0x53, 0xFB, + 0x29, 0x60, 0xA4, 0x64, 0x54, 0xFB, 0x13, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xCE, 0x61, + 0xA1, 0xD1, 0x02, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x64, 0x40, 0x01, 0x2A, 0x07, 0x00, + 0x00, 0x64, 0xA1, 0xDB, 0x02, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0xCA, 0x60, + 0x58, 0x4E, 0xA7, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0x80, 0x62, 0x1A, 0x60, 0x40, 0x65, 0xA2, 0xD3, + 0xA5, 0xD1, 0x60, 0x40, 0x0C, 0x22, 0x04, 0x00, 0x04, 0x61, 0xD1, 0x80, 0xFF, 0xFF, 0x2D, 0x05, + 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x4E, 0xE4, 0x60, 0x58, 0x4F, 0xFB, 0x78, + 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x60, 0xEC, 0x62, 0x10, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCB, 0x60, + 0x95, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1F, 0x60, 0x80, 0x64, 0xA0, 0xD3, + 0xFF, 0xFF, 0x60, 0x40, 0x0C, 0x26, 0x11, 0x00, 0xFD, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, + 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x38, 0x00, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x0F, 0x4E, 0xEC, 0x60, 0x58, 0x4F, 0xB9, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x60, + 0xEC, 0x62, 0x10, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCB, 0x60, 0xC2, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x14, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xFD, 0x60, 0xFF, 0x65, 0x20, 0x44, + 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x88, 0xF1, 0x19, 0x60, 0x86, 0x63, + 0xD3, 0x80, 0x20, 0x44, 0x05, 0x03, 0x10, 0xBC, 0x40, 0x40, 0xCD, 0x60, 0xE8, 0x78, 0xFF, 0xFF, + 0x89, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0x20, 0x44, 0x06, 0x02, 0xD4, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, + 0xFF, 0xFF, 0x1E, 0x02, 0x72, 0x00, 0x10, 0xBC, 0x40, 0x40, 0x64, 0x42, 0x5A, 0xD1, 0x06, 0x63, + 0xA4, 0xD1, 0xC3, 0x83, 0x7F, 0xF9, 0xBD, 0xD1, 0x81, 0xF9, 0xBD, 0xD1, 0xFF, 0xFF, 0x82, 0xF9, + 0xBD, 0xD1, 0x83, 0xF9, 0x04, 0xA3, 0xBD, 0xD1, 0x2D, 0x60, 0x7A, 0x64, 0x64, 0x41, 0xDD, 0x81, + 0xFE, 0xB1, 0xA0, 0xD9, 0x04, 0x03, 0xBD, 0xD1, 0xC9, 0x81, 0x58, 0xD9, 0xFC, 0x02, 0x1E, 0x00, + 0xE5, 0xF3, 0x7F, 0xFB, 0x29, 0x60, 0xA4, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x2D, 0x60, + 0x7A, 0x63, 0x02, 0x02, 0x27, 0x60, 0xB8, 0x61, 0xA1, 0xD3, 0xBD, 0xDB, 0xDC, 0x84, 0xFE, 0xB4, + 0x59, 0xD1, 0xC8, 0x84, 0xBD, 0xD9, 0xFC, 0x02, 0xED, 0xF3, 0x72, 0x45, 0xEC, 0xF3, 0x94, 0x83, + 0x83, 0xFD, 0x94, 0x83, 0x82, 0xFD, 0x65, 0x5F, 0x02, 0x64, 0x81, 0xFB, 0x0F, 0x60, 0xEA, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, + 0xA2, 0xDB, 0xCC, 0x60, 0x26, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x18, 0x64, + 0x3B, 0x42, 0x5A, 0xDB, 0x7F, 0xF1, 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCC, 0x60, + 0x4D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0xCC, 0x60, 0xAD, 0x78, 0xFF, 0xFF, 0x16, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0xFF, 0x60, 0xEF, 0x65, 0x20, 0x44, 0x24, 0x80, 0xCA, 0x60, 0x58, 0x4E, 0xA7, 0x78, 0xFF, 0xFF, + 0x17, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x02, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, + 0xF2, 0xFB, 0xF7, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, + 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0xDA, 0xFE, 0xC1, 0xFE, 0x1A, 0x60, 0x40, 0x62, 0xA2, 0xD1, 0x1A, 0x60, 0x6A, 0x62, + 0xA2, 0xD9, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x06, 0x64, 0xA2, 0xDB, 0xCB, 0x60, + 0x22, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x1A, 0x60, 0x40, 0x61, 0x75, 0x60, 0x30, 0x65, 0xA1, 0xD3, + 0xFF, 0xFF, 0xFF, 0xA0, 0xE0, 0x84, 0x02, 0x02, 0x03, 0x60, 0xE8, 0x64, 0xD4, 0x80, 0xFF, 0xFF, + 0x01, 0x04, 0x65, 0x44, 0xA1, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x79, 0xF3, 0x7A, 0xFB, 0x1F, 0x60, + 0x52, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xFF, 0x60, 0xDF, 0x65, 0x20, 0x44, 0x24, 0x80, 0xBF, 0xF1, + 0x1A, 0x60, 0x6A, 0x62, 0xA2, 0xD9, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, + 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xF7, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, + 0x10, 0x26, 0x67, 0x00, 0x00, 0x64, 0xB5, 0xFB, 0xB6, 0xFB, 0xB7, 0xFB, 0x00, 0x75, 0x00, 0x72, + 0xBD, 0xF1, 0x80, 0xF9, 0x64, 0x44, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x93, 0xE6, 0xF1, + 0x86, 0xF9, 0x28, 0x60, 0xD2, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, 0x08, 0x02, + 0x01, 0x60, 0xB0, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, 0x01, 0x03, 0x02, 0x64, + 0x60, 0x41, 0x2D, 0x60, 0x28, 0x63, 0xBD, 0xD3, 0xA3, 0xD3, 0xFF, 0xB5, 0x65, 0x5C, 0xCD, 0x81, + 0x80, 0xBF, 0x0E, 0x03, 0x80, 0xBF, 0xBD, 0xDB, 0x65, 0x44, 0xC8, 0x84, 0xFF, 0xFF, 0x0B, 0x03, + 0x60, 0x45, 0xCD, 0x81, 0xA3, 0xD3, 0x07, 0x03, 0xCD, 0x81, 0x80, 0xBF, 0x01, 0x03, 0x80, 0xBC, + 0x60, 0x47, 0xBD, 0xDB, 0x00, 0x65, 0x64, 0x41, 0x2D, 0x60, 0x2A, 0x63, 0xBD, 0xD3, 0xFF, 0xFF, + 0x80, 0xB0, 0xFF, 0xFF, 0x01, 0x03, 0x60, 0x45, 0x60, 0x47, 0x80, 0xB0, 0xFF, 0xFF, 0x01, 0x03, + 0x60, 0x45, 0xC9, 0x81, 0xFF, 0xFF, 0xF2, 0x02, 0x65, 0x44, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, + 0x0A, 0x64, 0x15, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x14, 0x64, 0x11, 0x00, 0x0A, 0x3A, 0x02, 0x00, + 0x32, 0x64, 0x0D, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x37, 0x64, 0x09, 0x00, 0x10, 0x3A, 0x02, 0x00, + 0x50, 0x64, 0x05, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x6E, 0x64, 0x01, 0x00, 0x14, 0x64, 0x7C, 0xFB, + 0x28, 0x00, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, + 0x84, 0x64, 0xA2, 0xDB, 0xCD, 0x60, 0x40, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x80, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0D, 0x03, + 0xA0, 0x84, 0xA2, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0xFF, 0x60, 0x7F, 0x61, 0xA1, 0x84, + 0x5A, 0xD1, 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x04, 0x00, 0xBB, 0xFE, 0xCB, 0x60, 0x22, 0x78, + 0xFF, 0xFF, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD1, 0x00, 0x65, 0x64, 0x40, 0x01, 0x36, 0x22, 0x65, + 0x64, 0x40, 0x07, 0x36, 0x01, 0x65, 0xA9, 0xF3, 0x66, 0x5C, 0x60, 0x46, 0x1F, 0x63, 0xE3, 0x83, + 0xB6, 0xF8, 0x02, 0xA6, 0x66, 0x44, 0xFC, 0x1F, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, + 0x60, 0x40, 0x07, 0x3A, 0x04, 0x00, 0xA9, 0xF3, 0x04, 0x65, 0x60, 0x46, 0xB6, 0xF8, 0x64, 0x46, + 0xA9, 0xF3, 0x32, 0x41, 0x60, 0x45, 0x08, 0xB1, 0x66, 0x41, 0x17, 0x03, 0x65, 0x46, 0x29, 0x60, + 0xA2, 0x62, 0xA2, 0xD3, 0x06, 0xF0, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x80, 0xBF, + 0xB0, 0x84, 0x06, 0xFA, 0x66, 0x43, 0x02, 0xA3, 0x63, 0x46, 0x06, 0xF0, 0xFF, 0xFF, 0xB0, 0x84, + 0x06, 0xFA, 0x61, 0x46, 0x32, 0x44, 0x10, 0xBC, 0x40, 0x52, 0x1F, 0x60, 0x52, 0x62, 0x01, 0x64, + 0xA2, 0xDB, 0x0F, 0x4E, 0xE7, 0x60, 0x58, 0x4F, 0x51, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x60, + 0xEA, 0x62, 0xA2, 0xD1, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x0F, 0x60, 0xEC, 0x62, + 0x00, 0x60, 0x04, 0x64, 0xA2, 0xDB, 0xCB, 0x60, 0x11, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x24, 0x60, + 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0xBB, 0xFE, 0x20, 0x44, 0x04, 0x27, 0x12, 0x00, 0x10, 0x26, 0x02, 0x00, 0xDB, 0xFE, 0x16, 0x00, + 0x0F, 0x60, 0xCE, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x36, 0x07, 0x00, 0x01, 0x64, + 0xA1, 0xDB, 0x01, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xD0, 0x62, + 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x64, 0x8C, 0xFB, + 0xFF, 0x60, 0xEF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x03, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, + 0xFE, 0xB4, 0xF2, 0xFB, 0xC1, 0xFE, 0x1E, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, + 0x15, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xBB, 0xFE, 0xCF, 0x60, 0xD6, 0x78, 0xFF, 0xFF, 0x28, 0x60, + 0x2C, 0x62, 0xA2, 0xD1, 0x00, 0x65, 0x64, 0x40, 0x01, 0x36, 0x22, 0x65, 0xA9, 0xF3, 0x66, 0x5C, + 0x60, 0x46, 0x1F, 0x63, 0xE3, 0x83, 0xB6, 0xF8, 0x02, 0xA6, 0x66, 0x44, 0xFC, 0x1F, 0x64, 0x46, + 0x79, 0xF1, 0xA9, 0xF3, 0x7A, 0xF9, 0x02, 0xA4, 0xD8, 0xF3, 0x60, 0x45, 0x66, 0x41, 0x65, 0x46, + 0x8C, 0xFA, 0x60, 0x40, 0x01, 0x36, 0x06, 0x00, 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, + 0x05, 0x3A, 0x02, 0x00, 0x00, 0x64, 0x01, 0x00, 0x01, 0x64, 0x6F, 0xFA, 0x79, 0xF3, 0x7A, 0xF1, + 0xFF, 0xFF, 0xA0, 0x84, 0x65, 0x43, 0x02, 0x02, 0x79, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, + 0xAE, 0x65, 0xD8, 0xF3, 0xFF, 0xFF, 0xE0, 0x84, 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, + 0x04, 0x02, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x7B, 0xFB, 0x6F, 0xF0, + 0x60, 0x47, 0x90, 0x84, 0x6F, 0xFA, 0x60, 0x47, 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, + 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x70, 0xF0, 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, + 0x02, 0x05, 0xDD, 0x81, 0xFB, 0x01, 0xE1, 0x81, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, + 0x66, 0x43, 0x0C, 0xF4, 0xA9, 0xF1, 0x02, 0x64, 0xC0, 0x85, 0x0C, 0x61, 0x32, 0x40, 0x08, 0x2A, + 0x15, 0x00, 0x29, 0x60, 0xA2, 0x62, 0xA2, 0xD3, 0x66, 0x41, 0x65, 0x46, 0x06, 0xF0, 0xE0, 0x84, + 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x80, 0xBF, 0xB0, 0x83, 0x06, 0xFC, 0x66, 0x42, 0xFE, 0xA2, + 0x62, 0x46, 0x06, 0xF0, 0xFF, 0xFF, 0xB0, 0x84, 0x06, 0xFA, 0x61, 0x46, 0x1D, 0x64, 0x3B, 0x42, + 0x5A, 0xDB, 0x0B, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF2, 0xFB, 0x01, 0x65, + 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0xE5, 0xF1, 0x7F, 0xF9, 0x0F, 0x60, 0xEA, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, + 0xA2, 0xDB, 0xCE, 0x60, 0x76, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7F, 0xF1, + 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, + 0xEC, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCE, 0x60, 0x9A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0xBE, 0xFE, + 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x01, 0x64, 0x8C, 0xFB, 0xFF, 0x60, 0xDF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x1E, 0x64, 0x3B, 0x42, + 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x06, 0x64, 0xDC, 0xFB, + 0xF2, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF2, 0xFB, 0xE5, 0xF1, 0x7F, 0xF9, 0x0F, 0x60, 0xEA, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x64, 0x8C, 0xFB, 0xFF, 0x60, 0xDF, 0x65, 0x20, 0x44, 0x24, 0x80, + 0xA9, 0xF1, 0x66, 0x45, 0x64, 0x46, 0x66, 0x43, 0x02, 0xA3, 0x63, 0x46, 0x02, 0x64, 0x06, 0xFA, + 0x04, 0x63, 0x04, 0x61, 0x01, 0x60, 0xCE, 0x64, 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, 0x65, 0x46, + 0x01, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0x1E, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x2F, 0x58, 0xFF, 0xFF, 0x1F, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x00, 0x64, 0x68, 0xFB, 0x69, 0xFB, + 0xA9, 0xF1, 0x0E, 0x64, 0x66, 0x41, 0x64, 0x42, 0x02, 0xA2, 0x62, 0x46, 0x06, 0xF0, 0xFF, 0x60, + 0xFC, 0x64, 0xA0, 0x84, 0x06, 0xFA, 0x61, 0x46, 0xDC, 0xF3, 0xFF, 0xFF, 0x04, 0xA8, 0x0F, 0x60, + 0xCE, 0x64, 0x07, 0x03, 0xA0, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x2A, 0x02, 0x00, 0x00, 0x63, + 0xA0, 0xDD, 0x01, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF2, 0xFB, 0x0F, 0x60, + 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, + 0xCA, 0x60, 0xFB, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, + 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x28, 0x60, 0x3A, 0x64, 0xA0, 0xD3, 0x00, 0xF4, 0x60, 0x40, 0x01, 0x3A, 0x42, 0x00, 0x18, 0x65, + 0x22, 0x61, 0x02, 0x60, 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, + 0x04, 0x65, 0x64, 0x44, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, + 0xCD, 0x81, 0xBD, 0xDB, 0xF0, 0x02, 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, 0x01, 0xA8, + 0xE0, 0x85, 0x27, 0x02, 0xC7, 0x83, 0xBD, 0xD3, 0xBD, 0xD3, 0x81, 0xA8, 0x0D, 0xA8, 0x21, 0x02, + 0x20, 0x02, 0xBD, 0xD3, 0xBD, 0xD3, 0x00, 0xA8, 0x60, 0xA8, 0x1B, 0x02, 0xBD, 0xD3, 0x19, 0x02, + 0x1D, 0xA8, 0xA3, 0xD1, 0x16, 0x02, 0xE3, 0xF9, 0x01, 0x60, 0xB8, 0x64, 0x63, 0x41, 0x0A, 0x63, + 0x59, 0xD1, 0x58, 0xD9, 0xFD, 0x1F, 0x59, 0xD1, 0x59, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x64, 0x5E, + 0xD6, 0xFB, 0x59, 0xD1, 0x28, 0x60, 0x36, 0x64, 0xA0, 0xD9, 0x28, 0x60, 0xD6, 0x64, 0xA0, 0xD9, + 0x23, 0x00, 0x28, 0x60, 0x40, 0x64, 0xA0, 0xD3, 0xE3, 0xFB, 0x60, 0x40, 0x05, 0x3A, 0x03, 0x00, + 0x68, 0x60, 0xBA, 0x61, 0x11, 0x00, 0x04, 0x3A, 0x03, 0x00, 0x68, 0x60, 0xAE, 0x61, 0x0C, 0x00, + 0x03, 0x3A, 0x03, 0x00, 0x68, 0x60, 0xA2, 0x61, 0x07, 0x00, 0x02, 0x3A, 0x03, 0x00, 0x68, 0x60, + 0x96, 0x61, 0x02, 0x00, 0x68, 0x60, 0x8A, 0x61, 0x3C, 0x60, 0x00, 0x66, 0x01, 0x60, 0xB8, 0x64, + 0x0A, 0x63, 0x59, 0xD0, 0x58, 0xD9, 0xFD, 0x1F, 0x01, 0x60, 0xBE, 0x61, 0xE4, 0xF3, 0x00, 0x66, + 0x00, 0xA8, 0x04, 0x65, 0x01, 0x03, 0xA1, 0xDB, 0x1F, 0x60, 0x08, 0x63, 0x55, 0xD3, 0xFF, 0xFF, + 0x20, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, 0x21, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, + 0x22, 0x7F, 0xA3, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, + 0x0F, 0x60, 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCF, 0x60, 0xA2, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0x9A, 0x62, 0x1F, 0x60, 0x06, 0x64, 0xA2, 0xDB, + 0x20, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x20, 0x60, 0x00, 0x64, + 0xA2, 0xDB, 0xCF, 0x60, 0xC7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, + 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, + 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x40, 0x64, 0x3B, 0x42, + 0x5A, 0xDB, 0xBC, 0xF1, 0x1A, 0x60, 0x6A, 0x62, 0xA2, 0xD9, 0x60, 0xF5, 0xEB, 0xF1, 0x2F, 0xF8, + 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0xBC, 0xF1, 0x19, 0xF8, 0xF8, 0x60, 0x80, 0x64, + 0x0E, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0xA9, 0xF1, 0x07, 0xF8, 0x00, 0x60, 0xD0, 0x63, 0x19, 0x60, + 0x84, 0x64, 0xA3, 0xDB, 0x44, 0x60, 0x44, 0x64, 0x81, 0xFB, 0x82, 0xFB, 0x83, 0xFB, 0x31, 0x44, + 0xF9, 0xB4, 0x40, 0x51, 0x00, 0x60, 0xD0, 0x63, 0x01, 0x60, 0x10, 0x65, 0xA3, 0xD3, 0xA5, 0xD1, + 0x04, 0xA4, 0xA3, 0xDB, 0xD0, 0x80, 0xA0, 0xD1, 0x0A, 0x06, 0x41, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xCC, 0x60, 0x5D, 0x78, 0xFF, 0xFF, 0x44, 0x47, + 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xFF, 0xA4, 0xFF, 0xFF, 0x08, 0x07, 0x0E, 0x61, + 0x41, 0xD3, 0x32, 0x40, 0x08, 0x26, 0x03, 0x00, 0x10, 0xB0, 0xFF, 0xFF, 0xD3, 0x02, 0x42, 0x64, + 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, + 0x0F, 0x60, 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD0, 0x60, 0x22, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0xD1, 0x7F, 0xF9, 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, + 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x20, 0x60, 0x00, 0x64, + 0xA2, 0xDB, 0xD0, 0x60, 0x47, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, + 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, + 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x1A, 0x60, 0x6A, 0x62, 0x07, 0x60, 0xD0, 0x64, + 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD3, 0x81, 0xFB, 0xBD, 0xD3, 0x82, 0xFB, + 0xA3, 0xD3, 0x83, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xEC, 0x62, + 0x01, 0x60, 0x04, 0x64, 0xA2, 0xDB, 0xD0, 0x60, 0x79, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0xBC, 0xF1, 0x1A, 0x60, 0x6A, 0x62, 0xA2, 0xD9, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, + 0xFE, 0x60, 0xFF, 0x61, 0xA1, 0x84, 0x5A, 0xD1, 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x0F, 0x60, + 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0xCF, 0x60, 0xF2, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x08, 0x65, 0x20, 0x44, 0x34, 0x80, + 0x5F, 0xF5, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0xBC, 0xF1, + 0x19, 0xF8, 0x80, 0x7E, 0xF8, 0x7F, 0x0E, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0xA9, 0xF1, 0x07, 0xF8, + 0x2B, 0xFA, 0xB0, 0x64, 0x2A, 0xFA, 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD1, 0x2C, 0xF8, 0x32, 0xF8, + 0xBD, 0xD1, 0x2D, 0xF8, 0x33, 0xF8, 0xA3, 0xD1, 0x2E, 0xF8, 0x34, 0xF8, 0x06, 0x63, 0x3F, 0xFC, + 0x1F, 0x60, 0x54, 0x61, 0xDC, 0xF3, 0xA1, 0xD3, 0x03, 0xA8, 0xAC, 0x83, 0x0F, 0x02, 0x0E, 0x03, + 0x1F, 0x60, 0x56, 0x61, 0xA1, 0xD1, 0x66, 0x45, 0x00, 0xF4, 0x09, 0xFC, 0x01, 0x64, 0x0A, 0xFA, + 0x0B, 0xF8, 0x1F, 0x60, 0x54, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x28, 0x00, 0x28, 0x60, 0x2E, 0x64, + 0xA0, 0xD3, 0x66, 0x45, 0x00, 0xF4, 0x60, 0x40, 0x01, 0x36, 0x16, 0x00, 0x02, 0x36, 0xC7, 0x00, + 0x03, 0x36, 0x07, 0x00, 0x04, 0x36, 0x10, 0x00, 0x05, 0x36, 0xC1, 0x00, 0x06, 0x36, 0x01, 0x00, + 0x0B, 0x00, 0x80, 0x64, 0x09, 0xFA, 0x01, 0x63, 0x0A, 0xFC, 0x00, 0x64, 0x0B, 0xFA, 0x2D, 0x60, + 0x54, 0x62, 0x03, 0x64, 0xA2, 0xDB, 0x0A, 0x00, 0x00, 0x64, 0x09, 0xFA, 0x01, 0x63, 0x0A, 0xFC, + 0x00, 0x64, 0x0B, 0xFA, 0x2D, 0x60, 0x54, 0x62, 0x01, 0x64, 0xA2, 0xDB, 0x24, 0x60, 0x74, 0x62, + 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x65, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0x00, 0x66, 0xDC, 0xF3, 0x46, 0x46, 0xFD, 0xA0, 0xC1, 0xFE, 0x02, 0x02, 0x2F, 0x58, + 0xFF, 0xFF, 0x01, 0x64, 0x69, 0xFB, 0x43, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x1A, 0x60, 0x44, 0x62, + 0xA2, 0xD3, 0xFF, 0xFF, 0x64, 0xA4, 0xA2, 0xDB, 0x1A, 0x60, 0x44, 0x62, 0xA2, 0xD1, 0x1A, 0x60, + 0x6A, 0x62, 0xA2, 0xD9, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x0C, 0x64, 0xA2, 0xDB, + 0xD1, 0x60, 0x2E, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, + 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x56, 0x03, 0xA0, 0x84, 0xA2, 0xDB, + 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x26, 0x46, + 0x00, 0xF4, 0x09, 0xF2, 0x0A, 0xF2, 0x00, 0xA8, 0x0B, 0xF2, 0x02, 0xA8, 0x16, 0x02, 0x00, 0xA8, + 0x1A, 0x02, 0x19, 0x02, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, + 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, 0xD3, 0x60, + 0x48, 0x78, 0xFF, 0xFF, 0xD9, 0x60, 0x68, 0x78, 0xFF, 0xFF, 0x09, 0xF2, 0x0A, 0xF2, 0x80, 0xA8, + 0x0B, 0xF2, 0x02, 0xA8, 0xE4, 0x03, 0x44, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0B, 0xF2, 0x26, 0x46, + 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, + 0x31, 0xF2, 0x59, 0xDB, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, + 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x03, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x4C, 0x78, + 0xFF, 0xFF, 0xDC, 0x60, 0xAA, 0x78, 0xFF, 0xFF, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, 0xA2, 0xDB, + 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x20, 0x40, 0x08, 0x2A, + 0x03, 0x00, 0xCF, 0x60, 0xF2, 0x78, 0xFF, 0xFF, 0xD7, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0x01, 0x63, + 0x09, 0xFC, 0x32, 0x40, 0x08, 0x26, 0x1A, 0x00, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, + 0x60, 0x40, 0x0B, 0x36, 0x03, 0x00, 0xD0, 0x60, 0xEC, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0xA2, 0xDB, + 0x2D, 0x60, 0x56, 0x62, 0x0B, 0x64, 0xA2, 0xDB, 0x2D, 0x60, 0x54, 0x62, 0x02, 0x64, 0xA2, 0xDB, + 0xA9, 0xF1, 0x66, 0x41, 0x64, 0x46, 0x22, 0x64, 0x36, 0xFA, 0x61, 0x46, 0x01, 0x64, 0x0A, 0xFA, + 0x00, 0x64, 0x0B, 0xFA, 0x01, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x65, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x66, 0xDC, 0xF3, 0x46, 0x46, 0xFD, 0xA0, 0xC1, 0xFE, + 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, + 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x0C, 0x64, + 0xA2, 0xDB, 0xD1, 0x60, 0xEF, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, + 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x3B, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x69, 0xFB, 0x26, 0x46, 0x00, 0xF4, 0x09, 0xF2, 0x0A, 0xF2, + 0x01, 0xA8, 0x0B, 0xF2, 0x02, 0xA8, 0x04, 0x02, 0x00, 0xA8, 0x02, 0x02, 0x01, 0x02, 0x31, 0x00, + 0xD2, 0x60, 0x58, 0x4D, 0xF6, 0x78, 0xFF, 0xFF, 0x0B, 0xF2, 0x26, 0x46, 0x40, 0x59, 0x02, 0x60, + 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x31, 0xF2, 0x59, 0xDB, + 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, + 0x00, 0x66, 0x46, 0x46, 0x03, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x4C, 0x78, 0xFF, 0xFF, 0xDC, 0x60, + 0xAA, 0x78, 0xFF, 0xFF, 0xD2, 0x60, 0x58, 0x4D, 0xF6, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x69, 0xFB, + 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, 0xCF, 0x60, 0xF2, 0x78, 0xFF, 0xFF, 0xD7, 0x60, 0xDD, 0x78, + 0xFF, 0xFF, 0x26, 0x46, 0x40, 0x60, 0x00, 0x65, 0x2A, 0xF2, 0x2F, 0xF0, 0xB4, 0x84, 0x2A, 0xFA, + 0x2C, 0xF8, 0x32, 0xF8, 0x30, 0xF2, 0x2D, 0xFA, 0x33, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0x34, 0xFA, + 0xEB, 0xF3, 0x2F, 0xFA, 0xEC, 0xF3, 0x30, 0xFA, 0xED, 0xF3, 0x31, 0xFA, 0xCC, 0xF1, 0x19, 0xF8, + 0x1C, 0xF0, 0x13, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x00, 0xF4, 0x03, 0x64, 0x0A, 0xFA, 0x00, 0x64, + 0x0B, 0xFA, 0x01, 0x63, 0x69, 0xFD, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x24, 0x60, + 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x66, 0xDC, 0xF3, 0x46, 0x46, 0xFD, 0xA0, 0xC1, 0xFE, 0x02, 0x02, + 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x0C, 0x64, 0xA2, 0xDB, + 0xD2, 0x60, 0x8E, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, + 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x51, 0x03, 0xA0, 0x84, 0xA2, 0xDB, + 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0x00, 0x64, 0x69, 0xFB, 0x26, 0x46, 0x00, 0xF4, 0x09, 0xF2, 0x0A, 0xF2, 0x01, 0xA8, + 0x0B, 0xF2, 0x04, 0xA8, 0x1A, 0x02, 0x00, 0xA8, 0x18, 0x02, 0x17, 0x02, 0xD2, 0x60, 0x58, 0x4D, + 0xF6, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, + 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, 0xD3, 0x60, + 0x48, 0x78, 0xFF, 0xFF, 0xD9, 0x60, 0x68, 0x78, 0xFF, 0xFF, 0xD2, 0x60, 0x58, 0x4D, 0xF6, 0x78, + 0xFF, 0xFF, 0x0B, 0xF2, 0x26, 0x46, 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, + 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x31, 0xF2, 0x59, 0xDB, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, + 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x03, 0x65, + 0xE9, 0x60, 0x58, 0x4E, 0x4C, 0x78, 0xFF, 0xFF, 0xDC, 0x60, 0xAA, 0x78, 0xFF, 0xFF, 0xD2, 0x60, + 0x58, 0x4D, 0xF6, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x69, 0xFB, 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, + 0xCF, 0x60, 0xF2, 0x78, 0xFF, 0xFF, 0xD7, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0x2D, 0x60, 0x56, 0x62, + 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x0B, 0x3A, 0x07, 0x00, 0x28, 0x60, 0x2C, 0x62, 0x0B, 0x64, + 0xA2, 0xDB, 0x2D, 0x60, 0x56, 0x62, 0xA2, 0xDF, 0x2D, 0x58, 0xFF, 0xFF, 0x28, 0x60, 0x2C, 0x62, + 0xA2, 0xD3, 0x61, 0x43, 0xA5, 0xD2, 0x60, 0x40, 0x0B, 0x2A, 0x30, 0x00, 0x85, 0x3A, 0x30, 0x00, + 0x60, 0x41, 0x65, 0x44, 0x0A, 0xA4, 0xA0, 0xD0, 0x2D, 0x60, 0x52, 0x62, 0x64, 0x40, 0x18, 0x26, + 0x06, 0x00, 0xA2, 0xDF, 0x28, 0x60, 0x2C, 0x62, 0x01, 0x64, 0xA2, 0xDB, 0x02, 0x00, 0x01, 0x64, + 0xA2, 0xDB, 0x61, 0x44, 0x60, 0x47, 0xFF, 0xB4, 0x02, 0xA4, 0x2E, 0x60, 0x62, 0x61, 0xA1, 0xD1, + 0xDF, 0x83, 0xC0, 0x84, 0xA1, 0xDB, 0xD0, 0x81, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, + 0xA5, 0xD2, 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, + 0x5D, 0x93, 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x2D, 0x58, 0xFF, 0xFF, + 0x2D, 0x60, 0x52, 0x62, 0xA2, 0xDF, 0x28, 0x60, 0x2C, 0x62, 0x01, 0x64, 0xA2, 0xDB, 0xF6, 0x01, + 0x45, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x2E, 0x60, 0xEA, 0x7C, 0x2E, 0x60, 0xDE, 0x63, 0xA3, 0xD9, + 0x64, 0x41, 0x29, 0x60, 0xA4, 0x63, 0xBD, 0xD3, 0x00, 0x7C, 0x03, 0x1B, 0x27, 0x43, 0x10, 0xA3, + 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x45, 0x64, 0x5F, 0xA1, 0xDB, 0x65, 0x44, 0xBD, 0xD1, 0xC8, 0x84, + 0x59, 0xD8, 0xFC, 0x05, 0x27, 0x41, 0x10, 0xA1, 0xA1, 0xD1, 0xFF, 0xFF, 0xC1, 0x81, 0x01, 0x26, + 0xDD, 0x81, 0x41, 0x4C, 0x59, 0xD1, 0x7C, 0x44, 0xB0, 0x84, 0x59, 0xD1, 0x59, 0xD1, 0xB0, 0x84, + 0xB0, 0x84, 0xFF, 0xFF, 0x02, 0x02, 0x67, 0x44, 0x5D, 0x00, 0x2D, 0x60, 0xE6, 0x63, 0xDD, 0x60, + 0x18, 0x64, 0xBD, 0xDA, 0x50, 0x60, 0x00, 0x64, 0xBD, 0xDA, 0x01, 0x60, 0xF2, 0x64, 0xBD, 0xDA, + 0x00, 0x60, 0x01, 0x64, 0xBD, 0xDA, 0x2C, 0x41, 0x59, 0xD3, 0x50, 0x60, 0x00, 0x7C, 0x60, 0x40, + 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, 0xF2, 0x64, 0x0E, 0x00, 0x04, 0x2A, 0x03, 0x00, 0x02, 0x60, + 0xF2, 0x64, 0x09, 0x00, 0x10, 0x2A, 0x03, 0x00, 0x04, 0x60, 0xF2, 0x64, 0x04, 0x00, 0x20, 0x2A, + 0x04, 0x00, 0x05, 0x60, 0xF2, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, 0x01, 0x64, 0xBD, 0xDB, 0x59, 0xD3, + 0x50, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, 0xF2, 0x64, 0x0E, 0x00, + 0x04, 0x2A, 0x03, 0x00, 0x02, 0x60, 0xF2, 0x64, 0x09, 0x00, 0x10, 0x2A, 0x03, 0x00, 0x04, 0x60, + 0xF2, 0x64, 0x04, 0x00, 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, 0xF2, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, + 0x01, 0x64, 0xBD, 0xDB, 0x59, 0xD3, 0x50, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x01, 0x2A, 0x03, 0x00, + 0x00, 0x60, 0xF2, 0x64, 0x09, 0x00, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, 0xF2, 0x64, 0x04, 0x00, + 0x04, 0x2A, 0x02, 0x00, 0x02, 0x60, 0xF2, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, 0x59, 0xD3, 0xBD, 0xDA, + 0x2D, 0x60, 0xE6, 0x64, 0x2E, 0x60, 0xE4, 0x62, 0xA2, 0xDB, 0x60, 0xF5, 0x00, 0x64, 0x2B, 0xFA, + 0x00, 0x64, 0x2A, 0xFA, 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD1, 0x2C, 0xF8, 0x32, 0xF8, 0xBD, 0xD1, + 0x2D, 0xF8, 0x33, 0xF8, 0xA3, 0xD1, 0x2E, 0xF8, 0x34, 0xF8, 0x00, 0xF4, 0x01, 0x63, 0x32, 0x40, + 0x08, 0x26, 0x10, 0xBB, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0xFE, 0x26, + 0x10, 0xBB, 0x09, 0xFC, 0x27, 0x42, 0x0C, 0xA2, 0x28, 0x60, 0x02, 0x63, 0xA2, 0xD3, 0xA3, 0xD3, + 0x00, 0xBD, 0x01, 0x63, 0xAC, 0x81, 0x09, 0x03, 0x08, 0x03, 0xB0, 0x60, 0x58, 0x4D, 0xB6, 0x78, + 0xFF, 0xFF, 0x00, 0xB8, 0x01, 0x63, 0x01, 0x03, 0x60, 0x43, 0x1A, 0x60, 0x3E, 0x64, 0xA0, 0xDD, + 0x12, 0x61, 0x59, 0xDC, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD3, 0xFF, 0x60, 0xFF, 0x7C, 0x60, 0x40, + 0x0B, 0x2A, 0x02, 0x00, 0x2D, 0x60, 0x32, 0x7C, 0x2E, 0x60, 0xE6, 0x62, 0xA2, 0xD9, 0x2E, 0x60, + 0xDE, 0x64, 0x40, 0x48, 0xD9, 0x81, 0xFF, 0x60, 0xF2, 0x64, 0xE8, 0x60, 0x58, 0x4D, 0xE8, 0x78, + 0xFF, 0xFF, 0x60, 0xF5, 0x3F, 0xFC, 0xDB, 0x83, 0x2E, 0x60, 0x08, 0x62, 0xA2, 0xDD, 0x00, 0x7C, + 0x5A, 0xD9, 0x63, 0x41, 0x2E, 0x60, 0x0C, 0x63, 0x12, 0x65, 0x00, 0xF4, 0xCD, 0x84, 0x4C, 0x91, + 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, + 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, + 0x60, 0xF5, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xC1, 0xFE, 0x06, 0x64, + 0x69, 0xFB, 0x46, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, + 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, + 0x1C, 0x64, 0xA2, 0xDB, 0xD4, 0x60, 0x68, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x3A, 0x03, + 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x26, 0x46, + 0x00, 0xF4, 0x0A, 0xF2, 0x00, 0x63, 0x00, 0xA8, 0x69, 0xFD, 0x5A, 0x03, 0x0A, 0xF2, 0x26, 0x46, + 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, + 0x31, 0xF2, 0x59, 0xDB, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, + 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x05, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x4C, 0x78, + 0xFF, 0xFF, 0xDC, 0x60, 0xAA, 0x78, 0xFF, 0xFF, 0x47, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xCF, 0x60, + 0xF2, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x21, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, + 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x49, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xD0, 0x60, 0x94, 0x78, 0xFF, 0xFF, + 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x4A, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xCF, 0x60, 0xF2, 0x78, 0xFF, 0xFF, + 0x48, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x09, 0xF0, 0x2E, 0x60, 0x64, 0x63, 0x10, 0x64, 0xBD, 0xDB, + 0xBD, 0xD9, 0x0A, 0xF0, 0xBD, 0xD9, 0x0B, 0xF0, 0xBD, 0xD9, 0x0C, 0xF2, 0xBD, 0xDB, 0x60, 0x47, + 0xFF, 0xB4, 0x0A, 0xA5, 0x2E, 0x60, 0x62, 0x61, 0x65, 0x5C, 0xA1, 0xD9, 0x60, 0x41, 0x1A, 0x65, + 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, + 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, + 0x20, 0xFE, 0xDF, 0x83, 0xD3, 0x60, 0x58, 0x4D, 0x06, 0x78, 0xFF, 0xFF, 0x0B, 0xF2, 0xFF, 0xFF, + 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x61, 0x44, 0x96, 0xFB, + 0x27, 0x45, 0x02, 0x62, 0x46, 0xD3, 0x5A, 0xD1, 0x60, 0x47, 0x56, 0xFB, 0x64, 0x47, 0x55, 0xFB, + 0x00, 0x64, 0x5C, 0xFB, 0x0C, 0x62, 0x46, 0xD3, 0x80, 0xFB, 0x0B, 0xF0, 0x0F, 0x60, 0xFF, 0x64, + 0xA0, 0x84, 0x85, 0xFB, 0x26, 0x46, 0x32, 0xF0, 0x81, 0xF9, 0x33, 0xF0, 0x0E, 0x63, 0xC7, 0x81, + 0x82, 0xF9, 0x34, 0xF0, 0x83, 0xF9, 0x59, 0xD1, 0xFF, 0xFF, 0x64, 0x44, 0x01, 0x2A, 0xC8, 0x84, + 0x60, 0x43, 0x2D, 0x60, 0x78, 0x64, 0x58, 0xD9, 0x59, 0xD1, 0x58, 0xD9, 0xFD, 0x1F, 0x28, 0x60, + 0x2C, 0x62, 0xA2, 0xD1, 0x59, 0xD3, 0x64, 0x40, 0x01, 0x36, 0x22, 0x64, 0x64, 0x40, 0x00, 0x36, + 0x50, 0x94, 0xA9, 0xF1, 0xFF, 0xFF, 0x44, 0x47, 0xA7, 0x46, 0x36, 0xFA, 0xB7, 0xFC, 0xA7, 0x46, + 0x1A, 0x60, 0x3E, 0x62, 0xA2, 0xD3, 0x87, 0xFB, 0x31, 0xF2, 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, + 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, + 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, + 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA9, 0xF3, 0x08, 0xFE, + 0x60, 0x43, 0x61, 0x46, 0xA9, 0xF1, 0xFF, 0xFF, 0xD3, 0x80, 0x31, 0xF2, 0x27, 0x02, 0x66, 0x41, + 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xA9, 0xF1, 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, + 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, + 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, + 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, + 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, 0x43, 0x47, 0x00, 0xF4, + 0x18, 0x65, 0x0C, 0x61, 0x02, 0x60, 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x64, 0x44, 0x00, 0x7F, + 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0xF4, 0x02, + 0x02, 0x60, 0x02, 0x61, 0xA1, 0xD3, 0x00, 0x65, 0x60, 0x43, 0x59, 0xD3, 0xFF, 0xFF, 0x7F, 0xB4, + 0x02, 0x3A, 0x02, 0x00, 0x01, 0x64, 0x15, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x02, 0x64, 0x11, 0x00, + 0x0A, 0x3A, 0x02, 0x00, 0x04, 0x64, 0x0D, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x08, 0x64, 0x09, 0x00, + 0x10, 0x3A, 0x02, 0x00, 0x10, 0x64, 0x05, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x20, 0x64, 0x01, 0x00, + 0x00, 0x64, 0xCF, 0x83, 0xB4, 0x85, 0xE1, 0x02, 0x65, 0x44, 0x7A, 0xFB, 0x02, 0x60, 0x02, 0x61, + 0xA1, 0xD3, 0x00, 0x65, 0x60, 0x43, 0x59, 0xD3, 0xFF, 0xFF, 0x80, 0xB0, 0xFF, 0xFF, 0x01, 0x03, + 0x60, 0x45, 0xCF, 0x83, 0x65, 0x44, 0xF7, 0x02, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, 0x0A, 0x64, + 0x15, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x14, 0x64, 0x11, 0x00, 0x0A, 0x3A, 0x02, 0x00, 0x32, 0x64, + 0x0D, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x37, 0x64, 0x09, 0x00, 0x10, 0x3A, 0x02, 0x00, 0x50, 0x64, + 0x05, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x6E, 0x64, 0x01, 0x00, 0x14, 0x64, 0x7C, 0xFB, 0x27, 0x44, + 0xD8, 0xF3, 0x60, 0x45, 0x66, 0x41, 0x65, 0x46, 0x8C, 0xFA, 0x60, 0x40, 0x01, 0x36, 0x06, 0x00, + 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x64, 0x01, 0x00, + 0x01, 0x64, 0x6F, 0xFA, 0x79, 0xF3, 0x7A, 0xF1, 0xFF, 0xFF, 0xA0, 0x84, 0x65, 0x43, 0x02, 0x02, + 0x79, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, 0xAE, 0x65, 0xD8, 0xF3, 0xFF, 0xFF, 0xE0, 0x84, + 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x04, 0x02, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, + 0xFC, 0x03, 0xA4, 0x84, 0x7B, 0xFB, 0x6F, 0xF0, 0x60, 0x47, 0x90, 0x84, 0x6F, 0xFA, 0x60, 0x47, + 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x70, 0xF0, + 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, 0x02, 0x05, 0xDD, 0x81, 0xFB, 0x01, 0xE1, 0x81, + 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x66, 0x43, 0x0C, 0xF4, 0x2D, 0x60, 0xD2, 0x62, + 0xA2, 0xD3, 0x2D, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x60, 0x47, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD1, + 0xB0, 0x84, 0x64, 0x40, 0x01, 0x36, 0x22, 0x64, 0x64, 0x40, 0x00, 0x36, 0x50, 0x94, 0xA7, 0x46, + 0x36, 0xFA, 0xB7, 0xFC, 0xA7, 0x46, 0x80, 0x60, 0x03, 0x65, 0x32, 0x40, 0x08, 0x2A, 0x03, 0x65, + 0xA7, 0x46, 0x06, 0xF0, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xB4, 0x84, 0x06, 0xFA, 0xB7, 0xFC, + 0xA7, 0x46, 0x26, 0x46, 0x2F, 0xF0, 0x30, 0xF0, 0x64, 0x43, 0x31, 0xF2, 0x27, 0x46, 0x03, 0xFC, + 0x04, 0xF8, 0x05, 0xFA, 0x26, 0x46, 0xCF, 0x60, 0x58, 0x4E, 0x20, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, + 0x46, 0x46, 0x01, 0x64, 0x8C, 0xFB, 0x28, 0x60, 0x38, 0x62, 0xA2, 0xD3, 0x20, 0x41, 0x00, 0xBC, + 0x20, 0xB9, 0x01, 0x03, 0x41, 0x40, 0x1F, 0x60, 0x52, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x04, 0x64, + 0xC1, 0xFE, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF2, 0xFB, 0xF7, 0x60, 0xFF, 0x65, + 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0x0F, 0x60, + 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0C, 0x64, + 0x69, 0xFB, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x31, 0x64, 0xA2, 0xDB, 0xD6, 0x60, 0xC4, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x0E, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x01, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x10, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x31, 0x60, 0x2C, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x03, 0x1B, + 0xDC, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0xDC, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0xD7, 0x60, 0x67, 0x78, + 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xF8, 0x03, 0xA0, 0x84, 0xA2, 0xDB, + 0xA9, 0xF3, 0xFF, 0xFF, 0x02, 0xA4, 0x60, 0x43, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, + 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0xA9, 0xF3, 0x63, 0x45, + 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, + 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x4B, 0x64, 0x3B, 0x42, + 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, 0x2E, 0x62, 0xA2, 0xD3, + 0xFF, 0xFF, 0x10, 0xB0, 0xFF, 0xFF, 0x13, 0x03, 0x0F, 0x60, 0xEC, 0x62, 0x04, 0x60, 0x00, 0x64, + 0xA2, 0xDB, 0xD7, 0x60, 0x2F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, + 0x01, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x6A, 0xF3, + 0xFF, 0xFF, 0x01, 0xB0, 0xFF, 0xFF, 0x13, 0x03, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, + 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xEC, 0x62, 0x02, 0x60, 0x00, 0x64, + 0xA2, 0xDB, 0xD7, 0x60, 0x47, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, + 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x64, 0x69, 0xFB, 0xD7, 0x60, 0x58, 0x4E, 0x77, 0x78, + 0xFF, 0xFF, 0x02, 0x64, 0x8C, 0xFB, 0x02, 0x64, 0xC1, 0xFE, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, + 0x01, 0xBC, 0xF2, 0xFB, 0x02, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0x03, 0x60, + 0xE8, 0x63, 0x1A, 0x60, 0x40, 0x64, 0xA0, 0xDD, 0xCB, 0x60, 0x1A, 0x78, 0xFF, 0xFF, 0x00, 0x60, + 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xFF, 0xFF, 0x08, 0x24, 0x54, 0x01, 0xA0, 0x84, 0xA2, 0xDB, + 0x00, 0x63, 0x69, 0xFD, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x15, 0x00, 0x24, 0x60, + 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x64, 0x8C, 0xFB, + 0xFF, 0xFF, 0xC1, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x50, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, + 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, 0x2E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x10, 0xB0, + 0xFF, 0xFF, 0x13, 0x03, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xEC, 0x62, 0x04, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD7, 0x60, + 0x8F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBC, 0xF1, 0x1A, 0x60, 0x6A, 0x62, + 0xA2, 0xD9, 0x7F, 0xF1, 0x7E, 0xF9, 0x02, 0x64, 0x8C, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x8C, 0xF3, + 0x00, 0x65, 0xD4, 0x80, 0xFF, 0xFF, 0x0F, 0x03, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x0F, 0x60, 0xEC, 0x62, 0x80, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD7, 0x60, 0xB3, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x51, 0x64, + 0x3B, 0x42, 0x5A, 0xDB, 0x19, 0x60, 0x84, 0x64, 0x68, 0xFB, 0x1A, 0x60, 0x46, 0x63, 0x81, 0xF3, + 0xBD, 0xDB, 0x82, 0xF3, 0xBD, 0xDB, 0x83, 0xF3, 0xA3, 0xDB, 0x01, 0x60, 0x10, 0x65, 0x68, 0xF3, + 0xA5, 0xD1, 0x04, 0xA4, 0x68, 0xFB, 0xD0, 0x80, 0xA0, 0xD3, 0x20, 0x07, 0x40, 0x47, 0x60, 0x41, + 0x0E, 0x65, 0x45, 0xD3, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD1, 0xFF, 0xFF, 0x03, 0x1B, 0x10, 0xB0, + 0xFF, 0xFF, 0xEB, 0x02, 0x27, 0x44, 0x06, 0xA4, 0x60, 0x41, 0xA1, 0xD1, 0x81, 0xF3, 0x82, 0xF1, + 0xD0, 0x80, 0x59, 0xD3, 0x08, 0x02, 0xD0, 0x80, 0x83, 0xF3, 0x59, 0xD1, 0x04, 0x02, 0xD0, 0x80, + 0xFF, 0xFF, 0x01, 0x02, 0x03, 0x00, 0xD8, 0x60, 0x99, 0x78, 0xFF, 0xFF, 0x1A, 0x60, 0x46, 0x63, + 0xBD, 0xD3, 0x81, 0xFB, 0xBD, 0xD3, 0x82, 0xFB, 0xA3, 0xD3, 0x83, 0xFB, 0x53, 0x64, 0x3B, 0x42, + 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, + 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD8, 0x60, 0x06, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x7E, 0xF1, 0x7F, 0xF9, 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, + 0xD8, 0x60, 0x36, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x63, 0x8C, 0xFD, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, + 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, 0x54, 0x64, 0x3B, 0x42, + 0x5A, 0xDB, 0x31, 0x44, 0xF9, 0xB4, 0x40, 0x51, 0x01, 0x60, 0xBA, 0x61, 0x1F, 0x60, 0x08, 0x63, + 0xA1, 0xD3, 0xFF, 0xFF, 0x20, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, 0x21, 0x7F, 0xBD, 0xDB, + 0x59, 0xD3, 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD8, 0x60, + 0x64, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0x9A, 0x62, 0x1F, 0x60, + 0x06, 0x64, 0xA2, 0xDB, 0x20, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, + 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD8, 0x60, 0x89, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, + 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xD6, 0x60, 0xB7, 0x78, + 0xFF, 0xFF, 0x27, 0x43, 0x2D, 0x60, 0x7A, 0x65, 0xA5, 0xD3, 0x65, 0x41, 0x10, 0xA3, 0x01, 0xA4, + 0xFE, 0xB4, 0xC4, 0x85, 0xFE, 0xA1, 0xBD, 0xD3, 0x59, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, 0xD5, 0x80, + 0x02, 0x02, 0x04, 0x03, 0xF8, 0x01, 0xD7, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0x55, 0x64, 0x3B, 0x42, + 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, + 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD8, 0x60, 0xB1, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0xD1, 0x7F, 0xF9, 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, + 0xD8, 0x60, 0xD6, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x60, 0xBA, 0x61, 0x1F, 0x60, 0x08, 0x63, 0xA1, 0xD3, + 0xFF, 0xFF, 0x20, 0x7F, 0xBD, 0xDB, 0x21, 0x60, 0x32, 0x64, 0xBD, 0xDB, 0x04, 0xA1, 0xA1, 0xD3, + 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, + 0x0B, 0x04, 0x0F, 0x60, 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD8, 0x60, 0xF3, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0x9A, 0x62, 0x1F, 0x60, 0x06, 0x64, + 0xA2, 0xDB, 0x20, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x20, 0x60, + 0x00, 0x64, 0xA2, 0xDB, 0xD9, 0x60, 0x18, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, + 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x1A, 0x60, 0x6A, 0x62, 0x07, 0x60, + 0xD0, 0x64, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD3, 0x81, 0xFB, 0xBD, 0xD3, + 0x82, 0xFB, 0xA3, 0xD3, 0x83, 0xFB, 0x31, 0x44, 0xF9, 0xB4, 0x40, 0x51, 0x0F, 0x60, 0xEA, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xEC, 0x62, 0x01, 0x60, 0x04, 0x64, 0xA2, 0xDB, 0xD9, 0x60, + 0x4D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBC, 0xF1, 0x1A, 0x60, 0x6A, 0x62, + 0xA2, 0xD9, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0xFE, 0x60, 0xFF, 0x61, 0xA1, 0x84, 0x5A, 0xD1, + 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xD7, 0x60, 0xDD, 0x78, 0xFF, 0xFF, + 0x27, 0x42, 0x0C, 0xA2, 0x28, 0x60, 0x02, 0x63, 0xA2, 0xD3, 0xA3, 0xD3, 0x00, 0xBD, 0x01, 0x63, + 0xAC, 0x81, 0x09, 0x03, 0x08, 0x03, 0xB0, 0x60, 0x58, 0x4D, 0xB6, 0x78, 0xFF, 0xFF, 0x00, 0xB8, + 0x01, 0x63, 0x01, 0x03, 0x60, 0x43, 0x1A, 0x60, 0x3E, 0x64, 0xA0, 0xDD, 0x60, 0xF5, 0x00, 0x64, + 0x2B, 0xFA, 0x20, 0x64, 0x2A, 0xFA, 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD1, 0x2C, 0xF8, 0x32, 0xF8, + 0xBD, 0xD1, 0x2D, 0xF8, 0x33, 0xF8, 0xA3, 0xD1, 0x2E, 0xF8, 0x34, 0xF8, 0xEB, 0xF1, 0x2F, 0xF8, + 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0xBC, 0xF1, 0x19, 0xF8, 0xF8, 0x60, 0x80, 0x64, + 0x0E, 0xFA, 0x00, 0xF4, 0x01, 0x63, 0x32, 0x40, 0x08, 0x26, 0x10, 0xBB, 0x28, 0x60, 0x2C, 0x62, + 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0xFE, 0x26, 0x10, 0xBB, 0x09, 0xFC, 0x1A, 0x60, 0x3E, 0x64, + 0xA0, 0xD3, 0x12, 0x61, 0x59, 0xDA, 0x1A, 0x60, 0x46, 0x63, 0xBD, 0xD1, 0x59, 0xD8, 0xBD, 0xD1, + 0x59, 0xD8, 0xA3, 0xD1, 0x59, 0xD8, 0x2E, 0x60, 0xDE, 0x64, 0x40, 0x48, 0xD9, 0x81, 0xFF, 0x60, + 0xF2, 0x64, 0xE8, 0x60, 0x58, 0x4D, 0xE8, 0x78, 0xFF, 0xFF, 0x60, 0xF5, 0x3F, 0xFC, 0xDB, 0x83, + 0x2E, 0x60, 0x08, 0x62, 0xA2, 0xDD, 0x20, 0x7C, 0x5A, 0xD9, 0x63, 0x41, 0x2E, 0x60, 0x0C, 0x63, + 0x12, 0x65, 0x00, 0xF4, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, + 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, + 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x60, 0xF5, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, + 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0x00, 0x66, 0x46, 0x46, 0xC1, 0xFE, 0x14, 0x64, 0x69, 0xFB, 0x56, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x1A, 0x60, 0x44, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x64, 0xA4, 0xA2, 0xDB, 0x1A, 0x60, 0x44, 0x62, + 0xA2, 0xD1, 0x1A, 0x60, 0x6A, 0x62, 0xA2, 0xD9, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, + 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, + 0x1C, 0x64, 0xA2, 0xDB, 0xDA, 0x60, 0x10, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0E, 0x03, + 0xA0, 0x84, 0xA2, 0xDB, 0x57, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, + 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xD7, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x17, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, + 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x58, 0x64, 0x3B, 0x42, + 0x5A, 0xDB, 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDB, 0x60, + 0xCB, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x3A, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x26, 0x46, 0x00, 0xF4, 0x0A, 0xF2, 0xFF, 0xFF, 0x2C, 0x18, 0x59, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x0A, 0xF2, 0x26, 0x46, 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, + 0x41, 0x58, 0x59, 0xDB, 0x31, 0xF2, 0x59, 0xDB, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, + 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x05, 0x65, 0xE9, 0x60, + 0x58, 0x4E, 0x4C, 0x78, 0xFF, 0xFF, 0xDC, 0x60, 0xAA, 0x78, 0xFF, 0xFF, 0xD7, 0x60, 0xDD, 0x78, + 0xFF, 0xFF, 0x5A, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x78, 0x43, 0x02, 0x61, 0x24, 0x60, 0xDD, 0x78, + 0xFF, 0xFF, 0x5B, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x09, 0xF0, 0x2E, 0x60, 0x64, 0x63, 0x30, 0x64, + 0xBD, 0xDB, 0xBD, 0xD9, 0x0A, 0xF0, 0xBD, 0xD9, 0x0B, 0xF0, 0xBD, 0xD9, 0x0C, 0xF2, 0xBD, 0xDB, + 0x60, 0x47, 0xFF, 0xB4, 0x0A, 0xA5, 0x2E, 0x60, 0x62, 0x62, 0x65, 0x5C, 0xA2, 0xD9, 0x60, 0x41, + 0x1A, 0x65, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, 0x7F, 0x26, + 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, 0xF6, 0x1F, + 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0xD3, 0x60, 0x58, 0x4D, 0x06, 0x78, 0xFF, 0xFF, 0x0B, 0xF2, + 0xFF, 0xFF, 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x61, 0x44, + 0x96, 0xFB, 0x27, 0x45, 0x02, 0x62, 0x46, 0xD3, 0x5A, 0xD1, 0x60, 0x47, 0x56, 0xFB, 0x64, 0x47, + 0x55, 0xFB, 0x00, 0x64, 0x5C, 0xFB, 0x0C, 0x62, 0x46, 0xD3, 0x80, 0xFB, 0x0B, 0xF0, 0x0F, 0x60, + 0xFF, 0x64, 0xA0, 0x84, 0x85, 0xFB, 0x1A, 0x60, 0x3E, 0x62, 0xA2, 0xD3, 0x87, 0xFB, 0x26, 0x46, + 0x32, 0xF0, 0x81, 0xF9, 0x33, 0xF0, 0x82, 0xF9, 0x34, 0xF0, 0x83, 0xF9, 0x00, 0xF4, 0x18, 0x65, + 0x0C, 0x61, 0x02, 0x60, 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x64, 0x44, 0x00, 0x7F, 0xCD, 0x81, + 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0xF4, 0x02, 0x02, 0x60, + 0x02, 0x61, 0xA1, 0xD3, 0x00, 0x65, 0x60, 0x43, 0x59, 0xD3, 0xFF, 0xFF, 0x7F, 0xB4, 0x02, 0x3A, + 0x02, 0x00, 0x01, 0x64, 0x15, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x02, 0x64, 0x11, 0x00, 0x0A, 0x3A, + 0x02, 0x00, 0x04, 0x64, 0x0D, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x08, 0x64, 0x09, 0x00, 0x10, 0x3A, + 0x02, 0x00, 0x10, 0x64, 0x05, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x20, 0x64, 0x01, 0x00, 0x00, 0x64, + 0xCF, 0x83, 0xB4, 0x85, 0xE1, 0x02, 0x65, 0x44, 0x7A, 0xFB, 0x02, 0x60, 0x02, 0x61, 0xA1, 0xD3, + 0x00, 0x65, 0x60, 0x43, 0x59, 0xD3, 0xFF, 0xFF, 0x80, 0xB0, 0xFF, 0xFF, 0x01, 0x03, 0x60, 0x45, + 0xCF, 0x83, 0x65, 0x44, 0xF7, 0x02, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, 0x0A, 0x64, 0x15, 0x00, + 0x04, 0x3A, 0x02, 0x00, 0x14, 0x64, 0x11, 0x00, 0x0A, 0x3A, 0x02, 0x00, 0x32, 0x64, 0x0D, 0x00, + 0x0B, 0x3A, 0x02, 0x00, 0x37, 0x64, 0x09, 0x00, 0x10, 0x3A, 0x02, 0x00, 0x50, 0x64, 0x05, 0x00, + 0x16, 0x3A, 0x02, 0x00, 0x6E, 0x64, 0x01, 0x00, 0x14, 0x64, 0x7C, 0xFB, 0xA9, 0xF3, 0xFF, 0xFF, + 0x02, 0xA4, 0xD8, 0xF3, 0x60, 0x45, 0x66, 0x41, 0x65, 0x46, 0x8C, 0xFA, 0x60, 0x40, 0x01, 0x36, + 0x06, 0x00, 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x64, + 0x01, 0x00, 0x01, 0x64, 0x6F, 0xFA, 0x79, 0xF3, 0x7A, 0xF1, 0xFF, 0xFF, 0xA0, 0x84, 0x65, 0x43, + 0x02, 0x02, 0x79, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, 0xAE, 0x65, 0xD8, 0xF3, 0xFF, 0xFF, + 0xE0, 0x84, 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x04, 0x02, 0xE8, 0x84, 0xA4, 0x80, + 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x7B, 0xFB, 0x6F, 0xF0, 0x60, 0x47, 0x90, 0x84, 0x6F, 0xFA, + 0x60, 0x47, 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, + 0x70, 0xF0, 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, 0x02, 0x05, 0xDD, 0x81, 0xFB, 0x01, + 0xE1, 0x81, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x66, 0x43, 0x0C, 0xF4, 0xA9, 0xF3, + 0x1C, 0x60, 0xBA, 0x65, 0x02, 0xA4, 0x60, 0x46, 0x05, 0xF0, 0x60, 0x41, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x00, 0x7C, 0x44, 0xD9, 0x26, 0x46, 0x31, 0xF2, 0x61, 0x5C, 0x60, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD9, 0x26, 0x46, 0x2F, 0xF0, 0x61, 0x46, 0x03, 0xF8, 0x26, 0x46, 0x30, 0xF0, + 0x61, 0x46, 0x04, 0xF8, 0x26, 0x46, 0x31, 0xF0, 0x61, 0x46, 0x05, 0xF8, 0x26, 0x46, 0xCF, 0x60, + 0x58, 0x4E, 0x20, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, + 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x03, 0x65, 0xE9, 0x60, 0x58, 0x4E, + 0x7B, 0x78, 0xFF, 0xFF, 0x01, 0x63, 0x8C, 0xFD, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, + 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, 0x5C, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0xD6, 0x60, 0xB7, 0x78, 0xFF, 0xFF, 0xFF, 0x60, 0xF7, 0x65, 0x20, 0x44, 0x24, 0x80, 0xD0, 0x60, + 0x98, 0x78, 0xFF, 0xFF, 0xDC, 0xF3, 0xFF, 0xFF, 0xFD, 0xA0, 0x2A, 0xF2, 0x03, 0x03, 0xDC, 0x60, + 0x7B, 0x78, 0xFF, 0xFF, 0x60, 0x40, 0xB0, 0x36, 0x11, 0x00, 0xC0, 0x36, 0x02, 0x00, 0x2F, 0x58, + 0xFF, 0xFF, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, + 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xD0, 0x60, 0x98, 0x78, 0xFF, 0xFF, 0x66, 0x45, 0x00, 0xF4, + 0x0A, 0xF2, 0x0B, 0xF2, 0xFE, 0xA0, 0xF3, 0xA0, 0x6F, 0x02, 0x60, 0x41, 0x09, 0xF2, 0x20, 0x03, + 0x00, 0xA0, 0xFF, 0xA0, 0x53, 0x03, 0x65, 0x03, 0x00, 0xA0, 0xFF, 0xFF, 0x4F, 0x03, 0x1F, 0x60, + 0x54, 0x61, 0x01, 0x64, 0xA1, 0xDB, 0x1F, 0x60, 0x56, 0x61, 0x0D, 0x64, 0xA1, 0xDB, 0x1F, 0x60, + 0x58, 0x61, 0x03, 0x64, 0xA1, 0xDB, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, + 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xD0, 0x60, 0x98, 0x78, 0xFF, 0xFF, + 0x28, 0x60, 0x2E, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0xFE, 0xA0, 0x1F, 0x60, 0x54, 0x61, 0x17, 0x02, + 0x01, 0x64, 0xA1, 0xDB, 0x1F, 0x60, 0x56, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x1F, 0x60, 0x58, 0x61, + 0x01, 0x64, 0xA1, 0xDB, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, + 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xD0, 0x60, 0x98, 0x78, 0xFF, 0xFF, 0x02, 0x64, + 0xA1, 0xDB, 0x1F, 0x60, 0x56, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x1F, 0x60, 0x58, 0x61, 0x01, 0x64, + 0xA1, 0xDB, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, + 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xD0, 0x60, 0x98, 0x78, 0xFF, 0xFF, 0x65, 0x46, 0x07, 0xF4, + 0x06, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, 0x06, 0xFA, 0x65, 0x46, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, + 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, + 0xFF, 0xFF, 0xD2, 0x60, 0x41, 0x78, 0xFF, 0xFF, 0x0A, 0xF2, 0x09, 0xF2, 0xFC, 0xA0, 0xFF, 0xA0, + 0x11, 0x02, 0x0A, 0x02, 0x0B, 0xF2, 0x65, 0x46, 0x0A, 0x1B, 0x66, 0x41, 0x07, 0xF4, 0x06, 0xF2, + 0xFF, 0xFF, 0x01, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0xD0, 0x60, 0x98, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0x2F, 0x58, 0xFF, 0xFF, 0x65, 0x46, 0x69, 0xF1, 0x2A, 0xF2, 0x64, 0x41, 0x60, 0x40, 0xA0, 0x3A, + 0x02, 0x00, 0x08, 0xB1, 0x04, 0x00, 0xC0, 0x3A, 0x0C, 0x00, 0x04, 0xB1, 0xFF, 0xFF, 0x20, 0x03, + 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x17, 0x00, 0xB0, 0x3A, 0x02, 0x00, 0x01, 0x65, 0x07, 0x00, 0x10, 0x3A, 0x02, 0x00, 0x02, 0x65, + 0x03, 0x00, 0x30, 0x3A, 0x0D, 0x00, 0x10, 0x65, 0xA5, 0x80, 0xFF, 0xFF, 0x09, 0x03, 0x0F, 0x60, + 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x66, + 0x2F, 0x58, 0xFF, 0xFF, 0x28, 0x60, 0x2E, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xFC, 0xA0, 0xFF, 0xFF, + 0x16, 0x04, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, 0xDC, 0x60, 0xBC, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2D, 0x60, 0x58, 0x65, 0xA5, 0xD1, 0x01, 0x60, + 0x00, 0x64, 0xA0, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0xD0, 0x60, 0x98, 0x78, 0xFF, 0xFF, 0x20, 0x40, + 0x08, 0x2A, 0x03, 0x00, 0xCF, 0x60, 0xF2, 0x78, 0xFF, 0xFF, 0xD7, 0x60, 0xDD, 0x78, 0xFF, 0xFF, + 0x4E, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x2E, 0xF5, 0xFF, 0xFF, 0x27, 0xF2, 0x1C, 0x60, 0xBA, 0x65, + 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, + 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, + 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, + 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA9, 0xF3, + 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x25, 0xF2, 0x26, 0xF0, 0xA7, 0xF2, 0xA8, 0xF0, 0x66, 0xF5, + 0xFF, 0xFF, 0x00, 0xF4, 0xFF, 0xFF, 0x89, 0xF8, 0x66, 0xF5, 0xFF, 0xFF, 0x07, 0xFC, 0x2C, 0xFA, + 0x2D, 0xF8, 0xAE, 0xFA, 0xEB, 0xF3, 0x2F, 0xFA, 0xEC, 0xF3, 0x30, 0xFA, 0xED, 0xF3, 0x31, 0xFA, + 0x81, 0xF3, 0x32, 0xFA, 0x82, 0xF3, 0x33, 0xFA, 0x83, 0xF3, 0x34, 0xFA, 0x31, 0x60, 0x2C, 0x61, + 0xA1, 0xD3, 0xFF, 0xFF, 0x03, 0x1B, 0x00, 0x60, 0xA0, 0x64, 0x02, 0x00, 0x00, 0x60, 0xC0, 0x64, + 0x2A, 0xFA, 0x02, 0x63, 0x3F, 0xFC, 0xAB, 0xFC, 0x00, 0x64, 0x3E, 0xFA, 0xCC, 0xF1, 0x19, 0xF8, + 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xC1, 0xFE, 0x0F, 0x60, 0xEA, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0xD6, 0x60, 0xC2, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x3A, 0x61, 0xAE, 0x60, + 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x62, 0xFB, 0xA9, 0xF3, 0x07, 0xFA, 0x0C, 0x60, + 0x80, 0x64, 0xBC, 0xF1, 0x19, 0xF8, 0x0E, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x00, 0x60, + 0x3A, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x61, 0xFB, 0xA9, 0xF3, + 0x07, 0xFA, 0x0C, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0xBC, 0xF1, 0x19, 0xF8, 0x00, 0x64, 0x3E, 0xFA, + 0x3F, 0xFA, 0x10, 0x60, 0x20, 0x62, 0xDE, 0x60, 0xDC, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xE0, 0x62, + 0x00, 0x60, 0x80, 0x64, 0xA2, 0xDB, 0xDD, 0x60, 0x71, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x20, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x27, 0x60, 0xB6, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, + 0x01, 0xA8, 0x03, 0xA8, 0x04, 0x03, 0x03, 0x03, 0xDE, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0x04, 0x60, + 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x0F, 0x60, 0xDE, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x9B, 0xFE, + 0x03, 0x05, 0x20, 0x40, 0x4B, 0x23, 0x0E, 0x00, 0x0F, 0x60, 0xE0, 0x62, 0x80, 0x60, 0x00, 0x64, + 0xA2, 0xDB, 0xDD, 0x60, 0x83, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x21, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x2F, 0x58, 0xFF, 0xFF, 0x1F, 0x60, 0x86, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, + 0x07, 0x00, 0x90, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x00, 0x64, 0xA1, 0xDB, 0x04, 0x00, + 0x10, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x8C, 0xF3, 0x58, 0xFB, 0x84, 0xF1, 0xBA, 0xFE, + 0x01, 0xA8, 0x59, 0xF9, 0x04, 0x02, 0x02, 0x64, 0x8C, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x64, 0x47, + 0xDC, 0xF3, 0x10, 0xB0, 0x04, 0xA8, 0x33, 0x02, 0x32, 0x02, 0x62, 0xF5, 0xEB, 0xF1, 0x2F, 0xF8, + 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0x81, 0xF1, 0x2C, 0xF8, 0x32, 0xF8, 0x82, 0xF1, + 0x2D, 0xF8, 0x33, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0x34, 0xF8, 0x10, 0x60, 0x48, 0x64, 0x2A, 0xFA, + 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x22, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, + 0xE0, 0x62, 0x00, 0x60, 0x01, 0x64, 0xA2, 0xDB, 0xDD, 0x60, 0xEA, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x23, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x10, 0x67, 0x84, 0xFB, 0x8C, 0xF3, + 0xFF, 0xFF, 0x00, 0xA8, 0xFF, 0xFF, 0x0B, 0x03, 0x0F, 0x60, 0xE0, 0x62, 0x80, 0x60, 0x00, 0x64, + 0xA2, 0xDB, 0xDD, 0x60, 0xEF, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, + 0xDE, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x1B, 0x60, 0xC6, 0x65, 0x1F, 0x60, 0x80, 0x64, 0xA0, 0xD3, + 0x05, 0x7C, 0x08, 0xB0, 0xA5, 0xD3, 0x05, 0x02, 0x00, 0xB8, 0xFF, 0xFF, 0x02, 0x03, 0x15, 0x7C, + 0x0B, 0x00, 0xDC, 0xF3, 0x12, 0x60, 0x26, 0x63, 0x03, 0xA8, 0x7F, 0xF3, 0x05, 0x02, 0xE0, 0x85, + 0x47, 0xD3, 0xFF, 0xFF, 0x07, 0xBC, 0xA2, 0xDB, 0x53, 0xF9, 0x29, 0x60, 0xC6, 0x64, 0x54, 0xFB, + 0x24, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x4E, 0xEC, 0x60, 0x58, 0x4F, 0xB9, 0x78, 0xFF, 0xFF, + 0x0E, 0x4F, 0x0F, 0x60, 0xE0, 0x62, 0x10, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0x60, 0x34, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xFF, 0xFF, + 0x59, 0xF3, 0x84, 0xFB, 0x60, 0x40, 0x10, 0x27, 0xDA, 0xFE, 0xDC, 0xF3, 0x00, 0xA8, 0x04, 0xA8, + 0x27, 0x02, 0x26, 0x02, 0x61, 0xF5, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, + 0x31, 0xF8, 0x81, 0xF1, 0x2C, 0xF8, 0x82, 0xF1, 0x2D, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0xA4, 0x64, + 0x2A, 0xFA, 0x85, 0xF1, 0xC0, 0x67, 0xB0, 0x84, 0x2B, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, + 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xC1, 0xFE, 0x20, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x26, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x9E, 0xF5, 0xFF, 0xFF, 0x07, 0x1B, 0x20, 0x40, 0x80, 0x2B, 0x5C, 0x00, 0x7F, 0x60, 0xFF, 0x65, + 0x20, 0x44, 0x24, 0x80, 0x00, 0x64, 0x41, 0xFB, 0xF1, 0x60, 0x01, 0x64, 0x24, 0xFA, 0xDA, 0x85, + 0x19, 0x60, 0x86, 0x63, 0x89, 0xF1, 0x43, 0x4C, 0xD3, 0x80, 0xBE, 0xD1, 0x14, 0x05, 0x65, 0x40, + 0x80, 0x2A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x64, 0x43, 0x32, 0x61, 0x0F, 0x4E, 0x2F, 0x60, + 0x58, 0x4F, 0x01, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x2C, 0x43, 0x04, 0xA3, 0x41, 0xF3, 0xFF, 0xFF, + 0x32, 0xA4, 0x41, 0xFB, 0xE7, 0x01, 0x20, 0x47, 0x20, 0xB0, 0x20, 0xAF, 0x0F, 0x03, 0x40, 0x40, + 0x0F, 0x60, 0xE0, 0x62, 0x00, 0x60, 0x01, 0x64, 0xA2, 0xDB, 0xDE, 0x60, 0xA3, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x9E, 0xF1, 0x41, 0xF3, + 0xFF, 0xFF, 0x02, 0xA4, 0xE8, 0x84, 0x64, 0x46, 0x23, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, + 0x64, 0x64, 0xA2, 0xDB, 0x5A, 0xD9, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x64, + 0x9E, 0xFB, 0xFA, 0xFE, 0xEB, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, + 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x58, 0xF3, 0x8C, 0xFB, + 0xFF, 0xFF, 0xC1, 0xFE, 0x0F, 0x60, 0xDE, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xE0, 0x62, + 0x00, 0x60, 0x80, 0x64, 0xA2, 0xDB, 0xDD, 0x60, 0x71, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2E, 0x64, + 0x3B, 0x42, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x9E, 0xF1, + 0x00, 0x64, 0xB0, 0x86, 0x9E, 0xFB, 0x07, 0x03, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, + 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0xEB, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, + 0xDE, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xE0, 0x62, 0x00, 0x60, 0x80, 0x64, 0xA2, 0xDB, + 0xDD, 0x60, 0x71, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x97, 0xF3, 0x26, 0x46, + 0x60, 0x43, 0x01, 0x2A, 0x22, 0x00, 0x0F, 0xF2, 0x2A, 0xF0, 0x60, 0x40, 0x10, 0x2A, 0x10, 0x00, + 0x64, 0x40, 0x04, 0x27, 0x1A, 0x00, 0xFD, 0xB3, 0x64, 0x40, 0x20, 0x27, 0x02, 0xBB, 0x0F, 0x60, + 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0C, 0x00, + 0xFB, 0xB3, 0x64, 0x40, 0x20, 0x27, 0x04, 0xBB, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, + 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x97, 0xFD, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, + 0xDC, 0xF3, 0x3F, 0xF2, 0x04, 0xA8, 0x57, 0xFB, 0x02, 0x03, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0xF4, + 0x1E, 0x63, 0x08, 0x64, 0x40, 0x48, 0xBD, 0xD2, 0xFF, 0xFF, 0x60, 0x47, 0x05, 0x36, 0x0B, 0x00, + 0xFF, 0xB5, 0xC7, 0x83, 0x01, 0x2A, 0xF7, 0x01, 0x4F, 0xD2, 0x5B, 0xD2, 0x60, 0x40, 0x05, 0x37, + 0x08, 0x00, 0xDF, 0x83, 0xF5, 0x01, 0xFF, 0xB5, 0x65, 0x41, 0x47, 0x8A, 0x5B, 0xD2, 0xDF, 0x83, + 0x07, 0x00, 0x00, 0x7F, 0xDC, 0x85, 0x47, 0x8A, 0x60, 0x41, 0x5B, 0xD2, 0xDB, 0x83, 0x60, 0x47, + 0x01, 0xB0, 0xFE, 0xB5, 0x02, 0x03, 0x02, 0x64, 0x40, 0x48, 0x85, 0xF1, 0x65, 0x44, 0xE0, 0x84, + 0xE0, 0x84, 0xE0, 0x84, 0xFD, 0xA1, 0xE1, 0x81, 0xE1, 0x81, 0xE1, 0x85, 0xC4, 0x81, 0xD0, 0x84, + 0xD1, 0x80, 0x2A, 0x07, 0x29, 0x06, 0x9C, 0x84, 0xDC, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x85, + 0x96, 0xF3, 0xC7, 0x83, 0x01, 0x26, 0x60, 0x47, 0xAB, 0x83, 0xFC, 0xA3, 0x02, 0x00, 0x03, 0x04, + 0x00, 0xF4, 0x84, 0xA3, 0xFC, 0x01, 0x80, 0x65, 0x47, 0xD0, 0x28, 0x41, 0xA0, 0x80, 0xFE, 0xA1, + 0x16, 0x03, 0x09, 0x02, 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x1E, 0x00, 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x15, 0x00, 0x28, 0x41, 0xFE, 0xA1, 0xFF, 0xFF, 0x09, 0x03, + 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x08, 0x00, 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x20, 0x40, 0x20, 0x2A, 0x58, 0x00, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, + 0xF4, 0xA3, 0x00, 0x60, 0x1D, 0x61, 0x00, 0x60, 0x80, 0x65, 0x60, 0xFE, 0x81, 0xA1, 0x7F, 0xA1, + 0x02, 0x06, 0x00, 0xF4, 0x03, 0x61, 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, 0xD4, 0x80, 0x2D, 0x03, + 0x17, 0x03, 0xCF, 0x83, 0x61, 0x44, 0x80, 0xA0, 0x28, 0x03, 0x02, 0x02, 0x00, 0xF4, 0x03, 0x61, + 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, 0x81, 0xA1, 0x20, 0x03, 0x05, 0x07, 0x7F, 0xA1, 0xCC, 0x84, + 0xDD, 0x81, 0xE4, 0x03, 0xF7, 0x01, 0x00, 0xF4, 0x00, 0xB8, 0x04, 0x61, 0xE4, 0x03, 0xF2, 0x01, + 0x01, 0x60, 0xFF, 0x63, 0x46, 0x48, 0x41, 0x4A, 0xDD, 0x81, 0xA1, 0xD0, 0xDF, 0x83, 0xA3, 0xD9, + 0x64, 0x44, 0xDD, 0x81, 0xA1, 0xD0, 0xDF, 0x83, 0xA3, 0xD9, 0xCC, 0x84, 0x81, 0xA1, 0x05, 0x03, + 0x7F, 0xA1, 0xF7, 0x04, 0x00, 0xF4, 0x03, 0x61, 0xF4, 0x01, 0x20, 0xFE, 0x00, 0xBB, 0x02, 0x60, + 0x00, 0x63, 0x08, 0x24, 0x11, 0x00, 0xBD, 0xD3, 0x06, 0x65, 0xD4, 0x80, 0xBD, 0xD3, 0x0C, 0x02, + 0x60, 0x40, 0x60, 0x3A, 0x09, 0x00, 0x1D, 0x3B, 0x07, 0x00, 0xBD, 0xD3, 0xFF, 0xFF, 0xFF, 0xB5, + 0x00, 0x7E, 0x5C, 0xFB, 0x65, 0x44, 0x5B, 0xFB, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, + 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x02, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x63, 0x97, 0xFD, 0x1A, 0x60, 0x72, 0x63, 0x00, 0x64, + 0xA3, 0xDB, 0x06, 0xA3, 0x10, 0x60, 0x50, 0x64, 0xBD, 0xDB, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, + 0x10, 0x60, 0x4E, 0x62, 0xE0, 0x60, 0x07, 0x64, 0xA2, 0xDB, 0xD2, 0xF1, 0x1A, 0x60, 0x76, 0x62, + 0xA2, 0xD9, 0x1A, 0x60, 0x7E, 0x63, 0x00, 0x64, 0xA3, 0xDB, 0x06, 0xA3, 0x10, 0x60, 0x54, 0x64, + 0xBD, 0xDB, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, 0x10, 0x60, 0x52, 0x62, 0xE0, 0x60, 0x11, 0x64, + 0xA2, 0xDB, 0x28, 0x60, 0x04, 0x62, 0xA2, 0xD1, 0x1A, 0x60, 0x82, 0x62, 0xA2, 0xD9, 0x00, 0x60, + 0x3A, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x64, 0xFB, 0xA9, 0xF3, + 0x07, 0xFA, 0xBC, 0xF3, 0x19, 0xFA, 0xF8, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0x00, 0x64, 0x3E, 0xFA, + 0x3F, 0xFA, 0x00, 0x60, 0x3A, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, + 0x65, 0xFB, 0xA9, 0xF3, 0x07, 0xFA, 0xBC, 0xF3, 0x19, 0xFA, 0x24, 0x60, 0x80, 0x64, 0x0E, 0xFA, + 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x10, 0x60, 0x14, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, + 0x10, 0x60, 0x28, 0x62, 0xE0, 0x60, 0x77, 0x64, 0xA2, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x63, + 0x97, 0xFD, 0xBA, 0xFE, 0xFE, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x84, 0xFD, 0x0F, 0x60, + 0xEA, 0x62, 0xA2, 0xD1, 0x04, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, + 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x28, 0x60, 0x04, 0x62, + 0xA2, 0xD1, 0x1A, 0x60, 0x82, 0x62, 0xA2, 0xD9, 0x27, 0x60, 0xFE, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, + 0x0A, 0x1B, 0x00, 0x64, 0x84, 0xFB, 0xBA, 0xFE, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0xBA, 0xFE, 0x97, 0xF3, 0x00, 0x63, 0x84, 0xFD, 0x10, 0xBC, + 0x97, 0xFB, 0xFE, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, + 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x60, 0x64, 0x63, 0x1A, 0x60, + 0x42, 0x64, 0xA0, 0xDD, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xF8, 0x62, + 0x01, 0x60, 0x04, 0x64, 0xA2, 0xDB, 0xE0, 0x60, 0xC9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xA3, 0x01, 0x31, 0x40, 0x04, 0x2A, 0xE3, 0x01, 0x20, 0x40, + 0x52, 0x23, 0x12, 0x00, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x14, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xF8, 0x62, 0x81, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xE0, 0x60, + 0xC9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0xDB, 0x01, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x01, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x65, 0xF5, 0xBC, 0xF1, 0x19, 0xF8, 0x81, 0xF1, + 0x2C, 0xF8, 0x32, 0xF8, 0x82, 0xF1, 0x2D, 0xF8, 0x33, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0x34, 0xF8, + 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0x11, 0x60, 0x48, 0x64, + 0x2A, 0xFA, 0x00, 0x64, 0x2B, 0xFA, 0x23, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, + 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, + 0x0F, 0x60, 0xF8, 0x62, 0x00, 0x60, 0x01, 0x64, 0xA2, 0xDB, 0xE1, 0x60, 0x23, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x65, 0xF5, 0x23, 0xF2, 0xFF, 0xFF, 0x01, 0x18, 0x7B, 0x01, + 0x10, 0x67, 0x84, 0xFB, 0x03, 0x64, 0x98, 0xFB, 0xFE, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, + 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xF8, 0x62, 0x81, 0x60, 0x00, 0x64, + 0xA2, 0xDB, 0xE1, 0x60, 0x46, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x0D, 0x00, 0x0F, 0x60, 0xF6, 0x62, + 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, + 0xE0, 0x60, 0x77, 0x78, 0xFF, 0xFF, 0x46, 0x60, 0x00, 0x65, 0x20, 0x41, 0x8E, 0xF3, 0xA5, 0x80, + 0x01, 0xB0, 0x01, 0x02, 0x06, 0x00, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x2F, 0x58, + 0xFF, 0xFF, 0x1A, 0x60, 0x42, 0x65, 0xA5, 0xD3, 0x01, 0x63, 0x8C, 0xFD, 0x27, 0x1B, 0x00, 0x60, + 0x64, 0x64, 0xA5, 0xDB, 0x65, 0xF5, 0xBC, 0xF1, 0x19, 0xF8, 0x81, 0xF1, 0x2C, 0xF8, 0x32, 0xF8, + 0x82, 0xF1, 0x2D, 0xF8, 0x33, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0x34, 0xF8, 0xEB, 0xF1, 0x2F, 0xF8, + 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0x11, 0x60, 0x48, 0x64, 0x2A, 0xFA, 0x00, 0x64, + 0x2B, 0xFA, 0x23, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x06, 0x00, 0x97, 0xF3, 0x32, 0x40, + 0x02, 0x26, 0x02, 0x00, 0x40, 0x2A, 0xDA, 0xFE, 0xC1, 0xFE, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x0F, 0x60, 0xF8, 0x62, 0x01, 0x60, 0x82, 0x64, 0xA2, 0xDB, 0xE1, 0x60, 0xA4, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x01, 0x60, + 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xE0, 0x60, 0x77, 0x78, + 0xFF, 0xFF, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x06, 0x03, 0xA0, 0x84, 0xA2, 0xDB, + 0xBA, 0xFE, 0xE3, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x8C, 0xFB, 0x01, 0x60, 0x00, 0x65, + 0x20, 0x44, 0x34, 0x80, 0xBA, 0xFE, 0xC1, 0xFE, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x10, 0x60, 0x14, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xF8, 0x62, 0x01, 0x60, 0x46, 0x64, + 0xA2, 0xDB, 0xE1, 0x60, 0xD7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, + 0xF6, 0x62, 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0xE0, 0x60, 0x77, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x3C, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x34, 0x01, 0x00, 0x60, 0x02, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x0C, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x28, 0x60, 0x00, 0x62, 0xA2, 0xD1, + 0x97, 0xF3, 0x00, 0x61, 0xD1, 0x80, 0xF7, 0xB4, 0xF0, 0x03, 0x97, 0xFB, 0x35, 0x00, 0x00, 0x60, + 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0F, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x28, 0x60, 0x00, 0x62, + 0xA2, 0xD1, 0x97, 0xF3, 0x00, 0x61, 0xD1, 0x80, 0x08, 0xBC, 0x03, 0x02, 0xE2, 0x60, 0xE8, 0x78, + 0xFF, 0xFF, 0x97, 0xFB, 0x21, 0x00, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, + 0xA0, 0x84, 0xA2, 0xDB, 0xE2, 0x60, 0xE8, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, + 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xC5, 0x01, + 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xE3, 0x60, + 0xC8, 0x78, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x02, 0x63, 0x97, 0xF3, 0x8C, 0xFD, 0x01, 0xBC, + 0xC1, 0xFE, 0x97, 0xFB, 0xD2, 0xF1, 0x1A, 0x60, 0x76, 0x62, 0xA2, 0xD9, 0x0F, 0x60, 0xF6, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x14, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xF8, 0x62, + 0x01, 0x60, 0x34, 0x64, 0xA2, 0xDB, 0xE2, 0x60, 0x62, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x24, 0x60, + 0xAA, 0x62, 0x1A, 0x60, 0x72, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, + 0x9C, 0x84, 0x0E, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x72, 0x64, + 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xE0, 0x60, 0x77, 0x78, 0xFF, 0xFF, + 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x17, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x97, 0xF3, + 0xFF, 0xFF, 0x60, 0x40, 0x04, 0x2A, 0x01, 0x00, 0xD2, 0x01, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, + 0x72, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x97, 0xF3, 0xFF, 0xFF, + 0x60, 0x40, 0x08, 0x2A, 0x4D, 0x00, 0x54, 0x00, 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, + 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x08, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x97, 0xF3, 0xFF, 0xFF, + 0x08, 0xBC, 0x97, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xAB, 0x01, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x0C, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x72, 0x64, 0xA2, 0xDB, + 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x2B, 0x00, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, + 0x9C, 0x84, 0x0C, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x72, 0x64, + 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x13, 0x00, 0x0F, 0x60, 0xF6, 0x62, + 0xA2, 0xD1, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x08, 0x03, 0xA0, 0x84, 0xA2, 0xDB, + 0x97, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x2A, 0x04, 0x00, 0x0A, 0x00, 0x2F, 0x58, 0xFF, 0xFF, + 0x00, 0x00, 0x97, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0x97, 0xFB, 0xE1, 0x60, 0x2A, 0x78, 0xFF, 0xFF, + 0x27, 0x60, 0xFE, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, 0x03, 0x02, 0xE3, 0x60, + 0xD1, 0x78, 0xFF, 0xFF, 0x97, 0xF3, 0x01, 0x63, 0x8C, 0xFD, 0x21, 0xBC, 0x97, 0xFB, 0x64, 0xF5, + 0x81, 0xF1, 0x2C, 0xF8, 0x82, 0xF1, 0x2D, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0x85, 0xF1, 0xC0, 0x67, + 0xB0, 0x84, 0x2B, 0xFA, 0xBC, 0xF1, 0x19, 0xF8, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, + 0xED, 0xF1, 0x31, 0xF8, 0x10, 0x60, 0xA4, 0x64, 0x2A, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, + 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xC1, 0xFE, 0x1A, 0x60, 0x76, 0x62, 0x00, 0x60, 0x50, 0x64, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, + 0x1A, 0x60, 0x72, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, + 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x14, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, + 0xF8, 0x62, 0x01, 0x60, 0x2C, 0x64, 0xA2, 0xDB, 0xE3, 0x60, 0x3A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, + 0x9C, 0x84, 0x0E, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x72, 0x64, + 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xE0, 0x60, 0x77, 0x78, 0xFF, 0xFF, + 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, + 0xA0, 0x84, 0xA2, 0xDB, 0x8D, 0x01, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x08, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x97, 0xF3, 0xFF, 0xFF, 0x02, 0xB0, + 0xFF, 0xFF, 0x4E, 0x03, 0x7D, 0x01, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, + 0xA0, 0x84, 0xA2, 0xDB, 0x45, 0x00, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x16, 0x03, + 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x72, 0x64, 0xA2, 0xDB, 0x03, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x28, 0x60, 0x00, 0x62, 0xA2, 0xD3, 0x97, 0xF3, 0x00, 0xA8, + 0xF7, 0xB4, 0x2E, 0x03, 0x97, 0xFB, 0xE2, 0x60, 0x3C, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x17, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, + 0x72, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x28, 0x60, 0x00, 0x62, + 0xA2, 0xD3, 0x97, 0xF3, 0x00, 0xA8, 0x08, 0xBC, 0x01, 0x02, 0x42, 0x01, 0x97, 0xFB, 0xE2, 0x60, + 0x3C, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, + 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x02, 0x00, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x00, + 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x72, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0x97, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0x97, 0xFB, 0xE1, 0x60, 0x2A, 0x78, 0xFF, 0xFF, + 0x97, 0xF3, 0x01, 0x63, 0x8C, 0xFD, 0x01, 0xBC, 0x97, 0xFB, 0x00, 0x64, 0x84, 0xFB, 0xC1, 0xFE, + 0x29, 0x00, 0x97, 0xF3, 0x01, 0x63, 0x8C, 0xFD, 0x01, 0xBC, 0x97, 0xFB, 0x00, 0x64, 0x84, 0xFB, + 0x64, 0xF5, 0x81, 0xF1, 0x2C, 0xF8, 0x82, 0xF1, 0x2D, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0x85, 0xF1, + 0xC0, 0x67, 0xB0, 0x84, 0x2B, 0xFA, 0xBC, 0xF1, 0x19, 0xF8, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, + 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0x00, 0x60, 0xA4, 0x64, 0x2A, 0xFA, 0x24, 0x60, 0x74, 0x62, + 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xC1, 0xFE, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x7E, 0x64, 0xA2, 0xDB, 0x02, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, + 0x14, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xF8, 0x62, 0x03, 0x60, 0x0E, 0x64, 0xA2, 0xDB, + 0xE4, 0x60, 0x16, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, + 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0E, 0x03, 0xA0, 0x84, 0xA2, 0xDB, + 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x7E, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0xE0, 0x60, 0x77, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x0A, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xC6, 0x01, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x15, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x8B, 0x01, 0x00, 0x60, 0x12, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xAC, 0x01, 0x0F, 0x60, 0xF6, 0x62, + 0xA2, 0xD1, 0x02, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xAD, 0x03, 0xA0, 0x84, 0xA2, 0xDB, + 0x10, 0x67, 0x84, 0xFB, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x14, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x65, 0xF5, 0xBC, 0xF1, 0x19, 0xF8, 0x81, 0xF1, 0x2C, 0xF8, 0x32, 0xF8, + 0x82, 0xF1, 0x2D, 0xF8, 0x33, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0x34, 0xF8, 0xEB, 0xF1, 0x2F, 0xF8, + 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0x11, 0x60, 0x48, 0x64, 0x2A, 0xFA, 0x00, 0x64, + 0x2B, 0xFA, 0x23, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x97, 0xF3, 0xC1, 0xFE, 0xFE, 0xB4, + 0x97, 0xFB, 0x0F, 0x60, 0xF8, 0x62, 0x00, 0x60, 0x03, 0x64, 0xA2, 0xDB, 0xE4, 0x60, 0x94, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, + 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x29, 0x01, 0x65, 0xF5, + 0x23, 0xF2, 0x98, 0xF3, 0x04, 0x18, 0xCC, 0x84, 0x98, 0xFB, 0x01, 0x03, 0x21, 0x01, 0xE1, 0x60, + 0x2A, 0x78, 0xFF, 0xFF, 0x27, 0x60, 0xFE, 0x62, 0xA2, 0xD3, 0x84, 0xF1, 0x02, 0xA8, 0x2A, 0xF2, + 0x03, 0x02, 0xB0, 0x84, 0x2A, 0xFA, 0x08, 0x00, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, + 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x22, 0x64, + 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, + 0x24, 0x60, 0x34, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0xDB, 0x02, 0xBF, 0x60, + 0xE7, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xFC, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1A, 0x60, 0xAE, 0x63, 0x00, 0x64, 0xA3, 0xDB, + 0x06, 0xA3, 0x10, 0x60, 0x5C, 0x64, 0xBD, 0xDB, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, 0x10, 0x60, + 0x5A, 0x62, 0xE4, 0x60, 0xD2, 0x64, 0xA2, 0xDB, 0x1F, 0x60, 0x5C, 0x62, 0xA2, 0xD1, 0x1A, 0x60, + 0xB2, 0x62, 0xA2, 0xD9, 0x10, 0x60, 0x2A, 0x62, 0xE4, 0x60, 0xF9, 0x64, 0xA2, 0xDB, 0x2F, 0x58, + 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x1F, 0x60, 0x80, 0x65, 0xA5, 0xD3, 0xFF, 0xFF, 0x02, 0xBC, + 0xF3, 0xB4, 0x01, 0xB0, 0xA5, 0xDB, 0x0C, 0x02, 0x12, 0x60, 0x26, 0x61, 0x00, 0x64, 0x1A, 0x63, + 0x59, 0xDB, 0xFE, 0x1F, 0x1F, 0x60, 0x5C, 0x61, 0x0A, 0x64, 0x1A, 0x63, 0x59, 0xDB, 0xFE, 0x1F, + 0x7F, 0xF3, 0x7E, 0xFB, 0x01, 0x64, 0x7F, 0xFB, 0x01, 0x61, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, + 0xE1, 0x81, 0xFB, 0x01, 0xBA, 0xF3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x69, 0x03, 0x0F, 0x60, + 0xFC, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xFE, 0x62, 0x40, 0x60, + 0x00, 0x64, 0xA2, 0xDB, 0xE5, 0x60, 0x1F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x7F, 0xF1, 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, + 0x0F, 0x60, 0xFE, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xE5, 0x60, 0x43, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, + 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xFC, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x0F, 0x60, 0xFE, 0x62, 0x00, 0x60, 0x1A, 0x64, 0xA2, 0xDB, 0xE5, 0x60, 0x64, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0xAE, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xFC, 0x62, 0xA2, 0xD1, 0x00, 0x60, + 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0C, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, + 0x1A, 0x60, 0xAE, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x26, 0x00, + 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0B, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, + 0xAA, 0x62, 0x1A, 0x60, 0xAE, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0x12, 0x60, 0x26, 0x65, 0x7F, 0xF3, 0xFF, 0xFF, 0x04, 0xA4, 0xF2, 0xA0, 0xFF, 0xFF, 0x01, 0x06, + 0xF1, 0xA4, 0x01, 0x36, 0x0B, 0x00, 0x00, 0x36, 0x04, 0xA4, 0x60, 0x41, 0xE0, 0x84, 0xC4, 0x84, + 0xA0, 0xD3, 0xFF, 0xFF, 0x00, 0xB8, 0x61, 0x44, 0xEF, 0x02, 0x75, 0x01, 0x1F, 0x60, 0x80, 0x65, + 0xA5, 0xD3, 0x7E, 0xF1, 0xFC, 0xB4, 0xA5, 0xDB, 0x7F, 0xF9, 0x0F, 0x60, 0xFC, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xFE, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, + 0xE5, 0x60, 0xA5, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7F, 0xF1, 0x24, 0x60, + 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xFE, 0x62, + 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xE5, 0x60, 0xC9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xFC, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x0F, 0x60, + 0xD0, 0x62, 0xA2, 0xD1, 0x10, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0xE6, 0x60, 0xE9, 0x78, 0xFF, 0xFF, 0xE6, 0x60, 0xED, 0x78, 0xFF, 0xFF, 0x1F, 0x60, + 0x80, 0x63, 0xA3, 0xD3, 0x26, 0x46, 0x02, 0xB0, 0x3F, 0xF2, 0xF6, 0x03, 0x02, 0x60, 0x00, 0x63, + 0x01, 0x60, 0x00, 0x65, 0xD4, 0x80, 0x00, 0xF4, 0x02, 0x24, 0x65, 0x44, 0x12, 0x65, 0x60, 0x41, + 0xA5, 0xD0, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x64, 0x44, 0x00, 0x7F, + 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0xF0, 0x02, + 0x02, 0x60, 0x14, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x01, 0xB4, 0xFF, 0xFF, 0x37, 0x02, 0x29, 0x60, + 0xA4, 0x64, 0xA0, 0xD1, 0x1F, 0x60, 0x0E, 0x63, 0x31, 0x18, 0x64, 0x41, 0x44, 0x4B, 0x29, 0x60, + 0xA6, 0x65, 0xA5, 0xD1, 0xDA, 0x85, 0x64, 0x44, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, + 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0xF4, 0x02, 0x02, 0x60, 0x1A, 0x61, 0xA1, 0xD3, + 0x2B, 0x45, 0x60, 0x40, 0x00, 0x36, 0x1A, 0x00, 0x01, 0x36, 0x18, 0x00, 0xD4, 0x80, 0x65, 0x43, + 0xB0, 0x02, 0x1F, 0x60, 0x0C, 0x64, 0xE3, 0x83, 0xFE, 0xA3, 0x59, 0xD1, 0x58, 0xD3, 0x40, 0x4B, + 0xD0, 0x80, 0x2B, 0x44, 0x02, 0x02, 0xF9, 0x1F, 0x09, 0x00, 0x02, 0x60, 0x1A, 0x61, 0x65, 0x43, + 0xE3, 0x83, 0xFE, 0xA3, 0x59, 0xD3, 0xFF, 0xFF, 0x9C, 0x1B, 0xFC, 0x1F, 0x26, 0x46, 0x3F, 0xF0, + 0x01, 0x60, 0x00, 0x64, 0xD0, 0x80, 0x64, 0x41, 0x01, 0x05, 0x60, 0x41, 0xF4, 0xA1, 0x02, 0x60, + 0x18, 0x63, 0xBD, 0xD3, 0xBD, 0xD1, 0xFD, 0xA0, 0xF9, 0xA0, 0x08, 0x03, 0x35, 0x03, 0xFE, 0xA1, + 0x64, 0x42, 0xE2, 0x85, 0xD1, 0x81, 0xC7, 0x83, 0x84, 0x06, 0xF3, 0x01, 0x12, 0x60, 0x26, 0x65, + 0xBD, 0xD3, 0xFD, 0xA1, 0xE0, 0x84, 0xC4, 0x85, 0x05, 0x64, 0xA5, 0xDB, 0x1F, 0x60, 0x80, 0x65, + 0xA5, 0xD3, 0x41, 0x48, 0x04, 0xBC, 0xA5, 0xDB, 0x12, 0x60, 0x28, 0x65, 0x12, 0x60, 0x44, 0x61, + 0x49, 0xD3, 0xD6, 0x80, 0x00, 0xB8, 0x0E, 0x03, 0xFB, 0x03, 0x62, 0x45, 0x12, 0x60, 0x26, 0x61, + 0x59, 0xD3, 0xD6, 0x80, 0x00, 0xB8, 0x06, 0x03, 0xFB, 0x03, 0x05, 0x64, 0xA2, 0xDB, 0xD6, 0x80, + 0x02, 0xA2, 0xFC, 0x02, 0x0F, 0x60, 0xFC, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x28, 0x41, 0xC5, 0x01, 0x63, 0x45, 0x04, 0x60, 0x00, 0x63, 0xD7, 0x83, + 0xEB, 0x83, 0xD3, 0x80, 0x65, 0x43, 0x01, 0x05, 0x54, 0x00, 0xFE, 0xA3, 0x43, 0x4B, 0xA3, 0xD3, + 0x63, 0x41, 0x60, 0x43, 0x1B, 0x60, 0xC6, 0x64, 0xA0, 0xDD, 0xE3, 0x83, 0xFE, 0xA3, 0x59, 0xD1, + 0x58, 0xD9, 0xFD, 0x1F, 0x00, 0x63, 0x58, 0xDD, 0x2B, 0x43, 0xBD, 0xD1, 0x1F, 0x60, 0x78, 0x64, + 0x64, 0x41, 0xBD, 0xD1, 0x58, 0xD9, 0xBD, 0xD1, 0xFC, 0xA1, 0x41, 0x4B, 0x58, 0xD9, 0xBD, 0xD1, + 0xA0, 0xD9, 0x12, 0x60, 0x26, 0x61, 0x12, 0x60, 0x42, 0x65, 0x00, 0x64, 0xD5, 0x80, 0x59, 0xDB, + 0xFD, 0x02, 0x12, 0x60, 0x24, 0x65, 0xBD, 0xD3, 0xA3, 0xD1, 0xE0, 0x84, 0xC4, 0x82, 0x12, 0x60, + 0x44, 0x65, 0x05, 0x64, 0x64, 0x41, 0x5A, 0xDB, 0xD6, 0x80, 0xCD, 0x81, 0x22, 0x03, 0xFB, 0x02, + 0x1F, 0x60, 0x5A, 0x61, 0x4B, 0xD1, 0x04, 0xA3, 0xBD, 0xD3, 0xFF, 0xFF, 0xF6, 0xA0, 0xC1, 0x82, + 0x05, 0x05, 0x64, 0x41, 0x5A, 0xDB, 0xCD, 0x81, 0xFF, 0xFF, 0xFC, 0x02, 0x2B, 0x41, 0xFD, 0xA1, + 0x41, 0x4B, 0xDF, 0x07, 0x0F, 0x60, 0xFC, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x1F, 0x60, 0x80, 0x65, 0xA5, 0xD3, 0xFF, 0xFF, 0x08, 0xBC, 0xA5, 0xDB, + 0xFF, 0xFF, 0x20, 0xFE, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x20, 0xFE, 0x9A, 0xFF, 0x5C, 0x61, + 0x3F, 0xF2, 0xFF, 0xFF, 0x83, 0xA0, 0xFF, 0xFF, 0x04, 0x28, 0x39, 0x00, 0xF4, 0xA4, 0x60, 0x43, + 0x00, 0xF4, 0x1E, 0x62, 0x60, 0xFE, 0xA2, 0xD2, 0xFF, 0xFF, 0x60, 0x40, 0x85, 0x36, 0x10, 0x00, + 0xDE, 0x82, 0xA2, 0xD2, 0xFF, 0xFF, 0x20, 0xFE, 0xFF, 0xB4, 0x02, 0xA4, 0x53, 0x93, 0x51, 0x91, + 0x05, 0x0E, 0xFF, 0xA4, 0x42, 0x92, 0x63, 0x40, 0x61, 0x40, 0xEC, 0x1C, 0x98, 0xFF, 0xD9, 0x01, + 0x20, 0xFE, 0x05, 0x64, 0x00, 0x7C, 0x42, 0x92, 0x60, 0xFE, 0xDE, 0x82, 0xA2, 0xD2, 0xDE, 0x82, + 0xA2, 0xD0, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0x60, 0x43, 0x60, 0xFE, 0xDE, 0x82, 0xA2, 0xD2, + 0xDE, 0x82, 0xA2, 0xD0, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0x98, 0xFF, 0x01, 0xA3, 0x01, 0xA4, + 0x2D, 0x60, 0x5A, 0x62, 0xA2, 0xDD, 0x2D, 0x60, 0x5E, 0x62, 0xA2, 0xDB, 0xBA, 0x01, 0x98, 0xFF, + 0xB8, 0x01, 0x00, 0x60, 0xA0, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, + 0x5D, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x80, 0x64, 0x2A, 0xFA, 0xCC, 0xF1, 0x19, 0xF8, 0x00, 0x64, + 0x3E, 0xFA, 0x00, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0xA9, 0xF1, 0x07, 0xF8, 0x67, 0x44, 0x2C, 0xFA, + 0x2D, 0xFA, 0x2E, 0xFA, 0x10, 0x60, 0x1C, 0x62, 0xE8, 0x60, 0xDF, 0x64, 0xA2, 0xDB, 0x2F, 0x58, + 0xFF, 0xFF, 0x5D, 0xF5, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, + 0x81, 0xF1, 0x32, 0xF8, 0x82, 0xF1, 0x33, 0xF8, 0x83, 0xF1, 0x34, 0xF8, 0x28, 0x60, 0x2C, 0x62, + 0xA2, 0xD1, 0x02, 0x64, 0x64, 0x40, 0xFE, 0x26, 0x10, 0xBC, 0x32, 0x40, 0x08, 0x26, 0x10, 0xBC, + 0x2F, 0x60, 0x44, 0x62, 0xA2, 0xDB, 0x28, 0x60, 0x2A, 0x62, 0xA2, 0xD1, 0x2D, 0x60, 0x7A, 0x64, + 0x02, 0x18, 0x27, 0x60, 0xDA, 0x64, 0x2E, 0x60, 0xAE, 0x62, 0xA2, 0xDB, 0x2E, 0x60, 0xCA, 0x62, + 0xA2, 0xDB, 0x2D, 0x60, 0xA6, 0x61, 0x28, 0x60, 0xCC, 0x62, 0xA2, 0xD3, 0x2E, 0x60, 0x96, 0x65, + 0xFE, 0xA4, 0xE0, 0x84, 0x02, 0x05, 0x67, 0x44, 0x99, 0x00, 0xE0, 0x84, 0xC4, 0x85, 0x2D, 0x60, + 0xCC, 0x62, 0xA2, 0xD3, 0xA5, 0xD1, 0xDA, 0x85, 0x2D, 0x60, 0xC4, 0x62, 0xA0, 0x83, 0xA2, 0xDD, + 0xA5, 0xD1, 0x2D, 0x60, 0xC2, 0x62, 0xA0, 0x83, 0xA2, 0xDD, 0x2D, 0x60, 0xA0, 0x61, 0xDD, 0x60, + 0x06, 0x64, 0xA1, 0xDB, 0x06, 0xA1, 0x2D, 0x60, 0xCA, 0x62, 0xA2, 0xD3, 0x2D, 0x60, 0xC2, 0x62, + 0x60, 0x40, 0xFD, 0xA0, 0xA2, 0xD3, 0x74, 0x03, 0x50, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x02, 0x2A, + 0x03, 0x00, 0x01, 0x60, 0xF2, 0x63, 0x0E, 0x00, 0x04, 0x2A, 0x03, 0x00, 0x02, 0x60, 0xF2, 0x63, + 0x09, 0x00, 0x10, 0x2A, 0x03, 0x00, 0x04, 0x60, 0xF2, 0x63, 0x04, 0x00, 0x20, 0x2A, 0x04, 0x00, + 0x05, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x2D, 0x60, 0xCA, 0x62, 0xA2, 0xD3, 0x2D, 0x60, + 0xC4, 0x62, 0xFE, 0xA0, 0xA2, 0xD3, 0x54, 0x03, 0x00, 0x60, 0x00, 0x63, 0x59, 0xDD, 0x61, 0x45, + 0x60, 0x40, 0x01, 0x2A, 0x04, 0x00, 0x00, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, + 0x02, 0x2A, 0x04, 0x00, 0x01, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x04, 0x2A, + 0x04, 0x00, 0x02, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x10, 0x2A, 0x04, 0x00, + 0x04, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, + 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0xD5, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xA5, 0xDD, 0x2D, 0x60, + 0xCA, 0x62, 0xA2, 0xD3, 0x2D, 0x60, 0xC6, 0x62, 0xFF, 0xA0, 0xA2, 0xD3, 0x21, 0x03, 0x00, 0x60, + 0x00, 0x63, 0x59, 0xDD, 0x61, 0x45, 0x60, 0x40, 0x01, 0x2A, 0x04, 0x00, 0x00, 0x60, 0xF2, 0x63, + 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x02, 0x2A, 0x04, 0x00, 0x01, 0x60, 0xF2, 0x63, 0x59, 0xD9, + 0x59, 0xDD, 0x60, 0x40, 0x04, 0x2A, 0x04, 0x00, 0x02, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, + 0xD5, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xA5, 0xDD, 0x2D, 0x60, 0xC8, 0x62, 0xA2, 0xD1, 0x59, 0xD9, + 0x2D, 0x60, 0xA0, 0x65, 0xD5, 0x84, 0xDD, 0x7F, 0xA5, 0xDB, 0x65, 0x44, 0x2E, 0x60, 0xB8, 0x62, + 0xA2, 0xDB, 0x2E, 0x60, 0xD4, 0x62, 0xA2, 0xDB, 0x0F, 0x60, 0xD4, 0x62, 0x00, 0x60, 0x04, 0x64, + 0xA2, 0xDB, 0xE8, 0x60, 0x2F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, + 0xD2, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x7F, 0xF1, 0x2F, 0x60, 0x0E, 0x62, 0xA2, 0xD9, 0x2E, 0x60, + 0xB6, 0x65, 0xE9, 0x60, 0x58, 0x4D, 0x32, 0x78, 0xFF, 0xFF, 0x5D, 0xF5, 0x00, 0xF4, 0x80, 0xF1, + 0x06, 0xF8, 0x2F, 0x60, 0x44, 0x62, 0xA2, 0xD3, 0x07, 0xFA, 0x2E, 0x60, 0xAE, 0x64, 0x40, 0x48, + 0x10, 0x61, 0x00, 0x60, 0x00, 0x64, 0xE8, 0x60, 0x58, 0x4D, 0xE8, 0x78, 0xFF, 0xFF, 0x5D, 0xF5, + 0x3F, 0xFC, 0xDB, 0xFE, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, + 0x5A, 0xDB, 0x04, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0xDC, 0xF3, 0x9B, 0xFE, 0xFD, 0xA0, 0x25, 0x04, 0x24, 0x02, 0x04, 0x64, 0x03, 0xFA, 0x00, 0xF4, + 0x09, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x3A, 0x1C, 0x00, 0x60, 0x43, 0x00, 0x36, 0x1C, 0x00, + 0xE0, 0xA0, 0xDA, 0x85, 0x16, 0x07, 0x2D, 0x60, 0x7A, 0x61, 0xA1, 0xD1, 0xFF, 0xFF, 0xD3, 0x80, + 0xCB, 0x83, 0x0F, 0x02, 0x07, 0x0E, 0x59, 0xD3, 0xA5, 0xD0, 0xDA, 0x85, 0xD0, 0x80, 0xFF, 0xFF, + 0x08, 0x02, 0xF9, 0x1F, 0x13, 0x1E, 0xA5, 0xD0, 0x59, 0xD3, 0xFF, 0xFF, 0x90, 0x80, 0xFF, 0x22, + 0x0D, 0x00, 0xE8, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0x28, 0x60, 0x2A, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, + 0x60, 0x40, 0x01, 0x2A, 0x03, 0x00, 0x27, 0x60, 0xDA, 0x64, 0x02, 0x00, 0x2D, 0x60, 0x7A, 0x64, + 0x2E, 0x60, 0xCA, 0x62, 0xA2, 0xDB, 0x26, 0x46, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, + 0x31, 0xF2, 0x2E, 0xFA, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, + 0x81, 0xF1, 0x32, 0xF8, 0x82, 0xF1, 0x33, 0xF8, 0x83, 0xF1, 0x34, 0xF8, 0x50, 0x63, 0x2A, 0xFC, + 0xCC, 0xF3, 0x19, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0xA9, 0xF3, 0x07, 0xFA, 0x00, 0xF4, 0x80, 0xF1, + 0x06, 0xF8, 0x2F, 0x60, 0x44, 0x62, 0xA2, 0xD3, 0x07, 0xFA, 0x2E, 0x60, 0xD2, 0x65, 0xE9, 0x60, + 0x58, 0x4D, 0x32, 0x78, 0xFF, 0xFF, 0x2E, 0x60, 0xCA, 0x64, 0x40, 0x48, 0x10, 0x61, 0x00, 0x60, + 0x00, 0x64, 0xE8, 0x60, 0x58, 0x4D, 0xE8, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xFC, 0x24, 0x60, + 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, + 0xD2, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x00, 0x64, 0x94, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, + 0x2F, 0x60, 0x46, 0x62, 0xA2, 0xDB, 0xCD, 0x81, 0x28, 0xD3, 0x5A, 0x88, 0xDC, 0x83, 0x39, 0x18, + 0xFB, 0x03, 0x61, 0x40, 0x7F, 0x3A, 0x07, 0x00, 0x2F, 0x60, 0x46, 0x62, 0xA2, 0xD3, 0x03, 0x61, + 0x7C, 0xA4, 0xA2, 0xDB, 0x00, 0xF4, 0x60, 0xFE, 0xA3, 0xD1, 0xDD, 0x81, 0xA1, 0xD8, 0x61, 0x40, + 0x7F, 0x3A, 0x09, 0x00, 0x20, 0xFE, 0x2F, 0x60, 0x46, 0x62, 0xA2, 0xD3, 0x03, 0x61, 0x7C, 0xA4, + 0xA2, 0xDB, 0x00, 0xF4, 0x60, 0xFE, 0xCF, 0x83, 0xA3, 0xD3, 0xDD, 0x81, 0xA1, 0xDA, 0xFF, 0xB4, + 0x00, 0x7F, 0x15, 0x03, 0xDB, 0x83, 0x61, 0x40, 0x7F, 0x3A, 0x0B, 0x00, 0x20, 0xFE, 0x60, 0x45, + 0x2F, 0x60, 0x46, 0x62, 0xA2, 0xD3, 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x65, 0x44, 0x00, 0xF4, + 0x60, 0xFE, 0xA3, 0xD1, 0xDF, 0x83, 0xDD, 0x81, 0xCC, 0x84, 0xA1, 0xD8, 0xEC, 0x02, 0x20, 0xFE, + 0xC3, 0x01, 0x2F, 0x60, 0x46, 0x62, 0xA2, 0xD1, 0xFD, 0xA1, 0xFF, 0xB1, 0xC1, 0x83, 0xA2, 0xDD, + 0x2D, 0x58, 0xFF, 0xFF, 0x67, 0x5C, 0x1B, 0x60, 0xC6, 0x61, 0xA1, 0xD3, 0xA5, 0xD9, 0x12, 0x18, + 0x60, 0x43, 0x2F, 0x60, 0x14, 0x64, 0xA5, 0xDB, 0x60, 0xFE, 0xA0, 0xDD, 0xFF, 0xFF, 0x20, 0xFE, + 0xDC, 0x84, 0xCF, 0x83, 0xE3, 0x83, 0x59, 0xD1, 0xDC, 0x84, 0x60, 0xFE, 0xA0, 0xD9, 0xFF, 0xFF, + 0x20, 0xFE, 0xF9, 0x1F, 0x2D, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, 0x40, 0x26, 0x29, 0x00, + 0x45, 0x48, 0x00, 0x60, 0x10, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x21, 0x03, + 0xF2, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x00, 0x60, 0x48, 0x61, 0x28, 0x44, 0x59, 0xDA, 0x03, 0x64, + 0x38, 0x43, 0xBD, 0xD1, 0xCC, 0x84, 0x59, 0xD8, 0xFC, 0x02, 0x39, 0x44, 0x59, 0xDA, 0x28, 0x60, + 0x2E, 0x64, 0xA0, 0xD3, 0x59, 0xDA, 0x07, 0x64, 0x23, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, + 0x64, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, 0x40, 0x26, 0x1C, 0x00, 0x45, 0x48, + 0x00, 0x60, 0x06, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x14, 0x03, 0x02, 0x64, + 0x23, 0xFA, 0xF2, 0x60, 0x00, 0x64, 0x5A, 0xDA, 0x28, 0x44, 0x5A, 0xDA, 0xFF, 0xFF, 0x24, 0x60, + 0x74, 0x62, 0x24, 0x60, 0x64, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, 0x32, 0x40, 0x40, 0x26, + 0x3E, 0x00, 0x9D, 0xF3, 0x67, 0x43, 0xDC, 0x84, 0xCC, 0x84, 0x39, 0x03, 0x60, 0x46, 0x0A, 0x02, + 0x9D, 0xFD, 0x00, 0x60, 0x46, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, + 0x9D, 0xFB, 0x2E, 0x03, 0x46, 0x4B, 0x27, 0x60, 0x72, 0x61, 0x18, 0x64, 0x23, 0xFA, 0xF1, 0x60, + 0x00, 0x64, 0x24, 0xFA, 0x4A, 0x65, 0xA2, 0xFF, 0x2C, 0x63, 0x00, 0x64, 0x59, 0xD1, 0xA2, 0xDB, + 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF7, 0x1F, 0x12, 0x63, + 0x59, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, + 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x64, 0x64, 0xA2, 0xDB, 0x2B, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0xA6, 0xFE, 0x00, 0x64, 0x9D, 0xFB, 0xA3, 0xFF, + 0xBF, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0xA6, 0xFE, 0xB8, 0x05, 0xA7, 0xFE, 0x12, 0x05, 0xA5, 0xFE, + 0x03, 0x04, 0xEA, 0x60, 0xC5, 0x78, 0xFF, 0xFF, 0xA4, 0xFE, 0xF2, 0x04, 0x0F, 0x60, 0xDE, 0x62, + 0xA2, 0xD1, 0x00, 0x60, 0x80, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xBF, 0x60, 0xE7, 0x78, + 0xFF, 0xFF, 0x36, 0x45, 0x20, 0x60, 0x08, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xF3, + 0xFF, 0xFF, 0x01, 0xB0, 0x00, 0x64, 0x41, 0x03, 0x9F, 0xFB, 0x31, 0x44, 0xE8, 0xB4, 0x40, 0x51, + 0x6A, 0x44, 0xFF, 0xFF, 0x80, 0x26, 0xFC, 0x01, 0x61, 0xFF, 0x62, 0xFF, 0x10, 0x60, 0x1A, 0x62, + 0xA2, 0xD1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x34, 0x60, 0x58, 0x4E, + 0x64, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xBC, 0x62, 0x1E, 0x60, 0xBE, 0x64, 0xA2, 0xDB, 0x00, 0x64, + 0x4A, 0xDB, 0x01, 0x60, 0xFE, 0x63, 0x1C, 0x60, 0xB8, 0x61, 0x00, 0x64, 0x59, 0xDB, 0xFE, 0x1F, + 0x1C, 0x63, 0x10, 0x60, 0x5C, 0x64, 0x58, 0xD1, 0xFF, 0xFF, 0x08, 0x1B, 0xFC, 0x1F, 0x00, 0x60, + 0x62, 0x63, 0x1B, 0x60, 0xC4, 0x64, 0x00, 0x7C, 0x58, 0xD9, 0xFE, 0x1F, 0x1C, 0x60, 0xB4, 0x63, + 0xA3, 0xD3, 0xFF, 0xFF, 0x04, 0xB0, 0xFF, 0xFF, 0x05, 0x03, 0x02, 0x65, 0xE9, 0x60, 0x58, 0x4E, + 0x7B, 0x78, 0xFF, 0xFF, 0xBF, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0xEA, 0x60, 0xC5, 0x78, 0xFF, 0xFF, + 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x74, 0x00, 0x28, 0x60, 0x50, 0x63, 0xBD, 0xD3, 0xBD, 0xD1, 0xBD, 0xD1, 0xB0, 0x84, 0xB0, 0x84, + 0xFF, 0xFF, 0x07, 0x02, 0x8C, 0xFB, 0x31, 0x44, 0xFE, 0xB4, 0x40, 0x51, 0x0D, 0x64, 0x05, 0xFB, + 0x64, 0x00, 0x28, 0xF3, 0x9F, 0xF1, 0x60, 0x47, 0x64, 0x41, 0x07, 0xB1, 0x07, 0xB4, 0x08, 0x24, + 0x67, 0x4C, 0x50, 0xFB, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0xA1, 0x80, + 0xB1, 0x83, 0x53, 0x02, 0x9F, 0xFD, 0x28, 0x60, 0x44, 0x62, 0xA2, 0xD3, 0xE5, 0xFB, 0x7F, 0xFB, + 0x24, 0x60, 0x5E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x46, 0x5E, 0x31, 0x44, + 0x01, 0xBC, 0x40, 0x51, 0xD8, 0xF3, 0x01, 0x63, 0x03, 0xA8, 0x4E, 0xFD, 0x05, 0x02, 0x02, 0x63, + 0x14, 0x60, 0x00, 0x64, 0xDB, 0xFB, 0x0C, 0x00, 0x02, 0xA8, 0x01, 0x63, 0x03, 0x03, 0x0A, 0x60, + 0x00, 0x64, 0x03, 0x00, 0x02, 0x63, 0x14, 0x60, 0x00, 0x64, 0xDB, 0xFB, 0x00, 0x64, 0x4E, 0xFB, + 0x4B, 0xFD, 0xA9, 0xF5, 0xFF, 0xFF, 0x0E, 0xF0, 0x0F, 0x60, 0xA2, 0x65, 0x28, 0x60, 0xD2, 0x62, + 0xA2, 0xD3, 0xFF, 0xFF, 0xFE, 0xA0, 0x03, 0xA8, 0x11, 0x06, 0x79, 0xF1, 0x06, 0x02, 0x64, 0x44, + 0x08, 0x2A, 0x09, 0x00, 0x06, 0x64, 0x44, 0xD3, 0x0D, 0x00, 0x64, 0x44, 0x20, 0x2A, 0x03, 0x00, + 0x0A, 0x64, 0x44, 0xD3, 0x07, 0x00, 0x01, 0x64, 0x44, 0xD3, 0x04, 0x00, 0xE8, 0x84, 0xE0, 0x84, + 0x44, 0xD3, 0x00, 0x00, 0x0E, 0xFA, 0xED, 0xE2, 0x0F, 0x4E, 0xC8, 0x60, 0x58, 0x4F, 0x15, 0x78, + 0xFF, 0xFF, 0x0E, 0x4F, 0xBF, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0xD7, 0xFE, 0xBF, 0x60, 0xE7, 0x78, + 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0xF3, 0x01, 0x24, 0x60, 0x46, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, + 0x0E, 0xF2, 0x4D, 0x03, 0x60, 0x40, 0xF0, 0x37, 0x3A, 0x00, 0xFF, 0x37, 0x2F, 0x00, 0xFD, 0x37, + 0x27, 0x00, 0xF8, 0x37, 0x0A, 0x00, 0x60, 0x47, 0xFF, 0xB5, 0x0F, 0x60, 0xD2, 0x62, 0x46, 0xD1, + 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x24, 0x60, 0x74, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xDA, 0x01, + 0x06, 0xB4, 0xFD, 0x7F, 0x0E, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x4C, 0x64, 0xA2, 0xDB, + 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF9, 0xFE, 0xCA, 0x01, + 0x23, 0xF0, 0x60, 0x40, 0x04, 0x26, 0xEC, 0x1B, 0x02, 0x26, 0xEA, 0x18, 0xA2, 0xFF, 0x02, 0xF0, + 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xB0, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0xB0, 0xFB, 0x24, 0x60, + 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0xB3, 0x01, 0xAC, 0xFE, + 0x09, 0x05, 0xAD, 0xFE, 0x10, 0x05, 0xAE, 0xFE, 0xAD, 0x05, 0xAF, 0xFE, 0x3A, 0x05, 0xBF, 0x60, + 0xE7, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x20, 0x60, 0x00, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0xF4, 0x01, 0x10, 0x60, 0x32, 0x65, 0x0B, 0x61, 0x07, 0x00, 0xA2, 0xDD, + 0x58, 0x4F, 0x64, 0x58, 0xFF, 0xFF, 0x00, 0xB9, 0xFF, 0xFF, 0x08, 0x03, 0x00, 0x63, 0xA5, 0xD1, + 0x5A, 0xD3, 0xDA, 0x85, 0x00, 0xA8, 0xCD, 0x81, 0xF2, 0x02, 0xF8, 0x02, 0xE0, 0x01, 0x0F, 0x60, + 0xCE, 0x62, 0x10, 0x60, 0x12, 0x65, 0xEB, 0x60, 0x5F, 0x63, 0x00, 0x64, 0x5A, 0xDB, 0xD6, 0x80, + 0xFF, 0xFF, 0x04, 0x03, 0x5A, 0xDB, 0x5A, 0xDB, 0x5A, 0xDD, 0xF9, 0x01, 0x10, 0x60, 0x30, 0x65, + 0x00, 0x64, 0x5A, 0xDB, 0xD6, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x5A, 0xDD, 0xFB, 0x01, 0x2F, 0x58, + 0xFF, 0xFF, 0x0F, 0x60, 0xD2, 0x64, 0x40, 0x41, 0x0F, 0x60, 0xD0, 0x63, 0xA3, 0xD1, 0x00, 0x64, + 0xD0, 0x80, 0x0B, 0x61, 0x08, 0x03, 0xBD, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0xB0, 0x84, 0xCD, 0x81, + 0xA3, 0xDB, 0x06, 0xA3, 0xF9, 0x02, 0x10, 0x60, 0x1A, 0x63, 0xA3, 0xD1, 0x00, 0x64, 0xD0, 0x80, + 0x0C, 0x61, 0x19, 0x03, 0xBD, 0xDB, 0x64, 0x44, 0xFE, 0xA3, 0x02, 0xA3, 0xCD, 0x81, 0xE8, 0x84, + 0xE3, 0x03, 0x02, 0x05, 0xE1, 0x03, 0xF9, 0x01, 0x99, 0xFB, 0x9B, 0xFD, 0x61, 0x5C, 0xA3, 0xD3, + 0x9A, 0xF9, 0x03, 0x18, 0x58, 0x4F, 0x60, 0x58, 0xFF, 0xFF, 0x9B, 0xF3, 0x9A, 0xF1, 0x60, 0x43, + 0x99, 0xF3, 0x64, 0x41, 0xEA, 0x01, 0x21, 0x43, 0x10, 0x60, 0x14, 0x65, 0xD7, 0x80, 0xBD, 0xD1, + 0xBD, 0xD3, 0x03, 0x02, 0xBF, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0xA0, 0x84, 0xBD, 0xD1, 0x43, 0x41, + 0xF5, 0x03, 0xEB, 0x60, 0x64, 0x64, 0x64, 0x58, 0x40, 0x4F, 0x2A, 0xF0, 0x83, 0x60, 0xFF, 0x65, + 0x64, 0x47, 0x03, 0x2B, 0x01, 0x00, 0x14, 0x00, 0x03, 0x26, 0x03, 0xAC, 0x60, 0x47, 0xA4, 0x84, + 0x2A, 0xFA, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0x64, 0x41, + 0xEB, 0xF3, 0x2F, 0xFA, 0x60, 0x43, 0xEC, 0xF3, 0x30, 0xFA, 0xED, 0xF1, 0x31, 0xF8, 0x19, 0x00, + 0x60, 0x47, 0xA4, 0x84, 0x2A, 0xFA, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, + 0x2E, 0xFA, 0x36, 0xF2, 0x32, 0xFA, 0x37, 0xF2, 0x33, 0xFA, 0x38, 0xF2, 0x34, 0xFA, 0xEB, 0xF3, + 0x2F, 0xFA, 0x36, 0xFA, 0xEC, 0xF3, 0x30, 0xFA, 0x37, 0xFA, 0xED, 0xF3, 0x31, 0xFA, 0x38, 0xFA, + 0x64, 0x41, 0x1C, 0xF2, 0x13, 0xFA, 0x00, 0xF4, 0x0D, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, + 0x18, 0x00, 0x81, 0x67, 0xA2, 0xDA, 0xEC, 0x60, 0x58, 0x4E, 0x5A, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0x3F, 0xFC, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, + 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xF0, 0x42, 0x64, 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x04, 0x3F, 0xFA, + 0x07, 0xF2, 0xA9, 0xF1, 0x01, 0x1B, 0x07, 0xF8, 0x1C, 0xF2, 0x13, 0xFA, 0x26, 0xF2, 0x27, 0xF0, + 0x60, 0x47, 0x00, 0xF4, 0x1F, 0xFA, 0x64, 0x47, 0x20, 0xFA, 0x61, 0x44, 0x21, 0xFA, 0x01, 0x67, + 0x0D, 0xFA, 0x10, 0x61, 0x28, 0x60, 0x06, 0x64, 0x1E, 0x63, 0x58, 0xD1, 0xCD, 0x81, 0xBD, 0xD8, + 0xFC, 0x02, 0xBB, 0xF1, 0xD8, 0xF1, 0x64, 0x5E, 0x64, 0x5F, 0x44, 0x63, 0xBD, 0xDA, 0x28, 0x60, + 0x00, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x4A, 0xD3, 0x60, 0x45, + 0x60, 0x40, 0x01, 0x36, 0x03, 0x64, 0x02, 0x36, 0x01, 0x64, 0xB4, 0x84, 0x06, 0xA2, 0xA2, 0xD1, + 0xBD, 0xDA, 0x64, 0x47, 0xBD, 0xDA, 0xD5, 0xF3, 0xD6, 0xF1, 0x60, 0x47, 0xBD, 0xDA, 0x64, 0x47, + 0xE3, 0xF1, 0xBD, 0xDA, 0x64, 0x44, 0xBD, 0xDA, 0x26, 0x46, 0x00, 0x64, 0x23, 0xF0, 0x3B, 0xF0, + 0x64, 0x40, 0x10, 0x2A, 0x06, 0x00, 0xC0, 0x67, 0xA0, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, + 0x10, 0xBC, 0x3E, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x34, 0x64, 0xA2, 0xDB, 0x26, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, 0x00, 0x66, 0x46, 0x46, + 0x2F, 0x58, 0xFF, 0xFF, 0xB4, 0xF3, 0x1F, 0xFA, 0x32, 0x47, 0x07, 0xFA, 0x24, 0x7E, 0x02, 0x7F, + 0x08, 0xFA, 0xD8, 0xF1, 0x09, 0xF8, 0x01, 0x60, 0x01, 0x64, 0x0A, 0xFA, 0x01, 0x64, 0x0B, 0xFA, + 0x24, 0x60, 0x74, 0x62, 0x18, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x0A, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0x52, 0x63, 0x2E, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0x2A, 0x61, 0xAE, 0x60, + 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x5E, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x67, 0x44, + 0x2C, 0xFA, 0x2D, 0xFA, 0x2E, 0xFA, 0x32, 0xFA, 0x33, 0xFA, 0x34, 0xFA, 0x12, 0x60, 0x80, 0x64, + 0xA9, 0xF1, 0x0E, 0xFA, 0x07, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x1A, 0x60, 0x4E, 0x63, 0xA3, 0xDB, + 0x06, 0xA3, 0x10, 0x60, 0x38, 0x64, 0xBD, 0xDB, 0x04, 0x64, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, + 0x10, 0x60, 0x36, 0x62, 0xEF, 0x60, 0xA9, 0x64, 0xA2, 0xDB, 0x1A, 0x60, 0x5A, 0x63, 0x00, 0x64, + 0xA3, 0xDB, 0x06, 0xA3, 0x10, 0x60, 0x3C, 0x64, 0xBD, 0xDB, 0x08, 0x64, 0xBD, 0xDB, 0x06, 0x64, + 0xA3, 0xDB, 0x10, 0x60, 0x3A, 0x62, 0xEF, 0x60, 0xB3, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x22, 0x62, + 0xEF, 0x60, 0x93, 0x64, 0xA2, 0xDB, 0x00, 0x64, 0x31, 0x60, 0x2A, 0x62, 0xA2, 0xDB, 0x2F, 0x58, + 0xFF, 0xFF, 0x5E, 0xF5, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, + 0xCC, 0xF1, 0x19, 0xF8, 0x30, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x00, 0x63, 0x8A, 0xFD, 0x1C, 0x60, 0x96, 0x65, 0xA5, 0xDD, 0x19, 0x60, 0x86, 0x63, + 0x88, 0xFD, 0x89, 0xFD, 0x20, 0x40, 0x10, 0x2B, 0x05, 0x00, 0x1F, 0x60, 0x82, 0x61, 0xA1, 0xD3, + 0xFF, 0xFF, 0x59, 0x18, 0x5E, 0xF5, 0x40, 0x64, 0x2A, 0xFA, 0x54, 0xF3, 0x00, 0xF4, 0x60, 0x43, + 0xBD, 0xD1, 0x04, 0x65, 0x64, 0x47, 0xA5, 0xDA, 0x64, 0x41, 0xDD, 0x81, 0xE9, 0x81, 0x62, 0x44, + 0x04, 0x03, 0xBD, 0xD1, 0xCD, 0x81, 0x58, 0xD8, 0xFC, 0x02, 0x58, 0x8B, 0x2D, 0x60, 0x28, 0x63, + 0xA3, 0xD1, 0x2B, 0x44, 0xC8, 0x84, 0x64, 0x41, 0xFF, 0xB1, 0x61, 0x45, 0x03, 0xA1, 0xE9, 0x81, + 0x41, 0x4C, 0xBD, 0xD1, 0xCD, 0x81, 0x58, 0xD8, 0xFC, 0x02, 0x2B, 0xD2, 0x2B, 0x43, 0x60, 0x47, + 0x01, 0x7E, 0x54, 0xF1, 0xA3, 0xDA, 0xA4, 0xD3, 0xCB, 0x83, 0x44, 0x8B, 0xF8, 0x84, 0x2C, 0x41, + 0x0C, 0x04, 0xBE, 0xD2, 0xFF, 0xFF, 0x60, 0x47, 0xBE, 0xDA, 0x00, 0x7E, 0xA3, 0xD2, 0x60, 0x45, + 0x00, 0x7F, 0xB4, 0x84, 0xCD, 0x81, 0xBD, 0xDA, 0xF4, 0x02, 0x5E, 0xF5, 0x2B, 0x44, 0x04, 0xA4, + 0x3F, 0xFA, 0x7F, 0xF3, 0x7E, 0xFB, 0x1F, 0x60, 0x84, 0x61, 0x01, 0x64, 0x54, 0xF1, 0xA1, 0xDB, + 0x7F, 0xFB, 0xA4, 0xD3, 0x04, 0x65, 0x53, 0xF3, 0x01, 0x18, 0x0C, 0x65, 0xF3, 0xB4, 0xB4, 0x84, + 0x53, 0xFB, 0x02, 0xB0, 0xFF, 0xFF, 0x16, 0x03, 0x7F, 0xF3, 0xFF, 0xFF, 0x60, 0x47, 0x0F, 0xB4, + 0x7F, 0xFB, 0x01, 0x03, 0x0F, 0x00, 0xEE, 0x60, 0x4F, 0x78, 0xFF, 0xFF, 0x53, 0xF1, 0x7F, 0xF3, + 0x64, 0x40, 0x02, 0x26, 0xF8, 0x01, 0xF3, 0xA0, 0x04, 0xA4, 0x01, 0x04, 0xF1, 0xA4, 0x10, 0x36, + 0xF2, 0x01, 0x7F, 0xFB, 0x20, 0x40, 0x10, 0x2B, 0x12, 0x00, 0x7F, 0xF3, 0x1F, 0x60, 0x82, 0x61, + 0xA1, 0xD1, 0xCC, 0x84, 0x01, 0x61, 0x08, 0x24, 0x03, 0x00, 0xE1, 0x81, 0xCC, 0x84, 0xFB, 0x01, + 0xA1, 0x84, 0x53, 0xF1, 0xE4, 0x03, 0x1F, 0x60, 0x84, 0x61, 0xA1, 0xDB, 0x19, 0x00, 0x53, 0xF3, + 0xFF, 0xFF, 0x10, 0xB0, 0x12, 0x60, 0x26, 0x63, 0x02, 0x03, 0x10, 0x60, 0x5C, 0x63, 0x31, 0x60, + 0x2A, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x0C, 0x1B, 0x7F, 0xF3, 0xFF, 0xFF, 0xE0, 0x85, 0x47, 0xD3, + 0x53, 0xF1, 0x01, 0xB0, 0x06, 0xB0, 0xCB, 0x03, 0x64, 0x40, 0x03, 0x26, 0x01, 0x00, 0xC7, 0x03, + 0x7F, 0xF3, 0x01, 0x61, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, 0xE1, 0x81, 0xFB, 0x01, 0xBA, 0xF3, + 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0xBB, 0x03, 0x31, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, + 0xE4, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xE6, 0x62, 0x40, 0x60, + 0x00, 0x64, 0xA2, 0xDB, 0xED, 0x60, 0x70, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x7F, 0xF1, 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, + 0x0F, 0x60, 0xE6, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xED, 0x60, 0xA3, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, + 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x5E, 0xF5, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x64, 0x51, 0xFB, 0x0F, 0x60, 0xE6, 0x62, + 0x00, 0x60, 0x01, 0x64, 0xA2, 0xDB, 0xED, 0x60, 0xCD, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, + 0x33, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x34, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xC6, 0xF1, 0x1A, 0x60, 0x52, 0x62, 0xA2, 0xD9, + 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x4E, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0xC7, 0xF1, 0x1A, 0x60, 0x5E, 0x62, 0xA2, 0xD9, 0x24, 0x60, 0xA8, 0x62, 0xA2, 0xD3, + 0xFF, 0xFF, 0xFD, 0x1B, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x5A, 0x64, 0xA2, 0xDB, 0x02, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xE6, 0x62, 0x00, 0x60, 0x08, 0x64, 0xA2, 0xDB, + 0xED, 0x60, 0xFE, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x51, 0xF1, 0x0F, 0x60, + 0xE4, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x64, 0x40, 0xFF, 0x26, 0x03, 0x00, 0xED, 0x60, 0x36, 0x78, + 0xFF, 0xFF, 0x02, 0x0A, 0x00, 0x64, 0x51, 0xFB, 0xC8, 0xF1, 0x1A, 0x60, 0x5E, 0x62, 0xA2, 0xD9, + 0x0F, 0x60, 0xE6, 0x62, 0x00, 0x60, 0x0C, 0x64, 0xA2, 0xDB, 0xEE, 0x60, 0x24, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x5A, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xE4, 0x62, 0xA2, 0xD1, 0x00, 0x60, + 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0C, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, + 0x1A, 0x60, 0x5A, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x14, 0x00, + 0xFF, 0x60, 0xF7, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x51, 0xF3, 0xDB, 0x0A, 0x00, 0xA0, 0x00, 0x64, + 0x02, 0x03, 0x51, 0xFB, 0xD6, 0x01, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x4E, 0x64, 0xA2, 0xDB, + 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xED, 0x60, 0x36, 0x78, 0xFF, 0xFF, 0x35, 0x64, + 0x3B, 0x42, 0x5A, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x4E, 0x64, 0xA2, 0xDB, 0x03, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x53, 0xF3, 0xFF, 0xFF, 0xE3, 0xB4, 0x53, 0xFB, 0x1F, 0x60, + 0x80, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xFE, 0xB4, 0xA2, 0xDB, 0x00, 0x64, 0x31, 0x60, 0x2A, 0x62, + 0xA2, 0xDB, 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0E, 0x04, 0x32, 0x64, + 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xE6, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xEE, 0x60, + 0x69, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7E, 0xF1, 0x7F, 0xF9, 0x24, 0x60, + 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xE6, 0x62, + 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xEE, 0x60, 0x91, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x1A, 0x60, 0x06, 0x63, 0x1C, 0x61, 0x00, 0x64, 0xCD, 0x81, 0xBD, 0xDB, + 0xFD, 0x02, 0x12, 0x60, 0x46, 0x61, 0x8A, 0xF3, 0x61, 0x43, 0xC6, 0xA5, 0x47, 0xD1, 0x0F, 0x04, + 0xBE, 0xD5, 0x1A, 0x60, 0x02, 0x63, 0xC3, 0x83, 0xC3, 0x83, 0xC3, 0x83, 0x43, 0xD3, 0xBE, 0xD1, + 0xDC, 0x84, 0xA3, 0xDB, 0x66, 0x44, 0xC0, 0x84, 0xBE, 0xDB, 0x65, 0x44, 0xED, 0x01, 0x1A, 0x60, + 0x06, 0x63, 0x0E, 0x61, 0x41, 0x4B, 0xBD, 0xD3, 0xBD, 0xD1, 0x00, 0xBD, 0x64, 0x41, 0x19, 0x03, + 0x01, 0xA8, 0x61, 0x44, 0x02, 0xA8, 0x15, 0x03, 0x02, 0x02, 0xE9, 0x84, 0x12, 0x00, 0x65, 0x47, + 0x60, 0x45, 0x61, 0x44, 0x09, 0x61, 0xCD, 0x81, 0xE0, 0x84, 0xFF, 0x23, 0xFC, 0x01, 0x02, 0x24, + 0xC4, 0x84, 0x02, 0x28, 0xD4, 0x84, 0xCD, 0x81, 0x01, 0x0E, 0x01, 0xBC, 0x02, 0x03, 0xE0, 0x84, + 0xF6, 0x01, 0x00, 0x7F, 0x2B, 0x41, 0x4D, 0x8B, 0xBF, 0xDB, 0xDD, 0x02, 0x12, 0x60, 0x46, 0x61, + 0x8A, 0xF3, 0x61, 0x43, 0xC6, 0xA5, 0x47, 0xD1, 0x0A, 0x04, 0xDA, 0x86, 0x1A, 0x60, 0x04, 0x63, + 0xC3, 0x83, 0xC3, 0x83, 0xC3, 0x83, 0x43, 0xD1, 0xA6, 0xD9, 0x65, 0x44, 0xF2, 0x01, 0x36, 0x64, + 0x3B, 0x42, 0x5A, 0xDB, 0x53, 0xF3, 0x8A, 0xF1, 0xF3, 0xB4, 0x53, 0xFB, 0x12, 0x60, 0x46, 0x63, + 0xC3, 0x85, 0x45, 0x4A, 0x19, 0x60, 0x86, 0x65, 0x89, 0xF3, 0x45, 0x4C, 0x40, 0x48, 0x20, 0x40, + 0x20, 0x2A, 0x02, 0x00, 0x00, 0x65, 0x45, 0x4B, 0x2A, 0x45, 0xD7, 0x80, 0x02, 0x65, 0x23, 0x05, + 0x47, 0xD1, 0x02, 0x65, 0x47, 0xD3, 0x0A, 0x65, 0xD0, 0x81, 0x47, 0xD3, 0x01, 0x05, 0x00, 0x61, + 0xF2, 0xA3, 0x01, 0xB0, 0x61, 0x44, 0x11, 0x03, 0x20, 0x40, 0x20, 0x2A, 0x08, 0x00, 0xF3, 0x60, + 0x58, 0x4E, 0x3E, 0x78, 0xFF, 0xFF, 0x2B, 0x44, 0x02, 0xA4, 0x40, 0x4B, 0x61, 0x44, 0x2C, 0x42, + 0xA2, 0xDB, 0x5A, 0xDD, 0x5A, 0x8C, 0x3A, 0xA3, 0xDF, 0x01, 0x28, 0x42, 0x4A, 0xDD, 0x4A, 0xDB, + 0x42, 0x48, 0x3A, 0xA3, 0xD9, 0x01, 0x28, 0x44, 0x88, 0xFB, 0x88, 0xF1, 0x19, 0x60, 0x86, 0x63, + 0x44, 0x48, 0x28, 0x45, 0xD7, 0x80, 0xA3, 0xD1, 0x15, 0x05, 0x04, 0x65, 0x46, 0xD3, 0x28, 0x45, + 0xD6, 0x80, 0xD0, 0x80, 0x02, 0x04, 0x04, 0xA3, 0xF5, 0x01, 0xF7, 0x06, 0x62, 0x46, 0xA2, 0xD9, + 0xA3, 0xDB, 0x5B, 0xD3, 0x66, 0x42, 0x5A, 0xD1, 0xA2, 0xDB, 0xA3, 0xD9, 0xFE, 0xA3, 0xA3, 0xD1, + 0x66, 0x42, 0xEB, 0x01, 0x88, 0xF3, 0x89, 0xF1, 0x60, 0x43, 0x44, 0x48, 0x28, 0x45, 0xD7, 0x80, + 0xA3, 0xD1, 0x15, 0x05, 0x04, 0x65, 0x46, 0xD3, 0x28, 0x45, 0xD6, 0x80, 0xD0, 0x80, 0x02, 0x04, + 0x04, 0xA3, 0xF5, 0x01, 0xF7, 0x06, 0x62, 0x46, 0xA2, 0xD9, 0xA3, 0xDB, 0x5B, 0xD3, 0x66, 0x42, + 0x5A, 0xD1, 0xA2, 0xDB, 0xA3, 0xD9, 0xFE, 0xA3, 0xA3, 0xD1, 0x66, 0x42, 0xEB, 0x01, 0x0F, 0x60, + 0xD0, 0x62, 0xA2, 0xD1, 0x10, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x20, 0x40, + 0x80, 0x2B, 0x17, 0x00, 0x00, 0x60, 0x04, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, + 0x01, 0x64, 0x23, 0xFA, 0xF1, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, + 0x64, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xFA, 0xFE, 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x3E, 0x64, 0x3B, 0x42, + 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x3F, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x24, 0x60, 0xAA, 0x62, + 0x1A, 0x60, 0x4E, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, + 0x53, 0xFB, 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0xBE, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x0F, 0x60, 0xE4, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xE4, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x79, 0xFB, 0xAC, 0x85, 0x60, 0x41, + 0x20, 0x03, 0x01, 0x60, 0x00, 0x63, 0x08, 0x64, 0xE9, 0x81, 0xCC, 0x84, 0x02, 0x24, 0xDF, 0x83, + 0xFB, 0x02, 0x2D, 0x60, 0x28, 0x64, 0xA0, 0xDD, 0x65, 0x41, 0x2D, 0x60, 0x2A, 0x63, 0x0F, 0x60, + 0xC0, 0x64, 0xE9, 0x81, 0x58, 0xD1, 0xFD, 0x04, 0xA3, 0xD9, 0x0B, 0x03, 0x58, 0xD1, 0xE9, 0x81, + 0x60, 0x45, 0xFC, 0x04, 0xA3, 0xD1, 0x64, 0x47, 0xB0, 0x84, 0xBD, 0xDB, 0x00, 0xB9, 0x65, 0x44, + 0xF0, 0x02, 0x2E, 0x58, 0xFF, 0xFF, 0x3C, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x20, 0x40, 0x90, 0x2B, + 0x03, 0x00, 0xF2, 0x60, 0xE5, 0x78, 0xFF, 0xFF, 0x53, 0xF3, 0x8A, 0xF1, 0x04, 0xB0, 0x07, 0x60, + 0x40, 0x64, 0xD0, 0x80, 0x21, 0x03, 0x20, 0x06, 0x26, 0x46, 0x8A, 0xF1, 0x12, 0x60, 0x46, 0x63, + 0xC3, 0x83, 0x7F, 0xF3, 0x26, 0xF0, 0xBD, 0xDB, 0x64, 0x44, 0x00, 0x7F, 0xBD, 0xDB, 0x64, 0x47, + 0x00, 0x7F, 0xBD, 0xDB, 0x32, 0xF0, 0xBD, 0xD9, 0x33, 0xF0, 0xBD, 0xD9, 0x34, 0xF0, 0xBD, 0xD9, + 0x00, 0xF4, 0x0D, 0xF0, 0xBD, 0xD9, 0x0E, 0xF0, 0xBD, 0xD9, 0x00, 0x64, 0x0F, 0xF0, 0xA3, 0xDB, + 0x64, 0x47, 0x60, 0x45, 0x00, 0x37, 0x03, 0x00, 0xF2, 0x60, 0xDF, 0x78, 0xFF, 0xFF, 0xBD, 0xDB, + 0xE0, 0xA0, 0x1F, 0x61, 0x00, 0xB8, 0xF8, 0x07, 0xF7, 0x03, 0x60, 0xFE, 0xDD, 0x81, 0xA1, 0xD0, + 0xCC, 0x84, 0xBD, 0xD9, 0xFB, 0x02, 0x65, 0x40, 0x01, 0x26, 0xDF, 0x83, 0x20, 0xFE, 0x2D, 0x60, + 0xE4, 0x62, 0xA2, 0xDD, 0x60, 0xFE, 0xDD, 0x81, 0xA1, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x3A, + 0x04, 0x00, 0xDD, 0x81, 0xA1, 0xD0, 0xFF, 0xFF, 0xC1, 0x81, 0xDD, 0x81, 0xA1, 0xD0, 0xFF, 0xFF, + 0x64, 0x40, 0x03, 0x36, 0x03, 0x00, 0xF2, 0x60, 0xDF, 0x78, 0xFF, 0xFF, 0xD9, 0x81, 0xA1, 0xD0, + 0x7F, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0x20, 0xFE, 0x08, 0x24, 0x03, 0x00, 0xF2, 0x60, 0xDF, 0x78, + 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xF4, 0xA3, 0x00, 0x60, 0x1D, 0x61, + 0x00, 0x60, 0x80, 0x65, 0x60, 0xFE, 0x81, 0xA1, 0x7F, 0xA1, 0x02, 0x06, 0x00, 0xF4, 0x03, 0x61, + 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, 0xD4, 0x80, 0x2D, 0x03, 0x17, 0x03, 0xCF, 0x83, 0x61, 0x44, + 0x80, 0xA0, 0x28, 0x03, 0x02, 0x02, 0x00, 0xF4, 0x03, 0x61, 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, + 0x81, 0xA1, 0x20, 0x03, 0x05, 0x07, 0x7F, 0xA1, 0xCC, 0x84, 0xDD, 0x81, 0xE4, 0x03, 0xF7, 0x01, + 0x00, 0xF4, 0x00, 0xB8, 0x04, 0x61, 0xE4, 0x03, 0xF2, 0x01, 0x01, 0x60, 0xFF, 0x63, 0x46, 0x48, + 0x41, 0x4A, 0xDD, 0x81, 0xA1, 0xD0, 0xDF, 0x83, 0xA3, 0xD9, 0x64, 0x44, 0xDD, 0x81, 0xA1, 0xD0, + 0xDF, 0x83, 0xA3, 0xD9, 0xCC, 0x84, 0x81, 0xA1, 0x05, 0x03, 0x7F, 0xA1, 0xF7, 0x04, 0x00, 0xF4, + 0x03, 0x61, 0xF4, 0x01, 0x20, 0xFE, 0x00, 0xBB, 0x02, 0x60, 0x00, 0x61, 0x45, 0x03, 0x60, 0xFE, + 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x3A, 0x3E, 0x00, 0xDD, 0x81, 0xA1, 0xD1, + 0xFF, 0xFF, 0x64, 0x40, 0x60, 0x3A, 0x38, 0x00, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, + 0x1D, 0x3A, 0x32, 0x00, 0xDD, 0x81, 0xA1, 0xD3, 0xFF, 0xFF, 0x20, 0xFE, 0xFF, 0xB4, 0x1C, 0x60, + 0x96, 0x65, 0xA5, 0xD3, 0x60, 0x5C, 0x02, 0xA4, 0xA5, 0xDB, 0xFE, 0xA5, 0x1A, 0x60, 0xC6, 0x64, + 0x44, 0xD9, 0x00, 0x7C, 0x60, 0xFE, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, 0x1B, 0x60, + 0x06, 0x64, 0xC4, 0x82, 0x64, 0x44, 0xFF, 0xB4, 0xA2, 0xDB, 0x12, 0x60, 0x48, 0x65, 0x8A, 0xF3, + 0xFF, 0xFF, 0xC4, 0x82, 0x64, 0x44, 0xA2, 0xD3, 0xFF, 0xB5, 0xD4, 0x80, 0xFF, 0xFF, 0x02, 0x05, + 0x65, 0x44, 0xA2, 0xDB, 0x09, 0x00, 0x20, 0xFE, 0x28, 0x46, 0x2A, 0x41, 0xFF, 0xB1, 0x60, 0xFE, + 0x82, 0x64, 0xA1, 0xDA, 0xFF, 0xFF, 0x20, 0xFE, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, + 0xF4, 0xA3, 0x00, 0x60, 0x1D, 0x61, 0x00, 0x60, 0xDD, 0x65, 0x60, 0xFE, 0x81, 0xA1, 0x7F, 0xA1, + 0x02, 0x06, 0x00, 0xF4, 0x03, 0x61, 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, 0xD4, 0x80, 0x2D, 0x03, + 0x17, 0x03, 0xCF, 0x83, 0x61, 0x44, 0x80, 0xA0, 0x28, 0x03, 0x02, 0x02, 0x00, 0xF4, 0x03, 0x61, + 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, 0x81, 0xA1, 0x20, 0x03, 0x05, 0x07, 0x7F, 0xA1, 0xCC, 0x84, + 0xDD, 0x81, 0xE4, 0x03, 0xF7, 0x01, 0x00, 0xF4, 0x00, 0xB8, 0x04, 0x61, 0xE4, 0x03, 0xF2, 0x01, + 0x02, 0x60, 0x00, 0x63, 0x46, 0x48, 0x41, 0x4A, 0xDD, 0x81, 0xA1, 0xD0, 0xDF, 0x83, 0xA3, 0xD9, + 0x64, 0x44, 0xDD, 0x81, 0xA1, 0xD0, 0xDF, 0x83, 0xA3, 0xD9, 0xCC, 0x84, 0x81, 0xA1, 0x05, 0x03, + 0x7F, 0xA1, 0xF7, 0x04, 0x00, 0xF4, 0x03, 0x61, 0xF4, 0x01, 0x20, 0xFE, 0x00, 0xBB, 0x02, 0x60, + 0x00, 0x61, 0x08, 0x24, 0xA6, 0x00, 0x2D, 0x60, 0xD6, 0x62, 0xA2, 0xDF, 0x2D, 0x60, 0xD8, 0x62, + 0xA2, 0xDF, 0x2D, 0x60, 0xDA, 0x62, 0xA2, 0xDF, 0x2D, 0x60, 0xDC, 0x62, 0xA2, 0xDF, 0x60, 0xFE, + 0xDD, 0x64, 0xA1, 0xDB, 0xDD, 0x81, 0xA1, 0xD3, 0xFF, 0xFF, 0xFA, 0xA4, 0xFF, 0xFF, 0x04, 0x34, + 0x9A, 0x01, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x3A, 0x94, 0x01, 0xDD, 0x81, + 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x50, 0x3A, 0x8E, 0x01, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, + 0x64, 0x40, 0xF2, 0x3A, 0x88, 0x01, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x3A, + 0xDC, 0x00, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x3A, 0xD6, 0x00, 0xDD, 0x81, + 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x3A, 0xD0, 0x00, 0x60, 0x5C, 0x00, 0x36, 0x39, 0x00, + 0x00, 0x64, 0xF2, 0x60, 0x58, 0x4E, 0x57, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x08, 0x26, 0xF7, 0x01, + 0x2D, 0x60, 0xD6, 0x62, 0xA2, 0xDB, 0x64, 0x40, 0x00, 0x36, 0x31, 0x00, 0xDD, 0x81, 0xA1, 0xD3, + 0xDD, 0x81, 0xF2, 0x60, 0x58, 0x4E, 0x57, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x08, 0x26, 0xF5, 0x01, + 0x2D, 0x60, 0xD8, 0x62, 0xA2, 0xDB, 0x64, 0x40, 0x00, 0x36, 0x27, 0x00, 0xDD, 0x81, 0xA1, 0xD3, + 0xDD, 0x81, 0xF2, 0x60, 0x58, 0x4E, 0x57, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x08, 0x26, 0xF5, 0x01, + 0x2D, 0x60, 0xDA, 0x62, 0xA2, 0xDB, 0x64, 0x40, 0x00, 0x36, 0x1D, 0x00, 0xDD, 0x81, 0xA1, 0xD1, + 0x2D, 0x60, 0xDC, 0x62, 0xA2, 0xD9, 0xDD, 0x81, 0xA1, 0xD1, 0x2D, 0x60, 0xDD, 0x62, 0xA2, 0xD9, + 0x18, 0x00, 0x20, 0xFE, 0x2D, 0x60, 0xD6, 0x62, 0x00, 0x60, 0x04, 0x64, 0xA2, 0xDB, 0x20, 0xFE, + 0x2D, 0x60, 0xD8, 0x62, 0x00, 0x60, 0x04, 0x64, 0xA2, 0xDB, 0x20, 0xFE, 0x2D, 0x60, 0xDA, 0x62, + 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, 0x20, 0xFE, 0x2D, 0x60, 0xDC, 0x62, 0x00, 0x60, 0x00, 0x64, + 0xA2, 0xDB, 0x20, 0xFE, 0x02, 0x60, 0x00, 0x65, 0x2D, 0x60, 0x9E, 0x63, 0xD5, 0x84, 0xDC, 0x84, + 0xBD, 0xDB, 0x60, 0x41, 0x66, 0x44, 0x63, 0x46, 0xCD, 0x83, 0xC7, 0x81, 0x60, 0x45, 0x60, 0xFE, + 0x5D, 0x93, 0xA3, 0xD3, 0x5D, 0x93, 0xA6, 0xDB, 0xDE, 0x86, 0xFA, 0x1F, 0x66, 0x43, 0x65, 0x46, + 0x20, 0xFE, 0x20, 0xFE, 0x2D, 0x60, 0xE4, 0x62, 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x43, 0x00, 0x64, + 0x2D, 0x60, 0xCE, 0x61, 0xA1, 0xDB, 0x2D, 0x60, 0xC2, 0x62, 0xA2, 0xD1, 0x2D, 0x60, 0xD6, 0x62, + 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0x84, 0xFF, 0xFF, 0x10, 0x26, 0x07, 0x00, 0x04, 0x26, 0x07, 0x00, + 0x20, 0x26, 0x07, 0x00, 0x02, 0x26, 0x07, 0x00, 0x48, 0x00, 0x10, 0x7C, 0x05, 0x00, 0x04, 0x7C, + 0x03, 0x00, 0x20, 0x7C, 0x01, 0x00, 0x02, 0x7C, 0x2D, 0x60, 0xCE, 0x61, 0xA1, 0xD9, 0x50, 0x94, + 0x2D, 0x60, 0xD0, 0x61, 0xA1, 0xDB, 0x2D, 0x60, 0xC4, 0x61, 0xA1, 0xD1, 0x2D, 0x60, 0xD8, 0x61, + 0xA1, 0xD3, 0x2D, 0x60, 0xCE, 0x61, 0xA0, 0x84, 0xA1, 0xD1, 0xFF, 0xFF, 0x10, 0x26, 0x05, 0x00, + 0x04, 0x26, 0x05, 0x00, 0x01, 0x26, 0x08, 0x00, 0x28, 0x00, 0x10, 0x7C, 0x06, 0x00, 0x64, 0x40, + 0x10, 0x26, 0x23, 0x00, 0x04, 0x7C, 0x01, 0x00, 0x01, 0x7C, 0x2D, 0x60, 0xD0, 0x61, 0xA1, 0xD9, + 0x50, 0x94, 0x2D, 0x60, 0xD2, 0x61, 0xA1, 0xDB, 0x2D, 0x60, 0xC6, 0x61, 0xA1, 0xD1, 0x2D, 0x60, + 0xDA, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0xA0, 0x84, 0x60, 0x40, 0x02, 0x26, 0x05, 0x00, 0x04, 0x26, + 0x05, 0x00, 0x01, 0x26, 0x05, 0x00, 0x09, 0x00, 0x02, 0x7C, 0x03, 0x00, 0x04, 0x7C, 0x01, 0x00, + 0x20, 0x7C, 0x2D, 0x60, 0xD2, 0x61, 0xA1, 0xD9, 0x0D, 0x00, 0x50, 0x94, 0x2D, 0x60, 0xCE, 0x62, + 0xA2, 0xDB, 0x2D, 0x60, 0xD0, 0x62, 0xA2, 0xDB, 0x2D, 0x60, 0xD2, 0x62, 0xA2, 0xDB, 0x2D, 0x60, + 0xD4, 0x62, 0xA2, 0xDB, 0x7C, 0x44, 0x2D, 0x60, 0xCE, 0x61, 0xA1, 0xD1, 0xBD, 0xD9, 0x2D, 0x60, + 0xD0, 0x61, 0xA1, 0xD1, 0xB0, 0x84, 0xBD, 0xD9, 0x2D, 0x60, 0xD2, 0x61, 0xA1, 0xD1, 0xB0, 0x84, + 0xBD, 0xD9, 0x2D, 0x60, 0xC8, 0x61, 0xA1, 0xD1, 0xB0, 0x84, 0xBD, 0xD9, 0x08, 0x28, 0x68, 0x00, + 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xFF, 0xA0, 0xFF, 0xFF, 0x0C, 0x24, 0x60, 0x00, + 0x60, 0x40, 0x0B, 0x36, 0x5D, 0x00, 0x20, 0x40, 0x10, 0x27, 0x5A, 0x00, 0x88, 0x00, 0x20, 0xFE, + 0x00, 0x65, 0x60, 0xFE, 0x2D, 0x60, 0xDE, 0x62, 0xA2, 0xDB, 0xE0, 0x84, 0xE0, 0x84, 0x08, 0x20, + 0x03, 0x00, 0x01, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x02, 0xA5, 0x64, 0x44, 0xD4, 0x9C, 0xD4, 0x80, + 0x2D, 0x60, 0xE0, 0x62, 0x02, 0x05, 0x08, 0x65, 0x41, 0x00, 0xA2, 0xD9, 0x7C, 0x44, 0x2D, 0x60, + 0xE2, 0x62, 0xA2, 0xDB, 0xDD, 0x81, 0xA1, 0xD1, 0x00, 0x65, 0x64, 0x40, 0x00, 0x3A, 0x01, 0x65, + 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x50, 0x3A, 0x01, 0x65, 0xDD, 0x81, 0xA1, 0xD1, + 0xFF, 0xFF, 0x64, 0x40, 0xF2, 0x3A, 0x01, 0x65, 0xDD, 0x81, 0xA1, 0xD1, 0x65, 0x40, 0x00, 0x3A, + 0x18, 0x00, 0x00, 0x60, 0x00, 0x65, 0x64, 0x40, 0x00, 0x36, 0x01, 0x65, 0x64, 0x40, 0x01, 0x36, + 0x02, 0x65, 0x64, 0x40, 0x02, 0x36, 0x04, 0x65, 0x64, 0x40, 0x04, 0x36, 0x10, 0x65, 0x64, 0x40, + 0x05, 0x36, 0x20, 0x65, 0x65, 0x5C, 0x2D, 0x60, 0xE2, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xB0, 0x84, + 0xA2, 0xDB, 0x2D, 0x60, 0xDE, 0x62, 0xA2, 0xD3, 0x00, 0x65, 0xFF, 0xA4, 0xA2, 0xDB, 0xCA, 0x02, + 0x2D, 0x60, 0xE2, 0x62, 0xA2, 0xD3, 0x2D, 0x60, 0xE0, 0x62, 0xA2, 0xD1, 0x2E, 0x58, 0xFF, 0xFF, + 0x20, 0xFE, 0x8A, 0xF3, 0xFF, 0xFF, 0x3A, 0xA4, 0x8A, 0xFB, 0x3D, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x89, 0xF3, 0x7F, 0xF1, 0x04, 0xA4, 0x89, 0xFB, 0x12, 0x60, 0x22, 0x63, 0x53, 0xF3, 0x64, 0x41, + 0x08, 0xB0, 0xE1, 0x85, 0x1C, 0x03, 0xFE, 0xA1, 0x47, 0xD3, 0x02, 0x06, 0xFB, 0xB4, 0xA3, 0xDB, + 0xDD, 0x81, 0x5B, 0xD3, 0x0C, 0x24, 0x02, 0x00, 0xFB, 0xB4, 0xA3, 0xDB, 0x5B, 0xD3, 0xDD, 0x81, + 0x02, 0xBC, 0xA3, 0xDB, 0x0E, 0x65, 0xDD, 0x81, 0xD5, 0x80, 0x5B, 0xD3, 0x08, 0x05, 0xFB, 0xB4, + 0xA3, 0xDB, 0xDD, 0x81, 0xD5, 0x80, 0x5B, 0xD3, 0x02, 0x03, 0xFB, 0xB4, 0xA3, 0xDB, 0xFF, 0xFF, + 0x20, 0xFE, 0x26, 0x46, 0x31, 0x40, 0x20, 0x2A, 0x18, 0x00, 0x3F, 0xF2, 0x47, 0x65, 0xC4, 0x84, + 0xE8, 0x84, 0x23, 0xFA, 0xF1, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, + 0x64, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xFA, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, + 0x16, 0x63, 0x1C, 0x60, 0x8C, 0x62, 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0x5B, 0xFB, 0x5C, 0xFB, + 0x1C, 0x60, 0x92, 0x63, 0x02, 0x64, 0xA3, 0xDB, 0x1A, 0x60, 0xC6, 0x62, 0x3E, 0x63, 0x00, 0x64, + 0x5A, 0xDB, 0xFE, 0x1F, 0x2E, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0x98, 0x62, 0xA2, 0xD3, 0x00, 0x63, + 0xF8, 0xA0, 0x01, 0xA4, 0x03, 0x03, 0xA2, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0xA2, 0xDD, 0x1C, 0x60, + 0x9A, 0x62, 0xA2, 0xD1, 0xA2, 0xDD, 0x5A, 0xD3, 0xA2, 0xDD, 0xC0, 0x81, 0x61, 0x44, 0x02, 0x24, + 0xFF, 0xFF, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0x5A, 0xD3, 0xE9, 0x81, 0xE8, 0x83, + 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x85, 0xD4, 0x85, 0xC5, 0x83, 0xA2, 0xDD, 0x1C, 0x60, + 0x8E, 0x62, 0x63, 0x47, 0x00, 0x7F, 0xA2, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0xA0, 0x65, + 0xA5, 0xDD, 0x1B, 0x60, 0x46, 0x65, 0x61, 0x44, 0x2B, 0x41, 0x45, 0xDB, 0x60, 0x41, 0x1B, 0x60, + 0x86, 0x65, 0x0A, 0xA3, 0xA3, 0xD1, 0x2B, 0x44, 0x44, 0xD9, 0x1C, 0x60, 0xA0, 0x65, 0xA5, 0xD3, + 0xFF, 0xFF, 0x60, 0x43, 0x00, 0xB9, 0xFF, 0xFF, 0x4C, 0x03, 0x06, 0xA3, 0xBD, 0xD1, 0x81, 0xF3, + 0x82, 0xF1, 0xD0, 0x80, 0xBD, 0xD3, 0x22, 0x02, 0x83, 0xF3, 0xD0, 0x80, 0xA3, 0xD1, 0x1E, 0x02, + 0xD0, 0x80, 0xFF, 0xFF, 0x1B, 0x02, 0x8A, 0xF3, 0x12, 0x60, 0x46, 0x63, 0xC6, 0xA5, 0x47, 0xD1, + 0x7F, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x08, 0x28, 0xFF, 0x61, 0x61, 0x43, 0x1A, 0x60, + 0xC6, 0x65, 0x2B, 0x44, 0x44, 0xD1, 0x1C, 0x60, 0x8E, 0x65, 0xA5, 0xD1, 0x64, 0x44, 0xD0, 0x81, + 0x1C, 0x60, 0x92, 0x65, 0x01, 0x05, 0x00, 0x61, 0xA5, 0xD3, 0x15, 0x00, 0x1A, 0x60, 0xC6, 0x65, + 0x2B, 0x44, 0x44, 0xD1, 0x1C, 0x60, 0x8E, 0x65, 0x64, 0x43, 0xA5, 0xD1, 0x64, 0x65, 0x63, 0x44, + 0xC0, 0x84, 0xD4, 0x80, 0xFF, 0xFF, 0x02, 0x06, 0x00, 0x61, 0x13, 0x00, 0x61, 0x43, 0xD0, 0x81, + 0x1C, 0x60, 0x92, 0x65, 0xA5, 0xD3, 0xE9, 0x81, 0xE9, 0x81, 0xCC, 0x84, 0xCC, 0x84, 0x02, 0x03, + 0x02, 0x03, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x85, 0xD7, 0x84, 0x60, 0x41, 0x01, 0x05, + 0x00, 0x61, 0x1C, 0x60, 0xA0, 0x65, 0xA5, 0xD3, 0xFF, 0xFF, 0x60, 0x43, 0x2E, 0x58, 0xFF, 0xFF, + 0x1C, 0x60, 0x94, 0x65, 0xA5, 0xD1, 0x5B, 0xF3, 0x64, 0x41, 0xCD, 0x81, 0xCD, 0x81, 0x02, 0x03, + 0x02, 0x03, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x85, 0x29, 0x44, 0x54, 0x89, 0x2E, 0x58, + 0xFF, 0xFF, 0xED, 0xF3, 0x1A, 0x60, 0xBE, 0x63, 0x0F, 0xB4, 0x01, 0xA4, 0xE0, 0x87, 0xE0, 0x84, + 0xE0, 0x84, 0xBD, 0xDB, 0x10, 0x60, 0x58, 0x64, 0xBD, 0xDB, 0x02, 0x64, 0xBD, 0xDB, 0x06, 0x64, + 0xA3, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0xBA, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0x2E, 0x58, 0xFF, 0xFF, 0x1A, 0x60, 0xBE, 0x63, 0xEA, 0x60, 0x60, 0x64, + 0xBD, 0xDB, 0x10, 0x60, 0x58, 0x64, 0xBD, 0xDB, 0x02, 0x64, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, + 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0xBA, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0x2E, 0x58, 0xFF, 0xFF, 0x16, 0x63, 0x1C, 0x60, 0x8C, 0x62, 0x00, 0x64, 0x5A, 0xDB, + 0xFE, 0x1F, 0x5B, 0xFB, 0x5C, 0xFB, 0x1C, 0x60, 0x92, 0x63, 0x02, 0x64, 0xA3, 0xDB, 0x1A, 0x60, + 0xC6, 0x62, 0x3E, 0x63, 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0x10, 0x60, 0x56, 0x62, 0xF5, 0x60, + 0x29, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x2C, 0x62, 0xF5, 0x60, 0x15, 0x64, 0xA2, 0xDB, 0x10, 0x60, + 0x02, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x04, 0x62, 0x00, 0x60, 0x04, 0x64, 0xA2, 0xDB, + 0xF4, 0x60, 0x16, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x20, 0x44, 0x40, 0x26, + 0x03, 0x00, 0xF4, 0x60, 0xEA, 0x78, 0xFF, 0xFF, 0x20, 0x40, 0x52, 0x23, 0x07, 0x00, 0x5A, 0xF3, + 0xFF, 0xFF, 0x01, 0xA4, 0x5A, 0xFB, 0xF4, 0x60, 0xD7, 0x78, 0xFF, 0xFF, 0x40, 0x60, 0x00, 0x65, + 0x20, 0x44, 0x34, 0x80, 0x1C, 0x60, 0x92, 0x65, 0x02, 0x64, 0xA5, 0xDB, 0x1A, 0x60, 0xC4, 0x62, + 0x7E, 0x63, 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0x1C, 0x60, 0x96, 0x62, 0xA2, 0xDD, 0x8C, 0xF3, + 0x58, 0xFB, 0x02, 0x64, 0x8C, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x8C, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, + 0xFF, 0xFF, 0x0B, 0x03, 0x10, 0x60, 0x04, 0x62, 0x80, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xF4, 0x60, + 0x3D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x04, 0x64, 0x53, 0xFB, 0x29, 0x60, + 0xA4, 0x64, 0x54, 0xFB, 0x0F, 0x4E, 0xEC, 0x60, 0x58, 0x4F, 0xB9, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, + 0x10, 0x60, 0x02, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x04, 0x62, 0x10, 0x60, 0x00, 0x64, + 0xA2, 0xDB, 0xF4, 0x60, 0x67, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x58, 0xF3, + 0x8C, 0xFB, 0xCA, 0xFE, 0xC1, 0xFE, 0x1C, 0x60, 0xA2, 0x62, 0x66, 0x44, 0xA2, 0xDB, 0x5A, 0xDD, + 0x61, 0x44, 0x5A, 0xDB, 0x67, 0xF5, 0xCC, 0xF1, 0x19, 0xF8, 0xF8, 0x60, 0x80, 0x64, 0x0E, 0xFA, + 0xA9, 0xF1, 0x07, 0xF8, 0x01, 0x60, 0x60, 0x67, 0x2C, 0xFA, 0x1D, 0x64, 0x2D, 0xFA, 0x01, 0x64, + 0x2E, 0xFA, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0x81, 0xF1, + 0x32, 0xF8, 0x82, 0xF1, 0x33, 0xF8, 0x83, 0xF1, 0x34, 0xF8, 0x08, 0x64, 0x2A, 0xFA, 0x40, 0x63, + 0x3F, 0xFC, 0x00, 0xF4, 0x02, 0x62, 0xCB, 0x83, 0x00, 0x64, 0x5A, 0xDA, 0xFE, 0x1F, 0x1C, 0x60, + 0x8E, 0x65, 0xA5, 0xD3, 0x02, 0xFA, 0x19, 0x60, 0x88, 0x64, 0xA0, 0xD1, 0x0A, 0x61, 0x41, 0xD3, + 0x03, 0xFA, 0x06, 0x61, 0x06, 0x63, 0x00, 0x65, 0x1B, 0x60, 0x86, 0x64, 0x44, 0xD1, 0x59, 0xD8, + 0x1B, 0x60, 0x46, 0x64, 0x44, 0xD1, 0x59, 0xD8, 0x1A, 0x60, 0xC6, 0x64, 0x44, 0xD1, 0x59, 0xD8, + 0x1B, 0x60, 0x06, 0x64, 0x44, 0xD1, 0x59, 0xD8, 0x65, 0x44, 0x02, 0xA4, 0x60, 0x45, 0xEC, 0x1F, + 0x67, 0xF5, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x22, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x1C, 0x60, 0xA2, 0x62, 0xA2, 0xD5, 0x5A, 0xD3, + 0x5A, 0xD3, 0x60, 0x43, 0x60, 0x41, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x20, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xBF, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0xF3, 0x60, + 0x58, 0x4E, 0xD4, 0x78, 0xFF, 0xFF, 0x10, 0x60, 0x02, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, + 0x04, 0x62, 0x10, 0x60, 0x02, 0x64, 0xA2, 0xDB, 0xF4, 0x60, 0x16, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0xA4, 0x63, 0x66, 0x44, 0xA3, 0xDB, 0x00, 0x60, 0x40, 0x61, + 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x67, 0xFB, 0x04, 0x64, 0x03, 0xFA, + 0x1C, 0x60, 0xA4, 0x63, 0xA3, 0xD1, 0x00, 0x64, 0x64, 0x46, 0xA3, 0xDB, 0x00, 0x60, 0x40, 0x65, + 0x20, 0x44, 0x34, 0x80, 0xF3, 0x60, 0x58, 0x4E, 0xB9, 0x78, 0xFF, 0xFF, 0x10, 0x60, 0x02, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x04, 0x62, 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, 0xF4, 0x60, + 0x16, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, + 0xBA, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x10, 0x60, 0x02, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0xFF, 0x60, 0x9F, 0x65, 0x20, 0x44, 0x24, 0x80, 0x2F, 0x58, + 0xFF, 0xFF, 0x10, 0x60, 0x02, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + +}; /* fw_image_4_data */ + +static const CFG_IDENTITY_STRCT fw_image_infoidentity[] = { + { + sizeof( CFG_IDENTITY_STRCT ) / sizeof(hcf_16) - 1, + CFG_FW_IDENTITY, + COMP_ID_FW_STA, + 3, //Variant + 2, //Major + 36 //Minor + }, + { 0000, 0000, 0000, 0000, 0000, 0000 } //endsentinel +}; + +static const CFG_PROG_STRCT fw_image_code[] = { + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0x0186, // sizeof(fw_image_1_data), + 0x00000060, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_1_data + }, + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0x2518, // sizeof(fw_image_2_data), + 0x00000C16, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_2_data + }, + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0x3daa, // sizeof(fw_image_3_data), + 0x001E312E, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_3_data + }, + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0xaa66, // sizeof(fw_image_4_data), + 0x001F4000, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_4_data + }, + { + 5, + CFG_PROG, + CFG_PROG_STOP, // mode + 0000, + 0x000F368E, // Start execution address + }, + { 0000, 0000, 0000, 0000, 00000000, 0000, 00000000} +}; + +static const CFG_RANGE20_STRCT fw_image_infocompat[] = { + { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), + CFG_FW_SUP_RANGE, + COMP_ROLE_SUPL, + COMP_ID_STA, + { + { 2, 2, 5 } //variant, bottom, top + } + }, + { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), + CFG_MFI_ACT_RANGES_STA, + COMP_ROLE_ACT, + COMP_ID_MFI, + { + { 4, 6, 7 }, //variant, bottom, top + { 5, 6, 7 }, //variant, bottom, top + { 6, 6, 7 } //variant, bottom, top + } + }, + { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), + CFG_CFI_ACT_RANGES_STA, + COMP_ROLE_ACT, + COMP_ID_CFI, + { + { 2, 1, 2 } //variant, bottom, top + } + }, + { 0000, 0000, 0000, 0000, { { 0000, 0000, 0000 } } } //endsentinel +}; + +memimage fw_image = { + "FUPU7D37dhfwci\001C", //signature, , C/Bin type + (CFG_PROG_STRCT *) fw_image_code, + 0x000F368E, + 00000000, //(dummy) pdaplug + 00000000, //(dummy) priplug + (CFG_RANGE20_STRCT *) fw_image_infocompat, + (CFG_IDENTITY_STRCT *) fw_image_infoidentity, +}; + diff --git a/drivers/staging/wlags49_h2/sta_h25.c b/drivers/staging/wlags49_h2/sta_h25.c new file mode 100644 index 0000000000000000000000000000000000000000..86ca1cdd849712b02db845d996082d8f90b8860e --- /dev/null +++ b/drivers/staging/wlags49_h2/sta_h25.c @@ -0,0 +1,5255 @@ +/* + * File: sta_h54.136 + * + * Abstract: This file contains memory image 'fw_image'. + * + * Contents: Total size of the memory image: 81742 bytes. + * Total number of blocks: 4 blocks. + * Block 1 : load address 00000060, 388 bytes. + * Block 2 : load address 00000C16, 11278 bytes. + * Block 3 : load address 001E3824, 21726 bytes. + * Block 4 : load address 001F4000, 48350 bytes. + * + * Identity: component id: 31 (variant 4) version 1.36 + * + * Compatibility: + * supplying interface 4 (variant 4) : 1 - 2 + * acting on interface 1 (variant 7) : 3 - 3 + * acting on interface 1 (variant 8) : 1 - 1 + * acting on interface 2 (variant 4) : 1 - 2 + * + * Generated: by g:\fw\fupu3.exe version 4.26 + * + * Commandline: g:\fw\fupu3.exe /f=4 /n=fw_image /i=r4013600.hex + */ + + +#include "hcfcfg.h" // to get hcf_16 etc defined as well as + // possible settings which inluence mdd.h or dhf.h +#include "mdd.h" //to get COMP_ID_STA etc defined +#include "dhf.h" //used to be "fhfmem.h", to get memblock,plugrecord, + +static const hcf_8 fw_image_1_data[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDA, 0x0C, 0x00, 0x00, + 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x65, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x1B, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x1B, 0xB2, 0x1B, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0xFF, 0x07, + 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, 0x10, 0x27, 0x10, 0x27, 0x14, 0x00, 0xD0, 0x07, 0xD0, 0x07, + 0x10, 0x27, 0x2F, 0x00, 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, 0x02, 0x00, 0x02, 0x00, 0x10, 0x27, + 0x05, 0x00, 0x00, 0x02, 0x00, 0x02, 0x13, 0x00, 0x07, 0x00, 0x03, 0x00, 0x32, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x09, 0x2B, 0x09, 0x2B, 0x09, 0xFF, 0x0F, 0xF0, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x40, 0x00, 0x32, 0x00, 0x32, 0x00, 0x0A, 0x00, + 0x02, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + +}; /* fw_image_1_data */ + +static const hcf_8 fw_image_2_data[] = { + 0xF4, 0xA3, 0x00, 0x16, 0x08, 0x40, 0x0F, 0xD2, 0xE1, 0x28, 0xA5, 0x7C, 0x50, 0x30, 0xF1, 0x84, + 0x44, 0x08, 0xAB, 0xAE, 0xA5, 0xB8, 0xFC, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x84, 0xF8, 0x99, 0xEE, + 0x8D, 0xF6, 0x0D, 0xFF, 0xBD, 0xD6, 0xB1, 0xDE, 0x54, 0x91, 0x50, 0x60, 0x03, 0x02, 0xA9, 0xCE, + 0x7D, 0x56, 0x19, 0xE7, 0x62, 0xB5, 0xE6, 0x4D, 0x9A, 0xEC, 0x45, 0x8F, 0x9D, 0x1F, 0x40, 0x89, + 0x87, 0xFA, 0x15, 0xEF, 0xEB, 0xB2, 0xC9, 0x8E, 0x0B, 0xFB, 0xEC, 0x41, 0x67, 0xB3, 0xFD, 0x5F, + 0xEA, 0x45, 0xBF, 0x23, 0xF7, 0x53, 0x96, 0xE4, 0x5B, 0x9B, 0xC2, 0x75, 0x1C, 0xE1, 0xAE, 0x3D, + 0x6A, 0x4C, 0x5A, 0x6C, 0x41, 0x7E, 0x02, 0xF5, 0x4F, 0x83, 0x5C, 0x68, 0xF4, 0x51, 0x34, 0xD1, + 0x08, 0xF9, 0x93, 0xE2, 0x73, 0xAB, 0x53, 0x62, 0x3F, 0x2A, 0x0C, 0x08, 0x52, 0x95, 0x65, 0x46, + 0x5E, 0x9D, 0x28, 0x30, 0xA1, 0x37, 0x0F, 0x0A, 0xB5, 0x2F, 0x09, 0x0E, 0x36, 0x24, 0x9B, 0x1B, + 0x3D, 0xDF, 0x26, 0xCD, 0x69, 0x4E, 0xCD, 0x7F, 0x9F, 0xEA, 0x1B, 0x12, 0x9E, 0x1D, 0x74, 0x58, + 0x2E, 0x34, 0x2D, 0x36, 0xB2, 0xDC, 0xEE, 0xB4, 0xFB, 0x5B, 0xF6, 0xA4, 0x4D, 0x76, 0x61, 0xB7, + 0xCE, 0x7D, 0x7B, 0x52, 0x3E, 0xDD, 0x71, 0x5E, 0x97, 0x13, 0xF5, 0xA6, 0x68, 0xB9, 0x00, 0x00, + 0x2C, 0xC1, 0x60, 0x40, 0x1F, 0xE3, 0xC8, 0x79, 0xED, 0xB6, 0xBE, 0xD4, 0x46, 0x8D, 0xD9, 0x67, + 0x4B, 0x72, 0xDE, 0x94, 0xD4, 0x98, 0xE8, 0xB0, 0x4A, 0x85, 0x6B, 0xBB, 0x2A, 0xC5, 0xE5, 0x4F, + 0x16, 0xED, 0xC5, 0x86, 0xD7, 0x9A, 0x55, 0x66, 0x94, 0x11, 0xCF, 0x8A, 0x10, 0xE9, 0x06, 0x04, + 0x81, 0xFE, 0xF0, 0xA0, 0x44, 0x78, 0xBA, 0x25, 0xE3, 0x4B, 0xF3, 0xA2, 0xFE, 0x5D, 0xC0, 0x80, + 0x8A, 0x05, 0xAD, 0x3F, 0xBC, 0x21, 0x48, 0x70, 0x04, 0xF1, 0xDF, 0x63, 0xC1, 0x77, 0x75, 0xAF, + 0x63, 0x42, 0x30, 0x20, 0x1A, 0xE5, 0x0E, 0xFD, 0x6D, 0xBF, 0x4C, 0x81, 0x14, 0x18, 0x35, 0x26, + 0x2F, 0xC3, 0xE1, 0xBE, 0xA2, 0x35, 0xCC, 0x88, 0x39, 0x2E, 0x57, 0x93, 0xF2, 0x55, 0x82, 0xFC, + 0x47, 0x7A, 0xAC, 0xC8, 0xE7, 0xBA, 0x2B, 0x32, 0x95, 0xE6, 0xA0, 0xC0, 0x98, 0x19, 0xD1, 0x9E, + 0x7F, 0xA3, 0x66, 0x44, 0x7E, 0x54, 0xAB, 0x3B, 0x83, 0x0B, 0xCA, 0x8C, 0x29, 0xC7, 0xD3, 0x6B, + 0x3C, 0x28, 0x79, 0xA7, 0xE2, 0xBC, 0x1D, 0x16, 0x76, 0xAD, 0x3B, 0xDB, 0x56, 0x64, 0x4E, 0x74, + 0x1E, 0x14, 0xDB, 0x92, 0x0A, 0x0C, 0x6C, 0x48, 0xE4, 0xB8, 0x5D, 0x9F, 0x6E, 0xBD, 0xEF, 0x43, + 0xA6, 0xC4, 0xA8, 0x39, 0xA4, 0x31, 0x37, 0xD3, 0x8B, 0xF2, 0x32, 0xD5, 0x43, 0x8B, 0x59, 0x6E, + 0xB7, 0xDA, 0x8C, 0x01, 0x64, 0xB1, 0xD2, 0x9C, 0xE0, 0x49, 0xB4, 0xD8, 0xFA, 0xAC, 0x07, 0xF3, + 0x25, 0xCF, 0xAF, 0xCA, 0x8E, 0xF4, 0xE9, 0x47, 0x18, 0x10, 0xD5, 0x6F, 0x88, 0xF0, 0x6F, 0x4A, + 0x72, 0x5C, 0x24, 0x38, 0xF1, 0x57, 0xC7, 0x73, 0x51, 0x97, 0x23, 0xCB, 0x7C, 0xA1, 0x9C, 0xE8, + 0x21, 0x3E, 0xDD, 0x96, 0xDC, 0x61, 0x86, 0x0D, 0x85, 0x0F, 0x90, 0xE0, 0x42, 0x7C, 0xC4, 0x71, + 0xAA, 0xCC, 0xD8, 0x90, 0x05, 0x06, 0x01, 0xF7, 0x12, 0x1C, 0xA3, 0xC2, 0x5F, 0x6A, 0xF9, 0xAE, + 0xD0, 0x69, 0x91, 0x17, 0x58, 0x99, 0x27, 0x3A, 0xB9, 0x27, 0x38, 0xD9, 0x13, 0xEB, 0xB3, 0x2B, + 0x33, 0x22, 0xBB, 0xD2, 0x70, 0xA9, 0x89, 0x07, 0xA7, 0x33, 0xB6, 0x2D, 0x22, 0x3C, 0x92, 0x15, + 0x20, 0xC9, 0x49, 0x87, 0xFF, 0xAA, 0x78, 0x50, 0x7A, 0xA5, 0x8F, 0x03, 0xF8, 0x59, 0x80, 0x09, + 0x17, 0x1A, 0xDA, 0x65, 0x31, 0xD7, 0xC6, 0x84, 0xB8, 0xD0, 0xC3, 0x82, 0xB0, 0x29, 0x77, 0x5A, + 0x11, 0x1E, 0xCB, 0x7B, 0xFC, 0xA8, 0xD6, 0x6D, 0x3A, 0x2C, 0x00, 0x30, 0x00, 0x31, 0x00, 0x33, + 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x38, 0x00, 0x3A, 0x00, 0x3B, + 0x00, 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, 0x3F, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x28, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x02, 0x14, 0x05, 0x32, 0x0B, 0x37, 0x08, 0x50, 0x0B, 0x6E, + 0x02, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x16, 0x00, 0x0C, 0x00, 0x12, 0x00, 0x18, 0x00, 0x24, 0x00, + 0x30, 0x00, 0x48, 0x00, 0x60, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x39, 0x00, 0x20, 0x00, 0x39, 0x00, 0x39, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x10, + 0x3E, 0x11, 0xF6, 0x10, 0x38, 0x11, 0xFC, 0x10, 0x32, 0x11, 0x02, 0x11, 0x2C, 0x11, 0x08, 0x11, + 0x26, 0x11, 0x0E, 0x11, 0x20, 0x11, 0x14, 0x11, 0x1A, 0x11, 0x07, 0x01, 0x00, 0x00, 0x16, 0x22, + 0x00, 0x04, 0x08, 0x01, 0x00, 0x00, 0x16, 0x26, 0x00, 0x04, 0x09, 0x01, 0x00, 0x00, 0x16, 0x2A, + 0x00, 0x04, 0x0A, 0x01, 0x00, 0x00, 0x16, 0x2E, 0x00, 0x04, 0x0B, 0x01, 0x00, 0x00, 0x10, 0x24, + 0x04, 0x04, 0x0C, 0x01, 0x00, 0x00, 0x10, 0x28, 0x04, 0x04, 0x0D, 0x01, 0x00, 0x00, 0x10, 0x2C, + 0x04, 0x04, 0x0E, 0x01, 0x00, 0x00, 0x10, 0x30, 0x04, 0x04, 0x0F, 0x01, 0x00, 0x00, 0x14, 0x34, + 0x08, 0x84, 0x10, 0x01, 0x00, 0x00, 0x14, 0x38, 0x08, 0x84, 0x11, 0x01, 0x00, 0x00, 0x14, 0x3C, + 0x08, 0x84, 0x12, 0x01, 0x00, 0x00, 0x14, 0x40, 0x08, 0x84, 0x13, 0x01, 0x00, 0x00, 0x17, 0x64, + 0x0C, 0x8B, 0x14, 0x01, 0x00, 0x00, 0x17, 0x68, 0x0C, 0x8B, 0x15, 0x01, 0x00, 0x00, 0x17, 0x6C, + 0x0C, 0x8B, 0x16, 0x01, 0x00, 0x00, 0x17, 0x70, 0x0C, 0x8B, 0x17, 0x01, 0x00, 0x00, 0x17, 0x74, + 0x0C, 0x8B, 0x18, 0x01, 0x00, 0x00, 0x17, 0x78, 0x0C, 0x8B, 0x19, 0x01, 0x00, 0x00, 0x17, 0x7C, + 0x0C, 0x8B, 0x1A, 0x01, 0x00, 0x00, 0x17, 0x80, 0x0C, 0x8B, 0x1B, 0x01, 0x00, 0x00, 0x17, 0x84, + 0x0C, 0x8B, 0x1C, 0x01, 0x00, 0x00, 0x17, 0x88, 0x0C, 0x8B, 0x1D, 0x01, 0x00, 0x00, 0x17, 0x8C, + 0x0C, 0x8B, 0x1E, 0x01, 0x00, 0x00, 0x0E, 0x95, 0x17, 0x04, 0x1F, 0x01, 0x00, 0x00, 0x0E, 0x99, + 0x17, 0x04, 0x20, 0x01, 0x00, 0x00, 0x0E, 0x9D, 0x17, 0x04, 0x21, 0x01, 0x00, 0x00, 0x0E, 0xA1, + 0x17, 0x04, 0x22, 0x01, 0x00, 0x00, 0x0E, 0xA5, 0x00, 0x00, 0x60, 0x11, 0x80, 0x11, 0xA0, 0x11, + 0xC0, 0x11, 0x18, 0x12, 0x68, 0x11, 0x88, 0x11, 0xA8, 0x11, 0xC8, 0x11, 0x20, 0x12, 0x70, 0x11, + 0x90, 0x11, 0xB0, 0x11, 0xD0, 0x11, 0x28, 0x12, 0x78, 0x11, 0x98, 0x11, 0xB8, 0x11, 0xD8, 0x11, + 0x30, 0x12, 0xE0, 0x11, 0xE8, 0x11, 0xF0, 0x11, 0xF8, 0x11, 0x00, 0x12, 0x08, 0x12, 0x10, 0x12, + 0x38, 0x12, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x0A, 0x0A, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x1E, 0x1E, 0x1E, 0x1E, + 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0A, 0x0A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x10, 0x10, + 0x10, 0x10, 0x17, 0x17, 0x17, 0x17, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x11, 0x11, 0x11, 0x11, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x16, 0x16, + 0x16, 0x16, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x0A, + 0x0A, 0x0A, 0x0A, 0x7F, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x10, 0x10, 0x10, 0x10, 0x7F, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x0A, 0x0A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x9D, 0x9D, 0xA1, 0xB4, + 0x10, 0x10, 0x00, 0x9D, 0x08, 0x02, 0x06, 0x00, 0xA5, 0xA5, 0xAA, 0xB4, 0x10, 0x10, 0x00, 0xA2, + 0x15, 0x05, 0x07, 0x00, 0xAA, 0xAA, 0xB4, 0xB4, 0x10, 0x10, 0x00, 0xA7, 0x1C, 0x0A, 0x08, 0x00, + 0xB7, 0xB7, 0xC1, 0xC1, 0x10, 0x10, 0x00, 0xB4, 0x29, 0x17, 0x08, 0x00, 0xBD, 0xBD, 0xC7, 0xC7, + 0x10, 0x10, 0x00, 0xBA, 0x2F, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0x1F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x42, 0x2A, 0x5B, 0x2A, 0x7E, 0x2A, 0x71, 0x30, 0xEE, 0x29, 0x88, 0x30, 0xB8, 0x2A, + 0x9F, 0x30, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0x21, 0x35, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, + 0xEE, 0x29, 0xEE, 0x29, 0x93, 0x2C, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, + 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, + 0xEE, 0x29, 0xEE, 0x29, 0xDE, 0x2C, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, + 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, + 0xEE, 0x29, 0x61, 0x2C, 0x7C, 0x2C, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, + 0xEE, 0x29, 0xE1, 0x27, 0xD7, 0x2A, 0xEA, 0x2A, 0x9A, 0x2B, 0x9E, 0x2B, 0xEE, 0x29, 0xEE, 0x29, + 0x4D, 0x2C, 0xA1, 0xF2, 0x62, 0xF2, 0x00, 0x00, 0x99, 0xF2, 0xEE, 0xF2, 0x12, 0xF3, 0x48, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x2A, 0x94, 0x2A, 0x00, 0x00, 0x67, 0x30, 0x7E, 0x30, 0x95, 0x30, + 0xAF, 0x30, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC, 0x45, 0x2D, 0xF7, 0x2F, 0x5A, 0x00, 0x02, 0x00, + 0xF9, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0xFC, 0x00, 0x02, 0x00, 0xF7, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, + 0xAA, 0x2D, 0x06, 0x00, 0xF0, 0xFF, 0x45, 0x2D, 0x22, 0x2D, 0x00, 0x00, 0x00, 0x02, 0xF6, 0xFF, + 0x45, 0x2D, 0x5B, 0x2D, 0x6C, 0x00, 0x02, 0x00, 0xF4, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0xA6, 0x01, + 0x02, 0x00, 0xF5, 0xFF, 0x45, 0x2D, 0x00, 0x30, 0x9C, 0x2D, 0x02, 0x00, 0xED, 0xFF, 0x45, 0x2D, + 0x12, 0x30, 0x98, 0x32, 0x02, 0x00, 0xEC, 0xFF, 0x45, 0x2D, 0x40, 0x30, 0x9A, 0x32, 0x02, 0x00, + 0xEB, 0xFF, 0x45, 0x2D, 0x46, 0x30, 0x9C, 0x32, 0x02, 0x00, 0xEE, 0xFF, 0x45, 0x2D, 0x4C, 0x30, + 0x12, 0x33, 0x02, 0x00, 0xDA, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0xF2, 0x13, 0x0C, 0x00, 0xEA, 0xFF, + 0x45, 0x2D, 0x22, 0x2D, 0x4C, 0x33, 0x06, 0x00, 0xE9, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0x52, 0x33, + 0x02, 0x00, 0xE8, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0x54, 0x33, 0x02, 0x00, 0xE7, 0xFF, 0x45, 0x2D, + 0x5B, 0x2D, 0x56, 0x33, 0x02, 0x00, 0xE6, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0x58, 0x33, 0x02, 0x00, + 0xE5, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0x5A, 0x33, 0x10, 0x00, 0xE4, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, + 0x6A, 0x33, 0x18, 0x00, 0xDB, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0x82, 0x33, 0x02, 0x00, 0xDC, 0xFF, + 0x45, 0x2D, 0x5B, 0x2D, 0x84, 0x33, 0x02, 0x00, 0xE1, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0x5A, 0x34, + 0x02, 0x00, 0xE0, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0x58, 0x34, 0x02, 0x00, 0xE3, 0xFF, 0x45, 0x2D, + 0x5B, 0x2D, 0x3C, 0x34, 0x02, 0x00, 0xE2, 0xFF, 0x93, 0x2D, 0x22, 0x2D, 0xF2, 0x33, 0x24, 0x00, + 0x03, 0xFC, 0x45, 0x2D, 0x01, 0x2F, 0x8C, 0x32, 0x02, 0x00, 0x04, 0xFC, 0x45, 0x2D, 0x55, 0x2D, + 0xB4, 0x2D, 0x22, 0x00, 0x06, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x9A, 0x2D, 0x02, 0x00, 0x07, 0xFC, + 0x45, 0x2D, 0x5B, 0x2D, 0xF8, 0x2D, 0x02, 0x00, 0x0E, 0xFC, 0x45, 0x2D, 0x2A, 0x2F, 0x02, 0x2E, + 0x22, 0x00, 0xB1, 0xFC, 0x45, 0x2D, 0x39, 0x31, 0x00, 0x2F, 0x02, 0x00, 0x20, 0xFC, 0x45, 0x2D, + 0x5B, 0x2D, 0x28, 0x2E, 0x02, 0x00, 0x25, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x34, 0x2E, 0x02, 0x00, + 0x26, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x36, 0x2E, 0x02, 0x00, 0x27, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, + 0x38, 0x2E, 0x02, 0x00, 0xB2, 0xFC, 0x45, 0x2D, 0x55, 0x2D, 0x24, 0x2F, 0x22, 0x00, 0xC1, 0xFC, + 0x45, 0x2D, 0x5B, 0x2D, 0x9E, 0x33, 0x20, 0x00, 0xB0, 0xFC, 0x18, 0x2D, 0x3D, 0x31, 0x00, 0x00, + 0x00, 0x00, 0xC4, 0xFC, 0x18, 0x2D, 0x57, 0x30, 0x00, 0x00, 0x08, 0x00, 0xC8, 0xFC, 0x18, 0x2D, + 0x55, 0x30, 0x00, 0x00, 0x08, 0x00, 0xB4, 0xFC, 0x18, 0x2D, 0x71, 0x31, 0x00, 0x00, 0x00, 0x00, + 0xB6, 0xFC, 0x18, 0x2D, 0x19, 0x32, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xFC, 0x18, 0x2D, 0x43, 0x32, + 0x00, 0x00, 0x00, 0x00, 0xB8, 0xFC, 0x18, 0x2D, 0x99, 0x32, 0x00, 0x00, 0x00, 0x00, 0xBC, 0xFC, + 0x18, 0x2D, 0xD2, 0x32, 0x00, 0x00, 0x00, 0x00, 0xBD, 0xFC, 0x18, 0x2D, 0x58, 0x33, 0x00, 0x00, + 0x00, 0x00, 0xBE, 0xFC, 0x18, 0x2D, 0x82, 0x33, 0x00, 0x00, 0x00, 0x00, 0xBF, 0xFC, 0x18, 0x2D, + 0xCF, 0x33, 0x00, 0x00, 0x00, 0x00, 0xB3, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0xA0, 0x0F, 0x10, 0x00, + 0xB5, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x38, 0x34, 0x02, 0x00, 0xB9, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, + 0x3A, 0x34, 0x02, 0x00, 0x90, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0x3E, 0x34, 0x02, 0x00, 0x88, 0xFC, + 0x45, 0x2D, 0x5B, 0x2D, 0x72, 0x32, 0x04, 0x00, 0x89, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x76, 0x32, + 0x04, 0x00, 0xC5, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x7A, 0x32, 0x04, 0x00, 0x23, 0xFC, 0x45, 0x2D, + 0x5B, 0x2D, 0x2E, 0x2E, 0x04, 0x00, 0x2A, 0xFC, 0x45, 0x2D, 0xE9, 0x2D, 0xB0, 0x2D, 0x02, 0x00, + 0xC7, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0xA0, 0x32, 0x0A, 0x00, 0x29, 0xFC, 0x3C, 0x2E, 0x00, 0x2E, + 0x00, 0x00, 0x00, 0x00, 0xC2, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x80, 0x32, 0x08, 0x00, 0x32, 0xFC, + 0x45, 0x2D, 0x5B, 0x2D, 0x98, 0x01, 0x02, 0x00, 0x33, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x9A, 0x01, + 0x02, 0x00, 0x35, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x88, 0x32, 0x02, 0x00, 0xC7, 0xFC, 0x45, 0x2D, + 0xD3, 0x2F, 0x8A, 0x32, 0x02, 0x00, 0x00, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0xB2, 0x2D, 0x02, 0x00, + 0x01, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0xAA, 0x2D, 0x06, 0x00, 0x02, 0xFC, 0x45, 0x2D, 0xD5, 0x2D, + 0x02, 0x2F, 0x22, 0x00, 0x05, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0xA0, 0x2D, 0x02, 0x00, 0x08, 0xFC, + 0x45, 0x2D, 0x5B, 0x2D, 0xA4, 0x2D, 0x06, 0x00, 0x09, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0xFA, 0x2D, + 0x02, 0x00, 0x0B, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0xFC, 0x2D, 0x02, 0x00, 0x0C, 0xFC, 0x45, 0x2D, + 0x5B, 0x2D, 0xFE, 0x2D, 0x02, 0x00, 0x0D, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x00, 0x2E, 0x02, 0x00, + 0x21, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x2A, 0x2E, 0x02, 0x00, 0x80, 0xFC, 0xB1, 0x2D, 0xC1, 0x2D, + 0x40, 0x2E, 0xC0, 0x00, 0x81, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0xA4, 0x01, 0x02, 0x00, 0x83, 0xFC, + 0x45, 0x2D, 0x5B, 0x2D, 0xA8, 0x01, 0x02, 0x00, 0x85, 0xFC, 0x45, 0x2D, 0x4A, 0x2F, 0xA0, 0x01, + 0x02, 0x00, 0x86, 0xFC, 0x45, 0x2D, 0x6E, 0x2F, 0xB0, 0x01, 0x02, 0x00, 0x28, 0xFC, 0x45, 0x2D, + 0x5B, 0x2D, 0x3A, 0x2E, 0x02, 0x00, 0x90, 0xFC, 0x45, 0x2D, 0x5C, 0x2F, 0xA2, 0x01, 0x02, 0x00, + 0x87, 0xFC, 0x45, 0x2D, 0x8C, 0x2F, 0x50, 0x2F, 0x22, 0x03, 0x30, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, + 0x3C, 0x2E, 0x02, 0x00, 0x84, 0xFC, 0x45, 0x2D, 0x92, 0x2F, 0xAC, 0x01, 0x04, 0x00, 0x2B, 0xFC, + 0x45, 0x2D, 0x5B, 0x2D, 0xE2, 0x37, 0x02, 0x00, 0xF8, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0xDC, 0x37, + 0x02, 0x00, 0xF3, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0xE4, 0x37, 0x02, 0x00, 0x20, 0xFD, 0x76, 0x2D, + 0x22, 0x2D, 0x5E, 0x40, 0x08, 0x00, 0x21, 0xFD, 0x76, 0x2D, 0x22, 0x2D, 0x62, 0x40, 0x0A, 0x00, + 0x22, 0xFD, 0x76, 0x2D, 0x22, 0x2D, 0x67, 0x40, 0x16, 0x00, 0x23, 0xFD, 0x76, 0x2D, 0x22, 0x2D, + 0x72, 0x40, 0x0A, 0x00, 0x45, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0xFC, 0x00, 0x02, 0x00, 0x47, 0xFD, + 0x45, 0x2D, 0x22, 0x2D, 0x72, 0x01, 0x02, 0x00, 0x48, 0xFD, 0x91, 0x2E, 0x22, 0x2D, 0x98, 0x01, + 0x02, 0x00, 0x49, 0xFD, 0x91, 0x2E, 0x22, 0x2D, 0x9A, 0x01, 0x02, 0x00, 0x4A, 0xFD, 0x45, 0x2D, + 0x22, 0x2D, 0x92, 0x01, 0x02, 0x00, 0x4B, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0x94, 0x01, 0x02, 0x00, + 0x4D, 0xFD, 0x76, 0x2D, 0x22, 0x2D, 0x77, 0x40, 0x0C, 0x00, 0x4F, 0xFD, 0xA5, 0x2E, 0x22, 0x2D, + 0x90, 0x32, 0x02, 0x00, 0xC2, 0xFD, 0x9B, 0x2E, 0x22, 0x2D, 0x00, 0x00, 0x02, 0x00, 0x40, 0xFD, + 0x6E, 0x2D, 0x22, 0x2D, 0xB6, 0x01, 0x02, 0x00, 0x24, 0xFD, 0xB5, 0x2E, 0x22, 0x2D, 0x00, 0x00, + 0x02, 0x00, 0x91, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0xC6, 0x25, 0x02, 0x00, 0x93, 0xFD, 0x45, 0x2D, + 0x22, 0x2D, 0xCC, 0x25, 0x02, 0x00, 0x8F, 0xFD, 0xD5, 0x2E, 0x22, 0x2D, 0x00, 0x00, 0x08, 0x00, + 0xC1, 0xFD, 0x00, 0x31, 0x22, 0x2D, 0xFA, 0x00, 0x02, 0x00, 0xC6, 0xFD, 0x45, 0x2D, 0x22, 0x2D, + 0xF8, 0x37, 0x04, 0x00, 0x25, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0x9E, 0x01, 0x02, 0x00, 0x89, 0xFD, + 0xB9, 0x30, 0x22, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xFD, 0x93, 0x2D, 0x22, 0x2D, 0x12, 0x34, + 0x24, 0x00, 0x41, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0xBE, 0x33, 0x22, 0x00, 0x42, 0xFD, 0x45, 0x2D, + 0x22, 0x2D, 0xFE, 0x00, 0x06, 0x00, 0x43, 0xFD, 0xC2, 0x2E, 0x22, 0x2D, 0x00, 0x00, 0x06, 0x00, + 0x44, 0xFD, 0xAC, 0x2E, 0x22, 0x2D, 0xB2, 0x01, 0x02, 0x00, 0x46, 0xFD, 0x21, 0x31, 0x22, 0x2D, + 0x00, 0x00, 0x00, 0x00, 0x4C, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0x46, 0x2F, 0x02, 0x00, 0x50, 0xFD, + 0x45, 0x2D, 0x22, 0x2D, 0xF2, 0x00, 0x02, 0x00, 0x51, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0xF4, 0x00, + 0x02, 0x00, 0x52, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0xC4, 0x01, 0x02, 0x00, 0x8C, 0xFD, 0x38, 0x2D, + 0x22, 0x2D, 0x98, 0x34, 0x56, 0x00, 0x8D, 0xFD, 0x38, 0x2D, 0x22, 0x2D, 0xF2, 0x34, 0x14, 0x00, + 0x00, 0xF1, 0x46, 0x00, 0xDC, 0x2C, 0x36, 0x01, 0x01, 0xF1, 0x84, 0x07, 0xDA, 0x2C, 0x38, 0x01, + 0x00, 0x03, 0xA0, 0x80, 0x1E, 0x00, 0x70, 0x01, 0xFA, 0x00, 0xD4, 0x01, 0xFE, 0x00, 0x3A, 0x01, + 0xB6, 0x01, 0xCC, 0x2C, 0x54, 0x01, 0xC6, 0x25, 0x20, 0x00, 0x00, 0x00, 0xC0, 0x1D, 0x00, 0x00, + 0xC4, 0x1F, 0x4E, 0x01, 0x0B, 0x00, 0xB8, 0x00, 0xEC, 0x00, 0x44, 0x00, 0x46, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x09, 0x08, 0x24, 0x28, 0x06, 0x0C, 0x18, 0x08, 0x30, 0x14, 0x0C, + 0x08, 0x36, 0x10, 0x12, 0x24, 0xB7, 0x97, 0xB6, 0xA3, 0xB7, 0xAC, 0xB7, 0xA8, 0xB6, 0x3E, 0xB7, + 0x16, 0xB7, 0x79, 0x3E, 0x57, 0x3D, 0x79, 0x3E, 0xF9, 0x3D, 0x5F, 0x3D, 0x52, 0x3D, 0x33, 0x3E, + 0x55, 0x3E, 0x6A, 0x3E, 0xAC, 0x3E, 0xD8, 0x3E, 0xF8, 0x3D, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, + 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, + 0x23, 0x46, 0x23, 0x46, 0x23, 0x46, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, + 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, + 0x1D, 0x47, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, + 0x5A, 0x48, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0x33, 0x48, 0x78, 0x49, + 0x78, 0x49, 0x79, 0x49, 0x79, 0x49, 0x79, 0x49, 0x79, 0x49, 0x7A, 0x49, 0x7A, 0x49, 0x7A, 0x49, + 0x7A, 0x49, 0x7B, 0x49, 0x7B, 0x49, 0x7B, 0x49, 0x7C, 0x49, 0xD8, 0x03, 0xDC, 0x03, 0xE0, 0x03, + 0xE4, 0x03, 0xF0, 0x03, 0xF4, 0x03, 0xF8, 0x03, 0x0A, 0x04, 0x0E, 0x04, 0x12, 0x04, 0x16, 0x04, + 0x0C, 0x04, 0x10, 0x04, 0x14, 0x04, 0x18, 0x04, 0x1C, 0x04, 0x20, 0x04, 0x24, 0x04, 0x28, 0x04, + 0x4C, 0x04, 0x50, 0x04, 0x54, 0x04, 0x58, 0x04, 0x5C, 0x04, 0x60, 0x04, 0x64, 0x04, 0x68, 0x04, + 0x6C, 0x04, 0x70, 0x04, 0x74, 0x04, 0x7D, 0x04, 0x81, 0x04, 0x85, 0x04, 0x89, 0x04, 0x8D, 0x04, + 0x10, 0x00, 0x8E, 0x19, 0xAC, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3C, 0x0C, 0x00, 0x00, + 0xFF, 0x3F, 0x44, 0x04, 0x00, 0x00, 0xD3, 0x22, 0x44, 0x04, 0x9C, 0x02, 0xCB, 0x54, 0x44, 0x04, + 0x00, 0x00, 0x01, 0x00, 0x44, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0C, 0x71, 0x00, 0x30, 0x50, + 0x20, 0x00, 0x80, 0xBF, 0x1F, 0xA6, 0x28, 0x00, 0x0B, 0x02, 0x60, 0x84, 0x4C, 0x00, 0x02, 0x00, + 0x4B, 0x1C, 0x98, 0x00, 0x00, 0x00, 0x20, 0x0B, 0x34, 0x04, 0xFD, 0x34, 0x34, 0x00, 0x38, 0x04, + 0xFD, 0x34, 0x34, 0x00, 0x3C, 0x04, 0x01, 0x00, 0x10, 0x00, 0x00, 0x08, 0x00, 0x52, 0x14, 0x00, + 0x04, 0x08, 0x0E, 0x32, 0x00, 0xA6, 0x10, 0x08, 0xC4, 0x03, 0x50, 0x60, 0x18, 0x08, 0xF0, 0x3F, + 0xFC, 0x01, 0x10, 0x0C, 0x00, 0x00, 0x80, 0x04, 0x14, 0x0C, 0x00, 0x00, 0x00, 0x41, 0x20, 0x0C, + 0xB0, 0x00, 0xB0, 0xB8, 0x24, 0x0C, 0x00, 0x00, 0xAB, 0x05, 0x2C, 0x0C, 0x80, 0x05, 0x00, 0xFF, + 0x30, 0x0C, 0x00, 0x00, 0xB0, 0x04, 0x34, 0x0C, 0x03, 0x00, 0x00, 0xE8, 0x44, 0x0C, 0x04, 0x00, + 0xFF, 0x0F, 0x00, 0x10, 0x2E, 0x00, 0x0C, 0xE3, 0x44, 0x04, 0x00, 0x00, 0x01, 0x04, 0x44, 0x04, + 0x00, 0x00, 0x01, 0x01, 0x44, 0x04, 0x00, 0x00, 0x01, 0x00, 0x44, 0x04, 0x00, 0x00, 0x01, 0x04, + 0x44, 0x04, 0x00, 0x00, 0x80, 0x03, 0x48, 0x0C, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x04, 0x08, 0x48, + 0x00, 0x00, 0x04, 0x04, 0x08, 0x40, 0x00, 0x00, 0x00, 0x0C, 0x71, 0x00, 0x30, 0x30, 0x00, 0x00, + 0x5E, 0x40, 0x01, 0x00, 0x18, 0x00, 0x36, 0xC0, 0xE8, 0x0E, 0x1C, 0x00, 0x78, 0xC8, 0xA5, 0x40, + 0x24, 0x00, 0x9E, 0xB0, 0xB9, 0x95, 0x08, 0x08, 0x00, 0xEA, 0x40, 0x01, 0x0C, 0x08, 0x00, 0xEA, + 0x00, 0x00, 0x1C, 0x08, 0x00, 0x00, 0x42, 0x07, 0x20, 0x08, 0x7B, 0x00, 0xD4, 0x09, 0x2C, 0x04, + 0x14, 0x00, 0x50, 0x14, 0x30, 0x04, 0x28, 0x0F, 0x28, 0x7F, 0x18, 0x08, 0x20, 0x00, 0xFC, 0x01, + 0x04, 0x10, 0x69, 0x00, 0xFD, 0xC3, 0x08, 0x10, 0x69, 0x00, 0xFD, 0xC3, 0x08, 0x0C, 0x00, 0x00, + 0x00, 0x00, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0C, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x04, + 0x08, 0x48, 0x02, 0x00, 0x00, 0x00, 0x5E, 0x48, 0x00, 0x00, 0x04, 0x04, 0x08, 0x40, 0x02, 0x00, + 0x00, 0x0C, 0x71, 0x00, 0x30, 0x50, 0x00, 0x00, 0x5E, 0x48, 0x01, 0x00, 0x18, 0x00, 0x3A, 0xC0, + 0xE8, 0x04, 0x1C, 0x00, 0x78, 0xD0, 0xA5, 0x40, 0x24, 0x00, 0x9E, 0xB0, 0xB9, 0x85, 0x2C, 0x04, + 0x14, 0x00, 0x50, 0x14, 0x30, 0x04, 0x28, 0x0F, 0x28, 0x7F, 0x08, 0x08, 0x00, 0xEA, 0x40, 0x01, + 0x0C, 0x08, 0x00, 0xEA, 0x00, 0x00, 0x1C, 0x08, 0x00, 0x00, 0x42, 0x07, 0x20, 0x08, 0x7B, 0x00, + 0xD4, 0x09, 0x18, 0x08, 0xF0, 0x3F, 0xFC, 0x01, 0x04, 0x10, 0x69, 0x00, 0xDD, 0xCD, 0x08, 0x10, + 0x69, 0x00, 0xDD, 0xCD, 0x08, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x04, 0x40, 0x01, 0x41, 0x01, 0x0C, 0x04, 0x40, 0x04, 0x41, 0x04, 0x10, 0x04, 0xD6, 0x08, + 0x56, 0x0A, 0x14, 0x04, 0x42, 0x02, 0x56, 0x0A, 0x18, 0x04, 0x56, 0x0A, 0x40, 0x02, 0x1C, 0x04, + 0x42, 0x0A, 0x42, 0x2A, 0x20, 0x04, 0xC2, 0x00, 0xD6, 0x08, 0x24, 0x04, 0xD6, 0x08, 0xC0, 0x00, + 0x28, 0x04, 0xC2, 0x08, 0xC2, 0x28, 0x08, 0x04, 0x40, 0x01, 0x41, 0x01, 0x0C, 0x04, 0x00, 0x01, + 0x01, 0x01, 0x10, 0x04, 0x56, 0x0A, 0x56, 0x0A, 0x14, 0x04, 0x42, 0x02, 0x56, 0x0A, 0x18, 0x04, + 0x56, 0x0A, 0x40, 0x02, 0x1C, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x20, 0x04, 0x42, 0x02, 0x56, 0x0A, + 0x24, 0x04, 0x56, 0x0A, 0x40, 0x02, 0x28, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x08, 0x04, 0x40, 0x01, + 0x41, 0x01, 0x0C, 0x04, 0x40, 0x04, 0x41, 0x04, 0x10, 0x04, 0xCE, 0x08, 0x4E, 0x0A, 0x14, 0x04, + 0x42, 0x02, 0x4E, 0x0A, 0x18, 0x04, 0x4E, 0x0A, 0x40, 0x02, 0x1C, 0x04, 0x42, 0x0A, 0x42, 0x2A, + 0x20, 0x04, 0xC2, 0x00, 0xCE, 0x08, 0x24, 0x04, 0xCE, 0x08, 0xC0, 0x00, 0x28, 0x04, 0xC2, 0x08, + 0xC2, 0x28, 0x08, 0x04, 0x40, 0x01, 0x41, 0x01, 0x0C, 0x04, 0x00, 0x01, 0x01, 0x01, 0x10, 0x04, + 0x4E, 0x0A, 0x4E, 0x0A, 0x14, 0x04, 0x42, 0x02, 0x4E, 0x0A, 0x18, 0x04, 0x4E, 0x0A, 0x40, 0x02, + 0x1C, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x20, 0x04, 0x42, 0x02, 0x4E, 0x0A, 0x24, 0x04, 0x4E, 0x0A, + 0x40, 0x02, 0x28, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x05, 0x00, 0xA0, 0x16, 0xA0, 0x16, + 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, + 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, + 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, + 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x17, 0xA0, 0x17, 0xA0, 0x17, 0xA0, 0x18, 0xFF, 0x06, 0xFF, 0x06, + 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, + 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, + 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, + 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0x00, 0x00, 0x65, 0x00, + 0x65, 0x00, 0x65, 0x00, 0x65, 0x00, 0x5D, 0x00, 0x52, 0x00, 0x48, 0x00, 0x40, 0x00, 0x38, 0x00, + 0x31, 0x00, 0x2C, 0x00, 0x27, 0x00, 0x23, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x65, 0x00, 0x65, 0x00, + 0x65, 0x00, 0x65, 0x00, 0x5D, 0x00, 0x52, 0x00, 0x48, 0x00, 0x40, 0x00, 0x38, 0x00, 0x31, 0x00, + 0x2C, 0x00, 0x27, 0x00, 0x23, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, + 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, + 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x15, 0x00, 0x6E, 0x6F, 0x6E, 0x2D, + 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x21, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x09, + 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x48, 0x45, 0x52, 0x4D, 0x45, 0x53, + 0x20, 0x32, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0x15, 0x00, + 0x6E, 0x6F, 0x6E, 0x2D, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x53, 0x53, + 0x49, 0x44, 0x20, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x01, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x48, 0x45, + 0x52, 0x4D, 0x45, 0x53, 0x20, 0x32, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x69, + 0x72, 0x73, 0x74, 0x20, 0x57, 0x61, 0x76, 0x65, 0x4C, 0x41, 0x4E, 0x20, 0x49, 0x49, 0x20, 0x53, + 0x53, 0x49, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xF0, 0x0F, + 0x0F, 0x00, 0x50, 0x01, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x24, 0x00, 0xFF, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0A, 0x00, + 0x0B, 0x00, 0x0B, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x02, 0x01, + 0x02, 0x04, 0x0B, 0x16, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x82, 0x84, 0x8B, 0x96, 0x00, 0x00, + 0x00, 0x00, 0x1C, 0x85, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, 0x1B, 0x00, 0x17, 0x00, 0x11, 0x00, 0x10, 0x00, 0x0B, 0x00, + 0x0B, 0x00, 0x09, 0x00, 0x17, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0D, 0x00, 0x0B, 0x00, 0x09, 0x00, + 0x08, 0x00, 0x07, 0x00, 0x0D, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x08, 0x00, 0x05, 0x00, 0x05, 0x00, + 0xD8, 0x0C, 0xC0, 0x08, 0x90, 0x0D, 0x60, 0x09, 0x48, 0x0E, 0x30, 0x0A, 0x24, 0x0F, 0x18, 0x0B, + 0x0B, 0x6E, 0x0B, 0x37, 0x02, 0x14, 0x01, 0x0A, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x43, 0x75, 0x72, 0x72, 0x65, + 0x6E, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x53, 0x65, 0x74, 0x20, 0x49, + 0x64, 0x65, 0x6E, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xDD, 0x00, 0x50, + 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x05, 0x02, 0x00, 0x00, 0x50, 0xF2, 0x02, 0x00, 0x50, + 0xF2, 0x04, 0x02, 0x00, 0x00, 0x50, 0xF2, 0x00, 0x00, 0x50, 0xF2, 0x01, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x14, 0x00, 0x15, 0x00, 0x36, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x11, 0x00, 0x36, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x10, 0x00, 0xBE, 0x33, 0x1E, 0x33, 0xCC, 0x35, 0xD0, 0x35, 0xD4, 0x35, 0x12, 0x34, + 0x04, 0x36, 0x08, 0x36, 0xF2, 0x33, 0x00, 0x00, 0x00, 0x00, 0x24, 0x2F, 0x14, 0x33, 0x08, 0x36, + 0xFF, 0xFF, 0x00, 0x00, 0xBE, 0x33, 0x1E, 0x33, 0xCC, 0x35, 0xD0, 0x35, 0xD4, 0x35, 0x12, 0x34, + 0x04, 0x36, 0x08, 0x36, 0xF2, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0xBE, 0x33, 0x14, 0x33, 0x08, 0x36, 0x5C, 0x34, 0x2A, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00, 0x02, 0x06, 0x00, 0x00, 0x06, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2A, + 0x00, 0x00, 0x08, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x30, 0x00, 0xFF, 0xFF, 0x1D, 0xFA, + 0xF9, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x19, 0x0A, + 0x09, 0x46, 0x1C, 0x60, 0x18, 0x00, 0x19, 0x1D, 0x09, 0x42, 0x1C, 0x60, 0x00, 0x00, + +}; /* fw_image_2_data */ + +static const hcf_8 fw_image_3_data[] = { + 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x26, 0x1A, 0x00, 0x80, 0x3A, 0x15, 0x00, 0x7F, 0xF1, + 0x32, 0xF2, 0x33, 0xF2, 0xD0, 0x80, 0x80, 0xF1, 0x0F, 0x02, 0xD0, 0x80, 0x34, 0xF2, 0x81, 0xF1, + 0x0B, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x08, 0x02, 0xE9, 0x60, 0x58, 0x4F, 0x30, 0x78, 0xFF, 0xFF, + 0x24, 0x60, 0x58, 0x4F, 0xE3, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xD7, 0x78, 0xFF, 0xFF, 0x00, 0xF4, + 0xAA, 0x60, 0xAA, 0x65, 0x09, 0xF2, 0x5A, 0xD0, 0xD4, 0x80, 0x03, 0x64, 0x12, 0x02, 0xD0, 0x80, + 0x1D, 0x60, 0x60, 0x65, 0x0E, 0x02, 0x5A, 0xD2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x60, 0x00, 0x65, + 0x08, 0x02, 0x5A, 0xD2, 0xFF, 0xFF, 0xD4, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0x1C, 0x60, 0xD7, 0x78, + 0xFF, 0xFF, 0x00, 0x60, 0xEA, 0xF1, 0x5A, 0xD1, 0x44, 0x48, 0x5A, 0xD1, 0x44, 0x4A, 0x26, 0x46, + 0x3F, 0xF2, 0x00, 0xF4, 0x44, 0x4C, 0xD8, 0x83, 0x70, 0x61, 0x68, 0x65, 0xD7, 0x80, 0xFF, 0xFF, + 0x07, 0x0E, 0x08, 0xF2, 0x08, 0x00, 0x68, 0x65, 0xD7, 0x80, 0xFF, 0xFF, 0x01, 0x0E, 0x03, 0x00, + 0x1C, 0x60, 0xED, 0x78, 0xFF, 0xFF, 0x58, 0x4F, 0x79, 0x00, 0x9C, 0x80, 0x01, 0x65, 0x02, 0x02, + 0x00, 0x65, 0x02, 0x00, 0xFF, 0x3B, 0xF7, 0x01, 0x58, 0x4F, 0x70, 0x00, 0x9C, 0x80, 0x45, 0x42, + 0xEA, 0x02, 0x58, 0x4F, 0x6B, 0x00, 0x9C, 0x80, 0xFF, 0xFF, 0xE5, 0x02, 0x58, 0x4F, 0x66, 0x00, + 0x9C, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0x00, 0x65, 0x45, 0x42, 0xF8, 0x01, 0xFF, 0x3A, 0x29, 0x00, + 0x60, 0x47, 0xFF, 0xB5, 0x28, 0x44, 0xFF, 0xB4, 0x94, 0x80, 0xFF, 0xFF, 0xD4, 0x02, 0x60, 0x45, + 0x28, 0x47, 0x2A, 0x5F, 0x40, 0x48, 0x2A, 0x47, 0x2C, 0x5F, 0x40, 0x4A, 0x2C, 0x47, 0x65, 0x5F, + 0x40, 0x4C, 0x10, 0x64, 0x40, 0x42, 0x28, 0x45, 0x05, 0x00, 0x58, 0x4F, 0x47, 0x00, 0x94, 0x80, + 0x28, 0x45, 0x26, 0x02, 0x58, 0x4F, 0x42, 0x00, 0x94, 0x80, 0x2A, 0x45, 0x21, 0x02, 0x58, 0x4F, + 0x3D, 0x00, 0x94, 0x80, 0xFF, 0xFF, 0x1C, 0x02, 0x22, 0x44, 0x4C, 0x82, 0x2C, 0x45, 0x31, 0x03, + 0xEC, 0x01, 0x10, 0x65, 0x45, 0x42, 0x28, 0x45, 0x94, 0x80, 0x2A, 0x45, 0x21, 0x02, 0x58, 0x4F, + 0x2D, 0x00, 0x94, 0x80, 0x2C, 0x45, 0x1C, 0x02, 0x58, 0x4F, 0x28, 0x00, 0x94, 0x80, 0xFF, 0xFF, + 0x17, 0x02, 0x22, 0x44, 0x4C, 0x82, 0x28, 0x45, 0x1C, 0x03, 0x58, 0x4F, 0x1F, 0x00, 0xEC, 0x01, + 0x40, 0x4B, 0x28, 0x47, 0x40, 0x48, 0x2A, 0x47, 0x40, 0x4A, 0x2C, 0x47, 0x60, 0x45, 0x2A, 0x5E, + 0x40, 0x4C, 0x2A, 0x44, 0x28, 0x5E, 0x40, 0x4A, 0x28, 0x44, 0x65, 0x5E, 0x40, 0x48, 0x2B, 0x44, + 0x68, 0x65, 0xD7, 0x80, 0xFF, 0xFF, 0x17, 0x0E, 0x90, 0x01, 0x26, 0x46, 0xD0, 0x60, 0xB5, 0x78, + 0xFF, 0xFF, 0xB9, 0xFF, 0x26, 0x46, 0xD0, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0xC9, 0x81, 0xCB, 0x83, + 0x07, 0x1C, 0x01, 0x1D, 0x08, 0x00, 0x00, 0xF4, 0x01, 0xF2, 0xFF, 0xFF, 0xFF, 0xB4, 0xD8, 0x81, + 0x5A, 0xD2, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0xD0, 0x60, 0x58, 0x4F, 0xD1, 0x78, 0xFF, 0xFF, + 0x01, 0x60, 0xFE, 0x61, 0x00, 0xF4, 0x12, 0x63, 0x6A, 0x64, 0x01, 0x65, 0xBD, 0xD0, 0xC8, 0x84, + 0x59, 0xD9, 0xFC, 0x02, 0x65, 0x40, 0x01, 0x3A, 0x05, 0x00, 0x00, 0xF4, 0x00, 0x65, 0x0E, 0x64, + 0x04, 0x63, 0xF4, 0x01, 0x2F, 0x60, 0x58, 0x64, 0x0E, 0x60, 0xD9, 0xFB, 0x1D, 0x60, 0xB0, 0x64, + 0xA0, 0xDF, 0x17, 0x60, 0xA8, 0xF3, 0x0E, 0x60, 0xDB, 0xFB, 0x0E, 0x60, 0xDB, 0xF3, 0x0E, 0x60, + 0xD8, 0xF3, 0x60, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0x1D, 0x60, 0x7B, 0x78, 0xFF, 0xFF, + 0x01, 0x64, 0x0E, 0x60, 0xD7, 0xFB, 0x0E, 0x60, 0xD9, 0xF3, 0x02, 0x60, 0x00, 0x61, 0x40, 0x48, + 0x40, 0x4A, 0xFA, 0xA4, 0xA0, 0xD3, 0x41, 0x4C, 0xDC, 0x84, 0xA8, 0x84, 0x0E, 0x60, 0xDC, 0xFB, + 0x28, 0x45, 0x44, 0x8B, 0x2B, 0xD3, 0x0E, 0x60, 0xDA, 0xFB, 0x28, 0x42, 0x4A, 0xD3, 0x2C, 0x45, + 0x44, 0x8C, 0x01, 0x64, 0x40, 0x48, 0x0E, 0x60, 0xDC, 0xF3, 0xFF, 0xFF, 0x36, 0x18, 0xCC, 0x84, + 0xA2, 0xDB, 0x0E, 0x60, 0xDA, 0xF3, 0x28, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x08, 0x03, 0x60, 0xFE, + 0x2C, 0xD3, 0x2A, 0xD3, 0x60, 0x45, 0xD4, 0x80, 0x20, 0xFE, 0x01, 0x03, 0x12, 0x00, 0x28, 0x44, + 0xE0, 0x84, 0xFF, 0xFF, 0x02, 0x24, 0x01, 0x00, 0x06, 0x00, 0x2B, 0x44, 0x58, 0x8B, 0x2B, 0xD3, + 0x0E, 0x60, 0xDA, 0xFB, 0x01, 0x64, 0x40, 0x48, 0x2A, 0x44, 0x5C, 0x8A, 0x2C, 0x44, 0x5C, 0x8C, + 0xDA, 0x01, 0x00, 0x64, 0x0E, 0x60, 0xD7, 0xFB, 0x0E, 0x60, 0xD9, 0xF3, 0xFF, 0xFF, 0x60, 0x45, + 0xFA, 0xA4, 0xA0, 0xD3, 0xFF, 0xFF, 0xC4, 0x81, 0x65, 0x44, 0xFC, 0xA4, 0xA0, 0xD3, 0x06, 0xA1, + 0xDC, 0x84, 0xA8, 0x84, 0x44, 0x94, 0x0E, 0x60, 0xD9, 0xFB, 0x0E, 0x60, 0xD7, 0xF3, 0xFF, 0xFF, + 0x60, 0x40, 0x01, 0x26, 0x09, 0x00, 0x0E, 0x60, 0xD8, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0xA2, 0xDB, + 0x94, 0x01, 0x1C, 0x60, 0xD7, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xDB, 0x78, 0xFF, 0xFF, 0x00, 0x60, + 0x2E, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x25, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x5F, 0xFB, 0x01, 0x60, + 0x05, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x25, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x5E, 0xFB, 0x00, 0x60, + 0x02, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x25, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x65, 0xFB, 0x1F, 0x60, + 0x6D, 0x64, 0x08, 0x60, 0x36, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x01, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, + 0xFF, 0xFF, 0xFE, 0xB4, 0xF1, 0xFB, 0x10, 0x60, 0x30, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, + 0x14, 0x63, 0x01, 0x60, 0xC2, 0x61, 0x2D, 0x60, 0x98, 0x64, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, + 0x00, 0x60, 0x8A, 0x63, 0x2D, 0x60, 0x0C, 0x61, 0x2D, 0x60, 0xB0, 0x64, 0x58, 0xD1, 0x59, 0xD9, + 0xFD, 0x1F, 0x16, 0x60, 0xAB, 0xF3, 0x19, 0x60, 0x48, 0xF1, 0xFF, 0xB5, 0x64, 0x40, 0x02, 0x2B, + 0x0B, 0x00, 0x60, 0x40, 0x03, 0x2E, 0x08, 0x00, 0x80, 0x2B, 0x06, 0x00, 0x32, 0x44, 0x00, 0x60, + 0x80, 0x63, 0x3C, 0x94, 0x40, 0x52, 0x05, 0x00, 0x32, 0x44, 0xFF, 0x60, 0x7F, 0x63, 0x2C, 0x94, + 0x40, 0x52, 0x65, 0x43, 0x16, 0x60, 0xAB, 0xFD, 0x16, 0x60, 0xC2, 0xF1, 0x66, 0x41, 0xA6, 0xF5, + 0x3A, 0xF2, 0x64, 0x40, 0x01, 0x36, 0x22, 0x64, 0x3A, 0xFA, 0x61, 0x46, 0x32, 0x45, 0x16, 0x60, + 0xCB, 0xF1, 0x10, 0x67, 0xB4, 0x85, 0x64, 0x40, 0x01, 0x2A, 0x94, 0x85, 0x45, 0x52, 0xFF, 0x60, + 0xE7, 0x65, 0x32, 0x41, 0xA5, 0x81, 0x16, 0x60, 0xC2, 0xF3, 0x08, 0x65, 0xFF, 0xA0, 0xFF, 0xFF, + 0x01, 0x03, 0x07, 0x00, 0x16, 0x60, 0xC4, 0xF3, 0xB5, 0x81, 0x10, 0x65, 0x60, 0x40, 0x01, 0x26, + 0xB5, 0x81, 0x41, 0x52, 0x19, 0x60, 0x48, 0xF3, 0x37, 0x60, 0xE6, 0x63, 0xF0, 0x84, 0xF0, 0x84, + 0xF0, 0x84, 0x03, 0xB5, 0xF0, 0x84, 0xF0, 0x84, 0x03, 0xB4, 0x65, 0x5C, 0xA3, 0xD9, 0x37, 0x60, + 0xE8, 0x63, 0x02, 0xA8, 0xA3, 0xDB, 0x15, 0x02, 0x00, 0x60, 0xC8, 0x64, 0x1B, 0x60, 0xF5, 0xFB, + 0x1B, 0x60, 0xF9, 0xFB, 0x07, 0x60, 0xD0, 0x64, 0x1B, 0x60, 0xF6, 0xFB, 0x1B, 0x60, 0xFA, 0xFB, + 0x01, 0x60, 0x90, 0x64, 0x1B, 0x60, 0xF7, 0xFB, 0x00, 0x60, 0x64, 0x64, 0x1B, 0x60, 0xF8, 0xFB, + 0x06, 0x00, 0x64, 0x64, 0x1B, 0x60, 0xF7, 0xFB, 0x64, 0x64, 0x1B, 0x60, 0xF8, 0xFB, 0x19, 0x60, + 0x48, 0xF1, 0x01, 0x64, 0x64, 0x40, 0x40, 0x2A, 0x02, 0x00, 0x1B, 0x60, 0xEE, 0xFB, 0x33, 0x60, + 0xBC, 0x61, 0x2D, 0x60, 0x0E, 0x64, 0x20, 0x63, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0xBA, 0xF1, + 0x7E, 0xF9, 0x1A, 0x63, 0x00, 0x60, 0xFC, 0x61, 0x00, 0x64, 0x59, 0xDB, 0xFE, 0x1F, 0x40, 0x40, + 0x01, 0x64, 0x85, 0xFB, 0x17, 0x60, 0x14, 0xF3, 0x35, 0x60, 0x36, 0x61, 0xFE, 0xA4, 0xE0, 0x84, + 0x04, 0x24, 0x0C, 0x00, 0xE0, 0x84, 0x41, 0x91, 0x1A, 0x60, 0x1F, 0xF3, 0xA1, 0xD1, 0x59, 0xD1, + 0xA0, 0x83, 0x1A, 0x60, 0x1B, 0xFD, 0xA0, 0x83, 0x1A, 0x60, 0x1A, 0xFD, 0xE4, 0xF3, 0x7D, 0xFB, + 0xCF, 0xF1, 0x10, 0x60, 0xEC, 0x63, 0x2F, 0x18, 0x60, 0x40, 0x01, 0x27, 0x12, 0x00, 0xCC, 0x84, + 0x06, 0xA3, 0xFD, 0x02, 0xA3, 0xD3, 0x10, 0x60, 0xF2, 0x63, 0x25, 0x1B, 0x11, 0x60, 0x44, 0x65, + 0xA3, 0xD3, 0x06, 0xA3, 0xD7, 0x80, 0x02, 0x1B, 0xFB, 0x04, 0x1D, 0x00, 0xF8, 0xA3, 0xA3, 0xD3, + 0x18, 0x00, 0x11, 0x60, 0x60, 0x63, 0x12, 0x60, 0x40, 0x65, 0xA3, 0xD1, 0x08, 0xA3, 0xD0, 0x80, + 0xD7, 0x80, 0x02, 0x03, 0xFA, 0x04, 0x0F, 0x00, 0xFA, 0xA3, 0xA3, 0xD3, 0x11, 0x60, 0x62, 0x63, + 0x0A, 0x1B, 0xA3, 0xD3, 0x08, 0xA3, 0xD7, 0x80, 0x02, 0x1B, 0xFB, 0x04, 0x04, 0x00, 0xF6, 0xA3, + 0xA3, 0xD3, 0xE4, 0xFB, 0x7D, 0xFB, 0x2E, 0x60, 0x2E, 0x64, 0x2D, 0x60, 0x8A, 0x63, 0xA0, 0xD1, + 0xA3, 0xD9, 0x64, 0x41, 0x58, 0xD1, 0x5B, 0xD9, 0x7D, 0xF3, 0x66, 0x45, 0xA6, 0xF5, 0x60, 0x40, + 0x01, 0x27, 0x08, 0x00, 0x91, 0xFA, 0x61, 0x44, 0xFD, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, + 0x12, 0xFA, 0x07, 0x00, 0x11, 0xF8, 0x64, 0x44, 0xFD, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, + 0x12, 0xFA, 0x65, 0x46, 0x46, 0x48, 0xE2, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x05, 0x3A, 0x03, 0x00, + 0x14, 0x60, 0x22, 0x66, 0x11, 0x00, 0x04, 0x3A, 0x03, 0x00, 0x14, 0x60, 0x16, 0x66, 0x0C, 0x00, + 0x03, 0x3A, 0x03, 0x00, 0x14, 0x60, 0x0A, 0x66, 0x07, 0x00, 0x02, 0x3A, 0x03, 0x00, 0x13, 0x60, + 0xFE, 0x66, 0x02, 0x00, 0x13, 0x60, 0xF2, 0x66, 0x60, 0xFE, 0xA6, 0xD3, 0xDE, 0x86, 0x13, 0x60, + 0xDC, 0xFB, 0xA6, 0xD3, 0xDE, 0x86, 0x28, 0x60, 0x29, 0x63, 0xA3, 0xDB, 0x28, 0x60, 0xA1, 0x63, + 0xA3, 0xDB, 0xA6, 0xD3, 0xDE, 0x86, 0x13, 0x60, 0xDB, 0xFB, 0xA6, 0xD3, 0xDE, 0x86, 0x27, 0x60, + 0xB9, 0x63, 0xA3, 0xDB, 0x20, 0xFE, 0xA6, 0xD3, 0xDA, 0x86, 0x60, 0x43, 0x1F, 0xB3, 0x63, 0x5C, + 0x1F, 0x60, 0x00, 0xB4, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xB0, 0x85, 0x14, 0x60, 0x12, 0xF3, + 0xFF, 0xFF, 0xFC, 0x60, 0x00, 0xB4, 0xB4, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0x4E, 0xFB, 0x28, 0x60, + 0xC4, 0x63, 0xA3, 0xD3, 0xA6, 0xD1, 0xDE, 0x86, 0x80, 0x60, 0x7F, 0xB5, 0x64, 0x44, 0x60, 0x47, + 0xE8, 0x84, 0x7F, 0x60, 0x80, 0xB4, 0xB4, 0x84, 0xA3, 0xDB, 0x60, 0xFE, 0xA6, 0xD3, 0xDE, 0x86, + 0x13, 0x60, 0xDF, 0xFB, 0xA6, 0xD3, 0xDE, 0x86, 0x00, 0x60, 0xDF, 0xFB, 0xA6, 0xD3, 0xDE, 0x86, + 0x00, 0x60, 0xE0, 0xFB, 0xA6, 0xD3, 0x00, 0x60, 0xE1, 0xFB, 0x20, 0xFE, 0x28, 0x46, 0x19, 0x60, + 0x4D, 0xF1, 0x00, 0x60, 0xCF, 0xF3, 0x64, 0x40, 0x00, 0x3A, 0x0F, 0x00, 0x60, 0x40, 0x01, 0x36, + 0x05, 0x00, 0x02, 0x36, 0x03, 0x00, 0x07, 0x36, 0x01, 0x00, 0x07, 0x00, 0x10, 0x60, 0xF0, 0x64, + 0x00, 0x7C, 0x44, 0xA4, 0xA0, 0xD9, 0x06, 0xA4, 0xA0, 0xD9, 0x36, 0x40, 0x08, 0x3A, 0x03, 0x00, + 0xF3, 0x60, 0x0A, 0x78, 0xFF, 0xFF, 0x00, 0x63, 0x10, 0x60, 0x10, 0xFD, 0x10, 0x60, 0x30, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x19, 0xFB, + 0x1E, 0x60, 0x8D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7D, 0xF1, 0x13, 0x60, + 0x1A, 0xF9, 0x0C, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x07, 0x64, 0xCC, 0xFB, 0x20, 0x60, + 0x00, 0x64, 0x08, 0x60, 0x19, 0xFB, 0x1F, 0x60, 0x53, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x10, 0x60, 0x30, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, + 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xC5, 0xFE, 0x08, 0x60, 0x15, 0xF1, + 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x64, 0x08, 0x60, 0x18, 0xFB, + 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x30, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x02, 0x64, + 0x89, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x08, 0x60, 0x30, 0xF1, 0x00, 0x60, 0xDF, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x64, 0x13, 0x60, 0x21, 0xFB, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x60, + 0x18, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x60, 0x08, 0x64, + 0x08, 0x60, 0x19, 0xFB, 0x1F, 0x60, 0x92, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x08, 0x60, 0x18, 0xF1, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x89, 0xF3, 0x00, 0x65, + 0xD4, 0x80, 0xFF, 0xFF, 0x0A, 0x03, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x19, 0xFB, 0x1F, 0x60, + 0x92, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x95, 0xF3, 0xFF, 0xFF, 0x7F, 0xB4, + 0x95, 0xFB, 0xDE, 0xFE, 0x0A, 0x04, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x19, 0xFB, 0x1F, 0x60, + 0xB7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x60, 0x34, 0x62, 0x06, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x00, 0x64, 0x08, 0x60, 0x18, 0xFB, 0x5A, 0xDB, 0xBE, 0xFE, + 0xDA, 0xFE, 0x25, 0x60, 0xDA, 0x61, 0x1F, 0x60, 0x58, 0x4E, 0xEA, 0x78, 0xFF, 0xFF, 0x25, 0x60, + 0xC8, 0x61, 0x1F, 0x60, 0x58, 0x4E, 0xEA, 0x78, 0xFF, 0xFF, 0x25, 0x60, 0xCE, 0x61, 0x1F, 0x60, + 0x58, 0x4E, 0xEA, 0x78, 0xFF, 0xFF, 0x25, 0x60, 0xEC, 0x61, 0x1F, 0x60, 0x58, 0x4E, 0xEA, 0x78, + 0xFF, 0xFF, 0x25, 0x60, 0xF2, 0x61, 0x1F, 0x60, 0x58, 0x4E, 0xEA, 0x78, 0xFF, 0xFF, 0x25, 0x60, + 0xFE, 0x61, 0x1F, 0x60, 0x58, 0x4E, 0xEA, 0x78, 0xFF, 0xFF, 0xC5, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0xA1, 0xD3, 0x0E, 0x57, 0x23, 0x00, 0x0E, 0xF2, 0x44, 0x4C, 0x80, 0xB0, 0x10, 0xB0, 0x0A, 0x03, + 0x00, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0x13, 0x00, 0x12, 0x02, 0xF0, 0x37, 0x09, 0x00, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, + 0xD0, 0x80, 0xA2, 0xFF, 0xAD, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0xAD, 0xFB, 0x26, 0x60, 0x1A, 0x64, + 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x2C, 0x44, 0xAC, 0x86, 0x09, 0xF0, + 0xDA, 0x02, 0x37, 0x58, 0xFF, 0xFF, 0x2E, 0x58, 0xFF, 0xFF, 0x2E, 0x58, 0xFF, 0xFF, 0x23, 0x60, + 0x85, 0x64, 0x08, 0x60, 0x32, 0xFB, 0x1C, 0x60, 0xB6, 0x62, 0xA2, 0xDF, 0x06, 0xA2, 0x10, 0x60, + 0x88, 0x64, 0xA2, 0xDB, 0x06, 0x64, 0x5A, 0xDB, 0x5A, 0xDB, 0x1C, 0x60, 0xC2, 0x62, 0xA2, 0xDF, + 0x06, 0xA2, 0x10, 0x60, 0x8C, 0x64, 0xA2, 0xDB, 0x06, 0x64, 0x5A, 0xDB, 0x5A, 0xDB, 0x1C, 0x60, + 0xCE, 0x62, 0xA2, 0xDF, 0x06, 0xA2, 0x10, 0x60, 0x90, 0x64, 0xA2, 0xDB, 0x06, 0x64, 0x5A, 0xDB, + 0x5A, 0xDB, 0xBD, 0xF1, 0x0E, 0x60, 0x69, 0xF9, 0x24, 0x60, 0xC1, 0x64, 0x08, 0x60, 0x43, 0xFB, + 0x24, 0x60, 0xCA, 0x64, 0x08, 0x60, 0x45, 0xFB, 0x24, 0x60, 0xD3, 0x64, 0x08, 0x60, 0x47, 0xFB, + 0x00, 0x60, 0x3A, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x62, 0xFB, + 0x04, 0x64, 0x03, 0xFA, 0xA6, 0xF3, 0x07, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x00, 0x60, + 0x02, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x20, 0x60, 0x63, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x10, 0x60, 0x18, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x69, 0xFB, 0x0F, 0x4E, + 0xEA, 0x60, 0x58, 0x4F, 0x34, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x00, 0x64, 0x6B, 0xFB, 0x62, 0xF5, + 0xEA, 0xF3, 0x2F, 0xFA, 0xEB, 0xF3, 0x30, 0xFA, 0xEC, 0xF3, 0x31, 0xFA, 0x7F, 0xF3, 0x2C, 0xFA, + 0x32, 0xFA, 0x80, 0xF3, 0x2D, 0xFA, 0x33, 0xFA, 0x81, 0xF3, 0x2E, 0xFA, 0x34, 0xFA, 0xB9, 0xF3, + 0x19, 0xFA, 0x06, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0xF7, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, + 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x08, 0x60, + 0x0C, 0xF1, 0xFF, 0x60, 0x8F, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xBE, 0xF1, 0x0E, 0x60, 0x63, 0xF9, + 0x1C, 0x60, 0xC2, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0x00, 0x64, 0x6B, 0xFB, 0x00, 0x60, 0x74, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x20, 0x60, 0xAE, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x04, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x23, 0x60, 0x85, 0x78, 0xFF, 0xFF, + 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xE2, 0x01, + 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x11, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, + 0x50, 0x27, 0xD8, 0x01, 0xAC, 0xF3, 0xFF, 0xFF, 0xFE, 0xA0, 0xFF, 0xFF, 0x0F, 0x06, 0x6B, 0xF3, + 0xFF, 0xFF, 0xEC, 0xA0, 0xDC, 0x84, 0x01, 0x05, 0xA2, 0xDB, 0xCC, 0x01, 0x00, 0x60, 0x10, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0xCF, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x01, 0x00, 0xC3, 0x01, 0x01, 0x64, + 0x19, 0x60, 0xF3, 0xFB, 0xDF, 0xF3, 0x29, 0x45, 0xD4, 0x80, 0x6B, 0xF3, 0x03, 0x04, 0x21, 0x60, + 0x28, 0x78, 0xFF, 0xFF, 0xEC, 0xA0, 0x00, 0x64, 0x04, 0x04, 0x40, 0x49, 0x21, 0x60, 0x28, 0x78, + 0xFF, 0xFF, 0x00, 0x60, 0x64, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x20, 0x60, 0xFD, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, + 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x23, 0x60, 0x85, 0x78, 0xFF, 0xFF, 0x00, 0x60, + 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xD0, 0x01, 0x00, 0x60, + 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xE5, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, 0x50, 0x27, + 0xE0, 0x01, 0xAC, 0xF3, 0xFF, 0xFF, 0xFE, 0xA0, 0xFF, 0xFF, 0x07, 0x06, 0x6B, 0xF3, 0xFF, 0xFF, + 0xEC, 0xA0, 0xDC, 0x84, 0x01, 0x05, 0xA2, 0xDB, 0xBA, 0x01, 0xB9, 0x01, 0x33, 0x60, 0xE6, 0x65, + 0xA5, 0xDF, 0xBF, 0xF1, 0x0E, 0x60, 0x63, 0xF9, 0xE0, 0xF3, 0x29, 0x45, 0x03, 0xA4, 0xD4, 0x80, + 0x01, 0x63, 0x01, 0x05, 0x00, 0x63, 0x53, 0xFD, 0x7D, 0xF3, 0x01, 0x60, 0x00, 0x65, 0xA4, 0x80, + 0x24, 0x44, 0xFE, 0xB4, 0x01, 0x03, 0x01, 0xBC, 0x40, 0x44, 0x21, 0x60, 0x45, 0x64, 0x6A, 0xFB, + 0x23, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0xFF, 0x60, 0xDF, 0x64, 0xA0, 0x84, + 0xA2, 0xDB, 0x86, 0xF1, 0x1B, 0x60, 0xB2, 0x63, 0xD3, 0x80, 0x67, 0xFD, 0x43, 0x03, 0x67, 0xF3, + 0xE1, 0xF1, 0x60, 0x43, 0x29, 0x44, 0xA3, 0xD3, 0xC0, 0x85, 0xD4, 0x80, 0x5B, 0xD3, 0x3A, 0x06, + 0x60, 0x43, 0x08, 0xA3, 0xBE, 0xD3, 0x81, 0xF1, 0xA3, 0xD3, 0xD0, 0x80, 0x80, 0xF1, 0x05, 0x02, + 0xBF, 0xD3, 0xD0, 0x80, 0x7F, 0xF1, 0x01, 0x02, 0xD0, 0x80, 0xF8, 0xA3, 0x28, 0x02, 0x21, 0x60, + 0x77, 0x64, 0x6A, 0xFB, 0x23, 0x60, 0xB4, 0x78, 0xFF, 0xFF, 0x01, 0xB0, 0x82, 0xF3, 0x22, 0x03, + 0x62, 0xF5, 0x48, 0x7E, 0x2A, 0xFA, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x60, 0x01, 0x64, + 0x08, 0x60, 0x0D, 0xFB, 0x21, 0x60, 0x92, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x08, 0x60, 0x0C, 0xF1, 0xFF, 0x60, 0xFE, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x03, 0x00, 0x23, 0x60, + 0x7A, 0x78, 0xFF, 0xFF, 0x6B, 0xF3, 0xFF, 0xFF, 0xEC, 0xA0, 0x00, 0x64, 0x02, 0x04, 0x40, 0x49, + 0x15, 0x00, 0xDF, 0xF3, 0x29, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x0B, 0x07, 0x1C, 0x60, 0xC2, 0x64, + 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x20, 0x60, 0x86, 0x78, + 0xFF, 0xFF, 0xE0, 0xF3, 0x29, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x16, 0x06, 0x04, 0x65, 0xF1, 0x60, + 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, 0x05, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, + 0xF1, 0xFB, 0x1C, 0x60, 0xC2, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0x22, 0x60, 0x1B, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x74, 0x64, 0x08, 0x60, 0x0D, 0xFB, + 0x21, 0x60, 0xD8, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, + 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x23, 0x60, + 0x85, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0xB0, 0x01, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x15, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x20, 0x40, 0x50, 0x27, 0xA6, 0x01, 0xAC, 0xF3, 0x6B, 0xF3, 0xFE, 0xA0, 0xEC, 0xA0, + 0x0A, 0x06, 0x03, 0x04, 0x00, 0x64, 0x55, 0xFB, 0x40, 0x49, 0x6B, 0xF3, 0xFF, 0xFF, 0xEC, 0xA0, + 0xDC, 0x84, 0x01, 0x05, 0xA2, 0xDB, 0x96, 0x01, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x0D, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x21, 0x60, 0x28, 0x78, 0xFF, 0xFF, 0x21, 0x60, 0x9C, 0x78, + 0xFF, 0xFF, 0x7D, 0xF3, 0x01, 0x60, 0x00, 0x65, 0xA4, 0x80, 0x24, 0x44, 0xFE, 0xB4, 0x01, 0x03, + 0x01, 0xBC, 0x02, 0xB0, 0xFB, 0xB4, 0x01, 0x03, 0x04, 0xBC, 0x40, 0x44, 0xC0, 0xF1, 0x0E, 0x60, + 0x63, 0xF9, 0xCF, 0xF3, 0x20, 0x60, 0x20, 0x65, 0x30, 0x1B, 0xA5, 0xD3, 0x24, 0x40, 0x01, 0x26, + 0x16, 0x00, 0x60, 0x40, 0x20, 0x26, 0x29, 0x00, 0x01, 0xBC, 0xA5, 0xDB, 0x08, 0x60, 0x1E, 0xF1, + 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, + 0x0D, 0xFB, 0x22, 0x60, 0x5F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x60, 0x40, + 0x10, 0x26, 0x13, 0x00, 0x01, 0xBC, 0xA5, 0xDB, 0x08, 0x60, 0x1E, 0xF1, 0x00, 0x60, 0x40, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x22, 0x60, + 0x5F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0D, 0x64, 0x53, 0xFB, 0x22, 0x60, + 0x67, 0x64, 0x6A, 0xFB, 0x23, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xCE, 0x64, 0x13, 0x60, + 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0xFF, 0x60, + 0xDF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x86, 0xF1, 0x1B, 0x60, 0xB2, 0x63, 0xD3, 0x80, 0x67, 0xFD, + 0x07, 0x02, 0x24, 0x44, 0x04, 0xB0, 0xFF, 0xFF, 0x36, 0x03, 0x05, 0xAC, 0x40, 0x44, 0xA6, 0x01, + 0x67, 0xF3, 0x29, 0x41, 0xA0, 0xD1, 0x58, 0xD3, 0xD1, 0x80, 0x64, 0x45, 0x60, 0x43, 0x2B, 0x05, + 0x08, 0xA3, 0xBE, 0xD3, 0x81, 0xF1, 0xA3, 0xD3, 0xD0, 0x80, 0x80, 0xF1, 0x05, 0x02, 0xBF, 0xD3, + 0xD0, 0x80, 0x7F, 0xF1, 0x01, 0x02, 0xD0, 0x80, 0xF8, 0xA3, 0x07, 0x02, 0x45, 0x49, 0x22, 0x60, + 0xCD, 0x64, 0x6A, 0xFB, 0x23, 0x60, 0xB4, 0x78, 0xFF, 0xFF, 0x05, 0x65, 0xF1, 0x60, 0x58, 0x4E, + 0xC3, 0x78, 0xFF, 0xFF, 0x04, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF1, 0xFB, + 0x23, 0x60, 0x7A, 0x78, 0xFF, 0xFF, 0x67, 0xF3, 0x86, 0xF1, 0x04, 0xA4, 0xD0, 0x80, 0xFF, 0xFF, + 0x02, 0x03, 0x67, 0xFB, 0xCD, 0x01, 0x6B, 0xF3, 0xFF, 0xFF, 0xEC, 0xA0, 0xFF, 0xFF, 0x01, 0x04, + 0x75, 0x00, 0xE0, 0xF3, 0x29, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x70, 0x05, 0x7D, 0xF3, 0xFF, 0xFF, + 0x60, 0x40, 0x01, 0x27, 0x08, 0x00, 0x22, 0x60, 0xCD, 0x63, 0x6A, 0xFD, 0x1C, 0x60, 0x78, 0x63, + 0x23, 0x60, 0xB4, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xC2, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x05, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, + 0x20, 0x60, 0x14, 0x61, 0xA1, 0xDF, 0x04, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, + 0xF1, 0xFB, 0x82, 0xF3, 0x62, 0xF5, 0x48, 0x7E, 0x2A, 0xFA, 0x02, 0x60, 0x00, 0x65, 0x20, 0x44, + 0x34, 0x80, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x60, 0x01, 0x64, 0x08, 0x60, 0x0D, 0xFB, + 0x23, 0x60, 0x00, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, + 0xFF, 0x60, 0xFE, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x00, 0x60, 0x32, 0x64, 0x0E, 0x60, 0x63, 0xFB, + 0x1C, 0x60, 0xC2, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0x00, 0x60, 0x10, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x23, 0x60, 0x1C, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0xFF, 0x60, 0xEF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, + 0xFD, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x20, 0x60, 0x86, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x74, 0x64, + 0x08, 0x60, 0x0D, 0xFB, 0x23, 0x60, 0x3A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x23, 0x60, 0x85, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x67, 0x01, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x15, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, 0x50, 0x27, 0xE0, 0x01, 0xAC, 0xF3, 0x6B, 0xF3, + 0xFE, 0xA0, 0xEC, 0xA0, 0x0A, 0x06, 0x03, 0x04, 0x00, 0x64, 0x55, 0xFB, 0x40, 0x49, 0x6B, 0xF3, + 0xFF, 0xFF, 0xEC, 0xA0, 0xDC, 0x84, 0x01, 0x05, 0xA2, 0xDB, 0x4D, 0x01, 0x00, 0x60, 0x10, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0xCB, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0xCE, 0x64, 0x13, 0x60, + 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x22, 0x60, 0x1B, 0x78, 0xFF, 0xFF, + 0x08, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x20, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x1C, 0x60, 0xB6, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x1C, 0x60, 0xC2, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x1C, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x08, 0x60, 0x0C, 0xFB, 0x5A, 0xDB, 0x00, 0x64, + 0x69, 0xFB, 0x08, 0x60, 0x08, 0xF1, 0x02, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x00, 0x60, 0x02, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x20, 0x60, 0x63, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0xA3, 0xD3, 0x7D, 0xF1, 0x7C, 0xFB, 0xD0, 0x80, 0x00, 0x64, 0x39, 0x03, + 0x08, 0x60, 0x0C, 0xF1, 0xBF, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, + 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x23, 0x60, 0xBA, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0xDF, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, + 0x7C, 0xF1, 0x7D, 0xF9, 0x13, 0x60, 0x1A, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, + 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x23, 0x60, 0xE4, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x08, 0x60, 0x0C, 0xF1, 0xDF, 0x60, 0xFF, 0x64, 0xA0, 0x84, + 0xA2, 0xDB, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x01, 0x64, 0x6A, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, + 0x08, 0x60, 0x0C, 0xF1, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, 0x51, 0x23, + 0x0A, 0x00, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x23, 0x60, 0xFA, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0x7F, 0x60, 0xFF, 0x61, 0xA1, 0x84, + 0x5A, 0xD1, 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x02, 0x64, 0x8A, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, + 0x8A, 0xF3, 0x00, 0x65, 0xD4, 0x80, 0xFF, 0xFF, 0x10, 0x03, 0x08, 0x60, 0x0C, 0xF1, 0x7F, 0x60, + 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x24, 0x60, + 0x16, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x33, 0x60, 0xBE, 0x64, 0x54, 0xFB, + 0x08, 0x60, 0x0C, 0xF1, 0xEF, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x44, 0x01, 0xB0, + 0xFF, 0xFF, 0x08, 0x02, 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x07, 0x00, 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x24, 0x60, 0x55, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0xC2, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0xEF, 0x60, 0xEF, 0x64, 0xA0, 0x84, + 0xA2, 0xDB, 0x01, 0x64, 0x8A, 0xFB, 0x6B, 0xF3, 0x00, 0x60, 0x95, 0xF3, 0xEC, 0xA0, 0x40, 0xBC, + 0x06, 0x04, 0xA2, 0xDB, 0x69, 0xF1, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, 0x69, 0xFB, 0xFD, 0x60, + 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, 0x6A, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0xF1, 0x28, 0x44, + 0xD0, 0x84, 0x03, 0xA4, 0x03, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0x04, 0x00, 0xFA, 0xA4, 0xE8, 0x84, + 0xE8, 0x87, 0xC0, 0xBF, 0xC0, 0x84, 0xA2, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0x56, 0xF1, 0x28, 0x44, + 0xD0, 0x84, 0x1F, 0xA4, 0x06, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, + 0x07, 0x00, 0xC2, 0xA4, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x87, 0xF8, 0xBF, + 0xC0, 0x84, 0x5B, 0xF1, 0x56, 0xFB, 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x05, 0x64, 0x44, 0x52, 0xFB, + 0x2E, 0x58, 0xFF, 0xFF, 0x52, 0xF1, 0x2F, 0x67, 0xD0, 0x80, 0x60, 0x45, 0x02, 0x28, 0x64, 0x45, + 0x55, 0xF1, 0x8B, 0x67, 0xD0, 0x80, 0x60, 0x41, 0x02, 0x24, 0x64, 0x41, 0xD5, 0x84, 0x80, 0x65, + 0xC4, 0x87, 0x01, 0x05, 0x00, 0x64, 0xFF, 0xB4, 0x40, 0x49, 0x2E, 0x58, 0xFF, 0xFF, 0x08, 0x60, + 0x0C, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x40, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x26, 0x46, 0x27, 0xF2, 0x70, 0x63, 0x60, 0x40, 0x0A, 0x36, 0x10, 0x00, 0x14, 0x36, + 0x14, 0x00, 0x37, 0x36, 0x0E, 0x00, 0x6E, 0x36, 0x0E, 0x00, 0x06, 0x36, 0x04, 0x00, 0x09, 0x36, + 0x04, 0x00, 0x18, 0x63, 0x0A, 0x00, 0x30, 0x63, 0x08, 0x00, 0x26, 0x63, 0x06, 0x00, 0xD0, 0x63, + 0x04, 0x00, 0x33, 0x63, 0x02, 0x00, 0x21, 0x63, 0x00, 0x00, 0x10, 0x60, 0x0E, 0xFD, 0x26, 0x46, + 0x3F, 0xF2, 0x87, 0xF0, 0x00, 0xF4, 0x45, 0x43, 0x03, 0x4B, 0x60, 0x43, 0xF4, 0xA3, 0x00, 0x60, + 0x1D, 0x61, 0x00, 0x60, 0x01, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, + 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x00, 0x02, 0x00, 0x64, 0x40, 0x4A, 0x60, 0xFE, + 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xFE, 0x60, 0x58, 0x4E, 0x2C, 0x78, + 0xFF, 0xFF, 0x20, 0xFE, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xF4, 0xA3, 0x00, 0x60, + 0x1D, 0x61, 0x00, 0x60, 0x32, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, + 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x0B, 0x03, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, + 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xFE, 0x60, 0x58, 0x4E, 0x2C, 0x78, 0xFF, 0xFF, 0x20, 0xFE, + 0x2A, 0x44, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xF2, 0x01, 0x60, + 0x00, 0x65, 0xF4, 0xA4, 0xD4, 0x80, 0x60, 0x41, 0x02, 0x24, 0x65, 0x41, 0x41, 0x48, 0x00, 0xF4, + 0x1E, 0x65, 0x02, 0x60, 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, + 0x04, 0x65, 0x64, 0x44, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, + 0xCD, 0x81, 0xBD, 0xDB, 0xF0, 0x02, 0x02, 0x60, 0x00, 0x63, 0x28, 0x41, 0xBD, 0xD3, 0xBD, 0xD1, + 0xFD, 0xA0, 0xFE, 0xA1, 0x07, 0x03, 0x09, 0x06, 0x64, 0x44, 0xE0, 0x85, 0xD1, 0x81, 0xC7, 0x83, + 0xF5, 0x07, 0x03, 0x00, 0xA3, 0xD3, 0x0E, 0x60, 0x3C, 0xFB, 0x31, 0x40, 0x06, 0x26, 0x57, 0x00, + 0x00, 0x64, 0x6F, 0xFB, 0x02, 0x60, 0x00, 0x63, 0x28, 0x41, 0xBD, 0xD3, 0xBD, 0xD1, 0xFC, 0xA0, + 0xFB, 0xA0, 0x09, 0x03, 0x28, 0x03, 0x64, 0x44, 0xE0, 0x85, 0xC7, 0x83, 0xD1, 0x81, 0xFE, 0xA1, + 0x46, 0x06, 0xF3, 0x07, 0x44, 0x00, 0xBD, 0xD3, 0xBD, 0xD3, 0x00, 0xB8, 0x6F, 0xFB, 0x6E, 0xFB, + 0xBD, 0xD3, 0x3D, 0x02, 0xA3, 0xD3, 0x60, 0x45, 0x60, 0x47, 0xB4, 0x84, 0x60, 0x41, 0x3F, 0xB5, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x71, 0xFB, 0x65, 0x47, + 0xE0, 0x84, 0xE0, 0x84, 0x70, 0xFB, 0x64, 0x44, 0xE0, 0x85, 0xFA, 0xA3, 0xC7, 0x83, 0x61, 0x44, + 0x0E, 0x60, 0x38, 0xFB, 0xD2, 0x01, 0xBD, 0xD3, 0xA3, 0xD3, 0x00, 0xB8, 0x6D, 0xFB, 0x73, 0xFB, + 0x1E, 0x02, 0x85, 0xF1, 0x6F, 0xF3, 0x6C, 0xF9, 0x04, 0x65, 0x60, 0x40, 0x00, 0x3A, 0x06, 0x65, + 0x31, 0x44, 0xB4, 0x84, 0x40, 0x51, 0x02, 0x2A, 0x0B, 0x00, 0x08, 0xBC, 0x40, 0x51, 0x71, 0xF3, + 0x70, 0xF1, 0x00, 0xB8, 0x64, 0x45, 0x01, 0x03, 0x67, 0x45, 0x65, 0x50, 0xCC, 0x84, 0x72, 0xFB, + 0x08, 0x60, 0x15, 0xF1, 0x01, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x08, 0x60, + 0x16, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2A, 0x3F, 0x00, 0x01, 0x64, 0x10, 0x60, 0x0A, 0xFB, + 0x26, 0x60, 0x58, 0x4E, 0x65, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x0D, 0xF2, 0x7E, 0xFB, + 0x00, 0x64, 0x84, 0xFB, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xF4, 0xA3, 0x00, 0x60, + 0x1D, 0x61, 0x00, 0x60, 0x07, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, + 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x14, 0x03, 0x02, 0x60, 0x00, 0x65, 0xA5, 0xD3, + 0x1C, 0x60, 0xE6, 0x63, 0xFF, 0xB4, 0x01, 0xA4, 0x60, 0x41, 0xA5, 0xD1, 0xDA, 0x85, 0x64, 0x44, + 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, + 0xF4, 0x02, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x80, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x32, 0x00, 0x27, 0x60, 0x57, 0x78, 0xFF, 0xFF, 0xDB, 0xF3, 0xFF, 0xFF, 0x03, 0xA8, 0x02, 0xA8, + 0x02, 0x03, 0x3E, 0x02, 0xF6, 0x01, 0x08, 0x60, 0x15, 0xF1, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, + 0xA2, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0x26, 0x46, 0x10, 0x60, 0x0E, 0xF3, 0x25, 0xF2, 0x60, 0x45, 0x24, 0xF0, 0x00, 0xF4, + 0x64, 0x43, 0xC7, 0x83, 0x60, 0x41, 0x02, 0x24, 0x01, 0xA1, 0x0A, 0xF0, 0x09, 0xF2, 0xD1, 0x80, + 0xFF, 0xFF, 0x09, 0x07, 0x04, 0x04, 0x63, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x04, 0x06, 0x26, 0x60, + 0x58, 0x4E, 0x65, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x26, 0xF0, 0xFF, 0x67, 0x20, 0x88, 0x64, 0x5F, + 0x40, 0x4A, 0x24, 0x60, 0x58, 0x4E, 0x80, 0x78, 0xFF, 0xFF, 0x0A, 0x48, 0x24, 0x60, 0x58, 0x4E, + 0x90, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, + 0x08, 0x60, 0x0D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x22, 0xB3, 0x01, 0x00, 0x60, 0x95, 0xF3, + 0xFF, 0xFF, 0xBF, 0xB4, 0xA2, 0xDB, 0x10, 0x60, 0x0E, 0xF3, 0x26, 0x46, 0x60, 0x45, 0x20, 0x60, + 0x04, 0x63, 0x00, 0xF4, 0x09, 0xF2, 0xBD, 0xDB, 0xFF, 0xFF, 0x0A, 0xF2, 0xBD, 0xDB, 0x0B, 0xF2, + 0xFF, 0xFF, 0xBD, 0xDB, 0x0C, 0xF2, 0xA3, 0xDB, 0xFA, 0xA3, 0x26, 0x46, 0xA3, 0xD3, 0x24, 0xF0, + 0x00, 0x61, 0xD0, 0x84, 0xF1, 0x81, 0xD4, 0x84, 0xF1, 0x81, 0xBD, 0xDB, 0xA3, 0xD3, 0x03, 0xB1, + 0x03, 0xA9, 0x25, 0xF0, 0x42, 0xFE, 0x05, 0x03, 0xFD, 0xA1, 0xCC, 0x84, 0x01, 0x02, 0xCC, 0x84, + 0x00, 0x61, 0xF1, 0x81, 0xD0, 0x84, 0xF1, 0x81, 0xBD, 0xDB, 0xA3, 0xD3, 0x03, 0xB1, 0x03, 0xA9, + 0x28, 0xF0, 0x42, 0xFE, 0x01, 0x03, 0xCC, 0x84, 0xF1, 0x81, 0xD0, 0x84, 0xF1, 0x81, 0xBD, 0xDB, + 0xA3, 0xD3, 0x03, 0xB1, 0x03, 0xA9, 0x29, 0xF0, 0x01, 0x03, 0xCC, 0x84, 0xD0, 0x84, 0xA3, 0xDB, + 0x10, 0x60, 0x0A, 0xF3, 0xFF, 0xFF, 0x02, 0xA8, 0xFF, 0xFF, 0x02, 0x02, 0x2E, 0x58, 0xFF, 0xFF, + 0xF5, 0xFE, 0x10, 0x60, 0x02, 0xF1, 0x06, 0xA2, 0xA2, 0xD3, 0x64, 0x45, 0x60, 0x40, 0x80, 0x2B, + 0x03, 0x00, 0xFF, 0x60, 0xFF, 0x64, 0x94, 0x85, 0x00, 0x60, 0x96, 0x64, 0xD4, 0x80, 0xFF, 0xFF, + 0x0A, 0x06, 0x10, 0x60, 0x0A, 0xF3, 0x69, 0xF3, 0x00, 0xA8, 0x04, 0xB0, 0x04, 0x02, 0x03, 0x03, + 0x27, 0x60, 0x33, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x09, 0xF2, 0x5A, 0xD2, 0x40, 0x48, + 0x40, 0x4A, 0x5A, 0xD2, 0x5A, 0xD2, 0x40, 0x4C, 0x60, 0x41, 0x5A, 0xD0, 0x7E, 0xF9, 0x40, 0x63, + 0xAD, 0x80, 0xF0, 0xA3, 0x09, 0x02, 0x3C, 0x03, 0x2C, 0x41, 0x2A, 0x44, 0x40, 0x4C, 0x28, 0x44, + 0x40, 0x4A, 0x00, 0x64, 0x40, 0x48, 0xF4, 0x01, 0xD1, 0x80, 0x01, 0x02, 0x31, 0x04, 0x10, 0xA3, + 0x80, 0x60, 0x00, 0x65, 0xA5, 0x80, 0xCF, 0x83, 0x08, 0x02, 0x28, 0x44, 0x60, 0x88, 0x2A, 0x44, + 0x70, 0x8A, 0x2C, 0x44, 0x70, 0x8C, 0xF1, 0x81, 0xF5, 0x01, 0xE7, 0xA3, 0x64, 0x44, 0x00, 0xA8, + 0x00, 0x62, 0x02, 0x02, 0x00, 0x61, 0x1C, 0x00, 0xE0, 0x84, 0xDE, 0x82, 0xFD, 0x04, 0x42, 0xFE, + 0xF8, 0x84, 0x62, 0x45, 0xC7, 0x83, 0x60, 0x45, 0x02, 0xFE, 0xD5, 0x84, 0x02, 0x05, 0x01, 0x05, + 0x61, 0x44, 0xCF, 0x83, 0x60, 0x41, 0x08, 0x03, 0x28, 0x44, 0x60, 0x88, 0x2A, 0x44, 0x70, 0x8A, + 0x2C, 0x44, 0x70, 0x8C, 0xF1, 0x81, 0xF1, 0x01, 0xCE, 0x82, 0xE9, 0x81, 0xFD, 0x02, 0xF1, 0x81, + 0x09, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0xE8, 0x84, 0xE8, 0x84, 0x5A, 0xD2, 0x3F, 0xB5, 0xE0, 0x84, + 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xB4, 0x84, 0x61, 0x45, 0xD4, 0x84, + 0xC0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x93, 0x10, 0x60, 0x0A, 0xF3, 0xFF, 0xFF, + 0x02, 0x18, 0x2E, 0x58, 0xFF, 0xFF, 0x16, 0x65, 0x32, 0x40, 0x80, 0x26, 0x16, 0x65, 0x73, 0x44, + 0xD4, 0x93, 0x69, 0xF3, 0x26, 0x46, 0x04, 0xBC, 0xA2, 0xDB, 0x26, 0xF0, 0xFF, 0x67, 0x20, 0x88, + 0x64, 0x5F, 0x40, 0x4A, 0x24, 0x60, 0x58, 0x4E, 0x80, 0x78, 0xFF, 0xFF, 0x0A, 0x48, 0x24, 0x60, + 0x58, 0x4E, 0x90, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x6B, 0xF3, + 0xFF, 0xFF, 0xC8, 0x84, 0xFF, 0xFF, 0x01, 0x05, 0x00, 0x64, 0x6B, 0xFB, 0x08, 0x60, 0x0C, 0xF1, + 0x00, 0x60, 0x40, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x1C, 0x60, 0xCE, 0x64, 0x13, 0x60, + 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0xFF, 0x60, + 0xDF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1E, 0xF1, + 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, + 0xDA, 0x63, 0xA3, 0xDF, 0x06, 0xA3, 0x10, 0x60, 0xA4, 0x64, 0xBD, 0xDB, 0xBD, 0xDB, 0x06, 0x64, + 0xA3, 0xDB, 0x27, 0x60, 0x68, 0x64, 0x08, 0x60, 0x51, 0xFB, 0x10, 0x60, 0x0F, 0xF1, 0x0E, 0x60, + 0x6F, 0xF9, 0x27, 0x60, 0xCF, 0x64, 0x08, 0x60, 0x38, 0xFB, 0x11, 0x60, 0x44, 0x63, 0x08, 0x60, + 0x66, 0xFD, 0x12, 0x60, 0x40, 0x63, 0x08, 0x60, 0x67, 0xFD, 0xCF, 0xF3, 0x02, 0x63, 0x01, 0x1B, + 0xCF, 0xFD, 0xCF, 0xF3, 0xFF, 0xFF, 0xF7, 0xA0, 0x01, 0x64, 0x01, 0x06, 0xCF, 0xFB, 0xCF, 0xF3, + 0xCF, 0xFB, 0xCF, 0xF3, 0x12, 0x60, 0x78, 0x63, 0x26, 0x18, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, + 0x2A, 0xA3, 0xFB, 0x01, 0x63, 0x46, 0x10, 0x60, 0xF2, 0x63, 0x0E, 0x61, 0x60, 0xFE, 0xA6, 0xD1, + 0xDE, 0x86, 0x01, 0x64, 0x64, 0x40, 0x7F, 0x36, 0x00, 0x64, 0xA3, 0xDB, 0xDB, 0x83, 0xA3, 0xD9, + 0xCD, 0x81, 0x04, 0xA3, 0xF4, 0x02, 0x11, 0x60, 0x62, 0x63, 0x1C, 0x61, 0xA6, 0xD1, 0xDE, 0x86, + 0x01, 0x64, 0x64, 0x40, 0x7F, 0x36, 0x00, 0x64, 0xA3, 0xDB, 0xDB, 0x83, 0xA3, 0xD9, 0xCD, 0x81, + 0x06, 0xA3, 0xF4, 0x02, 0x20, 0xFE, 0x00, 0x60, 0x60, 0x64, 0x08, 0x60, 0x1F, 0xFB, 0x27, 0x60, + 0xE1, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x11, 0x60, 0x44, 0x63, 0x08, 0x60, + 0x66, 0xFD, 0x12, 0x60, 0x40, 0x63, 0x08, 0x60, 0x67, 0xFD, 0x00, 0x60, 0x60, 0x64, 0x08, 0x60, + 0x1F, 0xFB, 0x27, 0x60, 0xE1, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x28, 0xF3, + 0xFF, 0xFF, 0x60, 0x47, 0x0F, 0xB4, 0x98, 0x00, 0xFF, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x04, 0x64, + 0x13, 0x60, 0x1C, 0xFB, 0x27, 0x00, 0x0C, 0x64, 0x3F, 0x40, 0x02, 0x2B, 0x23, 0x00, 0x29, 0xF1, + 0x13, 0x60, 0x1C, 0xFB, 0x5A, 0xD9, 0x27, 0x60, 0xFD, 0x64, 0x9F, 0xFB, 0xFF, 0xFF, 0x2D, 0xFF, + 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x29, 0x60, 0x1C, 0x63, 0x09, 0x61, 0x3D, 0x60, 0x58, 0x4D, + 0x23, 0x78, 0xFF, 0xFF, 0x75, 0x00, 0x95, 0xF3, 0xFF, 0xFF, 0x7F, 0xB4, 0x95, 0xFB, 0x06, 0x64, + 0x13, 0x60, 0x1C, 0xFB, 0xFF, 0xFF, 0x2D, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x08, 0x64, + 0x13, 0x60, 0x1C, 0xFB, 0x28, 0x60, 0x7A, 0x64, 0x9F, 0xFB, 0xFF, 0xFF, 0x2D, 0xFF, 0x2A, 0x60, + 0x1D, 0x78, 0xFF, 0xFF, 0x29, 0xF3, 0x12, 0x60, 0x45, 0x65, 0x60, 0x5C, 0x3F, 0x40, 0x02, 0x2B, + 0x13, 0x00, 0x00, 0x37, 0x11, 0x00, 0x01, 0x3B, 0x53, 0x00, 0x11, 0x60, 0x65, 0x63, 0xFF, 0xB7, + 0x60, 0x5C, 0xA3, 0xD3, 0x08, 0xA3, 0x00, 0x7E, 0xD0, 0x80, 0xD7, 0x80, 0x02, 0x03, 0xF9, 0x02, + 0x47, 0x00, 0xF4, 0xA3, 0xA3, 0xD3, 0x05, 0x00, 0x00, 0xBC, 0xF2, 0xA4, 0x41, 0x03, 0x40, 0x07, + 0x64, 0x44, 0x7D, 0xFB, 0xA1, 0xFB, 0x07, 0x64, 0xA2, 0xFB, 0x28, 0x60, 0x7A, 0x64, 0x9F, 0xFB, + 0xFF, 0xFF, 0xDF, 0xFE, 0x00, 0x64, 0x19, 0xFF, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x88, 0xFF, + 0xBA, 0x60, 0x98, 0x71, 0x8D, 0xE2, 0x01, 0x11, 0x09, 0x00, 0x71, 0x40, 0x80, 0x27, 0xFB, 0x01, + 0x88, 0xE2, 0xBA, 0x60, 0xD0, 0x64, 0x03, 0xFB, 0x8D, 0xFF, 0x15, 0x00, 0x8D, 0xFF, 0x28, 0x60, + 0xFB, 0x63, 0x06, 0x60, 0x0B, 0xFD, 0xFF, 0xFF, 0x62, 0xFF, 0x28, 0x60, 0x67, 0x63, 0x9F, 0xFD, + 0xFF, 0xFF, 0x1A, 0xFF, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0xA3, 0x60, 0xF4, 0x63, 0x06, 0x60, + 0x0B, 0xFD, 0xFF, 0xFF, 0x62, 0xFF, 0x29, 0xF5, 0x26, 0x60, 0x20, 0x63, 0x25, 0x60, 0xF2, 0x64, + 0xBD, 0xDB, 0x66, 0x44, 0xBD, 0xDB, 0x02, 0x64, 0xA3, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF9, 0xFE, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x68, 0x01, 0x00, 0x36, 0x69, 0x01, 0x01, 0x36, 0x6B, 0x01, + 0x02, 0x36, 0x81, 0x01, 0x03, 0x36, 0x8B, 0x01, 0x04, 0x36, 0xC1, 0x01, 0x05, 0x36, 0xBF, 0x01, + 0x06, 0x36, 0xF1, 0x01, 0x07, 0x36, 0xBB, 0x01, 0x08, 0x36, 0x8C, 0x01, 0x09, 0x36, 0x0C, 0x00, + 0x0A, 0x36, 0x0D, 0x00, 0x0B, 0x36, 0x0E, 0x00, 0x0C, 0x36, 0x17, 0x00, 0x0D, 0x36, 0x0D, 0x00, + 0x0E, 0x36, 0x1D, 0x00, 0x0F, 0x36, 0x41, 0x00, 0x02, 0x60, 0x00, 0x64, 0x08, 0x00, 0x04, 0x60, + 0x00, 0x64, 0x05, 0x00, 0x00, 0x60, 0x01, 0x64, 0x02, 0x00, 0x20, 0x60, 0x00, 0x64, 0x32, 0x45, + 0xB4, 0x85, 0x45, 0x52, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x29, 0x60, 0xDE, 0x63, 0x06, 0x60, + 0x0B, 0xFD, 0x62, 0xFF, 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x3F, 0x40, + 0x02, 0x2B, 0x15, 0x00, 0x88, 0xFF, 0xBA, 0x60, 0x98, 0x71, 0x8D, 0xE2, 0x01, 0x11, 0x09, 0x00, + 0x71, 0x40, 0x80, 0x27, 0xFB, 0x01, 0x88, 0xE2, 0xBA, 0x60, 0xD0, 0x64, 0x03, 0xFB, 0x8D, 0xFF, + 0x11, 0x00, 0x8D, 0xFF, 0x90, 0x60, 0x00, 0xE8, 0x28, 0x60, 0xFB, 0x63, 0x04, 0x00, 0x91, 0x60, + 0x00, 0xE8, 0x29, 0x60, 0xC4, 0x63, 0x2A, 0xE8, 0x06, 0x60, 0x0B, 0xFD, 0xFF, 0xFF, 0x62, 0xFF, + 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xF1, 0xF3, 0xFF, 0xFF, 0xEF, 0xB4, + 0xF1, 0xFB, 0xAD, 0x4F, 0xFD, 0xB4, 0xA0, 0x5D, 0xD0, 0x60, 0x00, 0xE8, 0x2A, 0xE8, 0xD9, 0x60, + 0xFE, 0x64, 0x32, 0x45, 0xA4, 0x85, 0x45, 0x52, 0x99, 0xFF, 0xA5, 0x4F, 0xFF, 0xB4, 0x07, 0xFB, + 0x98, 0xFF, 0xA3, 0x60, 0xF4, 0x63, 0x06, 0x60, 0x0B, 0xFD, 0x62, 0xFF, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x43, 0xFF, 0x01, 0x60, 0x00, 0xE1, 0x28, 0xF3, + 0x47, 0xFF, 0x60, 0x40, 0x07, 0x37, 0x66, 0x00, 0x05, 0x3B, 0x04, 0x00, 0xFF, 0x0A, 0x80, 0xE1, + 0xA1, 0xFF, 0xFF, 0xFF, 0x1B, 0x60, 0xF3, 0xF1, 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, + 0x7D, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, + 0xA0, 0x5D, 0x29, 0xF5, 0x2A, 0xF3, 0x47, 0xFF, 0x3F, 0xF0, 0x01, 0x1B, 0x01, 0x64, 0x60, 0x56, + 0xAD, 0xE2, 0xB5, 0xFF, 0x6C, 0x40, 0x40, 0xE1, 0xA1, 0xFF, 0x00, 0xF4, 0x6E, 0x61, 0x12, 0x62, + 0x64, 0x43, 0x01, 0xE1, 0x03, 0x64, 0xE2, 0xD0, 0xC9, 0x81, 0x64, 0x4C, 0xCC, 0x84, 0xDA, 0x82, + 0xFA, 0x02, 0x01, 0x60, 0x00, 0x6B, 0x9A, 0xFF, 0xCA, 0x82, 0x03, 0x00, 0x00, 0xF4, 0x81, 0xF2, + 0xFF, 0xFF, 0x7A, 0xD0, 0xA1, 0xFF, 0x64, 0x4C, 0xFC, 0x1C, 0xF8, 0x1D, 0x00, 0xB9, 0x06, 0x1E, + 0x02, 0x02, 0x00, 0xF4, 0xDA, 0x82, 0x5A, 0xD2, 0xA1, 0xFF, 0x60, 0x4D, 0x3F, 0x40, 0x02, 0x2B, + 0x10, 0x00, 0x28, 0xF3, 0xA5, 0x60, 0xC4, 0x65, 0x60, 0x40, 0x0E, 0x3B, 0x0A, 0x00, 0xF1, 0xF3, + 0xFF, 0xFF, 0x10, 0xBC, 0xF1, 0xFB, 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0x85, 0x4C, + 0xFE, 0x01, 0xF1, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xF1, 0xFB, 0xA1, 0xFF, 0x87, 0x4E, 0x87, 0x4C, + 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x67, 0x4C, 0xFF, 0xFF, 0xBC, 0xFF, 0x00, 0xE1, 0xD5, 0xFE, + 0xA1, 0xFF, 0xFF, 0xFF, 0x00, 0x64, 0x40, 0x46, 0x60, 0x41, 0xB5, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, + 0x29, 0xF5, 0x3F, 0xF0, 0x24, 0xF2, 0x44, 0x43, 0x40, 0x4D, 0x00, 0xF4, 0xF3, 0x60, 0xA0, 0x65, + 0x10, 0x62, 0x5A, 0xD2, 0xD9, 0x81, 0xD4, 0x80, 0xFF, 0xFF, 0xFB, 0x02, 0x61, 0x45, 0x2D, 0x44, + 0xD4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xFD, 0xA5, 0x48, 0x60, 0x00, 0x64, 0xC4, 0x9D, + 0x0D, 0x60, 0x00, 0x6B, 0x2D, 0x44, 0xC0, 0x83, 0xBB, 0xFF, 0x29, 0xF5, 0x01, 0xE1, 0x00, 0xF4, + 0x6C, 0x61, 0x10, 0x62, 0x05, 0x00, 0x00, 0xF4, 0x01, 0xF2, 0xFF, 0xFF, 0x60, 0x41, 0x04, 0x62, + 0xA1, 0xFF, 0xFF, 0xFF, 0x01, 0x10, 0x1A, 0x00, 0x26, 0x44, 0x01, 0x26, 0x0C, 0x00, 0x2D, 0x44, + 0xC8, 0x84, 0x40, 0x4D, 0x02, 0x03, 0x6C, 0x45, 0xF3, 0x01, 0x03, 0x15, 0x01, 0x64, 0x05, 0xFA, + 0x15, 0x00, 0x6C, 0x45, 0xED, 0x01, 0x23, 0x44, 0xC8, 0x84, 0x40, 0x43, 0x02, 0x03, 0x6C, 0x45, + 0xE7, 0x01, 0x00, 0x64, 0x01, 0x15, 0x01, 0x64, 0x6C, 0x45, 0x05, 0xFB, 0xE2, 0xD2, 0xDA, 0x82, + 0xC9, 0x81, 0x60, 0x4C, 0xDD, 0x1C, 0xD7, 0x03, 0xBC, 0xFF, 0xDA, 0x01, 0x00, 0xE1, 0xD5, 0xFE, + 0xA1, 0xFF, 0xFF, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, 0x67, 0x4C, 0x43, 0xFF, 0xF1, 0xF3, 0xFF, 0xFF, + 0x10, 0xBC, 0xF1, 0xFB, 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0x01, 0xE1, 0x01, 0x60, + 0x69, 0x6B, 0xA5, 0x60, 0xC4, 0x64, 0x60, 0x4C, 0xBB, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x60, 0x4C, + 0xA1, 0xFF, 0xFF, 0xFF, 0x60, 0x4C, 0xFC, 0x01, 0x29, 0xF3, 0x2A, 0xF1, 0x07, 0xB5, 0x04, 0xE1, + 0x65, 0x41, 0x64, 0x54, 0xCD, 0xE2, 0x95, 0x81, 0xA1, 0x5D, 0xA1, 0xFF, 0xFF, 0xFF, 0xF9, 0x01, + 0x61, 0x44, 0xFE, 0xFB, 0xFF, 0xFD, 0xFF, 0x01, 0x7F, 0x67, 0x01, 0x61, 0x23, 0x58, 0xFF, 0xFF, + 0xB1, 0xFE, 0x08, 0x05, 0xB0, 0xFE, 0x09, 0x05, 0xB2, 0xFE, 0xB3, 0xFE, 0x78, 0x43, 0x01, 0x61, + 0x29, 0x60, 0xEA, 0x78, 0x34, 0x60, 0x8D, 0x78, 0xFF, 0xFF, 0x28, 0xF3, 0x29, 0xF1, 0x40, 0x44, + 0x44, 0x45, 0x2A, 0xF1, 0x2B, 0xF1, 0x44, 0x46, 0x44, 0x47, 0x3F, 0xB4, 0xE0, 0x85, 0x20, 0x60, + 0x28, 0x64, 0x44, 0xD7, 0x58, 0x43, 0xFF, 0xFF, 0x60, 0x45, 0x0E, 0x60, 0xDD, 0xF3, 0x61, 0x43, + 0x04, 0xB4, 0x24, 0x44, 0x02, 0x03, 0x13, 0xFF, 0x06, 0x00, 0x3F, 0xB4, 0xB4, 0x84, 0xFF, 0x27, + 0x05, 0xFD, 0x04, 0xFB, 0x10, 0x75, 0xA1, 0xFF, 0xFF, 0xFF, 0x86, 0x3E, 0xB4, 0xFE, 0x0B, 0x05, + 0xB5, 0xFE, 0x02, 0x24, 0x9F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0xFE, 0x07, 0x05, 0x78, 0x43, + 0x01, 0x61, 0x29, 0x60, 0xEA, 0x78, 0x34, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x36, 0x44, 0x00, 0x7F, + 0xEE, 0xA0, 0x60, 0x45, 0x05, 0x05, 0x20, 0x60, 0xBA, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, + 0x78, 0x43, 0x01, 0x61, 0x29, 0x60, 0xEA, 0x78, 0x78, 0x43, 0x01, 0x61, 0x29, 0x60, 0xEA, 0x78, + 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x10, 0x02, 0x10, 0x64, + 0x40, 0x40, 0x02, 0x64, 0x40, 0x50, 0x61, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x04, 0x00, 0x10, 0xE0, + 0x46, 0x60, 0x09, 0xE0, 0x00, 0x00, 0x27, 0xF1, 0x00, 0x66, 0x20, 0x78, 0x42, 0xFE, 0x23, 0x58, + 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x1A, 0x02, + 0x0E, 0x60, 0xDD, 0xF3, 0x07, 0x7C, 0x20, 0xB5, 0x0C, 0xB5, 0x04, 0x03, 0x03, 0x02, 0xDB, 0xF9, + 0x00, 0x67, 0x10, 0x00, 0x00, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0xAD, 0x01, 0x36, 0x47, 0xFF, 0x23, + 0x04, 0x00, 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x05, 0x00, 0x62, 0xFF, 0x20, 0x44, 0x80, 0xBC, + 0x40, 0x40, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, + 0x7F, 0x67, 0x02, 0x61, 0x31, 0x02, 0x0E, 0x60, 0xDD, 0xF3, 0x01, 0x7C, 0x20, 0xB5, 0x0C, 0xB5, + 0x03, 0x03, 0x02, 0x02, 0xDB, 0xF9, 0xFF, 0xFF, 0x02, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0x2A, 0x60, + 0x1D, 0x78, 0xFF, 0xFF, 0x9D, 0xF1, 0x20, 0x44, 0x64, 0x40, 0xFF, 0x26, 0x1C, 0x00, 0x7F, 0xB4, + 0x40, 0x40, 0x5C, 0x5E, 0x82, 0xFF, 0x26, 0x44, 0xFD, 0xB4, 0x40, 0x46, 0x5C, 0x41, 0x87, 0xFF, + 0x62, 0xFF, 0x13, 0x60, 0x02, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x04, 0x03, 0x09, 0xF2, + 0x8F, 0xFC, 0xAC, 0x86, 0xFB, 0x01, 0x95, 0xF3, 0xFF, 0xFF, 0x7F, 0xB4, 0x95, 0xFB, 0x06, 0x64, + 0x13, 0x60, 0x1C, 0xFB, 0x2D, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x00, 0x67, 0x20, 0x40, + 0x80, 0x2A, 0x02, 0x00, 0x7F, 0x67, 0x06, 0x61, 0x60, 0x45, 0x0E, 0x60, 0xDD, 0xF3, 0x61, 0x43, + 0x04, 0xB4, 0x24, 0x44, 0x02, 0x03, 0x13, 0xFF, 0x56, 0x01, 0x3F, 0xB4, 0xB4, 0x84, 0xFF, 0x27, + 0x05, 0xFD, 0x04, 0xFB, 0x20, 0x40, 0x80, 0x2A, 0x02, 0x00, 0x10, 0x75, 0x05, 0x00, 0x01, 0x64, + 0x19, 0x60, 0xF7, 0xFB, 0x08, 0x60, 0x10, 0x75, 0x46, 0x01, 0x25, 0x46, 0x01, 0xF2, 0x08, 0xF0, + 0x60, 0x47, 0x03, 0xB4, 0x03, 0xAC, 0x7F, 0x67, 0x03, 0x61, 0x08, 0x02, 0x26, 0x60, 0x20, 0x64, + 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x24, 0x40, 0x01, 0x2B, 0x49, 0x00, 0x25, 0x44, 0x1F, 0xB4, 0xE0, 0x85, 0x2A, 0x60, 0xF4, 0x64, + 0xC4, 0x98, 0xFF, 0xFF, 0xC0, 0xFE, 0x3D, 0x00, 0xC1, 0xFE, 0x3B, 0x00, 0xC2, 0xFE, 0x39, 0x00, + 0xC3, 0xFE, 0x37, 0x00, 0xC4, 0xFE, 0x35, 0x00, 0xC5, 0xFE, 0x33, 0x00, 0xC6, 0xFE, 0x31, 0x00, + 0xC7, 0xFE, 0x2F, 0x00, 0xC8, 0xFE, 0x2D, 0x00, 0xC9, 0xFE, 0x2B, 0x00, 0xCA, 0xFE, 0x29, 0x00, + 0xCB, 0xFE, 0x27, 0x00, 0xCC, 0xFE, 0x25, 0x00, 0xCD, 0xFE, 0x23, 0x00, 0xCE, 0xFE, 0x21, 0x00, + 0xCF, 0xFE, 0x1F, 0x00, 0xD0, 0xFE, 0x1D, 0x00, 0xD1, 0xFE, 0x1B, 0x00, 0xD2, 0xFE, 0x19, 0x00, + 0xD3, 0xFE, 0x17, 0x00, 0xD4, 0xFE, 0x15, 0x00, 0xD5, 0xFE, 0x13, 0x00, 0xD6, 0xFE, 0x11, 0x00, + 0xD7, 0xFE, 0x0F, 0x00, 0xD8, 0xFE, 0x0D, 0x00, 0xD9, 0xFE, 0x0B, 0x00, 0xDA, 0xFE, 0x09, 0x00, + 0xDB, 0xFE, 0x07, 0x00, 0xDC, 0xFE, 0x05, 0x00, 0xDD, 0xFE, 0x03, 0x00, 0xDE, 0xFE, 0x01, 0x00, + 0xDF, 0xFE, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x9F, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x9E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9D, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9C, 0xFE, 0xF0, 0x84, + 0xFF, 0xFF, 0x9B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9A, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x99, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x98, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x97, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x96, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x95, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x94, 0xFE, 0xF0, 0x84, + 0xFF, 0xFF, 0x93, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x92, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x91, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x90, 0xFE, 0xF0, 0x84, 0x06, 0xFB, 0x8F, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x8E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8D, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8C, 0xFE, 0xF0, 0x84, + 0xFF, 0xFF, 0x8B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8A, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x89, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x88, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x87, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, + 0x86, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x85, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x84, 0xFE, 0xF0, 0x84, + 0xFF, 0xFF, 0x83, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x82, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x81, 0xFE, + 0xF0, 0x84, 0xFF, 0xFF, 0x80, 0xFE, 0xF0, 0x84, 0x05, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x5C, 0x5C, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x24, 0x40, 0x01, 0x27, 0x55, 0x00, 0x05, 0x60, + 0x00, 0x63, 0x05, 0xFD, 0x30, 0x44, 0xBD, 0xDB, 0x31, 0x44, 0xBD, 0xDB, 0x32, 0x44, 0xBD, 0xDB, + 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, 0x35, 0x44, 0xBD, 0xDB, 0x36, 0x44, 0xBD, 0xDB, + 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, 0x39, 0x44, 0xBD, 0xDB, 0x3A, 0x44, 0xBD, 0xDB, + 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, 0x3D, 0x44, 0xBD, 0xDB, 0x3E, 0x44, 0xBD, 0xDB, + 0x3F, 0x44, 0xBD, 0xDB, 0x02, 0x61, 0x61, 0x44, 0x02, 0x36, 0x82, 0xFF, 0x03, 0x36, 0x83, 0xFF, + 0x04, 0x36, 0x84, 0xFF, 0x05, 0x36, 0x85, 0xFF, 0x06, 0x36, 0x86, 0xFF, 0x07, 0x36, 0x87, 0xFF, + 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, 0x23, 0x44, 0xBD, 0xDB, + 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, 0x27, 0x44, 0xBD, 0xDB, + 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, 0x2B, 0x44, 0xBD, 0xDB, + 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, 0x2F, 0x44, 0xBD, 0xDB, + 0xDD, 0x81, 0x08, 0x3A, 0xD0, 0x01, 0x54, 0x00, 0x27, 0x40, 0x10, 0x26, 0x30, 0x00, 0x26, 0x44, + 0x01, 0x36, 0x2D, 0x00, 0x02, 0x36, 0x82, 0xFF, 0x03, 0x36, 0x83, 0xFF, 0x04, 0x36, 0x84, 0xFF, + 0x05, 0x36, 0x85, 0xFF, 0x06, 0x36, 0x86, 0xFF, 0x25, 0x44, 0x00, 0x36, 0x44, 0x40, 0x01, 0x36, + 0x44, 0x41, 0x02, 0x36, 0x44, 0x42, 0x03, 0x36, 0x44, 0x43, 0x04, 0x36, 0x44, 0x44, 0x05, 0x36, + 0x44, 0x45, 0x06, 0x36, 0x44, 0x46, 0x07, 0x36, 0x44, 0x47, 0x08, 0x36, 0x44, 0x48, 0x09, 0x36, + 0x44, 0x49, 0x0A, 0x36, 0x44, 0x4A, 0x0B, 0x36, 0x44, 0x4B, 0x0C, 0x36, 0x44, 0x4C, 0x0D, 0x36, + 0x44, 0x4D, 0x0E, 0x36, 0x44, 0x4E, 0x0F, 0x36, 0x44, 0x4F, 0x87, 0xFF, 0x21, 0x00, 0x25, 0x44, + 0x10, 0x36, 0x44, 0x50, 0x11, 0x36, 0x44, 0x51, 0x12, 0x36, 0x44, 0x52, 0x13, 0x36, 0x44, 0x53, + 0x14, 0x36, 0x44, 0x54, 0x15, 0x36, 0x44, 0x55, 0x16, 0x36, 0x44, 0x56, 0x17, 0x36, 0x44, 0x57, + 0x18, 0x36, 0x44, 0x58, 0x19, 0x36, 0x44, 0x59, 0x1A, 0x36, 0x44, 0x5A, 0x1B, 0x36, 0x44, 0x5B, + 0x1C, 0x36, 0x44, 0x5C, 0x1D, 0x36, 0x44, 0x5D, 0x1E, 0x36, 0x44, 0x5E, 0x1F, 0x36, 0x44, 0x5F, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0x46, 0xB5, 0x60, 0x58, 0x4F, 0xCE, 0x78, 0xFF, 0xFF, + 0x03, 0x61, 0x7F, 0x67, 0x0A, 0x02, 0x00, 0xF0, 0x04, 0x64, 0x13, 0x60, 0x10, 0xFB, 0x5A, 0xD9, + 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, + 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x12, 0x02, 0x14, 0x64, 0x13, 0x60, + 0x1C, 0xFB, 0x00, 0x60, 0x50, 0x63, 0x5A, 0xDD, 0x2C, 0x60, 0x75, 0x64, 0x9F, 0xFB, 0x2D, 0xFF, + 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x2A, 0xF3, 0x05, 0xFB, 0x2B, 0xF3, 0x06, 0xFB, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, + 0x0E, 0x02, 0x16, 0x64, 0x13, 0x60, 0x1C, 0xFB, 0x00, 0x60, 0x50, 0x63, 0x5A, 0xDD, 0x2C, 0x60, + 0x90, 0x64, 0x9F, 0xFB, 0x2D, 0xFF, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x02, 0x61, 0x38, 0x02, 0x25, 0x45, + 0x20, 0x44, 0x80, 0x2A, 0x34, 0x00, 0xF1, 0x60, 0x00, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x06, 0x03, + 0xF1, 0x60, 0x02, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x2F, 0x03, 0x28, 0x00, 0x19, 0x60, 0x40, 0xF1, + 0xB7, 0xF3, 0x20, 0x60, 0x22, 0x61, 0xA0, 0x84, 0xA1, 0xDB, 0x25, 0x45, 0x25, 0x60, 0x86, 0x63, + 0x02, 0x61, 0xBD, 0xD3, 0xBD, 0xD1, 0xD4, 0x80, 0xBD, 0xD3, 0xBD, 0xD5, 0xCD, 0x81, 0x02, 0x03, + 0x15, 0x03, 0xF7, 0x01, 0xA2, 0xFF, 0xA6, 0xD3, 0x40, 0x4C, 0x00, 0xA8, 0x67, 0x43, 0x0C, 0x02, + 0xA2, 0xDD, 0x42, 0x48, 0x64, 0x41, 0xB6, 0x60, 0x58, 0x4D, 0x25, 0x78, 0xFF, 0xFF, 0x66, 0x44, + 0x28, 0xDB, 0x02, 0x03, 0x2C, 0x58, 0xA3, 0xFF, 0x0C, 0x61, 0x03, 0x00, 0x04, 0x61, 0x7F, 0x67, + 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x64, 0x10, 0x60, 0x13, 0xFB, 0xFF, 0xFF, + 0xC4, 0xFE, 0xF7, 0x01, 0xC6, 0xFE, 0xF5, 0x01, 0x7E, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, + 0x02, 0x61, 0x3F, 0x02, 0x25, 0x45, 0xF8, 0x2B, 0x3B, 0x00, 0x2E, 0xF5, 0x67, 0x44, 0xD4, 0x80, + 0x20, 0x60, 0xCC, 0x63, 0x39, 0x03, 0x79, 0x61, 0x24, 0x44, 0x01, 0x27, 0x29, 0x00, 0xA3, 0xFC, + 0xA4, 0xF8, 0xBD, 0xD3, 0xA3, 0xD1, 0xD4, 0x80, 0xCD, 0x81, 0x08, 0x24, 0x64, 0x58, 0x08, 0xA3, + 0xF8, 0x02, 0x08, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xA3, 0xD1, 0xFE, 0xA0, 0xFA, 0x60, 0x00, 0x64, + 0xD0, 0x80, 0x14, 0x02, 0x13, 0x02, 0x04, 0xA3, 0xBE, 0xD3, 0xBD, 0xD1, 0x0F, 0x18, 0xD4, 0x80, + 0x0D, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x64, 0x41, 0xDD, 0x81, 0xE1, 0x81, + 0xCB, 0x83, 0x46, 0x65, 0x36, 0x60, 0x58, 0x4F, 0x22, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x0A, 0x00, + 0xBD, 0xD3, 0xBE, 0xD1, 0xD4, 0x80, 0xCD, 0x81, 0x08, 0x24, 0x64, 0x58, 0x08, 0xA3, 0xF8, 0x02, + 0x04, 0x61, 0x7F, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x0F, 0x64, 0x23, 0xFA, 0x67, 0x44, 0x24, 0xFA, + 0x62, 0x41, 0x3C, 0x60, 0x00, 0x65, 0x1A, 0x63, 0x80, 0x60, 0x9E, 0x64, 0x65, 0x46, 0x58, 0xD0, + 0x2E, 0xF5, 0x59, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xCB, 0x83, 0xBF, 0xD1, + 0x4A, 0x65, 0x64, 0x43, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0x01, 0x26, 0xDC, 0x81, 0xE9, 0x84, + 0xDC, 0x84, 0x23, 0xFA, 0x09, 0x00, 0x4B, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0xE8, 0x84, 0xDC, 0x84, + 0x23, 0xFA, 0xBF, 0xD1, 0x4A, 0x65, 0x64, 0x43, 0x36, 0x60, 0x58, 0x4F, 0x22, 0x78, 0xFF, 0xFF, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xE0, 0xA0, 0x20, 0x64, 0x01, 0x06, + 0x25, 0xFA, 0x23, 0xF2, 0xDF, 0xD1, 0xCC, 0x84, 0xE0, 0x85, 0x0B, 0x06, 0xBF, 0xD1, 0x64, 0x41, + 0xD5, 0x80, 0x64, 0x43, 0x01, 0x06, 0x65, 0x41, 0x4A, 0x65, 0x2E, 0x60, 0x58, 0x4F, 0x7A, 0x78, + 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xDB, 0xF3, 0x02, 0x63, 0x23, 0xFC, 0x07, 0xB4, + 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x4B, 0xD3, 0xBF, 0xD3, 0x60, 0x41, 0xC9, 0x83, + 0xE9, 0x81, 0xDD, 0x81, 0xA3, 0xFA, 0xE0, 0x81, 0x3C, 0x60, 0x00, 0x67, 0x02, 0x24, 0x02, 0xA4, + 0x60, 0x47, 0x40, 0x4B, 0xC9, 0x81, 0x4A, 0x65, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0xA5, 0xD8, + 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF6, 0x1F, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD1, 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, 0x60, 0x47, 0x25, 0xFA, + 0x00, 0x7E, 0x60, 0x47, 0x01, 0x26, 0xDC, 0x84, 0x60, 0x41, 0xE8, 0x84, 0xD8, 0x84, 0x23, 0xFA, + 0xAB, 0x01, 0xFC, 0xA3, 0xA3, 0xD1, 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, 0x00, 0x7F, 0x25, 0xFA, + 0x60, 0x41, 0x01, 0x26, 0xDD, 0x81, 0xE9, 0x84, 0xD8, 0x84, 0x23, 0xFA, 0x9D, 0x01, 0x2E, 0x60, + 0x40, 0x63, 0xBF, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0xE8, 0x84, 0xDC, 0x84, 0x23, 0xFA, 0x4A, 0x65, + 0x36, 0x60, 0x58, 0x4F, 0x22, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x2E, 0x60, + 0x40, 0x63, 0x23, 0xF2, 0xC0, 0x65, 0xCC, 0x84, 0xE0, 0x81, 0x0A, 0x04, 0xBF, 0xDB, 0xD5, 0x80, + 0x07, 0x03, 0x01, 0x06, 0x65, 0x41, 0x61, 0x44, 0xBF, 0xDB, 0x4A, 0x65, 0x58, 0x4F, 0xA8, 0x00, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x03, 0x4E, 0x2D, 0x60, 0x58, 0x43, 0x55, 0x78, 0xFF, 0xFF, + 0x2F, 0x60, 0x24, 0x61, 0x17, 0x60, 0x81, 0xF3, 0xA1, 0xDB, 0xCC, 0x84, 0xA8, 0x83, 0x05, 0x04, + 0x2F, 0x60, 0x02, 0x64, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0x0E, 0x43, 0x82, 0x01, 0x23, 0xF2, + 0x25, 0xF2, 0x02, 0xA8, 0xF8, 0xA0, 0x0F, 0x02, 0xEC, 0xA0, 0x0D, 0x04, 0x0C, 0x07, 0x19, 0x60, + 0x4F, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x04, 0x07, 0x19, 0x60, 0x4F, 0xFB, 0x19, 0x60, + 0x53, 0xFB, 0x16, 0x60, 0xD8, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x1D, 0x60, + 0xAE, 0x65, 0x60, 0x41, 0x1D, 0x60, 0x4A, 0x63, 0xA3, 0xDB, 0xFF, 0xA1, 0x48, 0x64, 0x58, 0xD0, + 0x7E, 0xA8, 0x5B, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xFF, 0xA1, 0xD7, 0x80, 0x02, 0x03, + 0x01, 0x03, 0xF5, 0x01, 0x2E, 0xF5, 0x00, 0x60, 0x2F, 0x65, 0x25, 0xF2, 0x00, 0x63, 0xCC, 0x84, + 0x03, 0xA3, 0xFD, 0x05, 0x4A, 0x64, 0xD7, 0x80, 0x1C, 0x60, 0xE6, 0x61, 0x18, 0x05, 0xA1, 0xDD, + 0xE3, 0x83, 0xFE, 0xA3, 0x58, 0xD0, 0x7E, 0xA8, 0x59, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, + 0xF9, 0x1F, 0x00, 0x63, 0x59, 0xDD, 0x2E, 0xF5, 0x25, 0xF0, 0x0E, 0x60, 0x73, 0xF3, 0xD3, 0x80, + 0x01, 0xB0, 0x04, 0x03, 0x01, 0xA4, 0x03, 0x03, 0xA2, 0xDB, 0x01, 0x00, 0xA2, 0xDD, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x1D, 0x60, 0x4A, 0x61, 0xA1, 0xD3, 0x23, 0xFA, 0xE0, 0x83, 0x4A, 0x65, + 0x04, 0x02, 0x02, 0x63, 0x23, 0xFC, 0xA5, 0xFC, 0x09, 0x00, 0xDB, 0x83, 0x59, 0xD1, 0xA5, 0xD8, + 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x0E, 0x60, 0x73, 0xF3, 0x00, 0x61, 0x02, 0xA4, 0xFE, 0xA0, 0x23, 0xFA, 0x1B, 0x03, + 0xFA, 0xA4, 0xFD, 0xA4, 0x01, 0xA1, 0xFD, 0x07, 0x61, 0x43, 0x23, 0xF2, 0x25, 0xFC, 0xE0, 0x83, + 0x02, 0xA3, 0x1C, 0x60, 0xE6, 0x61, 0x00, 0x60, 0x4A, 0x64, 0x59, 0xD1, 0x58, 0xD8, 0x7E, 0x3A, + 0x02, 0x00, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x25, 0xF2, 0x23, 0xF2, 0x01, 0xB0, 0xCC, 0x84, + 0x04, 0x02, 0x23, 0xFA, 0x02, 0x00, 0x00, 0x64, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x41, 0x4B, 0x65, 0x42, 0x80, 0x64, 0xD4, 0x85, 0x2B, 0x41, 0x00, 0xA1, 0x55, 0x8B, 0x0D, 0x03, + 0x02, 0x04, 0x65, 0x41, 0x02, 0x00, 0x00, 0x64, 0x40, 0x4B, 0xCA, 0x84, 0x58, 0xD0, 0xC9, 0x81, + 0xBD, 0xD9, 0xFC, 0x02, 0x00, 0xF4, 0x04, 0x65, 0xEC, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, + 0xA3, 0xD3, 0x02, 0x7C, 0xA0, 0xD3, 0x23, 0xF8, 0xDC, 0x84, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x02, 0x64, 0x23, 0xFA, 0x01, 0x64, 0x9D, 0xFE, 0x02, 0x28, 0x02, 0x64, 0x25, 0xFA, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x02, 0x7C, 0x23, 0xF8, 0x01, 0x64, 0x25, 0xFA, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD1, 0x02, 0x64, 0x23, 0xFA, 0xA4, 0xD3, 0x25, 0xFA, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x02, 0x64, 0x23, 0xFA, 0x88, 0xFF, 0x75, 0x44, 0x8D, 0xFF, + 0xE8, 0x87, 0xE8, 0x84, 0xE8, 0x84, 0x03, 0xB4, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x04, 0x64, 0x23, 0xFA, 0x86, 0xFF, 0x29, 0x44, 0x87, 0xFF, 0x25, 0xFA, 0x55, 0xF3, 0x52, 0xF1, + 0x80, 0x65, 0xC4, 0x87, 0x00, 0x7F, 0x26, 0xFA, 0x64, 0x44, 0xC4, 0x87, 0x00, 0x7F, 0x27, 0xFA, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x05, 0x64, 0x23, 0xFA, 0x52, 0x63, 0xB4, 0xF3, 0x4B, 0xDA, + 0xB3, 0xF3, 0x4B, 0xDA, 0xB2, 0xF3, 0x4B, 0xDA, 0x60, 0x41, 0x88, 0xFF, 0x72, 0x5C, 0x89, 0xFF, + 0x4A, 0xD8, 0xA2, 0x48, 0x20, 0x23, 0x0E, 0x00, 0x64, 0x40, 0x80, 0x27, 0x15, 0x00, 0xDC, 0x84, + 0xBD, 0xDA, 0xBD, 0xD2, 0x11, 0x04, 0xDC, 0x84, 0xA2, 0xDA, 0xA3, 0xD2, 0x0D, 0x04, 0xDC, 0x84, + 0xA3, 0xDA, 0x0A, 0x00, 0x52, 0x63, 0xB4, 0xF3, 0x4B, 0xDA, 0xB3, 0xF3, 0x4B, 0xDA, 0xB2, 0xF3, + 0x4B, 0xDA, 0x54, 0x90, 0x4C, 0x63, 0xE0, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF0, + 0x23, 0xF2, 0x19, 0x60, 0x46, 0xF9, 0x02, 0xA8, 0x64, 0x44, 0x1F, 0x02, 0x3F, 0x40, 0x02, 0x2B, + 0x16, 0x00, 0x00, 0x37, 0x14, 0x00, 0x01, 0x3B, 0x18, 0x00, 0x12, 0x60, 0x45, 0x65, 0x11, 0x60, + 0x65, 0x63, 0xFF, 0xB7, 0x60, 0x5C, 0xA3, 0xD3, 0x08, 0xA3, 0x00, 0x7E, 0xD0, 0x80, 0xD7, 0x80, + 0x03, 0x03, 0xF9, 0x02, 0x7F, 0x67, 0x0A, 0x00, 0xF4, 0xA3, 0xA3, 0xD1, 0x04, 0x00, 0x00, 0xBC, + 0xF2, 0xA4, 0x03, 0x03, 0x02, 0x07, 0x16, 0x60, 0xCF, 0xF9, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x20, 0x63, 0x2E, 0x60, 0x00, 0x61, 0x48, 0x64, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x25, 0xF0, + 0x20, 0x64, 0xD0, 0x81, 0xFF, 0xFF, 0x02, 0x07, 0x25, 0xFA, 0x0F, 0x00, 0x2E, 0x60, 0x04, 0x63, + 0xC3, 0x83, 0x01, 0x2A, 0x06, 0x00, 0xCF, 0x83, 0xA3, 0xD3, 0xCD, 0x81, 0x00, 0x7F, 0xBD, 0xDB, + 0x04, 0x03, 0x00, 0x64, 0xC9, 0x81, 0xBD, 0xDB, 0xFD, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x01, 0x60, 0xA0, 0x62, 0x09, 0x02, 0xA2, 0xD9, 0x64, 0x41, + 0x32, 0x44, 0x02, 0xB5, 0x00, 0xB9, 0xD4, 0x84, 0x08, 0x28, 0x02, 0xBC, 0x40, 0x52, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x01, 0x60, 0xA2, 0x62, 0x09, 0x02, + 0xA2, 0xD9, 0x64, 0x41, 0x32, 0x44, 0x04, 0xB5, 0x00, 0xB9, 0xD4, 0x84, 0x08, 0x28, 0x04, 0xBC, + 0x40, 0x52, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x01, 0x60, + 0xB0, 0x62, 0x15, 0x02, 0xA2, 0xD9, 0x64, 0x41, 0x32, 0x44, 0x40, 0xB5, 0x00, 0xB9, 0xD4, 0x84, + 0x08, 0x24, 0x0C, 0x00, 0x40, 0xBC, 0x02, 0xB5, 0xD4, 0x84, 0x43, 0xF9, 0x37, 0x60, 0x76, 0x63, + 0xD3, 0x80, 0x2F, 0x60, 0x50, 0x7C, 0x02, 0x03, 0x43, 0xFD, 0xA4, 0xDF, 0x40, 0x52, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x37, 0x60, 0x76, 0x64, 0x43, 0xFB, 0x2D, 0x60, 0x5B, 0x78, 0xFF, 0xFF, + 0x23, 0xF2, 0x25, 0xF0, 0x01, 0x60, 0xAC, 0x63, 0x7F, 0x67, 0x39, 0x18, 0xA3, 0xD9, 0x26, 0xF0, + 0x7F, 0x67, 0x35, 0x18, 0x5B, 0xD9, 0x16, 0x60, 0x87, 0xF3, 0x25, 0xF0, 0x60, 0x40, 0x03, 0x3A, + 0x2D, 0x00, 0xA6, 0xF3, 0x20, 0x63, 0xE3, 0x83, 0x60, 0x46, 0x0F, 0xF8, 0x30, 0x61, 0x94, 0xFA, + 0x01, 0x61, 0x91, 0xFA, 0x16, 0x64, 0x12, 0xFA, 0x60, 0x40, 0x10, 0x36, 0x05, 0x00, 0x12, 0x36, + 0x08, 0x00, 0x0C, 0x36, 0x0B, 0x00, 0x0F, 0x00, 0x40, 0x61, 0xA1, 0x80, 0x0A, 0x64, 0x11, 0x02, + 0xF3, 0x01, 0x10, 0x61, 0xA1, 0x80, 0x0E, 0x64, 0x0C, 0x02, 0xEE, 0x01, 0x08, 0x61, 0xA1, 0x80, + 0x10, 0x64, 0x07, 0x02, 0xE9, 0x01, 0xE1, 0x81, 0xA1, 0x80, 0x05, 0x05, 0xC8, 0x84, 0x01, 0x02, + 0xE3, 0x01, 0x12, 0xFA, 0x91, 0xFA, 0x66, 0x44, 0x02, 0xA6, 0xD7, 0x1F, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x25, 0xF2, 0x19, 0x60, 0x45, 0xFB, 0x19, 0x60, 0x4C, 0xF3, 0xFF, 0xFF, 0x60, 0x40, + 0x08, 0x26, 0x18, 0x00, 0x19, 0x60, 0x45, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x0A, 0x00, + 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0x60, 0x44, 0xA2, 0xDB, 0x19, 0x60, 0x45, 0xF3, + 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x2A, 0x06, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0x04, 0xBC, + 0x60, 0x44, 0xA2, 0xDB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, + 0x00, 0x67, 0x02, 0x02, 0x2D, 0xF9, 0x2C, 0xF9, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF2, + 0x02, 0xA8, 0x00, 0xA8, 0x0A, 0x02, 0x07, 0x03, 0xD0, 0xA0, 0x30, 0x65, 0x03, 0x04, 0xA7, 0xA0, + 0x59, 0x65, 0x01, 0x06, 0x65, 0x44, 0x16, 0x60, 0xCE, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x25, 0xF2, 0x19, 0x60, 0x4C, 0xFB, 0xFF, 0xFF, 0x08, 0x2A, 0x25, 0x00, 0x19, 0x60, 0x7B, 0xF3, + 0xFF, 0xFF, 0xE9, 0xB4, 0x60, 0x44, 0x19, 0x60, 0x4C, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x26, + 0x02, 0xBC, 0x64, 0x40, 0x02, 0x2A, 0x04, 0xBC, 0x64, 0x40, 0x04, 0x26, 0x08, 0x00, 0x19, 0x60, + 0x7B, 0xFB, 0x13, 0x64, 0xCB, 0xFB, 0x01, 0x60, 0x67, 0x64, 0x37, 0xFB, 0x0C, 0x00, 0x10, 0xBC, + 0x19, 0x60, 0x7B, 0xFB, 0x08, 0x64, 0xCB, 0xFB, 0xA1, 0xF3, 0x01, 0x60, 0x67, 0x7C, 0x60, 0x40, + 0x01, 0x27, 0x5B, 0x7C, 0x37, 0xF9, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0x19, 0x60, + 0x4D, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0x19, 0x60, 0x4E, 0xFB, 0x00, 0x67, + 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0x19, 0x60, 0x89, 0xFB, 0xFF, 0xFF, 0x0F, 0x22, 0x41, 0x75, + 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x64, 0x01, 0x00, 0x00, 0x64, 0x1B, 0x60, 0xFE, 0xFB, + 0x7E, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x0E, 0x02, 0x06, 0x61, + 0x41, 0x56, 0xC7, 0xFE, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, + 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, + 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x0E, 0x02, 0x08, 0x61, 0x41, 0x56, + 0xC7, 0xFE, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, 0x00, 0x7F, + 0x60, 0x41, 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, + 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x0E, 0x02, 0x0A, 0x61, 0x41, 0x56, 0xC7, 0xFE, + 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, 0x00, 0x7F, 0x60, 0x41, + 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7E, 0x60, 0xC0, 0x64, 0x24, 0x45, + 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x11, 0x02, 0x65, 0x43, 0x19, 0x60, 0xA5, 0xFD, 0x0C, 0x61, + 0x41, 0x56, 0xC7, 0xFE, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, + 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x20, 0x64, + 0x23, 0xFA, 0x4A, 0x61, 0x10, 0x60, 0xDA, 0x64, 0xA0, 0xD1, 0xA1, 0xD8, 0x58, 0xD1, 0x59, 0xD8, + 0x58, 0xD1, 0x59, 0xD8, 0x01, 0xA1, 0x10, 0x60, 0xF2, 0x63, 0x5D, 0x65, 0xA3, 0xD3, 0x02, 0xA3, + 0x02, 0x1B, 0x7F, 0x64, 0x01, 0x00, 0xA3, 0xD3, 0x60, 0xFE, 0x5D, 0xDA, 0x20, 0xFE, 0xD5, 0x80, + 0x04, 0xA3, 0xF4, 0x02, 0x01, 0xA1, 0x10, 0x60, 0xE0, 0x64, 0xA0, 0xD1, 0xA1, 0xD8, 0x58, 0xD1, + 0x59, 0xD8, 0x58, 0xD1, 0x59, 0xD8, 0x01, 0xA1, 0x60, 0xFE, 0x07, 0x63, 0x7F, 0x64, 0xCF, 0x83, + 0x5D, 0xDA, 0xFD, 0x02, 0x20, 0xFE, 0x12, 0x60, 0x40, 0x7C, 0x11, 0x60, 0x62, 0x63, 0x7F, 0x65, + 0xA3, 0xD3, 0x02, 0xA3, 0x02, 0x1B, 0x7F, 0x64, 0x01, 0x00, 0xA3, 0xD3, 0x60, 0xFE, 0x5D, 0xDA, + 0x20, 0xFE, 0xD5, 0x80, 0x06, 0xA3, 0x03, 0x02, 0x46, 0x45, 0x00, 0xF4, 0x03, 0x61, 0xD3, 0x80, + 0xFF, 0xFF, 0xEE, 0x04, 0x25, 0x46, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x02, 0x63, 0x7D, 0xF3, + 0x23, 0xFC, 0x60, 0x40, 0x01, 0x23, 0x17, 0x00, 0x01, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x11, 0x60, + 0x60, 0x61, 0x12, 0x60, 0x40, 0x65, 0xA1, 0xD1, 0xD5, 0x80, 0xD0, 0x80, 0x0B, 0x03, 0x02, 0x03, + 0x08, 0xA1, 0xF9, 0x01, 0x04, 0xA1, 0xA1, 0xD3, 0x01, 0x60, 0x00, 0x65, 0x60, 0x47, 0xFF, 0xB4, + 0xB4, 0x84, 0x01, 0x00, 0xFF, 0x64, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x0C, 0x63, + 0x23, 0xFC, 0xE2, 0xF3, 0x13, 0x60, 0xF2, 0x63, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x06, 0x0C, 0xA3, + 0xFB, 0x01, 0x48, 0x61, 0x61, 0x44, 0x18, 0xA5, 0x60, 0xFE, 0xBD, 0xD3, 0x20, 0xFE, 0x00, 0x7F, + 0x59, 0xDA, 0xD5, 0x80, 0xFF, 0xFF, 0xF8, 0x04, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF0, + 0x17, 0x60, 0x80, 0xF9, 0x11, 0x00, 0x0C, 0x60, 0xFE, 0x62, 0x40, 0x63, 0x5A, 0xDF, 0xFE, 0x1F, + 0x04, 0x65, 0x0C, 0x60, 0xFE, 0x61, 0x48, 0x64, 0x3E, 0x63, 0x7C, 0xA8, 0x58, 0xD0, 0x59, 0xD9, + 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x17, 0x60, 0x80, 0xF1, 0x0C, 0x60, 0xDA, 0x65, + 0x02, 0xFE, 0x64, 0x44, 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x87, 0x60, 0x41, 0x64, 0x44, 0xE0, 0x84, + 0xE0, 0x84, 0xC4, 0x84, 0x3E, 0xFB, 0x60, 0x42, 0x61, 0x44, 0x03, 0xA2, 0x60, 0xFE, 0xA2, 0xDB, + 0x20, 0xFE, 0x64, 0x44, 0x0D, 0x60, 0x00, 0x65, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, + 0xC4, 0x84, 0x40, 0xFB, 0xFF, 0xFF, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x5C, 0x41, + 0x25, 0xF2, 0xFF, 0xFF, 0x40, 0x42, 0x80, 0x2B, 0x04, 0x00, 0xFF, 0xB4, 0x40, 0x42, 0x01, 0x64, + 0x40, 0x41, 0xA6, 0xF3, 0x46, 0x4B, 0x60, 0x46, 0x20, 0x63, 0xE3, 0x83, 0xAB, 0x46, 0x26, 0xF0, + 0xAB, 0x46, 0x59, 0xF8, 0xAB, 0x46, 0x27, 0xF0, 0xAB, 0x46, 0x5A, 0xF8, 0xAB, 0x46, 0x28, 0xF0, + 0xAB, 0x46, 0x5B, 0xF8, 0x66, 0x44, 0x02, 0xA6, 0xF1, 0x1F, 0xA6, 0xF3, 0xFF, 0xFF, 0x60, 0x46, + 0xAB, 0x46, 0x0C, 0x60, 0x38, 0x65, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0xC4, 0x81, 0xC9, 0x81, 0x52, 0x64, 0x0E, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, + 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, 0xAB, 0x46, 0xF0, 0xA1, 0x76, 0x64, 0x0E, 0x63, 0x59, 0xD1, + 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, + 0x0C, 0x60, 0x9A, 0x65, 0xC4, 0x81, 0x60, 0x45, 0xC9, 0x81, 0x62, 0x64, 0x06, 0x63, 0x58, 0xD0, + 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, 0xAB, 0x46, 0xF8, 0xA1, 0xB6, 0x64, + 0x06, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, 0x65, 0x44, 0x0C, 0x60, 0xBA, 0x65, + 0xC4, 0x81, 0xC9, 0x81, 0x6A, 0x64, 0x06, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x22, 0x44, + 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x85, 0xC4, 0x84, 0x0C, 0x60, 0x80, 0x65, 0xC4, 0x81, 0x72, 0x64, + 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0xAB, 0x46, 0x21, 0x44, 0x01, 0x2A, 0x06, 0x00, + 0xFA, 0xA1, 0x90, 0x64, 0x04, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0x3B, 0xF0, 0x21, 0x44, + 0x01, 0x2A, 0x13, 0x00, 0x22, 0x44, 0x3D, 0xFB, 0x60, 0x41, 0x02, 0xFE, 0xF8, 0x84, 0xF8, 0x84, + 0xF8, 0x84, 0x3C, 0xFB, 0x0C, 0x60, 0x7C, 0x63, 0x88, 0xFF, 0xCD, 0x81, 0x06, 0xA3, 0xFD, 0x0D, + 0x8D, 0xFF, 0x3B, 0xFD, 0x64, 0x47, 0x80, 0xBF, 0x60, 0x5C, 0x22, 0x43, 0x80, 0x61, 0x88, 0xFF, + 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, 0xB1, 0x84, 0x3B, 0xFA, + 0x1F, 0x63, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0x3B, 0xF0, 0x66, 0x44, 0xB1, 0x9C, 0x3B, 0xF8, + 0x02, 0xA6, 0xFA, 0x1F, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, + 0x25, 0xF0, 0x02, 0xA8, 0x00, 0x67, 0x22, 0x02, 0x3D, 0xF1, 0x64, 0x44, 0x03, 0xB4, 0x40, 0x42, + 0xD0, 0x80, 0xA6, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xBB, 0xF4, 0x80, 0x61, 0x02, 0x02, 0xE3, 0x83, + 0xEB, 0x83, 0x22, 0x44, 0x88, 0xFF, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, + 0x31, 0x91, 0x9D, 0x85, 0xA7, 0x83, 0x3B, 0xFC, 0x1F, 0x63, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, + 0xBB, 0xF2, 0x66, 0x44, 0xA5, 0x81, 0xBB, 0xFA, 0x02, 0xA6, 0xFA, 0x1F, 0x00, 0x67, 0x23, 0x58, + 0xFF, 0xFF, 0x27, 0xF2, 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, + 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, + 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, + 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, + 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, + 0x2A, 0x00, 0x43, 0x4B, 0xAB, 0x46, 0x3B, 0xF2, 0x80, 0x60, 0x30, 0x7C, 0xB0, 0x84, 0xA2, 0xDA, + 0x4E, 0x61, 0x76, 0x64, 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, + 0x90, 0x64, 0x04, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0xD9, 0x81, + 0xA0, 0x64, 0x04, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0xD9, 0x81, + 0xB6, 0x64, 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x00, 0x67, + 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x27, 0xF2, + 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, + 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, + 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, + 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, + 0xE8, 0x1B, 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x0D, 0x00, 0x43, 0x4B, + 0xAB, 0x46, 0x3B, 0xF2, 0x80, 0x60, 0x30, 0x61, 0x9D, 0x85, 0xA4, 0x84, 0xA2, 0xDA, 0xAB, 0x46, + 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, + 0x00, 0x64, 0x40, 0x41, 0x4A, 0x64, 0xA0, 0xD2, 0xFF, 0xFF, 0x40, 0x42, 0x80, 0x2B, 0x04, 0x00, + 0xFF, 0xB4, 0x40, 0x42, 0x01, 0x64, 0x40, 0x41, 0xA6, 0xF3, 0x46, 0x4B, 0x60, 0x46, 0x20, 0x63, + 0xE3, 0x83, 0xAB, 0x46, 0x32, 0xF0, 0xAB, 0x46, 0x59, 0xF8, 0xAB, 0x46, 0x33, 0xF0, 0xAB, 0x46, + 0x5A, 0xF8, 0xAB, 0x46, 0x34, 0xF0, 0xAB, 0x46, 0x5B, 0xF8, 0x66, 0x44, 0x02, 0xA6, 0xF1, 0x1F, + 0xA6, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xAB, 0x46, 0x0C, 0x60, 0x38, 0x65, 0x22, 0x44, 0xFF, 0xB4, + 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x81, 0xC9, 0x81, 0x4A, 0x64, 0x0E, 0x63, + 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, 0xAB, 0x46, 0xF0, 0xA1, + 0x76, 0x64, 0x0E, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, 0x22, 0x44, 0xFF, 0xB4, + 0xE0, 0x84, 0xE0, 0x85, 0xC4, 0x84, 0x0C, 0x60, 0x80, 0x65, 0xC4, 0x81, 0x5A, 0x64, 0x04, 0x63, + 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0xAB, 0x46, 0x21, 0x44, 0x01, 0x2A, 0x06, 0x00, 0xFA, 0xA1, + 0x90, 0x64, 0x04, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0x3B, 0xF0, 0x21, 0x44, 0x01, 0x2A, + 0x13, 0x00, 0x22, 0x44, 0x3D, 0xFB, 0x60, 0x41, 0x02, 0xFE, 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x84, + 0x3C, 0xFB, 0x0C, 0x60, 0x7C, 0x63, 0x88, 0xFF, 0xCD, 0x81, 0x06, 0xA3, 0xFD, 0x0D, 0x8D, 0xFF, + 0x3B, 0xFD, 0x64, 0x47, 0x80, 0xBF, 0x60, 0x5C, 0x22, 0x43, 0x80, 0x61, 0x88, 0xFF, 0xCF, 0x83, + 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, 0xB1, 0x84, 0x3B, 0xFA, 0x1F, 0x63, + 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0x3B, 0xF0, 0x66, 0x44, 0xB1, 0x9C, 0x3B, 0xF8, 0x02, 0xA6, + 0xFA, 0x1F, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, + 0x02, 0xA8, 0x00, 0x67, 0x22, 0x02, 0x3D, 0xF1, 0x64, 0x44, 0x03, 0xB4, 0x40, 0x42, 0xD0, 0x80, + 0xA6, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xBB, 0xF4, 0x80, 0x61, 0x02, 0x02, 0xE3, 0x83, 0xEB, 0x83, + 0x22, 0x44, 0x88, 0xFF, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, + 0x9D, 0x85, 0xA7, 0x83, 0x3B, 0xFC, 0x1F, 0x63, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0xBB, 0xF2, + 0x66, 0x44, 0xA5, 0x81, 0xBB, 0xFA, 0x02, 0xA6, 0xFA, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, + 0x27, 0xF2, 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, + 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, + 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, + 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, + 0x63, 0x46, 0xE8, 0x1B, 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x21, 0x00, + 0x43, 0x4B, 0xAB, 0x46, 0x3B, 0xF2, 0x80, 0x60, 0x30, 0x7C, 0xB0, 0x84, 0xA2, 0xDA, 0x4E, 0x61, + 0x76, 0x64, 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x90, 0x64, + 0x04, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0xA0, 0x64, 0x04, 0x63, + 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, + 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x27, 0xF2, 0x1D, 0x60, 0xC0, 0x65, + 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, + 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, + 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, + 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA6, 0xF3, + 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x0D, 0x00, 0x43, 0x4B, 0xAB, 0x46, 0x3B, 0xF2, + 0x80, 0x60, 0x30, 0x61, 0x9D, 0x85, 0xA4, 0x84, 0xA2, 0xDA, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, + 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, 0x46, 0x45, + 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0x00, 0xF4, 0x01, 0xF2, 0x66, 0x5C, 0x25, 0x46, + 0x56, 0x02, 0x70, 0x27, 0x54, 0x00, 0x12, 0x64, 0x03, 0xFA, 0x04, 0xF8, 0x0E, 0xF2, 0x87, 0xFC, + 0x8D, 0xFC, 0x8E, 0xFC, 0xDA, 0x82, 0x16, 0x61, 0x00, 0x63, 0xC9, 0x81, 0x5A, 0xDC, 0xFD, 0x02, + 0x60, 0x40, 0xF0, 0x3B, 0x16, 0x00, 0x32, 0x44, 0xAC, 0xF3, 0x01, 0xB0, 0xFA, 0xA0, 0x08, 0x24, + 0x2C, 0x05, 0xDC, 0x83, 0xF0, 0x67, 0x0E, 0xFA, 0x26, 0x60, 0x04, 0x64, 0x2B, 0xDB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xAC, 0xFD, 0x2B, 0xFF, 0xFE, 0x64, 0x3B, 0x42, 0x4A, 0xDB, + 0x4F, 0x00, 0xAD, 0xF3, 0x05, 0x65, 0xD4, 0x80, 0xDC, 0x83, 0x17, 0x05, 0xAD, 0xFD, 0x98, 0xFE, + 0x04, 0x04, 0x00, 0x7F, 0x08, 0x7E, 0x0E, 0xFA, 0x3B, 0xFF, 0x25, 0x60, 0xF8, 0x64, 0x2B, 0xDB, + 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0x0E, 0xF2, 0x2B, 0xFF, 0x60, 0x40, 0x08, 0x26, + 0xF7, 0xFE, 0xFD, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x32, 0x00, 0xA9, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, + 0xFF, 0xFF, 0x0D, 0x04, 0x26, 0x60, 0x10, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFC, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x21, 0x00, 0x46, 0x45, + 0x00, 0x64, 0x2B, 0xDB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xA2, 0xFF, 0x00, 0xF4, 0x01, 0xF0, 0x0A, 0x18, 0x70, 0x67, 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, + 0xC0, 0x84, 0x01, 0xFA, 0x25, 0x46, 0x25, 0x44, 0x80, 0xFC, 0x05, 0xFA, 0xB6, 0x60, 0x58, 0x4E, + 0xF5, 0x78, 0xFF, 0xFF, 0xD4, 0xFE, 0xA3, 0xFF, 0xFF, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0xD4, 0xFE, + 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0x25, 0x60, 0xFE, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x0D, 0x00, + 0x25, 0x60, 0xF2, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x18, 0x00, 0x26, 0x60, 0x0A, 0x64, 0x40, 0x47, + 0x58, 0x4F, 0x03, 0x00, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x27, 0xD5, 0x0E, 0xF2, 0x0B, 0x18, + 0x60, 0x40, 0x01, 0x2A, 0x08, 0x00, 0x26, 0x60, 0x20, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, + 0x08, 0x78, 0xFF, 0xFF, 0xF2, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0xD5, 0x0E, 0xF2, 0x14, 0x18, + 0x60, 0x40, 0x01, 0x2A, 0x11, 0x00, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, + 0xAD, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0xAD, 0xFB, 0x26, 0x60, 0x20, 0x64, 0x40, 0x4B, 0x34, 0x60, + 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0xE9, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xFB, 0x64, 0x3A, 0x42, + 0x4A, 0xDB, 0xA2, 0xFF, 0xB0, 0xF3, 0xAC, 0xF3, 0xCC, 0x80, 0xFD, 0xA0, 0x01, 0x14, 0x1D, 0x05, + 0xB5, 0x60, 0x58, 0x4D, 0xFA, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, 0x17, 0x03, 0xF0, 0x67, 0x0E, 0xFA, + 0x26, 0x60, 0x04, 0x64, 0x13, 0x60, 0x10, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xF6, 0x64, 0x3A, 0x42, 0x4A, 0xDB, 0xB0, 0xF3, 0xAC, 0xF3, 0xCC, 0x83, + 0xDC, 0x84, 0x01, 0x15, 0xB0, 0xFD, 0xAC, 0xFB, 0xD4, 0xFE, 0xAF, 0xF3, 0xAD, 0xF3, 0x00, 0xA8, + 0xAE, 0xF1, 0x03, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x26, 0x05, 0xB5, 0x60, 0x58, 0x4D, 0xFA, 0x78, + 0xFF, 0xFF, 0xA2, 0xFF, 0x20, 0x03, 0x00, 0x63, 0xAF, 0xF3, 0x0E, 0xFC, 0xCC, 0x84, 0xFF, 0x3A, + 0xAF, 0xFB, 0x98, 0xFE, 0x03, 0x04, 0x08, 0xBB, 0x0E, 0xFC, 0x3B, 0xFF, 0x25, 0x60, 0xF8, 0x64, + 0x13, 0x60, 0x10, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xF7, 0x64, 0x3A, 0x42, 0x4A, 0xDB, 0xAD, 0xF3, 0x0E, 0xF2, 0xDC, 0x83, 0x08, 0xB0, 0xAD, 0xFD, + 0x08, 0x28, 0xF7, 0xFE, 0xD4, 0xFE, 0xA3, 0xFF, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0xB9, 0xFE, + 0x13, 0xFF, 0x24, 0x40, 0x80, 0x2B, 0x0B, 0x00, 0xA2, 0xFF, 0x25, 0x46, 0x09, 0xF4, 0x0E, 0xF2, + 0x05, 0x18, 0x08, 0xBC, 0x0E, 0xFA, 0xFF, 0xFF, 0xF7, 0xFE, 0x01, 0x00, 0xD8, 0xFE, 0xA3, 0xFF, + 0x25, 0x46, 0x3E, 0xF2, 0x00, 0xF4, 0x08, 0xF0, 0x25, 0x46, 0x06, 0xB4, 0xFF, 0x7F, 0x10, 0xBC, + 0x06, 0x26, 0xFD, 0x7F, 0x0E, 0xFA, 0x3E, 0xF2, 0x3F, 0xF2, 0x60, 0x41, 0x08, 0x2A, 0x64, 0x47, + 0x3F, 0xFA, 0x60, 0x45, 0xB9, 0xFC, 0x16, 0x60, 0xAA, 0xF3, 0xA3, 0xFC, 0xAB, 0xFC, 0x91, 0xFC, + 0xD4, 0x80, 0x18, 0x60, 0x21, 0x65, 0xA5, 0x80, 0x01, 0x04, 0x07, 0x03, 0x23, 0xF0, 0x08, 0x64, + 0xB0, 0x84, 0xA2, 0xDA, 0x35, 0x60, 0xEA, 0x78, 0xFF, 0xFF, 0x36, 0x60, 0x58, 0x4F, 0x30, 0x78, + 0xFF, 0xFF, 0x0B, 0x04, 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x2C, 0x60, 0xEE, 0x64, + 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x83, 0x00, 0xDB, 0xF3, 0xA6, 0xF1, 0x07, 0xB4, + 0x64, 0x43, 0xFD, 0xA0, 0x2C, 0xF2, 0x71, 0x02, 0x01, 0xB0, 0x64, 0x43, 0x78, 0x02, 0x2E, 0xF2, + 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, + 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x2E, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, + 0x0C, 0x02, 0x61, 0x46, 0x2D, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, + 0x2C, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, + 0xE8, 0x1B, 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x51, 0x03, 0x63, 0x46, 0x80, 0xF6, + 0x25, 0x46, 0x43, 0x18, 0x2E, 0xF2, 0x66, 0x41, 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, + 0xA6, 0xF1, 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, + 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, + 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, + 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, + 0x60, 0x43, 0x61, 0x46, 0x43, 0x4B, 0x2C, 0xF0, 0xAD, 0xF0, 0x2E, 0xF2, 0xAB, 0x46, 0x03, 0xF8, + 0x84, 0xF8, 0x05, 0xFA, 0x03, 0x64, 0x06, 0xFA, 0xAB, 0x46, 0x1F, 0x60, 0xC2, 0x61, 0xA1, 0xD3, + 0x20, 0x60, 0x04, 0x7C, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, + 0x49, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xA1, 0xDB, 0x0A, 0x00, 0xDB, 0xF3, 0x02, 0xA3, 0xFE, 0xA0, + 0xF9, 0xA0, 0x01, 0x06, 0x04, 0x02, 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x07, 0xFC, + 0x23, 0xF2, 0xFF, 0xFF, 0x24, 0x1B, 0x16, 0x60, 0xAB, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x00, 0x3A, + 0x0F, 0x00, 0x25, 0x60, 0xC8, 0x64, 0x13, 0x60, 0x10, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xC1, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0x1D, 0x00, + 0x25, 0x60, 0xDA, 0x64, 0x13, 0x60, 0x10, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xC8, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0x0E, 0x00, 0x25, 0x60, + 0xEC, 0x64, 0x13, 0x60, 0x10, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0x0E, 0xF2, 0xCE, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, + 0xCB, 0x84, 0xC9, 0x83, 0xFF, 0xFF, 0x08, 0x04, 0x58, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, + 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x2F, 0x58, 0xFF, 0xFF, 0x3E, 0xF2, 0xC9, 0xF1, + 0x08, 0xB0, 0x19, 0xF8, 0x57, 0x02, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF3, 0x30, 0xFA, 0x60, 0x45, + 0xEC, 0xF3, 0x31, 0xFA, 0x46, 0x4A, 0x00, 0xF4, 0x60, 0x43, 0x05, 0xF2, 0x06, 0xF2, 0xD0, 0x80, + 0x07, 0xF0, 0x05, 0x02, 0xD4, 0x80, 0xD3, 0x80, 0x02, 0x02, 0xDB, 0xF3, 0x03, 0x03, 0xAA, 0x46, + 0x42, 0xFE, 0x41, 0x00, 0x60, 0x40, 0x03, 0x2A, 0x20, 0x00, 0x02, 0xF2, 0x03, 0xF0, 0x04, 0xF2, + 0x60, 0x43, 0xAA, 0x46, 0x2C, 0xFC, 0x2D, 0xF8, 0x2E, 0xFA, 0x7F, 0xF1, 0x32, 0xF8, 0x80, 0xF1, + 0x33, 0xF8, 0x81, 0xF1, 0x34, 0xF8, 0x08, 0x64, 0x32, 0x40, 0x04, 0x2A, 0x0D, 0x00, 0x2C, 0xF0, + 0x39, 0xF0, 0x64, 0x40, 0x01, 0x26, 0x08, 0x00, 0x3E, 0xF2, 0xFF, 0xFF, 0x00, 0x60, 0xC0, 0xB4, + 0xE8, 0x84, 0xB0, 0x9C, 0x39, 0xF8, 0x88, 0x64, 0x1C, 0x00, 0x02, 0xF2, 0x03, 0xF0, 0x04, 0xF2, + 0x60, 0x43, 0xAA, 0x46, 0x32, 0xFC, 0x33, 0xF8, 0x34, 0xFA, 0x7F, 0xF1, 0x2C, 0xF8, 0x80, 0xF1, + 0x2D, 0xF8, 0x81, 0xF1, 0x2E, 0xF8, 0x01, 0x60, 0x08, 0x64, 0x32, 0x40, 0x04, 0x2A, 0x09, 0x00, + 0x3E, 0xF2, 0x39, 0xF0, 0x00, 0x60, 0xC0, 0xB4, 0xE8, 0x84, 0xB0, 0x9C, 0x39, 0xF8, 0x01, 0x60, + 0x88, 0x64, 0x2A, 0xFA, 0x02, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x36, 0x60, 0x22, 0x63, 0x20, 0x44, + 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, + 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, + 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, + 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, 0x2F, 0x44, 0xBD, 0xDB, 0x1B, 0x60, + 0x0B, 0xFD, 0x37, 0x60, 0x42, 0x63, 0x1B, 0x60, 0x0C, 0xFD, 0x30, 0x44, 0x1B, 0x60, 0x0D, 0xFB, + 0x31, 0x44, 0x1B, 0x60, 0x0E, 0xFB, 0x32, 0x44, 0x1B, 0x60, 0x0F, 0xFB, 0x33, 0x44, 0x1B, 0x60, + 0x10, 0xFB, 0x81, 0xFF, 0x91, 0xFF, 0x58, 0x51, 0x44, 0x00, 0x82, 0xFF, 0x92, 0xFF, 0x58, 0x51, + 0x40, 0x00, 0x83, 0xFF, 0x93, 0xFF, 0x58, 0x51, 0x3C, 0x00, 0x84, 0xFF, 0x94, 0xFF, 0x58, 0x51, + 0x38, 0x00, 0x85, 0xFF, 0x95, 0xFF, 0x58, 0x51, 0x34, 0x00, 0x86, 0xFF, 0x96, 0xFF, 0x58, 0x51, + 0x30, 0x00, 0x87, 0xFF, 0x97, 0xFF, 0x58, 0x51, 0x2C, 0x00, 0x80, 0xFF, 0x90, 0xFF, 0x99, 0xFF, + 0x1B, 0x60, 0x0B, 0xF1, 0x30, 0x44, 0x64, 0x43, 0xBD, 0xDB, 0x31, 0x44, 0xBD, 0xDB, 0x32, 0x44, + 0xBD, 0xDB, 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, 0x35, 0x44, 0xBD, 0xDB, 0x36, 0x44, + 0xBD, 0xDB, 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, 0x39, 0x44, 0xBD, 0xDB, 0x3A, 0x44, + 0xBD, 0xDB, 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, 0x3D, 0x44, 0xBD, 0xDB, 0x3E, 0x44, + 0xBD, 0xDB, 0x3F, 0x44, 0xBD, 0xDB, 0xF6, 0x60, 0x16, 0x64, 0x0A, 0xFB, 0x40, 0x21, 0xFE, 0x01, + 0x74, 0x00, 0x42, 0x50, 0x40, 0x53, 0x1B, 0x60, 0x0C, 0xF3, 0xFF, 0xFF, 0x40, 0x52, 0x33, 0x44, + 0x32, 0x42, 0xA2, 0xDB, 0xDA, 0x82, 0xA2, 0xDD, 0xDA, 0x83, 0x65, 0x44, 0xBD, 0xDB, 0x61, 0x44, + 0xBD, 0xDB, 0x66, 0x44, 0xBD, 0xDB, 0xBD, 0xD9, 0x30, 0x44, 0xBD, 0xDB, 0x99, 0xFF, 0xA4, 0x4C, + 0xBD, 0xDB, 0xA5, 0x4C, 0xBD, 0xDB, 0xA0, 0x4C, 0xBD, 0xDB, 0xA1, 0x4C, 0xBD, 0xDB, 0x98, 0xFF, + 0x1B, 0x60, 0x0C, 0xFD, 0x1B, 0x60, 0x0D, 0xF3, 0xFF, 0xFF, 0x40, 0x50, 0x1B, 0x60, 0x0F, 0xF3, + 0xFF, 0xFF, 0x40, 0x52, 0x1B, 0x60, 0x10, 0xF3, 0xFF, 0xFF, 0x40, 0x53, 0x31, 0x41, 0x1B, 0x60, + 0x0E, 0xF3, 0xFF, 0xFF, 0x40, 0x51, 0x1B, 0x60, 0x0B, 0xF3, 0xFF, 0xFF, 0x60, 0x43, 0x20, 0x44, + 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, + 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, + 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, + 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, 0x2F, 0x44, 0xBD, 0xDB, 0x1B, 0x60, + 0x0B, 0xFD, 0x61, 0x58, 0xFF, 0xFF, 0x2F, 0x60, 0x4E, 0x63, 0xA3, 0xD3, 0x33, 0x5C, 0x02, 0xA4, + 0xBD, 0xDB, 0xFE, 0xB4, 0xE0, 0x85, 0xC4, 0x85, 0x47, 0xD9, 0x34, 0x44, 0x5B, 0xDB, 0x44, 0xF3, + 0x5B, 0xDB, 0xA1, 0xFF, 0xFF, 0xFF, 0x87, 0x3E, 0x84, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x87, 0x3E, + 0xFF, 0x01, 0x86, 0xE1, 0x80, 0xFF, 0x90, 0xFF, 0x88, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x87, 0x3E, + 0x19, 0x60, 0xF7, 0xF3, 0xFF, 0xFF, 0x10, 0x1B, 0x32, 0x40, 0x80, 0x2A, 0xF6, 0x01, 0x9D, 0xFE, + 0xF4, 0x05, 0xDB, 0xF3, 0xFF, 0xFF, 0x04, 0xA8, 0x33, 0x60, 0xE2, 0x62, 0x01, 0x02, 0xBD, 0x00, + 0xA2, 0xD3, 0xFF, 0xFF, 0x4A, 0x1B, 0xE9, 0x01, 0x87, 0xFF, 0x20, 0x44, 0x80, 0xFF, 0x60, 0x40, + 0x80, 0x26, 0xE3, 0x01, 0xF1, 0xFC, 0xAD, 0x4F, 0xFD, 0xB4, 0xA0, 0x5D, 0xC0, 0x60, 0x40, 0xEC, + 0xC0, 0x60, 0x00, 0xED, 0xC0, 0x60, 0x80, 0xEE, 0xAC, 0x4F, 0xBF, 0xB4, 0xA0, 0x5C, 0x19, 0x60, + 0x48, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x02, 0x27, 0x06, 0x00, 0x28, 0xE2, 0x24, 0xE2, 0x40, 0x21, + 0xFE, 0x01, 0x75, 0x40, 0x0D, 0x00, 0x28, 0xE2, 0x24, 0xE2, 0x75, 0x40, 0x80, 0x2B, 0xAB, 0xFF, + 0x14, 0xE0, 0x94, 0xE0, 0x40, 0x21, 0xFE, 0x01, 0x10, 0xE0, 0x75, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, + 0x33, 0x60, 0xEE, 0x62, 0xA2, 0xDF, 0x01, 0x60, 0x39, 0xE2, 0x04, 0x60, 0x00, 0x7A, 0xAC, 0x4F, + 0x40, 0xBC, 0x00, 0x7F, 0xA0, 0x5C, 0xC0, 0x60, 0x59, 0xEC, 0xC0, 0x60, 0x07, 0xED, 0xC0, 0x60, + 0x8F, 0xEE, 0xAE, 0x4F, 0x04, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x26, 0x61, 0xCD, 0x81, 0xFF, 0xFF, + 0xFD, 0x02, 0xAE, 0x4F, 0xFB, 0xB4, 0xA0, 0x5E, 0xA0, 0x01, 0xF1, 0xFC, 0xAD, 0x4F, 0xFD, 0xB4, + 0xA0, 0x5D, 0x15, 0x60, 0x80, 0xE7, 0xC0, 0x60, 0x40, 0xEC, 0xC0, 0x60, 0x00, 0xED, 0xAC, 0x4F, + 0xBF, 0xB4, 0xA0, 0x5C, 0xC0, 0x60, 0x84, 0xEE, 0xAE, 0x4F, 0x04, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, + 0x00, 0x7A, 0x0F, 0x60, 0x19, 0xE2, 0x0E, 0x60, 0x36, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x75, 0x44, + 0x80, 0x2B, 0xAB, 0xFF, 0x80, 0x27, 0x08, 0x00, 0x14, 0xE0, 0x94, 0xE0, 0x34, 0xE2, 0x61, 0x5A, + 0x48, 0x21, 0xFE, 0x01, 0x00, 0xE0, 0x75, 0x40, 0x0A, 0x60, 0x19, 0xE2, 0x00, 0x64, 0x19, 0x60, + 0xF1, 0xFB, 0x08, 0x60, 0x15, 0xF1, 0x08, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x01, 0x64, 0x19, 0x60, 0xF2, 0xFB, 0xFF, 0xFF, 0x10, 0xE0, 0x01, 0x60, 0x34, 0xE2, 0xFF, 0xFF, + 0x05, 0x7A, 0xAC, 0x4F, 0x40, 0xBC, 0x00, 0x7F, 0xA0, 0x5C, 0xC0, 0x60, 0x59, 0xEC, 0xC0, 0x60, + 0x07, 0xED, 0xC0, 0x60, 0x8F, 0xEE, 0xAE, 0x4F, 0x04, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x1B, 0x60, + 0xF3, 0xF1, 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x7D, 0xF1, 0x02, 0xB1, 0x04, 0x65, + 0x02, 0x02, 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x26, 0x61, 0xCD, 0x81, + 0xFF, 0xFF, 0xFD, 0x02, 0xAE, 0x4F, 0xFB, 0xB4, 0xA0, 0x5E, 0x1B, 0x60, 0xF3, 0xF1, 0xAD, 0x4F, + 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x7D, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, 0x64, 0x40, + 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x30, 0x01, 0x19, 0x60, 0xF3, 0xF3, 0xFF, 0xFF, + 0x01, 0x1B, 0x2B, 0x01, 0x31, 0x44, 0x04, 0x2A, 0x28, 0x01, 0x08, 0x26, 0x26, 0x01, 0x19, 0x60, + 0xF4, 0xF3, 0xFF, 0xFF, 0x01, 0x18, 0x21, 0x01, 0x7E, 0xF5, 0xF1, 0xFC, 0xAD, 0x4F, 0xFD, 0xB4, + 0xA0, 0x5D, 0x15, 0x60, 0x80, 0xE7, 0xC0, 0x60, 0x40, 0xEC, 0xC0, 0x60, 0x00, 0xED, 0xAC, 0x4F, + 0xBF, 0xB4, 0xA0, 0x5C, 0xC0, 0x60, 0x84, 0xEE, 0xAE, 0x4F, 0x04, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, + 0x00, 0x7A, 0x2D, 0x60, 0x5A, 0x63, 0xA3, 0xD1, 0x05, 0x60, 0xDC, 0x64, 0xD0, 0x80, 0x00, 0x64, + 0x01, 0x06, 0x01, 0x64, 0x40, 0x4E, 0xB2, 0xF1, 0x66, 0x41, 0xE1, 0x81, 0xE1, 0x81, 0xE1, 0x81, + 0xE1, 0x81, 0x61, 0x46, 0x73, 0x42, 0x5A, 0x92, 0x3F, 0x64, 0xA0, 0x84, 0x60, 0x47, 0xE0, 0x84, + 0xE0, 0x85, 0x62, 0x47, 0xE8, 0x84, 0xE8, 0x84, 0x3F, 0xB4, 0x60, 0x41, 0x64, 0x44, 0x14, 0x90, + 0x3F, 0x26, 0xCC, 0x84, 0x14, 0x90, 0x3F, 0x26, 0xCC, 0x84, 0x62, 0x41, 0x60, 0x55, 0xB2, 0xFB, + 0x72, 0x5C, 0x67, 0x42, 0xD2, 0x80, 0xA2, 0x48, 0x20, 0x2B, 0x05, 0x00, 0x01, 0x02, 0x7C, 0x5C, + 0x04, 0x60, 0x00, 0x64, 0xC4, 0x85, 0xE8, 0xE2, 0xE4, 0xE2, 0x61, 0x42, 0x49, 0x91, 0x64, 0x44, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xB4, 0x84, 0x60, 0x45, + 0x51, 0x94, 0x04, 0x60, 0x00, 0x61, 0x01, 0x0D, 0x44, 0x94, 0x62, 0x41, 0x19, 0x60, 0xF5, 0xF1, + 0x61, 0x42, 0x64, 0x43, 0xCF, 0x83, 0xCF, 0x83, 0x03, 0x03, 0xE3, 0x83, 0x48, 0x94, 0xFE, 0x1F, + 0x2E, 0x40, 0x01, 0x26, 0xE0, 0x84, 0x60, 0x41, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, + 0x44, 0x94, 0xE9, 0x81, 0xE9, 0x81, 0x54, 0x94, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0x44, 0x94, + 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0x54, 0x94, 0x19, 0xE2, 0x2E, 0x40, 0x01, 0x26, 0xE8, 0x84, + 0x29, 0x61, 0x54, 0x91, 0x61, 0x43, 0x11, 0x06, 0x75, 0x44, 0x80, 0x2B, 0xAB, 0xFF, 0x80, 0x27, + 0x0C, 0x00, 0x14, 0xE0, 0x94, 0xE0, 0x34, 0xE2, 0x61, 0x5A, 0x48, 0x21, 0xFE, 0x01, 0x00, 0xE0, + 0x7A, 0x43, 0x15, 0xA1, 0x75, 0x40, 0x80, 0x2B, 0x06, 0xA1, 0x5D, 0x91, 0x61, 0x44, 0x2E, 0x40, + 0x01, 0x26, 0xE0, 0x84, 0x60, 0x43, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0x89, 0xFF, 0x10, 0xE0, + 0x80, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xEB, 0x83, 0xEB, 0x83, 0x5C, 0x94, 0xEB, 0x83, 0x5C, 0x94, + 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0x4C, 0x94, 0x2E, 0x40, 0x01, 0x26, + 0xE8, 0x84, 0x60, 0x43, 0x65, 0x41, 0x62, 0x45, 0xD5, 0x85, 0x04, 0x60, 0x00, 0x61, 0x01, 0x0D, + 0xC5, 0x85, 0xC4, 0x84, 0x60, 0x43, 0x62, 0x41, 0xE1, 0x81, 0xE1, 0x81, 0xE1, 0x81, 0xE1, 0x81, + 0xE1, 0x81, 0xE1, 0x9C, 0x00, 0x61, 0xDD, 0x81, 0x58, 0x94, 0x4A, 0x92, 0xFC, 0x05, 0x41, 0x4F, + 0x00, 0x61, 0x62, 0x45, 0x1C, 0x60, 0x0A, 0xF3, 0xE3, 0x83, 0xF1, 0x81, 0xE3, 0x83, 0xF1, 0x81, + 0xE3, 0x83, 0xF1, 0x81, 0xE3, 0x83, 0xF1, 0x81, 0xE3, 0x83, 0xF1, 0x81, 0xE3, 0x83, 0xF1, 0x81, + 0xA0, 0x52, 0xB2, 0xF3, 0xC3, 0x9C, 0x44, 0x94, 0x01, 0x04, 0xDC, 0x84, 0x60, 0x55, 0xB2, 0xFB, + 0x64, 0x52, 0xE9, 0xE2, 0x65, 0x53, 0xB3, 0xF3, 0x06, 0x04, 0xDC, 0x84, 0xB3, 0xFB, 0xB4, 0xF3, + 0x02, 0x04, 0xDC, 0x84, 0xB4, 0xFB, 0x2F, 0x43, 0xCF, 0x83, 0x6C, 0xF3, 0xFF, 0xFF, 0x5C, 0x94, + 0xFF, 0xFF, 0x0C, 0x24, 0x01, 0x64, 0x6C, 0xFB, 0x16, 0x60, 0xAC, 0xF1, 0xFF, 0xFF, 0x03, 0x1B, + 0x31, 0x40, 0x02, 0x2A, 0x07, 0x00, 0x73, 0xF3, 0xFF, 0xFF, 0x5C, 0x94, 0xFF, 0xFF, 0x0C, 0x24, + 0x00, 0x64, 0x73, 0xFB, 0x19, 0x60, 0xF5, 0xF3, 0x01, 0x7C, 0x5C, 0x94, 0x00, 0x36, 0x01, 0x64, + 0xA2, 0xDB, 0x19, 0x60, 0xF2, 0xF9, 0x01, 0x60, 0x34, 0xE2, 0x32, 0x7A, 0xAC, 0x4F, 0x40, 0xBC, + 0x00, 0x7F, 0xA0, 0x5C, 0xC0, 0x60, 0x59, 0xEC, 0xC0, 0x60, 0x07, 0xED, 0xC0, 0x60, 0x8F, 0xEE, + 0xAE, 0x4F, 0x04, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x0A, 0x61, 0xCD, 0x81, 0xFF, 0xFF, 0xFD, 0x02, + 0xAE, 0x4F, 0xFB, 0xB4, 0xA0, 0x5E, 0x1B, 0x60, 0xF3, 0xF1, 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, + 0x64, 0x41, 0x7D, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, + 0xB4, 0x84, 0xA0, 0x5D, 0x37, 0x60, 0x7F, 0x78, 0xFF, 0xFF, 0x24, 0xE2, 0x2D, 0xF3, 0x2C, 0xF3, + 0x00, 0xBD, 0xCC, 0x84, 0x08, 0x03, 0x2C, 0xFB, 0x06, 0x02, 0x65, 0x44, 0x2C, 0xFB, 0x8A, 0xFF, + 0x80, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x44, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x44, 0xFB, 0x2F, 0x60, + 0x4A, 0x65, 0x2F, 0x60, 0x48, 0x61, 0xA5, 0xD3, 0xA1, 0xD3, 0x11, 0x18, 0xCC, 0x84, 0xA1, 0xDB, + 0x0E, 0x02, 0xA5, 0xD3, 0xA1, 0xDB, 0x17, 0x60, 0xA7, 0xF3, 0x17, 0x60, 0xA6, 0xF1, 0xA2, 0xDB, + 0xD0, 0x80, 0xFF, 0xFF, 0x04, 0x03, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xF1, 0xF3, + 0x31, 0x40, 0x01, 0x2A, 0x3D, 0x00, 0x60, 0x43, 0x04, 0xB0, 0x02, 0xB0, 0x08, 0x24, 0x16, 0x02, + 0x10, 0xB0, 0x29, 0x44, 0x34, 0x02, 0x00, 0xA8, 0xCC, 0x81, 0x0D, 0x03, 0x41, 0x49, 0x2F, 0x02, + 0x63, 0x40, 0x08, 0x2A, 0x08, 0x00, 0xF7, 0xB3, 0x1B, 0x60, 0xF6, 0xF1, 0xAD, 0x4F, 0xFD, 0xB4, + 0xA0, 0x5D, 0x44, 0x49, 0x24, 0x00, 0x63, 0x40, 0x02, 0x2A, 0x10, 0x00, 0x1B, 0x60, 0xF7, 0xF3, + 0x1B, 0x60, 0xF5, 0xFB, 0x40, 0x49, 0x1B, 0x60, 0xF8, 0xF3, 0x1B, 0x60, 0xF6, 0xFB, 0x0C, 0xBB, + 0xFD, 0xB3, 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0x11, 0x00, 0x1B, 0x60, 0xF9, 0xF3, + 0x37, 0x60, 0xEA, 0x7C, 0x0C, 0x18, 0xA4, 0xDB, 0x40, 0x49, 0x1B, 0x60, 0xFA, 0xF3, 0x1B, 0x60, + 0xF6, 0xFB, 0x08, 0xBB, 0xFB, 0xB3, 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0xF1, 0xFD, + 0x00, 0x60, 0xA4, 0xF3, 0x62, 0x43, 0x17, 0x18, 0x58, 0xD3, 0x62, 0x41, 0x03, 0x18, 0xCC, 0x84, + 0xA1, 0xDB, 0x11, 0x00, 0x49, 0xD3, 0xA3, 0xDB, 0x06, 0xA1, 0xA1, 0xD3, 0x59, 0xD1, 0x60, 0x45, + 0xA5, 0xD3, 0x59, 0xD1, 0xB0, 0x84, 0xA5, 0xDB, 0x64, 0x44, 0x06, 0x36, 0xCD, 0xFE, 0x07, 0x36, + 0xD6, 0xFE, 0xE6, 0x01, 0x23, 0x46, 0xB8, 0x60, 0x03, 0x78, 0xFF, 0xFF, 0x46, 0x43, 0x26, 0x60, + 0x3E, 0x61, 0xA1, 0xD3, 0x59, 0xD1, 0x06, 0x1B, 0x59, 0xD3, 0x59, 0xD1, 0x03, 0x1B, 0x59, 0xD3, + 0x59, 0xD1, 0xF0, 0x18, 0x00, 0x63, 0x49, 0xDD, 0x60, 0x40, 0x02, 0x36, 0x11, 0x00, 0x03, 0x36, + 0x32, 0x00, 0x01, 0x36, 0x08, 0x00, 0x05, 0x3A, 0xEA, 0x01, 0xA4, 0xD3, 0x5A, 0xD3, 0x9C, 0x85, + 0xA4, 0x84, 0xA2, 0xDB, 0xE4, 0x01, 0x01, 0x60, 0x48, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0xDF, 0x01, + 0x3A, 0x60, 0x3E, 0x64, 0x40, 0x45, 0x22, 0x00, 0x01, 0x60, 0x48, 0x66, 0xA6, 0xD3, 0x04, 0xA1, + 0x60, 0x43, 0xA1, 0xD3, 0xC9, 0x81, 0x60, 0x45, 0x00, 0xBB, 0xA1, 0xDB, 0xBE, 0xD3, 0x09, 0x03, + 0xD4, 0x84, 0x9C, 0x84, 0xDC, 0x84, 0xFF, 0xFF, 0x04, 0x0E, 0xA3, 0xD1, 0x63, 0x46, 0x64, 0x43, + 0xF2, 0x01, 0x9C, 0x84, 0xDC, 0x85, 0x49, 0xDD, 0x61, 0x44, 0x00, 0xBB, 0xA6, 0xDB, 0x02, 0x03, + 0x65, 0x44, 0xBE, 0xDB, 0xBC, 0x01, 0x3A, 0x60, 0x19, 0x64, 0x40, 0x45, 0x01, 0x60, 0x48, 0x66, + 0xA6, 0xD3, 0xFF, 0xFF, 0xD0, 0x80, 0x0F, 0x18, 0x02, 0x03, 0x60, 0x46, 0xF9, 0x01, 0x58, 0xD3, + 0xA4, 0xD3, 0x60, 0x45, 0x00, 0x63, 0xA4, 0xDD, 0x05, 0x18, 0x58, 0xD3, 0xFF, 0xFF, 0xC4, 0x83, + 0xA2, 0xDD, 0xCA, 0x84, 0xA6, 0xDB, 0x25, 0x58, 0x64, 0x41, 0x00, 0x60, 0x46, 0x74, 0xCD, 0xE2, + 0x04, 0xE1, 0x02, 0x60, 0x00, 0xE1, 0x3F, 0x44, 0x40, 0x26, 0x05, 0x00, 0x1C, 0x60, 0x0F, 0xF3, + 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x50, 0x3F, 0x40, 0x02, 0x2B, 0x03, 0x00, 0x3A, 0x60, 0xB7, 0x78, + 0xFF, 0xFF, 0x04, 0x29, 0xFE, 0x01, 0xC4, 0xE2, 0x43, 0x64, 0x3A, 0xDB, 0xA1, 0xF3, 0xFF, 0xFF, + 0x60, 0x41, 0x3F, 0x44, 0xFF, 0x01, 0x3F, 0x40, 0x40, 0x26, 0x05, 0x00, 0x1C, 0x60, 0x0D, 0xF3, + 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x52, 0xC4, 0xE2, 0x32, 0x7B, 0x4D, 0xE2, 0xBF, 0xFE, 0xC4, 0xE2, + 0x41, 0xFF, 0xE0, 0xFE, 0xE1, 0xFE, 0xE2, 0xFE, 0x43, 0xFF, 0x44, 0xFF, 0x46, 0xFF, 0xA2, 0xF3, + 0x62, 0xFF, 0x60, 0x40, 0x05, 0x36, 0x2D, 0xFF, 0x07, 0x36, 0xD5, 0xFE, 0x08, 0xE1, 0x88, 0x60, + 0x85, 0x71, 0x8D, 0xE2, 0xA2, 0x60, 0x41, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x62, 0x3D, 0x60, + 0x58, 0x4D, 0x3B, 0x78, 0xFF, 0xFF, 0x64, 0x41, 0xA9, 0x9C, 0x60, 0x45, 0x3D, 0x60, 0x58, 0x4D, + 0x0F, 0x78, 0xFF, 0xFF, 0xA1, 0xF1, 0x09, 0x60, 0xB4, 0x61, 0x64, 0x44, 0x01, 0x27, 0x24, 0x00, + 0x60, 0x40, 0x0E, 0x3A, 0x0D, 0x00, 0x01, 0x7C, 0x14, 0x60, 0x6F, 0xF9, 0x44, 0x60, 0x08, 0x7C, + 0x14, 0x60, 0x41, 0xF9, 0x16, 0x60, 0x62, 0xF1, 0x02, 0x60, 0xB0, 0x61, 0xB1, 0x9C, 0x26, 0x00, + 0x00, 0x7C, 0x14, 0x60, 0x6F, 0xF9, 0x40, 0x60, 0x08, 0x7C, 0x14, 0x60, 0x41, 0xF9, 0x16, 0x60, + 0x62, 0xF1, 0x02, 0x60, 0x90, 0x61, 0xB1, 0x9C, 0x09, 0x60, 0x67, 0x65, 0xFF, 0xB4, 0xC4, 0x85, + 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x81, 0x12, 0x00, 0xFF, 0xB4, 0xED, 0xA0, 0x2C, 0x60, 0xC6, 0x61, + 0x04, 0x04, 0xE2, 0xA0, 0xD9, 0x81, 0x01, 0x04, 0xD9, 0x81, 0xA1, 0xD1, 0x02, 0x60, 0x50, 0x61, + 0x26, 0x60, 0xF0, 0x65, 0xE0, 0x84, 0x44, 0xD3, 0xB1, 0x9C, 0xC8, 0x81, 0x61, 0x47, 0x00, 0x7E, + 0xE9, 0x81, 0x07, 0x60, 0xF0, 0x65, 0xA5, 0x81, 0x0B, 0xB9, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x85, + 0xB5, 0x85, 0x04, 0x60, 0x44, 0x62, 0x3D, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0xA1, 0xF3, + 0xC8, 0x61, 0x61, 0x54, 0xCD, 0xE2, 0x60, 0x40, 0x01, 0x27, 0x2E, 0x00, 0xCC, 0x84, 0xE0, 0x85, + 0x15, 0x60, 0xA2, 0xE7, 0x26, 0x60, 0x80, 0x64, 0x3D, 0x60, 0x58, 0x4F, 0x04, 0x78, 0xFF, 0xFF, + 0x26, 0x60, 0x9C, 0x64, 0x3D, 0x60, 0x58, 0x4F, 0x04, 0x78, 0xFF, 0xFF, 0x26, 0x60, 0xB8, 0x64, + 0x3D, 0x60, 0x58, 0x4F, 0x04, 0x78, 0xFF, 0xFF, 0x26, 0x60, 0xD4, 0x64, 0x3D, 0x60, 0x58, 0x4F, + 0x04, 0x78, 0xFF, 0xFF, 0x75, 0x64, 0x06, 0x61, 0x61, 0x48, 0x60, 0x44, 0x80, 0xBC, 0xFF, 0xB4, + 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x28, 0x60, 0xE6, 0x7C, 0x07, 0x60, 0xE8, 0xF9, + 0x28, 0x60, 0x6E, 0x63, 0x14, 0x61, 0x21, 0x00, 0x14, 0x60, 0xDF, 0xF1, 0xFF, 0xB4, 0xED, 0xA0, + 0x64, 0x41, 0x04, 0x04, 0xE2, 0xA0, 0xD9, 0x81, 0x01, 0x04, 0xD9, 0x81, 0xA1, 0xD1, 0x14, 0x60, + 0x0E, 0xF3, 0x64, 0x41, 0xFF, 0xB1, 0xFF, 0x60, 0x00, 0x65, 0xA4, 0x84, 0x34, 0x94, 0xA2, 0xDB, + 0x5A, 0xD3, 0x64, 0x41, 0xA5, 0x81, 0xFF, 0xB4, 0x34, 0x94, 0xA2, 0xDB, 0x29, 0x60, 0x52, 0x7C, + 0x07, 0x60, 0xE8, 0xF9, 0x27, 0x60, 0xFC, 0x63, 0x13, 0x61, 0x3D, 0x60, 0x58, 0x4D, 0x23, 0x78, + 0xFF, 0xFF, 0x07, 0x60, 0xE8, 0xF3, 0x31, 0x40, 0x80, 0x26, 0x36, 0xA4, 0x07, 0x60, 0xE8, 0xFB, + 0x60, 0x43, 0x09, 0x61, 0x3D, 0x60, 0x58, 0x4D, 0x23, 0x78, 0xFF, 0xFF, 0xA1, 0xF3, 0x29, 0x60, + 0xBE, 0x61, 0x00, 0x7C, 0x7E, 0x63, 0x59, 0xD9, 0xFE, 0x1F, 0x60, 0x40, 0x01, 0x27, 0x03, 0x00, + 0x2A, 0x60, 0x40, 0x65, 0x15, 0x00, 0xFF, 0xB4, 0xF9, 0xA0, 0x2A, 0x60, 0x62, 0x65, 0x01, 0x7C, + 0x0D, 0x04, 0xED, 0xA0, 0x2A, 0x60, 0x84, 0x65, 0x11, 0x7C, 0x08, 0x04, 0xE2, 0xA0, 0x2A, 0x60, + 0xA6, 0x65, 0x21, 0x7C, 0x03, 0x04, 0x2A, 0x60, 0xC8, 0x65, 0x31, 0x7C, 0x64, 0x5F, 0x7D, 0xFB, + 0xA5, 0xD3, 0xDA, 0x85, 0xF0, 0xA0, 0x29, 0x60, 0xBE, 0x61, 0x08, 0x06, 0x40, 0x54, 0x58, 0x53, + 0x08, 0xFF, 0x37, 0x60, 0x7A, 0x64, 0x43, 0xFB, 0x08, 0xFF, 0xFF, 0x01, 0x60, 0x43, 0x60, 0x46, + 0xA5, 0xD1, 0xDA, 0x85, 0xA5, 0xD3, 0xDA, 0x85, 0x59, 0xD9, 0x59, 0xDB, 0x59, 0xD9, 0x59, 0xDB, + 0xFB, 0x1F, 0x0C, 0x63, 0xA5, 0xD1, 0xDA, 0x85, 0xA5, 0xD3, 0xDA, 0x85, 0x59, 0xD9, 0x59, 0xDB, + 0x59, 0xD9, 0x59, 0xDB, 0xF7, 0x1F, 0x66, 0x44, 0x0E, 0x63, 0x53, 0x93, 0x60, 0x40, 0x10, 0x36, + 0x07, 0x00, 0x65, 0x44, 0x48, 0xD3, 0x59, 0xD9, 0x59, 0xDB, 0x59, 0xD9, 0x59, 0xDB, 0xFB, 0x1F, + 0x16, 0x60, 0x39, 0xF1, 0x7D, 0xF3, 0x64, 0x43, 0xDB, 0x81, 0x2C, 0x60, 0x54, 0x65, 0x60, 0x40, + 0x01, 0x37, 0x12, 0x00, 0x11, 0x37, 0x17, 0x00, 0x21, 0x37, 0x1D, 0x00, 0x31, 0x37, 0x22, 0x00, + 0xA3, 0xD1, 0x16, 0x60, 0x34, 0xF5, 0x64, 0x44, 0xFF, 0xB4, 0x16, 0x60, 0x33, 0xFB, 0x64, 0x47, + 0xFF, 0xB4, 0x16, 0x60, 0x2A, 0xF1, 0x1D, 0x00, 0xA1, 0xD3, 0x16, 0x60, 0x35, 0xF5, 0xFF, 0xB4, + 0x16, 0x60, 0x2B, 0xF1, 0x16, 0x00, 0xA1, 0xD3, 0x16, 0x60, 0x36, 0xF5, 0x60, 0x47, 0xFF, 0xB4, + 0x16, 0x60, 0x2C, 0xF1, 0x0E, 0x00, 0x59, 0xD3, 0x16, 0x60, 0x37, 0xF5, 0xFF, 0xB4, 0x16, 0x60, + 0x2D, 0xF1, 0x07, 0x00, 0x59, 0xD3, 0x16, 0x60, 0x38, 0xF5, 0x60, 0x47, 0xFF, 0xB4, 0x16, 0x60, + 0x2E, 0xF1, 0x16, 0x60, 0x32, 0xFB, 0x16, 0x60, 0x2F, 0xF9, 0x66, 0x42, 0xFC, 0xA2, 0xA2, 0xD3, + 0x2B, 0x60, 0x42, 0x63, 0xCC, 0x84, 0xE8, 0x84, 0xCC, 0x81, 0x63, 0x45, 0xA6, 0xD3, 0xDA, 0x82, + 0xFF, 0xB4, 0xFF, 0xFF, 0x03, 0x03, 0x60, 0x40, 0x80, 0x2B, 0x03, 0x00, 0xDA, 0x86, 0xCD, 0x81, + 0xF5, 0x01, 0x00, 0xB9, 0xA6, 0xD3, 0x0B, 0x03, 0x5A, 0xD1, 0xDA, 0x86, 0xFF, 0xB4, 0xE0, 0x84, + 0xC4, 0x84, 0x5C, 0x90, 0xBD, 0xD9, 0xFD, 0x02, 0xCD, 0x81, 0x66, 0x42, 0xF2, 0x02, 0x5A, 0xD3, + 0x2B, 0x60, 0x80, 0x65, 0xD7, 0x80, 0xBD, 0xDB, 0xFD, 0x02, 0x7D, 0xF3, 0x19, 0x60, 0x7B, 0xF1, + 0x60, 0x40, 0x01, 0x27, 0x09, 0x00, 0x64, 0x40, 0x10, 0x26, 0x06, 0x00, 0x13, 0x64, 0xCB, 0xFB, + 0x01, 0x60, 0x67, 0x64, 0x37, 0xFB, 0x09, 0x00, 0x08, 0x64, 0xCB, 0xFB, 0xA1, 0xF3, 0x01, 0x60, + 0x67, 0x7C, 0x60, 0x40, 0x01, 0x27, 0x5B, 0x7C, 0x37, 0xF9, 0x19, 0x60, 0x4D, 0xF1, 0x7D, 0xF3, + 0x64, 0x40, 0x00, 0x3A, 0x1B, 0x00, 0x60, 0x40, 0x01, 0x27, 0x0D, 0x00, 0x32, 0x60, 0xAB, 0x63, + 0x4C, 0x94, 0x0E, 0xA5, 0x60, 0xFE, 0xA0, 0xD1, 0xA5, 0xD3, 0x19, 0x60, 0x72, 0xF9, 0x19, 0x60, + 0x73, 0xFB, 0x20, 0xFE, 0x0B, 0x00, 0xFF, 0xB4, 0xF8, 0xA4, 0x32, 0x60, 0xC8, 0x63, 0x4C, 0x94, + 0x60, 0xFE, 0xA0, 0xD1, 0xFF, 0xFF, 0x19, 0x60, 0x73, 0xF9, 0x20, 0xFE, 0x19, 0x60, 0x75, 0xF3, + 0x16, 0x60, 0xD8, 0xF1, 0x60, 0x43, 0xD3, 0x80, 0x19, 0x60, 0x76, 0xF3, 0x01, 0x07, 0x63, 0x5C, + 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x07, 0x60, 0x5C, 0x19, 0x60, 0x4F, 0xF9, 0x19, 0x60, 0x53, 0xF9, + 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, 0x0A, 0x00, 0xFF, 0xB5, 0x10, 0x60, 0xF4, 0x63, + 0x65, 0x41, 0xCD, 0x81, 0x06, 0xA3, 0xFD, 0x02, 0xFA, 0xA3, 0xA3, 0xD3, 0x0F, 0x00, 0x01, 0x60, + 0xFF, 0x65, 0xA4, 0x84, 0x11, 0x60, 0x60, 0x61, 0xA1, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, 0x08, 0xA1, + 0xFB, 0x02, 0xFC, 0xA1, 0xA1, 0xD3, 0x19, 0x60, 0x4F, 0xF1, 0xFF, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, + 0x04, 0x07, 0x19, 0x60, 0x4F, 0xFB, 0x19, 0x60, 0x53, 0xFB, 0x19, 0x60, 0x4F, 0xF3, 0x19, 0x60, + 0x72, 0xF1, 0x19, 0x60, 0x74, 0xFB, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x04, 0x19, 0x60, 0x74, 0xF9, + 0x2C, 0x60, 0x74, 0x63, 0x2B, 0x60, 0x02, 0x65, 0x16, 0x60, 0x33, 0xF1, 0x2A, 0x60, 0xEA, 0x61, + 0x2C, 0x60, 0x62, 0x64, 0x40, 0x4F, 0x04, 0x64, 0xC3, 0x60, 0x58, 0x4D, 0x1A, 0x78, 0xFF, 0xFF, + 0x19, 0x60, 0x4F, 0xF3, 0x19, 0x60, 0x73, 0xF1, 0x19, 0x60, 0x74, 0xFB, 0xD0, 0x80, 0xFF, 0xFF, + 0x02, 0x04, 0x19, 0x60, 0x74, 0xF9, 0x2C, 0x60, 0x7C, 0x63, 0x16, 0x60, 0x32, 0xF1, 0x2B, 0x60, + 0x42, 0x65, 0x2C, 0x60, 0x60, 0x64, 0x40, 0x4F, 0x08, 0x64, 0xC3, 0x60, 0x58, 0x4D, 0x1A, 0x78, + 0xFF, 0xFF, 0x7D, 0xF3, 0x08, 0x7C, 0x38, 0xF9, 0x2B, 0x60, 0xDA, 0x61, 0x60, 0x40, 0x01, 0x2B, + 0x0E, 0x00, 0x01, 0x37, 0x06, 0x00, 0x11, 0x37, 0x03, 0x00, 0x21, 0x3B, 0x1E, 0xA1, 0x1E, 0xA1, + 0x1E, 0xA1, 0x1C, 0x63, 0x2B, 0x60, 0xBC, 0x64, 0x59, 0xD1, 0x58, 0xD9, 0xFD, 0x1F, 0x16, 0x60, + 0x2F, 0xF3, 0x00, 0x7C, 0x60, 0x45, 0x70, 0x62, 0x3D, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, + 0x04, 0x29, 0xFE, 0x01, 0x00, 0x60, 0x10, 0x62, 0x3D, 0x60, 0x58, 0x4D, 0x3B, 0x78, 0xFF, 0xFF, + 0x01, 0x61, 0xB1, 0x9C, 0x60, 0x45, 0x3D, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0x3A, 0x60, + 0x95, 0x78, 0xFF, 0xFF, 0x44, 0xD3, 0x80, 0x7C, 0x60, 0x48, 0x60, 0x47, 0x00, 0x7F, 0xB0, 0x8A, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xD5, 0x60, 0x84, 0xE7, 0x62, 0x47, + 0x80, 0xBF, 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x64, 0x4A, 0xFF, 0xFF, 0x01, 0x16, + 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x2D, 0x58, + 0xFF, 0xFF, 0x00, 0x7C, 0xBD, 0xD3, 0xD5, 0x60, 0x84, 0xE7, 0x60, 0x47, 0x80, 0xBF, 0x60, 0x4A, + 0xBD, 0xD3, 0x01, 0x16, 0xFE, 0x01, 0x90, 0x8A, 0xBD, 0xD3, 0x01, 0x16, 0xFE, 0x01, 0x90, 0x8A, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0xCD, 0x81, 0x95, 0x60, 0x84, 0xE7, 0xEB, 0x02, 0x2D, 0x58, + 0xFF, 0xFF, 0xD5, 0x60, 0x84, 0xE7, 0x62, 0x4A, 0x02, 0x64, 0x01, 0x16, 0xFE, 0x01, 0xCC, 0x84, + 0xFF, 0xFF, 0xFD, 0x02, 0x7C, 0x49, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x68, 0x5C, 0x7C, 0x49, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x68, 0x44, 0x95, 0x60, 0x84, 0xE7, 0x2D, 0x58, 0xFF, 0xFF, + 0x40, 0xFF, 0x20, 0x44, 0xBF, 0xB4, 0x40, 0x40, 0x03, 0x00, 0x20, 0x44, 0x40, 0xBC, 0x40, 0x40, + 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x02, 0x00, 0x43, 0x45, 0xF6, 0x01, 0x00, 0x64, + 0x19, 0x60, 0xF2, 0xFB, 0x3F, 0x44, 0x40, 0x26, 0x05, 0x00, 0x1C, 0x60, 0x0F, 0xF3, 0x5A, 0xD1, + 0xA0, 0x50, 0xA4, 0x50, 0xAE, 0x4F, 0xFD, 0xB4, 0x04, 0xBC, 0xA0, 0x5E, 0x00, 0x60, 0x02, 0x71, + 0x8D, 0xE2, 0x40, 0xE1, 0x40, 0x29, 0xFE, 0x01, 0x04, 0xAC, 0xA0, 0x5E, 0xFF, 0xFF, 0x00, 0x60, + 0x10, 0x62, 0x19, 0x60, 0x8E, 0x7C, 0x00, 0x60, 0xAC, 0x65, 0x3D, 0x60, 0x58, 0x4D, 0x0F, 0x78, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x62, 0x3D, 0x60, 0x58, 0x4D, 0x3B, 0x78, 0xFF, 0xFF, + 0x60, 0x40, 0x19, 0x60, 0x8E, 0x64, 0x64, 0x40, 0xD0, 0x80, 0x14, 0x71, 0x05, 0x03, 0x8D, 0xE2, + 0x40, 0xE1, 0x40, 0x29, 0xFE, 0x01, 0xE2, 0x01, 0x3F, 0x44, 0x40, 0x26, 0x05, 0x00, 0x1C, 0x60, + 0x0D, 0xF3, 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x52, 0x27, 0x60, 0x36, 0x63, 0x1E, 0x61, 0x3D, 0x60, + 0x58, 0x4D, 0x23, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x14, 0x71, 0x8D, 0xE2, 0x40, 0xE1, 0x40, 0x29, + 0xFE, 0x01, 0x31, 0x44, 0x40, 0x26, 0x02, 0x00, 0x80, 0x26, 0x17, 0x00, 0x28, 0x60, 0xE6, 0x63, + 0x07, 0x60, 0xE8, 0xFD, 0x09, 0x61, 0x3D, 0x60, 0x58, 0x4D, 0x23, 0x78, 0xFF, 0xFF, 0x31, 0x44, + 0x40, 0x2A, 0x14, 0x00, 0x31, 0x44, 0x7F, 0xB4, 0x40, 0x51, 0xAE, 0x4C, 0x10, 0x26, 0x0E, 0x00, + 0x07, 0x60, 0xE9, 0xFB, 0x31, 0x44, 0x80, 0xBC, 0x40, 0x51, 0x29, 0x60, 0x1C, 0x63, 0x07, 0x60, + 0xE8, 0xFD, 0x09, 0x61, 0x3D, 0x60, 0x58, 0x4D, 0x23, 0x78, 0xFF, 0xFF, 0x27, 0x60, 0xEA, 0x63, + 0x03, 0x61, 0x3D, 0x60, 0x58, 0x4D, 0x23, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x62, 0x19, 0x60, + 0x8F, 0x7C, 0x00, 0x60, 0xAC, 0x65, 0x3D, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0x80, 0xE1, + 0xBF, 0xFE, 0xA1, 0x4F, 0x70, 0xB4, 0x50, 0x36, 0x0C, 0x00, 0x20, 0x36, 0x03, 0x00, 0x3A, 0x60, + 0x77, 0x78, 0xFF, 0xFF, 0x01, 0x60, 0x1A, 0xE1, 0xDF, 0xFE, 0x19, 0xFF, 0x00, 0xE1, 0xA1, 0xFF, + 0xFF, 0xFF, 0x20, 0x44, 0x40, 0x2A, 0x85, 0x00, 0x7D, 0xF1, 0x3B, 0x00, 0x83, 0x00, 0x19, 0x60, + 0xF2, 0xF3, 0xFF, 0xFF, 0x01, 0x18, 0x59, 0x01, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, + 0x1C, 0x60, 0x0F, 0xF3, 0x3F, 0x40, 0x40, 0x26, 0x01, 0x00, 0xA0, 0x50, 0xAE, 0x4F, 0xFD, 0xB4, + 0xA0, 0x5E, 0xAC, 0x4F, 0x10, 0xBC, 0xA0, 0x5C, 0xFF, 0xFF, 0x10, 0xAC, 0xA0, 0x5C, 0x00, 0x60, + 0xC8, 0x71, 0x8D, 0xE2, 0x40, 0xE1, 0x40, 0x29, 0xFE, 0x01, 0x7D, 0xF1, 0x30, 0x61, 0x64, 0x44, + 0x01, 0x2B, 0x20, 0xA1, 0x30, 0x64, 0x61, 0x5F, 0x60, 0x45, 0x0C, 0x60, 0x00, 0x62, 0x00, 0x60, + 0x71, 0x7C, 0x3D, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0xC8, 0x71, 0x8D, 0xE2, + 0x40, 0xE1, 0x40, 0x29, 0xFE, 0x01, 0x01, 0x60, 0x08, 0xE1, 0x7D, 0xF1, 0x20, 0x44, 0x40, 0xBC, + 0x40, 0x40, 0x19, 0x60, 0xF2, 0xF3, 0xFF, 0xFF, 0x03, 0x18, 0x3D, 0x60, 0x57, 0x78, 0xFF, 0xFF, + 0x1B, 0x60, 0xF3, 0xF1, 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x7D, 0xF1, 0x02, 0xB1, + 0x04, 0x65, 0x02, 0x02, 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x20, 0x44, + 0x40, 0x2A, 0x43, 0x45, 0x20, 0xBC, 0x40, 0x40, 0xA1, 0xF9, 0x05, 0x64, 0xA2, 0xFB, 0xDF, 0xFE, + 0x19, 0xFF, 0xDD, 0xFE, 0x26, 0x00, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x43, 0x45, 0xA4, 0xD1, + 0xDA, 0x83, 0xC3, 0x85, 0x80, 0xE1, 0xDF, 0xFE, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x48, 0x60, 0x47, + 0x80, 0xBC, 0x00, 0x7F, 0x60, 0x4A, 0xD7, 0x80, 0xA1, 0xFF, 0xF6, 0x02, 0xBF, 0xFE, 0x11, 0x00, + 0x43, 0x45, 0xA4, 0xD1, 0xDA, 0x83, 0x0D, 0x18, 0x64, 0x44, 0x00, 0x61, 0xFA, 0xA4, 0xDD, 0x81, + 0xFD, 0x02, 0x3D, 0x60, 0x58, 0x4D, 0x23, 0x78, 0xFF, 0xFF, 0xBF, 0xFE, 0x02, 0x00, 0xF1, 0xFE, + 0x01, 0x00, 0x25, 0x43, 0x21, 0xE1, 0x00, 0x64, 0xBF, 0xDB, 0x20, 0x44, 0x20, 0x2A, 0x07, 0x00, + 0x07, 0xB4, 0x04, 0x36, 0xC3, 0xFE, 0x06, 0x36, 0xCC, 0xFE, 0x07, 0x36, 0xD5, 0xFE, 0x20, 0x44, + 0x98, 0xB4, 0x40, 0x40, 0x26, 0x60, 0x26, 0x63, 0xBD, 0xD3, 0x03, 0x61, 0x0F, 0x1B, 0x04, 0xA3, + 0xBD, 0xD3, 0x04, 0x61, 0x0B, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x06, 0x61, 0x07, 0x1B, 0x04, 0xA3, + 0xBD, 0xD3, 0x07, 0x61, 0x03, 0x1B, 0xC3, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0xA3, 0xD1, 0x40, 0x44, + 0x20, 0x44, 0x07, 0xB5, 0xD4, 0x85, 0x35, 0x80, 0x24, 0x45, 0x26, 0x60, 0x66, 0x64, 0x44, 0xD7, + 0xFF, 0xFF, 0xFF, 0xFF, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x64, 0x43, 0xBD, 0xD3, + 0xBD, 0xD1, 0x40, 0x44, 0x10, 0x27, 0x19, 0x00, 0x3F, 0x40, 0x02, 0x2B, 0x06, 0x00, 0x24, 0x47, + 0x08, 0x2B, 0x13, 0x00, 0x07, 0xB4, 0x01, 0x36, 0x11, 0x00, 0xFF, 0x60, 0x7F, 0x65, 0x15, 0x60, + 0xA2, 0x64, 0x24, 0x40, 0x08, 0x2B, 0xA4, 0x84, 0xA0, 0x57, 0xFF, 0xFF, 0x64, 0x49, 0xFF, 0xFF, + 0x68, 0x44, 0x01, 0x16, 0xFD, 0x01, 0x00, 0x7F, 0xA3, 0xDB, 0xAB, 0x01, 0x64, 0x42, 0x3D, 0x60, + 0x58, 0x4D, 0x3B, 0x78, 0xFF, 0xFF, 0xBD, 0xD9, 0xA3, 0xDB, 0xA3, 0x01, 0x43, 0x45, 0x20, 0x44, + 0x20, 0xBC, 0x40, 0x40, 0x64, 0x43, 0xBD, 0xD3, 0xA3, 0xD1, 0x40, 0x44, 0x10, 0x2B, 0x16, 0x00, + 0xBE, 0xD1, 0xFF, 0xFF, 0x15, 0x60, 0x80, 0xE7, 0x24, 0x40, 0x07, 0x27, 0x04, 0x00, 0xAC, 0x4F, + 0x10, 0xBC, 0x00, 0x7F, 0xA0, 0x5C, 0x64, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x24, 0x40, + 0x20, 0x27, 0x1D, 0x00, 0xAC, 0x4F, 0xEF, 0xB4, 0xA0, 0x5C, 0x19, 0x00, 0x3F, 0x40, 0x02, 0x2B, + 0x06, 0x00, 0x24, 0x47, 0x08, 0x2B, 0x13, 0x00, 0x07, 0xB4, 0x01, 0x36, 0x11, 0x00, 0x15, 0x60, + 0x22, 0x64, 0x24, 0x40, 0x08, 0x27, 0x80, 0xBC, 0x7C, 0x48, 0xBE, 0xD3, 0xA0, 0x57, 0x60, 0x48, + 0x64, 0x44, 0x80, 0xBC, 0xFF, 0xB4, 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x69, 0x01, + 0x01, 0x61, 0x3D, 0x60, 0x58, 0x4D, 0x23, 0x78, 0xFF, 0xFF, 0x63, 0x01, 0x30, 0x44, 0x02, 0xA8, + 0x00, 0xE1, 0x07, 0x02, 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, 0x66, 0xFF, 0xBF, 0xFE, + 0xA1, 0xFF, 0x82, 0xFF, 0x88, 0xFF, 0x6C, 0x40, 0x41, 0xFF, 0xC4, 0xE2, 0x43, 0xFF, 0x5C, 0x49, + 0x08, 0xE1, 0xA2, 0x60, 0x41, 0x78, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x02, 0x02, + 0xA1, 0xFF, 0xFF, 0xFF, 0x82, 0xFF, 0x88, 0xFF, 0xA8, 0xE2, 0xCB, 0xF1, 0x00, 0x6B, 0x89, 0xFF, + 0x64, 0x54, 0x88, 0xFF, 0x9F, 0xFE, 0x02, 0x05, 0x64, 0x44, 0x60, 0x54, 0xCD, 0xE2, 0xC2, 0x64, + 0x3A, 0xDB, 0xBC, 0xFF, 0xB5, 0xFF, 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xB4, 0x40, 0x46, 0x3C, 0x44, + 0x00, 0xBC, 0xFF, 0xFF, 0x06, 0x03, 0x27, 0x40, 0x26, 0x22, 0x03, 0x00, 0x02, 0x64, 0x31, 0xFB, + 0xC0, 0xFE, 0x27, 0x44, 0x20, 0x2A, 0x04, 0x00, 0xA0, 0x60, 0x00, 0xEA, 0xB0, 0x60, 0x00, 0xEA, + 0x5C, 0x44, 0x27, 0x44, 0x18, 0xB4, 0x40, 0x47, 0x00, 0xE1, 0x29, 0x40, 0x50, 0x2B, 0x37, 0x00, + 0xEF, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x31, 0x40, 0x08, 0x26, 0x0B, 0x00, 0x21, 0x46, + 0xA7, 0xF4, 0x1D, 0xF2, 0xFF, 0xB3, 0x00, 0x7C, 0x05, 0x03, 0x06, 0x61, 0x5D, 0x91, 0x09, 0x60, + 0x02, 0x65, 0x02, 0x03, 0x00, 0x61, 0x15, 0x00, 0xD4, 0x80, 0x63, 0x45, 0xFB, 0x07, 0x65, 0x43, + 0x80, 0x60, 0x00, 0x62, 0xF6, 0x82, 0x53, 0x90, 0xE3, 0x83, 0xFC, 0x04, 0xEB, 0x83, 0xEB, 0x83, + 0xEA, 0x82, 0x5C, 0x94, 0xB2, 0x9C, 0xF3, 0x07, 0x64, 0x41, 0xDD, 0x81, 0xE1, 0x81, 0xE1, 0x81, + 0xE1, 0x81, 0x2B, 0x44, 0x54, 0x90, 0x70, 0x45, 0x02, 0x28, 0x61, 0x44, 0xC4, 0x84, 0xFF, 0xFF, + 0x04, 0x24, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, 0x20, 0x29, 0x6D, 0xE2, 0xA4, 0xE2, + 0xC4, 0xE2, 0x47, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0x32, 0xF1, 0x08, 0x29, 0x09, 0x00, + 0x64, 0x40, 0x07, 0x22, 0x06, 0x00, 0x43, 0xFF, 0x27, 0x44, 0x10, 0xBC, 0x40, 0x47, 0x00, 0x64, + 0x32, 0xFB, 0x31, 0x41, 0x3C, 0x44, 0x01, 0xB1, 0x00, 0xBC, 0x0A, 0x02, 0x09, 0x03, 0x32, 0xF3, + 0x00, 0x7C, 0x01, 0xB4, 0xFF, 0xFF, 0x04, 0x03, 0x32, 0xF9, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, + 0xC8, 0x60, 0x09, 0x7D, 0x00, 0x60, 0x00, 0x6B, 0x00, 0x64, 0x33, 0xFB, 0x0C, 0x60, 0x16, 0x64, + 0xA0, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xE1, 0x30, 0x40, 0x02, 0x36, 0xA1, 0xFF, 0x83, 0xFF, + 0x8D, 0xFF, 0x5C, 0x44, 0x5C, 0x43, 0x5C, 0x42, 0x5C, 0x41, 0x5C, 0x40, 0xAC, 0xFF, 0xAD, 0xFF, + 0xE7, 0xE1, 0xB3, 0x60, 0xFC, 0x78, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x03, 0x02, + 0x28, 0xE2, 0x40, 0xFF, 0xA1, 0xFF, 0x84, 0xFF, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0xB7, 0x60, + 0xF7, 0x64, 0x40, 0x40, 0xBA, 0xF3, 0x7E, 0xFB, 0x0F, 0x60, 0xE2, 0x63, 0xC7, 0xF3, 0xBD, 0xDB, + 0x00, 0x60, 0x9A, 0x64, 0xBD, 0xDB, 0x02, 0x64, 0xBD, 0xDB, 0x04, 0x64, 0xA3, 0xDB, 0x5C, 0x49, + 0x0A, 0x64, 0x40, 0x4B, 0x5C, 0x5C, 0x01, 0x60, 0x39, 0xE2, 0x04, 0x60, 0x00, 0x7A, 0x89, 0xFF, + 0x03, 0x60, 0xFF, 0x73, 0x88, 0xFF, 0xB7, 0x60, 0xF7, 0x78, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, + 0x00, 0xE1, 0x06, 0x02, 0x40, 0xFF, 0x42, 0xFF, 0x43, 0xFF, 0x44, 0xFF, 0x45, 0xFF, 0xA1, 0xFF, + 0x88, 0xFF, 0x85, 0xFF, 0x21, 0xE1, 0x5C, 0x40, 0xC3, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, + 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x01, 0x02, 0xA1, 0xFF, 0x86, 0xFF, 0x88, 0xFF, 0x5C, 0x46, + 0x5C, 0x49, 0x5C, 0x40, 0xEF, 0x60, 0x58, 0x4F, 0x1B, 0x78, 0xFF, 0xFF, 0x1D, 0x60, 0x58, 0x4F, + 0x81, 0x78, 0xFF, 0xFF, 0xD3, 0x60, 0x58, 0x4F, 0x58, 0x78, 0xFF, 0xFF, 0xE7, 0x60, 0x58, 0x4F, + 0x99, 0x78, 0xFF, 0xFF, 0x20, 0x60, 0x58, 0x4F, 0x19, 0x78, 0xFF, 0xFF, 0xF4, 0x60, 0x58, 0x4F, + 0xE9, 0x78, 0xFF, 0xFF, 0xE9, 0x60, 0x58, 0x4F, 0xCA, 0x78, 0xFF, 0xFF, 0x27, 0x60, 0x58, 0x4F, + 0x71, 0x78, 0xFF, 0xFF, 0xEE, 0x60, 0x58, 0x4F, 0x69, 0x78, 0xFF, 0xFF, 0x1F, 0xE1, 0xA3, 0xFF, + 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0x03, 0xE1, 0xA3, 0xFF, 0xFE, 0xFC, 0xFF, 0xFC, 0x25, 0x60, + 0x96, 0x63, 0x17, 0xFD, 0xAE, 0xFF, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x42, 0x6F, 0x6F, 0x74, + 0x63, 0x6F, 0x64, 0x65, 0x20, 0x21, 0x21, 0x20, 0x20, 0x00, 0x53, 0x54, 0x41, 0x2F, 0x41, 0x50, + 0x20, 0x46, 0x75, 0x6E, 0x63, 0x27, 0x73, 0x00, 0x1F, 0x00, 0x04, 0x00, 0x01, 0x00, 0x24, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x07, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x07, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0xA6, 0xF3, 0x21, 0x61, 0x00, 0x7C, 0x01, 0x00, 0x00, 0xFA, + 0x60, 0x46, 0xFE, 0x63, 0xA3, 0xD8, 0xFE, 0x1F, 0xCD, 0x81, 0xD8, 0x84, 0xF8, 0x02, 0x21, 0x61, + 0x80, 0x67, 0x40, 0x4A, 0xA6, 0xF5, 0x05, 0x18, 0x2A, 0x43, 0x02, 0xFC, 0x5F, 0x8A, 0x00, 0xF4, + 0xFA, 0x01, 0x2E, 0x58, 0xFF, 0xFF, 0xA8, 0xF1, 0xA7, 0xF3, 0x7C, 0x63, 0xAA, 0xFB, 0x60, 0x46, + 0x01, 0xFC, 0xDC, 0x84, 0xD0, 0x80, 0x00, 0xFA, 0xFA, 0x04, 0xAB, 0xFB, 0x60, 0x46, 0x00, 0x64, + 0x00, 0xFA, 0x63, 0x44, 0x80, 0x7F, 0x01, 0xFA, 0xA8, 0xF3, 0xA7, 0xF1, 0xDC, 0x84, 0xD0, 0x84, + 0xA9, 0xFB, 0x03, 0x60, 0x26, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0x66, 0x44, + 0x2E, 0xFB, 0x82, 0xFF, 0x40, 0x42, 0x87, 0xFF, 0xA9, 0xF3, 0xB1, 0xFB, 0x00, 0x64, 0x40, 0x50, + 0x63, 0xFF, 0x60, 0xFF, 0x66, 0xFF, 0x65, 0xFF, 0x64, 0xFF, 0x61, 0xFF, 0x62, 0xFF, 0x49, 0x60, + 0x02, 0xE1, 0x52, 0x60, 0x02, 0xE1, 0x5C, 0x60, 0x02, 0xE1, 0x65, 0x60, 0x02, 0xE1, 0x6B, 0x60, + 0x02, 0xE1, 0x76, 0x60, 0x02, 0xE1, 0x41, 0x60, 0x02, 0xE1, 0x0C, 0x64, 0x13, 0x60, 0x1C, 0xFB, + 0x41, 0x60, 0x07, 0x64, 0x9F, 0xFB, 0x2D, 0xFF, 0x06, 0x61, 0x41, 0x4B, 0x09, 0x60, 0x08, 0x61, + 0xB6, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0xF0, 0x67, 0x0E, 0xFA, 0x26, 0x60, 0x04, 0x64, + 0x13, 0x60, 0x10, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0x2B, 0x41, 0x4D, 0x8B, 0xFF, 0xFF, 0xEA, 0x02, 0x05, 0x61, 0x41, 0x4B, 0x09, 0x60, 0x08, 0x61, + 0xB6, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0x25, 0x60, 0xF8, 0x64, 0x13, 0x60, 0x10, 0xFB, + 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x2B, 0x41, 0x4D, 0x8B, + 0xFF, 0xFF, 0xEC, 0x02, 0x40, 0x60, 0x45, 0x78, 0xFF, 0xFF, 0x00, 0xEA, 0x00, 0xEB, 0x50, 0x60, + 0x03, 0xEA, 0x51, 0x60, 0x13, 0xEA, 0x52, 0x60, 0x30, 0xEA, 0x53, 0x60, 0x40, 0xEA, 0x54, 0x60, + 0x52, 0xEA, 0x55, 0x60, 0x6D, 0xEA, 0x56, 0x60, 0x71, 0xEA, 0x57, 0x60, 0x8B, 0xEA, 0x58, 0x60, + 0x47, 0xEA, 0x59, 0x60, 0xA0, 0xEA, 0x5A, 0x60, 0xB2, 0xEA, 0x5B, 0x60, 0xC1, 0xEA, 0x5C, 0x60, + 0xD7, 0xEA, 0x5D, 0x60, 0xEB, 0xEA, 0x5E, 0x60, 0xA0, 0xEA, 0x50, 0x60, 0x36, 0xEB, 0x51, 0x60, + 0x37, 0xEB, 0x52, 0x60, 0x20, 0xEB, 0x53, 0x60, 0xE4, 0xEB, 0x54, 0x60, 0x34, 0xEB, 0x55, 0x60, + 0x58, 0xEB, 0x56, 0x60, 0x48, 0xEB, 0x57, 0x60, 0xD0, 0xEB, 0x58, 0x60, 0xC3, 0xEB, 0x59, 0x60, + 0xFC, 0xEB, 0x5A, 0x60, 0x34, 0xEB, 0x5B, 0x60, 0x58, 0xEB, 0x5C, 0x60, 0xC0, 0xEB, 0x5D, 0x60, + 0xD0, 0xEB, 0x5E, 0x60, 0x91, 0xEB, 0x00, 0xEA, 0x00, 0xEB, 0xE0, 0x60, 0x02, 0xEA, 0xE0, 0x60, + 0x03, 0xEB, 0xA0, 0x60, 0x00, 0xEB, 0xB0, 0x60, 0x00, 0xEB, 0xAB, 0x48, 0x40, 0x3B, 0x01, 0x00, + 0xFC, 0x01, 0x00, 0xEB, 0x03, 0x60, 0x02, 0x64, 0xA0, 0xDB, 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, + 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x24, 0x44, 0xFF, 0xB4, + 0x04, 0xFB, 0x50, 0x60, 0x00, 0x64, 0x05, 0xFB, 0x10, 0x60, 0x10, 0x75, 0x2A, 0x60, 0x1D, 0x78, + 0xFF, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x40, 0x00, 0x05, 0x60, 0xF9, 0xF1, 0x42, 0x60, 0x08, 0x64, + 0x09, 0x60, 0x19, 0x63, 0x64, 0x40, 0x01, 0x2B, 0x04, 0x00, 0x42, 0x60, 0x09, 0x64, 0x0A, 0x60, + 0x19, 0x63, 0x1C, 0x60, 0x0F, 0xFB, 0x04, 0x60, 0x00, 0xBC, 0x1C, 0x60, 0x0B, 0xFB, 0x1C, 0x60, + 0x0A, 0xFD, 0x1D, 0x60, 0x19, 0x63, 0x1C, 0x60, 0x0E, 0xFD, 0x80, 0x60, 0x1C, 0x64, 0x3F, 0x40, + 0x01, 0x2A, 0x02, 0x00, 0x60, 0x60, 0x1C, 0x64, 0x1C, 0x60, 0x10, 0xFB, 0x1C, 0x60, 0x0C, 0xFB, + 0x1C, 0x60, 0x0F, 0xF3, 0xA0, 0x50, 0xA0, 0x50, 0x0B, 0x60, 0xF8, 0x63, 0xA3, 0xD1, 0x38, 0x60, + 0x12, 0x61, 0xA1, 0xD3, 0xF8, 0xA3, 0x90, 0x84, 0xA2, 0xDB, 0xA3, 0xD1, 0x59, 0xD3, 0x06, 0xA3, + 0x90, 0x84, 0xA2, 0xDB, 0xA3, 0xD1, 0x59, 0xD3, 0xFE, 0xA3, 0x90, 0x84, 0xA2, 0xDB, 0xA3, 0xD1, + 0x59, 0xD3, 0xFF, 0xFF, 0x90, 0x84, 0xA2, 0xDB, 0x80, 0x60, 0x58, 0xEC, 0x80, 0x60, 0x00, 0xED, + 0x80, 0x60, 0x80, 0xEE, 0x40, 0xEC, 0x00, 0xED, 0x00, 0xEE, 0xC0, 0x60, 0x59, 0xEC, 0xC0, 0x60, + 0x07, 0xED, 0xC0, 0x60, 0x8F, 0xEE, 0xAD, 0x4F, 0xFA, 0xB4, 0xA0, 0x5D, 0x00, 0xF3, 0x28, 0xFB, + 0x40, 0x44, 0x37, 0x60, 0x7B, 0x7C, 0x20, 0xF9, 0x3F, 0x60, 0x18, 0x7C, 0x21, 0xF9, 0x3F, 0x60, + 0x2E, 0x7C, 0x22, 0xF9, 0x3F, 0x60, 0xC5, 0x7C, 0x23, 0xF9, 0x3F, 0x60, 0xD6, 0x7C, 0x24, 0xF9, + 0x40, 0x60, 0x00, 0x7C, 0x25, 0xF9, 0x40, 0x60, 0x11, 0x7C, 0x26, 0xF9, 0xD0, 0x60, 0x00, 0xE8, + 0x28, 0xE8, 0x44, 0x60, 0x01, 0xE6, 0x10, 0x67, 0x40, 0x52, 0x10, 0x60, 0x04, 0xE6, 0x08, 0x60, + 0x06, 0x63, 0xFD, 0x60, 0x0C, 0x65, 0x5B, 0xD3, 0xBF, 0xD1, 0x10, 0x18, 0xC3, 0x83, 0xD4, 0x80, + 0xC3, 0x83, 0xF9, 0x02, 0xFA, 0xA3, 0xA3, 0xD3, 0x02, 0x60, 0x00, 0x65, 0xF9, 0xA0, 0xFC, 0xA0, + 0x0D, 0x05, 0x04, 0x05, 0x78, 0x43, 0x02, 0x61, 0x29, 0x60, 0xEA, 0x78, 0x21, 0x60, 0x00, 0x65, + 0x3F, 0x43, 0x21, 0x60, 0x00, 0x65, 0xC0, 0x60, 0x8F, 0xEE, 0x08, 0x00, 0x02, 0x60, 0x00, 0x65, + 0x00, 0x60, 0x00, 0x64, 0x18, 0xFB, 0x3F, 0x43, 0x11, 0x60, 0x10, 0xE6, 0xB7, 0x84, 0x40, 0x5F, + 0x37, 0x60, 0xF8, 0x63, 0x3F, 0x40, 0x20, 0x27, 0x06, 0x00, 0x0F, 0x60, 0xFF, 0x64, 0xBD, 0xDB, + 0x0F, 0x60, 0xF0, 0x64, 0x03, 0x00, 0x0F, 0x64, 0xBD, 0xDB, 0x00, 0x64, 0xA3, 0xDB, 0x00, 0x60, + 0x30, 0xE2, 0x00, 0x60, 0x50, 0xE2, 0x00, 0x60, 0x79, 0xE2, 0x00, 0x60, 0x90, 0xE2, 0x01, 0x60, + 0xD0, 0xE2, 0x01, 0x60, 0xF0, 0xE2, 0x01, 0x60, 0xB0, 0xE2, 0x13, 0x64, 0xCB, 0xFB, 0x01, 0x60, + 0x67, 0x64, 0x37, 0xFB, 0x00, 0x60, 0x28, 0x64, 0x36, 0xFB, 0x09, 0x60, 0x2A, 0x64, 0xB6, 0xFB, + 0x82, 0xFF, 0x92, 0xFF, 0x5C, 0x41, 0x5C, 0x46, 0x5C, 0x47, 0x00, 0xE1, 0xA3, 0x60, 0xF4, 0x63, + 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x87, 0xFF, 0x97, 0xFF, 0x0C, 0x60, 0x02, 0x64, 0x40, 0x5A, + 0x06, 0xA4, 0x40, 0x5B, 0x5C, 0x5E, 0x16, 0x60, 0xCF, 0xF3, 0x7D, 0xFB, 0x3F, 0x40, 0x01, 0x22, + 0x03, 0x00, 0x80, 0x60, 0x37, 0x7C, 0x02, 0x00, 0x80, 0x60, 0x27, 0x7C, 0x1A, 0x60, 0x1F, 0xF9, + 0x01, 0x60, 0x06, 0x64, 0xA7, 0xFB, 0x02, 0x60, 0x7F, 0x64, 0x00, 0x60, 0x42, 0x65, 0xD4, 0x84, + 0xA8, 0xFB, 0xDC, 0x84, 0xA6, 0xFB, 0x12, 0x60, 0xD8, 0xFB, 0x40, 0x60, 0x58, 0x4E, 0x7D, 0x78, + 0xFF, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x05, 0x00, 0x1C, 0x60, 0x0D, 0xF3, 0x5A, 0xD1, 0xA0, 0x50, + 0xA4, 0x52, 0x08, 0x60, 0x00, 0x63, 0xFA, 0x60, 0x00, 0x65, 0xBD, 0xD3, 0xA3, 0xD3, 0x02, 0xA8, + 0xD4, 0x80, 0x21, 0x02, 0x20, 0x02, 0x19, 0x60, 0x48, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x80, 0x26, + 0x1A, 0x00, 0x04, 0xA3, 0xFD, 0x60, 0x0D, 0x65, 0x5B, 0xD3, 0xBF, 0xD1, 0x14, 0x18, 0xC3, 0x83, + 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xBF, 0xD3, 0xAD, 0x49, 0xFE, 0xA0, 0x00, 0x64, 0x0C, 0x04, + 0x08, 0xB1, 0x20, 0xBC, 0x08, 0x28, 0x18, 0xBC, 0x07, 0x7C, 0x0E, 0x60, 0xDF, 0xF9, 0x05, 0x7C, + 0x0E, 0x60, 0xDE, 0xF9, 0x01, 0x00, 0x00, 0x64, 0x0E, 0x60, 0xDD, 0xFB, 0x40, 0x60, 0x95, 0x78, + 0xFF, 0xFF, 0x5C, 0x51, 0x3F, 0x41, 0xA5, 0x4C, 0x50, 0x37, 0x0B, 0x00, 0x01, 0xB9, 0x41, 0x5F, + 0xB5, 0x60, 0x55, 0xE0, 0x05, 0x60, 0xF9, 0xF1, 0xC0, 0x67, 0x90, 0x84, 0x3F, 0x40, 0x01, 0x26, + 0xA0, 0x50, 0x06, 0x60, 0x08, 0xF3, 0x01, 0x60, 0x01, 0x65, 0x01, 0x60, 0x02, 0x7C, 0xD4, 0x80, + 0xD0, 0x80, 0x01, 0x03, 0x10, 0x02, 0x5A, 0xD1, 0x5A, 0xD3, 0x3C, 0x60, 0x00, 0x66, 0xE0, 0x87, + 0x40, 0x4A, 0x80, 0x60, 0x9E, 0x61, 0x64, 0x44, 0xC8, 0x84, 0x0C, 0x63, 0xAA, 0x46, 0x58, 0xD0, + 0xAA, 0x46, 0x59, 0xD8, 0xFB, 0x1F, 0x08, 0x60, 0x00, 0x63, 0xFA, 0x60, 0x00, 0x65, 0xBD, 0xD3, + 0xA3, 0xD3, 0x02, 0xA8, 0xD4, 0x80, 0x07, 0x02, 0x06, 0x02, 0x8C, 0x60, 0xBA, 0x61, 0x3C, 0x60, + 0x00, 0x66, 0x41, 0x4B, 0x03, 0x00, 0x46, 0x60, 0x3B, 0x78, 0xFF, 0xFF, 0x2B, 0x41, 0x8D, 0x60, + 0x02, 0x7C, 0xD1, 0x80, 0xA1, 0xD2, 0x25, 0x05, 0x59, 0xD0, 0x60, 0x45, 0x59, 0xD2, 0x44, 0x47, + 0xE0, 0x87, 0x40, 0x4A, 0x59, 0xD2, 0x59, 0x8B, 0x40, 0x4C, 0x08, 0x60, 0x00, 0x63, 0xBE, 0xD3, + 0xBD, 0xD1, 0xEC, 0x18, 0xD4, 0x80, 0xEA, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, + 0x67, 0x44, 0xC0, 0x84, 0xE0, 0x85, 0x2C, 0x44, 0xD4, 0x80, 0x63, 0x41, 0x01, 0x06, 0x65, 0x44, + 0xC8, 0x83, 0xAA, 0x46, 0x59, 0xD1, 0x27, 0xD8, 0x5A, 0x87, 0xFC, 0x1F, 0xAA, 0x46, 0x2B, 0x41, + 0xD5, 0x01, 0x8D, 0x60, 0x02, 0x61, 0x41, 0x4B, 0x2B, 0x41, 0x8D, 0x60, 0x02, 0x7C, 0xD1, 0x80, + 0xA1, 0xD2, 0x27, 0x05, 0x59, 0xD0, 0x60, 0x45, 0x59, 0xD2, 0x44, 0x47, 0xE0, 0x87, 0x40, 0x4A, + 0x59, 0xD2, 0x59, 0x8B, 0x40, 0x4C, 0x08, 0x60, 0x00, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, 0xEC, 0x18, + 0xD4, 0x80, 0xEA, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x04, 0xA3, 0xA3, 0xD1, + 0x5A, 0x88, 0x2C, 0x43, 0xD3, 0x80, 0xFF, 0xFF, 0x01, 0x06, 0x64, 0x43, 0xCF, 0x83, 0xAA, 0x46, + 0x60, 0xFE, 0x28, 0xD1, 0x5E, 0x88, 0x27, 0xD8, 0x5A, 0x87, 0xFB, 0x1F, 0x20, 0xFE, 0xAA, 0x46, + 0xD3, 0x01, 0x07, 0x60, 0xEC, 0xF3, 0x20, 0x60, 0x00, 0x7C, 0x08, 0xB0, 0x10, 0xB0, 0x05, 0x02, + 0x04, 0x03, 0x07, 0x60, 0xEB, 0xF9, 0x07, 0x60, 0xEA, 0xF9, 0x02, 0xB0, 0x04, 0xB0, 0x0F, 0x02, + 0x13, 0x60, 0xD2, 0xF3, 0x0C, 0x03, 0x02, 0xBC, 0xA2, 0xDB, 0x14, 0x60, 0x65, 0xF3, 0x14, 0x60, + 0x29, 0xF3, 0x02, 0xBD, 0x02, 0xBC, 0xA2, 0xDB, 0x65, 0x44, 0x14, 0x60, 0x65, 0xFB, 0x07, 0x60, + 0xEC, 0xF3, 0x31, 0x41, 0x60, 0x40, 0x20, 0x2A, 0x40, 0xB9, 0x40, 0x26, 0x03, 0x00, 0x60, 0x40, + 0x01, 0x26, 0x80, 0xB9, 0x41, 0x51, 0xFA, 0x60, 0x3A, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, + 0xFF, 0xFF, 0x03, 0x02, 0x44, 0x60, 0xAD, 0x78, 0xFF, 0xFF, 0x5B, 0xD3, 0xF8, 0x60, 0x3F, 0x65, + 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x14, 0x60, 0x74, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, + 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0xBD, 0xD3, 0xFF, 0xFF, + 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x14, 0x60, 0x77, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, + 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x28, 0x60, + 0xF4, 0x61, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0xA1, 0xD3, + 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA1, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0x00, 0x7F, 0xE0, 0x84, + 0xE0, 0x84, 0x59, 0xD3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA1, 0xDB, 0x14, 0x60, 0x7D, 0xF3, + 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, + 0xA2, 0xDB, 0x14, 0x60, 0x80, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, + 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0x83, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, + 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0xA3, 0xD3, + 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x14, 0x60, 0x86, 0xF3, 0xE0, 0x9C, + 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, + 0x14, 0x60, 0x89, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, + 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0x8C, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, + 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x02, 0xA3, 0xA3, 0xD3, + 0xF8, 0x60, 0x3F, 0x65, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x14, 0x60, 0x8F, 0xF3, 0xE0, 0x9C, + 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, + 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x14, 0x60, 0x92, 0xF3, + 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, + 0xA2, 0xDB, 0x29, 0x60, 0x2A, 0x61, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, + 0xE0, 0x84, 0xA1, 0xD3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA1, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, + 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x59, 0xD3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA1, 0xDB, + 0x14, 0x60, 0x98, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, + 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0x9B, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, + 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0x9E, 0xF3, + 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, + 0xA2, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x14, 0x60, + 0xA1, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, + 0xB0, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0xA4, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, + 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0xA7, 0xF3, 0xFF, 0xFF, + 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, + 0x00, 0x60, 0x6A, 0x63, 0x29, 0x60, 0x50, 0x61, 0x28, 0x60, 0xE4, 0x64, 0x58, 0xD1, 0x59, 0xD9, + 0xFD, 0x1F, 0x14, 0x60, 0xB0, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, + 0x18, 0xAC, 0xA2, 0xDB, 0x14, 0x60, 0xB4, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x14, 0x60, + 0xB6, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x14, 0x60, 0xBD, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, + 0xA2, 0xDB, 0x14, 0x60, 0xBF, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x14, 0x60, 0xCB, 0xF3, + 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x14, 0x60, + 0xCF, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x14, 0x60, 0xD1, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, + 0xA2, 0xDB, 0x14, 0x60, 0xD8, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x14, 0x60, 0xDA, 0xF3, + 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0xFA, 0x60, 0x2C, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, + 0xFF, 0xFF, 0x0E, 0x03, 0x63, 0x45, 0x2A, 0x60, 0xEA, 0x63, 0x06, 0x61, 0xA5, 0xD1, 0xDA, 0x85, + 0x64, 0x44, 0x0F, 0xB4, 0xBD, 0xDB, 0x64, 0x47, 0x0F, 0xB4, 0xCD, 0x81, 0xBD, 0xDB, 0xF6, 0x02, + 0xFA, 0x60, 0x30, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x14, 0x03, 0xBD, 0xD3, + 0x63, 0x46, 0x2B, 0x60, 0x82, 0x63, 0x15, 0x60, 0xD0, 0xFB, 0xDA, 0x85, 0xBD, 0xDB, 0x0E, 0x61, + 0xA6, 0xD1, 0xDA, 0x86, 0x64, 0x44, 0xFF, 0xB4, 0xA5, 0xDB, 0xDA, 0x85, 0x64, 0x47, 0xFF, 0xB4, + 0xCD, 0x81, 0xBD, 0xDB, 0xF5, 0x02, 0xFA, 0x60, 0x31, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, + 0xFF, 0xFF, 0x22, 0x03, 0xBD, 0xD3, 0x15, 0x60, 0xEE, 0xFB, 0x5A, 0x81, 0x15, 0x60, 0xFD, 0xFB, + 0x5A, 0x82, 0x16, 0x60, 0x0C, 0xFB, 0x5A, 0x83, 0x16, 0x60, 0x1B, 0xFB, 0x5A, 0x84, 0x0E, 0x61, + 0xBD, 0xD1, 0xBD, 0xD5, 0x64, 0x44, 0xFF, 0xB4, 0x21, 0xDB, 0x5A, 0x81, 0x64, 0x47, 0xFF, 0xB4, + 0x22, 0xDB, 0x5A, 0x82, 0x66, 0x44, 0xFF, 0xB4, 0x23, 0xDB, 0x5A, 0x83, 0x66, 0x47, 0xFF, 0xB4, + 0x24, 0xDB, 0xCD, 0x81, 0x5A, 0x84, 0xEC, 0x02, 0xFA, 0x60, 0x47, 0x65, 0x46, 0x60, 0x58, 0x4D, + 0x4E, 0x78, 0xFF, 0xFF, 0x11, 0x03, 0x63, 0x45, 0x2C, 0x60, 0x54, 0x63, 0xA5, 0xD1, 0xDA, 0x85, + 0xBD, 0xD9, 0x02, 0x61, 0xA5, 0xD1, 0xDA, 0x85, 0x64, 0x47, 0x00, 0x7E, 0xBD, 0xDB, 0x64, 0x44, + 0x00, 0x7E, 0xCD, 0x81, 0xBD, 0xDB, 0xF6, 0x02, 0xFA, 0x60, 0x2E, 0x65, 0x46, 0x60, 0x58, 0x4D, + 0x4E, 0x78, 0xFF, 0xFF, 0x1F, 0x03, 0x63, 0x46, 0xFC, 0xA3, 0xA3, 0xD3, 0x2B, 0x60, 0x02, 0x63, + 0xCC, 0x84, 0xE8, 0x84, 0xCC, 0x81, 0x00, 0x36, 0x0D, 0x00, 0x63, 0x45, 0xA6, 0xD3, 0x5A, 0xD1, + 0xDA, 0x86, 0xFF, 0xB4, 0xE0, 0x84, 0xC4, 0x84, 0x5C, 0x90, 0xBD, 0xD9, 0xFD, 0x02, 0xCD, 0x81, + 0x66, 0x42, 0xF4, 0x02, 0x66, 0x42, 0x5A, 0xD3, 0x2B, 0x60, 0x42, 0x65, 0xBD, 0xDB, 0xD7, 0x80, + 0xFF, 0xFF, 0xFC, 0x02, 0x2C, 0x60, 0x68, 0x61, 0xFA, 0x60, 0x46, 0x65, 0x46, 0x60, 0x58, 0x4D, + 0x4E, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, 0x2F, 0x65, 0x46, 0x60, + 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, 0x3E, 0x65, + 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, + 0x3F, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, + 0xFA, 0x60, 0x40, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, + 0xD9, 0x81, 0xFA, 0x60, 0x3B, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x01, 0x03, + 0xA1, 0xDD, 0xFA, 0x60, 0x48, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x10, 0x03, + 0xBD, 0xD3, 0x2C, 0x60, 0xC4, 0x61, 0x0E, 0xB4, 0xBD, 0xD1, 0xA1, 0xDB, 0x64, 0x47, 0x0E, 0xB4, + 0xA3, 0xD1, 0x59, 0xDB, 0x64, 0x44, 0x0E, 0xB4, 0x59, 0xDB, 0x64, 0x47, 0x0E, 0xB4, 0x59, 0xDB, + 0xFA, 0x60, 0x29, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x07, 0x03, 0x04, 0xA3, + 0xA3, 0xD3, 0x20, 0x60, 0x00, 0x65, 0xB4, 0x84, 0x13, 0x60, 0xA6, 0xFB, 0xFA, 0x60, 0x2A, 0x65, + 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x30, 0x03, 0x04, 0xA3, 0xBD, 0xD1, 0x14, 0x60, + 0x4A, 0xF3, 0x64, 0x41, 0x64, 0x5E, 0xA2, 0xDB, 0x64, 0x47, 0x5A, 0xD3, 0x60, 0x5C, 0x64, 0x5F, + 0xA2, 0xDB, 0x14, 0x60, 0x60, 0xF3, 0xFF, 0x60, 0xC0, 0xB5, 0x61, 0x40, 0x80, 0x27, 0x05, 0x00, + 0xE9, 0x87, 0x3F, 0xB4, 0xB4, 0x84, 0xA2, 0xDB, 0x15, 0x00, 0x65, 0x44, 0xA2, 0xDB, 0xE1, 0x80, + 0xF9, 0x87, 0x01, 0x7F, 0x14, 0x60, 0x63, 0xF3, 0x60, 0x41, 0xE0, 0x84, 0xE0, 0x84, 0xE9, 0x81, + 0xF8, 0x84, 0xE9, 0x81, 0xF8, 0x84, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0x60, 0x80, 0x65, 0xA4, 0x84, + 0x34, 0x94, 0xA2, 0xDB, 0xDB, 0x83, 0x14, 0x60, 0xDF, 0xFD, 0xFA, 0x60, 0x2B, 0x65, 0x46, 0x60, + 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x07, 0x03, 0x04, 0xA3, 0xBD, 0xD3, 0x14, 0x60, 0x4D, 0xFB, + 0xA3, 0xD3, 0x14, 0x60, 0x11, 0xFB, 0xFA, 0x60, 0x3C, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, + 0xFF, 0xFF, 0x1F, 0x03, 0xA3, 0xD3, 0xFC, 0x60, 0xFC, 0x65, 0xA4, 0x84, 0x60, 0x5C, 0x00, 0x7E, + 0xC0, 0x60, 0x00, 0xA0, 0x60, 0x43, 0x07, 0x04, 0x14, 0x60, 0x51, 0xF3, 0xFF, 0xFF, 0x03, 0x60, + 0xFF, 0xB4, 0x3C, 0x94, 0xA2, 0xDB, 0x28, 0x60, 0x2A, 0x61, 0x64, 0x44, 0x00, 0x7F, 0xC0, 0xA0, + 0x60, 0x47, 0x07, 0x04, 0x60, 0x43, 0xA1, 0xD3, 0xFF, 0xFF, 0x03, 0x60, 0xFF, 0xB4, 0x3C, 0x94, + 0xA1, 0xDB, 0xFA, 0x60, 0x49, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x1B, 0x03, + 0x32, 0x60, 0xAB, 0x61, 0x1C, 0x7C, 0x60, 0xFE, 0xA3, 0xD3, 0x5D, 0xD3, 0x0F, 0xB5, 0xD4, 0x84, + 0xA1, 0xDB, 0xBD, 0xD3, 0xFF, 0xFF, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x5D, 0xD3, + 0x0F, 0xB5, 0xD4, 0x84, 0xA1, 0xDB, 0x67, 0x44, 0xC0, 0x9C, 0x64, 0x40, 0x00, 0x36, 0x10, 0x00, + 0x64, 0x40, 0x0E, 0x3A, 0xE9, 0x01, 0x20, 0xFE, 0xFA, 0x60, 0x4A, 0x65, 0x46, 0x60, 0x58, 0x4D, + 0x4E, 0x78, 0xFF, 0xFF, 0x05, 0x03, 0x32, 0x60, 0xC7, 0x61, 0x0E, 0x7C, 0x60, 0xFE, 0xDC, 0x01, + 0x20, 0xFE, 0xB8, 0xFE, 0xB9, 0xFE, 0xBA, 0xFE, 0xBB, 0xFE, 0xBD, 0xFE, 0xBF, 0xFE, 0x19, 0x60, + 0x48, 0xF3, 0x12, 0x63, 0x60, 0x40, 0x01, 0x27, 0x04, 0x00, 0x0B, 0x60, 0xEA, 0x62, 0x5A, 0xDF, + 0xFE, 0x1F, 0x41, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x06, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, + 0x07, 0x18, 0xD4, 0x80, 0x05, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0xDB, 0x83, + 0x00, 0xBC, 0x2D, 0x58, 0xFF, 0xFF, 0x86, 0xFD, 0xAA, 0x2D, 0x00, 0x00, 0x06, 0x00, 0x10, 0xFD, + 0x6E, 0x01, 0x00, 0x00, 0x02, 0x00, 0x14, 0xFD, 0x8E, 0x32, 0x00, 0x00, 0x0A, 0x00, 0x41, 0xFA, + 0x40, 0x2A, 0x00, 0x00, 0x22, 0x00, 0x42, 0xFA, 0x62, 0x2A, 0x00, 0x00, 0x22, 0x00, 0x43, 0xFA, + 0x84, 0x2A, 0x00, 0x00, 0x22, 0x00, 0x44, 0xFA, 0xA6, 0x2A, 0x00, 0x00, 0x22, 0x00, 0x45, 0xFA, + 0xC8, 0x2A, 0x00, 0x00, 0x22, 0x00, 0x25, 0xFD, 0x9E, 0x01, 0x00, 0x00, 0x02, 0x00, + +}; /* fw_image_3_data */ + +static const hcf_8 fw_image_4_data[] = { + 0x6C, 0x40, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x41, 0xFF, 0x33, 0xF3, 0x02, 0x11, 0x31, 0x18, 0x1E, 0x00, 0x44, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, + 0xC4, 0xE2, 0x27, 0x44, 0x20, 0x2A, 0x01, 0x00, 0xFF, 0xFF, 0x42, 0x64, 0x3A, 0xDB, 0x23, 0x00, + 0x41, 0xFF, 0xA2, 0x60, 0x45, 0x78, 0xE2, 0xFE, 0x40, 0x49, 0x02, 0x60, 0x01, 0xE1, 0x1D, 0x00, + 0x44, 0xFF, 0x1B, 0x09, 0x29, 0x44, 0x10, 0x2A, 0x04, 0x74, 0xCD, 0xE2, 0x10, 0x65, 0x0B, 0x00, + 0xA3, 0x60, 0xC1, 0x78, 0xA4, 0xE2, 0x29, 0x44, 0x20, 0x2A, 0x0D, 0x00, 0x20, 0xAC, 0xEC, 0x01, + 0xA3, 0x60, 0xC1, 0x78, 0x46, 0xFF, 0xB4, 0x84, 0x40, 0x49, 0xA1, 0xFF, 0xFF, 0xFF, 0x80, 0x3E, + 0xA3, 0x60, 0xC1, 0x78, 0xFF, 0xFF, 0x62, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, + 0xAA, 0x60, 0xA5, 0x78, 0x4C, 0x4E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAA, 0x60, 0xB3, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC4, 0xE2, 0x84, 0xFF, 0x22, 0x58, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA4, 0x60, 0x39, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0xE1, 0x01, 0xFF, 0xFF, + 0x10, 0x29, 0xFA, 0x01, 0xE4, 0xE2, 0xAA, 0x60, 0x5F, 0x78, 0xB2, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC1, 0x60, 0xFC, 0x78, 0x64, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAA, 0x60, 0x46, 0x78, 0xAC, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x80, 0x29, 0xE2, 0x01, 0xAA, 0x60, 0xA2, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB5, 0x60, 0x5C, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB5, 0x60, 0x94, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB3, 0x60, 0xC9, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB3, 0x60, 0xFC, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB3, 0x60, 0xFC, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB7, 0x60, 0x20, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB3, 0x60, 0xFF, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x60, 0x83, 0x64, 0x80, 0x29, 0x09, 0xFB, 0xB5, 0x60, 0x25, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, + 0x98, 0xFF, 0x3A, 0x60, 0x18, 0x78, 0x40, 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, + 0x39, 0x60, 0x8F, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC0, 0x60, 0x67, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBF, 0x60, 0xE1, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xB7, 0x60, 0xE9, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA1, 0xFF, 0x98, 0xFF, 0x83, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC3, 0x60, 0x4D, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xB0, 0xFF, 0xB1, 0xFF, 0x40, 0xFF, 0x43, 0xFF, 0xC3, 0x60, 0x48, 0x78, 0x44, 0xFF, 0xFF, 0x01, + 0xC3, 0x60, 0x4D, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0x3E, 0x60, 0x8C, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xC3, 0x60, 0x48, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xC3, 0x60, 0x47, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xCA, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF3, 0x60, 0x9A, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x42, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x85, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xCA, 0x60, 0xD0, 0x78, 0x24, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF2, 0x60, 0x47, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xCA, 0x60, 0xD0, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xCA, 0x60, 0xD0, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xCA, 0x60, 0xD0, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x29, 0x60, 0xF2, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x2A, 0x60, 0x20, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x2A, 0x60, 0x3E, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x2A, 0x60, 0x1D, 0x78, 0x28, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x2A, 0x60, 0x1D, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x2A, 0x60, 0x1D, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x2A, 0x60, 0x1D, 0x78, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x60, 0x87, 0x64, 0x80, 0x29, 0x09, 0xFB, 0x47, 0xFF, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xF7, 0xA7, 0xFF, 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x37, 0x60, 0x82, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x60, 0x8F, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x41, 0xFF, 0x00, 0x60, 0x03, 0xE1, 0x21, 0x46, 0x66, 0x45, 0x00, 0xF4, 0x2E, 0x44, 0x09, 0xFA, + 0x6A, 0x61, 0x7F, 0x60, 0xFE, 0x63, 0xA1, 0xFF, 0x9A, 0xFF, 0x05, 0x11, 0x0A, 0x00, 0x00, 0xF4, + 0x01, 0xF2, 0x17, 0x18, 0x7A, 0x61, 0x02, 0x25, 0x04, 0x00, 0x6C, 0x44, 0x7A, 0xDA, 0xFB, 0x1C, + 0xF6, 0x11, 0xD9, 0x81, 0x41, 0xFF, 0x02, 0x1C, 0x00, 0xF4, 0xDA, 0x82, 0x41, 0xFF, 0xC9, 0x81, + 0xCB, 0x83, 0x6C, 0x44, 0x5A, 0xDA, 0x02, 0x1C, 0x00, 0xF4, 0x81, 0xF2, 0x6C, 0x44, 0x5A, 0xDA, + 0xCB, 0x83, 0x02, 0x74, 0x02, 0x60, 0x04, 0xE1, 0x80, 0x60, 0x00, 0x61, 0x5D, 0x93, 0xB5, 0xFF, + 0x98, 0xFF, 0x26, 0x44, 0xFD, 0xB4, 0x84, 0xBC, 0x40, 0x46, 0x65, 0x46, 0x00, 0x64, 0x23, 0xFA, + 0x3F, 0xFC, 0x63, 0x47, 0x0A, 0x63, 0x0F, 0xFC, 0x00, 0xF4, 0x08, 0xFA, 0xCB, 0xFE, 0x18, 0xE1, + 0x44, 0xFF, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0xE2, 0xFE, 0x03, 0x04, 0xA3, 0x60, 0x05, 0x78, + 0xFF, 0xFF, 0xE0, 0xFE, 0x03, 0x04, 0xA3, 0x60, 0x1B, 0x78, 0xFF, 0xFF, 0xE1, 0xFE, 0x07, 0x05, + 0x9F, 0xFE, 0x03, 0x04, 0x3A, 0x60, 0x77, 0x78, 0xFF, 0xFF, 0x43, 0xFF, 0xA9, 0x01, 0x95, 0xF3, + 0xFF, 0xFF, 0x80, 0xB4, 0xFF, 0xFF, 0x08, 0x24, 0x16, 0x00, 0x29, 0x44, 0x08, 0x26, 0xE1, 0x01, + 0x72, 0x44, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xB2, 0xF3, 0xE8, 0x85, + 0xFF, 0xB7, 0xE0, 0x84, 0xE0, 0x84, 0xB4, 0x85, 0x73, 0x44, 0xD4, 0x84, 0x10, 0x65, 0xD4, 0x80, + 0xFF, 0xFF, 0x01, 0x05, 0x8F, 0x00, 0x80, 0x60, 0x01, 0xE0, 0xD5, 0x60, 0x84, 0xE7, 0xA1, 0xF3, + 0x7C, 0x45, 0x60, 0x40, 0x01, 0x23, 0x02, 0x65, 0x8C, 0x60, 0x48, 0x6A, 0xFF, 0xFF, 0x01, 0x16, + 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x7F, 0x6A, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, + 0x48, 0x60, 0x08, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, + 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x40, 0x60, 0x08, 0x6A, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, + 0x84, 0xE7, 0xBD, 0xFE, 0x0C, 0x60, 0x00, 0x62, 0x00, 0x60, 0x71, 0x7C, 0x00, 0x60, 0xB1, 0x65, + 0x3D, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0x08, 0xE1, 0x62, 0xFF, 0xA3, 0xFF, 0xFF, 0xFF, + 0xA2, 0xFF, 0x02, 0x60, 0x08, 0xE1, 0xAE, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x3F, 0x40, + 0x40, 0x26, 0x09, 0x00, 0x1C, 0x60, 0x09, 0xF3, 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x52, 0x5A, 0xD3, + 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x50, 0xDB, 0xF3, 0xF1, 0xF1, 0x01, 0xA8, 0x07, 0xA8, 0x0A, 0x03, + 0x09, 0x03, 0x64, 0x40, 0x01, 0x26, 0x09, 0x00, 0x1B, 0x60, 0xF3, 0xF3, 0xFF, 0xFF, 0x01, 0xB4, + 0xFF, 0xFF, 0x03, 0x02, 0xAD, 0x4F, 0xFA, 0xB4, 0xA0, 0x5D, 0x19, 0x60, 0xF6, 0xF1, 0x89, 0xFF, + 0x32, 0x40, 0x80, 0x2A, 0x1E, 0x00, 0x31, 0x40, 0x01, 0x2A, 0x1B, 0x00, 0x12, 0x60, 0xFF, 0xF3, + 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x05, 0x03, 0x0E, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, + 0x10, 0x00, 0x13, 0x60, 0x02, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x03, 0x03, 0x0F, 0xF2, + 0xFF, 0xFF, 0x07, 0x1B, 0x64, 0x40, 0x01, 0x26, 0x03, 0x00, 0x08, 0x60, 0x00, 0x75, 0x01, 0x00, + 0x10, 0xFF, 0x88, 0xFF, 0xA2, 0x60, 0x41, 0x78, 0xFF, 0xFF, 0x21, 0x46, 0x01, 0x5D, 0x5C, 0x62, + 0x03, 0xE1, 0x44, 0xFF, 0xA1, 0xFF, 0x9A, 0xFF, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x62, 0x62, + 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0xA1, 0xFF, 0x5A, 0xDC, 0x12, 0xE1, 0x02, 0x60, 0x01, 0xE1, + 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x28, 0x40, 0x40, 0x2B, 0x03, 0x00, 0x29, 0x40, 0x20, 0x27, + 0xA3, 0x00, 0xC8, 0x74, 0xCD, 0xE2, 0x29, 0x44, 0x08, 0xBC, 0x40, 0x49, 0x44, 0xFF, 0x05, 0xE1, + 0xDB, 0xF3, 0x37, 0x60, 0xE8, 0x63, 0x03, 0xA8, 0x04, 0xA8, 0x06, 0x03, 0x05, 0x03, 0xA3, 0xD3, + 0xFF, 0xFF, 0x01, 0xA8, 0x07, 0x18, 0x0A, 0x03, 0x28, 0x40, 0x08, 0x2A, 0x07, 0x00, 0x28, 0x40, + 0x48, 0x36, 0x04, 0x00, 0xF1, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xF1, 0xFB, 0x29, 0x44, 0xFF, 0x60, + 0xEF, 0x65, 0x24, 0x89, 0x40, 0x27, 0x3F, 0x00, 0x00, 0x00, 0x29, 0x40, 0x80, 0x27, 0x0B, 0x00, + 0x07, 0x61, 0xA1, 0xFF, 0xCD, 0x81, 0x04, 0x25, 0x61, 0x00, 0x87, 0x4C, 0xFB, 0x02, 0xF3, 0x60, + 0xA0, 0x64, 0x80, 0x4C, 0x07, 0x00, 0xA1, 0xFF, 0x9C, 0x4C, 0x9C, 0x4C, 0x9C, 0x4D, 0x05, 0x60, + 0xCF, 0x64, 0x80, 0x4C, 0x28, 0x40, 0x40, 0x2B, 0x05, 0x00, 0x29, 0x40, 0x20, 0x27, 0x02, 0x00, + 0x15, 0x60, 0x6F, 0x6B, 0x04, 0x25, 0x4A, 0x00, 0x30, 0x64, 0x3A, 0xDB, 0x44, 0xFF, 0x04, 0x25, + 0x45, 0x00, 0x04, 0x60, 0x00, 0x65, 0x25, 0x44, 0xB4, 0x84, 0x80, 0x4E, 0x2D, 0x41, 0x04, 0x25, + 0x3D, 0x00, 0x61, 0x4C, 0x00, 0x60, 0x8A, 0x65, 0xC5, 0x81, 0x61, 0x54, 0xA1, 0xFF, 0xFF, 0xFF, + 0x04, 0x25, 0x34, 0x00, 0x67, 0x4E, 0x07, 0x64, 0x1C, 0xFB, 0x00, 0xE1, 0x02, 0x60, 0x05, 0xE1, + 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x28, 0x40, 0x40, 0x27, 0x0A, 0x00, 0x1C, 0x65, 0x28, 0x40, + 0xA4, 0x36, 0x14, 0x65, 0x23, 0x44, 0xC4, 0x84, 0x28, 0x40, 0x08, 0x2A, 0x0C, 0x00, 0x07, 0x00, + 0x23, 0x44, 0x1C, 0xA4, 0x29, 0x40, 0x20, 0x27, 0x02, 0x00, 0x11, 0x60, 0x0F, 0x6B, 0x3C, 0x46, + 0x98, 0xF0, 0x23, 0x44, 0xC4, 0x84, 0x06, 0x74, 0x25, 0x5C, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0xB0, 0x84, 0x80, 0x4C, 0x9C, 0x4C, 0x44, 0xFF, 0x18, 0xE1, 0x0A, 0x64, 0x1E, 0x74, + 0x02, 0x60, 0x05, 0xE1, 0x40, 0x40, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0xC4, 0xE2, 0x27, 0x44, + 0x20, 0x2A, 0x06, 0x00, 0x42, 0x64, 0x3A, 0xDB, 0x67, 0x4C, 0xB1, 0x60, 0xAD, 0x78, 0xFF, 0xFF, + 0x41, 0x64, 0x3A, 0xDB, 0x62, 0xFF, 0x08, 0xE1, 0xE2, 0xFE, 0x72, 0x52, 0xA1, 0xFF, 0x98, 0xFF, + 0x80, 0x3E, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x28, 0x40, 0x08, 0x27, 0x5A, 0x01, 0x3C, 0x46, + 0x8B, 0xFF, 0x84, 0x60, 0x00, 0xE4, 0x0F, 0x60, 0x90, 0x64, 0xC9, 0x60, 0x58, 0x4F, 0x56, 0x78, + 0xFF, 0xFF, 0x3F, 0xF2, 0x00, 0x60, 0x18, 0x70, 0x18, 0x71, 0x20, 0x72, 0x00, 0xF2, 0x60, 0x53, + 0x20, 0xE1, 0xA1, 0xFF, 0x88, 0x75, 0x00, 0xE1, 0xFF, 0xFF, 0x60, 0x50, 0x75, 0x44, 0x12, 0x71, + 0x6E, 0x72, 0x81, 0x75, 0xFF, 0xFF, 0x88, 0xFF, 0xA3, 0x60, 0x21, 0x78, 0xFF, 0xFF, 0x32, 0xF3, + 0x08, 0x29, 0x0A, 0x00, 0x60, 0x40, 0x07, 0x22, 0x07, 0x00, 0xFE, 0xB4, 0x32, 0xFB, 0x27, 0x44, + 0x10, 0xBC, 0xF7, 0xB4, 0x40, 0x47, 0x43, 0xFF, 0x00, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x08, 0xE1, + 0x31, 0x40, 0x01, 0x2A, 0x06, 0x00, 0x00, 0x64, 0x33, 0xFB, 0x01, 0x60, 0x0A, 0xE1, 0x25, 0x11, + 0x24, 0x0A, 0xE5, 0xFE, 0x2D, 0x05, 0x32, 0x40, 0x80, 0x2A, 0x05, 0x00, 0x19, 0x60, 0xF2, 0xF3, + 0xFF, 0xFF, 0x01, 0x18, 0x16, 0x00, 0x9F, 0xFE, 0x14, 0x05, 0x9D, 0xFE, 0x12, 0x04, 0x31, 0x41, + 0x40, 0x2A, 0x0F, 0x00, 0x07, 0x60, 0xE9, 0xF1, 0xAE, 0x4C, 0x90, 0x80, 0x10, 0x2A, 0x09, 0x00, + 0x7F, 0xB1, 0x07, 0x60, 0xE9, 0xFB, 0x60, 0x40, 0x10, 0x2A, 0x80, 0xB9, 0x41, 0x51, 0xDF, 0xFE, + 0x19, 0xFF, 0x9F, 0xFE, 0x02, 0x04, 0x40, 0xE1, 0x08, 0x00, 0x7C, 0xE1, 0x31, 0x44, 0x01, 0x2A, + 0x04, 0x00, 0xFD, 0xE1, 0x27, 0x44, 0x10, 0x26, 0x06, 0x00, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, + 0xAA, 0x60, 0x6F, 0x78, 0xFF, 0xFF, 0x27, 0x44, 0x08, 0x26, 0xFF, 0xFF, 0xC1, 0x60, 0xA3, 0x78, + 0xFF, 0xFF, 0x48, 0xF3, 0x32, 0xF1, 0x00, 0x63, 0x64, 0x40, 0x07, 0x26, 0x03, 0x00, 0xA5, 0x60, + 0x0F, 0x78, 0xFF, 0xFF, 0x43, 0xFF, 0x31, 0x40, 0x08, 0x26, 0xF0, 0x01, 0xCD, 0xE2, 0x85, 0xE1, + 0x70, 0x41, 0xAD, 0x80, 0x71, 0x40, 0x80, 0x27, 0xE9, 0x12, 0x03, 0x03, 0xC2, 0x60, 0x15, 0x78, + 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0xC4, 0xE2, 0x32, 0xFD, 0x60, 0x40, 0x01, 0x2A, 0xDB, 0x01, + 0x00, 0x63, 0x32, 0xFD, 0x3C, 0x46, 0x3E, 0xF2, 0x2A, 0xF0, 0x27, 0x41, 0x44, 0x48, 0x20, 0xB9, + 0x01, 0xB4, 0xF7, 0xB1, 0x0A, 0x03, 0x64, 0x40, 0x08, 0x27, 0x07, 0x00, 0x0F, 0x60, 0xDA, 0x63, + 0x00, 0x64, 0x45, 0xFB, 0x46, 0xFB, 0xBD, 0xDB, 0xA3, 0xDB, 0xC8, 0x0A, 0xC7, 0x11, 0x1B, 0x60, + 0xEE, 0xF3, 0xFF, 0xFF, 0x14, 0x18, 0x28, 0x40, 0xD4, 0x36, 0x11, 0x00, 0xAC, 0x4C, 0x80, 0x2A, + 0x0E, 0x00, 0x1B, 0x60, 0xF1, 0xF3, 0xFF, 0xFF, 0x0A, 0x18, 0x1B, 0x60, 0xF2, 0xF3, 0x1B, 0x60, + 0xEF, 0xF3, 0x60, 0x45, 0xD4, 0x80, 0xDC, 0x84, 0x02, 0x03, 0xA2, 0xDB, 0xAF, 0x01, 0x00, 0x64, + 0x1B, 0x60, 0xEF, 0xFB, 0x41, 0x47, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x10, 0x26, 0x04, 0x00, + 0x01, 0x2A, 0x05, 0x00, 0x10, 0x2B, 0x03, 0x00, 0x29, 0x47, 0x20, 0xBF, 0x40, 0x49, 0x1B, 0x60, + 0xEE, 0xF3, 0xFF, 0xFF, 0x04, 0x18, 0xAE, 0x4F, 0x08, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x05, 0xE1, + 0x01, 0x60, 0x08, 0xE1, 0x2A, 0xE8, 0x3C, 0x46, 0x0F, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x2A, + 0x03, 0x00, 0xA7, 0x60, 0xE1, 0x78, 0xFF, 0xFF, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, + 0x0E, 0x00, 0x1F, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x2B, 0x09, 0x00, 0x19, 0x60, 0x7B, 0xF3, + 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x2A, 0x03, 0x00, 0xA8, 0x60, 0xEC, 0x78, 0xFF, 0xFF, 0x1F, 0xF2, + 0xC0, 0x60, 0x00, 0x65, 0xA4, 0x9C, 0x3F, 0x60, 0xCF, 0x65, 0x29, 0x44, 0xA4, 0x84, 0x30, 0x89, + 0x19, 0x60, 0x77, 0xF3, 0xFF, 0xFF, 0x19, 0x60, 0x55, 0xFB, 0x1F, 0xF2, 0x39, 0xF1, 0xE0, 0x60, + 0xFF, 0xB5, 0x0A, 0x18, 0x60, 0x47, 0x1F, 0xB4, 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, + 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, 0xB4, 0x81, 0x07, 0x60, 0xEA, 0xF1, 0xFF, 0xFF, + 0xB1, 0x8C, 0x29, 0x40, 0x40, 0x2B, 0x10, 0x00, 0x29, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x1F, 0xB4, + 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x01, 0x60, 0x09, 0x6B, + 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, 0x14, 0x00, 0x29, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x1F, 0xB4, + 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, + 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, 0x7C, 0x44, 0x29, 0x40, 0x80, 0x2B, 0x67, 0x44, 0x60, 0x4C, + 0x00, 0xE1, 0x84, 0xFF, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0x82, 0xFF, 0x0D, 0x00, 0xE5, 0xFE, + 0x03, 0x04, 0xAA, 0x60, 0x6F, 0x78, 0xFF, 0xFF, 0x32, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x07, 0x22, + 0x43, 0xFF, 0xA3, 0x60, 0xF4, 0x78, 0xFF, 0xFF, 0x0B, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x0A, 0xE1, + 0x1C, 0x42, 0x22, 0x46, 0x13, 0xF2, 0xFF, 0x65, 0x60, 0x47, 0x2A, 0xF2, 0x40, 0x45, 0x40, 0x48, + 0x04, 0x2B, 0x13, 0x00, 0x16, 0xF2, 0x1D, 0xF2, 0x40, 0x43, 0x0F, 0xF2, 0x40, 0x4D, 0x0F, 0x64, + 0x14, 0xF0, 0x35, 0xF2, 0xA0, 0x82, 0x0F, 0xB4, 0xCA, 0x85, 0xD4, 0x80, 0x10, 0xF2, 0x01, 0x02, + 0x2B, 0xFA, 0x27, 0x44, 0x40, 0xBC, 0x40, 0x47, 0x13, 0x00, 0x17, 0xF2, 0x2C, 0xF0, 0x40, 0x43, + 0x1B, 0xF2, 0x1D, 0xFA, 0x40, 0x4D, 0x64, 0x40, 0x01, 0x2A, 0x02, 0x00, 0xAB, 0xFC, 0x05, 0x00, + 0x28, 0x40, 0xA4, 0x36, 0x02, 0x00, 0x11, 0xF2, 0x2B, 0xFA, 0x27, 0x44, 0xBF, 0xB4, 0x40, 0x47, + 0xF0, 0xFE, 0xB0, 0x60, 0xB0, 0x78, 0xFF, 0xFF, 0x22, 0x46, 0x2C, 0xF0, 0x27, 0x44, 0xDF, 0xB4, + 0x40, 0x47, 0x64, 0x40, 0x01, 0x26, 0x09, 0x00, 0x2A, 0xF2, 0x39, 0xF0, 0x8F, 0xB0, 0x88, 0x3A, + 0x0D, 0x00, 0x64, 0x44, 0x60, 0xB0, 0x20, 0x3A, 0x09, 0x00, 0x28, 0x44, 0x04, 0x27, 0x05, 0x00, + 0xD4, 0x3A, 0x03, 0x00, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, 0x11, 0x00, 0x2A, 0xF0, 0x01, 0x65, + 0x64, 0x40, 0xA4, 0x3A, 0x04, 0x65, 0x27, 0x44, 0x34, 0x87, 0x36, 0xF3, 0xFF, 0xFF, 0x60, 0x56, + 0xAD, 0xE2, 0x04, 0x64, 0x3A, 0xDB, 0x41, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x06, 0x64, + 0x3A, 0xDB, 0x22, 0x46, 0x01, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xC2, 0x60, 0x1E, 0x78, 0xFF, 0xFF, + 0x28, 0x40, 0xC4, 0x3A, 0x0C, 0x00, 0x27, 0x44, 0xFD, 0xB4, 0x40, 0x47, 0xA8, 0xE2, 0x05, 0xE1, + 0x01, 0x60, 0x08, 0xE1, 0x2A, 0xE8, 0x3C, 0x46, 0xA4, 0x60, 0xBF, 0x78, 0xFF, 0xFF, 0x3F, 0x40, + 0x01, 0x2B, 0x05, 0x00, 0x67, 0x4C, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, 0x07, 0x60, + 0xEB, 0xF1, 0x1F, 0xF2, 0x2A, 0xE8, 0xB0, 0x81, 0x29, 0x40, 0x40, 0x2B, 0x14, 0x00, 0x61, 0x4C, + 0x29, 0x60, 0xC0, 0x65, 0x61, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, + 0x01, 0x60, 0x00, 0xE1, 0x01, 0x60, 0x09, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0xFF, 0x60, 0xF2, 0x64, + 0x64, 0x4C, 0x40, 0x43, 0x18, 0x00, 0x29, 0x47, 0x80, 0xB7, 0x34, 0x94, 0x60, 0x4C, 0x29, 0x60, + 0xC0, 0x65, 0x61, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, + 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, 0x7C, 0x44, 0x29, 0x40, + 0x80, 0x2B, 0x67, 0x44, 0x60, 0x4C, 0x40, 0xE1, 0x01, 0x60, 0x08, 0xE1, 0x28, 0x45, 0xBF, 0x60, + 0xFF, 0x64, 0x24, 0x88, 0xC4, 0xE2, 0x08, 0x64, 0x3A, 0xDB, 0x21, 0x46, 0x2A, 0x44, 0x72, 0x45, + 0x24, 0xFA, 0xB2, 0xF3, 0x06, 0x04, 0xE4, 0xE2, 0xDC, 0x9C, 0x29, 0x40, 0x01, 0x26, 0x64, 0x44, + 0xB2, 0xF9, 0x25, 0xFA, 0xB3, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB3, 0xFB, 0x28, 0xFA, 0xB4, 0xF3, + 0x02, 0x04, 0xDC, 0x84, 0xB4, 0xFB, 0x29, 0xFA, 0x24, 0x44, 0x04, 0x2A, 0x06, 0x00, 0x28, 0x40, + 0xA4, 0x36, 0x03, 0x00, 0xA6, 0x60, 0xB1, 0x78, 0xFF, 0xFF, 0x26, 0x43, 0x84, 0xBB, 0xFC, 0xB3, + 0x21, 0x46, 0x01, 0x5D, 0x0F, 0xFC, 0x5C, 0x46, 0x05, 0xFF, 0x27, 0x44, 0x01, 0x2A, 0x13, 0x00, + 0x50, 0xFE, 0x28, 0x40, 0x08, 0x3A, 0x12, 0x00, 0x2F, 0xF2, 0x30, 0xF0, 0x60, 0x43, 0x31, 0xF2, + 0x22, 0x46, 0x64, 0x41, 0x2C, 0xF0, 0x2D, 0xF0, 0xD3, 0x80, 0x2E, 0xF0, 0xD1, 0x80, 0xD0, 0x80, + 0x27, 0x44, 0x09, 0x0C, 0x03, 0x00, 0x27, 0x44, 0x06, 0x22, 0x05, 0x00, 0xB8, 0xB4, 0x40, 0x47, + 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xD4, 0x64, 0x40, 0x48, 0x0D, 0x64, 0x3A, 0xDB, 0x7C, 0x44, + 0x1B, 0x60, 0xF0, 0xFB, 0x21, 0x46, 0x1C, 0xF2, 0x00, 0xE1, 0xF0, 0xFE, 0x00, 0x63, 0x28, 0x44, + 0xA4, 0x36, 0x0A, 0x00, 0x04, 0x2B, 0x08, 0x00, 0x30, 0xF3, 0x2D, 0x45, 0xD4, 0x84, 0xCA, 0x65, + 0xD4, 0x83, 0x01, 0x64, 0x1B, 0x60, 0xF0, 0xFB, 0xD4, 0x64, 0x35, 0x00, 0x0F, 0x64, 0x3A, 0xDB, + 0x21, 0x46, 0x29, 0x40, 0x40, 0x27, 0x15, 0x00, 0x80, 0x27, 0x02, 0x00, 0xCA, 0x65, 0x01, 0x00, + 0x6A, 0x65, 0x1C, 0xF2, 0xFF, 0xFF, 0x04, 0x7F, 0x40, 0x45, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, + 0x38, 0x64, 0x37, 0x36, 0x15, 0x64, 0x6E, 0x3A, 0x17, 0x00, 0x84, 0x7F, 0x40, 0x45, 0x0B, 0x64, + 0x13, 0x00, 0x1C, 0xF2, 0x1E, 0x65, 0x40, 0x45, 0x0B, 0x36, 0x1E, 0x64, 0x0F, 0x36, 0x16, 0x64, + 0x0A, 0x36, 0x12, 0x64, 0x0E, 0x36, 0x0E, 0x64, 0x09, 0x36, 0x0E, 0x64, 0x0D, 0x36, 0x0A, 0x64, + 0x08, 0x36, 0x0A, 0x64, 0x0C, 0x36, 0x0A, 0x64, 0x40, 0x4D, 0x00, 0xE1, 0xF0, 0xFE, 0x2B, 0xF2, + 0xC4, 0x85, 0xD4, 0x83, 0xC4, 0x64, 0x40, 0x48, 0x2F, 0xF0, 0xB0, 0xF0, 0xB1, 0xF2, 0xA1, 0xFF, + 0x12, 0x74, 0xCD, 0xE2, 0x80, 0x4E, 0x12, 0x74, 0x83, 0x4C, 0x12, 0x74, 0x9A, 0xFF, 0x84, 0x4C, + 0x12, 0x74, 0x85, 0x4C, 0x12, 0x74, 0x81, 0x4C, 0x12, 0x74, 0xA1, 0xFF, 0x98, 0xFF, 0xB2, 0x60, + 0x58, 0x4F, 0x2D, 0x78, 0xFF, 0xFF, 0x01, 0x60, 0x18, 0xE1, 0x78, 0x44, 0x03, 0xA4, 0x35, 0xFB, + 0xB2, 0x60, 0x70, 0x78, 0xFF, 0xFF, 0x29, 0x44, 0xF7, 0xB4, 0x40, 0x49, 0x28, 0x40, 0xC4, 0x36, + 0x07, 0x00, 0x1B, 0x60, 0xF0, 0xF3, 0xFF, 0xFF, 0x03, 0x1B, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, + 0x27, 0x44, 0x01, 0x2A, 0x05, 0x00, 0xFE, 0xB4, 0x40, 0x47, 0xA5, 0x60, 0x7F, 0x78, 0xFF, 0xFF, + 0x16, 0x60, 0xAB, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x36, 0xC1, 0xFE, 0xA3, 0x60, 0xE7, 0x78, + 0xFF, 0xFF, 0x28, 0x40, 0xB4, 0x3A, 0x0B, 0x00, 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, + 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xA6, 0x60, 0x3E, 0x78, 0xFF, 0xFF, 0x28, 0x44, + 0xD4, 0x36, 0x03, 0x00, 0xA7, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0xA8, 0xE2, 0x27, 0x44, 0xFB, 0xB4, + 0x40, 0x47, 0x1C, 0x42, 0x22, 0x46, 0x19, 0x60, 0xCF, 0xF3, 0xFF, 0xFF, 0x34, 0xFB, 0x2A, 0xF0, + 0xF7, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDA, 0x60, 0x40, 0x40, 0x2B, 0xC4, 0x00, 0x22, 0xF2, + 0xFF, 0xFF, 0x60, 0x40, 0x22, 0x26, 0x3F, 0x00, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, 0x05, 0x00, + 0xBA, 0x00, 0x04, 0x2B, 0xB8, 0x00, 0xA6, 0xF5, 0x01, 0x00, 0x07, 0xF4, 0x4B, 0xF2, 0xFF, 0xFF, + 0xDC, 0x84, 0x4B, 0xFA, 0x0C, 0x60, 0xFC, 0x62, 0x80, 0xFF, 0xC8, 0x60, 0x78, 0x44, 0x02, 0xA4, + 0xA2, 0xDB, 0x8C, 0x78, 0xFF, 0xFF, 0x82, 0xFF, 0xA6, 0xF3, 0x66, 0x5C, 0xD0, 0x80, 0x00, 0x7C, + 0x07, 0x03, 0x66, 0x43, 0x22, 0x46, 0x22, 0xF2, 0x63, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x01, 0x00, + 0x3C, 0xF1, 0x4B, 0xF0, 0x64, 0x41, 0x64, 0x47, 0x60, 0x5F, 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, + 0x60, 0x47, 0x22, 0x46, 0x3A, 0xFA, 0x64, 0x44, 0x20, 0x7F, 0x34, 0x94, 0x3B, 0xFA, 0x08, 0x60, + 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, + 0xD1, 0x60, 0x00, 0xEA, 0x80, 0x00, 0x2A, 0xF2, 0x00, 0x60, 0x7C, 0x62, 0x60, 0x40, 0x40, 0x2B, + 0x24, 0x00, 0xA2, 0xD3, 0x00, 0x61, 0x60, 0xFE, 0xA0, 0xD3, 0x5E, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, + 0x64, 0x5F, 0xDC, 0x84, 0xF1, 0x81, 0xC0, 0x2B, 0x04, 0x00, 0x80, 0x2A, 0x02, 0x00, 0x7F, 0xA4, + 0xDC, 0x84, 0xFF, 0x3B, 0x03, 0x00, 0x60, 0x47, 0xDC, 0x87, 0x01, 0x61, 0xC0, 0x80, 0x00, 0x36, + 0xDC, 0x84, 0x4E, 0xDB, 0x60, 0xFE, 0x5A, 0xD1, 0xFF, 0xFF, 0xC1, 0x84, 0xF0, 0x22, 0x10, 0xA4, + 0xF0, 0x2A, 0x01, 0x00, 0x00, 0x64, 0xA2, 0xDB, 0x20, 0xFE, 0x00, 0x60, 0x3E, 0xF3, 0xFF, 0xFF, + 0xA0, 0xD3, 0x5A, 0xD1, 0x3A, 0xFA, 0x3B, 0xF8, 0x74, 0x62, 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, + 0xE0, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, + 0xA0, 0x5A, 0x00, 0x60, 0x40, 0xF3, 0xFF, 0xFF, 0xA0, 0xD1, 0x5A, 0xD1, 0x64, 0x45, 0x64, 0x44, + 0xE3, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE5, 0x7F, + 0xA0, 0x5A, 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5A, + 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, + 0xE9, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEB, 0x7F, + 0xA0, 0x5A, 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5A, + 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEF, 0x7F, 0xA0, 0x5A, 0x08, 0x60, + 0x00, 0xEA, 0x65, 0x44, 0x02, 0xA4, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, + 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x0B, 0xF2, 0xFF, 0xFF, 0x7F, 0xB4, 0x0C, 0xF0, 0x04, 0x02, + 0x64, 0x46, 0x00, 0xF0, 0x04, 0x64, 0x22, 0x46, 0x03, 0xFA, 0x60, 0x41, 0x64, 0x46, 0x01, 0xF2, + 0xFC, 0xA1, 0x61, 0x45, 0xD4, 0x84, 0xFF, 0xFF, 0x08, 0x02, 0x00, 0xF0, 0x04, 0x63, 0x64, 0x46, + 0x01, 0xF2, 0x22, 0x46, 0x1A, 0xFA, 0x03, 0xFC, 0x02, 0x00, 0x22, 0x46, 0x1A, 0xFA, 0x35, 0xF2, + 0x04, 0xF8, 0xDC, 0x84, 0x35, 0xFA, 0x14, 0xF2, 0x0F, 0xB5, 0x0F, 0xB4, 0xCC, 0x84, 0x94, 0x80, + 0x04, 0x60, 0x00, 0x65, 0x2A, 0xF2, 0x01, 0x02, 0x94, 0x84, 0x2A, 0xFA, 0x95, 0xFC, 0x06, 0x00, + 0xC4, 0x3A, 0x07, 0x00, 0x27, 0x44, 0xFD, 0xB4, 0x40, 0x47, 0xA8, 0xE2, 0xA5, 0x60, 0x1C, 0x78, + 0xFF, 0xFF, 0x28, 0x44, 0x04, 0x26, 0x05, 0x00, 0x68, 0x3A, 0x03, 0x00, 0x32, 0x44, 0x00, 0x27, + 0x03, 0x00, 0xA3, 0x60, 0xF4, 0x78, 0xFF, 0xFF, 0x0A, 0x64, 0x3A, 0xDB, 0xA3, 0x60, 0xF4, 0x78, + 0xFF, 0xFF, 0x0E, 0x64, 0x3A, 0xDB, 0x3C, 0x44, 0x60, 0x46, 0x1E, 0xF0, 0x40, 0x42, 0x64, 0x40, + 0x40, 0x27, 0x48, 0x00, 0x1F, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x27, 0x3C, 0x00, 0x80, 0x2B, + 0x0B, 0x00, 0xBF, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x80, 0x60, 0x00, 0x65, 0x29, 0x44, + 0x34, 0x89, 0x80, 0x60, 0x00, 0x63, 0x05, 0x00, 0x3F, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, + 0x00, 0x63, 0x1E, 0xF2, 0x39, 0xF1, 0xC0, 0x60, 0xFF, 0xB5, 0x0A, 0x18, 0x60, 0x47, 0x1F, 0xB4, + 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, + 0xB4, 0x84, 0x07, 0x60, 0xEA, 0xF1, 0x3C, 0x94, 0xB0, 0x84, 0x60, 0x4C, 0x29, 0x60, 0xC0, 0x65, + 0x60, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, + 0x05, 0x60, 0x69, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, 0x7C, 0x44, 0x29, 0x40, 0x80, 0x2B, + 0x67, 0x44, 0x60, 0x4C, 0x32, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x04, 0x26, + 0xCB, 0x01, 0xBF, 0x01, 0x40, 0x60, 0x00, 0x65, 0x29, 0x44, 0x34, 0x89, 0x40, 0x60, 0x00, 0x63, + 0x9F, 0xF2, 0x1E, 0xF2, 0x39, 0xF1, 0xC0, 0x60, 0xFF, 0xB5, 0x0A, 0x18, 0x60, 0x47, 0x1F, 0xB4, + 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, + 0xB4, 0x84, 0x07, 0x60, 0xEA, 0xF1, 0x3C, 0x94, 0xB0, 0x81, 0x61, 0x4C, 0x29, 0x60, 0xC0, 0x65, + 0x61, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, + 0x01, 0x60, 0x09, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, 0x40, 0xE1, 0x01, 0x60, 0x08, 0xE1, + 0x84, 0xFF, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0x82, 0xFF, 0x2A, 0xF2, 0x10, 0x60, 0x00, 0x65, + 0xA4, 0x84, 0xB4, 0xBC, 0x1E, 0xF0, 0x40, 0x48, 0x64, 0x40, 0x40, 0x27, 0x17, 0x00, 0x1C, 0xF2, + 0xFF, 0xFF, 0x60, 0x40, 0x0A, 0x36, 0x06, 0x00, 0x14, 0x36, 0x07, 0x00, 0x37, 0x36, 0x08, 0x00, + 0x6E, 0x36, 0x09, 0x00, 0x70, 0x7C, 0xA0, 0x63, 0x0F, 0x00, 0x38, 0x7C, 0x50, 0x63, 0x0C, 0x00, + 0x15, 0x7C, 0x1E, 0x63, 0x09, 0x00, 0x0B, 0x7C, 0x0F, 0x63, 0x06, 0x00, 0x9C, 0xF4, 0xFF, 0x65, + 0x63, 0x47, 0xA4, 0x9C, 0xA7, 0x84, 0x23, 0x00, 0x40, 0x45, 0x43, 0x4D, 0x00, 0xE1, 0xF0, 0xFE, + 0x29, 0x40, 0x80, 0x2B, 0x03, 0x00, 0x00, 0x60, 0x6A, 0x65, 0x02, 0x00, 0x00, 0x60, 0xCA, 0x65, + 0x1F, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x27, 0x0E, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, + 0x04, 0x27, 0x03, 0x00, 0x65, 0x44, 0xE0, 0x85, 0x12, 0x00, 0x2B, 0xF2, 0x11, 0xF0, 0xC0, 0x84, + 0xD0, 0x84, 0xC4, 0x83, 0x11, 0x00, 0x1E, 0x64, 0xC4, 0x84, 0x60, 0x45, 0x08, 0x00, 0x40, 0x45, + 0xFF, 0x60, 0xF8, 0x64, 0x40, 0x43, 0x00, 0xE1, 0xF0, 0xFE, 0x00, 0x60, 0x3C, 0x65, 0x91, 0xF4, + 0x1B, 0xF0, 0xC3, 0x84, 0xC4, 0x84, 0xC0, 0x83, 0x28, 0x44, 0xA1, 0xFF, 0x12, 0x74, 0x80, 0x4E, + 0x12, 0x74, 0x83, 0x4C, 0x9A, 0xFF, 0x12, 0x74, 0x56, 0x62, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, + 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x5C, 0x62, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, + 0x7A, 0xD4, 0x12, 0x74, 0xA1, 0xFF, 0x98, 0xFF, 0xB2, 0x60, 0x58, 0x4F, 0x2D, 0x78, 0xFF, 0xFF, + 0xBC, 0xFF, 0xB5, 0xFF, 0x01, 0x60, 0x18, 0xE1, 0x47, 0xFF, 0x27, 0x44, 0x02, 0xBC, 0x40, 0x47, + 0x36, 0xF3, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, 0x60, 0x56, + 0xAD, 0xE2, 0xA5, 0x60, 0x79, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x7B, 0xF3, 0x19, 0x60, 0x3B, 0xF3, + 0x60, 0x40, 0x04, 0x26, 0x0B, 0x00, 0x07, 0xB4, 0x60, 0x40, 0x01, 0x36, 0x07, 0x00, 0x29, 0x44, + 0xBF, 0x60, 0xFF, 0xB7, 0x80, 0xBF, 0x40, 0x49, 0x80, 0x67, 0x05, 0x00, 0x3F, 0x60, 0xFF, 0x65, + 0x29, 0x44, 0x24, 0x89, 0x00, 0x64, 0x16, 0x60, 0x50, 0xF1, 0xFF, 0xFF, 0x19, 0x60, 0x55, 0xF9, + 0x39, 0xF1, 0x16, 0x60, 0x3C, 0xF1, 0x64, 0x41, 0x64, 0x5E, 0x60, 0x45, 0x64, 0x47, 0x1F, 0xB4, + 0x54, 0x94, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, + 0x07, 0x60, 0xEA, 0xF1, 0xB4, 0x84, 0xB0, 0x8C, 0x29, 0x60, 0xC0, 0x7C, 0x60, 0x47, 0x1F, 0xB4, + 0xE0, 0x84, 0xE0, 0x84, 0x40, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, + 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, 0x7C, 0x44, 0x29, 0x40, 0x80, 0x2B, 0x67, 0x44, 0x60, 0x4C, + 0x40, 0xE1, 0x01, 0x60, 0x08, 0xE1, 0x84, 0xFF, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0x82, 0xFF, + 0x3C, 0x44, 0x60, 0x46, 0x40, 0x42, 0x13, 0x64, 0x3A, 0xDB, 0x10, 0x60, 0x00, 0x65, 0x3C, 0x46, + 0x2A, 0xF2, 0x19, 0x60, 0x3B, 0xF1, 0xA4, 0x84, 0xC4, 0xBC, 0x40, 0x48, 0x64, 0x44, 0x04, 0x26, + 0x09, 0x00, 0x02, 0x26, 0x0A, 0x00, 0x01, 0x26, 0x0B, 0x00, 0x08, 0x2A, 0x03, 0x00, 0x0B, 0x63, + 0x6E, 0x64, 0x08, 0x00, 0x15, 0x63, 0x37, 0x64, 0x05, 0x00, 0x38, 0x63, 0x14, 0x64, 0x02, 0x00, + 0x70, 0x63, 0x0A, 0x64, 0x43, 0x4D, 0x40, 0x45, 0x00, 0xE1, 0xF0, 0xFE, 0x00, 0x60, 0x1E, 0x64, + 0x1B, 0xF0, 0x11, 0xF0, 0xC0, 0x84, 0xC0, 0x84, 0x60, 0x43, 0x28, 0x44, 0xA1, 0xFF, 0x12, 0x74, + 0x80, 0x4E, 0x12, 0x74, 0x83, 0x4C, 0x9A, 0xFF, 0x12, 0x74, 0x5C, 0x62, 0x7A, 0xD4, 0x12, 0x74, + 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0xA1, 0xFF, 0x98, 0xFF, 0xB2, 0x60, 0x58, 0x4F, + 0x2D, 0x78, 0xFF, 0xFF, 0x01, 0x60, 0x18, 0xE1, 0x78, 0x44, 0x03, 0xA4, 0x35, 0xFB, 0xB2, 0x60, + 0x70, 0x78, 0xFF, 0xFF, 0xC4, 0xE2, 0x08, 0x64, 0x3A, 0xDB, 0xA4, 0x60, 0xBF, 0x78, 0xFF, 0xFF, + 0x26, 0x43, 0x24, 0x40, 0x01, 0x2A, 0x0E, 0x00, 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xBC, 0x40, 0x46, + 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, + 0x30, 0xF1, 0x81, 0x00, 0xFC, 0xB3, 0x32, 0x40, 0x01, 0x2A, 0x06, 0x00, 0x0A, 0xBB, 0x0F, 0xFC, + 0xCB, 0xFE, 0xA3, 0x60, 0xF4, 0x78, 0xFF, 0xFF, 0x24, 0x44, 0x04, 0x26, 0x29, 0x00, 0x0F, 0xFC, + 0x05, 0xFF, 0xDB, 0xF3, 0x28, 0x40, 0x80, 0x3A, 0x23, 0x00, 0x60, 0x40, 0x03, 0x3A, 0x20, 0x00, + 0x32, 0xF2, 0x7F, 0xF1, 0x33, 0xF2, 0xD0, 0x80, 0x80, 0xF1, 0x1A, 0x02, 0xD0, 0x80, 0x34, 0xF2, + 0x81, 0xF1, 0x16, 0x02, 0xD0, 0x80, 0x3C, 0x44, 0x13, 0x02, 0xAC, 0x86, 0xBB, 0xFE, 0x10, 0x03, + 0x2A, 0xF2, 0x21, 0x46, 0x60, 0x40, 0x80, 0x3A, 0x0B, 0x00, 0x01, 0x64, 0x31, 0xFB, 0xC0, 0xFE, + 0x00, 0x64, 0x32, 0xFB, 0x43, 0xFF, 0x84, 0xFF, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0x82, 0xFF, + 0x30, 0xF1, 0x27, 0x44, 0x05, 0x22, 0x34, 0x00, 0xFA, 0xB4, 0x40, 0x47, 0x24, 0x44, 0x10, 0x2A, + 0x2B, 0x00, 0x28, 0x40, 0xD4, 0x3A, 0x28, 0x00, 0x31, 0x40, 0x08, 0x26, 0x00, 0x7C, 0x29, 0x40, + 0x50, 0x2B, 0x0D, 0x00, 0xEF, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x31, 0x40, 0x08, 0x2A, + 0x06, 0x00, 0x1C, 0x60, 0x11, 0xF3, 0xFF, 0xFF, 0xE0, 0x85, 0x2B, 0x44, 0x05, 0x05, 0x2B, 0x44, + 0xFF, 0xA4, 0x01, 0xA4, 0x04, 0x24, 0x00, 0x64, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, 0x64, 0x44, + 0xC4, 0x84, 0xFF, 0xFF, 0x04, 0x24, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, 0x20, 0x29, + 0x6D, 0xE2, 0xA5, 0x60, 0x7F, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x07, 0x00, + 0x02, 0x2A, 0x05, 0x00, 0xFD, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x05, 0x64, + 0x3A, 0xDB, 0x28, 0x44, 0xA4, 0x3A, 0x07, 0x00, 0x01, 0x60, 0x02, 0x7C, 0x25, 0x44, 0x0A, 0x3A, + 0x02, 0x00, 0x01, 0x60, 0x3A, 0x7C, 0x31, 0x40, 0x08, 0x26, 0x00, 0x7C, 0x29, 0x40, 0x50, 0x2B, + 0x0D, 0x00, 0xEF, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x31, 0x40, 0x08, 0x2A, 0x06, 0x00, + 0x1C, 0x60, 0x11, 0xF3, 0xFF, 0xFF, 0xE0, 0x85, 0x2B, 0x44, 0x05, 0x05, 0x2B, 0x44, 0xFF, 0xA4, + 0x01, 0xA4, 0x04, 0x24, 0x00, 0x64, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, 0x64, 0x44, 0xC4, 0x84, + 0xFF, 0xFF, 0x04, 0x24, 0x00, 0xB4, 0x28, 0x40, 0xE4, 0x36, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, + 0x01, 0x00, 0x20, 0x29, 0x6D, 0xE2, 0xA3, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0x27, 0x44, 0x05, 0x22, + 0x09, 0x00, 0xBA, 0xB4, 0x40, 0x47, 0x3C, 0x46, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xA3, 0x60, + 0xF4, 0x78, 0xFF, 0xFF, 0x27, 0x44, 0x02, 0x2A, 0x06, 0x00, 0xFD, 0xB4, 0x40, 0x47, 0x06, 0x64, + 0x31, 0xFB, 0xC0, 0xFE, 0xF4, 0x01, 0xF3, 0x0A, 0x7C, 0x50, 0x6D, 0xE2, 0xF0, 0x01, 0x72, 0x45, + 0xDC, 0x84, 0xB2, 0xFB, 0x11, 0x64, 0x3A, 0xDB, 0xB3, 0xF3, 0x06, 0x04, 0xDC, 0x84, 0xB3, 0xFB, + 0xB4, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB4, 0xFB, 0xA4, 0x60, 0x01, 0x78, 0xFF, 0xFF, 0x00, 0x61, + 0x12, 0x64, 0x3A, 0xDB, 0x20, 0x60, 0x04, 0x63, 0xBD, 0xD3, 0x72, 0x45, 0x44, 0x8A, 0x02, 0x28, + 0x03, 0x00, 0xE4, 0xE2, 0xDD, 0x81, 0x04, 0x00, 0x02, 0x28, 0x02, 0x00, 0xE4, 0xE2, 0xDD, 0x81, + 0xBD, 0xD3, 0xB2, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, 0xC4, 0x84, + 0x60, 0x55, 0x2A, 0x52, 0xE4, 0xE2, 0xB2, 0xFB, 0x02, 0x24, 0x01, 0xB9, 0xBD, 0xD3, 0xB3, 0xF1, + 0x61, 0x45, 0xC0, 0x84, 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, 0xC4, 0x84, 0xB3, 0xFB, 0x02, 0x24, + 0x01, 0xB9, 0xBD, 0xD3, 0xB4, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0xC4, 0x84, 0xB4, 0xFB, 0xA5, 0x60, + 0x14, 0x78, 0xFF, 0xFF, 0xB0, 0x60, 0x9E, 0x78, 0xFF, 0xFF, 0x47, 0xFF, 0x1B, 0x60, 0xEE, 0xF3, + 0xFF, 0xFF, 0x04, 0x18, 0xAE, 0x4F, 0x08, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0xC8, 0x74, 0xCD, 0xE2, + 0xAA, 0x60, 0xB9, 0x78, 0x00, 0x61, 0xA3, 0x60, 0xF4, 0x78, 0xFF, 0xFF, 0xAB, 0x60, 0xE8, 0x78, + 0xFF, 0xFF, 0x21, 0x46, 0x5C, 0x44, 0x26, 0x44, 0x02, 0x26, 0x01, 0x00, 0x3E, 0x46, 0x09, 0xF2, + 0x46, 0x41, 0x66, 0x40, 0xF3, 0x18, 0x40, 0x5E, 0xFD, 0xFB, 0x02, 0x64, 0x40, 0x46, 0x41, 0x5D, + 0x00, 0x64, 0x31, 0xFA, 0x00, 0xF2, 0x46, 0x45, 0x87, 0xFC, 0xAC, 0xE2, 0x01, 0x64, 0x33, 0xFB, + 0x32, 0x40, 0x01, 0x2A, 0x21, 0x00, 0x19, 0xF3, 0x01, 0x60, 0x1E, 0xE1, 0x1D, 0x18, 0x80, 0x64, + 0x40, 0x49, 0x00, 0xE1, 0x19, 0xFF, 0x08, 0x64, 0x2A, 0xFA, 0x5A, 0xDA, 0x2C, 0xFA, 0x5A, 0xDA, + 0x5A, 0xDA, 0xF1, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xF1, 0xFB, 0x72, 0x44, 0x24, 0xFA, 0xB2, 0xF3, + 0x25, 0xFA, 0xA1, 0xFF, 0xFF, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, + 0x7C, 0x4B, 0xA3, 0x60, 0xF4, 0x78, 0xFF, 0xFF, 0x01, 0xE1, 0x01, 0x60, 0x1A, 0xE1, 0x3F, 0x60, + 0xCF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x2E, 0x44, 0x00, 0x36, 0x48, 0x00, 0x01, 0x3A, 0xE5, 0x00, + 0x88, 0xFF, 0x40, 0x67, 0x29, 0x45, 0x34, 0x89, 0x04, 0x64, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, + 0xA1, 0xFF, 0x6C, 0x45, 0x65, 0x44, 0x0F, 0xB4, 0x40, 0x45, 0x1C, 0xFA, 0x65, 0x44, 0x29, 0x41, + 0xF9, 0x81, 0x52, 0x4A, 0x71, 0x89, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x83, 0x1D, 0xFC, + 0x1B, 0xFC, 0x10, 0x60, 0x00, 0x65, 0x29, 0x44, 0x34, 0x89, 0x50, 0x4B, 0x67, 0x50, 0x69, 0xE2, + 0xB6, 0xF1, 0xFC, 0xA3, 0xD3, 0x80, 0x43, 0x43, 0x03, 0x04, 0xAB, 0x60, 0xDE, 0x78, 0xFF, 0xFF, + 0x09, 0x7C, 0xD3, 0x80, 0x9A, 0xFF, 0x03, 0x07, 0xAB, 0x60, 0xDE, 0x78, 0xFF, 0xFF, 0x25, 0x44, + 0x01, 0x26, 0x0F, 0xAC, 0x26, 0x60, 0x4A, 0x65, 0x44, 0xD3, 0x12, 0x65, 0x45, 0x46, 0x60, 0x47, + 0x40, 0x7F, 0x27, 0xFA, 0x8F, 0xFC, 0x18, 0x61, 0xEA, 0xF1, 0xA1, 0xFF, 0x6C, 0x44, 0xDC, 0x80, + 0xFF, 0xFF, 0x21, 0x03, 0x50, 0xFE, 0xAC, 0x60, 0xC1, 0x78, 0xFF, 0xFF, 0xC8, 0x60, 0x0B, 0x7D, + 0x08, 0x60, 0x00, 0x6B, 0xB5, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xAA, 0x74, 0xCD, 0xE2, 0x01, 0x64, + 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0x01, 0x60, 0x08, 0xE1, 0x05, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, + 0x04, 0x25, 0x8B, 0x00, 0x6C, 0x44, 0x0A, 0x36, 0x07, 0x00, 0x14, 0x36, 0x05, 0x00, 0x37, 0x36, + 0x03, 0x00, 0x6E, 0x36, 0x01, 0x00, 0x81, 0x00, 0x40, 0x45, 0x32, 0x74, 0xA1, 0xFF, 0x1C, 0xFA, + 0x40, 0x4E, 0x8C, 0x44, 0x60, 0x43, 0x1D, 0xFA, 0x01, 0xE1, 0x20, 0x64, 0x3A, 0xDB, 0x2E, 0x44, + 0x14, 0x36, 0x12, 0x00, 0x0A, 0x36, 0x0F, 0x00, 0x63, 0x45, 0xE3, 0x83, 0xE3, 0x83, 0xC7, 0x83, + 0xE3, 0x83, 0xC7, 0x83, 0xFF, 0xFF, 0x37, 0x36, 0x05, 0x00, 0x6E, 0x36, 0x04, 0x00, 0xAC, 0x60, + 0xBF, 0x78, 0xFF, 0xFF, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xFF, 0xFF, 0x80, 0x27, + 0xCF, 0x83, 0x1B, 0xFC, 0x01, 0x64, 0x51, 0xFB, 0xA1, 0xFF, 0x29, 0x41, 0xF9, 0x81, 0x52, 0x4A, + 0x71, 0x89, 0x2E, 0x44, 0x27, 0xFA, 0xB6, 0xF1, 0xFC, 0xA3, 0xD3, 0x80, 0x43, 0x43, 0x03, 0x04, + 0xAB, 0x60, 0xDE, 0x78, 0xFF, 0xFF, 0x9A, 0xFF, 0x54, 0x63, 0x12, 0x64, 0x40, 0x46, 0x8F, 0xFC, + 0x18, 0x61, 0xEA, 0xF1, 0x50, 0xFE, 0x6C, 0x40, 0x9E, 0x15, 0x01, 0x60, 0x08, 0xE1, 0x80, 0xE1, + 0x00, 0x64, 0x33, 0xFB, 0x29, 0x40, 0x50, 0x2B, 0x0F, 0x00, 0x2B, 0x44, 0x70, 0x45, 0xC4, 0x84, + 0xFF, 0xFF, 0x04, 0x24, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, 0x20, 0x29, 0x6D, 0xE2, + 0xEF, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x01, 0x60, 0x18, 0xE1, 0x01, 0x11, 0x12, 0x00, + 0x29, 0x44, 0x20, 0xBC, 0x40, 0x49, 0x01, 0x64, 0x33, 0xFB, 0xB6, 0xFF, 0x00, 0xE1, 0x01, 0x60, + 0x1A, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x40, 0xFC, 0x11, 0x01, 0x60, 0x18, 0xE1, 0xAE, 0x4F, + 0xF7, 0xB4, 0xA0, 0x5E, 0xB5, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, + 0x7C, 0x4B, 0x35, 0xE1, 0xAC, 0xE2, 0xAA, 0x60, 0x46, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0x7F, 0xF3, + 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, 0x21, 0x64, 0x3A, 0xDB, 0xBD, 0x01, + 0xAC, 0xE2, 0x01, 0x64, 0x33, 0xFB, 0x01, 0xE1, 0x3F, 0x60, 0xCF, 0x65, 0x29, 0x44, 0x24, 0x89, + 0x2E, 0x44, 0x00, 0x36, 0x21, 0x00, 0x01, 0x3A, 0xF0, 0x01, 0x88, 0xFF, 0x40, 0x67, 0x29, 0x45, + 0x34, 0x89, 0xA1, 0xFF, 0x6C, 0x45, 0x65, 0x44, 0x0F, 0xB4, 0x40, 0x45, 0x65, 0x44, 0x29, 0x41, + 0xF9, 0x81, 0x52, 0x4A, 0x71, 0x89, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x83, 0x0E, 0x7C, + 0xD3, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0xAB, 0x60, 0xDE, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, 0x6C, 0x44, + 0xDC, 0x80, 0xFF, 0xFF, 0xD2, 0x03, 0x41, 0x00, 0xC8, 0x60, 0x0B, 0x7D, 0x08, 0x60, 0x00, 0x6B, + 0xB5, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xAA, 0x74, 0xCD, 0xE2, 0x01, 0x60, 0x08, 0xE1, 0x05, 0xE1, + 0xA1, 0xFF, 0xFF, 0xFF, 0x04, 0x25, 0xC1, 0x01, 0x6C, 0x44, 0x0A, 0x36, 0x07, 0x00, 0x14, 0x36, + 0x05, 0x00, 0x37, 0x36, 0x03, 0x00, 0x6E, 0x36, 0x01, 0x00, 0xB7, 0x01, 0x40, 0x45, 0x32, 0x74, + 0xA1, 0xFF, 0x40, 0x4E, 0x8C, 0x44, 0x60, 0x43, 0x01, 0xE1, 0x20, 0x64, 0x3A, 0xDB, 0x2E, 0x44, + 0x14, 0x36, 0x09, 0x00, 0x0A, 0x36, 0x07, 0x00, 0x37, 0x36, 0x05, 0x00, 0x6E, 0x36, 0x03, 0x00, + 0xAC, 0x60, 0xBF, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x51, 0xFB, 0xA1, 0xFF, 0x29, 0x41, 0xF9, 0x81, + 0x52, 0x4A, 0x71, 0x89, 0x0E, 0x7C, 0xD3, 0x80, 0x43, 0x43, 0x03, 0x03, 0xAB, 0x60, 0xDE, 0x78, + 0xFF, 0xFF, 0x6C, 0x40, 0xFF, 0xFF, 0x01, 0x15, 0x90, 0x01, 0x12, 0x64, 0x40, 0x46, 0xEA, 0xF1, + 0x50, 0xFE, 0xA1, 0xFF, 0x12, 0x61, 0x8C, 0x44, 0xEB, 0xF0, 0x40, 0x48, 0x8C, 0x44, 0x30, 0xFB, + 0x04, 0x61, 0x50, 0xFE, 0x8C, 0x44, 0xD0, 0x80, 0x8C, 0x44, 0xD4, 0x80, 0x8C, 0x44, 0xEC, 0xF1, + 0x00, 0x65, 0xD0, 0x80, 0x28, 0x44, 0x01, 0x0C, 0x13, 0x00, 0x10, 0x65, 0x60, 0x40, 0xC4, 0x36, + 0x04, 0x00, 0xD4, 0x3A, 0x0D, 0x00, 0x27, 0x40, 0x40, 0x26, 0x30, 0x65, 0x35, 0x84, 0xA1, 0xFF, + 0x8C, 0x44, 0x47, 0xFF, 0x50, 0x4B, 0x67, 0x50, 0x69, 0xE2, 0x6A, 0x44, 0x40, 0x2B, 0x09, 0x15, + 0x2C, 0x60, 0xEC, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x2A, 0x64, 0x3A, 0xDB, + 0x1C, 0x01, 0x29, 0x40, 0x10, 0x26, 0x02, 0x00, 0x04, 0x74, 0xCD, 0xE2, 0x8C, 0x44, 0xB6, 0xFF, + 0xB7, 0xFF, 0x01, 0x60, 0x18, 0xE1, 0x05, 0xE1, 0x00, 0x64, 0x33, 0xFB, 0xA1, 0xFF, 0x6C, 0x44, + 0xA1, 0xFF, 0x6C, 0x44, 0x29, 0x40, 0x40, 0x2B, 0x03, 0x00, 0xB6, 0xFF, 0xA1, 0xFF, 0x6C, 0x44, + 0xA1, 0xFF, 0x02, 0x74, 0x29, 0x44, 0x40, 0x27, 0x05, 0x74, 0xCD, 0xE2, 0xA1, 0xFF, 0xCB, 0xF3, + 0xC4, 0xE2, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0xDC, 0x84, 0xE0, 0x94, 0x26, 0x44, 0x84, 0xBC, + 0x40, 0x46, 0x23, 0x64, 0x3A, 0xDB, 0xB5, 0xFF, 0xBC, 0xFF, 0x47, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, + 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, 0xA9, 0x60, 0x88, 0x78, 0xFF, 0xFF, 0x29, 0x64, + 0x3A, 0xDB, 0xA2, 0xFC, 0x32, 0x40, 0x01, 0x2A, 0xB9, 0x00, 0x01, 0x60, 0x1A, 0xE1, 0x23, 0x43, + 0xA1, 0xFF, 0xEC, 0x44, 0x2A, 0xFA, 0x40, 0x48, 0xA1, 0xFF, 0x7A, 0xDC, 0x7E, 0x36, 0x04, 0xA2, + 0xFC, 0x1C, 0x03, 0x1D, 0x00, 0x64, 0x3F, 0xFA, 0x2E, 0x00, 0x03, 0x2B, 0x04, 0x00, 0xA1, 0xFF, + 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x8F, 0xB0, 0x88, 0x3A, 0x03, 0x00, 0x70, 0x62, 0xA1, 0xFF, + 0x7A, 0xDC, 0x28, 0x40, 0x40, 0x2B, 0x06, 0x00, 0x72, 0x62, 0xA1, 0xFF, 0x7A, 0xDC, 0x7A, 0xDC, + 0x7A, 0xDC, 0x7A, 0xDC, 0x3F, 0xFC, 0x00, 0xF4, 0x10, 0x62, 0x6E, 0x61, 0xA1, 0xFF, 0x05, 0x1D, + 0x12, 0x1E, 0x0C, 0x00, 0x00, 0xF4, 0x7C, 0x61, 0x02, 0x62, 0x7A, 0xDC, 0x63, 0x40, 0xFD, 0x1C, + 0xF9, 0x1D, 0xFF, 0xB1, 0x08, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, 0xB6, 0xFF, 0xB7, 0xFF, + 0xA1, 0xFF, 0x6C, 0x44, 0x5A, 0xDA, 0x98, 0xFF, 0xA1, 0xFF, 0x6C, 0x40, 0xA1, 0xFF, 0x47, 0xFF, + 0x7C, 0x44, 0x33, 0xFB, 0x26, 0x44, 0xFD, 0xB4, 0x84, 0xBC, 0x01, 0x15, 0x7F, 0xB4, 0x40, 0x46, + 0x6C, 0x40, 0xB6, 0xFF, 0xB7, 0xFF, 0xA1, 0xFF, 0x6C, 0x45, 0xA1, 0xFF, 0x7F, 0x60, 0x7F, 0x7C, + 0x6C, 0x44, 0xA0, 0x84, 0x15, 0xA7, 0x15, 0xA4, 0x21, 0x46, 0x26, 0xFA, 0x29, 0x40, 0x40, 0x2B, + 0x07, 0x00, 0xB6, 0xFF, 0x40, 0x60, 0x00, 0x65, 0xA1, 0xFF, 0x6C, 0x44, 0x1A, 0xFA, 0x09, 0x00, + 0x65, 0x44, 0x0F, 0xB4, 0x06, 0xA8, 0x80, 0x60, 0x00, 0x65, 0x08, 0x28, 0x7C, 0x45, 0x29, 0x44, + 0x34, 0x89, 0x27, 0xF0, 0x65, 0x44, 0x64, 0x5E, 0x27, 0xFA, 0x81, 0xE1, 0x01, 0x60, 0x18, 0xE1, + 0x01, 0x11, 0x12, 0x00, 0x29, 0x44, 0x20, 0xBC, 0x40, 0x49, 0x01, 0x64, 0x33, 0xFB, 0xB6, 0xFF, + 0x00, 0xE1, 0x01, 0x60, 0x1A, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x40, 0xFC, 0x11, 0x01, 0x60, + 0x18, 0xE1, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, 0x00, 0x70, 0x00, 0x64, 0x40, 0x4B, 0x21, 0x46, + 0xB5, 0xFF, 0xBC, 0xFF, 0x47, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, + 0x7C, 0x4B, 0x28, 0x44, 0x04, 0x27, 0x09, 0x00, 0xD4, 0x36, 0x04, 0x00, 0x0C, 0x22, 0x02, 0x00, + 0x0C, 0x3A, 0x03, 0x00, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, 0x2A, 0x44, 0x72, 0x45, 0x24, 0xFA, + 0xB2, 0xF3, 0x06, 0x04, 0xE4, 0xE2, 0xDC, 0x9C, 0x29, 0x40, 0x01, 0x26, 0x64, 0x44, 0xB2, 0xF9, + 0x25, 0xFA, 0xB3, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB3, 0xFB, 0x28, 0xFA, 0xB4, 0xF3, 0x02, 0x04, + 0xDC, 0x84, 0xB4, 0xFB, 0x29, 0xFA, 0xA9, 0x60, 0x88, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, 0x19, 0x60, + 0xA3, 0xF3, 0x12, 0x61, 0x60, 0x40, 0x01, 0x2A, 0x08, 0x00, 0x00, 0x64, 0x3B, 0xFA, 0xBF, 0x60, + 0xFF, 0x65, 0x8C, 0x44, 0x3D, 0xFA, 0xA4, 0x84, 0x01, 0x00, 0x8C, 0x44, 0xEB, 0xF0, 0x2A, 0xFA, + 0x40, 0x48, 0x04, 0x26, 0x48, 0x00, 0xA1, 0xFF, 0x8C, 0x44, 0x5A, 0xDA, 0x30, 0xFB, 0x6C, 0x44, + 0x2C, 0xFA, 0xFF, 0xFF, 0x01, 0x26, 0x2B, 0x00, 0xD0, 0x80, 0xA1, 0xFF, 0x8C, 0x44, 0x6C, 0x5C, + 0x00, 0xE1, 0xF2, 0xFE, 0x2D, 0xFA, 0xEC, 0xF3, 0xD4, 0x80, 0xD0, 0x80, 0x2E, 0xF8, 0x24, 0x44, + 0x16, 0x0C, 0x32, 0x40, 0x02, 0x2A, 0x07, 0x00, 0x28, 0x42, 0x0C, 0xB2, 0x08, 0x3A, 0x03, 0x00, + 0x10, 0xBC, 0x40, 0x44, 0x61, 0x00, 0x04, 0x0A, 0xA1, 0xFF, 0xAB, 0x60, 0xE7, 0x78, 0xFF, 0xFF, + 0x11, 0xBC, 0x40, 0x44, 0x28, 0x45, 0xBF, 0x60, 0xFF, 0x64, 0x24, 0x88, 0x55, 0x00, 0x30, 0xBC, + 0x40, 0x44, 0x22, 0xF0, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x4D, 0x00, 0x20, 0xB9, + 0x5C, 0x8E, 0xA1, 0xFF, 0x8C, 0x44, 0x2D, 0xFA, 0xDC, 0x9C, 0x6C, 0x44, 0x00, 0xE1, 0xF2, 0xFE, + 0x2E, 0xFA, 0x08, 0x28, 0x44, 0x4E, 0xDC, 0x84, 0x2E, 0x5C, 0xB0, 0x84, 0xEF, 0xB1, 0x08, 0x24, + 0x40, 0xB9, 0x41, 0x46, 0x39, 0x00, 0x23, 0x41, 0x13, 0x64, 0x51, 0x90, 0x56, 0x63, 0x03, 0x04, + 0xAB, 0x60, 0xDE, 0x78, 0xFF, 0xFF, 0x8C, 0x44, 0x04, 0x61, 0x2B, 0xFA, 0x50, 0xFE, 0x80, 0x27, + 0x00, 0x64, 0x30, 0xFB, 0x8C, 0x44, 0x2C, 0xFA, 0xD0, 0x80, 0x8C, 0x44, 0x2D, 0xFA, 0xD4, 0x80, + 0x00, 0x65, 0x8C, 0x44, 0xEC, 0xF1, 0x2E, 0xFA, 0xD0, 0x80, 0x28, 0x44, 0x03, 0x0C, 0xA0, 0x2A, + 0x0A, 0x00, 0x11, 0x00, 0x10, 0x65, 0x60, 0x40, 0xC4, 0x36, 0x04, 0x00, 0xD4, 0x3A, 0x08, 0x00, + 0x27, 0x40, 0x40, 0x26, 0x30, 0x65, 0x00, 0x64, 0x3F, 0xFA, 0x46, 0x4E, 0x35, 0x84, 0x64, 0x00, + 0x40, 0x26, 0xF9, 0x01, 0x30, 0x65, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x04, 0x61, 0xF3, 0x01, + 0xA1, 0xFF, 0xAB, 0x60, 0xA5, 0x78, 0xFF, 0xFF, 0xFF, 0x60, 0xFE, 0x65, 0x23, 0x43, 0xE8, 0xA3, + 0x80, 0x27, 0xF6, 0x01, 0x20, 0xE6, 0x08, 0x60, 0x00, 0xEB, 0x28, 0x44, 0x03, 0x2B, 0x05, 0x00, + 0x6A, 0x62, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x28, 0x44, 0x8F, 0xB0, 0x88, 0x3A, 0x03, 0x00, + 0x70, 0x62, 0x7A, 0xDC, 0x28, 0x44, 0x40, 0x2B, 0x0D, 0x00, 0x72, 0x62, 0x7A, 0xDC, 0xA1, 0xFF, + 0x6C, 0x5C, 0x5A, 0xD8, 0xE4, 0x40, 0x20, 0x2B, 0x03, 0x00, 0x7A, 0xDC, 0x7A, 0xDC, 0xF8, 0xA3, + 0x25, 0xFF, 0xB0, 0xFF, 0x3F, 0xFC, 0x00, 0xF4, 0x10, 0x62, 0x10, 0x61, 0x57, 0x90, 0x6C, 0x61, + 0xA1, 0xFF, 0x09, 0x07, 0x02, 0x1D, 0x28, 0x1E, 0x1F, 0x00, 0xCB, 0x83, 0x7A, 0xDC, 0xFE, 0x1C, + 0xD9, 0x81, 0x22, 0x1E, 0x19, 0x00, 0xCB, 0x83, 0x0E, 0xA3, 0xA7, 0x84, 0xF2, 0xA3, 0x7A, 0xDC, + 0xFE, 0x1C, 0x03, 0x1D, 0x7C, 0xA8, 0xD9, 0x81, 0x0A, 0x02, 0x00, 0xF4, 0x02, 0x62, 0xA7, 0x84, + 0x7A, 0x61, 0x7A, 0xDC, 0xFE, 0x1C, 0xF9, 0x1D, 0x7C, 0xA8, 0xD9, 0x81, 0xF6, 0x03, 0xFF, 0xB1, + 0x0B, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, 0xA1, 0xFF, 0xFF, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, + 0x6C, 0x44, 0x5A, 0xDA, 0xCD, 0x81, 0x64, 0x40, 0x46, 0x45, 0x28, 0x44, 0x40, 0x2B, 0x0E, 0x00, + 0x64, 0x40, 0x20, 0x2B, 0x0B, 0x00, 0x01, 0xA2, 0x62, 0x44, 0x46, 0x45, 0x21, 0x46, 0x00, 0xF4, + 0x02, 0x62, 0x9A, 0xFF, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x01, 0x60, 0x18, 0xE1, + 0x24, 0x76, 0xAD, 0xE2, 0x41, 0xE1, 0x98, 0xFF, 0x00, 0xE6, 0x01, 0xF2, 0x61, 0x45, 0xD4, 0x9E, + 0x21, 0x46, 0x16, 0xFA, 0x25, 0x44, 0x06, 0xFA, 0xA1, 0xFF, 0x8C, 0x44, 0xA1, 0xFF, 0x47, 0xFF, + 0x29, 0x40, 0x50, 0x2B, 0x06, 0x00, 0x2B, 0x44, 0x1C, 0x60, 0x11, 0xFB, 0x70, 0x45, 0x44, 0x8B, + 0x01, 0x00, 0x50, 0x4B, 0x67, 0x50, 0x69, 0xE2, 0x25, 0x46, 0x01, 0xF2, 0x61, 0x45, 0xD4, 0x9E, + 0x21, 0x46, 0x16, 0xFA, 0x25, 0x45, 0x86, 0xF8, 0xFF, 0xFF, 0x6A, 0x44, 0x40, 0x2B, 0x03, 0x15, + 0xAF, 0x60, 0xF3, 0x78, 0xFF, 0xFF, 0x29, 0x40, 0x10, 0x26, 0x04, 0x00, 0x04, 0x74, 0xCD, 0xE2, + 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x44, 0xB6, 0xFF, 0xB7, 0xFF, 0xC4, 0xE2, 0x01, 0x60, 0x18, 0xE1, + 0x05, 0x76, 0xAD, 0xE2, 0x41, 0xE1, 0xA1, 0xFF, 0x6C, 0x45, 0xA1, 0xFF, 0x65, 0x41, 0x7F, 0x60, + 0x7F, 0x7C, 0x6C, 0x44, 0xA0, 0x84, 0x15, 0xA7, 0x15, 0xA4, 0x21, 0x46, 0x26, 0xFA, 0x22, 0x46, + 0x10, 0xFA, 0x21, 0x46, 0x29, 0x40, 0x40, 0x2B, 0x07, 0x00, 0xB6, 0xFF, 0xA1, 0xFF, 0x40, 0x60, + 0x00, 0x65, 0x6C, 0x44, 0x1A, 0xFA, 0x09, 0x00, 0x65, 0x44, 0x0F, 0xB4, 0x06, 0xA8, 0x80, 0x60, + 0x00, 0x65, 0x08, 0x28, 0x7C, 0x45, 0x29, 0x44, 0x34, 0x89, 0x00, 0x64, 0x33, 0xFB, 0x40, 0x21, + 0x00, 0x00, 0xAC, 0xE2, 0x05, 0xE1, 0x27, 0xF0, 0x65, 0x44, 0x64, 0x5E, 0x27, 0xFA, 0x28, 0x44, + 0x8F, 0xB0, 0x88, 0x3A, 0x09, 0x00, 0x39, 0xF2, 0xFF, 0xFF, 0x60, 0xB0, 0x20, 0x3A, 0x04, 0x00, + 0x24, 0x44, 0xFF, 0x60, 0xDF, 0xB4, 0x40, 0x44, 0x28, 0x40, 0x03, 0x26, 0xE2, 0x00, 0x31, 0x40, + 0x20, 0x2A, 0x03, 0x00, 0x28, 0x40, 0x50, 0x3A, 0xDC, 0x00, 0x24, 0x44, 0x20, 0x2A, 0xD9, 0x00, + 0x29, 0x40, 0x50, 0x2B, 0x0D, 0x00, 0xEF, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x31, 0x40, + 0x08, 0x2A, 0x06, 0x00, 0x1C, 0x60, 0x11, 0xF3, 0xFF, 0xFF, 0xE0, 0x85, 0x2B, 0x44, 0x06, 0x05, + 0x2B, 0x44, 0xFF, 0xA4, 0x01, 0xA4, 0x04, 0x24, 0x00, 0x64, 0x40, 0x4B, 0xAC, 0x80, 0x28, 0x40, + 0xB4, 0x3A, 0x03, 0x00, 0x02, 0x03, 0x30, 0xFB, 0xBC, 0x00, 0x28, 0x44, 0xBF, 0x60, 0xFF, 0x65, + 0xA4, 0x84, 0x40, 0x48, 0x2B, 0x50, 0xA1, 0xFF, 0xFF, 0xFF, 0x01, 0x60, 0x08, 0xE1, 0x1C, 0xF2, + 0xC4, 0xE2, 0x40, 0x45, 0x28, 0x40, 0xC4, 0x36, 0x9C, 0x00, 0x29, 0x40, 0x40, 0x2B, 0x48, 0x00, + 0x32, 0x60, 0xFA, 0x63, 0x60, 0x40, 0x0B, 0x36, 0x20, 0x00, 0x0F, 0x36, 0x1B, 0x00, 0x0A, 0x36, + 0x16, 0x00, 0x0E, 0x36, 0x11, 0x00, 0x09, 0x36, 0x0C, 0x00, 0x0D, 0x36, 0x07, 0x00, 0x08, 0x36, + 0x02, 0x00, 0xA3, 0xD3, 0x15, 0x00, 0x02, 0xA3, 0xA3, 0xD3, 0x12, 0x00, 0x04, 0xA3, 0xA3, 0xD3, + 0x0F, 0x00, 0x06, 0xA3, 0xA3, 0xD3, 0x0C, 0x00, 0x08, 0xA3, 0xA3, 0xD3, 0x09, 0x00, 0x0A, 0xA3, + 0xA3, 0xD3, 0x06, 0x00, 0x0C, 0xA3, 0xA3, 0xD3, 0x03, 0x00, 0x0E, 0xA3, 0xA3, 0xD3, 0xFF, 0xFF, + 0x2C, 0x60, 0x7C, 0x63, 0x60, 0x40, 0x0C, 0x36, 0x19, 0x00, 0x08, 0x36, 0x15, 0x00, 0x0D, 0x36, + 0x11, 0x00, 0x09, 0x36, 0x0D, 0x00, 0x0E, 0x36, 0x09, 0x00, 0x0A, 0x36, 0x05, 0x00, 0x0F, 0x36, + 0x01, 0x00, 0x39, 0x00, 0x02, 0xA3, 0x37, 0x00, 0x04, 0xA3, 0x35, 0x00, 0x06, 0xA3, 0x33, 0x00, + 0x08, 0xA3, 0x31, 0x00, 0x0A, 0xA3, 0x2F, 0x00, 0x0C, 0xA3, 0x2D, 0x00, 0x0E, 0xA3, 0x2B, 0x00, + 0x33, 0x60, 0x0A, 0x63, 0x25, 0x44, 0x0A, 0x36, 0x0C, 0x00, 0x14, 0x36, 0x07, 0x00, 0x37, 0x36, + 0x02, 0x00, 0xA3, 0xD3, 0x09, 0x00, 0x02, 0xA3, 0xA3, 0xD3, 0x06, 0x00, 0x04, 0xA3, 0xA3, 0xD3, + 0x03, 0x00, 0x06, 0xA3, 0xA3, 0xD3, 0xFF, 0xFF, 0x40, 0x45, 0x0A, 0x36, 0x0D, 0x00, 0x14, 0x36, + 0x38, 0x64, 0x37, 0x3A, 0x03, 0x00, 0x04, 0x7F, 0x40, 0x45, 0x15, 0x64, 0x6E, 0x3A, 0x09, 0x00, + 0x84, 0x7F, 0x40, 0x45, 0x0B, 0x64, 0x05, 0x00, 0x29, 0x44, 0x7F, 0x60, 0xFF, 0xB4, 0x40, 0x49, + 0x70, 0x64, 0x40, 0x4D, 0x02, 0x00, 0x40, 0x45, 0x0A, 0x00, 0x2C, 0x60, 0x74, 0x63, 0x0A, 0x36, + 0x06, 0x00, 0x14, 0x36, 0x02, 0xA3, 0x37, 0x36, 0x04, 0xA3, 0x6E, 0x36, 0x06, 0xA3, 0x28, 0xA3, + 0xA3, 0xD1, 0xD8, 0xA3, 0x19, 0x60, 0x55, 0xF9, 0x39, 0xF1, 0xA3, 0xD1, 0x64, 0x41, 0x64, 0x5E, + 0x60, 0x45, 0x64, 0x47, 0x1F, 0xB4, 0x54, 0x94, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, 0x02, 0x00, + 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, 0xB4, 0x85, 0x29, 0x44, 0xC0, 0x60, 0x00, 0xB4, 0xB4, 0x84, + 0x1F, 0xFA, 0xB5, 0xFF, 0xA1, 0xFF, 0xCB, 0xF3, 0xC4, 0xE2, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, + 0xDC, 0x84, 0xE0, 0x94, 0xFF, 0x60, 0xCF, 0x65, 0x29, 0x44, 0x24, 0x89, 0xA5, 0x60, 0x88, 0x78, + 0x04, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0xC4, 0xE2, 0xA1, 0xFF, 0xFF, 0x60, 0xCF, 0x65, 0x29, 0x44, + 0x24, 0x89, 0xCB, 0xF3, 0xC4, 0xE2, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0xDC, 0x84, 0xE0, 0x94, + 0x26, 0x44, 0x84, 0xBC, 0x24, 0x40, 0x0C, 0x22, 0xFD, 0xB4, 0x40, 0x46, 0x23, 0x64, 0x3A, 0xDB, + 0xAD, 0x60, 0x4F, 0x78, 0xFF, 0xFF, 0x27, 0x40, 0x26, 0x22, 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, + 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x29, 0x40, 0x10, 0x26, 0x02, 0x00, 0x04, 0x74, 0xCD, 0xE2, + 0x01, 0x60, 0x18, 0xE1, 0x01, 0x60, 0x18, 0xE1, 0x01, 0x11, 0x12, 0x00, 0x29, 0x44, 0x20, 0xBC, + 0x40, 0x49, 0x01, 0x64, 0x33, 0xFB, 0xB6, 0xFF, 0x00, 0xE1, 0x01, 0x60, 0x1A, 0xE1, 0xA1, 0xFF, + 0xFF, 0xFF, 0x6C, 0x40, 0xFC, 0x11, 0x01, 0x60, 0x18, 0xE1, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, + 0xB5, 0xFF, 0x47, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, + 0x29, 0x40, 0x50, 0x2B, 0x1B, 0x00, 0x31, 0x40, 0x08, 0x2A, 0x0D, 0x00, 0x1C, 0x60, 0x11, 0xF3, + 0xFF, 0xFF, 0xE0, 0x85, 0x2B, 0x44, 0x07, 0x04, 0x70, 0x45, 0xC4, 0x84, 0xEF, 0x60, 0xFF, 0x65, + 0x29, 0x44, 0x24, 0x89, 0x11, 0x00, 0x2B, 0x44, 0x70, 0x45, 0xC4, 0x84, 0xFF, 0xFF, 0x04, 0x24, + 0x00, 0xB4, 0x40, 0x4B, 0xEF, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x37, 0xF3, 0x2B, 0x45, + 0xD4, 0x80, 0xFF, 0xFF, 0x02, 0x28, 0x65, 0x44, 0x60, 0x50, 0xA0, 0x4C, 0x20, 0xBC, 0xFF, 0xB4, + 0xA0, 0x51, 0x00, 0x60, 0x2E, 0x7C, 0x74, 0x44, 0xC0, 0x94, 0x32, 0x40, 0x02, 0x2A, 0x19, 0x00, + 0x28, 0x44, 0xA4, 0x36, 0x03, 0x00, 0x0C, 0xB4, 0x04, 0x36, 0x13, 0x00, 0x26, 0x43, 0xFD, 0xB3, + 0x04, 0xBB, 0x43, 0x46, 0x01, 0x2A, 0x03, 0x00, 0x28, 0x47, 0x40, 0xBF, 0x40, 0x48, 0x0A, 0xBB, + 0x0F, 0xFC, 0x50, 0x4B, 0x67, 0x50, 0x00, 0x64, 0x30, 0xFB, 0x05, 0xFF, 0xAD, 0x60, 0x4F, 0x78, + 0xFF, 0xFF, 0x24, 0x64, 0x3A, 0xDB, 0x28, 0x44, 0x04, 0x2A, 0x03, 0x00, 0xA3, 0x60, 0xE7, 0x78, + 0xFF, 0xFF, 0x32, 0x40, 0x04, 0x2A, 0x1C, 0x00, 0x28, 0x44, 0x0C, 0xB0, 0x08, 0x3A, 0x18, 0x00, + 0x2C, 0xF0, 0x22, 0xF0, 0x64, 0x40, 0x01, 0x26, 0x0B, 0x00, 0x64, 0x40, 0x40, 0x2B, 0x10, 0x00, + 0x8F, 0xB0, 0x88, 0x3A, 0x0D, 0x00, 0x39, 0xF2, 0xFF, 0xFF, 0x60, 0xB0, 0x20, 0x3A, 0x08, 0x00, + 0x26, 0x44, 0xFD, 0xB4, 0x04, 0xBC, 0x40, 0x46, 0xFC, 0xB4, 0x0F, 0xFA, 0x05, 0xFF, 0x01, 0x00, + 0x1D, 0xFF, 0x01, 0xE2, 0x26, 0x40, 0x10, 0x2A, 0x06, 0x00, 0x2C, 0x60, 0xEA, 0x64, 0xF1, 0x60, + 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0xA3, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0x03, 0x0A, 0xA3, 0x60, + 0xF4, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x51, 0xFB, 0x1B, 0x60, 0xEE, 0xF3, 0xFF, 0xFF, 0x04, 0x18, + 0xAE, 0x4F, 0x08, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0xE1, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, + 0x54, 0x62, 0x22, 0x46, 0xA2, 0xD0, 0x16, 0x63, 0x7C, 0x41, 0x44, 0x48, 0x80, 0x36, 0x04, 0x61, + 0x28, 0x40, 0x50, 0x36, 0x04, 0x61, 0x41, 0x4E, 0x28, 0x44, 0xA4, 0x36, 0x0E, 0x63, 0x9A, 0xFF, + 0xA1, 0xFF, 0x19, 0x60, 0xA3, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x06, 0x00, 0x3D, 0xF2, + 0xAA, 0xF0, 0xFF, 0xFF, 0xB4, 0x84, 0x08, 0x36, 0x2A, 0xFA, 0x12, 0x74, 0xCD, 0xE2, 0x54, 0x62, + 0xA2, 0xD2, 0xFF, 0xFF, 0x6A, 0x40, 0x80, 0x4E, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, + 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, + 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0xFF, 0xFF, 0x01, 0x1D, 0xB2, 0x00, 0x7A, 0xD4, 0x12, 0x74, + 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x28, 0x40, 0x03, 0x2B, + 0x06, 0x00, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x70, 0x62, + 0x28, 0x44, 0x8F, 0xB0, 0x88, 0x3A, 0x02, 0x00, 0x7A, 0xD4, 0x12, 0x74, 0x28, 0x40, 0x40, 0x2B, + 0x16, 0x00, 0x72, 0x62, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD2, 0x12, 0x74, 0x80, 0x4C, 0x20, 0x2B, + 0x05, 0x00, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x22, 0xF2, 0xFF, 0xFF, + 0x60, 0x40, 0x10, 0x26, 0x04, 0x00, 0x26, 0x26, 0x4D, 0x00, 0x26, 0x27, 0x4B, 0x00, 0x23, 0x43, + 0xFF, 0xFF, 0x06, 0x1D, 0x2E, 0x1E, 0x00, 0x00, 0x03, 0xF0, 0x04, 0xF4, 0x64, 0x42, 0x3D, 0x00, + 0x2E, 0x40, 0x04, 0x2A, 0x27, 0x00, 0xA1, 0xFF, 0x02, 0xFE, 0x10, 0x25, 0x42, 0xFE, 0x12, 0x74, + 0x72, 0x45, 0x65, 0x4C, 0xB2, 0xF3, 0x03, 0x04, 0xE4, 0xE2, 0xDC, 0x84, 0xB2, 0xFB, 0xA1, 0xFF, + 0x12, 0x74, 0x80, 0x4C, 0x12, 0x74, 0xB3, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB3, 0xFB, 0x80, 0x4C, + 0x12, 0x74, 0xB4, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB4, 0xFB, 0x80, 0x4C, 0x12, 0x74, 0x5C, 0x4E, + 0xF8, 0xA3, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, 0xFF, 0xB1, 0xF8, 0xA1, 0x06, 0xA4, 0x60, 0x42, + 0x0A, 0x00, 0x4E, 0x00, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, 0xC8, 0x82, 0xFF, 0xB1, 0x03, 0x00, + 0x00, 0xF4, 0x81, 0xF2, 0xFF, 0xB1, 0x7A, 0xD4, 0x12, 0x74, 0xFD, 0x1C, 0xF9, 0x1D, 0xFF, 0xB1, + 0x1B, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0xDA, 0x82, 0xDA, 0x82, 0xA2, 0xD2, 0xA1, 0xFF, 0x09, 0x74, + 0x60, 0x4D, 0x12, 0x00, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, 0x23, 0x43, 0xA1, 0xFF, 0x12, 0x74, + 0xA0, 0xD2, 0xFE, 0xA1, 0xCB, 0x83, 0x60, 0x4E, 0xAF, 0x83, 0x03, 0x1D, 0x05, 0x03, 0x12, 0x74, + 0xEB, 0x01, 0xA1, 0xFF, 0x12, 0x74, 0xDF, 0x01, 0x12, 0x74, 0xDA, 0x83, 0x66, 0x44, 0x22, 0x46, + 0x0C, 0xFA, 0x22, 0xF2, 0x0B, 0xFC, 0x28, 0x40, 0x40, 0x2B, 0x1A, 0x00, 0x10, 0x26, 0x04, 0x00, + 0x26, 0x26, 0x0F, 0x00, 0x26, 0x27, 0x0D, 0x00, 0x00, 0xF4, 0x02, 0x62, 0xA1, 0xFF, 0x12, 0x74, + 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, + 0x07, 0x00, 0xA1, 0xFF, 0x12, 0x74, 0x9C, 0x4E, 0x12, 0x74, 0x9C, 0x4C, 0x12, 0x74, 0x00, 0x00, + 0x88, 0xFF, 0xA1, 0xFF, 0xB2, 0x60, 0x58, 0x4F, 0x2D, 0x78, 0xFF, 0xFF, 0x01, 0x60, 0x18, 0xE1, + 0x78, 0x44, 0x02, 0xA4, 0x35, 0xFB, 0xCC, 0x00, 0x29, 0x44, 0xF7, 0xB4, 0x40, 0x49, 0x34, 0x64, + 0x3A, 0xDB, 0x44, 0xE1, 0xA5, 0x60, 0x54, 0x78, 0xFF, 0xFF, 0x00, 0x6B, 0xBC, 0xFF, 0x15, 0xF3, + 0xFF, 0xFF, 0xDC, 0x84, 0x15, 0xFB, 0x78, 0x5C, 0x07, 0x00, 0x78, 0x5C, 0x2F, 0x00, 0x62, 0xFF, + 0xFF, 0xFF, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x80, 0x60, 0x01, 0xE0, 0xD5, 0x60, 0x84, 0xE7, + 0xA1, 0xF3, 0x40, 0x60, 0x60, 0x40, 0x01, 0x23, 0x48, 0x60, 0x5E, 0x65, 0x80, 0x60, 0x00, 0x6A, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, + 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x80, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, + 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x01, 0x6A, 0xFF, 0xFF, + 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x64, 0x58, 0xFF, 0xFF, 0x80, 0x60, 0x01, 0xE0, + 0xD5, 0x60, 0x84, 0xE7, 0xA1, 0xF3, 0x7C, 0x45, 0x60, 0x40, 0x01, 0x23, 0x02, 0x65, 0x8C, 0x60, + 0x48, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, + 0xFE, 0x01, 0x00, 0x60, 0x7F, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x48, 0x60, 0x08, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, + 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, + 0xFE, 0x01, 0x40, 0x60, 0x08, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, + 0x01, 0x16, 0xFE, 0x01, 0x8C, 0x60, 0x48, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, + 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, + 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x64, 0x58, 0xFF, 0xFF, 0x12, 0x74, 0x6A, 0x40, 0x87, 0x4F, + 0x12, 0x74, 0x87, 0x4C, 0x12, 0x74, 0x29, 0x40, 0x40, 0x2B, 0x08, 0x00, 0x0A, 0x64, 0x89, 0xFF, + 0x60, 0x54, 0x88, 0xFF, 0x87, 0x4D, 0x12, 0x74, 0x87, 0x4D, 0x09, 0x00, 0x03, 0x64, 0x89, 0xFF, + 0x60, 0x54, 0x88, 0xFF, 0x87, 0x4F, 0x12, 0x74, 0x87, 0x4D, 0x12, 0x74, 0x87, 0x4D, 0x7C, 0x44, + 0x01, 0x08, 0x01, 0x00, 0x67, 0x44, 0x12, 0x74, 0x87, 0x4C, 0x12, 0x74, 0x87, 0x4C, 0x12, 0x74, + 0x87, 0x4C, 0x12, 0x74, 0x87, 0x4D, 0x12, 0x74, 0x87, 0x4D, 0x12, 0x74, 0x87, 0x4D, 0x12, 0x74, + 0x04, 0x21, 0x04, 0x00, 0xFF, 0x2A, 0x01, 0x00, 0x04, 0x00, 0x03, 0x00, 0xFF, 0x2A, 0x0D, 0x00, + 0x0C, 0x00, 0xBC, 0xFF, 0x61, 0xFF, 0x78, 0x5C, 0x57, 0x01, 0x78, 0x5C, 0x7F, 0x01, 0xB6, 0xFF, + 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, 0x6A, 0x44, 0x2F, 0x58, 0xFF, 0xFF, + 0x04, 0x74, 0xC4, 0xE2, 0x04, 0xE1, 0x29, 0x40, 0x40, 0x2B, 0x05, 0x00, 0xA1, 0xFF, 0xFF, 0xFF, + 0xBC, 0xFF, 0x14, 0x74, 0x01, 0x00, 0x04, 0x74, 0xC4, 0xE2, 0x04, 0xE1, 0xBC, 0xFF, 0xB5, 0xFF, + 0x47, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, 0x29, 0x40, + 0x40, 0x27, 0x04, 0x00, 0xC2, 0x60, 0x58, 0x4F, 0xBA, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, 0x29, 0x40, + 0x10, 0x26, 0x6D, 0x00, 0x80, 0x60, 0x01, 0xE0, 0xD5, 0x60, 0x84, 0xE7, 0xA1, 0xF3, 0x40, 0x60, + 0x60, 0x40, 0x01, 0x23, 0x48, 0x60, 0x5E, 0x65, 0x80, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, + 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, + 0x01, 0x16, 0xFE, 0x01, 0x80, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x01, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, + 0x95, 0x60, 0x84, 0xE7, 0x80, 0x60, 0x01, 0xE0, 0xD5, 0x60, 0x84, 0xE7, 0xA1, 0xF3, 0x7C, 0x45, + 0x60, 0x40, 0x01, 0x23, 0x02, 0x65, 0x8C, 0x60, 0x48, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, + 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x7F, 0x6A, 0xFF, 0xFF, + 0x01, 0x16, 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x48, 0x60, + 0x08, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, + 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x40, 0x60, 0x08, 0x6A, 0xFF, 0xFF, + 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x8C, 0x60, 0x48, 0x6A, + 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, + 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x01, 0x60, + 0x08, 0xE1, 0xFF, 0xFF, 0xC4, 0xE2, 0x29, 0x40, 0x40, 0x2B, 0x04, 0x00, 0xC2, 0x60, 0x58, 0x4F, + 0xBA, 0x78, 0xFF, 0xFF, 0xC2, 0x60, 0x58, 0x4F, 0xC5, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, 0xCB, 0xF3, + 0xC4, 0xE2, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0xDC, 0x84, 0xE0, 0x94, 0x35, 0xF7, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x01, 0x10, 0x61, 0x7F, 0x60, 0xC0, 0x64, 0xA0, 0x80, 0x7F, 0x67, 0x02, 0x63, + 0x25, 0x02, 0x98, 0xFE, 0x19, 0x05, 0x12, 0x60, 0xFC, 0xF5, 0x0E, 0xF2, 0x15, 0x18, 0x02, 0x18, + 0x09, 0xF4, 0xFB, 0x01, 0x23, 0x44, 0x00, 0xA8, 0x08, 0x7E, 0x0A, 0x02, 0x66, 0x44, 0x11, 0xFB, + 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x28, 0xB9, 0x10, 0x7E, + 0x00, 0x7F, 0x0E, 0xFA, 0x00, 0x67, 0x0A, 0x00, 0x20, 0x44, 0xDC, 0x85, 0x0F, 0xB4, 0xFB, 0xA0, + 0x7F, 0x67, 0x07, 0x63, 0x03, 0x05, 0x45, 0x40, 0x00, 0x67, 0xD8, 0xFE, 0xFF, 0x27, 0x05, 0xFD, + 0x0A, 0x7E, 0x04, 0xFB, 0x61, 0x55, 0x48, 0x00, 0x28, 0xFB, 0x01, 0xF3, 0x29, 0xFB, 0x44, 0x46, + 0x40, 0x45, 0x10, 0x61, 0x7E, 0x60, 0xC0, 0x64, 0xA0, 0x80, 0x7F, 0x67, 0x02, 0x63, 0x30, 0x02, + 0xB5, 0x60, 0x58, 0x4F, 0xCE, 0x78, 0xFF, 0xFF, 0x7F, 0x67, 0x03, 0x63, 0x29, 0x02, 0x26, 0x40, + 0x01, 0x2B, 0x23, 0x00, 0x98, 0xFE, 0x18, 0x05, 0x12, 0x60, 0xFC, 0xF5, 0x0E, 0xF2, 0x14, 0x18, + 0x02, 0x18, 0x09, 0xF4, 0xFB, 0x01, 0x23, 0x44, 0x00, 0xA8, 0x08, 0x7E, 0x0A, 0x02, 0x66, 0x44, + 0x11, 0xFB, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x08, 0xB9, + 0x10, 0x7E, 0x00, 0x7F, 0x0E, 0xFA, 0x09, 0x00, 0x20, 0x44, 0xDC, 0x85, 0x0F, 0xB4, 0xFB, 0xA0, + 0x7F, 0x67, 0x07, 0x63, 0x05, 0x05, 0x45, 0x40, 0xD8, 0xFE, 0x00, 0x67, 0xD0, 0xFE, 0xD9, 0xFE, + 0xFF, 0x27, 0x05, 0xFD, 0x0B, 0x7E, 0x04, 0xFB, 0x0E, 0x60, 0xDD, 0xF3, 0xFF, 0xFF, 0x20, 0xB0, + 0x80, 0xBC, 0x08, 0x28, 0xA2, 0xDB, 0x61, 0x55, 0x66, 0x00, 0x04, 0xB5, 0x82, 0xB5, 0x25, 0x02, + 0x04, 0x03, 0x20, 0x44, 0x7F, 0xB4, 0x40, 0x40, 0xA3, 0xD3, 0x99, 0xFE, 0x04, 0x04, 0x02, 0xBC, + 0xFE, 0xB4, 0xA3, 0xDB, 0x59, 0x00, 0xDB, 0xF3, 0x20, 0x40, 0x80, 0x26, 0x55, 0x00, 0xA3, 0xD3, + 0xFF, 0xA0, 0xF8, 0xB4, 0x02, 0x02, 0xA3, 0xDB, 0x1C, 0x00, 0x04, 0xBC, 0xBF, 0xB4, 0xA3, 0xDB, + 0x08, 0xB0, 0x01, 0x64, 0x08, 0x24, 0x02, 0x64, 0x28, 0xFB, 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, + 0xD0, 0xFE, 0x42, 0x00, 0xBF, 0xB4, 0xA3, 0xDB, 0x3F, 0x00, 0x40, 0xB0, 0xFF, 0xFF, 0xFA, 0x02, + 0xF8, 0xB4, 0xA3, 0xDB, 0x08, 0xB5, 0x07, 0x7C, 0x01, 0x02, 0xDB, 0xF9, 0x20, 0x44, 0x7F, 0xB4, + 0x40, 0x40, 0x1D, 0x60, 0xBA, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB5, 0x07, 0xB5, 0x08, 0x28, + 0xC4, 0x02, 0x99, 0xFE, 0x29, 0x05, 0x20, 0x44, 0x80, 0x26, 0x26, 0x00, 0x20, 0x2A, 0x03, 0x00, + 0xDF, 0xB4, 0x40, 0x40, 0x74, 0x00, 0x40, 0x2A, 0x1F, 0x00, 0xBF, 0xB4, 0x40, 0x40, 0x09, 0x00, + 0xA8, 0xFF, 0x20, 0x44, 0x99, 0xFE, 0x02, 0x05, 0x80, 0x2A, 0x03, 0x00, 0x40, 0xBC, 0x40, 0x40, + 0x13, 0x00, 0x00, 0xF1, 0x80, 0xBC, 0x40, 0x40, 0x64, 0x44, 0xE0, 0x84, 0xE8, 0x84, 0x0A, 0x36, + 0x29, 0x01, 0x0B, 0x36, 0x59, 0x01, 0x28, 0xFB, 0x01, 0xF1, 0x29, 0xF9, 0x02, 0xF1, 0x2A, 0xF9, + 0x03, 0xF1, 0x2B, 0xF9, 0xD0, 0xFE, 0xAE, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x82, 0x3E, 0x75, 0x44, + 0x02, 0xB0, 0x01, 0xB0, 0x54, 0x02, 0xDC, 0x02, 0x04, 0xB0, 0x08, 0xB0, 0x10, 0x02, 0x2A, 0x02, + 0x40, 0x26, 0xA7, 0xFF, 0x8C, 0xFF, 0x75, 0x40, 0x80, 0x2B, 0x06, 0x00, 0xAB, 0xFF, 0x19, 0x60, + 0xF6, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xA2, 0xDB, 0x75, 0x44, 0x8D, 0xFF, 0xE5, 0x01, 0x0A, 0xF3, + 0xAA, 0xFF, 0x60, 0x40, 0x20, 0x2B, 0x02, 0x00, 0x38, 0xFF, 0x0D, 0x00, 0x01, 0x26, 0x0C, 0x00, + 0xC0, 0x60, 0x00, 0x7C, 0xA0, 0x84, 0x80, 0x3B, 0x02, 0x00, 0xC0, 0x67, 0x03, 0x00, 0x40, 0x3B, + 0x02, 0x00, 0x00, 0x67, 0x0A, 0xFB, 0xD0, 0x01, 0x19, 0x60, 0xF6, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, + 0xA2, 0xDB, 0xCA, 0x01, 0x0B, 0xF1, 0xAB, 0xFF, 0x64, 0x44, 0xFF, 0x27, 0x1F, 0x00, 0x20, 0x26, + 0x03, 0x00, 0x02, 0x60, 0x00, 0x75, 0x1A, 0x00, 0x19, 0xF3, 0xFF, 0xFF, 0x03, 0x1B, 0x04, 0x60, + 0x00, 0x75, 0x0A, 0x64, 0xCC, 0x84, 0x19, 0xFB, 0x01, 0x60, 0x00, 0x75, 0x64, 0x40, 0x03, 0x22, + 0x0D, 0x00, 0x20, 0x44, 0x80, 0x2A, 0x03, 0x00, 0x20, 0xBC, 0x40, 0x40, 0x07, 0x00, 0xD9, 0xFE, + 0x81, 0x60, 0x0B, 0x64, 0x28, 0xFB, 0x2C, 0x44, 0x29, 0xFB, 0xD0, 0xFE, 0xA5, 0x01, 0xA9, 0xFF, + 0x77, 0x44, 0x60, 0x57, 0x40, 0x4A, 0x01, 0x2A, 0x31, 0x00, 0x24, 0x44, 0xAC, 0x86, 0x08, 0xF2, + 0x2D, 0x03, 0x25, 0x60, 0xFE, 0x65, 0xD4, 0x80, 0x0E, 0xF2, 0x02, 0x03, 0xA5, 0xD5, 0x04, 0x00, + 0x01, 0xBC, 0x0E, 0xFA, 0x09, 0xF4, 0xD1, 0xFE, 0x46, 0x44, 0x11, 0x1B, 0x32, 0x40, 0x80, 0x2A, + 0x1D, 0x00, 0x9D, 0xFE, 0x1B, 0x05, 0x13, 0x60, 0x02, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, + 0x03, 0x03, 0x0F, 0xF2, 0xFF, 0xFF, 0x12, 0x1B, 0x08, 0x60, 0x00, 0x75, 0x0F, 0x00, 0x3F, 0xF2, + 0x48, 0x65, 0xC4, 0x84, 0x13, 0xFB, 0x66, 0x44, 0x10, 0xFB, 0x66, 0x47, 0x20, 0xBF, 0x3B, 0x42, + 0x04, 0xA2, 0xA2, 0xDB, 0x0E, 0xF2, 0x41, 0x75, 0x10, 0xBC, 0x0E, 0xFA, 0x2A, 0x44, 0x08, 0x2A, + 0x17, 0x00, 0x23, 0x44, 0x00, 0xA8, 0x5C, 0x43, 0x13, 0x03, 0x12, 0x60, 0xFC, 0xF5, 0x01, 0x00, + 0x09, 0xF4, 0x0E, 0xF2, 0x0D, 0x18, 0x08, 0xB0, 0x18, 0xAC, 0xFA, 0x03, 0x0E, 0xFA, 0x66, 0x43, + 0x11, 0xFD, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x28, 0x75, + 0x2A, 0x44, 0x06, 0x22, 0x2D, 0x00, 0x22, 0x44, 0x00, 0xA8, 0x60, 0x46, 0x0E, 0xF2, 0x28, 0x03, + 0x10, 0xB0, 0x01, 0xBC, 0x03, 0x02, 0x00, 0x64, 0x40, 0x42, 0x22, 0x00, 0x0E, 0xFA, 0xD1, 0xFE, + 0x25, 0x60, 0xF2, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x94, 0x00, 0x46, 0x42, 0x19, 0x02, 0x22, 0x47, + 0x40, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x23, 0xF2, 0x66, 0x43, 0x00, 0xA8, 0x0E, 0xF2, + 0x08, 0x02, 0x60, 0x40, 0x02, 0x2A, 0xE4, 0x01, 0x12, 0xFD, 0x10, 0x64, 0x0E, 0xFA, 0x02, 0x75, + 0x07, 0x00, 0x60, 0x40, 0x04, 0x2A, 0xDC, 0x01, 0x12, 0xFD, 0x10, 0x64, 0x0E, 0xFA, 0x04, 0x75, + 0x2A, 0x44, 0x80, 0x2A, 0x19, 0x00, 0x21, 0x44, 0xAC, 0x86, 0x0E, 0xF2, 0x15, 0x03, 0x01, 0xBC, + 0x0E, 0xFA, 0xD1, 0xFE, 0x26, 0x60, 0x0A, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x6A, 0x00, 0x46, 0x41, + 0x0B, 0x02, 0x21, 0x47, 0x10, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x0E, 0xF2, 0x66, 0x43, + 0x08, 0xFD, 0x10, 0xBC, 0x0E, 0xFA, 0x80, 0x75, 0x2A, 0x44, 0x10, 0xB0, 0x20, 0x44, 0x18, 0x03, + 0x7F, 0xB4, 0x40, 0x40, 0x1D, 0x60, 0xBA, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB0, 0x80, 0xB0, + 0x09, 0x03, 0x08, 0x03, 0x40, 0xBC, 0x7F, 0xB4, 0x04, 0xB0, 0xA3, 0xDB, 0x03, 0x03, 0x20, 0x44, + 0x80, 0xBC, 0x40, 0x40, 0x2A, 0x40, 0x08, 0x27, 0x03, 0x00, 0xB3, 0x60, 0xC9, 0x78, 0xFF, 0xFF, + 0x2A, 0x40, 0x08, 0x2B, 0x0F, 0x00, 0x32, 0x40, 0x80, 0x26, 0x05, 0x00, 0x19, 0x60, 0xF7, 0xF3, + 0xFF, 0xFF, 0x01, 0x1B, 0x07, 0x00, 0x19, 0x60, 0xF6, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, 0xA2, 0xDB, + 0xFF, 0xFF, 0x10, 0xFF, 0xB3, 0x60, 0xFC, 0x78, 0xFF, 0xFF, 0xE8, 0xFE, 0x14, 0x05, 0xEA, 0xFE, + 0x23, 0x05, 0xE9, 0xFE, 0x1C, 0x05, 0xE7, 0xFE, 0x09, 0x05, 0x47, 0xFF, 0x20, 0x44, 0x0F, 0x22, + 0x03, 0x00, 0xCC, 0x84, 0x40, 0x40, 0x0F, 0x22, 0xB8, 0xFE, 0xEC, 0x01, 0x23, 0x41, 0x00, 0xB9, + 0x5C, 0x4A, 0xE8, 0x02, 0x5A, 0x01, 0x24, 0x41, 0x00, 0xB9, 0x25, 0x60, 0xFE, 0x65, 0x45, 0x47, + 0xE1, 0x02, 0x58, 0x4F, 0x0E, 0x00, 0xDE, 0x02, 0x5C, 0x4A, 0x46, 0x44, 0x38, 0x01, 0x22, 0x41, + 0x00, 0xB9, 0x5C, 0x4A, 0xD7, 0x02, 0x6C, 0x01, 0x21, 0x41, 0x00, 0xB9, 0x5C, 0x4A, 0x92, 0x03, + 0xD1, 0x01, 0x27, 0xD3, 0x03, 0x00, 0x10, 0xB0, 0x09, 0xF2, 0x04, 0x03, 0xAC, 0x86, 0x0E, 0xF2, + 0xFA, 0x02, 0x08, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0E, 0xF3, 0x0F, 0x60, 0xFE, 0x65, 0x0C, 0xF3, + 0x24, 0x86, 0x24, 0x46, 0x60, 0x40, 0xFB, 0x3B, 0x07, 0x00, 0x80, 0x26, 0x02, 0x00, 0x23, 0x46, + 0x03, 0x4C, 0x46, 0x61, 0x3A, 0x65, 0x0C, 0x00, 0x2E, 0xF3, 0x40, 0x45, 0xF8, 0x2B, 0x02, 0x00, + 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, 0x5A, 0x00, 0x07, 0x02, 0x58, 0x4F, 0x66, 0x00, 0x04, 0x05, + 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, 0x09, 0x00, 0x26, 0x47, 0x00, 0xBF, 0x0E, 0xFB, 0x2E, 0xF5, + 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, 0x00, 0x72, 0x7E, 0x71, 0xAC, 0xFF, 0x31, 0x40, 0x01, 0x2A, + 0x08, 0x00, 0x19, 0x60, 0xF2, 0xF3, 0xFF, 0xFF, 0x04, 0x18, 0x0C, 0x64, 0x13, 0x60, 0x13, 0xFB, + 0x2D, 0xFF, 0xB3, 0x60, 0xFC, 0x78, 0xFF, 0xFF, 0x8E, 0xFF, 0x0F, 0xF3, 0x0F, 0x60, 0xFE, 0x65, + 0x24, 0x86, 0x0D, 0xF3, 0x24, 0x46, 0x60, 0x40, 0xFB, 0x3B, 0x07, 0x00, 0x80, 0x26, 0x02, 0x00, + 0x23, 0x46, 0x03, 0x4C, 0x46, 0x61, 0x3A, 0x65, 0x0C, 0x00, 0x2E, 0xF3, 0x40, 0x45, 0xF8, 0x2B, + 0x02, 0x00, 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, 0x21, 0x00, 0x07, 0x02, 0x58, 0x4F, 0x2D, 0x00, + 0x04, 0x05, 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, 0x09, 0x00, 0x26, 0x47, 0x00, 0xBF, 0x0F, 0xFB, + 0x2E, 0xF5, 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, 0x00, 0x72, 0x7E, 0x71, 0x8D, 0xFF, 0xAD, 0xFF, + 0x31, 0x40, 0x01, 0x2A, 0xCE, 0x01, 0x19, 0x60, 0xF2, 0xF3, 0xFF, 0xFF, 0x04, 0x18, 0x0C, 0x64, + 0x13, 0x60, 0x13, 0xFB, 0x2D, 0xFF, 0xB3, 0x60, 0xFC, 0x78, 0xFF, 0xFF, 0x25, 0x44, 0xA7, 0xF1, + 0xA8, 0xF1, 0xD0, 0x80, 0xD0, 0x80, 0x07, 0x04, 0x01, 0x06, 0x05, 0x00, 0x25, 0x46, 0x01, 0xF0, + 0x03, 0x67, 0xA0, 0x85, 0x94, 0x80, 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x46, 0x26, 0x41, 0x46, 0x63, + 0x01, 0xF2, 0xFF, 0xFF, 0xFF, 0xB5, 0xD5, 0x81, 0x00, 0xF2, 0x05, 0x04, 0x04, 0x63, 0x60, 0x46, + 0xF7, 0x1B, 0x42, 0xFE, 0x0D, 0x00, 0x61, 0x44, 0xC5, 0x81, 0x63, 0x45, 0xC5, 0x81, 0x9C, 0x84, + 0xDC, 0x84, 0x01, 0xF2, 0xF0, 0x85, 0xF0, 0x80, 0x65, 0x44, 0xF8, 0x85, 0xFF, 0xFF, 0x02, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, 0x13, 0x60, 0x08, 0xF3, 0xFF, 0xFF, 0xAC, 0x86, 0x0E, 0xF2, + 0x07, 0x03, 0x00, 0xA8, 0x09, 0xF2, 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, 0x08, 0xFE, 0x17, 0x00, + 0xA9, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, 0x00, 0xB4, 0x12, 0x06, 0x09, 0x60, 0x08, 0x61, 0x41, 0x4A, + 0x7C, 0xA1, 0x0E, 0xA1, 0xA2, 0xFF, 0xB6, 0x60, 0x58, 0x4E, 0x44, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, + 0x06, 0x03, 0x2A, 0x43, 0xB6, 0x60, 0x58, 0x4E, 0x65, 0x78, 0xFF, 0xFF, 0x08, 0xFE, 0xA3, 0xFF, + 0x2D, 0x58, 0xFF, 0xFF, 0x41, 0x4A, 0x42, 0xA1, 0x03, 0x00, 0x41, 0x4A, 0x7C, 0xA1, 0x0E, 0xA1, + 0xA2, 0xFF, 0xB6, 0x60, 0x58, 0x4E, 0x44, 0x78, 0xFF, 0xFF, 0x07, 0x03, 0x2A, 0x43, 0xB6, 0x60, + 0x58, 0x4E, 0x65, 0x78, 0xFF, 0xFF, 0x08, 0xFE, 0x0C, 0x00, 0x13, 0x60, 0x08, 0xF3, 0xFF, 0xFF, + 0xAC, 0x86, 0x0E, 0xF2, 0x06, 0x03, 0x00, 0xA8, 0x09, 0xF2, 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, + 0x08, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0xAA, 0xF3, 0x7C, 0x63, 0x00, 0xBE, 0x40, 0x45, + 0x1A, 0x03, 0x00, 0x65, 0x65, 0x44, 0xDC, 0x85, 0x84, 0xA1, 0x00, 0xF2, 0x06, 0x06, 0x01, 0xFC, + 0x00, 0xA8, 0x60, 0x46, 0xF7, 0x02, 0x40, 0x45, 0x0E, 0x00, 0xA9, 0xF3, 0x00, 0x63, 0xD4, 0x84, + 0xA9, 0xFB, 0x80, 0x60, 0x7C, 0x64, 0x01, 0xFA, 0x00, 0xF0, 0x00, 0xFC, 0xD3, 0x80, 0xAA, 0xF9, + 0x02, 0x02, 0xAB, 0xF9, 0x08, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x66, 0x44, 0x25, 0x46, 0x05, 0xFA, + 0x06, 0xFA, 0x01, 0xF0, 0x03, 0x67, 0x02, 0xFC, 0xB0, 0x84, 0x3A, 0x7E, 0x01, 0xFA, 0x12, 0x64, + 0x03, 0xFA, 0x00, 0xF0, 0x04, 0xF8, 0x00, 0x64, 0x0C, 0x61, 0x10, 0x63, 0x59, 0xDA, 0xFE, 0x1F, + 0x2E, 0x58, 0xFF, 0xFF, 0x27, 0x43, 0xE3, 0x81, 0xE9, 0x81, 0x03, 0x05, 0x16, 0x03, 0x00, 0x61, + 0x01, 0x00, 0xEC, 0x63, 0x61, 0x46, 0xBF, 0xD2, 0x27, 0x45, 0xDC, 0x84, 0xA2, 0xDA, 0xBE, 0xD2, + 0x25, 0x46, 0x88, 0xF8, 0x04, 0x1B, 0x25, 0x44, 0x61, 0x46, 0xA3, 0xDA, 0x04, 0x00, 0x0A, 0xFA, + 0x60, 0x46, 0x25, 0x44, 0x09, 0xFA, 0x61, 0x46, 0xBE, 0xDA, 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x44, + 0x00, 0xA8, 0x07, 0x4B, 0x0C, 0x03, 0x58, 0x4F, 0x33, 0x00, 0x0B, 0x47, 0x26, 0x60, 0x04, 0x65, + 0x27, 0x44, 0xD4, 0x80, 0x00, 0x64, 0x01, 0x02, 0x0F, 0xFA, 0x58, 0x4F, 0xD3, 0x01, 0x70, 0x00, + 0x25, 0x43, 0xE3, 0x84, 0x7C, 0x41, 0x02, 0x04, 0xE8, 0x81, 0xEC, 0x63, 0x61, 0x46, 0xA3, 0xD2, + 0x00, 0x7C, 0x40, 0x45, 0xBF, 0xD8, 0xA3, 0xD8, 0xBE, 0xD8, 0x27, 0x42, 0x5A, 0xD3, 0x25, 0x5C, + 0x60, 0x41, 0x02, 0x1B, 0x27, 0xD9, 0x05, 0x00, 0x25, 0x46, 0x0A, 0xFA, 0x61, 0x46, 0x25, 0x44, + 0x09, 0xFA, 0x25, 0x44, 0x27, 0x43, 0x00, 0x61, 0x60, 0x46, 0x09, 0xF2, 0x08, 0xFC, 0x00, 0xA8, + 0xDD, 0x81, 0xFA, 0x02, 0xBF, 0xD1, 0x66, 0x44, 0xBE, 0xDB, 0xC1, 0x84, 0xBF, 0xDB, 0x48, 0x00, + 0x25, 0x46, 0xEC, 0x63, 0x08, 0xF2, 0x89, 0xF2, 0x1E, 0x18, 0x40, 0x47, 0xE0, 0x84, 0xE8, 0x85, + 0x02, 0x05, 0xE8, 0x83, 0x00, 0x65, 0x65, 0x46, 0xBF, 0xD2, 0x61, 0x5C, 0xCC, 0x84, 0xA2, 0xDA, + 0x25, 0x46, 0x0A, 0xF2, 0x00, 0xB9, 0x65, 0x46, 0x08, 0x24, 0xBE, 0xDA, 0x02, 0x1B, 0xA3, 0xD8, + 0x02, 0x00, 0x60, 0x46, 0x89, 0xFA, 0x00, 0xB9, 0x61, 0x46, 0x08, 0x28, 0x0A, 0xFA, 0x25, 0x46, + 0x89, 0xFC, 0x8A, 0xFC, 0x88, 0xFC, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x61, 0x28, 0x65, 0x25, 0x43, + 0xAB, 0xF3, 0xAF, 0x83, 0x00, 0xBE, 0x18, 0x03, 0x02, 0x03, 0x00, 0xFC, 0x01, 0x00, 0xAA, 0xFD, + 0x63, 0x46, 0x65, 0x44, 0xCC, 0x85, 0x00, 0xF2, 0x07, 0x02, 0xAB, 0xF5, 0x00, 0x64, 0x00, 0xFA, + 0xDE, 0x60, 0xAF, 0x64, 0x09, 0xFB, 0x08, 0x00, 0x66, 0x43, 0x00, 0xBE, 0xDD, 0x81, 0xF1, 0x02, + 0xA9, 0xF1, 0xAB, 0xFD, 0xC1, 0x84, 0xA9, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x45, + 0x29, 0x43, 0xFC, 0xA3, 0x66, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x00, 0x64, 0xBD, 0xDB, + 0x03, 0x61, 0x0E, 0x65, 0x26, 0x60, 0x18, 0x63, 0x43, 0x49, 0xA3, 0xD3, 0x06, 0xA3, 0x00, 0xA8, + 0xCD, 0x81, 0x04, 0x02, 0xF9, 0x02, 0xB3, 0x60, 0xFC, 0x78, 0xFF, 0xFF, 0x01, 0x26, 0xE6, 0x01, + 0xD4, 0x80, 0x60, 0x45, 0xE3, 0x05, 0xF6, 0xA3, 0xBD, 0xD1, 0xBD, 0xD1, 0x44, 0x47, 0x44, 0x48, + 0x44, 0x45, 0x26, 0x60, 0x5A, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x25, 0x60, 0xC8, 0x63, + 0x0D, 0x65, 0x00, 0x61, 0x41, 0x48, 0xA3, 0xD3, 0x06, 0xA3, 0xAC, 0x86, 0x00, 0x61, 0x09, 0x03, + 0x00, 0xF2, 0x09, 0xF0, 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x64, 0x44, 0xAC, 0x86, + 0xF6, 0x01, 0x61, 0x44, 0x25, 0x46, 0x27, 0xDA, 0x65, 0x44, 0x28, 0x45, 0x45, 0x88, 0xCC, 0x85, + 0x5A, 0x87, 0xE9, 0x02, 0x00, 0x64, 0x27, 0xDA, 0x5A, 0xDA, 0x5A, 0x87, 0xA6, 0xF3, 0xA5, 0xF1, + 0x02, 0xA4, 0x60, 0x46, 0x60, 0x45, 0x00, 0x61, 0x22, 0xF2, 0xFF, 0xFF, 0xAC, 0x86, 0x00, 0xF2, + 0x04, 0x03, 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x65, 0x44, 0x02, 0xA5, 0x65, 0x46, + 0x64, 0x44, 0xCC, 0x9C, 0xFF, 0xFF, 0xF0, 0x02, 0x61, 0x44, 0x25, 0x46, 0x27, 0xDA, 0x5A, 0x87, + 0x28, 0x45, 0x45, 0x88, 0x00, 0x64, 0x27, 0xDA, 0x5A, 0x87, 0x06, 0x60, 0x40, 0x65, 0xAA, 0xF3, + 0x01, 0x61, 0xAC, 0x86, 0x00, 0xF2, 0x03, 0x03, 0xD5, 0x80, 0xDD, 0x81, 0xFA, 0x04, 0xCD, 0x84, + 0x25, 0x46, 0x27, 0xDA, 0x28, 0x45, 0xC4, 0x84, 0x5A, 0xDA, 0xDA, 0x81, 0xA9, 0xF1, 0x59, 0xD8, + 0x25, 0x60, 0xC6, 0x64, 0x18, 0x63, 0xA0, 0xD1, 0x06, 0xA4, 0x59, 0xD8, 0xFC, 0x1F, 0x00, 0x64, + 0x59, 0xDA, 0x59, 0xDA, 0x01, 0x60, 0x56, 0x64, 0x0A, 0x63, 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, + 0xDB, 0xF1, 0x59, 0xD8, 0x75, 0x01, 0x07, 0x4B, 0xB6, 0x60, 0x58, 0x4F, 0xD0, 0x78, 0xFF, 0xFF, + 0x0B, 0x47, 0x58, 0x4F, 0x21, 0x00, 0x6C, 0x01, 0x07, 0x4B, 0xB6, 0x60, 0x58, 0x4F, 0xD0, 0x78, + 0xFF, 0xFF, 0x0B, 0x47, 0x27, 0x44, 0x00, 0xBE, 0x08, 0xF0, 0x15, 0x03, 0x64, 0x42, 0x4A, 0xD3, + 0x09, 0xF2, 0xDC, 0x83, 0xA2, 0xDD, 0x25, 0x43, 0x09, 0xFC, 0x63, 0x46, 0x27, 0x43, 0x0A, 0xFC, + 0x09, 0xFA, 0x08, 0xF8, 0x00, 0xA8, 0x66, 0x43, 0x03, 0x02, 0x64, 0x44, 0x58, 0xDD, 0x03, 0x00, + 0x60, 0x46, 0x25, 0x44, 0x0A, 0xFA, 0x4C, 0x01, 0x27, 0x43, 0xE3, 0x81, 0xE9, 0x81, 0x03, 0x05, + 0x16, 0x03, 0x00, 0x61, 0x01, 0x00, 0xEC, 0x63, 0x61, 0x46, 0xBF, 0xD2, 0x27, 0x45, 0xDC, 0x84, + 0xA2, 0xDA, 0xA3, 0xD2, 0x25, 0x46, 0x88, 0xF8, 0x04, 0x1B, 0x25, 0x44, 0x61, 0x46, 0xBE, 0xDA, + 0x04, 0x00, 0x09, 0xFA, 0x60, 0x46, 0x25, 0x44, 0x0A, 0xFA, 0x61, 0x46, 0xA3, 0xDA, 0x2F, 0x58, + 0xFF, 0xFF, 0xA0, 0xFE, 0x07, 0x05, 0xA3, 0xFE, 0x07, 0x05, 0xA1, 0xFE, 0x48, 0x05, 0x60, 0x64, + 0x3B, 0xDB, 0x11, 0x00, 0x20, 0x58, 0xFF, 0xFF, 0x4F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x60, + 0xDF, 0xF3, 0xFF, 0xFF, 0xFB, 0xB4, 0xA2, 0xDB, 0xA0, 0x4C, 0x59, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, + 0xA0, 0x4C, 0x7D, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, 0x83, 0x3E, 0x40, 0x60, 0x0B, 0x65, + 0x2B, 0x44, 0x00, 0x63, 0xE8, 0x80, 0xF8, 0x84, 0x02, 0x24, 0x94, 0x84, 0xF3, 0x83, 0xCD, 0x81, + 0xFF, 0xFF, 0xF8, 0x02, 0xDF, 0x83, 0x2F, 0x58, 0x40, 0x4B, 0x00, 0x62, 0x01, 0x64, 0xD4, 0x80, + 0xE0, 0x84, 0x1A, 0x03, 0xD4, 0x80, 0xE0, 0x84, 0x15, 0x03, 0x61, 0x44, 0x11, 0x61, 0xE0, 0x84, + 0xCD, 0x81, 0xFD, 0x04, 0x01, 0x00, 0xE0, 0x84, 0xF2, 0x82, 0xFF, 0xFF, 0x02, 0x24, 0xC6, 0x82, + 0x02, 0x28, 0xD6, 0x82, 0xE2, 0x80, 0xCD, 0x81, 0x02, 0x28, 0x01, 0xBC, 0xF4, 0x02, 0x01, 0x2A, + 0xC6, 0x82, 0x03, 0x00, 0xE9, 0x81, 0xF2, 0x82, 0x61, 0x44, 0x2D, 0x58, 0xFF, 0xFF, 0x00, 0x64, + 0x3B, 0xDB, 0x3C, 0x44, 0xAC, 0x80, 0xFF, 0xFF, 0xC6, 0x02, 0x89, 0xF3, 0x8A, 0xF3, 0x02, 0xA8, + 0x02, 0xA8, 0x08, 0x02, 0x00, 0x64, 0x8B, 0xFB, 0x89, 0xFB, 0x8A, 0xFB, 0x00, 0x64, 0x8C, 0xFB, + 0xCA, 0xFE, 0x2A, 0x00, 0x03, 0x02, 0x00, 0x64, 0x8A, 0xFB, 0xCA, 0xFE, 0x01, 0x64, 0x3B, 0xDB, + 0x12, 0x60, 0xE7, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x13, 0x03, 0xDB, 0xF3, 0x2A, 0xF2, + 0xFD, 0xA0, 0x60, 0x40, 0x80, 0x3A, 0x33, 0x00, 0x32, 0x02, 0x9B, 0xFE, 0x30, 0x05, 0x00, 0x64, + 0x13, 0x60, 0x0A, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xE7, 0x01, 0x8A, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, 0x06, 0x02, 0x12, 0x60, 0xE4, 0xF3, + 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x1B, 0x02, 0x86, 0xFF, 0x20, 0x40, 0x12, 0x27, 0x13, 0x00, + 0x9A, 0xFE, 0x11, 0x04, 0x9D, 0xFE, 0x0F, 0x04, 0x95, 0xF3, 0xFF, 0xFF, 0x80, 0xBC, 0x95, 0xFB, + 0x84, 0xFF, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0x06, 0x64, 0x13, 0x60, 0x16, 0xFB, 0xFF, 0xFF, + 0x2D, 0xFF, 0x12, 0x64, 0x3B, 0xDB, 0x84, 0xFF, 0xB7, 0x60, 0xF7, 0x78, 0xFF, 0xFF, 0x66, 0x44, + 0xFC, 0xFB, 0x46, 0x5C, 0x19, 0x60, 0xCF, 0xF3, 0x0D, 0xF2, 0x60, 0x5C, 0x64, 0x5F, 0x0D, 0xFA, + 0x11, 0x64, 0x3B, 0xDB, 0x9D, 0xFE, 0x06, 0x05, 0x08, 0x64, 0x13, 0x60, 0x16, 0xFB, 0x2D, 0xFF, + 0xFF, 0xFF, 0xA3, 0xFE, 0x07, 0xF0, 0x00, 0x64, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x02, 0x23, 0xF0, + 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xBF, 0x60, 0x79, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x00, 0x63, + 0x40, 0x47, 0x50, 0x36, 0x05, 0x00, 0xA4, 0x36, 0x03, 0x00, 0x80, 0x36, 0x01, 0x00, 0x01, 0x63, + 0x48, 0xFD, 0x40, 0x47, 0x08, 0x2A, 0x08, 0x00, 0x03, 0x2F, 0x06, 0x00, 0x7F, 0xF1, 0x2C, 0xF8, + 0x80, 0xF1, 0x2D, 0xF8, 0x81, 0xF1, 0x2E, 0xF8, 0x4A, 0xF3, 0x35, 0xFA, 0x10, 0xA4, 0x4A, 0xFB, + 0x00, 0x64, 0x15, 0xFA, 0x16, 0xFA, 0x0F, 0xFA, 0x07, 0xF0, 0xA6, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, + 0xFF, 0xFF, 0x05, 0x03, 0x66, 0x43, 0x64, 0x46, 0x11, 0xF2, 0xD9, 0xFB, 0x63, 0x46, 0x03, 0xF2, + 0x00, 0xF4, 0x01, 0xF2, 0xFC, 0xA5, 0x00, 0x7F, 0xD4, 0x84, 0x27, 0x45, 0x3C, 0x46, 0x1A, 0xFA, + 0x22, 0x63, 0x7B, 0x60, 0xFF, 0x64, 0xA4, 0x84, 0x03, 0x2B, 0x1C, 0x63, 0x2A, 0xFA, 0x8F, 0xB0, + 0x88, 0x36, 0x02, 0xA3, 0x60, 0x40, 0xA4, 0x36, 0x14, 0x63, 0x43, 0x4C, 0x18, 0xFC, 0x00, 0x7C, + 0x22, 0xF8, 0x64, 0x41, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x3A, 0xF2, 0x63, 0x46, 0xFF, 0xB4, + 0x22, 0xFA, 0x60, 0x40, 0x00, 0x36, 0x82, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x0C, 0xB0, 0x08, 0x3A, + 0xAD, 0x00, 0x60, 0x40, 0x40, 0x26, 0xAA, 0x00, 0x03, 0xF2, 0x00, 0xF4, 0xA0, 0xD2, 0xAA, 0x60, + 0xAA, 0x65, 0x5A, 0xD0, 0xD4, 0x80, 0x03, 0x64, 0x0A, 0x02, 0xD0, 0x80, 0x00, 0x64, 0x5A, 0xD0, + 0x06, 0x02, 0xD0, 0x80, 0xF8, 0x7F, 0xD0, 0x80, 0x01, 0x03, 0x01, 0x02, 0x01, 0x61, 0x62, 0x43, + 0x46, 0x43, 0x3C, 0x46, 0x07, 0xF4, 0x3A, 0xF2, 0xFF, 0xFF, 0xA3, 0x46, 0x60, 0x40, 0x22, 0x26, + 0x64, 0x00, 0x60, 0x45, 0x63, 0x42, 0x5A, 0xD0, 0xCD, 0x81, 0x3C, 0x46, 0x1B, 0x02, 0x64, 0x44, + 0x88, 0x3A, 0x18, 0x00, 0x8E, 0x37, 0x03, 0x00, 0xC7, 0x37, 0x01, 0x00, 0x13, 0x00, 0x65, 0x44, + 0x01, 0x26, 0x7C, 0x00, 0x04, 0x26, 0x03, 0x00, 0x10, 0x26, 0x01, 0x00, 0x31, 0x00, 0xA3, 0x46, + 0x3B, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x27, 0x5B, 0x00, 0xA3, 0x46, 0x00, 0x7C, 0x22, 0xF8, + 0xA3, 0x46, 0x6C, 0x00, 0xA3, 0x46, 0x65, 0x44, 0x01, 0x26, 0x0B, 0x00, 0x04, 0x26, 0x03, 0x00, + 0x10, 0x26, 0x01, 0x00, 0x1D, 0x00, 0x3B, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x27, 0x48, 0x00, + 0x17, 0x00, 0xA6, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0x3A, 0xF2, 0x66, 0x43, 0xFF, 0xB4, 0x3C, 0x46, + 0x22, 0xF0, 0x60, 0x47, 0xB0, 0x84, 0x22, 0xFA, 0x63, 0x46, 0x3B, 0xF0, 0x60, 0x40, 0x04, 0x27, + 0x03, 0x00, 0x10, 0x27, 0x01, 0x00, 0x04, 0x00, 0x64, 0x40, 0x80, 0x27, 0x31, 0x00, 0x00, 0x00, + 0x3C, 0x46, 0x02, 0x65, 0xBF, 0x60, 0x19, 0x78, 0xFF, 0xFF, 0xCD, 0x81, 0x63, 0x42, 0x5A, 0xD0, + 0x3C, 0x46, 0x26, 0x02, 0x64, 0x44, 0x88, 0x3A, 0x23, 0x00, 0x77, 0x37, 0x37, 0x00, 0x78, 0x37, + 0x35, 0x00, 0x8E, 0x37, 0x33, 0x00, 0xC7, 0x37, 0x31, 0x00, 0x1A, 0x00, 0x19, 0x60, 0xA3, 0xF3, + 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x2A, 0x00, 0x06, 0x00, 0x19, 0x60, 0xA3, 0xF3, 0xFF, 0xFF, + 0x60, 0x40, 0x01, 0x2A, 0xE2, 0x01, 0x3C, 0x46, 0x3E, 0xF2, 0x40, 0x60, 0x00, 0x65, 0xF0, 0x84, + 0xA4, 0x84, 0x3D, 0xFA, 0x2A, 0xF2, 0xBF, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x2A, 0xFA, 0x16, 0x00, + 0x3C, 0x46, 0x22, 0xF0, 0x80, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0xFF, 0xFF, 0x3F, 0xF2, 0x3E, 0xF0, + 0x08, 0xA4, 0x60, 0x41, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, + 0x03, 0x00, 0x04, 0x00, 0x04, 0x2B, 0x02, 0x00, 0x61, 0x44, 0x3F, 0xFA, 0x3C, 0x46, 0x2C, 0xF2, + 0x27, 0x40, 0x01, 0x27, 0x32, 0xF2, 0xD3, 0xF1, 0x60, 0x40, 0x01, 0x26, 0x47, 0x00, 0x09, 0x60, + 0x00, 0x64, 0xD0, 0x80, 0x3F, 0xF2, 0x09, 0x06, 0x2C, 0x45, 0xC4, 0x84, 0xD0, 0x80, 0x40, 0x4A, + 0x34, 0x06, 0x60, 0x43, 0x64, 0x44, 0x54, 0x88, 0x17, 0x00, 0x60, 0x45, 0x16, 0x60, 0xC8, 0xF3, + 0xDA, 0xF3, 0x00, 0xBC, 0x60, 0x47, 0xEC, 0xA0, 0x28, 0x03, 0x27, 0x07, 0x2C, 0x44, 0xC4, 0x81, + 0x02, 0x60, 0x1C, 0x65, 0x45, 0x4A, 0xD5, 0x80, 0x2C, 0x45, 0x1F, 0x06, 0x27, 0x40, 0x04, 0x27, + 0x25, 0x00, 0x2A, 0x43, 0xD7, 0x85, 0x45, 0x48, 0xD4, 0xF1, 0x0F, 0xF2, 0xD3, 0x80, 0x01, 0x65, + 0x01, 0x07, 0x00, 0x65, 0xB4, 0x84, 0x0F, 0xFA, 0x00, 0x63, 0x3F, 0xF2, 0x28, 0x45, 0x60, 0x41, + 0xD4, 0x84, 0xDF, 0x83, 0xFC, 0x07, 0x14, 0xFC, 0x17, 0xFA, 0x04, 0x60, 0x00, 0x64, 0x27, 0x45, + 0xB4, 0x84, 0x2A, 0xFA, 0x28, 0x43, 0x16, 0xFC, 0x0D, 0x00, 0x3F, 0xF2, 0x2C, 0x45, 0xD4, 0xF1, + 0xC4, 0x81, 0xD1, 0x80, 0x0F, 0xF2, 0x01, 0x06, 0x01, 0xBC, 0x0F, 0xFA, 0x3F, 0xF2, 0x17, 0xFA, + 0x01, 0x64, 0x14, 0xFA, 0xAA, 0xF2, 0x19, 0x60, 0x3F, 0xF3, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, + 0x44, 0x44, 0x61, 0x40, 0x08, 0x26, 0x02, 0x00, 0x61, 0x40, 0x80, 0x36, 0x12, 0xF2, 0x63, 0x46, + 0x33, 0x60, 0x86, 0x61, 0x00, 0x7F, 0x60, 0x45, 0x45, 0xD3, 0xFF, 0xFF, 0x60, 0x45, 0x00, 0x7F, + 0x4B, 0xFB, 0x65, 0x44, 0x00, 0x7E, 0xDA, 0xFB, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x12, 0xF0, + 0x60, 0x47, 0x63, 0x46, 0x64, 0x40, 0x10, 0x2A, 0x1E, 0x00, 0x33, 0x60, 0x0A, 0x63, 0x60, 0x40, + 0x0A, 0x36, 0x0C, 0x00, 0x14, 0x36, 0x07, 0x00, 0x37, 0x36, 0x02, 0x00, 0xA3, 0xD3, 0x09, 0x00, + 0x02, 0xA3, 0xA3, 0xD3, 0x06, 0x00, 0x04, 0xA3, 0xA3, 0xD3, 0x03, 0x00, 0x06, 0xA3, 0xA3, 0xD3, + 0xFF, 0xFF, 0x60, 0x40, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, 0x37, 0x36, 0x15, 0x64, + 0x6E, 0x36, 0x0B, 0x64, 0x39, 0x00, 0x32, 0x60, 0xFA, 0x63, 0x60, 0x40, 0x0B, 0x36, 0x20, 0x00, + 0x0F, 0x36, 0x1B, 0x00, 0x0A, 0x36, 0x16, 0x00, 0x0E, 0x36, 0x11, 0x00, 0x09, 0x36, 0x0C, 0x00, + 0x0D, 0x36, 0x07, 0x00, 0x08, 0x36, 0x02, 0x00, 0xA3, 0xD3, 0x15, 0x00, 0x02, 0xA3, 0xA3, 0xD3, + 0x12, 0x00, 0x04, 0xA3, 0xA3, 0xD3, 0x0F, 0x00, 0x06, 0xA3, 0xA3, 0xD3, 0x0C, 0x00, 0x08, 0xA3, + 0xA3, 0xD3, 0x09, 0x00, 0x0A, 0xA3, 0xA3, 0xD3, 0x06, 0x00, 0x0C, 0xA3, 0xA3, 0xD3, 0x03, 0x00, + 0x0E, 0xA3, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x0B, 0x36, 0x1E, 0x64, 0x0F, 0x36, 0x16, 0x64, + 0x0A, 0x36, 0x12, 0x64, 0x0E, 0x36, 0x0E, 0x64, 0x09, 0x36, 0x0E, 0x64, 0x0D, 0x36, 0x0A, 0x64, + 0x08, 0x36, 0x0A, 0x64, 0x0C, 0x36, 0x0A, 0x64, 0x40, 0x46, 0x2A, 0xF2, 0x07, 0xF0, 0x60, 0x40, + 0xB0, 0x3A, 0x03, 0x00, 0x40, 0x3B, 0x01, 0x00, 0x12, 0x00, 0x0C, 0xB4, 0x08, 0x3A, 0x44, 0x00, + 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, 0x3F, 0x00, 0x17, 0xF2, 0x22, 0xF0, 0xFF, 0xFF, + 0x64, 0x40, 0x22, 0x22, 0x04, 0x00, 0x00, 0xA8, 0x01, 0xA8, 0x36, 0x03, 0x35, 0x03, 0x3C, 0x46, + 0x2A, 0xF0, 0x40, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x60, 0x45, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x43, + 0x60, 0x40, 0x01, 0x26, 0x05, 0x00, 0x04, 0x26, 0x1D, 0x00, 0x10, 0x26, 0x10, 0x00, 0x04, 0x00, + 0x04, 0x27, 0x18, 0x00, 0x10, 0x27, 0x0B, 0x00, 0x65, 0x44, 0x2A, 0x61, 0x60, 0x40, 0x03, 0x2B, + 0x24, 0x61, 0x8F, 0xB0, 0x88, 0x36, 0x02, 0xA1, 0x41, 0x4C, 0x98, 0xFA, 0x15, 0x00, 0x65, 0x44, + 0x32, 0x61, 0x60, 0x40, 0x03, 0x2B, 0x2C, 0x61, 0x8F, 0xB0, 0x88, 0x36, 0x02, 0xA1, 0x41, 0x4C, + 0x98, 0xFA, 0x0A, 0x00, 0x65, 0x44, 0x2E, 0x61, 0x60, 0x40, 0x03, 0x2B, 0x28, 0x61, 0x8F, 0xB0, + 0x88, 0x36, 0x02, 0xA1, 0x41, 0x4C, 0x98, 0xFA, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x27, + 0x03, 0x00, 0xBC, 0x60, 0x46, 0x78, 0xFF, 0xFF, 0x22, 0xF2, 0x46, 0x43, 0x60, 0x40, 0x22, 0x26, + 0x09, 0x00, 0x01, 0x26, 0x0A, 0x00, 0x04, 0x26, 0x4B, 0x00, 0x10, 0x26, 0x10, 0x00, 0xBC, 0x60, + 0x46, 0x78, 0xFF, 0xFF, 0xBB, 0x60, 0xC1, 0x78, 0xFF, 0xFF, 0x04, 0x27, 0x3D, 0x00, 0x10, 0x27, + 0x03, 0x00, 0xBC, 0x60, 0x46, 0x78, 0xFF, 0xFF, 0xA6, 0xF3, 0x3C, 0xF1, 0x02, 0x00, 0x07, 0xF2, + 0x00, 0x7C, 0x40, 0x43, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x27, 0x21, 0x00, 0xA3, 0x46, + 0x4B, 0xF2, 0xFF, 0xFF, 0xDC, 0x84, 0x4B, 0xFA, 0x4A, 0xF2, 0x08, 0x04, 0xDC, 0x84, 0x4A, 0xFA, + 0x49, 0xF2, 0x04, 0x04, 0xDC, 0x84, 0x49, 0xFA, 0x01, 0x04, 0xFF, 0xFF, 0xA6, 0xF3, 0x66, 0x5C, + 0xD0, 0x80, 0x00, 0x7C, 0x01, 0x02, 0x3C, 0xF1, 0x4B, 0xF0, 0x64, 0x47, 0x20, 0xBF, 0xA3, 0x46, + 0x3A, 0xF8, 0x3B, 0xFA, 0xA3, 0x46, 0x4A, 0xF2, 0x49, 0xF0, 0xA3, 0x46, 0x3C, 0xFA, 0x3D, 0xF8, + 0x0F, 0x60, 0x9E, 0x64, 0xA3, 0x46, 0x76, 0x61, 0x0E, 0x63, 0x59, 0xD0, 0x58, 0xD9, 0xFD, 0x1F, + 0xA3, 0x46, 0xBC, 0x60, 0x46, 0x78, 0xFF, 0xFF, 0xA6, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0x02, 0x00, + 0x07, 0xF4, 0xFF, 0xFF, 0xA3, 0x46, 0x2A, 0xF2, 0xA3, 0x46, 0x60, 0x40, 0x08, 0x27, 0x48, 0x00, + 0xA6, 0xF3, 0x66, 0x5C, 0xD0, 0x80, 0x3B, 0xF0, 0x08, 0x03, 0x64, 0x40, 0x10, 0x2A, 0x12, 0x00, + 0xFF, 0x60, 0xEF, 0x64, 0xA0, 0x84, 0x3B, 0xFA, 0x24, 0x00, 0x3D, 0xF3, 0x01, 0x61, 0x60, 0x43, + 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, 0xE9, 0x81, 0xA1, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0x91, 0x84, + 0x3B, 0xFA, 0x17, 0x00, 0x4B, 0xF2, 0xFF, 0xFF, 0x10, 0xA0, 0xFF, 0xFF, 0x02, 0x04, 0xFF, 0x60, + 0xFF, 0x64, 0xDC, 0x84, 0x4B, 0xFA, 0x4A, 0xF2, 0x16, 0x04, 0xDC, 0x84, 0x4A, 0xFA, 0x49, 0xF2, + 0x08, 0x04, 0xDC, 0x84, 0x49, 0xFA, 0x05, 0x04, 0x3B, 0xF2, 0xFF, 0xFF, 0xE0, 0x84, 0xE8, 0x84, + 0x3B, 0xFA, 0x0C, 0x60, 0xFC, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC8, 0x60, + 0x15, 0x78, 0xFF, 0xFF, 0x84, 0xFF, 0x06, 0x60, 0x17, 0xE1, 0x77, 0x40, 0x8B, 0xFF, 0x02, 0x60, + 0x00, 0x75, 0xC9, 0x60, 0x58, 0x4F, 0xAD, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x06, 0x60, 0x7F, 0xFB, + 0x0C, 0x60, 0xFC, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC8, 0x60, 0x8C, 0x78, + 0xFF, 0xFF, 0x84, 0xFF, 0x00, 0x7C, 0x06, 0x60, 0x7F, 0xF3, 0xA2, 0xD9, 0x60, 0x40, 0x01, 0x2A, + 0x04, 0x00, 0xC9, 0x60, 0x58, 0x4F, 0xF6, 0x78, 0xFF, 0xFF, 0x3C, 0x46, 0x07, 0xF4, 0xA6, 0xF3, + 0x66, 0x5C, 0xD0, 0x80, 0x00, 0x7C, 0x07, 0x03, 0x66, 0x43, 0x3C, 0x46, 0x22, 0xF2, 0x63, 0x46, + 0x60, 0x40, 0x01, 0x2A, 0x01, 0x00, 0x3C, 0xF1, 0x4B, 0xF0, 0x64, 0x41, 0x64, 0x47, 0xFF, 0xB4, + 0x60, 0x5F, 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, 0x60, 0x47, 0xA3, 0x46, 0x3A, 0xFA, 0x64, 0x44, + 0x20, 0x7F, 0x34, 0x94, 0x3B, 0xFA, 0xA3, 0x46, 0x4A, 0xF2, 0x49, 0xF0, 0xA3, 0x46, 0x3C, 0xFA, + 0x3D, 0xF8, 0x80, 0x60, 0x10, 0xE0, 0x08, 0x60, 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, + 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0xBC, 0x60, 0x46, 0x78, + 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x27, 0x31, 0x00, 0x2A, 0xF2, 0x00, 0x60, + 0x7C, 0x62, 0x60, 0x40, 0x40, 0x2B, 0x24, 0x00, 0xA2, 0xD3, 0x00, 0x61, 0x60, 0xFE, 0xA0, 0xD3, + 0x5E, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0xDC, 0x84, 0xF1, 0x81, 0xC0, 0x2B, 0x04, 0x00, + 0x80, 0x2A, 0x02, 0x00, 0x7F, 0xA4, 0xDC, 0x84, 0xFF, 0x3B, 0x03, 0x00, 0x60, 0x47, 0xDC, 0x87, + 0x01, 0x61, 0xC0, 0x80, 0x00, 0x36, 0xDC, 0x84, 0x4E, 0xDB, 0x60, 0xFE, 0x5A, 0xD1, 0xFF, 0xFF, + 0xC1, 0x84, 0xF0, 0x22, 0x10, 0xA4, 0xF0, 0x2A, 0x01, 0x00, 0x00, 0x64, 0xA2, 0xDB, 0x20, 0xFE, + 0x00, 0x60, 0x3E, 0xF3, 0xFF, 0xFF, 0xA0, 0xD3, 0x5A, 0xD1, 0x3A, 0xFA, 0x3B, 0xF8, 0x74, 0x62, + 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, + 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, 0x40, 0xF3, 0xFF, 0xFF, 0xA0, 0xD1, + 0x5A, 0xD1, 0x64, 0x45, 0x64, 0x44, 0xE3, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, + 0xA0, 0x5A, 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, + 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5A, 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, + 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE9, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, + 0xA0, 0x5A, 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, + 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, + 0xEF, 0x7F, 0xA0, 0x5A, 0x08, 0x60, 0x00, 0xEA, 0x65, 0x44, 0x02, 0xA4, 0x60, 0x7F, 0xA0, 0x5A, + 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x66, 0x45, 0xAA, 0xF2, + 0x19, 0x60, 0x3F, 0xF3, 0x24, 0x46, 0x61, 0x40, 0x08, 0x26, 0x02, 0x00, 0x61, 0x40, 0x80, 0x36, + 0x12, 0xF2, 0x65, 0x46, 0x60, 0x40, 0x10, 0x26, 0x34, 0x00, 0x2C, 0x45, 0x17, 0xF2, 0x4B, 0xF1, + 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, 0x64, 0x45, 0x16, 0xA1, 0xB8, 0x60, 0x58, 0x4D, + 0x15, 0x78, 0xFF, 0xFF, 0x7D, 0xF1, 0x01, 0xA4, 0xE0, 0x84, 0xE0, 0x84, 0x64, 0x40, 0x01, 0x2B, + 0x06, 0xA4, 0x1B, 0xFA, 0xDA, 0xF3, 0x2C, 0x60, 0x7C, 0x65, 0x60, 0x40, 0x0B, 0x37, 0x00, 0x63, + 0x0F, 0x37, 0x02, 0x63, 0x0A, 0x37, 0x04, 0x63, 0x0E, 0x37, 0x06, 0x63, 0x09, 0x37, 0x08, 0x63, + 0x0D, 0x37, 0x0A, 0x63, 0x08, 0x37, 0x0C, 0x63, 0x0C, 0x37, 0x0E, 0x63, 0x28, 0xA3, 0x47, 0xD1, + 0xD8, 0xA3, 0xD7, 0x83, 0x19, 0x60, 0x77, 0xF9, 0x47, 0xD1, 0x40, 0x67, 0xB0, 0x84, 0x1F, 0xFA, + 0x58, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x36, 0x19, 0x00, 0x50, 0x36, 0x17, 0x00, + 0x40, 0x36, 0x15, 0x00, 0x00, 0x36, 0x13, 0x00, 0x20, 0x36, 0x11, 0x00, 0xA0, 0x36, 0x0F, 0x00, + 0xB0, 0x36, 0x0D, 0x00, 0xC0, 0x36, 0x0B, 0x00, 0xDA, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x0A, 0x37, + 0x06, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0x80, 0x60, 0x00, 0x61, 0x60, 0x40, 0x04, 0x26, 0x00, 0x61, + 0xDA, 0xF3, 0x2C, 0x60, 0x74, 0x65, 0x60, 0x40, 0x0A, 0x37, 0x00, 0x63, 0x14, 0x37, 0x02, 0x63, + 0x37, 0x37, 0x04, 0x63, 0x6E, 0x37, 0x06, 0x63, 0x28, 0xA3, 0x47, 0xD1, 0xD8, 0xA3, 0xD7, 0x83, + 0x19, 0x60, 0x77, 0xF9, 0x47, 0xD1, 0xFF, 0xFF, 0xB1, 0x84, 0x1F, 0xFA, 0xDA, 0xF1, 0x2C, 0x45, + 0x64, 0x43, 0x17, 0xF2, 0x4B, 0xF1, 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, 0x63, 0x40, + 0x37, 0x37, 0xE1, 0x81, 0x64, 0x45, 0xB8, 0x60, 0x58, 0x4D, 0x15, 0x78, 0xFF, 0xFF, 0xAE, 0x82, + 0xFC, 0xA2, 0x0A, 0x03, 0x63, 0x40, 0x6E, 0x3B, 0x06, 0x00, 0x60, 0x41, 0x04, 0x0D, 0x63, 0x44, + 0x80, 0x7E, 0xDA, 0xFB, 0x61, 0x44, 0xDC, 0x84, 0x2B, 0xF0, 0x1B, 0xFA, 0x64, 0x44, 0x80, 0x27, + 0x58, 0x00, 0x07, 0xF0, 0x66, 0x45, 0x64, 0x46, 0x12, 0xF2, 0x65, 0x46, 0x60, 0x40, 0x10, 0x2A, + 0x31, 0x00, 0x16, 0xF2, 0x0F, 0xF0, 0xAC, 0x84, 0x2C, 0x45, 0x2C, 0x03, 0x4B, 0xF1, 0xC4, 0x84, + 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, 0x63, 0x40, 0x37, 0x37, 0xE1, 0x81, 0x64, 0x45, 0x0F, 0xF0, + 0xB8, 0x60, 0x58, 0x4D, 0x15, 0x78, 0xFF, 0xFF, 0xAE, 0x82, 0xFC, 0xA2, 0x0A, 0x03, 0x63, 0x40, + 0x6E, 0x3B, 0x06, 0x00, 0x60, 0x41, 0x04, 0x0D, 0x80, 0x67, 0xB0, 0x84, 0x0F, 0xFA, 0x61, 0x44, + 0xDC, 0x84, 0x1D, 0xFA, 0x1F, 0xF0, 0x01, 0x60, 0x3E, 0x65, 0x64, 0x40, 0x80, 0x27, 0x02, 0x00, + 0x02, 0x60, 0x5E, 0x65, 0x1B, 0xF0, 0x26, 0x41, 0xE1, 0x81, 0xC5, 0x81, 0x44, 0x94, 0xC1, 0x81, + 0x2B, 0xFA, 0x90, 0xFA, 0x26, 0x44, 0x2C, 0xF0, 0x0A, 0xA4, 0x66, 0x45, 0x24, 0x46, 0x92, 0xF2, + 0x65, 0x46, 0x9F, 0xF0, 0x61, 0x40, 0x10, 0x2A, 0x05, 0x00, 0x60, 0xA4, 0x65, 0x40, 0x80, 0x2B, + 0x60, 0xA4, 0x01, 0x00, 0x14, 0xA4, 0x64, 0x40, 0x01, 0x26, 0x00, 0x64, 0x60, 0x45, 0x2A, 0xF2, + 0x39, 0xF0, 0x8F, 0xB0, 0x88, 0x3A, 0x04, 0x00, 0x64, 0x44, 0x60, 0xB0, 0x20, 0x36, 0x00, 0x65, + 0x65, 0x44, 0x11, 0xFA, 0xDA, 0xF3, 0x13, 0xFA, 0x7C, 0x44, 0x1D, 0xFA, 0x0F, 0xF0, 0xFF, 0xFF, + 0x64, 0x40, 0x01, 0x2A, 0x6F, 0x00, 0x7D, 0xF1, 0x19, 0x60, 0x7B, 0xF3, 0x64, 0x40, 0x01, 0x27, + 0x03, 0x00, 0x60, 0x40, 0x02, 0x26, 0x14, 0x00, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x12, 0xF0, + 0x19, 0x60, 0x7C, 0xF3, 0x63, 0x46, 0x64, 0x40, 0x10, 0x2A, 0x20, 0x00, 0x60, 0x40, 0x02, 0x26, + 0x07, 0x00, 0x01, 0x26, 0x08, 0x00, 0x04, 0x26, 0x09, 0x00, 0x06, 0x61, 0x6E, 0x63, 0x08, 0x00, + 0x02, 0x61, 0x14, 0x63, 0x05, 0x00, 0x00, 0x61, 0x0A, 0x63, 0x02, 0x00, 0x04, 0x61, 0x37, 0x63, + 0x00, 0x64, 0x2C, 0x60, 0x9C, 0x65, 0x45, 0xD1, 0xD5, 0x81, 0x19, 0x60, 0x78, 0xF9, 0x2C, 0x60, + 0x74, 0x65, 0x45, 0xD1, 0x1C, 0xFC, 0xB0, 0x84, 0x1E, 0xFA, 0x3C, 0x00, 0x60, 0x40, 0x10, 0x2A, + 0x04, 0x00, 0x08, 0x61, 0x1E, 0x60, 0x0B, 0x63, 0x27, 0x00, 0x20, 0x2A, 0x04, 0x00, 0x0A, 0x61, + 0x16, 0x60, 0x0F, 0x63, 0x21, 0x00, 0x40, 0x2A, 0x04, 0x00, 0x0C, 0x61, 0x12, 0x60, 0x0A, 0x63, + 0x1B, 0x00, 0x80, 0x2A, 0x04, 0x00, 0x0E, 0x61, 0x0E, 0x60, 0x0E, 0x63, 0x15, 0x00, 0x01, 0x2B, + 0x04, 0x00, 0x10, 0x61, 0x0E, 0x60, 0x09, 0x63, 0x0F, 0x00, 0x02, 0x2B, 0x04, 0x00, 0x12, 0x61, + 0x0A, 0x60, 0x0D, 0x63, 0x09, 0x00, 0x04, 0x2B, 0x04, 0x00, 0x14, 0x61, 0x0A, 0x60, 0x08, 0x63, + 0x03, 0x00, 0x16, 0x61, 0x0A, 0x60, 0x0C, 0x63, 0x1E, 0xF0, 0x40, 0x67, 0x2C, 0x60, 0x9C, 0x65, + 0x45, 0xD1, 0xD5, 0x81, 0x19, 0x60, 0x78, 0xF9, 0x2C, 0x60, 0x74, 0x65, 0x45, 0xD1, 0x1C, 0xFC, + 0xB0, 0x84, 0x1E, 0xFA, 0xFF, 0xFF, 0x0D, 0xF2, 0x3E, 0xF0, 0x60, 0x47, 0xFF, 0xB4, 0x64, 0x41, + 0x01, 0xB1, 0x01, 0x63, 0x17, 0x02, 0x60, 0x41, 0xFF, 0x22, 0x04, 0x00, 0xB8, 0x60, 0x58, 0x4F, + 0x06, 0x78, 0xFF, 0xFF, 0x07, 0x60, 0xED, 0xFD, 0x19, 0x60, 0xCF, 0xF3, 0xFF, 0xFF, 0x60, 0x41, + 0x01, 0x63, 0x61, 0x40, 0xFF, 0x22, 0x04, 0x00, 0xB8, 0x60, 0x58, 0x4F, 0x06, 0x78, 0xFF, 0xFF, + 0x07, 0x60, 0xEE, 0xFD, 0x02, 0x64, 0x3B, 0xDB, 0xBF, 0x60, 0xE4, 0x78, 0xFF, 0xFF, 0x66, 0x44, + 0xFC, 0xFB, 0x07, 0xF0, 0x00, 0x64, 0xD0, 0x80, 0xA6, 0xF3, 0x0E, 0x03, 0xD0, 0x80, 0xFF, 0xFF, + 0x0B, 0x03, 0x47, 0xF1, 0x07, 0xF0, 0x64, 0x40, 0x02, 0x26, 0x01, 0x00, 0x08, 0x00, 0x03, 0x12, + 0xBE, 0x60, 0xA0, 0x78, 0xFF, 0xFF, 0xFC, 0x0A, 0xBF, 0x60, 0x00, 0x78, 0xFF, 0xFF, 0x87, 0xF0, + 0xA6, 0xF3, 0x10, 0xF0, 0xD4, 0x80, 0xFF, 0xFF, 0x3D, 0x03, 0x66, 0x43, 0x65, 0x46, 0xFF, 0x67, + 0x20, 0x85, 0x64, 0x5F, 0x40, 0x44, 0x15, 0xF0, 0x25, 0x44, 0xD0, 0x84, 0x03, 0xA4, 0x03, 0x0E, + 0xE8, 0x84, 0xE8, 0x84, 0x04, 0x00, 0xFA, 0xA4, 0xE8, 0x84, 0xE8, 0x87, 0xC0, 0xBF, 0xC0, 0x84, + 0x15, 0xFA, 0x40, 0x45, 0x14, 0xF0, 0x24, 0x44, 0xD0, 0x84, 0x1F, 0xA4, 0x06, 0x0E, 0xE8, 0x84, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x07, 0x00, 0xC2, 0xA4, 0xE8, 0x84, 0xE8, 0x84, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x87, 0xF8, 0xBF, 0xC0, 0x84, 0x14, 0xFA, 0x60, 0x5C, 0x2F, 0x67, + 0xD0, 0x80, 0x60, 0x45, 0x02, 0x28, 0x64, 0x45, 0x25, 0x5C, 0x8B, 0x67, 0xD0, 0x80, 0x60, 0x41, + 0x02, 0x24, 0x64, 0x41, 0xD5, 0x84, 0x80, 0x65, 0xC4, 0x87, 0x01, 0x05, 0x00, 0x64, 0xFF, 0xB4, + 0x0E, 0xFA, 0x63, 0x46, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x17, 0xF2, 0x63, 0x46, 0x60, 0x40, + 0x00, 0x36, 0x2E, 0x00, 0x01, 0x36, 0x1E, 0x00, 0x03, 0x3A, 0x25, 0x00, 0x64, 0x46, 0x10, 0xF2, + 0x11, 0xFA, 0x12, 0xF2, 0x00, 0x61, 0x60, 0x47, 0x00, 0x7F, 0x12, 0xFA, 0x97, 0xFA, 0x46, 0x44, + 0x63, 0x46, 0xC2, 0x60, 0x58, 0x4E, 0x4C, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x00, 0x3A, 0x04, 0x00, + 0xC2, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x96, 0xFC, + 0x63, 0x46, 0x43, 0x00, 0x64, 0x46, 0x16, 0xF2, 0x00, 0x61, 0x20, 0x28, 0xFF, 0xA4, 0x97, 0xFA, + 0x16, 0xFA, 0x63, 0x46, 0x3A, 0x00, 0x64, 0x46, 0x00, 0x61, 0x97, 0xFA, 0x63, 0x46, 0x35, 0x00, + 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x16, 0xF2, 0xFF, 0xFF, 0x20, 0x28, 0xFF, 0xA4, 0x16, 0xFA, + 0x93, 0xF4, 0x12, 0xF2, 0x20, 0x28, 0xFF, 0xA3, 0x13, 0xFC, 0x61, 0x46, 0x63, 0x40, 0x00, 0x3A, + 0x24, 0x00, 0xC2, 0x60, 0x58, 0x4E, 0x6D, 0x78, 0xFF, 0xFF, 0x61, 0x40, 0xFF, 0x36, 0x1D, 0x00, + 0x66, 0x41, 0x64, 0x46, 0x12, 0xF2, 0x93, 0xF4, 0x61, 0x46, 0x20, 0x28, 0x16, 0x00, 0x44, 0x44, + 0xC2, 0x60, 0x58, 0x4E, 0x4C, 0x78, 0xFF, 0xFF, 0x24, 0x5C, 0x65, 0x40, 0x00, 0x36, 0x06, 0x00, + 0x66, 0x41, 0x64, 0x46, 0x01, 0x64, 0x17, 0xFA, 0x61, 0x46, 0x07, 0x00, 0x66, 0x43, 0x64, 0x46, + 0xC2, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0x63, 0x46, 0xBF, 0x60, 0x00, 0x78, 0xFF, 0xFF, + 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x17, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0xFF, 0x27, 0xFF, 0xFF, + 0x00, 0x36, 0x07, 0x00, 0x01, 0x36, 0x1C, 0x00, 0x02, 0x36, 0x24, 0x00, 0x03, 0x36, 0x43, 0x00, + 0xFF, 0xFF, 0x19, 0x60, 0xA9, 0xF1, 0x16, 0xF2, 0x43, 0x44, 0xD0, 0x80, 0x33, 0x60, 0x84, 0x61, + 0x09, 0x03, 0xA1, 0xD1, 0x33, 0x60, 0x82, 0x63, 0xC0, 0x84, 0x16, 0xFA, 0xA3, 0xD3, 0xFF, 0xFF, + 0x13, 0xFA, 0x39, 0x00, 0x96, 0xFC, 0xC2, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0x33, 0x00, + 0x43, 0x44, 0xC2, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0xC1, 0xF3, 0x96, 0xFC, + 0x13, 0xFA, 0x29, 0x00, 0x63, 0x46, 0x33, 0x60, 0x54, 0x63, 0xA3, 0xD3, 0x15, 0xF2, 0x60, 0x45, + 0xD4, 0x80, 0x07, 0xF0, 0x0C, 0x03, 0x66, 0x41, 0x44, 0x44, 0x64, 0x46, 0x12, 0xF2, 0x61, 0x46, + 0xC2, 0x60, 0x58, 0x4E, 0x4C, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x00, 0x3A, 0x19, 0x00, 0x66, 0x43, + 0x24, 0x46, 0xC2, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0x12, 0xF2, 0x91, 0xF2, 0x90, 0xFA, + 0x60, 0x5F, 0x12, 0xFA, 0x04, 0x00, 0xC2, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0x03, 0x64, + 0x17, 0xFA, 0x63, 0x46, 0x05, 0x00, 0x24, 0x43, 0x02, 0x64, 0x17, 0xFA, 0x63, 0x46, 0x00, 0x00, + 0x03, 0x64, 0x3B, 0xDB, 0xCA, 0xFE, 0x47, 0xF1, 0x01, 0x65, 0x32, 0x40, 0x04, 0x27, 0x11, 0x00, + 0x2C, 0xF2, 0x64, 0x45, 0x02, 0x22, 0x0D, 0x00, 0x60, 0x40, 0x01, 0x26, 0x0A, 0x00, 0x2A, 0xF2, + 0x39, 0xF0, 0x8F, 0xB0, 0x88, 0x3A, 0x77, 0x00, 0x64, 0x44, 0x60, 0xB0, 0x20, 0x36, 0x01, 0x00, + 0x72, 0x00, 0x14, 0xF2, 0x65, 0x40, 0x01, 0x26, 0x0C, 0x00, 0x60, 0x45, 0x05, 0x64, 0x3B, 0xDB, + 0x65, 0x44, 0xCC, 0x85, 0x2C, 0x60, 0xD0, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xF0, 0x78, 0xB5, 0xF1, + 0x50, 0x00, 0x60, 0x41, 0x2A, 0xF0, 0x00, 0x60, 0x0C, 0x64, 0xA0, 0x84, 0x04, 0x36, 0x02, 0x00, + 0x0C, 0x3A, 0x01, 0x00, 0x46, 0x00, 0x61, 0x45, 0x60, 0x43, 0x2C, 0x60, 0xD0, 0x64, 0xF1, 0x60, + 0x78, 0x41, 0xF0, 0x78, 0xB5, 0xF1, 0x63, 0x40, 0x08, 0x36, 0x01, 0x00, 0x3A, 0x00, 0x14, 0xF2, + 0x1C, 0x65, 0x60, 0x41, 0x00, 0x63, 0xCD, 0x81, 0xC7, 0x83, 0xFD, 0x02, 0x3F, 0xF0, 0x2C, 0xF2, + 0xC3, 0x83, 0x60, 0x40, 0x01, 0x2A, 0x0D, 0x00, 0x2C, 0x60, 0xCE, 0x64, 0xF1, 0x60, 0x78, 0x41, + 0xE4, 0x78, 0xB5, 0xF1, 0x2C, 0x60, 0xD4, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xEF, 0x78, 0x63, 0x45, + 0x20, 0x00, 0x2C, 0x60, 0xCC, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x2C, 0x60, + 0xD2, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xEF, 0x78, 0x63, 0x45, 0x15, 0xF2, 0xFF, 0xFF, 0x0F, 0xB4, + 0x00, 0xA8, 0x01, 0xA8, 0x0E, 0x03, 0x07, 0x03, 0x2C, 0x60, 0xDA, 0x64, 0xF1, 0x60, 0x78, 0x41, + 0xE4, 0x78, 0xB5, 0xF1, 0x06, 0x00, 0x2C, 0x60, 0xD8, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, + 0xB5, 0xF1, 0x04, 0x64, 0x3B, 0xDB, 0x25, 0x60, 0xEC, 0x64, 0x13, 0x60, 0x0A, 0xFB, 0x3C, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x5C, 0x5C, 0xFC, 0xFC, 0xCE, 0xFE, + 0xB8, 0x60, 0x37, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x50, 0xA8, 0x02, 0x7C, 0x09, 0x03, + 0x0F, 0xF0, 0x15, 0xF2, 0x64, 0x41, 0x01, 0x2A, 0x02, 0x00, 0xCD, 0xF1, 0x02, 0x00, 0xCC, 0xF1, + 0xFF, 0xFF, 0x64, 0x45, 0xDC, 0x84, 0xD4, 0x80, 0x15, 0xFA, 0x2D, 0x07, 0x61, 0x40, 0x01, 0x2A, + 0x08, 0x00, 0x16, 0x60, 0x80, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, + 0x07, 0x00, 0x16, 0x60, 0x81, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, + 0x2A, 0xF0, 0x08, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x00, 0x64, 0x48, 0xFB, 0x19, 0x60, 0xA3, 0xF3, + 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x0C, 0x00, 0x3C, 0x46, 0x3E, 0xF2, 0x40, 0x60, 0x00, 0x65, + 0xF0, 0x84, 0xA4, 0x84, 0x3D, 0xFA, 0x2A, 0xF2, 0xBF, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x2A, 0xFA, + 0xBA, 0x60, 0x02, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x49, 0xFB, 0x2C, 0x60, 0xDA, 0x64, 0xF1, 0x60, + 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x2C, 0x60, 0xDC, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, + 0xB5, 0xF1, 0x27, 0x44, 0xF7, 0xB4, 0x40, 0x47, 0x23, 0xF0, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDA, + 0x98, 0x01, 0xC0, 0x60, 0x5F, 0x78, 0xFF, 0xFF, 0x21, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0x01, 0x63, + 0xC4, 0xB4, 0x31, 0xFB, 0x32, 0xFD, 0xC0, 0x60, 0x14, 0x62, 0x42, 0x40, 0xA0, 0x4C, 0x40, 0xBC, + 0x7D, 0xB4, 0xA0, 0x51, 0xA0, 0xFE, 0x1A, 0xFF, 0x25, 0x60, 0xE0, 0x64, 0x08, 0xF0, 0x07, 0xF0, + 0xD0, 0x80, 0x25, 0x60, 0xE6, 0x62, 0x13, 0x02, 0xA2, 0xD3, 0x01, 0x63, 0xAC, 0x86, 0x07, 0xF2, + 0x0E, 0x03, 0xD0, 0x80, 0x09, 0xF2, 0xFA, 0x02, 0x23, 0xFC, 0x25, 0x60, 0xEC, 0x64, 0x13, 0x60, + 0x0A, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x3C, 0x46, + 0x06, 0x64, 0xA1, 0xFF, 0x49, 0xFB, 0x83, 0x3E, 0x31, 0xF3, 0x87, 0x60, 0x80, 0x61, 0x1D, 0xF0, + 0x60, 0x40, 0x01, 0x2A, 0x0F, 0x00, 0xFE, 0xB4, 0x31, 0xFB, 0x00, 0x64, 0x49, 0xFB, 0x01, 0x64, + 0x47, 0xFB, 0x00, 0x71, 0x05, 0x64, 0x64, 0x5F, 0x0D, 0xFA, 0x40, 0x64, 0x3B, 0xDB, 0xC0, 0x60, + 0x5F, 0x78, 0xFF, 0xFF, 0x02, 0x2A, 0x18, 0x00, 0xD1, 0x91, 0x8D, 0xE2, 0x41, 0x64, 0x3B, 0xDB, + 0x31, 0xF3, 0x33, 0x60, 0xA6, 0x63, 0xFD, 0xB4, 0x31, 0xFB, 0xA3, 0xD3, 0x02, 0x63, 0x60, 0x5C, + 0x0D, 0xF2, 0x47, 0xFD, 0xFF, 0xB5, 0x60, 0x47, 0xFF, 0xB4, 0xD0, 0x80, 0xDC, 0x84, 0x1F, 0x03, + 0x60, 0x47, 0xB4, 0x84, 0x0D, 0xFA, 0x1B, 0x00, 0x08, 0x2A, 0x07, 0x00, 0x42, 0x64, 0x3B, 0xDB, + 0x31, 0xF3, 0xFF, 0xFF, 0xF7, 0xB4, 0x31, 0xFB, 0x12, 0x00, 0x10, 0x2A, 0x09, 0x00, 0x43, 0x64, + 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, 0xEF, 0xB4, 0x31, 0xFB, 0xBF, 0x60, 0xE4, 0x78, 0xFF, 0xFF, + 0x44, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, 0xDF, 0xB4, 0x31, 0xFB, 0x00, 0x00, 0x2A, 0x64, + 0x3B, 0xDB, 0xB7, 0x60, 0xF7, 0x64, 0x40, 0x40, 0xBD, 0x60, 0xD7, 0x78, 0xFF, 0xFF, 0x0E, 0x60, + 0xDF, 0xF3, 0xFF, 0xFF, 0x02, 0xB5, 0x04, 0xB5, 0x04, 0x03, 0x03, 0x03, 0xC1, 0x60, 0x70, 0x78, + 0xFF, 0xFF, 0x31, 0x40, 0x01, 0x26, 0x16, 0x00, 0xA0, 0x4C, 0x49, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, + 0x0E, 0x60, 0xDF, 0xF3, 0xFF, 0xFF, 0x02, 0xB5, 0x04, 0xBC, 0x09, 0x03, 0x60, 0x40, 0x01, 0x26, + 0xED, 0xE2, 0xFE, 0xB4, 0xA2, 0xDB, 0xA0, 0x4C, 0x7D, 0xB4, 0xA0, 0x51, 0x03, 0x00, 0xA0, 0x4C, + 0x6D, 0xB4, 0xA0, 0x51, 0xDB, 0xF3, 0xFF, 0xFF, 0xFD, 0xA0, 0xFF, 0xFF, 0x08, 0x24, 0x59, 0x00, + 0x31, 0x40, 0x04, 0x2A, 0x38, 0x00, 0x01, 0x64, 0x19, 0x60, 0xF4, 0xFB, 0x6C, 0xF3, 0x73, 0xF3, + 0xCC, 0x83, 0x6C, 0xFD, 0xCC, 0x84, 0x73, 0xFB, 0x1E, 0x02, 0x31, 0x40, 0x02, 0x2A, 0x12, 0x00, + 0x6E, 0xF3, 0x6F, 0xF1, 0xCC, 0x84, 0x6E, 0xFB, 0x0D, 0x02, 0x6E, 0xF9, 0x31, 0x44, 0x08, 0xBC, + 0x40, 0x51, 0x71, 0xF3, 0x70, 0xF1, 0x00, 0xB8, 0x64, 0x45, 0x01, 0x03, 0x67, 0x45, 0x65, 0x50, + 0xCC, 0x84, 0x72, 0xFB, 0x16, 0x60, 0xAC, 0xF3, 0x6D, 0xF1, 0x00, 0xB8, 0x73, 0xF9, 0x03, 0x03, + 0x85, 0xF3, 0x6C, 0xFB, 0x04, 0x00, 0x6C, 0xF3, 0x85, 0xF1, 0x0D, 0x1B, 0x6C, 0xF9, 0x31, 0x40, + 0x01, 0x2A, 0x09, 0x00, 0x9D, 0xFE, 0x07, 0x05, 0xBA, 0xFE, 0x08, 0x64, 0x13, 0x60, 0x16, 0xFB, + 0x2D, 0xFF, 0xFF, 0xFF, 0xA3, 0xFE, 0x32, 0x40, 0x80, 0x2A, 0x12, 0x00, 0x31, 0x40, 0x04, 0x2A, + 0x0F, 0x00, 0x16, 0x60, 0xAC, 0xF3, 0x6C, 0xF1, 0x03, 0x1B, 0x31, 0x40, 0x02, 0x2A, 0x06, 0x00, + 0x73, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x07, 0x60, 0x5C, 0x19, 0x60, 0xF5, 0xF9, + 0x00, 0x64, 0x19, 0x60, 0xF4, 0xFB, 0x0E, 0x60, 0x37, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0xFF, 0x2B, + 0xA2, 0xDB, 0xCF, 0xF1, 0x07, 0x60, 0xE9, 0xF3, 0x64, 0x40, 0x02, 0x3A, 0x3A, 0x00, 0x0A, 0x60, + 0x18, 0xF1, 0x10, 0xB4, 0x90, 0x80, 0xFF, 0xFF, 0x34, 0x03, 0x0A, 0x60, 0x18, 0xFB, 0x01, 0x63, + 0x60, 0x40, 0x10, 0x22, 0x00, 0x63, 0x08, 0x60, 0xC1, 0xFD, 0x08, 0x60, 0xC5, 0xFD, 0x08, 0x60, + 0xC9, 0xFD, 0x08, 0x60, 0xCD, 0xFD, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x23, 0x21, 0x00, + 0x0B, 0x36, 0x07, 0x00, 0x0C, 0x36, 0x05, 0x00, 0x0D, 0x36, 0x03, 0x00, 0x0E, 0x36, 0x01, 0x00, + 0x18, 0x00, 0xDB, 0xF3, 0x01, 0x63, 0x0E, 0x60, 0x36, 0xFD, 0x60, 0x40, 0x03, 0x3A, 0x08, 0x00, + 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x09, 0x00, + 0x04, 0x3A, 0x07, 0x00, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x10, 0x64, 0x3B, 0xDB, 0x7E, 0xF3, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0xC4, 0x93, 0xC9, 0xFE, 0x49, 0xF3, 0x3C, 0x46, 0x25, 0x18, 0xCC, 0x84, 0x49, 0xFB, + 0x22, 0x02, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0xFC, 0xFC, 0x00, 0x64, 0x5C, 0x5C, 0x32, 0xFB, + 0x82, 0xFF, 0x5C, 0x47, 0x84, 0xFF, 0x62, 0xFF, 0x16, 0x60, 0x7E, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, + 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, 0x23, 0xF0, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x25, 0x60, + 0xEC, 0x64, 0x13, 0x60, 0x0A, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xC1, 0xFE, 0xCE, 0xFE, 0x69, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0xFD, 0xB4, 0xA2, 0xDB, + 0x61, 0x44, 0x01, 0xB0, 0x02, 0xB0, 0x0B, 0x03, 0x0A, 0x02, 0x9D, 0xFE, 0x08, 0x04, 0x1C, 0x60, + 0xCE, 0x64, 0x13, 0x60, 0x20, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x07, 0x00, + 0x7E, 0xF3, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x93, 0x1D, 0x60, + 0xBA, 0x63, 0xA3, 0xD3, 0xAD, 0x49, 0x20, 0xB5, 0x08, 0xB1, 0x22, 0x03, 0xE1, 0x81, 0x10, 0xB5, + 0x95, 0x81, 0x60, 0x41, 0x18, 0x02, 0x1D, 0x60, 0xBC, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, + 0xA4, 0xDB, 0x16, 0x02, 0x05, 0x64, 0xA4, 0xDB, 0x61, 0x44, 0x07, 0xB4, 0xFF, 0xFF, 0x10, 0x02, + 0x08, 0xB1, 0xE1, 0x81, 0x95, 0x81, 0xA3, 0xD3, 0x0B, 0x03, 0x08, 0xAC, 0x01, 0xBC, 0xA3, 0xDB, + 0xFF, 0xFF, 0x13, 0xFF, 0x05, 0x00, 0x10, 0xAC, 0xA3, 0xDB, 0x05, 0x7C, 0x0E, 0x60, 0xDE, 0xF9, + 0xB8, 0x60, 0x03, 0x78, 0xFF, 0xFF, 0x46, 0xF3, 0x45, 0xF1, 0x04, 0x1B, 0x64, 0x44, 0x02, 0x1B, + 0x07, 0x60, 0xED, 0xF3, 0x45, 0xFB, 0x00, 0x63, 0x46, 0xFD, 0x60, 0x41, 0x25, 0x64, 0x3B, 0xDB, + 0x27, 0x44, 0xEF, 0xB4, 0x40, 0x47, 0x00, 0xB9, 0x71, 0x40, 0x80, 0x27, 0x01, 0x12, 0x27, 0x03, + 0xC1, 0x60, 0xC5, 0x62, 0x84, 0xFF, 0x42, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, + 0xA0, 0x51, 0x2D, 0x0A, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, 0x27, 0x0A, + 0x71, 0x40, 0x80, 0x27, 0xF7, 0x12, 0x45, 0xF3, 0x48, 0x02, 0x11, 0x18, 0x1B, 0x60, 0xEE, 0xF3, + 0x1B, 0x60, 0xEF, 0xF3, 0x07, 0x18, 0x06, 0x18, 0xAC, 0x4C, 0x80, 0x26, 0x03, 0x00, 0x00, 0x64, + 0x45, 0xFB, 0x05, 0x00, 0x45, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0x45, 0xFB, 0xE3, 0x02, 0x06, 0x0A, + 0xA0, 0x4C, 0xFB, 0xB4, 0xA0, 0x51, 0xA4, 0x60, 0x58, 0x78, 0xFF, 0xFF, 0x84, 0xFF, 0xC1, 0x60, + 0xA3, 0x64, 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0xB0, 0x60, + 0x9E, 0x78, 0xFF, 0xFF, 0x3C, 0x44, 0xAC, 0x80, 0x32, 0xF1, 0x25, 0x03, 0x64, 0x40, 0x07, 0x22, + 0x22, 0x00, 0xA4, 0x60, 0x36, 0x78, 0xFF, 0xFF, 0xA0, 0x4C, 0x1C, 0xBC, 0xDF, 0xB4, 0xA0, 0x51, + 0x31, 0x40, 0x08, 0x2A, 0xEF, 0x01, 0x72, 0xF3, 0x70, 0xF1, 0x00, 0xA0, 0xDC, 0x80, 0x05, 0x03, + 0x08, 0x03, 0xCC, 0x84, 0x72, 0xFB, 0x67, 0x50, 0x08, 0x00, 0xCC, 0x84, 0x72, 0xFB, 0x64, 0x50, + 0x04, 0x00, 0x31, 0x44, 0xF7, 0xB4, 0x40, 0x51, 0x06, 0x00, 0x28, 0x64, 0x3A, 0xDB, 0xA0, 0x4C, + 0x30, 0xBC, 0xF3, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x28, 0x64, 0x3B, 0xDB, + 0x07, 0x60, 0xEE, 0xF3, 0x32, 0x40, 0x02, 0x27, 0x16, 0x00, 0x46, 0xFB, 0x14, 0x18, 0xC2, 0x60, + 0x33, 0x64, 0x84, 0xFF, 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x15, 0xBC, 0xF7, 0xB4, 0xA0, 0x51, + 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, 0x46, 0xF3, 0xB8, 0x0A, 0xDD, 0x02, + 0xCC, 0x84, 0x46, 0xFB, 0xF5, 0x02, 0x84, 0xFF, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0x82, 0xFF, + 0x27, 0x44, 0x08, 0xBC, 0x40, 0x47, 0xF9, 0xE1, 0x04, 0x00, 0x78, 0xE1, 0x31, 0x40, 0x01, 0x26, + 0xF9, 0xE1, 0xA4, 0x60, 0x2D, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0xAB, 0xF1, 0x60, 0x45, 0x33, 0x60, + 0x6A, 0x61, 0xC5, 0x83, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0x66, 0x45, 0x24, 0x46, 0x0E, 0xF2, + 0x65, 0x46, 0x64, 0x45, 0xD5, 0x81, 0x61, 0x45, 0x00, 0x7F, 0xD4, 0x80, 0x64, 0x43, 0x08, 0x04, + 0xE3, 0x83, 0x63, 0x45, 0xC5, 0x81, 0x61, 0x45, 0xD4, 0x80, 0x02, 0x65, 0x03, 0x07, 0x03, 0x00, + 0x00, 0x65, 0x01, 0x00, 0x01, 0x65, 0x2E, 0x58, 0xFF, 0xFF, 0x66, 0x43, 0x64, 0x46, 0x8F, 0xF0, + 0x12, 0xF2, 0x91, 0xF2, 0x60, 0x40, 0x10, 0x36, 0x05, 0x00, 0x12, 0x36, 0x08, 0x00, 0x0C, 0x36, + 0x0B, 0x00, 0x0F, 0x00, 0x40, 0x61, 0xA5, 0x80, 0x0A, 0x64, 0x13, 0x02, 0xF3, 0x01, 0x10, 0x61, + 0xA5, 0x80, 0x0E, 0x64, 0x0E, 0x02, 0xEE, 0x01, 0x08, 0x61, 0xA5, 0x80, 0x10, 0x64, 0x09, 0x02, + 0xE9, 0x01, 0xE1, 0x81, 0xA5, 0x80, 0x03, 0x05, 0xC8, 0x84, 0x03, 0x02, 0xE3, 0x01, 0xFF, 0x61, + 0x02, 0x00, 0x12, 0xFA, 0x91, 0xFA, 0x63, 0x46, 0x2E, 0x58, 0xFF, 0xFF, 0x8F, 0xF0, 0x12, 0xF2, + 0x91, 0xF2, 0x60, 0x40, 0x0A, 0x36, 0x05, 0x00, 0x0E, 0x36, 0x08, 0x00, 0x10, 0x36, 0x0B, 0x00, + 0x0F, 0x00, 0x08, 0x61, 0xA5, 0x80, 0x10, 0x7E, 0x11, 0x02, 0xF3, 0x01, 0x04, 0x61, 0xA5, 0x80, + 0x12, 0x7E, 0x0C, 0x02, 0xEE, 0x01, 0x20, 0x61, 0xA5, 0x80, 0x0C, 0x7E, 0x07, 0x02, 0xE9, 0x01, + 0xE9, 0x81, 0xA5, 0x80, 0x05, 0x05, 0xD8, 0x84, 0x01, 0x02, 0xE3, 0x01, 0x12, 0xFA, 0x91, 0xFA, + 0x2E, 0x58, 0xFF, 0xFF, 0x28, 0x40, 0x08, 0x3A, 0x06, 0x00, 0x04, 0x60, 0x40, 0x62, 0x3D, 0x60, + 0x58, 0x4D, 0x3B, 0x78, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x2B, 0x50, 0x00, + 0x28, 0x40, 0x08, 0x3A, 0x4D, 0x00, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x19, 0x60, + 0x52, 0xFB, 0x7D, 0xF1, 0x2B, 0x60, 0x82, 0x63, 0x64, 0x40, 0x01, 0x27, 0x3C, 0xA3, 0x29, 0x40, + 0x40, 0x2B, 0x1E, 0xA3, 0xBD, 0xD1, 0x63, 0x45, 0x44, 0x4E, 0x0E, 0x61, 0xBD, 0xD1, 0xCD, 0x81, + 0xD0, 0x80, 0x01, 0x03, 0xFB, 0x04, 0xCB, 0x83, 0x19, 0x60, 0x55, 0xF3, 0x39, 0xF1, 0xD7, 0x83, + 0xEB, 0x83, 0x2E, 0x41, 0x5D, 0x93, 0xDF, 0x83, 0x19, 0x60, 0x51, 0xFD, 0x19, 0x60, 0x50, 0xFB, + 0x53, 0x93, 0xDF, 0x80, 0x10, 0x03, 0x38, 0xF3, 0xCF, 0x83, 0x08, 0x03, 0xDF, 0x83, 0x0B, 0x02, + 0xDF, 0x83, 0xDC, 0x84, 0xF0, 0xA0, 0x38, 0xFB, 0x06, 0x03, 0x03, 0x00, 0xCC, 0x84, 0x38, 0xFB, + 0x02, 0x03, 0x00, 0x63, 0x02, 0x00, 0x08, 0x64, 0x38, 0xFB, 0xE3, 0x80, 0xFB, 0x83, 0xC3, 0x83, + 0x63, 0x44, 0xFC, 0xA0, 0x02, 0x0E, 0x08, 0x07, 0x08, 0x00, 0x04, 0xA4, 0xFF, 0xFF, 0x05, 0x0D, + 0xFC, 0x64, 0xFF, 0x7F, 0x60, 0x43, 0x01, 0x00, 0x04, 0x63, 0x39, 0xFD, 0x19, 0x60, 0x54, 0xFD, + 0x2F, 0x58, 0xFF, 0xFF, 0x19, 0x60, 0x74, 0xF3, 0x40, 0x4E, 0x60, 0x46, 0x2F, 0xDB, 0x44, 0x44, + 0xA1, 0xD3, 0xD9, 0x81, 0x48, 0x94, 0x24, 0x5C, 0xD0, 0x9C, 0x66, 0x42, 0x04, 0x06, 0xD2, 0x9C, + 0x2F, 0xD9, 0x64, 0x46, 0x24, 0x44, 0xE0, 0x84, 0x44, 0xD3, 0xA3, 0xDB, 0xFF, 0xB4, 0x60, 0x5C, + 0x66, 0x44, 0x22, 0xA4, 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, + 0x1F, 0x64, 0xA2, 0xD3, 0x60, 0x5C, 0x64, 0x5E, 0x60, 0x47, 0x2F, 0xD1, 0x28, 0xA3, 0xA3, 0xD9, + 0xD8, 0xA3, 0x2E, 0x42, 0x4E, 0x8E, 0xBD, 0xDB, 0xDB, 0x02, 0x2D, 0x58, 0xFF, 0xFF, 0x43, 0xFF, + 0x39, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x84, 0x3E, 0xFB, 0x01, 0x3D, 0x44, 0x00, 0xA8, 0xFF, 0xFF, + 0x03, 0x02, 0x40, 0xFF, 0x44, 0xFF, 0xF4, 0x01, 0xA0, 0x4C, 0x3D, 0x46, 0x2A, 0xF2, 0x46, 0x4D, + 0x92, 0xFC, 0x10, 0x25, 0x12, 0x00, 0x09, 0xE1, 0xA1, 0xFF, 0x2D, 0x46, 0x0F, 0xF2, 0x01, 0x29, + 0x06, 0x00, 0x2A, 0xF0, 0x40, 0xFF, 0x64, 0x40, 0x40, 0x2B, 0x08, 0xBC, 0x02, 0xBC, 0x0F, 0xFA, + 0x08, 0x25, 0xDD, 0x01, 0xCB, 0xFE, 0x5C, 0x5D, 0xDB, 0x01, 0x44, 0xFF, 0x31, 0xF2, 0x1D, 0x60, + 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, + 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, + 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, + 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, + 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x07, 0xFC, 0x3F, 0xF2, 0x09, 0x60, 0xB0, 0x65, + 0xD4, 0x80, 0x2A, 0xF2, 0xC0, 0x05, 0x08, 0x25, 0xAA, 0x01, 0x5C, 0x4B, 0x0C, 0x60, 0xEA, 0x61, + 0xA1, 0xDF, 0x2D, 0x46, 0x3B, 0xF2, 0xA6, 0xF1, 0x87, 0xF4, 0x60, 0x40, 0x20, 0x2B, 0xC1, 0x00, + 0xD3, 0x80, 0x2C, 0xF0, 0xB0, 0x03, 0x07, 0xF4, 0x64, 0x40, 0x01, 0x26, 0xA6, 0xF5, 0xBA, 0xF4, + 0x2D, 0x46, 0x04, 0x64, 0x04, 0xB3, 0x22, 0xF0, 0x03, 0x03, 0xC5, 0x60, 0xE2, 0x78, 0xFF, 0xFF, + 0x10, 0x64, 0xB0, 0x9C, 0x3B, 0xF2, 0x22, 0xF8, 0x60, 0x47, 0xC0, 0xB7, 0x02, 0xFE, 0xF0, 0x84, + 0xF0, 0x84, 0xF0, 0x84, 0x00, 0xA8, 0x40, 0x4A, 0x17, 0x03, 0xE0, 0x81, 0x61, 0x43, 0x42, 0xFE, + 0x00, 0x64, 0xF0, 0x84, 0xFE, 0x1F, 0x40, 0x4A, 0xE1, 0x84, 0xE0, 0x84, 0x2D, 0x46, 0x07, 0xF4, + 0xE0, 0x81, 0x3B, 0xF0, 0x2A, 0x47, 0x0C, 0x60, 0x38, 0x63, 0xA0, 0x84, 0x47, 0x9C, 0x10, 0x03, + 0x7C, 0x44, 0x00, 0x60, 0xB2, 0x63, 0x1C, 0x00, 0x07, 0xF4, 0x3B, 0xF0, 0x66, 0x44, 0x64, 0x40, + 0x80, 0x2B, 0x06, 0x00, 0x00, 0x60, 0x78, 0x7C, 0x00, 0x60, 0xA2, 0x63, 0x43, 0x4C, 0x10, 0x00, + 0x2D, 0x46, 0xC5, 0x60, 0xD5, 0x78, 0xFF, 0xFF, 0x2D, 0x46, 0x22, 0xF2, 0x10, 0x60, 0x00, 0x7C, + 0xB0, 0x84, 0x22, 0xFA, 0x32, 0x40, 0x04, 0x26, 0x25, 0x00, 0xC5, 0x60, 0xD5, 0x78, 0xFF, 0xFF, + 0xED, 0xFB, 0xEE, 0xF9, 0xEF, 0xFD, 0xAD, 0x46, 0x3D, 0xF2, 0xAD, 0x46, 0xA3, 0xD0, 0xAD, 0x46, + 0xD0, 0x80, 0x3C, 0xF2, 0xAD, 0x46, 0x02, 0x03, 0x15, 0x07, 0xE6, 0x04, 0x5B, 0xD0, 0xAD, 0x46, + 0xD0, 0x80, 0x3A, 0xF2, 0x03, 0x03, 0xAD, 0x46, 0x0D, 0x07, 0xDE, 0x04, 0x3A, 0xF0, 0xAD, 0x46, + 0x5B, 0xD0, 0x64, 0x44, 0xD0, 0x80, 0x2B, 0x44, 0x05, 0x07, 0xD6, 0x03, 0xD0, 0x84, 0x10, 0xA4, + 0xFF, 0xFF, 0x00, 0x07, 0xEE, 0xF3, 0xED, 0xF5, 0xFE, 0xA4, 0x0F, 0x60, 0xBE, 0x61, 0x0E, 0x63, + 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x2D, 0x46, 0x8B, 0xFF, 0x2D, 0x46, 0x22, 0xF2, 0x20, 0x60, + 0x00, 0x7C, 0xB0, 0x84, 0x22, 0xFA, 0x0F, 0x60, 0xB0, 0x64, 0xC9, 0x60, 0x58, 0x4F, 0x56, 0x78, + 0xFF, 0xFF, 0x3F, 0xF2, 0x00, 0x60, 0x18, 0x70, 0x18, 0x71, 0x20, 0x72, 0x60, 0x53, 0x88, 0x75, + 0x00, 0xF2, 0x09, 0xE1, 0x60, 0x50, 0x12, 0x71, 0x6E, 0x72, 0x83, 0x75, 0xA1, 0xFF, 0xFF, 0xFF, + 0x08, 0x25, 0x1D, 0x00, 0x40, 0xFF, 0x02, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x75, 0x40, 0x03, 0x2A, + 0x03, 0x00, 0x80, 0x75, 0x0A, 0x64, 0x0B, 0x00, 0x80, 0x75, 0x1B, 0xF3, 0x8B, 0xFF, 0x02, 0x60, + 0x00, 0x75, 0xFF, 0xFF, 0x02, 0x60, 0x00, 0x75, 0xDC, 0x84, 0xA2, 0xDB, 0x02, 0x64, 0x98, 0xFF, + 0x2D, 0x46, 0x0F, 0xF0, 0xFF, 0xFF, 0xB0, 0x84, 0xA2, 0xDA, 0x88, 0xFF, 0x0B, 0x01, 0x8B, 0xFF, + 0x02, 0x60, 0x00, 0x75, 0xFF, 0xFF, 0x02, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xC5, 0x60, 0xBB, 0x78, + 0xFF, 0xFF, 0x22, 0xF0, 0x22, 0x64, 0xB0, 0x84, 0x22, 0xFA, 0x3A, 0xF0, 0xFF, 0xFF, 0x64, 0x44, + 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5B, 0x64, 0x44, 0xE2, 0x7F, + 0xA0, 0x5B, 0x64, 0x47, 0x7C, 0x5F, 0xE8, 0x84, 0xE8, 0x85, 0x0D, 0x60, 0x00, 0x64, 0x44, 0xD3, + 0x5A, 0xD1, 0x03, 0x1B, 0xC5, 0x60, 0xD5, 0x78, 0xFF, 0xFF, 0x60, 0x45, 0x64, 0x44, 0xE3, 0x7F, + 0xA0, 0x5B, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5B, + 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5B, 0x65, 0x40, + 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xE9, 0x7F, + 0xA0, 0x5B, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5B, + 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5B, 0x64, 0x47, + 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xEF, 0x7F, 0xA0, 0x5B, 0x65, 0x44, 0xD8, 0x84, + 0x08, 0x25, 0x25, 0x00, 0x60, 0x7F, 0xA0, 0x5B, 0x80, 0x60, 0x00, 0xEB, 0xA0, 0x60, 0x00, 0xEB, + 0xD1, 0x60, 0x00, 0xEB, 0x22, 0xF2, 0x20, 0x60, 0x00, 0x7C, 0xB0, 0x84, 0x22, 0xFA, 0x3F, 0xF2, + 0x3B, 0xF0, 0x60, 0x43, 0xFC, 0xA4, 0x64, 0x40, 0x20, 0x2B, 0x04, 0x00, 0x08, 0xA4, 0x3F, 0xFA, + 0x08, 0xA3, 0xF8, 0xA3, 0x3F, 0xFA, 0x0A, 0xE1, 0xB3, 0xFF, 0x9A, 0xFF, 0xCB, 0x83, 0x00, 0xF4, + 0x10, 0x62, 0x6C, 0x61, 0x0E, 0xA3, 0xAB, 0x84, 0xF2, 0xA3, 0xA1, 0xFF, 0x09, 0x00, 0xDA, 0x00, + 0x00, 0xF4, 0x81, 0xF2, 0xFC, 0x18, 0x02, 0x62, 0xC9, 0x81, 0xAB, 0x84, 0x01, 0x00, 0xA2, 0xDC, + 0x7A, 0xD4, 0xFD, 0x1C, 0xA2, 0xDC, 0x08, 0x25, 0xCE, 0x00, 0xF2, 0x1D, 0x41, 0x44, 0x7C, 0xA8, + 0xD9, 0x81, 0xEE, 0x03, 0xFF, 0xB1, 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x64, 0x40, + 0x20, 0x27, 0x04, 0x00, 0x08, 0x25, 0xBF, 0x00, 0x7B, 0x1E, 0x6F, 0x00, 0x08, 0x25, 0xBB, 0x00, + 0x40, 0xFF, 0x42, 0x42, 0x46, 0x43, 0x06, 0x1E, 0x04, 0x02, 0x00, 0xF4, 0x02, 0x62, 0x42, 0x42, + 0x46, 0x43, 0x01, 0xA2, 0x63, 0x45, 0x01, 0xA2, 0x62, 0x43, 0x46, 0x4C, 0xC6, 0x60, 0x58, 0x4F, + 0x87, 0x78, 0xFF, 0xFF, 0x0A, 0xE1, 0x9A, 0xFF, 0x2D, 0x46, 0x12, 0xF2, 0x3B, 0xF0, 0x33, 0x1B, + 0x64, 0x40, 0x20, 0x2B, 0x38, 0x00, 0x2D, 0x5C, 0x24, 0x41, 0x02, 0xA1, 0x65, 0x43, 0x08, 0xA3, + 0x23, 0x46, 0x22, 0x42, 0x7E, 0x3A, 0x0A, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0xB8, 0x18, 0x02, 0x62, + 0xC9, 0x81, 0xAB, 0x84, 0x03, 0x00, 0xA2, 0xDC, 0x7E, 0x36, 0xF6, 0x01, 0x15, 0x11, 0x7A, 0xD4, + 0xFF, 0xFF, 0xF9, 0x1C, 0xA2, 0xDC, 0xF0, 0x1D, 0xD9, 0x81, 0xFF, 0xB1, 0x41, 0x1E, 0x62, 0x40, + 0x7E, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x02, 0x62, 0x07, 0x11, 0x5A, 0xD2, 0x89, 0xFF, 0x80, 0x4F, + 0x6F, 0x44, 0xA2, 0xDA, 0x88, 0xFF, 0x34, 0x00, 0x62, 0x45, 0x33, 0xF3, 0xFF, 0xFF, 0x03, 0x1B, + 0x65, 0x42, 0xE5, 0x1D, 0xF2, 0x01, 0x98, 0xFF, 0x2D, 0x46, 0x01, 0x64, 0x12, 0xFA, 0x0F, 0xF0, + 0x0A, 0x64, 0xB0, 0x84, 0x41, 0x00, 0x24, 0x41, 0x02, 0xA1, 0x65, 0x43, 0x08, 0xA3, 0x23, 0x46, + 0x22, 0x42, 0x7E, 0x3A, 0x0A, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0x5C, 0x18, 0x02, 0x62, 0xC9, 0x81, + 0xAB, 0x84, 0x03, 0x00, 0xA2, 0xDC, 0x7E, 0x36, 0xF6, 0x01, 0x7A, 0xD4, 0xFF, 0xFF, 0xFA, 0x1C, + 0xA2, 0xDC, 0xF1, 0x1D, 0xD9, 0x81, 0xFF, 0xB1, 0x0B, 0x1E, 0x62, 0x40, 0x7E, 0x3A, 0x02, 0x00, + 0x00, 0xF4, 0x02, 0x62, 0x5A, 0xD2, 0x89, 0xFF, 0x80, 0x4F, 0x6F, 0x44, 0xA2, 0xDA, 0x88, 0xFF, + 0x98, 0xFF, 0x2D, 0x46, 0x0F, 0xF0, 0x0A, 0x64, 0xB0, 0x84, 0x16, 0x14, 0xF7, 0xB4, 0xA2, 0xDA, + 0x06, 0x60, 0x75, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x0B, 0x00, 0xF0, 0xF5, 0xEF, 0xF4, + 0x0C, 0x60, 0xEA, 0x61, 0x59, 0xD1, 0x3B, 0xF8, 0x05, 0x64, 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, + 0xFC, 0x02, 0xC3, 0x60, 0x6A, 0x78, 0xFF, 0xFF, 0xA2, 0xDA, 0x2D, 0x46, 0x3B, 0xF0, 0xFF, 0xFF, + 0x64, 0x40, 0x20, 0x2B, 0x1C, 0x00, 0x07, 0xF4, 0xBB, 0xF0, 0x2A, 0x44, 0xA4, 0x84, 0xFF, 0xFF, + 0x2F, 0x26, 0x15, 0x00, 0x2D, 0x46, 0x64, 0x44, 0x3A, 0xF0, 0xBC, 0xF0, 0x64, 0x5F, 0x3D, 0xF0, + 0x07, 0xF4, 0xEF, 0xF4, 0xFF, 0xFF, 0x08, 0xA3, 0x5B, 0xD8, 0x65, 0x5C, 0x5B, 0xD8, 0x5B, 0xDA, + 0x2D, 0x46, 0xED, 0xF3, 0x3C, 0xFA, 0xEE, 0xF3, 0x3D, 0xFA, 0x2A, 0x44, 0x23, 0xFA, 0xC3, 0x60, + 0x6A, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0x98, 0xFF, 0x43, 0xFF, 0x40, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, + 0x2D, 0x46, 0x0C, 0x60, 0xEA, 0x61, 0xA1, 0xD3, 0x2D, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x0A, 0x00, + 0xF0, 0xF5, 0xEF, 0xF4, 0x59, 0xD1, 0x3B, 0xF8, 0x05, 0x64, 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, + 0xFC, 0x02, 0x2D, 0x46, 0xC3, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, + 0x2D, 0x46, 0x08, 0x25, 0xE0, 0x01, 0x0F, 0xF2, 0x40, 0xFF, 0x02, 0xBC, 0xA2, 0xDA, 0xC3, 0x60, + 0x6A, 0x78, 0xFF, 0xFF, 0xB0, 0x84, 0x22, 0xFA, 0xA0, 0x60, 0x00, 0xEB, 0xB0, 0x60, 0x00, 0xEB, + 0x00, 0x63, 0x3B, 0xF2, 0x06, 0x60, 0x75, 0xFD, 0x60, 0x47, 0xC0, 0xB7, 0x02, 0xFE, 0xF0, 0x84, + 0xF0, 0x84, 0xF0, 0x84, 0x00, 0xA8, 0x40, 0x4A, 0x16, 0x03, 0xE0, 0x81, 0x61, 0x43, 0x42, 0xFE, + 0x00, 0x64, 0xF0, 0x84, 0xFE, 0x1F, 0x40, 0x4A, 0xE1, 0x84, 0xE0, 0x84, 0x2D, 0x46, 0x07, 0xF4, + 0xE0, 0x81, 0x3B, 0xF0, 0x2A, 0x47, 0x0C, 0x60, 0x38, 0x63, 0xA0, 0x84, 0x47, 0x9C, 0x10, 0x03, + 0x7C, 0x44, 0xA8, 0x63, 0x0F, 0x00, 0x07, 0xF4, 0x20, 0x64, 0x40, 0x4A, 0x3B, 0xF0, 0x66, 0x44, + 0x64, 0x40, 0x80, 0x2B, 0x05, 0x00, 0x00, 0x60, 0x78, 0x7C, 0x00, 0x60, 0x98, 0x63, 0x02, 0x00, + 0x2D, 0x46, 0xBB, 0x01, 0x2D, 0x46, 0xED, 0xFB, 0xEE, 0xF9, 0xEF, 0xFD, 0x07, 0xF2, 0xF0, 0xFB, + 0x60, 0x46, 0x3B, 0xF0, 0x2A, 0x44, 0x06, 0x60, 0x76, 0xF9, 0x5C, 0x4B, 0xA0, 0x84, 0xFF, 0xFF, + 0x3F, 0x22, 0x05, 0x00, 0x90, 0x84, 0x3B, 0xFA, 0x01, 0x64, 0x40, 0x4B, 0x2C, 0x00, 0xAD, 0x46, + 0x0A, 0xA3, 0x3D, 0xF2, 0xAD, 0x46, 0xA3, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3C, 0xF2, 0xAD, 0x46, + 0x02, 0x03, 0x21, 0x07, 0x14, 0x04, 0x5B, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3B, 0xF2, 0x03, 0x03, + 0xAD, 0x46, 0x19, 0x07, 0x0C, 0x04, 0x3A, 0xF0, 0xAD, 0x46, 0x5B, 0xD0, 0x64, 0x5F, 0xD0, 0x80, + 0x2B, 0x44, 0x22, 0x07, 0x04, 0x03, 0xD0, 0x84, 0x10, 0xA4, 0xFF, 0xFF, 0x1D, 0x07, 0x2D, 0x46, + 0x22, 0xF2, 0x10, 0x60, 0x00, 0x7C, 0xB0, 0x84, 0x22, 0xFA, 0x32, 0x40, 0x04, 0x26, 0x14, 0x00, + 0xC5, 0x60, 0xD5, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x06, 0x60, 0x75, 0xFB, 0x2D, 0x46, 0x0C, 0x60, + 0xFA, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC6, 0x60, 0xBC, 0x78, 0xFF, 0xFF, + 0x85, 0xFF, 0x2D, 0x46, 0x08, 0x25, 0x4F, 0x01, 0x2D, 0x46, 0x0C, 0x60, 0xFA, 0x62, 0x80, 0xFF, + 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC7, 0x60, 0x44, 0x78, 0xFF, 0xFF, 0x85, 0xFF, 0x2D, 0x46, + 0x08, 0x25, 0x41, 0x01, 0x00, 0x60, 0x0F, 0x64, 0x08, 0x25, 0x3C, 0x01, 0x60, 0x7F, 0xA0, 0x5B, + 0x80, 0x60, 0x00, 0xEB, 0xD3, 0x60, 0x00, 0xEB, 0xC4, 0x60, 0xC2, 0x78, 0xFF, 0xFF, 0x2D, 0x46, + 0x3B, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x20, 0x2B, 0x23, 0x00, 0x08, 0x61, 0x23, 0x11, 0x2D, 0x46, + 0x00, 0xF4, 0x0A, 0x62, 0x56, 0x92, 0x5A, 0xD0, 0x2C, 0x46, 0x64, 0x47, 0x63, 0x40, 0x7F, 0x2A, + 0x03, 0x00, 0x00, 0xF4, 0x03, 0x63, 0x46, 0x4C, 0x60, 0xFE, 0xDE, 0xD8, 0x7F, 0x3A, 0x03, 0x00, + 0x00, 0xF4, 0x03, 0x63, 0x46, 0x4C, 0xDE, 0xDA, 0xFE, 0xA1, 0x20, 0xFE, 0xE7, 0x02, 0x63, 0x41, + 0xFD, 0xA1, 0x46, 0x4C, 0x01, 0xF2, 0x2D, 0x46, 0x61, 0x5E, 0x16, 0xFA, 0x2C, 0x44, 0x06, 0xFA, + 0x2F, 0x58, 0xFF, 0xFF, 0x2D, 0x5C, 0x3D, 0x44, 0x00, 0xA8, 0xD0, 0x80, 0xD8, 0x03, 0xD7, 0x03, + 0x2D, 0x46, 0x01, 0x64, 0x12, 0xFA, 0xF4, 0x01, 0x07, 0xF4, 0x66, 0x41, 0x03, 0xF2, 0x04, 0xF2, + 0x40, 0x42, 0x05, 0xF2, 0x40, 0x43, 0x40, 0x44, 0x61, 0x46, 0x3C, 0xF2, 0x3D, 0xF2, 0x40, 0x40, + 0x40, 0x41, 0x0D, 0x60, 0x70, 0x65, 0x00, 0x61, 0xEE, 0xF1, 0xED, 0xF5, 0x44, 0x4C, 0x2C, 0x5C, + 0xE9, 0x80, 0x00, 0x64, 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, 0x24, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x20, 0x44, 0x40, 0x80, 0xDB, 0x83, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x21, 0x44, 0x40, 0x81, 0xDB, 0x83, 0xBD, 0xD2, 0x21, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x22, 0x44, 0x40, 0x82, 0xDB, 0x83, 0xBD, 0xD2, 0x22, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x23, 0x44, 0x40, 0x83, 0xF2, 0xA3, 0xBD, 0xD2, 0x23, 0x5C, 0x90, 0x9C, + 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x47, 0x90, 0x9C, 0x24, 0x44, 0xC0, 0x9C, 0x41, 0x84, 0xDD, 0x81, 0x08, 0x2A, 0xA7, 0x01, + 0x0C, 0x60, 0xEC, 0x61, 0x05, 0x64, 0xEF, 0xF4, 0xF0, 0xF5, 0xFE, 0xA3, 0x5B, 0xD0, 0xCC, 0x84, + 0x59, 0xD9, 0xFC, 0x02, 0xEF, 0xF3, 0xF0, 0xF5, 0x60, 0x42, 0x20, 0x44, 0xA2, 0xDA, 0x21, 0x44, + 0x5A, 0xDA, 0x22, 0x44, 0x5A, 0xDA, 0x23, 0x44, 0x5A, 0xDA, 0x24, 0x44, 0x5A, 0xDA, 0x61, 0x46, + 0x06, 0x60, 0x7D, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x41, 0xEF, 0xF3, 0xF0, 0xF5, 0xA0, 0xD2, + 0x5A, 0xD0, 0x40, 0x40, 0x44, 0x41, 0x5A, 0xD2, 0x5A, 0xD0, 0x40, 0x42, 0x5A, 0xD0, 0x44, 0x43, + 0x61, 0x46, 0xBA, 0xF0, 0x3B, 0xF2, 0x44, 0x44, 0x65, 0x5F, 0x40, 0x85, 0xEE, 0xF4, 0xED, 0xF5, + 0x43, 0x4C, 0x0D, 0x60, 0x70, 0x65, 0xBD, 0xD2, 0x25, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x20, 0x44, 0x40, 0x80, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x21, 0x44, + 0x40, 0x81, 0xBD, 0xD2, 0x21, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x22, 0x44, 0x40, 0x82, + 0xBD, 0xD2, 0x22, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x23, 0x44, 0x40, 0x83, 0xBD, 0xD2, + 0x23, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x24, 0x44, 0x40, 0x84, 0xBD, 0xD2, 0x24, 0x5C, + 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x25, 0x44, 0x40, 0x85, 0x61, 0x46, 0x3A, 0xF0, 0xFF, 0xFF, + 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5B, 0x64, 0x44, + 0xE2, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xED, 0xF5, 0xBD, 0xD2, 0x25, 0x5C, 0x90, 0x84, 0xE8, 0x80, + 0xF8, 0x84, 0x20, 0x5C, 0x40, 0x80, 0x20, 0x44, 0xE4, 0x7F, 0xA0, 0x5B, 0x20, 0x47, 0xE5, 0x7F, + 0xA0, 0x5B, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x21, 0x5C, 0x40, 0x81, + 0x21, 0x44, 0xE6, 0x7F, 0xA0, 0x5B, 0x21, 0x47, 0xE7, 0x7F, 0xA0, 0x5B, 0x21, 0x44, 0xE8, 0x80, + 0xF8, 0x84, 0x22, 0x5C, 0x40, 0x82, 0x22, 0x44, 0xE8, 0x7F, 0xA0, 0x5B, 0x22, 0x47, 0xE9, 0x7F, + 0xA0, 0x5B, 0x22, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x23, 0x5C, 0x40, 0x83, 0x23, 0x44, 0xEA, 0x7F, + 0xA0, 0x5B, 0x23, 0x47, 0xEB, 0x7F, 0xA0, 0x5B, 0x23, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x24, 0x5C, + 0x40, 0x84, 0x24, 0x44, 0xEC, 0x7F, 0xA0, 0x5B, 0x24, 0x47, 0xED, 0x7F, 0xA0, 0x5B, 0x24, 0x44, + 0xE8, 0x80, 0xF8, 0x84, 0x25, 0x5C, 0x40, 0x85, 0x25, 0x44, 0xEE, 0x7F, 0xA0, 0x5B, 0x25, 0x47, + 0xEF, 0x7F, 0xA0, 0x5B, 0x2C, 0x43, 0xA3, 0xD2, 0x25, 0x5C, 0x90, 0x81, 0xE9, 0x84, 0xE3, 0x7F, + 0xA0, 0x5B, 0x06, 0x60, 0x7D, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0xF3, 0x5A, 0xD3, 0x40, 0x48, + 0x5A, 0xD3, 0x40, 0x49, 0x40, 0x4A, 0x00, 0x60, 0x78, 0x7C, 0x44, 0x4D, 0x49, 0xF2, 0x4A, 0xF2, + 0x40, 0x47, 0x40, 0x46, 0x0D, 0x60, 0x70, 0x65, 0x00, 0x61, 0x2D, 0x5C, 0xE9, 0x80, 0x00, 0x64, + 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, 0x2A, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x26, 0x44, 0x40, 0x86, 0xDB, 0x83, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x27, 0x44, 0x40, 0x87, 0xDB, 0x83, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x28, 0x44, 0x40, 0x88, 0xDB, 0x83, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x29, 0x44, 0x40, 0x89, 0xF2, 0xA3, 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x2A, 0x44, 0xC0, 0x9C, 0x41, 0x8A, 0xDD, 0x81, 0x08, 0x2A, 0xA7, 0x01, 0x26, 0x44, 0x44, 0xFA, + 0x27, 0x44, 0x45, 0xFA, 0x28, 0x44, 0x46, 0xFA, 0x29, 0x44, 0x47, 0xFA, 0x2A, 0x44, 0x48, 0xFA, + 0x06, 0x60, 0x7E, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x88, 0x7C, 0x44, 0x4D, 0x2D, 0x42, + 0xA2, 0xD2, 0x5A, 0xD0, 0x40, 0x46, 0x44, 0x47, 0x5A, 0xD2, 0x5A, 0xD0, 0x40, 0x48, 0x5A, 0xD0, + 0x44, 0x49, 0x4B, 0xF2, 0x44, 0x4A, 0x40, 0x8B, 0x60, 0x5C, 0x64, 0x47, 0xE0, 0x7F, 0xA0, 0x5A, + 0xFF, 0xB4, 0x20, 0xBC, 0x7F, 0xB4, 0xE1, 0x7F, 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5A, + 0x00, 0x60, 0x78, 0x63, 0x0D, 0x60, 0x70, 0x65, 0xBD, 0xD2, 0x2B, 0x5C, 0x90, 0x9C, 0x64, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, + 0x90, 0x9C, 0x26, 0x44, 0x40, 0x86, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, + 0x27, 0x44, 0x40, 0x87, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, + 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x28, 0x44, + 0x40, 0x88, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, + 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x29, 0x44, 0x40, 0x89, + 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2A, 0x44, 0x40, 0x8A, 0xBD, 0xD2, + 0x2A, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2B, 0x44, 0x40, 0x8B, 0xBD, 0xD2, 0x2B, 0x5C, + 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x26, 0x5C, 0x40, 0x86, 0x26, 0x44, 0xE4, 0x7F, 0xA0, 0x5A, + 0x26, 0x47, 0xE5, 0x7F, 0xA0, 0x5A, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, + 0x27, 0x5C, 0x40, 0x87, 0x27, 0x44, 0xE6, 0x7F, 0xA0, 0x5A, 0x27, 0x47, 0xE7, 0x7F, 0xA0, 0x5A, + 0x27, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x28, 0x5C, 0x40, 0x88, 0x28, 0x44, 0xE8, 0x7F, 0xA0, 0x5A, + 0x28, 0x47, 0xE9, 0x7F, 0xA0, 0x5A, 0x28, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x29, 0x5C, 0x40, 0x89, + 0x29, 0x44, 0xEA, 0x7F, 0xA0, 0x5A, 0x29, 0x47, 0xEB, 0x7F, 0xA0, 0x5A, 0x29, 0x44, 0xE8, 0x80, + 0xF8, 0x84, 0x2A, 0x5C, 0x40, 0x8A, 0x2A, 0x44, 0xEC, 0x7F, 0xA0, 0x5A, 0x2A, 0x47, 0xED, 0x7F, + 0xA0, 0x5A, 0x2A, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x2B, 0x5C, 0x40, 0x8B, 0x2B, 0x44, 0xEE, 0x7F, + 0xA0, 0x5A, 0x2B, 0x47, 0xEF, 0x7F, 0xA0, 0x5A, 0x3C, 0xF0, 0x2B, 0x44, 0x90, 0x84, 0xE8, 0x84, + 0xE3, 0x7F, 0xA0, 0x5A, 0x06, 0x60, 0x7E, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x60, 0x45, 0x00, 0xF0, + 0x84, 0x60, 0x00, 0xE3, 0x04, 0x71, 0x64, 0x50, 0x01, 0x2A, 0x04, 0x71, 0x5C, 0x61, 0x04, 0x63, + 0x59, 0xD0, 0x58, 0xD9, 0xFD, 0x1F, 0x3D, 0xF2, 0x60, 0x43, 0x60, 0x47, 0x5B, 0xDB, 0x3C, 0xF2, + 0xFF, 0xFF, 0x60, 0x47, 0x5B, 0xDB, 0x3A, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x5B, 0xDB, 0x3F, 0xF2, + 0xFF, 0xFF, 0x60, 0x47, 0x5B, 0xDB, 0x81, 0x60, 0x18, 0xE3, 0x65, 0x43, 0xE3, 0x84, 0x60, 0x47, + 0x00, 0x7F, 0x60, 0x50, 0x7F, 0x64, 0x23, 0x94, 0x60, 0x51, 0x7C, 0x72, 0x04, 0x75, 0x0C, 0x60, + 0x16, 0x61, 0x16, 0x60, 0x00, 0x63, 0x59, 0xDD, 0x2A, 0xF2, 0x87, 0x60, 0x8F, 0x65, 0xA4, 0x87, + 0x40, 0xBF, 0x59, 0xDB, 0x56, 0x64, 0x0A, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x62, 0x64, + 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x35, 0xF2, 0x0F, 0x65, 0xA4, 0x9C, 0x59, 0xD9, + 0x06, 0x63, 0x59, 0xDF, 0xFE, 0x1F, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x45, 0x03, 0x2B, 0x05, 0x00, + 0x6A, 0x64, 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x65, 0x40, 0x8F, 0xB0, 0x88, 0x3A, + 0x02, 0x00, 0x39, 0xF0, 0x59, 0xD9, 0x2F, 0x58, 0xFF, 0xFF, 0x0C, 0x60, 0x16, 0x61, 0xA3, 0x46, + 0x00, 0xF4, 0x02, 0x64, 0x0A, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x59, 0xDF, 0x59, 0xDF, + 0xA0, 0x4C, 0x04, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0x23, 0x44, 0x01, 0xA7, 0x80, 0xBF, 0x60, 0x50, + 0x80, 0x60, 0x38, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x01, 0x76, 0xFF, 0xFF, 0x76, 0x44, 0x01, 0x3A, + 0xFD, 0x01, 0x40, 0x76, 0x40, 0x76, 0x42, 0xFF, 0xFF, 0xFF, 0x40, 0x76, 0x80, 0x60, 0x18, 0x70, + 0x80, 0x60, 0x18, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x80, 0x60, 0x10, 0x73, 0x02, 0x76, 0x76, 0x44, + 0xFF, 0xFF, 0x76, 0x44, 0x02, 0x3A, 0xFD, 0x01, 0x40, 0x76, 0x42, 0xFF, 0x3C, 0x46, 0x00, 0xF2, + 0x80, 0x60, 0x00, 0xBC, 0x60, 0x50, 0x80, 0x60, 0x12, 0x71, 0x80, 0x60, 0x6E, 0x72, 0x3F, 0xF2, + 0xFF, 0xFF, 0xF8, 0xA7, 0x80, 0xBF, 0x60, 0x53, 0x04, 0x76, 0xFF, 0xFF, 0x88, 0xFF, 0x3C, 0x46, + 0x07, 0xF2, 0xFF, 0xFF, 0x40, 0x43, 0xA3, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x77, 0x40, 0x8B, 0xFF, + 0xA0, 0x4B, 0x04, 0xE1, 0xFF, 0xFF, 0x76, 0x44, 0x04, 0x3A, 0xFD, 0x01, 0x40, 0x76, 0x42, 0xFF, + 0xFF, 0xFF, 0x10, 0x76, 0xFF, 0xFF, 0x76, 0x44, 0x20, 0x3A, 0xFD, 0x01, 0x40, 0x76, 0x42, 0xFF, + 0x63, 0x44, 0x00, 0x7F, 0xA0, 0x51, 0x02, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xA0, 0x4C, 0xFB, 0xB4, + 0xA0, 0x51, 0x06, 0x60, 0x1F, 0xE1, 0x16, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xF2, + 0xFF, 0xFF, 0xF8, 0xA4, 0x3F, 0xFA, 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, 0xA0, 0x48, 0x08, 0x26, + 0x07, 0x00, 0xA0, 0x4C, 0x04, 0xE1, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, 0xA0, 0x51, + 0x42, 0xFF, 0x26, 0x46, 0x8B, 0xFF, 0x02, 0x60, 0x00, 0x75, 0x3C, 0xF2, 0x40, 0x76, 0x14, 0x1B, + 0x26, 0x46, 0x3B, 0xF2, 0x0C, 0x60, 0xBA, 0x63, 0x60, 0x47, 0xC0, 0xB4, 0xE8, 0x84, 0xE8, 0x84, + 0xE8, 0x84, 0x43, 0x93, 0xE3, 0x9C, 0x64, 0x47, 0x80, 0x7C, 0x64, 0x5F, 0x60, 0x50, 0x7F, 0x64, + 0x23, 0x97, 0x80, 0xBF, 0x60, 0x51, 0x07, 0x00, 0x01, 0xA7, 0x80, 0xBF, 0x60, 0x50, 0x80, 0x60, + 0x40, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x01, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x0C, 0x21, + 0xFC, 0x01, 0x04, 0x25, 0xD5, 0x01, 0x40, 0x76, 0x43, 0xFF, 0x0C, 0x60, 0x22, 0x61, 0x26, 0x46, + 0x00, 0xF4, 0x02, 0x64, 0x0A, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x59, 0xDF, 0x59, 0xDF, + 0x80, 0x60, 0x18, 0x70, 0x80, 0x60, 0x24, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x80, 0x60, 0x10, 0x73, + 0x02, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x0C, 0x21, 0xFC, 0x01, 0x04, 0x25, 0xB8, 0x01, + 0x40, 0x76, 0x43, 0xFF, 0x26, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x80, 0xBF, 0x60, 0x50, + 0x80, 0x60, 0x12, 0x71, 0x3F, 0xF2, 0x80, 0x60, 0x6E, 0x72, 0x60, 0x47, 0x80, 0xBF, 0x60, 0x53, + 0x04, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x0C, 0x21, 0xFC, 0x01, 0x04, 0x25, 0xA0, 0x01, + 0x40, 0x76, 0x43, 0xFF, 0x08, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x0C, 0x21, 0xFC, 0x01, + 0x04, 0x25, 0x96, 0x01, 0x76, 0x5C, 0xFF, 0xFF, 0x40, 0x76, 0x43, 0xFF, 0x88, 0xFF, 0x26, 0x46, + 0x2F, 0x58, 0xFF, 0xFF, 0xEE, 0x60, 0x60, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, + 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x00, 0xDB, 0xF3, 0x31, 0x41, 0x01, 0xB1, + 0x03, 0xA8, 0x2A, 0x03, 0x15, 0x02, 0x20, 0x40, 0x04, 0x2B, 0x0B, 0x00, 0xBB, 0xFE, 0xCA, 0xFE, + 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0x07, 0x00, 0x08, 0x60, 0x09, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x80, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0C, 0x00, + 0xA9, 0xFE, 0xDB, 0x05, 0xAB, 0xFE, 0x0C, 0x05, 0xA8, 0xFE, 0xCC, 0x05, 0xAA, 0xFE, 0xCD, 0x05, + 0x78, 0x43, 0x01, 0x61, 0x29, 0x60, 0xEA, 0x78, 0xA1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x85, 0x3E, + 0x13, 0x60, 0x02, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x03, 0x02, 0xCA, 0x60, 0xD4, 0x78, + 0xFF, 0xFF, 0x26, 0x45, 0xD4, 0x80, 0x0F, 0xF0, 0xF9, 0x03, 0x64, 0x44, 0x70, 0xB0, 0x70, 0x2A, + 0x13, 0x00, 0x16, 0x60, 0x85, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, + 0xA2, 0xFF, 0xAC, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0xFE, 0xA0, 0xAC, 0xFB, 0x01, 0x07, 0xD4, 0xFE, + 0xA3, 0xFF, 0xD0, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0x64, 0x40, 0x02, 0x26, 0x09, 0x00, 0x66, 0x45, + 0x09, 0xF4, 0x0F, 0xF2, 0x02, 0x18, 0x65, 0x46, 0xE4, 0x1B, 0x00, 0x64, 0x40, 0x46, 0xCC, 0x01, + 0xA2, 0xFF, 0xAC, 0xF3, 0x46, 0x46, 0xCC, 0x84, 0xFE, 0xA0, 0xAC, 0xFB, 0x01, 0x07, 0xD4, 0xFE, + 0xA3, 0xFF, 0x0F, 0xF0, 0xA3, 0xFC, 0x64, 0x44, 0x80, 0x26, 0x35, 0x00, 0x2C, 0x60, 0xEA, 0x64, + 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, 0x07, 0x60, + 0x01, 0x64, 0x22, 0x00, 0x02, 0x2A, 0x03, 0x00, 0x00, 0x60, 0x01, 0x64, 0x1D, 0x00, 0x04, 0x2A, + 0x1F, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x0C, 0xB0, 0x08, 0x3A, 0x1A, 0x00, 0x2C, 0xF0, 0x22, 0xF0, + 0x64, 0x40, 0x01, 0x26, 0x0B, 0x00, 0x64, 0x40, 0x40, 0x2B, 0x12, 0x00, 0x8F, 0xB0, 0x88, 0x3A, + 0x0F, 0x00, 0x39, 0xF2, 0xFF, 0xFF, 0x60, 0xB0, 0x20, 0x3A, 0x0A, 0x00, 0x23, 0xF2, 0x00, 0x60, + 0x01, 0x7C, 0xB0, 0x84, 0x23, 0xFA, 0x0C, 0x00, 0x23, 0xFA, 0xD0, 0x60, 0xC1, 0x78, 0xFF, 0xFF, + 0xD0, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x10, 0x27, 0xF8, 0x01, + 0x0F, 0xF0, 0xFF, 0xFF, 0x64, 0x44, 0x08, 0x26, 0x64, 0x00, 0x2A, 0xF2, 0x60, 0x63, 0x60, 0x40, + 0x02, 0x2B, 0x66, 0x63, 0xBE, 0xD2, 0x81, 0xF1, 0xA3, 0xD2, 0xD0, 0x80, 0x80, 0xF1, 0x0D, 0x02, + 0xBF, 0xD2, 0xD0, 0x80, 0x7F, 0xF1, 0x09, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x06, 0x02, 0x2C, 0x60, + 0xF6, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, + 0x07, 0x60, 0x02, 0x64, 0x04, 0x00, 0x02, 0x2A, 0x06, 0x00, 0x00, 0x60, 0x02, 0x64, 0x23, 0xFA, + 0xD0, 0x60, 0xC1, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0xB0, 0x3A, 0x06, 0x00, + 0x00, 0x60, 0x02, 0x64, 0x23, 0xFA, 0xCC, 0x60, 0x31, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x04, 0x2A, + 0x2D, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x0C, 0xB0, 0x08, 0x3A, 0x28, 0x00, 0x2C, 0xF0, 0x22, 0xF0, + 0x64, 0x40, 0x01, 0x26, 0x0B, 0x00, 0x64, 0x40, 0x40, 0x2B, 0x20, 0x00, 0x8F, 0xB0, 0x88, 0x3A, + 0x1D, 0x00, 0x39, 0xF2, 0xFF, 0xFF, 0x60, 0xB0, 0x20, 0x3A, 0x18, 0x00, 0x2C, 0xF0, 0x66, 0x45, + 0x07, 0xF4, 0x64, 0x40, 0x01, 0x26, 0xA6, 0xF5, 0x3A, 0xF2, 0x65, 0x46, 0x60, 0x40, 0x00, 0x36, + 0x0D, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x10, 0x2A, 0x08, 0x00, 0x20, 0x2B, 0x06, 0x00, + 0x23, 0xF2, 0x00, 0x60, 0x02, 0x7C, 0xB0, 0x84, 0x23, 0xFA, 0x03, 0x00, 0xD0, 0x60, 0xB5, 0x78, + 0xFF, 0xFF, 0x32, 0x44, 0x01, 0x2A, 0x4A, 0x00, 0x2E, 0x60, 0x40, 0x63, 0xBF, 0xD3, 0x00, 0x65, + 0xB4, 0x81, 0xDB, 0x83, 0x3D, 0x03, 0xBF, 0xD3, 0xA3, 0xD3, 0x40, 0x48, 0xBE, 0xD3, 0x40, 0x4A, + 0x2E, 0xF0, 0x40, 0x4C, 0xD0, 0x80, 0x2D, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x2C, 0xF0, + 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x2B, 0x03, 0x31, 0xF0, 0x2C, 0x44, 0xD0, 0x80, + 0x30, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x2F, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, + 0xFF, 0xFF, 0x1E, 0x03, 0x34, 0xF0, 0x2C, 0x44, 0xD0, 0x80, 0x33, 0xF0, 0x08, 0x02, 0x2A, 0x44, + 0xD0, 0x80, 0x32, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x11, 0x03, 0x38, 0xF0, + 0x2C, 0x44, 0xD0, 0x80, 0x37, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x36, 0xF0, 0x04, 0x02, + 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x04, 0x03, 0xFA, 0xA1, 0x06, 0xA3, 0xB7, 0x03, 0xC3, 0x01, + 0x07, 0x60, 0x00, 0x64, 0x23, 0xFA, 0xD0, 0x60, 0xC1, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x0F, 0xF0, + 0x60, 0x45, 0xA4, 0x36, 0x08, 0x00, 0x0C, 0xB4, 0x04, 0x36, 0x02, 0x00, 0x0C, 0x3A, 0x06, 0x00, + 0xD0, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0xCE, 0x60, 0x7C, 0x78, 0xFF, 0xFF, 0x0F, 0xF0, 0x65, 0x40, + 0x40, 0x2B, 0x17, 0x00, 0x32, 0x40, 0x08, 0x26, 0x14, 0x00, 0x07, 0xF4, 0x3A, 0xF2, 0xFF, 0xFF, + 0x37, 0xB4, 0x26, 0x46, 0x0E, 0x02, 0x2C, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x06, 0x00, + 0x2C, 0x60, 0xF0, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0xD0, 0x60, 0xB5, 0x78, + 0xFF, 0xFF, 0x2A, 0xF2, 0x64, 0x40, 0x60, 0x26, 0x03, 0x00, 0xCE, 0x60, 0x4E, 0x78, 0xFF, 0xFF, + 0x60, 0x41, 0xA6, 0xF3, 0x07, 0xFA, 0x61, 0x44, 0x80, 0x3A, 0x02, 0x00, 0x2A, 0xF2, 0x12, 0x00, + 0x60, 0x40, 0x40, 0x3A, 0x0F, 0x00, 0xDB, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, 0x03, 0x3A, 0xE6, 0x01, + 0xD1, 0x60, 0x58, 0x4D, 0xA6, 0x78, 0xFF, 0xFF, 0xE1, 0x02, 0xA6, 0xF3, 0x07, 0xFA, 0xCD, 0x60, + 0xE1, 0x78, 0xFF, 0xFF, 0x5E, 0x63, 0x60, 0x40, 0x02, 0x2B, 0x64, 0x63, 0x50, 0xFE, 0xBD, 0xD2, + 0x7F, 0xF1, 0xBD, 0xD2, 0xD0, 0x80, 0x80, 0xF1, 0xBD, 0xD2, 0xD0, 0x80, 0x81, 0xF1, 0x2A, 0xF2, + 0xD0, 0x80, 0x60, 0x40, 0x08, 0x3A, 0x09, 0x00, 0x01, 0x0C, 0xC8, 0x01, 0xE9, 0x60, 0x58, 0x4F, + 0x08, 0x78, 0xFF, 0xFF, 0xCD, 0x60, 0xE1, 0x78, 0xFF, 0xFF, 0x23, 0x0C, 0xD1, 0x60, 0x58, 0x4D, + 0xA6, 0x78, 0xFF, 0xFF, 0xBB, 0x02, 0x02, 0x64, 0x10, 0x60, 0x0A, 0xFB, 0x00, 0x64, 0x10, 0x60, + 0x0E, 0xFB, 0x26, 0x60, 0x58, 0x4E, 0x65, 0x78, 0xFF, 0xFF, 0x10, 0x60, 0x05, 0xF3, 0xFF, 0xFF, + 0x60, 0x40, 0x80, 0x27, 0x07, 0x00, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x64, 0x10, 0x60, 0x0A, 0xFB, 0xA0, 0x01, 0xCD, 0x60, 0xE1, 0x78, + 0xFF, 0xFF, 0xDB, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, 0xFD, 0xA0, 0xFF, 0xFF, 0x03, 0x03, 0x20, 0x40, + 0x10, 0x22, 0xF4, 0x01, 0x08, 0x60, 0x07, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x36, 0x07, 0x00, + 0x01, 0x64, 0xA2, 0xDB, 0x01, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0x31, 0xF2, 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, + 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, + 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, + 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, + 0x63, 0x46, 0xE8, 0x1B, 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0xA6, 0xF1, 0x43, 0x43, + 0xD3, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0xCD, 0x60, 0xD9, 0x78, 0xFF, 0xFF, 0xD0, 0x60, 0x58, 0x4F, + 0xFC, 0x78, 0xFF, 0xFF, 0x03, 0x4B, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xF4, 0xA3, 0x00, 0x60, + 0x1D, 0x61, 0x00, 0x60, 0x01, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, + 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x00, 0x02, 0x00, 0x64, 0x40, 0x4A, 0x60, 0xFE, + 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xFE, 0x60, 0x58, 0x4E, 0x2C, 0x78, + 0xFF, 0xFF, 0x20, 0xFE, 0x00, 0x65, 0x00, 0x64, 0x19, 0x60, 0x3B, 0xFB, 0x02, 0x00, 0x20, 0xFE, + 0xFF, 0x65, 0x02, 0x60, 0x00, 0x63, 0x60, 0xFE, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0x20, 0xFE, + 0xCD, 0x81, 0x60, 0x40, 0x80, 0x2A, 0x39, 0x00, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, 0x01, 0x64, + 0x2E, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x02, 0x64, 0x2A, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x04, 0x64, + 0x26, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x08, 0x64, 0x22, 0x00, 0x0C, 0x3A, 0x02, 0x00, 0x10, 0x64, + 0x1E, 0x00, 0x12, 0x3A, 0x02, 0x00, 0x20, 0x64, 0x1A, 0x00, 0x18, 0x3A, 0x02, 0x00, 0x40, 0x64, + 0x16, 0x00, 0x24, 0x3A, 0x02, 0x00, 0x80, 0x64, 0x12, 0x00, 0x30, 0x3A, 0x02, 0x00, 0x01, 0x67, + 0x0E, 0x00, 0x48, 0x3A, 0x02, 0x00, 0x02, 0x67, 0x0A, 0x00, 0x60, 0x3A, 0x02, 0x00, 0x04, 0x67, + 0x06, 0x00, 0x6C, 0x3A, 0x02, 0x00, 0x08, 0x67, 0x02, 0x00, 0x00, 0x64, 0x00, 0x00, 0x19, 0x60, + 0x3B, 0xF1, 0xFF, 0xFF, 0xB0, 0x84, 0x19, 0x60, 0x3B, 0xFB, 0x61, 0x40, 0x00, 0x36, 0x05, 0x00, + 0x60, 0xFE, 0xBD, 0xD3, 0xFF, 0xFF, 0x20, 0xFE, 0xBB, 0x01, 0x65, 0x40, 0x00, 0x3A, 0x1E, 0x00, + 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xF4, 0xA3, 0x00, 0x60, 0x1D, 0x61, 0x00, 0x60, + 0x32, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, 0x7A, 0x78, 0xFF, 0xFF, + 0x00, 0xBB, 0xFF, 0xFF, 0x0B, 0x03, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, + 0x60, 0x41, 0xFE, 0x60, 0x58, 0x4E, 0x2C, 0x78, 0xFF, 0xFF, 0x91, 0x01, 0x20, 0xFE, 0x00, 0x65, + 0xFC, 0x60, 0x58, 0x4E, 0xC7, 0x78, 0xFF, 0xFF, 0xA1, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, + 0x04, 0x00, 0xFD, 0x60, 0x58, 0x4E, 0x11, 0x78, 0xFF, 0xFF, 0x20, 0xFE, 0x37, 0x60, 0xF8, 0x61, + 0xA1, 0xD1, 0xA1, 0xF3, 0x01, 0x60, 0xAC, 0x63, 0x60, 0x45, 0x2A, 0x44, 0x79, 0xFB, 0xA3, 0xD5, + 0x65, 0x40, 0x01, 0x27, 0x5B, 0xD5, 0x65, 0x40, 0x01, 0x27, 0x59, 0xD1, 0x66, 0x41, 0xA0, 0x84, + 0x24, 0x94, 0x2B, 0x46, 0x0F, 0xFA, 0x7A, 0xFB, 0x16, 0x64, 0x12, 0xFA, 0x01, 0x64, 0x11, 0xFA, + 0x66, 0x5C, 0xC2, 0x60, 0x58, 0x4E, 0x6D, 0x78, 0xFF, 0xFF, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, + 0x01, 0x27, 0x28, 0x00, 0x19, 0x60, 0x44, 0xF3, 0x32, 0x60, 0x88, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, + 0x60, 0x40, 0x01, 0x2A, 0x0C, 0x00, 0x0F, 0x64, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, + 0xFF, 0x60, 0xFF, 0x63, 0x1A, 0x60, 0xB3, 0xFD, 0x1A, 0x60, 0xC3, 0xFD, 0x1C, 0x00, 0x19, 0x60, + 0x39, 0xF3, 0x3F, 0x40, 0x01, 0x27, 0x08, 0x00, 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xFC, 0x60, + 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, 0x0F, 0x00, 0x0F, 0xB4, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, + 0xFF, 0xFF, 0x09, 0x00, 0x19, 0x60, 0x3A, 0xF3, 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xFC, 0x60, + 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, 0xD3, 0x60, 0x58, 0x4E, 0x78, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0x23, 0x43, 0x32, 0x40, 0x08, 0x2A, 0x05, 0x00, 0x63, 0x46, 0x80, 0x60, 0x02, 0x64, 0x06, 0xFA, + 0x26, 0x46, 0x2C, 0x60, 0xE4, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x27, 0xF2, + 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x3B, 0x07, 0x00, 0x2C, 0x60, 0xF2, 0x64, 0xF1, 0x60, 0x78, 0x41, + 0xE4, 0x78, 0xB5, 0xF1, 0x08, 0x00, 0x02, 0x3B, 0x06, 0x00, 0x2C, 0x60, 0xF4, 0x64, 0xF1, 0x60, + 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x1B, 0xF2, 0xFF, 0xFF, 0xE4, 0xA4, 0x3E, 0xFA, 0x2A, 0xF2, + 0x28, 0x41, 0x40, 0xA8, 0x01, 0xB1, 0x02, 0x02, 0x46, 0x02, 0x76, 0x00, 0x60, 0x40, 0x08, 0x2A, + 0x0F, 0x00, 0x2C, 0x60, 0xE2, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x1B, 0xF2, + 0xFF, 0xFF, 0x60, 0x45, 0x2C, 0x60, 0xE8, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xF0, 0x78, 0xB5, 0xF1, + 0x0F, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x26, 0x28, 0x00, 0x32, 0x44, 0x02, 0x26, 0x25, 0x00, + 0x10, 0x2B, 0x29, 0x00, 0x2E, 0x60, 0x40, 0x63, 0xBF, 0xD3, 0x2C, 0xF0, 0x00, 0xA8, 0x60, 0x41, + 0x0D, 0x03, 0x50, 0xFE, 0xBD, 0xD3, 0x2D, 0xF0, 0xD0, 0x80, 0xBD, 0xD3, 0x2E, 0xF0, 0xD0, 0x80, + 0xBD, 0xD3, 0x2C, 0xF0, 0xD0, 0x80, 0xFA, 0xA1, 0x10, 0x0C, 0xF3, 0x02, 0x50, 0xFE, 0x60, 0x60, + 0x01, 0x64, 0xD0, 0x80, 0x2D, 0xF0, 0x1D, 0x64, 0xD0, 0x80, 0x2E, 0xF0, 0x01, 0x64, 0xD0, 0x80, + 0xFF, 0xFF, 0x03, 0x0C, 0xD0, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x40, 0x2A, 0x03, 0x00, + 0x1C, 0x60, 0x12, 0x78, 0xFF, 0xFF, 0xD0, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x40, 0x26, + 0xF7, 0x01, 0x2A, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x08, 0x2A, 0x2A, 0x00, 0xDB, 0xF3, 0xFF, 0xFF, + 0x07, 0xB4, 0x03, 0xA8, 0xFF, 0xFF, 0x03, 0x03, 0x32, 0x40, 0x02, 0x2A, 0x1D, 0x00, 0x03, 0x67, + 0xA0, 0x84, 0x00, 0x37, 0x64, 0x63, 0x60, 0x40, 0x02, 0x37, 0x5E, 0x63, 0x60, 0x40, 0x01, 0x37, + 0x58, 0x63, 0x60, 0x40, 0x03, 0x37, 0x0D, 0x00, 0xBD, 0xD2, 0x7F, 0xF1, 0xBD, 0xD2, 0xD0, 0x80, + 0x80, 0xF1, 0x07, 0x02, 0xD0, 0x80, 0xBD, 0xD2, 0x81, 0xF1, 0x03, 0x02, 0xD0, 0x80, 0xFF, 0xFF, + 0x03, 0x03, 0xD0, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0xE9, 0x60, 0x58, 0x4F, 0x08, 0x78, 0xFF, 0xFF, + 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x26, 0x06, 0x00, 0x20, 0x40, 0x10, 0x2B, 0x03, 0x00, + 0xD0, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x87, 0xF4, 0xA6, 0xF1, 0x27, 0x1B, 0x31, 0xF2, 0x1D, 0x60, + 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, + 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, + 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, + 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, + 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x03, 0x00, 0xD3, 0x80, 0xFF, 0xFF, 0xD6, 0x03, + 0x43, 0x43, 0xDB, 0xF3, 0x32, 0x40, 0x02, 0x26, 0x04, 0x00, 0x07, 0xB4, 0x03, 0xA8, 0x2A, 0xF2, + 0x45, 0x02, 0xA6, 0xF1, 0x23, 0x43, 0xD3, 0x80, 0xFF, 0xFF, 0x40, 0x02, 0xD0, 0x60, 0x58, 0x4F, + 0xFC, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x02, 0x2A, 0x05, 0x00, 0x63, 0x46, 0x02, 0x64, 0x06, 0xFA, + 0x26, 0x46, 0x34, 0x00, 0x32, 0x40, 0x08, 0x2A, 0x05, 0x00, 0x63, 0x46, 0x80, 0x60, 0x02, 0x64, + 0x06, 0xFA, 0x26, 0x46, 0x43, 0x43, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, 0x09, 0x00, + 0x19, 0x60, 0x44, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x03, 0x00, 0x23, 0x46, 0x0F, 0x64, + 0x10, 0x00, 0x37, 0x60, 0xF8, 0x61, 0xA1, 0xD1, 0xA1, 0xF3, 0x01, 0x60, 0xAC, 0x63, 0x60, 0x45, + 0xA3, 0xD3, 0x65, 0x40, 0x01, 0x27, 0x5B, 0xD3, 0x65, 0x40, 0x01, 0x27, 0x59, 0xD1, 0x23, 0x46, + 0xA0, 0x84, 0x0F, 0xFA, 0x7A, 0xFB, 0x79, 0xFB, 0x16, 0x64, 0x12, 0xFA, 0x01, 0x64, 0x11, 0xFA, + 0x66, 0x5C, 0xC2, 0x60, 0x58, 0x4E, 0x6D, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x07, 0xFC, 0x43, 0x43, + 0x2A, 0xF2, 0x63, 0x45, 0x0C, 0xB4, 0x08, 0x3A, 0x0A, 0x00, 0xDB, 0xF3, 0x23, 0x46, 0x07, 0xB4, + 0xFD, 0xA0, 0x06, 0xF2, 0x26, 0x46, 0x03, 0x03, 0x60, 0x40, 0x02, 0x2A, 0x0D, 0x00, 0x2A, 0xF2, + 0x35, 0xF0, 0x60, 0x40, 0xA4, 0x36, 0x0B, 0x00, 0x08, 0x2B, 0x0C, 0x00, 0x23, 0x46, 0x26, 0xF2, + 0x26, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x06, 0x02, 0xD0, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0xD0, 0x60, + 0x6B, 0x78, 0xFF, 0xFF, 0x23, 0x46, 0x22, 0xF2, 0x26, 0x46, 0x44, 0x4C, 0x0F, 0x26, 0x1D, 0x00, + 0x00, 0xBC, 0x40, 0x45, 0x0B, 0x03, 0x00, 0x64, 0x23, 0x46, 0x22, 0xFA, 0x26, 0x46, 0xA2, 0xFF, + 0xB6, 0x60, 0x58, 0x4E, 0xF5, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x26, 0x46, 0x2A, 0xF0, 0x2C, 0x44, + 0x64, 0x40, 0x04, 0x27, 0x0A, 0x00, 0x23, 0x46, 0x26, 0xFA, 0x26, 0x46, 0x1B, 0xF2, 0xFF, 0xFF, + 0xE4, 0xA4, 0x3E, 0xFA, 0xD0, 0x60, 0x22, 0x78, 0xFF, 0xFF, 0x3F, 0xF2, 0x02, 0xFA, 0xA2, 0xFF, + 0x16, 0xF0, 0xFF, 0xFF, 0x64, 0x44, 0x01, 0x26, 0xDC, 0x9C, 0xB0, 0xF3, 0x2A, 0xF2, 0xDC, 0x83, + 0xB0, 0xFD, 0x06, 0xF4, 0x01, 0xF8, 0x26, 0x46, 0x60, 0x40, 0x40, 0x2B, 0x18, 0x00, 0x64, 0x44, + 0x00, 0x65, 0xFF, 0xB4, 0xFC, 0xA4, 0x06, 0xF0, 0x03, 0x03, 0x64, 0x46, 0x0C, 0x0D, 0x02, 0x65, + 0x26, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x60, 0x46, 0xF9, 0x01, + 0x01, 0xF2, 0xFF, 0xFF, 0xD4, 0x84, 0x01, 0xFA, 0x66, 0x44, 0x26, 0x46, 0x06, 0xFA, 0x06, 0xF4, + 0x00, 0xF2, 0x80, 0xFC, 0x40, 0x45, 0xB6, 0x60, 0x58, 0x4E, 0xF5, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, + 0x26, 0x46, 0x2C, 0x44, 0x0F, 0x26, 0x13, 0x00, 0x23, 0x46, 0x26, 0xFA, 0x26, 0x44, 0x22, 0xFA, + 0x26, 0x46, 0x1B, 0xF2, 0xFF, 0xFF, 0xE4, 0xA4, 0x3E, 0xFA, 0x00, 0x64, 0x13, 0x60, 0x0D, 0xFB, + 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x6E, 0x00, 0xA3, 0x46, + 0x26, 0xF2, 0x60, 0x45, 0xDC, 0x84, 0xD4, 0x80, 0x26, 0xFA, 0xA3, 0x46, 0x6B, 0x02, 0x2A, 0xF0, + 0xA3, 0x46, 0x22, 0xF2, 0xA3, 0x46, 0x00, 0xBC, 0x00, 0xF2, 0x01, 0x02, 0x63, 0x00, 0x44, 0x4C, + 0x3F, 0xF0, 0x60, 0x43, 0x23, 0x46, 0x22, 0xF4, 0x09, 0x60, 0x00, 0x65, 0x3F, 0xF2, 0x26, 0x46, + 0xC0, 0x84, 0xD4, 0x80, 0x60, 0x45, 0x56, 0x07, 0x80, 0xFC, 0x1B, 0xF2, 0x06, 0xF2, 0x60, 0x41, + 0x23, 0x46, 0x22, 0xF4, 0x1B, 0xF0, 0x06, 0xF0, 0xC1, 0x81, 0x06, 0xFA, 0x05, 0xFA, 0x9B, 0xFA, + 0x65, 0x44, 0x3F, 0xFA, 0x64, 0x46, 0x00, 0xFC, 0x63, 0x46, 0x01, 0xF2, 0x10, 0x61, 0xF2, 0xA4, + 0x01, 0xFA, 0xC8, 0x83, 0x02, 0x64, 0x59, 0xD0, 0x58, 0xD8, 0xFD, 0x1F, 0x06, 0x45, 0x00, 0x64, + 0x13, 0x60, 0x0D, 0xFB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xA2, 0xFF, 0x00, 0xF4, 0x01, 0xF0, 0x0A, 0x18, 0x70, 0x67, 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, + 0xC0, 0x84, 0x01, 0xFA, 0x25, 0x46, 0x25, 0x44, 0x80, 0xFC, 0x05, 0xFA, 0xB6, 0x60, 0x58, 0x4E, + 0xF5, 0x78, 0xFF, 0xFF, 0xD4, 0xFE, 0xA3, 0xFF, 0x2C, 0x44, 0x04, 0x27, 0x16, 0x00, 0x23, 0x46, + 0x22, 0xF2, 0xA2, 0xFC, 0x60, 0x46, 0x46, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, + 0x26, 0x46, 0x2C, 0x43, 0x2A, 0xFC, 0x06, 0xF4, 0x00, 0x64, 0x00, 0xFA, 0x01, 0xF0, 0x80, 0x60, + 0x00, 0x64, 0xB0, 0x84, 0x01, 0xFA, 0x26, 0x46, 0x1D, 0x00, 0x00, 0x66, 0x46, 0x46, 0xCA, 0x60, + 0xD8, 0x78, 0xFF, 0xFF, 0xA3, 0x46, 0x22, 0xF0, 0xA2, 0xFC, 0x00, 0x63, 0x33, 0x85, 0xA3, 0x46, + 0x0D, 0x03, 0xA3, 0x46, 0x26, 0xF2, 0x0F, 0x65, 0xA4, 0x85, 0xD4, 0x84, 0x26, 0xFA, 0xA3, 0x46, + 0xA2, 0xFF, 0xB6, 0x60, 0x58, 0x4E, 0xF5, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x26, 0x46, 0xD0, 0x60, + 0xB5, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x32, 0xF0, 0x60, 0x40, 0x08, 0x2A, 0x24, 0x00, 0x01, 0x2B, + 0x13, 0x00, 0x64, 0x40, 0x01, 0x2A, 0x10, 0x00, 0x2C, 0x60, 0xE2, 0x64, 0xF1, 0x60, 0x78, 0x41, + 0xE4, 0x78, 0xB5, 0xF1, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, 0x2C, 0x60, 0xE8, 0x64, 0xF1, 0x60, + 0x78, 0x41, 0xF0, 0x78, 0xB5, 0xF1, 0x0F, 0x00, 0x2C, 0x60, 0xE0, 0x64, 0xF1, 0x60, 0x78, 0x41, + 0xE4, 0x78, 0xB5, 0xF1, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, 0x2C, 0x60, 0xE6, 0x64, 0xF1, 0x60, + 0x78, 0x41, 0xF0, 0x78, 0xB5, 0xF1, 0x07, 0xF4, 0xFF, 0xFF, 0x26, 0xF2, 0x26, 0x46, 0x0F, 0xB4, + 0xDC, 0x85, 0x2C, 0x60, 0xE4, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xF0, 0x78, 0xB5, 0xF1, 0x27, 0xF2, + 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x3B, 0x07, 0x00, 0x2C, 0x60, 0xF2, 0x64, 0xF1, 0x60, 0x78, 0x41, + 0xE4, 0x78, 0xB5, 0xF1, 0x08, 0x00, 0x02, 0x3B, 0x06, 0x00, 0x2C, 0x60, 0xF4, 0x64, 0xF1, 0x60, + 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x07, 0xF2, 0x26, 0xF0, 0x41, 0x18, 0x60, 0x46, 0xFF, 0x67, + 0x20, 0x88, 0x64, 0x5F, 0x40, 0x4A, 0x15, 0xF0, 0x28, 0x44, 0xD0, 0x84, 0x03, 0xA4, 0x03, 0x0E, + 0xE8, 0x84, 0xE8, 0x84, 0x04, 0x00, 0xFA, 0xA4, 0xE8, 0x84, 0xE8, 0x87, 0xC0, 0xBF, 0xC0, 0x84, + 0x15, 0xFA, 0x40, 0x48, 0x14, 0xF0, 0x2A, 0x44, 0xD0, 0x84, 0x1F, 0xA4, 0x06, 0x0E, 0xE8, 0x84, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x07, 0x00, 0xC2, 0xA4, 0xE8, 0x84, 0xE8, 0x84, + 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x87, 0xF8, 0xBF, 0xC0, 0x84, 0x14, 0xFA, 0x33, 0x60, 0x4C, 0x63, + 0xBD, 0xDB, 0x60, 0x5C, 0x2F, 0x67, 0xD0, 0x80, 0x60, 0x45, 0x02, 0x28, 0x64, 0x45, 0x28, 0x5C, + 0xBD, 0xD9, 0x8B, 0x67, 0xD0, 0x80, 0x60, 0x41, 0x02, 0x24, 0x64, 0x41, 0xD5, 0x84, 0x80, 0x65, + 0xC4, 0x87, 0x01, 0x05, 0x00, 0x64, 0xFF, 0xB4, 0x0E, 0xFA, 0xA3, 0xDB, 0x26, 0x46, 0xD1, 0x60, + 0xDB, 0x78, 0xFF, 0xFF, 0xCA, 0x60, 0xD8, 0x78, 0xFF, 0xFF, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, + 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xCA, 0x60, 0xD8, 0x78, + 0xFF, 0xFF, 0x25, 0x60, 0xFE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0x00, 0x66, 0x46, 0x46, 0xCA, 0x60, 0xD8, 0x78, + 0xFF, 0xFF, 0x2A, 0xF2, 0x58, 0x63, 0x60, 0x47, 0x01, 0x27, 0x64, 0x63, 0x61, 0x5C, 0x1B, 0x60, + 0xFB, 0xF9, 0xBD, 0xD0, 0xBD, 0xD0, 0x64, 0x45, 0x64, 0x41, 0xBD, 0xD0, 0x00, 0xF4, 0x04, 0xF8, + 0x83, 0xFA, 0x82, 0xF8, 0xA6, 0x46, 0x02, 0xB0, 0x5E, 0x63, 0x04, 0x03, 0x64, 0x63, 0x03, 0xB0, + 0x02, 0x3A, 0x6C, 0x63, 0x3F, 0xF2, 0xBD, 0xD0, 0xBD, 0xD0, 0x64, 0x45, 0x64, 0x41, 0xBD, 0xD0, + 0xA6, 0x46, 0x07, 0xF8, 0x86, 0xFA, 0x85, 0xF8, 0x60, 0x47, 0x08, 0xFA, 0x1B, 0x60, 0xFB, 0xF1, + 0x26, 0x46, 0x64, 0x41, 0x2F, 0x58, 0xFF, 0xFF, 0xA6, 0xF5, 0x00, 0xF2, 0x26, 0x46, 0x31, 0xF0, + 0x39, 0x18, 0x66, 0x41, 0x1D, 0x60, 0xC0, 0x65, 0x64, 0x47, 0x00, 0x7F, 0xA6, 0xF1, 0xE0, 0x84, + 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, + 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, + 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, + 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, + 0x1F, 0x60, 0xC2, 0x61, 0xA1, 0xD3, 0x20, 0x60, 0x04, 0x7C, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, + 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, 0x49, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xA1, 0xDB, 0xD1, 0x60, + 0x97, 0x78, 0xFF, 0xFF, 0x20, 0x7C, 0x72, 0x44, 0xFF, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x04, + 0xD0, 0x84, 0xFB, 0x01, 0xE0, 0x83, 0xA6, 0xF3, 0x02, 0xA3, 0x43, 0x93, 0xA6, 0xF3, 0xFF, 0xFF, + 0x02, 0xA5, 0xD7, 0x80, 0x04, 0xA5, 0x08, 0x24, 0x65, 0x43, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, + 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x1D, 0x60, 0xC0, 0x65, + 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0xA6, 0xF3, + 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, + 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x31, 0xF0, + 0x66, 0x41, 0x1D, 0x60, 0xC0, 0x65, 0x64, 0x47, 0x00, 0x7F, 0xA6, 0xF1, 0xE0, 0x84, 0x44, 0xD3, + 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, + 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, + 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, + 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, 0x2F, 0xF2, + 0x30, 0xF0, 0x31, 0xF0, 0x64, 0x45, 0x46, 0x43, 0x63, 0x46, 0x03, 0xFA, 0x06, 0xF2, 0x84, 0xF8, + 0x00, 0x7E, 0x06, 0xFA, 0x05, 0xF8, 0xA3, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0xDB, 0xF3, 0x2A, 0xF2, + 0x07, 0xB0, 0x03, 0x3A, 0x2A, 0x00, 0x00, 0xF4, 0x09, 0xF2, 0x60, 0x45, 0x80, 0x3A, 0x05, 0x00, + 0x0E, 0xF2, 0xFF, 0xFF, 0x02, 0xB0, 0x0F, 0xF2, 0x20, 0x03, 0x60, 0x47, 0x00, 0x3A, 0x1D, 0x00, + 0x60, 0x41, 0x00, 0x36, 0x13, 0x00, 0xDA, 0x85, 0x33, 0x60, 0xBE, 0x63, 0xBD, 0xD1, 0xFF, 0xFF, + 0xD1, 0x80, 0xFF, 0xFF, 0x12, 0x02, 0x60, 0xFE, 0xBD, 0xD3, 0xA5, 0xD0, 0xDE, 0x85, 0xD0, 0x80, + 0xCD, 0x81, 0x0B, 0x02, 0xF9, 0x02, 0x20, 0xFE, 0x00, 0x64, 0x09, 0x00, 0x26, 0x46, 0x48, 0xFE, + 0x65, 0x40, 0x40, 0x3A, 0x02, 0x00, 0x01, 0x64, 0x02, 0x00, 0x28, 0xFE, 0x00, 0x64, 0x40, 0x48, + 0x26, 0x46, 0x2D, 0x58, 0xFF, 0xFF, 0x19, 0x60, 0xA3, 0xF3, 0x3D, 0xF2, 0x60, 0x40, 0x01, 0x26, + 0x2A, 0xFA, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x26, 0x03, 0x00, 0xD2, 0x60, 0xB5, 0x78, + 0xFF, 0xFF, 0x3F, 0xF0, 0x32, 0x40, 0x10, 0x2A, 0x0E, 0x00, 0x2C, 0xF0, 0x64, 0x41, 0x60, 0x40, + 0x40, 0x27, 0x09, 0x00, 0xCD, 0x81, 0xDD, 0x81, 0x06, 0x03, 0x05, 0x03, 0x64, 0x40, 0x01, 0x26, + 0x02, 0x00, 0x01, 0x61, 0x01, 0x00, 0x00, 0x61, 0x60, 0x40, 0x18, 0x36, 0x1F, 0x00, 0xD0, 0x60, + 0x58, 0x4F, 0xD1, 0x78, 0xFF, 0xFF, 0x0F, 0xF0, 0xEA, 0xF1, 0x64, 0x44, 0x60, 0x22, 0x19, 0x00, + 0xDB, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, 0xFD, 0xA0, 0x2A, 0xF2, 0x03, 0x02, 0x08, 0xB0, 0xFF, 0xFF, + 0x10, 0x02, 0x32, 0xF2, 0x33, 0xF2, 0xD0, 0x80, 0xEB, 0xF1, 0x0B, 0x02, 0xD0, 0x80, 0x34, 0xF2, + 0x08, 0x02, 0xEC, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0x0F, 0xF0, 0x03, 0x02, 0xD3, 0x60, 0x10, 0x78, + 0xFF, 0xFF, 0x00, 0xF4, 0xAA, 0x60, 0xAA, 0x65, 0x09, 0xF2, 0x5A, 0xD0, 0xD4, 0x80, 0x03, 0x64, + 0x57, 0x02, 0xD0, 0x80, 0x00, 0x64, 0x5A, 0xD0, 0x53, 0x02, 0x64, 0x45, 0xD4, 0x80, 0xF8, 0x7F, + 0x08, 0x02, 0x5A, 0xD0, 0x26, 0x46, 0x64, 0x45, 0x23, 0xF0, 0x20, 0x67, 0xB0, 0x84, 0xA2, 0xDA, + 0x0B, 0x00, 0xD4, 0x80, 0x1D, 0x60, 0x60, 0x64, 0x16, 0x02, 0x5A, 0xD0, 0x26, 0x46, 0x64, 0x45, + 0x23, 0xF0, 0x40, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x65, 0x44, 0x88, 0x3A, 0x07, 0x00, 0x77, 0x37, + 0x08, 0x00, 0x78, 0x37, 0x06, 0x00, 0x8E, 0x37, 0x04, 0x00, 0x32, 0x00, 0x81, 0x3A, 0x30, 0x00, + 0x80, 0x37, 0x00, 0x61, 0x2D, 0x00, 0xD4, 0x80, 0x01, 0x60, 0x00, 0x64, 0x5A, 0xD0, 0x28, 0x02, + 0xD0, 0x80, 0x5A, 0xD0, 0x25, 0x02, 0x26, 0x46, 0x64, 0x47, 0x7F, 0xB4, 0xFD, 0xA0, 0x09, 0x03, + 0x1F, 0x07, 0x32, 0x40, 0x02, 0x26, 0x44, 0x00, 0x23, 0xF0, 0x60, 0x67, 0xB0, 0x84, 0xA2, 0xDA, + 0x3F, 0x00, 0x0F, 0xF2, 0x32, 0x40, 0x02, 0x26, 0x3B, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, + 0x08, 0x2A, 0x07, 0x00, 0x60, 0x40, 0x48, 0x36, 0x04, 0x00, 0xF1, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, + 0xF1, 0xFB, 0xF4, 0x60, 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, 0xD3, 0x60, 0x1A, 0x78, 0xFF, 0xFF, + 0x26, 0x46, 0x61, 0x40, 0x01, 0x2A, 0x07, 0x00, 0x2C, 0x60, 0xF8, 0x64, 0xF1, 0x60, 0x78, 0x41, + 0xE4, 0x78, 0xB5, 0xF1, 0x85, 0x00, 0x0F, 0xF2, 0x7F, 0xF1, 0x2A, 0xF2, 0x60, 0x40, 0x20, 0x2A, + 0x12, 0x00, 0x5E, 0x63, 0x60, 0x40, 0x02, 0x2B, 0x64, 0x63, 0xBD, 0xD2, 0xBD, 0xD2, 0xD0, 0x80, + 0x80, 0xF1, 0x08, 0x02, 0xD0, 0x80, 0xA3, 0xD2, 0x81, 0xF1, 0x04, 0x02, 0xD0, 0x80, 0xFF, 0xFF, + 0x01, 0x02, 0x06, 0x00, 0x6D, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, 0x36, 0x68, 0x00, + 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x2A, 0x07, 0x00, 0x60, 0x40, 0x48, 0x36, 0x04, 0x00, + 0xF1, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xF1, 0xFB, 0x68, 0x00, 0x26, 0x46, 0x2A, 0xF2, 0xFF, 0xFF, + 0xFF, 0xFF, 0x0C, 0x26, 0x55, 0x00, 0xB0, 0x36, 0x15, 0x00, 0x10, 0x36, 0x13, 0x00, 0x30, 0x36, + 0x11, 0x00, 0xC0, 0x36, 0x02, 0x00, 0xA0, 0x3A, 0x12, 0x00, 0x7F, 0xF1, 0x32, 0xF2, 0x33, 0xF2, + 0xD0, 0x80, 0x80, 0xF1, 0x45, 0x02, 0xD0, 0x80, 0x34, 0xF2, 0x81, 0xF1, 0x41, 0x02, 0xD0, 0x80, + 0xFF, 0xFF, 0x3E, 0x02, 0xE6, 0x60, 0x58, 0x4F, 0x3D, 0x78, 0xFF, 0xFF, 0x35, 0x00, 0x50, 0x3A, + 0x05, 0x00, 0xF8, 0x60, 0x58, 0x4F, 0xE1, 0x78, 0xFF, 0xFF, 0x2E, 0x00, 0x40, 0x3A, 0x05, 0x00, + 0xF0, 0x60, 0x58, 0x4F, 0x99, 0x78, 0xFF, 0xFF, 0x27, 0x00, 0x80, 0x3A, 0x24, 0x00, 0x7F, 0xF1, + 0x32, 0xF2, 0x33, 0xF2, 0xD0, 0x80, 0x80, 0xF1, 0x23, 0x02, 0xD0, 0x80, 0x34, 0xF2, 0x81, 0xF1, + 0x1F, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x1C, 0x02, 0xE9, 0x60, 0x58, 0x4F, 0x30, 0x78, 0xFF, 0xFF, + 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, 0x0A, 0x00, 0x19, 0x60, 0x4C, 0xF3, 0xFF, 0xFF, + 0x60, 0x40, 0x08, 0x26, 0x04, 0x00, 0xEE, 0x60, 0x58, 0x4F, 0x81, 0x78, 0xFF, 0xFF, 0x24, 0x60, + 0x58, 0x4F, 0xE3, 0x78, 0xFF, 0xFF, 0x04, 0x00, 0x66, 0x44, 0x00, 0xA8, 0xFF, 0xFF, 0x0A, 0x03, + 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, + 0x00, 0x66, 0x46, 0x46, 0xD0, 0x60, 0xB2, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x3B, 0xF0, 0x60, 0x40, + 0x40, 0x2B, 0x06, 0x00, 0xC0, 0x60, 0x00, 0x64, 0x64, 0x40, 0x20, 0x2B, 0x01, 0x00, 0x03, 0x00, + 0xD3, 0x60, 0x4C, 0x78, 0xFF, 0xFF, 0x22, 0xF2, 0xFF, 0xFF, 0x04, 0xB4, 0xFF, 0xFF, 0xF8, 0x03, + 0x23, 0xF2, 0x07, 0xF4, 0xBB, 0xF0, 0x26, 0x46, 0xA4, 0x84, 0xFF, 0xFF, 0x60, 0x40, 0x2F, 0x26, + 0xD7, 0x01, 0x12, 0xF0, 0xFF, 0xFF, 0x10, 0x1B, 0xCA, 0x60, 0x58, 0x4F, 0x16, 0x78, 0xFF, 0xFF, + 0x64, 0x40, 0x18, 0x36, 0x09, 0x00, 0x04, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, + 0x26, 0x46, 0xD3, 0x60, 0x10, 0x78, 0xFF, 0xFF, 0x25, 0x60, 0xFE, 0x64, 0x13, 0x60, 0x0D, 0xFB, + 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0xC0, 0x01, + 0x1C, 0x60, 0x92, 0x63, 0x00, 0x64, 0xA3, 0xDB, 0x06, 0xA3, 0x10, 0x60, 0x94, 0x64, 0xBD, 0xDB, + 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, 0x00, 0x63, 0x08, 0x60, 0x77, 0xFD, 0xD9, 0x60, 0xA5, 0x64, + 0x08, 0x60, 0x49, 0xFB, 0xD9, 0x60, 0x6A, 0x64, 0x08, 0x60, 0x35, 0xFB, 0x00, 0x60, 0x02, 0x64, + 0x08, 0x60, 0x16, 0xFB, 0xD3, 0x60, 0x9C, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x7D, 0xF3, 0x33, 0x60, 0x20, 0x63, 0x60, 0x40, 0x01, 0x27, 0x03, 0x00, 0x19, 0x60, 0x3B, 0xF3, + 0x02, 0x00, 0x19, 0x60, 0x3C, 0xF3, 0x08, 0x61, 0x60, 0xFE, 0xA3, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, + 0x00, 0xA8, 0xE8, 0x84, 0x0F, 0x03, 0x60, 0xFE, 0x02, 0x28, 0xF6, 0x01, 0x80, 0x62, 0xB2, 0x9C, + 0xBD, 0xD9, 0x7B, 0xF9, 0xCD, 0x81, 0x00, 0x36, 0x01, 0x00, 0xEE, 0x01, 0x36, 0x60, 0x0A, 0x63, + 0x08, 0x61, 0xEA, 0x01, 0x2E, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0xBA, 0xFE, 0x16, 0x60, 0x87, 0xF3, 0xFF, 0xFF, 0x03, 0xA8, 0x02, 0xA8, 0x04, 0x03, 0x28, 0x02, + 0xD9, 0x60, 0x41, 0x78, 0xFF, 0xFF, 0xD8, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, + 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x11, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xAC, 0xF3, + 0xFF, 0xFF, 0xFE, 0xA0, 0xFF, 0xFF, 0x0A, 0x07, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, + 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x20, 0x60, 0x20, 0x65, + 0xA5, 0xDF, 0x00, 0x64, 0x08, 0x60, 0x27, 0xFB, 0x5A, 0xDB, 0xD4, 0x60, 0xF6, 0x78, 0xFF, 0xFF, + 0x01, 0x63, 0x0E, 0x60, 0x36, 0xFD, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x64, + 0x08, 0x60, 0x15, 0xFB, 0x5A, 0xDB, 0xBA, 0xFE, 0x02, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, + 0x01, 0xBC, 0xF1, 0xFB, 0x44, 0x60, 0x44, 0x64, 0x7F, 0xFB, 0x80, 0xFB, 0x81, 0xFB, 0x08, 0x60, + 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x08, 0x60, 0x77, 0xF3, 0xFF, 0xFF, 0x15, 0x18, 0xA2, 0xDF, + 0x40, 0x60, 0x58, 0x4E, 0x7D, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0xC4, 0x64, 0x0F, 0x60, 0xE1, 0xFB, + 0x4A, 0xDF, 0x01, 0x60, 0xFE, 0x63, 0x1D, 0x60, 0xBE, 0x61, 0x00, 0x64, 0x59, 0xDB, 0xFE, 0x1F, + 0x10, 0x60, 0x0E, 0x62, 0xA2, 0xDF, 0x5B, 0x00, 0xCF, 0xF3, 0xFF, 0xFF, 0x52, 0x1B, 0x10, 0x60, + 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x24, 0x40, 0x02, 0x22, 0x26, 0x00, 0x08, 0x60, 0x1E, 0xF1, + 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, + 0x16, 0xFB, 0xD4, 0x60, 0x1F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, + 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x08, 0x60, 0x1E, 0xF1, 0x00, 0x60, 0x40, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD4, 0x60, 0x59, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x40, 0x01, 0x26, 0x11, 0x00, 0x08, 0x60, + 0x1E, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, + 0x08, 0x60, 0x16, 0xFB, 0xD4, 0x60, 0x59, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x08, 0x60, 0x1E, 0xF1, 0x00, 0x60, 0x40, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, + 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD4, 0x60, 0x59, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0xFD, 0x60, 0x89, 0x65, 0xF3, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x10, 0x60, + 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x64, 0x08, 0x60, 0x15, 0xFB, 0x5A, 0xDB, 0x10, 0x60, + 0x4E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xF7, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, + 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xBB, 0xFE, 0xFD, 0x60, + 0x40, 0x65, 0xF3, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x03, 0x64, 0x08, 0x60, + 0x28, 0xFB, 0xD4, 0x60, 0x87, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, + 0x27, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x07, 0x03, 0xA0, 0x84, 0xA2, 0xDB, + 0x10, 0x60, 0x4E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xE2, 0x01, 0x10, 0x60, 0x4E, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x00, 0x64, 0x08, 0x60, 0x27, 0xFB, 0x5A, 0xDB, 0x20, 0x40, 0x04, 0x2B, 0x14, 0x00, + 0x9B, 0xFE, 0x08, 0x04, 0xBB, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD4, 0x60, 0x95, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, + 0x16, 0x60, 0xCC, 0xF3, 0x00, 0x61, 0x60, 0x40, 0x00, 0x36, 0x00, 0xB9, 0x60, 0x40, 0x01, 0x36, + 0x01, 0xB9, 0x60, 0x40, 0x02, 0x36, 0x06, 0xB9, 0x60, 0x40, 0x03, 0x36, 0x07, 0xB9, 0x41, 0x44, + 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, + 0x08, 0x60, 0x16, 0xFB, 0xD4, 0x60, 0xC8, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x7D, 0xF1, 0x13, 0x60, 0x1A, 0xF9, 0x0C, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, + 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD4, 0x60, 0xE9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, + 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x75, 0x00, 0x10, 0x60, 0x2A, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0xBA, 0xFE, 0x02, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, + 0xF1, 0xFB, 0x44, 0x60, 0x44, 0x64, 0x7F, 0xFB, 0x80, 0xFB, 0x81, 0xFB, 0xFF, 0xFF, 0x20, 0x40, + 0x04, 0x2B, 0x14, 0x00, 0x9B, 0xFE, 0x08, 0x04, 0xBB, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, + 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, + 0xD5, 0x60, 0x07, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x00, 0x65, + 0x20, 0x44, 0x34, 0x80, 0x08, 0x60, 0x07, 0xF1, 0x02, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, + 0x64, 0x40, 0x01, 0x2A, 0x06, 0x00, 0xA2, 0xDF, 0x02, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, + 0xFF, 0xFF, 0xCF, 0xF3, 0x20, 0x60, 0x20, 0x65, 0x36, 0x1B, 0xA5, 0xD3, 0x24, 0x40, 0x01, 0x26, + 0x16, 0x00, 0x60, 0x40, 0x20, 0x26, 0x2F, 0x00, 0x01, 0xBC, 0xA5, 0xDB, 0x08, 0x60, 0x1E, 0xF1, + 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, + 0x16, 0xFB, 0xD5, 0x60, 0x65, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x60, 0x40, + 0x10, 0x26, 0x19, 0x00, 0x01, 0xBC, 0xA5, 0xDB, 0x08, 0x60, 0x1E, 0xF1, 0x00, 0x60, 0x40, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD5, 0x60, + 0x65, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xFD, 0x60, 0x89, 0x65, 0xF3, 0x60, + 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0xCF, 0xF1, 0x07, 0x60, 0xE9, 0xF3, 0x64, 0x40, 0x02, 0x3A, + 0x0C, 0x00, 0x01, 0x63, 0x60, 0x40, 0x10, 0x22, 0x00, 0x63, 0x08, 0x60, 0xC1, 0xFD, 0x08, 0x60, + 0xC5, 0xFD, 0x08, 0x60, 0xC9, 0xFD, 0x08, 0x60, 0xCD, 0xFD, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x01, 0x64, 0x53, 0xFB, 0x2F, 0x60, 0x02, 0x64, 0x54, 0xFB, 0x24, 0x40, 0x01, 0x26, + 0x11, 0x00, 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD5, 0x60, 0xAB, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD5, 0x60, 0xAB, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xFD, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, + 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x2A, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x86, 0xF1, 0x1B, 0x60, 0xB2, 0x63, 0xD3, 0x80, 0x20, 0x44, 0x03, 0x03, + 0xD8, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0x87, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x1B, 0x02, + 0x24, 0x44, 0x04, 0x22, 0x12, 0x00, 0x24, 0x44, 0x01, 0xAC, 0xFB, 0xB4, 0x40, 0x44, 0xF7, 0x60, + 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0xD4, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0xD2, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, + 0xFF, 0xFF, 0x1F, 0x02, 0x87, 0x00, 0x20, 0x44, 0x10, 0xBC, 0x40, 0x40, 0x64, 0x42, 0x5A, 0xD1, + 0x06, 0x63, 0xA4, 0xD1, 0xC3, 0x83, 0x7D, 0xF9, 0xBD, 0xD1, 0x7F, 0xF9, 0xBD, 0xD1, 0xFF, 0xFF, + 0x80, 0xF9, 0xBD, 0xD1, 0x81, 0xF9, 0x04, 0xA3, 0xBD, 0xD1, 0x33, 0x60, 0xBE, 0x64, 0x64, 0x41, + 0xDD, 0x81, 0xFE, 0xB1, 0xA0, 0xD9, 0x04, 0x03, 0xBD, 0xD1, 0xC9, 0x81, 0x58, 0xD9, 0xFC, 0x02, + 0x39, 0x00, 0xE4, 0xF3, 0x7D, 0xFB, 0x66, 0x41, 0x60, 0x40, 0x01, 0x27, 0x06, 0x00, 0x10, 0x60, + 0xF0, 0x63, 0x11, 0x60, 0x44, 0x65, 0x06, 0x66, 0x05, 0x00, 0x11, 0x60, 0x60, 0x63, 0x12, 0x60, + 0x40, 0x65, 0x08, 0x66, 0xA3, 0xD1, 0x4B, 0x93, 0xD0, 0x80, 0xD7, 0x80, 0x02, 0x03, 0xFA, 0x04, + 0x04, 0x00, 0x5B, 0x93, 0x02, 0xA3, 0x01, 0x64, 0xA3, 0xDB, 0x61, 0x46, 0x2F, 0x60, 0x02, 0x61, + 0xA1, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x33, 0x60, 0xBE, 0x63, 0x02, 0x02, 0x2D, 0x60, 0x10, 0x61, + 0xA1, 0xD3, 0xBD, 0xDB, 0xDC, 0x84, 0xFE, 0xB4, 0x59, 0xD1, 0xC8, 0x84, 0xBD, 0xD9, 0xFC, 0x02, + 0xEC, 0xF3, 0x72, 0x45, 0xEB, 0xF3, 0x94, 0x83, 0x81, 0xFD, 0x94, 0x83, 0x80, 0xFD, 0x65, 0x5F, + 0x02, 0x64, 0x7F, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, + 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD6, 0x60, 0x3A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x7D, 0xF1, 0x13, 0x60, 0x1A, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD6, 0x60, 0x5B, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, + 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xD7, 0x60, + 0x7B, 0x78, 0xFF, 0xFF, 0xFF, 0x60, 0xEF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x02, 0x64, 0xDB, 0xFB, + 0xF1, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, 0xF1, 0xFB, 0xF7, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, + 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, + 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x24, 0x44, 0x02, 0x22, 0x03, 0x00, 0x01, 0xAC, 0x04, 0xBC, + 0x40, 0x44, 0x32, 0x40, 0x80, 0x2A, 0x8C, 0x00, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD6, 0x60, 0x8C, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x95, 0xF3, 0xFF, 0xFF, 0x7F, 0xB4, 0x95, 0xFB, 0x26, 0x60, 0x34, 0x62, 0x06, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x2D, 0xFF, 0xFF, 0xFF, 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xDA, 0xFE, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x12, 0x60, 0xFF, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x05, 0x03, 0x0E, 0xF2, 0xFF, 0xFF, + 0x60, 0x40, 0x01, 0x2A, 0x22, 0x00, 0x13, 0x60, 0x02, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, + 0x03, 0x03, 0x0F, 0xF2, 0xFF, 0xFF, 0x19, 0x1B, 0x08, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, + 0xD6, 0x60, 0xE5, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x01, 0x64, 0x19, 0x60, 0xF1, 0xFB, 0x19, 0x60, + 0xF6, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x26, 0x05, 0x00, 0x89, 0xFF, 0x08, 0x60, 0x00, 0x75, + 0x88, 0xFF, 0x01, 0x00, 0x10, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD6, 0x60, + 0xE5, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x7D, 0xF1, 0x13, 0x60, 0x1A, 0xF9, 0x08, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, + 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD7, 0x60, 0x0A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0xBA, 0xFE, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x1E, 0x00, + 0xDA, 0xFE, 0xC1, 0xFE, 0x0E, 0x60, 0x36, 0xF1, 0x0E, 0x60, 0x4B, 0xF9, 0x1C, 0x60, 0x92, 0x64, + 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x60, 0x06, 0x64, + 0x08, 0x60, 0x16, 0xFB, 0xD7, 0x60, 0x4E, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x00, 0x60, 0x02, 0x64, + 0x08, 0x60, 0x28, 0xFB, 0xD7, 0x60, 0x55, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x1C, 0x60, 0x6C, 0x61, + 0x75, 0x60, 0x30, 0x65, 0xA1, 0xD3, 0xFF, 0xFF, 0xFF, 0xA0, 0xE0, 0x84, 0x02, 0x02, 0x03, 0x60, + 0xE8, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x01, 0x04, 0x65, 0x44, 0xA1, 0xDB, 0x32, 0x40, 0x80, 0x2A, + 0x03, 0x00, 0xD4, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x08, 0x60, + 0x27, 0xFB, 0x5A, 0xDB, 0xD4, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0x20, 0x40, 0x06, 0x23, 0x10, 0x00, + 0x08, 0x60, 0x27, 0xF1, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x80, 0x60, 0x00, 0x64, + 0x08, 0x60, 0x28, 0xFB, 0xD7, 0x60, 0x55, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x10, 0x60, 0x4E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x64, 0x08, 0x60, 0x27, 0xFB, 0x5A, 0xDB, + 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0xD3, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0x78, 0xF3, 0x79, 0xFB, 0x20, 0x60, 0x14, 0x62, 0xA2, 0xDF, + 0xFF, 0x60, 0xDF, 0x65, 0x20, 0x44, 0x24, 0x80, 0xBC, 0xF1, 0x0E, 0x60, 0x4B, 0xF9, 0x1C, 0x60, + 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xF7, 0x60, + 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x10, 0x26, 0x38, 0x00, 0x00, 0x64, 0xB2, 0xFB, 0xB3, 0xFB, + 0xB4, 0xFB, 0x00, 0x75, 0x00, 0x72, 0xBA, 0xF1, 0x7E, 0xF9, 0x64, 0x44, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0xE0, 0x93, 0xE5, 0xF1, 0x84, 0xF9, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, + 0x1E, 0x00, 0x19, 0x60, 0x44, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x0A, 0x00, 0x0F, 0x64, + 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, 0x67, 0x43, 0x1A, 0x60, 0xB3, 0xFD, 0x1A, 0x60, + 0xC3, 0xFD, 0xD3, 0x60, 0x58, 0x4E, 0x78, 0x78, 0xFF, 0xFF, 0x00, 0x65, 0xFC, 0x60, 0x58, 0x4E, + 0xC7, 0x78, 0xFF, 0xFF, 0xFD, 0x60, 0x58, 0x4E, 0x11, 0x78, 0xFF, 0xFF, 0x05, 0x00, 0xFF, 0x65, + 0xFC, 0x60, 0x58, 0x4E, 0xC7, 0x78, 0xFF, 0xFF, 0x44, 0x00, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x00, 0x60, 0x84, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD7, 0x60, 0xDB, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x80, 0x64, 0xA0, 0x80, + 0x9C, 0x84, 0x2B, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x08, 0x60, 0x15, 0xF1, 0xFF, 0x60, 0x7F, 0x61, + 0xA1, 0x84, 0x5A, 0xD1, 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x2E, 0x60, 0x2E, 0x64, 0x2D, 0x60, + 0x8A, 0x63, 0xA0, 0xD1, 0xA3, 0xD9, 0x64, 0x41, 0x58, 0xD1, 0x5B, 0xD9, 0x7D, 0xF3, 0x66, 0x45, + 0xA6, 0xF5, 0x60, 0x40, 0x01, 0x27, 0x08, 0x00, 0x91, 0xFA, 0x61, 0x44, 0xFD, 0x60, 0x58, 0x4E, + 0xAC, 0x78, 0xFF, 0xFF, 0x12, 0xFA, 0x07, 0x00, 0x11, 0xF8, 0x64, 0x44, 0xFD, 0x60, 0x58, 0x4E, + 0xAC, 0x78, 0xFF, 0xFF, 0x12, 0xFA, 0x65, 0x46, 0x04, 0x00, 0xBB, 0xFE, 0xD4, 0x60, 0xF6, 0x78, + 0xFF, 0xFF, 0x16, 0x60, 0xC2, 0xF1, 0x00, 0x65, 0x64, 0x40, 0x01, 0x36, 0x22, 0x65, 0x64, 0x40, + 0x07, 0x36, 0x01, 0x65, 0x64, 0x40, 0x0A, 0x36, 0x01, 0x65, 0x64, 0x40, 0x0B, 0x36, 0x22, 0x65, + 0xA6, 0xF3, 0x66, 0x5C, 0x60, 0x46, 0x1F, 0x63, 0xE3, 0x83, 0xBA, 0xF8, 0x02, 0xA6, 0x66, 0x44, + 0xFC, 0x1F, 0x16, 0x60, 0xC2, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x07, 0x36, 0x03, 0x00, 0x0A, 0x36, + 0x06, 0x00, 0x09, 0x00, 0xA6, 0xF3, 0x04, 0x65, 0x60, 0x46, 0xBA, 0xF8, 0x04, 0x00, 0xA6, 0xF3, + 0x10, 0x65, 0x60, 0x46, 0xBA, 0xF8, 0x64, 0x46, 0xA6, 0xF3, 0x32, 0x41, 0x60, 0x45, 0x08, 0xB1, + 0x66, 0x41, 0x16, 0x03, 0x65, 0x46, 0x17, 0x60, 0x80, 0xF3, 0x06, 0xF0, 0xE0, 0x84, 0xE0, 0x84, + 0xE0, 0x84, 0xE0, 0x84, 0x80, 0xBF, 0xB0, 0x84, 0x06, 0xFA, 0x66, 0x43, 0x02, 0xA3, 0x63, 0x46, + 0x06, 0xF0, 0xFF, 0xFF, 0xB0, 0x84, 0x06, 0xFA, 0x61, 0x46, 0x32, 0x44, 0x10, 0xBC, 0x40, 0x52, + 0x01, 0x64, 0x10, 0x60, 0x0A, 0xFB, 0x0F, 0x4E, 0xEF, 0x60, 0x58, 0x4F, 0x3A, 0x78, 0xFF, 0xFF, + 0x0E, 0x4F, 0x08, 0x60, 0x15, 0xF1, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x00, 0x60, + 0x04, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD3, 0x60, 0xAE, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x1C, 0x60, + 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xBB, 0xFE, + 0x20, 0x44, 0x04, 0x27, 0x11, 0x00, 0x10, 0x26, 0x02, 0x00, 0xDB, 0xFE, 0x14, 0x00, 0x08, 0x60, + 0x07, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x36, 0x07, 0x00, 0x01, 0x64, 0xA2, 0xDB, 0x01, 0x65, + 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x64, 0x8A, 0xFB, 0xFF, 0x60, 0xEF, 0x65, 0x20, 0x44, + 0x24, 0x80, 0x03, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF1, 0xFB, 0xC1, 0xFE, + 0x00, 0x60, 0x02, 0x64, 0x08, 0x60, 0x28, 0xFB, 0xD8, 0x60, 0xAA, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x20, 0x40, 0x06, 0x23, 0x10, 0x00, 0x08, 0x60, 0x27, 0xF1, 0x7F, 0x60, + 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x28, 0xFB, 0xD8, 0x60, + 0xAA, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x4E, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x00, 0x64, 0x08, 0x60, 0x27, 0xFB, 0x5A, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, + 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xD3, 0x60, 0xD0, 0x78, 0xFF, 0xFF, + 0xBB, 0xFE, 0xD9, 0x60, 0xB0, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0xC2, 0xF1, 0x00, 0x65, 0x64, 0x40, + 0x01, 0x36, 0x22, 0x65, 0xA6, 0xF3, 0x66, 0x5C, 0x60, 0x46, 0x1F, 0x63, 0xE3, 0x83, 0xBA, 0xF8, + 0x02, 0xA6, 0x66, 0x44, 0xFC, 0x1F, 0x64, 0x46, 0xA6, 0xF1, 0x02, 0x64, 0xC0, 0x85, 0x0C, 0x61, + 0x32, 0x40, 0x08, 0x2A, 0x14, 0x00, 0x17, 0x60, 0x80, 0xF3, 0x66, 0x41, 0x65, 0x46, 0x06, 0xF0, + 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x80, 0xBF, 0xB0, 0x83, 0x06, 0xFC, 0x66, 0x42, + 0xFE, 0xA2, 0x62, 0x46, 0x06, 0xF0, 0xFF, 0xFF, 0xB0, 0x84, 0x06, 0xFA, 0x61, 0x46, 0x0B, 0x64, + 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF1, 0xFB, 0x01, 0x65, 0xF1, 0x60, 0x58, 0x4E, + 0xC3, 0x78, 0xFF, 0xFF, 0xE4, 0xF1, 0x7D, 0xF9, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD9, 0x60, 0x0C, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7D, 0xF1, 0x13, 0x60, 0x1A, 0xF9, 0x0E, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD9, 0x60, + 0x2D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x08, 0x60, 0x15, 0xFB, + 0x5A, 0xDB, 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x01, 0x64, 0x8A, 0xFB, 0xFF, 0x60, 0xDF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x2F, 0x58, + 0xFF, 0xFF, 0x06, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF1, 0xFB, 0xE4, 0xF1, + 0x7D, 0xF9, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x64, 0x8A, 0xFB, 0xFF, 0x60, + 0xDF, 0x65, 0x20, 0x44, 0x24, 0x80, 0xA6, 0xF1, 0x66, 0x45, 0x64, 0x46, 0x66, 0x43, 0x02, 0xA3, + 0x63, 0x46, 0x02, 0x64, 0x06, 0xFA, 0x04, 0x63, 0x04, 0x61, 0x01, 0x60, 0xCC, 0x64, 0x58, 0xD1, + 0x59, 0xD8, 0xFD, 0x1F, 0x65, 0x46, 0x01, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, + 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x67, 0xFB, 0x68, 0xFB, 0xA6, 0xF1, 0x0E, 0x64, 0x66, 0x41, + 0x64, 0x42, 0x02, 0xA2, 0x62, 0x46, 0x06, 0xF0, 0xFF, 0x60, 0xFC, 0x64, 0xA0, 0x84, 0x06, 0xFA, + 0x61, 0x46, 0xDB, 0xF3, 0xFF, 0xFF, 0x04, 0xA8, 0x10, 0x60, 0x0E, 0x64, 0x07, 0x03, 0xA0, 0xD1, + 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x2A, 0x02, 0x00, 0x00, 0x63, 0xA0, 0xDD, 0x01, 0x64, 0xDB, 0xFB, + 0xF1, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF1, 0xFB, 0x00, 0x63, 0x08, 0x60, 0x77, 0xFD, 0x10, 0x60, + 0x4E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x64, 0x08, 0x60, 0x27, 0xFB, 0x5A, 0xDB, 0x10, 0x60, + 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x02, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD3, 0x60, + 0x9C, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, + 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2E, 0x58, 0xFF, 0xFF, + 0x40, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xB9, 0xF1, 0x0E, 0x60, 0x4B, 0xF9, 0x5F, 0xF5, 0xEA, 0xF1, + 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0xB9, 0xF1, 0x19, 0xF8, 0xF8, 0x60, + 0x80, 0x64, 0x0E, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0xA6, 0xF1, 0x07, 0xF8, 0x1B, 0x60, 0xB0, 0x64, + 0x00, 0x60, 0x67, 0xFB, 0x44, 0x60, 0x44, 0x64, 0x7F, 0xFB, 0x80, 0xFB, 0x81, 0xFB, 0x31, 0x44, + 0xF9, 0xB4, 0x40, 0x51, 0x00, 0x60, 0xCE, 0x63, 0x01, 0x60, 0x0C, 0x65, 0xA3, 0xD3, 0xA5, 0xD1, + 0x04, 0xA4, 0xA3, 0xDB, 0xD0, 0x80, 0xA0, 0xD1, 0x0A, 0x06, 0x41, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xD6, 0x60, 0x6A, 0x78, 0xFF, 0xFF, 0x44, 0x47, + 0x16, 0x60, 0xC2, 0xF3, 0xFF, 0xFF, 0xFF, 0xA4, 0xFF, 0xFF, 0x09, 0x07, 0x0E, 0x61, 0x41, 0xD3, + 0x32, 0x40, 0x08, 0x26, 0x04, 0x00, 0x10, 0xB0, 0xFF, 0xFF, 0x01, 0x03, 0xD3, 0x01, 0x42, 0x64, + 0x3B, 0x42, 0x5A, 0xDB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, + 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD9, 0x60, 0xFA, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0xD1, 0x7D, 0xF9, 0x13, 0x60, 0x1A, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xDA, 0x60, 0x1C, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x07, 0x60, 0xD0, 0x64, 0x0E, 0x60, 0x4B, 0xFB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, + 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD3, 0x7F, 0xFB, + 0xBD, 0xD3, 0x80, 0xFB, 0xA3, 0xD3, 0x81, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x01, 0x60, 0x04, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xDA, 0x60, 0x4A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0xB9, 0xF1, 0x0E, 0x60, 0x4B, 0xF9, 0x08, 0x60, 0x15, 0xF1, 0xFE, 0x60, + 0xFF, 0x61, 0xA1, 0x84, 0x5A, 0xD1, 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x08, 0x60, 0x15, 0xF1, + 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xD9, 0x60, + 0xCA, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x08, 0x65, 0x20, 0x44, 0x34, 0x80, 0x7D, 0xF1, 0x32, 0x60, + 0x7A, 0x61, 0xA1, 0xD3, 0x64, 0x40, 0x01, 0x27, 0x59, 0xD3, 0x32, 0x60, 0x7E, 0x61, 0xFD, 0x60, + 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0xA1, 0xDB, 0x5E, 0xF5, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, + 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0xB9, 0xF1, 0x19, 0xF8, 0x80, 0x7E, 0xF8, 0x7F, 0x0E, 0xFA, + 0x00, 0x64, 0x3E, 0xFA, 0xA6, 0xF1, 0x07, 0xF8, 0x2B, 0xFA, 0xB0, 0x64, 0x2A, 0xFA, 0x27, 0x43, + 0x06, 0xA3, 0xBD, 0xD1, 0x2C, 0xF8, 0x32, 0xF8, 0xBD, 0xD1, 0x2D, 0xF8, 0x33, 0xF8, 0xA3, 0xD1, + 0x2E, 0xF8, 0x34, 0xF8, 0x06, 0x63, 0x3F, 0xFC, 0x20, 0x60, 0x16, 0x61, 0xDB, 0xF3, 0xA1, 0xD3, + 0x03, 0xA8, 0xAC, 0x83, 0x0E, 0x02, 0x0D, 0x03, 0x20, 0x60, 0x18, 0x61, 0xA1, 0xD1, 0x66, 0x45, + 0x00, 0xF4, 0x09, 0xFC, 0x01, 0x64, 0x0A, 0xFA, 0x0B, 0xF8, 0x20, 0x60, 0x16, 0x61, 0xA1, 0xDF, + 0x25, 0x00, 0x16, 0x60, 0xC3, 0xF3, 0x66, 0x45, 0x00, 0xF4, 0x60, 0x40, 0x01, 0x36, 0x15, 0x00, + 0x02, 0x36, 0xBD, 0x00, 0x03, 0x36, 0x07, 0x00, 0x04, 0x36, 0x0F, 0x00, 0x05, 0x36, 0xB7, 0x00, + 0x06, 0x36, 0x01, 0x00, 0x0A, 0x00, 0x80, 0x64, 0x09, 0xFA, 0x01, 0x63, 0x0A, 0xFC, 0x00, 0x64, + 0x0B, 0xFA, 0x80, 0x60, 0xF4, 0x62, 0xA2, 0xDF, 0x09, 0x00, 0x00, 0x64, 0x09, 0xFA, 0x01, 0x63, + 0x0A, 0xFC, 0x00, 0x64, 0x0B, 0xFA, 0x80, 0x60, 0xF4, 0x62, 0xA2, 0xDF, 0x25, 0x60, 0xCE, 0x64, + 0x13, 0x60, 0x0D, 0xFB, 0x65, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0x00, 0x66, 0xDB, 0xF3, 0x46, 0x46, 0xFD, 0xA0, 0xC1, 0xFE, 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, + 0x01, 0x64, 0x68, 0xFB, 0x43, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0E, 0x60, 0x38, 0xF3, 0xFF, 0xFF, + 0x64, 0xA4, 0xA2, 0xDB, 0x0E, 0x60, 0x38, 0xF1, 0x0E, 0x60, 0x4B, 0xF9, 0x1C, 0x60, 0x92, 0x64, + 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x60, 0x0C, 0x64, + 0x08, 0x60, 0x16, 0xFB, 0xDB, 0x60, 0x00, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x55, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0x00, 0x64, 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x26, 0x46, + 0x00, 0xF4, 0x09, 0xF2, 0x0A, 0xF2, 0x00, 0xA8, 0x0B, 0xF2, 0x02, 0xA8, 0x16, 0x02, 0x00, 0xA8, + 0x1A, 0x02, 0x19, 0x02, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, + 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, 0xDC, 0x60, + 0xF6, 0x78, 0xFF, 0xFF, 0xE3, 0x60, 0x69, 0x78, 0xFF, 0xFF, 0x09, 0xF2, 0x0A, 0xF2, 0x80, 0xA8, + 0x0B, 0xF2, 0x02, 0xA8, 0xE4, 0x03, 0x44, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0B, 0xF2, 0x26, 0x46, + 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, + 0x31, 0xF2, 0x59, 0xDB, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, + 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x03, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0x96, 0x78, + 0xFF, 0xFF, 0xE7, 0x60, 0x0B, 0x78, 0xFF, 0xFF, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, 0xA2, 0xDB, + 0x00, 0x64, 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x20, 0x40, 0x08, 0x2A, + 0x03, 0x00, 0xD9, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0xE2, 0x60, 0x73, 0x78, 0xFF, 0xFF, 0x01, 0x63, + 0x09, 0xFC, 0x32, 0x40, 0x08, 0x26, 0x14, 0x00, 0x16, 0x60, 0xC2, 0xF3, 0xFF, 0xFF, 0x60, 0x40, + 0x0B, 0x36, 0x03, 0x00, 0xDA, 0x60, 0xC5, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0xA2, 0xDB, 0x0B, 0x64, + 0x19, 0x60, 0xA4, 0xFB, 0xA6, 0xF1, 0x66, 0x41, 0x64, 0x46, 0x22, 0x64, 0x3A, 0xFA, 0x61, 0x46, + 0x01, 0x64, 0x0A, 0xFA, 0x00, 0x64, 0x0B, 0xFA, 0x01, 0x64, 0x40, 0x60, 0x7A, 0xFB, 0x01, 0x64, + 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, + 0x0D, 0xFB, 0x65, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x66, + 0xDB, 0xF3, 0x46, 0x46, 0xFD, 0xA0, 0xC1, 0xFE, 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, + 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x60, + 0x0C, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xDB, 0x60, 0xB9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x3A, 0x03, + 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x68, 0xFB, 0x26, 0x46, 0x00, 0xF4, 0x09, 0xF2, 0x0A, 0xF2, + 0x01, 0xA8, 0x0B, 0xF2, 0x02, 0xA8, 0x04, 0x02, 0x00, 0xA8, 0x02, 0x02, 0x01, 0x02, 0x31, 0x00, + 0xDC, 0x60, 0x58, 0x4D, 0xB9, 0x78, 0xFF, 0xFF, 0x0B, 0xF2, 0x26, 0x46, 0x40, 0x59, 0x02, 0x60, + 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x31, 0xF2, 0x59, 0xDB, + 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, + 0x00, 0x66, 0x46, 0x46, 0x03, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0xE7, 0x60, + 0x0B, 0x78, 0xFF, 0xFF, 0xDC, 0x60, 0x58, 0x4D, 0xB9, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x68, 0xFB, + 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, 0xD9, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0xE2, 0x60, 0x73, 0x78, + 0xFF, 0xFF, 0x26, 0x46, 0x40, 0x60, 0x00, 0x65, 0x2A, 0xF2, 0x2F, 0xF0, 0xB4, 0x84, 0x2A, 0xFA, + 0x2C, 0xF8, 0x32, 0xF8, 0x30, 0xF2, 0x2D, 0xFA, 0x33, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0x34, 0xFA, + 0xEA, 0xF3, 0x2F, 0xFA, 0xEB, 0xF3, 0x30, 0xFA, 0xEC, 0xF3, 0x31, 0xFA, 0xC9, 0xF1, 0x19, 0xF8, + 0x1C, 0xF0, 0x13, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x00, 0xF4, 0x03, 0x64, 0x0A, 0xFA, 0x00, 0x64, + 0x0B, 0xFA, 0x01, 0x63, 0x68, 0xFD, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x25, 0x60, + 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0x00, 0x66, 0xDB, 0xF3, 0x46, 0x46, 0xFD, 0xA0, 0xC1, 0xFE, 0x02, 0x02, 0x2F, 0x58, + 0xFF, 0xFF, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0x00, 0x60, 0x0C, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xDC, 0x60, 0x53, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, + 0x9C, 0x84, 0x50, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, + 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x68, 0xFB, 0x26, 0x46, 0x00, 0xF4, + 0x09, 0xF2, 0x0A, 0xF2, 0x01, 0xA8, 0x0B, 0xF2, 0x04, 0xA8, 0x1A, 0x02, 0x00, 0xA8, 0x18, 0x02, + 0x17, 0x02, 0xDC, 0x60, 0x58, 0x4D, 0xB9, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, + 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x20, 0x40, + 0x08, 0x2A, 0x03, 0x00, 0xDC, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0xE3, 0x60, 0x69, 0x78, 0xFF, 0xFF, + 0xDC, 0x60, 0x58, 0x4D, 0xB9, 0x78, 0xFF, 0xFF, 0x0B, 0xF2, 0x26, 0x46, 0x40, 0x59, 0x02, 0x60, + 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x31, 0xF2, 0x59, 0xDB, + 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, + 0x00, 0x66, 0x46, 0x46, 0x03, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0xE7, 0x60, + 0x0B, 0x78, 0xFF, 0xFF, 0xDC, 0x60, 0x58, 0x4D, 0xB9, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x68, 0xFB, + 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, 0xD9, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0xE2, 0x60, 0x73, 0x78, + 0xFF, 0xFF, 0x19, 0x60, 0xA4, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x0B, 0x3A, 0x06, 0x00, 0x0B, 0x64, + 0x16, 0x60, 0xC2, 0xFB, 0x33, 0x60, 0x48, 0x62, 0xA2, 0xDF, 0x2D, 0x58, 0xFF, 0xFF, 0x16, 0x60, + 0xC2, 0xF1, 0xA5, 0xD2, 0x64, 0x40, 0x0B, 0x2A, 0x20, 0x00, 0x85, 0x36, 0x0B, 0x00, 0x32, 0x3A, + 0x1E, 0x00, 0x60, 0x47, 0xFF, 0xB4, 0x02, 0xA4, 0xC4, 0x85, 0xA5, 0xD2, 0xFF, 0xFF, 0x60, 0x40, + 0x85, 0x3A, 0x15, 0x00, 0x65, 0x44, 0x0A, 0xA4, 0xA0, 0xD0, 0x33, 0x60, 0x46, 0x62, 0x64, 0x40, + 0x18, 0x26, 0x09, 0x00, 0xA2, 0xDF, 0x01, 0x64, 0x16, 0x60, 0xC2, 0xFB, 0x32, 0x41, 0x08, 0x65, + 0xB5, 0x81, 0x41, 0x52, 0x02, 0x00, 0x01, 0x64, 0xA2, 0xDB, 0x2D, 0x58, 0xFF, 0xFF, 0x33, 0x60, + 0x46, 0x62, 0xA2, 0xDF, 0x01, 0x64, 0x16, 0x60, 0xC2, 0xFB, 0xF7, 0x01, 0x45, 0x64, 0x3B, 0x42, + 0x5A, 0xDB, 0x35, 0x60, 0xAA, 0x7C, 0x35, 0x60, 0x98, 0x63, 0xA3, 0xD9, 0x64, 0x41, 0x2F, 0x60, + 0x02, 0x63, 0xBD, 0xD3, 0x00, 0x7C, 0x03, 0x1B, 0x27, 0x43, 0x10, 0xA3, 0xBD, 0xD3, 0xFF, 0xFF, + 0x60, 0x45, 0x64, 0x5F, 0xA1, 0xDB, 0x65, 0x44, 0xBD, 0xD1, 0xC8, 0x84, 0x59, 0xD8, 0xFC, 0x05, + 0x27, 0x41, 0x10, 0xA1, 0xA1, 0xD1, 0xFF, 0xFF, 0xC1, 0x81, 0x01, 0x26, 0xDD, 0x81, 0x41, 0x4C, + 0x59, 0xD1, 0x7C, 0x44, 0xB0, 0x84, 0x59, 0xD1, 0x59, 0xD1, 0xB0, 0x84, 0xB0, 0x84, 0xFF, 0xFF, + 0x02, 0x02, 0x67, 0x44, 0xC2, 0x00, 0x34, 0x60, 0x5C, 0x63, 0xD9, 0x81, 0x59, 0xD3, 0x38, 0x60, + 0x10, 0x62, 0x00, 0xBC, 0xA2, 0xDF, 0x09, 0x03, 0x01, 0x7C, 0xA2, 0xD9, 0x30, 0x60, 0x14, 0x64, + 0xBD, 0xDA, 0x00, 0x60, 0x01, 0x64, 0xBD, 0xDA, 0x58, 0x00, 0xDD, 0x60, 0x18, 0x64, 0xBD, 0xDA, + 0x50, 0x60, 0x00, 0x64, 0xBD, 0xDA, 0x01, 0x60, 0xF2, 0x64, 0xBD, 0xDA, 0x00, 0x60, 0x01, 0x64, + 0xBD, 0xDA, 0x2C, 0x41, 0x59, 0xD3, 0x50, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x02, 0x2A, 0x03, 0x00, + 0x01, 0x60, 0xF2, 0x64, 0x0E, 0x00, 0x04, 0x2A, 0x03, 0x00, 0x02, 0x60, 0xF2, 0x64, 0x09, 0x00, + 0x10, 0x2A, 0x03, 0x00, 0x04, 0x60, 0xF2, 0x64, 0x04, 0x00, 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, + 0xF2, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, 0x01, 0x64, 0xBD, 0xDB, 0x59, 0xD3, 0x50, 0x60, 0x00, 0x7C, + 0x60, 0x40, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, 0xF2, 0x64, 0x0E, 0x00, 0x04, 0x2A, 0x03, 0x00, + 0x02, 0x60, 0xF2, 0x64, 0x09, 0x00, 0x10, 0x2A, 0x03, 0x00, 0x04, 0x60, 0xF2, 0x64, 0x04, 0x00, + 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, 0xF2, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, 0x01, 0x64, 0xBD, 0xDB, + 0x59, 0xD3, 0x50, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x01, 0x2A, 0x03, 0x00, 0x00, 0x60, 0xF2, 0x64, + 0x09, 0x00, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, 0xF2, 0x64, 0x04, 0x00, 0x04, 0x2A, 0x02, 0x00, + 0x02, 0x60, 0xF2, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, 0x4B, 0x00, 0x2C, 0x41, 0x59, 0xD3, 0x0F, 0x60, + 0x00, 0x7C, 0x60, 0x40, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, 0xAC, 0x64, 0x0E, 0x00, 0x04, 0x2A, + 0x03, 0x00, 0x02, 0x60, 0xAC, 0x64, 0x09, 0x00, 0x10, 0x2A, 0x03, 0x00, 0x04, 0x60, 0xAC, 0x64, + 0x04, 0x00, 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, 0xAC, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, 0x01, 0x64, + 0xBD, 0xDB, 0x59, 0xD3, 0x0F, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, + 0xAC, 0x64, 0x0E, 0x00, 0x04, 0x2A, 0x03, 0x00, 0x02, 0x60, 0xAC, 0x64, 0x09, 0x00, 0x10, 0x2A, + 0x03, 0x00, 0x04, 0x60, 0xAC, 0x64, 0x04, 0x00, 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, 0xAC, 0x64, + 0xBD, 0xD9, 0xBD, 0xDB, 0x01, 0x64, 0xBD, 0xDB, 0x59, 0xD3, 0x0F, 0x60, 0x00, 0x7C, 0x60, 0x40, + 0x01, 0x2A, 0x03, 0x00, 0x00, 0x60, 0xAC, 0x64, 0x09, 0x00, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, + 0xAC, 0x64, 0x04, 0x00, 0x04, 0x2A, 0x02, 0x00, 0x02, 0x60, 0xAC, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, + 0x1C, 0x60, 0x08, 0xF3, 0xFF, 0xFF, 0x03, 0x18, 0x1A, 0x60, 0x2D, 0xF3, 0x03, 0x00, 0x1A, 0x60, + 0x1D, 0xF3, 0xFF, 0xFF, 0xBD, 0xDA, 0x34, 0x60, 0x5C, 0x64, 0x1A, 0x60, 0xCF, 0xFB, 0x5F, 0xF5, + 0x00, 0x64, 0x2B, 0xFA, 0x00, 0x64, 0x2A, 0xFA, 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD1, 0x2C, 0xF8, + 0x32, 0xF8, 0xBD, 0xD1, 0x2D, 0xF8, 0x33, 0xF8, 0xA3, 0xD1, 0x2E, 0xF8, 0x34, 0xF8, 0x00, 0xF4, + 0x01, 0x63, 0x32, 0x40, 0x08, 0x26, 0x10, 0xBB, 0x16, 0x60, 0xC2, 0xF1, 0xFF, 0xFF, 0x64, 0x40, + 0xFE, 0x26, 0x10, 0xBB, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, 0x0A, 0x00, 0x19, 0x60, + 0x45, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x22, 0x20, 0xBB, 0x63, 0x44, 0xFF, 0xFF, 0x04, 0x7F, + 0x60, 0x43, 0x09, 0xFC, 0x27, 0x42, 0x0C, 0xA2, 0x2D, 0x60, 0x5A, 0x63, 0xA2, 0xD3, 0xA3, 0xD3, + 0x00, 0xBD, 0x01, 0x63, 0xAC, 0x81, 0x09, 0x03, 0x08, 0x03, 0xB8, 0x60, 0x58, 0x4D, 0x15, 0x78, + 0xFF, 0xFF, 0x00, 0xB8, 0x01, 0x63, 0x01, 0x03, 0x60, 0x43, 0x0E, 0x60, 0x35, 0xFD, 0x12, 0x61, + 0x59, 0xDC, 0x16, 0x60, 0xC2, 0xF3, 0xFF, 0x60, 0xFF, 0x7C, 0x60, 0x40, 0x0B, 0x2A, 0x02, 0x00, + 0x33, 0x60, 0x28, 0x7C, 0x1A, 0x60, 0xD0, 0xF9, 0x35, 0x60, 0x98, 0x64, 0x40, 0x48, 0xD9, 0x81, + 0xFF, 0x60, 0xF2, 0x64, 0xF1, 0x60, 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x5F, 0xF5, 0x3F, 0xFC, + 0xDB, 0x83, 0x1A, 0x60, 0x4C, 0xFD, 0x00, 0x7C, 0x5A, 0xD9, 0x63, 0x41, 0x34, 0x60, 0x9C, 0x63, + 0x12, 0x65, 0x00, 0xF4, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, + 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, + 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x5F, 0xF5, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, + 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x66, + 0x46, 0x46, 0xC1, 0xFE, 0x06, 0x64, 0x68, 0xFB, 0x46, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x1C, 0x60, + 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x60, + 0x1C, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xDE, 0x60, 0x84, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0xDE, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x08, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0xF6, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, + 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x26, 0x46, 0x00, 0xF4, 0x0A, 0xF2, 0x00, 0x63, 0x00, 0xA8, 0x68, 0xFD, 0x06, 0x02, + 0x09, 0xF2, 0xFF, 0xFF, 0x01, 0xB0, 0x01, 0x7C, 0x5A, 0x02, 0x0A, 0xF8, 0x0A, 0xF2, 0x26, 0x46, + 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, + 0x31, 0xF2, 0x59, 0xDB, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, + 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x05, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0x96, 0x78, + 0xFF, 0xFF, 0xE7, 0x60, 0x0B, 0x78, 0xFF, 0xFF, 0x47, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xD9, 0x60, + 0xCA, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x20, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, + 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x00, 0x64, 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x49, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xDA, 0x60, 0x62, 0x78, 0xFF, 0xFF, 0xFF, 0x60, + 0xFB, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x00, 0x64, 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x4A, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xD9, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0x48, 0x64, + 0x3B, 0x42, 0x5A, 0xDB, 0x0C, 0xF2, 0xFF, 0xFF, 0x60, 0x41, 0xFF, 0xB1, 0xFF, 0xA1, 0x60, 0x47, + 0xFF, 0xB4, 0x9B, 0x02, 0x9A, 0x03, 0x34, 0x60, 0xF4, 0x63, 0x10, 0x64, 0xBD, 0xDB, 0x66, 0x45, + 0x26, 0x46, 0x3F, 0xF2, 0x34, 0x60, 0xF2, 0x61, 0xC2, 0xA0, 0xFF, 0xFF, 0x01, 0x04, 0x3E, 0x64, + 0x65, 0x46, 0x02, 0xA4, 0xA1, 0xDB, 0xC8, 0x81, 0x12, 0x65, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, + 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, + 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x0C, 0xF2, + 0xFF, 0xFF, 0x1A, 0x65, 0x60, 0x47, 0xFF, 0xB4, 0xC4, 0x85, 0xDC, 0x60, 0x58, 0x4D, 0xC7, 0x78, + 0xFF, 0xFF, 0x0B, 0xF2, 0xFF, 0xFF, 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, + 0xFD, 0x02, 0x61, 0x44, 0x94, 0xFB, 0x27, 0x45, 0x02, 0x62, 0x46, 0xD3, 0x5A, 0xD1, 0x60, 0x47, + 0x56, 0xFB, 0x64, 0x47, 0x55, 0xFB, 0x00, 0x64, 0x5B, 0xFB, 0x0C, 0x62, 0x46, 0xD3, 0x7E, 0xFB, + 0x0B, 0xF0, 0x0F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0x83, 0xFB, 0x26, 0x46, 0x32, 0xF0, 0x7F, 0xF9, + 0x33, 0xF0, 0x0E, 0x63, 0xC7, 0x81, 0x80, 0xF9, 0x34, 0xF0, 0x81, 0xF9, 0x59, 0xD1, 0xFF, 0xFF, + 0x64, 0x44, 0x01, 0x2A, 0xC8, 0x84, 0x60, 0x43, 0x33, 0x60, 0xBC, 0x64, 0x58, 0xD9, 0x59, 0xD1, + 0x58, 0xD9, 0xFD, 0x1F, 0x16, 0x60, 0xC2, 0xF1, 0x59, 0xD3, 0x64, 0x40, 0x01, 0x36, 0x22, 0x64, + 0x64, 0x40, 0x00, 0x36, 0x50, 0x94, 0xA6, 0xF1, 0xFF, 0xFF, 0x44, 0x47, 0xA7, 0x46, 0x3A, 0xFA, + 0xBB, 0xFC, 0xA7, 0x46, 0x0E, 0x60, 0x35, 0xF3, 0x85, 0xFB, 0x2E, 0x60, 0x2E, 0x64, 0x2D, 0x60, + 0x8A, 0x63, 0xA0, 0xD1, 0xA3, 0xD9, 0x64, 0x41, 0x58, 0xD1, 0x5B, 0xD9, 0x7D, 0xF3, 0x66, 0x45, + 0xA6, 0xF5, 0x60, 0x40, 0x01, 0x27, 0x08, 0x00, 0x91, 0xFA, 0x61, 0x44, 0xFD, 0x60, 0x58, 0x4E, + 0xAC, 0x78, 0xFF, 0xFF, 0x12, 0xFA, 0x07, 0x00, 0x11, 0xF8, 0x64, 0x44, 0xFD, 0x60, 0x58, 0x4E, + 0xAC, 0x78, 0xFF, 0xFF, 0x12, 0xFA, 0x65, 0x46, 0x31, 0xF2, 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, + 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, + 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, + 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, + 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA6, 0xF3, 0x08, 0xFE, + 0x60, 0x43, 0x61, 0x46, 0xA6, 0xF1, 0xFF, 0xFF, 0xD3, 0x80, 0x31, 0xF2, 0x27, 0x02, 0x66, 0x41, + 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xA6, 0xF1, 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, + 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, + 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, + 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, + 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, 0x43, 0x4B, 0x01, 0x65, + 0xFD, 0x60, 0x58, 0x4E, 0xDD, 0x78, 0xFF, 0xFF, 0x43, 0x47, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, + 0xFA, 0xA3, 0x00, 0x60, 0x17, 0x61, 0x00, 0x60, 0x01, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, + 0xFD, 0x60, 0x58, 0x4E, 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x00, 0x02, 0x00, 0x64, + 0x40, 0x4A, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xFE, 0x60, + 0x58, 0x4E, 0x2C, 0x78, 0xFF, 0xFF, 0x20, 0xFE, 0x00, 0x65, 0x00, 0x64, 0x19, 0x60, 0x3B, 0xFB, + 0x02, 0x00, 0x20, 0xFE, 0xFF, 0x65, 0x02, 0x60, 0x00, 0x63, 0x60, 0xFE, 0xBD, 0xD3, 0xBD, 0xD3, + 0x60, 0x41, 0x20, 0xFE, 0xCD, 0x81, 0x60, 0x40, 0x80, 0x2A, 0x39, 0x00, 0x7F, 0xB4, 0x02, 0x3A, + 0x02, 0x00, 0x01, 0x64, 0x2E, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x02, 0x64, 0x2A, 0x00, 0x0B, 0x3A, + 0x02, 0x00, 0x04, 0x64, 0x26, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x08, 0x64, 0x22, 0x00, 0x0C, 0x3A, + 0x02, 0x00, 0x10, 0x64, 0x1E, 0x00, 0x12, 0x3A, 0x02, 0x00, 0x20, 0x64, 0x1A, 0x00, 0x18, 0x3A, + 0x02, 0x00, 0x40, 0x64, 0x16, 0x00, 0x24, 0x3A, 0x02, 0x00, 0x80, 0x64, 0x12, 0x00, 0x30, 0x3A, + 0x02, 0x00, 0x01, 0x67, 0x0E, 0x00, 0x48, 0x3A, 0x02, 0x00, 0x02, 0x67, 0x0A, 0x00, 0x60, 0x3A, + 0x02, 0x00, 0x04, 0x67, 0x06, 0x00, 0x6C, 0x3A, 0x02, 0x00, 0x08, 0x67, 0x02, 0x00, 0x00, 0x64, + 0x00, 0x00, 0x19, 0x60, 0x3B, 0xF1, 0xFF, 0xFF, 0xB0, 0x84, 0x19, 0x60, 0x3B, 0xFB, 0x61, 0x40, + 0x00, 0x36, 0x05, 0x00, 0x60, 0xFE, 0xBD, 0xD3, 0xFF, 0xFF, 0x20, 0xFE, 0xBB, 0x01, 0x65, 0x40, + 0x00, 0x3A, 0x1E, 0x00, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xFA, 0xA3, 0x00, 0x60, + 0x17, 0x61, 0x00, 0x60, 0x32, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, + 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x0B, 0x03, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, + 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xFE, 0x60, 0x58, 0x4E, 0x2C, 0x78, 0xFF, 0xFF, 0x91, 0x01, + 0x20, 0xFE, 0x00, 0x65, 0xFC, 0x60, 0x58, 0x4E, 0xC7, 0x78, 0xFF, 0xFF, 0xA1, 0xF3, 0xFF, 0xFF, + 0x60, 0x40, 0x01, 0x27, 0x04, 0x00, 0xFD, 0x60, 0x58, 0x4E, 0x11, 0x78, 0xFF, 0xFF, 0x20, 0xFE, + 0x37, 0x60, 0xF8, 0x61, 0xA1, 0xD1, 0xA1, 0xF3, 0x01, 0x60, 0xAC, 0x63, 0x60, 0x45, 0x2A, 0x44, + 0x79, 0xFB, 0xA3, 0xD5, 0x65, 0x40, 0x01, 0x27, 0x5B, 0xD5, 0x65, 0x40, 0x01, 0x27, 0x59, 0xD1, + 0x66, 0x41, 0xA0, 0x84, 0x24, 0x94, 0x2B, 0x46, 0x0F, 0xFA, 0x7A, 0xFB, 0x16, 0x64, 0x12, 0xFA, + 0x01, 0x64, 0x11, 0xFA, 0x66, 0x5C, 0xC2, 0x60, 0x58, 0x4E, 0x6D, 0x78, 0xFF, 0xFF, 0x1A, 0x60, + 0x22, 0xF3, 0x1A, 0x60, 0x21, 0xF1, 0x60, 0x47, 0xB0, 0x84, 0x1C, 0x60, 0x08, 0xF1, 0xFF, 0xFF, + 0x01, 0x18, 0x80, 0xBC, 0x16, 0x60, 0xC2, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x22, 0x64, + 0x64, 0x40, 0x00, 0x36, 0x50, 0x94, 0xA7, 0x46, 0x3A, 0xFA, 0xBB, 0xFC, 0xA7, 0x46, 0x80, 0x60, + 0x03, 0x65, 0x32, 0x40, 0x08, 0x2A, 0x03, 0x65, 0xA7, 0x46, 0x06, 0xF0, 0x7F, 0x60, 0xFF, 0x64, + 0xA0, 0x84, 0xB4, 0x84, 0x06, 0xFA, 0xBB, 0xFC, 0xA7, 0x46, 0x26, 0x46, 0x2F, 0xF0, 0x30, 0xF0, + 0x64, 0x43, 0x31, 0xF2, 0x27, 0x46, 0x03, 0xFC, 0x04, 0xF8, 0x05, 0xFA, 0x26, 0x46, 0xD9, 0x60, + 0x58, 0x4E, 0xAE, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, + 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x01, 0x64, 0x8A, 0xFB, 0x16, 0x60, + 0xC9, 0xF3, 0x20, 0x41, 0x00, 0xBC, 0x20, 0xB9, 0x01, 0x03, 0x41, 0x40, 0x20, 0x60, 0x14, 0x61, + 0xA1, 0xDF, 0x04, 0x64, 0xC1, 0xFE, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF1, 0xFB, + 0xF7, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, + 0x33, 0x60, 0xE6, 0x65, 0xA5, 0xDF, 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x0C, 0x64, 0x68, 0xFB, 0x00, 0x60, 0x31, 0x64, 0x08, 0x60, 0x16, 0xFB, + 0xE1, 0x60, 0x36, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x00, 0x60, 0x02, 0x64, 0x08, 0x60, 0x28, 0xFB, + 0xE1, 0x60, 0xF7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x08, 0x60, + 0x27, 0xFB, 0x5A, 0xDB, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x01, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x0F, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1B, 0x60, 0xFE, 0xF3, 0xFF, 0xFF, 0x03, 0x1B, 0xE7, 0x60, + 0x2E, 0x78, 0xFF, 0xFF, 0xE7, 0x60, 0x2E, 0x78, 0xFF, 0xFF, 0xE1, 0x60, 0xE7, 0x78, 0xFF, 0xFF, + 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xF8, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xA6, 0xF3, + 0xFF, 0xFF, 0x02, 0xA4, 0x60, 0x43, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, + 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0xA6, 0xF3, 0x63, 0x45, 0x60, 0x46, + 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, + 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x4B, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x95, 0xF3, 0xFF, 0xFF, 0x10, 0xB0, + 0xFF, 0xFF, 0x11, 0x03, 0x04, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE1, 0x60, 0x9B, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x69, 0xF3, 0xFF, 0xFF, 0x01, 0xB0, 0xFF, 0xFF, 0x11, 0x03, + 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x02, 0x60, + 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE1, 0x60, 0xB1, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x64, 0x68, 0xFB, 0xE2, 0x60, + 0x58, 0x4E, 0x13, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x8A, 0xFB, 0x02, 0x64, 0xC1, 0xFE, 0xDB, 0xFB, + 0xF1, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, 0xF1, 0xFB, 0x02, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, + 0xFF, 0xFF, 0x03, 0x60, 0xE8, 0x63, 0x0E, 0x60, 0x36, 0xFD, 0x08, 0x60, 0x77, 0xF3, 0xFF, 0xFF, + 0x13, 0x1B, 0x16, 0x60, 0xCC, 0xF3, 0x00, 0x61, 0x60, 0x40, 0x00, 0x36, 0x00, 0xB9, 0x60, 0x40, + 0x01, 0x36, 0x01, 0xB9, 0x60, 0x40, 0x02, 0x36, 0x06, 0xB9, 0x60, 0x40, 0x03, 0x36, 0x07, 0xB9, + 0x41, 0x44, 0xD4, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0xD3, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0x00, 0x60, + 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xFF, 0xFF, 0x08, 0x24, 0x46, 0x01, 0xA0, 0x84, 0xA2, 0xDB, + 0x00, 0x63, 0x68, 0xFD, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x30, 0x00, 0x20, 0x40, + 0x06, 0x23, 0x10, 0x00, 0x08, 0x60, 0x27, 0xF1, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, + 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x28, 0xFB, 0xE1, 0x60, 0xF7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x08, 0x60, 0x27, 0xFB, 0x5A, 0xDB, 0x10, 0x60, 0x4E, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x44, 0x01, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x01, 0x64, 0x8A, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x50, 0x64, + 0x3B, 0x42, 0x5A, 0xDB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x95, 0xF3, + 0xFF, 0xFF, 0x10, 0xB0, 0xFF, 0xFF, 0x11, 0x03, 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, 0x00, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x04, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE2, 0x60, + 0x2A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xB9, 0xF1, 0x0E, 0x60, 0x4B, 0xF9, + 0x7D, 0xF1, 0x7C, 0xF9, 0x02, 0x64, 0x8A, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x8A, 0xF3, 0x00, 0x65, + 0xD4, 0x80, 0xFF, 0xFF, 0x0E, 0x03, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x80, 0x60, + 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE2, 0x60, 0x4A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x51, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x1B, 0x60, 0xB0, 0x64, 0x67, 0xFB, 0x1C, 0x60, 0x72, 0x63, 0x7F, 0xF3, 0xBD, 0xDB, 0x80, 0xF3, + 0xBD, 0xDB, 0x81, 0xF3, 0xA3, 0xDB, 0x67, 0xF3, 0x00, 0x60, 0x86, 0xF1, 0x04, 0xA4, 0x67, 0xFB, + 0xD0, 0x80, 0xA0, 0xD3, 0x1F, 0x07, 0x40, 0x47, 0x60, 0x41, 0x0E, 0x65, 0x45, 0xD3, 0x16, 0x60, + 0xC2, 0xF1, 0xFF, 0xFF, 0x03, 0x1B, 0x10, 0xB0, 0xFF, 0xFF, 0xED, 0x02, 0x27, 0x44, 0x06, 0xA4, + 0x60, 0x41, 0xA1, 0xD1, 0x7F, 0xF3, 0x80, 0xF1, 0xD0, 0x80, 0x59, 0xD3, 0x08, 0x02, 0xD0, 0x80, + 0x81, 0xF3, 0x59, 0xD1, 0x04, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x02, 0x03, 0x00, 0xE2, 0x60, + 0xE6, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0x72, 0x63, 0xBD, 0xD3, 0x7F, 0xFB, 0xBD, 0xD3, 0x80, 0xFB, + 0xA3, 0xD3, 0x81, 0xFB, 0x53, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE2, 0x60, + 0x9A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7C, 0xF1, 0x7D, 0xF9, 0x13, 0x60, + 0x1A, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, + 0x16, 0xFB, 0xE2, 0x60, 0xC7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, + 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x63, 0x8A, 0xFD, 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, + 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, 0x54, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x31, 0x44, 0xF9, 0xB4, 0x40, 0x51, 0xE1, 0x60, 0x22, 0x78, 0xFF, 0xFF, 0x27, 0x43, 0x33, 0x60, + 0xBE, 0x65, 0xA5, 0xD3, 0x65, 0x41, 0x10, 0xA3, 0x01, 0xA4, 0xFE, 0xB4, 0xC4, 0x85, 0xFE, 0xA1, + 0xBD, 0xD3, 0x59, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, 0xD5, 0x80, 0x02, 0x02, 0x04, 0x03, 0xF8, 0x01, + 0xE2, 0x60, 0x73, 0x78, 0xFF, 0xFF, 0x55, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x10, 0x60, 0x2A, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, + 0xE2, 0x60, 0xFE, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0xD1, 0x7D, 0xF9, + 0x13, 0x60, 0x1A, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, + 0x08, 0x60, 0x16, 0xFB, 0xE3, 0x60, 0x20, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, + 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x07, 0x60, 0xD0, 0x64, 0x0E, 0x60, 0x4B, 0xFB, + 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, + 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD3, 0x7F, 0xFB, 0xBD, 0xD3, 0x80, 0xFB, 0xA3, 0xD3, 0x81, 0xFB, + 0x31, 0x44, 0xF9, 0xB4, 0x40, 0x51, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, + 0x04, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE3, 0x60, 0x51, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0xB9, 0xF1, 0x0E, 0x60, 0x4B, 0xF9, 0x08, 0x60, 0x15, 0xF1, 0xFE, 0x60, 0xFF, 0x61, + 0xA1, 0x84, 0x5A, 0xD1, 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, + 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xE2, 0x60, 0x73, 0x78, + 0xFF, 0xFF, 0x7D, 0xF1, 0x32, 0x60, 0x7A, 0x61, 0xA1, 0xD3, 0x64, 0x40, 0x01, 0x27, 0x59, 0xD3, + 0x32, 0x60, 0x7E, 0x61, 0xFD, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0xA1, 0xDB, 0x27, 0x42, + 0x0C, 0xA2, 0xA2, 0xD3, 0x16, 0x60, 0xAD, 0xF3, 0x00, 0xBD, 0x01, 0x63, 0xAC, 0x81, 0x09, 0x03, + 0x08, 0x03, 0xB8, 0x60, 0x58, 0x4D, 0x15, 0x78, 0xFF, 0xFF, 0x00, 0xB8, 0x01, 0x63, 0x01, 0x03, + 0x60, 0x43, 0x0E, 0x60, 0x35, 0xFD, 0x5F, 0xF5, 0x00, 0x64, 0x2B, 0xFA, 0x20, 0x64, 0x2A, 0xFA, + 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD1, 0x2C, 0xF8, 0x32, 0xF8, 0xBD, 0xD1, 0x2D, 0xF8, 0x33, 0xF8, + 0xA3, 0xD1, 0x2E, 0xF8, 0x34, 0xF8, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, + 0x31, 0xF8, 0xB9, 0xF1, 0x19, 0xF8, 0xF8, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0x00, 0xF4, 0x01, 0x63, + 0x32, 0x40, 0x08, 0x26, 0x10, 0xBB, 0x16, 0x60, 0xC2, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0xFE, 0x26, + 0x10, 0xBB, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, 0x0A, 0x00, 0x19, 0x60, 0x45, 0xF3, + 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x22, 0x20, 0xBB, 0x63, 0x44, 0xFF, 0xFF, 0x04, 0x7F, 0x60, 0x43, + 0x09, 0xFC, 0x0E, 0x60, 0x35, 0xF3, 0x12, 0x61, 0x59, 0xDA, 0x1C, 0x60, 0x72, 0x63, 0xBD, 0xD1, + 0x59, 0xD8, 0xBD, 0xD1, 0x59, 0xD8, 0xA3, 0xD1, 0x59, 0xD8, 0x35, 0x60, 0x98, 0x64, 0x40, 0x48, + 0xD9, 0x81, 0xFF, 0x60, 0xF2, 0x64, 0xF1, 0x60, 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x5F, 0xF5, + 0x3F, 0xFC, 0xDB, 0x83, 0x1A, 0x60, 0x4C, 0xFD, 0x20, 0x7C, 0x5A, 0xD9, 0x63, 0x41, 0x34, 0x60, + 0x9C, 0x63, 0x12, 0x65, 0x00, 0xF4, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, + 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, + 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x5F, 0xF5, 0x25, 0x60, 0xCE, 0x64, + 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0x00, 0x66, 0x46, 0x46, 0xC1, 0xFE, 0x16, 0x64, 0x68, 0xFB, 0x56, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x0E, 0x60, 0x38, 0xF3, 0xFF, 0xFF, 0x64, 0xA4, 0xA2, 0xDB, 0x0E, 0x60, 0x38, 0xF1, 0x0E, 0x60, + 0x4B, 0xF9, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0x00, 0x60, 0x1C, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE4, 0x60, 0x23, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, + 0x9C, 0x84, 0x0E, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x57, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x00, 0x64, + 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xE2, 0x60, 0x73, 0x78, 0xFF, 0xFF, + 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x16, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, + 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x58, 0x64, + 0x3B, 0x42, 0x5A, 0xDB, 0x00, 0x64, 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0xE6, 0x60, 0x36, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x3D, 0x03, + 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x26, 0x46, 0x00, 0xF4, 0x0A, 0xF2, 0x09, 0xF2, 0x04, 0x1B, 0x01, 0xB0, 0x01, 0x7C, 0x2D, 0x02, + 0x0A, 0xF8, 0x59, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0A, 0xF2, 0x26, 0x46, 0x40, 0x59, 0x02, 0x60, + 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x31, 0xF2, 0x59, 0xDB, + 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, + 0x00, 0x66, 0x46, 0x46, 0x05, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0xE7, 0x60, + 0x0B, 0x78, 0xFF, 0xFF, 0xE2, 0x60, 0x73, 0x78, 0xFF, 0xFF, 0x5A, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x78, 0x43, 0x02, 0x61, 0x29, 0x60, 0xEA, 0x78, 0xFF, 0xFF, 0x5B, 0x64, 0x3B, 0x42, 0x5A, 0xDB, + 0x0C, 0xF2, 0xFF, 0xFF, 0x60, 0x41, 0xFF, 0xB1, 0xFF, 0xA1, 0x60, 0x47, 0xFF, 0xB4, 0xC8, 0x02, + 0xC7, 0x03, 0x34, 0x60, 0xF4, 0x63, 0x30, 0x64, 0xBD, 0xDB, 0x66, 0x45, 0x26, 0x46, 0x3F, 0xF2, + 0x34, 0x60, 0xF2, 0x61, 0xC2, 0xA0, 0xFF, 0xFF, 0x01, 0x04, 0x3E, 0x64, 0x65, 0x46, 0x02, 0xA4, + 0xA1, 0xDB, 0xC8, 0x81, 0x12, 0x65, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, + 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, + 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x0C, 0xF2, 0xFF, 0xFF, 0x1A, 0x65, + 0x60, 0x47, 0xFF, 0xB4, 0xC4, 0x85, 0xDC, 0x60, 0x58, 0x4D, 0xC7, 0x78, 0xFF, 0xFF, 0x0B, 0xF2, + 0xFF, 0xFF, 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x61, 0x44, + 0x94, 0xFB, 0x27, 0x45, 0x02, 0x62, 0x46, 0xD3, 0x5A, 0xD1, 0x60, 0x47, 0x56, 0xFB, 0x64, 0x47, + 0x55, 0xFB, 0x00, 0x64, 0x5B, 0xFB, 0x0C, 0x62, 0x46, 0xD3, 0x7E, 0xFB, 0x0B, 0xF0, 0x0F, 0x60, + 0xFF, 0x64, 0xA0, 0x84, 0x83, 0xFB, 0x1C, 0x60, 0x6A, 0x62, 0xA2, 0xD3, 0x85, 0xFB, 0x26, 0x46, + 0x32, 0xF0, 0x7F, 0xF9, 0x33, 0xF0, 0x80, 0xF9, 0x34, 0xF0, 0x81, 0xF9, 0x2E, 0x60, 0x2E, 0x64, + 0x2D, 0x60, 0x8A, 0x63, 0xA0, 0xD1, 0xA3, 0xD9, 0x64, 0x41, 0x58, 0xD1, 0x5B, 0xD9, 0x7D, 0xF3, + 0x66, 0x45, 0xA6, 0xF5, 0x60, 0x40, 0x01, 0x27, 0x08, 0x00, 0x91, 0xFA, 0x61, 0x44, 0xFD, 0x60, + 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x12, 0xFA, 0x07, 0x00, 0x11, 0xF8, 0x64, 0x44, 0xFD, 0x60, + 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x12, 0xFA, 0x65, 0x46, 0xA6, 0xF3, 0xFF, 0xFF, 0x02, 0xA4, + 0x40, 0x4B, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xFA, 0xA3, 0x00, 0x60, 0x17, 0x61, 0x00, 0x60, + 0x01, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, 0x7A, 0x78, 0xFF, 0xFF, + 0x00, 0xBB, 0xFF, 0xFF, 0x00, 0x02, 0x00, 0x64, 0x40, 0x4A, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, + 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xFE, 0x60, 0x58, 0x4E, 0x2C, 0x78, 0xFF, 0xFF, 0x20, 0xFE, + 0x00, 0x65, 0x00, 0x64, 0x19, 0x60, 0x3B, 0xFB, 0x02, 0x00, 0x20, 0xFE, 0xFF, 0x65, 0x02, 0x60, + 0x00, 0x63, 0x60, 0xFE, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0x20, 0xFE, 0xCD, 0x81, 0x60, 0x40, + 0x80, 0x2A, 0x39, 0x00, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, 0x01, 0x64, 0x2E, 0x00, 0x04, 0x3A, + 0x02, 0x00, 0x02, 0x64, 0x2A, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x04, 0x64, 0x26, 0x00, 0x16, 0x3A, + 0x02, 0x00, 0x08, 0x64, 0x22, 0x00, 0x0C, 0x3A, 0x02, 0x00, 0x10, 0x64, 0x1E, 0x00, 0x12, 0x3A, + 0x02, 0x00, 0x20, 0x64, 0x1A, 0x00, 0x18, 0x3A, 0x02, 0x00, 0x40, 0x64, 0x16, 0x00, 0x24, 0x3A, + 0x02, 0x00, 0x80, 0x64, 0x12, 0x00, 0x30, 0x3A, 0x02, 0x00, 0x01, 0x67, 0x0E, 0x00, 0x48, 0x3A, + 0x02, 0x00, 0x02, 0x67, 0x0A, 0x00, 0x60, 0x3A, 0x02, 0x00, 0x04, 0x67, 0x06, 0x00, 0x6C, 0x3A, + 0x02, 0x00, 0x08, 0x67, 0x02, 0x00, 0x00, 0x64, 0x00, 0x00, 0x19, 0x60, 0x3B, 0xF1, 0xFF, 0xFF, + 0xB0, 0x84, 0x19, 0x60, 0x3B, 0xFB, 0x61, 0x40, 0x00, 0x36, 0x05, 0x00, 0x60, 0xFE, 0xBD, 0xD3, + 0xFF, 0xFF, 0x20, 0xFE, 0xBB, 0x01, 0x65, 0x40, 0x00, 0x3A, 0x1E, 0x00, 0x26, 0x46, 0x3F, 0xF2, + 0x00, 0xF4, 0x60, 0x43, 0xFA, 0xA3, 0x00, 0x60, 0x17, 0x61, 0x00, 0x60, 0x32, 0x65, 0x01, 0x60, + 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, + 0x0B, 0x03, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xFE, 0x60, + 0x58, 0x4E, 0x2C, 0x78, 0xFF, 0xFF, 0x91, 0x01, 0x20, 0xFE, 0x00, 0x65, 0xFC, 0x60, 0x58, 0x4E, + 0xC7, 0x78, 0xFF, 0xFF, 0xA1, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, 0x04, 0x00, 0xFD, 0x60, + 0x58, 0x4E, 0x11, 0x78, 0xFF, 0xFF, 0x20, 0xFE, 0x37, 0x60, 0xF8, 0x61, 0xA1, 0xD1, 0xA1, 0xF3, + 0x01, 0x60, 0xAC, 0x63, 0x60, 0x45, 0x2A, 0x44, 0x79, 0xFB, 0xA3, 0xD5, 0x65, 0x40, 0x01, 0x27, + 0x5B, 0xD5, 0x65, 0x40, 0x01, 0x27, 0x59, 0xD1, 0x66, 0x41, 0xA0, 0x84, 0x24, 0x94, 0x2B, 0x46, + 0x0F, 0xFA, 0x7A, 0xFB, 0x16, 0x64, 0x12, 0xFA, 0x01, 0x64, 0x11, 0xFA, 0x66, 0x5C, 0xC2, 0x60, + 0x58, 0x4E, 0x6D, 0x78, 0xFF, 0xFF, 0xA6, 0xF3, 0xFF, 0xFF, 0x02, 0xA4, 0x40, 0x4B, 0x60, 0x46, + 0x00, 0x64, 0x17, 0xFA, 0x00, 0x64, 0x16, 0xFA, 0x13, 0xFA, 0x00, 0x65, 0x26, 0x46, 0xFD, 0x60, + 0x58, 0x4E, 0xDD, 0x78, 0xFF, 0xFF, 0xA6, 0xF3, 0x1D, 0x60, 0xC0, 0x65, 0x02, 0xA4, 0x60, 0x46, + 0x05, 0xF0, 0x60, 0x41, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x00, 0x7C, 0x44, 0xD9, 0x26, 0x46, + 0x31, 0xF2, 0x61, 0x5C, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x26, 0x46, 0x2F, 0xF0, + 0x61, 0x46, 0x03, 0xF8, 0x26, 0x46, 0x30, 0xF0, 0x61, 0x46, 0x04, 0xF8, 0x26, 0x46, 0x31, 0xF0, + 0x61, 0x46, 0x05, 0xF8, 0x26, 0x46, 0xD9, 0x60, 0x58, 0x4E, 0xAE, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, + 0x46, 0x46, 0x03, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, 0x01, 0x63, 0x8A, 0xFD, + 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, + 0x5C, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xE1, 0x60, 0x22, 0x78, 0xFF, 0xFF, 0xFF, 0x60, 0xF7, 0x65, + 0x20, 0x44, 0x24, 0x80, 0xDA, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0xDB, 0xF3, 0xFF, 0xFF, 0xFD, 0xA0, + 0x2A, 0xF2, 0x03, 0x03, 0xE6, 0x60, 0xDE, 0x78, 0xFF, 0xFF, 0x60, 0x40, 0xB0, 0x36, 0x11, 0x00, + 0xC0, 0x36, 0x02, 0x00, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, + 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xDA, 0x60, 0x74, 0x78, + 0xFF, 0xFF, 0x66, 0x45, 0x00, 0xF4, 0x0A, 0xF2, 0x0B, 0xF2, 0xFE, 0xA0, 0xF3, 0xA0, 0x67, 0x02, + 0x60, 0x41, 0x09, 0xF2, 0x1D, 0x03, 0x00, 0xA0, 0xFF, 0xA0, 0x4B, 0x03, 0x5D, 0x03, 0x00, 0xA0, + 0xFF, 0xFF, 0x47, 0x03, 0x01, 0x64, 0x10, 0x60, 0x0B, 0xFB, 0x0D, 0x64, 0x10, 0x60, 0x0C, 0xFB, + 0x03, 0x64, 0x10, 0x60, 0x0D, 0xFB, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, + 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xDA, 0x60, 0x74, 0x78, 0xFF, 0xFF, + 0x16, 0x60, 0xC3, 0xF3, 0xFF, 0xFF, 0xFE, 0xA0, 0x20, 0x60, 0x16, 0x61, 0x15, 0x02, 0x01, 0x64, + 0xA1, 0xDB, 0x00, 0x64, 0x10, 0x60, 0x0C, 0xFB, 0x01, 0x64, 0x10, 0x60, 0x0D, 0xFB, 0x26, 0x46, + 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, + 0x46, 0x46, 0xDA, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0xA1, 0xDB, 0x00, 0x64, 0x10, 0x60, + 0x0C, 0xFB, 0x01, 0x64, 0x10, 0x60, 0x0D, 0xFB, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, + 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xDA, 0x60, 0x74, 0x78, + 0xFF, 0xFF, 0x65, 0x46, 0x07, 0xF4, 0x06, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, 0x06, 0xFA, 0x65, 0x46, + 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, + 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0xDC, 0x60, 0x09, 0x78, 0xFF, 0xFF, 0x0A, 0xF2, + 0x09, 0xF2, 0xFC, 0xA0, 0xFF, 0xA0, 0x11, 0x02, 0x0A, 0x02, 0x0B, 0xF2, 0x65, 0x46, 0x0A, 0x1B, + 0x66, 0x41, 0x07, 0xF4, 0x06, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0xDA, 0x60, + 0x74, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x65, 0x46, 0x68, 0xF1, 0x2A, 0xF2, + 0x64, 0x41, 0x60, 0x40, 0xA0, 0x3A, 0x02, 0x00, 0x08, 0xB1, 0x04, 0x00, 0xC0, 0x3A, 0x0B, 0x00, + 0x04, 0xB1, 0xFF, 0xFF, 0x1E, 0x03, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x16, 0x00, 0xB0, 0x3A, 0x02, 0x00, 0x01, 0x65, 0x07, 0x00, 0x10, 0x3A, + 0x02, 0x00, 0x02, 0x65, 0x03, 0x00, 0x30, 0x3A, 0x0C, 0x00, 0x10, 0x65, 0xA5, 0x80, 0xFF, 0xFF, + 0x08, 0x03, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x00, 0x66, 0x2F, 0x58, 0xFF, 0xFF, 0x16, 0x60, 0xC3, 0xF3, 0xFF, 0xFF, 0xFC, 0xA0, 0xFF, 0xFF, + 0x14, 0x04, 0x00, 0x60, 0x02, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE7, 0x60, 0x1B, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x19, 0x60, 0xA5, 0xF1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, + 0xFF, 0xFF, 0x03, 0x03, 0xDA, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, + 0xD9, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0xE2, 0x60, 0x73, 0x78, 0xFF, 0xFF, 0x4E, 0x64, 0x3B, 0x42, + 0x5A, 0xDB, 0x2E, 0xF5, 0xFF, 0xFF, 0x27, 0xF2, 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, + 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, + 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, + 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, + 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, + 0x61, 0x46, 0x25, 0xF2, 0x26, 0xF0, 0xA7, 0xF2, 0xA8, 0xF0, 0x65, 0xF5, 0xFF, 0xFF, 0x00, 0xF4, + 0xFF, 0xFF, 0x89, 0xF8, 0x65, 0xF5, 0xFF, 0xFF, 0x07, 0xFC, 0x2C, 0xFA, 0x2D, 0xF8, 0xAE, 0xFA, + 0xEA, 0xF3, 0x2F, 0xFA, 0xEB, 0xF3, 0x30, 0xFA, 0xEC, 0xF3, 0x31, 0xFA, 0x7F, 0xF3, 0x32, 0xFA, + 0x80, 0xF3, 0x33, 0xFA, 0x81, 0xF3, 0x34, 0xFA, 0x1B, 0x60, 0xFE, 0xF3, 0xFF, 0xFF, 0x03, 0x1B, + 0x00, 0x60, 0xA0, 0x64, 0x02, 0x00, 0x00, 0x60, 0xC0, 0x64, 0x2A, 0xFA, 0x02, 0x63, 0x3F, 0xFC, + 0xAB, 0xFC, 0x00, 0x64, 0x3E, 0xFA, 0xC9, 0xF1, 0x19, 0xF8, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, + 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x66, + 0x46, 0x46, 0xC1, 0xFE, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xE1, 0x60, 0x34, 0x78, + 0xFF, 0xFF, 0x00, 0x60, 0x3A, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, 0xFF, 0xFF, 0x66, 0x44, + 0x61, 0xFB, 0xA6, 0xF3, 0x07, 0xFA, 0x0C, 0x60, 0x80, 0x64, 0xB9, 0xF1, 0x19, 0xF8, 0x0E, 0xFA, + 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x00, 0x60, 0x3A, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, + 0xFF, 0xFF, 0x66, 0x44, 0x60, 0xFB, 0xA6, 0xF3, 0x07, 0xFA, 0x0C, 0x60, 0x80, 0x64, 0x0E, 0xFA, + 0xB9, 0xF1, 0x19, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0xE8, 0x60, 0xEA, 0x64, 0x08, 0x60, + 0x33, 0xFB, 0x00, 0x60, 0x80, 0x64, 0x08, 0x60, 0x10, 0xFB, 0xE7, 0x60, 0xCB, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x16, 0x60, 0x87, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, 0x03, 0xA8, + 0x04, 0x03, 0x03, 0x03, 0xE8, 0x60, 0xDC, 0x78, 0xFF, 0xFF, 0x04, 0x60, 0x00, 0x65, 0x20, 0x44, + 0x34, 0x80, 0x10, 0x60, 0x1E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x9B, 0xFE, 0x03, 0x05, 0x20, 0x40, + 0x4B, 0x23, 0x0A, 0x00, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x10, 0xFB, 0xE7, 0x60, 0xD9, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x13, 0xF3, 0xFF, 0xFF, 0x60, 0x40, + 0x01, 0x2A, 0x07, 0x00, 0x90, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x00, 0x64, 0xA2, 0xDB, + 0x04, 0x00, 0x10, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x8A, 0xF3, 0x58, 0xFB, 0x82, 0xF1, + 0xBA, 0xFE, 0x01, 0xA8, 0x59, 0xF9, 0x04, 0x02, 0x02, 0x64, 0x8A, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, + 0x64, 0x47, 0xDB, 0xF3, 0x10, 0xB0, 0x04, 0xA8, 0x2B, 0x02, 0x2A, 0x02, 0x61, 0xF5, 0xEA, 0xF1, + 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0x7F, 0xF1, 0x2C, 0xF8, 0x32, 0xF8, + 0x80, 0xF1, 0x2D, 0xF8, 0x33, 0xF8, 0x81, 0xF1, 0x2E, 0xF8, 0x34, 0xF8, 0x10, 0x60, 0x48, 0x64, + 0x2A, 0xFA, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x60, 0x01, 0x64, 0x08, 0x60, 0x10, 0xFB, + 0xE8, 0x60, 0x36, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x67, 0x82, 0xFB, + 0x8A, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0xFF, 0xFF, 0x0A, 0x03, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, + 0x10, 0xFB, 0xE8, 0x60, 0x38, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, + 0x1E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x05, 0x7C, 0x53, 0xF9, 0x2F, 0x60, 0x24, 0x64, 0x54, 0xFB, + 0x19, 0x60, 0x40, 0xF3, 0xFF, 0xFF, 0x15, 0x18, 0x10, 0x60, 0x1E, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, + 0x00, 0x64, 0x08, 0x60, 0x10, 0xFB, 0xE8, 0x60, 0x69, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x19, 0x60, 0x41, 0xF3, 0xFF, 0x60, 0x80, 0x65, 0xA4, 0x80, 0x5A, 0xD3, 0x05, 0x02, + 0x04, 0x1B, 0x5A, 0xD3, 0xFF, 0xFF, 0x01, 0x1B, 0x15, 0x00, 0x10, 0x60, 0x1E, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x10, 0xFB, 0xE8, 0x60, 0x8A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0xFF, 0xFF, 0x59, 0xF3, 0x82, 0xFB, 0x60, 0x40, 0x10, 0x27, 0xDA, 0xFE, + 0xDB, 0xF3, 0x00, 0xA8, 0x04, 0xA8, 0x23, 0x02, 0x22, 0x02, 0x60, 0xF5, 0xEA, 0xF1, 0x2F, 0xF8, + 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0x7F, 0xF1, 0x2C, 0xF8, 0x80, 0xF1, 0x2D, 0xF8, + 0x81, 0xF1, 0x2E, 0xF8, 0xA4, 0x64, 0x2A, 0xFA, 0x83, 0xF1, 0xC0, 0x67, 0xB0, 0x84, 0x2B, 0xFA, + 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x20, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x00, 0x60, + 0x04, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x23, 0xFA, 0xF1, 0x60, + 0x02, 0x64, 0x24, 0xFA, 0x26, 0x60, 0x0A, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0xEB, 0x60, 0xFF, 0x65, 0x20, 0x44, + 0x24, 0x80, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x58, 0xF3, 0x8A, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x10, 0x60, 0x1E, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x00, 0x60, 0x80, 0x64, 0x08, 0x60, 0x10, 0xFB, 0xE7, 0x60, 0xCB, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x9C, 0xF1, 0x00, 0x64, 0xB0, 0x86, 0x9C, 0xFB, 0x07, 0x03, 0x26, 0x60, + 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0xEB, 0x60, 0xFF, 0x65, + 0x20, 0x44, 0x24, 0x80, 0x10, 0x60, 0x1E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x80, 0x64, + 0x08, 0x60, 0x10, 0xFB, 0xE7, 0x60, 0xCB, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x95, 0xF3, 0x26, 0x46, 0x60, 0x43, 0x01, 0x2A, 0x20, 0x00, 0x0F, 0xF2, 0x2A, 0xF0, 0x60, 0x40, + 0x10, 0x2A, 0x0F, 0x00, 0x64, 0x40, 0x04, 0x27, 0x18, 0x00, 0xFD, 0xB3, 0x64, 0x40, 0x20, 0x27, + 0x02, 0xBB, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x0B, 0x00, 0xFB, 0xB3, 0x64, 0x40, 0x20, 0x27, 0x04, 0xBB, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, + 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x95, 0xFD, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, + 0xDB, 0xF3, 0x3F, 0xF2, 0x04, 0xA8, 0x57, 0xFB, 0x02, 0x03, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0xF4, + 0x1E, 0x63, 0x08, 0x64, 0x40, 0x48, 0xBD, 0xD2, 0xFF, 0xFF, 0x60, 0x47, 0x05, 0x36, 0x0B, 0x00, + 0xFF, 0xB5, 0xC7, 0x83, 0x01, 0x2A, 0xF7, 0x01, 0x4F, 0xD2, 0x5B, 0xD2, 0x60, 0x40, 0x05, 0x37, + 0x0B, 0x00, 0xDF, 0x83, 0xF5, 0x01, 0xFF, 0xB5, 0x65, 0x41, 0xA3, 0xD2, 0x47, 0x8A, 0x60, 0x47, + 0x40, 0x4C, 0x5B, 0xD2, 0xDF, 0x83, 0x08, 0x00, 0x40, 0x4C, 0x00, 0x7F, 0xDC, 0x85, 0x47, 0x8A, + 0x60, 0x41, 0x5B, 0xD2, 0xDB, 0x83, 0x60, 0x47, 0x01, 0xB0, 0xFE, 0xB5, 0x02, 0x03, 0x02, 0x64, + 0x40, 0x48, 0x2C, 0x47, 0xFF, 0xB4, 0x73, 0xF1, 0x08, 0x28, 0x73, 0xFB, 0x83, 0xF1, 0x65, 0x44, + 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xFD, 0xA1, 0xE1, 0x81, 0xE1, 0x81, 0xE1, 0x85, 0xC4, 0x81, + 0xD0, 0x84, 0xD1, 0x80, 0x28, 0x07, 0x27, 0x06, 0x9C, 0x84, 0xDC, 0x84, 0xE8, 0x84, 0xE8, 0x84, + 0xE8, 0x85, 0x94, 0xF3, 0xC7, 0x83, 0x01, 0x26, 0x60, 0x47, 0xAB, 0x83, 0xFC, 0xA3, 0x02, 0x00, + 0x03, 0x04, 0x00, 0xF4, 0x84, 0xA3, 0xFC, 0x01, 0x80, 0x65, 0x47, 0xD0, 0x28, 0x41, 0xA0, 0x80, + 0xFE, 0xA1, 0x14, 0x03, 0x08, 0x02, 0x08, 0x60, 0x2D, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x1B, 0x00, 0x08, 0x60, 0x2D, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x13, 0x00, 0x28, 0x41, 0xFE, 0xA1, 0xFF, 0xFF, 0x08, 0x03, 0x08, 0x60, + 0x2D, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x07, 0x00, 0x08, 0x60, + 0x2D, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x08, 0x60, 0x1B, 0xF1, + 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, + 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x02, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x63, 0x95, 0xFD, 0x1C, 0x60, 0x9E, 0x63, 0x00, 0x64, 0xA3, 0xDB, + 0x06, 0xA3, 0x10, 0x60, 0x98, 0x64, 0xBD, 0xDB, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, 0xE9, 0x60, + 0xB8, 0x64, 0x08, 0x60, 0x4B, 0xFB, 0xCE, 0xF1, 0x0E, 0x60, 0x51, 0xF9, 0x1C, 0x60, 0xAA, 0x63, + 0x00, 0x64, 0xA3, 0xDB, 0x06, 0xA3, 0x10, 0x60, 0x9C, 0x64, 0xBD, 0xDB, 0xBD, 0xDB, 0x06, 0x64, + 0xA3, 0xDB, 0xE9, 0x60, 0xC1, 0x64, 0x08, 0x60, 0x4D, 0xFB, 0x16, 0x60, 0xAE, 0xF1, 0x0E, 0x60, + 0x57, 0xF9, 0x00, 0x60, 0x3A, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, 0xFF, 0xFF, 0x66, 0x44, + 0x63, 0xFB, 0xA6, 0xF3, 0x07, 0xFA, 0xB9, 0xF3, 0x19, 0xFA, 0xF8, 0x60, 0x80, 0x64, 0x0E, 0xFA, + 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x00, 0x60, 0x3A, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, + 0xFF, 0xFF, 0x66, 0x44, 0x64, 0xFB, 0xA6, 0xF3, 0x07, 0xFA, 0xB9, 0xF3, 0x19, 0xFA, 0x24, 0x60, + 0x80, 0x64, 0x0E, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x00, 0x64, 0x08, 0x60, 0x2D, 0xFB, + 0x5A, 0xDB, 0xEA, 0x60, 0x1F, 0x64, 0x08, 0x60, 0x37, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x63, + 0x95, 0xFD, 0xBA, 0xFE, 0xFE, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x82, 0xFD, 0x08, 0x60, + 0x15, 0xF1, 0x04, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x64, 0x08, 0x60, + 0x1B, 0xFB, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x16, 0x60, 0xAB, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, + 0xFF, 0xFF, 0x05, 0x03, 0x19, 0x60, 0xF0, 0xF1, 0x0E, 0x60, 0x57, 0xF9, 0x04, 0x00, 0x16, 0x60, + 0xAE, 0xF1, 0x0E, 0x60, 0x57, 0xF9, 0x16, 0x60, 0xAB, 0xF3, 0xFF, 0xFF, 0x09, 0x1B, 0x00, 0x64, + 0x82, 0xFB, 0xBA, 0xFE, 0x00, 0x64, 0x08, 0x60, 0x1B, 0xFB, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, + 0xBA, 0xFE, 0x95, 0xF3, 0x00, 0x63, 0x82, 0xFD, 0x10, 0xBC, 0x95, 0xFB, 0xFE, 0x60, 0xFF, 0x65, + 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0x00, 0x60, 0x64, 0x63, 0x0E, 0x60, 0x37, 0xFD, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x01, 0x60, 0x04, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEA, 0x60, 0x73, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, + 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xA2, 0x01, 0x31, 0x40, 0x04, 0x2A, 0xE5, 0x01, + 0x20, 0x40, 0x12, 0x23, 0x11, 0x00, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, + 0x5A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x81, 0x60, 0x00, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEA, 0x60, + 0x73, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0xDD, 0x01, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x01, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x64, 0xF5, 0xB9, 0xF1, 0x19, 0xF8, 0x7F, 0xF1, + 0x2C, 0xF8, 0x32, 0xF8, 0x80, 0xF1, 0x2D, 0xF8, 0x33, 0xF8, 0x81, 0xF1, 0x2E, 0xF8, 0x34, 0xF8, + 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0x11, 0x60, 0x48, 0x64, + 0x2A, 0xFA, 0x00, 0x64, 0x2B, 0xFA, 0x23, 0xFA, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, + 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x60, + 0x01, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEA, 0x60, 0xC9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x64, 0xF5, 0x23, 0xF2, 0xFF, 0xFF, 0x01, 0x18, 0x82, 0x01, 0x10, 0x67, 0x82, 0xFB, + 0x03, 0x64, 0x96, 0xFB, 0xFE, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, 0x08, 0xF1, + 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0x81, 0x60, 0x00, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEA, 0x60, 0xEA, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x0C, 0x00, 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xEA, 0x60, 0x1F, 0x78, 0xFF, 0xFF, 0x06, 0x60, 0x00, 0x65, + 0x20, 0x41, 0x8C, 0xF3, 0xA5, 0x80, 0x01, 0xB0, 0x01, 0x02, 0x06, 0x00, 0x10, 0x60, 0x36, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0x6E, 0x65, 0xA5, 0xD3, 0x01, 0x63, + 0x8A, 0xFD, 0x26, 0x1B, 0x00, 0x60, 0x64, 0x64, 0xA5, 0xDB, 0x64, 0xF5, 0xB9, 0xF1, 0x19, 0xF8, + 0x7F, 0xF1, 0x2C, 0xF8, 0x32, 0xF8, 0x80, 0xF1, 0x2D, 0xF8, 0x33, 0xF8, 0x81, 0xF1, 0x2E, 0xF8, + 0x34, 0xF8, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0x11, 0x60, + 0x48, 0x64, 0x2A, 0xFA, 0x00, 0x64, 0x2B, 0xFA, 0x23, 0xFA, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, + 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x06, 0x00, + 0x95, 0xF3, 0x32, 0x40, 0x02, 0x26, 0x02, 0x00, 0x40, 0x2A, 0xDA, 0xFE, 0xC1, 0xFE, 0x10, 0x60, + 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, 0x82, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEB, 0x60, + 0x45, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, + 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xEA, 0x60, 0x1F, 0x78, + 0xFF, 0xFF, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x06, 0x03, 0xA0, 0x84, 0xA2, 0xDB, + 0xBA, 0xFE, 0xED, 0x60, 0x6D, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x8A, 0xFB, 0x01, 0x60, 0x00, 0x65, + 0x20, 0x44, 0x34, 0x80, 0xBA, 0xFE, 0xC1, 0xFE, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x10, 0x60, 0x5A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, 0x46, 0x64, 0x08, 0x60, 0x1C, 0xFB, + 0xEB, 0x60, 0x76, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, + 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xEA, 0x60, + 0x1F, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x45, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x08, 0x60, 0x2D, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0F, 0x03, + 0xA0, 0x84, 0xA2, 0xDB, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xED, 0x60, 0x6D, 0x78, 0xFF, 0xFF, 0x31, 0x01, 0x00, 0x60, + 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0B, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x16, 0x60, 0xAC, 0xF1, + 0x95, 0xF3, 0x00, 0x61, 0xD1, 0x80, 0xF7, 0xB4, 0xF1, 0x03, 0x95, 0xFB, 0x33, 0x00, 0x00, 0x60, + 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0E, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x16, 0x60, 0xAC, 0xF1, + 0x95, 0xF3, 0x00, 0x61, 0xD1, 0x80, 0x08, 0xBC, 0x03, 0x02, 0xEC, 0x60, 0x9C, 0x78, 0xFF, 0xFF, + 0x95, 0xFB, 0x20, 0x00, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0xEC, 0x60, 0x9C, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x40, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xC8, 0x01, 0x00, 0x60, 0x02, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xED, 0x60, 0x6D, 0x78, 0xFF, 0xFF, + 0x2F, 0x58, 0xFF, 0xFF, 0x02, 0x63, 0x95, 0xF3, 0x8A, 0xFD, 0x01, 0xBC, 0xC1, 0xFE, 0x95, 0xFB, + 0xCE, 0xF1, 0x0E, 0x60, 0x51, 0xF9, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, + 0x5A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, 0x34, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEC, 0x60, + 0x05, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x1C, 0x60, 0x9E, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, + 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0D, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x9E, 0x64, + 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xEA, 0x60, 0x1F, 0x78, + 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x22, 0x03, 0xA0, 0x84, 0xA2, 0xDB, + 0x95, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x04, 0x2A, 0x01, 0x00, 0xD5, 0x01, 0x1C, 0x60, 0x9E, 0x64, + 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x95, 0xF3, 0xFF, 0xFF, + 0x60, 0x40, 0x08, 0x2A, 0x01, 0x00, 0x68, 0x00, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x02, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x59, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xED, 0x60, 0x6D, 0x78, 0xFF, 0xFF, + 0x08, 0x60, 0x2D, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x08, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x95, 0xF3, 0xFF, 0xFF, 0x08, 0xBC, 0x95, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x60, + 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xA4, 0x01, 0x00, 0x60, + 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0B, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x9E, 0x64, + 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x35, 0x00, 0x00, 0x60, + 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0B, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x9E, 0x64, + 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x1E, 0x00, 0x08, 0x60, + 0x1B, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x14, 0x03, 0xA0, 0x84, 0xA2, 0xDB, + 0x95, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x2A, 0x01, 0x00, 0x16, 0x00, 0x08, 0x60, 0x1B, 0xF1, + 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x08, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xED, 0x60, + 0x6D, 0x78, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x00, 0x95, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, + 0x95, 0xFB, 0xEA, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0xAB, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, + 0xFF, 0xFF, 0x03, 0x02, 0xED, 0x60, 0x76, 0x78, 0xFF, 0xFF, 0x95, 0xF3, 0x01, 0x63, 0x8A, 0xFD, + 0x21, 0xBC, 0x95, 0xFB, 0x63, 0xF5, 0x7F, 0xF1, 0x2C, 0xF8, 0x80, 0xF1, 0x2D, 0xF8, 0x81, 0xF1, + 0x2E, 0xF8, 0x83, 0xF1, 0xC0, 0x67, 0xB0, 0x84, 0x2B, 0xFA, 0xB9, 0xF1, 0x19, 0xF8, 0xEA, 0xF1, + 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0x10, 0x60, 0xA4, 0x64, 0x2A, 0xFA, + 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x60, 0x50, 0x64, 0x0E, 0x60, 0x51, 0xFB, 0x1C, 0x60, + 0x9E, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x10, 0x60, + 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x5A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, + 0x2C, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEC, 0x60, 0xE9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0D, 0x03, + 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x9E, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, + 0xFF, 0xFF, 0x04, 0xFF, 0xEA, 0x60, 0x1F, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x2D, 0xF1, 0x00, 0x60, + 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x95, 0x01, 0x08, 0x60, + 0x1B, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x08, 0x03, 0xA0, 0x84, 0xA2, 0xDB, + 0x95, 0xF3, 0xFF, 0xFF, 0x02, 0xB0, 0xFF, 0xFF, 0x49, 0x03, 0x86, 0x01, 0x00, 0x60, 0x08, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x40, 0x00, 0x00, 0x60, 0x02, 0x64, + 0xA0, 0x80, 0x9C, 0x84, 0x14, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x9E, 0x64, 0x13, 0x60, + 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x16, 0x60, 0xAC, 0xF3, 0x95, 0xF3, + 0x00, 0xA8, 0xF7, 0xB4, 0x2B, 0x03, 0x95, 0xFB, 0xEB, 0x60, 0xE2, 0x78, 0xFF, 0xFF, 0x00, 0x60, + 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x15, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x9E, 0x64, + 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x16, 0x60, 0xAC, 0xF3, + 0x95, 0xF3, 0x00, 0xA8, 0x08, 0xBC, 0x01, 0x02, 0x4F, 0x01, 0x95, 0xFB, 0xEB, 0x60, 0xE2, 0x78, + 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, + 0xA0, 0x84, 0xA2, 0xDB, 0x02, 0x00, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x00, 0x1C, 0x60, 0x9E, 0x64, + 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x95, 0xF3, 0xFF, 0xFF, + 0xFE, 0xB4, 0x95, 0xFB, 0xEA, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0x95, 0xF3, 0x01, 0x63, 0x8A, 0xFD, + 0x01, 0xBC, 0x95, 0xFB, 0x00, 0x64, 0x82, 0xFB, 0xC1, 0xFE, 0x28, 0x00, 0x95, 0xF3, 0x01, 0x63, + 0x8A, 0xFD, 0x01, 0xBC, 0x95, 0xFB, 0x00, 0x64, 0x82, 0xFB, 0x63, 0xF5, 0x7F, 0xF1, 0x2C, 0xF8, + 0x80, 0xF1, 0x2D, 0xF8, 0x81, 0xF1, 0x2E, 0xF8, 0x83, 0xF1, 0xC0, 0x67, 0xB0, 0x84, 0x2B, 0xFA, + 0xB9, 0xF1, 0x19, 0xF8, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, + 0x00, 0x60, 0xA4, 0x64, 0x2A, 0xFA, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x1C, 0x60, 0xAA, 0x64, + 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x10, 0x60, 0x36, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x5A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x03, 0x60, 0x0E, 0x64, + 0x08, 0x60, 0x1C, 0xFB, 0xED, 0x60, 0xB8, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0D, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x1C, 0x60, 0xAA, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0xEA, 0x60, 0x1F, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x0A, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xCA, 0x01, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, + 0x14, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x08, 0x60, 0x2D, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, + 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x91, 0x01, 0x00, 0x60, 0x12, 0x64, 0xA0, 0x80, + 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xB1, 0x01, 0x08, 0x60, 0x1B, 0xF1, 0x02, 0x60, + 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xB2, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x10, 0x67, 0x82, 0xFB, + 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x5A, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x64, 0xF5, 0xB9, 0xF1, 0x19, 0xF8, 0x7F, 0xF1, 0x2C, 0xF8, 0x32, 0xF8, 0x80, 0xF1, 0x2D, 0xF8, + 0x33, 0xF8, 0x81, 0xF1, 0x2E, 0xF8, 0x34, 0xF8, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, + 0xEC, 0xF1, 0x31, 0xF8, 0x11, 0x60, 0x48, 0x64, 0x2A, 0xFA, 0x00, 0x64, 0x2B, 0xFA, 0x23, 0xFA, + 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0x95, 0xF3, 0xC1, 0xFE, 0xFE, 0xB4, 0x95, 0xFB, 0x00, 0x60, 0x03, 0x64, + 0x08, 0x60, 0x1C, 0xFB, 0xEE, 0x60, 0x30, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x33, 0x01, 0x64, 0xF5, 0x23, 0xF2, 0x96, 0xF3, 0x04, 0x18, 0xCC, 0x84, 0x96, 0xFB, + 0x01, 0x03, 0x2B, 0x01, 0xEA, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0xAB, 0xF3, 0x82, 0xF1, + 0x02, 0xA8, 0x2A, 0xF2, 0x03, 0x02, 0xB0, 0x84, 0x2A, 0xFA, 0x07, 0x00, 0x08, 0x60, 0x1B, 0xF1, + 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x25, 0x60, 0xC8, 0x64, 0x13, 0x60, + 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, + 0x12, 0x60, 0xED, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0xDF, 0x02, 0xCA, 0x60, 0xD4, 0x78, + 0xFF, 0xFF, 0x10, 0x60, 0x48, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x06, 0x64, 0x08, 0x60, + 0x25, 0xFB, 0xEE, 0x60, 0x77, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x60, + 0x18, 0x64, 0x08, 0x60, 0x25, 0xFB, 0xEE, 0x60, 0x77, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0xDB, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, 0x03, 0x36, 0x1B, 0x00, + 0x0E, 0xF0, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0xEF, 0xB4, 0x60, 0x44, 0x64, 0x40, 0x04, 0x27, + 0x07, 0x00, 0xA2, 0xDB, 0x13, 0x64, 0xCB, 0xFB, 0x01, 0x60, 0x67, 0x64, 0x37, 0xFB, 0x0B, 0x00, + 0x10, 0xBC, 0xA2, 0xDB, 0x08, 0x64, 0xCB, 0xFB, 0xA1, 0xF3, 0x01, 0x60, 0x67, 0x7C, 0x60, 0x40, + 0x01, 0x27, 0x5B, 0x7C, 0x37, 0xF9, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xF4, 0xA3, + 0x00, 0x60, 0x1D, 0x61, 0x00, 0x60, 0x2A, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, + 0x58, 0x4E, 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x01, 0x02, 0x3B, 0x00, 0x02, 0x60, + 0x01, 0x63, 0xA3, 0xD1, 0xDB, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, 0x03, 0x36, 0x1F, 0x00, 0x19, 0x60, + 0x45, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x09, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, + 0xFD, 0xB4, 0x60, 0x44, 0x64, 0x40, 0x02, 0x27, 0x02, 0xBC, 0xA2, 0xDB, 0x19, 0x60, 0x45, 0xF3, + 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x26, 0x1C, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0xFB, 0xB4, + 0x60, 0x44, 0x64, 0x40, 0x04, 0x27, 0x04, 0xBC, 0xA2, 0xDB, 0x12, 0x00, 0x64, 0x40, 0x02, 0x2B, + 0x06, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0x60, 0x44, 0xA2, 0xDB, 0x64, 0x40, + 0x04, 0x2B, 0x06, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0x04, 0xBC, 0x60, 0x44, 0xA2, 0xDB, + 0x2F, 0x58, 0xFF, 0xFF, 0x0E, 0xF0, 0xDB, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, 0x03, 0x36, 0x18, 0x00, + 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0x60, 0x44, 0xFB, 0xB4, 0x60, 0x44, 0x64, 0x40, + 0x20, 0x2A, 0x0A, 0x00, 0x60, 0x43, 0x19, 0x60, 0x45, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x26, + 0x02, 0x00, 0x63, 0x44, 0x02, 0x00, 0x63, 0x44, 0x04, 0xBC, 0x19, 0x60, 0x7B, 0xFB, 0x09, 0x00, + 0x64, 0x40, 0x20, 0x26, 0x06, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0x04, 0xBC, 0x60, 0x44, + 0xA2, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0xB0, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x25, 0x78, + 0xFF, 0xFF, 0x66, 0x44, 0x5C, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x80, 0x64, 0x2A, 0xFA, 0xC9, 0xF1, + 0x19, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x00, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0xA6, 0xF1, 0x07, 0xF8, + 0x67, 0x44, 0x2C, 0xFA, 0x2D, 0xFA, 0x2E, 0xFA, 0xF1, 0x60, 0x2C, 0x64, 0x08, 0x60, 0x31, 0xFB, + 0x2F, 0x58, 0xFF, 0xFF, 0x5C, 0xF5, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, + 0x31, 0xF8, 0x7F, 0xF1, 0x32, 0xF8, 0x80, 0xF1, 0x33, 0xF8, 0x81, 0xF1, 0x34, 0xF8, 0x16, 0x60, + 0xC2, 0xF1, 0x02, 0x64, 0x64, 0x40, 0xFE, 0x26, 0x10, 0xBC, 0x32, 0x40, 0x08, 0x26, 0x10, 0xBC, + 0x20, 0xBC, 0xFB, 0x60, 0xFF, 0x65, 0x60, 0x44, 0xA4, 0x84, 0x1B, 0x60, 0x09, 0xFB, 0x16, 0x60, + 0xC1, 0xF1, 0x33, 0x60, 0xBE, 0x64, 0x02, 0x18, 0x2D, 0x60, 0x32, 0x64, 0x1A, 0x60, 0xAD, 0xFB, + 0x1A, 0x60, 0xBD, 0xFB, 0x34, 0x60, 0x18, 0x61, 0x17, 0x60, 0x14, 0xF3, 0x35, 0x60, 0x36, 0x65, + 0xFE, 0xA4, 0xE0, 0x84, 0x06, 0x05, 0x67, 0x44, 0x1A, 0x60, 0xB5, 0xFB, 0x1A, 0x60, 0xC5, 0xFB, + 0x4B, 0x00, 0xE0, 0x84, 0xC4, 0x85, 0x1A, 0x60, 0x1F, 0xF3, 0xA5, 0xD1, 0xDA, 0x85, 0xA0, 0x83, + 0x1A, 0x60, 0x1B, 0xFD, 0xA5, 0xD1, 0x34, 0x60, 0x34, 0x62, 0xA0, 0x83, 0xA2, 0xDD, 0x67, 0x44, + 0x1A, 0x60, 0xB5, 0xFB, 0x1A, 0x60, 0xC5, 0xFB, 0x1A, 0x60, 0x2C, 0xF3, 0xFF, 0xFF, 0x21, 0x18, + 0x33, 0x60, 0xF4, 0x61, 0x0F, 0x60, 0x00, 0x7C, 0x00, 0x60, 0xAC, 0x65, 0xEF, 0x60, 0x58, 0x4D, + 0xC1, 0x78, 0xFF, 0xFF, 0x1A, 0x60, 0x2D, 0xF1, 0x59, 0xD9, 0x33, 0x60, 0xF2, 0x65, 0xD5, 0x84, + 0x30, 0x7F, 0xA5, 0xDB, 0x65, 0x44, 0x1A, 0x60, 0xB5, 0xFB, 0x1A, 0x60, 0xC5, 0xFB, 0x1A, 0x60, + 0x2C, 0xF3, 0xFF, 0xFF, 0xFE, 0xA4, 0xFF, 0xFF, 0x08, 0x24, 0x03, 0x00, 0xFF, 0x60, 0xFF, 0x64, + 0x13, 0x00, 0x34, 0x60, 0x18, 0x61, 0x50, 0x60, 0x00, 0x7C, 0x00, 0x60, 0xF2, 0x65, 0xEF, 0x60, + 0x58, 0x4D, 0xC1, 0x78, 0xFF, 0xFF, 0x1A, 0x60, 0x1D, 0xF1, 0x59, 0xD9, 0x34, 0x60, 0x12, 0x65, + 0xD5, 0x84, 0xDD, 0x7F, 0xA5, 0xDB, 0x65, 0x44, 0x1A, 0x60, 0xB2, 0xFB, 0x1A, 0x60, 0xC2, 0xFB, + 0x79, 0x00, 0x1A, 0x60, 0x1E, 0xF3, 0x34, 0x60, 0x34, 0x62, 0xFD, 0xA0, 0xA2, 0xD3, 0xEE, 0x03, + 0x60, 0x40, 0x02, 0x2A, 0x02, 0x00, 0x01, 0x63, 0x0B, 0x00, 0x04, 0x2A, 0x02, 0x00, 0x02, 0x63, + 0x07, 0x00, 0x10, 0x2A, 0x02, 0x00, 0x04, 0x63, 0x03, 0x00, 0x20, 0x2A, 0x01, 0x00, 0x05, 0x63, + 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x1A, 0x60, 0x1E, 0xF3, 0x1A, 0x60, 0x1B, 0xF3, + 0xFE, 0xA0, 0x40, 0x4C, 0xD3, 0x03, 0x00, 0x60, 0x00, 0x63, 0x59, 0xDD, 0x41, 0x4A, 0x2C, 0x40, + 0x01, 0x2A, 0x05, 0x00, 0x00, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, + 0x02, 0x2A, 0x03, 0x00, 0x01, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x04, 0x2A, 0x05, 0x00, + 0x02, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x10, 0x2A, 0x05, 0x00, + 0x04, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x20, 0x2A, 0x05, 0x00, + 0x05, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2A, 0x44, 0x51, 0x93, 0xEB, 0x83, + 0xEB, 0x83, 0xA0, 0xDD, 0x1A, 0x60, 0x1E, 0xF3, 0x1A, 0x60, 0x1C, 0xF3, 0xFF, 0xA0, 0x40, 0x4C, + 0x9D, 0x03, 0x59, 0xDF, 0x41, 0x4A, 0x2C, 0x40, 0x01, 0x2A, 0x05, 0x00, 0x00, 0x63, 0x63, 0x47, + 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x02, 0x2A, 0x05, 0x00, 0x01, 0x63, 0x63, 0x47, + 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x04, 0x2A, 0x05, 0x00, 0x02, 0x63, 0x63, 0x47, + 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2A, 0x44, 0x51, 0x93, 0xEB, 0x83, 0xEB, 0x83, 0xA0, 0xDD, + 0x2D, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0x04, 0x64, 0x08, 0x60, 0x0A, 0xFB, 0xF0, 0x60, 0x44, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x12, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0x7D, 0xF1, 0x35, 0x60, 0xCC, 0x64, 0x64, 0x40, 0x01, 0x2B, 0x01, 0x00, 0x67, 0x44, 0x1A, 0x60, + 0xAF, 0xFB, 0x1A, 0x60, 0xBF, 0xFB, 0x1A, 0x60, 0xE7, 0xF9, 0x35, 0x60, 0x62, 0x65, 0xF1, 0x60, + 0x58, 0x4D, 0x74, 0x78, 0xFF, 0xFF, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2B, 0x05, 0x00, + 0xFF, 0x60, 0xFF, 0x63, 0x1A, 0x60, 0xB3, 0xFD, 0x08, 0x00, 0x36, 0x60, 0x04, 0x63, 0x1A, 0x60, + 0xB3, 0xFD, 0xF1, 0x60, 0x58, 0x4D, 0x8C, 0x78, 0xFF, 0xFF, 0x5C, 0xF5, 0x00, 0xF4, 0x7E, 0xF1, + 0x06, 0xF8, 0x1B, 0x60, 0x09, 0xF3, 0x19, 0x60, 0x7B, 0xF1, 0xFB, 0x60, 0xFF, 0x65, 0x60, 0x44, + 0xA4, 0x84, 0x60, 0x47, 0x64, 0x40, 0x10, 0x26, 0x04, 0xBC, 0x60, 0x47, 0x07, 0xFA, 0x35, 0x60, + 0x5A, 0x64, 0x40, 0x48, 0x10, 0x61, 0x00, 0x60, 0x00, 0x64, 0xF1, 0x60, 0x58, 0x4D, 0x34, 0x78, + 0xFF, 0xFF, 0x5C, 0xF5, 0x3F, 0xFC, 0xDB, 0xFE, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, + 0x66, 0x44, 0x5A, 0xDB, 0x04, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0xDB, 0xF3, 0x9B, 0xFE, 0xFD, 0xA0, 0x25, 0x04, 0x24, 0x02, 0x04, 0x64, 0x03, 0xFA, + 0x00, 0xF4, 0x09, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x3A, 0x1C, 0x00, 0x60, 0x43, 0x00, 0x36, + 0x1C, 0x00, 0xE0, 0xA0, 0xDA, 0x85, 0x16, 0x07, 0x33, 0x60, 0xBE, 0x61, 0xA1, 0xD1, 0xFF, 0xFF, + 0xD3, 0x80, 0xCB, 0x83, 0x0F, 0x02, 0x07, 0x0E, 0x59, 0xD3, 0xA5, 0xD0, 0xDA, 0x85, 0xD0, 0x80, + 0xFF, 0xFF, 0x08, 0x02, 0xF9, 0x1F, 0x12, 0x1E, 0xA5, 0xD0, 0x59, 0xD3, 0xFF, 0xFF, 0x90, 0x80, + 0xFF, 0x22, 0x0C, 0x00, 0xF1, 0x60, 0x2A, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0xC1, 0xF3, 0xFF, 0xFF, + 0x60, 0x40, 0x01, 0x2A, 0x03, 0x00, 0x2D, 0x60, 0x32, 0x64, 0x02, 0x00, 0x33, 0x60, 0xBE, 0x64, + 0x1A, 0x60, 0xBD, 0xFB, 0x26, 0x46, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, + 0x2E, 0xFA, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0x7F, 0xF1, + 0x32, 0xF8, 0x80, 0xF1, 0x33, 0xF8, 0x81, 0xF1, 0x34, 0xF8, 0x00, 0x65, 0xFD, 0x60, 0x58, 0x4E, + 0xDD, 0x78, 0xFF, 0xFF, 0x61, 0x44, 0x19, 0x60, 0x3F, 0xFB, 0x50, 0x63, 0x2A, 0xFC, 0xC9, 0xF3, + 0x19, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0xA6, 0xF3, 0x07, 0xFA, 0x00, 0xF4, 0x7E, 0xF1, 0x06, 0xF8, + 0x1B, 0x60, 0x09, 0xF3, 0x19, 0x60, 0x7B, 0xF1, 0xFB, 0x60, 0xFF, 0xB7, 0x64, 0x40, 0x10, 0x26, + 0x04, 0xBC, 0x60, 0x47, 0x07, 0xFA, 0x35, 0x60, 0x82, 0x65, 0xF1, 0x60, 0x58, 0x4D, 0x74, 0x78, + 0xFF, 0xFF, 0x7D, 0xF3, 0x36, 0x60, 0x04, 0x63, 0x60, 0x40, 0x01, 0x27, 0x67, 0x43, 0x1A, 0x60, + 0xC3, 0xFD, 0x35, 0x60, 0x7A, 0x64, 0x40, 0x48, 0x10, 0x61, 0x00, 0x60, 0x00, 0x64, 0xF1, 0x60, + 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xFC, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, + 0x0D, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, + 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x08, 0x60, 0x09, 0xFB, 0x5A, 0xDB, + 0x00, 0x64, 0x92, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x1B, 0x60, 0x0A, 0xFB, 0xCD, 0x81, 0x28, 0xD3, + 0x5A, 0x88, 0xDC, 0x83, 0x31, 0x18, 0xFB, 0x03, 0x61, 0x40, 0x7F, 0x3A, 0x06, 0x00, 0x1B, 0x60, + 0x0A, 0xF3, 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x00, 0xF4, 0x60, 0xFE, 0xA3, 0xD1, 0x5D, 0xD8, + 0x61, 0x40, 0x7F, 0x3A, 0x08, 0x00, 0x20, 0xFE, 0x1B, 0x60, 0x0A, 0xF3, 0x03, 0x61, 0x7C, 0xA4, + 0xA2, 0xDB, 0x00, 0xF4, 0x60, 0xFE, 0xBF, 0xD3, 0x5D, 0xDA, 0xFF, 0xB4, 0x00, 0x7F, 0x12, 0x03, + 0xDF, 0x83, 0x61, 0x40, 0x7F, 0x3A, 0x0A, 0x00, 0x20, 0xFE, 0x60, 0x45, 0x1B, 0x60, 0x0A, 0xF3, + 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x65, 0x44, 0x00, 0xF4, 0x60, 0xFE, 0xBD, 0xD1, 0xCC, 0x84, + 0x5D, 0xD8, 0xEF, 0x02, 0x20, 0xFE, 0xCB, 0x01, 0x1B, 0x60, 0x0A, 0xF1, 0xFD, 0xA1, 0xFF, 0xB1, + 0xC1, 0x83, 0xA2, 0xDD, 0x2D, 0x58, 0xFF, 0xFF, 0x67, 0x5C, 0x1C, 0x60, 0xE6, 0x61, 0xA1, 0xD3, + 0xA5, 0xD9, 0x10, 0x18, 0x60, 0x43, 0x35, 0x60, 0xD4, 0x64, 0xA5, 0xDB, 0x60, 0xFE, 0xA0, 0xDD, + 0x20, 0xFE, 0xDC, 0x84, 0xCF, 0x83, 0xE3, 0x83, 0x59, 0xD1, 0xDC, 0x84, 0x60, 0xFE, 0xA0, 0xD9, + 0x20, 0xFE, 0xFA, 0x1F, 0x2D, 0x58, 0xFF, 0xFF, 0x19, 0x60, 0x7B, 0xF3, 0x36, 0x60, 0x06, 0x62, + 0x07, 0xB4, 0x60, 0xFE, 0xA2, 0xDB, 0x20, 0xFE, 0x2D, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, + 0x40, 0x26, 0x27, 0x00, 0x45, 0x48, 0x00, 0x60, 0x10, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, + 0xFF, 0xFF, 0x1F, 0x03, 0xF2, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x00, 0x60, 0x48, 0x61, 0x28, 0x44, + 0x59, 0xDA, 0x03, 0x64, 0x38, 0x43, 0xBD, 0xD1, 0xCC, 0x84, 0x59, 0xD8, 0xFC, 0x02, 0x39, 0x44, + 0x59, 0xDA, 0x16, 0x60, 0xC3, 0xF3, 0x59, 0xDA, 0x07, 0x64, 0x23, 0xFA, 0x26, 0x60, 0x0A, 0x64, + 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, + 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, 0x40, 0x26, 0x1B, 0x00, 0x45, 0x48, + 0x00, 0x60, 0x06, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, 0xFF, 0xFF, 0x13, 0x03, 0x02, 0x64, + 0x23, 0xFA, 0xF2, 0x60, 0x00, 0x64, 0x5A, 0xDA, 0x28, 0x44, 0x5A, 0xDA, 0xFF, 0xFF, 0x26, 0x60, + 0x0A, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, + 0xD0, 0x80, 0x03, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0xDD, 0x98, 0xFF, 0xFF, 0xB5, 0xF1, + 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0C, 0x03, 0x08, 0x05, 0xDC, 0x80, 0xD0, 0x80, + 0x05, 0x03, 0xA2, 0xDB, 0x02, 0x24, 0xC6, 0xFE, 0xDD, 0x98, 0xFF, 0xFF, 0xFF, 0x60, 0xFE, 0x64, + 0xA2, 0xDB, 0xDD, 0x98, 0xFF, 0xFF, 0xA2, 0xFF, 0x32, 0x40, 0x40, 0x26, 0x3C, 0x00, 0x9B, 0xF3, + 0x67, 0x43, 0xDC, 0x84, 0xCC, 0x84, 0x37, 0x03, 0x60, 0x46, 0x0A, 0x02, 0x9B, 0xFD, 0x00, 0x60, + 0x46, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x9B, 0xFB, 0x2C, 0x03, + 0x46, 0x4B, 0x2C, 0x60, 0xCA, 0x61, 0x18, 0x64, 0x23, 0xFA, 0xF1, 0x60, 0x00, 0x64, 0x24, 0xFA, + 0x4A, 0x65, 0xA2, 0xFF, 0x2C, 0x63, 0x59, 0xD1, 0xA2, 0xDF, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, + 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF7, 0x1F, 0x12, 0x63, 0x59, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, + 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x26, 0x60, 0x0A, 0x64, 0x13, 0x60, + 0x0D, 0xFB, 0x2B, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, + 0xA6, 0xFE, 0x00, 0x64, 0x9B, 0xFB, 0xA3, 0xFF, 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0xA6, 0xFE, + 0xBA, 0x05, 0xA7, 0xFE, 0x11, 0x05, 0xA5, 0xFE, 0x03, 0x04, 0xF2, 0x60, 0xD8, 0x78, 0xFF, 0xFF, + 0xA4, 0xFE, 0xF2, 0x04, 0x08, 0x60, 0x0F, 0xF1, 0x00, 0x60, 0x80, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0x36, 0x45, 0x20, 0x60, 0xA8, 0x64, 0x44, 0xD7, + 0xFF, 0xFF, 0xFF, 0xFF, 0x9D, 0xF3, 0xFF, 0xFF, 0x01, 0xB0, 0x00, 0x64, 0x2F, 0x03, 0x9D, 0xFB, + 0x31, 0x44, 0xE8, 0xB4, 0x40, 0x51, 0x6A, 0x44, 0xFF, 0xFF, 0x80, 0x26, 0xFC, 0x01, 0x61, 0xFF, + 0x62, 0xFF, 0x08, 0x60, 0x30, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x40, 0x60, 0x58, 0x4E, 0x7D, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0xC4, 0x64, 0x0F, 0x60, 0xE1, 0xFB, + 0x4A, 0xDF, 0x01, 0x60, 0xFE, 0x63, 0x1D, 0x60, 0xBE, 0x61, 0x00, 0x64, 0x59, 0xDB, 0xFE, 0x1F, + 0x0E, 0x60, 0xDD, 0xF3, 0xFF, 0xFF, 0x04, 0xB0, 0xFF, 0xFF, 0x05, 0x03, 0x02, 0x65, 0xF1, 0x60, + 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0xF2, 0x60, 0xD8, 0x78, + 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x37, 0x00, 0x2D, 0x60, 0xAA, 0x63, 0xBD, 0xD3, 0xBD, 0xD1, 0xBD, 0xD1, 0xB0, 0x84, 0xB0, 0x84, + 0xFF, 0xFF, 0x07, 0x02, 0x8A, 0xFB, 0x31, 0x44, 0xFE, 0xB4, 0x40, 0x51, 0x0D, 0x64, 0x05, 0xFB, + 0x27, 0x00, 0x28, 0xF3, 0x9D, 0xF1, 0x60, 0x47, 0x64, 0x41, 0x07, 0xB1, 0x07, 0xB4, 0x50, 0xFB, + 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0xA1, 0x80, 0xB1, 0x83, 0x18, 0x02, + 0x9D, 0xFD, 0x16, 0x60, 0xCF, 0xF3, 0xE4, 0xFB, 0x7D, 0xFB, 0x13, 0x60, 0x02, 0xF3, 0xFF, 0xFF, + 0x00, 0xA8, 0x60, 0x46, 0x46, 0x5E, 0x31, 0x44, 0x01, 0xBC, 0x40, 0x51, 0xED, 0xE2, 0x0F, 0x4E, + 0x1D, 0x60, 0x58, 0x4F, 0x9F, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, + 0xD7, 0xFE, 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0xF2, 0x60, 0xE4, 0x64, 0x08, 0x60, 0x3B, 0xFB, + 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x08, 0x60, 0x27, 0xFB, 0x5A, 0xDB, + 0x10, 0x60, 0x4E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x28, 0xF3, + 0xFF, 0xFF, 0x01, 0xB0, 0xFF, 0xFF, 0x1D, 0x03, 0x20, 0x40, 0x06, 0x23, 0x10, 0x00, 0x08, 0x60, + 0x27, 0xF1, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, + 0x28, 0xFB, 0xF2, 0x60, 0xF4, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1D, 0x60, + 0xA9, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x27, 0xF1, 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0xC6, 0x01, 0x08, 0x60, 0x27, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, + 0xCF, 0xFE, 0xDB, 0xF3, 0x01, 0x63, 0xFD, 0xA0, 0x08, 0x60, 0x77, 0xFD, 0x07, 0x02, 0x08, 0x60, + 0x30, 0xF1, 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xB1, 0x01, 0x0E, 0x57, + 0x32, 0x40, 0x40, 0x26, 0x1B, 0x00, 0x45, 0x48, 0x00, 0x60, 0x06, 0x61, 0xB6, 0x60, 0x58, 0x4D, + 0x22, 0x78, 0xFF, 0xFF, 0x13, 0x03, 0x02, 0x64, 0x23, 0xFA, 0xF2, 0x60, 0x04, 0x64, 0x5A, 0xDA, + 0x28, 0x44, 0x5A, 0xDA, 0xFF, 0xFF, 0x26, 0x60, 0x0A, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, + 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, + 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x88, 0x01, + 0x12, 0x60, 0xF6, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x0E, 0xF2, 0x4B, 0x03, 0x60, 0x40, + 0xF0, 0x37, 0x38, 0x00, 0xFF, 0x37, 0x2D, 0x00, 0xFD, 0x37, 0x25, 0x00, 0xF8, 0x37, 0x0A, 0x00, + 0x60, 0x47, 0xFF, 0xB5, 0x10, 0x60, 0x12, 0x62, 0x46, 0xD1, 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, + 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xDC, 0x01, 0x06, 0xB4, 0xFD, 0x7F, 0x0E, 0xFA, 0x25, 0x60, + 0xF2, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, + 0x2B, 0xFF, 0xF9, 0xFE, 0xCD, 0x01, 0x23, 0xF0, 0x60, 0x40, 0x04, 0x26, 0xED, 0x1B, 0x02, 0x26, + 0xEB, 0x18, 0xA2, 0xFF, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xAD, 0xF3, 0x02, 0x02, + 0xCC, 0x84, 0xAD, 0xFB, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, + 0xFF, 0xFF, 0xB6, 0x01, 0xAC, 0xFE, 0x09, 0x05, 0xAD, 0xFE, 0x0F, 0x05, 0xAE, 0xFE, 0xB0, 0x05, + 0xAF, 0xFE, 0x37, 0x05, 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x08, 0xF1, 0x20, 0x60, + 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xF5, 0x01, 0x10, 0x60, 0x7A, 0x65, 0x0D, 0x61, + 0x07, 0x00, 0xA2, 0xDD, 0x58, 0x4F, 0x64, 0x58, 0xFF, 0xFF, 0x00, 0xB9, 0xFF, 0xFF, 0x08, 0x03, + 0x00, 0x63, 0xA5, 0xD1, 0x5A, 0xD3, 0xDA, 0x85, 0x00, 0xA8, 0xCD, 0x81, 0xF2, 0x02, 0xF8, 0x02, + 0xE1, 0x01, 0x10, 0x60, 0x0E, 0x62, 0x10, 0x60, 0x58, 0x65, 0xF3, 0x60, 0xD7, 0x63, 0x5A, 0xDF, + 0xD6, 0x80, 0xFF, 0xFF, 0x04, 0x03, 0x5A, 0xDF, 0x5A, 0xDF, 0x5A, 0xDD, 0xF9, 0x01, 0x10, 0x60, + 0x78, 0x65, 0x5A, 0xDF, 0xD6, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x5A, 0xDD, 0xFB, 0x01, 0x2F, 0x58, + 0xFF, 0xFF, 0x10, 0x60, 0x12, 0x64, 0x40, 0x41, 0x10, 0x60, 0x10, 0x63, 0xA3, 0xD1, 0x00, 0x64, + 0xD0, 0x80, 0x0C, 0x61, 0x08, 0x03, 0xBD, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0xB0, 0x84, 0xCD, 0x81, + 0xA3, 0xDB, 0x06, 0xA3, 0xF9, 0x02, 0x10, 0x60, 0x60, 0x63, 0xA3, 0xD1, 0x00, 0x64, 0xD0, 0x80, + 0x0D, 0x61, 0x19, 0x03, 0xBD, 0xDB, 0x64, 0x44, 0xFE, 0xA3, 0x02, 0xA3, 0xCD, 0x81, 0xE8, 0x84, + 0xE3, 0x03, 0x02, 0x05, 0xE1, 0x03, 0xF9, 0x01, 0x97, 0xFB, 0x99, 0xFD, 0x61, 0x5C, 0xA3, 0xD3, + 0x98, 0xF9, 0x03, 0x18, 0x58, 0x4F, 0x60, 0x58, 0xFF, 0xFF, 0x99, 0xF3, 0x98, 0xF1, 0x60, 0x43, + 0x97, 0xF3, 0x64, 0x41, 0xEA, 0x01, 0x21, 0x43, 0x10, 0x60, 0x5A, 0x65, 0xD7, 0x80, 0xBD, 0xD1, + 0xBD, 0xD3, 0x03, 0x02, 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0xA0, 0x84, 0xBD, 0xD1, 0x43, 0x41, + 0xF5, 0x03, 0xF3, 0x60, 0xDC, 0x64, 0x64, 0x58, 0x40, 0x4F, 0x2A, 0xF0, 0x83, 0x60, 0xFF, 0x65, + 0x64, 0x47, 0x03, 0x2B, 0x01, 0x00, 0x14, 0x00, 0x03, 0x26, 0x03, 0xAC, 0x60, 0x47, 0xA4, 0x84, + 0x2A, 0xFA, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0x64, 0x41, + 0xEA, 0xF3, 0x2F, 0xFA, 0x60, 0x43, 0xEB, 0xF3, 0x30, 0xFA, 0xEC, 0xF1, 0x31, 0xF8, 0x19, 0x00, + 0x60, 0x47, 0xA4, 0x84, 0x2A, 0xFA, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, + 0x2E, 0xFA, 0x36, 0xF2, 0x32, 0xFA, 0x37, 0xF2, 0x33, 0xFA, 0x38, 0xF2, 0x34, 0xFA, 0xEA, 0xF3, + 0x2F, 0xFA, 0x36, 0xFA, 0xEB, 0xF3, 0x30, 0xFA, 0x37, 0xFA, 0xEC, 0xF3, 0x31, 0xFA, 0x38, 0xFA, + 0x64, 0x41, 0x1C, 0xF2, 0x13, 0xFA, 0x00, 0xF4, 0x0D, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, + 0x17, 0x00, 0x81, 0x67, 0xA2, 0xDA, 0xF4, 0x60, 0x58, 0x4E, 0xCF, 0x78, 0xFF, 0xFF, 0x26, 0x46, + 0x3F, 0xFC, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, + 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, + 0x26, 0x46, 0x3F, 0xF0, 0x42, 0x64, 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x04, 0x3F, 0xFA, 0x07, 0xF2, + 0xA6, 0xF1, 0x01, 0x1B, 0x07, 0xF8, 0x1C, 0xF2, 0x13, 0xFA, 0x26, 0xF2, 0x27, 0xF0, 0x60, 0x47, + 0x00, 0xF4, 0x1F, 0xFA, 0x64, 0x47, 0x20, 0xFA, 0x61, 0x44, 0x21, 0xFA, 0x01, 0x67, 0x0D, 0xFA, + 0x10, 0x61, 0x2D, 0x60, 0x5E, 0x64, 0x1E, 0x63, 0x58, 0xD1, 0xCD, 0x81, 0xBD, 0xD8, 0xFC, 0x02, + 0xB8, 0xF1, 0xD6, 0xF1, 0x64, 0x5E, 0x64, 0x5F, 0x44, 0x63, 0xBD, 0xDA, 0x16, 0x60, 0xAC, 0xF3, + 0xFF, 0xFF, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x4A, 0xD3, 0x60, 0x45, 0x60, 0x40, 0x01, 0x36, + 0x03, 0x64, 0x02, 0x36, 0x01, 0x64, 0xB4, 0x84, 0x06, 0xA2, 0xA2, 0xD1, 0xBD, 0xDA, 0x64, 0x47, + 0xBD, 0xDA, 0xD3, 0xF3, 0xD4, 0xF1, 0x60, 0x47, 0xBD, 0xDA, 0x64, 0x47, 0xE2, 0xF1, 0xBD, 0xDA, + 0x64, 0x44, 0xBD, 0xDA, 0x26, 0x46, 0x00, 0x64, 0x23, 0xF0, 0x3B, 0xF0, 0x64, 0x40, 0x10, 0x2A, + 0x06, 0x00, 0xC0, 0x67, 0xA0, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x10, 0xBC, 0x3E, 0xFA, + 0x25, 0x60, 0xDA, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, + 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0xB1, 0xF3, + 0x1F, 0xFA, 0x32, 0x47, 0x07, 0xFA, 0x24, 0x7E, 0x01, 0x7F, 0x08, 0xFA, 0xD6, 0xF1, 0x09, 0xF8, + 0x01, 0x60, 0x01, 0x64, 0x0A, 0xFA, 0x01, 0x64, 0x0B, 0xFA, 0x18, 0x64, 0x13, 0x60, 0x0D, 0xFB, + 0x66, 0x44, 0x5A, 0xDB, 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x52, 0x63, 0x2E, 0x58, + 0xFF, 0xFF, 0x00, 0x60, 0x2A, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x25, 0x78, 0xFF, 0xFF, 0x66, 0x44, + 0x5D, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x67, 0x44, 0x2C, 0xFA, 0x2D, 0xFA, 0x2E, 0xFA, 0x32, 0xFA, + 0x33, 0xFA, 0x34, 0xFA, 0x12, 0x60, 0x80, 0x64, 0xA6, 0xF1, 0x0E, 0xFA, 0x07, 0xF8, 0x00, 0x64, + 0x3E, 0xFA, 0x0E, 0x60, 0x3D, 0xFB, 0x06, 0xA2, 0x10, 0x60, 0x80, 0x64, 0xA2, 0xDB, 0x04, 0x64, + 0x5A, 0xDB, 0x06, 0x64, 0x5A, 0xDB, 0xF8, 0x60, 0xCF, 0x64, 0x08, 0x60, 0x3F, 0xFB, 0x00, 0x64, + 0x0E, 0x60, 0x43, 0xFB, 0x06, 0xA2, 0x10, 0x60, 0x84, 0x64, 0xA2, 0xDB, 0x08, 0x64, 0x5A, 0xDB, + 0x06, 0x64, 0x5A, 0xDB, 0xF8, 0x60, 0xD8, 0x64, 0x08, 0x60, 0x41, 0xFB, 0xF8, 0x60, 0xB4, 0x64, + 0x08, 0x60, 0x34, 0xFB, 0x00, 0x60, 0x30, 0x64, 0x08, 0x60, 0x13, 0xFB, 0xF5, 0x60, 0x31, 0x64, + 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0xF7, 0x60, 0x6C, 0x78, + 0xFF, 0xFF, 0x5D, 0xF5, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, + 0xC9, 0xF1, 0x19, 0xF8, 0x00, 0x63, 0x88, 0xFD, 0x1B, 0x60, 0xB2, 0x63, 0x86, 0xFD, 0x87, 0xFD, + 0x20, 0x40, 0x10, 0x2B, 0x00, 0x00, 0x5D, 0xF5, 0x40, 0x64, 0x2A, 0xFA, 0x7D, 0xF3, 0x7C, 0xFB, + 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x03, 0x00, 0xF6, 0x60, 0xC6, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x3D, 0xF3, 0xFD, 0x60, + 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x3F, 0xFB, 0x19, 0x60, 0x39, 0xF3, 0x3F, 0x40, + 0x01, 0x27, 0x08, 0x00, 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, + 0xFF, 0xFF, 0x05, 0x00, 0x0F, 0xB4, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, 0x5D, 0xF5, + 0x35, 0x60, 0x70, 0x64, 0x00, 0xF4, 0x40, 0x48, 0x2F, 0x60, 0x24, 0x64, 0x20, 0x40, 0x10, 0x27, + 0x02, 0x00, 0x2F, 0x60, 0x02, 0x64, 0x28, 0xDB, 0x04, 0x61, 0x00, 0x60, 0x00, 0x64, 0xF1, 0x60, + 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x5D, 0xF5, 0x3F, 0xFC, 0x01, 0x64, 0x54, 0xF1, 0x10, 0x60, + 0x12, 0xFB, 0x7D, 0xFB, 0xA4, 0xD3, 0x04, 0x65, 0x53, 0xF3, 0x01, 0x18, 0x0C, 0x65, 0xF3, 0xB4, + 0xB4, 0x84, 0x53, 0xFB, 0x0D, 0x00, 0xF7, 0x60, 0x6C, 0x78, 0xFF, 0xFF, 0x53, 0xF1, 0x7D, 0xF3, + 0xFF, 0xFF, 0xF3, 0xA0, 0x04, 0xA4, 0x01, 0x04, 0xF1, 0xA4, 0x10, 0x36, 0xF4, 0x01, 0x7D, 0xFB, + 0x20, 0x40, 0x10, 0x2B, 0x10, 0x00, 0x7D, 0xF3, 0x32, 0x60, 0x80, 0x61, 0xA1, 0xD1, 0xCC, 0x84, + 0x01, 0x61, 0x08, 0x24, 0x03, 0x00, 0xE1, 0x81, 0xCC, 0x84, 0xFB, 0x01, 0xA1, 0x84, 0x53, 0xF1, + 0xE6, 0x03, 0x10, 0x60, 0x12, 0xFB, 0x7D, 0xF3, 0x10, 0x60, 0xF2, 0x61, 0xCC, 0x84, 0xFF, 0xFF, + 0x02, 0x03, 0x06, 0xA1, 0xFB, 0x01, 0xA1, 0xD3, 0x53, 0xF1, 0x01, 0xB0, 0x02, 0xB0, 0xD7, 0x03, + 0x64, 0x40, 0x01, 0x26, 0x05, 0x00, 0x20, 0x40, 0x10, 0x27, 0x02, 0x00, 0xD0, 0x03, 0x00, 0x00, + 0x9D, 0xFE, 0x3D, 0x05, 0xBA, 0xFE, 0x10, 0x60, 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, + 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x13, 0xFB, 0xF5, 0x60, 0xCB, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x7D, 0xF1, + 0x13, 0x60, 0x1A, 0xF9, 0x08, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, + 0x08, 0x60, 0x13, 0xFB, 0xF5, 0x60, 0xF0, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x1B, 0x60, 0xF3, 0xF1, 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x7D, 0xF1, 0x02, 0xB1, + 0x04, 0x65, 0x02, 0x02, 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x10, 0x60, + 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, + 0x13, 0xFB, 0xF5, 0x60, 0xC8, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7D, 0xF1, + 0x13, 0x60, 0x1A, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, + 0x08, 0x60, 0x13, 0xFB, 0xF6, 0x60, 0x28, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, + 0x10, 0x60, 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5D, 0xF5, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, + 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x64, + 0x51, 0xFB, 0x00, 0x60, 0x01, 0x64, 0x08, 0x60, 0x13, 0xFB, 0xF6, 0x60, 0x4C, 0x64, 0x5A, 0xDB, + 0xCF, 0xFE, 0xC1, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, + 0xC3, 0xF1, 0x0E, 0x60, 0x3F, 0xF9, 0x1C, 0x60, 0x7A, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xC4, 0xF1, 0x0E, 0x60, 0x45, 0xF9, 0x26, 0x60, 0x42, 0x62, + 0xA2, 0xD3, 0xFF, 0xFF, 0xFD, 0x1B, 0x1C, 0x60, 0x86, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, + 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x60, 0x08, 0x64, 0x08, 0x60, 0x13, 0xFB, 0xF6, 0x60, + 0x75, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x51, 0xF1, 0x10, 0x60, 0x24, 0x62, + 0x00, 0x64, 0xA2, 0xDB, 0x64, 0x40, 0xFF, 0x26, 0x0B, 0x00, 0x53, 0xF3, 0xFF, 0xFF, 0x80, 0xB0, + 0xFF, 0xFF, 0x03, 0x03, 0xF7, 0x60, 0x65, 0x78, 0xFF, 0xFF, 0xF5, 0x60, 0x96, 0x78, 0xFF, 0xFF, + 0x02, 0x0A, 0x00, 0x64, 0x51, 0xFB, 0xC5, 0xF1, 0x0E, 0x60, 0x45, 0xF9, 0x00, 0x60, 0x0C, 0x64, + 0x08, 0x60, 0x13, 0xFB, 0xF6, 0x60, 0xA0, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x1C, 0x60, 0x86, 0x64, + 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, + 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0B, 0x03, 0xA0, 0x84, + 0xA2, 0xDB, 0x1C, 0x60, 0x86, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, + 0x04, 0xFF, 0x13, 0x00, 0xFF, 0x60, 0xF7, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x51, 0xF3, 0xDE, 0x0A, + 0x00, 0xA0, 0x00, 0x64, 0x02, 0x03, 0x51, 0xFB, 0xD9, 0x01, 0x1C, 0x60, 0x7A, 0x64, 0x13, 0x60, + 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xB7, 0x01, 0x19, 0x60, 0x3E, 0xF3, + 0xFD, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x3F, 0xFB, 0x19, 0x60, 0x3A, 0xF3, + 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, 0x5D, 0xF5, + 0x35, 0x60, 0x70, 0x64, 0x00, 0xF4, 0x40, 0x48, 0x2F, 0x60, 0x24, 0x64, 0x20, 0x40, 0x10, 0x27, + 0x02, 0x00, 0x2F, 0x60, 0x02, 0x64, 0x28, 0xDB, 0x04, 0x61, 0x00, 0x60, 0x00, 0x64, 0xF1, 0x60, + 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x5D, 0xF5, 0x3F, 0xFC, 0x53, 0xF3, 0x20, 0x40, 0x10, 0x23, + 0x02, 0x00, 0x20, 0xBC, 0x04, 0x00, 0x60, 0x40, 0x01, 0x22, 0x40, 0xBC, 0x04, 0xBC, 0x80, 0xBC, + 0x53, 0xFB, 0x11, 0x60, 0x62, 0x64, 0x08, 0x60, 0x6C, 0xFB, 0x06, 0x64, 0x08, 0x60, 0x73, 0xFB, + 0x19, 0x60, 0x43, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, 0xA2, 0xDB, 0x53, 0xF3, 0x08, 0x60, 0x6C, 0xF1, + 0x60, 0x40, 0x20, 0x26, 0x03, 0x00, 0x01, 0x26, 0x32, 0x00, 0x45, 0x00, 0x08, 0x60, 0x73, 0xF3, + 0xFF, 0xFF, 0xDD, 0xA0, 0x01, 0xA4, 0x58, 0x03, 0xA2, 0xDB, 0x32, 0x60, 0x82, 0x61, 0xE0, 0xA0, + 0xF0, 0xA0, 0x05, 0x05, 0x01, 0x05, 0x05, 0x00, 0x02, 0xA1, 0xF0, 0xA4, 0x02, 0x00, 0x04, 0xA1, + 0xE0, 0xA4, 0xA1, 0xD1, 0x01, 0x61, 0xDC, 0x84, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, 0xE1, 0x81, + 0xFB, 0x01, 0xA1, 0x80, 0x10, 0x60, 0xE6, 0x64, 0x01, 0x02, 0xE0, 0x01, 0xA0, 0xD3, 0x11, 0x60, + 0x5A, 0x63, 0xFA, 0xA4, 0xCC, 0x84, 0x08, 0xA3, 0xFD, 0x02, 0xCF, 0xF1, 0xA3, 0xD3, 0x01, 0x18, + 0xD5, 0x18, 0xFE, 0xA3, 0xA3, 0xD3, 0x7D, 0xFB, 0xF5, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x12, 0x60, + 0x40, 0x65, 0x64, 0x41, 0xA1, 0xD3, 0xD5, 0x80, 0x00, 0xB8, 0x26, 0x07, 0x02, 0x02, 0x08, 0xA1, + 0xF9, 0x01, 0x61, 0x44, 0x08, 0x60, 0x6C, 0xFB, 0x01, 0x64, 0xA1, 0xDB, 0x49, 0xD3, 0x7D, 0xFB, + 0xF5, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x12, 0x60, 0x40, 0x65, 0x64, 0x41, 0xA1, 0xD3, 0xD5, 0x80, + 0x04, 0xB0, 0x12, 0x07, 0x02, 0x02, 0x08, 0xA1, 0xF9, 0x01, 0x61, 0x44, 0x08, 0x60, 0x6C, 0xFB, + 0x49, 0xD3, 0x7D, 0xFB, 0xF5, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x10, 0x60, 0xD8, 0x65, 0xA5, 0xD3, + 0xFF, 0xFF, 0x08, 0xA4, 0xA5, 0xDB, 0x99, 0x01, 0x1C, 0x60, 0x7A, 0x64, 0x13, 0x60, 0x22, 0xFB, + 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x53, 0xF3, 0xFF, 0xFF, 0xE3, 0xB4, 0x53, 0xFB, + 0x10, 0x60, 0x10, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xA2, 0xDB, 0x10, 0x60, 0x24, 0x62, 0x00, 0x64, + 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x13, 0xFB, 0xF7, 0x60, + 0x7D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7C, 0xF1, 0x7D, 0xF9, 0x13, 0x60, + 0x1A, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, + 0x13, 0xFB, 0xF7, 0x60, 0x9F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, + 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x53, 0xF3, + 0xFF, 0xFF, 0x80, 0xB0, 0xFF, 0xFF, 0x54, 0x02, 0x1C, 0x60, 0x32, 0x63, 0x1C, 0x61, 0xCD, 0x81, + 0xBD, 0xDF, 0xFD, 0x02, 0x14, 0x60, 0x32, 0x61, 0x88, 0xF3, 0x61, 0x43, 0xC4, 0xA5, 0x47, 0xD1, + 0x0F, 0x04, 0xBE, 0xD5, 0x1C, 0x60, 0x2E, 0x63, 0xC3, 0x83, 0xC3, 0x83, 0xC3, 0x83, 0x43, 0xD3, + 0xBE, 0xD1, 0xDC, 0x84, 0xA3, 0xDB, 0x66, 0x44, 0xC0, 0x84, 0xBE, 0xDB, 0x65, 0x44, 0xED, 0x01, + 0x1C, 0x60, 0x32, 0x63, 0x0E, 0x61, 0x41, 0x4B, 0xBD, 0xD3, 0xBD, 0xD1, 0x00, 0xBD, 0x64, 0x41, + 0x19, 0x03, 0x01, 0xA8, 0x61, 0x44, 0x02, 0xA8, 0x15, 0x03, 0x02, 0x02, 0xE9, 0x84, 0x12, 0x00, + 0x65, 0x47, 0x60, 0x45, 0x61, 0x44, 0x09, 0x61, 0xCD, 0x81, 0xE0, 0x84, 0xFF, 0x23, 0xFC, 0x01, + 0x02, 0x24, 0xC4, 0x84, 0x02, 0x28, 0xD4, 0x84, 0xCD, 0x81, 0x01, 0x0E, 0x01, 0xBC, 0x02, 0x03, + 0xE0, 0x84, 0xF6, 0x01, 0x00, 0x7F, 0x2B, 0x41, 0x4D, 0x8B, 0xBF, 0xDB, 0xDD, 0x02, 0x14, 0x60, + 0x32, 0x61, 0x88, 0xF3, 0x61, 0x43, 0xC4, 0xA5, 0x47, 0xD1, 0x0A, 0x04, 0xDA, 0x86, 0x1C, 0x60, + 0x30, 0x63, 0xC3, 0x83, 0xC3, 0x83, 0xC3, 0x83, 0x43, 0xD1, 0xA6, 0xD9, 0x65, 0x44, 0xF2, 0x01, + 0x53, 0xF3, 0x88, 0xF1, 0xF3, 0xB4, 0x53, 0xFB, 0x14, 0x60, 0x32, 0x63, 0xC3, 0x85, 0x45, 0x4A, + 0x1B, 0x60, 0xB2, 0x65, 0x87, 0xF3, 0x45, 0x4C, 0x40, 0x48, 0x2A, 0x45, 0xD7, 0x80, 0x02, 0x65, + 0x17, 0x05, 0x47, 0xD1, 0x02, 0x65, 0x47, 0xD3, 0x0A, 0x65, 0xD0, 0x81, 0x47, 0xD3, 0x01, 0x05, + 0x00, 0x61, 0xF2, 0xA3, 0x01, 0xB0, 0x61, 0x44, 0x05, 0x03, 0x2C, 0xDB, 0x5A, 0xDD, 0x5A, 0x8C, + 0x3C, 0xA3, 0xEB, 0x01, 0x28, 0x42, 0x4A, 0xDD, 0x4A, 0xDB, 0x42, 0x48, 0x3C, 0xA3, 0xE5, 0x01, + 0x28, 0x44, 0x86, 0xFB, 0x86, 0xF1, 0x1B, 0x60, 0xB2, 0x63, 0x44, 0x48, 0x28, 0x45, 0xD7, 0x80, + 0xA3, 0xD1, 0x15, 0x05, 0x04, 0x65, 0x46, 0xD3, 0x28, 0x45, 0xD6, 0x80, 0xD0, 0x80, 0x02, 0x04, + 0x04, 0xA3, 0xF5, 0x01, 0xF7, 0x06, 0x62, 0x46, 0xA2, 0xD9, 0xA3, 0xDB, 0x5B, 0xD3, 0x66, 0x42, + 0x5A, 0xD1, 0xA2, 0xDB, 0xA3, 0xD9, 0xFE, 0xA3, 0xA3, 0xD1, 0x66, 0x42, 0xEB, 0x01, 0x86, 0xF3, + 0x87, 0xF1, 0x60, 0x43, 0x44, 0x48, 0x28, 0x45, 0xD7, 0x80, 0xA3, 0xD1, 0x15, 0x05, 0x04, 0x65, + 0x46, 0xD3, 0x28, 0x45, 0xD6, 0x80, 0xD0, 0x80, 0x02, 0x04, 0x04, 0xA3, 0xF5, 0x01, 0xF7, 0x06, + 0x62, 0x46, 0xA2, 0xD9, 0xA3, 0xDB, 0x5B, 0xD3, 0x66, 0x42, 0x5A, 0xD1, 0xA2, 0xDB, 0xA3, 0xD9, + 0xFE, 0xA3, 0xA3, 0xD1, 0x66, 0x42, 0xEB, 0x01, 0x08, 0x60, 0x08, 0xF1, 0x10, 0x60, 0x00, 0x64, + 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x7D, 0xF1, 0x19, 0x60, 0x3D, 0xF3, 0x64, 0x40, 0x01, 0x27, + 0x27, 0x00, 0xFD, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x3F, 0xFB, 0x19, 0x60, + 0x39, 0xF3, 0x3F, 0x40, 0x01, 0x27, 0x16, 0x00, 0x0F, 0x60, 0xFF, 0x65, 0x60, 0x41, 0xDB, 0xF3, + 0xFF, 0xFF, 0x60, 0x40, 0x03, 0x36, 0x07, 0x00, 0x19, 0x60, 0x44, 0xF3, 0xFF, 0xFF, 0x60, 0x40, + 0x01, 0x2A, 0x01, 0x00, 0x0F, 0x61, 0x61, 0x44, 0xA4, 0x84, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, + 0xFF, 0xFF, 0x16, 0x00, 0x0F, 0xB4, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, 0x10, 0x00, + 0x5A, 0xD3, 0xFD, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x3F, 0xFB, 0x19, 0x60, + 0x3A, 0xF3, 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, + 0x00, 0x60, 0x30, 0x64, 0x08, 0x60, 0x13, 0xFB, 0xF5, 0x60, 0x31, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, + 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0x7A, 0x64, 0x13, 0x60, 0x22, 0xFB, + 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x53, 0xFB, 0x00, 0x64, 0x08, 0x60, + 0x12, 0xFB, 0x5A, 0xDB, 0xBE, 0xFE, 0x00, 0x60, 0x30, 0x64, 0x08, 0x60, 0x13, 0xFB, 0xF5, 0x60, + 0x31, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, + 0x12, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, + 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, + 0xFF, 0xFF, 0x20, 0x40, 0x90, 0x2B, 0x03, 0x00, 0xFB, 0x60, 0xFC, 0x78, 0xFF, 0xFF, 0x53, 0xF3, + 0x88, 0xF1, 0x04, 0xB0, 0x07, 0x60, 0x80, 0x64, 0xD0, 0x80, 0x20, 0x03, 0x1F, 0x06, 0x26, 0x46, + 0x88, 0xF1, 0x14, 0x60, 0x32, 0x63, 0xC3, 0x83, 0x7D, 0xF3, 0x26, 0xF0, 0xBD, 0xDB, 0x64, 0x44, + 0x00, 0x7F, 0xBD, 0xDB, 0x64, 0x47, 0x00, 0x7F, 0xBD, 0xDB, 0x32, 0xF0, 0xBD, 0xD9, 0x33, 0xF0, + 0xBD, 0xD9, 0x34, 0xF0, 0xBD, 0xD9, 0x00, 0xF4, 0x0D, 0xF0, 0xBD, 0xD9, 0x0E, 0xF0, 0xBD, 0xD9, + 0x0F, 0xF0, 0xA3, 0xDF, 0x64, 0x47, 0x60, 0x45, 0x00, 0x37, 0x03, 0x00, 0xFB, 0x60, 0xF7, 0x78, + 0xFF, 0xFF, 0xBD, 0xDB, 0xE0, 0xA0, 0x1F, 0x61, 0x00, 0xB8, 0xF8, 0x07, 0xF7, 0x03, 0x60, 0xFE, + 0x5D, 0xD0, 0xCC, 0x84, 0xBD, 0xD9, 0xFC, 0x02, 0x65, 0x40, 0x01, 0x26, 0xDF, 0x83, 0x5D, 0xD0, + 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x3A, 0x03, 0x00, 0x5D, 0xD0, 0xFF, 0xFF, 0xC1, 0x81, 0x5D, 0xD0, + 0xFF, 0xFF, 0x64, 0x40, 0x03, 0x36, 0x07, 0x00, 0x53, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2A, + 0xDD, 0x01, 0xCD, 0x81, 0x13, 0x00, 0x53, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2A, 0x04, 0x00, + 0x5D, 0xD0, 0xFF, 0xFF, 0xC1, 0x81, 0x0A, 0x00, 0x59, 0xD0, 0x7D, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, + 0x20, 0xFE, 0x08, 0x24, 0x03, 0x00, 0xFB, 0x60, 0xF7, 0x78, 0xFF, 0xFF, 0x7C, 0x44, 0x1A, 0x60, + 0x24, 0xFB, 0x1A, 0x60, 0x25, 0xFB, 0x1A, 0x60, 0x26, 0xFB, 0x1A, 0x60, 0x27, 0xFB, 0x1C, 0x60, + 0x08, 0xFB, 0x1C, 0x60, 0x04, 0xFB, 0x00, 0x64, 0x1C, 0x60, 0x04, 0xFB, 0x20, 0xFE, 0x37, 0x60, + 0xFE, 0x64, 0x40, 0x4A, 0xF9, 0x60, 0x58, 0x4D, 0xC3, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0x04, 0xF3, + 0xFF, 0xFF, 0x09, 0x18, 0xFF, 0xFF, 0x1C, 0x60, 0x06, 0xF3, 0x1C, 0x60, 0x07, 0xF5, 0x60, 0x41, + 0x00, 0x64, 0x1C, 0x60, 0x04, 0xFB, 0x20, 0xFE, 0x2A, 0xD1, 0xDA, 0x85, 0x64, 0x44, 0x01, 0xA0, + 0xFF, 0xFF, 0x01, 0x02, 0x79, 0x00, 0x45, 0x4A, 0x7C, 0x44, 0x60, 0xFE, 0xA1, 0xD2, 0xFF, 0xFF, + 0xD0, 0x80, 0x20, 0xFE, 0x01, 0x03, 0xEF, 0x01, 0x1C, 0x60, 0x04, 0xF3, 0xFF, 0xFF, 0x02, 0x18, + 0xDD, 0x81, 0x35, 0x00, 0x60, 0xFE, 0x5D, 0xD2, 0xFF, 0xFF, 0x60, 0x5C, 0x41, 0x94, 0x81, 0xA0, + 0x20, 0xFE, 0x2D, 0x04, 0x01, 0x64, 0x1C, 0x60, 0x04, 0xFB, 0xC1, 0x84, 0x84, 0xA4, 0x1C, 0x60, + 0x06, 0xFB, 0x00, 0xF2, 0x1C, 0x60, 0x07, 0xFB, 0x1C, 0x60, 0x05, 0xFD, 0x02, 0x60, 0x00, 0x63, + 0xCD, 0x85, 0x64, 0x44, 0xD8, 0x81, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, + 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, + 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x00, 0x60, 0x01, 0x61, 0x02, 0x60, + 0x00, 0x64, 0xE0, 0x87, 0x60, 0x46, 0x1C, 0x60, 0x05, 0xF3, 0xFF, 0xFF, 0x60, 0x43, 0x60, 0xFE, + 0xCD, 0x81, 0x20, 0xFE, 0x2A, 0x44, 0x38, 0x60, 0x00, 0x7C, 0xD0, 0x84, 0x38, 0x60, 0x04, 0x65, + 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0x60, 0x04, 0xF3, 0xFF, 0xFF, 0x08, 0x18, 0x1C, 0x60, + 0x06, 0xF3, 0x1C, 0x60, 0x07, 0xF5, 0x60, 0x41, 0x00, 0x64, 0x1C, 0x60, 0x04, 0xFB, 0x26, 0x44, + 0x01, 0xA4, 0x58, 0x90, 0xFF, 0xFF, 0x03, 0x02, 0x61, 0x44, 0x0B, 0xA5, 0x04, 0x00, 0x61, 0x44, + 0xFC, 0xA4, 0x8B, 0x7C, 0xC0, 0x85, 0xDD, 0x81, 0x66, 0x44, 0x1C, 0x60, 0x07, 0xFB, 0x26, 0x46, + 0x1B, 0xF0, 0x1C, 0x60, 0x07, 0xF5, 0x64, 0x44, 0xD4, 0x80, 0xFF, 0xFF, 0x02, 0x06, 0x2D, 0x58, + 0xFF, 0xFF, 0xFA, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0x60, 0xFE, 0x5D, 0xD2, 0xFF, 0xFF, 0x20, 0xFE, + 0xFF, 0xB4, 0x41, 0x94, 0x81, 0xA0, 0xFF, 0xFF, 0x02, 0x04, 0x00, 0xF4, 0x84, 0xA4, 0x60, 0x41, + 0x5D, 0x01, 0x1A, 0x60, 0x2C, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x3A, 0x6C, 0x01, 0x61, 0x5C, + 0x1A, 0x60, 0x2B, 0xF9, 0x60, 0xFE, 0x5D, 0xD2, 0xFF, 0xFF, 0xFE, 0xA4, 0xFF, 0xFF, 0x04, 0x20, + 0x02, 0x00, 0xFF, 0xA1, 0x60, 0x01, 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x02, 0x00, + 0xFE, 0xA1, 0x59, 0x01, 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x36, 0x02, 0x00, 0xFD, 0xA1, + 0x52, 0x01, 0x01, 0x7C, 0x1C, 0x60, 0x08, 0xF9, 0x4C, 0x00, 0x1A, 0x60, 0x2C, 0xF3, 0xFF, 0xFF, + 0x01, 0x18, 0x49, 0x01, 0x00, 0x7C, 0x1C, 0x60, 0x08, 0xF9, 0x61, 0x5C, 0x1A, 0x60, 0x2B, 0xF9, + 0x60, 0xFE, 0x5D, 0xD2, 0xFF, 0xFF, 0xFA, 0xA4, 0xFF, 0xFF, 0x04, 0x20, 0x04, 0x00, 0xFF, 0xA1, + 0xF9, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x36, 0x04, 0x00, + 0xC9, 0x81, 0xF9, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x50, 0x36, + 0x04, 0x00, 0xFD, 0xA1, 0xF9, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, + 0xF2, 0x36, 0x04, 0x00, 0xFC, 0xA1, 0xF9, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x5D, 0xD0, 0xFF, 0xFF, + 0x64, 0x40, 0x01, 0x36, 0x04, 0x00, 0xFB, 0xA1, 0xF9, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x5D, 0xD0, + 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x04, 0x00, 0xFA, 0xA1, 0xF9, 0x60, 0x6B, 0x78, 0xFF, 0xFF, + 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x36, 0x04, 0x00, 0xF9, 0xA1, 0xF9, 0x60, 0x6B, 0x78, + 0xFF, 0xFF, 0x60, 0x5C, 0x00, 0x36, 0x32, 0x00, 0x00, 0x64, 0xFB, 0x60, 0x58, 0x4E, 0x66, 0x78, + 0xFF, 0xFF, 0x65, 0x40, 0x08, 0x26, 0xF7, 0x01, 0x1A, 0x60, 0x24, 0xFB, 0x64, 0x40, 0x00, 0x36, + 0x2A, 0x00, 0x5D, 0xD2, 0xDD, 0x81, 0xFB, 0x60, 0x58, 0x4E, 0x66, 0x78, 0xFF, 0xFF, 0x65, 0x40, + 0x08, 0x26, 0xF6, 0x01, 0x1A, 0x60, 0x25, 0xFB, 0x64, 0x40, 0x00, 0x36, 0x21, 0x00, 0x5D, 0xD2, + 0xDD, 0x81, 0xFB, 0x60, 0x58, 0x4E, 0x66, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x08, 0x26, 0xF6, 0x01, + 0x1A, 0x60, 0x26, 0xFB, 0x64, 0x40, 0x00, 0x36, 0x18, 0x00, 0x5D, 0xD0, 0x34, 0x60, 0x4E, 0x62, + 0xA2, 0xD9, 0x5D, 0xD0, 0x34, 0x60, 0x4F, 0x62, 0xA2, 0xD9, 0x14, 0x00, 0x20, 0xFE, 0x00, 0x60, + 0x04, 0x64, 0x1A, 0x60, 0x24, 0xFB, 0x20, 0xFE, 0x00, 0x60, 0x04, 0x64, 0x1A, 0x60, 0x25, 0xFB, + 0x20, 0xFE, 0x00, 0x60, 0x02, 0x64, 0x1A, 0x60, 0x26, 0xFB, 0x20, 0xFE, 0x00, 0x60, 0x00, 0x64, + 0x1A, 0x60, 0x27, 0xFB, 0x20, 0xFE, 0x1C, 0x60, 0x08, 0xF1, 0xFF, 0xFF, 0x03, 0x18, 0x01, 0x7C, + 0x1C, 0x60, 0x08, 0xF9, 0x1A, 0x60, 0x2B, 0xF1, 0xA2, 0xDD, 0x61, 0x44, 0x1A, 0x60, 0x28, 0xFB, + 0xD1, 0x84, 0xDC, 0x84, 0x64, 0x45, 0x34, 0x60, 0x10, 0x63, 0xBD, 0xDB, 0x60, 0x41, 0xCD, 0x84, + 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, + 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, + 0xDF, 0x83, 0x1A, 0x60, 0x09, 0xF3, 0xFF, 0xFF, 0x60, 0x47, 0xA2, 0xDB, 0x1A, 0x60, 0x28, 0xF3, + 0x1A, 0x60, 0x2B, 0xF1, 0x60, 0x41, 0x64, 0x43, 0xF9, 0x60, 0x56, 0x78, 0xFF, 0xFF, 0x20, 0xFE, + 0x7C, 0x44, 0x1A, 0x60, 0x20, 0xFB, 0x1A, 0x60, 0x1A, 0xF1, 0x1A, 0x60, 0x24, 0xF3, 0xFF, 0xFF, + 0xA0, 0x84, 0xFF, 0xFF, 0x10, 0x26, 0x07, 0x00, 0x04, 0x26, 0x07, 0x00, 0x20, 0x26, 0x07, 0x00, + 0x02, 0x26, 0x07, 0x00, 0x3F, 0x00, 0x10, 0x7C, 0x05, 0x00, 0x04, 0x7C, 0x03, 0x00, 0x20, 0x7C, + 0x01, 0x00, 0x02, 0x7C, 0x1A, 0x60, 0x20, 0xF9, 0x7C, 0x44, 0x1A, 0x60, 0x21, 0xFB, 0x1A, 0x60, + 0x1B, 0xF1, 0x1A, 0x60, 0x25, 0xF3, 0x34, 0x60, 0x40, 0x61, 0xA0, 0x84, 0xA1, 0xD1, 0xFF, 0xFF, + 0x10, 0x26, 0x05, 0x00, 0x04, 0x26, 0x05, 0x00, 0x01, 0x26, 0x08, 0x00, 0x23, 0x00, 0x10, 0x7C, + 0x06, 0x00, 0x64, 0x40, 0x10, 0x26, 0x1E, 0x00, 0x04, 0x7C, 0x01, 0x00, 0x01, 0x7C, 0x1A, 0x60, + 0x21, 0xF9, 0x7C, 0x44, 0x1A, 0x60, 0x22, 0xFB, 0x1A, 0x60, 0x1C, 0xF1, 0x1A, 0x60, 0x26, 0xF3, + 0xFF, 0xFF, 0xA0, 0x84, 0x60, 0x40, 0x02, 0x26, 0x05, 0x00, 0x04, 0x26, 0x05, 0x00, 0x01, 0x26, + 0x05, 0x00, 0x08, 0x00, 0x02, 0x7C, 0x03, 0x00, 0x04, 0x7C, 0x01, 0x00, 0x20, 0x7C, 0x1A, 0x60, + 0x22, 0xF9, 0x09, 0x00, 0x7C, 0x44, 0x1A, 0x60, 0x20, 0xFB, 0x1A, 0x60, 0x21, 0xFB, 0x1A, 0x60, + 0x22, 0xFB, 0x1A, 0x60, 0x23, 0xFB, 0x7C, 0x44, 0x1A, 0x60, 0x20, 0xF1, 0xBD, 0xD9, 0x1A, 0x60, + 0x21, 0xF1, 0xB0, 0x84, 0xBD, 0xD9, 0x1A, 0x60, 0x22, 0xF1, 0xB0, 0x84, 0xBD, 0xD9, 0x1A, 0x60, + 0x1D, 0xF1, 0xB0, 0x84, 0xBD, 0xD9, 0x04, 0x03, 0x1C, 0x60, 0x08, 0xF1, 0xBD, 0xD9, 0x72, 0x00, + 0x16, 0x60, 0xC2, 0xF3, 0xFF, 0xFF, 0xFF, 0xA0, 0xFF, 0xFF, 0x0C, 0x24, 0x6B, 0x00, 0x60, 0x40, + 0x0B, 0x36, 0x68, 0x00, 0x20, 0x40, 0x10, 0x27, 0x65, 0x00, 0x91, 0x00, 0x20, 0xFE, 0x00, 0x65, + 0x60, 0xFE, 0x1A, 0x60, 0x28, 0xFB, 0xE0, 0x84, 0xE0, 0x84, 0x08, 0x20, 0x03, 0x00, 0x01, 0x64, + 0xA2, 0xDB, 0x02, 0x64, 0x02, 0xA5, 0x64, 0x44, 0xD4, 0x9C, 0xD4, 0x80, 0x34, 0x60, 0x52, 0x62, + 0x02, 0x05, 0x08, 0x65, 0x4D, 0x00, 0xA2, 0xD9, 0x7C, 0x44, 0x34, 0x60, 0x54, 0x62, 0xA2, 0xDB, + 0x20, 0xFE, 0x00, 0x64, 0x60, 0xFE, 0x1C, 0x60, 0x08, 0xF3, 0xFF, 0xFF, 0x00, 0xA0, 0x5D, 0xD0, + 0x00, 0x65, 0x04, 0x03, 0x64, 0x40, 0x00, 0x3A, 0x01, 0x65, 0x03, 0x00, 0x64, 0x40, 0x00, 0x3A, + 0x01, 0x65, 0x5D, 0xD0, 0x04, 0x03, 0x64, 0x40, 0x0F, 0x3A, 0x01, 0x65, 0x03, 0x00, 0x64, 0x40, + 0x50, 0x3A, 0x01, 0x65, 0x5D, 0xD0, 0x04, 0x03, 0x64, 0x40, 0xAC, 0x3A, 0x01, 0x65, 0x03, 0x00, + 0x64, 0x40, 0xF2, 0x3A, 0x01, 0x65, 0x5D, 0xD0, 0x65, 0x40, 0x00, 0x3A, 0x17, 0x00, 0x00, 0x60, + 0x00, 0x65, 0x64, 0x40, 0x00, 0x36, 0x01, 0x65, 0x64, 0x40, 0x01, 0x36, 0x02, 0x65, 0x64, 0x40, + 0x02, 0x36, 0x04, 0x65, 0x64, 0x40, 0x04, 0x36, 0x10, 0x65, 0x64, 0x40, 0x05, 0x36, 0x20, 0x65, + 0x65, 0x5C, 0x1A, 0x60, 0x2A, 0xF3, 0xFF, 0xFF, 0xB0, 0x84, 0xA2, 0xDB, 0x1A, 0x60, 0x28, 0xF3, + 0x00, 0x65, 0xFF, 0xA4, 0xA2, 0xDB, 0xBC, 0x02, 0x1A, 0x60, 0x2A, 0xF3, 0x1A, 0x60, 0x29, 0xF1, + 0x2E, 0x58, 0xFF, 0xFF, 0x20, 0xFE, 0x88, 0xF3, 0xFF, 0xFF, 0x3C, 0xA4, 0x88, 0xFB, 0x87, 0xF3, + 0x7D, 0xF1, 0x04, 0xA4, 0x87, 0xFB, 0x53, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x26, 0x0D, 0x00, + 0x7D, 0xF3, 0x10, 0x60, 0xF2, 0x61, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, 0x06, 0xA1, 0xFB, 0x01, + 0xA1, 0xD3, 0xFF, 0xFF, 0x02, 0xBC, 0xA1, 0xDB, 0x12, 0x00, 0x7D, 0xF3, 0x11, 0x60, 0x60, 0x63, + 0x01, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x12, 0x60, 0x40, 0x65, 0xA3, 0xD1, 0xD7, 0x80, 0xD0, 0x80, + 0x06, 0x03, 0x02, 0x03, 0x08, 0xA3, 0xF9, 0x01, 0x02, 0xA3, 0x04, 0x64, 0xA3, 0xDB, 0x20, 0xFE, + 0x26, 0x46, 0x31, 0x40, 0x20, 0x2A, 0x35, 0x00, 0x3F, 0xF2, 0x47, 0x65, 0xC4, 0x84, 0xE8, 0x84, + 0x23, 0xFA, 0xF1, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x7D, 0xF3, 0x01, 0x60, 0xFF, 0x65, 0xA4, 0x84, + 0x01, 0x23, 0x14, 0x00, 0x11, 0x60, 0x60, 0x61, 0x12, 0x60, 0x40, 0x65, 0xA1, 0xD1, 0xD5, 0x80, + 0xD0, 0x80, 0x0B, 0x03, 0x02, 0x03, 0x08, 0xA1, 0xF9, 0x01, 0x04, 0xA1, 0xA1, 0xD3, 0x01, 0x60, + 0x00, 0x65, 0x60, 0x47, 0xFF, 0xB4, 0xB4, 0x84, 0x01, 0x00, 0x01, 0x64, 0x00, 0xF4, 0x08, 0xFA, + 0xFF, 0xFF, 0x26, 0x46, 0x26, 0x60, 0x0A, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x26, 0x44, 0x5A, 0xDB, + 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, + 0xFF, 0xFF, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x78, 0xFB, 0xAC, 0x85, 0x60, 0x41, 0x55, 0x03, + 0x32, 0x60, 0x00, 0x63, 0x1B, 0x60, 0x04, 0xFD, 0x62, 0x43, 0x1A, 0x60, 0xB4, 0xFD, 0x1A, 0x60, + 0xBA, 0xFD, 0x1A, 0x60, 0xC4, 0xFD, 0x1A, 0x60, 0xCE, 0xFD, 0x00, 0x63, 0xE9, 0x81, 0x08, 0x64, + 0x02, 0x24, 0xDF, 0x83, 0xFB, 0x02, 0x53, 0x94, 0x32, 0x7F, 0x03, 0x06, 0x1B, 0x60, 0x04, 0xFB, + 0x08, 0x63, 0x63, 0x5E, 0x01, 0x7F, 0x19, 0x60, 0x8A, 0xFB, 0x65, 0x41, 0x33, 0x60, 0x16, 0x65, + 0x0F, 0x60, 0xF4, 0x64, 0xE9, 0x81, 0x58, 0xD1, 0xFD, 0x04, 0xCF, 0x83, 0xA5, 0xD9, 0x0C, 0x03, + 0xE9, 0x81, 0x58, 0xD1, 0xFD, 0x04, 0x40, 0x48, 0xA5, 0xD1, 0x64, 0x5F, 0x64, 0x5E, 0xA5, 0xDB, + 0xDA, 0x85, 0xCF, 0x83, 0x28, 0x44, 0xEE, 0x02, 0x00, 0xB9, 0xD8, 0x83, 0x15, 0x03, 0x36, 0x60, + 0x0A, 0x65, 0xE9, 0x81, 0xBD, 0xD1, 0x02, 0x05, 0xFC, 0x02, 0x17, 0x00, 0xA5, 0xD9, 0x15, 0x03, + 0xE9, 0x81, 0xBD, 0xD1, 0x02, 0x05, 0xFC, 0x02, 0x10, 0x00, 0xA5, 0xD3, 0xFF, 0xFF, 0x64, 0x5F, + 0xA5, 0xDB, 0xDA, 0x85, 0xEE, 0x02, 0x09, 0x00, 0x67, 0x43, 0x1A, 0x60, 0xB4, 0xFD, 0x1A, 0x60, + 0xBA, 0xFD, 0x1A, 0x60, 0xC4, 0xFD, 0x1A, 0x60, 0xCE, 0xFD, 0x2E, 0x45, 0x25, 0x60, 0x46, 0x64, + 0xD4, 0x80, 0xFF, 0xFF, 0x10, 0x03, 0x20, 0x40, 0x10, 0x27, 0x0D, 0x00, 0x33, 0x60, 0x1E, 0x61, + 0x19, 0x60, 0x8A, 0xF3, 0xA1, 0xDB, 0xFF, 0xB4, 0xCC, 0x84, 0xA8, 0x83, 0x33, 0x60, 0x14, 0x64, + 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0x7D, 0xF3, 0x33, 0x60, 0x20, 0x63, 0x60, 0x40, 0x01, 0x27, + 0x03, 0x00, 0x19, 0x60, 0x3B, 0xF3, 0x02, 0x00, 0x19, 0x60, 0x3C, 0xF3, 0x08, 0x61, 0x60, 0xFE, + 0xA3, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, 0x00, 0xA8, 0xE8, 0x84, 0x0F, 0x03, 0x60, 0xFE, 0x02, 0x28, + 0xF6, 0x01, 0x80, 0x62, 0xB2, 0x9C, 0xBD, 0xD9, 0x7B, 0xF9, 0xCD, 0x81, 0x00, 0x36, 0x01, 0x00, + 0xEE, 0x01, 0x36, 0x60, 0x0A, 0x63, 0x08, 0x61, 0xEA, 0x01, 0x2E, 0x58, 0xFF, 0xFF, 0x32, 0x60, + 0x76, 0x63, 0x65, 0x40, 0xFF, 0x36, 0x02, 0xA3, 0xA3, 0xD3, 0xFF, 0xFF, 0xE8, 0x84, 0xE8, 0x84, + 0xE8, 0x84, 0xE8, 0x84, 0x40, 0x26, 0x7F, 0xB4, 0x20, 0x26, 0x3F, 0xB4, 0x60, 0x45, 0x80, 0x63, + 0xFD, 0x60, 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x7D, 0xFB, 0x40, 0x63, 0xFD, 0x60, + 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x7E, 0xFB, 0x20, 0x63, 0xFD, 0x60, 0x58, 0x4D, + 0x34, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x7F, 0xFB, 0x10, 0x63, 0xFD, 0x60, 0x58, 0x4D, 0x34, 0x78, + 0xFF, 0xFF, 0x19, 0x60, 0x80, 0xFB, 0x08, 0x63, 0xFD, 0x60, 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, + 0x19, 0x60, 0x81, 0xFB, 0x04, 0x63, 0xFD, 0x60, 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x19, 0x60, + 0x82, 0xFB, 0x02, 0x63, 0xFD, 0x60, 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x83, 0xFB, + 0x01, 0x63, 0xFD, 0x60, 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x84, 0xFB, 0x2E, 0x58, + 0xFF, 0xFF, 0x19, 0x60, 0x3B, 0xF3, 0xFF, 0xFF, 0x0F, 0xB4, 0x60, 0x45, 0x08, 0x63, 0xFD, 0x60, + 0x58, 0x4D, 0x5F, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x85, 0xFB, 0x04, 0x63, 0xFD, 0x60, 0x58, 0x4D, + 0x5F, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x86, 0xFB, 0x02, 0x63, 0xFD, 0x60, 0x58, 0x4D, 0x5F, 0x78, + 0xFF, 0xFF, 0x19, 0x60, 0x87, 0xFB, 0x01, 0x63, 0xFD, 0x60, 0x58, 0x4D, 0x5F, 0x78, 0xFF, 0xFF, + 0x19, 0x60, 0x88, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x63, 0x5C, 0xA7, 0x84, 0xEB, 0x83, 0x14, 0x02, + 0x01, 0x03, 0xFB, 0x01, 0x64, 0x44, 0x01, 0x36, 0x0B, 0x64, 0x02, 0x36, 0x0B, 0x64, 0x04, 0x36, + 0x0A, 0x64, 0x08, 0x36, 0x0A, 0x64, 0x10, 0x36, 0x09, 0x64, 0x20, 0x36, 0x09, 0x64, 0x40, 0x36, + 0x09, 0x64, 0x80, 0x36, 0x09, 0x64, 0x11, 0x00, 0x60, 0x40, 0x01, 0x36, 0x0B, 0x64, 0x02, 0x36, + 0x0F, 0x64, 0x04, 0x36, 0x0A, 0x64, 0x08, 0x36, 0x0E, 0x64, 0x10, 0x36, 0x09, 0x64, 0x20, 0x36, + 0x0D, 0x64, 0x40, 0x36, 0x08, 0x64, 0x80, 0x36, 0x0C, 0x64, 0x2D, 0x58, 0xFF, 0xFF, 0x63, 0x5C, + 0xA7, 0x84, 0xEB, 0x83, 0x0C, 0x02, 0x01, 0x03, 0xFB, 0x01, 0x64, 0x44, 0x01, 0x36, 0x0A, 0x64, + 0x02, 0x36, 0x14, 0x64, 0x04, 0x36, 0x37, 0x64, 0x08, 0x36, 0x6E, 0x64, 0x09, 0x00, 0x60, 0x40, + 0x01, 0x36, 0x0A, 0x64, 0x02, 0x36, 0x14, 0x64, 0x04, 0x36, 0x37, 0x64, 0x08, 0x36, 0x6E, 0x64, + 0x2D, 0x58, 0xFF, 0xFF, 0x60, 0xFE, 0x81, 0xA1, 0x7F, 0xA1, 0x02, 0x06, 0x00, 0xF4, 0x03, 0x61, + 0x5D, 0xD2, 0xCF, 0x83, 0xD4, 0x80, 0x25, 0x03, 0x16, 0x03, 0xCF, 0x83, 0x61, 0x44, 0x80, 0xA0, + 0x20, 0x03, 0x02, 0x02, 0x00, 0xF4, 0x03, 0x61, 0x5D, 0xD2, 0xCF, 0x83, 0x81, 0xA1, 0x19, 0x03, + 0x05, 0x07, 0x7F, 0xA1, 0xCC, 0x84, 0xDD, 0x81, 0xE6, 0x03, 0xF7, 0x01, 0x00, 0xF4, 0x00, 0xB8, + 0x04, 0x61, 0xE6, 0x03, 0xF2, 0x01, 0x2C, 0x43, 0x5D, 0xD0, 0xDE, 0xD9, 0x64, 0x44, 0x5D, 0xD0, + 0xDE, 0xD9, 0xCC, 0x84, 0x81, 0xA1, 0x05, 0x03, 0x7F, 0xA1, 0xF9, 0x04, 0x00, 0xF4, 0x03, 0x61, + 0xF6, 0x01, 0x20, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x01, 0x3A, 0x02, 0x00, 0x16, 0x64, 0x2B, 0x00, + 0x02, 0x3A, 0x02, 0x00, 0x14, 0x64, 0x27, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x12, 0x64, 0x23, 0x00, + 0x08, 0x3A, 0x02, 0x00, 0x10, 0x64, 0x1F, 0x00, 0x10, 0x3A, 0x02, 0x00, 0x0E, 0x64, 0x1B, 0x00, + 0x20, 0x3A, 0x02, 0x00, 0x0C, 0x64, 0x17, 0x00, 0x40, 0x3A, 0x02, 0x00, 0x0A, 0x64, 0x13, 0x00, + 0x80, 0x3A, 0x02, 0x00, 0x08, 0x64, 0x0F, 0x00, 0x01, 0x3B, 0x02, 0x00, 0x06, 0x64, 0x0B, 0x00, + 0x02, 0x3B, 0x02, 0x00, 0x04, 0x64, 0x07, 0x00, 0x04, 0x3B, 0x02, 0x00, 0x02, 0x64, 0x03, 0x00, + 0x08, 0x3B, 0xFF, 0x01, 0x00, 0x64, 0x2E, 0x58, 0xFF, 0xFF, 0x27, 0xF2, 0xFF, 0xFF, 0x60, 0x40, + 0x36, 0x3A, 0x02, 0x00, 0x00, 0x61, 0x30, 0x00, 0x30, 0x3A, 0x02, 0x00, 0x02, 0x61, 0x2C, 0x00, + 0x24, 0x3A, 0x02, 0x00, 0x04, 0x61, 0x28, 0x00, 0x18, 0x3A, 0x02, 0x00, 0x06, 0x61, 0x24, 0x00, + 0x12, 0x3A, 0x02, 0x00, 0x08, 0x61, 0x20, 0x00, 0x0C, 0x3A, 0x02, 0x00, 0x0A, 0x61, 0x1C, 0x00, + 0x09, 0x3A, 0x02, 0x00, 0x0C, 0x61, 0x18, 0x00, 0x06, 0x3A, 0x02, 0x00, 0x0E, 0x61, 0x14, 0x00, + 0x6E, 0x3A, 0x02, 0x00, 0x10, 0x61, 0x10, 0x00, 0x37, 0x3A, 0x02, 0x00, 0x12, 0x61, 0x0C, 0x00, + 0x14, 0x3A, 0x02, 0x00, 0x14, 0x61, 0x08, 0x00, 0x0A, 0x3A, 0x02, 0x00, 0x16, 0x61, 0x04, 0x00, + 0x78, 0x43, 0x03, 0x61, 0x29, 0x60, 0xEA, 0x78, 0x65, 0x40, 0x01, 0x3A, 0x13, 0x00, 0x66, 0x45, + 0x2B, 0x46, 0x92, 0xFA, 0x65, 0x46, 0x26, 0xF2, 0xFF, 0xFF, 0x60, 0x41, 0x00, 0x7F, 0x60, 0x45, + 0x61, 0x47, 0x00, 0x7F, 0xD4, 0x84, 0x66, 0x41, 0x2B, 0x46, 0x0E, 0xF2, 0x60, 0x45, 0x65, 0x5E, + 0x0E, 0xFA, 0x61, 0x46, 0x2E, 0x58, 0xFF, 0xFF, 0xCD, 0x81, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, + 0x01, 0x64, 0x32, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x02, 0x64, 0x2E, 0x00, 0x0B, 0x3A, 0x02, 0x00, + 0x04, 0x64, 0x2A, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x08, 0x64, 0x26, 0x00, 0x0C, 0x3A, 0x02, 0x00, + 0x10, 0x64, 0x22, 0x00, 0x12, 0x3A, 0x02, 0x00, 0x20, 0x64, 0x1E, 0x00, 0x18, 0x3A, 0x02, 0x00, + 0x40, 0x64, 0x1A, 0x00, 0x24, 0x3A, 0x02, 0x00, 0x80, 0x64, 0x16, 0x00, 0x30, 0x3A, 0x03, 0x00, + 0x00, 0x7E, 0x01, 0x7F, 0x11, 0x00, 0x48, 0x3A, 0x03, 0x00, 0x00, 0x7E, 0x02, 0x7F, 0x0C, 0x00, + 0x60, 0x3A, 0x03, 0x00, 0x00, 0x7E, 0x04, 0x7F, 0x07, 0x00, 0x6C, 0x3A, 0x03, 0x00, 0x00, 0x7E, + 0x08, 0x7F, 0x02, 0x00, 0x00, 0x64, 0x00, 0x00, 0x20, 0xFE, 0x2A, 0x45, 0x34, 0x8A, 0x60, 0xFE, + 0x61, 0x40, 0x00, 0x36, 0x02, 0x00, 0xBD, 0xD3, 0xBF, 0x01, 0x2E, 0x58, 0xFF, 0xFF, + +}; /* fw_image_4_data */ + +static const CFG_IDENTITY_STRCT fw_image_infoidentity[] = { + { + sizeof( CFG_IDENTITY_STRCT ) / sizeof(hcf_16) - 1, + CFG_FW_IDENTITY, + COMP_ID_FW_STA, + 4, //Variant + 1, //Major + 36 //Minor + }, + { 0000, 0000, 0000, 0000, 0000, 0000 } //endsentinel +}; + +static const CFG_PROG_STRCT fw_image_code[] = { + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0x0184, // sizeof(fw_image_1_data), + 0x00000060, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_1_data + }, + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0x2c0e, // sizeof(fw_image_2_data), + 0x00000C16, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_2_data + }, + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0x54de, // sizeof(fw_image_3_data), + 0x001E3824, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_3_data + }, + { + 8, + CFG_PROG, + CFG_PROG_VOLATILE, // mode + 0xbcde, // sizeof(fw_image_4_data), + 0x001F4000, // Target address in NIC Memory + 0x0000, // CRC: yes/no TYPE: primary/station/tertiary + (hcf_8 FAR *) fw_image_4_data + }, + { + 5, + CFG_PROG, + CFG_PROG_STOP, // mode + 0000, + 0x000F429B, // Start execution address + }, + { 0000, 0000, 0000, 0000, 00000000, 0000, 00000000} +}; + +static const CFG_RANGE20_STRCT fw_image_infocompat[] = { + { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), + CFG_FW_SUP_RANGE, + COMP_ROLE_SUPL, + COMP_ID_STA, + { + { 4, 1, 2 } //variant, bottom, top + } + }, + { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), + CFG_MFI_ACT_RANGES_STA, + COMP_ROLE_ACT, + COMP_ID_MFI, + { + { 7, 3, 3 }, //variant, bottom, top + { 8, 1, 1 } //variant, bottom, top + } + }, + { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), + CFG_CFI_ACT_RANGES_STA, + COMP_ROLE_ACT, + COMP_ID_CFI, + { + { 4, 1, 2 } //variant, bottom, top + } + }, + { 0000, 0000, 0000, 0000, { { 0000, 0000, 0000 } } } //endsentinel +}; + +memimage fw_image = { + "FUPU7D37dhfwci\001C", //signature, , C/Bin type + (CFG_PROG_STRCT *) fw_image_code, + 0x000F429B, + 00000000, //(dummy) pdaplug + 00000000, //(dummy) priplug + (CFG_RANGE20_STRCT *) fw_image_infocompat, + (CFG_IDENTITY_STRCT *) fw_image_infoidentity, +}; + diff --git a/drivers/staging/wlags49_h2/wl_cs.c b/drivers/staging/wlags49_h2/wl_cs.c new file mode 100644 index 0000000000000000000000000000000000000000..811a8daa660ec5913e53558d1b8a858b53c3a986 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_cs.c @@ -0,0 +1,702 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * This file contains processing and initialization specific to Card Services + * devices (PCMCIA, CF). + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +/******************************************************************************* + * include 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 +#include +#include +#include +#include + + +/******************************************************************************* + * macro definitions + ******************************************************************************/ +#define CS_CHECK(fn, ret) do { \ + last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \ + } while (0) + +/******************************************************************************* + * global definitions + ******************************************************************************/ +#if DBG +extern dbg_info_t *DbgInfo; +#endif /* DBG */ + + +/******************************************************************************* + * wl_adapter_attach() + ******************************************************************************* + * + * DESCRIPTION: + * + * Creates an instance of the driver, allocating local data structures for + * one device. The device is registered with Card Services. + * + * PARAMETERS: + * + * none + * + * RETURNS: + * + * pointer to an allocated dev_link_t structure + * NULL on failure + * + ******************************************************************************/ +static int wl_adapter_attach(struct pcmcia_device *link) +{ + struct net_device *dev; + struct wl_private *lp; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_adapter_attach" ); + DBG_ENTER( DbgInfo ); + + dev = wl_device_alloc(); + if(dev == NULL) { + DBG_ERROR( DbgInfo, "wl_device_alloc returned NULL\n"); + return -ENOMEM; + } + + link->io.NumPorts1 = HCF_NUM_IO_PORTS; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + link->io.IOAddrLines = 6; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; + link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; + link->irq.Handler = &wl_isr; + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.IntType = INT_MEMORY_AND_IO; + link->conf.ConfigIndex = 5; + link->conf.Present = PRESENT_OPTION; + + link->priv = link->irq.Instance = dev; + lp = wl_priv(dev); + lp->link = link; + + wl_adapter_insert(link); + + DBG_LEAVE( DbgInfo ); + return 0; +} // wl_adapter_attach +/*============================================================================*/ + + + +/******************************************************************************* + * wl_adapter_detach() + ******************************************************************************* + * + * DESCRIPTION: + * + * This deletes a driver "instance". The device is de-registered with Card + * Services. If it has been released, then the net device is unregistered, and + * all local data structures are freed. Otherwise, the structures will be + * freed when the device is released. + * + * PARAMETERS: + * + * link - pointer to the dev_link_t structure representing the device to + * detach + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +static void wl_adapter_detach(struct pcmcia_device *link) +{ + struct net_device *dev = link->priv; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wl_adapter_detach" ); + DBG_ENTER( DbgInfo ); + DBG_PARAM( DbgInfo, "link", "0x%p", link ); + + wl_adapter_release(link); + + if (dev) { + unregister_wlags_sysfs(dev); + unregister_netdev(dev); + } + + wl_device_dealloc(dev); + + DBG_LEAVE( DbgInfo ); +} // wl_adapter_detach +/*============================================================================*/ + + +/******************************************************************************* + * wl_adapter_release() + ******************************************************************************* + * + * DESCRIPTION: + * + * After a card is removed, this routine will release the PCMCIA + * configuration. If the device is still open, this will be postponed until it + * is closed. + * + * PARAMETERS: + * + * arg - a u_long representing a pointer to a dev_link_t structure for the + * device to be released. + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_adapter_release( struct pcmcia_device *link ) +{ + DBG_FUNC( "wl_adapter_release" ); + DBG_ENTER( DbgInfo ); + DBG_PARAM( DbgInfo, "link", "0x%p", link); + + /* Stop hardware */ + wl_remove(link->priv); + + pcmcia_disable_device(link); + + DBG_LEAVE( DbgInfo ); +} // wl_adapter_release +/*============================================================================*/ + +static int wl_adapter_suspend(struct pcmcia_device *link) +{ + struct net_device *dev = link->priv; + + //if (link->open) { + netif_device_detach(dev); + wl_suspend(dev); +//// CHECK! pcmcia_release_configuration(link->handle); + //} + + return 0; +} // wl_adapter_suspend + +static int wl_adapter_resume(struct pcmcia_device *link) +{ + struct net_device *dev = link->priv; + + wl_resume(dev); + + netif_device_attach( dev ); + + return 0; +} // wl_adapter_resume + +/******************************************************************************* + * wl_adapter_insert() + ******************************************************************************* + * + * DESCRIPTION: + * + * wl_adapter_insert() is scheduled to run after a CARD_INSERTION event is + * received, to configure the PCMCIA socket, and to make the ethernet device + * available to the system. + * + * PARAMETERS: + * + * link - pointer to the dev_link_t structure representing the device to + * insert + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_adapter_insert( struct pcmcia_device *link ) +{ + struct net_device *dev; + int i; + int last_fn, last_ret; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_adapter_insert" ); + DBG_ENTER( DbgInfo ); + DBG_PARAM( DbgInfo, "link", "0x%p", link ); + + dev = link->priv; + + /* Do we need to allocate an interrupt? */ + link->conf.Attributes |= CONF_ENABLE_IRQ; + + CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); + + + dev->irq = link->irq.AssignedIRQ; + dev->base_addr = link->io.BasePort1; + + SET_NETDEV_DEV(dev, &handle_to_dev(link)); + if (register_netdev(dev) != 0) { + printk("%s: register_netdev() failed\n", MODULE_NAME); + goto failed; + } + link->dev_node = &( wl_priv(dev) )->node; + strcpy(( wl_priv(dev) )->node.dev_name, dev->name); + register_wlags_sysfs(dev); + + printk(KERN_INFO "%s: Wireless, io_addr %#03lx, irq %d, ""mac_address ", + dev->name, dev->base_addr, dev->irq); + for( i = 0; i < ETH_ALEN; i++ ) { + printk("%02X%c", dev->dev_addr[i], ((i < (ETH_ALEN-1)) ? ':' : '\n')); + } + + DBG_LEAVE( DbgInfo ); + return; + + +cs_failed: + cs_error( link, last_fn, last_ret ); + + +failed: + wl_adapter_release( link ); + + DBG_LEAVE(DbgInfo); + return; +} // wl_adapter_insert +/*============================================================================*/ + + +/******************************************************************************* + * wl_adapter_open() + ******************************************************************************* + * + * DESCRIPTION: + * + * Open the device. + * + * PARAMETERS: + * + * dev - a pointer to a net_device structure representing the network + * device to open. + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_adapter_open( struct net_device *dev ) +{ + struct wl_private *lp = wl_priv(dev); + struct pcmcia_device *link = lp->link; + int result = 0; + int hcf_status = HCF_SUCCESS; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wl_adapter_open" ); + DBG_ENTER( DbgInfo ); + DBG_PRINT( "%s\n", VERSION_INFO ); + DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + + if(!pcmcia_dev_present(link)) + { + DBG_LEAVE( DbgInfo ); + return -ENODEV; + } + + link->open++; + + hcf_status = wl_open( dev ); + + if( hcf_status != HCF_SUCCESS ) { + link->open--; + result = -ENODEV; + } + + DBG_LEAVE( DbgInfo ); + return result; +} // wl_adapter_open +/*============================================================================*/ + + +/******************************************************************************* + * wl_adapter_close() + ******************************************************************************* + * + * DESCRIPTION: + * + * Close the device. + * + * PARAMETERS: + * + * dev - a pointer to a net_device structure representing the network + * device to close. + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_adapter_close( struct net_device *dev ) +{ + struct wl_private *lp = wl_priv(dev); + struct pcmcia_device *link = lp->link; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wl_adapter_close" ); + DBG_ENTER( DbgInfo ); + DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + + if( link == NULL ) { + DBG_LEAVE( DbgInfo ); + return -ENODEV; + } + + DBG_TRACE( DbgInfo, "%s: Shutting down adapter.\n", dev->name ); + wl_close( dev ); + + link->open--; + + DBG_LEAVE( DbgInfo ); + return 0; +} // wl_adapter_close +/*============================================================================*/ + +static struct pcmcia_device_id wl_adapter_ids[] = { +#if ! ((HCF_TYPE) & HCF_TYPE_HII5) + PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0003), + PCMCIA_DEVICE_PROD_ID12("Agere Systems", "Wireless PC Card Model 0110", + 0x33103a9b, 0xe175b0dd), +#else + PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0004), + PCMCIA_DEVICE_PROD_ID12("Linksys", "WCF54G_Wireless-G_CompactFlash_Card", + 0x0733cc81, 0x98a599e1), +#endif // (HCF_TYPE) & HCF_TYPE_HII5 + PCMCIA_DEVICE_NULL, + }; +MODULE_DEVICE_TABLE(pcmcia, wl_adapter_ids); + +static struct pcmcia_driver wlags49_driver = { + .owner = THIS_MODULE, + .drv = { + .name = DRIVER_NAME, + }, + .probe = wl_adapter_attach, + .remove = wl_adapter_detach, + .id_table = wl_adapter_ids, + .suspend = wl_adapter_suspend, + .resume = wl_adapter_resume, +}; + + + +/******************************************************************************* + * wl_adapter_init_module() + ******************************************************************************* + * + * DESCRIPTION: + * + * Called by init_module() to perform PCMCIA driver initialization. + * + * PARAMETERS: + * + * N/A + * + * RETURNS: + * + * 0 on success + * -1 on error + * + ******************************************************************************/ +int wl_adapter_init_module( void ) +{ + int ret; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wl_adapter_init_module" ); + DBG_ENTER( DbgInfo ); + DBG_TRACE( DbgInfo, "wl_adapter_init_module() -- PCMCIA\n" ); + + ret = pcmcia_register_driver(&wlags49_driver); + + DBG_LEAVE( DbgInfo ); + return ret; +} // wl_adapter_init_module +/*============================================================================*/ + + +/******************************************************************************* + * wl_adapter_cleanup_module() + ******************************************************************************* + * + * DESCRIPTION: + * + * Called by cleanup_module() to perform driver uninitialization. + * + * PARAMETERS: + * + * N/A + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_adapter_cleanup_module( void ) +{ + DBG_FUNC( "wl_adapter_cleanup_module" ); + DBG_ENTER( DbgInfo ); + DBG_TRACE( DbgInfo, "wl_adapter_cleanup_module() -- PCMCIA\n" ); + + + pcmcia_unregister_driver(&wlags49_driver); + + DBG_LEAVE( DbgInfo ); + return; +} // wl_adapter_cleanup_module +/*============================================================================*/ + + +/******************************************************************************* + * wl_adapter_is_open() + ******************************************************************************* + * + * DESCRIPTION: + * + * Check with Card Services to determine if this device is open. + * + * PARAMETERS: + * + * dev - a pointer to the net_device structure whose open status will be + * checked + * + * RETURNS: + * + * nonzero if device is open + * 0 otherwise + * + ******************************************************************************/ +int wl_adapter_is_open( struct net_device *dev ) +{ + struct wl_private *lp = wl_priv(dev); + struct pcmcia_device *link = lp->link; + + if(!pcmcia_dev_present(link)) { + return 0; + } + + return( link->open ); +} // wl_adapter_is_open +/*============================================================================*/ + + +#if DBG + +/******************************************************************************* + * DbgEvent() + ******************************************************************************* + * + * DESCRIPTION: + * + * Converts the card serivces events to text for debugging. + * + * PARAMETERS: + * + * mask - a integer representing the error(s) being reported by Card + * Services. + * + * RETURNS: + * + * a pointer to a string describing the error(s) + * + ******************************************************************************/ +const char* DbgEvent( int mask ) +{ + static char DbgBuffer[256]; + char *pBuf; + /*------------------------------------------------------------------------*/ + + + pBuf = DbgBuffer; + *pBuf = '\0'; + + + if( mask & CS_EVENT_WRITE_PROTECT ) + strcat( pBuf, "WRITE_PROTECT " ); + + if(mask & CS_EVENT_CARD_LOCK) + strcat( pBuf, "CARD_LOCK " ); + + if(mask & CS_EVENT_CARD_INSERTION) + strcat( pBuf, "CARD_INSERTION " ); + + if(mask & CS_EVENT_CARD_REMOVAL) + strcat( pBuf, "CARD_REMOVAL " ); + + if(mask & CS_EVENT_BATTERY_DEAD) + strcat( pBuf, "BATTERY_DEAD " ); + + if(mask & CS_EVENT_BATTERY_LOW) + strcat( pBuf, "BATTERY_LOW " ); + + if(mask & CS_EVENT_READY_CHANGE) + strcat( pBuf, "READY_CHANGE " ); + + if(mask & CS_EVENT_CARD_DETECT) + strcat( pBuf, "CARD_DETECT " ); + + if(mask & CS_EVENT_RESET_REQUEST) + strcat( pBuf, "RESET_REQUEST " ); + + if(mask & CS_EVENT_RESET_PHYSICAL) + strcat( pBuf, "RESET_PHYSICAL " ); + + if(mask & CS_EVENT_CARD_RESET) + strcat( pBuf, "CARD_RESET " ); + + if(mask & CS_EVENT_REGISTRATION_COMPLETE) + strcat( pBuf, "REGISTRATION_COMPLETE " ); + + // if(mask & CS_EVENT_RESET_COMPLETE) + // strcat( pBuf, "RESET_COMPLETE " ); + + if(mask & CS_EVENT_PM_SUSPEND) + strcat( pBuf, "PM_SUSPEND " ); + + if(mask & CS_EVENT_PM_RESUME) + strcat( pBuf, "PM_RESUME " ); + + if(mask & CS_EVENT_INSERTION_REQUEST) + strcat( pBuf, "INSERTION_REQUEST " ); + + if(mask & CS_EVENT_EJECTION_REQUEST) + strcat( pBuf, "EJECTION_REQUEST " ); + + if(mask & CS_EVENT_MTD_REQUEST) + strcat( pBuf, "MTD_REQUEST " ); + + if(mask & CS_EVENT_ERASE_COMPLETE) + strcat( pBuf, "ERASE_COMPLETE " ); + + if(mask & CS_EVENT_REQUEST_ATTENTION) + strcat( pBuf, "REQUEST_ATTENTION " ); + + if(mask & CS_EVENT_CB_DETECT) + strcat( pBuf, "CB_DETECT " ); + + if(mask & CS_EVENT_3VCARD) + strcat( pBuf, "3VCARD " ); + + if(mask & CS_EVENT_XVCARD) + strcat( pBuf, "XVCARD " ); + + + if( *pBuf ) { + pBuf[strlen(pBuf) - 1] = '\0'; + } else { + if( mask != 0x0 ) { + sprintf( pBuf, "<<0x%08x>>", mask ); + } + } + + return pBuf; +} // DbgEvent +/*============================================================================*/ + +#endif /* DBG */ diff --git a/drivers/staging/wlags49_h2/wl_cs.h b/drivers/staging/wlags49_h2/wl_cs.h new file mode 100644 index 0000000000000000000000000000000000000000..2a0e67450fbe6c013004c256ac622feec61ee2e9 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_cs.h @@ -0,0 +1,95 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * Header describing information required for the driver to support PCMCIA. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +#ifndef __WL_CS_H__ +#define __WL_CS_H__ + + + + +/******************************************************************************* + * function protoypes + ******************************************************************************/ + +void wl_adapter_insert(struct pcmcia_device *link); + +void wl_adapter_release(struct pcmcia_device *link); + +int wl_adapter_event(event_t event, int priority, event_callback_args_t *args ); + +int wl_adapter_init_module( void ); + +void wl_adapter_cleanup_module( void ); + +int wl_adapter_open(struct net_device *dev); + +int wl_adapter_close(struct net_device *dev); + +int wl_adapter_is_open(struct net_device *dev); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) +void cs_error(client_handle_t handle, int func, int ret); +#endif + +const char *DbgEvent( int mask ); + + + +#endif // __WL_CS_H__ diff --git a/drivers/staging/wlags49_h2/wl_enc.c b/drivers/staging/wlags49_h2/wl_enc.c new file mode 100644 index 0000000000000000000000000000000000000000..48c44c8fdb28e9e3470f72086f6eb40a2451cf2e --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_enc.c @@ -0,0 +1,231 @@ + +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * This file defines functions related to WEP key coding/decoding. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +/******************************************************************************* + * include files + ******************************************************************************/ +#include + +#include +#include + +#include + + + + +/******************************************************************************* + * global definitions + ******************************************************************************/ +#if DBG + +extern dbg_info_t *DbgInfo; + +#endif /* DBG */ + + + + +/******************************************************************************* + * wl_wep_code() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function encodes a set of wep keys for privacy + * + * PARAMETERS: + * + * szCrypt - + * szDest - + * Data - + * nLen - + * + * RETURNS: + * + * OK + * + ******************************************************************************/ +int wl_wep_code( char *szCrypt, char *szDest, void *Data, int nLen ) +{ + int i; + int t; + int k ; + char bits; + char *szData = (char *) Data; + /*------------------------------------------------------------------------*/ + + + for( i = bits = 0 ; i < MACADDRESS_STR_LEN; i++ ) { + bits ^= szCrypt[i]; + bits += szCrypt[i]; + } + + for( i = t = *szDest = 0; i < nLen; i++, t++ ) { + k = szData[i] ^ ( bits + i ); + + + switch( i % 3 ) { + + case 0 : + + szDest[t] = ((k & 0xFC) >> 2) + CH_START ; + szDest[t+1] = ((k & 0x03) << 4) + CH_START ; + szDest[t+2] = '\0'; + + break; + + + case 1 : + + szDest[t] += (( k & 0xF0 ) >> 4 ); + szDest[t+1] = (( k & 0x0F ) << 2 ) + CH_START ; + szDest[t+2] = '\0'; + + break; + + + case 2 : + + szDest[t] += (( k & 0xC0 ) >> 6 ); + szDest[t+1] = ( k & 0x3F ) + CH_START ; + szDest[t+2] = '\0'; + t++; + + break; + } + } + + return( strlen( szDest )) ; + +} +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_wep_decode() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function decodes a set of WEP keys for use by the card. + * + * PARAMETERS: + * + * szCrypt - + * szDest - + * Data - + * + * RETURNS: + * + * OK + * + ******************************************************************************/ +int wl_wep_decode( char *szCrypt, void *Dest, char *szData ) +{ + int i; + int t; + int nLen; + char bits; + char *szDest = Dest; + /*------------------------------------------------------------------------*/ + + + for( i = bits = 0 ; i < 12; i++ ) { + bits ^= szCrypt[i] ; + bits += szCrypt[i] ; + } + + nLen = ( strlen( szData ) * 3) / 4 ; + + for( i = t = 0; i < nLen; i++, t++ ) { + switch( i % 3 ) { + case 0 : + + szDest[i] = ((( szData[t]-CH_START ) & 0x3f ) << 2 ) + + ((( szData[t+1]-CH_START ) & 0x30 ) >> 4 ); + break; + + + case 1 : + szDest[i] = ((( szData[t]-CH_START ) & 0x0f ) << 4 ) + + ((( szData[t+1]-CH_START ) & 0x3c ) >> 2 ); + break; + + + case 2 : + szDest[i] = ((( szData[t]-CH_START ) & 0x03 ) << 6 ) + + (( szData[t+1]-CH_START ) & 0x3f ); + t++; + break; + } + + szDest[i] ^= ( bits + i ) ; + + } + + return( i ) ; + +} +/*============================================================================*/ + diff --git a/drivers/staging/wlags49_h2/wl_enc.h b/drivers/staging/wlags49_h2/wl_enc.h new file mode 100644 index 0000000000000000000000000000000000000000..b4f54d81f311eede8b262a9d9077416fbd07ec63 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_enc.h @@ -0,0 +1,118 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * Header for performing coding/decoding of the WEP keys. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +#ifndef __WAVELAN2_ENCRYPTION_H__ +#define __WAVELAN2_ENCRYPTION_H__ + + + + +/******************************************************************************* + * constant definitions + ******************************************************************************/ +#define CRYPT_CODE "57617665A5D6" +#define ENCRYPTION_LEN 102 +#define ENCRYPTION_MAGIC 0x48576877L // HWhw +#define DEF_CRYPT_STR "G?TIUEA]d5MAdZV'eUb&&6.)'&:,'VF/(FR2)6^5*'*8*W6;+GB>,7NA-'ZD-X&G.H2J/8>M0(JP0XVS1HbV29.Y3):\\3YF_4IRb56" + +#define DEFAULT_CRYPT_MAC "W\x01\x6B\x66\xA5\x5A" +#define CH_START '&' +#define MACADDRESS_STR_LEN 12 + +#define KEY_LEN 14 +#define NUM_KEYS 4 + +#define KEY_LENGTH_NONE_ASCII 0 +#define KEY_LENGTH_64_BIT_ASCII 5 +#define KEY_LENGTH_128_BIT_ASCII 13 + +#define KEY_LENGTH_NONE_HEX ( KEY_LENGTH_NONE_ASCII * sizeof( unsigned short )) +#define KEY_LENGTH_64_BIT_HEX ( KEY_LENGTH_64_BIT_ASCII * sizeof( unsigned short )) +#define KEY_LENGTH_128_BIT_HEX ( KEY_LENGTH_128_BIT_ASCII * sizeof( unsigned short )) + + + + +/******************************************************************************* + * type definitions + ******************************************************************************/ +typedef struct _encstct +{ + hcf_32 dwMagic; + hcf_16 wTxKeyID; + hcf_16 wEnabled; + CFG_DEFAULT_KEYS_STRCT EncStr; +} +ENCSTRCT, *PENCSTRCT; + + + + +/******************************************************************************* + * function prrottypes + ******************************************************************************/ +int wl_wep_code( char *szCrypt, char *szDest, void *Data, int nLen ); + +int wl_wep_decode( char *szCrypt, void *Dest, char *szData ); + + + + +#endif // __WAVELAN2_ENCRYPTION_H__ diff --git a/drivers/staging/wlags49_h2/wl_if.h b/drivers/staging/wlags49_h2/wl_if.h new file mode 100644 index 0000000000000000000000000000000000000000..ed2b4135a10e02591e6cb255393247931ae12e48 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_if.h @@ -0,0 +1,234 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * Driver common header for info needed by driver source and user-space + * processes communicating with the driver. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +#ifndef __WAVELAN2_IF_H__ +#define __WAVELAN2_IF_H__ + + + + +/******************************************************************************* + * constant definitions + ******************************************************************************/ +#define MAX_LTV_BUF_SIZE (512 - (sizeof(hcf_16) * 2)) + +#define HCF_TALLIES_SIZE (sizeof(CFG_HERMES_TALLIES_STRCT) + \ + (sizeof(hcf_16) * 2)) + +#define HCF_MAX_MULTICAST 16 +#define HCF_MAX_NAME_LEN 32 +#define MAX_LINE_SIZE 256 +#define HCF_NUM_IO_PORTS 0x80 +#define TX_TIMEOUT ((800 * HZ) / 1000) + + +//#define HCF_MIN_COMM_QUALITY 0 +//#define HCF_MAX_COMM_QUALITY 92 +//#define HCF_MIN_SIGNAL_LEVEL 47 +//#define HCF_MAX_SIGNAL_LEVEL 138 +//#define HCF_MIN_NOISE_LEVEL 47 +//#define HCF_MAX_NOISE_LEVEL 138 +//#define HCF_0DBM_OFFSET 149 + +// PE1DNN +// Better data from the real world. Not scientific but empirical data gathered +// from a Thomson Speedtouch 110 which is identified as: +// PCMCIA Info: "Agere Systems" "Wireless PC Card Model 0110" +// Manufacture ID: 0156,0003 +// Lowest measurment for noise floor seen is value 54 +// Highest signal strength in close proximity to the AP seen is value 118 +// Very good must be arround 100 (otherwise its never "full scale" +// All other constants are derrived from these. This makes the signal gauge +// work for me... +#define HCF_MIN_SIGNAL_LEVEL 54 +#define HCF_MAX_SIGNAL_LEVEL 100 +#define HCF_MIN_NOISE_LEVEL HCF_MIN_SIGNAL_LEVEL +#define HCF_MAX_NOISE_LEVEL HCF_MAX_SIGNAL_LEVEL +#define HCF_0DBM_OFFSET (HCF_MAX_SIGNAL_LEVEL + 1) +#define HCF_MIN_COMM_QUALITY 0 +#define HCF_MAX_COMM_QUALITY (HCF_MAX_SIGNAL_LEVEL - HCF_MIN_NOISE_LEVEL + 1) + + +/* For encryption (WEP) */ +#define MIN_KEY_SIZE 5 // 40 bits RC4 - WEP +#define MAX_KEY_SIZE 13 // 104 bits +#define MAX_KEYS 4 + +#define RADIO_CHANNELS 14 +#define RADIO_SENSITIVITY_LEVELS 3 +#define RADIO_TX_POWER_MWATT 32 +#define RADIO_TX_POWER_DBM 15 + +#define MIN_RTS_BYTES 0 +#define MAX_RTS_BYTES 2347 + +#define MAX_RATES 8 +#define MEGABIT 1024*1024 + +#define HCF_FAILURE 0xFF +#define UIL_FAILURE 0xFF +#define CFG_UIL_CONNECT 0xA123 // Define differently? +#define CFG_UIL_CONNECT_ACK_CODE 0x5653435A // VSCZ +#define WVLAN2_UIL_CONNECTED (0x01L << 0) +#define WVLAN2_UIL_BUSY (0x01L << 1) + + + + +/******************************************************************************* + * driver ioctl interface + ******************************************************************************/ +#define WVLAN2_IOCTL_UIL SIOCDEVPRIVATE + +/* The UIL Interface used in conjunction with the WVLAN2_IOCTL_UIL code above + is defined in mdd.h. A quick reference of the UIL codes is listed below */ +/* +UIL_FUN_CONNECT +UIL_FUN_DISCONNECT +UIL_FUN_ACTION + UIL_ACT_BLOCK + UIL_ACT_UNBLOCK + UIL_ACT_SCA + UIL_ACT_DIAG + UIL_ACT_APPLY +UIL_FUN_SEND_DIAG_MSG +UIL_FUN_GET_INFO +UIL_FUN_PUT_INFO +*/ + +#define SIOCSIWNETNAME SIOCDEVPRIVATE+1 +#define SIOCGIWNETNAME SIOCDEVPRIVATE+2 +#define SIOCSIWSTANAME SIOCDEVPRIVATE+3 +#define SIOCGIWSTANAME SIOCDEVPRIVATE+4 +#define SIOCSIWPORTTYPE SIOCDEVPRIVATE+5 +#define SIOCGIWPORTTYPE SIOCDEVPRIVATE+6 + +/* IOCTL code for the RTS interface */ +#define WL_IOCTL_RTS SIOCDEVPRIVATE+7 + +/* IOCTL subcodes for WL_IOCTL_RTS */ +#define WL_IOCTL_RTS_READ 1 +#define WL_IOCTL_RTS_WRITE 2 +#define WL_IOCTL_RTS_BATCH_READ 3 +#define WL_IOCTL_RTS_BATCH_WRITE 4 + + +/******************************************************************************* + * STRUCTURE DEFINITIONS + ******************************************************************************/ +typedef struct +{ + __u16 length; + __u8 name[HCF_MAX_NAME_LEN]; +} +wvName_t; + + +typedef struct +{ + hcf_16 len; + hcf_16 typ; + union + { + hcf_8 u8[MAX_LTV_BUF_SIZE / sizeof(hcf_8)]; + hcf_16 u16[MAX_LTV_BUF_SIZE / sizeof(hcf_16)]; + hcf_32 u32[MAX_LTV_BUF_SIZE / sizeof(hcf_32)]; + } u; +} +ltv_t; + + +struct uilreq +{ + union + { + char ifrn_name[IFNAMSIZ]; + } ifr_ifrn; + + IFBP hcfCtx; + __u8 command; + __u8 result; + + /* The data field in this structure is typically an LTV of some type. The + len field is the size of the buffer in bytes, as opposed to words (like + the L-field in the LTV */ + __u16 len; + void *data; +}; + + +struct rtsreq +{ + union + { + char ifrn_name[IFNAMSIZ]; + } + ifr_ifrn; + + __u16 typ; + __u16 reg; + __u16 len; + __u16 *data; +}; + + +#endif // __WAVELAN2_IF_H__ + diff --git a/drivers/staging/wlags49_h2/wl_internal.h b/drivers/staging/wlags49_h2/wl_internal.h new file mode 100644 index 0000000000000000000000000000000000000000..466fb6215acd1708dee4def0edc1a5fe6db87100 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_internal.h @@ -0,0 +1,1056 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * Header for defintions and macros internal to the drvier. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +#ifndef __WAVELAN2_H__ +#define __WAVELAN2_H__ + + + + +/******************************************************************************* + * include files + ******************************************************************************/ +#include +#ifdef BUS_PCMCIA +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) +#include +#endif +#include +#include +#include +#include +#include +#include +#endif // BUS_PCMCIA + +#ifdef HAS_WIRELESS_EXTENSIONS +#include +#if WIRELESS_EXT > 13 +#include +#endif // WIRELESS_EXT > 13 +#define USE_DBM +#define RETURN_CURRENT_NETWORKNAME +#define USE_FREQUENCY +#endif // HAS_WIRELESS_EXTENSIONS/ + +#include + +#include + + + + +/******************************************************************************* + * constant definitions + ******************************************************************************/ +#define p_u8 __u8 +#define p_s8 __s8 +#define p_u16 __u16 +#define p_s16 __s16 +#define p_u32 __u32 +#define p_s32 __s32 +#define p_char char + +#define MAX_KEY_LEN (2 + (13 * 2)) // 0x plus 13 hex digit pairs +#define MB_SIZE 1024 +#define MAX_ENC_LEN 104 + +#define MAX_SCAN_TIME_SEC 8 +#define MAX_NAPS 32 + +#define CFG_MB_INFO 0x0820 //Mail Box Info Block + +#define NUM_WDS_PORTS 6 + +#define WVLAN_MAX_LOOKAHEAD (HCF_MAX_MSG+46) /* as per s0005MIC_4.doc */ + + +/* Min/Max/Default Parameter Values */ +#if 0 //;? (HCF_TYPE) & HCF_TYPE_AP +//;? why this difference depending on compile option, seems to me it should depend on runtime if anything +#define PARM_DEFAULT_SSID "LinuxAP" +#else +#define PARM_DEFAULT_SSID "ANY" +#endif // HCF_TYPE_AP + +#define PARM_MIN_NAME_LEN 1 +#define PARM_MAX_NAME_LEN 32 + + +/* The following definitions pertain to module and profile parameters */ +// #define PARM_AP_MODE APMode +// #define PARM_NAME_AP_MODE TEXT("APMode") +// #define PARM_DEFAULT_AP_MODE FALSE + +#define PARM_AUTHENTICATION Authentication +#define PARM_NAME_AUTHENTICATION TEXT("Authentication") +#define PARM_MIN_AUTHENTICATION 1 +#define PARM_MAX_AUTHENTICATION 2 +#define PARM_DEFAULT_AUTHENTICATION 1 + +#define PARM_AUTH_KEY_MGMT_SUITE AuthKeyMgmtSuite +#define PARM_NAME_AUTH_KEY_MGMT_SUITE TEXT("AuthKeyMgmtSuite") +#define PARM_MIN_AUTH_KEY_MGMT_SUITE 0 +#define PARM_MAX_AUTH_KEY_MGMT_SUITE 4 +#define PARM_DEFAULT_AUTH_KEY_MGMT_SUITE 0 + +#define PARM_BRSC_2GHZ BRSC2GHz +#define PARM_NAME_BRSC_2GHZ TEXT("BRSC2GHz") +#define PARM_MIN_BRSC 0x0000 +#define PARM_MAX_BRSC 0x0FFF +#define PARM_DEFAULT_BRSC_2GHZ 0x000F + +#define PARM_BRSC_5GHZ BRSC5GHz +#define PARM_NAME_BRSC_5GHZ TEXT("BRSC5GHz") +#define PARM_DEFAULT_BRSC_5GHZ 0x0150 + +#define PARM_COEXISTENCE Coexistence +#define PARM_NAME_COEXISTENCE TEXT("Coexistence") +#define PARM_MIN_COEXISTENCE 0x0000 +#define PARM_MAX_COEXISTENCE 0x0007 +#define PARM_DEFAULT_COEXISTENCE 0x0000 + +#define PARM_CONFIGURED Configured +#define PARM_NAME_CONFIGURED TEXT("Configured") + +#define PARM_CONNECTION_CONTROL ConnectionControl +#define PARM_NAME_CONNECTION_CONTROL TEXT("ConnectionControl") +#define PARM_MIN_CONNECTION_CONTROL 0 +#define PARM_MAX_CONNECTION_CONTROL 3 +#define PARM_DEFAULT_CONNECTION_CONTROL 2 + +#define PARM_CREATE_IBSS CreateIBSS +#define PARM_NAME_CREATE_IBSS TEXT("CreateIBSS") +#define PARM_DEFAULT_CREATE_IBSS FALSE +#define PARM_DEFAULT_CREATE_IBSS_STR "N" + +#define PARM_DEBUG_FLAG DebugFlag +#define PARM_NAME_DEBUG_FLAG TEXT("DebugFlag") +#define PARM_MIN_DEBUG_FLAG 0 +#define PARM_MAX_DEBUG_FLAG 0xFFFF +#define PARM_DEFAULT_DEBUG_FLAG 0xFFFF + +#define PARM_DESIRED_SSID DesiredSSID +#define PARM_NAME_DESIRED_SSID TEXT("DesiredSSID") + +#define PARM_DOWNLOAD_FIRMWARE DownloadFirmware +#define PARM_NAME_DOWNLOAD_FIRMWARE TEXT("DownloadFirmware") + +#define PARM_DRIVER_ENABLE DriverEnable +#define PARM_NAME_DRIVER_ENABLE TEXT("DriverEnable") +#define PARM_DEFAULT_DRIVER_ENABLE TRUE + +#define PARM_ENABLE_ENCRYPTION EnableEncryption +#define PARM_NAME_ENABLE_ENCRYPTION TEXT("EnableEncryption") +#define PARM_MIN_ENABLE_ENCRYPTION 0 +#define PARM_MAX_ENABLE_ENCRYPTION 7 +#define PARM_DEFAULT_ENABLE_ENCRYPTION 0 + +#define PARM_ENCRYPTION Encryption +#define PARM_NAME_ENCRYPTION TEXT("Encryption") + +#define PARM_EXCLUDE_UNENCRYPTED ExcludeUnencrypted +#define PARM_NAME_EXCLUDE_UNENCRYPTED TEXT("ExcludeUnencrypted") +#define PARM_DEFAULT_EXCLUDE_UNENCRYPTED TRUE +#define PARM_DEFAULT_EXCLUDE_UNENCRYPTED_STR "N" + +#define PARM_INTRA_BSS_RELAY IntraBSSRelay +#define PARM_NAME_INTRA_BSS_RELAY TEXT("IntraBSSRelay") +#define PARM_DEFAULT_INTRA_BSS_RELAY TRUE +#define PARM_DEFAULT_INTRA_BSS_RELAY_STR "Y" + +#define PARM_KEY1 Key1 +#define PARM_NAME_KEY1 TEXT("Key1") +#define PARM_KEY2 Key2 +#define PARM_NAME_KEY2 TEXT("Key2") +#define PARM_KEY3 Key3 +#define PARM_NAME_KEY3 TEXT("Key3") +#define PARM_KEY4 Key4 +#define PARM_NAME_KEY4 TEXT("Key4") + +//;? #define PARM_KEY_FORMAT AsciiHex +//;? #define PARM_NAME_KEY_FORMAT TEXT("AsciiHex") + +#define PARM_LOAD_BALANCING LoadBalancing +#define PARM_NAME_LOAD_BALANCING TEXT("LoadBalancing") +#define PARM_DEFAULT_LOAD_BALANCING TRUE +#define PARM_DEFAULT_LOAD_BALANCING_STR "Y" + +#define PARM_MAX_DATA_LENGTH MaxDataLength +#define PARM_NAME_MAX_DATA_LENGTH TEXT("MaxDataLength") + +#define PARM_MAX_SLEEP MaxSleepDuration +#define PARM_NAME_MAX_SLEEP TEXT("MaxSleepDuration") +#define PARM_MIN_MAX_PM_SLEEP 1 //;?names nearly right? +#define PARM_MAX_MAX_PM_SLEEP 65535 +#define PARM_DEFAULT_MAX_PM_SLEEP 100 + +#define PARM_MEDIUM_DISTRIBUTION MediumDistribution +#define PARM_NAME_MEDIUM_DISTRIBUTION TEXT("MediumDistribution") +#define PARM_DEFAULT_MEDIUM_DISTRIBUTION TRUE +#define PARM_DEFAULT_MEDIUM_DISTRIBUTION_STR "Y" + +#define PARM_MICROWAVE_ROBUSTNESS MicroWaveRobustness +#define PARM_NAME_MICROWAVE_ROBUSTNESS TEXT("MicroWaveRobustness") +#define PARM_DEFAULT_MICROWAVE_ROBUSTNESS FALSE +#define PARM_DEFAULT_MICROWAVE_ROBUSTNESS_STR "N" + +#define PARM_MULTICAST_PM_BUFFERING MulticastPMBuffering +#define PARM_NAME_MULTICAST_PM_BUFFERING TEXT("MulticastPMBuffering") +#define PARM_DEFAULT_MULTICAST_PM_BUFFERING TRUE +#define PARM_DEFAULT_MULTICAST_PM_BUFFERING_STR "Y" + +#define PARM_MULTICAST_RATE MulticastRate +#define PARM_NAME_MULTICAST_RATE TEXT("MulticastRate") +#ifdef WARP +#define PARM_MIN_MULTICAST_RATE 0x0001 +#define PARM_MAX_MULTICAST_RATE 0x0fff +#define PARM_DEFAULT_MULTICAST_RATE_2GHZ 0x0004 +#define PARM_DEFAULT_MULTICAST_RATE_5GHZ 0x0010 +#else +#define PARM_MIN_MULTICAST_RATE 0x0001 +#define PARM_MAX_MULTICAST_RATE 0x0004 +#define PARM_DEFAULT_MULTICAST_RATE_2GHZ 0x0002 +#define PARM_DEFAULT_MULTICAST_RATE_5GHZ 0x0000 +#endif // WARP + +#define PARM_MULTICAST_RX MulticastReceive +#define PARM_NAME_MULTICAST_RX TEXT("MulticastReceive") +#define PARM_DEFAULT_MULTICAST_RX TRUE +#define PARM_DEFAULT_MULTICAST_RX_STR "Y" + +#define PARM_NETWORK_ADDR NetworkAddress +#define PARM_NAME_NETWORK_ADDR TEXT("NetworkAddress") +#define PARM_DEFAULT_NETWORK_ADDR { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define PARM_NETWORK_TYPE NetworkType +#define PARM_NAME_NETWORK_TYPE TEXT("NetworkType") +#define PARM_DEFAULT_NETWORK_TYPE 0 + +#define PARM_OWN_ATIM_WINDOW OwnATIMWindow +#define PARM_NAME_OWN_ATIM_WINDOW TEXT("OwnATIMWindow") +#define PARM_MIN_OWN_ATIM_WINDOW 0 +#define PARM_MAX_OWN_ATIM_WINDOW 100 +#define PARM_DEFAULT_OWN_ATIM_WINDOW 0 + +#define PARM_OWN_BEACON_INTERVAL OwnBeaconInterval +#define PARM_NAME_OWN_BEACON_INTERVAL TEXT("OwnBeaconInterval") +#define PARM_MIN_OWN_BEACON_INTERVAL 20 +#define PARM_MAX_OWN_BEACON_INTERVAL 200 +#define PARM_DEFAULT_OWN_BEACON_INTERVAL 100 + +#define PARM_OWN_CHANNEL OwnChannel +#define PARM_NAME_OWN_CHANNEL TEXT("OwnChannel") +#define PARM_MIN_OWN_CHANNEL 1 +#define PARM_MAX_OWN_CHANNEL 161 +#define PARM_DEFAULT_OWN_CHANNEL 10 + +#define PARM_OWN_DTIM_PERIOD OwnDTIMPeriod +#define PARM_NAME_OWN_DTIM_PERIOD TEXT("OwnDTIMPeriod") +#define PARM_MIN_OWN_DTIM_PERIOD 1 +#define PARM_MAX_OWN_DTIM_PERIOD 65535 +#define PARM_DEFAULT_OWN_DTIM_PERIOD 1 + +#define PARM_OWN_NAME OwnName +#define PARM_NAME_OWN_NAME TEXT("OwnName") +#define PARM_DEFAULT_OWN_NAME "Linux" + +#define PARM_OWN_SSID OwnSSID +#define PARM_NAME_OWN_SSID TEXT("OwnSSID") + +#define PARM_PM_ENABLED PMEnabled +#define PARM_NAME_PM_ENABLED TEXT("PMEnabled") +#define PARM_MAX_PM_ENABLED 3 + +#define PARM_PMEPS PMEPS +#define PARM_NAME_PMEPS TEXT("PMEPS") + +#define PARM_PM_HOLDOVER_DURATION PMHoldoverDuration +#define PARM_NAME_PM_HOLDOVER_DURATION TEXT("PMHoldoverDuration") +#define PARM_MIN_PM_HOLDOVER_DURATION 1 +#define PARM_MAX_PM_HOLDOVER_DURATION 1000 +#define PARM_DEFAULT_PM_HOLDOVER_DURATION 100 + +#define PARM_PM_MODE PowerMode +#define PARM_NAME_PM_MODE TEXT("PowerMode") + +#define PARM_PORT_TYPE PortType +#define PARM_NAME_PORT_TYPE TEXT("PortType") +#define PARM_MIN_PORT_TYPE 1 +#define PARM_MAX_PORT_TYPE 3 +#define PARM_DEFAULT_PORT_TYPE 1 + +#define PARM_PROMISCUOUS_MODE PromiscuousMode +#define PARM_NAME_PROMISCUOUS_MODE TEXT("PromiscuousMode") +#define PARM_DEFAULT_PROMISCUOUS_MODE FALSE +#define PARM_DEFAULT_PROMISCUOUS_MODE_STR "N" + +#define PARM_REJECT_ANY RejectANY +#define PARM_NAME_REJECT_ANY TEXT("RejectANY") +#define PARM_DEFAULT_REJECT_ANY FALSE +#define PARM_DEFAULT_REJECT_ANY_STR "N" + +#define PARM_RTS_THRESHOLD RTSThreshold +#define PARM_NAME_RTS_THRESHOLD TEXT("RTSThreshold") +#define PARM_MIN_RTS_THRESHOLD 0 +#define PARM_MAX_RTS_THRESHOLD 2347 +#define PARM_DEFAULT_RTS_THRESHOLD 2347 + +#define PARM_RTS_THRESHOLD1 RTSThreshold1 +#define PARM_NAME_RTS_THRESHOLD1 TEXT("RTSThreshold1") +#define PARM_RTS_THRESHOLD2 RTSThreshold2 +#define PARM_NAME_RTS_THRESHOLD2 TEXT("RTSThreshold2") +#define PARM_RTS_THRESHOLD3 RTSThreshold3 +#define PARM_NAME_RTS_THRESHOLD3 TEXT("RTSThreshold3") +#define PARM_RTS_THRESHOLD4 RTSThreshold4 +#define PARM_NAME_RTS_THRESHOLD4 TEXT("RTSThreshold4") +#define PARM_RTS_THRESHOLD5 RTSThreshold5 +#define PARM_NAME_RTS_THRESHOLD5 TEXT("RTSThreshold5") +#define PARM_RTS_THRESHOLD6 RTSThreshold6 +#define PARM_NAME_RTS_THRESHOLD6 TEXT("RTSThreshold6") + +#define PARM_SRSC_2GHZ SRSC2GHz +#define PARM_NAME_SRSC_2GHZ TEXT("SRSC2GHz") +#define PARM_MIN_SRSC 0x0000 +#define PARM_MAX_SRSC 0x0FFF +#define PARM_DEFAULT_SRSC_2GHZ 0x0FFF + +#define PARM_SRSC_5GHZ SRSC5GHz +#define PARM_NAME_SRSC_5GHZ TEXT("SRSC5GHz") +#define PARM_DEFAULT_SRSC_5GHZ 0x0FF0 + +#define PARM_SYSTEM_SCALE SystemScale +#define PARM_NAME_SYSTEM_SCALE TEXT("SystemScale") +#define PARM_MIN_SYSTEM_SCALE 1 +#define PARM_MAX_SYSTEM_SCALE 5 +#define PARM_DEFAULT_SYSTEM_SCALE 1 + +#define PARM_TX_KEY TxKey +#define PARM_NAME_TX_KEY TEXT("TxKey") +#define PARM_MIN_TX_KEY 1 +#define PARM_MAX_TX_KEY 4 +#define PARM_DEFAULT_TX_KEY 1 + +#define PARM_TX_POW_LEVEL TxPowLevel +#define PARM_NAME_TX_POW_LEVEL TEXT("TxPowLevel") +#define PARM_MIN_TX_POW_LEVEL 1 // 20 dBm +#define PARM_MAX_TX_POW_LEVEL 6 // 8 dBm +#define PARM_DEFAULT_TX_POW_LEVEL 3 // 15 dBm + +#define PARM_TX_RATE TxRateControl +#define PARM_NAME_TX_RATE TEXT("TxRateControl") +#define PARM_MIN_TX_RATE 0x0001 +#ifdef WARP +#define PARM_MAX_TX_RATE 0x0FFF +#define PARM_DEFAULT_TX_RATE_2GHZ 0x0FFF +#define PARM_DEFAULT_TX_RATE_5GHZ 0x0FF0 +#else +#define PARM_MAX_TX_RATE 0x0007 +#define PARM_DEFAULT_TX_RATE_2GHZ 0x0003 +#define PARM_DEFAULT_TX_RATE_5GHZ 0x0000 +#endif // WARP + +#define PARM_TX_RATE1 TxRateControl1 +#define PARM_NAME_TX_RATE1 TEXT("TxRateControl1") +#define PARM_TX_RATE2 TxRateControl2 +#define PARM_NAME_TX_RATE2 TEXT("TxRateControl2") +#define PARM_TX_RATE3 TxRateControl3 +#define PARM_NAME_TX_RATE3 TEXT("TxRateControl3") +#define PARM_TX_RATE4 TxRateControl4 +#define PARM_NAME_TX_RATE4 TEXT("TxRateControl4") +#define PARM_TX_RATE5 TxRateControl5 +#define PARM_NAME_TX_RATE5 TEXT("TxRateControl5") +#define PARM_TX_RATE6 TxRateControl6 +#define PARM_NAME_TX_RATE6 TEXT("TxRateControl6") + +#define PARM_VENDORDESCRIPTION VendorDescription +#define PARM_NAME_VENDORDESCRIPTION TEXT("VendorDescription") + +#define PARM_WDS_ADDRESS WDSAddress +#define PARM_NAME_WDS_ADDRESS TEXT("WDSAddress") + +#define PARM_WDS_ADDRESS1 WDSAddress1 +#define PARM_NAME_WDS_ADDRESS1 TEXT("WDSAddress1") +#define PARM_WDS_ADDRESS2 WDSAddress2 +#define PARM_NAME_WDS_ADDRESS2 TEXT("WDSAddress2") +#define PARM_WDS_ADDRESS3 WDSAddress3 +#define PARM_NAME_WDS_ADDRESS3 TEXT("WDSAddress3") +#define PARM_WDS_ADDRESS4 WDSAddress4 +#define PARM_NAME_WDS_ADDRESS4 TEXT("WDSAddress4") +#define PARM_WDS_ADDRESS5 WDSAddress5 +#define PARM_NAME_WDS_ADDRESS5 TEXT("WDSAddress5") +#define PARM_WDS_ADDRESS6 WDSAddress6 +#define PARM_NAME_WDS_ADDRESS6 TEXT("WDSAddress6") + +/* +#define PARM_LONG_RETRY_LIMIT LongRetryLimit +#define PARM_NAME_LONG_RETRY_LIMIT TEXT("LongRetryLimit") +#define PARM_MIN_LONG_RETRY_LIMIT 1 +#define PARM_MAX_LONG_RETRY_LIMIT 15 +#define PARM_DEFAULT_LONG_RETRY_LIMIT 3 + + +#define PARM_PROBE_DATA_RATES ProbeDataRates +#define PARM_NAME_PROBE_DATA_RATES TEXT("ProbeDataRates") +#define PARM_MIN_PROBE_DATA_RATES 0x0000 +#define PARM_MAX_PROBE_DATA_RATES 0x0FFF +#define PARM_DEFAULT_PROBE_DATA_RATES_2GHZ 0x0002 +#define PARM_DEFAULT_PROBE_DATA_RATES_5GHZ 0x0010 + +#define PARM_SHORT_RETRY_LIMIT ShortRetryLimit +#define PARM_NAME_SHORT_RETRY_LIMIT TEXT("ShortRetryLimit") +#define PARM_MIN_SHORT_RETRY_LIMIT 1 +#define PARM_MAX_SHORT_RETRY_LIMIT 15 +#define PARM_DEFAULT_SHORT_RETRY_LIMIT 7 + + +*/ + +/******************************************************************************* + * state definitions + ******************************************************************************/ +/* The following constants are used to track state the device */ +#define WL_FRIMWARE_PRESENT 1 // Download if needed +#define WL_FRIMWARE_NOT_PRESENT 0 // Skip over download, assume its already there +#define WL_HANDLING_INT 1 // Actually call the HCF to switch interrupts on/off +#define WL_NOT_HANDLING_INT 0 // Not yet handling interrupts, do not switch on/off + +/******************************************************************************* + * macro definitions + ******************************************************************************/ +/* The following macro ensures that no symbols are exported, minimizing the + chance of a symbol collision in the kernel */ +// EXPORT_NO_SYMBOLS; + +#define NELEM(arr) (sizeof(arr) / sizeof(arr[0])) + +#define WVLAN_VALID_MAC_ADDRESS( x ) \ +((x[0]!=0xFF) && (x[1]!=0xFF) && (x[2]!=0xFF) && (x[3]!=0xFF) && (x[4]!=0xFF) && (x[5]!=0xFF)) + + + + +/******************************************************************************* + * type definitions + ******************************************************************************/ +#undef FALSE +#undef TRUE + +typedef enum +{ + FALSE = 0, + TRUE = 1 +} +bool_t; + + +typedef struct _ScanResult +{ + //hcf_16 len; + //hcf_16 typ; + int scan_complete; + int num_aps; + SCAN_RS_STRCT APTable [MAX_NAPS]; +} +ScanResult; + + +typedef struct _LINK_STATUS_STRCT +{ + hcf_16 len; + hcf_16 typ; + hcf_16 linkStatus; /* 1..5 */ +} +LINK_STATUS_STRCT; + + +typedef struct _ASSOC_STATUS_STRCT +{ + hcf_16 len; + hcf_16 typ; + hcf_16 assocStatus; /* 1..3 */ + hcf_8 staAddr[ETH_ALEN]; + hcf_8 oldApAddr[ETH_ALEN]; +} +ASSOC_STATUS_STRCT; + + +typedef struct _SECURITY_STATUS_STRCT +{ + hcf_16 len; + hcf_16 typ; + hcf_16 securityStatus; /* 1..3 */ + hcf_8 staAddr[ETH_ALEN]; + hcf_16 reason; +} +SECURITY_STATUS_STRCT; + +#define WVLAN_WMP_PDU_TYPE_LT_REQ 0x00 +#define WVLAN_WMP_PDU_TYPE_LT_RSP 0x01 +#define WVLAN_WMP_PDU_TYPE_APL_REQ 0x02 +#define WVLAN_WMP_PDU_TYPE_APL_RSP 0x03 + +typedef struct wvlan_eth_hdr +{ + unsigned char dst[ETH_ALEN]; /* Destination address. */ + unsigned char src[ETH_ALEN]; /* Source address. */ + unsigned short len; /* Length of the PDU. */ +} +WVLAN_ETH_HDR, *PWVLAN_ETH_HDR; + +typedef struct wvlan_llc_snap +{ + unsigned char dsap; /* DSAP (0xAA) */ + unsigned char ssap; /* SSAP (0xAA) */ + unsigned char ctrl; /* Control (0x03) */ + unsigned char oui[3]; /* Organization Unique ID (00-60-1d). */ + unsigned char specid[2]; /* Specific ID code (00-01). */ +} +WVLAN_LLC_SNAP, *PWVLAN_LLC_SNAP; + + +typedef struct wvlan_lt_hdr +{ + unsigned char version; /* Version (0x00) */ + unsigned char type; /* PDU type: 0-req/1-resp. */ + unsigned short id; /* Identifier to associate resp to req. */ +} +WVLAN_LT_HDR, *PWVLAN_LT_HDR; + + +typedef struct wvlan_wmp_hdr +{ + unsigned char version; /* Version */ + unsigned char type; /* PDU type */ +} +WVLAN_WMP_HDR, *PWVLAN_WMP_HDR; + + +#define FILLER_SIZE 1554 +#define TEST_PATTERN_SIZE 54 + + +typedef struct wvlan_lt_req +{ + unsigned char Filler[TEST_PATTERN_SIZE]; /* minimal length of 54 bytes */ +} +WVLAN_LT_REQ, *PWVLAN_LT_REQ; + + +typedef struct wvlan_lt_rsp +{ + char name[32]; + /* Measured Data */ + unsigned char signal; + unsigned char noise; + unsigned char rxFlow; + unsigned char dataRate; + unsigned short protocol; + /* Capabilities */ + unsigned char station; + unsigned char dataRateCap; + unsigned char powerMgmt[4]; + unsigned char robustness[4]; + unsigned char scaling; + unsigned char reserved[5]; +} +WVLAN_LT_RSP, *PWVLAN_LT_RSP; + + +typedef struct wvlan_rx_wmp_hdr +{ + unsigned short status; + unsigned short reserved1[2]; + unsigned char silence; + unsigned char signal; + unsigned char rate; + unsigned char rxFlow; + unsigned short reserved2[2]; + unsigned short frameControl; + unsigned short duration; + unsigned short address1[3]; + unsigned short address2[3]; + unsigned short address3[3]; + unsigned short sequenceControl; + unsigned short address4[3]; +#ifndef HERMES25 //;?just to be on the safe side of inherited but not comprehended code #ifdef HERMES2 + unsigned short seems_to_be_unused_reserved3[5]; //;? + unsigned short seems_to_be_unused_reserved4; //;? +#endif // HERMES25 + unsigned short HeaderDataLen; +} +WVLAN_RX_WMP_HDR, *PWVLAN_RX_WMP_HDR; + + +typedef struct wvlan_linktest_req_pdu +{ + WVLAN_ETH_HDR ethHdr; + WVLAN_LLC_SNAP llcSnap; + WVLAN_LT_HDR ltHdr; + WVLAN_LT_REQ ltReq; +} +WVLAN_LINKTEST_REQ_PDU, *PWVLAN_LINKTEST_REQ_PDU; + + +typedef struct wvlan_linktest_rsp_pdu +{ + WVLAN_RX_WMP_HDR wmpRxHdr; + WVLAN_ETH_HDR ethHdr; + WVLAN_LLC_SNAP llcSnap; + WVLAN_LT_HDR ltHdr; + WVLAN_LT_RSP ltRsp; +} +WVLAN_LINKTEST_RSP_PDU, *PWVLAN_LINKTEST_RSP_PDU; + + +typedef struct _LINKTEST_RSP_STRCT +{ + hcf_16 len; + hcf_16 typ; + WVLAN_LINKTEST_RSP_PDU ltRsp; +} +LINKTEST_RSP_STRCT; + + +typedef struct wvlan_wmp_rsp_pdu +{ + WVLAN_RX_WMP_HDR wmpRxHdr; + WVLAN_ETH_HDR ethHdr; + WVLAN_LLC_SNAP llcSnap; + WVLAN_WMP_HDR wmpHdr; +} +WVLAN_WMP_RSP_PDU, *PWVLAN_WMP_RSP_PDU; + + +typedef struct _WMP_RSP_STRCT +{ + hcf_16 len; + hcf_16 typ; + WVLAN_WMP_RSP_PDU wmpRsp; +} +WMP_RSP_STRCT; + + +typedef struct _PROBE_RESP +{ + // first part: 802.11 + hcf_16 length; + hcf_16 infoType; + hcf_16 reserved0; + //hcf_8 signal; + hcf_8 silence; + hcf_8 signal; // Moved signal here as signal/noise values were flipped + hcf_8 rxFlow; + hcf_8 rate; + hcf_16 reserved1[2]; + + // second part: + hcf_16 frameControl; + hcf_16 durID; + hcf_8 address1[6]; + hcf_8 address2[6]; + hcf_8 BSSID[6]; //! this is correct, right ? + hcf_16 sequence; + hcf_8 address4[6]; + +#ifndef WARP + hcf_8 reserved2[12]; +#endif // WARP + + hcf_16 dataLength; + // the information in the next 3 fields (DA/SA/LenType) is actually not filled in. + hcf_8 DA[6]; + hcf_8 SA[6]; + +#ifdef WARP + hcf_8 channel; + hcf_8 band; +#else + hcf_16 lenType; +#endif // WARP + + hcf_8 timeStamp[8]; + hcf_16 beaconInterval; + hcf_16 capability; + hcf_8 rawData[200]; //! <<< think about this number ! + hcf_16 flags; +} +PROBE_RESP, *PPROBE_RESP; + + +typedef struct _ProbeResult +{ + int scan_complete; + int num_aps; + PROBE_RESP ProbeTable[MAX_NAPS]; +} +ProbeResult; + +/* Definitions used to parse capabilities out of the probe responses */ +#define CAPABILITY_ESS 0x0001 +#define CAPABILITY_IBSS 0x0002 +#define CAPABILITY_PRIVACY 0x0010 + +/* Definitions used to parse the Information Elements out of probe responses */ +#define DS_INFO_ELEM 0x03 +#define GENERIC_INFO_ELEM 0xdd +#define WPA_MAX_IE_LEN 40 +#define WPA_SELECTOR_LEN 4 +#define WPA_OUI_TYPE { 0x00, 0x50, 0xf2, 1 } +#define WPA_VERSION 1 +#define WPA_AUTH_KEY_MGMT_UNSPEC_802_1X { 0x00, 0x50, 0xf2, 1 } +#define WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X { 0x00, 0x50, 0xf2, 2 } +#define WPA_CIPHER_SUITE_NONE { 0x00, 0x50, 0xf2, 0 } +#define WPA_CIPHER_SUITE_WEP40 { 0x00, 0x50, 0xf2, 1 } +#define WPA_CIPHER_SUITE_TKIP { 0x00, 0x50, 0xf2, 2 } +#define WPA_CIPHER_SUITE_WRAP { 0x00, 0x50, 0xf2, 3 } +#define WPA_CIPHER_SUITE_CCMP { 0x00, 0x50, 0xf2, 4 } +#define WPA_CIPHER_SUITE_WEP104 { 0x00, 0x50, 0xf2, 5 } + +typedef enum wvlan_drv_mode +{ + WVLAN_DRV_MODE_NO_DOWNLOAD, /* this is the same as STA for Hermes 1 */ + /* it is also only applicable for Hermes 1 */ + WVLAN_DRV_MODE_STA, + WVLAN_DRV_MODE_AP, + WVLAN_DRV_MODE_MAX +} +WVLAN_DRV_MODE, *PWVLAN_DRV_MODE; + + +typedef enum wvlan_port_state +{ + WVLAN_PORT_STATE_ENABLED, + WVLAN_PORT_STATE_DISABLED, + WVLAN_PORT_STATE_CONNECTED +} +WVLAN_PORT_STATE, *PWVLAN_PORT_STATE; + +/* +typedef enum wvlan_connect_state +{ + WVLAN_CONNECT_STATE_CONNECTED, + WVLAN_CONNECT_STATE_DISCONNECTED +} +WVLAN_CONNECT_STATE, *PWVLAN_CONNECT_STATE; +*/ + +typedef enum wvlan_pm_state +{ + WVLAN_PM_STATE_DISABLED, + WVLAN_PM_STATE_ENHANCED, + WVLAN_PM_STATE_STANDARD +} +WVLAN_PM_STATE, *PWVLAN_PM_STATE; + + +typedef struct wvlan_frame +{ + struct sk_buff *skb; /* sk_buff for frame. */ + hcf_16 port; /* MAC port for the frame. */ + hcf_16 len; /* Length of the frame. */ +} +WVLAN_FRAME, *PWVLAN_FRAME; + + +typedef struct wvlan_lframe +{ + struct list_head node; /* Node in the list */ + WVLAN_FRAME frame; /* Frame. */ +} +WVLAN_LFRAME, *PWVLAN_LFRAME; + + + +#define DEFAULT_NUM_TX_FRAMES 48 +#define TX_Q_LOW_WATER_MARK (DEFAULT_NUM_TX_FRAMES/3) + +#define WVLAN_MAX_TX_QUEUES 1 + + +#ifdef USE_WDS + +typedef struct wvlan_wds_if +{ + struct net_device *dev; + int is_registered; + int netif_queue_on; + struct net_device_stats stats; + hcf_16 rtsThreshold; + hcf_16 txRateCntl; + hcf_8 wdsAddress[ETH_ALEN]; +} WVLAN_WDS_IF, *PWVLAN_WDS_IF; + +#endif // USE_WDS + + + +#define NUM_RX_DESC 5 +#define NUM_TX_DESC 5 + +typedef struct dma_strct +{ + DESC_STRCT *tx_packet[NUM_TX_DESC]; + DESC_STRCT *rx_packet[NUM_RX_DESC]; + DESC_STRCT *rx_reclaim_desc, *tx_reclaim_desc; // Descriptors for host-reclaim purposes (see HCF) + int tx_rsc_ind; // DMA Tx resource indicator is maintained in the MSF, not in the HCF + int rx_rsc_ind; // Also added rx rsource indicator so that cleanup can be performed if alloc fails + int status; +} DMA_STRCT; + + +/* Macros used in DMA support */ +/* get bus address of {rx,tx}dma structure member, in little-endian byte order */ +#define WL_DMA_BUS_ADDR_LE(str, i, mem) \ + cpu_to_le32(str##_dma_addr[(i)] + ((hcf_8 *)&str[(i)]->mem - (hcf_8 *)str[(i)])) + + +struct wl_private +{ + +#ifdef BUS_PCMCIA + dev_node_t node; + struct pcmcia_device *link; +#endif // BUS_PCMCIA + + + struct net_device *dev; +// struct net_device *dev_next; + spinlock_t slock; + struct tasklet_struct task; + struct net_device_stats stats; + + +#ifdef WIRELESS_EXT + struct iw_statistics wstats; +// int spy_number; +// u_char spy_address[IW_MAX_SPY][ETH_ALEN]; +// struct iw_quality spy_stat[IW_MAX_SPY]; + struct iw_spy_data spy_data; + struct iw_public_data wireless_data; +#endif // WIRELESS_EXT + + + IFB_STRCT hcfCtx; +//;? struct timer_list timer_oor; +//;? hcf_16 timer_oor_cnt; + u_long wlags49_type; //controls output in /proc/wlags49 + u_long flags; + hcf_16 DebugFlag; + int is_registered; + int is_handling_int; + int firmware_present; + char sysfsCreated; + CFG_DRV_INFO_STRCT driverInfo; + CFG_IDENTITY_STRCT driverIdentity; + CFG_FW_IDENTITY_STRCT StationIdentity; + CFG_PRI_IDENTITY_STRCT PrimaryIdentity; + CFG_PRI_IDENTITY_STRCT NICIdentity; + + ltv_t ltvRecord; + u_long txBytes; + hcf_16 maxPort; /* 0 for STA, 6 for AP */ + + /* Elements used for async notification from hardware */ + RID_LOG_STRCT RidList[10]; + ltv_t updatedRecord; + PROBE_RESP ProbeResp; + ASSOC_STATUS_STRCT assoc_stat; + SECURITY_STATUS_STRCT sec_stat; + + u_char lookAheadBuf[WVLAN_MAX_LOOKAHEAD]; + + hcf_8 PortType; // 1 - 3 (1 [Normal] | 3 [AdHoc]) + hcf_16 Channel; // 0 - 14 (0) + hcf_16 TxRateControl[2]; + hcf_8 DistanceBetweenAPs; // 1 - 3 (1) + hcf_16 RTSThreshold; // 0 - 2347 (2347) + hcf_16 PMEnabled; // 0 - 2, 8001 - 8002 (0) + hcf_8 MicrowaveRobustness;// 0 - 1 (0) + hcf_8 CreateIBSS; // 0 - 1 (0) + hcf_8 MulticastReceive; // 0 - 1 (1) + hcf_16 MaxSleepDuration; // 0 - 65535 (100) + hcf_8 MACAddress[ETH_ALEN]; + char NetworkName[HCF_MAX_NAME_LEN+1]; + char StationName[HCF_MAX_NAME_LEN+1]; + hcf_8 EnableEncryption; // 0 - 1 (0) + char Key1[MAX_KEY_LEN+1]; + char Key2[MAX_KEY_LEN+1]; + char Key3[MAX_KEY_LEN+1]; + char Key4[MAX_KEY_LEN+1]; + hcf_8 TransmitKeyID; // 1 - 4 (1) + CFG_DEFAULT_KEYS_STRCT DefaultKeys; + u_char mailbox[MB_SIZE]; + char szEncryption[MAX_ENC_LEN]; + + hcf_16 driverEnable; + hcf_16 wolasEnable; + hcf_16 atimWindow; + hcf_16 holdoverDuration; + hcf_16 MulticastRate[2]; + + hcf_16 authentication; // is this AP specific? + hcf_16 promiscuousMode; + WVLAN_DRV_MODE DownloadFirmware; // 0 - 2 (0 [None] | 1 [STA] | 2 [AP]) + + char fw_image_filename[MAX_LINE_SIZE+1]; + + hcf_16 AuthKeyMgmtSuite; + + hcf_16 loadBalancing; + hcf_16 mediumDistribution; + hcf_16 txPowLevel; + //hcf_16 shortRetryLimit; + //hcf_16 longRetryLimit; + hcf_16 srsc[2]; + hcf_16 brsc[2]; + hcf_16 connectionControl; + //hcf_16 probeDataRates[2]; + hcf_16 ownBeaconInterval; + hcf_16 coexistence; + + WVLAN_FRAME txF; + WVLAN_LFRAME txList[DEFAULT_NUM_TX_FRAMES]; + struct list_head txFree; + struct list_head txQ[WVLAN_MAX_TX_QUEUES]; + int netif_queue_on; + int txQ_count; + DESC_STRCT desc_rx; + DESC_STRCT desc_tx; + + WVLAN_PORT_STATE portState; + + ScanResult scan_results; + ProbeResult probe_results; + int probe_num_aps; + + int use_dma; + DMA_STRCT dma; +#ifdef USE_RTS + int useRTS; +#endif // USE_RTS + hcf_8 DTIMPeriod; // 1 - 255 (1) + hcf_16 multicastPMBuffering; + hcf_8 RejectAny; // 0 - 1 (0) + hcf_8 ExcludeUnencrypted; // 0 - 1 (1) + hcf_16 intraBSSRelay; +#ifdef USE_WDS + WVLAN_WDS_IF wds_port[NUM_WDS_PORTS]; +#endif // USE_WDS +}; // wl_private + +#ifdef HAVE_NETDEV_PRIV +#define wl_priv(dev) ((struct wl_private *) netdev_priv(dev)) +#else +extern inline struct wl_private *wl_priv(struct net_device *dev) +{ + return dev->priv; +} +#endif + +/********************************************************************/ +/* Locking and synchronization functions */ +/********************************************************************/ + +/* These functions *must* be inline or they will break horribly on + * SPARC, due to its weird semantics for save/restore flags. extern + * inline should prevent the kernel from linking or module from + * loading if they are not inlined. */ +extern inline void wl_lock(struct wl_private *lp, + unsigned long *flags) +{ + spin_lock_irqsave(&lp->slock, *flags); +} + +extern inline void wl_unlock(struct wl_private *lp, + unsigned long *flags) +{ + spin_unlock_irqrestore(&lp->slock, *flags); +} + +/********************************************************************/ +/* Interrupt enable disable functions */ +/********************************************************************/ + +extern inline void wl_act_int_on(struct wl_private *lp) +{ + /* + * Only do something when the driver is handling + * interrupts. Handling starts at wl_open and + * ends at wl_close when not in RTS mode + */ + if(lp->is_handling_int == WL_HANDLING_INT) { + hcf_action( &lp->hcfCtx, HCF_ACT_INT_ON ); + } +} + +extern inline void wl_act_int_off(struct wl_private *lp) +{ + /* + * Only do something when the driver is handling + * interrupts. Handling starts at wl_open and + * ends at wl_close when not in RTS mode + */ + if(lp->is_handling_int == WL_HANDLING_INT) { + hcf_action( &lp->hcfCtx, HCF_ACT_INT_OFF ); + } +} + +#endif // __WAVELAN2_H__ diff --git a/drivers/staging/wlags49_h2/wl_main.c b/drivers/staging/wlags49_h2/wl_main.c new file mode 100644 index 0000000000000000000000000000000000000000..16764a0009428ed1499cab6d9eb52fb4eeac27f5 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_main.c @@ -0,0 +1,3866 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * This file contains the main driver entry points and other adapter + * specific routines. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +/******************************************************************************* + * constant definitions + ******************************************************************************/ + +/* Allow support for calling system fcns to access F/W iamge file */ +#define __KERNEL_SYSCALLS__ + +/******************************************************************************* + * include 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 + +#define BIN_DL 0 +#if BIN_DL +#include +#endif // BIN_DL + + +#include + +#include +#include +//in order to get around:: wl_main.c:2229: `HREG_EV_RDMAD' undeclared (first use in this function) +#include + +#include +#include +#include +#include +#include +#include + +#ifdef USE_PROFILE +#include +#endif /* USE_PROFILE */ + +#ifdef BUS_PCMCIA +#include +#endif /* BUS_PCMCIA */ + +#ifdef BUS_PCI +#include +#endif /* BUS_PCI */ +/******************************************************************************* + * macro defintions + ******************************************************************************/ +#define VALID_PARAM(C) \ + { \ + if (!(C)) \ + { \ + printk(KERN_INFO "Wireless, parameter error: \"%s\"\n", #C); \ + goto failed; \ + } \ + } +/******************************************************************************* + * local functions + ******************************************************************************/ +void wl_isr_handler( unsigned long p ); + +#if 0 //SCULL_USE_PROC /* don't waste space if unused */ +//int scull_read_procmem(char *buf, char **start, off_t offset, int len, int unused); +int scull_read_procmem(char *buf, char **start, off_t offset, int len, int *eof, void *data ); +static int write_int(struct file *file, const char *buffer, unsigned long count, void *data); +static void proc_write(const char *name, write_proc_t *w, void *data); + +#endif /* SCULL_USE_PROC */ + +/******************************************************************************* + * module parameter definitions - set with 'insmod' + ******************************************************************************/ +static p_u16 irq_mask = 0xdeb8; // IRQ3,4,5,7,9,10,11,12,14,15 +static p_s8 irq_list[4] = { -1 }; + +#if 0 +MODULE_PARM(irq_mask, "h"); +MODULE_PARM_DESC(irq_mask, "IRQ mask [0xdeb8]"); +MODULE_PARM(irq_list, "1-4b"); +MODULE_PARM_DESC(irq_list, "IRQ list []"); +#endif + +static p_u8 PARM_AUTHENTICATION = PARM_DEFAULT_AUTHENTICATION; +static p_u16 PARM_AUTH_KEY_MGMT_SUITE = PARM_DEFAULT_AUTH_KEY_MGMT_SUITE; +static p_u16 PARM_BRSC_2GHZ = PARM_DEFAULT_BRSC_2GHZ; +static p_u16 PARM_BRSC_5GHZ = PARM_DEFAULT_BRSC_5GHZ; +static p_u16 PARM_COEXISTENCE = PARM_DEFAULT_COEXISTENCE; +static p_u16 PARM_CONNECTION_CONTROL = PARM_DEFAULT_CONNECTION_CONTROL; //;?rename and move +static p_char *PARM_CREATE_IBSS = PARM_DEFAULT_CREATE_IBSS_STR; +static p_char *PARM_DESIRED_SSID = PARM_DEFAULT_SSID; +static p_char *PARM_DOWNLOAD_FIRMWARE = ""; +static p_u16 PARM_ENABLE_ENCRYPTION = PARM_DEFAULT_ENABLE_ENCRYPTION; +static p_char *PARM_EXCLUDE_UNENCRYPTED = PARM_DEFAULT_EXCLUDE_UNENCRYPTED_STR; +static p_char *PARM_INTRA_BSS_RELAY = PARM_DEFAULT_INTRA_BSS_RELAY_STR; +static p_char *PARM_KEY1 = ""; +static p_char *PARM_KEY2 = ""; +static p_char *PARM_KEY3 = ""; +static p_char *PARM_KEY4 = ""; +static p_char *PARM_LOAD_BALANCING = PARM_DEFAULT_LOAD_BALANCING_STR; +static p_u16 PARM_MAX_SLEEP = PARM_DEFAULT_MAX_PM_SLEEP; +static p_char *PARM_MEDIUM_DISTRIBUTION = PARM_DEFAULT_MEDIUM_DISTRIBUTION_STR; +static p_char *PARM_MICROWAVE_ROBUSTNESS = PARM_DEFAULT_MICROWAVE_ROBUSTNESS_STR; +static p_char *PARM_MULTICAST_PM_BUFFERING = PARM_DEFAULT_MULTICAST_PM_BUFFERING_STR; +static p_u16 PARM_MULTICAST_RATE = PARM_DEFAULT_MULTICAST_RATE_2GHZ; +static p_char *PARM_MULTICAST_RX = PARM_DEFAULT_MULTICAST_RX_STR; +static p_u8 PARM_NETWORK_ADDR[ETH_ALEN] = PARM_DEFAULT_NETWORK_ADDR; +static p_u16 PARM_OWN_ATIM_WINDOW = PARM_DEFAULT_OWN_ATIM_WINDOW; +static p_u16 PARM_OWN_BEACON_INTERVAL = PARM_DEFAULT_OWN_BEACON_INTERVAL; +static p_u8 PARM_OWN_CHANNEL = PARM_DEFAULT_OWN_CHANNEL; +static p_u8 PARM_OWN_DTIM_PERIOD = PARM_DEFAULT_OWN_DTIM_PERIOD; +static p_char *PARM_OWN_NAME = PARM_DEFAULT_OWN_NAME; +static p_char *PARM_OWN_SSID = PARM_DEFAULT_SSID; +static p_u16 PARM_PM_ENABLED = WVLAN_PM_STATE_DISABLED; +static p_u16 PARM_PM_HOLDOVER_DURATION = PARM_DEFAULT_PM_HOLDOVER_DURATION; +static p_u8 PARM_PORT_TYPE = PARM_DEFAULT_PORT_TYPE; +static p_char *PARM_PROMISCUOUS_MODE = PARM_DEFAULT_PROMISCUOUS_MODE_STR; +static p_char *PARM_REJECT_ANY = PARM_DEFAULT_REJECT_ANY_STR; +#ifdef USE_WDS +static p_u16 PARM_RTS_THRESHOLD1 = PARM_DEFAULT_RTS_THRESHOLD; +static p_u16 PARM_RTS_THRESHOLD2 = PARM_DEFAULT_RTS_THRESHOLD; +static p_u16 PARM_RTS_THRESHOLD3 = PARM_DEFAULT_RTS_THRESHOLD; +static p_u16 PARM_RTS_THRESHOLD4 = PARM_DEFAULT_RTS_THRESHOLD; +static p_u16 PARM_RTS_THRESHOLD5 = PARM_DEFAULT_RTS_THRESHOLD; +static p_u16 PARM_RTS_THRESHOLD6 = PARM_DEFAULT_RTS_THRESHOLD; +#endif // USE_WDS +static p_u16 PARM_RTS_THRESHOLD = PARM_DEFAULT_RTS_THRESHOLD; +static p_u16 PARM_SRSC_2GHZ = PARM_DEFAULT_SRSC_2GHZ; +static p_u16 PARM_SRSC_5GHZ = PARM_DEFAULT_SRSC_5GHZ; +static p_u8 PARM_SYSTEM_SCALE = PARM_DEFAULT_SYSTEM_SCALE; +static p_u8 PARM_TX_KEY = PARM_DEFAULT_TX_KEY; +static p_u16 PARM_TX_POW_LEVEL = PARM_DEFAULT_TX_POW_LEVEL; +#ifdef USE_WDS +static p_u16 PARM_TX_RATE1 = PARM_DEFAULT_TX_RATE_2GHZ; +static p_u16 PARM_TX_RATE2 = PARM_DEFAULT_TX_RATE_2GHZ; +static p_u16 PARM_TX_RATE3 = PARM_DEFAULT_TX_RATE_2GHZ; +static p_u16 PARM_TX_RATE4 = PARM_DEFAULT_TX_RATE_2GHZ; +static p_u16 PARM_TX_RATE5 = PARM_DEFAULT_TX_RATE_2GHZ; +static p_u16 PARM_TX_RATE6 = PARM_DEFAULT_TX_RATE_2GHZ; +#endif // USE_WDS +static p_u16 PARM_TX_RATE = PARM_DEFAULT_TX_RATE_2GHZ; +#ifdef USE_WDS +static p_u8 PARM_WDS_ADDRESS1[ETH_ALEN] = PARM_DEFAULT_NETWORK_ADDR; +static p_u8 PARM_WDS_ADDRESS2[ETH_ALEN] = PARM_DEFAULT_NETWORK_ADDR; +static p_u8 PARM_WDS_ADDRESS3[ETH_ALEN] = PARM_DEFAULT_NETWORK_ADDR; +static p_u8 PARM_WDS_ADDRESS4[ETH_ALEN] = PARM_DEFAULT_NETWORK_ADDR; +static p_u8 PARM_WDS_ADDRESS5[ETH_ALEN] = PARM_DEFAULT_NETWORK_ADDR; +static p_u8 PARM_WDS_ADDRESS6[ETH_ALEN] = PARM_DEFAULT_NETWORK_ADDR; +#endif // USE_WDS + + +#if 0 +MODULE_PARM(PARM_DESIRED_SSID, "s"); +MODULE_PARM_DESC(PARM_DESIRED_SSID, "Network Name () [ANY]"); +MODULE_PARM(PARM_OWN_SSID, "s"); +MODULE_PARM_DESC(PARM_OWN_SSID, "Network Name () [ANY]"); +MODULE_PARM(PARM_OWN_CHANNEL, "b"); +MODULE_PARM_DESC(PARM_OWN_CHANNEL, "Channel (0 - 14) [0]"); +MODULE_PARM(PARM_SYSTEM_SCALE, "b"); +MODULE_PARM_DESC(PARM_SYSTEM_SCALE, "Distance Between APs (1 - 3) [1]"); +MODULE_PARM(PARM_TX_RATE, "b"); +MODULE_PARM_DESC(PARM_TX_RATE, "Transmit Rate Control"); +MODULE_PARM(PARM_RTS_THRESHOLD, "h"); +MODULE_PARM_DESC(PARM_RTS_THRESHOLD, "Medium Reservation (RTS/CTS Fragment Length) (256 - 2347) [2347]"); +MODULE_PARM(PARM_MICROWAVE_ROBUSTNESS, "s"); +MODULE_PARM_DESC(PARM_MICROWAVE_ROBUSTNESS, "Microwave Oven Robustness Enabled ( N or Y) [N]"); +MODULE_PARM(PARM_OWN_NAME, "s"); +MODULE_PARM_DESC(PARM_OWN_NAME, "Station Name () [Linux]"); + +MODULE_PARM(PARM_ENABLE_ENCRYPTION, "b"); +MODULE_PARM_DESC(PARM_ENABLE_ENCRYPTION, "Encryption Mode (0 - 7) [0]"); + +MODULE_PARM(PARM_KEY1, "s"); +MODULE_PARM_DESC(PARM_KEY1, "Data Encryption Key 1 () []"); +MODULE_PARM(PARM_KEY2, "s"); +MODULE_PARM_DESC(PARM_KEY2, "Data Encryption Key 2 () []"); +MODULE_PARM(PARM_KEY3, "s"); +MODULE_PARM_DESC(PARM_KEY3, "Data Encryption Key 3 () []"); +MODULE_PARM(PARM_KEY4, "s"); +MODULE_PARM_DESC(PARM_KEY4, "Data Encryption Key 4 () []"); +MODULE_PARM(PARM_TX_KEY, "b"); +MODULE_PARM_DESC(PARM_TX_KEY, "Transmit Key ID (1 - 4) [1]"); +MODULE_PARM(PARM_MULTICAST_RATE, "b"); +MODULE_PARM_DESC(PARM_MULTICAST_RATE, "Multicast Rate"); +MODULE_PARM(PARM_DOWNLOAD_FIRMWARE, "s"); +MODULE_PARM_DESC(PARM_DOWNLOAD_FIRMWARE, "filename of firmware image"); + +MODULE_PARM(PARM_AUTH_KEY_MGMT_SUITE, "b"); +MODULE_PARM_DESC(PARM_AUTH_KEY_MGMT_SUITE, "Authentication Key Management suite (0-4) [0]"); + +MODULE_PARM(PARM_LOAD_BALANCING, "s"); +MODULE_PARM_DESC(PARM_LOAD_BALANCING, "Load Balancing Enabled ( N or Y) [Y]"); +MODULE_PARM(PARM_MEDIUM_DISTRIBUTION, "s"); +MODULE_PARM_DESC(PARM_MEDIUM_DISTRIBUTION, "Medium Distribution Enabled ( N or Y) [Y]"); +MODULE_PARM(PARM_TX_POW_LEVEL, "b"); +MODULE_PARM_DESC(PARM_TX_POW_LEVEL, "Transmit Power (0 - 6) [3]"); +MODULE_PARM(PARM_SRSC_2GHZ, "b"); +MODULE_PARM_DESC(PARM_SRSC_2GHZ, "Supported Rate Set Control 2.4 GHz"); +MODULE_PARM(PARM_SRSC_5GHZ, "b"); +MODULE_PARM_DESC(PARM_SRSC_5GHZ, "Supported Rate Set Control 5.0 GHz"); +MODULE_PARM(PARM_BRSC_2GHZ, "b"); +MODULE_PARM_DESC(PARM_BRSC_2GHZ, "Basic Rate Set Control 2.4 GHz"); +MODULE_PARM(PARM_BRSC_5GHZ, "b"); +MODULE_PARM_DESC(PARM_BRSC_5GHZ, "Basic Rate Set Control 5.0 GHz"); +#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA +//;?seems reasonable that even an AP-only driver could afford this small additional footprint +MODULE_PARM(PARM_PM_ENABLED, "h"); +MODULE_PARM_DESC(PARM_PM_ENABLED, "Power Management State (0 - 2, 8001 - 8002) [0]"); +MODULE_PARM(PARM_PORT_TYPE, "b"); +MODULE_PARM_DESC(PARM_PORT_TYPE, "Port Type (1 - 3) [1]"); +//;?MODULE_PARM(PARM_CREATE_IBSS, "s"); +//;?MODULE_PARM_DESC(PARM_CREATE_IBSS, "Create IBSS ( N or Y) [N]"); +//;?MODULE_PARM(PARM_MULTICAST_RX, "s"); +//;?MODULE_PARM_DESC(PARM_MULTICAST_RX, "Multicast Receive Enable ( N or Y) [Y]"); +//;?MODULE_PARM(PARM_MAX_SLEEP, "h"); +//;?MODULE_PARM_DESC(PARM_MAX_SLEEP, "Maximum Power Management Sleep Duration (0 - 65535) [100]"); +//;?MODULE_PARM(PARM_NETWORK_ADDR, "6b"); +//;?MODULE_PARM_DESC(PARM_NETWORK_ADDR, "Hardware Ethernet Address ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) []"); +//;?MODULE_PARM(PARM_AUTHENTICATION, "b"); +// +//tracker 12448 +//;?MODULE_PARM_DESC(PARM_AUTHENTICATION, "Authentication Type (0-2) [0] 0=Open 1=SharedKey 2=LEAP"); +//;?MODULE_PARM_DESC(authentication, "Authentication Type (1-2) [1] 1=Open 2=SharedKey"); +//tracker 12448 +// +//;?MODULE_PARM(PARM_OWN_ATIM_WINDOW, "b"); +//;?MODULE_PARM_DESC(PARM_OWN_ATIM_WINDOW, "ATIM Window time in TU for IBSS creation (0-100) [0]"); +//;?MODULE_PARM(PARM_PM_HOLDOVER_DURATION, "b"); +//;?MODULE_PARM_DESC(PARM_PM_HOLDOVER_DURATION, "Time station remains awake after MAC frame transfer when PM is on (0-65535) [100]"); +//;?MODULE_PARM(PARM_PROMISCUOUS_MODE, "s"); +//;?MODULE_PARM_DESC(PARM_PROMISCUOUS_MODE, "Promiscuous Mode Enable ( Y or N ) [N]" ); +//;? +MODULE_PARM(PARM_CONNECTION_CONTROL, "b"); +MODULE_PARM_DESC(PARM_CONNECTION_CONTROL, "Connection Control (0 - 3) [2]"); +#endif /* HCF_STA */ +#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP + //;?should we restore this to allow smaller memory footprint +MODULE_PARM(PARM_OWN_DTIM_PERIOD, "b"); +MODULE_PARM_DESC(PARM_OWN_DTIM_PERIOD, "DTIM Period (0 - 255) [1]"); +MODULE_PARM(PARM_REJECT_ANY, "s"); +MODULE_PARM_DESC(PARM_REJECT_ANY, "Closed System ( N or Y) [N]"); +MODULE_PARM(PARM_EXCLUDE_UNENCRYPTED, "s"); +MODULE_PARM_DESC(PARM_EXCLUDE_UNENCRYPTED, "Deny non-encrypted ( N or Y) [Y]"); +MODULE_PARM(PARM_MULTICAST_PM_BUFFERING,"s"); +MODULE_PARM_DESC(PARM_MULTICAST_PM_BUFFERING, "Buffer MAC frames for Tx after DTIM ( Y or N) [Y]"); +MODULE_PARM(PARM_INTRA_BSS_RELAY, "s"); +MODULE_PARM_DESC(PARM_INTRA_BSS_RELAY, "IntraBSS Relay ( N or Y) [Y]"); +MODULE_PARM(PARM_RTS_THRESHOLD1, "h"); +MODULE_PARM_DESC(PARM_RTS_THRESHOLD1, "RTS Threshold, WDS Port 1 (256 - 2347) [2347]"); +MODULE_PARM(PARM_RTS_THRESHOLD2, "h"); +MODULE_PARM_DESC(PARM_RTS_THRESHOLD2, "RTS Threshold, WDS Port 2 (256 - 2347) [2347]"); +MODULE_PARM(PARM_RTS_THRESHOLD3, "h"); +MODULE_PARM_DESC(PARM_RTS_THRESHOLD3, "RTS Threshold, WDS Port 3 (256 - 2347) [2347]"); +MODULE_PARM(PARM_RTS_THRESHOLD4, "h"); +MODULE_PARM_DESC(PARM_RTS_THRESHOLD4, "RTS Threshold, WDS Port 4 (256 - 2347) [2347]"); +MODULE_PARM(PARM_RTS_THRESHOLD5, "h"); +MODULE_PARM_DESC(PARM_RTS_THRESHOLD5, "RTS Threshold, WDS Port 5 (256 - 2347) [2347]"); +MODULE_PARM(PARM_RTS_THRESHOLD6, "h"); +MODULE_PARM_DESC(PARM_RTS_THRESHOLD6, "RTS Threshold, WDS Port 6 (256 - 2347) [2347]"); +MODULE_PARM(PARM_TX_RATE1, "b"); +MODULE_PARM_DESC(PARM_TX_RATE1, "Transmit Rate Control, WDS Port 1 (1 - 7) [3]"); +MODULE_PARM(PARM_TX_RATE2, "b"); +MODULE_PARM_DESC(PARM_TX_RATE2, "Transmit Rate Control, WDS Port 2 (1 - 7) [3]"); +MODULE_PARM(PARM_TX_RATE3, "b"); +MODULE_PARM_DESC(PARM_TX_RATE3, "Transmit Rate Control, WDS Port 3 (1 - 7) [3]"); +MODULE_PARM(PARM_TX_RATE4, "b"); +MODULE_PARM_DESC(PARM_TX_RATE4, "Transmit Rate Control, WDS Port 4 (1 - 7) [3]"); +MODULE_PARM(PARM_TX_RATE5, "b"); +MODULE_PARM_DESC(PARM_TX_RATE5, "Transmit Rate Control, WDS Port 5 (1 - 7) [3]"); +MODULE_PARM(PARM_TX_RATE6, "b"); +MODULE_PARM_DESC(PARM_TX_RATE6, "Transmit Rate Control, WDS Port 6 (1 - 7) [3]"); +MODULE_PARM(PARM_WDS_ADDRESS1, "6b"); +MODULE_PARM_DESC(PARM_WDS_ADDRESS1, "MAC Address, WDS Port 1 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]"); +MODULE_PARM(PARM_WDS_ADDRESS2, "6b"); +MODULE_PARM_DESC(PARM_WDS_ADDRESS2, "MAC Address, WDS Port 2 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]"); +MODULE_PARM(PARM_WDS_ADDRESS3, "6b"); +MODULE_PARM_DESC(PARM_WDS_ADDRESS3, "MAC Address, WDS Port 3 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]"); +MODULE_PARM(PARM_WDS_ADDRESS4, "6b"); +MODULE_PARM_DESC(PARM_WDS_ADDRESS4, "MAC Address, WDS Port 4 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]"); +MODULE_PARM(PARM_WDS_ADDRESS5, "6b"); +MODULE_PARM_DESC(PARM_WDS_ADDRESS5, "MAC Address, WDS Port 5 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]"); +MODULE_PARM(PARM_WDS_ADDRESS6, "6b"); +MODULE_PARM_DESC(PARM_WDS_ADDRESS6, "MAC Address, WDS Port 6 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]"); + +MODULE_PARM(PARM_OWN_BEACON_INTERVAL, "b"); +MODULE_PARM_DESC(PARM_OWN_BEACON_INTERVAL, "Own Beacon Interval (20 - 200) [100]"); +MODULE_PARM(PARM_COEXISTENCE, "b"); +MODULE_PARM_DESC(PARM_COEXISTENCE, "Coexistence (0-7) [0]"); + +#endif /* HCF_AP */ +#endif + +/* END NEW PARAMETERS */ +/******************************************************************************* + * debugging specifics + ******************************************************************************/ +#if DBG + +static p_u32 pc_debug = DBG_LVL; +//MODULE_PARM(pc_debug, "i"); +/*static ;?conflicts with my understanding of CL parameters and breaks now I moved + * the correspondig logic to wl_profile + */ p_u32 DebugFlag = ~0; //recognizable "undefined value" rather then DBG_DEFAULTS; +//MODULE_PARM(DebugFlag, "l"); + +dbg_info_t wl_info = { DBG_MOD_NAME, 0, 0 }; +dbg_info_t *DbgInfo = &wl_info; + +#endif /* DBG */ +#ifdef USE_RTS + +static p_char *useRTS = "N"; +MODULE_PARM( useRTS, "s" ); +MODULE_PARM_DESC( useRTS, "Use RTS test interface ( N or Y) [N]" ); + +#endif /* USE_RTS */ +/******************************************************************************* + * firmware download specifics + ******************************************************************************/ +extern struct CFG_RANGE2_STRCT BASED + cfg_drv_act_ranges_pri; // describes primary-actor range of HCF + +#if 0 //;? (HCF_TYPE) & HCF_TYPE_AP +extern memimage ap; // AP firmware image to be downloaded +#endif /* HCF_AP */ + +#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA +//extern memimage station; // STA firmware image to be downloaded +extern memimage fw_image; // firmware image to be downloaded +#endif /* HCF_STA */ + + +/******************************************************************************* + * wl_insert() + ******************************************************************************* + * + * DESCRIPTION: + * + * wl_insert() is scheduled to run after a CARD_INSERTION event is + * received, to configure the PCMCIA socket, and to make the ethernet device + * available to the system. + * + * PARAMETERS: + * + * dev - a pointer to the net_device struct of the wireless device + * + * RETURNS: + * + * TRUE or FALSE + * + ******************************************************************************/ +int wl_insert( struct net_device *dev ) +{ + int result = 0; + int hcf_status = HCF_SUCCESS; + int i; + unsigned long flags = 0; + struct wl_private *lp = wl_priv(dev); + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_insert" ); + DBG_ENTER( DbgInfo ); + + /* Initialize the adapter hardware. */ + memset( &( lp->hcfCtx ), 0, sizeof( IFB_STRCT )); + + /* Initialize the adapter parameters. */ + spin_lock_init( &( lp->slock )); + + /* Intialize states */ + //lp->lockcount = 0; //PE1DNN + lp->is_handling_int = WL_NOT_HANDLING_INT; + lp->firmware_present = WL_FRIMWARE_NOT_PRESENT; + + lp->dev = dev; + + DBG_PARAM( DbgInfo, "irq_mask", "0x%04x", irq_mask & 0x0FFFF ); + DBG_PARAM( DbgInfo, "irq_list", "0x%02x 0x%02x 0x%02x 0x%02x", + irq_list[0] & 0x0FF, irq_list[1] & 0x0FF, + irq_list[2] & 0x0FF, irq_list[3] & 0x0FF ); + DBG_PARAM( DbgInfo, PARM_NAME_DESIRED_SSID, "\"%s\"", PARM_DESIRED_SSID ); + DBG_PARAM( DbgInfo, PARM_NAME_OWN_SSID, "\"%s\"", PARM_OWN_SSID ); + DBG_PARAM( DbgInfo, PARM_NAME_OWN_CHANNEL, "%d", PARM_OWN_CHANNEL); + DBG_PARAM( DbgInfo, PARM_NAME_SYSTEM_SCALE, "%d", PARM_SYSTEM_SCALE ); + DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE, "%d", PARM_TX_RATE ); + DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD, "%d", PARM_RTS_THRESHOLD ); + DBG_PARAM( DbgInfo, PARM_NAME_MICROWAVE_ROBUSTNESS, "\"%s\"", PARM_MICROWAVE_ROBUSTNESS ); + DBG_PARAM( DbgInfo, PARM_NAME_OWN_NAME, "\"%s\"", PARM_OWN_NAME ); +//;? DBG_PARAM( DbgInfo, PARM_NAME_ENABLE_ENCRYPTION, "\"%s\"", PARM_ENABLE_ENCRYPTION ); + DBG_PARAM( DbgInfo, PARM_NAME_KEY1, "\"%s\"", PARM_KEY1 ); + DBG_PARAM( DbgInfo, PARM_NAME_KEY2, "\"%s\"", PARM_KEY2 ); + DBG_PARAM( DbgInfo, PARM_NAME_KEY3, "\"%s\"", PARM_KEY3 ); + DBG_PARAM( DbgInfo, PARM_NAME_KEY4, "\"%s\"", PARM_KEY4 ); + DBG_PARAM( DbgInfo, PARM_NAME_TX_KEY, "%d", PARM_TX_KEY ); + DBG_PARAM( DbgInfo, PARM_NAME_MULTICAST_RATE, "%d", PARM_MULTICAST_RATE ); + DBG_PARAM( DbgInfo, PARM_NAME_DOWNLOAD_FIRMWARE, "\"%s\"", PARM_DOWNLOAD_FIRMWARE ); + DBG_PARAM( DbgInfo, PARM_NAME_AUTH_KEY_MGMT_SUITE, "%d", PARM_AUTH_KEY_MGMT_SUITE ); +//;?#if (HCF_TYPE) & HCF_TYPE_STA + //;?should we make this code conditional depending on in STA mode +//;? DBG_PARAM( DbgInfo, PARM_NAME_PORT_TYPE, "%d", PARM_PORT_TYPE ); + DBG_PARAM( DbgInfo, PARM_NAME_PM_ENABLED, "%04x", PARM_PM_ENABLED ); +//;? DBG_PARAM( DbgInfo, PARM_NAME_CREATE_IBSS, "\"%s\"", PARM_CREATE_IBSS ); +//;? DBG_PARAM( DbgInfo, PARM_NAME_MULTICAST_RX, "\"%s\"", PARM_MULTICAST_RX ); +//;? DBG_PARAM( DbgInfo, PARM_NAME_MAX_SLEEP, "%d", PARM_MAX_SLEEP ); +//;? DBG_PARAM( DbgInfo, PARM_NAME_NETWORK_ADDR, "\"%s\"", DbgHwAddr( PARM_NETWORK_ADDR )); +//;? DBG_PARAM( DbgInfo, PARM_NAME_AUTHENTICATION, "%d", PARM_AUTHENTICATION ); +//;? DBG_PARAM( DbgInfo, PARM_NAME_OWN_ATIM_WINDOW, "%d", PARM_OWN_ATIM_WINDOW ); +//;? DBG_PARAM( DbgInfo, PARM_NAME_PM_HOLDOVER_DURATION, "%d", PARM_PM_HOLDOVER_DURATION ); +//;? DBG_PARAM( DbgInfo, PARM_NAME_PROMISCUOUS_MODE, "\"%s\"", PARM_PROMISCUOUS_MODE ); +//;?#endif /* HCF_STA */ +#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP + //;?should we restore this to allow smaller memory footprint + //;?I guess: no, since this is Debug mode only + DBG_PARAM( DbgInfo, PARM_NAME_OWN_DTIM_PERIOD, "%d", PARM_OWN_DTIM_PERIOD ); + DBG_PARAM( DbgInfo, PARM_NAME_REJECT_ANY, "\"%s\"", PARM_REJECT_ANY ); + DBG_PARAM( DbgInfo, PARM_NAME_EXCLUDE_UNENCRYPTED, "\"%s\"", PARM_EXCLUDE_UNENCRYPTED ); + DBG_PARAM( DbgInfo, PARM_NAME_MULTICAST_PM_BUFFERING, "\"%s\"", PARM_MULTICAST_PM_BUFFERING ); + DBG_PARAM( DbgInfo, PARM_NAME_INTRA_BSS_RELAY, "\"%s\"", PARM_INTRA_BSS_RELAY ); +#ifdef USE_WDS + DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD1, "%d", PARM_RTS_THRESHOLD1 ); + DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD2, "%d", PARM_RTS_THRESHOLD2 ); + DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD3, "%d", PARM_RTS_THRESHOLD3 ); + DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD4, "%d", PARM_RTS_THRESHOLD4 ); + DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD5, "%d", PARM_RTS_THRESHOLD5 ); + DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD6, "%d", PARM_RTS_THRESHOLD6 ); + DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE1, "%d", PARM_TX_RATE1 ); + DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE2, "%d", PARM_TX_RATE2 ); + DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE3, "%d", PARM_TX_RATE3 ); + DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE4, "%d", PARM_TX_RATE4 ); + DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE5, "%d", PARM_TX_RATE5 ); + DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE6, "%d", PARM_TX_RATE6 ); + DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS1, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS1 )); + DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS2, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS2 )); + DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS3, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS3 )); + DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS4, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS4 )); + DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS5, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS5 )); + DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS6, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS6 )); +#endif /* USE_WDS */ +#endif /* HCF_AP */ + + VALID_PARAM( !PARM_DESIRED_SSID || ( strlen( PARM_DESIRED_SSID ) <= PARM_MAX_NAME_LEN )); + VALID_PARAM( !PARM_OWN_SSID || ( strlen( PARM_OWN_SSID ) <= PARM_MAX_NAME_LEN )); + VALID_PARAM(( PARM_OWN_CHANNEL <= PARM_MAX_OWN_CHANNEL )); + VALID_PARAM(( PARM_SYSTEM_SCALE >= PARM_MIN_SYSTEM_SCALE ) && ( PARM_SYSTEM_SCALE <= PARM_MAX_SYSTEM_SCALE )); + VALID_PARAM(( PARM_TX_RATE >= PARM_MIN_TX_RATE ) && ( PARM_TX_RATE <= PARM_MAX_TX_RATE )); + VALID_PARAM(( PARM_RTS_THRESHOLD <= PARM_MAX_RTS_THRESHOLD )); + VALID_PARAM( !PARM_MICROWAVE_ROBUSTNESS || strchr( "NnYy", PARM_MICROWAVE_ROBUSTNESS[0] ) != NULL ); + VALID_PARAM( !PARM_OWN_NAME || ( strlen( PARM_NAME_OWN_NAME ) <= PARM_MAX_NAME_LEN )); + VALID_PARAM(( PARM_ENABLE_ENCRYPTION <= PARM_MAX_ENABLE_ENCRYPTION )); + VALID_PARAM( is_valid_key_string( PARM_KEY1 )); + VALID_PARAM( is_valid_key_string( PARM_KEY2 )); + VALID_PARAM( is_valid_key_string( PARM_KEY3 )); + VALID_PARAM( is_valid_key_string( PARM_KEY4 )); + VALID_PARAM(( PARM_TX_KEY >= PARM_MIN_TX_KEY ) && ( PARM_TX_KEY <= PARM_MAX_TX_KEY )); + + VALID_PARAM(( PARM_MULTICAST_RATE >= PARM_MIN_MULTICAST_RATE ) && + ( PARM_MULTICAST_RATE <= PARM_MAX_MULTICAST_RATE )); + + VALID_PARAM( !PARM_DOWNLOAD_FIRMWARE || ( strlen( PARM_DOWNLOAD_FIRMWARE ) <= 255 /*;?*/ )); + VALID_PARAM(( PARM_AUTH_KEY_MGMT_SUITE < PARM_MAX_AUTH_KEY_MGMT_SUITE )); + + VALID_PARAM( !PARM_LOAD_BALANCING || strchr( "NnYy", PARM_LOAD_BALANCING[0] ) != NULL ); + VALID_PARAM( !PARM_MEDIUM_DISTRIBUTION || strchr( "NnYy", PARM_MEDIUM_DISTRIBUTION[0] ) != NULL ); + VALID_PARAM(( PARM_TX_POW_LEVEL <= PARM_MAX_TX_POW_LEVEL )); + + VALID_PARAM(( PARM_PORT_TYPE >= PARM_MIN_PORT_TYPE ) && ( PARM_PORT_TYPE <= PARM_MAX_PORT_TYPE )); + VALID_PARAM( PARM_PM_ENABLED <= WVLAN_PM_STATE_STANDARD || + ( PARM_PM_ENABLED & 0x7FFF ) <= WVLAN_PM_STATE_STANDARD ); + VALID_PARAM( !PARM_CREATE_IBSS || strchr( "NnYy", PARM_CREATE_IBSS[0] ) != NULL ); + VALID_PARAM( !PARM_MULTICAST_RX || strchr( "NnYy", PARM_MULTICAST_RX[0] ) != NULL ); + VALID_PARAM(( PARM_MAX_SLEEP <= PARM_MAX_MAX_PM_SLEEP )); + VALID_PARAM(( PARM_AUTHENTICATION <= PARM_MAX_AUTHENTICATION )); + VALID_PARAM(( PARM_OWN_ATIM_WINDOW <= PARM_MAX_OWN_ATIM_WINDOW )); + VALID_PARAM(( PARM_PM_HOLDOVER_DURATION <= PARM_MAX_PM_HOLDOVER_DURATION )); + VALID_PARAM( !PARM_PROMISCUOUS_MODE || strchr( "NnYy", PARM_PROMISCUOUS_MODE[0] ) != NULL ); + VALID_PARAM(( PARM_CONNECTION_CONTROL <= PARM_MAX_CONNECTION_CONTROL )); + + VALID_PARAM(( PARM_OWN_DTIM_PERIOD >= PARM_MIN_OWN_DTIM_PERIOD )); + VALID_PARAM( !PARM_REJECT_ANY || strchr( "NnYy", PARM_REJECT_ANY[0] ) != NULL ); + VALID_PARAM( !PARM_EXCLUDE_UNENCRYPTED || strchr( "NnYy", PARM_EXCLUDE_UNENCRYPTED[0] ) != NULL ); + VALID_PARAM( !PARM_MULTICAST_PM_BUFFERING || strchr( "NnYy", PARM_MULTICAST_PM_BUFFERING[0] ) != NULL ); + VALID_PARAM( !PARM_INTRA_BSS_RELAY || strchr( "NnYy", PARM_INTRA_BSS_RELAY[0] ) != NULL ); +#ifdef USE_WDS + VALID_PARAM(( PARM_RTS_THRESHOLD1 <= PARM_MAX_RTS_THRESHOLD )); + VALID_PARAM(( PARM_RTS_THRESHOLD2 <= PARM_MAX_RTS_THRESHOLD )); + VALID_PARAM(( PARM_RTS_THRESHOLD3 <= PARM_MAX_RTS_THRESHOLD )); + VALID_PARAM(( PARM_RTS_THRESHOLD4 <= PARM_MAX_RTS_THRESHOLD )); + VALID_PARAM(( PARM_RTS_THRESHOLD5 <= PARM_MAX_RTS_THRESHOLD )); + VALID_PARAM(( PARM_RTS_THRESHOLD6 <= PARM_MAX_RTS_THRESHOLD )); + VALID_PARAM(( PARM_TX_RATE1 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE1 <= PARM_MAX_TX_RATE )); + VALID_PARAM(( PARM_TX_RATE2 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE2 <= PARM_MAX_TX_RATE )); + VALID_PARAM(( PARM_TX_RATE3 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE3 <= PARM_MAX_TX_RATE )); + VALID_PARAM(( PARM_TX_RATE4 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE4 <= PARM_MAX_TX_RATE )); + VALID_PARAM(( PARM_TX_RATE5 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE5 <= PARM_MAX_TX_RATE )); + VALID_PARAM(( PARM_TX_RATE6 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE6 <= PARM_MAX_TX_RATE )); +#endif /* USE_WDS */ + + VALID_PARAM(( PARM_OWN_BEACON_INTERVAL >= PARM_MIN_OWN_BEACON_INTERVAL ) && ( PARM_OWN_BEACON_INTERVAL <= PARM_MAX_OWN_BEACON_INTERVAL )); + VALID_PARAM(( PARM_COEXISTENCE <= PARM_COEXISTENCE )); + + /* Set the driver parameters from the passed in parameters. */ + + /* THESE MODULE PARAMETERS ARE TO BE DEPRECATED IN FAVOR OF A NAMING CONVENTION + WHICH IS INLINE WITH THE FORTHCOMING WAVELAN API */ + + /* START NEW PARAMETERS */ + + lp->Channel = PARM_OWN_CHANNEL; + lp->DistanceBetweenAPs = PARM_SYSTEM_SCALE; + + /* Need to determine how to handle the new bands for 5GHz */ + lp->TxRateControl[0] = PARM_DEFAULT_TX_RATE_2GHZ; + lp->TxRateControl[1] = PARM_DEFAULT_TX_RATE_5GHZ; + + lp->RTSThreshold = PARM_RTS_THRESHOLD; + + /* Need to determine how to handle the new bands for 5GHz */ + lp->MulticastRate[0] = PARM_DEFAULT_MULTICAST_RATE_2GHZ; + lp->MulticastRate[1] = PARM_DEFAULT_MULTICAST_RATE_5GHZ; + + if ( strchr( "Yy", PARM_MICROWAVE_ROBUSTNESS[0] ) != NULL ) { + lp->MicrowaveRobustness = 1; + } else { + lp->MicrowaveRobustness = 0; + } + if ( PARM_DESIRED_SSID && ( strlen( PARM_DESIRED_SSID ) <= HCF_MAX_NAME_LEN )) { + strcpy( lp->NetworkName, PARM_DESIRED_SSID ); + } + if ( PARM_OWN_SSID && ( strlen( PARM_OWN_SSID ) <= HCF_MAX_NAME_LEN )) { + strcpy( lp->NetworkName, PARM_OWN_SSID ); + } + if ( PARM_OWN_NAME && ( strlen( PARM_OWN_NAME ) <= HCF_MAX_NAME_LEN )) { + strcpy( lp->StationName, PARM_OWN_NAME ); + } + lp->EnableEncryption = PARM_ENABLE_ENCRYPTION; + if ( PARM_KEY1 && ( strlen( PARM_KEY1 ) <= MAX_KEY_LEN )) { + strcpy( lp->Key1, PARM_KEY1 ); + } + if ( PARM_KEY2 && ( strlen( PARM_KEY2 ) <= MAX_KEY_LEN )) { + strcpy( lp->Key2, PARM_KEY2 ); + } + if ( PARM_KEY3 && ( strlen( PARM_KEY3 ) <= MAX_KEY_LEN )) { + strcpy( lp->Key3, PARM_KEY3 ); + } + if ( PARM_KEY4 && ( strlen( PARM_KEY4 ) <= MAX_KEY_LEN )) { + strcpy( lp->Key4, PARM_KEY4 ); + } + + lp->TransmitKeyID = PARM_TX_KEY; + + key_string2key( lp->Key1, &(lp->DefaultKeys.key[0] )); + key_string2key( lp->Key2, &(lp->DefaultKeys.key[1] )); + key_string2key( lp->Key3, &(lp->DefaultKeys.key[2] )); + key_string2key( lp->Key4, &(lp->DefaultKeys.key[3] )); + + lp->DownloadFirmware = 1 ; //;?to be upgraded PARM_DOWNLOAD_FIRMWARE; + lp->AuthKeyMgmtSuite = PARM_AUTH_KEY_MGMT_SUITE; + + if ( strchr( "Yy", PARM_LOAD_BALANCING[0] ) != NULL ) { + lp->loadBalancing = 1; + } else { + lp->loadBalancing = 0; + } + + if ( strchr( "Yy", PARM_MEDIUM_DISTRIBUTION[0] ) != NULL ) { + lp->mediumDistribution = 1; + } else { + lp->mediumDistribution = 0; + } + + lp->txPowLevel = PARM_TX_POW_LEVEL; + + lp->srsc[0] = PARM_SRSC_2GHZ; + lp->srsc[1] = PARM_SRSC_5GHZ; + lp->brsc[0] = PARM_BRSC_2GHZ; + lp->brsc[1] = PARM_BRSC_5GHZ; +#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA +//;?seems reasonable that even an AP-only driver could afford this small additional footprint + lp->PortType = PARM_PORT_TYPE; + lp->MaxSleepDuration = PARM_MAX_SLEEP; + lp->authentication = PARM_AUTHENTICATION; + lp->atimWindow = PARM_OWN_ATIM_WINDOW; + lp->holdoverDuration = PARM_PM_HOLDOVER_DURATION; + lp->PMEnabled = PARM_PM_ENABLED; //;? + if ( strchr( "Yy", PARM_CREATE_IBSS[0] ) != NULL ) { + lp->CreateIBSS = 1; + } else { + lp->CreateIBSS = 0; + } + if ( strchr( "Nn", PARM_MULTICAST_RX[0] ) != NULL ) { + lp->MulticastReceive = 0; + } else { + lp->MulticastReceive = 1; + } + if ( strchr( "Yy", PARM_PROMISCUOUS_MODE[0] ) != NULL ) { + lp->promiscuousMode = 1; + } else { + lp->promiscuousMode = 0; + } + for( i = 0; i < ETH_ALEN; i++ ) { + lp->MACAddress[i] = PARM_NETWORK_ADDR[i]; + } + + lp->connectionControl = PARM_CONNECTION_CONTROL; + +#endif /* HCF_STA */ +#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP + //;?should we restore this to allow smaller memory footprint + lp->DTIMPeriod = PARM_OWN_DTIM_PERIOD; + + if ( strchr( "Yy", PARM_REJECT_ANY[0] ) != NULL ) { + lp->RejectAny = 1; + } else { + lp->RejectAny = 0; + } + if ( strchr( "Nn", PARM_EXCLUDE_UNENCRYPTED[0] ) != NULL ) { + lp->ExcludeUnencrypted = 0; + } else { + lp->ExcludeUnencrypted = 1; + } + if ( strchr( "Yy", PARM_MULTICAST_PM_BUFFERING[0] ) != NULL ) { + lp->multicastPMBuffering = 1; + } else { + lp->multicastPMBuffering = 0; + } + if ( strchr( "Yy", PARM_INTRA_BSS_RELAY[0] ) != NULL ) { + lp->intraBSSRelay = 1; + } else { + lp->intraBSSRelay = 0; + } + + lp->ownBeaconInterval = PARM_OWN_BEACON_INTERVAL; + lp->coexistence = PARM_COEXISTENCE; + +#ifdef USE_WDS + lp->wds_port[0].rtsThreshold = PARM_RTS_THRESHOLD1; + lp->wds_port[1].rtsThreshold = PARM_RTS_THRESHOLD2; + lp->wds_port[2].rtsThreshold = PARM_RTS_THRESHOLD3; + lp->wds_port[3].rtsThreshold = PARM_RTS_THRESHOLD4; + lp->wds_port[4].rtsThreshold = PARM_RTS_THRESHOLD5; + lp->wds_port[5].rtsThreshold = PARM_RTS_THRESHOLD6; + lp->wds_port[0].txRateCntl = PARM_TX_RATE1; + lp->wds_port[1].txRateCntl = PARM_TX_RATE2; + lp->wds_port[2].txRateCntl = PARM_TX_RATE3; + lp->wds_port[3].txRateCntl = PARM_TX_RATE4; + lp->wds_port[4].txRateCntl = PARM_TX_RATE5; + lp->wds_port[5].txRateCntl = PARM_TX_RATE6; + + for( i = 0; i < ETH_ALEN; i++ ) { + lp->wds_port[0].wdsAddress[i] = PARM_WDS_ADDRESS1[i]; + } + for( i = 0; i < ETH_ALEN; i++ ) { + lp->wds_port[1].wdsAddress[i] = PARM_WDS_ADDRESS2[i]; + } + for( i = 0; i < ETH_ALEN; i++ ) { + lp->wds_port[2].wdsAddress[i] = PARM_WDS_ADDRESS3[i]; + } + for( i = 0; i < ETH_ALEN; i++ ) { + lp->wds_port[3].wdsAddress[i] = PARM_WDS_ADDRESS4[i]; + } + for( i = 0; i < ETH_ALEN; i++ ) { + lp->wds_port[4].wdsAddress[i] = PARM_WDS_ADDRESS5[i]; + } + for( i = 0; i < ETH_ALEN; i++ ) { + lp->wds_port[5].wdsAddress[i] = PARM_WDS_ADDRESS6[i]; + } +#endif /* USE_WDS */ +#endif /* HCF_AP */ +#ifdef USE_RTS + if ( strchr( "Yy", useRTS[0] ) != NULL ) { + lp->useRTS = 1; + } else { + lp->useRTS = 0; + } +#endif /* USE_RTS */ + + + /* END NEW PARAMETERS */ + + + wl_lock( lp, &flags ); + + /* Initialize the portState variable */ + lp->portState = WVLAN_PORT_STATE_DISABLED; + + /* Initialize the ScanResult struct */ + memset( &( lp->scan_results ), 0, sizeof( lp->scan_results )); + lp->scan_results.scan_complete = FALSE; + + /* Initialize the ProbeResult struct */ + memset( &( lp->probe_results ), 0, sizeof( lp->probe_results )); + lp->probe_results.scan_complete = FALSE; + lp->probe_num_aps = 0; + + + /* Initialize Tx queue stuff */ + memset( lp->txList, 0, sizeof( lp->txList )); + + INIT_LIST_HEAD( &( lp->txFree )); + + lp->txF.skb = NULL; + lp->txF.port = 0; + + + for( i = 0; i < DEFAULT_NUM_TX_FRAMES; i++ ) { + list_add_tail( &( lp->txList[i].node ), &( lp->txFree )); + } + + + for( i = 0; i < WVLAN_MAX_TX_QUEUES; i++ ) { + INIT_LIST_HEAD( &( lp->txQ[i] )); + } + + lp->netif_queue_on = TRUE; + lp->txQ_count = 0; + /* Initialize the use_dma element in the adapter structure. Not sure if + this should be a compile-time or run-time configurable. So for now, + implement as run-time and just define here */ +#ifdef WARP +#ifdef ENABLE_DMA + DBG_TRACE( DbgInfo, "HERMES 2.5 BUSMASTER DMA MODE\n" ); + lp->use_dma = 1; +#else + DBG_TRACE( DbgInfo, "HERMES 2.5 PORT I/O MODE\n" ); + lp->use_dma = 0; +#endif // ENABLE_DMA +#endif // WARP + + /* Register the ISR handler information here, so that it's not done + repeatedly in the ISR */ + tasklet_init(&lp->task, wl_isr_handler, (unsigned long)lp); + + /* Connect to the adapter */ + DBG_TRACE( DbgInfo, "Calling hcf_connect()...\n" ); + hcf_status = hcf_connect( &lp->hcfCtx, dev->base_addr ); + //HCF_ERR_INCOMP_FW is acceptable, because download must still take place + //HCF_ERR_INCOMP_PRI is not acceptable + if ( hcf_status != HCF_SUCCESS && hcf_status != HCF_ERR_INCOMP_FW ) { + DBG_ERROR( DbgInfo, "hcf_connect() failed, status: 0x%x\n", hcf_status ); + wl_unlock( lp, &flags ); + goto hcf_failed; + } + + //;?should set HCF_version and how about driver_stat + lp->driverInfo.IO_address = dev->base_addr; + lp->driverInfo.IO_range = HCF_NUM_IO_PORTS; //;?conditionally 0x40 or 0x80 seems better + lp->driverInfo.IRQ_number = dev->irq; + lp->driverInfo.card_stat = lp->hcfCtx.IFB_CardStat; + //;? what happened to frame_type + + /* Fill in the driver identity structure */ + lp->driverIdentity.len = ( sizeof( lp->driverIdentity ) / sizeof( hcf_16 )) - 1; + lp->driverIdentity.typ = CFG_DRV_IDENTITY; + lp->driverIdentity.comp_id = DRV_IDENTITY; + lp->driverIdentity.variant = DRV_VARIANT; + lp->driverIdentity.version_major = DRV_MAJOR_VERSION; + lp->driverIdentity.version_minor = DRV_MINOR_VERSION; + + + /* Start the card here - This needs to be done in order to get the + MAC address for the network layer */ + DBG_TRACE( DbgInfo, "Calling wvlan_go() to perform a card reset...\n" ); + hcf_status = wl_go( lp ); + + if ( hcf_status != HCF_SUCCESS ) { + DBG_ERROR( DbgInfo, "wl_go() failed\n" ); + wl_unlock( lp, &flags ); + goto hcf_failed; + } + + /* Certain RIDs must be set before enabling the ports */ + wl_put_ltv_init( lp ); + +#if 0 //;?why was this already commented out in wl_lkm_720 + /* Enable the ports */ + if ( wl_adapter_is_open( lp->dev )) { + /* Enable the ports */ + DBG_TRACE( DbgInfo, "Enabling Port 0\n" ); + hcf_status = wl_enable( lp ); + + if ( hcf_status != HCF_SUCCESS ) { + DBG_TRACE( DbgInfo, "Enable port 0 failed: 0x%x\n", hcf_status ); + } + +#if (HCF_TYPE) & HCF_TYPE_AP + DBG_TRACE( DbgInfo, "Enabling WDS Ports\n" ); + //wl_enable_wds_ports( lp ); +#endif /* (HCF_TYPE) & HCF_TYPE_AP */ + + } +#endif + + /* Fill out the MAC address information in the net_device struct */ + memcpy( lp->dev->dev_addr, lp->MACAddress, ETH_ALEN ); + dev->addr_len = ETH_ALEN; + + lp->is_registered = TRUE; + +#ifdef USE_PROFILE + /* Parse the config file for the sake of creating WDS ports if WDS is + configured there but not in the module options */ + parse_config( dev ); +#endif /* USE_PROFILE */ + + /* If we're going into AP Mode, register the "virtual" ethernet devices + needed for WDS */ + WL_WDS_NETDEV_REGISTER( lp ); + + /* Reset the DownloadFirmware variable in the private struct. If the + config file is not used, this will not matter; if it is used, it + will be reparsed in wl_open(). This is done because logic in wl_open + used to check if a firmware download is needed is broken by parsing + the file here; however, this parsing is needed to register WDS ports + in AP mode, if they are configured */ + lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //;?download_firmware; + +#ifdef USE_RTS + if ( lp->useRTS == 1 ) { + DBG_TRACE( DbgInfo, "ENTERING RTS MODE...\n" ); + wl_act_int_off( lp ); + lp->is_handling_int = WL_NOT_HANDLING_INT; // Not handling interrupts anymore + + wl_disable( lp ); + + hcf_connect( &lp->hcfCtx, HCF_DISCONNECT); + } +#endif /* USE_RTS */ + + wl_unlock( lp, &flags ); + + DBG_TRACE( DbgInfo, "%s: Wireless, io_addr %#03lx, irq %d, ""mac_address ", + dev->name, dev->base_addr, dev->irq ); + + for( i = 0; i < ETH_ALEN; i++ ) { + printk( "%02X%c", dev->dev_addr[i], (( i < ( ETH_ALEN-1 )) ? ':' : '\n' )); + } + +#if 0 //SCULL_USE_PROC /* don't waste space if unused */ + create_proc_read_entry( "wlags", 0, NULL, scull_read_procmem, dev ); + proc_mkdir("driver/wlags49", 0); + proc_write("driver/wlags49/wlags49_type", write_int, &lp->wlags49_type); +#endif /* SCULL_USE_PROC */ + + DBG_LEAVE( DbgInfo ); + return result; + +hcf_failed: + wl_hcf_error( dev, hcf_status ); + +failed: + + DBG_ERROR( DbgInfo, "wl_insert() FAILED\n" ); + + if ( lp->is_registered == TRUE ) { + lp->is_registered = FALSE; + } + + WL_WDS_NETDEV_DEREGISTER( lp ); + + result = -EFAULT; + + + DBG_LEAVE( DbgInfo ); + return result; +} // wl_insert +/*============================================================================*/ + + +/******************************************************************************* + * wl_reset() + ******************************************************************************* + * + * DESCRIPTION: + * + * Reset the adapter. + * + * PARAMETERS: + * + * dev - a pointer to the net_device struct of the wireless device + * + * RETURNS: + * + * an HCF status code + * + ******************************************************************************/ +int wl_reset(struct net_device *dev) +{ + struct wl_private *lp = wl_priv(dev); + int hcf_status = HCF_SUCCESS; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_reset" ); + DBG_ENTER( DbgInfo ); + DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + DBG_PARAM( DbgInfo, "dev->base_addr", "(%#03lx)", dev->base_addr ); + + /* + * The caller should already have a lock and + * disable the interrupts, we do not lock here, + * nor do we enable/disable interrupts! + */ + + DBG_TRACE( DbgInfo, "Device Base Address: %#03lx\n", dev->base_addr ); + if ( dev->base_addr ) { + /* Shutdown the adapter. */ + hcf_connect( &lp->hcfCtx, HCF_DISCONNECT ); + + /* Reset the driver information. */ + lp->txBytes = 0; + + /* Connect to the adapter. */ + hcf_status = hcf_connect( &lp->hcfCtx, dev->base_addr ); + if ( hcf_status != HCF_SUCCESS && hcf_status != HCF_ERR_INCOMP_FW ) { + DBG_ERROR( DbgInfo, "hcf_connect() failed, status: 0x%x\n", hcf_status ); + goto out; + } + + /* Check if firmware is present, if not change state */ + if ( hcf_status == HCF_ERR_INCOMP_FW ) { + lp->firmware_present = WL_FRIMWARE_NOT_PRESENT; + } + + /* Initialize the portState variable */ + lp->portState = WVLAN_PORT_STATE_DISABLED; + + /* Restart the adapter. */ + hcf_status = wl_go( lp ); + if ( hcf_status != HCF_SUCCESS ) { + DBG_ERROR( DbgInfo, "wl_go() failed, status: 0x%x\n", hcf_status ); + goto out; + } + + /* Certain RIDs must be set before enabling the ports */ + wl_put_ltv_init( lp ); + } else { + DBG_ERROR( DbgInfo, "Device Base Address INVALID!!!\n" ); + } + +out: + DBG_LEAVE( DbgInfo ); + return hcf_status; +} // wl_reset +/*============================================================================*/ + + +/******************************************************************************* + * wl_go() + ******************************************************************************* + * + * DESCRIPTION: + * + * Reset the adapter. + * + * PARAMETERS: + * + * dev - a pointer to the net_device struct of the wireless device + * + * RETURNS: + * + * an HCF status code + * + ******************************************************************************/ +int wl_go( struct wl_private *lp ) +{ + int hcf_status = HCF_SUCCESS; + char *cp = NULL; //fw_image + int retries = 0; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_go" ); + DBG_ENTER( DbgInfo ); + + hcf_status = wl_disable( lp ); + if ( hcf_status != HCF_SUCCESS ) { + DBG_TRACE( DbgInfo, "Disable port 0 failed: 0x%x\n", hcf_status ); + + while (( hcf_status != HCF_SUCCESS ) && (retries < 10)) { + retries++; + hcf_status = wl_disable( lp ); + } + if ( hcf_status == HCF_SUCCESS ) { + DBG_TRACE( DbgInfo, "Disable port 0 succes : %d retries\n", retries ); + } else { + DBG_TRACE( DbgInfo, "Disable port 0 failed after: %d retries\n", retries ); + } + } + +#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP + //DBG_TRACE( DbgInfo, "Disabling WDS Ports\n" ); + //wl_disable_wds_ports( lp ); +#endif /* (HCF_TYPE) & HCF_TYPE_AP */ + +//;?what was the purpose of this +// /* load the appropriate firmware image, depending on driver mode */ +// lp->ltvRecord.len = ( sizeof( CFG_RANGE20_STRCT ) / sizeof( hcf_16 )) - 1; +// lp->ltvRecord.typ = CFG_DRV_ACT_RANGES_PRI; +// hcf_get_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + +#if BIN_DL + if ( strlen( lp->fw_image_filename ) ) { +mm_segment_t fs; +int file_desc; +int rc; + + DBG_TRACE( DbgInfo, "F/W image:%s:\n", lp->fw_image_filename ); + /* Obtain a user-space process context, storing the original context */ + fs = get_fs( ); + set_fs( get_ds( )); + file_desc = open( lp->fw_image_filename, O_RDONLY, 0 ); + if ( file_desc == -1 ) { + DBG_ERROR( DbgInfo, "No image file found\n" ); + } else { + DBG_TRACE( DbgInfo, "F/W image file found\n" ); +#define DHF_ALLOC_SIZE 96000 //just below 96K, let's hope it suffices for now and for the future + cp = (char*)vmalloc( DHF_ALLOC_SIZE ); + if ( cp == NULL ) { + DBG_ERROR( DbgInfo, "error in vmalloc\n" ); + } else { + rc = read( file_desc, cp, DHF_ALLOC_SIZE ); + if ( rc == DHF_ALLOC_SIZE ) { + DBG_ERROR( DbgInfo, "buffer too small, %d\n", DHF_ALLOC_SIZE ); + } else if ( rc > 0 ) { + DBG_TRACE( DbgInfo, "read O.K.: %d bytes %.12s\n", rc, cp ); + rc = read( file_desc, &cp[rc], 1 ); + if ( rc == 0 ) { //;/change to an until-loop at rc<=0 + DBG_TRACE( DbgInfo, "no more to read\n" ); + } + } + if ( rc != 0 ) { + DBG_ERROR( DbgInfo, "file not read in one swoop or other error"\ + ", give up, too complicated, rc = %0X\n", rc ); + DBG_ERROR( DbgInfo, "still have to change code to get a real download now !!!!!!!!\n" ); + } else { + DBG_TRACE( DbgInfo, "before dhf_download_binary\n" ); + hcf_status = dhf_download_binary( (memimage *)cp ); + DBG_TRACE( DbgInfo, "after dhf_download_binary, before dhf_download_fw\n" ); + //;?improve error flow/handling + hcf_status = dhf_download_fw( &lp->hcfCtx, (memimage *)cp ); + DBG_TRACE( DbgInfo, "after dhf_download_fw\n" ); + } + vfree( cp ); + } + close( file_desc ); + } + set_fs( fs ); /* Return to the original context */ + } +#endif // BIN_DL + + /* If firmware is present but the type is unknown then download anyway */ + if ( (lp->firmware_present == WL_FRIMWARE_PRESENT) + && + ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) != COMP_ID_FW_STA ) + && + ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) != COMP_ID_FW_AP ) ) { + /* Unknown type, download needed. */ + lp->firmware_present = WL_FRIMWARE_NOT_PRESENT; + } + + if(lp->firmware_present == WL_FRIMWARE_NOT_PRESENT) + { + if ( cp == NULL ) { + DBG_TRACE( DbgInfo, "Downloading STA firmware...\n" ); +// hcf_status = dhf_download_fw( &lp->hcfCtx, &station ); + hcf_status = dhf_download_fw( &lp->hcfCtx, &fw_image ); + } + if ( hcf_status != HCF_SUCCESS ) { + DBG_ERROR( DbgInfo, "Firmware Download failed\n" ); + DBG_LEAVE( DbgInfo ); + return hcf_status; + } + } + /* Report the FW versions */ + //;?obsolete, use the available IFB info:: wl_get_pri_records( lp ); + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) { + DBG_TRACE( DbgInfo, "downloaded station F/W\n" ); + } else if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { + DBG_TRACE( DbgInfo, "downloaded AP F/W\n" ); + } else { + DBG_ERROR( DbgInfo, "unknown F/W type\n" ); + } + + /* + * Downloaded, no need to repeat this next time, assume the + * contents stays in the card until it is powered off. Note we + * do not switch firmware on the fly, the firmware is fixed in + * the driver for now. + */ + lp->firmware_present = WL_FRIMWARE_PRESENT; + + DBG_TRACE( DbgInfo, "ComponentID:%04x variant:%04x major:%04x minor:%04x\n", + CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ), + CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.variant ), + CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.version_major ), + CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.version_minor )); + + /* now we wil get the MAC address of the card */ + lp->ltvRecord.len = 4; + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { + lp->ltvRecord.typ = CFG_NIC_MAC_ADDR; + } else + { + lp->ltvRecord.typ = CFG_CNF_OWN_MAC_ADDR; + } + hcf_status = hcf_get_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + if ( hcf_status != HCF_SUCCESS ) { + DBG_ERROR( DbgInfo, "Could not retrieve MAC address\n" ); + DBG_LEAVE( DbgInfo ); + return hcf_status; + } + memcpy( lp->MACAddress, &lp->ltvRecord.u.u8[0], ETH_ALEN ); + DBG_TRACE( DbgInfo, "Card MAC Address: %s\n", DbgHwAddr( lp->MACAddress )); + + /* Write out configuration to the device, enable, and reconnect. However, + only reconnect if in AP mode. For STA mode, need to wait for passive scan + completion before a connect can be issued */ + wl_put_ltv( lp ); + /* Enable the ports */ + hcf_status = wl_enable( lp ); + + if ( lp->DownloadFirmware == WVLAN_DRV_MODE_AP ) { +#ifdef USE_WDS + wl_enable_wds_ports( lp ); +#endif // USE_WDS + hcf_status = wl_connect( lp ); + } + DBG_LEAVE( DbgInfo ); + return hcf_status; +} // wl_go +/*============================================================================*/ + + +/******************************************************************************* + * wl_set_wep_keys() + ******************************************************************************* + * + * DESCRIPTION: + * + * Write TxKeyID and WEP keys to the adapter. This is separated from + * wl_apply() to allow dynamic WEP key updates through the wireless + * extensions. + * + * PARAMETERS: + * + * lp - a pointer to the wireless adapter's private structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_set_wep_keys( struct wl_private *lp ) +{ + int count = 0; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_set_wep_keys" ); + DBG_ENTER( DbgInfo ); + DBG_PARAM( DbgInfo, "lp", "%s (0x%p)", lp->dev->name, lp ); + if ( lp->EnableEncryption ) { + /* NOTE: CFG_CNF_ENCRYPTION is set in wl_put_ltv() as it's a static + RID */ + + /* set TxKeyID */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_TX_KEY_ID; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->TransmitKeyID - 1); + + hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + DBG_TRACE( DbgInfo, "Key 1 len: %d\n", lp->DefaultKeys.key[0].len ); + DBG_TRACE( DbgInfo, "Key 2 len: %d\n", lp->DefaultKeys.key[1].len ); + DBG_TRACE( DbgInfo, "Key 3 len: %d\n", lp->DefaultKeys.key[2].len ); + DBG_TRACE( DbgInfo, "Key 4 len: %d\n", lp->DefaultKeys.key[3].len ); + + /* write keys */ + lp->DefaultKeys.len = sizeof( lp->DefaultKeys ) / sizeof( hcf_16 ) - 1; + lp->DefaultKeys.typ = CFG_DEFAULT_KEYS; + + /* endian translate the appropriate key information */ + for( count = 0; count < MAX_KEYS; count++ ) { + lp->DefaultKeys.key[count].len = CNV_INT_TO_LITTLE( lp->DefaultKeys.key[count].len ); + } + + hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->DefaultKeys )); + + /* Reverse the above endian translation, since these keys are accessed + elsewhere */ + for( count = 0; count < MAX_KEYS; count++ ) { + lp->DefaultKeys.key[count].len = CNV_INT_TO_LITTLE( lp->DefaultKeys.key[count].len ); + } + + DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID ); + DBG_NOTICE( DbgInfo, "set key: %s(%d) [%d]\n", lp->DefaultKeys.key[lp->TransmitKeyID-1].key, lp->DefaultKeys.key[lp->TransmitKeyID-1].len, lp->TransmitKeyID-1 ); + } + + DBG_LEAVE( DbgInfo ); +} // wl_set_wep_keys +/*============================================================================*/ + + +/******************************************************************************* + * wl_apply() + ******************************************************************************* + * + * DESCRIPTION: + * + * Write the parameters to the adapter. (re-)enables the card if device is + * open. Returns hcf_status of hcf_enable(). + * + * PARAMETERS: + * + * lp - a pointer to the wireless adapter's private structure + * + * RETURNS: + * + * an HCF status code + * + ******************************************************************************/ +int wl_apply(struct wl_private *lp) +{ + int hcf_status = HCF_SUCCESS; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_apply" ); + DBG_ENTER( DbgInfo ); + DBG_ASSERT( lp != NULL); + DBG_PARAM( DbgInfo, "lp", "%s (0x%p)", lp->dev->name, lp ); + + if ( !( lp->flags & WVLAN2_UIL_BUSY )) { + /* The adapter parameters have changed: + disable card + reload parameters + enable card + */ + + if ( wl_adapter_is_open( lp->dev )) { + /* Disconnect and disable if necessary */ + hcf_status = wl_disconnect( lp ); + if ( hcf_status != HCF_SUCCESS ) { + DBG_ERROR( DbgInfo, "Disconnect failed\n" ); + DBG_LEAVE( DbgInfo ); + return -1; + } + hcf_status = wl_disable( lp ); + if ( hcf_status != HCF_SUCCESS ) { + DBG_ERROR( DbgInfo, "Disable failed\n" ); + DBG_LEAVE( DbgInfo ); + return -1; + } else { + /* Write out configuration to the device, enable, and reconnect. + However, only reconnect if in AP mode. For STA mode, need to + wait for passive scan completion before a connect can be + issued */ + hcf_status = wl_put_ltv( lp ); + + if ( hcf_status == HCF_SUCCESS ) { + hcf_status = wl_enable( lp ); + + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { + hcf_status = wl_connect( lp ); + } + } else { + DBG_WARNING( DbgInfo, "wl_put_ltv() failed\n" ); + } + } + } + } + + DBG_LEAVE( DbgInfo ); + return hcf_status; +} // wl_apply +/*============================================================================*/ + + +/******************************************************************************* + * wl_put_ltv_init() + ******************************************************************************* + * + * DESCRIPTION: + * + * Used to set basic parameters for card initialization. + * + * PARAMETERS: + * + * lp - a pointer to the wireless adapter's private structure + * + * RETURNS: + * + * an HCF status code + * + ******************************************************************************/ +int wl_put_ltv_init( struct wl_private *lp ) +{ + int i; + int hcf_status; + CFG_RID_LOG_STRCT *RidLog; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_put_ltv_init" ); + DBG_ENTER( DbgInfo ); + if ( lp == NULL ) { + DBG_ERROR( DbgInfo, "lp pointer is NULL\n" ); + DBG_LEAVE( DbgInfo ); + return -1; + } + /* DMA/IO */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNTL_OPT; + + /* The Card Services build must ALWAYS configure for 16-bit I/O. PCI or + CardBus can be set to either 16/32 bit I/O, or Bus Master DMA, but only + for Hermes-2.5 */ +#ifdef BUS_PCMCIA + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( USE_16BIT ); +#else + if ( lp->use_dma ) { + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( USE_DMA ); + } else { + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); + } + +#endif + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + DBG_TRACE( DbgInfo, "CFG_CNTL_OPT : 0x%04x\n", + lp->ltvRecord.u.u16[0] ); + DBG_TRACE( DbgInfo, "CFG_CNTL_OPT result : 0x%04x\n", + hcf_status ); + + /* Register the list of RIDs on which asynchronous notification is + required. Note that this mechanism replaces the mailbox, so the mailbox + can be queried by the host (if desired) without contention from us */ + i=0; + + lp->RidList[i].len = sizeof( lp->ProbeResp ); + lp->RidList[i].typ = CFG_ACS_SCAN; + lp->RidList[i].bufp = (wci_recordp)&lp->ProbeResp; + //lp->ProbeResp.infoType = 0xFFFF; + i++; + + lp->RidList[i].len = sizeof( lp->assoc_stat ); + lp->RidList[i].typ = CFG_ASSOC_STAT; + lp->RidList[i].bufp = (wci_recordp)&lp->assoc_stat; + lp->assoc_stat.len = 0xFFFF; + i++; + + lp->RidList[i].len = 4; + lp->RidList[i].typ = CFG_UPDATED_INFO_RECORD; + lp->RidList[i].bufp = (wci_recordp)&lp->updatedRecord; + lp->updatedRecord.len = 0xFFFF; + i++; + + lp->RidList[i].len = sizeof( lp->sec_stat ); + lp->RidList[i].typ = CFG_SECURITY_STAT; + lp->RidList[i].bufp = (wci_recordp)&lp->sec_stat; + lp->sec_stat.len = 0xFFFF; + i++; + + lp->RidList[i].typ = 0; // Terminate List + + RidLog = (CFG_RID_LOG_STRCT *)&lp->ltvRecord; + RidLog->len = 3; + RidLog->typ = CFG_REG_INFO_LOG; + RidLog->recordp = (RID_LOGP)&lp->RidList[0]; + + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + DBG_TRACE( DbgInfo, "CFG_REG_INFO_LOG\n" ); + DBG_TRACE( DbgInfo, "CFG_REG_INFO_LOG result : 0x%04x\n", + hcf_status ); + DBG_LEAVE( DbgInfo ); + return hcf_status; +} // wl_put_ltv_init +/*============================================================================*/ + + +/******************************************************************************* + * wl_put_ltv() + ******************************************************************************* + * + * DESCRIPTION: + * + * Used by wvlan_apply() and wvlan_go to set the card's configuration. + * + * PARAMETERS: + * + * lp - a pointer to the wireless adapter's private structure + * + * RETURNS: + * + * an HCF status code + * + ******************************************************************************/ +int wl_put_ltv( struct wl_private *lp ) +{ + int len; + int hcf_status; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_put_ltv" ); + DBG_ENTER( DbgInfo ); + + if ( lp == NULL ) { + DBG_ERROR( DbgInfo, "lp pointer is NULL\n" ); + return -1; + } + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { + lp->maxPort = 6; //;?why set this here and not as part of download process + } else { + lp->maxPort = 0; + } + + /* Send our configuration to the card. Perform any endian translation + necessary */ + /* Register the Mailbox; VxWorks does this elsewhere; why;? */ + lp->ltvRecord.len = 4; + lp->ltvRecord.typ = CFG_REG_MB; + lp->ltvRecord.u.u32[0] = (u_long)&( lp->mailbox ); + lp->ltvRecord.u.u16[2] = ( MB_SIZE / sizeof( hcf_16 )); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Max Data Length */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_MAX_DATA_LEN; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( HCF_MAX_PACKET_SIZE ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* System Scale / Distance between APs */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_SYSTEM_SCALE; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->DistanceBetweenAPs ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Channel */ + if ( lp->CreateIBSS && ( lp->Channel == 0 )) { + DBG_TRACE( DbgInfo, "Create IBSS" ); + lp->Channel = 10; + } + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_OWN_CHANNEL; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->Channel ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Microwave Robustness */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_MICRO_WAVE; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->MicrowaveRobustness ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Load Balancing */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_LOAD_BALANCING; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->loadBalancing ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Medium Distribution */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_MEDIUM_DISTRIBUTION; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->mediumDistribution ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + /* Country Code */ + +#ifdef WARP + /* Tx Power Level (for supported cards) */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_TX_POW_LVL; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->txPowLevel ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Short Retry Limit */ + /*lp->ltvRecord.len = 2; + lp->ltvRecord.typ = 0xFC32; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->shortRetryLimit ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + */ + + /* Long Retry Limit */ + /*lp->ltvRecord.len = 2; + lp->ltvRecord.typ = 0xFC33; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->longRetryLimit ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + */ + + /* Supported Rate Set Control */ + lp->ltvRecord.len = 3; + lp->ltvRecord.typ = CFG_SUPPORTED_RATE_SET_CNTL; //0xFC88; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->srsc[0] ); + lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->srsc[1] ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Basic Rate Set Control */ + lp->ltvRecord.len = 3; + lp->ltvRecord.typ = CFG_BASIC_RATE_SET_CNTL; //0xFC89; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->brsc[0] ); + lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->brsc[1] ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Frame Burst Limit */ + /* Defined, but not currently available in Firmware */ + +#endif // WARP + +#ifdef WARP + /* Multicast Rate */ + lp->ltvRecord.len = 3; + lp->ltvRecord.typ = CFG_CNF_MCAST_RATE; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->MulticastRate[0] ); + lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->MulticastRate[1] ); +#else + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_MCAST_RATE; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->MulticastRate[0] ); +#endif // WARP + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Own Name (Station Nickname) */ + if (( len = ( strlen( lp->StationName ) + 1 ) & ~0x01 ) != 0 ) { + //DBG_TRACE( DbgInfo, "CFG_CNF_OWN_NAME : %s\n", + // lp->StationName ); + + lp->ltvRecord.len = 2 + ( len / sizeof( hcf_16 )); + lp->ltvRecord.typ = CFG_CNF_OWN_NAME; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( strlen( lp->StationName )); + + memcpy( &( lp->ltvRecord.u.u8[2] ), lp->StationName, len ); + } else { + //DBG_TRACE( DbgInfo, "CFG_CNF_OWN_NAME : EMPTY\n" ); + + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_OWN_NAME; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); + } + + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + //DBG_TRACE( DbgInfo, "CFG_CNF_OWN_NAME result : 0x%04x\n", + // hcf_status ); + + /* The following are set in STA mode only */ + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) { + + /* RTS Threshold */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_RTS_THRH; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->RTSThreshold ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Port Type */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_PORT_TYPE; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->PortType ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Tx Rate Control */ +#ifdef WARP + lp->ltvRecord.len = 3; + lp->ltvRecord.typ = CFG_TX_RATE_CNTL; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->TxRateControl[0] ); + lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->TxRateControl[1] ); +#else + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_TX_RATE_CNTL; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->TxRateControl[0] ); +#endif // WARP + +//;?skip temporarily to see whether the RID or something else is the probelm hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL 2.4GHz : 0x%04x\n", + lp->TxRateControl[0] ); + DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL 5.0GHz : 0x%04x\n", + lp->TxRateControl[1] ); + DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL result : 0x%04x\n", + hcf_status ); + /* Power Management */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_PM_ENABLED; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->PMEnabled ); +// lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x8001 ); + DBG_TRACE( DbgInfo, "CFG_CNF_PM_ENABLED : 0x%04x\n", lp->PMEnabled ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + /* Multicast Receive */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_MCAST_RX; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->MulticastReceive ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Max Sleep Duration */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_MAX_SLEEP_DURATION; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->MaxSleepDuration ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Create IBSS */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CREATE_IBSS; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->CreateIBSS ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Desired SSID */ + if ((( len = ( strlen( lp->NetworkName ) + 1 ) & ~0x01 ) != 0 ) && + ( strcmp( lp->NetworkName, "ANY" ) != 0 ) && + ( strcmp( lp->NetworkName, "any" ) != 0 )) { + //DBG_TRACE( DbgInfo, "CFG_DESIRED_SSID : %s\n", + // lp->NetworkName ); + + lp->ltvRecord.len = 2 + (len / sizeof(hcf_16)); + lp->ltvRecord.typ = CFG_DESIRED_SSID; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( strlen( lp->NetworkName )); + + memcpy( &( lp->ltvRecord.u.u8[2] ), lp->NetworkName, len ); + } else { + //DBG_TRACE( DbgInfo, "CFG_DESIRED_SSID : ANY\n" ); + + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_DESIRED_SSID; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); + } + + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + //DBG_TRACE( DbgInfo, "CFG_DESIRED_SSID result : 0x%04x\n", + // hcf_status ); + /* Own ATIM window */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_OWN_ATIM_WINDOW; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->atimWindow ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + + /* Holdover Duration */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_HOLDOVER_DURATION; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->holdoverDuration ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Promiscuous Mode */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_PROMISCUOUS_MODE; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->promiscuousMode ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Authentication */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_AUTHENTICATION; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->authentication ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); +#ifdef WARP + /* Connection Control */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_CONNECTION_CNTL; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->connectionControl ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + + + /* Probe data rate */ + /*lp->ltvRecord.len = 3; + lp->ltvRecord.typ = CFG_PROBE_DATA_RATE; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->probeDataRates[0] ); + lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->probeDataRates[1] ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + DBG_TRACE( DbgInfo, "CFG_PROBE_DATA_RATE 2.4GHz : 0x%04x\n", + lp->probeDataRates[0] ); + DBG_TRACE( DbgInfo, "CFG_PROBE_DATA_RATE 5.0GHz : 0x%04x\n", + lp->probeDataRates[1] ); + DBG_TRACE( DbgInfo, "CFG_PROBE_DATA_RATE result : 0x%04x\n", + hcf_status );*/ +#endif // WARP + } else { + /* The following are set in AP mode only */ +#if 0 //;? (HCF_TYPE) & HCF_TYPE_AP + //;?should we restore this to allow smaller memory footprint + + /* DTIM Period */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_OWN_DTIM_PERIOD; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->DTIMPeriod ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Multicast PM Buffering */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_MCAST_PM_BUF; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->multicastPMBuffering ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Reject ANY - Closed System */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_REJECT_ANY; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->RejectAny ); + + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Exclude Unencrypted */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_EXCL_UNENCRYPTED; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->ExcludeUnencrypted ); + + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* IntraBSS Relay */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_INTRA_BSS_RELAY; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->intraBSSRelay ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* RTS Threshold 0 */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_RTS_THRH0; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->RTSThreshold ); + + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Tx Rate Control 0 */ +#ifdef WARP + lp->ltvRecord.len = 3; + lp->ltvRecord.typ = CFG_TX_RATE_CNTL0; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->TxRateControl[0] ); + lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->TxRateControl[1] ); +#else + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_TX_RATE_CNTL0; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->TxRateControl[0] ); +#endif // WARP + + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Own Beacon Interval */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = 0xFC31; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->ownBeaconInterval ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Co-Existence Behavior */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = 0xFCC7; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->coexistence ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + +#ifdef USE_WDS + + /* RTS Threshold 1 */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_RTS_THRH1; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[0].rtsThreshold ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* RTS Threshold 2 */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_RTS_THRH2; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[1].rtsThreshold ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + + /* RTS Threshold 3 */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_RTS_THRH3; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[2].rtsThreshold ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + + /* RTS Threshold 4 */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_RTS_THRH4; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[3].rtsThreshold ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + + /* RTS Threshold 5 */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_RTS_THRH5; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[4].rtsThreshold ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* RTS Threshold 6 */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_RTS_THRH6; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[5].rtsThreshold ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); +#if 0 + /* TX Rate Control 1 */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_TX_RATE_CNTL1; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[0].txRateCntl ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* TX Rate Control 2 */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_TX_RATE_CNTL2; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[1].txRateCntl ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* TX Rate Control 3 */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_TX_RATE_CNTL3; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[2].txRateCntl ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* TX Rate Control 4 */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_TX_RATE_CNTL4; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[3].txRateCntl ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* TX Rate Control 5 */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_TX_RATE_CNTL5; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[4].txRateCntl ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* TX Rate Control 6 */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_TX_RATE_CNTL6; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[5].txRateCntl ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + +#endif + + /* WDS addresses. It's okay to blindly send these parameters, because + the port needs to be enabled, before anything is done with it. */ + + /* WDS Address 1 */ + lp->ltvRecord.len = 4; + lp->ltvRecord.typ = CFG_CNF_WDS_ADDR1; + + memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[0].wdsAddress, ETH_ALEN ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* WDS Address 2 */ + lp->ltvRecord.len = 4; + lp->ltvRecord.typ = CFG_CNF_WDS_ADDR2; + + memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[1].wdsAddress, ETH_ALEN ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* WDS Address 3 */ + lp->ltvRecord.len = 4; + lp->ltvRecord.typ = CFG_CNF_WDS_ADDR3; + + memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[2].wdsAddress, ETH_ALEN ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* WDS Address 4 */ + lp->ltvRecord.len = 4; + lp->ltvRecord.typ = CFG_CNF_WDS_ADDR4; + + memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[3].wdsAddress, ETH_ALEN ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* WDS Address 5 */ + lp->ltvRecord.len = 4; + lp->ltvRecord.typ = CFG_CNF_WDS_ADDR5; + + memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[4].wdsAddress, ETH_ALEN ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* WDS Address 6 */ + lp->ltvRecord.len = 4; + lp->ltvRecord.typ = CFG_CNF_WDS_ADDR6; + + memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[5].wdsAddress, ETH_ALEN ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); +#endif /* USE_WDS */ +#endif /* (HCF_TYPE) & HCF_TYPE_AP */ + } + + /* Own MAC Address */ + //DBG_TRACE( DbgInfo, "MAC Address : %s\n", + // DbgHwAddr( lp->MACAddress )); + + if ( WVLAN_VALID_MAC_ADDRESS( lp->MACAddress )) { + /* Make the MAC address valid by: + Clearing the multicast bit + Setting the local MAC address bit + */ + //lp->MACAddress[0] &= ~0x03; //;?why is this commented out already in 720 + //lp->MACAddress[0] |= 0x02; + + lp->ltvRecord.len = 1 + ( ETH_ALEN / sizeof( hcf_16 )); + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { + //DBG_TRACE( DbgInfo, "CFG_NIC_MAC_ADDR\n" ); + lp->ltvRecord.typ = CFG_NIC_MAC_ADDR; + } else { + //DBG_TRACE( DbgInfo, "CFG_CNF_OWN_MAC_ADDR\n" ); + lp->ltvRecord.typ = CFG_CNF_OWN_MAC_ADDR; + } + /* MAC address is byte aligned, no endian conversion needed */ + memcpy( &( lp->ltvRecord.u.u8[0] ), lp->MACAddress, ETH_ALEN ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + //DBG_TRACE( DbgInfo, "CFG_XXX_MAC_ADDR result : 0x%04x\n", + // hcf_status ); + + /* Update the MAC address in the netdevice struct */ + memcpy( lp->dev->dev_addr, lp->MACAddress, ETH_ALEN ); //;?what is the purpose of this seemingly complex logic + } + /* Own SSID */ + if ((( len = ( strlen( lp->NetworkName ) + 1 ) & ~0x01 ) != 0 ) && + ( strcmp( lp->NetworkName, "ANY" ) != 0 ) && + ( strcmp( lp->NetworkName, "any" ) != 0 )) { + //DBG_TRACE( DbgInfo, "CFG_CNF_OWN_SSID : %s\n", + // lp->NetworkName ); + lp->ltvRecord.len = 2 + (len / sizeof(hcf_16)); + lp->ltvRecord.typ = CFG_CNF_OWN_SSID; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( strlen( lp->NetworkName )); + + memcpy( &( lp->ltvRecord.u.u8[2] ), lp->NetworkName, len ); + } else { + //DBG_TRACE( DbgInfo, "CFG_CNF_OWN_SSID : ANY\n" ); + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_OWN_SSID; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); + } + + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + //DBG_TRACE( DbgInfo, "CFG_CNF_OWN_SSID result : 0x%04x\n", + // hcf_status ); + /* enable/disable encryption */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_ENCRYPTION; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->EnableEncryption ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + /* Set the Authentication Key Management Suite */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->AuthKeyMgmtSuite ); + hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + /* WEP Keys */ + wl_set_wep_keys( lp ); + + /* Country Code */ + /* countryInfo, ltvCountryInfo, CFG_CNF_COUNTRY_INFO */ + + DBG_LEAVE( DbgInfo ); + return hcf_status; +} // wl_put_ltv +/*============================================================================*/ + + +/******************************************************************************* + * init_module() + ******************************************************************************* + * + * DESCRIPTION: + * + * Load the kernel module. + * + * PARAMETERS: + * + * N/A + * + * RETURNS: + * + * 0 on success + * an errno value otherwise + * + ******************************************************************************/ +static int __init wl_module_init( void ) +{ + int result; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_module_init" ); + +#if DBG + /* Convert "standard" PCMCIA parameter pc_debug to a reasonable DebugFlag value. + * NOTE: The values all fall through to the lower values. */ + DbgInfo->DebugFlag = 0; + DbgInfo->DebugFlag = DBG_TRACE_ON; //;?get this mess resolved one day + if ( pc_debug ) switch( pc_debug ) { + case 8: + DbgInfo->DebugFlag |= DBG_DS_ON; + case 7: + DbgInfo->DebugFlag |= DBG_RX_ON | DBG_TX_ON; + case 6: + DbgInfo->DebugFlag |= DBG_PARAM_ON; + case 5: + DbgInfo->DebugFlag |= DBG_TRACE_ON; + case 4: + DbgInfo->DebugFlag |= DBG_VERBOSE_ON; + case 1: + DbgInfo->DebugFlag |= DBG_DEFAULTS; + default: + break; + } +#endif /* DBG */ + + DBG_ENTER( DbgInfo ); + printk(KERN_INFO "%s\n", VERSION_INFO); + printk(KERN_INFO "*** Modified for kernel 2.6 by Henk de Groot \n"); + printk(KERN_INFO "*** Based on 7.18 version by Andrey Borzenkov $Revision: 39 $\n"); + + +// ;?#if (HCF_TYPE) & HCF_TYPE_AP +// DBG_PRINT( "Access Point Mode (AP) Support: YES\n" ); +// #else +// DBG_PRINT( "Access Point Mode (AP) Support: NO\n" ); +// #endif /* (HCF_TYPE) & HCF_TYPE_AP */ + + result = wl_adapter_init_module( ); + DBG_LEAVE( DbgInfo ); + return result; +} // init_module +/*============================================================================*/ + + +/******************************************************************************* + * cleanup_module() + ******************************************************************************* + * + * DESCRIPTION: + * + * Unload the kernel module. + * + * PARAMETERS: + * + * N/A + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +static void __exit wl_module_exit( void ) +{ + DBG_FUNC( "wl_module_exit" ); + DBG_ENTER(DbgInfo); + + wl_adapter_cleanup_module( ); +#if 0 //SCULL_USE_PROC /* don't waste space if unused */ + remove_proc_entry( "wlags", NULL ); //;?why so a-symmetric compared to location of create_proc_read_entry +#endif + + DBG_LEAVE( DbgInfo ); + return; +} // cleanup_module +/*============================================================================*/ + +module_init(wl_module_init); +module_exit(wl_module_exit); + +/******************************************************************************* + * wl_isr() + ******************************************************************************* + * + * DESCRIPTION: + * + * The Interrupt Service Routine for the driver. + * + * PARAMETERS: + * + * irq - the irq the interrupt came in on + * dev_id - a buffer containing information about the request + * regs - + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +irqreturn_t wl_isr( int irq, void *dev_id, struct pt_regs *regs ) +{ + int events; + struct net_device *dev = (struct net_device *) dev_id; + struct wl_private *lp = NULL; + /*------------------------------------------------------------------------*/ + if (( dev == NULL ) || ( !netif_device_present( dev ))) { + return IRQ_NONE; + } + + /* Set the wl_private pointer (lp), now that we know that dev is non-null */ + lp = wl_priv(dev); + +#ifdef USE_RTS + if ( lp->useRTS == 1 ) { + DBG_PRINT( "EXITING ISR, IN RTS MODE...\n" ); + return; + } +#endif /* USE_RTS */ + + /* If we have interrupts pending, then put them on a system task + queue. Otherwise turn interrupts back on */ + events = hcf_action( &lp->hcfCtx, HCF_ACT_INT_OFF ); + + if ( events == HCF_INT_PENDING ) { + /* Schedule the ISR handler as a bottom-half task in the + tq_immediate queue */ + tasklet_schedule(&lp->task); + } else { + //DBG_PRINT( "NOT OUR INTERRUPT\n" ); + hcf_action( &lp->hcfCtx, HCF_ACT_INT_ON ); + } + + return IRQ_RETVAL(events == HCF_INT_PENDING); +} // wl_isr +/*============================================================================*/ + + +/******************************************************************************* + * wl_isr_handler() + ******************************************************************************* + * + * DESCRIPTION: + * + * The ISR handler, scheduled to run in a deferred context by the ISR. This + * is where the ISR's work actually gets done. + * + * PARAMETERS: + * + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +#define WVLAN_MAX_INT_SERVICES 50 + +void wl_isr_handler( unsigned long p ) +{ + struct net_device *dev; + unsigned long flags; + bool_t stop = TRUE; + int count; + int result; + struct wl_private *lp = (struct wl_private *)p; + /*------------------------------------------------------------------------*/ + + if ( lp == NULL ) { + DBG_PRINT( "wl_isr_handler lp adapter pointer is NULL!!!\n" ); + } else { + wl_lock( lp, &flags ); + + dev = (struct net_device *)lp->dev; + if ( dev != NULL && netif_device_present( dev ) ) stop = FALSE; + for( count = 0; stop == FALSE && count < WVLAN_MAX_INT_SERVICES; count++ ) { + stop = TRUE; + result = hcf_service_nic( &lp->hcfCtx, + (wci_bufp)lp->lookAheadBuf, + sizeof( lp->lookAheadBuf )); + if ( result == HCF_ERR_MIC ) { + wl_wext_event_mic_failed( dev ); /* Send an event that MIC failed */ + //;?this seems wrong if HCF_ERR_MIC coincides with another event, stop gets FALSE + //so why not do it always ;? + } + +#ifndef USE_MBOX_SYNC + if ( lp->hcfCtx.IFB_MBInfoLen != 0 ) { /* anything in the mailbox */ + wl_mbx( lp ); + stop = FALSE; + } +#endif + /* Check for a Link status event */ + if ( ( lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW ) != 0 ) { + wl_process_link_status( lp ); + stop = FALSE; + } + /* Check for probe response events */ + if ( lp->ProbeResp.infoType != 0 && + lp->ProbeResp.infoType != 0xFFFF ) { + wl_process_probe_response( lp ); + memset( &lp->ProbeResp, 0, sizeof( lp->ProbeResp )); + lp->ProbeResp.infoType = 0xFFFF; + stop = FALSE; + } + /* Check for updated record events */ + if ( lp->updatedRecord.len != 0xFFFF ) { + wl_process_updated_record( lp ); + lp->updatedRecord.len = 0xFFFF; + stop = FALSE; + } + /* Check for association status events */ + if ( lp->assoc_stat.len != 0xFFFF ) { + wl_process_assoc_status( lp ); + lp->assoc_stat.len = 0xFFFF; + stop = FALSE; + } + /* Check for security status events */ + if ( lp->sec_stat.len != 0xFFFF ) { + wl_process_security_status( lp ); + lp->sec_stat.len = 0xFFFF; + stop = FALSE; + } + +#ifdef ENABLE_DMA + if ( lp->use_dma ) { + /* Check for DMA Rx packets */ + if ( lp->hcfCtx.IFB_DmaPackets & HREG_EV_RDMAD ) { + wl_rx_dma( dev ); + stop = FALSE; + } + /* Return Tx DMA descriptors to host */ + if ( lp->hcfCtx.IFB_DmaPackets & HREG_EV_TDMAD ) { + wl_pci_dma_hcf_reclaim_tx( lp ); + stop = FALSE; + } + } + else +#endif // ENABLE_DMA + { + /* Check for Rx packets */ + if ( lp->hcfCtx.IFB_RxLen != 0 ) { + wl_rx( dev ); + stop = FALSE; + } + /* Make sure that queued frames get sent */ + if ( wl_send( lp )) { + stop = FALSE; + } + } + } + /* We're done, so turn interrupts which were turned off in wl_isr, back on */ + hcf_action( &lp->hcfCtx, HCF_ACT_INT_ON ); + wl_unlock( lp, &flags ); + } + return; +} // wl_isr_handler +/*============================================================================*/ + + +/******************************************************************************* + * wl_remove() + ******************************************************************************* + * + * DESCRIPTION: + * + * Notify the adapter that it has been removed. Since the adapter is gone, + * we should no longer try to talk to it. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_remove( struct net_device *dev ) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_remove" ); + DBG_ENTER( DbgInfo ); + + DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + + wl_lock( lp, &flags ); + + /* stop handling interrupts */ + wl_act_int_off( lp ); + lp->is_handling_int = WL_NOT_HANDLING_INT; + + /* + * Disable the ports: just change state: since the + * card is gone it is useless to talk to it and at + * disconnect all state information is lost anyway. + */ + /* Reset portState */ + lp->portState = WVLAN_PORT_STATE_DISABLED; + +#if 0 //;? (HCF_TYPE) & HCF_TYPE_AP +#ifdef USE_WDS + //wl_disable_wds_ports( lp ); +#endif // USE_WDS +#endif /* (HCF_TYPE) & HCF_TYPE_AP */ + + /* Mark the device as unregistered */ + lp->is_registered = FALSE; + + /* Deregister the WDS ports as well */ + WL_WDS_NETDEV_DEREGISTER( lp ); +#ifdef USE_RTS + if ( lp->useRTS == 1 ) { + wl_unlock( lp, &flags ); + + DBG_LEAVE( DbgInfo ); + return; + } +#endif /* USE_RTS */ + + /* Inform the HCF that the card has been removed */ + hcf_connect( &lp->hcfCtx, HCF_DISCONNECT ); + + wl_unlock( lp, &flags ); + + DBG_LEAVE( DbgInfo ); + return; +} // wl_remove +/*============================================================================*/ + + +/******************************************************************************* + * wl_suspend() + ******************************************************************************* + * + * DESCRIPTION: + * + * Power-down and halt the adapter. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_suspend( struct net_device *dev ) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_suspend" ); + DBG_ENTER( DbgInfo ); + + DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + + /* The adapter is suspended: + Stop the adapter + Power down + */ + wl_lock( lp, &flags ); + + /* Disable interrupt handling */ + wl_act_int_off( lp ); + + /* Disconnect */ + wl_disconnect( lp ); + + /* Disable */ + wl_disable( lp ); + + /* Disconnect from the adapter */ + hcf_connect( &lp->hcfCtx, HCF_DISCONNECT ); + + /* Reset portState to be sure (should have been done by wl_disable */ + lp->portState = WVLAN_PORT_STATE_DISABLED; + + wl_unlock( lp, &flags ); + + DBG_LEAVE( DbgInfo ); + return; +} // wl_suspend +/*============================================================================*/ + + +/******************************************************************************* + * wl_resume() + ******************************************************************************* + * + * DESCRIPTION: + * + * Resume a previously suspended adapter. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_resume(struct net_device *dev) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_resume" ); + DBG_ENTER( DbgInfo ); + + DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + + wl_lock( lp, &flags ); + + /* Connect to the adapter */ + hcf_connect( &lp->hcfCtx, dev->base_addr ); + + /* Reset portState */ + lp->portState = WVLAN_PORT_STATE_DISABLED; + + /* Power might have been off, assume the card lost the firmware*/ + lp->firmware_present = WL_FRIMWARE_NOT_PRESENT; + + /* Reload the firmware and restart */ + wl_reset( dev ); + + /* Resume interrupt handling */ + wl_act_int_on( lp ); + + wl_unlock( lp, &flags ); + + DBG_LEAVE( DbgInfo ); + return; +} // wl_resume +/*============================================================================*/ + + +/******************************************************************************* + * wl_release() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function perfroms a check on the device and calls wl_remove() if + * necessary. This function can be used for all bus types, but exists mostly + * for the benefit of the Card Services driver, as there are times when + * wl_remove() does not get called. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_release( struct net_device *dev ) +{ + struct wl_private *lp = wl_priv(dev); + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_release" ); + DBG_ENTER( DbgInfo ); + + DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + /* If wl_remove() hasn't been called (i.e. when Card Services is shut + down with the card in the slot), then call it */ + if ( lp->is_registered == TRUE ) { + DBG_TRACE( DbgInfo, "Calling unregister_netdev(), as it wasn't called yet\n" ); + wl_remove( dev ); + + lp->is_registered = FALSE; + } + + DBG_LEAVE( DbgInfo ); + return; +} // wl_release +/*============================================================================*/ + + +/******************************************************************************* + * wl_get_irq_mask() + ******************************************************************************* + * + * DESCRIPTION: + * + * Accessor function to retrieve the irq_mask module parameter + * + * PARAMETERS: + * + * N/A + * + * RETURNS: + * + * The irq_mask module parameter + * + ******************************************************************************/ +p_u16 wl_get_irq_mask( void ) +{ + return irq_mask; +} // wl_get_irq_mask +/*============================================================================*/ + + +/******************************************************************************* + * wl_get_irq_list() + ******************************************************************************* + * + * DESCRIPTION: + * + * Accessor function to retrieve the irq_list module parameter + * + * PARAMETERS: + * + * N/A + * + * RETURNS: + * + * The irq_list module parameter + * + ******************************************************************************/ +p_s8 * wl_get_irq_list( void ) +{ + return irq_list; +} // wl_get_irq_list +/*============================================================================*/ + + + +/******************************************************************************* + * wl_enable() + ******************************************************************************* + * + * DESCRIPTION: + * + * Used to enable MAC ports + * + * PARAMETERS: + * + * lp - pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +int wl_enable( struct wl_private *lp ) +{ + int hcf_status = HCF_SUCCESS; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_enable" ); + DBG_ENTER( DbgInfo ); + + if ( lp->portState == WVLAN_PORT_STATE_ENABLED ) { + DBG_TRACE( DbgInfo, "No action: Card already enabled\n" ); + } else if ( lp->portState == WVLAN_PORT_STATE_CONNECTED ) { + //;?suspicuous logic, how can you be connected without being enabled so this is probably dead code + DBG_TRACE( DbgInfo, "No action: Card already connected\n" ); + } else { + hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_ENABLE ); + if ( hcf_status == HCF_SUCCESS ) { + /* Set the status of the NIC to enabled */ + lp->portState = WVLAN_PORT_STATE_ENABLED; //;?bad mnemonic, NIC iso PORT +#ifdef ENABLE_DMA + if ( lp->use_dma ) { + wl_pci_dma_hcf_supply( lp ); //;?always succes? + } +#endif + } + } + if ( hcf_status != HCF_SUCCESS ) { //;?make this an assert + DBG_TRACE( DbgInfo, "failed: 0x%x\n", hcf_status ); + } + DBG_LEAVE( DbgInfo ); + return hcf_status; +} // wl_enable +/*============================================================================*/ + + +#ifdef USE_WDS +/******************************************************************************* + * wl_enable_wds_ports() + ******************************************************************************* + * + * DESCRIPTION: + * + * Used to enable the WDS MAC ports 1-6 + * + * PARAMETERS: + * + * lp - pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_enable_wds_ports( struct wl_private * lp ) +{ + + DBG_FUNC( "wl_enable_wds_ports" ); + DBG_ENTER( DbgInfo ); + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ){ + DBG_ERROR( DbgInfo, "!!!!;? someone misunderstood something !!!!!\n" ); + } + DBG_LEAVE( DbgInfo ); + return; +} // wl_enable_wds_ports +#endif /* USE_WDS */ +/*============================================================================*/ + + +/******************************************************************************* + * wl_connect() + ******************************************************************************* + * + * DESCRIPTION: + * + * Used to connect a MAC port + * + * PARAMETERS: + * + * lp - pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +int wl_connect( struct wl_private *lp ) +{ + int hcf_status; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_connect" ); + DBG_ENTER( DbgInfo ); + + if ( lp->portState != WVLAN_PORT_STATE_ENABLED ) { + DBG_TRACE( DbgInfo, "No action: Not in enabled state\n" ); + DBG_LEAVE( DbgInfo ); + return HCF_SUCCESS; + } + hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_CONNECT ); + if ( hcf_status == HCF_SUCCESS ) { + lp->portState = WVLAN_PORT_STATE_CONNECTED; + } + DBG_LEAVE( DbgInfo ); + return hcf_status; +} // wl_connect +/*============================================================================*/ + + +/******************************************************************************* + * wl_disconnect() + ******************************************************************************* + * + * DESCRIPTION: + * + * Used to disconnect a MAC port + * + * PARAMETERS: + * + * lp - pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +int wl_disconnect( struct wl_private *lp ) +{ + int hcf_status; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_disconnect" ); + DBG_ENTER( DbgInfo ); + + if ( lp->portState != WVLAN_PORT_STATE_CONNECTED ) { + DBG_TRACE( DbgInfo, "No action: Not in connected state\n" ); + DBG_LEAVE( DbgInfo ); + return HCF_SUCCESS; + } + hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_DISCONNECT ); + if ( hcf_status == HCF_SUCCESS ) { + lp->portState = WVLAN_PORT_STATE_ENABLED; + } + DBG_LEAVE( DbgInfo ); + return hcf_status; +} // wl_disconnect +/*============================================================================*/ + + +/******************************************************************************* + * wl_disable() + ******************************************************************************* + * + * DESCRIPTION: + * + * Used to disable MAC ports + * + * PARAMETERS: + * + * lp - pointer to the device's private adapter structure + * port - the MAC port to disable + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +int wl_disable( struct wl_private *lp ) +{ + int hcf_status = HCF_SUCCESS; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_disable" ); + DBG_ENTER( DbgInfo ); + + if ( lp->portState == WVLAN_PORT_STATE_DISABLED ) { + DBG_TRACE( DbgInfo, "No action: Port state is disabled\n" ); + } else { + hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_DISABLE ); + if ( hcf_status == HCF_SUCCESS ) { + /* Set the status of the port to disabled */ //;?bad mnemonic use NIC iso PORT + lp->portState = WVLAN_PORT_STATE_DISABLED; + +#ifdef ENABLE_DMA + if ( lp->use_dma ) { + wl_pci_dma_hcf_reclaim( lp ); + } +#endif + } + } + if ( hcf_status != HCF_SUCCESS ) { + DBG_TRACE( DbgInfo, "failed: 0x%x\n", hcf_status ); + } + DBG_LEAVE( DbgInfo ); + return hcf_status; +} // wl_disable +/*============================================================================*/ + + +#ifdef USE_WDS +/******************************************************************************* + * wl_disable_wds_ports() + ******************************************************************************* + * + * DESCRIPTION: + * + * Used to disable the WDS MAC ports 1-6 + * + * PARAMETERS: + * + * lp - pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_disable_wds_ports( struct wl_private * lp ) +{ + + DBG_FUNC( "wl_disable_wds_ports" ); + DBG_ENTER( DbgInfo ); + + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ){ + DBG_ERROR( DbgInfo, "!!!!;? someone misunderstood something !!!!!\n" ); + } +// if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { +// wl_disable( lp, HCF_PORT_1 ); +// wl_disable( lp, HCF_PORT_2 ); +// wl_disable( lp, HCF_PORT_3 ); +// wl_disable( lp, HCF_PORT_4 ); +// wl_disable( lp, HCF_PORT_5 ); +// wl_disable( lp, HCF_PORT_6 ); +// } + DBG_LEAVE( DbgInfo ); + return; +} // wl_disable_wds_ports +#endif // USE_WDS +/*============================================================================*/ + + +#ifndef USE_MBOX_SYNC +/******************************************************************************* + * wl_mbx() + ******************************************************************************* + * + * DESCRIPTION: + * This function is used to read and process a mailbox message. + * + * + * PARAMETERS: + * + * lp - pointer to the device's private adapter structure + * + * RETURNS: + * + * an HCF status code + * + ******************************************************************************/ +int wl_mbx( struct wl_private *lp ) +{ + int hcf_status = HCF_SUCCESS; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_mbx" ); + DBG_ENTER( DbgInfo ); + DBG_TRACE( DbgInfo, "Mailbox Info: IFB_MBInfoLen: %d\n", + lp->hcfCtx.IFB_MBInfoLen ); + + memset( &( lp->ltvRecord ), 0, sizeof( ltv_t )); + + lp->ltvRecord.len = MB_SIZE; + lp->ltvRecord.typ = CFG_MB_INFO; + hcf_status = hcf_get_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); + + if ( hcf_status != HCF_SUCCESS ) { + DBG_ERROR( DbgInfo, "hcf_get_info returned 0x%x\n", hcf_status ); + + DBG_LEAVE( DbgInfo ); + return hcf_status; + } + + if ( lp->ltvRecord.typ == CFG_MB_INFO ) { + DBG_LEAVE( DbgInfo ); + return hcf_status; + } + /* Endian translate the mailbox data, then process the message */ + wl_endian_translate_mailbox( &( lp->ltvRecord )); + wl_process_mailbox( lp ); + DBG_LEAVE( DbgInfo ); + return hcf_status; +} // wl_mbx +/*============================================================================*/ + + +/******************************************************************************* + * wl_endian_translate_mailbox() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function will perform the tedious task of endian translating all + * fields withtin a mailbox message which need translating. + * + * PARAMETERS: + * + * ltv - pointer to the LTV to endian translate + * + * RETURNS: + * + * none + * + ******************************************************************************/ +void wl_endian_translate_mailbox( ltv_t *ltv ) +{ + + DBG_FUNC( "wl_endian_translate_mailbox" ); + DBG_ENTER( DbgInfo ); + switch( ltv->typ ) { + case CFG_TALLIES: + break; + + case CFG_SCAN: + { + int num_aps; + SCAN_RS_STRCT *aps = (SCAN_RS_STRCT *)<v->u.u8[0]; + + num_aps = (hcf_16)(( (size_t)(ltv->len - 1 ) * 2 ) / + ( sizeof( SCAN_RS_STRCT ))); + + while( num_aps >= 1 ) { + num_aps--; + + aps[num_aps].channel_id = + CNV_LITTLE_TO_INT( aps[num_aps].channel_id ); + + aps[num_aps].noise_level = + CNV_LITTLE_TO_INT( aps[num_aps].noise_level ); + + aps[num_aps].signal_level = + CNV_LITTLE_TO_INT( aps[num_aps].signal_level ); + + aps[num_aps].beacon_interval_time = + CNV_LITTLE_TO_INT( aps[num_aps].beacon_interval_time ); + + aps[num_aps].capability = + CNV_LITTLE_TO_INT( aps[num_aps].capability ); + + aps[num_aps].ssid_len = + CNV_LITTLE_TO_INT( aps[num_aps].ssid_len ); + + aps[num_aps].ssid_val[aps[num_aps].ssid_len] = 0; + } + } + break; + + case CFG_ACS_SCAN: + { + PROBE_RESP *probe_resp = (PROBE_RESP *)ltv; + + probe_resp->frameControl = CNV_LITTLE_TO_INT( probe_resp->frameControl ); + probe_resp->durID = CNV_LITTLE_TO_INT( probe_resp->durID ); + probe_resp->sequence = CNV_LITTLE_TO_INT( probe_resp->sequence ); + probe_resp->dataLength = CNV_LITTLE_TO_INT( probe_resp->dataLength ); +#ifndef WARP + probe_resp->lenType = CNV_LITTLE_TO_INT( probe_resp->lenType ); +#endif // WARP + probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval ); + probe_resp->capability = CNV_LITTLE_TO_INT( probe_resp->capability ); + probe_resp->flags = CNV_LITTLE_TO_INT( probe_resp->flags ); + } + break; + + case CFG_LINK_STAT: +#define ls ((LINK_STATUS_STRCT *)ltv) + ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus ); + break; +#undef ls + + case CFG_ASSOC_STAT: + { + ASSOC_STATUS_STRCT *as = (ASSOC_STATUS_STRCT *)ltv; + + as->assocStatus = CNV_LITTLE_TO_INT( as->assocStatus ); + } + break; + + case CFG_SECURITY_STAT: + { + SECURITY_STATUS_STRCT *ss = (SECURITY_STATUS_STRCT *)ltv; + + ss->securityStatus = CNV_LITTLE_TO_INT( ss->securityStatus ); + ss->reason = CNV_LITTLE_TO_INT( ss->reason ); + } + break; + + case CFG_WMP: + break; + + case CFG_NULL: + break; + + default: + break; + } + + DBG_LEAVE( DbgInfo ); + return; +} // wl_endian_translate_mailbox +/*============================================================================*/ + +/******************************************************************************* + * wl_process_mailbox() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function will process the mailbox data. + * + * PARAMETERS: + * + * ltv - pointer to the LTV to be processed. + * + * RETURNS: + * + * none + * + ******************************************************************************/ +void wl_process_mailbox( struct wl_private *lp ) +{ + ltv_t *ltv; + hcf_16 ltv_val = 0xFFFF; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_process_mailbox" ); + DBG_ENTER( DbgInfo ); + ltv = &( lp->ltvRecord ); + + switch( ltv->typ ) { + + case CFG_TALLIES: + DBG_TRACE( DbgInfo, "CFG_TALLIES\n" ); + break; + case CFG_SCAN: + DBG_TRACE( DbgInfo, "CFG_SCAN\n" ); + + { + int num_aps; + SCAN_RS_STRCT *aps = (SCAN_RS_STRCT *)<v->u.u8[0]; + + num_aps = (hcf_16)(( (size_t)(ltv->len - 1 ) * 2 ) / + ( sizeof( SCAN_RS_STRCT ))); + + lp->scan_results.num_aps = num_aps; + + DBG_TRACE( DbgInfo, "Number of APs: %d\n", num_aps ); + + while( num_aps >= 1 ) { + num_aps--; + + DBG_TRACE( DbgInfo, "AP : %d\n", num_aps ); + DBG_TRACE( DbgInfo, "=========================\n" ); + DBG_TRACE( DbgInfo, "Channel ID : 0x%04x\n", + aps[num_aps].channel_id ); + DBG_TRACE( DbgInfo, "Noise Level : 0x%04x\n", + aps[num_aps].noise_level ); + DBG_TRACE( DbgInfo, "Signal Level : 0x%04x\n", + aps[num_aps].signal_level ); + DBG_TRACE( DbgInfo, "Beacon Interval : 0x%04x\n", + aps[num_aps].beacon_interval_time ); + DBG_TRACE( DbgInfo, "Capability : 0x%04x\n", + aps[num_aps].capability ); + DBG_TRACE( DbgInfo, "SSID Length : 0x%04x\n", + aps[num_aps].ssid_len ); + DBG_TRACE( DbgInfo, "BSSID : %s\n", + DbgHwAddr( aps[num_aps].bssid )); + + if ( aps[num_aps].ssid_len != 0 ) { + DBG_TRACE( DbgInfo, "SSID : %s.\n", + aps[num_aps].ssid_val ); + } else { + DBG_TRACE( DbgInfo, "SSID : %s.\n", "ANY" ); + } + + DBG_TRACE( DbgInfo, "\n" ); + + /* Copy the info to the ScanResult structure in the private + adapter struct */ + memcpy( &( lp->scan_results.APTable[num_aps]), &( aps[num_aps] ), + sizeof( SCAN_RS_STRCT )); + } + + /* Set scan result to true so that any scan requests will + complete */ + lp->scan_results.scan_complete = TRUE; + } + + break; + case CFG_ACS_SCAN: + DBG_TRACE( DbgInfo, "CFG_ACS_SCAN\n" ); + + { + PROBE_RESP *probe_rsp = (PROBE_RESP *)ltv; + hcf_8 *wpa_ie = NULL; + hcf_16 wpa_ie_len = 0; + + DBG_TRACE( DbgInfo, "(%s) =========================\n", + lp->dev->name ); + + DBG_TRACE( DbgInfo, "(%s) length : 0x%04x.\n", + lp->dev->name, probe_rsp->length ); + + if ( probe_rsp->length > 1 ) { + DBG_TRACE( DbgInfo, "(%s) infoType : 0x%04x.\n", + lp->dev->name, probe_rsp->infoType ); + + DBG_TRACE( DbgInfo, "(%s) signal : 0x%02x.\n", + lp->dev->name, probe_rsp->signal ); + + DBG_TRACE( DbgInfo, "(%s) silence : 0x%02x.\n", + lp->dev->name, probe_rsp->silence ); + + DBG_TRACE( DbgInfo, "(%s) rxFlow : 0x%02x.\n", + lp->dev->name, probe_rsp->rxFlow ); + + DBG_TRACE( DbgInfo, "(%s) rate : 0x%02x.\n", + lp->dev->name, probe_rsp->rate ); + + DBG_TRACE( DbgInfo, "(%s) frame cntl : 0x%04x.\n", + lp->dev->name, probe_rsp->frameControl ); + + DBG_TRACE( DbgInfo, "(%s) durID : 0x%04x.\n", + lp->dev->name, probe_rsp->durID ); + + DBG_TRACE( DbgInfo, "(%s) address1 : %s\n", + lp->dev->name, DbgHwAddr( probe_rsp->address1 )); + + DBG_TRACE( DbgInfo, "(%s) address2 : %s\n", + lp->dev->name, DbgHwAddr( probe_rsp->address2 )); + + DBG_TRACE( DbgInfo, "(%s) BSSID : %s\n", + lp->dev->name, DbgHwAddr( probe_rsp->BSSID )); + + DBG_TRACE( DbgInfo, "(%s) sequence : 0x%04x.\n", + lp->dev->name, probe_rsp->sequence ); + + DBG_TRACE( DbgInfo, "(%s) address4 : %s\n", + lp->dev->name, DbgHwAddr( probe_rsp->address4 )); + + DBG_TRACE( DbgInfo, "(%s) datalength : 0x%04x.\n", + lp->dev->name, probe_rsp->dataLength ); + + DBG_TRACE( DbgInfo, "(%s) DA : %s\n", + lp->dev->name, DbgHwAddr( probe_rsp->DA )); + + DBG_TRACE( DbgInfo, "(%s) SA : %s\n", + lp->dev->name, DbgHwAddr( probe_rsp->SA )); + + //DBG_TRACE( DbgInfo, "(%s) lenType : 0x%04x.\n", + // lp->dev->name, probe_rsp->lenType ); + + DBG_TRACE( DbgInfo, "(%s) timeStamp : %s\n", + lp->dev->name, DbgHwAddr( probe_rsp->timeStamp )); + + DBG_TRACE( DbgInfo, "(%s) beaconInt : 0x%04x.\n", + lp->dev->name, probe_rsp->beaconInterval ); + + DBG_TRACE( DbgInfo, "(%s) capability : 0x%04x.\n", + lp->dev->name, probe_rsp->capability ); + + DBG_TRACE( DbgInfo, "(%s) SSID len : 0x%04x.\n", + lp->dev->name, probe_rsp->rawData[1] ); + + if ( probe_rsp->rawData[1] > 0 ) { + char ssid[HCF_MAX_NAME_LEN]; + + memset( ssid, 0, sizeof( ssid )); + strncpy( ssid, &probe_rsp->rawData[2], + probe_rsp->rawData[1] ); + + DBG_TRACE( DbgInfo, "(%s) SSID : %s\n", + lp->dev->name, ssid ); + } + + /* Parse out the WPA-IE, if one exists */ + wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len ); + if ( wpa_ie != NULL ) { + DBG_TRACE( DbgInfo, "(%s) WPA-IE : %s\n", + lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len )); + } + + DBG_TRACE( DbgInfo, "(%s) flags : 0x%04x.\n", + lp->dev->name, probe_rsp->flags ); + } + + DBG_TRACE( DbgInfo, "\n\n" ); + /* If probe response length is 1, then the scan is complete */ + if ( probe_rsp->length == 1 ) { + DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" ); + lp->probe_results.num_aps = lp->probe_num_aps; + lp->probe_results.scan_complete = TRUE; + + /* Reset the counter for the next scan request */ + lp->probe_num_aps = 0; + + /* Send a wireless extensions event that the scan completed */ + wl_wext_event_scan_complete( lp->dev ); + } else { + /* Only copy to the table if the entry is unique; APs sometimes + respond more than once to a probe */ + if ( lp->probe_num_aps == 0 ) { + /* Copy the info to the ScanResult structure in the private + adapter struct */ + memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ), + probe_rsp, sizeof( PROBE_RESP )); + + /* Increment the number of APs detected */ + lp->probe_num_aps++; + } else { + int count; + int unique = 1; + + for( count = 0; count < lp->probe_num_aps; count++ ) { + if ( memcmp( &( probe_rsp->BSSID ), + lp->probe_results.ProbeTable[count].BSSID, + ETH_ALEN ) == 0 ) { + unique = 0; + } + } + + if ( unique ) { + /* Copy the info to the ScanResult structure in the + private adapter struct. Only copy if there's room in the + table */ + if ( lp->probe_num_aps < MAX_NAPS ) + { + memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ), + probe_rsp, sizeof( PROBE_RESP )); + } + else + { + DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" ); + } + + /* Increment the number of APs detected. Note I do this + here even when I don't copy the probe response to the + buffer in order to detect the overflow condition */ + lp->probe_num_aps++; + } + } + } + } + + break; + + case CFG_LINK_STAT: +#define ls ((LINK_STATUS_STRCT *)ltv) + DBG_TRACE( DbgInfo, "CFG_LINK_STAT\n" ); + + switch( ls->linkStatus ) { + case 1: + DBG_TRACE( DbgInfo, "Link Status : Connected\n" ); + wl_wext_event_ap( lp->dev ); + break; + + case 2: + DBG_TRACE( DbgInfo, "Link Status : Disconnected\n" ); + break; + + case 3: + DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" ); + break; + + case 4: + DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" ); + break; + + case 5: + DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" ); + break; + + default: + DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", + ls->linkStatus ); + break; + } + + break; +#undef ls + + case CFG_ASSOC_STAT: + DBG_TRACE( DbgInfo, "CFG_ASSOC_STAT\n" ); + + { + ASSOC_STATUS_STRCT *as = (ASSOC_STATUS_STRCT *)ltv; + + switch( as->assocStatus ) { + case 1: + DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" ); + break; + + case 2: + DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" ); + break; + + case 3: + DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" ); + break; + + default: + DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n", + as->assocStatus ); + break; + } + + DBG_TRACE( DbgInfo, "STA Address : %s\n", + DbgHwAddr( as->staAddr )); + + if (( as->assocStatus == 2 ) && ( as->len == 8 )) { + DBG_TRACE( DbgInfo, "Old AP Address : %s\n", + DbgHwAddr( as->oldApAddr )); + } + } + + break; + + case CFG_SECURITY_STAT: + DBG_TRACE( DbgInfo, "CFG_SECURITY_STAT\n" ); + + { + SECURITY_STATUS_STRCT *ss = (SECURITY_STATUS_STRCT *)ltv; + + switch( ss->securityStatus ) { + case 1: + DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" ); + break; + + case 2: + DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" ); + break; + + case 3: + DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" ); + break; + + case 4: + DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" ); + break; + + case 5: + DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" ); + break; + + default: + DBG_TRACE( DbgInfo, "Security Status : UNKNOWN %d\n", + ss->securityStatus ); + break; + } + + DBG_TRACE( DbgInfo, "STA Address : %s\n", DbgHwAddr( ss->staAddr )); + + DBG_TRACE( DbgInfo, "Reason : 0x%04x \n", ss->reason ); + } + + break; + + case CFG_WMP: + DBG_TRACE( DbgInfo, "CFG_WMP, size is %d bytes\n", ltv->len ); + { + WMP_RSP_STRCT *wmp_rsp = (WMP_RSP_STRCT *)ltv; + + DBG_TRACE( DbgInfo, "CFG_WMP, pdu type is 0x%x\n", + wmp_rsp->wmpRsp.wmpHdr.type ); + + switch( wmp_rsp->wmpRsp.wmpHdr.type ) { + case WVLAN_WMP_PDU_TYPE_LT_RSP: + { +#if DBG + LINKTEST_RSP_STRCT *lt_rsp = (LINKTEST_RSP_STRCT *)ltv; +#endif // DBG + DBG_TRACE( DbgInfo, "LINK TEST RESULT\n" ); + DBG_TRACE( DbgInfo, "================\n" ); + DBG_TRACE( DbgInfo, "Length : %d.\n", lt_rsp->len ); + + DBG_TRACE( DbgInfo, "Name : %s.\n", lt_rsp->ltRsp.ltRsp.name ); + DBG_TRACE( DbgInfo, "Signal Level : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.signal ); + DBG_TRACE( DbgInfo, "Noise Level : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.noise ); + DBG_TRACE( DbgInfo, "Receive Flow : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.rxFlow ); + DBG_TRACE( DbgInfo, "Data Rate : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.dataRate ); + DBG_TRACE( DbgInfo, "Protocol : 0x%04x.\n", lt_rsp->ltRsp.ltRsp.protocol ); + DBG_TRACE( DbgInfo, "Station : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.station ); + DBG_TRACE( DbgInfo, "Data Rate Cap : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.dataRateCap ); + + DBG_TRACE( DbgInfo, "Power Mgmt : 0x%02x 0x%02x 0x%02x 0x%02x.\n", + lt_rsp->ltRsp.ltRsp.powerMgmt[0], + lt_rsp->ltRsp.ltRsp.powerMgmt[1], + lt_rsp->ltRsp.ltRsp.powerMgmt[2], + lt_rsp->ltRsp.ltRsp.powerMgmt[3] ); + + DBG_TRACE( DbgInfo, "Robustness : 0x%02x 0x%02x 0x%02x 0x%02x.\n", + lt_rsp->ltRsp.ltRsp.robustness[0], + lt_rsp->ltRsp.ltRsp.robustness[1], + lt_rsp->ltRsp.ltRsp.robustness[2], + lt_rsp->ltRsp.ltRsp.robustness[3] ); + + DBG_TRACE( DbgInfo, "Scaling : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.scaling ); + } + + break; + + default: + break; + } + } + + break; + + case CFG_NULL: + DBG_TRACE( DbgInfo, "CFG_NULL\n" ); + break; + + case CFG_UPDATED_INFO_RECORD: // Updated Information Record + DBG_TRACE( DbgInfo, "UPDATED INFORMATION RECORD\n" ); + + ltv_val = CNV_INT_TO_LITTLE( ltv->u.u16[0] ); + + /* Check and see which RID was updated */ + switch( ltv_val ) { + case CFG_CUR_COUNTRY_INFO: // Indicate Passive Scan Completion + DBG_TRACE( DbgInfo, "Updated country info\n" ); + + /* Do I need to hold off on updating RIDs until the process is + complete? */ + wl_connect( lp ); + break; + + case CFG_PORT_STAT: // Wait for Connect Event + //wl_connect( lp ); + + break; + + default: + DBG_WARNING( DbgInfo, "Unknown RID: 0x%04x\n", ltv_val ); + } + + break; + + default: + DBG_TRACE( DbgInfo, "UNKNOWN MESSAGE: 0x%04x\n", ltv->typ ); + break; + } + DBG_LEAVE( DbgInfo ); + return; +} // wl_process_mailbox +/*============================================================================*/ +#endif /* ifndef USE_MBOX_SYNC */ + +#ifdef USE_WDS +/******************************************************************************* + * wl_wds_netdev_register() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function registers net_device structures with the system's network + * layer for use with the WDS ports. + * + * + * PARAMETERS: + * + * lp - pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wds_netdev_register( struct wl_private *lp ) +{ + int count; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_wds_netdev_register" ); + DBG_ENTER( DbgInfo ); + //;?why is there no USE_WDS clause like in wl_enable_wds_ports + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { + for( count = 0; count < NUM_WDS_PORTS; count++ ) { + if ( WVLAN_VALID_MAC_ADDRESS( lp->wds_port[count].wdsAddress )) { + if ( register_netdev( lp->wds_port[count].dev ) != 0 ) { + DBG_WARNING( DbgInfo, "net device for WDS port %d could not be registered\n", + ( count + 1 )); + } + lp->wds_port[count].is_registered = TRUE; + + /* Fill out the net_device structs with the MAC addr */ + memcpy( lp->wds_port[count].dev->dev_addr, lp->MACAddress, ETH_ALEN ); + lp->wds_port[count].dev->addr_len = ETH_ALEN; + } + } + } + DBG_LEAVE( DbgInfo ); + return; +} // wl_wds_netdev_register +/*============================================================================*/ + + +/******************************************************************************* + * wl_wds_netdev_deregister() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function deregisters the WDS net_device structures used by the + * system's network layer. + * + * + * PARAMETERS: + * + * lp - pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wds_netdev_deregister( struct wl_private *lp ) +{ + int count; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wl_wds_netdev_deregister" ); + DBG_ENTER( DbgInfo ); + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { + for( count = 0; count < NUM_WDS_PORTS; count++ ) { + if ( WVLAN_VALID_MAC_ADDRESS( lp->wds_port[count].wdsAddress )) { + unregister_netdev( lp->wds_port[count].dev ); + } + lp->wds_port[count].is_registered = FALSE; + } + } + DBG_LEAVE( DbgInfo ); + return; +} // wl_wds_netdev_deregister +/*============================================================================*/ +#endif /* USE_WDS */ + + +#if 0 //SCULL_USE_PROC /* don't waste space if unused */ +/* + * The proc filesystem: function to read and entry + */ +int printf_hcf_16( char *s, char *buf, hcf_16* p, int n ); +int printf_hcf_16( char *s, char *buf, hcf_16* p, int n ) { + +int i, len; + + len = sprintf(buf, "%s", s ); + while ( len < 20 ) len += sprintf(buf+len, " " ); + len += sprintf(buf+len,": " ); + for ( i = 0; i < n; i++ ) { + if ( len % 80 > 75 ) { + len += sprintf(buf+len,"\n" ); + } + len += sprintf(buf+len,"%04X ", p[i] ); + } + len += sprintf(buf+len,"\n" ); + return len; +} // printf_hcf_16 + +int printf_hcf_8( char *s, char *buf, hcf_8* p, int n ); +int printf_hcf_8( char *s, char *buf, hcf_8* p, int n ) { + +int i, len; + + len = sprintf(buf, "%s", s ); + while ( len < 20 ) len += sprintf(buf+len, " " ); + len += sprintf(buf+len,": " ); + for ( i = 0; i <= n; i++ ) { + if ( len % 80 > 77 ) { + len += sprintf(buf+len,"\n" ); + } + len += sprintf(buf+len,"%02X ", p[i] ); + } + len += sprintf(buf+len,"\n" ); + return len; +} // printf_hcf8 + +int printf_strct( char *s, char *buf, hcf_16* p ); +int printf_strct( char *s, char *buf, hcf_16* p ) { + +int i, len; + + len = sprintf(buf, "%s", s ); + while ( len < 20 ) len += sprintf(buf+len, " " ); + len += sprintf(buf+len,": " ); + for ( i = 0; i <= *p; i++ ) { + if ( len % 80 > 75 ) { + len += sprintf(buf+len,"\n" ); + } + len += sprintf(buf+len,"%04X ", p[i] ); + } + len += sprintf(buf+len,"\n" ); + return len; +} // printf_strct + +int scull_read_procmem(char *buf, char **start, off_t offset, int len, int *eof, void *data ) +{ + struct wl_private *lp = NULL; + IFBP ifbp; + CFG_HERMES_TALLIES_STRCT *p; + + #define LIMIT (PAGE_SIZE-80) /* don't print any more after this size */ + + len=0; + + if ( ( lp = ((struct net_device *)data)->priv ) == NULL ) { + len += sprintf(buf+len,"No wl_private in scull_read_procmem\n" ); + } else if ( lp->wlags49_type == 0 ){ + ifbp = &lp->hcfCtx; + len += sprintf(buf+len,"Magic: 0x%04X\n", ifbp->IFB_Magic ); + len += sprintf(buf+len,"IOBase: 0x%04X\n", ifbp->IFB_IOBase ); + len += sprintf(buf+len,"LinkStat: 0x%04X\n", ifbp->IFB_LinkStat ); + len += sprintf(buf+len,"DSLinkStat: 0x%04X\n", ifbp->IFB_DSLinkStat ); + len += sprintf(buf+len,"TickIni: 0x%08lX\n", ifbp->IFB_TickIni ); + len += sprintf(buf+len,"TickCnt: 0x%04X\n", ifbp->IFB_TickCnt ); + len += sprintf(buf+len,"IntOffCnt: 0x%04X\n", ifbp->IFB_IntOffCnt ); + len += printf_hcf_16( "IFB_FWIdentity", &buf[len], + &ifbp->IFB_FWIdentity.len, ifbp->IFB_FWIdentity.len + 1 ); + } else if ( lp->wlags49_type == 1 ) { + len += sprintf(buf+len,"Channel: 0x%04X\n", lp->Channel ); +/****** len += sprintf(buf+len,"slock: %d\n", lp->slock ); */ +//x struct tq_struct "task: 0x%04X\n", lp->task ); +//x struct net_device_stats "stats: 0x%04X\n", lp->stats ); +#ifdef WIRELESS_EXT +//x struct iw_statistics "wstats: 0x%04X\n", lp->wstats ); +//x len += sprintf(buf+len,"spy_number: 0x%04X\n", lp->spy_number ); +//x u_char spy_address[IW_MAX_SPY][ETH_ALEN]; +//x struct iw_quality spy_stat[IW_MAX_SPY]; +#endif // WIRELESS_EXT + len += sprintf(buf+len,"IFB: 0x%p\n", &lp->hcfCtx ); + len += sprintf(buf+len,"flags: %#.8lX\n", lp->flags ); //;?use this format from now on + len += sprintf(buf+len,"DebugFlag(wl_private) 0x%04X\n", lp->DebugFlag ); +#if DBG + len += sprintf(buf+len,"DebugFlag (DbgInfo): 0x%08lX\n", DbgInfo->DebugFlag ); +#endif // DBG + len += sprintf(buf+len,"is_registered: 0x%04X\n", lp->is_registered ); +//x CFG_DRV_INFO_STRCT "driverInfo: 0x%04X\n", lp->driverInfo ); + len += printf_strct( "driverInfo", &buf[len], (hcf_16*)&lp->driverInfo ); +//x CFG_IDENTITY_STRCT "driverIdentity: 0x%04X\n", lp->driverIdentity ); + len += printf_strct( "driverIdentity", &buf[len], (hcf_16*)&lp->driverIdentity ); +//x CFG_FW_IDENTITY_STRCT "StationIdentity: 0x%04X\n", lp->StationIdentity ); + len += printf_strct( "StationIdentity", &buf[len], (hcf_16*)&lp->StationIdentity ); +//x CFG_PRI_IDENTITY_STRCT "PrimaryIdentity: 0x%04X\n", lp->PrimaryIdentity ); + len += printf_strct( "PrimaryIdentity", &buf[len], (hcf_16*)&lp->hcfCtx.IFB_PRIIdentity ); + len += printf_strct( "PrimarySupplier", &buf[len], (hcf_16*)&lp->hcfCtx.IFB_PRISup ); +//x CFG_PRI_IDENTITY_STRCT "NICIdentity: 0x%04X\n", lp->NICIdentity ); + len += printf_strct( "NICIdentity", &buf[len], (hcf_16*)&lp->NICIdentity ); +//x ltv_t "ltvRecord: 0x%04X\n", lp->ltvRecord ); + len += sprintf(buf+len,"txBytes: 0x%08lX\n", lp->txBytes ); + len += sprintf(buf+len,"maxPort: 0x%04X\n", lp->maxPort ); /* 0 for STA, 6 for AP */ + /* Elements used for async notification from hardware */ +//x RID_LOG_STRCT RidList[10]; +//x ltv_t "updatedRecord: 0x%04X\n", lp->updatedRecord ); +//x PROBE_RESP "ProbeResp: 0x%04X\n", lp->ProbeResp ); +//x ASSOC_STATUS_STRCT "assoc_stat: 0x%04X\n", lp->assoc_stat ); +//x SECURITY_STATUS_STRCT "sec_stat: 0x%04X\n", lp->sec_stat ); +//x u_char lookAheadBuf[WVLAN_MAX_LOOKAHEAD]; + len += sprintf(buf+len,"PortType: 0x%04X\n", lp->PortType ); // 1 - 3 (1 [Normal] | 3 [AdHoc]) + len += sprintf(buf+len,"Channel: 0x%04X\n", lp->Channel ); // 0 - 14 (0) +//x hcf_16 TxRateControl[2]; + len += sprintf(buf+len,"TxRateControl[2]: 0x%04X 0x%04X\n", + lp->TxRateControl[0], lp->TxRateControl[1] ); + len += sprintf(buf+len,"DistanceBetweenAPs: 0x%04X\n", lp->DistanceBetweenAPs ); // 1 - 3 (1) + len += sprintf(buf+len,"RTSThreshold: 0x%04X\n", lp->RTSThreshold ); // 0 - 2347 (2347) + len += sprintf(buf+len,"PMEnabled: 0x%04X\n", lp->PMEnabled ); // 0 - 2, 8001 - 8002 (0) + len += sprintf(buf+len,"MicrowaveRobustness: 0x%04X\n", lp->MicrowaveRobustness );// 0 - 1 (0) + len += sprintf(buf+len,"CreateIBSS: 0x%04X\n", lp->CreateIBSS ); // 0 - 1 (0) + len += sprintf(buf+len,"MulticastReceive: 0x%04X\n", lp->MulticastReceive ); // 0 - 1 (1) + len += sprintf(buf+len,"MaxSleepDuration: 0x%04X\n", lp->MaxSleepDuration ); // 0 - 65535 (100) +//x hcf_8 MACAddress[ETH_ALEN]; + len += printf_hcf_8( "MACAddress", &buf[len], lp->MACAddress, ETH_ALEN ); +//x char NetworkName[HCF_MAX_NAME_LEN+1]; + len += sprintf(buf+len,"NetworkName: %.32s\n", lp->NetworkName ); +//x char StationName[HCF_MAX_NAME_LEN+1]; + len += sprintf(buf+len,"EnableEncryption: 0x%04X\n", lp->EnableEncryption ); // 0 - 1 (0) +//x char Key1[MAX_KEY_LEN+1]; + len += printf_hcf_8( "Key1", &buf[len], lp->Key1, MAX_KEY_LEN ); +//x char Key2[MAX_KEY_LEN+1]; +//x char Key3[MAX_KEY_LEN+1]; +//x char Key4[MAX_KEY_LEN+1]; + len += sprintf(buf+len,"TransmitKeyID: 0x%04X\n", lp->TransmitKeyID ); // 1 - 4 (1) +//x CFG_DEFAULT_KEYS_STRCT "DefaultKeys: 0x%04X\n", lp->DefaultKeys ); +//x u_char mailbox[MB_SIZE]; +//x char szEncryption[MAX_ENC_LEN]; + len += sprintf(buf+len,"driverEnable: 0x%04X\n", lp->driverEnable ); + len += sprintf(buf+len,"wolasEnable: 0x%04X\n", lp->wolasEnable ); + len += sprintf(buf+len,"atimWindow: 0x%04X\n", lp->atimWindow ); + len += sprintf(buf+len,"holdoverDuration: 0x%04X\n", lp->holdoverDuration ); +//x hcf_16 MulticastRate[2]; + len += sprintf(buf+len,"authentication: 0x%04X\n", lp->authentication ); // is this AP specific? + len += sprintf(buf+len,"promiscuousMode: 0x%04X\n", lp->promiscuousMode ); + len += sprintf(buf+len,"DownloadFirmware: 0x%04X\n", lp->DownloadFirmware ); // 0 - 2 (0 [None] | 1 [STA] | 2 [AP]) + len += sprintf(buf+len,"AuthKeyMgmtSuite: 0x%04X\n", lp->AuthKeyMgmtSuite ); + len += sprintf(buf+len,"loadBalancing: 0x%04X\n", lp->loadBalancing ); + len += sprintf(buf+len,"mediumDistribution: 0x%04X\n", lp->mediumDistribution ); + len += sprintf(buf+len,"txPowLevel: 0x%04X\n", lp->txPowLevel ); +// len += sprintf(buf+len,"shortRetryLimit: 0x%04X\n", lp->shortRetryLimit ); +// len += sprintf(buf+len,"longRetryLimit: 0x%04X\n", lp->longRetryLimit ); +//x hcf_16 srsc[2]; +//x hcf_16 brsc[2]; + len += sprintf(buf+len,"connectionControl: 0x%04X\n", lp->connectionControl ); +//x //hcf_16 probeDataRates[2]; + len += sprintf(buf+len,"ownBeaconInterval: 0x%04X\n", lp->ownBeaconInterval ); + len += sprintf(buf+len,"coexistence: 0x%04X\n", lp->coexistence ); +//x WVLAN_FRAME "txF: 0x%04X\n", lp->txF ); +//x WVLAN_LFRAME txList[DEFAULT_NUM_TX_FRAMES]; +//x struct list_head "txFree: 0x%04X\n", lp->txFree ); +//x struct list_head txQ[WVLAN_MAX_TX_QUEUES]; + len += sprintf(buf+len,"netif_queue_on: 0x%04X\n", lp->netif_queue_on ); + len += sprintf(buf+len,"txQ_count: 0x%04X\n", lp->txQ_count ); +//x DESC_STRCT "desc_rx: 0x%04X\n", lp->desc_rx ); +//x DESC_STRCT "desc_tx: 0x%04X\n", lp->desc_tx ); +//x WVLAN_PORT_STATE "portState: 0x%04X\n", lp->portState ); +//x ScanResult "scan_results: 0x%04X\n", lp->scan_results ); +//x ProbeResult "probe_results: 0x%04X\n", lp->probe_results ); + len += sprintf(buf+len,"probe_num_aps: 0x%04X\n", lp->probe_num_aps ); + len += sprintf(buf+len,"use_dma: 0x%04X\n", lp->use_dma ); +//x DMA_STRCT "dma: 0x%04X\n", lp->dma ); +#ifdef USE_RTS + len += sprintf(buf+len,"useRTS: 0x%04X\n", lp->useRTS ); +#endif // USE_RTS +#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP + //;?should we restore this to allow smaller memory footprint + //;?I guess not. This should be brought under Debug mode only + len += sprintf(buf+len,"DTIMPeriod: 0x%04X\n", lp->DTIMPeriod ); // 1 - 255 (1) + len += sprintf(buf+len,"multicastPMBuffering: 0x%04X\n", lp->multicastPMBuffering ); + len += sprintf(buf+len,"RejectAny: 0x%04X\n", lp->RejectAny ); // 0 - 1 (0) + len += sprintf(buf+len,"ExcludeUnencrypted: 0x%04X\n", lp->ExcludeUnencrypted ); // 0 - 1 (1) + len += sprintf(buf+len,"intraBSSRelay: 0x%04X\n", lp->intraBSSRelay ); + len += sprintf(buf+len,"wlags49_type: 0x%08lX\n", lp->wlags49_type ); +#ifdef USE_WDS +//x WVLAN_WDS_IF wds_port[NUM_WDS_PORTS]; +#endif // USE_WDS +#endif // HCF_AP + } else if ( lp->wlags49_type == 2 ){ + len += sprintf(buf+len,"tallies to be added\n" ); +//Hermes Tallies (IFB substructure) { + p = &lp->hcfCtx.IFB_NIC_Tallies; + len += sprintf(buf+len,"TxUnicastFrames: %08lX\n", p->TxUnicastFrames ); + len += sprintf(buf+len,"TxMulticastFrames: %08lX\n", p->TxMulticastFrames ); + len += sprintf(buf+len,"TxFragments: %08lX\n", p->TxFragments ); + len += sprintf(buf+len,"TxUnicastOctets: %08lX\n", p->TxUnicastOctets ); + len += sprintf(buf+len,"TxMulticastOctets: %08lX\n", p->TxMulticastOctets ); + len += sprintf(buf+len,"TxDeferredTransmissions: %08lX\n", p->TxDeferredTransmissions ); + len += sprintf(buf+len,"TxSingleRetryFrames: %08lX\n", p->TxSingleRetryFrames ); + len += sprintf(buf+len,"TxMultipleRetryFrames: %08lX\n", p->TxMultipleRetryFrames ); + len += sprintf(buf+len,"TxRetryLimitExceeded: %08lX\n", p->TxRetryLimitExceeded ); + len += sprintf(buf+len,"TxDiscards: %08lX\n", p->TxDiscards ); + len += sprintf(buf+len,"RxUnicastFrames: %08lX\n", p->RxUnicastFrames ); + len += sprintf(buf+len,"RxMulticastFrames: %08lX\n", p->RxMulticastFrames ); + len += sprintf(buf+len,"RxFragments: %08lX\n", p->RxFragments ); + len += sprintf(buf+len,"RxUnicastOctets: %08lX\n", p->RxUnicastOctets ); + len += sprintf(buf+len,"RxMulticastOctets: %08lX\n", p->RxMulticastOctets ); + len += sprintf(buf+len,"RxFCSErrors: %08lX\n", p->RxFCSErrors ); + len += sprintf(buf+len,"RxDiscardsNoBuffer: %08lX\n", p->RxDiscardsNoBuffer ); + len += sprintf(buf+len,"TxDiscardsWrongSA: %08lX\n", p->TxDiscardsWrongSA ); + len += sprintf(buf+len,"RxWEPUndecryptable: %08lX\n", p->RxWEPUndecryptable ); + len += sprintf(buf+len,"RxMsgInMsgFragments: %08lX\n", p->RxMsgInMsgFragments ); + len += sprintf(buf+len,"RxMsgInBadMsgFragments: %08lX\n", p->RxMsgInBadMsgFragments ); + len += sprintf(buf+len,"RxDiscardsWEPICVError: %08lX\n", p->RxDiscardsWEPICVError ); + len += sprintf(buf+len,"RxDiscardsWEPExcluded: %08lX\n", p->RxDiscardsWEPExcluded ); +#if (HCF_EXT) & HCF_EXT_TALLIES_FW + //to be added ;? +#endif // HCF_EXT_TALLIES_FW + } else if ( lp->wlags49_type & 0x8000 ) { //;?kludgy but it is unclear to me were else to place this +#if DBG + DbgInfo->DebugFlag = lp->wlags49_type & 0x7FFF; +#endif // DBG + lp->wlags49_type = 0; //default to IFB again ;? + } else { + len += sprintf(buf+len,"unknown value for wlags49_type: 0x%08lX\n", lp->wlags49_type ); + len += sprintf(buf+len,"0x0000 - IFB\n" ); + len += sprintf(buf+len,"0x0001 - wl_private\n" ); + len += sprintf(buf+len,"0x0002 - Tallies\n" ); + len += sprintf(buf+len,"0x8xxx - Change debufflag\n" ); + len += sprintf(buf+len,"ERROR 0001\nWARNING 0002\nNOTICE 0004\nTRACE 0008\n" ); + len += sprintf(buf+len,"VERBOSE 0010\nPARAM 0020\nBREAK 0040\nRX 0100\n" ); + len += sprintf(buf+len,"TX 0200\nDS 0400\n" ); + } + return len; +} // scull_read_procmem + +static void proc_write(const char *name, write_proc_t *w, void *data) +{ + struct proc_dir_entry * entry = create_proc_entry(name, S_IFREG | S_IWUSR, NULL); + if (entry) { + entry->write_proc = w; + entry->data = data; + } +} // proc_write + +static int write_int(struct file *file, const char *buffer, unsigned long count, void *data) +{ + static char proc_number[11]; + unsigned int nr = 0; + + DBG_FUNC( "write_int" ); + DBG_ENTER( DbgInfo ); + + if (count > 9) { + count = -EINVAL; + } else if ( copy_from_user(proc_number, buffer, count) ) { + count = -EFAULT; + } + if (count > 0 ) { + proc_number[count] = 0; + nr = wl_atoi( proc_number ); + *(unsigned int *)data = nr; + if ( nr & 0x8000 ) { //;?kludgy but it is unclear to me were else to place this +#if DBG + DbgInfo->DebugFlag = nr & 0x7FFF; +#endif // DBG + } + } + DBG_PRINT( "value: %08X\n", nr ); + DBG_LEAVE( DbgInfo ); + return count; +} // write_int + +#endif /* SCULL_USE_PROC */ + +#ifdef DN554 +#define RUN_AT(x) (jiffies+(x)) //"borrowed" from include/pcmcia/k_compat.h +#define DS_OOR 0x8000 //Deepsleep OutOfRange Status + + lp->timer_oor_cnt = DS_OOR; + init_timer( &lp->timer_oor ); + lp->timer_oor.function = timer_oor; + lp->timer_oor.data = (unsigned long)lp; + lp->timer_oor.expires = RUN_AT( 3 * HZ ); + add_timer( &lp->timer_oor ); + printk( "<5>wl_enable: %ld\n", jiffies ); //;?remove me 1 day +#endif //DN554 +#ifdef DN554 +/******************************************************************************* + * timer_oor() + ******************************************************************************* + * + * DESCRIPTION: + * + * + * PARAMETERS: + * + * arg - a u_long representing a pointer to a dev_link_t structure for the + * device to be released. + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void timer_oor( u_long arg ) +{ + struct wl_private *lp = (struct wl_private *)arg; + + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "timer_oor" ); + DBG_ENTER( DbgInfo ); + DBG_PARAM( DbgInfo, "arg", "0x%08lx", arg ); + + printk( "<5>timer_oor: %ld 0x%04X\n", jiffies, lp->timer_oor_cnt ); //;?remove me 1 day + lp->timer_oor_cnt += 10; + if ( (lp->timer_oor_cnt & ~DS_OOR) > 300 ) { + lp->timer_oor_cnt = 300; + } + lp->timer_oor_cnt |= DS_OOR; + init_timer( &lp->timer_oor ); + lp->timer_oor.function = timer_oor; + lp->timer_oor.data = (unsigned long)lp; + lp->timer_oor.expires = RUN_AT( (lp->timer_oor_cnt & ~DS_OOR) * HZ ); + add_timer( &lp->timer_oor ); + + DBG_LEAVE( DbgInfo ); +} // timer_oor +#endif //DN554 + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/staging/wlags49_h2/wl_main.h b/drivers/staging/wlags49_h2/wl_main.h new file mode 100644 index 0000000000000000000000000000000000000000..d593ae535fb8a75a0628ab5d801adc3b01ff7a1d --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_main.h @@ -0,0 +1,138 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * Header describing device specific routines and driver init/un-init. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +#ifndef __WL_MAIN_H__ +#define __WL_MAIN_H__ + + + + +/******************************************************************************* + * function prototypes + ******************************************************************************/ +int wl_insert( struct net_device *dev ); + +void wl_set_wep_keys( struct wl_private *lp ); + +int wl_put_ltv_init( struct wl_private *lp ); + +int wl_put_ltv( struct wl_private *lp ); + +p_u16 wl_get_irq_mask( void ); + +p_s8 * wl_get_irq_list( void ); + +int wl_reset( struct net_device *dev ); + +int wl_go( struct wl_private *lp ); + +int wl_apply( struct wl_private *lp ); + +irqreturn_t wl_isr( int irq, void *dev_id, struct pt_regs *regs ); + +void wl_remove( struct net_device *dev ); + +void wl_suspend( struct net_device *dev ); + +void wl_resume( struct net_device *dev ); + +void wl_release( struct net_device *dev ); + +int wl_enable( struct wl_private *lp ); + +int wl_connect( struct wl_private *lp ); + +int wl_disable( struct wl_private *lp ); + +int wl_disconnect( struct wl_private *lp ); + +void wl_enable_wds_ports( struct wl_private * lp ); + +void wl_disable_wds_ports( struct wl_private * lp ); + +#ifndef USE_MBOX_SYNC + +int wl_mbx( struct wl_private *lp ); +void wl_endian_translate_mailbox( ltv_t *ltv ); +void wl_process_mailbox( struct wl_private *lp ); + +#endif /* USE_MBOX_SYNC */ + + +#ifdef USE_WDS + +void wl_wds_netdev_register( struct wl_private *lp ); +void wl_wds_netdev_deregister( struct wl_private *lp ); + +#endif /* USE_WDS */ + + +#ifdef USE_WDS + +#define WL_WDS_NETDEV_REGISTER( ARG ) wl_wds_netdev_register( ARG ) +#define WL_WDS_NETDEV_DEREGISTER( ARG ) wl_wds_netdev_deregister( ARG ) + +#else + +#define WL_WDS_NETDEV_REGISTER( ARG ) +#define WL_WDS_NETDEV_DEREGISTER( ARG ) + +#endif /* USE_WDS */ +#endif // __WL_MAIN_H__ diff --git a/drivers/staging/wlags49_h2/wl_netdev.c b/drivers/staging/wlags49_h2/wl_netdev.c new file mode 100644 index 0000000000000000000000000000000000000000..ac38902479657c2c56d8921ae646d3ef2b5e7c4a --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_netdev.c @@ -0,0 +1,2070 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * This file contains handler functions registered with the net_device + * structure. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +/******************************************************************************* + * include 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 +#include +#include + +#ifdef USE_PROFILE +#include +#endif /* USE_PROFILE */ + +#ifdef BUS_PCMCIA +#include +#endif /* BUS_PCMCIA */ + +#ifdef BUS_PCI +#include +#endif /* BUS_PCI */ + + +/******************************************************************************* + * global variables + ******************************************************************************/ +#if DBG +extern dbg_info_t *DbgInfo; +#endif /* DBG */ + + +#if HCF_ENCAP +#define MTU_MAX (HCF_MAX_MSG - ETH_HLEN - 8) +#else +#define MTU_MAX (HCF_MAX_MSG - ETH_HLEN) +#endif + +//static int mtu = MTU_MAX; +//MODULE_PARM(mtu, "i"); +//MODULE_PARM_DESC(mtu, "MTU"); + +/******************************************************************************* + * macros + ******************************************************************************/ +#define BLOCK_INPUT(buf, len) \ + desc->buf_addr = buf; \ + desc->BUF_SIZE = len; \ + status = hcf_rcv_msg(&(lp->hcfCtx), desc, 0) + +#define BLOCK_INPUT_DMA(buf, len) memcpy( buf, desc_next->buf_addr, pktlen ) + +/******************************************************************************* + * function prototypes + ******************************************************************************/ + +/******************************************************************************* + * wl_init() + ******************************************************************************* + * + * DESCRIPTION: + * + * We never need to do anything when a "Wireless" device is "initialized" + * by the net software, because we only register already-found cards. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_init( struct net_device *dev ) +{ +// unsigned long flags; +// struct wl_private *lp = wl_priv(dev); + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_init" ); + DBG_ENTER( DbgInfo ); + + DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + + /* Nothing to do, but grab the spinlock anyway just in case we ever need + this routine */ +// wl_lock( lp, &flags ); +// wl_unlock( lp, &flags ); + + DBG_LEAVE( DbgInfo ); + return 0; +} // wl_init +/*============================================================================*/ + +/******************************************************************************* + * wl_config() + ******************************************************************************* + * + * DESCRIPTION: + * + * Implement the SIOCSIFMAP interface. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure + * map - a pointer to the device's ifmap structure + * + * RETURNS: + * + * 0 on success + * errno otherwise + * + ******************************************************************************/ +int wl_config( struct net_device *dev, struct ifmap *map ) +{ + DBG_FUNC( "wl_config" ); + DBG_ENTER( DbgInfo ); + + DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + DBG_PARAM( DbgInfo, "map", "0x%p", map ); + + /* The only thing we care about here is a port change. Since this not needed, + ignore the request. */ + DBG_TRACE( DbgInfo, "%s: %s called.\n", dev->name, __FUNC__ ); + + DBG_LEAVE( DbgInfo ); + return 0; +} // wl_config +/*============================================================================*/ + +/******************************************************************************* + * wl_stats() + ******************************************************************************* + * + * DESCRIPTION: + * + * Return the current device statistics. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure + * + * RETURNS: + * + * a pointer to a net_device_stats structure containing the network + * statistics. + * + ******************************************************************************/ +struct net_device_stats *wl_stats( struct net_device *dev ) +{ +#ifdef USE_WDS + int count; +#endif /* USE_WDS */ + unsigned long flags; + struct net_device_stats *pStats; + struct wl_private *lp = wl_priv(dev); + /*------------------------------------------------------------------------*/ + + //DBG_FUNC( "wl_stats" ); + //DBG_ENTER( DbgInfo ); + //DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + + pStats = NULL; + + wl_lock( lp, &flags ); + +#ifdef USE_RTS + if( lp->useRTS == 1 ) { + wl_unlock( lp, &flags ); + + //DBG_LEAVE( DbgInfo ); + return NULL; + } +#endif /* USE_RTS */ + + /* Return the statistics for the appropriate device */ +#ifdef USE_WDS + + for( count = 0; count < NUM_WDS_PORTS; count++ ) { + if( dev == lp->wds_port[count].dev ) { + pStats = &( lp->wds_port[count].stats ); + } + } + +#endif /* USE_WDS */ + + /* If pStats is still NULL, then the device is not a WDS port */ + if( pStats == NULL ) { + pStats = &( lp->stats ); + } + + wl_unlock( lp, &flags ); + + //DBG_LEAVE( DbgInfo ); + + return pStats; +} // wl_stats +/*============================================================================*/ + +/******************************************************************************* + * wl_open() + ******************************************************************************* + * + * DESCRIPTION: + * + * Open the device. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure + * + * RETURNS: + * + * 0 on success + * errno otherwise + * + ******************************************************************************/ +int wl_open(struct net_device *dev) +{ + int status = HCF_SUCCESS; + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_open" ); + DBG_ENTER( DbgInfo ); + + wl_lock( lp, &flags ); + +#ifdef USE_RTS + if( lp->useRTS == 1 ) { + DBG_TRACE( DbgInfo, "Skipping device open, in RTS mode\n" ); + wl_unlock( lp, &flags ); + DBG_LEAVE( DbgInfo ); + return -EIO; + } +#endif /* USE_RTS */ + +#ifdef USE_PROFILE + parse_config( dev ); +#endif + + if( lp->portState == WVLAN_PORT_STATE_DISABLED ) { + DBG_TRACE( DbgInfo, "Enabling Port 0\n" ); + status = wl_enable( lp ); + + if( status != HCF_SUCCESS ) { + DBG_TRACE( DbgInfo, "Enable port 0 failed: 0x%x\n", status ); + } + } + + // Holding the lock too long, make a gap to allow other processes + wl_unlock(lp, &flags); + wl_lock( lp, &flags ); + + if ( strlen( lp->fw_image_filename ) ) { + DBG_TRACE( DbgInfo, ";???? Kludgy way to force a download\n" ); + status = wl_go( lp ); + } else { + status = wl_apply( lp ); + } + + // Holding the lock too long, make a gap to allow other processes + wl_unlock(lp, &flags); + wl_lock( lp, &flags ); + + if( status != HCF_SUCCESS ) { + // Unsuccesfull, try reset of the card to recover + status = wl_reset( dev ); + } + + // Holding the lock too long, make a gap to allow other processes + wl_unlock(lp, &flags); + wl_lock( lp, &flags ); + + if( status == HCF_SUCCESS ) { + netif_carrier_on( dev ); + WL_WDS_NETIF_CARRIER_ON( lp ); + + lp->is_handling_int = WL_HANDLING_INT; // Start handling interrupts + wl_act_int_on( lp ); + + netif_start_queue( dev ); + WL_WDS_NETIF_START_QUEUE( lp ); + } else { + wl_hcf_error( dev, status ); /* Report the error */ + netif_device_detach( dev ); /* Stop the device and queue */ + } + + wl_unlock( lp, &flags ); + + DBG_LEAVE( DbgInfo ); + return status; +} // wl_open +/*============================================================================*/ + +/******************************************************************************* + * wl_close() + ******************************************************************************* + * + * DESCRIPTION: + * + * Close the device. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure + * + * RETURNS: + * + * 0 on success + * errno otherwise + * + ******************************************************************************/ +int wl_close( struct net_device *dev ) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + /*------------------------------------------------------------------------*/ + + DBG_FUNC("wl_close"); + DBG_ENTER(DbgInfo); + DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); + + /* Mark the adapter as busy */ + netif_stop_queue( dev ); + WL_WDS_NETIF_STOP_QUEUE( lp ); + + netif_carrier_off( dev ); + WL_WDS_NETIF_CARRIER_OFF( lp ); + + /* Shutdown the adapter: + Disable adapter interrupts + Stop Tx/Rx + Update statistics + Set low power mode + */ + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + lp->is_handling_int = WL_NOT_HANDLING_INT; // Stop handling interrupts + +#ifdef USE_RTS + if( lp->useRTS == 1 ) { + DBG_TRACE( DbgInfo, "Skipping device close, in RTS mode\n" ); + wl_unlock( lp, &flags ); + DBG_LEAVE( DbgInfo ); + return -EIO; + } +#endif /* USE_RTS */ + + /* Disable the ports */ + wl_disable( lp ); + + wl_unlock( lp, &flags ); + + DBG_LEAVE( DbgInfo ); + return 0; +} // wl_close +/*============================================================================*/ + +static void wl_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1); + strncpy(info->version, DRV_VERSION_STR, sizeof(info->version) - 1); +// strncpy(info.fw_version, priv->fw_name, +// sizeof(info.fw_version) - 1); + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20)) + if (dev->dev.parent) { + dev_set_name(dev->dev.parent, "%s", info->bus_info); + //strncpy(info->bus_info, dev->dev.parent->bus_id, + // sizeof(info->bus_info) - 1); +#else + if (dev->class_dev.parent) { + sizeof(info->bus_info) - 1); +#endif + } else { + snprintf(info->bus_info, sizeof(info->bus_info) - 1, + "PCMCIA FIXME"); +// "PCMCIA 0x%lx", priv->hw.iobase); + } +} // wl_get_drvinfo + +static struct ethtool_ops wl_ethtool_ops = { + .get_drvinfo = wl_get_drvinfo, + .get_link = ethtool_op_get_link, +}; + + +/******************************************************************************* + * wl_ioctl() + ******************************************************************************* + * + * DESCRIPTION: + * + * The IOCTL handler for the device. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device struct. + * rq - a pointer to the IOCTL request buffer. + * cmd - the IOCTL command code. + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_ioctl( struct net_device *dev, struct ifreq *rq, int cmd ) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_ioctl" ); + DBG_ENTER(DbgInfo); + DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); + DBG_PARAM(DbgInfo, "rq", "0x%p", rq); + DBG_PARAM(DbgInfo, "cmd", "0x%04x", cmd); + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + +#ifdef USE_RTS + if( lp->useRTS == 1 ) { + /* Handle any RTS IOCTL here */ + if( cmd == WL_IOCTL_RTS ) { + DBG_TRACE( DbgInfo, "IOCTL: WL_IOCTL_RTS\n" ); + ret = wvlan_rts( (struct rtsreq *)rq, dev->base_addr ); + } else { + DBG_TRACE( DbgInfo, "IOCTL not supported in RTS mode: 0x%X\n", cmd ); + ret = -EOPNOTSUPP; + } + + goto out_act_int_on_unlock; + } +#endif /* USE_RTS */ + + /* Only handle UIL IOCTL requests when the UIL has the system blocked. */ + if( !(( lp->flags & WVLAN2_UIL_BUSY ) && ( cmd != WVLAN2_IOCTL_UIL ))) { +#ifdef USE_UIL + struct uilreq *urq = (struct uilreq *)rq; +#endif /* USE_UIL */ + + switch( cmd ) { + // ================== Private IOCTLs (up to 16) ================== +#ifdef USE_UIL + case WVLAN2_IOCTL_UIL: + DBG_TRACE( DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL\n" ); + ret = wvlan_uil( urq, lp ); + break; +#endif /* USE_UIL */ + + default: + DBG_TRACE(DbgInfo, "IOCTL CODE NOT SUPPORTED: 0x%X\n", cmd ); + ret = -EOPNOTSUPP; + break; + } + } else { + DBG_WARNING( DbgInfo, "DEVICE IS BUSY, CANNOT PROCESS REQUEST\n" ); + ret = -EBUSY; + } + +#ifdef USE_RTS +out_act_int_on_unlock: +#endif /* USE_RTS */ + wl_act_int_on( lp ); + + wl_unlock( lp, &flags ); + + DBG_LEAVE( DbgInfo ); + return ret; +} // wl_ioctl +/*============================================================================*/ + +#ifdef CONFIG_NET_POLL_CONTROLLER +void wl_poll(struct net_device *dev) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + struct pt_regs regs; + + wl_lock( lp, &flags ); + wl_isr(dev->irq, dev, ®s); + wl_unlock( lp, &flags ); +} +#endif + +/******************************************************************************* + * wl_tx_timeout() + ******************************************************************************* + * + * DESCRIPTION: + * + * The handler called when, for some reason, a Tx request is not completed. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device struct. + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_tx_timeout( struct net_device *dev ) +{ +#ifdef USE_WDS + int count; +#endif /* USE_WDS */ + unsigned long flags; + struct wl_private *lp = wl_priv(dev); + struct net_device_stats *pStats = NULL; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_tx_timeout" ); + DBG_ENTER( DbgInfo ); + + DBG_WARNING( DbgInfo, "%s: Transmit timeout.\n", dev->name ); + + wl_lock( lp, &flags ); + +#ifdef USE_RTS + if( lp->useRTS == 1 ) { + DBG_TRACE( DbgInfo, "Skipping tx_timeout handler, in RTS mode\n" ); + wl_unlock( lp, &flags ); + + DBG_LEAVE( DbgInfo ); + return; + } +#endif /* USE_RTS */ + + /* Figure out which device (the "root" device or WDS port) this timeout + is for */ +#ifdef USE_WDS + + for( count = 0; count < NUM_WDS_PORTS; count++ ) { + if( dev == lp->wds_port[count].dev ) { + pStats = &( lp->wds_port[count].stats ); + + /* Break the loop so that we can use the counter to access WDS + information in the private structure */ + break; + } + } + +#endif /* USE_WDS */ + + /* If pStats is still NULL, then the device is not a WDS port */ + if( pStats == NULL ) { + pStats = &( lp->stats ); + } + + /* Accumulate the timeout error */ + pStats->tx_errors++; + + wl_unlock( lp, &flags ); + + DBG_LEAVE( DbgInfo ); + return; +} // wl_tx_timeout +/*============================================================================*/ + +/******************************************************************************* + * wl_send() + ******************************************************************************* + * + * DESCRIPTION: + * + * The routine which performs data transmits. + * + * PARAMETERS: + * + * lp - a pointer to the device's wl_private struct. + * + * RETURNS: + * + * 0 on success + * 1 on error + * + ******************************************************************************/ +int wl_send( struct wl_private *lp ) +{ + + int status; + DESC_STRCT *desc; + WVLAN_LFRAME *txF = NULL; + struct list_head *element; + int len; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_send" ); + + if( lp == NULL ) { + DBG_ERROR( DbgInfo, "Private adapter struct is NULL\n" ); + return FALSE; + } + if( lp->dev == NULL ) { + DBG_ERROR( DbgInfo, "net_device struct in wl_private is NULL\n" ); + return FALSE; + } + + /* Check for the availability of FIDs; if none are available, don't take any + frames off the txQ */ + if( lp->hcfCtx.IFB_RscInd == 0 ) { + return FALSE; + } + + /* Reclaim the TxQ Elements and place them back on the free queue */ + if( !list_empty( &( lp->txQ[0] ))) { + element = lp->txQ[0].next; + + txF = (WVLAN_LFRAME * )list_entry( element, WVLAN_LFRAME, node ); + if( txF != NULL ) { + lp->txF.skb = txF->frame.skb; + lp->txF.port = txF->frame.port; + + txF->frame.skb = NULL; + txF->frame.port = 0; + + list_del( &( txF->node )); + list_add( element, &( lp->txFree )); + + lp->txQ_count--; + + if( lp->txQ_count < TX_Q_LOW_WATER_MARK ) { + if( lp->netif_queue_on == FALSE ) { + DBG_TX( DbgInfo, "Kickstarting Q: %d\n", lp->txQ_count ); + netif_wake_queue( lp->dev ); + WL_WDS_NETIF_WAKE_QUEUE( lp ); + lp->netif_queue_on = TRUE; + } + } + } + } + + if( lp->txF.skb == NULL ) { + return FALSE; + } + + /* If the device has resources (FIDs) available, then Tx the packet */ + /* Format the TxRequest and send it to the adapter */ + len = lp->txF.skb->len < ETH_ZLEN ? ETH_ZLEN : lp->txF.skb->len; + + desc = &( lp->desc_tx ); + desc->buf_addr = lp->txF.skb->data; + desc->BUF_CNT = len; + desc->next_desc_addr = NULL; + + status = hcf_send_msg( &( lp->hcfCtx ), desc, lp->txF.port ); + + if( status == HCF_SUCCESS ) { + lp->dev->trans_start = jiffies; + + DBG_TX( DbgInfo, "Transmit...\n" ); + + if( lp->txF.port == HCF_PORT_0 ) { + lp->stats.tx_packets++; + lp->stats.tx_bytes += lp->txF.skb->len; + } + +#ifdef USE_WDS + else + { + lp->wds_port[(( lp->txF.port >> 8 ) - 1)].stats.tx_packets++; + lp->wds_port[(( lp->txF.port >> 8 ) - 1)].stats.tx_bytes += lp->txF.skb->len; + } + +#endif /* USE_WDS */ + + /* Free the skb and perform queue cleanup, as the buffer was + transmitted successfully */ + dev_kfree_skb( lp->txF.skb ); + + lp->txF.skb = NULL; + lp->txF.port = 0; + } + + return TRUE; +} // wl_send +/*============================================================================*/ + +/******************************************************************************* + * wl_tx() + ******************************************************************************* + * + * DESCRIPTION: + * + * The Tx handler function for the network layer. + * + * PARAMETERS: + * + * skb - a pointer to the sk_buff structure containing the data to transfer. + * dev - a pointer to the device's net_device structure. + * + * RETURNS: + * + * 0 on success + * 1 on error + * + ******************************************************************************/ +int wl_tx( struct sk_buff *skb, struct net_device *dev, int port ) +{ + unsigned long flags; + struct wl_private *lp = wl_priv(dev); + WVLAN_LFRAME *txF = NULL; + struct list_head *element; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_tx" ); + + /* Grab the spinlock */ + wl_lock( lp, &flags ); + + if( lp->flags & WVLAN2_UIL_BUSY ) { + DBG_WARNING( DbgInfo, "UIL has device blocked\n" ); + /* Start dropping packets here??? */ + wl_unlock( lp, &flags ); + return 1; + } + +#ifdef USE_RTS + if( lp->useRTS == 1 ) { + DBG_PRINT( "RTS: we're getting a Tx...\n" ); + wl_unlock( lp, &flags ); + return 1; + } +#endif /* USE_RTS */ + + if( !lp->use_dma ) { + /* Get an element from the queue */ + element = lp->txFree.next; + txF = (WVLAN_LFRAME *)list_entry( element, WVLAN_LFRAME, node ); + if( txF == NULL ) { + DBG_ERROR( DbgInfo, "Problem with list_entry\n" ); + wl_unlock( lp, &flags ); + return 1; + } + /* Fill out the frame */ + txF->frame.skb = skb; + txF->frame.port = port; + /* Move the frame to the txQ */ + /* NOTE: Here's where we would do priority queueing */ + list_del( &( txF->node )); + list_add( &( txF->node ), &( lp->txQ[0] )); + + lp->txQ_count++; + if( lp->txQ_count >= DEFAULT_NUM_TX_FRAMES ) { + DBG_TX( DbgInfo, "Q Full: %d\n", lp->txQ_count ); + if( lp->netif_queue_on == TRUE ) { + netif_stop_queue( lp->dev ); + WL_WDS_NETIF_STOP_QUEUE( lp ); + lp->netif_queue_on = FALSE; + } + } + } + wl_act_int_off( lp ); /* Disable Interrupts */ + + /* Send the data to the hardware using the appropriate method */ +#ifdef ENABLE_DMA + if( lp->use_dma ) { + wl_send_dma( lp, skb, port ); + } + else +#endif + { + wl_send( lp ); + } + /* Re-enable Interrupts, release the spinlock and return */ + wl_act_int_on( lp ); + wl_unlock( lp, &flags ); + return 0; +} // wl_tx +/*============================================================================*/ + +/******************************************************************************* + * wl_rx() + ******************************************************************************* + * + * DESCRIPTION: + * + * The routine which performs data reception. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure. + * + * RETURNS: + * + * 0 on success + * 1 on error + * + ******************************************************************************/ +int wl_rx(struct net_device *dev) +{ + int port; + struct sk_buff *skb; + struct wl_private *lp = wl_priv(dev); + int status; + hcf_16 pktlen; + hcf_16 hfs_stat; + DESC_STRCT *desc; + /*------------------------------------------------------------------------*/ + + DBG_FUNC("wl_rx") + DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); + + if(!( lp->flags & WVLAN2_UIL_BUSY )) { + +#ifdef USE_RTS + if( lp->useRTS == 1 ) { + DBG_PRINT( "RTS: We're getting an Rx...\n" ); + return -EIO; + } +#endif /* USE_RTS */ + + /* Read the HFS_STAT register from the lookahead buffer */ + hfs_stat = (hcf_16)(( lp->lookAheadBuf[HFS_STAT] ) | + ( lp->lookAheadBuf[HFS_STAT + 1] << 8 )); + + /* Make sure the frame isn't bad */ + if(( hfs_stat & HFS_STAT_ERR ) != HCF_SUCCESS ) { + DBG_WARNING( DbgInfo, "HFS_STAT_ERROR (0x%x) in Rx Packet\n", + lp->lookAheadBuf[HFS_STAT] ); + return -EIO; + } + + /* Determine what port this packet is for */ + port = ( hfs_stat >> 8 ) & 0x0007; + DBG_RX( DbgInfo, "Rx frame for port %d\n", port ); + + if(( pktlen = lp->hcfCtx.IFB_RxLen ) != 0 ) { + if(( skb = ALLOC_SKB( pktlen )) != NULL ) { + /* Set the netdev based on the port */ + switch( port ) { +#ifdef USE_WDS + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + skb->dev = lp->wds_port[port-1].dev; + break; +#endif /* USE_WDS */ + + case 0: + default: + skb->dev = dev; + break; + } + + desc = &( lp->desc_rx ); + + desc->next_desc_addr = NULL; + +/* +#define BLOCK_INPUT(buf, len) \ + desc->buf_addr = buf; \ + desc->BUF_SIZE = len; \ + status = hcf_rcv_msg(&(lp->hcfCtx), desc, 0) +*/ + + GET_PACKET( skb->dev, skb, pktlen ); + + if( status == HCF_SUCCESS ) { + netif_rx( skb ); + + if( port == 0 ) { + lp->stats.rx_packets++; + lp->stats.rx_bytes += pktlen; + } +#ifdef USE_WDS + else + { + lp->wds_port[port-1].stats.rx_packets++; + lp->wds_port[port-1].stats.rx_bytes += pktlen; + } +#endif /* USE_WDS */ + + dev->last_rx = jiffies; + +#ifdef WIRELESS_EXT +#ifdef WIRELESS_SPY + if( lp->spydata.spy_number > 0 ) { + char *srcaddr = skb->mac.raw + MAC_ADDR_SIZE; + + wl_spy_gather( dev, srcaddr ); + } +#endif /* WIRELESS_SPY */ +#endif /* WIRELESS_EXT */ + } else { + DBG_ERROR( DbgInfo, "Rx request to card FAILED\n" ); + + if( port == 0 ) { + lp->stats.rx_dropped++; + } +#ifdef USE_WDS + else + { + lp->wds_port[port-1].stats.rx_dropped++; + } +#endif /* USE_WDS */ + + dev_kfree_skb( skb ); + } + } else { + DBG_ERROR( DbgInfo, "Could not alloc skb\n" ); + + if( port == 0 ) { + lp->stats.rx_dropped++; + } +#ifdef USE_WDS + else + { + lp->wds_port[port-1].stats.rx_dropped++; + } +#endif /* USE_WDS */ + } + } + } + + return 0; +} // wl_rx +/*============================================================================*/ + +/******************************************************************************* + * wl_multicast() + ******************************************************************************* + * + * DESCRIPTION: + * + * Function to handle multicast packets + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure. + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +#ifdef NEW_MULTICAST + +void wl_multicast( struct net_device *dev ) +{ +#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA //;?should we return an error status in AP mode +//;?seems reasonable that even an AP-only driver could afford this small additional footprint + + int x; + struct dev_mc_list *mclist; + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_multicast" ); + DBG_ENTER( DbgInfo ); + DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + + if( !wl_adapter_is_open( dev )) { + DBG_LEAVE( DbgInfo ); + return; + } + +#if DBG + if( DBG_FLAGS( DbgInfo ) & DBG_PARAM_ON ) { + DBG_PRINT(" flags: %s%s%s\n", + ( dev->flags & IFF_PROMISC ) ? "Promiscous " : "", + ( dev->flags & IFF_MULTICAST ) ? "Multicast " : "", + ( dev->flags & IFF_ALLMULTI ) ? "All-Multicast" : "" ); + + DBG_PRINT( " mc_count: %d\n", dev->mc_count ); + + for( x = 0, mclist = dev->mc_list; mclist && x < dev->mc_count; + x++, mclist = mclist->next ) { + DBG_PRINT( " %s (%d)\n", DbgHwAddr(mclist->dmi_addr), + mclist->dmi_addrlen ); + } + } +#endif /* DBG */ + + if(!( lp->flags & WVLAN2_UIL_BUSY )) { + +#ifdef USE_RTS + if( lp->useRTS == 1 ) { + DBG_TRACE( DbgInfo, "Skipping multicast, in RTS mode\n" ); + + DBG_LEAVE( DbgInfo ); + return; + } +#endif /* USE_RTS */ + + wl_lock( lp, &flags ); + wl_act_int_off( lp ); + + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) { + if( dev->flags & IFF_PROMISC ) { + /* Enable promiscuous mode */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_PROMISCUOUS_MODE; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 1 ); + DBG_PRINT( "Enabling Promiscuous mode (IFF_PROMISC)\n" ); + hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + } + else if(( dev->mc_count > HCF_MAX_MULTICAST ) || + ( dev->flags & IFF_ALLMULTI )) { + /* Shutting off this filter will enable all multicast frames to + be sent up from the device; however, this is a static RID, so + a call to wl_apply() is needed */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_RX_ALL_GROUP_ADDR; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); + DBG_PRINT( "Enabling all multicast mode (IFF_ALLMULTI)\n" ); + hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + wl_apply( lp ); + } + else if( dev->mc_count != 0 ) { + /* Set the multicast addresses */ + lp->ltvRecord.len = ( dev->mc_count * 3 ) + 1; + lp->ltvRecord.typ = CFG_GROUP_ADDR; + + for( x = 0, mclist = dev->mc_list; + ( x < dev->mc_count ) && ( mclist != NULL ); + x++, mclist = mclist->next ) { + memcpy( &( lp->ltvRecord.u.u8[x * ETH_ALEN] ), + mclist->dmi_addr, ETH_ALEN ); + } + DBG_PRINT( "Setting multicast list\n" ); + hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + } else { + /* Disable promiscuous mode */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_PROMISCUOUS_MODE; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); + DBG_PRINT( "Disabling Promiscuous mode\n" ); + hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + + /* Disable multicast mode */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_GROUP_ADDR; + DBG_PRINT( "Disabling Multicast mode\n" ); + hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + + /* Turning on this filter will prevent all multicast frames from + being sent up from the device; however, this is a static RID, + so a call to wl_apply() is needed */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_RX_ALL_GROUP_ADDR; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 1 ); + DBG_PRINT( "Disabling all multicast mode (IFF_ALLMULTI)\n" ); + hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + wl_apply( lp ); + } + } + wl_act_int_on( lp ); + wl_unlock( lp, &flags ); + } + DBG_LEAVE( DbgInfo ); +#endif /* HCF_STA */ +} // wl_multicast +/*============================================================================*/ + +#else /* NEW_MULTICAST */ + +void wl_multicast( struct net_device *dev, int num_addrs, void *addrs ) +{ + DBG_FUNC( "wl_multicast"); + DBG_ENTER(DbgInfo); + + DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + DBG_PARAM( DbgInfo, "num_addrs", "%d", num_addrs ); + DBG_PARAM( DbgInfo, "addrs", "0x%p", addrs ); + +#error Obsolete set multicast interface! + + DBG_LEAVE( DbgInfo ); +} // wl_multicast +/*============================================================================*/ + +#endif /* NEW_MULTICAST */ + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)) +static const struct net_device_ops wl_netdev_ops = +{ + .ndo_start_xmit = &wl_tx_port0, + + .ndo_set_config = &wl_config, + .ndo_get_stats = &wl_stats, + .ndo_set_multicast_list = &wl_multicast, + + .ndo_init = &wl_insert, + .ndo_open = &wl_adapter_open, + .ndo_stop = &wl_adapter_close, + .ndo_do_ioctl = &wl_ioctl, + +#ifdef HAVE_TX_TIMEOUT + .ndo_tx_timeout = &wl_tx_timeout, +#endif + +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = wl_poll, +#endif +}; +#endif // (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)) + +/******************************************************************************* + * wl_device_alloc() + ******************************************************************************* + * + * DESCRIPTION: + * + * Create instances of net_device and wl_private for the new adapter + * and register the device's entry points in the net_device structure. + * + * PARAMETERS: + * + * N/A + * + * RETURNS: + * + * a pointer to an allocated and initialized net_device struct for this + * device. + * + ******************************************************************************/ +struct net_device * wl_device_alloc( void ) +{ + struct net_device *dev = NULL; + struct wl_private *lp = NULL; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_device_alloc" ); + DBG_ENTER( DbgInfo ); + + /* Alloc a net_device struct */ + dev = alloc_etherdev(sizeof(struct wl_private)); + if (!dev) + return NULL; + + /* Initialize the 'next' pointer in the struct. Currently only used for PCI, + but do it here just in case it's used for other buses in the future */ + lp = wl_priv(dev); + + + /* Check MTU */ + if( dev->mtu > MTU_MAX ) + { + DBG_WARNING( DbgInfo, "%s: MTU set too high, limiting to %d.\n", + dev->name, MTU_MAX ); + dev->mtu = MTU_MAX; + } + + /* Setup the function table in the device structure. */ + + dev->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def; + lp->wireless_data.spy_data = &lp->spy_data; + dev->wireless_data = &lp->wireless_data; + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)) + dev->netdev_ops = &wl_netdev_ops; +#else + dev->hard_start_xmit = &wl_tx_port0; + + dev->set_config = &wl_config; + dev->get_stats = &wl_stats; + dev->set_multicast_list = &wl_multicast; + + dev->init = &wl_insert; + dev->open = &wl_adapter_open; + dev->stop = &wl_adapter_close; + dev->do_ioctl = &wl_ioctl; + +#ifdef HAVE_TX_TIMEOUT + dev->tx_timeout = &wl_tx_timeout; +#endif + +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = wl_poll; +#endif + +#endif // (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)) + +#ifdef HAVE_TX_TIMEOUT + dev->watchdog_timeo = TX_TIMEOUT; +#endif + + dev->ethtool_ops = &wl_ethtool_ops; + + netif_stop_queue( dev ); + + /* Allocate virutal devices for WDS support if needed */ + WL_WDS_DEVICE_ALLOC( lp ); + + DBG_LEAVE( DbgInfo ); + return dev; +} // wl_device_alloc +/*============================================================================*/ + +/******************************************************************************* + * wl_device_dealloc() + ******************************************************************************* + * + * DESCRIPTION: + * + * Free instances of net_device and wl_private strcutres for an adapter + * and perform basic cleanup. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure. + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_device_dealloc( struct net_device *dev ) +{ +// struct wl_private *lp = wl_priv(dev); + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_device_dealloc" ); + DBG_ENTER( DbgInfo ); + + /* Dealloc the WDS ports */ + WL_WDS_DEVICE_DEALLOC( lp ); + + free_netdev( dev ); + + DBG_LEAVE( DbgInfo ); + return; +} // wl_device_dealloc +/*============================================================================*/ + +/******************************************************************************* + * wl_tx_port0() + ******************************************************************************* + * + * DESCRIPTION: + * + * The handler routine for Tx over HCF_PORT_0. + * + * PARAMETERS: + * + * skb - a pointer to the sk_buff to transmit. + * dev - a pointer to a net_device structure representing HCF_PORT_0. + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +int wl_tx_port0( struct sk_buff *skb, struct net_device *dev ) +{ + DBG_TX( DbgInfo, "Tx on Port 0\n" ); + + return wl_tx( skb, dev, HCF_PORT_0 ); +#ifdef ENABLE_DMA + return wl_tx_dma( skb, dev, HCF_PORT_0 ); +#endif +} // wl_tx_port0 +/*============================================================================*/ + +#ifdef USE_WDS + +/******************************************************************************* + * wl_tx_port1() + ******************************************************************************* + * + * DESCRIPTION: + * + * The handler routine for Tx over HCF_PORT_1. + * + * PARAMETERS: + * + * skb - a pointer to the sk_buff to transmit. + * dev - a pointer to a net_device structure representing HCF_PORT_1. + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +int wl_tx_port1( struct sk_buff *skb, struct net_device *dev ) +{ + DBG_TX( DbgInfo, "Tx on Port 1\n" ); + return wl_tx( skb, dev, HCF_PORT_1 ); +} // wl_tx_port1 +/*============================================================================*/ + +/******************************************************************************* + * wl_tx_port2() + ******************************************************************************* + * + * DESCRIPTION: + * + * The handler routine for Tx over HCF_PORT_2. + * + * PARAMETERS: + * + * skb - a pointer to the sk_buff to transmit. + * dev - a pointer to a net_device structure representing HCF_PORT_2. + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +int wl_tx_port2( struct sk_buff *skb, struct net_device *dev ) +{ + DBG_TX( DbgInfo, "Tx on Port 2\n" ); + return wl_tx( skb, dev, HCF_PORT_2 ); +} // wl_tx_port2 +/*============================================================================*/ + +/******************************************************************************* + * wl_tx_port3() + ******************************************************************************* + * + * DESCRIPTION: + * + * The handler routine for Tx over HCF_PORT_3. + * + * PARAMETERS: + * + * skb - a pointer to the sk_buff to transmit. + * dev - a pointer to a net_device structure representing HCF_PORT_3. + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +int wl_tx_port3( struct sk_buff *skb, struct net_device *dev ) +{ + DBG_TX( DbgInfo, "Tx on Port 3\n" ); + return wl_tx( skb, dev, HCF_PORT_3 ); +} // wl_tx_port3 +/*============================================================================*/ + +/******************************************************************************* + * wl_tx_port4() + ******************************************************************************* + * + * DESCRIPTION: + * + * The handler routine for Tx over HCF_PORT_4. + * + * PARAMETERS: + * + * skb - a pointer to the sk_buff to transmit. + * dev - a pointer to a net_device structure representing HCF_PORT_4. + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +int wl_tx_port4( struct sk_buff *skb, struct net_device *dev ) +{ + DBG_TX( DbgInfo, "Tx on Port 4\n" ); + return wl_tx( skb, dev, HCF_PORT_4 ); +} // wl_tx_port4 +/*============================================================================*/ + +/******************************************************************************* + * wl_tx_port5() + ******************************************************************************* + * + * DESCRIPTION: + * + * The handler routine for Tx over HCF_PORT_5. + * + * PARAMETERS: + * + * skb - a pointer to the sk_buff to transmit. + * dev - a pointer to a net_device structure representing HCF_PORT_5. + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +int wl_tx_port5( struct sk_buff *skb, struct net_device *dev ) +{ + DBG_TX( DbgInfo, "Tx on Port 5\n" ); + return wl_tx( skb, dev, HCF_PORT_5 ); +} // wl_tx_port5 +/*============================================================================*/ + +/******************************************************************************* + * wl_tx_port6() + ******************************************************************************* + * + * DESCRIPTION: + * + * The handler routine for Tx over HCF_PORT_6. + * + * PARAMETERS: + * + * skb - a pointer to the sk_buff to transmit. + * dev - a pointer to a net_device structure representing HCF_PORT_6. + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +int wl_tx_port6( struct sk_buff *skb, struct net_device *dev ) +{ + DBG_TX( DbgInfo, "Tx on Port 6\n" ); + return wl_tx( skb, dev, HCF_PORT_6 ); +} // wl_tx_port6 +/*============================================================================*/ + +/******************************************************************************* + * wl_wds_device_alloc() + ******************************************************************************* + * + * DESCRIPTION: + * + * Create instances of net_device to represent the WDS ports, and register + * the device's entry points in the net_device structure. + * + * PARAMETERS: + * + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A, but will place pointers to the allocated and initialized net_device + * structs in the private adapter structure. + * + ******************************************************************************/ +void wl_wds_device_alloc( struct wl_private *lp ) +{ + int count; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_wds_device_alloc" ); + DBG_ENTER( DbgInfo ); + + /* WDS support requires additional net_device structs to be allocated, + so that user space apps can use these virtual devices to specify the + port on which to Tx/Rx */ + for( count = 0; count < NUM_WDS_PORTS; count++ ) { + struct net_device *dev_wds = NULL; + + dev_wds = kmalloc( sizeof( struct net_device ), GFP_KERNEL ); + memset( dev_wds, 0, sizeof( struct net_device )); + + ether_setup( dev_wds ); + + lp->wds_port[count].dev = dev_wds; + + /* Re-use wl_init for all the devices, as it currently does nothing, but + is required. Re-use the stats/tx_timeout handler for all as well; the + WDS port which is requesting these operations can be determined by + the net_device pointer. Set the private member of all devices to point + to the same net_device struct; that way, all information gets + funnelled through the one "real" net_device. Name the WDS ports + "wds" */ + lp->wds_port[count].dev->init = &wl_init; + lp->wds_port[count].dev->get_stats = &wl_stats; + lp->wds_port[count].dev->tx_timeout = &wl_tx_timeout; + lp->wds_port[count].dev->watchdog_timeo = TX_TIMEOUT; + lp->wds_port[count].dev->priv = lp; + + sprintf( lp->wds_port[count].dev->name, "wds%d", count ); + } + + /* Register the Tx handlers */ + lp->wds_port[0].dev->hard_start_xmit = &wl_tx_port1; + lp->wds_port[1].dev->hard_start_xmit = &wl_tx_port2; + lp->wds_port[2].dev->hard_start_xmit = &wl_tx_port3; + lp->wds_port[3].dev->hard_start_xmit = &wl_tx_port4; + lp->wds_port[4].dev->hard_start_xmit = &wl_tx_port5; + lp->wds_port[5].dev->hard_start_xmit = &wl_tx_port6; + + WL_WDS_NETIF_STOP_QUEUE( lp ); + + DBG_LEAVE( DbgInfo ); + return; +} // wl_wds_device_alloc +/*============================================================================*/ + +/******************************************************************************* + * wl_wds_device_dealloc() + ******************************************************************************* + * + * DESCRIPTION: + * + * Free instances of net_device structures used to support WDS. + * + * PARAMETERS: + * + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wds_device_dealloc( struct wl_private *lp ) +{ + int count; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_wds_device_dealloc" ); + DBG_ENTER( DbgInfo ); + + for( count = 0; count < NUM_WDS_PORTS; count++ ) { + struct net_device *dev_wds = NULL; + + dev_wds = lp->wds_port[count].dev; + + if( dev_wds != NULL ) { + if( dev_wds->flags & IFF_UP ) { + dev_close( dev_wds ); + dev_wds->flags &= ~( IFF_UP | IFF_RUNNING ); + } + + kfree( dev_wds ); + lp->wds_port[count].dev = NULL; + } + } + + DBG_LEAVE( DbgInfo ); + return; +} // wl_wds_device_dealloc +/*============================================================================*/ + +/******************************************************************************* + * wl_wds_netif_start_queue() + ******************************************************************************* + * + * DESCRIPTION: + * + * Used to start the netif queues of all the "virtual" network devices + * which repesent the WDS ports. + * + * PARAMETERS: + * + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wds_netif_start_queue( struct wl_private *lp ) +{ + int count; + /*------------------------------------------------------------------------*/ + + if( lp != NULL ) { + for( count = 0; count < NUM_WDS_PORTS; count++ ) { + if( lp->wds_port[count].is_registered && + lp->wds_port[count].netif_queue_on == FALSE ) { + netif_start_queue( lp->wds_port[count].dev ); + lp->wds_port[count].netif_queue_on = TRUE; + } + } + } + + return; +} // wl_wds_netif_start_queue +/*============================================================================*/ + +/******************************************************************************* + * wl_wds_netif_stop_queue() + ******************************************************************************* + * + * DESCRIPTION: + * + * Used to stop the netif queues of all the "virtual" network devices + * which repesent the WDS ports. + * + * PARAMETERS: + * + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wds_netif_stop_queue( struct wl_private *lp ) +{ + int count; + /*------------------------------------------------------------------------*/ + + if( lp != NULL ) { + for( count = 0; count < NUM_WDS_PORTS; count++ ) { + if( lp->wds_port[count].is_registered && + lp->wds_port[count].netif_queue_on == TRUE ) { + netif_stop_queue( lp->wds_port[count].dev ); + lp->wds_port[count].netif_queue_on = FALSE; + } + } + } + + return; +} // wl_wds_netif_stop_queue +/*============================================================================*/ + +/******************************************************************************* + * wl_wds_netif_wake_queue() + ******************************************************************************* + * + * DESCRIPTION: + * + * Used to wake the netif queues of all the "virtual" network devices + * which repesent the WDS ports. + * + * PARAMETERS: + * + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wds_netif_wake_queue( struct wl_private *lp ) +{ + int count; + /*------------------------------------------------------------------------*/ + + if( lp != NULL ) { + for( count = 0; count < NUM_WDS_PORTS; count++ ) { + if( lp->wds_port[count].is_registered && + lp->wds_port[count].netif_queue_on == FALSE ) { + netif_wake_queue( lp->wds_port[count].dev ); + lp->wds_port[count].netif_queue_on = TRUE; + } + } + } + + return; +} // wl_wds_netif_wake_queue +/*============================================================================*/ + +/******************************************************************************* + * wl_wds_netif_carrier_on() + ******************************************************************************* + * + * DESCRIPTION: + * + * Used to signal the network layer that carrier is present on all of the + * "virtual" network devices which repesent the WDS ports. + * + * PARAMETERS: + * + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wds_netif_carrier_on( struct wl_private *lp ) +{ + int count; + /*------------------------------------------------------------------------*/ + + if( lp != NULL ) { + for( count = 0; count < NUM_WDS_PORTS; count++ ) { + if( lp->wds_port[count].is_registered ) { + netif_carrier_on( lp->wds_port[count].dev ); + } + } + } + + return; +} // wl_wds_netif_carrier_on +/*============================================================================*/ + +/******************************************************************************* + * wl_wds_netif_carrier_off() + ******************************************************************************* + * + * DESCRIPTION: + * + * Used to signal the network layer that carrier is NOT present on all of + * the "virtual" network devices which repesent the WDS ports. + * + * PARAMETERS: + * + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wds_netif_carrier_off( struct wl_private *lp ) +{ + int count; + /*------------------------------------------------------------------------*/ + + if( lp != NULL ) { + for( count = 0; count < NUM_WDS_PORTS; count++ ) { + if( lp->wds_port[count].is_registered ) { + netif_carrier_off( lp->wds_port[count].dev ); + } + } + } + + return; +} // wl_wds_netif_carrier_off +/*============================================================================*/ + +#endif /* USE_WDS */ + +#ifdef ENABLE_DMA +/******************************************************************************* + * wl_send_dma() + ******************************************************************************* + * + * DESCRIPTION: + * + * The routine which performs data transmits when using busmaster DMA. + * + * PARAMETERS: + * + * lp - a pointer to the device's wl_private struct. + * skb - a pointer to the network layer's data buffer. + * port - the Hermes port on which to transmit. + * + * RETURNS: + * + * 0 on success + * 1 on error + * + ******************************************************************************/ +int wl_send_dma( struct wl_private *lp, struct sk_buff *skb, int port ) +{ + int len; + DESC_STRCT *desc = NULL; + DESC_STRCT *desc_next = NULL; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_send_dma" ); + + if( lp == NULL ) + { + DBG_ERROR( DbgInfo, "Private adapter struct is NULL\n" ); + return FALSE; + } + + if( lp->dev == NULL ) + { + DBG_ERROR( DbgInfo, "net_device struct in wl_private is NULL\n" ); + return FALSE; + } + + /* AGAIN, ALL THE QUEUEING DONE HERE IN I/O MODE IS NOT PERFORMED */ + + if( skb == NULL ) + { + DBG_WARNING (DbgInfo, "Nothing to send.\n"); + return FALSE; + } + + len = skb->len; + + /* Get a free descriptor */ + desc = wl_pci_dma_get_tx_packet( lp ); + + if( desc == NULL ) + { + if( lp->netif_queue_on == TRUE ) { + netif_stop_queue( lp->dev ); + WL_WDS_NETIF_STOP_QUEUE( lp ); + lp->netif_queue_on = FALSE; + + dev_kfree_skb( skb ); + return 0; + } + } + + SET_BUF_CNT( desc, /*HCF_DMA_FD_CNT*/HFS_ADDR_DEST ); + SET_BUF_SIZE( desc, HCF_DMA_TX_BUF1_SIZE ); + + desc_next = desc->next_desc_addr; + + if( desc_next->buf_addr == NULL ) + { + DBG_ERROR( DbgInfo, "DMA descriptor buf_addr is NULL\n" ); + return FALSE; + } + + /* Copy the payload into the DMA packet */ + memcpy( desc_next->buf_addr, skb->data, len ); + + SET_BUF_CNT( desc_next, len ); + SET_BUF_SIZE( desc_next, HCF_MAX_PACKET_SIZE ); + + hcf_dma_tx_put( &( lp->hcfCtx ), desc, 0 ); + + /* Free the skb and perform queue cleanup, as the buffer was + transmitted successfully */ + dev_kfree_skb( skb ); + + return TRUE; +} // wl_send_dma +/*============================================================================*/ + +/******************************************************************************* + * wl_rx_dma() + ******************************************************************************* + * + * DESCRIPTION: + * + * The routine which performs data reception when using busmaster DMA. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure. + * + * RETURNS: + * + * 0 on success + * 1 on error + * + ******************************************************************************/ +int wl_rx_dma( struct net_device *dev ) +{ + int port; + hcf_16 pktlen; + hcf_16 hfs_stat; + struct sk_buff *skb; + struct wl_private *lp = NULL; + DESC_STRCT *desc, *desc_next; + //CFG_MB_INFO_RANGE2_STRCT x; + /*------------------------------------------------------------------------*/ + + DBG_FUNC("wl_rx") + DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); + + if((( lp = (struct wl_private *)dev->priv ) != NULL ) && + !( lp->flags & WVLAN2_UIL_BUSY )) { + +#ifdef USE_RTS + if( lp->useRTS == 1 ) { + DBG_PRINT( "RTS: We're getting an Rx...\n" ); + return -EIO; + } +#endif /* USE_RTS */ + + //if( lp->dma.status == 0 ) + //{ + desc = hcf_dma_rx_get( &( lp->hcfCtx )); + + if( desc != NULL ) + { + /* Check and see if we rcvd. a WMP frame */ + /* + if((( *(hcf_8 *)&desc->buf_addr[HFS_STAT] ) & + ( HFS_STAT_MSG_TYPE | HFS_STAT_ERR )) == HFS_STAT_WMP_MSG ) + { + DBG_TRACE( DbgInfo, "Got a WMP frame\n" ); + + x.len = sizeof( CFG_MB_INFO_RANGE2_STRCT ) / sizeof( hcf_16 ); + x.typ = CFG_MB_INFO; + x.base_typ = CFG_WMP; + x.frag_cnt = 2; + x.frag_buf[0].frag_len = GET_BUF_CNT( descp ) / sizeof( hcf_16 ); + x.frag_buf[0].frag_addr = (hcf_8 *) descp->buf_addr ; + x.frag_buf[1].frag_len = ( GET_BUF_CNT( descp->next_desc_addr ) + 1 ) / sizeof( hcf_16 ); + x.frag_buf[1].frag_addr = (hcf_8 *) descp->next_desc_addr->buf_addr ; + + hcf_put_info( &( lp->hcfCtx ), (LTVP)&x ); + } + */ + + desc_next = desc->next_desc_addr; + + /* Make sure the buffer isn't empty */ + if( GET_BUF_CNT( desc ) == 0 ) { + DBG_WARNING( DbgInfo, "Buffer is empty!\n" ); + + /* Give the descriptor back to the HCF */ + hcf_dma_rx_put( &( lp->hcfCtx ), desc ); + return -EIO; + } + + /* Read the HFS_STAT register from the lookahead buffer */ + hfs_stat = (hcf_16)( desc->buf_addr[HFS_STAT/2] ); + + /* Make sure the frame isn't bad */ + if(( hfs_stat & HFS_STAT_ERR ) != HCF_SUCCESS ) + { + DBG_WARNING( DbgInfo, "HFS_STAT_ERROR (0x%x) in Rx Packet\n", + desc->buf_addr[HFS_STAT/2] ); + + /* Give the descriptor back to the HCF */ + hcf_dma_rx_put( &( lp->hcfCtx ), desc ); + return -EIO; + } + + /* Determine what port this packet is for */ + port = ( hfs_stat >> 8 ) & 0x0007; + DBG_RX( DbgInfo, "Rx frame for port %d\n", port ); + + if(( pktlen = GET_BUF_CNT( desc_next )) != 0 ) { + if(( skb = ALLOC_SKB( pktlen )) != NULL ) { + switch( port ) { +#ifdef USE_WDS + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + skb->dev = lp->wds_port[port-1].dev; + break; +#endif /* USE_WDS */ + + case 0: + default: + skb->dev = dev; + break; + } + + GET_PACKET_DMA( skb->dev, skb, pktlen ); + + /* Give the descriptor back to the HCF */ + hcf_dma_rx_put( &( lp->hcfCtx ), desc ); + + netif_rx( skb ); + + if( port == 0 ) { + lp->stats.rx_packets++; + lp->stats.rx_bytes += pktlen; + } +#ifdef USE_WDS + else + { + lp->wds_port[port-1].stats.rx_packets++; + lp->wds_port[port-1].stats.rx_bytes += pktlen; + } +#endif /* USE_WDS */ + + dev->last_rx = jiffies; + + } else { + DBG_ERROR( DbgInfo, "Could not alloc skb\n" ); + + if( port == 0 ) + { + lp->stats.rx_dropped++; + } +#ifdef USE_WDS + else + { + lp->wds_port[port-1].stats.rx_dropped++; + } +#endif /* USE_WDS */ + } + } + } + //} + } + + return 0; +} // wl_rx_dma +/*============================================================================*/ +#endif // ENABLE_DMA diff --git a/drivers/staging/wlags49_h2/wl_netdev.h b/drivers/staging/wlags49_h2/wl_netdev.h new file mode 100644 index 0000000000000000000000000000000000000000..632ab2e6302c31a8375cd36ca0080c7a6467e31d --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_netdev.h @@ -0,0 +1,154 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * Header describing information required by the network layerentry points + * into the driver. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +#ifndef __WL_NETDEV_H__ +#define __WL_NETDEV_H__ + + + + +/******************************************************************************* + * function prototypes + ******************************************************************************/ +int wl_init( struct net_device *dev ); + +int wl_config( struct net_device *dev, struct ifmap *map ); + +struct net_device *wl_device_alloc( void ); + +void wl_device_dealloc( struct net_device *dev ); + +int wl_open( struct net_device *dev ); + +int wl_close( struct net_device *dev ); + +int wl_ioctl( struct net_device *dev, struct ifreq *rq, int cmd ); + +int wl_tx( struct sk_buff *skb, struct net_device *dev, int port ); + +int wl_send( struct wl_private *lp ); + +int wl_rx( struct net_device *dev ); + +void wl_tx_timeout( struct net_device *dev ); + +struct net_device_stats *wl_stats( struct net_device *dev ); + + +#ifdef ENABLE_DMA +int wl_send_dma( struct wl_private *lp, struct sk_buff *skb, int port ); +int wl_rx_dma( struct net_device *dev ); +#endif + +#ifdef NEW_MULTICAST +void wl_multicast( struct net_device *dev ); +#else +void wl_multicast( struct net_device *dev, int num_addrs, void *addrs ); +#endif // NEW_MULTICAST + + +int wl_tx_port0( struct sk_buff *skb, struct net_device *dev ); + + +#ifdef USE_WDS + +int wl_tx_port1( struct sk_buff *skb, struct net_device *dev ); +int wl_tx_port2( struct sk_buff *skb, struct net_device *dev ); +int wl_tx_port3( struct sk_buff *skb, struct net_device *dev ); +int wl_tx_port4( struct sk_buff *skb, struct net_device *dev ); +int wl_tx_port5( struct sk_buff *skb, struct net_device *dev ); +int wl_tx_port6( struct sk_buff *skb, struct net_device *dev ); + +void wl_wds_device_alloc( struct wl_private *lp ); +void wl_wds_device_dealloc( struct wl_private *lp ); +void wl_wds_netif_start_queue( struct wl_private *lp ); +void wl_wds_netif_stop_queue( struct wl_private *lp ); +void wl_wds_netif_wake_queue( struct wl_private *lp ); +void wl_wds_netif_carrier_on( struct wl_private *lp ); +void wl_wds_netif_carrier_off( struct wl_private *lp ); + +#endif /* USE_WDS */ + + +#ifdef USE_WDS + +#define WL_WDS_DEVICE_ALLOC( ARG ) wl_wds_device_alloc( ARG ) +#define WL_WDS_DEVICE_DEALLOC( ARG ) wl_wds_device_dealloc( ARG ) +#define WL_WDS_NETIF_START_QUEUE( ARG ) wl_wds_netif_start_queue( ARG ) +#define WL_WDS_NETIF_STOP_QUEUE( ARG ) wl_wds_netif_stop_queue( ARG ) +#define WL_WDS_NETIF_WAKE_QUEUE( ARG ) wl_wds_netif_wake_queue( ARG ) +#define WL_WDS_NETIF_CARRIER_ON( ARG ) wl_wds_netif_carrier_on( ARG ) +#define WL_WDS_NETIF_CARRIER_OFF( ARG ) wl_wds_netif_carrier_off( ARG ) + +#else + +#define WL_WDS_DEVICE_ALLOC( ARG ) +#define WL_WDS_DEVICE_DEALLOC( ARG ) +#define WL_WDS_NETIF_START_QUEUE( ARG ) +#define WL_WDS_NETIF_STOP_QUEUE( ARG ) +#define WL_WDS_NETIF_WAKE_QUEUE( ARG ) +#define WL_WDS_NETIF_CARRIER_ON( ARG ) +#define WL_WDS_NETIF_CARRIER_OFF( ARG ) + +#endif /* USE_WDS */ + + +#endif // __WL_NETDEV_H__ diff --git a/drivers/staging/wlags49_h2/wl_pci.c b/drivers/staging/wlags49_h2/wl_pci.c new file mode 100644 index 0000000000000000000000000000000000000000..a3db111d4a95b77425a4f02dd91ad2d9f7dff604 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_pci.c @@ -0,0 +1,1581 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * This file contains processing and initialization specific to PCI/miniPCI + * devices. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +/******************************************************************************* + * include 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 +#include +#include +#include +#include +#include + + +/******************************************************************************* + * global variables + ******************************************************************************/ +#if DBG +extern dbg_info_t *DbgInfo; +#endif // DBG + +/* define the PCI device Table Cardname and id tables */ +enum hermes_pci_versions { + CH_Agere_Systems_Mini_PCI_V1 = 0, +}; + +static struct pci_device_id wl_pci_tbl[] __devinitdata = { + { WL_LKM_PCI_VENDOR_ID, WL_LKM_PCI_DEVICE_ID_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Agere_Systems_Mini_PCI_V1 }, + { WL_LKM_PCI_VENDOR_ID, WL_LKM_PCI_DEVICE_ID_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Agere_Systems_Mini_PCI_V1 }, + { WL_LKM_PCI_VENDOR_ID, WL_LKM_PCI_DEVICE_ID_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Agere_Systems_Mini_PCI_V1 }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(pci, wl_pci_tbl); + +/******************************************************************************* + * function prototypes + ******************************************************************************/ +int __devinit wl_pci_probe( struct pci_dev *pdev, + const struct pci_device_id *ent ); +void __devexit wl_pci_remove(struct pci_dev *pdev); +int wl_pci_setup( struct pci_dev *pdev ); +void wl_pci_enable_cardbus_interrupts( struct pci_dev *pdev ); + +#ifdef ENABLE_DMA +int wl_pci_dma_alloc( struct pci_dev *pdev, struct wl_private *lp ); +int wl_pci_dma_free( struct pci_dev *pdev, struct wl_private *lp ); +int wl_pci_dma_alloc_tx_packet( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc ); +int wl_pci_dma_free_tx_packet( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc ); +int wl_pci_dma_alloc_rx_packet( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc ); +int wl_pci_dma_free_rx_packet( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc ); +int wl_pci_dma_alloc_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc, int size ); +int wl_pci_dma_free_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc ); +int wl_pci_dma_alloc_desc( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc ); +int wl_pci_dma_free_desc( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc ); +int wl_pci_dma_alloc_buf( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT *desc, int size ); +int wl_pci_dma_free_buf( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT *desc ); + +void wl_pci_dma_hcf_reclaim_rx( struct wl_private *lp ); +#endif // ENABLE_DMA + +/******************************************************************************* + * PCI module function registration + ******************************************************************************/ +static struct pci_driver wl_driver = +{ + name: MODULE_NAME, + id_table: wl_pci_tbl, + probe: wl_pci_probe, + remove: __devexit_p(wl_pci_remove), + suspend: NULL, + resume: NULL, +}; + +/******************************************************************************* + * wl_adapter_init_module() + ******************************************************************************* + * + * DESCRIPTION: + * + * Called by init_module() to perform PCI-specific driver initialization. + * + * PARAMETERS: + * + * N/A + * + * RETURNS: + * + * 0 + * + ******************************************************************************/ +int wl_adapter_init_module( void ) +{ + int result; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_adapter_init_module()" ); + DBG_ENTER( DbgInfo ); + DBG_TRACE( DbgInfo, "wl_adapter_init_module() -- PCI\n" ); + + result = pci_register_driver( &wl_driver ); //;?replace with pci_module_init, Rubini pg 490 + //;? why not do something with the result + + DBG_LEAVE( DbgInfo ); + return 0; +} // wl_adapter_init_module +/*============================================================================*/ + +/******************************************************************************* + * wl_adapter_cleanup_module() + ******************************************************************************* + * + * DESCRIPTION: + * + * Called by cleanup_module() to perform PCI-specific driver cleanup. + * + * PARAMETERS: + * + * N/A + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_adapter_cleanup_module( void ) +{ + //;?how comes wl_adapter_cleanup_module is located in a seemingly pci specific module + DBG_FUNC( "wl_adapter_cleanup_module" ); + DBG_ENTER( DbgInfo ); + + //;?DBG_TRACE below feels like nearly redundant in the light of DBG_ENTER above + DBG_TRACE( DbgInfo, "wl_adapter_cleanup_module() -- PCI\n" ); + + pci_unregister_driver( &wl_driver ); + + DBG_LEAVE( DbgInfo ); + return; +} // wl_adapter_cleanup_module +/*============================================================================*/ + +/******************************************************************************* + * wl_adapter_insert() + ******************************************************************************* + * + * DESCRIPTION: + * + * Called by wl_pci_probe() to continue the process of device insertion. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure + * + * RETURNS: + * + * TRUE or FALSE + * + ******************************************************************************/ +int wl_adapter_insert( struct net_device *dev ) +{ + int result = FALSE; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_adapter_insert" ); + DBG_ENTER( DbgInfo ); + + DBG_TRACE( DbgInfo, "wl_adapter_insert() -- PCI\n" ); + + if( dev == NULL ) { + DBG_ERROR( DbgInfo, "net_device pointer is NULL!!!\n" ); + } else if( dev->priv == NULL ) { + DBG_ERROR( DbgInfo, "wl_private pointer is NULL!!!\n" ); + } else if( wl_insert( dev ) ) { /* Perform remaining device initialization */ + result = TRUE; + } else { + DBG_TRACE( DbgInfo, "wl_insert() FAILED\n" ); + } + DBG_LEAVE( DbgInfo ); + return result; +} // wl_adapter_insert +/*============================================================================*/ + +/******************************************************************************* + * wl_adapter_open() + ******************************************************************************* + * + * DESCRIPTION: + * + * Open the device. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure + * + * RETURNS: + * + * an HCF status code + * + ******************************************************************************/ +int wl_adapter_open( struct net_device *dev ) +{ + int result = 0; + int hcf_status = HCF_SUCCESS; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_adapter_open" ); + DBG_ENTER( DbgInfo ); + + DBG_TRACE( DbgInfo, "wl_adapter_open() -- PCI\n" ); + + hcf_status = wl_open( dev ); + + if( hcf_status != HCF_SUCCESS ) { + result = -ENODEV; + } + + DBG_LEAVE( DbgInfo ); + return result; +} // wl_adapter_open +/*============================================================================*/ + +/******************************************************************************* + * wl_adapter_close() + ******************************************************************************* + * + * DESCRIPTION: + * + * Close the device + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure + * + * RETURNS: + * + * 0 + * + ******************************************************************************/ +int wl_adapter_close( struct net_device *dev ) +{ + DBG_FUNC( "wl_adapter_close" ); + DBG_ENTER( DbgInfo ); + + DBG_TRACE( DbgInfo, "wl_adapter_close() -- PCI\n" ); + DBG_TRACE( DbgInfo, "%s: Shutting down adapter.\n", dev->name ); + + wl_close( dev ); + + DBG_LEAVE( DbgInfo ); + return 0; +} // wl_adapter_close +/*============================================================================*/ + +/******************************************************************************* + * wl_adapter_is_open() + ******************************************************************************* + * + * DESCRIPTION: + * + * Check whether this device is open. Returns + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure + * + * RETURNS: + * + * nonzero if device is open. + * + ******************************************************************************/ +int wl_adapter_is_open( struct net_device *dev ) +{ + /* This function is used in PCMCIA to check the status of the 'open' field + in the dev_link_t structure associated with a network device. There + doesn't seem to be an analog to this for PCI, and checking the status + contained in the net_device structure doesn't have the same effect. + For now, return TRUE, but find out if this is necessary for PCI. */ + + return TRUE; +} // wl_adapter_is_open +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_probe() + ******************************************************************************* + * + * DESCRIPTION: + * + * Registered in the pci_driver structure, this function is called when the + * PCI subsystem finds a new PCI device which matches the infomation contained + * in the pci_device_id table. + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * ent - this device's entry in the pci_device_id table + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int __devinit wl_pci_probe( struct pci_dev *pdev, + const struct pci_device_id *ent ) +{ + int result; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_pci_probe" ); + DBG_ENTER( DbgInfo ); + DBG_PRINT( "%s\n", VERSION_INFO ); + + result = wl_pci_setup( pdev ); + + DBG_LEAVE( DbgInfo ); + + return result; +} // wl_pci_probe +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_remove() + ******************************************************************************* + * + * DESCRIPTION: + * + * Registered in the pci_driver structure, this function is called when the + * PCI subsystem detects that a PCI device which matches the infomation + * contained in the pci_device_id table has been removed. + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void __devexit wl_pci_remove(struct pci_dev *pdev) +{ + struct net_device *dev = NULL; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_pci_remove" ); + DBG_ENTER( DbgInfo ); + + /* Make sure the pci_dev pointer passed in is valid */ + if( pdev == NULL ) { + DBG_ERROR( DbgInfo, "PCI subsys passed in an invalid pci_dev pointer\n" ); + return; + } + + dev = (struct net_device *)pci_get_drvdata( pdev ); + if( dev == NULL ) { + DBG_ERROR( DbgInfo, "Could not retrieve net_device structure\n" ); + return; + } + + /* Perform device cleanup */ + wl_remove( dev ); + free_irq( dev->irq, dev ); + +#ifdef ENABLE_DMA + wl_pci_dma_free( pdev, (struct wl_private *)dev->priv ); +#endif + + wl_device_dealloc( dev ); + + DBG_LEAVE( DbgInfo ); + return; +} // wl_pci_remove +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_setup() + ******************************************************************************* + * + * DESCRIPTION: + * + * Called by wl_pci_probe() to begin a device's initialization process. + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_pci_setup( struct pci_dev *pdev ) +{ + int result = 0; + struct net_device *dev = NULL; + struct wl_private *lp = NULL; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_pci_setup" ); + DBG_ENTER( DbgInfo ); + + /* Make sure the pci_dev pointer passed in is valid */ + if( pdev == NULL ) { + DBG_ERROR( DbgInfo, "PCI subsys passed in an invalid pci_dev pointer\n" ); + return -ENODEV; + } + + result = pci_enable_device( pdev ); + if( result != 0 ) { + DBG_ERROR( DbgInfo, "pci_enable_device() failed\n" ); + DBG_LEAVE( DbgInfo ); + return result; + } + + /* We found our device! Let's register it with the system */ + DBG_TRACE( DbgInfo, "Found our device, now registering\n" ); + dev = wl_device_alloc( ); + if( dev == NULL ) { + DBG_ERROR( DbgInfo, "Could not register device!!!\n" ); + DBG_LEAVE( DbgInfo ); + return -ENOMEM; + } + + /* Make sure that space was allocated for our private adapter struct */ + if( dev->priv == NULL ) { + DBG_ERROR( DbgInfo, "Private adapter struct was not allocated!!!\n" ); + DBG_LEAVE( DbgInfo ); + return -ENOMEM; + } + +#ifdef ENABLE_DMA + /* Allocate DMA Descriptors */ + if( wl_pci_dma_alloc( pdev, (struct wl_private *)dev->priv ) < 0 ) { + DBG_ERROR( DbgInfo, "Could not allocate DMA descriptor memory!!!\n" ); + DBG_LEAVE( DbgInfo ); + return -ENOMEM; + } +#endif + + /* Register our private adapter structure with PCI */ + pci_set_drvdata( pdev, dev ); + + /* Fill out bus specific information in the net_device struct */ + dev->irq = pdev->irq; + SET_MODULE_OWNER( dev ); + + DBG_TRACE( DbgInfo, "Device Base Address: %#03lx\n", pdev->resource[0].start ); + dev->base_addr = pdev->resource[0].start; + + /* Initialize our device here */ + if( !wl_adapter_insert( dev )) { + DBG_ERROR( DbgInfo, "wl_adapter_insert() FAILED!!!\n" ); + wl_device_dealloc( dev ); + DBG_LEAVE( DbgInfo ); + return -EINVAL; + } + + /* Register our ISR */ + DBG_TRACE( DbgInfo, "Registering ISR...\n" ); + + result = request_irq(dev->irq, wl_isr, SA_SHIRQ, dev->name, dev); + if( result ) { + DBG_WARNING( DbgInfo, "Could not register ISR!!!\n" ); + DBG_LEAVE( DbgInfo ); + return result; + } + + /* Make sure interrupts are enabled properly for CardBus */ + lp = (struct wl_private *)dev->priv; + + if( lp->hcfCtx.IFB_BusType == CFG_NIC_BUS_TYPE_CARDBUS || + lp->hcfCtx.IFB_BusType == CFG_NIC_BUS_TYPE_PCI ) { + DBG_TRACE( DbgInfo, "This is a PCI/CardBus card, enable interrupts\n" ); + wl_pci_enable_cardbus_interrupts( pdev ); + } + + /* Enable bus mastering */ + pci_set_master( pdev ); + + DBG_LEAVE( DbgInfo ); + return 0; +} // wl_pci_setup +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_enable_cardbus_interrupts() + ******************************************************************************* + * + * DESCRIPTION: + * + * Called by wl_pci_setup() to enable interrupts on a CardBus device. This + * is done by writing bit 15 to the function event mask register. This + * CardBus-specific register is located in BAR2 (counting from BAR0), in memory + * space at byte offset 1f4 (7f4 for WARP). + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_pci_enable_cardbus_interrupts( struct pci_dev *pdev ) +{ + u32 bar2_reg; + u32 mem_addr_bus; + u32 func_evt_mask_reg; + void *mem_addr_kern = NULL; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_pci_enable_cardbus_interrupts" ); + DBG_ENTER( DbgInfo ); + + /* Initialize to known bad values */ + bar2_reg = 0xdeadbeef; + mem_addr_bus = 0xdeadbeef; + + /* Read the BAR2 register; this register contains the base address of the + memory region where the function event mask register lives */ + pci_read_config_dword( pdev, PCI_BASE_ADDRESS_2, &bar2_reg ); + mem_addr_bus = bar2_reg & PCI_BASE_ADDRESS_MEM_MASK; + + /* Once the base address is obtained, remap the memory region to kernel + space so we can retrieve the register */ + mem_addr_kern = ioremap( mem_addr_bus, 0x200 ); + +#ifdef HERMES25 +#define REG_OFFSET 0x07F4 +#else +#define REG_OFFSET 0x01F4 +#endif // HERMES25 + +#define BIT15 0x8000 + + /* Retrieve the functional event mask register, enable interrupts by + setting Bit 15, and write back the value */ + func_evt_mask_reg = *(u32 *)( mem_addr_kern + REG_OFFSET ); + func_evt_mask_reg |= BIT15; + *(u32 *)( mem_addr_kern + REG_OFFSET ) = func_evt_mask_reg; + + /* Once complete, unmap the region and exit */ + iounmap( mem_addr_kern ); + + DBG_LEAVE( DbgInfo ); + return; +} // wl_pci_enable_cardbus_interrupts +/*============================================================================*/ + +#ifdef ENABLE_DMA +/******************************************************************************* + * wl_pci_dma_alloc() + ******************************************************************************* + * + * DESCRIPTION: + * + * Allocates all resources needed for PCI/CardBus DMA operation + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_pci_dma_alloc( struct pci_dev *pdev, struct wl_private *lp ) +{ + int i; + int status = 0; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_pci_dma_alloc" ); + DBG_ENTER( DbgInfo ); + +// lp->dma.tx_rsc_ind = lp->dma.rx_rsc_ind = 0; +// +// /* Alloc for the Tx chain and its reclaim descriptor */ +// for( i = 0; i < NUM_TX_DESC; i++ ) { +// status = wl_pci_dma_alloc_tx_packet( pdev, lp, &lp->dma.tx_packet[i] ); +// if( status == 0 ) { +// DBG_PRINT( "lp->dma.tx_packet[%d] : 0x%p\n", i, lp->dma.tx_packet[i] ); +// DBG_PRINT( "lp->dma.tx_packet[%d]->next_desc_addr : 0x%p\n", i, lp->dma.tx_packet[i]->next_desc_addr ); +// lp->dma.tx_rsc_ind++; +// } else { +// DBG_ERROR( DbgInfo, "Could not alloc DMA Tx Packet\n" ); +// break; +// } +// } +// if( status == 0 ) { +// status = wl_pci_dma_alloc_desc( pdev, lp, &lp->dma.tx_reclaim_desc ); +// DBG_PRINT( "lp->dma.tx_reclaim_desc: 0x%p\n", lp->dma.tx_reclaim_desc ); +// } +// /* Alloc for the Rx chain and its reclaim descriptor */ +// if( status == 0 ) { +// for( i = 0; i < NUM_RX_DESC; i++ ) { +// status = wl_pci_dma_alloc_rx_packet( pdev, lp, &lp->dma.rx_packet[i] ); +// if( status == 0 ) { +// DBG_PRINT( "lp->dma.rx_packet[%d] : 0x%p\n", i, lp->dma.rx_packet[i] ); +// DBG_PRINT( "lp->dma.rx_packet[%d]->next_desc_addr : 0x%p\n", i, lp->dma.rx_packet[i]->next_desc_addr ); +// lp->dma.rx_rsc_ind++; +// } else { +// DBG_ERROR( DbgInfo, "Could not alloc DMA Rx Packet\n" ); +// break; +// } +// } +// } +// if( status == 0 ) { +// status = wl_pci_dma_alloc_desc( pdev, lp, &lp->dma.rx_reclaim_desc ); +// DBG_PRINT( "lp->dma.rx_reclaim_desc: 0x%p\n", lp->dma.rx_reclaim_desc ); +// } +// /* Store status, as host should not call HCF functions if this fails */ +// lp->dma.status = status; //;?all useages of dma.status have been commented out +// DBG_LEAVE( DbgInfo ); + return status; +} // wl_pci_dma_alloc +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_free() + ******************************************************************************* + * + * DESCRIPTION: + * + * Deallocated all resources needed for PCI/CardBus DMA operation + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_pci_dma_free( struct pci_dev *pdev, struct wl_private *lp ) +{ + int i; + int status = 0; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_pci_dma_free" ); + DBG_ENTER( DbgInfo ); + + /* Reclaim all Rx packets that were handed over to the HCF */ + /* Do I need to do this? Before this free is called, I've already disabled + the port which will call wl_pci_dma_hcf_reclaim */ + //if( lp->dma.status == 0 ) + //{ + // wl_pci_dma_hcf_reclaim( lp ); + //} + + /* Free everything needed for DMA Rx */ + for( i = 0; i < NUM_RX_DESC; i++ ) { + if( lp->dma.rx_packet[i] ) { + status = wl_pci_dma_free_rx_packet( pdev, lp, &lp->dma.rx_packet[i] ); + if( status != 0 ) { + DBG_WARNING( DbgInfo, "Problem freeing Rx packet\n" ); + } + } + } + lp->dma.rx_rsc_ind = 0; + + if( lp->dma.rx_reclaim_desc ) { + status = wl_pci_dma_free_desc( pdev, lp, &lp->dma.rx_reclaim_desc ); + if( status != 0 ) { + DBG_WARNING( DbgInfo, "Problem freeing Rx reclaim descriptor\n" ); + } + } + + /* Free everything needed for DMA Tx */ + for( i = 0; i < NUM_TX_DESC; i++ ) { + if( lp->dma.tx_packet[i] ) { + status = wl_pci_dma_free_tx_packet( pdev, lp, &lp->dma.tx_packet[i] ); + if( status != 0 ) { + DBG_WARNING( DbgInfo, "Problem freeing Tx packet\n" ); + } + } + } + lp->dma.tx_rsc_ind = 0; + + if( lp->dma.tx_reclaim_desc ) { + status = wl_pci_dma_free_desc( pdev, lp, &lp->dma.tx_reclaim_desc ); + if( status != 0 ) { + DBG_WARNING( DbgInfo, "Problem freeing Tx reclaim descriptor\n" ); + } + } + + DBG_LEAVE( DbgInfo ); + return status; +} // wl_pci_dma_free + +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_alloc_tx_packet() + ******************************************************************************* + * + * DESCRIPTION: + * + * Allocates a single Tx packet, consisting of several descriptors and + * buffers. Data to transmit is first copied into the 'payload' buffer + * before being transmitted. + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * lp - the device's private adapter structure + * desc - a pointer which will reference the descriptor to be alloc'd. + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_pci_dma_alloc_tx_packet( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc ) +{ +// int status = 0; +// /*------------------------------------------------------------------------*/ +// +// if( desc == NULL ) { +// status = -EFAULT; +// } +// if( status == 0 ) { +// status = wl_pci_dma_alloc_desc_and_buf( pdev, lp, desc, +// HCF_DMA_TX_BUF1_SIZE ); +// +// if( status == 0 ) { +// status = wl_pci_dma_alloc_desc_and_buf( pdev, lp, +// &( (*desc)->next_desc_addr ), +// HCF_MAX_PACKET_SIZE ); +// } +// } +// if( status == 0 ) { +// (*desc)->next_desc_phys_addr = (*desc)->next_desc_addr->desc_phys_addr; +// } +// return status; +} // wl_pci_dma_alloc_tx_packet +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_free_tx_packet() + ******************************************************************************* + * + * DESCRIPTION: + * + * Frees a single Tx packet, described in the corresponding alloc function. + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * lp - the device's private adapter structure + * desc - a pointer which will reference the descriptor to be alloc'd. + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_pci_dma_free_tx_packet( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc ) +{ + int status = 0; + /*------------------------------------------------------------------------*/ + + if( *desc == NULL ) { + DBG_PRINT( "Null descriptor\n" ); + status = -EFAULT; + } + //;?the "limited" NDIS strategy, assuming a frame consists ALWAYS out of 2 + //descriptors, make this robust + if( status == 0 && (*desc)->next_desc_addr ) { + status = wl_pci_dma_free_desc_and_buf( pdev, lp, &(*desc)->next_desc_addr ); + } + if( status == 0 ) { + status = wl_pci_dma_free_desc_and_buf( pdev, lp, desc ); + } + return status; +} // wl_pci_dma_free_tx_packet +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_alloc_rx_packet() + ******************************************************************************* + * + * DESCRIPTION: + * + * Allocates a single Rx packet, consisting of two descriptors and one + * contiguous buffer. THe buffer starts with the hermes-specific header. + * One descriptor points at the start, the other at offset 0x3a of the + * buffer. + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * lp - the device's private adapter structure + * desc - a pointer which will reference the descriptor to be alloc'd. + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_pci_dma_alloc_rx_packet( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc ) +{ + int status = 0; + DESC_STRCT *p; + /*------------------------------------------------------------------------*/ + +// if( desc == NULL ) { +// status = -EFAULT; +// } +// //;?the "limited" NDIS strategy, assuming a frame consists ALWAYS out of 2 +// //descriptors, make this robust +// if( status == 0 ) { +// status = wl_pci_dma_alloc_desc( pdev, lp, desc ); +// } +// if( status == 0 ) { +// status = wl_pci_dma_alloc_buf( pdev, lp, *desc, HCF_MAX_PACKET_SIZE ); +// } +// if( status == 0 ) { +// status = wl_pci_dma_alloc_desc( pdev, lp, &p ); +// } +// if( status == 0 ) { +// /* Size of 1st descriptor becomes 0x3a bytes */ +// SET_BUF_SIZE( *desc, HCF_DMA_RX_BUF1_SIZE ); +// +// /* Make 2nd descriptor point at offset 0x3a of the buffer */ +// SET_BUF_SIZE( p, ( HCF_MAX_PACKET_SIZE - HCF_DMA_RX_BUF1_SIZE )); +// p->buf_addr = (*desc)->buf_addr + HCF_DMA_RX_BUF1_SIZE; +// p->buf_phys_addr = (*desc)->buf_phys_addr + HCF_DMA_RX_BUF1_SIZE; +// p->next_desc_addr = NULL; +// +// /* Chain 2nd descriptor to 1st descriptor */ +// (*desc)->next_desc_addr = p; +// (*desc)->next_desc_phys_addr = p->desc_phys_addr; +// } + + return status; +} // wl_pci_dma_alloc_rx_packet +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_free_rx_packet() + ******************************************************************************* + * + * DESCRIPTION: + * + * Frees a single Rx packet, described in the corresponding alloc function. + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * lp - the device's private adapter structure + * desc - a pointer which will reference the descriptor to be alloc'd. + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_pci_dma_free_rx_packet( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc ) +{ + int status = 0; + DESC_STRCT *p; + /*------------------------------------------------------------------------*/ + + if( *desc == NULL ) { + status = -EFAULT; + } + if( status == 0 ) { + p = (*desc)->next_desc_addr; + + /* Free the 2nd descriptor */ + if( p != NULL ) { + p->buf_addr = NULL; + p->buf_phys_addr = 0; + + status = wl_pci_dma_free_desc( pdev, lp, &p ); + } + } + + /* Free the buffer and 1st descriptor */ + if( status == 0 ) { + SET_BUF_SIZE( *desc, HCF_MAX_PACKET_SIZE ); + status = wl_pci_dma_free_desc_and_buf( pdev, lp, desc ); + } + return status; +} // wl_pci_dma_free_rx_packet +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_alloc_desc_and_buf() + ******************************************************************************* + * + * DESCRIPTION: + * + * Allocates a DMA descriptor and buffer, and associates them with one + * another. + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * lp - the device's private adapter structure + * desc - a pointer which will reference the descriptor to be alloc'd + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_pci_dma_alloc_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc, int size ) +{ + int status = 0; + /*------------------------------------------------------------------------*/ + +// if( desc == NULL ) { +// status = -EFAULT; +// } +// if( status == 0 ) { +// status = wl_pci_dma_alloc_desc( pdev, lp, desc ); +// +// if( status == 0 ) { +// status = wl_pci_dma_alloc_buf( pdev, lp, *desc, size ); +// } +// } + return status; +} // wl_pci_dma_alloc_desc_and_buf +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_free_desc_and_buf() + ******************************************************************************* + * + * DESCRIPTION: + * + * Frees a DMA descriptor and associated buffer. + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * lp - the device's private adapter structure + * desc - a pointer which will reference the descriptor to be alloc'd + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_pci_dma_free_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc ) +{ + int status = 0; + /*------------------------------------------------------------------------*/ + + if( desc == NULL ) { + status = -EFAULT; + } + if( status == 0 && *desc == NULL ) { + status = -EFAULT; + } + if( status == 0 ) { + status = wl_pci_dma_free_buf( pdev, lp, *desc ); + + if( status == 0 ) { + status = wl_pci_dma_free_desc( pdev, lp, desc ); + } + } + return status; +} // wl_pci_dma_free_desc_and_buf +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_alloc_desc() + ******************************************************************************* + * + * DESCRIPTION: + * + * Allocates one DMA descriptor in cache coherent memory. + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_pci_dma_alloc_desc( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc ) +{ +// int status = 0; +// dma_addr_t pa; +// /*------------------------------------------------------------------------*/ +// +// DBG_FUNC( "wl_pci_dma_alloc_desc" ); +// DBG_ENTER( DbgInfo ); +// +// if( desc == NULL ) { +// status = -EFAULT; +// } +// if( status == 0 ) { +// *desc = pci_alloc_consistent( pdev, sizeof( DESC_STRCT ), &pa ); +// } +// if( *desc == NULL ) { +// DBG_ERROR( DbgInfo, "pci_alloc_consistent() failed\n" ); +// status = -ENOMEM; +// } else { +// memset( *desc, 0, sizeof( DESC_STRCT )); +// (*desc)->desc_phys_addr = cpu_to_le32( pa ); +// } +// DBG_LEAVE( DbgInfo ); +// return status; +} // wl_pci_dma_alloc_desc +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_free_desc() + ******************************************************************************* + * + * DESCRIPTION: + * + * Frees one DMA descriptor in cache coherent memory. + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_pci_dma_free_desc( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT **desc ) +{ + int status = 0; + /*------------------------------------------------------------------------*/ + + if( *desc == NULL ) { + status = -EFAULT; + } + if( status == 0 ) { + pci_free_consistent( pdev, sizeof( DESC_STRCT ), *desc, + (*desc)->desc_phys_addr ); + } + *desc = NULL; + return status; +} // wl_pci_dma_free_desc +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_alloc_buf() + ******************************************************************************* + * + * DESCRIPTION: + * + * Allocates one DMA buffer in cache coherent memory, and associates a DMA + * descriptor with this buffer. + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_pci_dma_alloc_buf( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT *desc, int size ) +{ + int status = 0; + dma_addr_t pa; + /*------------------------------------------------------------------------*/ + +// DBG_FUNC( "wl_pci_dma_alloc_buf" ); +// DBG_ENTER( DbgInfo ); +// +// if( desc == NULL ) { +// status = -EFAULT; +// } +// if( status == 0 && desc->buf_addr != NULL ) { +// status = -EFAULT; +// } +// if( status == 0 ) { +// desc->buf_addr = pci_alloc_consistent( pdev, size, &pa ); +// } +// if( desc->buf_addr == NULL ) { +// DBG_ERROR( DbgInfo, "pci_alloc_consistent() failed\n" ); +// status = -ENOMEM; +// } else { +// desc->buf_phys_addr = cpu_to_le32( pa ); +// SET_BUF_SIZE( desc, size ); +// } +// DBG_LEAVE( DbgInfo ); + return status; +} // wl_pci_dma_alloc_buf +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_free_buf() + ******************************************************************************* + * + * DESCRIPTION: + * + * Allocates one DMA buffer in cache coherent memory, and associates a DMA + * descriptor with this buffer. + * + * PARAMETERS: + * + * pdev - a pointer to the device's pci_dev structure + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wl_pci_dma_free_buf( struct pci_dev *pdev, struct wl_private *lp, + DESC_STRCT *desc ) +{ + int status = 0; + /*------------------------------------------------------------------------*/ + + if( desc == NULL ) { + status = -EFAULT; + } + if( status == 0 && desc->buf_addr == NULL ) { + status = -EFAULT; + } + if( status == 0 ) { + pci_free_consistent( pdev, GET_BUF_SIZE( desc ), desc->buf_addr, + desc->buf_phys_addr ); + + desc->buf_addr = 0; + desc->buf_phys_addr = 0; + SET_BUF_SIZE( desc, 0 ); + } + return status; +} // wl_pci_dma_free_buf +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_hcf_supply() + ******************************************************************************* + * + * DESCRIPTION: + * + * Supply HCF with DMA-related resources. These consist of: + * - buffers and descriptors for receive purposes + * - one 'reclaim' descriptor for the transmit path, used to fulfill a + * certain H25 DMA engine requirement + * - one 'reclaim' descriptor for the receive path, used to fulfill a + * certain H25 DMA engine requirement + * + * This function is called at start-of-day or at re-initialization. + * + * PARAMETERS: + * + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +void wl_pci_dma_hcf_supply( struct wl_private *lp ) +{ + int i; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_pci_dma_hcf_supply" ); + DBG_ENTER( DbgInfo ); + + //if( lp->dma.status == 0 ); + //{ + /* Hand over the Rx/Tx reclaim descriptors to the HCF */ + if( lp->dma.tx_reclaim_desc ) { + DBG_PRINT( "lp->dma.tx_reclaim_desc: 0x%p\n", lp->dma.tx_reclaim_desc ); + hcf_dma_tx_put( &lp->hcfCtx, lp->dma.tx_reclaim_desc, 0 ); + lp->dma.tx_reclaim_desc = NULL; + DBG_PRINT( "lp->dma.tx_reclaim_desc: 0x%p\n", lp->dma.tx_reclaim_desc ); + } + if( lp->dma.rx_reclaim_desc ) { + DBG_PRINT( "lp->dma.rx_reclaim_desc: 0x%p\n", lp->dma.rx_reclaim_desc ); + hcf_dma_rx_put( &lp->hcfCtx, lp->dma.rx_reclaim_desc ); + lp->dma.rx_reclaim_desc = NULL; + DBG_PRINT( "lp->dma.rx_reclaim_desc: 0x%p\n", lp->dma.rx_reclaim_desc ); + } + /* Hand over the Rx descriptor chain to the HCF */ + for( i = 0; i < NUM_RX_DESC; i++ ) { + DBG_PRINT( "lp->dma.rx_packet[%d]: 0x%p\n", i, lp->dma.rx_packet[i] ); + hcf_dma_rx_put( &lp->hcfCtx, lp->dma.rx_packet[i] ); + lp->dma.rx_packet[i] = NULL; + DBG_PRINT( "lp->dma.rx_packet[%d]: 0x%p\n", i, lp->dma.rx_packet[i] ); + } + //} + + DBG_LEAVE( DbgInfo ); + return; +} // wl_pci_dma_hcf_supply +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_hcf_reclaim() + ******************************************************************************* + * + * DESCRIPTION: + * + * Return DMA-related resources from the HCF. These consist of: + * - buffers and descriptors for receive purposes + * - buffers and descriptors for transmit purposes + * - one 'reclaim' descriptor for the transmit path, used to fulfill a + * certain H25 DMA engine requirement + * - one 'reclaim' descriptor for the receive path, used to fulfill a + * certain H25 DMA engine requirement + * + * This function is called at end-of-day or at re-initialization. + * + * PARAMETERS: + * + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +void wl_pci_dma_hcf_reclaim( struct wl_private *lp ) +{ + int i; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_pci_dma_hcf_reclaim" ); + DBG_ENTER( DbgInfo ); + + wl_pci_dma_hcf_reclaim_rx( lp ); + for( i = 0; i < NUM_RX_DESC; i++ ) { + DBG_PRINT( "rx_packet[%d] 0x%p\n", i, lp->dma.rx_packet[i] ); +// if( lp->dma.rx_packet[i] == NULL ) { +// DBG_PRINT( "wl_pci_dma_hcf_reclaim: rx_packet[%d] NULL\n", i ); +// } + } + + wl_pci_dma_hcf_reclaim_tx( lp ); + for( i = 0; i < NUM_TX_DESC; i++ ) { + DBG_PRINT( "tx_packet[%d] 0x%p\n", i, lp->dma.tx_packet[i] ); +// if( lp->dma.tx_packet[i] == NULL ) { +// DBG_PRINT( "wl_pci_dma_hcf_reclaim: tx_packet[%d] NULL\n", i ); +// } + } + + DBG_LEAVE( DbgInfo ); + return; +} // wl_pci_dma_hcf_reclaim +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_hcf_reclaim_rx() + ******************************************************************************* + * + * DESCRIPTION: + * + * Reclaim Rx packets that have already been processed by the HCF. + * + * PARAMETERS: + * + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +void wl_pci_dma_hcf_reclaim_rx( struct wl_private *lp ) +{ + int i; + DESC_STRCT *p; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_pci_dma_hcf_reclaim_rx" ); + DBG_ENTER( DbgInfo ); + + //if( lp->dma.status == 0 ) + //{ + while ( ( p = hcf_dma_rx_get( &lp->hcfCtx ) ) != NULL ) { + if( p && p->buf_addr == NULL ) { + /* A reclaim descriptor is being given back by the HCF. Reclaim + descriptors have a NULL buf_addr */ + lp->dma.rx_reclaim_desc = p; + DBG_PRINT( "reclaim_descriptor: 0x%p\n", p ); + continue; + } + for( i = 0; i < NUM_RX_DESC; i++ ) { + if( lp->dma.rx_packet[i] == NULL ) { + break; + } + } + /* An Rx buffer descriptor is being given back by the HCF */ + lp->dma.rx_packet[i] = p; + lp->dma.rx_rsc_ind++; + DBG_PRINT( "rx_packet[%d] 0x%p\n", i, lp->dma.rx_packet[i] ); + } + //} + DBG_LEAVE( DbgInfo ); +} // wl_pci_dma_hcf_reclaim_rx +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_get_tx_packet() + ******************************************************************************* + * + * DESCRIPTION: + * + * Obtains a Tx descriptor from the chain to use for Tx. + * + * PARAMETERS: + * + * lp - a pointer to the device's wl_private structure. + * + * RETURNS: + * + * A pointer to the retrieved descriptor + * + ******************************************************************************/ +DESC_STRCT * wl_pci_dma_get_tx_packet( struct wl_private *lp ) +{ + int i; + DESC_STRCT *desc = NULL; + /*------------------------------------------------------------------------*/ + + for( i = 0; i < NUM_TX_DESC; i++ ) { + if( lp->dma.tx_packet[i] ) { + break; + } + } + + if( i != NUM_TX_DESC ) { + desc = lp->dma.tx_packet[i]; + + lp->dma.tx_packet[i] = NULL; + lp->dma.tx_rsc_ind--; + + memset( desc->buf_addr, 0, HCF_DMA_TX_BUF1_SIZE ); + } + + return desc; +} // wl_pci_dma_get_tx_packet +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_put_tx_packet() + ******************************************************************************* + * + * DESCRIPTION: + * + * Returns a Tx descriptor to the chain. + * + * PARAMETERS: + * + * lp - a pointer to the device's wl_private structure. + * desc - a pointer to the descriptor to return. + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_pci_dma_put_tx_packet( struct wl_private *lp, DESC_STRCT *desc ) +{ + int i; + /*------------------------------------------------------------------------*/ + + for( i = 0; i < NUM_TX_DESC; i++ ) { + if( lp->dma.tx_packet[i] == NULL ) { + break; + } + } + + if( i != NUM_TX_DESC ) { + lp->dma.tx_packet[i] = desc; + lp->dma.tx_rsc_ind++; + } +} // wl_pci_dma_put_tx_packet +/*============================================================================*/ + +/******************************************************************************* + * wl_pci_dma_hcf_reclaim_tx() + ******************************************************************************* + * + * DESCRIPTION: + * + * Reclaim Tx packets that have either been processed by the HCF due to a + * port disable or a Tx completion. + * + * PARAMETERS: + * + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +void wl_pci_dma_hcf_reclaim_tx( struct wl_private *lp ) +{ + int i; + DESC_STRCT *p; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_pci_dma_hcf_reclaim_tx" ); + DBG_ENTER( DbgInfo ); + + //if( lp->dma.status == 0 ) + //{ + while ( ( p = hcf_dma_tx_get( &lp->hcfCtx ) ) != NULL ) { + + if( p != NULL && p->buf_addr == NULL ) { + /* A Reclaim descriptor is being given back by the HCF. Reclaim + descriptors have a NULL buf_addr */ + lp->dma.tx_reclaim_desc = p; + DBG_PRINT( "reclaim_descriptor: 0x%p\n", p ); + continue; + } + for( i = 0; i < NUM_TX_DESC; i++ ) { + if( lp->dma.tx_packet[i] == NULL ) { + break; + } + } + /* An Rx buffer descriptor is being given back by the HCF */ + lp->dma.tx_packet[i] = p; + lp->dma.tx_rsc_ind++; + DBG_PRINT( "tx_packet[%d] 0x%p\n", i, lp->dma.tx_packet[i] ); + } + //} + + if( lp->netif_queue_on == FALSE ) { + netif_wake_queue( lp->dev ); + WL_WDS_NETIF_WAKE_QUEUE( lp ); + lp->netif_queue_on = TRUE; + } + DBG_LEAVE( DbgInfo ); + return; +} // wl_pci_dma_hcf_reclaim_tx +/*============================================================================*/ +#endif // ENABLE_DMA diff --git a/drivers/staging/wlags49_h2/wl_pci.h b/drivers/staging/wlags49_h2/wl_pci.h new file mode 100644 index 0000000000000000000000000000000000000000..18d7b514ea6cd6caf1de58fd10be0afdaf5e9fab --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_pci.h @@ -0,0 +1,109 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * Header describing information required for the driver to support PCI. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +#ifndef __WL_PCI_H__ +#define __WL_PCI_H__ + + + + +/******************************************************************************* + * constant definitions + ******************************************************************************/ +#define WL_LKM_PCI_VENDOR_ID 0x11C1 // Lucent Microelectronics +#define WL_LKM_PCI_DEVICE_ID_0 0xAB30 // Mini PCI +#define WL_LKM_PCI_DEVICE_ID_1 0xAB34 // Mini PCI +#define WL_LKM_PCI_DEVICE_ID_2 0xAB11 // WARP CardBus + + + + +/******************************************************************************* + * function prototypes + ******************************************************************************/ +int wl_adapter_init_module( void ); + +void wl_adapter_cleanup_module( void ); + +int wl_adapter_insert( struct net_device *dev ); + +int wl_adapter_open( struct net_device *dev ); + +int wl_adapter_close( struct net_device *dev ); + +int wl_adapter_is_open( struct net_device *dev ); + + +#ifdef ENABLE_DMA + +void wl_pci_dma_hcf_supply( struct wl_private *lp ); + +void wl_pci_dma_hcf_reclaim( struct wl_private *lp ); + +DESC_STRCT * wl_pci_dma_get_tx_packet( struct wl_private *lp ); + +void wl_pci_dma_put_tx_packet( struct wl_private *lp, DESC_STRCT *desc ); + +void wl_pci_dma_hcf_reclaim_tx( struct wl_private *lp ); + +#endif // ENABLE_DMA + + +#endif // __WL_PCI_H__ diff --git a/drivers/staging/wlags49_h2/wl_priv.c b/drivers/staging/wlags49_h2/wl_priv.c new file mode 100644 index 0000000000000000000000000000000000000000..ee610c76457e99235575a91532c0a688353377ad --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_priv.c @@ -0,0 +1,2078 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * This file defines handling routines for the private IOCTLs + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +/******************************************************************************* + * include files + ******************************************************************************/ +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +int wvlan_uil_connect( struct uilreq *urq, struct wl_private *lp ); +int wvlan_uil_disconnect( struct uilreq *urq, struct wl_private *lp ); +int wvlan_uil_action( struct uilreq *urq, struct wl_private *lp ); +int wvlan_uil_block( struct uilreq *urq, struct wl_private *lp ); +int wvlan_uil_unblock( struct uilreq *urq, struct wl_private *lp ); +int wvlan_uil_send_diag_msg( struct uilreq *urq, struct wl_private *lp ); +int wvlan_uil_put_info( struct uilreq *urq, struct wl_private *lp ); +int wvlan_uil_get_info( struct uilreq *urq, struct wl_private *lp ); + +int cfg_driver_info( struct uilreq *urq, struct wl_private *lp ); +int cfg_driver_identity( struct uilreq *urq, struct wl_private *lp ); + + +/******************************************************************************* + * global variables + ******************************************************************************/ +#if DBG +extern dbg_info_t *DbgInfo; +#endif // DBG + + + + +/* If USE_UIL is not defined, then none of the UIL Interface code below will + be included in the build */ +#ifdef USE_UIL + +/******************************************************************************* + * wvlan_uil() + ******************************************************************************* + * + * DESCRIPTION: + * + * The handler function for the UIL interface. + * + * PARAMETERS: + * + * urq - a pointer to the UIL request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wvlan_uil( struct uilreq *urq, struct wl_private *lp ) +{ + int ioctl_ret = 0; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wvlan_uil" ); + DBG_ENTER( DbgInfo ); + + switch( urq->command ) { + case UIL_FUN_CONNECT: + DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_CONNECT\n"); + ioctl_ret = wvlan_uil_connect( urq, lp ); + break; + case UIL_FUN_DISCONNECT: + DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_DISCONNECT\n"); + ioctl_ret = wvlan_uil_disconnect( urq, lp ); + break; + case UIL_FUN_ACTION: + DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_ACTION\n" ); + ioctl_ret = wvlan_uil_action( urq, lp ); + break; + case UIL_FUN_SEND_DIAG_MSG: + DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_SEND_DIAG_MSG\n"); + ioctl_ret = wvlan_uil_send_diag_msg( urq, lp ); + break; + case UIL_FUN_GET_INFO: + DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_GET_INFO\n"); + ioctl_ret = wvlan_uil_get_info( urq, lp ); + break; + case UIL_FUN_PUT_INFO: + DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_PUT_INFO\n"); + ioctl_ret = wvlan_uil_put_info( urq, lp ); + break; + default: + DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- UNSUPPORTED UIL CODE: 0x%X", urq->command ); + ioctl_ret = -EOPNOTSUPP; + break; + } + DBG_LEAVE( DbgInfo ); + return ioctl_ret; +} // wvlan_uil +/*============================================================================*/ + + + + +/******************************************************************************* + * wvlan_uil_connect() + ******************************************************************************* + * + * DESCRIPTION: + * + * Connect to the UIL in order to make a request. + * + * PARAMETERS: + * + * urq - a pointer to the UIL request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * UIL_SUCCESS + * UIL_ERR_xxx value otherwise + * + ******************************************************************************/ +int wvlan_uil_connect( struct uilreq *urq, struct wl_private *lp ) +{ + int result = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wvlan_uil_connect" ); + DBG_ENTER( DbgInfo ); + + + if( !( lp->flags & WVLAN2_UIL_CONNECTED )) { + lp->flags |= WVLAN2_UIL_CONNECTED; + urq->hcfCtx = &( lp->hcfCtx ); + urq->result = UIL_SUCCESS; + } else { + DBG_WARNING( DbgInfo, "UIL_ERR_IN_USE\n" ); + urq->result = UIL_ERR_IN_USE; + } + + DBG_LEAVE( DbgInfo ); + return result; +} // wvlan_uil_connect +/*============================================================================*/ + + + + +/******************************************************************************* + * wvlan_uil_disconnect() + ******************************************************************************* + * + * DESCRIPTION: + * + * Disonnect from the UIL after a request has been completed. + * + * PARAMETERS: + * + * urq - a pointer to the UIL request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * UIL_SUCCESS + * UIL_ERR_xxx value otherwise + * + ******************************************************************************/ +int wvlan_uil_disconnect( struct uilreq *urq, struct wl_private *lp ) +{ + int result = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wvlan_uil_disconnect" ); + DBG_ENTER( DbgInfo ); + + + if( urq->hcfCtx == &( lp->hcfCtx )) { + if (lp->flags & WVLAN2_UIL_CONNECTED) { + lp->flags &= ~WVLAN2_UIL_CONNECTED; + /* + if (lp->flags & WVLAN2_UIL_BUSY) { + lp->flags &= ~WVLAN2_UIL_BUSY; + netif_start_queue(lp->dev); + } + */ + } + + urq->hcfCtx = NULL; + urq->result = UIL_SUCCESS; + } else { + DBG_ERROR( DbgInfo, "UIL_ERR_WRONG_IFB\n" ); + urq->result = UIL_ERR_WRONG_IFB; + } + + DBG_LEAVE( DbgInfo ); + return result; +} // wvlan_uil_disconnect +/*============================================================================*/ + + + + +/******************************************************************************* + * wvlan_uil_action() + ******************************************************************************* + * + * DESCRIPTION: + * + * Handler for the UIL_ACT_xxx subcodes associated with UIL_FUN_ACTION + * + * PARAMETERS: + * + * urq - a pointer to the UIL request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * UIL_SUCCESS + * UIL_ERR_xxx value otherwise + * + ******************************************************************************/ +int wvlan_uil_action( struct uilreq *urq, struct wl_private *lp ) +{ + int result = 0; + ltv_t *ltv; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wvlan_uil_action" ); + DBG_ENTER( DbgInfo ); + + + if( urq->hcfCtx == &( lp->hcfCtx )) { + /* Make sure there's an LTV in the request buffer */ + ltv = (ltv_t *)urq->data; + if( ltv != NULL ) { + /* Switch on the Type field of the LTV contained in the request + buffer */ + switch( ltv->typ ) { + case UIL_ACT_BLOCK: + DBG_TRACE( DbgInfo, "UIL_ACT_BLOCK\n" ); + result = wvlan_uil_block( urq, lp ); + break; + case UIL_ACT_UNBLOCK: + DBG_TRACE( DbgInfo, "UIL_ACT_UNBLOCK\n" ); + result = wvlan_uil_unblock( urq, lp ); + break; + case UIL_ACT_SCAN: + DBG_TRACE( DbgInfo, "UIL_ACT_SCAN\n" ); + urq->result = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN ); + break; + case UIL_ACT_APPLY: + DBG_TRACE( DbgInfo, "UIL_ACT_APPLY\n" ); + urq->result = wl_apply( lp ); + break; + case UIL_ACT_RESET: + DBG_TRACE( DbgInfo, "UIL_ACT_RESET\n" ); + urq->result = wl_go( lp ); + break; + default: + DBG_WARNING( DbgInfo, "Unknown action code: 0x%x\n", ltv->typ ); + break; + } + } else { + DBG_ERROR( DbgInfo, "Bad LTV for this action\n" ); + urq->result = UIL_ERR_LEN; + } + } else { + DBG_ERROR( DbgInfo, "UIL_ERR_WRONG_IFB\n" ); + urq->result = UIL_ERR_WRONG_IFB; + } + + DBG_LEAVE( DbgInfo ); + return result; +} // wvlan_uil_action +/*============================================================================*/ + + + + +/******************************************************************************* + * wvlan_uil_block() + ******************************************************************************* + * + * DESCRIPTION: + * + * Sets a block in the driver to prevent access to the card by other + * processes. + * + * PARAMETERS: + * + * urq - a pointer to the UIL request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * UIL_SUCCESS + * UIL_ERR_xxx value otherwise + * + ******************************************************************************/ + +int wvlan_uil_block( struct uilreq *urq, struct wl_private *lp ) +{ + int result = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wvlan_uil_block" ); + DBG_ENTER( DbgInfo ); + + if( urq->hcfCtx == &( lp->hcfCtx )) { + if( capable( CAP_NET_ADMIN )) { + lp->flags |= WVLAN2_UIL_BUSY; + netif_stop_queue(lp->dev); + WL_WDS_NETIF_STOP_QUEUE( lp ); + urq->result = UIL_SUCCESS; + } else { + DBG_ERROR( DbgInfo, "EPERM\n" ); + urq->result = UIL_FAILURE; + result = -EPERM; + } + } else { + DBG_ERROR( DbgInfo, "UIL_ERR_WRONG_IFB\n" ); + urq->result = UIL_ERR_WRONG_IFB; + } + + DBG_LEAVE( DbgInfo ); + return result; +} // wvlan_uil_block +/*============================================================================*/ + + + + +/******************************************************************************* + * wvlan_uil_unblock() + ******************************************************************************* + * + * DESCRIPTION: + * + * Unblocks the driver to restore access to the card by other processes. + * + * PARAMETERS: + * + * urq - a pointer to the UIL request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * UIL_SUCCESS + * UIL_ERR_xxx value otherwise + * + ******************************************************************************/ +int wvlan_uil_unblock( struct uilreq *urq, struct wl_private *lp ) +{ + int result = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wvlan_uil_unblock" ); + DBG_ENTER( DbgInfo ); + + if( urq->hcfCtx == &( lp->hcfCtx )) { + if( capable( CAP_NET_ADMIN )) { + if (lp->flags & WVLAN2_UIL_BUSY) { + lp->flags &= ~WVLAN2_UIL_BUSY; + netif_wake_queue(lp->dev); + WL_WDS_NETIF_WAKE_QUEUE( lp ); + } + } else { + DBG_ERROR( DbgInfo, "EPERM\n" ); + urq->result = UIL_FAILURE; + result = -EPERM; + } + } else { + DBG_ERROR( DbgInfo, "UIL_ERR_WRONG_IFB\n" ); + urq->result = UIL_ERR_WRONG_IFB; + } + + DBG_LEAVE( DbgInfo ); + return result; +} // wvlan_uil_unblock +/*============================================================================*/ + + + + +/******************************************************************************* + * wvlan_uil_send_diag_msg() + ******************************************************************************* + * + * DESCRIPTION: + * + * Sends a diagnostic message to the card. + * + * PARAMETERS: + * + * urq - a pointer to the UIL request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * UIL_SUCCESS + * UIL_ERR_xxx value otherwise + * + ******************************************************************************/ +int wvlan_uil_send_diag_msg( struct uilreq *urq, struct wl_private *lp ) +{ + int result = 0; + DESC_STRCT Descp[1]; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wvlan_uil_send_diag_msg" ); + DBG_ENTER( DbgInfo ); + + if( urq->hcfCtx == &( lp->hcfCtx )) { + if( capable( CAP_NET_ADMIN )) { + if ((urq->data != NULL) && (urq->len != 0)) { + if (lp->hcfCtx.IFB_RscInd != 0) { + u_char *data; + + // Verify the user buffer + result = verify_area(VERIFY_READ, urq->data, urq->len); + if (result != 0) { + DBG_ERROR( DbgInfo, "verify_area failed, result: %d\n", result ); + urq->result = UIL_FAILURE; + DBG_LEAVE( DbgInfo ); + return result; + } + + if ((data = kmalloc(urq->len, GFP_KERNEL)) != NULL) { + memset( Descp, 0, sizeof( DESC_STRCT )); + memcpy( data, urq->data, urq->len ); + + Descp[0].buf_addr = (wci_bufp)data; + Descp[0].BUF_CNT = urq->len; + Descp[0].next_desc_addr = 0; // terminate list + + hcf_send_msg( &(lp->hcfCtx), &Descp[0], HCF_PORT_0 ); + kfree( data ); + } else { + DBG_ERROR( DbgInfo, "ENOMEM\n" ); + urq->result = UIL_FAILURE; + result = -ENOMEM; + DBG_LEAVE( DbgInfo ); + return result; + } + + } else { + urq->result = UIL_ERR_BUSY; + } + + } else { + urq->result = UIL_FAILURE; + } + } else { + DBG_ERROR( DbgInfo, "EPERM\n" ); + urq->result = UIL_FAILURE; + result = -EPERM; + } + } else { + DBG_ERROR( DbgInfo, "UIL_ERR_WRONG_IFB\n" ); + urq->result = UIL_ERR_WRONG_IFB; + } + + DBG_LEAVE( DbgInfo ); + return result; +} // wvlan_uil_send_diag_msg +/*============================================================================*/ + + +/******************************************************************************* + * wvlan_uil_put_info() + ******************************************************************************* + * + * DESCRIPTION: + * + * Sends a specific RID directly to the driver to set configuration info. + * + * PARAMETERS: + * + * urq - a pointer to the UIL request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * UIL_SUCCESS + * UIL_ERR_xxx value otherwise + * + ******************************************************************************/ +int wvlan_uil_put_info( struct uilreq *urq, struct wl_private *lp ) +{ + int result = 0; + ltv_t *pLtv; + bool_t ltvAllocated = FALSE; + ENCSTRCT sEncryption; + +#ifdef USE_WDS + hcf_16 hcfPort = HCF_PORT_0; +#endif /* USE_WDS */ + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wvlan_uil_put_info" ); + DBG_ENTER( DbgInfo ); + + + if( urq->hcfCtx == &( lp->hcfCtx )) { + if( capable( CAP_NET_ADMIN )) { + if(( urq->data != NULL ) && ( urq->len != 0 )) { + /* Make sure that we have at least a command and length to send. */ + if( urq->len < ( sizeof( hcf_16 ) * 2 )) { + urq->len = sizeof( lp->ltvRecord ); + urq->result = UIL_ERR_LEN; + DBG_ERROR( DbgInfo, "No Length/Type in LTV!!!\n" ); + DBG_ERROR( DbgInfo, "UIL_ERR_LEN\n" ); + DBG_LEAVE( DbgInfo ); + return result; + } + + /* Verify the user buffer */ + result = verify_area( VERIFY_READ, urq->data, urq->len ); + if( result != 0 ) { + urq->result = UIL_FAILURE; + DBG_ERROR( DbgInfo, "verify_area(), VERIFY_READ FAILED\n" ); + DBG_LEAVE( DbgInfo ); + return result; + } + + /* Get only the command and length information. */ + copy_from_user( &( lp->ltvRecord ), urq->data, sizeof( hcf_16 ) * 2 ); + + /* Make sure the incoming LTV record length is within the bounds of the + IOCTL length */ + if((( lp->ltvRecord.len + 1 ) * sizeof( hcf_16 )) > urq->len ) { + urq->len = sizeof( lp->ltvRecord ); + urq->result = UIL_ERR_LEN; + DBG_ERROR( DbgInfo, "UIL_ERR_LEN\n" ); + DBG_LEAVE( DbgInfo ); + return result; + } + + /* If the requested length is greater than the size of our local + LTV record, try to allocate it from the kernel stack. + Otherwise, we just use our local LTV record. */ + if( urq->len > sizeof( lp->ltvRecord )) { + if(( pLtv = (ltv_t *)kmalloc( urq->len, GFP_KERNEL )) != NULL ) { + ltvAllocated = TRUE; + } else { + DBG_ERROR( DbgInfo, "Alloc FAILED\n" ); + urq->len = sizeof( lp->ltvRecord ); + urq->result = UIL_ERR_LEN; + result = -ENOMEM; + DBG_LEAVE( DbgInfo ); + return result; + } + } else { + pLtv = &( lp->ltvRecord ); + } + + /* Copy the data from the user's buffer into the local LTV + record data area. */ + copy_from_user( pLtv, urq->data, urq->len ); + + + /* We need to snoop the commands to see if there is anything we + need to store for the purposes of a reset or start/stop + sequence. Perform endian translation as needed */ + switch( pLtv->typ ) { + case CFG_CNF_PORT_TYPE: + lp->PortType = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_CNF_OWN_MAC_ADDR: + /* TODO: determine if we are going to store anything based on this */ + break; + case CFG_CNF_OWN_CHANNEL: + lp->Channel = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + /* CFG_CNF_OWN_SSID currently same as CNF_DESIRED_SSID. Do we + need seperate storage for this? */ + //case CFG_CNF_OWN_SSID: + case CFG_CNF_OWN_ATIM_WINDOW: + lp->atimWindow = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_CNF_SYSTEM_SCALE: + lp->DistanceBetweenAPs = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + + case CFG_CNF_MAX_DATA_LEN: + /* TODO: determine if we are going to store anything based + on this */ + break; + case CFG_CNF_PM_ENABLED: + lp->PMEnabled = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_CNF_MCAST_RX: + lp->MulticastReceive = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_CNF_MAX_SLEEP_DURATION: + lp->MaxSleepDuration = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_CNF_HOLDOVER_DURATION: + lp->holdoverDuration = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_CNF_OWN_NAME: + memset( lp->StationName, 0, sizeof( lp->StationName )); + memcpy( (void *)lp->StationName, (void *)&pLtv->u.u8[2], (size_t)pLtv->u.u16[0]); + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_CNF_LOAD_BALANCING: + lp->loadBalancing = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_CNF_MEDIUM_DISTRIBUTION: + lp->mediumDistribution = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; +#ifdef WARP + case CFG_CNF_TX_POW_LVL: + lp->txPowLevel = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + //case CFG_CNF_SHORT_RETRY_LIMIT: // Short Retry Limit + //case 0xFC33: // Long Retry Limit + case CFG_SUPPORTED_RATE_SET_CNTL: // Supported Rate Set Control + lp->srsc[0] = pLtv->u.u16[0]; + lp->srsc[1] = pLtv->u.u16[1]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + pLtv->u.u16[1] = CNV_INT_TO_LITTLE( pLtv->u.u16[1] ); + break; + case CFG_BASIC_RATE_SET_CNTL: // Basic Rate Set Control + lp->brsc[0] = pLtv->u.u16[0]; + lp->brsc[1] = pLtv->u.u16[1]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + pLtv->u.u16[1] = CNV_INT_TO_LITTLE( pLtv->u.u16[1] ); + break; + case CFG_CNF_CONNECTION_CNTL: + lp->connectionControl = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + //case CFG_PROBE_DATA_RATE: +#endif // HERMES25 + +#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP + //;?should we restore this to allow smaller memory footprint + + case CFG_CNF_OWN_DTIM_PERIOD: + lp->DTIMPeriod = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; +#ifdef WARP + case CFG_CNF_OWN_BEACON_INTERVAL: // Own Beacon Interval + lp->ownBeaconInterval = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; +#endif // WARP + case CFG_COEXISTENSE_BEHAVIOUR: // Coexistence behavior + lp->coexistence = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; +#ifdef USE_WDS + case CFG_CNF_WDS_ADDR1: + memcpy( &lp->wds_port[0].wdsAddress, &pLtv->u.u8[0], ETH_ALEN ); + hcfPort = HCF_PORT_1; + break; + case CFG_CNF_WDS_ADDR2: + memcpy( &lp->wds_port[1].wdsAddress, &pLtv->u.u8[0], ETH_ALEN ); + hcfPort = HCF_PORT_2; + break; + case CFG_CNF_WDS_ADDR3: + memcpy( &lp->wds_port[2].wdsAddress, &pLtv->u.u8[0], ETH_ALEN ); + hcfPort = HCF_PORT_3; + break; + case CFG_CNF_WDS_ADDR4: + memcpy( &lp->wds_port[3].wdsAddress, &pLtv->u.u8[0], ETH_ALEN ); + hcfPort = HCF_PORT_4; + break; + case CFG_CNF_WDS_ADDR5: + memcpy( &lp->wds_port[4].wdsAddress, &pLtv->u.u8[0], ETH_ALEN ); + hcfPort = HCF_PORT_5; + break; + case CFG_CNF_WDS_ADDR6: + memcpy( &lp->wds_port[5].wdsAddress, &pLtv->u.u8[0], ETH_ALEN ); + hcfPort = HCF_PORT_6; + break; +#endif /* USE_WDS */ + + case CFG_CNF_MCAST_PM_BUF: + lp->multicastPMBuffering = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_CNF_REJECT_ANY: + lp->RejectAny = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; +#endif + + case CFG_CNF_ENCRYPTION: + lp->EnableEncryption = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_CNF_AUTHENTICATION: + lp->authentication = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; +#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP + //;?should we restore this to allow smaller memory footprint + + //case CFG_CNF_EXCL_UNENCRYPTED: + //lp->ExcludeUnencrypted = pLtv->u.u16[0]; + //pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + //break; + case CFG_CNF_MCAST_RATE: + /* TODO: determine if we are going to store anything based on this */ + break; + case CFG_CNF_INTRA_BSS_RELAY: + lp->intraBSSRelay = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; +#endif + + case CFG_CNF_MICRO_WAVE: + /* TODO: determine if we are going to store anything based on this */ + break; + //case CFG_CNF_LOAD_BALANCING: + /* TODO: determine if we are going to store anything based on this */ + //break; + //case CFG_CNF_MEDIUM_DISTRIBUTION: + /* TODO: determine if we are going to store anything based on this */ + //break; + //case CFG_CNF_RX_ALL_GROUP_ADDRESS: + // TODO: determine if we are going to store anything based on this + //break; + //case CFG_CNF_COUNTRY_INFO: + /* TODO: determine if we are going to store anything based on this */ + //break; + case CFG_CNF_OWN_SSID: + //case CNF_DESIRED_SSID: + case CFG_DESIRED_SSID: + memset( lp->NetworkName, 0, sizeof( lp->NetworkName )); + memcpy( (void *)lp->NetworkName, (void *)&pLtv->u.u8[2], (size_t)pLtv->u.u16[0] ); + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + + /* take care of the special network name "ANY" case */ + if(( strlen( &pLtv->u.u8[2] ) == 0 ) || + ( strcmp( &pLtv->u.u8[2], "ANY" ) == 0 ) || + ( strcmp( &pLtv->u.u8[2], "any" ) == 0 )) { + /* set the SSID_STRCT llen field (u16[0]) to zero, and the + effectually null the string u8[2] */ + pLtv->u.u16[0] = 0; + pLtv->u.u8[2] = 0; + } + break; + case CFG_GROUP_ADDR: + /* TODO: determine if we are going to store anything based on this */ + break; + case CFG_CREATE_IBSS: + lp->CreateIBSS = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_RTS_THRH: + lp->RTSThreshold = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_TX_RATE_CNTL: + lp->TxRateControl[0] = pLtv->u.u16[0]; + lp->TxRateControl[1] = pLtv->u.u16[1]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + pLtv->u.u16[1] = CNV_INT_TO_LITTLE( pLtv->u.u16[1] ); + break; + case CFG_PROMISCUOUS_MODE: + /* TODO: determine if we are going to store anything based on this */ + break; + //case CFG_WAKE_ON_LAN: + /* TODO: determine if we are going to store anything based on this */ + //break; +#if 1 //;? #if (HCF_TYPE) & HCF_TYPE_AP + //;?should we restore this to allow smaller memory footprint + case CFG_RTS_THRH0: + lp->RTSThreshold = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_TX_RATE_CNTL0: +//;?no idea what this should be, get going so comment it out lp->TxRateControl = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; +#ifdef USE_WDS + case CFG_RTS_THRH1: + lp->wds_port[0].rtsThreshold = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + hcfPort = HCF_PORT_1; + break; + case CFG_RTS_THRH2: + lp->wds_port[1].rtsThreshold = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + hcfPort = HCF_PORT_2; + break; + case CFG_RTS_THRH3: + lp->wds_port[2].rtsThreshold = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + hcfPort = HCF_PORT_3; + break; + case CFG_RTS_THRH4: + lp->wds_port[3].rtsThreshold = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + hcfPort = HCF_PORT_4; + break; + case CFG_RTS_THRH5: + lp->wds_port[4].rtsThreshold = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + hcfPort = HCF_PORT_5; + break; + case CFG_RTS_THRH6: + lp->wds_port[5].rtsThreshold = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + hcfPort = HCF_PORT_6; + break; + case CFG_TX_RATE_CNTL1: + lp->wds_port[0].txRateCntl = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + hcfPort = HCF_PORT_1; + break; + case CFG_TX_RATE_CNTL2: + lp->wds_port[1].txRateCntl = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + hcfPort = HCF_PORT_2; + break; + case CFG_TX_RATE_CNTL3: + lp->wds_port[2].txRateCntl = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + hcfPort = HCF_PORT_3; + break; + case CFG_TX_RATE_CNTL4: + lp->wds_port[3].txRateCntl = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + hcfPort = HCF_PORT_4; + break; + case CFG_TX_RATE_CNTL5: + lp->wds_port[4].txRateCntl = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + hcfPort = HCF_PORT_5; + break; + case CFG_TX_RATE_CNTL6: + lp->wds_port[5].txRateCntl = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + hcfPort = HCF_PORT_6; + break; +#endif /* USE_WDS */ +#endif /* (HCF_TYPE) & HCF_TYPE_AP */ + + case CFG_DEFAULT_KEYS: + { + CFG_DEFAULT_KEYS_STRCT *pKeys = (CFG_DEFAULT_KEYS_STRCT *)pLtv; + + pKeys->key[0].len = CNV_INT_TO_LITTLE( pKeys->key[0].len ); + pKeys->key[1].len = CNV_INT_TO_LITTLE( pKeys->key[1].len ); + pKeys->key[2].len = CNV_INT_TO_LITTLE( pKeys->key[2].len ); + pKeys->key[3].len = CNV_INT_TO_LITTLE( pKeys->key[3].len ); + + memcpy( (void *)&(lp->DefaultKeys), (void *)pKeys, + sizeof( CFG_DEFAULT_KEYS_STRCT )); + } + break; + case CFG_TX_KEY_ID: + lp->TransmitKeyID = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_SCAN_SSID: + /* TODO: determine if we are going to store anything based on this */ + break; + case CFG_TICK_TIME: + /* TODO: determine if we are going to store anything based on this */ + break; + /* these RIDS are Info RIDs, and should they be allowed for puts??? */ + case CFG_MAX_LOAD_TIME: + case CFG_DL_BUF: + //case CFG_HSI_SUP_RANGE: + case CFG_NIC_SERIAL_NUMBER: + case CFG_NIC_IDENTITY: + case CFG_NIC_MFI_SUP_RANGE: + case CFG_NIC_CFI_SUP_RANGE: + case CFG_NIC_TEMP_TYPE: + case CFG_NIC_PROFILE: + case CFG_FW_IDENTITY: + case CFG_FW_SUP_RANGE: + case CFG_MFI_ACT_RANGES_STA: + case CFG_CFI_ACT_RANGES_STA: + case CFG_PORT_STAT: + case CFG_CUR_SSID: + case CFG_CUR_BSSID: + case CFG_COMMS_QUALITY: + case CFG_CUR_TX_RATE: + case CFG_CUR_BEACON_INTERVAL: + case CFG_CUR_SCALE_THRH: + case CFG_PROTOCOL_RSP_TIME: + case CFG_CUR_SHORT_RETRY_LIMIT: + case CFG_CUR_LONG_RETRY_LIMIT: + case CFG_MAX_TX_LIFETIME: + case CFG_MAX_RX_LIFETIME: + case CFG_CF_POLLABLE: + case CFG_AUTHENTICATION_ALGORITHMS: + case CFG_PRIVACY_OPT_IMPLEMENTED: + //case CFG_CURRENT_REMOTE_RATES: + //case CFG_CURRENT_USED_RATES: + //case CFG_CURRENT_SYSTEM_SCALE: + //case CFG_CURRENT_TX_RATE1: + //case CFG_CURRENT_TX_RATE2: + //case CFG_CURRENT_TX_RATE3: + //case CFG_CURRENT_TX_RATE4: + //case CFG_CURRENT_TX_RATE5: + //case CFG_CURRENT_TX_RATE6: + case CFG_NIC_MAC_ADDR: + case CFG_PCF_INFO: + //case CFG_CURRENT_COUNTRY_INFO: + case CFG_PHY_TYPE: + case CFG_CUR_CHANNEL: + //case CFG_CURRENT_POWER_STATE: + //case CFG_CCAMODE: + case CFG_SUPPORTED_DATA_RATES: + break; + case CFG_AP_MODE: +//;? lp->DownloadFirmware = ( pLtv->u.u16[0] ) + 1; + DBG_ERROR( DbgInfo, "set CFG_AP_MODE no longer supported\n" ); + break; + case CFG_ENCRYPT_STRING: + /* TODO: ENDIAN TRANSLATION HERE??? */ + memset( lp->szEncryption, 0, sizeof( lp->szEncryption )); + memcpy( (void *)lp->szEncryption, (void *)&pLtv->u.u8[0], + ( pLtv->len * sizeof( hcf_16 )) ); + wl_wep_decode( CRYPT_CODE, &sEncryption, + lp->szEncryption ); + + /* the Linux driver likes to use 1-4 for the key IDs, and then + convert to 0-3 when sending to the card. The Windows code + base used 0-3 in the API DLL, which was ported to Linux. For + the sake of the user experience, we decided to keep 0-3 as the + numbers used in the DLL; and will perform the +1 conversion here. + We could have converted the entire Linux driver, but this is + less obtrusive. This may be a "todo" to convert the whole driver */ + lp->TransmitKeyID = sEncryption.wTxKeyID + 1; + lp->EnableEncryption = sEncryption.wEnabled; + + memcpy( &lp->DefaultKeys, &sEncryption.EncStr, + sizeof( CFG_DEFAULT_KEYS_STRCT )); + break; + /*case CFG_COUNTRY_STRING: + memset( lp->countryString, 0, sizeof( lp->countryString )); + memcpy( (void *)lp->countryString, (void *)&pLtv->u.u8[2], (size_t)pLtv->u.u16[0]); + break; + */ + + case CFG_DRIVER_ENABLE: + lp->driverEnable = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_WOLAS_ENABLE: + lp->wolasEnable = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_SET_WPA_AUTH_KEY_MGMT_SUITE: + lp->AuthKeyMgmtSuite = pLtv->u.u16[0]; + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_DISASSOCIATE_ADDR: + pLtv->u.u16[ETH_ALEN / 2] = CNV_INT_TO_LITTLE( pLtv->u.u16[ETH_ALEN / 2] ); + break; + case CFG_ADD_TKIP_DEFAULT_KEY: + case CFG_REMOVE_TKIP_DEFAULT_KEY: + /* Endian convert the Tx Key Information */ + pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] ); + break; + case CFG_ADD_TKIP_MAPPED_KEY: + break; + case CFG_REMOVE_TKIP_MAPPED_KEY: + break; + /* some RIDs just can't be put */ + case CFG_MB_INFO: + case CFG_IFB: + default: + break; + } + + /* This code will prevent Static Configuration Entities from + being sent to the card, as they require a call to + UIL_ACT_APPLY to take effect. Dynamic Entities will be sent + immediately */ + switch( pLtv->typ ) { + case CFG_CNF_PORT_TYPE: + case CFG_CNF_OWN_MAC_ADDR: + case CFG_CNF_OWN_CHANNEL: + case CFG_CNF_OWN_SSID: + case CFG_CNF_OWN_ATIM_WINDOW: + case CFG_CNF_SYSTEM_SCALE: + case CFG_CNF_MAX_DATA_LEN: + case CFG_CNF_PM_ENABLED: + case CFG_CNF_MCAST_RX: + case CFG_CNF_MAX_SLEEP_DURATION: + case CFG_CNF_HOLDOVER_DURATION: + case CFG_CNF_OWN_NAME: + case CFG_CNF_LOAD_BALANCING: + case CFG_CNF_MEDIUM_DISTRIBUTION: +#ifdef WARP + case CFG_CNF_TX_POW_LVL: + case CFG_CNF_CONNECTION_CNTL: + //case CFG_PROBE_DATA_RATE: +#endif // HERMES25 +#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP + //;?should we restore this to allow smaller memory footprint + case CFG_CNF_OWN_DTIM_PERIOD: +#ifdef WARP + case CFG_CNF_OWN_BEACON_INTERVAL: // Own Beacon Interval +#endif // WARP +#ifdef USE_WDS + case CFG_CNF_WDS_ADDR1: + case CFG_CNF_WDS_ADDR2: + case CFG_CNF_WDS_ADDR3: + case CFG_CNF_WDS_ADDR4: + case CFG_CNF_WDS_ADDR5: + case CFG_CNF_WDS_ADDR6: +#endif + case CFG_CNF_MCAST_PM_BUF: + case CFG_CNF_REJECT_ANY: +#endif + + case CFG_CNF_ENCRYPTION: + case CFG_CNF_AUTHENTICATION: +#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP + //;?should we restore this to allow smaller memory footprint + + case CFG_CNF_EXCL_UNENCRYPTED: + case CFG_CNF_MCAST_RATE: + case CFG_CNF_INTRA_BSS_RELAY: +#endif + + case CFG_CNF_MICRO_WAVE: + //case CFG_CNF_LOAD_BALANCING: + //case CFG_CNF_MEDIUM_DISTRIBUTION: + //case CFG_CNF_RX_ALL_GROUP_ADDRESS: + //case CFG_CNF_COUNTRY_INFO: + //case CFG_COUNTRY_STRING: + case CFG_AP_MODE: + case CFG_ENCRYPT_STRING: + //case CFG_DRIVER_ENABLE: + case CFG_WOLAS_ENABLE: + case CFG_MB_INFO: + case CFG_IFB: + break; + /* Deal with this dynamic MSF RID, as it's required for WPA */ + case CFG_DRIVER_ENABLE: + if( lp->driverEnable ) { + //hcf_cntl_port( &( lp->hcfCtx ), + // HCF_PORT_ENABLE | HCF_PORT_0 ); + // //hcf_cntl( &( lp->hcfCtx ), + // // HCF_PORT_ENABLE | HCF_PORT_0 ); + //hcf_cntl( &( lp->hcfCtx ), HCF_CNTL_ENABLE ); + // //hcf_cntl( &( lp->hcfCtx ), HCF_CNTL_CONNECT ); + + hcf_cntl( &( lp->hcfCtx ), HCF_CNTL_ENABLE | HCF_PORT_0 ); + hcf_cntl( &( lp->hcfCtx ), HCF_CNTL_CONNECT ); + } else { + //hcf_cntl_port( &( lp->hcfCtx ), + // HCF_PORT_DISABLE | HCF_PORT_0 ); + // //hcf_cntl( &( lp->hcfCtx ), + // // HCF_PORT_DISABLE | HCF_PORT_0 ); + //hcf_cntl( &( lp->hcfCtx ), HCF_CNTL_DISABLE ); + // //hcf_cntl( &( lp->hcfCtx ), HCF_CNTL_DISCONNECT ); + + hcf_cntl( &( lp->hcfCtx ), HCF_CNTL_DISABLE | HCF_PORT_0 ); + hcf_cntl( &( lp->hcfCtx ), HCF_CNTL_DISCONNECT ); + } + break; + default: + wl_act_int_off( lp ); + urq->result = hcf_put_info(&(lp->hcfCtx), (LTVP) pLtv); + wl_act_int_on( lp ); + break; + } + + if( ltvAllocated ) { + kfree( pLtv ); + } + } else { + urq->result = UIL_FAILURE; + } + } else { + DBG_ERROR( DbgInfo, "EPERM\n" ); + urq->result = UIL_FAILURE; + result = -EPERM; + } + } else { + DBG_ERROR( DbgInfo, "UIL_ERR_WRONG_IFB\n" ); + urq->result = UIL_ERR_WRONG_IFB; + } + + DBG_LEAVE( DbgInfo ); + return result; +} // wvlan_uil_put_info +/*============================================================================*/ + +/******************************************************************************* + * wvlan_uil_get_info() + ******************************************************************************* + * + * DESCRIPTION: + * + * Sends a specific RID directly to the driver to retrieve configuration + * info. + * + * PARAMETERS: + * + * urq - a pointer to the UIL request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * UIL_SUCCESS + * UIL_ERR_xxx value otherwise + * + ******************************************************************************/ +int wvlan_uil_get_info( struct uilreq *urq, struct wl_private *lp ) +{ + int result = 0; + int i; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wvlan_uil_get_info" ); + DBG_ENTER( DbgInfo ); + + if( urq->hcfCtx == &( lp->hcfCtx )) { + if(( urq->data != NULL ) && ( urq->len != 0 )) { + ltv_t *pLtv; + bool_t ltvAllocated = FALSE; + + /* Make sure that we have at least a command and length */ + if( urq->len < ( sizeof( hcf_16 ) * 2 )) { + urq->len = sizeof( lp->ltvRecord ); + DBG_ERROR( DbgInfo, "No Length/Type in LTV!!!\n" ); + DBG_ERROR( DbgInfo, "UIL_ERR_LEN\n" ); + urq->result = UIL_ERR_LEN; + DBG_LEAVE( DbgInfo ); + return result; + } + + /* Verify the user's LTV record header. */ + result = verify_area( VERIFY_READ, urq->data, sizeof( hcf_16 ) * 2 ); + if( result != 0 ) { + DBG_ERROR( DbgInfo, "verify_area(), VERIFY_READ FAILED\n" ); + urq->result = UIL_FAILURE; + DBG_LEAVE( DbgInfo ); + return result; + } + + /* Get only the command and length information. */ + result = copy_from_user( &( lp->ltvRecord ), urq->data, sizeof( hcf_16 ) * 2 ); + + /* Make sure the incoming LTV record length is within the bounds of + the IOCTL length. */ + if((( lp->ltvRecord.len + 1 ) * sizeof( hcf_16 )) > urq->len ) { + DBG_ERROR( DbgInfo, "Incoming LTV too big\n" ); + urq->len = sizeof( lp->ltvRecord ); + urq->result = UIL_ERR_LEN; + DBG_LEAVE( DbgInfo ); + return result; + } + + /* Determine if hcf_get_info() is needed or not */ + switch ( lp->ltvRecord.typ ) { + case CFG_NIC_IDENTITY: + memcpy( &lp->ltvRecord.u.u8[0], &lp->NICIdentity, sizeof( lp->NICIdentity )); + break; + case CFG_PRI_IDENTITY: + memcpy( &lp->ltvRecord.u.u8[0], &lp->PrimaryIdentity, sizeof( lp->PrimaryIdentity )); + break; + case CFG_AP_MODE: + DBG_ERROR( DbgInfo, "set CFG_AP_MODE no longer supported, so is get useful ????\n" ); + lp->ltvRecord.u.u16[0] = + CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP; + break; + //case CFG_DRV_INFO: + case CFG_ENCRYPT_STRING: + case CFG_COUNTRY_STRING: + case CFG_DRIVER_ENABLE: + case CFG_WOLAS_ENABLE: + // TODO: determine if we're going to support these + urq->result = UIL_FAILURE; + break; + case CFG_DRV_INFO: + DBG_TRACE( DbgInfo, "Intercept CFG_DRV_INFO\n" ); + result = cfg_driver_info( urq, lp ); + break; + case CFG_DRV_IDENTITY: + DBG_TRACE( DbgInfo, "Intercept CFG_DRV_IDENTITY\n" ); + result = cfg_driver_identity( urq, lp ); + break; + case CFG_IFB: + /* IFB can be a security hole */ + if( !capable( CAP_NET_ADMIN )) { + result = -EPERM; + break; + } + + /* Else fall through to the default */ + + case CFG_FW_IDENTITY: // For Hermes-1, this is cached + default: + + /* Verify the user buffer */ + result = verify_area( VERIFY_WRITE, urq->data, urq->len ); + if( result != 0 ) { + DBG_ERROR( DbgInfo, "verify_area(), VERIFY_WRITE FAILED\n" ); + urq->result = UIL_FAILURE; + break; + } + + /* If the requested length is greater than the size of our local + LTV record, try to allocate it from the kernel stack. + Otherwise, we just use our local LTV record. */ + if( urq->len > sizeof( lp->ltvRecord )) { + if(( pLtv = (ltv_t *)kmalloc( urq->len, GFP_KERNEL )) != NULL ) { + ltvAllocated = TRUE; + + /* Copy the command/length information into the new buffer. */ + memcpy( pLtv, &( lp->ltvRecord ), sizeof( hcf_16 ) * 2 ); + } else { + urq->len = sizeof( lp->ltvRecord ); + urq->result = UIL_ERR_LEN; + DBG_ERROR( DbgInfo, "kmalloc FAILED\n" ); + DBG_ERROR( DbgInfo, "UIL_ERR_LEN\n" ); + result = -ENOMEM; + break; + } + } else { + pLtv = &( lp->ltvRecord ); + } + + wl_act_int_off( lp ); + urq->result = hcf_get_info( &( lp->hcfCtx ), (LTVP) pLtv ); + wl_act_int_on( lp ); + + // Copy the LTV into the user's buffer. + //copy_to_user( urq->data, pLtv, urq->len ); + + //if( ltvAllocated ) + //{ + // kfree( pLtv ); + //} + + //urq->result = UIL_SUCCESS; + break; + } + + /* Handle endian conversion of special fields */ + switch( lp->ltvRecord.typ ) { + /* simple int gets just need the first hcf_16 byte flipped */ + case CFG_CNF_PORT_TYPE: + case CFG_CNF_OWN_CHANNEL: + case CFG_CNF_OWN_ATIM_WINDOW: + case CFG_CNF_SYSTEM_SCALE: + case CFG_CNF_MAX_DATA_LEN: + case CFG_CNF_PM_ENABLED: + case CFG_CNF_MCAST_RX: + case CFG_CNF_MAX_SLEEP_DURATION: + case CFG_CNF_HOLDOVER_DURATION: + case CFG_CNF_OWN_DTIM_PERIOD: + case CFG_CNF_MCAST_PM_BUF: + case CFG_CNF_REJECT_ANY: + case CFG_CNF_ENCRYPTION: + case CFG_CNF_AUTHENTICATION: + case CFG_CNF_EXCL_UNENCRYPTED: + case CFG_CNF_INTRA_BSS_RELAY: + case CFG_CNF_MICRO_WAVE: + case CFG_CNF_LOAD_BALANCING: + case CFG_CNF_MEDIUM_DISTRIBUTION: +#ifdef WARP + case CFG_CNF_TX_POW_LVL: + case CFG_CNF_CONNECTION_CNTL: + case CFG_CNF_OWN_BEACON_INTERVAL: // Own Beacon Interval + case CFG_COEXISTENSE_BEHAVIOUR: // Coexistence Behavior + //case CFG_CNF_RX_ALL_GROUP_ADDRESS: +#endif // HERMES25 + case CFG_CREATE_IBSS: + case CFG_RTS_THRH: + case CFG_PROMISCUOUS_MODE: + //case CFG_WAKE_ON_LAN: + case CFG_RTS_THRH0: + case CFG_RTS_THRH1: + case CFG_RTS_THRH2: + case CFG_RTS_THRH3: + case CFG_RTS_THRH4: + case CFG_RTS_THRH5: + case CFG_RTS_THRH6: + case CFG_TX_RATE_CNTL0: + case CFG_TX_RATE_CNTL1: + case CFG_TX_RATE_CNTL2: + case CFG_TX_RATE_CNTL3: + case CFG_TX_RATE_CNTL4: + case CFG_TX_RATE_CNTL5: + case CFG_TX_RATE_CNTL6: + case CFG_TX_KEY_ID: + case CFG_TICK_TIME: + case CFG_MAX_LOAD_TIME: + case CFG_NIC_TEMP_TYPE: + case CFG_PORT_STAT: + case CFG_CUR_TX_RATE: + case CFG_CUR_BEACON_INTERVAL: + case CFG_PROTOCOL_RSP_TIME: + case CFG_CUR_SHORT_RETRY_LIMIT: + case CFG_CUR_LONG_RETRY_LIMIT: + case CFG_MAX_TX_LIFETIME: + case CFG_MAX_RX_LIFETIME: + case CFG_CF_POLLABLE: + case CFG_PRIVACY_OPT_IMPLEMENTED: + //case CFG_CURRENT_REMOTE_RATES: + //case CFG_CURRENT_USED_RATES: + //case CFG_CURRENT_SYSTEM_SCALE: + //case CFG_CURRENT_TX_RATE1: + //case CFG_CURRENT_TX_RATE2: + //case CFG_CURRENT_TX_RATE3: + //case CFG_CURRENT_TX_RATE4: + //case CFG_CURRENT_TX_RATE5: + //case CFG_CURRENT_TX_RATE6: + case CFG_PHY_TYPE: + case CFG_CUR_CHANNEL: + //case CFG_CURRENT_POWER_STATE: + //case CFG_CCAMODE: + // lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[0] ); + // break; + /* name string gets just need the first hcf_16 byte flipped (length of string) */ + case CFG_CNF_OWN_SSID: + case CFG_CNF_OWN_NAME: + //case CNF_DESIRED_SSID: + case CFG_DESIRED_SSID: + case CFG_SCAN_SSID: + case CFG_CUR_SSID: + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[0] ); + break; + /* non-length counted strings need no byte flipping */ + case CFG_CNF_OWN_MAC_ADDR: + /* this case is no longer valid: CFG_CNF_WDS_ADDR */ + case CFG_CNF_WDS_ADDR1: + case CFG_CNF_WDS_ADDR2: + case CFG_CNF_WDS_ADDR3: + case CFG_CNF_WDS_ADDR4: + case CFG_CNF_WDS_ADDR5: + case CFG_CNF_WDS_ADDR6: + case CFG_GROUP_ADDR: + case CFG_NIC_SERIAL_NUMBER: + case CFG_CUR_BSSID: + case CFG_NIC_MAC_ADDR: + case CFG_SUPPORTED_DATA_RATES: /* need to ensure we can treat this as a string */ + break; + //case CFG_CNF_COUNTRY_INFO: /* special case, see page 75 of 022486, Rev C. */ + //case CFG_CURRENT_COUNTRY_INFO: /* special case, see page 101 of 022486, Rev C. */ + /* + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[0] ); + lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[3] ); + + for( i = 4; i < lp->ltvRecord.len; i++ ) { + lp->ltvRecord.u.u16[i] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[i] ); + } + break; + */ + + case CFG_DEFAULT_KEYS: + { + CFG_DEFAULT_KEYS_STRCT *pKeys = (CFG_DEFAULT_KEYS_STRCT *)&lp->ltvRecord.u.u8[0]; + + pKeys[0].len = CNV_INT_TO_LITTLE( pKeys[0].len ); + pKeys[1].len = CNV_INT_TO_LITTLE( pKeys[1].len ); + pKeys[2].len = CNV_INT_TO_LITTLE( pKeys[2].len ); + pKeys[3].len = CNV_INT_TO_LITTLE( pKeys[3].len ); + } + break; + case CFG_CNF_MCAST_RATE: + case CFG_TX_RATE_CNTL: + case CFG_SUPPORTED_RATE_SET_CNTL: // Supported Rate Set Control + case CFG_BASIC_RATE_SET_CNTL: // Basic Rate Set Control + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[0] ); + lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[1] ); + break; + case CFG_DL_BUF: + case CFG_NIC_IDENTITY: + case CFG_COMMS_QUALITY: + case CFG_PCF_INFO: + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[0] ); + lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[1] ); + lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[2] ); + break; + case CFG_FW_IDENTITY: + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[0] ); + lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[1] ); + lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[2] ); + lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[3] ); + break; + //case CFG_HSI_SUP_RANGE: + case CFG_NIC_MFI_SUP_RANGE: + case CFG_NIC_CFI_SUP_RANGE: + case CFG_NIC_PROFILE: + case CFG_FW_SUP_RANGE: + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[0] ); + lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[1] ); + lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[2] ); + lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[3] ); + lp->ltvRecord.u.u16[4] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[4] ); + break; + case CFG_MFI_ACT_RANGES_STA: + case CFG_CFI_ACT_RANGES_STA: + case CFG_CUR_SCALE_THRH: + case CFG_AUTHENTICATION_ALGORITHMS: + for( i = 0; i < ( lp->ltvRecord.len - 1 ); i++ ) { + lp->ltvRecord.u.u16[i] = CNV_INT_TO_LITTLE( lp->ltvRecord.u.u16[i] ); + } + break; + /* done at init time, and endian handled then */ + case CFG_PRI_IDENTITY: + break; + case CFG_MB_INFO: + //wvlanEndianTranslateMailbox( pLtv ); + break; + /* MSF and HCF RIDS */ + case CFG_IFB: + case CFG_DRV_INFO: + case CFG_AP_MODE: + case CFG_ENCRYPT_STRING: + case CFG_COUNTRY_STRING: + case CFG_DRIVER_ENABLE: + case CFG_WOLAS_ENABLE: + default: + break; + } + + // Copy the LTV into the user's buffer. + copy_to_user( urq->data, &( lp->ltvRecord ), urq->len ); + + if( ltvAllocated ) { + kfree( &( lp->ltvRecord )); + } + + urq->result = UIL_SUCCESS; + } else { + urq->result = UIL_FAILURE; + } + } else { + DBG_ERROR( DbgInfo, "UIL_ERR_WRONG_IFB\n" ); + urq->result = UIL_ERR_WRONG_IFB; + } + + DBG_LEAVE( DbgInfo ); + return result; +} // wvlan_uil_get_info +/*============================================================================*/ + + + + + +/******************************************************************************* + * cfg_driver_info() + ******************************************************************************* + * + * DESCRIPTION: + * + * Retrieves driver information. + * + * PARAMETERS: + * + * urq - a pointer to the UIL request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * UIL_SUCCESS + * UIL_ERR_xxx value otherwise + * + ******************************************************************************/ +int cfg_driver_info( struct uilreq *urq, struct wl_private *lp ) +{ + int result = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "cfg_driver_info" ); + DBG_ENTER( DbgInfo ); + + + /* Make sure that user buffer can handle the driver information buffer */ + if( urq->len < sizeof( lp->driverInfo )) { + urq->len = sizeof( lp->driverInfo ); + urq->result = UIL_ERR_LEN; + DBG_LEAVE( DbgInfo ); + return result; + } + + /* Verify the user buffer. */ + result = verify_area( VERIFY_WRITE, urq->data, sizeof( lp->driverInfo )); + if( result != 0 ) { + urq->result = UIL_FAILURE; + DBG_LEAVE( DbgInfo ); + return result; + } + + lp->driverInfo.card_stat = lp->hcfCtx.IFB_CardStat; + + // Copy the driver information into the user's buffer. + urq->result = UIL_SUCCESS; + copy_to_user( urq->data, &( lp->driverInfo ), sizeof( lp->driverInfo )); + + DBG_LEAVE( DbgInfo ); + return result; +} // cfg_driver_info +/*============================================================================*/ + + + + +/******************************************************************************* + * cfg_driver_identity() + ******************************************************************************* + * + * DESCRIPTION: + * + * Retrieves ID information from the card. + * + * PARAMETERS: + * + * urq - a pointer to the UIL request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * UIL_SUCCESS + * UIL_ERR_xxx value otherwise + * + ******************************************************************************/ +int cfg_driver_identity( struct uilreq *urq, struct wl_private *lp ) +{ + int result = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wvlan_driver_identity" ); + DBG_ENTER( DbgInfo ); + + + /* Make sure that user buffer can handle the driver identity structure. */ + if( urq->len < sizeof( lp->driverIdentity )) { + urq->len = sizeof( lp->driverIdentity ); + urq->result = UIL_ERR_LEN; + DBG_LEAVE( DbgInfo ); + return result; + } + + /* Verify the user buffer. */ + result = verify_area( VERIFY_WRITE, urq->data, sizeof( lp->driverIdentity )); + if( result != 0 ) { + urq->result = UIL_FAILURE; + DBG_LEAVE( DbgInfo ); + return result; + } + + /* Copy the driver identity into the user's buffer. */ + urq->result = UIL_SUCCESS; + copy_to_user( urq->data, &( lp->driverIdentity ), sizeof( lp->driverIdentity )); + + DBG_LEAVE( DbgInfo ); + return result; +} // cfg_driver_identity +/*============================================================================*/ + + +#endif /* USE_UIL */ + + +/* If WIRELESS_EXT is not defined, then the functions that follow will not be + included in the build. */ +/* NOTE: Are these still even needed? */ +#ifdef WIRELESS_EXT + + +/******************************************************************************* + * wvlan_set_netname() + ******************************************************************************* + * + * DESCRIPTION: + * + * Set the ESSID of the card. + * + * PARAMETERS: + * + * wrq - a pointer to the wireless request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wvlan_set_netname(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wvlan_set_netname" ); + DBG_ENTER( DbgInfo ); + + wl_lock(lp, &flags); + + memset( lp->NetworkName, 0, sizeof( lp->NetworkName )); + memcpy( lp->NetworkName, extra, wrqu->data.length); + + /* Commit the adapter parameters */ + wl_apply(lp); + wl_unlock(lp, &flags); + + DBG_LEAVE( DbgInfo ); + return ret; +} // wvlan_set_netname +/*============================================================================*/ + + + + +/******************************************************************************* + * wvlan_get_netname() + ******************************************************************************* + * + * DESCRIPTION: + * + * Get the ESSID of the card. + * + * PARAMETERS: + * + * wrq - a pointer to the wireless request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wvlan_get_netname(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + int status = -1; + wvName_t *pName; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wvlan_get_netname" ); + DBG_ENTER( DbgInfo ); + + wl_lock(lp, &flags); + + /* Get the current network name */ + lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 )); + lp->ltvRecord.typ = CFG_CUR_SSID; + + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + + if( status == HCF_SUCCESS ) { + pName = (wvName_t *)&( lp->ltvRecord.u.u32 ); + + memset(extra, '\0', HCF_MAX_NAME_LEN); + wrqu->data.length = pName->length; + + memcpy(extra, pName->name, pName->length); + } else { + ret = -EFAULT; + } + + wl_unlock(lp, &flags); + + DBG_LEAVE( DbgInfo ); + return ret; +} // wvlan_get_netname +/*============================================================================*/ + + + + +/******************************************************************************* + * wvlan_set_station_nickname() + ******************************************************************************* + * + * DESCRIPTION: + * + * Set the card's station nickname. + * + * PARAMETERS: + * + * wrq - a pointer to the wireless request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wvlan_set_station_nickname(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wvlan_set_station_nickname" ); + DBG_ENTER( DbgInfo ); + + wl_lock(lp, &flags); + + memset( lp->StationName, 0, sizeof( lp->StationName )); + + memcpy( lp->StationName, extra, wrqu->data.length); + + /* Commit the adapter parameters */ + wl_apply( lp ); + wl_unlock(lp, &flags); + + DBG_LEAVE( DbgInfo ); + return ret; +} // wvlan_set_station_nickname +/*============================================================================*/ + + + + +/******************************************************************************* + * wvlan_get_station_nickname() + ******************************************************************************* + * + * DESCRIPTION: + * + * Get the card's station nickname. + * + * PARAMETERS: + * + * wrq - a pointer to the wireless request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wvlan_get_station_nickname(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + int status = -1; + wvName_t *pName; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wvlan_get_station_nickname" ); + DBG_ENTER( DbgInfo ); + + wl_lock( lp, &flags ); + + /* Get the current station name */ + lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 )); + lp->ltvRecord.typ = CFG_CNF_OWN_NAME; + + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + + if( status == HCF_SUCCESS ) { + pName = (wvName_t *)&( lp->ltvRecord.u.u32 ); + + memset(extra, '\0', HCF_MAX_NAME_LEN); + wrqu->data.length = pName->length; + memcpy(extra, pName->name, pName->length); + } else { + ret = -EFAULT; + } + + wl_unlock(lp, &flags); + +//out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wvlan_get_station_nickname +/*============================================================================*/ + + + + +/******************************************************************************* + * wvlan_set_porttype() + ******************************************************************************* + * + * DESCRIPTION: + * + * Set the card's porttype + * + * PARAMETERS: + * + * wrq - a pointer to the wireless request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wvlan_set_porttype(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + hcf_16 portType; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wvlan_set_porttype" ); + DBG_ENTER( DbgInfo ); + + wl_lock(lp, &flags); + + /* Validate the new value */ + portType = *((__u32 *)extra); + + if( !(( portType == 1 ) || ( portType == 3 ))) { + ret = -EINVAL; + goto out_unlock; + } + + lp->PortType = portType; + + /* Commit the adapter parameters */ + wl_apply( lp ); + +out_unlock: + wl_unlock(lp, &flags); + +//out: + DBG_LEAVE( DbgInfo ); + return ret; +} + +/*============================================================================*/ + + +/******************************************************************************* + * wvlan_get_porttype() + ******************************************************************************* + * + * DESCRIPTION: + * + * Get the card's porttype + * + * PARAMETERS: + * + * wrq - a pointer to the wireless request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wvlan_get_porttype(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + int status = -1; + hcf_16 *pPortType; + __u32 *pData = (__u32 *)extra; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wvlan_get_porttype" ); + DBG_ENTER( DbgInfo ); + + wl_lock( lp, &flags ); + + /* Get the current port type */ + lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 )); + lp->ltvRecord.typ = CFG_CNF_PORT_TYPE; + + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + + if( status == HCF_SUCCESS ) { + pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 ); + + *pData = CNV_LITTLE_TO_INT( *pPortType ); + } else { + ret = -EFAULT; + } + + wl_unlock(lp, &flags); + +//out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wvlan_get_porttype +/*============================================================================*/ + +#endif // WIRELESS_EXT + + + + +#ifdef USE_RTS +/******************************************************************************* + * wvlan_rts() + ******************************************************************************* + * + * DESCRIPTION: + * + * IOCTL handler for RTS commands + * + * PARAMETERS: + * + * rrq - a pointer to the rts request buffer + * lp - a pointer to the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wvlan_rts( struct rtsreq *rrq, __u32 io_base ) +{ + int ioctl_ret = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wvlan_rts" ); + DBG_ENTER( DbgInfo ); + + + DBG_PRINT( "io_base: 0x%08x\n", io_base ); + + switch( rrq->typ ) { + case WL_IOCTL_RTS_READ: + DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- WL_IOCTL_RTS_READ\n"); + rrq->data[0] = IN_PORT_WORD( io_base + rrq->reg ); + DBG_TRACE( DbgInfo, " reg 0x%04x ==> 0x%04x\n", rrq->reg, CNV_LITTLE_TO_SHORT( rrq->data[0] ) ); + break; + case WL_IOCTL_RTS_WRITE: + DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- WL_IOCTL_RTS_WRITE\n"); + OUT_PORT_WORD( io_base + rrq->reg, rrq->data[0] ); + DBG_TRACE( DbgInfo, " reg 0x%04x <== 0x%04x\n", rrq->reg, CNV_LITTLE_TO_SHORT( rrq->data[0] ) ); + break; + case WL_IOCTL_RTS_BATCH_READ: + DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- WL_IOCTL_RTS_BATCH_READ\n"); + IN_PORT_STRING_16( io_base + rrq->reg, rrq->data, rrq->len ); + DBG_TRACE( DbgInfo, " reg 0x%04x ==> %d bytes\n", rrq->reg, rrq->len * sizeof (__u16 ) ); + break; + case WL_IOCTL_RTS_BATCH_WRITE: + DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- WL_IOCTL_RTS_BATCH_WRITE\n"); + OUT_PORT_STRING_16( io_base + rrq->reg, rrq->data, rrq->len ); + DBG_TRACE( DbgInfo, " reg 0x%04x <== %d bytes\n", rrq->reg, rrq->len * sizeof (__u16) ); + break; + default: + + DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- UNSUPPORTED RTS CODE: 0x%X", rrq->typ ); + ioctl_ret = -EOPNOTSUPP; + break; + } + + DBG_LEAVE( DbgInfo ); + return ioctl_ret; +} // wvlan_rts +/*============================================================================*/ + +#endif /* USE_RTS */ diff --git a/drivers/staging/wlags49_h2/wl_priv.h b/drivers/staging/wlags49_h2/wl_priv.h new file mode 100644 index 0000000000000000000000000000000000000000..9b0254497aa7592c4cc690e825054a3cbd211a98 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_priv.h @@ -0,0 +1,121 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * Header describing information required for the private IOCTL handlers. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +#ifndef __WL_PRIV_H__ +#define __WL_PRIV_H__ + + + + +/******************************************************************************* + * function prototypes + ******************************************************************************/ +#ifdef WIRELESS_EXT + + +int wvlan_set_netname( struct net_device *, struct iw_request_info *, union iwreq_data *, char *extra ); + +int wvlan_get_netname( struct net_device *, struct iw_request_info *, union iwreq_data *, char *extra ); + +int wvlan_set_station_nickname( struct net_device *, struct iw_request_info *, union iwreq_data *, char *extra ); + +int wvlan_get_station_nickname( struct net_device *, struct iw_request_info *, union iwreq_data *, char *extra ); + +int wvlan_set_porttype( struct net_device *, struct iw_request_info *, union iwreq_data *, char *extra ); + +int wvlan_get_porttype( struct net_device *, struct iw_request_info *, union iwreq_data *, char *extra ); + + +#endif // WIRELESS_EXT + + + + +#ifdef USE_UIL + +int wvlan_uil( struct uilreq *urq, struct wl_private *lp ); + +// int wvlan_uil_connect( struct uilreq *urq, struct wl_private *lp ); +// int wvlan_uil_disconnect( struct uilreq *urq, struct wl_private *lp ); +// int wvlan_uil_action( struct uilreq *urq, struct wl_private *lp ); +// int wvlan_uil_block( struct uilreq *urq, struct wl_private *lp ); +// int wvlan_uil_unblock( struct uilreq *urq, struct wl_private *lp ); +// int wvlan_uil_send_diag_msg( struct uilreq *urq, struct wl_private *lp ); +// int wvlan_uil_put_info( struct uilreq *urq, struct wl_private *lp ); +// int wvlan_uil_get_info( struct uilreq *urq, struct wl_private *lp ); + +//int cfg_driver_info( struct uilreq *urq, struct wl_private *lp ); +//int cfg_driver_identity( struct uilreq *urq, struct wl_private *lp ); + +#endif // USE_UIL + + +#ifdef USE_RTS + +int wvlan_rts( struct rtsreq *rrq, __u32 io_base ); +int wvlan_rts_read( __u16 reg, __u16 *val, __u32 io_base ); +int wvlan_rts_write( __u16 reg, __u16 val, __u32 io_base ); +int wvlan_rts_batch_read( struct rtsreq *rrq, __u32 io_base ); +int wvlan_rts_batch_write( struct rtsreq *rrq, __u32 io_base ); + +#endif // USE_RTS + + +#endif // __WL_PRIV_H__ diff --git a/drivers/staging/wlags49_h2/wl_profile.c b/drivers/staging/wlags49_h2/wl_profile.c new file mode 100644 index 0000000000000000000000000000000000000000..715f027a923f672b566237856b659d2e5ac47726 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_profile.c @@ -0,0 +1,1111 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * This file defines routines required to parse configuration parameters + * listed in a config file, if that config file exists. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +/* Only include this file if USE_PROFILE is defined */ +#ifdef USE_PROFILE + + + + +/******************************************************************************* + * constant definitions + ******************************************************************************/ + + +/* Allow support for calling system fcns to parse config file */ +#define __KERNEL_SYSCALLS__ + + + + +/******************************************************************************* + * include files + ******************************************************************************/ +#include + +#include +#include +#include +#include +#include + +#define BIN_DL 1 + +#include +#include +//#include + +#include +#include +#include +#include +#include +#include + + +/******************************************************************************* + * global variables + ******************************************************************************/ + +/* Definition needed to prevent unresolved external in unistd.h */ +static int errno; + +#if DBG +extern p_u32 DebugFlag; +extern dbg_info_t *DbgInfo; +#endif + +int parse_yes_no( char* value ); + + +int parse_yes_no( char* value ) { +int rc = 0; //default to NO for invalid parameters + + if ( strlen( value ) == 1 ) { + if ( ( value[0] | ('Y'^'y') ) == 'y' ) rc = 1; +// } else { +// this should not be debug time info, it is an enduser data entry error ;? +// DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_MICROWAVE_ROBUSTNESS ); + } + return rc; +} // parse_yes_no + + +/******************************************************************************* + * parse_config() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function opens the device's config file and parses the options from + * it, so that it can properly configure itself. If no configuration file + * or configuration is present, then continue to use the options already + * parsed from config.opts or wireless.opts. + * + * PARAMETERS: + * + * dev - a pointer to the device's net_device structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void parse_config( struct net_device *dev ) +{ + int file_desc; +#if 0 // BIN_DL + int rc; + char *cp = NULL; +#endif // BIN_DL + char buffer[MAX_LINE_SIZE]; + char filename[MAX_LINE_SIZE]; + mm_segment_t fs; + struct wl_private *wvlan_config = NULL; + ENCSTRCT sEncryption; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "parse_config" ); + DBG_ENTER( DbgInfo ); + + /* Get the wavelan specific info for this device */ + wvlan_config = (struct wl_private *)dev->priv; + if ( wvlan_config == NULL ) { + DBG_ERROR( DbgInfo, "Wavelan specific info struct not present?\n" ); + return; + } + + /* setup the default encryption string */ + strcpy( wvlan_config->szEncryption, DEF_CRYPT_STR ); + + /* Obtain a user-space process context, storing the original context */ + fs = get_fs( ); + set_fs( get_ds( )); + + /* Determine the filename for this device and attempt to open it */ + sprintf( filename, "%s%s", ROOT_CONFIG_FILENAME, dev->name ); + file_desc = open( filename, O_RDONLY, 0 ); + if ( file_desc != -1 ) { + DBG_TRACE( DbgInfo, "Wireless config file found. Parsing options...\n" ); + + /* Read out the options */ + while( readline( file_desc, buffer )) { + translate_option( buffer, wvlan_config ); + } + /* Close the file */ + close( file_desc ); //;?even if file_desc == -1 ??? + } else { + DBG_TRACE( DbgInfo, "No iwconfig file found for this device; " + "config.opts or wireless.opts will be used\n" ); + } + /* Return to the original context */ + set_fs( fs ); + + /* convert the WEP keys, if read in as key1, key2, type of data */ + if ( wvlan_config->EnableEncryption ) { + memset( &sEncryption, 0, sizeof( sEncryption )); + + wl_wep_decode( CRYPT_CODE, &sEncryption, + wvlan_config->szEncryption ); + + /* the Linux driver likes to use 1-4 for the key IDs, and then + convert to 0-3 when sending to the card. The Windows code + base used 0-3 in the API DLL, which was ported to Linux. For + the sake of the user experience, we decided to keep 0-3 as the + numbers used in the DLL; and will perform the +1 conversion here. + We could have converted the entire Linux driver, but this is + less obtrusive. This may be a "todo" to convert the whole driver */ + sEncryption.wEnabled = wvlan_config->EnableEncryption; + sEncryption.wTxKeyID = wvlan_config->TransmitKeyID - 1; + + memcpy( &sEncryption.EncStr, &wvlan_config->DefaultKeys, + sizeof( CFG_DEFAULT_KEYS_STRCT )); + + memset( wvlan_config->szEncryption, 0, sizeof( wvlan_config->szEncryption )); + + wl_wep_code( CRYPT_CODE, wvlan_config->szEncryption, &sEncryption, + sizeof( sEncryption )); + } + + /* decode the encryption string for the call to wl_commit() */ + wl_wep_decode( CRYPT_CODE, &sEncryption, wvlan_config->szEncryption ); + + wvlan_config->TransmitKeyID = sEncryption.wTxKeyID + 1; + wvlan_config->EnableEncryption = sEncryption.wEnabled; + + memcpy( &wvlan_config->DefaultKeys, &sEncryption.EncStr, + sizeof( CFG_DEFAULT_KEYS_STRCT )); + +#if 0 //BIN_DL + /* Obtain a user-space process context, storing the original context */ + fs = get_fs( ); + set_fs( get_ds( )); + + //;?just to fake something + strcpy(/*wvlan_config->fw_image_*/filename, "/etc/agere/fw.bin" ); + file_desc = open( /*wvlan_config->fw_image_*/filename, 0, 0 ); + if ( file_desc == -1 ) { + DBG_ERROR( DbgInfo, "No image file found\n" ); + } else { + DBG_TRACE( DbgInfo, "F/W image file found\n" ); +#define DHF_ALLOC_SIZE 96000 //just below 96K, let's hope it suffices for now and for the future + cp = (char*)vmalloc( DHF_ALLOC_SIZE ); + if ( cp == NULL ) { + DBG_ERROR( DbgInfo, "error in vmalloc\n" ); + } else { + rc = read( file_desc, cp, DHF_ALLOC_SIZE ); + if ( rc == DHF_ALLOC_SIZE ) { + DBG_ERROR( DbgInfo, "buffer too small, %d\n", DHF_ALLOC_SIZE ); + } else if ( rc > 0 ) { + DBG_TRACE( DbgInfo, "read O.K.: %d bytes %.12s\n", rc, cp ); + rc = read( file_desc, &cp[rc], 1 ); + if ( rc == 0 ) { + DBG_TRACE( DbgInfo, "no more to read\n" ); + } + } + if ( rc != 0 ) { + DBG_ERROR( DbgInfo, "file not read in one swoop or other error"\ + ", give up, too complicated, rc = %0X\n", rc ); + } + vfree( cp ); + } + close( file_desc ); + } + set_fs( fs ); /* Return to the original context */ +#endif // BIN_DL + + DBG_LEAVE( DbgInfo ); + return; +} // parse_config + +/******************************************************************************* + * readline() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function reads in data from a given file one line at a time, + * converting the detected newline character '\n' to a null '\0'. Note that + * the file descriptor must be valid before calling this function. + * + * PARAMETERS: + * + * filedesc - the file descriptor for the open configuration file + * buffer - a buffer pointer, passed in by the caller, to which the + * line will be stored. + * + * RETURNS: + * + * the number of bytes read + * -1 on error + * + ******************************************************************************/ +int readline( int filedesc, char *buffer ) +{ + int result = -1; + int bytes_read = 0; + /*------------------------------------------------------------------------*/ + + /* Make sure the file descriptor is good */ + if ( filedesc != -1 ) { + /* Read in from the file byte by byte until a newline is reached */ + while(( result = read( filedesc, &buffer[bytes_read], 1 )) == 1 ) { + if ( buffer[bytes_read] == '\n' ) { + buffer[bytes_read] = '\0'; + bytes_read++; + break; + } + bytes_read++; + } + } + + /* Return the number of bytes read */ + if ( result == -1 ) { + return result; + } else { + return bytes_read; + } +} // readline +/*============================================================================*/ + +/******************************************************************************* + * translate_option() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function takes a line read in from the config file and parses out + * the key/value pairs. It then determines which key has been parsed and sets + * the card's configuration based on the value given. + * + * PARAMETERS: + * + * buffer - a buffer containing a line to translate + * config - a pointer to the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void translate_option( char *buffer, struct wl_private *lp ) +{ + unsigned int value_convert = 0; + int string_length = 0; + char *key = NULL; + char *value = NULL; + u_char mac_value[ETH_ALEN]; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "translate_option" ); + + if ( buffer == NULL || lp == NULL ) { + DBG_ERROR( DbgInfo, "Config file buffer and/or wavelan buffer ptr NULL\n" ); + return; + } + + ParseConfigLine( buffer, &key, &value ); + + if ( key == NULL || value == NULL ) { + return; + } + + /* Determine which key it is and perform the appropriate action */ + + /* Configuration parameters used in all scenarios */ +#if DBG + /* handle DebugFlag as early as possible so it starts its influence as early + * as possible + */ + if ( strcmp( key, PARM_NAME_DEBUG_FLAG ) == 0 ) { + if ( DebugFlag == ~0 ) { //if DebugFlag is not specified on the command line + if ( DbgInfo->DebugFlag == 0 ) { /* if pc_debug did not set DebugFlag (i.e.pc_debug is + * not specified or specified outside the 4-8 range + */ + DbgInfo->DebugFlag |= DBG_DEFAULTS; + } + } else { + DbgInfo->DebugFlag = wl_atoi( value ); //;?DebugFlag; + } + DbgInfo->DebugFlag = wl_atoi( value ); //;?Delete ASAP + } +#endif /* DBG */ + if ( strcmp( key, PARM_NAME_AUTH_KEY_MGMT_SUITE ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_AUTH_KEY_MGMT_SUITE, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_AUTH_KEY_MGMT_SUITE ) || ( value_convert <= PARM_MAX_AUTH_KEY_MGMT_SUITE )) { + lp->AuthKeyMgmtSuite = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_AUTH_KEY_MGMT_SUITE ); + } + } + else if ( strcmp( key, PARM_NAME_BRSC_2GHZ ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_BRSC_2GHZ, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_BRSC ) || ( value_convert <= PARM_MAX_BRSC )) { + lp->brsc[0] = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invaid; will be ignored\n", PARM_NAME_BRSC_2GHZ ); + } + } + else if ( strcmp( key, PARM_NAME_BRSC_5GHZ ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_BRSC_5GHZ, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_BRSC ) || ( value_convert <= PARM_MAX_BRSC )) { + lp->brsc[1] = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invaid; will be ignored\n", PARM_NAME_BRSC_5GHZ ); + } + } + else if (( strcmp( key, PARM_NAME_DESIRED_SSID ) == 0 ) || ( strcmp( key, PARM_NAME_OWN_SSID ) == 0 )) { + DBG_TRACE( DbgInfo, "SSID, value: %s\n", value ); + + memset( lp->NetworkName, 0, ( PARM_MAX_NAME_LEN + 1 )); + + /* Make sure the value isn't too long */ + string_length = strlen( value ); + if ( string_length > PARM_MAX_NAME_LEN ) { + DBG_WARNING( DbgInfo, "SSID too long; will be truncated\n" ); + string_length = PARM_MAX_NAME_LEN; + } + + memcpy( lp->NetworkName, value, string_length ); + } +#if 0 + else if ( strcmp( key, PARM_NAME_DOWNLOAD_FIRMWARE ) == 0 ) { + DBG_TRACE( DbgInfo, "DOWNLOAD_FIRMWARE, value: %s\n", value ); + memset( lp->fw_image_filename, 0, ( MAX_LINE_SIZE + 1 )); + /* Make sure the value isn't too long */ + string_length = strlen( value ); + if ( string_length > MAX_LINE_SIZE ) { + DBG_WARNING( DbgInfo, "F/W image file name too long; will be ignored\n" ); + } else { + memcpy( lp->fw_image_filename, value, string_length ); + } + } +#endif + else if ( strcmp( key, PARM_NAME_ENABLE_ENCRYPTION ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_ENABLE_ENCRYPTION, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_ENABLE_ENCRYPTION ) && ( value_convert <= PARM_MAX_ENABLE_ENCRYPTION )) { + lp->EnableEncryption = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_ENABLE_ENCRYPTION ); + } + } + else if ( strcmp( key, PARM_NAME_ENCRYPTION ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_ENCRYPTION, value ); + + memset( lp->szEncryption, 0, sizeof( lp->szEncryption )); + + /* Make sure the value isn't too long */ + string_length = strlen( value ); + if ( string_length > sizeof( lp->szEncryption ) ) { + DBG_WARNING( DbgInfo, "%s too long; will be truncated\n", PARM_NAME_ENCRYPTION ); + string_length = sizeof( lp->szEncryption ); + } + + memcpy( lp->szEncryption, value, string_length ); + } + else if ( strcmp( key, PARM_NAME_KEY1 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_KEY1, value ); + + if ( is_valid_key_string( value )) { + memset( lp->DefaultKeys.key[0].key, 0, MAX_KEY_SIZE ); + + key_string2key( value, &lp->DefaultKeys.key[0] ); + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_KEY1 ); + } + } + else if ( strcmp( key, PARM_NAME_KEY2 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_KEY2, value ); + + if ( is_valid_key_string( value )) { + memset( lp->DefaultKeys.key[1].key, 0, MAX_KEY_SIZE ); + + key_string2key( value, &lp->DefaultKeys.key[1] ); + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_KEY2 ); + } + } + else if ( strcmp( key, PARM_NAME_KEY3 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_KEY3, value ); + + if ( is_valid_key_string( value )) { + memset( lp->DefaultKeys.key[2].key, 0, MAX_KEY_SIZE ); + + key_string2key( value, &lp->DefaultKeys.key[2] ); + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_KEY3 ); + } + } + else if ( strcmp( key, PARM_NAME_KEY4 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_KEY4, value ); + + if ( is_valid_key_string( value )) { + memset( lp->DefaultKeys.key[3].key, 0, MAX_KEY_SIZE ); + + key_string2key( value, &lp->DefaultKeys.key[3] ); + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_KEY4 ); + } + } + /* New Parameters for WARP */ + else if ( strcmp( key, PARM_NAME_LOAD_BALANCING ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_LOAD_BALANCING, value ); + lp->loadBalancing = parse_yes_no(value); + } + else if ( strcmp( key, PARM_NAME_MEDIUM_DISTRIBUTION ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_MEDIUM_DISTRIBUTION, value ); + lp->mediumDistribution = parse_yes_no(value); + } + else if ( strcmp( key, PARM_NAME_MICROWAVE_ROBUSTNESS) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_MICROWAVE_ROBUSTNESS, value ); + lp->MicrowaveRobustness = parse_yes_no(value); + } + else if ( strcmp( key, PARM_NAME_MULTICAST_RATE ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_MULTICAST_RATE, value ); + + value_convert = wl_atoi( value ); + + if (( value_convert >= PARM_MIN_MULTICAST_RATE ) && ( value_convert <= PARM_MAX_MULTICAST_RATE )) { + lp->MulticastRate[0] = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_MULTICAST_RATE ); + } + } + else if ( strcmp( key, PARM_NAME_OWN_CHANNEL ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_CHANNEL, value ); + + value_convert = wl_atoi( value ); + if ( wl_is_a_valid_chan( value_convert )) { + if ( value_convert > 14 ) { + value_convert = value_convert | 0x100; + } + lp->Channel = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_OWN_CHANNEL ); + } + } + else if ( strcmp( key, PARM_NAME_OWN_NAME ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_NAME, value ); + + memset( lp->StationName, 0, ( PARM_MAX_NAME_LEN + 1 )); + + /* Make sure the value isn't too long */ + string_length = strlen( value ); + if ( string_length > PARM_MAX_NAME_LEN ) { + DBG_WARNING( DbgInfo, "%s too long; will be truncated\n", PARM_NAME_OWN_NAME ); + string_length = PARM_MAX_NAME_LEN; + } + + memcpy( lp->StationName, value, string_length ); + } + else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) { + lp->RTSThreshold = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_RTS_THRESHOLD ); + } + } + else if ( strcmp( key, PARM_NAME_SRSC_2GHZ ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_SRSC_2GHZ, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_SRSC ) || ( value_convert <= PARM_MAX_SRSC )) { + lp->srsc[0] = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invaid; will be ignored\n", PARM_NAME_SRSC_2GHZ ); + } + } + else if ( strcmp( key, PARM_NAME_SRSC_5GHZ ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_SRSC_5GHZ, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_SRSC ) || ( value_convert <= PARM_MAX_SRSC )) { + lp->srsc[1] = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invaid; will be ignored\n", PARM_NAME_SRSC_5GHZ ); + } + } + else if ( strcmp( key, PARM_NAME_SYSTEM_SCALE ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_SYSTEM_SCALE, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_SYSTEM_SCALE ) && ( value_convert <= PARM_MAX_SYSTEM_SCALE )) { + lp->DistanceBetweenAPs = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_SYSTEM_SCALE ); + } + } + else if ( strcmp( key, PARM_NAME_TX_KEY ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_KEY, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_TX_KEY ) && ( value_convert <= PARM_MAX_TX_KEY )) { + lp->TransmitKeyID = wl_atoi( value ); + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_KEY ); + } + } + else if ( strcmp( key, PARM_NAME_TX_RATE ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) { + lp->TxRateControl[0] = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_RATE ); + } + } + else if ( strcmp( key, PARM_NAME_TX_POW_LEVEL ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_POW_LEVEL, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_TX_POW_LEVEL ) || ( value_convert <= PARM_MAX_TX_POW_LEVEL )) { + lp->txPowLevel = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_POW_LEVEL ); + } + } + + /* Need to add? : Country code, Short/Long retry */ + + /* Configuration parameters specific to STA mode */ +#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA +//;?seems reasonable that even an AP-only driver could afford this small additional footprint + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) { + //;?should we return an error status in AP mode + if ( strcmp( key, PARM_NAME_PORT_TYPE ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_PORT_TYPE, value ); + + value_convert = wl_atoi( value ); + if (( value_convert == PARM_MIN_PORT_TYPE ) || ( value_convert == PARM_MAX_PORT_TYPE )) { + lp->PortType = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_PORT_TYPE ); + } + } + else if ( strcmp( key, PARM_NAME_PM_ENABLED ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_PM_ENABLED, value ); + value_convert = wl_atoi( value ); + /* ;? how about wl_main.c containing + * VALID_PARAM( PARM_PM_ENABLED <= WVLAN_PM_STATE_STANDARD || + * ( PARM_PM_ENABLED & 0x7FFF ) <= WVLAN_PM_STATE_STANDARD ); + */ + if ( ( value_convert & 0x7FFF ) <= PARM_MAX_PM_ENABLED) { + lp->PMEnabled = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_PM_ENABLED ); + //;?this is a data entry error, hence not a DBG_WARNING + } + } + else if ( strcmp( key, PARM_NAME_CREATE_IBSS ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_CREATE_IBSS, value ); + lp->CreateIBSS = parse_yes_no(value); + } + else if ( strcmp( key, PARM_NAME_MULTICAST_RX ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_MULTICAST_RX, value ); + lp->MulticastReceive = parse_yes_no(value); + } + else if ( strcmp( key, PARM_NAME_MAX_SLEEP ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_MAX_SLEEP, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= 0 ) && ( value_convert <= 65535 )) { + lp->MaxSleepDuration = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_MAX_SLEEP ); + } + } + else if ( strcmp( key, PARM_NAME_NETWORK_ADDR ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_NETWORK_ADDR, value ); + + if ( parse_mac_address( value, mac_value ) == ETH_ALEN ) { + memcpy( lp->MACAddress, mac_value, ETH_ALEN ); + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_NETWORK_ADDR ); + } + } + else if ( strcmp( key, PARM_NAME_AUTHENTICATION ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_AUTHENTICATION, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_AUTHENTICATION ) && ( value_convert <= PARM_MAX_AUTHENTICATION )) { + lp->authentication = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_AUTHENTICATION ); + } + } + else if ( strcmp( key, PARM_NAME_OWN_ATIM_WINDOW ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_ATIM_WINDOW, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_OWN_ATIM_WINDOW ) && ( value_convert <= PARM_MAX_OWN_ATIM_WINDOW )) { + lp->atimWindow = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_OWN_ATIM_WINDOW ); + } + } + else if ( strcmp( key, PARM_NAME_PM_HOLDOVER_DURATION ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_PM_HOLDOVER_DURATION, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_PM_HOLDOVER_DURATION ) && ( value_convert <= PARM_MAX_PM_HOLDOVER_DURATION )) { + lp->holdoverDuration = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_PM_HOLDOVER_DURATION ); + } + } + else if ( strcmp( key, PARM_NAME_PROMISCUOUS_MODE ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_PROMISCUOUS_MODE, value ); + lp->promiscuousMode = parse_yes_no(value); + } + else if ( strcmp( key, PARM_NAME_CONNECTION_CONTROL ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_CONNECTION_CONTROL, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_CONNECTION_CONTROL ) && ( value_convert <= PARM_MAX_CONNECTION_CONTROL )) { + lp->connectionControl = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_CONNECTION_CONTROL ); + } + } + + /* Need to add? : Probe Data Rate */ + } +#endif /* (HCF_TYPE) & HCF_TYPE_STA */ + + /* Configuration parameters specific to AP mode */ +#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP + //;?should we restore this to allow smaller memory footprint + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { + if ( strcmp( key, PARM_NAME_OWN_DTIM_PERIOD ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_DTIM_PERIOD, value ); + + value_convert = wl_atoi( value ); + if ( value_convert >= PARM_MIN_OWN_DTIM_PERIOD ) { + lp->DTIMPeriod = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_OWN_DTIM_PERIOD ); + } + } + else if ( strcmp( key, PARM_NAME_REJECT_ANY ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_REJECT_ANY, value ); + lp->RejectAny = parse_yes_no(value); + } + else if ( strcmp( key, PARM_NAME_EXCLUDE_UNENCRYPTED ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_EXCLUDE_UNENCRYPTED, value ); + lp->ExcludeUnencrypted = parse_yes_no(value); + } + else if ( strcmp( key, PARM_NAME_MULTICAST_PM_BUFFERING ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_MULTICAST_PM_BUFFERING, value ); + lp->ExcludeUnencrypted = parse_yes_no(value); + } + else if ( strcmp( key, PARM_NAME_INTRA_BSS_RELAY ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_INTRA_BSS_RELAY, value ); + lp->ExcludeUnencrypted = parse_yes_no(value); + } + else if ( strcmp( key, PARM_NAME_OWN_BEACON_INTERVAL ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_BEACON_INTERVAL, value ); + + value_convert = wl_atoi( value ); + if ( value_convert >= PARM_MIN_OWN_BEACON_INTERVAL ) { + lp->ownBeaconInterval = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_OWN_BEACON_INTERVAL ); + } + } + else if ( strcmp( key, PARM_NAME_COEXISTENCE ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_COEXISTENCE, value ); + + value_convert = wl_atoi( value ); + if ( value_convert >= PARM_MIN_COEXISTENCE ) { + lp->coexistence = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_COEXISTENCE ); + } + } + +#ifdef USE_WDS + else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD1 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD1, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) { + lp->wds_port[0].rtsThreshold = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_RTS_THRESHOLD1 ); + } + } + else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD2 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD2, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) { + lp->wds_port[1].rtsThreshold = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_RTS_THRESHOLD2 ); + } + } + else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD3 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD3, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) { + lp->wds_port[2].rtsThreshold = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_RTS_THRESHOLD3 ); + } + } + else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD4 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD4, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) { + lp->wds_port[3].rtsThreshold = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_RTS_THRESHOLD4 ); + } + } + else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD5 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD5, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) { + lp->wds_port[4].rtsThreshold = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_RTS_THRESHOLD5 ); + } + } + else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD6 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD6, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) { + lp->wds_port[5].rtsThreshold = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_RTS_THRESHOLD6 ); + } + } + else if ( strcmp( key, PARM_NAME_TX_RATE1 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE1, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) { + lp->wds_port[0].txRateCntl = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_RATE1 ); + } + } + else if ( strcmp( key, PARM_NAME_TX_RATE2 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE2, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) { + lp->wds_port[1].txRateCntl = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_RATE2 ); + } + } + else if ( strcmp( key, PARM_NAME_TX_RATE3 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE3, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) { + lp->wds_port[2].txRateCntl = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_RATE3 ); + } + } + else if ( strcmp( key, PARM_NAME_TX_RATE4 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE4, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) { + lp->wds_port[3].txRateCntl = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_RATE4 ); + } + } + else if ( strcmp( key, PARM_NAME_TX_RATE5 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE5, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) { + lp->wds_port[4].txRateCntl = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_RATE5 ); + } + } + else if ( strcmp( key, PARM_NAME_TX_RATE6 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE6, value ); + + value_convert = wl_atoi( value ); + if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) { + lp->wds_port[5].txRateCntl = value_convert; + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_RATE6 ); + } + } + else if ( strcmp( key, PARM_NAME_WDS_ADDRESS1 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_WDS_ADDRESS1, value ); + + if ( parse_mac_address( value, mac_value ) == ETH_ALEN ) { + memcpy( lp->wds_port[0].wdsAddress, mac_value, ETH_ALEN ); + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_WDS_ADDRESS1 ); + } + } + else if ( strcmp( key, PARM_NAME_WDS_ADDRESS2 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_WDS_ADDRESS2, value ); + + if ( parse_mac_address( value, mac_value ) == ETH_ALEN ) { + memcpy( lp->wds_port[1].wdsAddress, mac_value, ETH_ALEN ); + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_WDS_ADDRESS2 ); + } + } + else if ( strcmp( key, PARM_NAME_WDS_ADDRESS3 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_WDS_ADDRESS3, value ); + + if ( parse_mac_address( value, mac_value ) == ETH_ALEN ) { + memcpy( lp->wds_port[2].wdsAddress, mac_value, ETH_ALEN ); + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_WDS_ADDRESS3 ); + } + } + else if ( strcmp( key, PARM_NAME_WDS_ADDRESS4 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_WDS_ADDRESS4, value ); + + if ( parse_mac_address( value, mac_value ) == ETH_ALEN ) { + memcpy( lp->wds_port[3].wdsAddress, mac_value, ETH_ALEN ); + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_WDS_ADDRESS4 ); + } + } + else if ( strcmp( key, PARM_NAME_WDS_ADDRESS5 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_WDS_ADDRESS5, value ); + + if ( parse_mac_address( value, mac_value ) == ETH_ALEN ) { + memcpy( lp->wds_port[4].wdsAddress, mac_value, ETH_ALEN ); + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_WDS_ADDRESS5 ); + } + } + else if ( strcmp( key, PARM_NAME_WDS_ADDRESS6 ) == 0 ) { + DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_WDS_ADDRESS6, value ); + + if ( parse_mac_address( value, mac_value ) == ETH_ALEN ) { + memcpy( lp->wds_port[5].wdsAddress, mac_value, ETH_ALEN ); + } else { + DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_WDS_ADDRESS6 ); + } + } +#endif /* USE_WDS */ + } +#endif /* (HCF_TYPE) & HCF_TYPE_AP */ + + return; +} // translate_option +/*============================================================================*/ + +/******************************************************************************* + * parse_mac_address() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function will parse a mac address string and convert it to a byte + * array. + * + * PARAMETERS: + * + * value - the MAC address, represented as a string + * byte_array - the MAC address, represented as a byte array of length + * ETH_ALEN + * + * RETURNS: + * + * The number of bytes in the final MAC address, should equal to ETH_ALEN. + * + ******************************************************************************/ +int parse_mac_address( char *value, u_char *byte_array ) +{ + int value_offset = 0; + int array_offset = 0; + int field_offset = 0; + char byte_field[3]; + /*------------------------------------------------------------------------*/ + + memset( byte_field, '\0', 3 ); + + while( value[value_offset] != '\0' ) { + /* Skip over the colon chars seperating the bytes, if they exist */ + if ( value[value_offset] == ':' ) { + value_offset++; + continue; + } + + byte_field[field_offset] = value[value_offset]; + field_offset++; + value_offset++; + + /* Once the byte_field is filled, convert it and store it */ + if ( field_offset == 2 ) { + byte_field[field_offset] = '\0'; + byte_array[array_offset] = simple_strtoul( byte_field, NULL, 16 ); + field_offset = 0; + array_offset++; + } + } + + /* Use the array_offset as a check; 6 bytes should be written to the + byte_array */ + return array_offset; +} // parse_mac_address +/*============================================================================*/ + +/******************************************************************************* + * ParseConfigLine() + ******************************************************************************* + * + * DESCRIPTION: + * + * Parses a line from the configuration file into an L-val and an R-val, + * representing a key/value pair. + * + * PARAMETERS: + * + * pszLine - the line from the config file to parse + * ppszLVal - the resulting L-val (Key) + * ppszRVal - the resulting R-val (Value) + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void ParseConfigLine( char *pszLine, char **ppszLVal, char **ppszRVal ) +{ + int i; + int size; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "ParseConfigLine" ); + DBG_ENTER( DbgInfo ); + + /* get a snapshot of our string size */ + size = strlen( pszLine ); + *ppszLVal = NULL; + *ppszRVal = NULL; + + if ( pszLine[0] != '#' && /* skip the line if it is a comment */ + pszLine[0] != '\n'&& /* if it's an empty UNIX line, do nothing */ + !( pszLine[0] == '\r' && pszLine[1] == '\n' ) /* if it's an empty MS-DOS line, do nothing */ + ) { + /* advance past any whitespace, and assign the L-value */ + for( i = 0; i < size; i++ ) { + if ( pszLine[i] != ' ' ) { + *ppszLVal = &pszLine[i]; + break; + } + } + /* advance to the end of the l-value*/ + for( i++; i < size; i++ ) { + if ( pszLine[i] == ' ' || pszLine[i] == '=' ) { + pszLine[i] = '\0'; + break; + } + } + /* make any whitespace and the equal sign a NULL character, and + advance to the R-Value */ + for( i++; i < size; i++ ) { + if ( pszLine[i] == ' ' || pszLine[i] == '=' ) { + pszLine[i] = '\0'; + continue; + } + *ppszRVal = &pszLine[i]; + break; + } + /* make the line ending character(s) a NULL */ + for( i++; i < size; i++ ) { + if ( pszLine[i] == '\n' ) { + pszLine[i] = '\0'; + } + if (( pszLine[i] == '\r' ) && ( pszLine[i+1] == '\n' )) { + pszLine[i] = '\0'; + } + } + } + DBG_LEAVE( DbgInfo ); +} // ParseConfigLine +/*============================================================================*/ + +#endif // USE_PROFILE diff --git a/drivers/staging/wlags49_h2/wl_profile.h b/drivers/staging/wlags49_h2/wl_profile.h new file mode 100644 index 0000000000000000000000000000000000000000..81db8e8c6ba873448070a0c64f2f0d210bc70823 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_profile.h @@ -0,0 +1,87 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * Header describing information required for the config parsing routines. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +#ifndef __WL_PROFILE_H__ +#define __WL_PROFILE_H__ + + + + +/******************************************************************************* + * constant definitions + ******************************************************************************/ +#define ROOT_CONFIG_FILENAME "/etc/agere/iwconfig-" + + +/******************************************************************************* + * function prototypes + ******************************************************************************/ +void parse_config( struct net_device *dev ); + +int readline( int filedesc, char *buffer ); + +void translate_option( char *buffer, struct wl_private *lp ); + +int parse_mac_address( char *value, u_char *byte_array ); + +void ParseConfigLine( char *pszLine, char **ppszLVal, char **ppszRVal ); + + +#endif // __WL_PROFILE_H__ diff --git a/drivers/staging/wlags49_h2/wl_sysfs.c b/drivers/staging/wlags49_h2/wl_sysfs.c new file mode 100644 index 0000000000000000000000000000000000000000..864e01a736c87c396eaccd1f741f80c8f4404527 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_sysfs.c @@ -0,0 +1,135 @@ +/* + * ex: sw=4 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static inline int dev_isalive(const struct net_device *dev) +{ + return dev->reg_state == NETREG_REGISTERED; +} + +/* + * empirically even if tallies are defined as 32 bits entities, only + * high 16 bits are relevant; low half is always zero. It means tallies + * are pretty much useless for traffic counting but at least give overview + * about where error come from + */ +static ssize_t show_tallies(struct device *d, struct device_attribute *attr, + char *buf) +{ + struct net_device *dev = to_net_dev(d); + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + CFG_HERMES_TALLIES_STRCT tallies; + ssize_t ret = -EINVAL; + + read_lock(&dev_base_lock); + if (dev_isalive(dev)) { + wl_lock(lp, &flags); + + if ((ret = wl_get_tallies(lp, &tallies)) == 0) { + wl_unlock(lp, &flags); + ret = snprintf(buf, PAGE_SIZE, + "TxUnicastFrames: %u\n" + "TxMulticastFrames: %u\n" + "TxFragments: %u\n" + "TxUnicastOctets: %u\n" + "TxMulticastOctets: %u\n" + "TxDeferredTransmissions: %u\n" + "TxSingleRetryFrames: %u\n" + "TxMultipleRetryFrames: %u\n" + "TxRetryLimitExceeded: %u\n" + "TxDiscards: %u\n" + "RxUnicastFrames: %u\n" + "RxMulticastFrames: %u\n" + "RxFragments: %u\n" + "RxUnicastOctets: %u\n" + "RxMulticastOctets: %u\n" + "RxFCSErrors: %u\n" + "RxDiscardsNoBuffer: %u\n" + "TxDiscardsWrongSA: %u\n" + "RxWEPUndecryptable: %u\n" + "RxMsgInMsgFragments: %u\n" + "RxMsgInBadMsgFragments: %u\n" + "RxDiscardsWEPICVError: %u\n" + "RxDiscardsWEPExcluded: %u\n" + , + (unsigned int)tallies.TxUnicastFrames, + (unsigned int)tallies.TxMulticastFrames, + (unsigned int)tallies.TxFragments, + (unsigned int)tallies.TxUnicastOctets, + (unsigned int)tallies.TxMulticastOctets, + (unsigned int)tallies.TxDeferredTransmissions, + (unsigned int)tallies.TxSingleRetryFrames, + (unsigned int)tallies.TxMultipleRetryFrames, + (unsigned int)tallies.TxRetryLimitExceeded, + (unsigned int)tallies.TxDiscards, + (unsigned int)tallies.RxUnicastFrames, + (unsigned int)tallies.RxMulticastFrames, + (unsigned int)tallies.RxFragments, + (unsigned int)tallies.RxUnicastOctets, + (unsigned int)tallies.RxMulticastOctets, + (unsigned int)tallies.RxFCSErrors, + (unsigned int)tallies.RxDiscardsNoBuffer, + (unsigned int)tallies.TxDiscardsWrongSA, + (unsigned int)tallies.RxWEPUndecryptable, + (unsigned int)tallies.RxMsgInMsgFragments, + (unsigned int)tallies.RxMsgInBadMsgFragments, + (unsigned int)tallies.RxDiscardsWEPICVError, + (unsigned int)tallies.RxDiscardsWEPExcluded); + } else { + wl_unlock( lp, &flags ); + } + } + + read_unlock(&dev_base_lock); + return ret; +} + +static DEVICE_ATTR(tallies, S_IRUGO, show_tallies, NULL); + +static struct attribute *wlags_attrs[] = { + &dev_attr_tallies.attr, + NULL +}; + +static struct attribute_group wlags_group = { + .name = "wlags", + .attrs = wlags_attrs, +}; + +void register_wlags_sysfs(struct net_device *net) +{ + struct device *dev = &(net->dev); + struct wl_private *lp = wl_priv(net); + + lp->sysfsCreated = sysfs_create_group(&dev->kobj, &wlags_group); +} + +void unregister_wlags_sysfs(struct net_device *net) +{ + struct device *dev = &(net->dev); + struct wl_private *lp = wl_priv(net); + + if (lp->sysfsCreated) + sysfs_remove_group(&dev->kobj, &wlags_group); +} diff --git a/drivers/staging/wlags49_h2/wl_sysfs.h b/drivers/staging/wlags49_h2/wl_sysfs.h new file mode 100644 index 0000000000000000000000000000000000000000..6d96d03cf4909877f89936f1571b6efadfad3665 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_sysfs.h @@ -0,0 +1,7 @@ +#ifdef CONFIG_SYSFS +extern void register_wlags_sysfs(struct net_device *); +extern void unregister_wlags_sysfs(struct net_device *); +#else +static void register_wlags_sysfs(struct net_device *) { return; }; +static void unregister_wlags_sysfs(struct net_device *) { return; }; +#endif diff --git a/drivers/staging/wlags49_h2/wl_util.c b/drivers/staging/wlags49_h2/wl_util.c new file mode 100644 index 0000000000000000000000000000000000000000..ac1e7f38f98274e67131fa6ec0c23cb07eadc649 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_util.c @@ -0,0 +1,1587 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * This file defines misc utility functions. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +/******************************************************************************* + * include 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 + + + +/******************************************************************************* + * global variables + ******************************************************************************/ + +/* A matrix which maps channels to frequencies */ +#define MAX_CHAN_FREQ_MAP_ENTRIES 50 +static const long chan_freq_list[][MAX_CHAN_FREQ_MAP_ENTRIES] = +{ + {1,2412}, + {2,2417}, + {3,2422}, + {4,2427}, + {5,2432}, + {6,2437}, + {7,2442}, + {8,2447}, + {9,2452}, + {10,2457}, + {11,2462}, + {12,2467}, + {13,2472}, + {14,2484}, + {36,5180}, + {40,5200}, + {44,5220}, + {48,5240}, + {52,5260}, + {56,5280}, + {60,5300}, + {64,5320}, + {149,5745}, + {153,5765}, + {157,5785}, + {161,5805} +}; + +#if DBG +extern dbg_info_t *DbgInfo; +#endif /* DBG */ + + + + +/******************************************************************************* + * dbm() + ******************************************************************************* + * + * DESCRIPTION: + * + * Return an energy value in dBm. + * + * PARAMETERS: + * + * value - the energy value to be converted + * + * RETURNS: + * + * the value in dBm + * + ******************************************************************************/ +int dbm( int value ) +{ + /* Truncate the value to be between min and max. */ + if( value < HCF_MIN_SIGNAL_LEVEL ) + value = HCF_MIN_SIGNAL_LEVEL; + + if( value > HCF_MAX_SIGNAL_LEVEL ) + value = HCF_MAX_SIGNAL_LEVEL; + + /* Return the energy value in dBm. */ + return ( value - HCF_0DBM_OFFSET ); +} // dbm +/*============================================================================*/ + + + + +/******************************************************************************* + * percent() + ******************************************************************************* + * + * DESCRIPTION: + * + * Return a value as a percentage of min to max. + * + * PARAMETERS: + * + * value - the value in question + * min - the minimum range value + * max - the maximum range value + * + * RETURNS: + * + * the percentage value + * + ******************************************************************************/ +int percent( int value, int min, int max ) +{ + /* Truncate the value to be between min and max. */ + if( value < min ) + value = min; + + if( value > max ) + value = max; + + /* Return the value as a percentage of min to max. */ + return ((( value - min ) * 100 ) / ( max - min )); +} // percent +/*============================================================================*/ + + + + +/******************************************************************************* + * is_valid_key_string() + ******************************************************************************* + * + * DESCRIPTION: + * + * Checks to determine if the WEP key string is valid + * + * PARAMETERS: + * + * s - the string in question + * + * RETURNS: + * + * non-zero if the string contains a valid key + * + ******************************************************************************/ +int is_valid_key_string( char *s ) +{ + int l; + int i; + /*------------------------------------------------------------------------*/ + + + l = strlen( s ); + + /* 0x followed by 5 or 13 hexadecimal digit pairs is valid */ + if( s[0] == '0' && ( s[1] == 'x' || s[1] == 'X' )) { + if( l == 12 || l == 28 ) { + for( i = 2; i < l; i++ ) { + if( !isxdigit( s[i] )) + return 0; + } + + return 1; + } else { + return 0; + } + } + + /* string with 0, 5, or 13 characters is valid */ + else + { + return( l == 0 || l == 5 || l == 13 ); + } +} // is_valid_key_string +/*============================================================================*/ + + + + +/******************************************************************************* + * hexdigit2int() + ******************************************************************************* + * + * DESCRIPTION: + * + * Converts a hexadecimal digit character to an integer + * + * PARAMETERS: + * + * c - the hexadecimal digit character + * + * RETURNS: + * + * the converted integer + * + ******************************************************************************/ +int hexdigit2int( char c ) +{ + if( c >= '0' && c <= '9' ) + return c - '0'; + + if( c >= 'A' && c <= 'F' ) + return c - 'A' + 10; + + if( c >= 'a' && c <= 'f' ) + return c - 'a' + 10; + + return 0; +} // hexdigit2int +/*============================================================================*/ + + + + +/******************************************************************************* + * key_string2key() + ******************************************************************************* + * + * DESCRIPTION: + * + * Converts a key_string to a key, Assumes the key_string is validated with + * is_valid_key_string(). + * + * PARAMETERS: + * + * ks - the valid key string + * key - a pointer to a KEY_STRUCT where the converted key information will + * be stored. + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void key_string2key( char *ks, KEY_STRCT *key ) +{ + int l,i,n; + char *p; + /*------------------------------------------------------------------------*/ + + + l = strlen( ks ); + + /* 0x followed by hexadecimal digit pairs */ + if( ks[0] == '0' && ( ks[1] == 'x' || ks[1] == 'X' )) { + n = 0; + p = (char *)key->key; + + for( i = 2; i < l; i+=2 ) { + *p++ = ( hexdigit2int( ks[i] ) << 4 ) + hexdigit2int (ks[i+1] ); + n++; + } + + /* Note that endian translation of the length field is not needed here + because it's performed in wl_put_ltv() */ + key->len = n; + } + /* character string */ + else + { + strcpy( (char *)key->key, ks ); + key->len = l; + } + + return; +} // key_string2key +/*============================================================================*/ + + + + +#if DBG +/******************************************************************************* + * DbgHwAddr() + ******************************************************************************* + * + * DESCRIPTION: + * + * Convert a hardware ethernet address to a character string + * + * PARAMETERS: + * + * hwAddr - an ethernet address + * + * RETURNS: + * + * a pointer to a string representing the ethernet address + * + ******************************************************************************/ +const char *DbgHwAddr(unsigned char *hwAddr) +{ + static char buffer[18]; + /*------------------------------------------------------------------------*/ + + + sprintf( buffer, "%02X:%02X:%02X:%02X:%02X:%02X", + hwAddr[0], hwAddr[1], hwAddr[2], hwAddr[3], hwAddr[4], hwAddr[5] ); + + return buffer; +} // DbgHwAddr +/*============================================================================*/ + +#endif /* DBG */ + + + + +/******************************************************************************* + * wl_has_wep() + ******************************************************************************* + * + * DESCRIPTION: + * + * Checks to see if the device supports WEP + * + * PARAMETERS: + * + * ifbp - the IFB pointer of the device in question + * + * RETURNS: + * + * 1 if WEP is known enabled, else 0 + * + ******************************************************************************/ +int wl_has_wep (IFBP ifbp) +{ + CFG_PRIVACY_OPT_IMPLEMENTED_STRCT ltv; + int rc, privacy; + /*------------------------------------------------------------------------*/ + + + /* This function allows us to distiguish bronze cards from other types, to + know if WEP exists. Does not distinguish (because there's no way to) + between silver and gold cards. */ + ltv.len = 2; + ltv.typ = CFG_PRIVACY_OPT_IMPLEMENTED; + + rc = hcf_get_info( ifbp, (LTVP) <v ); + + privacy = CNV_LITTLE_TO_INT( ltv.privacy_opt_implemented ); + + //return rc ? 0 : privacy; + return 1; +} // wl_has_wep +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_hcf_error() + ******************************************************************************* + * + * DESCRIPTION: + * + * Report the type of HCF error message + * + * PARAMETERS: + * + * none + * + * RETURNS: + * + * A descriptive string indicating the error, quiet otherwise. + * + ******************************************************************************/ +void wl_hcf_error( struct net_device *dev, int hcfStatus ) +{ + char buffer[64], *pMsg; + /*------------------------------------------------------------------------*/ + + + if( hcfStatus != HCF_SUCCESS ) { + switch( hcfStatus ) { + + case HCF_ERR_TIME_OUT: + + pMsg = "Expected adapter event did not occur in expected time"; + break; + + + case HCF_ERR_NO_NIC: + + pMsg = "Card not found (ejected unexpectedly)"; + break; + + + case HCF_ERR_LEN: + + pMsg = "Command buffer size insufficient"; + break; + + + case HCF_ERR_INCOMP_PRI: + + pMsg = "Primary functions are not compatible"; + break; + + + case HCF_ERR_INCOMP_FW: + + pMsg = "Primary functions are compatible, " + "station/ap functions are not"; + break; + + + case HCF_ERR_BUSY: + + pMsg = "Inquire cmd while another Inquire in progress"; + break; + + + //case HCF_ERR_SEQ_BUG: + + // pMsg = "Unexpected command completed"; + // break; + + + case HCF_ERR_DEFUNCT_AUX: + + pMsg = "Timeout on ack for enable/disable of AUX registers"; + break; + + + case HCF_ERR_DEFUNCT_TIMER: + pMsg = "Timeout on timer calibration during initialization process"; + break; + + + case HCF_ERR_DEFUNCT_TIME_OUT: + pMsg = "Timeout on Busy bit drop during BAP setup"; + break; + + + case HCF_ERR_DEFUNCT_CMD_SEQ: + pMsg = "Hermes and HCF are out of sync"; + break; + + + default: + + sprintf( buffer, "Error code %d", hcfStatus ); + pMsg = buffer; + break; + } + + printk( KERN_INFO "%s: Wireless, HCF failure: \"%s\"\n", + dev->name, pMsg ); + } +} // wl_hcf_error +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_endian_translate_event() + ******************************************************************************* + * + * DESCRIPTION: + * + * Determines what type of data is in the mailbox and performs the proper + * endian translation. + * + * PARAMETERS: + * + * pLtv - an LTV pointer + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_endian_translate_event( ltv_t *pLtv ) +{ + DBG_FUNC( "wl_endian_translate_event" ); + DBG_ENTER( DbgInfo ); + + + switch( pLtv->typ ) { + case CFG_TALLIES: + break; + + + case CFG_SCAN: + { + int numAPs; + SCAN_RS_STRCT *pAps = (SCAN_RS_STRCT*)&pLtv->u.u8[0]; + + numAPs = (hcf_16)(( (size_t)( pLtv->len - 1 ) * 2 ) / + (sizeof( SCAN_RS_STRCT ))); + + while( numAPs >= 1 ) { + numAPs--; + + pAps[numAPs].channel_id = + CNV_LITTLE_TO_INT( pAps[numAPs].channel_id ); + + pAps[numAPs].noise_level = + CNV_LITTLE_TO_INT( pAps[numAPs].noise_level ); + + pAps[numAPs].signal_level = + CNV_LITTLE_TO_INT( pAps[numAPs].signal_level ); + + pAps[numAPs].beacon_interval_time = + CNV_LITTLE_TO_INT( pAps[numAPs].beacon_interval_time ); + + pAps[numAPs].capability = + CNV_LITTLE_TO_INT( pAps[numAPs].capability ); + + pAps[numAPs].ssid_len = + CNV_LITTLE_TO_INT( pAps[numAPs].ssid_len ); + + pAps[numAPs].ssid_val[pAps[numAPs].ssid_len] = 0; + + } + } + break; + + + case CFG_ACS_SCAN: + { + PROBE_RESP *probe_resp = (PROBE_RESP *)pLtv; + + probe_resp->frameControl = CNV_LITTLE_TO_INT( probe_resp->frameControl ); + probe_resp->durID = CNV_LITTLE_TO_INT( probe_resp->durID ); + probe_resp->sequence = CNV_LITTLE_TO_INT( probe_resp->sequence ); + probe_resp->dataLength = CNV_LITTLE_TO_INT( probe_resp->dataLength ); + +#ifndef WARP + probe_resp->lenType = CNV_LITTLE_TO_INT( probe_resp->lenType ); +#endif // WARP + + probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval ); + probe_resp->capability = CNV_LITTLE_TO_INT( probe_resp->capability ); + probe_resp->flags = CNV_LITTLE_TO_INT( probe_resp->flags ); + } + break; + + + case CFG_LINK_STAT: +#define ls ((LINK_STATUS_STRCT *)pLtv) + ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus ); + break; +#undef ls + + case CFG_ASSOC_STAT: + { + ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv; + + pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus ); + } + break; + + + case CFG_SECURITY_STAT: + { + SECURITY_STATUS_STRCT *pSs = (SECURITY_STATUS_STRCT *)pLtv; + + pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus ); + pSs->reason = CNV_LITTLE_TO_INT( pSs->reason ); + } + break; + + + case CFG_WMP: + break; + + + case CFG_NULL: + break; + + + default: + break; + } + + DBG_LEAVE( DbgInfo ); + return; +} // wl_endian_translate_event +/*============================================================================*/ + + +/******************************************************************************* + * msf_assert() + ******************************************************************************* + * + * DESCRIPTION: + * + * Print statement used to display asserts from within the HCF. Only called + * when asserts in the HCF are turned on. See hcfcfg.h for more information. + * + * PARAMETERS: + * + * file_namep - the filename in which the assert occurred. + * line_number - the line number on which the assert occurred. + * trace - a comment associated with the assert. + * qual - return code or other value related to the assert + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual ) +{ + DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual ); +} // msf_assert +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_parse_ds_ie() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function parses the Direct Sequence Parameter Set IE, used to + * determine channel/frequency information. + * + * PARAMETERS: + * + * probe_rsp - a pointer to a PROBE_RESP structure containing the probe + * response. + * + * RETURNS: + * + * The channel on which the BSS represented by this probe response is + * transmitting. + * + ******************************************************************************/ +hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp ) +{ + int i; + int ie_length = 0; + hcf_8 *buf; + hcf_8 buf_size; + /*------------------------------------------------------------------------*/ + + + if( probe_rsp == NULL ) { + return 0; + } + + buf = probe_rsp->rawData; + buf_size = sizeof( probe_rsp->rawData ); + + + for( i = 0; i < buf_size; i++ ) { + if( buf[i] == DS_INFO_ELEM ) { + /* Increment by 1 to get the length, and test it; in a DS element, + length should always be 1 */ + i++; + ie_length = buf[i]; + + if( buf[i] == 1 ) { + /* Get the channel information */ + i++; + return buf[i]; + } + } + } + + /* If we get here, we didn't find a DS-IE, which is strange */ + return 0; +} // wl_parse_ds_ie + + +/******************************************************************************* + * wl_parse_wpa_ie() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function parses the Probe Response for a valid WPA-IE. + * + * PARAMETERS: + * + * probe_rsp - a pointer to a PROBE_RESP structure containing the probe + * response + * length - a pointer to an hcf_16 in which the size of the WPA-IE will + * be stored (if found). + * + * RETURNS: + * + * A pointer to the location in the probe response buffer where a valid + * WPA-IE lives. The length of this IE is written back to the 'length' + * argument passed to the function. + * + ******************************************************************************/ +hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length ) +{ + int i; + int ie_length = 0; + hcf_8 *buf; + hcf_8 buf_size; + hcf_8 wpa_oui[] = WPA_OUI_TYPE; + /*------------------------------------------------------------------------*/ + + + if( probe_rsp == NULL || length == NULL ) { + return NULL; + } + + buf = probe_rsp->rawData; + buf_size = sizeof( probe_rsp->rawData ); + *length = 0; + + + for( i = 0; i < buf_size; i++ ) { + if( buf[i] == GENERIC_INFO_ELEM ) { + /* Increment by one to get the IE length */ + i++; + ie_length = probe_rsp->rawData[i]; + + /* Increment by one to point to the IE payload */ + i++; + + /* Does the IE contain a WPA OUI? If not, it's a proprietary IE */ + if( memcmp( &buf[i], &wpa_oui, WPA_SELECTOR_LEN ) == 0 ) { + /* Pass back length and return a pointer to the WPA-IE */ + /* NOTE: Length contained in the WPA-IE is only the length of + the payload. The entire WPA-IE, including the IE identifier + and the length, is 2 bytes larger */ + *length = ie_length + 2; + + /* Back up the pointer 2 bytes to include the IE identifier and + the length in the buffer returned */ + i -= 2; + return &buf[i]; + } + + /* Increment past this non-WPA IE and continue looking */ + i += ( ie_length - 1 ); + } + } + + /* If we're here, we didn't find a WPA-IE in the buffer */ + return NULL; +} // wl_parse_wpa_ie + + +/******************************************************************************* + * wl_print_wpa_ie() + ******************************************************************************* + * + * DESCRIPTION: + * + * Function used to take a WPA Information Element (WPA-IE) buffer and + * display it in a readable format. + * + * PARAMETERS: + * + * buffer - the byte buffer containing the WPA-IE + * length - the length of the above buffer + * + * RETURNS: + * + * A pointer to the formatted WPA-IE string. Note that the format used is + * byte-by-byte printing as %02x hex values with no spaces. This is + * required for proper operation with some WPA supplicants. + * + ******************************************************************************/ +hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length ) +{ + int count; + int rows; + int remainder; + int rowsize = 4; + hcf_8 row_buf[64]; + static hcf_8 output[512]; + /*------------------------------------------------------------------------*/ + + + memset( output, 0, sizeof( output )); + memset( row_buf, 0, sizeof( row_buf )); + + + /* Determine how many rows will be needed, and the remainder */ + rows = length / rowsize; + remainder = length % rowsize; + + + /* Format the rows */ + for( count = 0; count < rows; count++ ) { + sprintf( row_buf, "%02x%02x%02x%02x", + buffer[count*rowsize], buffer[count*rowsize+1], + buffer[count*rowsize+2], buffer[count*rowsize+3]); + strcat( output, row_buf ); + } + + memset( row_buf, 0, sizeof( row_buf )); + + + /* Format the remainder */ + for( count = 0; count < remainder; count++ ) { + sprintf( row_buf, "%02x", buffer[(rows*rowsize)+count]); + strcat( output, row_buf ); + } + + return output; +} // wl_print_wpa_ie +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_is_a_valid_chan() + ******************************************************************************* + * + * DESCRIPTION: + * + * Checks if a given channel is valid + * + * PARAMETERS: + * + * channel - the channel + * + * RETURNS: + * + * 1 if TRUE + * 0 if FALSE + * + ******************************************************************************/ +int wl_is_a_valid_chan( int channel ) +{ + int i; + /*------------------------------------------------------------------------*/ + + + /* Strip out the high bit set by the FW for 802.11a channels */ + if( channel & 0x100 ) { + channel = channel & 0x0FF; + } + + /* Iterate through the matrix and retrieve the frequency */ + for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) { + if( chan_freq_list[i][0] == channel ) { + return 1; + } + } + + return 0; +} // wl_is_a_valid_chan +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_get_chan_from_freq() + ******************************************************************************* + * + * DESCRIPTION: + * + * Checks if a given frequency is valid + * + * PARAMETERS: + * + * freq - the frequency + * + * RETURNS: + * + * 1 if TRUE + * 0 if FALSE + * + ******************************************************************************/ +int wl_is_a_valid_freq( long frequency ) +{ + int i; + /*------------------------------------------------------------------------*/ + + + /* Iterate through the matrix and retrieve the channel */ + for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) { + if( chan_freq_list[i][1] == frequency ) { + return 1; + } + } + + return 0; +} // wl_is_a_valid_freq +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_get_freq_from_chan() + ******************************************************************************* + * + * DESCRIPTION: + * + * Function used to look up the frequency for a given channel on which the + * adapter is Tx/Rx. + * + * PARAMETERS: + * + * channel - the channel + * + * RETURNS: + * + * The corresponding frequency + * + ******************************************************************************/ +long wl_get_freq_from_chan( int channel ) +{ + int i; + /*------------------------------------------------------------------------*/ + + + /* Strip out the high bit set by the FW for 802.11a channels */ + if( channel & 0x100 ) { + channel = channel & 0x0FF; + } + + /* Iterate through the matrix and retrieve the frequency */ + for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) { + if( chan_freq_list[i][0] == channel ) { + return chan_freq_list[i][1]; + } + } + + return 0; +} // wl_get_freq_from_chan +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_get_chan_from_freq() + ******************************************************************************* + * + * DESCRIPTION: + * + * Function used to look up the channel for a given frequency on which the + * adapter is Tx/Rx. + * + * PARAMETERS: + * + * frequency - the frequency + * + * RETURNS: + * + * The corresponding channel + * + ******************************************************************************/ +int wl_get_chan_from_freq( long frequency ) +{ + int i; + /*------------------------------------------------------------------------*/ + + + /* Iterate through the matrix and retrieve the channel */ + for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) { + if( chan_freq_list[i][1] == frequency ) { + return chan_freq_list[i][0]; + } + } + + return 0; +} // wl_get_chan_from_freq +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_process_link_status() + ******************************************************************************* + * + * DESCRIPTION: + * + * Process the link status message signaled by the device. + * + * PARAMETERS: + * + * lp - a pointer to the device's private structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_process_link_status( struct wl_private *lp ) +{ + hcf_16 link_stat; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_process_link_status" ); + DBG_ENTER( DbgInfo ); + + if( lp != NULL ) { + //link_stat = lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_FW; + link_stat = lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW; + switch( link_stat ) { + case 1: + DBG_TRACE( DbgInfo, "Link Status : Connected\n" ); + wl_wext_event_ap( lp->dev ); + break; + case 2: + DBG_TRACE( DbgInfo, "Link Status : Disconnected\n" ); + break; + case 3: + DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" ); + break; + case 4: + DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" ); + break; + case 5: + DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" ); + break; + default: + DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat ); + break; + } + } + DBG_LEAVE( DbgInfo ); + return; +} // wl_process_link_status +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_process_probe_response() + ******************************************************************************* + * + * DESCRIPTION: + * + * Process the probe responses retunred by the device as a result of an + * active scan. + * + * PARAMETERS: + * + * lp - a pointer to the device's private structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_process_probe_response( struct wl_private *lp ) +{ + PROBE_RESP *probe_rsp; + hcf_8 *wpa_ie = NULL; + hcf_16 wpa_ie_len = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wl_process_probe_response" ); + DBG_ENTER( DbgInfo ); + + + if( lp != NULL ) { + probe_rsp = (PROBE_RESP *)&lp->ProbeResp; + + wl_endian_translate_event( (ltv_t *)probe_rsp ); + + DBG_TRACE( DbgInfo, "(%s) =========================\n", lp->dev->name ); + DBG_TRACE( DbgInfo, "(%s) length : 0x%04x.\n", lp->dev->name, + probe_rsp->length ); + + if( probe_rsp->length > 1 ) { + DBG_TRACE( DbgInfo, "(%s) infoType : 0x%04x.\n", lp->dev->name, + probe_rsp->infoType ); + + DBG_TRACE( DbgInfo, "(%s) signal : 0x%02x.\n", lp->dev->name, + probe_rsp->signal ); + + DBG_TRACE( DbgInfo, "(%s) silence : 0x%02x.\n", lp->dev->name, + probe_rsp->silence ); + + DBG_TRACE( DbgInfo, "(%s) rxFlow : 0x%02x.\n", lp->dev->name, + probe_rsp->rxFlow ); + + DBG_TRACE( DbgInfo, "(%s) rate : 0x%02x.\n", lp->dev->name, + probe_rsp->rate ); + + DBG_TRACE( DbgInfo, "(%s) frame cntl : 0x%04x.\n", lp->dev->name, + probe_rsp->frameControl ); + + DBG_TRACE( DbgInfo, "(%s) durID : 0x%04x.\n", lp->dev->name, + probe_rsp->durID ); + + DBG_TRACE( DbgInfo, "(%s) address1 : %s\n", lp->dev->name, + DbgHwAddr( probe_rsp->address1 )); + + DBG_TRACE( DbgInfo, "(%s) address2 : %s\n", lp->dev->name, + DbgHwAddr( probe_rsp->address2 )); + + DBG_TRACE( DbgInfo, "(%s) BSSID : %s\n", lp->dev->name, + DbgHwAddr( probe_rsp->BSSID )); + + DBG_TRACE( DbgInfo, "(%s) sequence : 0x%04x.\n", lp->dev->name, + probe_rsp->sequence ); + + DBG_TRACE( DbgInfo, "(%s) address4 : %s\n", lp->dev->name, + DbgHwAddr( probe_rsp->address4 )); + + DBG_TRACE( DbgInfo, "(%s) datalength : 0x%04x.\n", lp->dev->name, + probe_rsp->dataLength ); + + DBG_TRACE( DbgInfo, "(%s) DA : %s\n", lp->dev->name, + DbgHwAddr( probe_rsp->DA )); + + DBG_TRACE( DbgInfo, "(%s) SA : %s\n", lp->dev->name, + DbgHwAddr( probe_rsp->SA )); + +#ifdef WARP + + DBG_TRACE( DbgInfo, "(%s) channel : %d\n", lp->dev->name, + probe_rsp->channel ); + + DBG_TRACE( DbgInfo, "(%s) band : %d\n", lp->dev->name, + probe_rsp->band ); +#else + DBG_TRACE( DbgInfo, "(%s) lenType : 0x%04x.\n", lp->dev->name, + probe_rsp->lenType ); +#endif // WARP + + DBG_TRACE( DbgInfo, "(%s) timeStamp : %d.%d.%d.%d.%d.%d.%d.%d\n", + lp->dev->name, + probe_rsp->timeStamp[0], + probe_rsp->timeStamp[1], + probe_rsp->timeStamp[2], + probe_rsp->timeStamp[3], + probe_rsp->timeStamp[4], + probe_rsp->timeStamp[5], + probe_rsp->timeStamp[6], + probe_rsp->timeStamp[7]); + + DBG_TRACE( DbgInfo, "(%s) beaconInt : 0x%04x.\n", lp->dev->name, + probe_rsp->beaconInterval ); + + DBG_TRACE( DbgInfo, "(%s) capability : 0x%04x.\n", lp->dev->name, + probe_rsp->capability ); + + DBG_TRACE( DbgInfo, "(%s) SSID len : 0x%04x.\n", lp->dev->name, + probe_rsp->rawData[1] ); + + + if( probe_rsp->rawData[1] > 0 ) { + char ssid[HCF_MAX_NAME_LEN]; + + memset( ssid, 0, sizeof( ssid )); + strncpy( ssid, &probe_rsp->rawData[2], + probe_rsp->rawData[1] ); + + DBG_TRACE( DbgInfo, "(%s) SSID : %s\n", + lp->dev->name, ssid ); + } + + + /* Parse out the WPA-IE, if one exists */ + wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len ); + if( wpa_ie != NULL ) { + DBG_TRACE( DbgInfo, "(%s) WPA-IE : %s\n", + lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len )); + } + + DBG_TRACE( DbgInfo, "(%s) flags : 0x%04x.\n", + lp->dev->name, probe_rsp->flags ); + } + + DBG_TRACE( DbgInfo, "\n" ); + + + /* If probe response length is 1, then the scan is complete */ + if( probe_rsp->length == 1 ) { + DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" ); + lp->probe_results.num_aps = lp->probe_num_aps; + lp->probe_results.scan_complete = TRUE; + + /* Reset the counter for the next scan request */ + lp->probe_num_aps = 0; + + /* Send a wireless extensions event that the scan completed */ + wl_wext_event_scan_complete( lp->dev ); + } else { + /* Only copy to the table if the entry is unique; APs sometimes + respond more than once to a probe */ + if( lp->probe_num_aps == 0 ) { + /* Copy the info to the ScanResult structure in the private + adapter struct */ + memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ), + probe_rsp, sizeof( PROBE_RESP )); + + /* Increment the number of APs detected */ + lp->probe_num_aps++; + } else { + int count; + int unique = 1; + + for( count = 0; count < lp->probe_num_aps; count++ ) { + if( memcmp( &( probe_rsp->BSSID ), + lp->probe_results.ProbeTable[count].BSSID, + ETH_ALEN ) == 0 ) { + unique = 0; + } + } + + if( unique ) { + /* Copy the info to the ScanResult structure in the + private adapter struct. Only copy if there's room in the + table */ + if( lp->probe_num_aps < MAX_NAPS ) + { + memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ), + probe_rsp, sizeof( PROBE_RESP )); + } + else + { + DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" ); + } + + /* Increment the number of APs detected. Note I do this + here even when I don't copy the probe response to the + buffer in order to detect the overflow condition */ + lp->probe_num_aps++; + } + } + } + } + + DBG_LEAVE( DbgInfo ); + return; +} // wl_process_probe_response +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_process_updated_record() + ******************************************************************************* + * + * DESCRIPTION: + * + * Process the updated information record message signaled by the device. + * + * PARAMETERS: + * + * lp - a pointer to the device's private structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_process_updated_record( struct wl_private *lp ) +{ + DBG_FUNC( "wl_process_updated_record" ); + DBG_ENTER( DbgInfo ); + + + if( lp != NULL ) { + lp->updatedRecord.u.u16[0] = CNV_LITTLE_TO_INT( lp->updatedRecord.u.u16[0] ); + + switch( lp->updatedRecord.u.u16[0] ) { + case CFG_CUR_COUNTRY_INFO: + DBG_TRACE( DbgInfo, "Updated Record: CFG_CUR_COUNTRY_INFO\n" ); + wl_connect( lp ); + break; + + case CFG_PORT_STAT: + DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" ); + //wl_connect( lp ); + break; + + default: + DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n", + lp->updatedRecord.u.u16[0] ); + } + } + + DBG_LEAVE( DbgInfo ); + return; +} // wl_process_updated_record +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_process_assoc_status() + ******************************************************************************* + * + * DESCRIPTION: + * + * Process the association status event signaled by the device. + * + * PARAMETERS: + * + * lp - a pointer to the device's private structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_process_assoc_status( struct wl_private *lp ) +{ + ASSOC_STATUS_STRCT *assoc_stat; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wl_process_assoc_status" ); + DBG_ENTER( DbgInfo ); + + + if( lp != NULL ) { + assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat; + + wl_endian_translate_event( (ltv_t *)assoc_stat ); + + switch( assoc_stat->assocStatus ) { + case 1: + DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" ); + break; + + case 2: + DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" ); + break; + + case 3: + DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" ); + break; + + default: + DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n", + assoc_stat->assocStatus ); + break; + } + + DBG_TRACE( DbgInfo, "STA Address : %s\n", + DbgHwAddr( assoc_stat->staAddr )); + + if(( assoc_stat->assocStatus == 2 ) && ( assoc_stat->len == 8 )) { + DBG_TRACE( DbgInfo, "Old AP Address : %s\n", + DbgHwAddr( assoc_stat->oldApAddr )); + } + } + + DBG_LEAVE( DbgInfo ); + return; +} // wl_process_assoc_status +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_process_security_status() + ******************************************************************************* + * + * DESCRIPTION: + * + * Process the security status message signaled by the device. + * + * PARAMETERS: + * + * lp - a pointer to the device's private structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_process_security_status( struct wl_private *lp ) +{ + SECURITY_STATUS_STRCT *sec_stat; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wl_process_security_status" ); + DBG_ENTER( DbgInfo ); + + + if( lp != NULL ) { + sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat; + + wl_endian_translate_event( (ltv_t *)sec_stat ); + + switch( sec_stat->securityStatus ) { + case 1: + DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" ); + break; + + case 2: + DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" ); + break; + + case 3: + DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" ); + break; + + case 4: + DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" ); + break; + + case 5: + DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" ); + break; + + default: + DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n", + sec_stat->securityStatus ); + break; + } + + DBG_TRACE( DbgInfo, "STA Address : %s\n", + DbgHwAddr( sec_stat->staAddr )); + DBG_TRACE( DbgInfo, "Reason : 0x%04x \n", sec_stat->reason ); + + } + + DBG_LEAVE( DbgInfo ); + return; +} // wl_process_security_status +/*============================================================================*/ + +int wl_get_tallies(struct wl_private *lp, + CFG_HERMES_TALLIES_STRCT *tallies) +{ + int ret = 0; + int status; + CFG_HERMES_TALLIES_STRCT *pTallies; + + DBG_FUNC( "wl_get_tallies" ); + DBG_ENTER(DbgInfo); + + /* Get the current tallies from the adapter */ + lp->ltvRecord.len = 1 + HCF_TOT_TAL_CNT * sizeof(hcf_16); + lp->ltvRecord.typ = CFG_TALLIES; + + status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord)); + + if( status == HCF_SUCCESS ) { + pTallies = (CFG_HERMES_TALLIES_STRCT *)&(lp->ltvRecord.u.u32); + memcpy(tallies, pTallies, sizeof(*tallies)); + DBG_TRACE( DbgInfo, "Get tallies okay, dixe: %d\n", sizeof(*tallies) ); + } else { + DBG_TRACE( DbgInfo, "Get tallies failed\n" ); + ret = -EFAULT; + } + + DBG_LEAVE( DbgInfo ); + + return ret; +} + +/******************************************************************************* + * wl_atoi() + ******************************************************************************* + * + * DESCRIPTION: + * + * Believe it or not, we need our own implementation of atoi in the kernel. + * + * PARAMETERS: + * + * string - the ASCII string to convert to an integer + * + * RETURNS: + * + * unsigned integer + * + ******************************************************************************/ +unsigned int wl_atoi( char *string ) +{ +unsigned int base = 10; //default to decimal +unsigned int value = 0; +unsigned int c; +int i = strlen( string ); + + if ( i > 2 && string[0] == '0' && ( string[1] | ('X'^'x') ) == 'x' ) { + base = 16; + string +=2; + } + while ( ( c = *string++ ) != '\0' ) { + if ( value > UINT_MAX / base ) { //test for overrun + DBG_FUNC( "wl_atoi" ); //don't overload the log file with good messages + DBG_ENTER( DbgInfo ); + DBG_ERROR( DbgInfo, "string \"%s\", lenght exceeds expectations\n", string ); + printk( "<1>string \"%s\", lenght exceeds expectations\n", string ); + DBG_LEAVE( DbgInfo ); + break; + } + c -= '0'; + if ( 0 <= c && c <= 9 ) value = base * value + c; + else if ( base == 16 ) { + c += '0'; + c |= 'A'^'a'; + c = c - 'a'+ 10; + if ( 10 <= c && c <= 15 ) value = base * value + c; + } + } + return value; +} // wl_atoi + diff --git a/drivers/staging/wlags49_h2/wl_util.h b/drivers/staging/wlags49_h2/wl_util.h new file mode 100644 index 0000000000000000000000000000000000000000..16cd6c578adb421402314675e3007f41e08504b5 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_util.h @@ -0,0 +1,105 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * Header describing information required for utility functions used + * throughout the driver. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +#ifndef __WL_UTIL_H__ +#define __WL_UTIL_H__ + +/******************************************************************************* + * function prototypes + ******************************************************************************/ +int dbm( int value ); + +int is_valid_key_string( char *s ); + +void key_string2key( char *ks, KEY_STRCT *key ); + +int hexdigit2int( char c ); + +void wl_hcf_error( struct net_device *dev, int hcfStatus ); + +void wl_endian_translate_event( ltv_t *pLtv ); + +int wl_has_wep( IFBP ifbp ); + + +#if DBG +const char *DbgHwAddr( unsigned char *hwAddr ); +#endif // DBG + +hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp ); +hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length ); +hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length ); + +int wl_get_tallies(struct wl_private *, CFG_HERMES_TALLIES_STRCT *); +int wl_is_a_valid_chan( int channel ); +int wl_is_a_valid_freq( long frequency ); +long wl_get_freq_from_chan( int channel ); +int wl_get_chan_from_freq( long frequency ); + +void wl_process_link_status( struct wl_private *lp ); +void wl_process_probe_response( struct wl_private *lp ); +void wl_process_updated_record( struct wl_private *lp ); +void wl_process_assoc_status( struct wl_private *lp ); +void wl_process_security_status( struct wl_private *lp ); + +unsigned int wl_atoi( char *string ); + +#endif // __WL_UTIL_H__ diff --git a/drivers/staging/wlags49_h2/wl_version.h b/drivers/staging/wlags49_h2/wl_version.h new file mode 100644 index 0000000000000000000000000000000000000000..a5e604cd19833cc0f28b42cf7d93cf572f453e9e --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_version.h @@ -0,0 +1,179 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * This header file contains version information for the code base, as well as + * special definitions and macros needed by certain versions of the code. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +#ifndef __WL_VERSION_H__ +#define __WL_VERSION_H__ + +/******************************************************************************* + * include files + ******************************************************************************/ +//#include +#include + +#ifndef CONFIG_MODVERSIONS +#define __NO_VERSION__ +#endif // CONFIG_MODVERSIONS + +/******************************************************************************* + * constant definitions + ******************************************************************************/ + +#define VENDOR_NAME "Agere Systems, http://www.agere.com" + +#define DRIVER_NAME "wlags49" +#define DRV_IDENTITY 49 + +#define DRV_MAJOR_VERSION 7 +#define DRV_MINOR_VERSION 22 +#define DRV_VERSION_STR "7.22" + + +#if defined BUS_PCMCIA +#define BUS_TYPE "PCMCIA" +#elif defined BUS_PCI +#define BUS_TYPE "PCI" +#else +err: define bus type; +#endif // BUS_XXX + +#if defined HERMES25 +#define HW_TYPE "HII.5" +#else +#define HW_TYPE "HII" +#endif // HERMES25 + +#if defined WARP +#define FW_TYPE "WARP" +#else +#define FW_TYPE "BEAGLE" +#endif // WARP + +#if defined HERMES25 +#if defined WARP +#define DRV_VARIANT 3 +#else +#define DRV_VARIANT 4 +#endif // WARP +#else +#define DRV_VARIANT 2 +#endif // HERMES25 + +#ifdef BUS_PCMCIA +#if defined HERMES25 +#define MODULE_NAME DRIVER_NAME "_h25_cs" +#else +#define MODULE_NAME DRIVER_NAME "_h2_cs" +#endif /* HERMES25 */ +#elif defined BUS_PCI +#if defined HERMES25 +#define MODULE_NAME DRIVER_NAME "_h25" +#else +#define MODULE_NAME DRIVER_NAME "_h2" +#endif /* HERMES25 */ +#endif /* BUS_XXX */ + +#ifdef DBG +#define MODULE_DATE __DATE__ " " __TIME__ +#else +#define MODULE_DATE "07/18/2004 13:30:00" +#endif // DBG + +//#define STR2(m) #m +//#define STR1(m) STR2(m) +//#define MODULE_NAME STR1( MOD_NAME ) + +#define VERSION_INFO MODULE_NAME " v" DRV_VERSION_STR \ + " for " BUS_TYPE ", " \ + MODULE_DATE " by " VENDOR_NAME + +#define WIRELESS_SUPPORT 15 // The version of wireless extensions we support + +//#define DBG_MOD_NAME DRIVER_NAME ":" BUS_TYPE ":" HW_TYPE ":" FW_TYPE +#define DBG_MOD_NAME MODULE_NAME + + + +/******************************************************************************* + * bus architechture specific defines, includes, etc. + ******************************************************************************/ +/* + * There doesn't seem to be a difference for PCMCIA and PCI anymore, at least + * for PCMCIA the same defines are needed now as previously only used for PCI + */ +#if USE_WEXT +#define HAS_WIRELESS_EXTENSIONS +#endif // USE_WEXT + +#define NEW_MULTICAST +#define ALLOC_SKB(len) dev_alloc_skb(len+2) +#define GET_PACKET(dev, skb, count)\ + skb_reserve((skb), 2); \ + BLOCK_INPUT(skb_put((skb), (count)), (count)); \ + (skb)->protocol = eth_type_trans((skb), (dev)) +#define GET_PACKET_DMA(dev, skb, count)\ + skb_reserve((skb), 2); \ + BLOCK_INPUT_DMA(skb_put((skb), (count)), (count)); \ + (skb)->protocol = eth_type_trans((skb), (dev)) + + + + +#endif // __WL_VERSION_H__ diff --git a/drivers/staging/wlags49_h2/wl_wext.c b/drivers/staging/wlags49_h2/wl_wext.c new file mode 100644 index 0000000000000000000000000000000000000000..4434e006548847df1c0cee808edce7439312fb0a --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_wext.c @@ -0,0 +1,4130 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +/******************************************************************************* + * include files + ******************************************************************************/ +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + + +/* If WIRELESS_EXT is not defined (as a result of HAS_WIRELESS_EXTENSIONS + #including linux/wireless.h), then these functions do not need to be included + in the build. */ +#ifdef WIRELESS_EXT + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) +#define IWE_STREAM_ADD_EVENT(info, buf, end, iwe, len) \ + iwe_stream_add_event(buf, end, iwe, len) +#define IWE_STREAM_ADD_POINT(info, buf, end, iwe, msg) \ + iwe_stream_add_point(buf, end, iwe, msg) +#else +#define IWE_STREAM_ADD_EVENT(info, buf, end, iwe, len) \ + iwe_stream_add_event(info, buf, end, iwe, len) +#define IWE_STREAM_ADD_POINT(info, buf, end, iwe, msg) \ + iwe_stream_add_point(info, buf, end, iwe, msg) +#endif + + + +/******************************************************************************* + * global definitions + ******************************************************************************/ +#if DBG +extern dbg_info_t *DbgInfo; +#endif // DBG + + + + +/******************************************************************************* + * wireless_commit() + ******************************************************************************* + * + * DESCRIPTION: + * + * Commit + * protocol used. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +static int wireless_commit(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *rqu, char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wireless_commit" ); + DBG_ENTER(DbgInfo); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + wl_apply(lp); + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_commit +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_get_protocol() + ******************************************************************************* + * + * DESCRIPTION: + * + * Returns a vendor-defined string that should identify the wireless + * protocol used. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra) +{ + DBG_FUNC( "wireless_get_protocol" ); + DBG_ENTER( DbgInfo ); + + /* Originally, the driver was placing the string "Wireless" here. However, + the wireless extensions (/linux/wireless.h) indicate this string should + describe the wireless protocol. */ + + strcpy(name, "IEEE 802.11b"); + + DBG_LEAVE(DbgInfo); + return 0; +} // wireless_get_protocol +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_set_frequency() + ******************************************************************************* + * + * DESCRIPTION: + * + * Sets the frequency (channel) on which the card should Tx/Rx. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int channel = 0; + int ret = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_set_frequency" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + if( !capable( CAP_NET_ADMIN )) { + ret = -EPERM; + DBG_LEAVE( DbgInfo ); + return ret; + } + + + /* If frequency specified, look up channel */ + if( freq->e == 1 ) { + int f = freq->m / 100000; + channel = wl_get_chan_from_freq( f ); + } + + + /* Channel specified */ + if( freq->e == 0 ) { + channel = freq->m; + } + + + /* If the channel is an 802.11a channel, set Bit 8 */ + if( channel > 14 ) { + channel = channel | 0x100; + } + + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + lp->Channel = channel; + + + /* Commit the adapter parameters */ + wl_apply( lp ); + + /* Send an event that channel/freq has been set */ + wl_wext_event_freq( lp->dev ); + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_set_frequency +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_get_frequency() + ******************************************************************************* + * + * DESCRIPTION: + * + * Gets the frequency (channel) on which the card is Tx/Rx. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra) + +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = -1; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_get_frequency" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CUR_CHANNEL; + + ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord )); + if( ret == HCF_SUCCESS ) { + hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ); + +#ifdef USE_FREQUENCY + + freq->m = wl_get_freq_from_chan( channel ) * 100000; + freq->e = 1; +#else + + freq->m = channel; + freq->e = 0; + +#endif /* USE_FREQUENCY */ + } + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + + ret = (ret == HCF_SUCCESS ? 0 : -EFAULT); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_get_frequency +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_get_range() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function is used to provide misc info and statistics about the + * wireless device. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + struct iw_range *range = (struct iw_range *) extra; + int ret = 0; + int status = -1; + int count; + __u16 *pTxRate; + int retries = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_get_range" ); + DBG_ENTER( DbgInfo ); + + /* Set range information */ + data->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + /* Set range information */ + memset( range, 0, sizeof( struct iw_range )); + +retry: + /* Get the current transmit rate from the adapter */ + lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16)); + lp->ltvRecord.typ = CFG_CUR_TX_RATE; + + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + if( status != HCF_SUCCESS ) { + /* Recovery action: reset and retry up to 10 times */ + DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status ); + + if (retries < 10) { + retries++; + + /* Holding the lock too long, make a gap to allow other processes */ + wl_unlock(lp, &flags); + wl_lock( lp, &flags ); + + status = wl_reset( dev ); + if ( status != HCF_SUCCESS ) { + DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status ); + + ret = -EFAULT; + goto out_unlock; + } + + /* Holding the lock too long, make a gap to allow other processes */ + wl_unlock(lp, &flags); + wl_lock( lp, &flags ); + + goto retry; + + } else { + DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries ); + ret = -EFAULT; + goto out_unlock; + } + } + + /* Holding the lock too long, make a gap to allow other processes */ + wl_unlock(lp, &flags); + wl_lock( lp, &flags ); + + pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 ); + + range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT; + + if (retries > 0) { + DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries ); + } + + // NWID - NOT SUPPORTED + + + /* Channel/Frequency Info */ + range->num_channels = RADIO_CHANNELS; + + + /* Signal Level Thresholds */ + range->sensitivity = RADIO_SENSITIVITY_LEVELS; + + + /* Link quality */ +#ifdef USE_DBM + + range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY; + + /* If the value returned in /proc/net/wireless is greater than the maximum range, + iwconfig assumes that the value is in dBm. Because an unsigned char is used, + it requires a bit of contorsion... */ + + range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 ); + range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 ); +#else + + range->max_qual.qual = 100; + range->max_qual.level = 100; + range->max_qual.noise = 100; + +#endif /* USE_DBM */ + + + /* Set available rates */ + range->num_bitrates = 0; + + lp->ltvRecord.len = 6; + lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES; + + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + if( status == HCF_SUCCESS ) { + for( count = 0; count < MAX_RATES; count++ ) + if( lp->ltvRecord.u.u8[count+2] != 0 ) { + range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2; + range->num_bitrates++; + } + } else { + DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status ); + ret = -EFAULT; + goto out_unlock; + } + + /* RTS Threshold info */ + range->min_rts = MIN_RTS_BYTES; + range->max_rts = MAX_RTS_BYTES; + + // Frag Threshold info - NOT SUPPORTED + + // Power Management info - NOT SUPPORTED + + /* Encryption */ + +#if WIRELESS_EXT > 8 + + /* Holding the lock too long, make a gap to allow other processes */ + wl_unlock(lp, &flags); + wl_lock( lp, &flags ); + + /* Is WEP supported? */ + + if( wl_has_wep( &( lp->hcfCtx ))) { + /* WEP: RC4 40 bits */ + range->encoding_size[0] = MIN_KEY_SIZE; + + /* RC4 ~128 bits */ + range->encoding_size[1] = MAX_KEY_SIZE; + range->num_encoding_sizes = 2; + range->max_encoding_tokens = MAX_KEYS; + } + +#endif /* WIRELESS_EXT > 8 */ + + /* Tx Power Info */ + range->txpower_capa = IW_TXPOW_MWATT; + range->num_txpower = 1; + range->txpower[0] = RADIO_TX_POWER_MWATT; + +#if WIRELESS_EXT > 10 + + /* Wireless Extension Info */ + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = WIRELESS_SUPPORT; + + // Retry Limits and Lifetime - NOT SUPPORTED + +#endif + + +#if WIRELESS_EXT > 11 + + /* Holding the lock too long, make a gap to allow other processes */ + wl_unlock(lp, &flags); + wl_lock( lp, &flags ); + + DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" ); + wl_wireless_stats( lp->dev ); + range->avg_qual = lp->wstats.qual; + DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" ); + +#endif + + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_K_0 | + IW_EVENT_CAPA_MASK(SIOCGIWAP) | + IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVREGISTERED) | + IW_EVENT_CAPA_MASK(IWEVCUSTOM) | + IW_EVENT_CAPA_MASK(IWEVEXPIRED)); + + range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP; + +out_unlock: + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + + DBG_LEAVE(DbgInfo); + return ret; +} // wireless_get_range +/*============================================================================*/ + + +/******************************************************************************* + * wireless_get_bssid() + ******************************************************************************* + * + * DESCRIPTION: + * + * Gets the BSSID the wireless device is currently associated with. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; +#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA + int status = -1; +#endif /* (HCF_TYPE) & HCF_TYPE_STA */ + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_get_bssid" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + memset( &ap_addr->sa_data, 0, ETH_ALEN ); + + ap_addr->sa_family = ARPHRD_ETHER; + + /* Assume AP mode here, which means the BSSID is our own MAC address. In + STA mode, this address will be overwritten with the actual BSSID using + the code below. */ + memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN); + + +#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA + //;?should we return an error status in AP mode + + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) { + /* Get Current BSSID */ + lp->ltvRecord.typ = CFG_CUR_BSSID; + lp->ltvRecord.len = 4; + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + + if( status == HCF_SUCCESS ) { + /* Copy info into sockaddr struct */ + memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN); + } else { + ret = -EFAULT; + } + } + +#endif // (HCF_TYPE) & HCF_TYPE_STA + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE(DbgInfo); + return ret; +} // wireless_get_bssid +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_get_ap_list() + ******************************************************************************* + * + * DESCRIPTION: + * + * Gets the results of a network scan. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + * NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function + * implements SIOCGIWAPLIST only to provide backwards compatibility. For + * all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN! + * + ******************************************************************************/ +static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret; + int num_aps = -1; + int sec_count = 0; + hcf_32 count; + struct sockaddr *hwa = NULL; + struct iw_quality *qual = NULL; +#ifdef WARP + ScanResult *p = &lp->scan_results; +#else + ProbeResult *p = &lp->probe_results; +#endif // WARP + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wireless_get_ap_list" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + /* Set the completion state to FALSE */ + lp->scan_results.scan_complete = FALSE; + lp->probe_results.scan_complete = FALSE; + /* Channels to scan */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_SCAN_CHANNELS_2GHZ; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF ); + ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret ); + + /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to + disassociate from the network we are currently on */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_SCAN_SSID; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); + ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret ); + + /* Initiate the scan */ +#ifdef WARP + ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN ); +#else + ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN ); +#endif // WARP + + wl_act_int_on( lp ); + + //;? unlock? what about the access to lp below? is it broken? + wl_unlock(lp, &flags); + + if( ret == HCF_SUCCESS ) { + DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" ); + while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) { + DBG_TRACE( DbgInfo, "Waiting for scan results...\n" ); + /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */ + if( sec_count++ > MAX_SCAN_TIME_SEC ) { + ret = -EIO; + } else { + /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do + other things in the meantime, This prevents system lockups by + giving some time back to the kernel */ + for( count = 0; count < 100; count ++ ) { + mdelay( 10 ); + schedule( ); + } + } + } + + rmb(); + + if ( ret != HCF_SUCCESS ) { + DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" ); + } else { + num_aps = (*p)/*lp->probe_results*/.num_aps; + if (num_aps > IW_MAX_AP) { + num_aps = IW_MAX_AP; + } + data->length = num_aps; + hwa = (struct sockaddr *)extra; + qual = (struct iw_quality *) extra + + ( sizeof( struct sockaddr ) * num_aps ); + + /* This flag is used to tell the user if we provide quality + information. Since we provide signal/noise levels but no + quality info on a scan, this is set to 0. Setting to 1 and + providing a quality of 0 produces weird results. If we ever + provide quality (or can calculate it), this can be changed */ + data->flags = 0; + + for( count = 0; count < num_aps; count++ ) { +#ifdef WARP + memcpy( hwa[count].sa_data, + (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN ); +#else //;?why use BSSID and bssid as names in seemingly very comparable situations + DBG_PRINT( "BSSID: %s\n", DbgHwAddr( (*p)/*lp->probe_results*/.ProbeTable[count].BSSID )); + memcpy( hwa[count].sa_data, + (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN ); +#endif // WARP + } + /* Once the data is copied to the wireless struct, invalidate the + scan result to initiate a rescan on the next request */ + (*p)/*lp->probe_results*/.scan_complete = FALSE; + /* Send the wireless event that the scan has completed, just in case + it's needed */ + wl_wext_event_scan_complete( lp->dev ); + } + } +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_get_ap_list +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_set_sensitivity() + ******************************************************************************* + * + * DESCRIPTION: + * + * Sets the sensitivity (distance between APs) of the wireless card. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + int dens = sens->value; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_set_sensitivity" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + if(( dens < 1 ) || ( dens > 3 )) { + ret = -EINVAL; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + lp->DistanceBetweenAPs = dens; + wl_apply( lp ); + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_set_sensitivity +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_get_sensitivity() + ******************************************************************************* + * + * DESCRIPTION: + * + * Gets the sensitivity (distance between APs) of the wireless card. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra) +{ + struct wl_private *lp = wl_priv(dev); + int ret = 0; + /*------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_get_sensitivity" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + /* not worth locking ... */ + sens->value = lp->DistanceBetweenAPs; + sens->fixed = 0; /* auto */ +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_get_sensitivity +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_set_essid() + ******************************************************************************* + * + * DESCRIPTION: + * + * Sets the ESSID (network name) that the wireless device should associate + * with. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + + DBG_FUNC( "wireless_set_essid" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) { + ret = -EINVAL; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + memset( lp->NetworkName, 0, sizeof( lp->NetworkName )); + + /* data->flags is zero to ask for "any" */ + if( data->flags == 0 ) { + /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP" + * ;?but there ain't no STAP anymore*/ + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) { + strcpy( lp->NetworkName, "ANY" ); + } else { + //strcpy( lp->NetworkName, "ANY" ); + strcpy( lp->NetworkName, PARM_DEFAULT_SSID ); + } + } else { + memcpy( lp->NetworkName, ssid, data->length ); + } + + DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid ); + + /* Commit the adapter parameters */ + wl_apply( lp ); + + /* Send an event that ESSID has been set */ + wl_wext_event_essid( lp->dev ); + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_set_essid +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_get_essid() + ******************************************************************************* + * + * DESCRIPTION: + * + * Gets the ESSID (network name) that the wireless device is associated + * with. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid) + +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + int status = -1; + wvName_t *pName; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_get_essid" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + /* Get the desired network name */ + lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 )); + + +#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA + //;?should we return an error status in AP mode + + lp->ltvRecord.typ = CFG_DESIRED_SSID; + +#endif + + +#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP + //;?should we restore this to allow smaller memory footprint + + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { + lp->ltvRecord.typ = CFG_CNF_OWN_SSID; + } + +#endif // HCF_AP + + + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + if( status == HCF_SUCCESS ) { + pName = (wvName_t *)&( lp->ltvRecord.u.u32 ); + + /* Endian translate the string length */ + pName->length = CNV_LITTLE_TO_INT( pName->length ); + + /* Copy the information into the user buffer */ + data->length = pName->length; + + /* NOTE: Null terminating is necessary for proper display of the SSID in + the wireless tools */ + data->length = pName->length + 1; + if( pName->length < HCF_MAX_NAME_LEN ) { + pName->name[pName->length] = '\0'; + } + + data->flags = 1; + + +#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA + //;?should we return an error status in AP mode +#ifdef RETURN_CURRENT_NETWORKNAME + + /* if desired is null ("any"), return current or "any" */ + if( pName->name[0] == '\0' ) { + /* Get the current network name */ + lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 )); + lp->ltvRecord.typ = CFG_CUR_SSID; + + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + + if( status == HCF_SUCCESS ) { + pName = (wvName_t *)&( lp->ltvRecord.u.u32 ); + + /* Endian translate the string length */ + pName->length = CNV_LITTLE_TO_INT( pName->length ); + + /* Copy the information into the user buffer */ + data->length = pName->length + 1; + if( pName->length < HCF_MAX_NAME_LEN ) { + pName->name[pName->length] = '\0'; + } + + data->flags = 1; + } else { + ret = -EFAULT; + goto out_unlock; + } + } + +#endif // RETURN_CURRENT_NETWORKNAME +#endif // HCF_STA + + data->length--; + + if (pName->length > IW_ESSID_MAX_SIZE) { + ret = -EFAULT; + goto out_unlock; + } + + memcpy(essid, pName->name, pName->length); + } else { + ret = -EFAULT; + goto out_unlock; + } + +out_unlock: + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_get_essid +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_set_encode() + ******************************************************************************* + * + * DESCRIPTION: + * + * Sets the encryption keys and status (enable or disable). + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + +#if 1 //;? #if WIRELESS_EXT > 8 - used unconditionally in the rest of the code... + hcf_8 encryption_state; +#endif // WIRELESS_EXT > 8 + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_set_encode" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + /* Is encryption supported? */ + if( !wl_has_wep( &( lp->hcfCtx ))) { + DBG_WARNING( DbgInfo, "WEP not supported on this device\n" ); + ret = -EOPNOTSUPP; + goto out_unlock; + } + + DBG_NOTICE( DbgInfo, "pointer: %p, length: %d, flags: %#x\n", + keybuf, erq->length, + erq->flags); + + /* Save state of Encryption switch */ + encryption_state = lp->EnableEncryption; + + /* Basic checking: do we have a key to set? */ + if((erq->length) != 0) { + int index = ( erq->flags & IW_ENCODE_INDEX ) - 1; + int tk = lp->TransmitKeyID - 1; // current key + + + /* Check the size of the key */ + switch(erq->length) { + case 0: + break; + + case MIN_KEY_SIZE: + case MAX_KEY_SIZE: + + /* Check the index */ + if(( index < 0 ) || ( index >= MAX_KEYS )) { + index = tk; + } + + /* Cleanup */ + memset( lp->DefaultKeys.key[index].key, 0, MAX_KEY_SIZE ); + + /* Copy the key in the driver */ + memcpy( lp->DefaultKeys.key[index].key, keybuf, erq->length); + + /* Set the length */ + lp->DefaultKeys.key[index].len = erq->length; + + DBG_NOTICE( DbgInfo, "encoding.length: %d\n", erq->length ); + DBG_NOTICE( DbgInfo, "set key: %s(%d) [%d]\n", lp->DefaultKeys.key[index].key, + lp->DefaultKeys.key[index].len, index ); + + /* Enable WEP (if possible) */ + if(( index == tk ) && ( lp->DefaultKeys.key[tk].len > 0 )) { + lp->EnableEncryption = 1; + } + + break; + + default: + DBG_WARNING( DbgInfo, "Invalid Key length\n" ); + ret = -EINVAL; + goto out_unlock; + } + } else { + int index = ( erq->flags & IW_ENCODE_INDEX ) - 1; + + + /* Do we want to just set the current transmit key? */ + if(( index >= 0 ) && ( index < MAX_KEYS )) { + DBG_NOTICE( DbgInfo, "index: %d; len: %d\n", index, + lp->DefaultKeys.key[index].len ); + + if( lp->DefaultKeys.key[index].len > 0 ) { + lp->TransmitKeyID = index + 1; + lp->EnableEncryption = 1; + } else { + DBG_WARNING( DbgInfo, "Problem setting the current TxKey\n" ); + DBG_LEAVE( DbgInfo ); + ret = -EINVAL; + } + } + } + + /* Read the flags */ + if( erq->flags & IW_ENCODE_DISABLED ) { + lp->EnableEncryption = 0; // disable encryption + } else { + lp->EnableEncryption = 1; + } + + if( erq->flags & IW_ENCODE_RESTRICTED ) { + DBG_WARNING( DbgInfo, "IW_ENCODE_RESTRICTED invalid\n" ); + ret = -EINVAL; // Invalid + } + + DBG_TRACE( DbgInfo, "encryption_state : %d\n", encryption_state ); + DBG_TRACE( DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption ); + DBG_TRACE( DbgInfo, "erq->length : %d\n", + erq->length); + DBG_TRACE( DbgInfo, "erq->flags : 0x%x\n", + erq->flags); + + /* Write the changes to the card */ + if( ret == 0 ) { + DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption, + lp->TransmitKeyID ); + + if( lp->EnableEncryption == encryption_state ) { + if( erq->length != 0 ) { + /* Dynamic WEP key update */ + wl_set_wep_keys( lp ); + } + } else { + /* To switch encryption on/off, soft reset is required */ + wl_apply( lp ); + } + } + + /* Send an event that Encryption has been set */ + wl_wext_event_encode( dev ); + +out_unlock: + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_set_encode +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_get_encode() + ******************************************************************************* + * + * DESCRIPTION: + * + * Gets the encryption keys and status. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key) + +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + int index; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_get_encode" ); + DBG_ENTER( DbgInfo ); + DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + /* Only super-user can see WEP key */ + if( !capable( CAP_NET_ADMIN )) { + ret = -EPERM; + DBG_LEAVE( DbgInfo ); + return ret; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + /* Is it supported? */ + if( !wl_has_wep( &( lp->hcfCtx ))) { + ret = -EOPNOTSUPP; + goto out_unlock; + } + + /* Basic checking */ + index = (erq->flags & IW_ENCODE_INDEX ) - 1; + + + /* Set the flags */ + erq->flags = 0; + + if( lp->EnableEncryption == 0 ) { + erq->flags |= IW_ENCODE_DISABLED; + } + + /* Which key do we want */ + if(( index < 0 ) || ( index >= MAX_KEYS )) { + index = lp->TransmitKeyID - 1; + } + + erq->flags |= index + 1; + + /* Copy the key to the user buffer */ + erq->length = lp->DefaultKeys.key[index].len; + + memcpy(key, lp->DefaultKeys.key[index].key, erq->length); + +out_unlock: + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_get_encode +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_set_nickname() + ******************************************************************************* + * + * DESCRIPTION: + * + * Sets the nickname, or station name, of the wireless device. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_set_nickname" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + +#if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version + if( !capable(CAP_NET_ADMIN )) { + ret = -EPERM; + DBG_LEAVE( DbgInfo ); + return ret; + } +#endif + + /* Validate the new value */ + if(data->length > HCF_MAX_NAME_LEN) { + ret = -EINVAL; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + memset( lp->StationName, 0, sizeof( lp->StationName )); + + memcpy( lp->StationName, nickname, data->length ); + + /* Commit the adapter parameters */ + wl_apply( lp ); + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_set_nickname +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_get_nickname() + ******************************************************************************* + * + * DESCRIPTION: + * + * Gets the nickname, or station name, of the wireless device. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + int status = -1; + wvName_t *pName; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_get_nickname" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + /* Get the current station name */ + lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 )); + lp->ltvRecord.typ = CFG_CNF_OWN_NAME; + + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + + if( status == HCF_SUCCESS ) { + pName = (wvName_t *)&( lp->ltvRecord.u.u32 ); + + /* Endian translate the length */ + pName->length = CNV_LITTLE_TO_INT( pName->length ); + + if ( pName->length > IW_ESSID_MAX_SIZE ) { + ret = -EFAULT; + } else { + /* Copy the information into the user buffer */ + data->length = pName->length; + memcpy(nickname, pName->name, pName->length); + } + } else { + ret = -EFAULT; + } + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE(DbgInfo); + return ret; +} // wireless_get_nickname +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_set_porttype() + ******************************************************************************* + * + * DESCRIPTION: + * + * Sets the port type of the wireless device. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + hcf_16 portType; + hcf_16 createIBSS; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wireless_set_porttype" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + /* Validate the new value */ + switch( *mode ) { + case IW_MODE_ADHOC: + + /* When user requests ad-hoc, set IBSS mode! */ + portType = 1; + createIBSS = 1; + + lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1; + + break; + + + case IW_MODE_AUTO: + case IW_MODE_INFRA: + + /* Both automatic and infrastructure set port to BSS/STA mode */ + portType = 1; + createIBSS = 0; + + lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1; + + break; + + +#if 0 //;? (HCF_TYPE) & HCF_TYPE_AP + + case IW_MODE_MASTER: + + /* Set BSS/AP mode */ + portType = 1; + + lp->CreateIBSS = 0; + lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2; + + break; + +#endif /* (HCF_TYPE) & HCF_TYPE_AP */ + + + default: + + portType = 0; + createIBSS = 0; + ret = -EINVAL; + } + + if( portType != 0 ) { + /* Only do something if there is a mode change */ + if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) { + lp->PortType = portType; + lp->CreateIBSS = createIBSS; + + /* Commit the adapter parameters */ + wl_go( lp ); + + /* Send an event that mode has been set */ + wl_wext_event_mode( lp->dev ); + } + } + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_set_porttype +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_get_porttype() + ******************************************************************************* + * + * DESCRIPTION: + * + * Gets the port type of the wireless device. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra) + +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + int status = -1; + hcf_16 *pPortType; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_get_porttype" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + /* Get the current port type */ + lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 )); + lp->ltvRecord.typ = CFG_CNF_PORT_TYPE; + + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + + if( status == HCF_SUCCESS ) { + pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 ); + + *pPortType = CNV_LITTLE_TO_INT( *pPortType ); + + switch( *pPortType ) { + case 1: + +#if 0 +#if (HCF_TYPE) & HCF_TYPE_AP + + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { + *mode = IW_MODE_MASTER; + } else { + *mode = IW_MODE_INFRA; + } + +#else + + *mode = IW_MODE_INFRA; + +#endif /* (HCF_TYPE) & HCF_TYPE_AP */ +#endif + + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { + *mode = IW_MODE_MASTER; + } else { + if( lp->CreateIBSS ) { + *mode = IW_MODE_ADHOC; + } else { + *mode = IW_MODE_INFRA; + } + } + + break; + + + case 3: + *mode = IW_MODE_ADHOC; + break; + + default: + ret = -EFAULT; + break; + } + } else { + ret = -EFAULT; + } + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_get_porttype +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_set_power() + ******************************************************************************* + * + * DESCRIPTION: + * + * Sets the power management settings of the wireless device. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_set_power" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" ); + +#if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version + if( !capable( CAP_NET_ADMIN )) { + ret = -EPERM; + + DBG_LEAVE( DbgInfo ); + return ret; + } +#endif + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + /* Set the power management state based on the 'disabled' value */ + if( wrq->disabled ) { + lp->PMEnabled = 0; + } else { + lp->PMEnabled = 1; + } + + /* Commit the adapter parameters */ + wl_apply( lp ); + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_set_power +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_get_power() + ******************************************************************************* + * + * DESCRIPTION: + * + * Gets the power management settings of the wireless device. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra) + +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wireless_get_power" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" ); + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + rrq->flags = 0; + rrq->value = 0; + + if( lp->PMEnabled ) { + rrq->disabled = 0; + } else { + rrq->disabled = 1; + } + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_get_power +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_get_tx_power() + ******************************************************************************* + * + * DESCRIPTION: + * + * Gets the transmit power of the wireless device's radio. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + /*------------------------------------------------------------------------*/ + DBG_FUNC( "wireless_get_tx_power" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + +#ifdef USE_POWER_DBM + rrq->value = RADIO_TX_POWER_DBM; + rrq->flags = IW_TXPOW_DBM; +#else + rrq->value = RADIO_TX_POWER_MWATT; + rrq->flags = IW_TXPOW_MWATT; +#endif + rrq->fixed = 1; + rrq->disabled = 0; + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_get_tx_power +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_set_rts_threshold() + ******************************************************************************* + * + * DESCRIPTION: + * + * Sets the RTS threshold for the wireless card. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra) +{ + int ret = 0; + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int rthr = rts->value; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_set_rts_threshold" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + if(rts->fixed == 0) { + ret = -EINVAL; + goto out; + } + +#if WIRELESS_EXT > 8 + if( rts->disabled ) { + rthr = 2347; + } +#endif /* WIRELESS_EXT > 8 */ + + if(( rthr < 256 ) || ( rthr > 2347 )) { + ret = -EINVAL; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + lp->RTSThreshold = rthr; + + wl_apply( lp ); + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_set_rts_threshold +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_get_rts_threshold() + ******************************************************************************* + * + * DESCRIPTION: + * + * Gets the RTS threshold for the wireless card. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra) +{ + int ret = 0; + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wireless_get_rts_threshold" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + rts->value = lp->RTSThreshold; + +#if WIRELESS_EXT > 8 + + rts->disabled = ( rts->value == 2347 ); + +#endif /* WIRELESS_EXT > 8 */ + + rts->fixed = 1; + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_get_rts_threshold +/*============================================================================*/ + + + + + +/******************************************************************************* + * wireless_set_rate() + ******************************************************************************* + * + * DESCRIPTION: + * + * Set the default data rate setting used by the wireless device. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; +#ifdef WARP + int status = -1; + int index = 0; +#endif // WARP + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_set_rate" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + +#ifdef WARP + + /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check + if Bit 9 is set in the current channel RID */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CUR_CHANNEL; + + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + + if( status == HCF_SUCCESS ) { + index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0; + + DBG_PRINT( "Index: %d\n", index ); + } else { + DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" ); + DBG_LEAVE( DbgInfo ); + ret = -EINVAL; + goto out_unlock; + } + + if( rrq->value > 0 && + rrq->value <= 1 * MEGABIT ) { + lp->TxRateControl[index] = 0x0001; + } + else if( rrq->value > 1 * MEGABIT && + rrq->value <= 2 * MEGABIT ) { + if( rrq->fixed == 1 ) { + lp->TxRateControl[index] = 0x0002; + } else { + lp->TxRateControl[index] = 0x0003; + } + } + else if( rrq->value > 2 * MEGABIT && + rrq->value <= 5 * MEGABIT ) { + if( rrq->fixed == 1 ) { + lp->TxRateControl[index] = 0x0004; + } else { + lp->TxRateControl[index] = 0x0007; + } + } + else if( rrq->value > 5 * MEGABIT && + rrq->value <= 6 * MEGABIT ) { + if( rrq->fixed == 1 ) { + lp->TxRateControl[index] = 0x0010; + } else { + lp->TxRateControl[index] = 0x0017; + } + } + else if( rrq->value > 6 * MEGABIT && + rrq->value <= 9 * MEGABIT ) { + if( rrq->fixed == 1 ) { + lp->TxRateControl[index] = 0x0020; + } else { + lp->TxRateControl[index] = 0x0037; + } + } + else if( rrq->value > 9 * MEGABIT && + rrq->value <= 11 * MEGABIT ) { + if( rrq->fixed == 1 ) { + lp->TxRateControl[index] = 0x0008; + } else { + lp->TxRateControl[index] = 0x003F; + } + } + else if( rrq->value > 11 * MEGABIT && + rrq->value <= 12 * MEGABIT ) { + if( rrq->fixed == 1 ) { + lp->TxRateControl[index] = 0x0040; + } else { + lp->TxRateControl[index] = 0x007F; + } + } + else if( rrq->value > 12 * MEGABIT && + rrq->value <= 18 * MEGABIT ) { + if( rrq->fixed == 1 ) { + lp->TxRateControl[index] = 0x0080; + } else { + lp->TxRateControl[index] = 0x00FF; + } + } + else if( rrq->value > 18 * MEGABIT && + rrq->value <= 24 * MEGABIT ) { + if( rrq->fixed == 1 ) { + lp->TxRateControl[index] = 0x0100; + } else { + lp->TxRateControl[index] = 0x01FF; + } + } + else if( rrq->value > 24 * MEGABIT && + rrq->value <= 36 * MEGABIT ) { + if( rrq->fixed == 1 ) { + lp->TxRateControl[index] = 0x0200; + } else { + lp->TxRateControl[index] = 0x03FF; + } + } + else if( rrq->value > 36 * MEGABIT && + rrq->value <= 48 * MEGABIT ) { + if( rrq->fixed == 1 ) { + lp->TxRateControl[index] = 0x0400; + } else { + lp->TxRateControl[index] = 0x07FF; + } + } + else if( rrq->value > 48 * MEGABIT && + rrq->value <= 54 * MEGABIT ) { + if( rrq->fixed == 1 ) { + lp->TxRateControl[index] = 0x0800; + } else { + lp->TxRateControl[index] = 0x0FFF; + } + } + else if( rrq->fixed == 0 ) { + /* In this case, the user has not specified a bitrate, only the "auto" + moniker. So, set to all supported rates */ + lp->TxRateControl[index] = PARM_MAX_TX_RATE; + } else { + rrq->value = 0; + ret = -EINVAL; + goto out_unlock; + } + + +#else + + if( rrq->value > 0 && + rrq->value <= 1 * MEGABIT ) { + lp->TxRateControl[0] = 1; + } + else if( rrq->value > 1 * MEGABIT && + rrq->value <= 2 * MEGABIT ) { + if( rrq->fixed ) { + lp->TxRateControl[0] = 2; + } else { + lp->TxRateControl[0] = 6; + } + } + else if( rrq->value > 2 * MEGABIT && + rrq->value <= 5 * MEGABIT ) { + if( rrq->fixed ) { + lp->TxRateControl[0] = 4; + } else { + lp->TxRateControl[0] = 7; + } + } + else if( rrq->value > 5 * MEGABIT && + rrq->value <= 11 * MEGABIT ) { + if( rrq->fixed) { + lp->TxRateControl[0] = 5; + } else { + lp->TxRateControl[0] = 3; + } + } + else if( rrq->fixed == 0 ) { + /* In this case, the user has not specified a bitrate, only the "auto" + moniker. So, set the rate to 11Mb auto */ + lp->TxRateControl[0] = 3; + } else { + rrq->value = 0; + ret = -EINVAL; + goto out_unlock; + } + +#endif // WARP + + + /* Commit the adapter parameters */ + wl_apply( lp ); + +out_unlock: + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_set_rate +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_get_rate() + ******************************************************************************* + * + * DESCRIPTION: + * + * Get the default data rate setting used by the wireless device. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra) + +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + int status = -1; + hcf_16 txRate; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_get_rate" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + /* Get the current transmit rate from the adapter */ + lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16)); + lp->ltvRecord.typ = CFG_CUR_TX_RATE; + + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + + if( status == HCF_SUCCESS ) { +#ifdef WARP + + txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ); + + if( txRate & 0x0001 ) { + txRate = 1; + } + else if( txRate & 0x0002 ) { + txRate = 2; + } + else if( txRate & 0x0004 ) { + txRate = 5; + } + else if( txRate & 0x0008 ) { + txRate = 11; + } + else if( txRate & 0x00010 ) { + txRate = 6; + } + else if( txRate & 0x00020 ) { + txRate = 9; + } + else if( txRate & 0x00040 ) { + txRate = 12; + } + else if( txRate & 0x00080 ) { + txRate = 18; + } + else if( txRate & 0x00100 ) { + txRate = 24; + } + else if( txRate & 0x00200 ) { + txRate = 36; + } + else if( txRate & 0x00400 ) { + txRate = 48; + } + else if( txRate & 0x00800 ) { + txRate = 54; + } + +#else + + txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] ); + +#endif // WARP + + rrq->value = txRate * MEGABIT; + } else { + rrq->value = 0; + ret = -EFAULT; + } + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_get_rate +/*============================================================================*/ + + + + +#if 0 //;? Not used anymore +/******************************************************************************* + * wireless_get_private_interface() + ******************************************************************************* + * + * DESCRIPTION: + * + * Returns the Linux Wireless Extensions' compatible private interface of + * the driver. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp ) +{ + int ret = 0; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_get_private_interface" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + if( wrq->u.data.pointer != NULL ) { + struct iw_priv_args priv[] = + { + { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" }, + { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" }, + { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" }, + { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" }, + { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" }, + { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" }, + }; + + /* Verify the user buffer */ + ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv )); + + if( ret != 0 ) { + DBG_LEAVE( DbgInfo ); + return ret; + } + + /* Copy the data into the user's buffer */ + wrq->u.data.length = NELEM( priv ); + copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv )); + } + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_get_private_interface +/*============================================================================*/ +#endif + + + +#if WIRELESS_EXT > 13 + +/******************************************************************************* + * wireless_set_scan() + ******************************************************************************* + * + * DESCRIPTION: + * + * Instructs the driver to initiate a network scan. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + int status = -1; + int retries = 0; + /*------------------------------------------------------------------------*/ + + //;? Note: shows results as trace, retruns always 0 unless BUSY + + DBG_FUNC( "wireless_set_scan" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + /* + * This looks like a nice place to test if the HCF is still + * communicating with the card. It seems that sometimes BAP_1 + * gets corrupted. By looking at the comments in HCF the + * cause is still a mistery. Okay, the communication to the + * card is dead, reset the card to revive. + */ + if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0) + { + DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" ); + wl_reset( dev ); + } + +retry: + /* Set the completion state to FALSE */ + lp->probe_results.scan_complete = FALSE; + + + /* Channels to scan */ +#ifdef WARP + lp->ltvRecord.len = 5; + lp->ltvRecord.typ = CFG_SCAN_CHANNEL; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band + lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band + lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // .. + lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // .. +#else + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_SCAN_CHANNEL; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF ); +#endif // WARP + + status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + + DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status ); + + // Holding the lock too long, make a gap to allow other processes + wl_unlock(lp, &flags); + wl_lock( lp, &flags ); + + if( status != HCF_SUCCESS ) { + //Recovery + retries++; + if(retries <= 10) { + DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries ); + wl_reset( dev ); + + // Holding the lock too long, make a gap to allow other processes + wl_unlock(lp, &flags); + wl_lock( lp, &flags ); + + goto retry; + } + } + + /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to + disassociate from the network we are currently on */ + lp->ltvRecord.len = 18; + lp->ltvRecord.typ = CFG_SCAN_SSID; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); + lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 ); + + status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + + // Holding the lock too long, make a gap to allow other processes + wl_unlock(lp, &flags); + wl_lock( lp, &flags ); + + DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status ); + + /* Initiate the scan */ + /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to + retrieve probe responses must always be used to support WPA */ + status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN ); + + if( status == HCF_SUCCESS ) { + DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" ); + } else { + DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" ); + } + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE(DbgInfo); + return ret; +} // wireless_set_scan +/*============================================================================*/ + + + + +/******************************************************************************* + * wireless_get_scan() + ******************************************************************************* + * + * DESCRIPTION: + * + * Instructs the driver to gather and return the results of a network scan. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + int count; + char *buf; + char *buf_end; + struct iw_event iwe; + PROBE_RESP *probe_resp; + hcf_8 msg[512]; + hcf_8 *wpa_ie; + hcf_16 wpa_ie_len; + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wireless_get_scan" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + /* If the scan is not done, tell the calling process to try again later */ + if( !lp->probe_results.scan_complete ) { + ret = -EAGAIN; + goto out_unlock; + } + + DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n", + lp->probe_results.num_aps ); + + buf = extra; + buf_end = extra + IW_SCAN_MAX_DATA; + + for( count = 0; count < lp->probe_results.num_aps; count++ ) { + /* Reference the probe response from the table */ + probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count]; + + + /* First entry MUST be the MAC address */ + memset( &iwe, 0, sizeof( iwe )); + + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN); + iwe.len = IW_EV_ADDR_LEN; + + buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_ADDR_LEN); + + + /* Use the mode to indicate if it's a station or AP */ + /* Won't always be an AP if in IBSS mode */ + memset( &iwe, 0, sizeof( iwe )); + + iwe.cmd = SIOCGIWMODE; + + if( probe_resp->capability & CAPABILITY_IBSS ) { + iwe.u.mode = IW_MODE_INFRA; + } else { + iwe.u.mode = IW_MODE_MASTER; + } + + iwe.len = IW_EV_UINT_LEN; + + buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_UINT_LEN); + + + /* Any quality information */ + memset(&iwe, 0, sizeof(iwe)); + + iwe.cmd = IWEVQUAL; + iwe.u.qual.level = dbm(probe_resp->signal); + iwe.u.qual.noise = dbm(probe_resp->silence); + iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise; + iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM; + iwe.len = IW_EV_QUAL_LEN; + + buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_QUAL_LEN); + + + /* ESSID information */ + if( probe_resp->rawData[1] > 0 ) { + memset( &iwe, 0, sizeof( iwe )); + + iwe.cmd = SIOCGIWESSID; + iwe.u.data.length = probe_resp->rawData[1]; + iwe.u.data.flags = 1; + + buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, &probe_resp->rawData[2]); + } + + + /* Encryption Information */ + memset( &iwe, 0, sizeof( iwe )); + + iwe.cmd = SIOCGIWENCODE; + iwe.u.data.length = 0; + + /* Check the capabilities field of the Probe Response to see if + 'privacy' is supported on the AP in question */ + if( probe_resp->capability & CAPABILITY_PRIVACY ) { + iwe.u.data.flags |= IW_ENCODE_ENABLED; + } else { + iwe.u.data.flags |= IW_ENCODE_DISABLED; + } + + buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, NULL); + + + /* Frequency Info */ + memset( &iwe, 0, sizeof( iwe )); + + iwe.cmd = SIOCGIWFREQ; + iwe.len = IW_EV_FREQ_LEN; + iwe.u.freq.m = wl_parse_ds_ie( probe_resp ); + iwe.u.freq.e = 0; + + buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_FREQ_LEN); + + +#if WIRELESS_EXT > 14 + /* Custom info (Beacon Interval) */ + memset( &iwe, 0, sizeof( iwe )); + memset( msg, 0, sizeof( msg )); + + iwe.cmd = IWEVCUSTOM; + sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval ); + iwe.u.data.length = strlen( msg ); + + buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg); + + + /* Custom info (WPA-IE) */ + wpa_ie = NULL; + wpa_ie_len = 0; + + wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len ); + if( wpa_ie != NULL ) { + memset( &iwe, 0, sizeof( iwe )); + memset( msg, 0, sizeof( msg )); + + iwe.cmd = IWEVCUSTOM; + sprintf( msg, "wpa_ie=%s", wl_print_wpa_ie( wpa_ie, wpa_ie_len )); + iwe.u.data.length = strlen( msg ); + + buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg); + } + + /* Add other custom info in formatted string format as needed... */ +#endif + } + + data->length = buf - extra; + +out_unlock: + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_get_scan +/*============================================================================*/ + +#endif // WIRELESS_EXT > 13 + + +#if WIRELESS_EXT > 17 + +static int wireless_set_auth(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *data, char *extra) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret; + int iwa_idx = data->flags & IW_AUTH_INDEX; + int iwa_val = data->value; + + DBG_FUNC( "wireless_set_auth" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + switch (iwa_idx) { + case IW_AUTH_WPA_VERSION: + DBG_TRACE( DbgInfo, "IW_AUTH_WPA_VERSION\n"); + /* We do support WPA only; how should DISABLED be treated? */ + if (iwa_val == IW_AUTH_WPA_VERSION_WPA) + ret = 0; + else + ret = -EINVAL; + break; + + case IW_AUTH_WPA_ENABLED: + DBG_TRACE( DbgInfo, "IW_AUTH_WPA_ENABLED: val = %d\n", iwa_val); + if (iwa_val) + lp->EnableEncryption = 2; + else + lp->EnableEncryption = 0; + ret = 0; + break; + + case IW_AUTH_TKIP_COUNTERMEASURES: + DBG_TRACE( DbgInfo, "IW_AUTH_TKIP_COUNTERMEASURES\n"); + lp->driverEnable = !iwa_val; + if(lp->driverEnable) + hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0); + else + hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0); + ret = 0; + break; + + case IW_AUTH_DROP_UNENCRYPTED: + DBG_TRACE( DbgInfo, "IW_AUTH_DROP_UNENCRYPTED\n"); + /* We do not actually do anything here, just to silence + * wpa_supplicant */ + ret = 0; + break; + + case IW_AUTH_CIPHER_PAIRWISE: + DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_PAIRWISE\n"); + /* not implemented, return an error */ + ret = -EINVAL; + break; + + case IW_AUTH_CIPHER_GROUP: + DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_GROUP\n"); + /* not implemented, return an error */ + ret = -EINVAL; + break; + + case IW_AUTH_KEY_MGMT: + DBG_TRACE( DbgInfo, "IW_AUTH_KEY_MGMT\n"); + /* not implemented, return an error */ + ret = -EINVAL; + break; + + case IW_AUTH_80211_AUTH_ALG: + DBG_TRACE( DbgInfo, "IW_AUTH_80211_AUTH_ALG\n"); + /* not implemented, return an error */ + ret = -EINVAL; + break; + + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + DBG_TRACE( DbgInfo, "IW_AUTH_RX_UNENCRYPTED_EAPOL\n"); + /* not implemented, return an error */ + ret = -EINVAL; + break; + + case IW_AUTH_ROAMING_CONTROL: + DBG_TRACE( DbgInfo, "IW_AUTH_ROAMING_CONTROL\n"); + /* not implemented, return an error */ + ret = -EINVAL; + break; + + case IW_AUTH_PRIVACY_INVOKED: + DBG_TRACE( DbgInfo, "IW_AUTH_PRIVACY_INVOKED\n"); + /* not implemented, return an error */ + ret = -EINVAL; + break; + + default: + DBG_TRACE( DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx); + /* return an error */ + ret = -EINVAL; + break; + } + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_set_auth +/*============================================================================*/ + + + +static int hermes_set_key(ltv_t *ltv, int alg, int key_idx, u8 *addr, + int set_tx, u8 *seq, u8 *key, size_t key_len) +{ + int ret = -EINVAL; + // int count = 0; + int buf_idx = 0; + hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] = + { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 }; + + DBG_FUNC( "hermes_set_key" ); + DBG_ENTER( DbgInfo ); + + /* + * Check the key index here; if 0, load as Pairwise Key, otherwise, + * load as a group key. Note that for the Hermes, the RIDs for + * group/pariwise keys are different from each other and different + * than the default WEP keys as well. + */ + switch (alg) + { + case IW_ENCODE_ALG_TKIP: + DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx); +#if 0 + /* + * Make sure that there is no data queued up in the firmware + * before setting the TKIP keys. If this check is not + * performed, some data may be sent out with incorrect MIC + * and cause synchronizarion errors with the AP + */ + /* Check every 1ms for 100ms */ + for( count = 0; count < 100; count++ ) + { + usleep( 1000 ); + + ltv.len = 2; + ltv.typ = 0xFD91; // This RID not defined in HCF yet!!! + ltv.u.u16[0] = 0; + + wl_get_info( sock, <v, ifname ); + + if( ltv.u.u16[0] == 0 ) + { + break; + } + } + + if( count == 100 ) + { + wpa_printf( MSG_DEBUG, "Timed out waiting for TxQ!" ); + } +#endif + + switch (key_idx) { + case 0: + ltv->len = 28; + ltv->typ = CFG_ADD_TKIP_MAPPED_KEY; + + /* Load the BSSID */ + memcpy(<v->u.u8[buf_idx], addr, ETH_ALEN); + buf_idx += ETH_ALEN; + + /* Load the TKIP key */ + memcpy(<v->u.u8[buf_idx], &key[0], 16); + buf_idx += 16; + + /* Load the TSC */ + memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE); + buf_idx += IW_ENCODE_SEQ_MAX_SIZE; + + /* Load the RSC */ + memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE); + buf_idx += IW_ENCODE_SEQ_MAX_SIZE; + + /* Load the TxMIC key */ + memcpy(<v->u.u8[buf_idx], &key[16], 8); + buf_idx += 8; + + /* Load the RxMIC key */ + memcpy(<v->u.u8[buf_idx], &key[24], 8); + + ret = 0; + break; + case 1: + case 2: + case 3: + ltv->len = 26; + ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY; + + /* Load the key Index */ + ltv->u.u16[buf_idx] = key_idx; + /* If this is a Tx Key, set bit 8000 */ + if(set_tx) + ltv->u.u16[buf_idx] |= 0x8000; + buf_idx += 2; + + /* Load the RSC */ + memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE); + buf_idx += IW_ENCODE_SEQ_MAX_SIZE; + + /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in + CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */ + memcpy(<v->u.u8[buf_idx], key, key_len); + buf_idx += key_len; + + /* Load the TSC */ + memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE); + + ltv->u.u16[0] = CNV_INT_TO_LITTLE(ltv->u.u16[0]); + + ret = 0; + break; + default: + break; + } + + break; + + case IW_ENCODE_ALG_WEP: + DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx); + break; + + case IW_ENCODE_ALG_CCMP: + DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx); + break; + + case IW_ENCODE_ALG_NONE: + DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx); + switch (key_idx) { + case 0: + if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) { + //if (addr != NULL) { + ltv->len = 7; + ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY; + memcpy(<v->u.u8[0], addr, ETH_ALEN); + ret = 0; + } + break; + case 1: + case 2: + case 3: + /* Clear the Group TKIP keys by index */ + ltv->len = 2; + ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY; + ltv->u.u16[0] = key_idx; + + ret = 0; + break; + default: + break; + } + break; + default: + DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx); + break; + } + + DBG_LEAVE( DbgInfo ); + return ret; +} // hermes_set_key +/*============================================================================*/ + + + +static int wireless_set_encodeext (struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, char *keybuf) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret; + int key_idx = (erq->flags&IW_ENCODE_INDEX) - 1; + ltv_t ltv; + struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf; + + DBG_FUNC( "wireless_set_encodeext" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + if (sizeof(ext->rx_seq) != 8) { + DBG_TRACE(DbgInfo, "rz_seq size mismatch\n"); + DBG_LEAVE(DbgInfo); + return -EINVAL; + } + + /* Handle WEP keys via the old set encode procedure */ + if(ext->alg == IW_ENCODE_ALG_WEP) { + struct iw_point wep_erq; + char *wep_keybuf; + + /* Build request structure */ + wep_erq.flags = erq->flags; // take over flags with key index + wep_erq.length = ext->key_len; // take length from extended key info + wep_keybuf = ext->key; // pointer to the key text + + /* Call wireless_set_encode tot handle the WEP key */ + ret = wireless_set_encode(dev, info, &wep_erq, wep_keybuf); + goto out; + } + + /* Proceed for extended encode functions for WAP and NONE */ + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + memset(<v, 0, sizeof(ltv)); + ret = hermes_set_key(<v, ext->alg, key_idx, ext->addr.sa_data, + ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, + ext->rx_seq, ext->key, ext->key_len); + + if (ret != 0) { + DBG_TRACE( DbgInfo, "hermes_set_key returned != 0, key not set\n"); + goto out_unlock; + } + + /* Put the key in HCF */ + ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v); + +out_unlock: + if(ret == HCF_SUCCESS) { + DBG_TRACE( DbgInfo, "Put key info succes\n"); + } else { + DBG_TRACE( DbgInfo, "Put key info failed, key not set\n"); + } + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} // wireless_set_encodeext +/*============================================================================*/ + + + +static int wireless_get_genie(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) + +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; + ltv_t ltv; + + DBG_FUNC( "wireless_get_genie" ); + DBG_ENTER( DbgInfo ); + + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + + memset(<v, 0, sizeof(ltv)); + ltv.len = 2; + ltv.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE; + lp->AuthKeyMgmtSuite = ltv.u.u16[0] = 4; + ltv.u.u16[0] = CNV_INT_TO_LITTLE(ltv.u.u16[0]); + + ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v); + + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + +out: + DBG_LEAVE( DbgInfo ); + return ret; +} +/*============================================================================*/ + + +#endif // WIRELESS_EXT > 17 + +/******************************************************************************* + * wl_wireless_stats() + ******************************************************************************* + * + * DESCRIPTION: + * + * Return the current device wireless statistics. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +struct iw_statistics * wl_wireless_stats( struct net_device *dev ) +{ + struct iw_statistics *pStats; + struct wl_private *lp = wl_priv(dev); + /*------------------------------------------------------------------------*/ + + + DBG_FUNC( "wl_wireless_stats" ); + DBG_ENTER(DbgInfo); + DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); + + pStats = NULL; + + /* Initialize the statistics */ + pStats = &( lp->wstats ); + pStats->qual.updated = 0x00; + + if( !( lp->flags & WVLAN2_UIL_BUSY )) + { + CFG_COMMS_QUALITY_STRCT *pQual; + CFG_HERMES_TALLIES_STRCT tallies; + int status; + + /* Update driver status */ + pStats->status = 0; + + /* Get the current link quality information */ + lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 )); + lp->ltvRecord.typ = CFG_COMMS_QUALITY; + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + + if( status == HCF_SUCCESS ) { + pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord ); + +#ifdef USE_DBM + pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual ); + pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl )); + pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl )); + + pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED | + IW_QUAL_LEVEL_UPDATED | + IW_QUAL_NOISE_UPDATED | + IW_QUAL_DBM); +#else + pStats->qual.qual = percent( CNV_LITTLE_TO_INT( pQual->coms_qual ), + HCF_MIN_COMM_QUALITY, + HCF_MAX_COMM_QUALITY ); + + pStats->qual.level = percent( CNV_LITTLE_TO_INT( pQual->signal_lvl ), + HCF_MIN_SIGNAL_LEVEL, + HCF_MAX_SIGNAL_LEVEL ); + + pStats->qual.noise = percent( CNV_LITTLE_TO_INT( pQual->noise_lvl ), + HCF_MIN_NOISE_LEVEL, + HCF_MAX_NOISE_LEVEL ); + + pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED | + IW_QUAL_LEVEL_UPDATED | + IW_QUAL_NOISE_UPDATED); +#endif /* USE_DBM */ + } else { + memset( &( pStats->qual ), 0, sizeof( pStats->qual )); + } + + /* Get the current tallies from the adapter */ + /* Only possible when the device is open */ + if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + if( wl_get_tallies( lp, &tallies ) == 0 ) { + /* No endian translation is needed here, as CFG_TALLIES is an + MSF RID; all processing is done on the host, not the card! */ + pStats->discard.nwid = 0L; + pStats->discard.code = tallies.RxWEPUndecryptable; + pStats->discard.misc = tallies.TxDiscards + + tallies.RxFCSErrors + + //tallies.RxDiscardsNoBuffer + + tallies.TxDiscardsWrongSA; + //;? Extra taken over from Linux driver based on 7.18 version + pStats->discard.retries = tallies.TxRetryLimitExceeded; + pStats->discard.fragment = tallies.RxMsgInBadMsgFragments; + } else { + memset( &( pStats->discard ), 0, sizeof( pStats->discard )); + } + } else { + memset( &( pStats->discard ), 0, sizeof( pStats->discard )); + } + } + + DBG_LEAVE( DbgInfo ); + return pStats; +} // wl_wireless_stats +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_get_wireless_stats() + ******************************************************************************* + * + * DESCRIPTION: + * + * Return the current device wireless statistics. This function calls + * wl_wireless_stats, but acquires spinlocks first as it can be called + * directly by the network layer. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +struct iw_statistics * wl_get_wireless_stats( struct net_device *dev ) +{ + unsigned long flags; + struct wl_private *lp = wl_priv(dev); + struct iw_statistics *pStats = NULL; + /*------------------------------------------------------------------------*/ + + DBG_FUNC( "wl_get_wireless_stats" ); + DBG_ENTER(DbgInfo); + + wl_lock( lp, &flags ); + + wl_act_int_off( lp ); + +#ifdef USE_RTS + if( lp->useRTS == 1 ) { + DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" ); + } else +#endif + { + pStats = wl_wireless_stats( dev ); + } + wl_act_int_on( lp ); + + wl_unlock(lp, &flags); + + DBG_LEAVE( DbgInfo ); + return pStats; +} // wl_get_wireless_stats + + +/******************************************************************************* + * wl_spy_gather() + ******************************************************************************* + * + * DESCRIPTION: + * + * Gather wireless spy statistics. + * + * PARAMETERS: + * + * wrq - the wireless request buffer + * lp - the device's private adapter structure + * + * RETURNS: + * + * 0 on success + * errno value otherwise + * + ******************************************************************************/ +inline void wl_spy_gather( struct net_device *dev, u_char *mac ) +{ + struct iw_quality wstats; + int status; + u_char stats[2]; + DESC_STRCT desc[1]; + struct wl_private *lp = wl_priv(dev); + /*------------------------------------------------------------------------*/ + + /* shortcut */ + if (!lp->spy_data.spy_number) { + return; + } + + /* Gather wireless spy statistics: for each packet, compare the source + address with out list, and if match, get the stats. */ + memset( stats, 0, sizeof(stats)); + memset( desc, 0, sizeof(DESC_STRCT)); + + desc[0].buf_addr = stats; + desc[0].BUF_SIZE = sizeof(stats); + desc[0].next_desc_addr = 0; // terminate list + + status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 ); + + if( status == HCF_SUCCESS ) { + wstats.level = (u_char) dbm(stats[1]); + wstats.noise = (u_char) dbm(stats[0]); + wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0; + + wstats.updated = (IW_QUAL_QUAL_UPDATED | + IW_QUAL_LEVEL_UPDATED | + IW_QUAL_NOISE_UPDATED | + IW_QUAL_DBM); + + wireless_spy_update( dev, mac, &wstats ); + } +} // wl_spy_gather +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_wext_event_freq() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function is used to send an event that the channel/freq + * configuration for a specific device has changed. + * + * + * PARAMETERS: + * + * dev - the network device for which this event is to be issued + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wext_event_freq( struct net_device *dev ) +{ +#if WIRELESS_EXT > 13 + union iwreq_data wrqu; + struct wl_private *lp = wl_priv(dev); + /*------------------------------------------------------------------------*/ + + + memset( &wrqu, 0, sizeof( wrqu )); + + wrqu.freq.m = lp->Channel; + wrqu.freq.e = 0; + + wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL ); +#endif /* WIRELESS_EXT > 13 */ + + return; +} // wl_wext_event_freq +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_wext_event_mode() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function is used to send an event that the mode of operation + * for a specific device has changed. + * + * + * PARAMETERS: + * + * dev - the network device for which this event is to be issued + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wext_event_mode( struct net_device *dev ) +{ +#if WIRELESS_EXT > 13 + union iwreq_data wrqu; + struct wl_private *lp = wl_priv(dev); + /*------------------------------------------------------------------------*/ + + + memset( &wrqu, 0, sizeof( wrqu )); + + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) { + wrqu.mode = IW_MODE_INFRA; + } else { + wrqu.mode = IW_MODE_MASTER; + } + + wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL ); +#endif /* WIRELESS_EXT > 13 */ + + return; +} // wl_wext_event_mode +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_wext_event_essid() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function is used to send an event that the ESSID configuration for + * a specific device has changed. + * + * + * PARAMETERS: + * + * dev - the network device for which this event is to be issued + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wext_event_essid( struct net_device *dev ) +{ +#if WIRELESS_EXT > 13 + union iwreq_data wrqu; + struct wl_private *lp = wl_priv(dev); + /*------------------------------------------------------------------------*/ + + + memset( &wrqu, 0, sizeof( wrqu )); + + /* Fill out the buffer. Note that the buffer doesn't actually contain the + ESSID, but a pointer to the contents. In addition, the 'extra' field of + the call to wireless_send_event() must also point to where the ESSID + lives */ + wrqu.essid.length = strlen( lp->NetworkName ); + wrqu.essid.pointer = (caddr_t)lp->NetworkName; + wrqu.essid.flags = 1; + + wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName ); +#endif /* WIRELESS_EXT > 13 */ + + return; +} // wl_wext_event_essid +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_wext_event_encode() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function is used to send an event that the encryption configuration + * for a specific device has changed. + * + * + * PARAMETERS: + * + * dev - the network device for which this event is to be issued + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wext_event_encode( struct net_device *dev ) +{ +#if WIRELESS_EXT > 13 + union iwreq_data wrqu; + struct wl_private *lp = wl_priv(dev); + int index = 0; + /*------------------------------------------------------------------------*/ + + + memset( &wrqu, 0, sizeof( wrqu )); + + if( lp->EnableEncryption == 0 ) { + wrqu.encoding.flags = IW_ENCODE_DISABLED; + } else { + wrqu.encoding.flags |= lp->TransmitKeyID; + + index = lp->TransmitKeyID - 1; + + /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted + if we're in AP mode */ +#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP + //;?should we restore this to allow smaller memory footprint + + if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { + if( lp->ExcludeUnencrypted ) { + wrqu.encoding.flags |= IW_ENCODE_RESTRICTED; + } else { + wrqu.encoding.flags |= IW_ENCODE_OPEN; + } + } + +#endif // HCF_TYPE_AP + + /* Only provide the key if permissions allow */ + if( capable( CAP_NET_ADMIN )) { + wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key; + wrqu.encoding.length = lp->DefaultKeys.key[index].len; + } else { + wrqu.encoding.flags |= IW_ENCODE_NOKEY; + } + } + + wireless_send_event( dev, SIOCSIWENCODE, &wrqu, + lp->DefaultKeys.key[index].key ); +#endif /* WIRELESS_EXT > 13 */ + + return; +} // wl_wext_event_encode +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_wext_event_ap() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function is used to send an event that the device has been + * associated to a new AP. + * + * + * PARAMETERS: + * + * dev - the network device for which this event is to be issued + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wext_event_ap( struct net_device *dev ) +{ +#if WIRELESS_EXT > 13 + union iwreq_data wrqu; + struct wl_private *lp = wl_priv(dev); + int status; + /*------------------------------------------------------------------------*/ + + + /* Retrieve the WPA-IEs used by the firmware and send an event. We must send + this event BEFORE sending the association event, as there are timing + issues with the hostap supplicant. The supplicant will attempt to process + an EAPOL-Key frame from an AP before receiving this information, which + is required properly process the said frame. */ + wl_wext_event_assoc_ie( dev ); + + /* Get the BSSID */ + lp->ltvRecord.typ = CFG_CUR_BSSID; + lp->ltvRecord.len = 4; + + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + if( status == HCF_SUCCESS ) { + memset( &wrqu, 0, sizeof( wrqu )); + + memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN ); + + wrqu.addr.sa_family = ARPHRD_ETHER; + + wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL ); + } + +#endif /* WIRELESS_EXT > 13 */ + + return; +} // wl_wext_event_ap +/*============================================================================*/ + + + +/******************************************************************************* + * wl_wext_event_scan_complete() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function is used to send an event that a request for a network scan + * has completed. + * + * + * PARAMETERS: + * + * dev - the network device for which this event is to be issued + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wext_event_scan_complete( struct net_device *dev ) +{ +#if WIRELESS_EXT > 13 + union iwreq_data wrqu; + /*------------------------------------------------------------------------*/ + + + memset( &wrqu, 0, sizeof( wrqu )); + + wrqu.addr.sa_family = ARPHRD_ETHER; + wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL ); +#endif /* WIRELESS_EXT > 13 */ + + return; +} // wl_wext_event_scan_complete +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_wext_event_new_sta() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function is used to send an event that an AP has registered a new + * station. + * + * + * PARAMETERS: + * + * dev - the network device for which this event is to be issued + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wext_event_new_sta( struct net_device *dev ) +{ +#if WIRELESS_EXT > 14 + union iwreq_data wrqu; + /*------------------------------------------------------------------------*/ + + + memset( &wrqu, 0, sizeof( wrqu )); + + /* Send the station's mac address here */ + memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN ); + wrqu.addr.sa_family = ARPHRD_ETHER; + wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL ); +#endif /* WIRELESS_EXT > 14 */ + + return; +} // wl_wext_event_new_sta +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_wext_event_expired_sta() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function is used to send an event that an AP has deregistered a + * station. + * + * + * PARAMETERS: + * + * dev - the network device for which this event is to be issued + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wext_event_expired_sta( struct net_device *dev ) +{ +#if WIRELESS_EXT > 14 + union iwreq_data wrqu; + /*------------------------------------------------------------------------*/ + + + memset( &wrqu, 0, sizeof( wrqu )); + + memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN ); + wrqu.addr.sa_family = ARPHRD_ETHER; + wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL ); +#endif /* WIRELESS_EXT > 14 */ + + return; +} // wl_wext_event_expired_sta +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_wext_event_mic_failed() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function is used to send an event that MIC calculations failed. + * + * + * PARAMETERS: + * + * dev - the network device for which this event is to be issued + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wext_event_mic_failed( struct net_device *dev ) +{ +#if WIRELESS_EXT > 14 + char msg[512]; + union iwreq_data wrqu; + struct wl_private *lp = wl_priv(dev); + int key_idx; + char *addr1; + char *addr2; + WVLAN_RX_WMP_HDR *hdr; + /*------------------------------------------------------------------------*/ + + + key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3; + key_idx &= 0x03; + + /* Cast the lookahead buffer into a RFS format */ + hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT]; + + /* Cast the addresses to byte buffers, as in the above RFS they are word + length */ + addr1 = (char *)hdr->address1; + addr2 = (char *)hdr->address2; + + DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx, + hdr->status ); + + memset( &wrqu, 0, sizeof( wrqu )); + memset( msg, 0, sizeof( msg )); + + + /* Becuase MIC failures are not part of the Wireless Extensions yet, they + must be passed as a string using an IWEVCUSTOM event. In order for the + event to be effective, the string format must be known by both the + driver and the supplicant. The following is the string format used by the + hostap project's WPA supplicant, and will be used here until the Wireless + Extensions interface adds this support: + + MLME-MICHAELMICFAILURE.indication(keyid=# broadcast/unicast addr=addr2) + */ + + /* NOTE: Format of MAC address (using colons to seperate bytes) may cause + a problem in future versions of the supplicant, if they ever + actually parse these parameters */ +#if DBG + sprintf( msg, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=" + "%s)", key_idx, addr1[0] & 0x01 ? "broad" : "uni", + DbgHwAddr( addr2 )); +#endif + wrqu.data.length = strlen( msg ); + wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg ); +#endif /* WIRELESS_EXT > 14 */ + + return; +} // wl_wext_event_mic_failed +/*============================================================================*/ + + + + +/******************************************************************************* + * wl_wext_event_assoc_ie() + ******************************************************************************* + * + * DESCRIPTION: + * + * This function is used to send an event containing the WPA-IE generated + * by the firmware in an association request. + * + * + * PARAMETERS: + * + * dev - the network device for which this event is to be issued + * + * RETURNS: + * + * N/A + * + ******************************************************************************/ +void wl_wext_event_assoc_ie( struct net_device *dev ) +{ +#if WIRELESS_EXT > 14 + char msg[512]; + union iwreq_data wrqu; + struct wl_private *lp = wl_priv(dev); + int status; + PROBE_RESP data; + hcf_16 length; + hcf_8 *wpa_ie; + /*------------------------------------------------------------------------*/ + + + memset( &wrqu, 0, sizeof( wrqu )); + memset( msg, 0, sizeof( msg )); + + /* Retrieve the Association Request IE */ + lp->ltvRecord.len = 45; + lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO; + + status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); + if( status == HCF_SUCCESS ) + { + length = 0; + memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 ); + wpa_ie = wl_parse_wpa_ie( &data, &length ); + + /* Becuase this event (Association WPA-IE) is not part of the Wireless + Extensions yet, it must be passed as a string using an IWEVCUSTOM event. + In order for the event to be effective, the string format must be known + by both the driver and the supplicant. The following is the string format + used by the hostap project's WPA supplicant, and will be used here until + the Wireless Extensions interface adds this support: + + ASSOCINFO(ReqIEs=WPA-IE RespIEs=WPA-IE) + */ + + if( length != 0 ) + { + sprintf( msg, "ASSOCINFO(ReqIEs=%s)", wl_print_wpa_ie( wpa_ie, length )); + wrqu.data.length = strlen( msg ); + wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg ); + } + } +#endif /* WIRELESS_EXT > 14 */ + + return; +} // wl_wext_event_assoc_ie +/*============================================================================*/ +/* Structures to export the Wireless Handlers */ + +static const iw_handler wl_handler[] = +{ + (iw_handler) wireless_commit, /* SIOCSIWCOMMIT */ + (iw_handler) wireless_get_protocol, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) wireless_set_frequency, /* SIOCSIWFREQ */ + (iw_handler) wireless_get_frequency, /* SIOCGIWFREQ */ + (iw_handler) wireless_set_porttype, /* SIOCSIWMODE */ + (iw_handler) wireless_get_porttype, /* SIOCGIWMODE */ + (iw_handler) wireless_set_sensitivity, /* SIOCSIWSENS */ + (iw_handler) wireless_get_sensitivity, /* SIOCGIWSENS */ + (iw_handler) NULL , /* SIOCSIWRANGE */ + (iw_handler) wireless_get_range, /* SIOCGIWRANGE */ + (iw_handler) NULL , /* SIOCSIWPRIV */ + (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ + (iw_handler) NULL , /* SIOCSIWSTATS */ + (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */ + iw_handler_set_spy, /* SIOCSIWSPY */ + iw_handler_get_spy, /* SIOCGIWSPY */ + NULL, /* SIOCSIWTHRSPY */ + NULL, /* SIOCGIWTHRSPY */ + (iw_handler) NULL, /* SIOCSIWAP */ +#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA + (iw_handler) wireless_get_bssid, /* SIOCGIWAP */ +#else + (iw_handler) NULL, /* SIOCGIWAP */ +#endif + (iw_handler) NULL, /* SIOCSIWMLME */ + (iw_handler) wireless_get_ap_list, /* SIOCGIWAPLIST */ + (iw_handler) wireless_set_scan, /* SIOCSIWSCAN */ + (iw_handler) wireless_get_scan, /* SIOCGIWSCAN */ + (iw_handler) wireless_set_essid, /* SIOCSIWESSID */ + (iw_handler) wireless_get_essid, /* SIOCGIWESSID */ + (iw_handler) wireless_set_nickname, /* SIOCSIWNICKN */ + (iw_handler) wireless_get_nickname, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) wireless_set_rate, /* SIOCSIWRATE */ + (iw_handler) wireless_get_rate, /* SIOCGIWRATE */ + (iw_handler) wireless_set_rts_threshold,/* SIOCSIWRTS */ + (iw_handler) wireless_get_rts_threshold,/* SIOCGIWRTS */ + (iw_handler) NULL, /* SIOCSIWFRAG */ + (iw_handler) NULL, /* SIOCGIWFRAG */ + (iw_handler) NULL, /* SIOCSIWTXPOW */ + (iw_handler) wireless_get_tx_power, /* SIOCGIWTXPOW */ + (iw_handler) NULL, /* SIOCSIWRETRY */ + (iw_handler) NULL, /* SIOCGIWRETRY */ + (iw_handler) wireless_set_encode, /* SIOCSIWENCODE */ + (iw_handler) wireless_get_encode, /* SIOCGIWENCODE */ + (iw_handler) wireless_set_power, /* SIOCSIWPOWER */ + (iw_handler) wireless_get_power, /* SIOCGIWPOWER */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) wireless_get_genie, /* SIOCSIWGENIE */ + (iw_handler) NULL, /* SIOCGIWGENIE */ + (iw_handler) wireless_set_auth, /* SIOCSIWAUTH */ + (iw_handler) NULL, /* SIOCGIWAUTH */ + (iw_handler) wireless_set_encodeext, /* SIOCSIWENCODEEXT */ + (iw_handler) NULL, /* SIOCGIWENCODEEXT */ + (iw_handler) NULL, /* SIOCSIWPMKSA */ + (iw_handler) NULL, /* -- hole -- */ +}; + +static const iw_handler wl_private_handler[] = +{ /* SIOCIWFIRSTPRIV + */ + wvlan_set_netname, /* 0: SIOCSIWNETNAME */ + wvlan_get_netname, /* 1: SIOCGIWNETNAME */ + wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */ + wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */ +#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA + wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */ + wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */ +#endif +}; + +struct iw_priv_args wl_priv_args[] = { + {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" }, + {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" }, + {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" }, + {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" }, +#if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA + {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" }, + {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" }, +#endif +}; + +const struct iw_handler_def wl_iw_handler_def = +{ + .num_private = sizeof(wl_private_handler) / sizeof(iw_handler), + .private = (iw_handler *) wl_private_handler, + .private_args = (struct iw_priv_args *) wl_priv_args, + .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args), + .num_standard = sizeof(wl_handler) / sizeof(iw_handler), + .standard = (iw_handler *) wl_handler, + .get_wireless_stats = wl_get_wireless_stats, +}; + +#endif // WIRELESS_EXT diff --git a/drivers/staging/wlags49_h2/wl_wext.h b/drivers/staging/wlags49_h2/wl_wext.h new file mode 100644 index 0000000000000000000000000000000000000000..39d39a47b05a549ff5f329cdd7f92bb34d4e6b02 --- /dev/null +++ b/drivers/staging/wlags49_h2/wl_wext.h @@ -0,0 +1,96 @@ +/******************************************************************************* + * Agere Systems Inc. + * Wireless device driver for Linux (wlags49). + * + * Copyright (c) 1998-2003 Agere Systems Inc. + * All rights reserved. + * http://www.agere.com + * + * Initially developed by TriplePoint, Inc. + * http://www.triplepoint.com + * + *------------------------------------------------------------------------------ + * + * Header describing information required for the wireless IOCTL handlers. + * + *------------------------------------------------------------------------------ + * + * SOFTWARE LICENSE + * + * This software is provided subject to the following terms and conditions, + * which you should read carefully before using the software. Using this + * software indicates your acceptance of these terms and conditions. If you do + * not agree with these terms and conditions, do not use the software. + * + * Copyright © 2003 Agere Systems Inc. + * All rights reserved. + * + * Redistribution and use in source or binary forms, with or without + * modifications, 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 as comments in the code as + * well as in the documentation and/or other materials provided with the + * distribution. + * + * . 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. + * + * . Neither the name of Agere Systems Inc. nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Disclaimer + * + * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY + * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN + * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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. + * + ******************************************************************************/ + +#ifndef __WL_WEXT_H__ +#define __WL_WEXT_H__ + + +#ifdef WIRELESS_EXT + + +/******************************************************************************* + * function protoypes + ******************************************************************************/ + +struct iw_statistics *wl_wireless_stats( struct net_device *dev ); + +struct iw_statistics * wl_get_wireless_stats( struct net_device *dev ); + +inline void wl_spy_gather (struct net_device *dev, u_char *mac); + +void wl_wext_event_freq( struct net_device *dev ); +void wl_wext_event_mode( struct net_device *dev ); +void wl_wext_event_essid( struct net_device *dev ); +void wl_wext_event_encode( struct net_device *dev ); +void wl_wext_event_ap( struct net_device *dev ); +void wl_wext_event_scan_complete( struct net_device *dev ); +void wl_wext_event_new_sta( struct net_device *dev ); +void wl_wext_event_expired_sta( struct net_device *dev ); +void wl_wext_event_mic_failed( struct net_device *dev ); +void wl_wext_event_assoc_ie( struct net_device *dev ); + +extern const struct iw_handler_def wl_iw_handler_def; + +#else +#error WIRELESS_EXT +#endif // WIRELESS_EXT + + +#endif // __WL_WEXT_H__ diff --git a/drivers/staging/wlags49_h25/Kconfig b/drivers/staging/wlags49_h25/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..304a8c96ce33a2f0bf71520d266322d20be7de0e --- /dev/null +++ b/drivers/staging/wlags49_h25/Kconfig @@ -0,0 +1,9 @@ +config WLAGS49_H25 + tristate "Linksys HERMES II.5 WCF54G_Wireless-G_CompactFlash_Card" + depends on WLAN_80211 && WIRELESS_EXT && PCMCIA + select WEXT_SPY + ---help--- + Driver for wireless cards using Agere's HERMES II.5 chipset + which are identified with Manufacture ID: 0156,0004 + The software is a modified version of wl_lkm_722_abg.tar.gz + from the Agere Systems website, addapted for Ubuntu 9.04. diff --git a/drivers/staging/wlags49_h25/Makefile b/drivers/staging/wlags49_h25/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d0b23d4ff95a0c5338877e388873c3370596a527 --- /dev/null +++ b/drivers/staging/wlags49_h25/Makefile @@ -0,0 +1,81 @@ +# +# Makefile for wlags49_h2_cs.ko and wlags49_h25_cs.ko +# +# Default build for Hermes-II base cards (possibly identified with +# "manfid: 0x0156, 0x0003" in "pccardctl ident" output), comment +# -DHERMES25 below +# +# If you want to build for Hermes-II.5 base cards (possibly identified with +# "manfid: 0x0156, 0x0004" in "pccardctl ident" output), uncomment +# -DHERMES25 below +# +# If you want to build AP support (untested), comment out -DSTA_ONLY + +INSTALLDIR := /lib/modules/$(shell uname -r)/kernel/drivers/net/wireless +EXTRA_CFLAGS += -I$(KERNELDIR)/include +EXTRA_CFLAGS += -I$(src) \ + -DBUS_PCMCIA \ + -DUSE_WPA \ + -DUSE_WEXT \ + -DSTA_ONLY \ + -DWVLAN_49 \ + -DHERMES25 \ +# -DDBG \ +# -DDBG_LVL=5 \ +# -DUSE_UIL \ +# -DUSE_PROFILE \ + +ifeq ($(findstring HERMES25,$(EXTRA_CFLAGS)),) +WLNAME := wlags49_h2_cs +$(WLNAME)-y := sta_h2.o +ifeq ($(findstring STA_ONLY,$(EXTRA_CFLAGS)),) +$(WLNAME)-y += ap_h2.o +endif +else +WLNAME=wlags49_h25_cs +$(WLNAME)-y := sta_h25.o +ifeq ($(findstring STA_ONLY,$(EXTRA_CFLAGS)),) +$(WLNAME)-y += ap_h25.o +endif +endif + +# If KERNELRELEASE is defined, we've been invoked from the +# kernel build system and can use its language. +ifneq ($(KERNELRELEASE),) + +obj-m += $(WLNAME).o + +$(WLNAME)-y += wl_profile.o \ + wl_wext.o \ + wl_priv.o \ + wl_main.o \ + wl_enc.o \ + wl_util.o \ + wl_netdev.o \ + wl_cs.o \ + mmd.o \ + hcf.o \ + dhf.o + +$(WLNAME)-$(CONFIG_SYSFS) += wl_sysfs.o + +# Otherwise we were called directly from the command +# line; invoke the kernel build system. +else + KERNELDIR ?= /lib/modules/$(shell uname -r)/build + PWD := $(shell pwd) + +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +endif + +clean: + rm -fr *.o *.ko *.mod.c *.mod.o .*.*.cmd Module.symvers \ + Module.markers modules.order .tmp_versions + +install: default + -rmmod $(WLNAME) + install -d $(INSTALLDIR) + install -m 0644 -o root -g root $(WLNAME).ko $(INSTALLDIR) + /sbin/depmod -aq + diff --git a/drivers/staging/wlags49_h25/README.txt b/drivers/staging/wlags49_h25/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..4c7a836972d7aad45746f7c9aace2c03d36e1d00 --- /dev/null +++ b/drivers/staging/wlags49_h25/README.txt @@ -0,0 +1,30 @@ +======================================================================= +WLAN driver for cards using the HERMES II and HERMES II.5 chipset + +HERMES II Card + +PCMCIA Info: "Agere Systems" "Wireless PC Card Model 0110" + Manufacture ID: 0156,0003 + +HERMES II.5 Card + +PCMCIA Info: "Linksys" "WCF54G_Wireless-G_CompactFlash_Card" + Manufacture ID: 0156,0004 + +Based on Agere Systems Linux LKM Wireless Driver Source Code, +Version 7.22; complies with Open Source BSD License. +======================================================================= + +DESCRIPTION + +This directory only contains files that refer to the source in wlags49_h2. +Only real sourcefiles are the Makefile which has been configured to build +the driver for the HERMES II.5 chipset and Kconfig to describe the driver. + +The wlags49_h2 directory contains the full source, including the files +exclusively used by this driver. + +For more information about the driver look at the wlags49_h2 direcory. + +======================================================================= + diff --git a/drivers/staging/wlags49_h25/TODO b/drivers/staging/wlags49_h25/TODO new file mode 100644 index 0000000000000000000000000000000000000000..14aa415b1a82acfd238f4b6f760d2d4e838619f0 --- /dev/null +++ b/drivers/staging/wlags49_h25/TODO @@ -0,0 +1,33 @@ +First of all, the best thing would be that this driver becomes obsolte by +adding support for Hermes II and Hermes II.5 cards to the existing orinoco +driver. The orinoco driver currently only supports Hermes I based cards. +Since this will not happen by magic and has not happend until now this +driver provides a stop-gap solution for these type of cards. + +Having said that, the following wishlist comes to mind to make the driver +suitable as fully supported kernel driver. Feel free to expand/enhance the +list. + +TODO: + - verify against a Hermes II.5 card + - verify with WPA encription (both with H2 and H2.5 cards) + - sometimes the card does not initialize correctly, retry mechanisms + are build in to catch most cases but not all + - once the driver runs it is very stable, but I have the impression + some the crittical sections take to long + - the driver is split into a Hermes II and a Hermes II.5 part, it + would be nice to handle both with one module instead of two + - review by the wireless developer community + - verify the code against the coding standards for a propper linux + driver + - resolve license issues (?) + +DONE: + - verified against a Hermes II card (Thomson Speedtouch 110 PCMCIA + card) + - verified with WEP encription + +Please send any patches or complaints about this driver to Greg +Kroah-Hartman and Cc: Henk de Groot +Don't bother the upstream wireless kernel developers about it, they +want nothing to do with it. diff --git a/drivers/staging/wlags49_h25/ap_h25.c b/drivers/staging/wlags49_h25/ap_h25.c new file mode 100644 index 0000000000000000000000000000000000000000..0344fa58dda61d62a4b737ba48c49e30fc845b35 --- /dev/null +++ b/drivers/staging/wlags49_h25/ap_h25.c @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/ap_h25.c" diff --git a/drivers/staging/wlags49_h25/debug.h b/drivers/staging/wlags49_h25/debug.h new file mode 100644 index 0000000000000000000000000000000000000000..b5fb136a2d54facfde56df88deb114b217126ed6 --- /dev/null +++ b/drivers/staging/wlags49_h25/debug.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/debug.h" diff --git a/drivers/staging/wlags49_h25/dhf.c b/drivers/staging/wlags49_h25/dhf.c new file mode 100644 index 0000000000000000000000000000000000000000..81762c80189cf1de1e73cb0f45819f82d8d477ca --- /dev/null +++ b/drivers/staging/wlags49_h25/dhf.c @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/dhf.c" diff --git a/drivers/staging/wlags49_h25/dhf.h b/drivers/staging/wlags49_h25/dhf.h new file mode 100644 index 0000000000000000000000000000000000000000..54181dc70a72de63da9cd761f76ab7f72a1b51df --- /dev/null +++ b/drivers/staging/wlags49_h25/dhf.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/dhf.h" diff --git a/drivers/staging/wlags49_h25/dhfcfg.h b/drivers/staging/wlags49_h25/dhfcfg.h new file mode 100644 index 0000000000000000000000000000000000000000..2586e39802148959292fb8a12b04492b25823b82 --- /dev/null +++ b/drivers/staging/wlags49_h25/dhfcfg.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/dhfcfg.h" diff --git a/drivers/staging/wlags49_h25/hcf.c b/drivers/staging/wlags49_h25/hcf.c new file mode 100644 index 0000000000000000000000000000000000000000..eeeba1f5553e3e408c25a99a9e03ebce1c80a9e7 --- /dev/null +++ b/drivers/staging/wlags49_h25/hcf.c @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/hcf.c" diff --git a/drivers/staging/wlags49_h25/hcf.h b/drivers/staging/wlags49_h25/hcf.h new file mode 100644 index 0000000000000000000000000000000000000000..d1143d9fce2d228d01b047a3a29f975958091d78 --- /dev/null +++ b/drivers/staging/wlags49_h25/hcf.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/hcf.h" diff --git a/drivers/staging/wlags49_h25/hcfcfg.h b/drivers/staging/wlags49_h25/hcfcfg.h new file mode 100644 index 0000000000000000000000000000000000000000..f88c4bcb3ff81cd220e20d4093bd17e28ef4e108 --- /dev/null +++ b/drivers/staging/wlags49_h25/hcfcfg.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/hcfcfg.h" diff --git a/drivers/staging/wlags49_h25/hcfdef.h b/drivers/staging/wlags49_h25/hcfdef.h new file mode 100644 index 0000000000000000000000000000000000000000..f6a0060c3a530b8b45c630b245ce66bc09bd2f9f --- /dev/null +++ b/drivers/staging/wlags49_h25/hcfdef.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/hcfdef.h" diff --git a/drivers/staging/wlags49_h25/mdd.h b/drivers/staging/wlags49_h25/mdd.h new file mode 100644 index 0000000000000000000000000000000000000000..4d8e142ffa3418c3449d89be5333dba615c2d2f7 --- /dev/null +++ b/drivers/staging/wlags49_h25/mdd.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/mdd.h" diff --git a/drivers/staging/wlags49_h25/mmd.c b/drivers/staging/wlags49_h25/mmd.c new file mode 100644 index 0000000000000000000000000000000000000000..b20782d334d283ebe4a4d00a0703fe619d658070 --- /dev/null +++ b/drivers/staging/wlags49_h25/mmd.c @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/mmd.c" diff --git a/drivers/staging/wlags49_h25/mmd.h b/drivers/staging/wlags49_h25/mmd.h new file mode 100644 index 0000000000000000000000000000000000000000..8284dd9155ed1554fbaf1cd15ef32f071dda8d4d --- /dev/null +++ b/drivers/staging/wlags49_h25/mmd.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/mmd.h" diff --git a/drivers/staging/wlags49_h25/sta_h25.c b/drivers/staging/wlags49_h25/sta_h25.c new file mode 100644 index 0000000000000000000000000000000000000000..83c76bbdc6e7588f87a57b9a42c7d54611410d6b --- /dev/null +++ b/drivers/staging/wlags49_h25/sta_h25.c @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/sta_h25.c" diff --git a/drivers/staging/wlags49_h25/wl_cs.c b/drivers/staging/wlags49_h25/wl_cs.c new file mode 100644 index 0000000000000000000000000000000000000000..e6e1f199ea683c565107f6235c1c4ccafcd45e1a --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_cs.c @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_cs.c" diff --git a/drivers/staging/wlags49_h25/wl_cs.h b/drivers/staging/wlags49_h25/wl_cs.h new file mode 100644 index 0000000000000000000000000000000000000000..657acee525cb1a8499d0fa80928c8f8c01e9055b --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_cs.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_cs.h" diff --git a/drivers/staging/wlags49_h25/wl_enc.c b/drivers/staging/wlags49_h25/wl_enc.c new file mode 100644 index 0000000000000000000000000000000000000000..fe59df145150421a2e465b620f8e38449e00f9fe --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_enc.c @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_enc.c" diff --git a/drivers/staging/wlags49_h25/wl_enc.h b/drivers/staging/wlags49_h25/wl_enc.h new file mode 100644 index 0000000000000000000000000000000000000000..f2e860e14be91487135c0406fa1eb19956192121 --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_enc.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_enc.h" diff --git a/drivers/staging/wlags49_h25/wl_if.h b/drivers/staging/wlags49_h25/wl_if.h new file mode 100644 index 0000000000000000000000000000000000000000..70d86f09f87a28831c8196a630da654a206a1417 --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_if.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_if.h" diff --git a/drivers/staging/wlags49_h25/wl_internal.h b/drivers/staging/wlags49_h25/wl_internal.h new file mode 100644 index 0000000000000000000000000000000000000000..c1687a3056cd85fc4957201536994a8536c6819e --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_internal.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_internal.h" diff --git a/drivers/staging/wlags49_h25/wl_main.c b/drivers/staging/wlags49_h25/wl_main.c new file mode 100644 index 0000000000000000000000000000000000000000..d2c06ad8f88a6f703368fc1cb6a98b79dcd710fb --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_main.c @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_main.c" diff --git a/drivers/staging/wlags49_h25/wl_main.h b/drivers/staging/wlags49_h25/wl_main.h new file mode 100644 index 0000000000000000000000000000000000000000..c98376e71957814a6b6bab5914d6b1cd5104908a --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_main.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_main.h" diff --git a/drivers/staging/wlags49_h25/wl_netdev.c b/drivers/staging/wlags49_h25/wl_netdev.c new file mode 100644 index 0000000000000000000000000000000000000000..f7512c3891a844b845fe21372c0062d47a710e41 --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_netdev.c @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_netdev.c" diff --git a/drivers/staging/wlags49_h25/wl_netdev.h b/drivers/staging/wlags49_h25/wl_netdev.h new file mode 100644 index 0000000000000000000000000000000000000000..519cd5f0461c1789e570ff0fcebe6bdd71509d07 --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_netdev.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_netdev.h" diff --git a/drivers/staging/wlags49_h25/wl_priv.c b/drivers/staging/wlags49_h25/wl_priv.c new file mode 100644 index 0000000000000000000000000000000000000000..160c8014051ade1b02c725473113dbf934dd34f2 --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_priv.c @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_priv.c" diff --git a/drivers/staging/wlags49_h25/wl_priv.h b/drivers/staging/wlags49_h25/wl_priv.h new file mode 100644 index 0000000000000000000000000000000000000000..28492b362db458bf2b03778652d7bcad7ff103f3 --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_priv.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_priv.h" diff --git a/drivers/staging/wlags49_h25/wl_profile.c b/drivers/staging/wlags49_h25/wl_profile.c new file mode 100644 index 0000000000000000000000000000000000000000..6baa201c132a7ce8fa8dfd53034d24391f0969fe --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_profile.c @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_profile.c" diff --git a/drivers/staging/wlags49_h25/wl_profile.h b/drivers/staging/wlags49_h25/wl_profile.h new file mode 100644 index 0000000000000000000000000000000000000000..5f253a5fb60e4965380188e465604e4b0d80600f --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_profile.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_profile.h" diff --git a/drivers/staging/wlags49_h25/wl_sysfs.c b/drivers/staging/wlags49_h25/wl_sysfs.c new file mode 100644 index 0000000000000000000000000000000000000000..6458ee63350d758a56c49240e26d650a78c7631c --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_sysfs.c @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_sysfs.c" diff --git a/drivers/staging/wlags49_h25/wl_sysfs.h b/drivers/staging/wlags49_h25/wl_sysfs.h new file mode 100644 index 0000000000000000000000000000000000000000..eb819a5ef8b53de9c39e09ecd93e5dbe47c002d3 --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_sysfs.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_sysfs.h" diff --git a/drivers/staging/wlags49_h25/wl_util.c b/drivers/staging/wlags49_h25/wl_util.c new file mode 100644 index 0000000000000000000000000000000000000000..771bebeeac4c28acfa185d675656ac65760afbc2 --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_util.c @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_util.c" diff --git a/drivers/staging/wlags49_h25/wl_util.h b/drivers/staging/wlags49_h25/wl_util.h new file mode 100644 index 0000000000000000000000000000000000000000..ccd74e73a4be6f245742ceb378c93d65b65e00a8 --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_util.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_util.h" diff --git a/drivers/staging/wlags49_h25/wl_version.h b/drivers/staging/wlags49_h25/wl_version.h new file mode 100644 index 0000000000000000000000000000000000000000..ad38e8f7214c2790d697e17c52c2e13a464120e8 --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_version.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_version.h" diff --git a/drivers/staging/wlags49_h25/wl_wext.c b/drivers/staging/wlags49_h25/wl_wext.c new file mode 100644 index 0000000000000000000000000000000000000000..f660e791b62006e312dfda321448a6cf13e53e26 --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_wext.c @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_wext.c" diff --git a/drivers/staging/wlags49_h25/wl_wext.h b/drivers/staging/wlags49_h25/wl_wext.h new file mode 100644 index 0000000000000000000000000000000000000000..31d63865c222c960bcfab14602e69d6fbab86f27 --- /dev/null +++ b/drivers/staging/wlags49_h25/wl_wext.h @@ -0,0 +1,2 @@ +/* Use common source from wlags49_h2 */ +#include "../wlags49_h2/wl_wext.h" diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 240750881d28d0a8c2d5c3d5a10312c701afe83b..81aac7f4ca59a589fc74d2729bf8328989d91e71 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -60,6 +60,8 @@ config USB_ARCH_HAS_EHCI default y if ARCH_IXP4XX default y if ARCH_W90X900 default y if ARCH_AT91SAM9G45 + default y if ARCH_MXC + default y if ARCH_OMAP34XX default PCI # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index be3c9b80bc9fb1bfda456f77fc9e83b681ca4dec..473aa1a20de9bab61df2590d049994f8f178ba1e 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -44,3 +44,5 @@ obj-y += early/ obj-$(CONFIG_USB_ATM) += atm/ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ + +obj-$(CONFIG_USB_ULPI) += otg/ diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index bba4d3eabe0f2c2d3109ae4ddaba459b2b244c93..c5395246886d060b11c4ba2e12867c5784d2e211 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -667,12 +667,12 @@ static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *conte else uea_info(usb, "firmware uploaded\n"); - uea_leaves(usb); - return; + goto err; err_fw_corrupted: uea_err(usb, "firmware is corrupted\n"); err: + release_firmware(fw_entry); uea_leaves(usb); } @@ -705,7 +705,8 @@ static int uea_load_firmware(struct usb_device *usb, unsigned int ver) break; } - ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware); + ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, + GFP_KERNEL, usb, uea_upload_pre_firmware); if (ret) uea_err(usb, "firmware %s is not available\n", fw_name); else diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index e4eca7810bcf1bed6821086e4bab6130525e3c17..34d4eb98829e0db97271e6e6e5f5adc6bffe3e33 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1461,6 +1461,12 @@ err_out: } #endif /* CONFIG_PM */ + +#define NOKIA_PCSUITE_ACM_INFO(x) \ + USB_DEVICE_AND_INTERFACE_INFO(0x0421, x, \ + USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ + USB_CDC_ACM_PROTO_VENDOR) + /* * USB driver structure. */ @@ -1519,6 +1525,57 @@ static struct usb_device_id acm_ids[] = { .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ }, + /* Nokia S60 phones expose two ACM channels. The first is + * a modem and is picked up by the standard AT-command + * information below. The second is 'vendor-specific' but + * is treated as a serial device at the S60 end, so we want + * to expose it on Linux too. */ + { NOKIA_PCSUITE_ACM_INFO(0x042D), }, /* Nokia 3250 */ + { NOKIA_PCSUITE_ACM_INFO(0x04D8), }, /* Nokia 5500 Sport */ + { NOKIA_PCSUITE_ACM_INFO(0x04C9), }, /* Nokia E50 */ + { NOKIA_PCSUITE_ACM_INFO(0x0419), }, /* Nokia E60 */ + { NOKIA_PCSUITE_ACM_INFO(0x044D), }, /* Nokia E61 */ + { NOKIA_PCSUITE_ACM_INFO(0x0001), }, /* Nokia E61i */ + { NOKIA_PCSUITE_ACM_INFO(0x0475), }, /* Nokia E62 */ + { NOKIA_PCSUITE_ACM_INFO(0x0508), }, /* Nokia E65 */ + { NOKIA_PCSUITE_ACM_INFO(0x0418), }, /* Nokia E70 */ + { NOKIA_PCSUITE_ACM_INFO(0x0425), }, /* Nokia N71 */ + { NOKIA_PCSUITE_ACM_INFO(0x0486), }, /* Nokia N73 */ + { NOKIA_PCSUITE_ACM_INFO(0x04DF), }, /* Nokia N75 */ + { NOKIA_PCSUITE_ACM_INFO(0x000e), }, /* Nokia N77 */ + { NOKIA_PCSUITE_ACM_INFO(0x0445), }, /* Nokia N80 */ + { NOKIA_PCSUITE_ACM_INFO(0x042F), }, /* Nokia N91 & N91 8GB */ + { NOKIA_PCSUITE_ACM_INFO(0x048E), }, /* Nokia N92 */ + { NOKIA_PCSUITE_ACM_INFO(0x0420), }, /* Nokia N93 */ + { NOKIA_PCSUITE_ACM_INFO(0x04E6), }, /* Nokia N93i */ + { NOKIA_PCSUITE_ACM_INFO(0x04B2), }, /* Nokia 5700 XpressMusic */ + { NOKIA_PCSUITE_ACM_INFO(0x0134), }, /* Nokia 6110 Navigator (China) */ + { NOKIA_PCSUITE_ACM_INFO(0x046E), }, /* Nokia 6110 Navigator */ + { NOKIA_PCSUITE_ACM_INFO(0x002f), }, /* Nokia 6120 classic & */ + { NOKIA_PCSUITE_ACM_INFO(0x0088), }, /* Nokia 6121 classic */ + { NOKIA_PCSUITE_ACM_INFO(0x00fc), }, /* Nokia 6124 classic */ + { NOKIA_PCSUITE_ACM_INFO(0x0042), }, /* Nokia E51 */ + { NOKIA_PCSUITE_ACM_INFO(0x00b0), }, /* Nokia E66 */ + { NOKIA_PCSUITE_ACM_INFO(0x00ab), }, /* Nokia E71 */ + { NOKIA_PCSUITE_ACM_INFO(0x0481), }, /* Nokia N76 */ + { NOKIA_PCSUITE_ACM_INFO(0x0007), }, /* Nokia N81 & N81 8GB */ + { NOKIA_PCSUITE_ACM_INFO(0x0071), }, /* Nokia N82 */ + { NOKIA_PCSUITE_ACM_INFO(0x04F0), }, /* Nokia N95 & N95-3 NAM */ + { NOKIA_PCSUITE_ACM_INFO(0x0070), }, /* Nokia N95 8GB */ + { NOKIA_PCSUITE_ACM_INFO(0x00e9), }, /* Nokia 5320 XpressMusic */ + { NOKIA_PCSUITE_ACM_INFO(0x0099), }, /* Nokia 6210 Navigator, RM-367 */ + { NOKIA_PCSUITE_ACM_INFO(0x0128), }, /* Nokia 6210 Navigator, RM-419 */ + { NOKIA_PCSUITE_ACM_INFO(0x008f), }, /* Nokia 6220 Classic */ + { NOKIA_PCSUITE_ACM_INFO(0x00a0), }, /* Nokia 6650 */ + { NOKIA_PCSUITE_ACM_INFO(0x007b), }, /* Nokia N78 */ + { NOKIA_PCSUITE_ACM_INFO(0x0094), }, /* Nokia N85 */ + { NOKIA_PCSUITE_ACM_INFO(0x003a), }, /* Nokia N96 & N96-3 */ + { NOKIA_PCSUITE_ACM_INFO(0x00e9), }, /* Nokia 5320 XpressMusic */ + { NOKIA_PCSUITE_ACM_INFO(0x0108), }, /* Nokia 5320 XpressMusic 2G */ + { NOKIA_PCSUITE_ACM_INFO(0x01f5), }, /* Nokia N97, RM-505 */ + + /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ + /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_ACM_PROTO_AT_V25TER) }, @@ -1533,7 +1590,6 @@ static struct usb_device_id acm_ids[] = { { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_ACM_PROTO_AT_CDMA) }, - /* NOTE: COMM/ACM/0xff is likely MSFT RNDIS ... NOT a modem!! */ { } }; diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index b4bd2411c666b330ccd94612934298b8b6139562..7c5f4e32c9202b9f7ac0b0b95c92fc5a3343f482 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -347,13 +347,8 @@ usbtmc_abort_bulk_out_check_status: goto exit; usbtmc_abort_bulk_out_clear_halt: - rv = usb_control_msg(data->usb_dev, - usb_sndctrlpipe(data->usb_dev, 0), - USB_REQ_CLEAR_FEATURE, - USB_DIR_OUT | USB_TYPE_STANDARD | - USB_RECIP_ENDPOINT, - USB_ENDPOINT_HALT, data->bulk_out, buffer, - 0, USBTMC_TIMEOUT); + rv = usb_clear_halt(data->usb_dev, + usb_sndbulkpipe(data->usb_dev, data->bulk_out)); if (rv < 0) { dev_err(dev, "usb_control_msg returned %d\n", rv); @@ -562,10 +557,16 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, n_bytes = roundup(12 + this_part, 4); memset(buffer + 12 + this_part, 0, n_bytes - (12 + this_part)); - retval = usb_bulk_msg(data->usb_dev, - usb_sndbulkpipe(data->usb_dev, - data->bulk_out), - buffer, n_bytes, &actual, USBTMC_TIMEOUT); + do { + retval = usb_bulk_msg(data->usb_dev, + usb_sndbulkpipe(data->usb_dev, + data->bulk_out), + buffer, n_bytes, + &actual, USBTMC_TIMEOUT); + if (retval != 0) + break; + n_bytes -= actual; + } while (n_bytes); data->bTag_last_write = data->bTag; data->bTag++; @@ -702,14 +703,8 @@ usbtmc_clear_check_status: usbtmc_clear_bulk_out_halt: - rv = usb_control_msg(data->usb_dev, - usb_sndctrlpipe(data->usb_dev, 0), - USB_REQ_CLEAR_FEATURE, - USB_DIR_OUT | USB_TYPE_STANDARD | - USB_RECIP_ENDPOINT, - USB_ENDPOINT_HALT, - data->bulk_out, buffer, 0, - USBTMC_TIMEOUT); + rv = usb_clear_halt(data->usb_dev, + usb_sndbulkpipe(data->usb_dev, data->bulk_out)); if (rv < 0) { dev_err(dev, "usb_control_msg returned %d\n", rv); goto exit; @@ -730,13 +725,8 @@ static int usbtmc_ioctl_clear_out_halt(struct usbtmc_device_data *data) if (!buffer) return -ENOMEM; - rv = usb_control_msg(data->usb_dev, - usb_sndctrlpipe(data->usb_dev, 0), - USB_REQ_CLEAR_FEATURE, - USB_DIR_OUT | USB_TYPE_STANDARD | - USB_RECIP_ENDPOINT, - USB_ENDPOINT_HALT, data->bulk_out, - buffer, 0, USBTMC_TIMEOUT); + rv = usb_clear_halt(data->usb_dev, + usb_sndbulkpipe(data->usb_dev, data->bulk_out)); if (rv < 0) { dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n", @@ -759,12 +749,8 @@ static int usbtmc_ioctl_clear_in_halt(struct usbtmc_device_data *data) if (!buffer) return -ENOMEM; - rv = usb_control_msg(data->usb_dev, usb_sndctrlpipe(data->usb_dev, 0), - USB_REQ_CLEAR_FEATURE, - USB_DIR_OUT | USB_TYPE_STANDARD | - USB_RECIP_ENDPOINT, - USB_ENDPOINT_HALT, data->bulk_in, buffer, 0, - USBTMC_TIMEOUT); + rv = usb_clear_halt(data->usb_dev, + usb_rcvbulkpipe(data->usb_dev, data->bulk_in)); if (rv < 0) { dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n", @@ -1109,13 +1095,13 @@ static void usbtmc_disconnect(struct usb_interface *intf) kref_put(&data->kref, usbtmc_delete); } -static int usbtmc_suspend (struct usb_interface *intf, pm_message_t message) +static int usbtmc_suspend(struct usb_interface *intf, pm_message_t message) { /* this driver does not have pending URBs */ return 0; } -static int usbtmc_resume (struct usb_interface *intf) +static int usbtmc_resume(struct usb_interface *intf) { return 0; } diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 181f78c84105c090df4689b44845638472ccb8ef..6e8bcdfd23b41ee8435efbbb5e6bfadeb8095eb3 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1388,6 +1388,46 @@ static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg) } #ifdef CONFIG_COMPAT +static int proc_control_compat(struct dev_state *ps, + struct usbdevfs_ctrltransfer32 __user *p32) +{ + struct usbdevfs_ctrltransfer __user *p; + __u32 udata; + p = compat_alloc_user_space(sizeof(*p)); + if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t))) || + get_user(udata, &p32->data) || + put_user(compat_ptr(udata), &p->data)) + return -EFAULT; + return proc_control(ps, p); +} + +static int proc_bulk_compat(struct dev_state *ps, + struct usbdevfs_bulktransfer32 __user *p32) +{ + struct usbdevfs_bulktransfer __user *p; + compat_uint_t n; + compat_caddr_t addr; + + p = compat_alloc_user_space(sizeof(*p)); + + if (get_user(n, &p32->ep) || put_user(n, &p->ep) || + get_user(n, &p32->len) || put_user(n, &p->len) || + get_user(n, &p32->timeout) || put_user(n, &p->timeout) || + get_user(addr, &p32->data) || put_user(compat_ptr(addr), &p->data)) + return -EFAULT; + + return proc_bulk(ps, p); +} +static int proc_disconnectsignal_compat(struct dev_state *ps, void __user *arg) +{ + struct usbdevfs_disconnectsignal32 ds; + + if (copy_from_user(&ds, arg, sizeof(ds))) + return -EFAULT; + ps->discsignr = ds.signr; + ps->disccontext = compat_ptr(ds.context); + return 0; +} static int get_urb32(struct usbdevfs_urb *kurb, struct usbdevfs_urb32 __user *uurb) @@ -1482,6 +1522,7 @@ static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg) return processcompl_compat(as, (void __user * __user *)arg); } + #endif static int proc_disconnectsignal(struct dev_state *ps, void __user *arg) @@ -1648,12 +1689,12 @@ static int proc_release_port(struct dev_state *ps, void __user *arg) * are assuming that somehow the configuration has been prevented from * changing. But there's no mechanism to ensure that... */ -static int usbdev_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long usbdev_do_ioctl(struct file *file, unsigned int cmd, + void __user *p) { struct dev_state *ps = file->private_data; + struct inode *inode = file->f_path.dentry->d_inode; struct usb_device *dev = ps->dev; - void __user *p = (void __user *)arg; int ret = -ENOTTY; if (!(file->f_mode & FMODE_WRITE)) @@ -1726,6 +1767,24 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, break; #ifdef CONFIG_COMPAT + case USBDEVFS_CONTROL32: + snoop(&dev->dev, "%s: CONTROL32\n", __func__); + ret = proc_control_compat(ps, p); + if (ret >= 0) + inode->i_mtime = CURRENT_TIME; + break; + + case USBDEVFS_BULK32: + snoop(&dev->dev, "%s: BULK32\n", __func__); + ret = proc_bulk_compat(ps, p); + if (ret >= 0) + inode->i_mtime = CURRENT_TIME; + break; + + case USBDEVFS_DISCSIGNAL32: + snoop(&dev->dev, "%s: DISCSIGNAL32\n", __func__); + ret = proc_disconnectsignal_compat(ps, p); + break; case USBDEVFS_SUBMITURB32: snoop(&dev->dev, "%s: SUBMITURB32\n", __func__); @@ -1745,7 +1804,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, break; case USBDEVFS_IOCTL32: - snoop(&dev->dev, "%s: IOCTL\n", __func__); + snoop(&dev->dev, "%s: IOCTL32\n", __func__); ret = proc_ioctl_compat(ps, ptr_to_compat(p)); break; #endif @@ -1801,6 +1860,32 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, return ret; } +static long usbdev_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret; + + lock_kernel(); + ret = usbdev_do_ioctl(file, cmd, (void __user *)arg); + unlock_kernel(); + + return ret; +} + +#ifdef CONFIG_COMPAT +static long usbdev_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret; + + lock_kernel(); + ret = usbdev_do_ioctl(file, cmd, compat_ptr(arg)); + unlock_kernel(); + + return ret; +} +#endif + /* No kernel lock - fine */ static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait) @@ -1817,13 +1902,16 @@ static unsigned int usbdev_poll(struct file *file, } const struct file_operations usbdev_file_operations = { - .owner = THIS_MODULE, - .llseek = usbdev_lseek, - .read = usbdev_read, - .poll = usbdev_poll, - .ioctl = usbdev_ioctl, - .open = usbdev_open, - .release = usbdev_release, + .owner = THIS_MODULE, + .llseek = usbdev_lseek, + .read = usbdev_read, + .poll = usbdev_poll, + .unlocked_ioctl = usbdev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = usbdev_compat_ioctl, +#endif + .open = usbdev_open, + .release = usbdev_release, }; static void usbdev_remove(struct usb_device *udev) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 4f864472c5c4db4eea4004cd49e902cb4acd75c9..60a45f1e3a67e13b41fd41770d51cbe83b39f730 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -83,6 +83,47 @@ static ssize_t store_new_id(struct device_driver *driver, } static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); +/** + * store_remove_id - remove a USB device ID from this driver + * @driver: target device driver + * @buf: buffer for scanning device ID data + * @count: input size + * + * Removes a dynamic usb device ID from this driver. + */ +static ssize_t +store_remove_id(struct device_driver *driver, const char *buf, size_t count) +{ + struct usb_dynid *dynid, *n; + struct usb_driver *usb_driver = to_usb_driver(driver); + u32 idVendor = 0; + u32 idProduct = 0; + int fields = 0; + int retval = 0; + + fields = sscanf(buf, "%x %x", &idVendor, &idProduct); + if (fields < 2) + return -EINVAL; + + spin_lock(&usb_driver->dynids.lock); + list_for_each_entry_safe(dynid, n, &usb_driver->dynids.list, node) { + struct usb_device_id *id = &dynid->id; + if ((id->idVendor == idVendor) && + (id->idProduct == idProduct)) { + list_del(&dynid->node); + kfree(dynid); + retval = 0; + break; + } + } + spin_unlock(&usb_driver->dynids.lock); + + if (retval) + return retval; + return count; +} +static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); + static int usb_create_newid_file(struct usb_driver *usb_drv) { int error = 0; @@ -107,6 +148,21 @@ static void usb_remove_newid_file(struct usb_driver *usb_drv) &driver_attr_new_id); } +static int +usb_create_removeid_file(struct usb_driver *drv) +{ + int error = 0; + if (drv->probe != NULL) + error = driver_create_file(&drv->drvwrap.driver, + &driver_attr_remove_id); + return error; +} + +static void usb_remove_removeid_file(struct usb_driver *drv) +{ + driver_remove_file(&drv->drvwrap.driver, &driver_attr_remove_id); +} + static void usb_free_dynids(struct usb_driver *usb_drv) { struct usb_dynid *dynid, *n; @@ -128,6 +184,16 @@ static void usb_remove_newid_file(struct usb_driver *usb_drv) { } +static int +usb_create_removeid_file(struct usb_driver *drv) +{ + return 0; +} + +static void usb_remove_removeid_file(struct usb_driver *drv) +{ +} + static inline void usb_free_dynids(struct usb_driver *usb_drv) { } @@ -774,19 +840,34 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner, INIT_LIST_HEAD(&new_driver->dynids.list); retval = driver_register(&new_driver->drvwrap.driver); + if (retval) + goto out; - if (!retval) { - pr_info("%s: registered new interface driver %s\n", + usbfs_update_special(); + + retval = usb_create_newid_file(new_driver); + if (retval) + goto out_newid; + + retval = usb_create_removeid_file(new_driver); + if (retval) + goto out_removeid; + + pr_info("%s: registered new interface driver %s\n", usbcore_name, new_driver->name); - usbfs_update_special(); - usb_create_newid_file(new_driver); - } else { - printk(KERN_ERR "%s: error %d registering interface " - " driver %s\n", - usbcore_name, retval, new_driver->name); - } +out: return retval; + +out_removeid: + usb_remove_newid_file(new_driver); +out_newid: + driver_unregister(&new_driver->drvwrap.driver); + + printk(KERN_ERR "%s: error %d registering interface " + " driver %s\n", + usbcore_name, retval, new_driver->name); + goto out; } EXPORT_SYMBOL_GPL(usb_register_driver); @@ -806,6 +887,7 @@ void usb_deregister(struct usb_driver *driver) pr_info("%s: deregistering interface driver %s\n", usbcore_name, driver->name); + usb_remove_removeid_file(driver); usb_remove_newid_file(driver); usb_free_dynids(driver); driver_unregister(&driver->drvwrap.driver); @@ -948,8 +1030,6 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg) done: dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status); - if (status == 0) - udev->autoresume_disabled = 0; return status; } @@ -1280,11 +1360,6 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg) /* Propagate the resume up the tree, if necessary */ if (udev->state == USB_STATE_SUSPENDED) { - if ((msg.event & PM_EVENT_AUTO) && - udev->autoresume_disabled) { - status = -EPERM; - goto done; - } if (parent) { status = usb_autoresume_device(parent); if (status == 0) { @@ -1341,7 +1416,6 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt) int status = 0; usb_pm_lock(udev); - udev->auto_pm = 1; udev->pm_usage_cnt += inc_usage_cnt; WARN_ON(udev->pm_usage_cnt < 0); if (inc_usage_cnt) @@ -1473,7 +1547,6 @@ static int usb_autopm_do_interface(struct usb_interface *intf, if (intf->condition == USB_INTERFACE_UNBOUND) status = -ENODEV; else { - udev->auto_pm = 1; atomic_add(inc_usage_cnt, &intf->pm_usage_cnt); udev->last_busy = jiffies; if (inc_usage_cnt >= 0 && @@ -1640,8 +1713,6 @@ int usb_autopm_get_interface_async(struct usb_interface *intf) if (intf->condition == USB_INTERFACE_UNBOUND) status = -ENODEV; - else if (udev->autoresume_disabled) - status = -EPERM; else { atomic_inc(&intf->pm_usage_cnt); if (atomic_read(&intf->pm_usage_cnt) > 0 && @@ -1654,28 +1725,6 @@ int usb_autopm_get_interface_async(struct usb_interface *intf) } EXPORT_SYMBOL_GPL(usb_autopm_get_interface_async); -/** - * usb_autopm_set_interface - set a USB interface's autosuspend state - * @intf: the usb_interface whose state should be set - * - * This routine sets the autosuspend state of @intf's device according - * to @intf's usage counter, which the caller must have set previously. - * If the counter is <= 0, the device is autosuspended (if it isn't - * already suspended and if nothing else prevents the autosuspend). If - * the counter is > 0, the device is autoresumed (if it isn't already - * awake). - */ -int usb_autopm_set_interface(struct usb_interface *intf) -{ - int status; - - status = usb_autopm_do_interface(intf, 0); - dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", - __func__, status, atomic_read(&intf->pm_usage_cnt)); - return status; -} -EXPORT_SYMBOL_GPL(usb_autopm_set_interface); - #else void usb_autosuspend_work(struct work_struct *work) @@ -1707,7 +1756,6 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg) do_unbind_rebind(udev, DO_UNBIND); usb_pm_lock(udev); - udev->auto_pm = 0; status = usb_suspend_both(udev, msg); usb_pm_unlock(udev); return status; @@ -1730,7 +1778,6 @@ int usb_external_resume_device(struct usb_device *udev, pm_message_t msg) int status; usb_pm_lock(udev); - udev->auto_pm = 0; status = usb_resume_both(udev, msg); udev->last_busy = jiffies; usb_pm_unlock(udev); diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 222ee07ea680f303d9ce0d5b94daaeaa9aa22c1d..bfc6c2eea6471d87bdf77455e4e4d8ca3e160ca1 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -99,6 +99,7 @@ static int init_usb_class(void) printk(KERN_ERR "class_create failed for usb devices\n"); kfree(usb_class); usb_class = NULL; + goto exit; } usb_class->class->devnode = usb_devnode; diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 05e6d313961e3e3ce9ed3a09126f80ba65f7daff..bdf87a8414a1af4f9278257c31e67415f78ff497 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -139,7 +139,7 @@ int usb_choose_configuration(struct usb_device *udev) if (best) { i = best->desc.bConfigurationValue; - dev_info(&udev->dev, + dev_dbg(&udev->dev, "configuration #%d chosen from %d choice%s\n", i, num_configs, plural(num_configs)); } else { diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 34de475f016e790efbba02ada9067131870c294d..6dac3b802d41b5cbc1631b20ecf3cd7a72588385 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -1275,13 +1276,16 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, if (usb_endpoint_xfer_control(&urb->ep->desc) && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) { - if (hcd->self.uses_dma) + if (hcd->self.uses_dma) { urb->setup_dma = dma_map_single( hcd->self.controller, urb->setup_packet, sizeof(struct usb_ctrlrequest), DMA_TO_DEVICE); - else if (hcd->driver->flags & HCD_LOCAL_MEM) + if (dma_mapping_error(hcd->self.controller, + urb->setup_dma)) + return -EAGAIN; + } else if (hcd->driver->flags & HCD_LOCAL_MEM) ret = hcd_alloc_coherent( urb->dev->bus, mem_flags, &urb->setup_dma, @@ -1293,13 +1297,16 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; if (ret == 0 && urb->transfer_buffer_length != 0 && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { - if (hcd->self.uses_dma) + if (hcd->self.uses_dma) { urb->transfer_dma = dma_map_single ( hcd->self.controller, urb->transfer_buffer, urb->transfer_buffer_length, dir); - else if (hcd->driver->flags & HCD_LOCAL_MEM) { + if (dma_mapping_error(hcd->self.controller, + urb->transfer_dma)) + return -EAGAIN; + } else if (hcd->driver->flags & HCD_LOCAL_MEM) { ret = hcd_alloc_coherent( urb->dev->bus, mem_flags, &urb->transfer_dma, @@ -1589,19 +1596,32 @@ rescan: } } -/* Check whether a new configuration or alt setting for an interface - * will exceed the bandwidth for the bus (or the host controller resources). - * Only pass in a non-NULL config or interface, not both! - * Passing NULL for both new_config and new_intf means the device will be - * de-configured by issuing a set configuration 0 command. +/** + * Check whether a new bandwidth setting exceeds the bus bandwidth. + * @new_config: new configuration to install + * @cur_alt: the current alternate interface setting + * @new_alt: alternate interface setting that is being installed + * + * To change configurations, pass in the new configuration in new_config, + * and pass NULL for cur_alt and new_alt. + * + * To reset a device's configuration (put the device in the ADDRESSED state), + * pass in NULL for new_config, cur_alt, and new_alt. + * + * To change alternate interface settings, pass in NULL for new_config, + * pass in the current alternate interface setting in cur_alt, + * and pass in the new alternate interface setting in new_alt. + * + * Returns an error if the requested bandwidth change exceeds the + * bus bandwidth or host controller internal resources. */ -int usb_hcd_check_bandwidth(struct usb_device *udev, +int usb_hcd_alloc_bandwidth(struct usb_device *udev, struct usb_host_config *new_config, - struct usb_interface *new_intf) + struct usb_host_interface *cur_alt, + struct usb_host_interface *new_alt) { int num_intfs, i, j; - struct usb_interface_cache *intf_cache; - struct usb_host_interface *alt = 0; + struct usb_host_interface *alt = NULL; int ret = 0; struct usb_hcd *hcd; struct usb_host_endpoint *ep; @@ -1611,7 +1631,7 @@ int usb_hcd_check_bandwidth(struct usb_device *udev, return 0; /* Configuration is being removed - set configuration 0 */ - if (!new_config && !new_intf) { + if (!new_config && !cur_alt) { for (i = 1; i < 16; ++i) { ep = udev->ep_out[i]; if (ep) @@ -1648,19 +1668,12 @@ int usb_hcd_check_bandwidth(struct usb_device *udev, } } for (i = 0; i < num_intfs; ++i) { + /* Set up endpoints for alternate interface setting 0 */ + alt = usb_find_alt_setting(new_config, i, 0); + if (!alt) + /* No alt setting 0? Pick the first setting. */ + alt = &new_config->intf_cache[i]->altsetting[0]; - /* Dig the endpoints for alt setting 0 out of the - * interface cache for this interface - */ - intf_cache = new_config->intf_cache[i]; - for (j = 0; j < intf_cache->num_altsetting; j++) { - if (intf_cache->altsetting[j].desc.bAlternateSetting == 0) - alt = &intf_cache->altsetting[j]; - } - if (!alt) { - printk(KERN_DEBUG "Did not find alt setting 0 for intf %d\n", i); - continue; - } for (j = 0; j < alt->desc.bNumEndpoints; j++) { ret = hcd->driver->add_endpoint(hcd, udev, &alt->endpoint[j]); if (ret < 0) @@ -1668,6 +1681,22 @@ int usb_hcd_check_bandwidth(struct usb_device *udev, } } } + if (cur_alt && new_alt) { + /* Drop all the endpoints in the current alt setting */ + for (i = 0; i < cur_alt->desc.bNumEndpoints; i++) { + ret = hcd->driver->drop_endpoint(hcd, udev, + &cur_alt->endpoint[i]); + if (ret < 0) + goto reset; + } + /* Add all the endpoints in the new alt setting */ + for (i = 0; i < new_alt->desc.bNumEndpoints; i++) { + ret = hcd->driver->add_endpoint(hcd, udev, + &new_alt->endpoint[i]); + if (ret < 0) + goto reset; + } + } ret = hcd->driver->check_bandwidth(hcd, udev); reset: if (ret < 0) @@ -1984,6 +2013,7 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, #ifdef CONFIG_PM INIT_WORK(&hcd->wakeup_work, hcd_resume_work); #endif + mutex_init(&hcd->bandwidth_mutex); hcd->driver = driver; hcd->product_desc = (driver->product_desc) ? driver->product_desc : diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 79782a1c43f6098d98ac008bb5591b8607911ca1..d8b43aee581e2d3c463efafcb396f9b8dd86a5e5 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -111,6 +111,20 @@ struct usb_hcd { u64 rsrc_len; /* memory/io resource length */ unsigned power_budget; /* in mA, 0 = no limit */ + /* bandwidth_mutex should be taken before adding or removing + * any new bus bandwidth constraints: + * 1. Before adding a configuration for a new device. + * 2. Before removing the configuration to put the device into + * the addressed state. + * 3. Before selecting a different configuration. + * 4. Before selecting an alternate interface setting. + * + * bandwidth_mutex should be dropped after a successful control message + * to the device, or resetting the bandwidth after a failed attempt. + */ + struct mutex bandwidth_mutex; + + #define HCD_BUFFER_POOLS 4 struct dma_pool *pool [HCD_BUFFER_POOLS]; @@ -290,9 +304,10 @@ extern void usb_hcd_disable_endpoint(struct usb_device *udev, extern void usb_hcd_reset_endpoint(struct usb_device *udev, struct usb_host_endpoint *ep); extern void usb_hcd_synchronize_unlinks(struct usb_device *udev); -extern int usb_hcd_check_bandwidth(struct usb_device *udev, +extern int usb_hcd_alloc_bandwidth(struct usb_device *udev, struct usb_host_config *new_config, - struct usb_interface *new_intf); + struct usb_host_interface *old_alt, + struct usb_host_interface *new_alt); extern int usb_hcd_get_frame_number(struct usb_device *udev); extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0f857e6450581159a261fc59d0403b7300fc8b24..06af970e10641a7fd884cd9cb857a8a5e3c12382 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -45,7 +45,6 @@ struct usb_hub { /* buffer for urb ... with extra space in case of babble */ char (*buffer)[8]; - dma_addr_t buffer_dma; /* DMA address for buffer */ union { struct usb_hub_status hub; struct usb_port_status port; @@ -61,6 +60,8 @@ struct usb_hub { status change */ unsigned long busy_bits[1]; /* ports being reset or resumed */ + unsigned long removed_bits[1]; /* ports with a "removed" + device present */ #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ #error event_bits[] is too short! #endif @@ -70,6 +71,7 @@ struct usb_hub { unsigned mA_per_port; /* current for each child */ + unsigned init_done:1; unsigned limited_power:1; unsigned quiescing:1; unsigned disconnected:1; @@ -374,12 +376,13 @@ static void kick_khubd(struct usb_hub *hub) { unsigned long flags; - /* Suppress autosuspend until khubd runs */ - atomic_set(&to_usb_interface(hub->intfdev)->pm_usage_cnt, 1); - spin_lock_irqsave(&hub_event_lock, flags); if (!hub->disconnected && list_empty(&hub->event_list)) { list_add_tail(&hub->event_list, &hub_event_list); + + /* Suppress autosuspend until khubd runs */ + usb_autopm_get_interface_no_resume( + to_usb_interface(hub->intfdev)); wake_up(&khubd_wait); } spin_unlock_irqrestore(&hub_event_lock, flags); @@ -636,8 +639,35 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1) kick_khubd(hub); } +/** + * usb_remove_device - disable a device's port on its parent hub + * @udev: device to be disabled and removed + * Context: @udev locked, must be able to sleep. + * + * After @udev's port has been disabled, khubd is notified and it will + * see that the device has been disconnected. When the device is + * physically unplugged and something is plugged in, the events will + * be received and processed normally. + */ +int usb_remove_device(struct usb_device *udev) +{ + struct usb_hub *hub; + struct usb_interface *intf; + + if (!udev->parent) /* Can't remove a root hub */ + return -EINVAL; + hub = hdev_to_hub(udev->parent); + intf = to_usb_interface(hub->intfdev); + + usb_autopm_get_interface(intf); + set_bit(udev->portnum, hub->removed_bits); + hub_port_logical_disconnect(hub, udev->portnum); + usb_autopm_put_interface(intf); + return 0; +} + enum hub_activation_type { - HUB_INIT, HUB_INIT2, HUB_INIT3, + HUB_INIT, HUB_INIT2, HUB_INIT3, /* INITs must come first */ HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME, }; @@ -682,8 +712,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) msecs_to_jiffies(delay)); /* Suppress autosuspend until init is done */ - atomic_set(&to_usb_interface(hub->intfdev)-> - pm_usage_cnt, 1); + usb_autopm_get_interface_no_resume( + to_usb_interface(hub->intfdev)); return; /* Continues at init2: below */ } else { hub_power_on(hub, true); @@ -731,6 +761,13 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) USB_PORT_FEAT_C_ENABLE); } + /* We can forget about a "removed" device when there's a + * physical disconnect or the connect status changes. + */ + if (!(portstatus & USB_PORT_STAT_CONNECTION) || + (portchange & USB_PORT_STAT_C_CONNECTION)) + clear_bit(port1, hub->removed_bits); + if (!udev || udev->state == USB_STATE_NOTATTACHED) { /* Tell khubd to disconnect the device or * check for a new connection @@ -783,6 +820,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) } init3: hub->quiescing = 0; + hub->init_done = 1; status = usb_submit_urb(hub->urb, GFP_NOIO); if (status < 0) @@ -792,6 +830,10 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) /* Scan all ports that need attention */ kick_khubd(hub); + + /* Allow autosuspend if it was suppressed */ + if (type <= HUB_INIT3) + usb_autopm_put_interface_async(to_usb_interface(hub->intfdev)); } /* Implement the continuations for the delays above */ @@ -819,6 +861,11 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) int i; cancel_delayed_work_sync(&hub->init_work); + if (!hub->init_done) { + hub->init_done = 1; + usb_autopm_put_interface_no_suspend( + to_usb_interface(hub->intfdev)); + } /* khubd and related activity won't re-trigger */ hub->quiescing = 1; @@ -869,8 +916,7 @@ static int hub_configure(struct usb_hub *hub, int maxp, ret; char *message = "out of memory"; - hub->buffer = usb_buffer_alloc(hdev, sizeof(*hub->buffer), GFP_KERNEL, - &hub->buffer_dma); + hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL); if (!hub->buffer) { ret = -ENOMEM; goto fail; @@ -1111,8 +1157,6 @@ static int hub_configure(struct usb_hub *hub, usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq, hub, endpoint->bInterval); - hub->urb->transfer_dma = hub->buffer_dma; - hub->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* maybe cycle the hub leds */ if (hub->has_indicators && blinkenlights) @@ -1144,7 +1188,10 @@ static void hub_disconnect(struct usb_interface *intf) /* Take the hub off the event list and don't let it be added again */ spin_lock_irq(&hub_event_lock); - list_del_init(&hub->event_list); + if (!list_empty(&hub->event_list)) { + list_del_init(&hub->event_list); + usb_autopm_put_interface_no_suspend(intf); + } hub->disconnected = 1; spin_unlock_irq(&hub_event_lock); @@ -1162,8 +1209,7 @@ static void hub_disconnect(struct usb_interface *intf) kfree(hub->port_owners); kfree(hub->descriptor); kfree(hub->status); - usb_buffer_free(hub->hdev, sizeof(*hub->buffer), hub->buffer, - hub->buffer_dma); + kfree(hub->buffer); kref_put(&hub->kref, hub_release); } @@ -1630,7 +1676,7 @@ static int usb_configure_device_otg(struct usb_device *udev) if (!udev->bus->is_b_host && udev->config && udev->parent == udev->bus->root_hub) { - struct usb_otg_descriptor *desc = 0; + struct usb_otg_descriptor *desc = NULL; struct usb_bus *bus = udev->bus; /* descriptor may appear anywhere in config */ @@ -2123,9 +2169,13 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); - if (status) + if (status) { dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", status); + /* bail if autosuspend is requested */ + if (msg.event & PM_EVENT_AUTO) + return status; + } } /* see 7.1.7.6 */ @@ -2134,7 +2184,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", port1, status); /* paranoia: "should not happen" */ - (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + if (udev->do_remote_wakeup) + (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0, @@ -2965,6 +3016,13 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, usb_disconnect(&hdev->children[port1-1]); clear_bit(port1, hub->change_bits); + /* We can forget about a "removed" device when there's a physical + * disconnect or the connect status changes. + */ + if (!(portstatus & USB_PORT_STAT_CONNECTION) || + (portchange & USB_PORT_STAT_C_CONNECTION)) + clear_bit(port1, hub->removed_bits); + if (portchange & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE)) { status = hub_port_debounce(hub, port1); @@ -2978,8 +3036,11 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, } } - /* Return now if debouncing failed or nothing is connected */ - if (!(portstatus & USB_PORT_STAT_CONNECTION)) { + /* Return now if debouncing failed or nothing is connected or + * the device was "removed". + */ + if (!(portstatus & USB_PORT_STAT_CONNECTION) || + test_bit(port1, hub->removed_bits)) { /* maybe switch power back on (e.g. root hub was reset) */ if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2 @@ -3189,7 +3250,7 @@ static void hub_events(void) * disconnected while waiting for the lock to succeed. */ usb_lock_device(hdev); if (unlikely(hub->disconnected)) - goto loop; + goto loop2; /* If the hub has died, clean up after it */ if (hdev->state == USB_STATE_NOTATTACHED) { @@ -3338,11 +3399,15 @@ static void hub_events(void) } } -loop_autopm: - /* Allow autosuspend if we're not going to run again */ - if (list_empty(&hub->event_list)) - usb_autopm_enable(intf); -loop: + loop_autopm: + /* Balance the usb_autopm_get_interface() above */ + usb_autopm_put_interface_no_suspend(intf); + loop: + /* Balance the usb_autopm_get_interface_no_resume() in + * kick_khubd() and allow autosuspend. + */ + usb_autopm_put_interface(intf); + loop2: usb_unlock_device(hdev); kref_put(&hub->kref, hub_release); @@ -3534,6 +3599,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) { struct usb_device *parent_hdev = udev->parent; struct usb_hub *parent_hub; + struct usb_hcd *hcd = bus_to_hcd(udev->bus); struct usb_device_descriptor descriptor = udev->descriptor; int i, ret = 0; int port1 = udev->portnum; @@ -3577,6 +3643,16 @@ static int usb_reset_and_verify_device(struct usb_device *udev) /* Restore the device's previous configuration */ if (!udev->actconfig) goto done; + + mutex_lock(&hcd->bandwidth_mutex); + ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL); + if (ret < 0) { + dev_warn(&udev->dev, + "Busted HC? Not enough HCD resources for " + "old configuration.\n"); + mutex_unlock(&hcd->bandwidth_mutex); + goto re_enumerate; + } ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), USB_REQ_SET_CONFIGURATION, 0, udev->actconfig->desc.bConfigurationValue, 0, @@ -3585,8 +3661,10 @@ static int usb_reset_and_verify_device(struct usb_device *udev) dev_err(&udev->dev, "can't restore configuration #%d (error=%d)\n", udev->actconfig->desc.bConfigurationValue, ret); + mutex_unlock(&hcd->bandwidth_mutex); goto re_enumerate; } + mutex_unlock(&hcd->bandwidth_mutex); usb_set_device_state(udev, USB_STATE_CONFIGURED); /* Put interfaces back into the same altsettings as before. @@ -3596,7 +3674,8 @@ static int usb_reset_and_verify_device(struct usb_device *udev) * endpoint state. */ for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { - struct usb_interface *intf = udev->actconfig->interface[i]; + struct usb_host_config *config = udev->actconfig; + struct usb_interface *intf = config->interface[i]; struct usb_interface_descriptor *desc; desc = &intf->cur_altsetting->desc; @@ -3605,6 +3684,17 @@ static int usb_reset_and_verify_device(struct usb_device *udev) usb_enable_interface(udev, intf, true); ret = 0; } else { + /* We've just reset the device, so it will think alt + * setting 0 is installed. For usb_set_interface() to + * work properly, we need to set the current alternate + * interface setting to 0 (or the first alt setting, if + * the device doesn't have alt setting 0). + */ + intf->cur_altsetting = + usb_find_alt_setting(config, i, 0); + if (!intf->cur_altsetting) + intf->cur_altsetting = + &config->intf_cache[i]->altsetting[0]; ret = usb_set_interface(udev, desc->bInterfaceNumber, desc->bAlternateSetting); } diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index e80f1af438c8f2af202438685662495ebc5df307..1b994846e8e01bec12219873eb6926e97cbc3e81 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -393,13 +393,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev, if (io->entries <= 0) return io->entries; - /* If we're running on an xHCI host controller, queue the whole scatter - * gather list with one call to urb_enqueue(). This is only for bulk, - * as that endpoint type does not care how the data gets broken up - * across frames. - */ - if (usb_pipebulk(pipe) && - bus_to_hcd(dev->bus)->driver->flags & HCD_USB3) { + if (dev->bus->sg_tablesize > 0) { io->urbs = kmalloc(sizeof *io->urbs, mem_flags); use_sg = true; } else { @@ -409,7 +403,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev, if (!io->urbs) goto nomem; - urb_flags = URB_NO_INTERRUPT; + urb_flags = 0; if (dma) urb_flags |= URB_NO_TRANSFER_DMA_MAP; if (usb_pipein(pipe)) @@ -441,6 +435,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev, io->urbs[0]->num_sgs = io->entries; io->entries = 1; } else { + urb_flags |= URB_NO_INTERRUPT; for_each_sg(sg, sg, io->entries, i) { unsigned len; @@ -1303,6 +1298,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) { struct usb_interface *iface; struct usb_host_interface *alt; + struct usb_hcd *hcd = bus_to_hcd(dev->bus); int ret; int manual = 0; unsigned int epaddr; @@ -1325,6 +1321,18 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) return -EINVAL; } + /* Make sure we have enough bandwidth for this alternate interface. + * Remove the current alt setting and add the new alt setting. + */ + mutex_lock(&hcd->bandwidth_mutex); + ret = usb_hcd_alloc_bandwidth(dev, NULL, iface->cur_altsetting, alt); + if (ret < 0) { + dev_info(&dev->dev, "Not enough bandwidth for altsetting %d\n", + alternate); + mutex_unlock(&hcd->bandwidth_mutex); + return ret; + } + if (dev->quirks & USB_QUIRK_NO_SET_INTF) ret = -EPIPE; else @@ -1340,8 +1348,13 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) "manual set_interface for iface %d, alt %d\n", interface, alternate); manual = 1; - } else if (ret < 0) + } else if (ret < 0) { + /* Re-instate the old alt setting */ + usb_hcd_alloc_bandwidth(dev, NULL, alt, iface->cur_altsetting); + mutex_unlock(&hcd->bandwidth_mutex); return ret; + } + mutex_unlock(&hcd->bandwidth_mutex); /* FIXME drivers shouldn't need to replicate/bugfix the logic here * when they implement async or easily-killable versions of this or @@ -1423,6 +1436,7 @@ int usb_reset_configuration(struct usb_device *dev) { int i, retval; struct usb_host_config *config; + struct usb_hcd *hcd = bus_to_hcd(dev->bus); if (dev->state == USB_STATE_SUSPENDED) return -EHOSTUNREACH; @@ -1438,12 +1452,46 @@ int usb_reset_configuration(struct usb_device *dev) } config = dev->actconfig; + retval = 0; + mutex_lock(&hcd->bandwidth_mutex); + /* Make sure we have enough bandwidth for each alternate setting 0 */ + for (i = 0; i < config->desc.bNumInterfaces; i++) { + struct usb_interface *intf = config->interface[i]; + struct usb_host_interface *alt; + + alt = usb_altnum_to_altsetting(intf, 0); + if (!alt) + alt = &intf->altsetting[0]; + if (alt != intf->cur_altsetting) + retval = usb_hcd_alloc_bandwidth(dev, NULL, + intf->cur_altsetting, alt); + if (retval < 0) + break; + } + /* If not, reinstate the old alternate settings */ + if (retval < 0) { +reset_old_alts: + for (; i >= 0; i--) { + struct usb_interface *intf = config->interface[i]; + struct usb_host_interface *alt; + + alt = usb_altnum_to_altsetting(intf, 0); + if (!alt) + alt = &intf->altsetting[0]; + if (alt != intf->cur_altsetting) + usb_hcd_alloc_bandwidth(dev, NULL, + alt, intf->cur_altsetting); + } + mutex_unlock(&hcd->bandwidth_mutex); + return retval; + } retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, config->desc.bConfigurationValue, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); if (retval < 0) - return retval; + goto reset_old_alts; + mutex_unlock(&hcd->bandwidth_mutex); /* re-init hc/hcd interface/endpoint state */ for (i = 0; i < config->desc.bNumInterfaces; i++) { @@ -1585,7 +1633,7 @@ static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev, * * See usb_queue_reset_device() for more details */ -void __usb_queue_reset_device(struct work_struct *ws) +static void __usb_queue_reset_device(struct work_struct *ws) { int rc; struct usb_interface *iface = @@ -1652,6 +1700,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) int i, ret; struct usb_host_config *cp = NULL; struct usb_interface **new_interfaces = NULL; + struct usb_hcd *hcd = bus_to_hcd(dev->bus); int n, nintf; if (dev->authorized == 0 || configuration == -1) @@ -1721,12 +1770,11 @@ free_interfaces: * host controller will not allow submissions to dropped endpoints. If * this call fails, the device state is unchanged. */ - if (cp) - ret = usb_hcd_check_bandwidth(dev, cp, NULL); - else - ret = usb_hcd_check_bandwidth(dev, NULL, NULL); + mutex_lock(&hcd->bandwidth_mutex); + ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); if (ret < 0) { usb_autosuspend_device(dev); + mutex_unlock(&hcd->bandwidth_mutex); goto free_interfaces; } @@ -1752,10 +1800,12 @@ free_interfaces: dev->actconfig = cp; if (!cp) { usb_set_device_state(dev, USB_STATE_ADDRESS); - usb_hcd_check_bandwidth(dev, NULL, NULL); + usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); usb_autosuspend_device(dev); + mutex_unlock(&hcd->bandwidth_mutex); goto free_interfaces; } + mutex_unlock(&hcd->bandwidth_mutex); usb_set_device_state(dev, USB_STATE_CONFIGURED); /* Initialize the new interface structures and the diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 7ec3041ae79ec7c2789193d44cdab5c83e904b0f..15477008b63179fdd3f28443c508653be74a744e 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -138,6 +138,16 @@ show_devnum(struct device *dev, struct device_attribute *attr, char *buf) } static DEVICE_ATTR(devnum, S_IRUGO, show_devnum, NULL); +static ssize_t +show_devpath(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct usb_device *udev; + + udev = to_usb_device(dev); + return sprintf(buf, "%s\n", udev->devpath); +} +static DEVICE_ATTR(devpath, S_IRUGO, show_devpath, NULL); + static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) { @@ -317,7 +327,6 @@ static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR, static const char on_string[] = "on"; static const char auto_string[] = "auto"; -static const char suspend_string[] = "suspend"; static ssize_t show_level(struct device *dev, struct device_attribute *attr, char *buf) @@ -325,13 +334,8 @@ show_level(struct device *dev, struct device_attribute *attr, char *buf) struct usb_device *udev = to_usb_device(dev); const char *p = auto_string; - if (udev->state == USB_STATE_SUSPENDED) { - if (udev->autoresume_disabled) - p = suspend_string; - } else { - if (udev->autosuspend_disabled) - p = on_string; - } + if (udev->state != USB_STATE_SUSPENDED && udev->autosuspend_disabled) + p = on_string; return sprintf(buf, "%s\n", p); } @@ -343,7 +347,7 @@ set_level(struct device *dev, struct device_attribute *attr, int len = count; char *cp; int rc = 0; - int old_autosuspend_disabled, old_autoresume_disabled; + int old_autosuspend_disabled; cp = memchr(buf, '\n', count); if (cp) @@ -351,7 +355,6 @@ set_level(struct device *dev, struct device_attribute *attr, usb_lock_device(udev); old_autosuspend_disabled = udev->autosuspend_disabled; - old_autoresume_disabled = udev->autoresume_disabled; /* Setting the flags without calling usb_pm_lock is a subject to * races, but who cares... @@ -359,28 +362,18 @@ set_level(struct device *dev, struct device_attribute *attr, if (len == sizeof on_string - 1 && strncmp(buf, on_string, len) == 0) { udev->autosuspend_disabled = 1; - udev->autoresume_disabled = 0; rc = usb_external_resume_device(udev, PMSG_USER_RESUME); } else if (len == sizeof auto_string - 1 && strncmp(buf, auto_string, len) == 0) { udev->autosuspend_disabled = 0; - udev->autoresume_disabled = 0; rc = usb_external_resume_device(udev, PMSG_USER_RESUME); - } else if (len == sizeof suspend_string - 1 && - strncmp(buf, suspend_string, len) == 0) { - udev->autosuspend_disabled = 0; - udev->autoresume_disabled = 1; - rc = usb_external_suspend_device(udev, PMSG_USER_SUSPEND); - } else rc = -EINVAL; - if (rc) { + if (rc) udev->autosuspend_disabled = old_autosuspend_disabled; - udev->autoresume_disabled = old_autoresume_disabled; - } usb_unlock_device(udev); return (rc < 0 ? rc : count); } @@ -508,6 +501,28 @@ static ssize_t usb_dev_authorized_store(struct device *dev, static DEVICE_ATTR(authorized, 0644, usb_dev_authorized_show, usb_dev_authorized_store); +/* "Safely remove a device" */ +static ssize_t usb_remove_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_device *udev = to_usb_device(dev); + int rc = 0; + + usb_lock_device(udev); + if (udev->state != USB_STATE_NOTATTACHED) { + + /* To avoid races, first unconfigure and then remove */ + usb_set_configuration(udev, -1); + rc = usb_remove_device(udev); + } + if (rc == 0) + rc = count; + usb_unlock_device(udev); + return rc; +} +static DEVICE_ATTR(remove, 0200, NULL, usb_remove_store); + static struct attribute *dev_attrs[] = { /* current configuration's attributes */ @@ -516,8 +531,8 @@ static struct attribute *dev_attrs[] = { &dev_attr_bConfigurationValue.attr, &dev_attr_bmAttributes.attr, &dev_attr_bMaxPower.attr, - &dev_attr_urbnum.attr, /* device attributes */ + &dev_attr_urbnum.attr, &dev_attr_idVendor.attr, &dev_attr_idProduct.attr, &dev_attr_bcdDevice.attr, @@ -529,10 +544,12 @@ static struct attribute *dev_attrs[] = { &dev_attr_speed.attr, &dev_attr_busnum.attr, &dev_attr_devnum.attr, + &dev_attr_devpath.attr, &dev_attr_version.attr, &dev_attr_maxchild.attr, &dev_attr_quirks.attr, &dev_attr_authorized.attr, + &dev_attr_remove.attr, NULL, }; static struct attribute_group dev_attr_grp = { diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 0885d4abdc6265d0b7775da9b9f5503fc2be0dff..e7cae1334693cf6a88327c331104411ce8092880 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -429,8 +429,16 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) case USB_ENDPOINT_XFER_ISOC: case USB_ENDPOINT_XFER_INT: /* too small? */ - if (urb->interval <= 0) - return -EINVAL; + switch (dev->speed) { + case USB_SPEED_VARIABLE: + if (urb->interval < 6) + return -EINVAL; + break; + default: + if (urb->interval <= 0) + return -EINVAL; + break; + } /* too big? */ switch (dev->speed) { case USB_SPEED_SUPER: /* units are 125us */ @@ -438,6 +446,10 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) if (urb->interval > (1 << 15)) return -EINVAL; max = 1 << 15; + case USB_SPEED_VARIABLE: + if (urb->interval > 16) + return -EINVAL; + break; case USB_SPEED_HIGH: /* units are microframes */ /* NOTE usb handles 2^15 */ if (urb->interval > (1024 * 8)) @@ -461,8 +473,10 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) default: return -EINVAL; } - /* Round down to a power of 2, no more than max */ - urb->interval = min(max, 1 << ilog2(urb->interval)); + if (dev->speed != USB_SPEED_VARIABLE) { + /* Round down to a power of 2, no more than max */ + urb->interval = min(max, 1 << ilog2(urb->interval)); + } } return usb_hcd_submit_urb(urb, mem_flags); diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index b1b85abb9a2df7c4177491c06f216daa9e40a3be..4e2c6df8d3cc6b0427f3d7ffa645c0073531490e 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -63,6 +63,43 @@ MODULE_PARM_DESC(autosuspend, "default autosuspend delay"); #endif +/** + * usb_find_alt_setting() - Given a configuration, find the alternate setting + * for the given interface. + * @config - the configuration to search (not necessarily the current config). + * @iface_num - interface number to search in + * @alt_num - alternate interface setting number to search for. + * + * Search the configuration's interface cache for the given alt setting. + */ +struct usb_host_interface *usb_find_alt_setting( + struct usb_host_config *config, + unsigned int iface_num, + unsigned int alt_num) +{ + struct usb_interface_cache *intf_cache = NULL; + int i; + + for (i = 0; i < config->desc.bNumInterfaces; i++) { + if (config->intf_cache[i]->altsetting[0].desc.bInterfaceNumber + == iface_num) { + intf_cache = config->intf_cache[i]; + break; + } + } + if (!intf_cache) + return NULL; + for (i = 0; i < intf_cache->num_altsetting; i++) + if (intf_cache->altsetting[i].desc.bAlternateSetting == alt_num) + return &intf_cache->altsetting[i]; + + printk(KERN_DEBUG "Did not find alt setting %u for intf %u, " + "config %u\n", alt_num, iface_num, + config->desc.bConfigurationValue); + return NULL; +} +EXPORT_SYMBOL_GPL(usb_find_alt_setting); + /** * usb_ifnum_to_if - get the interface object with a given interface number * @dev: the device whose current configuration is considered @@ -130,24 +167,17 @@ struct usb_host_interface *usb_altnum_to_altsetting( } EXPORT_SYMBOL_GPL(usb_altnum_to_altsetting); -struct find_interface_arg { - int minor; - struct usb_interface *interface; -}; - static int __find_interface(struct device *dev, void *data) { - struct find_interface_arg *arg = data; + int *minor = data; struct usb_interface *intf; if (!is_usb_interface(dev)) return 0; intf = to_usb_interface(dev); - if (intf->minor != -1 && intf->minor == arg->minor) { - arg->interface = intf; + if (intf->minor != -1 && intf->minor == *minor) return 1; - } return 0; } @@ -156,21 +186,20 @@ static int __find_interface(struct device *dev, void *data) * @drv: the driver whose current configuration is considered * @minor: the minor number of the desired device * - * This walks the driver device list and returns a pointer to the interface + * This walks the bus device list and returns a pointer to the interface * with the matching minor. Note, this only works for devices that share the * USB major number. */ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) { - struct find_interface_arg argb; - int retval; + struct device *dev; + + dev = bus_find_device(&usb_bus_type, NULL, &minor, __find_interface); + + /* Drop reference count from bus_find_device */ + put_device(dev); - argb.minor = minor; - argb.interface = NULL; - /* eat the error, it will be in argb.interface */ - retval = driver_for_each_device(&drv->drvwrap.driver, NULL, &argb, - __find_interface); - return argb.interface; + return dev ? to_usb_interface(dev) : NULL; } EXPORT_SYMBOL_GPL(usb_find_interface); @@ -1038,7 +1067,7 @@ static struct notifier_block usb_bus_nb = { struct dentry *usb_debug_root; EXPORT_SYMBOL_GPL(usb_debug_root); -struct dentry *usb_debug_devices; +static struct dentry *usb_debug_devices; static int usb_debugfs_init(void) { diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 9a8b15e6377acab8cf23be6b864f14577561fdbe..4c36c7f512a05e03728ef7575c5b0e4cefa93295 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -24,6 +24,7 @@ extern void usb_disable_device(struct usb_device *dev, int skip_ep0); extern int usb_deauthorize_device(struct usb_device *); extern int usb_authorize_device(struct usb_device *); extern void usb_detect_quirks(struct usb_device *udev); +extern int usb_remove_device(struct usb_device *udev); extern int usb_get_device_descriptor(struct usb_device *dev, unsigned int size); diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index a18e3c5dd82e48142519f85c1e36d26216052a47..ee411206c699c8b5d1812f94d510dc95f79359aa 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -732,6 +732,24 @@ config USB_FILE_STORAGE_TEST behavior of USB Mass Storage hosts. Not needed for normal operation. +config USB_MASS_STORAGE + tristate "Mass Storage Gadget" + depends on BLOCK + help + The Mass Storage Gadget acts as a USB Mass Storage disk drive. + As its storage repository it can use a regular file or a block + device (in much the same way as the "loop" device driver), + specified as a module parameter or sysfs option. + + This is heavily based on File-backed Storage Gadget and in most + cases you will want to use FSG instead. This gadget is mostly + here to test the functionality of the Mass Storage Function + which may be used with composite framework. + + Say "y" to link the driver statically, or "m" to build + a dynamically linked module called "g_file_storage". If unsure, + consider File-backed Storage Gadget. + config USB_G_SERIAL tristate "Serial Gadget (with CDC ACM and CDC OBEX support)" help @@ -794,6 +812,48 @@ config USB_CDC_COMPOSITE Say "y" to link the driver statically, or "m" to build a dynamically linked module. +config USB_G_MULTI + tristate "Multifunction Composite Gadget (EXPERIMENTAL)" + depends on BLOCK && NET + help + The Multifunction Composite Gadget provides Ethernet (RNDIS + and/or CDC Ethernet), mass storage and ACM serial link + interfaces. + + You will be asked to choose which of the two configurations is + to be available in the gadget. At least one configuration must + be chosen to make the gadget usable. Selecting more than one + configuration will prevent Windows from automatically detecting + the gadget as a composite gadget, so an INF file will be needed to + use the gadget. + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "g_multi". + +config USB_G_MULTI_RNDIS + bool "RNDIS + CDC Serial + Storage configuration" + depends on USB_G_MULTI + default y + help + This option enables a configuration with RNDIS, CDC Serial and + Mass Storage functions available in the Multifunction Composite + Gadget. This is the configuration dedicated for Windows since RNDIS + is Microsoft's protocol. + + If unsure, say "y". + +config USB_G_MULTI_CDC + bool "CDC Ethernet + CDC Serial + Storage configuration" + depends on USB_G_MULTI + default n + help + This option enables a configuration with CDC Ethernet (ECM), CDC + Serial and Mass Storage functions available in the Multifunction + Composite Gadget. + + If unsure, say "y". + + # put drivers that need isochronous transfer support (for audio # or video class gadget drivers), or specific hardware, here. diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 9d7b87c52e9f4b1f6cc0d52447040fd5477971e3..2e2c047262b78e12e71df90330219a0bf7219f71 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -39,16 +39,20 @@ g_serial-objs := serial.o g_midi-objs := gmidi.o gadgetfs-objs := inode.o g_file_storage-objs := file_storage.o +g_mass_storage-objs := mass_storage.o g_printer-objs := printer.o g_cdc-objs := cdc2.o +g_multi-objs := multi.o obj-$(CONFIG_USB_ZERO) += g_zero.o obj-$(CONFIG_USB_AUDIO) += g_audio.o obj-$(CONFIG_USB_ETH) += g_ether.o obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o +obj-$(CONFIG_USB_MASS_STORAGE) += g_mass_storage.o obj-$(CONFIG_USB_G_SERIAL) += g_serial.o obj-$(CONFIG_USB_G_PRINTER) += g_printer.o obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o +obj-$(CONFIG_USB_G_MULTI) += g_multi.o diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 66450a1abc227a3fc437e165a385b161fd7b9792..043e04db2a0555e7548782d8ddeb967a31772bd7 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -892,7 +892,7 @@ static void pullup(struct at91_udc *udc, int is_on) txvc |= AT91_UDP_TXVC_PUON; at91_udp_write(udc, AT91_UDP_TXVC, txvc); - } else if (cpu_is_at91sam9261()) { + } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) { u32 usbpucr; usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR); @@ -910,7 +910,7 @@ static void pullup(struct at91_udc *udc, int is_on) txvc &= ~AT91_UDP_TXVC_PUON; at91_udp_write(udc, AT91_UDP_TXVC, txvc); - } else if (cpu_is_at91sam9261()) { + } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) { u32 usbpucr; usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR); @@ -1692,7 +1692,7 @@ static int __init at91udc_probe(struct platform_device *pdev) udc->ep[3].maxpacket = 64; udc->ep[4].maxpacket = 512; udc->ep[5].maxpacket = 512; - } else if (cpu_is_at91sam9261()) { + } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) { udc->ep[3].maxpacket = 64; } else if (cpu_is_at91sam9263()) { udc->ep[0].maxpacket = 64; diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index a3a0f4a27ef0d9edea1720aba630050ab9abd7ab..58f2203238471ae06f0504ae26b71b53b27bd71f 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -89,120 +89,6 @@ static const struct usb_descriptor_header *otg_desc[] = { /*-------------------------------------------------------------------------*/ -/** - * Handle USB audio endpoint set/get command in setup class request - */ - -static int audio_set_endpoint_req(struct usb_configuration *c, - const struct usb_ctrlrequest *ctrl) -{ - struct usb_composite_dev *cdev = c->cdev; - int value = -EOPNOTSUPP; - u16 ep = le16_to_cpu(ctrl->wIndex); - u16 len = le16_to_cpu(ctrl->wLength); - u16 w_value = le16_to_cpu(ctrl->wValue); - - DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", - ctrl->bRequest, w_value, len, ep); - - switch (ctrl->bRequest) { - case UAC_SET_CUR: - value = 0; - break; - - case UAC_SET_MIN: - break; - - case UAC_SET_MAX: - break; - - case UAC_SET_RES: - break; - - case UAC_SET_MEM: - break; - - default: - break; - } - - return value; -} - -static int audio_get_endpoint_req(struct usb_configuration *c, - const struct usb_ctrlrequest *ctrl) -{ - struct usb_composite_dev *cdev = c->cdev; - int value = -EOPNOTSUPP; - u8 ep = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF); - u16 len = le16_to_cpu(ctrl->wLength); - u16 w_value = le16_to_cpu(ctrl->wValue); - - DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", - ctrl->bRequest, w_value, len, ep); - - switch (ctrl->bRequest) { - case UAC_GET_CUR: - case UAC_GET_MIN: - case UAC_GET_MAX: - case UAC_GET_RES: - value = 3; - break; - case UAC_GET_MEM: - break; - default: - break; - } - - return value; -} - -static int -audio_setup(struct usb_configuration *c, const struct usb_ctrlrequest *ctrl) -{ - struct usb_composite_dev *cdev = c->cdev; - struct usb_request *req = cdev->req; - int value = -EOPNOTSUPP; - u16 w_index = le16_to_cpu(ctrl->wIndex); - u16 w_value = le16_to_cpu(ctrl->wValue); - u16 w_length = le16_to_cpu(ctrl->wLength); - - /* composite driver infrastructure handles everything except - * Audio class messages; interface activation uses set_alt(). - */ - switch (ctrl->bRequestType) { - case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: - value = audio_set_endpoint_req(c, ctrl); - break; - - case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: - value = audio_get_endpoint_req(c, ctrl); - break; - - default: - ERROR(cdev, "Invalid control req%02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - w_value, w_index, w_length); - } - - /* respond with data transfer or status phase? */ - if (value >= 0) { - DBG(cdev, "Audio req%02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - w_value, w_index, w_length); - req->zero = 0; - req->length = value; - value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); - if (value < 0) - ERROR(cdev, "Audio response on err %d\n", value); - } - - /* device either stalls (value < 0) or reports success */ - return value; -} - -/*-------------------------------------------------------------------------*/ - static int __init audio_do_config(struct usb_configuration *c) { /* FIXME alloc iConfiguration string, set it in c->strings */ @@ -220,7 +106,6 @@ static int __init audio_do_config(struct usb_configuration *c) static struct usb_configuration audio_config_driver = { .label = DRIVER_DESC, .bind = audio_do_config, - .setup = audio_setup, .bConfigurationValue = 1, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index d05397ec8a183ebb4467b10f55fe9b67e1cce189..09289bb1e20fcf984b388b32f55a6c404cc1dcb3 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -373,6 +373,8 @@ static void reset_config(struct usb_composite_dev *cdev) list_for_each_entry(f, &cdev->config->functions, list) { if (f->disable) f->disable(f); + + bitmap_zero(f->endpoints, 32); } cdev->config = NULL; } @@ -418,10 +420,35 @@ static int set_config(struct usb_composite_dev *cdev, /* Initialize all interfaces by setting them to altsetting zero. */ for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) { struct usb_function *f = c->interface[tmp]; + struct usb_descriptor_header **descriptors; if (!f) break; + /* + * Record which endpoints are used by the function. This is used + * to dispatch control requests targeted at that endpoint to the + * function's setup callback instead of the current + * configuration's setup callback. + */ + if (gadget->speed == USB_SPEED_HIGH) + descriptors = f->hs_descriptors; + else + descriptors = f->descriptors; + + for (; *descriptors; ++descriptors) { + struct usb_endpoint_descriptor *ep; + int addr; + + if ((*descriptors)->bDescriptorType != USB_DT_ENDPOINT) + continue; + + ep = (struct usb_endpoint_descriptor *)*descriptors; + addr = ((ep->bEndpointAddress & 0x80) >> 3) + | (ep->bEndpointAddress & 0x0f); + set_bit(addr, f->endpoints); + } + result = f->set_alt(f, tmp, 0); if (result < 0) { DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n", @@ -688,6 +715,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) u16 w_value = le16_to_cpu(ctrl->wValue); u16 w_length = le16_to_cpu(ctrl->wLength); struct usb_function *f = NULL; + u8 endp; /* partial re-init of the response message; the function or the * gadget might need to intercept e.g. a control-OUT completion @@ -800,23 +828,33 @@ unknown: ctrl->bRequestType, ctrl->bRequest, w_value, w_index, w_length); - /* functions always handle their interfaces ... punt other - * recipients (endpoint, other, WUSB, ...) to the current + /* functions always handle their interfaces and endpoints... + * punt other recipients (other, WUSB, ...) to the current * configuration code. * * REVISIT it could make sense to let the composite device * take such requests too, if that's ever needed: to work * in config 0, etc. */ - if ((ctrl->bRequestType & USB_RECIP_MASK) - == USB_RECIP_INTERFACE) { + switch (ctrl->bRequestType & USB_RECIP_MASK) { + case USB_RECIP_INTERFACE: f = cdev->config->interface[intf]; - if (f && f->setup) - value = f->setup(f, ctrl); - else + break; + + case USB_RECIP_ENDPOINT: + endp = ((w_index & 0x80) >> 3) | (w_index & 0x0f); + list_for_each_entry(f, &cdev->config->functions, list) { + if (test_bit(endp, f->endpoints)) + break; + } + if (&f->list == &cdev->config->functions) f = NULL; + break; } - if (value < 0 && !f) { + + if (f && f->setup) + value = f->setup(f, ctrl); + else { struct usb_configuration *c; c = cdev->config; @@ -1054,7 +1092,8 @@ static struct usb_gadget_driver composite_driver = { .speed = USB_SPEED_HIGH, .bind = composite_bind, - .unbind = __exit_p(composite_unbind), + /* .unbind = __exit_p(composite_unbind), */ + .unbind = composite_unbind, .setup = composite_setup, .disconnect = composite_disconnect, @@ -1103,7 +1142,7 @@ int __init usb_composite_register(struct usb_composite_driver *driver) * This function is used to unregister drivers using the composite * driver framework. */ -void __exit usb_composite_unregister(struct usb_composite_driver *driver) +void /* __exit */ usb_composite_unregister(struct usb_composite_driver *driver) { if (composite != driver) return; diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 167cb2a8ecefc1849545655cddf408dd3f009a7f..141372b6e7a143b9a2497a1abf5d21b5f9ca3249 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -25,6 +25,14 @@ #include #include + +#if defined USB_ETH_RNDIS +# undef USB_ETH_RNDIS +#endif +#ifdef CONFIG_USB_ETH_RNDIS +# define USB_ETH_RNDIS y +#endif + #include "u_ether.h" @@ -66,7 +74,7 @@ #define DRIVER_DESC "Ethernet Gadget" #define DRIVER_VERSION "Memorial Day 2008" -#ifdef CONFIG_USB_ETH_RNDIS +#ifdef USB_ETH_RNDIS #define PREFIX "RNDIS/" #else #define PREFIX "" @@ -87,7 +95,7 @@ static inline bool has_rndis(void) { -#ifdef CONFIG_USB_ETH_RNDIS +#ifdef USB_ETH_RNDIS return true; #else return false; @@ -110,7 +118,7 @@ static inline bool has_rndis(void) #include "f_ecm.c" #include "f_subset.c" -#ifdef CONFIG_USB_ETH_RNDIS +#ifdef USB_ETH_RNDIS #include "f_rndis.c" #include "rndis.c" #endif @@ -251,7 +259,7 @@ static struct usb_configuration rndis_config_driver = { /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_USB_ETH_EEM +#ifdef USB_ETH_EEM static int use_eem = 1; #else static int use_eem; diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index 4e3657808b0f49fd245ac08d973975716827dd75..d10353d46b8604f927e4e051e61ff159932c2cc9 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -4,6 +4,8 @@ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) * Copyright (C) 2008 by David Brownell * Copyright (C) 2008 by Nokia Corporation + * Copyright (C) 2009 by Samsung Electronics + * Author: Michal Nazarewicz (m.nazarewicz@samsung.com) * * This software is distributed under the terms of the GNU General * Public License ("GPL") as published by the Free Software Foundation, @@ -99,6 +101,20 @@ static inline struct f_acm *port_to_acm(struct gserial *p) /* interface and class descriptors: */ +static struct usb_interface_assoc_descriptor +acm_iad_descriptor = { + .bLength = sizeof acm_iad_descriptor, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + + /* .bFirstInterface = DYNAMIC, */ + .bInterfaceCount = 2, // control + data + .bFunctionClass = USB_CLASS_COMM, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_CDC_PROTO_NONE, + /* .iFunction = DYNAMIC */ +}; + + static struct usb_interface_descriptor acm_control_interface_desc __initdata = { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, @@ -178,6 +194,7 @@ static struct usb_endpoint_descriptor acm_fs_out_desc __initdata = { }; static struct usb_descriptor_header *acm_fs_function[] __initdata = { + (struct usb_descriptor_header *) &acm_iad_descriptor, (struct usb_descriptor_header *) &acm_control_interface_desc, (struct usb_descriptor_header *) &acm_header_desc, (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, @@ -216,6 +233,7 @@ static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = { }; static struct usb_descriptor_header *acm_hs_function[] __initdata = { + (struct usb_descriptor_header *) &acm_iad_descriptor, (struct usb_descriptor_header *) &acm_control_interface_desc, (struct usb_descriptor_header *) &acm_header_desc, (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, @@ -232,11 +250,13 @@ static struct usb_descriptor_header *acm_hs_function[] __initdata = { #define ACM_CTRL_IDX 0 #define ACM_DATA_IDX 1 +#define ACM_IAD_IDX 2 /* static strings, in UTF-8 */ static struct usb_string acm_string_defs[] = { [ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)", [ACM_DATA_IDX].s = "CDC ACM Data", + [ACM_IAD_IDX ].s = "CDC Serial", { /* ZEROES END LIST */ }, }; @@ -563,6 +583,7 @@ acm_bind(struct usb_configuration *c, struct usb_function *f) if (status < 0) goto fail; acm->ctrl_id = status; + acm_iad_descriptor.bFirstInterface = status; acm_control_interface_desc.bInterfaceNumber = status; acm_union_desc .bMasterInterface0 = status; @@ -732,6 +753,13 @@ int __init acm_bind_config(struct usb_configuration *c, u8 port_num) acm_string_defs[ACM_DATA_IDX].id = status; acm_data_interface_desc.iInterface = status; + + status = usb_string_id(c->cdev); + if (status < 0) + return status; + acm_string_defs[ACM_IAD_IDX].id = status; + + acm_iad_descriptor.iFunction = status; } /* allocate and initialize one new instance */ diff --git a/drivers/usb/gadget/f_audio.c b/drivers/usb/gadget/f_audio.c index 98e9bb977291f3b61139c945df3cd5d9c4fda2a9..c43c89ffa2c89b07fd690afeca58cb34651b0358 100644 --- a/drivers/usb/gadget/f_audio.c +++ b/drivers/usb/gadget/f_audio.c @@ -445,6 +445,70 @@ static int audio_get_intf_req(struct usb_function *f, return len; } +static int audio_set_endpoint_req(struct usb_function *f, + const struct usb_ctrlrequest *ctrl) +{ + struct usb_composite_dev *cdev = f->config->cdev; + int value = -EOPNOTSUPP; + u16 ep = le16_to_cpu(ctrl->wIndex); + u16 len = le16_to_cpu(ctrl->wLength); + u16 w_value = le16_to_cpu(ctrl->wValue); + + DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", + ctrl->bRequest, w_value, len, ep); + + switch (ctrl->bRequest) { + case UAC_SET_CUR: + value = 0; + break; + + case UAC_SET_MIN: + break; + + case UAC_SET_MAX: + break; + + case UAC_SET_RES: + break; + + case UAC_SET_MEM: + break; + + default: + break; + } + + return value; +} + +static int audio_get_endpoint_req(struct usb_function *f, + const struct usb_ctrlrequest *ctrl) +{ + struct usb_composite_dev *cdev = f->config->cdev; + int value = -EOPNOTSUPP; + u8 ep = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF); + u16 len = le16_to_cpu(ctrl->wLength); + u16 w_value = le16_to_cpu(ctrl->wValue); + + DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", + ctrl->bRequest, w_value, len, ep); + + switch (ctrl->bRequest) { + case UAC_GET_CUR: + case UAC_GET_MIN: + case UAC_GET_MAX: + case UAC_GET_RES: + value = 3; + break; + case UAC_GET_MEM: + break; + default: + break; + } + + return value; +} + static int f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) { @@ -455,8 +519,8 @@ f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) u16 w_value = le16_to_cpu(ctrl->wValue); u16 w_length = le16_to_cpu(ctrl->wLength); - /* composite driver infrastructure handles everything except - * Audio class messages; interface activation uses set_alt(). + /* composite driver infrastructure handles everything; interface + * activation uses set_alt(). */ switch (ctrl->bRequestType) { case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE: @@ -467,6 +531,14 @@ f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) value = audio_get_intf_req(f, ctrl); break; + case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: + value = audio_set_endpoint_req(f, ctrl); + break; + + case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: + value = audio_get_endpoint_req(f, ctrl); + break; + default: ERROR(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n", ctrl->bRequestType, ctrl->bRequest, diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c new file mode 100644 index 0000000000000000000000000000000000000000..a37640eba4344b144cc6d5747d155f55ec6f8239 --- /dev/null +++ b/drivers/usb/gadget/f_mass_storage.c @@ -0,0 +1,3091 @@ +/* + * f_mass_storage.c -- Mass Storage USB Composite Function + * + * Copyright (C) 2003-2008 Alan Stern + * Copyright (C) 2009 Samsung Electronics + * Author: Michal Nazarewicz + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + + +/* + * The Mass Storage Function acts as a USB Mass Storage device, + * appearing to the host as a disk drive or as a CD-ROM drive. In + * addition to providing an example of a genuinely useful composite + * function for a USB device, it also illustrates a technique of + * double-buffering for increased throughput. + * + * Function supports multiple logical units (LUNs). Backing storage + * for each LUN is provided by a regular file or a block device. + * Access for each LUN can be limited to read-only. Moreover, the + * function can indicate that LUN is removable and/or CD-ROM. (The + * later implies read-only access.) + * + * MSF is configured by specifying a fsg_config structure. It has the + * following fields: + * + * nluns Number of LUNs function have (anywhere from 1 + * to FSG_MAX_LUNS which is 8). + * luns An array of LUN configuration values. This + * should be filled for each LUN that + * function will include (ie. for "nluns" + * LUNs). Each element of the array has + * the following fields: + * ->filename The path to the backing file for the LUN. + * Required if LUN is not marked as + * removable. + * ->ro Flag specifying access to the LUN shall be + * read-only. This is implied if CD-ROM + * emulation is enabled as well as when + * it was impossible to open "filename" + * in R/W mode. + * ->removable Flag specifying that LUN shall be indicated as + * being removable. + * ->cdrom Flag specifying that LUN shall be reported as + * being a CD-ROM. + * + * lun_name_format A printf-like format for names of the LUN + * devices. This determines how the + * directory in sysfs will be named. + * Unless you are using several MSFs in + * a single gadget (as opposed to single + * MSF in many configurations) you may + * leave it as NULL (in which case + * "lun%d" will be used). In the format + * you can use "%d" to index LUNs for + * MSF's with more than one LUN. (Beware + * that there is only one integer given + * as an argument for the format and + * specifying invalid format may cause + * unspecified behaviour.) + * thread_name Name of the kernel thread process used by the + * MSF. You can safely set it to NULL + * (in which case default "file-storage" + * will be used). + * + * vendor_name + * product_name + * release Information used as a reply to INQUIRY + * request. To use default set to NULL, + * NULL, 0xffff respectively. The first + * field should be 8 and the second 16 + * characters or less. + * + * can_stall Set to permit function to halt bulk endpoints. + * Disabled on some USB devices known not + * to work correctly. You should set it + * to true. + * + * If "removable" is not set for a LUN then a backing file must be + * specified. If it is set, then NULL filename means the LUN's medium + * is not loaded (an empty string as "filename" in the fsg_config + * structure causes error). The CD-ROM emulation includes a single + * data track and no audio tracks; hence there need be only one + * backing file per LUN. Note also that the CD-ROM block length is + * set to 512 rather than the more common value 2048. + * + * + * MSF includes support for module parameters. If gadget using it + * decides to use it, the following module parameters will be + * available: + * + * file=filename[,filename...] + * Names of the files or block devices used for + * backing storage. + * ro=b[,b...] Default false, boolean for read-only access. + * removable=b[,b...] + * Default true, boolean for removable media. + * cdrom=b[,b...] Default false, boolean for whether to emulate + * a CD-ROM drive. + * luns=N Default N = number of filenames, number of + * LUNs to support. + * stall Default determined according to the type of + * USB device controller (usually true), + * boolean to permit the driver to halt + * bulk endpoints. + * + * The module parameters may be prefixed with some string. You need + * to consult gadget's documentation or source to verify whether it is + * using those module parameters and if it does what are the prefixes + * (look for FSG_MODULE_PARAMETERS() macro usage, what's inside it is + * the prefix). + * + * + * Requirements are modest; only a bulk-in and a bulk-out endpoint are + * needed. The memory requirement amounts to two 16K buffers, size + * configurable by a parameter. Support is included for both + * full-speed and high-speed operation. + * + * Note that the driver is slightly non-portable in that it assumes a + * single memory/DMA buffer will be useable for bulk-in, bulk-out, and + * interrupt-in endpoints. With most device controllers this isn't an + * issue, but there may be some with hardware restrictions that prevent + * a buffer from being used by more than one endpoint. + * + * + * The pathnames of the backing files and the ro settings are + * available in the attribute files "file" and "ro" in the lun (or + * to be more precise in a directory which name comes from + * "lun_name_format" option!) subdirectory of the gadget's sysfs + * directory. If the "removable" option is set, writing to these + * files will simulate ejecting/loading the medium (writing an empty + * line means eject) and adjusting a write-enable tab. Changes to the + * ro setting are not allowed when the medium is loaded or if CD-ROM + * emulation is being used. + * + * + * This function is heavily based on "File-backed Storage Gadget" by + * Alan Stern which in turn is heavily based on "Gadget Zero" by David + * Brownell. The driver's SCSI command interface was based on the + * "Information technology - Small Computer System Interface - 2" + * document from X3T9.2 Project 375D, Revision 10L, 7-SEP-93, + * available at . + * The single exception is opcode 0x23 (READ FORMAT CAPACITIES), which + * was based on the "Universal Serial Bus Mass Storage Class UFI + * Command Specification" document, Revision 1.0, December 14, 1998, + * available at + * . + */ + + +/* + * Driver Design + * + * The MSF is fairly straightforward. There is a main kernel + * thread that handles most of the work. Interrupt routines field + * callbacks from the controller driver: bulk- and interrupt-request + * completion notifications, endpoint-0 events, and disconnect events. + * Completion events are passed to the main thread by wakeup calls. Many + * ep0 requests are handled at interrupt time, but SetInterface, + * SetConfiguration, and device reset requests are forwarded to the + * thread in the form of "exceptions" using SIGUSR1 signals (since they + * should interrupt any ongoing file I/O operations). + * + * The thread's main routine implements the standard command/data/status + * parts of a SCSI interaction. It and its subroutines are full of tests + * for pending signals/exceptions -- all this polling is necessary since + * the kernel has no setjmp/longjmp equivalents. (Maybe this is an + * indication that the driver really wants to be running in userspace.) + * An important point is that so long as the thread is alive it keeps an + * open reference to the backing file. This will prevent unmounting + * the backing file's underlying filesystem and could cause problems + * during system shutdown, for example. To prevent such problems, the + * thread catches INT, TERM, and KILL signals and converts them into + * an EXIT exception. + * + * In normal operation the main thread is started during the gadget's + * fsg_bind() callback and stopped during fsg_unbind(). But it can + * also exit when it receives a signal, and there's no point leaving + * the gadget running when the thread is dead. At of this moment, MSF + * provides no way to deregister the gadget when thread dies -- maybe + * a callback functions is needed. + * + * To provide maximum throughput, the driver uses a circular pipeline of + * buffer heads (struct fsg_buffhd). In principle the pipeline can be + * arbitrarily long; in practice the benefits don't justify having more + * than 2 stages (i.e., double buffering). But it helps to think of the + * pipeline as being a long one. Each buffer head contains a bulk-in and + * a bulk-out request pointer (since the buffer can be used for both + * output and input -- directions always are given from the host's + * point of view) as well as a pointer to the buffer and various state + * variables. + * + * Use of the pipeline follows a simple protocol. There is a variable + * (fsg->next_buffhd_to_fill) that points to the next buffer head to use. + * At any time that buffer head may still be in use from an earlier + * request, so each buffer head has a state variable indicating whether + * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the + * buffer head to be EMPTY, filling the buffer either by file I/O or by + * USB I/O (during which the buffer head is BUSY), and marking the buffer + * head FULL when the I/O is complete. Then the buffer will be emptied + * (again possibly by USB I/O, during which it is marked BUSY) and + * finally marked EMPTY again (possibly by a completion routine). + * + * A module parameter tells the driver to avoid stalling the bulk + * endpoints wherever the transport specification allows. This is + * necessary for some UDCs like the SuperH, which cannot reliably clear a + * halt on a bulk endpoint. However, under certain circumstances the + * Bulk-only specification requires a stall. In such cases the driver + * will halt the endpoint and set a flag indicating that it should clear + * the halt in software during the next device reset. Hopefully this + * will permit everything to work correctly. Furthermore, although the + * specification allows the bulk-out endpoint to halt when the host sends + * too much data, implementing this would cause an unavoidable race. + * The driver will always use the "no-stall" approach for OUT transfers. + * + * One subtle point concerns sending status-stage responses for ep0 + * requests. Some of these requests, such as device reset, can involve + * interrupting an ongoing file I/O operation, which might take an + * arbitrarily long time. During that delay the host might give up on + * the original ep0 request and issue a new one. When that happens the + * driver should not notify the host about completion of the original + * request, as the host will no longer be waiting for it. So the driver + * assigns to each ep0 request a unique tag, and it keeps track of the + * tag value of the request associated with a long-running exception + * (device-reset, interface-change, or configuration-change). When the + * exception handler is finished, the status-stage response is submitted + * only if the current ep0 request tag is equal to the exception request + * tag. Thus only the most recently received ep0 request will get a + * status-stage response. + * + * Warning: This driver source file is too long. It ought to be split up + * into a header file plus about 3 separate .c files, to handle the details + * of the Gadget, USB Mass Storage, and SCSI protocols. + */ + + +/* #define VERBOSE_DEBUG */ +/* #define DUMP_MSGS */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "gadget_chips.h" + + + +/*------------------------------------------------------------------------*/ + +#define FSG_DRIVER_DESC "Mass Storage Function" +#define FSG_DRIVER_VERSION "2009/09/11" + +static const char fsg_string_interface[] = "Mass Storage"; + + +#define FSG_NO_INTR_EP 1 +#define FSG_BUFFHD_STATIC_BUFFER 1 +#define FSG_NO_DEVICE_STRINGS 1 +#define FSG_NO_OTG 1 +#define FSG_NO_INTR_EP 1 + +#include "storage_common.c" + + +/*-------------------------------------------------------------------------*/ + +struct fsg_dev; + + +/* Data shared by all the FSG instances. */ +struct fsg_common { + struct usb_gadget *gadget; + struct fsg_dev *fsg; + struct fsg_dev *prev_fsg; + + /* filesem protects: backing files in use */ + struct rw_semaphore filesem; + + /* lock protects: state, all the req_busy's */ + spinlock_t lock; + + struct usb_ep *ep0; /* Copy of gadget->ep0 */ + struct usb_request *ep0req; /* Copy of cdev->req */ + unsigned int ep0_req_tag; + const char *ep0req_name; + + struct fsg_buffhd *next_buffhd_to_fill; + struct fsg_buffhd *next_buffhd_to_drain; + struct fsg_buffhd buffhds[FSG_NUM_BUFFERS]; + + int cmnd_size; + u8 cmnd[MAX_COMMAND_SIZE]; + + unsigned int nluns; + unsigned int lun; + struct fsg_lun *luns; + struct fsg_lun *curlun; + + unsigned int bulk_out_maxpacket; + enum fsg_state state; /* For exception handling */ + unsigned int exception_req_tag; + + u8 config, new_config; + enum data_direction data_dir; + u32 data_size; + u32 data_size_from_cmnd; + u32 tag; + u32 residue; + u32 usb_amount_left; + + unsigned int can_stall:1; + unsigned int free_storage_on_release:1; + unsigned int phase_error:1; + unsigned int short_packet_received:1; + unsigned int bad_lun_okay:1; + unsigned int running:1; + + int thread_wakeup_needed; + struct completion thread_notifier; + struct task_struct *thread_task; + + /* Callback function to call when thread exits. */ + void (*thread_exits)(struct fsg_common *common); + /* Gadget's private data. */ + void *private_data; + + /* Vendor (8 chars), product (16 chars), release (4 + * hexadecimal digits) and NUL byte */ + char inquiry_string[8 + 16 + 4 + 1]; + + struct kref ref; +}; + + +struct fsg_config { + unsigned nluns; + struct fsg_lun_config { + const char *filename; + char ro; + char removable; + char cdrom; + } luns[FSG_MAX_LUNS]; + + const char *lun_name_format; + const char *thread_name; + + /* Callback function to call when thread exits. */ + void (*thread_exits)(struct fsg_common *common); + /* Gadget's private data. */ + void *private_data; + + const char *vendor_name; /* 8 characters or less */ + const char *product_name; /* 16 characters or less */ + u16 release; + + char can_stall; +}; + + +struct fsg_dev { + struct usb_function function; + struct usb_gadget *gadget; /* Copy of cdev->gadget */ + struct fsg_common *common; + + u16 interface_number; + + unsigned int bulk_in_enabled:1; + unsigned int bulk_out_enabled:1; + + unsigned long atomic_bitflags; +#define IGNORE_BULK_OUT 0 + + struct usb_ep *bulk_in; + struct usb_ep *bulk_out; +}; + + +static inline int __fsg_is_set(struct fsg_common *common, + const char *func, unsigned line) +{ + if (common->fsg) + return 1; + ERROR(common, "common->fsg is NULL in %s at %u\n", func, line); + return 0; +} + +#define fsg_is_set(common) likely(__fsg_is_set(common, __func__, __LINE__)) + + +static inline struct fsg_dev *fsg_from_func(struct usb_function *f) +{ + return container_of(f, struct fsg_dev, function); +} + + +typedef void (*fsg_routine_t)(struct fsg_dev *); + +static int exception_in_progress(struct fsg_common *common) +{ + return common->state > FSG_STATE_IDLE; +} + +/* Make bulk-out requests be divisible by the maxpacket size */ +static void set_bulk_out_req_length(struct fsg_common *common, + struct fsg_buffhd *bh, unsigned int length) +{ + unsigned int rem; + + bh->bulk_out_intended_length = length; + rem = length % common->bulk_out_maxpacket; + if (rem > 0) + length += common->bulk_out_maxpacket - rem; + bh->outreq->length = length; +} + +/*-------------------------------------------------------------------------*/ + +static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) +{ + const char *name; + + if (ep == fsg->bulk_in) + name = "bulk-in"; + else if (ep == fsg->bulk_out) + name = "bulk-out"; + else + name = ep->name; + DBG(fsg, "%s set halt\n", name); + return usb_ep_set_halt(ep); +} + + +/*-------------------------------------------------------------------------*/ + +/* These routines may be called in process context or in_irq */ + +/* Caller must hold fsg->lock */ +static void wakeup_thread(struct fsg_common *common) +{ + /* Tell the main thread that something has happened */ + common->thread_wakeup_needed = 1; + if (common->thread_task) + wake_up_process(common->thread_task); +} + + +static void raise_exception(struct fsg_common *common, enum fsg_state new_state) +{ + unsigned long flags; + + /* Do nothing if a higher-priority exception is already in progress. + * If a lower-or-equal priority exception is in progress, preempt it + * and notify the main thread by sending it a signal. */ + spin_lock_irqsave(&common->lock, flags); + if (common->state <= new_state) { + common->exception_req_tag = common->ep0_req_tag; + common->state = new_state; + if (common->thread_task) + send_sig_info(SIGUSR1, SEND_SIG_FORCED, + common->thread_task); + } + spin_unlock_irqrestore(&common->lock, flags); +} + + +/*-------------------------------------------------------------------------*/ + +static int ep0_queue(struct fsg_common *common) +{ + int rc; + + rc = usb_ep_queue(common->ep0, common->ep0req, GFP_ATOMIC); + common->ep0->driver_data = common; + if (rc != 0 && rc != -ESHUTDOWN) { + /* We can't do much more than wait for a reset */ + WARNING(common, "error in submission: %s --> %d\n", + common->ep0->name, rc); + } + return rc; +} + +/*-------------------------------------------------------------------------*/ + +/* Bulk and interrupt endpoint completion handlers. + * These always run in_irq. */ + +static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct fsg_common *common = ep->driver_data; + struct fsg_buffhd *bh = req->context; + + if (req->status || req->actual != req->length) + DBG(common, "%s --> %d, %u/%u\n", __func__, + req->status, req->actual, req->length); + if (req->status == -ECONNRESET) /* Request was cancelled */ + usb_ep_fifo_flush(ep); + + /* Hold the lock while we update the request and buffer states */ + smp_wmb(); + spin_lock(&common->lock); + bh->inreq_busy = 0; + bh->state = BUF_STATE_EMPTY; + wakeup_thread(common); + spin_unlock(&common->lock); +} + +static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct fsg_common *common = ep->driver_data; + struct fsg_buffhd *bh = req->context; + + dump_msg(common, "bulk-out", req->buf, req->actual); + if (req->status || req->actual != bh->bulk_out_intended_length) + DBG(common, "%s --> %d, %u/%u\n", __func__, + req->status, req->actual, + bh->bulk_out_intended_length); + if (req->status == -ECONNRESET) /* Request was cancelled */ + usb_ep_fifo_flush(ep); + + /* Hold the lock while we update the request and buffer states */ + smp_wmb(); + spin_lock(&common->lock); + bh->outreq_busy = 0; + bh->state = BUF_STATE_FULL; + wakeup_thread(common); + spin_unlock(&common->lock); +} + + +/*-------------------------------------------------------------------------*/ + +/* Ep0 class-specific handlers. These always run in_irq. */ + +static int fsg_setup(struct usb_function *f, + const struct usb_ctrlrequest *ctrl) +{ + struct fsg_dev *fsg = fsg_from_func(f); + struct usb_request *req = fsg->common->ep0req; + u16 w_index = le16_to_cpu(ctrl->wIndex); + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + + if (!fsg->common->config) + return -EOPNOTSUPP; + + switch (ctrl->bRequest) { + + case USB_BULK_RESET_REQUEST: + if (ctrl->bRequestType != + (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) + break; + if (w_index != fsg->interface_number || w_value != 0) + return -EDOM; + + /* Raise an exception to stop the current operation + * and reinitialize our state. */ + DBG(fsg, "bulk reset request\n"); + raise_exception(fsg->common, FSG_STATE_RESET); + return DELAYED_STATUS; + + case USB_BULK_GET_MAX_LUN_REQUEST: + if (ctrl->bRequestType != + (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) + break; + if (w_index != fsg->interface_number || w_value != 0) + return -EDOM; + VDBG(fsg, "get max LUN\n"); + *(u8 *) req->buf = fsg->common->nluns - 1; + return 1; + } + + VDBG(fsg, + "unknown class-specific control req " + "%02x.%02x v%04x i%04x l%u\n", + ctrl->bRequestType, ctrl->bRequest, + le16_to_cpu(ctrl->wValue), w_index, w_length); + return -EOPNOTSUPP; +} + + +/*-------------------------------------------------------------------------*/ + +/* All the following routines run in process context */ + + +/* Use this for bulk or interrupt transfers, not ep0 */ +static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, + struct usb_request *req, int *pbusy, + enum fsg_buffer_state *state) +{ + int rc; + + if (ep == fsg->bulk_in) + dump_msg(fsg, "bulk-in", req->buf, req->length); + + spin_lock_irq(&fsg->common->lock); + *pbusy = 1; + *state = BUF_STATE_BUSY; + spin_unlock_irq(&fsg->common->lock); + rc = usb_ep_queue(ep, req, GFP_KERNEL); + if (rc != 0) { + *pbusy = 0; + *state = BUF_STATE_EMPTY; + + /* We can't do much more than wait for a reset */ + + /* Note: currently the net2280 driver fails zero-length + * submissions if DMA is enabled. */ + if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && + req->length == 0)) + WARNING(fsg, "error in submission: %s --> %d\n", + ep->name, rc); + } +} + +#define START_TRANSFER_OR(common, ep_name, req, pbusy, state) \ + if (fsg_is_set(common)) \ + start_transfer((common)->fsg, (common)->fsg->ep_name, \ + req, pbusy, state); \ + else + +#define START_TRANSFER(common, ep_name, req, pbusy, state) \ + START_TRANSFER_OR(common, ep_name, req, pbusy, state) (void)0 + + + +static int sleep_thread(struct fsg_common *common) +{ + int rc = 0; + + /* Wait until a signal arrives or we are woken up */ + for (;;) { + try_to_freeze(); + set_current_state(TASK_INTERRUPTIBLE); + if (signal_pending(current)) { + rc = -EINTR; + break; + } + if (common->thread_wakeup_needed) + break; + schedule(); + } + __set_current_state(TASK_RUNNING); + common->thread_wakeup_needed = 0; + return rc; +} + + +/*-------------------------------------------------------------------------*/ + +static int do_read(struct fsg_common *common) +{ + struct fsg_lun *curlun = common->curlun; + u32 lba; + struct fsg_buffhd *bh; + int rc; + u32 amount_left; + loff_t file_offset, file_offset_tmp; + unsigned int amount; + unsigned int partial_page; + ssize_t nread; + + /* Get the starting Logical Block Address and check that it's + * not too big */ + if (common->cmnd[0] == SC_READ_6) + lba = get_unaligned_be24(&common->cmnd[1]); + else { + lba = get_unaligned_be32(&common->cmnd[2]); + + /* We allow DPO (Disable Page Out = don't save data in the + * cache) and FUA (Force Unit Access = don't read from the + * cache), but we don't implement them. */ + if ((common->cmnd[1] & ~0x18) != 0) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + } + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + file_offset = ((loff_t) lba) << 9; + + /* Carry out the file reads */ + amount_left = common->data_size_from_cmnd; + if (unlikely(amount_left == 0)) + return -EIO; /* No default reply */ + + for (;;) { + + /* Figure out how much we need to read: + * Try to read the remaining amount. + * But don't read more than the buffer size. + * And don't try to read past the end of the file. + * Finally, if we're not at a page boundary, don't read past + * the next page. + * If this means reading 0 then we were asked to read past + * the end of file. */ + amount = min(amount_left, FSG_BUFLEN); + amount = min((loff_t) amount, + curlun->file_length - file_offset); + partial_page = file_offset & (PAGE_CACHE_SIZE - 1); + if (partial_page > 0) + amount = min(amount, (unsigned int) PAGE_CACHE_SIZE - + partial_page); + + /* Wait for the next buffer to become available */ + bh = common->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { + rc = sleep_thread(common); + if (rc) + return rc; + } + + /* If we were asked to read past the end of file, + * end with an empty buffer. */ + if (amount == 0) { + curlun->sense_data = + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + curlun->sense_data_info = file_offset >> 9; + curlun->info_valid = 1; + bh->inreq->length = 0; + bh->state = BUF_STATE_FULL; + break; + } + + /* Perform the read */ + file_offset_tmp = file_offset; + nread = vfs_read(curlun->filp, + (char __user *) bh->buf, + amount, &file_offset_tmp); + VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, + (unsigned long long) file_offset, + (int) nread); + if (signal_pending(current)) + return -EINTR; + + if (nread < 0) { + LDBG(curlun, "error in file read: %d\n", + (int) nread); + nread = 0; + } else if (nread < amount) { + LDBG(curlun, "partial file read: %d/%u\n", + (int) nread, amount); + nread -= (nread & 511); /* Round down to a block */ + } + file_offset += nread; + amount_left -= nread; + common->residue -= nread; + bh->inreq->length = nread; + bh->state = BUF_STATE_FULL; + + /* If an error occurred, report it and its position */ + if (nread < amount) { + curlun->sense_data = SS_UNRECOVERED_READ_ERROR; + curlun->sense_data_info = file_offset >> 9; + curlun->info_valid = 1; + break; + } + + if (amount_left == 0) + break; /* No more left to read */ + + /* Send this buffer and go read some more */ + bh->inreq->zero = 0; + START_TRANSFER_OR(common, bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state) + /* Don't know what to do if + * common->fsg is NULL */ + return -EIO; + common->next_buffhd_to_fill = bh->next; + } + + return -EIO; /* No default reply */ +} + + +/*-------------------------------------------------------------------------*/ + +static int do_write(struct fsg_common *common) +{ + struct fsg_lun *curlun = common->curlun; + u32 lba; + struct fsg_buffhd *bh; + int get_some_more; + u32 amount_left_to_req, amount_left_to_write; + loff_t usb_offset, file_offset, file_offset_tmp; + unsigned int amount; + unsigned int partial_page; + ssize_t nwritten; + int rc; + + if (curlun->ro) { + curlun->sense_data = SS_WRITE_PROTECTED; + return -EINVAL; + } + spin_lock(&curlun->filp->f_lock); + curlun->filp->f_flags &= ~O_SYNC; /* Default is not to wait */ + spin_unlock(&curlun->filp->f_lock); + + /* Get the starting Logical Block Address and check that it's + * not too big */ + if (common->cmnd[0] == SC_WRITE_6) + lba = get_unaligned_be24(&common->cmnd[1]); + else { + lba = get_unaligned_be32(&common->cmnd[2]); + + /* We allow DPO (Disable Page Out = don't save data in the + * cache) and FUA (Force Unit Access = write directly to the + * medium). We don't implement DPO; we implement FUA by + * performing synchronous output. */ + if (common->cmnd[1] & ~0x18) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + if (common->cmnd[1] & 0x08) { /* FUA */ + spin_lock(&curlun->filp->f_lock); + curlun->filp->f_flags |= O_SYNC; + spin_unlock(&curlun->filp->f_lock); + } + } + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + + /* Carry out the file writes */ + get_some_more = 1; + file_offset = usb_offset = ((loff_t) lba) << 9; + amount_left_to_req = common->data_size_from_cmnd; + amount_left_to_write = common->data_size_from_cmnd; + + while (amount_left_to_write > 0) { + + /* Queue a request for more data from the host */ + bh = common->next_buffhd_to_fill; + if (bh->state == BUF_STATE_EMPTY && get_some_more) { + + /* Figure out how much we want to get: + * Try to get the remaining amount. + * But don't get more than the buffer size. + * And don't try to go past the end of the file. + * If we're not at a page boundary, + * don't go past the next page. + * If this means getting 0, then we were asked + * to write past the end of file. + * Finally, round down to a block boundary. */ + amount = min(amount_left_to_req, FSG_BUFLEN); + amount = min((loff_t) amount, curlun->file_length - + usb_offset); + partial_page = usb_offset & (PAGE_CACHE_SIZE - 1); + if (partial_page > 0) + amount = min(amount, + (unsigned int) PAGE_CACHE_SIZE - partial_page); + + if (amount == 0) { + get_some_more = 0; + curlun->sense_data = + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + curlun->sense_data_info = usb_offset >> 9; + curlun->info_valid = 1; + continue; + } + amount -= (amount & 511); + if (amount == 0) { + + /* Why were we were asked to transfer a + * partial block? */ + get_some_more = 0; + continue; + } + + /* Get the next buffer */ + usb_offset += amount; + common->usb_amount_left -= amount; + amount_left_to_req -= amount; + if (amount_left_to_req == 0) + get_some_more = 0; + + /* amount is always divisible by 512, hence by + * the bulk-out maxpacket size */ + bh->outreq->length = amount; + bh->bulk_out_intended_length = amount; + bh->outreq->short_not_ok = 1; + START_TRANSFER_OR(common, bulk_out, bh->outreq, + &bh->outreq_busy, &bh->state) + /* Don't know what to do if + * common->fsg is NULL */ + return -EIO; + common->next_buffhd_to_fill = bh->next; + continue; + } + + /* Write the received data to the backing file */ + bh = common->next_buffhd_to_drain; + if (bh->state == BUF_STATE_EMPTY && !get_some_more) + break; /* We stopped early */ + if (bh->state == BUF_STATE_FULL) { + smp_rmb(); + common->next_buffhd_to_drain = bh->next; + bh->state = BUF_STATE_EMPTY; + + /* Did something go wrong with the transfer? */ + if (bh->outreq->status != 0) { + curlun->sense_data = SS_COMMUNICATION_FAILURE; + curlun->sense_data_info = file_offset >> 9; + curlun->info_valid = 1; + break; + } + + amount = bh->outreq->actual; + if (curlun->file_length - file_offset < amount) { + LERROR(curlun, + "write %u @ %llu beyond end %llu\n", + amount, (unsigned long long) file_offset, + (unsigned long long) curlun->file_length); + amount = curlun->file_length - file_offset; + } + + /* Perform the write */ + file_offset_tmp = file_offset; + nwritten = vfs_write(curlun->filp, + (char __user *) bh->buf, + amount, &file_offset_tmp); + VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, + (unsigned long long) file_offset, + (int) nwritten); + if (signal_pending(current)) + return -EINTR; /* Interrupted! */ + + if (nwritten < 0) { + LDBG(curlun, "error in file write: %d\n", + (int) nwritten); + nwritten = 0; + } else if (nwritten < amount) { + LDBG(curlun, "partial file write: %d/%u\n", + (int) nwritten, amount); + nwritten -= (nwritten & 511); + /* Round down to a block */ + } + file_offset += nwritten; + amount_left_to_write -= nwritten; + common->residue -= nwritten; + + /* If an error occurred, report it and its position */ + if (nwritten < amount) { + curlun->sense_data = SS_WRITE_ERROR; + curlun->sense_data_info = file_offset >> 9; + curlun->info_valid = 1; + break; + } + + /* Did the host decide to stop early? */ + if (bh->outreq->actual != bh->outreq->length) { + common->short_packet_received = 1; + break; + } + continue; + } + + /* Wait for something to happen */ + rc = sleep_thread(common); + if (rc) + return rc; + } + + return -EIO; /* No default reply */ +} + + +/*-------------------------------------------------------------------------*/ + +static int do_synchronize_cache(struct fsg_common *common) +{ + struct fsg_lun *curlun = common->curlun; + int rc; + + /* We ignore the requested LBA and write out all file's + * dirty data buffers. */ + rc = fsg_lun_fsync_sub(curlun); + if (rc) + curlun->sense_data = SS_WRITE_ERROR; + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +static void invalidate_sub(struct fsg_lun *curlun) +{ + struct file *filp = curlun->filp; + struct inode *inode = filp->f_path.dentry->d_inode; + unsigned long rc; + + rc = invalidate_mapping_pages(inode->i_mapping, 0, -1); + VLDBG(curlun, "invalidate_inode_pages -> %ld\n", rc); +} + +static int do_verify(struct fsg_common *common) +{ + struct fsg_lun *curlun = common->curlun; + u32 lba; + u32 verification_length; + struct fsg_buffhd *bh = common->next_buffhd_to_fill; + loff_t file_offset, file_offset_tmp; + u32 amount_left; + unsigned int amount; + ssize_t nread; + + /* Get the starting Logical Block Address and check that it's + * not too big */ + lba = get_unaligned_be32(&common->cmnd[2]); + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + + /* We allow DPO (Disable Page Out = don't save data in the + * cache) but we don't implement it. */ + if (common->cmnd[1] & ~0x10) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + verification_length = get_unaligned_be16(&common->cmnd[7]); + if (unlikely(verification_length == 0)) + return -EIO; /* No default reply */ + + /* Prepare to carry out the file verify */ + amount_left = verification_length << 9; + file_offset = ((loff_t) lba) << 9; + + /* Write out all the dirty buffers before invalidating them */ + fsg_lun_fsync_sub(curlun); + if (signal_pending(current)) + return -EINTR; + + invalidate_sub(curlun); + if (signal_pending(current)) + return -EINTR; + + /* Just try to read the requested blocks */ + while (amount_left > 0) { + + /* Figure out how much we need to read: + * Try to read the remaining amount, but not more than + * the buffer size. + * And don't try to read past the end of the file. + * If this means reading 0 then we were asked to read + * past the end of file. */ + amount = min(amount_left, FSG_BUFLEN); + amount = min((loff_t) amount, + curlun->file_length - file_offset); + if (amount == 0) { + curlun->sense_data = + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + curlun->sense_data_info = file_offset >> 9; + curlun->info_valid = 1; + break; + } + + /* Perform the read */ + file_offset_tmp = file_offset; + nread = vfs_read(curlun->filp, + (char __user *) bh->buf, + amount, &file_offset_tmp); + VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, + (unsigned long long) file_offset, + (int) nread); + if (signal_pending(current)) + return -EINTR; + + if (nread < 0) { + LDBG(curlun, "error in file verify: %d\n", + (int) nread); + nread = 0; + } else if (nread < amount) { + LDBG(curlun, "partial file verify: %d/%u\n", + (int) nread, amount); + nread -= (nread & 511); /* Round down to a sector */ + } + if (nread == 0) { + curlun->sense_data = SS_UNRECOVERED_READ_ERROR; + curlun->sense_data_info = file_offset >> 9; + curlun->info_valid = 1; + break; + } + file_offset += nread; + amount_left -= nread; + } + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + u8 *buf = (u8 *) bh->buf; + + if (!curlun) { /* Unsupported LUNs are okay */ + common->bad_lun_okay = 1; + memset(buf, 0, 36); + buf[0] = 0x7f; /* Unsupported, no device-type */ + buf[4] = 31; /* Additional length */ + return 36; + } + + buf[0] = curlun->cdrom ? TYPE_CDROM : TYPE_DISK; + buf[1] = curlun->removable ? 0x80 : 0; + buf[2] = 2; /* ANSI SCSI level 2 */ + buf[3] = 2; /* SCSI-2 INQUIRY data format */ + buf[4] = 31; /* Additional length */ + buf[5] = 0; /* No special options */ + buf[6] = 0; + buf[7] = 0; + memcpy(buf + 8, common->inquiry_string, sizeof common->inquiry_string); + return 36; +} + + +static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + u8 *buf = (u8 *) bh->buf; + u32 sd, sdinfo; + int valid; + + /* + * From the SCSI-2 spec., section 7.9 (Unit attention condition): + * + * If a REQUEST SENSE command is received from an initiator + * with a pending unit attention condition (before the target + * generates the contingent allegiance condition), then the + * target shall either: + * a) report any pending sense data and preserve the unit + * attention condition on the logical unit, or, + * b) report the unit attention condition, may discard any + * pending sense data, and clear the unit attention + * condition on the logical unit for that initiator. + * + * FSG normally uses option a); enable this code to use option b). + */ +#if 0 + if (curlun && curlun->unit_attention_data != SS_NO_SENSE) { + curlun->sense_data = curlun->unit_attention_data; + curlun->unit_attention_data = SS_NO_SENSE; + } +#endif + + if (!curlun) { /* Unsupported LUNs are okay */ + common->bad_lun_okay = 1; + sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; + sdinfo = 0; + valid = 0; + } else { + sd = curlun->sense_data; + sdinfo = curlun->sense_data_info; + valid = curlun->info_valid << 7; + curlun->sense_data = SS_NO_SENSE; + curlun->sense_data_info = 0; + curlun->info_valid = 0; + } + + memset(buf, 0, 18); + buf[0] = valid | 0x70; /* Valid, current error */ + buf[2] = SK(sd); + put_unaligned_be32(sdinfo, &buf[3]); /* Sense information */ + buf[7] = 18 - 8; /* Additional sense length */ + buf[12] = ASC(sd); + buf[13] = ASCQ(sd); + return 18; +} + + +static int do_read_capacity(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + u32 lba = get_unaligned_be32(&common->cmnd[2]); + int pmi = common->cmnd[8]; + u8 *buf = (u8 *) bh->buf; + + /* Check the PMI and LBA fields */ + if (pmi > 1 || (pmi == 0 && lba != 0)) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); + /* Max logical block */ + put_unaligned_be32(512, &buf[4]); /* Block length */ + return 8; +} + + +static int do_read_header(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + int msf = common->cmnd[1] & 0x02; + u32 lba = get_unaligned_be32(&common->cmnd[2]); + u8 *buf = (u8 *) bh->buf; + + if (common->cmnd[1] & ~0x02) { /* Mask away MSF */ + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + + memset(buf, 0, 8); + buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */ + store_cdrom_address(&buf[4], msf, lba); + return 8; +} + + +static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + int msf = common->cmnd[1] & 0x02; + int start_track = common->cmnd[6]; + u8 *buf = (u8 *) bh->buf; + + if ((common->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ + start_track > 1) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + memset(buf, 0, 20); + buf[1] = (20-2); /* TOC data length */ + buf[2] = 1; /* First track number */ + buf[3] = 1; /* Last track number */ + buf[5] = 0x16; /* Data track, copying allowed */ + buf[6] = 0x01; /* Only track is number 1 */ + store_cdrom_address(&buf[8], msf, 0); + + buf[13] = 0x16; /* Lead-out track is data */ + buf[14] = 0xAA; /* Lead-out track number */ + store_cdrom_address(&buf[16], msf, curlun->num_sectors); + return 20; +} + + +static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + int mscmnd = common->cmnd[0]; + u8 *buf = (u8 *) bh->buf; + u8 *buf0 = buf; + int pc, page_code; + int changeable_values, all_pages; + int valid_page = 0; + int len, limit; + + if ((common->cmnd[1] & ~0x08) != 0) { /* Mask away DBD */ + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + pc = common->cmnd[2] >> 6; + page_code = common->cmnd[2] & 0x3f; + if (pc == 3) { + curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; + return -EINVAL; + } + changeable_values = (pc == 1); + all_pages = (page_code == 0x3f); + + /* Write the mode parameter header. Fixed values are: default + * medium type, no cache control (DPOFUA), and no block descriptors. + * The only variable value is the WriteProtect bit. We will fill in + * the mode data length later. */ + memset(buf, 0, 8); + if (mscmnd == SC_MODE_SENSE_6) { + buf[2] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ + buf += 4; + limit = 255; + } else { /* SC_MODE_SENSE_10 */ + buf[3] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ + buf += 8; + limit = 65535; /* Should really be FSG_BUFLEN */ + } + + /* No block descriptors */ + + /* The mode pages, in numerical order. The only page we support + * is the Caching page. */ + if (page_code == 0x08 || all_pages) { + valid_page = 1; + buf[0] = 0x08; /* Page code */ + buf[1] = 10; /* Page length */ + memset(buf+2, 0, 10); /* None of the fields are changeable */ + + if (!changeable_values) { + buf[2] = 0x04; /* Write cache enable, */ + /* Read cache not disabled */ + /* No cache retention priorities */ + put_unaligned_be16(0xffff, &buf[4]); + /* Don't disable prefetch */ + /* Minimum prefetch = 0 */ + put_unaligned_be16(0xffff, &buf[8]); + /* Maximum prefetch */ + put_unaligned_be16(0xffff, &buf[10]); + /* Maximum prefetch ceiling */ + } + buf += 12; + } + + /* Check that a valid page was requested and the mode data length + * isn't too long. */ + len = buf - buf0; + if (!valid_page || len > limit) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + /* Store the mode data length */ + if (mscmnd == SC_MODE_SENSE_6) + buf0[0] = len - 1; + else + put_unaligned_be16(len - 2, buf0); + return len; +} + + +static int do_start_stop(struct fsg_common *common) +{ + if (!common->curlun) { + return -EINVAL; + } else if (!common->curlun->removable) { + common->curlun->sense_data = SS_INVALID_COMMAND; + return -EINVAL; + } + return 0; +} + + +static int do_prevent_allow(struct fsg_common *common) +{ + struct fsg_lun *curlun = common->curlun; + int prevent; + + if (!common->curlun) { + return -EINVAL; + } else if (!common->curlun->removable) { + common->curlun->sense_data = SS_INVALID_COMMAND; + return -EINVAL; + } + + prevent = common->cmnd[4] & 0x01; + if ((common->cmnd[4] & ~0x01) != 0) { /* Mask away Prevent */ + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + if (curlun->prevent_medium_removal && !prevent) + fsg_lun_fsync_sub(curlun); + curlun->prevent_medium_removal = prevent; + return 0; +} + + +static int do_read_format_capacities(struct fsg_common *common, + struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + u8 *buf = (u8 *) bh->buf; + + buf[0] = buf[1] = buf[2] = 0; + buf[3] = 8; /* Only the Current/Maximum Capacity Descriptor */ + buf += 4; + + put_unaligned_be32(curlun->num_sectors, &buf[0]); + /* Number of blocks */ + put_unaligned_be32(512, &buf[4]); /* Block length */ + buf[4] = 0x02; /* Current capacity */ + return 12; +} + + +static int do_mode_select(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + + /* We don't support MODE SELECT */ + if (curlun) + curlun->sense_data = SS_INVALID_COMMAND; + return -EINVAL; +} + + +/*-------------------------------------------------------------------------*/ + +static int halt_bulk_in_endpoint(struct fsg_dev *fsg) +{ + int rc; + + rc = fsg_set_halt(fsg, fsg->bulk_in); + if (rc == -EAGAIN) + VDBG(fsg, "delayed bulk-in endpoint halt\n"); + while (rc != 0) { + if (rc != -EAGAIN) { + WARNING(fsg, "usb_ep_set_halt -> %d\n", rc); + rc = 0; + break; + } + + /* Wait for a short time and then try again */ + if (msleep_interruptible(100) != 0) + return -EINTR; + rc = usb_ep_set_halt(fsg->bulk_in); + } + return rc; +} + +static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) +{ + int rc; + + DBG(fsg, "bulk-in set wedge\n"); + rc = usb_ep_set_wedge(fsg->bulk_in); + if (rc == -EAGAIN) + VDBG(fsg, "delayed bulk-in endpoint wedge\n"); + while (rc != 0) { + if (rc != -EAGAIN) { + WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc); + rc = 0; + break; + } + + /* Wait for a short time and then try again */ + if (msleep_interruptible(100) != 0) + return -EINTR; + rc = usb_ep_set_wedge(fsg->bulk_in); + } + return rc; +} + +static int pad_with_zeros(struct fsg_dev *fsg) +{ + struct fsg_buffhd *bh = fsg->common->next_buffhd_to_fill; + u32 nkeep = bh->inreq->length; + u32 nsend; + int rc; + + bh->state = BUF_STATE_EMPTY; /* For the first iteration */ + fsg->common->usb_amount_left = nkeep + fsg->common->residue; + while (fsg->common->usb_amount_left > 0) { + + /* Wait for the next buffer to be free */ + while (bh->state != BUF_STATE_EMPTY) { + rc = sleep_thread(fsg->common); + if (rc) + return rc; + } + + nsend = min(fsg->common->usb_amount_left, FSG_BUFLEN); + memset(bh->buf + nkeep, 0, nsend - nkeep); + bh->inreq->length = nsend; + bh->inreq->zero = 0; + start_transfer(fsg, fsg->bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state); + bh = fsg->common->next_buffhd_to_fill = bh->next; + fsg->common->usb_amount_left -= nsend; + nkeep = 0; + } + return 0; +} + +static int throw_away_data(struct fsg_common *common) +{ + struct fsg_buffhd *bh; + u32 amount; + int rc; + + for (bh = common->next_buffhd_to_drain; + bh->state != BUF_STATE_EMPTY || common->usb_amount_left > 0; + bh = common->next_buffhd_to_drain) { + + /* Throw away the data in a filled buffer */ + if (bh->state == BUF_STATE_FULL) { + smp_rmb(); + bh->state = BUF_STATE_EMPTY; + common->next_buffhd_to_drain = bh->next; + + /* A short packet or an error ends everything */ + if (bh->outreq->actual != bh->outreq->length || + bh->outreq->status != 0) { + raise_exception(common, + FSG_STATE_ABORT_BULK_OUT); + return -EINTR; + } + continue; + } + + /* Try to submit another request if we need one */ + bh = common->next_buffhd_to_fill; + if (bh->state == BUF_STATE_EMPTY + && common->usb_amount_left > 0) { + amount = min(common->usb_amount_left, FSG_BUFLEN); + + /* amount is always divisible by 512, hence by + * the bulk-out maxpacket size */ + bh->outreq->length = amount; + bh->bulk_out_intended_length = amount; + bh->outreq->short_not_ok = 1; + START_TRANSFER_OR(common, bulk_out, bh->outreq, + &bh->outreq_busy, &bh->state) + /* Don't know what to do if + * common->fsg is NULL */ + return -EIO; + common->next_buffhd_to_fill = bh->next; + common->usb_amount_left -= amount; + continue; + } + + /* Otherwise wait for something to happen */ + rc = sleep_thread(common); + if (rc) + return rc; + } + return 0; +} + + +static int finish_reply(struct fsg_common *common) +{ + struct fsg_buffhd *bh = common->next_buffhd_to_fill; + int rc = 0; + + switch (common->data_dir) { + case DATA_DIR_NONE: + break; /* Nothing to send */ + + /* If we don't know whether the host wants to read or write, + * this must be CB or CBI with an unknown command. We mustn't + * try to send or receive any data. So stall both bulk pipes + * if we can and wait for a reset. */ + case DATA_DIR_UNKNOWN: + if (!common->can_stall) { + /* Nothing */ + } else if (fsg_is_set(common)) { + fsg_set_halt(common->fsg, common->fsg->bulk_out); + rc = halt_bulk_in_endpoint(common->fsg); + } else { + /* Don't know what to do if common->fsg is NULL */ + rc = -EIO; + } + break; + + /* All but the last buffer of data must have already been sent */ + case DATA_DIR_TO_HOST: + if (common->data_size == 0) { + /* Nothing to send */ + + /* If there's no residue, simply send the last buffer */ + } else if (common->residue == 0) { + bh->inreq->zero = 0; + START_TRANSFER_OR(common, bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state) + return -EIO; + common->next_buffhd_to_fill = bh->next; + + /* For Bulk-only, if we're allowed to stall then send the + * short packet and halt the bulk-in endpoint. If we can't + * stall, pad out the remaining data with 0's. */ + } else if (common->can_stall) { + bh->inreq->zero = 1; + START_TRANSFER_OR(common, bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state) + /* Don't know what to do if + * common->fsg is NULL */ + rc = -EIO; + common->next_buffhd_to_fill = bh->next; + if (common->fsg) + rc = halt_bulk_in_endpoint(common->fsg); + } else if (fsg_is_set(common)) { + rc = pad_with_zeros(common->fsg); + } else { + /* Don't know what to do if common->fsg is NULL */ + rc = -EIO; + } + break; + + /* We have processed all we want from the data the host has sent. + * There may still be outstanding bulk-out requests. */ + case DATA_DIR_FROM_HOST: + if (common->residue == 0) { + /* Nothing to receive */ + + /* Did the host stop sending unexpectedly early? */ + } else if (common->short_packet_received) { + raise_exception(common, FSG_STATE_ABORT_BULK_OUT); + rc = -EINTR; + + /* We haven't processed all the incoming data. Even though + * we may be allowed to stall, doing so would cause a race. + * The controller may already have ACK'ed all the remaining + * bulk-out packets, in which case the host wouldn't see a + * STALL. Not realizing the endpoint was halted, it wouldn't + * clear the halt -- leading to problems later on. */ +#if 0 + } else if (common->can_stall) { + if (fsg_is_set(common)) + fsg_set_halt(common->fsg, + common->fsg->bulk_out); + raise_exception(common, FSG_STATE_ABORT_BULK_OUT); + rc = -EINTR; +#endif + + /* We can't stall. Read in the excess data and throw it + * all away. */ + } else { + rc = throw_away_data(common); + } + break; + } + return rc; +} + + +static int send_status(struct fsg_common *common) +{ + struct fsg_lun *curlun = common->curlun; + struct fsg_buffhd *bh; + struct bulk_cs_wrap *csw; + int rc; + u8 status = USB_STATUS_PASS; + u32 sd, sdinfo = 0; + + /* Wait for the next buffer to become available */ + bh = common->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { + rc = sleep_thread(common); + if (rc) + return rc; + } + + if (curlun) { + sd = curlun->sense_data; + sdinfo = curlun->sense_data_info; + } else if (common->bad_lun_okay) + sd = SS_NO_SENSE; + else + sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; + + if (common->phase_error) { + DBG(common, "sending phase-error status\n"); + status = USB_STATUS_PHASE_ERROR; + sd = SS_INVALID_COMMAND; + } else if (sd != SS_NO_SENSE) { + DBG(common, "sending command-failure status\n"); + status = USB_STATUS_FAIL; + VDBG(common, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" + " info x%x\n", + SK(sd), ASC(sd), ASCQ(sd), sdinfo); + } + + /* Store and send the Bulk-only CSW */ + csw = (void *)bh->buf; + + csw->Signature = cpu_to_le32(USB_BULK_CS_SIG); + csw->Tag = common->tag; + csw->Residue = cpu_to_le32(common->residue); + csw->Status = status; + + bh->inreq->length = USB_BULK_CS_WRAP_LEN; + bh->inreq->zero = 0; + START_TRANSFER_OR(common, bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state) + /* Don't know what to do if common->fsg is NULL */ + return -EIO; + + common->next_buffhd_to_fill = bh->next; + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +/* Check whether the command is properly formed and whether its data size + * and direction agree with the values we already have. */ +static int check_command(struct fsg_common *common, int cmnd_size, + enum data_direction data_dir, unsigned int mask, + int needs_medium, const char *name) +{ + int i; + int lun = common->cmnd[1] >> 5; + static const char dirletter[4] = {'u', 'o', 'i', 'n'}; + char hdlen[20]; + struct fsg_lun *curlun; + + hdlen[0] = 0; + if (common->data_dir != DATA_DIR_UNKNOWN) + sprintf(hdlen, ", H%c=%u", dirletter[(int) common->data_dir], + common->data_size); + VDBG(common, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n", + name, cmnd_size, dirletter[(int) data_dir], + common->data_size_from_cmnd, common->cmnd_size, hdlen); + + /* We can't reply at all until we know the correct data direction + * and size. */ + if (common->data_size_from_cmnd == 0) + data_dir = DATA_DIR_NONE; + if (common->data_size < common->data_size_from_cmnd) { + /* Host data size < Device data size is a phase error. + * Carry out the command, but only transfer as much as + * we are allowed. */ + common->data_size_from_cmnd = common->data_size; + common->phase_error = 1; + } + common->residue = common->data_size; + common->usb_amount_left = common->data_size; + + /* Conflicting data directions is a phase error */ + if (common->data_dir != data_dir + && common->data_size_from_cmnd > 0) { + common->phase_error = 1; + return -EINVAL; + } + + /* Verify the length of the command itself */ + if (cmnd_size != common->cmnd_size) { + + /* Special case workaround: There are plenty of buggy SCSI + * implementations. Many have issues with cbw->Length + * field passing a wrong command size. For those cases we + * always try to work around the problem by using the length + * sent by the host side provided it is at least as large + * as the correct command length. + * Examples of such cases would be MS-Windows, which issues + * REQUEST SENSE with cbw->Length == 12 where it should + * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and + * REQUEST SENSE with cbw->Length == 10 where it should + * be 6 as well. + */ + if (cmnd_size <= common->cmnd_size) { + DBG(common, "%s is buggy! Expected length %d " + "but we got %d\n", name, + cmnd_size, common->cmnd_size); + cmnd_size = common->cmnd_size; + } else { + common->phase_error = 1; + return -EINVAL; + } + } + + /* Check that the LUN values are consistent */ + if (common->lun != lun) + DBG(common, "using LUN %d from CBW, not LUN %d from CDB\n", + common->lun, lun); + + /* Check the LUN */ + if (common->lun >= 0 && common->lun < common->nluns) { + curlun = &common->luns[common->lun]; + common->curlun = curlun; + if (common->cmnd[0] != SC_REQUEST_SENSE) { + curlun->sense_data = SS_NO_SENSE; + curlun->sense_data_info = 0; + curlun->info_valid = 0; + } + } else { + common->curlun = NULL; + curlun = NULL; + common->bad_lun_okay = 0; + + /* INQUIRY and REQUEST SENSE commands are explicitly allowed + * to use unsupported LUNs; all others may not. */ + if (common->cmnd[0] != SC_INQUIRY && + common->cmnd[0] != SC_REQUEST_SENSE) { + DBG(common, "unsupported LUN %d\n", common->lun); + return -EINVAL; + } + } + + /* If a unit attention condition exists, only INQUIRY and + * REQUEST SENSE commands are allowed; anything else must fail. */ + if (curlun && curlun->unit_attention_data != SS_NO_SENSE && + common->cmnd[0] != SC_INQUIRY && + common->cmnd[0] != SC_REQUEST_SENSE) { + curlun->sense_data = curlun->unit_attention_data; + curlun->unit_attention_data = SS_NO_SENSE; + return -EINVAL; + } + + /* Check that only command bytes listed in the mask are non-zero */ + common->cmnd[1] &= 0x1f; /* Mask away the LUN */ + for (i = 1; i < cmnd_size; ++i) { + if (common->cmnd[i] && !(mask & (1 << i))) { + if (curlun) + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + } + + /* If the medium isn't mounted and the command needs to access + * it, return an error. */ + if (curlun && !fsg_lun_is_open(curlun) && needs_medium) { + curlun->sense_data = SS_MEDIUM_NOT_PRESENT; + return -EINVAL; + } + + return 0; +} + + +static int do_scsi_command(struct fsg_common *common) +{ + struct fsg_buffhd *bh; + int rc; + int reply = -EINVAL; + int i; + static char unknown[16]; + + dump_cdb(common); + + /* Wait for the next buffer to become available for data or status */ + bh = common->next_buffhd_to_fill; + common->next_buffhd_to_drain = bh; + while (bh->state != BUF_STATE_EMPTY) { + rc = sleep_thread(common); + if (rc) + return rc; + } + common->phase_error = 0; + common->short_packet_received = 0; + + down_read(&common->filesem); /* We're using the backing file */ + switch (common->cmnd[0]) { + + case SC_INQUIRY: + common->data_size_from_cmnd = common->cmnd[4]; + reply = check_command(common, 6, DATA_DIR_TO_HOST, + (1<<4), 0, + "INQUIRY"); + if (reply == 0) + reply = do_inquiry(common, bh); + break; + + case SC_MODE_SELECT_6: + common->data_size_from_cmnd = common->cmnd[4]; + reply = check_command(common, 6, DATA_DIR_FROM_HOST, + (1<<1) | (1<<4), 0, + "MODE SELECT(6)"); + if (reply == 0) + reply = do_mode_select(common, bh); + break; + + case SC_MODE_SELECT_10: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_FROM_HOST, + (1<<1) | (3<<7), 0, + "MODE SELECT(10)"); + if (reply == 0) + reply = do_mode_select(common, bh); + break; + + case SC_MODE_SENSE_6: + common->data_size_from_cmnd = common->cmnd[4]; + reply = check_command(common, 6, DATA_DIR_TO_HOST, + (1<<1) | (1<<2) | (1<<4), 0, + "MODE SENSE(6)"); + if (reply == 0) + reply = do_mode_sense(common, bh); + break; + + case SC_MODE_SENSE_10: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (1<<1) | (1<<2) | (3<<7), 0, + "MODE SENSE(10)"); + if (reply == 0) + reply = do_mode_sense(common, bh); + break; + + case SC_PREVENT_ALLOW_MEDIUM_REMOVAL: + common->data_size_from_cmnd = 0; + reply = check_command(common, 6, DATA_DIR_NONE, + (1<<4), 0, + "PREVENT-ALLOW MEDIUM REMOVAL"); + if (reply == 0) + reply = do_prevent_allow(common); + break; + + case SC_READ_6: + i = common->cmnd[4]; + common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; + reply = check_command(common, 6, DATA_DIR_TO_HOST, + (7<<1) | (1<<4), 1, + "READ(6)"); + if (reply == 0) + reply = do_read(common); + break; + + case SC_READ_10: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]) << 9; + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (1<<1) | (0xf<<2) | (3<<7), 1, + "READ(10)"); + if (reply == 0) + reply = do_read(common); + break; + + case SC_READ_12: + common->data_size_from_cmnd = + get_unaligned_be32(&common->cmnd[6]) << 9; + reply = check_command(common, 12, DATA_DIR_TO_HOST, + (1<<1) | (0xf<<2) | (0xf<<6), 1, + "READ(12)"); + if (reply == 0) + reply = do_read(common); + break; + + case SC_READ_CAPACITY: + common->data_size_from_cmnd = 8; + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (0xf<<2) | (1<<8), 1, + "READ CAPACITY"); + if (reply == 0) + reply = do_read_capacity(common, bh); + break; + + case SC_READ_HEADER: + if (!common->curlun || !common->curlun->cdrom) + goto unknown_cmnd; + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (3<<7) | (0x1f<<1), 1, + "READ HEADER"); + if (reply == 0) + reply = do_read_header(common, bh); + break; + + case SC_READ_TOC: + if (!common->curlun || !common->curlun->cdrom) + goto unknown_cmnd; + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (7<<6) | (1<<1), 1, + "READ TOC"); + if (reply == 0) + reply = do_read_toc(common, bh); + break; + + case SC_READ_FORMAT_CAPACITIES: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (3<<7), 1, + "READ FORMAT CAPACITIES"); + if (reply == 0) + reply = do_read_format_capacities(common, bh); + break; + + case SC_REQUEST_SENSE: + common->data_size_from_cmnd = common->cmnd[4]; + reply = check_command(common, 6, DATA_DIR_TO_HOST, + (1<<4), 0, + "REQUEST SENSE"); + if (reply == 0) + reply = do_request_sense(common, bh); + break; + + case SC_START_STOP_UNIT: + common->data_size_from_cmnd = 0; + reply = check_command(common, 6, DATA_DIR_NONE, + (1<<1) | (1<<4), 0, + "START-STOP UNIT"); + if (reply == 0) + reply = do_start_stop(common); + break; + + case SC_SYNCHRONIZE_CACHE: + common->data_size_from_cmnd = 0; + reply = check_command(common, 10, DATA_DIR_NONE, + (0xf<<2) | (3<<7), 1, + "SYNCHRONIZE CACHE"); + if (reply == 0) + reply = do_synchronize_cache(common); + break; + + case SC_TEST_UNIT_READY: + common->data_size_from_cmnd = 0; + reply = check_command(common, 6, DATA_DIR_NONE, + 0, 1, + "TEST UNIT READY"); + break; + + /* Although optional, this command is used by MS-Windows. We + * support a minimal version: BytChk must be 0. */ + case SC_VERIFY: + common->data_size_from_cmnd = 0; + reply = check_command(common, 10, DATA_DIR_NONE, + (1<<1) | (0xf<<2) | (3<<7), 1, + "VERIFY"); + if (reply == 0) + reply = do_verify(common); + break; + + case SC_WRITE_6: + i = common->cmnd[4]; + common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; + reply = check_command(common, 6, DATA_DIR_FROM_HOST, + (7<<1) | (1<<4), 1, + "WRITE(6)"); + if (reply == 0) + reply = do_write(common); + break; + + case SC_WRITE_10: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]) << 9; + reply = check_command(common, 10, DATA_DIR_FROM_HOST, + (1<<1) | (0xf<<2) | (3<<7), 1, + "WRITE(10)"); + if (reply == 0) + reply = do_write(common); + break; + + case SC_WRITE_12: + common->data_size_from_cmnd = + get_unaligned_be32(&common->cmnd[6]) << 9; + reply = check_command(common, 12, DATA_DIR_FROM_HOST, + (1<<1) | (0xf<<2) | (0xf<<6), 1, + "WRITE(12)"); + if (reply == 0) + reply = do_write(common); + break; + + /* Some mandatory commands that we recognize but don't implement. + * They don't mean much in this setting. It's left as an exercise + * for anyone interested to implement RESERVE and RELEASE in terms + * of Posix locks. */ + case SC_FORMAT_UNIT: + case SC_RELEASE: + case SC_RESERVE: + case SC_SEND_DIAGNOSTIC: + /* Fall through */ + + default: +unknown_cmnd: + common->data_size_from_cmnd = 0; + sprintf(unknown, "Unknown x%02x", common->cmnd[0]); + reply = check_command(common, common->cmnd_size, + DATA_DIR_UNKNOWN, 0xff, 0, unknown); + if (reply == 0) { + common->curlun->sense_data = SS_INVALID_COMMAND; + reply = -EINVAL; + } + break; + } + up_read(&common->filesem); + + if (reply == -EINTR || signal_pending(current)) + return -EINTR; + + /* Set up the single reply buffer for finish_reply() */ + if (reply == -EINVAL) + reply = 0; /* Error reply length */ + if (reply >= 0 && common->data_dir == DATA_DIR_TO_HOST) { + reply = min((u32) reply, common->data_size_from_cmnd); + bh->inreq->length = reply; + bh->state = BUF_STATE_FULL; + common->residue -= reply; + } /* Otherwise it's already set */ + + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) +{ + struct usb_request *req = bh->outreq; + struct fsg_bulk_cb_wrap *cbw = req->buf; + struct fsg_common *common = fsg->common; + + /* Was this a real packet? Should it be ignored? */ + if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) + return -EINVAL; + + /* Is the CBW valid? */ + if (req->actual != USB_BULK_CB_WRAP_LEN || + cbw->Signature != cpu_to_le32( + USB_BULK_CB_SIG)) { + DBG(fsg, "invalid CBW: len %u sig 0x%x\n", + req->actual, + le32_to_cpu(cbw->Signature)); + + /* The Bulk-only spec says we MUST stall the IN endpoint + * (6.6.1), so it's unavoidable. It also says we must + * retain this state until the next reset, but there's + * no way to tell the controller driver it should ignore + * Clear-Feature(HALT) requests. + * + * We aren't required to halt the OUT endpoint; instead + * we can simply accept and discard any data received + * until the next reset. */ + wedge_bulk_in_endpoint(fsg); + set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); + return -EINVAL; + } + + /* Is the CBW meaningful? */ + if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || + cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { + DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " + "cmdlen %u\n", + cbw->Lun, cbw->Flags, cbw->Length); + + /* We can do anything we want here, so let's stall the + * bulk pipes if we are allowed to. */ + if (common->can_stall) { + fsg_set_halt(fsg, fsg->bulk_out); + halt_bulk_in_endpoint(fsg); + } + return -EINVAL; + } + + /* Save the command for later */ + common->cmnd_size = cbw->Length; + memcpy(common->cmnd, cbw->CDB, common->cmnd_size); + if (cbw->Flags & USB_BULK_IN_FLAG) + common->data_dir = DATA_DIR_TO_HOST; + else + common->data_dir = DATA_DIR_FROM_HOST; + common->data_size = le32_to_cpu(cbw->DataTransferLength); + if (common->data_size == 0) + common->data_dir = DATA_DIR_NONE; + common->lun = cbw->Lun; + common->tag = cbw->Tag; + return 0; +} + + +static int get_next_command(struct fsg_common *common) +{ + struct fsg_buffhd *bh; + int rc = 0; + + /* Wait for the next buffer to become available */ + bh = common->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { + rc = sleep_thread(common); + if (rc) + return rc; + } + + /* Queue a request to read a Bulk-only CBW */ + set_bulk_out_req_length(common, bh, USB_BULK_CB_WRAP_LEN); + bh->outreq->short_not_ok = 1; + START_TRANSFER_OR(common, bulk_out, bh->outreq, + &bh->outreq_busy, &bh->state) + /* Don't know what to do if common->fsg is NULL */ + return -EIO; + + /* We will drain the buffer in software, which means we + * can reuse it for the next filling. No need to advance + * next_buffhd_to_fill. */ + + /* Wait for the CBW to arrive */ + while (bh->state != BUF_STATE_FULL) { + rc = sleep_thread(common); + if (rc) + return rc; + } + smp_rmb(); + rc = fsg_is_set(common) ? received_cbw(common->fsg, bh) : -EIO; + bh->state = BUF_STATE_EMPTY; + + return rc; +} + + +/*-------------------------------------------------------------------------*/ + +static int enable_endpoint(struct fsg_common *common, struct usb_ep *ep, + const struct usb_endpoint_descriptor *d) +{ + int rc; + + ep->driver_data = common; + rc = usb_ep_enable(ep, d); + if (rc) + ERROR(common, "can't enable %s, result %d\n", ep->name, rc); + return rc; +} + +static int alloc_request(struct fsg_common *common, struct usb_ep *ep, + struct usb_request **preq) +{ + *preq = usb_ep_alloc_request(ep, GFP_ATOMIC); + if (*preq) + return 0; + ERROR(common, "can't allocate request for %s\n", ep->name); + return -ENOMEM; +} + +/* + * Reset interface setting and re-init endpoint state (toggle etc). + * Call with altsetting < 0 to disable the interface. The only other + * available altsetting is 0, which enables the interface. + */ +static int do_set_interface(struct fsg_common *common, int altsetting) +{ + int rc = 0; + int i; + const struct usb_endpoint_descriptor *d; + + if (common->running) + DBG(common, "reset interface\n"); + +reset: + /* Deallocate the requests */ + if (common->prev_fsg) { + struct fsg_dev *fsg = common->prev_fsg; + + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + struct fsg_buffhd *bh = &common->buffhds[i]; + + if (bh->inreq) { + usb_ep_free_request(fsg->bulk_in, bh->inreq); + bh->inreq = NULL; + } + if (bh->outreq) { + usb_ep_free_request(fsg->bulk_out, bh->outreq); + bh->outreq = NULL; + } + } + + /* Disable the endpoints */ + if (fsg->bulk_in_enabled) { + usb_ep_disable(fsg->bulk_in); + fsg->bulk_in_enabled = 0; + } + if (fsg->bulk_out_enabled) { + usb_ep_disable(fsg->bulk_out); + fsg->bulk_out_enabled = 0; + } + + common->prev_fsg = 0; + } + + common->running = 0; + if (altsetting < 0 || rc != 0) + return rc; + + DBG(common, "set interface %d\n", altsetting); + + if (fsg_is_set(common)) { + struct fsg_dev *fsg = common->fsg; + common->prev_fsg = common->fsg; + + /* Enable the endpoints */ + d = fsg_ep_desc(common->gadget, + &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); + rc = enable_endpoint(common, fsg->bulk_in, d); + if (rc) + goto reset; + fsg->bulk_in_enabled = 1; + + d = fsg_ep_desc(common->gadget, + &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); + rc = enable_endpoint(common, fsg->bulk_out, d); + if (rc) + goto reset; + fsg->bulk_out_enabled = 1; + common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); + clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); + + /* Allocate the requests */ + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + struct fsg_buffhd *bh = &common->buffhds[i]; + + rc = alloc_request(common, fsg->bulk_in, &bh->inreq); + if (rc) + goto reset; + rc = alloc_request(common, fsg->bulk_out, &bh->outreq); + if (rc) + goto reset; + bh->inreq->buf = bh->outreq->buf = bh->buf; + bh->inreq->context = bh->outreq->context = bh; + bh->inreq->complete = bulk_in_complete; + bh->outreq->complete = bulk_out_complete; + } + + common->running = 1; + for (i = 0; i < common->nluns; ++i) + common->luns[i].unit_attention_data = SS_RESET_OCCURRED; + return rc; + } else { + return -EIO; + } +} + + +/* + * Change our operational configuration. This code must agree with the code + * that returns config descriptors, and with interface altsetting code. + * + * It's also responsible for power management interactions. Some + * configurations might not work with our current power sources. + * For now we just assume the gadget is always self-powered. + */ +static int do_set_config(struct fsg_common *common, u8 new_config) +{ + int rc = 0; + + /* Disable the single interface */ + if (common->config != 0) { + DBG(common, "reset config\n"); + common->config = 0; + rc = do_set_interface(common, -1); + } + + /* Enable the interface */ + if (new_config != 0) { + common->config = new_config; + rc = do_set_interface(common, 0); + if (rc != 0) + common->config = 0; /* Reset on errors */ + } + return rc; +} + + +/****************************** ALT CONFIGS ******************************/ + + +static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) +{ + struct fsg_dev *fsg = fsg_from_func(f); + fsg->common->prev_fsg = fsg->common->fsg; + fsg->common->fsg = fsg; + fsg->common->new_config = 1; + raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); + return 0; +} + +static void fsg_disable(struct usb_function *f) +{ + struct fsg_dev *fsg = fsg_from_func(f); + fsg->common->prev_fsg = fsg->common->fsg; + fsg->common->fsg = fsg; + fsg->common->new_config = 0; + raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); +} + + +/*-------------------------------------------------------------------------*/ + +static void handle_exception(struct fsg_common *common) +{ + siginfo_t info; + int sig; + int i; + struct fsg_buffhd *bh; + enum fsg_state old_state; + u8 new_config; + struct fsg_lun *curlun; + unsigned int exception_req_tag; + int rc; + + /* Clear the existing signals. Anything but SIGUSR1 is converted + * into a high-priority EXIT exception. */ + for (;;) { + sig = dequeue_signal_lock(current, ¤t->blocked, &info); + if (!sig) + break; + if (sig != SIGUSR1) { + if (common->state < FSG_STATE_EXIT) + DBG(common, "Main thread exiting on signal\n"); + raise_exception(common, FSG_STATE_EXIT); + } + } + + /* Cancel all the pending transfers */ + if (fsg_is_set(common)) { + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + bh = &common->buffhds[i]; + if (bh->inreq_busy) + usb_ep_dequeue(common->fsg->bulk_in, bh->inreq); + if (bh->outreq_busy) + usb_ep_dequeue(common->fsg->bulk_out, + bh->outreq); + } + + /* Wait until everything is idle */ + for (;;) { + int num_active = 0; + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + bh = &common->buffhds[i]; + num_active += bh->inreq_busy + bh->outreq_busy; + } + if (num_active == 0) + break; + if (sleep_thread(common)) + return; + } + + /* Clear out the controller's fifos */ + if (common->fsg->bulk_in_enabled) + usb_ep_fifo_flush(common->fsg->bulk_in); + if (common->fsg->bulk_out_enabled) + usb_ep_fifo_flush(common->fsg->bulk_out); + } + + /* Reset the I/O buffer states and pointers, the SCSI + * state, and the exception. Then invoke the handler. */ + spin_lock_irq(&common->lock); + + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + bh = &common->buffhds[i]; + bh->state = BUF_STATE_EMPTY; + } + common->next_buffhd_to_fill = &common->buffhds[0]; + common->next_buffhd_to_drain = &common->buffhds[0]; + exception_req_tag = common->exception_req_tag; + new_config = common->new_config; + old_state = common->state; + + if (old_state == FSG_STATE_ABORT_BULK_OUT) + common->state = FSG_STATE_STATUS_PHASE; + else { + for (i = 0; i < common->nluns; ++i) { + curlun = &common->luns[i]; + curlun->prevent_medium_removal = 0; + curlun->sense_data = SS_NO_SENSE; + curlun->unit_attention_data = SS_NO_SENSE; + curlun->sense_data_info = 0; + curlun->info_valid = 0; + } + common->state = FSG_STATE_IDLE; + } + spin_unlock_irq(&common->lock); + + /* Carry out any extra actions required for the exception */ + switch (old_state) { + case FSG_STATE_ABORT_BULK_OUT: + send_status(common); + spin_lock_irq(&common->lock); + if (common->state == FSG_STATE_STATUS_PHASE) + common->state = FSG_STATE_IDLE; + spin_unlock_irq(&common->lock); + break; + + case FSG_STATE_RESET: + /* In case we were forced against our will to halt a + * bulk endpoint, clear the halt now. (The SuperH UDC + * requires this.) */ + if (!fsg_is_set(common)) + break; + if (test_and_clear_bit(IGNORE_BULK_OUT, + &common->fsg->atomic_bitflags)) + usb_ep_clear_halt(common->fsg->bulk_in); + + if (common->ep0_req_tag == exception_req_tag) + ep0_queue(common); /* Complete the status stage */ + + /* Technically this should go here, but it would only be + * a waste of time. Ditto for the INTERFACE_CHANGE and + * CONFIG_CHANGE cases. */ + /* for (i = 0; i < common->nluns; ++i) */ + /* common->luns[i].unit_attention_data = */ + /* SS_RESET_OCCURRED; */ + break; + + case FSG_STATE_CONFIG_CHANGE: + rc = do_set_config(common, new_config); + if (common->ep0_req_tag != exception_req_tag) + break; + if (rc != 0) { /* STALL on errors */ + DBG(common, "ep0 set halt\n"); + usb_ep_set_halt(common->ep0); + } else { /* Complete the status stage */ + ep0_queue(common); + } + break; + + case FSG_STATE_EXIT: + case FSG_STATE_TERMINATED: + do_set_config(common, 0); /* Free resources */ + spin_lock_irq(&common->lock); + common->state = FSG_STATE_TERMINATED; /* Stop the thread */ + spin_unlock_irq(&common->lock); + break; + + case FSG_STATE_INTERFACE_CHANGE: + case FSG_STATE_DISCONNECT: + case FSG_STATE_COMMAND_PHASE: + case FSG_STATE_DATA_PHASE: + case FSG_STATE_STATUS_PHASE: + case FSG_STATE_IDLE: + break; + } +} + + +/*-------------------------------------------------------------------------*/ + +static int fsg_main_thread(void *common_) +{ + struct fsg_common *common = common_; + + /* Allow the thread to be killed by a signal, but set the signal mask + * to block everything but INT, TERM, KILL, and USR1. */ + allow_signal(SIGINT); + allow_signal(SIGTERM); + allow_signal(SIGKILL); + allow_signal(SIGUSR1); + + /* Allow the thread to be frozen */ + set_freezable(); + + /* Arrange for userspace references to be interpreted as kernel + * pointers. That way we can pass a kernel pointer to a routine + * that expects a __user pointer and it will work okay. */ + set_fs(get_ds()); + + /* The main loop */ + while (common->state != FSG_STATE_TERMINATED) { + if (exception_in_progress(common) || signal_pending(current)) { + handle_exception(common); + continue; + } + + if (!common->running) { + sleep_thread(common); + continue; + } + + if (get_next_command(common)) + continue; + + spin_lock_irq(&common->lock); + if (!exception_in_progress(common)) + common->state = FSG_STATE_DATA_PHASE; + spin_unlock_irq(&common->lock); + + if (do_scsi_command(common) || finish_reply(common)) + continue; + + spin_lock_irq(&common->lock); + if (!exception_in_progress(common)) + common->state = FSG_STATE_STATUS_PHASE; + spin_unlock_irq(&common->lock); + + if (send_status(common)) + continue; + + spin_lock_irq(&common->lock); + if (!exception_in_progress(common)) + common->state = FSG_STATE_IDLE; + spin_unlock_irq(&common->lock); + } + + spin_lock_irq(&common->lock); + common->thread_task = NULL; + spin_unlock_irq(&common->lock); + + if (common->thread_exits) + common->thread_exits(common); + + /* Let the unbind and cleanup routines know the thread has exited */ + complete_and_exit(&common->thread_notifier, 0); +} + + +/*************************** DEVICE ATTRIBUTES ***************************/ + +/* Write permission is checked per LUN in store_*() functions. */ +static DEVICE_ATTR(ro, 0644, fsg_show_ro, fsg_store_ro); +static DEVICE_ATTR(file, 0644, fsg_show_file, fsg_store_file); + + +/****************************** FSG COMMON ******************************/ + +static void fsg_common_release(struct kref *ref); + +static void fsg_lun_release(struct device *dev) +{ + /* Nothing needs to be done */ +} + +static inline void fsg_common_get(struct fsg_common *common) +{ + kref_get(&common->ref); +} + +static inline void fsg_common_put(struct fsg_common *common) +{ + kref_put(&common->ref, fsg_common_release); +} + + +static struct fsg_common *fsg_common_init(struct fsg_common *common, + struct usb_composite_dev *cdev, + struct fsg_config *cfg) +{ + struct usb_gadget *gadget = cdev->gadget; + struct fsg_buffhd *bh; + struct fsg_lun *curlun; + struct fsg_lun_config *lcfg; + int nluns, i, rc; + char *pathbuf; + + /* Find out how many LUNs there should be */ + nluns = cfg->nluns; + if (nluns < 1 || nluns > FSG_MAX_LUNS) { + dev_err(&gadget->dev, "invalid number of LUNs: %u\n", nluns); + return ERR_PTR(-EINVAL); + } + + /* Allocate? */ + if (!common) { + common = kzalloc(sizeof *common, GFP_KERNEL); + if (!common) + return ERR_PTR(-ENOMEM); + common->free_storage_on_release = 1; + } else { + memset(common, 0, sizeof common); + common->free_storage_on_release = 0; + } + + common->private_data = cfg->private_data; + + common->gadget = gadget; + common->ep0 = gadget->ep0; + common->ep0req = cdev->req; + + /* Maybe allocate device-global string IDs, and patch descriptors */ + if (fsg_strings[FSG_STRING_INTERFACE].id == 0) { + rc = usb_string_id(cdev); + if (rc < 0) { + kfree(common); + return ERR_PTR(rc); + } + fsg_strings[FSG_STRING_INTERFACE].id = rc; + fsg_intf_desc.iInterface = rc; + } + + /* Create the LUNs, open their backing files, and register the + * LUN devices in sysfs. */ + curlun = kzalloc(nluns * sizeof *curlun, GFP_KERNEL); + if (!curlun) { + kfree(common); + return ERR_PTR(-ENOMEM); + } + common->luns = curlun; + + init_rwsem(&common->filesem); + + for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun, ++lcfg) { + curlun->cdrom = !!lcfg->cdrom; + curlun->ro = lcfg->cdrom || lcfg->ro; + curlun->removable = lcfg->removable; + curlun->dev.release = fsg_lun_release; + curlun->dev.parent = &gadget->dev; + /* curlun->dev.driver = &fsg_driver.driver; XXX */ + dev_set_drvdata(&curlun->dev, &common->filesem); + dev_set_name(&curlun->dev, + cfg->lun_name_format + ? cfg->lun_name_format + : "lun%d", + i); + + rc = device_register(&curlun->dev); + if (rc) { + INFO(common, "failed to register LUN%d: %d\n", i, rc); + common->nluns = i; + goto error_release; + } + + rc = device_create_file(&curlun->dev, &dev_attr_ro); + if (rc) + goto error_luns; + rc = device_create_file(&curlun->dev, &dev_attr_file); + if (rc) + goto error_luns; + + if (lcfg->filename) { + rc = fsg_lun_open(curlun, lcfg->filename); + if (rc) + goto error_luns; + } else if (!curlun->removable) { + ERROR(common, "no file given for LUN%d\n", i); + rc = -EINVAL; + goto error_luns; + } + } + common->nluns = nluns; + + + /* Data buffers cyclic list */ + /* Buffers in buffhds are static -- no need for additional + * allocation. */ + bh = common->buffhds; + i = FSG_NUM_BUFFERS - 1; + do { + bh->next = bh + 1; + } while (++bh, --i); + bh->next = common->buffhds; + + + /* Prepare inquiryString */ + if (cfg->release != 0xffff) { + i = cfg->release; + } else { + /* The sa1100 controller is not supported */ + i = gadget_is_sa1100(gadget) + ? -1 + : usb_gadget_controller_number(gadget); + if (i >= 0) { + i = 0x0300 + i; + } else { + WARNING(common, "controller '%s' not recognized\n", + gadget->name); + i = 0x0399; + } + } +#define OR(x, y) ((x) ? (x) : (y)) + snprintf(common->inquiry_string, sizeof common->inquiry_string, + "%-8s%-16s%04x", + OR(cfg->vendor_name, "Linux "), + /* Assume product name dependent on the first LUN */ + OR(cfg->product_name, common->luns->cdrom + ? "File-Stor Gadget" + : "File-CD Gadget "), + i); + + + /* Some peripheral controllers are known not to be able to + * halt bulk endpoints correctly. If one of them is present, + * disable stalls. + */ + common->can_stall = cfg->can_stall && + !(gadget_is_sh(common->gadget) || + gadget_is_at91(common->gadget)); + + + spin_lock_init(&common->lock); + kref_init(&common->ref); + + + /* Tell the thread to start working */ + common->thread_exits = cfg->thread_exits; + common->thread_task = + kthread_create(fsg_main_thread, common, + OR(cfg->thread_name, "file-storage")); + if (IS_ERR(common->thread_task)) { + rc = PTR_ERR(common->thread_task); + goto error_release; + } + init_completion(&common->thread_notifier); +#undef OR + + + /* Information */ + INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n"); + INFO(common, "Number of LUNs=%d\n", common->nluns); + + pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); + for (i = 0, nluns = common->nluns, curlun = common->luns; + i < nluns; + ++curlun, ++i) { + char *p = "(no medium)"; + if (fsg_lun_is_open(curlun)) { + p = "(error)"; + if (pathbuf) { + p = d_path(&curlun->filp->f_path, + pathbuf, PATH_MAX); + if (IS_ERR(p)) + p = "(error)"; + } + } + LINFO(curlun, "LUN: %s%s%sfile: %s\n", + curlun->removable ? "removable " : "", + curlun->ro ? "read only " : "", + curlun->cdrom ? "CD-ROM " : "", + p); + } + kfree(pathbuf); + + DBG(common, "I/O thread pid: %d\n", task_pid_nr(common->thread_task)); + + wake_up_process(common->thread_task); + + return common; + + +error_luns: + common->nluns = i + 1; +error_release: + common->state = FSG_STATE_TERMINATED; /* The thread is dead */ + /* Call fsg_common_release() directly, ref might be not + * initialised */ + fsg_common_release(&common->ref); + complete(&common->thread_notifier); + return ERR_PTR(rc); +} + + +static void fsg_common_release(struct kref *ref) +{ + struct fsg_common *common = + container_of(ref, struct fsg_common, ref); + unsigned i = common->nluns; + struct fsg_lun *lun = common->luns; + + /* If the thread isn't already dead, tell it to exit now */ + if (common->state != FSG_STATE_TERMINATED) { + raise_exception(common, FSG_STATE_EXIT); + wait_for_completion(&common->thread_notifier); + + /* The cleanup routine waits for this completion also */ + complete(&common->thread_notifier); + } + + /* Beware tempting for -> do-while optimization: when in error + * recovery nluns may be zero. */ + + for (; i; --i, ++lun) { + device_remove_file(&lun->dev, &dev_attr_ro); + device_remove_file(&lun->dev, &dev_attr_file); + fsg_lun_close(lun); + device_unregister(&lun->dev); + } + + kfree(common->luns); + if (common->free_storage_on_release) + kfree(common); +} + + +/*-------------------------------------------------------------------------*/ + + +static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) +{ + struct fsg_dev *fsg = fsg_from_func(f); + + DBG(fsg, "unbind\n"); + fsg_common_put(fsg->common); + kfree(fsg); +} + + +static int fsg_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct fsg_dev *fsg = fsg_from_func(f); + struct usb_gadget *gadget = c->cdev->gadget; + int rc; + int i; + struct usb_ep *ep; + + fsg->gadget = gadget; + + /* New interface */ + i = usb_interface_id(c, f); + if (i < 0) + return i; + fsg_intf_desc.bInterfaceNumber = i; + fsg->interface_number = i; + + /* Find all the endpoints we will use */ + ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc); + if (!ep) + goto autoconf_fail; + ep->driver_data = fsg->common; /* claim the endpoint */ + fsg->bulk_in = ep; + + ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc); + if (!ep) + goto autoconf_fail; + ep->driver_data = fsg->common; /* claim the endpoint */ + fsg->bulk_out = ep; + + if (gadget_is_dualspeed(gadget)) { + /* Assume endpoint addresses are the same for both speeds */ + fsg_hs_bulk_in_desc.bEndpointAddress = + fsg_fs_bulk_in_desc.bEndpointAddress; + fsg_hs_bulk_out_desc.bEndpointAddress = + fsg_fs_bulk_out_desc.bEndpointAddress; + f->hs_descriptors = fsg_hs_function; + } + + return 0; + +autoconf_fail: + ERROR(fsg, "unable to autoconfigure all endpoints\n"); + rc = -ENOTSUPP; + fsg_unbind(c, f); + return rc; +} + + +/****************************** ADD FUNCTION ******************************/ + +static struct usb_gadget_strings *fsg_strings_array[] = { + &fsg_stringtab, + NULL, +}; + +static int fsg_add(struct usb_composite_dev *cdev, + struct usb_configuration *c, + struct fsg_common *common) +{ + struct fsg_dev *fsg; + int rc; + + fsg = kzalloc(sizeof *fsg, GFP_KERNEL); + if (unlikely(!fsg)) + return -ENOMEM; + + fsg->function.name = FSG_DRIVER_DESC; + fsg->function.strings = fsg_strings_array; + fsg->function.descriptors = fsg_fs_function; + fsg->function.bind = fsg_bind; + fsg->function.unbind = fsg_unbind; + fsg->function.setup = fsg_setup; + fsg->function.set_alt = fsg_set_alt; + fsg->function.disable = fsg_disable; + + fsg->common = common; + /* Our caller holds a reference to common structure so we + * don't have to be worry about it being freed until we return + * from this function. So instead of incrementing counter now + * and decrement in error recovery we increment it only when + * call to usb_add_function() was successful. */ + + rc = usb_add_function(c, &fsg->function); + + if (likely(rc == 0)) + fsg_common_get(fsg->common); + else + kfree(fsg); + + return rc; +} + + + +/************************* Module parameters *************************/ + + +struct fsg_module_parameters { + char *file[FSG_MAX_LUNS]; + int ro[FSG_MAX_LUNS]; + int removable[FSG_MAX_LUNS]; + int cdrom[FSG_MAX_LUNS]; + + unsigned int file_count, ro_count, removable_count, cdrom_count; + unsigned int luns; /* nluns */ + int stall; /* can_stall */ +}; + + +#define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc) \ + module_param_array_named(prefix ## name, params.name, type, \ + &prefix ## params.name ## _count, \ + S_IRUGO); \ + MODULE_PARM_DESC(prefix ## name, desc) + +#define _FSG_MODULE_PARAM(prefix, params, name, type, desc) \ + module_param_named(prefix ## name, params.name, type, \ + S_IRUGO); \ + MODULE_PARM_DESC(prefix ## name, desc) + +#define FSG_MODULE_PARAMETERS(prefix, params) \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, file, charp, \ + "names of backing files or devices"); \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, ro, bool, \ + "true to force read-only"); \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, removable, bool, \ + "true to simulate removable media"); \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool, \ + "true to simulate CD-ROM instead of disk"); \ + _FSG_MODULE_PARAM(prefix, params, luns, uint, \ + "number of LUNs"); \ + _FSG_MODULE_PARAM(prefix, params, stall, bool, \ + "false to prevent bulk stalls") + + +static void +fsg_config_from_params(struct fsg_config *cfg, + const struct fsg_module_parameters *params) +{ + struct fsg_lun_config *lun; + unsigned i; + + /* Configure LUNs */ + cfg->nluns = + min(params->luns ?: (params->file_count ?: 1u), + (unsigned)FSG_MAX_LUNS); + for (i = 0, lun = cfg->luns; i < cfg->nluns; ++i, ++lun) { + lun->ro = !!params->ro[i]; + lun->cdrom = !!params->cdrom[i]; + lun->removable = /* Removable by default */ + params->removable_count <= i || params->removable[i]; + lun->filename = + params->file_count > i && params->file[i][0] + ? params->file[i] + : 0; + } + + /* Let MSF use defaults */ + cfg->lun_name_format = 0; + cfg->thread_name = 0; + cfg->vendor_name = 0; + cfg->product_name = 0; + cfg->release = 0xffff; + + cfg->thread_exits = 0; + cfg->private_data = 0; + + /* Finalise */ + cfg->can_stall = params->stall; +} + +static inline struct fsg_common * +fsg_common_from_params(struct fsg_common *common, + struct usb_composite_dev *cdev, + const struct fsg_module_parameters *params) + __attribute__((unused)); +static inline struct fsg_common * +fsg_common_from_params(struct fsg_common *common, + struct usb_composite_dev *cdev, + const struct fsg_module_parameters *params) +{ + struct fsg_config cfg; + fsg_config_from_params(&cfg, params); + return fsg_common_init(common, cdev, &cfg); +} + diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index c9966cc07d3a87576ab749286650e5c5ab3e6b0f..95dae4c1ea40d8cabaea0f1698b4f6b16acf847f 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -4,6 +4,8 @@ * Copyright (C) 2003-2005,2008 David Brownell * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger * Copyright (C) 2008 Nokia Corporation + * Copyright (C) 2009 Samsung Electronics + * Author: Michal Nazarewicz (m.nazarewicz@samsung.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 @@ -149,8 +151,8 @@ static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = { .bDataInterface = 0x01, }; -static struct usb_cdc_acm_descriptor acm_descriptor __initdata = { - .bLength = sizeof acm_descriptor, +static struct usb_cdc_acm_descriptor rndis_acm_descriptor __initdata = { + .bLength = sizeof rndis_acm_descriptor, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_ACM_TYPE, @@ -179,6 +181,20 @@ static struct usb_interface_descriptor rndis_data_intf __initdata = { /* .iInterface = DYNAMIC */ }; + +static struct usb_interface_assoc_descriptor +rndis_iad_descriptor = { + .bLength = sizeof rndis_iad_descriptor, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + + .bFirstInterface = 0, /* XXX, hardcoded */ + .bInterfaceCount = 2, // control + data + .bFunctionClass = USB_CLASS_COMM, + .bFunctionSubClass = USB_CDC_SUBCLASS_ETHERNET, + .bFunctionProtocol = USB_CDC_PROTO_NONE, + /* .iFunction = DYNAMIC */ +}; + /* full speed support: */ static struct usb_endpoint_descriptor fs_notify_desc __initdata = { @@ -208,11 +224,12 @@ static struct usb_endpoint_descriptor fs_out_desc __initdata = { }; static struct usb_descriptor_header *eth_fs_function[] __initdata = { + (struct usb_descriptor_header *) &rndis_iad_descriptor, /* control interface matches ACM, not Ethernet */ (struct usb_descriptor_header *) &rndis_control_intf, (struct usb_descriptor_header *) &header_desc, (struct usb_descriptor_header *) &call_mgmt_descriptor, - (struct usb_descriptor_header *) &acm_descriptor, + (struct usb_descriptor_header *) &rndis_acm_descriptor, (struct usb_descriptor_header *) &rndis_union_desc, (struct usb_descriptor_header *) &fs_notify_desc, /* data interface has no altsetting */ @@ -252,11 +269,12 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = { }; static struct usb_descriptor_header *eth_hs_function[] __initdata = { + (struct usb_descriptor_header *) &rndis_iad_descriptor, /* control interface matches ACM, not Ethernet */ (struct usb_descriptor_header *) &rndis_control_intf, (struct usb_descriptor_header *) &header_desc, (struct usb_descriptor_header *) &call_mgmt_descriptor, - (struct usb_descriptor_header *) &acm_descriptor, + (struct usb_descriptor_header *) &rndis_acm_descriptor, (struct usb_descriptor_header *) &rndis_union_desc, (struct usb_descriptor_header *) &hs_notify_desc, /* data interface has no altsetting */ @@ -271,6 +289,7 @@ static struct usb_descriptor_header *eth_hs_function[] __initdata = { static struct usb_string rndis_string_defs[] = { [0].s = "RNDIS Communications Control", [1].s = "RNDIS Ethernet Data", + [2].s = "RNDIS", { } /* end of list */ }; @@ -587,6 +606,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) if (status < 0) goto fail; rndis->ctrl_id = status; + rndis_iad_descriptor.bFirstInterface = status; rndis_control_intf.bInterfaceNumber = status; rndis_union_desc.bMasterInterface0 = status; @@ -798,6 +818,13 @@ int __init rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) return status; rndis_string_defs[1].id = status; rndis_data_intf.iInterface = status; + + /* IAD iFunction label */ + status = usb_string_id(c->cdev); + if (status < 0) + return status; + rndis_string_defs[2].id = status; + rndis_iad_descriptor.iFunction = status; } /* allocate and initialize one new instance */ diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 1e6aa504d58a9390d196a0b5c3823e3e4f299e69..29dfb0277ffbf5c9d6adcd80d2b68b274401c17d 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -248,8 +248,6 @@ #include #include -#include - #include #include @@ -274,21 +272,20 @@ #define DRIVER_NAME "g_file_storage" #define DRIVER_VERSION "20 November 2008" -static const char longname[] = DRIVER_DESC; -static const char shortname[] = DRIVER_NAME; +static char fsg_string_manufacturer[64]; +static const char fsg_string_product[] = DRIVER_DESC; +static char fsg_string_serial[13]; +static const char fsg_string_config[] = "Self-powered"; +static const char fsg_string_interface[] = "Mass Storage"; + + +#include "storage_common.c" + MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR("Alan Stern"); MODULE_LICENSE("Dual BSD/GPL"); -/* Thanks to NetChip Technologies for donating this product ID. - * - * DO NOT REUSE THESE IDs with any other driver!! Ever!! - * Instead: allocate your own, using normal USB-IF procedures. */ -#define DRIVER_VENDOR_ID 0x0525 // NetChip -#define DRIVER_PRODUCT_ID 0xa4a5 // Linux-USB File-backed Storage Gadget - - /* * This driver assumes self-powered hardware and has no way for users to * trigger remote wakeup. It uses autoconfiguration to select endpoints @@ -298,54 +295,12 @@ MODULE_LICENSE("Dual BSD/GPL"); /*-------------------------------------------------------------------------*/ -#define LDBG(lun,fmt,args...) \ - dev_dbg(&(lun)->dev , fmt , ## args) -#define MDBG(fmt,args...) \ - pr_debug(DRIVER_NAME ": " fmt , ## args) - -#ifndef DEBUG -#undef VERBOSE_DEBUG -#undef DUMP_MSGS -#endif /* !DEBUG */ - -#ifdef VERBOSE_DEBUG -#define VLDBG LDBG -#else -#define VLDBG(lun,fmt,args...) \ - do { } while (0) -#endif /* VERBOSE_DEBUG */ - -#define LERROR(lun,fmt,args...) \ - dev_err(&(lun)->dev , fmt , ## args) -#define LWARN(lun,fmt,args...) \ - dev_warn(&(lun)->dev , fmt , ## args) -#define LINFO(lun,fmt,args...) \ - dev_info(&(lun)->dev , fmt , ## args) - -#define MINFO(fmt,args...) \ - pr_info(DRIVER_NAME ": " fmt , ## args) - -#define DBG(d, fmt, args...) \ - dev_dbg(&(d)->gadget->dev , fmt , ## args) -#define VDBG(d, fmt, args...) \ - dev_vdbg(&(d)->gadget->dev , fmt , ## args) -#define ERROR(d, fmt, args...) \ - dev_err(&(d)->gadget->dev , fmt , ## args) -#define WARNING(d, fmt, args...) \ - dev_warn(&(d)->gadget->dev , fmt , ## args) -#define INFO(d, fmt, args...) \ - dev_info(&(d)->gadget->dev , fmt , ## args) - - -/*-------------------------------------------------------------------------*/ /* Encapsulate the module parameter settings */ -#define MAX_LUNS 8 - static struct { - char *file[MAX_LUNS]; - int ro[MAX_LUNS]; + char *file[FSG_MAX_LUNS]; + int ro[FSG_MAX_LUNS]; unsigned int num_filenames; unsigned int num_ros; unsigned int nluns; @@ -372,8 +327,8 @@ static struct { .removable = 0, .can_stall = 1, .cdrom = 0, - .vendor = DRIVER_VENDOR_ID, - .product = DRIVER_PRODUCT_ID, + .vendor = FSG_VENDOR_ID, + .product = FSG_PRODUCT_ID, .release = 0xffff, // Use controller chip type .buflen = 16384, }; @@ -425,125 +380,6 @@ MODULE_PARM_DESC(buflen, "I/O buffer size"); #endif /* CONFIG_USB_FILE_STORAGE_TEST */ -/*-------------------------------------------------------------------------*/ - -/* SCSI device types */ -#define TYPE_DISK 0x00 -#define TYPE_CDROM 0x05 - -/* USB protocol value = the transport method */ -#define USB_PR_CBI 0x00 // Control/Bulk/Interrupt -#define USB_PR_CB 0x01 // Control/Bulk w/o interrupt -#define USB_PR_BULK 0x50 // Bulk-only - -/* USB subclass value = the protocol encapsulation */ -#define USB_SC_RBC 0x01 // Reduced Block Commands (flash) -#define USB_SC_8020 0x02 // SFF-8020i, MMC-2, ATAPI (CD-ROM) -#define USB_SC_QIC 0x03 // QIC-157 (tape) -#define USB_SC_UFI 0x04 // UFI (floppy) -#define USB_SC_8070 0x05 // SFF-8070i (removable) -#define USB_SC_SCSI 0x06 // Transparent SCSI - -/* Bulk-only data structures */ - -/* Command Block Wrapper */ -struct bulk_cb_wrap { - __le32 Signature; // Contains 'USBC' - u32 Tag; // Unique per command id - __le32 DataTransferLength; // Size of the data - u8 Flags; // Direction in bit 7 - u8 Lun; // LUN (normally 0) - u8 Length; // Of the CDB, <= MAX_COMMAND_SIZE - u8 CDB[16]; // Command Data Block -}; - -#define USB_BULK_CB_WRAP_LEN 31 -#define USB_BULK_CB_SIG 0x43425355 // Spells out USBC -#define USB_BULK_IN_FLAG 0x80 - -/* Command Status Wrapper */ -struct bulk_cs_wrap { - __le32 Signature; // Should = 'USBS' - u32 Tag; // Same as original command - __le32 Residue; // Amount not transferred - u8 Status; // See below -}; - -#define USB_BULK_CS_WRAP_LEN 13 -#define USB_BULK_CS_SIG 0x53425355 // Spells out 'USBS' -#define USB_STATUS_PASS 0 -#define USB_STATUS_FAIL 1 -#define USB_STATUS_PHASE_ERROR 2 - -/* Bulk-only class specific requests */ -#define USB_BULK_RESET_REQUEST 0xff -#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe - - -/* CBI Interrupt data structure */ -struct interrupt_data { - u8 bType; - u8 bValue; -}; - -#define CBI_INTERRUPT_DATA_LEN 2 - -/* CBI Accept Device-Specific Command request */ -#define USB_CBI_ADSC_REQUEST 0x00 - - -#define MAX_COMMAND_SIZE 16 // Length of a SCSI Command Data Block - -/* SCSI commands that we recognize */ -#define SC_FORMAT_UNIT 0x04 -#define SC_INQUIRY 0x12 -#define SC_MODE_SELECT_6 0x15 -#define SC_MODE_SELECT_10 0x55 -#define SC_MODE_SENSE_6 0x1a -#define SC_MODE_SENSE_10 0x5a -#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e -#define SC_READ_6 0x08 -#define SC_READ_10 0x28 -#define SC_READ_12 0xa8 -#define SC_READ_CAPACITY 0x25 -#define SC_READ_FORMAT_CAPACITIES 0x23 -#define SC_READ_HEADER 0x44 -#define SC_READ_TOC 0x43 -#define SC_RELEASE 0x17 -#define SC_REQUEST_SENSE 0x03 -#define SC_RESERVE 0x16 -#define SC_SEND_DIAGNOSTIC 0x1d -#define SC_START_STOP_UNIT 0x1b -#define SC_SYNCHRONIZE_CACHE 0x35 -#define SC_TEST_UNIT_READY 0x00 -#define SC_VERIFY 0x2f -#define SC_WRITE_6 0x0a -#define SC_WRITE_10 0x2a -#define SC_WRITE_12 0xaa - -/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */ -#define SS_NO_SENSE 0 -#define SS_COMMUNICATION_FAILURE 0x040800 -#define SS_INVALID_COMMAND 0x052000 -#define SS_INVALID_FIELD_IN_CDB 0x052400 -#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100 -#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500 -#define SS_MEDIUM_NOT_PRESENT 0x023a00 -#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302 -#define SS_NOT_READY_TO_READY_TRANSITION 0x062800 -#define SS_RESET_OCCURRED 0x062900 -#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900 -#define SS_UNRECOVERED_READ_ERROR 0x031100 -#define SS_WRITE_ERROR 0x030c02 -#define SS_WRITE_PROTECTED 0x072700 - -#define SK(x) ((u8) ((x) >> 16)) // Sense Key byte, etc. -#define ASC(x) ((u8) ((x) >> 8)) -#define ASCQ(x) ((u8) (x)) - - -/*-------------------------------------------------------------------------*/ - /* * These definitions will permit the compiler to avoid generating code for * parts of the driver that aren't used in the non-TEST version. Even gcc @@ -566,81 +402,8 @@ struct interrupt_data { #endif /* CONFIG_USB_FILE_STORAGE_TEST */ -struct lun { - struct file *filp; - loff_t file_length; - loff_t num_sectors; - - unsigned int ro : 1; - unsigned int prevent_medium_removal : 1; - unsigned int registered : 1; - unsigned int info_valid : 1; - - u32 sense_data; - u32 sense_data_info; - u32 unit_attention_data; - - struct device dev; -}; - -#define backing_file_is_open(curlun) ((curlun)->filp != NULL) - -static struct lun *dev_to_lun(struct device *dev) -{ - return container_of(dev, struct lun, dev); -} - - -/* Big enough to hold our biggest descriptor */ -#define EP0_BUFSIZE 256 -#define DELAYED_STATUS (EP0_BUFSIZE + 999) // An impossibly large value - -/* Number of buffers we will use. 2 is enough for double-buffering */ -#define NUM_BUFFERS 2 - -enum fsg_buffer_state { - BUF_STATE_EMPTY = 0, - BUF_STATE_FULL, - BUF_STATE_BUSY -}; - -struct fsg_buffhd { - void *buf; - enum fsg_buffer_state state; - struct fsg_buffhd *next; - - /* The NetChip 2280 is faster, and handles some protocol faults - * better, if we don't submit any short bulk-out read requests. - * So we will record the intended request length here. */ - unsigned int bulk_out_intended_length; - - struct usb_request *inreq; - int inreq_busy; - struct usb_request *outreq; - int outreq_busy; -}; - -enum fsg_state { - FSG_STATE_COMMAND_PHASE = -10, // This one isn't used anywhere - FSG_STATE_DATA_PHASE, - FSG_STATE_STATUS_PHASE, - - FSG_STATE_IDLE = 0, - FSG_STATE_ABORT_BULK_OUT, - FSG_STATE_RESET, - FSG_STATE_INTERFACE_CHANGE, - FSG_STATE_CONFIG_CHANGE, - FSG_STATE_DISCONNECT, - FSG_STATE_EXIT, - FSG_STATE_TERMINATED -}; +/*-------------------------------------------------------------------------*/ -enum data_direction { - DATA_DIR_UNKNOWN = 0, - DATA_DIR_FROM_HOST, - DATA_DIR_TO_HOST, - DATA_DIR_NONE -}; struct fsg_dev { /* lock protects: state, all the req_busy's, and cbbuf_cmnd */ @@ -662,7 +425,7 @@ struct fsg_dev { int intreq_busy; struct fsg_buffhd *intr_buffhd; - unsigned int bulk_out_maxpacket; + unsigned int bulk_out_maxpacket; enum fsg_state state; // For exception handling unsigned int exception_req_tag; @@ -687,7 +450,7 @@ struct fsg_dev { struct fsg_buffhd *next_buffhd_to_fill; struct fsg_buffhd *next_buffhd_to_drain; - struct fsg_buffhd buffhds[NUM_BUFFERS]; + struct fsg_buffhd buffhds[FSG_NUM_BUFFERS]; int thread_wakeup_needed; struct completion thread_notifier; @@ -712,8 +475,8 @@ struct fsg_dev { u8 cbbuf_cmnd[MAX_COMMAND_SIZE]; unsigned int nluns; - struct lun *luns; - struct lun *curlun; + struct fsg_lun *luns; + struct fsg_lun *curlun; }; typedef void (*fsg_routine_t)(struct fsg_dev *); @@ -739,49 +502,9 @@ static void set_bulk_out_req_length(struct fsg_dev *fsg, static struct fsg_dev *the_fsg; static struct usb_gadget_driver fsg_driver; -static void close_backing_file(struct lun *curlun); - /*-------------------------------------------------------------------------*/ -#ifdef DUMP_MSGS - -static void dump_msg(struct fsg_dev *fsg, const char *label, - const u8 *buf, unsigned int length) -{ - if (length < 512) { - DBG(fsg, "%s, length %u:\n", label, length); - print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, - 16, 1, buf, length, 0); - } -} - -static void dump_cdb(struct fsg_dev *fsg) -{} - -#else - -static void dump_msg(struct fsg_dev *fsg, const char *label, - const u8 *buf, unsigned int length) -{} - -#ifdef VERBOSE_DEBUG - -static void dump_cdb(struct fsg_dev *fsg) -{ - print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE, - 16, 1, fsg->cmnd, fsg->cmnd_size, 0); -} - -#else - -static void dump_cdb(struct fsg_dev *fsg) -{} - -#endif /* VERBOSE_DEBUG */ -#endif /* DUMP_MSGS */ - - static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) { const char *name; @@ -797,16 +520,6 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) } -/*-------------------------------------------------------------------------*/ - -/* Routines for unaligned data access */ - -static u32 get_unaligned_be24(u8 *buf) -{ - return 0xffffff & (u32) get_unaligned_be32(buf - 1); -} - - /*-------------------------------------------------------------------------*/ /* @@ -814,11 +527,6 @@ static u32 get_unaligned_be24(u8 *buf) * descriptors are built on demand. Also the (static) config and interface * descriptors are adjusted during fsg_bind(). */ -#define STRING_MANUFACTURER 1 -#define STRING_PRODUCT 2 -#define STRING_SERIAL 3 -#define STRING_CONFIG 4 -#define STRING_INTERFACE 5 /* There is only one configuration. */ #define CONFIG_VALUE 1 @@ -832,13 +540,13 @@ device_desc = { .bDeviceClass = USB_CLASS_PER_INTERFACE, /* The next three values can be overridden by module parameters */ - .idVendor = cpu_to_le16(DRIVER_VENDOR_ID), - .idProduct = cpu_to_le16(DRIVER_PRODUCT_ID), + .idVendor = cpu_to_le16(FSG_VENDOR_ID), + .idProduct = cpu_to_le16(FSG_PRODUCT_ID), .bcdDevice = cpu_to_le16(0xffff), - .iManufacturer = STRING_MANUFACTURER, - .iProduct = STRING_PRODUCT, - .iSerialNumber = STRING_SERIAL, + .iManufacturer = FSG_STRING_MANUFACTURER, + .iProduct = FSG_STRING_PRODUCT, + .iSerialNumber = FSG_STRING_SERIAL, .bNumConfigurations = 1, }; @@ -850,86 +558,12 @@ config_desc = { /* wTotalLength computed by usb_gadget_config_buf() */ .bNumInterfaces = 1, .bConfigurationValue = CONFIG_VALUE, - .iConfiguration = STRING_CONFIG, + .iConfiguration = FSG_STRING_CONFIG, .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, }; -static struct usb_otg_descriptor -otg_desc = { - .bLength = sizeof(otg_desc), - .bDescriptorType = USB_DT_OTG, - - .bmAttributes = USB_OTG_SRP, -}; - -/* There is only one interface. */ -static struct usb_interface_descriptor -intf_desc = { - .bLength = sizeof intf_desc, - .bDescriptorType = USB_DT_INTERFACE, - - .bNumEndpoints = 2, // Adjusted during fsg_bind() - .bInterfaceClass = USB_CLASS_MASS_STORAGE, - .bInterfaceSubClass = USB_SC_SCSI, // Adjusted during fsg_bind() - .bInterfaceProtocol = USB_PR_BULK, // Adjusted during fsg_bind() - .iInterface = STRING_INTERFACE, -}; - -/* Three full-speed endpoint descriptors: bulk-in, bulk-out, - * and interrupt-in. */ - -static struct usb_endpoint_descriptor -fs_bulk_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - /* wMaxPacketSize set by autoconfiguration */ -}; - -static struct usb_endpoint_descriptor -fs_bulk_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - /* wMaxPacketSize set by autoconfiguration */ -}; - -static struct usb_endpoint_descriptor -fs_intr_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(2), - .bInterval = 32, // frames -> 32 ms -}; - -static const struct usb_descriptor_header *fs_function[] = { - (struct usb_descriptor_header *) &otg_desc, - (struct usb_descriptor_header *) &intf_desc, - (struct usb_descriptor_header *) &fs_bulk_in_desc, - (struct usb_descriptor_header *) &fs_bulk_out_desc, - (struct usb_descriptor_header *) &fs_intr_in_desc, - NULL, -}; -#define FS_FUNCTION_PRE_EP_ENTRIES 2 - - -/* - * USB 2.0 devices need to expose both high speed and full speed - * descriptors, unless they only run at full speed. - * - * That means alternate endpoint descriptors (bigger packets) - * and a "device qualifier" ... plus more construction options - * for the config descriptor. - */ static struct usb_qualifier_descriptor dev_qualifier = { .bLength = sizeof dev_qualifier, @@ -941,78 +575,6 @@ dev_qualifier = { .bNumConfigurations = 1, }; -static struct usb_endpoint_descriptor -hs_bulk_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16(512), -}; - -static struct usb_endpoint_descriptor -hs_bulk_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16(512), - .bInterval = 1, // NAK every 1 uframe -}; - -static struct usb_endpoint_descriptor -hs_intr_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(2), - .bInterval = 9, // 2**(9-1) = 256 uframes -> 32 ms -}; - -static const struct usb_descriptor_header *hs_function[] = { - (struct usb_descriptor_header *) &otg_desc, - (struct usb_descriptor_header *) &intf_desc, - (struct usb_descriptor_header *) &hs_bulk_in_desc, - (struct usb_descriptor_header *) &hs_bulk_out_desc, - (struct usb_descriptor_header *) &hs_intr_in_desc, - NULL, -}; -#define HS_FUNCTION_PRE_EP_ENTRIES 2 - -/* Maxpacket and other transfer characteristics vary by speed. */ -static struct usb_endpoint_descriptor * -ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, - struct usb_endpoint_descriptor *hs) -{ - if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) - return hs; - return fs; -} - - -/* The CBI specification limits the serial string to 12 uppercase hexadecimal - * characters. */ -static char manufacturer[64]; -static char serial[13]; - -/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */ -static struct usb_string strings[] = { - {STRING_MANUFACTURER, manufacturer}, - {STRING_PRODUCT, longname}, - {STRING_SERIAL, serial}, - {STRING_CONFIG, "Self-powered"}, - {STRING_INTERFACE, "Mass Storage"}, - {} -}; - -static struct usb_gadget_strings stringtab = { - .language = 0x0409, // en-us - .strings = strings, -}; /* @@ -1032,10 +594,9 @@ static int populate_config_buf(struct usb_gadget *gadget, if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG) speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed; - if (gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH) - function = hs_function; - else - function = fs_function; + function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH + ? (const struct usb_descriptor_header **)fsg_hs_function + : (const struct usb_descriptor_header **)fsg_fs_function; /* for now, don't advertise srp-only devices */ if (!gadget_is_otg(gadget)) @@ -1386,7 +947,7 @@ get_config: VDBG(fsg, "get string descriptor\n"); /* wIndex == language code */ - value = usb_gadget_get_string(&stringtab, + value = usb_gadget_get_string(&fsg_stringtab, w_value & 0xff, req->buf); break; } @@ -1551,7 +1112,7 @@ static int sleep_thread(struct fsg_dev *fsg) static int do_read(struct fsg_dev *fsg) { - struct lun *curlun = fsg->curlun; + struct fsg_lun *curlun = fsg->curlun; u32 lba; struct fsg_buffhd *bh; int rc; @@ -1677,7 +1238,7 @@ static int do_read(struct fsg_dev *fsg) static int do_write(struct fsg_dev *fsg) { - struct lun *curlun = fsg->curlun; + struct fsg_lun *curlun = fsg->curlun; u32 lba; struct fsg_buffhd *bh; int get_some_more; @@ -1713,7 +1274,7 @@ static int do_write(struct fsg_dev *fsg) } if (fsg->cmnd[1] & 0x08) { // FUA spin_lock(&curlun->filp->f_lock); - curlun->filp->f_flags |= O_SYNC; + curlun->filp->f_flags |= O_DSYNC; spin_unlock(&curlun->filp->f_lock); } } @@ -1864,33 +1425,14 @@ static int do_write(struct fsg_dev *fsg) /*-------------------------------------------------------------------------*/ -/* Sync the file data, don't bother with the metadata. - * This code was copied from fs/buffer.c:sys_fdatasync(). */ -static int fsync_sub(struct lun *curlun) -{ - struct file *filp = curlun->filp; - - if (curlun->ro || !filp) - return 0; - return vfs_fsync(filp, filp->f_path.dentry, 1); -} - -static void fsync_all(struct fsg_dev *fsg) -{ - int i; - - for (i = 0; i < fsg->nluns; ++i) - fsync_sub(&fsg->luns[i]); -} - static int do_synchronize_cache(struct fsg_dev *fsg) { - struct lun *curlun = fsg->curlun; + struct fsg_lun *curlun = fsg->curlun; int rc; /* We ignore the requested LBA and write out all file's * dirty data buffers. */ - rc = fsync_sub(curlun); + rc = fsg_lun_fsync_sub(curlun); if (rc) curlun->sense_data = SS_WRITE_ERROR; return 0; @@ -1899,7 +1441,7 @@ static int do_synchronize_cache(struct fsg_dev *fsg) /*-------------------------------------------------------------------------*/ -static void invalidate_sub(struct lun *curlun) +static void invalidate_sub(struct fsg_lun *curlun) { struct file *filp = curlun->filp; struct inode *inode = filp->f_path.dentry->d_inode; @@ -1911,7 +1453,7 @@ static void invalidate_sub(struct lun *curlun) static int do_verify(struct fsg_dev *fsg) { - struct lun *curlun = fsg->curlun; + struct fsg_lun *curlun = fsg->curlun; u32 lba; u32 verification_length; struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; @@ -1944,7 +1486,7 @@ static int do_verify(struct fsg_dev *fsg) file_offset = ((loff_t) lba) << 9; /* Write out all the dirty buffers before invalidating them */ - fsync_sub(curlun); + fsg_lun_fsync_sub(curlun); if (signal_pending(current)) return -EINTR; @@ -2041,7 +1583,7 @@ static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) { - struct lun *curlun = fsg->curlun; + struct fsg_lun *curlun = fsg->curlun; u8 *buf = (u8 *) bh->buf; u32 sd, sdinfo; int valid; @@ -2095,7 +1637,7 @@ static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh) { - struct lun *curlun = fsg->curlun; + struct fsg_lun *curlun = fsg->curlun; u32 lba = get_unaligned_be32(&fsg->cmnd[2]); int pmi = fsg->cmnd[8]; u8 *buf = (u8 *) bh->buf; @@ -2113,27 +1655,9 @@ static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh) } -static void store_cdrom_address(u8 *dest, int msf, u32 addr) -{ - if (msf) { - /* Convert to Minutes-Seconds-Frames */ - addr >>= 2; /* Convert to 2048-byte frames */ - addr += 2*75; /* Lead-in occupies 2 seconds */ - dest[3] = addr % 75; /* Frames */ - addr /= 75; - dest[2] = addr % 60; /* Seconds */ - addr /= 60; - dest[1] = addr; /* Minutes */ - dest[0] = 0; /* Reserved */ - } else { - /* Absolute sector */ - put_unaligned_be32(addr, dest); - } -} - static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh) { - struct lun *curlun = fsg->curlun; + struct fsg_lun *curlun = fsg->curlun; int msf = fsg->cmnd[1] & 0x02; u32 lba = get_unaligned_be32(&fsg->cmnd[2]); u8 *buf = (u8 *) bh->buf; @@ -2156,7 +1680,7 @@ static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh) static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh) { - struct lun *curlun = fsg->curlun; + struct fsg_lun *curlun = fsg->curlun; int msf = fsg->cmnd[1] & 0x02; int start_track = fsg->cmnd[6]; u8 *buf = (u8 *) bh->buf; @@ -2184,7 +1708,7 @@ static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh) static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) { - struct lun *curlun = fsg->curlun; + struct fsg_lun *curlun = fsg->curlun; int mscmnd = fsg->cmnd[0]; u8 *buf = (u8 *) bh->buf; u8 *buf0 = buf; @@ -2265,7 +1789,7 @@ static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) static int do_start_stop(struct fsg_dev *fsg) { - struct lun *curlun = fsg->curlun; + struct fsg_lun *curlun = fsg->curlun; int loej, start; if (!mod_data.removable) { @@ -2295,7 +1819,7 @@ static int do_start_stop(struct fsg_dev *fsg) if (loej) { // Simulate an unload/eject up_read(&fsg->filesem); down_write(&fsg->filesem); - close_backing_file(curlun); + fsg_lun_close(curlun); up_write(&fsg->filesem); down_read(&fsg->filesem); } @@ -2303,7 +1827,7 @@ static int do_start_stop(struct fsg_dev *fsg) /* Our emulation doesn't support mounting; the medium is * available for use as soon as it is loaded. */ - if (!backing_file_is_open(curlun)) { + if (!fsg_lun_is_open(curlun)) { curlun->sense_data = SS_MEDIUM_NOT_PRESENT; return -EINVAL; } @@ -2315,7 +1839,7 @@ static int do_start_stop(struct fsg_dev *fsg) static int do_prevent_allow(struct fsg_dev *fsg) { - struct lun *curlun = fsg->curlun; + struct fsg_lun *curlun = fsg->curlun; int prevent; if (!mod_data.removable) { @@ -2330,7 +1854,7 @@ static int do_prevent_allow(struct fsg_dev *fsg) } if (curlun->prevent_medium_removal && !prevent) - fsync_sub(curlun); + fsg_lun_fsync_sub(curlun); curlun->prevent_medium_removal = prevent; return 0; } @@ -2339,7 +1863,7 @@ static int do_prevent_allow(struct fsg_dev *fsg) static int do_read_format_capacities(struct fsg_dev *fsg, struct fsg_buffhd *bh) { - struct lun *curlun = fsg->curlun; + struct fsg_lun *curlun = fsg->curlun; u8 *buf = (u8 *) bh->buf; buf[0] = buf[1] = buf[2] = 0; @@ -2356,7 +1880,7 @@ static int do_read_format_capacities(struct fsg_dev *fsg, static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh) { - struct lun *curlun = fsg->curlun; + struct fsg_lun *curlun = fsg->curlun; /* We don't support MODE SELECT */ curlun->sense_data = SS_INVALID_COMMAND; @@ -2599,7 +2123,7 @@ static int finish_reply(struct fsg_dev *fsg) static int send_status(struct fsg_dev *fsg) { - struct lun *curlun = fsg->curlun; + struct fsg_lun *curlun = fsg->curlun; struct fsg_buffhd *bh; int rc; u8 status = USB_STATUS_PASS; @@ -2691,7 +2215,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, int lun = fsg->cmnd[1] >> 5; static const char dirletter[4] = {'u', 'o', 'i', 'n'}; char hdlen[20]; - struct lun *curlun; + struct fsg_lun *curlun; /* Adjust the expected cmnd_size for protocol encapsulation padding. * Transparent SCSI doesn't pad. */ @@ -2820,7 +2344,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, /* If the medium isn't mounted and the command needs to access * it, return an error. */ - if (curlun && !backing_file_is_open(curlun) && needs_medium) { + if (curlun && !fsg_lun_is_open(curlun) && needs_medium) { curlun->sense_data = SS_MEDIUM_NOT_PRESENT; return -EINVAL; } @@ -3075,8 +2599,8 @@ static int do_scsi_command(struct fsg_dev *fsg) static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) { - struct usb_request *req = bh->outreq; - struct bulk_cb_wrap *cbw = req->buf; + struct usb_request *req = bh->outreq; + struct fsg_bulk_cb_wrap *cbw = req->buf; /* Was this a real packet? Should it be ignored? */ if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) @@ -3105,7 +2629,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) } /* Is the CBW meaningful? */ - if (cbw->Lun >= MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || + if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " "cmdlen %u\n", @@ -3238,7 +2762,7 @@ static int do_set_interface(struct fsg_dev *fsg, int altsetting) reset: /* Deallocate the requests */ - for (i = 0; i < NUM_BUFFERS; ++i) { + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { struct fsg_buffhd *bh = &fsg->buffhds[i]; if (bh->inreq) { @@ -3276,12 +2800,14 @@ reset: DBG(fsg, "set interface %d\n", altsetting); /* Enable the endpoints */ - d = ep_desc(fsg->gadget, &fs_bulk_in_desc, &hs_bulk_in_desc); + d = fsg_ep_desc(fsg->gadget, + &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0) goto reset; fsg->bulk_in_enabled = 1; - d = ep_desc(fsg->gadget, &fs_bulk_out_desc, &hs_bulk_out_desc); + d = fsg_ep_desc(fsg->gadget, + &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0) goto reset; fsg->bulk_out_enabled = 1; @@ -3289,14 +2815,15 @@ reset: clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); if (transport_is_cbi()) { - d = ep_desc(fsg->gadget, &fs_intr_in_desc, &hs_intr_in_desc); + d = fsg_ep_desc(fsg->gadget, + &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc); if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0) goto reset; fsg->intr_in_enabled = 1; } /* Allocate the requests */ - for (i = 0; i < NUM_BUFFERS; ++i) { + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { struct fsg_buffhd *bh = &fsg->buffhds[i]; if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0) @@ -3372,7 +2899,7 @@ static void handle_exception(struct fsg_dev *fsg) struct fsg_buffhd *bh; enum fsg_state old_state; u8 new_config; - struct lun *curlun; + struct fsg_lun *curlun; unsigned int exception_req_tag; int rc; @@ -3392,7 +2919,7 @@ static void handle_exception(struct fsg_dev *fsg) /* Cancel all the pending transfers */ if (fsg->intreq_busy) usb_ep_dequeue(fsg->intr_in, fsg->intreq); - for (i = 0; i < NUM_BUFFERS; ++i) { + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { bh = &fsg->buffhds[i]; if (bh->inreq_busy) usb_ep_dequeue(fsg->bulk_in, bh->inreq); @@ -3403,7 +2930,7 @@ static void handle_exception(struct fsg_dev *fsg) /* Wait until everything is idle */ for (;;) { num_active = fsg->intreq_busy; - for (i = 0; i < NUM_BUFFERS; ++i) { + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { bh = &fsg->buffhds[i]; num_active += bh->inreq_busy + bh->outreq_busy; } @@ -3425,7 +2952,7 @@ static void handle_exception(struct fsg_dev *fsg) * state, and the exception. Then invoke the handler. */ spin_lock_irq(&fsg->lock); - for (i = 0; i < NUM_BUFFERS; ++i) { + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { bh = &fsg->buffhds[i]; bh->state = BUF_STATE_EMPTY; } @@ -3506,7 +3033,8 @@ static void handle_exception(struct fsg_dev *fsg) break; case FSG_STATE_DISCONNECT: - fsync_all(fsg); + for (i = 0; i < fsg->nluns; ++i) + fsg_lun_fsync_sub(fsg->luns + i); do_set_config(fsg, 0); // Unconfigured state break; @@ -3595,201 +3123,10 @@ static int fsg_main_thread(void *fsg_) /*-------------------------------------------------------------------------*/ -/* If the next two routines are called while the gadget is registered, - * the caller must own fsg->filesem for writing. */ - -static int open_backing_file(struct lun *curlun, const char *filename) -{ - int ro; - struct file *filp = NULL; - int rc = -EINVAL; - struct inode *inode = NULL; - loff_t size; - loff_t num_sectors; - loff_t min_sectors; - - /* R/W if we can, R/O if we must */ - ro = curlun->ro; - if (!ro) { - filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0); - if (-EROFS == PTR_ERR(filp)) - ro = 1; - } - if (ro) - filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0); - if (IS_ERR(filp)) { - LINFO(curlun, "unable to open backing file: %s\n", filename); - return PTR_ERR(filp); - } - - if (!(filp->f_mode & FMODE_WRITE)) - ro = 1; - - if (filp->f_path.dentry) - inode = filp->f_path.dentry->d_inode; - if (inode && S_ISBLK(inode->i_mode)) { - if (bdev_read_only(inode->i_bdev)) - ro = 1; - } else if (!inode || !S_ISREG(inode->i_mode)) { - LINFO(curlun, "invalid file type: %s\n", filename); - goto out; - } - - /* If we can't read the file, it's no good. - * If we can't write the file, use it read-only. */ - if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) { - LINFO(curlun, "file not readable: %s\n", filename); - goto out; - } - if (!(filp->f_op->write || filp->f_op->aio_write)) - ro = 1; - - size = i_size_read(inode->i_mapping->host); - if (size < 0) { - LINFO(curlun, "unable to find file size: %s\n", filename); - rc = (int) size; - goto out; - } - num_sectors = size >> 9; // File size in 512-byte blocks - min_sectors = 1; - if (mod_data.cdrom) { - num_sectors &= ~3; // Reduce to a multiple of 2048 - min_sectors = 300*4; // Smallest track is 300 frames - if (num_sectors >= 256*60*75*4) { - num_sectors = (256*60*75 - 1) * 4; - LINFO(curlun, "file too big: %s\n", filename); - LINFO(curlun, "using only first %d blocks\n", - (int) num_sectors); - } - } - if (num_sectors < min_sectors) { - LINFO(curlun, "file too small: %s\n", filename); - rc = -ETOOSMALL; - goto out; - } - - get_file(filp); - curlun->ro = ro; - curlun->filp = filp; - curlun->file_length = size; - curlun->num_sectors = num_sectors; - LDBG(curlun, "open backing file: %s\n", filename); - rc = 0; - -out: - filp_close(filp, current->files); - return rc; -} - - -static void close_backing_file(struct lun *curlun) -{ - if (curlun->filp) { - LDBG(curlun, "close backing file\n"); - fput(curlun->filp); - curlun->filp = NULL; - } -} - - -static ssize_t show_ro(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct lun *curlun = dev_to_lun(dev); - - return sprintf(buf, "%d\n", curlun->ro); -} - -static ssize_t show_file(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lun *curlun = dev_to_lun(dev); - struct fsg_dev *fsg = dev_get_drvdata(dev); - char *p; - ssize_t rc; - - down_read(&fsg->filesem); - if (backing_file_is_open(curlun)) { // Get the complete pathname - p = d_path(&curlun->filp->f_path, buf, PAGE_SIZE - 1); - if (IS_ERR(p)) - rc = PTR_ERR(p); - else { - rc = strlen(p); - memmove(buf, p, rc); - buf[rc] = '\n'; // Add a newline - buf[++rc] = 0; - } - } else { // No file, return 0 bytes - *buf = 0; - rc = 0; - } - up_read(&fsg->filesem); - return rc; -} - - -static ssize_t store_ro(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - ssize_t rc = count; - struct lun *curlun = dev_to_lun(dev); - struct fsg_dev *fsg = dev_get_drvdata(dev); - int i; - - if (sscanf(buf, "%d", &i) != 1) - return -EINVAL; - - /* Allow the write-enable status to change only while the backing file - * is closed. */ - down_read(&fsg->filesem); - if (backing_file_is_open(curlun)) { - LDBG(curlun, "read-only status change prevented\n"); - rc = -EBUSY; - } else { - curlun->ro = !!i; - LDBG(curlun, "read-only status set to %d\n", curlun->ro); - } - up_read(&fsg->filesem); - return rc; -} - -static ssize_t store_file(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct lun *curlun = dev_to_lun(dev); - struct fsg_dev *fsg = dev_get_drvdata(dev); - int rc = 0; - - if (curlun->prevent_medium_removal && backing_file_is_open(curlun)) { - LDBG(curlun, "eject attempt prevented\n"); - return -EBUSY; // "Door is locked" - } - - /* Remove a trailing newline */ - if (count > 0 && buf[count-1] == '\n') - ((char *) buf)[count-1] = 0; // Ugh! - - /* Eject current medium */ - down_write(&fsg->filesem); - if (backing_file_is_open(curlun)) { - close_backing_file(curlun); - curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; - } - - /* Load new medium */ - if (count > 0 && buf[0]) { - rc = open_backing_file(curlun, buf); - if (rc == 0) - curlun->unit_attention_data = - SS_NOT_READY_TO_READY_TRANSITION; - } - up_write(&fsg->filesem); - return (rc < 0 ? rc : count); -} - /* The write permissions and store_xxx pointers are set in fsg_bind() */ -static DEVICE_ATTR(ro, 0444, show_ro, NULL); -static DEVICE_ATTR(file, 0444, show_file, NULL); +static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL); +static DEVICE_ATTR(file, 0444, fsg_show_file, NULL); /*-------------------------------------------------------------------------*/ @@ -3804,7 +3141,9 @@ static void fsg_release(struct kref *ref) static void lun_release(struct device *dev) { - struct fsg_dev *fsg = dev_get_drvdata(dev); + struct rw_semaphore *filesem = dev_get_drvdata(dev); + struct fsg_dev *fsg = + container_of(filesem, struct fsg_dev, filesem); kref_put(&fsg->ref, fsg_release); } @@ -3813,7 +3152,7 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) { struct fsg_dev *fsg = get_gadget_data(gadget); int i; - struct lun *curlun; + struct fsg_lun *curlun; struct usb_request *req = fsg->ep0req; DBG(fsg, "unbind\n"); @@ -3825,7 +3164,7 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) if (curlun->registered) { device_remove_file(&curlun->dev, &dev_attr_ro); device_remove_file(&curlun->dev, &dev_attr_file); - close_backing_file(curlun); + fsg_lun_close(curlun); device_unregister(&curlun->dev); curlun->registered = 0; } @@ -3841,7 +3180,7 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) } /* Free the data buffers */ - for (i = 0; i < NUM_BUFFERS; ++i) + for (i = 0; i < FSG_NUM_BUFFERS; ++i) kfree(fsg->buffhds[i].buf); /* Free the request and buffer for endpoint 0 */ @@ -3948,7 +3287,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) struct fsg_dev *fsg = the_fsg; int rc; int i; - struct lun *curlun; + struct fsg_lun *curlun; struct usb_ep *ep; struct usb_request *req; char *pathbuf, *p; @@ -3963,10 +3302,10 @@ static int __init fsg_bind(struct usb_gadget *gadget) if (mod_data.removable) { // Enable the store_xxx attributes dev_attr_file.attr.mode = 0644; - dev_attr_file.store = store_file; + dev_attr_file.store = fsg_store_file; if (!mod_data.cdrom) { dev_attr_ro.attr.mode = 0644; - dev_attr_ro.store = store_ro; + dev_attr_ro.store = fsg_store_ro; } } @@ -3974,7 +3313,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) i = mod_data.nluns; if (i == 0) i = max(mod_data.num_filenames, 1u); - if (i > MAX_LUNS) { + if (i > FSG_MAX_LUNS) { ERROR(fsg, "invalid number of LUNs: %d\n", i); rc = -EINVAL; goto out; @@ -3982,7 +3321,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) /* Create the LUNs, open their backing files, and register the * LUN devices in sysfs. */ - fsg->luns = kzalloc(i * sizeof(struct lun), GFP_KERNEL); + fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL); if (!fsg->luns) { rc = -ENOMEM; goto out; @@ -3991,13 +3330,14 @@ static int __init fsg_bind(struct usb_gadget *gadget) for (i = 0; i < fsg->nluns; ++i) { curlun = &fsg->luns[i]; - curlun->ro = mod_data.ro[i]; - if (mod_data.cdrom) - curlun->ro = 1; + curlun->cdrom = !!mod_data.cdrom; + curlun->ro = mod_data.cdrom || mod_data.ro[i]; + curlun->initially_ro = curlun->ro; + curlun->removable = mod_data.removable; curlun->dev.release = lun_release; curlun->dev.parent = &gadget->dev; curlun->dev.driver = &fsg_driver.driver; - dev_set_drvdata(&curlun->dev, fsg); + dev_set_drvdata(&curlun->dev, &fsg->filesem); dev_set_name(&curlun->dev,"%s-lun%d", dev_name(&gadget->dev), i); @@ -4016,7 +3356,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) kref_get(&fsg->ref); if (mod_data.file[i] && *mod_data.file[i]) { - if ((rc = open_backing_file(curlun, + if ((rc = fsg_lun_open(curlun, mod_data.file[i])) != 0) goto out; } else if (!mod_data.removable) { @@ -4028,20 +3368,20 @@ static int __init fsg_bind(struct usb_gadget *gadget) /* Find all the endpoints we will use */ usb_ep_autoconfig_reset(gadget); - ep = usb_ep_autoconfig(gadget, &fs_bulk_in_desc); + ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc); if (!ep) goto autoconf_fail; ep->driver_data = fsg; // claim the endpoint fsg->bulk_in = ep; - ep = usb_ep_autoconfig(gadget, &fs_bulk_out_desc); + ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc); if (!ep) goto autoconf_fail; ep->driver_data = fsg; // claim the endpoint fsg->bulk_out = ep; if (transport_is_cbi()) { - ep = usb_ep_autoconfig(gadget, &fs_intr_in_desc); + ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc); if (!ep) goto autoconf_fail; ep->driver_data = fsg; // claim the endpoint @@ -4055,28 +3395,28 @@ static int __init fsg_bind(struct usb_gadget *gadget) device_desc.bcdDevice = cpu_to_le16(mod_data.release); i = (transport_is_cbi() ? 3 : 2); // Number of endpoints - intf_desc.bNumEndpoints = i; - intf_desc.bInterfaceSubClass = mod_data.protocol_type; - intf_desc.bInterfaceProtocol = mod_data.transport_type; - fs_function[i + FS_FUNCTION_PRE_EP_ENTRIES] = NULL; + fsg_intf_desc.bNumEndpoints = i; + fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type; + fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type; + fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL; if (gadget_is_dualspeed(gadget)) { - hs_function[i + HS_FUNCTION_PRE_EP_ENTRIES] = NULL; + fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL; /* Assume ep0 uses the same maxpacket value for both speeds */ dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket; /* Assume endpoint addresses are the same for both speeds */ - hs_bulk_in_desc.bEndpointAddress = - fs_bulk_in_desc.bEndpointAddress; - hs_bulk_out_desc.bEndpointAddress = - fs_bulk_out_desc.bEndpointAddress; - hs_intr_in_desc.bEndpointAddress = - fs_intr_in_desc.bEndpointAddress; + fsg_hs_bulk_in_desc.bEndpointAddress = + fsg_fs_bulk_in_desc.bEndpointAddress; + fsg_hs_bulk_out_desc.bEndpointAddress = + fsg_fs_bulk_out_desc.bEndpointAddress; + fsg_hs_intr_in_desc.bEndpointAddress = + fsg_fs_intr_in_desc.bEndpointAddress; } if (gadget_is_otg(gadget)) - otg_desc.bmAttributes |= USB_OTG_HNP; + fsg_otg_desc.bmAttributes |= USB_OTG_HNP; rc = -ENOMEM; @@ -4090,7 +3430,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) req->complete = ep0_complete; /* Allocate the data buffers */ - for (i = 0; i < NUM_BUFFERS; ++i) { + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { struct fsg_buffhd *bh = &fsg->buffhds[i]; /* Allocate for the bulk-in endpoint. We assume that @@ -4101,23 +3441,24 @@ static int __init fsg_bind(struct usb_gadget *gadget) goto out; bh->next = bh + 1; } - fsg->buffhds[NUM_BUFFERS - 1].next = &fsg->buffhds[0]; + fsg->buffhds[FSG_NUM_BUFFERS - 1].next = &fsg->buffhds[0]; /* This should reflect the actual gadget power source */ usb_gadget_set_selfpowered(gadget); - snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", + snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer, + "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); /* On a real device, serial[] would be loaded from permanent * storage. We just encode it from the driver version string. */ - for (i = 0; i < sizeof(serial) - 2; i += 2) { + for (i = 0; i < sizeof fsg_string_serial - 2; i += 2) { unsigned char c = DRIVER_VERSION[i / 2]; if (!c) break; - sprintf(&serial[i], "%02X", c); + sprintf(&fsg_string_serial[i], "%02X", c); } fsg->thread_task = kthread_create(fsg_main_thread, fsg, @@ -4133,7 +3474,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); for (i = 0; i < fsg->nluns; ++i) { curlun = &fsg->luns[i]; - if (backing_file_is_open(curlun)) { + if (fsg_lun_is_open(curlun)) { p = NULL; if (pathbuf) { p = d_path(&curlun->filp->f_path, @@ -4203,7 +3544,7 @@ static struct usb_gadget_driver fsg_driver = { #else .speed = USB_SPEED_FULL, #endif - .function = (char *) longname, + .function = (char *) fsg_string_product, .bind = fsg_bind, .unbind = fsg_unbind, .disconnect = fsg_disconnect, @@ -4212,7 +3553,7 @@ static struct usb_gadget_driver fsg_driver = { .resume = fsg_resume, .driver = { - .name = (char *) shortname, + .name = DRIVER_NAME, .owner = THIS_MODULE, // .release = ... // .suspend = ... diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/fsl_qe_udc.h index 31b2710882e43d8db4063852c985b8905baefce9..bea5b827bebeb7e48eb468818eb6e19ce69b4780 100644 --- a/drivers/usb/gadget/fsl_qe_udc.h +++ b/drivers/usb/gadget/fsl_qe_udc.h @@ -419,19 +419,4 @@ struct qe_udc { #define CPM_USB_RESTART_TX_OPCODE 0x0b #define CPM_USB_EP_SHIFT 5 -#ifndef CONFIG_CPM -inline int cpm_command(u32 command, u8 opcode) -{ - return -EOPNOTSUPP; -} -#endif - -#ifndef CONFIG_QUICC_ENGINE -inline int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, - u32 cmd_input) -{ - return -EOPNOTSUPP; -} -#endif - #endif /* __FSL_QE_UDC_H */ diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c new file mode 100644 index 0000000000000000000000000000000000000000..19619fbf20ace5b4673520a2d0219996dc7f446f --- /dev/null +++ b/drivers/usb/gadget/mass_storage.c @@ -0,0 +1,240 @@ +/* + * mass_storage.c -- Mass Storage USB Gadget + * + * Copyright (C) 2003-2008 Alan Stern + * Copyright (C) 2009 Samsung Electronics + * Author: Michal Nazarewicz + * 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 Mass Storage Gadget acts as a USB Mass Storage device, + * appearing to the host as a disk drive or as a CD-ROM drive. In + * addition to providing an example of a genuinely useful gadget + * driver for a USB device, it also illustrates a technique of + * double-buffering for increased throughput. Last but not least, it + * gives an easy way to probe the behavior of the Mass Storage drivers + * in a USB host. + * + * Since this file serves only administrative purposes and all the + * business logic is implemented in f_mass_storage.* file. Read + * comments in this file for more detailed description. + */ + + +#include +#include +#include + + +/*-------------------------------------------------------------------------*/ + +#define DRIVER_DESC "Mass Storage Gadget" +#define DRIVER_VERSION "2009/09/11" + +/*-------------------------------------------------------------------------*/ + +/* + * kbuild is not very cooperative with respect to linking separately + * compiled library objects into one module. So for now we won't use + * separate compilation ... ensuring init/exit sections work to shrink + * the runtime footprint, and giving us at least some parts of what + * a "gcc --combine ... part1.c part2.c part3.c ... " build would. + */ + +#include "composite.c" +#include "usbstring.c" +#include "config.c" +#include "epautoconf.c" +#include "f_mass_storage.c" + +/*-------------------------------------------------------------------------*/ + +static struct usb_device_descriptor msg_device_desc = { + .bLength = sizeof msg_device_desc, + .bDescriptorType = USB_DT_DEVICE, + + .bcdUSB = cpu_to_le16(0x0200), + .bDeviceClass = USB_CLASS_PER_INTERFACE, + + /* Vendor and product id can be overridden by module parameters. */ + .idVendor = cpu_to_le16(FSG_VENDOR_ID), + .idProduct = cpu_to_le16(FSG_PRODUCT_ID), + /* .bcdDevice = f(hardware) */ + /* .iManufacturer = DYNAMIC */ + /* .iProduct = DYNAMIC */ + /* NO SERIAL NUMBER */ + .bNumConfigurations = 1, +}; + +static struct usb_otg_descriptor otg_descriptor = { + .bLength = sizeof otg_descriptor, + .bDescriptorType = USB_DT_OTG, + + /* REVISIT SRP-only hardware is possible, although + * it would not be called "OTG" ... + */ + .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, +}; + +static const struct usb_descriptor_header *otg_desc[] = { + (struct usb_descriptor_header *) &otg_descriptor, + NULL, +}; + + +/* string IDs are assigned dynamically */ + +#define STRING_MANUFACTURER_IDX 0 +#define STRING_PRODUCT_IDX 1 +#define STRING_CONFIGURATION_IDX 2 + +static char manufacturer[50]; + +static struct usb_string strings_dev[] = { + [STRING_MANUFACTURER_IDX].s = manufacturer, + [STRING_PRODUCT_IDX].s = DRIVER_DESC, + [STRING_CONFIGURATION_IDX].s = "Self Powered", + { } /* end of list */ +}; + +static struct usb_gadget_strings stringtab_dev = { + .language = 0x0409, /* en-us */ + .strings = strings_dev, +}; + +static struct usb_gadget_strings *dev_strings[] = { + &stringtab_dev, + NULL, +}; + + + +/****************************** Configurations ******************************/ + +static struct fsg_module_parameters mod_data = { + .stall = 1 +}; +FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); + +static unsigned long msg_registered = 0; +static void msg_cleanup(void); + +static int __init msg_do_config(struct usb_configuration *c) +{ + struct fsg_common *common; + struct fsg_config config; + int ret; + + if (gadget_is_otg(c->cdev->gadget)) { + c->descriptors = otg_desc; + c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + + fsg_config_from_params(&config, &mod_data); + config.thread_exits = (void(*)(struct fsg_common*))&msg_cleanup; + common = fsg_common_init(0, c->cdev, &config); + if (IS_ERR(common)) + return PTR_ERR(common); + + ret = fsg_add(c->cdev, c, common); + fsg_common_put(common); + return ret; +} + +static struct usb_configuration msg_config_driver = { + .label = "Linux File-Backed Storage", + .bind = msg_do_config, + .bConfigurationValue = 1, + /* .iConfiguration = DYNAMIC */ + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, +}; + + + +/****************************** Gadget Bind ******************************/ + + +static int __init msg_bind(struct usb_composite_dev *cdev) +{ + struct usb_gadget *gadget = cdev->gadget; + int status; + + /* Allocate string descriptor numbers ... note that string + * contents can be overridden by the composite_dev glue. + */ + + /* device descriptor strings: manufacturer, product */ + snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", + init_utsname()->sysname, init_utsname()->release, + gadget->name); + status = usb_string_id(cdev); + if (status < 0) + return status; + strings_dev[STRING_MANUFACTURER_IDX].id = status; + msg_device_desc.iManufacturer = status; + + status = usb_string_id(cdev); + if (status < 0) + return status; + strings_dev[STRING_PRODUCT_IDX].id = status; + msg_device_desc.iProduct = status; + + status = usb_string_id(cdev); + if (status < 0) + return status; + strings_dev[STRING_CONFIGURATION_IDX].id = status; + msg_config_driver.iConfiguration = status; + + /* register our second configuration */ + status = usb_add_config(cdev, &msg_config_driver); + if (status < 0) + return status; + + dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); + set_bit(0, &msg_registered); + return 0; +} + + +/****************************** Some noise ******************************/ + + +static struct usb_composite_driver msg_driver = { + .name = "g_mass_storage", + .dev = &msg_device_desc, + .strings = dev_strings, + .bind = msg_bind, +}; + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Michal Nazarewicz"); +MODULE_LICENSE("GPL"); + +static int __init msg_init(void) +{ + return usb_composite_register(&msg_driver); +} +module_init(msg_init); + +static void msg_cleanup(void) +{ + if (test_and_clear_bit(0, &msg_registered)) + usb_composite_unregister(&msg_driver); +} +module_exit(msg_cleanup); diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c new file mode 100644 index 0000000000000000000000000000000000000000..429560100b10fc048a9e6c92d65efeac51effe20 --- /dev/null +++ b/drivers/usb/gadget/multi.c @@ -0,0 +1,358 @@ +/* + * multi.c -- Multifunction Composite driver + * + * Copyright (C) 2008 David Brownell + * Copyright (C) 2008 Nokia Corporation + * Copyright (C) 2009 Samsung Electronics + * Author: Michal Nazarewicz (m.nazarewicz@samsung.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 + + +#if defined USB_ETH_RNDIS +# undef USB_ETH_RNDIS +#endif +#ifdef CONFIG_USB_ETH_RNDIS +# define USB_ETH_RNDIS y +#endif + + +#define DRIVER_DESC "Multifunction Composite Gadget" +#define DRIVER_VERSION "2009/07/21" + +/*-------------------------------------------------------------------------*/ + +#define MULTI_VENDOR_NUM 0x0525 /* XXX NetChip */ +#define MULTI_PRODUCT_NUM 0xa4ab /* XXX */ + +/*-------------------------------------------------------------------------*/ + +/* + * kbuild is not very cooperative with respect to linking separately + * compiled library objects into one module. So for now we won't use + * separate compilation ... ensuring init/exit sections work to shrink + * the runtime footprint, and giving us at least some parts of what + * a "gcc --combine ... part1.c part2.c part3.c ... " build would. + */ + +#include "composite.c" +#include "usbstring.c" +#include "config.c" +#include "epautoconf.c" + +#include "u_serial.c" +#include "f_acm.c" + +#include "f_ecm.c" +#include "f_subset.c" +#ifdef USB_ETH_RNDIS +# include "f_rndis.c" +# include "rndis.c" +#endif +#include "u_ether.c" + +#undef DBG /* u_ether.c has broken idea about macros */ +#undef VDBG /* so clean up after it */ +#undef ERROR +#undef INFO +#include "f_mass_storage.c" + +/*-------------------------------------------------------------------------*/ + +static struct usb_device_descriptor device_desc = { + .bLength = sizeof device_desc, + .bDescriptorType = USB_DT_DEVICE, + + .bcdUSB = cpu_to_le16(0x0200), + + /* .bDeviceClass = USB_CLASS_COMM, */ + /* .bDeviceSubClass = 0, */ + /* .bDeviceProtocol = 0, */ + .bDeviceClass = 0xEF, + .bDeviceSubClass = 2, + .bDeviceProtocol = 1, + /* .bMaxPacketSize0 = f(hardware) */ + + /* Vendor and product id can be overridden by module parameters. */ + .idVendor = cpu_to_le16(MULTI_VENDOR_NUM), + .idProduct = cpu_to_le16(MULTI_PRODUCT_NUM), + /* .bcdDevice = f(hardware) */ + /* .iManufacturer = DYNAMIC */ + /* .iProduct = DYNAMIC */ + /* NO SERIAL NUMBER */ + .bNumConfigurations = 1, +}; + +static struct usb_otg_descriptor otg_descriptor = { + .bLength = sizeof otg_descriptor, + .bDescriptorType = USB_DT_OTG, + + /* REVISIT SRP-only hardware is possible, although + * it would not be called "OTG" ... + */ + .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, +}; + +static const struct usb_descriptor_header *otg_desc[] = { + (struct usb_descriptor_header *) &otg_descriptor, + NULL, +}; + + +/* string IDs are assigned dynamically */ + +#define STRING_MANUFACTURER_IDX 0 +#define STRING_PRODUCT_IDX 1 + +static char manufacturer[50]; + +static struct usb_string strings_dev[] = { + [STRING_MANUFACTURER_IDX].s = manufacturer, + [STRING_PRODUCT_IDX].s = DRIVER_DESC, + { } /* end of list */ +}; + +static struct usb_gadget_strings stringtab_dev = { + .language = 0x0409, /* en-us */ + .strings = strings_dev, +}; + +static struct usb_gadget_strings *dev_strings[] = { + &stringtab_dev, + NULL, +}; + +static u8 hostaddr[ETH_ALEN]; + + + +/****************************** Configurations ******************************/ + +static struct fsg_module_parameters mod_data = { + .stall = 1 +}; +FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); + +static struct fsg_common *fsg_common; + + +#ifdef USB_ETH_RNDIS + +static int __init rndis_do_config(struct usb_configuration *c) +{ + int ret; + + if (gadget_is_otg(c->cdev->gadget)) { + c->descriptors = otg_desc; + c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + + ret = rndis_bind_config(c, hostaddr); + if (ret < 0) + return ret; + + ret = acm_bind_config(c, 0); + if (ret < 0) + return ret; + + ret = fsg_add(c->cdev, c, fsg_common); + if (ret < 0) + return ret; + + return 0; +} + +static struct usb_configuration rndis_config_driver = { + .label = "Multifunction Composite (RNDIS + MS + ACM)", + .bind = rndis_do_config, + .bConfigurationValue = 2, + /* .iConfiguration = DYNAMIC */ + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, +}; + +#endif + +#ifdef CONFIG_USB_G_MULTI_CDC + +static int __init cdc_do_config(struct usb_configuration *c) +{ + int ret; + + if (gadget_is_otg(c->cdev->gadget)) { + c->descriptors = otg_desc; + c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + + ret = ecm_bind_config(c, hostaddr); + if (ret < 0) + return ret; + + ret = acm_bind_config(c, 0); + if (ret < 0) + return ret; + + ret = fsg_add(c->cdev, c, fsg_common); + if (ret < 0) + return ret; + if (ret < 0) + return ret; + + return 0; +} + +static struct usb_configuration cdc_config_driver = { + .label = "Multifunction Composite (CDC + MS + ACM)", + .bind = cdc_do_config, + .bConfigurationValue = 1, + /* .iConfiguration = DYNAMIC */ + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, +}; + +#endif + + + +/****************************** Gadget Bind ******************************/ + + +static int __init multi_bind(struct usb_composite_dev *cdev) +{ + struct usb_gadget *gadget = cdev->gadget; + int status, gcnum; + + if (!can_support_ecm(cdev->gadget)) { + dev_err(&gadget->dev, "controller '%s' not usable\n", + gadget->name); + return -EINVAL; + } + + /* set up network link layer */ + status = gether_setup(cdev->gadget, hostaddr); + if (status < 0) + return status; + + /* set up serial link layer */ + status = gserial_setup(cdev->gadget, 1); + if (status < 0) + goto fail0; + + /* set up mass storage function */ + fsg_common = fsg_common_from_params(0, cdev, &mod_data); + if (IS_ERR(fsg_common)) { + status = PTR_ERR(fsg_common); + goto fail1; + } + + + gcnum = usb_gadget_controller_number(gadget); + if (gcnum >= 0) + device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); + else { + /* We assume that can_support_ecm() tells the truth; + * but if the controller isn't recognized at all then + * that assumption is a bit more likely to be wrong. + */ + WARNING(cdev, "controller '%s' not recognized\n", + gadget->name); + device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099); + } + + + /* Allocate string descriptor numbers ... note that string + * contents can be overridden by the composite_dev glue. + */ + + /* device descriptor strings: manufacturer, product */ + snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", + init_utsname()->sysname, init_utsname()->release, + gadget->name); + status = usb_string_id(cdev); + if (status < 0) + goto fail2; + strings_dev[STRING_MANUFACTURER_IDX].id = status; + device_desc.iManufacturer = status; + + status = usb_string_id(cdev); + if (status < 0) + goto fail2; + strings_dev[STRING_PRODUCT_IDX].id = status; + device_desc.iProduct = status; + +#ifdef USB_ETH_RNDIS + /* register our first configuration */ + status = usb_add_config(cdev, &rndis_config_driver); + if (status < 0) + goto fail2; +#endif + +#ifdef CONFIG_USB_G_MULTI_CDC + /* register our second configuration */ + status = usb_add_config(cdev, &cdc_config_driver); + if (status < 0) + goto fail2; +#endif + + dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); + fsg_common_put(fsg_common); + return 0; + +fail2: + fsg_common_put(fsg_common); +fail1: + gserial_cleanup(); +fail0: + gether_cleanup(); + return status; +} + +static int __exit multi_unbind(struct usb_composite_dev *cdev) +{ + gserial_cleanup(); + gether_cleanup(); + return 0; +} + + +/****************************** Some noise ******************************/ + + +static struct usb_composite_driver multi_driver = { + .name = "g_multi", + .dev = &device_desc, + .strings = dev_strings, + .bind = multi_bind, + .unbind = __exit_p(multi_unbind), +}; + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Michal Nazarewicz"); +MODULE_LICENSE("GPL"); + +static int __init g_multi_init(void) +{ + return usb_composite_register(&multi_driver); +} +module_init(g_multi_init); + +static void __exit g_multi_cleanup(void) +{ + usb_composite_unregister(&multi_driver); +} +module_exit(g_multi_cleanup); diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c new file mode 100644 index 0000000000000000000000000000000000000000..868d8ee86756671192a2fd1e93c866ae06121229 --- /dev/null +++ b/drivers/usb/gadget/storage_common.c @@ -0,0 +1,778 @@ +/* + * storage_common.c -- Common definitions for mass storage functionality + * + * Copyright (C) 2003-2008 Alan Stern + * Copyeight (C) 2009 Samsung Electronics + * Author: Michal Nazarewicz (m.nazarewicz@samsung.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 + */ + + +/* + * This file requires the following identifiers used in USB strings to + * be defined (each of type pointer to char): + * - fsg_string_manufacturer -- name of the manufacturer + * - fsg_string_product -- name of the product + * - fsg_string_serial -- product's serial + * - fsg_string_config -- name of the configuration + * - fsg_string_interface -- name of the interface + * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS + * macro is defined prior to including this file. + */ + +/* + * When FSG_NO_INTR_EP is defined fsg_fs_intr_in_desc and + * fsg_hs_intr_in_desc objects as well as + * FSG_FS_FUNCTION_PRE_EP_ENTRIES and FSG_HS_FUNCTION_PRE_EP_ENTRIES + * macros are not defined. + * + * When FSG_NO_DEVICE_STRINGS is defined FSG_STRING_MANUFACTURER, + * FSG_STRING_PRODUCT, FSG_STRING_SERIAL and FSG_STRING_CONFIG are not + * defined (as well as corresponding entries in string tables are + * missing) and FSG_STRING_INTERFACE has value of zero. + * + * When FSG_NO_OTG is defined fsg_otg_desc won't be defined. + */ + +/* + * When FSG_BUFFHD_STATIC_BUFFER is defined when this file is included + * the fsg_buffhd structure's buf field will be an array of FSG_BUFLEN + * characters rather then a pointer to void. + */ + + +#include + + +/* Thanks to NetChip Technologies for donating this product ID. + * + * DO NOT REUSE THESE IDs with any other driver!! Ever!! + * Instead: allocate your own, using normal USB-IF procedures. */ +#define FSG_VENDOR_ID 0x0525 /* NetChip */ +#define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ + + +/*-------------------------------------------------------------------------*/ + + +#ifndef DEBUG +#undef VERBOSE_DEBUG +#undef DUMP_MSGS +#endif /* !DEBUG */ + +#ifdef VERBOSE_DEBUG +#define VLDBG LDBG +#else +#define VLDBG(lun, fmt, args...) do { } while (0) +#endif /* VERBOSE_DEBUG */ + +#define LDBG(lun, fmt, args...) dev_dbg (&(lun)->dev, fmt, ## args) +#define LERROR(lun, fmt, args...) dev_err (&(lun)->dev, fmt, ## args) +#define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args) +#define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args) + +/* Keep those macros in sync with thos in + * include/linux/ubs/composite.h or else GCC will complain. If they + * are identical (the same names of arguments, white spaces in the + * same places) GCC will allow redefinition otherwise (even if some + * white space is removed or added) warning will be issued. No + * checking if those symbols is defined is performed because warning + * is desired when those macros were defined by someone else to mean + * something else. */ +#define DBG(d, fmt, args...) dev_dbg(&(d)->gadget->dev , fmt , ## args) +#define VDBG(d, fmt, args...) dev_vdbg(&(d)->gadget->dev , fmt , ## args) +#define ERROR(d, fmt, args...) dev_err(&(d)->gadget->dev , fmt , ## args) +#define WARNING(d, fmt, args...) dev_warn(&(d)->gadget->dev , fmt , ## args) +#define INFO(d, fmt, args...) dev_info(&(d)->gadget->dev , fmt , ## args) + + + +#ifdef DUMP_MSGS + +# define dump_msg(fsg, /* const char * */ label, \ + /* const u8 * */ buf, /* unsigned */ length) do { \ + if (length < 512) { \ + DBG(fsg, "%s, length %u:\n", label, length); \ + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \ + 16, 1, buf, length, 0); \ + } \ +} while (0) + +# define dump_cdb(fsg) do { } while (0) + +#else + +# define dump_msg(fsg, /* const char * */ label, \ + /* const u8 * */ buf, /* unsigned */ length) do { } while (0) + +# ifdef VERBOSE_DEBUG + +# define dump_cdb(fsg) \ + print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE, \ + 16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0) \ + +# else + +# define dump_cdb(fsg) do { } while (0) + +# endif /* VERBOSE_DEBUG */ + +#endif /* DUMP_MSGS */ + + + + + +/*-------------------------------------------------------------------------*/ + +/* SCSI device types */ +#define TYPE_DISK 0x00 +#define TYPE_CDROM 0x05 + +/* USB protocol value = the transport method */ +#define USB_PR_CBI 0x00 /* Control/Bulk/Interrupt */ +#define USB_PR_CB 0x01 /* Control/Bulk w/o interrupt */ +#define USB_PR_BULK 0x50 /* Bulk-only */ + +/* USB subclass value = the protocol encapsulation */ +#define USB_SC_RBC 0x01 /* Reduced Block Commands (flash) */ +#define USB_SC_8020 0x02 /* SFF-8020i, MMC-2, ATAPI (CD-ROM) */ +#define USB_SC_QIC 0x03 /* QIC-157 (tape) */ +#define USB_SC_UFI 0x04 /* UFI (floppy) */ +#define USB_SC_8070 0x05 /* SFF-8070i (removable) */ +#define USB_SC_SCSI 0x06 /* Transparent SCSI */ + +/* Bulk-only data structures */ + +/* Command Block Wrapper */ +struct fsg_bulk_cb_wrap { + __le32 Signature; /* Contains 'USBC' */ + u32 Tag; /* Unique per command id */ + __le32 DataTransferLength; /* Size of the data */ + u8 Flags; /* Direction in bit 7 */ + u8 Lun; /* LUN (normally 0) */ + u8 Length; /* Of the CDB, <= MAX_COMMAND_SIZE */ + u8 CDB[16]; /* Command Data Block */ +}; + +#define USB_BULK_CB_WRAP_LEN 31 +#define USB_BULK_CB_SIG 0x43425355 /* Spells out USBC */ +#define USB_BULK_IN_FLAG 0x80 + +/* Command Status Wrapper */ +struct bulk_cs_wrap { + __le32 Signature; /* Should = 'USBS' */ + u32 Tag; /* Same as original command */ + __le32 Residue; /* Amount not transferred */ + u8 Status; /* See below */ +}; + +#define USB_BULK_CS_WRAP_LEN 13 +#define USB_BULK_CS_SIG 0x53425355 /* Spells out 'USBS' */ +#define USB_STATUS_PASS 0 +#define USB_STATUS_FAIL 1 +#define USB_STATUS_PHASE_ERROR 2 + +/* Bulk-only class specific requests */ +#define USB_BULK_RESET_REQUEST 0xff +#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe + + +/* CBI Interrupt data structure */ +struct interrupt_data { + u8 bType; + u8 bValue; +}; + +#define CBI_INTERRUPT_DATA_LEN 2 + +/* CBI Accept Device-Specific Command request */ +#define USB_CBI_ADSC_REQUEST 0x00 + + +/* Length of a SCSI Command Data Block */ +#define MAX_COMMAND_SIZE 16 + +/* SCSI commands that we recognize */ +#define SC_FORMAT_UNIT 0x04 +#define SC_INQUIRY 0x12 +#define SC_MODE_SELECT_6 0x15 +#define SC_MODE_SELECT_10 0x55 +#define SC_MODE_SENSE_6 0x1a +#define SC_MODE_SENSE_10 0x5a +#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e +#define SC_READ_6 0x08 +#define SC_READ_10 0x28 +#define SC_READ_12 0xa8 +#define SC_READ_CAPACITY 0x25 +#define SC_READ_FORMAT_CAPACITIES 0x23 +#define SC_READ_HEADER 0x44 +#define SC_READ_TOC 0x43 +#define SC_RELEASE 0x17 +#define SC_REQUEST_SENSE 0x03 +#define SC_RESERVE 0x16 +#define SC_SEND_DIAGNOSTIC 0x1d +#define SC_START_STOP_UNIT 0x1b +#define SC_SYNCHRONIZE_CACHE 0x35 +#define SC_TEST_UNIT_READY 0x00 +#define SC_VERIFY 0x2f +#define SC_WRITE_6 0x0a +#define SC_WRITE_10 0x2a +#define SC_WRITE_12 0xaa + +/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */ +#define SS_NO_SENSE 0 +#define SS_COMMUNICATION_FAILURE 0x040800 +#define SS_INVALID_COMMAND 0x052000 +#define SS_INVALID_FIELD_IN_CDB 0x052400 +#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100 +#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500 +#define SS_MEDIUM_NOT_PRESENT 0x023a00 +#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302 +#define SS_NOT_READY_TO_READY_TRANSITION 0x062800 +#define SS_RESET_OCCURRED 0x062900 +#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900 +#define SS_UNRECOVERED_READ_ERROR 0x031100 +#define SS_WRITE_ERROR 0x030c02 +#define SS_WRITE_PROTECTED 0x072700 + +#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */ +#define ASC(x) ((u8) ((x) >> 8)) +#define ASCQ(x) ((u8) (x)) + + +/*-------------------------------------------------------------------------*/ + + +struct fsg_lun { + struct file *filp; + loff_t file_length; + loff_t num_sectors; + + unsigned int initially_ro:1; + unsigned int ro:1; + unsigned int removable:1; + unsigned int cdrom:1; + unsigned int prevent_medium_removal:1; + unsigned int registered:1; + unsigned int info_valid:1; + + u32 sense_data; + u32 sense_data_info; + u32 unit_attention_data; + + struct device dev; +}; + +#define fsg_lun_is_open(curlun) ((curlun)->filp != NULL) + +static struct fsg_lun *fsg_lun_from_dev(struct device *dev) +{ + return container_of(dev, struct fsg_lun, dev); +} + + +/* Big enough to hold our biggest descriptor */ +#define EP0_BUFSIZE 256 +#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */ + +/* Number of buffers we will use. 2 is enough for double-buffering */ +#define FSG_NUM_BUFFERS 2 + +/* Default size of buffer length. */ +#define FSG_BUFLEN ((u32)16384) + +/* Maximal number of LUNs supported in mass storage function */ +#define FSG_MAX_LUNS 8 + +enum fsg_buffer_state { + BUF_STATE_EMPTY = 0, + BUF_STATE_FULL, + BUF_STATE_BUSY +}; + +struct fsg_buffhd { +#ifdef FSG_BUFFHD_STATIC_BUFFER + char buf[FSG_BUFLEN]; +#else + void *buf; +#endif + enum fsg_buffer_state state; + struct fsg_buffhd *next; + + /* The NetChip 2280 is faster, and handles some protocol faults + * better, if we don't submit any short bulk-out read requests. + * So we will record the intended request length here. */ + unsigned int bulk_out_intended_length; + + struct usb_request *inreq; + int inreq_busy; + struct usb_request *outreq; + int outreq_busy; +}; + +enum fsg_state { + /* This one isn't used anywhere */ + FSG_STATE_COMMAND_PHASE = -10, + FSG_STATE_DATA_PHASE, + FSG_STATE_STATUS_PHASE, + + FSG_STATE_IDLE = 0, + FSG_STATE_ABORT_BULK_OUT, + FSG_STATE_RESET, + FSG_STATE_INTERFACE_CHANGE, + FSG_STATE_CONFIG_CHANGE, + FSG_STATE_DISCONNECT, + FSG_STATE_EXIT, + FSG_STATE_TERMINATED +}; + +enum data_direction { + DATA_DIR_UNKNOWN = 0, + DATA_DIR_FROM_HOST, + DATA_DIR_TO_HOST, + DATA_DIR_NONE +}; + + +/*-------------------------------------------------------------------------*/ + + +static inline u32 get_unaligned_be24(u8 *buf) +{ + return 0xffffff & (u32) get_unaligned_be32(buf - 1); +} + + +/*-------------------------------------------------------------------------*/ + + +enum { +#ifndef FSG_NO_DEVICE_STRINGS + FSG_STRING_MANUFACTURER = 1, + FSG_STRING_PRODUCT, + FSG_STRING_SERIAL, + FSG_STRING_CONFIG, +#endif + FSG_STRING_INTERFACE +}; + + +#ifndef FSG_NO_OTG +static struct usb_otg_descriptor +fsg_otg_desc = { + .bLength = sizeof fsg_otg_desc, + .bDescriptorType = USB_DT_OTG, + + .bmAttributes = USB_OTG_SRP, +}; +#endif + +/* There is only one interface. */ + +static struct usb_interface_descriptor +fsg_intf_desc = { + .bLength = sizeof fsg_intf_desc, + .bDescriptorType = USB_DT_INTERFACE, + + .bNumEndpoints = 2, /* Adjusted during fsg_bind() */ + .bInterfaceClass = USB_CLASS_MASS_STORAGE, + .bInterfaceSubClass = USB_SC_SCSI, /* Adjusted during fsg_bind() */ + .bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */ + .iInterface = FSG_STRING_INTERFACE, +}; + +/* Three full-speed endpoint descriptors: bulk-in, bulk-out, + * and interrupt-in. */ + +static struct usb_endpoint_descriptor +fsg_fs_bulk_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + /* wMaxPacketSize set by autoconfiguration */ +}; + +static struct usb_endpoint_descriptor +fsg_fs_bulk_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + /* wMaxPacketSize set by autoconfiguration */ +}; + +#ifndef FSG_NO_INTR_EP + +static struct usb_endpoint_descriptor +fsg_fs_intr_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(2), + .bInterval = 32, /* frames -> 32 ms */ +}; + +#ifndef FSG_NO_OTG +# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 2 +#else +# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 1 +#endif + +#endif + +static struct usb_descriptor_header *fsg_fs_function[] = { +#ifndef FSG_NO_OTG + (struct usb_descriptor_header *) &fsg_otg_desc, +#endif + (struct usb_descriptor_header *) &fsg_intf_desc, + (struct usb_descriptor_header *) &fsg_fs_bulk_in_desc, + (struct usb_descriptor_header *) &fsg_fs_bulk_out_desc, +#ifndef FSG_NO_INTR_EP + (struct usb_descriptor_header *) &fsg_fs_intr_in_desc, +#endif + NULL, +}; + + +/* + * USB 2.0 devices need to expose both high speed and full speed + * descriptors, unless they only run at full speed. + * + * That means alternate endpoint descriptors (bigger packets) + * and a "device qualifier" ... plus more construction options + * for the config descriptor. + */ +static struct usb_endpoint_descriptor +fsg_hs_bulk_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(512), +}; + +static struct usb_endpoint_descriptor +fsg_hs_bulk_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(512), + .bInterval = 1, /* NAK every 1 uframe */ +}; + +#ifndef FSG_NO_INTR_EP + +static struct usb_endpoint_descriptor +fsg_hs_intr_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(2), + .bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */ +}; + +#ifndef FSG_NO_OTG +# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 2 +#else +# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 1 +#endif + +#endif + +static struct usb_descriptor_header *fsg_hs_function[] = { +#ifndef FSG_NO_OTG + (struct usb_descriptor_header *) &fsg_otg_desc, +#endif + (struct usb_descriptor_header *) &fsg_intf_desc, + (struct usb_descriptor_header *) &fsg_hs_bulk_in_desc, + (struct usb_descriptor_header *) &fsg_hs_bulk_out_desc, +#ifndef FSG_NO_INTR_EP + (struct usb_descriptor_header *) &fsg_hs_intr_in_desc, +#endif + NULL, +}; + +/* Maxpacket and other transfer characteristics vary by speed. */ +static struct usb_endpoint_descriptor * +fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, + struct usb_endpoint_descriptor *hs) +{ + if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) + return hs; + return fs; +} + + +/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */ +static struct usb_string fsg_strings[] = { +#ifndef FSG_NO_DEVICE_STRINGS + {FSG_STRING_MANUFACTURER, fsg_string_manufacturer}, + {FSG_STRING_PRODUCT, fsg_string_product}, + {FSG_STRING_SERIAL, fsg_string_serial}, + {FSG_STRING_CONFIG, fsg_string_config}, +#endif + {FSG_STRING_INTERFACE, fsg_string_interface}, + {} +}; + +static struct usb_gadget_strings fsg_stringtab = { + .language = 0x0409, /* en-us */ + .strings = fsg_strings, +}; + + + /*-------------------------------------------------------------------------*/ + +/* If the next two routines are called while the gadget is registered, + * the caller must own fsg->filesem for writing. */ + +static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) +{ + int ro; + struct file *filp = NULL; + int rc = -EINVAL; + struct inode *inode = NULL; + loff_t size; + loff_t num_sectors; + loff_t min_sectors; + + /* R/W if we can, R/O if we must */ + ro = curlun->initially_ro; + if (!ro) { + filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0); + if (-EROFS == PTR_ERR(filp)) + ro = 1; + } + if (ro) + filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0); + if (IS_ERR(filp)) { + LINFO(curlun, "unable to open backing file: %s\n", filename); + return PTR_ERR(filp); + } + + if (!(filp->f_mode & FMODE_WRITE)) + ro = 1; + + if (filp->f_path.dentry) + inode = filp->f_path.dentry->d_inode; + if (inode && S_ISBLK(inode->i_mode)) { + if (bdev_read_only(inode->i_bdev)) + ro = 1; + } else if (!inode || !S_ISREG(inode->i_mode)) { + LINFO(curlun, "invalid file type: %s\n", filename); + goto out; + } + + /* If we can't read the file, it's no good. + * If we can't write the file, use it read-only. */ + if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) { + LINFO(curlun, "file not readable: %s\n", filename); + goto out; + } + if (!(filp->f_op->write || filp->f_op->aio_write)) + ro = 1; + + size = i_size_read(inode->i_mapping->host); + if (size < 0) { + LINFO(curlun, "unable to find file size: %s\n", filename); + rc = (int) size; + goto out; + } + num_sectors = size >> 9; /* File size in 512-byte blocks */ + min_sectors = 1; + if (curlun->cdrom) { + num_sectors &= ~3; /* Reduce to a multiple of 2048 */ + min_sectors = 300*4; /* Smallest track is 300 frames */ + if (num_sectors >= 256*60*75*4) { + num_sectors = (256*60*75 - 1) * 4; + LINFO(curlun, "file too big: %s\n", filename); + LINFO(curlun, "using only first %d blocks\n", + (int) num_sectors); + } + } + if (num_sectors < min_sectors) { + LINFO(curlun, "file too small: %s\n", filename); + rc = -ETOOSMALL; + goto out; + } + + get_file(filp); + curlun->ro = ro; + curlun->filp = filp; + curlun->file_length = size; + curlun->num_sectors = num_sectors; + LDBG(curlun, "open backing file: %s\n", filename); + rc = 0; + +out: + filp_close(filp, current->files); + return rc; +} + + +static void fsg_lun_close(struct fsg_lun *curlun) +{ + if (curlun->filp) { + LDBG(curlun, "close backing file\n"); + fput(curlun->filp); + curlun->filp = NULL; + } +} + + +/*-------------------------------------------------------------------------*/ + +/* Sync the file data, don't bother with the metadata. + * This code was copied from fs/buffer.c:sys_fdatasync(). */ +static int fsg_lun_fsync_sub(struct fsg_lun *curlun) +{ + struct file *filp = curlun->filp; + + if (curlun->ro || !filp) + return 0; + return vfs_fsync(filp, filp->f_path.dentry, 1); +} + +static void store_cdrom_address(u8 *dest, int msf, u32 addr) +{ + if (msf) { + /* Convert to Minutes-Seconds-Frames */ + addr >>= 2; /* Convert to 2048-byte frames */ + addr += 2*75; /* Lead-in occupies 2 seconds */ + dest[3] = addr % 75; /* Frames */ + addr /= 75; + dest[2] = addr % 60; /* Seconds */ + addr /= 60; + dest[1] = addr; /* Minutes */ + dest[0] = 0; /* Reserved */ + } else { + /* Absolute sector */ + put_unaligned_be32(addr, dest); + } +} + + +/*-------------------------------------------------------------------------*/ + + +static ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + + return sprintf(buf, "%d\n", fsg_lun_is_open(curlun) + ? curlun->ro + : curlun->initially_ro); +} + +static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + struct rw_semaphore *filesem = dev_get_drvdata(dev); + char *p; + ssize_t rc; + + down_read(filesem); + if (fsg_lun_is_open(curlun)) { /* Get the complete pathname */ + p = d_path(&curlun->filp->f_path, buf, PAGE_SIZE - 1); + if (IS_ERR(p)) + rc = PTR_ERR(p); + else { + rc = strlen(p); + memmove(buf, p, rc); + buf[rc] = '\n'; /* Add a newline */ + buf[++rc] = 0; + } + } else { /* No file, return 0 bytes */ + *buf = 0; + rc = 0; + } + up_read(filesem); + return rc; +} + + +static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t rc = count; + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + struct rw_semaphore *filesem = dev_get_drvdata(dev); + int i; + + if (sscanf(buf, "%d", &i) != 1) + return -EINVAL; + + /* Allow the write-enable status to change only while the backing file + * is closed. */ + down_read(filesem); + if (fsg_lun_is_open(curlun)) { + LDBG(curlun, "read-only status change prevented\n"); + rc = -EBUSY; + } else { + curlun->ro = !!i; + curlun->initially_ro = !!i; + LDBG(curlun, "read-only status set to %d\n", curlun->ro); + } + up_read(filesem); + return rc; +} + +static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + struct rw_semaphore *filesem = dev_get_drvdata(dev); + int rc = 0; + + if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) { + LDBG(curlun, "eject attempt prevented\n"); + return -EBUSY; /* "Door is locked" */ + } + + /* Remove a trailing newline */ + if (count > 0 && buf[count-1] == '\n') + ((char *) buf)[count-1] = 0; /* Ugh! */ + + /* Eject current medium */ + down_write(filesem); + if (fsg_lun_is_open(curlun)) { + fsg_lun_close(curlun); + curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; + } + + /* Load new medium */ + if (count > 0 && buf[0]) { + rc = fsg_lun_open(curlun, buf); + if (rc == 0) + curlun->unit_attention_data = + SS_NOT_READY_TO_READY_TRANSITION; + } + up_write(filesem); + return (rc < 0 ? rc : count); +} diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h index 91b39ffdf6eacc56b4a56807913bf166d2657398..fd55f450bc0e02e88afb55980c12008a073aacb4 100644 --- a/drivers/usb/gadget/u_ether.h +++ b/drivers/usb/gadget/u_ether.h @@ -112,7 +112,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); int eem_bind_config(struct usb_configuration *c); -#ifdef CONFIG_USB_ETH_RNDIS +#ifdef USB_ETH_RNDIS int rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 9b43b226817f161d89324c965e647b18611e66d2..2678a1624fcce8703ef0f9af61c4a0212a4ebb36 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -90,14 +90,25 @@ config USB_EHCI_TT_NEWSCHED config USB_EHCI_BIG_ENDIAN_MMIO bool - depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX) + depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX) default y config USB_EHCI_BIG_ENDIAN_DESC bool - depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX) + depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX) default y +config XPS_USB_HCD_XILINX + bool "Use Xilinx usb host EHCI controller core" + depends on USB_EHCI_HCD && (PPC32 || MICROBLAZE) + select USB_EHCI_BIG_ENDIAN_DESC + select USB_EHCI_BIG_ENDIAN_MMIO + ---help--- + Xilinx xps USB host controller core is EHCI compilant and has + transaction translator built-in. It can be configured to either + support both high speed and full speed devices, or high speed + devices only. + config USB_EHCI_FSL bool "Support for Freescale on-chip EHCI USB controller" depends on USB_EHCI_HCD && FSL_SOC @@ -105,6 +116,13 @@ config USB_EHCI_FSL ---help--- Variation of ARC USB block used in some Freescale chips. +config USB_EHCI_MXC + bool "Support for Freescale on-chip EHCI USB controller" + depends on USB_EHCI_HCD && ARCH_MXC + select USB_EHCI_ROOT_HUB_TT + ---help--- + Variation of ARC USB block used in some Freescale chips. + config USB_EHCI_HCD_PPC_OF bool "EHCI support for PPC USB controller on OF platform bus" depends on USB_EHCI_HCD && PPC_OF diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index d8f4aaa616f2774b951fc753682bef07fc7c50d0..5859522d6edd9f0dde4fc8241d5398b0f4381698 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -549,7 +549,7 @@ static int ehci_init(struct usb_hcd *hcd) /* controllers may cache some of the periodic schedule ... */ hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); if (HCC_ISOC_CACHE(hcc_params)) // full frame cache - ehci->i_thresh = 8; + ehci->i_thresh = 2 + 8; else // N microframes cached ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); @@ -605,6 +605,8 @@ static int ehci_init(struct usb_hcd *hcd) } ehci->command = temp; + /* Accept arbitrarily long scatter-gather lists */ + hcd->self.sg_tablesize = ~0; return 0; } @@ -1105,11 +1107,21 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_fsl_driver #endif +#ifdef CONFIG_USB_EHCI_MXC +#include "ehci-mxc.c" +#define PLATFORM_DRIVER ehci_mxc_driver +#endif + #ifdef CONFIG_SOC_AU1200 #include "ehci-au1xxx.c" #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver #endif +#ifdef CONFIG_ARCH_OMAP34XX +#include "ehci-omap.c" +#define PLATFORM_DRIVER ehci_hcd_omap_driver +#endif + #ifdef CONFIG_PPC_PS3 #include "ehci-ps3.c" #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver @@ -1120,6 +1132,11 @@ MODULE_LICENSE ("GPL"); #define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver #endif +#ifdef CONFIG_XPS_USB_HCD_XILINX +#include "ehci-xilinx-of.c" +#define OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver +#endif + #ifdef CONFIG_PLAT_ORION #include "ehci-orion.c" #define PLATFORM_DRIVER ehci_orion_driver diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 1b6f1c0e5cee23c6c62f406c204a655d9b13fe67..2c6571c05f35c99398d973382680137f56363dcb 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -236,7 +236,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) } if (unlikely(ehci->debug)) { - if (ehci->debug && !dbgp_reset_prep()) + if (!dbgp_reset_prep()) ehci->debug = NULL; else dbgp_external_startup(); diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c new file mode 100644 index 0000000000000000000000000000000000000000..35c56f40bdbb1718ce2092800eeb7d5f187b8024 --- /dev/null +++ b/drivers/usb/host/ehci-mxc.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2008 Sascha Hauer , Pengutronix + * Copyright (c) 2009 Daniel Mack + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You 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 + +#define ULPI_VIEWPORT_OFFSET 0x170 +#define PORTSC_OFFSET 0x184 +#define USBMODE_OFFSET 0x1a8 +#define USBMODE_CM_HOST 3 + +struct ehci_mxc_priv { + struct clk *usbclk, *ahbclk; + struct usb_hcd *hcd; +}; + +/* called during probe() after chip reset completes */ +static int ehci_mxc_setup(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int retval; + + /* EHCI registers start at offset 0x100 */ + ehci->caps = hcd->regs + 0x100; + ehci->regs = hcd->regs + 0x100 + + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); + dbg_hcs_params(ehci, "reset"); + dbg_hcc_params(ehci, "reset"); + + /* cache this readonly data; minimize chip reads */ + ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); + + retval = ehci_halt(ehci); + if (retval) + return retval; + + /* data structure init */ + retval = ehci_init(hcd); + if (retval) + return retval; + + hcd->has_tt = 1; + + ehci->sbrn = 0x20; + + ehci_reset(ehci); + + ehci_port_power(ehci, 0); + return 0; +} + +static const struct hc_driver ehci_mxc_hc_driver = { + .description = hcd_name, + .product_desc = "Freescale On-Chip EHCI Host Controller", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_USB2 | HCD_MEMORY, + + /* + * basic lifecycle operations + */ + .reset = ehci_mxc_setup, + .start = ehci_run, + .stop = ehci_stop, + .shutdown = ehci_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, + .bus_suspend = ehci_bus_suspend, + .bus_resume = ehci_bus_resume, + .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, +}; + +static int ehci_mxc_drv_probe(struct platform_device *pdev) +{ + struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; + struct usb_hcd *hcd; + struct resource *res; + int irq, ret, temp; + struct ehci_mxc_priv *priv; + struct device *dev = &pdev->dev; + + dev_info(&pdev->dev, "initializing i.MX USB Controller\n"); + + if (!pdata) { + dev_err(dev, "No platform data given, bailing out.\n"); + return -EINVAL; + } + + irq = platform_get_irq(pdev, 0); + + hcd = usb_create_hcd(&ehci_mxc_hc_driver, dev, dev_name(dev)); + if (!hcd) + return -ENOMEM; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + goto err_alloc; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "Found HC with no register addr. Check setup!\n"); + ret = -ENODEV; + goto err_get_resource; + } + + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + dev_dbg(dev, "controller already in use\n"); + ret = -EBUSY; + goto err_request_mem; + } + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + dev_err(dev, "error mapping memory\n"); + ret = -EFAULT; + goto err_ioremap; + } + + /* enable clocks */ + priv->usbclk = clk_get(dev, "usb"); + if (IS_ERR(priv->usbclk)) { + ret = PTR_ERR(priv->usbclk); + goto err_clk; + } + clk_enable(priv->usbclk); + + if (!cpu_is_mx35()) { + priv->ahbclk = clk_get(dev, "usb_ahb"); + if (IS_ERR(priv->ahbclk)) { + ret = PTR_ERR(priv->ahbclk); + goto err_clk_ahb; + } + clk_enable(priv->ahbclk); + } + + /* set USBMODE to host mode */ + temp = readl(hcd->regs + USBMODE_OFFSET); + writel(temp | USBMODE_CM_HOST, hcd->regs + USBMODE_OFFSET); + + /* set up the PORTSCx register */ + writel(pdata->portsc, hcd->regs + PORTSC_OFFSET); + mdelay(10); + + /* setup USBCONTROL. */ + ret = mxc_set_usbcontrol(pdev->id, pdata->flags); + if (ret < 0) + goto err_init; + + /* call platform specific init function */ + if (pdata->init) { + ret = pdata->init(pdev); + if (ret) { + dev_err(dev, "platform init failed\n"); + goto err_init; + } + } + + /* most platforms need some time to settle changed IO settings */ + mdelay(10); + + /* Initialize the transceiver */ + if (pdata->otg) { + pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET; + if (otg_init(pdata->otg) != 0) + dev_err(dev, "unable to init transceiver\n"); + else if (otg_set_vbus(pdata->otg, 1) != 0) + dev_err(dev, "unable to enable vbus on transceiver\n"); + } + + priv->hcd = hcd; + platform_set_drvdata(pdev, priv); + + ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); + if (ret) + goto err_add; + + return 0; + +err_add: + if (pdata && pdata->exit) + pdata->exit(pdev); +err_init: + if (priv->ahbclk) { + clk_disable(priv->ahbclk); + clk_put(priv->ahbclk); + } +err_clk_ahb: + clk_disable(priv->usbclk); + clk_put(priv->usbclk); +err_clk: + iounmap(hcd->regs); +err_ioremap: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +err_request_mem: +err_get_resource: + kfree(priv); +err_alloc: + usb_put_hcd(hcd); + return ret; +} + +static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) +{ + struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; + struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); + struct usb_hcd *hcd = priv->hcd; + + if (pdata && pdata->exit) + pdata->exit(pdev); + + if (pdata->otg) + otg_shutdown(pdata->otg); + + usb_remove_hcd(hcd); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); + platform_set_drvdata(pdev, NULL); + + clk_disable(priv->usbclk); + clk_put(priv->usbclk); + if (priv->ahbclk) { + clk_disable(priv->ahbclk); + clk_put(priv->ahbclk); + } + + kfree(priv); + + return 0; +} + +static void ehci_mxc_drv_shutdown(struct platform_device *pdev) +{ + struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); + struct usb_hcd *hcd = priv->hcd; + + if (hcd->driver->shutdown) + hcd->driver->shutdown(hcd); +} + +MODULE_ALIAS("platform:mxc-ehci"); + +static struct platform_driver ehci_mxc_driver = { + .probe = ehci_mxc_drv_probe, + .remove = __exit_p(ehci_mxc_drv_remove), + .shutdown = ehci_mxc_drv_shutdown, + .driver = { + .name = "mxc-ehci", + }, +}; diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c new file mode 100644 index 0000000000000000000000000000000000000000..12f1ad2fd0e81282cf3937dc2168822b4f8fc686 --- /dev/null +++ b/drivers/usb/host/ehci-omap.c @@ -0,0 +1,756 @@ +/* + * ehci-omap.c - driver for USBHOST on OMAP 34xx processor + * + * Bus Glue for OMAP34xx USBHOST 3 port EHCI controller + * Tested on OMAP3430 ES2.0 SDP + * + * Copyright (C) 2007-2008 Texas Instruments, Inc. + * Author: Vikram Pandita + * + * Copyright (C) 2009 Nokia Corporation + * Contact: Felipe Balbi + * + * Based on "ehci-fsl.c" and "ehci-au1xxx.c" ehci glue layers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * TODO (last updated Feb 23rd, 2009): + * - add kernel-doc + * - enable AUTOIDLE + * - move DPLL5 programming to clock fw + * - add suspend/resume + * - move workarounds to board-files + */ + +#include +#include +#include +#include + +/* + * OMAP USBHOST Register addresses: VIRTUAL ADDRESSES + * Use ehci_omap_readl()/ehci_omap_writel() functions + */ + +/* TLL Register Set */ +#define OMAP_USBTLL_REVISION (0x00) +#define OMAP_USBTLL_SYSCONFIG (0x10) +#define OMAP_USBTLL_SYSCONFIG_CACTIVITY (1 << 8) +#define OMAP_USBTLL_SYSCONFIG_SIDLEMODE (1 << 3) +#define OMAP_USBTLL_SYSCONFIG_ENAWAKEUP (1 << 2) +#define OMAP_USBTLL_SYSCONFIG_SOFTRESET (1 << 1) +#define OMAP_USBTLL_SYSCONFIG_AUTOIDLE (1 << 0) + +#define OMAP_USBTLL_SYSSTATUS (0x14) +#define OMAP_USBTLL_SYSSTATUS_RESETDONE (1 << 0) + +#define OMAP_USBTLL_IRQSTATUS (0x18) +#define OMAP_USBTLL_IRQENABLE (0x1C) + +#define OMAP_TLL_SHARED_CONF (0x30) +#define OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN (1 << 6) +#define OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN (1 << 5) +#define OMAP_TLL_SHARED_CONF_USB_DIVRATION (1 << 2) +#define OMAP_TLL_SHARED_CONF_FCLK_REQ (1 << 1) +#define OMAP_TLL_SHARED_CONF_FCLK_IS_ON (1 << 0) + +#define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num) +#define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11) +#define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10) +#define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE (1 << 9) +#define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8) +#define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0) + +#define OMAP_TLL_ULPI_FUNCTION_CTRL(num) (0x804 + 0x100 * num) +#define OMAP_TLL_ULPI_INTERFACE_CTRL(num) (0x807 + 0x100 * num) +#define OMAP_TLL_ULPI_OTG_CTRL(num) (0x80A + 0x100 * num) +#define OMAP_TLL_ULPI_INT_EN_RISE(num) (0x80D + 0x100 * num) +#define OMAP_TLL_ULPI_INT_EN_FALL(num) (0x810 + 0x100 * num) +#define OMAP_TLL_ULPI_INT_STATUS(num) (0x813 + 0x100 * num) +#define OMAP_TLL_ULPI_INT_LATCH(num) (0x814 + 0x100 * num) +#define OMAP_TLL_ULPI_DEBUG(num) (0x815 + 0x100 * num) +#define OMAP_TLL_ULPI_SCRATCH_REGISTER(num) (0x816 + 0x100 * num) + +#define OMAP_TLL_CHANNEL_COUNT 3 +#define OMAP_TLL_CHANNEL_1_EN_MASK (1 << 1) +#define OMAP_TLL_CHANNEL_2_EN_MASK (1 << 2) +#define OMAP_TLL_CHANNEL_3_EN_MASK (1 << 4) + +/* UHH Register Set */ +#define OMAP_UHH_REVISION (0x00) +#define OMAP_UHH_SYSCONFIG (0x10) +#define OMAP_UHH_SYSCONFIG_MIDLEMODE (1 << 12) +#define OMAP_UHH_SYSCONFIG_CACTIVITY (1 << 8) +#define OMAP_UHH_SYSCONFIG_SIDLEMODE (1 << 3) +#define OMAP_UHH_SYSCONFIG_ENAWAKEUP (1 << 2) +#define OMAP_UHH_SYSCONFIG_SOFTRESET (1 << 1) +#define OMAP_UHH_SYSCONFIG_AUTOIDLE (1 << 0) + +#define OMAP_UHH_SYSSTATUS (0x14) +#define OMAP_UHH_HOSTCONFIG (0x40) +#define OMAP_UHH_HOSTCONFIG_ULPI_BYPASS (1 << 0) +#define OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS (1 << 0) +#define OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS (1 << 11) +#define OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS (1 << 12) +#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN (1 << 2) +#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN (1 << 3) +#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN (1 << 4) +#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN (1 << 5) +#define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS (1 << 8) +#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9) +#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10) + +#define OMAP_UHH_DEBUG_CSR (0x44) + +/* EHCI Register Set */ +#define EHCI_INSNREG05_ULPI (0xA4) +#define EHCI_INSNREG05_ULPI_CONTROL_SHIFT 31 +#define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT 24 +#define EHCI_INSNREG05_ULPI_OPSEL_SHIFT 22 +#define EHCI_INSNREG05_ULPI_REGADD_SHIFT 16 +#define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 +#define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 + +/*-------------------------------------------------------------------------*/ + +static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val) +{ + __raw_writel(val, base + reg); +} + +static inline u32 ehci_omap_readl(void __iomem *base, u32 reg) +{ + return __raw_readl(base + reg); +} + +static inline void ehci_omap_writeb(void __iomem *base, u8 reg, u8 val) +{ + __raw_writeb(val, base + reg); +} + +static inline u8 ehci_omap_readb(void __iomem *base, u8 reg) +{ + return __raw_readb(base + reg); +} + +/*-------------------------------------------------------------------------*/ + +struct ehci_hcd_omap { + struct ehci_hcd *ehci; + struct device *dev; + + struct clk *usbhost_ick; + struct clk *usbhost2_120m_fck; + struct clk *usbhost1_48m_fck; + struct clk *usbtll_fck; + struct clk *usbtll_ick; + + /* FIXME the following two workarounds are + * board specific not silicon-specific so these + * should be moved to board-file instead. + * + * Maybe someone from TI will know better which + * board is affected and needs the workarounds + * to be applied + */ + + /* gpio for resetting phy */ + int reset_gpio_port[OMAP3_HS_USB_PORTS]; + + /* phy reset workaround */ + int phy_reset; + + /* desired phy_mode: TLL, PHY */ + enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS]; + + void __iomem *uhh_base; + void __iomem *tll_base; + void __iomem *ehci_base; +}; + +/*-------------------------------------------------------------------------*/ + +static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask) +{ + unsigned reg; + int i; + + /* Program the 3 TLL channels upfront */ + for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { + reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); + + /* Disable AutoIdle, BitStuffing and use SDR Mode */ + reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE + | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF + | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE); + ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); + } + + /* Program Common TLL register */ + reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_SHARED_CONF); + reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON + | OMAP_TLL_SHARED_CONF_USB_DIVRATION + | OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN); + reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN; + + ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); + + /* Enable channels now */ + for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { + reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); + + /* Enable only the reg that is needed */ + if (!(tll_channel_mask & 1<tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); + + ehci_omap_writeb(omap->tll_base, + OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe); + dev_dbg(omap->dev, "ULPI_SCRATCH_REG[ch=%d]= 0x%02x\n", + i+1, ehci_omap_readb(omap->tll_base, + OMAP_TLL_ULPI_SCRATCH_REGISTER(i))); + } +} + +/*-------------------------------------------------------------------------*/ + +/* omap_start_ehc + * - Start the TI USBHOST controller + */ +static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + u8 tll_ch_mask = 0; + unsigned reg = 0; + int ret = 0; + + dev_dbg(omap->dev, "starting TI EHCI USB Controller\n"); + + /* Enable Clocks for USBHOST */ + omap->usbhost_ick = clk_get(omap->dev, "usbhost_ick"); + if (IS_ERR(omap->usbhost_ick)) { + ret = PTR_ERR(omap->usbhost_ick); + goto err_host_ick; + } + clk_enable(omap->usbhost_ick); + + omap->usbhost2_120m_fck = clk_get(omap->dev, "usbhost_120m_fck"); + if (IS_ERR(omap->usbhost2_120m_fck)) { + ret = PTR_ERR(omap->usbhost2_120m_fck); + goto err_host_120m_fck; + } + clk_enable(omap->usbhost2_120m_fck); + + omap->usbhost1_48m_fck = clk_get(omap->dev, "usbhost_48m_fck"); + if (IS_ERR(omap->usbhost1_48m_fck)) { + ret = PTR_ERR(omap->usbhost1_48m_fck); + goto err_host_48m_fck; + } + clk_enable(omap->usbhost1_48m_fck); + + if (omap->phy_reset) { + /* Refer: ISSUE1 */ + if (gpio_is_valid(omap->reset_gpio_port[0])) { + gpio_request(omap->reset_gpio_port[0], + "USB1 PHY reset"); + gpio_direction_output(omap->reset_gpio_port[0], 0); + } + + if (gpio_is_valid(omap->reset_gpio_port[1])) { + gpio_request(omap->reset_gpio_port[1], + "USB2 PHY reset"); + gpio_direction_output(omap->reset_gpio_port[1], 0); + } + + /* Hold the PHY in RESET for enough time till DIR is high */ + udelay(10); + } + + /* Configure TLL for 60Mhz clk for ULPI */ + omap->usbtll_fck = clk_get(omap->dev, "usbtll_fck"); + if (IS_ERR(omap->usbtll_fck)) { + ret = PTR_ERR(omap->usbtll_fck); + goto err_tll_fck; + } + clk_enable(omap->usbtll_fck); + + omap->usbtll_ick = clk_get(omap->dev, "usbtll_ick"); + if (IS_ERR(omap->usbtll_ick)) { + ret = PTR_ERR(omap->usbtll_ick); + goto err_tll_ick; + } + clk_enable(omap->usbtll_ick); + + /* perform TLL soft reset, and wait until reset is complete */ + ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, + OMAP_USBTLL_SYSCONFIG_SOFTRESET); + + /* Wait for TLL reset to complete */ + while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) + & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { + cpu_relax(); + + if (time_after(jiffies, timeout)) { + dev_dbg(omap->dev, "operation timed out\n"); + ret = -EINVAL; + goto err_sys_status; + } + } + + dev_dbg(omap->dev, "TLL RESET DONE\n"); + + /* (1<<3) = no idle mode only for initial debugging */ + ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, + OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | + OMAP_USBTLL_SYSCONFIG_SIDLEMODE | + OMAP_USBTLL_SYSCONFIG_CACTIVITY); + + + /* Put UHH in NoIdle/NoStandby mode */ + reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); + reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP + | OMAP_UHH_SYSCONFIG_SIDLEMODE + | OMAP_UHH_SYSCONFIG_CACTIVITY + | OMAP_UHH_SYSCONFIG_MIDLEMODE); + reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; + + ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); + + reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); + + /* setup ULPI bypass and burst configurations */ + reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN + | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN + | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); + reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; + + if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) + reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; + if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) + reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; + if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN) + reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; + + /* Bypass the TLL module for PHY mode operation */ + if (omap_rev() <= OMAP3430_REV_ES2_1) { + dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1 \n"); + if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) || + (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) || + (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY)) + reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; + else + reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; + } else { + dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); + if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) + reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; + else if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) + reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; + + if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) + reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; + else if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) + reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; + + if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY) + reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; + else if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) + reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; + + } + ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); + dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); + + + if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) || + (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) || + (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) { + + if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) + tll_ch_mask |= OMAP_TLL_CHANNEL_1_EN_MASK; + if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) + tll_ch_mask |= OMAP_TLL_CHANNEL_2_EN_MASK; + if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) + tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK; + + /* Enable UTMI mode for required TLL channels */ + omap_usb_utmi_init(omap, tll_ch_mask); + } + + if (omap->phy_reset) { + /* Refer ISSUE1: + * Hold the PHY in RESET for enough time till + * PHY is settled and ready + */ + udelay(10); + + if (gpio_is_valid(omap->reset_gpio_port[0])) + gpio_set_value(omap->reset_gpio_port[0], 1); + + if (gpio_is_valid(omap->reset_gpio_port[1])) + gpio_set_value(omap->reset_gpio_port[1], 1); + } + + return 0; + +err_sys_status: + clk_disable(omap->usbtll_ick); + clk_put(omap->usbtll_ick); + +err_tll_ick: + clk_disable(omap->usbtll_fck); + clk_put(omap->usbtll_fck); + +err_tll_fck: + clk_disable(omap->usbhost1_48m_fck); + clk_put(omap->usbhost1_48m_fck); + + if (omap->phy_reset) { + if (gpio_is_valid(omap->reset_gpio_port[0])) + gpio_free(omap->reset_gpio_port[0]); + + if (gpio_is_valid(omap->reset_gpio_port[1])) + gpio_free(omap->reset_gpio_port[1]); + } + +err_host_48m_fck: + clk_disable(omap->usbhost2_120m_fck); + clk_put(omap->usbhost2_120m_fck); + +err_host_120m_fck: + clk_disable(omap->usbhost_ick); + clk_put(omap->usbhost_ick); + +err_host_ick: + return ret; +} + +static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(100); + + dev_dbg(omap->dev, "stopping TI EHCI USB Controller\n"); + + /* Reset OMAP modules for insmod/rmmod to work */ + ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, + OMAP_UHH_SYSCONFIG_SOFTRESET); + while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) + & (1 << 0))) { + cpu_relax(); + + if (time_after(jiffies, timeout)) + dev_dbg(omap->dev, "operation timed out\n"); + } + + while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) + & (1 << 1))) { + cpu_relax(); + + if (time_after(jiffies, timeout)) + dev_dbg(omap->dev, "operation timed out\n"); + } + + while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) + & (1 << 2))) { + cpu_relax(); + + if (time_after(jiffies, timeout)) + dev_dbg(omap->dev, "operation timed out\n"); + } + + ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1)); + + while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) + & (1 << 0))) { + cpu_relax(); + + if (time_after(jiffies, timeout)) + dev_dbg(omap->dev, "operation timed out\n"); + } + + if (omap->usbtll_fck != NULL) { + clk_disable(omap->usbtll_fck); + clk_put(omap->usbtll_fck); + omap->usbtll_fck = NULL; + } + + if (omap->usbhost_ick != NULL) { + clk_disable(omap->usbhost_ick); + clk_put(omap->usbhost_ick); + omap->usbhost_ick = NULL; + } + + if (omap->usbhost1_48m_fck != NULL) { + clk_disable(omap->usbhost1_48m_fck); + clk_put(omap->usbhost1_48m_fck); + omap->usbhost1_48m_fck = NULL; + } + + if (omap->usbhost2_120m_fck != NULL) { + clk_disable(omap->usbhost2_120m_fck); + clk_put(omap->usbhost2_120m_fck); + omap->usbhost2_120m_fck = NULL; + } + + if (omap->usbtll_ick != NULL) { + clk_disable(omap->usbtll_ick); + clk_put(omap->usbtll_ick); + omap->usbtll_ick = NULL; + } + + if (omap->phy_reset) { + if (gpio_is_valid(omap->reset_gpio_port[0])) + gpio_free(omap->reset_gpio_port[0]); + + if (gpio_is_valid(omap->reset_gpio_port[1])) + gpio_free(omap->reset_gpio_port[1]); + } + + dev_dbg(omap->dev, "Clock to USB host has been disabled\n"); +} + +/*-------------------------------------------------------------------------*/ + +static const struct hc_driver ehci_omap_hc_driver; + +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ + +/** + * ehci_hcd_omap_probe - initialize TI-based HCDs + * + * Allocates basic resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + */ +static int ehci_hcd_omap_probe(struct platform_device *pdev) +{ + struct ehci_hcd_omap_platform_data *pdata = pdev->dev.platform_data; + struct ehci_hcd_omap *omap; + struct resource *res; + struct usb_hcd *hcd; + + int irq = platform_get_irq(pdev, 0); + int ret = -ENODEV; + + if (!pdata) { + dev_dbg(&pdev->dev, "missing platform_data\n"); + goto err_pdata; + } + + if (usb_disabled()) + goto err_disabled; + + omap = kzalloc(sizeof(*omap), GFP_KERNEL); + if (!omap) { + ret = -ENOMEM; + goto err_disabled; + } + + hcd = usb_create_hcd(&ehci_omap_hc_driver, &pdev->dev, + dev_name(&pdev->dev)); + if (!hcd) { + dev_dbg(&pdev->dev, "failed to create hcd with err %d\n", ret); + ret = -ENOMEM; + goto err_create_hcd; + } + + platform_set_drvdata(pdev, omap); + omap->dev = &pdev->dev; + omap->phy_reset = pdata->phy_reset; + omap->reset_gpio_port[0] = pdata->reset_gpio_port[0]; + omap->reset_gpio_port[1] = pdata->reset_gpio_port[1]; + omap->reset_gpio_port[2] = pdata->reset_gpio_port[2]; + omap->port_mode[0] = pdata->port_mode[0]; + omap->port_mode[1] = pdata->port_mode[1]; + omap->port_mode[2] = pdata->port_mode[2]; + omap->ehci = hcd_to_ehci(hcd); + omap->ehci->sbrn = 0x20; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + dev_err(&pdev->dev, "EHCI ioremap failed\n"); + ret = -ENOMEM; + goto err_ioremap; + } + + /* we know this is the memory we want, no need to ioremap again */ + omap->ehci->caps = hcd->regs; + omap->ehci_base = hcd->regs; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + omap->uhh_base = ioremap(res->start, resource_size(res)); + if (!omap->uhh_base) { + dev_err(&pdev->dev, "UHH ioremap failed\n"); + ret = -ENOMEM; + goto err_uhh_ioremap; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); + omap->tll_base = ioremap(res->start, resource_size(res)); + if (!omap->tll_base) { + dev_err(&pdev->dev, "TLL ioremap failed\n"); + ret = -ENOMEM; + goto err_tll_ioremap; + } + + ret = omap_start_ehc(omap, hcd); + if (ret) { + dev_dbg(&pdev->dev, "failed to start ehci\n"); + goto err_start; + } + + omap->ehci->regs = hcd->regs + + HC_LENGTH(readl(&omap->ehci->caps->hc_capbase)); + + /* cache this readonly data; minimize chip reads */ + omap->ehci->hcs_params = readl(&omap->ehci->caps->hcs_params); + + /* SET 1 micro-frame Interrupt interval */ + writel(readl(&omap->ehci->regs->command) | (1 << 16), + &omap->ehci->regs->command); + + ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); + if (ret) { + dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret); + goto err_add_hcd; + } + + return 0; + +err_add_hcd: + omap_stop_ehc(omap, hcd); + +err_start: + iounmap(omap->tll_base); + +err_tll_ioremap: + iounmap(omap->uhh_base); + +err_uhh_ioremap: + iounmap(hcd->regs); + +err_ioremap: + usb_put_hcd(hcd); + +err_create_hcd: + kfree(omap); +err_disabled: +err_pdata: + return ret; +} + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +/** + * ehci_hcd_omap_remove - shutdown processing for EHCI HCDs + * @pdev: USB Host Controller being removed + * + * Reverses the effect of usb_ehci_hcd_omap_probe(), first invoking + * the HCD's stop() method. It is always called from a thread + * context, normally "rmmod", "apmd", or something similar. + */ +static int ehci_hcd_omap_remove(struct platform_device *pdev) +{ + struct ehci_hcd_omap *omap = platform_get_drvdata(pdev); + struct usb_hcd *hcd = ehci_to_hcd(omap->ehci); + + usb_remove_hcd(hcd); + omap_stop_ehc(omap, hcd); + iounmap(hcd->regs); + iounmap(omap->tll_base); + iounmap(omap->uhh_base); + usb_put_hcd(hcd); + + return 0; +} + +static void ehci_hcd_omap_shutdown(struct platform_device *pdev) +{ + struct ehci_hcd_omap *omap = platform_get_drvdata(pdev); + struct usb_hcd *hcd = ehci_to_hcd(omap->ehci); + + if (hcd->driver->shutdown) + hcd->driver->shutdown(hcd); +} + +static struct platform_driver ehci_hcd_omap_driver = { + .probe = ehci_hcd_omap_probe, + .remove = ehci_hcd_omap_remove, + .shutdown = ehci_hcd_omap_shutdown, + /*.suspend = ehci_hcd_omap_suspend, */ + /*.resume = ehci_hcd_omap_resume, */ + .driver = { + .name = "ehci-omap", + } +}; + +/*-------------------------------------------------------------------------*/ + +static const struct hc_driver ehci_omap_hc_driver = { + .description = hcd_name, + .product_desc = "OMAP-EHCI Host Controller", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + */ + .reset = ehci_init, + .start = ehci_run, + .stop = ehci_stop, + .shutdown = ehci_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, + .endpoint_reset = ehci_endpoint_reset, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, + .bus_suspend = ehci_bus_suspend, + .bus_resume = ehci_bus_resume, + + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, +}; + +MODULE_ALIAS("platform:omap-ehci"); +MODULE_AUTHOR("Texas Instruments, Inc."); +MODULE_AUTHOR("Felipe Balbi "); + diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 139a2cc3f6410a3381936d3820c0cb37030ef8c6..a427d3b0063468659bd73351ecf6aba86e9210fb 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -616,9 +616,11 @@ qh_urb_transaction ( ) { struct ehci_qtd *qtd, *qtd_prev; dma_addr_t buf; - int len, maxpacket; + int len, this_sg_len, maxpacket; int is_input; u32 token; + int i; + struct scatterlist *sg; /* * URBs map to sequences of QTDs: one logical transaction @@ -659,7 +661,20 @@ qh_urb_transaction ( /* * data transfer stage: buffer setup */ - buf = urb->transfer_dma; + i = urb->num_sgs; + if (len > 0 && i > 0) { + sg = urb->sg->sg; + buf = sg_dma_address(sg); + + /* urb->transfer_buffer_length may be smaller than the + * size of the scatterlist (or vice versa) + */ + this_sg_len = min_t(int, sg_dma_len(sg), len); + } else { + sg = NULL; + buf = urb->transfer_dma; + this_sg_len = len; + } if (is_input) token |= (1 /* "in" */ << 8); @@ -675,7 +690,9 @@ qh_urb_transaction ( for (;;) { int this_qtd_len; - this_qtd_len = qtd_fill(ehci, qtd, buf, len, token, maxpacket); + this_qtd_len = qtd_fill(ehci, qtd, buf, this_sg_len, token, + maxpacket); + this_sg_len -= this_qtd_len; len -= this_qtd_len; buf += this_qtd_len; @@ -691,8 +708,13 @@ qh_urb_transaction ( if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0) token ^= QTD_TOGGLE; - if (likely (len <= 0)) - break; + if (likely(this_sg_len <= 0)) { + if (--i <= 0 || len <= 0) + break; + sg = sg_next(sg); + buf = sg_dma_address(sg); + this_sg_len = min_t(int, sg_dma_len(sg), len); + } qtd_prev = qtd; qtd = ehci_qtd_alloc (ehci, flags); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index a5535b5e3fe27860caebb3d50f228ea6d85fd1b8..1e391e624c8affee6e58d699de953df4bcaa857a 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1385,7 +1385,7 @@ sitd_slot_ok ( * given EHCI_TUNE_FLS and the slop). Or, write a smarter scheduler! */ -#define SCHEDULE_SLOP 10 /* frames */ +#define SCHEDULE_SLOP 80 /* microframes */ static int iso_stream_schedule ( @@ -1394,12 +1394,13 @@ iso_stream_schedule ( struct ehci_iso_stream *stream ) { - u32 now, start, max, period; + u32 now, next, start, period; int status; unsigned mod = ehci->periodic_size << 3; struct ehci_iso_sched *sched = urb->hcpriv; + struct pci_dev *pdev; - if (sched->span > (mod - 8 * SCHEDULE_SLOP)) { + if (sched->span > (mod - SCHEDULE_SLOP)) { ehci_dbg (ehci, "iso request %p too long\n", urb); status = -EFBIG; goto fail; @@ -1418,26 +1419,35 @@ iso_stream_schedule ( now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; - /* when's the last uframe this urb could start? */ - max = now + mod; - /* Typical case: reuse current schedule, stream is still active. * Hopefully there are no gaps from the host falling behind * (irq delays etc), but if there are we'll take the next * slot in the schedule, implicitly assuming URB_ISO_ASAP. */ if (likely (!list_empty (&stream->td_list))) { + pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); start = stream->next_uframe; - if (start < now) - start += mod; + + /* For high speed devices, allow scheduling within the + * isochronous scheduling threshold. For full speed devices, + * don't. (Work around for Intel ICH9 bug.) + */ + if (!stream->highspeed && + pdev->vendor == PCI_VENDOR_ID_INTEL) + next = now + ehci->i_thresh; + else + next = now; /* Fell behind (by up to twice the slop amount)? */ - if (start >= max - 2 * 8 * SCHEDULE_SLOP) + if (((start - next) & (mod - 1)) >= + mod - 2 * SCHEDULE_SLOP) start += period * DIV_ROUND_UP( - max - start, period) - mod; + (next - start) & (mod - 1), + period); /* Tried to schedule too far into the future? */ - if (unlikely((start + sched->span) >= max)) { + if (unlikely(((start - now) & (mod - 1)) + sched->span + >= mod - 2 * SCHEDULE_SLOP)) { status = -EFBIG; goto fail; } @@ -1451,7 +1461,7 @@ iso_stream_schedule ( * can also help high bandwidth if the dma and irq loads don't * jump until after the queue is primed. */ - start = SCHEDULE_SLOP * 8 + (now & ~0x07); + start = SCHEDULE_SLOP + (now & ~0x07); start %= mod; stream->next_uframe = start; @@ -1482,7 +1492,7 @@ iso_stream_schedule ( /* no room in the schedule */ ehci_dbg (ehci, "iso %ssched full %p (now %d max %d)\n", list_empty (&stream->td_list) ? "" : "re", - urb, now, max); + urb, now, now + mod); status = -ENOSPC; fail: diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c new file mode 100644 index 0000000000000000000000000000000000000000..a5861531ad3e052f596caf6d79c178ace0238b53 --- /dev/null +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -0,0 +1,300 @@ +/* + * EHCI HCD (Host Controller Driver) for USB. + * + * Bus Glue for Xilinx EHCI core on the of_platform bus + * + * Copyright (c) 2009 Xilinx, Inc. + * + * Based on "ehci-ppc-of.c" by Valentine Barshak + * and "ehci-ppc-soc.c" by Stefan Roese + * and "ohci-ppc-of.c" by Sylvain Munaut + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You 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 + +/** + * ehci_xilinx_of_setup - Initialize the device for ehci_reset() + * @hcd: Pointer to the usb_hcd device to which the host controller bound + * + * called during probe() after chip reset completes. + */ +static int ehci_xilinx_of_setup(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int retval; + + retval = ehci_halt(ehci); + if (retval) + return retval; + + retval = ehci_init(hcd); + if (retval) + return retval; + + ehci->sbrn = 0x20; + + return ehci_reset(ehci); +} + +/** + * ehci_xilinx_port_handed_over - hand the port out if failed to enable it + * @hcd: Pointer to the usb_hcd device to which the host controller bound + * @portnum:Port number to which the device is attached. + * + * This function is used as a place to tell the user that the Xilinx USB host + * controller does support LS devices. And in an HS only configuration, it + * does not support FS devices either. It is hoped that this can help a + * confused user. + * + * There are cases when the host controller fails to enable the port due to, + * for example, insufficient power that can be supplied to the device from + * the USB bus. In those cases, the messages printed here are not helpful. + */ +static int ehci_xilinx_port_handed_over(struct usb_hcd *hcd, int portnum) +{ + dev_warn(hcd->self.controller, "port %d cannot be enabled\n", portnum); + if (hcd->has_tt) { + dev_warn(hcd->self.controller, + "Maybe you have connected a low speed device?\n"); + + dev_warn(hcd->self.controller, + "We do not support low speed devices\n"); + } else { + dev_warn(hcd->self.controller, + "Maybe your device is not a high speed device?\n"); + dev_warn(hcd->self.controller, + "The USB host controller does not support full speed " + "nor low speed devices\n"); + dev_warn(hcd->self.controller, + "You can reconfigure the host controller to have " + "full speed support\n"); + } + + return 0; +} + + +static const struct hc_driver ehci_xilinx_of_hc_driver = { + .description = hcd_name, + .product_desc = "OF EHCI", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + */ + .reset = ehci_xilinx_of_setup, + .start = ehci_run, + .stop = ehci_stop, + .shutdown = ehci_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, +#ifdef CONFIG_PM + .bus_suspend = ehci_bus_suspend, + .bus_resume = ehci_bus_resume, +#endif + .relinquish_port = NULL, + .port_handed_over = ehci_xilinx_port_handed_over, + + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, +}; + +/** + * ehci_hcd_xilinx_of_probe - Probe method for the USB host controller + * @op: pointer to the of_device to which the host controller bound + * @match: pointer to of_device_id structure, not used + * + * This function requests resources and sets up appropriate properties for the + * host controller. Because the Xilinx USB host controller can be configured + * as HS only or HS/FS only, it checks the configuration in the device tree + * entry, and sets an appropriate value for hcd->has_tt. + */ +static int __devinit +ehci_hcd_xilinx_of_probe(struct of_device *op, const struct of_device_id *match) +{ + struct device_node *dn = op->node; + struct usb_hcd *hcd; + struct ehci_hcd *ehci; + struct resource res; + int irq; + int rv; + int *value; + + if (usb_disabled()) + return -ENODEV; + + dev_dbg(&op->dev, "initializing XILINX-OF USB Controller\n"); + + rv = of_address_to_resource(dn, 0, &res); + if (rv) + return rv; + + hcd = usb_create_hcd(&ehci_xilinx_of_hc_driver, &op->dev, + "XILINX-OF USB"); + if (!hcd) + return -ENOMEM; + + hcd->rsrc_start = res.start; + hcd->rsrc_len = res.end - res.start + 1; + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + printk(KERN_ERR __FILE__ ": request_mem_region failed\n"); + rv = -EBUSY; + goto err_rmr; + } + + irq = irq_of_parse_and_map(dn, 0); + if (irq == NO_IRQ) { + printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n"); + rv = -EBUSY; + goto err_irq; + } + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + printk(KERN_ERR __FILE__ ": ioremap failed\n"); + rv = -ENOMEM; + goto err_ioremap; + } + + ehci = hcd_to_ehci(hcd); + + /* This core always has big-endian register interface and uses + * big-endian memory descriptors. + */ + ehci->big_endian_mmio = 1; + ehci->big_endian_desc = 1; + + /* Check whether the FS support option is selected in the hardware. + */ + value = (int *)of_get_property(dn, "xlnx,support-usb-fs", NULL); + if (value && (*value == 1)) { + ehci_dbg(ehci, "USB host controller supports FS devices\n"); + hcd->has_tt = 1; + } else { + ehci_dbg(ehci, + "USB host controller is HS only\n"); + hcd->has_tt = 0; + } + + /* Debug registers are at the first 0x100 region + */ + ehci->caps = hcd->regs + 0x100; + ehci->regs = hcd->regs + 0x100 + + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); + + /* cache this readonly data; minimize chip reads */ + ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); + + rv = usb_add_hcd(hcd, irq, 0); + if (rv == 0) + return 0; + + iounmap(hcd->regs); + +err_ioremap: +err_irq: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +err_rmr: + usb_put_hcd(hcd); + + return rv; +} + +/** + * ehci_hcd_xilinx_of_remove - shutdown hcd and release resources + * @op: pointer to of_device structure that is to be removed + * + * Remove the hcd structure, and release resources that has been requested + * during probe. + */ +static int ehci_hcd_xilinx_of_remove(struct of_device *op) +{ + struct usb_hcd *hcd = dev_get_drvdata(&op->dev); + dev_set_drvdata(&op->dev, NULL); + + dev_dbg(&op->dev, "stopping XILINX-OF USB Controller\n"); + + usb_remove_hcd(hcd); + + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + + usb_put_hcd(hcd); + + return 0; +} + +/** + * ehci_hcd_xilinx_of_shutdown - shutdown the hcd + * @op: pointer to of_device structure that is to be removed + * + * Properly shutdown the hcd, call driver's shutdown routine. + */ +static int ehci_hcd_xilinx_of_shutdown(struct of_device *op) +{ + struct usb_hcd *hcd = dev_get_drvdata(&op->dev); + + if (hcd->driver->shutdown) + hcd->driver->shutdown(hcd); + + return 0; +} + + +static struct of_device_id ehci_hcd_xilinx_of_match[] = { + {.compatible = "xlnx,xps-usb-host-1.00.a",}, + {}, +}; +MODULE_DEVICE_TABLE(of, ehci_hcd_xilinx_of_match); + +static struct of_platform_driver ehci_hcd_xilinx_of_driver = { + .name = "xilinx-of-ehci", + .match_table = ehci_hcd_xilinx_of_match, + .probe = ehci_hcd_xilinx_of_probe, + .remove = ehci_hcd_xilinx_of_remove, + .shutdown = ehci_hcd_xilinx_of_shutdown, + .driver = { + .name = "xilinx-of-ehci", + .owner = THIS_MODULE, + }, +}; diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h index 1a253ebf7e50c5bfb409215fa0652a398aa76c73..5151516ea1dee98a093b35cee1b89f4bca3cd457 100644 --- a/drivers/usb/host/isp1362.h +++ b/drivers/usb/host/isp1362.h @@ -534,8 +534,8 @@ struct isp1362_hcd { /* periodic schedule: isochronous */ struct list_head isoc; - int istl_flip:1; - int irq_active:1; + unsigned int istl_flip:1; + unsigned int irq_active:1; /* Schedules for the current frame */ struct isp1362_ep_queue atl_queue; diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 7ccffcbe7b6f48f7ef1f0dc24b183f7be0e7a3ab..68b83ab70719aa8b76f79d7b766625cc991cbe4c 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -35,7 +35,7 @@ extern int usb_disabled(void); static void at91_start_clock(void) { - if (cpu_is_at91sam9261()) + if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) clk_enable(hclk); clk_enable(iclk); clk_enable(fclk); @@ -46,7 +46,7 @@ static void at91_stop_clock(void) { clk_disable(fclk); clk_disable(iclk); - if (cpu_is_at91sam9261()) + if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) clk_disable(hclk); clocked = 0; } @@ -142,7 +142,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, iclk = clk_get(&pdev->dev, "ohci_clk"); fclk = clk_get(&pdev->dev, "uhpck"); - if (cpu_is_at91sam9261()) + if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) hclk = clk_get(&pdev->dev, "hck0"); at91_start_hc(pdev); @@ -155,7 +155,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, /* Error handling */ at91_stop_hc(pdev); - if (cpu_is_at91sam9261()) + if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) clk_put(hclk); clk_put(fclk); clk_put(iclk); @@ -192,7 +192,7 @@ static void usb_hcd_at91_remove(struct usb_hcd *hcd, release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); - if (cpu_is_at91sam9261()) + if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) clk_put(hclk); clk_put(fclk); clk_put(iclk); diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index 100bf3d8437c12e7e1d68e090759c79c355aa5cb..2769326da42e83f33575c6bf28348338d5ff7c8f 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c @@ -98,8 +98,8 @@ #define ISP1301_I2C_INTERRUPT_RISING 0xE #define ISP1301_I2C_REG_CLEAR_ADDR 1 -struct i2c_driver isp1301_driver; -struct i2c_client *isp1301_i2c_client; +static struct i2c_driver isp1301_driver; +static struct i2c_client *isp1301_i2c_client; extern int usb_disabled(void); extern int ocpi_enable(void); @@ -120,12 +120,12 @@ static int isp1301_remove(struct i2c_client *client) return 0; } -const struct i2c_device_id isp1301_id[] = { +static const struct i2c_device_id isp1301_id[] = { { "isp1301_pnx", 0 }, { } }; -struct i2c_driver isp1301_driver = { +static struct i2c_driver isp1301_driver = { .driver = { .name = "isp1301_pnx", }, diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index e33d36256350b8d0b3a4c23577d9f59a92ed1ef3..41dbc70ae752eaf41332807d4be86905801c47a8 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -822,8 +822,6 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address) return; list_for_each_entry_safe(td, next, list, queue) { - if (!td) - continue; if (td->address != address) continue; @@ -2025,8 +2023,6 @@ static struct r8a66597_device *get_r8a66597_device(struct r8a66597 *r8a66597, struct list_head *list = &r8a66597->child_device; list_for_each_entry(dev, list, device_list) { - if (!dev) - continue; if (dev->usb_address != addr) continue; diff --git a/drivers/usb/host/whci/debug.c b/drivers/usb/host/whci/debug.c index 2273c815941fe1cf4a886c19831bc63cb871d0f9..8c1c610c9513222aa494e86e6977799c57cbc991 100644 --- a/drivers/usb/host/whci/debug.c +++ b/drivers/usb/host/whci/debug.c @@ -31,17 +31,29 @@ struct whc_dbg { void qset_print(struct seq_file *s, struct whc_qset *qset) { + static const char *qh_type[] = { + "ctrl", "isoc", "bulk", "intr", "rsvd", "rsvd", "rsvd", "lpintr", }; struct whc_std *std; struct urb *urb = NULL; int i; - seq_printf(s, "qset %08x\n", (u32)qset->qset_dma); + seq_printf(s, "qset %08x", (u32)qset->qset_dma); + if (&qset->list_node == qset->whc->async_list.prev) { + seq_printf(s, " (dummy)\n"); + } else { + seq_printf(s, " ep%d%s-%s maxpkt: %d\n", + qset->qh.info1 & 0x0f, + (qset->qh.info1 >> 4) & 0x1 ? "in" : "out", + qh_type[(qset->qh.info1 >> 5) & 0x7], + (qset->qh.info1 >> 16) & 0xffff); + } seq_printf(s, " -> %08x\n", (u32)qset->qh.link); seq_printf(s, " info: %08x %08x %08x\n", - qset->qh.info1, qset->qh.info2, qset->qh.info3); - seq_printf(s, " sts: %04x errs: %d\n", qset->qh.status, qset->qh.err_count); + qset->qh.info1, qset->qh.info2, qset->qh.info3); + seq_printf(s, " sts: %04x errs: %d curwin: %08x\n", + qset->qh.status, qset->qh.err_count, qset->qh.cur_window); seq_printf(s, " TD: sts: %08x opts: %08x\n", - qset->qh.overlay.qtd.status, qset->qh.overlay.qtd.options); + qset->qh.overlay.qtd.status, qset->qh.overlay.qtd.options); for (i = 0; i < WHCI_QSET_TD_MAX; i++) { seq_printf(s, " %c%c TD[%d]: sts: %08x opts: %08x ptr: %08x\n", diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c index 687b622a1612e49d024c9b2494c33cb3064bbe2d..e0d3401285c8d99e59e3ed78ce6e14ae76448091 100644 --- a/drivers/usb/host/whci/hcd.c +++ b/drivers/usb/host/whci/hcd.c @@ -250,6 +250,7 @@ static int whc_probe(struct umc_dev *umc) } usb_hcd->wireless = 1; + usb_hcd->self.sg_tablesize = 2048; /* somewhat arbitrary */ wusbhc = usb_hcd_to_wusbhc(usb_hcd); whc = wusbhc_to_whc(wusbhc); diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index 1b9dc15715703781922100186a7e354277969e73..7d4204db0f61c7ce18bb9e897700b22335094139 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c @@ -49,16 +49,19 @@ struct whc_qset *qset_alloc(struct whc *whc, gfp_t mem_flags) * state * @urb: an urb for a transfer to this endpoint */ -static void qset_fill_qh(struct whc_qset *qset, struct urb *urb) +static void qset_fill_qh(struct whc *whc, struct whc_qset *qset, struct urb *urb) { struct usb_device *usb_dev = urb->dev; + struct wusb_dev *wusb_dev = usb_dev->wusb_dev; struct usb_wireless_ep_comp_descriptor *epcd; bool is_out; + uint8_t phy_rate; is_out = usb_pipeout(urb->pipe); - epcd = (struct usb_wireless_ep_comp_descriptor *)qset->ep->extra; + qset->max_packet = le16_to_cpu(urb->ep->desc.wMaxPacketSize); + epcd = (struct usb_wireless_ep_comp_descriptor *)qset->ep->extra; if (epcd) { qset->max_seq = epcd->bMaxSequence; qset->max_burst = epcd->bMaxBurst; @@ -67,12 +70,28 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb) qset->max_burst = 1; } + /* + * Initial PHY rate is 53.3 Mbit/s for control endpoints or + * the maximum supported by the device for other endpoints + * (unless limited by the user). + */ + if (usb_pipecontrol(urb->pipe)) + phy_rate = UWB_PHY_RATE_53; + else { + uint16_t phy_rates; + + phy_rates = le16_to_cpu(wusb_dev->wusb_cap_descr->wPHYRates); + phy_rate = fls(phy_rates) - 1; + if (phy_rate > whc->wusbhc.phy_rate) + phy_rate = whc->wusbhc.phy_rate; + } + qset->qh.info1 = cpu_to_le32( QH_INFO1_EP(usb_pipeendpoint(urb->pipe)) | (is_out ? QH_INFO1_DIR_OUT : QH_INFO1_DIR_IN) | usb_pipe_to_qh_type(urb->pipe) | QH_INFO1_DEV_INFO_IDX(wusb_port_no_to_idx(usb_dev->portnum)) - | QH_INFO1_MAX_PKT_LEN(usb_maxpacket(urb->dev, urb->pipe, is_out)) + | QH_INFO1_MAX_PKT_LEN(qset->max_packet) ); qset->qh.info2 = cpu_to_le32( QH_INFO2_BURST(qset->max_burst) @@ -86,7 +105,7 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb) * strength and can presumably guess the Tx power required * from that? */ qset->qh.info3 = cpu_to_le32( - QH_INFO3_TX_RATE_53_3 + QH_INFO3_TX_RATE(phy_rate) | QH_INFO3_TX_PWR(0) /* 0 == max power */ ); @@ -148,7 +167,7 @@ struct whc_qset *get_qset(struct whc *whc, struct urb *urb, qset->ep = urb->ep; urb->ep->hcpriv = qset; - qset_fill_qh(qset, urb); + qset_fill_qh(whc, qset, urb); } return qset; } @@ -241,6 +260,36 @@ static void qset_remove_qtd(struct whc *whc, struct whc_qset *qset) qset->ntds--; } +static void qset_copy_bounce_to_sg(struct whc *whc, struct whc_std *std) +{ + struct scatterlist *sg; + void *bounce; + size_t remaining, offset; + + bounce = std->bounce_buf; + remaining = std->len; + + sg = std->bounce_sg; + offset = std->bounce_offset; + + while (remaining) { + size_t len; + + len = min(sg->length - offset, remaining); + memcpy(sg_virt(sg) + offset, bounce, len); + + bounce += len; + remaining -= len; + + offset += len; + if (offset >= sg->length) { + sg = sg_next(sg); + offset = 0; + } + } + +} + /** * qset_free_std - remove an sTD and free it. * @whc: the WHCI host controller @@ -249,13 +298,29 @@ static void qset_remove_qtd(struct whc *whc, struct whc_qset *qset) void qset_free_std(struct whc *whc, struct whc_std *std) { list_del(&std->list_node); - if (std->num_pointers) { - dma_unmap_single(whc->wusbhc.dev, std->dma_addr, - std->num_pointers * sizeof(struct whc_page_list_entry), - DMA_TO_DEVICE); + if (std->bounce_buf) { + bool is_out = usb_pipeout(std->urb->pipe); + dma_addr_t dma_addr; + + if (std->num_pointers) + dma_addr = le64_to_cpu(std->pl_virt[0].buf_ptr); + else + dma_addr = std->dma_addr; + + dma_unmap_single(whc->wusbhc.dev, dma_addr, + std->len, is_out ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + if (!is_out) + qset_copy_bounce_to_sg(whc, std); + kfree(std->bounce_buf); + } + if (std->pl_virt) { + if (std->dma_addr) + dma_unmap_single(whc->wusbhc.dev, std->dma_addr, + std->num_pointers * sizeof(struct whc_page_list_entry), + DMA_TO_DEVICE); kfree(std->pl_virt); + std->pl_virt = NULL; } - kfree(std); } @@ -293,12 +358,17 @@ static int qset_fill_page_list(struct whc *whc, struct whc_std *std, gfp_t mem_f { dma_addr_t dma_addr = std->dma_addr; dma_addr_t sp, ep; - size_t std_len = std->len; size_t pl_len; int p; - sp = ALIGN(dma_addr, WHCI_PAGE_SIZE); - ep = dma_addr + std_len; + /* Short buffers don't need a page list. */ + if (std->len <= WHCI_PAGE_SIZE) { + std->num_pointers = 0; + return 0; + } + + sp = dma_addr & ~(WHCI_PAGE_SIZE-1); + ep = dma_addr + std->len; std->num_pointers = DIV_ROUND_UP(ep - sp, WHCI_PAGE_SIZE); pl_len = std->num_pointers * sizeof(struct whc_page_list_entry); @@ -309,7 +379,7 @@ static int qset_fill_page_list(struct whc *whc, struct whc_std *std, gfp_t mem_f for (p = 0; p < std->num_pointers; p++) { std->pl_virt[p].buf_ptr = cpu_to_le64(dma_addr); - dma_addr = ALIGN(dma_addr + WHCI_PAGE_SIZE, WHCI_PAGE_SIZE); + dma_addr = (dma_addr + WHCI_PAGE_SIZE) & ~(WHCI_PAGE_SIZE-1); } return 0; @@ -339,6 +409,218 @@ static void urb_dequeue_work(struct work_struct *work) spin_unlock_irqrestore(&whc->lock, flags); } +static struct whc_std *qset_new_std(struct whc *whc, struct whc_qset *qset, + struct urb *urb, gfp_t mem_flags) +{ + struct whc_std *std; + + std = kzalloc(sizeof(struct whc_std), mem_flags); + if (std == NULL) + return NULL; + + std->urb = urb; + std->qtd = NULL; + + INIT_LIST_HEAD(&std->list_node); + list_add_tail(&std->list_node, &qset->stds); + + return std; +} + +static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *urb, + gfp_t mem_flags) +{ + size_t remaining; + struct scatterlist *sg; + int i; + int ntds = 0; + struct whc_std *std = NULL; + struct whc_page_list_entry *entry; + dma_addr_t prev_end = 0; + size_t pl_len; + int p = 0; + + remaining = urb->transfer_buffer_length; + + for_each_sg(urb->sg->sg, sg, urb->num_sgs, i) { + dma_addr_t dma_addr; + size_t dma_remaining; + dma_addr_t sp, ep; + int num_pointers; + + if (remaining == 0) { + break; + } + + dma_addr = sg_dma_address(sg); + dma_remaining = min_t(size_t, sg_dma_len(sg), remaining); + + while (dma_remaining) { + size_t dma_len; + + /* + * We can use the previous std (if it exists) provided that: + * - the previous one ended on a page boundary. + * - the current one begins on a page boundary. + * - the previous one isn't full. + * + * If a new std is needed but the previous one + * was not a whole number of packets then this + * sg list cannot be mapped onto multiple + * qTDs. Return an error and let the caller + * sort it out. + */ + if (!std + || (prev_end & (WHCI_PAGE_SIZE-1)) + || (dma_addr & (WHCI_PAGE_SIZE-1)) + || std->len + WHCI_PAGE_SIZE > QTD_MAX_XFER_SIZE) { + if (std->len % qset->max_packet != 0) + return -EINVAL; + std = qset_new_std(whc, qset, urb, mem_flags); + if (std == NULL) { + return -ENOMEM; + } + ntds++; + p = 0; + } + + dma_len = dma_remaining; + + /* + * If the remainder of this element doesn't + * fit in a single qTD, limit the qTD to a + * whole number of packets. This allows the + * remainder to go into the next qTD. + */ + if (std->len + dma_len > QTD_MAX_XFER_SIZE) { + dma_len = (QTD_MAX_XFER_SIZE / qset->max_packet) + * qset->max_packet - std->len; + } + + std->len += dma_len; + std->ntds_remaining = -1; /* filled in later */ + + sp = dma_addr & ~(WHCI_PAGE_SIZE-1); + ep = dma_addr + dma_len; + num_pointers = DIV_ROUND_UP(ep - sp, WHCI_PAGE_SIZE); + std->num_pointers += num_pointers; + + pl_len = std->num_pointers * sizeof(struct whc_page_list_entry); + + std->pl_virt = krealloc(std->pl_virt, pl_len, mem_flags); + if (std->pl_virt == NULL) { + return -ENOMEM; + } + + for (;p < std->num_pointers; p++, entry++) { + std->pl_virt[p].buf_ptr = cpu_to_le64(dma_addr); + dma_addr = (dma_addr + WHCI_PAGE_SIZE) & ~(WHCI_PAGE_SIZE-1); + } + + prev_end = dma_addr = ep; + dma_remaining -= dma_len; + remaining -= dma_len; + } + } + + /* Now the number of stds is know, go back and fill in + std->ntds_remaining. */ + list_for_each_entry(std, &qset->stds, list_node) { + if (std->ntds_remaining == -1) { + pl_len = std->num_pointers * sizeof(struct whc_page_list_entry); + std->ntds_remaining = ntds--; + std->dma_addr = dma_map_single(whc->wusbhc.dev, std->pl_virt, + pl_len, DMA_TO_DEVICE); + } + } + return 0; +} + +/** + * qset_add_urb_sg_linearize - add an urb with sg list, copying the data + * + * If the URB contains an sg list whose elements cannot be directly + * mapped to qTDs then the data must be transferred via bounce + * buffers. + */ +static int qset_add_urb_sg_linearize(struct whc *whc, struct whc_qset *qset, + struct urb *urb, gfp_t mem_flags) +{ + bool is_out = usb_pipeout(urb->pipe); + size_t max_std_len; + size_t remaining; + int ntds = 0; + struct whc_std *std = NULL; + void *bounce = NULL; + struct scatterlist *sg; + int i; + + /* limit maximum bounce buffer to 16 * 3.5 KiB ~= 28 k */ + max_std_len = qset->max_burst * qset->max_packet; + + remaining = urb->transfer_buffer_length; + + for_each_sg(urb->sg->sg, sg, urb->sg->nents, i) { + size_t len; + size_t sg_remaining; + void *orig; + + if (remaining == 0) { + break; + } + + sg_remaining = min_t(size_t, remaining, sg->length); + orig = sg_virt(sg); + + while (sg_remaining) { + if (!std || std->len == max_std_len) { + std = qset_new_std(whc, qset, urb, mem_flags); + if (std == NULL) + return -ENOMEM; + std->bounce_buf = kmalloc(max_std_len, mem_flags); + if (std->bounce_buf == NULL) + return -ENOMEM; + std->bounce_sg = sg; + std->bounce_offset = orig - sg_virt(sg); + bounce = std->bounce_buf; + ntds++; + } + + len = min(sg_remaining, max_std_len - std->len); + + if (is_out) + memcpy(bounce, orig, len); + + std->len += len; + std->ntds_remaining = -1; /* filled in later */ + + bounce += len; + orig += len; + sg_remaining -= len; + remaining -= len; + } + } + + /* + * For each of the new sTDs, map the bounce buffers, create + * page lists (if necessary), and fill in std->ntds_remaining. + */ + list_for_each_entry(std, &qset->stds, list_node) { + if (std->ntds_remaining != -1) + continue; + + std->dma_addr = dma_map_single(&whc->umc->dev, std->bounce_buf, std->len, + is_out ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + + if (qset_fill_page_list(whc, std, mem_flags) < 0) + return -ENOMEM; + + std->ntds_remaining = ntds--; + } + + return 0; +} + /** * qset_add_urb - add an urb to the qset's queue. * @@ -353,10 +635,7 @@ int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb, int remaining = urb->transfer_buffer_length; u64 transfer_dma = urb->transfer_dma; int ntds_remaining; - - ntds_remaining = DIV_ROUND_UP(remaining, QTD_MAX_XFER_SIZE); - if (ntds_remaining == 0) - ntds_remaining = 1; + int ret; wurb = kzalloc(sizeof(struct whc_urb), mem_flags); if (wurb == NULL) @@ -366,32 +645,39 @@ int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb, wurb->urb = urb; INIT_WORK(&wurb->dequeue_work, urb_dequeue_work); + if (urb->sg) { + ret = qset_add_urb_sg(whc, qset, urb, mem_flags); + if (ret == -EINVAL) { + qset_free_stds(qset, urb); + ret = qset_add_urb_sg_linearize(whc, qset, urb, mem_flags); + } + if (ret < 0) + goto err_no_mem; + return 0; + } + + ntds_remaining = DIV_ROUND_UP(remaining, QTD_MAX_XFER_SIZE); + if (ntds_remaining == 0) + ntds_remaining = 1; + while (ntds_remaining) { struct whc_std *std; size_t std_len; - std = kmalloc(sizeof(struct whc_std), mem_flags); - if (std == NULL) - goto err_no_mem; - std_len = remaining; if (std_len > QTD_MAX_XFER_SIZE) std_len = QTD_MAX_XFER_SIZE; - std->urb = urb; + std = qset_new_std(whc, qset, urb, mem_flags); + if (std == NULL) + goto err_no_mem; + std->dma_addr = transfer_dma; std->len = std_len; std->ntds_remaining = ntds_remaining; - std->qtd = NULL; - INIT_LIST_HEAD(&std->list_node); - list_add_tail(&std->list_node, &qset->stds); - - if (std_len > WHCI_PAGE_SIZE) { - if (qset_fill_page_list(whc, std, mem_flags) < 0) - goto err_no_mem; - } else - std->num_pointers = 0; + if (qset_fill_page_list(whc, std, mem_flags) < 0) + goto err_no_mem; ntds_remaining--; remaining -= std_len; diff --git a/drivers/usb/host/whci/whcd.h b/drivers/usb/host/whci/whcd.h index 24e94d983c5e38bcef2ca3460973c84657d095b2..c80c7d93bc4ac63019f40b8e6107f34a650226b1 100644 --- a/drivers/usb/host/whci/whcd.h +++ b/drivers/usb/host/whci/whcd.h @@ -84,6 +84,11 @@ struct whc { * @len: the length of data in the associated TD. * @ntds_remaining: number of TDs (starting from this one) in this transfer. * + * @bounce_buf: a bounce buffer if the std was from an urb with a sg + * list that could not be mapped to qTDs directly. + * @bounce_sg: the first scatterlist element bounce_buf is for. + * @bounce_offset: the offset into bounce_sg for the start of bounce_buf. + * * Queued URBs may require more TDs than are available in a qset so we * use a list of these "software TDs" (sTDs) to hold per-TD data. */ @@ -97,6 +102,10 @@ struct whc_std { int num_pointers; dma_addr_t dma_addr; struct whc_page_list_entry *pl_virt; + + void *bounce_buf; + struct scatterlist *bounce_sg; + unsigned bounce_offset; }; /** diff --git a/drivers/usb/host/whci/whci-hc.h b/drivers/usb/host/whci/whci-hc.h index e8d0001605be2c7192d2a01d0400877bbd2b234d..4d4cbc0730bf032fc32d263b6f46fbb26c2764d7 100644 --- a/drivers/usb/host/whci/whci-hc.h +++ b/drivers/usb/host/whci/whci-hc.h @@ -172,14 +172,7 @@ struct whc_qhead { #define QH_INFO3_MAX_DELAY(d) ((d) << 0) /* maximum stream delay in 125 us units (isoc only) */ #define QH_INFO3_INTERVAL(i) ((i) << 16) /* segment interval in 125 us units (isoc only) */ -#define QH_INFO3_TX_RATE_53_3 (0 << 24) -#define QH_INFO3_TX_RATE_80 (1 << 24) -#define QH_INFO3_TX_RATE_106_7 (2 << 24) -#define QH_INFO3_TX_RATE_160 (3 << 24) -#define QH_INFO3_TX_RATE_200 (4 << 24) -#define QH_INFO3_TX_RATE_320 (5 << 24) -#define QH_INFO3_TX_RATE_400 (6 << 24) -#define QH_INFO3_TX_RATE_480 (7 << 24) +#define QH_INFO3_TX_RATE(r) ((r) << 24) /* PHY rate (see [ECMA-368] section 10.3.1.1) */ #define QH_INFO3_TX_PWR(p) ((p) << 29) /* transmit power (see [WUSB] section 5.2.1.2) */ #define QH_STATUS_FLOW_CTRL (1 << 15) @@ -267,8 +260,9 @@ struct whc_qset { unsigned reset:1; struct urb *pause_after_urb; struct completion remove_complete; - int max_burst; - int max_seq; + uint16_t max_packet; + uint8_t max_burst; + uint8_t max_seq; }; static inline void whc_qset_set_link_ptr(u64 *ptr, u64 target) diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index 932f9993848175e476244fd23fa90303cc6b7d61..5e92c72df6420d025573850890d89319b12cd043 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -67,22 +67,14 @@ static int handshake(struct xhci_hcd *xhci, void __iomem *ptr, } /* - * Force HC into halt state. - * - * Disable any IRQs and clear the run/stop bit. - * HC will complete any current and actively pipelined transactions, and - * should halt within 16 microframes of the run/stop bit being cleared. - * Read HC Halted bit in the status register to see when the HC is finished. - * XXX: shouldn't we set HC_STATE_HALT here somewhere? + * Disable interrupts and begin the xHCI halting process. */ -int xhci_halt(struct xhci_hcd *xhci) +void xhci_quiesce(struct xhci_hcd *xhci) { u32 halted; u32 cmd; u32 mask; - xhci_dbg(xhci, "// Halt the HC\n"); - /* Disable all interrupts from the host controller */ mask = ~(XHCI_IRQS); halted = xhci_readl(xhci, &xhci->op_regs->status) & STS_HALT; if (!halted) @@ -91,6 +83,21 @@ int xhci_halt(struct xhci_hcd *xhci) cmd = xhci_readl(xhci, &xhci->op_regs->command); cmd &= mask; xhci_writel(xhci, cmd, &xhci->op_regs->command); +} + +/* + * Force HC into halt state. + * + * Disable any IRQs and clear the run/stop bit. + * HC will complete any current and actively pipelined transactions, and + * should halt within 16 microframes of the run/stop bit being cleared. + * Read HC Halted bit in the status register to see when the HC is finished. + * XXX: shouldn't we set HC_STATE_HALT here somewhere? + */ +int xhci_halt(struct xhci_hcd *xhci) +{ + xhci_dbg(xhci, "// Halt the HC\n"); + xhci_quiesce(xhci); return handshake(xhci, &xhci->op_regs->status, STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); @@ -124,28 +131,6 @@ int xhci_reset(struct xhci_hcd *xhci) return handshake(xhci, &xhci->op_regs->command, CMD_RESET, 0, 250 * 1000); } -/* - * Stop the HC from processing the endpoint queues. - */ -static void xhci_quiesce(struct xhci_hcd *xhci) -{ - /* - * Queues are per endpoint, so we need to disable an endpoint or slot. - * - * To disable a slot, we need to insert a disable slot command on the - * command ring and ring the doorbell. This will also free any internal - * resources associated with the slot (which might not be what we want). - * - * A Release Endpoint command sounds better - doesn't free internal HC - * memory, but removes the endpoints from the schedule and releases the - * bandwidth, disables the doorbells, and clears the endpoint enable - * flag. Usually used prior to a set interface command. - * - * TODO: Implement after command ring code is done. - */ - BUG_ON(!HC_IS_RUNNING(xhci_to_hcd(xhci)->state)); - xhci_dbg(xhci, "Finished quiescing -- code not written yet\n"); -} #if 0 /* Set up MSI-X table for entry 0 (may claim other entries later) */ @@ -261,8 +246,14 @@ static void xhci_work(struct xhci_hcd *xhci) /* Flush posted writes */ xhci_readl(xhci, &xhci->ir_set->irq_pending); - /* FIXME this should be a delayed service routine that clears the EHB */ - xhci_handle_event(xhci); + if (xhci->xhc_state & XHCI_STATE_DYING) + xhci_dbg(xhci, "xHCI dying, ignoring interrupt. " + "Shouldn't IRQs be disabled?\n"); + else + /* FIXME this should be a delayed service routine + * that clears the EHB. + */ + xhci_handle_event(xhci); /* Clear the event handler busy flag (RW1C); the event ring should be empty. */ temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); @@ -335,7 +326,7 @@ void xhci_event_ring_work(unsigned long arg) spin_lock_irqsave(&xhci->lock, flags); temp = xhci_readl(xhci, &xhci->op_regs->status); xhci_dbg(xhci, "op reg status = 0x%x\n", temp); - if (temp == 0xffffffff) { + if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING)) { xhci_dbg(xhci, "HW died, polling stopped.\n"); spin_unlock_irqrestore(&xhci->lock, flags); return; @@ -490,8 +481,6 @@ void xhci_stop(struct usb_hcd *hcd) struct xhci_hcd *xhci = hcd_to_xhci(hcd); spin_lock_irq(&xhci->lock); - if (HC_IS_RUNNING(hcd->state)) - xhci_quiesce(xhci); xhci_halt(xhci); xhci_reset(xhci); spin_unlock_irq(&xhci->lock); @@ -727,16 +716,22 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) * atomic context to this function, which may allocate memory. */ spin_lock_irqsave(&xhci->lock, flags); + if (xhci->xhc_state & XHCI_STATE_DYING) + goto dying; ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); spin_unlock_irqrestore(&xhci->lock, flags); } else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) { spin_lock_irqsave(&xhci->lock, flags); + if (xhci->xhc_state & XHCI_STATE_DYING) + goto dying; ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); spin_unlock_irqrestore(&xhci->lock, flags); } else if (usb_endpoint_xfer_int(&urb->ep->desc)) { spin_lock_irqsave(&xhci->lock, flags); + if (xhci->xhc_state & XHCI_STATE_DYING) + goto dying; ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); spin_unlock_irqrestore(&xhci->lock, flags); @@ -745,6 +740,12 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) } exit: return ret; +dying: + xhci_dbg(xhci, "Ep 0x%x: URB %p submitted for " + "non-responsive xHCI host.\n", + urb->ep->desc.bEndpointAddress, urb); + spin_unlock_irqrestore(&xhci->lock, flags); + return -ESHUTDOWN; } /* @@ -806,6 +807,17 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) kfree(td); return ret; } + if (xhci->xhc_state & XHCI_STATE_DYING) { + xhci_dbg(xhci, "Ep 0x%x: URB %p to be canceled on " + "non-responsive xHCI host.\n", + urb->ep->desc.bEndpointAddress, urb); + /* Let the stop endpoint command watchdog timer (which set this + * state) finish cleaning up the endpoint TD lists. We must + * have caught it in the middle of dropping a lock and giving + * back an URB. + */ + goto done; + } xhci_dbg(xhci, "Cancel URB %p\n", urb); xhci_dbg(xhci, "Event ring:\n"); @@ -817,12 +829,16 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) xhci_debug_ring(xhci, ep_ring); td = (struct xhci_td *) urb->hcpriv; - ep->cancels_pending++; list_add_tail(&td->cancelled_td_list, &ep->cancelled_td_list); /* Queue a stop endpoint command, but only if this is * the first cancellation to be handled. */ - if (ep->cancels_pending == 1) { + if (!(ep->ep_state & EP_HALT_PENDING)) { + ep->ep_state |= EP_HALT_PENDING; + ep->stop_cmds_pending++; + ep->stop_cmd_timer.expires = jiffies + + XHCI_STOP_EP_CMD_TIMEOUT * HZ; + add_timer(&ep->stop_cmd_timer); xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index); xhci_ring_cmd_db(xhci); } @@ -1246,13 +1262,35 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) LAST_CTX_TO_EP_NUM(slot_ctx->dev_info)); xhci_zero_in_ctx(xhci, virt_dev); - /* Free any old rings */ + /* Install new rings and free or cache any old rings */ for (i = 1; i < 31; ++i) { - if (virt_dev->eps[i].new_ring) { - xhci_ring_free(xhci, virt_dev->eps[i].ring); - virt_dev->eps[i].ring = virt_dev->eps[i].new_ring; - virt_dev->eps[i].new_ring = NULL; + int rings_cached; + + if (!virt_dev->eps[i].new_ring) + continue; + /* Only cache or free the old ring if it exists. + * It may not if this is the first add of an endpoint. + */ + if (virt_dev->eps[i].ring) { + rings_cached = virt_dev->num_rings_cached; + if (rings_cached < XHCI_MAX_RINGS_CACHED) { + virt_dev->num_rings_cached++; + rings_cached = virt_dev->num_rings_cached; + virt_dev->ring_cache[rings_cached] = + virt_dev->eps[i].ring; + xhci_dbg(xhci, "Cached old ring, " + "%d ring%s cached\n", + rings_cached, + (rings_cached > 1) ? "s" : ""); + } else { + xhci_ring_free(xhci, virt_dev->eps[i].ring); + xhci_dbg(xhci, "Ring cache full (%d rings), " + "freeing ring\n", + virt_dev->num_rings_cached); + } } + virt_dev->eps[i].ring = virt_dev->eps[i].new_ring; + virt_dev->eps[i].new_ring = NULL; } return ret; @@ -1427,16 +1465,27 @@ void xhci_endpoint_reset(struct usb_hcd *hcd, void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct xhci_virt_device *virt_dev; unsigned long flags; u32 state; + int i; if (udev->slot_id == 0) return; + virt_dev = xhci->devs[udev->slot_id]; + if (!virt_dev) + return; + + /* Stop any wayward timer functions (which may grab the lock) */ + for (i = 0; i < 31; ++i) { + virt_dev->eps[i].ep_state &= ~EP_HALT_PENDING; + del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); + } spin_lock_irqsave(&xhci->lock, flags); /* Don't disable the slot if the host controller is dead. */ state = xhci_readl(xhci, &xhci->op_regs->status); - if (state == 0xffffffff) { + if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING)) { xhci_free_virt_device(xhci, udev->slot_id); spin_unlock_irqrestore(&xhci->lock, flags); return; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index b8fd270a8b0d5f2630ed87dbcf6d24f8a566c86e..bffcef7a5545ec87dbdcc24cd0d43a45be401f60 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -125,6 +125,23 @@ void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring) kfree(ring); } +static void xhci_initialize_ring_info(struct xhci_ring *ring) +{ + /* The ring is empty, so the enqueue pointer == dequeue pointer */ + ring->enqueue = ring->first_seg->trbs; + ring->enq_seg = ring->first_seg; + ring->dequeue = ring->enqueue; + ring->deq_seg = ring->first_seg; + /* The ring is initialized to 0. The producer must write 1 to the cycle + * bit to handover ownership of the TRB, so PCS = 1. The consumer must + * compare CCS to the cycle bit to check ownership, so CCS = 1. + */ + ring->cycle_state = 1; + /* Not necessary for new rings, but needed for re-initialized rings */ + ring->enq_updates = 0; + ring->deq_updates = 0; +} + /** * Create a new ring with zero or more segments. * @@ -173,17 +190,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, " segment %p (virtual), 0x%llx (DMA)\n", prev, (unsigned long long)prev->dma); } - /* The ring is empty, so the enqueue pointer == dequeue pointer */ - ring->enqueue = ring->first_seg->trbs; - ring->enq_seg = ring->first_seg; - ring->dequeue = ring->enqueue; - ring->deq_seg = ring->first_seg; - /* The ring is initialized to 0. The producer must write 1 to the cycle - * bit to handover ownership of the TRB, so PCS = 1. The consumer must - * compare CCS to the cycle bit to check ownership, so CCS = 1. - */ - ring->cycle_state = 1; - + xhci_initialize_ring_info(ring); return ring; fail: @@ -191,6 +198,27 @@ fail: return 0; } +/* Zero an endpoint ring (except for link TRBs) and move the enqueue and dequeue + * pointers to the beginning of the ring. + */ +static void xhci_reinit_cached_ring(struct xhci_hcd *xhci, + struct xhci_ring *ring) +{ + struct xhci_segment *seg = ring->first_seg; + do { + memset(seg->trbs, 0, + sizeof(union xhci_trb)*TRBS_PER_SEGMENT); + /* All endpoint rings have link TRBs */ + xhci_link_segments(xhci, seg, seg->next, 1); + seg = seg->next; + } while (seg != ring->first_seg); + xhci_initialize_ring_info(ring); + /* td list should be empty since all URBs have been cancelled, + * but just in case... + */ + INIT_LIST_HEAD(&ring->td_list); +} + #define CTX_SIZE(_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32) struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci, @@ -248,6 +276,15 @@ struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, (ctx->bytes + (ep_index * CTX_SIZE(xhci->hcc_params))); } +static void xhci_init_endpoint_timer(struct xhci_hcd *xhci, + struct xhci_virt_ep *ep) +{ + init_timer(&ep->stop_cmd_timer); + ep->stop_cmd_timer.data = (unsigned long) ep; + ep->stop_cmd_timer.function = xhci_stop_endpoint_command_watchdog; + ep->xhci = xhci; +} + /* All the xhci_tds in the ring's TD list should be freed at this point */ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) { @@ -267,6 +304,12 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) if (dev->eps[i].ring) xhci_ring_free(xhci, dev->eps[i].ring); + if (dev->ring_cache) { + for (i = 0; i < dev->num_rings_cached; i++) + xhci_ring_free(xhci, dev->ring_cache[i]); + kfree(dev->ring_cache); + } + if (dev->in_ctx) xhci_free_container_ctx(xhci, dev->in_ctx); if (dev->out_ctx) @@ -309,15 +352,25 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, xhci_dbg(xhci, "Slot %d input ctx = 0x%llx (dma)\n", slot_id, (unsigned long long)dev->in_ctx->dma); - /* Initialize the cancellation list for each endpoint */ - for (i = 0; i < 31; i++) + /* Initialize the cancellation list and watchdog timers for each ep */ + for (i = 0; i < 31; i++) { + xhci_init_endpoint_timer(xhci, &dev->eps[i]); INIT_LIST_HEAD(&dev->eps[i].cancelled_td_list); + } /* Allocate endpoint 0 ring */ dev->eps[0].ring = xhci_ring_alloc(xhci, 1, true, flags); if (!dev->eps[0].ring) goto fail; + /* Allocate pointers to the ring cache */ + dev->ring_cache = kzalloc( + sizeof(struct xhci_ring *)*XHCI_MAX_RINGS_CACHED, + flags); + if (!dev->ring_cache) + goto fail; + dev->num_rings_cached = 0; + init_completion(&dev->cmd_completion); INIT_LIST_HEAD(&dev->cmd_list); @@ -544,8 +597,16 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, /* Set up the endpoint ring */ virt_dev->eps[ep_index].new_ring = xhci_ring_alloc(xhci, 1, true, mem_flags); - if (!virt_dev->eps[ep_index].new_ring) - return -ENOMEM; + if (!virt_dev->eps[ep_index].new_ring) { + /* Attempt to use the ring cache */ + if (virt_dev->num_rings_cached == 0) + return -ENOMEM; + virt_dev->eps[ep_index].new_ring = + virt_dev->ring_cache[virt_dev->num_rings_cached]; + virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL; + virt_dev->num_rings_cached--; + xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring); + } ep_ring = virt_dev->eps[ep_index].new_ring; ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state; @@ -768,14 +829,17 @@ struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci, command->in_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_INPUT, mem_flags); - if (!command->in_ctx) + if (!command->in_ctx) { + kfree(command); return NULL; + } if (allocate_completion) { command->completion = kzalloc(sizeof(struct completion), mem_flags); if (!command->completion) { xhci_free_container_ctx(xhci, command->in_ctx); + kfree(command); return NULL; } init_completion(command->completion); @@ -848,6 +912,163 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci->page_shift = 0; } +static int xhci_test_trb_in_td(struct xhci_hcd *xhci, + struct xhci_segment *input_seg, + union xhci_trb *start_trb, + union xhci_trb *end_trb, + dma_addr_t input_dma, + struct xhci_segment *result_seg, + char *test_name, int test_number) +{ + unsigned long long start_dma; + unsigned long long end_dma; + struct xhci_segment *seg; + + start_dma = xhci_trb_virt_to_dma(input_seg, start_trb); + end_dma = xhci_trb_virt_to_dma(input_seg, end_trb); + + seg = trb_in_td(input_seg, start_trb, end_trb, input_dma); + if (seg != result_seg) { + xhci_warn(xhci, "WARN: %s TRB math test %d failed!\n", + test_name, test_number); + xhci_warn(xhci, "Tested TRB math w/ seg %p and " + "input DMA 0x%llx\n", + input_seg, + (unsigned long long) input_dma); + xhci_warn(xhci, "starting TRB %p (0x%llx DMA), " + "ending TRB %p (0x%llx DMA)\n", + start_trb, start_dma, + end_trb, end_dma); + xhci_warn(xhci, "Expected seg %p, got seg %p\n", + result_seg, seg); + return -1; + } + return 0; +} + +/* TRB math checks for xhci_trb_in_td(), using the command and event rings. */ +static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci, gfp_t mem_flags) +{ + struct { + dma_addr_t input_dma; + struct xhci_segment *result_seg; + } simple_test_vector [] = { + /* A zeroed DMA field should fail */ + { 0, NULL }, + /* One TRB before the ring start should fail */ + { xhci->event_ring->first_seg->dma - 16, NULL }, + /* One byte before the ring start should fail */ + { xhci->event_ring->first_seg->dma - 1, NULL }, + /* Starting TRB should succeed */ + { xhci->event_ring->first_seg->dma, xhci->event_ring->first_seg }, + /* Ending TRB should succeed */ + { xhci->event_ring->first_seg->dma + (TRBS_PER_SEGMENT - 1)*16, + xhci->event_ring->first_seg }, + /* One byte after the ring end should fail */ + { xhci->event_ring->first_seg->dma + (TRBS_PER_SEGMENT - 1)*16 + 1, NULL }, + /* One TRB after the ring end should fail */ + { xhci->event_ring->first_seg->dma + (TRBS_PER_SEGMENT)*16, NULL }, + /* An address of all ones should fail */ + { (dma_addr_t) (~0), NULL }, + }; + struct { + struct xhci_segment *input_seg; + union xhci_trb *start_trb; + union xhci_trb *end_trb; + dma_addr_t input_dma; + struct xhci_segment *result_seg; + } complex_test_vector [] = { + /* Test feeding a valid DMA address from a different ring */ + { .input_seg = xhci->event_ring->first_seg, + .start_trb = xhci->event_ring->first_seg->trbs, + .end_trb = &xhci->event_ring->first_seg->trbs[TRBS_PER_SEGMENT - 1], + .input_dma = xhci->cmd_ring->first_seg->dma, + .result_seg = NULL, + }, + /* Test feeding a valid end TRB from a different ring */ + { .input_seg = xhci->event_ring->first_seg, + .start_trb = xhci->event_ring->first_seg->trbs, + .end_trb = &xhci->cmd_ring->first_seg->trbs[TRBS_PER_SEGMENT - 1], + .input_dma = xhci->cmd_ring->first_seg->dma, + .result_seg = NULL, + }, + /* Test feeding a valid start and end TRB from a different ring */ + { .input_seg = xhci->event_ring->first_seg, + .start_trb = xhci->cmd_ring->first_seg->trbs, + .end_trb = &xhci->cmd_ring->first_seg->trbs[TRBS_PER_SEGMENT - 1], + .input_dma = xhci->cmd_ring->first_seg->dma, + .result_seg = NULL, + }, + /* TRB in this ring, but after this TD */ + { .input_seg = xhci->event_ring->first_seg, + .start_trb = &xhci->event_ring->first_seg->trbs[0], + .end_trb = &xhci->event_ring->first_seg->trbs[3], + .input_dma = xhci->event_ring->first_seg->dma + 4*16, + .result_seg = NULL, + }, + /* TRB in this ring, but before this TD */ + { .input_seg = xhci->event_ring->first_seg, + .start_trb = &xhci->event_ring->first_seg->trbs[3], + .end_trb = &xhci->event_ring->first_seg->trbs[6], + .input_dma = xhci->event_ring->first_seg->dma + 2*16, + .result_seg = NULL, + }, + /* TRB in this ring, but after this wrapped TD */ + { .input_seg = xhci->event_ring->first_seg, + .start_trb = &xhci->event_ring->first_seg->trbs[TRBS_PER_SEGMENT - 3], + .end_trb = &xhci->event_ring->first_seg->trbs[1], + .input_dma = xhci->event_ring->first_seg->dma + 2*16, + .result_seg = NULL, + }, + /* TRB in this ring, but before this wrapped TD */ + { .input_seg = xhci->event_ring->first_seg, + .start_trb = &xhci->event_ring->first_seg->trbs[TRBS_PER_SEGMENT - 3], + .end_trb = &xhci->event_ring->first_seg->trbs[1], + .input_dma = xhci->event_ring->first_seg->dma + (TRBS_PER_SEGMENT - 4)*16, + .result_seg = NULL, + }, + /* TRB not in this ring, and we have a wrapped TD */ + { .input_seg = xhci->event_ring->first_seg, + .start_trb = &xhci->event_ring->first_seg->trbs[TRBS_PER_SEGMENT - 3], + .end_trb = &xhci->event_ring->first_seg->trbs[1], + .input_dma = xhci->cmd_ring->first_seg->dma + 2*16, + .result_seg = NULL, + }, + }; + + unsigned int num_tests; + int i, ret; + + num_tests = sizeof(simple_test_vector) / sizeof(simple_test_vector[0]); + for (i = 0; i < num_tests; i++) { + ret = xhci_test_trb_in_td(xhci, + xhci->event_ring->first_seg, + xhci->event_ring->first_seg->trbs, + &xhci->event_ring->first_seg->trbs[TRBS_PER_SEGMENT - 1], + simple_test_vector[i].input_dma, + simple_test_vector[i].result_seg, + "Simple", i); + if (ret < 0) + return ret; + } + + num_tests = sizeof(complex_test_vector) / sizeof(complex_test_vector[0]); + for (i = 0; i < num_tests; i++) { + ret = xhci_test_trb_in_td(xhci, + complex_test_vector[i].input_seg, + complex_test_vector[i].start_trb, + complex_test_vector[i].end_trb, + complex_test_vector[i].input_dma, + complex_test_vector[i].result_seg, + "Complex", i); + if (ret < 0) + return ret; + } + xhci_dbg(xhci, "TRB math tests passed.\n"); + return 0; +} + + int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) { dma_addr_t dma; @@ -951,6 +1172,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, false, flags); if (!xhci->event_ring) goto fail; + if (xhci_check_trb_in_td_math(xhci, flags) < 0) + goto fail; xhci->erst.entries = pci_alloc_consistent(to_pci_dev(dev), sizeof(struct xhci_erst_entry)*ERST_NUM_SEGS, &dma); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 06595ec27bb71af11cd4524c316070c61da1f2d0..e097008d6fb1afe9cf8269721b60265ac2115970 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -54,6 +54,8 @@ static int xhci_pci_setup(struct usb_hcd *hcd) struct pci_dev *pdev = to_pci_dev(hcd->self.controller); int retval; + hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 1; + xhci->cap_regs = hcd->regs; xhci->op_regs = hcd->regs + HC_LENGTH(xhci_readl(xhci, &xhci->cap_regs->hc_capbase)); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 821b7b4709de6531b28afb78c428ad4f5379ff81..ee7bc7ecbc595c98985eeca9f7e9fcfb7e16f677 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -306,7 +306,7 @@ static void ring_ep_doorbell(struct xhci_hcd *xhci, /* Don't ring the doorbell for this endpoint if there are pending * cancellations because the we don't want to interrupt processing. */ - if (!ep->cancels_pending && !(ep_state & SET_DEQ_PENDING) + if (!(ep_state & EP_HALT_PENDING) && !(ep_state & SET_DEQ_PENDING) && !(ep_state & EP_HALTED)) { field = xhci_readl(xhci, db_addr) & DB_MASK; xhci_writel(xhci, field | EPI_TO_DB(ep_index), db_addr); @@ -475,6 +475,35 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci, ep->ep_state |= SET_DEQ_PENDING; } +static inline void xhci_stop_watchdog_timer_in_irq(struct xhci_hcd *xhci, + struct xhci_virt_ep *ep) +{ + ep->ep_state &= ~EP_HALT_PENDING; + /* Can't del_timer_sync in interrupt, so we attempt to cancel. If the + * timer is running on another CPU, we don't decrement stop_cmds_pending + * (since we didn't successfully stop the watchdog timer). + */ + if (del_timer(&ep->stop_cmd_timer)) + ep->stop_cmds_pending--; +} + +/* Must be called with xhci->lock held in interrupt context */ +static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci, + struct xhci_td *cur_td, int status, char *adjective) +{ + struct usb_hcd *hcd = xhci_to_hcd(xhci); + + cur_td->urb->hcpriv = NULL; + usb_hcd_unlink_urb_from_ep(hcd, cur_td->urb); + xhci_dbg(xhci, "Giveback %s URB %p\n", adjective, cur_td->urb); + + spin_unlock(&xhci->lock); + usb_hcd_giveback_urb(hcd, cur_td->urb, status); + kfree(cur_td); + spin_lock(&xhci->lock); + xhci_dbg(xhci, "%s URB given back\n", adjective); +} + /* * When we get a command completion for a Stop Endpoint Command, we need to * unlink any cancelled TDs from the ring. There are two ways to do that: @@ -497,9 +526,6 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, struct xhci_td *last_unlinked_td; struct xhci_dequeue_state deq_state; -#ifdef CONFIG_USB_HCD_STAT - ktime_t stop_time = ktime_get(); -#endif memset(&deq_state, 0, sizeof(deq_state)); slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]); @@ -507,8 +533,11 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, ep = &xhci->devs[slot_id]->eps[ep_index]; ep_ring = ep->ring; - if (list_empty(&ep->cancelled_td_list)) + if (list_empty(&ep->cancelled_td_list)) { + xhci_stop_watchdog_timer_in_irq(xhci, ep); + ring_ep_doorbell(xhci, slot_id, ep_index); return; + } /* Fix up the ep ring first, so HW stops executing cancelled TDs. * We have the xHCI lock, so nothing can modify this list until we drop @@ -535,9 +564,9 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, * the cancelled TD list for URB completion later. */ list_del(&cur_td->td_list); - ep->cancels_pending--; } last_unlinked_td = cur_td; + xhci_stop_watchdog_timer_in_irq(xhci, ep); /* If necessary, queue a Set Transfer Ring Dequeue Pointer command */ if (deq_state.new_deq_ptr && deq_state.new_deq_seg) { @@ -561,27 +590,136 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, list_del(&cur_td->cancelled_td_list); /* Clean up the cancelled URB */ -#ifdef CONFIG_USB_HCD_STAT - hcd_stat_update(xhci->tp_stat, cur_td->urb->actual_length, - ktime_sub(stop_time, cur_td->start_time)); -#endif - cur_td->urb->hcpriv = NULL; - usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), cur_td->urb); - - xhci_dbg(xhci, "Giveback cancelled URB %p\n", cur_td->urb); - spin_unlock(&xhci->lock); /* Doesn't matter what we pass for status, since the core will * just overwrite it (because the URB has been unlinked). */ - usb_hcd_giveback_urb(xhci_to_hcd(xhci), cur_td->urb, 0); - kfree(cur_td); + xhci_giveback_urb_in_irq(xhci, cur_td, 0, "cancelled"); - spin_lock(&xhci->lock); + /* Stop processing the cancelled list if the watchdog timer is + * running. + */ + if (xhci->xhc_state & XHCI_STATE_DYING) + return; } while (cur_td != last_unlinked_td); /* Return to the event handler with xhci->lock re-acquired */ } +/* Watchdog timer function for when a stop endpoint command fails to complete. + * In this case, we assume the host controller is broken or dying or dead. The + * host may still be completing some other events, so we have to be careful to + * let the event ring handler and the URB dequeueing/enqueueing functions know + * through xhci->state. + * + * The timer may also fire if the host takes a very long time to respond to the + * command, and the stop endpoint command completion handler cannot delete the + * timer before the timer function is called. Another endpoint cancellation may + * sneak in before the timer function can grab the lock, and that may queue + * another stop endpoint command and add the timer back. So we cannot use a + * simple flag to say whether there is a pending stop endpoint command for a + * particular endpoint. + * + * Instead we use a combination of that flag and a counter for the number of + * pending stop endpoint commands. If the timer is the tail end of the last + * stop endpoint command, and the endpoint's command is still pending, we assume + * the host is dying. + */ +void xhci_stop_endpoint_command_watchdog(unsigned long arg) +{ + struct xhci_hcd *xhci; + struct xhci_virt_ep *ep; + struct xhci_virt_ep *temp_ep; + struct xhci_ring *ring; + struct xhci_td *cur_td; + int ret, i, j; + + ep = (struct xhci_virt_ep *) arg; + xhci = ep->xhci; + + spin_lock(&xhci->lock); + + ep->stop_cmds_pending--; + if (xhci->xhc_state & XHCI_STATE_DYING) { + xhci_dbg(xhci, "Stop EP timer ran, but another timer marked " + "xHCI as DYING, exiting.\n"); + spin_unlock(&xhci->lock); + return; + } + if (!(ep->stop_cmds_pending == 0 && (ep->ep_state & EP_HALT_PENDING))) { + xhci_dbg(xhci, "Stop EP timer ran, but no command pending, " + "exiting.\n"); + spin_unlock(&xhci->lock); + return; + } + + xhci_warn(xhci, "xHCI host not responding to stop endpoint command.\n"); + xhci_warn(xhci, "Assuming host is dying, halting host.\n"); + /* Oops, HC is dead or dying or at least not responding to the stop + * endpoint command. + */ + xhci->xhc_state |= XHCI_STATE_DYING; + /* Disable interrupts from the host controller and start halting it */ + xhci_quiesce(xhci); + spin_unlock(&xhci->lock); + + ret = xhci_halt(xhci); + + spin_lock(&xhci->lock); + if (ret < 0) { + /* This is bad; the host is not responding to commands and it's + * not allowing itself to be halted. At least interrupts are + * disabled, so we can set HC_STATE_HALT and notify the + * USB core. But if we call usb_hc_died(), it will attempt to + * disconnect all device drivers under this host. Those + * disconnect() methods will wait for all URBs to be unlinked, + * so we must complete them. + */ + xhci_warn(xhci, "Non-responsive xHCI host is not halting.\n"); + xhci_warn(xhci, "Completing active URBs anyway.\n"); + /* We could turn all TDs on the rings to no-ops. This won't + * help if the host has cached part of the ring, and is slow if + * we want to preserve the cycle bit. Skip it and hope the host + * doesn't touch the memory. + */ + } + for (i = 0; i < MAX_HC_SLOTS; i++) { + if (!xhci->devs[i]) + continue; + for (j = 0; j < 31; j++) { + temp_ep = &xhci->devs[i]->eps[j]; + ring = temp_ep->ring; + if (!ring) + continue; + xhci_dbg(xhci, "Killing URBs for slot ID %u, " + "ep index %u\n", i, j); + while (!list_empty(&ring->td_list)) { + cur_td = list_first_entry(&ring->td_list, + struct xhci_td, + td_list); + list_del(&cur_td->td_list); + if (!list_empty(&cur_td->cancelled_td_list)) + list_del(&cur_td->cancelled_td_list); + xhci_giveback_urb_in_irq(xhci, cur_td, + -ESHUTDOWN, "killed"); + } + while (!list_empty(&temp_ep->cancelled_td_list)) { + cur_td = list_first_entry( + &temp_ep->cancelled_td_list, + struct xhci_td, + cancelled_td_list); + list_del(&cur_td->cancelled_td_list); + xhci_giveback_urb_in_irq(xhci, cur_td, + -ESHUTDOWN, "killed"); + } + } + } + spin_unlock(&xhci->lock); + xhci_to_hcd(xhci)->state = HC_STATE_HALT; + xhci_dbg(xhci, "Calling usb_hc_died()\n"); + usb_hc_died(xhci_to_hcd(xhci)); + xhci_dbg(xhci, "xHCI host controller is dead.\n"); +} + /* * When we get a completion for a Set Transfer Ring Dequeue Pointer command, * we need to clear the set deq pending flag in the endpoint ring state, so that @@ -765,28 +903,32 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, virt_dev->in_ctx); /* Input ctx add_flags are the endpoint index plus one */ ep_index = xhci_last_valid_endpoint(ctrl_ctx->add_flags) - 1; - ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; - if (!ep_ring) { - /* This must have been an initial configure endpoint */ - xhci->devs[slot_id]->cmd_status = - GET_COMP_CODE(event->status); - complete(&xhci->devs[slot_id]->cmd_completion); - break; - } - ep_state = xhci->devs[slot_id]->eps[ep_index].ep_state; - xhci_dbg(xhci, "Completed config ep cmd - last ep index = %d, " - "state = %d\n", ep_index, ep_state); + /* A usb_set_interface() call directly after clearing a halted + * condition may race on this quirky hardware. + * Not worth worrying about, since this is prototype hardware. + */ if (xhci->quirks & XHCI_RESET_EP_QUIRK && - ep_state & EP_HALTED) { + ep_index != (unsigned int) -1 && + ctrl_ctx->add_flags - SLOT_FLAG == + ctrl_ctx->drop_flags) { + ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; + ep_state = xhci->devs[slot_id]->eps[ep_index].ep_state; + if (!(ep_state & EP_HALTED)) + goto bandwidth_change; + xhci_dbg(xhci, "Completed config ep cmd - " + "last ep index = %d, state = %d\n", + ep_index, ep_state); /* Clear our internal halted state and restart ring */ xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_HALTED; ring_ep_doorbell(xhci, slot_id, ep_index); - } else { - xhci->devs[slot_id]->cmd_status = - GET_COMP_CODE(event->status); - complete(&xhci->devs[slot_id]->cmd_completion); + break; } +bandwidth_change: + xhci_dbg(xhci, "Completed config ep cmd\n"); + xhci->devs[slot_id]->cmd_status = + GET_COMP_CODE(event->status); + complete(&xhci->devs[slot_id]->cmd_completion); break; case TRB_TYPE(TRB_EVAL_CONTEXT): virt_dev = xhci->devs[slot_id]; @@ -849,8 +991,7 @@ static void handle_port_status(struct xhci_hcd *xhci, * TRB in this TD, this function returns that TRB's segment. Otherwise it * returns 0. */ -static struct xhci_segment *trb_in_td( - struct xhci_segment *start_seg, +struct xhci_segment *trb_in_td(struct xhci_segment *start_seg, union xhci_trb *start_trb, union xhci_trb *end_trb, dma_addr_t suspect_dma) @@ -900,6 +1041,45 @@ static struct xhci_segment *trb_in_td( return 0; } +static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci, + unsigned int slot_id, unsigned int ep_index, + struct xhci_td *td, union xhci_trb *event_trb) +{ + struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index]; + ep->ep_state |= EP_HALTED; + ep->stopped_td = td; + ep->stopped_trb = event_trb; + xhci_queue_reset_ep(xhci, slot_id, ep_index); + xhci_cleanup_stalled_ring(xhci, td->urb->dev, ep_index); + xhci_ring_cmd_db(xhci); +} + +/* Check if an error has halted the endpoint ring. The class driver will + * cleanup the halt for a non-default control endpoint if we indicate a stall. + * However, a babble and other errors also halt the endpoint ring, and the class + * driver won't clear the halt in that case, so we need to issue a Set Transfer + * Ring Dequeue Pointer command manually. + */ +static int xhci_requires_manual_halt_cleanup(struct xhci_hcd *xhci, + struct xhci_ep_ctx *ep_ctx, + unsigned int trb_comp_code) +{ + /* TRB completion codes that may require a manual halt cleanup */ + if (trb_comp_code == COMP_TX_ERR || + trb_comp_code == COMP_BABBLE || + trb_comp_code == COMP_SPLIT_ERR) + /* The 0.96 spec says a babbling control endpoint + * is not halted. The 0.96 spec says it is. Some HW + * claims to be 0.95 compliant, but it halts the control + * endpoint anyway. Check if a babble halted the + * endpoint. + */ + if ((ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_HALTED) + return 1; + + return 0; +} + /* * If this function returns an error condition, it means it got a Transfer * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address. @@ -1002,6 +1182,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, xhci_warn(xhci, "WARN: TRB error on endpoint\n"); status = -EILSEQ; break; + case COMP_SPLIT_ERR: case COMP_TX_ERR: xhci_warn(xhci, "WARN: transfer error on endpoint\n"); status = -EPROTO; @@ -1015,6 +1196,16 @@ static int handle_tx_event(struct xhci_hcd *xhci, status = -ENOSR; break; default: + if (trb_comp_code >= 224 && trb_comp_code <= 255) { + /* Vendor defined "informational" completion code, + * treat as not-an-error. + */ + xhci_dbg(xhci, "Vendor defined info completion code %u\n", + trb_comp_code); + xhci_dbg(xhci, "Treating code as success.\n"); + status = 0; + break; + } xhci_warn(xhci, "ERROR Unknown event condition, HC probably busted\n"); urb = NULL; goto cleanup; @@ -1043,15 +1234,14 @@ static int handle_tx_event(struct xhci_hcd *xhci, else status = 0; break; - case COMP_BABBLE: - /* The 0.96 spec says a babbling control endpoint - * is not halted. The 0.96 spec says it is. Some HW - * claims to be 0.95 compliant, but it halts the control - * endpoint anyway. Check if a babble halted the - * endpoint. - */ - if (ep_ctx->ep_info != EP_STATE_HALTED) + + default: + if (!xhci_requires_manual_halt_cleanup(xhci, + ep_ctx, trb_comp_code)) break; + xhci_dbg(xhci, "TRB error code %u, " + "halted endpoint index = %u\n", + trb_comp_code, ep_index); /* else fall through */ case COMP_STALL: /* Did we transfer part of the data (middle) phase? */ @@ -1063,15 +1253,9 @@ static int handle_tx_event(struct xhci_hcd *xhci, else td->urb->actual_length = 0; - ep->stopped_td = td; - ep->stopped_trb = event_trb; - xhci_queue_reset_ep(xhci, slot_id, ep_index); - xhci_cleanup_stalled_ring(xhci, td->urb->dev, ep_index); - xhci_ring_cmd_db(xhci); + xhci_cleanup_halted_endpoint(xhci, + slot_id, ep_index, td, event_trb); goto td_cleanup; - default: - /* Others already handled above */ - break; } /* * Did we transfer any data, despite the errors that might have @@ -1209,16 +1393,25 @@ static int handle_tx_event(struct xhci_hcd *xhci, ep->stopped_td = td; ep->stopped_trb = event_trb; } else { - if (trb_comp_code == COMP_STALL || - trb_comp_code == COMP_BABBLE) { + if (trb_comp_code == COMP_STALL) { /* The transfer is completed from the driver's * perspective, but we need to issue a set dequeue * command for this stalled endpoint to move the dequeue * pointer past the TD. We can't do that here because - * the halt condition must be cleared first. + * the halt condition must be cleared first. Let the + * USB class driver clear the stall later. */ ep->stopped_td = td; ep->stopped_trb = event_trb; + } else if (xhci_requires_manual_halt_cleanup(xhci, + ep_ctx, trb_comp_code)) { + /* Other types of errors halt the endpoint, but the + * class driver doesn't call usb_reset_endpoint() unless + * the error is -EPIPE. Clear the halted status in the + * xHCI hardware manually. + */ + xhci_cleanup_halted_endpoint(xhci, + slot_id, ep_index, td, event_trb); } else { /* Update ring dequeue pointer */ while (ep_ring->dequeue != td->last_trb) @@ -1249,10 +1442,9 @@ td_cleanup: } list_del(&td->td_list); /* Was this TD slated to be cancelled but completed anyway? */ - if (!list_empty(&td->cancelled_td_list)) { + if (!list_empty(&td->cancelled_td_list)) list_del(&td->cancelled_td_list); - ep->cancels_pending--; - } + /* Leave the TD around for the reset endpoint function to use * (but only if it's not a control endpoint, since we already * queued the Set TR dequeue pointer command for stalled @@ -1331,6 +1523,14 @@ void xhci_handle_event(struct xhci_hcd *xhci) default: xhci->error_bitmask |= 1 << 3; } + /* Any of the above functions may drop and re-acquire the lock, so check + * to make sure a watchdog timer didn't mark the host as non-responsive. + */ + if (xhci->xhc_state & XHCI_STATE_DYING) { + xhci_dbg(xhci, "xHCI host dying, returning from " + "event handler.\n"); + return; + } if (update_ptrs) { /* Update SW and HC event ring dequeue pointer */ @@ -1555,6 +1755,21 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, return xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); } +/* + * The TD size is the number of bytes remaining in the TD (including this TRB), + * right shifted by 10. + * It must fit in bits 21:17, so it can't be bigger than 31. + */ +static u32 xhci_td_remainder(unsigned int remainder) +{ + u32 max = (1 << (21 - 17 + 1)) - 1; + + if ((remainder >> 10) >= max) + return max << 17; + else + return (remainder >> 10) << 17; +} + static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index) { @@ -1612,6 +1827,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, do { u32 field = 0; u32 length_field = 0; + u32 remainder = 0; /* Don't change the cycle bit of the first TRB until later */ if (first_trb) @@ -1641,8 +1857,10 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, (unsigned int) (addr + TRB_MAX_BUFF_SIZE) & ~(TRB_MAX_BUFF_SIZE - 1), (unsigned int) addr + trb_buff_len); } + remainder = xhci_td_remainder(urb->transfer_buffer_length - + running_total) ; length_field = TRB_LEN(trb_buff_len) | - TD_REMAINDER(urb->transfer_buffer_length - running_total) | + remainder | TRB_INTR_TARGET(0); queue_trb(xhci, ep_ring, false, lower_32_bits(addr), @@ -1755,6 +1973,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* Queue the first TRB, even if it's zero-length */ do { + u32 remainder = 0; field = 0; /* Don't change the cycle bit of the first TRB until later */ @@ -1773,8 +1992,10 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, td->last_trb = ep_ring->enqueue; field |= TRB_IOC; } + remainder = xhci_td_remainder(urb->transfer_buffer_length - + running_total); length_field = TRB_LEN(trb_buff_len) | - TD_REMAINDER(urb->transfer_buffer_length - running_total) | + remainder | TRB_INTR_TARGET(0); queue_trb(xhci, ep_ring, false, lower_32_bits(addr), @@ -1862,7 +2083,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* If there's data, queue data TRBs */ field = 0; length_field = TRB_LEN(urb->transfer_buffer_length) | - TD_REMAINDER(urb->transfer_buffer_length) | + xhci_td_remainder(urb->transfer_buffer_length) | TRB_INTR_TARGET(0); if (urb->transfer_buffer_length > 0) { if (setup->bRequestType & USB_DIR_IN) diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 4b254b6fa2456468731925199a69de85afd84602..877813505ef2044d062a1f66b8215b4a952aeda2 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -652,13 +652,17 @@ struct xhci_virt_ep { struct xhci_ring *new_ring; unsigned int ep_state; #define SET_DEQ_PENDING (1 << 0) -#define EP_HALTED (1 << 1) +#define EP_HALTED (1 << 1) /* For stall handling */ +#define EP_HALT_PENDING (1 << 2) /* For URB cancellation */ /* ---- Related to URB cancellation ---- */ struct list_head cancelled_td_list; - unsigned int cancels_pending; /* The TRB that was last reported in a stopped endpoint ring */ union xhci_trb *stopped_trb; struct xhci_td *stopped_td; + /* Watchdog timer for stop endpoint command to cancel URBs */ + struct timer_list stop_cmd_timer; + int stop_cmds_pending; + struct xhci_hcd *xhci; }; struct xhci_virt_device { @@ -673,6 +677,10 @@ struct xhci_virt_device { struct xhci_container_ctx *out_ctx; /* Used for addressing devices and configuration changes */ struct xhci_container_ctx *in_ctx; + /* Rings saved to ensure old alt settings can be re-instated */ + struct xhci_ring **ring_cache; + int num_rings_cached; +#define XHCI_MAX_RINGS_CACHED 31 struct xhci_virt_ep eps[31]; struct completion cmd_completion; /* Status of the last command issued for this device */ @@ -824,9 +832,6 @@ struct xhci_event_cmd { /* Normal TRB fields */ /* transfer_len bitmasks - bits 0:16 */ #define TRB_LEN(p) ((p) & 0x1ffff) -/* TD size - number of bytes remaining in the TD (including this TRB): - * bits 17 - 21. Shift the number of bytes by 10. */ -#define TD_REMAINDER(p) ((((p) >> 10) & 0x1f) << 17) /* Interrupter Target - which MSI-X vector to target the completion event at */ #define TRB_INTR_TARGET(p) (((p) & 0x3ff) << 22) #define GET_INTR_TARGET(p) (((p) >> 22) & 0x3ff) @@ -1022,6 +1027,8 @@ struct xhci_scratchpad { #define ERST_ENTRIES 1 /* Poll every 60 seconds */ #define POLL_TIMEOUT 60 +/* Stop endpoint command timeout (secs) for URB cancellation watchdog timer */ +#define XHCI_STOP_EP_CMD_TIMEOUT 5 /* XXX: Make these module parameters */ @@ -1083,6 +1090,21 @@ struct xhci_hcd { struct timer_list event_ring_timer; int zombie; #endif + /* Host controller watchdog timer structures */ + unsigned int xhc_state; +/* Host controller is dying - not responding to commands. "I'm not dead yet!" + * + * xHC interrupts have been disabled and a watchdog timer will (or has already) + * halt the xHCI host, and complete all URBs with an -ESHUTDOWN code. Any code + * that sees this status (other than the timer that set it) should stop touching + * hardware immediately. Interrupt handlers should return immediately when + * they see this status (any time they drop and re-acquire xhci->lock). + * xhci_urb_dequeue() should call usb_hcd_check_unlink_urb() and return without + * putting the TD on the canceled list, etc. + * + * There are no reports of xHCI host controllers that display this issue. + */ +#define XHCI_STATE_DYING (1 << 0) /* Statistics */ int noops_submitted; int noops_handled; @@ -1223,6 +1245,7 @@ void xhci_unregister_pci(void); #endif /* xHCI host controller glue */ +void xhci_quiesce(struct xhci_hcd *xhci); int xhci_halt(struct xhci_hcd *xhci); int xhci_reset(struct xhci_hcd *xhci); int xhci_init(struct usb_hcd *hcd); @@ -1246,6 +1269,9 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); /* xHCI ring, segment, TRB, and TD functions */ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb); +struct xhci_segment *trb_in_td(struct xhci_segment *start_seg, + union xhci_trb *start_trb, union xhci_trb *end_trb, + dma_addr_t suspect_dma); void xhci_ring_cmd_db(struct xhci_hcd *xhci); void *xhci_setup_one_noop(struct xhci_hcd *xhci); void xhci_handle_event(struct xhci_hcd *xhci); @@ -1278,6 +1304,7 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, struct xhci_dequeue_state *deq_state); +void xhci_stop_endpoint_command_watchdog(unsigned long arg); /* xHCI roothub code */ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index a9f06d76960ffa936858adaf321d5c53d39605dd..3dab0c0b196f56a4f3c625b883d8064ffa900992 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -213,8 +213,9 @@ static struct urb *simple_alloc_urb ( } static unsigned pattern = 0; -module_param (pattern, uint, S_IRUGO); -MODULE_PARM_DESC(pattern, "i/o pattern (0 == zeroes)"); +static unsigned mod_pattern; +module_param_named(pattern, mod_pattern, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(mod_pattern, "i/o pattern (0 == zeroes)"); static inline void simple_fill_buf (struct urb *urb) { @@ -1567,6 +1568,8 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) // FIXME USBDEVFS_CONNECTINFO doesn't say how fast the device is. + pattern = mod_pattern; + if (code != USBTEST_REQUEST) return -EOPNOTSUPP; diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 10f3205798e880ce4f1351735666bac903e34398..385ec052016705386e4f10fa8bffc51a44dec9e9 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -221,7 +222,7 @@ static void mon_free_buff(struct mon_pgmap *map, int npages); /* * This is a "chunked memcpy". It does not manipulate any counters. */ -static void mon_copy_to_buff(const struct mon_reader_bin *this, +static unsigned int mon_copy_to_buff(const struct mon_reader_bin *this, unsigned int off, const unsigned char *from, unsigned int length) { unsigned int step_len; @@ -246,6 +247,7 @@ static void mon_copy_to_buff(const struct mon_reader_bin *this, from += step_len; length -= step_len; } + return off; } /* @@ -394,14 +396,44 @@ static inline char mon_bin_get_setup(unsigned char *setupb, return 0; } -static char mon_bin_get_data(const struct mon_reader_bin *rp, - unsigned int offset, struct urb *urb, unsigned int length) +static unsigned int mon_bin_get_data(const struct mon_reader_bin *rp, + unsigned int offset, struct urb *urb, unsigned int length, + char *flag) { + int i; + struct scatterlist *sg; + unsigned int this_len; + + *flag = 0; + if (urb->num_sgs == 0) { + if (urb->transfer_buffer == NULL) { + *flag = 'Z'; + return length; + } + mon_copy_to_buff(rp, offset, urb->transfer_buffer, length); + length = 0; - if (urb->transfer_buffer == NULL) - return 'Z'; - mon_copy_to_buff(rp, offset, urb->transfer_buffer, length); - return 0; + } else { + /* If IOMMU coalescing occurred, we cannot trust sg_page */ + if (urb->sg->nents != urb->num_sgs) { + *flag = 'D'; + return length; + } + + /* Copy up to the first non-addressable segment */ + for_each_sg(urb->sg->sg, sg, urb->num_sgs, i) { + if (length == 0 || PageHighMem(sg_page(sg))) + break; + this_len = min_t(unsigned int, sg->length, length); + offset = mon_copy_to_buff(rp, offset, sg_virt(sg), + this_len); + length -= this_len; + } + if (i == 0) + *flag = 'D'; + } + + return length; } static void mon_bin_get_isodesc(const struct mon_reader_bin *rp, @@ -536,8 +568,9 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, } if (length != 0) { - ep->flag_data = mon_bin_get_data(rp, offset, urb, length); - if (ep->flag_data != 0) { /* Yes, it's 0x00, not '0' */ + length = mon_bin_get_data(rp, offset, urb, length, + &ep->flag_data); + if (length > 0) { delta = (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1); ep->len_cap -= length; delta -= (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1); diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index 9f1a9227ebe6571454ee3081d4df80ec5490f4c7..047568ff223db60743435effeaaf522b995d3e20 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "usb_mon.h" @@ -137,6 +138,8 @@ static inline char mon_text_get_setup(struct mon_event_text *ep, static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, int len, char ev_type, struct mon_bus *mbus) { + void *src; + if (len <= 0) return 'L'; if (len >= DATA_MAX) @@ -150,10 +153,24 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, return '>'; } - if (urb->transfer_buffer == NULL) - return 'Z'; /* '0' would be not as pretty. */ + if (urb->num_sgs == 0) { + src = urb->transfer_buffer; + if (src == NULL) + return 'Z'; /* '0' would be not as pretty. */ + } else { + struct scatterlist *sg = urb->sg->sg; + + /* If IOMMU coalescing occurred, we cannot trust sg_page */ + if (urb->sg->nents != urb->num_sgs || + PageHighMem(sg_page(sg))) + return 'D'; + + /* For the text interface we copy only the first sg buffer */ + len = min_t(int, sg->length, len); + src = sg_virt(sg); + } - memcpy(ep->data, urb->transfer_buffer, len); + memcpy(ep->data, src, len); return 0; } diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index b84abd8ee8a585f4e4ff884077be4f0f3a6ce7f0..d9db8649802263d8ff855bf7dc7f060b6c07f5ea 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -9,10 +9,9 @@ comment "Enable Host or Gadget support to see Inventra options" # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller config USB_MUSB_HDRC depends on (USB || USB_GADGET) - depends on (ARM || BLACKFIN) - select NOP_USB_XCEIV if ARCH_DAVINCI + depends on (ARM || (BF54x && !BF544) || (BF52x && !BF522 && !BF523)) + select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN) select TWL4030_USB if MACH_OMAP_3430SDP - select NOP_USB_XCEIV if MACH_OMAP3EVM select USB_OTG_UTILS tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' help diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index fcec87ea709e6d682f4c045d79c19c2c4a1fbcda..fe4934d9602c9a66d98d1498d5bd5d99a85f2337 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -53,13 +53,11 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) { void __iomem *fifo = hw_ep->fifo; + +#ifdef CONFIG_BF52x u8 epnum = hw_ep->epnum; u16 dma_reg = 0; - DBG(4, "%cX ep%d fifo %p count %d buf %p\n", - 'R', hw_ep->epnum, fifo, len, dst); - -#ifdef CONFIG_BF52x invalidate_dcache_range((unsigned int)dst, (unsigned int)(dst + len)); @@ -102,6 +100,9 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) len & 0x01 ? (len >> 1) + 1 : len >> 1); #endif + DBG(4, "%cX ep%d fifo %p count %d buf %p\n", + 'R', hw_ep->epnum, fifo, len, dst); + dump_fifo_data(dst, len); } @@ -225,8 +226,9 @@ int musb_platform_get_vbus_status(struct musb *musb) return 0; } -void musb_platform_set_mode(struct musb *musb, u8 musb_mode) +int musb_platform_set_mode(struct musb *musb, u8 musb_mode) { + return -EIO; } int __init musb_platform_init(struct musb *musb) @@ -261,10 +263,6 @@ int __init musb_platform_init(struct musb *musb) SSYNC(); } - /* TODO - * Set SIC-IVG register - */ - /* Configure PLL oscillator register */ bfin_write_USB_PLLOSC_CTRL(0x30a8); SSYNC(); diff --git a/drivers/usb/musb/blackfin.h b/drivers/usb/musb/blackfin.h index a240c1e53d16e16bf3acf214b2847b79d8643965..10b7d7584f4b99e7d6818772a853516e97aec057 100644 --- a/drivers/usb/musb/blackfin.h +++ b/drivers/usb/musb/blackfin.h @@ -14,6 +14,43 @@ * Blackfin specific definitions */ +/* Anomalies notes: + * + * 05000450 - USB DMA Mode 1 Short Packet Data Corruption: + * MUSB driver is designed to transfer buffer of N * maxpacket size + * in DMA mode 1 and leave the rest of the data to the next + * transfer in DMA mode 0, so we never transmit a short packet in + * DMA mode 1. + * + * 05000463 - This anomaly doesn't affect this driver since it + * never uses L1 or L2 memory as data destination. + * + * 05000464 - This anomaly doesn't affect this driver since it + * never uses L1 or L2 memory as data source. + * + * 05000465 - The anomaly can be seen when SCLK is over 100 MHz, and there is + * no way to workaround for bulk endpoints. Since the wMaxPackSize + * of bulk is less than or equal to 512, while the fifo size of + * endpoint 5, 6, 7 is 1024, the double buffer mode is enabled + * automatically when these endpoints are used for bulk OUT. + * + * 05000466 - This anomaly doesn't affect this driver since it never mixes + * concurrent DMA and core accesses to the TX endpoint FIFOs. + * + * 05000467 - The workaround for this anomaly will introduce another + * anomaly - 05000465. + */ + +/* The Mentor USB DMA engine on BF52x (silicon v0.0 and v0.1) seems to be + * unstable in host mode. This may be caused by Anomaly 05000380. After + * digging out the root cause, we will change this number accordingly. + * So, need to either use silicon v0.2+ or disable DMA mode in MUSB. + */ +#if ANOMALY_05000380 && defined(CONFIG_BF52x) && \ + defined(CONFIG_USB_MUSB_HDRC) && !defined(CONFIG_MUSB_PIO_ONLY) +# error "Please use PIO mode in MUSB driver on bf52x chip v0.0 and v0.1" +#endif + #undef DUMP_FIFO_DATA #ifdef DUMP_FIFO_DATA static void dump_fifo_data(u8 *buf, u16 len) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 547e0e3907268cc0d6f1b6b71d45d0a14e1129a8..49f2346afad3e8016d5f548e6f74d57b7322d49a 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1319,7 +1319,6 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) #endif u8 reg; char *type; - u16 hwvers, rev_major, rev_minor; char aInfo[78], aRevision[32], aDate[12]; void __iomem *mbase = musb->mregs; int status = 0; @@ -1391,11 +1390,10 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) } /* log release info */ - hwvers = musb_read_hwvers(mbase); - rev_major = (hwvers >> 10) & 0x1f; - rev_minor = hwvers & 0x3ff; - snprintf(aRevision, 32, "%d.%d%s", rev_major, - rev_minor, (hwvers & 0x8000) ? "RC" : ""); + musb->hwvers = musb_read_hwvers(mbase); + snprintf(aRevision, 32, "%d.%d%s", MUSB_HWVERS_MAJOR(musb->hwvers), + MUSB_HWVERS_MINOR(musb->hwvers), + (musb->hwvers & MUSB_HWVERS_RC) ? "RC" : ""); printk(KERN_DEBUG "%s: %sHDRC RTL version %s %s\n", musb_driver_name, type, aRevision, aDate); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 6aa5f22e52749e2325997f27e34d5e2ba366e511..03d50909b078345d5e4d82e116ee7a44b0b96280 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -322,6 +322,14 @@ struct musb { struct clk *clock; irqreturn_t (*isr)(int, void *); struct work_struct irq_work; +#define MUSB_HWVERS_MAJOR(x) ((x >> 10) & 0x1f) +#define MUSB_HWVERS_MINOR(x) (x & 0x3ff) +#define MUSB_HWVERS_RC 0x8000 +#define MUSB_HWVERS_1300 0x52C +#define MUSB_HWVERS_1400 0x590 +#define MUSB_HWVERS_1800 0x720 +#define MUSB_HWVERS_2000 0x800 + u16 hwvers; /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */ #define MUSB_PORT_STAT_RESUME (1 << 31) diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h index 0a2c4e3602c1bce77ab28cec193e5ea51d1bfda6..916065ba9e70ddb7dce7469baf5985d98b36121a 100644 --- a/drivers/usb/musb/musb_dma.h +++ b/drivers/usb/musb/musb_dma.h @@ -80,6 +80,17 @@ struct musb_hw_ep; #define tusb_dma_omap() 0 #endif +/* Anomaly 05000456 - USB Receive Interrupt Is Not Generated in DMA Mode 1 + * Only allow DMA mode 1 to be used when the USB will actually generate the + * interrupts we expect. + */ +#ifdef CONFIG_BLACKFIN +# undef USE_MODE1 +# if !ANOMALY_05000456 +# define USE_MODE1 +# endif +#endif + /* * DMA channel status ... updated by the dma controller driver whenever that * status changes, and protected by the overall controller spinlock. diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 74073f9a43f09cafc6afed82e5a9cadd17304d62..c49b9ba025ab2a75daa6794c4eedc97bcd8e87b1 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -429,112 +429,102 @@ void musb_g_tx(struct musb *musb, u8 epnum) DBG(4, "<== %s, txcsr %04x\n", musb_ep->end_point.name, csr); dma = is_dma_capable() ? musb_ep->dma : NULL; - do { - /* REVISIT for high bandwidth, MUSB_TXCSR_P_INCOMPTX - * probably rates reporting as a host error + + /* + * REVISIT: for high bandwidth, MUSB_TXCSR_P_INCOMPTX + * probably rates reporting as a host error. + */ + if (csr & MUSB_TXCSR_P_SENTSTALL) { + csr |= MUSB_TXCSR_P_WZC_BITS; + csr &= ~MUSB_TXCSR_P_SENTSTALL; + musb_writew(epio, MUSB_TXCSR, csr); + return; + } + + if (csr & MUSB_TXCSR_P_UNDERRUN) { + /* We NAKed, no big deal... little reason to care. */ + csr |= MUSB_TXCSR_P_WZC_BITS; + csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY); + musb_writew(epio, MUSB_TXCSR, csr); + DBG(20, "underrun on ep%d, req %p\n", epnum, request); + } + + if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { + /* + * SHOULD NOT HAPPEN... has with CPPI though, after + * changing SENDSTALL (and other cases); harmless? */ - if (csr & MUSB_TXCSR_P_SENTSTALL) { - csr |= MUSB_TXCSR_P_WZC_BITS; - csr &= ~MUSB_TXCSR_P_SENTSTALL; - musb_writew(epio, MUSB_TXCSR, csr); - break; - } + DBG(5, "%s dma still busy?\n", musb_ep->end_point.name); + return; + } + + if (request) { + u8 is_dma = 0; - if (csr & MUSB_TXCSR_P_UNDERRUN) { - /* we NAKed, no big deal ... little reason to care */ + if (dma && (csr & MUSB_TXCSR_DMAENAB)) { + is_dma = 1; csr |= MUSB_TXCSR_P_WZC_BITS; - csr &= ~(MUSB_TXCSR_P_UNDERRUN - | MUSB_TXCSR_TXPKTRDY); + csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN | + MUSB_TXCSR_TXPKTRDY); musb_writew(epio, MUSB_TXCSR, csr); - DBG(20, "underrun on ep%d, req %p\n", epnum, request); + /* Ensure writebuffer is empty. */ + csr = musb_readw(epio, MUSB_TXCSR); + request->actual += musb_ep->dma->actual_len; + DBG(4, "TXCSR%d %04x, DMA off, len %zu, req %p\n", + epnum, csr, musb_ep->dma->actual_len, request); } - if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { - /* SHOULD NOT HAPPEN ... has with cppi though, after - * changing SENDSTALL (and other cases); harmless? + if (is_dma || request->actual == request->length) { + /* + * First, maybe a terminating short packet. Some DMA + * engines might handle this by themselves. */ - DBG(5, "%s dma still busy?\n", musb_ep->end_point.name); - break; - } - - if (request) { - u8 is_dma = 0; - - if (dma && (csr & MUSB_TXCSR_DMAENAB)) { - is_dma = 1; - csr |= MUSB_TXCSR_P_WZC_BITS; - csr &= ~(MUSB_TXCSR_DMAENAB - | MUSB_TXCSR_P_UNDERRUN - | MUSB_TXCSR_TXPKTRDY); - musb_writew(epio, MUSB_TXCSR, csr); - /* ensure writebuffer is empty */ - csr = musb_readw(epio, MUSB_TXCSR); - request->actual += musb_ep->dma->actual_len; - DBG(4, "TXCSR%d %04x, dma off, " - "len %zu, req %p\n", - epnum, csr, - musb_ep->dma->actual_len, - request); - } - - if (is_dma || request->actual == request->length) { - - /* First, maybe a terminating short packet. - * Some DMA engines might handle this by - * themselves. - */ - if ((request->zero - && request->length - && (request->length - % musb_ep->packet_sz) - == 0) + if ((request->zero && request->length + && request->length % musb_ep->packet_sz == 0) #ifdef CONFIG_USB_INVENTRA_DMA - || (is_dma && - ((!dma->desired_mode) || - (request->actual & - (musb_ep->packet_sz - 1)))) + || (is_dma && (!dma->desired_mode || + (request->actual & + (musb_ep->packet_sz - 1)))) #endif - ) { - /* on dma completion, fifo may not - * be available yet ... - */ - if (csr & MUSB_TXCSR_TXPKTRDY) - break; - - DBG(4, "sending zero pkt\n"); - musb_writew(epio, MUSB_TXCSR, - MUSB_TXCSR_MODE - | MUSB_TXCSR_TXPKTRDY); - request->zero = 0; - } - - /* ... or if not, then complete it */ - musb_g_giveback(musb_ep, request, 0); - - /* kickstart next transfer if appropriate; - * the packet that just completed might not - * be transmitted for hours or days. - * REVISIT for double buffering... - * FIXME revisit for stalls too... + ) { + /* + * On DMA completion, FIFO may not be + * available yet... */ - musb_ep_select(mbase, epnum); - csr = musb_readw(epio, MUSB_TXCSR); - if (csr & MUSB_TXCSR_FIFONOTEMPTY) - break; - request = musb_ep->desc - ? next_request(musb_ep) - : NULL; - if (!request) { - DBG(4, "%s idle now\n", - musb_ep->end_point.name); - break; - } + if (csr & MUSB_TXCSR_TXPKTRDY) + return; + + DBG(4, "sending zero pkt\n"); + musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE + | MUSB_TXCSR_TXPKTRDY); + request->zero = 0; } - txstate(musb, to_musb_request(request)); + /* ... or if not, then complete it. */ + musb_g_giveback(musb_ep, request, 0); + + /* + * Kickstart next transfer if appropriate; + * the packet that just completed might not + * be transmitted for hours or days. + * REVISIT for double buffering... + * FIXME revisit for stalls too... + */ + musb_ep_select(mbase, epnum); + csr = musb_readw(epio, MUSB_TXCSR); + if (csr & MUSB_TXCSR_FIFONOTEMPTY) + return; + + if (!musb_ep->desc) { + DBG(4, "%s idle now\n", + musb_ep->end_point.name); + return; + } else + request = next_request(musb_ep); } - } while (0); + txstate(musb, to_musb_request(request)); + } } /* ------------------------------------------------------------ */ @@ -966,6 +956,7 @@ static int musb_gadget_enable(struct usb_ep *ep, musb_ep->desc = desc; musb_ep->busy = 0; + musb_ep->wedged = 0; status = 0; pr_debug("%s periph: enabled %s for %s %s, %smaxpacket %d\n", @@ -1220,7 +1211,7 @@ done: * * exported to ep0 code */ -int musb_gadget_set_halt(struct usb_ep *ep, int value) +static int musb_gadget_set_halt(struct usb_ep *ep, int value) { struct musb_ep *musb_ep = to_musb_ep(ep); u8 epnum = musb_ep->current_epnum; @@ -1262,7 +1253,8 @@ int musb_gadget_set_halt(struct usb_ep *ep, int value) goto done; } } - } + } else + musb_ep->wedged = 0; /* set/clear the stall and toggle bits */ DBG(2, "%s: %s stall\n", ep->name, value ? "set" : "clear"); @@ -1301,6 +1293,21 @@ done: return status; } +/* + * Sets the halt feature with the clear requests ignored + */ +static int musb_gadget_set_wedge(struct usb_ep *ep) +{ + struct musb_ep *musb_ep = to_musb_ep(ep); + + if (!ep) + return -EINVAL; + + musb_ep->wedged = 1; + + return usb_ep_set_halt(ep); +} + static int musb_gadget_fifo_status(struct usb_ep *ep) { struct musb_ep *musb_ep = to_musb_ep(ep); @@ -1371,6 +1378,7 @@ static const struct usb_ep_ops musb_ep_ops = { .queue = musb_gadget_queue, .dequeue = musb_gadget_dequeue, .set_halt = musb_gadget_set_halt, + .set_wedge = musb_gadget_set_wedge, .fifo_status = musb_gadget_fifo_status, .fifo_flush = musb_gadget_fifo_flush }; diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h index 59502da9f739ce179bca5faa549147d6c34ad078..c8b140325d82bf4bb6cd3ad85216fa24ec308ce7 100644 --- a/drivers/usb/musb/musb_gadget.h +++ b/drivers/usb/musb/musb_gadget.h @@ -75,6 +75,8 @@ struct musb_ep { /* later things are modified based on usage */ struct list_head req_list; + u8 wedged; + /* true if lock must be dropped but req_list may not be advanced */ u8 busy; }; @@ -103,6 +105,4 @@ extern void musb_gadget_cleanup(struct musb *); extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int); -extern int musb_gadget_set_halt(struct usb_ep *ep, int value); - #endif /* __MUSB_GADGET_H */ diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 522efb31b56b5304a0f2d52b4e232749f8c6a319..8fba3f11e473eaeb45502eef094506bd732cb5bd 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -199,7 +199,6 @@ service_in_request(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest) static void musb_g_ep0_giveback(struct musb *musb, struct usb_request *req) { musb_g_giveback(&musb->endpoints[0].ep_in, req, 0); - musb->ep0_state = MUSB_EP0_STAGE_SETUP; } /* @@ -258,30 +257,53 @@ __acquires(musb->lock) case USB_RECIP_INTERFACE: break; case USB_RECIP_ENDPOINT:{ - const u8 num = ctrlrequest->wIndex & 0x0f; - struct musb_ep *musb_ep; + const u8 epnum = + ctrlrequest->wIndex & 0x0f; + struct musb_ep *musb_ep; + struct musb_hw_ep *ep; + void __iomem *regs; + int is_in; + u16 csr; - if (num == 0 - || num >= MUSB_C_NUM_EPS - || ctrlrequest->wValue - != USB_ENDPOINT_HALT) + if (epnum == 0 || epnum >= MUSB_C_NUM_EPS || + ctrlrequest->wValue != USB_ENDPOINT_HALT) break; - if (ctrlrequest->wIndex & USB_DIR_IN) - musb_ep = &musb->endpoints[num].ep_in; + ep = musb->endpoints + epnum; + regs = ep->regs; + is_in = ctrlrequest->wIndex & USB_DIR_IN; + if (is_in) + musb_ep = &ep->ep_in; else - musb_ep = &musb->endpoints[num].ep_out; + musb_ep = &ep->ep_out; if (!musb_ep->desc) break; - /* REVISIT do it directly, no locking games */ - spin_unlock(&musb->lock); - musb_gadget_set_halt(&musb_ep->end_point, 0); - spin_lock(&musb->lock); + handled = 1; + /* Ignore request if endpoint is wedged */ + if (musb_ep->wedged) + break; + + musb_ep_select(mbase, epnum); + if (is_in) { + csr = musb_readw(regs, MUSB_TXCSR); + csr |= MUSB_TXCSR_CLRDATATOG | + MUSB_TXCSR_P_WZC_BITS; + csr &= ~(MUSB_TXCSR_P_SENDSTALL | + MUSB_TXCSR_P_SENTSTALL | + MUSB_TXCSR_TXPKTRDY); + musb_writew(regs, MUSB_TXCSR, csr); + } else { + csr = musb_readw(regs, MUSB_RXCSR); + csr |= MUSB_RXCSR_CLRDATATOG | + MUSB_RXCSR_P_WZC_BITS; + csr &= ~(MUSB_RXCSR_P_SENDSTALL | + MUSB_RXCSR_P_SENTSTALL); + musb_writew(regs, MUSB_RXCSR, csr); + } /* select ep0 again */ musb_ep_select(mbase, 0); - handled = 1; } break; default: /* class, vendor, etc ... delegate */ @@ -374,10 +396,8 @@ stall: int is_in; u16 csr; - if (epnum == 0 - || epnum >= MUSB_C_NUM_EPS - || ctrlrequest->wValue - != USB_ENDPOINT_HALT) + if (epnum == 0 || epnum >= MUSB_C_NUM_EPS || + ctrlrequest->wValue != USB_ENDPOINT_HALT) break; ep = musb->endpoints + epnum; @@ -392,24 +412,20 @@ stall: musb_ep_select(mbase, epnum); if (is_in) { - csr = musb_readw(regs, - MUSB_TXCSR); + csr = musb_readw(regs, MUSB_TXCSR); if (csr & MUSB_TXCSR_FIFONOTEMPTY) csr |= MUSB_TXCSR_FLUSHFIFO; csr |= MUSB_TXCSR_P_SENDSTALL | MUSB_TXCSR_CLRDATATOG | MUSB_TXCSR_P_WZC_BITS; - musb_writew(regs, MUSB_TXCSR, - csr); + musb_writew(regs, MUSB_TXCSR, csr); } else { - csr = musb_readw(regs, - MUSB_RXCSR); + csr = musb_readw(regs, MUSB_RXCSR); csr |= MUSB_RXCSR_P_SENDSTALL | MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_CLRDATATOG | MUSB_RXCSR_P_WZC_BITS; - musb_writew(regs, MUSB_RXCSR, - csr); + musb_writew(regs, MUSB_RXCSR, csr); } /* select ep0 again */ diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index e3ab40a966eb4ce4f5b9a35eecdbf1ed49e48477..74c4c3698f1ebbff7511b85b78a1010a284eba4a 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1642,18 +1642,18 @@ void musb_host_rx(struct musb *musb, u8 epnum) c = musb->dma_controller; if (usb_pipeisoc(pipe)) { - int status = 0; + int d_status = 0; struct usb_iso_packet_descriptor *d; d = urb->iso_frame_desc + qh->iso_idx; if (iso_err) { - status = -EILSEQ; + d_status = -EILSEQ; urb->error_count++; } if (rx_count > d->length) { - if (status == 0) { - status = -EOVERFLOW; + if (d_status == 0) { + d_status = -EOVERFLOW; urb->error_count++; } DBG(2, "** OVERFLOW %d into %d\n",\ @@ -1662,7 +1662,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) length = d->length; } else length = rx_count; - d->status = status; + d->status = d_status; buf = urb->transfer_dma + d->offset; } else { length = rx_count; diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index cc1d71b57d3cae33435d2f204fb60b12dd6aa41d..473a94ef905f9f620b31480c29865b407d4d3cb9 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -465,9 +465,9 @@ static inline u16 musb_read_hwvers(void __iomem *mbase) return 0; } -static inline u16 musb_read_target_reg_base(u8 i, void __iomem *mbase) +static inline void __iomem *musb_read_target_reg_base(u8 i, void __iomem *mbase) { - return 0; + return NULL; } static inline void musb_write_rxfunaddr(void __iomem *ep_target_regs, diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 5e83f96d6b77f5588f7dfe6ffa82644787d91c8e..a237550f91bfdd17acd3f9ff40b1f124ce3b0e12 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -259,6 +259,11 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) if (!int_hsdma) goto done; +#ifdef CONFIG_BLACKFIN + /* Clear DMA interrupt flags */ + musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma); +#endif + for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) { if (int_hsdma & (1 << bchannel)) { musb_channel = (struct musb_dma_channel *) @@ -280,7 +285,7 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) channel->actual_len = addr - musb_channel->start_addr; - DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n", + DBG(2, "ch %p, 0x%x -> 0x%x (%zu / %d) %s\n", channel, musb_channel->start_addr, addr, channel->actual_len, musb_channel->len, @@ -324,11 +329,6 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) } } -#ifdef CONFIG_BLACKFIN - /* Clear DMA interrup flags */ - musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma); -#endif - retval = IRQ_HANDLED; done: spin_unlock_irqrestore(&musb->lock, flags); diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 6761d2088db85e955b2dc28e21a9e80da11db37b..83beeac5e7bf3ba55982e1c8feab9e7f0c3e0011 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -315,7 +315,7 @@ int musb_platform_exit(struct musb *musb) musb_platform_suspend(musb); clk_put(musb->clock); - musb->clock = 0; + musb->clock = NULL; return 0; } diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index aa884d072f0b4c7202e5b421e52b0ca37a5163de..de56b3d743d781a4294801e32af9341967943d06 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -41,6 +41,15 @@ config ISP1301_OMAP This driver can also be built as a module. If so, the module will be called isp1301_omap. +config USB_ULPI + bool "Generic ULPI Transceiver Driver" + depends on ARM + help + Enable this to support ULPI connected USB OTG transceivers which + are likely found on embedded boards. + + The only chip currently supported is NXP's ISP1504 + config TWL4030_USB tristate "TWL4030 USB Transceiver Driver" depends on TWL4030_CORE && REGULATOR_TWL4030 diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 208167856529f26225807cd7edea4fb29a3640e9..aeb49a8ec4127185584ad286aacb0489bc3075f5 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o +obj-$(CONFIG_USB_ULPI) += ulpi.o ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 9e3e7a5c258bc32d78678e5b05bb877dcac46be6..2be9f2fa41f91b87d6f794b57ca0c7c39cd522f1 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include @@ -276,16 +276,16 @@ static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl, { u8 check; - if ((twl4030_i2c_write_u8(module, data, address) >= 0) && - (twl4030_i2c_read_u8(module, &check, address) >= 0) && + if ((twl_i2c_write_u8(module, data, address) >= 0) && + (twl_i2c_read_u8(module, &check, address) >= 0) && (check == data)) return 0; dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", 1, module, address, check, data); /* Failed once: Try again */ - if ((twl4030_i2c_write_u8(module, data, address) >= 0) && - (twl4030_i2c_read_u8(module, &check, address) >= 0) && + if ((twl_i2c_write_u8(module, data, address) >= 0) && + (twl_i2c_read_u8(module, &check, address) >= 0) && (check == data)) return 0; dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", @@ -303,7 +303,7 @@ static inline int twl4030_usb_write(struct twl4030_usb *twl, { int ret = 0; - ret = twl4030_i2c_write_u8(TWL4030_MODULE_USB, data, address); + ret = twl_i2c_write_u8(TWL4030_MODULE_USB, data, address); if (ret < 0) dev_dbg(twl->dev, "TWL4030:USB:Write[0x%x] Error %d\n", address, ret); @@ -315,7 +315,7 @@ static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address) u8 data; int ret = 0; - ret = twl4030_i2c_read_u8(module, &data, address); + ret = twl_i2c_read_u8(module, &data, address); if (ret >= 0) ret = data; else @@ -462,7 +462,7 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) * SLEEP. We work around this by clearing the bit after usv3v1 * is re-activated. This ensures that VUSB3V1 is really active. */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, + twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); regulator_enable(twl->usb1v5); pwr &= ~PHY_PWR_PHYPWD; @@ -505,44 +505,44 @@ static void twl4030_phy_resume(struct twl4030_usb *twl) static int twl4030_usb_ldo_init(struct twl4030_usb *twl) { /* Enable writing to power configuration registers */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); - twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY); + twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); + twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY); /* put VUSB3V1 LDO in active state */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); + twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); /* input to VUSB3V1 LDO is from VBAT, not VBUS */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); + twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); /* Initialize 3.1V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); + twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); twl->usb3v1 = regulator_get(twl->dev, "usb3v1"); if (IS_ERR(twl->usb3v1)) return -ENODEV; - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); + twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); /* Initialize 1.5V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); + twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); twl->usb1v5 = regulator_get(twl->dev, "usb1v5"); if (IS_ERR(twl->usb1v5)) goto fail1; - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); + twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); /* Initialize 1.8V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); + twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); twl->usb1v8 = regulator_get(twl->dev, "usb1v8"); if (IS_ERR(twl->usb1v8)) goto fail2; - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); + twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); /* disable access to power configuration registers */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); + twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); return 0; @@ -598,12 +598,12 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) * USB_LINK_VBUS state. musb_hdrc won't care until it * starts to handle softconnect right. */ - twl4030charger_usb_en(status == USB_LINK_VBUS); - if (status == USB_LINK_NONE) twl4030_phy_suspend(twl, 0); else twl4030_phy_resume(twl); + + twl4030charger_usb_en(status == USB_LINK_VBUS); } sysfs_notify(&twl->dev->kobj, NULL, "vbus"); diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c new file mode 100644 index 0000000000000000000000000000000000000000..896527456b7e4fee4632672b47c9822d39d33da6 --- /dev/null +++ b/drivers/usb/otg/ulpi.c @@ -0,0 +1,136 @@ +/* + * Generic ULPI USB transceiver support + * + * Copyright (C) 2009 Daniel Mack + * + * Based on sources from + * + * Sascha Hauer + * Freescale Semiconductors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You 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 + +/* ULPI register addresses */ +#define ULPI_VID_LOW 0x00 /* Vendor ID low */ +#define ULPI_VID_HIGH 0x01 /* Vendor ID high */ +#define ULPI_PID_LOW 0x02 /* Product ID low */ +#define ULPI_PID_HIGH 0x03 /* Product ID high */ +#define ULPI_ITFCTL 0x07 /* Interface Control */ +#define ULPI_OTGCTL 0x0A /* OTG Control */ + +/* add to above register address to access Set/Clear functions */ +#define ULPI_REG_SET 0x01 +#define ULPI_REG_CLEAR 0x02 + +/* ULPI OTG Control Register bits */ +#define ID_PULL_UP (1 << 0) /* enable ID Pull Up */ +#define DP_PULL_DOWN (1 << 1) /* enable DP Pull Down */ +#define DM_PULL_DOWN (1 << 2) /* enable DM Pull Down */ +#define DISCHRG_VBUS (1 << 3) /* Discharge Vbus */ +#define CHRG_VBUS (1 << 4) /* Charge Vbus */ +#define DRV_VBUS (1 << 5) /* Drive Vbus */ +#define DRV_VBUS_EXT (1 << 6) /* Drive Vbus external */ +#define USE_EXT_VBUS_IND (1 << 7) /* Use ext. Vbus indicator */ + +#define ULPI_ID(vendor, product) (((vendor) << 16) | (product)) + +#define TR_FLAG(flags, a, b) (((flags) & a) ? b : 0) + +/* ULPI hardcoded IDs, used for probing */ +static unsigned int ulpi_ids[] = { + ULPI_ID(0x04cc, 0x1504), /* NXP ISP1504 */ +}; + +static int ulpi_set_flags(struct otg_transceiver *otg) +{ + unsigned int flags = 0; + + if (otg->flags & USB_OTG_PULLUP_ID) + flags |= ID_PULL_UP; + + if (otg->flags & USB_OTG_PULLDOWN_DM) + flags |= DM_PULL_DOWN; + + if (otg->flags & USB_OTG_PULLDOWN_DP) + flags |= DP_PULL_DOWN; + + if (otg->flags & USB_OTG_EXT_VBUS_INDICATOR) + flags |= USE_EXT_VBUS_IND; + + return otg_io_write(otg, flags, ULPI_OTGCTL + ULPI_REG_SET); +} + +static int ulpi_init(struct otg_transceiver *otg) +{ + int i, vid, pid; + + vid = (otg_io_read(otg, ULPI_VID_HIGH) << 8) | + otg_io_read(otg, ULPI_VID_LOW); + pid = (otg_io_read(otg, ULPI_PID_HIGH) << 8) | + otg_io_read(otg, ULPI_PID_LOW); + + pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid); + + for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) + if (ulpi_ids[i] == ULPI_ID(vid, pid)) + return ulpi_set_flags(otg); + + pr_err("ULPI ID does not match any known transceiver.\n"); + return -ENODEV; +} + +static int ulpi_set_vbus(struct otg_transceiver *otg, bool on) +{ + unsigned int flags = otg_io_read(otg, ULPI_OTGCTL); + + flags &= ~(DRV_VBUS | DRV_VBUS_EXT); + + if (on) { + if (otg->flags & USB_OTG_DRV_VBUS) + flags |= DRV_VBUS; + + if (otg->flags & USB_OTG_DRV_VBUS_EXT) + flags |= DRV_VBUS_EXT; + } + + return otg_io_write(otg, flags, ULPI_OTGCTL + ULPI_REG_SET); +} + +struct otg_transceiver * +otg_ulpi_create(struct otg_io_access_ops *ops, + unsigned int flags) +{ + struct otg_transceiver *otg; + + otg = kzalloc(sizeof(*otg), GFP_KERNEL); + if (!otg) + return NULL; + + otg->label = "ULPI"; + otg->flags = flags; + otg->io_ops = ops; + otg->init = ulpi_init; + otg->set_vbus = ulpi_set_vbus; + + return otg; +} +EXPORT_SYMBOL_GPL(otg_ulpi_create); + diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 131e61adaaf72bdab5da517830ed43293eb2a69e..a9c2dec8e3fb66ce7233e8185c8d08fb4a2cedad 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -1,4 +1,6 @@ /* + * Copyright (C) 2009 by Bart Hartgers (bart.hartgers+ark3116@gmail.com) + * Original version: * Copyright (C) 2006 * Simon Schulz (ark3116_driver auctionant.de) * @@ -6,10 +8,13 @@ * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547, * productid=0x0232) (used in a datacable called KQ-U8A) * - * - based on code by krisfx -> thanks !! - * (see http://www.linuxquestions.org/questions/showthread.php?p=2184457#post2184457) + * Supports full modem status lines, break, hardware flow control. Does not + * support software flow control, since I do not know how to enable it in hw. * - * - based on logs created by usbsnoopy + * This driver is a essentially new implementation. I initially dug + * into the old ark3116.c driver and suddenly realized the ark3116 is + * a 16450 with a USB interface glued to it. See comments at the + * bottom of this file. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -19,15 +24,31 @@ #include #include +#include #include +#include #include #include #include #include +#include #include - +#include +#include static int debug; +/* + * Version information + */ + +#define DRIVER_VERSION "v0.5" +#define DRIVER_AUTHOR "Bart Hartgers " +#define DRIVER_DESC "USB ARK3116 serial/IrDA driver" +#define DRIVER_DEV_DESC "ARK3116 RS232/IrDA" +#define DRIVER_NAME "ark3116" + +/* usb timeout of 1 second */ +#define ARK_TIMEOUT (1*HZ) static struct usb_device_id id_table [] = { { USB_DEVICE(0x6547, 0x0232) }, @@ -45,118 +66,152 @@ static int is_irda(struct usb_serial *serial) return 0; } -static inline void ARK3116_SND(struct usb_serial *serial, int seq, - __u8 request, __u8 requesttype, - __u16 value, __u16 index) +struct ark3116_private { + wait_queue_head_t delta_msr_wait; + struct async_icount icount; + int irda; /* 1 for irda device */ + + /* protects hw register updates */ + struct mutex hw_lock; + + int quot; /* baudrate divisor */ + __u32 lcr; /* line control register value */ + __u32 hcr; /* handshake control register (0x8) + * value */ + __u32 mcr; /* modem contol register value */ + + /* protects the status values below */ + spinlock_t status_lock; + __u32 msr; /* modem status register value */ + __u32 lsr; /* line status register value */ +}; + +static int ark3116_write_reg(struct usb_serial *serial, + unsigned reg, __u8 val) { int result; + /* 0xfe 0x40 are magic values taken from original driver */ result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - request, requesttype, value, index, - NULL, 0x00, 1000); - dbg("%03d > ok", seq); + 0xfe, 0x40, val, reg, + NULL, 0, ARK_TIMEOUT); + return result; } -static inline void ARK3116_RCV(struct usb_serial *serial, int seq, - __u8 request, __u8 requesttype, - __u16 value, __u16 index, __u8 expected, - char *buf) +static int ark3116_read_reg(struct usb_serial *serial, + unsigned reg, unsigned char *buf) { int result; + /* 0xfe 0xc0 are magic values taken from original driver */ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - request, requesttype, value, index, - buf, 0x0000001, 1000); - if (result) - dbg("%03d < %d bytes [0x%02X]", seq, result, - ((unsigned char *)buf)[0]); + 0xfe, 0xc0, 0, reg, + buf, 1, ARK_TIMEOUT); + if (result < 0) + return result; else - dbg("%03d < 0 bytes", seq); + return buf[0]; } -static inline void ARK3116_RCV_QUIET(struct usb_serial *serial, - __u8 request, __u8 requesttype, - __u16 value, __u16 index, char *buf) +static inline int calc_divisor(int bps) { - usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - request, requesttype, value, index, - buf, 0x0000001, 1000); + /* Original ark3116 made some exceptions in rounding here + * because windows did the same. Assume that is not really + * necessary. + * Crystal is 12MHz, probably because of USB, but we divide by 4? + */ + return (12000000 + 2*bps) / (4*bps); } static int ark3116_attach(struct usb_serial *serial) { - char *buf; + struct usb_serial_port *port = serial->port[0]; + struct ark3116_private *priv; + + /* make sure we have our end-points */ + if ((serial->num_bulk_in == 0) || + (serial->num_bulk_out == 0) || + (serial->num_interrupt_in == 0)) { + dev_err(&serial->dev->dev, + "%s - missing endpoint - " + "bulk in: %d, bulk out: %d, int in %d\n", + KBUILD_MODNAME, + serial->num_bulk_in, + serial->num_bulk_out, + serial->num_interrupt_in); + return -EINVAL; + } - buf = kmalloc(1, GFP_KERNEL); - if (!buf) { - dbg("error kmalloc -> out of mem?"); + priv = kzalloc(sizeof(struct ark3116_private), + GFP_KERNEL); + if (!priv) return -ENOMEM; - } - if (is_irda(serial)) - dbg("IrDA mode"); + init_waitqueue_head(&priv->delta_msr_wait); + mutex_init(&priv->hw_lock); + spin_lock_init(&priv->status_lock); + + priv->irda = is_irda(serial); - /* 3 */ - ARK3116_SND(serial, 3, 0xFE, 0x40, 0x0008, 0x0002); - ARK3116_SND(serial, 4, 0xFE, 0x40, 0x0008, 0x0001); - ARK3116_SND(serial, 5, 0xFE, 0x40, 0x0000, 0x0008); - ARK3116_SND(serial, 6, 0xFE, 0x40, is_irda(serial) ? 0x0001 : 0x0000, - 0x000B); + usb_set_serial_port_data(port, priv); - if (is_irda(serial)) { - ARK3116_SND(serial, 1001, 0xFE, 0x40, 0x0000, 0x000C); - ARK3116_SND(serial, 1002, 0xFE, 0x40, 0x0041, 0x000D); - ARK3116_SND(serial, 1003, 0xFE, 0x40, 0x0001, 0x000A); + /* setup the hardware */ + ark3116_write_reg(serial, UART_IER, 0); + /* disable DMA */ + ark3116_write_reg(serial, UART_FCR, 0); + /* handshake control */ + priv->hcr = 0; + ark3116_write_reg(serial, 0x8 , 0); + /* modem control */ + priv->mcr = 0; + ark3116_write_reg(serial, UART_MCR, 0); + + if (!(priv->irda)) { + ark3116_write_reg(serial, 0xb , 0); + } else { + ark3116_write_reg(serial, 0xb , 1); + ark3116_write_reg(serial, 0xc , 0); + ark3116_write_reg(serial, 0xd , 0x41); + ark3116_write_reg(serial, 0xa , 1); } - /* <-- seq7 */ - ARK3116_RCV(serial, 7, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf); - ARK3116_SND(serial, 8, 0xFE, 0x40, 0x0080, 0x0003); - ARK3116_SND(serial, 9, 0xFE, 0x40, 0x001A, 0x0000); - ARK3116_SND(serial, 10, 0xFE, 0x40, 0x0000, 0x0001); - ARK3116_SND(serial, 11, 0xFE, 0x40, 0x0000, 0x0003); - - /* <-- seq12 */ - ARK3116_RCV(serial, 12, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); - ARK3116_SND(serial, 13, 0xFE, 0x40, 0x0000, 0x0004); - - /* 14 */ - ARK3116_RCV(serial, 14, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); - ARK3116_SND(serial, 15, 0xFE, 0x40, 0x0000, 0x0004); - - /* 16 */ - ARK3116_RCV(serial, 16, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); - /* --> seq17 */ - ARK3116_SND(serial, 17, 0xFE, 0x40, 0x0001, 0x0004); - - /* <-- seq18 */ - ARK3116_RCV(serial, 18, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf); - - /* --> seq19 */ - ARK3116_SND(serial, 19, 0xFE, 0x40, 0x0003, 0x0004); - - /* <-- seq20 */ - /* seems like serial port status info (RTS, CTS, ...) */ - /* returns modem control line status?! */ - ARK3116_RCV(serial, 20, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf); - - /* set 9600 baud & do some init?! */ - ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003); - ARK3116_SND(serial, 148, 0xFE, 0x40, 0x0038, 0x0000); - ARK3116_SND(serial, 149, 0xFE, 0x40, 0x0001, 0x0001); - if (is_irda(serial)) - ARK3116_SND(serial, 1004, 0xFE, 0x40, 0x0000, 0x0009); - ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003); - ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf); - ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003); - ARK3116_RCV(serial, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf); - ARK3116_SND(serial, 154, 0xFE, 0x40, 0x0003, 0x0003); + /* setup baudrate */ + ark3116_write_reg(serial, UART_LCR, UART_LCR_DLAB); - kfree(buf); + /* setup for 9600 8N1 */ + priv->quot = calc_divisor(9600); + ark3116_write_reg(serial, UART_DLL, priv->quot & 0xff); + ark3116_write_reg(serial, UART_DLM, (priv->quot>>8) & 0xff); + + priv->lcr = UART_LCR_WLEN8; + ark3116_write_reg(serial, UART_LCR, UART_LCR_WLEN8); + + ark3116_write_reg(serial, 0xe, 0); + + if (priv->irda) + ark3116_write_reg(serial, 0x9, 0); + + dev_info(&serial->dev->dev, + "%s using %s mode\n", + KBUILD_MODNAME, + priv->irda ? "IrDA" : "RS232"); return 0; } +static void ark3116_release(struct usb_serial *serial) +{ + struct usb_serial_port *port = serial->port[0]; + struct ark3116_private *priv = usb_get_serial_port_data(port); + + /* device is closed, so URBs and DMA should be down */ + + usb_set_serial_port_data(port, NULL); + + mutex_destroy(&priv->hw_lock); + + kfree(priv); +} + static void ark3116_init_termios(struct tty_struct *tty) { struct ktermios *termios = tty->termios; @@ -172,200 +227,189 @@ static void ark3116_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; + struct ark3116_private *priv = usb_get_serial_port_data(port); struct ktermios *termios = tty->termios; unsigned int cflag = termios->c_cflag; - int baud; - int ark3116_baud; - char *buf; - char config; - - config = 0; - - dbg("%s - port %d", __func__, port->number); + int bps = tty_get_baud_rate(tty); + int quot; + __u8 lcr, hcr, eval; + + /* set data bit count */ + switch (cflag & CSIZE) { + case CS5: + lcr = UART_LCR_WLEN5; + break; + case CS6: + lcr = UART_LCR_WLEN6; + break; + case CS7: + lcr = UART_LCR_WLEN7; + break; + default: + case CS8: + lcr = UART_LCR_WLEN8; + break; + } + if (cflag & CSTOPB) + lcr |= UART_LCR_STOP; + if (cflag & PARENB) + lcr |= UART_LCR_PARITY; + if (!(cflag & PARODD)) + lcr |= UART_LCR_EPAR; +#ifdef CMSPAR + if (cflag & CMSPAR) + lcr |= UART_LCR_SPAR; +#endif + /* handshake control */ + hcr = (cflag & CRTSCTS) ? 0x03 : 0x00; + + /* calc baudrate */ + dbg("%s - setting bps to %d", __func__, bps); + eval = 0; + switch (bps) { + case 0: + quot = calc_divisor(9600); + break; + default: + if ((bps < 75) || (bps > 3000000)) + bps = 9600; + quot = calc_divisor(bps); + break; + case 460800: + eval = 1; + quot = calc_divisor(bps); + break; + case 921600: + eval = 2; + quot = calc_divisor(bps); + break; + } + /* Update state: synchronize */ + mutex_lock(&priv->hw_lock); - cflag = termios->c_cflag; - termios->c_cflag &= ~(CMSPAR|CRTSCTS); + /* keep old LCR_SBC bit */ + lcr |= (priv->lcr & UART_LCR_SBC); - buf = kmalloc(1, GFP_KERNEL); - if (!buf) { - dbg("error kmalloc"); - *termios = *old_termios; - return; - } + dbg("%s - setting hcr:0x%02x,lcr:0x%02x,quot:%d", + __func__, hcr, lcr, quot); - /* set data bit count (8/7/6/5) */ - if (cflag & CSIZE) { - switch (cflag & CSIZE) { - case CS5: - config |= 0x00; - dbg("setting CS5"); - break; - case CS6: - config |= 0x01; - dbg("setting CS6"); - break; - case CS7: - config |= 0x02; - dbg("setting CS7"); - break; - default: - dbg("CSIZE was set but not CS5-CS8, using CS8!"); - /* fall through */ - case CS8: - config |= 0x03; - dbg("setting CS8"); - break; - } + /* handshake control */ + if (priv->hcr != hcr) { + priv->hcr = hcr; + ark3116_write_reg(serial, 0x8, hcr); } - /* set parity (NONE/EVEN/ODD) */ - if (cflag & PARENB) { - if (cflag & PARODD) { - config |= 0x08; - dbg("setting parity to ODD"); - } else { - config |= 0x18; - dbg("setting parity to EVEN"); - } - } else { - dbg("setting parity to NONE"); + /* baudrate */ + if (priv->quot != quot) { + priv->quot = quot; + priv->lcr = lcr; /* need to write lcr anyway */ + + /* disable DMA since transmit/receive is + * shadowed by UART_DLL + */ + ark3116_write_reg(serial, UART_FCR, 0); + + ark3116_write_reg(serial, UART_LCR, + lcr|UART_LCR_DLAB); + ark3116_write_reg(serial, UART_DLL, quot & 0xff); + ark3116_write_reg(serial, UART_DLM, (quot>>8) & 0xff); + + /* restore lcr */ + ark3116_write_reg(serial, UART_LCR, lcr); + /* magic baudrate thingy: not sure what it does, + * but windows does this as well. + */ + ark3116_write_reg(serial, 0xe, eval); + + /* enable DMA */ + ark3116_write_reg(serial, UART_FCR, UART_FCR_DMA_SELECT); + } else if (priv->lcr != lcr) { + priv->lcr = lcr; + ark3116_write_reg(serial, UART_LCR, lcr); } - /* set stop bit (1/2) */ - if (cflag & CSTOPB) { - config |= 0x04; - dbg("setting 2 stop bits"); - } else { - dbg("setting 1 stop bit"); - } + mutex_unlock(&priv->hw_lock); - /* set baudrate */ - baud = tty_get_baud_rate(tty); - - switch (baud) { - case 75: - case 150: - case 300: - case 600: - case 1200: - case 1800: - case 2400: - case 4800: - case 9600: - case 19200: - case 38400: - case 57600: - case 115200: - case 230400: - case 460800: - /* Report the resulting rate back to the caller */ - tty_encode_baud_rate(tty, baud, baud); - break; - /* set 9600 as default (if given baudrate is invalid for example) */ - default: - tty_encode_baud_rate(tty, 9600, 9600); - case 0: - baud = 9600; + /* check for software flow control */ + if (I_IXOFF(tty) || I_IXON(tty)) { + dev_warn(&serial->dev->dev, + "%s: don't know how to do software flow control\n", + KBUILD_MODNAME); } - /* - * found by try'n'error, be careful, maybe there are other options - * for multiplicator etc! (3.5 for example) - */ - if (baud == 460800) - /* strange, for 460800 the formula is wrong - * if using round() then 9600baud is wrong) */ - ark3116_baud = 7; - else - ark3116_baud = 3000000 / baud; - - /* ? */ - ARK3116_RCV(serial, 0, 0xFE, 0xC0, 0x0000, 0x0003, 0x03, buf); - - /* offset = buf[0]; */ - /* offset = 0x03; */ - /* dbg("using 0x%04X as target for 0x0003:", 0x0080 + offset); */ - - /* set baudrate */ - dbg("setting baudrate to %d (->reg=%d)", baud, ark3116_baud); - ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003); - ARK3116_SND(serial, 148, 0xFE, 0x40, - (ark3116_baud & 0x00FF), 0x0000); - ARK3116_SND(serial, 149, 0xFE, 0x40, - (ark3116_baud & 0xFF00) >> 8, 0x0001); - ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003); - - /* ? */ - ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf); - ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003); - - /* set data bit count, stop bit count & parity: */ - dbg("updating bit count, stop bit or parity (cfg=0x%02X)", config); - ARK3116_RCV(serial, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf); - ARK3116_SND(serial, 154, 0xFE, 0x40, config, 0x0003); + /* Don't rewrite B0 */ + if (tty_termios_baud_rate(termios)) + tty_termios_encode_baud_rate(termios, bps, bps); +} - if (cflag & CRTSCTS) - dbg("CRTSCTS not supported by chipset?!"); +static void ark3116_close(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; - /* TEST ARK3116_SND(154, 0xFE, 0x40, 0xFFFF, 0x0006); */ + if (serial->dev) { + /* disable DMA */ + ark3116_write_reg(serial, UART_FCR, 0); - kfree(buf); + /* deactivate interrupts */ + ark3116_write_reg(serial, UART_IER, 0); - return; + /* shutdown any bulk reads that might be going on */ + if (serial->num_bulk_out) + usb_kill_urb(port->write_urb); + if (serial->num_bulk_in) + usb_kill_urb(port->read_urb); + if (serial->num_interrupt_in) + usb_kill_urb(port->interrupt_in_urb); + } } static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port) { - struct ktermios tmp_termios; + struct ark3116_private *priv = usb_get_serial_port_data(port); struct usb_serial *serial = port->serial; - char *buf; - int result = 0; - - dbg("%s - port %d", __func__, port->number); + unsigned char *buf; + int result; buf = kmalloc(1, GFP_KERNEL); - if (!buf) { - dbg("error kmalloc -> out of mem?"); + if (buf == NULL) return -ENOMEM; - } result = usb_serial_generic_open(tty, port); - if (result) + if (result) { + dbg("%s - usb_serial_generic_open failed: %d", + __func__, result); goto err_out; + } - /* open */ - ARK3116_RCV(serial, 111, 0xFE, 0xC0, 0x0000, 0x0003, 0x02, buf); - - ARK3116_SND(serial, 112, 0xFE, 0x40, 0x0082, 0x0003); - ARK3116_SND(serial, 113, 0xFE, 0x40, 0x001A, 0x0000); - ARK3116_SND(serial, 114, 0xFE, 0x40, 0x0000, 0x0001); - ARK3116_SND(serial, 115, 0xFE, 0x40, 0x0002, 0x0003); - - ARK3116_RCV(serial, 116, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf); - ARK3116_SND(serial, 117, 0xFE, 0x40, 0x0002, 0x0004); - - ARK3116_RCV(serial, 118, 0xFE, 0xC0, 0x0000, 0x0004, 0x02, buf); - ARK3116_SND(serial, 119, 0xFE, 0x40, 0x0000, 0x0004); - - ARK3116_RCV(serial, 120, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); + /* setup termios */ + if (tty) + ark3116_set_termios(tty, port, NULL); - ARK3116_SND(serial, 121, 0xFE, 0x40, 0x0001, 0x0004); + /* remove any data still left: also clears error state */ + ark3116_read_reg(serial, UART_RX, buf); - ARK3116_RCV(serial, 122, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf); + /* read modem status */ + priv->msr = ark3116_read_reg(serial, UART_MSR, buf); + /* read line status */ + priv->lsr = ark3116_read_reg(serial, UART_LSR, buf); - ARK3116_SND(serial, 123, 0xFE, 0x40, 0x0003, 0x0004); + result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (result) { + dev_err(&port->dev, "submit irq_in urb failed %d\n", + result); + ark3116_close(port); + goto err_out; + } - /* returns different values (control lines?!) */ - ARK3116_RCV(serial, 124, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf); + /* activate interrupts */ + ark3116_write_reg(port->serial, UART_IER, UART_IER_MSI|UART_IER_RLSI); - /* initialise termios */ - if (tty) - ark3116_set_termios(tty, port, &tmp_termios); + /* enable DMA */ + ark3116_write_reg(port->serial, UART_FCR, UART_FCR_DMA_SELECT); err_out: kfree(buf); - return result; } @@ -373,6 +417,7 @@ static int ark3116_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { struct usb_serial_port *port = tty->driver_data; + struct ark3116_private *priv = usb_get_serial_port_data(port); struct serial_struct serstruct; void __user *user_arg = (void __user *)arg; @@ -394,9 +439,48 @@ static int ark3116_ioctl(struct tty_struct *tty, struct file *file, if (copy_from_user(&serstruct, user_arg, sizeof(serstruct))) return -EFAULT; return 0; - default: - dbg("%s cmd 0x%04x not supported", __func__, cmd); + case TIOCMIWAIT: + for (;;) { + struct async_icount prev = priv->icount; + interruptible_sleep_on(&priv->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + if ((prev.rng == priv->icount.rng) && + (prev.dsr == priv->icount.dsr) && + (prev.dcd == priv->icount.dcd) && + (prev.cts == priv->icount.cts)) + return -EIO; + if ((arg & TIOCM_RNG && + (prev.rng != priv->icount.rng)) || + (arg & TIOCM_DSR && + (prev.dsr != priv->icount.dsr)) || + (arg & TIOCM_CD && + (prev.dcd != priv->icount.dcd)) || + (arg & TIOCM_CTS && + (prev.cts != priv->icount.cts))) + return 0; + } break; + case TIOCGICOUNT: { + struct serial_icounter_struct icount; + struct async_icount cnow = priv->icount; + memset(&icount, 0, sizeof(icount)); + icount.cts = cnow.cts; + icount.dsr = cnow.dsr; + icount.rng = cnow.rng; + icount.dcd = cnow.dcd; + icount.rx = cnow.rx; + icount.tx = cnow.tx; + icount.frame = cnow.frame; + icount.overrun = cnow.overrun; + icount.parity = cnow.parity; + icount.brk = cnow.brk; + icount.buf_overrun = cnow.buf_overrun; + if (copy_to_user(user_arg, &icount, sizeof(icount))) + return -EFAULT; + return 0; + } } return -ENOIOCTLCMD; @@ -405,32 +489,273 @@ static int ark3116_ioctl(struct tty_struct *tty, struct file *file, static int ark3116_tiocmget(struct tty_struct *tty, struct file *file) { struct usb_serial_port *port = tty->driver_data; - struct usb_serial *serial = port->serial; - char *buf; - char temp; + struct ark3116_private *priv = usb_get_serial_port_data(port); + __u32 status; + __u32 ctrl; + unsigned long flags; + + mutex_lock(&priv->hw_lock); + ctrl = priv->mcr; + mutex_unlock(&priv->hw_lock); + + spin_lock_irqsave(&priv->status_lock, flags); + status = priv->msr; + spin_unlock_irqrestore(&priv->status_lock, flags); + + return (status & UART_MSR_DSR ? TIOCM_DSR : 0) | + (status & UART_MSR_CTS ? TIOCM_CTS : 0) | + (status & UART_MSR_RI ? TIOCM_RI : 0) | + (status & UART_MSR_DCD ? TIOCM_CD : 0) | + (ctrl & UART_MCR_DTR ? TIOCM_DTR : 0) | + (ctrl & UART_MCR_RTS ? TIOCM_RTS : 0) | + (ctrl & UART_MCR_OUT1 ? TIOCM_OUT1 : 0) | + (ctrl & UART_MCR_OUT2 ? TIOCM_OUT2 : 0); +} - /* seems like serial port status info (RTS, CTS, ...) is stored - * in reg(?) 0x0006 - * pcb connection point 11 = GND -> sets bit4 of response - * pcb connection point 7 = GND -> sets bit6 of response +static int ark3116_tiocmset(struct tty_struct *tty, struct file *file, + unsigned set, unsigned clr) +{ + struct usb_serial_port *port = tty->driver_data; + struct ark3116_private *priv = usb_get_serial_port_data(port); + + /* we need to take the mutex here, to make sure that the value + * in priv->mcr is actually the one that is in the hardware */ - buf = kmalloc(1, GFP_KERNEL); - if (!buf) { - dbg("error kmalloc"); - return -ENOMEM; + mutex_lock(&priv->hw_lock); + + if (set & TIOCM_RTS) + priv->mcr |= UART_MCR_RTS; + if (set & TIOCM_DTR) + priv->mcr |= UART_MCR_DTR; + if (set & TIOCM_OUT1) + priv->mcr |= UART_MCR_OUT1; + if (set & TIOCM_OUT2) + priv->mcr |= UART_MCR_OUT2; + if (clr & TIOCM_RTS) + priv->mcr &= ~UART_MCR_RTS; + if (clr & TIOCM_DTR) + priv->mcr &= ~UART_MCR_DTR; + if (clr & TIOCM_OUT1) + priv->mcr &= ~UART_MCR_OUT1; + if (clr & TIOCM_OUT2) + priv->mcr &= ~UART_MCR_OUT2; + + ark3116_write_reg(port->serial, UART_MCR, priv->mcr); + + mutex_unlock(&priv->hw_lock); + + return 0; +} + +static void ark3116_break_ctl(struct tty_struct *tty, int break_state) +{ + struct usb_serial_port *port = tty->driver_data; + struct ark3116_private *priv = usb_get_serial_port_data(port); + + /* LCR is also used for other things: protect access */ + mutex_lock(&priv->hw_lock); + + if (break_state) + priv->lcr |= UART_LCR_SBC; + else + priv->lcr &= ~UART_LCR_SBC; + + ark3116_write_reg(port->serial, UART_LCR, priv->lcr); + + mutex_unlock(&priv->hw_lock); +} + +static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr) +{ + struct ark3116_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + + spin_lock_irqsave(&priv->status_lock, flags); + priv->msr = msr; + spin_unlock_irqrestore(&priv->status_lock, flags); + + if (msr & UART_MSR_ANY_DELTA) { + /* update input line counters */ + if (msr & UART_MSR_DCTS) + priv->icount.cts++; + if (msr & UART_MSR_DDSR) + priv->icount.dsr++; + if (msr & UART_MSR_DDCD) + priv->icount.dcd++; + if (msr & UART_MSR_TERI) + priv->icount.rng++; + wake_up_interruptible(&priv->delta_msr_wait); } +} - /* read register */ - ARK3116_RCV_QUIET(serial, 0xFE, 0xC0, 0x0000, 0x0006, buf); - temp = buf[0]; - kfree(buf); +static void ark3116_update_lsr(struct usb_serial_port *port, __u8 lsr) +{ + struct ark3116_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + + spin_lock_irqsave(&priv->status_lock, flags); + /* combine bits */ + priv->lsr |= lsr; + spin_unlock_irqrestore(&priv->status_lock, flags); + + if (lsr&UART_LSR_BRK_ERROR_BITS) { + if (lsr & UART_LSR_BI) + priv->icount.brk++; + if (lsr & UART_LSR_FE) + priv->icount.frame++; + if (lsr & UART_LSR_PE) + priv->icount.parity++; + if (lsr & UART_LSR_OE) + priv->icount.overrun++; + } +} - /* i do not really know if bit4=CTS and bit6=DSR... just a - * quick guess! - */ - return (temp & (1<<4) ? TIOCM_CTS : 0) - | (temp & (1<<6) ? TIOCM_DSR : 0); +static void ark3116_read_int_callback(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + int status = urb->status; + const __u8 *data = urb->transfer_buffer; + int result; + + switch (status) { + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __func__, status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __func__, status); + break; + case 0: /* success */ + /* discovered this by trail and error... */ + if ((urb->actual_length == 4) && (data[0] == 0xe8)) { + const __u8 id = data[1]&UART_IIR_ID; + dbg("%s: iir=%02x", __func__, data[1]); + if (id == UART_IIR_MSI) { + dbg("%s: msr=%02x", __func__, data[3]); + ark3116_update_msr(port, data[3]); + break; + } else if (id == UART_IIR_RLSI) { + dbg("%s: lsr=%02x", __func__, data[2]); + ark3116_update_lsr(port, data[2]); + break; + } + } + /* + * Not sure what this data meant... + */ + usb_serial_debug_data(debug, &port->dev, + __func__, + urb->actual_length, + urb->transfer_buffer); + break; + } + + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) + dev_err(&urb->dev->dev, + "%s - Error %d submitting interrupt urb\n", + __func__, result); +} + + +/* Data comes in via the bulk (data) URB, erors/interrupts via the int URB. + * This means that we cannot be sure which data byte has an associated error + * condition, so we report an error for all data in the next bulk read. + * + * Actually, there might even be a window between the bulk data leaving the + * ark and reading/resetting the lsr in the read_bulk_callback where an + * interrupt for the next data block could come in. + * Without somekind of ordering on the ark, we would have to report the + * error for the next block of data as well... + * For now, let's pretend this can't happen. + */ + +static void send_to_tty(struct tty_struct *tty, + const unsigned char *chars, + size_t size, char flag) +{ + if (size == 0) + return; + if (flag == TTY_NORMAL) { + tty_insert_flip_string(tty, chars, size); + } else { + int i; + for (i = 0; i < size; ++i) + tty_insert_flip_char(tty, chars[i], flag); + } +} + +static void ark3116_read_bulk_callback(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + struct ark3116_private *priv = usb_get_serial_port_data(port); + const __u8 *data = urb->transfer_buffer; + int status = urb->status; + struct tty_struct *tty; + unsigned long flags; + int result; + char flag; + __u32 lsr; + + switch (status) { + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __func__, status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __func__, status); + break; + case 0: /* success */ + + spin_lock_irqsave(&priv->status_lock, flags); + lsr = priv->lsr; + /* clear error bits */ + priv->lsr &= ~UART_LSR_BRK_ERROR_BITS; + spin_unlock_irqrestore(&priv->status_lock, flags); + + if (unlikely(lsr & UART_LSR_BI)) + flag = TTY_BREAK; + else if (unlikely(lsr & UART_LSR_PE)) + flag = TTY_PARITY; + else if (unlikely(lsr & UART_LSR_FE)) + flag = TTY_FRAME; + else + flag = TTY_NORMAL; + + tty = tty_port_tty_get(&port->port); + if (tty) { + tty_buffer_request_room(tty, urb->actual_length + 1); + /* overrun is special, not associated with a char */ + if (unlikely(lsr & UART_LSR_OE)) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + send_to_tty(tty, data, urb->actual_length, flag); + tty_flip_buffer_push(tty); + tty_kref_put(tty); + } + + /* Throttle the device if requested by tty */ + spin_lock_irqsave(&port->lock, flags); + port->throttled = port->throttle_req; + if (port->throttled) { + spin_unlock_irqrestore(&port->lock, flags); + return; + } else + spin_unlock_irqrestore(&port->lock, flags); + } + /* Continue reading from device */ + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) + dev_err(&urb->dev->dev, "%s - failed resubmitting" + " read urb, error %d\n", __func__, result); } static struct usb_driver ark3116_driver = { @@ -450,11 +775,17 @@ static struct usb_serial_driver ark3116_device = { .usb_driver = &ark3116_driver, .num_ports = 1, .attach = ark3116_attach, + .release = ark3116_release, .set_termios = ark3116_set_termios, .init_termios = ark3116_init_termios, .ioctl = ark3116_ioctl, .tiocmget = ark3116_tiocmget, + .tiocmset = ark3116_tiocmset, .open = ark3116_open, + .close = ark3116_close, + .break_ctl = ark3116_break_ctl, + .read_int_callback = ark3116_read_int_callback, + .read_bulk_callback = ark3116_read_bulk_callback, }; static int __init ark3116_init(void) @@ -465,7 +796,12 @@ static int __init ark3116_init(void) if (retval) return retval; retval = usb_register(&ark3116_driver); - if (retval) + if (retval == 0) { + printk(KERN_INFO "%s:" + DRIVER_VERSION ":" + DRIVER_DESC "\n", + KBUILD_MODNAME); + } else usb_serial_deregister(&ark3116_device); return retval; } @@ -480,6 +816,109 @@ module_init(ark3116_init); module_exit(ark3116_exit); MODULE_LICENSE("GPL"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); + module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); +MODULE_PARM_DESC(debug, "Enable debug"); +/* + * The following describes what I learned from studying the old + * ark3116.c driver, disassembling the windows driver, and some lucky + * guesses. Since I do not have any datasheet or other + * documentation, inaccuracies are almost guaranteed. + * + * Some specs for the ARK3116 can be found here: + * http://web.archive.org/web/20060318000438/ + * www.arkmicro.com/en/products/view.php?id=10 + * On that page, 2 GPIO pins are mentioned: I assume these are the + * OUT1 and OUT2 pins of the UART, so I added support for those + * through the MCR. Since the pins are not available on my hardware, + * I could not verify this. + * Also, it states there is "on-chip hardware flow control". I have + * discovered how to enable that. Unfortunately, I do not know how to + * enable XON/XOFF (software) flow control, which would need support + * from the chip as well to work. Because of the wording on the web + * page there is a real possibility the chip simply does not support + * software flow control. + * + * I got my ark3116 as part of a mobile phone adapter cable. On the + * PCB, the following numbered contacts are present: + * + * 1:- +5V + * 2:o DTR + * 3:i RX + * 4:i DCD + * 5:o RTS + * 6:o TX + * 7:i RI + * 8:i DSR + * 10:- 0V + * 11:i CTS + * + * On my chip, all signals seem to be 3.3V, but 5V tolerant. But that + * may be different for the one you have ;-). + * + * The windows driver limits the registers to 0-F, so I assume there + * are actually 16 present on the device. + * + * On an UART interrupt, 4 bytes of data come in on the interrupt + * endpoint. The bytes are 0xe8 IIR LSR MSR. + * + * The baudrate seems to be generated from the 12MHz crystal, using + * 4-times subsampling. So quot=12e6/(4*baud). Also see description + * of register E. + * + * Registers 0-7: + * These seem to be the same as for a regular 16450. The FCR is set + * to UART_FCR_DMA_SELECT (0x8), I guess to enable transfers between + * the UART and the USB bridge/DMA engine. + * + * Register 8: + * By trial and error, I found out that bit 0 enables hardware CTS, + * stopping TX when CTS is +5V. Bit 1 does the same for RTS, making + * RTS +5V when the 3116 cannot transfer the data to the USB bus + * (verified by disabling the reading URB). Note that as far as I can + * tell, the windows driver does NOT use this, so there might be some + * hardware bug or something. + * + * According to a patch provided here + * (http://lkml.org/lkml/2009/7/26/56), the ARK3116 can also be used + * as an IrDA dongle. Since I do not have such a thing, I could not + * investigate that aspect. However, I can speculate ;-). + * + * - IrDA encodes data differently than RS232. Most likely, one of + * the bits in registers 9..E enables the IR ENDEC (encoder/decoder). + * - Depending on the IR transceiver, the input and output need to be + * inverted, so there are probably bits for that as well. + * - IrDA is half-duplex, so there should be a bit for selecting that. + * + * This still leaves at least two registers unaccounted for. Perhaps + * The chip can do XON/XOFF or CRC in HW? + * + * Register 9: + * Set to 0x00 for IrDA, when the baudrate is initialised. + * + * Register A: + * Set to 0x01 for IrDA, at init. + * + * Register B: + * Set to 0x01 for IrDA, 0x00 for RS232, at init. + * + * Register C: + * Set to 00 for IrDA, at init. + * + * Register D: + * Set to 0x41 for IrDA, at init. + * + * Register E: + * Somekind of baudrate override. The windows driver seems to set + * this to 0x00 for normal baudrates, 0x01 for 460800, 0x02 for 921600. + * Since 460800 and 921600 cannot be obtained by dividing 3MHz by an integer, + * it could be somekind of subdivisor thingy. + * However,it does not seem to do anything: selecting 921600 (divisor 3, + * reg E=2), still gets 1 MHz. I also checked if registers 9, C or F would + * work, but they don't. + * + * Register F: unknown + */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ebcc6d0e2e91ec48d355a020e6da86f34c727508..f99498fca99a3c4ed67b39675e7546a93fa96894 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -598,6 +598,20 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USOPTL4_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USPTL4_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USO9ML2DR_2_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USO9ML2DR_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USOPTL4DR2_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USOPTL4DR_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_485USB9F_2W_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_485USB9F_4W_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_232USB9M_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_485USBTB_2W_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_485USBTB_4W_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_TTL5USB9M_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_TTL3USB9M_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_ZZ_PROG1_USB_PID) }, { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) }, { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) }, @@ -2195,15 +2209,21 @@ static void ftdi_set_termios(struct tty_struct *tty, /* Set number of data bits, parity, stop bits */ - termios->c_cflag &= ~CMSPAR; - urb_value = 0; urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 : FTDI_SIO_SET_DATA_STOP_BITS_1); - urb_value |= (cflag & PARENB ? - (cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD : - FTDI_SIO_SET_DATA_PARITY_EVEN) : - FTDI_SIO_SET_DATA_PARITY_NONE); + if (cflag & PARENB) { + if (cflag & CMSPAR) + urb_value |= cflag & PARODD ? + FTDI_SIO_SET_DATA_PARITY_MARK : + FTDI_SIO_SET_DATA_PARITY_SPACE; + else + urb_value |= cflag & PARODD ? + FTDI_SIO_SET_DATA_PARITY_ODD : + FTDI_SIO_SET_DATA_PARITY_EVEN; + } else { + urb_value |= FTDI_SIO_SET_DATA_PARITY_NONE; + } if (cflag & CSIZE) { switch (cflag & CSIZE) { case CS5: urb_value |= 5; dbg("Setting CS5"); break; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 6f31e0d7189889aca4f47758f0790aebe40f747d..4586a24fafb020c5f128c6b385cc10d1611b887c 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -662,6 +662,20 @@ #define BANDB_USOTL4_PID 0xAC01 /* USOTL4 Isolated RS-485 Converter */ #define BANDB_USTL4_PID 0xAC02 /* USTL4 RS-485 Converter */ #define BANDB_USO9ML2_PID 0xAC03 /* USO9ML2 Isolated RS-232 Converter */ +#define BANDB_USOPTL4_PID 0xAC11 +#define BANDB_USPTL4_PID 0xAC12 +#define BANDB_USO9ML2DR_2_PID 0xAC16 +#define BANDB_USO9ML2DR_PID 0xAC17 +#define BANDB_USOPTL4DR2_PID 0xAC18 /* USOPTL4R-2 2-port Isolated RS-232 Converter */ +#define BANDB_USOPTL4DR_PID 0xAC19 +#define BANDB_485USB9F_2W_PID 0xAC25 +#define BANDB_485USB9F_4W_PID 0xAC26 +#define BANDB_232USB9M_PID 0xAC27 +#define BANDB_485USBTB_2W_PID 0xAC33 +#define BANDB_485USBTB_4W_PID 0xAC34 +#define BANDB_TTL5USB9M_PID 0xAC49 +#define BANDB_TTL3USB9M_PID 0xAC50 +#define BANDB_ZZ_PROG1_USB_PID 0xBA02 /* * RM Michaelides CANview USB (http://www.rmcan.com) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index f11abf52be7db6b6e2afb082d86c8abd8fbd49e2..485fa9c5b10766698caabf03c580f92715c86bba 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -121,8 +121,14 @@ * moschip_id_table_combined */ #define USB_VENDOR_ID_BANDB 0x0856 -#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 +#define BANDB_DEVICE_ID_USO9ML2_2 0xAC22 +#define BANDB_DEVICE_ID_USO9ML2_4 0xAC24 +#define BANDB_DEVICE_ID_US9ML2_2 0xAC29 +#define BANDB_DEVICE_ID_US9ML2_4 0xAC30 +#define BANDB_DEVICE_ID_USPTL4_2 0xAC31 +#define BANDB_DEVICE_ID_USPTL4_4 0xAC32 #define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 +#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 /* This driver also supports * ATEN UC2324 device using Moschip MCS7840 @@ -177,8 +183,14 @@ static struct usb_device_id moschip_port_id_table[] = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, - {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ @@ -187,8 +199,14 @@ static struct usb_device_id moschip_port_id_table[] = { static __devinitdata struct usb_device_id moschip_id_table_combined[] = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, - {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 80f59b6350cbdcee5a9864ef51990c51e2309ad4..4cdb975caa89a96a897451ba57203e97968a7bdc 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -501,12 +501,13 @@ static int opticon_resume(struct usb_interface *intf) struct usb_serial_port *port = serial->port[0]; int result; - mutex_lock(&port->mutex); - if (port->port.count) + mutex_lock(&port->port.mutex); + /* This is protected by the port mutex against close/open */ + if (test_bit(ASYNCB_INITIALIZED, &port->port.flags)) result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO); else result = 0; - mutex_unlock(&port->mutex); + mutex_unlock(&port->port.mutex); return result; } diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 0577e4b611147806203ebf1e0864167cfc98d0c3..9a2b903492ecd028cccddc56fb56d8197dc0b7dd 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -580,12 +580,48 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0106, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0108, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0145, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0146, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0148, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0149, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0150, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0151, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0154, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0160, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, @@ -599,6 +635,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) }, { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */ { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) }, + { USB_DEVICE(ALINK_VENDOR_ID, 0xce16) }, { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, @@ -1312,7 +1349,7 @@ static int option_suspend(struct usb_serial *serial, pm_message_t message) dbg("%s entered", __func__); - if (serial->dev->auto_pm) { + if (message.event & PM_EVENT_AUTO) { spin_lock_irq(&intfdata->susp_lock); b = intfdata->in_flight; spin_unlock_irq(&intfdata->susp_lock); diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 5019325ba25dda93486a08757c68cba44cf0b4a0..ac1b6449fb6abc779f6904cd4899508f466426de 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -16,8 +16,9 @@ Portions based on the option driver by Matthias Urlichs Whom based his on the Keyspan driver by Hugh Blemings */ - -#define DRIVER_VERSION "v.1.3.8" +/* Uncomment to log function calls */ +/* #define DEBUG */ +#define DRIVER_VERSION "v.1.7.16" #define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer" #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" @@ -33,8 +34,10 @@ #define SWIMS_USB_REQUEST_SetPower 0x00 #define SWIMS_USB_REQUEST_SetNmea 0x07 -#define N_IN_URB 8 -#define N_OUT_URB 64 +#define N_IN_URB_HM 8 +#define N_OUT_URB_HM 64 +#define N_IN_URB 4 +#define N_OUT_URB 4 #define IN_BUFLEN 4096 #define MAX_TRANSFER (PAGE_SIZE - 512) @@ -124,6 +127,23 @@ static int is_blacklisted(const u8 ifnum, return 0; } +static int is_himemory(const u8 ifnum, + const struct sierra_iface_info *himemorylist) +{ + const u8 *info; + int i; + + if (himemorylist) { + info = himemorylist->ifaceinfo; + + for (i=0; i < himemorylist->infolen; i++) { + if (info[i] == ifnum) + return 1; + } + } + return 0; +} + static int sierra_calc_interface(struct usb_serial *serial) { int interface; @@ -186,6 +206,20 @@ static int sierra_probe(struct usb_serial *serial, return result; } +/* interfaces with higher memory requirements */ +static const u8 hi_memory_typeA_ifaces[] = { 0, 2 }; +static const struct sierra_iface_info typeA_interface_list = { + .infolen = ARRAY_SIZE(hi_memory_typeA_ifaces), + .ifaceinfo = hi_memory_typeA_ifaces, +}; + +static const u8 hi_memory_typeB_ifaces[] = { 3, 4, 5, 6 }; +static const struct sierra_iface_info typeB_interface_list = { + .infolen = ARRAY_SIZE(hi_memory_typeB_ifaces), + .ifaceinfo = hi_memory_typeB_ifaces, +}; + +/* 'blacklist' of interfaces not served by this driver */ static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 }; static const struct sierra_iface_info direct_ip_interface_blacklist = { .infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces), @@ -286,8 +320,10 @@ struct sierra_port_private { struct usb_anchor active; struct usb_anchor delayed; + int num_out_urbs; + int num_in_urbs; /* Input endpoints and buffers for this port */ - struct urb *in_urbs[N_IN_URB]; + struct urb *in_urbs[N_IN_URB_HM]; /* Settings for the port */ int rts_state; /* Handshaking pins (outputs) */ @@ -460,7 +496,7 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, spin_lock_irqsave(&portdata->lock, flags); dev_dbg(&port->dev, "%s - outstanding_urbs: %d\n", __func__, portdata->outstanding_urbs); - if (portdata->outstanding_urbs > N_OUT_URB) { + if (portdata->outstanding_urbs > portdata->num_out_urbs) { spin_unlock_irqrestore(&portdata->lock, flags); dev_dbg(&port->dev, "%s - write limit hit\n", __func__); return 0; @@ -665,7 +701,7 @@ static int sierra_write_room(struct tty_struct *tty) /* try to give a good number back based on if we have any free urbs at * this point in time */ spin_lock_irqsave(&portdata->lock, flags); - if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) { + if (portdata->outstanding_urbs > (portdata->num_out_urbs * 2) / 3) { spin_unlock_irqrestore(&portdata->lock, flags); dev_dbg(&port->dev, "%s - write limit hit\n", __func__); return 0; @@ -680,7 +716,7 @@ static void sierra_stop_rx_urbs(struct usb_serial_port *port) int i; struct sierra_port_private *portdata = usb_get_serial_port_data(port); - for (i = 0; i < ARRAY_SIZE(portdata->in_urbs); i++) + for (i = 0; i < portdata->num_in_urbs; i++) usb_kill_urb(portdata->in_urbs[i]); usb_kill_urb(port->interrupt_in_urb); @@ -695,7 +731,7 @@ static int sierra_submit_rx_urbs(struct usb_serial_port *port, gfp_t mem_flags) struct sierra_port_private *portdata = usb_get_serial_port_data(port); ok_cnt = 0; - for (i = 0; i < ARRAY_SIZE(portdata->in_urbs); i++) { + for (i = 0; i < portdata->num_in_urbs; i++) { urb = portdata->in_urbs[i]; if (!urb) continue; @@ -791,7 +827,7 @@ static void sierra_close(struct usb_serial_port *port) /* Stop reading urbs */ sierra_stop_rx_urbs(port); /* .. and release them */ - for (i = 0; i < N_IN_URB; i++) { + for (i = 0; i < portdata->num_in_urbs; i++) { sierra_release_urb(portdata->in_urbs[i]); portdata->in_urbs[i] = NULL; } @@ -818,7 +854,7 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) endpoint = port->bulk_in_endpointAddress; - for (i = 0; i < ARRAY_SIZE(portdata->in_urbs); i++) { + for (i = 0; i < portdata->num_in_urbs; i++) { urb = sierra_setup_urb(serial, endpoint, USB_DIR_IN, port, IN_BUFLEN, GFP_KERNEL, sierra_indat_callback); @@ -869,7 +905,9 @@ static int sierra_startup(struct usb_serial *serial) { struct usb_serial_port *port; struct sierra_port_private *portdata; + struct sierra_iface_info *himemoryp = NULL; int i; + u8 ifnum; dev_dbg(&serial->dev->dev, "%s\n", __func__); @@ -886,13 +924,40 @@ static int sierra_startup(struct usb_serial *serial) portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); if (!portdata) { dev_dbg(&port->dev, "%s: kmalloc for " - "sierra_port_private (%d) failed!.\n", + "sierra_port_private (%d) failed!\n", __func__, i); return -ENOMEM; } spin_lock_init(&portdata->lock); init_usb_anchor(&portdata->active); init_usb_anchor(&portdata->delayed); + ifnum = i; + /* Assume low memory requirements */ + portdata->num_out_urbs = N_OUT_URB; + portdata->num_in_urbs = N_IN_URB; + + /* Determine actual memory requirements */ + if (serial->num_ports == 1) { + /* Get interface number for composite device */ + ifnum = sierra_calc_interface(serial); + himemoryp = + (struct sierra_iface_info *)&typeB_interface_list; + if (is_himemory(ifnum, himemoryp)) { + portdata->num_out_urbs = N_OUT_URB_HM; + portdata->num_in_urbs = N_IN_URB_HM; + } + } + else { + himemoryp = + (struct sierra_iface_info *)&typeA_interface_list; + if (is_himemory(i, himemoryp)) { + portdata->num_out_urbs = N_OUT_URB_HM; + portdata->num_in_urbs = N_IN_URB_HM; + } + } + dev_dbg(&serial->dev->dev, + "Memory usage (urbs) interface #%d, in=%d, out=%d\n", + ifnum,portdata->num_in_urbs, portdata->num_out_urbs ); /* Set the port private data pointer */ usb_set_serial_port_data(port, portdata); } @@ -940,7 +1005,7 @@ static int sierra_suspend(struct usb_serial *serial, pm_message_t message) struct sierra_intf_private *intfdata; int b; - if (serial->dev->auto_pm) { + if (message.event & PM_EVENT_AUTO) { intfdata = serial->private; spin_lock_irq(&intfdata->susp_lock); b = intfdata->in_flight; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index bd3fa7ff15b12166bf0cf2ad86f3214144f914c0..4543f359be75ea9d423d12dc700d9c1cd479e5e6 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -247,96 +247,66 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) return retval; } -static int serial_open(struct tty_struct *tty, struct file *filp) +static int serial_activate(struct tty_port *tport, struct tty_struct *tty) { - struct usb_serial_port *port = tty->driver_data; + struct usb_serial_port *port = + container_of(tport, struct usb_serial_port, port); struct usb_serial *serial = port->serial; int retval; - dbg("%s - port %d", __func__, port->number); - - spin_lock_irq(&port->port.lock); - if (!tty_hung_up_p(filp)) - ++port->port.count; - spin_unlock_irq(&port->port.lock); - tty_port_tty_set(&port->port, tty); + mutex_lock(&serial->disc_mutex); + if (serial->disconnected) + retval = -ENODEV; + else + retval = port->serial->type->open(tty, port); + mutex_unlock(&serial->disc_mutex); + return retval; +} - /* Do the device-specific open only if the hardware isn't - * already initialized. - */ - if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) { - if (mutex_lock_interruptible(&port->mutex)) - return -ERESTARTSYS; - mutex_lock(&serial->disc_mutex); - if (serial->disconnected) - retval = -ENODEV; - else - retval = port->serial->type->open(tty, port); - mutex_unlock(&serial->disc_mutex); - mutex_unlock(&port->mutex); - if (retval) - return retval; - set_bit(ASYNCB_INITIALIZED, &port->port.flags); - } +static int serial_open(struct tty_struct *tty, struct file *filp) +{ + struct usb_serial_port *port = tty->driver_data; - /* Now do the correct tty layer semantics */ - retval = tty_port_block_til_ready(&port->port, tty, filp); - return retval; + dbg("%s - port %d", __func__, port->number); + return tty_port_open(&port->port, tty, filp); } /** * serial_down - shut down hardware - * @port: port to shut down + * @tport: tty port to shut down * * Shut down a USB serial port unless it is the console. We never - * shut down the console hardware as it will always be in use. + * shut down the console hardware as it will always be in use. Serialized + * against activate by the tport mutex and kept to matching open/close pairs + * of calls by the ASYNCB_INITIALIZED flag. */ -static void serial_down(struct usb_serial_port *port) +static void serial_down(struct tty_port *tport) { + struct usb_serial_port *port = + container_of(tport, struct usb_serial_port, port); struct usb_serial_driver *drv = port->serial->type; - /* * The console is magical. Do not hang up the console hardware * or there will be tears. */ if (port->console) return; - - /* Don't call the close method if the hardware hasn't been - * initialized. - */ - if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags)) - return; - - mutex_lock(&port->mutex); if (drv->close) drv->close(port); - mutex_unlock(&port->mutex); } static void serial_hangup(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - dbg("%s - port %d", __func__, port->number); - - serial_down(port); tty_port_hangup(&port->port); } static void serial_close(struct tty_struct *tty, struct file *filp) { struct usb_serial_port *port = tty->driver_data; - dbg("%s - port %d", __func__, port->number); - - if (tty_hung_up_p(filp)) - return; - if (tty_port_close_start(&port->port, tty, filp) == 0) - return; - serial_down(port); - tty_port_close_end(&port->port, tty); - tty_port_tty_set(&port->port, NULL); + tty_port_close(&port->port, tty, filp); } /** @@ -725,6 +695,8 @@ static void serial_dtr_rts(struct tty_port *port, int on) static const struct tty_port_operations serial_port_ops = { .carrier_raised = serial_carrier_raised, .dtr_rts = serial_dtr_rts, + .activate = serial_activate, + .shutdown = serial_down, }; int usb_serial_probe(struct usb_interface *interface, @@ -923,7 +895,8 @@ int usb_serial_probe(struct usb_interface *interface, port->port.ops = &serial_port_ops; port->serial = serial; spin_lock_init(&port->lock); - mutex_init(&port->mutex); + /* Keep this for private driver use for the moment but + should probably go away */ INIT_WORK(&port->work, usb_serial_port_work); serial->port[i] = port; port->dev.parent = &interface->dev; diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index cfa26d56ce60c4f2c69346aae433444a5c812297..e5e6df39e73707989711ea0284a4109d56409b44 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -73,7 +73,8 @@ static const char* host_info(struct Scsi_Host *host) { - return "SCSI emulation for USB Mass Storage devices"; + struct us_data *us = host_to_us(host); + return us->scsi_name; } static int slave_alloc (struct scsi_device *sdev) diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 589f6b4404f0b1550718c66353ec4c807c0a46ac..cc313d16d727d0dc827627835d380249f638ab9c 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -666,10 +666,11 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) * to wait for at least one CHECK_CONDITION to determine * SANE_SENSE support */ - if ((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) && + if (unlikely((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) && result == USB_STOR_TRANSPORT_GOOD && !(us->fflags & US_FL_SANE_SENSE) && - !(srb->cmnd[2] & 0x20)) { + !(us->fflags & US_FL_BAD_SENSE) && + !(srb->cmnd[2] & 0x20))) { US_DEBUGP("-- SAT supported, increasing auto-sense\n"); us->fflags |= US_FL_SANE_SENSE; } @@ -718,6 +719,12 @@ Retry_Sense: if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { US_DEBUGP("-- auto-sense aborted\n"); srb->result = DID_ABORT << 16; + + /* If SANE_SENSE caused this problem, disable it */ + if (sense_size != US_SENSE_SIZE) { + us->fflags &= ~US_FL_SANE_SENSE; + us->fflags |= US_FL_BAD_SENSE; + } goto Handle_Errors; } @@ -727,10 +734,11 @@ Retry_Sense: * (small) sense request. This fixes some USB GSM modems */ if (temp_result == USB_STOR_TRANSPORT_FAILED && - (us->fflags & US_FL_SANE_SENSE) && - sense_size != US_SENSE_SIZE) { + sense_size != US_SENSE_SIZE) { US_DEBUGP("-- auto-sense failure, retry small sense\n"); sense_size = US_SENSE_SIZE; + us->fflags &= ~US_FL_SANE_SENSE; + us->fflags |= US_FL_BAD_SENSE; goto Retry_Sense; } @@ -754,6 +762,7 @@ Retry_Sense: */ if (srb->sense_buffer[7] > (US_SENSE_SIZE - 8) && !(us->fflags & US_FL_SANE_SENSE) && + !(us->fflags & US_FL_BAD_SENSE) && (srb->sense_buffer[0] & 0x7C) == 0x70) { US_DEBUGP("-- SANE_SENSE support enabled\n"); us->fflags |= US_FL_SANE_SENSE; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index d4f034ebaa8a44080af462b8876ecbc632c62cee..64a0a2c27e12b4478734ae9683fead5750abfe67 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -818,6 +818,13 @@ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Reported by Daniel Kukula */ +UNUSUAL_DEV( 0x067b, 0x1063, 0x0100, 0x0100, + "Prolific Technology, Inc.", + "Prolific Storage Gadget", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_BAD_SENSE ), + /* Reported by Rogerio Brito */ UNUSUAL_DEV( 0x067b, 0x2317, 0x0001, 0x001, "Prolific Technology, Inc.", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 8060b85fe1a3fb377476e1cd0a6de55df6de9014..5a53d4f0dd11cb547f58430afc17c8501ef4a8a7 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -45,6 +45,10 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef CONFIG_USB_STORAGE_DEBUG +#define DEBUG +#endif + #include #include #include @@ -228,6 +232,7 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data, if (data_len<36) // You lose. return; + memset(data+8, ' ', 28); if(data[0]&0x20) { /* USB device currently not connected. Return peripheral qualifier 001b ("...however, the physical device is not currently connected @@ -237,15 +242,15 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data, device, it may return zeros or ASCII spaces (20h) in those fields until the data is available from the device."). */ - memset(data+8,0,28); } else { u16 bcdDevice = le16_to_cpu(us->pusb_dev->descriptor.bcdDevice); - memcpy(data+8, us->unusual_dev->vendorName, - strlen(us->unusual_dev->vendorName) > 8 ? 8 : - strlen(us->unusual_dev->vendorName)); - memcpy(data+16, us->unusual_dev->productName, - strlen(us->unusual_dev->productName) > 16 ? 16 : - strlen(us->unusual_dev->productName)); + int n; + + n = strlen(us->unusual_dev->vendorName); + memcpy(data+8, us->unusual_dev->vendorName, min(8, n)); + n = strlen(us->unusual_dev->productName); + memcpy(data+16, us->unusual_dev->productName, min(16, n)); + data[32] = 0x30 + ((bcdDevice>>12) & 0x0F); data[33] = 0x30 + ((bcdDevice>>8) & 0x0F); data[34] = 0x30 + ((bcdDevice>>4) & 0x0F); @@ -459,6 +464,9 @@ static void adjust_quirks(struct us_data *us) case 'a': f |= US_FL_SANE_SENSE; break; + case 'b': + f |= US_FL_BAD_SENSE; + break; case 'c': f |= US_FL_FIX_CAPACITY; break; @@ -808,14 +816,13 @@ static int usb_stor_scan_thread(void * __us) { struct us_data *us = (struct us_data *)__us; - printk(KERN_DEBUG - "usb-storage: device found at %d\n", us->pusb_dev->devnum); + dev_dbg(&us->pusb_intf->dev, "device found\n"); set_freezable(); /* Wait for the timeout to expire or for a disconnect */ if (delay_use > 0) { - printk(KERN_DEBUG "usb-storage: waiting for device " - "to settle before scanning\n"); + dev_dbg(&us->pusb_intf->dev, "waiting for device to settle " + "before scanning\n"); wait_event_freezable_timeout(us->delay_wait, test_bit(US_FLIDX_DONT_SCAN, &us->dflags), delay_use * HZ); @@ -832,7 +839,7 @@ static int usb_stor_scan_thread(void * __us) mutex_unlock(&us->dev_mutex); } scsi_scan_host(us_to_host(us)); - printk(KERN_DEBUG "usb-storage: device scan complete\n"); + dev_dbg(&us->pusb_intf->dev, "scan complete\n"); /* Should we unbind if no devices were detected? */ } @@ -840,6 +847,15 @@ static int usb_stor_scan_thread(void * __us) complete_and_exit(&us->scanning_done, 0); } +static unsigned int usb_stor_sg_tablesize(struct usb_interface *intf) +{ + struct usb_device *usb_dev = interface_to_usbdev(intf); + + if (usb_dev->bus->sg_tablesize) { + return usb_dev->bus->sg_tablesize; + } + return SG_ALL; +} /* First part of general USB mass-storage probing */ int usb_stor_probe1(struct us_data **pus, @@ -868,6 +884,7 @@ int usb_stor_probe1(struct us_data **pus, * Allow 16-byte CDBs and thus > 2TB */ host->max_cmd_len = 16; + host->sg_tablesize = usb_stor_sg_tablesize(intf); *pus = us = host_to_us(host); memset(us, 0, sizeof(struct us_data)); mutex_init(&(us->dev_mutex)); @@ -929,6 +946,8 @@ int usb_stor_probe2(struct us_data *us) result = usb_stor_acquire_resources(us); if (result) goto BadDevice; + snprintf(us->scsi_name, sizeof(us->scsi_name), "usb-storage %s", + dev_name(&us->pusb_intf->dev)); result = scsi_add_host(us_to_host(us), &us->pusb_intf->dev); if (result) { printk(KERN_WARNING USB_STORAGE diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 2609efb2bd7ea86da818450e241aaf835ea46a77..69717134231b5f8469e62614533e1d411705c562 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -132,6 +132,7 @@ struct us_data { /* SCSI interfaces */ struct scsi_cmnd *srb; /* current srb */ unsigned int tag; /* current dCBWTag */ + char scsi_name[32]; /* scsi_host name */ /* control and bulk communications data */ struct urb *current_urb; /* USB requests */ diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index b62f2bc064f695f732696dea3d5fd54d450e2704..b1e579c5c97cbb90bc19be3619d41aaee1f8e6f4 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -358,7 +358,7 @@ retry: rv = skel_do_read_io(dev, count); if (rv < 0) goto exit; - else if (!file->f_flags & O_NONBLOCK) + else if (!(file->f_flags & O_NONBLOCK)) goto retry; rv = -EAGAIN; } @@ -411,7 +411,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, * limit the number of URBs in flight to stop a user from using up all * RAM */ - if (!file->f_flags & O_NONBLOCK) { + if (!(file->f_flags & O_NONBLOCK)) { if (down_interruptible(&dev->limit_sem)) { retval = -ERESTARTSYS; goto exit; diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index 4ac4300a3f9aa9e2f173c42209f65585acf97792..dced419f7abac944a2f13f2cb661b8de31fbc632 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c @@ -119,10 +119,12 @@ static struct wusb_dev *wusb_dev_alloc(struct wusbhc *wusbhc) urb = usb_alloc_urb(0, GFP_KERNEL); if (urb == NULL) goto err; + wusb_dev->set_gtk_urb = urb; - req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); + req = kmalloc(sizeof(*req), GFP_KERNEL); if (req == NULL) goto err; + wusb_dev->set_gtk_req = req; req->bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; req->bRequest = USB_REQ_SET_DESCRIPTOR; @@ -130,9 +132,6 @@ static struct wusb_dev *wusb_dev_alloc(struct wusbhc *wusbhc) req->wIndex = 0; req->wLength = cpu_to_le16(wusbhc->gtk.descr.bLength); - wusb_dev->set_gtk_urb = urb; - wusb_dev->set_gtk_req = req; - return wusb_dev; err: wusb_dev_free(wusb_dev); diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c index 4516c36436e6187e053d74c5766ea020036a2218..edcd2d7560378f1681f8c2ec74dc042a4e0815f6 100644 --- a/drivers/usb/wusbcore/security.c +++ b/drivers/usb/wusbcore/security.c @@ -205,15 +205,15 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc, const void *itr, *top; char buf[64]; - secd = kmalloc(sizeof(struct usb_security_descriptor), GFP_KERNEL); + secd = kmalloc(sizeof(*secd), GFP_KERNEL); if (secd == NULL) { result = -ENOMEM; goto out; } result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, - 0, secd, sizeof(struct usb_security_descriptor)); - if (result < sizeof(secd)) { + 0, secd, sizeof(*secd)); + if (result < sizeof(*secd)) { dev_err(dev, "Can't read security descriptor or " "not enough data: %d\n", result); goto out; diff --git a/drivers/usb/wusbcore/wusbhc.c b/drivers/usb/wusbcore/wusbhc.c index ee6256f236368921a7b0aada69b06ff86c9e5e23..eab86e4bc770ca1dc81fb8a11f7bec1727ddcf82 100644 --- a/drivers/usb/wusbcore/wusbhc.c +++ b/drivers/usb/wusbcore/wusbhc.c @@ -147,10 +147,40 @@ static ssize_t wusb_chid_store(struct device *dev, } static DEVICE_ATTR(wusb_chid, 0644, wusb_chid_show, wusb_chid_store); + +static ssize_t wusb_phy_rate_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); + + return sprintf(buf, "%d\n", wusbhc->phy_rate); +} + +static ssize_t wusb_phy_rate_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); + uint8_t phy_rate; + ssize_t result; + + result = sscanf(buf, "%hhu", &phy_rate); + if (result != 1) + return -EINVAL; + if (phy_rate >= UWB_PHY_RATE_INVALID) + return -EINVAL; + + wusbhc->phy_rate = phy_rate; + return size; +} +static DEVICE_ATTR(wusb_phy_rate, 0644, wusb_phy_rate_show, wusb_phy_rate_store); + /* Group all the WUSBHC attributes */ static struct attribute *wusbhc_attrs[] = { &dev_attr_wusb_trust_timeout.attr, &dev_attr_wusb_chid.attr, + &dev_attr_wusb_phy_rate.attr, NULL, }; @@ -177,6 +207,8 @@ int wusbhc_create(struct wusbhc *wusbhc) int result = 0; wusbhc->trust_timeout = WUSB_TRUST_TIMEOUT_MS; + wusbhc->phy_rate = UWB_PHY_RATE_INVALID - 1; + mutex_init(&wusbhc->mutex); result = wusbhc_mmcie_create(wusbhc); if (result < 0) diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h index 797c2453a35bf829ec2fef965d5ac42a37cd33af..fd2fd4e277e1914871d530adcea2d08ef3f8abeb 100644 --- a/drivers/usb/wusbcore/wusbhc.h +++ b/drivers/usb/wusbcore/wusbhc.h @@ -253,6 +253,7 @@ struct wusbhc { unsigned trust_timeout; /* in jiffies */ struct wusb_ckhdid chid; + uint8_t phy_rate; struct wuie_host_info *wuie_host_info; struct mutex mutex; /* locks everything else */ diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 6b89eb55ed327d56bf16e02d58db2aebac611d67..99c0df1c7ebf5ec9f4fed97d7bfdd2de241b488b 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2066,6 +2066,7 @@ config XEN_FBDEV_FRONTEND select FB_SYS_IMAGEBLIT select FB_SYS_FOPS select FB_DEFERRED_IO + select XEN_XENBUS_FRONTEND default y help This driver implements the front-end of the Xen virtual @@ -2130,7 +2131,7 @@ config FB_PRE_INIT_FB the bootloader. config FB_MSM - tristate + tristate "MSM Framebuffer support" depends on FB && ARCH_MSM select FB_CFB_FILLRECT select FB_CFB_COPYAREA @@ -2164,6 +2165,7 @@ config FB_BROADSHEET a bridge adapter. source "drivers/video/omap/Kconfig" +source "drivers/video/omap2/Kconfig" source "drivers/video/backlight/Kconfig" source "drivers/video/display/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 80232e124889b1eab9b26f4869c3a1a010aaade4..0f8da331ba0f7d76a80eb98216d95f4aa9ea6284 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -124,6 +124,7 @@ obj-$(CONFIG_FB_SM501) += sm501fb.o obj-$(CONFIG_FB_XILINX) += xilinxfb.o obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o obj-$(CONFIG_FB_OMAP) += omap/ +obj-y += omap2/ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o obj-$(CONFIG_FB_CARMINE) += carminefb.o obj-$(CONFIG_FB_MB862XX) += mb862xx/ diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c index ad05da5ba3c75caf2e6862cefac5c9a32772479c..4c10edecfb6616070ce46610a5694f2fbf051080 100644 --- a/drivers/video/backlight/adp5520_bl.c +++ b/drivers/video/backlight/adp5520_bl.c @@ -15,7 +15,7 @@ struct adp5520_bl { struct device *master; - struct adp5520_backlight_platfrom_data *pdata; + struct adp5520_backlight_platform_data *pdata; struct mutex lock; unsigned long cached_daylight_max; int id; @@ -31,29 +31,30 @@ static int adp5520_bl_set(struct backlight_device *bl, int brightness) if (data->pdata->en_ambl_sens) { if ((brightness > 0) && (brightness < ADP5020_MAX_BRIGHTNESS)) { /* Disable Ambient Light auto adjust */ - ret |= adp5520_clr_bits(master, BL_CONTROL, - BL_AUTO_ADJ); - ret |= adp5520_write(master, DAYLIGHT_MAX, brightness); + ret |= adp5520_clr_bits(master, ADP5520_BL_CONTROL, + ADP5520_BL_AUTO_ADJ); + ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX, + brightness); } else { /* * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust * restore daylight l3 sysfs brightness */ - ret |= adp5520_write(master, DAYLIGHT_MAX, + ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX, data->cached_daylight_max); - ret |= adp5520_set_bits(master, BL_CONTROL, - BL_AUTO_ADJ); + ret |= adp5520_set_bits(master, ADP5520_BL_CONTROL, + ADP5520_BL_AUTO_ADJ); } } else { - ret |= adp5520_write(master, DAYLIGHT_MAX, brightness); + ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX, brightness); } if (data->current_brightness && brightness == 0) ret |= adp5520_set_bits(master, - MODE_STATUS, DIM_EN); + ADP5520_MODE_STATUS, ADP5520_DIM_EN); else if (data->current_brightness == 0 && brightness) ret |= adp5520_clr_bits(master, - MODE_STATUS, DIM_EN); + ADP5520_MODE_STATUS, ADP5520_DIM_EN); if (!ret) data->current_brightness = brightness; @@ -79,7 +80,7 @@ static int adp5520_bl_get_brightness(struct backlight_device *bl) int error; uint8_t reg_val; - error = adp5520_read(data->master, BL_VALUE, ®_val); + error = adp5520_read(data->master, ADP5520_BL_VALUE, ®_val); return error ? data->current_brightness : reg_val; } @@ -93,33 +94,46 @@ static int adp5520_bl_setup(struct backlight_device *bl) { struct adp5520_bl *data = bl_get_data(bl); struct device *master = data->master; - struct adp5520_backlight_platfrom_data *pdata = data->pdata; + struct adp5520_backlight_platform_data *pdata = data->pdata; int ret = 0; - ret |= adp5520_write(master, DAYLIGHT_MAX, pdata->l1_daylight_max); - ret |= adp5520_write(master, DAYLIGHT_DIM, pdata->l1_daylight_dim); + ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX, + pdata->l1_daylight_max); + ret |= adp5520_write(master, ADP5520_DAYLIGHT_DIM, + pdata->l1_daylight_dim); if (pdata->en_ambl_sens) { data->cached_daylight_max = pdata->l1_daylight_max; - ret |= adp5520_write(master, OFFICE_MAX, pdata->l2_office_max); - ret |= adp5520_write(master, OFFICE_DIM, pdata->l2_office_dim); - ret |= adp5520_write(master, DARK_MAX, pdata->l3_dark_max); - ret |= adp5520_write(master, DARK_DIM, pdata->l3_dark_dim); - ret |= adp5520_write(master, L2_TRIP, pdata->l2_trip); - ret |= adp5520_write(master, L2_HYS, pdata->l2_hyst); - ret |= adp5520_write(master, L3_TRIP, pdata->l3_trip); - ret |= adp5520_write(master, L3_HYS, pdata->l3_hyst); - ret |= adp5520_write(master, ALS_CMPR_CFG, - ALS_CMPR_CFG_VAL(pdata->abml_filt, L3_EN)); + ret |= adp5520_write(master, ADP5520_OFFICE_MAX, + pdata->l2_office_max); + ret |= adp5520_write(master, ADP5520_OFFICE_DIM, + pdata->l2_office_dim); + ret |= adp5520_write(master, ADP5520_DARK_MAX, + pdata->l3_dark_max); + ret |= adp5520_write(master, ADP5520_DARK_DIM, + pdata->l3_dark_dim); + ret |= adp5520_write(master, ADP5520_L2_TRIP, + pdata->l2_trip); + ret |= adp5520_write(master, ADP5520_L2_HYS, + pdata->l2_hyst); + ret |= adp5520_write(master, ADP5520_L3_TRIP, + pdata->l3_trip); + ret |= adp5520_write(master, ADP5520_L3_HYS, + pdata->l3_hyst); + ret |= adp5520_write(master, ADP5520_ALS_CMPR_CFG, + ALS_CMPR_CFG_VAL(pdata->abml_filt, + ADP5520_L3_EN)); } - ret |= adp5520_write(master, BL_CONTROL, - BL_CTRL_VAL(pdata->fade_led_law, pdata->en_ambl_sens)); + ret |= adp5520_write(master, ADP5520_BL_CONTROL, + BL_CTRL_VAL(pdata->fade_led_law, + pdata->en_ambl_sens)); - ret |= adp5520_write(master, BL_FADE, FADE_VAL(pdata->fade_in, + ret |= adp5520_write(master, ADP5520_BL_FADE, FADE_VAL(pdata->fade_in, pdata->fade_out)); - ret |= adp5520_set_bits(master, MODE_STATUS, BL_EN | DIM_EN); + ret |= adp5520_set_bits(master, ADP5520_MODE_STATUS, + ADP5520_BL_EN | ADP5520_DIM_EN); return ret; } @@ -156,29 +170,31 @@ static ssize_t adp5520_store(struct device *dev, const char *buf, } static ssize_t adp5520_bl_dark_max_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { - return adp5520_show(dev, buf, DARK_MAX); + return adp5520_show(dev, buf, ADP5520_DARK_MAX); } static ssize_t adp5520_bl_dark_max_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) + struct device_attribute *attr, + const char *buf, size_t count) { - return adp5520_store(dev, buf, count, DARK_MAX); + return adp5520_store(dev, buf, count, ADP5520_DARK_MAX); } static DEVICE_ATTR(dark_max, 0664, adp5520_bl_dark_max_show, adp5520_bl_dark_max_store); static ssize_t adp5520_bl_office_max_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { - return adp5520_show(dev, buf, OFFICE_MAX); + return adp5520_show(dev, buf, ADP5520_OFFICE_MAX); } static ssize_t adp5520_bl_office_max_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) + struct device_attribute *attr, + const char *buf, size_t count) { - return adp5520_store(dev, buf, count, OFFICE_MAX); + return adp5520_store(dev, buf, count, ADP5520_OFFICE_MAX); } static DEVICE_ATTR(office_max, 0664, adp5520_bl_office_max_show, adp5520_bl_office_max_store); @@ -186,16 +202,17 @@ static DEVICE_ATTR(office_max, 0664, adp5520_bl_office_max_show, static ssize_t adp5520_bl_daylight_max_show(struct device *dev, struct device_attribute *attr, char *buf) { - return adp5520_show(dev, buf, DAYLIGHT_MAX); + return adp5520_show(dev, buf, ADP5520_DAYLIGHT_MAX); } static ssize_t adp5520_bl_daylight_max_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) + struct device_attribute *attr, + const char *buf, size_t count) { struct adp5520_bl *data = dev_get_drvdata(dev); strict_strtoul(buf, 10, &data->cached_daylight_max); - return adp5520_store(dev, buf, count, DAYLIGHT_MAX); + return adp5520_store(dev, buf, count, ADP5520_DAYLIGHT_MAX); } static DEVICE_ATTR(daylight_max, 0664, adp5520_bl_daylight_max_show, adp5520_bl_daylight_max_store); @@ -203,14 +220,14 @@ static DEVICE_ATTR(daylight_max, 0664, adp5520_bl_daylight_max_show, static ssize_t adp5520_bl_dark_dim_show(struct device *dev, struct device_attribute *attr, char *buf) { - return adp5520_show(dev, buf, DARK_DIM); + return adp5520_show(dev, buf, ADP5520_DARK_DIM); } static ssize_t adp5520_bl_dark_dim_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) + struct device_attribute *attr, + const char *buf, size_t count) { - return adp5520_store(dev, buf, count, DARK_DIM); + return adp5520_store(dev, buf, count, ADP5520_DARK_DIM); } static DEVICE_ATTR(dark_dim, 0664, adp5520_bl_dark_dim_show, adp5520_bl_dark_dim_store); @@ -218,29 +235,29 @@ static DEVICE_ATTR(dark_dim, 0664, adp5520_bl_dark_dim_show, static ssize_t adp5520_bl_office_dim_show(struct device *dev, struct device_attribute *attr, char *buf) { - return adp5520_show(dev, buf, OFFICE_DIM); + return adp5520_show(dev, buf, ADP5520_OFFICE_DIM); } static ssize_t adp5520_bl_office_dim_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) + struct device_attribute *attr, + const char *buf, size_t count) { - return adp5520_store(dev, buf, count, OFFICE_DIM); + return adp5520_store(dev, buf, count, ADP5520_OFFICE_DIM); } static DEVICE_ATTR(office_dim, 0664, adp5520_bl_office_dim_show, adp5520_bl_office_dim_store); static ssize_t adp5520_bl_daylight_dim_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { - return adp5520_show(dev, buf, DAYLIGHT_DIM); + return adp5520_show(dev, buf, ADP5520_DAYLIGHT_DIM); } static ssize_t adp5520_bl_daylight_dim_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) + struct device_attribute *attr, + const char *buf, size_t count) { - return adp5520_store(dev, buf, count, DAYLIGHT_DIM); + return adp5520_store(dev, buf, count, ADP5520_DAYLIGHT_DIM); } static DEVICE_ATTR(daylight_dim, 0664, adp5520_bl_daylight_dim_show, adp5520_bl_daylight_dim_store); @@ -316,7 +333,7 @@ static int __devexit adp5520_bl_remove(struct platform_device *pdev) struct backlight_device *bl = platform_get_drvdata(pdev); struct adp5520_bl *data = bl_get_data(bl); - adp5520_clr_bits(data->master, MODE_STATUS, BL_EN); + adp5520_clr_bits(data->master, ADP5520_MODE_STATUS, ADP5520_BL_EN); if (data->pdata->en_ambl_sens) sysfs_remove_group(&bl->dev.kobj, diff --git a/drivers/video/broadsheetfb.c b/drivers/video/broadsheetfb.c index 509cb92e873105b8874ea08cdacca171636c4651..df9ccb901d86f442d7359294ab01b55486f4be54 100644 --- a/drivers/video/broadsheetfb.c +++ b/drivers/video/broadsheetfb.c @@ -470,7 +470,7 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) par->read_reg = broadsheet_read_reg; init_waitqueue_head(&par->waitq); - info->flags = FBINFO_FLAG_DEFAULT; + info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; info->fbdefio = &broadsheetfb_defio; fb_deferred_io_init(info); diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index e59c083208866611472f4f570485a798d930c201..44ce908a478b5f4d4ef116e6e92c93172e44b760 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c @@ -144,7 +144,9 @@ static const struct address_space_operations fb_deferred_io_aops = { static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) { vma->vm_ops = &fb_deferred_io_vm_ops; - vma->vm_flags |= ( VM_IO | VM_RESERVED | VM_DONTEXPAND ); + vma->vm_flags |= ( VM_RESERVED | VM_DONTEXPAND ); + if (!(info->flags & FBINFO_VIRTFB)) + vma->vm_flags |= VM_IO; vma->vm_private_data = info; return 0; } diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c index 0b4bffbe67c812ff71fcc385efdbfc8acde82af4..f9d77adf035d92a027ef29a2d376eb2e237b23a9 100644 --- a/drivers/video/hecubafb.c +++ b/drivers/video/hecubafb.c @@ -253,7 +253,7 @@ static int __devinit hecubafb_probe(struct platform_device *dev) par->send_command = apollo_send_command; par->send_data = apollo_send_data; - info->flags = FBINFO_FLAG_DEFAULT; + info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; info->fbdefio = &hecubafb_defio; fb_deferred_io_init(info); diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c index df1f757a6161cde2f7d189be4501567af96fd6f2..661bfd20d1943e805dd6aa2865d4c2f361a38eb1 100644 --- a/drivers/video/metronomefb.c +++ b/drivers/video/metronomefb.c @@ -700,7 +700,7 @@ static int __devinit metronomefb_probe(struct platform_device *dev) if (retval < 0) goto err_free_irq; - info->flags = FBINFO_FLAG_DEFAULT; + info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; info->fbdefio = &metronomefb_defio; fb_deferred_io_init(info); diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 4d8c54c23dd7e320289fadec313d52ec5f333392..b043ac83c41265b884bbe07e2510519be4ba91dd 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -282,8 +282,17 @@ static int offb_set_par(struct fb_info *info) return 0; } +static void offb_destroy(struct fb_info *info) +{ + if (info->screen_base) + iounmap(info->screen_base); + release_mem_region(info->aperture_base, info->aperture_size); + framebuffer_release(info); +} + static struct fb_ops offb_ops = { .owner = THIS_MODULE, + .fb_destroy = offb_destroy, .fb_setcolreg = offb_setcolreg, .fb_set_par = offb_set_par, .fb_blank = offb_blank, @@ -482,10 +491,14 @@ static void __init offb_init_fb(const char *name, const char *full_name, var->sync = 0; var->vmode = FB_VMODE_NONINTERLACED; + /* set offb aperture size for generic probing */ + info->aperture_base = address; + info->aperture_size = fix->smem_len; + info->fbops = &offb_ops; info->screen_base = ioremap(address, fix->smem_len); info->pseudo_palette = (void *) (info + 1); - info->flags = FBINFO_DEFAULT | foreign_endian; + info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE | foreign_endian; fb_alloc_cmap(&info->cmap, 256, 0); diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 551e3e9c4cbee0e3b43a246f0997b9787bf511a7..455c6055325dcae647858eb6cede512388f033dc 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -1,6 +1,7 @@ config FB_OMAP tristate "OMAP frame buffer support (EXPERIMENTAL)" - depends on FB && ARCH_OMAP + depends on FB && ARCH_OMAP && (OMAP2_DSS = "n") + select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -72,7 +73,7 @@ config FB_OMAP_LCD_MIPID config FB_OMAP_BOOTLOADER_INIT bool "Check bootloader initialization" - depends on FB_OMAP + depends on FB_OMAP || FB_OMAP2 help Say Y here if you want to enable checking if the bootloader has already initialized the display controller. In this case the diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c index f5d75f22cef9ef2357f2338562c8120ccf62ec73..2ffb34af4c59ed2c7ea342c1a627aa1b0a5f1832 100644 --- a/drivers/video/omap/blizzard.c +++ b/drivers/video/omap/blizzard.c @@ -27,9 +27,9 @@ #include #include -#include #include +#include "omapfb.h" #include "dispc.h" #define MODULE_NAME "blizzard" diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c index 7c833db4f9b7cabdb5f646618980ead27fc36a10..c7c6455f1fa89350c2ef45bb1eefc3f5fad10dd8 100644 --- a/drivers/video/omap/dispc.c +++ b/drivers/video/omap/dispc.c @@ -24,11 +24,12 @@ #include #include #include +#include #include -#include #include +#include "omapfb.h" #include "dispc.h" #define MODULE_NAME "dispc" @@ -188,6 +189,11 @@ static struct { struct omapfb_color_key color_key; } dispc; +static struct platform_device omapdss_device = { + .name = "omapdss", + .id = -1, +}; + static void enable_lcd_clocks(int enable); static void inline dispc_write_reg(int idx, u32 val) @@ -914,20 +920,20 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev) static int get_dss_clocks(void) { - dispc.dss_ick = clk_get(dispc.fbdev->dev, "ick"); + dispc.dss_ick = clk_get(&omapdss_device.dev, "ick"); if (IS_ERR(dispc.dss_ick)) { dev_err(dispc.fbdev->dev, "can't get ick\n"); return PTR_ERR(dispc.dss_ick); } - dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck"); + dispc.dss1_fck = clk_get(&omapdss_device.dev, "dss1_fck"); if (IS_ERR(dispc.dss1_fck)) { dev_err(dispc.fbdev->dev, "can't get dss1_fck\n"); clk_put(dispc.dss_ick); return PTR_ERR(dispc.dss1_fck); } - dispc.dss_54m_fck = clk_get(dispc.fbdev->dev, "tv_fck"); + dispc.dss_54m_fck = clk_get(&omapdss_device.dev, "tv_fck"); if (IS_ERR(dispc.dss_54m_fck)) { dev_err(dispc.fbdev->dev, "can't get tv_fck\n"); clk_put(dispc.dss_ick); @@ -1379,6 +1385,12 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, int skip_init = 0; int i; + r = platform_device_register(&omapdss_device); + if (r) { + dev_err(fbdev->dev, "can't register omapdss device\n"); + return r; + } + memset(&dispc, 0, sizeof(dispc)); dispc.base = ioremap(DISPC_BASE, SZ_1K); @@ -1522,6 +1534,7 @@ static void omap_dispc_cleanup(void) free_irq(INT_24XX_DSS_IRQ, dispc.fbdev); put_dss_clocks(); iounmap(dispc.base); + platform_device_unregister(&omapdss_device); } const struct lcd_ctrl omap2_int_ctrl = { diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c index 17a975e4c9c99c78424795261647d0d011755512..0016f77cd13fb076c09682586454598e97e0d386 100644 --- a/drivers/video/omap/hwa742.c +++ b/drivers/video/omap/hwa742.c @@ -25,10 +25,11 @@ #include #include #include +#include #include -#include #include +#include "omapfb.h" #define HWA742_REV_CODE_REG 0x0 #define HWA742_CONFIG_REG 0x2 diff --git a/drivers/video/omap/lcd_2430sdp.c b/drivers/video/omap/lcd_2430sdp.c index fea7feee0b7743af431d04246d3b81a47094efb4..e3eccc9af78e3c18f8b4b2ec5c2f98bcac7ee464 100644 --- a/drivers/video/omap/lcd_2430sdp.c +++ b/drivers/video/omap/lcd_2430sdp.c @@ -25,12 +25,13 @@ #include #include #include -#include +#include #include -#include #include +#include "omapfb.h" + #define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91 #define SDP2430_LCD_PANEL_ENABLE_GPIO 154 #define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24 @@ -51,7 +52,7 @@ static unsigned enable_gpio; #define TWL4030_VPLL2_DEV_GRP 0x33 #define TWL4030_VPLL2_DEDICATED 0x36 -#define t2_out(c, r, v) twl4030_i2c_write_u8(c, r, v) +#define t2_out(c, r, v) twl_i2c_write_u8(c, r, v) static int sdp2430_panel_init(struct lcd_panel *panel, diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c index b3973ebd1b0f4aabc229caa5aeeaa632b324e852..567db6ac32c80ea0d80f6a7b5f398c82dc96ea7f 100644 --- a/drivers/video/omap/lcd_ams_delta.c +++ b/drivers/video/omap/lcd_ams_delta.c @@ -27,7 +27,8 @@ #include #include -#include + +#include "omapfb.h" #define AMS_DELTA_DEFAULT_CONTRAST 112 diff --git a/drivers/video/omap/lcd_apollon.c b/drivers/video/omap/lcd_apollon.c index 4c5cefc5153bc8f614c411d8594109a2fec07eb5..2be94eb3bbf518319bbd952e220af96c7d6c49e4 100644 --- a/drivers/video/omap/lcd_apollon.c +++ b/drivers/video/omap/lcd_apollon.c @@ -26,7 +26,8 @@ #include #include -#include + +#include "omapfb.h" /* #define USE_35INCH_LCD 1 */ diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c index 240b4fb10741a1547ab43ba8540c39b8fec43b97..8df688748b5a5376b6fd6419484e4bbdf296f0ba 100644 --- a/drivers/video/omap/lcd_h3.c +++ b/drivers/video/omap/lcd_h3.c @@ -24,7 +24,7 @@ #include #include -#include +#include "omapfb.h" #define MODULE_NAME "omapfb-lcd_h3" diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c index 720625da1f4e1325fb287414f325ce8a5d0f979c..03a06a982750bcc711653632c6ce829e7a526d09 100644 --- a/drivers/video/omap/lcd_h4.c +++ b/drivers/video/omap/lcd_h4.c @@ -22,7 +22,7 @@ #include #include -#include +#include "omapfb.h" static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) { diff --git a/drivers/video/omap/lcd_htcherald.c b/drivers/video/omap/lcd_htcherald.c index 2e0c81ea7483398ffc0f6db97bb599c179f7e8f6..a9007c5d1fad0bf07c14b5d834e12ab6264ae0f3 100644 --- a/drivers/video/omap/lcd_htcherald.c +++ b/drivers/video/omap/lcd_htcherald.c @@ -29,7 +29,7 @@ #include #include -#include +#include "omapfb.h" static int htcherald_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c index aafe9b497e2dc3126a75fecce6eb328d356b6e8e..3271f1643b26fd40a8a3b5b6ad97c75d6e61ecf3 100644 --- a/drivers/video/omap/lcd_inn1510.c +++ b/drivers/video/omap/lcd_inn1510.c @@ -24,7 +24,7 @@ #include #include -#include +#include "omapfb.h" static int innovator1510_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c index 0de338264a8a8ec962e3c26dd83e4f140c358abf..9fff86f67bde401ff475e2ba977db90897c613b0 100644 --- a/drivers/video/omap/lcd_inn1610.c +++ b/drivers/video/omap/lcd_inn1610.c @@ -23,7 +23,7 @@ #include #include -#include +#include "omapfb.h" #define MODULE_NAME "omapfb-lcd_h3" diff --git a/drivers/video/omap/lcd_ldp.c b/drivers/video/omap/lcd_ldp.c index 6a260dfdadc5523fe00d279313035b2a1ffa3baa..5bb7f6f146010ae667a523a95515f3f816808555 100644 --- a/drivers/video/omap/lcd_ldp.c +++ b/drivers/video/omap/lcd_ldp.c @@ -28,9 +28,10 @@ #include #include -#include #include +#include "omapfb.h" + #define LCD_PANEL_BACKLIGHT_GPIO (15 + OMAP_MAX_GPIO_LINES) #define LCD_PANEL_ENABLE_GPIO (7 + OMAP_MAX_GPIO_LINES) diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c index 8f3e2b4bb4f3d78f61f07a77359f35f45f48d341..abe1c76a3257249cf7e6eaca2cc2965dd145d079 100644 --- a/drivers/video/omap/lcd_mipid.c +++ b/drivers/video/omap/lcd_mipid.c @@ -23,9 +23,10 @@ #include #include -#include #include +#include "omapfb.h" + #define MIPID_MODULE_NAME "lcd_mipid" #define MIPID_CMD_READ_DISP_ID 0x04 diff --git a/drivers/video/omap/lcd_omap2evm.c b/drivers/video/omap/lcd_omap2evm.c index e1a38abca3e7461906b030f9d0a0a59ee780c13e..006c2fe7360ee5c3ad8f2604a931f376ee61b368 100644 --- a/drivers/video/omap/lcd_omap2evm.c +++ b/drivers/video/omap/lcd_omap2evm.c @@ -27,9 +27,10 @@ #include #include -#include #include +#include "omapfb.h" + #define LCD_PANEL_ENABLE_GPIO 154 #define LCD_PANEL_LR 128 #define LCD_PANEL_UD 129 diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c index ccec084ed6470bd8b41e2872adba0d0d6fc4f278..fc503d8f3c24c4790de120650fd479afa7319f44 100644 --- a/drivers/video/omap/lcd_omap3beagle.c +++ b/drivers/video/omap/lcd_omap3beagle.c @@ -26,9 +26,11 @@ #include #include -#include +#include #include +#include "omapfb.h" + #define LCD_PANEL_ENABLE_GPIO 170 static int omap3beagle_panel_init(struct lcd_panel *panel, diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c index 556eb31db24cd0a2938e531e8aeeb6525064e793..ae2edc4081a80f36ee793eed980f3fa27ecd517f 100644 --- a/drivers/video/omap/lcd_omap3evm.c +++ b/drivers/video/omap/lcd_omap3evm.c @@ -26,9 +26,10 @@ #include #include -#include #include +#include "omapfb.h" + #define LCD_PANEL_ENABLE_GPIO 153 #define LCD_PANEL_LR 2 #define LCD_PANEL_UD 3 diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c index bb21d7dca39ee26a2eeb731308087a180913f8b9..b87e8b83f29c5fe12f40c5c76f14ff1f071baa32 100644 --- a/drivers/video/omap/lcd_osk.c +++ b/drivers/video/omap/lcd_osk.c @@ -25,7 +25,7 @@ #include #include -#include +#include "omapfb.h" static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) { diff --git a/drivers/video/omap/lcd_overo.c b/drivers/video/omap/lcd_overo.c index b0f86e514cde2afaeb5cd99933af9620668ad93b..56ee192e9ee231357c8ba104ed5ba5b677cb1f57 100644 --- a/drivers/video/omap/lcd_overo.c +++ b/drivers/video/omap/lcd_overo.c @@ -25,9 +25,10 @@ #include #include -#include #include +#include "omapfb.h" + #define LCD_ENABLE 144 static int overo_panel_init(struct lcd_panel *panel, diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c index d30289603ce81413a32dcb91e85684b18fbe6c13..4cb301750d0269cca38b7129607a2fb51fa1c2e8 100644 --- a/drivers/video/omap/lcd_palmte.c +++ b/drivers/video/omap/lcd_palmte.c @@ -24,7 +24,7 @@ #include #include -#include +#include "omapfb.h" static int palmte_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c index 557424fb6df1144750c71bc2e3dd80925c418f47..ff0e6d7ab3a207b118fed6ffa0d189caae46b838 100644 --- a/drivers/video/omap/lcd_palmtt.c +++ b/drivers/video/omap/lcd_palmtt.c @@ -30,7 +30,7 @@ GPIO13 - screen blanking #include #include -#include +#include "omapfb.h" static int palmtt_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c index 5f4b5b2c1f4126d92dee22c9c3e7d2f07762565e..2334e56536bc94bf6310d20591ea79406110a40e 100644 --- a/drivers/video/omap/lcd_palmz71.c +++ b/drivers/video/omap/lcd_palmz71.c @@ -24,7 +24,7 @@ #include #include -#include +#include "omapfb.h" static int palmz71_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c index 5f32cafbf74c3565145918dbdea2cb35df7b2071..a33483910dc8361aaf86a84714b9f0705164e499 100644 --- a/drivers/video/omap/lcdc.c +++ b/drivers/video/omap/lcdc.c @@ -29,47 +29,17 @@ #include #include +#include #include -#include #include +#include "omapfb.h" + #include "lcdc.h" #define MODULE_NAME "lcdc" -#define OMAP_LCDC_BASE 0xfffec000 -#define OMAP_LCDC_SIZE 256 -#define OMAP_LCDC_IRQ INT_LCD_CTRL - -#define OMAP_LCDC_CONTROL (OMAP_LCDC_BASE + 0x00) -#define OMAP_LCDC_TIMING0 (OMAP_LCDC_BASE + 0x04) -#define OMAP_LCDC_TIMING1 (OMAP_LCDC_BASE + 0x08) -#define OMAP_LCDC_TIMING2 (OMAP_LCDC_BASE + 0x0c) -#define OMAP_LCDC_STATUS (OMAP_LCDC_BASE + 0x10) -#define OMAP_LCDC_SUBPANEL (OMAP_LCDC_BASE + 0x14) -#define OMAP_LCDC_LINE_INT (OMAP_LCDC_BASE + 0x18) -#define OMAP_LCDC_DISPLAY_STATUS (OMAP_LCDC_BASE + 0x1c) - -#define OMAP_LCDC_STAT_DONE (1 << 0) -#define OMAP_LCDC_STAT_VSYNC (1 << 1) -#define OMAP_LCDC_STAT_SYNC_LOST (1 << 2) -#define OMAP_LCDC_STAT_ABC (1 << 3) -#define OMAP_LCDC_STAT_LINE_INT (1 << 4) -#define OMAP_LCDC_STAT_FUF (1 << 5) -#define OMAP_LCDC_STAT_LOADED_PALETTE (1 << 6) - -#define OMAP_LCDC_CTRL_LCD_EN (1 << 0) -#define OMAP_LCDC_CTRL_LCD_TFT (1 << 7) -#define OMAP_LCDC_CTRL_LINE_IRQ_CLR_SEL (1 << 10) - -#define OMAP_LCDC_IRQ_VSYNC (1 << 2) -#define OMAP_LCDC_IRQ_DONE (1 << 3) -#define OMAP_LCDC_IRQ_LOADED_PALETTE (1 << 4) -#define OMAP_LCDC_IRQ_LINE_NIRQ (1 << 5) -#define OMAP_LCDC_IRQ_LINE (1 << 6) -#define OMAP_LCDC_IRQ_MASK (((1 << 5) - 1) << 2) - #define MAX_PALETTE_SIZE PAGE_SIZE enum lcdc_load_mode { diff --git a/arch/arm/plat-omap/include/plat/omapfb.h b/drivers/video/omap/omapfb.h similarity index 60% rename from arch/arm/plat-omap/include/plat/omapfb.h rename to drivers/video/omap/omapfb.h index bfef7ab95f1788414a7e5d15ef2029f4fc8030a0..46e4714014e8b420b3cd62f7f0951fe81b6680aa 100644 --- a/arch/arm/plat-omap/include/plat/omapfb.h +++ b/drivers/video/omap/omapfb.h @@ -1,5 +1,5 @@ /* - * File: arch/arm/plat-omap/include/mach/omapfb.h + * File: drivers/video/omap/omapfb.h * * Framebuffer driver for TI OMAP boards * @@ -24,151 +24,12 @@ #ifndef __OMAPFB_H #define __OMAPFB_H -#include -#include - -/* IOCTL commands. */ - -#define OMAP_IOW(num, dtype) _IOW('O', num, dtype) -#define OMAP_IOR(num, dtype) _IOR('O', num, dtype) -#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype) -#define OMAP_IO(num) _IO('O', num) - -#define OMAPFB_MIRROR OMAP_IOW(31, int) -#define OMAPFB_SYNC_GFX OMAP_IO(37) -#define OMAPFB_VSYNC OMAP_IO(38) -#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int) -#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps) -#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int) -#define OMAPFB_LCD_TEST OMAP_IOW(45, int) -#define OMAPFB_CTRL_TEST OMAP_IOW(46, int) -#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old) -#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key) -#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key) -#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info) -#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info) -#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window) -#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info) -#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info) - -#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff -#define OMAPFB_CAPS_LCDC_MASK 0x00fff000 -#define OMAPFB_CAPS_PANEL_MASK 0xff000000 - -#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000 -#define OMAPFB_CAPS_TEARSYNC 0x00002000 -#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000 -#define OMAPFB_CAPS_PLANE_SCALE 0x00008000 -#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000 -#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000 -#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000 -#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000 -#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000 - -/* Values from DSP must map to lower 16-bits */ -#define OMAPFB_FORMAT_MASK 0x00ff -#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100 -#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200 -#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400 -#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800 -#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000 - -#define OMAPFB_EVENT_READY 1 -#define OMAPFB_EVENT_DISABLED 2 - -#define OMAPFB_MEMTYPE_SDRAM 0 -#define OMAPFB_MEMTYPE_SRAM 1 -#define OMAPFB_MEMTYPE_MAX 1 - -enum omapfb_color_format { - OMAPFB_COLOR_RGB565 = 0, - OMAPFB_COLOR_YUV422, - OMAPFB_COLOR_YUV420, - OMAPFB_COLOR_CLUT_8BPP, - OMAPFB_COLOR_CLUT_4BPP, - OMAPFB_COLOR_CLUT_2BPP, - OMAPFB_COLOR_CLUT_1BPP, - OMAPFB_COLOR_RGB444, - OMAPFB_COLOR_YUY422, -}; - -struct omapfb_update_window { - __u32 x, y; - __u32 width, height; - __u32 format; - __u32 out_x, out_y; - __u32 out_width, out_height; - __u32 reserved[8]; -}; - -struct omapfb_update_window_old { - __u32 x, y; - __u32 width, height; - __u32 format; -}; - -enum omapfb_plane { - OMAPFB_PLANE_GFX = 0, - OMAPFB_PLANE_VID1, - OMAPFB_PLANE_VID2, -}; - -enum omapfb_channel_out { - OMAPFB_CHANNEL_OUT_LCD = 0, - OMAPFB_CHANNEL_OUT_DIGIT, -}; - -struct omapfb_plane_info { - __u32 pos_x; - __u32 pos_y; - __u8 enabled; - __u8 channel_out; - __u8 mirror; - __u8 reserved1; - __u32 out_width; - __u32 out_height; - __u32 reserved2[12]; -}; - -struct omapfb_mem_info { - __u32 size; - __u8 type; - __u8 reserved[3]; -}; - -struct omapfb_caps { - __u32 ctrl; - __u32 plane_color; - __u32 wnd_color; -}; - -enum omapfb_color_key_type { - OMAPFB_COLOR_KEY_DISABLED = 0, - OMAPFB_COLOR_KEY_GFX_DST, - OMAPFB_COLOR_KEY_VID_SRC, -}; - -struct omapfb_color_key { - __u8 channel_out; - __u32 background; - __u32 trans_key; - __u8 key_type; -}; - -enum omapfb_update_mode { - OMAPFB_UPDATE_DISABLED = 0, - OMAPFB_AUTO_UPDATE, - OMAPFB_MANUAL_UPDATE -}; - -#ifdef __KERNEL__ - -#include -#include #include #include +#include -#include +#define OMAPFB_EVENT_READY 1 +#define OMAPFB_EVENT_DISABLED 2 #define OMAP_LCDC_INV_VSYNC 0x0001 #define OMAP_LCDC_INV_HSYNC 0x0002 @@ -184,12 +45,6 @@ enum omapfb_update_mode { #define OMAPFB_PLANE_XRES_MIN 8 #define OMAPFB_PLANE_YRES_MIN 8 -#ifdef CONFIG_ARCH_OMAP1 -#define OMAPFB_PLANE_NUM 1 -#else -#define OMAPFB_PLANE_NUM 3 -#endif - struct omapfb_device; struct lcd_panel { @@ -256,7 +111,7 @@ struct lcd_ctrl_extif { void (*read_data) (void *buf, unsigned int len); void (*write_data) (const void *buf, unsigned int len); void (*transfer_area) (int width, int height, - void (callback)(void * data), void *data); + void (callback)(void *data), void *data); int (*setup_tearsync) (unsigned pin_cnt, unsigned hs_pulse_time, unsigned vs_pulse_time, int hs_pol_inv, int vs_pol_inv, int div); @@ -275,20 +130,6 @@ typedef int (*omapfb_notifier_callback_t)(struct notifier_block *, unsigned long event, void *fbi); -struct omapfb_mem_region { - u32 paddr; - void __iomem *vaddr; - unsigned long size; - u8 type; /* OMAPFB_PLANE_MEM_* */ - unsigned alloc:1; /* allocated by the driver */ - unsigned map:1; /* kernel mapped by the driver */ -}; - -struct omapfb_mem_desc { - int region_cnt; - struct omapfb_mem_region region[OMAPFB_PLANE_NUM]; -}; - struct lcd_ctrl { const char *name; void *data; @@ -331,9 +172,9 @@ struct lcd_ctrl { }; enum omapfb_state { - OMAPFB_DISABLED = 0, - OMAPFB_SUSPENDED= 99, - OMAPFB_ACTIVE = 100 + OMAPFB_DISABLED = 0, + OMAPFB_SUSPENDED = 99, + OMAPFB_ACTIVE = 100 }; struct omapfb_plane_struct { @@ -345,8 +186,8 @@ struct omapfb_plane_struct { struct omapfb_device { int state; - int ext_lcdc; /* Using external - LCD controller */ + int ext_lcdc; /* Using external + LCD controller */ struct mutex rqueue_mutex; int palette_size; @@ -364,19 +205,12 @@ struct omapfb_device { struct fb_info *fb_info[OMAPFB_PLANE_NUM]; }; -struct omapfb_platform_data { - struct omap_lcd_config lcd; - struct omapfb_mem_desc mem_desc; - void *ctrl_platform_data; -}; - #ifdef CONFIG_ARCH_OMAP1 extern struct lcd_ctrl omap1_lcd_ctrl; #else extern struct lcd_ctrl omap2_disp_ctrl; #endif -extern void omapfb_reserve_sdram(void); extern void omapfb_register_panel(struct lcd_panel *panel); extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); extern void omapfb_notify_clients(struct omapfb_device *fbdev, @@ -390,9 +224,4 @@ extern int omapfb_update_window_async(struct fb_info *fbi, void (*callback)(void *), void *callback_data); -/* in arch/arm/plat-omap/fb.c */ -extern void omapfb_set_ctrl_platform_data(void *pdata); - -#endif /* __KERNEL__ */ - #endif /* __OMAPFB_H */ diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index f900a43db8d7c868b2afa71403600f04a66545b5..c7f59a5ccdbc3866ac8a19a24ca38582bb6822f2 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c @@ -29,8 +29,8 @@ #include #include -#include +#include "omapfb.h" #include "lcdc.h" #include "dispc.h" diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c index c90fa39486b41cd51fadff8836c44fab3d76fd8f..fed7b1bda19c58d488cd4b301c922a4fc3c0ef80 100644 --- a/drivers/video/omap/rfbi.c +++ b/drivers/video/omap/rfbi.c @@ -27,8 +27,7 @@ #include #include -#include - +#include "omapfb.h" #include "dispc.h" /* To work around an RFBI transfer rate limitation */ diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c index 79dc84f0971316aff44f62df53123b9582f067f3..8fb7c708f563946f63866c20a094fb9608747124 100644 --- a/drivers/video/omap/sossi.c +++ b/drivers/video/omap/sossi.c @@ -23,10 +23,11 @@ #include #include #include +#include #include -#include +#include "omapfb.h" #include "lcdc.h" #define MODULE_NAME "omapfb-sossi" diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..d877c361abdaa02405133cd12b9d23288aa82662 --- /dev/null +++ b/drivers/video/omap2/Kconfig @@ -0,0 +1,9 @@ +config OMAP2_VRAM + bool + +config OMAP2_VRFB + bool + +source "drivers/video/omap2/dss/Kconfig" +source "drivers/video/omap2/omapfb/Kconfig" +source "drivers/video/omap2/displays/Kconfig" diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d853d05dad312361b0d83aa4d4d351d47fd75140 --- /dev/null +++ b/drivers/video/omap2/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_OMAP2_VRAM) += vram.o +obj-$(CONFIG_OMAP2_VRFB) += vrfb.o + +obj-y += dss/ +obj-y += omapfb/ +obj-y += displays/ diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..b12a59c9c50a7ff1fa2a7dd61e285ce31d7c8b85 --- /dev/null +++ b/drivers/video/omap2/displays/Kconfig @@ -0,0 +1,22 @@ +menu "OMAP2/3 Display Device Drivers" + depends on OMAP2_DSS + +config PANEL_GENERIC + tristate "Generic Panel" + help + Generic panel driver. + Used for DVI output for Beagle and OMAP3 SDP. + +config PANEL_SHARP_LS037V7DW01 + tristate "Sharp LS037V7DW01 LCD Panel" + depends on OMAP2_DSS + help + LCD Panel used in TI's SDP3430 and EVM boards + +config PANEL_TAAL + tristate "Taal DSI Panel" + depends on OMAP2_DSS_DSI + help + Taal DSI command mode panel from TPO. + +endmenu diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..955646440b3a4218ff03673682402abce89a8858 --- /dev/null +++ b/drivers/video/omap2/displays/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o +obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o + +obj-$(CONFIG_PANEL_TAAL) += panel-taal.o diff --git a/drivers/video/omap2/displays/panel-generic.c b/drivers/video/omap2/displays/panel-generic.c new file mode 100644 index 0000000000000000000000000000000000000000..eb48d1afd8008437458bb3fe87e351b5ce785c42 --- /dev/null +++ b/drivers/video/omap2/displays/panel-generic.c @@ -0,0 +1,104 @@ +/* + * Generic panel support + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen + * + * 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, see . + */ + +#include +#include + +#include + +static struct omap_video_timings generic_panel_timings = { + /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ + .x_res = 640, + .y_res = 480, + .pixel_clock = 23500, + .hfp = 48, + .hsw = 32, + .hbp = 80, + .vfp = 3, + .vsw = 4, + .vbp = 7, +}; + +static int generic_panel_probe(struct omap_dss_device *dssdev) +{ + dssdev->panel.config = OMAP_DSS_LCD_TFT; + dssdev->panel.timings = generic_panel_timings; + + return 0; +} + +static void generic_panel_remove(struct omap_dss_device *dssdev) +{ +} + +static int generic_panel_enable(struct omap_dss_device *dssdev) +{ + int r = 0; + + if (dssdev->platform_enable) + r = dssdev->platform_enable(dssdev); + + return r; +} + +static void generic_panel_disable(struct omap_dss_device *dssdev) +{ + if (dssdev->platform_disable) + dssdev->platform_disable(dssdev); +} + +static int generic_panel_suspend(struct omap_dss_device *dssdev) +{ + generic_panel_disable(dssdev); + return 0; +} + +static int generic_panel_resume(struct omap_dss_device *dssdev) +{ + return generic_panel_enable(dssdev); +} + +static struct omap_dss_driver generic_driver = { + .probe = generic_panel_probe, + .remove = generic_panel_remove, + + .enable = generic_panel_enable, + .disable = generic_panel_disable, + .suspend = generic_panel_suspend, + .resume = generic_panel_resume, + + .driver = { + .name = "generic_panel", + .owner = THIS_MODULE, + }, +}; + +static int __init generic_panel_drv_init(void) +{ + return omap_dss_register_driver(&generic_driver); +} + +static void __exit generic_panel_drv_exit(void) +{ + omap_dss_unregister_driver(&generic_driver); +} + +module_init(generic_panel_drv_init); +module_exit(generic_panel_drv_exit); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c new file mode 100644 index 0000000000000000000000000000000000000000..bbe880bbe795b36729cf9c75bbf7676823834d4f --- /dev/null +++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c @@ -0,0 +1,153 @@ +/* + * LCD panel driver for Sharp LS037V7DW01 + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen + * + * 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, see . + */ + +#include +#include +#include +#include +#include + +#include + +struct sharp_data { + /* XXX This regulator should actually be in SDP board file, not here, + * as it doesn't actually power the LCD, but something else that + * affects the output to LCD (I think. Somebody clarify). It doesn't do + * harm here, as SDP is the only board using this currently */ + struct regulator *vdvi_reg; +}; + +static struct omap_video_timings sharp_ls_timings = { + .x_res = 480, + .y_res = 640, + + .pixel_clock = 19200, + + .hsw = 2, + .hfp = 1, + .hbp = 28, + + .vsw = 1, + .vfp = 1, + .vbp = 1, +}; + +static int sharp_ls_panel_probe(struct omap_dss_device *dssdev) +{ + struct sharp_data *sd; + + dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | + OMAP_DSS_LCD_IHS; + dssdev->panel.acb = 0x28; + dssdev->panel.timings = sharp_ls_timings; + + sd = kzalloc(sizeof(*sd), GFP_KERNEL); + if (!sd) + return -ENOMEM; + + dev_set_drvdata(&dssdev->dev, sd); + + sd->vdvi_reg = regulator_get(&dssdev->dev, "vdvi"); + if (IS_ERR(sd->vdvi_reg)) { + kfree(sd); + pr_err("failed to get VDVI regulator\n"); + return PTR_ERR(sd->vdvi_reg); + } + + return 0; +} + +static void sharp_ls_panel_remove(struct omap_dss_device *dssdev) +{ + struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); + + regulator_put(sd->vdvi_reg); + + kfree(sd); +} + +static int sharp_ls_panel_enable(struct omap_dss_device *dssdev) +{ + struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); + int r = 0; + + /* wait couple of vsyncs until enabling the LCD */ + msleep(50); + + regulator_enable(sd->vdvi_reg); + + if (dssdev->platform_enable) + r = dssdev->platform_enable(dssdev); + + return r; +} + +static void sharp_ls_panel_disable(struct omap_dss_device *dssdev) +{ + struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); + + if (dssdev->platform_disable) + dssdev->platform_disable(dssdev); + + regulator_disable(sd->vdvi_reg); + + /* wait at least 5 vsyncs after disabling the LCD */ + + msleep(100); +} + +static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev) +{ + sharp_ls_panel_disable(dssdev); + return 0; +} + +static int sharp_ls_panel_resume(struct omap_dss_device *dssdev) +{ + return sharp_ls_panel_enable(dssdev); +} + +static struct omap_dss_driver sharp_ls_driver = { + .probe = sharp_ls_panel_probe, + .remove = sharp_ls_panel_remove, + + .enable = sharp_ls_panel_enable, + .disable = sharp_ls_panel_disable, + .suspend = sharp_ls_panel_suspend, + .resume = sharp_ls_panel_resume, + + .driver = { + .name = "sharp_ls_panel", + .owner = THIS_MODULE, + }, +}; + +static int __init sharp_ls_panel_drv_init(void) +{ + return omap_dss_register_driver(&sharp_ls_driver); +} + +static void __exit sharp_ls_panel_drv_exit(void) +{ + omap_dss_unregister_driver(&sharp_ls_driver); +} + +module_init(sharp_ls_panel_drv_init); +module_exit(sharp_ls_panel_drv_exit); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c new file mode 100644 index 0000000000000000000000000000000000000000..1f01dfc5e52e6d6d50f1c1459e87b2fd46f0df9b --- /dev/null +++ b/drivers/video/omap2/displays/panel-taal.c @@ -0,0 +1,1003 @@ +/* + * Taal DSI command mode panel + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * 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, see . + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* DSI Virtual channel. Hardcoded for now. */ +#define TCH 0 + +#define DCS_READ_NUM_ERRORS 0x05 +#define DCS_READ_POWER_MODE 0x0a +#define DCS_READ_MADCTL 0x0b +#define DCS_READ_PIXEL_FORMAT 0x0c +#define DCS_RDDSDR 0x0f +#define DCS_SLEEP_IN 0x10 +#define DCS_SLEEP_OUT 0x11 +#define DCS_DISPLAY_OFF 0x28 +#define DCS_DISPLAY_ON 0x29 +#define DCS_COLUMN_ADDR 0x2a +#define DCS_PAGE_ADDR 0x2b +#define DCS_MEMORY_WRITE 0x2c +#define DCS_TEAR_OFF 0x34 +#define DCS_TEAR_ON 0x35 +#define DCS_MEM_ACC_CTRL 0x36 +#define DCS_PIXEL_FORMAT 0x3a +#define DCS_BRIGHTNESS 0x51 +#define DCS_CTRL_DISPLAY 0x53 +#define DCS_WRITE_CABC 0x55 +#define DCS_READ_CABC 0x56 +#define DCS_GET_ID1 0xda +#define DCS_GET_ID2 0xdb +#define DCS_GET_ID3 0xdc + +/* #define TAAL_USE_ESD_CHECK */ +#define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000) + +struct taal_data { + struct backlight_device *bldev; + + unsigned long hw_guard_end; /* next value of jiffies when we can + * issue the next sleep in/out command + */ + unsigned long hw_guard_wait; /* max guard time in jiffies */ + + struct omap_dss_device *dssdev; + + bool enabled; + u8 rotate; + bool mirror; + + bool te_enabled; + bool use_ext_te; + struct completion te_completion; + + bool use_dsi_bl; + + bool cabc_broken; + unsigned cabc_mode; + + bool intro_printed; + + struct workqueue_struct *esd_wq; + struct delayed_work esd_work; +}; + +static void taal_esd_work(struct work_struct *work); + +static void hw_guard_start(struct taal_data *td, int guard_msec) +{ + td->hw_guard_wait = msecs_to_jiffies(guard_msec); + td->hw_guard_end = jiffies + td->hw_guard_wait; +} + +static void hw_guard_wait(struct taal_data *td) +{ + unsigned long wait = td->hw_guard_end - jiffies; + + if ((long)wait > 0 && wait <= td->hw_guard_wait) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(wait); + } +} + +static int taal_dcs_read_1(u8 dcs_cmd, u8 *data) +{ + int r; + u8 buf[1]; + + r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1); + + if (r < 0) + return r; + + *data = buf[0]; + + return 0; +} + +static int taal_dcs_write_0(u8 dcs_cmd) +{ + return dsi_vc_dcs_write(TCH, &dcs_cmd, 1); +} + +static int taal_dcs_write_1(u8 dcs_cmd, u8 param) +{ + u8 buf[2]; + buf[0] = dcs_cmd; + buf[1] = param; + return dsi_vc_dcs_write(TCH, buf, 2); +} + +static int taal_sleep_in(struct taal_data *td) + +{ + u8 cmd; + int r; + + hw_guard_wait(td); + + cmd = DCS_SLEEP_IN; + r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1); + if (r) + return r; + + hw_guard_start(td, 120); + + msleep(5); + + return 0; +} + +static int taal_sleep_out(struct taal_data *td) +{ + int r; + + hw_guard_wait(td); + + r = taal_dcs_write_0(DCS_SLEEP_OUT); + if (r) + return r; + + hw_guard_start(td, 120); + + msleep(5); + + return 0; +} + +static int taal_get_id(u8 *id1, u8 *id2, u8 *id3) +{ + int r; + + r = taal_dcs_read_1(DCS_GET_ID1, id1); + if (r) + return r; + r = taal_dcs_read_1(DCS_GET_ID2, id2); + if (r) + return r; + r = taal_dcs_read_1(DCS_GET_ID3, id3); + if (r) + return r; + + return 0; +} + +static int taal_set_addr_mode(u8 rotate, bool mirror) +{ + int r; + u8 mode; + int b5, b6, b7; + + r = taal_dcs_read_1(DCS_READ_MADCTL, &mode); + if (r) + return r; + + switch (rotate) { + default: + case 0: + b7 = 0; + b6 = 0; + b5 = 0; + break; + case 1: + b7 = 0; + b6 = 1; + b5 = 1; + break; + case 2: + b7 = 1; + b6 = 1; + b5 = 0; + break; + case 3: + b7 = 1; + b6 = 0; + b5 = 1; + break; + } + + if (mirror) + b6 = !b6; + + mode &= ~((1<<7) | (1<<6) | (1<<5)); + mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); + + return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode); +} + +static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) +{ + int r; + u16 x1 = x; + u16 x2 = x + w - 1; + u16 y1 = y; + u16 y2 = y + h - 1; + + u8 buf[5]; + buf[0] = DCS_COLUMN_ADDR; + buf[1] = (x1 >> 8) & 0xff; + buf[2] = (x1 >> 0) & 0xff; + buf[3] = (x2 >> 8) & 0xff; + buf[4] = (x2 >> 0) & 0xff; + + r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); + if (r) + return r; + + buf[0] = DCS_PAGE_ADDR; + buf[1] = (y1 >> 8) & 0xff; + buf[2] = (y1 >> 0) & 0xff; + buf[3] = (y2 >> 8) & 0xff; + buf[4] = (y2 >> 0) & 0xff; + + r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); + if (r) + return r; + + dsi_vc_send_bta_sync(TCH); + + return r; +} + +static int taal_bl_update_status(struct backlight_device *dev) +{ + struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + int r; + int level; + + if (dev->props.fb_blank == FB_BLANK_UNBLANK && + dev->props.power == FB_BLANK_UNBLANK) + level = dev->props.brightness; + else + level = 0; + + dev_dbg(&dssdev->dev, "update brightness to %d\n", level); + + if (td->use_dsi_bl) { + if (td->enabled) { + dsi_bus_lock(); + r = taal_dcs_write_1(DCS_BRIGHTNESS, level); + dsi_bus_unlock(); + if (r) + return r; + } + } else { + if (!dssdev->set_backlight) + return -EINVAL; + + r = dssdev->set_backlight(dssdev, level); + if (r) + return r; + } + + return 0; +} + +static int taal_bl_get_intensity(struct backlight_device *dev) +{ + if (dev->props.fb_blank == FB_BLANK_UNBLANK && + dev->props.power == FB_BLANK_UNBLANK) + return dev->props.brightness; + + return 0; +} + +static struct backlight_ops taal_bl_ops = { + .get_brightness = taal_bl_get_intensity, + .update_status = taal_bl_update_status, +}; + +static void taal_get_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + *timings = dssdev->panel.timings; +} + +static void taal_get_resolution(struct omap_dss_device *dssdev, + u16 *xres, u16 *yres) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + + if (td->rotate == 0 || td->rotate == 2) { + *xres = dssdev->panel.timings.x_res; + *yres = dssdev->panel.timings.y_res; + } else { + *yres = dssdev->panel.timings.x_res; + *xres = dssdev->panel.timings.y_res; + } +} + +static irqreturn_t taal_te_isr(int irq, void *data) +{ + struct omap_dss_device *dssdev = data; + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + + complete_all(&td->te_completion); + + return IRQ_HANDLED; +} + +static ssize_t taal_num_errors_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + u8 errors; + int r; + + if (td->enabled) { + dsi_bus_lock(); + r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors); + dsi_bus_unlock(); + } else { + r = -ENODEV; + } + + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%d\n", errors); +} + +static ssize_t taal_hw_revision_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + u8 id1, id2, id3; + int r; + + if (td->enabled) { + dsi_bus_lock(); + r = taal_get_id(&id1, &id2, &id3); + dsi_bus_unlock(); + } else { + r = -ENODEV; + } + + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3); +} + +static const char *cabc_modes[] = { + "off", /* used also always when CABC is not supported */ + "ui", + "still-image", + "moving-image", +}; + +static ssize_t show_cabc_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + const char *mode_str; + int mode; + int len; + + mode = td->cabc_mode; + + mode_str = "unknown"; + if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes)) + mode_str = cabc_modes[mode]; + len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str); + + return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1; +} + +static ssize_t store_cabc_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + int i; + + for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) { + if (sysfs_streq(cabc_modes[i], buf)) + break; + } + + if (i == ARRAY_SIZE(cabc_modes)) + return -EINVAL; + + if (td->enabled) { + dsi_bus_lock(); + if (!td->cabc_broken) + taal_dcs_write_1(DCS_WRITE_CABC, i); + dsi_bus_unlock(); + } + + td->cabc_mode = i; + + return count; +} + +static ssize_t show_cabc_available_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int len; + int i; + + for (i = 0, len = 0; + len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++) + len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s", + i ? " " : "", cabc_modes[i], + i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : ""); + + return len < PAGE_SIZE ? len : PAGE_SIZE - 1; +} + +static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL); +static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL); +static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR, + show_cabc_mode, store_cabc_mode); +static DEVICE_ATTR(cabc_available_modes, S_IRUGO, + show_cabc_available_modes, NULL); + +static struct attribute *taal_attrs[] = { + &dev_attr_num_dsi_errors.attr, + &dev_attr_hw_revision.attr, + &dev_attr_cabc_mode.attr, + &dev_attr_cabc_available_modes.attr, + NULL, +}; + +static struct attribute_group taal_attr_group = { + .attrs = taal_attrs, +}; + +static int taal_probe(struct omap_dss_device *dssdev) +{ + struct taal_data *td; + struct backlight_device *bldev; + int r; + + const struct omap_video_timings taal_panel_timings = { + .x_res = 864, + .y_res = 480, + }; + + dev_dbg(&dssdev->dev, "probe\n"); + + dssdev->panel.config = OMAP_DSS_LCD_TFT; + dssdev->panel.timings = taal_panel_timings; + dssdev->ctrl.pixel_size = 24; + + td = kzalloc(sizeof(*td), GFP_KERNEL); + if (!td) { + r = -ENOMEM; + goto err0; + } + td->dssdev = dssdev; + + td->esd_wq = create_singlethread_workqueue("taal_esd"); + if (td->esd_wq == NULL) { + dev_err(&dssdev->dev, "can't create ESD workqueue\n"); + r = -ENOMEM; + goto err2; + } + INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work); + + dev_set_drvdata(&dssdev->dev, td); + + dssdev->get_timings = taal_get_timings; + dssdev->get_resolution = taal_get_resolution; + + /* if no platform set_backlight() defined, presume DSI backlight + * control */ + if (!dssdev->set_backlight) + td->use_dsi_bl = true; + + bldev = backlight_device_register("taal", &dssdev->dev, dssdev, + &taal_bl_ops); + if (IS_ERR(bldev)) { + r = PTR_ERR(bldev); + goto err1; + } + + td->bldev = bldev; + + bldev->props.fb_blank = FB_BLANK_UNBLANK; + bldev->props.power = FB_BLANK_UNBLANK; + if (td->use_dsi_bl) { + bldev->props.max_brightness = 255; + bldev->props.brightness = 255; + } else { + bldev->props.max_brightness = 127; + bldev->props.brightness = 127; + } + + taal_bl_update_status(bldev); + + if (dssdev->phy.dsi.ext_te) { + int gpio = dssdev->phy.dsi.ext_te_gpio; + + r = gpio_request(gpio, "taal irq"); + if (r) { + dev_err(&dssdev->dev, "GPIO request failed\n"); + goto err3; + } + + gpio_direction_input(gpio); + + r = request_irq(gpio_to_irq(gpio), taal_te_isr, + IRQF_DISABLED | IRQF_TRIGGER_RISING, + "taal vsync", dssdev); + + if (r) { + dev_err(&dssdev->dev, "IRQ request failed\n"); + gpio_free(gpio); + goto err3; + } + + init_completion(&td->te_completion); + + td->use_ext_te = true; + } + + r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); + if (r) { + dev_err(&dssdev->dev, "failed to create sysfs files\n"); + goto err4; + } + + return 0; +err4: + if (td->use_ext_te) { + int gpio = dssdev->phy.dsi.ext_te_gpio; + free_irq(gpio_to_irq(gpio), dssdev); + gpio_free(gpio); + } +err3: + backlight_device_unregister(bldev); +err2: + cancel_delayed_work_sync(&td->esd_work); + destroy_workqueue(td->esd_wq); +err1: + kfree(td); +err0: + return r; +} + +static void taal_remove(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + struct backlight_device *bldev; + + dev_dbg(&dssdev->dev, "remove\n"); + + sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); + + if (td->use_ext_te) { + int gpio = dssdev->phy.dsi.ext_te_gpio; + free_irq(gpio_to_irq(gpio), dssdev); + gpio_free(gpio); + } + + bldev = td->bldev; + bldev->props.power = FB_BLANK_POWERDOWN; + taal_bl_update_status(bldev); + backlight_device_unregister(bldev); + + cancel_delayed_work_sync(&td->esd_work); + destroy_workqueue(td->esd_wq); + + kfree(td); +} + +static int taal_enable(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + u8 id1, id2, id3; + int r; + + dev_dbg(&dssdev->dev, "enable\n"); + + if (dssdev->platform_enable) { + r = dssdev->platform_enable(dssdev); + if (r) + return r; + } + + /* it seems we have to wait a bit until taal is ready */ + msleep(5); + + r = taal_sleep_out(td); + if (r) + goto err; + + r = taal_get_id(&id1, &id2, &id3); + if (r) + goto err; + + /* on early revisions CABC is broken */ + if (id2 == 0x00 || id2 == 0xff || id2 == 0x81) + td->cabc_broken = true; + + taal_dcs_write_1(DCS_BRIGHTNESS, 0xff); + taal_dcs_write_1(DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */ + + taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ + + taal_set_addr_mode(td->rotate, td->mirror); + if (!td->cabc_broken) + taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode); + + taal_dcs_write_0(DCS_DISPLAY_ON); + +#ifdef TAAL_USE_ESD_CHECK + queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); +#endif + + td->enabled = 1; + + if (!td->intro_printed) { + dev_info(&dssdev->dev, "revision %02x.%02x.%02x\n", + id1, id2, id3); + if (td->cabc_broken) + dev_info(&dssdev->dev, + "old Taal version, CABC disabled\n"); + td->intro_printed = true; + } + + return 0; +err: + if (dssdev->platform_disable) + dssdev->platform_disable(dssdev); + + return r; +} + +static void taal_disable(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + + dev_dbg(&dssdev->dev, "disable\n"); + + cancel_delayed_work(&td->esd_work); + + taal_dcs_write_0(DCS_DISPLAY_OFF); + taal_sleep_in(td); + + /* wait a bit so that the message goes through */ + msleep(10); + + if (dssdev->platform_disable) + dssdev->platform_disable(dssdev); + + td->enabled = 0; +} + +static int taal_suspend(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + struct backlight_device *bldev = td->bldev; + + bldev->props.power = FB_BLANK_POWERDOWN; + taal_bl_update_status(bldev); + + return 0; +} + +static int taal_resume(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + struct backlight_device *bldev = td->bldev; + + bldev->props.power = FB_BLANK_UNBLANK; + taal_bl_update_status(bldev); + + return 0; +} + +static void taal_setup_update(struct omap_dss_device *dssdev, + u16 x, u16 y, u16 w, u16 h) +{ + taal_set_update_window(x, y, w, h); +} + +static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + int r; + + td->te_enabled = enable; + + if (enable) + r = taal_dcs_write_1(DCS_TEAR_ON, 0); + else + r = taal_dcs_write_0(DCS_TEAR_OFF); + + return r; +} + +static int taal_wait_te(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + long wait = msecs_to_jiffies(500); + + if (!td->use_ext_te || !td->te_enabled) + return 0; + + INIT_COMPLETION(td->te_completion); + wait = wait_for_completion_timeout(&td->te_completion, wait); + if (wait == 0) { + dev_err(&dssdev->dev, "timeout waiting TE\n"); + return -ETIME; + } + + return 0; +} + +static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + int r; + + dev_dbg(&dssdev->dev, "rotate %d\n", rotate); + + if (td->enabled) { + r = taal_set_addr_mode(rotate, td->mirror); + + if (r) + return r; + } + + td->rotate = rotate; + + return 0; +} + +static u8 taal_get_rotate(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + return td->rotate; +} + +static int taal_mirror(struct omap_dss_device *dssdev, bool enable) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + int r; + + dev_dbg(&dssdev->dev, "mirror %d\n", enable); + + if (td->enabled) { + r = taal_set_addr_mode(td->rotate, enable); + + if (r) + return r; + } + + td->mirror = enable; + + return 0; +} + +static bool taal_get_mirror(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + return td->mirror; +} + +static int taal_run_test(struct omap_dss_device *dssdev, int test_num) +{ + u8 id1, id2, id3; + int r; + + r = taal_dcs_read_1(DCS_GET_ID1, &id1); + if (r) + return r; + r = taal_dcs_read_1(DCS_GET_ID2, &id2); + if (r) + return r; + r = taal_dcs_read_1(DCS_GET_ID3, &id3); + if (r) + return r; + + return 0; +} + +static int taal_memory_read(struct omap_dss_device *dssdev, + void *buf, size_t size, + u16 x, u16 y, u16 w, u16 h) +{ + int r; + int first = 1; + int plen; + unsigned buf_used = 0; + + if (size < w * h * 3) + return -ENOMEM; + + size = min(w * h * 3, + dssdev->panel.timings.x_res * + dssdev->panel.timings.y_res * 3); + + /* plen 1 or 2 goes into short packet. until checksum error is fixed, + * use short packets. plen 32 works, but bigger packets seem to cause + * an error. */ + if (size % 2) + plen = 1; + else + plen = 2; + + taal_setup_update(dssdev, x, y, w, h); + + r = dsi_vc_set_max_rx_packet_size(TCH, plen); + if (r) + return r; + + while (buf_used < size) { + u8 dcs_cmd = first ? 0x2e : 0x3e; + first = 0; + + r = dsi_vc_dcs_read(TCH, dcs_cmd, + buf + buf_used, size - buf_used); + + if (r < 0) { + dev_err(&dssdev->dev, "read error\n"); + goto err; + } + + buf_used += r; + + if (r < plen) { + dev_err(&dssdev->dev, "short read\n"); + break; + } + + if (signal_pending(current)) { + dev_err(&dssdev->dev, "signal pending, " + "aborting memory read\n"); + r = -ERESTARTSYS; + goto err; + } + } + + r = buf_used; + +err: + dsi_vc_set_max_rx_packet_size(TCH, 1); + + return r; +} + +static void taal_esd_work(struct work_struct *work) +{ + struct taal_data *td = container_of(work, struct taal_data, + esd_work.work); + struct omap_dss_device *dssdev = td->dssdev; + u8 state1, state2; + int r; + + if (!td->enabled) + return; + + dsi_bus_lock(); + + r = taal_dcs_read_1(DCS_RDDSDR, &state1); + if (r) { + dev_err(&dssdev->dev, "failed to read Taal status\n"); + goto err; + } + + /* Run self diagnostics */ + r = taal_sleep_out(td); + if (r) { + dev_err(&dssdev->dev, "failed to run Taal self-diagnostics\n"); + goto err; + } + + r = taal_dcs_read_1(DCS_RDDSDR, &state2); + if (r) { + dev_err(&dssdev->dev, "failed to read Taal status\n"); + goto err; + } + + /* Each sleep out command will trigger a self diagnostic and flip + * Bit6 if the test passes. + */ + if (!((state1 ^ state2) & (1 << 6))) { + dev_err(&dssdev->dev, "LCD self diagnostics failed\n"); + goto err; + } + /* Self-diagnostics result is also shown on TE GPIO line. We need + * to re-enable TE after self diagnostics */ + if (td->use_ext_te && td->te_enabled) + taal_enable_te(dssdev, true); + + dsi_bus_unlock(); + + queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); + + return; +err: + dev_err(&dssdev->dev, "performing LCD reset\n"); + + taal_disable(dssdev); + taal_enable(dssdev); + + dsi_bus_unlock(); + + queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); +} + +static struct omap_dss_driver taal_driver = { + .probe = taal_probe, + .remove = taal_remove, + + .enable = taal_enable, + .disable = taal_disable, + .suspend = taal_suspend, + .resume = taal_resume, + + .setup_update = taal_setup_update, + .enable_te = taal_enable_te, + .wait_for_te = taal_wait_te, + .set_rotate = taal_rotate, + .get_rotate = taal_get_rotate, + .set_mirror = taal_mirror, + .get_mirror = taal_get_mirror, + .run_test = taal_run_test, + .memory_read = taal_memory_read, + + .driver = { + .name = "taal", + .owner = THIS_MODULE, + }, +}; + +static int __init taal_init(void) +{ + omap_dss_register_driver(&taal_driver); + + return 0; +} + +static void __exit taal_exit(void) +{ + omap_dss_unregister_driver(&taal_driver); +} + +module_init(taal_init); +module_exit(taal_exit); + +MODULE_AUTHOR("Tomi Valkeinen "); +MODULE_DESCRIPTION("Taal Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..71d8dec30635d3b17e44bca7e130726e614816d9 --- /dev/null +++ b/drivers/video/omap2/dss/Kconfig @@ -0,0 +1,89 @@ +menuconfig OMAP2_DSS + tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" + depends on ARCH_OMAP2 || ARCH_OMAP3 + help + OMAP2/3 Display Subsystem support. + +if OMAP2_DSS + +config OMAP2_VRAM_SIZE + int "VRAM size (MB)" + range 0 32 + default 0 + help + The amount of SDRAM to reserve at boot time for video RAM use. + This VRAM will be used by omapfb and other drivers that need + large continuous RAM area for video use. + + You can also set this with "vram=" kernel argument, or + in the board file. + +config OMAP2_DSS_DEBUG_SUPPORT + bool "Debug support" + default y + help + This enables debug messages. You need to enable printing + with 'debug' module parameter. + +config OMAP2_DSS_RFBI + bool "RFBI support" + default n + help + MIPI DBI, or RFBI (Remote Framebuffer Interface), support. + +config OMAP2_DSS_VENC + bool "VENC support" + default y + help + OMAP Video Encoder support. + +config OMAP2_DSS_SDI + bool "SDI support" + depends on ARCH_OMAP3 + default n + help + SDI (Serial Display Interface) support. + +config OMAP2_DSS_DSI + bool "DSI support" + depends on ARCH_OMAP3 + default n + help + MIPI DSI support. + +config OMAP2_DSS_USE_DSI_PLL + bool "Use DSI PLL for PCLK (EXPERIMENTAL)" + default n + depends on OMAP2_DSS_DSI + help + Use DSI PLL to generate pixel clock. Currently only for DPI output. + DSI PLL can be used to generate higher and more precise pixel clocks. + +config OMAP2_DSS_FAKE_VSYNC + bool "Fake VSYNC irq from manual update displays" + default n + help + If this is selected, DSI will generate a fake DISPC VSYNC interrupt + when DSI has sent a frame. This is only needed with DSI or RFBI + displays using manual mode, and you want VSYNC to, for example, + time animation. + +config OMAP2_DSS_MIN_FCK_PER_PCK + int "Minimum FCK/PCK ratio (for scaling)" + range 0 32 + default 0 + help + This can be used to adjust the minimum FCK/PCK ratio. + + With this you can make sure that DISPC FCK is at least + n x PCK. Video plane scaling requires higher FCK than + normally. + + If this is set to 0, there's no extra constraint on the + DISPC FCK. However, the FCK will at minimum be + 2xPCK (if active matrix) or 3xPCK (if passive matrix). + + Max FCK is 173MHz, so this doesn't work if your PCK + is very high. + +endif diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..980c72c2db98b876f4e0b69bfa614de176b643a1 --- /dev/null +++ b/drivers/video/omap2/dss/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_OMAP2_DSS) += omapdss.o +omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o +omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o +omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o +omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o +omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c new file mode 100644 index 0000000000000000000000000000000000000000..29497a0c9a91a8e76fbc446f52172ab531298c6e --- /dev/null +++ b/drivers/video/omap2/dss/core.c @@ -0,0 +1,919 @@ +/* + * linux/drivers/video/omap2/dss/core.c + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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, see . + */ + +#define DSS_SUBSYS_NAME "CORE" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "dss.h" + +static struct { + struct platform_device *pdev; + int ctx_id; + + struct clk *dss_ick; + struct clk *dss1_fck; + struct clk *dss2_fck; + struct clk *dss_54m_fck; + struct clk *dss_96m_fck; + unsigned num_clks_enabled; +} core; + +static void dss_clk_enable_all_no_ctx(void); +static void dss_clk_disable_all_no_ctx(void); +static void dss_clk_enable_no_ctx(enum dss_clock clks); +static void dss_clk_disable_no_ctx(enum dss_clock clks); + +static char *def_disp_name; +module_param_named(def_disp, def_disp_name, charp, 0); +MODULE_PARM_DESC(def_disp_name, "default display name"); + +#ifdef DEBUG +unsigned int dss_debug; +module_param_named(debug, dss_debug, bool, 0644); +#endif + +/* CONTEXT */ +static int dss_get_ctx_id(void) +{ + struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; + int r; + + if (!pdata->get_last_off_on_transaction_id) + return 0; + r = pdata->get_last_off_on_transaction_id(&core.pdev->dev); + if (r < 0) { + dev_err(&core.pdev->dev, "getting transaction ID failed, " + "will force context restore\n"); + r = -1; + } + return r; +} + +int dss_need_ctx_restore(void) +{ + int id = dss_get_ctx_id(); + + if (id < 0 || id != core.ctx_id) { + DSSDBG("ctx id %d -> id %d\n", + core.ctx_id, id); + core.ctx_id = id; + return 1; + } else { + return 0; + } +} + +static void save_all_ctx(void) +{ + DSSDBG("save context\n"); + + dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); + + dss_save_context(); + dispc_save_context(); +#ifdef CONFIG_OMAP2_DSS_DSI + dsi_save_context(); +#endif + + dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); +} + +static void restore_all_ctx(void) +{ + DSSDBG("restore context\n"); + + dss_clk_enable_all_no_ctx(); + + dss_restore_context(); + dispc_restore_context(); +#ifdef CONFIG_OMAP2_DSS_DSI + dsi_restore_context(); +#endif + + dss_clk_disable_all_no_ctx(); +} + +/* CLOCKS */ +static void core_dump_clocks(struct seq_file *s) +{ + int i; + struct clk *clocks[5] = { + core.dss_ick, + core.dss1_fck, + core.dss2_fck, + core.dss_54m_fck, + core.dss_96m_fck + }; + + seq_printf(s, "- CORE -\n"); + + seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled); + + for (i = 0; i < 5; i++) { + if (!clocks[i]) + continue; + seq_printf(s, "%-15s\t%lu\t%d\n", + clocks[i]->name, + clk_get_rate(clocks[i]), + clocks[i]->usecount); + } +} + +static int dss_get_clock(struct clk **clock, const char *clk_name) +{ + struct clk *clk; + + clk = clk_get(&core.pdev->dev, clk_name); + + if (IS_ERR(clk)) { + DSSERR("can't get clock %s", clk_name); + return PTR_ERR(clk); + } + + *clock = clk; + + DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); + + return 0; +} + +static int dss_get_clocks(void) +{ + int r; + + core.dss_ick = NULL; + core.dss1_fck = NULL; + core.dss2_fck = NULL; + core.dss_54m_fck = NULL; + core.dss_96m_fck = NULL; + + r = dss_get_clock(&core.dss_ick, "ick"); + if (r) + goto err; + + r = dss_get_clock(&core.dss1_fck, "dss1_fck"); + if (r) + goto err; + + r = dss_get_clock(&core.dss2_fck, "dss2_fck"); + if (r) + goto err; + + r = dss_get_clock(&core.dss_54m_fck, "tv_fck"); + if (r) + goto err; + + r = dss_get_clock(&core.dss_96m_fck, "video_fck"); + if (r) + goto err; + + return 0; + +err: + if (core.dss_ick) + clk_put(core.dss_ick); + if (core.dss1_fck) + clk_put(core.dss1_fck); + if (core.dss2_fck) + clk_put(core.dss2_fck); + if (core.dss_54m_fck) + clk_put(core.dss_54m_fck); + if (core.dss_96m_fck) + clk_put(core.dss_96m_fck); + + return r; +} + +static void dss_put_clocks(void) +{ + if (core.dss_96m_fck) + clk_put(core.dss_96m_fck); + clk_put(core.dss_54m_fck); + clk_put(core.dss1_fck); + clk_put(core.dss2_fck); + clk_put(core.dss_ick); +} + +unsigned long dss_clk_get_rate(enum dss_clock clk) +{ + switch (clk) { + case DSS_CLK_ICK: + return clk_get_rate(core.dss_ick); + case DSS_CLK_FCK1: + return clk_get_rate(core.dss1_fck); + case DSS_CLK_FCK2: + return clk_get_rate(core.dss2_fck); + case DSS_CLK_54M: + return clk_get_rate(core.dss_54m_fck); + case DSS_CLK_96M: + return clk_get_rate(core.dss_96m_fck); + } + + BUG(); + return 0; +} + +static unsigned count_clk_bits(enum dss_clock clks) +{ + unsigned num_clks = 0; + + if (clks & DSS_CLK_ICK) + ++num_clks; + if (clks & DSS_CLK_FCK1) + ++num_clks; + if (clks & DSS_CLK_FCK2) + ++num_clks; + if (clks & DSS_CLK_54M) + ++num_clks; + if (clks & DSS_CLK_96M) + ++num_clks; + + return num_clks; +} + +static void dss_clk_enable_no_ctx(enum dss_clock clks) +{ + unsigned num_clks = count_clk_bits(clks); + + if (clks & DSS_CLK_ICK) + clk_enable(core.dss_ick); + if (clks & DSS_CLK_FCK1) + clk_enable(core.dss1_fck); + if (clks & DSS_CLK_FCK2) + clk_enable(core.dss2_fck); + if (clks & DSS_CLK_54M) + clk_enable(core.dss_54m_fck); + if (clks & DSS_CLK_96M) + clk_enable(core.dss_96m_fck); + + core.num_clks_enabled += num_clks; +} + +void dss_clk_enable(enum dss_clock clks) +{ + dss_clk_enable_no_ctx(clks); + + if (cpu_is_omap34xx() && dss_need_ctx_restore()) + restore_all_ctx(); +} + +static void dss_clk_disable_no_ctx(enum dss_clock clks) +{ + unsigned num_clks = count_clk_bits(clks); + + if (clks & DSS_CLK_ICK) + clk_disable(core.dss_ick); + if (clks & DSS_CLK_FCK1) + clk_disable(core.dss1_fck); + if (clks & DSS_CLK_FCK2) + clk_disable(core.dss2_fck); + if (clks & DSS_CLK_54M) + clk_disable(core.dss_54m_fck); + if (clks & DSS_CLK_96M) + clk_disable(core.dss_96m_fck); + + core.num_clks_enabled -= num_clks; +} + +void dss_clk_disable(enum dss_clock clks) +{ + if (cpu_is_omap34xx()) { + unsigned num_clks = count_clk_bits(clks); + + BUG_ON(core.num_clks_enabled < num_clks); + + if (core.num_clks_enabled == num_clks) + save_all_ctx(); + } + + dss_clk_disable_no_ctx(clks); +} + +static void dss_clk_enable_all_no_ctx(void) +{ + enum dss_clock clks; + + clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; + if (cpu_is_omap34xx()) + clks |= DSS_CLK_96M; + dss_clk_enable_no_ctx(clks); +} + +static void dss_clk_disable_all_no_ctx(void) +{ + enum dss_clock clks; + + clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; + if (cpu_is_omap34xx()) + clks |= DSS_CLK_96M; + dss_clk_disable_no_ctx(clks); +} + +static void dss_clk_disable_all(void) +{ + enum dss_clock clks; + + clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; + if (cpu_is_omap34xx()) + clks |= DSS_CLK_96M; + dss_clk_disable(clks); +} + +/* DEBUGFS */ +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) +static void dss_debug_dump_clocks(struct seq_file *s) +{ + core_dump_clocks(s); + dss_dump_clocks(s); + dispc_dump_clocks(s); +#ifdef CONFIG_OMAP2_DSS_DSI + dsi_dump_clocks(s); +#endif +} + +static int dss_debug_show(struct seq_file *s, void *unused) +{ + void (*func)(struct seq_file *) = s->private; + func(s); + return 0; +} + +static int dss_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, dss_debug_show, inode->i_private); +} + +static const struct file_operations dss_debug_fops = { + .open = dss_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct dentry *dss_debugfs_dir; + +static int dss_initialize_debugfs(void) +{ + dss_debugfs_dir = debugfs_create_dir("omapdss", NULL); + if (IS_ERR(dss_debugfs_dir)) { + int err = PTR_ERR(dss_debugfs_dir); + dss_debugfs_dir = NULL; + return err; + } + + debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, + &dss_debug_dump_clocks, &dss_debug_fops); + + debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, + &dss_dump_regs, &dss_debug_fops); + debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir, + &dispc_dump_regs, &dss_debug_fops); +#ifdef CONFIG_OMAP2_DSS_RFBI + debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir, + &rfbi_dump_regs, &dss_debug_fops); +#endif +#ifdef CONFIG_OMAP2_DSS_DSI + debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir, + &dsi_dump_regs, &dss_debug_fops); +#endif +#ifdef CONFIG_OMAP2_DSS_VENC + debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, + &venc_dump_regs, &dss_debug_fops); +#endif + return 0; +} + +static void dss_uninitialize_debugfs(void) +{ + if (dss_debugfs_dir) + debugfs_remove_recursive(dss_debugfs_dir); +} +#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ + +/* PLATFORM DEVICE */ +static int omap_dss_probe(struct platform_device *pdev) +{ + struct omap_dss_board_info *pdata = pdev->dev.platform_data; + int skip_init = 0; + int r; + int i; + + core.pdev = pdev; + + dss_init_overlay_managers(pdev); + dss_init_overlays(pdev); + + r = dss_get_clocks(); + if (r) + goto fail0; + + dss_clk_enable_all_no_ctx(); + + core.ctx_id = dss_get_ctx_id(); + DSSDBG("initial ctx id %u\n", core.ctx_id); + +#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT + /* DISPC_CONTROL */ + if (omap_readl(0x48050440) & 1) /* LCD enabled? */ + skip_init = 1; +#endif + + r = dss_init(skip_init); + if (r) { + DSSERR("Failed to initialize DSS\n"); + goto fail0; + } + +#ifdef CONFIG_OMAP2_DSS_RFBI + r = rfbi_init(); + if (r) { + DSSERR("Failed to initialize rfbi\n"); + goto fail0; + } +#endif + + r = dpi_init(); + if (r) { + DSSERR("Failed to initialize dpi\n"); + goto fail0; + } + + r = dispc_init(); + if (r) { + DSSERR("Failed to initialize dispc\n"); + goto fail0; + } +#ifdef CONFIG_OMAP2_DSS_VENC + r = venc_init(pdev); + if (r) { + DSSERR("Failed to initialize venc\n"); + goto fail0; + } +#endif + if (cpu_is_omap34xx()) { +#ifdef CONFIG_OMAP2_DSS_SDI + r = sdi_init(skip_init); + if (r) { + DSSERR("Failed to initialize SDI\n"); + goto fail0; + } +#endif +#ifdef CONFIG_OMAP2_DSS_DSI + r = dsi_init(pdev); + if (r) { + DSSERR("Failed to initialize DSI\n"); + goto fail0; + } +#endif + } + +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) + r = dss_initialize_debugfs(); + if (r) + goto fail0; +#endif + + for (i = 0; i < pdata->num_devices; ++i) { + struct omap_dss_device *dssdev = pdata->devices[i]; + + r = omap_dss_register_device(dssdev); + if (r) + DSSERR("device reg failed %d\n", i); + + if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0) + pdata->default_device = dssdev; + } + + dss_clk_disable_all(); + + return 0; + + /* XXX fail correctly */ +fail0: + return r; +} + +static int omap_dss_remove(struct platform_device *pdev) +{ + struct omap_dss_board_info *pdata = pdev->dev.platform_data; + int i; + int c; + +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) + dss_uninitialize_debugfs(); +#endif + +#ifdef CONFIG_OMAP2_DSS_VENC + venc_exit(); +#endif + dispc_exit(); + dpi_exit(); +#ifdef CONFIG_OMAP2_DSS_RFBI + rfbi_exit(); +#endif + if (cpu_is_omap34xx()) { +#ifdef CONFIG_OMAP2_DSS_DSI + dsi_exit(); +#endif +#ifdef CONFIG_OMAP2_DSS_SDI + sdi_exit(); +#endif + } + + dss_exit(); + + /* these should be removed at some point */ + c = core.dss_ick->usecount; + if (c > 0) { + DSSERR("warning: dss_ick usecount %d, disabling\n", c); + while (c-- > 0) + clk_disable(core.dss_ick); + } + + c = core.dss1_fck->usecount; + if (c > 0) { + DSSERR("warning: dss1_fck usecount %d, disabling\n", c); + while (c-- > 0) + clk_disable(core.dss1_fck); + } + + c = core.dss2_fck->usecount; + if (c > 0) { + DSSERR("warning: dss2_fck usecount %d, disabling\n", c); + while (c-- > 0) + clk_disable(core.dss2_fck); + } + + c = core.dss_54m_fck->usecount; + if (c > 0) { + DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c); + while (c-- > 0) + clk_disable(core.dss_54m_fck); + } + + if (core.dss_96m_fck) { + c = core.dss_96m_fck->usecount; + if (c > 0) { + DSSERR("warning: dss_96m_fck usecount %d, disabling\n", + c); + while (c-- > 0) + clk_disable(core.dss_96m_fck); + } + } + + dss_put_clocks(); + + dss_uninit_overlays(pdev); + dss_uninit_overlay_managers(pdev); + + for (i = 0; i < pdata->num_devices; ++i) + omap_dss_unregister_device(pdata->devices[i]); + + return 0; +} + +static void omap_dss_shutdown(struct platform_device *pdev) +{ + DSSDBG("shutdown\n"); + dss_disable_all_devices(); +} + +static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state) +{ + DSSDBG("suspend %d\n", state.event); + + return dss_suspend_all_devices(); +} + +static int omap_dss_resume(struct platform_device *pdev) +{ + DSSDBG("resume\n"); + + return dss_resume_all_devices(); +} + +static struct platform_driver omap_dss_driver = { + .probe = omap_dss_probe, + .remove = omap_dss_remove, + .shutdown = omap_dss_shutdown, + .suspend = omap_dss_suspend, + .resume = omap_dss_resume, + .driver = { + .name = "omapdss", + .owner = THIS_MODULE, + }, +}; + +/* BUS */ +static int dss_bus_match(struct device *dev, struct device_driver *driver) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + + DSSDBG("bus_match. dev %s/%s, drv %s\n", + dev_name(dev), dssdev->driver_name, driver->name); + + return strcmp(dssdev->driver_name, driver->name) == 0; +} + +static ssize_t device_name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + return snprintf(buf, PAGE_SIZE, "%s\n", + dssdev->name ? + dssdev->name : ""); +} + +static struct device_attribute default_dev_attrs[] = { + __ATTR(name, S_IRUGO, device_name_show, NULL), + __ATTR_NULL, +}; + +static ssize_t driver_name_show(struct device_driver *drv, char *buf) +{ + struct omap_dss_driver *dssdrv = to_dss_driver(drv); + return snprintf(buf, PAGE_SIZE, "%s\n", + dssdrv->driver.name ? + dssdrv->driver.name : ""); +} +static struct driver_attribute default_drv_attrs[] = { + __ATTR(name, S_IRUGO, driver_name_show, NULL), + __ATTR_NULL, +}; + +static struct bus_type dss_bus_type = { + .name = "omapdss", + .match = dss_bus_match, + .dev_attrs = default_dev_attrs, + .drv_attrs = default_drv_attrs, +}; + +static void dss_bus_release(struct device *dev) +{ + DSSDBG("bus_release\n"); +} + +static struct device dss_bus = { + .release = dss_bus_release, +}; + +struct bus_type *dss_get_bus(void) +{ + return &dss_bus_type; +} + +/* DRIVER */ +static int dss_driver_probe(struct device *dev) +{ + int r; + struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); + struct omap_dss_device *dssdev = to_dss_device(dev); + struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; + bool force; + + DSSDBG("driver_probe: dev %s/%s, drv %s\n", + dev_name(dev), dssdev->driver_name, + dssdrv->driver.name); + + dss_init_device(core.pdev, dssdev); + + /* skip this if the device is behind a ctrl */ + if (!dssdev->panel.ctrl) { + force = pdata->default_device == dssdev; + dss_recheck_connections(dssdev, force); + } + + r = dssdrv->probe(dssdev); + + if (r) { + DSSERR("driver probe failed: %d\n", r); + return r; + } + + DSSDBG("probe done for device %s\n", dev_name(dev)); + + dssdev->driver = dssdrv; + + return 0; +} + +static int dss_driver_remove(struct device *dev) +{ + struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); + struct omap_dss_device *dssdev = to_dss_device(dev); + + DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev), + dssdev->driver_name); + + dssdrv->remove(dssdev); + + dss_uninit_device(core.pdev, dssdev); + + dssdev->driver = NULL; + + return 0; +} + +int omap_dss_register_driver(struct omap_dss_driver *dssdriver) +{ + dssdriver->driver.bus = &dss_bus_type; + dssdriver->driver.probe = dss_driver_probe; + dssdriver->driver.remove = dss_driver_remove; + return driver_register(&dssdriver->driver); +} +EXPORT_SYMBOL(omap_dss_register_driver); + +void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver) +{ + driver_unregister(&dssdriver->driver); +} +EXPORT_SYMBOL(omap_dss_unregister_driver); + +/* DEVICE */ +static void reset_device(struct device *dev, int check) +{ + u8 *dev_p = (u8 *)dev; + u8 *dev_end = dev_p + sizeof(*dev); + void *saved_pdata; + + saved_pdata = dev->platform_data; + if (check) { + /* + * Check if there is any other setting than platform_data + * in struct device; warn that these will be reset by our + * init. + */ + dev->platform_data = NULL; + while (dev_p < dev_end) { + if (*dev_p) { + WARN("%s: struct device fields will be " + "discarded\n", + __func__); + break; + } + dev_p++; + } + } + memset(dev, 0, sizeof(*dev)); + dev->platform_data = saved_pdata; +} + + +static void omap_dss_dev_release(struct device *dev) +{ + reset_device(dev, 0); +} + +int omap_dss_register_device(struct omap_dss_device *dssdev) +{ + static int dev_num; + static int panel_num; + int r; + + WARN_ON(!dssdev->driver_name); + + reset_device(&dssdev->dev, 1); + dssdev->dev.bus = &dss_bus_type; + dssdev->dev.parent = &dss_bus; + dssdev->dev.release = omap_dss_dev_release; + dev_set_name(&dssdev->dev, "display%d", dev_num++); + r = device_register(&dssdev->dev); + if (r) + return r; + + if (dssdev->ctrl.panel) { + struct omap_dss_device *panel = dssdev->ctrl.panel; + + panel->panel.ctrl = dssdev; + + reset_device(&panel->dev, 1); + panel->dev.bus = &dss_bus_type; + panel->dev.parent = &dssdev->dev; + panel->dev.release = omap_dss_dev_release; + dev_set_name(&panel->dev, "panel%d", panel_num++); + r = device_register(&panel->dev); + if (r) + return r; + } + + return 0; +} + +void omap_dss_unregister_device(struct omap_dss_device *dssdev) +{ + device_unregister(&dssdev->dev); + + if (dssdev->ctrl.panel) { + struct omap_dss_device *panel = dssdev->ctrl.panel; + device_unregister(&panel->dev); + } +} + +/* BUS */ +static int omap_dss_bus_register(void) +{ + int r; + + r = bus_register(&dss_bus_type); + if (r) { + DSSERR("bus register failed\n"); + return r; + } + + dev_set_name(&dss_bus, "omapdss"); + r = device_register(&dss_bus); + if (r) { + DSSERR("bus driver register failed\n"); + bus_unregister(&dss_bus_type); + return r; + } + + return 0; +} + +/* INIT */ + +#ifdef CONFIG_OMAP2_DSS_MODULE +static void omap_dss_bus_unregister(void) +{ + device_unregister(&dss_bus); + + bus_unregister(&dss_bus_type); +} + +static int __init omap_dss_init(void) +{ + int r; + + r = omap_dss_bus_register(); + if (r) + return r; + + r = platform_driver_register(&omap_dss_driver); + if (r) { + omap_dss_bus_unregister(); + return r; + } + + return 0; +} + +static void __exit omap_dss_exit(void) +{ + platform_driver_unregister(&omap_dss_driver); + + omap_dss_bus_unregister(); +} + +module_init(omap_dss_init); +module_exit(omap_dss_exit); +#else +static int __init omap_dss_init(void) +{ + return omap_dss_bus_register(); +} + +static int __init omap_dss_init2(void) +{ + return platform_driver_register(&omap_dss_driver); +} + +core_initcall(omap_dss_init); +device_initcall(omap_dss_init2); +#endif + +MODULE_AUTHOR("Tomi Valkeinen "); +MODULE_DESCRIPTION("OMAP2/3 Display Subsystem"); +MODULE_LICENSE("GPL v2"); + diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c new file mode 100644 index 0000000000000000000000000000000000000000..6dabf4b2f00531a6720f9ff754f79af684e8df63 --- /dev/null +++ b/drivers/video/omap2/dss/dispc.c @@ -0,0 +1,3091 @@ +/* + * linux/drivers/video/omap2/dss/dispc.c + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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, see . + */ + +#define DSS_SUBSYS_NAME "DISPC" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "dss.h" + +/* DISPC */ +#define DISPC_BASE 0x48050400 + +#define DISPC_SZ_REGS SZ_1K + +struct dispc_reg { u16 idx; }; + +#define DISPC_REG(idx) ((const struct dispc_reg) { idx }) + +/* DISPC common */ +#define DISPC_REVISION DISPC_REG(0x0000) +#define DISPC_SYSCONFIG DISPC_REG(0x0010) +#define DISPC_SYSSTATUS DISPC_REG(0x0014) +#define DISPC_IRQSTATUS DISPC_REG(0x0018) +#define DISPC_IRQENABLE DISPC_REG(0x001C) +#define DISPC_CONTROL DISPC_REG(0x0040) +#define DISPC_CONFIG DISPC_REG(0x0044) +#define DISPC_CAPABLE DISPC_REG(0x0048) +#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C) +#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050) +#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054) +#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058) +#define DISPC_LINE_STATUS DISPC_REG(0x005C) +#define DISPC_LINE_NUMBER DISPC_REG(0x0060) +#define DISPC_TIMING_H DISPC_REG(0x0064) +#define DISPC_TIMING_V DISPC_REG(0x0068) +#define DISPC_POL_FREQ DISPC_REG(0x006C) +#define DISPC_DIVISOR DISPC_REG(0x0070) +#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) +#define DISPC_SIZE_DIG DISPC_REG(0x0078) +#define DISPC_SIZE_LCD DISPC_REG(0x007C) + +/* DISPC GFX plane */ +#define DISPC_GFX_BA0 DISPC_REG(0x0080) +#define DISPC_GFX_BA1 DISPC_REG(0x0084) +#define DISPC_GFX_POSITION DISPC_REG(0x0088) +#define DISPC_GFX_SIZE DISPC_REG(0x008C) +#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0) +#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4) +#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8) +#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC) +#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0) +#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4) +#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8) + +#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4) +#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8) +#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC) + +#define DISPC_CPR_COEF_R DISPC_REG(0x0220) +#define DISPC_CPR_COEF_G DISPC_REG(0x0224) +#define DISPC_CPR_COEF_B DISPC_REG(0x0228) + +#define DISPC_GFX_PRELOAD DISPC_REG(0x022C) + +/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */ +#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx) + +#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000) +#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004) +#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008) +#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C) +#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010) +#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014) +#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018) +#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C) +#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020) +#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024) +#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028) +#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C) +#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030) + +/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ +#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8) +/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ +#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8) +/* coef index i = {0, 1, 2, 3, 4} */ +#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4) +/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ +#define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4) + +#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04) + + +#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ + DISPC_IRQ_OCP_ERR | \ + DISPC_IRQ_VID1_FIFO_UNDERFLOW | \ + DISPC_IRQ_VID2_FIFO_UNDERFLOW | \ + DISPC_IRQ_SYNC_LOST | \ + DISPC_IRQ_SYNC_LOST_DIGIT) + +#define DISPC_MAX_NR_ISRS 8 + +struct omap_dispc_isr_data { + omap_dispc_isr_t isr; + void *arg; + u32 mask; +}; + +#define REG_GET(idx, start, end) \ + FLD_GET(dispc_read_reg(idx), start, end) + +#define REG_FLD_MOD(idx, val, start, end) \ + dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) + +static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES, + DISPC_VID_ATTRIBUTES(0), + DISPC_VID_ATTRIBUTES(1) }; + +static struct { + void __iomem *base; + + u32 fifo_size[3]; + + spinlock_t irq_lock; + u32 irq_error_mask; + struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS]; + u32 error_irqs; + struct work_struct error_work; + + u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; +} dispc; + +static void _omap_dispc_set_irqs(void); + +static inline void dispc_write_reg(const struct dispc_reg idx, u32 val) +{ + __raw_writel(val, dispc.base + idx.idx); +} + +static inline u32 dispc_read_reg(const struct dispc_reg idx) +{ + return __raw_readl(dispc.base + idx.idx); +} + +#define SR(reg) \ + dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg) +#define RR(reg) \ + dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)]) + +void dispc_save_context(void) +{ + if (cpu_is_omap24xx()) + return; + + SR(SYSCONFIG); + SR(IRQENABLE); + SR(CONTROL); + SR(CONFIG); + SR(DEFAULT_COLOR0); + SR(DEFAULT_COLOR1); + SR(TRANS_COLOR0); + SR(TRANS_COLOR1); + SR(LINE_NUMBER); + SR(TIMING_H); + SR(TIMING_V); + SR(POL_FREQ); + SR(DIVISOR); + SR(GLOBAL_ALPHA); + SR(SIZE_DIG); + SR(SIZE_LCD); + + SR(GFX_BA0); + SR(GFX_BA1); + SR(GFX_POSITION); + SR(GFX_SIZE); + SR(GFX_ATTRIBUTES); + SR(GFX_FIFO_THRESHOLD); + SR(GFX_ROW_INC); + SR(GFX_PIXEL_INC); + SR(GFX_WINDOW_SKIP); + SR(GFX_TABLE_BA); + + SR(DATA_CYCLE1); + SR(DATA_CYCLE2); + SR(DATA_CYCLE3); + + SR(CPR_COEF_R); + SR(CPR_COEF_G); + SR(CPR_COEF_B); + + SR(GFX_PRELOAD); + + /* VID1 */ + SR(VID_BA0(0)); + SR(VID_BA1(0)); + SR(VID_POSITION(0)); + SR(VID_SIZE(0)); + SR(VID_ATTRIBUTES(0)); + SR(VID_FIFO_THRESHOLD(0)); + SR(VID_ROW_INC(0)); + SR(VID_PIXEL_INC(0)); + SR(VID_FIR(0)); + SR(VID_PICTURE_SIZE(0)); + SR(VID_ACCU0(0)); + SR(VID_ACCU1(0)); + + SR(VID_FIR_COEF_H(0, 0)); + SR(VID_FIR_COEF_H(0, 1)); + SR(VID_FIR_COEF_H(0, 2)); + SR(VID_FIR_COEF_H(0, 3)); + SR(VID_FIR_COEF_H(0, 4)); + SR(VID_FIR_COEF_H(0, 5)); + SR(VID_FIR_COEF_H(0, 6)); + SR(VID_FIR_COEF_H(0, 7)); + + SR(VID_FIR_COEF_HV(0, 0)); + SR(VID_FIR_COEF_HV(0, 1)); + SR(VID_FIR_COEF_HV(0, 2)); + SR(VID_FIR_COEF_HV(0, 3)); + SR(VID_FIR_COEF_HV(0, 4)); + SR(VID_FIR_COEF_HV(0, 5)); + SR(VID_FIR_COEF_HV(0, 6)); + SR(VID_FIR_COEF_HV(0, 7)); + + SR(VID_CONV_COEF(0, 0)); + SR(VID_CONV_COEF(0, 1)); + SR(VID_CONV_COEF(0, 2)); + SR(VID_CONV_COEF(0, 3)); + SR(VID_CONV_COEF(0, 4)); + + SR(VID_FIR_COEF_V(0, 0)); + SR(VID_FIR_COEF_V(0, 1)); + SR(VID_FIR_COEF_V(0, 2)); + SR(VID_FIR_COEF_V(0, 3)); + SR(VID_FIR_COEF_V(0, 4)); + SR(VID_FIR_COEF_V(0, 5)); + SR(VID_FIR_COEF_V(0, 6)); + SR(VID_FIR_COEF_V(0, 7)); + + SR(VID_PRELOAD(0)); + + /* VID2 */ + SR(VID_BA0(1)); + SR(VID_BA1(1)); + SR(VID_POSITION(1)); + SR(VID_SIZE(1)); + SR(VID_ATTRIBUTES(1)); + SR(VID_FIFO_THRESHOLD(1)); + SR(VID_ROW_INC(1)); + SR(VID_PIXEL_INC(1)); + SR(VID_FIR(1)); + SR(VID_PICTURE_SIZE(1)); + SR(VID_ACCU0(1)); + SR(VID_ACCU1(1)); + + SR(VID_FIR_COEF_H(1, 0)); + SR(VID_FIR_COEF_H(1, 1)); + SR(VID_FIR_COEF_H(1, 2)); + SR(VID_FIR_COEF_H(1, 3)); + SR(VID_FIR_COEF_H(1, 4)); + SR(VID_FIR_COEF_H(1, 5)); + SR(VID_FIR_COEF_H(1, 6)); + SR(VID_FIR_COEF_H(1, 7)); + + SR(VID_FIR_COEF_HV(1, 0)); + SR(VID_FIR_COEF_HV(1, 1)); + SR(VID_FIR_COEF_HV(1, 2)); + SR(VID_FIR_COEF_HV(1, 3)); + SR(VID_FIR_COEF_HV(1, 4)); + SR(VID_FIR_COEF_HV(1, 5)); + SR(VID_FIR_COEF_HV(1, 6)); + SR(VID_FIR_COEF_HV(1, 7)); + + SR(VID_CONV_COEF(1, 0)); + SR(VID_CONV_COEF(1, 1)); + SR(VID_CONV_COEF(1, 2)); + SR(VID_CONV_COEF(1, 3)); + SR(VID_CONV_COEF(1, 4)); + + SR(VID_FIR_COEF_V(1, 0)); + SR(VID_FIR_COEF_V(1, 1)); + SR(VID_FIR_COEF_V(1, 2)); + SR(VID_FIR_COEF_V(1, 3)); + SR(VID_FIR_COEF_V(1, 4)); + SR(VID_FIR_COEF_V(1, 5)); + SR(VID_FIR_COEF_V(1, 6)); + SR(VID_FIR_COEF_V(1, 7)); + + SR(VID_PRELOAD(1)); +} + +void dispc_restore_context(void) +{ + RR(SYSCONFIG); + RR(IRQENABLE); + /*RR(CONTROL);*/ + RR(CONFIG); + RR(DEFAULT_COLOR0); + RR(DEFAULT_COLOR1); + RR(TRANS_COLOR0); + RR(TRANS_COLOR1); + RR(LINE_NUMBER); + RR(TIMING_H); + RR(TIMING_V); + RR(POL_FREQ); + RR(DIVISOR); + RR(GLOBAL_ALPHA); + RR(SIZE_DIG); + RR(SIZE_LCD); + + RR(GFX_BA0); + RR(GFX_BA1); + RR(GFX_POSITION); + RR(GFX_SIZE); + RR(GFX_ATTRIBUTES); + RR(GFX_FIFO_THRESHOLD); + RR(GFX_ROW_INC); + RR(GFX_PIXEL_INC); + RR(GFX_WINDOW_SKIP); + RR(GFX_TABLE_BA); + + RR(DATA_CYCLE1); + RR(DATA_CYCLE2); + RR(DATA_CYCLE3); + + RR(CPR_COEF_R); + RR(CPR_COEF_G); + RR(CPR_COEF_B); + + RR(GFX_PRELOAD); + + /* VID1 */ + RR(VID_BA0(0)); + RR(VID_BA1(0)); + RR(VID_POSITION(0)); + RR(VID_SIZE(0)); + RR(VID_ATTRIBUTES(0)); + RR(VID_FIFO_THRESHOLD(0)); + RR(VID_ROW_INC(0)); + RR(VID_PIXEL_INC(0)); + RR(VID_FIR(0)); + RR(VID_PICTURE_SIZE(0)); + RR(VID_ACCU0(0)); + RR(VID_ACCU1(0)); + + RR(VID_FIR_COEF_H(0, 0)); + RR(VID_FIR_COEF_H(0, 1)); + RR(VID_FIR_COEF_H(0, 2)); + RR(VID_FIR_COEF_H(0, 3)); + RR(VID_FIR_COEF_H(0, 4)); + RR(VID_FIR_COEF_H(0, 5)); + RR(VID_FIR_COEF_H(0, 6)); + RR(VID_FIR_COEF_H(0, 7)); + + RR(VID_FIR_COEF_HV(0, 0)); + RR(VID_FIR_COEF_HV(0, 1)); + RR(VID_FIR_COEF_HV(0, 2)); + RR(VID_FIR_COEF_HV(0, 3)); + RR(VID_FIR_COEF_HV(0, 4)); + RR(VID_FIR_COEF_HV(0, 5)); + RR(VID_FIR_COEF_HV(0, 6)); + RR(VID_FIR_COEF_HV(0, 7)); + + RR(VID_CONV_COEF(0, 0)); + RR(VID_CONV_COEF(0, 1)); + RR(VID_CONV_COEF(0, 2)); + RR(VID_CONV_COEF(0, 3)); + RR(VID_CONV_COEF(0, 4)); + + RR(VID_FIR_COEF_V(0, 0)); + RR(VID_FIR_COEF_V(0, 1)); + RR(VID_FIR_COEF_V(0, 2)); + RR(VID_FIR_COEF_V(0, 3)); + RR(VID_FIR_COEF_V(0, 4)); + RR(VID_FIR_COEF_V(0, 5)); + RR(VID_FIR_COEF_V(0, 6)); + RR(VID_FIR_COEF_V(0, 7)); + + RR(VID_PRELOAD(0)); + + /* VID2 */ + RR(VID_BA0(1)); + RR(VID_BA1(1)); + RR(VID_POSITION(1)); + RR(VID_SIZE(1)); + RR(VID_ATTRIBUTES(1)); + RR(VID_FIFO_THRESHOLD(1)); + RR(VID_ROW_INC(1)); + RR(VID_PIXEL_INC(1)); + RR(VID_FIR(1)); + RR(VID_PICTURE_SIZE(1)); + RR(VID_ACCU0(1)); + RR(VID_ACCU1(1)); + + RR(VID_FIR_COEF_H(1, 0)); + RR(VID_FIR_COEF_H(1, 1)); + RR(VID_FIR_COEF_H(1, 2)); + RR(VID_FIR_COEF_H(1, 3)); + RR(VID_FIR_COEF_H(1, 4)); + RR(VID_FIR_COEF_H(1, 5)); + RR(VID_FIR_COEF_H(1, 6)); + RR(VID_FIR_COEF_H(1, 7)); + + RR(VID_FIR_COEF_HV(1, 0)); + RR(VID_FIR_COEF_HV(1, 1)); + RR(VID_FIR_COEF_HV(1, 2)); + RR(VID_FIR_COEF_HV(1, 3)); + RR(VID_FIR_COEF_HV(1, 4)); + RR(VID_FIR_COEF_HV(1, 5)); + RR(VID_FIR_COEF_HV(1, 6)); + RR(VID_FIR_COEF_HV(1, 7)); + + RR(VID_CONV_COEF(1, 0)); + RR(VID_CONV_COEF(1, 1)); + RR(VID_CONV_COEF(1, 2)); + RR(VID_CONV_COEF(1, 3)); + RR(VID_CONV_COEF(1, 4)); + + RR(VID_FIR_COEF_V(1, 0)); + RR(VID_FIR_COEF_V(1, 1)); + RR(VID_FIR_COEF_V(1, 2)); + RR(VID_FIR_COEF_V(1, 3)); + RR(VID_FIR_COEF_V(1, 4)); + RR(VID_FIR_COEF_V(1, 5)); + RR(VID_FIR_COEF_V(1, 6)); + RR(VID_FIR_COEF_V(1, 7)); + + RR(VID_PRELOAD(1)); + + /* enable last, because LCD & DIGIT enable are here */ + RR(CONTROL); +} + +#undef SR +#undef RR + +static inline void enable_clocks(bool enable) +{ + if (enable) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); +} + +bool dispc_go_busy(enum omap_channel channel) +{ + int bit; + + if (channel == OMAP_DSS_CHANNEL_LCD) + bit = 5; /* GOLCD */ + else + bit = 6; /* GODIGIT */ + + return REG_GET(DISPC_CONTROL, bit, bit) == 1; +} + +void dispc_go(enum omap_channel channel) +{ + int bit; + + enable_clocks(1); + + if (channel == OMAP_DSS_CHANNEL_LCD) + bit = 0; /* LCDENABLE */ + else + bit = 1; /* DIGITALENABLE */ + + /* if the channel is not enabled, we don't need GO */ + if (REG_GET(DISPC_CONTROL, bit, bit) == 0) + goto end; + + if (channel == OMAP_DSS_CHANNEL_LCD) + bit = 5; /* GOLCD */ + else + bit = 6; /* GODIGIT */ + + if (REG_GET(DISPC_CONTROL, bit, bit) == 1) { + DSSERR("GO bit not down for channel %d\n", channel); + goto end; + } + + DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT"); + + REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); +end: + enable_clocks(0); +} + +static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) +{ + BUG_ON(plane == OMAP_DSS_GFX); + + dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value); +} + +static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) +{ + BUG_ON(plane == OMAP_DSS_GFX); + + dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value); +} + +static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value) +{ + BUG_ON(plane == OMAP_DSS_GFX); + + dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value); +} + +static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, + int vscaleup, int five_taps) +{ + /* Coefficients for horizontal up-sampling */ + static const u32 coef_hup[8] = { + 0x00800000, + 0x0D7CF800, + 0x1E70F5FF, + 0x335FF5FE, + 0xF74949F7, + 0xF55F33FB, + 0xF5701EFE, + 0xF87C0DFF, + }; + + /* Coefficients for horizontal down-sampling */ + static const u32 coef_hdown[8] = { + 0x24382400, + 0x28371FFE, + 0x2C361BFB, + 0x303516F9, + 0x11343311, + 0x1635300C, + 0x1B362C08, + 0x1F372804, + }; + + /* Coefficients for horizontal and vertical up-sampling */ + static const u32 coef_hvup[2][8] = { + { + 0x00800000, + 0x037B02FF, + 0x0C6F05FE, + 0x205907FB, + 0x00404000, + 0x075920FE, + 0x056F0CFF, + 0x027B0300, + }, + { + 0x00800000, + 0x0D7CF8FF, + 0x1E70F5FE, + 0x335FF5FB, + 0xF7404000, + 0xF55F33FE, + 0xF5701EFF, + 0xF87C0D00, + }, + }; + + /* Coefficients for horizontal and vertical down-sampling */ + static const u32 coef_hvdown[2][8] = { + { + 0x24382400, + 0x28391F04, + 0x2D381B08, + 0x3237170C, + 0x123737F7, + 0x173732F9, + 0x1B382DFB, + 0x1F3928FE, + }, + { + 0x24382400, + 0x28371F04, + 0x2C361B08, + 0x3035160C, + 0x113433F7, + 0x163530F9, + 0x1B362CFB, + 0x1F3728FE, + }, + }; + + /* Coefficients for vertical up-sampling */ + static const u32 coef_vup[8] = { + 0x00000000, + 0x0000FF00, + 0x0000FEFF, + 0x0000FBFE, + 0x000000F7, + 0x0000FEFB, + 0x0000FFFE, + 0x000000FF, + }; + + + /* Coefficients for vertical down-sampling */ + static const u32 coef_vdown[8] = { + 0x00000000, + 0x000004FE, + 0x000008FB, + 0x00000CF9, + 0x0000F711, + 0x0000F90C, + 0x0000FB08, + 0x0000FE04, + }; + + const u32 *h_coef; + const u32 *hv_coef; + const u32 *hv_coef_mod; + const u32 *v_coef; + int i; + + if (hscaleup) + h_coef = coef_hup; + else + h_coef = coef_hdown; + + if (vscaleup) { + hv_coef = coef_hvup[five_taps]; + v_coef = coef_vup; + + if (hscaleup) + hv_coef_mod = NULL; + else + hv_coef_mod = coef_hvdown[five_taps]; + } else { + hv_coef = coef_hvdown[five_taps]; + v_coef = coef_vdown; + + if (hscaleup) + hv_coef_mod = coef_hvup[five_taps]; + else + hv_coef_mod = NULL; + } + + for (i = 0; i < 8; i++) { + u32 h, hv; + + h = h_coef[i]; + + hv = hv_coef[i]; + + if (hv_coef_mod) { + hv &= 0xffffff00; + hv |= (hv_coef_mod[i] & 0xff); + } + + _dispc_write_firh_reg(plane, i, h); + _dispc_write_firhv_reg(plane, i, hv); + } + + if (!five_taps) + return; + + for (i = 0; i < 8; i++) { + u32 v; + v = v_coef[i]; + _dispc_write_firv_reg(plane, i, v); + } +} + +static void _dispc_setup_color_conv_coef(void) +{ + const struct color_conv_coef { + int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; + int full_range; + } ctbl_bt601_5 = { + 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, + }; + + const struct color_conv_coef *ct; + +#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) + + ct = &ctbl_bt601_5; + + dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry)); + dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb)); + dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr)); + dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by)); + dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb)); + + dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry)); + dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb)); + dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr)); + dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by)); + dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb)); + +#undef CVAL + + REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11); + REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11); +} + + +static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) +{ + const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0, + DISPC_VID_BA0(0), + DISPC_VID_BA0(1) }; + + dispc_write_reg(ba0_reg[plane], paddr); +} + +static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) +{ + const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1, + DISPC_VID_BA1(0), + DISPC_VID_BA1(1) }; + + dispc_write_reg(ba1_reg[plane], paddr); +} + +static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) +{ + const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION, + DISPC_VID_POSITION(0), + DISPC_VID_POSITION(1) }; + + u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); + dispc_write_reg(pos_reg[plane], val); +} + +static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) +{ + const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE, + DISPC_VID_PICTURE_SIZE(0), + DISPC_VID_PICTURE_SIZE(1) }; + u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); + dispc_write_reg(siz_reg[plane], val); +} + +static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) +{ + u32 val; + const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0), + DISPC_VID_SIZE(1) }; + + BUG_ON(plane == OMAP_DSS_GFX); + + val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); + dispc_write_reg(vsi_reg[plane-1], val); +} + +static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) +{ + + BUG_ON(plane == OMAP_DSS_VIDEO1); + + if (cpu_is_omap24xx()) + return; + + if (plane == OMAP_DSS_GFX) + REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0); + else if (plane == OMAP_DSS_VIDEO2) + REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16); +} + +static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc) +{ + const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC, + DISPC_VID_PIXEL_INC(0), + DISPC_VID_PIXEL_INC(1) }; + + dispc_write_reg(ri_reg[plane], inc); +} + +static void _dispc_set_row_inc(enum omap_plane plane, s32 inc) +{ + const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC, + DISPC_VID_ROW_INC(0), + DISPC_VID_ROW_INC(1) }; + + dispc_write_reg(ri_reg[plane], inc); +} + +static void _dispc_set_color_mode(enum omap_plane plane, + enum omap_color_mode color_mode) +{ + u32 m = 0; + + switch (color_mode) { + case OMAP_DSS_COLOR_CLUT1: + m = 0x0; break; + case OMAP_DSS_COLOR_CLUT2: + m = 0x1; break; + case OMAP_DSS_COLOR_CLUT4: + m = 0x2; break; + case OMAP_DSS_COLOR_CLUT8: + m = 0x3; break; + case OMAP_DSS_COLOR_RGB12U: + m = 0x4; break; + case OMAP_DSS_COLOR_ARGB16: + m = 0x5; break; + case OMAP_DSS_COLOR_RGB16: + m = 0x6; break; + case OMAP_DSS_COLOR_RGB24U: + m = 0x8; break; + case OMAP_DSS_COLOR_RGB24P: + m = 0x9; break; + case OMAP_DSS_COLOR_YUV2: + m = 0xa; break; + case OMAP_DSS_COLOR_UYVY: + m = 0xb; break; + case OMAP_DSS_COLOR_ARGB32: + m = 0xc; break; + case OMAP_DSS_COLOR_RGBA32: + m = 0xd; break; + case OMAP_DSS_COLOR_RGBX32: + m = 0xe; break; + default: + BUG(); break; + } + + REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1); +} + +static void _dispc_set_channel_out(enum omap_plane plane, + enum omap_channel channel) +{ + int shift; + u32 val; + + switch (plane) { + case OMAP_DSS_GFX: + shift = 8; + break; + case OMAP_DSS_VIDEO1: + case OMAP_DSS_VIDEO2: + shift = 16; + break; + default: + BUG(); + return; + } + + val = dispc_read_reg(dispc_reg_att[plane]); + val = FLD_MOD(val, channel, shift, shift); + dispc_write_reg(dispc_reg_att[plane], val); +} + +void dispc_set_burst_size(enum omap_plane plane, + enum omap_burst_size burst_size) +{ + int shift; + u32 val; + + enable_clocks(1); + + switch (plane) { + case OMAP_DSS_GFX: + shift = 6; + break; + case OMAP_DSS_VIDEO1: + case OMAP_DSS_VIDEO2: + shift = 14; + break; + default: + BUG(); + return; + } + + val = dispc_read_reg(dispc_reg_att[plane]); + val = FLD_MOD(val, burst_size, shift+1, shift); + dispc_write_reg(dispc_reg_att[plane], val); + + enable_clocks(0); +} + +static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) +{ + u32 val; + + BUG_ON(plane == OMAP_DSS_GFX); + + val = dispc_read_reg(dispc_reg_att[plane]); + val = FLD_MOD(val, enable, 9, 9); + dispc_write_reg(dispc_reg_att[plane], val); +} + +void dispc_enable_replication(enum omap_plane plane, bool enable) +{ + int bit; + + if (plane == OMAP_DSS_GFX) + bit = 5; + else + bit = 10; + + enable_clocks(1); + REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit); + enable_clocks(0); +} + +void dispc_set_lcd_size(u16 width, u16 height) +{ + u32 val; + BUG_ON((width > (1 << 11)) || (height > (1 << 11))); + val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); + enable_clocks(1); + dispc_write_reg(DISPC_SIZE_LCD, val); + enable_clocks(0); +} + +void dispc_set_digit_size(u16 width, u16 height) +{ + u32 val; + BUG_ON((width > (1 << 11)) || (height > (1 << 11))); + val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); + enable_clocks(1); + dispc_write_reg(DISPC_SIZE_DIG, val); + enable_clocks(0); +} + +static void dispc_read_plane_fifo_sizes(void) +{ + const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS, + DISPC_VID_FIFO_SIZE_STATUS(0), + DISPC_VID_FIFO_SIZE_STATUS(1) }; + u32 size; + int plane; + + enable_clocks(1); + + for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { + if (cpu_is_omap24xx()) + size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0); + else if (cpu_is_omap34xx()) + size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0); + else + BUG(); + + dispc.fifo_size[plane] = size; + } + + enable_clocks(0); +} + +u32 dispc_get_plane_fifo_size(enum omap_plane plane) +{ + return dispc.fifo_size[plane]; +} + +void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) +{ + const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD, + DISPC_VID_FIFO_THRESHOLD(0), + DISPC_VID_FIFO_THRESHOLD(1) }; + enable_clocks(1); + + DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", + plane, + REG_GET(ftrs_reg[plane], 11, 0), + REG_GET(ftrs_reg[plane], 27, 16), + low, high); + + if (cpu_is_omap24xx()) + dispc_write_reg(ftrs_reg[plane], + FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0)); + else + dispc_write_reg(ftrs_reg[plane], + FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0)); + + enable_clocks(0); +} + +void dispc_enable_fifomerge(bool enable) +{ + enable_clocks(1); + + DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled"); + REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); + + enable_clocks(0); +} + +static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc) +{ + u32 val; + const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0), + DISPC_VID_FIR(1) }; + + BUG_ON(plane == OMAP_DSS_GFX); + + if (cpu_is_omap24xx()) + val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0); + else + val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0); + dispc_write_reg(fir_reg[plane-1], val); +} + +static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) +{ + u32 val; + const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0), + DISPC_VID_ACCU0(1) }; + + BUG_ON(plane == OMAP_DSS_GFX); + + val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); + dispc_write_reg(ac0_reg[plane-1], val); +} + +static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) +{ + u32 val; + const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0), + DISPC_VID_ACCU1(1) }; + + BUG_ON(plane == OMAP_DSS_GFX); + + val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); + dispc_write_reg(ac1_reg[plane-1], val); +} + + +static void _dispc_set_scaling(enum omap_plane plane, + u16 orig_width, u16 orig_height, + u16 out_width, u16 out_height, + bool ilace, bool five_taps, + bool fieldmode) +{ + int fir_hinc; + int fir_vinc; + int hscaleup, vscaleup; + int accu0 = 0; + int accu1 = 0; + u32 l; + + BUG_ON(plane == OMAP_DSS_GFX); + + hscaleup = orig_width <= out_width; + vscaleup = orig_height <= out_height; + + _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps); + + if (!orig_width || orig_width == out_width) + fir_hinc = 0; + else + fir_hinc = 1024 * orig_width / out_width; + + if (!orig_height || orig_height == out_height) + fir_vinc = 0; + else + fir_vinc = 1024 * orig_height / out_height; + + _dispc_set_fir(plane, fir_hinc, fir_vinc); + + l = dispc_read_reg(dispc_reg_att[plane]); + l &= ~((0x0f << 5) | (0x3 << 21)); + + l |= fir_hinc ? (1 << 5) : 0; + l |= fir_vinc ? (1 << 6) : 0; + + l |= hscaleup ? 0 : (1 << 7); + l |= vscaleup ? 0 : (1 << 8); + + l |= five_taps ? (1 << 21) : 0; + l |= five_taps ? (1 << 22) : 0; + + dispc_write_reg(dispc_reg_att[plane], l); + + /* + * field 0 = even field = bottom field + * field 1 = odd field = top field + */ + if (ilace && !fieldmode) { + accu1 = 0; + accu0 = (fir_vinc / 2) & 0x3ff; + if (accu0 >= 1024/2) { + accu1 = 1024/2; + accu0 -= accu1; + } + } + + _dispc_set_vid_accu0(plane, 0, accu0); + _dispc_set_vid_accu1(plane, 0, accu1); +} + +static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, + bool mirroring, enum omap_color_mode color_mode) +{ + if (color_mode == OMAP_DSS_COLOR_YUV2 || + color_mode == OMAP_DSS_COLOR_UYVY) { + int vidrot = 0; + + if (mirroring) { + switch (rotation) { + case OMAP_DSS_ROT_0: + vidrot = 2; + break; + case OMAP_DSS_ROT_90: + vidrot = 1; + break; + case OMAP_DSS_ROT_180: + vidrot = 0; + break; + case OMAP_DSS_ROT_270: + vidrot = 3; + break; + } + } else { + switch (rotation) { + case OMAP_DSS_ROT_0: + vidrot = 0; + break; + case OMAP_DSS_ROT_90: + vidrot = 1; + break; + case OMAP_DSS_ROT_180: + vidrot = 2; + break; + case OMAP_DSS_ROT_270: + vidrot = 3; + break; + } + } + + REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12); + + if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270) + REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18); + else + REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18); + } else { + REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12); + REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18); + } +} + +static int color_mode_to_bpp(enum omap_color_mode color_mode) +{ + switch (color_mode) { + case OMAP_DSS_COLOR_CLUT1: + return 1; + case OMAP_DSS_COLOR_CLUT2: + return 2; + case OMAP_DSS_COLOR_CLUT4: + return 4; + case OMAP_DSS_COLOR_CLUT8: + return 8; + case OMAP_DSS_COLOR_RGB12U: + case OMAP_DSS_COLOR_RGB16: + case OMAP_DSS_COLOR_ARGB16: + case OMAP_DSS_COLOR_YUV2: + case OMAP_DSS_COLOR_UYVY: + return 16; + case OMAP_DSS_COLOR_RGB24P: + return 24; + case OMAP_DSS_COLOR_RGB24U: + case OMAP_DSS_COLOR_ARGB32: + case OMAP_DSS_COLOR_RGBA32: + case OMAP_DSS_COLOR_RGBX32: + return 32; + default: + BUG(); + } +} + +static s32 pixinc(int pixels, u8 ps) +{ + if (pixels == 1) + return 1; + else if (pixels > 1) + return 1 + (pixels - 1) * ps; + else if (pixels < 0) + return 1 - (-pixels + 1) * ps; + else + BUG(); +} + +static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, + u16 screen_width, + u16 width, u16 height, + enum omap_color_mode color_mode, bool fieldmode, + unsigned int field_offset, + unsigned *offset0, unsigned *offset1, + s32 *row_inc, s32 *pix_inc) +{ + u8 ps; + + /* FIXME CLUT formats */ + switch (color_mode) { + case OMAP_DSS_COLOR_CLUT1: + case OMAP_DSS_COLOR_CLUT2: + case OMAP_DSS_COLOR_CLUT4: + case OMAP_DSS_COLOR_CLUT8: + BUG(); + return; + case OMAP_DSS_COLOR_YUV2: + case OMAP_DSS_COLOR_UYVY: + ps = 4; + break; + default: + ps = color_mode_to_bpp(color_mode) / 8; + break; + } + + DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width, + width, height); + + /* + * field 0 = even field = bottom field + * field 1 = odd field = top field + */ + switch (rotation + mirror * 4) { + case OMAP_DSS_ROT_0: + case OMAP_DSS_ROT_180: + /* + * If the pixel format is YUV or UYVY divide the width + * of the image by 2 for 0 and 180 degree rotation. + */ + if (color_mode == OMAP_DSS_COLOR_YUV2 || + color_mode == OMAP_DSS_COLOR_UYVY) + width = width >> 1; + case OMAP_DSS_ROT_90: + case OMAP_DSS_ROT_270: + *offset1 = 0; + if (field_offset) + *offset0 = field_offset * screen_width * ps; + else + *offset0 = 0; + + *row_inc = pixinc(1 + (screen_width - width) + + (fieldmode ? screen_width : 0), + ps); + *pix_inc = pixinc(1, ps); + break; + + case OMAP_DSS_ROT_0 + 4: + case OMAP_DSS_ROT_180 + 4: + /* If the pixel format is YUV or UYVY divide the width + * of the image by 2 for 0 degree and 180 degree + */ + if (color_mode == OMAP_DSS_COLOR_YUV2 || + color_mode == OMAP_DSS_COLOR_UYVY) + width = width >> 1; + case OMAP_DSS_ROT_90 + 4: + case OMAP_DSS_ROT_270 + 4: + *offset1 = 0; + if (field_offset) + *offset0 = field_offset * screen_width * ps; + else + *offset0 = 0; + *row_inc = pixinc(1 - (screen_width + width) - + (fieldmode ? screen_width : 0), + ps); + *pix_inc = pixinc(1, ps); + break; + + default: + BUG(); + } +} + +static void calc_dma_rotation_offset(u8 rotation, bool mirror, + u16 screen_width, + u16 width, u16 height, + enum omap_color_mode color_mode, bool fieldmode, + unsigned int field_offset, + unsigned *offset0, unsigned *offset1, + s32 *row_inc, s32 *pix_inc) +{ + u8 ps; + u16 fbw, fbh; + + /* FIXME CLUT formats */ + switch (color_mode) { + case OMAP_DSS_COLOR_CLUT1: + case OMAP_DSS_COLOR_CLUT2: + case OMAP_DSS_COLOR_CLUT4: + case OMAP_DSS_COLOR_CLUT8: + BUG(); + return; + default: + ps = color_mode_to_bpp(color_mode) / 8; + break; + } + + DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width, + width, height); + + /* width & height are overlay sizes, convert to fb sizes */ + + if (rotation == OMAP_DSS_ROT_0 || rotation == OMAP_DSS_ROT_180) { + fbw = width; + fbh = height; + } else { + fbw = height; + fbh = width; + } + + /* + * field 0 = even field = bottom field + * field 1 = odd field = top field + */ + switch (rotation + mirror * 4) { + case OMAP_DSS_ROT_0: + *offset1 = 0; + if (field_offset) + *offset0 = *offset1 + field_offset * screen_width * ps; + else + *offset0 = *offset1; + *row_inc = pixinc(1 + (screen_width - fbw) + + (fieldmode ? screen_width : 0), + ps); + *pix_inc = pixinc(1, ps); + break; + case OMAP_DSS_ROT_90: + *offset1 = screen_width * (fbh - 1) * ps; + if (field_offset) + *offset0 = *offset1 + field_offset * ps; + else + *offset0 = *offset1; + *row_inc = pixinc(screen_width * (fbh - 1) + 1 + + (fieldmode ? 1 : 0), ps); + *pix_inc = pixinc(-screen_width, ps); + break; + case OMAP_DSS_ROT_180: + *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; + if (field_offset) + *offset0 = *offset1 - field_offset * screen_width * ps; + else + *offset0 = *offset1; + *row_inc = pixinc(-1 - + (screen_width - fbw) - + (fieldmode ? screen_width : 0), + ps); + *pix_inc = pixinc(-1, ps); + break; + case OMAP_DSS_ROT_270: + *offset1 = (fbw - 1) * ps; + if (field_offset) + *offset0 = *offset1 - field_offset * ps; + else + *offset0 = *offset1; + *row_inc = pixinc(-screen_width * (fbh - 1) - 1 - + (fieldmode ? 1 : 0), ps); + *pix_inc = pixinc(screen_width, ps); + break; + + /* mirroring */ + case OMAP_DSS_ROT_0 + 4: + *offset1 = (fbw - 1) * ps; + if (field_offset) + *offset0 = *offset1 + field_offset * screen_width * ps; + else + *offset0 = *offset1; + *row_inc = pixinc(screen_width * 2 - 1 + + (fieldmode ? screen_width : 0), + ps); + *pix_inc = pixinc(-1, ps); + break; + + case OMAP_DSS_ROT_90 + 4: + *offset1 = 0; + if (field_offset) + *offset0 = *offset1 + field_offset * ps; + else + *offset0 = *offset1; + *row_inc = pixinc(-screen_width * (fbh - 1) + 1 + + (fieldmode ? 1 : 0), + ps); + *pix_inc = pixinc(screen_width, ps); + break; + + case OMAP_DSS_ROT_180 + 4: + *offset1 = screen_width * (fbh - 1) * ps; + if (field_offset) + *offset0 = *offset1 - field_offset * screen_width * ps; + else + *offset0 = *offset1; + *row_inc = pixinc(1 - screen_width * 2 - + (fieldmode ? screen_width : 0), + ps); + *pix_inc = pixinc(1, ps); + break; + + case OMAP_DSS_ROT_270 + 4: + *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; + if (field_offset) + *offset0 = *offset1 - field_offset * ps; + else + *offset0 = *offset1; + *row_inc = pixinc(screen_width * (fbh - 1) - 1 - + (fieldmode ? 1 : 0), + ps); + *pix_inc = pixinc(-screen_width, ps); + break; + + default: + BUG(); + } +} + +static unsigned long calc_fclk_five_taps(u16 width, u16 height, + u16 out_width, u16 out_height, enum omap_color_mode color_mode) +{ + u32 fclk = 0; + /* FIXME venc pclk? */ + u64 tmp, pclk = dispc_pclk_rate(); + + if (height > out_height) { + /* FIXME get real display PPL */ + unsigned int ppl = 800; + + tmp = pclk * height * out_width; + do_div(tmp, 2 * out_height * ppl); + fclk = tmp; + + if (height > 2 * out_height && ppl != out_width) { + tmp = pclk * (height - 2 * out_height) * out_width; + do_div(tmp, 2 * out_height * (ppl - out_width)); + fclk = max(fclk, (u32) tmp); + } + } + + if (width > out_width) { + tmp = pclk * width; + do_div(tmp, out_width); + fclk = max(fclk, (u32) tmp); + + if (color_mode == OMAP_DSS_COLOR_RGB24U) + fclk <<= 1; + } + + return fclk; +} + +static unsigned long calc_fclk(u16 width, u16 height, + u16 out_width, u16 out_height) +{ + unsigned int hf, vf; + + /* + * FIXME how to determine the 'A' factor + * for the no downscaling case ? + */ + + if (width > 3 * out_width) + hf = 4; + else if (width > 2 * out_width) + hf = 3; + else if (width > out_width) + hf = 2; + else + hf = 1; + + if (height > out_height) + vf = 2; + else + vf = 1; + + /* FIXME venc pclk? */ + return dispc_pclk_rate() * vf * hf; +} + +void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out) +{ + enable_clocks(1); + _dispc_set_channel_out(plane, channel_out); + enable_clocks(0); +} + +static int _dispc_setup_plane(enum omap_plane plane, + u32 paddr, u16 screen_width, + u16 pos_x, u16 pos_y, + u16 width, u16 height, + u16 out_width, u16 out_height, + enum omap_color_mode color_mode, + bool ilace, + enum omap_dss_rotation_type rotation_type, + u8 rotation, int mirror, + u8 global_alpha) +{ + const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; + bool five_taps = 0; + bool fieldmode = 0; + int cconv = 0; + unsigned offset0, offset1; + s32 row_inc; + s32 pix_inc; + u16 frame_height = height; + unsigned int field_offset = 0; + + if (paddr == 0) + return -EINVAL; + + if (ilace && height == out_height) + fieldmode = 1; + + if (ilace) { + if (fieldmode) + height /= 2; + pos_y /= 2; + out_height /= 2; + + DSSDBG("adjusting for ilace: height %d, pos_y %d, " + "out_height %d\n", + height, pos_y, out_height); + } + + if (plane == OMAP_DSS_GFX) { + if (width != out_width || height != out_height) + return -EINVAL; + + switch (color_mode) { + case OMAP_DSS_COLOR_ARGB16: + case OMAP_DSS_COLOR_ARGB32: + case OMAP_DSS_COLOR_RGBA32: + case OMAP_DSS_COLOR_RGBX32: + if (cpu_is_omap24xx()) + return -EINVAL; + /* fall through */ + case OMAP_DSS_COLOR_RGB12U: + case OMAP_DSS_COLOR_RGB16: + case OMAP_DSS_COLOR_RGB24P: + case OMAP_DSS_COLOR_RGB24U: + break; + + default: + return -EINVAL; + } + } else { + /* video plane */ + + unsigned long fclk = 0; + + if (out_width < width / maxdownscale || + out_width > width * 8) + return -EINVAL; + + if (out_height < height / maxdownscale || + out_height > height * 8) + return -EINVAL; + + switch (color_mode) { + case OMAP_DSS_COLOR_RGBX32: + case OMAP_DSS_COLOR_RGB12U: + if (cpu_is_omap24xx()) + return -EINVAL; + /* fall through */ + case OMAP_DSS_COLOR_RGB16: + case OMAP_DSS_COLOR_RGB24P: + case OMAP_DSS_COLOR_RGB24U: + break; + + case OMAP_DSS_COLOR_ARGB16: + case OMAP_DSS_COLOR_ARGB32: + case OMAP_DSS_COLOR_RGBA32: + if (cpu_is_omap24xx()) + return -EINVAL; + if (plane == OMAP_DSS_VIDEO1) + return -EINVAL; + break; + + case OMAP_DSS_COLOR_YUV2: + case OMAP_DSS_COLOR_UYVY: + cconv = 1; + break; + + default: + return -EINVAL; + } + + /* Must use 5-tap filter? */ + five_taps = height > out_height * 2; + + if (!five_taps) { + fclk = calc_fclk(width, height, + out_width, out_height); + + /* Try 5-tap filter if 3-tap fclk is too high */ + if (cpu_is_omap34xx() && height > out_height && + fclk > dispc_fclk_rate()) + five_taps = true; + } + + if (width > (2048 >> five_taps)) { + DSSERR("failed to set up scaling, fclk too low\n"); + return -EINVAL; + } + + if (five_taps) + fclk = calc_fclk_five_taps(width, height, + out_width, out_height, color_mode); + + DSSDBG("required fclk rate = %lu Hz\n", fclk); + DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); + + if (fclk > dispc_fclk_rate()) { + DSSERR("failed to set up scaling, " + "required fclk rate = %lu Hz, " + "current fclk rate = %lu Hz\n", + fclk, dispc_fclk_rate()); + return -EINVAL; + } + } + + if (ilace && !fieldmode) { + /* + * when downscaling the bottom field may have to start several + * source lines below the top field. Unfortunately ACCUI + * registers will only hold the fractional part of the offset + * so the integer part must be added to the base address of the + * bottom field. + */ + if (!height || height == out_height) + field_offset = 0; + else + field_offset = height / out_height / 2; + } + + /* Fields are independent but interleaved in memory. */ + if (fieldmode) + field_offset = 1; + + if (rotation_type == OMAP_DSS_ROT_DMA) + calc_dma_rotation_offset(rotation, mirror, + screen_width, width, frame_height, color_mode, + fieldmode, field_offset, + &offset0, &offset1, &row_inc, &pix_inc); + else + calc_vrfb_rotation_offset(rotation, mirror, + screen_width, width, frame_height, color_mode, + fieldmode, field_offset, + &offset0, &offset1, &row_inc, &pix_inc); + + DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", + offset0, offset1, row_inc, pix_inc); + + _dispc_set_color_mode(plane, color_mode); + + _dispc_set_plane_ba0(plane, paddr + offset0); + _dispc_set_plane_ba1(plane, paddr + offset1); + + _dispc_set_row_inc(plane, row_inc); + _dispc_set_pix_inc(plane, pix_inc); + + DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height, + out_width, out_height); + + _dispc_set_plane_pos(plane, pos_x, pos_y); + + _dispc_set_pic_size(plane, width, height); + + if (plane != OMAP_DSS_GFX) { + _dispc_set_scaling(plane, width, height, + out_width, out_height, + ilace, five_taps, fieldmode); + _dispc_set_vid_size(plane, out_width, out_height); + _dispc_set_vid_color_conv(plane, cconv); + } + + _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode); + + if (plane != OMAP_DSS_VIDEO1) + _dispc_setup_global_alpha(plane, global_alpha); + + return 0; +} + +static void _dispc_enable_plane(enum omap_plane plane, bool enable) +{ + REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0); +} + +static void dispc_disable_isr(void *data, u32 mask) +{ + struct completion *compl = data; + complete(compl); +} + +static void _enable_lcd_out(bool enable) +{ + REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); +} + +void dispc_enable_lcd_out(bool enable) +{ + struct completion frame_done_completion; + bool is_on; + int r; + + enable_clocks(1); + + /* When we disable LCD output, we need to wait until frame is done. + * Otherwise the DSS is still working, and turning off the clocks + * prevents DSS from going to OFF mode */ + is_on = REG_GET(DISPC_CONTROL, 0, 0); + + if (!enable && is_on) { + init_completion(&frame_done_completion); + + r = omap_dispc_register_isr(dispc_disable_isr, + &frame_done_completion, + DISPC_IRQ_FRAMEDONE); + + if (r) + DSSERR("failed to register FRAMEDONE isr\n"); + } + + _enable_lcd_out(enable); + + if (!enable && is_on) { + if (!wait_for_completion_timeout(&frame_done_completion, + msecs_to_jiffies(100))) + DSSERR("timeout waiting for FRAME DONE\n"); + + r = omap_dispc_unregister_isr(dispc_disable_isr, + &frame_done_completion, + DISPC_IRQ_FRAMEDONE); + + if (r) + DSSERR("failed to unregister FRAMEDONE isr\n"); + } + + enable_clocks(0); +} + +static void _enable_digit_out(bool enable) +{ + REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1); +} + +void dispc_enable_digit_out(bool enable) +{ + struct completion frame_done_completion; + int r; + + enable_clocks(1); + + if (REG_GET(DISPC_CONTROL, 1, 1) == enable) { + enable_clocks(0); + return; + } + + if (enable) { + unsigned long flags; + /* When we enable digit output, we'll get an extra digit + * sync lost interrupt, that we need to ignore */ + spin_lock_irqsave(&dispc.irq_lock, flags); + dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT; + _omap_dispc_set_irqs(); + spin_unlock_irqrestore(&dispc.irq_lock, flags); + } + + /* When we disable digit output, we need to wait until fields are done. + * Otherwise the DSS is still working, and turning off the clocks + * prevents DSS from going to OFF mode. And when enabling, we need to + * wait for the extra sync losts */ + init_completion(&frame_done_completion); + + r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion, + DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); + if (r) + DSSERR("failed to register EVSYNC isr\n"); + + _enable_digit_out(enable); + + /* XXX I understand from TRM that we should only wait for the + * current field to complete. But it seems we have to wait + * for both fields */ + if (!wait_for_completion_timeout(&frame_done_completion, + msecs_to_jiffies(100))) + DSSERR("timeout waiting for EVSYNC\n"); + + if (!wait_for_completion_timeout(&frame_done_completion, + msecs_to_jiffies(100))) + DSSERR("timeout waiting for EVSYNC\n"); + + r = omap_dispc_unregister_isr(dispc_disable_isr, + &frame_done_completion, + DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); + if (r) + DSSERR("failed to unregister EVSYNC isr\n"); + + if (enable) { + unsigned long flags; + spin_lock_irqsave(&dispc.irq_lock, flags); + dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; + dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); + _omap_dispc_set_irqs(); + spin_unlock_irqrestore(&dispc.irq_lock, flags); + } + + enable_clocks(0); +} + +void dispc_lcd_enable_signal_polarity(bool act_high) +{ + enable_clocks(1); + REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); + enable_clocks(0); +} + +void dispc_lcd_enable_signal(bool enable) +{ + enable_clocks(1); + REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); + enable_clocks(0); +} + +void dispc_pck_free_enable(bool enable) +{ + enable_clocks(1); + REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); + enable_clocks(0); +} + +void dispc_enable_fifohandcheck(bool enable) +{ + enable_clocks(1); + REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16); + enable_clocks(0); +} + + +void dispc_set_lcd_display_type(enum omap_lcd_display_type type) +{ + int mode; + + switch (type) { + case OMAP_DSS_LCD_DISPLAY_STN: + mode = 0; + break; + + case OMAP_DSS_LCD_DISPLAY_TFT: + mode = 1; + break; + + default: + BUG(); + return; + } + + enable_clocks(1); + REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3); + enable_clocks(0); +} + +void dispc_set_loadmode(enum omap_dss_load_mode mode) +{ + enable_clocks(1); + REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1); + enable_clocks(0); +} + + +void dispc_set_default_color(enum omap_channel channel, u32 color) +{ + const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0, + DISPC_DEFAULT_COLOR1 }; + + enable_clocks(1); + dispc_write_reg(def_reg[channel], color); + enable_clocks(0); +} + +u32 dispc_get_default_color(enum omap_channel channel) +{ + const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0, + DISPC_DEFAULT_COLOR1 }; + u32 l; + + BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT && + channel != OMAP_DSS_CHANNEL_LCD); + + enable_clocks(1); + l = dispc_read_reg(def_reg[channel]); + enable_clocks(0); + + return l; +} + +void dispc_set_trans_key(enum omap_channel ch, + enum omap_dss_trans_key_type type, + u32 trans_key) +{ + const struct dispc_reg tr_reg[] = { + DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 }; + + enable_clocks(1); + if (ch == OMAP_DSS_CHANNEL_LCD) + REG_FLD_MOD(DISPC_CONFIG, type, 11, 11); + else /* OMAP_DSS_CHANNEL_DIGIT */ + REG_FLD_MOD(DISPC_CONFIG, type, 13, 13); + + dispc_write_reg(tr_reg[ch], trans_key); + enable_clocks(0); +} + +void dispc_get_trans_key(enum omap_channel ch, + enum omap_dss_trans_key_type *type, + u32 *trans_key) +{ + const struct dispc_reg tr_reg[] = { + DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 }; + + enable_clocks(1); + if (type) { + if (ch == OMAP_DSS_CHANNEL_LCD) + *type = REG_GET(DISPC_CONFIG, 11, 11); + else if (ch == OMAP_DSS_CHANNEL_DIGIT) + *type = REG_GET(DISPC_CONFIG, 13, 13); + else + BUG(); + } + + if (trans_key) + *trans_key = dispc_read_reg(tr_reg[ch]); + enable_clocks(0); +} + +void dispc_enable_trans_key(enum omap_channel ch, bool enable) +{ + enable_clocks(1); + if (ch == OMAP_DSS_CHANNEL_LCD) + REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); + else /* OMAP_DSS_CHANNEL_DIGIT */ + REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12); + enable_clocks(0); +} +void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) +{ + if (cpu_is_omap24xx()) + return; + + enable_clocks(1); + if (ch == OMAP_DSS_CHANNEL_LCD) + REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); + else /* OMAP_DSS_CHANNEL_DIGIT */ + REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); + enable_clocks(0); +} +bool dispc_alpha_blending_enabled(enum omap_channel ch) +{ + bool enabled; + + if (cpu_is_omap24xx()) + return false; + + enable_clocks(1); + if (ch == OMAP_DSS_CHANNEL_LCD) + enabled = REG_GET(DISPC_CONFIG, 18, 18); + else if (ch == OMAP_DSS_CHANNEL_DIGIT) + enabled = REG_GET(DISPC_CONFIG, 18, 18); + else + BUG(); + enable_clocks(0); + + return enabled; + +} + + +bool dispc_trans_key_enabled(enum omap_channel ch) +{ + bool enabled; + + enable_clocks(1); + if (ch == OMAP_DSS_CHANNEL_LCD) + enabled = REG_GET(DISPC_CONFIG, 10, 10); + else if (ch == OMAP_DSS_CHANNEL_DIGIT) + enabled = REG_GET(DISPC_CONFIG, 12, 12); + else + BUG(); + enable_clocks(0); + + return enabled; +} + + +void dispc_set_tft_data_lines(u8 data_lines) +{ + int code; + + switch (data_lines) { + case 12: + code = 0; + break; + case 16: + code = 1; + break; + case 18: + code = 2; + break; + case 24: + code = 3; + break; + default: + BUG(); + return; + } + + enable_clocks(1); + REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); + enable_clocks(0); +} + +void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode) +{ + u32 l; + int stallmode; + int gpout0 = 1; + int gpout1; + + switch (mode) { + case OMAP_DSS_PARALLELMODE_BYPASS: + stallmode = 0; + gpout1 = 1; + break; + + case OMAP_DSS_PARALLELMODE_RFBI: + stallmode = 1; + gpout1 = 0; + break; + + case OMAP_DSS_PARALLELMODE_DSI: + stallmode = 1; + gpout1 = 1; + break; + + default: + BUG(); + return; + } + + enable_clocks(1); + + l = dispc_read_reg(DISPC_CONTROL); + + l = FLD_MOD(l, stallmode, 11, 11); + l = FLD_MOD(l, gpout0, 15, 15); + l = FLD_MOD(l, gpout1, 16, 16); + + dispc_write_reg(DISPC_CONTROL, l); + + enable_clocks(0); +} + +static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, + int vsw, int vfp, int vbp) +{ + if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { + if (hsw < 1 || hsw > 64 || + hfp < 1 || hfp > 256 || + hbp < 1 || hbp > 256 || + vsw < 1 || vsw > 64 || + vfp < 0 || vfp > 255 || + vbp < 0 || vbp > 255) + return false; + } else { + if (hsw < 1 || hsw > 256 || + hfp < 1 || hfp > 4096 || + hbp < 1 || hbp > 4096 || + vsw < 1 || vsw > 256 || + vfp < 0 || vfp > 4095 || + vbp < 0 || vbp > 4095) + return false; + } + + return true; +} + +bool dispc_lcd_timings_ok(struct omap_video_timings *timings) +{ + return _dispc_lcd_timings_ok(timings->hsw, timings->hfp, + timings->hbp, timings->vsw, + timings->vfp, timings->vbp); +} + +static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp, + int vsw, int vfp, int vbp) +{ + u32 timing_h, timing_v; + + if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { + timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) | + FLD_VAL(hbp-1, 27, 20); + + timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) | + FLD_VAL(vbp, 27, 20); + } else { + timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) | + FLD_VAL(hbp-1, 31, 20); + + timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) | + FLD_VAL(vbp, 31, 20); + } + + enable_clocks(1); + dispc_write_reg(DISPC_TIMING_H, timing_h); + dispc_write_reg(DISPC_TIMING_V, timing_v); + enable_clocks(0); +} + +/* change name to mode? */ +void dispc_set_lcd_timings(struct omap_video_timings *timings) +{ + unsigned xtot, ytot; + unsigned long ht, vt; + + if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp, + timings->hbp, timings->vsw, + timings->vfp, timings->vbp)) + BUG(); + + _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp, + timings->vsw, timings->vfp, timings->vbp); + + dispc_set_lcd_size(timings->x_res, timings->y_res); + + xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; + ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; + + ht = (timings->pixel_clock * 1000) / xtot; + vt = (timings->pixel_clock * 1000) / xtot / ytot; + + DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res); + DSSDBG("pck %u\n", timings->pixel_clock); + DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", + timings->hsw, timings->hfp, timings->hbp, + timings->vsw, timings->vfp, timings->vbp); + + DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); +} + +static void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div) +{ + BUG_ON(lck_div < 1); + BUG_ON(pck_div < 2); + + enable_clocks(1); + dispc_write_reg(DISPC_DIVISOR, + FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); + enable_clocks(0); +} + +static void dispc_get_lcd_divisor(int *lck_div, int *pck_div) +{ + u32 l; + l = dispc_read_reg(DISPC_DIVISOR); + *lck_div = FLD_GET(l, 23, 16); + *pck_div = FLD_GET(l, 7, 0); +} + +unsigned long dispc_fclk_rate(void) +{ + unsigned long r = 0; + + if (dss_get_dispc_clk_source() == 0) + r = dss_clk_get_rate(DSS_CLK_FCK1); + else +#ifdef CONFIG_OMAP2_DSS_DSI + r = dsi_get_dsi1_pll_rate(); +#else + BUG(); +#endif + return r; +} + +unsigned long dispc_lclk_rate(void) +{ + int lcd; + unsigned long r; + u32 l; + + l = dispc_read_reg(DISPC_DIVISOR); + + lcd = FLD_GET(l, 23, 16); + + r = dispc_fclk_rate(); + + return r / lcd; +} + +unsigned long dispc_pclk_rate(void) +{ + int lcd, pcd; + unsigned long r; + u32 l; + + l = dispc_read_reg(DISPC_DIVISOR); + + lcd = FLD_GET(l, 23, 16); + pcd = FLD_GET(l, 7, 0); + + r = dispc_fclk_rate(); + + return r / lcd / pcd; +} + +void dispc_dump_clocks(struct seq_file *s) +{ + int lcd, pcd; + + enable_clocks(1); + + dispc_get_lcd_divisor(&lcd, &pcd); + + seq_printf(s, "- DISPC -\n"); + + seq_printf(s, "dispc fclk source = %s\n", + dss_get_dispc_clk_source() == 0 ? + "dss1_alwon_fclk" : "dsi1_pll_fclk"); + + seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); + seq_printf(s, "lck\t\t%-16lulck div\t%u\n", dispc_lclk_rate(), lcd); + seq_printf(s, "pck\t\t%-16lupck div\t%u\n", dispc_pclk_rate(), pcd); + + enable_clocks(0); +} + +void dispc_dump_regs(struct seq_file *s) +{ +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + DUMPREG(DISPC_REVISION); + DUMPREG(DISPC_SYSCONFIG); + DUMPREG(DISPC_SYSSTATUS); + DUMPREG(DISPC_IRQSTATUS); + DUMPREG(DISPC_IRQENABLE); + DUMPREG(DISPC_CONTROL); + DUMPREG(DISPC_CONFIG); + DUMPREG(DISPC_CAPABLE); + DUMPREG(DISPC_DEFAULT_COLOR0); + DUMPREG(DISPC_DEFAULT_COLOR1); + DUMPREG(DISPC_TRANS_COLOR0); + DUMPREG(DISPC_TRANS_COLOR1); + DUMPREG(DISPC_LINE_STATUS); + DUMPREG(DISPC_LINE_NUMBER); + DUMPREG(DISPC_TIMING_H); + DUMPREG(DISPC_TIMING_V); + DUMPREG(DISPC_POL_FREQ); + DUMPREG(DISPC_DIVISOR); + DUMPREG(DISPC_GLOBAL_ALPHA); + DUMPREG(DISPC_SIZE_DIG); + DUMPREG(DISPC_SIZE_LCD); + + DUMPREG(DISPC_GFX_BA0); + DUMPREG(DISPC_GFX_BA1); + DUMPREG(DISPC_GFX_POSITION); + DUMPREG(DISPC_GFX_SIZE); + DUMPREG(DISPC_GFX_ATTRIBUTES); + DUMPREG(DISPC_GFX_FIFO_THRESHOLD); + DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS); + DUMPREG(DISPC_GFX_ROW_INC); + DUMPREG(DISPC_GFX_PIXEL_INC); + DUMPREG(DISPC_GFX_WINDOW_SKIP); + DUMPREG(DISPC_GFX_TABLE_BA); + + DUMPREG(DISPC_DATA_CYCLE1); + DUMPREG(DISPC_DATA_CYCLE2); + DUMPREG(DISPC_DATA_CYCLE3); + + DUMPREG(DISPC_CPR_COEF_R); + DUMPREG(DISPC_CPR_COEF_G); + DUMPREG(DISPC_CPR_COEF_B); + + DUMPREG(DISPC_GFX_PRELOAD); + + DUMPREG(DISPC_VID_BA0(0)); + DUMPREG(DISPC_VID_BA1(0)); + DUMPREG(DISPC_VID_POSITION(0)); + DUMPREG(DISPC_VID_SIZE(0)); + DUMPREG(DISPC_VID_ATTRIBUTES(0)); + DUMPREG(DISPC_VID_FIFO_THRESHOLD(0)); + DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0)); + DUMPREG(DISPC_VID_ROW_INC(0)); + DUMPREG(DISPC_VID_PIXEL_INC(0)); + DUMPREG(DISPC_VID_FIR(0)); + DUMPREG(DISPC_VID_PICTURE_SIZE(0)); + DUMPREG(DISPC_VID_ACCU0(0)); + DUMPREG(DISPC_VID_ACCU1(0)); + + DUMPREG(DISPC_VID_BA0(1)); + DUMPREG(DISPC_VID_BA1(1)); + DUMPREG(DISPC_VID_POSITION(1)); + DUMPREG(DISPC_VID_SIZE(1)); + DUMPREG(DISPC_VID_ATTRIBUTES(1)); + DUMPREG(DISPC_VID_FIFO_THRESHOLD(1)); + DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1)); + DUMPREG(DISPC_VID_ROW_INC(1)); + DUMPREG(DISPC_VID_PIXEL_INC(1)); + DUMPREG(DISPC_VID_FIR(1)); + DUMPREG(DISPC_VID_PICTURE_SIZE(1)); + DUMPREG(DISPC_VID_ACCU0(1)); + DUMPREG(DISPC_VID_ACCU1(1)); + + DUMPREG(DISPC_VID_FIR_COEF_H(0, 0)); + DUMPREG(DISPC_VID_FIR_COEF_H(0, 1)); + DUMPREG(DISPC_VID_FIR_COEF_H(0, 2)); + DUMPREG(DISPC_VID_FIR_COEF_H(0, 3)); + DUMPREG(DISPC_VID_FIR_COEF_H(0, 4)); + DUMPREG(DISPC_VID_FIR_COEF_H(0, 5)); + DUMPREG(DISPC_VID_FIR_COEF_H(0, 6)); + DUMPREG(DISPC_VID_FIR_COEF_H(0, 7)); + DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0)); + DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1)); + DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2)); + DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3)); + DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4)); + DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5)); + DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6)); + DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7)); + DUMPREG(DISPC_VID_CONV_COEF(0, 0)); + DUMPREG(DISPC_VID_CONV_COEF(0, 1)); + DUMPREG(DISPC_VID_CONV_COEF(0, 2)); + DUMPREG(DISPC_VID_CONV_COEF(0, 3)); + DUMPREG(DISPC_VID_CONV_COEF(0, 4)); + DUMPREG(DISPC_VID_FIR_COEF_V(0, 0)); + DUMPREG(DISPC_VID_FIR_COEF_V(0, 1)); + DUMPREG(DISPC_VID_FIR_COEF_V(0, 2)); + DUMPREG(DISPC_VID_FIR_COEF_V(0, 3)); + DUMPREG(DISPC_VID_FIR_COEF_V(0, 4)); + DUMPREG(DISPC_VID_FIR_COEF_V(0, 5)); + DUMPREG(DISPC_VID_FIR_COEF_V(0, 6)); + DUMPREG(DISPC_VID_FIR_COEF_V(0, 7)); + + DUMPREG(DISPC_VID_FIR_COEF_H(1, 0)); + DUMPREG(DISPC_VID_FIR_COEF_H(1, 1)); + DUMPREG(DISPC_VID_FIR_COEF_H(1, 2)); + DUMPREG(DISPC_VID_FIR_COEF_H(1, 3)); + DUMPREG(DISPC_VID_FIR_COEF_H(1, 4)); + DUMPREG(DISPC_VID_FIR_COEF_H(1, 5)); + DUMPREG(DISPC_VID_FIR_COEF_H(1, 6)); + DUMPREG(DISPC_VID_FIR_COEF_H(1, 7)); + DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0)); + DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1)); + DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2)); + DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3)); + DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4)); + DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5)); + DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6)); + DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7)); + DUMPREG(DISPC_VID_CONV_COEF(1, 0)); + DUMPREG(DISPC_VID_CONV_COEF(1, 1)); + DUMPREG(DISPC_VID_CONV_COEF(1, 2)); + DUMPREG(DISPC_VID_CONV_COEF(1, 3)); + DUMPREG(DISPC_VID_CONV_COEF(1, 4)); + DUMPREG(DISPC_VID_FIR_COEF_V(1, 0)); + DUMPREG(DISPC_VID_FIR_COEF_V(1, 1)); + DUMPREG(DISPC_VID_FIR_COEF_V(1, 2)); + DUMPREG(DISPC_VID_FIR_COEF_V(1, 3)); + DUMPREG(DISPC_VID_FIR_COEF_V(1, 4)); + DUMPREG(DISPC_VID_FIR_COEF_V(1, 5)); + DUMPREG(DISPC_VID_FIR_COEF_V(1, 6)); + DUMPREG(DISPC_VID_FIR_COEF_V(1, 7)); + + DUMPREG(DISPC_VID_PRELOAD(0)); + DUMPREG(DISPC_VID_PRELOAD(1)); + + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); +#undef DUMPREG +} + +static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc, + bool ihs, bool ivs, u8 acbi, u8 acb) +{ + u32 l = 0; + + DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n", + onoff, rf, ieo, ipc, ihs, ivs, acbi, acb); + + l |= FLD_VAL(onoff, 17, 17); + l |= FLD_VAL(rf, 16, 16); + l |= FLD_VAL(ieo, 15, 15); + l |= FLD_VAL(ipc, 14, 14); + l |= FLD_VAL(ihs, 13, 13); + l |= FLD_VAL(ivs, 12, 12); + l |= FLD_VAL(acbi, 11, 8); + l |= FLD_VAL(acb, 7, 0); + + enable_clocks(1); + dispc_write_reg(DISPC_POL_FREQ, l); + enable_clocks(0); +} + +void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb) +{ + _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0, + (config & OMAP_DSS_LCD_RF) != 0, + (config & OMAP_DSS_LCD_IEO) != 0, + (config & OMAP_DSS_LCD_IPC) != 0, + (config & OMAP_DSS_LCD_IHS) != 0, + (config & OMAP_DSS_LCD_IVS) != 0, + acbi, acb); +} + +/* with fck as input clock rate, find dispc dividers that produce req_pck */ +void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, + struct dispc_clock_info *cinfo) +{ + u16 pcd_min = is_tft ? 2 : 3; + unsigned long best_pck; + u16 best_ld, cur_ld; + u16 best_pd, cur_pd; + + best_pck = 0; + best_ld = 0; + best_pd = 0; + + for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { + unsigned long lck = fck / cur_ld; + + for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) { + unsigned long pck = lck / cur_pd; + long old_delta = abs(best_pck - req_pck); + long new_delta = abs(pck - req_pck); + + if (best_pck == 0 || new_delta < old_delta) { + best_pck = pck; + best_ld = cur_ld; + best_pd = cur_pd; + + if (pck == req_pck) + goto found; + } + + if (pck < req_pck) + break; + } + + if (lck / pcd_min < req_pck) + break; + } + +found: + cinfo->lck_div = best_ld; + cinfo->pck_div = best_pd; + cinfo->lck = fck / cinfo->lck_div; + cinfo->pck = cinfo->lck / cinfo->pck_div; +} + +/* calculate clock rates using dividers in cinfo */ +int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, + struct dispc_clock_info *cinfo) +{ + if (cinfo->lck_div > 255 || cinfo->lck_div == 0) + return -EINVAL; + if (cinfo->pck_div < 2 || cinfo->pck_div > 255) + return -EINVAL; + + cinfo->lck = dispc_fclk_rate / cinfo->lck_div; + cinfo->pck = cinfo->lck / cinfo->pck_div; + + return 0; +} + +int dispc_set_clock_div(struct dispc_clock_info *cinfo) +{ + DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); + DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); + + dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div); + + return 0; +} + +int dispc_get_clock_div(struct dispc_clock_info *cinfo) +{ + unsigned long fck; + + fck = dispc_fclk_rate(); + + cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16); + cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0); + + cinfo->lck = fck / cinfo->lck_div; + cinfo->pck = cinfo->lck / cinfo->pck_div; + + return 0; +} + +/* dispc.irq_lock has to be locked by the caller */ +static void _omap_dispc_set_irqs(void) +{ + u32 mask; + u32 old_mask; + int i; + struct omap_dispc_isr_data *isr_data; + + mask = dispc.irq_error_mask; + + for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { + isr_data = &dispc.registered_isr[i]; + + if (isr_data->isr == NULL) + continue; + + mask |= isr_data->mask; + } + + enable_clocks(1); + + old_mask = dispc_read_reg(DISPC_IRQENABLE); + /* clear the irqstatus for newly enabled irqs */ + dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask); + + dispc_write_reg(DISPC_IRQENABLE, mask); + + enable_clocks(0); +} + +int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) +{ + int i; + int ret; + unsigned long flags; + struct omap_dispc_isr_data *isr_data; + + if (isr == NULL) + return -EINVAL; + + spin_lock_irqsave(&dispc.irq_lock, flags); + + /* check for duplicate entry */ + for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { + isr_data = &dispc.registered_isr[i]; + if (isr_data->isr == isr && isr_data->arg == arg && + isr_data->mask == mask) { + ret = -EINVAL; + goto err; + } + } + + isr_data = NULL; + ret = -EBUSY; + + for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { + isr_data = &dispc.registered_isr[i]; + + if (isr_data->isr != NULL) + continue; + + isr_data->isr = isr; + isr_data->arg = arg; + isr_data->mask = mask; + ret = 0; + + break; + } + + _omap_dispc_set_irqs(); + + spin_unlock_irqrestore(&dispc.irq_lock, flags); + + return 0; +err: + spin_unlock_irqrestore(&dispc.irq_lock, flags); + + return ret; +} +EXPORT_SYMBOL(omap_dispc_register_isr); + +int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask) +{ + int i; + unsigned long flags; + int ret = -EINVAL; + struct omap_dispc_isr_data *isr_data; + + spin_lock_irqsave(&dispc.irq_lock, flags); + + for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { + isr_data = &dispc.registered_isr[i]; + if (isr_data->isr != isr || isr_data->arg != arg || + isr_data->mask != mask) + continue; + + /* found the correct isr */ + + isr_data->isr = NULL; + isr_data->arg = NULL; + isr_data->mask = 0; + + ret = 0; + break; + } + + if (ret == 0) + _omap_dispc_set_irqs(); + + spin_unlock_irqrestore(&dispc.irq_lock, flags); + + return ret; +} +EXPORT_SYMBOL(omap_dispc_unregister_isr); + +#ifdef DEBUG +static void print_irq_status(u32 status) +{ + if ((status & dispc.irq_error_mask) == 0) + return; + + printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status); + +#define PIS(x) \ + if (status & DISPC_IRQ_##x) \ + printk(#x " "); + PIS(GFX_FIFO_UNDERFLOW); + PIS(OCP_ERR); + PIS(VID1_FIFO_UNDERFLOW); + PIS(VID2_FIFO_UNDERFLOW); + PIS(SYNC_LOST); + PIS(SYNC_LOST_DIGIT); +#undef PIS + + printk("\n"); +} +#endif + +/* Called from dss.c. Note that we don't touch clocks here, + * but we presume they are on because we got an IRQ. However, + * an irq handler may turn the clocks off, so we may not have + * clock later in the function. */ +void dispc_irq_handler(void) +{ + int i; + u32 irqstatus; + u32 handledirqs = 0; + u32 unhandled_errors; + struct omap_dispc_isr_data *isr_data; + struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS]; + + spin_lock(&dispc.irq_lock); + + irqstatus = dispc_read_reg(DISPC_IRQSTATUS); + +#ifdef DEBUG + if (dss_debug) + print_irq_status(irqstatus); +#endif + /* Ack the interrupt. Do it here before clocks are possibly turned + * off */ + dispc_write_reg(DISPC_IRQSTATUS, irqstatus); + /* flush posted write */ + dispc_read_reg(DISPC_IRQSTATUS); + + /* make a copy and unlock, so that isrs can unregister + * themselves */ + memcpy(registered_isr, dispc.registered_isr, + sizeof(registered_isr)); + + spin_unlock(&dispc.irq_lock); + + for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { + isr_data = ®istered_isr[i]; + + if (!isr_data->isr) + continue; + + if (isr_data->mask & irqstatus) { + isr_data->isr(isr_data->arg, irqstatus); + handledirqs |= isr_data->mask; + } + } + + spin_lock(&dispc.irq_lock); + + unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask; + + if (unhandled_errors) { + dispc.error_irqs |= unhandled_errors; + + dispc.irq_error_mask &= ~unhandled_errors; + _omap_dispc_set_irqs(); + + schedule_work(&dispc.error_work); + } + + spin_unlock(&dispc.irq_lock); +} + +static void dispc_error_worker(struct work_struct *work) +{ + int i; + u32 errors; + unsigned long flags; + + spin_lock_irqsave(&dispc.irq_lock, flags); + errors = dispc.error_irqs; + dispc.error_irqs = 0; + spin_unlock_irqrestore(&dispc.irq_lock, flags); + + if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) { + DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n"); + for (i = 0; i < omap_dss_get_num_overlays(); ++i) { + struct omap_overlay *ovl; + ovl = omap_dss_get_overlay(i); + + if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) + continue; + + if (ovl->id == 0) { + dispc_enable_plane(ovl->id, 0); + dispc_go(ovl->manager->id); + mdelay(50); + break; + } + } + } + + if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) { + DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n"); + for (i = 0; i < omap_dss_get_num_overlays(); ++i) { + struct omap_overlay *ovl; + ovl = omap_dss_get_overlay(i); + + if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) + continue; + + if (ovl->id == 1) { + dispc_enable_plane(ovl->id, 0); + dispc_go(ovl->manager->id); + mdelay(50); + break; + } + } + } + + if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) { + DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n"); + for (i = 0; i < omap_dss_get_num_overlays(); ++i) { + struct omap_overlay *ovl; + ovl = omap_dss_get_overlay(i); + + if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) + continue; + + if (ovl->id == 2) { + dispc_enable_plane(ovl->id, 0); + dispc_go(ovl->manager->id); + mdelay(50); + break; + } + } + } + + if (errors & DISPC_IRQ_SYNC_LOST) { + struct omap_overlay_manager *manager = NULL; + bool enable = false; + + DSSERR("SYNC_LOST, disabling LCD\n"); + + for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { + struct omap_overlay_manager *mgr; + mgr = omap_dss_get_overlay_manager(i); + + if (mgr->id == OMAP_DSS_CHANNEL_LCD) { + manager = mgr; + enable = mgr->device->state == + OMAP_DSS_DISPLAY_ACTIVE; + mgr->device->disable(mgr->device); + break; + } + } + + if (manager) { + for (i = 0; i < omap_dss_get_num_overlays(); ++i) { + struct omap_overlay *ovl; + ovl = omap_dss_get_overlay(i); + + if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) + continue; + + if (ovl->id != 0 && ovl->manager == manager) + dispc_enable_plane(ovl->id, 0); + } + + dispc_go(manager->id); + mdelay(50); + if (enable) + manager->device->enable(manager->device); + } + } + + if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) { + struct omap_overlay_manager *manager = NULL; + bool enable = false; + + DSSERR("SYNC_LOST_DIGIT, disabling TV\n"); + + for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { + struct omap_overlay_manager *mgr; + mgr = omap_dss_get_overlay_manager(i); + + if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) { + manager = mgr; + enable = mgr->device->state == + OMAP_DSS_DISPLAY_ACTIVE; + mgr->device->disable(mgr->device); + break; + } + } + + if (manager) { + for (i = 0; i < omap_dss_get_num_overlays(); ++i) { + struct omap_overlay *ovl; + ovl = omap_dss_get_overlay(i); + + if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) + continue; + + if (ovl->id != 0 && ovl->manager == manager) + dispc_enable_plane(ovl->id, 0); + } + + dispc_go(manager->id); + mdelay(50); + if (enable) + manager->device->enable(manager->device); + } + } + + if (errors & DISPC_IRQ_OCP_ERR) { + DSSERR("OCP_ERR\n"); + for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { + struct omap_overlay_manager *mgr; + mgr = omap_dss_get_overlay_manager(i); + + if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC) + mgr->device->disable(mgr->device); + } + } + + spin_lock_irqsave(&dispc.irq_lock, flags); + dispc.irq_error_mask |= errors; + _omap_dispc_set_irqs(); + spin_unlock_irqrestore(&dispc.irq_lock, flags); +} + +int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout) +{ + void dispc_irq_wait_handler(void *data, u32 mask) + { + complete((struct completion *)data); + } + + int r; + DECLARE_COMPLETION_ONSTACK(completion); + + r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion, + irqmask); + + if (r) + return r; + + timeout = wait_for_completion_timeout(&completion, timeout); + + omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask); + + if (timeout == 0) + return -ETIMEDOUT; + + if (timeout == -ERESTARTSYS) + return -ERESTARTSYS; + + return 0; +} + +int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, + unsigned long timeout) +{ + void dispc_irq_wait_handler(void *data, u32 mask) + { + complete((struct completion *)data); + } + + int r; + DECLARE_COMPLETION_ONSTACK(completion); + + r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion, + irqmask); + + if (r) + return r; + + timeout = wait_for_completion_interruptible_timeout(&completion, + timeout); + + omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask); + + if (timeout == 0) + return -ETIMEDOUT; + + if (timeout == -ERESTARTSYS) + return -ERESTARTSYS; + + return 0; +} + +#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC +void dispc_fake_vsync_irq(void) +{ + u32 irqstatus = DISPC_IRQ_VSYNC; + int i; + + local_irq_disable(); + + for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { + struct omap_dispc_isr_data *isr_data; + isr_data = &dispc.registered_isr[i]; + + if (!isr_data->isr) + continue; + + if (isr_data->mask & irqstatus) + isr_data->isr(isr_data->arg, irqstatus); + } + + local_irq_enable(); +} +#endif + +static void _omap_dispc_initialize_irq(void) +{ + unsigned long flags; + + spin_lock_irqsave(&dispc.irq_lock, flags); + + memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr)); + + dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; + + /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, + * so clear it */ + dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS)); + + _omap_dispc_set_irqs(); + + spin_unlock_irqrestore(&dispc.irq_lock, flags); +} + +void dispc_enable_sidle(void) +{ + REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */ +} + +void dispc_disable_sidle(void) +{ + REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */ +} + +static void _omap_dispc_initial_config(void) +{ + u32 l; + + l = dispc_read_reg(DISPC_SYSCONFIG); + l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */ + l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */ + l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */ + l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ + dispc_write_reg(DISPC_SYSCONFIG, l); + + /* FUNCGATED */ + REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); + + /* L3 firewall setting: enable access to OCM RAM */ + /* XXX this should be somewhere in plat-omap */ + if (cpu_is_omap24xx()) + __raw_writel(0x402000b0, OMAP2_L3_IO_ADDRESS(0x680050a0)); + + _dispc_setup_color_conv_coef(); + + dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY); + + dispc_read_plane_fifo_sizes(); +} + +int dispc_init(void) +{ + u32 rev; + + spin_lock_init(&dispc.irq_lock); + + INIT_WORK(&dispc.error_work, dispc_error_worker); + + dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS); + if (!dispc.base) { + DSSERR("can't ioremap DISPC\n"); + return -ENOMEM; + } + + enable_clocks(1); + + _omap_dispc_initial_config(); + + _omap_dispc_initialize_irq(); + + dispc_save_context(); + + rev = dispc_read_reg(DISPC_REVISION); + printk(KERN_INFO "OMAP DISPC rev %d.%d\n", + FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); + + enable_clocks(0); + + return 0; +} + +void dispc_exit(void) +{ + iounmap(dispc.base); +} + +int dispc_enable_plane(enum omap_plane plane, bool enable) +{ + DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); + + enable_clocks(1); + _dispc_enable_plane(plane, enable); + enable_clocks(0); + + return 0; +} + +int dispc_setup_plane(enum omap_plane plane, + u32 paddr, u16 screen_width, + u16 pos_x, u16 pos_y, + u16 width, u16 height, + u16 out_width, u16 out_height, + enum omap_color_mode color_mode, + bool ilace, + enum omap_dss_rotation_type rotation_type, + u8 rotation, bool mirror, u8 global_alpha) +{ + int r = 0; + + DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " + "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n", + plane, paddr, screen_width, pos_x, pos_y, + width, height, + out_width, out_height, + ilace, color_mode, + rotation, mirror); + + enable_clocks(1); + + r = _dispc_setup_plane(plane, + paddr, screen_width, + pos_x, pos_y, + width, height, + out_width, out_height, + color_mode, ilace, + rotation_type, + rotation, mirror, + global_alpha); + + enable_clocks(0); + + return r; +} diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c new file mode 100644 index 0000000000000000000000000000000000000000..3b92b84b95607086f856d0c8314dfb8d8a883b0b --- /dev/null +++ b/drivers/video/omap2/dss/display.c @@ -0,0 +1,671 @@ +/* + * linux/drivers/video/omap2/dss/display.c + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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, see . + */ + +#define DSS_SUBSYS_NAME "DISPLAY" + +#include +#include +#include +#include +#include + +#include +#include "dss.h" + +static LIST_HEAD(display_list); + +static ssize_t display_enabled_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED; + + return snprintf(buf, PAGE_SIZE, "%d\n", enabled); +} + +static ssize_t display_enabled_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + bool enabled, r; + + enabled = simple_strtoul(buf, NULL, 10); + + if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { + if (enabled) { + r = dssdev->enable(dssdev); + if (r) + return r; + } else { + dssdev->disable(dssdev); + } + } + + return size; +} + +static ssize_t display_upd_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO; + if (dssdev->get_update_mode) + mode = dssdev->get_update_mode(dssdev); + return snprintf(buf, PAGE_SIZE, "%d\n", mode); +} + +static ssize_t display_upd_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + int val, r; + enum omap_dss_update_mode mode; + + val = simple_strtoul(buf, NULL, 10); + + switch (val) { + case OMAP_DSS_UPDATE_DISABLED: + case OMAP_DSS_UPDATE_AUTO: + case OMAP_DSS_UPDATE_MANUAL: + mode = (enum omap_dss_update_mode)val; + break; + default: + return -EINVAL; + } + + r = dssdev->set_update_mode(dssdev, mode); + if (r) + return r; + + return size; +} + +static ssize_t display_tear_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", + dssdev->get_te ? dssdev->get_te(dssdev) : 0); +} + +static ssize_t display_tear_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + unsigned long te; + int r; + + if (!dssdev->enable_te || !dssdev->get_te) + return -ENOENT; + + te = simple_strtoul(buf, NULL, 0); + + r = dssdev->enable_te(dssdev, te); + if (r) + return r; + + return size; +} + +static ssize_t display_timings_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + struct omap_video_timings t; + + if (!dssdev->get_timings) + return -ENOENT; + + dssdev->get_timings(dssdev, &t); + + return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n", + t.pixel_clock, + t.x_res, t.hfp, t.hbp, t.hsw, + t.y_res, t.vfp, t.vbp, t.vsw); +} + +static ssize_t display_timings_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + struct omap_video_timings t; + int r, found; + + if (!dssdev->set_timings || !dssdev->check_timings) + return -ENOENT; + + found = 0; +#ifdef CONFIG_OMAP2_DSS_VENC + if (strncmp("pal", buf, 3) == 0) { + t = omap_dss_pal_timings; + found = 1; + } else if (strncmp("ntsc", buf, 4) == 0) { + t = omap_dss_ntsc_timings; + found = 1; + } +#endif + if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu", + &t.pixel_clock, + &t.x_res, &t.hfp, &t.hbp, &t.hsw, + &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9) + return -EINVAL; + + r = dssdev->check_timings(dssdev, &t); + if (r) + return r; + + dssdev->set_timings(dssdev, &t); + + return size; +} + +static ssize_t display_rotate_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + int rotate; + if (!dssdev->get_rotate) + return -ENOENT; + rotate = dssdev->get_rotate(dssdev); + return snprintf(buf, PAGE_SIZE, "%u\n", rotate); +} + +static ssize_t display_rotate_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + unsigned long rot; + int r; + + if (!dssdev->set_rotate || !dssdev->get_rotate) + return -ENOENT; + + rot = simple_strtoul(buf, NULL, 0); + + r = dssdev->set_rotate(dssdev, rot); + if (r) + return r; + + return size; +} + +static ssize_t display_mirror_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + int mirror; + if (!dssdev->get_mirror) + return -ENOENT; + mirror = dssdev->get_mirror(dssdev); + return snprintf(buf, PAGE_SIZE, "%u\n", mirror); +} + +static ssize_t display_mirror_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + unsigned long mirror; + int r; + + if (!dssdev->set_mirror || !dssdev->get_mirror) + return -ENOENT; + + mirror = simple_strtoul(buf, NULL, 0); + + r = dssdev->set_mirror(dssdev, mirror); + if (r) + return r; + + return size; +} + +static ssize_t display_wss_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + unsigned int wss; + + if (!dssdev->get_wss) + return -ENOENT; + + wss = dssdev->get_wss(dssdev); + + return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss); +} + +static ssize_t display_wss_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + unsigned long wss; + int r; + + if (!dssdev->get_wss || !dssdev->set_wss) + return -ENOENT; + + if (strict_strtoul(buf, 0, &wss)) + return -EINVAL; + + if (wss > 0xfffff) + return -EINVAL; + + r = dssdev->set_wss(dssdev, wss); + if (r) + return r; + + return size; +} + +static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR, + display_enabled_show, display_enabled_store); +static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR, + display_upd_mode_show, display_upd_mode_store); +static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR, + display_tear_show, display_tear_store); +static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR, + display_timings_show, display_timings_store); +static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR, + display_rotate_show, display_rotate_store); +static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR, + display_mirror_show, display_mirror_store); +static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR, + display_wss_show, display_wss_store); + +static struct device_attribute *display_sysfs_attrs[] = { + &dev_attr_enabled, + &dev_attr_update_mode, + &dev_attr_tear_elim, + &dev_attr_timings, + &dev_attr_rotate, + &dev_attr_mirror, + &dev_attr_wss, + NULL +}; + +static void default_get_resolution(struct omap_dss_device *dssdev, + u16 *xres, u16 *yres) +{ + *xres = dssdev->panel.timings.x_res; + *yres = dssdev->panel.timings.y_res; +} + +void default_get_overlay_fifo_thresholds(enum omap_plane plane, + u32 fifo_size, enum omap_burst_size *burst_size, + u32 *fifo_low, u32 *fifo_high) +{ + unsigned burst_size_bytes; + + *burst_size = OMAP_DSS_BURST_16x32; + burst_size_bytes = 16 * 32 / 8; + + *fifo_high = fifo_size - 1; + *fifo_low = fifo_size - burst_size_bytes; +} + +static int default_wait_vsync(struct omap_dss_device *dssdev) +{ + unsigned long timeout = msecs_to_jiffies(500); + u32 irq; + + if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) + irq = DISPC_IRQ_EVSYNC_ODD; + else + irq = DISPC_IRQ_VSYNC; + + return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); +} + +static int default_get_recommended_bpp(struct omap_dss_device *dssdev) +{ + if (dssdev->panel.recommended_bpp) + return dssdev->panel.recommended_bpp; + + switch (dssdev->type) { + case OMAP_DISPLAY_TYPE_DPI: + if (dssdev->phy.dpi.data_lines == 24) + return 24; + else + return 16; + + case OMAP_DISPLAY_TYPE_DBI: + case OMAP_DISPLAY_TYPE_DSI: + if (dssdev->ctrl.pixel_size == 24) + return 24; + else + return 16; + case OMAP_DISPLAY_TYPE_VENC: + case OMAP_DISPLAY_TYPE_SDI: + return 24; + return 24; + default: + BUG(); + } +} + +/* Checks if replication logic should be used. Only use for active matrix, + * when overlay is in RGB12U or RGB16 mode, and LCD interface is + * 18bpp or 24bpp */ +bool dss_use_replication(struct omap_dss_device *dssdev, + enum omap_color_mode mode) +{ + int bpp; + + if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16) + return false; + + if (dssdev->type == OMAP_DISPLAY_TYPE_DPI && + (dssdev->panel.config & OMAP_DSS_LCD_TFT) == 0) + return false; + + switch (dssdev->type) { + case OMAP_DISPLAY_TYPE_DPI: + bpp = dssdev->phy.dpi.data_lines; + break; + case OMAP_DISPLAY_TYPE_VENC: + case OMAP_DISPLAY_TYPE_SDI: + bpp = 24; + break; + case OMAP_DISPLAY_TYPE_DBI: + case OMAP_DISPLAY_TYPE_DSI: + bpp = dssdev->ctrl.pixel_size; + break; + default: + BUG(); + } + + return bpp > 16; +} + +void dss_init_device(struct platform_device *pdev, + struct omap_dss_device *dssdev) +{ + struct device_attribute *attr; + int i; + int r; + + switch (dssdev->type) { + case OMAP_DISPLAY_TYPE_DPI: +#ifdef CONFIG_OMAP2_DSS_RFBI + case OMAP_DISPLAY_TYPE_DBI: +#endif +#ifdef CONFIG_OMAP2_DSS_SDI + case OMAP_DISPLAY_TYPE_SDI: +#endif +#ifdef CONFIG_OMAP2_DSS_DSI + case OMAP_DISPLAY_TYPE_DSI: +#endif +#ifdef CONFIG_OMAP2_DSS_VENC + case OMAP_DISPLAY_TYPE_VENC: +#endif + break; + default: + DSSERR("Support for display '%s' not compiled in.\n", + dssdev->name); + return; + } + + dssdev->get_resolution = default_get_resolution; + dssdev->get_recommended_bpp = default_get_recommended_bpp; + dssdev->wait_vsync = default_wait_vsync; + + switch (dssdev->type) { + case OMAP_DISPLAY_TYPE_DPI: + r = dpi_init_display(dssdev); + break; +#ifdef CONFIG_OMAP2_DSS_RFBI + case OMAP_DISPLAY_TYPE_DBI: + r = rfbi_init_display(dssdev); + break; +#endif +#ifdef CONFIG_OMAP2_DSS_VENC + case OMAP_DISPLAY_TYPE_VENC: + r = venc_init_display(dssdev); + break; +#endif +#ifdef CONFIG_OMAP2_DSS_SDI + case OMAP_DISPLAY_TYPE_SDI: + r = sdi_init_display(dssdev); + break; +#endif +#ifdef CONFIG_OMAP2_DSS_DSI + case OMAP_DISPLAY_TYPE_DSI: + r = dsi_init_display(dssdev); + break; +#endif + default: + BUG(); + } + + if (r) { + DSSERR("failed to init display %s\n", dssdev->name); + return; + } + + /* create device sysfs files */ + i = 0; + while ((attr = display_sysfs_attrs[i++]) != NULL) { + r = device_create_file(&dssdev->dev, attr); + if (r) + DSSERR("failed to create sysfs file\n"); + } + + /* create display? sysfs links */ + r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj, + dev_name(&dssdev->dev)); + if (r) + DSSERR("failed to create sysfs display link\n"); +} + +void dss_uninit_device(struct platform_device *pdev, + struct omap_dss_device *dssdev) +{ + struct device_attribute *attr; + int i = 0; + + sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev)); + + while ((attr = display_sysfs_attrs[i++]) != NULL) + device_remove_file(&dssdev->dev, attr); + + if (dssdev->manager) + dssdev->manager->unset_device(dssdev->manager); +} + +static int dss_suspend_device(struct device *dev, void *data) +{ + int r; + struct omap_dss_device *dssdev = to_dss_device(dev); + + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { + dssdev->activate_after_resume = false; + return 0; + } + + if (!dssdev->suspend) { + DSSERR("display '%s' doesn't implement suspend\n", + dssdev->name); + return -ENOSYS; + } + + r = dssdev->suspend(dssdev); + if (r) + return r; + + dssdev->activate_after_resume = true; + + return 0; +} + +int dss_suspend_all_devices(void) +{ + int r; + struct bus_type *bus = dss_get_bus(); + + r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device); + if (r) { + /* resume all displays that were suspended */ + dss_resume_all_devices(); + return r; + } + + return 0; +} + +static int dss_resume_device(struct device *dev, void *data) +{ + int r; + struct omap_dss_device *dssdev = to_dss_device(dev); + + if (dssdev->activate_after_resume && dssdev->resume) { + r = dssdev->resume(dssdev); + if (r) + return r; + } + + dssdev->activate_after_resume = false; + + return 0; +} + +int dss_resume_all_devices(void) +{ + struct bus_type *bus = dss_get_bus(); + + return bus_for_each_dev(bus, NULL, NULL, dss_resume_device); +} + +static int dss_disable_device(struct device *dev, void *data) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + dssdev->disable(dssdev); + return 0; +} + +void dss_disable_all_devices(void) +{ + struct bus_type *bus = dss_get_bus(); + bus_for_each_dev(bus, NULL, NULL, dss_disable_device); +} + + +void omap_dss_get_device(struct omap_dss_device *dssdev) +{ + get_device(&dssdev->dev); +} +EXPORT_SYMBOL(omap_dss_get_device); + +void omap_dss_put_device(struct omap_dss_device *dssdev) +{ + put_device(&dssdev->dev); +} +EXPORT_SYMBOL(omap_dss_put_device); + +/* ref count of the found device is incremented. ref count + * of from-device is decremented. */ +struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from) +{ + struct device *dev; + struct device *dev_start = NULL; + struct omap_dss_device *dssdev = NULL; + + int match(struct device *dev, void *data) + { + /* skip panels connected to controllers */ + if (to_dss_device(dev)->panel.ctrl) + return 0; + + return 1; + } + + if (from) + dev_start = &from->dev; + dev = bus_find_device(dss_get_bus(), dev_start, NULL, match); + if (dev) + dssdev = to_dss_device(dev); + if (from) + put_device(&from->dev); + + return dssdev; +} +EXPORT_SYMBOL(omap_dss_get_next_device); + +struct omap_dss_device *omap_dss_find_device(void *data, + int (*match)(struct omap_dss_device *dssdev, void *data)) +{ + struct omap_dss_device *dssdev = NULL; + + while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) { + if (match(dssdev, data)) + return dssdev; + } + + return NULL; +} +EXPORT_SYMBOL(omap_dss_find_device); + +int omap_dss_start_device(struct omap_dss_device *dssdev) +{ + int r; + + if (!dssdev->driver) { + DSSDBG("no driver\n"); + r = -ENODEV; + goto err0; + } + + if (dssdev->ctrl.panel && !dssdev->ctrl.panel->driver) { + DSSDBG("no panel driver\n"); + r = -ENODEV; + goto err0; + } + + if (!try_module_get(dssdev->dev.driver->owner)) { + r = -ENODEV; + goto err0; + } + + if (dssdev->ctrl.panel) { + if (!try_module_get(dssdev->ctrl.panel->dev.driver->owner)) { + r = -ENODEV; + goto err1; + } + } + + return 0; +err1: + module_put(dssdev->dev.driver->owner); +err0: + return r; +} +EXPORT_SYMBOL(omap_dss_start_device); + +void omap_dss_stop_device(struct omap_dss_device *dssdev) +{ + if (dssdev->ctrl.panel) + module_put(dssdev->ctrl.panel->dev.driver->owner); + + module_put(dssdev->dev.driver->owner); +} +EXPORT_SYMBOL(omap_dss_stop_device); + diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c new file mode 100644 index 0000000000000000000000000000000000000000..2d71031baa2551d09b723f34781136ea80674467 --- /dev/null +++ b/drivers/video/omap2/dss/dpi.c @@ -0,0 +1,399 @@ +/* + * linux/drivers/video/omap2/dss/dpi.c + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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, see . + */ + +#define DSS_SUBSYS_NAME "DPI" + +#include +#include +#include +#include + +#include +#include + +#include "dss.h" + +static struct { + int update_enabled; +} dpi; + +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL +static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req, + unsigned long *fck, int *lck_div, int *pck_div) +{ + struct dsi_clock_info dsi_cinfo; + struct dispc_clock_info dispc_cinfo; + int r; + + r = dsi_pll_calc_clock_div_pck(is_tft, pck_req, &dsi_cinfo, + &dispc_cinfo); + if (r) + return r; + + r = dsi_pll_set_clock_div(&dsi_cinfo); + if (r) + return r; + + dss_select_clk_source(0, 1); + + r = dispc_set_clock_div(&dispc_cinfo); + if (r) + return r; + + *fck = dsi_cinfo.dsi1_pll_fclk; + *lck_div = dispc_cinfo.lck_div; + *pck_div = dispc_cinfo.pck_div; + + return 0; +} +#else +static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req, + unsigned long *fck, int *lck_div, int *pck_div) +{ + struct dss_clock_info dss_cinfo; + struct dispc_clock_info dispc_cinfo; + int r; + + r = dss_calc_clock_div(is_tft, pck_req, &dss_cinfo, &dispc_cinfo); + if (r) + return r; + + r = dss_set_clock_div(&dss_cinfo); + if (r) + return r; + + r = dispc_set_clock_div(&dispc_cinfo); + if (r) + return r; + + *fck = dss_cinfo.fck; + *lck_div = dispc_cinfo.lck_div; + *pck_div = dispc_cinfo.pck_div; + + return 0; +} +#endif + +static int dpi_set_mode(struct omap_dss_device *dssdev) +{ + struct omap_video_timings *t = &dssdev->panel.timings; + int lck_div, pck_div; + unsigned long fck; + unsigned long pck; + bool is_tft; + int r = 0; + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, + dssdev->panel.acb); + + is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; + +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL + r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000, + &fck, &lck_div, &pck_div); +#else + r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000, + &fck, &lck_div, &pck_div); +#endif + if (r) + goto err0; + + pck = fck / lck_div / pck_div / 1000; + + if (pck != t->pixel_clock) { + DSSWARN("Could not find exact pixel clock. " + "Requested %d kHz, got %lu kHz\n", + t->pixel_clock, pck); + + t->pixel_clock = pck; + } + + dispc_set_lcd_timings(t); + +err0: + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + return r; +} + +static int dpi_basic_init(struct omap_dss_device *dssdev) +{ + bool is_tft; + + is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; + + dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); + dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT : + OMAP_DSS_LCD_DISPLAY_STN); + dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines); + + return 0; +} + +static int dpi_display_enable(struct omap_dss_device *dssdev) +{ + int r; + + r = omap_dss_start_device(dssdev); + if (r) { + DSSERR("failed to start device\n"); + goto err0; + } + + if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { + DSSERR("display already enabled\n"); + r = -EINVAL; + goto err1; + } + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + r = dpi_basic_init(dssdev); + if (r) + goto err2; + +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL + dss_clk_enable(DSS_CLK_FCK2); + r = dsi_pll_init(dssdev, 0, 1); + if (r) + goto err3; +#endif + r = dpi_set_mode(dssdev); + if (r) + goto err4; + + mdelay(2); + + dispc_enable_lcd_out(1); + + r = dssdev->driver->enable(dssdev); + if (r) + goto err5; + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + + return 0; + +err5: + dispc_enable_lcd_out(0); +err4: +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL + dsi_pll_uninit(); +err3: + dss_clk_disable(DSS_CLK_FCK2); +#endif +err2: + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); +err1: + omap_dss_stop_device(dssdev); +err0: + return r; +} + +static int dpi_display_resume(struct omap_dss_device *dssdev); + +static void dpi_display_disable(struct omap_dss_device *dssdev) +{ + if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED) + return; + + if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) + dpi_display_resume(dssdev); + + dssdev->driver->disable(dssdev); + + dispc_enable_lcd_out(0); + +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL + dss_select_clk_source(0, 0); + dsi_pll_uninit(); + dss_clk_disable(DSS_CLK_FCK2); +#endif + + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + + dssdev->state = OMAP_DSS_DISPLAY_DISABLED; + + omap_dss_stop_device(dssdev); +} + +static int dpi_display_suspend(struct omap_dss_device *dssdev) +{ + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + return -EINVAL; + + DSSDBG("dpi_display_suspend\n"); + + if (dssdev->driver->suspend) + dssdev->driver->suspend(dssdev); + + dispc_enable_lcd_out(0); + + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + + dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; + + return 0; +} + +static int dpi_display_resume(struct omap_dss_device *dssdev) +{ + if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) + return -EINVAL; + + DSSDBG("dpi_display_resume\n"); + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + dispc_enable_lcd_out(1); + + if (dssdev->driver->resume) + dssdev->driver->resume(dssdev); + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + + return 0; +} + +static void dpi_set_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + DSSDBG("dpi_set_timings\n"); + dssdev->panel.timings = *timings; + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { + dpi_set_mode(dssdev); + dispc_go(OMAP_DSS_CHANNEL_LCD); + } +} + +static int dpi_check_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + bool is_tft; + int r; + int lck_div, pck_div; + unsigned long fck; + unsigned long pck; + + if (!dispc_lcd_timings_ok(timings)) + return -EINVAL; + + if (timings->pixel_clock == 0) + return -EINVAL; + + is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; + +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL + { + struct dsi_clock_info dsi_cinfo; + struct dispc_clock_info dispc_cinfo; + r = dsi_pll_calc_clock_div_pck(is_tft, + timings->pixel_clock * 1000, + &dsi_cinfo, &dispc_cinfo); + + if (r) + return r; + + fck = dsi_cinfo.dsi1_pll_fclk; + lck_div = dispc_cinfo.lck_div; + pck_div = dispc_cinfo.pck_div; + } +#else + { + struct dss_clock_info dss_cinfo; + struct dispc_clock_info dispc_cinfo; + r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000, + &dss_cinfo, &dispc_cinfo); + + if (r) + return r; + + fck = dss_cinfo.fck; + lck_div = dispc_cinfo.lck_div; + pck_div = dispc_cinfo.pck_div; + } +#endif + + pck = fck / lck_div / pck_div / 1000; + + timings->pixel_clock = pck; + + return 0; +} + +static void dpi_get_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + *timings = dssdev->panel.timings; +} + +static int dpi_display_set_update_mode(struct omap_dss_device *dssdev, + enum omap_dss_update_mode mode) +{ + if (mode == OMAP_DSS_UPDATE_MANUAL) + return -EINVAL; + + if (mode == OMAP_DSS_UPDATE_DISABLED) { + dispc_enable_lcd_out(0); + dpi.update_enabled = 0; + } else { + dispc_enable_lcd_out(1); + dpi.update_enabled = 1; + } + + return 0; +} + +static enum omap_dss_update_mode dpi_display_get_update_mode( + struct omap_dss_device *dssdev) +{ + return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO : + OMAP_DSS_UPDATE_DISABLED; +} + +int dpi_init_display(struct omap_dss_device *dssdev) +{ + DSSDBG("init_display\n"); + + dssdev->enable = dpi_display_enable; + dssdev->disable = dpi_display_disable; + dssdev->suspend = dpi_display_suspend; + dssdev->resume = dpi_display_resume; + dssdev->set_timings = dpi_set_timings; + dssdev->check_timings = dpi_check_timings; + dssdev->get_timings = dpi_get_timings; + dssdev->set_update_mode = dpi_display_set_update_mode; + dssdev->get_update_mode = dpi_display_get_update_mode; + + return 0; +} + +int dpi_init(void) +{ + return 0; +} + +void dpi_exit(void) +{ +} + diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c new file mode 100644 index 0000000000000000000000000000000000000000..5936487b5defb2155cca33c5cf1205284e3e336a --- /dev/null +++ b/drivers/video/omap2/dss/dsi.c @@ -0,0 +1,3710 @@ +/* + * linux/drivers/video/omap2/dss/dsi.c + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * 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, see . + */ + +#define DSS_SUBSYS_NAME "DSI" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "dss.h" + +/*#define VERBOSE_IRQ*/ +#define DSI_CATCH_MISSING_TE + +#define DSI_BASE 0x4804FC00 + +struct dsi_reg { u16 idx; }; + +#define DSI_REG(idx) ((const struct dsi_reg) { idx }) + +#define DSI_SZ_REGS SZ_1K +/* DSI Protocol Engine */ + +#define DSI_REVISION DSI_REG(0x0000) +#define DSI_SYSCONFIG DSI_REG(0x0010) +#define DSI_SYSSTATUS DSI_REG(0x0014) +#define DSI_IRQSTATUS DSI_REG(0x0018) +#define DSI_IRQENABLE DSI_REG(0x001C) +#define DSI_CTRL DSI_REG(0x0040) +#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048) +#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C) +#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050) +#define DSI_CLK_CTRL DSI_REG(0x0054) +#define DSI_TIMING1 DSI_REG(0x0058) +#define DSI_TIMING2 DSI_REG(0x005C) +#define DSI_VM_TIMING1 DSI_REG(0x0060) +#define DSI_VM_TIMING2 DSI_REG(0x0064) +#define DSI_VM_TIMING3 DSI_REG(0x0068) +#define DSI_CLK_TIMING DSI_REG(0x006C) +#define DSI_TX_FIFO_VC_SIZE DSI_REG(0x0070) +#define DSI_RX_FIFO_VC_SIZE DSI_REG(0x0074) +#define DSI_COMPLEXIO_CFG2 DSI_REG(0x0078) +#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(0x007C) +#define DSI_VM_TIMING4 DSI_REG(0x0080) +#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(0x0084) +#define DSI_VM_TIMING5 DSI_REG(0x0088) +#define DSI_VM_TIMING6 DSI_REG(0x008C) +#define DSI_VM_TIMING7 DSI_REG(0x0090) +#define DSI_STOPCLK_TIMING DSI_REG(0x0094) +#define DSI_VC_CTRL(n) DSI_REG(0x0100 + (n * 0x20)) +#define DSI_VC_TE(n) DSI_REG(0x0104 + (n * 0x20)) +#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(0x0108 + (n * 0x20)) +#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(0x010C + (n * 0x20)) +#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(0x0110 + (n * 0x20)) +#define DSI_VC_IRQSTATUS(n) DSI_REG(0x0118 + (n * 0x20)) +#define DSI_VC_IRQENABLE(n) DSI_REG(0x011C + (n * 0x20)) + +/* DSIPHY_SCP */ + +#define DSI_DSIPHY_CFG0 DSI_REG(0x200 + 0x0000) +#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004) +#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008) +#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014) + +/* DSI_PLL_CTRL_SCP */ + +#define DSI_PLL_CONTROL DSI_REG(0x300 + 0x0000) +#define DSI_PLL_STATUS DSI_REG(0x300 + 0x0004) +#define DSI_PLL_GO DSI_REG(0x300 + 0x0008) +#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C) +#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010) + +#define REG_GET(idx, start, end) \ + FLD_GET(dsi_read_reg(idx), start, end) + +#define REG_FLD_MOD(idx, val, start, end) \ + dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end)) + +/* Global interrupts */ +#define DSI_IRQ_VC0 (1 << 0) +#define DSI_IRQ_VC1 (1 << 1) +#define DSI_IRQ_VC2 (1 << 2) +#define DSI_IRQ_VC3 (1 << 3) +#define DSI_IRQ_WAKEUP (1 << 4) +#define DSI_IRQ_RESYNC (1 << 5) +#define DSI_IRQ_PLL_LOCK (1 << 7) +#define DSI_IRQ_PLL_UNLOCK (1 << 8) +#define DSI_IRQ_PLL_RECALL (1 << 9) +#define DSI_IRQ_COMPLEXIO_ERR (1 << 10) +#define DSI_IRQ_HS_TX_TIMEOUT (1 << 14) +#define DSI_IRQ_LP_RX_TIMEOUT (1 << 15) +#define DSI_IRQ_TE_TRIGGER (1 << 16) +#define DSI_IRQ_ACK_TRIGGER (1 << 17) +#define DSI_IRQ_SYNC_LOST (1 << 18) +#define DSI_IRQ_LDO_POWER_GOOD (1 << 19) +#define DSI_IRQ_TA_TIMEOUT (1 << 20) +#define DSI_IRQ_ERROR_MASK \ + (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ + DSI_IRQ_TA_TIMEOUT) +#define DSI_IRQ_CHANNEL_MASK 0xf + +/* Virtual channel interrupts */ +#define DSI_VC_IRQ_CS (1 << 0) +#define DSI_VC_IRQ_ECC_CORR (1 << 1) +#define DSI_VC_IRQ_PACKET_SENT (1 << 2) +#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3) +#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4) +#define DSI_VC_IRQ_BTA (1 << 5) +#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6) +#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7) +#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8) +#define DSI_VC_IRQ_ERROR_MASK \ + (DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \ + DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \ + DSI_VC_IRQ_FIFO_TX_UDF) + +/* ComplexIO interrupts */ +#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0) +#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1) +#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2) +#define DSI_CIO_IRQ_ERRESC1 (1 << 5) +#define DSI_CIO_IRQ_ERRESC2 (1 << 6) +#define DSI_CIO_IRQ_ERRESC3 (1 << 7) +#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10) +#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11) +#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12) +#define DSI_CIO_IRQ_STATEULPS1 (1 << 15) +#define DSI_CIO_IRQ_STATEULPS2 (1 << 16) +#define DSI_CIO_IRQ_STATEULPS3 (1 << 17) +#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20) +#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21) +#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22) +#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23) +#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24) +#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25) +#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30) +#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31) + +#define DSI_DT_DCS_SHORT_WRITE_0 0x05 +#define DSI_DT_DCS_SHORT_WRITE_1 0x15 +#define DSI_DT_DCS_READ 0x06 +#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37 +#define DSI_DT_NULL_PACKET 0x09 +#define DSI_DT_DCS_LONG_WRITE 0x39 + +#define DSI_DT_RX_ACK_WITH_ERR 0x02 +#define DSI_DT_RX_DCS_LONG_READ 0x1c +#define DSI_DT_RX_SHORT_READ_1 0x21 +#define DSI_DT_RX_SHORT_READ_2 0x22 + +#define FINT_MAX 2100000 +#define FINT_MIN 750000 +#define REGN_MAX (1 << 7) +#define REGM_MAX ((1 << 11) - 1) +#define REGM3_MAX (1 << 4) +#define REGM4_MAX (1 << 4) +#define LP_DIV_MAX ((1 << 13) - 1) + +enum fifo_size { + DSI_FIFO_SIZE_0 = 0, + DSI_FIFO_SIZE_32 = 1, + DSI_FIFO_SIZE_64 = 2, + DSI_FIFO_SIZE_96 = 3, + DSI_FIFO_SIZE_128 = 4, +}; + +enum dsi_vc_mode { + DSI_VC_MODE_L4 = 0, + DSI_VC_MODE_VP, +}; + +struct dsi_update_region { + bool dirty; + u16 x, y, w, h; + struct omap_dss_device *device; +}; + +static struct +{ + void __iomem *base; + + struct dsi_clock_info current_cinfo; + + struct regulator *vdds_dsi_reg; + + struct { + enum dsi_vc_mode mode; + struct omap_dss_device *dssdev; + enum fifo_size fifo_size; + int dest_per; /* destination peripheral 0-3 */ + } vc[4]; + + struct mutex lock; + struct mutex bus_lock; + + unsigned pll_locked; + + struct completion bta_completion; + + struct task_struct *thread; + wait_queue_head_t waitqueue; + + spinlock_t update_lock; + bool framedone_received; + struct dsi_update_region update_region; + struct dsi_update_region active_update_region; + struct completion update_completion; + + enum omap_dss_update_mode user_update_mode; + enum omap_dss_update_mode update_mode; + bool te_enabled; + bool use_ext_te; + +#ifdef DSI_CATCH_MISSING_TE + struct timer_list te_timer; +#endif + + unsigned long cache_req_pck; + unsigned long cache_clk_freq; + struct dsi_clock_info cache_cinfo; + + u32 errors; + spinlock_t errors_lock; +#ifdef DEBUG + ktime_t perf_setup_time; + ktime_t perf_start_time; + ktime_t perf_start_time_auto; + int perf_measure_frames; +#endif + int debug_read; + int debug_write; +} dsi; + +#ifdef DEBUG +static unsigned int dsi_perf; +module_param_named(dsi_perf, dsi_perf, bool, 0644); +#endif + +static inline void dsi_write_reg(const struct dsi_reg idx, u32 val) +{ + __raw_writel(val, dsi.base + idx.idx); +} + +static inline u32 dsi_read_reg(const struct dsi_reg idx) +{ + return __raw_readl(dsi.base + idx.idx); +} + + +void dsi_save_context(void) +{ +} + +void dsi_restore_context(void) +{ +} + +void dsi_bus_lock(void) +{ + mutex_lock(&dsi.bus_lock); +} +EXPORT_SYMBOL(dsi_bus_lock); + +void dsi_bus_unlock(void) +{ + mutex_unlock(&dsi.bus_lock); +} +EXPORT_SYMBOL(dsi_bus_unlock); + +static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, + int value) +{ + int t = 100000; + + while (REG_GET(idx, bitnum, bitnum) != value) { + if (--t == 0) + return !value; + } + + return value; +} + +#ifdef DEBUG +static void dsi_perf_mark_setup(void) +{ + dsi.perf_setup_time = ktime_get(); +} + +static void dsi_perf_mark_start(void) +{ + dsi.perf_start_time = ktime_get(); +} + +static void dsi_perf_mark_start_auto(void) +{ + dsi.perf_measure_frames = 0; + dsi.perf_start_time_auto = ktime_get(); +} + +static void dsi_perf_show(const char *name) +{ + ktime_t t, setup_time, trans_time; + u32 total_bytes; + u32 setup_us, trans_us, total_us; + + if (!dsi_perf) + return; + + if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED) + return; + + t = ktime_get(); + + setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time); + setup_us = (u32)ktime_to_us(setup_time); + if (setup_us == 0) + setup_us = 1; + + trans_time = ktime_sub(t, dsi.perf_start_time); + trans_us = (u32)ktime_to_us(trans_time); + if (trans_us == 0) + trans_us = 1; + + total_us = setup_us + trans_us; + + total_bytes = dsi.active_update_region.w * + dsi.active_update_region.h * + dsi.active_update_region.device->ctrl.pixel_size / 8; + + if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) { + static u32 s_total_trans_us, s_total_setup_us; + static u32 s_min_trans_us = 0xffffffff, s_min_setup_us; + static u32 s_max_trans_us, s_max_setup_us; + const int numframes = 100; + ktime_t total_time_auto; + u32 total_time_auto_us; + + dsi.perf_measure_frames++; + + if (setup_us < s_min_setup_us) + s_min_setup_us = setup_us; + + if (setup_us > s_max_setup_us) + s_max_setup_us = setup_us; + + s_total_setup_us += setup_us; + + if (trans_us < s_min_trans_us) + s_min_trans_us = trans_us; + + if (trans_us > s_max_trans_us) + s_max_trans_us = trans_us; + + s_total_trans_us += trans_us; + + if (dsi.perf_measure_frames < numframes) + return; + + total_time_auto = ktime_sub(t, dsi.perf_start_time_auto); + total_time_auto_us = (u32)ktime_to_us(total_time_auto); + + printk(KERN_INFO "DSI(%s): %u fps, setup %u/%u/%u, " + "trans %u/%u/%u\n", + name, + 1000 * 1000 * numframes / total_time_auto_us, + s_min_setup_us, + s_max_setup_us, + s_total_setup_us / numframes, + s_min_trans_us, + s_max_trans_us, + s_total_trans_us / numframes); + + s_total_setup_us = 0; + s_min_setup_us = 0xffffffff; + s_max_setup_us = 0; + s_total_trans_us = 0; + s_min_trans_us = 0xffffffff; + s_max_trans_us = 0; + dsi_perf_mark_start_auto(); + } else { + printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " + "%u bytes, %u kbytes/sec\n", + name, + setup_us, + trans_us, + total_us, + 1000*1000 / total_us, + total_bytes, + total_bytes * 1000 / total_us); + } +} +#else +#define dsi_perf_mark_setup() +#define dsi_perf_mark_start() +#define dsi_perf_mark_start_auto() +#define dsi_perf_show(x) +#endif + +static void print_irq_status(u32 status) +{ +#ifndef VERBOSE_IRQ + if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0) + return; +#endif + printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status); + +#define PIS(x) \ + if (status & DSI_IRQ_##x) \ + printk(#x " "); +#ifdef VERBOSE_IRQ + PIS(VC0); + PIS(VC1); + PIS(VC2); + PIS(VC3); +#endif + PIS(WAKEUP); + PIS(RESYNC); + PIS(PLL_LOCK); + PIS(PLL_UNLOCK); + PIS(PLL_RECALL); + PIS(COMPLEXIO_ERR); + PIS(HS_TX_TIMEOUT); + PIS(LP_RX_TIMEOUT); + PIS(TE_TRIGGER); + PIS(ACK_TRIGGER); + PIS(SYNC_LOST); + PIS(LDO_POWER_GOOD); + PIS(TA_TIMEOUT); +#undef PIS + + printk("\n"); +} + +static void print_irq_status_vc(int channel, u32 status) +{ +#ifndef VERBOSE_IRQ + if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0) + return; +#endif + printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status); + +#define PIS(x) \ + if (status & DSI_VC_IRQ_##x) \ + printk(#x " "); + PIS(CS); + PIS(ECC_CORR); +#ifdef VERBOSE_IRQ + PIS(PACKET_SENT); +#endif + PIS(FIFO_TX_OVF); + PIS(FIFO_RX_OVF); + PIS(BTA); + PIS(ECC_NO_CORR); + PIS(FIFO_TX_UDF); + PIS(PP_BUSY_CHANGE); +#undef PIS + printk("\n"); +} + +static void print_irq_status_cio(u32 status) +{ + printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status); + +#define PIS(x) \ + if (status & DSI_CIO_IRQ_##x) \ + printk(#x " "); + PIS(ERRSYNCESC1); + PIS(ERRSYNCESC2); + PIS(ERRSYNCESC3); + PIS(ERRESC1); + PIS(ERRESC2); + PIS(ERRESC3); + PIS(ERRCONTROL1); + PIS(ERRCONTROL2); + PIS(ERRCONTROL3); + PIS(STATEULPS1); + PIS(STATEULPS2); + PIS(STATEULPS3); + PIS(ERRCONTENTIONLP0_1); + PIS(ERRCONTENTIONLP1_1); + PIS(ERRCONTENTIONLP0_2); + PIS(ERRCONTENTIONLP1_2); + PIS(ERRCONTENTIONLP0_3); + PIS(ERRCONTENTIONLP1_3); + PIS(ULPSACTIVENOT_ALL0); + PIS(ULPSACTIVENOT_ALL1); +#undef PIS + + printk("\n"); +} + +static int debug_irq; + +/* called from dss */ +void dsi_irq_handler(void) +{ + u32 irqstatus, vcstatus, ciostatus; + int i; + + irqstatus = dsi_read_reg(DSI_IRQSTATUS); + + if (irqstatus & DSI_IRQ_ERROR_MASK) { + DSSERR("DSI error, irqstatus %x\n", irqstatus); + print_irq_status(irqstatus); + spin_lock(&dsi.errors_lock); + dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK; + spin_unlock(&dsi.errors_lock); + } else if (debug_irq) { + print_irq_status(irqstatus); + } + +#ifdef DSI_CATCH_MISSING_TE + if (irqstatus & DSI_IRQ_TE_TRIGGER) + del_timer(&dsi.te_timer); +#endif + + for (i = 0; i < 4; ++i) { + if ((irqstatus & (1<phy.dsi.div.lp_clk_div; + + if (lp_clk_div == 0 || lp_clk_div > LP_DIV_MAX) + return -EINVAL; + + dsi_fclk = dsi_fclk_rate(); + + lp_clk = dsi_fclk / 2 / lp_clk_div; + + DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk); + dsi.current_cinfo.lp_clk = lp_clk; + dsi.current_cinfo.lp_clk_div = lp_clk_div; + + REG_FLD_MOD(DSI_CLK_CTRL, lp_clk_div, 12, 0); /* LP_CLK_DIVISOR */ + + REG_FLD_MOD(DSI_CLK_CTRL, dsi_fclk > 30000000 ? 1 : 0, + 21, 21); /* LP_RX_SYNCHRO_ENABLE */ + + return 0; +} + + +enum dsi_pll_power_state { + DSI_PLL_POWER_OFF = 0x0, + DSI_PLL_POWER_ON_HSCLK = 0x1, + DSI_PLL_POWER_ON_ALL = 0x2, + DSI_PLL_POWER_ON_DIV = 0x3, +}; + +static int dsi_pll_power(enum dsi_pll_power_state state) +{ + int t = 0; + + REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */ + + /* PLL_PWR_STATUS */ + while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) { + udelay(1); + if (t++ > 1000) { + DSSERR("Failed to set DSI PLL power mode to %d\n", + state); + return -ENODEV; + } + } + + return 0; +} + +/* calculate clock rates using dividers in cinfo */ +static int dsi_calc_clock_rates(struct dsi_clock_info *cinfo) +{ + if (cinfo->regn == 0 || cinfo->regn > REGN_MAX) + return -EINVAL; + + if (cinfo->regm == 0 || cinfo->regm > REGM_MAX) + return -EINVAL; + + if (cinfo->regm3 > REGM3_MAX) + return -EINVAL; + + if (cinfo->regm4 > REGM4_MAX) + return -EINVAL; + + if (cinfo->use_dss2_fck) { + cinfo->clkin = dss_clk_get_rate(DSS_CLK_FCK2); + /* XXX it is unclear if highfreq should be used + * with DSS2_FCK source also */ + cinfo->highfreq = 0; + } else { + cinfo->clkin = dispc_pclk_rate(); + + if (cinfo->clkin < 32000000) + cinfo->highfreq = 0; + else + cinfo->highfreq = 1; + } + + cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); + + if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN) + return -EINVAL; + + cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; + + if (cinfo->clkin4ddr > 1800 * 1000 * 1000) + return -EINVAL; + + if (cinfo->regm3 > 0) + cinfo->dsi1_pll_fclk = cinfo->clkin4ddr / cinfo->regm3; + else + cinfo->dsi1_pll_fclk = 0; + + if (cinfo->regm4 > 0) + cinfo->dsi2_pll_fclk = cinfo->clkin4ddr / cinfo->regm4; + else + cinfo->dsi2_pll_fclk = 0; + + return 0; +} + +int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, + struct dsi_clock_info *dsi_cinfo, + struct dispc_clock_info *dispc_cinfo) +{ + struct dsi_clock_info cur, best; + struct dispc_clock_info best_dispc; + int min_fck_per_pck; + int match = 0; + unsigned long dss_clk_fck2; + + dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2); + + if (req_pck == dsi.cache_req_pck && + dsi.cache_cinfo.clkin == dss_clk_fck2) { + DSSDBG("DSI clock info found from cache\n"); + *dsi_cinfo = dsi.cache_cinfo; + dispc_find_clk_divs(is_tft, req_pck, dsi_cinfo->dsi1_pll_fclk, + dispc_cinfo); + return 0; + } + + min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; + + if (min_fck_per_pck && + req_pck * min_fck_per_pck > DISPC_MAX_FCK) { + DSSERR("Requested pixel clock not possible with the current " + "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " + "the constraint off.\n"); + min_fck_per_pck = 0; + } + + DSSDBG("dsi_pll_calc\n"); + +retry: + memset(&best, 0, sizeof(best)); + memset(&best_dispc, 0, sizeof(best_dispc)); + + memset(&cur, 0, sizeof(cur)); + cur.clkin = dss_clk_fck2; + cur.use_dss2_fck = 1; + cur.highfreq = 0; + + /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ + /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ + /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ + for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) { + if (cur.highfreq == 0) + cur.fint = cur.clkin / cur.regn; + else + cur.fint = cur.clkin / (2 * cur.regn); + + if (cur.fint > FINT_MAX || cur.fint < FINT_MIN) + continue; + + /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ + for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) { + unsigned long a, b; + + a = 2 * cur.regm * (cur.clkin/1000); + b = cur.regn * (cur.highfreq + 1); + cur.clkin4ddr = a / b * 1000; + + if (cur.clkin4ddr > 1800 * 1000 * 1000) + break; + + /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */ + for (cur.regm3 = 1; cur.regm3 < REGM3_MAX; + ++cur.regm3) { + struct dispc_clock_info cur_dispc; + cur.dsi1_pll_fclk = cur.clkin4ddr / cur.regm3; + + /* this will narrow down the search a bit, + * but still give pixclocks below what was + * requested */ + if (cur.dsi1_pll_fclk < req_pck) + break; + + if (cur.dsi1_pll_fclk > DISPC_MAX_FCK) + continue; + + if (min_fck_per_pck && + cur.dsi1_pll_fclk < + req_pck * min_fck_per_pck) + continue; + + match = 1; + + dispc_find_clk_divs(is_tft, req_pck, + cur.dsi1_pll_fclk, + &cur_dispc); + + if (abs(cur_dispc.pck - req_pck) < + abs(best_dispc.pck - req_pck)) { + best = cur; + best_dispc = cur_dispc; + + if (cur_dispc.pck == req_pck) + goto found; + } + } + } + } +found: + if (!match) { + if (min_fck_per_pck) { + DSSERR("Could not find suitable clock settings.\n" + "Turning FCK/PCK constraint off and" + "trying again.\n"); + min_fck_per_pck = 0; + goto retry; + } + + DSSERR("Could not find suitable clock settings.\n"); + + return -EINVAL; + } + + /* DSI2_PLL_FCLK (regm4) is not used */ + best.regm4 = 0; + best.dsi2_pll_fclk = 0; + + if (dsi_cinfo) + *dsi_cinfo = best; + if (dispc_cinfo) + *dispc_cinfo = best_dispc; + + dsi.cache_req_pck = req_pck; + dsi.cache_clk_freq = 0; + dsi.cache_cinfo = best; + + return 0; +} + +int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) +{ + int r = 0; + u32 l; + int f; + + DSSDBGF(); + + dsi.current_cinfo.fint = cinfo->fint; + dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr; + dsi.current_cinfo.dsi1_pll_fclk = cinfo->dsi1_pll_fclk; + dsi.current_cinfo.dsi2_pll_fclk = cinfo->dsi2_pll_fclk; + + dsi.current_cinfo.regn = cinfo->regn; + dsi.current_cinfo.regm = cinfo->regm; + dsi.current_cinfo.regm3 = cinfo->regm3; + dsi.current_cinfo.regm4 = cinfo->regm4; + + DSSDBG("DSI Fint %ld\n", cinfo->fint); + + DSSDBG("clkin (%s) rate %ld, highfreq %d\n", + cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree", + cinfo->clkin, + cinfo->highfreq); + + /* DSIPHY == CLKIN4DDR */ + DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu / %d = %lu\n", + cinfo->regm, + cinfo->regn, + cinfo->clkin, + cinfo->highfreq + 1, + cinfo->clkin4ddr); + + DSSDBG("Data rate on 1 DSI lane %ld Mbps\n", + cinfo->clkin4ddr / 1000 / 1000 / 2); + + DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); + + DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n", + cinfo->regm3, cinfo->dsi1_pll_fclk); + DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n", + cinfo->regm4, cinfo->dsi2_pll_fclk); + + REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ + + l = dsi_read_reg(DSI_PLL_CONFIGURATION1); + l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ + l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */ + l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */ + l = FLD_MOD(l, cinfo->regm3 > 0 ? cinfo->regm3 - 1 : 0, + 22, 19); /* DSI_CLOCK_DIV */ + l = FLD_MOD(l, cinfo->regm4 > 0 ? cinfo->regm4 - 1 : 0, + 26, 23); /* DSIPROTO_CLOCK_DIV */ + dsi_write_reg(DSI_PLL_CONFIGURATION1, l); + + BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000); + if (cinfo->fint < 1000000) + f = 0x3; + else if (cinfo->fint < 1250000) + f = 0x4; + else if (cinfo->fint < 1500000) + f = 0x5; + else if (cinfo->fint < 1750000) + f = 0x6; + else + f = 0x7; + + l = dsi_read_reg(DSI_PLL_CONFIGURATION2); + l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ + l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, + 11, 11); /* DSI_PLL_CLKSEL */ + l = FLD_MOD(l, cinfo->highfreq, + 12, 12); /* DSI_PLL_HIGHFREQ */ + l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ + l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ + l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ + dsi_write_reg(DSI_PLL_CONFIGURATION2, l); + + REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */ + + if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) { + DSSERR("dsi pll go bit not going down.\n"); + r = -EIO; + goto err; + } + + if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) { + DSSERR("cannot lock PLL\n"); + r = -EIO; + goto err; + } + + dsi.pll_locked = 1; + + l = dsi_read_reg(DSI_PLL_CONFIGURATION2); + l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */ + l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */ + l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */ + l = FLD_MOD(l, 0, 7, 7); /* DSI_PLL_TIGHTPHASELOCK */ + l = FLD_MOD(l, 0, 8, 8); /* DSI_PLL_DRIFTGUARDEN */ + l = FLD_MOD(l, 0, 10, 9); /* DSI_PLL_LOCKSEL */ + l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ + l = FLD_MOD(l, 1, 14, 14); /* DSIPHY_CLKINEN */ + l = FLD_MOD(l, 0, 15, 15); /* DSI_BYPASSEN */ + l = FLD_MOD(l, 1, 16, 16); /* DSS_CLOCK_EN */ + l = FLD_MOD(l, 0, 17, 17); /* DSS_CLOCK_PWDN */ + l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */ + l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */ + l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */ + dsi_write_reg(DSI_PLL_CONFIGURATION2, l); + + DSSDBG("PLL config done\n"); +err: + return r; +} + +int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, + bool enable_hsdiv) +{ + int r = 0; + enum dsi_pll_power_state pwstate; + + DSSDBG("PLL init\n"); + + enable_clocks(1); + dsi_enable_pll_clock(1); + + r = regulator_enable(dsi.vdds_dsi_reg); + if (r) + goto err0; + + /* XXX PLL does not come out of reset without this... */ + dispc_pck_free_enable(1); + + if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) { + DSSERR("PLL not coming out of reset.\n"); + r = -ENODEV; + goto err1; + } + + /* XXX ... but if left on, we get problems when planes do not + * fill the whole display. No idea about this */ + dispc_pck_free_enable(0); + + if (enable_hsclk && enable_hsdiv) + pwstate = DSI_PLL_POWER_ON_ALL; + else if (enable_hsclk) + pwstate = DSI_PLL_POWER_ON_HSCLK; + else if (enable_hsdiv) + pwstate = DSI_PLL_POWER_ON_DIV; + else + pwstate = DSI_PLL_POWER_OFF; + + r = dsi_pll_power(pwstate); + + if (r) + goto err1; + + DSSDBG("PLL init done\n"); + + return 0; +err1: + regulator_disable(dsi.vdds_dsi_reg); +err0: + enable_clocks(0); + dsi_enable_pll_clock(0); + return r; +} + +void dsi_pll_uninit(void) +{ + enable_clocks(0); + dsi_enable_pll_clock(0); + + dsi.pll_locked = 0; + dsi_pll_power(DSI_PLL_POWER_OFF); + regulator_disable(dsi.vdds_dsi_reg); + DSSDBG("PLL uninit done\n"); +} + +void dsi_dump_clocks(struct seq_file *s) +{ + int clksel; + struct dsi_clock_info *cinfo = &dsi.current_cinfo; + + enable_clocks(1); + + clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11); + + seq_printf(s, "- DSI PLL -\n"); + + seq_printf(s, "dsi pll source = %s\n", + clksel == 0 ? + "dss2_alwon_fclk" : "pclkfree"); + + seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); + + seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", + cinfo->clkin4ddr, cinfo->regm); + + seq_printf(s, "dsi1_pll_fck\t%-16luregm3 %u\t(%s)\n", + cinfo->dsi1_pll_fclk, + cinfo->regm3, + dss_get_dispc_clk_source() == 0 ? "off" : "on"); + + seq_printf(s, "dsi2_pll_fck\t%-16luregm4 %u\t(%s)\n", + cinfo->dsi2_pll_fclk, + cinfo->regm4, + dss_get_dsi_clk_source() == 0 ? "off" : "on"); + + seq_printf(s, "- DSI -\n"); + + seq_printf(s, "dsi fclk source = %s\n", + dss_get_dsi_clk_source() == 0 ? + "dss1_alwon_fclk" : "dsi2_pll_fclk"); + + seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate()); + + seq_printf(s, "DDR_CLK\t\t%lu\n", + cinfo->clkin4ddr / 4); + + seq_printf(s, "TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs()); + + seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk); + + seq_printf(s, "VP_CLK\t\t%lu\n" + "VP_PCLK\t\t%lu\n", + dispc_lclk_rate(), + dispc_pclk_rate()); + + enable_clocks(0); +} + +void dsi_dump_regs(struct seq_file *s) +{ +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + DUMPREG(DSI_REVISION); + DUMPREG(DSI_SYSCONFIG); + DUMPREG(DSI_SYSSTATUS); + DUMPREG(DSI_IRQSTATUS); + DUMPREG(DSI_IRQENABLE); + DUMPREG(DSI_CTRL); + DUMPREG(DSI_COMPLEXIO_CFG1); + DUMPREG(DSI_COMPLEXIO_IRQ_STATUS); + DUMPREG(DSI_COMPLEXIO_IRQ_ENABLE); + DUMPREG(DSI_CLK_CTRL); + DUMPREG(DSI_TIMING1); + DUMPREG(DSI_TIMING2); + DUMPREG(DSI_VM_TIMING1); + DUMPREG(DSI_VM_TIMING2); + DUMPREG(DSI_VM_TIMING3); + DUMPREG(DSI_CLK_TIMING); + DUMPREG(DSI_TX_FIFO_VC_SIZE); + DUMPREG(DSI_RX_FIFO_VC_SIZE); + DUMPREG(DSI_COMPLEXIO_CFG2); + DUMPREG(DSI_RX_FIFO_VC_FULLNESS); + DUMPREG(DSI_VM_TIMING4); + DUMPREG(DSI_TX_FIFO_VC_EMPTINESS); + DUMPREG(DSI_VM_TIMING5); + DUMPREG(DSI_VM_TIMING6); + DUMPREG(DSI_VM_TIMING7); + DUMPREG(DSI_STOPCLK_TIMING); + + DUMPREG(DSI_VC_CTRL(0)); + DUMPREG(DSI_VC_TE(0)); + DUMPREG(DSI_VC_LONG_PACKET_HEADER(0)); + DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(0)); + DUMPREG(DSI_VC_SHORT_PACKET_HEADER(0)); + DUMPREG(DSI_VC_IRQSTATUS(0)); + DUMPREG(DSI_VC_IRQENABLE(0)); + + DUMPREG(DSI_VC_CTRL(1)); + DUMPREG(DSI_VC_TE(1)); + DUMPREG(DSI_VC_LONG_PACKET_HEADER(1)); + DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(1)); + DUMPREG(DSI_VC_SHORT_PACKET_HEADER(1)); + DUMPREG(DSI_VC_IRQSTATUS(1)); + DUMPREG(DSI_VC_IRQENABLE(1)); + + DUMPREG(DSI_VC_CTRL(2)); + DUMPREG(DSI_VC_TE(2)); + DUMPREG(DSI_VC_LONG_PACKET_HEADER(2)); + DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(2)); + DUMPREG(DSI_VC_SHORT_PACKET_HEADER(2)); + DUMPREG(DSI_VC_IRQSTATUS(2)); + DUMPREG(DSI_VC_IRQENABLE(2)); + + DUMPREG(DSI_VC_CTRL(3)); + DUMPREG(DSI_VC_TE(3)); + DUMPREG(DSI_VC_LONG_PACKET_HEADER(3)); + DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(3)); + DUMPREG(DSI_VC_SHORT_PACKET_HEADER(3)); + DUMPREG(DSI_VC_IRQSTATUS(3)); + DUMPREG(DSI_VC_IRQENABLE(3)); + + DUMPREG(DSI_DSIPHY_CFG0); + DUMPREG(DSI_DSIPHY_CFG1); + DUMPREG(DSI_DSIPHY_CFG2); + DUMPREG(DSI_DSIPHY_CFG5); + + DUMPREG(DSI_PLL_CONTROL); + DUMPREG(DSI_PLL_STATUS); + DUMPREG(DSI_PLL_GO); + DUMPREG(DSI_PLL_CONFIGURATION1); + DUMPREG(DSI_PLL_CONFIGURATION2); + + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); +#undef DUMPREG +} + +enum dsi_complexio_power_state { + DSI_COMPLEXIO_POWER_OFF = 0x0, + DSI_COMPLEXIO_POWER_ON = 0x1, + DSI_COMPLEXIO_POWER_ULPS = 0x2, +}; + +static int dsi_complexio_power(enum dsi_complexio_power_state state) +{ + int t = 0; + + /* PWR_CMD */ + REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27); + + /* PWR_STATUS */ + while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) { + udelay(1); + if (t++ > 1000) { + DSSERR("failed to set complexio power state to " + "%d\n", state); + return -ENODEV; + } + } + + return 0; +} + +static void dsi_complexio_config(struct omap_dss_device *dssdev) +{ + u32 r; + + int clk_lane = dssdev->phy.dsi.clk_lane; + int data1_lane = dssdev->phy.dsi.data1_lane; + int data2_lane = dssdev->phy.dsi.data2_lane; + int clk_pol = dssdev->phy.dsi.clk_pol; + int data1_pol = dssdev->phy.dsi.data1_pol; + int data2_pol = dssdev->phy.dsi.data2_pol; + + r = dsi_read_reg(DSI_COMPLEXIO_CFG1); + r = FLD_MOD(r, clk_lane, 2, 0); + r = FLD_MOD(r, clk_pol, 3, 3); + r = FLD_MOD(r, data1_lane, 6, 4); + r = FLD_MOD(r, data1_pol, 7, 7); + r = FLD_MOD(r, data2_lane, 10, 8); + r = FLD_MOD(r, data2_pol, 11, 11); + dsi_write_reg(DSI_COMPLEXIO_CFG1, r); + + /* The configuration of the DSI complex I/O (number of data lanes, + position, differential order) should not be changed while + DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for + the hardware to take into account a new configuration of the complex + I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to + follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, + then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set + DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the + DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the + DSI complex I/O configuration is unknown. */ + + /* + REG_FLD_MOD(DSI_CTRL, 1, 0, 0); + REG_FLD_MOD(DSI_CTRL, 0, 0, 0); + REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); + REG_FLD_MOD(DSI_CTRL, 1, 0, 0); + */ +} + +static inline unsigned ns2ddr(unsigned ns) +{ + /* convert time in ns to ddr ticks, rounding up */ + unsigned long ddr_clk = dsi.current_cinfo.clkin4ddr / 4; + return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000; +} + +static inline unsigned ddr2ns(unsigned ddr) +{ + unsigned long ddr_clk = dsi.current_cinfo.clkin4ddr / 4; + return ddr * 1000 * 1000 / (ddr_clk / 1000); +} + +static void dsi_complexio_timings(void) +{ + u32 r; + u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit; + u32 tlpx_half, tclk_trail, tclk_zero; + u32 tclk_prepare; + + /* calculate timings */ + + /* 1 * DDR_CLK = 2 * UI */ + + /* min 40ns + 4*UI max 85ns + 6*UI */ + ths_prepare = ns2ddr(70) + 2; + + /* min 145ns + 10*UI */ + ths_prepare_ths_zero = ns2ddr(175) + 2; + + /* min max(8*UI, 60ns+4*UI) */ + ths_trail = ns2ddr(60) + 5; + + /* min 100ns */ + ths_exit = ns2ddr(145); + + /* tlpx min 50n */ + tlpx_half = ns2ddr(25); + + /* min 60ns */ + tclk_trail = ns2ddr(60) + 2; + + /* min 38ns, max 95ns */ + tclk_prepare = ns2ddr(65); + + /* min tclk-prepare + tclk-zero = 300ns */ + tclk_zero = ns2ddr(260); + + DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n", + ths_prepare, ddr2ns(ths_prepare), + ths_prepare_ths_zero, ddr2ns(ths_prepare_ths_zero)); + DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n", + ths_trail, ddr2ns(ths_trail), + ths_exit, ddr2ns(ths_exit)); + + DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), " + "tclk_zero %u (%uns)\n", + tlpx_half, ddr2ns(tlpx_half), + tclk_trail, ddr2ns(tclk_trail), + tclk_zero, ddr2ns(tclk_zero)); + DSSDBG("tclk_prepare %u (%uns)\n", + tclk_prepare, ddr2ns(tclk_prepare)); + + /* program timings */ + + r = dsi_read_reg(DSI_DSIPHY_CFG0); + r = FLD_MOD(r, ths_prepare, 31, 24); + r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16); + r = FLD_MOD(r, ths_trail, 15, 8); + r = FLD_MOD(r, ths_exit, 7, 0); + dsi_write_reg(DSI_DSIPHY_CFG0, r); + + r = dsi_read_reg(DSI_DSIPHY_CFG1); + r = FLD_MOD(r, tlpx_half, 22, 16); + r = FLD_MOD(r, tclk_trail, 15, 8); + r = FLD_MOD(r, tclk_zero, 7, 0); + dsi_write_reg(DSI_DSIPHY_CFG1, r); + + r = dsi_read_reg(DSI_DSIPHY_CFG2); + r = FLD_MOD(r, tclk_prepare, 7, 0); + dsi_write_reg(DSI_DSIPHY_CFG2, r); +} + + +static int dsi_complexio_init(struct omap_dss_device *dssdev) +{ + int r = 0; + + DSSDBG("dsi_complexio_init\n"); + + /* CIO_CLK_ICG, enable L3 clk to CIO */ + REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14); + + /* A dummy read using the SCP interface to any DSIPHY register is + * required after DSIPHY reset to complete the reset of the DSI complex + * I/O. */ + dsi_read_reg(DSI_DSIPHY_CFG5); + + if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) { + DSSERR("ComplexIO PHY not coming out of reset.\n"); + r = -ENODEV; + goto err; + } + + dsi_complexio_config(dssdev); + + r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON); + + if (r) + goto err; + + if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) { + DSSERR("ComplexIO not coming out of reset.\n"); + r = -ENODEV; + goto err; + } + + if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) { + DSSERR("ComplexIO LDO power down.\n"); + r = -ENODEV; + goto err; + } + + dsi_complexio_timings(); + + /* + The configuration of the DSI complex I/O (number of data lanes, + position, differential order) should not be changed while + DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the + hardware to recognize a new configuration of the complex I/O (done + in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow + this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next + reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20] + LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN + bit to 1. If the sequence is not followed, the DSi complex I/O + configuration is undetermined. + */ + dsi_if_enable(1); + dsi_if_enable(0); + REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */ + dsi_if_enable(1); + dsi_if_enable(0); + + DSSDBG("CIO init done\n"); +err: + return r; +} + +static void dsi_complexio_uninit(void) +{ + dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF); +} + +static int _dsi_wait_reset(void) +{ + int i = 0; + + while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) { + if (i++ > 5) { + DSSERR("soft reset failed\n"); + return -ENODEV; + } + udelay(1); + } + + return 0; +} + +static int _dsi_reset(void) +{ + /* Soft reset */ + REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1); + return _dsi_wait_reset(); +} + +static void dsi_reset_tx_fifo(int channel) +{ + u32 mask; + u32 l; + + /* set fifosize of the channel to 0, then return the old size */ + l = dsi_read_reg(DSI_TX_FIFO_VC_SIZE); + + mask = FLD_MASK((8 * channel) + 7, (8 * channel) + 4); + dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l & ~mask); + + dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l); +} + +static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, + enum fifo_size size3, enum fifo_size size4) +{ + u32 r = 0; + int add = 0; + int i; + + dsi.vc[0].fifo_size = size1; + dsi.vc[1].fifo_size = size2; + dsi.vc[2].fifo_size = size3; + dsi.vc[3].fifo_size = size4; + + for (i = 0; i < 4; i++) { + u8 v; + int size = dsi.vc[i].fifo_size; + + if (add + size > 4) { + DSSERR("Illegal FIFO configuration\n"); + BUG(); + } + + v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); + r |= v << (8 * i); + /*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */ + add += size; + } + + dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r); +} + +static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2, + enum fifo_size size3, enum fifo_size size4) +{ + u32 r = 0; + int add = 0; + int i; + + dsi.vc[0].fifo_size = size1; + dsi.vc[1].fifo_size = size2; + dsi.vc[2].fifo_size = size3; + dsi.vc[3].fifo_size = size4; + + for (i = 0; i < 4; i++) { + u8 v; + int size = dsi.vc[i].fifo_size; + + if (add + size > 4) { + DSSERR("Illegal FIFO configuration\n"); + BUG(); + } + + v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); + r |= v << (8 * i); + /*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */ + add += size; + } + + dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r); +} + +static int dsi_force_tx_stop_mode_io(void) +{ + u32 r; + + r = dsi_read_reg(DSI_TIMING1); + r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ + dsi_write_reg(DSI_TIMING1, r); + + if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) { + DSSERR("TX_STOP bit not going down\n"); + return -EIO; + } + + return 0; +} + +static void dsi_vc_print_status(int channel) +{ + u32 r; + + r = dsi_read_reg(DSI_VC_CTRL(channel)); + DSSDBG("vc %d: TX_FIFO_NOT_EMPTY %d, BTA_EN %d, VC_BUSY %d, " + "TX_FIFO_FULL %d, RX_FIFO_NOT_EMPTY %d, ", + channel, + FLD_GET(r, 5, 5), + FLD_GET(r, 6, 6), + FLD_GET(r, 15, 15), + FLD_GET(r, 16, 16), + FLD_GET(r, 20, 20)); + + r = dsi_read_reg(DSI_TX_FIFO_VC_EMPTINESS); + DSSDBG("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff); +} + +static int dsi_vc_enable(int channel, bool enable) +{ + if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO) + DSSDBG("dsi_vc_enable channel %d, enable %d\n", + channel, enable); + + enable = enable ? 1 : 0; + + REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0); + + if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) { + DSSERR("Failed to set dsi_vc_enable to %d\n", enable); + return -EIO; + } + + return 0; +} + +static void dsi_vc_initial_config(int channel) +{ + u32 r; + + DSSDBGF("%d", channel); + + r = dsi_read_reg(DSI_VC_CTRL(channel)); + + if (FLD_GET(r, 15, 15)) /* VC_BUSY */ + DSSERR("VC(%d) busy when trying to configure it!\n", + channel); + + r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */ + r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */ + r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */ + r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */ + r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */ + r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */ + r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */ + + r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */ + r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ + + dsi_write_reg(DSI_VC_CTRL(channel), r); + + dsi.vc[channel].mode = DSI_VC_MODE_L4; +} + +static void dsi_vc_config_l4(int channel) +{ + if (dsi.vc[channel].mode == DSI_VC_MODE_L4) + return; + + DSSDBGF("%d", channel); + + dsi_vc_enable(channel, 0); + + if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */ + DSSERR("vc(%d) busy when trying to config for L4\n", channel); + + REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ + + dsi_vc_enable(channel, 1); + + dsi.vc[channel].mode = DSI_VC_MODE_L4; +} + +static void dsi_vc_config_vp(int channel) +{ + if (dsi.vc[channel].mode == DSI_VC_MODE_VP) + return; + + DSSDBGF("%d", channel); + + dsi_vc_enable(channel, 0); + + if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */ + DSSERR("vc(%d) busy when trying to config for VP\n", channel); + + REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */ + + dsi_vc_enable(channel, 1); + + dsi.vc[channel].mode = DSI_VC_MODE_VP; +} + + +static void dsi_vc_enable_hs(int channel, bool enable) +{ + DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); + + dsi_vc_enable(channel, 0); + dsi_if_enable(0); + + REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9); + + dsi_vc_enable(channel, 1); + dsi_if_enable(1); + + dsi_force_tx_stop_mode_io(); +} + +static void dsi_vc_flush_long_data(int channel) +{ + while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { + u32 val; + val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); + DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n", + (val >> 0) & 0xff, + (val >> 8) & 0xff, + (val >> 16) & 0xff, + (val >> 24) & 0xff); + } +} + +static void dsi_show_rx_ack_with_err(u16 err) +{ + DSSERR("\tACK with ERROR (%#x):\n", err); + if (err & (1 << 0)) + DSSERR("\t\tSoT Error\n"); + if (err & (1 << 1)) + DSSERR("\t\tSoT Sync Error\n"); + if (err & (1 << 2)) + DSSERR("\t\tEoT Sync Error\n"); + if (err & (1 << 3)) + DSSERR("\t\tEscape Mode Entry Command Error\n"); + if (err & (1 << 4)) + DSSERR("\t\tLP Transmit Sync Error\n"); + if (err & (1 << 5)) + DSSERR("\t\tHS Receive Timeout Error\n"); + if (err & (1 << 6)) + DSSERR("\t\tFalse Control Error\n"); + if (err & (1 << 7)) + DSSERR("\t\t(reserved7)\n"); + if (err & (1 << 8)) + DSSERR("\t\tECC Error, single-bit (corrected)\n"); + if (err & (1 << 9)) + DSSERR("\t\tECC Error, multi-bit (not corrected)\n"); + if (err & (1 << 10)) + DSSERR("\t\tChecksum Error\n"); + if (err & (1 << 11)) + DSSERR("\t\tData type not recognized\n"); + if (err & (1 << 12)) + DSSERR("\t\tInvalid VC ID\n"); + if (err & (1 << 13)) + DSSERR("\t\tInvalid Transmission Length\n"); + if (err & (1 << 14)) + DSSERR("\t\t(reserved14)\n"); + if (err & (1 << 15)) + DSSERR("\t\tDSI Protocol Violation\n"); +} + +static u16 dsi_vc_flush_receive_data(int channel) +{ + /* RX_FIFO_NOT_EMPTY */ + while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { + u32 val; + u8 dt; + val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); + DSSDBG("\trawval %#08x\n", val); + dt = FLD_GET(val, 5, 0); + if (dt == DSI_DT_RX_ACK_WITH_ERR) { + u16 err = FLD_GET(val, 23, 8); + dsi_show_rx_ack_with_err(err); + } else if (dt == DSI_DT_RX_SHORT_READ_1) { + DSSDBG("\tDCS short response, 1 byte: %#x\n", + FLD_GET(val, 23, 8)); + } else if (dt == DSI_DT_RX_SHORT_READ_2) { + DSSDBG("\tDCS short response, 2 byte: %#x\n", + FLD_GET(val, 23, 8)); + } else if (dt == DSI_DT_RX_DCS_LONG_READ) { + DSSDBG("\tDCS long response, len %d\n", + FLD_GET(val, 23, 8)); + dsi_vc_flush_long_data(channel); + } else { + DSSERR("\tunknown datatype 0x%02x\n", dt); + } + } + return 0; +} + +static int dsi_vc_send_bta(int channel) +{ + if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO && + (dsi.debug_write || dsi.debug_read)) + DSSDBG("dsi_vc_send_bta %d\n", channel); + + WARN_ON(!mutex_is_locked(&dsi.bus_lock)); + + if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */ + DSSERR("rx fifo not empty when sending BTA, dumping data:\n"); + dsi_vc_flush_receive_data(channel); + } + + REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */ + + return 0; +} + +int dsi_vc_send_bta_sync(int channel) +{ + int r = 0; + u32 err; + + INIT_COMPLETION(dsi.bta_completion); + + dsi_vc_enable_bta_irq(channel); + + r = dsi_vc_send_bta(channel); + if (r) + goto err; + + if (wait_for_completion_timeout(&dsi.bta_completion, + msecs_to_jiffies(500)) == 0) { + DSSERR("Failed to receive BTA\n"); + r = -EIO; + goto err; + } + + err = dsi_get_errors(); + if (err) { + DSSERR("Error while sending BTA: %x\n", err); + r = -EIO; + goto err; + } +err: + dsi_vc_disable_bta_irq(channel); + + return r; +} +EXPORT_SYMBOL(dsi_vc_send_bta_sync); + +static inline void dsi_vc_write_long_header(int channel, u8 data_type, + u16 len, u8 ecc) +{ + u32 val; + u8 data_id; + + WARN_ON(!mutex_is_locked(&dsi.bus_lock)); + + /*data_id = data_type | channel << 6; */ + data_id = data_type | dsi.vc[channel].dest_per << 6; + + val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | + FLD_VAL(ecc, 31, 24); + + dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val); +} + +static inline void dsi_vc_write_long_payload(int channel, + u8 b1, u8 b2, u8 b3, u8 b4) +{ + u32 val; + + val = b4 << 24 | b3 << 16 | b2 << 8 | b1 << 0; + +/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n", + b1, b2, b3, b4, val); */ + + dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val); +} + +static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len, + u8 ecc) +{ + /*u32 val; */ + int i; + u8 *p; + int r = 0; + u8 b1, b2, b3, b4; + + if (dsi.debug_write) + DSSDBG("dsi_vc_send_long, %d bytes\n", len); + + /* len + header */ + if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) { + DSSERR("unable to send long packet: packet too long.\n"); + return -EINVAL; + } + + dsi_vc_config_l4(channel); + + dsi_vc_write_long_header(channel, data_type, len, ecc); + + /*dsi_vc_print_status(0); */ + + p = data; + for (i = 0; i < len >> 2; i++) { + if (dsi.debug_write) + DSSDBG("\tsending full packet %d\n", i); + /*dsi_vc_print_status(0); */ + + b1 = *p++; + b2 = *p++; + b3 = *p++; + b4 = *p++; + + dsi_vc_write_long_payload(channel, b1, b2, b3, b4); + } + + i = len % 4; + if (i) { + b1 = 0; b2 = 0; b3 = 0; + + if (dsi.debug_write) + DSSDBG("\tsending remainder bytes %d\n", i); + + switch (i) { + case 3: + b1 = *p++; + b2 = *p++; + b3 = *p++; + break; + case 2: + b1 = *p++; + b2 = *p++; + break; + case 1: + b1 = *p++; + break; + } + + dsi_vc_write_long_payload(channel, b1, b2, b3, 0); + } + + return r; +} + +static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc) +{ + u32 r; + u8 data_id; + + WARN_ON(!mutex_is_locked(&dsi.bus_lock)); + + if (dsi.debug_write) + DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n", + channel, + data_type, data & 0xff, (data >> 8) & 0xff); + + dsi_vc_config_l4(channel); + + if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) { + DSSERR("ERROR FIFO FULL, aborting transfer\n"); + return -EINVAL; + } + + data_id = data_type | channel << 6; + + r = (data_id << 0) | (data << 8) | (ecc << 24); + + dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r); + + return 0; +} + +int dsi_vc_send_null(int channel) +{ + u8 nullpkg[] = {0, 0, 0, 0}; + return dsi_vc_send_long(0, DSI_DT_NULL_PACKET, nullpkg, 4, 0); +} +EXPORT_SYMBOL(dsi_vc_send_null); + +int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len) +{ + int r; + + BUG_ON(len == 0); + + if (len == 1) { + r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0, + data[0], 0); + } else if (len == 2) { + r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1, + data[0] | (data[1] << 8), 0); + } else { + /* 0x39 = DCS Long Write */ + r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE, + data, len, 0); + } + + return r; +} +EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); + +int dsi_vc_dcs_write(int channel, u8 *data, int len) +{ + int r; + + r = dsi_vc_dcs_write_nosync(channel, data, len); + if (r) + return r; + + r = dsi_vc_send_bta_sync(channel); + + return r; +} +EXPORT_SYMBOL(dsi_vc_dcs_write); + +int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) +{ + u32 val; + u8 dt; + int r; + + if (dsi.debug_read) + DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %u)\n", channel, dcs_cmd); + + r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0); + if (r) + return r; + + r = dsi_vc_send_bta_sync(channel); + if (r) + return r; + + /* RX_FIFO_NOT_EMPTY */ + if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) { + DSSERR("RX fifo empty when trying to read.\n"); + return -EIO; + } + + val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); + if (dsi.debug_read) + DSSDBG("\theader: %08x\n", val); + dt = FLD_GET(val, 5, 0); + if (dt == DSI_DT_RX_ACK_WITH_ERR) { + u16 err = FLD_GET(val, 23, 8); + dsi_show_rx_ack_with_err(err); + return -EIO; + + } else if (dt == DSI_DT_RX_SHORT_READ_1) { + u8 data = FLD_GET(val, 15, 8); + if (dsi.debug_read) + DSSDBG("\tDCS short response, 1 byte: %02x\n", data); + + if (buflen < 1) + return -EIO; + + buf[0] = data; + + return 1; + } else if (dt == DSI_DT_RX_SHORT_READ_2) { + u16 data = FLD_GET(val, 23, 8); + if (dsi.debug_read) + DSSDBG("\tDCS short response, 2 byte: %04x\n", data); + + if (buflen < 2) + return -EIO; + + buf[0] = data & 0xff; + buf[1] = (data >> 8) & 0xff; + + return 2; + } else if (dt == DSI_DT_RX_DCS_LONG_READ) { + int w; + int len = FLD_GET(val, 23, 8); + if (dsi.debug_read) + DSSDBG("\tDCS long response, len %d\n", len); + + if (len > buflen) + return -EIO; + + /* two byte checksum ends the packet, not included in len */ + for (w = 0; w < len + 2;) { + int b; + val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); + if (dsi.debug_read) + DSSDBG("\t\t%02x %02x %02x %02x\n", + (val >> 0) & 0xff, + (val >> 8) & 0xff, + (val >> 16) & 0xff, + (val >> 24) & 0xff); + + for (b = 0; b < 4; ++b) { + if (w < len) + buf[w] = (val >> (b * 8)) & 0xff; + /* we discard the 2 byte checksum */ + ++w; + } + } + + return len; + + } else { + DSSERR("\tunknown datatype 0x%02x\n", dt); + return -EIO; + } +} +EXPORT_SYMBOL(dsi_vc_dcs_read); + + +int dsi_vc_set_max_rx_packet_size(int channel, u16 len) +{ + int r; + r = dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE, + len, 0); + + if (r) + return r; + + r = dsi_vc_send_bta_sync(channel); + + return r; +} +EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); + +static void dsi_set_lp_rx_timeout(unsigned long ns) +{ + u32 r; + unsigned x4, x16; + unsigned long fck; + unsigned long ticks; + + /* ticks in DSI_FCK */ + + fck = dsi_fclk_rate(); + ticks = (fck / 1000 / 1000) * ns / 1000; + x4 = 0; + x16 = 0; + + if (ticks > 0x1fff) { + ticks = (fck / 1000 / 1000) * ns / 1000 / 4; + x4 = 1; + x16 = 0; + } + + if (ticks > 0x1fff) { + ticks = (fck / 1000 / 1000) * ns / 1000 / 16; + x4 = 0; + x16 = 1; + } + + if (ticks > 0x1fff) { + ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16); + x4 = 1; + x16 = 1; + } + + if (ticks > 0x1fff) { + DSSWARN("LP_TX_TO over limit, setting it to max\n"); + ticks = 0x1fff; + x4 = 1; + x16 = 1; + } + + r = dsi_read_reg(DSI_TIMING2); + r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */ + r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */ + r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */ + r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */ + dsi_write_reg(DSI_TIMING2, r); + + DSSDBG("LP_RX_TO %lu ns (%#lx ticks%s%s)\n", + (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / + (fck / 1000 / 1000), + ticks, x4 ? " x4" : "", x16 ? " x16" : ""); +} + +static void dsi_set_ta_timeout(unsigned long ns) +{ + u32 r; + unsigned x8, x16; + unsigned long fck; + unsigned long ticks; + + /* ticks in DSI_FCK */ + fck = dsi_fclk_rate(); + ticks = (fck / 1000 / 1000) * ns / 1000; + x8 = 0; + x16 = 0; + + if (ticks > 0x1fff) { + ticks = (fck / 1000 / 1000) * ns / 1000 / 8; + x8 = 1; + x16 = 0; + } + + if (ticks > 0x1fff) { + ticks = (fck / 1000 / 1000) * ns / 1000 / 16; + x8 = 0; + x16 = 1; + } + + if (ticks > 0x1fff) { + ticks = (fck / 1000 / 1000) * ns / 1000 / (8 * 16); + x8 = 1; + x16 = 1; + } + + if (ticks > 0x1fff) { + DSSWARN("TA_TO over limit, setting it to max\n"); + ticks = 0x1fff; + x8 = 1; + x16 = 1; + } + + r = dsi_read_reg(DSI_TIMING1); + r = FLD_MOD(r, 1, 31, 31); /* TA_TO */ + r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */ + r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */ + r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */ + dsi_write_reg(DSI_TIMING1, r); + + DSSDBG("TA_TO %lu ns (%#lx ticks%s%s)\n", + (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) / + (fck / 1000 / 1000), + ticks, x8 ? " x8" : "", x16 ? " x16" : ""); +} + +static void dsi_set_stop_state_counter(unsigned long ns) +{ + u32 r; + unsigned x4, x16; + unsigned long fck; + unsigned long ticks; + + /* ticks in DSI_FCK */ + + fck = dsi_fclk_rate(); + ticks = (fck / 1000 / 1000) * ns / 1000; + x4 = 0; + x16 = 0; + + if (ticks > 0x1fff) { + ticks = (fck / 1000 / 1000) * ns / 1000 / 4; + x4 = 1; + x16 = 0; + } + + if (ticks > 0x1fff) { + ticks = (fck / 1000 / 1000) * ns / 1000 / 16; + x4 = 0; + x16 = 1; + } + + if (ticks > 0x1fff) { + ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16); + x4 = 1; + x16 = 1; + } + + if (ticks > 0x1fff) { + DSSWARN("STOP_STATE_COUNTER_IO over limit, " + "setting it to max\n"); + ticks = 0x1fff; + x4 = 1; + x16 = 1; + } + + r = dsi_read_reg(DSI_TIMING1); + r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ + r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */ + r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */ + r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */ + dsi_write_reg(DSI_TIMING1, r); + + DSSDBG("STOP_STATE_COUNTER %lu ns (%#lx ticks%s%s)\n", + (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / + (fck / 1000 / 1000), + ticks, x4 ? " x4" : "", x16 ? " x16" : ""); +} + +static void dsi_set_hs_tx_timeout(unsigned long ns) +{ + u32 r; + unsigned x4, x16; + unsigned long fck; + unsigned long ticks; + + /* ticks in TxByteClkHS */ + + fck = dsi_get_txbyteclkhs(); + ticks = (fck / 1000 / 1000) * ns / 1000; + x4 = 0; + x16 = 0; + + if (ticks > 0x1fff) { + ticks = (fck / 1000 / 1000) * ns / 1000 / 4; + x4 = 1; + x16 = 0; + } + + if (ticks > 0x1fff) { + ticks = (fck / 1000 / 1000) * ns / 1000 / 16; + x4 = 0; + x16 = 1; + } + + if (ticks > 0x1fff) { + ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16); + x4 = 1; + x16 = 1; + } + + if (ticks > 0x1fff) { + DSSWARN("HS_TX_TO over limit, setting it to max\n"); + ticks = 0x1fff; + x4 = 1; + x16 = 1; + } + + r = dsi_read_reg(DSI_TIMING2); + r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */ + r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */ + r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */ + r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */ + dsi_write_reg(DSI_TIMING2, r); + + DSSDBG("HS_TX_TO %lu ns (%#lx ticks%s%s)\n", + (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / + (fck / 1000 / 1000), + ticks, x4 ? " x4" : "", x16 ? " x16" : ""); +} +static int dsi_proto_config(struct omap_dss_device *dssdev) +{ + u32 r; + int buswidth = 0; + + dsi_config_tx_fifo(DSI_FIFO_SIZE_128, + DSI_FIFO_SIZE_0, + DSI_FIFO_SIZE_0, + DSI_FIFO_SIZE_0); + + dsi_config_rx_fifo(DSI_FIFO_SIZE_128, + DSI_FIFO_SIZE_0, + DSI_FIFO_SIZE_0, + DSI_FIFO_SIZE_0); + + /* XXX what values for the timeouts? */ + dsi_set_stop_state_counter(1000); + dsi_set_ta_timeout(6400000); + dsi_set_lp_rx_timeout(48000); + dsi_set_hs_tx_timeout(1000000); + + switch (dssdev->ctrl.pixel_size) { + case 16: + buswidth = 0; + break; + case 18: + buswidth = 1; + break; + case 24: + buswidth = 2; + break; + default: + BUG(); + } + + r = dsi_read_reg(DSI_CTRL); + r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */ + r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */ + r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */ + r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/ + r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */ + r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */ + r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */ + r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ + r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ + r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */ + r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */ + + dsi_write_reg(DSI_CTRL, r); + + dsi_vc_initial_config(0); + + /* set all vc targets to peripheral 0 */ + dsi.vc[0].dest_per = 0; + dsi.vc[1].dest_per = 0; + dsi.vc[2].dest_per = 0; + dsi.vc[3].dest_per = 0; + + return 0; +} + +static void dsi_proto_timings(struct omap_dss_device *dssdev) +{ + unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; + unsigned tclk_pre, tclk_post; + unsigned ths_prepare, ths_prepare_ths_zero, ths_zero; + unsigned ths_trail, ths_exit; + unsigned ddr_clk_pre, ddr_clk_post; + unsigned enter_hs_mode_lat, exit_hs_mode_lat; + unsigned ths_eot; + u32 r; + + r = dsi_read_reg(DSI_DSIPHY_CFG0); + ths_prepare = FLD_GET(r, 31, 24); + ths_prepare_ths_zero = FLD_GET(r, 23, 16); + ths_zero = ths_prepare_ths_zero - ths_prepare; + ths_trail = FLD_GET(r, 15, 8); + ths_exit = FLD_GET(r, 7, 0); + + r = dsi_read_reg(DSI_DSIPHY_CFG1); + tlpx = FLD_GET(r, 22, 16) * 2; + tclk_trail = FLD_GET(r, 15, 8); + tclk_zero = FLD_GET(r, 7, 0); + + r = dsi_read_reg(DSI_DSIPHY_CFG2); + tclk_prepare = FLD_GET(r, 7, 0); + + /* min 8*UI */ + tclk_pre = 20; + /* min 60ns + 52*UI */ + tclk_post = ns2ddr(60) + 26; + + /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */ + if (dssdev->phy.dsi.data1_lane != 0 && + dssdev->phy.dsi.data2_lane != 0) + ths_eot = 2; + else + ths_eot = 4; + + ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, + 4); + ddr_clk_post = DIV_ROUND_UP(tclk_post + ths_trail, 4) + ths_eot; + + BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255); + BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255); + + r = dsi_read_reg(DSI_CLK_TIMING); + r = FLD_MOD(r, ddr_clk_pre, 15, 8); + r = FLD_MOD(r, ddr_clk_post, 7, 0); + dsi_write_reg(DSI_CLK_TIMING, r); + + DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n", + ddr_clk_pre, + ddr_clk_post); + + enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) + + DIV_ROUND_UP(ths_prepare, 4) + + DIV_ROUND_UP(ths_zero + 3, 4); + + exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot; + + r = FLD_VAL(enter_hs_mode_lat, 31, 16) | + FLD_VAL(exit_hs_mode_lat, 15, 0); + dsi_write_reg(DSI_VM_TIMING7, r); + + DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", + enter_hs_mode_lat, exit_hs_mode_lat); +} + + +#define DSI_DECL_VARS \ + int __dsi_cb = 0; u32 __dsi_cv = 0; + +#define DSI_FLUSH(ch) \ + if (__dsi_cb > 0) { \ + /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \ + dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \ + __dsi_cb = __dsi_cv = 0; \ + } + +#define DSI_PUSH(ch, data) \ + do { \ + __dsi_cv |= (data) << (__dsi_cb * 8); \ + /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \ + if (++__dsi_cb > 3) \ + DSI_FLUSH(ch); \ + } while (0) + +static int dsi_update_screen_l4(struct omap_dss_device *dssdev, + int x, int y, int w, int h) +{ + /* Note: supports only 24bit colors in 32bit container */ + int first = 1; + int fifo_stalls = 0; + int max_dsi_packet_size; + int max_data_per_packet; + int max_pixels_per_packet; + int pixels_left; + int bytespp = dssdev->ctrl.pixel_size / 8; + int scr_width; + u32 __iomem *data; + int start_offset; + int horiz_inc; + int current_x; + struct omap_overlay *ovl; + + debug_irq = 0; + + DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n", + x, y, w, h); + + ovl = dssdev->manager->overlays[0]; + + if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U) + return -EINVAL; + + if (dssdev->ctrl.pixel_size != 24) + return -EINVAL; + + scr_width = ovl->info.screen_width; + data = ovl->info.vaddr; + + start_offset = scr_width * y + x; + horiz_inc = scr_width - w; + current_x = x; + + /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes + * in fifo */ + + /* When using CPU, max long packet size is TX buffer size */ + max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4; + + /* we seem to get better perf if we divide the tx fifo to half, + and while the other half is being sent, we fill the other half + max_dsi_packet_size /= 2; */ + + max_data_per_packet = max_dsi_packet_size - 4 - 1; + + max_pixels_per_packet = max_data_per_packet / bytespp; + + DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet); + + pixels_left = w * h; + + DSSDBG("total pixels %d\n", pixels_left); + + data += start_offset; + + while (pixels_left > 0) { + /* 0x2c = write_memory_start */ + /* 0x3c = write_memory_continue */ + u8 dcs_cmd = first ? 0x2c : 0x3c; + int pixels; + DSI_DECL_VARS; + first = 0; + +#if 1 + /* using fifo not empty */ + /* TX_FIFO_NOT_EMPTY */ + while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) { + udelay(1); + fifo_stalls++; + if (fifo_stalls > 0xfffff) { + DSSERR("fifo stalls overflow, pixels left %d\n", + pixels_left); + dsi_if_enable(0); + return -EIO; + } + } +#elif 1 + /* using fifo emptiness */ + while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 < + max_dsi_packet_size) { + fifo_stalls++; + if (fifo_stalls > 0xfffff) { + DSSERR("fifo stalls overflow, pixels left %d\n", + pixels_left); + dsi_if_enable(0); + return -EIO; + } + } +#else + while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) { + fifo_stalls++; + if (fifo_stalls > 0xfffff) { + DSSERR("fifo stalls overflow, pixels left %d\n", + pixels_left); + dsi_if_enable(0); + return -EIO; + } + } +#endif + pixels = min(max_pixels_per_packet, pixels_left); + + pixels_left -= pixels; + + dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE, + 1 + pixels * bytespp, 0); + + DSI_PUSH(0, dcs_cmd); + + while (pixels-- > 0) { + u32 pix = __raw_readl(data++); + + DSI_PUSH(0, (pix >> 16) & 0xff); + DSI_PUSH(0, (pix >> 8) & 0xff); + DSI_PUSH(0, (pix >> 0) & 0xff); + + current_x++; + if (current_x == x+w) { + current_x = x; + data += horiz_inc; + } + } + + DSI_FLUSH(0); + } + + return 0; +} + +static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, + u16 x, u16 y, u16 w, u16 h) +{ + unsigned bytespp; + unsigned bytespl; + unsigned bytespf; + unsigned total_len; + unsigned packet_payload; + unsigned packet_len; + u32 l; + bool use_te_trigger; + const unsigned channel = 0; + /* line buffer is 1024 x 24bits */ + /* XXX: for some reason using full buffer size causes considerable TX + * slowdown with update sizes that fill the whole buffer */ + const unsigned line_buf_size = 1023 * 3; + + use_te_trigger = dsi.te_enabled && !dsi.use_ext_te; + + if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO) + DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", + x, y, w, h); + + bytespp = dssdev->ctrl.pixel_size / 8; + bytespl = w * bytespp; + bytespf = bytespl * h; + + /* NOTE: packet_payload has to be equal to N * bytespl, where N is + * number of lines in a packet. See errata about VP_CLK_RATIO */ + + if (bytespf < line_buf_size) + packet_payload = bytespf; + else + packet_payload = (line_buf_size) / bytespl * bytespl; + + packet_len = packet_payload + 1; /* 1 byte for DCS cmd */ + total_len = (bytespf / packet_payload) * packet_len; + + if (bytespf % packet_payload) + total_len += (bytespf % packet_payload) + 1; + + if (0) + dsi_vc_print_status(1); + + l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ + dsi_write_reg(DSI_VC_TE(channel), l); + + dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0); + + if (use_te_trigger) + l = FLD_MOD(l, 1, 30, 30); /* TE_EN */ + else + l = FLD_MOD(l, 1, 31, 31); /* TE_START */ + dsi_write_reg(DSI_VC_TE(channel), l); + + /* We put SIDLEMODE to no-idle for the duration of the transfer, + * because DSS interrupts are not capable of waking up the CPU and the + * framedone interrupt could be delayed for quite a long time. I think + * the same goes for any DSS interrupts, but for some reason I have not + * seen the problem anywhere else than here. + */ + dispc_disable_sidle(); + + dss_start_update(dssdev); + + if (use_te_trigger) { + /* disable LP_RX_TO, so that we can receive TE. Time to wait + * for TE is longer than the timer allows */ + REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */ + + dsi_vc_send_bta(channel); + +#ifdef DSI_CATCH_MISSING_TE + mod_timer(&dsi.te_timer, jiffies + msecs_to_jiffies(250)); +#endif + } +} + +#ifdef DSI_CATCH_MISSING_TE +static void dsi_te_timeout(unsigned long arg) +{ + DSSERR("TE not received for 250ms!\n"); +} +#endif + +static void dsi_framedone_irq_callback(void *data, u32 mask) +{ + /* Note: We get FRAMEDONE when DISPC has finished sending pixels and + * turns itself off. However, DSI still has the pixels in its buffers, + * and is sending the data. + */ + + /* SIDLEMODE back to smart-idle */ + dispc_enable_sidle(); + + dsi.framedone_received = true; + wake_up(&dsi.waitqueue); +} + +static void dsi_set_update_region(struct omap_dss_device *dssdev, + u16 x, u16 y, u16 w, u16 h) +{ + spin_lock(&dsi.update_lock); + if (dsi.update_region.dirty) { + dsi.update_region.x = min(x, dsi.update_region.x); + dsi.update_region.y = min(y, dsi.update_region.y); + dsi.update_region.w = max(w, dsi.update_region.w); + dsi.update_region.h = max(h, dsi.update_region.h); + } else { + dsi.update_region.x = x; + dsi.update_region.y = y; + dsi.update_region.w = w; + dsi.update_region.h = h; + } + + dsi.update_region.device = dssdev; + dsi.update_region.dirty = true; + + spin_unlock(&dsi.update_lock); + +} + +static int dsi_set_update_mode(struct omap_dss_device *dssdev, + enum omap_dss_update_mode mode) +{ + int r = 0; + int i; + + WARN_ON(!mutex_is_locked(&dsi.bus_lock)); + + if (dsi.update_mode != mode) { + dsi.update_mode = mode; + + /* Mark the overlays dirty, and do apply(), so that we get the + * overlays configured properly after update mode change. */ + for (i = 0; i < omap_dss_get_num_overlays(); ++i) { + struct omap_overlay *ovl; + ovl = omap_dss_get_overlay(i); + if (ovl->manager == dssdev->manager) + ovl->info_dirty = true; + } + + r = dssdev->manager->apply(dssdev->manager); + + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE && + mode == OMAP_DSS_UPDATE_AUTO) { + u16 w, h; + + DSSDBG("starting auto update\n"); + + dssdev->get_resolution(dssdev, &w, &h); + + dsi_set_update_region(dssdev, 0, 0, w, h); + + dsi_perf_mark_start_auto(); + + wake_up(&dsi.waitqueue); + } + } + + return r; +} + +static int dsi_set_te(struct omap_dss_device *dssdev, bool enable) +{ + int r; + r = dssdev->driver->enable_te(dssdev, enable); + /* XXX for some reason, DSI TE breaks if we don't wait here. + * Panel bug? Needs more studying */ + msleep(100); + return r; +} + +static void dsi_handle_framedone(void) +{ + int r; + const int channel = 0; + bool use_te_trigger; + + use_te_trigger = dsi.te_enabled && !dsi.use_ext_te; + + if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO) + DSSDBG("FRAMEDONE\n"); + + if (use_te_trigger) { + /* enable LP_RX_TO again after the TE */ + REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ + } + + /* Send BTA after the frame. We need this for the TE to work, as TE + * trigger is only sent for BTAs without preceding packet. Thus we need + * to BTA after the pixel packets so that next BTA will cause TE + * trigger. + * + * This is not needed when TE is not in use, but we do it anyway to + * make sure that the transfer has been completed. It would be more + * optimal, but more complex, to wait only just before starting next + * transfer. */ + r = dsi_vc_send_bta_sync(channel); + if (r) + DSSERR("BTA after framedone failed\n"); + + /* RX_FIFO_NOT_EMPTY */ + if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { + DSSERR("Received error during frame transfer:\n"); + dsi_vc_flush_receive_data(0); + } + +#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC + dispc_fake_vsync_irq(); +#endif +} + +static int dsi_update_thread(void *data) +{ + unsigned long timeout; + struct omap_dss_device *device; + u16 x, y, w, h; + + while (1) { + bool sched; + + wait_event_interruptible(dsi.waitqueue, + dsi.update_mode == OMAP_DSS_UPDATE_AUTO || + (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL && + dsi.update_region.dirty == true) || + kthread_should_stop()); + + if (kthread_should_stop()) + break; + + dsi_bus_lock(); + + if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED || + kthread_should_stop()) { + dsi_bus_unlock(); + break; + } + + dsi_perf_mark_setup(); + + if (dsi.update_region.dirty) { + spin_lock(&dsi.update_lock); + dsi.active_update_region = dsi.update_region; + dsi.update_region.dirty = false; + spin_unlock(&dsi.update_lock); + } + + device = dsi.active_update_region.device; + x = dsi.active_update_region.x; + y = dsi.active_update_region.y; + w = dsi.active_update_region.w; + h = dsi.active_update_region.h; + + if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { + + if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL) + dss_setup_partial_planes(device, + &x, &y, &w, &h); + + dispc_set_lcd_size(w, h); + } + + if (dsi.active_update_region.dirty) { + dsi.active_update_region.dirty = false; + /* XXX TODO we don't need to send the coords, if they + * are the same that are already programmed to the + * panel. That should speed up manual update a bit */ + device->driver->setup_update(device, x, y, w, h); + } + + dsi_perf_mark_start(); + + if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { + dsi_vc_config_vp(0); + + if (dsi.te_enabled && dsi.use_ext_te) + device->driver->wait_for_te(device); + + dsi.framedone_received = false; + + dsi_update_screen_dispc(device, x, y, w, h); + + /* wait for framedone */ + timeout = msecs_to_jiffies(1000); + wait_event_timeout(dsi.waitqueue, + dsi.framedone_received == true, + timeout); + + if (!dsi.framedone_received) { + DSSERR("framedone timeout\n"); + DSSERR("failed update %d,%d %dx%d\n", + x, y, w, h); + + dispc_enable_sidle(); + dispc_enable_lcd_out(0); + + dsi_reset_tx_fifo(0); + } else { + dsi_handle_framedone(); + dsi_perf_show("DISPC"); + } + } else { + dsi_update_screen_l4(device, x, y, w, h); + dsi_perf_show("L4"); + } + + sched = atomic_read(&dsi.bus_lock.count) < 0; + + complete_all(&dsi.update_completion); + + dsi_bus_unlock(); + + /* XXX We need to give others chance to get the bus lock. Is + * there a better way for this? */ + if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO && sched) + schedule_timeout_interruptible(1); + } + + DSSDBG("update thread exiting\n"); + + return 0; +} + + + +/* Display funcs */ + +static int dsi_display_init_dispc(struct omap_dss_device *dssdev) +{ + int r; + + r = omap_dispc_register_isr(dsi_framedone_irq_callback, NULL, + DISPC_IRQ_FRAMEDONE); + if (r) { + DSSERR("can't get FRAMEDONE irq\n"); + return r; + } + + dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); + + dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI); + dispc_enable_fifohandcheck(1); + + dispc_set_tft_data_lines(dssdev->ctrl.pixel_size); + + { + struct omap_video_timings timings = { + .hsw = 1, + .hfp = 1, + .hbp = 1, + .vsw = 1, + .vfp = 0, + .vbp = 0, + }; + + dispc_set_lcd_timings(&timings); + } + + return 0; +} + +static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) +{ + omap_dispc_unregister_isr(dsi_framedone_irq_callback, NULL, + DISPC_IRQ_FRAMEDONE); +} + +static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) +{ + struct dsi_clock_info cinfo; + int r; + + /* we always use DSS2_FCK as input clock */ + cinfo.use_dss2_fck = true; + cinfo.regn = dssdev->phy.dsi.div.regn; + cinfo.regm = dssdev->phy.dsi.div.regm; + cinfo.regm3 = dssdev->phy.dsi.div.regm3; + cinfo.regm4 = dssdev->phy.dsi.div.regm4; + r = dsi_calc_clock_rates(&cinfo); + if (r) + return r; + + r = dsi_pll_set_clock_div(&cinfo); + if (r) { + DSSERR("Failed to set dsi clocks\n"); + return r; + } + + return 0; +} + +static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) +{ + struct dispc_clock_info dispc_cinfo; + int r; + unsigned long long fck; + + fck = dsi_get_dsi1_pll_rate(); + + dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div; + dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div; + + r = dispc_calc_clock_rates(fck, &dispc_cinfo); + if (r) { + DSSERR("Failed to calc dispc clocks\n"); + return r; + } + + r = dispc_set_clock_div(&dispc_cinfo); + if (r) { + DSSERR("Failed to set dispc clocks\n"); + return r; + } + + return 0; +} + +static int dsi_display_init_dsi(struct omap_dss_device *dssdev) +{ + int r; + + _dsi_print_reset_status(); + + r = dsi_pll_init(dssdev, true, true); + if (r) + goto err0; + + r = dsi_configure_dsi_clocks(dssdev); + if (r) + goto err1; + + dss_select_clk_source(true, true); + + DSSDBG("PLL OK\n"); + + r = dsi_configure_dispc_clocks(dssdev); + if (r) + goto err2; + + r = dsi_complexio_init(dssdev); + if (r) + goto err2; + + _dsi_print_reset_status(); + + dsi_proto_timings(dssdev); + dsi_set_lp_clk_divisor(dssdev); + + if (1) + _dsi_print_reset_status(); + + r = dsi_proto_config(dssdev); + if (r) + goto err3; + + /* enable interface */ + dsi_vc_enable(0, 1); + dsi_if_enable(1); + dsi_force_tx_stop_mode_io(); + + if (dssdev->driver->enable) { + r = dssdev->driver->enable(dssdev); + if (r) + goto err4; + } + + /* enable high-speed after initial config */ + dsi_vc_enable_hs(0, 1); + + return 0; +err4: + dsi_if_enable(0); +err3: + dsi_complexio_uninit(); +err2: + dss_select_clk_source(false, false); +err1: + dsi_pll_uninit(); +err0: + return r; +} + +static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) +{ + if (dssdev->driver->disable) + dssdev->driver->disable(dssdev); + + dss_select_clk_source(false, false); + dsi_complexio_uninit(); + dsi_pll_uninit(); +} + +static int dsi_core_init(void) +{ + /* Autoidle */ + REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0); + + /* ENWAKEUP */ + REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2); + + /* SIDLEMODE smart-idle */ + REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3); + + _dsi_initialize_irq(); + + return 0; +} + +static int dsi_display_enable(struct omap_dss_device *dssdev) +{ + int r = 0; + + DSSDBG("dsi_display_enable\n"); + + mutex_lock(&dsi.lock); + dsi_bus_lock(); + + r = omap_dss_start_device(dssdev); + if (r) { + DSSERR("failed to start device\n"); + goto err0; + } + + if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { + DSSERR("dssdev already enabled\n"); + r = -EINVAL; + goto err1; + } + + enable_clocks(1); + dsi_enable_pll_clock(1); + + r = _dsi_reset(); + if (r) + goto err2; + + dsi_core_init(); + + r = dsi_display_init_dispc(dssdev); + if (r) + goto err2; + + r = dsi_display_init_dsi(dssdev); + if (r) + goto err3; + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + + dsi.use_ext_te = dssdev->phy.dsi.ext_te; + r = dsi_set_te(dssdev, dsi.te_enabled); + if (r) + goto err4; + + dsi_set_update_mode(dssdev, dsi.user_update_mode); + + dsi_bus_unlock(); + mutex_unlock(&dsi.lock); + + return 0; + +err4: + + dsi_display_uninit_dsi(dssdev); +err3: + dsi_display_uninit_dispc(dssdev); +err2: + enable_clocks(0); + dsi_enable_pll_clock(0); +err1: + omap_dss_stop_device(dssdev); +err0: + dsi_bus_unlock(); + mutex_unlock(&dsi.lock); + DSSDBG("dsi_display_enable FAILED\n"); + return r; +} + +static void dsi_display_disable(struct omap_dss_device *dssdev) +{ + DSSDBG("dsi_display_disable\n"); + + mutex_lock(&dsi.lock); + dsi_bus_lock(); + + if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED || + dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) + goto end; + + dsi.update_mode = OMAP_DSS_UPDATE_DISABLED; + dssdev->state = OMAP_DSS_DISPLAY_DISABLED; + + dsi_display_uninit_dispc(dssdev); + + dsi_display_uninit_dsi(dssdev); + + enable_clocks(0); + dsi_enable_pll_clock(0); + + omap_dss_stop_device(dssdev); +end: + dsi_bus_unlock(); + mutex_unlock(&dsi.lock); +} + +static int dsi_display_suspend(struct omap_dss_device *dssdev) +{ + DSSDBG("dsi_display_suspend\n"); + + mutex_lock(&dsi.lock); + dsi_bus_lock(); + + if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED || + dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) + goto end; + + dsi.update_mode = OMAP_DSS_UPDATE_DISABLED; + dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; + + dsi_display_uninit_dispc(dssdev); + + dsi_display_uninit_dsi(dssdev); + + enable_clocks(0); + dsi_enable_pll_clock(0); +end: + dsi_bus_unlock(); + mutex_unlock(&dsi.lock); + + return 0; +} + +static int dsi_display_resume(struct omap_dss_device *dssdev) +{ + int r; + + DSSDBG("dsi_display_resume\n"); + + mutex_lock(&dsi.lock); + dsi_bus_lock(); + + if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { + DSSERR("dssdev not suspended\n"); + r = -EINVAL; + goto err0; + } + + enable_clocks(1); + dsi_enable_pll_clock(1); + + r = _dsi_reset(); + if (r) + goto err1; + + dsi_core_init(); + + r = dsi_display_init_dispc(dssdev); + if (r) + goto err1; + + r = dsi_display_init_dsi(dssdev); + if (r) + goto err2; + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + + r = dsi_set_te(dssdev, dsi.te_enabled); + if (r) + goto err2; + + dsi_set_update_mode(dssdev, dsi.user_update_mode); + + dsi_bus_unlock(); + mutex_unlock(&dsi.lock); + + return 0; + +err2: + dsi_display_uninit_dispc(dssdev); +err1: + enable_clocks(0); + dsi_enable_pll_clock(0); +err0: + dsi_bus_unlock(); + mutex_unlock(&dsi.lock); + DSSDBG("dsi_display_resume FAILED\n"); + return r; +} + +static int dsi_display_update(struct omap_dss_device *dssdev, + u16 x, u16 y, u16 w, u16 h) +{ + int r = 0; + u16 dw, dh; + + DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h); + + mutex_lock(&dsi.lock); + + if (dsi.update_mode != OMAP_DSS_UPDATE_MANUAL) + goto end; + + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + goto end; + + dssdev->get_resolution(dssdev, &dw, &dh); + + if (x > dw || y > dh) + goto end; + + if (x + w > dw) + w = dw - x; + + if (y + h > dh) + h = dh - y; + + if (w == 0 || h == 0) + goto end; + + if (w == 1) { + r = -EINVAL; + goto end; + } + + dsi_set_update_region(dssdev, x, y, w, h); + + wake_up(&dsi.waitqueue); + +end: + mutex_unlock(&dsi.lock); + + return r; +} + +static int dsi_display_sync(struct omap_dss_device *dssdev) +{ + bool wait; + + DSSDBG("dsi_display_sync()\n"); + + mutex_lock(&dsi.lock); + dsi_bus_lock(); + + if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL && + dsi.update_region.dirty) { + INIT_COMPLETION(dsi.update_completion); + wait = true; + } else { + wait = false; + } + + dsi_bus_unlock(); + mutex_unlock(&dsi.lock); + + if (wait) + wait_for_completion_interruptible(&dsi.update_completion); + + DSSDBG("dsi_display_sync() done\n"); + return 0; +} + +static int dsi_display_set_update_mode(struct omap_dss_device *dssdev, + enum omap_dss_update_mode mode) +{ + int r = 0; + + DSSDBGF("%d", mode); + + mutex_lock(&dsi.lock); + dsi_bus_lock(); + + dsi.user_update_mode = mode; + r = dsi_set_update_mode(dssdev, mode); + + dsi_bus_unlock(); + mutex_unlock(&dsi.lock); + + return r; +} + +static enum omap_dss_update_mode dsi_display_get_update_mode( + struct omap_dss_device *dssdev) +{ + return dsi.update_mode; +} + + +static int dsi_display_enable_te(struct omap_dss_device *dssdev, bool enable) +{ + int r = 0; + + DSSDBGF("%d", enable); + + if (!dssdev->driver->enable_te) + return -ENOENT; + + dsi_bus_lock(); + + dsi.te_enabled = enable; + + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + goto end; + + r = dsi_set_te(dssdev, enable); +end: + dsi_bus_unlock(); + + return r; +} + +static int dsi_display_get_te(struct omap_dss_device *dssdev) +{ + return dsi.te_enabled; +} + +static int dsi_display_set_rotate(struct omap_dss_device *dssdev, u8 rotate) +{ + + DSSDBGF("%d", rotate); + + if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate) + return -EINVAL; + + dsi_bus_lock(); + dssdev->driver->set_rotate(dssdev, rotate); + if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) { + u16 w, h; + /* the display dimensions may have changed, so set a new + * update region */ + dssdev->get_resolution(dssdev, &w, &h); + dsi_set_update_region(dssdev, 0, 0, w, h); + } + dsi_bus_unlock(); + + return 0; +} + +static u8 dsi_display_get_rotate(struct omap_dss_device *dssdev) +{ + if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate) + return 0; + + return dssdev->driver->get_rotate(dssdev); +} + +static int dsi_display_set_mirror(struct omap_dss_device *dssdev, bool mirror) +{ + DSSDBGF("%d", mirror); + + if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) + return -EINVAL; + + dsi_bus_lock(); + dssdev->driver->set_mirror(dssdev, mirror); + dsi_bus_unlock(); + + return 0; +} + +static bool dsi_display_get_mirror(struct omap_dss_device *dssdev) +{ + if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) + return 0; + + return dssdev->driver->get_mirror(dssdev); +} + +static int dsi_display_run_test(struct omap_dss_device *dssdev, int test_num) +{ + int r; + + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + return -EIO; + + DSSDBGF("%d", test_num); + + dsi_bus_lock(); + + /* run test first in low speed mode */ + dsi_vc_enable_hs(0, 0); + + if (dssdev->driver->run_test) { + r = dssdev->driver->run_test(dssdev, test_num); + if (r) + goto end; + } + + /* then in high speed */ + dsi_vc_enable_hs(0, 1); + + if (dssdev->driver->run_test) { + r = dssdev->driver->run_test(dssdev, test_num); + if (r) + goto end; + } + +end: + dsi_vc_enable_hs(0, 1); + + dsi_bus_unlock(); + + return r; +} + +static int dsi_display_memory_read(struct omap_dss_device *dssdev, + void *buf, size_t size, + u16 x, u16 y, u16 w, u16 h) +{ + int r; + + DSSDBGF(""); + + if (!dssdev->driver->memory_read) + return -EINVAL; + + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + return -EIO; + + dsi_bus_lock(); + + r = dssdev->driver->memory_read(dssdev, buf, size, + x, y, w, h); + + /* Memory read usually changes the update area. This will + * force the next update to re-set the update area */ + dsi.active_update_region.dirty = true; + + dsi_bus_unlock(); + + return r; +} + +void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, + u32 fifo_size, enum omap_burst_size *burst_size, + u32 *fifo_low, u32 *fifo_high) +{ + unsigned burst_size_bytes; + + *burst_size = OMAP_DSS_BURST_16x32; + burst_size_bytes = 16 * 32 / 8; + + *fifo_high = fifo_size - burst_size_bytes; + *fifo_low = fifo_size - burst_size_bytes * 8; +} + +int dsi_init_display(struct omap_dss_device *dssdev) +{ + DSSDBG("DSI init\n"); + + dssdev->enable = dsi_display_enable; + dssdev->disable = dsi_display_disable; + dssdev->suspend = dsi_display_suspend; + dssdev->resume = dsi_display_resume; + dssdev->update = dsi_display_update; + dssdev->sync = dsi_display_sync; + dssdev->set_update_mode = dsi_display_set_update_mode; + dssdev->get_update_mode = dsi_display_get_update_mode; + dssdev->enable_te = dsi_display_enable_te; + dssdev->get_te = dsi_display_get_te; + + dssdev->get_rotate = dsi_display_get_rotate; + dssdev->set_rotate = dsi_display_set_rotate; + + dssdev->get_mirror = dsi_display_get_mirror; + dssdev->set_mirror = dsi_display_set_mirror; + + dssdev->run_test = dsi_display_run_test; + dssdev->memory_read = dsi_display_memory_read; + + /* XXX these should be figured out dynamically */ + dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | + OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; + + dsi.vc[0].dssdev = dssdev; + dsi.vc[1].dssdev = dssdev; + + return 0; +} + +int dsi_init(struct platform_device *pdev) +{ + u32 rev; + int r; + struct sched_param param = { + .sched_priority = MAX_USER_RT_PRIO-1 + }; + + spin_lock_init(&dsi.errors_lock); + dsi.errors = 0; + + init_completion(&dsi.bta_completion); + init_completion(&dsi.update_completion); + + dsi.thread = kthread_create(dsi_update_thread, NULL, "dsi"); + if (IS_ERR(dsi.thread)) { + DSSERR("cannot create kthread\n"); + r = PTR_ERR(dsi.thread); + goto err0; + } + sched_setscheduler(dsi.thread, SCHED_FIFO, ¶m); + + init_waitqueue_head(&dsi.waitqueue); + spin_lock_init(&dsi.update_lock); + + mutex_init(&dsi.lock); + mutex_init(&dsi.bus_lock); + +#ifdef DSI_CATCH_MISSING_TE + init_timer(&dsi.te_timer); + dsi.te_timer.function = dsi_te_timeout; + dsi.te_timer.data = 0; +#endif + + dsi.update_mode = OMAP_DSS_UPDATE_DISABLED; + dsi.user_update_mode = OMAP_DSS_UPDATE_DISABLED; + + dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS); + if (!dsi.base) { + DSSERR("can't ioremap DSI\n"); + r = -ENOMEM; + goto err1; + } + + dsi.vdds_dsi_reg = regulator_get(&pdev->dev, "vdds_dsi"); + if (IS_ERR(dsi.vdds_dsi_reg)) { + iounmap(dsi.base); + DSSERR("can't get VDDS_DSI regulator\n"); + r = PTR_ERR(dsi.vdds_dsi_reg); + goto err2; + } + + enable_clocks(1); + + rev = dsi_read_reg(DSI_REVISION); + printk(KERN_INFO "OMAP DSI rev %d.%d\n", + FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); + + enable_clocks(0); + + wake_up_process(dsi.thread); + + return 0; +err2: + iounmap(dsi.base); +err1: + kthread_stop(dsi.thread); +err0: + return r; +} + +void dsi_exit(void) +{ + kthread_stop(dsi.thread); + + regulator_put(dsi.vdds_dsi_reg); + + iounmap(dsi.base); + + DSSDBG("omap_dsi_exit\n"); +} + diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c new file mode 100644 index 0000000000000000000000000000000000000000..9b05ee65a15dbcaba06de15b296ff80d3dad35c5 --- /dev/null +++ b/drivers/video/omap2/dss/dss.c @@ -0,0 +1,596 @@ +/* + * linux/drivers/video/omap2/dss/dss.c + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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, see . + */ + +#define DSS_SUBSYS_NAME "DSS" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "dss.h" + +#define DSS_BASE 0x48050000 + +#define DSS_SZ_REGS SZ_512 + +struct dss_reg { + u16 idx; +}; + +#define DSS_REG(idx) ((const struct dss_reg) { idx }) + +#define DSS_REVISION DSS_REG(0x0000) +#define DSS_SYSCONFIG DSS_REG(0x0010) +#define DSS_SYSSTATUS DSS_REG(0x0014) +#define DSS_IRQSTATUS DSS_REG(0x0018) +#define DSS_CONTROL DSS_REG(0x0040) +#define DSS_SDI_CONTROL DSS_REG(0x0044) +#define DSS_PLL_CONTROL DSS_REG(0x0048) +#define DSS_SDI_STATUS DSS_REG(0x005C) + +#define REG_GET(idx, start, end) \ + FLD_GET(dss_read_reg(idx), start, end) + +#define REG_FLD_MOD(idx, val, start, end) \ + dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) + +static struct { + void __iomem *base; + + struct clk *dpll4_m4_ck; + + unsigned long cache_req_pck; + unsigned long cache_prate; + struct dss_clock_info cache_dss_cinfo; + struct dispc_clock_info cache_dispc_cinfo; + + u32 ctx[DSS_SZ_REGS / sizeof(u32)]; +} dss; + +static int _omap_dss_wait_reset(void); + +static inline void dss_write_reg(const struct dss_reg idx, u32 val) +{ + __raw_writel(val, dss.base + idx.idx); +} + +static inline u32 dss_read_reg(const struct dss_reg idx) +{ + return __raw_readl(dss.base + idx.idx); +} + +#define SR(reg) \ + dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg) +#define RR(reg) \ + dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)]) + +void dss_save_context(void) +{ + if (cpu_is_omap24xx()) + return; + + SR(SYSCONFIG); + SR(CONTROL); + +#ifdef CONFIG_OMAP2_DSS_SDI + SR(SDI_CONTROL); + SR(PLL_CONTROL); +#endif +} + +void dss_restore_context(void) +{ + if (_omap_dss_wait_reset()) + DSSERR("DSS not coming out of reset after sleep\n"); + + RR(SYSCONFIG); + RR(CONTROL); + +#ifdef CONFIG_OMAP2_DSS_SDI + RR(SDI_CONTROL); + RR(PLL_CONTROL); +#endif +} + +#undef SR +#undef RR + +void dss_sdi_init(u8 datapairs) +{ + u32 l; + + BUG_ON(datapairs > 3 || datapairs < 1); + + l = dss_read_reg(DSS_SDI_CONTROL); + l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */ + l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */ + l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */ + dss_write_reg(DSS_SDI_CONTROL, l); + + l = dss_read_reg(DSS_PLL_CONTROL); + l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */ + l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */ + l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */ + dss_write_reg(DSS_PLL_CONTROL, l); +} + +int dss_sdi_enable(void) +{ + unsigned long timeout; + + dispc_pck_free_enable(1); + + /* Reset SDI PLL */ + REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */ + udelay(1); /* wait 2x PCLK */ + + /* Lock SDI PLL */ + REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */ + + /* Waiting for PLL lock request to complete */ + timeout = jiffies + msecs_to_jiffies(500); + while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) { + if (time_after_eq(jiffies, timeout)) { + DSSERR("PLL lock request timed out\n"); + goto err1; + } + } + + /* Clearing PLL_GO bit */ + REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28); + + /* Waiting for PLL to lock */ + timeout = jiffies + msecs_to_jiffies(500); + while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) { + if (time_after_eq(jiffies, timeout)) { + DSSERR("PLL lock timed out\n"); + goto err1; + } + } + + dispc_lcd_enable_signal(1); + + /* Waiting for SDI reset to complete */ + timeout = jiffies + msecs_to_jiffies(500); + while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) { + if (time_after_eq(jiffies, timeout)) { + DSSERR("SDI reset timed out\n"); + goto err2; + } + } + + return 0; + + err2: + dispc_lcd_enable_signal(0); + err1: + /* Reset SDI PLL */ + REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ + + dispc_pck_free_enable(0); + + return -ETIMEDOUT; +} + +void dss_sdi_disable(void) +{ + dispc_lcd_enable_signal(0); + + dispc_pck_free_enable(0); + + /* Reset SDI PLL */ + REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ +} + +void dss_dump_clocks(struct seq_file *s) +{ + unsigned long dpll4_ck_rate; + unsigned long dpll4_m4_ck_rate; + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); + dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck); + + seq_printf(s, "- DSS -\n"); + + seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); + + seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n", + dpll4_ck_rate, + dpll4_ck_rate / dpll4_m4_ck_rate, + dss_clk_get_rate(DSS_CLK_FCK1)); + + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); +} + +void dss_dump_regs(struct seq_file *s) +{ +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + DUMPREG(DSS_REVISION); + DUMPREG(DSS_SYSCONFIG); + DUMPREG(DSS_SYSSTATUS); + DUMPREG(DSS_IRQSTATUS); + DUMPREG(DSS_CONTROL); + DUMPREG(DSS_SDI_CONTROL); + DUMPREG(DSS_PLL_CONTROL); + DUMPREG(DSS_SDI_STATUS); + + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); +#undef DUMPREG +} + +void dss_select_clk_source(bool dsi, bool dispc) +{ + u32 r; + r = dss_read_reg(DSS_CONTROL); + r = FLD_MOD(r, dsi, 1, 1); /* DSI_CLK_SWITCH */ + r = FLD_MOD(r, dispc, 0, 0); /* DISPC_CLK_SWITCH */ + dss_write_reg(DSS_CONTROL, r); +} + +int dss_get_dsi_clk_source(void) +{ + return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1); +} + +int dss_get_dispc_clk_source(void) +{ + return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0); +} + +/* calculate clock rates using dividers in cinfo */ +int dss_calc_clock_rates(struct dss_clock_info *cinfo) +{ + unsigned long prate; + + if (cinfo->fck_div > 16 || cinfo->fck_div == 0) + return -EINVAL; + + prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); + + cinfo->fck = prate / cinfo->fck_div; + + return 0; +} + +int dss_set_clock_div(struct dss_clock_info *cinfo) +{ + unsigned long prate; + int r; + + if (cpu_is_omap34xx()) { + prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); + DSSDBG("dpll4_m4 = %ld\n", prate); + + r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); + if (r) + return r; + } + + DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); + + return 0; +} + +int dss_get_clock_div(struct dss_clock_info *cinfo) +{ + cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1); + + if (cpu_is_omap34xx()) { + unsigned long prate; + prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); + cinfo->fck_div = prate / (cinfo->fck / 2); + } else { + cinfo->fck_div = 0; + } + + return 0; +} + +unsigned long dss_get_dpll4_rate(void) +{ + if (cpu_is_omap34xx()) + return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); + else + return 0; +} + +int dss_calc_clock_div(bool is_tft, unsigned long req_pck, + struct dss_clock_info *dss_cinfo, + struct dispc_clock_info *dispc_cinfo) +{ + unsigned long prate; + struct dss_clock_info best_dss; + struct dispc_clock_info best_dispc; + + unsigned long fck; + + u16 fck_div; + + int match = 0; + int min_fck_per_pck; + + prate = dss_get_dpll4_rate(); + + fck = dss_clk_get_rate(DSS_CLK_FCK1); + if (req_pck == dss.cache_req_pck && + ((cpu_is_omap34xx() && prate == dss.cache_prate) || + dss.cache_dss_cinfo.fck == fck)) { + DSSDBG("dispc clock info found from cache.\n"); + *dss_cinfo = dss.cache_dss_cinfo; + *dispc_cinfo = dss.cache_dispc_cinfo; + return 0; + } + + min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; + + if (min_fck_per_pck && + req_pck * min_fck_per_pck > DISPC_MAX_FCK) { + DSSERR("Requested pixel clock not possible with the current " + "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " + "the constraint off.\n"); + min_fck_per_pck = 0; + } + +retry: + memset(&best_dss, 0, sizeof(best_dss)); + memset(&best_dispc, 0, sizeof(best_dispc)); + + if (cpu_is_omap24xx()) { + struct dispc_clock_info cur_dispc; + /* XXX can we change the clock on omap2? */ + fck = dss_clk_get_rate(DSS_CLK_FCK1); + fck_div = 1; + + dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc); + match = 1; + + best_dss.fck = fck; + best_dss.fck_div = fck_div; + + best_dispc = cur_dispc; + + goto found; + } else if (cpu_is_omap34xx()) { + for (fck_div = 16; fck_div > 0; --fck_div) { + struct dispc_clock_info cur_dispc; + + fck = prate / fck_div * 2; + + if (fck > DISPC_MAX_FCK) + continue; + + if (min_fck_per_pck && + fck < req_pck * min_fck_per_pck) + continue; + + match = 1; + + dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc); + + if (abs(cur_dispc.pck - req_pck) < + abs(best_dispc.pck - req_pck)) { + + best_dss.fck = fck; + best_dss.fck_div = fck_div; + + best_dispc = cur_dispc; + + if (cur_dispc.pck == req_pck) + goto found; + } + } + } else { + BUG(); + } + +found: + if (!match) { + if (min_fck_per_pck) { + DSSERR("Could not find suitable clock settings.\n" + "Turning FCK/PCK constraint off and" + "trying again.\n"); + min_fck_per_pck = 0; + goto retry; + } + + DSSERR("Could not find suitable clock settings.\n"); + + return -EINVAL; + } + + if (dss_cinfo) + *dss_cinfo = best_dss; + if (dispc_cinfo) + *dispc_cinfo = best_dispc; + + dss.cache_req_pck = req_pck; + dss.cache_prate = prate; + dss.cache_dss_cinfo = best_dss; + dss.cache_dispc_cinfo = best_dispc; + + return 0; +} + + + +static irqreturn_t dss_irq_handler_omap2(int irq, void *arg) +{ + dispc_irq_handler(); + + return IRQ_HANDLED; +} + +static irqreturn_t dss_irq_handler_omap3(int irq, void *arg) +{ + u32 irqstatus; + + irqstatus = dss_read_reg(DSS_IRQSTATUS); + + if (irqstatus & (1<<0)) /* DISPC_IRQ */ + dispc_irq_handler(); +#ifdef CONFIG_OMAP2_DSS_DSI + if (irqstatus & (1<<1)) /* DSI_IRQ */ + dsi_irq_handler(); +#endif + + return IRQ_HANDLED; +} + +static int _omap_dss_wait_reset(void) +{ + unsigned timeout = 1000; + + while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) { + udelay(1); + if (!--timeout) { + DSSERR("soft reset failed\n"); + return -ENODEV; + } + } + + return 0; +} + +static int _omap_dss_reset(void) +{ + /* Soft reset */ + REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1); + return _omap_dss_wait_reset(); +} + +void dss_set_venc_output(enum omap_dss_venc_type type) +{ + int l = 0; + + if (type == OMAP_DSS_VENC_TYPE_COMPOSITE) + l = 0; + else if (type == OMAP_DSS_VENC_TYPE_SVIDEO) + l = 1; + else + BUG(); + + /* venc out selection. 0 = comp, 1 = svideo */ + REG_FLD_MOD(DSS_CONTROL, l, 6, 6); +} + +void dss_set_dac_pwrdn_bgz(bool enable) +{ + REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ +} + +int dss_init(bool skip_init) +{ + int r; + u32 rev; + + dss.base = ioremap(DSS_BASE, DSS_SZ_REGS); + if (!dss.base) { + DSSERR("can't ioremap DSS\n"); + r = -ENOMEM; + goto fail0; + } + + if (!skip_init) { + /* disable LCD and DIGIT output. This seems to fix the synclost + * problem that we get, if the bootloader starts the DSS and + * the kernel resets it */ + omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); + + /* We need to wait here a bit, otherwise we sometimes start to + * get synclost errors, and after that only power cycle will + * restore DSS functionality. I have no idea why this happens. + * And we have to wait _before_ resetting the DSS, but after + * enabling clocks. + */ + msleep(50); + + _omap_dss_reset(); + } + + /* autoidle */ + REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0); + + /* Select DPLL */ + REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); + +#ifdef CONFIG_OMAP2_DSS_VENC + REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ + REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ + REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ +#endif + + r = request_irq(INT_24XX_DSS_IRQ, + cpu_is_omap24xx() + ? dss_irq_handler_omap2 + : dss_irq_handler_omap3, + 0, "OMAP DSS", NULL); + + if (r < 0) { + DSSERR("omap2 dss: request_irq failed\n"); + goto fail1; + } + + if (cpu_is_omap34xx()) { + dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); + if (IS_ERR(dss.dpll4_m4_ck)) { + DSSERR("Failed to get dpll4_m4_ck\n"); + r = PTR_ERR(dss.dpll4_m4_ck); + goto fail2; + } + } + + dss_save_context(); + + rev = dss_read_reg(DSS_REVISION); + printk(KERN_INFO "OMAP DSS rev %d.%d\n", + FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); + + return 0; + +fail2: + free_irq(INT_24XX_DSS_IRQ, NULL); +fail1: + iounmap(dss.base); +fail0: + return r; +} + +void dss_exit(void) +{ + if (cpu_is_omap34xx()) + clk_put(dss.dpll4_m4_ck); + + free_irq(INT_24XX_DSS_IRQ, NULL); + + iounmap(dss.base); +} + diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h new file mode 100644 index 0000000000000000000000000000000000000000..8da5ac42151b7bad6fbcdabf64afc9711737c346 --- /dev/null +++ b/drivers/video/omap2/dss/dss.h @@ -0,0 +1,370 @@ +/* + * linux/drivers/video/omap2/dss/dss.h + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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, see . + */ + +#ifndef __OMAP2_DSS_H +#define __OMAP2_DSS_H + +#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT +#define DEBUG +#endif + +#ifdef DEBUG +extern unsigned int dss_debug; +#ifdef DSS_SUBSYS_NAME +#define DSSDBG(format, ...) \ + if (dss_debug) \ + printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \ + ## __VA_ARGS__) +#else +#define DSSDBG(format, ...) \ + if (dss_debug) \ + printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__) +#endif + +#ifdef DSS_SUBSYS_NAME +#define DSSDBGF(format, ...) \ + if (dss_debug) \ + printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \ + ": %s(" format ")\n", \ + __func__, \ + ## __VA_ARGS__) +#else +#define DSSDBGF(format, ...) \ + if (dss_debug) \ + printk(KERN_DEBUG "omapdss: " \ + ": %s(" format ")\n", \ + __func__, \ + ## __VA_ARGS__) +#endif + +#else /* DEBUG */ +#define DSSDBG(format, ...) +#define DSSDBGF(format, ...) +#endif + + +#ifdef DSS_SUBSYS_NAME +#define DSSERR(format, ...) \ + printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \ + ## __VA_ARGS__) +#else +#define DSSERR(format, ...) \ + printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__) +#endif + +#ifdef DSS_SUBSYS_NAME +#define DSSINFO(format, ...) \ + printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \ + ## __VA_ARGS__) +#else +#define DSSINFO(format, ...) \ + printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__) +#endif + +#ifdef DSS_SUBSYS_NAME +#define DSSWARN(format, ...) \ + printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \ + ## __VA_ARGS__) +#else +#define DSSWARN(format, ...) \ + printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__) +#endif + +/* OMAP TRM gives bitfields as start:end, where start is the higher bit + number. For example 7:0 */ +#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end)) +#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end)) +#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end)) +#define FLD_MOD(orig, val, start, end) \ + (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) + +#define DISPC_MAX_FCK 173000000 + +enum omap_burst_size { + OMAP_DSS_BURST_4x32 = 0, + OMAP_DSS_BURST_8x32 = 1, + OMAP_DSS_BURST_16x32 = 2, +}; + +enum omap_parallel_interface_mode { + OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */ + OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */ + OMAP_DSS_PARALLELMODE_DSI, +}; + +enum dss_clock { + DSS_CLK_ICK = 1 << 0, + DSS_CLK_FCK1 = 1 << 1, + DSS_CLK_FCK2 = 1 << 2, + DSS_CLK_54M = 1 << 3, + DSS_CLK_96M = 1 << 4, +}; + +struct dss_clock_info { + /* rates that we get with dividers below */ + unsigned long fck; + + /* dividers */ + u16 fck_div; +}; + +struct dispc_clock_info { + /* rates that we get with dividers below */ + unsigned long lck; + unsigned long pck; + + /* dividers */ + u16 lck_div; + u16 pck_div; +}; + +struct dsi_clock_info { + /* rates that we get with dividers below */ + unsigned long fint; + unsigned long clkin4ddr; + unsigned long clkin; + unsigned long dsi1_pll_fclk; + unsigned long dsi2_pll_fclk; + + unsigned long lp_clk; + + /* dividers */ + u16 regn; + u16 regm; + u16 regm3; + u16 regm4; + + u16 lp_clk_div; + + u8 highfreq; + bool use_dss2_fck; +}; + +struct seq_file; +struct platform_device; + +/* core */ +void dss_clk_enable(enum dss_clock clks); +void dss_clk_disable(enum dss_clock clks); +unsigned long dss_clk_get_rate(enum dss_clock clk); +int dss_need_ctx_restore(void); +void dss_dump_clocks(struct seq_file *s); +struct bus_type *dss_get_bus(void); + +/* display */ +int dss_suspend_all_devices(void); +int dss_resume_all_devices(void); +void dss_disable_all_devices(void); + +void dss_init_device(struct platform_device *pdev, + struct omap_dss_device *dssdev); +void dss_uninit_device(struct platform_device *pdev, + struct omap_dss_device *dssdev); +bool dss_use_replication(struct omap_dss_device *dssdev, + enum omap_color_mode mode); +void default_get_overlay_fifo_thresholds(enum omap_plane plane, + u32 fifo_size, enum omap_burst_size *burst_size, + u32 *fifo_low, u32 *fifo_high); + +/* manager */ +int dss_init_overlay_managers(struct platform_device *pdev); +void dss_uninit_overlay_managers(struct platform_device *pdev); +int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); +void dss_setup_partial_planes(struct omap_dss_device *dssdev, + u16 *x, u16 *y, u16 *w, u16 *h); +void dss_start_update(struct omap_dss_device *dssdev); + +/* overlay */ +void dss_init_overlays(struct platform_device *pdev); +void dss_uninit_overlays(struct platform_device *pdev); +int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev); +void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); +#ifdef L4_EXAMPLE +void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr); +#endif +void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); + +/* DSS */ +int dss_init(bool skip_init); +void dss_exit(void); + +void dss_save_context(void); +void dss_restore_context(void); + +void dss_dump_regs(struct seq_file *s); + +void dss_sdi_init(u8 datapairs); +int dss_sdi_enable(void); +void dss_sdi_disable(void); + +void dss_select_clk_source(bool dsi, bool dispc); +int dss_get_dsi_clk_source(void); +int dss_get_dispc_clk_source(void); +void dss_set_venc_output(enum omap_dss_venc_type type); +void dss_set_dac_pwrdn_bgz(bool enable); + +unsigned long dss_get_dpll4_rate(void); +int dss_calc_clock_rates(struct dss_clock_info *cinfo); +int dss_set_clock_div(struct dss_clock_info *cinfo); +int dss_get_clock_div(struct dss_clock_info *cinfo); +int dss_calc_clock_div(bool is_tft, unsigned long req_pck, + struct dss_clock_info *dss_cinfo, + struct dispc_clock_info *dispc_cinfo); + +/* SDI */ +int sdi_init(bool skip_init); +void sdi_exit(void); +int sdi_init_display(struct omap_dss_device *display); + +/* DSI */ +int dsi_init(struct platform_device *pdev); +void dsi_exit(void); + +void dsi_dump_clocks(struct seq_file *s); +void dsi_dump_regs(struct seq_file *s); + +void dsi_save_context(void); +void dsi_restore_context(void); + +int dsi_init_display(struct omap_dss_device *display); +void dsi_irq_handler(void); +unsigned long dsi_get_dsi1_pll_rate(void); +int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo); +int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, + struct dsi_clock_info *cinfo, + struct dispc_clock_info *dispc_cinfo); +int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, + bool enable_hsdiv); +void dsi_pll_uninit(void); +void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, + u32 fifo_size, enum omap_burst_size *burst_size, + u32 *fifo_low, u32 *fifo_high); + +/* DPI */ +int dpi_init(void); +void dpi_exit(void); +int dpi_init_display(struct omap_dss_device *dssdev); + +/* DISPC */ +int dispc_init(void); +void dispc_exit(void); +void dispc_dump_clocks(struct seq_file *s); +void dispc_dump_regs(struct seq_file *s); +void dispc_irq_handler(void); +void dispc_fake_vsync_irq(void); + +void dispc_save_context(void); +void dispc_restore_context(void); + +void dispc_enable_sidle(void); +void dispc_disable_sidle(void); + +void dispc_lcd_enable_signal_polarity(bool act_high); +void dispc_lcd_enable_signal(bool enable); +void dispc_pck_free_enable(bool enable); +void dispc_enable_fifohandcheck(bool enable); + +void dispc_set_lcd_size(u16 width, u16 height); +void dispc_set_digit_size(u16 width, u16 height); +u32 dispc_get_plane_fifo_size(enum omap_plane plane); +void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high); +void dispc_enable_fifomerge(bool enable); +void dispc_set_burst_size(enum omap_plane plane, + enum omap_burst_size burst_size); + +void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr); +void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr); +void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y); +void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height); +void dispc_set_channel_out(enum omap_plane plane, + enum omap_channel channel_out); + +int dispc_setup_plane(enum omap_plane plane, + u32 paddr, u16 screen_width, + u16 pos_x, u16 pos_y, + u16 width, u16 height, + u16 out_width, u16 out_height, + enum omap_color_mode color_mode, + bool ilace, + enum omap_dss_rotation_type rotation_type, + u8 rotation, bool mirror, + u8 global_alpha); + +bool dispc_go_busy(enum omap_channel channel); +void dispc_go(enum omap_channel channel); +void dispc_enable_lcd_out(bool enable); +void dispc_enable_digit_out(bool enable); +int dispc_enable_plane(enum omap_plane plane, bool enable); +void dispc_enable_replication(enum omap_plane plane, bool enable); + +void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode); +void dispc_set_tft_data_lines(u8 data_lines); +void dispc_set_lcd_display_type(enum omap_lcd_display_type type); +void dispc_set_loadmode(enum omap_dss_load_mode mode); + +void dispc_set_default_color(enum omap_channel channel, u32 color); +u32 dispc_get_default_color(enum omap_channel channel); +void dispc_set_trans_key(enum omap_channel ch, + enum omap_dss_trans_key_type type, + u32 trans_key); +void dispc_get_trans_key(enum omap_channel ch, + enum omap_dss_trans_key_type *type, + u32 *trans_key); +void dispc_enable_trans_key(enum omap_channel ch, bool enable); +void dispc_enable_alpha_blending(enum omap_channel ch, bool enable); +bool dispc_trans_key_enabled(enum omap_channel ch); +bool dispc_alpha_blending_enabled(enum omap_channel ch); + +bool dispc_lcd_timings_ok(struct omap_video_timings *timings); +void dispc_set_lcd_timings(struct omap_video_timings *timings); +unsigned long dispc_fclk_rate(void); +unsigned long dispc_lclk_rate(void); +unsigned long dispc_pclk_rate(void); +void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb); +void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, + struct dispc_clock_info *cinfo); +int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, + struct dispc_clock_info *cinfo); +int dispc_set_clock_div(struct dispc_clock_info *cinfo); +int dispc_get_clock_div(struct dispc_clock_info *cinfo); + + +/* VENC */ +int venc_init(struct platform_device *pdev); +void venc_exit(void); +void venc_dump_regs(struct seq_file *s); +int venc_init_display(struct omap_dss_device *display); + +/* RFBI */ +int rfbi_init(void); +void rfbi_exit(void); +void rfbi_dump_regs(struct seq_file *s); + +int rfbi_configure(int rfbi_module, int bpp, int lines); +void rfbi_enable_rfbi(bool enable); +void rfbi_transfer_area(u16 width, u16 height, + void (callback)(void *data), void *data); +void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); +unsigned long rfbi_get_max_tx_rate(void); +int rfbi_init_display(struct omap_dss_device *display); + +#endif diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c new file mode 100644 index 0000000000000000000000000000000000000000..27d9c465c8518554cdcdb5f1ff046bd491bcdde6 --- /dev/null +++ b/drivers/video/omap2/dss/manager.c @@ -0,0 +1,1487 @@ +/* + * linux/drivers/video/omap2/dss/manager.c + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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, see . + */ + +#define DSS_SUBSYS_NAME "MANAGER" + +#include +#include +#include +#include +#include + +#include +#include + +#include "dss.h" + +static int num_managers; +static struct list_head manager_list; + +static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name); +} + +static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", + mgr->device ? mgr->device->name : ""); +} + +static ssize_t manager_display_store(struct omap_overlay_manager *mgr, + const char *buf, size_t size) +{ + int r = 0; + size_t len = size; + struct omap_dss_device *dssdev = NULL; + + int match(struct omap_dss_device *dssdev, void *data) + { + const char *str = data; + return sysfs_streq(dssdev->name, str); + } + + if (buf[size-1] == '\n') + --len; + + if (len > 0) + dssdev = omap_dss_find_device((void *)buf, match); + + if (len > 0 && dssdev == NULL) + return -EINVAL; + + if (dssdev) + DSSDBG("display %s found\n", dssdev->name); + + if (mgr->device) { + r = mgr->unset_device(mgr); + if (r) { + DSSERR("failed to unset display\n"); + goto put_device; + } + } + + if (dssdev) { + r = mgr->set_device(mgr, dssdev); + if (r) { + DSSERR("failed to set manager\n"); + goto put_device; + } + + r = mgr->apply(mgr); + if (r) { + DSSERR("failed to apply dispc config\n"); + goto put_device; + } + } + +put_device: + if (dssdev) + omap_dss_put_device(dssdev); + + return r ? r : size; +} + +static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color); +} + +static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, + const char *buf, size_t size) +{ + struct omap_overlay_manager_info info; + u32 color; + int r; + + if (sscanf(buf, "%d", &color) != 1) + return -EINVAL; + + mgr->get_manager_info(mgr, &info); + + info.default_color = color; + + r = mgr->set_manager_info(mgr, &info); + if (r) + return r; + + r = mgr->apply(mgr); + if (r) + return r; + + return size; +} + +static const char *trans_key_type_str[] = { + "gfx-destination", + "video-source", +}; + +static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr, + char *buf) +{ + enum omap_dss_trans_key_type key_type; + + key_type = mgr->info.trans_key_type; + BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str)); + + return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]); +} + +static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr, + const char *buf, size_t size) +{ + enum omap_dss_trans_key_type key_type; + struct omap_overlay_manager_info info; + int r; + + for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST; + key_type < ARRAY_SIZE(trans_key_type_str); key_type++) { + if (sysfs_streq(buf, trans_key_type_str[key_type])) + break; + } + + if (key_type == ARRAY_SIZE(trans_key_type_str)) + return -EINVAL; + + mgr->get_manager_info(mgr, &info); + + info.trans_key_type = key_type; + + r = mgr->set_manager_info(mgr, &info); + if (r) + return r; + + r = mgr->apply(mgr); + if (r) + return r; + + return size; +} + +static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key); +} + +static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, + const char *buf, size_t size) +{ + struct omap_overlay_manager_info info; + u32 key_value; + int r; + + if (sscanf(buf, "%d", &key_value) != 1) + return -EINVAL; + + mgr->get_manager_info(mgr, &info); + + info.trans_key = key_value; + + r = mgr->set_manager_info(mgr, &info); + if (r) + return r; + + r = mgr->apply(mgr); + if (r) + return r; + + return size; +} + +static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled); +} + +static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr, + const char *buf, size_t size) +{ + struct omap_overlay_manager_info info; + int enable; + int r; + + if (sscanf(buf, "%d", &enable) != 1) + return -EINVAL; + + mgr->get_manager_info(mgr, &info); + + info.trans_enabled = enable ? true : false; + + r = mgr->set_manager_info(mgr, &info); + if (r) + return r; + + r = mgr->apply(mgr); + if (r) + return r; + + return size; +} + +static ssize_t manager_alpha_blending_enabled_show( + struct omap_overlay_manager *mgr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled); +} + +static ssize_t manager_alpha_blending_enabled_store( + struct omap_overlay_manager *mgr, + const char *buf, size_t size) +{ + struct omap_overlay_manager_info info; + int enable; + int r; + + if (sscanf(buf, "%d", &enable) != 1) + return -EINVAL; + + mgr->get_manager_info(mgr, &info); + + info.alpha_enabled = enable ? true : false; + + r = mgr->set_manager_info(mgr, &info); + if (r) + return r; + + r = mgr->apply(mgr); + if (r) + return r; + + return size; +} + +struct manager_attribute { + struct attribute attr; + ssize_t (*show)(struct omap_overlay_manager *, char *); + ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t); +}; + +#define MANAGER_ATTR(_name, _mode, _show, _store) \ + struct manager_attribute manager_attr_##_name = \ + __ATTR(_name, _mode, _show, _store) + +static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL); +static MANAGER_ATTR(display, S_IRUGO|S_IWUSR, + manager_display_show, manager_display_store); +static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR, + manager_default_color_show, manager_default_color_store); +static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR, + manager_trans_key_type_show, manager_trans_key_type_store); +static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR, + manager_trans_key_value_show, manager_trans_key_value_store); +static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR, + manager_trans_key_enabled_show, + manager_trans_key_enabled_store); +static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR, + manager_alpha_blending_enabled_show, + manager_alpha_blending_enabled_store); + + +static struct attribute *manager_sysfs_attrs[] = { + &manager_attr_name.attr, + &manager_attr_display.attr, + &manager_attr_default_color.attr, + &manager_attr_trans_key_type.attr, + &manager_attr_trans_key_value.attr, + &manager_attr_trans_key_enabled.attr, + &manager_attr_alpha_blending_enabled.attr, + NULL +}; + +static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct omap_overlay_manager *manager; + struct manager_attribute *manager_attr; + + manager = container_of(kobj, struct omap_overlay_manager, kobj); + manager_attr = container_of(attr, struct manager_attribute, attr); + + if (!manager_attr->show) + return -ENOENT; + + return manager_attr->show(manager, buf); +} + +static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t size) +{ + struct omap_overlay_manager *manager; + struct manager_attribute *manager_attr; + + manager = container_of(kobj, struct omap_overlay_manager, kobj); + manager_attr = container_of(attr, struct manager_attribute, attr); + + if (!manager_attr->store) + return -ENOENT; + + return manager_attr->store(manager, buf, size); +} + +static struct sysfs_ops manager_sysfs_ops = { + .show = manager_attr_show, + .store = manager_attr_store, +}; + +static struct kobj_type manager_ktype = { + .sysfs_ops = &manager_sysfs_ops, + .default_attrs = manager_sysfs_attrs, +}; + +/* + * We have 4 levels of cache for the dispc settings. First two are in SW and + * the latter two in HW. + * + * +--------------------+ + * |overlay/manager_info| + * +--------------------+ + * v + * apply() + * v + * +--------------------+ + * | dss_cache | + * +--------------------+ + * v + * configure() + * v + * +--------------------+ + * | shadow registers | + * +--------------------+ + * v + * VFP or lcd/digit_enable + * v + * +--------------------+ + * | registers | + * +--------------------+ + */ + +struct overlay_cache_data { + /* If true, cache changed, but not written to shadow registers. Set + * in apply(), cleared when registers written. */ + bool dirty; + /* If true, shadow registers contain changed values not yet in real + * registers. Set when writing to shadow registers, cleared at + * VSYNC/EVSYNC */ + bool shadow_dirty; + + bool enabled; + + u32 paddr; + void __iomem *vaddr; + u16 screen_width; + u16 width; + u16 height; + enum omap_color_mode color_mode; + u8 rotation; + enum omap_dss_rotation_type rotation_type; + bool mirror; + + u16 pos_x; + u16 pos_y; + u16 out_width; /* if 0, out_width == width */ + u16 out_height; /* if 0, out_height == height */ + u8 global_alpha; + + enum omap_channel channel; + bool replication; + bool ilace; + + enum omap_burst_size burst_size; + u32 fifo_low; + u32 fifo_high; + + bool manual_update; +}; + +struct manager_cache_data { + /* If true, cache changed, but not written to shadow registers. Set + * in apply(), cleared when registers written. */ + bool dirty; + /* If true, shadow registers contain changed values not yet in real + * registers. Set when writing to shadow registers, cleared at + * VSYNC/EVSYNC */ + bool shadow_dirty; + + u32 default_color; + + enum omap_dss_trans_key_type trans_key_type; + u32 trans_key; + bool trans_enabled; + + bool alpha_enabled; + + bool manual_upd_display; + bool manual_update; + bool do_manual_update; + + /* manual update region */ + u16 x, y, w, h; +}; + +static struct { + spinlock_t lock; + struct overlay_cache_data overlay_cache[3]; + struct manager_cache_data manager_cache[2]; + + bool irq_enabled; +} dss_cache; + + + +static int omap_dss_set_device(struct omap_overlay_manager *mgr, + struct omap_dss_device *dssdev) +{ + int i; + int r; + + if (dssdev->manager) { + DSSERR("display '%s' already has a manager '%s'\n", + dssdev->name, dssdev->manager->name); + return -EINVAL; + } + + if ((mgr->supported_displays & dssdev->type) == 0) { + DSSERR("display '%s' does not support manager '%s'\n", + dssdev->name, mgr->name); + return -EINVAL; + } + + for (i = 0; i < mgr->num_overlays; i++) { + struct omap_overlay *ovl = mgr->overlays[i]; + + if (ovl->manager != mgr || !ovl->info.enabled) + continue; + + r = dss_check_overlay(ovl, dssdev); + if (r) + return r; + } + + dssdev->manager = mgr; + mgr->device = dssdev; + mgr->device_changed = true; + + return 0; +} + +static int omap_dss_unset_device(struct omap_overlay_manager *mgr) +{ + if (!mgr->device) { + DSSERR("failed to unset display, display not set.\n"); + return -EINVAL; + } + + mgr->device->manager = NULL; + mgr->device = NULL; + mgr->device_changed = true; + + return 0; +} + +static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) +{ + unsigned long timeout = msecs_to_jiffies(500); + struct manager_cache_data *mc; + enum omap_channel channel; + u32 irq; + int r; + int i; + + if (!mgr->device) + return 0; + + if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) { + irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; + channel = OMAP_DSS_CHANNEL_DIGIT; + } else { + if (mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { + enum omap_dss_update_mode mode; + mode = mgr->device->get_update_mode(mgr->device); + if (mode != OMAP_DSS_UPDATE_AUTO) + return 0; + + irq = DISPC_IRQ_FRAMEDONE; + } else { + irq = DISPC_IRQ_VSYNC; + } + channel = OMAP_DSS_CHANNEL_LCD; + } + + mc = &dss_cache.manager_cache[mgr->id]; + i = 0; + while (1) { + unsigned long flags; + bool shadow_dirty, dirty; + + spin_lock_irqsave(&dss_cache.lock, flags); + dirty = mc->dirty; + shadow_dirty = mc->shadow_dirty; + spin_unlock_irqrestore(&dss_cache.lock, flags); + + if (!dirty && !shadow_dirty) { + r = 0; + break; + } + + /* 4 iterations is the worst case: + * 1 - initial iteration, dirty = true (between VFP and VSYNC) + * 2 - first VSYNC, dirty = true + * 3 - dirty = false, shadow_dirty = true + * 4 - shadow_dirty = false */ + if (i++ == 3) { + DSSERR("mgr(%d)->wait_for_go() not finishing\n", + mgr->id); + r = 0; + break; + } + + r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); + if (r == -ERESTARTSYS) + break; + + if (r) { + DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id); + break; + } + } + + return r; +} + +int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) +{ + unsigned long timeout = msecs_to_jiffies(500); + enum omap_channel channel; + struct overlay_cache_data *oc; + struct omap_dss_device *dssdev; + u32 irq; + int r; + int i; + + if (!ovl->manager || !ovl->manager->device) + return 0; + + dssdev = ovl->manager->device; + + if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { + irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; + channel = OMAP_DSS_CHANNEL_DIGIT; + } else { + if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { + enum omap_dss_update_mode mode; + mode = dssdev->get_update_mode(dssdev); + if (mode != OMAP_DSS_UPDATE_AUTO) + return 0; + + irq = DISPC_IRQ_FRAMEDONE; + } else { + irq = DISPC_IRQ_VSYNC; + } + channel = OMAP_DSS_CHANNEL_LCD; + } + + oc = &dss_cache.overlay_cache[ovl->id]; + i = 0; + while (1) { + unsigned long flags; + bool shadow_dirty, dirty; + + spin_lock_irqsave(&dss_cache.lock, flags); + dirty = oc->dirty; + shadow_dirty = oc->shadow_dirty; + spin_unlock_irqrestore(&dss_cache.lock, flags); + + if (!dirty && !shadow_dirty) { + r = 0; + break; + } + + /* 4 iterations is the worst case: + * 1 - initial iteration, dirty = true (between VFP and VSYNC) + * 2 - first VSYNC, dirty = true + * 3 - dirty = false, shadow_dirty = true + * 4 - shadow_dirty = false */ + if (i++ == 3) { + DSSERR("ovl(%d)->wait_for_go() not finishing\n", + ovl->id); + r = 0; + break; + } + + r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); + if (r == -ERESTARTSYS) + break; + + if (r) { + DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id); + break; + } + } + + return r; +} + +static int overlay_enabled(struct omap_overlay *ovl) +{ + return ovl->info.enabled && ovl->manager && ovl->manager->device; +} + +/* Is rect1 a subset of rect2? */ +static bool rectangle_subset(int x1, int y1, int w1, int h1, + int x2, int y2, int w2, int h2) +{ + if (x1 < x2 || y1 < y2) + return false; + + if (x1 + w1 > x2 + w2) + return false; + + if (y1 + h1 > y2 + h2) + return false; + + return true; +} + +/* Do rect1 and rect2 overlap? */ +static bool rectangle_intersects(int x1, int y1, int w1, int h1, + int x2, int y2, int w2, int h2) +{ + if (x1 >= x2 + w2) + return false; + + if (x2 >= x1 + w1) + return false; + + if (y1 >= y2 + h2) + return false; + + if (y2 >= y1 + h1) + return false; + + return true; +} + +static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc) +{ + if (oc->out_width != 0 && oc->width != oc->out_width) + return true; + + if (oc->out_height != 0 && oc->height != oc->out_height) + return true; + + return false; +} + +static int configure_overlay(enum omap_plane plane) +{ + struct overlay_cache_data *c; + struct manager_cache_data *mc; + u16 outw, outh; + u16 x, y, w, h; + u32 paddr; + int r; + + DSSDBGF("%d", plane); + + c = &dss_cache.overlay_cache[plane]; + + if (!c->enabled) { + dispc_enable_plane(plane, 0); + return 0; + } + + mc = &dss_cache.manager_cache[c->channel]; + + x = c->pos_x; + y = c->pos_y; + w = c->width; + h = c->height; + outw = c->out_width == 0 ? c->width : c->out_width; + outh = c->out_height == 0 ? c->height : c->out_height; + paddr = c->paddr; + + if (c->manual_update && mc->do_manual_update) { + unsigned bpp; + /* If the overlay is outside the update region, disable it */ + if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, + x, y, outw, outh)) { + dispc_enable_plane(plane, 0); + return 0; + } + + switch (c->color_mode) { + case OMAP_DSS_COLOR_RGB16: + case OMAP_DSS_COLOR_ARGB16: + case OMAP_DSS_COLOR_YUV2: + case OMAP_DSS_COLOR_UYVY: + bpp = 16; + break; + + case OMAP_DSS_COLOR_RGB24P: + bpp = 24; + break; + + case OMAP_DSS_COLOR_RGB24U: + case OMAP_DSS_COLOR_ARGB32: + case OMAP_DSS_COLOR_RGBA32: + case OMAP_DSS_COLOR_RGBX32: + bpp = 32; + break; + + default: + BUG(); + } + + if (dispc_is_overlay_scaled(c)) { + /* If the overlay is scaled, the update area has + * already been enlarged to cover the whole overlay. We + * only need to adjust x/y here */ + x = c->pos_x - mc->x; + y = c->pos_y - mc->y; + } else { + if (mc->x > c->pos_x) { + x = 0; + w -= (mc->x - c->pos_x); + paddr += (mc->x - c->pos_x) * bpp / 8; + } else { + x = c->pos_x - mc->x; + } + + if (mc->y > c->pos_y) { + y = 0; + h -= (mc->y - c->pos_y); + paddr += (mc->y - c->pos_y) * c->screen_width * + bpp / 8; + } else { + y = c->pos_y - mc->y; + } + + if (mc->w < (x+w)) + w -= (x+w) - (mc->w); + + if (mc->h < (y+h)) + h -= (y+h) - (mc->h); + + outw = w; + outh = h; + } + } + + r = dispc_setup_plane(plane, + paddr, + c->screen_width, + x, y, + w, h, + outw, outh, + c->color_mode, + c->ilace, + c->rotation_type, + c->rotation, + c->mirror, + c->global_alpha); + + if (r) { + /* this shouldn't happen */ + DSSERR("dispc_setup_plane failed for ovl %d\n", plane); + dispc_enable_plane(plane, 0); + return r; + } + + dispc_enable_replication(plane, c->replication); + + dispc_set_burst_size(plane, c->burst_size); + dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high); + + dispc_enable_plane(plane, 1); + + return 0; +} + +static void configure_manager(enum omap_channel channel) +{ + struct manager_cache_data *c; + + DSSDBGF("%d", channel); + + c = &dss_cache.manager_cache[channel]; + + dispc_set_trans_key(channel, c->trans_key_type, c->trans_key); + dispc_enable_trans_key(channel, c->trans_enabled); + dispc_enable_alpha_blending(channel, c->alpha_enabled); +} + +/* configure_dispc() tries to write values from cache to shadow registers. + * It writes only to those managers/overlays that are not busy. + * returns 0 if everything could be written to shadow registers. + * returns 1 if not everything could be written to shadow registers. */ +static int configure_dispc(void) +{ + struct overlay_cache_data *oc; + struct manager_cache_data *mc; + const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); + const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); + int i; + int r; + bool mgr_busy[2]; + bool mgr_go[2]; + bool busy; + + r = 0; + busy = false; + + mgr_busy[0] = dispc_go_busy(0); + mgr_busy[1] = dispc_go_busy(1); + mgr_go[0] = false; + mgr_go[1] = false; + + /* Commit overlay settings */ + for (i = 0; i < num_ovls; ++i) { + oc = &dss_cache.overlay_cache[i]; + mc = &dss_cache.manager_cache[oc->channel]; + + if (!oc->dirty) + continue; + + if (oc->manual_update && !mc->do_manual_update) + continue; + + if (mgr_busy[oc->channel]) { + busy = true; + continue; + } + + r = configure_overlay(i); + if (r) + DSSERR("configure_overlay %d failed\n", i); + + oc->dirty = false; + oc->shadow_dirty = true; + mgr_go[oc->channel] = true; + } + + /* Commit manager settings */ + for (i = 0; i < num_mgrs; ++i) { + mc = &dss_cache.manager_cache[i]; + + if (!mc->dirty) + continue; + + if (mc->manual_update && !mc->do_manual_update) + continue; + + if (mgr_busy[i]) { + busy = true; + continue; + } + + configure_manager(i); + mc->dirty = false; + mc->shadow_dirty = true; + mgr_go[i] = true; + } + + /* set GO */ + for (i = 0; i < num_mgrs; ++i) { + mc = &dss_cache.manager_cache[i]; + + if (!mgr_go[i]) + continue; + + /* We don't need GO with manual update display. LCD iface will + * always be turned off after frame, and new settings will be + * taken in to use at next update */ + if (!mc->manual_upd_display) + dispc_go(i); + } + + if (busy) + r = 1; + else + r = 0; + + return r; +} + +/* Configure dispc for partial update. Return possibly modified update + * area */ +void dss_setup_partial_planes(struct omap_dss_device *dssdev, + u16 *xi, u16 *yi, u16 *wi, u16 *hi) +{ + struct overlay_cache_data *oc; + struct manager_cache_data *mc; + const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); + struct omap_overlay_manager *mgr; + int i; + u16 x, y, w, h; + unsigned long flags; + + x = *xi; + y = *yi; + w = *wi; + h = *hi; + + DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n", + *xi, *yi, *wi, *hi); + + mgr = dssdev->manager; + + if (!mgr) { + DSSDBG("no manager\n"); + return; + } + + spin_lock_irqsave(&dss_cache.lock, flags); + + /* We need to show the whole overlay if it is scaled. So look for + * those, and make the update area larger if found. + * Also mark the overlay cache dirty */ + for (i = 0; i < num_ovls; ++i) { + unsigned x1, y1, x2, y2; + unsigned outw, outh; + + oc = &dss_cache.overlay_cache[i]; + + if (oc->channel != mgr->id) + continue; + + oc->dirty = true; + + if (!oc->enabled) + continue; + + if (!dispc_is_overlay_scaled(oc)) + continue; + + outw = oc->out_width == 0 ? oc->width : oc->out_width; + outh = oc->out_height == 0 ? oc->height : oc->out_height; + + /* is the overlay outside the update region? */ + if (!rectangle_intersects(x, y, w, h, + oc->pos_x, oc->pos_y, + outw, outh)) + continue; + + /* if the overlay totally inside the update region? */ + if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh, + x, y, w, h)) + continue; + + if (x > oc->pos_x) + x1 = oc->pos_x; + else + x1 = x; + + if (y > oc->pos_y) + y1 = oc->pos_y; + else + y1 = y; + + if ((x + w) < (oc->pos_x + outw)) + x2 = oc->pos_x + outw; + else + x2 = x + w; + + if ((y + h) < (oc->pos_y + outh)) + y2 = oc->pos_y + outh; + else + y2 = y + h; + + x = x1; + y = y1; + w = x2 - x1; + h = y2 - y1; + + DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n", + i, x, y, w, h); + } + + mc = &dss_cache.manager_cache[mgr->id]; + mc->do_manual_update = true; + mc->x = x; + mc->y = y; + mc->w = w; + mc->h = h; + + configure_dispc(); + + mc->do_manual_update = false; + + spin_unlock_irqrestore(&dss_cache.lock, flags); + + *xi = x; + *yi = y; + *wi = w; + *hi = h; +} + +void dss_start_update(struct omap_dss_device *dssdev) +{ + struct manager_cache_data *mc; + struct overlay_cache_data *oc; + const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); + const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); + struct omap_overlay_manager *mgr; + int i; + + mgr = dssdev->manager; + + for (i = 0; i < num_ovls; ++i) { + oc = &dss_cache.overlay_cache[i]; + if (oc->channel != mgr->id) + continue; + + oc->shadow_dirty = false; + } + + for (i = 0; i < num_mgrs; ++i) { + mc = &dss_cache.manager_cache[i]; + if (mgr->id != i) + continue; + + mc->shadow_dirty = false; + } + + dispc_enable_lcd_out(1); +} + +static void dss_apply_irq_handler(void *data, u32 mask) +{ + struct manager_cache_data *mc; + struct overlay_cache_data *oc; + const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); + const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); + int i, r; + bool mgr_busy[2]; + + mgr_busy[0] = dispc_go_busy(0); + mgr_busy[1] = dispc_go_busy(1); + + spin_lock(&dss_cache.lock); + + for (i = 0; i < num_ovls; ++i) { + oc = &dss_cache.overlay_cache[i]; + if (!mgr_busy[oc->channel]) + oc->shadow_dirty = false; + } + + for (i = 0; i < num_mgrs; ++i) { + mc = &dss_cache.manager_cache[i]; + if (!mgr_busy[i]) + mc->shadow_dirty = false; + } + + r = configure_dispc(); + if (r == 1) + goto end; + + /* re-read busy flags */ + mgr_busy[0] = dispc_go_busy(0); + mgr_busy[1] = dispc_go_busy(1); + + /* keep running as long as there are busy managers, so that + * we can collect overlay-applied information */ + for (i = 0; i < num_mgrs; ++i) { + if (mgr_busy[i]) + goto end; + } + + omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, + DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | + DISPC_IRQ_EVSYNC_EVEN); + dss_cache.irq_enabled = false; + +end: + spin_unlock(&dss_cache.lock); +} + +static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) +{ + struct overlay_cache_data *oc; + struct manager_cache_data *mc; + int i; + struct omap_overlay *ovl; + int num_planes_enabled = 0; + bool use_fifomerge; + unsigned long flags; + int r; + + DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name); + + spin_lock_irqsave(&dss_cache.lock, flags); + + /* Configure overlays */ + for (i = 0; i < omap_dss_get_num_overlays(); ++i) { + struct omap_dss_device *dssdev; + + ovl = omap_dss_get_overlay(i); + + if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) + continue; + + oc = &dss_cache.overlay_cache[ovl->id]; + + if (!overlay_enabled(ovl)) { + if (oc->enabled) { + oc->enabled = false; + oc->dirty = true; + } + continue; + } + + if (!ovl->info_dirty) { + if (oc->enabled) + ++num_planes_enabled; + continue; + } + + dssdev = ovl->manager->device; + + if (dss_check_overlay(ovl, dssdev)) { + if (oc->enabled) { + oc->enabled = false; + oc->dirty = true; + } + continue; + } + + ovl->info_dirty = false; + oc->dirty = true; + + oc->paddr = ovl->info.paddr; + oc->vaddr = ovl->info.vaddr; + oc->screen_width = ovl->info.screen_width; + oc->width = ovl->info.width; + oc->height = ovl->info.height; + oc->color_mode = ovl->info.color_mode; + oc->rotation = ovl->info.rotation; + oc->rotation_type = ovl->info.rotation_type; + oc->mirror = ovl->info.mirror; + oc->pos_x = ovl->info.pos_x; + oc->pos_y = ovl->info.pos_y; + oc->out_width = ovl->info.out_width; + oc->out_height = ovl->info.out_height; + oc->global_alpha = ovl->info.global_alpha; + + oc->replication = + dss_use_replication(dssdev, ovl->info.color_mode); + + oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC; + + oc->channel = ovl->manager->id; + + oc->enabled = true; + + oc->manual_update = + dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE && + dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO; + + ++num_planes_enabled; + } + + /* Configure managers */ + list_for_each_entry(mgr, &manager_list, list) { + struct omap_dss_device *dssdev; + + if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC)) + continue; + + mc = &dss_cache.manager_cache[mgr->id]; + + if (mgr->device_changed) { + mgr->device_changed = false; + mgr->info_dirty = true; + } + + if (!mgr->info_dirty) + continue; + + if (!mgr->device) + continue; + + dssdev = mgr->device; + + mgr->info_dirty = false; + mc->dirty = true; + + mc->default_color = mgr->info.default_color; + mc->trans_key_type = mgr->info.trans_key_type; + mc->trans_key = mgr->info.trans_key; + mc->trans_enabled = mgr->info.trans_enabled; + mc->alpha_enabled = mgr->info.alpha_enabled; + + mc->manual_upd_display = + dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; + + mc->manual_update = + dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE && + dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO; + } + + /* XXX TODO: Try to get fifomerge working. The problem is that it + * affects both managers, not individually but at the same time. This + * means the change has to be well synchronized. I guess the proper way + * is to have a two step process for fifo merge: + * fifomerge enable: + * 1. disable other planes, leaving one plane enabled + * 2. wait until the planes are disabled on HW + * 3. config merged fifo thresholds, enable fifomerge + * fifomerge disable: + * 1. config unmerged fifo thresholds, disable fifomerge + * 2. wait until fifo changes are in HW + * 3. enable planes + */ + use_fifomerge = false; + + /* Configure overlay fifos */ + for (i = 0; i < omap_dss_get_num_overlays(); ++i) { + struct omap_dss_device *dssdev; + u32 size; + + ovl = omap_dss_get_overlay(i); + + if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) + continue; + + oc = &dss_cache.overlay_cache[ovl->id]; + + if (!oc->enabled) + continue; + + dssdev = ovl->manager->device; + + size = dispc_get_plane_fifo_size(ovl->id); + if (use_fifomerge) + size *= 3; + + switch (dssdev->type) { + case OMAP_DISPLAY_TYPE_DPI: + case OMAP_DISPLAY_TYPE_DBI: + case OMAP_DISPLAY_TYPE_SDI: + case OMAP_DISPLAY_TYPE_VENC: + default_get_overlay_fifo_thresholds(ovl->id, size, + &oc->burst_size, &oc->fifo_low, + &oc->fifo_high); + break; +#ifdef CONFIG_OMAP2_DSS_DSI + case OMAP_DISPLAY_TYPE_DSI: + dsi_get_overlay_fifo_thresholds(ovl->id, size, + &oc->burst_size, &oc->fifo_low, + &oc->fifo_high); + break; +#endif + default: + BUG(); + } + } + + r = 0; + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + if (!dss_cache.irq_enabled) { + r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, + DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | + DISPC_IRQ_EVSYNC_EVEN); + dss_cache.irq_enabled = true; + } + configure_dispc(); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + + spin_unlock_irqrestore(&dss_cache.lock, flags); + + return r; +} + +static int dss_check_manager(struct omap_overlay_manager *mgr) +{ + /* OMAP supports only graphics source transparency color key and alpha + * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */ + + if (mgr->info.alpha_enabled && mgr->info.trans_enabled && + mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) + return -EINVAL; + + return 0; +} + +static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr, + struct omap_overlay_manager_info *info) +{ + int r; + struct omap_overlay_manager_info old_info; + + old_info = mgr->info; + mgr->info = *info; + + r = dss_check_manager(mgr); + if (r) { + mgr->info = old_info; + return r; + } + + mgr->info_dirty = true; + + return 0; +} + +static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr, + struct omap_overlay_manager_info *info) +{ + *info = mgr->info; +} + +static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager) +{ + ++num_managers; + list_add_tail(&manager->list, &manager_list); +} + +int dss_init_overlay_managers(struct platform_device *pdev) +{ + int i, r; + + spin_lock_init(&dss_cache.lock); + + INIT_LIST_HEAD(&manager_list); + + num_managers = 0; + + for (i = 0; i < 2; ++i) { + struct omap_overlay_manager *mgr; + mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); + + BUG_ON(mgr == NULL); + + switch (i) { + case 0: + mgr->name = "lcd"; + mgr->id = OMAP_DSS_CHANNEL_LCD; + mgr->supported_displays = + OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | + OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI; + break; + case 1: + mgr->name = "tv"; + mgr->id = OMAP_DSS_CHANNEL_DIGIT; + mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC; + break; + } + + mgr->set_device = &omap_dss_set_device; + mgr->unset_device = &omap_dss_unset_device; + mgr->apply = &omap_dss_mgr_apply; + mgr->set_manager_info = &omap_dss_mgr_set_info; + mgr->get_manager_info = &omap_dss_mgr_get_info; + mgr->wait_for_go = &dss_mgr_wait_for_go; + + mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC; + + dss_overlay_setup_dispc_manager(mgr); + + omap_dss_add_overlay_manager(mgr); + + r = kobject_init_and_add(&mgr->kobj, &manager_ktype, + &pdev->dev.kobj, "manager%d", i); + + if (r) { + DSSERR("failed to create sysfs file\n"); + continue; + } + } + +#ifdef L4_EXAMPLE + { + int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr) + { + DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name); + + return 0; + } + + struct omap_overlay_manager *mgr; + mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); + + BUG_ON(mgr == NULL); + + mgr->name = "l4"; + mgr->supported_displays = + OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI; + + mgr->set_device = &omap_dss_set_device; + mgr->unset_device = &omap_dss_unset_device; + mgr->apply = &omap_dss_mgr_apply_l4; + mgr->set_manager_info = &omap_dss_mgr_set_info; + mgr->get_manager_info = &omap_dss_mgr_get_info; + + dss_overlay_setup_l4_manager(mgr); + + omap_dss_add_overlay_manager(mgr); + + r = kobject_init_and_add(&mgr->kobj, &manager_ktype, + &pdev->dev.kobj, "managerl4"); + + if (r) + DSSERR("failed to create sysfs file\n"); + } +#endif + + return 0; +} + +void dss_uninit_overlay_managers(struct platform_device *pdev) +{ + struct omap_overlay_manager *mgr; + + while (!list_empty(&manager_list)) { + mgr = list_first_entry(&manager_list, + struct omap_overlay_manager, list); + list_del(&mgr->list); + kobject_del(&mgr->kobj); + kobject_put(&mgr->kobj); + kfree(mgr); + } + + num_managers = 0; +} + +int omap_dss_get_num_overlay_managers(void) +{ + return num_managers; +} +EXPORT_SYMBOL(omap_dss_get_num_overlay_managers); + +struct omap_overlay_manager *omap_dss_get_overlay_manager(int num) +{ + int i = 0; + struct omap_overlay_manager *mgr; + + list_for_each_entry(mgr, &manager_list, list) { + if (i++ == num) + return mgr; + } + + return NULL; +} +EXPORT_SYMBOL(omap_dss_get_overlay_manager); + diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c new file mode 100644 index 0000000000000000000000000000000000000000..b7f9a73398428384511e6f8385cd7b55fc872299 --- /dev/null +++ b/drivers/video/omap2/dss/overlay.c @@ -0,0 +1,680 @@ +/* + * linux/drivers/video/omap2/dss/overlay.c + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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, see . + */ + +#define DSS_SUBSYS_NAME "OVERLAY" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "dss.h" + +static int num_overlays; +static struct list_head overlay_list; + +static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name); +} + +static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", + ovl->manager ? ovl->manager->name : ""); +} + +static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf, + size_t size) +{ + int i, r; + struct omap_overlay_manager *mgr = NULL; + struct omap_overlay_manager *old_mgr; + int len = size; + + if (buf[size-1] == '\n') + --len; + + if (len > 0) { + for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { + mgr = omap_dss_get_overlay_manager(i); + + if (strncmp(buf, mgr->name, len) == 0) + break; + + mgr = NULL; + } + } + + if (len > 0 && mgr == NULL) + return -EINVAL; + + if (mgr) + DSSDBG("manager %s found\n", mgr->name); + + if (mgr == ovl->manager) + return size; + + old_mgr = ovl->manager; + + /* detach old manager */ + if (old_mgr) { + r = ovl->unset_manager(ovl); + if (r) { + DSSERR("detach failed\n"); + return r; + } + + r = old_mgr->apply(old_mgr); + if (r) + return r; + } + + if (mgr) { + r = ovl->set_manager(ovl, mgr); + if (r) { + DSSERR("Failed to attach overlay\n"); + return r; + } + + r = mgr->apply(mgr); + if (r) + return r; + } + + return size; +} + +static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d,%d\n", + ovl->info.width, ovl->info.height); +} + +static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width); +} + +static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d,%d\n", + ovl->info.pos_x, ovl->info.pos_y); +} + +static ssize_t overlay_position_store(struct omap_overlay *ovl, + const char *buf, size_t size) +{ + int r; + char *last; + struct omap_overlay_info info; + + ovl->get_overlay_info(ovl, &info); + + info.pos_x = simple_strtoul(buf, &last, 10); + ++last; + if (last - buf >= size) + return -EINVAL; + + info.pos_y = simple_strtoul(last, &last, 10); + + r = ovl->set_overlay_info(ovl, &info); + if (r) + return r; + + if (ovl->manager) { + r = ovl->manager->apply(ovl->manager); + if (r) + return r; + } + + return size; +} + +static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d,%d\n", + ovl->info.out_width, ovl->info.out_height); +} + +static ssize_t overlay_output_size_store(struct omap_overlay *ovl, + const char *buf, size_t size) +{ + int r; + char *last; + struct omap_overlay_info info; + + ovl->get_overlay_info(ovl, &info); + + info.out_width = simple_strtoul(buf, &last, 10); + ++last; + if (last - buf >= size) + return -EINVAL; + + info.out_height = simple_strtoul(last, &last, 10); + + r = ovl->set_overlay_info(ovl, &info); + if (r) + return r; + + if (ovl->manager) { + r = ovl->manager->apply(ovl->manager); + if (r) + return r; + } + + return size; +} + +static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled); +} + +static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, + size_t size) +{ + int r; + struct omap_overlay_info info; + + ovl->get_overlay_info(ovl, &info); + + info.enabled = simple_strtoul(buf, NULL, 10); + + r = ovl->set_overlay_info(ovl, &info); + if (r) + return r; + + if (ovl->manager) { + r = ovl->manager->apply(ovl->manager); + if (r) + return r; + } + + return size; +} + +static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", + ovl->info.global_alpha); +} + +static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, + const char *buf, size_t size) +{ + int r; + struct omap_overlay_info info; + + ovl->get_overlay_info(ovl, &info); + + /* Video1 plane does not support global alpha + * to always make it 255 completely opaque + */ + if (ovl->id == OMAP_DSS_VIDEO1) + info.global_alpha = 255; + else + info.global_alpha = simple_strtoul(buf, NULL, 10); + + r = ovl->set_overlay_info(ovl, &info); + if (r) + return r; + + if (ovl->manager) { + r = ovl->manager->apply(ovl->manager); + if (r) + return r; + } + + return size; +} + +struct overlay_attribute { + struct attribute attr; + ssize_t (*show)(struct omap_overlay *, char *); + ssize_t (*store)(struct omap_overlay *, const char *, size_t); +}; + +#define OVERLAY_ATTR(_name, _mode, _show, _store) \ + struct overlay_attribute overlay_attr_##_name = \ + __ATTR(_name, _mode, _show, _store) + +static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL); +static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR, + overlay_manager_show, overlay_manager_store); +static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL); +static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL); +static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR, + overlay_position_show, overlay_position_store); +static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR, + overlay_output_size_show, overlay_output_size_store); +static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR, + overlay_enabled_show, overlay_enabled_store); +static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, + overlay_global_alpha_show, overlay_global_alpha_store); + +static struct attribute *overlay_sysfs_attrs[] = { + &overlay_attr_name.attr, + &overlay_attr_manager.attr, + &overlay_attr_input_size.attr, + &overlay_attr_screen_width.attr, + &overlay_attr_position.attr, + &overlay_attr_output_size.attr, + &overlay_attr_enabled.attr, + &overlay_attr_global_alpha.attr, + NULL +}; + +static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct omap_overlay *overlay; + struct overlay_attribute *overlay_attr; + + overlay = container_of(kobj, struct omap_overlay, kobj); + overlay_attr = container_of(attr, struct overlay_attribute, attr); + + if (!overlay_attr->show) + return -ENOENT; + + return overlay_attr->show(overlay, buf); +} + +static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t size) +{ + struct omap_overlay *overlay; + struct overlay_attribute *overlay_attr; + + overlay = container_of(kobj, struct omap_overlay, kobj); + overlay_attr = container_of(attr, struct overlay_attribute, attr); + + if (!overlay_attr->store) + return -ENOENT; + + return overlay_attr->store(overlay, buf, size); +} + +static struct sysfs_ops overlay_sysfs_ops = { + .show = overlay_attr_show, + .store = overlay_attr_store, +}; + +static struct kobj_type overlay_ktype = { + .sysfs_ops = &overlay_sysfs_ops, + .default_attrs = overlay_sysfs_attrs, +}; + +/* Check if overlay parameters are compatible with display */ +int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev) +{ + struct omap_overlay_info *info; + u16 outw, outh; + u16 dw, dh; + + if (!dssdev) + return 0; + + if (!ovl->info.enabled) + return 0; + + info = &ovl->info; + + if (info->paddr == 0) { + DSSDBG("check_overlay failed: paddr 0\n"); + return -EINVAL; + } + + dssdev->get_resolution(dssdev, &dw, &dh); + + DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n", + ovl->id, + info->pos_x, info->pos_y, + info->width, info->height, + info->out_width, info->out_height, + dw, dh); + + if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { + outw = info->width; + outh = info->height; + } else { + if (info->out_width == 0) + outw = info->width; + else + outw = info->out_width; + + if (info->out_height == 0) + outh = info->height; + else + outh = info->out_height; + } + + if (dw < info->pos_x + outw) { + DSSDBG("check_overlay failed 1: %d < %d + %d\n", + dw, info->pos_x, outw); + return -EINVAL; + } + + if (dh < info->pos_y + outh) { + DSSDBG("check_overlay failed 2: %d < %d + %d\n", + dh, info->pos_y, outh); + return -EINVAL; + } + + if ((ovl->supported_modes & info->color_mode) == 0) { + DSSERR("overlay doesn't support mode %d\n", info->color_mode); + return -EINVAL; + } + + return 0; +} + +static int dss_ovl_set_overlay_info(struct omap_overlay *ovl, + struct omap_overlay_info *info) +{ + int r; + struct omap_overlay_info old_info; + + old_info = ovl->info; + ovl->info = *info; + + if (ovl->manager) { + r = dss_check_overlay(ovl, ovl->manager->device); + if (r) { + ovl->info = old_info; + return r; + } + } + + ovl->info_dirty = true; + + return 0; +} + +static void dss_ovl_get_overlay_info(struct omap_overlay *ovl, + struct omap_overlay_info *info) +{ + *info = ovl->info; +} + +static int dss_ovl_wait_for_go(struct omap_overlay *ovl) +{ + return dss_mgr_wait_for_go_ovl(ovl); +} + +static int omap_dss_set_manager(struct omap_overlay *ovl, + struct omap_overlay_manager *mgr) +{ + if (!mgr) + return -EINVAL; + + if (ovl->manager) { + DSSERR("overlay '%s' already has a manager '%s'\n", + ovl->name, ovl->manager->name); + return -EINVAL; + } + + if (ovl->info.enabled) { + DSSERR("overlay has to be disabled to change the manager\n"); + return -EINVAL; + } + + ovl->manager = mgr; + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + /* XXX: on manual update display, in auto update mode, a bug happens + * here. When an overlay is first enabled on LCD, then it's disabled, + * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT + * errors. Waiting before changing the channel_out fixes it. I'm + * guessing that the overlay is still somehow being used for the LCD, + * but I don't understand how or why. */ + msleep(40); + dispc_set_channel_out(ovl->id, mgr->id); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + + return 0; +} + +static int omap_dss_unset_manager(struct omap_overlay *ovl) +{ + int r; + + if (!ovl->manager) { + DSSERR("failed to detach overlay: manager not set\n"); + return -EINVAL; + } + + if (ovl->info.enabled) { + DSSERR("overlay has to be disabled to unset the manager\n"); + return -EINVAL; + } + + r = ovl->wait_for_go(ovl); + if (r) + return r; + + ovl->manager = NULL; + + return 0; +} + +int omap_dss_get_num_overlays(void) +{ + return num_overlays; +} +EXPORT_SYMBOL(omap_dss_get_num_overlays); + +struct omap_overlay *omap_dss_get_overlay(int num) +{ + int i = 0; + struct omap_overlay *ovl; + + list_for_each_entry(ovl, &overlay_list, list) { + if (i++ == num) + return ovl; + } + + return NULL; +} +EXPORT_SYMBOL(omap_dss_get_overlay); + +static void omap_dss_add_overlay(struct omap_overlay *overlay) +{ + ++num_overlays; + list_add_tail(&overlay->list, &overlay_list); +} + +static struct omap_overlay *dispc_overlays[3]; + +void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr) +{ + mgr->num_overlays = 3; + mgr->overlays = dispc_overlays; +} + +#ifdef L4_EXAMPLE +static struct omap_overlay *l4_overlays[1]; +void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr) +{ + mgr->num_overlays = 1; + mgr->overlays = l4_overlays; +} +#endif + +void dss_init_overlays(struct platform_device *pdev) +{ + int i, r; + + INIT_LIST_HEAD(&overlay_list); + + num_overlays = 0; + + for (i = 0; i < 3; ++i) { + struct omap_overlay *ovl; + ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); + + BUG_ON(ovl == NULL); + + switch (i) { + case 0: + ovl->name = "gfx"; + ovl->id = OMAP_DSS_GFX; + ovl->supported_modes = cpu_is_omap34xx() ? + OMAP_DSS_COLOR_GFX_OMAP3 : + OMAP_DSS_COLOR_GFX_OMAP2; + ovl->caps = OMAP_DSS_OVL_CAP_DISPC; + ovl->info.global_alpha = 255; + break; + case 1: + ovl->name = "vid1"; + ovl->id = OMAP_DSS_VIDEO1; + ovl->supported_modes = cpu_is_omap34xx() ? + OMAP_DSS_COLOR_VID1_OMAP3 : + OMAP_DSS_COLOR_VID_OMAP2; + ovl->caps = OMAP_DSS_OVL_CAP_SCALE | + OMAP_DSS_OVL_CAP_DISPC; + ovl->info.global_alpha = 255; + break; + case 2: + ovl->name = "vid2"; + ovl->id = OMAP_DSS_VIDEO2; + ovl->supported_modes = cpu_is_omap34xx() ? + OMAP_DSS_COLOR_VID2_OMAP3 : + OMAP_DSS_COLOR_VID_OMAP2; + ovl->caps = OMAP_DSS_OVL_CAP_SCALE | + OMAP_DSS_OVL_CAP_DISPC; + ovl->info.global_alpha = 255; + break; + } + + ovl->set_manager = &omap_dss_set_manager; + ovl->unset_manager = &omap_dss_unset_manager; + ovl->set_overlay_info = &dss_ovl_set_overlay_info; + ovl->get_overlay_info = &dss_ovl_get_overlay_info; + ovl->wait_for_go = &dss_ovl_wait_for_go; + + omap_dss_add_overlay(ovl); + + r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, + &pdev->dev.kobj, "overlay%d", i); + + if (r) { + DSSERR("failed to create sysfs file\n"); + continue; + } + + dispc_overlays[i] = ovl; + } + +#ifdef L4_EXAMPLE + { + struct omap_overlay *ovl; + ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); + + BUG_ON(ovl == NULL); + + ovl->name = "l4"; + ovl->supported_modes = OMAP_DSS_COLOR_RGB24U; + + ovl->set_manager = &omap_dss_set_manager; + ovl->unset_manager = &omap_dss_unset_manager; + ovl->set_overlay_info = &dss_ovl_set_overlay_info; + ovl->get_overlay_info = &dss_ovl_get_overlay_info; + + omap_dss_add_overlay(ovl); + + r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, + &pdev->dev.kobj, "overlayl4"); + + if (r) + DSSERR("failed to create sysfs file\n"); + + l4_overlays[0] = ovl; + } +#endif +} + +/* connect overlays to the new device, if not already connected. if force + * selected, connect always. */ +void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) +{ + int i; + struct omap_overlay_manager *lcd_mgr; + struct omap_overlay_manager *tv_mgr; + struct omap_overlay_manager *mgr = NULL; + + lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD); + tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV); + + if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) { + if (!lcd_mgr->device || force) { + if (lcd_mgr->device) + lcd_mgr->unset_device(lcd_mgr); + lcd_mgr->set_device(lcd_mgr, dssdev); + mgr = lcd_mgr; + } + } + + if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { + if (!tv_mgr->device || force) { + if (tv_mgr->device) + tv_mgr->unset_device(tv_mgr); + tv_mgr->set_device(tv_mgr, dssdev); + mgr = tv_mgr; + } + } + + if (mgr) { + for (i = 0; i < 3; i++) { + struct omap_overlay *ovl; + ovl = omap_dss_get_overlay(i); + if (!ovl->manager || force) { + if (ovl->manager) + omap_dss_unset_manager(ovl); + omap_dss_set_manager(ovl, mgr); + } + } + } +} + +void dss_uninit_overlays(struct platform_device *pdev) +{ + struct omap_overlay *ovl; + + while (!list_empty(&overlay_list)) { + ovl = list_first_entry(&overlay_list, + struct omap_overlay, list); + list_del(&ovl->list); + kobject_del(&ovl->kobj); + kobject_put(&ovl->kobj); + kfree(ovl); + } + + num_overlays = 0; +} + diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c new file mode 100644 index 0000000000000000000000000000000000000000..d0b3006ad8a5e673a2f4278d8ea59e4da741ccbc --- /dev/null +++ b/drivers/video/omap2/dss/rfbi.c @@ -0,0 +1,1309 @@ +/* + * linux/drivers/video/omap2/dss/rfbi.c + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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, see . + */ + +#define DSS_SUBSYS_NAME "RFBI" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "dss.h" + +/*#define MEASURE_PERF*/ + +#define RFBI_BASE 0x48050800 + +struct rfbi_reg { u16 idx; }; + +#define RFBI_REG(idx) ((const struct rfbi_reg) { idx }) + +#define RFBI_REVISION RFBI_REG(0x0000) +#define RFBI_SYSCONFIG RFBI_REG(0x0010) +#define RFBI_SYSSTATUS RFBI_REG(0x0014) +#define RFBI_CONTROL RFBI_REG(0x0040) +#define RFBI_PIXEL_CNT RFBI_REG(0x0044) +#define RFBI_LINE_NUMBER RFBI_REG(0x0048) +#define RFBI_CMD RFBI_REG(0x004c) +#define RFBI_PARAM RFBI_REG(0x0050) +#define RFBI_DATA RFBI_REG(0x0054) +#define RFBI_READ RFBI_REG(0x0058) +#define RFBI_STATUS RFBI_REG(0x005c) + +#define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18) +#define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18) +#define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18) +#define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18) +#define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18) +#define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18) + +#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090) +#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094) + +#define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param)) + +#define REG_FLD_MOD(idx, val, start, end) \ + rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end)) + +/* To work around an RFBI transfer rate limitation */ +#define OMAP_RFBI_RATE_LIMIT 1 + +enum omap_rfbi_cycleformat { + OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0, + OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1, + OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2, + OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3, +}; + +enum omap_rfbi_datatype { + OMAP_DSS_RFBI_DATATYPE_12 = 0, + OMAP_DSS_RFBI_DATATYPE_16 = 1, + OMAP_DSS_RFBI_DATATYPE_18 = 2, + OMAP_DSS_RFBI_DATATYPE_24 = 3, +}; + +enum omap_rfbi_parallelmode { + OMAP_DSS_RFBI_PARALLELMODE_8 = 0, + OMAP_DSS_RFBI_PARALLELMODE_9 = 1, + OMAP_DSS_RFBI_PARALLELMODE_12 = 2, + OMAP_DSS_RFBI_PARALLELMODE_16 = 3, +}; + +enum update_cmd { + RFBI_CMD_UPDATE = 0, + RFBI_CMD_SYNC = 1, +}; + +static int rfbi_convert_timings(struct rfbi_timings *t); +static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); +static void process_cmd_fifo(void); + +static struct { + void __iomem *base; + + unsigned long l4_khz; + + enum omap_rfbi_datatype datatype; + enum omap_rfbi_parallelmode parallelmode; + + enum omap_rfbi_te_mode te_mode; + int te_enabled; + + void (*framedone_callback)(void *data); + void *framedone_callback_data; + + struct omap_dss_device *dssdev[2]; + + struct kfifo *cmd_fifo; + spinlock_t cmd_lock; + struct completion cmd_done; + atomic_t cmd_fifo_full; + atomic_t cmd_pending; +#ifdef MEASURE_PERF + unsigned perf_bytes; + ktime_t perf_setup_time; + ktime_t perf_start_time; +#endif +} rfbi; + +struct update_region { + u16 x; + u16 y; + u16 w; + u16 h; +}; + +struct update_param { + u8 rfbi_module; + u8 cmd; + + union { + struct update_region r; + struct completion *sync; + } par; +}; + +static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) +{ + __raw_writel(val, rfbi.base + idx.idx); +} + +static inline u32 rfbi_read_reg(const struct rfbi_reg idx) +{ + return __raw_readl(rfbi.base + idx.idx); +} + +static void rfbi_enable_clocks(bool enable) +{ + if (enable) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); +} + +void omap_rfbi_write_command(const void *buf, u32 len) +{ + rfbi_enable_clocks(1); + switch (rfbi.parallelmode) { + case OMAP_DSS_RFBI_PARALLELMODE_8: + { + const u8 *b = buf; + for (; len; len--) + rfbi_write_reg(RFBI_CMD, *b++); + break; + } + + case OMAP_DSS_RFBI_PARALLELMODE_16: + { + const u16 *w = buf; + BUG_ON(len & 1); + for (; len; len -= 2) + rfbi_write_reg(RFBI_CMD, *w++); + break; + } + + case OMAP_DSS_RFBI_PARALLELMODE_9: + case OMAP_DSS_RFBI_PARALLELMODE_12: + default: + BUG(); + } + rfbi_enable_clocks(0); +} +EXPORT_SYMBOL(omap_rfbi_write_command); + +void omap_rfbi_read_data(void *buf, u32 len) +{ + rfbi_enable_clocks(1); + switch (rfbi.parallelmode) { + case OMAP_DSS_RFBI_PARALLELMODE_8: + { + u8 *b = buf; + for (; len; len--) { + rfbi_write_reg(RFBI_READ, 0); + *b++ = rfbi_read_reg(RFBI_READ); + } + break; + } + + case OMAP_DSS_RFBI_PARALLELMODE_16: + { + u16 *w = buf; + BUG_ON(len & ~1); + for (; len; len -= 2) { + rfbi_write_reg(RFBI_READ, 0); + *w++ = rfbi_read_reg(RFBI_READ); + } + break; + } + + case OMAP_DSS_RFBI_PARALLELMODE_9: + case OMAP_DSS_RFBI_PARALLELMODE_12: + default: + BUG(); + } + rfbi_enable_clocks(0); +} +EXPORT_SYMBOL(omap_rfbi_read_data); + +void omap_rfbi_write_data(const void *buf, u32 len) +{ + rfbi_enable_clocks(1); + switch (rfbi.parallelmode) { + case OMAP_DSS_RFBI_PARALLELMODE_8: + { + const u8 *b = buf; + for (; len; len--) + rfbi_write_reg(RFBI_PARAM, *b++); + break; + } + + case OMAP_DSS_RFBI_PARALLELMODE_16: + { + const u16 *w = buf; + BUG_ON(len & 1); + for (; len; len -= 2) + rfbi_write_reg(RFBI_PARAM, *w++); + break; + } + + case OMAP_DSS_RFBI_PARALLELMODE_9: + case OMAP_DSS_RFBI_PARALLELMODE_12: + default: + BUG(); + + } + rfbi_enable_clocks(0); +} +EXPORT_SYMBOL(omap_rfbi_write_data); + +void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, + u16 x, u16 y, + u16 w, u16 h) +{ + int start_offset = scr_width * y + x; + int horiz_offset = scr_width - w; + int i; + + rfbi_enable_clocks(1); + + if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && + rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { + const u16 __iomem *pd = buf; + pd += start_offset; + + for (; h; --h) { + for (i = 0; i < w; ++i) { + const u8 __iomem *b = (const u8 __iomem *)pd; + rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1)); + rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0)); + ++pd; + } + pd += horiz_offset; + } + } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 && + rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { + const u32 __iomem *pd = buf; + pd += start_offset; + + for (; h; --h) { + for (i = 0; i < w; ++i) { + const u8 __iomem *b = (const u8 __iomem *)pd; + rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2)); + rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1)); + rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0)); + ++pd; + } + pd += horiz_offset; + } + } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && + rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) { + const u16 __iomem *pd = buf; + pd += start_offset; + + for (; h; --h) { + for (i = 0; i < w; ++i) { + rfbi_write_reg(RFBI_PARAM, __raw_readw(pd)); + ++pd; + } + pd += horiz_offset; + } + } else { + BUG(); + } + + rfbi_enable_clocks(0); +} +EXPORT_SYMBOL(omap_rfbi_write_pixels); + +#ifdef MEASURE_PERF +static void perf_mark_setup(void) +{ + rfbi.perf_setup_time = ktime_get(); +} + +static void perf_mark_start(void) +{ + rfbi.perf_start_time = ktime_get(); +} + +static void perf_show(const char *name) +{ + ktime_t t, setup_time, trans_time; + u32 total_bytes; + u32 setup_us, trans_us, total_us; + + t = ktime_get(); + + setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time); + setup_us = (u32)ktime_to_us(setup_time); + if (setup_us == 0) + setup_us = 1; + + trans_time = ktime_sub(t, rfbi.perf_start_time); + trans_us = (u32)ktime_to_us(trans_time); + if (trans_us == 0) + trans_us = 1; + + total_us = setup_us + trans_us; + + total_bytes = rfbi.perf_bytes; + + DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, " + "%u kbytes/sec\n", + name, + setup_us, + trans_us, + total_us, + 1000*1000 / total_us, + total_bytes, + total_bytes * 1000 / total_us); +} +#else +#define perf_mark_setup() +#define perf_mark_start() +#define perf_show(x) +#endif + +void rfbi_transfer_area(u16 width, u16 height, + void (callback)(void *data), void *data) +{ + u32 l; + + /*BUG_ON(callback == 0);*/ + BUG_ON(rfbi.framedone_callback != NULL); + + DSSDBG("rfbi_transfer_area %dx%d\n", width, height); + + dispc_set_lcd_size(width, height); + + dispc_enable_lcd_out(1); + + rfbi.framedone_callback = callback; + rfbi.framedone_callback_data = data; + + rfbi_enable_clocks(1); + + rfbi_write_reg(RFBI_PIXEL_CNT, width * height); + + l = rfbi_read_reg(RFBI_CONTROL); + l = FLD_MOD(l, 1, 0, 0); /* enable */ + if (!rfbi.te_enabled) + l = FLD_MOD(l, 1, 4, 4); /* ITE */ + + perf_mark_start(); + + rfbi_write_reg(RFBI_CONTROL, l); +} + +static void framedone_callback(void *data, u32 mask) +{ + void (*callback)(void *data); + + DSSDBG("FRAMEDONE\n"); + + perf_show("DISPC"); + + REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0); + + rfbi_enable_clocks(0); + + callback = rfbi.framedone_callback; + rfbi.framedone_callback = NULL; + + /*callback(rfbi.framedone_callback_data);*/ + + atomic_set(&rfbi.cmd_pending, 0); + + process_cmd_fifo(); +} + +#if 1 /* VERBOSE */ +static void rfbi_print_timings(void) +{ + u32 l; + u32 time; + + l = rfbi_read_reg(RFBI_CONFIG(0)); + time = 1000000000 / rfbi.l4_khz; + if (l & (1 << 4)) + time *= 2; + + DSSDBG("Tick time %u ps\n", time); + l = rfbi_read_reg(RFBI_ONOFF_TIME(0)); + DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, " + "REONTIME %d, REOFFTIME %d\n", + l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f, + (l >> 20) & 0x0f, (l >> 24) & 0x3f); + + l = rfbi_read_reg(RFBI_CYCLE_TIME(0)); + DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, " + "ACCESSTIME %d\n", + (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f, + (l >> 22) & 0x3f); +} +#else +static void rfbi_print_timings(void) {} +#endif + + + + +static u32 extif_clk_period; + +static inline unsigned long round_to_extif_ticks(unsigned long ps, int div) +{ + int bus_tick = extif_clk_period * div; + return (ps + bus_tick - 1) / bus_tick * bus_tick; +} + +static int calc_reg_timing(struct rfbi_timings *t, int div) +{ + t->clk_div = div; + + t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div); + + t->we_on_time = round_to_extif_ticks(t->we_on_time, div); + t->we_off_time = round_to_extif_ticks(t->we_off_time, div); + t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div); + + t->re_on_time = round_to_extif_ticks(t->re_on_time, div); + t->re_off_time = round_to_extif_ticks(t->re_off_time, div); + t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div); + + t->access_time = round_to_extif_ticks(t->access_time, div); + t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div); + t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div); + + DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n", + t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); + DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n", + t->we_on_time, t->we_off_time, t->re_cycle_time, + t->we_cycle_time); + DSSDBG("[reg]rdaccess %d cspulse %d\n", + t->access_time, t->cs_pulse_width); + + return rfbi_convert_timings(t); +} + +static int calc_extif_timings(struct rfbi_timings *t) +{ + u32 max_clk_div; + int div; + + rfbi_get_clk_info(&extif_clk_period, &max_clk_div); + for (div = 1; div <= max_clk_div; div++) { + if (calc_reg_timing(t, div) == 0) + break; + } + + if (div <= max_clk_div) + return 0; + + DSSERR("can't setup timings\n"); + return -1; +} + + +void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t) +{ + int r; + + if (!t->converted) { + r = calc_extif_timings(t); + if (r < 0) + DSSERR("Failed to calc timings\n"); + } + + BUG_ON(!t->converted); + + rfbi_enable_clocks(1); + rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]); + rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]); + + /* TIMEGRANULARITY */ + REG_FLD_MOD(RFBI_CONFIG(rfbi_module), + (t->tim[2] ? 1 : 0), 4, 4); + + rfbi_print_timings(); + rfbi_enable_clocks(0); +} + +static int ps_to_rfbi_ticks(int time, int div) +{ + unsigned long tick_ps; + int ret; + + /* Calculate in picosecs to yield more exact results */ + tick_ps = 1000000000 / (rfbi.l4_khz) * div; + + ret = (time + tick_ps - 1) / tick_ps; + + return ret; +} + +#ifdef OMAP_RFBI_RATE_LIMIT +unsigned long rfbi_get_max_tx_rate(void) +{ + unsigned long l4_rate, dss1_rate; + int min_l4_ticks = 0; + int i; + + /* According to TI this can't be calculated so make the + * adjustments for a couple of known frequencies and warn for + * others. + */ + static const struct { + unsigned long l4_clk; /* HZ */ + unsigned long dss1_clk; /* HZ */ + unsigned long min_l4_ticks; + } ftab[] = { + { 55, 132, 7, }, /* 7.86 MPix/s */ + { 110, 110, 12, }, /* 9.16 MPix/s */ + { 110, 132, 10, }, /* 11 Mpix/s */ + { 120, 120, 10, }, /* 12 Mpix/s */ + { 133, 133, 10, }, /* 13.3 Mpix/s */ + }; + + l4_rate = rfbi.l4_khz / 1000; + dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000; + + for (i = 0; i < ARRAY_SIZE(ftab); i++) { + /* Use a window instead of an exact match, to account + * for different DPLL multiplier / divider pairs. + */ + if (abs(ftab[i].l4_clk - l4_rate) < 3 && + abs(ftab[i].dss1_clk - dss1_rate) < 3) { + min_l4_ticks = ftab[i].min_l4_ticks; + break; + } + } + if (i == ARRAY_SIZE(ftab)) { + /* Can't be sure, return anyway the maximum not + * rate-limited. This might cause a problem only for the + * tearing synchronisation. + */ + DSSERR("can't determine maximum RFBI transfer rate\n"); + return rfbi.l4_khz * 1000; + } + return rfbi.l4_khz * 1000 / min_l4_ticks; +} +#else +int rfbi_get_max_tx_rate(void) +{ + return rfbi.l4_khz * 1000; +} +#endif + +static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div) +{ + *clk_period = 1000000000 / rfbi.l4_khz; + *max_clk_div = 2; +} + +static int rfbi_convert_timings(struct rfbi_timings *t) +{ + u32 l; + int reon, reoff, weon, weoff, cson, csoff, cs_pulse; + int actim, recyc, wecyc; + int div = t->clk_div; + + if (div <= 0 || div > 2) + return -1; + + /* Make sure that after conversion it still holds that: + * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff, + * csoff > cson, csoff >= max(weoff, reoff), actim > reon + */ + weon = ps_to_rfbi_ticks(t->we_on_time, div); + weoff = ps_to_rfbi_ticks(t->we_off_time, div); + if (weoff <= weon) + weoff = weon + 1; + if (weon > 0x0f) + return -1; + if (weoff > 0x3f) + return -1; + + reon = ps_to_rfbi_ticks(t->re_on_time, div); + reoff = ps_to_rfbi_ticks(t->re_off_time, div); + if (reoff <= reon) + reoff = reon + 1; + if (reon > 0x0f) + return -1; + if (reoff > 0x3f) + return -1; + + cson = ps_to_rfbi_ticks(t->cs_on_time, div); + csoff = ps_to_rfbi_ticks(t->cs_off_time, div); + if (csoff <= cson) + csoff = cson + 1; + if (csoff < max(weoff, reoff)) + csoff = max(weoff, reoff); + if (cson > 0x0f) + return -1; + if (csoff > 0x3f) + return -1; + + l = cson; + l |= csoff << 4; + l |= weon << 10; + l |= weoff << 14; + l |= reon << 20; + l |= reoff << 24; + + t->tim[0] = l; + + actim = ps_to_rfbi_ticks(t->access_time, div); + if (actim <= reon) + actim = reon + 1; + if (actim > 0x3f) + return -1; + + wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div); + if (wecyc < weoff) + wecyc = weoff; + if (wecyc > 0x3f) + return -1; + + recyc = ps_to_rfbi_ticks(t->re_cycle_time, div); + if (recyc < reoff) + recyc = reoff; + if (recyc > 0x3f) + return -1; + + cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div); + if (cs_pulse > 0x3f) + return -1; + + l = wecyc; + l |= recyc << 6; + l |= cs_pulse << 12; + l |= actim << 22; + + t->tim[1] = l; + + t->tim[2] = div - 1; + + t->converted = 1; + + return 0; +} + +/* xxx FIX module selection missing */ +int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode, + unsigned hs_pulse_time, unsigned vs_pulse_time, + int hs_pol_inv, int vs_pol_inv, int extif_div) +{ + int hs, vs; + int min; + u32 l; + + hs = ps_to_rfbi_ticks(hs_pulse_time, 1); + vs = ps_to_rfbi_ticks(vs_pulse_time, 1); + if (hs < 2) + return -EDOM; + if (mode == OMAP_DSS_RFBI_TE_MODE_2) + min = 2; + else /* OMAP_DSS_RFBI_TE_MODE_1 */ + min = 4; + if (vs < min) + return -EDOM; + if (vs == hs) + return -EINVAL; + rfbi.te_mode = mode; + DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n", + mode, hs, vs, hs_pol_inv, vs_pol_inv); + + rfbi_enable_clocks(1); + rfbi_write_reg(RFBI_HSYNC_WIDTH, hs); + rfbi_write_reg(RFBI_VSYNC_WIDTH, vs); + + l = rfbi_read_reg(RFBI_CONFIG(0)); + if (hs_pol_inv) + l &= ~(1 << 21); + else + l |= 1 << 21; + if (vs_pol_inv) + l &= ~(1 << 20); + else + l |= 1 << 20; + rfbi_enable_clocks(0); + + return 0; +} +EXPORT_SYMBOL(omap_rfbi_setup_te); + +/* xxx FIX module selection missing */ +int omap_rfbi_enable_te(bool enable, unsigned line) +{ + u32 l; + + DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode); + if (line > (1 << 11) - 1) + return -EINVAL; + + rfbi_enable_clocks(1); + l = rfbi_read_reg(RFBI_CONFIG(0)); + l &= ~(0x3 << 2); + if (enable) { + rfbi.te_enabled = 1; + l |= rfbi.te_mode << 2; + } else + rfbi.te_enabled = 0; + rfbi_write_reg(RFBI_CONFIG(0), l); + rfbi_write_reg(RFBI_LINE_NUMBER, line); + rfbi_enable_clocks(0); + + return 0; +} +EXPORT_SYMBOL(omap_rfbi_enable_te); + +#if 0 +static void rfbi_enable_config(int enable1, int enable2) +{ + u32 l; + int cs = 0; + + if (enable1) + cs |= 1<<0; + if (enable2) + cs |= 1<<1; + + rfbi_enable_clocks(1); + + l = rfbi_read_reg(RFBI_CONTROL); + + l = FLD_MOD(l, cs, 3, 2); + l = FLD_MOD(l, 0, 1, 1); + + rfbi_write_reg(RFBI_CONTROL, l); + + + l = rfbi_read_reg(RFBI_CONFIG(0)); + l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */ + /*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */ + /*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */ + + l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */ + l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */ + l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */ + + l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0); + rfbi_write_reg(RFBI_CONFIG(0), l); + + rfbi_enable_clocks(0); +} +#endif + +int rfbi_configure(int rfbi_module, int bpp, int lines) +{ + u32 l; + int cycle1 = 0, cycle2 = 0, cycle3 = 0; + enum omap_rfbi_cycleformat cycleformat; + enum omap_rfbi_datatype datatype; + enum omap_rfbi_parallelmode parallelmode; + + switch (bpp) { + case 12: + datatype = OMAP_DSS_RFBI_DATATYPE_12; + break; + case 16: + datatype = OMAP_DSS_RFBI_DATATYPE_16; + break; + case 18: + datatype = OMAP_DSS_RFBI_DATATYPE_18; + break; + case 24: + datatype = OMAP_DSS_RFBI_DATATYPE_24; + break; + default: + BUG(); + return 1; + } + rfbi.datatype = datatype; + + switch (lines) { + case 8: + parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8; + break; + case 9: + parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9; + break; + case 12: + parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12; + break; + case 16: + parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16; + break; + default: + BUG(); + return 1; + } + rfbi.parallelmode = parallelmode; + + if ((bpp % lines) == 0) { + switch (bpp / lines) { + case 1: + cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1; + break; + case 2: + cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1; + break; + case 3: + cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1; + break; + default: + BUG(); + return 1; + } + } else if ((2 * bpp % lines) == 0) { + if ((2 * bpp / lines) == 3) + cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2; + else { + BUG(); + return 1; + } + } else { + BUG(); + return 1; + } + + switch (cycleformat) { + case OMAP_DSS_RFBI_CYCLEFORMAT_1_1: + cycle1 = lines; + break; + + case OMAP_DSS_RFBI_CYCLEFORMAT_2_1: + cycle1 = lines; + cycle2 = lines; + break; + + case OMAP_DSS_RFBI_CYCLEFORMAT_3_1: + cycle1 = lines; + cycle2 = lines; + cycle3 = lines; + break; + + case OMAP_DSS_RFBI_CYCLEFORMAT_3_2: + cycle1 = lines; + cycle2 = (lines / 2) | ((lines / 2) << 16); + cycle3 = (lines << 16); + break; + } + + rfbi_enable_clocks(1); + + REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */ + + l = 0; + l |= FLD_VAL(parallelmode, 1, 0); + l |= FLD_VAL(0, 3, 2); /* TRIGGERMODE: ITE */ + l |= FLD_VAL(0, 4, 4); /* TIMEGRANULARITY */ + l |= FLD_VAL(datatype, 6, 5); + /* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */ + l |= FLD_VAL(0, 8, 7); /* L4FORMAT, 1pix/L4 */ + l |= FLD_VAL(cycleformat, 10, 9); + l |= FLD_VAL(0, 12, 11); /* UNUSEDBITS */ + l |= FLD_VAL(0, 16, 16); /* A0POLARITY */ + l |= FLD_VAL(0, 17, 17); /* REPOLARITY */ + l |= FLD_VAL(0, 18, 18); /* WEPOLARITY */ + l |= FLD_VAL(0, 19, 19); /* CSPOLARITY */ + l |= FLD_VAL(1, 20, 20); /* TE_VSYNC_POLARITY */ + l |= FLD_VAL(1, 21, 21); /* HSYNCPOLARITY */ + rfbi_write_reg(RFBI_CONFIG(rfbi_module), l); + + rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1); + rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2); + rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3); + + + l = rfbi_read_reg(RFBI_CONTROL); + l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */ + l = FLD_MOD(l, 0, 1, 1); /* clear bypass */ + rfbi_write_reg(RFBI_CONTROL, l); + + + DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n", + bpp, lines, cycle1, cycle2, cycle3); + + rfbi_enable_clocks(0); + + return 0; +} +EXPORT_SYMBOL(rfbi_configure); + +static int rfbi_find_display(struct omap_dss_device *dssdev) +{ + if (dssdev == rfbi.dssdev[0]) + return 0; + + if (dssdev == rfbi.dssdev[1]) + return 1; + + BUG(); + return -1; +} + + +static void signal_fifo_waiters(void) +{ + if (atomic_read(&rfbi.cmd_fifo_full) > 0) { + /* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */ + complete(&rfbi.cmd_done); + atomic_dec(&rfbi.cmd_fifo_full); + } +} + +/* returns 1 for async op, and 0 for sync op */ +static int do_update(struct omap_dss_device *dssdev, struct update_region *upd) +{ + u16 x = upd->x; + u16 y = upd->y; + u16 w = upd->w; + u16 h = upd->h; + + perf_mark_setup(); + + if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { + /*dssdev->driver->enable_te(dssdev, 1); */ + dss_setup_partial_planes(dssdev, &x, &y, &w, &h); + } + +#ifdef MEASURE_PERF + rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */ +#endif + + dssdev->driver->setup_update(dssdev, x, y, w, h); + + if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { + rfbi_transfer_area(w, h, NULL, NULL); + return 1; + } else { + struct omap_overlay *ovl; + void __iomem *addr; + int scr_width; + + ovl = dssdev->manager->overlays[0]; + scr_width = ovl->info.screen_width; + addr = ovl->info.vaddr; + + omap_rfbi_write_pixels(addr, scr_width, x, y, w, h); + + perf_show("L4"); + + return 0; + } +} + +static void process_cmd_fifo(void) +{ + int len; + struct update_param p; + struct omap_dss_device *dssdev; + unsigned long flags; + + if (atomic_inc_return(&rfbi.cmd_pending) != 1) + return; + + while (true) { + spin_lock_irqsave(rfbi.cmd_fifo->lock, flags); + + len = __kfifo_get(rfbi.cmd_fifo, (unsigned char *)&p, + sizeof(struct update_param)); + if (len == 0) { + DSSDBG("nothing more in fifo\n"); + atomic_set(&rfbi.cmd_pending, 0); + spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); + break; + } + + /* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/ + + spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); + + BUG_ON(len != sizeof(struct update_param)); + BUG_ON(p.rfbi_module > 1); + + dssdev = rfbi.dssdev[p.rfbi_module]; + + if (p.cmd == RFBI_CMD_UPDATE) { + if (do_update(dssdev, &p.par.r)) + break; /* async op */ + } else if (p.cmd == RFBI_CMD_SYNC) { + DSSDBG("Signaling SYNC done!\n"); + complete(p.par.sync); + } else + BUG(); + } + + signal_fifo_waiters(); +} + +static void rfbi_push_cmd(struct update_param *p) +{ + int ret; + + while (1) { + unsigned long flags; + int available; + + spin_lock_irqsave(rfbi.cmd_fifo->lock, flags); + available = RFBI_CMD_FIFO_LEN_BYTES - + __kfifo_len(rfbi.cmd_fifo); + +/* DSSDBG("%d bytes left in fifo\n", available); */ + if (available < sizeof(struct update_param)) { + DSSDBG("Going to wait because FIFO FULL..\n"); + spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); + atomic_inc(&rfbi.cmd_fifo_full); + wait_for_completion(&rfbi.cmd_done); + /*DSSDBG("Woke up because fifo not full anymore\n");*/ + continue; + } + + ret = __kfifo_put(rfbi.cmd_fifo, (unsigned char *)p, + sizeof(struct update_param)); +/* DSSDBG("pushed %d bytes\n", ret);*/ + + spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); + + BUG_ON(ret != sizeof(struct update_param)); + + break; + } +} + +static void rfbi_push_update(int rfbi_module, int x, int y, int w, int h) +{ + struct update_param p; + + p.rfbi_module = rfbi_module; + p.cmd = RFBI_CMD_UPDATE; + + p.par.r.x = x; + p.par.r.y = y; + p.par.r.w = w; + p.par.r.h = h; + + DSSDBG("RFBI pushed %d,%d %dx%d\n", x, y, w, h); + + rfbi_push_cmd(&p); + + process_cmd_fifo(); +} + +static void rfbi_push_sync(int rfbi_module, struct completion *sync_comp) +{ + struct update_param p; + + p.rfbi_module = rfbi_module; + p.cmd = RFBI_CMD_SYNC; + p.par.sync = sync_comp; + + rfbi_push_cmd(&p); + + DSSDBG("RFBI sync pushed to cmd fifo\n"); + + process_cmd_fifo(); +} + +void rfbi_dump_regs(struct seq_file *s) +{ +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + DUMPREG(RFBI_REVISION); + DUMPREG(RFBI_SYSCONFIG); + DUMPREG(RFBI_SYSSTATUS); + DUMPREG(RFBI_CONTROL); + DUMPREG(RFBI_PIXEL_CNT); + DUMPREG(RFBI_LINE_NUMBER); + DUMPREG(RFBI_CMD); + DUMPREG(RFBI_PARAM); + DUMPREG(RFBI_DATA); + DUMPREG(RFBI_READ); + DUMPREG(RFBI_STATUS); + + DUMPREG(RFBI_CONFIG(0)); + DUMPREG(RFBI_ONOFF_TIME(0)); + DUMPREG(RFBI_CYCLE_TIME(0)); + DUMPREG(RFBI_DATA_CYCLE1(0)); + DUMPREG(RFBI_DATA_CYCLE2(0)); + DUMPREG(RFBI_DATA_CYCLE3(0)); + + DUMPREG(RFBI_CONFIG(1)); + DUMPREG(RFBI_ONOFF_TIME(1)); + DUMPREG(RFBI_CYCLE_TIME(1)); + DUMPREG(RFBI_DATA_CYCLE1(1)); + DUMPREG(RFBI_DATA_CYCLE2(1)); + DUMPREG(RFBI_DATA_CYCLE3(1)); + + DUMPREG(RFBI_VSYNC_WIDTH); + DUMPREG(RFBI_HSYNC_WIDTH); + + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); +#undef DUMPREG +} + +int rfbi_init(void) +{ + u32 rev; + u32 l; + + spin_lock_init(&rfbi.cmd_lock); + rfbi.cmd_fifo = kfifo_alloc(RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL, + &rfbi.cmd_lock); + if (IS_ERR(rfbi.cmd_fifo)) + return -ENOMEM; + + init_completion(&rfbi.cmd_done); + atomic_set(&rfbi.cmd_fifo_full, 0); + atomic_set(&rfbi.cmd_pending, 0); + + rfbi.base = ioremap(RFBI_BASE, SZ_256); + if (!rfbi.base) { + DSSERR("can't ioremap RFBI\n"); + return -ENOMEM; + } + + rfbi_enable_clocks(1); + + msleep(10); + + rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; + + /* Enable autoidle and smart-idle */ + l = rfbi_read_reg(RFBI_SYSCONFIG); + l |= (1 << 0) | (2 << 3); + rfbi_write_reg(RFBI_SYSCONFIG, l); + + rev = rfbi_read_reg(RFBI_REVISION); + printk(KERN_INFO "OMAP RFBI rev %d.%d\n", + FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); + + rfbi_enable_clocks(0); + + return 0; +} + +void rfbi_exit(void) +{ + DSSDBG("rfbi_exit\n"); + + kfifo_free(rfbi.cmd_fifo); + + iounmap(rfbi.base); +} + +/* struct omap_display support */ +static int rfbi_display_update(struct omap_dss_device *dssdev, + u16 x, u16 y, u16 w, u16 h) +{ + int rfbi_module; + + if (w == 0 || h == 0) + return 0; + + rfbi_module = rfbi_find_display(dssdev); + + rfbi_push_update(rfbi_module, x, y, w, h); + + return 0; +} + +static int rfbi_display_sync(struct omap_dss_device *dssdev) +{ + struct completion sync_comp; + int rfbi_module; + + rfbi_module = rfbi_find_display(dssdev); + + init_completion(&sync_comp); + rfbi_push_sync(rfbi_module, &sync_comp); + DSSDBG("Waiting for SYNC to happen...\n"); + wait_for_completion(&sync_comp); + DSSDBG("Released from SYNC\n"); + return 0; +} + +static int rfbi_display_enable_te(struct omap_dss_device *dssdev, bool enable) +{ + dssdev->driver->enable_te(dssdev, enable); + return 0; +} + +static int rfbi_display_enable(struct omap_dss_device *dssdev) +{ + int r; + + r = omap_dss_start_device(dssdev); + if (r) { + DSSERR("failed to start device\n"); + goto err0; + } + + r = omap_dispc_register_isr(framedone_callback, NULL, + DISPC_IRQ_FRAMEDONE); + if (r) { + DSSERR("can't get FRAMEDONE irq\n"); + goto err1; + } + + dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); + + dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI); + + dispc_set_tft_data_lines(dssdev->ctrl.pixel_size); + + rfbi_configure(dssdev->phy.rfbi.channel, + dssdev->ctrl.pixel_size, + dssdev->phy.rfbi.data_lines); + + rfbi_set_timings(dssdev->phy.rfbi.channel, + &dssdev->ctrl.rfbi_timings); + + + if (dssdev->driver->enable) { + r = dssdev->driver->enable(dssdev); + if (r) + goto err2; + } + + return 0; +err2: + omap_dispc_unregister_isr(framedone_callback, NULL, + DISPC_IRQ_FRAMEDONE); +err1: + omap_dss_stop_device(dssdev); +err0: + return r; +} + +static void rfbi_display_disable(struct omap_dss_device *dssdev) +{ + dssdev->driver->disable(dssdev); + omap_dispc_unregister_isr(framedone_callback, NULL, + DISPC_IRQ_FRAMEDONE); + omap_dss_stop_device(dssdev); +} + +int rfbi_init_display(struct omap_dss_device *dssdev) +{ + dssdev->enable = rfbi_display_enable; + dssdev->disable = rfbi_display_disable; + dssdev->update = rfbi_display_update; + dssdev->sync = rfbi_display_sync; + dssdev->enable_te = rfbi_display_enable_te; + + rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; + + dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; + + return 0; +} diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c new file mode 100644 index 0000000000000000000000000000000000000000..c24f307d3da1706ba6a8cebfe2591e436ee06edf --- /dev/null +++ b/drivers/video/omap2/dss/sdi.c @@ -0,0 +1,277 @@ +/* + * linux/drivers/video/omap2/dss/sdi.c + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * 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, see . + */ + +#define DSS_SUBSYS_NAME "SDI" + +#include +#include +#include +#include + +#include +#include "dss.h" + +static struct { + bool skip_init; + bool update_enabled; +} sdi; + +static void sdi_basic_init(void) +{ + dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); + + dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); + dispc_set_tft_data_lines(24); + dispc_lcd_enable_signal_polarity(1); +} + +static int sdi_display_enable(struct omap_dss_device *dssdev) +{ + struct omap_video_timings *t = &dssdev->panel.timings; + struct dss_clock_info dss_cinfo; + struct dispc_clock_info dispc_cinfo; + u16 lck_div, pck_div; + unsigned long fck; + unsigned long pck; + int r; + + r = omap_dss_start_device(dssdev); + if (r) { + DSSERR("failed to start device\n"); + goto err0; + } + + if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { + DSSERR("dssdev already enabled\n"); + r = -EINVAL; + goto err1; + } + + /* In case of skip_init sdi_init has already enabled the clocks */ + if (!sdi.skip_init) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + sdi_basic_init(); + + /* 15.5.9.1.2 */ + dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; + + dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, + dssdev->panel.acb); + + if (!sdi.skip_init) { + r = dss_calc_clock_div(1, t->pixel_clock * 1000, + &dss_cinfo, &dispc_cinfo); + } else { + r = dss_get_clock_div(&dss_cinfo); + r = dispc_get_clock_div(&dispc_cinfo); + } + + if (r) + goto err2; + + fck = dss_cinfo.fck; + lck_div = dispc_cinfo.lck_div; + pck_div = dispc_cinfo.pck_div; + + pck = fck / lck_div / pck_div / 1000; + + if (pck != t->pixel_clock) { + DSSWARN("Could not find exact pixel clock. Requested %d kHz, " + "got %lu kHz\n", + t->pixel_clock, pck); + + t->pixel_clock = pck; + } + + + dispc_set_lcd_timings(t); + + r = dss_set_clock_div(&dss_cinfo); + if (r) + goto err2; + + r = dispc_set_clock_div(&dispc_cinfo); + if (r) + goto err2; + + if (!sdi.skip_init) { + dss_sdi_init(dssdev->phy.sdi.datapairs); + r = dss_sdi_enable(); + if (r) + goto err1; + mdelay(2); + } + + dispc_enable_lcd_out(1); + + if (dssdev->driver->enable) { + r = dssdev->driver->enable(dssdev); + if (r) + goto err3; + } + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + + sdi.skip_init = 0; + + return 0; +err3: + dispc_enable_lcd_out(0); +err2: + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); +err1: + omap_dss_stop_device(dssdev); +err0: + return r; +} + +static int sdi_display_resume(struct omap_dss_device *dssdev); + +static void sdi_display_disable(struct omap_dss_device *dssdev) +{ + if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED) + return; + + if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) + if (sdi_display_resume(dssdev)) + return; + + if (dssdev->driver->disable) + dssdev->driver->disable(dssdev); + + dispc_enable_lcd_out(0); + + dss_sdi_disable(); + + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + + dssdev->state = OMAP_DSS_DISPLAY_DISABLED; + + omap_dss_stop_device(dssdev); +} + +static int sdi_display_suspend(struct omap_dss_device *dssdev) +{ + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + return -EINVAL; + + if (dssdev->driver->suspend) + dssdev->driver->suspend(dssdev); + + dispc_enable_lcd_out(0); + + dss_sdi_disable(); + + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + + dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; + + return 0; +} + +static int sdi_display_resume(struct omap_dss_device *dssdev) +{ + int r; + + if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) + return -EINVAL; + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + r = dss_sdi_enable(); + if (r) + goto err; + mdelay(2); + + dispc_enable_lcd_out(1); + + if (dssdev->driver->resume) + dssdev->driver->resume(dssdev); + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + + return 0; +err: + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + return r; +} + +static int sdi_display_set_update_mode(struct omap_dss_device *dssdev, + enum omap_dss_update_mode mode) +{ + if (mode == OMAP_DSS_UPDATE_MANUAL) + return -EINVAL; + + if (mode == OMAP_DSS_UPDATE_DISABLED) { + dispc_enable_lcd_out(0); + sdi.update_enabled = 0; + } else { + dispc_enable_lcd_out(1); + sdi.update_enabled = 1; + } + + return 0; +} + +static enum omap_dss_update_mode sdi_display_get_update_mode( + struct omap_dss_device *dssdev) +{ + return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO : + OMAP_DSS_UPDATE_DISABLED; +} + +static void sdi_get_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + *timings = dssdev->panel.timings; +} + +int sdi_init_display(struct omap_dss_device *dssdev) +{ + DSSDBG("SDI init\n"); + + dssdev->enable = sdi_display_enable; + dssdev->disable = sdi_display_disable; + dssdev->suspend = sdi_display_suspend; + dssdev->resume = sdi_display_resume; + dssdev->set_update_mode = sdi_display_set_update_mode; + dssdev->get_update_mode = sdi_display_get_update_mode; + dssdev->get_timings = sdi_get_timings; + + return 0; +} + +int sdi_init(bool skip_init) +{ + /* we store this for first display enable, then clear it */ + sdi.skip_init = skip_init; + + /* + * Enable clocks already here, otherwise there would be a toggle + * of them until sdi_display_enable is called. + */ + if (skip_init) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + return 0; +} + +void sdi_exit(void) +{ +} diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c new file mode 100644 index 0000000000000000000000000000000000000000..749a5a0f5be476fb49f3abb56505a0537e7a337b --- /dev/null +++ b/drivers/video/omap2/dss/venc.c @@ -0,0 +1,797 @@ +/* + * linux/drivers/video/omap2/dss/venc.c + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * VENC settings from TI's DSS driver + * + * 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, see . + */ + +#define DSS_SUBSYS_NAME "VENC" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "dss.h" + +#define VENC_BASE 0x48050C00 + +/* Venc registers */ +#define VENC_REV_ID 0x00 +#define VENC_STATUS 0x04 +#define VENC_F_CONTROL 0x08 +#define VENC_VIDOUT_CTRL 0x10 +#define VENC_SYNC_CTRL 0x14 +#define VENC_LLEN 0x1C +#define VENC_FLENS 0x20 +#define VENC_HFLTR_CTRL 0x24 +#define VENC_CC_CARR_WSS_CARR 0x28 +#define VENC_C_PHASE 0x2C +#define VENC_GAIN_U 0x30 +#define VENC_GAIN_V 0x34 +#define VENC_GAIN_Y 0x38 +#define VENC_BLACK_LEVEL 0x3C +#define VENC_BLANK_LEVEL 0x40 +#define VENC_X_COLOR 0x44 +#define VENC_M_CONTROL 0x48 +#define VENC_BSTAMP_WSS_DATA 0x4C +#define VENC_S_CARR 0x50 +#define VENC_LINE21 0x54 +#define VENC_LN_SEL 0x58 +#define VENC_L21__WC_CTL 0x5C +#define VENC_HTRIGGER_VTRIGGER 0x60 +#define VENC_SAVID__EAVID 0x64 +#define VENC_FLEN__FAL 0x68 +#define VENC_LAL__PHASE_RESET 0x6C +#define VENC_HS_INT_START_STOP_X 0x70 +#define VENC_HS_EXT_START_STOP_X 0x74 +#define VENC_VS_INT_START_X 0x78 +#define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C +#define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80 +#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84 +#define VENC_VS_EXT_STOP_Y 0x88 +#define VENC_AVID_START_STOP_X 0x90 +#define VENC_AVID_START_STOP_Y 0x94 +#define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0 +#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4 +#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8 +#define VENC_TVDETGP_INT_START_STOP_X 0xB0 +#define VENC_TVDETGP_INT_START_STOP_Y 0xB4 +#define VENC_GEN_CTRL 0xB8 +#define VENC_OUTPUT_CONTROL 0xC4 +#define VENC_OUTPUT_TEST 0xC8 +#define VENC_DAC_B__DAC_C 0xC8 + +struct venc_config { + u32 f_control; + u32 vidout_ctrl; + u32 sync_ctrl; + u32 llen; + u32 flens; + u32 hfltr_ctrl; + u32 cc_carr_wss_carr; + u32 c_phase; + u32 gain_u; + u32 gain_v; + u32 gain_y; + u32 black_level; + u32 blank_level; + u32 x_color; + u32 m_control; + u32 bstamp_wss_data; + u32 s_carr; + u32 line21; + u32 ln_sel; + u32 l21__wc_ctl; + u32 htrigger_vtrigger; + u32 savid__eavid; + u32 flen__fal; + u32 lal__phase_reset; + u32 hs_int_start_stop_x; + u32 hs_ext_start_stop_x; + u32 vs_int_start_x; + u32 vs_int_stop_x__vs_int_start_y; + u32 vs_int_stop_y__vs_ext_start_x; + u32 vs_ext_stop_x__vs_ext_start_y; + u32 vs_ext_stop_y; + u32 avid_start_stop_x; + u32 avid_start_stop_y; + u32 fid_int_start_x__fid_int_start_y; + u32 fid_int_offset_y__fid_ext_start_x; + u32 fid_ext_start_y__fid_ext_offset_y; + u32 tvdetgp_int_start_stop_x; + u32 tvdetgp_int_start_stop_y; + u32 gen_ctrl; +}; + +/* from TRM */ +static const struct venc_config venc_config_pal_trm = { + .f_control = 0, + .vidout_ctrl = 1, + .sync_ctrl = 0x40, + .llen = 0x35F, /* 863 */ + .flens = 0x270, /* 624 */ + .hfltr_ctrl = 0, + .cc_carr_wss_carr = 0x2F7225ED, + .c_phase = 0, + .gain_u = 0x111, + .gain_v = 0x181, + .gain_y = 0x140, + .black_level = 0x3B, + .blank_level = 0x3B, + .x_color = 0x7, + .m_control = 0x2, + .bstamp_wss_data = 0x3F, + .s_carr = 0x2A098ACB, + .line21 = 0, + .ln_sel = 0x01290015, + .l21__wc_ctl = 0x0000F603, + .htrigger_vtrigger = 0, + + .savid__eavid = 0x06A70108, + .flen__fal = 0x00180270, + .lal__phase_reset = 0x00040135, + .hs_int_start_stop_x = 0x00880358, + .hs_ext_start_stop_x = 0x000F035F, + .vs_int_start_x = 0x01A70000, + .vs_int_stop_x__vs_int_start_y = 0x000001A7, + .vs_int_stop_y__vs_ext_start_x = 0x01AF0000, + .vs_ext_stop_x__vs_ext_start_y = 0x000101AF, + .vs_ext_stop_y = 0x00000025, + .avid_start_stop_x = 0x03530083, + .avid_start_stop_y = 0x026C002E, + .fid_int_start_x__fid_int_start_y = 0x0001008A, + .fid_int_offset_y__fid_ext_start_x = 0x002E0138, + .fid_ext_start_y__fid_ext_offset_y = 0x01380001, + + .tvdetgp_int_start_stop_x = 0x00140001, + .tvdetgp_int_start_stop_y = 0x00010001, + .gen_ctrl = 0x00FF0000, +}; + +/* from TRM */ +static const struct venc_config venc_config_ntsc_trm = { + .f_control = 0, + .vidout_ctrl = 1, + .sync_ctrl = 0x8040, + .llen = 0x359, + .flens = 0x20C, + .hfltr_ctrl = 0, + .cc_carr_wss_carr = 0x043F2631, + .c_phase = 0, + .gain_u = 0x102, + .gain_v = 0x16C, + .gain_y = 0x12F, + .black_level = 0x43, + .blank_level = 0x38, + .x_color = 0x7, + .m_control = 0x1, + .bstamp_wss_data = 0x38, + .s_carr = 0x21F07C1F, + .line21 = 0, + .ln_sel = 0x01310011, + .l21__wc_ctl = 0x0000F003, + .htrigger_vtrigger = 0, + + .savid__eavid = 0x069300F4, + .flen__fal = 0x0016020C, + .lal__phase_reset = 0x00060107, + .hs_int_start_stop_x = 0x008E0350, + .hs_ext_start_stop_x = 0x000F0359, + .vs_int_start_x = 0x01A00000, + .vs_int_stop_x__vs_int_start_y = 0x020701A0, + .vs_int_stop_y__vs_ext_start_x = 0x01AC0024, + .vs_ext_stop_x__vs_ext_start_y = 0x020D01AC, + .vs_ext_stop_y = 0x00000006, + .avid_start_stop_x = 0x03480078, + .avid_start_stop_y = 0x02060024, + .fid_int_start_x__fid_int_start_y = 0x0001008A, + .fid_int_offset_y__fid_ext_start_x = 0x01AC0106, + .fid_ext_start_y__fid_ext_offset_y = 0x01060006, + + .tvdetgp_int_start_stop_x = 0x00140001, + .tvdetgp_int_start_stop_y = 0x00010001, + .gen_ctrl = 0x00F90000, +}; + +static const struct venc_config venc_config_pal_bdghi = { + .f_control = 0, + .vidout_ctrl = 0, + .sync_ctrl = 0, + .hfltr_ctrl = 0, + .x_color = 0, + .line21 = 0, + .ln_sel = 21, + .htrigger_vtrigger = 0, + .tvdetgp_int_start_stop_x = 0x00140001, + .tvdetgp_int_start_stop_y = 0x00010001, + .gen_ctrl = 0x00FB0000, + + .llen = 864-1, + .flens = 625-1, + .cc_carr_wss_carr = 0x2F7625ED, + .c_phase = 0xDF, + .gain_u = 0x111, + .gain_v = 0x181, + .gain_y = 0x140, + .black_level = 0x3e, + .blank_level = 0x3e, + .m_control = 0<<2 | 1<<1, + .bstamp_wss_data = 0x42, + .s_carr = 0x2a098acb, + .l21__wc_ctl = 0<<13 | 0x16<<8 | 0<<0, + .savid__eavid = 0x06A70108, + .flen__fal = 23<<16 | 624<<0, + .lal__phase_reset = 2<<17 | 310<<0, + .hs_int_start_stop_x = 0x00920358, + .hs_ext_start_stop_x = 0x000F035F, + .vs_int_start_x = 0x1a7<<16, + .vs_int_stop_x__vs_int_start_y = 0x000601A7, + .vs_int_stop_y__vs_ext_start_x = 0x01AF0036, + .vs_ext_stop_x__vs_ext_start_y = 0x27101af, + .vs_ext_stop_y = 0x05, + .avid_start_stop_x = 0x03530082, + .avid_start_stop_y = 0x0270002E, + .fid_int_start_x__fid_int_start_y = 0x0005008A, + .fid_int_offset_y__fid_ext_start_x = 0x002E0138, + .fid_ext_start_y__fid_ext_offset_y = 0x01380005, +}; + +const struct omap_video_timings omap_dss_pal_timings = { + .x_res = 720, + .y_res = 574, + .pixel_clock = 13500, + .hsw = 64, + .hfp = 12, + .hbp = 68, + .vsw = 5, + .vfp = 5, + .vbp = 41, +}; +EXPORT_SYMBOL(omap_dss_pal_timings); + +const struct omap_video_timings omap_dss_ntsc_timings = { + .x_res = 720, + .y_res = 482, + .pixel_clock = 13500, + .hsw = 64, + .hfp = 16, + .hbp = 58, + .vsw = 6, + .vfp = 6, + .vbp = 31, +}; +EXPORT_SYMBOL(omap_dss_ntsc_timings); + +static struct { + void __iomem *base; + struct mutex venc_lock; + u32 wss_data; + struct regulator *vdda_dac_reg; +} venc; + +static inline void venc_write_reg(int idx, u32 val) +{ + __raw_writel(val, venc.base + idx); +} + +static inline u32 venc_read_reg(int idx) +{ + u32 l = __raw_readl(venc.base + idx); + return l; +} + +static void venc_write_config(const struct venc_config *config) +{ + DSSDBG("write venc conf\n"); + + venc_write_reg(VENC_LLEN, config->llen); + venc_write_reg(VENC_FLENS, config->flens); + venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr); + venc_write_reg(VENC_C_PHASE, config->c_phase); + venc_write_reg(VENC_GAIN_U, config->gain_u); + venc_write_reg(VENC_GAIN_V, config->gain_v); + venc_write_reg(VENC_GAIN_Y, config->gain_y); + venc_write_reg(VENC_BLACK_LEVEL, config->black_level); + venc_write_reg(VENC_BLANK_LEVEL, config->blank_level); + venc_write_reg(VENC_M_CONTROL, config->m_control); + venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | + venc.wss_data); + venc_write_reg(VENC_S_CARR, config->s_carr); + venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl); + venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid); + venc_write_reg(VENC_FLEN__FAL, config->flen__fal); + venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset); + venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x); + venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x); + venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x); + venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y, + config->vs_int_stop_x__vs_int_start_y); + venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X, + config->vs_int_stop_y__vs_ext_start_x); + venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y, + config->vs_ext_stop_x__vs_ext_start_y); + venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y); + venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x); + venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y); + venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y, + config->fid_int_start_x__fid_int_start_y); + venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X, + config->fid_int_offset_y__fid_ext_start_x); + venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y, + config->fid_ext_start_y__fid_ext_offset_y); + + venc_write_reg(VENC_DAC_B__DAC_C, venc_read_reg(VENC_DAC_B__DAC_C)); + venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl); + venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl); + venc_write_reg(VENC_X_COLOR, config->x_color); + venc_write_reg(VENC_LINE21, config->line21); + venc_write_reg(VENC_LN_SEL, config->ln_sel); + venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger); + venc_write_reg(VENC_TVDETGP_INT_START_STOP_X, + config->tvdetgp_int_start_stop_x); + venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y, + config->tvdetgp_int_start_stop_y); + venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl); + venc_write_reg(VENC_F_CONTROL, config->f_control); + venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl); +} + +static void venc_reset(void) +{ + int t = 1000; + + venc_write_reg(VENC_F_CONTROL, 1<<8); + while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) { + if (--t == 0) { + DSSERR("Failed to reset venc\n"); + return; + } + } + + /* the magical sleep that makes things work */ + msleep(20); +} + +static void venc_enable_clocks(int enable) +{ + if (enable) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | + DSS_CLK_96M); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | + DSS_CLK_96M); +} + +static const struct venc_config *venc_timings_to_config( + struct omap_video_timings *timings) +{ + if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0) + return &venc_config_pal_trm; + + if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0) + return &venc_config_ntsc_trm; + + BUG(); +} + + + + + +/* driver */ +static int venc_panel_probe(struct omap_dss_device *dssdev) +{ + dssdev->panel.timings = omap_dss_pal_timings; + + return 0; +} + +static void venc_panel_remove(struct omap_dss_device *dssdev) +{ +} + +static int venc_panel_enable(struct omap_dss_device *dssdev) +{ + int r = 0; + + /* wait couple of vsyncs until enabling the LCD */ + msleep(50); + + if (dssdev->platform_enable) + r = dssdev->platform_enable(dssdev); + + return r; +} + +static void venc_panel_disable(struct omap_dss_device *dssdev) +{ + if (dssdev->platform_disable) + dssdev->platform_disable(dssdev); + + /* wait at least 5 vsyncs after disabling the LCD */ + + msleep(100); +} + +static int venc_panel_suspend(struct omap_dss_device *dssdev) +{ + venc_panel_disable(dssdev); + return 0; +} + +static int venc_panel_resume(struct omap_dss_device *dssdev) +{ + return venc_panel_enable(dssdev); +} + +static struct omap_dss_driver venc_driver = { + .probe = venc_panel_probe, + .remove = venc_panel_remove, + + .enable = venc_panel_enable, + .disable = venc_panel_disable, + .suspend = venc_panel_suspend, + .resume = venc_panel_resume, + + .driver = { + .name = "venc", + .owner = THIS_MODULE, + }, +}; +/* driver end */ + + + +int venc_init(struct platform_device *pdev) +{ + u8 rev_id; + + mutex_init(&venc.venc_lock); + + venc.wss_data = 0; + + venc.base = ioremap(VENC_BASE, SZ_1K); + if (!venc.base) { + DSSERR("can't ioremap VENC\n"); + return -ENOMEM; + } + + venc.vdda_dac_reg = regulator_get(&pdev->dev, "vdda_dac"); + if (IS_ERR(venc.vdda_dac_reg)) { + iounmap(venc.base); + DSSERR("can't get VDDA_DAC regulator\n"); + return PTR_ERR(venc.vdda_dac_reg); + } + + venc_enable_clocks(1); + + rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); + printk(KERN_INFO "OMAP VENC rev %d\n", rev_id); + + venc_enable_clocks(0); + + return omap_dss_register_driver(&venc_driver); +} + +void venc_exit(void) +{ + omap_dss_unregister_driver(&venc_driver); + + regulator_put(venc.vdda_dac_reg); + + iounmap(venc.base); +} + +static void venc_power_on(struct omap_dss_device *dssdev) +{ + u32 l; + + venc_enable_clocks(1); + + venc_reset(); + venc_write_config(venc_timings_to_config(&dssdev->panel.timings)); + + dss_set_venc_output(dssdev->phy.venc.type); + dss_set_dac_pwrdn_bgz(1); + + l = 0; + + if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) + l |= 1 << 1; + else /* S-Video */ + l |= (1 << 0) | (1 << 2); + + if (dssdev->phy.venc.invert_polarity == false) + l |= 1 << 3; + + venc_write_reg(VENC_OUTPUT_CONTROL, l); + + dispc_set_digit_size(dssdev->panel.timings.x_res, + dssdev->panel.timings.y_res/2); + + regulator_enable(venc.vdda_dac_reg); + + if (dssdev->platform_enable) + dssdev->platform_enable(dssdev); + + dispc_enable_digit_out(1); +} + +static void venc_power_off(struct omap_dss_device *dssdev) +{ + venc_write_reg(VENC_OUTPUT_CONTROL, 0); + dss_set_dac_pwrdn_bgz(0); + + dispc_enable_digit_out(0); + + if (dssdev->platform_disable) + dssdev->platform_disable(dssdev); + + regulator_disable(venc.vdda_dac_reg); + + venc_enable_clocks(0); +} + +static int venc_enable_display(struct omap_dss_device *dssdev) +{ + int r = 0; + + DSSDBG("venc_enable_display\n"); + + mutex_lock(&venc.venc_lock); + + if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { + r = -EINVAL; + goto err; + } + + venc_power_on(dssdev); + + venc.wss_data = 0; + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; +err: + mutex_unlock(&venc.venc_lock); + + return r; +} + +static void venc_disable_display(struct omap_dss_device *dssdev) +{ + DSSDBG("venc_disable_display\n"); + + mutex_lock(&venc.venc_lock); + + if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED) + goto end; + + if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) { + /* suspended is the same as disabled with venc */ + dssdev->state = OMAP_DSS_DISPLAY_DISABLED; + goto end; + } + + venc_power_off(dssdev); + + dssdev->state = OMAP_DSS_DISPLAY_DISABLED; +end: + mutex_unlock(&venc.venc_lock); +} + +static int venc_display_suspend(struct omap_dss_device *dssdev) +{ + int r = 0; + + DSSDBG("venc_display_suspend\n"); + + mutex_lock(&venc.venc_lock); + + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { + r = -EINVAL; + goto err; + } + + venc_power_off(dssdev); + + dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; +err: + mutex_unlock(&venc.venc_lock); + + return r; +} + +static int venc_display_resume(struct omap_dss_device *dssdev) +{ + int r = 0; + + DSSDBG("venc_display_resume\n"); + + mutex_lock(&venc.venc_lock); + + if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { + r = -EINVAL; + goto err; + } + + venc_power_on(dssdev); + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; +err: + mutex_unlock(&venc.venc_lock); + + return r; +} + +static void venc_get_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + *timings = dssdev->panel.timings; +} + +static void venc_set_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + DSSDBG("venc_set_timings\n"); + + /* Reset WSS data when the TV standard changes. */ + if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings))) + venc.wss_data = 0; + + dssdev->panel.timings = *timings; + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { + /* turn the venc off and on to get new timings to use */ + venc_disable_display(dssdev); + venc_enable_display(dssdev); + } +} + +static int venc_check_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + DSSDBG("venc_check_timings\n"); + + if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0) + return 0; + + if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0) + return 0; + + return -EINVAL; +} + +static u32 venc_get_wss(struct omap_dss_device *dssdev) +{ + /* Invert due to VENC_L21_WC_CTL:INV=1 */ + return (venc.wss_data >> 8) ^ 0xfffff; +} + +static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) +{ + const struct venc_config *config; + + DSSDBG("venc_set_wss\n"); + + mutex_lock(&venc.venc_lock); + + config = venc_timings_to_config(&dssdev->panel.timings); + + /* Invert due to VENC_L21_WC_CTL:INV=1 */ + venc.wss_data = (wss ^ 0xfffff) << 8; + + venc_enable_clocks(1); + + venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | + venc.wss_data); + + venc_enable_clocks(0); + + mutex_unlock(&venc.venc_lock); + + return 0; +} + +static enum omap_dss_update_mode venc_display_get_update_mode( + struct omap_dss_device *dssdev) +{ + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) + return OMAP_DSS_UPDATE_AUTO; + else + return OMAP_DSS_UPDATE_DISABLED; +} + +int venc_init_display(struct omap_dss_device *dssdev) +{ + DSSDBG("init_display\n"); + + dssdev->enable = venc_enable_display; + dssdev->disable = venc_disable_display; + dssdev->suspend = venc_display_suspend; + dssdev->resume = venc_display_resume; + dssdev->get_timings = venc_get_timings; + dssdev->set_timings = venc_set_timings; + dssdev->check_timings = venc_check_timings; + dssdev->get_wss = venc_get_wss; + dssdev->set_wss = venc_set_wss; + dssdev->get_update_mode = venc_display_get_update_mode; + + return 0; +} + +void venc_dump_regs(struct seq_file *s) +{ +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) + + venc_enable_clocks(1); + + DUMPREG(VENC_F_CONTROL); + DUMPREG(VENC_VIDOUT_CTRL); + DUMPREG(VENC_SYNC_CTRL); + DUMPREG(VENC_LLEN); + DUMPREG(VENC_FLENS); + DUMPREG(VENC_HFLTR_CTRL); + DUMPREG(VENC_CC_CARR_WSS_CARR); + DUMPREG(VENC_C_PHASE); + DUMPREG(VENC_GAIN_U); + DUMPREG(VENC_GAIN_V); + DUMPREG(VENC_GAIN_Y); + DUMPREG(VENC_BLACK_LEVEL); + DUMPREG(VENC_BLANK_LEVEL); + DUMPREG(VENC_X_COLOR); + DUMPREG(VENC_M_CONTROL); + DUMPREG(VENC_BSTAMP_WSS_DATA); + DUMPREG(VENC_S_CARR); + DUMPREG(VENC_LINE21); + DUMPREG(VENC_LN_SEL); + DUMPREG(VENC_L21__WC_CTL); + DUMPREG(VENC_HTRIGGER_VTRIGGER); + DUMPREG(VENC_SAVID__EAVID); + DUMPREG(VENC_FLEN__FAL); + DUMPREG(VENC_LAL__PHASE_RESET); + DUMPREG(VENC_HS_INT_START_STOP_X); + DUMPREG(VENC_HS_EXT_START_STOP_X); + DUMPREG(VENC_VS_INT_START_X); + DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y); + DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X); + DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y); + DUMPREG(VENC_VS_EXT_STOP_Y); + DUMPREG(VENC_AVID_START_STOP_X); + DUMPREG(VENC_AVID_START_STOP_Y); + DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y); + DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X); + DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y); + DUMPREG(VENC_TVDETGP_INT_START_STOP_X); + DUMPREG(VENC_TVDETGP_INT_START_STOP_Y); + DUMPREG(VENC_GEN_CTRL); + DUMPREG(VENC_OUTPUT_CONTROL); + DUMPREG(VENC_OUTPUT_TEST); + + venc_enable_clocks(0); + +#undef DUMPREG +} diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..bb694cc52a508ecbcaa22c0d609b75f48e464176 --- /dev/null +++ b/drivers/video/omap2/omapfb/Kconfig @@ -0,0 +1,37 @@ +menuconfig FB_OMAP2 + tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)" + depends on FB && OMAP2_DSS + + select OMAP2_VRAM + select OMAP2_VRFB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Frame buffer driver for OMAP2/3 based boards. + +config FB_OMAP2_DEBUG_SUPPORT + bool "Debug support for OMAP2/3 FB" + default y + depends on FB_OMAP2 + help + Support for debug output. You have to enable the actual printing + with debug module parameter. + +config FB_OMAP2_FORCE_AUTO_UPDATE + bool "Force main display to automatic update mode" + depends on FB_OMAP2 + help + Forces main display to automatic update mode (if possible), + and also enables tearsync (if possible). By default + displays that support manual update are started in manual + update mode. + +config FB_OMAP2_NUM_FBS + int "Number of framebuffers" + range 1 10 + default 3 + depends on FB_OMAP2 + help + Select the number of framebuffers created. OMAP2/3 has 3 overlays + so normally this would be 3. diff --git a/drivers/video/omap2/omapfb/Makefile b/drivers/video/omap2/omapfb/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..51c2e00d9bf8e03d57d9980c7cce4f37b195c283 --- /dev/null +++ b/drivers/video/omap2/omapfb/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_FB_OMAP2) += omapfb.o +omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c new file mode 100644 index 0000000000000000000000000000000000000000..4c4bafdfaa4386b4a03f174b2c7821aca5bb334d --- /dev/null +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c @@ -0,0 +1,755 @@ +/* + * linux/drivers/video/omap2/omapfb-ioctl.c + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "omapfb.h" + +static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omap_overlay *ovl; + struct omap_overlay_info info; + int r = 0; + + DBG("omapfb_setup_plane\n"); + + if (ofbi->num_overlays != 1) { + r = -EINVAL; + goto out; + } + + /* XXX uses only the first overlay */ + ovl = ofbi->overlays[0]; + + if (pi->enabled && !ofbi->region.size) { + /* + * This plane's memory was freed, can't enable it + * until it's reallocated. + */ + r = -EINVAL; + goto out; + } + + ovl->get_overlay_info(ovl, &info); + + info.pos_x = pi->pos_x; + info.pos_y = pi->pos_y; + info.out_width = pi->out_width; + info.out_height = pi->out_height; + info.enabled = pi->enabled; + + r = ovl->set_overlay_info(ovl, &info); + if (r) + goto out; + + if (ovl->manager) { + r = ovl->manager->apply(ovl->manager); + if (r) + goto out; + } + +out: + if (r) + dev_err(fbdev->dev, "setup_plane failed\n"); + return r; +} + +static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + + if (ofbi->num_overlays != 1) { + memset(pi, 0, sizeof(*pi)); + } else { + struct omap_overlay_info *ovli; + struct omap_overlay *ovl; + + ovl = ofbi->overlays[0]; + ovli = &ovl->info; + + pi->pos_x = ovli->pos_x; + pi->pos_y = ovli->pos_y; + pi->enabled = ovli->enabled; + pi->channel_out = 0; /* xxx */ + pi->mirror = 0; + pi->out_width = ovli->out_width; + pi->out_height = ovli->out_height; + } + + return 0; +} + +static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omapfb2_mem_region *rg; + int r, i; + size_t size; + + if (mi->type > OMAPFB_MEMTYPE_MAX) + return -EINVAL; + + size = PAGE_ALIGN(mi->size); + + rg = &ofbi->region; + + for (i = 0; i < ofbi->num_overlays; i++) { + if (ofbi->overlays[i]->info.enabled) + return -EBUSY; + } + + if (rg->size != size || rg->type != mi->type) { + r = omapfb_realloc_fbmem(fbi, size, mi->type); + if (r) { + dev_err(fbdev->dev, "realloc fbmem failed\n"); + return r; + } + } + + return 0; +} + +static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_mem_region *rg; + + rg = &ofbi->region; + memset(mi, 0, sizeof(*mi)); + + mi->size = rg->size; + mi->type = rg->type; + + return 0; +} + +static int omapfb_update_window_nolock(struct fb_info *fbi, + u32 x, u32 y, u32 w, u32 h) +{ + struct omap_dss_device *display = fb2display(fbi); + u16 dw, dh; + + if (!display) + return 0; + + if (w == 0 || h == 0) + return 0; + + display->get_resolution(display, &dw, &dh); + + if (x + w > dw || y + h > dh) + return -EINVAL; + + return display->update(display, x, y, w, h); +} + +/* This function is exported for SGX driver use */ +int omapfb_update_window(struct fb_info *fbi, + u32 x, u32 y, u32 w, u32 h) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + int r; + + omapfb_lock(fbdev); + lock_fb_info(fbi); + + r = omapfb_update_window_nolock(fbi, x, y, w, h); + + unlock_fb_info(fbi); + omapfb_unlock(fbdev); + + return r; +} +EXPORT_SYMBOL(omapfb_update_window); + +static int omapfb_set_update_mode(struct fb_info *fbi, + enum omapfb_update_mode mode) +{ + struct omap_dss_device *display = fb2display(fbi); + enum omap_dss_update_mode um; + int r; + + if (!display || !display->set_update_mode) + return -EINVAL; + + switch (mode) { + case OMAPFB_UPDATE_DISABLED: + um = OMAP_DSS_UPDATE_DISABLED; + break; + + case OMAPFB_AUTO_UPDATE: + um = OMAP_DSS_UPDATE_AUTO; + break; + + case OMAPFB_MANUAL_UPDATE: + um = OMAP_DSS_UPDATE_MANUAL; + break; + + default: + return -EINVAL; + } + + r = display->set_update_mode(display, um); + + return r; +} + +static int omapfb_get_update_mode(struct fb_info *fbi, + enum omapfb_update_mode *mode) +{ + struct omap_dss_device *display = fb2display(fbi); + enum omap_dss_update_mode m; + + if (!display || !display->get_update_mode) + return -EINVAL; + + m = display->get_update_mode(display); + + switch (m) { + case OMAP_DSS_UPDATE_DISABLED: + *mode = OMAPFB_UPDATE_DISABLED; + break; + case OMAP_DSS_UPDATE_AUTO: + *mode = OMAPFB_AUTO_UPDATE; + break; + case OMAP_DSS_UPDATE_MANUAL: + *mode = OMAPFB_MANUAL_UPDATE; + break; + default: + BUG(); + } + + return 0; +} + +/* XXX this color key handling is a hack... */ +static struct omapfb_color_key omapfb_color_keys[2]; + +static int _omapfb_set_color_key(struct omap_overlay_manager *mgr, + struct omapfb_color_key *ck) +{ + struct omap_overlay_manager_info info; + enum omap_dss_trans_key_type kt; + int r; + + mgr->get_manager_info(mgr, &info); + + if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) { + info.trans_enabled = false; + omapfb_color_keys[mgr->id] = *ck; + + r = mgr->set_manager_info(mgr, &info); + if (r) + return r; + + r = mgr->apply(mgr); + + return r; + } + + switch (ck->key_type) { + case OMAPFB_COLOR_KEY_GFX_DST: + kt = OMAP_DSS_COLOR_KEY_GFX_DST; + break; + case OMAPFB_COLOR_KEY_VID_SRC: + kt = OMAP_DSS_COLOR_KEY_VID_SRC; + break; + default: + return -EINVAL; + } + + info.default_color = ck->background; + info.trans_key = ck->trans_key; + info.trans_key_type = kt; + info.trans_enabled = true; + + omapfb_color_keys[mgr->id] = *ck; + + r = mgr->set_manager_info(mgr, &info); + if (r) + return r; + + r = mgr->apply(mgr); + + return r; +} + +static int omapfb_set_color_key(struct fb_info *fbi, + struct omapfb_color_key *ck) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + int r; + int i; + struct omap_overlay_manager *mgr = NULL; + + omapfb_lock(fbdev); + + for (i = 0; i < ofbi->num_overlays; i++) { + if (ofbi->overlays[i]->manager) { + mgr = ofbi->overlays[i]->manager; + break; + } + } + + if (!mgr) { + r = -EINVAL; + goto err; + } + + r = _omapfb_set_color_key(mgr, ck); +err: + omapfb_unlock(fbdev); + + return r; +} + +static int omapfb_get_color_key(struct fb_info *fbi, + struct omapfb_color_key *ck) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omap_overlay_manager *mgr = NULL; + int r = 0; + int i; + + omapfb_lock(fbdev); + + for (i = 0; i < ofbi->num_overlays; i++) { + if (ofbi->overlays[i]->manager) { + mgr = ofbi->overlays[i]->manager; + break; + } + } + + if (!mgr) { + r = -EINVAL; + goto err; + } + + *ck = omapfb_color_keys[mgr->id]; +err: + omapfb_unlock(fbdev); + + return r; +} + +static int omapfb_memory_read(struct fb_info *fbi, + struct omapfb_memory_read *mr) +{ + struct omap_dss_device *display = fb2display(fbi); + void *buf; + int r; + + if (!display || !display->memory_read) + return -ENOENT; + + if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size)) + return -EFAULT; + + if (mr->w * mr->h * 3 > mr->buffer_size) + return -EINVAL; + + buf = vmalloc(mr->buffer_size); + if (!buf) { + DBG("vmalloc failed\n"); + return -ENOMEM; + } + + r = display->memory_read(display, buf, mr->buffer_size, + mr->x, mr->y, mr->w, mr->h); + + if (r > 0) { + if (copy_to_user(mr->buffer, buf, mr->buffer_size)) + r = -EFAULT; + } + + vfree(buf); + + return r; +} + +static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev, + struct omapfb_ovl_colormode *mode) +{ + int ovl_idx = mode->overlay_idx; + int mode_idx = mode->mode_idx; + struct omap_overlay *ovl; + enum omap_color_mode supported_modes; + struct fb_var_screeninfo var; + int i; + + if (ovl_idx >= fbdev->num_overlays) + return -ENODEV; + ovl = fbdev->overlays[ovl_idx]; + supported_modes = ovl->supported_modes; + + mode_idx = mode->mode_idx; + + for (i = 0; i < sizeof(supported_modes) * 8; i++) { + if (!(supported_modes & (1 << i))) + continue; + /* + * It's possible that the FB doesn't support a mode + * that is supported by the overlay, so call the + * following here. + */ + if (dss_mode_to_fb_mode(1 << i, &var) < 0) + continue; + + mode_idx--; + if (mode_idx < 0) + break; + } + + if (i == sizeof(supported_modes) * 8) + return -ENOENT; + + mode->bits_per_pixel = var.bits_per_pixel; + mode->nonstd = var.nonstd; + mode->red = var.red; + mode->green = var.green; + mode->blue = var.blue; + mode->transp = var.transp; + + return 0; +} + +static int omapfb_wait_for_go(struct fb_info *fbi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + int r = 0; + int i; + + for (i = 0; i < ofbi->num_overlays; ++i) { + struct omap_overlay *ovl = ofbi->overlays[i]; + r = ovl->wait_for_go(ovl); + if (r) + break; + } + + return r; +} + +int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omap_dss_device *display = fb2display(fbi); + + union { + struct omapfb_update_window_old uwnd_o; + struct omapfb_update_window uwnd; + struct omapfb_plane_info plane_info; + struct omapfb_caps caps; + struct omapfb_mem_info mem_info; + struct omapfb_color_key color_key; + struct omapfb_ovl_colormode ovl_colormode; + enum omapfb_update_mode update_mode; + int test_num; + struct omapfb_memory_read memory_read; + struct omapfb_vram_info vram_info; + struct omapfb_tearsync_info tearsync_info; + } p; + + int r = 0; + + switch (cmd) { + case OMAPFB_SYNC_GFX: + DBG("ioctl SYNC_GFX\n"); + if (!display || !display->sync) { + /* DSS1 never returns an error here, so we neither */ + /*r = -EINVAL;*/ + break; + } + + r = display->sync(display); + break; + + case OMAPFB_UPDATE_WINDOW_OLD: + DBG("ioctl UPDATE_WINDOW_OLD\n"); + if (!display || !display->update) { + r = -EINVAL; + break; + } + + if (copy_from_user(&p.uwnd_o, + (void __user *)arg, + sizeof(p.uwnd_o))) { + r = -EFAULT; + break; + } + + r = omapfb_update_window_nolock(fbi, p.uwnd_o.x, p.uwnd_o.y, + p.uwnd_o.width, p.uwnd_o.height); + break; + + case OMAPFB_UPDATE_WINDOW: + DBG("ioctl UPDATE_WINDOW\n"); + if (!display || !display->update) { + r = -EINVAL; + break; + } + + if (copy_from_user(&p.uwnd, (void __user *)arg, + sizeof(p.uwnd))) { + r = -EFAULT; + break; + } + + r = omapfb_update_window_nolock(fbi, p.uwnd.x, p.uwnd.y, + p.uwnd.width, p.uwnd.height); + break; + + case OMAPFB_SETUP_PLANE: + DBG("ioctl SETUP_PLANE\n"); + if (copy_from_user(&p.plane_info, (void __user *)arg, + sizeof(p.plane_info))) + r = -EFAULT; + else + r = omapfb_setup_plane(fbi, &p.plane_info); + break; + + case OMAPFB_QUERY_PLANE: + DBG("ioctl QUERY_PLANE\n"); + r = omapfb_query_plane(fbi, &p.plane_info); + if (r < 0) + break; + if (copy_to_user((void __user *)arg, &p.plane_info, + sizeof(p.plane_info))) + r = -EFAULT; + break; + + case OMAPFB_SETUP_MEM: + DBG("ioctl SETUP_MEM\n"); + if (copy_from_user(&p.mem_info, (void __user *)arg, + sizeof(p.mem_info))) + r = -EFAULT; + else + r = omapfb_setup_mem(fbi, &p.mem_info); + break; + + case OMAPFB_QUERY_MEM: + DBG("ioctl QUERY_MEM\n"); + r = omapfb_query_mem(fbi, &p.mem_info); + if (r < 0) + break; + if (copy_to_user((void __user *)arg, &p.mem_info, + sizeof(p.mem_info))) + r = -EFAULT; + break; + + case OMAPFB_GET_CAPS: + DBG("ioctl GET_CAPS\n"); + if (!display) { + r = -EINVAL; + break; + } + + memset(&p.caps, 0, sizeof(p.caps)); + if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) + p.caps.ctrl |= OMAPFB_CAPS_MANUAL_UPDATE; + if (display->caps & OMAP_DSS_DISPLAY_CAP_TEAR_ELIM) + p.caps.ctrl |= OMAPFB_CAPS_TEARSYNC; + + if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps))) + r = -EFAULT; + break; + + case OMAPFB_GET_OVERLAY_COLORMODE: + DBG("ioctl GET_OVERLAY_COLORMODE\n"); + if (copy_from_user(&p.ovl_colormode, (void __user *)arg, + sizeof(p.ovl_colormode))) { + r = -EFAULT; + break; + } + r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode); + if (r < 0) + break; + if (copy_to_user((void __user *)arg, &p.ovl_colormode, + sizeof(p.ovl_colormode))) + r = -EFAULT; + break; + + case OMAPFB_SET_UPDATE_MODE: + DBG("ioctl SET_UPDATE_MODE\n"); + if (get_user(p.update_mode, (int __user *)arg)) + r = -EFAULT; + else + r = omapfb_set_update_mode(fbi, p.update_mode); + break; + + case OMAPFB_GET_UPDATE_MODE: + DBG("ioctl GET_UPDATE_MODE\n"); + r = omapfb_get_update_mode(fbi, &p.update_mode); + if (r) + break; + if (put_user(p.update_mode, + (enum omapfb_update_mode __user *)arg)) + r = -EFAULT; + break; + + case OMAPFB_SET_COLOR_KEY: + DBG("ioctl SET_COLOR_KEY\n"); + if (copy_from_user(&p.color_key, (void __user *)arg, + sizeof(p.color_key))) + r = -EFAULT; + else + r = omapfb_set_color_key(fbi, &p.color_key); + break; + + case OMAPFB_GET_COLOR_KEY: + DBG("ioctl GET_COLOR_KEY\n"); + r = omapfb_get_color_key(fbi, &p.color_key); + if (r) + break; + if (copy_to_user((void __user *)arg, &p.color_key, + sizeof(p.color_key))) + r = -EFAULT; + break; + + case OMAPFB_WAITFORVSYNC: + DBG("ioctl WAITFORVSYNC\n"); + if (!display) { + r = -EINVAL; + break; + } + + r = display->wait_vsync(display); + break; + + case OMAPFB_WAITFORGO: + DBG("ioctl WAITFORGO\n"); + if (!display) { + r = -EINVAL; + break; + } + + r = omapfb_wait_for_go(fbi); + break; + + /* LCD and CTRL tests do the same thing for backward + * compatibility */ + case OMAPFB_LCD_TEST: + DBG("ioctl LCD_TEST\n"); + if (get_user(p.test_num, (int __user *)arg)) { + r = -EFAULT; + break; + } + if (!display || !display->run_test) { + r = -EINVAL; + break; + } + + r = display->run_test(display, p.test_num); + + break; + + case OMAPFB_CTRL_TEST: + DBG("ioctl CTRL_TEST\n"); + if (get_user(p.test_num, (int __user *)arg)) { + r = -EFAULT; + break; + } + if (!display || !display->run_test) { + r = -EINVAL; + break; + } + + r = display->run_test(display, p.test_num); + + break; + + case OMAPFB_MEMORY_READ: + DBG("ioctl MEMORY_READ\n"); + + if (copy_from_user(&p.memory_read, (void __user *)arg, + sizeof(p.memory_read))) { + r = -EFAULT; + break; + } + + r = omapfb_memory_read(fbi, &p.memory_read); + + break; + + case OMAPFB_GET_VRAM_INFO: { + unsigned long vram, free, largest; + + DBG("ioctl GET_VRAM_INFO\n"); + + omap_vram_get_info(&vram, &free, &largest); + p.vram_info.total = vram; + p.vram_info.free = free; + p.vram_info.largest_free_block = largest; + + if (copy_to_user((void __user *)arg, &p.vram_info, + sizeof(p.vram_info))) + r = -EFAULT; + break; + } + + case OMAPFB_SET_TEARSYNC: { + DBG("ioctl SET_TEARSYNC\n"); + + if (copy_from_user(&p.tearsync_info, (void __user *)arg, + sizeof(p.tearsync_info))) { + r = -EFAULT; + break; + } + + if (!display->enable_te) { + r = -ENODEV; + break; + } + + r = display->enable_te(display, !!p.tearsync_info.enabled); + + break; + } + + default: + dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd); + r = -EINVAL; + } + + if (r < 0) + DBG("ioctl failed: %d\n", r); + + return r; +} + + diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c new file mode 100644 index 0000000000000000000000000000000000000000..ef299839858aa5b87c4826fdd1bd36127c5072d1 --- /dev/null +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -0,0 +1,2261 @@ +/* + * linux/drivers/video/omap2/omapfb-main.c + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "omapfb.h" + +#define MODULE_NAME "omapfb" + +#define OMAPFB_PLANE_XRES_MIN 8 +#define OMAPFB_PLANE_YRES_MIN 8 + +static char *def_mode; +static char *def_vram; +static int def_vrfb; +static int def_rotate; +static int def_mirror; + +#ifdef DEBUG +unsigned int omapfb_debug; +module_param_named(debug, omapfb_debug, bool, 0644); +static unsigned int omapfb_test_pattern; +module_param_named(test, omapfb_test_pattern, bool, 0644); +#endif + +static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi); + +#ifdef DEBUG +static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color) +{ + struct fb_var_screeninfo *var = &fbi->var; + struct fb_fix_screeninfo *fix = &fbi->fix; + void __iomem *addr = fbi->screen_base; + const unsigned bytespp = var->bits_per_pixel >> 3; + const unsigned line_len = fix->line_length / bytespp; + + int r = (color >> 16) & 0xff; + int g = (color >> 8) & 0xff; + int b = (color >> 0) & 0xff; + + if (var->bits_per_pixel == 16) { + u16 __iomem *p = (u16 __iomem *)addr; + p += y * line_len + x; + + r = r * 32 / 256; + g = g * 64 / 256; + b = b * 32 / 256; + + __raw_writew((r << 11) | (g << 5) | (b << 0), p); + } else if (var->bits_per_pixel == 24) { + u8 __iomem *p = (u8 __iomem *)addr; + p += (y * line_len + x) * 3; + + __raw_writeb(b, p + 0); + __raw_writeb(g, p + 1); + __raw_writeb(r, p + 2); + } else if (var->bits_per_pixel == 32) { + u32 __iomem *p = (u32 __iomem *)addr; + p += y * line_len + x; + __raw_writel(color, p); + } +} + +static void fill_fb(struct fb_info *fbi) +{ + struct fb_var_screeninfo *var = &fbi->var; + const short w = var->xres_virtual; + const short h = var->yres_virtual; + void __iomem *addr = fbi->screen_base; + int y, x; + + if (!addr) + return; + + DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length); + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + if (x < 20 && y < 20) + draw_pixel(fbi, x, y, 0xffffff); + else if (x < 20 && (y > 20 && y < h - 20)) + draw_pixel(fbi, x, y, 0xff); + else if (y < 20 && (x > 20 && x < w - 20)) + draw_pixel(fbi, x, y, 0xff00); + else if (x > w - 20 && (y > 20 && y < h - 20)) + draw_pixel(fbi, x, y, 0xff0000); + else if (y > h - 20 && (x > 20 && x < w - 20)) + draw_pixel(fbi, x, y, 0xffff00); + else if (x == 20 || x == w - 20 || + y == 20 || y == h - 20) + draw_pixel(fbi, x, y, 0xffffff); + else if (x == y || w - x == h - y) + draw_pixel(fbi, x, y, 0xff00ff); + else if (w - x == y || x == h - y) + draw_pixel(fbi, x, y, 0x00ffff); + else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) { + int t = x * 3 / w; + unsigned r = 0, g = 0, b = 0; + unsigned c; + if (var->bits_per_pixel == 16) { + if (t == 0) + b = (y % 32) * 256 / 32; + else if (t == 1) + g = (y % 64) * 256 / 64; + else if (t == 2) + r = (y % 32) * 256 / 32; + } else { + if (t == 0) + b = (y % 256); + else if (t == 1) + g = (y % 256); + else if (t == 2) + r = (y % 256); + } + c = (r << 16) | (g << 8) | (b << 0); + draw_pixel(fbi, x, y, c); + } else { + draw_pixel(fbi, x, y, 0); + } + } + } +} +#endif + +static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot) +{ + struct vrfb *vrfb = &ofbi->region.vrfb; + unsigned offset; + + switch (rot) { + case FB_ROTATE_UR: + offset = 0; + break; + case FB_ROTATE_CW: + offset = vrfb->yoffset; + break; + case FB_ROTATE_UD: + offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset; + break; + case FB_ROTATE_CCW: + offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN; + break; + default: + BUG(); + } + + offset *= vrfb->bytespp; + + return offset; +} + +static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi, int rot) +{ + if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { + return ofbi->region.vrfb.paddr[rot] + + omapfb_get_vrfb_offset(ofbi, rot); + } else { + return ofbi->region.paddr; + } +} + +static u32 omapfb_get_region_paddr(struct omapfb_info *ofbi) +{ + if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) + return ofbi->region.vrfb.paddr[0]; + else + return ofbi->region.paddr; +} + +static void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi) +{ + if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) + return ofbi->region.vrfb.vaddr[0]; + else + return ofbi->region.vaddr; +} + +static struct omapfb_colormode omapfb_colormodes[] = { + { + .dssmode = OMAP_DSS_COLOR_UYVY, + .bits_per_pixel = 16, + .nonstd = OMAPFB_COLOR_YUV422, + }, { + .dssmode = OMAP_DSS_COLOR_YUV2, + .bits_per_pixel = 16, + .nonstd = OMAPFB_COLOR_YUY422, + }, { + .dssmode = OMAP_DSS_COLOR_ARGB16, + .bits_per_pixel = 16, + .red = { .length = 4, .offset = 8, .msb_right = 0 }, + .green = { .length = 4, .offset = 4, .msb_right = 0 }, + .blue = { .length = 4, .offset = 0, .msb_right = 0 }, + .transp = { .length = 4, .offset = 12, .msb_right = 0 }, + }, { + .dssmode = OMAP_DSS_COLOR_RGB16, + .bits_per_pixel = 16, + .red = { .length = 5, .offset = 11, .msb_right = 0 }, + .green = { .length = 6, .offset = 5, .msb_right = 0 }, + .blue = { .length = 5, .offset = 0, .msb_right = 0 }, + .transp = { .length = 0, .offset = 0, .msb_right = 0 }, + }, { + .dssmode = OMAP_DSS_COLOR_RGB24P, + .bits_per_pixel = 24, + .red = { .length = 8, .offset = 16, .msb_right = 0 }, + .green = { .length = 8, .offset = 8, .msb_right = 0 }, + .blue = { .length = 8, .offset = 0, .msb_right = 0 }, + .transp = { .length = 0, .offset = 0, .msb_right = 0 }, + }, { + .dssmode = OMAP_DSS_COLOR_RGB24U, + .bits_per_pixel = 32, + .red = { .length = 8, .offset = 16, .msb_right = 0 }, + .green = { .length = 8, .offset = 8, .msb_right = 0 }, + .blue = { .length = 8, .offset = 0, .msb_right = 0 }, + .transp = { .length = 0, .offset = 0, .msb_right = 0 }, + }, { + .dssmode = OMAP_DSS_COLOR_ARGB32, + .bits_per_pixel = 32, + .red = { .length = 8, .offset = 16, .msb_right = 0 }, + .green = { .length = 8, .offset = 8, .msb_right = 0 }, + .blue = { .length = 8, .offset = 0, .msb_right = 0 }, + .transp = { .length = 8, .offset = 24, .msb_right = 0 }, + }, { + .dssmode = OMAP_DSS_COLOR_RGBA32, + .bits_per_pixel = 32, + .red = { .length = 8, .offset = 24, .msb_right = 0 }, + .green = { .length = 8, .offset = 16, .msb_right = 0 }, + .blue = { .length = 8, .offset = 8, .msb_right = 0 }, + .transp = { .length = 8, .offset = 0, .msb_right = 0 }, + }, { + .dssmode = OMAP_DSS_COLOR_RGBX32, + .bits_per_pixel = 32, + .red = { .length = 8, .offset = 24, .msb_right = 0 }, + .green = { .length = 8, .offset = 16, .msb_right = 0 }, + .blue = { .length = 8, .offset = 8, .msb_right = 0 }, + .transp = { .length = 0, .offset = 0, .msb_right = 0 }, + }, +}; + +static bool cmp_var_to_colormode(struct fb_var_screeninfo *var, + struct omapfb_colormode *color) +{ + bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2) + { + return f1->length == f2->length && + f1->offset == f2->offset && + f1->msb_right == f2->msb_right; + } + + if (var->bits_per_pixel == 0 || + var->red.length == 0 || + var->blue.length == 0 || + var->green.length == 0) + return 0; + + return var->bits_per_pixel == color->bits_per_pixel && + cmp_component(&var->red, &color->red) && + cmp_component(&var->green, &color->green) && + cmp_component(&var->blue, &color->blue) && + cmp_component(&var->transp, &color->transp); +} + +static void assign_colormode_to_var(struct fb_var_screeninfo *var, + struct omapfb_colormode *color) +{ + var->bits_per_pixel = color->bits_per_pixel; + var->nonstd = color->nonstd; + var->red = color->red; + var->green = color->green; + var->blue = color->blue; + var->transp = color->transp; +} + +static int fb_mode_to_dss_mode(struct fb_var_screeninfo *var, + enum omap_color_mode *mode) +{ + enum omap_color_mode dssmode; + int i; + + /* first match with nonstd field */ + if (var->nonstd) { + for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { + struct omapfb_colormode *m = &omapfb_colormodes[i]; + if (var->nonstd == m->nonstd) { + assign_colormode_to_var(var, m); + *mode = m->dssmode; + return 0; + } + } + + return -EINVAL; + } + + /* then try exact match of bpp and colors */ + for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { + struct omapfb_colormode *m = &omapfb_colormodes[i]; + if (cmp_var_to_colormode(var, m)) { + assign_colormode_to_var(var, m); + *mode = m->dssmode; + return 0; + } + } + + /* match with bpp if user has not filled color fields + * properly */ + switch (var->bits_per_pixel) { + case 1: + dssmode = OMAP_DSS_COLOR_CLUT1; + break; + case 2: + dssmode = OMAP_DSS_COLOR_CLUT2; + break; + case 4: + dssmode = OMAP_DSS_COLOR_CLUT4; + break; + case 8: + dssmode = OMAP_DSS_COLOR_CLUT8; + break; + case 12: + dssmode = OMAP_DSS_COLOR_RGB12U; + break; + case 16: + dssmode = OMAP_DSS_COLOR_RGB16; + break; + case 24: + dssmode = OMAP_DSS_COLOR_RGB24P; + break; + case 32: + dssmode = OMAP_DSS_COLOR_RGB24U; + break; + default: + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { + struct omapfb_colormode *m = &omapfb_colormodes[i]; + if (dssmode == m->dssmode) { + assign_colormode_to_var(var, m); + *mode = m->dssmode; + return 0; + } + } + + return -EINVAL; +} + +static int check_fb_res_bounds(struct fb_var_screeninfo *var) +{ + int xres_min = OMAPFB_PLANE_XRES_MIN; + int xres_max = 2048; + int yres_min = OMAPFB_PLANE_YRES_MIN; + int yres_max = 2048; + + /* XXX: some applications seem to set virtual res to 0. */ + if (var->xres_virtual == 0) + var->xres_virtual = var->xres; + + if (var->yres_virtual == 0) + var->yres_virtual = var->yres; + + if (var->xres_virtual < xres_min || var->yres_virtual < yres_min) + return -EINVAL; + + if (var->xres < xres_min) + var->xres = xres_min; + if (var->yres < yres_min) + var->yres = yres_min; + if (var->xres > xres_max) + var->xres = xres_max; + if (var->yres > yres_max) + var->yres = yres_max; + + if (var->xres > var->xres_virtual) + var->xres = var->xres_virtual; + if (var->yres > var->yres_virtual) + var->yres = var->yres_virtual; + + return 0; +} + +static void shrink_height(unsigned long max_frame_size, + struct fb_var_screeninfo *var) +{ + DBG("can't fit FB into memory, reducing y\n"); + var->yres_virtual = max_frame_size / + (var->xres_virtual * var->bits_per_pixel >> 3); + + if (var->yres_virtual < OMAPFB_PLANE_YRES_MIN) + var->yres_virtual = OMAPFB_PLANE_YRES_MIN; + + if (var->yres > var->yres_virtual) + var->yres = var->yres_virtual; +} + +static void shrink_width(unsigned long max_frame_size, + struct fb_var_screeninfo *var) +{ + DBG("can't fit FB into memory, reducing x\n"); + var->xres_virtual = max_frame_size / var->yres_virtual / + (var->bits_per_pixel >> 3); + + if (var->xres_virtual < OMAPFB_PLANE_XRES_MIN) + var->xres_virtual = OMAPFB_PLANE_XRES_MIN; + + if (var->xres > var->xres_virtual) + var->xres = var->xres_virtual; +} + +static int check_vrfb_fb_size(unsigned long region_size, + const struct fb_var_screeninfo *var) +{ + unsigned long min_phys_size = omap_vrfb_min_phys_size(var->xres_virtual, + var->yres_virtual, var->bits_per_pixel >> 3); + + return min_phys_size > region_size ? -EINVAL : 0; +} + +static int check_fb_size(const struct omapfb_info *ofbi, + struct fb_var_screeninfo *var) +{ + unsigned long max_frame_size = ofbi->region.size; + int bytespp = var->bits_per_pixel >> 3; + unsigned long line_size = var->xres_virtual * bytespp; + + if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { + /* One needs to check for both VRFB and OMAPFB limitations. */ + if (check_vrfb_fb_size(max_frame_size, var)) + shrink_height(omap_vrfb_max_height( + max_frame_size, var->xres_virtual, bytespp) * + line_size, var); + + if (check_vrfb_fb_size(max_frame_size, var)) { + DBG("cannot fit FB to memory\n"); + return -EINVAL; + } + + return 0; + } + + DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size); + + if (line_size * var->yres_virtual > max_frame_size) + shrink_height(max_frame_size, var); + + if (line_size * var->yres_virtual > max_frame_size) { + shrink_width(max_frame_size, var); + line_size = var->xres_virtual * bytespp; + } + + if (line_size * var->yres_virtual > max_frame_size) { + DBG("cannot fit FB to memory\n"); + return -EINVAL; + } + + return 0; +} + +/* + * Consider if VRFB assisted rotation is in use and if the virtual space for + * the zero degree view needs to be mapped. The need for mapping also acts as + * the trigger for setting up the hardware on the context in question. This + * ensures that one does not attempt to access the virtual view before the + * hardware is serving the address translations. + */ +static int setup_vrfb_rotation(struct fb_info *fbi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_mem_region *rg = &ofbi->region; + struct vrfb *vrfb = &rg->vrfb; + struct fb_var_screeninfo *var = &fbi->var; + struct fb_fix_screeninfo *fix = &fbi->fix; + unsigned bytespp; + bool yuv_mode; + enum omap_color_mode mode; + int r; + bool reconf; + + if (!rg->size || ofbi->rotation_type != OMAP_DSS_ROT_VRFB) + return 0; + + DBG("setup_vrfb_rotation\n"); + + r = fb_mode_to_dss_mode(var, &mode); + if (r) + return r; + + bytespp = var->bits_per_pixel >> 3; + + yuv_mode = mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY; + + /* We need to reconfigure VRFB if the resolution changes, if yuv mode + * is enabled/disabled, or if bytes per pixel changes */ + + /* XXX we shouldn't allow this when framebuffer is mmapped */ + + reconf = false; + + if (yuv_mode != vrfb->yuv_mode) + reconf = true; + else if (bytespp != vrfb->bytespp) + reconf = true; + else if (vrfb->xres != var->xres_virtual || + vrfb->yres != var->yres_virtual) + reconf = true; + + if (vrfb->vaddr[0] && reconf) { + fbi->screen_base = NULL; + fix->smem_start = 0; + fix->smem_len = 0; + iounmap(vrfb->vaddr[0]); + vrfb->vaddr[0] = NULL; + DBG("setup_vrfb_rotation: reset fb\n"); + } + + if (vrfb->vaddr[0]) + return 0; + + omap_vrfb_setup(&rg->vrfb, rg->paddr, + var->xres_virtual, + var->yres_virtual, + bytespp, yuv_mode); + + /* Now one can ioremap the 0 angle view */ + r = omap_vrfb_map_angle(vrfb, var->yres_virtual, 0); + if (r) + return r; + + /* used by open/write in fbmem.c */ + fbi->screen_base = ofbi->region.vrfb.vaddr[0]; + + fix->smem_start = ofbi->region.vrfb.paddr[0]; + + switch (var->nonstd) { + case OMAPFB_COLOR_YUV422: + case OMAPFB_COLOR_YUY422: + fix->line_length = + (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2; + break; + default: + fix->line_length = + (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3; + break; + } + + fix->smem_len = var->yres_virtual * fix->line_length; + + return 0; +} + +int dss_mode_to_fb_mode(enum omap_color_mode dssmode, + struct fb_var_screeninfo *var) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { + struct omapfb_colormode *mode = &omapfb_colormodes[i]; + if (dssmode == mode->dssmode) { + assign_colormode_to_var(var, mode); + return 0; + } + } + return -ENOENT; +} + +void set_fb_fix(struct fb_info *fbi) +{ + struct fb_fix_screeninfo *fix = &fbi->fix; + struct fb_var_screeninfo *var = &fbi->var; + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_mem_region *rg = &ofbi->region; + + DBG("set_fb_fix\n"); + + /* used by open/write in fbmem.c */ + fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi); + + /* used by mmap in fbmem.c */ + if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { + switch (var->nonstd) { + case OMAPFB_COLOR_YUV422: + case OMAPFB_COLOR_YUY422: + fix->line_length = + (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2; + break; + default: + fix->line_length = + (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3; + break; + } + + fix->smem_len = var->yres_virtual * fix->line_length; + } else { + fix->line_length = + (var->xres_virtual * var->bits_per_pixel) >> 3; + fix->smem_len = rg->size; + } + + fix->smem_start = omapfb_get_region_paddr(ofbi); + + fix->type = FB_TYPE_PACKED_PIXELS; + + if (var->nonstd) + fix->visual = FB_VISUAL_PSEUDOCOLOR; + else { + switch (var->bits_per_pixel) { + case 32: + case 24: + case 16: + case 12: + fix->visual = FB_VISUAL_TRUECOLOR; + /* 12bpp is stored in 16 bits */ + break; + case 1: + case 2: + case 4: + case 8: + fix->visual = FB_VISUAL_PSEUDOCOLOR; + break; + } + } + + fix->accel = FB_ACCEL_NONE; + + fix->xpanstep = 1; + fix->ypanstep = 1; +} + +/* check new var and possibly modify it to be ok */ +int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omap_dss_device *display = fb2display(fbi); + enum omap_color_mode mode = 0; + int i; + int r; + + DBG("check_fb_var %d\n", ofbi->id); + + if (ofbi->region.size == 0) + return 0; + + r = fb_mode_to_dss_mode(var, &mode); + if (r) { + DBG("cannot convert var to omap dss mode\n"); + return r; + } + + for (i = 0; i < ofbi->num_overlays; ++i) { + if ((ofbi->overlays[i]->supported_modes & mode) == 0) { + DBG("invalid mode\n"); + return -EINVAL; + } + } + + if (var->rotate < 0 || var->rotate > 3) + return -EINVAL; + + if (check_fb_res_bounds(var)) + return -EINVAL; + + if (check_fb_size(ofbi, var)) + return -EINVAL; + + if (var->xres + var->xoffset > var->xres_virtual) + var->xoffset = var->xres_virtual - var->xres; + if (var->yres + var->yoffset > var->yres_virtual) + var->yoffset = var->yres_virtual - var->yres; + + DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n", + var->xres, var->yres, + var->xres_virtual, var->yres_virtual); + + var->height = -1; + var->width = -1; + var->grayscale = 0; + + if (display && display->get_timings) { + struct omap_video_timings timings; + display->get_timings(display, &timings); + + /* pixclock in ps, the rest in pixclock */ + var->pixclock = timings.pixel_clock != 0 ? + KHZ2PICOS(timings.pixel_clock) : + 0; + var->left_margin = timings.hfp; + var->right_margin = timings.hbp; + var->upper_margin = timings.vfp; + var->lower_margin = timings.vbp; + var->hsync_len = timings.hsw; + var->vsync_len = timings.vsw; + } else { + var->pixclock = 0; + var->left_margin = 0; + var->right_margin = 0; + var->upper_margin = 0; + var->lower_margin = 0; + var->hsync_len = 0; + var->vsync_len = 0; + } + + /* TODO: get these from panel->config */ + var->vmode = FB_VMODE_NONINTERLACED; + var->sync = 0; + + return 0; +} + +/* + * --------------------------------------------------------------------------- + * fbdev framework callbacks + * --------------------------------------------------------------------------- + */ +static int omapfb_open(struct fb_info *fbi, int user) +{ + return 0; +} + +static int omapfb_release(struct fb_info *fbi, int user) +{ +#if 0 + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omap_dss_device *display = fb2display(fbi); + + DBG("Closing fb with plane index %d\n", ofbi->id); + + omapfb_lock(fbdev); + + if (display && display->get_update_mode && display->update) { + /* XXX this update should be removed, I think. But it's + * good for debugging */ + if (display->get_update_mode(display) == + OMAP_DSS_UPDATE_MANUAL) { + u16 w, h; + + if (display->sync) + display->sync(display); + + display->get_resolution(display, &w, &h); + display->update(display, 0, 0, w, h); + } + } + + if (display && display->sync) + display->sync(display); + + omapfb_unlock(fbdev); +#endif + return 0; +} + +static unsigned calc_rotation_offset_dma(struct fb_var_screeninfo *var, + struct fb_fix_screeninfo *fix, int rotation) +{ + unsigned offset; + + offset = var->yoffset * fix->line_length + + var->xoffset * (var->bits_per_pixel >> 3); + + return offset; +} + +static unsigned calc_rotation_offset_vrfb(struct fb_var_screeninfo *var, + struct fb_fix_screeninfo *fix, int rotation) +{ + unsigned offset; + + if (rotation == FB_ROTATE_UD) + offset = (var->yres_virtual - var->yres) * + fix->line_length; + else if (rotation == FB_ROTATE_CW) + offset = (var->yres_virtual - var->yres) * + (var->bits_per_pixel >> 3); + else + offset = 0; + + if (rotation == FB_ROTATE_UR) + offset += var->yoffset * fix->line_length + + var->xoffset * (var->bits_per_pixel >> 3); + else if (rotation == FB_ROTATE_UD) + offset -= var->yoffset * fix->line_length + + var->xoffset * (var->bits_per_pixel >> 3); + else if (rotation == FB_ROTATE_CW) + offset -= var->xoffset * fix->line_length + + var->yoffset * (var->bits_per_pixel >> 3); + else if (rotation == FB_ROTATE_CCW) + offset += var->xoffset * fix->line_length + + var->yoffset * (var->bits_per_pixel >> 3); + + return offset; +} + + +/* setup overlay according to the fb */ +static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, + u16 posx, u16 posy, u16 outw, u16 outh) +{ + int r = 0; + struct omapfb_info *ofbi = FB2OFB(fbi); + struct fb_var_screeninfo *var = &fbi->var; + struct fb_fix_screeninfo *fix = &fbi->fix; + enum omap_color_mode mode = 0; + int offset; + u32 data_start_p; + void __iomem *data_start_v; + struct omap_overlay_info info; + int xres, yres; + int screen_width; + int mirror; + int rotation = var->rotate; + int i; + + for (i = 0; i < ofbi->num_overlays; i++) { + if (ovl != ofbi->overlays[i]) + continue; + + rotation = (rotation + ofbi->rotation[i]) % 4; + break; + } + + DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id, + posx, posy, outw, outh); + + if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) { + xres = var->yres; + yres = var->xres; + } else { + xres = var->xres; + yres = var->yres; + } + + + if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { + data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); + data_start_v = NULL; + } else { + data_start_p = omapfb_get_region_paddr(ofbi); + data_start_v = omapfb_get_region_vaddr(ofbi); + } + + if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) + offset = calc_rotation_offset_vrfb(var, fix, rotation); + else + offset = calc_rotation_offset_dma(var, fix, rotation); + + data_start_p += offset; + data_start_v += offset; + + if (offset) + DBG("offset %d, %d = %d\n", + var->xoffset, var->yoffset, offset); + + DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v); + + r = fb_mode_to_dss_mode(var, &mode); + if (r) { + DBG("fb_mode_to_dss_mode failed"); + goto err; + } + + switch (var->nonstd) { + case OMAPFB_COLOR_YUV422: + case OMAPFB_COLOR_YUY422: + if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { + screen_width = fix->line_length + / (var->bits_per_pixel >> 2); + break; + } + default: + screen_width = fix->line_length / (var->bits_per_pixel >> 3); + break; + } + + ovl->get_overlay_info(ovl, &info); + + if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) + mirror = 0; + else + mirror = ofbi->mirror; + + info.paddr = data_start_p; + info.vaddr = data_start_v; + info.screen_width = screen_width; + info.width = xres; + info.height = yres; + info.color_mode = mode; + info.rotation_type = ofbi->rotation_type; + info.rotation = rotation; + info.mirror = mirror; + + info.pos_x = posx; + info.pos_y = posy; + info.out_width = outw; + info.out_height = outh; + + r = ovl->set_overlay_info(ovl, &info); + if (r) { + DBG("ovl->setup_overlay_info failed\n"); + goto err; + } + + return 0; + +err: + DBG("setup_overlay failed\n"); + return r; +} + +/* apply var to the overlay */ +int omapfb_apply_changes(struct fb_info *fbi, int init) +{ + int r = 0; + struct omapfb_info *ofbi = FB2OFB(fbi); + struct fb_var_screeninfo *var = &fbi->var; + struct omap_overlay *ovl; + u16 posx, posy; + u16 outw, outh; + int i; + +#ifdef DEBUG + if (omapfb_test_pattern) + fill_fb(fbi); +#endif + + for (i = 0; i < ofbi->num_overlays; i++) { + ovl = ofbi->overlays[i]; + + DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id); + + if (ofbi->region.size == 0) { + /* the fb is not available. disable the overlay */ + omapfb_overlay_enable(ovl, 0); + if (!init && ovl->manager) + ovl->manager->apply(ovl->manager); + continue; + } + + if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { + int rotation = (var->rotate + ofbi->rotation[i]) % 4; + if (rotation == FB_ROTATE_CW || + rotation == FB_ROTATE_CCW) { + outw = var->yres; + outh = var->xres; + } else { + outw = var->xres; + outh = var->yres; + } + } else { + outw = ovl->info.out_width; + outh = ovl->info.out_height; + } + + if (init) { + posx = 0; + posy = 0; + } else { + posx = ovl->info.pos_x; + posy = ovl->info.pos_y; + } + + r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh); + if (r) + goto err; + + if (!init && ovl->manager) + ovl->manager->apply(ovl->manager); + } + return 0; +err: + DBG("apply_changes failed\n"); + return r; +} + +/* checks var and eventually tweaks it to something supported, + * DO NOT MODIFY PAR */ +static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) +{ + int r; + + DBG("check_var(%d)\n", FB2OFB(fbi)->id); + + r = check_fb_var(fbi, var); + + return r; +} + +/* set the video mode according to info->var */ +static int omapfb_set_par(struct fb_info *fbi) +{ + int r; + + DBG("set_par(%d)\n", FB2OFB(fbi)->id); + + set_fb_fix(fbi); + + r = setup_vrfb_rotation(fbi); + if (r) + return r; + + r = omapfb_apply_changes(fbi, 0); + + return r; +} + +static int omapfb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *fbi) +{ + struct fb_var_screeninfo new_var; + int r; + + DBG("pan_display(%d)\n", FB2OFB(fbi)->id); + + if (var->xoffset == fbi->var.xoffset && + var->yoffset == fbi->var.yoffset) + return 0; + + new_var = fbi->var; + new_var.xoffset = var->xoffset; + new_var.yoffset = var->yoffset; + + fbi->var = new_var; + + r = omapfb_apply_changes(fbi, 0); + + return r; +} + +static void mmap_user_open(struct vm_area_struct *vma) +{ + struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; + + atomic_inc(&ofbi->map_count); +} + +static void mmap_user_close(struct vm_area_struct *vma) +{ + struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; + + atomic_dec(&ofbi->map_count); +} + +static struct vm_operations_struct mmap_user_ops = { + .open = mmap_user_open, + .close = mmap_user_close, +}; + +static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct fb_fix_screeninfo *fix = &fbi->fix; + unsigned long off; + unsigned long start; + u32 len; + + if (vma->vm_end - vma->vm_start == 0) + return 0; + if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) + return -EINVAL; + off = vma->vm_pgoff << PAGE_SHIFT; + + start = omapfb_get_region_paddr(ofbi); + len = fix->smem_len; + if (off >= len) + return -EINVAL; + if ((vma->vm_end - vma->vm_start + off) > len) + return -EINVAL; + + off += start; + + DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off); + + vma->vm_pgoff = off >> PAGE_SHIFT; + vma->vm_flags |= VM_IO | VM_RESERVED; + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + vma->vm_ops = &mmap_user_ops; + vma->vm_private_data = ofbi; + if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) + return -EAGAIN; + /* vm_ops.open won't be called for mmap itself. */ + atomic_inc(&ofbi->map_count); + return 0; +} + +/* Store a single color palette entry into a pseudo palette or the hardware + * palette if one is available. For now we support only 16bpp and thus store + * the entry only to the pseudo palette. + */ +static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green, + u_int blue, u_int transp, int update_hw_pal) +{ + /*struct omapfb_info *ofbi = FB2OFB(fbi);*/ + /*struct omapfb2_device *fbdev = ofbi->fbdev;*/ + struct fb_var_screeninfo *var = &fbi->var; + int r = 0; + + enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */ + + /*switch (plane->color_mode) {*/ + switch (mode) { + case OMAPFB_COLOR_YUV422: + case OMAPFB_COLOR_YUV420: + case OMAPFB_COLOR_YUY422: + r = -EINVAL; + break; + case OMAPFB_COLOR_CLUT_8BPP: + case OMAPFB_COLOR_CLUT_4BPP: + case OMAPFB_COLOR_CLUT_2BPP: + case OMAPFB_COLOR_CLUT_1BPP: + /* + if (fbdev->ctrl->setcolreg) + r = fbdev->ctrl->setcolreg(regno, red, green, blue, + transp, update_hw_pal); + */ + /* Fallthrough */ + r = -EINVAL; + break; + case OMAPFB_COLOR_RGB565: + case OMAPFB_COLOR_RGB444: + case OMAPFB_COLOR_RGB24P: + case OMAPFB_COLOR_RGB24U: + if (r != 0) + break; + + if (regno < 0) { + r = -EINVAL; + break; + } + + if (regno < 16) { + u16 pal; + pal = ((red >> (16 - var->red.length)) << + var->red.offset) | + ((green >> (16 - var->green.length)) << + var->green.offset) | + (blue >> (16 - var->blue.length)); + ((u32 *)(fbi->pseudo_palette))[regno] = pal; + } + break; + default: + BUG(); + } + return r; +} + +static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + DBG("setcolreg\n"); + + return _setcolreg(info, regno, red, green, blue, transp, 1); +} + +static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info) +{ + int count, index, r; + u16 *red, *green, *blue, *transp; + u16 trans = 0xffff; + + DBG("setcmap\n"); + + red = cmap->red; + green = cmap->green; + blue = cmap->blue; + transp = cmap->transp; + index = cmap->start; + + for (count = 0; count < cmap->len; count++) { + if (transp) + trans = *transp++; + r = _setcolreg(info, index++, *red++, *green++, *blue++, trans, + count == cmap->len - 1); + if (r != 0) + return r; + } + + return 0; +} + +static int omapfb_blank(int blank, struct fb_info *fbi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omap_dss_device *display = fb2display(fbi); + int do_update = 0; + int r = 0; + + omapfb_lock(fbdev); + + switch (blank) { + case FB_BLANK_UNBLANK: + if (display->state != OMAP_DSS_DISPLAY_SUSPENDED) + goto exit; + + if (display->resume) + r = display->resume(display); + + if (r == 0 && display->get_update_mode && + display->get_update_mode(display) == + OMAP_DSS_UPDATE_MANUAL) + do_update = 1; + + break; + + case FB_BLANK_NORMAL: + /* FB_BLANK_NORMAL could be implemented. + * Needs DSS additions. */ + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_POWERDOWN: + if (display->state != OMAP_DSS_DISPLAY_ACTIVE) + goto exit; + + if (display->suspend) + r = display->suspend(display); + + break; + + default: + r = -EINVAL; + } + +exit: + omapfb_unlock(fbdev); + + if (r == 0 && do_update && display->update) { + u16 w, h; + display->get_resolution(display, &w, &h); + + r = display->update(display, 0, 0, w, h); + } + + return r; +} + +#if 0 +/* XXX fb_read and fb_write are needed for VRFB */ +ssize_t omapfb_write(struct fb_info *info, const char __user *buf, + size_t count, loff_t *ppos) +{ + DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos); + /* XXX needed for VRFB */ + return count; +} +#endif + +static struct fb_ops omapfb_ops = { + .owner = THIS_MODULE, + .fb_open = omapfb_open, + .fb_release = omapfb_release, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_blank = omapfb_blank, + .fb_ioctl = omapfb_ioctl, + .fb_check_var = omapfb_check_var, + .fb_set_par = omapfb_set_par, + .fb_pan_display = omapfb_pan_display, + .fb_mmap = omapfb_mmap, + .fb_setcolreg = omapfb_setcolreg, + .fb_setcmap = omapfb_setcmap, + /*.fb_write = omapfb_write,*/ +}; + +static void omapfb_free_fbmem(struct fb_info *fbi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omapfb2_mem_region *rg; + + rg = &ofbi->region; + + if (rg->paddr) + if (omap_vram_free(rg->paddr, rg->size)) + dev_err(fbdev->dev, "VRAM FREE failed\n"); + + if (rg->vaddr) + iounmap(rg->vaddr); + + if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { + /* unmap the 0 angle rotation */ + if (rg->vrfb.vaddr[0]) { + iounmap(rg->vrfb.vaddr[0]); + omap_vrfb_release_ctx(&rg->vrfb); + } + } + + rg->vaddr = NULL; + rg->paddr = 0; + rg->alloc = 0; + rg->size = 0; +} + +static void clear_fb_info(struct fb_info *fbi) +{ + memset(&fbi->var, 0, sizeof(fbi->var)); + memset(&fbi->fix, 0, sizeof(fbi->fix)); + strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id)); +} + +static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev) +{ + int i; + + DBG("free all fbmem\n"); + + for (i = 0; i < fbdev->num_fbs; i++) { + struct fb_info *fbi = fbdev->fbs[i]; + omapfb_free_fbmem(fbi); + clear_fb_info(fbi); + } + + return 0; +} + +static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size, + unsigned long paddr) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omapfb2_mem_region *rg; + void __iomem *vaddr; + int r; + + rg = &ofbi->region; + memset(rg, 0, sizeof(*rg)); + + size = PAGE_ALIGN(size); + + if (!paddr) { + DBG("allocating %lu bytes for fb %d\n", size, ofbi->id); + r = omap_vram_alloc(OMAP_VRAM_MEMTYPE_SDRAM, size, &paddr); + } else { + DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr, + ofbi->id); + r = omap_vram_reserve(paddr, size); + } + + if (r) { + dev_err(fbdev->dev, "failed to allocate framebuffer\n"); + return -ENOMEM; + } + + if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) { + vaddr = ioremap_wc(paddr, size); + + if (!vaddr) { + dev_err(fbdev->dev, "failed to ioremap framebuffer\n"); + omap_vram_free(paddr, size); + return -ENOMEM; + } + + DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr); + } else { + r = omap_vrfb_request_ctx(&rg->vrfb); + if (r) { + dev_err(fbdev->dev, "vrfb create ctx failed\n"); + return r; + } + + vaddr = NULL; + } + + rg->paddr = paddr; + rg->vaddr = vaddr; + rg->size = size; + rg->alloc = 1; + + return 0; +} + +/* allocate fbmem using display resolution as reference */ +static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size, + unsigned long paddr) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omap_dss_device *display; + int bytespp; + + display = fb2display(fbi); + + if (!display) + return 0; + + switch (display->get_recommended_bpp(display)) { + case 16: + bytespp = 2; + break; + case 24: + bytespp = 4; + break; + default: + bytespp = 4; + break; + } + + if (!size) { + u16 w, h; + + display->get_resolution(display, &w, &h); + + if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { + size = max(omap_vrfb_min_phys_size(w, h, bytespp), + omap_vrfb_min_phys_size(h, w, bytespp)); + + DBG("adjusting fb mem size for VRFB, %u -> %lu\n", + w * h * bytespp, size); + } else { + size = w * h * bytespp; + } + } + + if (!size) + return 0; + + return omapfb_alloc_fbmem(fbi, size, paddr); +} + +static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format fmt) +{ + enum omap_color_mode mode; + + switch (fmt) { + case OMAPFB_COLOR_RGB565: + mode = OMAP_DSS_COLOR_RGB16; + break; + case OMAPFB_COLOR_YUV422: + mode = OMAP_DSS_COLOR_YUV2; + break; + case OMAPFB_COLOR_CLUT_8BPP: + mode = OMAP_DSS_COLOR_CLUT8; + break; + case OMAPFB_COLOR_CLUT_4BPP: + mode = OMAP_DSS_COLOR_CLUT4; + break; + case OMAPFB_COLOR_CLUT_2BPP: + mode = OMAP_DSS_COLOR_CLUT2; + break; + case OMAPFB_COLOR_CLUT_1BPP: + mode = OMAP_DSS_COLOR_CLUT1; + break; + case OMAPFB_COLOR_RGB444: + mode = OMAP_DSS_COLOR_RGB12U; + break; + case OMAPFB_COLOR_YUY422: + mode = OMAP_DSS_COLOR_UYVY; + break; + case OMAPFB_COLOR_ARGB16: + mode = OMAP_DSS_COLOR_ARGB16; + break; + case OMAPFB_COLOR_RGB24U: + mode = OMAP_DSS_COLOR_RGB24U; + break; + case OMAPFB_COLOR_RGB24P: + mode = OMAP_DSS_COLOR_RGB24P; + break; + case OMAPFB_COLOR_ARGB32: + mode = OMAP_DSS_COLOR_ARGB32; + break; + case OMAPFB_COLOR_RGBA32: + mode = OMAP_DSS_COLOR_RGBA32; + break; + case OMAPFB_COLOR_RGBX32: + mode = OMAP_DSS_COLOR_RGBX32; + break; + default: + mode = -EINVAL; + } + + return mode; +} + +static int omapfb_parse_vram_param(const char *param, int max_entries, + unsigned long *sizes, unsigned long *paddrs) +{ + int fbnum; + unsigned long size; + unsigned long paddr = 0; + char *p, *start; + + start = (char *)param; + + while (1) { + p = start; + + fbnum = simple_strtoul(p, &p, 10); + + if (p == param) + return -EINVAL; + + if (*p != ':') + return -EINVAL; + + if (fbnum >= max_entries) + return -EINVAL; + + size = memparse(p + 1, &p); + + if (!size) + return -EINVAL; + + paddr = 0; + + if (*p == '@') { + paddr = simple_strtoul(p + 1, &p, 16); + + if (!paddr) + return -EINVAL; + + } + + paddrs[fbnum] = paddr; + sizes[fbnum] = size; + + if (*p == 0) + break; + + if (*p != ',') + return -EINVAL; + + ++p; + + start = p; + } + + return 0; +} + +static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev) +{ + int i, r; + unsigned long vram_sizes[10]; + unsigned long vram_paddrs[10]; + + memset(&vram_sizes, 0, sizeof(vram_sizes)); + memset(&vram_paddrs, 0, sizeof(vram_paddrs)); + + if (def_vram && omapfb_parse_vram_param(def_vram, 10, + vram_sizes, vram_paddrs)) { + dev_err(fbdev->dev, "failed to parse vram parameter\n"); + + memset(&vram_sizes, 0, sizeof(vram_sizes)); + memset(&vram_paddrs, 0, sizeof(vram_paddrs)); + } + + if (fbdev->dev->platform_data) { + struct omapfb_platform_data *opd; + opd = fbdev->dev->platform_data; + for (i = 0; i < opd->mem_desc.region_cnt; ++i) { + if (!vram_sizes[i]) { + unsigned long size; + unsigned long paddr; + + size = opd->mem_desc.region[i].size; + paddr = opd->mem_desc.region[i].paddr; + + vram_sizes[i] = size; + vram_paddrs[i] = paddr; + } + } + } + + for (i = 0; i < fbdev->num_fbs; i++) { + /* allocate memory automatically only for fb0, or if + * excplicitly defined with vram or plat data option */ + if (i == 0 || vram_sizes[i] != 0) { + r = omapfb_alloc_fbmem_display(fbdev->fbs[i], + vram_sizes[i], vram_paddrs[i]); + + if (r) + return r; + } + } + + for (i = 0; i < fbdev->num_fbs; i++) { + struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); + struct omapfb2_mem_region *rg; + rg = &ofbi->region; + + DBG("region%d phys %08x virt %p size=%lu\n", + i, + rg->paddr, + rg->vaddr, + rg->size); + } + + return 0; +} + +int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omap_dss_device *display = fb2display(fbi); + struct omapfb2_mem_region *rg = &ofbi->region; + unsigned long old_size = rg->size; + unsigned long old_paddr = rg->paddr; + int old_type = rg->type; + int r; + + if (type > OMAPFB_MEMTYPE_MAX) + return -EINVAL; + + size = PAGE_ALIGN(size); + + if (old_size == size && old_type == type) + return 0; + + if (display && display->sync) + display->sync(display); + + omapfb_free_fbmem(fbi); + + if (size == 0) { + clear_fb_info(fbi); + return 0; + } + + r = omapfb_alloc_fbmem(fbi, size, 0); + + if (r) { + if (old_size) + omapfb_alloc_fbmem(fbi, old_size, old_paddr); + + if (rg->size == 0) + clear_fb_info(fbi); + + return r; + } + + if (old_size == size) + return 0; + + if (old_size == 0) { + DBG("initializing fb %d\n", ofbi->id); + r = omapfb_fb_init(fbdev, fbi); + if (r) { + DBG("omapfb_fb_init failed\n"); + goto err; + } + r = omapfb_apply_changes(fbi, 1); + if (r) { + DBG("omapfb_apply_changes failed\n"); + goto err; + } + } else { + struct fb_var_screeninfo new_var; + memcpy(&new_var, &fbi->var, sizeof(new_var)); + r = check_fb_var(fbi, &new_var); + if (r) + goto err; + memcpy(&fbi->var, &new_var, sizeof(fbi->var)); + set_fb_fix(fbi); + r = setup_vrfb_rotation(fbi); + if (r) + goto err; + } + + return 0; +err: + omapfb_free_fbmem(fbi); + clear_fb_info(fbi); + return r; +} + +/* initialize fb_info, var, fix to something sane based on the display */ +static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi) +{ + struct fb_var_screeninfo *var = &fbi->var; + struct omap_dss_device *display = fb2display(fbi); + struct omapfb_info *ofbi = FB2OFB(fbi); + int r = 0; + + fbi->fbops = &omapfb_ops; + fbi->flags = FBINFO_FLAG_DEFAULT; + fbi->pseudo_palette = fbdev->pseudo_palette; + + if (ofbi->region.size == 0) { + clear_fb_info(fbi); + return 0; + } + + var->nonstd = 0; + var->bits_per_pixel = 0; + + var->rotate = def_rotate; + + /* + * Check if there is a default color format set in the board file, + * and use this format instead the default deducted from the + * display bpp. + */ + if (fbdev->dev->platform_data) { + struct omapfb_platform_data *opd; + int id = ofbi->id; + + opd = fbdev->dev->platform_data; + if (opd->mem_desc.region[id].format_used) { + enum omap_color_mode mode; + enum omapfb_color_format format; + + format = opd->mem_desc.region[id].format; + mode = fb_format_to_dss_mode(format); + if (mode < 0) { + r = mode; + goto err; + } + r = dss_mode_to_fb_mode(mode, var); + if (r < 0) + goto err; + } + } + + if (display) { + u16 w, h; + int rotation = (var->rotate + ofbi->rotation[0]) % 4; + + display->get_resolution(display, &w, &h); + + if (rotation == FB_ROTATE_CW || + rotation == FB_ROTATE_CCW) { + var->xres = h; + var->yres = w; + } else { + var->xres = w; + var->yres = h; + } + + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; + + if (!var->bits_per_pixel) { + switch (display->get_recommended_bpp(display)) { + case 16: + var->bits_per_pixel = 16; + break; + case 24: + var->bits_per_pixel = 32; + break; + default: + dev_err(fbdev->dev, "illegal display " + "bpp\n"); + return -EINVAL; + } + } + } else { + /* if there's no display, let's just guess some basic values */ + var->xres = 320; + var->yres = 240; + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; + if (!var->bits_per_pixel) + var->bits_per_pixel = 16; + } + + r = check_fb_var(fbi, var); + if (r) + goto err; + + set_fb_fix(fbi); + r = setup_vrfb_rotation(fbi); + if (r) + goto err; + + r = fb_alloc_cmap(&fbi->cmap, 256, 0); + if (r) + dev_err(fbdev->dev, "unable to allocate color map memory\n"); + +err: + return r; +} + +static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi) +{ + fb_dealloc_cmap(&fbi->cmap); +} + + +static void omapfb_free_resources(struct omapfb2_device *fbdev) +{ + int i; + + DBG("free_resources\n"); + + if (fbdev == NULL) + return; + + for (i = 0; i < fbdev->num_fbs; i++) + unregister_framebuffer(fbdev->fbs[i]); + + /* free the reserved fbmem */ + omapfb_free_all_fbmem(fbdev); + + for (i = 0; i < fbdev->num_fbs; i++) { + fbinfo_cleanup(fbdev, fbdev->fbs[i]); + framebuffer_release(fbdev->fbs[i]); + } + + for (i = 0; i < fbdev->num_displays; i++) { + if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED) + fbdev->displays[i]->disable(fbdev->displays[i]); + + omap_dss_put_device(fbdev->displays[i]); + } + + dev_set_drvdata(fbdev->dev, NULL); + kfree(fbdev); +} + +static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) +{ + int r, i; + + fbdev->num_fbs = 0; + + DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS); + + /* allocate fb_infos */ + for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) { + struct fb_info *fbi; + struct omapfb_info *ofbi; + + fbi = framebuffer_alloc(sizeof(struct omapfb_info), + fbdev->dev); + + if (fbi == NULL) { + dev_err(fbdev->dev, + "unable to allocate memory for plane info\n"); + return -ENOMEM; + } + + clear_fb_info(fbi); + + fbdev->fbs[i] = fbi; + + ofbi = FB2OFB(fbi); + ofbi->fbdev = fbdev; + ofbi->id = i; + + /* assign these early, so that fb alloc can use them */ + ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : + OMAP_DSS_ROT_DMA; + ofbi->mirror = def_mirror; + + fbdev->num_fbs++; + } + + DBG("fb_infos allocated\n"); + + /* assign overlays for the fbs */ + for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) { + struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); + + ofbi->overlays[0] = fbdev->overlays[i]; + ofbi->num_overlays = 1; + } + + /* allocate fb memories */ + r = omapfb_allocate_all_fbs(fbdev); + if (r) { + dev_err(fbdev->dev, "failed to allocate fbmem\n"); + return r; + } + + DBG("fbmems allocated\n"); + + /* setup fb_infos */ + for (i = 0; i < fbdev->num_fbs; i++) { + r = omapfb_fb_init(fbdev, fbdev->fbs[i]); + if (r) { + dev_err(fbdev->dev, "failed to setup fb_info\n"); + return r; + } + } + + DBG("fb_infos initialized\n"); + + for (i = 0; i < fbdev->num_fbs; i++) { + r = register_framebuffer(fbdev->fbs[i]); + if (r != 0) { + dev_err(fbdev->dev, + "registering framebuffer %d failed\n", i); + return r; + } + } + + DBG("framebuffers registered\n"); + + for (i = 0; i < fbdev->num_fbs; i++) { + r = omapfb_apply_changes(fbdev->fbs[i], 1); + if (r) { + dev_err(fbdev->dev, "failed to change mode\n"); + return r; + } + } + + DBG("create sysfs for fbs\n"); + r = omapfb_create_sysfs(fbdev); + if (r) { + dev_err(fbdev->dev, "failed to create sysfs entries\n"); + return r; + } + + /* Enable fb0 */ + if (fbdev->num_fbs > 0) { + struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]); + + if (ofbi->num_overlays > 0) { + struct omap_overlay *ovl = ofbi->overlays[0]; + + r = omapfb_overlay_enable(ovl, 1); + + if (r) { + dev_err(fbdev->dev, + "failed to enable overlay\n"); + return r; + } + } + } + + DBG("create_framebuffers done\n"); + + return 0; +} + +static int omapfb_mode_to_timings(const char *mode_str, + struct omap_video_timings *timings, u8 *bpp) +{ + struct fb_info fbi; + struct fb_var_screeninfo var; + struct fb_ops fbops; + int r; + +#ifdef CONFIG_OMAP2_DSS_VENC + if (strcmp(mode_str, "pal") == 0) { + *timings = omap_dss_pal_timings; + *bpp = 0; + return 0; + } else if (strcmp(mode_str, "ntsc") == 0) { + *timings = omap_dss_ntsc_timings; + *bpp = 0; + return 0; + } +#endif + + /* this is quite a hack, but I wanted to use the modedb and for + * that we need fb_info and var, so we create dummy ones */ + + memset(&fbi, 0, sizeof(fbi)); + memset(&var, 0, sizeof(var)); + memset(&fbops, 0, sizeof(fbops)); + fbi.fbops = &fbops; + + r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24); + + if (r != 0) { + timings->pixel_clock = PICOS2KHZ(var.pixclock); + timings->hfp = var.left_margin; + timings->hbp = var.right_margin; + timings->vfp = var.upper_margin; + timings->vbp = var.lower_margin; + timings->hsw = var.hsync_len; + timings->vsw = var.vsync_len; + timings->x_res = var.xres; + timings->y_res = var.yres; + + switch (var.bits_per_pixel) { + case 16: + *bpp = 16; + break; + case 24: + case 32: + default: + *bpp = 24; + break; + } + + return 0; + } else { + return -EINVAL; + } +} + +static int omapfb_set_def_mode(struct omap_dss_device *display, char *mode_str) +{ + int r; + u8 bpp; + struct omap_video_timings timings; + + r = omapfb_mode_to_timings(mode_str, &timings, &bpp); + if (r) + return r; + + display->panel.recommended_bpp = bpp; + + if (!display->check_timings || !display->set_timings) + return -EINVAL; + + r = display->check_timings(display, &timings); + if (r) + return r; + + display->set_timings(display, &timings); + + return 0; +} + +static int omapfb_parse_def_modes(struct omapfb2_device *fbdev) +{ + char *str, *options, *this_opt; + int r = 0; + + str = kmalloc(strlen(def_mode) + 1, GFP_KERNEL); + strcpy(str, def_mode); + options = str; + + while (!r && (this_opt = strsep(&options, ",")) != NULL) { + char *p, *display_str, *mode_str; + struct omap_dss_device *display; + int i; + + p = strchr(this_opt, ':'); + if (!p) { + r = -EINVAL; + break; + } + + *p = 0; + display_str = this_opt; + mode_str = p + 1; + + display = NULL; + for (i = 0; i < fbdev->num_displays; ++i) { + if (strcmp(fbdev->displays[i]->name, + display_str) == 0) { + display = fbdev->displays[i]; + break; + } + } + + if (!display) { + r = -EINVAL; + break; + } + + r = omapfb_set_def_mode(display, mode_str); + if (r) + break; + } + + kfree(str); + + return r; +} + +static int omapfb_probe(struct platform_device *pdev) +{ + struct omapfb2_device *fbdev = NULL; + int r = 0; + int i; + struct omap_overlay *ovl; + struct omap_dss_device *def_display; + struct omap_dss_device *dssdev; + + DBG("omapfb_probe\n"); + + if (pdev->num_resources != 0) { + dev_err(&pdev->dev, "probed for an unknown device\n"); + r = -ENODEV; + goto err0; + } + + fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL); + if (fbdev == NULL) { + r = -ENOMEM; + goto err0; + } + + mutex_init(&fbdev->mtx); + + fbdev->dev = &pdev->dev; + platform_set_drvdata(pdev, fbdev); + + fbdev->num_displays = 0; + dssdev = NULL; + for_each_dss_dev(dssdev) { + omap_dss_get_device(dssdev); + fbdev->displays[fbdev->num_displays++] = dssdev; + } + + if (fbdev->num_displays == 0) { + dev_err(&pdev->dev, "no displays\n"); + r = -EINVAL; + goto cleanup; + } + + fbdev->num_overlays = omap_dss_get_num_overlays(); + for (i = 0; i < fbdev->num_overlays; i++) + fbdev->overlays[i] = omap_dss_get_overlay(i); + + fbdev->num_managers = omap_dss_get_num_overlay_managers(); + for (i = 0; i < fbdev->num_managers; i++) + fbdev->managers[i] = omap_dss_get_overlay_manager(i); + + if (def_mode && strlen(def_mode) > 0) { + if (omapfb_parse_def_modes(fbdev)) + dev_warn(&pdev->dev, "cannot parse default modes\n"); + } + + r = omapfb_create_framebuffers(fbdev); + if (r) + goto cleanup; + + for (i = 0; i < fbdev->num_managers; i++) { + struct omap_overlay_manager *mgr; + mgr = fbdev->managers[i]; + r = mgr->apply(mgr); + if (r) + dev_warn(fbdev->dev, "failed to apply dispc config\n"); + } + + DBG("mgr->apply'ed\n"); + + /* gfx overlay should be the default one. find a display + * connected to that, and use it as default display */ + ovl = omap_dss_get_overlay(0); + if (ovl->manager && ovl->manager->device) { + def_display = ovl->manager->device; + } else { + dev_warn(&pdev->dev, "cannot find default display\n"); + def_display = NULL; + } + + if (def_display) { +#ifndef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE + u16 w, h; +#endif + r = def_display->enable(def_display); + if (r) + dev_warn(fbdev->dev, "Failed to enable display '%s'\n", + def_display->name); + + /* set the update mode */ + if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { +#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE + if (def_display->enable_te) + def_display->enable_te(def_display, 1); + if (def_display->set_update_mode) + def_display->set_update_mode(def_display, + OMAP_DSS_UPDATE_AUTO); +#else /* MANUAL_UPDATE */ + if (def_display->enable_te) + def_display->enable_te(def_display, 0); + if (def_display->set_update_mode) + def_display->set_update_mode(def_display, + OMAP_DSS_UPDATE_MANUAL); + + def_display->get_resolution(def_display, &w, &h); + def_display->update(def_display, 0, 0, w, h); +#endif + } else { + if (def_display->set_update_mode) + def_display->set_update_mode(def_display, + OMAP_DSS_UPDATE_AUTO); + } + } + + return 0; + +cleanup: + omapfb_free_resources(fbdev); +err0: + dev_err(&pdev->dev, "failed to setup omapfb\n"); + return r; +} + +static int omapfb_remove(struct platform_device *pdev) +{ + struct omapfb2_device *fbdev = platform_get_drvdata(pdev); + + /* FIXME: wait till completion of pending events */ + + omapfb_remove_sysfs(fbdev); + + omapfb_free_resources(fbdev); + + return 0; +} + +static struct platform_driver omapfb_driver = { + .probe = omapfb_probe, + .remove = omapfb_remove, + .driver = { + .name = "omapfb", + .owner = THIS_MODULE, + }, +}; + +static int __init omapfb_init(void) +{ + DBG("omapfb_init\n"); + + if (platform_driver_register(&omapfb_driver)) { + printk(KERN_ERR "failed to register omapfb driver\n"); + return -ENODEV; + } + + return 0; +} + +static void __exit omapfb_exit(void) +{ + DBG("omapfb_exit\n"); + platform_driver_unregister(&omapfb_driver); +} + +module_param_named(mode, def_mode, charp, 0); +module_param_named(vram, def_vram, charp, 0); +module_param_named(rotate, def_rotate, int, 0); +module_param_named(vrfb, def_vrfb, bool, 0); +module_param_named(mirror, def_mirror, bool, 0); + +/* late_initcall to let panel/ctrl drivers loaded first. + * I guess better option would be a more dynamic approach, + * so that omapfb reacts to new panels when they are loaded */ +late_initcall(omapfb_init); +/*module_init(omapfb_init);*/ +module_exit(omapfb_exit); + +MODULE_AUTHOR("Tomi Valkeinen "); +MODULE_DESCRIPTION("OMAP2/3 Framebuffer"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c new file mode 100644 index 0000000000000000000000000000000000000000..62bb88f5c192ad3160d57c7c699fb5421010b55a --- /dev/null +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c @@ -0,0 +1,507 @@ +/* + * linux/drivers/video/omap2/omapfb-sysfs.c + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "omapfb.h" + +static ssize_t show_rotate_type(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct omapfb_info *ofbi = FB2OFB(fbi); + + return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type); +} + +static ssize_t store_rotate_type(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct omapfb_info *ofbi = FB2OFB(fbi); + enum omap_dss_rotation_type rot_type; + int r; + + rot_type = simple_strtoul(buf, NULL, 0); + + if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB) + return -EINVAL; + + lock_fb_info(fbi); + + r = 0; + if (rot_type == ofbi->rotation_type) + goto out; + + if (ofbi->region.size) { + r = -EBUSY; + goto out; + } + + ofbi->rotation_type = rot_type; + + /* + * Since the VRAM for this FB is not allocated at the moment we don't + * need to do any further parameter checking at this point. + */ +out: + unlock_fb_info(fbi); + + return r ? r : count; +} + + +static ssize_t show_mirror(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct omapfb_info *ofbi = FB2OFB(fbi); + + return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror); +} + +static ssize_t store_mirror(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct omapfb_info *ofbi = FB2OFB(fbi); + bool mirror; + int r; + struct fb_var_screeninfo new_var; + + mirror = simple_strtoul(buf, NULL, 0); + + if (mirror != 0 && mirror != 1) + return -EINVAL; + + lock_fb_info(fbi); + + ofbi->mirror = mirror; + + memcpy(&new_var, &fbi->var, sizeof(new_var)); + r = check_fb_var(fbi, &new_var); + if (r) + goto out; + memcpy(&fbi->var, &new_var, sizeof(fbi->var)); + + set_fb_fix(fbi); + + r = omapfb_apply_changes(fbi, 0); + if (r) + goto out; + + r = count; +out: + unlock_fb_info(fbi); + + return r; +} + +static ssize_t show_overlays(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + ssize_t l = 0; + int t; + + omapfb_lock(fbdev); + lock_fb_info(fbi); + + for (t = 0; t < ofbi->num_overlays; t++) { + struct omap_overlay *ovl = ofbi->overlays[t]; + int ovlnum; + + for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum) + if (ovl == fbdev->overlays[ovlnum]) + break; + + l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", + t == 0 ? "" : ",", ovlnum); + } + + l += snprintf(buf + l, PAGE_SIZE - l, "\n"); + + unlock_fb_info(fbi); + omapfb_unlock(fbdev); + + return l; +} + +static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev, + struct omap_overlay *ovl) +{ + int i, t; + + for (i = 0; i < fbdev->num_fbs; i++) { + struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); + + for (t = 0; t < ofbi->num_overlays; t++) { + if (ofbi->overlays[t] == ovl) + return ofbi; + } + } + + return NULL; +} + +static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct omapfb_info *ofbi = FB2OFB(fbi); + struct omapfb2_device *fbdev = ofbi->fbdev; + struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB]; + struct omap_overlay *ovl; + int num_ovls, r, i; + int len; + bool added = false; + + num_ovls = 0; + + len = strlen(buf); + if (buf[len - 1] == '\n') + len = len - 1; + + omapfb_lock(fbdev); + lock_fb_info(fbi); + + if (len > 0) { + char *p = (char *)buf; + int ovlnum; + + while (p < buf + len) { + int found; + if (num_ovls == OMAPFB_MAX_OVL_PER_FB) { + r = -EINVAL; + goto out; + } + + ovlnum = simple_strtoul(p, &p, 0); + if (ovlnum > fbdev->num_overlays) { + r = -EINVAL; + goto out; + } + + found = 0; + for (i = 0; i < num_ovls; ++i) { + if (ovls[i] == fbdev->overlays[ovlnum]) { + found = 1; + break; + } + } + + if (!found) + ovls[num_ovls++] = fbdev->overlays[ovlnum]; + + p++; + } + } + + for (i = 0; i < num_ovls; ++i) { + struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]); + if (ofbi2 && ofbi2 != ofbi) { + dev_err(fbdev->dev, "overlay already in use\n"); + r = -EINVAL; + goto out; + } + } + + /* detach unused overlays */ + for (i = 0; i < ofbi->num_overlays; ++i) { + int t, found; + + ovl = ofbi->overlays[i]; + + found = 0; + + for (t = 0; t < num_ovls; ++t) { + if (ovl == ovls[t]) { + found = 1; + break; + } + } + + if (found) + continue; + + DBG("detaching %d\n", ofbi->overlays[i]->id); + + omapfb_overlay_enable(ovl, 0); + + if (ovl->manager) + ovl->manager->apply(ovl->manager); + + for (t = i + 1; t < ofbi->num_overlays; t++) { + ofbi->rotation[t-1] = ofbi->rotation[t]; + ofbi->overlays[t-1] = ofbi->overlays[t]; + } + + ofbi->num_overlays--; + i--; + } + + for (i = 0; i < num_ovls; ++i) { + int t, found; + + ovl = ovls[i]; + + found = 0; + + for (t = 0; t < ofbi->num_overlays; ++t) { + if (ovl == ofbi->overlays[t]) { + found = 1; + break; + } + } + + if (found) + continue; + ofbi->rotation[ofbi->num_overlays] = 0; + ofbi->overlays[ofbi->num_overlays++] = ovl; + + added = true; + } + + if (added) { + r = omapfb_apply_changes(fbi, 0); + if (r) + goto out; + } + + r = count; +out: + unlock_fb_info(fbi); + omapfb_unlock(fbdev); + + return r; +} + +static ssize_t show_overlays_rotate(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct omapfb_info *ofbi = FB2OFB(fbi); + ssize_t l = 0; + int t; + + lock_fb_info(fbi); + + for (t = 0; t < ofbi->num_overlays; t++) { + l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", + t == 0 ? "" : ",", ofbi->rotation[t]); + } + + l += snprintf(buf + l, PAGE_SIZE - l, "\n"); + + unlock_fb_info(fbi); + + return l; +} + +static ssize_t store_overlays_rotate(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct omapfb_info *ofbi = FB2OFB(fbi); + int num_ovls = 0, r, i; + int len; + bool changed = false; + u8 rotation[OMAPFB_MAX_OVL_PER_FB]; + + len = strlen(buf); + if (buf[len - 1] == '\n') + len = len - 1; + + lock_fb_info(fbi); + + if (len > 0) { + char *p = (char *)buf; + + while (p < buf + len) { + int rot; + + if (num_ovls == ofbi->num_overlays) { + r = -EINVAL; + goto out; + } + + rot = simple_strtoul(p, &p, 0); + if (rot < 0 || rot > 3) { + r = -EINVAL; + goto out; + } + + if (ofbi->rotation[num_ovls] != rot) + changed = true; + + rotation[num_ovls++] = rot; + + p++; + } + } + + if (num_ovls != ofbi->num_overlays) { + r = -EINVAL; + goto out; + } + + if (changed) { + for (i = 0; i < num_ovls; ++i) + ofbi->rotation[i] = rotation[i]; + + r = omapfb_apply_changes(fbi, 0); + if (r) + goto out; + + /* FIXME error handling? */ + } + + r = count; +out: + unlock_fb_info(fbi); + + return r; +} + +static ssize_t show_size(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct omapfb_info *ofbi = FB2OFB(fbi); + + return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size); +} + +static ssize_t store_size(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct omapfb_info *ofbi = FB2OFB(fbi); + unsigned long size; + int r; + int i; + + size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0)); + + lock_fb_info(fbi); + + for (i = 0; i < ofbi->num_overlays; i++) { + if (ofbi->overlays[i]->info.enabled) { + r = -EBUSY; + goto out; + } + } + + if (size != ofbi->region.size) { + r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type); + if (r) { + dev_err(dev, "realloc fbmem failed\n"); + goto out; + } + } + + r = count; +out: + unlock_fb_info(fbi); + + return r; +} + +static ssize_t show_phys(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct omapfb_info *ofbi = FB2OFB(fbi); + + return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr); +} + +static ssize_t show_virt(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct omapfb_info *ofbi = FB2OFB(fbi); + + return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr); +} + +static struct device_attribute omapfb_attrs[] = { + __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type, + store_rotate_type), + __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror), + __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size), + __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays), + __ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate, + store_overlays_rotate), + __ATTR(phys_addr, S_IRUGO, show_phys, NULL), + __ATTR(virt_addr, S_IRUGO, show_virt, NULL), +}; + +int omapfb_create_sysfs(struct omapfb2_device *fbdev) +{ + int i; + int r; + + DBG("create sysfs for fbs\n"); + for (i = 0; i < fbdev->num_fbs; i++) { + int t; + for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) { + r = device_create_file(fbdev->fbs[i]->dev, + &omapfb_attrs[t]); + + if (r) { + dev_err(fbdev->dev, "failed to create sysfs " + "file\n"); + return r; + } + } + } + + return 0; +} + +void omapfb_remove_sysfs(struct omapfb2_device *fbdev) +{ + int i, t; + + DBG("remove sysfs for fbs\n"); + for (i = 0; i < fbdev->num_fbs; i++) { + for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) + device_remove_file(fbdev->fbs[i]->dev, + &omapfb_attrs[t]); + } +} + diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h new file mode 100644 index 0000000000000000000000000000000000000000..f7c9c739e5ef7f6ba2784dd2419f400645b31a70 --- /dev/null +++ b/drivers/video/omap2/omapfb/omapfb.h @@ -0,0 +1,146 @@ +/* + * linux/drivers/video/omap2/omapfb.h + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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, see . + */ + +#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__ +#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__ + +#ifdef CONFIG_FB_OMAP2_DEBUG_SUPPORT +#define DEBUG +#endif + +#include + +#ifdef DEBUG +extern unsigned int omapfb_debug; +#define DBG(format, ...) \ + if (omapfb_debug) \ + printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__) +#else +#define DBG(format, ...) +#endif + +#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par)) + +/* max number of overlays to which a framebuffer data can be direct */ +#define OMAPFB_MAX_OVL_PER_FB 3 + +struct omapfb2_mem_region { + u32 paddr; + void __iomem *vaddr; + struct vrfb vrfb; + unsigned long size; + u8 type; /* OMAPFB_PLANE_MEM_* */ + bool alloc; /* allocated by the driver */ + bool map; /* kernel mapped by the driver */ +}; + +/* appended to fb_info */ +struct omapfb_info { + int id; + struct omapfb2_mem_region region; + atomic_t map_count; + int num_overlays; + struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB]; + struct omapfb2_device *fbdev; + enum omap_dss_rotation_type rotation_type; + u8 rotation[OMAPFB_MAX_OVL_PER_FB]; + bool mirror; +}; + +struct omapfb2_device { + struct device *dev; + struct mutex mtx; + + u32 pseudo_palette[17]; + + int state; + + unsigned num_fbs; + struct fb_info *fbs[10]; + + unsigned num_displays; + struct omap_dss_device *displays[10]; + unsigned num_overlays; + struct omap_overlay *overlays[10]; + unsigned num_managers; + struct omap_overlay_manager *managers[10]; +}; + +struct omapfb_colormode { + enum omap_color_mode dssmode; + u32 bits_per_pixel; + u32 nonstd; + struct fb_bitfield red; + struct fb_bitfield green; + struct fb_bitfield blue; + struct fb_bitfield transp; +}; + +void set_fb_fix(struct fb_info *fbi); +int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var); +int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type); +int omapfb_apply_changes(struct fb_info *fbi, int init); + +int omapfb_create_sysfs(struct omapfb2_device *fbdev); +void omapfb_remove_sysfs(struct omapfb2_device *fbdev); + +int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg); + +int dss_mode_to_fb_mode(enum omap_color_mode dssmode, + struct fb_var_screeninfo *var); + +/* find the display connected to this fb, if any */ +static inline struct omap_dss_device *fb2display(struct fb_info *fbi) +{ + struct omapfb_info *ofbi = FB2OFB(fbi); + int i; + + /* XXX: returns the display connected to first attached overlay */ + for (i = 0; i < ofbi->num_overlays; i++) { + if (ofbi->overlays[i]->manager) + return ofbi->overlays[i]->manager->device; + } + + return NULL; +} + +static inline void omapfb_lock(struct omapfb2_device *fbdev) +{ + mutex_lock(&fbdev->mtx); +} + +static inline void omapfb_unlock(struct omapfb2_device *fbdev) +{ + mutex_unlock(&fbdev->mtx); +} + +static inline int omapfb_overlay_enable(struct omap_overlay *ovl, + int enable) +{ + struct omap_overlay_info info; + + ovl->get_overlay_info(ovl, &info); + info.enabled = enable; + return ovl->set_overlay_info(ovl, &info); +} + +#endif diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c new file mode 100644 index 0000000000000000000000000000000000000000..55a4de5e5d10df6cc45c7dd6c9ef68c97636cd40 --- /dev/null +++ b/drivers/video/omap2/vram.c @@ -0,0 +1,655 @@ +/* + * VRAM manager for OMAP + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * 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. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#ifdef DEBUG +#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__) +#else +#define DBG(format, ...) +#endif + +#define OMAP2_SRAM_START 0x40200000 +/* Maximum size, in reality this is smaller if SRAM is partially locked. */ +#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */ + +/* postponed regions are used to temporarily store region information at boot + * time when we cannot yet allocate the region list */ +#define MAX_POSTPONED_REGIONS 10 + +static bool vram_initialized; +static int postponed_cnt; +static struct { + unsigned long paddr; + size_t size; +} postponed_regions[MAX_POSTPONED_REGIONS]; + +struct vram_alloc { + struct list_head list; + unsigned long paddr; + unsigned pages; +}; + +struct vram_region { + struct list_head list; + struct list_head alloc_list; + unsigned long paddr; + unsigned pages; +}; + +static DEFINE_MUTEX(region_mutex); +static LIST_HEAD(region_list); + +static inline int region_mem_type(unsigned long paddr) +{ + if (paddr >= OMAP2_SRAM_START && + paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE) + return OMAP_VRAM_MEMTYPE_SRAM; + else + return OMAP_VRAM_MEMTYPE_SDRAM; +} + +static struct vram_region *omap_vram_create_region(unsigned long paddr, + unsigned pages) +{ + struct vram_region *rm; + + rm = kzalloc(sizeof(*rm), GFP_KERNEL); + + if (rm) { + INIT_LIST_HEAD(&rm->alloc_list); + rm->paddr = paddr; + rm->pages = pages; + } + + return rm; +} + +#if 0 +static void omap_vram_free_region(struct vram_region *vr) +{ + list_del(&vr->list); + kfree(vr); +} +#endif + +static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr, + unsigned long paddr, unsigned pages) +{ + struct vram_alloc *va; + struct vram_alloc *new; + + new = kzalloc(sizeof(*va), GFP_KERNEL); + + if (!new) + return NULL; + + new->paddr = paddr; + new->pages = pages; + + list_for_each_entry(va, &vr->alloc_list, list) { + if (va->paddr > new->paddr) + break; + } + + list_add_tail(&new->list, &va->list); + + return new; +} + +static void omap_vram_free_allocation(struct vram_alloc *va) +{ + list_del(&va->list); + kfree(va); +} + +int omap_vram_add_region(unsigned long paddr, size_t size) +{ + struct vram_region *rm; + unsigned pages; + + if (vram_initialized) { + DBG("adding region paddr %08lx size %d\n", + paddr, size); + + size &= PAGE_MASK; + pages = size >> PAGE_SHIFT; + + rm = omap_vram_create_region(paddr, pages); + if (rm == NULL) + return -ENOMEM; + + list_add(&rm->list, ®ion_list); + } else { + if (postponed_cnt == MAX_POSTPONED_REGIONS) + return -ENOMEM; + + postponed_regions[postponed_cnt].paddr = paddr; + postponed_regions[postponed_cnt].size = size; + + ++postponed_cnt; + } + return 0; +} + +int omap_vram_free(unsigned long paddr, size_t size) +{ + struct vram_region *rm; + struct vram_alloc *alloc; + unsigned start, end; + + DBG("free mem paddr %08lx size %d\n", paddr, size); + + size = PAGE_ALIGN(size); + + mutex_lock(®ion_mutex); + + list_for_each_entry(rm, ®ion_list, list) { + list_for_each_entry(alloc, &rm->alloc_list, list) { + start = alloc->paddr; + end = alloc->paddr + (alloc->pages >> PAGE_SHIFT); + + if (start >= paddr && end < paddr + size) + goto found; + } + } + + mutex_unlock(®ion_mutex); + return -EINVAL; + +found: + omap_vram_free_allocation(alloc); + + mutex_unlock(®ion_mutex); + return 0; +} +EXPORT_SYMBOL(omap_vram_free); + +static int _omap_vram_reserve(unsigned long paddr, unsigned pages) +{ + struct vram_region *rm; + struct vram_alloc *alloc; + size_t size; + + size = pages << PAGE_SHIFT; + + list_for_each_entry(rm, ®ion_list, list) { + unsigned long start, end; + + DBG("checking region %lx %d\n", rm->paddr, rm->pages); + + if (region_mem_type(rm->paddr) != region_mem_type(paddr)) + continue; + + start = rm->paddr; + end = start + (rm->pages << PAGE_SHIFT) - 1; + if (start > paddr || end < paddr + size - 1) + continue; + + DBG("block ok, checking allocs\n"); + + list_for_each_entry(alloc, &rm->alloc_list, list) { + end = alloc->paddr - 1; + + if (start <= paddr && end >= paddr + size - 1) + goto found; + + start = alloc->paddr + (alloc->pages << PAGE_SHIFT); + } + + end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1; + + if (!(start <= paddr && end >= paddr + size - 1)) + continue; +found: + DBG("found area start %lx, end %lx\n", start, end); + + if (omap_vram_create_allocation(rm, paddr, pages) == NULL) + return -ENOMEM; + + return 0; + } + + return -ENOMEM; +} + +int omap_vram_reserve(unsigned long paddr, size_t size) +{ + unsigned pages; + int r; + + DBG("reserve mem paddr %08lx size %d\n", paddr, size); + + size = PAGE_ALIGN(size); + pages = size >> PAGE_SHIFT; + + mutex_lock(®ion_mutex); + + r = _omap_vram_reserve(paddr, pages); + + mutex_unlock(®ion_mutex); + + return r; +} +EXPORT_SYMBOL(omap_vram_reserve); + +static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data) +{ + struct completion *compl = data; + complete(compl); +} + +static int _omap_vram_clear(u32 paddr, unsigned pages) +{ + struct completion compl; + unsigned elem_count; + unsigned frame_count; + int r; + int lch; + + init_completion(&compl); + + r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA", + _omap_vram_dma_cb, + &compl, &lch); + if (r) { + pr_err("VRAM: request_dma failed for memory clear\n"); + return -EBUSY; + } + + elem_count = pages * PAGE_SIZE / 4; + frame_count = 1; + + omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32, + elem_count, frame_count, + OMAP_DMA_SYNC_ELEMENT, + 0, 0); + + omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC, + paddr, 0, 0); + + omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000); + + omap_start_dma(lch); + + if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) { + omap_stop_dma(lch); + pr_err("VRAM: dma timeout while clearing memory\n"); + r = -EIO; + goto err; + } + + r = 0; +err: + omap_free_dma(lch); + + return r; +} + +static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr) +{ + struct vram_region *rm; + struct vram_alloc *alloc; + + list_for_each_entry(rm, ®ion_list, list) { + unsigned long start, end; + + DBG("checking region %lx %d\n", rm->paddr, rm->pages); + + if (region_mem_type(rm->paddr) != mtype) + continue; + + start = rm->paddr; + + list_for_each_entry(alloc, &rm->alloc_list, list) { + end = alloc->paddr; + + if (end - start >= pages << PAGE_SHIFT) + goto found; + + start = alloc->paddr + (alloc->pages << PAGE_SHIFT); + } + + end = rm->paddr + (rm->pages << PAGE_SHIFT); +found: + if (end - start < pages << PAGE_SHIFT) + continue; + + DBG("found %lx, end %lx\n", start, end); + + alloc = omap_vram_create_allocation(rm, start, pages); + if (alloc == NULL) + return -ENOMEM; + + *paddr = start; + + _omap_vram_clear(start, pages); + + return 0; + } + + return -ENOMEM; +} + +int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr) +{ + unsigned pages; + int r; + + BUG_ON(mtype > OMAP_VRAM_MEMTYPE_MAX || !size); + + DBG("alloc mem type %d size %d\n", mtype, size); + + size = PAGE_ALIGN(size); + pages = size >> PAGE_SHIFT; + + mutex_lock(®ion_mutex); + + r = _omap_vram_alloc(mtype, pages, paddr); + + mutex_unlock(®ion_mutex); + + return r; +} +EXPORT_SYMBOL(omap_vram_alloc); + +void omap_vram_get_info(unsigned long *vram, + unsigned long *free_vram, + unsigned long *largest_free_block) +{ + struct vram_region *vr; + struct vram_alloc *va; + + *vram = 0; + *free_vram = 0; + *largest_free_block = 0; + + mutex_lock(®ion_mutex); + + list_for_each_entry(vr, ®ion_list, list) { + unsigned free; + unsigned long pa; + + pa = vr->paddr; + *vram += vr->pages << PAGE_SHIFT; + + list_for_each_entry(va, &vr->alloc_list, list) { + free = va->paddr - pa; + *free_vram += free; + if (free > *largest_free_block) + *largest_free_block = free; + pa = va->paddr + (va->pages << PAGE_SHIFT); + } + + free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa; + *free_vram += free; + if (free > *largest_free_block) + *largest_free_block = free; + } + + mutex_unlock(®ion_mutex); +} +EXPORT_SYMBOL(omap_vram_get_info); + +#if defined(CONFIG_DEBUG_FS) +static int vram_debug_show(struct seq_file *s, void *unused) +{ + struct vram_region *vr; + struct vram_alloc *va; + unsigned size; + + mutex_lock(®ion_mutex); + + list_for_each_entry(vr, ®ion_list, list) { + size = vr->pages << PAGE_SHIFT; + seq_printf(s, "%08lx-%08lx (%d bytes)\n", + vr->paddr, vr->paddr + size - 1, + size); + + list_for_each_entry(va, &vr->alloc_list, list) { + size = va->pages << PAGE_SHIFT; + seq_printf(s, " %08lx-%08lx (%d bytes)\n", + va->paddr, va->paddr + size - 1, + size); + } + } + + mutex_unlock(®ion_mutex); + + return 0; +} + +static int vram_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, vram_debug_show, inode->i_private); +} + +static const struct file_operations vram_debug_fops = { + .open = vram_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init omap_vram_create_debugfs(void) +{ + struct dentry *d; + + d = debugfs_create_file("vram", S_IRUGO, NULL, + NULL, &vram_debug_fops); + if (IS_ERR(d)) + return PTR_ERR(d); + + return 0; +} +#endif + +static __init int omap_vram_init(void) +{ + int i; + + vram_initialized = 1; + + for (i = 0; i < postponed_cnt; i++) + omap_vram_add_region(postponed_regions[i].paddr, + postponed_regions[i].size); + +#ifdef CONFIG_DEBUG_FS + if (omap_vram_create_debugfs()) + pr_err("VRAM: Failed to create debugfs file\n"); +#endif + + return 0; +} + +arch_initcall(omap_vram_init); + +/* boottime vram alloc stuff */ + +/* set from board file */ +static u32 omap_vram_sram_start __initdata; +static u32 omap_vram_sram_size __initdata; + +/* set from board file */ +static u32 omap_vram_sdram_start __initdata; +static u32 omap_vram_sdram_size __initdata; + +/* set from kernel cmdline */ +static u32 omap_vram_def_sdram_size __initdata; +static u32 omap_vram_def_sdram_start __initdata; + +static void __init omap_vram_early_vram(char **p) +{ + omap_vram_def_sdram_size = memparse(*p, p); + if (**p == ',') + omap_vram_def_sdram_start = simple_strtoul((*p) + 1, p, 16); +} +__early_param("vram=", omap_vram_early_vram); + +/* + * Called from map_io. We need to call to this early enough so that we + * can reserve the fixed SDRAM regions before VM could get hold of them. + */ +void __init omap_vram_reserve_sdram(void) +{ + struct bootmem_data *bdata; + unsigned long sdram_start, sdram_size; + u32 paddr; + u32 size = 0; + + /* cmdline arg overrides the board file definition */ + if (omap_vram_def_sdram_size) { + size = omap_vram_def_sdram_size; + paddr = omap_vram_def_sdram_start; + } + + if (!size) { + size = omap_vram_sdram_size; + paddr = omap_vram_sdram_start; + } + +#ifdef CONFIG_OMAP2_VRAM_SIZE + if (!size) { + size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024; + paddr = 0; + } +#endif + + if (!size) + return; + + size = PAGE_ALIGN(size); + + bdata = NODE_DATA(0)->bdata; + sdram_start = bdata->node_min_pfn << PAGE_SHIFT; + sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start; + + if (paddr) { + if ((paddr & ~PAGE_MASK) || paddr < sdram_start || + paddr + size > sdram_start + sdram_size) { + pr_err("Illegal SDRAM region for VRAM\n"); + return; + } + + if (reserve_bootmem(paddr, size, BOOTMEM_EXCLUSIVE) < 0) { + pr_err("FB: failed to reserve VRAM\n"); + return; + } + } else { + if (size > sdram_size) { + pr_err("Illegal SDRAM size for VRAM\n"); + return; + } + + paddr = virt_to_phys(alloc_bootmem_pages(size)); + BUG_ON(paddr & ~PAGE_MASK); + } + + omap_vram_add_region(paddr, size); + + pr_info("Reserving %u bytes SDRAM for VRAM\n", size); +} + +/* + * Called at sram init time, before anything is pushed to the SRAM stack. + * Because of the stack scheme, we will allocate everything from the + * start of the lowest address region to the end of SRAM. This will also + * include padding for page alignment and possible holes between regions. + * + * As opposed to the SDRAM case, we'll also do any dynamic allocations at + * this point, since the driver built as a module would have problem with + * freeing / reallocating the regions. + */ +unsigned long __init omap_vram_reserve_sram(unsigned long sram_pstart, + unsigned long sram_vstart, + unsigned long sram_size, + unsigned long pstart_avail, + unsigned long size_avail) +{ + unsigned long pend_avail; + unsigned long reserved; + u32 paddr; + u32 size; + + paddr = omap_vram_sram_start; + size = omap_vram_sram_size; + + if (!size) + return 0; + + reserved = 0; + pend_avail = pstart_avail + size_avail; + + if (!paddr) { + /* Dynamic allocation */ + if ((size_avail & PAGE_MASK) < size) { + pr_err("Not enough SRAM for VRAM\n"); + return 0; + } + size_avail = (size_avail - size) & PAGE_MASK; + paddr = pstart_avail + size_avail; + } + + if (paddr < sram_pstart || + paddr + size > sram_pstart + sram_size) { + pr_err("Illegal SRAM region for VRAM\n"); + return 0; + } + + /* Reserve everything above the start of the region. */ + if (pend_avail - paddr > reserved) + reserved = pend_avail - paddr; + size_avail = pend_avail - reserved - pstart_avail; + + omap_vram_add_region(paddr, size); + + if (reserved) + pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved); + + return reserved; +} + +void __init omap_vram_set_sdram_vram(u32 size, u32 start) +{ + omap_vram_sdram_start = start; + omap_vram_sdram_size = size; +} + +void __init omap_vram_set_sram_vram(u32 size, u32 start) +{ + omap_vram_sram_start = start; + omap_vram_sram_size = size; +} diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c new file mode 100644 index 0000000000000000000000000000000000000000..fd227160037058e2a2220fa60f917056e5d630ef --- /dev/null +++ b/drivers/video/omap2/vrfb.c @@ -0,0 +1,315 @@ +/* + * VRFB Rotation Engine + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen + * + * 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. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef DEBUG +#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__) +#else +#define DBG(format, ...) +#endif + +#define SMS_ROT_VIRT_BASE(context, rot) \ + (((context >= 4) ? 0xD0000000 : 0x70000000) \ + + (0x4000000 * (context)) \ + + (0x1000000 * (rot))) + +#define OMAP_VRFB_SIZE (2048 * 2048 * 4) + +#define VRFB_PAGE_WIDTH_EXP 5 /* Assuming SDRAM pagesize= 1024 */ +#define VRFB_PAGE_HEIGHT_EXP 5 /* 1024 = 2^5 * 2^5 */ +#define VRFB_PAGE_WIDTH (1 << VRFB_PAGE_WIDTH_EXP) +#define VRFB_PAGE_HEIGHT (1 << VRFB_PAGE_HEIGHT_EXP) +#define SMS_IMAGEHEIGHT_OFFSET 16 +#define SMS_IMAGEWIDTH_OFFSET 0 +#define SMS_PH_OFFSET 8 +#define SMS_PW_OFFSET 4 +#define SMS_PS_OFFSET 0 + +#define VRFB_NUM_CTXS 12 +/* bitmap of reserved contexts */ +static unsigned long ctx_map; + +static DEFINE_MUTEX(ctx_lock); + +/* + * Access to this happens from client drivers or the PM core after wake-up. + * For the first case we require locking at the driver level, for the second + * we don't need locking, since no drivers will run until after the wake-up + * has finished. + */ +static struct { + u32 physical_ba; + u32 control; + u32 size; +} vrfb_hw_context[VRFB_NUM_CTXS]; + +static inline void restore_hw_context(int ctx) +{ + omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx); + omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx); + omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx); +} + +static u32 get_image_width_roundup(u16 width, u8 bytespp) +{ + unsigned long stride = width * bytespp; + unsigned long ceil_pages_per_stride = (stride / VRFB_PAGE_WIDTH) + + (stride % VRFB_PAGE_WIDTH != 0); + + return ceil_pages_per_stride * VRFB_PAGE_WIDTH / bytespp; +} + +/* + * This the extra space needed in the VRFB physical area for VRFB to safely wrap + * any memory accesses to the invisible part of the virtual view to the physical + * area. + */ +static inline u32 get_extra_physical_size(u16 image_width_roundup, u8 bytespp) +{ + return (OMAP_VRFB_LINE_LEN - image_width_roundup) * VRFB_PAGE_HEIGHT * + bytespp; +} + +void omap_vrfb_restore_context(void) +{ + int i; + unsigned long map = ctx_map; + + for (i = ffs(map); i; i = ffs(map)) { + /* i=1..32 */ + i--; + map &= ~(1 << i); + restore_hw_context(i); + } +} + +void omap_vrfb_adjust_size(u16 *width, u16 *height, + u8 bytespp) +{ + *width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp; + *height = ALIGN(*height, VRFB_PAGE_HEIGHT); +} +EXPORT_SYMBOL(omap_vrfb_adjust_size); + +u32 omap_vrfb_min_phys_size(u16 width, u16 height, u8 bytespp) +{ + unsigned long image_width_roundup = get_image_width_roundup(width, + bytespp); + + if (image_width_roundup > OMAP_VRFB_LINE_LEN) + return 0; + + return (width * height * bytespp) + get_extra_physical_size( + image_width_roundup, bytespp); +} +EXPORT_SYMBOL(omap_vrfb_min_phys_size); + +u16 omap_vrfb_max_height(u32 phys_size, u16 width, u8 bytespp) +{ + unsigned long image_width_roundup = get_image_width_roundup(width, + bytespp); + unsigned long height; + unsigned long extra; + + if (image_width_roundup > OMAP_VRFB_LINE_LEN) + return 0; + + extra = get_extra_physical_size(image_width_roundup, bytespp); + + if (phys_size < extra) + return 0; + + height = (phys_size - extra) / (width * bytespp); + + /* Virtual views provided by VRFB are limited to 2048x2048. */ + return min_t(unsigned long, height, 2048); +} +EXPORT_SYMBOL(omap_vrfb_max_height); + +void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr, + u16 width, u16 height, + unsigned bytespp, bool yuv_mode) +{ + unsigned pixel_size_exp; + u16 vrfb_width; + u16 vrfb_height; + u8 ctx = vrfb->context; + u32 size; + u32 control; + + DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d, %d)\n", ctx, paddr, + width, height, bytespp, yuv_mode); + + /* For YUV2 and UYVY modes VRFB needs to handle pixels a bit + * differently. See TRM. */ + if (yuv_mode) { + bytespp *= 2; + width /= 2; + } + + if (bytespp == 4) + pixel_size_exp = 2; + else if (bytespp == 2) + pixel_size_exp = 1; + else + BUG(); + + vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp; + vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT); + + DBG("vrfb w %u, h %u bytespp %d\n", vrfb_width, vrfb_height, bytespp); + + size = vrfb_width << SMS_IMAGEWIDTH_OFFSET; + size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET; + + control = pixel_size_exp << SMS_PS_OFFSET; + control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET; + control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET; + + vrfb_hw_context[ctx].physical_ba = paddr; + vrfb_hw_context[ctx].size = size; + vrfb_hw_context[ctx].control = control; + + omap2_sms_write_rot_physical_ba(paddr, ctx); + omap2_sms_write_rot_size(size, ctx); + omap2_sms_write_rot_control(control, ctx); + + DBG("vrfb offset pixels %d, %d\n", + vrfb_width - width, vrfb_height - height); + + vrfb->xres = width; + vrfb->yres = height; + vrfb->xoffset = vrfb_width - width; + vrfb->yoffset = vrfb_height - height; + vrfb->bytespp = bytespp; + vrfb->yuv_mode = yuv_mode; +} +EXPORT_SYMBOL(omap_vrfb_setup); + +int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot) +{ + unsigned long size = height * OMAP_VRFB_LINE_LEN * vrfb->bytespp; + + vrfb->vaddr[rot] = ioremap_wc(vrfb->paddr[rot], size); + + if (!vrfb->vaddr[rot]) { + printk(KERN_ERR "vrfb: ioremap failed\n"); + return -ENOMEM; + } + + DBG("ioremapped vrfb area %d of size %lu into %p\n", rot, size, + vrfb->vaddr[rot]); + + return 0; +} +EXPORT_SYMBOL(omap_vrfb_map_angle); + +void omap_vrfb_release_ctx(struct vrfb *vrfb) +{ + int rot; + int ctx = vrfb->context; + + if (ctx == 0xff) + return; + + DBG("release ctx %d\n", ctx); + + mutex_lock(&ctx_lock); + + BUG_ON(!(ctx_map & (1 << ctx))); + + clear_bit(ctx, &ctx_map); + + for (rot = 0; rot < 4; ++rot) { + if (vrfb->paddr[rot]) { + release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE); + vrfb->paddr[rot] = 0; + } + } + + vrfb->context = 0xff; + + mutex_unlock(&ctx_lock); +} +EXPORT_SYMBOL(omap_vrfb_release_ctx); + +int omap_vrfb_request_ctx(struct vrfb *vrfb) +{ + int rot; + u32 paddr; + u8 ctx; + int r; + + DBG("request ctx\n"); + + mutex_lock(&ctx_lock); + + for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx) + if ((ctx_map & (1 << ctx)) == 0) + break; + + if (ctx == VRFB_NUM_CTXS) { + pr_err("vrfb: no free contexts\n"); + r = -EBUSY; + goto out; + } + + DBG("found free ctx %d\n", ctx); + + set_bit(ctx, &ctx_map); + + memset(vrfb, 0, sizeof(*vrfb)); + + vrfb->context = ctx; + + for (rot = 0; rot < 4; ++rot) { + paddr = SMS_ROT_VIRT_BASE(ctx, rot); + if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) { + pr_err("vrfb: failed to reserve VRFB " + "area for ctx %d, rotation %d\n", + ctx, rot * 90); + omap_vrfb_release_ctx(vrfb); + r = -ENOMEM; + goto out; + } + + vrfb->paddr[rot] = paddr; + + DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]); + } + + r = 0; +out: + mutex_unlock(&ctx_lock); + return r; +} +EXPORT_SYMBOL(omap_vrfb_request_ctx); diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c index 54cd916101744ff7c5c1c21d68d4d4f6b028f066..603598f4dbb1a5ddc969478d42a41912d1bfe1fe 100644 --- a/drivers/video/xen-fbfront.c +++ b/drivers/video/xen-fbfront.c @@ -25,7 +25,10 @@ #include #include #include + #include + +#include #include #include #include @@ -440,7 +443,7 @@ static int __devinit xenfb_probe(struct xenbus_device *dev, fb_info->fix.type = FB_TYPE_PACKED_PIXELS; fb_info->fix.accel = FB_ACCEL_NONE; - fb_info->flags = FBINFO_FLAG_DEFAULT; + fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; ret = fb_alloc_cmap(&fb_info->cmap, 256, 0); if (ret < 0) { diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 3711b888d482f13f2284d5c25c16a9d84d1ecbab..d958b76430a2414bd22958090a57f32af6539b96 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -861,8 +861,10 @@ config GEF_WDT Watchdog timer found in a number of GE Fanuc single board computers. config MPC5200_WDT - tristate "MPC5200 Watchdog Timer" + bool "MPC52xx Watchdog Timer" depends on PPC_MPC52xx + help + Use General Purpose Timer (GPT) 0 on the MPC5200 as Watchdog. config 8xxx_WDT tristate "MPC8xxx Platform Watchdog Timer" diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 699199b1baa6baf24d31f8e0355631ab84b1060d..89c045dc468e388e3a336508a7ab652be4405c2a 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -118,7 +118,6 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o # POWERPC Architecture obj-$(CONFIG_GEF_WDT) += gef_wdt.o -obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o obj-$(CONFIG_8xxx_WDT) += mpc8xxx_wdt.o obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o obj-$(CONFIG_PIKA_WDT) += pika_wdt.o diff --git a/drivers/watchdog/mpc5200_wdt.c b/drivers/watchdog/mpc5200_wdt.c deleted file mode 100644 index fa9c47ce0ae7b3d32a9c4a34a3747c2df08ae7d6..0000000000000000000000000000000000000000 --- a/drivers/watchdog/mpc5200_wdt.c +++ /dev/null @@ -1,293 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define GPT_MODE_WDT (1 << 15) -#define GPT_MODE_CE (1 << 12) -#define GPT_MODE_MS_TIMER (0x4) - - -struct mpc5200_wdt { - unsigned count; /* timer ticks before watchdog kicks in */ - long ipb_freq; - struct miscdevice miscdev; - struct resource mem; - struct mpc52xx_gpt __iomem *regs; - spinlock_t io_lock; -}; - -/* is_active stores wether or not the /dev/watchdog device is opened */ -static unsigned long is_active; - -/* misc devices don't provide a way, to get back to 'dev' or 'miscdev' from - * file operations, which sucks. But there can be max 1 watchdog anyway, so... - */ -static struct mpc5200_wdt *wdt_global; - - -/* helper to calculate timeout in timer counts */ -static void mpc5200_wdt_set_timeout(struct mpc5200_wdt *wdt, int timeout) -{ - /* use biggest prescaler of 64k */ - wdt->count = (wdt->ipb_freq + 0xffff) / 0x10000 * timeout; - - if (wdt->count > 0xffff) - wdt->count = 0xffff; -} -/* return timeout in seconds (calculated from timer count) */ -static int mpc5200_wdt_get_timeout(struct mpc5200_wdt *wdt) -{ - return wdt->count * 0x10000 / wdt->ipb_freq; -} - - -/* watchdog operations */ -static int mpc5200_wdt_start(struct mpc5200_wdt *wdt) -{ - spin_lock(&wdt->io_lock); - /* disable */ - out_be32(&wdt->regs->mode, 0); - /* set timeout, with maximum prescaler */ - out_be32(&wdt->regs->count, 0x0 | wdt->count); - /* enable watchdog */ - out_be32(&wdt->regs->mode, GPT_MODE_CE | GPT_MODE_WDT | - GPT_MODE_MS_TIMER); - spin_unlock(&wdt->io_lock); - - return 0; -} -static int mpc5200_wdt_ping(struct mpc5200_wdt *wdt) -{ - spin_lock(&wdt->io_lock); - /* writing A5 to OCPW resets the watchdog */ - out_be32(&wdt->regs->mode, 0xA5000000 | - (0xffffff & in_be32(&wdt->regs->mode))); - spin_unlock(&wdt->io_lock); - return 0; -} -static int mpc5200_wdt_stop(struct mpc5200_wdt *wdt) -{ - spin_lock(&wdt->io_lock); - /* disable */ - out_be32(&wdt->regs->mode, 0); - spin_unlock(&wdt->io_lock); - return 0; -} - - -/* file operations */ -static ssize_t mpc5200_wdt_write(struct file *file, const char __user *data, - size_t len, loff_t *ppos) -{ - struct mpc5200_wdt *wdt = file->private_data; - mpc5200_wdt_ping(wdt); - return 0; -} -static struct watchdog_info mpc5200_wdt_info = { - .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, - .identity = "mpc5200 watchdog on GPT0", -}; -static long mpc5200_wdt_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct mpc5200_wdt *wdt = file->private_data; - int __user *data = (int __user *)arg; - int timeout; - int ret = 0; - - switch (cmd) { - case WDIOC_GETSUPPORT: - ret = copy_to_user(data, &mpc5200_wdt_info, - sizeof(mpc5200_wdt_info)); - if (ret) - ret = -EFAULT; - break; - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - ret = put_user(0, data); - break; - - case WDIOC_KEEPALIVE: - mpc5200_wdt_ping(wdt); - break; - - case WDIOC_SETTIMEOUT: - ret = get_user(timeout, data); - if (ret) - break; - mpc5200_wdt_set_timeout(wdt, timeout); - mpc5200_wdt_start(wdt); - /* fall through and return the timeout */ - - case WDIOC_GETTIMEOUT: - timeout = mpc5200_wdt_get_timeout(wdt); - ret = put_user(timeout, data); - break; - - default: - ret = -ENOTTY; - } - return ret; -} - -static int mpc5200_wdt_open(struct inode *inode, struct file *file) -{ - /* /dev/watchdog can only be opened once */ - if (test_and_set_bit(0, &is_active)) - return -EBUSY; - - /* Set and activate the watchdog */ - mpc5200_wdt_set_timeout(wdt_global, 30); - mpc5200_wdt_start(wdt_global); - file->private_data = wdt_global; - return nonseekable_open(inode, file); -} -static int mpc5200_wdt_release(struct inode *inode, struct file *file) -{ -#if WATCHDOG_NOWAYOUT == 0 - struct mpc5200_wdt *wdt = file->private_data; - mpc5200_wdt_stop(wdt); - wdt->count = 0; /* == disabled */ -#endif - clear_bit(0, &is_active); - return 0; -} - -static const struct file_operations mpc5200_wdt_fops = { - .owner = THIS_MODULE, - .write = mpc5200_wdt_write, - .unlocked_ioctl = mpc5200_wdt_ioctl, - .open = mpc5200_wdt_open, - .release = mpc5200_wdt_release, -}; - -/* module operations */ -static int mpc5200_wdt_probe(struct of_device *op, - const struct of_device_id *match) -{ - struct mpc5200_wdt *wdt; - int err; - const void *has_wdt; - int size; - - has_wdt = of_get_property(op->node, "has-wdt", NULL); - if (!has_wdt) - has_wdt = of_get_property(op->node, "fsl,has-wdt", NULL); - if (!has_wdt) - return -ENODEV; - - wdt = kzalloc(sizeof(*wdt), GFP_KERNEL); - if (!wdt) - return -ENOMEM; - - wdt->ipb_freq = mpc5xxx_get_bus_frequency(op->node); - - err = of_address_to_resource(op->node, 0, &wdt->mem); - if (err) - goto out_free; - size = wdt->mem.end - wdt->mem.start + 1; - if (!request_mem_region(wdt->mem.start, size, "mpc5200_wdt")) { - err = -ENODEV; - goto out_free; - } - wdt->regs = ioremap(wdt->mem.start, size); - if (!wdt->regs) { - err = -ENODEV; - goto out_release; - } - - dev_set_drvdata(&op->dev, wdt); - spin_lock_init(&wdt->io_lock); - - wdt->miscdev = (struct miscdevice) { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &mpc5200_wdt_fops, - .parent = &op->dev, - }; - wdt_global = wdt; - err = misc_register(&wdt->miscdev); - if (!err) - return 0; - - iounmap(wdt->regs); -out_release: - release_mem_region(wdt->mem.start, size); -out_free: - kfree(wdt); - return err; -} - -static int mpc5200_wdt_remove(struct of_device *op) -{ - struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev); - - mpc5200_wdt_stop(wdt); - misc_deregister(&wdt->miscdev); - iounmap(wdt->regs); - release_mem_region(wdt->mem.start, wdt->mem.end - wdt->mem.start + 1); - kfree(wdt); - - return 0; -} -static int mpc5200_wdt_suspend(struct of_device *op, pm_message_t state) -{ - struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev); - mpc5200_wdt_stop(wdt); - return 0; -} -static int mpc5200_wdt_resume(struct of_device *op) -{ - struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev); - if (wdt->count) - mpc5200_wdt_start(wdt); - return 0; -} -static int mpc5200_wdt_shutdown(struct of_device *op) -{ - struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev); - mpc5200_wdt_stop(wdt); - return 0; -} - -static struct of_device_id mpc5200_wdt_match[] = { - { .compatible = "mpc5200-gpt", }, - { .compatible = "fsl,mpc5200-gpt", }, - {}, -}; -static struct of_platform_driver mpc5200_wdt_driver = { - .owner = THIS_MODULE, - .name = "mpc5200-gpt-wdt", - .match_table = mpc5200_wdt_match, - .probe = mpc5200_wdt_probe, - .remove = mpc5200_wdt_remove, - .suspend = mpc5200_wdt_suspend, - .resume = mpc5200_wdt_resume, - .shutdown = mpc5200_wdt_shutdown, -}; - - -static int __init mpc5200_wdt_init(void) -{ - return of_register_platform_driver(&mpc5200_wdt_driver); -} - -static void __exit mpc5200_wdt_exit(void) -{ - of_unregister_platform_driver(&mpc5200_wdt_driver); -} - -module_init(mpc5200_wdt_init); -module_exit(mpc5200_wdt_exit); - -MODULE_AUTHOR("Domen Puncer "); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/watchdog/twl4030_wdt.c b/drivers/watchdog/twl4030_wdt.c index cb46556f2973fb43900050ad9fa97e476b68a576..8162a40d15220aed9f2b6cfe972f9221a4520166 100644 --- a/drivers/watchdog/twl4030_wdt.c +++ b/drivers/watchdog/twl4030_wdt.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #define TWL4030_WATCHDOG_CFG_REG_OFFS 0x3 @@ -48,7 +48,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " static int twl4030_wdt_write(unsigned char val) { - return twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, val, + return twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, val, TWL4030_WATCHDOG_CFG_REG_OFFS); } diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index d31505b6f7a465fd965257210da53466cc83e34e..f6738d8b02bcdd55d7b3ebdde6782f3394726831 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -52,6 +52,8 @@ #include #include + +#include #include #include #include @@ -66,8 +68,6 @@ struct balloon_stats { /* We aim for 'current allocation' == 'target allocation'. */ unsigned long current_pages; unsigned long target_pages; - /* We may hit the hard limit in Xen. If we do then we remember it. */ - unsigned long hard_limit; /* * Drivers may alter the memory reservation independently, but they * must inform the balloon driver so we avoid hitting the hard limit. @@ -136,6 +136,8 @@ static void balloon_append(struct page *page) list_add(&page->lru, &ballooned_pages); balloon_stats.balloon_low++; } + + totalram_pages--; } /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ @@ -156,6 +158,8 @@ static struct page *balloon_retrieve(void) else balloon_stats.balloon_low--; + totalram_pages++; + return page; } @@ -181,7 +185,7 @@ static void balloon_alarm(unsigned long unused) static unsigned long current_target(void) { - unsigned long target = min(balloon_stats.target_pages, balloon_stats.hard_limit); + unsigned long target = balloon_stats.target_pages; target = min(target, balloon_stats.current_pages + @@ -217,23 +221,10 @@ static int increase_reservation(unsigned long nr_pages) set_xen_guest_handle(reservation.extent_start, frame_list); reservation.nr_extents = nr_pages; rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); - if (rc < nr_pages) { - if (rc > 0) { - int ret; - - /* We hit the Xen hard limit: reprobe. */ - reservation.nr_extents = rc; - ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, - &reservation); - BUG_ON(ret != rc); - } - if (rc >= 0) - balloon_stats.hard_limit = (balloon_stats.current_pages + rc - - balloon_stats.driver_pages); + if (rc < 0) goto out; - } - for (i = 0; i < nr_pages; i++) { + for (i = 0; i < rc; i++) { page = balloon_retrieve(); BUG_ON(page == NULL); @@ -259,13 +250,12 @@ static int increase_reservation(unsigned long nr_pages) __free_page(page); } - balloon_stats.current_pages += nr_pages; - totalram_pages = balloon_stats.current_pages; + balloon_stats.current_pages += rc; out: spin_unlock_irqrestore(&balloon_lock, flags); - return 0; + return rc < 0 ? rc : rc != nr_pages; } static int decrease_reservation(unsigned long nr_pages) @@ -323,7 +313,6 @@ static int decrease_reservation(unsigned long nr_pages) BUG_ON(ret != nr_pages); balloon_stats.current_pages -= nr_pages; - totalram_pages = balloon_stats.current_pages; spin_unlock_irqrestore(&balloon_lock, flags); @@ -367,7 +356,6 @@ static void balloon_process(struct work_struct *work) static void balloon_set_new_target(unsigned long target) { /* No need for lock. Not read-modify-write updates. */ - balloon_stats.hard_limit = ~0UL; balloon_stats.target_pages = target; schedule_work(&balloon_worker); } @@ -422,12 +410,10 @@ static int __init balloon_init(void) pr_info("xen_balloon: Initialising balloon driver.\n"); balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn); - totalram_pages = balloon_stats.current_pages; balloon_stats.target_pages = balloon_stats.current_pages; balloon_stats.balloon_low = 0; balloon_stats.balloon_high = 0; balloon_stats.driver_pages = 0UL; - balloon_stats.hard_limit = ~0UL; init_timer(&balloon_timer); balloon_timer.data = 0; @@ -472,9 +458,6 @@ module_exit(balloon_exit); BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages)); BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low)); BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high)); -BALLOON_SHOW(hard_limit_kb, - (balloon_stats.hard_limit!=~0UL) ? "%lu\n" : "???\n", - (balloon_stats.hard_limit!=~0UL) ? PAGES2KB(balloon_stats.hard_limit) : 0); BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages)); static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr, @@ -544,7 +527,6 @@ static struct attribute *balloon_info_attrs[] = { &attr_current_kb.attr, &attr_low_kb.attr, &attr_high_kb.attr, - &attr_hard_limit_kb.attr, &attr_driver_kb.attr, NULL }; diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c index 0f765a92018913ff93791a3c97c6d7d094c586df..14e2d995e95800ca88a064ac5ba09caec2b48973 100644 --- a/drivers/xen/cpu_hotplug.c +++ b/drivers/xen/cpu_hotplug.c @@ -1,5 +1,6 @@ #include +#include #include #include diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 2f57276e87a2f65cd8c468529484e3ca21f88c8b..ce602dd09bc18c60381c68f0f1310bb168817bed 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -474,6 +474,9 @@ static void unbind_from_irq(unsigned int irq) bind_evtchn_to_cpu(evtchn, 0); evtchn_to_irq[evtchn] = -1; + } + + if (irq_info[irq].type != IRQT_UNBOUND) { irq_info[irq] = mk_unbound_info(); dynamic_irq_cleanup(irq); diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c index 79bedba44feef5651177f10c2e3469e98a089e9a..f70a4f4698c5994348a14dd216bb91ad72ec5b6a 100644 --- a/drivers/xen/evtchn.c +++ b/drivers/xen/evtchn.c @@ -48,6 +48,8 @@ #include #include #include + +#include #include #include #include diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 7d8f531fb8e8a60a342f2fce3f2168fe5127db39..4c6c0bd636a8073ab743dbcc2a643d3ea7fd73a0 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -37,6 +37,7 @@ #include #include +#include #include #include #include diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 10d03d7931c47236a42e2e7ac158ac7564308354..c4997930afc71a741a429df77b7e98f7b5d58872 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -43,7 +43,6 @@ static int xen_suspend(void *data) if (err) { printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n", err); - dpm_resume_noirq(PMSG_RESUME); return err; } @@ -69,7 +68,6 @@ static int xen_suspend(void *data) } sysdev_resume(); - dpm_resume_noirq(PMSG_RESUME); return 0; } @@ -81,6 +79,12 @@ static void do_suspend(void) shutting_down = SHUTDOWN_SUSPEND; + err = stop_machine_create(); + if (err) { + printk(KERN_ERR "xen suspend: failed to setup stop_machine %d\n", err); + goto out; + } + #ifdef CONFIG_PREEMPT /* If the kernel is preemptible, we need to freeze all the processes to prevent them from being in the middle of a pagetable update @@ -88,29 +92,32 @@ static void do_suspend(void) err = freeze_processes(); if (err) { printk(KERN_ERR "xen suspend: freeze failed %d\n", err); - return; + goto out_destroy_sm; } #endif err = dpm_suspend_start(PMSG_SUSPEND); if (err) { printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err); - goto out; + goto out_thaw; } - printk(KERN_DEBUG "suspending xenstore...\n"); - xs_suspend(); - err = dpm_suspend_noirq(PMSG_SUSPEND); if (err) { printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err); - goto resume_devices; + goto out_resume; } + printk(KERN_DEBUG "suspending xenstore...\n"); + xs_suspend(); + err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); + + dpm_resume_noirq(PMSG_RESUME); + if (err) { printk(KERN_ERR "failed to start xen_suspend: %d\n", err); - goto out; + cancelled = 1; } if (!cancelled) { @@ -119,17 +126,21 @@ static void do_suspend(void) } else xs_suspend_cancel(); - dpm_resume_noirq(PMSG_RESUME); - -resume_devices: +out_resume: dpm_resume_end(PMSG_RESUME); /* Make sure timer events get retriggered on all CPUs */ clock_was_set(); -out: + +out_thaw: #ifdef CONFIG_PREEMPT thaw_processes(); + +out_destroy_sm: #endif + stop_machine_destroy(); + +out: shutting_down = SHUTDOWN_INVALID; } #endif /* CONFIG_PM_SLEEP */ diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c index 88a60e03ccf079f40c1bab8f4da18d03720d5955..ae5cb05a1a1cb01cd4777d84b66ea3ba84e98c8a 100644 --- a/drivers/xen/sys-hypervisor.c +++ b/drivers/xen/sys-hypervisor.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index d42e25d5968dcf48acd5448a7a6af56d21abd5fb..2f7aaa99dc47e5d26701308e761612a2cdcbec8e 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -49,6 +49,8 @@ #include #include #include + +#include #include #include #include @@ -454,21 +456,21 @@ static ssize_t xendev_show_nodename(struct device *dev, { return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename); } -DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL); +static DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL); static ssize_t xendev_show_devtype(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype); } -DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL); +static DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL); static ssize_t xendev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype); } -DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL); +static DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL); int xenbus_probe_node(struct xen_bus_type *bus, const char *type, @@ -843,7 +845,7 @@ postcore_initcall(xenbus_probe_init); MODULE_LICENSE("GPL"); -static int is_disconnected_device(struct device *dev, void *data) +static int is_device_connecting(struct device *dev, void *data) { struct xenbus_device *xendev = to_xenbus_device(dev); struct device_driver *drv = data; @@ -861,14 +863,15 @@ static int is_disconnected_device(struct device *dev, void *data) return 0; xendrv = to_xenbus_driver(dev->driver); - return (xendev->state != XenbusStateConnected || - (xendrv->is_ready && !xendrv->is_ready(xendev))); + return (xendev->state < XenbusStateConnected || + (xendev->state == XenbusStateConnected && + xendrv->is_ready && !xendrv->is_ready(xendev))); } -static int exists_disconnected_device(struct device_driver *drv) +static int exists_connecting_device(struct device_driver *drv) { return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, - is_disconnected_device); + is_device_connecting); } static int print_device_status(struct device *dev, void *data) @@ -884,10 +887,13 @@ static int print_device_status(struct device *dev, void *data) /* Information only: is this too noisy? */ printk(KERN_INFO "XENBUS: Device with no driver: %s\n", xendev->nodename); - } else if (xendev->state != XenbusStateConnected) { + } else if (xendev->state < XenbusStateConnected) { + enum xenbus_state rstate = XenbusStateUnknown; + if (xendev->otherend) + rstate = xenbus_read_driver_state(xendev->otherend); printk(KERN_WARNING "XENBUS: Timeout connecting " - "to device: %s (state %d)\n", - xendev->nodename, xendev->state); + "to device: %s (local state %d, remote state %d)\n", + xendev->nodename, xendev->state, rstate); } return 0; @@ -897,7 +903,7 @@ static int print_device_status(struct device *dev, void *data) static int ready_to_wait_for_devices; /* - * On a 10 second timeout, wait for all devices currently configured. We need + * On a 5-minute timeout, wait for all devices currently configured. We need * to do this to guarantee that the filesystems and / or network devices * needed for boot are available, before we can allow the boot to proceed. * @@ -912,18 +918,30 @@ static int ready_to_wait_for_devices; */ static void wait_for_devices(struct xenbus_driver *xendrv) { - unsigned long timeout = jiffies + 10*HZ; + unsigned long start = jiffies; struct device_driver *drv = xendrv ? &xendrv->driver : NULL; + unsigned int seconds_waited = 0; if (!ready_to_wait_for_devices || !xen_domain()) return; - while (exists_disconnected_device(drv)) { - if (time_after(jiffies, timeout)) - break; + while (exists_connecting_device(drv)) { + if (time_after(jiffies, start + (seconds_waited+5)*HZ)) { + if (!seconds_waited) + printk(KERN_WARNING "XENBUS: Waiting for " + "devices to initialise: "); + seconds_waited += 5; + printk("%us...", 300 - seconds_waited); + if (seconds_waited == 300) + break; + } + schedule_timeout_interruptible(HZ/10); } + if (seconds_waited) + printk("\n"); + bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, print_device_status); } diff --git a/drivers/xen/xenfs/super.c b/drivers/xen/xenfs/super.c index 6559e0c752ce1494baa127921834e388832cbd75..8924d93136f152a7dd6b84d267db3162a4ff739b 100644 --- a/drivers/xen/xenfs/super.c +++ b/drivers/xen/xenfs/super.c @@ -13,6 +13,8 @@ #include #include +#include + #include "xenfs.h" #include diff --git a/fs/afs/write.c b/fs/afs/write.c index c63a3c8beb73d50f84674b6b21963e177d937562..5e15a21dbf9f3f9d705c2889761e04749c45531a 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -671,7 +671,6 @@ ssize_t afs_file_write(struct kiocb *iocb, const struct iovec *iov, struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode); ssize_t result; size_t count = iov_length(iov, nr_segs); - int ret; _enter("{%x.%u},{%zu},%lu,", vnode->fid.vid, vnode->fid.vnode, count, nr_segs); @@ -691,13 +690,6 @@ ssize_t afs_file_write(struct kiocb *iocb, const struct iovec *iov, return result; } - /* return error values for O_SYNC and IS_SYNC() */ - if (IS_SYNC(&vnode->vfs_inode) || iocb->ki_filp->f_flags & O_SYNC) { - ret = afs_fsync(iocb->ki_filp, dentry, 1); - if (ret < 0) - result = ret; - } - _leave(" = %zd", result); return result; } diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 06550affbd27ea9181bd08db8d1ea18d9e8f42c0..77f759302e125da0467e8a3ff3341b6ee11f0b97 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -909,7 +909,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, unsigned long last_index; int will_write; - will_write = ((file->f_flags & O_SYNC) || IS_SYNC(inode) || + will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) || (file->f_flags & O_DIRECT)); nrptrs = min((count + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE, @@ -1076,7 +1076,7 @@ out_nolock: if (err) num_written = err; - if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { + if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) { trans = btrfs_start_transaction(root, 1); ret = btrfs_log_dentry_safe(trans, root, file->f_dentry); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 1f42f772865a54f1f45b516b090533a4a4715bf4..6ccf7262d1b7c78267263ca7dd1eb6ce3b3b86e2 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -214,7 +214,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode, posix_flags |= SMB_O_EXCL; if (oflags & O_TRUNC) posix_flags |= SMB_O_TRUNC; - if (oflags & O_SYNC) + /* be safe and imply O_SYNC for O_DSYNC */ + if (oflags & O_DSYNC) posix_flags |= SMB_O_SYNC; if (oflags & O_DIRECTORY) posix_flags |= SMB_O_DIRECTORY; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 429337eb7afec9f0933c72927eedcc7412207c88..057e1dae12ab521a98f356a814fd303b99624776 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -76,8 +76,10 @@ static inline fmode_t cifs_posix_convert_flags(unsigned int flags) reopening a file. They had their effect on the original open */ if (flags & O_APPEND) posix_flags |= (fmode_t)O_APPEND; - if (flags & O_SYNC) - posix_flags |= (fmode_t)O_SYNC; + if (flags & O_DSYNC) + posix_flags |= (fmode_t)O_DSYNC; + if (flags & __O_SYNC) + posix_flags |= (fmode_t)__O_SYNC; if (flags & O_DIRECTORY) posix_flags |= (fmode_t)O_DIRECTORY; if (flags & O_NOFOLLOW) diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 2346895b3a77c60b967c482dc0b74dcbe3580fa3..14cbc831422a1cb84026bfe90d7c2a68cc43d99f 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -111,43 +111,40 @@ #include #include +#include + #ifdef CONFIG_SPARC #include #endif -static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *f) -{ - return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg)); -} - -static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) +static int w_long(unsigned int fd, unsigned int cmd, + compat_ulong_t __user *argp) { mm_segment_t old_fs = get_fs(); int err; unsigned long val; - + set_fs (KERNEL_DS); err = sys_ioctl(fd, cmd, (unsigned long)&val); set_fs (old_fs); - if (!err && put_user(val, (u32 __user *)compat_ptr(arg))) + if (!err && put_user(val, argp)) return -EFAULT; return err; } - -static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg) + +static int rw_long(unsigned int fd, unsigned int cmd, + compat_ulong_t __user *argp) { mm_segment_t old_fs = get_fs(); - u32 __user *argptr = compat_ptr(arg); int err; unsigned long val; - - if(get_user(val, argptr)) + + if(get_user(val, argp)) return -EFAULT; set_fs (KERNEL_DS); err = sys_ioctl(fd, cmd, (unsigned long)&val); set_fs (old_fs); - if (!err && put_user(val, argptr)) + if (!err && put_user(val, argp)) return -EFAULT; return err; } @@ -161,7 +158,8 @@ struct compat_video_event { } u; }; -static int do_video_get_event(unsigned int fd, unsigned int cmd, unsigned long arg) +static int do_video_get_event(unsigned int fd, unsigned int cmd, + struct compat_video_event __user *up) { struct video_event kevent; mm_segment_t old_fs = get_fs(); @@ -172,8 +170,6 @@ static int do_video_get_event(unsigned int fd, unsigned int cmd, unsigned long a set_fs(old_fs); if (!err) { - struct compat_video_event __user *up = compat_ptr(arg); - err = put_user(kevent.type, &up->type); err |= put_user(kevent.timestamp, &up->timestamp); err |= put_user(kevent.u.size.w, &up->u.size.w); @@ -192,15 +188,14 @@ struct compat_video_still_picture { int32_t size; }; -static int do_video_stillpicture(unsigned int fd, unsigned int cmd, unsigned long arg) +static int do_video_stillpicture(unsigned int fd, unsigned int cmd, + struct compat_video_still_picture __user *up) { - struct compat_video_still_picture __user *up; struct video_still_picture __user *up_native; compat_uptr_t fp; int32_t size; int err; - up = (struct compat_video_still_picture __user *) arg; err = get_user(fp, &up->iFrame); err |= get_user(size, &up->size); if (err) @@ -224,14 +219,13 @@ struct compat_video_spu_palette { compat_uptr_t palette; }; -static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, unsigned long arg) +static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, + struct compat_video_spu_palette __user *up) { - struct compat_video_spu_palette __user *up; struct video_spu_palette __user *up_native; compat_uptr_t palp; int length, err; - up = (struct compat_video_spu_palette __user *) arg; err = get_user(palp, &up->palette); err |= get_user(length, &up->length); @@ -299,16 +293,15 @@ static int sg_build_iovec(sg_io_hdr_t __user *sgio, void __user *dxferp, u16 iov return 0; } -static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, + sg_io_hdr32_t __user *sgio32) { sg_io_hdr_t __user *sgio; - sg_io_hdr32_t __user *sgio32; u16 iovec_count; u32 data; void __user *dxferp; int err; - sgio32 = compat_ptr(arg); if (get_user(iovec_count, &sgio32->iovec_count)) return -EFAULT; @@ -398,11 +391,11 @@ struct compat_sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */ int unused; }; -static int sg_grt_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +static int sg_grt_trans(unsigned int fd, unsigned int cmd, struct + compat_sg_req_info __user *o) { int err, i; sg_req_info_t __user *r; - struct compat_sg_req_info __user *o = (void __user *)arg; r = compat_alloc_user_space(sizeof(sg_req_info_t)*SG_MAX_QUEUE); err = sys_ioctl(fd,cmd,(unsigned long)r); if (err < 0) @@ -430,9 +423,9 @@ struct sock_fprog32 { #define PPPIOCSPASS32 _IOW('t', 71, struct sock_fprog32) #define PPPIOCSACTIVE32 _IOW('t', 70, struct sock_fprog32) -static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, + struct sock_fprog32 __user *u_fprog32) { - struct sock_fprog32 __user *u_fprog32 = compat_ptr(arg); struct sock_fprog __user *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog)); void __user *fptr64; u32 fptr32; @@ -469,15 +462,14 @@ struct ppp_idle32 { }; #define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32) -static int ppp_gidle(unsigned int fd, unsigned int cmd, unsigned long arg) +static int ppp_gidle(unsigned int fd, unsigned int cmd, + struct ppp_idle32 __user *idle32) { struct ppp_idle __user *idle; - struct ppp_idle32 __user *idle32; __kernel_time_t xmit, recv; int err; idle = compat_alloc_user_space(sizeof(*idle)); - idle32 = compat_ptr(arg); err = sys_ioctl(fd, PPPIOCGIDLE, (unsigned long) idle); @@ -491,15 +483,14 @@ static int ppp_gidle(unsigned int fd, unsigned int cmd, unsigned long arg) return err; } -static int ppp_scompress(unsigned int fd, unsigned int cmd, unsigned long arg) +static int ppp_scompress(unsigned int fd, unsigned int cmd, + struct ppp_option_data32 __user *odata32) { struct ppp_option_data __user *odata; - struct ppp_option_data32 __user *odata32; __u32 data; void __user *datap; odata = compat_alloc_user_space(sizeof(*odata)); - odata32 = compat_ptr(arg); if (get_user(data, &odata32->ptr)) return -EFAULT; @@ -515,35 +506,6 @@ static int ppp_scompress(unsigned int fd, unsigned int cmd, unsigned long arg) return sys_ioctl(fd, PPPIOCSCOMPRESS, (unsigned long) odata); } -static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - int err; - - switch (cmd) { - case PPPIOCGIDLE32: - err = ppp_gidle(fd, cmd, arg); - break; - - case PPPIOCSCOMPRESS32: - err = ppp_scompress(fd, cmd, arg); - break; - - default: - do { - static int count; - if (++count <= 20) - printk("ppp_ioctl: Unknown cmd fd(%d) " - "cmd(%08x) arg(%08x)\n", - (int)fd, (unsigned int)cmd, (unsigned int)arg); - } while(0); - err = -EINVAL; - break; - }; - - return err; -} - - #ifdef CONFIG_BLOCK struct mtget32 { compat_long_t mt_type; @@ -561,7 +523,7 @@ struct mtpos32 { }; #define MTIOCPOS32 _IOR('m', 3, struct mtpos32) -static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, void __user *argp) { mm_segment_t old_fs = get_fs(); struct mtget get; @@ -581,15 +543,6 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) kcmd = MTIOCGET; karg = &get; break; - default: - do { - static int count; - if (++count <= 20) - printk("mt_ioctl: Unknown cmd fd(%d) " - "cmd(%08x) arg(%08x)\n", - (int)fd, (unsigned int)cmd, (unsigned int)arg); - } while(0); - return -EINVAL; } set_fs (KERNEL_DS); err = sys_ioctl (fd, kcmd, (unsigned long)karg); @@ -598,11 +551,11 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) return err; switch (cmd) { case MTIOCPOS32: - upos32 = compat_ptr(arg); + upos32 = argp; err = __put_user(pos.mt_blkno, &upos32->mt_blkno); break; case MTIOCGET32: - umget32 = compat_ptr(arg); + umget32 = argp; err = __put_user(get.mt_type, &umget32->mt_type); err |= __put_user(get.mt_resid, &umget32->mt_resid); err |= __put_user(get.mt_dsreg, &umget32->mt_dsreg); @@ -617,162 +570,8 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) #endif /* CONFIG_BLOCK */ -#ifdef CONFIG_VT - -static int vt_check(struct file *file) -{ - struct tty_struct *tty; - struct inode *inode = file->f_path.dentry->d_inode; - struct vc_data *vc; - - if (file->f_op->unlocked_ioctl != tty_ioctl) - return -EINVAL; - - tty = (struct tty_struct *)file->private_data; - if (tty_paranoia_check(tty, inode, "tty_ioctl")) - return -EINVAL; - - if (tty->ops->ioctl != vt_ioctl) - return -EINVAL; - - vc = (struct vc_data *)tty->driver_data; - if (!vc_cons_allocated(vc->vc_num)) /* impossible? */ - return -ENOIOCTLCMD; - - /* - * To have permissions to do most of the vt ioctls, we either have - * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. - */ - if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) - return 1; - return 0; -} - -struct consolefontdesc32 { - unsigned short charcount; /* characters in font (256 or 512) */ - unsigned short charheight; /* scan lines per character (1-32) */ - compat_caddr_t chardata; /* font data in expanded form */ -}; - -static int do_fontx_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) -{ - struct consolefontdesc32 __user *user_cfd = compat_ptr(arg); - struct console_font_op op; - compat_caddr_t data; - int i, perm; - - perm = vt_check(file); - if (perm < 0) return perm; - - switch (cmd) { - case PIO_FONTX: - if (!perm) - return -EPERM; - op.op = KD_FONT_OP_SET; - op.flags = 0; - op.width = 8; - if (get_user(op.height, &user_cfd->charheight) || - get_user(op.charcount, &user_cfd->charcount) || - get_user(data, &user_cfd->chardata)) - return -EFAULT; - op.data = compat_ptr(data); - return con_font_op(vc_cons[fg_console].d, &op); - case GIO_FONTX: - op.op = KD_FONT_OP_GET; - op.flags = 0; - op.width = 8; - if (get_user(op.height, &user_cfd->charheight) || - get_user(op.charcount, &user_cfd->charcount) || - get_user(data, &user_cfd->chardata)) - return -EFAULT; - if (!data) - return 0; - op.data = compat_ptr(data); - i = con_font_op(vc_cons[fg_console].d, &op); - if (i) - return i; - if (put_user(op.height, &user_cfd->charheight) || - put_user(op.charcount, &user_cfd->charcount) || - put_user((compat_caddr_t)(unsigned long)op.data, - &user_cfd->chardata)) - return -EFAULT; - return 0; - } - return -EINVAL; -} - -struct console_font_op32 { - compat_uint_t op; /* operation code KD_FONT_OP_* */ - compat_uint_t flags; /* KD_FONT_FLAG_* */ - compat_uint_t width, height; /* font size */ - compat_uint_t charcount; - compat_caddr_t data; /* font data with height fixed to 32 */ -}; - -static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) -{ - struct console_font_op op; - struct console_font_op32 __user *fontop = compat_ptr(arg); - int perm = vt_check(file), i; - struct vc_data *vc; - - if (perm < 0) return perm; - - if (copy_from_user(&op, fontop, sizeof(struct console_font_op32))) - return -EFAULT; - if (!perm && op.op != KD_FONT_OP_GET) - return -EPERM; - op.data = compat_ptr(((struct console_font_op32 *)&op)->data); - op.flags |= KD_FONT_FLAG_OLD; - vc = ((struct tty_struct *)file->private_data)->driver_data; - i = con_font_op(vc, &op); - if (i) - return i; - ((struct console_font_op32 *)&op)->data = (unsigned long)op.data; - if (copy_to_user(fontop, &op, sizeof(struct console_font_op32))) - return -EFAULT; - return 0; -} - -struct unimapdesc32 { - unsigned short entry_ct; - compat_caddr_t entries; -}; - -static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) -{ - struct unimapdesc32 tmp; - struct unimapdesc32 __user *user_ud = compat_ptr(arg); - int perm = vt_check(file); - struct vc_data *vc; - - if (perm < 0) - return perm; - if (copy_from_user(&tmp, user_ud, sizeof tmp)) - return -EFAULT; - if (tmp.entries) - if (!access_ok(VERIFY_WRITE, compat_ptr(tmp.entries), - tmp.entry_ct*sizeof(struct unipair))) - return -EFAULT; - vc = ((struct tty_struct *)file->private_data)->driver_data; - switch (cmd) { - case PIO_UNIMAP: - if (!perm) - return -EPERM; - return con_set_unimap(vc, tmp.entry_ct, - compat_ptr(tmp.entries)); - case GIO_UNIMAP: - if (!perm && fg_console != vc->vc_num) - return -EPERM; - return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), - compat_ptr(tmp.entries)); - } - return 0; -} - -#endif /* CONFIG_VT */ - -static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long arg) +static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, + compat_uid_t __user *argp) { mm_segment_t old_fs = get_fs(); __kernel_uid_t kuid; @@ -785,20 +584,15 @@ static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long a set_fs(old_fs); if (err >= 0) - err = put_user(kuid, (compat_uid_t __user *)compat_ptr(arg)); + err = put_user(kuid, argp); return err; } -static __used int -ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - return -EINVAL; -} - -static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) +static int ioc_settimeout(unsigned int fd, unsigned int cmd, + compat_ulong_t __user *argp) { - return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); + return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, argp); } /* Bluetooth ioctls */ @@ -856,7 +650,8 @@ static int set_raw32_request(struct raw_config_request *req, struct raw32_config return ret ? -EFAULT : 0; } -static int raw_ioctl(unsigned fd, unsigned cmd, unsigned long arg) +static int raw_ioctl(unsigned fd, unsigned cmd, + struct raw32_config_request __user *user_req) { int ret; @@ -864,7 +659,6 @@ static int raw_ioctl(unsigned fd, unsigned cmd, unsigned long arg) case RAW_SETBIND: case RAW_GETBIND: { struct raw_config_request req; - struct raw32_config_request __user *user_req = compat_ptr(arg); mm_segment_t oldfs = get_fs(); if ((ret = get_raw32_request(&req, user_req))) @@ -879,9 +673,6 @@ static int raw_ioctl(unsigned fd, unsigned cmd, unsigned long arg) } break; } - default: - ret = sys_ioctl(fd, cmd, arg); - break; } return ret; } @@ -909,11 +700,11 @@ struct serial_struct32 { compat_int_t reserved[1]; }; -static int serial_struct_ioctl(unsigned fd, unsigned cmd, unsigned long arg) +static int serial_struct_ioctl(unsigned fd, unsigned cmd, + struct serial_struct32 __user *ss32) { typedef struct serial_struct SS; typedef struct serial_struct32 SS32; - struct serial_struct32 __user *ss32 = compat_ptr(arg); int err; struct serial_struct ss; mm_segment_t oldseg = get_fs(); @@ -951,96 +742,6 @@ static int serial_struct_ioctl(unsigned fd, unsigned cmd, unsigned long arg) return err; } -struct usbdevfs_ctrltransfer32 { - u8 bRequestType; - u8 bRequest; - u16 wValue; - u16 wIndex; - u16 wLength; - u32 timeout; /* in milliseconds */ - compat_caddr_t data; -}; - -#define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32) - -static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_ctrltransfer32 __user *p32 = compat_ptr(arg); - struct usbdevfs_ctrltransfer __user *p; - __u32 udata; - p = compat_alloc_user_space(sizeof(*p)); - if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t))) || - get_user(udata, &p32->data) || - put_user(compat_ptr(udata), &p->data)) - return -EFAULT; - return sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)p); -} - - -struct usbdevfs_bulktransfer32 { - compat_uint_t ep; - compat_uint_t len; - compat_uint_t timeout; /* in milliseconds */ - compat_caddr_t data; -}; - -#define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32) - -static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_bulktransfer32 __user *p32 = compat_ptr(arg); - struct usbdevfs_bulktransfer __user *p; - compat_uint_t n; - compat_caddr_t addr; - - p = compat_alloc_user_space(sizeof(*p)); - - if (get_user(n, &p32->ep) || put_user(n, &p->ep) || - get_user(n, &p32->len) || put_user(n, &p->len) || - get_user(n, &p32->timeout) || put_user(n, &p->timeout) || - get_user(addr, &p32->data) || put_user(compat_ptr(addr), &p->data)) - return -EFAULT; - - return sys_ioctl(fd, USBDEVFS_BULK, (unsigned long)p); -} - - -/* - * USBDEVFS_SUBMITURB, USBDEVFS_REAPURB and USBDEVFS_REAPURBNDELAY - * are handled in usbdevfs core. -Christopher Li - */ - -struct usbdevfs_disconnectsignal32 { - compat_int_t signr; - compat_caddr_t context; -}; - -#define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32) - -static int do_usbdevfs_discsignal(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_disconnectsignal kdis; - struct usbdevfs_disconnectsignal32 __user *udis; - mm_segment_t old_fs; - u32 uctx; - int err; - - udis = compat_ptr(arg); - - if (get_user(kdis.signr, &udis->signr) || - __get_user(uctx, &udis->context)) - return -EFAULT; - - kdis.context = compat_ptr(uctx); - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_DISCSIGNAL, (unsigned long) &kdis); - set_fs(old_fs); - - return err; -} - /* * I2C layer ioctls */ @@ -1069,9 +770,9 @@ struct i2c_rdwr_aligned { struct i2c_msg msgs[0]; }; -static int do_i2c_rdwr_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +static int do_i2c_rdwr_ioctl(unsigned int fd, unsigned int cmd, + struct i2c_rdwr_ioctl_data32 __user *udata) { - struct i2c_rdwr_ioctl_data32 __user *udata = compat_ptr(arg); struct i2c_rdwr_aligned __user *tdata; struct i2c_msg __user *tmsgs; struct i2c_msg32 __user *umsgs; @@ -1105,10 +806,10 @@ static int do_i2c_rdwr_ioctl(unsigned int fd, unsigned int cmd, unsigned long ar return sys_ioctl(fd, cmd, (unsigned long)tdata); } -static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, + struct i2c_smbus_ioctl_data32 __user *udata) { struct i2c_smbus_ioctl_data __user *tdata; - struct i2c_smbus_ioctl_data32 __user *udata; compat_caddr_t datap; tdata = compat_alloc_user_space(sizeof(*tdata)); @@ -1117,7 +818,6 @@ static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, unsigned long a if (!access_ok(VERIFY_WRITE, tdata, sizeof(*tdata))) return -EFAULT; - udata = compat_ptr(arg); if (!access_ok(VERIFY_READ, udata, sizeof(*udata))) return -EFAULT; @@ -1137,7 +837,7 @@ static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, unsigned long a #define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) #define RTC_EPOCH_SET32 _IOW('p', 0x0e, compat_ulong_t) -static int rtc_ioctl(unsigned fd, unsigned cmd, unsigned long arg) +static int rtc_ioctl(unsigned fd, unsigned cmd, void __user *argp) { mm_segment_t oldfs = get_fs(); compat_ulong_t val32; @@ -1155,29 +855,14 @@ static int rtc_ioctl(unsigned fd, unsigned cmd, unsigned long arg) if (ret) return ret; val32 = kval; - return put_user(val32, (unsigned int __user *)arg); + return put_user(val32, (unsigned int __user *)argp); case RTC_IRQP_SET32: - return sys_ioctl(fd, RTC_IRQP_SET, arg); + return sys_ioctl(fd, RTC_IRQP_SET, (unsigned long)argp); case RTC_EPOCH_SET32: - return sys_ioctl(fd, RTC_EPOCH_SET, arg); - default: - /* unreached */ - return -ENOIOCTLCMD; + return sys_ioctl(fd, RTC_EPOCH_SET, (unsigned long)argp); } -} -static int -lp_timeout_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct compat_timeval __user *tc = (struct compat_timeval __user *)arg; - struct timeval __user *tn = compat_alloc_user_space(sizeof(struct timeval)); - struct timeval ts; - if (get_user(ts.tv_sec, &tc->tv_sec) || - get_user(ts.tv_usec, &tc->tv_usec) || - put_user(ts.tv_sec, &tn->tv_sec) || - put_user(ts.tv_usec, &tn->tv_usec)) - return -EFAULT; - return sys_ioctl(fd, cmd, (unsigned long)tn); + return -ENOIOCTLCMD; } /* on ia32 l_start is on a 32-bit boundary */ @@ -1197,9 +882,9 @@ struct space_resv_32 { #define FS_IOC_RESVSP64_32 _IOW ('X', 42, struct space_resv_32) /* just account for different alignment */ -static int compat_ioctl_preallocate(struct file *file, unsigned long arg) +static int compat_ioctl_preallocate(struct file *file, + struct space_resv_32 __user *p32) { - struct space_resv_32 __user *p32 = compat_ptr(arg); struct space_resv __user *p = compat_alloc_user_space(sizeof(*p)); if (copy_in_user(&p->l_type, &p32->l_type, sizeof(s16)) || @@ -1215,27 +900,13 @@ static int compat_ioctl_preallocate(struct file *file, unsigned long arg) } #endif +/* + * simple reversible transform to make our table more evenly + * distributed after sorting. + */ +#define XFORM(i) (((i) ^ ((i) << 27) ^ ((i) << 17)) & 0xffffffff) -typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int, - unsigned long, struct file *); - -struct ioctl_trans { - unsigned long cmd; - ioctl_trans_handler_t handler; - struct ioctl_trans *next; -}; - -#define HANDLE_IOCTL(cmd,handler) \ - { (cmd), (ioctl_trans_handler_t)(handler) }, - -/* pointer to compatible structure or no argument */ -#define COMPATIBLE_IOCTL(cmd) \ - { (cmd), do_ioctl32_pointer }, - -/* argument is an unsigned long integer, not a pointer */ -#define ULONG_IOCTL(cmd) \ - { (cmd), (ioctl_trans_handler_t)sys_ioctl }, - +#define COMPATIBLE_IOCTL(cmd) XFORM(cmd), /* ioctl should not be warned about even if it's not implemented. Valid reasons to use this: - It is implemented with ->compat_ioctl on some device, but programs @@ -1245,7 +916,7 @@ struct ioctl_trans { Most other reasons are not valid. */ #define IGNORE_IOCTL(cmd) COMPATIBLE_IOCTL(cmd) -static struct ioctl_trans ioctl_start[] = { +static unsigned int ioctl_pointer[] = { /* compatible ioctls first */ COMPATIBLE_IOCTL(0x4B50) /* KDGHWCLK - not in the kernel, but don't complain */ COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain */ @@ -1256,7 +927,6 @@ COMPATIBLE_IOCTL(TCSETA) COMPATIBLE_IOCTL(TCSETAW) COMPATIBLE_IOCTL(TCSETAF) COMPATIBLE_IOCTL(TCSBRK) -ULONG_IOCTL(TCSBRKP) COMPATIBLE_IOCTL(TCXONC) COMPATIBLE_IOCTL(TCFLSH) COMPATIBLE_IOCTL(TCGETS) @@ -1266,7 +936,6 @@ COMPATIBLE_IOCTL(TCSETSF) COMPATIBLE_IOCTL(TIOCLINUX) COMPATIBLE_IOCTL(TIOCSBRK) COMPATIBLE_IOCTL(TIOCCBRK) -ULONG_IOCTL(TIOCMIWAIT) COMPATIBLE_IOCTL(TIOCGICOUNT) /* Little t */ COMPATIBLE_IOCTL(TIOCGETD) @@ -1288,7 +957,6 @@ COMPATIBLE_IOCTL(TIOCSTI) COMPATIBLE_IOCTL(TIOCOUTQ) COMPATIBLE_IOCTL(TIOCSPGRP) COMPATIBLE_IOCTL(TIOCGPGRP) -ULONG_IOCTL(TIOCSCTTY) COMPATIBLE_IOCTL(TIOCGPTN) COMPATIBLE_IOCTL(TIOCSPTLCK) COMPATIBLE_IOCTL(TIOCSERGETLSR) @@ -1311,44 +979,11 @@ COMPATIBLE_IOCTL(FIGETBSZ) /* 'X' - originally XFS but some now in the VFS */ COMPATIBLE_IOCTL(FIFREEZE) COMPATIBLE_IOCTL(FITHAW) -/* RAID */ -COMPATIBLE_IOCTL(RAID_VERSION) -COMPATIBLE_IOCTL(GET_ARRAY_INFO) -COMPATIBLE_IOCTL(GET_DISK_INFO) -COMPATIBLE_IOCTL(PRINT_RAID_DEBUG) -COMPATIBLE_IOCTL(RAID_AUTORUN) -COMPATIBLE_IOCTL(CLEAR_ARRAY) -COMPATIBLE_IOCTL(ADD_NEW_DISK) -ULONG_IOCTL(HOT_REMOVE_DISK) -COMPATIBLE_IOCTL(SET_ARRAY_INFO) -COMPATIBLE_IOCTL(SET_DISK_INFO) -COMPATIBLE_IOCTL(WRITE_RAID_INFO) -COMPATIBLE_IOCTL(UNPROTECT_ARRAY) -COMPATIBLE_IOCTL(PROTECT_ARRAY) -ULONG_IOCTL(HOT_ADD_DISK) -ULONG_IOCTL(SET_DISK_FAULTY) -COMPATIBLE_IOCTL(RUN_ARRAY) -COMPATIBLE_IOCTL(STOP_ARRAY) -COMPATIBLE_IOCTL(STOP_ARRAY_RO) -COMPATIBLE_IOCTL(RESTART_ARRAY_RW) -COMPATIBLE_IOCTL(GET_BITMAP_FILE) -ULONG_IOCTL(SET_BITMAP_FILE) -/* Big K */ -COMPATIBLE_IOCTL(PIO_FONT) -COMPATIBLE_IOCTL(GIO_FONT) -COMPATIBLE_IOCTL(PIO_CMAP) -COMPATIBLE_IOCTL(GIO_CMAP) -ULONG_IOCTL(KDSIGACCEPT) COMPATIBLE_IOCTL(KDGETKEYCODE) COMPATIBLE_IOCTL(KDSETKEYCODE) -ULONG_IOCTL(KIOCSOUND) -ULONG_IOCTL(KDMKTONE) COMPATIBLE_IOCTL(KDGKBTYPE) -ULONG_IOCTL(KDSETMODE) COMPATIBLE_IOCTL(KDGETMODE) -ULONG_IOCTL(KDSKBMODE) COMPATIBLE_IOCTL(KDGKBMODE) -ULONG_IOCTL(KDSKBMETA) COMPATIBLE_IOCTL(KDGKBMETA) COMPATIBLE_IOCTL(KDGKBENT) COMPATIBLE_IOCTL(KDSKBENT) @@ -1358,15 +993,7 @@ COMPATIBLE_IOCTL(KDGKBDIACR) COMPATIBLE_IOCTL(KDSKBDIACR) COMPATIBLE_IOCTL(KDKBDREP) COMPATIBLE_IOCTL(KDGKBLED) -ULONG_IOCTL(KDSKBLED) COMPATIBLE_IOCTL(KDGETLED) -ULONG_IOCTL(KDSETLED) -COMPATIBLE_IOCTL(GIO_SCRNMAP) -COMPATIBLE_IOCTL(PIO_SCRNMAP) -COMPATIBLE_IOCTL(GIO_UNISCRNMAP) -COMPATIBLE_IOCTL(PIO_UNISCRNMAP) -COMPATIBLE_IOCTL(PIO_FONTRESET) -COMPATIBLE_IOCTL(PIO_UNIMAPCLR) #ifdef CONFIG_BLOCK /* Big S */ COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN) @@ -1378,20 +1005,6 @@ COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST) COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) #endif -/* Big V */ -COMPATIBLE_IOCTL(VT_SETMODE) -COMPATIBLE_IOCTL(VT_GETMODE) -COMPATIBLE_IOCTL(VT_GETSTATE) -COMPATIBLE_IOCTL(VT_OPENQRY) -ULONG_IOCTL(VT_ACTIVATE) -ULONG_IOCTL(VT_WAITACTIVE) -ULONG_IOCTL(VT_RELDISP) -ULONG_IOCTL(VT_DISALLOCATE) -COMPATIBLE_IOCTL(VT_RESIZE) -COMPATIBLE_IOCTL(VT_RESIZEX) -COMPATIBLE_IOCTL(VT_LOCKSWITCH) -COMPATIBLE_IOCTL(VT_UNLOCKSWITCH) -COMPATIBLE_IOCTL(VT_GETHIFONTMASK) /* Little p (/dev/rtc, /dev/envctrl, etc.) */ COMPATIBLE_IOCTL(RTC_AIE_ON) COMPATIBLE_IOCTL(RTC_AIE_OFF) @@ -1420,11 +1033,12 @@ COMPATIBLE_IOCTL(MTIOCTOP) /* Socket level stuff */ COMPATIBLE_IOCTL(FIOQSIZE) #ifdef CONFIG_BLOCK +/* loop */ +IGNORE_IOCTL(LOOP_CLR_FD) /* SG stuff */ COMPATIBLE_IOCTL(SG_SET_TIMEOUT) COMPATIBLE_IOCTL(SG_GET_TIMEOUT) COMPATIBLE_IOCTL(SG_EMULATED_HOST) -ULONG_IOCTL(SG_SET_TRANSFORM) COMPATIBLE_IOCTL(SG_GET_TRANSFORM) COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE) COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE) @@ -1478,8 +1092,6 @@ COMPATIBLE_IOCTL(PPPIOCGCHAN) /* PPPOX */ COMPATIBLE_IOCTL(PPPOEIOCSFWD) COMPATIBLE_IOCTL(PPPOEIOCDFWD) -/* LP */ -COMPATIBLE_IOCTL(LPGETSTATUS) /* ppdev */ COMPATIBLE_IOCTL(PPSETMODE) COMPATIBLE_IOCTL(PPRSTATUS) @@ -1661,8 +1273,6 @@ COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS) COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS) COMPATIBLE_IOCTL(OSS_GETVERSION) /* AUTOFS */ -ULONG_IOCTL(AUTOFS_IOC_READY) -ULONG_IOCTL(AUTOFS_IOC_FAIL) COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC) COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER) COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE) @@ -1755,30 +1365,11 @@ COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) -/* USB */ -COMPATIBLE_IOCTL(USBDEVFS_RESETEP) -COMPATIBLE_IOCTL(USBDEVFS_SETINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_SETCONFIGURATION) -COMPATIBLE_IOCTL(USBDEVFS_GETDRIVER) -COMPATIBLE_IOCTL(USBDEVFS_DISCARDURB) -COMPATIBLE_IOCTL(USBDEVFS_CLAIMINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_RELEASEINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_CONNECTINFO) -COMPATIBLE_IOCTL(USBDEVFS_HUB_PORTINFO) -COMPATIBLE_IOCTL(USBDEVFS_RESET) -COMPATIBLE_IOCTL(USBDEVFS_SUBMITURB32) -COMPATIBLE_IOCTL(USBDEVFS_REAPURB32) -COMPATIBLE_IOCTL(USBDEVFS_REAPURBNDELAY32) -COMPATIBLE_IOCTL(USBDEVFS_CLEAR_HALT) /* NBD */ -ULONG_IOCTL(NBD_SET_SOCK) -ULONG_IOCTL(NBD_SET_BLKSIZE) -ULONG_IOCTL(NBD_SET_SIZE) COMPATIBLE_IOCTL(NBD_DO_IT) COMPATIBLE_IOCTL(NBD_CLEAR_SOCK) COMPATIBLE_IOCTL(NBD_CLEAR_QUE) COMPATIBLE_IOCTL(NBD_PRINT_DEBUG) -ULONG_IOCTL(NBD_SET_SIZE_BLOCKS) COMPATIBLE_IOCTL(NBD_DISCONNECT) /* i2c */ COMPATIBLE_IOCTL(I2C_SLAVE) @@ -1878,42 +1469,6 @@ COMPATIBLE_IOCTL(JSIOCGAXES) COMPATIBLE_IOCTL(JSIOCGBUTTONS) COMPATIBLE_IOCTL(JSIOCGNAME(0)) -/* now things that need handlers */ -#ifdef CONFIG_BLOCK -HANDLE_IOCTL(SG_IO,sg_ioctl_trans) -HANDLE_IOCTL(SG_GET_REQUEST_TABLE, sg_grt_trans) -#endif -HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans) -HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans) -HANDLE_IOCTL(PPPIOCSPASS32, ppp_sock_fprog_ioctl_trans) -HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans) -#ifdef CONFIG_BLOCK -HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans) -HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans) -#endif -#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) -HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout) -#ifdef CONFIG_VT -HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl) -HANDLE_IOCTL(GIO_FONTX, do_fontx_ioctl) -HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl) -HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl) -HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl) -#endif -/* One SMB ioctl needs translations. */ -#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t) -HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid) -/* block stuff */ -#ifdef CONFIG_BLOCK -/* loop */ -IGNORE_IOCTL(LOOP_CLR_FD) -/* Raw devices */ -HANDLE_IOCTL(RAW_SETBIND, raw_ioctl) -HANDLE_IOCTL(RAW_GETBIND, raw_ioctl) -#endif -/* Serial */ -HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl) -HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl) #ifdef TIOCGLTC COMPATIBLE_IOCTL(TIOCGLTC) COMPATIBLE_IOCTL(TIOCSLTC) @@ -1928,39 +1483,6 @@ COMPATIBLE_IOCTL(TIOCSLTC) COMPATIBLE_IOCTL(TIOCSTART) COMPATIBLE_IOCTL(TIOCSTOP) #endif -/* Usbdevfs */ -HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) -HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) -HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal) -COMPATIBLE_IOCTL(USBDEVFS_IOCTL32) -/* i2c */ -HANDLE_IOCTL(I2C_FUNCS, w_long) -HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl) -HANDLE_IOCTL(I2C_SMBUS, do_i2c_smbus_ioctl) -/* Not implemented in the native kernel */ -HANDLE_IOCTL(RTC_IRQP_READ32, rtc_ioctl) -HANDLE_IOCTL(RTC_IRQP_SET32, rtc_ioctl) -HANDLE_IOCTL(RTC_EPOCH_READ32, rtc_ioctl) -HANDLE_IOCTL(RTC_EPOCH_SET32, rtc_ioctl) - -/* dvb */ -HANDLE_IOCTL(VIDEO_GET_EVENT, do_video_get_event) -HANDLE_IOCTL(VIDEO_STILLPICTURE, do_video_stillpicture) -HANDLE_IOCTL(VIDEO_SET_SPU_PALETTE, do_video_set_spu_palette) - -/* parport */ -COMPATIBLE_IOCTL(LPTIME) -COMPATIBLE_IOCTL(LPCHAR) -COMPATIBLE_IOCTL(LPABORTOPEN) -COMPATIBLE_IOCTL(LPCAREFUL) -COMPATIBLE_IOCTL(LPWAIT) -COMPATIBLE_IOCTL(LPSETIRQ) -COMPATIBLE_IOCTL(LPGETSTATUS) -COMPATIBLE_IOCTL(LPGETSTATUS) -COMPATIBLE_IOCTL(LPRESET) -/*LPGETSTATS not implemented, but no kernels seem to compile it in anyways*/ -COMPATIBLE_IOCTL(LPGETFLAGS) -HANDLE_IOCTL(LPSETTIMEOUT, lp_timeout_trans) /* fat 'r' ioctls. These are handled by fat with ->compat_ioctl, but we don't want warnings on other file systems. So declare @@ -1988,12 +1510,110 @@ IGNORE_IOCTL(FBIOGCURSOR32) #endif }; -#define IOCTL_HASHSIZE 256 -static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE]; - -static inline unsigned long ioctl32_hash(unsigned long cmd) +/* + * Convert common ioctl arguments based on their command number + * + * Please do not add any code in here. Instead, implement + * a compat_ioctl operation in the place that handleÑ• the + * ioctl for the native case. + */ +static long do_ioctl_trans(int fd, unsigned int cmd, + unsigned long arg, struct file *file) { - return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE; + void __user *argp = compat_ptr(arg); + + switch (cmd) { + case PPPIOCGIDLE32: + return ppp_gidle(fd, cmd, argp); + case PPPIOCSCOMPRESS32: + return ppp_scompress(fd, cmd, argp); + case PPPIOCSPASS32: + case PPPIOCSACTIVE32: + return ppp_sock_fprog_ioctl_trans(fd, cmd, argp); +#ifdef CONFIG_BLOCK + case SG_IO: + return sg_ioctl_trans(fd, cmd, argp); + case SG_GET_REQUEST_TABLE: + return sg_grt_trans(fd, cmd, argp); + case MTIOCGET32: + case MTIOCPOS32: + return mt_ioctl_trans(fd, cmd, argp); + /* Raw devices */ + case RAW_SETBIND: + case RAW_GETBIND: + return raw_ioctl(fd, cmd, argp); +#endif +#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) + case AUTOFS_IOC_SETTIMEOUT32: + return ioc_settimeout(fd, cmd, argp); + /* One SMB ioctl needs translations. */ +#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t) + case SMB_IOC_GETMOUNTUID_32: + return do_smb_getmountuid(fd, cmd, argp); + /* Serial */ + case TIOCGSERIAL: + case TIOCSSERIAL: + return serial_struct_ioctl(fd, cmd, argp); + /* i2c */ + case I2C_FUNCS: + return w_long(fd, cmd, argp); + case I2C_RDWR: + return do_i2c_rdwr_ioctl(fd, cmd, argp); + case I2C_SMBUS: + return do_i2c_smbus_ioctl(fd, cmd, argp); + /* Not implemented in the native kernel */ + case RTC_IRQP_READ32: + case RTC_IRQP_SET32: + case RTC_EPOCH_READ32: + case RTC_EPOCH_SET32: + return rtc_ioctl(fd, cmd, argp); + + /* dvb */ + case VIDEO_GET_EVENT: + return do_video_get_event(fd, cmd, argp); + case VIDEO_STILLPICTURE: + return do_video_stillpicture(fd, cmd, argp); + case VIDEO_SET_SPU_PALETTE: + return do_video_set_spu_palette(fd, cmd, argp); + } + + /* + * These take an integer instead of a pointer as 'arg', + * so we must not do a compat_ptr() translation. + */ + switch (cmd) { + /* Big T */ + case TCSBRKP: + case TIOCMIWAIT: + case TIOCSCTTY: + /* RAID */ + case HOT_REMOVE_DISK: + case HOT_ADD_DISK: + case SET_DISK_FAULTY: + case SET_BITMAP_FILE: + /* Big K */ + case KDSIGACCEPT: + case KIOCSOUND: + case KDMKTONE: + case KDSETMODE: + case KDSKBMODE: + case KDSKBMETA: + case KDSKBLED: + case KDSETLED: + /* SG stuff */ + case SG_SET_TRANSFORM: + /* AUTOFS */ + case AUTOFS_IOC_READY: + case AUTOFS_IOC_FAIL: + /* NBD */ + case NBD_SET_SOCK: + case NBD_SET_BLKSIZE: + case NBD_SET_SIZE: + case NBD_SET_SIZE_BLOCKS: + return do_vfs_ioctl(file, fd, cmd, arg); + } + + return -ENOIOCTLCMD; } static void compat_ioctl_error(struct file *filp, unsigned int fd, @@ -2025,12 +1645,33 @@ static void compat_ioctl_error(struct file *filp, unsigned int fd, free_page((unsigned long)path); } +static int compat_ioctl_check_table(unsigned int xcmd) +{ + int i; + const int max = ARRAY_SIZE(ioctl_pointer) - 1; + + BUILD_BUG_ON(max >= (1 << 16)); + + /* guess initial offset into table, assuming a + normalized distribution */ + i = ((xcmd >> 16) * max) >> 16; + + /* do linear search up first, until greater or equal */ + while (ioctl_pointer[i] < xcmd && i < max) + i++; + + /* then do linear search down */ + while (ioctl_pointer[i] > xcmd && i > 0) + i--; + + return ioctl_pointer[i] == xcmd; +} + asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct file *filp; int error = -EBADF; - struct ioctl_trans *t; int fput_needed; filp = fget_light(fd, &fput_needed); @@ -2058,7 +1699,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, #if defined(CONFIG_IA64) || defined(CONFIG_X86_64) case FS_IOC_RESVSP_32: case FS_IOC_RESVSP64_32: - error = compat_ioctl_preallocate(filp, arg); + error = compat_ioctl_preallocate(filp, compat_ptr(arg)); goto out_fput; #else case FS_IOC_RESVSP: @@ -2087,12 +1728,11 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, break; } - for (t = ioctl32_hash_table[ioctl32_hash(cmd)]; t; t = t->next) { - if (t->cmd == cmd) - goto found_handler; - } + if (compat_ioctl_check_table(XFORM(cmd))) + goto found_handler; - { + error = do_ioctl_trans(fd, cmd, arg, filp); + if (error == -ENOIOCTLCMD) { static int count; if (++count <= 50) @@ -2103,13 +1743,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, goto out_fput; found_handler: - if (t->handler) { - lock_kernel(); - error = t->handler(fd, cmd, arg, filp); - unlock_kernel(); - goto out_fput; - } - + arg = (unsigned long)compat_ptr(arg); do_ioctl: error = do_vfs_ioctl(filp, fd, cmd, arg); out_fput: @@ -2118,35 +1752,22 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, return error; } -static void ioctl32_insert_translation(struct ioctl_trans *trans) +static int __init init_sys32_ioctl_cmp(const void *p, const void *q) { - unsigned long hash; - struct ioctl_trans *t; - - hash = ioctl32_hash (trans->cmd); - if (!ioctl32_hash_table[hash]) - ioctl32_hash_table[hash] = trans; - else { - t = ioctl32_hash_table[hash]; - while (t->next) - t = t->next; - trans->next = NULL; - t->next = trans; - } + unsigned int a, b; + a = *(unsigned int *)p; + b = *(unsigned int *)q; + if (a > b) + return 1; + if (a < b) + return -1; + return 0; } static int __init init_sys32_ioctl(void) { - int i; - - for (i = 0; i < ARRAY_SIZE(ioctl_start); i++) { - if (ioctl_start[i].next) { - printk("ioctl translation %d bad\n",i); - return -1; - } - - ioctl32_insert_translation(&ioctl_start[i]); - } + sort(ioctl_pointer, ARRAY_SIZE(ioctl_pointer), sizeof(*ioctl_pointer), + init_sys32_ioctl_cmp, NULL); return 0; } __initcall(init_sys32_ioctl); diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 0d23b52dd22cbfef0d0f29cc437ff527135f2325..b486169f42bf997e9e620f12996f7711070140e2 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -32,7 +32,9 @@ static struct vfsmount *debugfs_mount; static int debugfs_mount_count; static bool debugfs_registered; -static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev) +static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev, + void *data, const struct file_operations *fops) + { struct inode *inode = new_inode(sb); @@ -44,14 +46,18 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d init_special_inode(inode, mode, dev); break; case S_IFREG: - inode->i_fop = &debugfs_file_operations; + inode->i_fop = fops ? fops : &debugfs_file_operations; + inode->i_private = data; break; case S_IFLNK: inode->i_op = &debugfs_link_operations; + inode->i_fop = fops; + inode->i_private = data; break; case S_IFDIR: inode->i_op = &simple_dir_inode_operations; - inode->i_fop = &simple_dir_operations; + inode->i_fop = fops ? fops : &simple_dir_operations; + inode->i_private = data; /* directory inodes start off with i_nlink == 2 * (for "." entry) */ @@ -64,7 +70,8 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d /* SMP-safe */ static int debugfs_mknod(struct inode *dir, struct dentry *dentry, - int mode, dev_t dev) + int mode, dev_t dev, void *data, + const struct file_operations *fops) { struct inode *inode; int error = -EPERM; @@ -72,7 +79,7 @@ static int debugfs_mknod(struct inode *dir, struct dentry *dentry, if (dentry->d_inode) return -EEXIST; - inode = debugfs_get_inode(dir->i_sb, mode, dev); + inode = debugfs_get_inode(dir->i_sb, mode, dev, data, fops); if (inode) { d_instantiate(dentry, inode); dget(dentry); @@ -81,12 +88,13 @@ static int debugfs_mknod(struct inode *dir, struct dentry *dentry, return error; } -static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode, + void *data, const struct file_operations *fops) { int res; mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; - res = debugfs_mknod(dir, dentry, mode, 0); + res = debugfs_mknod(dir, dentry, mode, 0, data, fops); if (!res) { inc_nlink(dir); fsnotify_mkdir(dir, dentry); @@ -94,18 +102,20 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) return res; } -static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode) +static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode, + void *data, const struct file_operations *fops) { mode = (mode & S_IALLUGO) | S_IFLNK; - return debugfs_mknod(dir, dentry, mode, 0); + return debugfs_mknod(dir, dentry, mode, 0, data, fops); } -static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode) +static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode, + void *data, const struct file_operations *fops) { int res; mode = (mode & S_IALLUGO) | S_IFREG; - res = debugfs_mknod(dir, dentry, mode, 0); + res = debugfs_mknod(dir, dentry, mode, 0, data, fops); if (!res) fsnotify_create(dir, dentry); return res; @@ -139,7 +149,9 @@ static struct file_system_type debug_fs_type = { static int debugfs_create_by_name(const char *name, mode_t mode, struct dentry *parent, - struct dentry **dentry) + struct dentry **dentry, + void *data, + const struct file_operations *fops) { int error = 0; @@ -164,13 +176,16 @@ static int debugfs_create_by_name(const char *name, mode_t mode, if (!IS_ERR(*dentry)) { switch (mode & S_IFMT) { case S_IFDIR: - error = debugfs_mkdir(parent->d_inode, *dentry, mode); + error = debugfs_mkdir(parent->d_inode, *dentry, mode, + data, fops); break; case S_IFLNK: - error = debugfs_link(parent->d_inode, *dentry, mode); + error = debugfs_link(parent->d_inode, *dentry, mode, + data, fops); break; default: - error = debugfs_create(parent->d_inode, *dentry, mode); + error = debugfs_create(parent->d_inode, *dentry, mode, + data, fops); break; } dput(*dentry); @@ -221,19 +236,13 @@ struct dentry *debugfs_create_file(const char *name, mode_t mode, if (error) goto exit; - error = debugfs_create_by_name(name, mode, parent, &dentry); + error = debugfs_create_by_name(name, mode, parent, &dentry, + data, fops); if (error) { dentry = NULL; simple_release_fs(&debugfs_mount, &debugfs_mount_count); goto exit; } - - if (dentry->d_inode) { - if (data) - dentry->d_inode->i_private = data; - if (fops) - dentry->d_inode->i_fop = fops; - } exit: return dentry; } diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index d5f8c96964be9a25f8235c869472b95a77ebbecc..8882ecc0f1bfbec879c7b9c27795ac8b5dd9f63a 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -517,11 +517,23 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty) struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number) { + struct dentry *dentry; + struct tty_struct *tty; + BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); + /* Ensure dentry has not been deleted by devpts_pty_kill() */ + dentry = d_find_alias(pts_inode); + if (!dentry) + return NULL; + + tty = NULL; if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) - return (struct tty_struct *)pts_inode->i_private; - return NULL; + tty = (struct tty_struct *)pts_inode->i_private; + + dput(dentry); + + return tty; } void devpts_pty_kill(struct tty_struct *tty) diff --git a/fs/dlm/config.c b/fs/dlm/config.c index fd9859f92fad3e05ed2ab372d226d6e61fdedfb8..0df243850818340c4423fa56ae9264151285c0a1 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c @@ -410,10 +410,10 @@ static struct config_group *make_cluster(struct config_group *g, struct dlm_comms *cms = NULL; void *gps = NULL; - cl = kzalloc(sizeof(struct dlm_cluster), GFP_KERNEL); - gps = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL); - sps = kzalloc(sizeof(struct dlm_spaces), GFP_KERNEL); - cms = kzalloc(sizeof(struct dlm_comms), GFP_KERNEL); + cl = kzalloc(sizeof(struct dlm_cluster), GFP_NOFS); + gps = kcalloc(3, sizeof(struct config_group *), GFP_NOFS); + sps = kzalloc(sizeof(struct dlm_spaces), GFP_NOFS); + cms = kzalloc(sizeof(struct dlm_comms), GFP_NOFS); if (!cl || !gps || !sps || !cms) goto fail; @@ -482,9 +482,9 @@ static struct config_group *make_space(struct config_group *g, const char *name) struct dlm_nodes *nds = NULL; void *gps = NULL; - sp = kzalloc(sizeof(struct dlm_space), GFP_KERNEL); - gps = kcalloc(2, sizeof(struct config_group *), GFP_KERNEL); - nds = kzalloc(sizeof(struct dlm_nodes), GFP_KERNEL); + sp = kzalloc(sizeof(struct dlm_space), GFP_NOFS); + gps = kcalloc(2, sizeof(struct config_group *), GFP_NOFS); + nds = kzalloc(sizeof(struct dlm_nodes), GFP_NOFS); if (!sp || !gps || !nds) goto fail; @@ -536,7 +536,7 @@ static struct config_item *make_comm(struct config_group *g, const char *name) { struct dlm_comm *cm; - cm = kzalloc(sizeof(struct dlm_comm), GFP_KERNEL); + cm = kzalloc(sizeof(struct dlm_comm), GFP_NOFS); if (!cm) return ERR_PTR(-ENOMEM); @@ -569,7 +569,7 @@ static struct config_item *make_node(struct config_group *g, const char *name) struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent); struct dlm_node *nd; - nd = kzalloc(sizeof(struct dlm_node), GFP_KERNEL); + nd = kzalloc(sizeof(struct dlm_node), GFP_NOFS); if (!nd) return ERR_PTR(-ENOMEM); @@ -705,7 +705,7 @@ static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len) if (cm->addr_count >= DLM_MAX_ADDR_COUNT) return -ENOSPC; - addr = kzalloc(sizeof(*addr), GFP_KERNEL); + addr = kzalloc(sizeof(*addr), GFP_NOFS); if (!addr) return -ENOMEM; @@ -868,7 +868,7 @@ int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out, ids_count = sp->members_count; - ids = kcalloc(ids_count, sizeof(int), GFP_KERNEL); + ids = kcalloc(ids_count, sizeof(int), GFP_NOFS); if (!ids) { rv = -ENOMEM; goto out; @@ -886,7 +886,7 @@ int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out, if (!new_count) goto out_ids; - new = kcalloc(new_count, sizeof(int), GFP_KERNEL); + new = kcalloc(new_count, sizeof(int), GFP_NOFS); if (!new) { kfree(ids); rv = -ENOMEM; diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c index 1c8bb8c3a82efd92519c16e0a01088e9bf9bf5bf..375a2359b3bfa526fd6c4950a024dfd83ce98d56 100644 --- a/fs/dlm/debug_fs.c +++ b/fs/dlm/debug_fs.c @@ -404,7 +404,7 @@ static void *table_seq_start(struct seq_file *seq, loff_t *pos) if (bucket >= ls->ls_rsbtbl_size) return NULL; - ri = kzalloc(sizeof(struct rsbtbl_iter), GFP_KERNEL); + ri = kzalloc(sizeof(struct rsbtbl_iter), GFP_NOFS); if (!ri) return NULL; if (n == 0) diff --git a/fs/dlm/dir.c b/fs/dlm/dir.c index c4dfa1dcc86f32d43469f5122c22ade5516544a5..7b84c1dbc82ebeaec0a42846537524c73d1db13f 100644 --- a/fs/dlm/dir.c +++ b/fs/dlm/dir.c @@ -49,8 +49,7 @@ static struct dlm_direntry *get_free_de(struct dlm_ls *ls, int len) spin_unlock(&ls->ls_recover_list_lock); if (!found) - de = kzalloc(sizeof(struct dlm_direntry) + len, - ls->ls_allocation); + de = kzalloc(sizeof(struct dlm_direntry) + len, GFP_NOFS); return de; } @@ -212,7 +211,7 @@ int dlm_recover_directory(struct dlm_ls *ls) dlm_dir_clear(ls); - last_name = kmalloc(DLM_RESNAME_MAXLEN, ls->ls_allocation); + last_name = kmalloc(DLM_RESNAME_MAXLEN, GFP_NOFS); if (!last_name) goto out; @@ -323,7 +322,7 @@ static int get_entry(struct dlm_ls *ls, int nodeid, char *name, if (namelen > DLM_RESNAME_MAXLEN) return -EINVAL; - de = kzalloc(sizeof(struct dlm_direntry) + namelen, ls->ls_allocation); + de = kzalloc(sizeof(struct dlm_direntry) + namelen, GFP_NOFS); if (!de) return -ENOMEM; diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index d01ca0a711db15de2f1d57854b9acb875e9c63e0..826d3dc6e0ab50db977500844ddc62cdcede83ad 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h @@ -473,7 +473,6 @@ struct dlm_ls { int ls_low_nodeid; int ls_total_weight; int *ls_node_array; - gfp_t ls_allocation; struct dlm_rsb ls_stub_rsb; /* for returning errors */ struct dlm_lkb ls_stub_lkb; /* for returning errors */ diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index eb507c453c5ff7ca221f933619a085461bec3300..9c0c1db1e10534aa2a44b9634ff9790859d542cc 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -2689,7 +2689,7 @@ static int _create_message(struct dlm_ls *ls, int mb_len, pass into lowcomms_commit and a message buffer (mb) that we write our data into */ - mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, ls->ls_allocation, &mb); + mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_NOFS, &mb); if (!mh) return -ENOBUFS; @@ -4512,7 +4512,7 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, } if (flags & DLM_LKF_VALBLK) { - ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_KERNEL); + ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_NOFS); if (!ua->lksb.sb_lvbptr) { kfree(ua); __put_lkb(ls, lkb); @@ -4582,7 +4582,7 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, ua = lkb->lkb_ua; if (flags & DLM_LKF_VALBLK && !ua->lksb.sb_lvbptr) { - ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_KERNEL); + ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_NOFS); if (!ua->lksb.sb_lvbptr) { error = -ENOMEM; goto out_put; diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index d489fcc86713de1d0484902d6e7f911b57377cd0..c010ecfc0d295525de2455b02bf8a94dd8dbedea 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -430,7 +430,7 @@ static int new_lockspace(const char *name, int namelen, void **lockspace, error = -ENOMEM; - ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL); + ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_NOFS); if (!ls) goto out; memcpy(ls->ls_name, name, namelen); @@ -443,11 +443,6 @@ static int new_lockspace(const char *name, int namelen, void **lockspace, if (flags & DLM_LSFL_TIMEWARN) set_bit(LSFL_TIMEWARN, &ls->ls_flags); - if (flags & DLM_LSFL_FS) - ls->ls_allocation = GFP_NOFS; - else - ls->ls_allocation = GFP_KERNEL; - /* ls_exflags are forced to match among nodes, and we don't need to require all nodes to have some flags set */ ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS | @@ -456,7 +451,7 @@ static int new_lockspace(const char *name, int namelen, void **lockspace, size = dlm_config.ci_rsbtbl_size; ls->ls_rsbtbl_size = size; - ls->ls_rsbtbl = kmalloc(sizeof(struct dlm_rsbtable) * size, GFP_KERNEL); + ls->ls_rsbtbl = kmalloc(sizeof(struct dlm_rsbtable) * size, GFP_NOFS); if (!ls->ls_rsbtbl) goto out_lsfree; for (i = 0; i < size; i++) { @@ -468,7 +463,7 @@ static int new_lockspace(const char *name, int namelen, void **lockspace, size = dlm_config.ci_lkbtbl_size; ls->ls_lkbtbl_size = size; - ls->ls_lkbtbl = kmalloc(sizeof(struct dlm_lkbtable) * size, GFP_KERNEL); + ls->ls_lkbtbl = kmalloc(sizeof(struct dlm_lkbtable) * size, GFP_NOFS); if (!ls->ls_lkbtbl) goto out_rsbfree; for (i = 0; i < size; i++) { @@ -480,7 +475,7 @@ static int new_lockspace(const char *name, int namelen, void **lockspace, size = dlm_config.ci_dirtbl_size; ls->ls_dirtbl_size = size; - ls->ls_dirtbl = kmalloc(sizeof(struct dlm_dirtable) * size, GFP_KERNEL); + ls->ls_dirtbl = kmalloc(sizeof(struct dlm_dirtable) * size, GFP_NOFS); if (!ls->ls_dirtbl) goto out_lkbfree; for (i = 0; i < size; i++) { @@ -527,7 +522,7 @@ static int new_lockspace(const char *name, int namelen, void **lockspace, mutex_init(&ls->ls_requestqueue_mutex); mutex_init(&ls->ls_clear_proc_locks); - ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL); + ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS); if (!ls->ls_recover_buf) goto out_dirfree; diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 70736eb4b51652e9ad64078180ffc8c154265df4..52cab160893ce0d095e771dd1abe72a4b170162f 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -1060,7 +1060,7 @@ static void init_local(void) if (dlm_our_addr(&sas, i)) break; - addr = kmalloc(sizeof(*addr), GFP_KERNEL); + addr = kmalloc(sizeof(*addr), GFP_NOFS); if (!addr) break; memcpy(addr, &sas, sizeof(*addr)); @@ -1099,7 +1099,7 @@ static int sctp_listen_for_all(void) struct sockaddr_storage localaddr; struct sctp_event_subscribe subscribe; int result = -EINVAL, num = 1, i, addr_len; - struct connection *con = nodeid2con(0, GFP_KERNEL); + struct connection *con = nodeid2con(0, GFP_NOFS); int bufsize = NEEDED_RMEM; if (!con) @@ -1171,7 +1171,7 @@ out: static int tcp_listen_for_all(void) { struct socket *sock = NULL; - struct connection *con = nodeid2con(0, GFP_KERNEL); + struct connection *con = nodeid2con(0, GFP_NOFS); int result = -EINVAL; if (!con) diff --git a/fs/dlm/member.c b/fs/dlm/member.c index b128775913b29d6b43aeeec34910af6f9583ce9a..84f70bfb0baf4dfe4e19fee23238783965a637cc 100644 --- a/fs/dlm/member.c +++ b/fs/dlm/member.c @@ -48,7 +48,7 @@ static int dlm_add_member(struct dlm_ls *ls, int nodeid) struct dlm_member *memb; int w, error; - memb = kzalloc(sizeof(struct dlm_member), ls->ls_allocation); + memb = kzalloc(sizeof(struct dlm_member), GFP_NOFS); if (!memb) return -ENOMEM; @@ -143,7 +143,7 @@ static void make_member_array(struct dlm_ls *ls) ls->ls_total_weight = total; - array = kmalloc(sizeof(int) * total, ls->ls_allocation); + array = kmalloc(sizeof(int) * total, GFP_NOFS); if (!array) return; @@ -226,7 +226,7 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out) continue; log_debug(ls, "new nodeid %d is a re-added member", rv->new[i]); - memb = kzalloc(sizeof(struct dlm_member), ls->ls_allocation); + memb = kzalloc(sizeof(struct dlm_member), GFP_NOFS); if (!memb) return -ENOMEM; memb->nodeid = rv->new[i]; @@ -341,7 +341,7 @@ int dlm_ls_start(struct dlm_ls *ls) int *ids = NULL, *new = NULL; int error, ids_count = 0, new_count = 0; - rv = kzalloc(sizeof(struct dlm_recover), ls->ls_allocation); + rv = kzalloc(sizeof(struct dlm_recover), GFP_NOFS); if (!rv) return -ENOMEM; diff --git a/fs/dlm/memory.c b/fs/dlm/memory.c index c1775b84ebab2e552e4a4a04e5c8491f1fe99e3a..8e0d00db004f8b8fd71cc75b3958c215beb836bd 100644 --- a/fs/dlm/memory.c +++ b/fs/dlm/memory.c @@ -39,7 +39,7 @@ char *dlm_allocate_lvb(struct dlm_ls *ls) { char *p; - p = kzalloc(ls->ls_lvblen, ls->ls_allocation); + p = kzalloc(ls->ls_lvblen, GFP_NOFS); return p; } @@ -57,7 +57,7 @@ struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls, int namelen) DLM_ASSERT(namelen <= DLM_RESNAME_MAXLEN,); - r = kzalloc(sizeof(*r) + namelen, ls->ls_allocation); + r = kzalloc(sizeof(*r) + namelen, GFP_NOFS); return r; } @@ -72,7 +72,7 @@ struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls) { struct dlm_lkb *lkb; - lkb = kmem_cache_zalloc(lkb_cache, ls->ls_allocation); + lkb = kmem_cache_zalloc(lkb_cache, GFP_NOFS); return lkb; } diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c index 55ea369f43a9f0d153ca769074b89e71d52082cf..052095cd592f3787ed20f525e1c7c08e0e30378b 100644 --- a/fs/dlm/netlink.c +++ b/fs/dlm/netlink.c @@ -26,7 +26,7 @@ static int prepare_data(u8 cmd, struct sk_buff **skbp, size_t size) struct sk_buff *skb; void *data; - skb = genlmsg_new(size, GFP_KERNEL); + skb = genlmsg_new(size, GFP_NOFS); if (!skb) return -ENOMEM; diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c index b540aa5d1f61edf80580a2f360aefd153c3f9a17..b5f89aef3b29c88a1447201504a797eb16e93dcb 100644 --- a/fs/dlm/plock.c +++ b/fs/dlm/plock.c @@ -82,7 +82,7 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file, if (!ls) return -EINVAL; - xop = kzalloc(sizeof(*xop), GFP_KERNEL); + xop = kzalloc(sizeof(*xop), GFP_NOFS); if (!xop) { rv = -ENOMEM; goto out; @@ -211,7 +211,7 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file, if (!ls) return -EINVAL; - op = kzalloc(sizeof(*op), GFP_KERNEL); + op = kzalloc(sizeof(*op), GFP_NOFS); if (!op) { rv = -ENOMEM; goto out; @@ -266,7 +266,7 @@ int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file, if (!ls) return -EINVAL; - op = kzalloc(sizeof(*op), GFP_KERNEL); + op = kzalloc(sizeof(*op), GFP_NOFS); if (!op) { rv = -ENOMEM; goto out; diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index 67522c268c14972d20fb9825de128ff66aa2b2a9..3c83a49a48a3c6d464a779cf3929c6f670073d08 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c @@ -38,7 +38,7 @@ static int create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len, char *mb; int mb_len = sizeof(struct dlm_rcom) + len; - mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, ls->ls_allocation, &mb); + mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_NOFS, &mb); if (!mh) { log_print("create_rcom to %d type %d len %d ENOBUFS", to_nodeid, type, len); diff --git a/fs/dlm/requestqueue.c b/fs/dlm/requestqueue.c index 7a2307c08911101e9f82b99e0c6bad22c03a6e24..a44fa22890e1dd06797ae5e43e77a86c0cf4ca63 100644 --- a/fs/dlm/requestqueue.c +++ b/fs/dlm/requestqueue.c @@ -35,7 +35,7 @@ void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_message *ms) struct rq_entry *e; int length = ms->m_header.h_length - sizeof(struct dlm_message); - e = kmalloc(sizeof(struct rq_entry) + length, ls->ls_allocation); + e = kmalloc(sizeof(struct rq_entry) + length, GFP_NOFS); if (!e) { log_print("dlm_add_requestqueue: out of memory len %d", length); return; diff --git a/fs/dlm/user.c b/fs/dlm/user.c index ebce994ab0b717253a0bfa98230c80cefde397d2..e73a4bb572aa2de896c3e493bf7545f8f2358434 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c @@ -267,7 +267,7 @@ static int device_user_lock(struct dlm_user_proc *proc, goto out; } - ua = kzalloc(sizeof(struct dlm_user_args), GFP_KERNEL); + ua = kzalloc(sizeof(struct dlm_user_args), GFP_NOFS); if (!ua) goto out; ua->proc = proc; @@ -307,7 +307,7 @@ static int device_user_unlock(struct dlm_user_proc *proc, if (!ls) return -ENOENT; - ua = kzalloc(sizeof(struct dlm_user_args), GFP_KERNEL); + ua = kzalloc(sizeof(struct dlm_user_args), GFP_NOFS); if (!ua) goto out; ua->proc = proc; @@ -352,7 +352,7 @@ static int dlm_device_register(struct dlm_ls *ls, char *name) error = -ENOMEM; len = strlen(name) + strlen(name_prefix) + 2; - ls->ls_device.name = kzalloc(len, GFP_KERNEL); + ls->ls_device.name = kzalloc(len, GFP_NOFS); if (!ls->ls_device.name) goto fail; @@ -520,7 +520,7 @@ static ssize_t device_write(struct file *file, const char __user *buf, #endif return -EINVAL; - kbuf = kzalloc(count + 1, GFP_KERNEL); + kbuf = kzalloc(count + 1, GFP_NOFS); if (!kbuf) return -ENOMEM; @@ -546,7 +546,7 @@ static ssize_t device_write(struct file *file, const char __user *buf, /* add 1 after namelen so that the name string is terminated */ kbuf = kzalloc(sizeof(struct dlm_write_request) + namelen + 1, - GFP_KERNEL); + GFP_NOFS); if (!kbuf) { kfree(k32buf); return -ENOMEM; @@ -648,7 +648,7 @@ static int device_open(struct inode *inode, struct file *file) if (!ls) return -ENOENT; - proc = kzalloc(sizeof(struct dlm_user_proc), GFP_KERNEL); + proc = kzalloc(sizeof(struct dlm_user_proc), GFP_NOFS); if (!proc) { dlm_put_lockspace(ls); return -ENOMEM; diff --git a/fs/exofs/Kbuild b/fs/exofs/Kbuild index cc2d22db119c4a9e4d74b5b8e369fec5750d8868..2d0f757fda3e499986c0a3ce37936bd69a4125ce 100644 --- a/fs/exofs/Kbuild +++ b/fs/exofs/Kbuild @@ -12,5 +12,5 @@ # Kbuild - Gets included from the Kernels Makefile and build system # -exofs-y := osd.o inode.o file.o symlink.o namei.o dir.o super.o +exofs-y := ios.o inode.o file.o symlink.o namei.o dir.o super.o obj-$(CONFIG_EXOFS_FS) += exofs.o diff --git a/fs/exofs/common.h b/fs/exofs/common.h index c6718e4817feab5e56a2903b409493a458d3de84..b1b178e61718a5a7cee88ee7e2083b9fa5f3a3bd 100644 --- a/fs/exofs/common.h +++ b/fs/exofs/common.h @@ -49,6 +49,7 @@ #define EXOFS_MIN_PID 0x10000 /* Smallest partition ID */ #define EXOFS_OBJ_OFF 0x10000 /* offset for objects */ #define EXOFS_SUPER_ID 0x10000 /* object ID for on-disk superblock */ +#define EXOFS_DEVTABLE_ID 0x10001 /* object ID for on-disk device table */ #define EXOFS_ROOT_ID 0x10002 /* object ID for root directory */ /* exofs Application specific page/attribute */ @@ -78,17 +79,67 @@ enum { #define EXOFS_SUPER_MAGIC 0x5DF5 /* - * The file system control block - stored in an object's data (mainly, the one - * with ID EXOFS_SUPER_ID). This is where the in-memory superblock is stored - * on disk. Right now it just has a magic value, which is basically a sanity - * check on our ability to communicate with the object store. + * The file system control block - stored in object EXOFS_SUPER_ID's data. + * This is where the in-memory superblock is stored on disk. */ +enum {EXOFS_FSCB_VER = 1, EXOFS_DT_VER = 1}; struct exofs_fscb { __le64 s_nextid; /* Highest object ID used */ - __le32 s_numfiles; /* Number of files on fs */ + __le64 s_numfiles; /* Number of files on fs */ + __le32 s_version; /* == EXOFS_FSCB_VER */ __le16 s_magic; /* Magic signature */ __le16 s_newfs; /* Non-zero if this is a new fs */ -}; + + /* From here on it's a static part, only written by mkexofs */ + __le64 s_dev_table_oid; /* Resurved, not used */ + __le64 s_dev_table_count; /* == 0 means no dev_table */ +} __packed; + +/* + * Describes the raid used in the FS. It is part of the device table. + * This here is taken from the pNFS-objects definition. In exofs we + * use one raid policy through-out the filesystem. (NOTE: the funny + * alignment at begining. We take care of it at exofs_device_table. + */ +struct exofs_dt_data_map { + __le32 cb_num_comps; + __le64 cb_stripe_unit; + __le32 cb_group_width; + __le32 cb_group_depth; + __le32 cb_mirror_cnt; + __le32 cb_raid_algorithm; +} __packed; + +/* + * This is an osd device information descriptor. It is a single entry in + * the exofs device table. It describes an osd target lun which + * contains data belonging to this FS. (Same partition_id on all devices) + */ +struct exofs_dt_device_info { + __le32 systemid_len; + u8 systemid[OSD_SYSTEMID_LEN]; + __le64 long_name_offset; /* If !0 then offset-in-file */ + __le32 osdname_len; /* */ + u8 osdname[44]; /* Embbeded, Ususally an asci uuid */ +} __packed; + +/* + * The EXOFS device table - stored in object EXOFS_DEVTABLE_ID's data. + * It contains the raid used for this multy-device FS and an array of + * participating devices. + */ +struct exofs_device_table { + __le32 dt_version; /* == EXOFS_DT_VER */ + struct exofs_dt_data_map dt_data_map; /* Raid policy to use */ + + /* Resurved space For future use. Total includeing this: + * (8 * sizeof(le64)) + */ + __le64 __Resurved[4]; + + __le64 dt_num_devices; /* Array size */ + struct exofs_dt_device_info dt_dev_table[]; /* Array of devices */ +} __packed; /**************************************************************************** * inode-related things @@ -155,22 +206,4 @@ enum { (((name_len) + offsetof(struct exofs_dir_entry, name) + \ EXOFS_DIR_ROUND) & ~EXOFS_DIR_ROUND) -/************************* - * function declarations * - *************************/ -/* osd.c */ -void exofs_make_credential(u8 cred_a[OSD_CAP_LEN], - const struct osd_obj_id *obj); - -int exofs_check_ok_resid(struct osd_request *or, u64 *in_resid, u64 *out_resid); -static inline int exofs_check_ok(struct osd_request *or) -{ - return exofs_check_ok_resid(or, NULL, NULL); -} -int exofs_sync_op(struct osd_request *or, int timeout, u8 *cred); -int exofs_async_op(struct osd_request *or, - osd_req_done_fn *async_done, void *caller_context, u8 *cred); - -int extract_attr_from_req(struct osd_request *or, struct osd_attr *attr); - #endif /*ifndef __EXOFS_COM_H__*/ diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h index 5ec72e020b22bb8fcbb1f08d1df4af037ab179bd..c35fd4623986cef5479d5edd3039595b788352ee 100644 --- a/fs/exofs/exofs.h +++ b/fs/exofs/exofs.h @@ -30,13 +30,17 @@ * along with exofs; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifndef __EXOFS_H__ +#define __EXOFS_H__ #include #include #include "common.h" -#ifndef __EXOFS_H__ -#define __EXOFS_H__ +/* FIXME: Remove once pnfs hits mainline + * #include + */ +#include "pnfs.h" #define EXOFS_ERR(fmt, a...) printk(KERN_ERR "exofs: " fmt, ##a) @@ -55,7 +59,7 @@ * our extension to the in-memory superblock */ struct exofs_sb_info { - struct osd_dev *s_dev; /* returned by get_osd_dev */ + struct exofs_fscb s_fscb; /* Written often, pre-allocate*/ osd_id s_pid; /* partition ID of file system*/ int s_timeout; /* timeout for OSD operations */ uint64_t s_nextid; /* highest object ID used */ @@ -63,7 +67,11 @@ struct exofs_sb_info { spinlock_t s_next_gen_lock; /* spinlock for gen # update */ u32 s_next_generation; /* next gen # to use */ atomic_t s_curr_pending; /* number of pending commands */ - uint8_t s_cred[OSD_CAP_LEN]; /* all-powerful credential */ + uint8_t s_cred[OSD_CAP_LEN]; /* credential for the fscb */ + + struct pnfs_osd_data_map data_map; /* Default raid to use */ + unsigned s_numdevs; /* Num of devices in array */ + struct osd_dev *s_ods[1]; /* Variable length, minimum 1 */ }; /* @@ -79,6 +87,50 @@ struct exofs_i_info { struct inode vfs_inode; /* normal in-memory inode */ }; +static inline osd_id exofs_oi_objno(struct exofs_i_info *oi) +{ + return oi->vfs_inode.i_ino + EXOFS_OBJ_OFF; +} + +struct exofs_io_state; +typedef void (*exofs_io_done_fn)(struct exofs_io_state *or, void *private); + +struct exofs_io_state { + struct kref kref; + + void *private; + exofs_io_done_fn done; + + struct exofs_sb_info *sbi; + struct osd_obj_id obj; + u8 *cred; + + /* Global read/write IO*/ + loff_t offset; + unsigned long length; + void *kern_buff; + struct bio *bio; + + /* Attributes */ + unsigned in_attr_len; + struct osd_attr *in_attr; + unsigned out_attr_len; + struct osd_attr *out_attr; + + /* Variable array of size numdevs */ + unsigned numdevs; + struct exofs_per_dev_state { + struct osd_request *or; + struct bio *bio; + } per_dev[]; +}; + +static inline unsigned exofs_io_state_size(unsigned numdevs) +{ + return sizeof(struct exofs_io_state) + + sizeof(struct exofs_per_dev_state) * numdevs; +} + /* * our inode flags */ @@ -130,6 +182,42 @@ static inline struct exofs_i_info *exofs_i(struct inode *inode) /************************* * function declarations * *************************/ + +/* ios.c */ +void exofs_make_credential(u8 cred_a[OSD_CAP_LEN], + const struct osd_obj_id *obj); +int exofs_read_kern(struct osd_dev *od, u8 *cred, struct osd_obj_id *obj, + u64 offset, void *p, unsigned length); + +int exofs_get_io_state(struct exofs_sb_info *sbi, struct exofs_io_state** ios); +void exofs_put_io_state(struct exofs_io_state *ios); + +int exofs_check_io(struct exofs_io_state *ios, u64 *resid); + +int exofs_sbi_create(struct exofs_io_state *ios); +int exofs_sbi_remove(struct exofs_io_state *ios); +int exofs_sbi_write(struct exofs_io_state *ios); +int exofs_sbi_read(struct exofs_io_state *ios); + +int extract_attr_from_ios(struct exofs_io_state *ios, struct osd_attr *attr); + +int exofs_oi_truncate(struct exofs_i_info *oi, u64 new_len); +static inline int exofs_oi_write(struct exofs_i_info *oi, + struct exofs_io_state *ios) +{ + ios->obj.id = exofs_oi_objno(oi); + ios->cred = oi->i_cred; + return exofs_sbi_write(ios); +} + +static inline int exofs_oi_read(struct exofs_i_info *oi, + struct exofs_io_state *ios) +{ + ios->obj.id = exofs_oi_objno(oi); + ios->cred = oi->i_cred; + return exofs_sbi_read(ios); +} + /* inode.c */ void exofs_truncate(struct inode *inode); int exofs_setattr(struct dentry *, struct iattr *); @@ -169,6 +257,7 @@ extern const struct file_operations exofs_file_operations; /* inode.c */ extern const struct address_space_operations exofs_aops; +extern const struct osd_attr g_attr_logical_length; /* namei.c */ extern const struct inode_operations exofs_dir_inode_operations; diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 6c10f7476699c4da76b18453a844aefcaa6c9f09..698a8636d39c5895e76e8ce4c15d9305d899ae00 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -37,15 +37,18 @@ #include "exofs.h" -#ifdef CONFIG_EXOFS_DEBUG -# define EXOFS_DEBUG_OBJ_ISIZE 1 -#endif +#define EXOFS_DBGMSG2(M...) do {} while (0) + +enum { BIO_MAX_PAGES_KMALLOC = + (PAGE_SIZE - sizeof(struct bio)) / sizeof(struct bio_vec), +}; struct page_collect { struct exofs_sb_info *sbi; struct request_queue *req_q; struct inode *inode; unsigned expected_pages; + struct exofs_io_state *ios; struct bio *bio; unsigned nr_pages; @@ -54,22 +57,23 @@ struct page_collect { }; static void _pcol_init(struct page_collect *pcol, unsigned expected_pages, - struct inode *inode) + struct inode *inode) { struct exofs_sb_info *sbi = inode->i_sb->s_fs_info; pcol->sbi = sbi; - pcol->req_q = osd_request_queue(sbi->s_dev); + /* Create master bios on first Q, later on cloning, each clone will be + * allocated on it's destination Q + */ + pcol->req_q = osd_request_queue(sbi->s_ods[0]); pcol->inode = inode; pcol->expected_pages = expected_pages; + pcol->ios = NULL; pcol->bio = NULL; pcol->nr_pages = 0; pcol->length = 0; pcol->pg_first = -1; - - EXOFS_DBGMSG("_pcol_init ino=0x%lx expected_pages=%u\n", inode->i_ino, - expected_pages); } static void _pcol_reset(struct page_collect *pcol) @@ -80,35 +84,49 @@ static void _pcol_reset(struct page_collect *pcol) pcol->nr_pages = 0; pcol->length = 0; pcol->pg_first = -1; - EXOFS_DBGMSG("_pcol_reset ino=0x%lx expected_pages=%u\n", - pcol->inode->i_ino, pcol->expected_pages); + pcol->ios = NULL; /* this is probably the end of the loop but in writes * it might not end here. don't be left with nothing */ if (!pcol->expected_pages) - pcol->expected_pages = 128; + pcol->expected_pages = BIO_MAX_PAGES_KMALLOC; } static int pcol_try_alloc(struct page_collect *pcol) { - int pages = min_t(unsigned, pcol->expected_pages, BIO_MAX_PAGES); + int pages = min_t(unsigned, pcol->expected_pages, + BIO_MAX_PAGES_KMALLOC); + + if (!pcol->ios) { /* First time allocate io_state */ + int ret = exofs_get_io_state(pcol->sbi, &pcol->ios); + + if (ret) + return ret; + } for (; pages; pages >>= 1) { - pcol->bio = bio_alloc(GFP_KERNEL, pages); + pcol->bio = bio_kmalloc(GFP_KERNEL, pages); if (likely(pcol->bio)) return 0; } - EXOFS_ERR("Failed to kcalloc expected_pages=%u\n", + EXOFS_ERR("Failed to bio_kmalloc expected_pages=%u\n", pcol->expected_pages); return -ENOMEM; } static void pcol_free(struct page_collect *pcol) { - bio_put(pcol->bio); - pcol->bio = NULL; + if (pcol->bio) { + bio_put(pcol->bio); + pcol->bio = NULL; + } + + if (pcol->ios) { + exofs_put_io_state(pcol->ios); + pcol->ios = NULL; + } } static int pcol_add_page(struct page_collect *pcol, struct page *page, @@ -161,22 +179,17 @@ static void update_write_page(struct page *page, int ret) /* Called at the end of reads, to optionally unlock pages and update their * status. */ -static int __readpages_done(struct osd_request *or, struct page_collect *pcol, - bool do_unlock) +static int __readpages_done(struct page_collect *pcol, bool do_unlock) { struct bio_vec *bvec; int i; u64 resid; u64 good_bytes; u64 length = 0; - int ret = exofs_check_ok_resid(or, &resid, NULL); - - osd_end_request(or); + int ret = exofs_check_io(pcol->ios, &resid); if (likely(!ret)) good_bytes = pcol->length; - else if (!resid) - good_bytes = 0; else good_bytes = pcol->length - resid; @@ -198,7 +211,7 @@ static int __readpages_done(struct osd_request *or, struct page_collect *pcol, else page_stat = ret; - EXOFS_DBGMSG(" readpages_done(0x%lx, 0x%lx) %s\n", + EXOFS_DBGMSG2(" readpages_done(0x%lx, 0x%lx) %s\n", inode->i_ino, page->index, page_stat ? "bad_bytes" : "good_bytes"); @@ -214,13 +227,13 @@ static int __readpages_done(struct osd_request *or, struct page_collect *pcol, } /* callback of async reads */ -static void readpages_done(struct osd_request *or, void *p) +static void readpages_done(struct exofs_io_state *ios, void *p) { struct page_collect *pcol = p; - __readpages_done(or, pcol, true); + __readpages_done(pcol, true); atomic_dec(&pcol->sbi->s_curr_pending); - kfree(p); + kfree(pcol); } static void _unlock_pcol_pages(struct page_collect *pcol, int ret, int rw) @@ -238,17 +251,13 @@ static void _unlock_pcol_pages(struct page_collect *pcol, int ret, int rw) unlock_page(page); } - pcol_free(pcol); } static int read_exec(struct page_collect *pcol, bool is_sync) { struct exofs_i_info *oi = exofs_i(pcol->inode); - struct osd_obj_id obj = {pcol->sbi->s_pid, - pcol->inode->i_ino + EXOFS_OBJ_OFF}; - struct osd_request *or = NULL; + struct exofs_io_state *ios = pcol->ios; struct page_collect *pcol_copy = NULL; - loff_t i_start = pcol->pg_first << PAGE_CACHE_SHIFT; int ret; if (!pcol->bio) @@ -257,17 +266,13 @@ static int read_exec(struct page_collect *pcol, bool is_sync) /* see comment in _readpage() about sync reads */ WARN_ON(is_sync && (pcol->nr_pages != 1)); - or = osd_start_request(pcol->sbi->s_dev, GFP_KERNEL); - if (unlikely(!or)) { - ret = -ENOMEM; - goto err; - } - - osd_req_read(or, &obj, i_start, pcol->bio, pcol->length); + ios->bio = pcol->bio; + ios->length = pcol->length; + ios->offset = pcol->pg_first << PAGE_CACHE_SHIFT; if (is_sync) { - exofs_sync_op(or, pcol->sbi->s_timeout, oi->i_cred); - return __readpages_done(or, pcol, false); + exofs_oi_read(oi, pcol->ios); + return __readpages_done(pcol, false); } pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL); @@ -277,14 +282,16 @@ static int read_exec(struct page_collect *pcol, bool is_sync) } *pcol_copy = *pcol; - ret = exofs_async_op(or, readpages_done, pcol_copy, oi->i_cred); + ios->done = readpages_done; + ios->private = pcol_copy; + ret = exofs_oi_read(oi, ios); if (unlikely(ret)) goto err; atomic_inc(&pcol->sbi->s_curr_pending); EXOFS_DBGMSG("read_exec obj=0x%llx start=0x%llx length=0x%lx\n", - obj.id, _LLU(i_start), pcol->length); + ios->obj.id, _LLU(ios->offset), pcol->length); /* pages ownership was passed to pcol_copy */ _pcol_reset(pcol); @@ -293,12 +300,10 @@ static int read_exec(struct page_collect *pcol, bool is_sync) err: if (!is_sync) _unlock_pcol_pages(pcol, ret, READ); - else /* Pages unlocked by caller in sync mode only free bio */ - pcol_free(pcol); + + pcol_free(pcol); kfree(pcol_copy); - if (or) - osd_end_request(or); return ret; } @@ -370,12 +375,12 @@ try_again: if (len != PAGE_CACHE_SIZE) zero_user(page, len, PAGE_CACHE_SIZE - len); - EXOFS_DBGMSG(" readpage_strip(0x%lx, 0x%lx) len=0x%zx\n", + EXOFS_DBGMSG2(" readpage_strip(0x%lx, 0x%lx) len=0x%zx\n", inode->i_ino, page->index, len); ret = pcol_add_page(pcol, page, len); if (ret) { - EXOFS_DBGMSG("Failed pcol_add_page pages[i]=%p " + EXOFS_DBGMSG2("Failed pcol_add_page pages[i]=%p " "this_len=0x%zx nr_pages=%u length=0x%lx\n", page, len, pcol->nr_pages, pcol->length); @@ -419,9 +424,8 @@ static int _readpage(struct page *page, bool is_sync) _pcol_init(&pcol, 1, page->mapping->host); - /* readpage_strip might call read_exec(,async) inside at several places - * but this is safe for is_async=0 since read_exec will not do anything - * when we have a single page. + /* readpage_strip might call read_exec(,is_sync==false) at several + * places but not if we have a single page. */ ret = readpage_strip(&pcol, page); if (ret) { @@ -440,8 +444,8 @@ static int exofs_readpage(struct file *file, struct page *page) return _readpage(page, false); } -/* Callback for osd_write. All writes are asynchronouse */ -static void writepages_done(struct osd_request *or, void *p) +/* Callback for osd_write. All writes are asynchronous */ +static void writepages_done(struct exofs_io_state *ios, void *p) { struct page_collect *pcol = p; struct bio_vec *bvec; @@ -449,16 +453,12 @@ static void writepages_done(struct osd_request *or, void *p) u64 resid; u64 good_bytes; u64 length = 0; + int ret = exofs_check_io(ios, &resid); - int ret = exofs_check_ok_resid(or, NULL, &resid); - - osd_end_request(or); atomic_dec(&pcol->sbi->s_curr_pending); if (likely(!ret)) good_bytes = pcol->length; - else if (!resid) - good_bytes = 0; else good_bytes = pcol->length - resid; @@ -482,7 +482,7 @@ static void writepages_done(struct osd_request *or, void *p) update_write_page(page, page_stat); unlock_page(page); - EXOFS_DBGMSG(" writepages_done(0x%lx, 0x%lx) status=%d\n", + EXOFS_DBGMSG2(" writepages_done(0x%lx, 0x%lx) status=%d\n", inode->i_ino, page->index, page_stat); length += bvec->bv_len; @@ -496,23 +496,13 @@ static void writepages_done(struct osd_request *or, void *p) static int write_exec(struct page_collect *pcol) { struct exofs_i_info *oi = exofs_i(pcol->inode); - struct osd_obj_id obj = {pcol->sbi->s_pid, - pcol->inode->i_ino + EXOFS_OBJ_OFF}; - struct osd_request *or = NULL; + struct exofs_io_state *ios = pcol->ios; struct page_collect *pcol_copy = NULL; - loff_t i_start = pcol->pg_first << PAGE_CACHE_SHIFT; int ret; if (!pcol->bio) return 0; - or = osd_start_request(pcol->sbi->s_dev, GFP_KERNEL); - if (unlikely(!or)) { - EXOFS_ERR("write_exec: Faild to osd_start_request()\n"); - ret = -ENOMEM; - goto err; - } - pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL); if (!pcol_copy) { EXOFS_ERR("write_exec: Faild to kmalloc(pcol)\n"); @@ -523,16 +513,22 @@ static int write_exec(struct page_collect *pcol) *pcol_copy = *pcol; pcol_copy->bio->bi_rw |= (1 << BIO_RW); /* FIXME: bio_set_dir() */ - osd_req_write(or, &obj, i_start, pcol_copy->bio, pcol_copy->length); - ret = exofs_async_op(or, writepages_done, pcol_copy, oi->i_cred); + + ios->bio = pcol_copy->bio; + ios->offset = pcol_copy->pg_first << PAGE_CACHE_SHIFT; + ios->length = pcol_copy->length; + ios->done = writepages_done; + ios->private = pcol_copy; + + ret = exofs_oi_write(oi, ios); if (unlikely(ret)) { - EXOFS_ERR("write_exec: exofs_async_op() Faild\n"); + EXOFS_ERR("write_exec: exofs_oi_write() Faild\n"); goto err; } atomic_inc(&pcol->sbi->s_curr_pending); EXOFS_DBGMSG("write_exec(0x%lx, 0x%llx) start=0x%llx length=0x%lx\n", - pcol->inode->i_ino, pcol->pg_first, _LLU(i_start), + pcol->inode->i_ino, pcol->pg_first, _LLU(ios->offset), pcol->length); /* pages ownership was passed to pcol_copy */ _pcol_reset(pcol); @@ -540,9 +536,9 @@ static int write_exec(struct page_collect *pcol) err: _unlock_pcol_pages(pcol, ret, WRITE); + pcol_free(pcol); kfree(pcol_copy); - if (or) - osd_end_request(or); + return ret; } @@ -586,6 +582,9 @@ static int writepage_strip(struct page *page, if (PageError(page)) ClearPageError(page); unlock_page(page); + EXOFS_DBGMSG("writepage_strip(0x%lx, 0x%lx) " + "outside the limits\n", + inode->i_ino, page->index); return 0; } } @@ -600,6 +599,9 @@ try_again: ret = write_exec(pcol); if (unlikely(ret)) goto fail; + + EXOFS_DBGMSG("writepage_strip(0x%lx, 0x%lx) Discontinuity\n", + inode->i_ino, page->index); goto try_again; } @@ -609,7 +611,7 @@ try_again: goto fail; } - EXOFS_DBGMSG(" writepage_strip(0x%lx, 0x%lx) len=0x%zx\n", + EXOFS_DBGMSG2(" writepage_strip(0x%lx, 0x%lx) len=0x%zx\n", inode->i_ino, page->index, len); ret = pcol_add_page(pcol, page, len); @@ -634,6 +636,8 @@ try_again: return 0; fail: + EXOFS_DBGMSG("Error: writepage_strip(0x%lx, 0x%lx)=>%d\n", + inode->i_ino, page->index, ret); set_bit(AS_EIO, &page->mapping->flags); unlock_page(page); return ret; @@ -652,14 +656,17 @@ static int exofs_writepages(struct address_space *mapping, wbc->range_end >> PAGE_CACHE_SHIFT; if (start || end) - expected_pages = min(end - start + 1, 32L); + expected_pages = end - start + 1; else expected_pages = mapping->nrpages; - EXOFS_DBGMSG("inode(0x%lx) wbc->start=0x%llx wbc->end=0x%llx" - " m->nrpages=%lu start=0x%lx end=0x%lx\n", + if (expected_pages < 32L) + expected_pages = 32L; + + EXOFS_DBGMSG("inode(0x%lx) wbc->start=0x%llx wbc->end=0x%llx " + "nrpages=%lu start=0x%lx end=0x%lx expected_pages=%ld\n", mapping->host->i_ino, wbc->range_start, wbc->range_end, - mapping->nrpages, start, end); + mapping->nrpages, start, end, expected_pages); _pcol_init(&pcol, expected_pages, mapping->host); @@ -771,19 +778,28 @@ static int exofs_get_block(struct inode *inode, sector_t iblock, const struct osd_attr g_attr_logical_length = ATTR_DEF( OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8); +static int _do_truncate(struct inode *inode) +{ + struct exofs_i_info *oi = exofs_i(inode); + loff_t isize = i_size_read(inode); + int ret; + + inode->i_mtime = inode->i_ctime = CURRENT_TIME; + + nobh_truncate_page(inode->i_mapping, isize, exofs_get_block); + + ret = exofs_oi_truncate(oi, (u64)isize); + EXOFS_DBGMSG("(0x%lx) size=0x%llx\n", inode->i_ino, isize); + return ret; +} + /* * Truncate a file to the specified size - all we have to do is set the size * attribute. We make sure the object exists first. */ void exofs_truncate(struct inode *inode) { - struct exofs_sb_info *sbi = inode->i_sb->s_fs_info; struct exofs_i_info *oi = exofs_i(inode); - struct osd_obj_id obj = {sbi->s_pid, inode->i_ino + EXOFS_OBJ_OFF}; - struct osd_request *or; - struct osd_attr attr; - loff_t isize = i_size_read(inode); - __be64 newsize; int ret; if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) @@ -793,22 +809,6 @@ void exofs_truncate(struct inode *inode) return; if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) return; - inode->i_mtime = inode->i_ctime = CURRENT_TIME; - - nobh_truncate_page(inode->i_mapping, isize, exofs_get_block); - - or = osd_start_request(sbi->s_dev, GFP_KERNEL); - if (unlikely(!or)) { - EXOFS_ERR("ERROR: exofs_truncate: osd_start_request failed\n"); - goto fail; - } - - osd_req_set_attributes(or, &obj); - - newsize = cpu_to_be64((u64)isize); - attr = g_attr_logical_length; - attr.val_ptr = &newsize; - osd_req_add_set_attr_list(or, &attr, 1); /* if we are about to truncate an object, and it hasn't been * created yet, wait @@ -816,8 +816,7 @@ void exofs_truncate(struct inode *inode) if (unlikely(wait_obj_created(oi))) goto fail; - ret = exofs_sync_op(or, sbi->s_timeout, oi->i_cred); - osd_end_request(or); + ret = _do_truncate(inode); if (ret) goto fail; @@ -847,65 +846,62 @@ int exofs_setattr(struct dentry *dentry, struct iattr *iattr) /* * Read an inode from the OSD, and return it as is. We also return the size - * attribute in the 'sanity' argument if we got compiled with debugging turned - * on. + * attribute in the 'obj_size' argument. */ static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi, - struct exofs_fcb *inode, uint64_t *sanity) + struct exofs_fcb *inode, uint64_t *obj_size) { struct exofs_sb_info *sbi = sb->s_fs_info; - struct osd_request *or; - struct osd_attr attr; - struct osd_obj_id obj = {sbi->s_pid, - oi->vfs_inode.i_ino + EXOFS_OBJ_OFF}; + struct osd_attr attrs[2]; + struct exofs_io_state *ios; int ret; - exofs_make_credential(oi->i_cred, &obj); - - or = osd_start_request(sbi->s_dev, GFP_KERNEL); - if (unlikely(!or)) { - EXOFS_ERR("exofs_get_inode: osd_start_request failed.\n"); - return -ENOMEM; + *obj_size = ~0; + ret = exofs_get_io_state(sbi, &ios); + if (unlikely(ret)) { + EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__); + return ret; } - osd_req_get_attributes(or, &obj); - /* we need the inode attribute */ - osd_req_add_get_attr_list(or, &g_attr_inode_data, 1); + ios->obj.id = exofs_oi_objno(oi); + exofs_make_credential(oi->i_cred, &ios->obj); + ios->cred = oi->i_cred; -#ifdef EXOFS_DEBUG_OBJ_ISIZE - /* we get the size attributes to do a sanity check */ - osd_req_add_get_attr_list(or, &g_attr_logical_length, 1); -#endif + attrs[0] = g_attr_inode_data; + attrs[1] = g_attr_logical_length; + ios->in_attr = attrs; + ios->in_attr_len = ARRAY_SIZE(attrs); - ret = exofs_sync_op(or, sbi->s_timeout, oi->i_cred); + ret = exofs_sbi_read(ios); if (ret) goto out; - attr = g_attr_inode_data; - ret = extract_attr_from_req(or, &attr); + ret = extract_attr_from_ios(ios, &attrs[0]); if (ret) { - EXOFS_ERR("exofs_get_inode: extract_attr_from_req failed\n"); + EXOFS_ERR("%s: extract_attr of inode_data failed\n", __func__); goto out; } + WARN_ON(attrs[0].len != EXOFS_INO_ATTR_SIZE); + memcpy(inode, attrs[0].val_ptr, EXOFS_INO_ATTR_SIZE); - WARN_ON(attr.len != EXOFS_INO_ATTR_SIZE); - memcpy(inode, attr.val_ptr, EXOFS_INO_ATTR_SIZE); - -#ifdef EXOFS_DEBUG_OBJ_ISIZE - attr = g_attr_logical_length; - ret = extract_attr_from_req(or, &attr); + ret = extract_attr_from_ios(ios, &attrs[1]); if (ret) { - EXOFS_ERR("ERROR: extract attr from or failed\n"); + EXOFS_ERR("%s: extract_attr of logical_length failed\n", + __func__); goto out; } - *sanity = get_unaligned_be64(attr.val_ptr); -#endif + *obj_size = get_unaligned_be64(attrs[1].val_ptr); out: - osd_end_request(or); + exofs_put_io_state(ios); return ret; } +static void __oi_init(struct exofs_i_info *oi) +{ + init_waitqueue_head(&oi->i_wq); + oi->i_flags = 0; +} /* * Fill in an inode read from the OSD and set it up for use */ @@ -914,7 +910,7 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino) struct exofs_i_info *oi; struct exofs_fcb fcb; struct inode *inode; - uint64_t uninitialized_var(sanity); + uint64_t obj_size; int ret; inode = iget_locked(sb, ino); @@ -923,13 +919,13 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino) if (!(inode->i_state & I_NEW)) return inode; oi = exofs_i(inode); + __oi_init(oi); /* read the inode from the osd */ - ret = exofs_get_inode(sb, oi, &fcb, &sanity); + ret = exofs_get_inode(sb, oi, &fcb, &obj_size); if (ret) goto bad_inode; - init_waitqueue_head(&oi->i_wq); set_obj_created(oi); /* copy stuff from on-disk struct to in-memory struct */ @@ -947,14 +943,12 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino) inode->i_blkbits = EXOFS_BLKSHIFT; inode->i_generation = le32_to_cpu(fcb.i_generation); -#ifdef EXOFS_DEBUG_OBJ_ISIZE - if ((inode->i_size != sanity) && + if ((inode->i_size != obj_size) && (!exofs_inode_is_fast_symlink(inode))) { - EXOFS_ERR("WARNING: Size of object from inode and " - "attributes differ (%lld != %llu)\n", - inode->i_size, _LLU(sanity)); + EXOFS_ERR("WARNING: Size of inode=%llu != object=%llu\n", + inode->i_size, _LLU(obj_size)); + /* FIXME: call exofs_inode_recovery() */ } -#endif oi->i_dir_start_lookup = 0; @@ -1020,23 +1014,30 @@ int __exofs_wait_obj_created(struct exofs_i_info *oi) * set the obj_created flag so that other methods know that the object exists on * the OSD. */ -static void create_done(struct osd_request *or, void *p) +static void create_done(struct exofs_io_state *ios, void *p) { struct inode *inode = p; struct exofs_i_info *oi = exofs_i(inode); struct exofs_sb_info *sbi = inode->i_sb->s_fs_info; int ret; - ret = exofs_check_ok(or); - osd_end_request(or); + ret = exofs_check_io(ios, NULL); + exofs_put_io_state(ios); + atomic_dec(&sbi->s_curr_pending); if (unlikely(ret)) { EXOFS_ERR("object=0x%llx creation faild in pid=0x%llx", - _LLU(sbi->s_pid), _LLU(inode->i_ino + EXOFS_OBJ_OFF)); - make_bad_inode(inode); - } else - set_obj_created(oi); + _LLU(exofs_oi_objno(oi)), _LLU(sbi->s_pid)); + /*TODO: When FS is corrupted creation can fail, object already + * exist. Get rid of this asynchronous creation, if exist + * increment the obj counter and try the next object. Until we + * succeed. All these dangling objects will be made into lost + * files by chkfs.exofs + */ + } + + set_obj_created(oi); atomic_dec(&inode->i_count); wake_up(&oi->i_wq); @@ -1051,8 +1052,7 @@ struct inode *exofs_new_inode(struct inode *dir, int mode) struct inode *inode; struct exofs_i_info *oi; struct exofs_sb_info *sbi; - struct osd_request *or; - struct osd_obj_id obj; + struct exofs_io_state *ios; int ret; sb = dir->i_sb; @@ -1061,8 +1061,8 @@ struct inode *exofs_new_inode(struct inode *dir, int mode) return ERR_PTR(-ENOMEM); oi = exofs_i(inode); + __oi_init(oi); - init_waitqueue_head(&oi->i_wq); set_obj_2bcreated(oi); sbi = sb->s_fs_info; @@ -1089,28 +1089,28 @@ struct inode *exofs_new_inode(struct inode *dir, int mode) mark_inode_dirty(inode); - obj.partition = sbi->s_pid; - obj.id = inode->i_ino + EXOFS_OBJ_OFF; - exofs_make_credential(oi->i_cred, &obj); - - or = osd_start_request(sbi->s_dev, GFP_KERNEL); - if (unlikely(!or)) { - EXOFS_ERR("exofs_new_inode: osd_start_request failed\n"); - return ERR_PTR(-ENOMEM); + ret = exofs_get_io_state(sbi, &ios); + if (unlikely(ret)) { + EXOFS_ERR("exofs_new_inode: exofs_get_io_state failed\n"); + return ERR_PTR(ret); } - osd_req_create_object(or, &obj); + ios->obj.id = exofs_oi_objno(oi); + exofs_make_credential(oi->i_cred, &ios->obj); /* increment the refcount so that the inode will still be around when we * reach the callback */ atomic_inc(&inode->i_count); - ret = exofs_async_op(or, create_done, inode, oi->i_cred); + ios->done = create_done; + ios->private = inode; + ios->cred = oi->i_cred; + ret = exofs_sbi_create(ios); if (ret) { atomic_dec(&inode->i_count); - osd_end_request(or); - return ERR_PTR(-EIO); + exofs_put_io_state(ios); + return ERR_PTR(ret); } atomic_inc(&sbi->s_curr_pending); @@ -1128,11 +1128,11 @@ struct updatei_args { /* * Callback function from exofs_update_inode(). */ -static void updatei_done(struct osd_request *or, void *p) +static void updatei_done(struct exofs_io_state *ios, void *p) { struct updatei_args *args = p; - osd_end_request(or); + exofs_put_io_state(ios); atomic_dec(&args->sbi->s_curr_pending); @@ -1148,8 +1148,7 @@ static int exofs_update_inode(struct inode *inode, int do_sync) struct exofs_i_info *oi = exofs_i(inode); struct super_block *sb = inode->i_sb; struct exofs_sb_info *sbi = sb->s_fs_info; - struct osd_obj_id obj = {sbi->s_pid, inode->i_ino + EXOFS_OBJ_OFF}; - struct osd_request *or; + struct exofs_io_state *ios; struct osd_attr attr; struct exofs_fcb *fcb; struct updatei_args *args; @@ -1186,18 +1185,16 @@ static int exofs_update_inode(struct inode *inode, int do_sync) } else memcpy(fcb->i_data, oi->i_data, sizeof(fcb->i_data)); - or = osd_start_request(sbi->s_dev, GFP_KERNEL); - if (unlikely(!or)) { - EXOFS_ERR("exofs_update_inode: osd_start_request failed.\n"); - ret = -ENOMEM; + ret = exofs_get_io_state(sbi, &ios); + if (unlikely(ret)) { + EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__); goto free_args; } - osd_req_set_attributes(or, &obj); - attr = g_attr_inode_data; attr.val_ptr = fcb; - osd_req_add_set_attr_list(or, &attr, 1); + ios->out_attr_len = 1; + ios->out_attr = &attr; if (!obj_created(oi)) { EXOFS_DBGMSG("!obj_created\n"); @@ -1206,22 +1203,19 @@ static int exofs_update_inode(struct inode *inode, int do_sync) EXOFS_DBGMSG("wait_event done\n"); } - if (do_sync) { - ret = exofs_sync_op(or, sbi->s_timeout, oi->i_cred); - osd_end_request(or); - goto free_args; - } else { + if (!do_sync) { args->sbi = sbi; + ios->done = updatei_done; + ios->private = args; + } - ret = exofs_async_op(or, updatei_done, args, oi->i_cred); - if (ret) { - osd_end_request(or); - goto free_args; - } + ret = exofs_oi_write(oi, ios); + if (!do_sync && !ret) { atomic_inc(&sbi->s_curr_pending); goto out; /* deallocation in updatei_done */ } + exofs_put_io_state(ios); free_args: kfree(args); out: @@ -1238,11 +1232,12 @@ int exofs_write_inode(struct inode *inode, int wait) * Callback function from exofs_delete_inode() - don't have much cleaning up to * do. */ -static void delete_done(struct osd_request *or, void *p) +static void delete_done(struct exofs_io_state *ios, void *p) { - struct exofs_sb_info *sbi; - osd_end_request(or); - sbi = p; + struct exofs_sb_info *sbi = p; + + exofs_put_io_state(ios); + atomic_dec(&sbi->s_curr_pending); } @@ -1256,8 +1251,7 @@ void exofs_delete_inode(struct inode *inode) struct exofs_i_info *oi = exofs_i(inode); struct super_block *sb = inode->i_sb; struct exofs_sb_info *sbi = sb->s_fs_info; - struct osd_obj_id obj = {sbi->s_pid, inode->i_ino + EXOFS_OBJ_OFF}; - struct osd_request *or; + struct exofs_io_state *ios; int ret; truncate_inode_pages(&inode->i_data, 0); @@ -1274,25 +1268,26 @@ void exofs_delete_inode(struct inode *inode) clear_inode(inode); - or = osd_start_request(sbi->s_dev, GFP_KERNEL); - if (unlikely(!or)) { - EXOFS_ERR("exofs_delete_inode: osd_start_request failed\n"); + ret = exofs_get_io_state(sbi, &ios); + if (unlikely(ret)) { + EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__); return; } - osd_req_remove_object(or, &obj); - /* if we are deleting an obj that hasn't been created yet, wait */ if (!obj_created(oi)) { BUG_ON(!obj_2bcreated(oi)); wait_event(oi->i_wq, obj_created(oi)); } - ret = exofs_async_op(or, delete_done, sbi, oi->i_cred); + ios->obj.id = exofs_oi_objno(oi); + ios->done = delete_done; + ios->private = sbi; + ios->cred = oi->i_cred; + ret = exofs_sbi_remove(ios); if (ret) { - EXOFS_ERR( - "ERROR: @exofs_delete_inode exofs_async_op failed\n"); - osd_end_request(or); + EXOFS_ERR("%s: exofs_sbi_remove failed\n", __func__); + exofs_put_io_state(ios); return; } atomic_inc(&sbi->s_curr_pending); diff --git a/fs/exofs/ios.c b/fs/exofs/ios.c new file mode 100644 index 0000000000000000000000000000000000000000..5bad01fa1f9fad6cbe74b2afe500c14c95221a57 --- /dev/null +++ b/fs/exofs/ios.c @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2005, 2006 + * Avishay Traeger (avishay@gmail.com) + * Copyright (C) 2008, 2009 + * Boaz Harrosh + * + * This file is part of exofs. + * + * exofs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. Since it is based on ext2, and the only + * valid version of GPL for the Linux kernel is version 2, the only valid + * version of GPL for exofs is version 2. + * + * exofs is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with exofs; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "exofs.h" + +void exofs_make_credential(u8 cred_a[OSD_CAP_LEN], const struct osd_obj_id *obj) +{ + osd_sec_init_nosec_doall_caps(cred_a, obj, false, true); +} + +int exofs_read_kern(struct osd_dev *od, u8 *cred, struct osd_obj_id *obj, + u64 offset, void *p, unsigned length) +{ + struct osd_request *or = osd_start_request(od, GFP_KERNEL); +/* struct osd_sense_info osi = {.key = 0};*/ + int ret; + + if (unlikely(!or)) { + EXOFS_DBGMSG("%s: osd_start_request failed.\n", __func__); + return -ENOMEM; + } + ret = osd_req_read_kern(or, obj, offset, p, length); + if (unlikely(ret)) { + EXOFS_DBGMSG("%s: osd_req_read_kern failed.\n", __func__); + goto out; + } + + ret = osd_finalize_request(or, 0, cred, NULL); + if (unlikely(ret)) { + EXOFS_DBGMSG("Faild to osd_finalize_request() => %d\n", ret); + goto out; + } + + ret = osd_execute_request(or); + if (unlikely(ret)) + EXOFS_DBGMSG("osd_execute_request() => %d\n", ret); + /* osd_req_decode_sense(or, ret); */ + +out: + osd_end_request(or); + return ret; +} + +int exofs_get_io_state(struct exofs_sb_info *sbi, struct exofs_io_state** pios) +{ + struct exofs_io_state *ios; + + /*TODO: Maybe use kmem_cach per sbi of size + * exofs_io_state_size(sbi->s_numdevs) + */ + ios = kzalloc(exofs_io_state_size(sbi->s_numdevs), GFP_KERNEL); + if (unlikely(!ios)) { + *pios = NULL; + return -ENOMEM; + } + + ios->sbi = sbi; + ios->obj.partition = sbi->s_pid; + *pios = ios; + return 0; +} + +void exofs_put_io_state(struct exofs_io_state *ios) +{ + if (ios) { + unsigned i; + + for (i = 0; i < ios->numdevs; i++) { + struct exofs_per_dev_state *per_dev = &ios->per_dev[i]; + + if (per_dev->or) + osd_end_request(per_dev->or); + if (per_dev->bio) + bio_put(per_dev->bio); + } + + kfree(ios); + } +} + +static void _sync_done(struct exofs_io_state *ios, void *p) +{ + struct completion *waiting = p; + + complete(waiting); +} + +static void _last_io(struct kref *kref) +{ + struct exofs_io_state *ios = container_of( + kref, struct exofs_io_state, kref); + + ios->done(ios, ios->private); +} + +static void _done_io(struct osd_request *or, void *p) +{ + struct exofs_io_state *ios = p; + + kref_put(&ios->kref, _last_io); +} + +static int exofs_io_execute(struct exofs_io_state *ios) +{ + DECLARE_COMPLETION_ONSTACK(wait); + bool sync = (ios->done == NULL); + int i, ret; + + if (sync) { + ios->done = _sync_done; + ios->private = &wait; + } + + for (i = 0; i < ios->numdevs; i++) { + struct osd_request *or = ios->per_dev[i].or; + if (unlikely(!or)) + continue; + + ret = osd_finalize_request(or, 0, ios->cred, NULL); + if (unlikely(ret)) { + EXOFS_DBGMSG("Faild to osd_finalize_request() => %d\n", + ret); + return ret; + } + } + + kref_init(&ios->kref); + + for (i = 0; i < ios->numdevs; i++) { + struct osd_request *or = ios->per_dev[i].or; + if (unlikely(!or)) + continue; + + kref_get(&ios->kref); + osd_execute_request_async(or, _done_io, ios); + } + + kref_put(&ios->kref, _last_io); + ret = 0; + + if (sync) { + wait_for_completion(&wait); + ret = exofs_check_io(ios, NULL); + } + return ret; +} + +int exofs_check_io(struct exofs_io_state *ios, u64 *resid) +{ + enum osd_err_priority acumulated_osd_err = 0; + int acumulated_lin_err = 0; + int i; + + for (i = 0; i < ios->numdevs; i++) { + struct osd_sense_info osi; + int ret = osd_req_decode_sense(ios->per_dev[i].or, &osi); + + if (likely(!ret)) + continue; + + if (unlikely(ret == -EFAULT)) { + EXOFS_DBGMSG("%s: EFAULT Need page clear\n", __func__); + /*FIXME: All the pages in this device range should: + * clear_highpage(page); + */ + } + + if (osi.osd_err_pri >= acumulated_osd_err) { + acumulated_osd_err = osi.osd_err_pri; + acumulated_lin_err = ret; + } + } + + /* TODO: raid specific residual calculations */ + if (resid) { + if (likely(!acumulated_lin_err)) + *resid = 0; + else + *resid = ios->length; + } + + return acumulated_lin_err; +} + +int exofs_sbi_create(struct exofs_io_state *ios) +{ + int i, ret; + + for (i = 0; i < ios->sbi->s_numdevs; i++) { + struct osd_request *or; + + or = osd_start_request(ios->sbi->s_ods[i], GFP_KERNEL); + if (unlikely(!or)) { + EXOFS_ERR("%s: osd_start_request failed\n", __func__); + ret = -ENOMEM; + goto out; + } + ios->per_dev[i].or = or; + ios->numdevs++; + + osd_req_create_object(or, &ios->obj); + } + ret = exofs_io_execute(ios); + +out: + return ret; +} + +int exofs_sbi_remove(struct exofs_io_state *ios) +{ + int i, ret; + + for (i = 0; i < ios->sbi->s_numdevs; i++) { + struct osd_request *or; + + or = osd_start_request(ios->sbi->s_ods[i], GFP_KERNEL); + if (unlikely(!or)) { + EXOFS_ERR("%s: osd_start_request failed\n", __func__); + ret = -ENOMEM; + goto out; + } + ios->per_dev[i].or = or; + ios->numdevs++; + + osd_req_remove_object(or, &ios->obj); + } + ret = exofs_io_execute(ios); + +out: + return ret; +} + +int exofs_sbi_write(struct exofs_io_state *ios) +{ + int i, ret; + + for (i = 0; i < ios->sbi->s_numdevs; i++) { + struct osd_request *or; + + or = osd_start_request(ios->sbi->s_ods[i], GFP_KERNEL); + if (unlikely(!or)) { + EXOFS_ERR("%s: osd_start_request failed\n", __func__); + ret = -ENOMEM; + goto out; + } + ios->per_dev[i].or = or; + ios->numdevs++; + + if (ios->bio) { + struct bio *bio; + + if (i != 0) { + bio = bio_kmalloc(GFP_KERNEL, + ios->bio->bi_max_vecs); + if (unlikely(!bio)) { + ret = -ENOMEM; + goto out; + } + + __bio_clone(bio, ios->bio); + bio->bi_bdev = NULL; + bio->bi_next = NULL; + ios->per_dev[i].bio = bio; + } else { + bio = ios->bio; + } + + osd_req_write(or, &ios->obj, ios->offset, bio, + ios->length); +/* EXOFS_DBGMSG("write sync=%d\n", sync);*/ + } else if (ios->kern_buff) { + osd_req_write_kern(or, &ios->obj, ios->offset, + ios->kern_buff, ios->length); +/* EXOFS_DBGMSG("write_kern sync=%d\n", sync);*/ + } else { + osd_req_set_attributes(or, &ios->obj); +/* EXOFS_DBGMSG("set_attributes sync=%d\n", sync);*/ + } + + if (ios->out_attr) + osd_req_add_set_attr_list(or, ios->out_attr, + ios->out_attr_len); + + if (ios->in_attr) + osd_req_add_get_attr_list(or, ios->in_attr, + ios->in_attr_len); + } + ret = exofs_io_execute(ios); + +out: + return ret; +} + +int exofs_sbi_read(struct exofs_io_state *ios) +{ + int i, ret; + + for (i = 0; i < 1; i++) { + struct osd_request *or; + unsigned first_dev = (unsigned)ios->obj.id; + + first_dev %= ios->sbi->s_numdevs; + or = osd_start_request(ios->sbi->s_ods[first_dev], GFP_KERNEL); + if (unlikely(!or)) { + EXOFS_ERR("%s: osd_start_request failed\n", __func__); + ret = -ENOMEM; + goto out; + } + ios->per_dev[i].or = or; + ios->numdevs++; + + if (ios->bio) { + osd_req_read(or, &ios->obj, ios->offset, ios->bio, + ios->length); +/* EXOFS_DBGMSG("read sync=%d\n", sync);*/ + } else if (ios->kern_buff) { + osd_req_read_kern(or, &ios->obj, ios->offset, + ios->kern_buff, ios->length); +/* EXOFS_DBGMSG("read_kern sync=%d\n", sync);*/ + } else { + osd_req_get_attributes(or, &ios->obj); +/* EXOFS_DBGMSG("get_attributes sync=%d\n", sync);*/ + } + + if (ios->out_attr) + osd_req_add_set_attr_list(or, ios->out_attr, + ios->out_attr_len); + + if (ios->in_attr) + osd_req_add_get_attr_list(or, ios->in_attr, + ios->in_attr_len); + } + ret = exofs_io_execute(ios); + +out: + return ret; +} + +int extract_attr_from_ios(struct exofs_io_state *ios, struct osd_attr *attr) +{ + struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */ + void *iter = NULL; + int nelem; + + do { + nelem = 1; + osd_req_decode_get_attr_list(ios->per_dev[0].or, + &cur_attr, &nelem, &iter); + if ((cur_attr.attr_page == attr->attr_page) && + (cur_attr.attr_id == attr->attr_id)) { + attr->len = cur_attr.len; + attr->val_ptr = cur_attr.val_ptr; + return 0; + } + } while (iter); + + return -EIO; +} + +int exofs_oi_truncate(struct exofs_i_info *oi, u64 size) +{ + struct exofs_sb_info *sbi = oi->vfs_inode.i_sb->s_fs_info; + struct exofs_io_state *ios; + struct osd_attr attr; + __be64 newsize; + int i, ret; + + if (exofs_get_io_state(sbi, &ios)) + return -ENOMEM; + + ios->obj.id = exofs_oi_objno(oi); + ios->cred = oi->i_cred; + + newsize = cpu_to_be64(size); + attr = g_attr_logical_length; + attr.val_ptr = &newsize; + + for (i = 0; i < sbi->s_numdevs; i++) { + struct osd_request *or; + + or = osd_start_request(sbi->s_ods[i], GFP_KERNEL); + if (unlikely(!or)) { + EXOFS_ERR("%s: osd_start_request failed\n", __func__); + ret = -ENOMEM; + goto out; + } + ios->per_dev[i].or = or; + ios->numdevs++; + + osd_req_set_attributes(or, &ios->obj); + osd_req_add_set_attr_list(or, &attr, 1); + } + ret = exofs_io_execute(ios); + +out: + exofs_put_io_state(ios); + return ret; +} diff --git a/fs/exofs/osd.c b/fs/exofs/osd.c deleted file mode 100644 index 4372542df284ed8336a86f6ce205f9465980e707..0000000000000000000000000000000000000000 --- a/fs/exofs/osd.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2005, 2006 - * Avishay Traeger (avishay@gmail.com) - * Copyright (C) 2008, 2009 - * Boaz Harrosh - * - * This file is part of exofs. - * - * exofs is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation. Since it is based on ext2, and the only - * valid version of GPL for the Linux kernel is version 2, the only valid - * version of GPL for exofs is version 2. - * - * exofs is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with exofs; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -#include "exofs.h" - -int exofs_check_ok_resid(struct osd_request *or, u64 *in_resid, u64 *out_resid) -{ - struct osd_sense_info osi; - int ret = osd_req_decode_sense(or, &osi); - - if (ret) { /* translate to Linux codes */ - if (osi.additional_code == scsi_invalid_field_in_cdb) { - if (osi.cdb_field_offset == OSD_CFO_STARTING_BYTE) - ret = -EFAULT; - if (osi.cdb_field_offset == OSD_CFO_OBJECT_ID) - ret = -ENOENT; - else - ret = -EINVAL; - } else if (osi.additional_code == osd_quota_error) - ret = -ENOSPC; - else - ret = -EIO; - } - - /* FIXME: should be include in osd_sense_info */ - if (in_resid) - *in_resid = or->in.req ? or->in.req->resid_len : 0; - - if (out_resid) - *out_resid = or->out.req ? or->out.req->resid_len : 0; - - return ret; -} - -void exofs_make_credential(u8 cred_a[OSD_CAP_LEN], const struct osd_obj_id *obj) -{ - osd_sec_init_nosec_doall_caps(cred_a, obj, false, true); -} - -/* - * Perform a synchronous OSD operation. - */ -int exofs_sync_op(struct osd_request *or, int timeout, uint8_t *credential) -{ - int ret; - - or->timeout = timeout; - ret = osd_finalize_request(or, 0, credential, NULL); - if (ret) { - EXOFS_DBGMSG("Faild to osd_finalize_request() => %d\n", ret); - return ret; - } - - ret = osd_execute_request(or); - - if (ret) - EXOFS_DBGMSG("osd_execute_request() => %d\n", ret); - /* osd_req_decode_sense(or, ret); */ - return ret; -} - -/* - * Perform an asynchronous OSD operation. - */ -int exofs_async_op(struct osd_request *or, osd_req_done_fn *async_done, - void *caller_context, u8 *cred) -{ - int ret; - - ret = osd_finalize_request(or, 0, cred, NULL); - if (ret) { - EXOFS_DBGMSG("Faild to osd_finalize_request() => %d\n", ret); - return ret; - } - - ret = osd_execute_request_async(or, async_done, caller_context); - - if (ret) - EXOFS_DBGMSG("osd_execute_request_async() => %d\n", ret); - return ret; -} - -int extract_attr_from_req(struct osd_request *or, struct osd_attr *attr) -{ - struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */ - void *iter = NULL; - int nelem; - - do { - nelem = 1; - osd_req_decode_get_attr_list(or, &cur_attr, &nelem, &iter); - if ((cur_attr.attr_page == attr->attr_page) && - (cur_attr.attr_id == attr->attr_id)) { - attr->len = cur_attr.len; - attr->val_ptr = cur_attr.val_ptr; - return 0; - } - } while (iter); - - return -EIO; -} diff --git a/fs/exofs/pnfs.h b/fs/exofs/pnfs.h new file mode 100644 index 0000000000000000000000000000000000000000..423033addd1fef0deb5fd7eb04339ecabc19ee2b --- /dev/null +++ b/fs/exofs/pnfs.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2008, 2009 + * Boaz Harrosh + * + * This file is part of exofs. + * + * exofs 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. + * + */ + +/* FIXME: Remove this file once pnfs hits mainline */ + +#ifndef __EXOFS_PNFS_H__ +#define __EXOFS_PNFS_H__ + +#if defined(CONFIG_PNFS) + + +/* FIXME: move this file to: linux/exportfs/pnfs_osd_xdr.h */ +#include "../nfs/objlayout/pnfs_osd_xdr.h" + +#else /* defined(CONFIG_PNFS) */ + +enum pnfs_iomode { + IOMODE_READ = 1, + IOMODE_RW = 2, + IOMODE_ANY = 3, +}; + +/* Layout Structure */ +enum pnfs_osd_raid_algorithm4 { + PNFS_OSD_RAID_0 = 1, + PNFS_OSD_RAID_4 = 2, + PNFS_OSD_RAID_5 = 3, + PNFS_OSD_RAID_PQ = 4 /* Reed-Solomon P+Q */ +}; + +struct pnfs_osd_data_map { + u32 odm_num_comps; + u64 odm_stripe_unit; + u32 odm_group_width; + u32 odm_group_depth; + u32 odm_mirror_cnt; + u32 odm_raid_algorithm; +}; + +#endif /* else defined(CONFIG_PNFS) */ + +#endif /* __EXOFS_PNFS_H__ */ diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 9f500dec3b5901982adcc2618670f72ca4b3c01a..a1d1e77b12eb45caa1a74463e645b36d1d7f2b9b 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -203,49 +203,45 @@ int exofs_sync_fs(struct super_block *sb, int wait) { struct exofs_sb_info *sbi; struct exofs_fscb *fscb; - struct osd_request *or; - struct osd_obj_id obj; + struct exofs_io_state *ios; int ret = -ENOMEM; - fscb = kzalloc(sizeof(struct exofs_fscb), GFP_KERNEL); - if (!fscb) { - EXOFS_ERR("exofs_write_super: memory allocation failed.\n"); - return -ENOMEM; - } - lock_super(sb); sbi = sb->s_fs_info; + fscb = &sbi->s_fscb; + + ret = exofs_get_io_state(sbi, &ios); + if (ret) + goto out; + + /* Note: We only write the changing part of the fscb. .i.e upto the + * the fscb->s_dev_table_oid member. There is no read-modify-write + * here. + */ + ios->length = offsetof(struct exofs_fscb, s_dev_table_oid); + memset(fscb, 0, ios->length); fscb->s_nextid = cpu_to_le64(sbi->s_nextid); fscb->s_numfiles = cpu_to_le32(sbi->s_numfiles); fscb->s_magic = cpu_to_le16(sb->s_magic); fscb->s_newfs = 0; + fscb->s_version = EXOFS_FSCB_VER; - or = osd_start_request(sbi->s_dev, GFP_KERNEL); - if (unlikely(!or)) { - EXOFS_ERR("exofs_write_super: osd_start_request failed.\n"); - goto out; - } + ios->obj.id = EXOFS_SUPER_ID; + ios->offset = 0; + ios->kern_buff = fscb; + ios->cred = sbi->s_cred; - obj.partition = sbi->s_pid; - obj.id = EXOFS_SUPER_ID; - ret = osd_req_write_kern(or, &obj, 0, fscb, sizeof(*fscb)); + ret = exofs_sbi_write(ios); if (unlikely(ret)) { - EXOFS_ERR("exofs_write_super: osd_req_write_kern failed.\n"); - goto out; - } - - ret = exofs_sync_op(or, sbi->s_timeout, sbi->s_cred); - if (unlikely(ret)) { - EXOFS_ERR("exofs_write_super: exofs_sync_op failed.\n"); + EXOFS_ERR("%s: exofs_sbi_write failed.\n", __func__); goto out; } sb->s_dirt = 0; out: - if (or) - osd_end_request(or); + EXOFS_DBGMSG("s_nextid=0x%llx ret=%d\n", _LLU(sbi->s_nextid), ret); + exofs_put_io_state(ios); unlock_super(sb); - kfree(fscb); return ret; } @@ -257,6 +253,29 @@ static void exofs_write_super(struct super_block *sb) sb->s_dirt = 0; } +static void _exofs_print_device(const char *msg, const char *dev_path, + struct osd_dev *od, u64 pid) +{ + const struct osd_dev_info *odi = osduld_device_info(od); + + printk(KERN_NOTICE "exofs: %s %s osd_name-%s pid-0x%llx\n", + msg, dev_path ?: "", odi->osdname, _LLU(pid)); +} + +void exofs_free_sbi(struct exofs_sb_info *sbi) +{ + while (sbi->s_numdevs) { + int i = --sbi->s_numdevs; + struct osd_dev *od = sbi->s_ods[i]; + + if (od) { + sbi->s_ods[i] = NULL; + osduld_put_device(od); + } + } + kfree(sbi); +} + /* * This function is called when the vfs is freeing the superblock. We just * need to free our own part. @@ -279,11 +298,182 @@ static void exofs_put_super(struct super_block *sb) msecs_to_jiffies(100)); } - osduld_put_device(sbi->s_dev); - kfree(sb->s_fs_info); + _exofs_print_device("Unmounting", NULL, sbi->s_ods[0], sbi->s_pid); + + exofs_free_sbi(sbi); sb->s_fs_info = NULL; } +static int _read_and_match_data_map(struct exofs_sb_info *sbi, unsigned numdevs, + struct exofs_device_table *dt) +{ + sbi->data_map.odm_num_comps = + le32_to_cpu(dt->dt_data_map.cb_num_comps); + sbi->data_map.odm_stripe_unit = + le64_to_cpu(dt->dt_data_map.cb_stripe_unit); + sbi->data_map.odm_group_width = + le32_to_cpu(dt->dt_data_map.cb_group_width); + sbi->data_map.odm_group_depth = + le32_to_cpu(dt->dt_data_map.cb_group_depth); + sbi->data_map.odm_mirror_cnt = + le32_to_cpu(dt->dt_data_map.cb_mirror_cnt); + sbi->data_map.odm_raid_algorithm = + le32_to_cpu(dt->dt_data_map.cb_raid_algorithm); + +/* FIXME: Hard coded mirror only for now. if not so do not mount */ + if ((sbi->data_map.odm_num_comps != numdevs) || + (sbi->data_map.odm_stripe_unit != EXOFS_BLKSIZE) || + (sbi->data_map.odm_raid_algorithm != PNFS_OSD_RAID_0) || + (sbi->data_map.odm_mirror_cnt != (numdevs - 1))) + return -EINVAL; + else + return 0; +} + +/* @odi is valid only as long as @fscb_dev is valid */ +static int exofs_devs_2_odi(struct exofs_dt_device_info *dt_dev, + struct osd_dev_info *odi) +{ + odi->systemid_len = le32_to_cpu(dt_dev->systemid_len); + memcpy(odi->systemid, dt_dev->systemid, odi->systemid_len); + + odi->osdname_len = le32_to_cpu(dt_dev->osdname_len); + odi->osdname = dt_dev->osdname; + + /* FIXME support long names. Will need a _put function */ + if (dt_dev->long_name_offset) + return -EINVAL; + + /* Make sure osdname is printable! + * mkexofs should give us space for a null-terminator else the + * device-table is invalid. + */ + if (unlikely(odi->osdname_len >= sizeof(dt_dev->osdname))) + odi->osdname_len = sizeof(dt_dev->osdname) - 1; + dt_dev->osdname[odi->osdname_len] = 0; + + /* If it's all zeros something is bad we read past end-of-obj */ + return !(odi->systemid_len || odi->osdname_len); +} + +static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi, + unsigned table_count) +{ + struct exofs_sb_info *sbi = *psbi; + struct osd_dev *fscb_od; + struct osd_obj_id obj = {.partition = sbi->s_pid, + .id = EXOFS_DEVTABLE_ID}; + struct exofs_device_table *dt; + unsigned table_bytes = table_count * sizeof(dt->dt_dev_table[0]) + + sizeof(*dt); + unsigned numdevs, i; + int ret; + + dt = kmalloc(table_bytes, GFP_KERNEL); + if (unlikely(!dt)) { + EXOFS_ERR("ERROR: allocating %x bytes for device table\n", + table_bytes); + return -ENOMEM; + } + + fscb_od = sbi->s_ods[0]; + sbi->s_ods[0] = NULL; + sbi->s_numdevs = 0; + ret = exofs_read_kern(fscb_od, sbi->s_cred, &obj, 0, dt, table_bytes); + if (unlikely(ret)) { + EXOFS_ERR("ERROR: reading device table\n"); + goto out; + } + + numdevs = le64_to_cpu(dt->dt_num_devices); + if (unlikely(!numdevs)) { + ret = -EINVAL; + goto out; + } + WARN_ON(table_count != numdevs); + + ret = _read_and_match_data_map(sbi, numdevs, dt); + if (unlikely(ret)) + goto out; + + if (likely(numdevs > 1)) { + unsigned size = numdevs * sizeof(sbi->s_ods[0]); + + sbi = krealloc(sbi, sizeof(*sbi) + size, GFP_KERNEL); + if (unlikely(!sbi)) { + ret = -ENOMEM; + goto out; + } + memset(&sbi->s_ods[1], 0, size - sizeof(sbi->s_ods[0])); + *psbi = sbi; + } + + for (i = 0; i < numdevs; i++) { + struct exofs_fscb fscb; + struct osd_dev_info odi; + struct osd_dev *od; + + if (exofs_devs_2_odi(&dt->dt_dev_table[i], &odi)) { + EXOFS_ERR("ERROR: Read all-zeros device entry\n"); + ret = -EINVAL; + goto out; + } + + printk(KERN_NOTICE "Add device[%d]: osd_name-%s\n", + i, odi.osdname); + + /* On all devices the device table is identical. The user can + * specify any one of the participating devices on the command + * line. We always keep them in device-table order. + */ + if (fscb_od && osduld_device_same(fscb_od, &odi)) { + sbi->s_ods[i] = fscb_od; + ++sbi->s_numdevs; + fscb_od = NULL; + continue; + } + + od = osduld_info_lookup(&odi); + if (unlikely(IS_ERR(od))) { + ret = PTR_ERR(od); + EXOFS_ERR("ERROR: device requested is not found " + "osd_name-%s =>%d\n", odi.osdname, ret); + goto out; + } + + sbi->s_ods[i] = od; + ++sbi->s_numdevs; + + /* Read the fscb of the other devices to make sure the FS + * partition is there. + */ + ret = exofs_read_kern(od, sbi->s_cred, &obj, 0, &fscb, + sizeof(fscb)); + if (unlikely(ret)) { + EXOFS_ERR("ERROR: Malformed participating device " + "error reading fscb osd_name-%s\n", + odi.osdname); + goto out; + } + + /* TODO: verify other information is correct and FS-uuid + * matches. Benny what did you say about device table + * generation and old devices? + */ + } + +out: + kfree(dt); + if (unlikely(!ret && fscb_od)) { + EXOFS_ERR( + "ERROR: Bad device-table container device not present\n"); + osduld_put_device(fscb_od); + ret = -EINVAL; + } + + return ret; +} + /* * Read the superblock from the OSD and fill in the fields */ @@ -292,24 +482,25 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) struct inode *root; struct exofs_mountopt *opts = data; struct exofs_sb_info *sbi; /*extended info */ + struct osd_dev *od; /* Master device */ struct exofs_fscb fscb; /*on-disk superblock info */ - struct osd_request *or = NULL; struct osd_obj_id obj; + unsigned table_count; int ret; sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) return -ENOMEM; - sb->s_fs_info = sbi; /* use mount options to fill superblock */ - sbi->s_dev = osduld_path_lookup(opts->dev_name); - if (IS_ERR(sbi->s_dev)) { - ret = PTR_ERR(sbi->s_dev); - sbi->s_dev = NULL; + od = osduld_path_lookup(opts->dev_name); + if (IS_ERR(od)) { + ret = PTR_ERR(od); goto free_sbi; } + sbi->s_ods[0] = od; + sbi->s_numdevs = 1; sbi->s_pid = opts->pid; sbi->s_timeout = opts->timeout; @@ -323,35 +514,13 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) sb->s_bdev = NULL; sb->s_dev = 0; - /* read data from on-disk superblock object */ obj.partition = sbi->s_pid; obj.id = EXOFS_SUPER_ID; exofs_make_credential(sbi->s_cred, &obj); - or = osd_start_request(sbi->s_dev, GFP_KERNEL); - if (unlikely(!or)) { - if (!silent) - EXOFS_ERR( - "exofs_fill_super: osd_start_request failed.\n"); - ret = -ENOMEM; - goto free_sbi; - } - ret = osd_req_read_kern(or, &obj, 0, &fscb, sizeof(fscb)); - if (unlikely(ret)) { - if (!silent) - EXOFS_ERR( - "exofs_fill_super: osd_req_read_kern failed.\n"); - ret = -ENOMEM; - goto free_sbi; - } - - ret = exofs_sync_op(or, sbi->s_timeout, sbi->s_cred); - if (unlikely(ret)) { - if (!silent) - EXOFS_ERR("exofs_fill_super: exofs_sync_op failed.\n"); - ret = -EIO; + ret = exofs_read_kern(od, sbi->s_cred, &obj, 0, &fscb, sizeof(fscb)); + if (unlikely(ret)) goto free_sbi; - } sb->s_magic = le16_to_cpu(fscb.s_magic); sbi->s_nextid = le64_to_cpu(fscb.s_nextid); @@ -364,12 +533,26 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) ret = -EINVAL; goto free_sbi; } + if (le32_to_cpu(fscb.s_version) != EXOFS_FSCB_VER) { + EXOFS_ERR("ERROR: Bad FSCB version expected-%d got-%d\n", + EXOFS_FSCB_VER, le32_to_cpu(fscb.s_version)); + ret = -EINVAL; + goto free_sbi; + } /* start generation numbers from a random point */ get_random_bytes(&sbi->s_next_generation, sizeof(u32)); spin_lock_init(&sbi->s_next_gen_lock); + table_count = le64_to_cpu(fscb.s_dev_table_count); + if (table_count) { + ret = exofs_read_lookup_dev_table(&sbi, table_count); + if (unlikely(ret)) + goto free_sbi; + } + /* set up operation vectors */ + sb->s_fs_info = sbi; sb->s_op = &exofs_sops; sb->s_export_op = &exofs_export_ops; root = exofs_iget(sb, EXOFS_ROOT_ID - EXOFS_OBJ_OFF); @@ -395,16 +578,15 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) goto free_sbi; } - ret = 0; -out: - if (or) - osd_end_request(or); - return ret; + _exofs_print_device("Mounting", opts->dev_name, sbi->s_ods[0], + sbi->s_pid); + return 0; free_sbi: - osduld_put_device(sbi->s_dev); /* NULL safe */ - kfree(sbi); - goto out; + EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n", + opts->dev_name, sbi->s_pid, ret); + exofs_free_sbi(sbi); + return ret; } /* @@ -433,7 +615,7 @@ static int exofs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; struct exofs_sb_info *sbi = sb->s_fs_info; - struct osd_obj_id obj = {sbi->s_pid, 0}; + struct exofs_io_state *ios; struct osd_attr attrs[] = { ATTR_DEF(OSD_APAGE_PARTITION_QUOTAS, OSD_ATTR_PQ_CAPACITY_QUOTA, sizeof(__be64)), @@ -442,32 +624,33 @@ static int exofs_statfs(struct dentry *dentry, struct kstatfs *buf) }; uint64_t capacity = ULLONG_MAX; uint64_t used = ULLONG_MAX; - struct osd_request *or; uint8_t cred_a[OSD_CAP_LEN]; int ret; - /* get used/capacity attributes */ - exofs_make_credential(cred_a, &obj); - - or = osd_start_request(sbi->s_dev, GFP_KERNEL); - if (unlikely(!or)) { - EXOFS_DBGMSG("exofs_statfs: osd_start_request failed.\n"); - return -ENOMEM; + ret = exofs_get_io_state(sbi, &ios); + if (ret) { + EXOFS_DBGMSG("exofs_get_io_state failed.\n"); + return ret; } - osd_req_get_attributes(or, &obj); - osd_req_add_get_attr_list(or, attrs, ARRAY_SIZE(attrs)); - ret = exofs_sync_op(or, sbi->s_timeout, cred_a); + exofs_make_credential(cred_a, &ios->obj); + ios->cred = sbi->s_cred; + ios->in_attr = attrs; + ios->in_attr_len = ARRAY_SIZE(attrs); + + ret = exofs_sbi_read(ios); if (unlikely(ret)) goto out; - ret = extract_attr_from_req(or, &attrs[0]); - if (likely(!ret)) + ret = extract_attr_from_ios(ios, &attrs[0]); + if (likely(!ret)) { capacity = get_unaligned_be64(attrs[0].val_ptr); - else + if (unlikely(!capacity)) + capacity = ULLONG_MAX; + } else EXOFS_DBGMSG("exofs_statfs: get capacity failed.\n"); - ret = extract_attr_from_req(or, &attrs[1]); + ret = extract_attr_from_ios(ios, &attrs[1]); if (likely(!ret)) used = get_unaligned_be64(attrs[1].val_ptr); else @@ -476,15 +659,15 @@ static int exofs_statfs(struct dentry *dentry, struct kstatfs *buf) /* fill in the stats buffer */ buf->f_type = EXOFS_SUPER_MAGIC; buf->f_bsize = EXOFS_BLKSIZE; - buf->f_blocks = (capacity >> EXOFS_BLKSHIFT); - buf->f_bfree = ((capacity - used) >> EXOFS_BLKSHIFT); + buf->f_blocks = capacity >> 9; + buf->f_bfree = (capacity - used) >> 9; buf->f_bavail = buf->f_bfree; buf->f_files = sbi->s_numfiles; buf->f_ffree = EXOFS_MAX_ID - sbi->s_numfiles; buf->f_namelen = EXOFS_NAME_LEN; out: - osd_end_request(or); + exofs_put_io_state(ios); return ret; } diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 6cde970b0a1a04fae6b58aec7600491800078333..fc2bd05d35591103587c53bb9dbbfe3348c51c9a 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -353,8 +353,8 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) * ext2_find_entry() * * finds an entry in the specified directory with the wanted name. It - * returns the page in which the entry was found, and the entry itself - * (as a parameter - res_dir). Page is returned mapped and unlocked. + * returns the page in which the entry was found (as a parameter - res_page), + * and the entry itself. Page is returned mapped and unlocked. * Entry is guaranteed to be valid. */ struct ext2_dir_entry_2 *ext2_find_entry (struct inode * dir, diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 9a8a8e27a063963210056c42feab2b335c89b566..da318b0fa6370f0ff266ccb4117aa5556767725e 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -142,7 +142,7 @@ struct dentry *ext2_get_parent(struct dentry *child); /* super.c */ extern void ext2_error (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); -extern void ext2_warning (struct super_block *, const char *, const char *, ...) +extern void ext2_msg(struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); extern void ext2_update_dynamic_rev (struct super_block *sb); extern void ext2_write_super (struct super_block *); diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index ade634076d0ab75371a852f0ec3c50d198a9012e..71b032c65a0220d6e9e6cea12d4621b61acca89b 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -137,7 +137,8 @@ static int ext2_block_to_path(struct inode *inode, int final = 0; if (i_block < 0) { - ext2_warning (inode->i_sb, "ext2_block_to_path", "block < 0"); + ext2_msg(inode->i_sb, KERN_WARNING, + "warning: %s: block < 0", __func__); } else if (i_block < direct_blocks) { offsets[n++] = i_block; final = direct_blocks; @@ -157,7 +158,8 @@ static int ext2_block_to_path(struct inode *inode, offsets[n++] = i_block & (ptrs - 1); final = ptrs; } else { - ext2_warning (inode->i_sb, "ext2_block_to_path", "block > big"); + ext2_msg(inode->i_sb, KERN_WARNING, + "warning: %s: block is too big", __func__); } if (boundary) *boundary = final - 1 - (i_block & (ptrs - 1)); diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 1a9ffee47d56c545dcc9420680178fb32ea6c374..1388802b78030802f419bb1a31f7bd913a2442ab 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -58,27 +58,27 @@ void ext2_error (struct super_block * sb, const char * function, } va_start(args, fmt); - printk(KERN_CRIT "EXT2-fs error (device %s): %s: ",sb->s_id, function); + printk(KERN_CRIT "EXT2-fs (%s): error: %s: ", sb->s_id, function); vprintk(fmt, args); printk("\n"); va_end(args); if (test_opt(sb, ERRORS_PANIC)) - panic("EXT2-fs panic from previous error\n"); + panic("EXT2-fs: panic from previous error\n"); if (test_opt(sb, ERRORS_RO)) { - printk("Remounting filesystem read-only\n"); + ext2_msg(sb, KERN_CRIT, + "error: remounting filesystem read-only"); sb->s_flags |= MS_RDONLY; } } -void ext2_warning (struct super_block * sb, const char * function, - const char * fmt, ...) +void ext2_msg(struct super_block *sb, const char *prefix, + const char *fmt, ...) { va_list args; va_start(args, fmt); - printk(KERN_WARNING "EXT2-fs warning (device %s): %s: ", - sb->s_id, function); + printk("%sEXT2-fs (%s): ", prefix, sb->s_id); vprintk(fmt, args); printk("\n"); va_end(args); @@ -91,9 +91,9 @@ void ext2_update_dynamic_rev(struct super_block *sb) if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV) return; - ext2_warning(sb, __func__, - "updating to rev %d because of new feature flag, " - "running e2fsck is recommended", + ext2_msg(sb, KERN_WARNING, + "warning: updating to rev %d because of " + "new feature flag, running e2fsck is recommended", EXT2_DYNAMIC_REV); es->s_first_ino = cpu_to_le32(EXT2_GOOD_OLD_FIRST_INO); @@ -419,10 +419,10 @@ static const match_table_t tokens = { {Opt_err, NULL} }; -static int parse_options (char * options, - struct ext2_sb_info *sbi) +static int parse_options(char *options, struct super_block *sb) { - char * p; + char *p; + struct ext2_sb_info *sbi = EXT2_SB(sb); substring_t args[MAX_OPT_ARGS]; int option; @@ -505,7 +505,8 @@ static int parse_options (char * options, #else case Opt_user_xattr: case Opt_nouser_xattr: - printk("EXT2 (no)user_xattr options not supported\n"); + ext2_msg(sb, KERN_INFO, "(no)user_xattr options" + "not supported"); break; #endif #ifdef CONFIG_EXT2_FS_POSIX_ACL @@ -518,14 +519,15 @@ static int parse_options (char * options, #else case Opt_acl: case Opt_noacl: - printk("EXT2 (no)acl options not supported\n"); + ext2_msg(sb, KERN_INFO, + "(no)acl options not supported"); break; #endif case Opt_xip: #ifdef CONFIG_EXT2_FS_XIP set_opt (sbi->s_mount_opt, XIP); #else - printk("EXT2 xip option not supported\n"); + ext2_msg(sb, KERN_INFO, "xip option not supported"); #endif break; @@ -542,19 +544,18 @@ static int parse_options (char * options, case Opt_quota: case Opt_usrquota: case Opt_grpquota: - printk(KERN_ERR - "EXT2-fs: quota operations not supported.\n"); - + ext2_msg(sb, KERN_INFO, + "quota operations not supported"); break; #endif case Opt_reservation: set_opt(sbi->s_mount_opt, RESERVATION); - printk("reservations ON\n"); + ext2_msg(sb, KERN_INFO, "reservations ON"); break; case Opt_noreservation: clear_opt(sbi->s_mount_opt, RESERVATION); - printk("reservations OFF\n"); + ext2_msg(sb, KERN_INFO, "reservations OFF"); break; case Opt_ignore: break; @@ -573,34 +574,40 @@ static int ext2_setup_super (struct super_block * sb, struct ext2_sb_info *sbi = EXT2_SB(sb); if (le32_to_cpu(es->s_rev_level) > EXT2_MAX_SUPP_REV) { - printk ("EXT2-fs warning: revision level too high, " - "forcing read-only mode\n"); + ext2_msg(sb, KERN_ERR, + "error: revision level too high, " + "forcing read-only mode"); res = MS_RDONLY; } if (read_only) return res; if (!(sbi->s_mount_state & EXT2_VALID_FS)) - printk ("EXT2-fs warning: mounting unchecked fs, " - "running e2fsck is recommended\n"); + ext2_msg(sb, KERN_WARNING, + "warning: mounting unchecked fs, " + "running e2fsck is recommended"); else if ((sbi->s_mount_state & EXT2_ERROR_FS)) - printk ("EXT2-fs warning: mounting fs with errors, " - "running e2fsck is recommended\n"); + ext2_msg(sb, KERN_WARNING, + "warning: mounting fs with errors, " + "running e2fsck is recommended"); else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 && le16_to_cpu(es->s_mnt_count) >= (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count)) - printk ("EXT2-fs warning: maximal mount count reached, " - "running e2fsck is recommended\n"); + ext2_msg(sb, KERN_WARNING, + "warning: maximal mount count reached, " + "running e2fsck is recommended"); else if (le32_to_cpu(es->s_checkinterval) && - (le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= get_seconds())) - printk ("EXT2-fs warning: checktime reached, " - "running e2fsck is recommended\n"); + (le32_to_cpu(es->s_lastcheck) + + le32_to_cpu(es->s_checkinterval) <= get_seconds())) + ext2_msg(sb, KERN_WARNING, + "warning: checktime reached, " + "running e2fsck is recommended"); if (!le16_to_cpu(es->s_max_mnt_count)) es->s_max_mnt_count = cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT); le16_add_cpu(&es->s_mnt_count, 1); ext2_write_super(sb); if (test_opt (sb, DEBUG)) - printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, " - "bpg=%lu, ipg=%lu, mo=%04lx]\n", + ext2_msg(sb, KERN_INFO, "%s, %s, bs=%lu, fs=%lu, gc=%lu, " + "bpg=%lu, ipg=%lu, mo=%04lx]", EXT2FS_VERSION, EXT2FS_DATE, sb->s_blocksize, sbi->s_frag_size, sbi->s_groups_count, @@ -767,7 +774,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) */ blocksize = sb_min_blocksize(sb, BLOCK_SIZE); if (!blocksize) { - printk ("EXT2-fs: unable to set blocksize\n"); + ext2_msg(sb, KERN_ERR, "error: unable to set blocksize"); goto failed_sbi; } @@ -783,7 +790,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) } if (!(bh = sb_bread(sb, logic_sb_block))) { - printk ("EXT2-fs: unable to read superblock\n"); + ext2_msg(sb, KERN_ERR, "error: unable to read superblock"); goto failed_sbi; } /* @@ -826,7 +833,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) set_opt(sbi->s_mount_opt, RESERVATION); - if (!parse_options ((char *) data, sbi)) + if (!parse_options((char *) data, sb)) goto failed_mount; sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | @@ -840,8 +847,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) || EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) || EXT2_HAS_INCOMPAT_FEATURE(sb, ~0U))) - printk("EXT2-fs warning: feature flags set on rev 0 fs, " - "running e2fsck is recommended\n"); + ext2_msg(sb, KERN_WARNING, + "warning: feature flags set on rev 0 fs, " + "running e2fsck is recommended"); /* * Check feature flags regardless of the revision level, since we * previously didn't change the revision level when setting the flags, @@ -849,16 +857,16 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) */ features = EXT2_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP); if (features) { - printk("EXT2-fs: %s: couldn't mount because of " - "unsupported optional features (%x).\n", - sb->s_id, le32_to_cpu(features)); + ext2_msg(sb, KERN_ERR, "error: couldn't mount because of " + "unsupported optional features (%x)", + le32_to_cpu(features)); goto failed_mount; } if (!(sb->s_flags & MS_RDONLY) && (features = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){ - printk("EXT2-fs: %s: couldn't mount RDWR because of " - "unsupported optional features (%x).\n", - sb->s_id, le32_to_cpu(features)); + ext2_msg(sb, KERN_ERR, "error: couldn't mount RDWR because of " + "unsupported optional features (%x)", + le32_to_cpu(features)); goto failed_mount; } @@ -866,7 +874,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) if (ext2_use_xip(sb) && blocksize != PAGE_SIZE) { if (!silent) - printk("XIP: Unsupported blocksize\n"); + ext2_msg(sb, KERN_ERR, + "error: unsupported blocksize for xip"); goto failed_mount; } @@ -875,7 +884,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) brelse(bh); if (!sb_set_blocksize(sb, blocksize)) { - printk(KERN_ERR "EXT2-fs: blocksize too small for device.\n"); + ext2_msg(sb, KERN_ERR, "error: blocksize is too small"); goto failed_sbi; } @@ -883,14 +892,14 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) offset = (sb_block*BLOCK_SIZE) % blocksize; bh = sb_bread(sb, logic_sb_block); if(!bh) { - printk("EXT2-fs: Couldn't read superblock on " - "2nd try.\n"); + ext2_msg(sb, KERN_ERR, "error: couldn't read" + "superblock on 2nd try"); goto failed_sbi; } es = (struct ext2_super_block *) (((char *)bh->b_data) + offset); sbi->s_es = es; if (es->s_magic != cpu_to_le16(EXT2_SUPER_MAGIC)) { - printk ("EXT2-fs: Magic mismatch, very weird !\n"); + ext2_msg(sb, KERN_ERR, "error: magic mismatch"); goto failed_mount; } } @@ -906,7 +915,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) if ((sbi->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE) || !is_power_of_2(sbi->s_inode_size) || (sbi->s_inode_size > blocksize)) { - printk ("EXT2-fs: unsupported inode size: %d\n", + ext2_msg(sb, KERN_ERR, + "error: unsupported inode size: %d", sbi->s_inode_size); goto failed_mount; } @@ -943,29 +953,33 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) if (sb->s_blocksize != bh->b_size) { if (!silent) - printk ("VFS: Unsupported blocksize on dev " - "%s.\n", sb->s_id); + ext2_msg(sb, KERN_ERR, "error: unsupported blocksize"); goto failed_mount; } if (sb->s_blocksize != sbi->s_frag_size) { - printk ("EXT2-fs: fragsize %lu != blocksize %lu (not supported yet)\n", + ext2_msg(sb, KERN_ERR, + "error: fragsize %lu != blocksize %lu" + "(not supported yet)", sbi->s_frag_size, sb->s_blocksize); goto failed_mount; } if (sbi->s_blocks_per_group > sb->s_blocksize * 8) { - printk ("EXT2-fs: #blocks per group too big: %lu\n", + ext2_msg(sb, KERN_ERR, + "error: #blocks per group too big: %lu", sbi->s_blocks_per_group); goto failed_mount; } if (sbi->s_frags_per_group > sb->s_blocksize * 8) { - printk ("EXT2-fs: #fragments per group too big: %lu\n", + ext2_msg(sb, KERN_ERR, + "error: #fragments per group too big: %lu", sbi->s_frags_per_group); goto failed_mount; } if (sbi->s_inodes_per_group > sb->s_blocksize * 8) { - printk ("EXT2-fs: #inodes per group too big: %lu\n", + ext2_msg(sb, KERN_ERR, + "error: #inodes per group too big: %lu", sbi->s_inodes_per_group); goto failed_mount; } @@ -979,13 +993,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) EXT2_DESC_PER_BLOCK(sb); sbi->s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL); if (sbi->s_group_desc == NULL) { - printk ("EXT2-fs: not enough memory\n"); + ext2_msg(sb, KERN_ERR, "error: not enough memory"); goto failed_mount; } bgl_lock_init(sbi->s_blockgroup_lock); sbi->s_debts = kcalloc(sbi->s_groups_count, sizeof(*sbi->s_debts), GFP_KERNEL); if (!sbi->s_debts) { - printk ("EXT2-fs: not enough memory\n"); + ext2_msg(sb, KERN_ERR, "error: not enough memory"); goto failed_mount_group_desc; } for (i = 0; i < db_count; i++) { @@ -994,12 +1008,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) if (!sbi->s_group_desc[i]) { for (j = 0; j < i; j++) brelse (sbi->s_group_desc[j]); - printk ("EXT2-fs: unable to read group descriptors\n"); + ext2_msg(sb, KERN_ERR, + "error: unable to read group descriptors"); goto failed_mount_group_desc; } } if (!ext2_check_descriptors (sb)) { - printk ("EXT2-fs: group descriptors corrupted!\n"); + ext2_msg(sb, KERN_ERR, "group descriptors corrupted"); goto failed_mount2; } sbi->s_gdb_count = db_count; @@ -1032,7 +1047,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) ext2_count_dirs(sb)); } if (err) { - printk(KERN_ERR "EXT2-fs: insufficient memory\n"); + ext2_msg(sb, KERN_ERR, "error: insufficient memory"); goto failed_mount3; } /* @@ -1048,27 +1063,28 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) } if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { iput(root); - printk(KERN_ERR "EXT2-fs: corrupt root inode, run e2fsck\n"); + ext2_msg(sb, KERN_ERR, "error: corrupt root inode, run e2fsck"); goto failed_mount3; } sb->s_root = d_alloc_root(root); if (!sb->s_root) { iput(root); - printk(KERN_ERR "EXT2-fs: get root inode failed\n"); + ext2_msg(sb, KERN_ERR, "error: get root inode failed"); ret = -ENOMEM; goto failed_mount3; } if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) - ext2_warning(sb, __func__, - "mounting ext3 filesystem as ext2"); + ext2_msg(sb, KERN_WARNING, + "warning: mounting ext3 filesystem as ext2"); ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); return 0; cantfind_ext2: if (!silent) - printk("VFS: Can't find an ext2 filesystem on dev %s.\n", - sb->s_id); + ext2_msg(sb, KERN_ERR, + "error: can't find an ext2 filesystem on dev %s.", + sb->s_id); goto failed_mount; failed_mount3: percpu_counter_destroy(&sbi->s_freeblocks_counter); @@ -1121,8 +1137,24 @@ static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es) static int ext2_sync_fs(struct super_block *sb, int wait) { struct ext2_super_block *es = EXT2_SB(sb)->s_es; + struct buffer_head *sbh = EXT2_SB(sb)->s_sbh; lock_kernel(); + if (buffer_write_io_error(sbh)) { + /* + * Oh, dear. A previous attempt to write the + * superblock failed. This could happen because the + * USB device was yanked out. Or it could happen to + * be a transient write error and maybe the block will + * be remapped. Nothing we can do but to retry the + * write and hope for the best. + */ + ext2_msg(sb, KERN_ERR, + "previous I/O error to superblock detected\n"); + clear_buffer_write_io_error(sbh); + set_buffer_uptodate(sbh); + } + if (es->s_state & cpu_to_le16(EXT2_VALID_FS)) { ext2_debug("setting valid to 0\n"); es->s_state &= cpu_to_le16(~EXT2_VALID_FS); @@ -1170,7 +1202,7 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) /* * Allow the "check" option to be passed as a remount option. */ - if (!parse_options (data, sbi)) { + if (!parse_options(data, sb)) { err = -EINVAL; goto restore_opts; } @@ -1182,7 +1214,8 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) EXT2_MOUNT_XIP if not */ if ((ext2_use_xip(sb)) && (sb->s_blocksize != PAGE_SIZE)) { - printk("XIP: Unsupported blocksize\n"); + ext2_msg(sb, KERN_WARNING, + "warning: unsupported blocksize for xip"); err = -EINVAL; goto restore_opts; } @@ -1191,8 +1224,8 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) != (old_mount_opt & EXT2_MOUNT_XIP)) && invalidate_inodes(sb)) { - ext2_warning(sb, __func__, "refusing change of xip flag " - "with busy inodes while remounting"); + ext2_msg(sb, KERN_WARNING, "warning: refusing change of " + "xip flag with busy inodes while remounting"); sbi->s_mount_opt &= ~EXT2_MOUNT_XIP; sbi->s_mount_opt |= old_mount_opt & EXT2_MOUNT_XIP; } @@ -1216,9 +1249,10 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) __le32 ret = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP); if (ret) { - printk("EXT2-fs: %s: couldn't remount RDWR because of " - "unsupported optional features (%x).\n", - sb->s_id, le32_to_cpu(ret)); + ext2_msg(sb, KERN_WARNING, + "warning: couldn't remount RDWR because of " + "unsupported optional features (%x).", + le32_to_cpu(ret)); err = -EROFS; goto restore_opts; } diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c index c18fbf3e4068c33429c6c8e3bf3ebcc1844fe505..322a56b2dfb1a190382a68e9844d3425339ab570 100644 --- a/fs/ext2/xip.c +++ b/fs/ext2/xip.c @@ -69,8 +69,9 @@ void ext2_xip_verify_sb(struct super_block *sb) if ((sbi->s_mount_opt & EXT2_MOUNT_XIP) && !sb->s_bdev->bd_disk->fops->direct_access) { sbi->s_mount_opt &= (~EXT2_MOUNT_XIP); - ext2_warning(sb, __func__, - "ignoring xip option - not supported by bdev"); + ext2_msg(sb, KERN_WARNING, + "warning: ignoring xip option - " + "not supported by bdev"); } } diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 2db957778903ba3ef9678c0d51b32b2a34579676..ad14227f509e8ed5bb11d9d8249a842f47bbf94f 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1151,6 +1151,16 @@ static int do_journal_get_write_access(handle_t *handle, return ext3_journal_get_write_access(handle, bh); } +/* + * Truncate blocks that were not used by write. We have to truncate the + * pagecache as well so that corresponding buffers get properly unmapped. + */ +static void ext3_truncate_failed_write(struct inode *inode) +{ + truncate_inode_pages(inode->i_mapping, inode->i_size); + ext3_truncate(inode); +} + static int ext3_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) @@ -1209,7 +1219,7 @@ write_begin_failed: unlock_page(page); page_cache_release(page); if (pos + len > inode->i_size) - ext3_truncate(inode); + ext3_truncate_failed_write(inode); } if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) goto retry; @@ -1304,7 +1314,7 @@ static int ext3_ordered_write_end(struct file *file, page_cache_release(page); if (pos + len > inode->i_size) - ext3_truncate(inode); + ext3_truncate_failed_write(inode); return ret ? ret : copied; } @@ -1330,7 +1340,7 @@ static int ext3_writeback_write_end(struct file *file, page_cache_release(page); if (pos + len > inode->i_size) - ext3_truncate(inode); + ext3_truncate_failed_write(inode); return ret ? ret : copied; } @@ -1383,7 +1393,7 @@ static int ext3_journalled_write_end(struct file *file, page_cache_release(page); if (pos + len > inode->i_size) - ext3_truncate(inode); + ext3_truncate_failed_write(inode); return ret ? ret : copied; } diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index 8359e7b3dc895b5bfc9b2e26f63c0c6de3227acc..5f83b61791786a06eba1d5014697bfbf31fa47ab 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c @@ -266,7 +266,7 @@ static int setup_new_group_blocks(struct super_block *sb, goto exit_bh; if (IS_ERR(gdb = bclean(handle, sb, block))) { - err = PTR_ERR(bh); + err = PTR_ERR(gdb); goto exit_bh; } ext3_journal_dirty_metadata(handle, gdb); diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 427496c4767cda4c542f43cb97b8a3089e77bcce..7ad1e8c30bd0a2adbfdc0268dc34377e47578684 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -135,12 +135,24 @@ void ext3_journal_abort_handle(const char *caller, const char *err_fn, if (is_handle_aborted(handle)) return; - printk(KERN_ERR "%s: aborting transaction: %s in %s\n", - caller, errstr, err_fn); + printk(KERN_ERR "EXT3-fs: %s: aborting transaction: %s in %s\n", + caller, errstr, err_fn); journal_abort_handle(handle); } +void ext3_msg(struct super_block *sb, const char *prefix, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + printk("%sEXT3-fs (%s): ", prefix, sb->s_id); + vprintk(fmt, args); + printk("\n"); + va_end(args); +} + /* Deal with the reporting of failure conditions on a filesystem such as * inconsistencies detected or read IO failures. * @@ -174,12 +186,13 @@ static void ext3_handle_error(struct super_block *sb) journal_abort(journal, -EIO); } if (test_opt (sb, ERRORS_RO)) { - printk (KERN_CRIT "Remounting filesystem read-only\n"); + ext3_msg(sb, KERN_CRIT, + "error: remounting filesystem read-only"); sb->s_flags |= MS_RDONLY; } ext3_commit_super(sb, es, 1); if (test_opt(sb, ERRORS_PANIC)) - panic("EXT3-fs (device %s): panic forced after error\n", + panic("EXT3-fs (%s): panic forced after error\n", sb->s_id); } @@ -247,8 +260,7 @@ void __ext3_std_error (struct super_block * sb, const char * function, return; errstr = ext3_decode_error(sb, errno, nbuf); - printk (KERN_CRIT "EXT3-fs error (device %s) in %s: %s\n", - sb->s_id, function, errstr); + ext3_msg(sb, KERN_CRIT, "error in %s: %s", function, errstr); ext3_handle_error(sb); } @@ -268,21 +280,20 @@ void ext3_abort (struct super_block * sb, const char * function, { va_list args; - printk (KERN_CRIT "ext3_abort called.\n"); - va_start(args, fmt); - printk(KERN_CRIT "EXT3-fs error (device %s): %s: ",sb->s_id, function); + printk(KERN_CRIT "EXT3-fs (%s): error: %s: ", sb->s_id, function); vprintk(fmt, args); printk("\n"); va_end(args); if (test_opt(sb, ERRORS_PANIC)) - panic("EXT3-fs panic from previous error\n"); + panic("EXT3-fs: panic from previous error\n"); if (sb->s_flags & MS_RDONLY) return; - printk(KERN_CRIT "Remounting filesystem read-only\n"); + ext3_msg(sb, KERN_CRIT, + "error: remounting filesystem read-only"); EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS; sb->s_flags |= MS_RDONLY; EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT; @@ -296,7 +307,7 @@ void ext3_warning (struct super_block * sb, const char * function, va_list args; va_start(args, fmt); - printk(KERN_WARNING "EXT3-fs warning (device %s): %s: ", + printk(KERN_WARNING "EXT3-fs (%s): warning: %s: ", sb->s_id, function); vprintk(fmt, args); printk("\n"); @@ -310,10 +321,10 @@ void ext3_update_dynamic_rev(struct super_block *sb) if (le32_to_cpu(es->s_rev_level) > EXT3_GOOD_OLD_REV) return; - ext3_warning(sb, __func__, - "updating to rev %d because of new feature flag, " - "running e2fsck is recommended", - EXT3_DYNAMIC_REV); + ext3_msg(sb, KERN_WARNING, + "warning: updating to rev %d because of " + "new feature flag, running e2fsck is recommended", + EXT3_DYNAMIC_REV); es->s_first_ino = cpu_to_le32(EXT3_GOOD_OLD_FIRST_INO); es->s_inode_size = cpu_to_le16(EXT3_GOOD_OLD_INODE_SIZE); @@ -331,7 +342,7 @@ void ext3_update_dynamic_rev(struct super_block *sb) /* * Open the external journal device */ -static struct block_device *ext3_blkdev_get(dev_t dev) +static struct block_device *ext3_blkdev_get(dev_t dev, struct super_block *sb) { struct block_device *bdev; char b[BDEVNAME_SIZE]; @@ -342,8 +353,9 @@ static struct block_device *ext3_blkdev_get(dev_t dev) return bdev; fail: - printk(KERN_ERR "EXT3: failed to open journal device %s: %ld\n", - __bdevname(dev, b), PTR_ERR(bdev)); + ext3_msg(sb, "error: failed to open journal device %s: %ld", + __bdevname(dev, b), PTR_ERR(bdev)); + return NULL; } @@ -378,13 +390,13 @@ static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi) { struct list_head *l; - printk(KERN_ERR "sb orphan head is %d\n", + ext3_msg(sb, KERN_ERR, "error: sb orphan head is %d", le32_to_cpu(sbi->s_es->s_last_orphan)); - printk(KERN_ERR "sb_info orphan list:\n"); + ext3_msg(sb, KERN_ERR, "sb_info orphan list:"); list_for_each(l, &sbi->s_orphan) { struct inode *inode = orphan_list_entry(l); - printk(KERN_ERR " " + ext3_msg(sb, KERN_ERR, " " "inode %s:%lu at %p: mode %o, nlink %d, next %d\n", inode->i_sb->s_id, inode->i_ino, inode, inode->i_mode, inode->i_nlink, @@ -527,9 +539,22 @@ static inline void ext3_show_quota_options(struct seq_file *seq, struct super_bl #if defined(CONFIG_QUOTA) struct ext3_sb_info *sbi = EXT3_SB(sb); - if (sbi->s_jquota_fmt) - seq_printf(seq, ",jqfmt=%s", - (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold": "vfsv0"); + if (sbi->s_jquota_fmt) { + char *fmtname = ""; + + switch (sbi->s_jquota_fmt) { + case QFMT_VFS_OLD: + fmtname = "vfsold"; + break; + case QFMT_VFS_V0: + fmtname = "vfsv0"; + break; + case QFMT_VFS_V1: + fmtname = "vfsv1"; + break; + } + seq_printf(seq, ",jqfmt=%s", fmtname); + } if (sbi->s_qf_names[USRQUOTA]) seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]); @@ -636,6 +661,9 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs) if (test_opt(sb, DATA_ERR_ABORT)) seq_puts(seq, ",data_err=abort"); + if (test_opt(sb, NOLOAD)) + seq_puts(seq, ",norecovery"); + ext3_show_quota_options(seq, sb); return 0; @@ -787,9 +815,9 @@ enum { Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, Opt_data_err_abort, Opt_data_err_ignore, Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, - Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, - Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, - Opt_grpquota + Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, + Opt_noquota, Opt_ignore, Opt_barrier, Opt_err, Opt_resize, + Opt_usrquota, Opt_grpquota }; static const match_table_t tokens = { @@ -818,6 +846,7 @@ static const match_table_t tokens = { {Opt_reservation, "reservation"}, {Opt_noreservation, "noreservation"}, {Opt_noload, "noload"}, + {Opt_noload, "norecovery"}, {Opt_nobh, "nobh"}, {Opt_bh, "bh"}, {Opt_commit, "commit=%u"}, @@ -836,6 +865,7 @@ static const match_table_t tokens = { {Opt_grpjquota, "grpjquota=%s"}, {Opt_jqfmt_vfsold, "jqfmt=vfsold"}, {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, + {Opt_jqfmt_vfsv1, "jqfmt=vfsv1"}, {Opt_grpquota, "grpquota"}, {Opt_noquota, "noquota"}, {Opt_quota, "quota"}, @@ -845,7 +875,7 @@ static const match_table_t tokens = { {Opt_err, NULL}, }; -static ext3_fsblk_t get_sb_block(void **data) +static ext3_fsblk_t get_sb_block(void **data, struct super_block *sb) { ext3_fsblk_t sb_block; char *options = (char *) *data; @@ -856,7 +886,7 @@ static ext3_fsblk_t get_sb_block(void **data) /*todo: use simple_strtoll with >32bit ext3 */ sb_block = simple_strtoul(options, &options, 0); if (*options && *options != ',') { - printk("EXT3-fs: Invalid sb specification: %s\n", + ext3_msg(sb, "error: invalid sb specification: %s", (char *) *data); return 1; } @@ -956,7 +986,8 @@ static int parse_options (char *options, struct super_block *sb, #else case Opt_user_xattr: case Opt_nouser_xattr: - printk("EXT3 (no)user_xattr options not supported\n"); + ext3_msg(sb, KERN_INFO, + "(no)user_xattr options not supported"); break; #endif #ifdef CONFIG_EXT3_FS_POSIX_ACL @@ -969,7 +1000,8 @@ static int parse_options (char *options, struct super_block *sb, #else case Opt_acl: case Opt_noacl: - printk("EXT3 (no)acl options not supported\n"); + ext3_msg(sb, KERN_INFO, + "(no)acl options not supported"); break; #endif case Opt_reservation: @@ -985,16 +1017,16 @@ static int parse_options (char *options, struct super_block *sb, user to specify an existing inode to be the journal file. */ if (is_remount) { - printk(KERN_ERR "EXT3-fs: cannot specify " - "journal on remount\n"); + ext3_msg(sb, KERN_ERR, "error: cannot specify " + "journal on remount"); return 0; } set_opt (sbi->s_mount_opt, UPDATE_JOURNAL); break; case Opt_journal_inum: if (is_remount) { - printk(KERN_ERR "EXT3-fs: cannot specify " - "journal on remount\n"); + ext3_msg(sb, KERN_ERR, "error: cannot specify " + "journal on remount"); return 0; } if (match_int(&args[0], &option)) @@ -1003,8 +1035,8 @@ static int parse_options (char *options, struct super_block *sb, break; case Opt_journal_dev: if (is_remount) { - printk(KERN_ERR "EXT3-fs: cannot specify " - "journal on remount\n"); + ext3_msg(sb, KERN_ERR, "error: cannot specify " + "journal on remount"); return 0; } if (match_int(&args[0], &option)) @@ -1036,12 +1068,11 @@ static int parse_options (char *options, struct super_block *sb, if ((sbi->s_mount_opt & EXT3_MOUNT_DATA_FLAGS) == data_opt) break; - printk(KERN_ERR - "EXT3-fs (device %s): Cannot change " + ext3_msg(sb, KERN_ERR, + "error: cannot change " "data mode on remount. The filesystem " "is mounted in data=%s mode and you " - "try to remount it in data=%s mode.\n", - sb->s_id, + "try to remount it in data=%s mode.", data_mode_string(sbi->s_mount_opt & EXT3_MOUNT_DATA_FLAGS), data_mode_string(data_opt)); @@ -1066,31 +1097,31 @@ static int parse_options (char *options, struct super_block *sb, set_qf_name: if (sb_any_quota_loaded(sb) && !sbi->s_qf_names[qtype]) { - printk(KERN_ERR - "EXT3-fs: Cannot change journaled " - "quota options when quota turned on.\n"); + ext3_msg(sb, KERN_ERR, + "error: cannot change journaled " + "quota options when quota turned on."); return 0; } qname = match_strdup(&args[0]); if (!qname) { - printk(KERN_ERR - "EXT3-fs: not enough memory for " - "storing quotafile name.\n"); + ext3_msg(sb, KERN_ERR, + "error: not enough memory for " + "storing quotafile name."); return 0; } if (sbi->s_qf_names[qtype] && strcmp(sbi->s_qf_names[qtype], qname)) { - printk(KERN_ERR - "EXT3-fs: %s quota file already " - "specified.\n", QTYPE2NAME(qtype)); + ext3_msg(sb, KERN_ERR, + "error: %s quota file already " + "specified.", QTYPE2NAME(qtype)); kfree(qname); return 0; } sbi->s_qf_names[qtype] = qname; if (strchr(sbi->s_qf_names[qtype], '/')) { - printk(KERN_ERR - "EXT3-fs: quotafile must be on " - "filesystem root.\n"); + ext3_msg(sb, KERN_ERR, + "error: quotafile must be on " + "filesystem root."); kfree(sbi->s_qf_names[qtype]); sbi->s_qf_names[qtype] = NULL; return 0; @@ -1105,9 +1136,9 @@ set_qf_name: clear_qf_name: if (sb_any_quota_loaded(sb) && sbi->s_qf_names[qtype]) { - printk(KERN_ERR "EXT3-fs: Cannot change " + ext3_msg(sb, KERN_ERR, "error: cannot change " "journaled quota options when " - "quota turned on.\n"); + "quota turned on."); return 0; } /* @@ -1121,12 +1152,15 @@ clear_qf_name: goto set_qf_format; case Opt_jqfmt_vfsv0: qfmt = QFMT_VFS_V0; + goto set_qf_format; + case Opt_jqfmt_vfsv1: + qfmt = QFMT_VFS_V1; set_qf_format: if (sb_any_quota_loaded(sb) && sbi->s_jquota_fmt != qfmt) { - printk(KERN_ERR "EXT3-fs: Cannot change " + ext3_msg(sb, KERN_ERR, "error: cannot change " "journaled quota options when " - "quota turned on.\n"); + "quota turned on."); return 0; } sbi->s_jquota_fmt = qfmt; @@ -1142,8 +1176,8 @@ set_qf_format: break; case Opt_noquota: if (sb_any_quota_loaded(sb)) { - printk(KERN_ERR "EXT3-fs: Cannot change quota " - "options when quota turned on.\n"); + ext3_msg(sb, KERN_ERR, "error: cannot change " + "quota options when quota turned on."); return 0; } clear_opt(sbi->s_mount_opt, QUOTA); @@ -1154,8 +1188,8 @@ set_qf_format: case Opt_quota: case Opt_usrquota: case Opt_grpquota: - printk(KERN_ERR - "EXT3-fs: quota options not supported.\n"); + ext3_msg(sb, KERN_ERR, + "error: quota options not supported."); break; case Opt_usrjquota: case Opt_grpjquota: @@ -1163,9 +1197,10 @@ set_qf_format: case Opt_offgrpjquota: case Opt_jqfmt_vfsold: case Opt_jqfmt_vfsv0: - printk(KERN_ERR - "EXT3-fs: journaled quota options not " - "supported.\n"); + case Opt_jqfmt_vfsv1: + ext3_msg(sb, KERN_ERR, + "error: journaled quota options not " + "supported."); break; case Opt_noquota: break; @@ -1185,8 +1220,9 @@ set_qf_format: break; case Opt_resize: if (!is_remount) { - printk("EXT3-fs: resize option only available " - "for remount\n"); + ext3_msg(sb, KERN_ERR, + "error: resize option only available " + "for remount"); return 0; } if (match_int(&args[0], &option) != 0) @@ -1200,9 +1236,9 @@ set_qf_format: clear_opt(sbi->s_mount_opt, NOBH); break; default: - printk (KERN_ERR - "EXT3-fs: Unrecognized mount option \"%s\" " - "or missing value\n", p); + ext3_msg(sb, KERN_ERR, + "error: unrecognized mount option \"%s\" " + "or missing value", p); return 0; } } @@ -1220,21 +1256,21 @@ set_qf_format: (sbi->s_mount_opt & EXT3_MOUNT_GRPQUOTA)) || (sbi->s_qf_names[GRPQUOTA] && (sbi->s_mount_opt & EXT3_MOUNT_USRQUOTA))) { - printk(KERN_ERR "EXT3-fs: old and new quota " - "format mixing.\n"); + ext3_msg(sb, KERN_ERR, "error: old and new quota " + "format mixing."); return 0; } if (!sbi->s_jquota_fmt) { - printk(KERN_ERR "EXT3-fs: journaled quota format " - "not specified.\n"); + ext3_msg(sb, KERN_ERR, "error: journaled quota format " + "not specified."); return 0; } } else { if (sbi->s_jquota_fmt) { - printk(KERN_ERR "EXT3-fs: journaled quota format " + ext3_msg(sb, KERN_ERR, "error: journaled quota format " "specified with no journaling " - "enabled.\n"); + "enabled."); return 0; } } @@ -1249,31 +1285,33 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es, int res = 0; if (le32_to_cpu(es->s_rev_level) > EXT3_MAX_SUPP_REV) { - printk (KERN_ERR "EXT3-fs warning: revision level too high, " - "forcing read-only mode\n"); + ext3_msg(sb, KERN_ERR, + "error: revision level too high, " + "forcing read-only mode"); res = MS_RDONLY; } if (read_only) return res; if (!(sbi->s_mount_state & EXT3_VALID_FS)) - printk (KERN_WARNING "EXT3-fs warning: mounting unchecked fs, " - "running e2fsck is recommended\n"); + ext3_msg(sb, KERN_WARNING, + "warning: mounting unchecked fs, " + "running e2fsck is recommended"); else if ((sbi->s_mount_state & EXT3_ERROR_FS)) - printk (KERN_WARNING - "EXT3-fs warning: mounting fs with errors, " - "running e2fsck is recommended\n"); + ext3_msg(sb, KERN_WARNING, + "warning: mounting fs with errors, " + "running e2fsck is recommended"); else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 && le16_to_cpu(es->s_mnt_count) >= (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count)) - printk (KERN_WARNING - "EXT3-fs warning: maximal mount count reached, " - "running e2fsck is recommended\n"); + ext3_msg(sb, KERN_WARNING, + "warning: maximal mount count reached, " + "running e2fsck is recommended"); else if (le32_to_cpu(es->s_checkinterval) && (le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= get_seconds())) - printk (KERN_WARNING - "EXT3-fs warning: checktime reached, " - "running e2fsck is recommended\n"); + ext3_msg(sb, KERN_WARNING, + "warning: checktime reached, " + "running e2fsck is recommended"); #if 0 /* @@@ We _will_ want to clear the valid bit if we find inconsistencies, to force a fsck at reboot. But for @@ -1290,22 +1328,20 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es, ext3_commit_super(sb, es, 1); if (test_opt(sb, DEBUG)) - printk(KERN_INFO "[EXT3 FS bs=%lu, gc=%lu, " - "bpg=%lu, ipg=%lu, mo=%04lx]\n", + ext3_msg(sb, KERN_INFO, "[bs=%lu, gc=%lu, " + "bpg=%lu, ipg=%lu, mo=%04lx]", sb->s_blocksize, sbi->s_groups_count, EXT3_BLOCKS_PER_GROUP(sb), EXT3_INODES_PER_GROUP(sb), sbi->s_mount_opt); - printk(KERN_INFO "EXT3 FS on %s, ", sb->s_id); if (EXT3_SB(sb)->s_journal->j_inode == NULL) { char b[BDEVNAME_SIZE]; - - printk("external journal on %s\n", + ext3_msg(sb, KERN_INFO, "using external journal on %s", bdevname(EXT3_SB(sb)->s_journal->j_dev, b)); } else { - printk("internal journal\n"); + ext3_msg(sb, KERN_INFO, "using internal journal"); } return res; } @@ -1399,8 +1435,8 @@ static void ext3_orphan_cleanup (struct super_block * sb, } if (bdev_read_only(sb->s_bdev)) { - printk(KERN_ERR "EXT3-fs: write access " - "unavailable, skipping orphan cleanup.\n"); + ext3_msg(sb, KERN_ERR, "error: write access " + "unavailable, skipping orphan cleanup."); return; } @@ -1414,8 +1450,7 @@ static void ext3_orphan_cleanup (struct super_block * sb, } if (s_flags & MS_RDONLY) { - printk(KERN_INFO "EXT3-fs: %s: orphan cleanup on readonly fs\n", - sb->s_id); + ext3_msg(sb, KERN_INFO, "orphan cleanup on readonly fs"); sb->s_flags &= ~MS_RDONLY; } #ifdef CONFIG_QUOTA @@ -1426,9 +1461,9 @@ static void ext3_orphan_cleanup (struct super_block * sb, if (EXT3_SB(sb)->s_qf_names[i]) { int ret = ext3_quota_on_mount(sb, i); if (ret < 0) - printk(KERN_ERR - "EXT3-fs: Cannot turn on journaled " - "quota: error %d\n", ret); + ext3_msg(sb, KERN_ERR, + "error: cannot turn on journaled " + "quota: %d", ret); } } #endif @@ -1466,11 +1501,11 @@ static void ext3_orphan_cleanup (struct super_block * sb, #define PLURAL(x) (x), ((x)==1) ? "" : "s" if (nr_orphans) - printk(KERN_INFO "EXT3-fs: %s: %d orphan inode%s deleted\n", - sb->s_id, PLURAL(nr_orphans)); + ext3_msg(sb, KERN_INFO, "%d orphan inode%s deleted", + PLURAL(nr_orphans)); if (nr_truncates) - printk(KERN_INFO "EXT3-fs: %s: %d truncate%s cleaned up\n", - sb->s_id, PLURAL(nr_truncates)); + ext3_msg(sb, KERN_INFO, "%d truncate%s cleaned up", + PLURAL(nr_truncates)); #ifdef CONFIG_QUOTA /* Turn quotas off */ for (i = 0; i < MAXQUOTAS; i++) { @@ -1554,7 +1589,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) struct ext3_super_block *es = NULL; struct ext3_sb_info *sbi; ext3_fsblk_t block; - ext3_fsblk_t sb_block = get_sb_block(&data); + ext3_fsblk_t sb_block = get_sb_block(&data, sb); ext3_fsblk_t logic_sb_block; unsigned long offset = 0; unsigned int journal_inum = 0; @@ -1590,7 +1625,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE); if (!blocksize) { - printk(KERN_ERR "EXT3-fs: unable to set blocksize\n"); + ext3_msg(sb, KERN_ERR, "error: unable to set blocksize"); goto out_fail; } @@ -1606,7 +1641,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) } if (!(bh = sb_bread(sb, logic_sb_block))) { - printk (KERN_ERR "EXT3-fs: unable to read superblock\n"); + ext3_msg(sb, KERN_ERR, "error: unable to read superblock"); goto out_fail; } /* @@ -1665,9 +1700,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) (EXT3_HAS_COMPAT_FEATURE(sb, ~0U) || EXT3_HAS_RO_COMPAT_FEATURE(sb, ~0U) || EXT3_HAS_INCOMPAT_FEATURE(sb, ~0U))) - printk(KERN_WARNING - "EXT3-fs warning: feature flags set on rev 0 fs, " - "running e2fsck is recommended\n"); + ext3_msg(sb, KERN_WARNING, + "warning: feature flags set on rev 0 fs, " + "running e2fsck is recommended"); /* * Check feature flags regardless of the revision level, since we * previously didn't change the revision level when setting the flags, @@ -1675,25 +1710,25 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) */ features = EXT3_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP); if (features) { - printk(KERN_ERR "EXT3-fs: %s: couldn't mount because of " - "unsupported optional features (%x).\n", - sb->s_id, le32_to_cpu(features)); + ext3_msg(sb, KERN_ERR, + "error: couldn't mount because of unsupported " + "optional features (%x)", le32_to_cpu(features)); goto failed_mount; } features = EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP); if (!(sb->s_flags & MS_RDONLY) && features) { - printk(KERN_ERR "EXT3-fs: %s: couldn't mount RDWR because of " - "unsupported optional features (%x).\n", - sb->s_id, le32_to_cpu(features)); + ext3_msg(sb, KERN_ERR, + "error: couldn't mount RDWR because of unsupported " + "optional features (%x)", le32_to_cpu(features)); goto failed_mount; } blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); if (blocksize < EXT3_MIN_BLOCK_SIZE || blocksize > EXT3_MAX_BLOCK_SIZE) { - printk(KERN_ERR - "EXT3-fs: Unsupported filesystem blocksize %d on %s.\n", - blocksize, sb->s_id); + ext3_msg(sb, KERN_ERR, + "error: couldn't mount because of unsupported " + "filesystem blocksize %d", blocksize); goto failed_mount; } @@ -1704,30 +1739,31 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) * than the hardware sectorsize for the machine. */ if (blocksize < hblock) { - printk(KERN_ERR "EXT3-fs: blocksize %d too small for " - "device blocksize %d.\n", blocksize, hblock); + ext3_msg(sb, KERN_ERR, + "error: fsblocksize %d too small for " + "hardware sectorsize %d", blocksize, hblock); goto failed_mount; } brelse (bh); if (!sb_set_blocksize(sb, blocksize)) { - printk(KERN_ERR "EXT3-fs: bad blocksize %d.\n", - blocksize); + ext3_msg(sb, KERN_ERR, + "error: bad blocksize %d", blocksize); goto out_fail; } logic_sb_block = (sb_block * EXT3_MIN_BLOCK_SIZE) / blocksize; offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize; bh = sb_bread(sb, logic_sb_block); if (!bh) { - printk(KERN_ERR - "EXT3-fs: Can't read superblock on 2nd try.\n"); + ext3_msg(sb, KERN_ERR, + "error: can't read superblock on 2nd try"); goto failed_mount; } es = (struct ext3_super_block *)(((char *)bh->b_data) + offset); sbi->s_es = es; if (es->s_magic != cpu_to_le16(EXT3_SUPER_MAGIC)) { - printk (KERN_ERR - "EXT3-fs: Magic mismatch, very weird !\n"); + ext3_msg(sb, KERN_ERR, + "error: magic mismatch"); goto failed_mount; } } @@ -1743,8 +1779,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) || (!is_power_of_2(sbi->s_inode_size)) || (sbi->s_inode_size > blocksize)) { - printk (KERN_ERR - "EXT3-fs: unsupported inode size: %d\n", + ext3_msg(sb, KERN_ERR, + "error: unsupported inode size: %d", sbi->s_inode_size); goto failed_mount; } @@ -1752,8 +1788,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) sbi->s_frag_size = EXT3_MIN_FRAG_SIZE << le32_to_cpu(es->s_log_frag_size); if (blocksize != sbi->s_frag_size) { - printk(KERN_ERR - "EXT3-fs: fragsize %lu != blocksize %u (unsupported)\n", + ext3_msg(sb, KERN_ERR, + "error: fragsize %lu != blocksize %u (unsupported)", sbi->s_frag_size, blocksize); goto failed_mount; } @@ -1789,31 +1825,31 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) } if (sbi->s_blocks_per_group > blocksize * 8) { - printk (KERN_ERR - "EXT3-fs: #blocks per group too big: %lu\n", + ext3_msg(sb, KERN_ERR, + "#blocks per group too big: %lu", sbi->s_blocks_per_group); goto failed_mount; } if (sbi->s_frags_per_group > blocksize * 8) { - printk (KERN_ERR - "EXT3-fs: #fragments per group too big: %lu\n", + ext3_msg(sb, KERN_ERR, + "error: #fragments per group too big: %lu", sbi->s_frags_per_group); goto failed_mount; } if (sbi->s_inodes_per_group > blocksize * 8) { - printk (KERN_ERR - "EXT3-fs: #inodes per group too big: %lu\n", + ext3_msg(sb, KERN_ERR, + "error: #inodes per group too big: %lu", sbi->s_inodes_per_group); goto failed_mount; } if (le32_to_cpu(es->s_blocks_count) > (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) { - printk(KERN_ERR "EXT3-fs: filesystem on %s:" - " too large to mount safely\n", sb->s_id); + ext3_msg(sb, KERN_ERR, + "error: filesystem is too large to mount safely"); if (sizeof(sector_t) < 8) - printk(KERN_WARNING "EXT3-fs: CONFIG_LBDAF not " - "enabled\n"); + ext3_msg(sb, KERN_ERR, + "error: CONFIG_LBDAF not enabled"); goto failed_mount; } @@ -1827,7 +1863,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *), GFP_KERNEL); if (sbi->s_group_desc == NULL) { - printk (KERN_ERR "EXT3-fs: not enough memory\n"); + ext3_msg(sb, KERN_ERR, + "error: not enough memory"); goto failed_mount; } @@ -1837,14 +1874,15 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) block = descriptor_loc(sb, logic_sb_block, i); sbi->s_group_desc[i] = sb_bread(sb, block); if (!sbi->s_group_desc[i]) { - printk (KERN_ERR "EXT3-fs: " - "can't read group descriptor %d\n", i); + ext3_msg(sb, KERN_ERR, + "error: can't read group descriptor %d", i); db_count = i; goto failed_mount2; } } if (!ext3_check_descriptors (sb)) { - printk(KERN_ERR "EXT3-fs: group descriptors corrupted!\n"); + ext3_msg(sb, KERN_ERR, + "error: group descriptors corrupted"); goto failed_mount2; } sbi->s_gdb_count = db_count; @@ -1862,7 +1900,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) ext3_count_dirs(sb)); } if (err) { - printk(KERN_ERR "EXT3-fs: insufficient memory\n"); + ext3_msg(sb, KERN_ERR, "error: insufficient memory"); goto failed_mount3; } @@ -1910,9 +1948,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) goto failed_mount3; } else { if (!silent) - printk (KERN_ERR - "ext3: No journal on filesystem on %s\n", - sb->s_id); + ext3_msg(sb, KERN_ERR, + "error: no journal found. " + "mounting ext3 over ext2?"); goto failed_mount3; } @@ -1934,8 +1972,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) case EXT3_MOUNT_WRITEBACK_DATA: if (!journal_check_available_features (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) { - printk(KERN_ERR "EXT3-fs: Journal does not support " - "requested data journaling mode\n"); + ext3_msg(sb, KERN_ERR, + "error: journal does not support " + "requested data journaling mode"); goto failed_mount4; } default: @@ -1944,8 +1983,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) if (test_opt(sb, NOBH)) { if (!(test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)) { - printk(KERN_WARNING "EXT3-fs: Ignoring nobh option - " - "its supported only with writeback mode\n"); + ext3_msg(sb, KERN_WARNING, + "warning: ignoring nobh option - " + "it is supported only with writeback mode"); clear_opt(sbi->s_mount_opt, NOBH); } } @@ -1956,18 +1996,18 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) root = ext3_iget(sb, EXT3_ROOT_INO); if (IS_ERR(root)) { - printk(KERN_ERR "EXT3-fs: get root inode failed\n"); + ext3_msg(sb, KERN_ERR, "error: get root inode failed"); ret = PTR_ERR(root); goto failed_mount4; } if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { iput(root); - printk(KERN_ERR "EXT3-fs: corrupt root inode, run e2fsck\n"); + ext3_msg(sb, KERN_ERR, "error: corrupt root inode, run e2fsck"); goto failed_mount4; } sb->s_root = d_alloc_root(root); if (!sb->s_root) { - printk(KERN_ERR "EXT3-fs: get root dentry failed\n"); + ext3_msg(sb, KERN_ERR, "error: get root dentry failed"); iput(root); ret = -ENOMEM; goto failed_mount4; @@ -1986,9 +2026,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) ext3_orphan_cleanup(sb, es); EXT3_SB(sb)->s_mount_state &= ~EXT3_ORPHAN_FS; if (needs_recovery) - printk (KERN_INFO "EXT3-fs: recovery complete.\n"); + ext3_msg(sb, KERN_INFO, "recovery complete"); ext3_mark_recovery_complete(sb, es); - printk (KERN_INFO "EXT3-fs: mounted filesystem with %s data mode.\n", + ext3_msg(sb, KERN_INFO, "mounted filesystem with %s data mode", test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA ? "journal": test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered": "writeback"); @@ -1998,7 +2038,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) cantfind_ext3: if (!silent) - printk(KERN_ERR "VFS: Can't find ext3 filesystem on dev %s.\n", + ext3_msg(sb, KERN_INFO, + "error: can't find ext3 filesystem on dev %s.", sb->s_id); goto failed_mount; @@ -2066,27 +2107,27 @@ static journal_t *ext3_get_journal(struct super_block *sb, journal_inode = ext3_iget(sb, journal_inum); if (IS_ERR(journal_inode)) { - printk(KERN_ERR "EXT3-fs: no journal found.\n"); + ext3_msg(sb, KERN_ERR, "error: no journal found"); return NULL; } if (!journal_inode->i_nlink) { make_bad_inode(journal_inode); iput(journal_inode); - printk(KERN_ERR "EXT3-fs: journal inode is deleted.\n"); + ext3_msg(sb, KERN_ERR, "error: journal inode is deleted"); return NULL; } jbd_debug(2, "Journal inode found at %p: %Ld bytes\n", journal_inode, journal_inode->i_size); if (!S_ISREG(journal_inode->i_mode)) { - printk(KERN_ERR "EXT3-fs: invalid journal inode.\n"); + ext3_msg(sb, KERN_ERR, "error: invalid journal inode"); iput(journal_inode); return NULL; } journal = journal_init_inode(journal_inode); if (!journal) { - printk(KERN_ERR "EXT3-fs: Could not load journal inode\n"); + ext3_msg(sb, KERN_ERR, "error: could not load journal inode"); iput(journal_inode); return NULL; } @@ -2108,13 +2149,13 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb, struct ext3_super_block * es; struct block_device *bdev; - bdev = ext3_blkdev_get(j_dev); + bdev = ext3_blkdev_get(j_dev, sb); if (bdev == NULL) return NULL; if (bd_claim(bdev, sb)) { - printk(KERN_ERR - "EXT3: failed to claim external journal device.\n"); + ext3_msg(sb, KERN_ERR, + "error: failed to claim external journal device"); blkdev_put(bdev, FMODE_READ|FMODE_WRITE); return NULL; } @@ -2122,8 +2163,8 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb, blocksize = sb->s_blocksize; hblock = bdev_logical_block_size(bdev); if (blocksize < hblock) { - printk(KERN_ERR - "EXT3-fs: blocksize too small for journal device.\n"); + ext3_msg(sb, KERN_ERR, + "error: blocksize too small for journal device"); goto out_bdev; } @@ -2131,8 +2172,8 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb, offset = EXT3_MIN_BLOCK_SIZE % blocksize; set_blocksize(bdev, blocksize); if (!(bh = __bread(bdev, sb_block, blocksize))) { - printk(KERN_ERR "EXT3-fs: couldn't read superblock of " - "external journal\n"); + ext3_msg(sb, KERN_ERR, "error: couldn't read superblock of " + "external journal"); goto out_bdev; } @@ -2140,14 +2181,14 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb, if ((le16_to_cpu(es->s_magic) != EXT3_SUPER_MAGIC) || !(le32_to_cpu(es->s_feature_incompat) & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { - printk(KERN_ERR "EXT3-fs: external journal has " - "bad superblock\n"); + ext3_msg(sb, KERN_ERR, "error: external journal has " + "bad superblock"); brelse(bh); goto out_bdev; } if (memcmp(EXT3_SB(sb)->s_es->s_journal_uuid, es->s_uuid, 16)) { - printk(KERN_ERR "EXT3-fs: journal UUID does not match\n"); + ext3_msg(sb, KERN_ERR, "error: journal UUID does not match"); brelse(bh); goto out_bdev; } @@ -2159,19 +2200,21 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb, journal = journal_init_dev(bdev, sb->s_bdev, start, len, blocksize); if (!journal) { - printk(KERN_ERR "EXT3-fs: failed to create device journal\n"); + ext3_msg(sb, KERN_ERR, + "error: failed to create device journal"); goto out_bdev; } journal->j_private = sb; ll_rw_block(READ, 1, &journal->j_sb_buffer); wait_on_buffer(journal->j_sb_buffer); if (!buffer_uptodate(journal->j_sb_buffer)) { - printk(KERN_ERR "EXT3-fs: I/O error on journal device\n"); + ext3_msg(sb, KERN_ERR, "I/O error on journal device"); goto out_journal; } if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) { - printk(KERN_ERR "EXT3-fs: External journal has more than one " - "user (unsupported) - %d\n", + ext3_msg(sb, KERN_ERR, + "error: external journal has more than one " + "user (unsupported) - %d", be32_to_cpu(journal->j_superblock->s_nr_users)); goto out_journal; } @@ -2197,8 +2240,8 @@ static int ext3_load_journal(struct super_block *sb, if (journal_devnum && journal_devnum != le32_to_cpu(es->s_journal_dev)) { - printk(KERN_INFO "EXT3-fs: external journal device major/minor " - "numbers have changed\n"); + ext3_msg(sb, KERN_INFO, "external journal device major/minor " + "numbers have changed"); journal_dev = new_decode_dev(journal_devnum); } else journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev)); @@ -2213,21 +2256,21 @@ static int ext3_load_journal(struct super_block *sb, if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER)) { if (sb->s_flags & MS_RDONLY) { - printk(KERN_INFO "EXT3-fs: INFO: recovery " - "required on readonly filesystem.\n"); + ext3_msg(sb, KERN_INFO, + "recovery required on readonly filesystem"); if (really_read_only) { - printk(KERN_ERR "EXT3-fs: write access " - "unavailable, cannot proceed.\n"); + ext3_msg(sb, KERN_ERR, "error: write access " + "unavailable, cannot proceed"); return -EROFS; } - printk (KERN_INFO "EXT3-fs: write access will " - "be enabled during recovery.\n"); + ext3_msg(sb, KERN_INFO, + "write access will be enabled during recovery"); } } if (journal_inum && journal_dev) { - printk(KERN_ERR "EXT3-fs: filesystem has both journal " - "and inode journals!\n"); + ext3_msg(sb, KERN_ERR, "error: filesystem has both journal " + "and inode journals"); return -EINVAL; } @@ -2242,7 +2285,7 @@ static int ext3_load_journal(struct super_block *sb, if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) { err = journal_update_format(journal); if (err) { - printk(KERN_ERR "EXT3-fs: error updating journal.\n"); + ext3_msg(sb, KERN_ERR, "error updating journal"); journal_destroy(journal); return err; } @@ -2254,7 +2297,7 @@ static int ext3_load_journal(struct super_block *sb, err = journal_load(journal); if (err) { - printk(KERN_ERR "EXT3-fs: error loading journal.\n"); + ext3_msg(sb, KERN_ERR, "error loading journal"); journal_destroy(journal); return err; } @@ -2273,16 +2316,17 @@ static int ext3_load_journal(struct super_block *sb, return 0; } -static int ext3_create_journal(struct super_block * sb, - struct ext3_super_block * es, +static int ext3_create_journal(struct super_block *sb, + struct ext3_super_block *es, unsigned int journal_inum) { journal_t *journal; int err; if (sb->s_flags & MS_RDONLY) { - printk(KERN_ERR "EXT3-fs: readonly filesystem when trying to " - "create journal.\n"); + ext3_msg(sb, KERN_ERR, + "error: readonly filesystem when trying to " + "create journal"); return -EROFS; } @@ -2290,12 +2334,12 @@ static int ext3_create_journal(struct super_block * sb, if (!journal) return -EINVAL; - printk(KERN_INFO "EXT3-fs: creating new journal on inode %u\n", + ext3_msg(sb, KERN_INFO, "creating new journal on inode %u", journal_inum); err = journal_create(journal); if (err) { - printk(KERN_ERR "EXT3-fs: error creating journal.\n"); + ext3_msg(sb, KERN_ERR, "error creating journal"); journal_destroy(journal); return -EIO; } @@ -2376,8 +2420,8 @@ out: * has recorded an error from a previous lifetime, move that error to the * main filesystem now. */ -static void ext3_clear_journal_err(struct super_block * sb, - struct ext3_super_block * es) +static void ext3_clear_journal_err(struct super_block *sb, + struct ext3_super_block *es) { journal_t *journal; int j_errno; @@ -2568,10 +2612,10 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) __le32 ret; if ((ret = EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP))) { - printk(KERN_WARNING "EXT3-fs: %s: couldn't " - "remount RDWR because of unsupported " - "optional features (%x).\n", - sb->s_id, le32_to_cpu(ret)); + ext3_msg(sb, KERN_WARNING, + "warning: couldn't remount RDWR " + "because of unsupported optional " + "features (%x)", le32_to_cpu(ret)); err = -EROFS; goto restore_opts; } @@ -2582,11 +2626,10 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) * require a full umount/remount for now. */ if (es->s_last_orphan) { - printk(KERN_WARNING "EXT3-fs: %s: couldn't " + ext3_msg(sb, KERN_WARNING, "warning: couldn't " "remount RDWR because of unprocessed " "orphan inode list. Please " - "umount/remount instead.\n", - sb->s_id); + "umount/remount instead."); err = -EINVAL; goto restore_opts; } @@ -2686,13 +2729,11 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf) buf->f_bsize = sb->s_blocksize; buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last; buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter); - es->s_free_blocks_count = cpu_to_le32(buf->f_bfree); buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count); if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count)) buf->f_bavail = 0; buf->f_files = le32_to_cpu(es->s_inodes_count); buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter); - es->s_free_inodes_count = cpu_to_le32(buf->f_ffree); buf->f_namelen = EXT3_NAME_LEN; fsid = le64_to_cpup((void *)es->s_uuid) ^ le64_to_cpup((void *)es->s_uuid + sizeof(u64)); @@ -2837,9 +2878,9 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id, if (EXT3_SB(sb)->s_qf_names[type]) { /* Quotafile not of fs root? */ if (path.dentry->d_parent != sb->s_root) - printk(KERN_WARNING - "EXT3-fs: Quota file not on filesystem root. " - "Journaled quota will not work.\n"); + ext3_msg(sb, KERN_WARNING, + "warning: Quota file not on filesystem root. " + "Journaled quota will not work."); } /* @@ -2921,8 +2962,9 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type, handle_t *handle = journal_current_handle(); if (!handle) { - printk(KERN_WARNING "EXT3-fs: Quota write (off=%Lu, len=%Lu)" - " cancelled because transaction is not started.\n", + ext3_msg(sb, KERN_WARNING, + "warning: quota write (off=%llu, len=%llu)" + " cancelled because transaction is not started.", (unsigned long long)off, (unsigned long long)len); return -EIO; } diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 545e37c4b91eb6387ddc015e17e000ad1ccbaaa3..387d92d00b977cd271bdab9416323909908242e3 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -960,6 +960,10 @@ ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, if (error) goto cleanup; + error = ext3_journal_get_write_access(handle, is.iloc.bh); + if (error) + goto cleanup; + if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) { struct ext3_inode *raw_inode = ext3_raw_inode(&is.iloc); memset(raw_inode, 0, EXT3_SB(inode->i_sb)->s_inode_size); @@ -985,9 +989,6 @@ ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, if (flags & XATTR_CREATE) goto cleanup; } - error = ext3_journal_get_write_access(handle, is.iloc.bh); - if (error) - goto cleanup; if (!value) { if (!is.s.not_found) error = ext3_xattr_ibody_set(handle, inode, &i, &is); diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig index 9f2d45d75b1a70084e5f153c94d49a2b5f863321..9acf7e808139d3df688da7d66ffb33b5cf081d8e 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig @@ -26,6 +26,16 @@ config EXT4_FS If unsure, say N. +config EXT4_USE_FOR_EXT23 + bool "Use ext4 for ext2/ext3 file systems" + depends on EXT3_FS=n || EXT2_FS=n + default y + help + Allow the ext4 file system driver code to be used for ext2 or + ext3 file system mounts. This allows users to reduce their + compiled kernel size by using one file system driver for + ext2, ext3, and ext4 file systems. + config EXT4_FS_XATTR bool "Ext4 extended attributes" depends on EXT4_FS diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 1d0418980f8db58e4ce34a3c47e00ee8bcb53d01..22bc7435d9134b397f537440faa15ce890b7c44f 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -498,44 +498,6 @@ error_return: return; } -/** - * ext4_free_blocks() -- Free given blocks and update quota - * @handle: handle for this transaction - * @inode: inode - * @block: start physical block to free - * @count: number of blocks to count - * @metadata: Are these metadata blocks - */ -void ext4_free_blocks(handle_t *handle, struct inode *inode, - ext4_fsblk_t block, unsigned long count, - int metadata) -{ - struct super_block *sb; - unsigned long dquot_freed_blocks; - - /* this isn't the right place to decide whether block is metadata - * inode.c/extents.c knows better, but for safety ... */ - if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) - metadata = 1; - - /* We need to make sure we don't reuse - * block released untill the transaction commit. - * writeback mode have weak data consistency so - * don't force data as metadata when freeing block - * for writeback mode. - */ - if (metadata == 0 && !ext4_should_writeback_data(inode)) - metadata = 1; - - sb = inode->i_sb; - - ext4_mb_free_blocks(handle, inode, block, count, - metadata, &dquot_freed_blocks); - if (dquot_freed_blocks) - vfs_dq_free_block(inode, dquot_freed_blocks); - return; -} - /** * ext4_has_free_blocks() * @sbi: in-core super block structure. @@ -761,7 +723,13 @@ static unsigned long ext4_bg_num_gdb_meta(struct super_block *sb, static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb, ext4_group_t group) { - return ext4_bg_has_super(sb, group) ? EXT4_SB(sb)->s_gdb_count : 0; + if (!ext4_bg_has_super(sb, group)) + return 0; + + if (EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG)) + return le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg); + else + return EXT4_SB(sb)->s_gdb_count; } /** diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c index 50784ef0756311b2958686fdbf3c60e1c7fe04fa..4df8621ec31cff1f5c8eef0211942750b92fd009 100644 --- a/fs/ext4/block_validity.c +++ b/fs/ext4/block_validity.c @@ -160,7 +160,7 @@ int ext4_setup_system_zone(struct super_block *sb) if (ext4_bg_has_super(sb, i) && ((i < 5) || ((i % flex_size) == 0))) add_system_zone(sbi, ext4_group_first_block_no(sb, i), - sbi->s_gdb_count + 1); + ext4_bg_num_gdb(sb, i) + 1); gdp = ext4_get_group_desc(sb, i, NULL); ret = add_system_zone(sbi, ext4_block_bitmap(sb, gdp), 1); if (ret) @@ -228,6 +228,7 @@ int ext4_data_block_valid(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk, struct rb_node *n = sbi->system_blks.rb_node; if ((start_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) || + (start_blk + count < start_blk) || (start_blk + count > ext4_blocks_count(sbi->s_es))) return 0; while (n) { diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 8825515eeddd8042881365c6e84a54fba9c6c2f3..ab31e65d46d017880644a540e23f05bca5398a92 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -375,6 +375,12 @@ struct ext4_new_group_data { #define EXT4_GET_BLOCKS_DIO_CONVERT_EXT (EXT4_GET_BLOCKS_CONVERT|\ EXT4_GET_BLOCKS_DIO_CREATE_EXT) +/* + * Flags used by ext4_free_blocks + */ +#define EXT4_FREE_BLOCKS_METADATA 0x0001 +#define EXT4_FREE_BLOCKS_FORGET 0x0002 + /* * ioctl commands */ @@ -703,6 +709,13 @@ struct ext4_inode_info { struct list_head i_aio_dio_complete_list; /* current io_end structure for async DIO write*/ ext4_io_end_t *cur_aio_dio; + + /* + * Transactions that contain inode's metadata needed to complete + * fsync and fdatasync, respectively. + */ + tid_t i_sync_tid; + tid_t i_datasync_tid; }; /* @@ -750,6 +763,7 @@ struct ext4_inode_info { #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */ #define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */ #define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000 /* Block validity checking */ +#define EXT4_MOUNT_DISCARD 0x40000000 /* Issue DISCARD requests */ #define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt #define set_opt(o, opt) o |= EXT4_MOUNT_##opt @@ -1324,8 +1338,6 @@ extern ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode, ext4_fsblk_t goal, unsigned long *count, int *errp); extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks); extern int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks); -extern void ext4_free_blocks(handle_t *handle, struct inode *inode, - ext4_fsblk_t block, unsigned long count, int metadata); extern void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, ext4_fsblk_t block, unsigned long count); extern ext4_fsblk_t ext4_count_free_blocks(struct super_block *); @@ -1384,16 +1396,15 @@ extern int ext4_mb_reserve_blocks(struct super_block *, int); extern void ext4_discard_preallocations(struct inode *); extern int __init init_ext4_mballoc(void); extern void exit_ext4_mballoc(void); -extern void ext4_mb_free_blocks(handle_t *, struct inode *, - ext4_fsblk_t, unsigned long, int, unsigned long *); +extern void ext4_free_blocks(handle_t *handle, struct inode *inode, + struct buffer_head *bh, ext4_fsblk_t block, + unsigned long count, int flags); extern int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t i, struct ext4_group_desc *desc); extern int ext4_mb_get_buddy_cache_lock(struct super_block *, ext4_group_t); extern void ext4_mb_put_buddy_cache_lock(struct super_block *, ext4_group_t, int); /* inode.c */ -int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode, - struct buffer_head *bh, ext4_fsblk_t blocknr); struct buffer_head *ext4_getblk(handle_t *, struct inode *, ext4_lblk_t, int, int *); struct buffer_head *ext4_bread(handle_t *, struct inode *, diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index 6a9409920deef2f6040b8d7279114cfc0612221d..b57e5c711b6de1048b98afb238fbdca874134497 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c @@ -4,6 +4,8 @@ #include "ext4_jbd2.h" +#include + int __ext4_journal_get_undo_access(const char *where, handle_t *handle, struct buffer_head *bh) { @@ -32,35 +34,69 @@ int __ext4_journal_get_write_access(const char *where, handle_t *handle, return err; } -int __ext4_journal_forget(const char *where, handle_t *handle, - struct buffer_head *bh) +/* + * The ext4 forget function must perform a revoke if we are freeing data + * which has been journaled. Metadata (eg. indirect blocks) must be + * revoked in all cases. + * + * "bh" may be NULL: a metadata block may have been freed from memory + * but there may still be a record of it in the journal, and that record + * still needs to be revoked. + * + * If the handle isn't valid we're not journaling, but we still need to + * call into ext4_journal_revoke() to put the buffer head. + */ +int __ext4_forget(const char *where, handle_t *handle, int is_metadata, + struct inode *inode, struct buffer_head *bh, + ext4_fsblk_t blocknr) { - int err = 0; + int err; - if (ext4_handle_valid(handle)) { - err = jbd2_journal_forget(handle, bh); - if (err) - ext4_journal_abort_handle(where, __func__, bh, - handle, err); - } - else + might_sleep(); + + trace_ext4_forget(inode, is_metadata, blocknr); + BUFFER_TRACE(bh, "enter"); + + jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, " + "data mode %x\n", + bh, is_metadata, inode->i_mode, + test_opt(inode->i_sb, DATA_FLAGS)); + + /* In the no journal case, we can just do a bforget and return */ + if (!ext4_handle_valid(handle)) { bforget(bh); - return err; -} + return 0; + } -int __ext4_journal_revoke(const char *where, handle_t *handle, - ext4_fsblk_t blocknr, struct buffer_head *bh) -{ - int err = 0; + /* Never use the revoke function if we are doing full data + * journaling: there is no need to, and a V1 superblock won't + * support it. Otherwise, only skip the revoke on un-journaled + * data blocks. */ - if (ext4_handle_valid(handle)) { - err = jbd2_journal_revoke(handle, blocknr, bh); - if (err) - ext4_journal_abort_handle(where, __func__, bh, - handle, err); + if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA || + (!is_metadata && !ext4_should_journal_data(inode))) { + if (bh) { + BUFFER_TRACE(bh, "call jbd2_journal_forget"); + err = jbd2_journal_forget(handle, bh); + if (err) + ext4_journal_abort_handle(where, __func__, bh, + handle, err); + return err; + } + return 0; } - else - bforget(bh); + + /* + * data!=journal && (is_metadata || should_journal_data(inode)) + */ + BUFFER_TRACE(bh, "call jbd2_journal_revoke"); + err = jbd2_journal_revoke(handle, blocknr, bh); + if (err) { + ext4_journal_abort_handle(where, __func__, bh, handle, err); + ext4_abort(inode->i_sb, __func__, + "error %d when attempting revoke", err); + } + BUFFER_TRACE(bh, "exit"); return err; } diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index a2865980342f90c21aed6d731fcf1d66d72e0312..05eca817d7046258f54d3a8715dafb946ff5e155 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h @@ -49,7 +49,7 @@ #define EXT4_DATA_TRANS_BLOCKS(sb) (EXT4_SINGLEDATA_TRANS_BLOCKS(sb) + \ EXT4_XATTR_TRANS_BLOCKS - 2 + \ - 2*EXT4_QUOTA_TRANS_BLOCKS(sb)) + EXT4_MAXQUOTAS_TRANS_BLOCKS(sb)) /* * Define the number of metadata blocks we need to account to modify data. @@ -57,7 +57,7 @@ * This include super block, inode block, quota blocks and xattr blocks */ #define EXT4_META_TRANS_BLOCKS(sb) (EXT4_XATTR_TRANS_BLOCKS + \ - 2*EXT4_QUOTA_TRANS_BLOCKS(sb)) + EXT4_MAXQUOTAS_TRANS_BLOCKS(sb)) /* Delete operations potentially hit one directory's namespace plus an * entire inode, plus arbitrary amounts of bitmap/indirection data. Be @@ -92,6 +92,7 @@ * but inode, sb and group updates are done only once */ #define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\ (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_INIT_REWRITE) : 0) + #define EXT4_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\ (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_DEL_REWRITE) : 0) #else @@ -99,6 +100,9 @@ #define EXT4_QUOTA_INIT_BLOCKS(sb) 0 #define EXT4_QUOTA_DEL_BLOCKS(sb) 0 #endif +#define EXT4_MAXQUOTAS_TRANS_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_TRANS_BLOCKS(sb)) +#define EXT4_MAXQUOTAS_INIT_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_INIT_BLOCKS(sb)) +#define EXT4_MAXQUOTAS_DEL_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_DEL_BLOCKS(sb)) int ext4_mark_iloc_dirty(handle_t *handle, @@ -116,12 +120,8 @@ int ext4_reserve_inode_write(handle_t *handle, struct inode *inode, int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode); /* - * Wrapper functions with which ext4 calls into JBD. The intent here is - * to allow these to be turned into appropriate stubs so ext4 can control - * ext2 filesystems, so ext2+ext4 systems only nee one fs. This work hasn't - * been done yet. + * Wrapper functions with which ext4 calls into JBD. */ - void ext4_journal_abort_handle(const char *caller, const char *err_fn, struct buffer_head *bh, handle_t *handle, int err); @@ -131,13 +131,9 @@ int __ext4_journal_get_undo_access(const char *where, handle_t *handle, int __ext4_journal_get_write_access(const char *where, handle_t *handle, struct buffer_head *bh); -/* When called with an invalid handle, this will still do a put on the BH */ -int __ext4_journal_forget(const char *where, handle_t *handle, - struct buffer_head *bh); - -/* When called with an invalid handle, this will still do a put on the BH */ -int __ext4_journal_revoke(const char *where, handle_t *handle, - ext4_fsblk_t blocknr, struct buffer_head *bh); +int __ext4_forget(const char *where, handle_t *handle, int is_metadata, + struct inode *inode, struct buffer_head *bh, + ext4_fsblk_t blocknr); int __ext4_journal_get_create_access(const char *where, handle_t *handle, struct buffer_head *bh); @@ -149,12 +145,11 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle, __ext4_journal_get_undo_access(__func__, (handle), (bh)) #define ext4_journal_get_write_access(handle, bh) \ __ext4_journal_get_write_access(__func__, (handle), (bh)) -#define ext4_journal_revoke(handle, blocknr, bh) \ - __ext4_journal_revoke(__func__, (handle), (blocknr), (bh)) +#define ext4_forget(handle, is_metadata, inode, bh, block_nr) \ + __ext4_forget(__func__, (handle), (is_metadata), (inode), (bh),\ + (block_nr)) #define ext4_journal_get_create_access(handle, bh) \ __ext4_journal_get_create_access(__func__, (handle), (bh)) -#define ext4_journal_forget(handle, bh) \ - __ext4_journal_forget(__func__, (handle), (bh)) #define ext4_handle_dirty_metadata(handle, inode, bh) \ __ext4_handle_dirty_metadata(__func__, (handle), (inode), (bh)) @@ -254,6 +249,19 @@ static inline int ext4_jbd2_file_inode(handle_t *handle, struct inode *inode) return 0; } +static inline void ext4_update_inode_fsync_trans(handle_t *handle, + struct inode *inode, + int datasync) +{ + struct ext4_inode_info *ei = EXT4_I(inode); + + if (ext4_handle_valid(handle)) { + ei->i_sync_tid = handle->h_transaction->t_tid; + if (datasync) + ei->i_datasync_tid = handle->h_transaction->t_tid; + } +} + /* super.c */ int ext4_force_commit(struct super_block *sb); diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 715264b4bae4b421c110af69ed3ccf8dc32bb1f6..3a7928f825e45f8fb244587cbe7c8921f6a3269b 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1007,7 +1007,8 @@ cleanup: for (i = 0; i < depth; i++) { if (!ablocks[i]) continue; - ext4_free_blocks(handle, inode, ablocks[i], 1, 1); + ext4_free_blocks(handle, inode, 0, ablocks[i], 1, + EXT4_FREE_BLOCKS_METADATA); } } kfree(ablocks); @@ -1761,7 +1762,9 @@ int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block, while (block < last && block != EXT_MAX_BLOCK) { num = last - block; /* find extent for this block */ + down_read(&EXT4_I(inode)->i_data_sem); path = ext4_ext_find_extent(inode, block, path); + up_read(&EXT4_I(inode)->i_data_sem); if (IS_ERR(path)) { err = PTR_ERR(path); path = NULL; @@ -1957,7 +1960,6 @@ errout: static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, struct ext4_ext_path *path) { - struct buffer_head *bh; int err; ext4_fsblk_t leaf; @@ -1973,9 +1975,8 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, if (err) return err; ext_debug("index is empty, remove it, free block %llu\n", leaf); - bh = sb_find_get_block(inode->i_sb, leaf); - ext4_forget(handle, 1, inode, bh, leaf); - ext4_free_blocks(handle, inode, leaf, 1, 1); + ext4_free_blocks(handle, inode, 0, leaf, 1, + EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); return err; } @@ -2042,12 +2043,11 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, struct ext4_extent *ex, ext4_lblk_t from, ext4_lblk_t to) { - struct buffer_head *bh; unsigned short ee_len = ext4_ext_get_actual_len(ex); - int i, metadata = 0; + int flags = EXT4_FREE_BLOCKS_FORGET; if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) - metadata = 1; + flags |= EXT4_FREE_BLOCKS_METADATA; #ifdef EXTENTS_STATS { struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); @@ -2072,11 +2072,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, num = le32_to_cpu(ex->ee_block) + ee_len - from; start = ext_pblock(ex) + ee_len - num; ext_debug("free last %u blocks starting %llu\n", num, start); - for (i = 0; i < num; i++) { - bh = sb_find_get_block(inode->i_sb, start + i); - ext4_forget(handle, 0, inode, bh, start + i); - } - ext4_free_blocks(handle, inode, start, num, metadata); + ext4_free_blocks(handle, inode, 0, start, num, flags); } else if (from == le32_to_cpu(ex->ee_block) && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) { printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n", @@ -2167,7 +2163,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, correct_index = 1; credits += (ext_depth(inode)) + 1; } - credits += 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb); + credits += EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb); err = ext4_ext_truncate_extend_restart(handle, inode, credits); if (err) @@ -3064,6 +3060,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, if (flags == EXT4_GET_BLOCKS_DIO_CONVERT_EXT) { ret = ext4_convert_unwritten_extents_dio(handle, inode, path); + if (ret >= 0) + ext4_update_inode_fsync_trans(handle, inode, 1); goto out2; } /* buffered IO case */ @@ -3091,6 +3089,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, ret = ext4_ext_convert_to_initialized(handle, inode, path, iblock, max_blocks); + if (ret >= 0) + ext4_update_inode_fsync_trans(handle, inode, 1); out: if (ret <= 0) { err = ret; @@ -3319,8 +3319,8 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, /* not a good idea to call discard here directly, * but otherwise we'd need to call it every free() */ ext4_discard_preallocations(inode); - ext4_free_blocks(handle, inode, ext_pblock(&newex), - ext4_ext_get_actual_len(&newex), 0); + ext4_free_blocks(handle, inode, 0, ext_pblock(&newex), + ext4_ext_get_actual_len(&newex), 0); goto out2; } @@ -3329,10 +3329,16 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, allocated = ext4_ext_get_actual_len(&newex); set_buffer_new(bh_result); - /* Cache only when it is _not_ an uninitialized extent */ - if ((flags & EXT4_GET_BLOCKS_UNINIT_EXT) == 0) + /* + * Cache the extent and update transaction to commit on fdatasync only + * when it is _not_ an uninitialized extent. + */ + if ((flags & EXT4_GET_BLOCKS_UNINIT_EXT) == 0) { ext4_ext_put_in_cache(inode, iblock, allocated, newblock, EXT4_EXT_CACHE_EXTENT); + ext4_update_inode_fsync_trans(handle, inode, 1); + } else + ext4_update_inode_fsync_trans(handle, inode, 0); out: if (allocated > max_blocks) allocated = max_blocks; @@ -3720,10 +3726,8 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, * Walk the extent tree gathering extent information. * ext4_ext_fiemap_cb will push extents back to user. */ - down_read(&EXT4_I(inode)->i_data_sem); error = ext4_ext_walk_space(inode, start_blk, len_blks, ext4_ext_fiemap_cb, fieinfo); - up_read(&EXT4_I(inode)->i_data_sem); } return error; diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index 2b1531266ee25010776dcebe8921103da29d9c3a..0b22497d92e1b079e2eb10c22eb7a6ce6f546153 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c @@ -51,25 +51,30 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; + struct ext4_inode_info *ei = EXT4_I(inode); journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; - int err, ret = 0; + int ret; + tid_t commit_tid; J_ASSERT(ext4_journal_current_handle() == NULL); trace_ext4_sync_file(file, dentry, datasync); + if (inode->i_sb->s_flags & MS_RDONLY) + return 0; + ret = flush_aio_dio_completed_IO(inode); if (ret < 0) - goto out; + return ret; + + if (!journal) + return simple_fsync(file, dentry, datasync); + /* - * data=writeback: + * data=writeback,ordered: * The caller's filemap_fdatawrite()/wait will sync the data. - * sync_inode() will sync the metadata - * - * data=ordered: - * The caller's filemap_fdatawrite() will write the data and - * sync_inode() will write the inode if it is dirty. Then the caller's - * filemap_fdatawait() will wait on the pages. + * Metadata is in the journal, we wait for proper transaction to + * commit here. * * data=journal: * filemap_fdatawrite won't do anything (the buffers are clean). @@ -79,32 +84,13 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync) * (they were dirtied by commit). But that's OK - the blocks are * safe in-journal, which is all fsync() needs to ensure. */ - if (ext4_should_journal_data(inode)) { - ret = ext4_force_commit(inode->i_sb); - goto out; - } + if (ext4_should_journal_data(inode)) + return ext4_force_commit(inode->i_sb); - if (!journal) - ret = sync_mapping_buffers(inode->i_mapping); - - if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) - goto out; - - /* - * The VFS has written the file data. If the inode is unaltered - * then we need not start a commit. - */ - if (inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC)) { - struct writeback_control wbc = { - .sync_mode = WB_SYNC_ALL, - .nr_to_write = 0, /* sys_fsync did this */ - }; - err = sync_inode(inode, &wbc); - if (ret == 0) - ret = err; - } -out: - if (journal && (journal->j_flags & JBD2_BARRIER)) + commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid; + if (jbd2_log_start_commit(journal, commit_tid)) + jbd2_log_wait_commit(journal, commit_tid); + else if (journal->j_flags & JBD2_BARRIER) blkdev_issue_flush(inode->i_sb->s_bdev, NULL); return ret; } diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 4e8e2f15b8bd6f96e834826192fec6e0ec09758d..5352db1a3086a075f777652b1ac496a1f2c84aaa 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -70,58 +70,6 @@ static int ext4_inode_is_fast_symlink(struct inode *inode) return (S_ISLNK(inode->i_mode) && inode->i_blocks - ea_blocks == 0); } -/* - * The ext4 forget function must perform a revoke if we are freeing data - * which has been journaled. Metadata (eg. indirect blocks) must be - * revoked in all cases. - * - * "bh" may be NULL: a metadata block may have been freed from memory - * but there may still be a record of it in the journal, and that record - * still needs to be revoked. - * - * If the handle isn't valid we're not journaling, but we still need to - * call into ext4_journal_revoke() to put the buffer head. - */ -int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode, - struct buffer_head *bh, ext4_fsblk_t blocknr) -{ - int err; - - might_sleep(); - - BUFFER_TRACE(bh, "enter"); - - jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, " - "data mode %x\n", - bh, is_metadata, inode->i_mode, - test_opt(inode->i_sb, DATA_FLAGS)); - - /* Never use the revoke function if we are doing full data - * journaling: there is no need to, and a V1 superblock won't - * support it. Otherwise, only skip the revoke on un-journaled - * data blocks. */ - - if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA || - (!is_metadata && !ext4_should_journal_data(inode))) { - if (bh) { - BUFFER_TRACE(bh, "call jbd2_journal_forget"); - return ext4_journal_forget(handle, bh); - } - return 0; - } - - /* - * data!=journal && (is_metadata || should_journal_data(inode)) - */ - BUFFER_TRACE(bh, "call ext4_journal_revoke"); - err = ext4_journal_revoke(handle, blocknr, bh); - if (err) - ext4_abort(inode->i_sb, __func__, - "error %d when attempting revoke", err); - BUFFER_TRACE(bh, "exit"); - return err; -} - /* * Work out how many blocks we need to proceed with the next chunk of a * truncate transaction. @@ -721,7 +669,7 @@ allocated: return ret; failed_out: for (i = 0; i < index; i++) - ext4_free_blocks(handle, inode, new_blocks[i], 1, 0); + ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0); return ret; } @@ -817,14 +765,20 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode, return err; failed: /* Allocation failed, free what we already allocated */ + ext4_free_blocks(handle, inode, 0, new_blocks[0], 1, 0); for (i = 1; i <= n ; i++) { - BUFFER_TRACE(branch[i].bh, "call jbd2_journal_forget"); - ext4_journal_forget(handle, branch[i].bh); + /* + * branch[i].bh is newly allocated, so there is no + * need to revoke the block, which is why we don't + * need to set EXT4_FREE_BLOCKS_METADATA. + */ + ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, + EXT4_FREE_BLOCKS_FORGET); } - for (i = 0; i < indirect_blks; i++) - ext4_free_blocks(handle, inode, new_blocks[i], 1, 0); + for (i = n+1; i < indirect_blks; i++) + ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0); - ext4_free_blocks(handle, inode, new_blocks[i], num, 0); + ext4_free_blocks(handle, inode, 0, new_blocks[i], num, 0); return err; } @@ -903,12 +857,16 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode, err_out: for (i = 1; i <= num; i++) { - BUFFER_TRACE(where[i].bh, "call jbd2_journal_forget"); - ext4_journal_forget(handle, where[i].bh); - ext4_free_blocks(handle, inode, - le32_to_cpu(where[i-1].key), 1, 0); + /* + * branch[i].bh is newly allocated, so there is no + * need to revoke the block, which is why we don't + * need to set EXT4_FREE_BLOCKS_METADATA. + */ + ext4_free_blocks(handle, inode, where[i].bh, 0, 1, + EXT4_FREE_BLOCKS_FORGET); } - ext4_free_blocks(handle, inode, le32_to_cpu(where[num].key), blks, 0); + ext4_free_blocks(handle, inode, 0, le32_to_cpu(where[num].key), + blks, 0); return err; } @@ -1021,10 +979,12 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, if (!err) err = ext4_splice_branch(handle, inode, iblock, partial, indirect_blks, count); - else + if (err) goto cleanup; set_buffer_new(bh_result); + + ext4_update_inode_fsync_trans(handle, inode, 1); got_it: map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key)); if (count > blocks_to_boundary) @@ -1052,7 +1012,7 @@ qsize_t ext4_get_reserved_space(struct inode *inode) EXT4_I(inode)->i_reserved_meta_blocks; spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); - return total; + return (total << inode->i_blkbits); } /* * Calculate the number of metadata blocks need to reserve @@ -1534,6 +1494,16 @@ static int do_journal_get_write_access(handle_t *handle, return ext4_journal_get_write_access(handle, bh); } +/* + * Truncate blocks that were not used by write. We have to truncate the + * pagecache as well so that corresponding buffers get properly unmapped. + */ +static void ext4_truncate_failed_write(struct inode *inode) +{ + truncate_inode_pages(inode->i_mapping, inode->i_size); + ext4_truncate(inode); +} + static int ext4_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) @@ -1599,7 +1569,7 @@ retry: ext4_journal_stop(handle); if (pos + len > inode->i_size) { - ext4_truncate(inode); + ext4_truncate_failed_write(inode); /* * If truncate failed early the inode might * still be on the orphan list; we need to @@ -1709,7 +1679,7 @@ static int ext4_ordered_write_end(struct file *file, ret = ret2; if (pos + len > inode->i_size) { - ext4_truncate(inode); + ext4_truncate_failed_write(inode); /* * If truncate failed early the inode might still be * on the orphan list; we need to make sure the inode @@ -1751,7 +1721,7 @@ static int ext4_writeback_write_end(struct file *file, ret = ret2; if (pos + len > inode->i_size) { - ext4_truncate(inode); + ext4_truncate_failed_write(inode); /* * If truncate failed early the inode might still be * on the orphan list; we need to make sure the inode @@ -1814,7 +1784,7 @@ static int ext4_journalled_write_end(struct file *file, if (!ret) ret = ret2; if (pos + len > inode->i_size) { - ext4_truncate(inode); + ext4_truncate_failed_write(inode); /* * If truncate failed early the inode might still be * on the orphan list; we need to make sure the inode @@ -2600,7 +2570,6 @@ static int bput_one(handle_t *handle, struct buffer_head *bh) } static int __ext4_journalled_writepage(struct page *page, - struct writeback_control *wbc, unsigned int len) { struct address_space *mapping = page->mapping; @@ -2758,7 +2727,7 @@ static int ext4_writepage(struct page *page, * doesn't seem much point in redirtying the page here. */ ClearPageChecked(page); - return __ext4_journalled_writepage(page, wbc, len); + return __ext4_journalled_writepage(page, len); } if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode)) @@ -2788,7 +2757,7 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode) * number of contiguous block. So we will limit * number of contiguous block to a sane value */ - if (!(inode->i_flags & EXT4_EXTENTS_FL) && + if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) && (max_blocks > EXT4_MAX_TRANS_DATA)) max_blocks = EXT4_MAX_TRANS_DATA; @@ -3091,7 +3060,7 @@ retry: * i_size_read because we hold i_mutex. */ if (pos + len > inode->i_size) - ext4_truncate(inode); + ext4_truncate_failed_write(inode); } if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) @@ -4120,6 +4089,11 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode, __le32 *last) { __le32 *p; + int flags = EXT4_FREE_BLOCKS_FORGET; + + if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) + flags |= EXT4_FREE_BLOCKS_METADATA; + if (try_to_extend_transaction(handle, inode)) { if (bh) { BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); @@ -4134,27 +4108,10 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode, } } - /* - * Any buffers which are on the journal will be in memory. We - * find them on the hash table so jbd2_journal_revoke() will - * run jbd2_journal_forget() on them. We've already detached - * each block from the file, so bforget() in - * jbd2_journal_forget() should be safe. - * - * AKPM: turn on bforget in jbd2_journal_forget()!!! - */ - for (p = first; p < last; p++) { - u32 nr = le32_to_cpu(*p); - if (nr) { - struct buffer_head *tbh; - - *p = 0; - tbh = sb_find_get_block(inode->i_sb, nr); - ext4_forget(handle, 0, inode, tbh, nr); - } - } + for (p = first; p < last; p++) + *p = 0; - ext4_free_blocks(handle, inode, block_to_free, count, 0); + ext4_free_blocks(handle, inode, 0, block_to_free, count, flags); } /** @@ -4342,7 +4299,8 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, blocks_for_truncate(inode)); } - ext4_free_blocks(handle, inode, nr, 1, 1); + ext4_free_blocks(handle, inode, 0, nr, 1, + EXT4_FREE_BLOCKS_METADATA); if (parent_bh) { /* @@ -4781,8 +4739,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) struct ext4_iloc iloc; struct ext4_inode *raw_inode; struct ext4_inode_info *ei; - struct buffer_head *bh; struct inode *inode; + journal_t *journal = EXT4_SB(sb)->s_journal; long ret; int block; @@ -4793,11 +4751,11 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) return inode; ei = EXT4_I(inode); + iloc.bh = 0; ret = __ext4_get_inode_loc(inode, &iloc, 0); if (ret < 0) goto bad_inode; - bh = iloc.bh; raw_inode = ext4_raw_inode(&iloc); inode->i_mode = le16_to_cpu(raw_inode->i_mode); inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); @@ -4820,7 +4778,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) if (inode->i_mode == 0 || !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) { /* this inode is deleted */ - brelse(bh); ret = -ESTALE; goto bad_inode; } @@ -4848,11 +4805,35 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ei->i_data[block] = raw_inode->i_block[block]; INIT_LIST_HEAD(&ei->i_orphan); + /* + * Set transaction id's of transactions that have to be committed + * to finish f[data]sync. We set them to currently running transaction + * as we cannot be sure that the inode or some of its metadata isn't + * part of the transaction - the inode could have been reclaimed and + * now it is reread from disk. + */ + if (journal) { + transaction_t *transaction; + tid_t tid; + + spin_lock(&journal->j_state_lock); + if (journal->j_running_transaction) + transaction = journal->j_running_transaction; + else + transaction = journal->j_committing_transaction; + if (transaction) + tid = transaction->t_tid; + else + tid = journal->j_commit_sequence; + spin_unlock(&journal->j_state_lock); + ei->i_sync_tid = tid; + ei->i_datasync_tid = tid; + } + if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) { ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize); if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > EXT4_INODE_SIZE(inode->i_sb)) { - brelse(bh); ret = -EIO; goto bad_inode; } @@ -4884,10 +4865,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ret = 0; if (ei->i_file_acl && - ((ei->i_file_acl < - (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) + - EXT4_SB(sb)->s_gdb_count)) || - (ei->i_file_acl >= ext4_blocks_count(EXT4_SB(sb)->s_es)))) { + !ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) { ext4_error(sb, __func__, "bad extended attribute block %llu in inode #%lu", ei->i_file_acl, inode->i_ino); @@ -4905,10 +4883,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) /* Validate block references which are part of inode */ ret = ext4_check_inode_blockref(inode); } - if (ret) { - brelse(bh); + if (ret) goto bad_inode; - } if (S_ISREG(inode->i_mode)) { inode->i_op = &ext4_file_inode_operations; @@ -4936,7 +4912,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) init_special_inode(inode, inode->i_mode, new_decode_dev(le32_to_cpu(raw_inode->i_block[1]))); } else { - brelse(bh); ret = -EIO; ext4_error(inode->i_sb, __func__, "bogus i_mode (%o) for inode=%lu", @@ -4949,6 +4924,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) return inode; bad_inode: + brelse(iloc.bh); iget_failed(inode); return ERR_PTR(ret); } @@ -5108,6 +5084,7 @@ static int ext4_do_update_inode(handle_t *handle, err = rc; ei->i_state &= ~EXT4_STATE_NEW; + ext4_update_inode_fsync_trans(handle, inode, 0); out_brelse: brelse(bh); ext4_std_error(inode->i_sb, err); @@ -5227,8 +5204,8 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) /* (user+group)*(old+new) structure, inode write (sb, * inode block, ? - but truncate inode update has it) */ - handle = ext4_journal_start(inode, 2*(EXT4_QUOTA_INIT_BLOCKS(inode->i_sb)+ - EXT4_QUOTA_DEL_BLOCKS(inode->i_sb))+3); + handle = ext4_journal_start(inode, (EXT4_MAXQUOTAS_INIT_BLOCKS(inode->i_sb)+ + EXT4_MAXQUOTAS_DEL_BLOCKS(inode->i_sb))+3); if (IS_ERR(handle)) { error = PTR_ERR(handle); goto err_out; diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index c1cdf613e7258e39f2964768c2d65b6422ce8c96..b63d193126dbf759236a52f075af914bc921d40a 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -221,31 +221,38 @@ setversion_out: struct file *donor_filp; int err; + if (!(filp->f_mode & FMODE_READ) || + !(filp->f_mode & FMODE_WRITE)) + return -EBADF; + if (copy_from_user(&me, (struct move_extent __user *)arg, sizeof(me))) return -EFAULT; + me.moved_len = 0; donor_filp = fget(me.donor_fd); if (!donor_filp) return -EBADF; - if (!capable(CAP_DAC_OVERRIDE)) { - if ((current->real_cred->fsuid != inode->i_uid) || - !(inode->i_mode & S_IRUSR) || - !(donor_filp->f_dentry->d_inode->i_mode & - S_IRUSR)) { - fput(donor_filp); - return -EACCES; - } + if (!(donor_filp->f_mode & FMODE_WRITE)) { + err = -EBADF; + goto mext_out; } + err = mnt_want_write(filp->f_path.mnt); + if (err) + goto mext_out; + err = ext4_move_extents(filp, donor_filp, me.orig_start, me.donor_start, me.len, &me.moved_len); - fput(donor_filp); + mnt_drop_write(filp->f_path.mnt); + if (me.moved_len > 0) + file_remove_suid(donor_filp); if (copy_to_user((struct move_extent *)arg, &me, sizeof(me))) - return -EFAULT; - + err = -EFAULT; +mext_out: + fput(donor_filp); return err; } diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 74e495dabe09a186f27118219400ca615bfc5922..b1fd3daadc9c50522894fd00ec62bb8e600f9fd0 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -2529,7 +2529,6 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) struct ext4_group_info *db; int err, count = 0, count2 = 0; struct ext4_free_data *entry; - ext4_fsblk_t discard_block; struct list_head *l, *ltmp; list_for_each_safe(l, ltmp, &txn->t_private_list) { @@ -2559,13 +2558,19 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) page_cache_release(e4b.bd_bitmap_page); } ext4_unlock_group(sb, entry->group); - discard_block = (ext4_fsblk_t) entry->group * EXT4_BLOCKS_PER_GROUP(sb) - + entry->start_blk - + le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); - trace_ext4_discard_blocks(sb, (unsigned long long)discard_block, - entry->count); - sb_issue_discard(sb, discard_block, entry->count); - + if (test_opt(sb, DISCARD)) { + ext4_fsblk_t discard_block; + struct ext4_super_block *es = EXT4_SB(sb)->s_es; + + discard_block = (ext4_fsblk_t)entry->group * + EXT4_BLOCKS_PER_GROUP(sb) + + entry->start_blk + + le32_to_cpu(es->s_first_data_block); + trace_ext4_discard_blocks(sb, + (unsigned long long)discard_block, + entry->count); + sb_issue_discard(sb, discard_block, entry->count); + } kmem_cache_free(ext4_free_ext_cachep, entry); ext4_mb_release_desc(&e4b); } @@ -3005,6 +3010,24 @@ static void ext4_mb_collect_stats(struct ext4_allocation_context *ac) trace_ext4_mballoc_prealloc(ac); } +/* + * Called on failure; free up any blocks from the inode PA for this + * context. We don't need this for MB_GROUP_PA because we only change + * pa_free in ext4_mb_release_context(), but on failure, we've already + * zeroed out ac->ac_b_ex.fe_len, so group_pa->pa_free is not changed. + */ +static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac) +{ + struct ext4_prealloc_space *pa = ac->ac_pa; + int len; + + if (pa && pa->pa_type == MB_INODE_PA) { + len = ac->ac_b_ex.fe_len; + pa->pa_free += len; + } + +} + /* * use blocks preallocated to inode */ @@ -3932,7 +3955,7 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac) * per cpu locality group is to reduce the contention between block * request from multiple CPUs. */ - ac->ac_lg = per_cpu_ptr(sbi->s_locality_groups, raw_smp_processor_id()); + ac->ac_lg = __this_cpu_ptr(sbi->s_locality_groups); /* we're going to use group allocation */ ac->ac_flags |= EXT4_MB_HINT_GROUP_ALLOC; @@ -4290,6 +4313,7 @@ repeat: ac->ac_status = AC_STATUS_CONTINUE; goto repeat; } else if (*errp) { + ext4_discard_allocated_blocks(ac); ac->ac_b_ex.fe_len = 0; ar->len = 0; ext4_mb_show_ac(ac); @@ -4422,18 +4446,24 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, return 0; } -/* - * Main entry point into mballoc to free blocks +/** + * ext4_free_blocks() -- Free given blocks and update quota + * @handle: handle for this transaction + * @inode: inode + * @block: start physical block to free + * @count: number of blocks to count + * @metadata: Are these metadata blocks */ -void ext4_mb_free_blocks(handle_t *handle, struct inode *inode, - ext4_fsblk_t block, unsigned long count, - int metadata, unsigned long *freed) +void ext4_free_blocks(handle_t *handle, struct inode *inode, + struct buffer_head *bh, ext4_fsblk_t block, + unsigned long count, int flags) { struct buffer_head *bitmap_bh = NULL; struct super_block *sb = inode->i_sb; struct ext4_allocation_context *ac = NULL; struct ext4_group_desc *gdp; struct ext4_super_block *es; + unsigned long freed = 0; unsigned int overflow; ext4_grpblk_t bit; struct buffer_head *gd_bh; @@ -4443,13 +4473,16 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode, int err = 0; int ret; - *freed = 0; + if (bh) { + if (block) + BUG_ON(block != bh->b_blocknr); + else + block = bh->b_blocknr; + } sbi = EXT4_SB(sb); es = EXT4_SB(sb)->s_es; - if (block < le32_to_cpu(es->s_first_data_block) || - block + count < block || - block + count > ext4_blocks_count(es)) { + if (!ext4_data_block_valid(sbi, block, count)) { ext4_error(sb, __func__, "Freeing blocks not in datazone - " "block = %llu, count = %lu", block, count); @@ -4457,7 +4490,32 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode, } ext4_debug("freeing block %llu\n", block); - trace_ext4_free_blocks(inode, block, count, metadata); + trace_ext4_free_blocks(inode, block, count, flags); + + if (flags & EXT4_FREE_BLOCKS_FORGET) { + struct buffer_head *tbh = bh; + int i; + + BUG_ON(bh && (count > 1)); + + for (i = 0; i < count; i++) { + if (!bh) + tbh = sb_find_get_block(inode->i_sb, + block + i); + ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA, + inode, tbh, block + i); + } + } + + /* + * We need to make sure we don't reuse the freed block until + * after the transaction is committed, which we can do by + * treating the block as metadata, below. We make an + * exception if the inode is to be written in writeback mode + * since writeback mode has weak data consistency guarantees. + */ + if (!ext4_should_writeback_data(inode)) + flags |= EXT4_FREE_BLOCKS_METADATA; ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS); if (ac) { @@ -4533,7 +4591,8 @@ do_more: err = ext4_mb_load_buddy(sb, block_group, &e4b); if (err) goto error_return; - if (metadata && ext4_handle_valid(handle)) { + + if ((flags & EXT4_FREE_BLOCKS_METADATA) && ext4_handle_valid(handle)) { struct ext4_free_data *new_entry; /* * blocks being freed are metadata. these blocks shouldn't @@ -4572,7 +4631,7 @@ do_more: ext4_mb_release_desc(&e4b); - *freed += count; + freed += count; /* We dirtied the bitmap block */ BUFFER_TRACE(bitmap_bh, "dirtied bitmap block"); @@ -4592,6 +4651,8 @@ do_more: } sb->s_dirt = 1; error_return: + if (freed) + vfs_dq_free_block(inode, freed); brelse(bitmap_bh); ext4_std_error(sb, err); if (ac) diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index a93d5b80f3e2f02b1c33592cbd1abc93193677a5..81415814b00b06a0455402078cd41588a615a701 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c @@ -238,7 +238,7 @@ static int extend_credit_for_blkdel(handle_t *handle, struct inode *inode) * So allocate a credit of 3. We may update * quota (user and group). */ - needed = 3 + 2*EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb); + needed = 3 + EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb); if (ext4_journal_extend(handle, needed) != 0) retval = ext4_journal_restart(handle, needed); @@ -262,13 +262,17 @@ static int free_dind_blocks(handle_t *handle, for (i = 0; i < max_entries; i++) { if (tmp_idata[i]) { extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, - le32_to_cpu(tmp_idata[i]), 1, 1); + ext4_free_blocks(handle, inode, 0, + le32_to_cpu(tmp_idata[i]), 1, + EXT4_FREE_BLOCKS_METADATA | + EXT4_FREE_BLOCKS_FORGET); } } put_bh(bh); extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, le32_to_cpu(i_data), 1, 1); + ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data), 1, + EXT4_FREE_BLOCKS_METADATA | + EXT4_FREE_BLOCKS_FORGET); return 0; } @@ -297,7 +301,9 @@ static int free_tind_blocks(handle_t *handle, } put_bh(bh); extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, le32_to_cpu(i_data), 1, 1); + ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data), 1, + EXT4_FREE_BLOCKS_METADATA | + EXT4_FREE_BLOCKS_FORGET); return 0; } @@ -308,8 +314,10 @@ static int free_ind_block(handle_t *handle, struct inode *inode, __le32 *i_data) /* ei->i_data[EXT4_IND_BLOCK] */ if (i_data[0]) { extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, - le32_to_cpu(i_data[0]), 1, 1); + ext4_free_blocks(handle, inode, 0, + le32_to_cpu(i_data[0]), 1, + EXT4_FREE_BLOCKS_METADATA | + EXT4_FREE_BLOCKS_FORGET); } /* ei->i_data[EXT4_DIND_BLOCK] */ @@ -419,7 +427,8 @@ static int free_ext_idx(handle_t *handle, struct inode *inode, } put_bh(bh); extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, block, 1, 1); + ext4_free_blocks(handle, inode, 0, block, 1, + EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); return retval; } @@ -477,7 +486,7 @@ int ext4_ext_migrate(struct inode *inode) handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + - 2 * EXT4_QUOTA_INIT_BLOCKS(inode->i_sb) + EXT4_MAXQUOTAS_INIT_BLOCKS(inode->i_sb) + 1); if (IS_ERR(handle)) { retval = PTR_ERR(handle); diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 25b6b1457360d2ed1df3ab943a99bac01d4a5e11..82c415be87a46be61a36dc205d24c47955937e03 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -77,12 +77,14 @@ static int mext_next_extent(struct inode *inode, struct ext4_ext_path *path, struct ext4_extent **extent) { + struct ext4_extent_header *eh; int ppos, leaf_ppos = path->p_depth; ppos = leaf_ppos; if (EXT_LAST_EXTENT(path[ppos].p_hdr) > path[ppos].p_ext) { /* leaf block */ *extent = ++path[ppos].p_ext; + path[ppos].p_block = ext_pblock(path[ppos].p_ext); return 0; } @@ -119,9 +121,18 @@ mext_next_extent(struct inode *inode, struct ext4_ext_path *path, ext_block_hdr(path[cur_ppos+1].p_bh); } + path[leaf_ppos].p_ext = *extent = NULL; + + eh = path[leaf_ppos].p_hdr; + if (le16_to_cpu(eh->eh_entries) == 0) + /* empty leaf is found */ + return -ENODATA; + /* leaf block */ path[leaf_ppos].p_ext = *extent = EXT_FIRST_EXTENT(path[leaf_ppos].p_hdr); + path[leaf_ppos].p_block = + ext_pblock(path[leaf_ppos].p_ext); return 0; } } @@ -155,40 +166,15 @@ mext_check_null_inode(struct inode *inode1, struct inode *inode2, } /** - * mext_double_down_read - Acquire two inodes' read semaphore - * - * @orig_inode: original inode structure - * @donor_inode: donor inode structure - * Acquire read semaphore of the two inodes (orig and donor) by i_ino order. - */ -static void -mext_double_down_read(struct inode *orig_inode, struct inode *donor_inode) -{ - struct inode *first = orig_inode, *second = donor_inode; - - /* - * Use the inode number to provide the stable locking order instead - * of its address, because the C language doesn't guarantee you can - * compare pointers that don't come from the same array. - */ - if (donor_inode->i_ino < orig_inode->i_ino) { - first = donor_inode; - second = orig_inode; - } - - down_read(&EXT4_I(first)->i_data_sem); - down_read(&EXT4_I(second)->i_data_sem); -} - -/** - * mext_double_down_write - Acquire two inodes' write semaphore + * double_down_write_data_sem - Acquire two inodes' write lock of i_data_sem * * @orig_inode: original inode structure * @donor_inode: donor inode structure - * Acquire write semaphore of the two inodes (orig and donor) by i_ino order. + * Acquire write lock of i_data_sem of the two inodes (orig and donor) by + * i_ino order. */ static void -mext_double_down_write(struct inode *orig_inode, struct inode *donor_inode) +double_down_write_data_sem(struct inode *orig_inode, struct inode *donor_inode) { struct inode *first = orig_inode, *second = donor_inode; @@ -203,32 +189,18 @@ mext_double_down_write(struct inode *orig_inode, struct inode *donor_inode) } down_write(&EXT4_I(first)->i_data_sem); - down_write(&EXT4_I(second)->i_data_sem); + down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING); } /** - * mext_double_up_read - Release two inodes' read semaphore + * double_up_write_data_sem - Release two inodes' write lock of i_data_sem * * @orig_inode: original inode structure to be released its lock first * @donor_inode: donor inode structure to be released its lock second - * Release read semaphore of two inodes (orig and donor). + * Release write lock of i_data_sem of two inodes (orig and donor). */ static void -mext_double_up_read(struct inode *orig_inode, struct inode *donor_inode) -{ - up_read(&EXT4_I(orig_inode)->i_data_sem); - up_read(&EXT4_I(donor_inode)->i_data_sem); -} - -/** - * mext_double_up_write - Release two inodes' write semaphore - * - * @orig_inode: original inode structure to be released its lock first - * @donor_inode: donor inode structure to be released its lock second - * Release write semaphore of two inodes (orig and donor). - */ -static void -mext_double_up_write(struct inode *orig_inode, struct inode *donor_inode) +double_up_write_data_sem(struct inode *orig_inode, struct inode *donor_inode) { up_write(&EXT4_I(orig_inode)->i_data_sem); up_write(&EXT4_I(donor_inode)->i_data_sem); @@ -596,7 +568,7 @@ out: * @tmp_oext: the extent that will belong to the donor inode * @orig_off: block offset of original inode * @donor_off: block offset of donor inode - * @max_count: the maximun length of extents + * @max_count: the maximum length of extents * * Return 0 on success, or a negative error value on failure. */ @@ -661,6 +633,7 @@ mext_calc_swap_extents(struct ext4_extent *tmp_dext, * @donor_inode: donor inode * @from: block offset of orig_inode * @count: block count to be replaced + * @err: pointer to save return value * * Replace original inode extents and donor inode extents page by page. * We implement this replacement in the following three steps: @@ -671,33 +644,33 @@ mext_calc_swap_extents(struct ext4_extent *tmp_dext, * 3. Change the block information of donor inode to point at the saved * original inode blocks in the dummy extents. * - * Return 0 on success, or a negative error value on failure. + * Return replaced block count. */ static int mext_replace_branches(handle_t *handle, struct inode *orig_inode, struct inode *donor_inode, ext4_lblk_t from, - ext4_lblk_t count) + ext4_lblk_t count, int *err) { struct ext4_ext_path *orig_path = NULL; struct ext4_ext_path *donor_path = NULL; struct ext4_extent *oext, *dext; struct ext4_extent tmp_dext, tmp_oext; ext4_lblk_t orig_off = from, donor_off = from; - int err = 0; int depth; int replaced_count = 0; int dext_alen; - mext_double_down_write(orig_inode, donor_inode); + /* Protect extent trees against block allocations via delalloc */ + double_down_write_data_sem(orig_inode, donor_inode); /* Get the original extent for the block "orig_off" */ - err = get_ext_path(orig_inode, orig_off, &orig_path); - if (err) + *err = get_ext_path(orig_inode, orig_off, &orig_path); + if (*err) goto out; /* Get the donor extent for the head */ - err = get_ext_path(donor_inode, donor_off, &donor_path); - if (err) + *err = get_ext_path(donor_inode, donor_off, &donor_path); + if (*err) goto out; depth = ext_depth(orig_inode); oext = orig_path[depth].p_ext; @@ -707,9 +680,9 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, dext = donor_path[depth].p_ext; tmp_dext = *dext; - err = mext_calc_swap_extents(&tmp_dext, &tmp_oext, orig_off, + *err = mext_calc_swap_extents(&tmp_dext, &tmp_oext, orig_off, donor_off, count); - if (err) + if (*err) goto out; /* Loop for the donor extents */ @@ -718,7 +691,7 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, if (!dext) { ext4_error(donor_inode->i_sb, __func__, "The extent for donor must be found"); - err = -EIO; + *err = -EIO; goto out; } else if (donor_off != le32_to_cpu(tmp_dext.ee_block)) { ext4_error(donor_inode->i_sb, __func__, @@ -726,20 +699,20 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, "extent(%u) should be equal", donor_off, le32_to_cpu(tmp_dext.ee_block)); - err = -EIO; + *err = -EIO; goto out; } /* Set donor extent to orig extent */ - err = mext_leaf_block(handle, orig_inode, + *err = mext_leaf_block(handle, orig_inode, orig_path, &tmp_dext, &orig_off); - if (err < 0) + if (*err) goto out; /* Set orig extent to donor extent */ - err = mext_leaf_block(handle, donor_inode, + *err = mext_leaf_block(handle, donor_inode, donor_path, &tmp_oext, &donor_off); - if (err < 0) + if (*err) goto out; dext_alen = ext4_ext_get_actual_len(&tmp_dext); @@ -753,35 +726,25 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, if (orig_path) ext4_ext_drop_refs(orig_path); - err = get_ext_path(orig_inode, orig_off, &orig_path); - if (err) + *err = get_ext_path(orig_inode, orig_off, &orig_path); + if (*err) goto out; depth = ext_depth(orig_inode); oext = orig_path[depth].p_ext; - if (le32_to_cpu(oext->ee_block) + - ext4_ext_get_actual_len(oext) <= orig_off) { - err = 0; - goto out; - } tmp_oext = *oext; if (donor_path) ext4_ext_drop_refs(donor_path); - err = get_ext_path(donor_inode, donor_off, &donor_path); - if (err) + *err = get_ext_path(donor_inode, donor_off, &donor_path); + if (*err) goto out; depth = ext_depth(donor_inode); dext = donor_path[depth].p_ext; - if (le32_to_cpu(dext->ee_block) + - ext4_ext_get_actual_len(dext) <= donor_off) { - err = 0; - goto out; - } tmp_dext = *dext; - err = mext_calc_swap_extents(&tmp_dext, &tmp_oext, orig_off, + *err = mext_calc_swap_extents(&tmp_dext, &tmp_oext, orig_off, donor_off, count - replaced_count); - if (err) + if (*err) goto out; } @@ -795,8 +758,12 @@ out: kfree(donor_path); } - mext_double_up_write(orig_inode, donor_inode); - return err; + ext4_ext_invalidate_cache(orig_inode); + ext4_ext_invalidate_cache(donor_inode); + + double_up_write_data_sem(orig_inode, donor_inode); + + return replaced_count; } /** @@ -808,16 +775,17 @@ out: * @data_offset_in_page: block index where data swapping starts * @block_len_in_page: the number of blocks to be swapped * @uninit: orig extent is uninitialized or not + * @err: pointer to save return value * * Save the data in original inode blocks and replace original inode extents * with donor inode extents by calling mext_replace_branches(). - * Finally, write out the saved data in new original inode blocks. Return 0 - * on success, or a negative error value on failure. + * Finally, write out the saved data in new original inode blocks. Return + * replaced block count. */ static int move_extent_per_page(struct file *o_filp, struct inode *donor_inode, pgoff_t orig_page_offset, int data_offset_in_page, - int block_len_in_page, int uninit) + int block_len_in_page, int uninit, int *err) { struct inode *orig_inode = o_filp->f_dentry->d_inode; struct address_space *mapping = orig_inode->i_mapping; @@ -829,9 +797,11 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, long long offs = orig_page_offset << PAGE_CACHE_SHIFT; unsigned long blocksize = orig_inode->i_sb->s_blocksize; unsigned int w_flags = 0; - unsigned int tmp_data_len, data_len; + unsigned int tmp_data_size, data_size, replaced_size; void *fsdata; - int ret, i, jblocks; + int i, jblocks; + int err2 = 0; + int replaced_count = 0; int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits; /* @@ -841,8 +811,8 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, jblocks = ext4_writepage_trans_blocks(orig_inode) * 2; handle = ext4_journal_start(orig_inode, jblocks); if (IS_ERR(handle)) { - ret = PTR_ERR(handle); - return ret; + *err = PTR_ERR(handle); + return 0; } if (segment_eq(get_fs(), KERNEL_DS)) @@ -858,39 +828,36 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, * Just swap data blocks between orig and donor. */ if (uninit) { - ret = mext_replace_branches(handle, orig_inode, - donor_inode, orig_blk_offset, - block_len_in_page); - - /* Clear the inode cache not to refer to the old data */ - ext4_ext_invalidate_cache(orig_inode); - ext4_ext_invalidate_cache(donor_inode); + replaced_count = mext_replace_branches(handle, orig_inode, + donor_inode, orig_blk_offset, + block_len_in_page, err); goto out2; } offs = (long long)orig_blk_offset << orig_inode->i_blkbits; - /* Calculate data_len */ + /* Calculate data_size */ if ((orig_blk_offset + block_len_in_page - 1) == ((orig_inode->i_size - 1) >> orig_inode->i_blkbits)) { /* Replace the last block */ - tmp_data_len = orig_inode->i_size & (blocksize - 1); + tmp_data_size = orig_inode->i_size & (blocksize - 1); /* - * If data_len equal zero, it shows data_len is multiples of + * If data_size equal zero, it shows data_size is multiples of * blocksize. So we set appropriate value. */ - if (tmp_data_len == 0) - tmp_data_len = blocksize; + if (tmp_data_size == 0) + tmp_data_size = blocksize; - data_len = tmp_data_len + + data_size = tmp_data_size + ((block_len_in_page - 1) << orig_inode->i_blkbits); - } else { - data_len = block_len_in_page << orig_inode->i_blkbits; - } + } else + data_size = block_len_in_page << orig_inode->i_blkbits; + + replaced_size = data_size; - ret = a_ops->write_begin(o_filp, mapping, offs, data_len, w_flags, + *err = a_ops->write_begin(o_filp, mapping, offs, data_size, w_flags, &page, &fsdata); - if (unlikely(ret < 0)) + if (unlikely(*err < 0)) goto out; if (!PageUptodate(page)) { @@ -911,14 +878,17 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, /* Release old bh and drop refs */ try_to_release_page(page, 0); - ret = mext_replace_branches(handle, orig_inode, donor_inode, - orig_blk_offset, block_len_in_page); - if (ret < 0) - goto out; - - /* Clear the inode cache not to refer to the old data */ - ext4_ext_invalidate_cache(orig_inode); - ext4_ext_invalidate_cache(donor_inode); + replaced_count = mext_replace_branches(handle, orig_inode, donor_inode, + orig_blk_offset, block_len_in_page, + &err2); + if (err2) { + if (replaced_count) { + block_len_in_page = replaced_count; + replaced_size = + block_len_in_page << orig_inode->i_blkbits; + } else + goto out; + } if (!page_has_buffers(page)) create_empty_buffers(page, 1 << orig_inode->i_blkbits, 0); @@ -928,16 +898,16 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, bh = bh->b_this_page; for (i = 0; i < block_len_in_page; i++) { - ret = ext4_get_block(orig_inode, + *err = ext4_get_block(orig_inode, (sector_t)(orig_blk_offset + i), bh, 0); - if (ret < 0) + if (*err < 0) goto out; if (bh->b_this_page != NULL) bh = bh->b_this_page; } - ret = a_ops->write_end(o_filp, mapping, offs, data_len, data_len, + *err = a_ops->write_end(o_filp, mapping, offs, data_size, replaced_size, page, fsdata); page = NULL; @@ -951,7 +921,10 @@ out: out2: ext4_journal_stop(handle); - return ret < 0 ? ret : 0; + if (err2) + *err = err2; + + return replaced_count; } /** @@ -962,7 +935,6 @@ out2: * @orig_start: logical start offset in block for orig * @donor_start: logical start offset in block for donor * @len: the number of blocks to be moved - * @moved_len: moved block length * * Check the arguments of ext4_move_extents() whether the files can be * exchanged with each other. @@ -970,8 +942,8 @@ out2: */ static int mext_check_arguments(struct inode *orig_inode, - struct inode *donor_inode, __u64 orig_start, - __u64 donor_start, __u64 *len, __u64 moved_len) + struct inode *donor_inode, __u64 orig_start, + __u64 donor_start, __u64 *len) { ext4_lblk_t orig_blocks, donor_blocks; unsigned int blkbits = orig_inode->i_blkbits; @@ -985,6 +957,13 @@ mext_check_arguments(struct inode *orig_inode, return -EINVAL; } + if (donor_inode->i_mode & (S_ISUID|S_ISGID)) { + ext4_debug("ext4 move extent: suid or sgid is set" + " to donor file [ino:orig %lu, donor %lu]\n", + orig_inode->i_ino, donor_inode->i_ino); + return -EINVAL; + } + /* Ext4 move extent does not support swapfile */ if (IS_SWAPFILE(orig_inode) || IS_SWAPFILE(donor_inode)) { ext4_debug("ext4 move extent: The argument files should " @@ -1025,13 +1004,6 @@ mext_check_arguments(struct inode *orig_inode, return -EINVAL; } - if (moved_len) { - ext4_debug("ext4 move extent: moved_len should be 0 " - "[ino:orig %lu, donor %lu]\n", orig_inode->i_ino, - donor_inode->i_ino); - return -EINVAL; - } - if ((orig_start > EXT_MAX_BLOCK) || (donor_start > EXT_MAX_BLOCK) || (*len > EXT_MAX_BLOCK) || @@ -1088,7 +1060,7 @@ mext_check_arguments(struct inode *orig_inode, } if (!*len) { - ext4_debug("ext4 move extent: len shoudld not be 0 " + ext4_debug("ext4 move extent: len should not be 0 " "[ino:orig %lu, donor %lu]\n", orig_inode->i_ino, donor_inode->i_ino); return -EINVAL; @@ -1232,16 +1204,16 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, return -EINVAL; } - /* protect orig and donor against a truncate */ + /* Protect orig and donor inodes against a truncate */ ret1 = mext_inode_double_lock(orig_inode, donor_inode); if (ret1 < 0) return ret1; - mext_double_down_read(orig_inode, donor_inode); + /* Protect extent tree against block allocations via delalloc */ + double_down_write_data_sem(orig_inode, donor_inode); /* Check the filesystem environment whether move_extent can be done */ ret1 = mext_check_arguments(orig_inode, donor_inode, orig_start, - donor_start, &len, *moved_len); - mext_double_up_read(orig_inode, donor_inode); + donor_start, &len); if (ret1) goto out; @@ -1355,36 +1327,39 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, seq_start = le32_to_cpu(ext_cur->ee_block); rest_blocks = seq_blocks; - /* Discard preallocations of two inodes */ - down_write(&EXT4_I(orig_inode)->i_data_sem); - ext4_discard_preallocations(orig_inode); - up_write(&EXT4_I(orig_inode)->i_data_sem); - - down_write(&EXT4_I(donor_inode)->i_data_sem); - ext4_discard_preallocations(donor_inode); - up_write(&EXT4_I(donor_inode)->i_data_sem); + /* + * Up semaphore to avoid following problems: + * a. transaction deadlock among ext4_journal_start, + * ->write_begin via pagefault, and jbd2_journal_commit + * b. racing with ->readpage, ->write_begin, and ext4_get_block + * in move_extent_per_page + */ + double_up_write_data_sem(orig_inode, donor_inode); while (orig_page_offset <= seq_end_page) { /* Swap original branches with new branches */ - ret1 = move_extent_per_page(o_filp, donor_inode, + block_len_in_page = move_extent_per_page( + o_filp, donor_inode, orig_page_offset, data_offset_in_page, - block_len_in_page, uninit); - if (ret1 < 0) - goto out; - orig_page_offset++; + block_len_in_page, uninit, + &ret1); + /* Count how many blocks we have exchanged */ *moved_len += block_len_in_page; + if (ret1 < 0) + break; if (*moved_len > len) { ext4_error(orig_inode->i_sb, __func__, "We replaced blocks too much! " "sum of replaced: %llu requested: %llu", *moved_len, len); ret1 = -EIO; - goto out; + break; } + orig_page_offset++; data_offset_in_page = 0; rest_blocks -= block_len_in_page; if (rest_blocks > blocks_per_page) @@ -1393,6 +1368,10 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, block_len_in_page = rest_blocks; } + double_down_write_data_sem(orig_inode, donor_inode); + if (ret1 < 0) + break; + /* Decrease buffer counter */ if (holecheck_path) ext4_ext_drop_refs(holecheck_path); @@ -1414,6 +1393,11 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, } out: + if (*moved_len) { + ext4_discard_preallocations(orig_inode); + ext4_discard_preallocations(donor_inode); + } + if (orig_path) { ext4_ext_drop_refs(orig_path); kfree(orig_path); @@ -1422,7 +1406,7 @@ out: ext4_ext_drop_refs(holecheck_path); kfree(holecheck_path); } - + double_up_write_data_sem(orig_inode, donor_inode); ret2 = mext_inode_double_unlock(orig_inode, donor_inode); if (ret1) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 6d2c1b897fc778bd6a08d680aef414a97ac5aa5e..17a17e10dd605198ddfe2dfed530d4cfff6812c1 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1292,9 +1292,6 @@ errout: * add_dirent_to_buf will attempt search the directory block for * space. It will return -ENOSPC if no space is available, and -EIO * and -EEXIST if directory entry already exists. - * - * NOTE! bh is NOT released in the case where ENOSPC is returned. In - * all other cases bh is released. */ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, struct inode *inode, struct ext4_dir_entry_2 *de, @@ -1315,14 +1312,10 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, top = bh->b_data + blocksize - reclen; while ((char *) de <= top) { if (!ext4_check_dir_entry("ext4_add_entry", dir, de, - bh, offset)) { - brelse(bh); + bh, offset)) return -EIO; - } - if (ext4_match(namelen, name, de)) { - brelse(bh); + if (ext4_match(namelen, name, de)) return -EEXIST; - } nlen = EXT4_DIR_REC_LEN(de->name_len); rlen = ext4_rec_len_from_disk(de->rec_len, blocksize); if ((de->inode? rlen - nlen: rlen) >= reclen) @@ -1337,7 +1330,6 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, err = ext4_journal_get_write_access(handle, bh); if (err) { ext4_std_error(dir->i_sb, err); - brelse(bh); return err; } @@ -1377,7 +1369,6 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, err = ext4_handle_dirty_metadata(handle, dir, bh); if (err) ext4_std_error(dir->i_sb, err); - brelse(bh); return 0; } @@ -1471,7 +1462,9 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, if (!(de)) return retval; - return add_dirent_to_buf(handle, dentry, inode, de, bh); + retval = add_dirent_to_buf(handle, dentry, inode, de, bh); + brelse(bh); + return retval; } /* @@ -1514,8 +1507,10 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, if(!bh) return retval; retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh); - if (retval != -ENOSPC) + if (retval != -ENOSPC) { + brelse(bh); return retval; + } if (blocks == 1 && !dx_fallback && EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) @@ -1528,7 +1523,9 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, de = (struct ext4_dir_entry_2 *) bh->b_data; de->inode = 0; de->rec_len = ext4_rec_len_to_disk(blocksize, blocksize); - return add_dirent_to_buf(handle, dentry, inode, de, bh); + retval = add_dirent_to_buf(handle, dentry, inode, de, bh); + brelse(bh); + return retval; } /* @@ -1561,10 +1558,8 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, goto journal_error; err = add_dirent_to_buf(handle, dentry, inode, NULL, bh); - if (err != -ENOSPC) { - bh = NULL; + if (err != -ENOSPC) goto cleanup; - } /* Block full, should compress but for now just split */ dxtrace(printk(KERN_DEBUG "using %u of %u node entries\n", @@ -1657,7 +1652,6 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, if (!de) goto cleanup; err = add_dirent_to_buf(handle, dentry, inode, de, bh); - bh = NULL; goto cleanup; journal_error: @@ -1775,7 +1769,7 @@ static int ext4_create(struct inode *dir, struct dentry *dentry, int mode, retry: handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + - 2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb)); + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -1809,7 +1803,7 @@ static int ext4_mknod(struct inode *dir, struct dentry *dentry, retry: handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + - 2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb)); + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -1846,7 +1840,7 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, int mode) retry: handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + - 2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb)); + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -2259,7 +2253,7 @@ static int ext4_symlink(struct inode *dir, retry: handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + EXT4_INDEX_EXTRA_TRANS_BLOCKS + 5 + - 2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb)); + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 3cfc343c41b53e3eae9e3d635519c653f600acc6..3b2c5541d8a686fe7c780a512c0acd3e6771b3ab 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -247,7 +247,7 @@ static int setup_new_group_blocks(struct super_block *sb, goto exit_bh; if (IS_ERR(gdb = bclean(handle, sb, block))) { - err = PTR_ERR(bh); + err = PTR_ERR(gdb); goto exit_bh; } ext4_handle_dirty_metadata(handle, NULL, gdb); diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d4ca92aab51411de0bab1bf8824e9aa8974b8d17..768c111a77ec16a84427544c9aa2ce0faf81d8b0 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -603,10 +603,6 @@ static void ext4_put_super(struct super_block *sb) if (sb->s_dirt) ext4_commit_super(sb, 1); - ext4_release_system_zone(sb); - ext4_mb_release(sb); - ext4_ext_release(sb); - ext4_xattr_put_super(sb); if (sbi->s_journal) { err = jbd2_journal_destroy(sbi->s_journal); sbi->s_journal = NULL; @@ -614,6 +610,12 @@ static void ext4_put_super(struct super_block *sb) ext4_abort(sb, __func__, "Couldn't clean up the journal"); } + + ext4_release_system_zone(sb); + ext4_mb_release(sb); + ext4_ext_release(sb); + ext4_xattr_put_super(sb); + if (!(sb->s_flags & MS_RDONLY)) { EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); es->s_state = cpu_to_le16(sbi->s_mount_state); @@ -704,6 +706,8 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) spin_lock_init(&(ei->i_block_reservation_lock)); INIT_LIST_HEAD(&ei->i_aio_dio_complete_list); ei->cur_aio_dio = NULL; + ei->i_sync_tid = 0; + ei->i_datasync_tid = 0; return &ei->vfs_inode; } @@ -765,9 +769,22 @@ static inline void ext4_show_quota_options(struct seq_file *seq, #if defined(CONFIG_QUOTA) struct ext4_sb_info *sbi = EXT4_SB(sb); - if (sbi->s_jquota_fmt) - seq_printf(seq, ",jqfmt=%s", - (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold" : "vfsv0"); + if (sbi->s_jquota_fmt) { + char *fmtname = ""; + + switch (sbi->s_jquota_fmt) { + case QFMT_VFS_OLD: + fmtname = "vfsold"; + break; + case QFMT_VFS_V0: + fmtname = "vfsv0"; + break; + case QFMT_VFS_V1: + fmtname = "vfsv1"; + break; + } + seq_printf(seq, ",jqfmt=%s", fmtname); + } if (sbi->s_qf_names[USRQUOTA]) seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]); @@ -899,6 +916,12 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) if (test_opt(sb, NO_AUTO_DA_ALLOC)) seq_puts(seq, ",noauto_da_alloc"); + if (test_opt(sb, DISCARD)) + seq_puts(seq, ",discard"); + + if (test_opt(sb, NOLOAD)) + seq_puts(seq, ",norecovery"); + ext4_show_quota_options(seq, sb); return 0; @@ -1074,12 +1097,13 @@ enum { Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, Opt_data_err_abort, Opt_data_err_ignore, Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, - Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, - Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize, - Opt_usrquota, Opt_grpquota, Opt_i_version, + Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, + Opt_noquota, Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, + Opt_resize, Opt_usrquota, Opt_grpquota, Opt_i_version, Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_block_validity, Opt_noblock_validity, - Opt_inode_readahead_blks, Opt_journal_ioprio + Opt_inode_readahead_blks, Opt_journal_ioprio, + Opt_discard, Opt_nodiscard, }; static const match_table_t tokens = { @@ -1104,6 +1128,7 @@ static const match_table_t tokens = { {Opt_acl, "acl"}, {Opt_noacl, "noacl"}, {Opt_noload, "noload"}, + {Opt_noload, "norecovery"}, {Opt_nobh, "nobh"}, {Opt_bh, "bh"}, {Opt_commit, "commit=%u"}, @@ -1125,6 +1150,7 @@ static const match_table_t tokens = { {Opt_grpjquota, "grpjquota=%s"}, {Opt_jqfmt_vfsold, "jqfmt=vfsold"}, {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, + {Opt_jqfmt_vfsv1, "jqfmt=vfsv1"}, {Opt_grpquota, "grpquota"}, {Opt_noquota, "noquota"}, {Opt_quota, "quota"}, @@ -1144,6 +1170,8 @@ static const match_table_t tokens = { {Opt_auto_da_alloc, "auto_da_alloc=%u"}, {Opt_auto_da_alloc, "auto_da_alloc"}, {Opt_noauto_da_alloc, "noauto_da_alloc"}, + {Opt_discard, "discard"}, + {Opt_nodiscard, "nodiscard"}, {Opt_err, NULL}, }; @@ -1425,6 +1453,9 @@ clear_qf_name: goto set_qf_format; case Opt_jqfmt_vfsv0: qfmt = QFMT_VFS_V0; + goto set_qf_format; + case Opt_jqfmt_vfsv1: + qfmt = QFMT_VFS_V1; set_qf_format: if (sb_any_quota_loaded(sb) && sbi->s_jquota_fmt != qfmt) { @@ -1467,6 +1498,7 @@ set_qf_format: case Opt_offgrpjquota: case Opt_jqfmt_vfsold: case Opt_jqfmt_vfsv0: + case Opt_jqfmt_vfsv1: ext4_msg(sb, KERN_ERR, "journaled quota options not supported"); break; @@ -1565,6 +1597,12 @@ set_qf_format: else set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC); break; + case Opt_discard: + set_opt(sbi->s_mount_opt, DISCARD); + break; + case Opt_nodiscard: + clear_opt(sbi->s_mount_opt, DISCARD); + break; default: ext4_msg(sb, KERN_ERR, "Unrecognized mount option \"%s\" " @@ -1673,14 +1711,14 @@ static int ext4_fill_flex_info(struct super_block *sb) size_t size; int i; - if (!sbi->s_es->s_log_groups_per_flex) { + sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex; + groups_per_flex = 1 << sbi->s_log_groups_per_flex; + + if (groups_per_flex < 2) { sbi->s_log_groups_per_flex = 0; return 1; } - sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex; - groups_per_flex = 1 << sbi->s_log_groups_per_flex; - /* We allocate both existing and potentially added groups */ flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) + ((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) << @@ -2721,26 +2759,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) { if (ext4_load_journal(sb, es, journal_devnum)) goto failed_mount3; - if (!(sb->s_flags & MS_RDONLY) && - EXT4_SB(sb)->s_journal->j_failed_commit) { - ext4_msg(sb, KERN_CRIT, "error: " - "ext4_fill_super: Journal transaction " - "%u is corrupt", - EXT4_SB(sb)->s_journal->j_failed_commit); - if (test_opt(sb, ERRORS_RO)) { - ext4_msg(sb, KERN_CRIT, - "Mounting filesystem read-only"); - sb->s_flags |= MS_RDONLY; - EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; - es->s_state |= cpu_to_le16(EXT4_ERROR_FS); - } - if (test_opt(sb, ERRORS_PANIC)) { - EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; - es->s_state |= cpu_to_le16(EXT4_ERROR_FS); - ext4_commit_super(sb, 1); - goto failed_mount4; - } - } } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) && EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) { ext4_msg(sb, KERN_ERR, "required journal recovery " @@ -3668,13 +3686,11 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) - percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter); - ext4_free_blocks_count_set(es, buf->f_bfree); buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); if (buf->f_bfree < ext4_r_blocks_count(es)) buf->f_bavail = 0; buf->f_files = le32_to_cpu(es->s_inodes_count); buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter); - es->s_free_inodes_count = cpu_to_le32(buf->f_ffree); buf->f_namelen = EXT4_NAME_LEN; fsid = le64_to_cpup((void *)es->s_uuid) ^ le64_to_cpup((void *)es->s_uuid + sizeof(u64)); @@ -3966,6 +3982,58 @@ static int ext4_get_sb(struct file_system_type *fs_type, int flags, return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super,mnt); } +#if !defined(CONTIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) +static struct file_system_type ext2_fs_type = { + .owner = THIS_MODULE, + .name = "ext2", + .get_sb = ext4_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV, +}; + +static inline void register_as_ext2(void) +{ + int err = register_filesystem(&ext2_fs_type); + if (err) + printk(KERN_WARNING + "EXT4-fs: Unable to register as ext2 (%d)\n", err); +} + +static inline void unregister_as_ext2(void) +{ + unregister_filesystem(&ext2_fs_type); +} +#else +static inline void register_as_ext2(void) { } +static inline void unregister_as_ext2(void) { } +#endif + +#if !defined(CONTIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) +static struct file_system_type ext3_fs_type = { + .owner = THIS_MODULE, + .name = "ext3", + .get_sb = ext4_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV, +}; + +static inline void register_as_ext3(void) +{ + int err = register_filesystem(&ext3_fs_type); + if (err) + printk(KERN_WARNING + "EXT4-fs: Unable to register as ext3 (%d)\n", err); +} + +static inline void unregister_as_ext3(void) +{ + unregister_filesystem(&ext3_fs_type); +} +#else +static inline void register_as_ext3(void) { } +static inline void unregister_as_ext3(void) { } +#endif + static struct file_system_type ext4_fs_type = { .owner = THIS_MODULE, .name = "ext4", @@ -3995,11 +4063,15 @@ static int __init init_ext4_fs(void) err = init_inodecache(); if (err) goto out1; + register_as_ext2(); + register_as_ext3(); err = register_filesystem(&ext4_fs_type); if (err) goto out; return 0; out: + unregister_as_ext2(); + unregister_as_ext3(); destroy_inodecache(); out1: exit_ext4_xattr(); @@ -4015,6 +4087,8 @@ out4: static void __exit exit_ext4_fs(void) { + unregister_as_ext2(); + unregister_as_ext3(); unregister_filesystem(&ext4_fs_type); destroy_inodecache(); exit_ext4_xattr(); diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index fed5b01d7a8daa38cae14572ff7f43f3a1860077..910bf9a59cb39c6018d7c7f4d31c0bc00ef26749 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -482,9 +482,10 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, ea_bdebug(bh, "refcount now=0; freeing"); if (ce) mb_cache_entry_free(ce); - ext4_free_blocks(handle, inode, bh->b_blocknr, 1, 1); get_bh(bh); - ext4_forget(handle, 1, inode, bh, bh->b_blocknr); + ext4_free_blocks(handle, inode, bh, 0, 1, + EXT4_FREE_BLOCKS_METADATA | + EXT4_FREE_BLOCKS_FORGET); } else { le32_add_cpu(&BHDR(bh)->h_refcount, -1); error = ext4_handle_dirty_metadata(handle, inode, bh); @@ -832,7 +833,8 @@ inserted: new_bh = sb_getblk(sb, block); if (!new_bh) { getblk_failed: - ext4_free_blocks(handle, inode, block, 1, 1); + ext4_free_blocks(handle, inode, 0, block, 1, + EXT4_FREE_BLOCKS_METADATA); error = -EIO; goto cleanup; } @@ -988,6 +990,10 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, if (error) goto cleanup; + error = ext4_journal_get_write_access(handle, is.iloc.bh); + if (error) + goto cleanup; + if (EXT4_I(inode)->i_state & EXT4_STATE_NEW) { struct ext4_inode *raw_inode = ext4_raw_inode(&is.iloc); memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size); @@ -1013,9 +1019,6 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, if (flags & XATTR_CREATE) goto cleanup; } - error = ext4_journal_get_write_access(handle, is.iloc.bh); - if (error) - goto cleanup; if (!value) { if (!is.s.not_found) error = ext4_xattr_ibody_set(handle, inode, &i, &is); diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c index defb932eee9a9f45836ac2f62ee9dcf5f3838152..0b3fa7974fa8fb26fb7c1bcfe81509ce24cda439 100644 --- a/fs/isofs/compress.c +++ b/fs/isofs/compress.c @@ -36,286 +36,323 @@ static void *zisofs_zlib_workspace; static DEFINE_MUTEX(zisofs_zlib_lock); /* - * When decompressing, we typically obtain more than one page - * per reference. We inject the additional pages into the page - * cache as a form of readahead. + * Read data of @inode from @block_start to @block_end and uncompress + * to one zisofs block. Store the data in the @pages array with @pcount + * entries. Start storing at offset @poffset of the first page. */ -static int zisofs_readpage(struct file *file, struct page *page) +static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start, + loff_t block_end, int pcount, + struct page **pages, unsigned poffset, + int *errp) { - struct inode *inode = file->f_path.dentry->d_inode; - struct address_space *mapping = inode->i_mapping; - unsigned int maxpage, xpage, fpage, blockindex; - unsigned long offset; - unsigned long blockptr, blockendptr, cstart, cend, csize; - struct buffer_head *bh, *ptrbh[2]; - unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); - unsigned int bufshift = ISOFS_BUFFER_BITS(inode); - unsigned long bufmask = bufsize - 1; - int err = -EIO; - int i; - unsigned int header_size = ISOFS_I(inode)->i_format_parm[0]; unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1]; - /* unsigned long zisofs_block_size = 1UL << zisofs_block_shift; */ - unsigned int zisofs_block_page_shift = zisofs_block_shift-PAGE_CACHE_SHIFT; - unsigned long zisofs_block_pages = 1UL << zisofs_block_page_shift; - unsigned long zisofs_block_page_mask = zisofs_block_pages-1; - struct page *pages[zisofs_block_pages]; - unsigned long index = page->index; - int indexblocks; - - /* We have already been given one page, this is the one - we must do. */ - xpage = index & zisofs_block_page_mask; - pages[xpage] = page; - - /* The remaining pages need to be allocated and inserted */ - offset = index & ~zisofs_block_page_mask; - blockindex = offset >> zisofs_block_page_shift; - maxpage = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - - /* - * If this page is wholly outside i_size we just return zero; - * do_generic_file_read() will handle this for us - */ - if (page->index >= maxpage) { - SetPageUptodate(page); - unlock_page(page); + unsigned int bufsize = ISOFS_BUFFER_SIZE(inode); + unsigned int bufshift = ISOFS_BUFFER_BITS(inode); + unsigned int bufmask = bufsize - 1; + int i, block_size = block_end - block_start; + z_stream stream = { .total_out = 0, + .avail_in = 0, + .avail_out = 0, }; + int zerr; + int needblocks = (block_size + (block_start & bufmask) + bufmask) + >> bufshift; + int haveblocks; + blkcnt_t blocknum; + struct buffer_head *bhs[needblocks + 1]; + int curbh, curpage; + + if (block_size > deflateBound(1UL << zisofs_block_shift)) { + *errp = -EIO; return 0; } - - maxpage = min(zisofs_block_pages, maxpage-offset); - - for ( i = 0 ; i < maxpage ; i++, offset++ ) { - if ( i != xpage ) { - pages[i] = grab_cache_page_nowait(mapping, offset); - } - page = pages[i]; - if ( page ) { - ClearPageError(page); - kmap(page); + /* Empty block? */ + if (block_size == 0) { + for ( i = 0 ; i < pcount ; i++ ) { + if (!pages[i]) + continue; + memset(page_address(pages[i]), 0, PAGE_CACHE_SIZE); + flush_dcache_page(pages[i]); + SetPageUptodate(pages[i]); } + return ((loff_t)pcount) << PAGE_CACHE_SHIFT; } - /* This is the last page filled, plus one; used in case of abort. */ - fpage = 0; + /* Because zlib is not thread-safe, do all the I/O at the top. */ + blocknum = block_start >> bufshift; + memset(bhs, 0, (needblocks + 1) * sizeof(struct buffer_head *)); + haveblocks = isofs_get_blocks(inode, blocknum, bhs, needblocks); + ll_rw_block(READ, haveblocks, bhs); - /* Find the pointer to this specific chunk */ - /* Note: we're not using isonum_731() here because the data is known aligned */ - /* Note: header_size is in 32-bit words (4 bytes) */ - blockptr = (header_size + blockindex) << 2; - blockendptr = blockptr + 4; + curbh = 0; + curpage = 0; + /* + * First block is special since it may be fractional. We also wait for + * it before grabbing the zlib mutex; odds are that the subsequent + * blocks are going to come in in short order so we don't hold the zlib + * mutex longer than necessary. + */ - indexblocks = ((blockptr^blockendptr) >> bufshift) ? 2 : 1; - ptrbh[0] = ptrbh[1] = NULL; + if (!bhs[0]) + goto b_eio; - if ( isofs_get_blocks(inode, blockptr >> bufshift, ptrbh, indexblocks) != indexblocks ) { - if ( ptrbh[0] ) brelse(ptrbh[0]); - printk(KERN_DEBUG "zisofs: Null buffer on reading block table, inode = %lu, block = %lu\n", - inode->i_ino, blockptr >> bufshift); - goto eio; - } - ll_rw_block(READ, indexblocks, ptrbh); - - bh = ptrbh[0]; - if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) { - printk(KERN_DEBUG "zisofs: Failed to read block table, inode = %lu, block = %lu\n", - inode->i_ino, blockptr >> bufshift); - if ( ptrbh[1] ) - brelse(ptrbh[1]); - goto eio; - } - cstart = le32_to_cpu(*(__le32 *)(bh->b_data + (blockptr & bufmask))); - - if ( indexblocks == 2 ) { - /* We just crossed a block boundary. Switch to the next block */ - brelse(bh); - bh = ptrbh[1]; - if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) { - printk(KERN_DEBUG "zisofs: Failed to read block table, inode = %lu, block = %lu\n", - inode->i_ino, blockendptr >> bufshift); - goto eio; - } + wait_on_buffer(bhs[0]); + if (!buffer_uptodate(bhs[0])) { + *errp = -EIO; + goto b_eio; } - cend = le32_to_cpu(*(__le32 *)(bh->b_data + (blockendptr & bufmask))); - brelse(bh); - if (cstart > cend) - goto eio; + stream.workspace = zisofs_zlib_workspace; + mutex_lock(&zisofs_zlib_lock); - csize = cend-cstart; - - if (csize > deflateBound(1UL << zisofs_block_shift)) - goto eio; - - /* Now page[] contains an array of pages, any of which can be NULL, - and the locks on which we hold. We should now read the data and - release the pages. If the pages are NULL the decompressed data - for that particular page should be discarded. */ - - if ( csize == 0 ) { - /* This data block is empty. */ - - for ( fpage = 0 ; fpage < maxpage ; fpage++ ) { - if ( (page = pages[fpage]) != NULL ) { - memset(page_address(page), 0, PAGE_CACHE_SIZE); - - flush_dcache_page(page); - SetPageUptodate(page); - kunmap(page); - unlock_page(page); - if ( fpage == xpage ) - err = 0; /* The critical page */ - else - page_cache_release(page); + zerr = zlib_inflateInit(&stream); + if (zerr != Z_OK) { + if (zerr == Z_MEM_ERROR) + *errp = -ENOMEM; + else + *errp = -EIO; + printk(KERN_DEBUG "zisofs: zisofs_inflateInit returned %d\n", + zerr); + goto z_eio; + } + + while (curpage < pcount && curbh < haveblocks && + zerr != Z_STREAM_END) { + if (!stream.avail_out) { + if (pages[curpage]) { + stream.next_out = page_address(pages[curpage]) + + poffset; + stream.avail_out = PAGE_CACHE_SIZE - poffset; + poffset = 0; + } else { + stream.next_out = (void *)&zisofs_sink_page; + stream.avail_out = PAGE_CACHE_SIZE; } } - } else { - /* This data block is compressed. */ - z_stream stream; - int bail = 0, left_out = -1; - int zerr; - int needblocks = (csize + (cstart & bufmask) + bufmask) >> bufshift; - int haveblocks; - struct buffer_head *bhs[needblocks+1]; - struct buffer_head **bhptr; - - /* Because zlib is not thread-safe, do all the I/O at the top. */ - - blockptr = cstart >> bufshift; - memset(bhs, 0, (needblocks+1)*sizeof(struct buffer_head *)); - haveblocks = isofs_get_blocks(inode, blockptr, bhs, needblocks); - ll_rw_block(READ, haveblocks, bhs); - - bhptr = &bhs[0]; - bh = *bhptr++; - - /* First block is special since it may be fractional. - We also wait for it before grabbing the zlib - mutex; odds are that the subsequent blocks are - going to come in in short order so we don't hold - the zlib mutex longer than necessary. */ - - if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) { - printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n", - fpage, xpage, csize); - goto b_eio; - } - stream.next_in = bh->b_data + (cstart & bufmask); - stream.avail_in = min(bufsize-(cstart & bufmask), csize); - csize -= stream.avail_in; - - stream.workspace = zisofs_zlib_workspace; - mutex_lock(&zisofs_zlib_lock); - - zerr = zlib_inflateInit(&stream); - if ( zerr != Z_OK ) { - if ( err && zerr == Z_MEM_ERROR ) - err = -ENOMEM; - printk(KERN_DEBUG "zisofs: zisofs_inflateInit returned %d\n", - zerr); - goto z_eio; + if (!stream.avail_in) { + wait_on_buffer(bhs[curbh]); + if (!buffer_uptodate(bhs[curbh])) { + *errp = -EIO; + break; + } + stream.next_in = bhs[curbh]->b_data + + (block_start & bufmask); + stream.avail_in = min_t(unsigned, bufsize - + (block_start & bufmask), + block_size); + block_size -= stream.avail_in; + block_start = 0; } - while ( !bail && fpage < maxpage ) { - page = pages[fpage]; - if ( page ) - stream.next_out = page_address(page); - else - stream.next_out = (void *)&zisofs_sink_page; - stream.avail_out = PAGE_CACHE_SIZE; - - while ( stream.avail_out ) { - int ao, ai; - if ( stream.avail_in == 0 && left_out ) { - if ( !csize ) { - printk(KERN_WARNING "zisofs: ZF read beyond end of input\n"); - bail = 1; - break; - } else { - bh = *bhptr++; - if ( !bh || - (wait_on_buffer(bh), !buffer_uptodate(bh)) ) { - /* Reached an EIO */ - printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n", - fpage, xpage, csize); - - bail = 1; - break; - } - stream.next_in = bh->b_data; - stream.avail_in = min(csize,bufsize); - csize -= stream.avail_in; - } - } - ao = stream.avail_out; ai = stream.avail_in; - zerr = zlib_inflate(&stream, Z_SYNC_FLUSH); - left_out = stream.avail_out; - if ( zerr == Z_BUF_ERROR && stream.avail_in == 0 ) - continue; - if ( zerr != Z_OK ) { - /* EOF, error, or trying to read beyond end of input */ - if ( err && zerr == Z_MEM_ERROR ) - err = -ENOMEM; - if ( zerr != Z_STREAM_END ) - printk(KERN_DEBUG "zisofs: zisofs_inflate returned %d, inode = %lu, index = %lu, fpage = %d, xpage = %d, avail_in = %d, avail_out = %d, ai = %d, ao = %d\n", - zerr, inode->i_ino, index, - fpage, xpage, - stream.avail_in, stream.avail_out, - ai, ao); - bail = 1; - break; + while (stream.avail_out && stream.avail_in) { + zerr = zlib_inflate(&stream, Z_SYNC_FLUSH); + if (zerr == Z_BUF_ERROR && stream.avail_in == 0) + break; + if (zerr == Z_STREAM_END) + break; + if (zerr != Z_OK) { + /* EOF, error, or trying to read beyond end of input */ + if (zerr == Z_MEM_ERROR) + *errp = -ENOMEM; + else { + printk(KERN_DEBUG + "zisofs: zisofs_inflate returned" + " %d, inode = %lu," + " page idx = %d, bh idx = %d," + " avail_in = %d," + " avail_out = %d\n", + zerr, inode->i_ino, curpage, + curbh, stream.avail_in, + stream.avail_out); + *errp = -EIO; } + goto inflate_out; } + } - if ( stream.avail_out && zerr == Z_STREAM_END ) { - /* Fractional page written before EOF. This may - be the last page in the file. */ - memset(stream.next_out, 0, stream.avail_out); - stream.avail_out = 0; + if (!stream.avail_out) { + /* This page completed */ + if (pages[curpage]) { + flush_dcache_page(pages[curpage]); + SetPageUptodate(pages[curpage]); } + curpage++; + } + if (!stream.avail_in) + curbh++; + } +inflate_out: + zlib_inflateEnd(&stream); - if ( !stream.avail_out ) { - /* This page completed */ - if ( page ) { - flush_dcache_page(page); - SetPageUptodate(page); - kunmap(page); - unlock_page(page); - if ( fpage == xpage ) - err = 0; /* The critical page */ - else - page_cache_release(page); - } - fpage++; - } +z_eio: + mutex_unlock(&zisofs_zlib_lock); + +b_eio: + for (i = 0; i < haveblocks; i++) + brelse(bhs[i]); + return stream.total_out; +} + +/* + * Uncompress data so that pages[full_page] is fully uptodate and possibly + * fills in other pages if we have data for them. + */ +static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount, + struct page **pages) +{ + loff_t start_off, end_off; + loff_t block_start, block_end; + unsigned int header_size = ISOFS_I(inode)->i_format_parm[0]; + unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1]; + unsigned int blockptr; + loff_t poffset = 0; + blkcnt_t cstart_block, cend_block; + struct buffer_head *bh; + unsigned int blkbits = ISOFS_BUFFER_BITS(inode); + unsigned int blksize = 1 << blkbits; + int err; + loff_t ret; + + BUG_ON(!pages[full_page]); + + /* + * We want to read at least 'full_page' page. Because we have to + * uncompress the whole compression block anyway, fill the surrounding + * pages with the data we have anyway... + */ + start_off = page_offset(pages[full_page]); + end_off = min_t(loff_t, start_off + PAGE_CACHE_SIZE, inode->i_size); + + cstart_block = start_off >> zisofs_block_shift; + cend_block = (end_off + (1 << zisofs_block_shift) - 1) + >> zisofs_block_shift; + + WARN_ON(start_off - (full_page << PAGE_CACHE_SHIFT) != + ((cstart_block << zisofs_block_shift) & PAGE_CACHE_MASK)); + + /* Find the pointer to this specific chunk */ + /* Note: we're not using isonum_731() here because the data is known aligned */ + /* Note: header_size is in 32-bit words (4 bytes) */ + blockptr = (header_size + cstart_block) << 2; + bh = isofs_bread(inode, blockptr >> blkbits); + if (!bh) + return -EIO; + block_start = le32_to_cpu(*(__le32 *) + (bh->b_data + (blockptr & (blksize - 1)))); + + while (cstart_block < cend_block && pcount > 0) { + /* Load end of the compressed block in the file */ + blockptr += 4; + /* Traversed to next block? */ + if (!(blockptr & (blksize - 1))) { + brelse(bh); + + bh = isofs_bread(inode, blockptr >> blkbits); + if (!bh) + return -EIO; + } + block_end = le32_to_cpu(*(__le32 *) + (bh->b_data + (blockptr & (blksize - 1)))); + if (block_start > block_end) { + brelse(bh); + return -EIO; + } + err = 0; + ret = zisofs_uncompress_block(inode, block_start, block_end, + pcount, pages, poffset, &err); + poffset += ret; + pages += poffset >> PAGE_CACHE_SHIFT; + pcount -= poffset >> PAGE_CACHE_SHIFT; + full_page -= poffset >> PAGE_CACHE_SHIFT; + poffset &= ~PAGE_CACHE_MASK; + + if (err) { + brelse(bh); + /* + * Did we finish reading the page we really wanted + * to read? + */ + if (full_page < 0) + return 0; + return err; } - zlib_inflateEnd(&stream); - z_eio: - mutex_unlock(&zisofs_zlib_lock); + block_start = block_end; + cstart_block++; + } + + if (poffset && *pages) { + memset(page_address(*pages) + poffset, 0, + PAGE_CACHE_SIZE - poffset); + flush_dcache_page(*pages); + SetPageUptodate(*pages); + } + return 0; +} - b_eio: - for ( i = 0 ; i < haveblocks ; i++ ) { - if ( bhs[i] ) - brelse(bhs[i]); +/* + * When decompressing, we typically obtain more than one page + * per reference. We inject the additional pages into the page + * cache as a form of readahead. + */ +static int zisofs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = file->f_path.dentry->d_inode; + struct address_space *mapping = inode->i_mapping; + int err; + int i, pcount, full_page; + unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1]; + unsigned int zisofs_pages_per_cblock = + PAGE_CACHE_SHIFT <= zisofs_block_shift ? + (1 << (zisofs_block_shift - PAGE_CACHE_SHIFT)) : 0; + struct page *pages[max_t(unsigned, zisofs_pages_per_cblock, 1)]; + pgoff_t index = page->index, end_index; + + end_index = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + /* + * If this page is wholly outside i_size we just return zero; + * do_generic_file_read() will handle this for us + */ + if (index >= end_index) { + SetPageUptodate(page); + unlock_page(page); + return 0; + } + + if (PAGE_CACHE_SHIFT <= zisofs_block_shift) { + /* We have already been given one page, this is the one + we must do. */ + full_page = index & (zisofs_pages_per_cblock - 1); + pcount = min_t(int, zisofs_pages_per_cblock, + end_index - (index & ~(zisofs_pages_per_cblock - 1))); + index -= full_page; + } else { + full_page = 0; + pcount = 1; + } + pages[full_page] = page; + + for (i = 0; i < pcount; i++, index++) { + if (i != full_page) + pages[i] = grab_cache_page_nowait(mapping, index); + if (pages[i]) { + ClearPageError(pages[i]); + kmap(pages[i]); } } -eio: + err = zisofs_fill_pages(inode, full_page, pcount, pages); /* Release any residual pages, do not SetPageUptodate */ - while ( fpage < maxpage ) { - page = pages[fpage]; - if ( page ) { - flush_dcache_page(page); - if ( fpage == xpage ) - SetPageError(page); - kunmap(page); - unlock_page(page); - if ( fpage != xpage ) - page_cache_release(page); + for (i = 0; i < pcount; i++) { + if (pages[i]) { + flush_dcache_page(pages[i]); + if (i == full_page && err) + SetPageError(pages[i]); + kunmap(pages[i]); + unlock_page(pages[i]); + if (i != full_page) + page_cache_release(pages[i]); } - fpage++; } /* At this point, err contains 0 or -EIO depending on the "critical" page */ diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index c2fb2dd0131f36cf2bcb3e1ad342a2c64cbd8422..96a685c550fde27420a1e8d2e697ef5c4bc72705 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -518,8 +518,7 @@ repeat: if (algo == SIG('p', 'z')) { int block_shift = isonum_711(&rr->u.ZF.parms[1]); - if (block_shift < PAGE_CACHE_SHIFT - || block_shift > 17) { + if (block_shift > 17) { printk(KERN_WARNING "isofs: " "Can't handle ZF block " "size of 2^%d\n", diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index d4cfd6d2779e07fe1d5381975840ccb3e3486566..6a10238d2c63d3f7c7945d1d6cbe6a4adcb57d04 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -286,7 +286,7 @@ static int journal_finish_inode_data_buffers(journal_t *journal, if (err) { /* * Because AS_EIO is cleared by - * wait_on_page_writeback_range(), set it again so + * filemap_fdatawait_range(), set it again so * that user process can get -EIO from fsync(). */ set_bit(AS_EIO, @@ -636,6 +636,10 @@ void jbd2_journal_commit_transaction(journal_t *journal) JBUFFER_TRACE(jh, "ph3: write metadata"); flags = jbd2_journal_write_metadata_buffer(commit_transaction, jh, &new_jh, blocknr); + if (flags < 0) { + jbd2_journal_abort(journal, flags); + continue; + } set_bit(BH_JWrite, &jh2bh(new_jh)->b_state); wbuf[bufs++] = jh2bh(new_jh); diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index fed85388ee86434509805091a933b34091c50596..b7ca3a92a4dba0b23f555a75cac79fea1b6ae9e4 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -78,6 +78,7 @@ EXPORT_SYMBOL(jbd2_journal_errno); EXPORT_SYMBOL(jbd2_journal_ack_err); EXPORT_SYMBOL(jbd2_journal_clear_err); EXPORT_SYMBOL(jbd2_log_wait_commit); +EXPORT_SYMBOL(jbd2_log_start_commit); EXPORT_SYMBOL(jbd2_journal_start_commit); EXPORT_SYMBOL(jbd2_journal_force_commit_nested); EXPORT_SYMBOL(jbd2_journal_wipe); @@ -358,6 +359,10 @@ repeat: jbd_unlock_bh_state(bh_in); tmp = jbd2_alloc(bh_in->b_size, GFP_NOFS); + if (!tmp) { + jbd2_journal_put_journal_head(new_jh); + return -ENOMEM; + } jbd_lock_bh_state(bh_in); if (jh_in->b_frozen_data) { jbd2_free(tmp, bh_in->b_size); @@ -1248,6 +1253,13 @@ int jbd2_journal_load(journal_t *journal) if (jbd2_journal_recover(journal)) goto recovery_error; + if (journal->j_failed_commit) { + printk(KERN_ERR "JBD2: journal transaction %u on %s " + "is corrupt.\n", journal->j_failed_commit, + journal->j_devname); + return -EIO; + } + /* OK, we've finished with the dynamic journal bits: * reinitialise the dynamic contents of the superblock in memory * and reset them on disk. */ diff --git a/fs/namei.c b/fs/namei.c index d11f404667e962ababa87f3678a52e78c50794dd..87f97ba90ad17d271baf15b2b2e65381a583c163 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1279,28 +1279,6 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) return __lookup_hash(&this, base, NULL); } -/** - * lookup_one_noperm - bad hack for sysfs - * @name: pathname component to lookup - * @base: base directory to lookup from - * - * This is a variant of lookup_one_len that doesn't perform any permission - * checks. It's a horrible hack to work around the braindead sysfs - * architecture and should not be used anywhere else. - * - * DON'T USE THIS FUNCTION EVER, thanks. - */ -struct dentry *lookup_one_noperm(const char *name, struct dentry *base) -{ - int err; - struct qstr this; - - err = __lookup_one_len(name, &this, base, strlen(name)); - if (err) - return ERR_PTR(err); - return __lookup_hash(&this, base, NULL); -} - int user_path_at(int dfd, const char __user *name, unsigned flags, struct path *path) { @@ -1678,6 +1656,15 @@ struct file *do_filp_open(int dfd, const char *pathname, int will_write; int flag = open_to_namei_flags(open_flag); + /* + * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only + * check for O_DSYNC if the need any syncing at all we enforce it's + * always set instead of having to deal with possibly weird behaviour + * for malicious applications setting only __O_SYNC. + */ + if (open_flag & __O_SYNC) + open_flag |= O_DSYNC; + if (!acc_mode) acc_mode = MAY_OPEN | ACC_MODE(flag); diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 293fa0528a6e10001a66ee5e94c33fcfa95b7c65..73ab220354dfc6c2a046535ec959707779ed56ed 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -78,11 +78,6 @@ nfs4_callback_svc(void *vrqstp) set_freezable(); - /* - * FIXME: do we really need to run this under the BKL? If so, please - * add a comment about what it's intended to protect. - */ - lock_kernel(); while (!kthread_should_stop()) { /* * Listen for a request on the socket @@ -104,7 +99,6 @@ nfs4_callback_svc(void *vrqstp) preverr = err; svc_process(rqstp); } - unlock_kernel(); return 0; } @@ -160,11 +154,6 @@ nfs41_callback_svc(void *vrqstp) set_freezable(); - /* - * FIXME: do we really need to run this under the BKL? If so, please - * add a comment about what it's intended to protect. - */ - lock_kernel(); while (!kthread_should_stop()) { prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE); spin_lock_bh(&serv->sv_cb_lock); @@ -183,7 +172,6 @@ nfs41_callback_svc(void *vrqstp) } finish_wait(&serv->sv_cb_waitq, &wq); } - unlock_kernel(); return 0; } @@ -397,6 +385,7 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp) */ static struct svc_version *nfs4_callback_version[] = { [1] = &nfs4_callback_version1, + [4] = &nfs4_callback_version4, }; static struct svc_stat nfs4_callback_stats; diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index 07baa8254ca1407a6342e80bc3e545c34868161e..d4036be0b589ffd24c391b53bded40bc55a6ab5f 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h @@ -106,6 +106,19 @@ struct cb_sequenceres { extern unsigned nfs4_callback_sequence(struct cb_sequenceargs *args, struct cb_sequenceres *res); +extern int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, + const nfs4_stateid *stateid); + +#define RCA4_TYPE_MASK_RDATA_DLG 0 +#define RCA4_TYPE_MASK_WDATA_DLG 1 + +struct cb_recallanyargs { + struct sockaddr *craa_addr; + uint32_t craa_objs_to_keep; + uint32_t craa_type_mask; +}; + +extern unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy); #endif /* CONFIG_NFS_V4_1 */ extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res); @@ -114,8 +127,9 @@ extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy); #ifdef CONFIG_NFS_V4 extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt); extern void nfs_callback_down(int minorversion); +extern int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, + const nfs4_stateid *stateid); #endif /* CONFIG_NFS_V4 */ - /* * nfs41: Callbacks are expected to not cause substantial latency, * so we limit their concurrency to 1 by setting up the maximum number diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index b7da1f54da68e3334aded5549ef3811ff5253f7a..defa9b4c470ebf0515d3b7da58585c0ec551e3db 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c @@ -61,6 +61,16 @@ out: return res->status; } +static int (*nfs_validate_delegation_stateid(struct nfs_client *clp))(struct nfs_delegation *, const nfs4_stateid *) +{ +#if defined(CONFIG_NFS_V4_1) + if (clp->cl_minorversion > 0) + return nfs41_validate_delegation_stateid; +#endif + return nfs4_validate_delegation_stateid; +} + + __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) { struct nfs_client *clp; @@ -81,7 +91,8 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) inode = nfs_delegation_find_inode(clp, &args->fh); if (inode != NULL) { /* Set up a helper thread to actually return the delegation */ - switch(nfs_async_inode_return_delegation(inode, &args->stateid)) { + switch (nfs_async_inode_return_delegation(inode, &args->stateid, + nfs_validate_delegation_stateid(clp))) { case 0: res = 0; break; @@ -102,8 +113,31 @@ out: return res; } +int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid) +{ + if (delegation == NULL || memcmp(delegation->stateid.data, stateid->data, + sizeof(delegation->stateid.data)) != 0) + return 0; + return 1; +} + #if defined(CONFIG_NFS_V4_1) +int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid) +{ + if (delegation == NULL) + return 0; + + /* seqid is 4-bytes long */ + if (((u32 *) &stateid->data)[0] != 0) + return 0; + if (memcmp(&delegation->stateid.data[4], &stateid->data[4], + sizeof(stateid->data)-4)) + return 0; + + return 1; +} + /* * Validate the sequenceID sent by the server. * Return success if the sequenceID is one more than what we last saw on @@ -227,4 +261,32 @@ out: return res->csr_status; } +unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy) +{ + struct nfs_client *clp; + int status; + fmode_t flags = 0; + + status = htonl(NFS4ERR_OP_NOT_IN_SESSION); + clp = nfs_find_client(args->craa_addr, 4); + if (clp == NULL) + goto out; + + dprintk("NFS: RECALL_ANY callback request from %s\n", + rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); + + if (test_bit(RCA4_TYPE_MASK_RDATA_DLG, (const unsigned long *) + &args->craa_type_mask)) + flags = FMODE_READ; + if (test_bit(RCA4_TYPE_MASK_WDATA_DLG, (const unsigned long *) + &args->craa_type_mask)) + flags |= FMODE_WRITE; + + if (flags) + nfs_expire_all_delegation_types(clp, flags); + status = htonl(NFS4_OK); +out: + dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); + return status; +} #endif /* CONFIG_NFS_V4_1 */ diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index 76b0aa0f73bfca33ac620c6569cbe926f099f901..8e1a2511c8be5b00e35fae972ee62cc921ce2d15 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c @@ -23,6 +23,7 @@ #if defined(CONFIG_NFS_V4_1) #define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \ 4 + 1 + 3) +#define CB_OP_RECALLANY_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ) #endif /* CONFIG_NFS_V4_1 */ #define NFSDBG_FACILITY NFSDBG_CALLBACK @@ -326,6 +327,25 @@ out_free: goto out; } +static unsigned decode_recallany_args(struct svc_rqst *rqstp, + struct xdr_stream *xdr, + struct cb_recallanyargs *args) +{ + uint32_t *p; + + args->craa_addr = svc_addr(rqstp); + p = read_buf(xdr, 4); + if (unlikely(p == NULL)) + return htonl(NFS4ERR_BADXDR); + args->craa_objs_to_keep = ntohl(*p++); + p = read_buf(xdr, 4); + if (unlikely(p == NULL)) + return htonl(NFS4ERR_BADXDR); + args->craa_type_mask = ntohl(*p); + + return 0; +} + #endif /* CONFIG_NFS_V4_1 */ static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) @@ -533,6 +553,7 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op) case OP_CB_GETATTR: case OP_CB_RECALL: case OP_CB_SEQUENCE: + case OP_CB_RECALL_ANY: *op = &callback_ops[op_nr]; break; @@ -540,7 +561,6 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op) case OP_CB_NOTIFY_DEVICEID: case OP_CB_NOTIFY: case OP_CB_PUSH_DELEG: - case OP_CB_RECALL_ANY: case OP_CB_RECALLABLE_OBJ_AVAIL: case OP_CB_RECALL_SLOT: case OP_CB_WANTS_CANCELLED: @@ -688,6 +708,11 @@ static struct callback_op callback_ops[] = { .encode_res = (callback_encode_res_t)encode_cb_sequence_res, .res_maxsize = CB_OP_SEQUENCE_RES_MAXSZ, }, + [OP_CB_RECALL_ANY] = { + .process_op = (callback_process_op_t)nfs4_callback_recallany, + .decode_args = (callback_decode_arg_t)decode_recallany_args, + .res_maxsize = CB_OP_RECALLANY_RES_MAXSZ, + }, #endif /* CONFIG_NFS_V4_1 */ }; @@ -718,3 +743,10 @@ struct svc_version nfs4_callback_version1 = { .vs_dispatch = NULL, }; +struct svc_version nfs4_callback_version4 = { + .vs_vers = 4, + .vs_nproc = ARRAY_SIZE(nfs4_callback_procedures1), + .vs_proc = nfs4_callback_procedures1, + .vs_xdrsize = NFS4_CALLBACK_XDRSIZE, + .vs_dispatch = NULL, +}; diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 99ea196f071f04d81c82fbc42bdcb000b9f0694d..ee77713ce68b10e020b0589920560f87c6fffe11 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -1260,10 +1260,20 @@ error: static void nfs4_session_set_rwsize(struct nfs_server *server) { #ifdef CONFIG_NFS_V4_1 + struct nfs4_session *sess; + u32 server_resp_sz; + u32 server_rqst_sz; + if (!nfs4_has_session(server->nfs_client)) return; - server->rsize = server->nfs_client->cl_session->fc_attrs.max_resp_sz; - server->wsize = server->nfs_client->cl_session->fc_attrs.max_rqst_sz; + sess = server->nfs_client->cl_session; + server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead; + server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead; + + if (server->rsize > server_resp_sz) + server->rsize = server_resp_sz; + if (server->wsize > server_rqst_sz) + server->wsize = server_rqst_sz; #endif /* CONFIG_NFS_V4_1 */ } diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 6dd48a4405b46d409af629d4195b27b17e83dab1..2563bebc4c670915f73de93625411062a52f3582 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -92,7 +92,7 @@ out: return status; } -static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid) +static int nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid) { struct nfs_inode *nfsi = NFS_I(inode); struct nfs_open_context *ctx; @@ -116,10 +116,11 @@ again: err = nfs_delegation_claim_locks(ctx, state); put_nfs_open_context(ctx); if (err != 0) - return; + return err; goto again; } spin_unlock(&inode->i_lock); + return 0; } /* @@ -261,30 +262,34 @@ static void nfs_msync_inode(struct inode *inode) /* * Basic procedure for returning a delegation to the server */ -static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation) +static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) { struct nfs_inode *nfsi = NFS_I(inode); + int err; - nfs_msync_inode(inode); /* * Guard against new delegated open/lock/unlock calls and against * state recovery */ down_write(&nfsi->rwsem); - nfs_delegation_claim_opens(inode, &delegation->stateid); + err = nfs_delegation_claim_opens(inode, &delegation->stateid); up_write(&nfsi->rwsem); - nfs_msync_inode(inode); + if (err) + goto out; - return nfs_do_return_delegation(inode, delegation, 1); + err = nfs_do_return_delegation(inode, delegation, issync); +out: + return err; } /* * Return all delegations that have been marked for return */ -void nfs_client_return_marked_delegations(struct nfs_client *clp) +int nfs_client_return_marked_delegations(struct nfs_client *clp) { struct nfs_delegation *delegation; struct inode *inode; + int err = 0; restart: rcu_read_lock(); @@ -298,12 +303,18 @@ restart: delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL); spin_unlock(&clp->cl_lock); rcu_read_unlock(); - if (delegation != NULL) - __nfs_inode_return_delegation(inode, delegation); + if (delegation != NULL) { + filemap_flush(inode->i_mapping); + err = __nfs_inode_return_delegation(inode, delegation, 0); + } iput(inode); - goto restart; + if (!err) + goto restart; + set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); + return err; } rcu_read_unlock(); + return 0; } /* @@ -338,8 +349,10 @@ int nfs_inode_return_delegation(struct inode *inode) spin_lock(&clp->cl_lock); delegation = nfs_detach_delegation_locked(nfsi, NULL); spin_unlock(&clp->cl_lock); - if (delegation != NULL) - err = __nfs_inode_return_delegation(inode, delegation); + if (delegation != NULL) { + nfs_msync_inode(inode); + err = __nfs_inode_return_delegation(inode, delegation, 1); + } } return err; } @@ -368,33 +381,47 @@ void nfs_super_return_all_delegations(struct super_block *sb) spin_unlock(&delegation->lock); } rcu_read_unlock(); - nfs_client_return_marked_delegations(clp); + if (nfs_client_return_marked_delegations(clp) != 0) + nfs4_schedule_state_manager(clp); } -static void nfs_client_mark_return_all_delegations(struct nfs_client *clp) +static +void nfs_client_mark_return_all_delegation_types(struct nfs_client *clp, fmode_t flags) { struct nfs_delegation *delegation; rcu_read_lock(); list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) { - set_bit(NFS_DELEGATION_RETURN, &delegation->flags); - set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); + if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE)) + continue; + if (delegation->type & flags) + nfs_mark_return_delegation(clp, delegation); } rcu_read_unlock(); } +static void nfs_client_mark_return_all_delegations(struct nfs_client *clp) +{ + nfs_client_mark_return_all_delegation_types(clp, FMODE_READ|FMODE_WRITE); +} + static void nfs_delegation_run_state_manager(struct nfs_client *clp) { if (test_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) nfs4_schedule_state_manager(clp); } -void nfs_expire_all_delegations(struct nfs_client *clp) +void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags) { - nfs_client_mark_return_all_delegations(clp); + nfs_client_mark_return_all_delegation_types(clp, flags); nfs_delegation_run_state_manager(clp); } +void nfs_expire_all_delegations(struct nfs_client *clp) +{ + nfs_expire_all_delegation_types(clp, FMODE_READ|FMODE_WRITE); +} + /* * Return all delegations following an NFS4ERR_CB_PATH_DOWN error. */ @@ -413,8 +440,7 @@ static void nfs_client_mark_return_unreferenced_delegations(struct nfs_client *c list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) { if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags)) continue; - set_bit(NFS_DELEGATION_RETURN, &delegation->flags); - set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); + nfs_mark_return_delegation(clp, delegation); } rcu_read_unlock(); } @@ -428,18 +454,21 @@ void nfs_expire_unreferenced_delegations(struct nfs_client *clp) /* * Asynchronous delegation recall! */ -int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid) +int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid, + int (*validate_stateid)(struct nfs_delegation *delegation, + const nfs4_stateid *stateid)) { struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; struct nfs_delegation *delegation; rcu_read_lock(); delegation = rcu_dereference(NFS_I(inode)->delegation); - if (delegation == NULL || memcmp(delegation->stateid.data, stateid->data, - sizeof(delegation->stateid.data)) != 0) { + + if (!validate_stateid(delegation, stateid)) { rcu_read_unlock(); return -ENOENT; } + nfs_mark_return_delegation(clp, delegation); rcu_read_unlock(); nfs_delegation_run_state_manager(clp); diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 09f383795174d065f36a413a6f698b467a93c57c..944b627ec6e1a956340ee8c0464b5510b185b336 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h @@ -34,15 +34,18 @@ enum { int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); int nfs_inode_return_delegation(struct inode *inode); -int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid); +int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid, + int (*validate_stateid)(struct nfs_delegation *delegation, + const nfs4_stateid *stateid)); void nfs_inode_return_delegation_noreclaim(struct inode *inode); struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle); void nfs_super_return_all_delegations(struct super_block *sb); void nfs_expire_all_delegations(struct nfs_client *clp); +void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags); void nfs_expire_unreferenced_delegations(struct nfs_client *clp); void nfs_handle_cb_pathdown(struct nfs_client *clp); -void nfs_client_return_marked_delegations(struct nfs_client *clp); +int nfs_client_return_marked_delegations(struct nfs_client *clp); void nfs_delegation_mark_reclaim(struct nfs_client *clp); void nfs_delegation_reap_unclaimed(struct nfs_client *clp); diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 7cb298525eefd1a5ebcac1870ce08679447a3f2e..2c5ace4f00a7ffecfcf41c21e512833ef70d426b 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1579,55 +1579,46 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct dentry *dentry = NULL, *rehash = NULL; int error = -EBUSY; - /* - * To prevent any new references to the target during the rename, - * we unhash the dentry and free the inode in advance. - */ - if (!d_unhashed(new_dentry)) { - d_drop(new_dentry); - rehash = new_dentry; - } - dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n", old_dentry->d_parent->d_name.name, old_dentry->d_name.name, new_dentry->d_parent->d_name.name, new_dentry->d_name.name, atomic_read(&new_dentry->d_count)); /* - * First check whether the target is busy ... we can't - * safely do _any_ rename if the target is in use. - * - * For files, make a copy of the dentry and then do a - * silly-rename. If the silly-rename succeeds, the - * copied dentry is hashed and becomes the new target. + * For non-directories, check whether the target is busy and if so, + * make a copy of the dentry and then do a silly-rename. If the + * silly-rename succeeds, the copied dentry is hashed and becomes + * the new target. */ - if (!new_inode) - goto go_ahead; - if (S_ISDIR(new_inode->i_mode)) { - error = -EISDIR; - if (!S_ISDIR(old_inode->i_mode)) - goto out; - } else if (atomic_read(&new_dentry->d_count) > 2) { - int err; - /* copy the target dentry's name */ - dentry = d_alloc(new_dentry->d_parent, - &new_dentry->d_name); - if (!dentry) - goto out; + if (new_inode && !S_ISDIR(new_inode->i_mode)) { + /* + * To prevent any new references to the target during the + * rename, we unhash the dentry in advance. + */ + if (!d_unhashed(new_dentry)) { + d_drop(new_dentry); + rehash = new_dentry; + } + + if (atomic_read(&new_dentry->d_count) > 2) { + int err; + + /* copy the target dentry's name */ + dentry = d_alloc(new_dentry->d_parent, + &new_dentry->d_name); + if (!dentry) + goto out; - /* silly-rename the existing target ... */ - err = nfs_sillyrename(new_dir, new_dentry); - if (!err) { - new_dentry = rehash = dentry; + /* silly-rename the existing target ... */ + err = nfs_sillyrename(new_dir, new_dentry); + if (err) + goto out; + + new_dentry = dentry; new_inode = NULL; - /* instantiate the replacement target */ - d_instantiate(new_dentry, NULL); - } else if (atomic_read(&new_dentry->d_count) > 1) - /* dentry still busy? */ - goto out; + } } -go_ahead: /* * ... prune child dentries and writebacks if needed. */ diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index f4d54ba97cc62653ffceedf568f4d4c987840682..95e1ca765d4757085117e8c401fbcb09046ecea5 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c @@ -146,7 +146,7 @@ static int nfs_dns_show(struct seq_file *m, struct cache_detail *cd, return 0; } -struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd, +static struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd, struct nfs_dns_ent *key) { struct cache_head *ch; @@ -159,7 +159,7 @@ struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd, return container_of(ch, struct nfs_dns_ent, h); } -struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd, +static struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd, struct nfs_dns_ent *new, struct nfs_dns_ent *key) { diff --git a/fs/nfs/file.c b/fs/nfs/file.c index f5fdd39e037a49ea5073aa32d19a5cb884d64a76..6b891328f332cfcf73e1e965a0e4b3912c56dce1 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -581,7 +581,7 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode) { struct nfs_open_context *ctx; - if (IS_SYNC(inode) || (filp->f_flags & O_SYNC)) + if (IS_SYNC(inode) || (filp->f_flags & O_DSYNC)) return 1; ctx = nfs_file_open_context(filp); if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) @@ -622,7 +622,7 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count); result = generic_file_aio_write(iocb, iov, nr_segs, pos); - /* Return error values for O_SYNC and IS_SYNC() */ + /* Return error values for O_DSYNC and IS_SYNC() */ if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode); if (err < 0) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index e21b1bb9972f893270c9090c31ffd110cc31ae43..29e464d23b32fe4107aea88394d0c734e02c10df 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -30,6 +30,15 @@ static inline int nfs4_has_session(const struct nfs_client *clp) return 0; } +static inline int nfs4_has_persistent_session(const struct nfs_client *clp) +{ +#ifdef CONFIG_NFS_V4_1 + if (nfs4_has_session(clp)) + return (clp->cl_session->flags & SESSION4_PERSIST); +#endif /* CONFIG_NFS_V4_1 */ + return 0; +} + struct nfs_clone_mount { const struct super_block *sb; const struct dentry *dentry; @@ -156,6 +165,7 @@ struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentr /* callback_xdr.c */ extern struct svc_version nfs4_callback_version1; +extern struct svc_version nfs4_callback_version4; /* pagelist.c */ extern int __init nfs_init_nfspagecache(void); @@ -177,24 +187,14 @@ extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int); extern struct rpc_procinfo nfs3_procedures[]; extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int); -/* nfs4proc.c */ -static inline void nfs4_restart_rpc(struct rpc_task *task, - const struct nfs_client *clp) -{ -#ifdef CONFIG_NFS_V4_1 - if (nfs4_has_session(clp) && - test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) { - rpc_restart_call_prepare(task); - return; - } -#endif /* CONFIG_NFS_V4_1 */ - rpc_restart_call(task); -} - /* nfs4xdr.c */ #ifdef CONFIG_NFS_V4 extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus); #endif +#ifdef CONFIG_NFS_V4_1 +extern const u32 nfs41_maxread_overhead; +extern const u32 nfs41_maxwrite_overhead; +#endif /* nfs4proc.c */ #ifdef CONFIG_NFS_V4 @@ -273,20 +273,6 @@ extern int _nfs4_call_sync_session(struct nfs_server *server, struct nfs4_sequence_res *res, int cache_reply); -#ifdef CONFIG_NFS_V4_1 -extern void nfs41_sequence_free_slot(const struct nfs_client *, - struct nfs4_sequence_res *res); -#endif /* CONFIG_NFS_V4_1 */ - -static inline void nfs4_sequence_free_slot(const struct nfs_client *clp, - struct nfs4_sequence_res *res) -{ -#ifdef CONFIG_NFS_V4_1 - if (nfs4_has_session(clp)) - nfs41_sequence_free_slot(clp, res); -#endif /* CONFIG_NFS_V4_1 */ -} - /* * Determine the device name as a string */ @@ -380,3 +366,15 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len) return ((unsigned long)len + (unsigned long)base + PAGE_SIZE - 1) >> PAGE_SHIFT; } + +/* + * Helper for restarting RPC calls in the possible presence of NFSv4.1 + * sessions. + */ +static inline void nfs_restart_rpc(struct rpc_task *task, const struct nfs_client *clp) +{ + if (nfs4_has_session(clp)) + rpc_restart_call_prepare(task); + else + rpc_restart_call(task); +} diff --git a/fs/nfs/iostat.h b/fs/nfs/iostat.h index ceda50aad73cc5a3bc93baeaaa7771ebd7a0f00f..46d779abafd356e3344ef79c151466dfc863fed5 100644 --- a/fs/nfs/iostat.h +++ b/fs/nfs/iostat.h @@ -25,13 +25,7 @@ struct nfs_iostats { static inline void nfs_inc_server_stats(const struct nfs_server *server, enum nfs_stat_eventcounters stat) { - struct nfs_iostats *iostats; - int cpu; - - cpu = get_cpu(); - iostats = per_cpu_ptr(server->io_stats, cpu); - iostats->events[stat]++; - put_cpu(); + this_cpu_inc(server->io_stats->events[stat]); } static inline void nfs_inc_stats(const struct inode *inode, @@ -44,13 +38,7 @@ static inline void nfs_add_server_stats(const struct nfs_server *server, enum nfs_stat_bytecounters stat, unsigned long addend) { - struct nfs_iostats *iostats; - int cpu; - - cpu = get_cpu(); - iostats = per_cpu_ptr(server->io_stats, cpu); - iostats->bytes[stat] += addend; - put_cpu(); + this_cpu_add(server->io_stats->bytes[stat], addend); } static inline void nfs_add_stats(const struct inode *inode, @@ -65,13 +53,7 @@ static inline void nfs_add_fscache_stats(struct inode *inode, enum nfs_stat_fscachecounters stat, unsigned long addend) { - struct nfs_iostats *iostats; - int cpu; - - cpu = get_cpu(); - iostats = per_cpu_ptr(NFS_SERVER(inode)->io_stats, cpu); - iostats->fscache[stat] += addend; - put_cpu(); + this_cpu_add(NFS_SERVER(inode)->io_stats->fscache[stat], addend); } #endif diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 6ea07a3c75d4942f6197e54791b7504502d3f54c..7e57b04e40141f5971dfabd63f848d07cc7ceeb2 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -44,7 +44,8 @@ enum nfs4_client_state { NFS4CLNT_RECLAIM_REBOOT, NFS4CLNT_RECLAIM_NOGRACE, NFS4CLNT_DELEGRETURN, - NFS4CLNT_SESSION_SETUP, + NFS4CLNT_SESSION_RESET, + NFS4CLNT_SESSION_DRAINING, }; /* @@ -180,6 +181,7 @@ struct nfs4_state_recovery_ops { int (*recover_lock)(struct nfs4_state *, struct file_lock *); int (*establish_clid)(struct nfs_client *, struct rpc_cred *); struct rpc_cred * (*get_clid_cred)(struct nfs_client *); + int (*reclaim_complete)(struct nfs_client *); }; struct nfs4_state_maintenance_ops { @@ -200,9 +202,11 @@ extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t); /* nfs4proc.c */ extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *); extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *); +extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred); extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *); extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *); extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *); +extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); extern int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait); extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); @@ -218,9 +222,11 @@ extern int nfs4_setup_sequence(struct nfs_client *clp, int cache_reply, struct rpc_task *task); extern void nfs4_destroy_session(struct nfs4_session *session); extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); -extern int nfs4_proc_create_session(struct nfs_client *, int reset); +extern int nfs4_proc_create_session(struct nfs_client *); extern int nfs4_proc_destroy_session(struct nfs4_session *); extern int nfs4_init_session(struct nfs_server *server); +extern int nfs4_proc_get_lease_time(struct nfs_client *clp, + struct nfs_fsinfo *fsinfo); #else /* CONFIG_NFS_v4_1 */ static inline int nfs4_setup_sequence(struct nfs_client *clp, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, @@ -267,6 +273,7 @@ extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); extern void nfs4_schedule_state_recovery(struct nfs_client *); extern void nfs4_schedule_state_manager(struct nfs_client *); extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state); +extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); @@ -287,6 +294,7 @@ struct nfs4_mount_data; /* callback_xdr.c */ extern struct svc_version nfs4_callback_version1; +extern struct svc_version nfs4_callback_version4; #else diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 741a562177fc3f587dcd1e1019f3cfe53c367de8..9f5f11ecfd93853ac3e18fe5b19a95f4b24d8645 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -270,11 +270,18 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, case -NFS4ERR_SEQ_MISORDERED: dprintk("%s ERROR: %d Reset session\n", __func__, errorcode); - set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); + nfs4_schedule_state_recovery(clp); exception->retry = 1; - /* FALLTHROUGH */ + break; #endif /* !defined(CONFIG_NFS_V4_1) */ case -NFS4ERR_FILE_OPEN: + if (exception->timeout > HZ) { + /* We have retried a decent amount, time to + * fail + */ + ret = -EBUSY; + break; + } case -NFS4ERR_GRACE: case -NFS4ERR_DELAY: ret = nfs4_delay(server->client, &exception->timeout); @@ -311,48 +318,54 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp * so we need to scan down from highest_used_slotid to 0 looking for the now * highest slotid in use. * If none found, highest_used_slotid is set to -1. + * + * Must be called while holding tbl->slot_tbl_lock */ static void nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid) { int slotid = free_slotid; - spin_lock(&tbl->slot_tbl_lock); /* clear used bit in bitmap */ __clear_bit(slotid, tbl->used_slots); /* update highest_used_slotid when it is freed */ if (slotid == tbl->highest_used_slotid) { slotid = find_last_bit(tbl->used_slots, tbl->max_slots); - if (slotid >= 0 && slotid < tbl->max_slots) + if (slotid < tbl->max_slots) tbl->highest_used_slotid = slotid; else tbl->highest_used_slotid = -1; } - rpc_wake_up_next(&tbl->slot_tbl_waitq); - spin_unlock(&tbl->slot_tbl_lock); dprintk("%s: free_slotid %u highest_used_slotid %d\n", __func__, free_slotid, tbl->highest_used_slotid); } -void nfs41_sequence_free_slot(const struct nfs_client *clp, +static void nfs41_sequence_free_slot(const struct nfs_client *clp, struct nfs4_sequence_res *res) { struct nfs4_slot_table *tbl; - if (!nfs4_has_session(clp)) { - dprintk("%s: No session\n", __func__); - return; - } tbl = &clp->cl_session->fc_slot_table; if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) { - dprintk("%s: No slot\n", __func__); /* just wake up the next guy waiting since * we may have not consumed a slot after all */ - rpc_wake_up_next(&tbl->slot_tbl_waitq); + dprintk("%s: No slot\n", __func__); return; } + + spin_lock(&tbl->slot_tbl_lock); nfs4_free_slot(tbl, res->sr_slotid); + + /* Signal state manager thread if session is drained */ + if (test_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state)) { + if (tbl->highest_used_slotid == -1) { + dprintk("%s COMPLETE: Session Drained\n", __func__); + complete(&clp->cl_session->complete); + } + } else + rpc_wake_up_next(&tbl->slot_tbl_waitq); + spin_unlock(&tbl->slot_tbl_lock); res->sr_slotid = NFS4_MAX_SLOT_TABLE; } @@ -377,10 +390,10 @@ static void nfs41_sequence_done(struct nfs_client *clp, if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) goto out; - tbl = &clp->cl_session->fc_slot_table; - slot = tbl->slots + res->sr_slotid; - + /* Check the SEQUENCE operation status */ if (res->sr_status == 0) { + tbl = &clp->cl_session->fc_slot_table; + slot = tbl->slots + res->sr_slotid; /* Update the slot's sequence and clientid lease timer */ ++slot->seq_nr; timestamp = res->sr_renewal_time; @@ -388,7 +401,8 @@ static void nfs41_sequence_done(struct nfs_client *clp, if (time_before(clp->cl_last_renewal, timestamp)) clp->cl_last_renewal = timestamp; spin_unlock(&clp->cl_lock); - return; + /* Check sequence flags */ + nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); } out: /* The session may be reset by one of the error handlers. */ @@ -429,24 +443,6 @@ out: return ret_id; } -static int nfs4_recover_session(struct nfs4_session *session) -{ - struct nfs_client *clp = session->clp; - unsigned int loop; - int ret; - - for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) { - ret = nfs4_wait_clnt_recover(clp); - if (ret != 0) - break; - if (!test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) - break; - nfs4_schedule_state_manager(clp); - ret = -EIO; - } - return ret; -} - static int nfs41_setup_sequence(struct nfs4_session *session, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, @@ -455,7 +451,6 @@ static int nfs41_setup_sequence(struct nfs4_session *session, { struct nfs4_slot *slot; struct nfs4_slot_table *tbl; - int status = 0; u8 slotid; dprintk("--> %s\n", __func__); @@ -468,21 +463,15 @@ static int nfs41_setup_sequence(struct nfs4_session *session, tbl = &session->fc_slot_table; spin_lock(&tbl->slot_tbl_lock); - if (test_bit(NFS4CLNT_SESSION_SETUP, &session->clp->cl_state)) { - if (tbl->highest_used_slotid != -1) { - rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); - spin_unlock(&tbl->slot_tbl_lock); - dprintk("<-- %s: Session reset: draining\n", __func__); - return -EAGAIN; - } - - /* The slot table is empty; start the reset thread */ - dprintk("%s Session Reset\n", __func__); + if (test_bit(NFS4CLNT_SESSION_DRAINING, &session->clp->cl_state)) { + /* + * The state manager will wait until the slot table is empty. + * Schedule the reset thread + */ + rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); spin_unlock(&tbl->slot_tbl_lock); - status = nfs4_recover_session(session); - if (status) - return status; - spin_lock(&tbl->slot_tbl_lock); + dprintk("%s Schedule Session Reset\n", __func__); + return -EAGAIN; } slotid = nfs4_find_slot(tbl, task); @@ -527,7 +516,7 @@ int nfs4_setup_sequence(struct nfs_client *clp, goto out; ret = nfs41_setup_sequence(clp->cl_session, args, res, cache_reply, task); - if (ret != -EAGAIN) { + if (ret && ret != -EAGAIN) { /* terminate rpc task */ task->tk_status = ret; task->tk_action = NULL; @@ -561,7 +550,6 @@ static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) struct nfs41_call_sync_data *data = calldata; nfs41_sequence_done(data->clp, data->seq_res, task->tk_status); - nfs41_sequence_free_slot(data->clp, data->seq_res); } struct rpc_call_ops nfs41_call_sync_ops = { @@ -637,15 +625,6 @@ static void nfs4_sequence_done(const struct nfs_server *server, #endif /* CONFIG_NFS_V4_1 */ } -/* no restart, therefore free slot here */ -static void nfs4_sequence_done_free_slot(const struct nfs_server *server, - struct nfs4_sequence_res *res, - int rpc_status) -{ - nfs4_sequence_done(server, res, rpc_status); - nfs4_sequence_free_slot(server->nfs_client, res); -} - static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) { struct nfs_inode *nfsi = NFS_I(dir); @@ -720,9 +699,15 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path, p->o_arg.bitmask = server->attr_bitmask; p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; if (flags & O_EXCL) { - u32 *s = (u32 *) p->o_arg.u.verifier.data; - s[0] = jiffies; - s[1] = current->pid; + if (nfs4_has_persistent_session(server->nfs_client)) { + /* GUARDED */ + p->o_arg.u.attrs = &p->attrs; + memcpy(&p->attrs, attrs, sizeof(p->attrs)); + } else { /* EXCLUSIVE4_1 */ + u32 *s = (u32 *) p->o_arg.u.verifier.data; + s[0] = jiffies; + s[1] = current->pid; + } } else if (flags & O_CREAT) { p->o_arg.u.attrs = &p->attrs; memcpy(&p->attrs, attrs, sizeof(p->attrs)); @@ -776,13 +761,16 @@ static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode goto out; switch (mode & (FMODE_READ|FMODE_WRITE)) { case FMODE_READ: - ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0; + ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0 + && state->n_rdonly != 0; break; case FMODE_WRITE: - ret |= test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0; + ret |= test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0 + && state->n_wronly != 0; break; case FMODE_READ|FMODE_WRITE: - ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0; + ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0 + && state->n_rdwr != 0; } out: return ret; @@ -1183,6 +1171,14 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state case -ENOENT: case -ESTALE: goto out; + case -NFS4ERR_BADSESSION: + case -NFS4ERR_BADSLOT: + case -NFS4ERR_BAD_HIGH_SLOT: + case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: + case -NFS4ERR_DEADSESSION: + nfs4_schedule_state_recovery( + server->nfs_client); + goto out; case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_STALE_STATEID: case -NFS4ERR_EXPIRED: @@ -1336,8 +1332,8 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata) data->rpc_status = task->tk_status; - nfs4_sequence_done_free_slot(data->o_arg.server, &data->o_res.seq_res, - task->tk_status); + nfs4_sequence_done(data->o_arg.server, &data->o_res.seq_res, + task->tk_status); if (RPC_ASSASSINATED(task)) return; @@ -1488,7 +1484,7 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s return ret; } -static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state) +static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state) { struct nfs_server *server = NFS_SERVER(state->inode); struct nfs4_exception exception = { }; @@ -1496,10 +1492,16 @@ static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4 do { err = _nfs4_open_expired(ctx, state); - if (err != -NFS4ERR_DELAY) - break; - nfs4_handle_exception(server, err, &exception); + switch (err) { + default: + goto out; + case -NFS4ERR_GRACE: + case -NFS4ERR_DELAY: + nfs4_handle_exception(server, err, &exception); + err = 0; + } } while (exception.retry); +out: return err; } @@ -1712,6 +1714,18 @@ static void nfs4_free_closedata(void *data) kfree(calldata); } +static void nfs4_close_clear_stateid_flags(struct nfs4_state *state, + fmode_t fmode) +{ + spin_lock(&state->owner->so_lock); + if (!(fmode & FMODE_READ)) + clear_bit(NFS_O_RDONLY_STATE, &state->flags); + if (!(fmode & FMODE_WRITE)) + clear_bit(NFS_O_WRONLY_STATE, &state->flags); + clear_bit(NFS_O_RDWR_STATE, &state->flags); + spin_unlock(&state->owner->so_lock); +} + static void nfs4_close_done(struct rpc_task *task, void *data) { struct nfs4_closedata *calldata = data; @@ -1728,6 +1742,8 @@ static void nfs4_close_done(struct rpc_task *task, void *data) case 0: nfs_set_open_stateid(state, &calldata->res.stateid, 0); renew_lease(server, calldata->timestamp); + nfs4_close_clear_stateid_flags(state, + calldata->arg.fmode); break; case -NFS4ERR_STALE_STATEID: case -NFS4ERR_OLD_STATEID: @@ -1737,11 +1753,10 @@ static void nfs4_close_done(struct rpc_task *task, void *data) break; default: if (nfs4_async_handle_error(task, server, state) == -EAGAIN) { - nfs4_restart_rpc(task, server->nfs_client); + nfs_restart_rpc(task, server->nfs_client); return; } } - nfs4_sequence_free_slot(server->nfs_client, &calldata->res.seq_res); nfs_refresh_inode(calldata->inode, calldata->res.fattr); } @@ -1749,38 +1764,39 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) { struct nfs4_closedata *calldata = data; struct nfs4_state *state = calldata->state; - int clear_rd, clear_wr, clear_rdwr; + int call_close = 0; if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) return; - clear_rd = clear_wr = clear_rdwr = 0; + task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; + calldata->arg.fmode = FMODE_READ|FMODE_WRITE; spin_lock(&state->owner->so_lock); /* Calculate the change in open mode */ if (state->n_rdwr == 0) { if (state->n_rdonly == 0) { - clear_rd |= test_and_clear_bit(NFS_O_RDONLY_STATE, &state->flags); - clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags); + call_close |= test_bit(NFS_O_RDONLY_STATE, &state->flags); + call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags); + calldata->arg.fmode &= ~FMODE_READ; } if (state->n_wronly == 0) { - clear_wr |= test_and_clear_bit(NFS_O_WRONLY_STATE, &state->flags); - clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags); + call_close |= test_bit(NFS_O_WRONLY_STATE, &state->flags); + call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags); + calldata->arg.fmode &= ~FMODE_WRITE; } } spin_unlock(&state->owner->so_lock); - if (!clear_rd && !clear_wr && !clear_rdwr) { + + if (!call_close) { /* Note: exit _without_ calling nfs4_close_done */ task->tk_action = NULL; return; } + + if (calldata->arg.fmode == 0) + task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE]; + nfs_fattr_init(calldata->res.fattr); - if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0) { - task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; - calldata->arg.fmode = FMODE_READ; - } else if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0) { - task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; - calldata->arg.fmode = FMODE_WRITE; - } calldata->timestamp = jiffies; if (nfs4_setup_sequence((NFS_SERVER(calldata->inode))->nfs_client, &calldata->arg.seq_args, &calldata->res.seq_res, @@ -1981,7 +1997,7 @@ out_drop: return 0; } -void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) +static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) { if (ctx->state == NULL) return; @@ -2532,7 +2548,6 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) nfs4_sequence_done(res->server, &res->seq_res, task->tk_status); if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) return 0; - nfs4_sequence_free_slot(res->server->nfs_client, &res->seq_res); update_changeattr(dir, &res->cinfo); nfs_post_op_update_inode(dir, &res->dir_attr); return 1; @@ -2971,11 +2986,10 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) dprintk("--> %s\n", __func__); - /* nfs4_sequence_free_slot called in the read rpc_call_done */ nfs4_sequence_done(server, &data->res.seq_res, task->tk_status); if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { - nfs4_restart_rpc(task, server->nfs_client); + nfs_restart_rpc(task, server->nfs_client); return -EAGAIN; } @@ -2995,12 +3009,11 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) { struct inode *inode = data->inode; - /* slot is freed in nfs_writeback_done */ nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res, task->tk_status); if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { - nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client); + nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); return -EAGAIN; } if (task->tk_status >= 0) { @@ -3028,11 +3041,9 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res, task->tk_status); if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { - nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client); + nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); return -EAGAIN; } - nfs4_sequence_free_slot(NFS_SERVER(inode)->nfs_client, - &data->res.seq_res); nfs_refresh_inode(inode, data->res.fattr); return 0; } @@ -3350,7 +3361,7 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, case -NFS4ERR_SEQ_MISORDERED: dprintk("%s ERROR %d, Reset session\n", __func__, task->tk_status); - set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); + nfs4_schedule_state_recovery(clp); task->tk_status = 0; return -EAGAIN; #endif /* CONFIG_NFS_V4_1 */ @@ -3483,12 +3494,23 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) { struct nfs4_delegreturndata *data = calldata; - nfs4_sequence_done_free_slot(data->res.server, &data->res.seq_res, - task->tk_status); + nfs4_sequence_done(data->res.server, &data->res.seq_res, + task->tk_status); - data->rpc_status = task->tk_status; - if (data->rpc_status == 0) + switch (task->tk_status) { + case -NFS4ERR_STALE_STATEID: + case -NFS4ERR_EXPIRED: + case 0: renew_lease(data->res.server, data->timestamp); + break; + default: + if (nfs4_async_handle_error(task, data->res.server, NULL) == + -EAGAIN) { + nfs_restart_rpc(task, data->res.server->nfs_client); + return; + } + } + data->rpc_status = task->tk_status; } static void nfs4_delegreturn_release(void *calldata) @@ -3741,11 +3763,9 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) break; default: if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) - nfs4_restart_rpc(task, - calldata->server->nfs_client); + nfs_restart_rpc(task, + calldata->server->nfs_client); } - nfs4_sequence_free_slot(calldata->server->nfs_client, - &calldata->res.seq_res); } static void nfs4_locku_prepare(struct rpc_task *task, void *data) @@ -3927,8 +3947,8 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata) dprintk("%s: begin!\n", __func__); - nfs4_sequence_done_free_slot(data->server, &data->res.seq_res, - task->tk_status); + nfs4_sequence_done(data->server, &data->res.seq_res, + task->tk_status); data->rpc_status = task->tk_status; if (RPC_ASSASSINATED(task)) @@ -4049,10 +4069,16 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) return 0; err = _nfs4_do_setlk(state, F_SETLK, request, 0); - if (err != -NFS4ERR_DELAY) - break; - nfs4_handle_exception(server, err, &exception); + switch (err) { + default: + goto out; + case -NFS4ERR_GRACE: + case -NFS4ERR_DELAY: + nfs4_handle_exception(server, err, &exception); + err = 0; + } } while (exception.retry); +out: return err; } @@ -4172,6 +4198,11 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) case -NFS4ERR_EXPIRED: case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_STALE_STATEID: + case -NFS4ERR_BADSESSION: + case -NFS4ERR_BADSLOT: + case -NFS4ERR_BAD_HIGH_SLOT: + case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: + case -NFS4ERR_DEADSESSION: nfs4_schedule_state_recovery(server->nfs_client); goto out; case -ERESTARTSYS: @@ -4296,7 +4327,7 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, * NFS4ERR_BADSESSION in the sequence operation, and will therefore * be in some phase of session reset. */ -static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) +int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) { nfs4_verifier verifier; struct nfs41_exchange_id_args args = { @@ -4318,6 +4349,9 @@ static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) dprintk("--> %s\n", __func__); BUG_ON(clp == NULL); + /* Remove server-only flags */ + args.flags &= ~EXCHGID4_FLAG_CONFIRMED_R; + p = (u32 *)verifier.data; *p++ = htonl((u32)clp->cl_boot_time.tv_sec); *p = htonl((u32)clp->cl_boot_time.tv_nsec); @@ -4389,10 +4423,9 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata) dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); rpc_delay(task, NFS4_POLL_RETRY_MIN); task->tk_status = 0; - nfs4_restart_rpc(task, data->clp); + nfs_restart_rpc(task, data->clp); return; } - nfs41_sequence_free_slot(data->clp, &data->res->lr_seq_res); dprintk("<-- %s\n", __func__); } @@ -4465,7 +4498,6 @@ static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, int max_slots, spin_lock(&tbl->slot_tbl_lock); for (i = 0; i < max_slots; ++i) tbl->slots[i].seq_nr = ivalue; - tbl->highest_used_slotid = -1; spin_unlock(&tbl->slot_tbl_lock); dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, tbl, tbl->slots, tbl->max_slots); @@ -4515,7 +4547,6 @@ static void nfs4_destroy_slot_tables(struct nfs4_session *session) static int nfs4_init_slot_table(struct nfs4_slot_table *tbl, int max_slots, int ivalue) { - int i; struct nfs4_slot *slot; int ret = -ENOMEM; @@ -4526,18 +4557,9 @@ static int nfs4_init_slot_table(struct nfs4_slot_table *tbl, slot = kcalloc(max_slots, sizeof(struct nfs4_slot), GFP_KERNEL); if (!slot) goto out; - for (i = 0; i < max_slots; ++i) - slot[i].seq_nr = ivalue; ret = 0; spin_lock(&tbl->slot_tbl_lock); - if (tbl->slots != NULL) { - spin_unlock(&tbl->slot_tbl_lock); - dprintk("%s: slot table already initialized. tbl=%p slots=%p\n", - __func__, tbl, tbl->slots); - WARN_ON(1); - goto out_free; - } tbl->max_slots = max_slots; tbl->slots = slot; tbl->highest_used_slotid = -1; /* no slot is currently used */ @@ -4547,10 +4569,6 @@ static int nfs4_init_slot_table(struct nfs4_slot_table *tbl, out: dprintk("<-- %s: return %d\n", __func__, ret); return ret; - -out_free: - kfree(slot); - goto out; } /* @@ -4558,17 +4576,24 @@ out_free: */ static int nfs4_init_slot_tables(struct nfs4_session *session) { - int status; + struct nfs4_slot_table *tbl; + int status = 0; - status = nfs4_init_slot_table(&session->fc_slot_table, - session->fc_attrs.max_reqs, 1); - if (status) - return status; + tbl = &session->fc_slot_table; + if (tbl->slots == NULL) { + status = nfs4_init_slot_table(tbl, + session->fc_attrs.max_reqs, 1); + if (status) + return status; + } - status = nfs4_init_slot_table(&session->bc_slot_table, - session->bc_attrs.max_reqs, 0); - if (status) - nfs4_destroy_slot_tables(session); + tbl = &session->bc_slot_table; + if (tbl->slots == NULL) { + status = nfs4_init_slot_table(tbl, + session->bc_attrs.max_reqs, 0); + if (status) + nfs4_destroy_slot_tables(session); + } return status; } @@ -4582,7 +4607,6 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) if (!session) return NULL; - set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); /* * The create session reply races with the server back * channel probe. Mark the client NFS_CS_SESSION_INITING @@ -4590,12 +4614,15 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) * nfs_client struct */ clp->cl_cons_state = NFS_CS_SESSION_INITING; + init_completion(&session->complete); tbl = &session->fc_slot_table; + tbl->highest_used_slotid = -1; spin_lock_init(&tbl->slot_tbl_lock); rpc_init_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); tbl = &session->bc_slot_table; + tbl->highest_used_slotid = -1; spin_lock_init(&tbl->slot_tbl_lock); rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); @@ -4747,11 +4774,10 @@ static int _nfs4_proc_create_session(struct nfs_client *clp) * It is the responsibility of the caller to verify the session is * expired before calling this routine. */ -int nfs4_proc_create_session(struct nfs_client *clp, int reset) +int nfs4_proc_create_session(struct nfs_client *clp) { int status; unsigned *ptr; - struct nfs_fsinfo fsinfo; struct nfs4_session *session = clp->cl_session; dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); @@ -4760,35 +4786,19 @@ int nfs4_proc_create_session(struct nfs_client *clp, int reset) if (status) goto out; - /* Init or reset the fore channel */ - if (reset) - status = nfs4_reset_slot_tables(session); - else - status = nfs4_init_slot_tables(session); - dprintk("fore channel slot table initialization returned %d\n", status); + /* Init and reset the fore channel */ + status = nfs4_init_slot_tables(session); + dprintk("slot table initialization returned %d\n", status); + if (status) + goto out; + status = nfs4_reset_slot_tables(session); + dprintk("slot table reset returned %d\n", status); if (status) goto out; ptr = (unsigned *)&session->sess_id.data[0]; dprintk("%s client>seqid %d sessionid %u:%u:%u:%u\n", __func__, clp->cl_seqid, ptr[0], ptr[1], ptr[2], ptr[3]); - - if (reset) - /* Lease time is aleady set */ - goto out; - - /* Get the lease time */ - status = nfs4_proc_get_lease_time(clp, &fsinfo); - if (status == 0) { - /* Update lease time and schedule renewal */ - spin_lock(&clp->cl_lock); - clp->cl_lease_time = fsinfo.lease_time * HZ; - clp->cl_last_renewal = jiffies; - clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); - spin_unlock(&clp->cl_lock); - - nfs4_schedule_state_renewal(clp); - } out: dprintk("<-- %s\n", __func__); return status; @@ -4827,13 +4837,16 @@ int nfs4_proc_destroy_session(struct nfs4_session *session) int nfs4_init_session(struct nfs_server *server) { struct nfs_client *clp = server->nfs_client; + struct nfs4_session *session; int ret; if (!nfs4_has_session(clp)) return 0; - clp->cl_session->fc_attrs.max_rqst_sz = server->wsize; - clp->cl_session->fc_attrs.max_resp_sz = server->rsize; + session = clp->cl_session; + session->fc_attrs.max_rqst_sz = server->wsize + nfs41_maxwrite_overhead; + session->fc_attrs.max_resp_sz = server->rsize + nfs41_maxread_overhead; + ret = nfs4_recover_expired_lease(server); if (!ret) ret = nfs4_check_client_ready(clp); @@ -4872,11 +4885,10 @@ void nfs41_sequence_call_done(struct rpc_task *task, void *data) if (_nfs4_async_handle_error(task, NULL, clp, NULL) == -EAGAIN) { - nfs4_restart_rpc(task, clp); + nfs_restart_rpc(task, clp); return; } } - nfs41_sequence_free_slot(clp, task->tk_msg.rpc_resp); dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred); kfree(task->tk_msg.rpc_argp); @@ -4931,6 +4943,109 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, &nfs41_sequence_ops, (void *)clp); } +struct nfs4_reclaim_complete_data { + struct nfs_client *clp; + struct nfs41_reclaim_complete_args arg; + struct nfs41_reclaim_complete_res res; +}; + +static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data) +{ + struct nfs4_reclaim_complete_data *calldata = data; + + if (nfs4_setup_sequence(calldata->clp, &calldata->arg.seq_args, + &calldata->res.seq_res, 0, task)) + return; + + rpc_call_start(task); +} + +static void nfs4_reclaim_complete_done(struct rpc_task *task, void *data) +{ + struct nfs4_reclaim_complete_data *calldata = data; + struct nfs_client *clp = calldata->clp; + struct nfs4_sequence_res *res = &calldata->res.seq_res; + + dprintk("--> %s\n", __func__); + nfs41_sequence_done(clp, res, task->tk_status); + switch (task->tk_status) { + case 0: + case -NFS4ERR_COMPLETE_ALREADY: + break; + case -NFS4ERR_BADSESSION: + case -NFS4ERR_DEADSESSION: + /* + * Handle the session error, but do not retry the operation, as + * we have no way of telling whether the clientid had to be + * reset before we got our reply. If reset, a new wave of + * reclaim operations will follow, containing their own reclaim + * complete. We don't want our retry to get on the way of + * recovery by incorrectly indicating to the server that we're + * done reclaiming state since the process had to be restarted. + */ + _nfs4_async_handle_error(task, NULL, clp, NULL); + break; + default: + if (_nfs4_async_handle_error( + task, NULL, clp, NULL) == -EAGAIN) { + rpc_restart_call_prepare(task); + return; + } + } + + dprintk("<-- %s\n", __func__); +} + +static void nfs4_free_reclaim_complete_data(void *data) +{ + struct nfs4_reclaim_complete_data *calldata = data; + + kfree(calldata); +} + +static const struct rpc_call_ops nfs4_reclaim_complete_call_ops = { + .rpc_call_prepare = nfs4_reclaim_complete_prepare, + .rpc_call_done = nfs4_reclaim_complete_done, + .rpc_release = nfs4_free_reclaim_complete_data, +}; + +/* + * Issue a global reclaim complete. + */ +static int nfs41_proc_reclaim_complete(struct nfs_client *clp) +{ + struct nfs4_reclaim_complete_data *calldata; + struct rpc_task *task; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RECLAIM_COMPLETE], + }; + struct rpc_task_setup task_setup_data = { + .rpc_client = clp->cl_rpcclient, + .rpc_message = &msg, + .callback_ops = &nfs4_reclaim_complete_call_ops, + .flags = RPC_TASK_ASYNC, + }; + int status = -ENOMEM; + + dprintk("--> %s\n", __func__); + calldata = kzalloc(sizeof(*calldata), GFP_KERNEL); + if (calldata == NULL) + goto out; + calldata->clp = clp; + calldata->arg.one_fs = 0; + calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; + + msg.rpc_argp = &calldata->arg; + msg.rpc_resp = &calldata->res; + task_setup_data.callback_data = calldata; + task = rpc_run_task(&task_setup_data); + if (IS_ERR(task)) + status = PTR_ERR(task); + rpc_put_task(task); +out: + dprintk("<-- %s status=%d\n", __func__, status); + return status; +} #endif /* CONFIG_NFS_V4_1 */ struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { @@ -4948,8 +5063,9 @@ struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = { .state_flag_bit = NFS_STATE_RECLAIM_REBOOT, .recover_open = nfs4_open_reclaim, .recover_lock = nfs4_lock_reclaim, - .establish_clid = nfs4_proc_exchange_id, + .establish_clid = nfs41_init_clientid, .get_clid_cred = nfs4_get_exchange_id_cred, + .reclaim_complete = nfs41_proc_reclaim_complete, }; #endif /* CONFIG_NFS_V4_1 */ @@ -4968,7 +5084,7 @@ struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = { .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, .recover_open = nfs4_open_expired, .recover_lock = nfs4_lock_expired, - .establish_clid = nfs4_proc_exchange_id, + .establish_clid = nfs41_init_clientid, .get_clid_cred = nfs4_get_exchange_id_cred, }; #endif /* CONFIG_NFS_V4_1 */ diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 2ef4fecf39847049cce4a5af771760255dca29c5..e76427e6346fc136a413b324a83d6c9994a14830 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -116,6 +116,68 @@ struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp) #if defined(CONFIG_NFS_V4_1) +static int nfs41_setup_state_renewal(struct nfs_client *clp) +{ + int status; + struct nfs_fsinfo fsinfo; + + status = nfs4_proc_get_lease_time(clp, &fsinfo); + if (status == 0) { + /* Update lease time and schedule renewal */ + spin_lock(&clp->cl_lock); + clp->cl_lease_time = fsinfo.lease_time * HZ; + clp->cl_last_renewal = jiffies; + spin_unlock(&clp->cl_lock); + + nfs4_schedule_state_renewal(clp); + } + + return status; +} + +static void nfs41_end_drain_session(struct nfs_client *clp, + struct nfs4_session *ses) +{ + if (test_and_clear_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state)) + rpc_wake_up(&ses->fc_slot_table.slot_tbl_waitq); +} + +static int nfs41_begin_drain_session(struct nfs_client *clp, + struct nfs4_session *ses) +{ + struct nfs4_slot_table *tbl = &ses->fc_slot_table; + + spin_lock(&tbl->slot_tbl_lock); + set_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state); + if (tbl->highest_used_slotid != -1) { + INIT_COMPLETION(ses->complete); + spin_unlock(&tbl->slot_tbl_lock); + return wait_for_completion_interruptible(&ses->complete); + } + spin_unlock(&tbl->slot_tbl_lock); + return 0; +} + +int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) +{ + int status; + + status = nfs41_begin_drain_session(clp, clp->cl_session); + if (status != 0) + goto out; + status = nfs4_proc_exchange_id(clp, cred); + if (status != 0) + goto out; + status = nfs4_proc_create_session(clp); + if (status != 0) + goto out; + nfs41_end_drain_session(clp, clp->cl_session); + nfs41_setup_state_renewal(clp); + nfs_mark_client_ready(clp, NFS_CS_READY); +out: + return status; +} + struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp) { struct rpc_cred *cred; @@ -877,6 +939,10 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_ case -NFS4ERR_EXPIRED: case -NFS4ERR_NO_GRACE: case -NFS4ERR_STALE_CLIENTID: + case -NFS4ERR_BADSESSION: + case -NFS4ERR_BADSLOT: + case -NFS4ERR_BAD_HIGH_SLOT: + case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: goto out; default: printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n", @@ -959,6 +1025,10 @@ restart: case -NFS4ERR_NO_GRACE: nfs4_state_mark_reclaim_nograce(sp->so_client, state); case -NFS4ERR_STALE_CLIENTID: + case -NFS4ERR_BADSESSION: + case -NFS4ERR_BADSLOT: + case -NFS4ERR_BAD_HIGH_SLOT: + case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: goto out_err; } nfs4_put_open_state(state); @@ -1011,6 +1081,14 @@ static void nfs4_state_start_reclaim_reboot(struct nfs_client *clp) nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_reboot); } +static void nfs4_reclaim_complete(struct nfs_client *clp, + const struct nfs4_state_recovery_ops *ops) +{ + /* Notify the server we're done reclaiming our state */ + if (ops->reclaim_complete) + (void)ops->reclaim_complete(clp); +} + static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) { struct nfs4_state_owner *sp; @@ -1020,6 +1098,9 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) return; + nfs4_reclaim_complete(clp, + nfs4_reboot_recovery_ops[clp->cl_minorversion]); + for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) { sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); spin_lock(&sp->so_lock); @@ -1046,25 +1127,25 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp) nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); } -static void nfs4_state_end_reclaim_nograce(struct nfs_client *clp) -{ - clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state); -} - -static void nfs4_recovery_handle_error(struct nfs_client *clp, int error) +static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) { switch (error) { case -NFS4ERR_CB_PATH_DOWN: nfs_handle_cb_pathdown(clp); - break; + return 0; + case -NFS4ERR_NO_GRACE: + nfs4_state_end_reclaim_reboot(clp); + return 0; case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_LEASE_MOVED: set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); + nfs4_state_end_reclaim_reboot(clp); nfs4_state_start_reclaim_reboot(clp); break; case -NFS4ERR_EXPIRED: set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); nfs4_state_start_reclaim_nograce(clp); + break; case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: case -NFS4ERR_BAD_HIGH_SLOT: @@ -1072,8 +1153,11 @@ static void nfs4_recovery_handle_error(struct nfs_client *clp, int error) case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: case -NFS4ERR_SEQ_FALSE_RETRY: case -NFS4ERR_SEQ_MISORDERED: - set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); + set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); + /* Zero session reset errors */ + return 0; } + return error; } static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops) @@ -1093,8 +1177,7 @@ restart: if (status < 0) { set_bit(ops->owner_flag_bit, &sp->so_flags); nfs4_put_state_owner(sp); - nfs4_recovery_handle_error(clp, status); - return status; + return nfs4_recovery_handle_error(clp, status); } nfs4_put_state_owner(sp); goto restart; @@ -1124,8 +1207,7 @@ static int nfs4_check_lease(struct nfs_client *clp) status = ops->renew_lease(clp, cred); put_rpccred(cred); out: - nfs4_recovery_handle_error(clp, status); - return status; + return nfs4_recovery_handle_error(clp, status); } static int nfs4_reclaim_lease(struct nfs_client *clp) @@ -1151,55 +1233,65 @@ static int nfs4_reclaim_lease(struct nfs_client *clp) } #ifdef CONFIG_NFS_V4_1 -static void nfs4_session_recovery_handle_error(struct nfs_client *clp, int err) +void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) { - switch (err) { - case -NFS4ERR_STALE_CLIENTID: + if (!flags) + return; + else if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) { set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); - set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); - } + nfs4_state_start_reclaim_reboot(clp); + nfs4_schedule_state_recovery(clp); + } else if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED | + SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED | + SEQ4_STATUS_ADMIN_STATE_REVOKED | + SEQ4_STATUS_RECALLABLE_STATE_REVOKED | + SEQ4_STATUS_LEASE_MOVED)) { + set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); + nfs4_state_start_reclaim_nograce(clp); + nfs4_schedule_state_recovery(clp); + } else if (flags & (SEQ4_STATUS_CB_PATH_DOWN | + SEQ4_STATUS_BACKCHANNEL_FAULT | + SEQ4_STATUS_CB_PATH_DOWN_SESSION)) + nfs_expire_all_delegations(clp); } static int nfs4_reset_session(struct nfs_client *clp) { + struct nfs4_session *ses = clp->cl_session; int status; + status = nfs41_begin_drain_session(clp, ses); + if (status != 0) + return status; + status = nfs4_proc_destroy_session(clp->cl_session); if (status && status != -NFS4ERR_BADSESSION && status != -NFS4ERR_DEADSESSION) { - nfs4_session_recovery_handle_error(clp, status); + status = nfs4_recovery_handle_error(clp, status); goto out; } memset(clp->cl_session->sess_id.data, 0, NFS4_MAX_SESSIONID_LEN); - status = nfs4_proc_create_session(clp, 1); + status = nfs4_proc_create_session(clp); if (status) - nfs4_session_recovery_handle_error(clp, status); - /* fall through*/ -out: - /* Wake up the next rpc task even on error */ - rpc_wake_up_next(&clp->cl_session->fc_slot_table.slot_tbl_waitq); - return status; -} - -static int nfs4_initialize_session(struct nfs_client *clp) -{ - int status; + status = nfs4_recovery_handle_error(clp, status); - status = nfs4_proc_create_session(clp, 0); - if (!status) { - nfs_mark_client_ready(clp, NFS_CS_READY); - } else if (status == -NFS4ERR_STALE_CLIENTID) { - set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); - set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); - } else { - nfs_mark_client_ready(clp, status); +out: + /* + * Let the state manager reestablish state + * without waking other tasks yet. + */ + if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { + /* Wake up the next rpc task */ + nfs41_end_drain_session(clp, ses); + if (status == 0) + nfs41_setup_state_renewal(clp); } return status; } + #else /* CONFIG_NFS_V4_1 */ static int nfs4_reset_session(struct nfs_client *clp) { return 0; } -static int nfs4_initialize_session(struct nfs_client *clp) { return 0; } #endif /* CONFIG_NFS_V4_1 */ /* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors @@ -1234,7 +1326,8 @@ static void nfs4_state_manager(struct nfs_client *clp) status = nfs4_reclaim_lease(clp); if (status) { nfs4_set_lease_expired(clp, status); - if (status == -EAGAIN) + if (test_bit(NFS4CLNT_LEASE_EXPIRED, + &clp->cl_state)) continue; if (clp->cl_cons_state == NFS_CS_SESSION_INITING) @@ -1242,55 +1335,51 @@ static void nfs4_state_manager(struct nfs_client *clp) goto out_error; } clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); + set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state); } if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { status = nfs4_check_lease(clp); - if (status != 0) + if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) continue; + if (status < 0 && status != -NFS4ERR_CB_PATH_DOWN) + goto out_error; } + /* Initialize or reset the session */ - if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state) + if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) && nfs4_has_session(clp)) { - if (clp->cl_cons_state == NFS_CS_SESSION_INITING) - status = nfs4_initialize_session(clp); - else - status = nfs4_reset_session(clp); - if (status) { - if (status == -NFS4ERR_STALE_CLIENTID) - continue; + status = nfs4_reset_session(clp); + if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) + continue; + if (status < 0) goto out_error; - } } + /* First recover reboot state... */ - if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { + if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { status = nfs4_do_reclaim(clp, nfs4_reboot_recovery_ops[clp->cl_minorversion]); - if (status == -NFS4ERR_STALE_CLIENTID) - continue; - if (test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) + if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || + test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) continue; nfs4_state_end_reclaim_reboot(clp); - continue; + if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) + continue; + if (status < 0) + goto out_error; } /* Now recover expired state... */ if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { status = nfs4_do_reclaim(clp, nfs4_nograce_recovery_ops[clp->cl_minorversion]); - if (status < 0) { - set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state); - if (status == -NFS4ERR_STALE_CLIENTID) - continue; - if (status == -NFS4ERR_EXPIRED) - continue; - if (test_bit(NFS4CLNT_SESSION_SETUP, - &clp->cl_state)) - continue; + if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || + test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) || + test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) + continue; + if (status < 0) goto out_error; - } else - nfs4_state_end_reclaim_nograce(clp); - continue; } if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { @@ -1309,8 +1398,6 @@ static void nfs4_state_manager(struct nfs_client *clp) out_error: printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" " with error %d\n", clp->cl_hostname, -status); - if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) - nfs4_state_end_reclaim_reboot(clp); nfs4_clear_state_manager_bit(clp); } diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 20b4e30e6c828e5e0aed77ea01c445a52caab0ee..e437fd6a819f6f5a3ea5bd7c303a3c3e6b260638 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -46,11 +46,13 @@ #include #include #include +#include #include #include #include #include #include "nfs4_fs.h" +#include "internal.h" #define NFSDBG_FACILITY NFSDBG_XDR @@ -134,7 +136,7 @@ static int nfs4_stat_to_errno(int); #define decode_lookup_maxsz (op_decode_hdr_maxsz) #define encode_share_access_maxsz \ (2) -#define encode_createmode_maxsz (1 + encode_attrs_maxsz) +#define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz) #define encode_opentype_maxsz (1 + encode_createmode_maxsz) #define encode_claim_null_maxsz (1 + nfs4_name_maxsz) #define encode_open_maxsz (op_encode_hdr_maxsz + \ @@ -299,6 +301,8 @@ static int nfs4_stat_to_errno(int); XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4) #define decode_sequence_maxsz (op_decode_hdr_maxsz + \ XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) +#define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) +#define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) #else /* CONFIG_NFS_V4_1 */ #define encode_sequence_maxsz 0 #define decode_sequence_maxsz 0 @@ -676,6 +680,25 @@ static int nfs4_stat_to_errno(int); decode_sequence_maxsz + \ decode_putrootfh_maxsz + \ decode_fsinfo_maxsz) +#define NFS4_enc_reclaim_complete_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ + encode_reclaim_complete_maxsz) +#define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ + decode_reclaim_complete_maxsz) + +const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + + compound_encode_hdr_maxsz + + encode_sequence_maxsz + + encode_putfh_maxsz + + encode_getattr_maxsz) * + XDR_UNIT); + +const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH + + compound_decode_hdr_maxsz + + decode_sequence_maxsz + + decode_putfh_maxsz) * + XDR_UNIT); #endif /* CONFIG_NFS_V4_1 */ static const umode_t nfs_type2fmt[] = { @@ -1140,6 +1163,7 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) { __be32 *p; + struct nfs_client *clp; p = reserve_space(xdr, 4); switch(arg->open_flags & O_EXCL) { @@ -1148,8 +1172,23 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op encode_attrs(xdr, arg->u.attrs, arg->server); break; default: - *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); - encode_nfs4_verifier(xdr, &arg->u.verifier); + clp = arg->server->nfs_client; + if (clp->cl_minorversion > 0) { + if (nfs4_has_persistent_session(clp)) { + *p = cpu_to_be32(NFS4_CREATE_GUARDED); + encode_attrs(xdr, arg->u.attrs, arg->server); + } else { + struct iattr dummy; + + *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); + encode_nfs4_verifier(xdr, &arg->u.verifier); + dummy.ia_valid = 0; + encode_attrs(xdr, &dummy, arg->server); + } + } else { + *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); + encode_nfs4_verifier(xdr, &arg->u.verifier); + } } } @@ -1592,6 +1631,19 @@ static void encode_destroy_session(struct xdr_stream *xdr, hdr->nops++; hdr->replen += decode_destroy_session_maxsz; } + +static void encode_reclaim_complete(struct xdr_stream *xdr, + struct nfs41_reclaim_complete_args *args, + struct compound_hdr *hdr) +{ + __be32 *p; + + p = reserve_space(xdr, 8); + *p++ = cpu_to_be32(OP_RECLAIM_COMPLETE); + *p++ = cpu_to_be32(args->one_fs); + hdr->nops++; + hdr->replen += decode_reclaim_complete_maxsz; +} #endif /* CONFIG_NFS_V4_1 */ static void encode_sequence(struct xdr_stream *xdr, @@ -2096,7 +2148,7 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p, encode_compound_hdr(&xdr, req, &hdr); encode_sequence(&xdr, &args->seq_args, &hdr); encode_putfh(&xdr, args->fh, &hdr); - replen = hdr.replen + nfs4_fattr_bitmap_maxsz + 1; + replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1; encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr); xdr_inline_pages(&req->rq_rcv_buf, replen << 2, @@ -2420,6 +2472,26 @@ static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p, encode_nops(&hdr); return 0; } + +/* + * a RECLAIM_COMPLETE request + */ +static int nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req, uint32_t *p, + struct nfs41_reclaim_complete_args *args) +{ + struct xdr_stream xdr; + struct compound_hdr hdr = { + .minorversion = nfs4_xdr_minorversion(&args->seq_args) + }; + + xdr_init_encode(&xdr, &req->rq_snd_buf, p); + encode_compound_hdr(&xdr, req, &hdr); + encode_sequence(&xdr, &args->seq_args, &hdr); + encode_reclaim_complete(&xdr, args, &hdr); + encode_nops(&hdr); + return 0; +} + #endif /* CONFIG_NFS_V4_1 */ static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) @@ -4528,6 +4600,11 @@ static int decode_destroy_session(struct xdr_stream *xdr, void *dummy) { return decode_op_hdr(xdr, OP_DESTROY_SESSION); } + +static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy) +{ + return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE); +} #endif /* CONFIG_NFS_V4_1 */ static int decode_sequence(struct xdr_stream *xdr, @@ -4583,8 +4660,8 @@ static int decode_sequence(struct xdr_stream *xdr, dummy = be32_to_cpup(p++); /* target highest slot id - currently not processed */ dummy = be32_to_cpup(p++); - /* result flags - currently not processed */ - dummy = be32_to_cpup(p); + /* result flags */ + res->sr_status_flags = be32_to_cpup(p); status = 0; out_err: res->sr_status = status; @@ -5309,7 +5386,7 @@ out: } /* - * FSINFO request + * Decode FSINFO response */ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsinfo_res *res) @@ -5330,7 +5407,7 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, } /* - * PATHCONF request + * Decode PATHCONF response */ static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p, struct nfs4_pathconf_res *res) @@ -5351,7 +5428,7 @@ static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p, } /* - * STATFS request + * Decode STATFS response */ static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p, struct nfs4_statfs_res *res) @@ -5372,7 +5449,7 @@ static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p, } /* - * GETATTR_BITMAP request + * Decode GETATTR_BITMAP response */ static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, __be32 *p, struct nfs4_server_caps_res *res) { @@ -5411,7 +5488,7 @@ static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, __be32 *p, void *dummy) } /* - * a SETCLIENTID request + * Decode SETCLIENTID response */ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs_client *clp) @@ -5428,7 +5505,7 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p, } /* - * a SETCLIENTID_CONFIRM request + * Decode SETCLIENTID_CONFIRM response */ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *fsinfo) { @@ -5448,7 +5525,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str } /* - * DELEGRETURN request + * Decode DELEGRETURN response */ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_delegreturnres *res) { @@ -5474,7 +5551,7 @@ out: } /* - * FS_LOCATIONS request + * Decode FS_LOCATIONS response */ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs4_fs_locations_res *res) @@ -5504,7 +5581,7 @@ out: #if defined(CONFIG_NFS_V4_1) /* - * EXCHANGE_ID request + * Decode EXCHANGE_ID response */ static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p, void *res) @@ -5521,7 +5598,7 @@ static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p, } /* - * a CREATE_SESSION request + * Decode CREATE_SESSION response */ static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, uint32_t *p, struct nfs41_create_session_res *res) @@ -5538,7 +5615,7 @@ static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, uint32_t *p, } /* - * a DESTROY_SESSION request + * Decode DESTROY_SESSION response */ static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, uint32_t *p, void *dummy) @@ -5555,7 +5632,7 @@ static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, uint32_t *p, } /* - * a SEQUENCE request + * Decode SEQUENCE response */ static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_sequence_res *res) @@ -5572,7 +5649,7 @@ static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, uint32_t *p, } /* - * a GET_LEASE_TIME request + * Decode GET_LEASE_TIME response */ static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_get_lease_time_res *res) @@ -5591,6 +5668,25 @@ static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p, status = decode_fsinfo(&xdr, res->lr_fsinfo); return status; } + +/* + * Decode RECLAIM_COMPLETE response + */ +static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, uint32_t *p, + struct nfs41_reclaim_complete_res *res) +{ + struct xdr_stream xdr; + struct compound_hdr hdr; + int status; + + xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); + status = decode_compound_hdr(&xdr, &hdr); + if (!status) + status = decode_sequence(&xdr, &res->seq_res, rqstp); + if (!status) + status = decode_reclaim_complete(&xdr, (void *)NULL); + return status; +} #endif /* CONFIG_NFS_V4_1 */ __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) @@ -5767,6 +5863,7 @@ struct rpc_procinfo nfs4_procedures[] = { PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session), PROC(SEQUENCE, enc_sequence, dec_sequence), PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time), + PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), #endif /* CONFIG_NFS_V4_1 */ }; diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 12c9e66d3f1d9739147573ecd00cbc703f9f70a8..db9b360ae19da9e61b13152318c6fc59013074ec 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -356,25 +356,19 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data struct nfs_readres *resp = &data->res; if (resp->eof || resp->count == argp->count) - goto out; + return; /* This is a short read! */ nfs_inc_stats(data->inode, NFSIOS_SHORTREAD); /* Has the server at least made some progress? */ if (resp->count == 0) - goto out; + return; /* Yes, so retry the read at the end of the data */ argp->offset += resp->count; argp->pgbase += resp->count; argp->count -= resp->count; - nfs4_restart_rpc(task, NFS_SERVER(data->inode)->nfs_client); - return; -out: - nfs4_sequence_free_slot(NFS_SERVER(data->inode)->nfs_client, - &data->res.seq_res); - return; - + nfs_restart_rpc(task, NFS_SERVER(data->inode)->nfs_client); } /* diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 90be551b80c19fa2733349cbecfdfe231f2a5573..ce907efc5508f049a9ff000a28f8d082159704ce 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -175,14 +175,16 @@ static const match_table_t nfs_mount_option_tokens = { }; enum { - Opt_xprt_udp, Opt_xprt_tcp, Opt_xprt_rdma, + Opt_xprt_udp, Opt_xprt_udp6, Opt_xprt_tcp, Opt_xprt_tcp6, Opt_xprt_rdma, Opt_xprt_err }; static const match_table_t nfs_xprt_protocol_tokens = { { Opt_xprt_udp, "udp" }, + { Opt_xprt_udp6, "udp6" }, { Opt_xprt_tcp, "tcp" }, + { Opt_xprt_tcp6, "tcp6" }, { Opt_xprt_rdma, "rdma" }, { Opt_xprt_err, NULL } @@ -492,6 +494,45 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour) return sec_flavours[i].str; } +static void nfs_show_mountd_netid(struct seq_file *m, struct nfs_server *nfss, + int showdefaults) +{ + struct sockaddr *sap = (struct sockaddr *) &nfss->mountd_address; + + seq_printf(m, ",mountproto="); + switch (sap->sa_family) { + case AF_INET: + switch (nfss->mountd_protocol) { + case IPPROTO_UDP: + seq_printf(m, RPCBIND_NETID_UDP); + break; + case IPPROTO_TCP: + seq_printf(m, RPCBIND_NETID_TCP); + break; + default: + if (showdefaults) + seq_printf(m, "auto"); + } + break; + case AF_INET6: + switch (nfss->mountd_protocol) { + case IPPROTO_UDP: + seq_printf(m, RPCBIND_NETID_UDP6); + break; + case IPPROTO_TCP: + seq_printf(m, RPCBIND_NETID_TCP6); + break; + default: + if (showdefaults) + seq_printf(m, "auto"); + } + break; + default: + if (showdefaults) + seq_printf(m, "auto"); + } +} + static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults) { @@ -505,7 +546,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss, } case AF_INET6: { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; - seq_printf(m, ",mountaddr=%pI6", &sin6->sin6_addr); + seq_printf(m, ",mountaddr=%pI6c", &sin6->sin6_addr); break; } default: @@ -518,17 +559,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss, if (nfss->mountd_port || showdefaults) seq_printf(m, ",mountport=%u", nfss->mountd_port); - switch (nfss->mountd_protocol) { - case IPPROTO_UDP: - seq_printf(m, ",mountproto=udp"); - break; - case IPPROTO_TCP: - seq_printf(m, ",mountproto=tcp"); - break; - default: - if (showdefaults) - seq_printf(m, ",mountproto=auto"); - } + nfs_show_mountd_netid(m, nfss, showdefaults); } /* @@ -578,7 +609,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, seq_puts(m, nfs_infop->nostr); } seq_printf(m, ",proto=%s", - rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO)); + rpc_peeraddr2str(nfss->client, RPC_DISPLAY_NETID)); if (version == 4) { if (nfss->port != NFS_PORT) seq_printf(m, ",port=%u", nfss->port); @@ -714,8 +745,6 @@ static void nfs_umount_begin(struct super_block *sb) struct nfs_server *server; struct rpc_clnt *rpc; - lock_kernel(); - server = NFS_SB(sb); /* -EIO all pending I/O */ rpc = server->client_acl; @@ -724,8 +753,6 @@ static void nfs_umount_begin(struct super_block *sb) rpc = server->client; if (!IS_ERR(rpc)) rpc_killall_tasks(rpc); - - unlock_kernel(); } static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version) @@ -734,8 +761,6 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int ve data = kzalloc(sizeof(*data), GFP_KERNEL); if (data) { - data->rsize = NFS_MAX_FILE_IO_SIZE; - data->wsize = NFS_MAX_FILE_IO_SIZE; data->acregmin = NFS_DEF_ACREGMIN; data->acregmax = NFS_DEF_ACREGMAX; data->acdirmin = NFS_DEF_ACDIRMIN; @@ -887,6 +912,8 @@ static int nfs_parse_mount_options(char *raw, { char *p, *string, *secdata; int rc, sloppy = 0, invalid_option = 0; + unsigned short protofamily = AF_UNSPEC; + unsigned short mountfamily = AF_UNSPEC; if (!raw) { dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); @@ -1232,12 +1259,17 @@ static int nfs_parse_mount_options(char *raw, token = match_token(string, nfs_xprt_protocol_tokens, args); + protofamily = AF_INET; switch (token) { + case Opt_xprt_udp6: + protofamily = AF_INET6; case Opt_xprt_udp: mnt->flags &= ~NFS_MOUNT_TCP; mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; kfree(string); break; + case Opt_xprt_tcp6: + protofamily = AF_INET6; case Opt_xprt_tcp: mnt->flags |= NFS_MOUNT_TCP; mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; @@ -1265,10 +1297,15 @@ static int nfs_parse_mount_options(char *raw, nfs_xprt_protocol_tokens, args); kfree(string); + mountfamily = AF_INET; switch (token) { + case Opt_xprt_udp6: + mountfamily = AF_INET6; case Opt_xprt_udp: mnt->mount_server.protocol = XPRT_TRANSPORT_UDP; break; + case Opt_xprt_tcp6: + mountfamily = AF_INET6; case Opt_xprt_tcp: mnt->mount_server.protocol = XPRT_TRANSPORT_TCP; break; @@ -1367,8 +1404,33 @@ static int nfs_parse_mount_options(char *raw, if (!sloppy && invalid_option) return 0; + /* + * verify that any proto=/mountproto= options match the address + * familiies in the addr=/mountaddr= options. + */ + if (protofamily != AF_UNSPEC && + protofamily != mnt->nfs_server.address.ss_family) + goto out_proto_mismatch; + + if (mountfamily != AF_UNSPEC) { + if (mnt->mount_server.addrlen) { + if (mountfamily != mnt->mount_server.address.ss_family) + goto out_mountproto_mismatch; + } else { + if (mountfamily != mnt->nfs_server.address.ss_family) + goto out_mountproto_mismatch; + } + } + return 1; +out_mountproto_mismatch: + printk(KERN_INFO "NFS: mount server address does not match mountproto= " + "option\n"); + return 0; +out_proto_mismatch: + printk(KERN_INFO "NFS: server address does not match proto= option\n"); + return 0; out_invalid_address: printk(KERN_INFO "NFS: bad IP address specified: %s\n", p); return 0; @@ -1881,7 +1943,6 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) if (data == NULL) return -ENOMEM; - lock_kernel(); /* fill out struct with values from existing mount */ data->flags = nfss->flags; data->rsize = nfss->rsize; @@ -1907,7 +1968,6 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) error = nfs_compare_remount_data(nfss, data); out: kfree(data); - unlock_kernel(); return error; } diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 1064c91ae810c3496f621729cbc754653be69a8e..6da3d3ff6edd652fdcaf5934ea5056acdd062135 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -83,7 +83,7 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata) struct inode *dir = data->dir; if (!NFS_PROTO(dir)->unlink_done(task, dir)) - nfs4_restart_rpc(task, NFS_SERVER(dir)->nfs_client); + nfs_restart_rpc(task, NFS_SERVER(dir)->nfs_client); } /** diff --git a/fs/nfs/write.c b/fs/nfs/write.c index c84b5cc1a943570ac9cba1fbf130288bcefe65e8..d171696017f4befe44f85ffd79b138f88db7c214 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -774,7 +774,7 @@ int nfs_updatepage(struct file *file, struct page *page, */ if (nfs_write_pageuptodate(page, inode) && inode->i_flock == NULL && - !(file->f_flags & O_SYNC)) { + !(file->f_flags & O_DSYNC)) { count = max(count + offset, nfs_page_length(page)); offset = 0; } @@ -1216,7 +1216,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) */ argp->stable = NFS_FILE_SYNC; } - nfs4_restart_rpc(task, server->nfs_client); + nfs_restart_rpc(task, server->nfs_client); return -EAGAIN; } if (time_before(complain, jiffies)) { @@ -1228,7 +1228,6 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) /* Can't do anything about it except throw an error. */ task->tk_status = -EIO; } - nfs4_sequence_free_slot(server->nfs_client, &data->res.seq_res); return 0; } @@ -1612,15 +1611,16 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage, if (ret) goto out_unlock; page_cache_get(newpage); + spin_lock(&mapping->host->i_lock); req->wb_page = newpage; SetPagePrivate(newpage); - set_page_private(newpage, page_private(page)); + set_page_private(newpage, (unsigned long)req); ClearPagePrivate(page); set_page_private(page, 0); + spin_unlock(&mapping->host->i_lock); page_cache_release(page); out_unlock: nfs_clear_page_tag_locked(req); - nfs_release_request(req); out: return ret; } diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c index d69e6ae59251f44f31f852d69b5ade0effea8805..3f959f1879d8b813a0ce775af216c5e5cd8df617 100644 --- a/fs/nilfs2/alloc.c +++ b/fs/nilfs2/alloc.c @@ -142,29 +142,75 @@ static void nilfs_palloc_desc_block_init(struct inode *inode, } } +static int nilfs_palloc_get_block(struct inode *inode, unsigned long blkoff, + int create, + void (*init_block)(struct inode *, + struct buffer_head *, + void *), + struct buffer_head **bhp, + struct nilfs_bh_assoc *prev, + spinlock_t *lock) +{ + int ret; + + spin_lock(lock); + if (prev->bh && blkoff == prev->blkoff) { + get_bh(prev->bh); + *bhp = prev->bh; + spin_unlock(lock); + return 0; + } + spin_unlock(lock); + + ret = nilfs_mdt_get_block(inode, blkoff, create, init_block, bhp); + if (!ret) { + spin_lock(lock); + /* + * The following code must be safe for change of the + * cache contents during the get block call. + */ + brelse(prev->bh); + get_bh(*bhp); + prev->bh = *bhp; + prev->blkoff = blkoff; + spin_unlock(lock); + } + return ret; +} + static int nilfs_palloc_get_desc_block(struct inode *inode, unsigned long group, int create, struct buffer_head **bhp) { - return nilfs_mdt_get_block(inode, - nilfs_palloc_desc_blkoff(inode, group), - create, nilfs_palloc_desc_block_init, bhp); + struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache; + + return nilfs_palloc_get_block(inode, + nilfs_palloc_desc_blkoff(inode, group), + create, nilfs_palloc_desc_block_init, + bhp, &cache->prev_desc, &cache->lock); } static int nilfs_palloc_get_bitmap_block(struct inode *inode, unsigned long group, int create, struct buffer_head **bhp) { - return nilfs_mdt_get_block(inode, - nilfs_palloc_bitmap_blkoff(inode, group), - create, NULL, bhp); + struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache; + + return nilfs_palloc_get_block(inode, + nilfs_palloc_bitmap_blkoff(inode, group), + create, NULL, bhp, + &cache->prev_bitmap, &cache->lock); } int nilfs_palloc_get_entry_block(struct inode *inode, __u64 nr, int create, struct buffer_head **bhp) { - return nilfs_mdt_get_block(inode, nilfs_palloc_entry_blkoff(inode, nr), - create, NULL, bhp); + struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache; + + return nilfs_palloc_get_block(inode, + nilfs_palloc_entry_blkoff(inode, nr), + create, NULL, bhp, + &cache->prev_entry, &cache->lock); } static struct nilfs_palloc_group_desc * @@ -176,13 +222,6 @@ nilfs_palloc_block_get_group_desc(const struct inode *inode, group % nilfs_palloc_groups_per_desc_block(inode); } -static unsigned char * -nilfs_palloc_block_get_bitmap(const struct inode *inode, - const struct buffer_head *bh, void *kaddr) -{ - return (unsigned char *)(kaddr + bh_offset(bh)); -} - void *nilfs_palloc_block_get_entry(const struct inode *inode, __u64 nr, const struct buffer_head *bh, void *kaddr) { @@ -289,8 +328,7 @@ int nilfs_palloc_prepare_alloc_entry(struct inode *inode, if (ret < 0) goto out_desc; bitmap_kaddr = kmap(bitmap_bh->b_page); - bitmap = nilfs_palloc_block_get_bitmap( - inode, bitmap_bh, bitmap_kaddr); + bitmap = bitmap_kaddr + bh_offset(bitmap_bh); pos = nilfs_palloc_find_available_slot( inode, group, group_offset, bitmap, entries_per_group); @@ -351,8 +389,7 @@ void nilfs_palloc_commit_free_entry(struct inode *inode, desc = nilfs_palloc_block_get_group_desc(inode, group, req->pr_desc_bh, desc_kaddr); bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page); - bitmap = nilfs_palloc_block_get_bitmap(inode, req->pr_bitmap_bh, - bitmap_kaddr); + bitmap = bitmap_kaddr + bh_offset(req->pr_bitmap_bh); if (!nilfs_clear_bit_atomic(nilfs_mdt_bgl_lock(inode, group), group_offset, bitmap)) @@ -385,8 +422,7 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode, desc = nilfs_palloc_block_get_group_desc(inode, group, req->pr_desc_bh, desc_kaddr); bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page); - bitmap = nilfs_palloc_block_get_bitmap(inode, req->pr_bitmap_bh, - bitmap_kaddr); + bitmap = bitmap_kaddr + bh_offset(req->pr_bitmap_bh); if (!nilfs_clear_bit_atomic(nilfs_mdt_bgl_lock(inode, group), group_offset, bitmap)) printk(KERN_WARNING "%s: entry numer %llu already freed\n", @@ -472,8 +508,7 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) desc = nilfs_palloc_block_get_group_desc( inode, group, desc_bh, desc_kaddr); bitmap_kaddr = kmap(bitmap_bh->b_page); - bitmap = nilfs_palloc_block_get_bitmap( - inode, bitmap_bh, bitmap_kaddr); + bitmap = bitmap_kaddr + bh_offset(bitmap_bh); for (j = i, n = 0; (j < nitems) && nilfs_palloc_group_is_in(inode, group, entry_nrs[j]); @@ -502,3 +537,30 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) } return 0; } + +void nilfs_palloc_setup_cache(struct inode *inode, + struct nilfs_palloc_cache *cache) +{ + NILFS_MDT(inode)->mi_palloc_cache = cache; + spin_lock_init(&cache->lock); +} + +void nilfs_palloc_clear_cache(struct inode *inode) +{ + struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache; + + spin_lock(&cache->lock); + brelse(cache->prev_desc.bh); + brelse(cache->prev_bitmap.bh); + brelse(cache->prev_entry.bh); + cache->prev_desc.bh = NULL; + cache->prev_bitmap.bh = NULL; + cache->prev_entry.bh = NULL; + spin_unlock(&cache->lock); +} + +void nilfs_palloc_destroy_cache(struct inode *inode) +{ + nilfs_palloc_clear_cache(inode); + NILFS_MDT(inode)->mi_palloc_cache = NULL; +} diff --git a/fs/nilfs2/alloc.h b/fs/nilfs2/alloc.h index 4ace5475c2c7a10b61bd90aa1ba3fd2985aa2454..f4543ac4f56068d539b80b156e4096acd3c5e5ca 100644 --- a/fs/nilfs2/alloc.h +++ b/fs/nilfs2/alloc.h @@ -69,4 +69,25 @@ int nilfs_palloc_freev(struct inode *, __u64 *, size_t); #define nilfs_clear_bit_atomic ext2_clear_bit_atomic #define nilfs_find_next_zero_bit ext2_find_next_zero_bit +/* + * persistent object allocator cache + */ + +struct nilfs_bh_assoc { + unsigned long blkoff; + struct buffer_head *bh; +}; + +struct nilfs_palloc_cache { + spinlock_t lock; + struct nilfs_bh_assoc prev_desc; + struct nilfs_bh_assoc prev_bitmap; + struct nilfs_bh_assoc prev_entry; +}; + +void nilfs_palloc_setup_cache(struct inode *inode, + struct nilfs_palloc_cache *cache); +void nilfs_palloc_clear_cache(struct inode *inode); +void nilfs_palloc_destroy_cache(struct inode *inode); + #endif /* _NILFS_ALLOC_H */ diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index 08834df6ec686911198ab4cc65d91b167109acc1..f4a14ea2ed9c3d17f269260affcb82947109ed46 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c @@ -402,19 +402,11 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap) void nilfs_bmap_add_blocks(const struct nilfs_bmap *bmap, int n) { inode_add_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n); - if (NILFS_MDT(bmap->b_inode)) - nilfs_mdt_mark_dirty(bmap->b_inode); - else - mark_inode_dirty(bmap->b_inode); } void nilfs_bmap_sub_blocks(const struct nilfs_bmap *bmap, int n) { inode_sub_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n); - if (NILFS_MDT(bmap->b_inode)) - nilfs_mdt_mark_dirty(bmap->b_inode); - else - mark_inode_dirty(bmap->b_inode); } __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap, diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c index 84c25382f8e3b35b13f6509463aef70308bb3164..471e269536ae1f24e07d84c9d412abcd5068d17d 100644 --- a/fs/nilfs2/btnode.c +++ b/fs/nilfs2/btnode.c @@ -68,9 +68,34 @@ void nilfs_btnode_cache_clear(struct address_space *btnc) truncate_inode_pages(btnc, 0); } +struct buffer_head * +nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr) +{ + struct inode *inode = NILFS_BTNC_I(btnc); + struct buffer_head *bh; + + bh = nilfs_grab_buffer(inode, btnc, blocknr, 1 << BH_NILFS_Node); + if (unlikely(!bh)) + return NULL; + + if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) || + buffer_dirty(bh))) { + brelse(bh); + BUG(); + } + memset(bh->b_data, 0, 1 << inode->i_blkbits); + bh->b_bdev = NILFS_I_NILFS(inode)->ns_bdev; + bh->b_blocknr = blocknr; + set_buffer_mapped(bh); + set_buffer_uptodate(bh); + + unlock_page(bh->b_page); + page_cache_release(bh->b_page); + return bh; +} + int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, - sector_t pblocknr, struct buffer_head **pbh, - int newblk) + sector_t pblocknr, struct buffer_head **pbh) { struct buffer_head *bh; struct inode *inode = NILFS_BTNC_I(btnc); @@ -81,19 +106,6 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, return -ENOMEM; err = -EEXIST; /* internal code */ - if (newblk) { - if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) || - buffer_dirty(bh))) { - brelse(bh); - BUG(); - } - memset(bh->b_data, 0, 1 << inode->i_blkbits); - bh->b_bdev = NILFS_I_NILFS(inode)->ns_bdev; - bh->b_blocknr = blocknr; - set_buffer_mapped(bh); - set_buffer_uptodate(bh); - goto found; - } if (buffer_uptodate(bh) || buffer_dirty(bh)) goto found; @@ -135,27 +147,6 @@ out_locked: return err; } -int nilfs_btnode_get(struct address_space *btnc, __u64 blocknr, - sector_t pblocknr, struct buffer_head **pbh, int newblk) -{ - struct buffer_head *bh; - int err; - - err = nilfs_btnode_submit_block(btnc, blocknr, pblocknr, pbh, newblk); - if (err == -EEXIST) /* internal code (cache hit) */ - return 0; - if (unlikely(err)) - return err; - - bh = *pbh; - wait_on_buffer(bh); - if (!buffer_uptodate(bh)) { - brelse(bh); - return -EIO; - } - return 0; -} - /** * nilfs_btnode_delete - delete B-tree node buffer * @bh: buffer to be deleted @@ -244,12 +235,13 @@ retry: unlock_page(obh->b_page); } - err = nilfs_btnode_get(btnc, newkey, 0, &nbh, 1); - if (likely(!err)) { - BUG_ON(nbh == obh); - ctxt->newbh = nbh; - } - return err; + nbh = nilfs_btnode_create_block(btnc, newkey); + if (!nbh) + return -ENOMEM; + + BUG_ON(nbh == obh); + ctxt->newbh = nbh; + return 0; failed_unlock: unlock_page(obh->b_page); diff --git a/fs/nilfs2/btnode.h b/fs/nilfs2/btnode.h index 3e2275172ed623cc48e428619fdd66b9a47484a9..07da83f07712a9caa7afd6a673bc070783d20795 100644 --- a/fs/nilfs2/btnode.h +++ b/fs/nilfs2/btnode.h @@ -40,10 +40,10 @@ struct nilfs_btnode_chkey_ctxt { void nilfs_btnode_cache_init_once(struct address_space *); void nilfs_btnode_cache_init(struct address_space *, struct backing_dev_info *); void nilfs_btnode_cache_clear(struct address_space *); +struct buffer_head *nilfs_btnode_create_block(struct address_space *btnc, + __u64 blocknr); int nilfs_btnode_submit_block(struct address_space *, __u64, sector_t, - struct buffer_head **, int); -int nilfs_btnode_get(struct address_space *, __u64, sector_t, - struct buffer_head **, int); + struct buffer_head **); void nilfs_btnode_delete(struct buffer_head *); int nilfs_btnode_prepare_change_key(struct address_space *, struct nilfs_btnode_chkey_ctxt *); diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index e25b507a474fc46c30f2ae84d2c5fb1521a0dbb3..7cdd98b8d51482c02ea1b24c3a954d5213ffaa46 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -114,7 +114,18 @@ static int nilfs_btree_get_block(const struct nilfs_btree *btree, __u64 ptr, { struct address_space *btnc = &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache; - return nilfs_btnode_get(btnc, ptr, 0, bhp, 0); + int err; + + err = nilfs_btnode_submit_block(btnc, ptr, 0, bhp); + if (err) + return err == -EEXIST ? 0 : err; + + wait_on_buffer(*bhp); + if (!buffer_uptodate(*bhp)) { + brelse(*bhp); + return -EIO; + } + return 0; } static int nilfs_btree_get_new_block(const struct nilfs_btree *btree, @@ -122,12 +133,15 @@ static int nilfs_btree_get_new_block(const struct nilfs_btree *btree, { struct address_space *btnc = &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache; - int ret; + struct buffer_head *bh; - ret = nilfs_btnode_get(btnc, ptr, 0, bhp, 1); - if (!ret) - set_buffer_nilfs_volatile(*bhp); - return ret; + bh = nilfs_btnode_create_block(btnc, ptr); + if (!bh) + return -ENOMEM; + + set_buffer_nilfs_volatile(bh); + *bhp = bh; + return 0; } static inline int @@ -444,6 +458,18 @@ nilfs_btree_get_node(const struct nilfs_btree *btree, nilfs_btree_get_nonroot_node(path, level); } +static inline int +nilfs_btree_bad_node(struct nilfs_btree_node *node, int level) +{ + if (unlikely(nilfs_btree_node_get_level(node) != level)) { + dump_stack(); + printk(KERN_CRIT "NILFS: btree level mismatch: %d != %d\n", + nilfs_btree_node_get_level(node), level); + return 1; + } + return 0; +} + static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, struct nilfs_btree_path *path, __u64 key, __u64 *ptrp, int minlevel) @@ -467,7 +493,8 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, if (ret < 0) return ret; node = nilfs_btree_get_nonroot_node(path, level); - BUG_ON(level != nilfs_btree_node_get_level(node)); + if (nilfs_btree_bad_node(node, level)) + return -EINVAL; if (!found) found = nilfs_btree_node_lookup(node, key, &index); else @@ -512,7 +539,8 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree, if (ret < 0) return ret; node = nilfs_btree_get_nonroot_node(path, level); - BUG_ON(level != nilfs_btree_node_get_level(node)); + if (nilfs_btree_bad_node(node, level)) + return -EINVAL; index = nilfs_btree_node_get_nchildren(node) - 1; ptr = nilfs_btree_node_get_ptr(btree, node, index); path[level].bp_index = index; @@ -638,13 +666,11 @@ static void nilfs_btree_promote_key(struct nilfs_btree *btree, { if (level < nilfs_btree_height(btree) - 1) { do { - lock_buffer(path[level].bp_bh); nilfs_btree_node_set_key( nilfs_btree_get_nonroot_node(path, level), path[level].bp_index, key); if (!buffer_dirty(path[level].bp_bh)) nilfs_btnode_mark_dirty(path[level].bp_bh); - unlock_buffer(path[level].bp_bh); } while ((path[level].bp_index == 0) && (++level < nilfs_btree_height(btree) - 1)); } @@ -663,13 +689,11 @@ static void nilfs_btree_do_insert(struct nilfs_btree *btree, struct nilfs_btree_node *node; if (level < nilfs_btree_height(btree) - 1) { - lock_buffer(path[level].bp_bh); node = nilfs_btree_get_nonroot_node(path, level); nilfs_btree_node_insert(btree, node, *keyp, *ptrp, path[level].bp_index); if (!buffer_dirty(path[level].bp_bh)) nilfs_btnode_mark_dirty(path[level].bp_bh); - unlock_buffer(path[level].bp_bh); if (path[level].bp_index == 0) nilfs_btree_promote_key(btree, path, level + 1, @@ -689,9 +713,6 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree, struct nilfs_btree_node *node, *left; int nchildren, lnchildren, n, move; - lock_buffer(path[level].bp_bh); - lock_buffer(path[level].bp_sib_bh); - node = nilfs_btree_get_nonroot_node(path, level); left = nilfs_btree_get_sib_node(path, level); nchildren = nilfs_btree_node_get_nchildren(node); @@ -712,9 +733,6 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree, if (!buffer_dirty(path[level].bp_sib_bh)) nilfs_btnode_mark_dirty(path[level].bp_sib_bh); - unlock_buffer(path[level].bp_bh); - unlock_buffer(path[level].bp_sib_bh); - nilfs_btree_promote_key(btree, path, level + 1, nilfs_btree_node_get_key(node, 0)); @@ -740,9 +758,6 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree, struct nilfs_btree_node *node, *right; int nchildren, rnchildren, n, move; - lock_buffer(path[level].bp_bh); - lock_buffer(path[level].bp_sib_bh); - node = nilfs_btree_get_nonroot_node(path, level); right = nilfs_btree_get_sib_node(path, level); nchildren = nilfs_btree_node_get_nchildren(node); @@ -763,9 +778,6 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree, if (!buffer_dirty(path[level].bp_sib_bh)) nilfs_btnode_mark_dirty(path[level].bp_sib_bh); - unlock_buffer(path[level].bp_bh); - unlock_buffer(path[level].bp_sib_bh); - path[level + 1].bp_index++; nilfs_btree_promote_key(btree, path, level + 1, nilfs_btree_node_get_key(right, 0)); @@ -794,9 +806,6 @@ static void nilfs_btree_split(struct nilfs_btree *btree, __u64 newptr; int nchildren, n, move; - lock_buffer(path[level].bp_bh); - lock_buffer(path[level].bp_sib_bh); - node = nilfs_btree_get_nonroot_node(path, level); right = nilfs_btree_get_sib_node(path, level); nchildren = nilfs_btree_node_get_nchildren(node); @@ -815,9 +824,6 @@ static void nilfs_btree_split(struct nilfs_btree *btree, if (!buffer_dirty(path[level].bp_sib_bh)) nilfs_btnode_mark_dirty(path[level].bp_sib_bh); - unlock_buffer(path[level].bp_bh); - unlock_buffer(path[level].bp_sib_bh); - newkey = nilfs_btree_node_get_key(right, 0); newptr = path[level].bp_newreq.bpr_ptr; @@ -852,8 +858,6 @@ static void nilfs_btree_grow(struct nilfs_btree *btree, struct nilfs_btree_node *root, *child; int n; - lock_buffer(path[level].bp_sib_bh); - root = nilfs_btree_get_root(btree); child = nilfs_btree_get_sib_node(path, level); @@ -865,8 +869,6 @@ static void nilfs_btree_grow(struct nilfs_btree *btree, if (!buffer_dirty(path[level].bp_sib_bh)) nilfs_btnode_mark_dirty(path[level].bp_sib_bh); - unlock_buffer(path[level].bp_sib_bh); - path[level].bp_bh = path[level].bp_sib_bh; path[level].bp_sib_bh = NULL; @@ -1023,11 +1025,9 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, stats->bs_nblocks++; - lock_buffer(bh); nilfs_btree_node_init(btree, (struct nilfs_btree_node *)bh->b_data, 0, level, 0, NULL, NULL); - unlock_buffer(bh); path[level].bp_sib_bh = bh; path[level].bp_op = nilfs_btree_split; } @@ -1052,10 +1052,8 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, if (ret < 0) goto err_out_curr_node; - lock_buffer(bh); nilfs_btree_node_init(btree, (struct nilfs_btree_node *)bh->b_data, 0, level, 0, NULL, NULL); - unlock_buffer(bh); path[level].bp_sib_bh = bh; path[level].bp_op = nilfs_btree_grow; @@ -1154,13 +1152,11 @@ static void nilfs_btree_do_delete(struct nilfs_btree *btree, struct nilfs_btree_node *node; if (level < nilfs_btree_height(btree) - 1) { - lock_buffer(path[level].bp_bh); node = nilfs_btree_get_nonroot_node(path, level); nilfs_btree_node_delete(btree, node, keyp, ptrp, path[level].bp_index); if (!buffer_dirty(path[level].bp_bh)) nilfs_btnode_mark_dirty(path[level].bp_bh); - unlock_buffer(path[level].bp_bh); if (path[level].bp_index == 0) nilfs_btree_promote_key(btree, path, level + 1, nilfs_btree_node_get_key(node, 0)); @@ -1180,9 +1176,6 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree, nilfs_btree_do_delete(btree, path, level, keyp, ptrp); - lock_buffer(path[level].bp_bh); - lock_buffer(path[level].bp_sib_bh); - node = nilfs_btree_get_nonroot_node(path, level); left = nilfs_btree_get_sib_node(path, level); nchildren = nilfs_btree_node_get_nchildren(node); @@ -1197,9 +1190,6 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree, if (!buffer_dirty(path[level].bp_sib_bh)) nilfs_btnode_mark_dirty(path[level].bp_sib_bh); - unlock_buffer(path[level].bp_bh); - unlock_buffer(path[level].bp_sib_bh); - nilfs_btree_promote_key(btree, path, level + 1, nilfs_btree_node_get_key(node, 0)); @@ -1217,9 +1207,6 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree, nilfs_btree_do_delete(btree, path, level, keyp, ptrp); - lock_buffer(path[level].bp_bh); - lock_buffer(path[level].bp_sib_bh); - node = nilfs_btree_get_nonroot_node(path, level); right = nilfs_btree_get_sib_node(path, level); nchildren = nilfs_btree_node_get_nchildren(node); @@ -1234,9 +1221,6 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree, if (!buffer_dirty(path[level].bp_sib_bh)) nilfs_btnode_mark_dirty(path[level].bp_sib_bh); - unlock_buffer(path[level].bp_bh); - unlock_buffer(path[level].bp_sib_bh); - path[level + 1].bp_index++; nilfs_btree_promote_key(btree, path, level + 1, nilfs_btree_node_get_key(right, 0)); @@ -1255,9 +1239,6 @@ static void nilfs_btree_concat_left(struct nilfs_btree *btree, nilfs_btree_do_delete(btree, path, level, keyp, ptrp); - lock_buffer(path[level].bp_bh); - lock_buffer(path[level].bp_sib_bh); - node = nilfs_btree_get_nonroot_node(path, level); left = nilfs_btree_get_sib_node(path, level); @@ -1268,9 +1249,6 @@ static void nilfs_btree_concat_left(struct nilfs_btree *btree, if (!buffer_dirty(path[level].bp_sib_bh)) nilfs_btnode_mark_dirty(path[level].bp_sib_bh); - unlock_buffer(path[level].bp_bh); - unlock_buffer(path[level].bp_sib_bh); - nilfs_btnode_delete(path[level].bp_bh); path[level].bp_bh = path[level].bp_sib_bh; path[level].bp_sib_bh = NULL; @@ -1286,9 +1264,6 @@ static void nilfs_btree_concat_right(struct nilfs_btree *btree, nilfs_btree_do_delete(btree, path, level, keyp, ptrp); - lock_buffer(path[level].bp_bh); - lock_buffer(path[level].bp_sib_bh); - node = nilfs_btree_get_nonroot_node(path, level); right = nilfs_btree_get_sib_node(path, level); @@ -1299,9 +1274,6 @@ static void nilfs_btree_concat_right(struct nilfs_btree *btree, if (!buffer_dirty(path[level].bp_bh)) nilfs_btnode_mark_dirty(path[level].bp_bh); - unlock_buffer(path[level].bp_bh); - unlock_buffer(path[level].bp_sib_bh); - nilfs_btnode_delete(path[level].bp_sib_bh); path[level].bp_sib_bh = NULL; path[level + 1].bp_index++; @@ -1316,7 +1288,6 @@ static void nilfs_btree_shrink(struct nilfs_btree *btree, nilfs_btree_do_delete(btree, path, level, keyp, ptrp); - lock_buffer(path[level].bp_bh); root = nilfs_btree_get_root(btree); child = nilfs_btree_get_nonroot_node(path, level); @@ -1324,7 +1295,6 @@ static void nilfs_btree_shrink(struct nilfs_btree *btree, nilfs_btree_node_set_level(root, level); n = nilfs_btree_node_get_nchildren(child); nilfs_btree_node_move_left(btree, root, child, n); - unlock_buffer(path[level].bp_bh); nilfs_btnode_delete(path[level].bp_bh); path[level].bp_bh = NULL; @@ -1699,7 +1669,6 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, nilfs_bmap_commit_alloc_ptr(bmap, nreq, dat); /* create child node at level 1 */ - lock_buffer(bh); node = (struct nilfs_btree_node *)bh->b_data; nilfs_btree_node_init(btree, node, 0, 1, n, keys, ptrs); nilfs_btree_node_insert(btree, node, @@ -1709,7 +1678,6 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, if (!nilfs_bmap_dirty(bmap)) nilfs_bmap_set_dirty(bmap); - unlock_buffer(bh); brelse(bh); /* create root node at level 2 */ @@ -2050,7 +2018,7 @@ static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *bmap, for (level = NILFS_BTREE_LEVEL_NODE_MIN; level < NILFS_BTREE_LEVEL_MAX; level++) - list_splice(&lists[level], listp->prev); + list_splice_tail(&lists[level], listp); } static int nilfs_btree_assign_p(struct nilfs_btree *btree, diff --git a/fs/nilfs2/btree.h b/fs/nilfs2/btree.h index 0e72bbbc6b648bb1a420f735fedaafe11b3d29ab..4b82d84ade750e6e9e7f1d525428b916d5931219 100644 --- a/fs/nilfs2/btree.h +++ b/fs/nilfs2/btree.h @@ -33,28 +33,6 @@ struct nilfs_btree; struct nilfs_btree_path; -/** - * struct nilfs_btree_node - B-tree node - * @bn_flags: flags - * @bn_level: level - * @bn_nchildren: number of children - * @bn_pad: padding - */ -struct nilfs_btree_node { - __u8 bn_flags; - __u8 bn_level; - __le16 bn_nchildren; - __le32 bn_pad; -}; - -/* flags */ -#define NILFS_BTREE_NODE_ROOT 0x01 - -/* level */ -#define NILFS_BTREE_LEVEL_DATA 0 -#define NILFS_BTREE_LEVEL_NODE_MIN (NILFS_BTREE_LEVEL_DATA + 1) -#define NILFS_BTREE_LEVEL_MAX 14 - /** * struct nilfs_btree - B-tree structure * @bt_bmap: bmap base structure diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c index 3f5d5d06f53c32990cdaf817b0008fa6386bbdb7..d5ad54e204a59f45c181990857d6977cc9b5a73b 100644 --- a/fs/nilfs2/cpfile.c +++ b/fs/nilfs2/cpfile.c @@ -926,3 +926,29 @@ int nilfs_cpfile_get_stat(struct inode *cpfile, struct nilfs_cpstat *cpstat) up_read(&NILFS_MDT(cpfile)->mi_sem); return ret; } + +/** + * nilfs_cpfile_read - read cpfile inode + * @cpfile: cpfile inode + * @raw_inode: on-disk cpfile inode + */ +int nilfs_cpfile_read(struct inode *cpfile, struct nilfs_inode *raw_inode) +{ + return nilfs_read_inode_common(cpfile, raw_inode); +} + +/** + * nilfs_cpfile_new - create cpfile + * @nilfs: nilfs object + * @cpsize: size of a checkpoint entry + */ +struct inode *nilfs_cpfile_new(struct the_nilfs *nilfs, size_t cpsize) +{ + struct inode *cpfile; + + cpfile = nilfs_mdt_new(nilfs, NULL, NILFS_CPFILE_INO, 0); + if (cpfile) + nilfs_mdt_set_entry_size(cpfile, cpsize, + sizeof(struct nilfs_cpfile_header)); + return cpfile; +} diff --git a/fs/nilfs2/cpfile.h b/fs/nilfs2/cpfile.h index debea896e70111a276a92ef3910ba1e96388b587..bc0809e0ab43d15dc60efad9ed731dd870348c22 100644 --- a/fs/nilfs2/cpfile.h +++ b/fs/nilfs2/cpfile.h @@ -40,4 +40,7 @@ int nilfs_cpfile_get_stat(struct inode *, struct nilfs_cpstat *); ssize_t nilfs_cpfile_get_cpinfo(struct inode *, __u64 *, int, void *, unsigned, size_t); +int nilfs_cpfile_read(struct inode *cpfile, struct nilfs_inode *raw_inode); +struct inode *nilfs_cpfile_new(struct the_nilfs *nilfs, size_t cpsize); + #endif /* _NILFS_CPFILE_H */ diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c index 1ff8e15bd36b52dad460dd1f28e7797916b87165..187dd07ba86c659b465daa6b988cf2b80cc9ce02 100644 --- a/fs/nilfs2/dat.c +++ b/fs/nilfs2/dat.c @@ -33,6 +33,16 @@ #define NILFS_CNO_MIN ((__u64)1) #define NILFS_CNO_MAX (~(__u64)0) +struct nilfs_dat_info { + struct nilfs_mdt_info mi; + struct nilfs_palloc_cache palloc_cache; +}; + +static inline struct nilfs_dat_info *NILFS_DAT_I(struct inode *dat) +{ + return (struct nilfs_dat_info *)NILFS_MDT(dat); +} + static int nilfs_dat_prepare_entry(struct inode *dat, struct nilfs_palloc_req *req, int create) { @@ -425,3 +435,40 @@ ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned visz, return nvi; } + +/** + * nilfs_dat_read - read dat inode + * @dat: dat inode + * @raw_inode: on-disk dat inode + */ +int nilfs_dat_read(struct inode *dat, struct nilfs_inode *raw_inode) +{ + return nilfs_read_inode_common(dat, raw_inode); +} + +/** + * nilfs_dat_new - create dat file + * @nilfs: nilfs object + * @entry_size: size of a dat entry + */ +struct inode *nilfs_dat_new(struct the_nilfs *nilfs, size_t entry_size) +{ + static struct lock_class_key dat_lock_key; + struct inode *dat; + struct nilfs_dat_info *di; + int err; + + dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO, sizeof(*di)); + if (dat) { + err = nilfs_palloc_init_blockgroup(dat, entry_size); + if (unlikely(err)) { + nilfs_mdt_destroy(dat); + return NULL; + } + + di = NILFS_DAT_I(dat); + lockdep_set_class(&di->mi.mi_sem, &dat_lock_key); + nilfs_palloc_setup_cache(dat, &di->palloc_cache); + } + return dat; +} diff --git a/fs/nilfs2/dat.h b/fs/nilfs2/dat.h index 406070d3ff4922b97dc62e36c28f47b47d671d74..d31c3aab0efefb7cb64bd7070feee322a17469a8 100644 --- a/fs/nilfs2/dat.h +++ b/fs/nilfs2/dat.h @@ -53,4 +53,7 @@ int nilfs_dat_freev(struct inode *, __u64 *, size_t); int nilfs_dat_move(struct inode *, __u64, sector_t); ssize_t nilfs_dat_get_vinfo(struct inode *, void *, unsigned, size_t); +int nilfs_dat_read(struct inode *dat, struct nilfs_inode *raw_inode); +struct inode *nilfs_dat_new(struct the_nilfs *nilfs, size_t entry_size); + #endif /* _NILFS_DAT_H */ diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index e097099bfc8f0923480e110243979d9ace0be924..76d803e060a95d983b633552a7a75c2b1bf42368 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c @@ -99,9 +99,9 @@ static int nilfs_prepare_chunk(struct page *page, NULL, nilfs_get_block); } -static int nilfs_commit_chunk(struct page *page, - struct address_space *mapping, - unsigned from, unsigned to) +static void nilfs_commit_chunk(struct page *page, + struct address_space *mapping, + unsigned from, unsigned to) { struct inode *dir = mapping->host; struct nilfs_sb_info *sbi = NILFS_SB(dir->i_sb); @@ -112,15 +112,13 @@ static int nilfs_commit_chunk(struct page *page, nr_dirty = nilfs_page_count_clean_buffers(page, from, to); copied = block_write_end(NULL, mapping, pos, len, len, page, NULL); - if (pos + copied > dir->i_size) { + if (pos + copied > dir->i_size) i_size_write(dir, pos + copied); - mark_inode_dirty(dir); - } if (IS_DIRSYNC(dir)) nilfs_set_transaction_flag(NILFS_TI_SYNC); err = nilfs_set_file_dirty(sbi, dir, nr_dirty); + WARN_ON(err); /* do not happen */ unlock_page(page); - return err; } static void nilfs_check_page(struct page *page) @@ -455,11 +453,10 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de, BUG_ON(err); de->inode = cpu_to_le64(inode->i_ino); nilfs_set_de_type(de, inode); - err = nilfs_commit_chunk(page, mapping, from, to); + nilfs_commit_chunk(page, mapping, from, to); nilfs_put_page(page); dir->i_mtime = dir->i_ctime = CURRENT_TIME; /* NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */ - mark_inode_dirty(dir); } /* @@ -548,10 +545,10 @@ got_it: memcpy(de->name, name, namelen); de->inode = cpu_to_le64(inode->i_ino); nilfs_set_de_type(de, inode); - err = nilfs_commit_chunk(page, page->mapping, from, to); + nilfs_commit_chunk(page, page->mapping, from, to); dir->i_mtime = dir->i_ctime = CURRENT_TIME; /* NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */ - mark_inode_dirty(dir); + nilfs_mark_inode_dirty(dir); /* OFFSET_CACHE */ out_put: nilfs_put_page(page); @@ -595,10 +592,9 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page) if (pde) pde->rec_len = cpu_to_le16(to - from); dir->inode = 0; - err = nilfs_commit_chunk(page, mapping, from, to); + nilfs_commit_chunk(page, mapping, from, to); inode->i_ctime = inode->i_mtime = CURRENT_TIME; /* NILFS_I(inode)->i_flags &= ~NILFS_BTREE_FL; */ - mark_inode_dirty(inode); out: nilfs_put_page(page); return err; @@ -640,7 +636,7 @@ int nilfs_make_empty(struct inode *inode, struct inode *parent) memcpy(de->name, "..\0", 4); nilfs_set_de_type(de, inode); kunmap_atomic(kaddr, KM_USER0); - err = nilfs_commit_chunk(page, mapping, 0, chunk_size); + nilfs_commit_chunk(page, mapping, 0, chunk_size); fail: page_cache_release(page); return err; diff --git a/fs/nilfs2/gcdat.c b/fs/nilfs2/gcdat.c index 93383c5cee90afb189e35b5f5cbca92ad39b3776..dd5f7e0a95f6657b28862c8a448e8d2506b4d851 100644 --- a/fs/nilfs2/gcdat.c +++ b/fs/nilfs2/gcdat.c @@ -61,6 +61,8 @@ void nilfs_commit_gcdat_inode(struct the_nilfs *nilfs) nilfs_bmap_commit_gcdat(gii->i_bmap, dii->i_bmap); + nilfs_palloc_clear_cache(dat); + nilfs_palloc_clear_cache(gcdat); nilfs_clear_dirty_pages(mapping); nilfs_copy_back_pages(mapping, gmapping); /* note: mdt dirty flags should be cleared by segctor. */ @@ -79,6 +81,7 @@ void nilfs_clear_gcdat_inode(struct the_nilfs *nilfs) gcdat->i_state = I_CLEAR; gii->i_flags = 0; + nilfs_palloc_clear_cache(gcdat); truncate_inode_pages(gcdat->i_mapping, 0); truncate_inode_pages(&gii->i_btnode_cache, 0); } diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c index e6de0a27ab5d7980076318ad6093c70548912311..e16a6664dfa2bf03d320379c2f2f93d7ebca71a3 100644 --- a/fs/nilfs2/gcinode.c +++ b/fs/nilfs2/gcinode.c @@ -149,7 +149,7 @@ int nilfs_gccache_submit_read_node(struct inode *inode, sector_t pbn, __u64 vbn, struct buffer_head **out_bh) { int ret = nilfs_btnode_submit_block(&NILFS_I(inode)->i_btnode_cache, - vbn ? : pbn, pbn, out_bh, 0); + vbn ? : pbn, pbn, out_bh); if (ret == -EEXIST) /* internal code (cache hit) */ ret = 0; return ret; @@ -212,9 +212,10 @@ void nilfs_destroy_gccache(struct the_nilfs *nilfs) static struct inode *alloc_gcinode(struct the_nilfs *nilfs, ino_t ino, __u64 cno) { - struct inode *inode = nilfs_mdt_new_common(nilfs, NULL, ino, GFP_NOFS); + struct inode *inode; struct nilfs_inode_info *ii; + inode = nilfs_mdt_new_common(nilfs, NULL, ino, GFP_NOFS, 0); if (!inode) return NULL; @@ -265,7 +266,6 @@ struct inode *nilfs_gc_iget(struct the_nilfs *nilfs, ino_t ino, __u64 cno) */ void nilfs_clear_gcinode(struct inode *inode) { - nilfs_mdt_clear(inode); nilfs_mdt_destroy(inode); } diff --git a/fs/nilfs2/ifile.c b/fs/nilfs2/ifile.c index de86401f209f57cdd712e62498c9c40be9a86744..922d9dd42c8fb352f6e024688c73f9ede88e6738 100644 --- a/fs/nilfs2/ifile.c +++ b/fs/nilfs2/ifile.c @@ -29,6 +29,17 @@ #include "alloc.h" #include "ifile.h" + +struct nilfs_ifile_info { + struct nilfs_mdt_info mi; + struct nilfs_palloc_cache palloc_cache; +}; + +static inline struct nilfs_ifile_info *NILFS_IFILE_I(struct inode *ifile) +{ + return (struct nilfs_ifile_info *)NILFS_MDT(ifile); +} + /** * nilfs_ifile_create_inode - create a new disk inode * @ifile: ifile inode @@ -148,3 +159,27 @@ int nilfs_ifile_get_inode_block(struct inode *ifile, ino_t ino, } return err; } + +/** + * nilfs_ifile_new - create inode file + * @sbi: nilfs_sb_info struct + * @inode_size: size of an inode + */ +struct inode *nilfs_ifile_new(struct nilfs_sb_info *sbi, size_t inode_size) +{ + struct inode *ifile; + int err; + + ifile = nilfs_mdt_new(sbi->s_nilfs, sbi->s_super, NILFS_IFILE_INO, + sizeof(struct nilfs_ifile_info)); + if (ifile) { + err = nilfs_palloc_init_blockgroup(ifile, inode_size); + if (unlikely(err)) { + nilfs_mdt_destroy(ifile); + return NULL; + } + nilfs_palloc_setup_cache(ifile, + &NILFS_IFILE_I(ifile)->palloc_cache); + } + return ifile; +} diff --git a/fs/nilfs2/ifile.h b/fs/nilfs2/ifile.h index ecc3ba76db475155f887f258d45cd0daf3b01341..cbca32e498f28204a9efc23866ae9280a3023812 100644 --- a/fs/nilfs2/ifile.h +++ b/fs/nilfs2/ifile.h @@ -49,4 +49,6 @@ int nilfs_ifile_create_inode(struct inode *, ino_t *, struct buffer_head **); int nilfs_ifile_delete_inode(struct inode *, ino_t); int nilfs_ifile_get_inode_block(struct inode *, ino_t, struct buffer_head **); +struct inode *nilfs_ifile_new(struct nilfs_sb_info *sbi, size_t inode_size); + #endif /* _NILFS_IFILE_H */ diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 2a0a5a3ac1346826b6f1c7ca668a5859b16a00dc..7868cc122ac764dba74d6d55f0305239ff91ed8f 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -97,6 +97,7 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff, nilfs_transaction_abort(inode->i_sb); goto out; } + nilfs_mark_inode_dirty(inode); nilfs_transaction_commit(inode->i_sb); /* never fails */ /* Error handling should be detailed */ set_buffer_new(bh_result); @@ -322,7 +323,6 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) nilfs_init_acl(), proper cancellation of above jobs should be considered */ - mark_inode_dirty(inode); return inode; failed_acl: @@ -525,7 +525,6 @@ void nilfs_update_inode(struct inode *inode, struct buffer_head *ibh) raw_inode = nilfs_ifile_map_inode(sbi->s_ifile, ino, ibh); - /* The buffer is guarded with lock_buffer() by the caller */ if (test_and_clear_bit(NILFS_I_NEW, &ii->i_state)) memset(raw_inode, 0, NILFS_MDT(sbi->s_ifile)->mi_entry_size); set_bit(NILFS_I_INODE_DIRTY, &ii->i_state); @@ -599,6 +598,7 @@ void nilfs_truncate(struct inode *inode) if (IS_SYNC(inode)) nilfs_set_transaction_flag(NILFS_TI_SYNC); + nilfs_mark_inode_dirty(inode); nilfs_set_file_dirty(NILFS_SB(sb), inode, 0); nilfs_transaction_commit(sb); /* May construct a logical segment and may fail in sync mode. @@ -623,6 +623,7 @@ void nilfs_delete_inode(struct inode *inode) truncate_inode_pages(&inode->i_data, 0); nilfs_truncate_bmap(ii, 0); + nilfs_mark_inode_dirty(inode); nilfs_free_inode(inode); /* nilfs_free_inode() marks inode buffer dirty */ if (IS_SYNC(inode)) @@ -745,9 +746,7 @@ int nilfs_mark_inode_dirty(struct inode *inode) "failed to reget inode block.\n"); return err; } - lock_buffer(ibh); nilfs_update_inode(inode, ibh); - unlock_buffer(ibh); nilfs_mdt_mark_buffer_dirty(ibh); nilfs_mdt_mark_dirty(sbi->s_ifile); brelse(ibh); diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index f6326112d647537c5ea0419d36ec4b73d466fbbd..06713ffcc7f2dc2f6a668e35c46e97e64be15884 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c @@ -186,7 +186,7 @@ nilfs_mdt_submit_block(struct inode *inode, unsigned long blkoff, } static int nilfs_mdt_read_block(struct inode *inode, unsigned long block, - struct buffer_head **out_bh) + int readahead, struct buffer_head **out_bh) { struct buffer_head *first_bh, *bh; unsigned long blkoff; @@ -200,16 +200,18 @@ static int nilfs_mdt_read_block(struct inode *inode, unsigned long block, if (unlikely(err)) goto failed; - blkoff = block + 1; - for (i = 0; i < nr_ra_blocks; i++, blkoff++) { - err = nilfs_mdt_submit_block(inode, blkoff, READA, &bh); - if (likely(!err || err == -EEXIST)) - brelse(bh); - else if (err != -EBUSY) - break; /* abort readahead if bmap lookup failed */ - - if (!buffer_locked(first_bh)) - goto out_no_wait; + if (readahead) { + blkoff = block + 1; + for (i = 0; i < nr_ra_blocks; i++, blkoff++) { + err = nilfs_mdt_submit_block(inode, blkoff, READA, &bh); + if (likely(!err || err == -EEXIST)) + brelse(bh); + else if (err != -EBUSY) + break; + /* abort readahead if bmap lookup failed */ + if (!buffer_locked(first_bh)) + goto out_no_wait; + } } wait_on_buffer(first_bh); @@ -263,7 +265,7 @@ int nilfs_mdt_get_block(struct inode *inode, unsigned long blkoff, int create, /* Should be rewritten with merging nilfs_mdt_read_block() */ retry: - ret = nilfs_mdt_read_block(inode, blkoff, out_bh); + ret = nilfs_mdt_read_block(inode, blkoff, !create, out_bh); if (!create || ret != -ENOENT) return ret; @@ -371,7 +373,7 @@ int nilfs_mdt_mark_block_dirty(struct inode *inode, unsigned long block) struct buffer_head *bh; int err; - err = nilfs_mdt_read_block(inode, block, &bh); + err = nilfs_mdt_read_block(inode, block, 0, &bh); if (unlikely(err)) return err; nilfs_mark_buffer_dirty(bh); @@ -445,9 +447,17 @@ static const struct file_operations def_mdt_fops; * longer than those of the super block structs; they may continue for * several consecutive mounts/umounts. This would need discussions. */ +/** + * nilfs_mdt_new_common - allocate a pseudo inode for metadata file + * @nilfs: nilfs object + * @sb: super block instance the metadata file belongs to + * @ino: inode number + * @gfp_mask: gfp mask for data pages + * @objsz: size of the private object attached to inode->i_private + */ struct inode * nilfs_mdt_new_common(struct the_nilfs *nilfs, struct super_block *sb, - ino_t ino, gfp_t gfp_mask) + ino_t ino, gfp_t gfp_mask, size_t objsz) { struct inode *inode = nilfs_alloc_inode_common(nilfs); @@ -455,8 +465,9 @@ nilfs_mdt_new_common(struct the_nilfs *nilfs, struct super_block *sb, return NULL; else { struct address_space * const mapping = &inode->i_data; - struct nilfs_mdt_info *mi = kzalloc(sizeof(*mi), GFP_NOFS); + struct nilfs_mdt_info *mi; + mi = kzalloc(max(sizeof(*mi), objsz), GFP_NOFS); if (!mi) { nilfs_destroy_inode(inode); return NULL; @@ -513,11 +524,11 @@ nilfs_mdt_new_common(struct the_nilfs *nilfs, struct super_block *sb, } struct inode *nilfs_mdt_new(struct the_nilfs *nilfs, struct super_block *sb, - ino_t ino) + ino_t ino, size_t objsz) { - struct inode *inode = nilfs_mdt_new_common(nilfs, sb, ino, - NILFS_MDT_GFP); + struct inode *inode; + inode = nilfs_mdt_new_common(nilfs, sb, ino, NILFS_MDT_GFP, objsz); if (!inode) return NULL; @@ -544,14 +555,15 @@ void nilfs_mdt_set_shadow(struct inode *orig, struct inode *shadow) &NILFS_I(orig)->i_btnode_cache; } -void nilfs_mdt_clear(struct inode *inode) +static void nilfs_mdt_clear(struct inode *inode) { struct nilfs_inode_info *ii = NILFS_I(inode); invalidate_mapping_pages(inode->i_mapping, 0, -1); truncate_inode_pages(inode->i_mapping, 0); - nilfs_bmap_clear(ii->i_bmap); + if (test_bit(NILFS_I_BMAP, &ii->i_state)) + nilfs_bmap_clear(ii->i_bmap); nilfs_btnode_cache_clear(&ii->i_btnode_cache); } @@ -559,6 +571,10 @@ void nilfs_mdt_destroy(struct inode *inode) { struct nilfs_mdt_info *mdi = NILFS_MDT(inode); + if (mdi->mi_palloc_cache) + nilfs_palloc_destroy_cache(inode); + nilfs_mdt_clear(inode); + kfree(mdi->mi_bgl); /* kfree(NULL) is safe */ kfree(mdi); nilfs_destroy_inode(inode); diff --git a/fs/nilfs2/mdt.h b/fs/nilfs2/mdt.h index 431599733c9b20e9479407590991f805633f36c6..6c4bbb0470fc10d71206f27c3f7181a80960e7de 100644 --- a/fs/nilfs2/mdt.h +++ b/fs/nilfs2/mdt.h @@ -36,6 +36,7 @@ * @mi_entry_size: size of an entry * @mi_first_entry_offset: offset to the first entry * @mi_entries_per_block: number of entries in a block + * @mi_palloc_cache: persistent object allocator cache * @mi_blocks_per_group: number of blocks in a group * @mi_blocks_per_desc_block: number of blocks per descriptor block */ @@ -46,6 +47,7 @@ struct nilfs_mdt_info { unsigned mi_entry_size; unsigned mi_first_entry_offset; unsigned long mi_entries_per_block; + struct nilfs_palloc_cache *mi_palloc_cache; unsigned long mi_blocks_per_group; unsigned long mi_blocks_per_desc_block; }; @@ -74,11 +76,11 @@ int nilfs_mdt_forget_block(struct inode *, unsigned long); int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long); int nilfs_mdt_fetch_dirty(struct inode *); -struct inode *nilfs_mdt_new(struct the_nilfs *, struct super_block *, ino_t); +struct inode *nilfs_mdt_new(struct the_nilfs *, struct super_block *, ino_t, + size_t); struct inode *nilfs_mdt_new_common(struct the_nilfs *, struct super_block *, - ino_t, gfp_t); + ino_t, gfp_t, size_t); void nilfs_mdt_destroy(struct inode *); -void nilfs_mdt_clear(struct inode *); void nilfs_mdt_set_entry_size(struct inode *, unsigned, unsigned); void nilfs_mdt_set_shadow(struct inode *, struct inode *); @@ -104,21 +106,4 @@ static inline __u64 nilfs_mdt_cno(struct inode *inode) #define nilfs_mdt_bgl_lock(inode, bg) \ (&NILFS_MDT(inode)->mi_bgl->locks[(bg) & (NR_BG_LOCKS-1)].lock) - -static inline int -nilfs_mdt_read_inode_direct(struct inode *inode, struct buffer_head *bh, - unsigned n) -{ - return nilfs_read_inode_common( - inode, (struct nilfs_inode *)(bh->b_data + n)); -} - -static inline void -nilfs_mdt_write_inode_direct(struct inode *inode, struct buffer_head *bh, - unsigned n) -{ - nilfs_write_inode_common( - inode, (struct nilfs_inode *)(bh->b_data + n), 1); -} - #endif /* _NILFS_MDT_H */ diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index ed02e886fa79ba8ad64d8f5180a3d1cc67e31541..07ba838ef089231d5ba387d9220bb16402c193a2 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c @@ -120,7 +120,7 @@ static int nilfs_create(struct inode *dir, struct dentry *dentry, int mode, inode->i_op = &nilfs_file_inode_operations; inode->i_fop = &nilfs_file_operations; inode->i_mapping->a_ops = &nilfs_aops; - mark_inode_dirty(inode); + nilfs_mark_inode_dirty(inode); err = nilfs_add_nondir(dentry, inode); } if (!err) @@ -148,7 +148,7 @@ nilfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, inode->i_mode, rdev); - mark_inode_dirty(inode); + nilfs_mark_inode_dirty(inode); err = nilfs_add_nondir(dentry, inode); } if (!err) @@ -188,7 +188,7 @@ static int nilfs_symlink(struct inode *dir, struct dentry *dentry, goto out_fail; /* mark_inode_dirty(inode); */ - /* nilfs_new_inode() and page_symlink() do this */ + /* page_symlink() do this */ err = nilfs_add_nondir(dentry, inode); out: @@ -200,7 +200,8 @@ out: return err; out_fail: - inode_dec_link_count(inode); + drop_nlink(inode); + nilfs_mark_inode_dirty(inode); iput(inode); goto out; } @@ -245,7 +246,7 @@ static int nilfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) if (err) return err; - inode_inc_link_count(dir); + inc_nlink(dir); inode = nilfs_new_inode(dir, S_IFDIR | mode); err = PTR_ERR(inode); @@ -256,7 +257,7 @@ static int nilfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) inode->i_fop = &nilfs_dir_operations; inode->i_mapping->a_ops = &nilfs_aops; - inode_inc_link_count(inode); + inc_nlink(inode); err = nilfs_make_empty(inode, dir); if (err) @@ -266,6 +267,7 @@ static int nilfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) if (err) goto out_fail; + nilfs_mark_inode_dirty(inode); d_instantiate(dentry, inode); out: if (!err) @@ -276,26 +278,23 @@ out: return err; out_fail: - inode_dec_link_count(inode); - inode_dec_link_count(inode); + drop_nlink(inode); + drop_nlink(inode); + nilfs_mark_inode_dirty(inode); iput(inode); out_dir: - inode_dec_link_count(dir); + drop_nlink(dir); + nilfs_mark_inode_dirty(dir); goto out; } -static int nilfs_unlink(struct inode *dir, struct dentry *dentry) +static int nilfs_do_unlink(struct inode *dir, struct dentry *dentry) { struct inode *inode; struct nilfs_dir_entry *de; struct page *page; - struct nilfs_transaction_info ti; int err; - err = nilfs_transaction_begin(dir->i_sb, &ti, 0); - if (err) - return err; - err = -ENOENT; de = nilfs_find_entry(dir, dentry, &page); if (!de) @@ -317,12 +316,28 @@ static int nilfs_unlink(struct inode *dir, struct dentry *dentry) goto out; inode->i_ctime = dir->i_ctime; - inode_dec_link_count(inode); + drop_nlink(inode); err = 0; out: - if (!err) + return err; +} + +static int nilfs_unlink(struct inode *dir, struct dentry *dentry) +{ + struct nilfs_transaction_info ti; + int err; + + err = nilfs_transaction_begin(dir->i_sb, &ti, 0); + if (err) + return err; + + err = nilfs_do_unlink(dir, dentry); + + if (!err) { + nilfs_mark_inode_dirty(dir); + nilfs_mark_inode_dirty(dentry->d_inode); err = nilfs_transaction_commit(dir->i_sb); - else + } else nilfs_transaction_abort(dir->i_sb); return err; @@ -340,11 +355,13 @@ static int nilfs_rmdir(struct inode *dir, struct dentry *dentry) err = -ENOTEMPTY; if (nilfs_empty_dir(inode)) { - err = nilfs_unlink(dir, dentry); + err = nilfs_do_unlink(dir, dentry); if (!err) { inode->i_size = 0; - inode_dec_link_count(inode); - inode_dec_link_count(dir); + drop_nlink(inode); + nilfs_mark_inode_dirty(inode); + drop_nlink(dir); + nilfs_mark_inode_dirty(dir); } } if (!err) @@ -395,42 +412,48 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry, new_de = nilfs_find_entry(new_dir, new_dentry, &new_page); if (!new_de) goto out_dir; - inode_inc_link_count(old_inode); + inc_nlink(old_inode); nilfs_set_link(new_dir, new_de, new_page, old_inode); + nilfs_mark_inode_dirty(new_dir); new_inode->i_ctime = CURRENT_TIME; if (dir_de) drop_nlink(new_inode); - inode_dec_link_count(new_inode); + drop_nlink(new_inode); + nilfs_mark_inode_dirty(new_inode); } else { if (dir_de) { err = -EMLINK; if (new_dir->i_nlink >= NILFS_LINK_MAX) goto out_dir; } - inode_inc_link_count(old_inode); + inc_nlink(old_inode); err = nilfs_add_link(new_dentry, old_inode); if (err) { - inode_dec_link_count(old_inode); + drop_nlink(old_inode); + nilfs_mark_inode_dirty(old_inode); goto out_dir; } - if (dir_de) - inode_inc_link_count(new_dir); + if (dir_de) { + inc_nlink(new_dir); + nilfs_mark_inode_dirty(new_dir); + } } /* * Like most other Unix systems, set the ctime for inodes on a * rename. - * inode_dec_link_count() will mark the inode dirty. */ old_inode->i_ctime = CURRENT_TIME; nilfs_delete_entry(old_de, old_page); - inode_dec_link_count(old_inode); + drop_nlink(old_inode); if (dir_de) { nilfs_set_link(old_inode, dir_de, dir_page, new_dir); - inode_dec_link_count(old_dir); + drop_nlink(old_dir); } + nilfs_mark_inode_dirty(old_dir); + nilfs_mark_inode_dirty(old_inode); err = nilfs_transaction_commit(old_dir->i_sb); return err; diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index 6dc83591d1182164c5fdaf4b27e92d20b794d4a6..c9c96c7825dc0e007d80bd1bc34004a3d86a051a 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c @@ -770,14 +770,8 @@ int nilfs_recover_logical_segments(struct the_nilfs *nilfs, nilfs_finish_roll_forward(nilfs, sbi, ri); } - nilfs_detach_checkpoint(sbi); - return 0; - failed: nilfs_detach_checkpoint(sbi); - nilfs_mdt_clear(nilfs->ns_cpfile); - nilfs_mdt_clear(nilfs->ns_sufile); - nilfs_mdt_clear(nilfs->ns_dat); return err; } @@ -804,6 +798,7 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, struct nilfs_segsum_info ssi; sector_t pseg_start, pseg_end, sr_pseg_start = 0; sector_t seg_start, seg_end; /* range of full segment (block number) */ + sector_t b, end; u64 seg_seq; __u64 segnum, nextnum = 0; __u64 cno; @@ -819,6 +814,11 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, /* Calculate range of segment */ nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); + /* Read ahead segment */ + b = seg_start; + while (b <= seg_end) + sb_breadahead(sbi->s_super, b++); + for (;;) { /* Load segment summary */ ret = load_segment_summary(sbi, pseg_start, seg_seq, &ssi, 1); @@ -841,14 +841,20 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, ri->ri_nextnum = nextnum; empty_seg = 0; + if (!NILFS_SEG_HAS_SR(&ssi) && !scan_newer) { + /* This will never happen because a superblock + (last_segment) always points to a pseg + having a super root. */ + ret = NILFS_SEG_FAIL_CONSISTENCY; + goto failed; + } + + if (pseg_start == seg_start) { + nilfs_get_segment_range(nilfs, nextnum, &b, &end); + while (b <= end) + sb_breadahead(sbi->s_super, b++); + } if (!NILFS_SEG_HAS_SR(&ssi)) { - if (!scan_newer) { - /* This will never happen because a superblock - (last_segment) always points to a pseg - having a super root. */ - ret = NILFS_SEG_FAIL_CONSISTENCY; - goto failed; - } if (!ri->ri_lsegs_start && NILFS_SEG_LOGBGN(&ssi)) { ri->ri_lsegs_start = pseg_start; ri->ri_lsegs_start_seq = seg_seq; @@ -919,7 +925,7 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, super_root_found: /* Updating pointers relating to the latest checkpoint */ - list_splice(&segments, ri->ri_used_segments.prev); + list_splice_tail(&segments, &ri->ri_used_segments); nilfs->ns_last_pseg = sr_pseg_start; nilfs->ns_last_seq = nilfs->ns_seg_seq; nilfs->ns_last_cno = ri->ri_cno; diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index e6d9e37fa241784c62400c0d4493185de97dd654..645c78656aa0e6f95c8e2c2b8dc5d2e7b24b48ea 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c @@ -24,10 +24,22 @@ #include #include #include +#include #include "page.h" #include "segbuf.h" +struct nilfs_write_info { + struct the_nilfs *nilfs; + struct bio *bio; + int start, end; /* The region to be submitted */ + int rest_blocks; + int max_pages; + int nr_vecs; + sector_t blocknr; +}; + + static struct kmem_cache *nilfs_segbuf_cachep; static void nilfs_segbuf_init_once(void *obj) @@ -63,6 +75,11 @@ struct nilfs_segment_buffer *nilfs_segbuf_new(struct super_block *sb) INIT_LIST_HEAD(&segbuf->sb_list); INIT_LIST_HEAD(&segbuf->sb_segsum_buffers); INIT_LIST_HEAD(&segbuf->sb_payload_buffers); + + init_completion(&segbuf->sb_bio_event); + atomic_set(&segbuf->sb_err, 0); + segbuf->sb_nbio = 0; + return segbuf; } @@ -83,6 +100,22 @@ void nilfs_segbuf_map(struct nilfs_segment_buffer *segbuf, __u64 segnum, segbuf->sb_fseg_end - segbuf->sb_pseg_start + 1; } +/** + * nilfs_segbuf_map_cont - map a new log behind a given log + * @segbuf: new segment buffer + * @prev: segment buffer containing a log to be continued + */ +void nilfs_segbuf_map_cont(struct nilfs_segment_buffer *segbuf, + struct nilfs_segment_buffer *prev) +{ + segbuf->sb_segnum = prev->sb_segnum; + segbuf->sb_fseg_start = prev->sb_fseg_start; + segbuf->sb_fseg_end = prev->sb_fseg_end; + segbuf->sb_pseg_start = prev->sb_pseg_start + prev->sb_sum.nblocks; + segbuf->sb_rest_blocks = + segbuf->sb_fseg_end - segbuf->sb_pseg_start + 1; +} + void nilfs_segbuf_set_next_segnum(struct nilfs_segment_buffer *segbuf, __u64 nextnum, struct the_nilfs *nilfs) { @@ -132,8 +165,6 @@ int nilfs_segbuf_reset(struct nilfs_segment_buffer *segbuf, unsigned flags, segbuf->sb_sum.sumbytes = sizeof(struct nilfs_segment_summary); segbuf->sb_sum.nfinfo = segbuf->sb_sum.nfileblk = 0; segbuf->sb_sum.ctime = ctime; - - segbuf->sb_io_error = 0; return 0; } @@ -219,7 +250,7 @@ void nilfs_segbuf_fill_in_data_crc(struct nilfs_segment_buffer *segbuf, raw_sum->ss_datasum = cpu_to_le32(crc); } -void nilfs_release_buffers(struct list_head *list) +static void nilfs_release_buffers(struct list_head *list) { struct buffer_head *bh, *n; @@ -241,13 +272,56 @@ void nilfs_release_buffers(struct list_head *list) } } +static void nilfs_segbuf_clear(struct nilfs_segment_buffer *segbuf) +{ + nilfs_release_buffers(&segbuf->sb_segsum_buffers); + nilfs_release_buffers(&segbuf->sb_payload_buffers); +} + +/* + * Iterators for segment buffers + */ +void nilfs_clear_logs(struct list_head *logs) +{ + struct nilfs_segment_buffer *segbuf; + + list_for_each_entry(segbuf, logs, sb_list) + nilfs_segbuf_clear(segbuf); +} + +void nilfs_truncate_logs(struct list_head *logs, + struct nilfs_segment_buffer *last) +{ + struct nilfs_segment_buffer *n, *segbuf; + + segbuf = list_prepare_entry(last, logs, sb_list); + list_for_each_entry_safe_continue(segbuf, n, logs, sb_list) { + list_del_init(&segbuf->sb_list); + nilfs_segbuf_clear(segbuf); + nilfs_segbuf_free(segbuf); + } +} + +int nilfs_wait_on_logs(struct list_head *logs) +{ + struct nilfs_segment_buffer *segbuf; + int err; + + list_for_each_entry(segbuf, logs, sb_list) { + err = nilfs_segbuf_wait(segbuf); + if (err) + return err; + } + return 0; +} + /* * BIO operations */ static void nilfs_end_bio_write(struct bio *bio, int err) { const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); - struct nilfs_write_info *wi = bio->bi_private; + struct nilfs_segment_buffer *segbuf = bio->bi_private; if (err == -EOPNOTSUPP) { set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); @@ -256,21 +330,22 @@ static void nilfs_end_bio_write(struct bio *bio, int err) } if (!uptodate) - atomic_inc(&wi->err); + atomic_inc(&segbuf->sb_err); bio_put(bio); - complete(&wi->bio_event); + complete(&segbuf->sb_bio_event); } -static int nilfs_submit_seg_bio(struct nilfs_write_info *wi, int mode) +static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer *segbuf, + struct nilfs_write_info *wi, int mode) { struct bio *bio = wi->bio; int err; - if (wi->nbio > 0 && bdi_write_congested(wi->bdi)) { - wait_for_completion(&wi->bio_event); - wi->nbio--; - if (unlikely(atomic_read(&wi->err))) { + if (segbuf->sb_nbio > 0 && bdi_write_congested(wi->nilfs->ns_bdi)) { + wait_for_completion(&segbuf->sb_bio_event); + segbuf->sb_nbio--; + if (unlikely(atomic_read(&segbuf->sb_err))) { bio_put(bio); err = -EIO; goto failed; @@ -278,7 +353,7 @@ static int nilfs_submit_seg_bio(struct nilfs_write_info *wi, int mode) } bio->bi_end_io = nilfs_end_bio_write; - bio->bi_private = wi; + bio->bi_private = segbuf; bio_get(bio); submit_bio(mode, bio); if (bio_flagged(bio, BIO_EOPNOTSUPP)) { @@ -286,7 +361,7 @@ static int nilfs_submit_seg_bio(struct nilfs_write_info *wi, int mode) err = -EOPNOTSUPP; goto failed; } - wi->nbio++; + segbuf->sb_nbio++; bio_put(bio); wi->bio = NULL; @@ -301,17 +376,15 @@ static int nilfs_submit_seg_bio(struct nilfs_write_info *wi, int mode) } /** - * nilfs_alloc_seg_bio - allocate a bio for writing segment. - * @sb: super block - * @start: beginning disk block number of this BIO. + * nilfs_alloc_seg_bio - allocate a new bio for writing log + * @nilfs: nilfs object + * @start: start block number of the bio * @nr_vecs: request size of page vector. * - * alloc_seg_bio() allocates a new BIO structure and initialize it. - * * Return Value: On success, pointer to the struct bio is returned. * On error, NULL is returned. */ -static struct bio *nilfs_alloc_seg_bio(struct super_block *sb, sector_t start, +static struct bio *nilfs_alloc_seg_bio(struct the_nilfs *nilfs, sector_t start, int nr_vecs) { struct bio *bio; @@ -322,36 +395,33 @@ static struct bio *nilfs_alloc_seg_bio(struct super_block *sb, sector_t start, bio = bio_alloc(GFP_NOIO, nr_vecs); } if (likely(bio)) { - bio->bi_bdev = sb->s_bdev; - bio->bi_sector = (sector_t)start << (sb->s_blocksize_bits - 9); + bio->bi_bdev = nilfs->ns_bdev; + bio->bi_sector = start << (nilfs->ns_blocksize_bits - 9); } return bio; } -void nilfs_segbuf_prepare_write(struct nilfs_segment_buffer *segbuf, - struct nilfs_write_info *wi) +static void nilfs_segbuf_prepare_write(struct nilfs_segment_buffer *segbuf, + struct nilfs_write_info *wi) { wi->bio = NULL; wi->rest_blocks = segbuf->sb_sum.nblocks; - wi->max_pages = bio_get_nr_vecs(wi->sb->s_bdev); + wi->max_pages = bio_get_nr_vecs(wi->nilfs->ns_bdev); wi->nr_vecs = min(wi->max_pages, wi->rest_blocks); wi->start = wi->end = 0; - wi->nbio = 0; wi->blocknr = segbuf->sb_pseg_start; - - atomic_set(&wi->err, 0); - init_completion(&wi->bio_event); } -static int nilfs_submit_bh(struct nilfs_write_info *wi, struct buffer_head *bh, - int mode) +static int nilfs_segbuf_submit_bh(struct nilfs_segment_buffer *segbuf, + struct nilfs_write_info *wi, + struct buffer_head *bh, int mode) { int len, err; BUG_ON(wi->nr_vecs <= 0); repeat: if (!wi->bio) { - wi->bio = nilfs_alloc_seg_bio(wi->sb, wi->blocknr + wi->end, + wi->bio = nilfs_alloc_seg_bio(wi->nilfs, wi->blocknr + wi->end, wi->nr_vecs); if (unlikely(!wi->bio)) return -ENOMEM; @@ -363,76 +433,83 @@ static int nilfs_submit_bh(struct nilfs_write_info *wi, struct buffer_head *bh, return 0; } /* bio is FULL */ - err = nilfs_submit_seg_bio(wi, mode); + err = nilfs_segbuf_submit_bio(segbuf, wi, mode); /* never submit current bh */ if (likely(!err)) goto repeat; return err; } +/** + * nilfs_segbuf_write - submit write requests of a log + * @segbuf: buffer storing a log to be written + * @nilfs: nilfs object + * + * Return Value: On Success, 0 is returned. On Error, one of the following + * negative error code is returned. + * + * %-EIO - I/O error + * + * %-ENOMEM - Insufficient memory available. + */ int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, - struct nilfs_write_info *wi) + struct the_nilfs *nilfs) { + struct nilfs_write_info wi; struct buffer_head *bh; - int res, rw = WRITE; + int res = 0, rw = WRITE; + + wi.nilfs = nilfs; + nilfs_segbuf_prepare_write(segbuf, &wi); list_for_each_entry(bh, &segbuf->sb_segsum_buffers, b_assoc_buffers) { - res = nilfs_submit_bh(wi, bh, rw); + res = nilfs_segbuf_submit_bh(segbuf, &wi, bh, rw); if (unlikely(res)) goto failed_bio; } list_for_each_entry(bh, &segbuf->sb_payload_buffers, b_assoc_buffers) { - res = nilfs_submit_bh(wi, bh, rw); + res = nilfs_segbuf_submit_bh(segbuf, &wi, bh, rw); if (unlikely(res)) goto failed_bio; } - if (wi->bio) { + if (wi.bio) { /* * Last BIO is always sent through the following * submission. */ rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG); - res = nilfs_submit_seg_bio(wi, rw); - if (unlikely(res)) - goto failed_bio; + res = nilfs_segbuf_submit_bio(segbuf, &wi, rw); } - res = 0; - out: - return res; - failed_bio: - atomic_inc(&wi->err); - goto out; + return res; } /** * nilfs_segbuf_wait - wait for completion of requested BIOs - * @wi: nilfs_write_info + * @segbuf: segment buffer * * Return Value: On Success, 0 is returned. On Error, one of the following * negative error code is returned. * * %-EIO - I/O error */ -int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf, - struct nilfs_write_info *wi) +int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf) { int err = 0; - if (!wi->nbio) + if (!segbuf->sb_nbio) return 0; do { - wait_for_completion(&wi->bio_event); - } while (--wi->nbio > 0); + wait_for_completion(&segbuf->sb_bio_event); + } while (--segbuf->sb_nbio > 0); - if (unlikely(atomic_read(&wi->err) > 0)) { + if (unlikely(atomic_read(&segbuf->sb_err) > 0)) { printk(KERN_ERR "NILFS: IO error writing segment\n"); err = -EIO; - segbuf->sb_io_error = 1; } return err; } diff --git a/fs/nilfs2/segbuf.h b/fs/nilfs2/segbuf.h index 0c3076f4e5926a53c745ad5454b023df0221438f..6af1630fb401fd088058c4abbde50d4bb592f036 100644 --- a/fs/nilfs2/segbuf.h +++ b/fs/nilfs2/segbuf.h @@ -27,7 +27,6 @@ #include #include #include -#include /** * struct nilfs_segsum_info - On-memory segment summary @@ -77,7 +76,9 @@ struct nilfs_segsum_info { * @sb_rest_blocks: Number of residual blocks in the current segment * @sb_segsum_buffers: List of buffers for segment summaries * @sb_payload_buffers: List of buffers for segment payload - * @sb_io_error: I/O error status + * @sb_nbio: Number of flying bio requests + * @sb_err: I/O error status + * @sb_bio_event: Completion event of log writing */ struct nilfs_segment_buffer { struct super_block *sb_super; @@ -96,7 +97,9 @@ struct nilfs_segment_buffer { struct list_head sb_payload_buffers; /* including super root */ /* io status */ - int sb_io_error; + int sb_nbio; + atomic_t sb_err; + struct completion sb_bio_event; }; #define NILFS_LIST_SEGBUF(head) \ @@ -125,6 +128,8 @@ struct nilfs_segment_buffer *nilfs_segbuf_new(struct super_block *); void nilfs_segbuf_free(struct nilfs_segment_buffer *); void nilfs_segbuf_map(struct nilfs_segment_buffer *, __u64, unsigned long, struct the_nilfs *); +void nilfs_segbuf_map_cont(struct nilfs_segment_buffer *segbuf, + struct nilfs_segment_buffer *prev); void nilfs_segbuf_set_next_segnum(struct nilfs_segment_buffer *, __u64, struct the_nilfs *); int nilfs_segbuf_reset(struct nilfs_segment_buffer *, unsigned, time_t); @@ -161,41 +166,18 @@ nilfs_segbuf_add_file_buffer(struct nilfs_segment_buffer *segbuf, segbuf->sb_sum.nfileblk++; } -void nilfs_release_buffers(struct list_head *); +int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, + struct the_nilfs *nilfs); +int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf); -static inline void nilfs_segbuf_clear(struct nilfs_segment_buffer *segbuf) +void nilfs_clear_logs(struct list_head *logs); +void nilfs_truncate_logs(struct list_head *logs, + struct nilfs_segment_buffer *last); +int nilfs_wait_on_logs(struct list_head *logs); + +static inline void nilfs_destroy_logs(struct list_head *logs) { - nilfs_release_buffers(&segbuf->sb_segsum_buffers); - nilfs_release_buffers(&segbuf->sb_payload_buffers); + nilfs_truncate_logs(logs, NULL); } -struct nilfs_write_info { - struct bio *bio; - int start, end; /* The region to be submitted */ - int rest_blocks; - int max_pages; - int nr_vecs; - sector_t blocknr; - - int nbio; - atomic_t err; - struct completion bio_event; - /* completion event of segment write */ - - /* - * The following fields must be set explicitly - */ - struct super_block *sb; - struct backing_dev_info *bdi; /* backing dev info */ - struct buffer_head *bh_sr; -}; - - -void nilfs_segbuf_prepare_write(struct nilfs_segment_buffer *, - struct nilfs_write_info *); -int nilfs_segbuf_write(struct nilfs_segment_buffer *, - struct nilfs_write_info *); -int nilfs_segbuf_wait(struct nilfs_segment_buffer *, - struct nilfs_write_info *); - #endif /* _NILFS_SEGBUF_H */ diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 6eff66a070d5e39c23a8c2af4f51f6b62ba91881..17584c524486c1b732c78d181ec7fb8d61ee1989 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -974,12 +974,12 @@ static void nilfs_segctor_fill_in_super_root(struct nilfs_sc_info *sci, nilfs->ns_nongc_ctime : sci->sc_seg_ctime); raw_sr->sr_flags = 0; - nilfs_mdt_write_inode_direct( - nilfs_dat_inode(nilfs), bh_sr, NILFS_SR_DAT_OFFSET(isz)); - nilfs_mdt_write_inode_direct( - nilfs->ns_cpfile, bh_sr, NILFS_SR_CPFILE_OFFSET(isz)); - nilfs_mdt_write_inode_direct( - nilfs->ns_sufile, bh_sr, NILFS_SR_SUFILE_OFFSET(isz)); + nilfs_write_inode_common(nilfs_dat_inode(nilfs), (void *)raw_sr + + NILFS_SR_DAT_OFFSET(isz), 1); + nilfs_write_inode_common(nilfs->ns_cpfile, (void *)raw_sr + + NILFS_SR_CPFILE_OFFSET(isz), 1); + nilfs_write_inode_common(nilfs->ns_sufile, (void *)raw_sr + + NILFS_SR_SUFILE_OFFSET(isz), 1); } static void nilfs_redirty_inodes(struct list_head *head) @@ -1273,73 +1273,75 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) return err; } -static int nilfs_touch_segusage(struct inode *sufile, __u64 segnum) -{ - struct buffer_head *bh_su; - struct nilfs_segment_usage *raw_su; - int err; - - err = nilfs_sufile_get_segment_usage(sufile, segnum, &raw_su, &bh_su); - if (unlikely(err)) - return err; - nilfs_mdt_mark_buffer_dirty(bh_su); - nilfs_mdt_mark_dirty(sufile); - nilfs_sufile_put_segment_usage(sufile, segnum, bh_su); - return 0; -} - +/** + * nilfs_segctor_begin_construction - setup segment buffer to make a new log + * @sci: nilfs_sc_info + * @nilfs: nilfs object + */ static int nilfs_segctor_begin_construction(struct nilfs_sc_info *sci, struct the_nilfs *nilfs) { - struct nilfs_segment_buffer *segbuf, *n; + struct nilfs_segment_buffer *segbuf, *prev; __u64 nextnum; - int err; + int err, alloc = 0; - if (list_empty(&sci->sc_segbufs)) { - segbuf = nilfs_segbuf_new(sci->sc_super); - if (unlikely(!segbuf)) - return -ENOMEM; - list_add(&segbuf->sb_list, &sci->sc_segbufs); - } else - segbuf = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); + segbuf = nilfs_segbuf_new(sci->sc_super); + if (unlikely(!segbuf)) + return -ENOMEM; + + if (list_empty(&sci->sc_write_logs)) { + nilfs_segbuf_map(segbuf, nilfs->ns_segnum, + nilfs->ns_pseg_offset, nilfs); + if (segbuf->sb_rest_blocks < NILFS_PSEG_MIN_BLOCKS) { + nilfs_shift_to_next_segment(nilfs); + nilfs_segbuf_map(segbuf, nilfs->ns_segnum, 0, nilfs); + } - nilfs_segbuf_map(segbuf, nilfs->ns_segnum, nilfs->ns_pseg_offset, - nilfs); + segbuf->sb_sum.seg_seq = nilfs->ns_seg_seq; + nextnum = nilfs->ns_nextnum; - if (segbuf->sb_rest_blocks < NILFS_PSEG_MIN_BLOCKS) { - nilfs_shift_to_next_segment(nilfs); - nilfs_segbuf_map(segbuf, nilfs->ns_segnum, 0, nilfs); + if (nilfs->ns_segnum == nilfs->ns_nextnum) + /* Start from the head of a new full segment */ + alloc++; + } else { + /* Continue logs */ + prev = NILFS_LAST_SEGBUF(&sci->sc_write_logs); + nilfs_segbuf_map_cont(segbuf, prev); + segbuf->sb_sum.seg_seq = prev->sb_sum.seg_seq; + nextnum = prev->sb_nextnum; + + if (segbuf->sb_rest_blocks < NILFS_PSEG_MIN_BLOCKS) { + nilfs_segbuf_map(segbuf, prev->sb_nextnum, 0, nilfs); + segbuf->sb_sum.seg_seq++; + alloc++; + } } - sci->sc_segbuf_nblocks = segbuf->sb_rest_blocks; - err = nilfs_touch_segusage(nilfs->ns_sufile, segbuf->sb_segnum); - if (unlikely(err)) - return err; + err = nilfs_sufile_mark_dirty(nilfs->ns_sufile, segbuf->sb_segnum); + if (err) + goto failed; - if (nilfs->ns_segnum == nilfs->ns_nextnum) { - /* Start from the head of a new full segment */ + if (alloc) { err = nilfs_sufile_alloc(nilfs->ns_sufile, &nextnum); - if (unlikely(err)) - return err; - } else - nextnum = nilfs->ns_nextnum; - - segbuf->sb_sum.seg_seq = nilfs->ns_seg_seq; + if (err) + goto failed; + } nilfs_segbuf_set_next_segnum(segbuf, nextnum, nilfs); - /* truncating segment buffers */ - list_for_each_entry_safe_continue(segbuf, n, &sci->sc_segbufs, - sb_list) { - list_del_init(&segbuf->sb_list); - nilfs_segbuf_free(segbuf); - } + BUG_ON(!list_empty(&sci->sc_segbufs)); + list_add_tail(&segbuf->sb_list, &sci->sc_segbufs); + sci->sc_segbuf_nblocks = segbuf->sb_rest_blocks; return 0; + + failed: + nilfs_segbuf_free(segbuf); + return err; } static int nilfs_segctor_extend_segments(struct nilfs_sc_info *sci, struct the_nilfs *nilfs, int nadd) { - struct nilfs_segment_buffer *segbuf, *prev, *n; + struct nilfs_segment_buffer *segbuf, *prev; struct inode *sufile = nilfs->ns_sufile; __u64 nextnextnum; LIST_HEAD(list); @@ -1352,7 +1354,7 @@ static int nilfs_segctor_extend_segments(struct nilfs_sc_info *sci, * not be dirty. The following call ensures that the buffer is dirty * and will pin the buffer on memory until the sufile is written. */ - err = nilfs_touch_segusage(sufile, prev->sb_nextnum); + err = nilfs_sufile_mark_dirty(sufile, prev->sb_nextnum); if (unlikely(err)) return err; @@ -1378,33 +1380,33 @@ static int nilfs_segctor_extend_segments(struct nilfs_sc_info *sci, list_add_tail(&segbuf->sb_list, &list); prev = segbuf; } - list_splice(&list, sci->sc_segbufs.prev); + list_splice_tail(&list, &sci->sc_segbufs); return 0; failed_segbuf: nilfs_segbuf_free(segbuf); failed: - list_for_each_entry_safe(segbuf, n, &list, sb_list) { + list_for_each_entry(segbuf, &list, sb_list) { ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum); WARN_ON(ret); /* never fails */ - list_del_init(&segbuf->sb_list); - nilfs_segbuf_free(segbuf); } + nilfs_destroy_logs(&list); return err; } -static void nilfs_segctor_free_incomplete_segments(struct nilfs_sc_info *sci, - struct the_nilfs *nilfs) +static void nilfs_free_incomplete_logs(struct list_head *logs, + struct the_nilfs *nilfs) { - struct nilfs_segment_buffer *segbuf; - int ret, done = 0; + struct nilfs_segment_buffer *segbuf, *prev; + struct inode *sufile = nilfs->ns_sufile; + int ret; - segbuf = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); + segbuf = NILFS_FIRST_SEGBUF(logs); if (nilfs->ns_nextnum != segbuf->sb_nextnum) { - ret = nilfs_sufile_free(nilfs->ns_sufile, segbuf->sb_nextnum); + ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum); WARN_ON(ret); /* never fails */ } - if (segbuf->sb_io_error) { + if (atomic_read(&segbuf->sb_err)) { /* Case 1: The first segment failed */ if (segbuf->sb_pseg_start != segbuf->sb_fseg_start) /* Case 1a: Partial segment appended into an existing @@ -1413,106 +1415,54 @@ static void nilfs_segctor_free_incomplete_segments(struct nilfs_sc_info *sci, segbuf->sb_fseg_end); else /* Case 1b: New full segment */ set_nilfs_discontinued(nilfs); - done++; } - list_for_each_entry_continue(segbuf, &sci->sc_segbufs, sb_list) { - ret = nilfs_sufile_free(nilfs->ns_sufile, segbuf->sb_nextnum); - WARN_ON(ret); /* never fails */ - if (!done && segbuf->sb_io_error) { - if (segbuf->sb_segnum != nilfs->ns_nextnum) - /* Case 2: extended segment (!= next) failed */ - nilfs_sufile_set_error(nilfs->ns_sufile, - segbuf->sb_segnum); - done++; - } - } -} - -static void nilfs_segctor_clear_segment_buffers(struct nilfs_sc_info *sci) -{ - struct nilfs_segment_buffer *segbuf; - - list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) - nilfs_segbuf_clear(segbuf); - sci->sc_super_root = NULL; -} - -static void nilfs_segctor_destroy_segment_buffers(struct nilfs_sc_info *sci) -{ - struct nilfs_segment_buffer *segbuf; - - while (!list_empty(&sci->sc_segbufs)) { - segbuf = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); - list_del_init(&segbuf->sb_list); - nilfs_segbuf_free(segbuf); - } - /* sci->sc_curseg = NULL; */ -} - -static void nilfs_segctor_end_construction(struct nilfs_sc_info *sci, - struct the_nilfs *nilfs, int err) -{ - if (unlikely(err)) { - nilfs_segctor_free_incomplete_segments(sci, nilfs); - if (sci->sc_stage.flags & NILFS_CF_SUFREED) { - int ret; - - ret = nilfs_sufile_cancel_freev(nilfs->ns_sufile, - sci->sc_freesegs, - sci->sc_nfreesegs, - NULL); - WARN_ON(ret); /* do not happen */ + prev = segbuf; + list_for_each_entry_continue(segbuf, logs, sb_list) { + if (prev->sb_nextnum != segbuf->sb_nextnum) { + ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum); + WARN_ON(ret); /* never fails */ } + if (atomic_read(&segbuf->sb_err) && + segbuf->sb_segnum != nilfs->ns_nextnum) + /* Case 2: extended segment (!= next) failed */ + nilfs_sufile_set_error(sufile, segbuf->sb_segnum); + prev = segbuf; } - nilfs_segctor_clear_segment_buffers(sci); } static void nilfs_segctor_update_segusage(struct nilfs_sc_info *sci, struct inode *sufile) { struct nilfs_segment_buffer *segbuf; - struct buffer_head *bh_su; - struct nilfs_segment_usage *raw_su; unsigned long live_blocks; int ret; list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { - ret = nilfs_sufile_get_segment_usage(sufile, segbuf->sb_segnum, - &raw_su, &bh_su); - WARN_ON(ret); /* always succeed because bh_su is dirty */ live_blocks = segbuf->sb_sum.nblocks + (segbuf->sb_pseg_start - segbuf->sb_fseg_start); - raw_su->su_lastmod = cpu_to_le64(sci->sc_seg_ctime); - raw_su->su_nblocks = cpu_to_le32(live_blocks); - nilfs_sufile_put_segment_usage(sufile, segbuf->sb_segnum, - bh_su); + ret = nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum, + live_blocks, + sci->sc_seg_ctime); + WARN_ON(ret); /* always succeed because the segusage is dirty */ } } -static void nilfs_segctor_cancel_segusage(struct nilfs_sc_info *sci, - struct inode *sufile) +static void nilfs_cancel_segusage(struct list_head *logs, struct inode *sufile) { struct nilfs_segment_buffer *segbuf; - struct buffer_head *bh_su; - struct nilfs_segment_usage *raw_su; int ret; - segbuf = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); - ret = nilfs_sufile_get_segment_usage(sufile, segbuf->sb_segnum, - &raw_su, &bh_su); - WARN_ON(ret); /* always succeed because bh_su is dirty */ - raw_su->su_nblocks = cpu_to_le32(segbuf->sb_pseg_start - - segbuf->sb_fseg_start); - nilfs_sufile_put_segment_usage(sufile, segbuf->sb_segnum, bh_su); + segbuf = NILFS_FIRST_SEGBUF(logs); + ret = nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum, + segbuf->sb_pseg_start - + segbuf->sb_fseg_start, 0); + WARN_ON(ret); /* always succeed because the segusage is dirty */ - list_for_each_entry_continue(segbuf, &sci->sc_segbufs, sb_list) { - ret = nilfs_sufile_get_segment_usage(sufile, segbuf->sb_segnum, - &raw_su, &bh_su); + list_for_each_entry_continue(segbuf, logs, sb_list) { + ret = nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum, + 0, 0); WARN_ON(ret); /* always succeed */ - raw_su->su_nblocks = 0; - nilfs_sufile_put_segment_usage(sufile, segbuf->sb_segnum, - bh_su); } } @@ -1520,17 +1470,15 @@ static void nilfs_segctor_truncate_segments(struct nilfs_sc_info *sci, struct nilfs_segment_buffer *last, struct inode *sufile) { - struct nilfs_segment_buffer *segbuf = last, *n; + struct nilfs_segment_buffer *segbuf = last; int ret; - list_for_each_entry_safe_continue(segbuf, n, &sci->sc_segbufs, - sb_list) { - list_del_init(&segbuf->sb_list); + list_for_each_entry_continue(segbuf, &sci->sc_segbufs, sb_list) { sci->sc_segbuf_nblocks -= segbuf->sb_rest_blocks; ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum); WARN_ON(ret); - nilfs_segbuf_free(segbuf); } + nilfs_truncate_logs(&sci->sc_segbufs, last); } @@ -1569,7 +1517,7 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci, NULL); WARN_ON(err); /* do not happen */ } - nilfs_segctor_clear_segment_buffers(sci); + nilfs_clear_logs(&sci->sc_segbufs); err = nilfs_segctor_extend_segments(sci, nilfs, nadd); if (unlikely(err)) @@ -1814,26 +1762,18 @@ static int nilfs_segctor_prepare_write(struct nilfs_sc_info *sci, } static int nilfs_segctor_write(struct nilfs_sc_info *sci, - struct backing_dev_info *bdi) + struct the_nilfs *nilfs) { struct nilfs_segment_buffer *segbuf; - struct nilfs_write_info wi; - int err, res; - - wi.sb = sci->sc_super; - wi.bh_sr = sci->sc_super_root; - wi.bdi = bdi; + int ret = 0; list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { - nilfs_segbuf_prepare_write(segbuf, &wi); - err = nilfs_segbuf_write(segbuf, &wi); - - res = nilfs_segbuf_wait(segbuf, &wi); - err = err ? : res; - if (err) - return err; + ret = nilfs_segbuf_write(segbuf, nilfs); + if (ret) + break; } - return 0; + list_splice_tail_init(&sci->sc_segbufs, &sci->sc_write_logs); + return ret; } static void __nilfs_end_page_io(struct page *page, int err) @@ -1911,15 +1851,17 @@ static void nilfs_clear_copied_buffers(struct list_head *list, int err) } } -static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci, - struct page *failed_page, int err) +static void nilfs_abort_logs(struct list_head *logs, struct page *failed_page, + struct buffer_head *bh_sr, int err) { struct nilfs_segment_buffer *segbuf; struct page *bd_page = NULL, *fs_page = NULL; + struct buffer_head *bh; - list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { - struct buffer_head *bh; + if (list_empty(logs)) + return; + list_for_each_entry(segbuf, logs, sb_list) { list_for_each_entry(bh, &segbuf->sb_segsum_buffers, b_assoc_buffers) { if (bh->b_page != bd_page) { @@ -1931,7 +1873,7 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci, list_for_each_entry(bh, &segbuf->sb_payload_buffers, b_assoc_buffers) { - if (bh == sci->sc_super_root) { + if (bh == bh_sr) { if (bh->b_page != bd_page) { end_page_writeback(bd_page); bd_page = bh->b_page; @@ -1941,7 +1883,7 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci, if (bh->b_page != fs_page) { nilfs_end_page_io(fs_page, err); if (fs_page && fs_page == failed_page) - goto done; + return; fs_page = bh->b_page; } } @@ -1950,8 +1892,34 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci, end_page_writeback(bd_page); nilfs_end_page_io(fs_page, err); - done: +} + +static void nilfs_segctor_abort_construction(struct nilfs_sc_info *sci, + struct the_nilfs *nilfs, int err) +{ + LIST_HEAD(logs); + int ret; + + list_splice_tail_init(&sci->sc_write_logs, &logs); + ret = nilfs_wait_on_logs(&logs); + if (ret) + nilfs_abort_logs(&logs, NULL, sci->sc_super_root, ret); + + list_splice_tail_init(&sci->sc_segbufs, &logs); + nilfs_cancel_segusage(&logs, nilfs->ns_sufile); + nilfs_free_incomplete_logs(&logs, nilfs); nilfs_clear_copied_buffers(&sci->sc_copied_buffers, err); + + if (sci->sc_stage.flags & NILFS_CF_SUFREED) { + ret = nilfs_sufile_cancel_freev(nilfs->ns_sufile, + sci->sc_freesegs, + sci->sc_nfreesegs, + NULL); + WARN_ON(ret); /* do not happen */ + } + + nilfs_destroy_logs(&logs); + sci->sc_super_root = NULL; } static void nilfs_set_next_segment(struct the_nilfs *nilfs, @@ -1973,7 +1941,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) struct the_nilfs *nilfs = sbi->s_nilfs; int update_sr = (sci->sc_super_root != NULL); - list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { + list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) { struct buffer_head *bh; list_for_each_entry(bh, &segbuf->sb_segsum_buffers, @@ -2046,7 +2014,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) sci->sc_nblk_inc += sci->sc_nblk_this_inc; - segbuf = NILFS_LAST_SEGBUF(&sci->sc_segbufs); + segbuf = NILFS_LAST_SEGBUF(&sci->sc_write_logs); nilfs_set_next_segment(nilfs, segbuf); if (update_sr) { @@ -2057,10 +2025,23 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) clear_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags); clear_bit(NILFS_SC_DIRTY, &sci->sc_flags); set_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags); + nilfs_segctor_clear_metadata_dirty(sci); } else clear_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags); } +static int nilfs_segctor_wait(struct nilfs_sc_info *sci) +{ + int ret; + + ret = nilfs_wait_on_logs(&sci->sc_write_logs); + if (!ret) { + nilfs_segctor_complete_write(sci); + nilfs_destroy_logs(&sci->sc_write_logs); + } + return ret; +} + static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, struct nilfs_sb_info *sbi) { @@ -2173,7 +2154,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) /* Avoid empty segment */ if (sci->sc_stage.scnt == NILFS_ST_DONE && NILFS_SEG_EMPTY(&sci->sc_curseg->sb_sum)) { - nilfs_segctor_end_construction(sci, nilfs, 1); + nilfs_segctor_abort_construction(sci, nilfs, 1); goto out; } @@ -2187,7 +2168,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) if (has_sr) { err = nilfs_segctor_fill_in_checkpoint(sci); if (unlikely(err)) - goto failed_to_make_up; + goto failed_to_write; nilfs_segctor_fill_in_super_root(sci, nilfs); } @@ -2195,42 +2176,46 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) /* Write partial segments */ err = nilfs_segctor_prepare_write(sci, &failed_page); - if (unlikely(err)) + if (err) { + nilfs_abort_logs(&sci->sc_segbufs, failed_page, + sci->sc_super_root, err); goto failed_to_write; - + } nilfs_segctor_fill_in_checksums(sci, nilfs->ns_crc_seed); - err = nilfs_segctor_write(sci, nilfs->ns_bdi); + err = nilfs_segctor_write(sci, nilfs); if (unlikely(err)) goto failed_to_write; - nilfs_segctor_complete_write(sci); - - /* Commit segments */ - if (has_sr) - nilfs_segctor_clear_metadata_dirty(sci); - - nilfs_segctor_end_construction(sci, nilfs, 0); - + if (sci->sc_stage.scnt == NILFS_ST_DONE || + nilfs->ns_blocksize_bits != PAGE_CACHE_SHIFT) { + /* + * At this point, we avoid double buffering + * for blocksize < pagesize because page dirty + * flag is turned off during write and dirty + * buffers are not properly collected for + * pages crossing over segments. + */ + err = nilfs_segctor_wait(sci); + if (err) + goto failed_to_write; + } } while (sci->sc_stage.scnt != NILFS_ST_DONE); + sci->sc_super_root = NULL; + out: - nilfs_segctor_destroy_segment_buffers(sci); nilfs_segctor_check_out_files(sci, sbi); return err; failed_to_write: - nilfs_segctor_abort_write(sci, failed_page, err); - nilfs_segctor_cancel_segusage(sci, nilfs->ns_sufile); - - failed_to_make_up: if (sci->sc_stage.flags & NILFS_CF_IFILE_STARTED) nilfs_redirty_inodes(&sci->sc_dirty_files); failed: if (nilfs_doing_gc()) nilfs_redirty_inodes(&sci->sc_gc_inodes); - nilfs_segctor_end_construction(sci, nilfs, err); + nilfs_segctor_abort_construction(sci, nilfs, err); goto out; } @@ -2559,7 +2544,7 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, sci->sc_freesegs = kbufs[4]; sci->sc_nfreesegs = argv[4].v_nmembs; - list_splice_init(&nilfs->ns_gc_inodes, sci->sc_gc_inodes.prev); + list_splice_tail_init(&nilfs->ns_gc_inodes, &sci->sc_gc_inodes); for (;;) { nilfs_segctor_accept(sci, &req); @@ -2788,6 +2773,7 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi) spin_lock_init(&sci->sc_state_lock); INIT_LIST_HEAD(&sci->sc_dirty_files); INIT_LIST_HEAD(&sci->sc_segbufs); + INIT_LIST_HEAD(&sci->sc_write_logs); INIT_LIST_HEAD(&sci->sc_gc_inodes); INIT_LIST_HEAD(&sci->sc_copied_buffers); @@ -2855,6 +2841,7 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) } WARN_ON(!list_empty(&sci->sc_segbufs)); + WARN_ON(!list_empty(&sci->sc_write_logs)); down_write(&sbi->s_nilfs->ns_segctor_sem); diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index 0d2a475a741b764cc352bf3e0a305b5fcced30ae..3d3ab2f9864ce52605ec6eb1d40a4ce4aa025889 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h @@ -97,6 +97,7 @@ struct nilfs_segsum_pointer { * @sc_dsync_start: start byte offset of data pages * @sc_dsync_end: end byte offset of data pages (inclusive) * @sc_segbufs: List of segment buffers + * @sc_write_logs: List of segment buffers to hold logs under writing * @sc_segbuf_nblocks: Number of available blocks in segment buffers. * @sc_curseg: Current segment buffer * @sc_super_root: Pointer to the super root buffer @@ -143,6 +144,7 @@ struct nilfs_sc_info { /* Segment buffers */ struct list_head sc_segbufs; + struct list_head sc_write_logs; unsigned long sc_segbuf_nblocks; struct nilfs_segment_buffer *sc_curseg; struct buffer_head *sc_super_root; diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c index 37994d4a59cc95a6f70ae097d850adeab376fc67..b6c36d0cc331542abb62166f8cb73a3fde6e7265 100644 --- a/fs/nilfs2/sufile.c +++ b/fs/nilfs2/sufile.c @@ -31,6 +31,16 @@ #include "sufile.h" +struct nilfs_sufile_info { + struct nilfs_mdt_info mi; + unsigned long ncleansegs; +}; + +static inline struct nilfs_sufile_info *NILFS_SUI(struct inode *sufile) +{ + return (struct nilfs_sufile_info *)NILFS_MDT(sufile); +} + static inline unsigned long nilfs_sufile_segment_usages_per_block(const struct inode *sufile) { @@ -62,14 +72,6 @@ nilfs_sufile_segment_usages_in_block(const struct inode *sufile, __u64 curr, max - curr + 1); } -static inline struct nilfs_sufile_header * -nilfs_sufile_block_get_header(const struct inode *sufile, - struct buffer_head *bh, - void *kaddr) -{ - return kaddr + bh_offset(bh); -} - static struct nilfs_segment_usage * nilfs_sufile_block_get_segment_usage(const struct inode *sufile, __u64 segnum, struct buffer_head *bh, void *kaddr) @@ -109,6 +111,15 @@ static void nilfs_sufile_mod_counter(struct buffer_head *header_bh, nilfs_mdt_mark_buffer_dirty(header_bh); } +/** + * nilfs_sufile_get_ncleansegs - return the number of clean segments + * @sufile: inode of segment usage file + */ +unsigned long nilfs_sufile_get_ncleansegs(struct inode *sufile) +{ + return NILFS_SUI(sufile)->ncleansegs; +} + /** * nilfs_sufile_updatev - modify multiple segment usages at a time * @sufile: inode of segment usage file @@ -270,7 +281,7 @@ int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump) if (ret < 0) goto out_sem; kaddr = kmap_atomic(header_bh->b_page, KM_USER0); - header = nilfs_sufile_block_get_header(sufile, header_bh, kaddr); + header = kaddr + bh_offset(header_bh); ncleansegs = le64_to_cpu(header->sh_ncleansegs); last_alloc = le64_to_cpu(header->sh_last_alloc); kunmap_atomic(kaddr, KM_USER0); @@ -302,13 +313,13 @@ int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump) kunmap_atomic(kaddr, KM_USER0); kaddr = kmap_atomic(header_bh->b_page, KM_USER0); - header = nilfs_sufile_block_get_header( - sufile, header_bh, kaddr); + header = kaddr + bh_offset(header_bh); le64_add_cpu(&header->sh_ncleansegs, -1); le64_add_cpu(&header->sh_ndirtysegs, 1); header->sh_last_alloc = cpu_to_le64(segnum); kunmap_atomic(kaddr, KM_USER0); + NILFS_SUI(sufile)->ncleansegs--; nilfs_mdt_mark_buffer_dirty(header_bh); nilfs_mdt_mark_buffer_dirty(su_bh); nilfs_mdt_mark_dirty(sufile); @@ -351,6 +362,8 @@ void nilfs_sufile_do_cancel_free(struct inode *sufile, __u64 segnum, kunmap_atomic(kaddr, KM_USER0); nilfs_sufile_mod_counter(header_bh, -1, 1); + NILFS_SUI(sufile)->ncleansegs--; + nilfs_mdt_mark_buffer_dirty(su_bh); nilfs_mdt_mark_dirty(sufile); } @@ -380,6 +393,8 @@ void nilfs_sufile_do_scrap(struct inode *sufile, __u64 segnum, kunmap_atomic(kaddr, KM_USER0); nilfs_sufile_mod_counter(header_bh, clean ? (u64)-1 : 0, dirty ? 0 : 1); + NILFS_SUI(sufile)->ncleansegs -= clean; + nilfs_mdt_mark_buffer_dirty(su_bh); nilfs_mdt_mark_dirty(sufile); } @@ -409,79 +424,65 @@ void nilfs_sufile_do_free(struct inode *sufile, __u64 segnum, nilfs_mdt_mark_buffer_dirty(su_bh); nilfs_sufile_mod_counter(header_bh, 1, sudirty ? (u64)-1 : 0); + NILFS_SUI(sufile)->ncleansegs++; + nilfs_mdt_mark_dirty(sufile); } /** - * nilfs_sufile_get_segment_usage - get a segment usage + * nilfs_sufile_mark_dirty - mark the buffer having a segment usage dirty * @sufile: inode of segment usage file * @segnum: segment number - * @sup: pointer to segment usage - * @bhp: pointer to buffer head - * - * Description: nilfs_sufile_get_segment_usage() acquires the segment usage - * specified by @segnum. - * - * Return Value: On success, 0 is returned, and the segment usage and the - * buffer head of the buffer on which the segment usage is located are stored - * in the place pointed by @sup and @bhp, respectively. On error, one of the - * following negative error codes is returned. - * - * %-EIO - I/O error. - * - * %-ENOMEM - Insufficient amount of memory available. - * - * %-EINVAL - Invalid segment usage number. */ -int nilfs_sufile_get_segment_usage(struct inode *sufile, __u64 segnum, - struct nilfs_segment_usage **sup, - struct buffer_head **bhp) +int nilfs_sufile_mark_dirty(struct inode *sufile, __u64 segnum) { struct buffer_head *bh; - struct nilfs_segment_usage *su; - void *kaddr; int ret; - /* segnum is 0 origin */ - if (segnum >= nilfs_sufile_get_nsegments(sufile)) - return -EINVAL; - down_write(&NILFS_MDT(sufile)->mi_sem); - ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 1, &bh); - if (ret < 0) - goto out_sem; - kaddr = kmap(bh->b_page); - su = nilfs_sufile_block_get_segment_usage(sufile, segnum, bh, kaddr); - if (nilfs_segment_usage_error(su)) { - kunmap(bh->b_page); + ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &bh); + if (!ret) { + nilfs_mdt_mark_buffer_dirty(bh); + nilfs_mdt_mark_dirty(sufile); brelse(bh); - ret = -EINVAL; - goto out_sem; } - - if (sup != NULL) - *sup = su; - *bhp = bh; - - out_sem: - up_write(&NILFS_MDT(sufile)->mi_sem); return ret; } /** - * nilfs_sufile_put_segment_usage - put a segment usage + * nilfs_sufile_set_segment_usage - set usage of a segment * @sufile: inode of segment usage file * @segnum: segment number - * @bh: buffer head - * - * Description: nilfs_sufile_put_segment_usage() releases the segment usage - * specified by @segnum. @bh must be the buffer head which have been returned - * by a previous call to nilfs_sufile_get_segment_usage() with @segnum. + * @nblocks: number of live blocks in the segment + * @modtime: modification time (option) */ -void nilfs_sufile_put_segment_usage(struct inode *sufile, __u64 segnum, - struct buffer_head *bh) +int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum, + unsigned long nblocks, time_t modtime) { - kunmap(bh->b_page); + struct buffer_head *bh; + struct nilfs_segment_usage *su; + void *kaddr; + int ret; + + down_write(&NILFS_MDT(sufile)->mi_sem); + ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &bh); + if (ret < 0) + goto out_sem; + + kaddr = kmap_atomic(bh->b_page, KM_USER0); + su = nilfs_sufile_block_get_segment_usage(sufile, segnum, bh, kaddr); + WARN_ON(nilfs_segment_usage_error(su)); + if (modtime) + su->su_lastmod = cpu_to_le64(modtime); + su->su_nblocks = cpu_to_le32(nblocks); + kunmap_atomic(kaddr, KM_USER0); + + nilfs_mdt_mark_buffer_dirty(bh); + nilfs_mdt_mark_dirty(sufile); brelse(bh); + + out_sem: + up_write(&NILFS_MDT(sufile)->mi_sem); + return ret; } /** @@ -515,7 +516,7 @@ int nilfs_sufile_get_stat(struct inode *sufile, struct nilfs_sustat *sustat) goto out_sem; kaddr = kmap_atomic(header_bh->b_page, KM_USER0); - header = nilfs_sufile_block_get_header(sufile, header_bh, kaddr); + header = kaddr + bh_offset(header_bh); sustat->ss_nsegs = nilfs_sufile_get_nsegments(sufile); sustat->ss_ncleansegs = le64_to_cpu(header->sh_ncleansegs); sustat->ss_ndirtysegs = le64_to_cpu(header->sh_ndirtysegs); @@ -532,33 +533,6 @@ int nilfs_sufile_get_stat(struct inode *sufile, struct nilfs_sustat *sustat) return ret; } -/** - * nilfs_sufile_get_ncleansegs - get the number of clean segments - * @sufile: inode of segment usage file - * @nsegsp: pointer to the number of clean segments - * - * Description: nilfs_sufile_get_ncleansegs() acquires the number of clean - * segments. - * - * Return Value: On success, 0 is returned and the number of clean segments is - * stored in the place pointed by @nsegsp. On error, one of the following - * negative error codes is returned. - * - * %-EIO - I/O error. - * - * %-ENOMEM - Insufficient amount of memory available. - */ -int nilfs_sufile_get_ncleansegs(struct inode *sufile, unsigned long *nsegsp) -{ - struct nilfs_sustat sustat; - int ret; - - ret = nilfs_sufile_get_stat(sufile, &sustat); - if (ret == 0) - *nsegsp = sustat.ss_ncleansegs; - return ret; -} - void nilfs_sufile_do_set_error(struct inode *sufile, __u64 segnum, struct buffer_head *header_bh, struct buffer_head *su_bh) @@ -577,8 +551,10 @@ void nilfs_sufile_do_set_error(struct inode *sufile, __u64 segnum, nilfs_segment_usage_set_error(su); kunmap_atomic(kaddr, KM_USER0); - if (suclean) + if (suclean) { nilfs_sufile_mod_counter(header_bh, -1, 0); + NILFS_SUI(sufile)->ncleansegs--; + } nilfs_mdt_mark_buffer_dirty(su_bh); nilfs_mdt_mark_dirty(sufile); } @@ -657,3 +633,48 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, up_read(&NILFS_MDT(sufile)->mi_sem); return ret; } + +/** + * nilfs_sufile_read - read sufile inode + * @sufile: sufile inode + * @raw_inode: on-disk sufile inode + */ +int nilfs_sufile_read(struct inode *sufile, struct nilfs_inode *raw_inode) +{ + struct nilfs_sufile_info *sui = NILFS_SUI(sufile); + struct buffer_head *header_bh; + struct nilfs_sufile_header *header; + void *kaddr; + int ret; + + ret = nilfs_read_inode_common(sufile, raw_inode); + if (ret < 0) + return ret; + + ret = nilfs_sufile_get_header_block(sufile, &header_bh); + if (!ret) { + kaddr = kmap_atomic(header_bh->b_page, KM_USER0); + header = kaddr + bh_offset(header_bh); + sui->ncleansegs = le64_to_cpu(header->sh_ncleansegs); + kunmap_atomic(kaddr, KM_USER0); + brelse(header_bh); + } + return ret; +} + +/** + * nilfs_sufile_new - create sufile + * @nilfs: nilfs object + * @susize: size of a segment usage entry + */ +struct inode *nilfs_sufile_new(struct the_nilfs *nilfs, size_t susize) +{ + struct inode *sufile; + + sufile = nilfs_mdt_new(nilfs, NULL, NILFS_SUFILE_INO, + sizeof(struct nilfs_sufile_info)); + if (sufile) + nilfs_mdt_set_entry_size(sufile, susize, + sizeof(struct nilfs_sufile_header)); + return sufile; +} diff --git a/fs/nilfs2/sufile.h b/fs/nilfs2/sufile.h index 0e99e5c0bd0f564fd4281bfb537fad4e3ee59c58..15163b8aff7d74384744839dcdadd05d83ea2931 100644 --- a/fs/nilfs2/sufile.h +++ b/fs/nilfs2/sufile.h @@ -34,14 +34,13 @@ static inline unsigned long nilfs_sufile_get_nsegments(struct inode *sufile) return NILFS_MDT(sufile)->mi_nilfs->ns_nsegments; } +unsigned long nilfs_sufile_get_ncleansegs(struct inode *sufile); + int nilfs_sufile_alloc(struct inode *, __u64 *); -int nilfs_sufile_get_segment_usage(struct inode *, __u64, - struct nilfs_segment_usage **, - struct buffer_head **); -void nilfs_sufile_put_segment_usage(struct inode *, __u64, - struct buffer_head *); +int nilfs_sufile_mark_dirty(struct inode *sufile, __u64 segnum); +int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum, + unsigned long nblocks, time_t modtime); int nilfs_sufile_get_stat(struct inode *, struct nilfs_sustat *); -int nilfs_sufile_get_ncleansegs(struct inode *, unsigned long *); ssize_t nilfs_sufile_get_suinfo(struct inode *, __u64, void *, unsigned, size_t); @@ -62,6 +61,9 @@ void nilfs_sufile_do_cancel_free(struct inode *, __u64, struct buffer_head *, void nilfs_sufile_do_set_error(struct inode *, __u64, struct buffer_head *, struct buffer_head *); +int nilfs_sufile_read(struct inode *sufile, struct nilfs_inode *raw_inode); +struct inode *nilfs_sufile_new(struct the_nilfs *nilfs, size_t susize); + /** * nilfs_sufile_scrap - make a segment garbage * @sufile: inode of segment usage file diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 644e66727dd0e6f5464eb092b9d6db6caeac837f..5403b3ef3a42bd745b80b2e550a7f57a7c3d2c48 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -363,14 +363,10 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) list_add(&sbi->s_list, &nilfs->ns_supers); up_write(&nilfs->ns_super_sem); - sbi->s_ifile = nilfs_mdt_new(nilfs, sbi->s_super, NILFS_IFILE_INO); + sbi->s_ifile = nilfs_ifile_new(sbi, nilfs->ns_inode_size); if (!sbi->s_ifile) return -ENOMEM; - err = nilfs_palloc_init_blockgroup(sbi->s_ifile, nilfs->ns_inode_size); - if (unlikely(err)) - goto failed; - down_read(&nilfs->ns_segctor_sem); err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, cno, 0, &raw_cp, &bh_cp); @@ -411,7 +407,6 @@ void nilfs_detach_checkpoint(struct nilfs_sb_info *sbi) { struct the_nilfs *nilfs = sbi->s_nilfs; - nilfs_mdt_clear(sbi->s_ifile); nilfs_mdt_destroy(sbi->s_ifile); sbi->s_ifile = NULL; down_write(&nilfs->ns_super_sem); @@ -419,22 +414,6 @@ void nilfs_detach_checkpoint(struct nilfs_sb_info *sbi) up_write(&nilfs->ns_super_sem); } -static int nilfs_mark_recovery_complete(struct nilfs_sb_info *sbi) -{ - struct the_nilfs *nilfs = sbi->s_nilfs; - int err = 0; - - down_write(&nilfs->ns_sem); - if (!(nilfs->ns_mount_state & NILFS_VALID_FS)) { - nilfs->ns_mount_state |= NILFS_VALID_FS; - err = nilfs_commit_super(sbi, 1); - if (likely(!err)) - printk(KERN_INFO "NILFS: recovery complete.\n"); - } - up_write(&nilfs->ns_sem); - return err; -} - static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; @@ -490,7 +469,7 @@ static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) struct nilfs_sb_info *sbi = NILFS_SB(sb); if (!nilfs_test_opt(sbi, BARRIER)) - seq_printf(seq, ",barrier=off"); + seq_printf(seq, ",nobarrier"); if (nilfs_test_opt(sbi, SNAPSHOT)) seq_printf(seq, ",cp=%llu", (unsigned long long int)sbi->s_snapshot_cno); @@ -500,6 +479,8 @@ static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) seq_printf(seq, ",errors=panic"); if (nilfs_test_opt(sbi, STRICT_ORDER)) seq_printf(seq, ",order=strict"); + if (nilfs_test_opt(sbi, NORECOVERY)) + seq_printf(seq, ",norecovery"); return 0; } @@ -568,7 +549,7 @@ static const struct export_operations nilfs_export_ops = { enum { Opt_err_cont, Opt_err_panic, Opt_err_ro, - Opt_barrier, Opt_snapshot, Opt_order, + Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, Opt_err, }; @@ -576,25 +557,13 @@ static match_table_t tokens = { {Opt_err_cont, "errors=continue"}, {Opt_err_panic, "errors=panic"}, {Opt_err_ro, "errors=remount-ro"}, - {Opt_barrier, "barrier=%s"}, + {Opt_nobarrier, "nobarrier"}, {Opt_snapshot, "cp=%u"}, {Opt_order, "order=%s"}, + {Opt_norecovery, "norecovery"}, {Opt_err, NULL} }; -static int match_bool(substring_t *s, int *result) -{ - int len = s->to - s->from; - - if (strncmp(s->from, "on", len) == 0) - *result = 1; - else if (strncmp(s->from, "off", len) == 0) - *result = 0; - else - return 1; - return 0; -} - static int parse_options(char *options, struct super_block *sb) { struct nilfs_sb_info *sbi = NILFS_SB(sb); @@ -612,13 +581,8 @@ static int parse_options(char *options, struct super_block *sb) token = match_token(p, tokens, args); switch (token) { - case Opt_barrier: - if (match_bool(&args[0], &option)) - return 0; - if (option) - nilfs_set_opt(sbi, BARRIER); - else - nilfs_clear_opt(sbi, BARRIER); + case Opt_nobarrier: + nilfs_clear_opt(sbi, BARRIER); break; case Opt_order: if (strcmp(args[0].from, "relaxed") == 0) @@ -647,6 +611,9 @@ static int parse_options(char *options, struct super_block *sb) sbi->s_snapshot_cno = option; nilfs_set_opt(sbi, SNAPSHOT); break; + case Opt_norecovery: + nilfs_set_opt(sbi, NORECOVERY); + break; default: printk(KERN_ERR "NILFS: Unrecognized mount option \"%s\"\n", p); @@ -672,9 +639,7 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi) int mnt_count = le16_to_cpu(sbp->s_mnt_count); /* nilfs->sem must be locked by the caller. */ - if (!(nilfs->ns_mount_state & NILFS_VALID_FS)) { - printk(KERN_WARNING "NILFS warning: mounting unchecked fs\n"); - } else if (nilfs->ns_mount_state & NILFS_ERROR_FS) { + if (nilfs->ns_mount_state & NILFS_ERROR_FS) { printk(KERN_WARNING "NILFS warning: mounting fs with errors\n"); #if 0 @@ -782,11 +747,10 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, sb->s_root = NULL; sb->s_time_gran = 1; - if (!nilfs_loaded(nilfs)) { - err = load_nilfs(nilfs, sbi); - if (err) - goto failed_sbi; - } + err = load_nilfs(nilfs, sbi); + if (err) + goto failed_sbi; + cno = nilfs_last_cno(nilfs); if (sb->s_flags & MS_RDONLY) { @@ -854,12 +818,6 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, up_write(&nilfs->ns_sem); } - err = nilfs_mark_recovery_complete(sbi); - if (unlikely(err)) { - printk(KERN_ERR "NILFS: recovery failed.\n"); - goto failed_root; - } - down_write(&nilfs->ns_super_sem); if (!nilfs_test_opt(sbi, SNAPSHOT)) nilfs->ns_current = sbi; @@ -867,10 +825,6 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, return 0; - failed_root: - dput(sb->s_root); - sb->s_root = NULL; - failed_segctor: nilfs_detach_segment_constructor(sbi); @@ -915,6 +869,14 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) goto restore_opts; } + if (!nilfs_valid_fs(nilfs)) { + printk(KERN_WARNING "NILFS (device %s): couldn't " + "remount because the filesystem is in an " + "incomplete recovery state.\n", sb->s_id); + err = -EINVAL; + goto restore_opts; + } + if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) goto out; if (*flags & MS_RDONLY) { diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index ad391a8c3e7e51190eb691e24699044fe11e256d..6241e1722efc570f3bb62c81f30a4b4e8f7092e3 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -146,13 +146,9 @@ void put_nilfs(struct the_nilfs *nilfs) might_sleep(); if (nilfs_loaded(nilfs)) { - nilfs_mdt_clear(nilfs->ns_sufile); nilfs_mdt_destroy(nilfs->ns_sufile); - nilfs_mdt_clear(nilfs->ns_cpfile); nilfs_mdt_destroy(nilfs->ns_cpfile); - nilfs_mdt_clear(nilfs->ns_dat); nilfs_mdt_destroy(nilfs->ns_dat); - /* XXX: how and when to clear nilfs->ns_gc_dat? */ nilfs_mdt_destroy(nilfs->ns_gc_dat); } if (nilfs_init(nilfs)) { @@ -166,7 +162,6 @@ void put_nilfs(struct the_nilfs *nilfs) static int nilfs_load_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, sector_t sr_block) { - static struct lock_class_key dat_lock_key; struct buffer_head *bh_sr; struct nilfs_super_root *raw_sr; struct nilfs_super_block **sbp = nilfs->ns_sbp; @@ -187,51 +182,36 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs, inode_size = nilfs->ns_inode_size; err = -ENOMEM; - nilfs->ns_dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO); + nilfs->ns_dat = nilfs_dat_new(nilfs, dat_entry_size); if (unlikely(!nilfs->ns_dat)) goto failed; - nilfs->ns_gc_dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO); + nilfs->ns_gc_dat = nilfs_dat_new(nilfs, dat_entry_size); if (unlikely(!nilfs->ns_gc_dat)) goto failed_dat; - nilfs->ns_cpfile = nilfs_mdt_new(nilfs, NULL, NILFS_CPFILE_INO); + nilfs->ns_cpfile = nilfs_cpfile_new(nilfs, checkpoint_size); if (unlikely(!nilfs->ns_cpfile)) goto failed_gc_dat; - nilfs->ns_sufile = nilfs_mdt_new(nilfs, NULL, NILFS_SUFILE_INO); + nilfs->ns_sufile = nilfs_sufile_new(nilfs, segment_usage_size); if (unlikely(!nilfs->ns_sufile)) goto failed_cpfile; - err = nilfs_palloc_init_blockgroup(nilfs->ns_dat, dat_entry_size); - if (unlikely(err)) - goto failed_sufile; - - err = nilfs_palloc_init_blockgroup(nilfs->ns_gc_dat, dat_entry_size); - if (unlikely(err)) - goto failed_sufile; - - lockdep_set_class(&NILFS_MDT(nilfs->ns_dat)->mi_sem, &dat_lock_key); - lockdep_set_class(&NILFS_MDT(nilfs->ns_gc_dat)->mi_sem, &dat_lock_key); - nilfs_mdt_set_shadow(nilfs->ns_dat, nilfs->ns_gc_dat); - nilfs_mdt_set_entry_size(nilfs->ns_cpfile, checkpoint_size, - sizeof(struct nilfs_cpfile_header)); - nilfs_mdt_set_entry_size(nilfs->ns_sufile, segment_usage_size, - sizeof(struct nilfs_sufile_header)); - err = nilfs_mdt_read_inode_direct( - nilfs->ns_dat, bh_sr, NILFS_SR_DAT_OFFSET(inode_size)); + err = nilfs_dat_read(nilfs->ns_dat, (void *)bh_sr->b_data + + NILFS_SR_DAT_OFFSET(inode_size)); if (unlikely(err)) goto failed_sufile; - err = nilfs_mdt_read_inode_direct( - nilfs->ns_cpfile, bh_sr, NILFS_SR_CPFILE_OFFSET(inode_size)); + err = nilfs_cpfile_read(nilfs->ns_cpfile, (void *)bh_sr->b_data + + NILFS_SR_CPFILE_OFFSET(inode_size)); if (unlikely(err)) goto failed_sufile; - err = nilfs_mdt_read_inode_direct( - nilfs->ns_sufile, bh_sr, NILFS_SR_SUFILE_OFFSET(inode_size)); + err = nilfs_sufile_read(nilfs->ns_sufile, (void *)bh_sr->b_data + + NILFS_SR_SUFILE_OFFSET(inode_size)); if (unlikely(err)) goto failed_sufile; @@ -281,29 +261,30 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) struct nilfs_recovery_info ri; unsigned int s_flags = sbi->s_super->s_flags; int really_read_only = bdev_read_only(nilfs->ns_bdev); - unsigned valid_fs; - int err = 0; - - nilfs_init_recovery_info(&ri); + int valid_fs = nilfs_valid_fs(nilfs); + int err; - down_write(&nilfs->ns_sem); - valid_fs = (nilfs->ns_mount_state & NILFS_VALID_FS); - up_write(&nilfs->ns_sem); + if (nilfs_loaded(nilfs)) { + if (valid_fs || + ((s_flags & MS_RDONLY) && nilfs_test_opt(sbi, NORECOVERY))) + return 0; + printk(KERN_ERR "NILFS: the filesystem is in an incomplete " + "recovery state.\n"); + return -EINVAL; + } - if (!valid_fs && (s_flags & MS_RDONLY)) { - printk(KERN_INFO "NILFS: INFO: recovery " - "required for readonly filesystem.\n"); - if (really_read_only) { - printk(KERN_ERR "NILFS: write access " - "unavailable, cannot proceed.\n"); - err = -EROFS; - goto failed; + if (!valid_fs) { + printk(KERN_WARNING "NILFS warning: mounting unchecked fs\n"); + if (s_flags & MS_RDONLY) { + printk(KERN_INFO "NILFS: INFO: recovery " + "required for readonly filesystem.\n"); + printk(KERN_INFO "NILFS: write access will " + "be enabled during recovery.\n"); } - printk(KERN_INFO "NILFS: write access will " - "be enabled during recovery.\n"); - sbi->s_super->s_flags &= ~MS_RDONLY; } + nilfs_init_recovery_info(&ri); + err = nilfs_search_super_root(nilfs, sbi, &ri); if (unlikely(err)) { printk(KERN_ERR "NILFS: error searching super root.\n"); @@ -316,19 +297,56 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) goto failed; } - if (!valid_fs) { - err = nilfs_recover_logical_segments(nilfs, sbi, &ri); - if (unlikely(err)) { - nilfs_mdt_destroy(nilfs->ns_cpfile); - nilfs_mdt_destroy(nilfs->ns_sufile); - nilfs_mdt_destroy(nilfs->ns_dat); - goto failed; + if (valid_fs) + goto skip_recovery; + + if (s_flags & MS_RDONLY) { + if (nilfs_test_opt(sbi, NORECOVERY)) { + printk(KERN_INFO "NILFS: norecovery option specified. " + "skipping roll-forward recovery\n"); + goto skip_recovery; } - if (ri.ri_need_recovery == NILFS_RECOVERY_SR_UPDATED) - sbi->s_super->s_dirt = 1; + if (really_read_only) { + printk(KERN_ERR "NILFS: write access " + "unavailable, cannot proceed.\n"); + err = -EROFS; + goto failed_unload; + } + sbi->s_super->s_flags &= ~MS_RDONLY; + } else if (nilfs_test_opt(sbi, NORECOVERY)) { + printk(KERN_ERR "NILFS: recovery cancelled because norecovery " + "option was specified for a read/write mount\n"); + err = -EINVAL; + goto failed_unload; } + err = nilfs_recover_logical_segments(nilfs, sbi, &ri); + if (err) + goto failed_unload; + + down_write(&nilfs->ns_sem); + nilfs->ns_mount_state |= NILFS_VALID_FS; + nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state); + err = nilfs_commit_super(sbi, 1); + up_write(&nilfs->ns_sem); + + if (err) { + printk(KERN_ERR "NILFS: failed to update super block. " + "recovery unfinished.\n"); + goto failed_unload; + } + printk(KERN_INFO "NILFS: recovery complete.\n"); + + skip_recovery: set_nilfs_loaded(nilfs); + nilfs_clear_recovery_info(&ri); + sbi->s_super->s_flags = s_flags; + return 0; + + failed_unload: + nilfs_mdt_destroy(nilfs->ns_cpfile); + nilfs_mdt_destroy(nilfs->ns_sufile); + nilfs_mdt_destroy(nilfs->ns_dat); failed: nilfs_clear_recovery_info(&ri); @@ -632,30 +650,23 @@ int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks) { struct inode *dat = nilfs_dat_inode(nilfs); unsigned long ncleansegs; - int err; down_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ - err = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile, &ncleansegs); + ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile); up_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ - if (likely(!err)) - *nblocks = (sector_t)ncleansegs * nilfs->ns_blocks_per_segment; - return err; + *nblocks = (sector_t)ncleansegs * nilfs->ns_blocks_per_segment; + return 0; } int nilfs_near_disk_full(struct the_nilfs *nilfs) { - struct inode *sufile = nilfs->ns_sufile; unsigned long ncleansegs, nincsegs; - int ret; - ret = nilfs_sufile_get_ncleansegs(sufile, &ncleansegs); - if (likely(!ret)) { - nincsegs = atomic_read(&nilfs->ns_ndirtyblks) / - nilfs->ns_blocks_per_segment + 1; - if (ncleansegs <= nilfs->ns_nrsvsegs + nincsegs) - ret++; - } - return ret; + ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile); + nincsegs = atomic_read(&nilfs->ns_ndirtyblks) / + nilfs->ns_blocks_per_segment + 1; + + return ncleansegs <= nilfs->ns_nrsvsegs + nincsegs; } /** diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 20abd55881e0adc7903682c4fb15a3a057230a97..589786e33464661a2e2df9321d75725011ba522f 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -258,6 +258,16 @@ static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi) kfree(sbi); } +static inline int nilfs_valid_fs(struct the_nilfs *nilfs) +{ + unsigned valid_fs; + + down_read(&nilfs->ns_sem); + valid_fs = (nilfs->ns_mount_state & NILFS_VALID_FS); + up_read(&nilfs->ns_sem); + return valid_fs; +} + static inline void nilfs_get_segment_range(struct the_nilfs *nilfs, __u64 segnum, sector_t *seg_start, sector_t *seg_end) diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index de059f49058694b7887c49f5d907deb32760bb82..3d30a1c974a89dbb4429d91d453a1c46d185bb55 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -2006,7 +2006,7 @@ out_dio: /* buffered aio wouldn't have proper lock coverage today */ BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); - if ((file->f_flags & O_SYNC && !direct_io) || IS_SYNC(inode)) { + if ((file->f_flags & O_DSYNC && !direct_io) || IS_SYNC(inode)) { ret = filemap_fdatawrite_range(file->f_mapping, pos, pos + count - 1); if (ret < 0) diff --git a/fs/ocfs2/quota.h b/fs/ocfs2/quota.h index e5df9d170b0cbd6cc8541f68fda5d34a1f62c7f5..123bc520a2c0378bd85f8a5a6fe8a30871ea3d32 100644 --- a/fs/ocfs2/quota.h +++ b/fs/ocfs2/quota.h @@ -17,10 +17,6 @@ #include "ocfs2.h" -/* Common stuff */ -/* id number of quota format */ -#define QFMT_OCFS2 3 - /* * In-memory structures */ diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 1a2c50a759faaef1f2b5eca5e6d7d865ecdbd47a..21f9e71223caf53b10c3f2b128782aef14169889 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c @@ -1325,7 +1325,7 @@ out: return status; } -static struct quota_format_ops ocfs2_format_ops = { +static const struct quota_format_ops ocfs2_format_ops = { .check_quota_file = ocfs2_local_check_quota_file, .read_file_info = ocfs2_local_read_info, .write_file_info = ocfs2_global_write_info, diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index 7ba79a54948cf049ad277a8c9d2fad0735ace088..123257bb356b38bc8fe614b101a2354a24c82e47 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -25,26 +26,27 @@ static struct proc_dir_entry *proc_device_tree; /* * Supply data on a read from /proc/device-tree/node/property. */ -static int property_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int property_proc_show(struct seq_file *m, void *v) { - struct property *pp = data; - int n; + struct property *pp = m->private; - if (off >= pp->length) { - *eof = 1; - return 0; - } - n = pp->length - off; - if (n > count) - n = count; - else - *eof = 1; - memcpy(page, (char *)pp->value + off, n); - *start = page; - return n; + seq_write(m, pp->value, pp->length); + return 0; +} + +static int property_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, property_proc_show, PDE(inode)->data); } +static const struct file_operations property_proc_fops = { + .owner = THIS_MODULE, + .open = property_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* * For a node with a name like "gc@10", we make symlinks called "gc" * and "@10" to it. @@ -63,10 +65,9 @@ __proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp, * Unfortunately proc_register puts each new entry * at the beginning of the list. So we rearrange them. */ - ent = create_proc_read_entry(name, - strncmp(name, "security-", 9) - ? S_IRUGO : S_IRUSR, de, - property_read_proc, pp); + ent = proc_create_data(name, + strncmp(name, "security-", 9) ? S_IRUGO : S_IRUSR, + de, &property_proc_fops, pp); if (ent == NULL) return NULL; diff --git a/fs/quota/Kconfig b/fs/quota/Kconfig index 353e78a9ebeec6067573895764fbc5d3d64965b7..efc02ebb8c70530147c6dbe3a72d1a0584aabd7c 100644 --- a/fs/quota/Kconfig +++ b/fs/quota/Kconfig @@ -46,12 +46,14 @@ config QFMT_V1 format say Y here. config QFMT_V2 - tristate "Quota format v2 support" + tristate "Quota format vfsv0 and vfsv1 support" depends on QUOTA select QUOTA_TREE help - This quota format allows using quotas with 32-bit UIDs/GIDs. If you - need this functionality say Y here. + This config option enables kernel support for vfsv0 and vfsv1 quota + formats. Both these formats support 32-bit UIDs/GIDs and vfsv1 format + also supports 64-bit inode and block quota limits. If you need this + functionality say Y here. config QUOTACTL bool diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index eb5a755718f6a25542938048793d8884ad73d126..cd6bb9a33c131f3ab2ee5cb7d4654069777f3ad6 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -2164,7 +2164,9 @@ int vfs_quota_on_mount(struct super_block *sb, char *qf_name, struct dentry *dentry; int error; + mutex_lock(&sb->s_root->d_inode->i_mutex); dentry = lookup_one_len(qf_name, sb->s_root, strlen(qf_name)); + mutex_unlock(&sb->s_root->d_inode->i_mutex); if (IS_ERR(dentry)) return PTR_ERR(dentry); diff --git a/fs/quota/quota_v1.c b/fs/quota/quota_v1.c index 0edcf42b177801c48a11d32b7e8ccb6c48fcb025..2ae757e9c008478bde15a0883925378770e6ee95 100644 --- a/fs/quota/quota_v1.c +++ b/fs/quota/quota_v1.c @@ -204,7 +204,7 @@ out: return ret; } -static struct quota_format_ops v1_format_ops = { +static const struct quota_format_ops v1_format_ops = { .check_quota_file = v1_check_quota_file, .read_file_info = v1_read_file_info, .write_file_info = v1_write_file_info, diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c index a5475fb1ae4478b62a02b9aae42d82a99a478bad..3dfc23e021351980693ea24b48d6d46dc5aa1e5e 100644 --- a/fs/quota/quota_v2.c +++ b/fs/quota/quota_v2.c @@ -23,14 +23,23 @@ MODULE_LICENSE("GPL"); #define __QUOTA_V2_PARANOIA -static void v2_mem2diskdqb(void *dp, struct dquot *dquot); -static void v2_disk2memdqb(struct dquot *dquot, void *dp); -static int v2_is_id(void *dp, struct dquot *dquot); - -static struct qtree_fmt_operations v2_qtree_ops = { - .mem2disk_dqblk = v2_mem2diskdqb, - .disk2mem_dqblk = v2_disk2memdqb, - .is_id = v2_is_id, +static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot); +static void v2r0_disk2memdqb(struct dquot *dquot, void *dp); +static int v2r0_is_id(void *dp, struct dquot *dquot); +static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot); +static void v2r1_disk2memdqb(struct dquot *dquot, void *dp); +static int v2r1_is_id(void *dp, struct dquot *dquot); + +static struct qtree_fmt_operations v2r0_qtree_ops = { + .mem2disk_dqblk = v2r0_mem2diskdqb, + .disk2mem_dqblk = v2r0_disk2memdqb, + .is_id = v2r0_is_id, +}; + +static struct qtree_fmt_operations v2r1_qtree_ops = { + .mem2disk_dqblk = v2r1_mem2diskdqb, + .disk2mem_dqblk = v2r1_disk2memdqb, + .is_id = v2r1_is_id, }; #define QUOTABLOCK_BITS 10 @@ -46,23 +55,33 @@ static inline qsize_t v2_qbtos(qsize_t blocks) return blocks << QUOTABLOCK_BITS; } +static int v2_read_header(struct super_block *sb, int type, + struct v2_disk_dqheader *dqhead) +{ + ssize_t size; + + size = sb->s_op->quota_read(sb, type, (char *)dqhead, + sizeof(struct v2_disk_dqheader), 0); + if (size != sizeof(struct v2_disk_dqheader)) { + printk(KERN_WARNING "quota_v2: Failed header read:" + " expected=%zd got=%zd\n", + sizeof(struct v2_disk_dqheader), size); + return 0; + } + return 1; +} + /* Check whether given file is really vfsv0 quotafile */ static int v2_check_quota_file(struct super_block *sb, int type) { struct v2_disk_dqheader dqhead; - ssize_t size; static const uint quota_magics[] = V2_INITQMAGICS; static const uint quota_versions[] = V2_INITQVERSIONS; - size = sb->s_op->quota_read(sb, type, (char *)&dqhead, - sizeof(struct v2_disk_dqheader), 0); - if (size != sizeof(struct v2_disk_dqheader)) { - printk("quota_v2: failed read expected=%zd got=%zd\n", - sizeof(struct v2_disk_dqheader), size); + if (!v2_read_header(sb, type, &dqhead)) return 0; - } if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] || - le32_to_cpu(dqhead.dqh_version) != quota_versions[type]) + le32_to_cpu(dqhead.dqh_version) > quota_versions[type]) return 0; return 1; } @@ -71,14 +90,20 @@ static int v2_check_quota_file(struct super_block *sb, int type) static int v2_read_file_info(struct super_block *sb, int type) { struct v2_disk_dqinfo dinfo; + struct v2_disk_dqheader dqhead; struct mem_dqinfo *info = sb_dqinfo(sb, type); struct qtree_mem_dqinfo *qinfo; ssize_t size; + unsigned int version; + + if (!v2_read_header(sb, type, &dqhead)) + return 0; + version = le32_to_cpu(dqhead.dqh_version); size = sb->s_op->quota_read(sb, type, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); if (size != sizeof(struct v2_disk_dqinfo)) { - printk(KERN_WARNING "Can't read info structure on device %s.\n", + printk(KERN_WARNING "quota_v2: Can't read info structure on device %s.\n", sb->s_id); return -1; } @@ -89,9 +114,15 @@ static int v2_read_file_info(struct super_block *sb, int type) return -1; } qinfo = info->dqi_priv; - /* limits are stored as unsigned 32-bit data */ - info->dqi_maxblimit = 0xffffffff; - info->dqi_maxilimit = 0xffffffff; + if (version == 0) { + /* limits are stored as unsigned 32-bit data */ + info->dqi_maxblimit = 0xffffffff; + info->dqi_maxilimit = 0xffffffff; + } else { + /* used space is stored as unsigned 64-bit value */ + info->dqi_maxblimit = 0xffffffffffffffff; /* 2^64-1 */ + info->dqi_maxilimit = 0xffffffffffffffff; + } info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace); info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace); info->dqi_flags = le32_to_cpu(dinfo.dqi_flags); @@ -103,8 +134,13 @@ static int v2_read_file_info(struct super_block *sb, int type) qinfo->dqi_blocksize_bits = V2_DQBLKSIZE_BITS; qinfo->dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS; qinfo->dqi_qtree_depth = qtree_depth(qinfo); - qinfo->dqi_entry_size = sizeof(struct v2_disk_dqblk); - qinfo->dqi_ops = &v2_qtree_ops; + if (version == 0) { + qinfo->dqi_entry_size = sizeof(struct v2r0_disk_dqblk); + qinfo->dqi_ops = &v2r0_qtree_ops; + } else { + qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk); + qinfo->dqi_ops = &v2r1_qtree_ops; + } return 0; } @@ -135,9 +171,9 @@ static int v2_write_file_info(struct super_block *sb, int type) return 0; } -static void v2_disk2memdqb(struct dquot *dquot, void *dp) +static void v2r0_disk2memdqb(struct dquot *dquot, void *dp) { - struct v2_disk_dqblk *d = dp, empty; + struct v2r0_disk_dqblk *d = dp, empty; struct mem_dqblk *m = &dquot->dq_dqb; m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit); @@ -149,15 +185,15 @@ static void v2_disk2memdqb(struct dquot *dquot, void *dp) m->dqb_curspace = le64_to_cpu(d->dqb_curspace); m->dqb_btime = le64_to_cpu(d->dqb_btime); /* We need to escape back all-zero structure */ - memset(&empty, 0, sizeof(struct v2_disk_dqblk)); + memset(&empty, 0, sizeof(struct v2r0_disk_dqblk)); empty.dqb_itime = cpu_to_le64(1); - if (!memcmp(&empty, dp, sizeof(struct v2_disk_dqblk))) + if (!memcmp(&empty, dp, sizeof(struct v2r0_disk_dqblk))) m->dqb_itime = 0; } -static void v2_mem2diskdqb(void *dp, struct dquot *dquot) +static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot) { - struct v2_disk_dqblk *d = dp; + struct v2r0_disk_dqblk *d = dp; struct mem_dqblk *m = &dquot->dq_dqb; struct qtree_mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; @@ -175,9 +211,60 @@ static void v2_mem2diskdqb(void *dp, struct dquot *dquot) d->dqb_itime = cpu_to_le64(1); } -static int v2_is_id(void *dp, struct dquot *dquot) +static int v2r0_is_id(void *dp, struct dquot *dquot) +{ + struct v2r0_disk_dqblk *d = dp; + struct qtree_mem_dqinfo *info = + sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; + + if (qtree_entry_unused(info, dp)) + return 0; + return le32_to_cpu(d->dqb_id) == dquot->dq_id; +} + +static void v2r1_disk2memdqb(struct dquot *dquot, void *dp) +{ + struct v2r1_disk_dqblk *d = dp, empty; + struct mem_dqblk *m = &dquot->dq_dqb; + + m->dqb_ihardlimit = le64_to_cpu(d->dqb_ihardlimit); + m->dqb_isoftlimit = le64_to_cpu(d->dqb_isoftlimit); + m->dqb_curinodes = le64_to_cpu(d->dqb_curinodes); + m->dqb_itime = le64_to_cpu(d->dqb_itime); + m->dqb_bhardlimit = v2_qbtos(le64_to_cpu(d->dqb_bhardlimit)); + m->dqb_bsoftlimit = v2_qbtos(le64_to_cpu(d->dqb_bsoftlimit)); + m->dqb_curspace = le64_to_cpu(d->dqb_curspace); + m->dqb_btime = le64_to_cpu(d->dqb_btime); + /* We need to escape back all-zero structure */ + memset(&empty, 0, sizeof(struct v2r1_disk_dqblk)); + empty.dqb_itime = cpu_to_le64(1); + if (!memcmp(&empty, dp, sizeof(struct v2r1_disk_dqblk))) + m->dqb_itime = 0; +} + +static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot) +{ + struct v2r1_disk_dqblk *d = dp; + struct mem_dqblk *m = &dquot->dq_dqb; + struct qtree_mem_dqinfo *info = + sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; + + d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit); + d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit); + d->dqb_curinodes = cpu_to_le64(m->dqb_curinodes); + d->dqb_itime = cpu_to_le64(m->dqb_itime); + d->dqb_bhardlimit = cpu_to_le64(v2_stoqb(m->dqb_bhardlimit)); + d->dqb_bsoftlimit = cpu_to_le64(v2_stoqb(m->dqb_bsoftlimit)); + d->dqb_curspace = cpu_to_le64(m->dqb_curspace); + d->dqb_btime = cpu_to_le64(m->dqb_btime); + d->dqb_id = cpu_to_le32(dquot->dq_id); + if (qtree_entry_unused(info, dp)) + d->dqb_itime = cpu_to_le64(1); +} + +static int v2r1_is_id(void *dp, struct dquot *dquot) { - struct v2_disk_dqblk *d = dp; + struct v2r1_disk_dqblk *d = dp; struct qtree_mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; @@ -207,7 +294,7 @@ static int v2_free_file_info(struct super_block *sb, int type) return 0; } -static struct quota_format_ops v2_format_ops = { +static const struct quota_format_ops v2_format_ops = { .check_quota_file = v2_check_quota_file, .read_file_info = v2_read_file_info, .write_file_info = v2_write_file_info, @@ -217,20 +304,32 @@ static struct quota_format_ops v2_format_ops = { .release_dqblk = v2_release_dquot, }; -static struct quota_format_type v2_quota_format = { +static struct quota_format_type v2r0_quota_format = { .qf_fmt_id = QFMT_VFS_V0, .qf_ops = &v2_format_ops, .qf_owner = THIS_MODULE }; +static struct quota_format_type v2r1_quota_format = { + .qf_fmt_id = QFMT_VFS_V1, + .qf_ops = &v2_format_ops, + .qf_owner = THIS_MODULE +}; + static int __init init_v2_quota_format(void) { - return register_quota_format(&v2_quota_format); + int ret; + + ret = register_quota_format(&v2r0_quota_format); + if (ret) + return ret; + return register_quota_format(&v2r1_quota_format); } static void __exit exit_v2_quota_format(void) { - unregister_quota_format(&v2_quota_format); + unregister_quota_format(&v2r0_quota_format); + unregister_quota_format(&v2r1_quota_format); } module_init(init_v2_quota_format); diff --git a/fs/quota/quotaio_v2.h b/fs/quota/quotaio_v2.h index 530fe580685c64abb2576f637f61454ee601c81c..f1966b42c2fdc07c3269a36402ab4bc3e2d9cb76 100644 --- a/fs/quota/quotaio_v2.h +++ b/fs/quota/quotaio_v2.h @@ -17,8 +17,8 @@ } #define V2_INITQVERSIONS {\ - 0, /* USRQUOTA */\ - 0 /* GRPQUOTA */\ + 1, /* USRQUOTA */\ + 1 /* GRPQUOTA */\ } /* First generic header */ @@ -32,7 +32,7 @@ struct v2_disk_dqheader { * (as it appears on disk) - the file is a radix tree whose leaves point * to blocks of these structures. */ -struct v2_disk_dqblk { +struct v2r0_disk_dqblk { __le32 dqb_id; /* id this quota applies to */ __le32 dqb_ihardlimit; /* absolute limit on allocated inodes */ __le32 dqb_isoftlimit; /* preferred inode limit */ @@ -44,6 +44,19 @@ struct v2_disk_dqblk { __le64 dqb_itime; /* time limit for excessive inode use */ }; +struct v2r1_disk_dqblk { + __le32 dqb_id; /* id this quota applies to */ + __le32 dqb_pad; + __le64 dqb_ihardlimit; /* absolute limit on allocated inodes */ + __le64 dqb_isoftlimit; /* preferred inode limit */ + __le64 dqb_curinodes; /* current # allocated inodes */ + __le64 dqb_bhardlimit; /* absolute limit on disk space (in QUOTABLOCK_SIZE) */ + __le64 dqb_bsoftlimit; /* preferred limit on disk space (in QUOTABLOCK_SIZE) */ + __le64 dqb_curspace; /* current space occupied (in bytes) */ + __le64 dqb_btime; /* time limit for excessive disk use */ + __le64 dqb_itime; /* time limit for excessive inode use */ +}; + /* Header with type and version specific information */ struct v2_disk_dqinfo { __le32 dqi_bgrace; /* Time before block soft limit becomes hard limit */ diff --git a/fs/sync.c b/fs/sync.c index d104591b066bf474f62f665e87e04154c4da5da1..36752a683481533566fda6910e11d4c8a0d66a41 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -295,10 +295,11 @@ SYSCALL_DEFINE1(fdatasync, unsigned int, fd) */ int generic_write_sync(struct file *file, loff_t pos, loff_t count) { - if (!(file->f_flags & O_SYNC) && !IS_SYNC(file->f_mapping->host)) + if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host)) return 0; return vfs_fsync_range(file, file->f_path.dentry, pos, - pos + count - 1, 1); + pos + count - 1, + (file->f_flags & __O_SYNC) ? 0 : 1); } EXPORT_SYMBOL(generic_write_sync); @@ -452,9 +453,7 @@ int do_sync_mapping_range(struct address_space *mapping, loff_t offset, ret = 0; if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) { - ret = wait_on_page_writeback_range(mapping, - offset >> PAGE_CACHE_SHIFT, - endbyte >> PAGE_CACHE_SHIFT); + ret = filemap_fdatawait_range(mapping, offset, endbyte); if (ret < 0) goto out; } @@ -467,9 +466,7 @@ int do_sync_mapping_range(struct address_space *mapping, loff_t offset, } if (flags & SYNC_FILE_RANGE_WAIT_AFTER) { - ret = wait_on_page_writeback_range(mapping, - offset >> PAGE_CACHE_SHIFT, - endbyte >> PAGE_CACHE_SHIFT); + ret = filemap_fdatawait_range(mapping, offset, endbyte); } out: return ret; diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index e0201837d24459fd466affe53827ee8fbc102cf0..f05f2303a8b8c60c80fb81a6059c0ebd39471b2f 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -25,7 +25,6 @@ #include "sysfs.h" DEFINE_MUTEX(sysfs_mutex); -DEFINE_MUTEX(sysfs_rename_mutex); DEFINE_SPINLOCK(sysfs_assoc_lock); static DEFINE_SPINLOCK(sysfs_ino_lock); @@ -84,46 +83,6 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) } } -/** - * sysfs_get_dentry - get dentry for the given sysfs_dirent - * @sd: sysfs_dirent of interest - * - * Get dentry for @sd. Dentry is looked up if currently not - * present. This function descends from the root looking up - * dentry for each step. - * - * LOCKING: - * mutex_lock(sysfs_rename_mutex) - * - * RETURNS: - * Pointer to found dentry on success, ERR_PTR() value on error. - */ -struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) -{ - struct dentry *dentry = dget(sysfs_sb->s_root); - - while (dentry->d_fsdata != sd) { - struct sysfs_dirent *cur; - struct dentry *parent; - - /* find the first ancestor which hasn't been looked up */ - cur = sd; - while (cur->s_parent != dentry->d_fsdata) - cur = cur->s_parent; - - /* look it up */ - parent = dentry; - mutex_lock(&parent->d_inode->i_mutex); - dentry = lookup_one_noperm(cur->s_name, parent); - mutex_unlock(&parent->d_inode->i_mutex); - dput(parent); - - if (IS_ERR(dentry)) - break; - } - return dentry; -} - /** * sysfs_get_active - get an active reference to sysfs_dirent * @sd: sysfs_dirent to get an active reference to @@ -298,7 +257,61 @@ void release_sysfs_dirent(struct sysfs_dirent * sd) goto repeat; } -static void sysfs_d_iput(struct dentry * dentry, struct inode * inode) +static int sysfs_dentry_delete(struct dentry *dentry) +{ + struct sysfs_dirent *sd = dentry->d_fsdata; + return !!(sd->s_flags & SYSFS_FLAG_REMOVED); +} + +static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd) +{ + struct sysfs_dirent *sd = dentry->d_fsdata; + int is_dir; + + mutex_lock(&sysfs_mutex); + + /* The sysfs dirent has been deleted */ + if (sd->s_flags & SYSFS_FLAG_REMOVED) + goto out_bad; + + /* The sysfs dirent has been moved? */ + if (dentry->d_parent->d_fsdata != sd->s_parent) + goto out_bad; + + /* The sysfs dirent has been renamed */ + if (strcmp(dentry->d_name.name, sd->s_name) != 0) + goto out_bad; + + mutex_unlock(&sysfs_mutex); +out_valid: + return 1; +out_bad: + /* Remove the dentry from the dcache hashes. + * If this is a deleted dentry we use d_drop instead of d_delete + * so sysfs doesn't need to cope with negative dentries. + * + * If this is a dentry that has simply been renamed we + * use d_drop to remove it from the dcache lookup on its + * old parent. If this dentry persists later when a lookup + * is performed at its new name the dentry will be readded + * to the dcache hashes. + */ + is_dir = (sysfs_type(sd) == SYSFS_DIR); + mutex_unlock(&sysfs_mutex); + if (is_dir) { + /* If we have submounts we must allow the vfs caches + * to lie about the state of the filesystem to prevent + * leaks and other nasty things. + */ + if (have_submounts(dentry)) + goto out_valid; + shrink_dcache_parent(dentry); + } + d_drop(dentry); + return 0; +} + +static void sysfs_dentry_iput(struct dentry *dentry, struct inode *inode) { struct sysfs_dirent * sd = dentry->d_fsdata; @@ -307,7 +320,9 @@ static void sysfs_d_iput(struct dentry * dentry, struct inode * inode) } static const struct dentry_operations sysfs_dentry_ops = { - .d_iput = sysfs_d_iput, + .d_revalidate = sysfs_dentry_revalidate, + .d_delete = sysfs_dentry_delete, + .d_iput = sysfs_dentry_iput, }; struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) @@ -344,12 +359,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) return NULL; } -static int sysfs_ilookup_test(struct inode *inode, void *arg) -{ - struct sysfs_dirent *sd = arg; - return inode->i_ino == sd->s_ino; -} - /** * sysfs_addrm_start - prepare for sysfs_dirent add/remove * @acxt: pointer to sysfs_addrm_cxt to be used @@ -357,47 +366,20 @@ static int sysfs_ilookup_test(struct inode *inode, void *arg) * * This function is called when the caller is about to add or * remove sysfs_dirent under @parent_sd. This function acquires - * sysfs_mutex, grabs inode for @parent_sd if available and lock - * i_mutex of it. @acxt is used to keep and pass context to + * sysfs_mutex. @acxt is used to keep and pass context to * other addrm functions. * * LOCKING: * Kernel thread context (may sleep). sysfs_mutex is locked on - * return. i_mutex of parent inode is locked on return if - * available. + * return. */ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *parent_sd) { - struct inode *inode; - memset(acxt, 0, sizeof(*acxt)); acxt->parent_sd = parent_sd; - /* Lookup parent inode. inode initialization is protected by - * sysfs_mutex, so inode existence can be determined by - * looking up inode while holding sysfs_mutex. - */ mutex_lock(&sysfs_mutex); - - inode = ilookup5(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test, - parent_sd); - if (inode) { - WARN_ON(inode->i_state & I_NEW); - - /* parent inode available */ - acxt->parent_inode = inode; - - /* sysfs_mutex is below i_mutex in lock hierarchy. - * First, trylock i_mutex. If fails, unlock - * sysfs_mutex and lock them in order. - */ - if (!mutex_trylock(&inode->i_mutex)) { - mutex_unlock(&sysfs_mutex); - mutex_lock(&inode->i_mutex); - mutex_lock(&sysfs_mutex); - } - } } /** @@ -422,18 +404,22 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, */ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) { + struct sysfs_inode_attrs *ps_iattr; + if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) return -EEXIST; sd->s_parent = sysfs_get(acxt->parent_sd); - if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) - inc_nlink(acxt->parent_inode); - - acxt->cnt++; - sysfs_link_sibling(sd); + /* Update timestamps on the parent */ + ps_iattr = acxt->parent_sd->s_iattr; + if (ps_iattr) { + struct iattr *ps_iattrs = &ps_iattr->ia_iattr; + ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; + } + return 0; } @@ -512,70 +498,22 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) */ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) { + struct sysfs_inode_attrs *ps_iattr; + BUG_ON(sd->s_flags & SYSFS_FLAG_REMOVED); sysfs_unlink_sibling(sd); + /* Update timestamps on the parent */ + ps_iattr = acxt->parent_sd->s_iattr; + if (ps_iattr) { + struct iattr *ps_iattrs = &ps_iattr->ia_iattr; + ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; + } + sd->s_flags |= SYSFS_FLAG_REMOVED; sd->s_sibling = acxt->removed; acxt->removed = sd; - - if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) - drop_nlink(acxt->parent_inode); - - acxt->cnt++; -} - -/** - * sysfs_drop_dentry - drop dentry for the specified sysfs_dirent - * @sd: target sysfs_dirent - * - * Drop dentry for @sd. @sd must have been unlinked from its - * parent on entry to this function such that it can't be looked - * up anymore. - */ -static void sysfs_drop_dentry(struct sysfs_dirent *sd) -{ - struct inode *inode; - struct dentry *dentry; - - inode = ilookup(sysfs_sb, sd->s_ino); - if (!inode) - return; - - /* Drop any existing dentries associated with sd. - * - * For the dentry to be properly freed we need to grab a - * reference to the dentry under the dcache lock, unhash it, - * and then put it. The playing with the dentry count allows - * dput to immediately free the dentry if it is not in use. - */ -repeat: - spin_lock(&dcache_lock); - list_for_each_entry(dentry, &inode->i_dentry, d_alias) { - if (d_unhashed(dentry)) - continue; - dget_locked(dentry); - spin_lock(&dentry->d_lock); - __d_drop(dentry); - spin_unlock(&dentry->d_lock); - spin_unlock(&dcache_lock); - dput(dentry); - goto repeat; - } - spin_unlock(&dcache_lock); - - /* adjust nlink and update timestamp */ - mutex_lock(&inode->i_mutex); - - inode->i_ctime = CURRENT_TIME; - drop_nlink(inode); - if (sysfs_type(sd) == SYSFS_DIR) - drop_nlink(inode); - - mutex_unlock(&inode->i_mutex); - - iput(inode); } /** @@ -584,25 +522,15 @@ repeat: * * Finish up sysfs_dirent add/remove. Resources acquired by * sysfs_addrm_start() are released and removed sysfs_dirents are - * cleaned up. Timestamps on the parent inode are updated. + * cleaned up. * * LOCKING: - * All mutexes acquired by sysfs_addrm_start() are released. + * sysfs_mutex is released. */ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) { /* release resources acquired by sysfs_addrm_start() */ mutex_unlock(&sysfs_mutex); - if (acxt->parent_inode) { - struct inode *inode = acxt->parent_inode; - - /* if added/removed, update timestamps on the parent */ - if (acxt->cnt) - inode->i_ctime = inode->i_mtime = CURRENT_TIME; - - mutex_unlock(&inode->i_mutex); - iput(inode); - } /* kill removed sysfs_dirents */ while (acxt->removed) { @@ -611,7 +539,6 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) acxt->removed = sd->s_sibling; sd->s_sibling = NULL; - sysfs_drop_dentry(sd); sysfs_deactivate(sd); unmap_bin_file(sd); sysfs_put(sd); @@ -751,10 +678,15 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, } /* instantiate and hash dentry */ - dentry->d_op = &sysfs_dentry_ops; - dentry->d_fsdata = sysfs_get(sd); - d_instantiate(dentry, inode); - d_rehash(dentry); + ret = d_find_alias(inode); + if (!ret) { + dentry->d_op = &sysfs_dentry_ops; + dentry->d_fsdata = sysfs_get(sd); + d_add(dentry, inode); + } else { + d_move(ret, dentry); + iput(inode); + } out_unlock: mutex_unlock(&sysfs_mutex); @@ -763,7 +695,9 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, const struct inode_operations sysfs_dir_inode_operations = { .lookup = sysfs_lookup, + .permission = sysfs_permission, .setattr = sysfs_setattr, + .getattr = sysfs_getattr, .setxattr = sysfs_setxattr, }; @@ -826,141 +760,65 @@ void sysfs_remove_dir(struct kobject * kobj) __sysfs_remove_dir(sd); } -int sysfs_rename_dir(struct kobject * kobj, const char *new_name) +int sysfs_rename(struct sysfs_dirent *sd, + struct sysfs_dirent *new_parent_sd, const char *new_name) { - struct sysfs_dirent *sd = kobj->sd; - struct dentry *parent = NULL; - struct dentry *old_dentry = NULL, *new_dentry = NULL; const char *dup_name = NULL; int error; - mutex_lock(&sysfs_rename_mutex); + mutex_lock(&sysfs_mutex); error = 0; - if (strcmp(sd->s_name, new_name) == 0) + if ((sd->s_parent == new_parent_sd) && + (strcmp(sd->s_name, new_name) == 0)) goto out; /* nothing to rename */ - /* get the original dentry */ - old_dentry = sysfs_get_dentry(sd); - if (IS_ERR(old_dentry)) { - error = PTR_ERR(old_dentry); - old_dentry = NULL; - goto out; - } - - parent = old_dentry->d_parent; - - /* lock parent and get dentry for new name */ - mutex_lock(&parent->d_inode->i_mutex); - mutex_lock(&sysfs_mutex); - error = -EEXIST; - if (sysfs_find_dirent(sd->s_parent, new_name)) - goto out_unlock; - - error = -ENOMEM; - new_dentry = d_alloc_name(parent, new_name); - if (!new_dentry) - goto out_unlock; + if (sysfs_find_dirent(new_parent_sd, new_name)) + goto out; /* rename sysfs_dirent */ - error = -ENOMEM; - new_name = dup_name = kstrdup(new_name, GFP_KERNEL); - if (!new_name) - goto out_unlock; - - dup_name = sd->s_name; - sd->s_name = new_name; + if (strcmp(sd->s_name, new_name) != 0) { + error = -ENOMEM; + new_name = dup_name = kstrdup(new_name, GFP_KERNEL); + if (!new_name) + goto out; + + dup_name = sd->s_name; + sd->s_name = new_name; + } - /* rename */ - d_add(new_dentry, NULL); - d_move(old_dentry, new_dentry); + /* Remove from old parent's list and insert into new parent's list. */ + if (sd->s_parent != new_parent_sd) { + sysfs_unlink_sibling(sd); + sysfs_get(new_parent_sd); + sysfs_put(sd->s_parent); + sd->s_parent = new_parent_sd; + sysfs_link_sibling(sd); + } error = 0; - out_unlock: + out: mutex_unlock(&sysfs_mutex); - mutex_unlock(&parent->d_inode->i_mutex); kfree(dup_name); - dput(old_dentry); - dput(new_dentry); - out: - mutex_unlock(&sysfs_rename_mutex); return error; } +int sysfs_rename_dir(struct kobject *kobj, const char *new_name) +{ + return sysfs_rename(kobj->sd, kobj->sd->s_parent, new_name); +} + int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) { struct sysfs_dirent *sd = kobj->sd; struct sysfs_dirent *new_parent_sd; - struct dentry *old_parent, *new_parent = NULL; - struct dentry *old_dentry = NULL, *new_dentry = NULL; - int error; - mutex_lock(&sysfs_rename_mutex); BUG_ON(!sd->s_parent); - new_parent_sd = (new_parent_kobj && new_parent_kobj->sd) ? + new_parent_sd = new_parent_kobj && new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; - error = 0; - if (sd->s_parent == new_parent_sd) - goto out; /* nothing to move */ - - /* get dentries */ - old_dentry = sysfs_get_dentry(sd); - if (IS_ERR(old_dentry)) { - error = PTR_ERR(old_dentry); - old_dentry = NULL; - goto out; - } - old_parent = old_dentry->d_parent; - - new_parent = sysfs_get_dentry(new_parent_sd); - if (IS_ERR(new_parent)) { - error = PTR_ERR(new_parent); - new_parent = NULL; - goto out; - } - -again: - mutex_lock(&old_parent->d_inode->i_mutex); - if (!mutex_trylock(&new_parent->d_inode->i_mutex)) { - mutex_unlock(&old_parent->d_inode->i_mutex); - goto again; - } - mutex_lock(&sysfs_mutex); - - error = -EEXIST; - if (sysfs_find_dirent(new_parent_sd, sd->s_name)) - goto out_unlock; - - error = -ENOMEM; - new_dentry = d_alloc_name(new_parent, sd->s_name); - if (!new_dentry) - goto out_unlock; - - error = 0; - d_add(new_dentry, NULL); - d_move(old_dentry, new_dentry); - - /* Remove from old parent's list and insert into new parent's list. */ - sysfs_unlink_sibling(sd); - sysfs_get(new_parent_sd); - drop_nlink(old_parent->d_inode); - sysfs_put(sd->s_parent); - sd->s_parent = new_parent_sd; - inc_nlink(new_parent->d_inode); - sysfs_link_sibling(sd); - - out_unlock: - mutex_unlock(&sysfs_mutex); - mutex_unlock(&new_parent->d_inode->i_mutex); - mutex_unlock(&old_parent->d_inode->i_mutex); - out: - dput(new_parent); - dput(old_dentry); - dput(new_dentry); - mutex_unlock(&sysfs_rename_mutex); - return error; + return sysfs_rename(sd, new_parent_sd, sd->s_name); } /* Relationship between s_mode and the DT_xxx types */ diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index f5ea4680f15fdca8a009f66a979bd6d3805244f6..dc30d9e31683cd64f5dfdccc6d645bdc16c1de54 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -579,46 +579,23 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); */ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) { - struct sysfs_dirent *victim_sd = NULL; - struct dentry *victim = NULL; - struct inode * inode; + struct sysfs_dirent *sd; struct iattr newattrs; int rc; - rc = -ENOENT; - victim_sd = sysfs_get_dirent(kobj->sd, attr->name); - if (!victim_sd) - goto out; + mutex_lock(&sysfs_mutex); - mutex_lock(&sysfs_rename_mutex); - victim = sysfs_get_dentry(victim_sd); - mutex_unlock(&sysfs_rename_mutex); - if (IS_ERR(victim)) { - rc = PTR_ERR(victim); - victim = NULL; + rc = -ENOENT; + sd = sysfs_find_dirent(kobj->sd, attr->name); + if (!sd) goto out; - } - - inode = victim->d_inode; - - mutex_lock(&inode->i_mutex); - newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - newattrs.ia_ctime = current_fs_time(inode->i_sb); - rc = sysfs_setattr(victim, &newattrs); + newattrs.ia_mode = (mode & S_IALLUGO) | (sd->s_mode & ~S_IALLUGO); + newattrs.ia_valid = ATTR_MODE; + rc = sysfs_sd_setattr(sd, &newattrs); - if (rc == 0) { - fsnotify_change(victim, newattrs.ia_valid); - mutex_lock(&sysfs_mutex); - victim_sd->s_mode = newattrs.ia_mode; - mutex_unlock(&sysfs_mutex); - } - - mutex_unlock(&inode->i_mutex); out: - dput(victim); - sysfs_put(victim_sd); + mutex_unlock(&sysfs_mutex); return rc; } EXPORT_SYMBOL_GPL(sysfs_chmod_file); diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index e28cecf179f50d6c746312baac37b045a326d5da..220b758523aed175e426a9e61a2085430e034364 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -37,7 +37,9 @@ static struct backing_dev_info sysfs_backing_dev_info = { }; static const struct inode_operations sysfs_inode_operations ={ + .permission = sysfs_permission, .setattr = sysfs_setattr, + .getattr = sysfs_getattr, .setxattr = sysfs_setxattr, }; @@ -46,7 +48,7 @@ int __init sysfs_inode_init(void) return bdi_init(&sysfs_backing_dev_info); } -struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd) +static struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd) { struct sysfs_inode_attrs *attrs; struct iattr *iattrs; @@ -64,30 +66,15 @@ struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd) return attrs; } -int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) + +int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr * iattr) { - struct inode * inode = dentry->d_inode; - struct sysfs_dirent * sd = dentry->d_fsdata; struct sysfs_inode_attrs *sd_attrs; struct iattr *iattrs; unsigned int ia_valid = iattr->ia_valid; - int error; - - if (!sd) - return -EINVAL; sd_attrs = sd->s_iattr; - error = inode_change_ok(inode, iattr); - if (error) - return error; - - iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ - - error = inode_setattr(inode, iattr); - if (error) - return error; - if (!sd_attrs) { /* setting attributes for the first time, allocate now */ sd_attrs = sysfs_init_inode_attrs(sd); @@ -103,42 +90,78 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) if (ia_valid & ATTR_GID) iattrs->ia_gid = iattr->ia_gid; if (ia_valid & ATTR_ATIME) - iattrs->ia_atime = timespec_trunc(iattr->ia_atime, - inode->i_sb->s_time_gran); + iattrs->ia_atime = iattr->ia_atime; if (ia_valid & ATTR_MTIME) - iattrs->ia_mtime = timespec_trunc(iattr->ia_mtime, - inode->i_sb->s_time_gran); + iattrs->ia_mtime = iattr->ia_mtime; if (ia_valid & ATTR_CTIME) - iattrs->ia_ctime = timespec_trunc(iattr->ia_ctime, - inode->i_sb->s_time_gran); + iattrs->ia_ctime = iattr->ia_ctime; if (ia_valid & ATTR_MODE) { umode_t mode = iattr->ia_mode; - - if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) - mode &= ~S_ISGID; iattrs->ia_mode = sd->s_mode = mode; } } + return 0; +} + +int sysfs_setattr(struct dentry *dentry, struct iattr *iattr) +{ + struct inode *inode = dentry->d_inode; + struct sysfs_dirent *sd = dentry->d_fsdata; + int error; + + if (!sd) + return -EINVAL; + + error = inode_change_ok(inode, iattr); + if (error) + return error; + + iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ + + error = inode_setattr(inode, iattr); + if (error) + return error; + + mutex_lock(&sysfs_mutex); + error = sysfs_sd_setattr(sd, iattr); + mutex_unlock(&sysfs_mutex); + return error; } +static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, u32 *secdata_len) +{ + struct sysfs_inode_attrs *iattrs; + void *old_secdata; + size_t old_secdata_len; + + iattrs = sd->s_iattr; + if (!iattrs) + iattrs = sysfs_init_inode_attrs(sd); + if (!iattrs) + return -ENOMEM; + + old_secdata = iattrs->ia_secdata; + old_secdata_len = iattrs->ia_secdata_len; + + iattrs->ia_secdata = *secdata; + iattrs->ia_secdata_len = *secdata_len; + + *secdata = old_secdata; + *secdata_len = old_secdata_len; + return 0; +} + int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { struct sysfs_dirent *sd = dentry->d_fsdata; - struct sysfs_inode_attrs *iattrs; void *secdata; int error; u32 secdata_len = 0; if (!sd) return -EINVAL; - if (!sd->s_iattr) - sd->s_iattr = sysfs_init_inode_attrs(sd); - if (!sd->s_iattr) - return -ENOMEM; - - iattrs = sd->s_iattr; if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) { const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; @@ -150,12 +173,13 @@ int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, &secdata, &secdata_len); if (error) goto out; - if (iattrs->ia_secdata) - security_release_secctx(iattrs->ia_secdata, - iattrs->ia_secdata_len); - iattrs->ia_secdata = secdata; - iattrs->ia_secdata_len = secdata_len; + mutex_lock(&sysfs_mutex); + error = sysfs_sd_setsecdata(sd, &secdata, &secdata_len); + mutex_unlock(&sysfs_mutex); + + if (secdata) + security_release_secctx(secdata, secdata_len); } else return -EINVAL; out: @@ -170,7 +194,6 @@ static inline void set_default_inode_attr(struct inode * inode, mode_t mode) static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) { - inode->i_mode = iattr->ia_mode; inode->i_uid = iattr->ia_uid; inode->i_gid = iattr->ia_gid; inode->i_atime = iattr->ia_atime; @@ -178,17 +201,6 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) inode->i_ctime = iattr->ia_ctime; } - -/* - * sysfs has a different i_mutex lock order behavior for i_mutex than other - * filesystems; sysfs i_mutex is called in many places with subsystem locks - * held. At the same time, many of the VFS locking rules do not apply to - * sysfs at all (cross directory rename for example). To untangle this mess - * (which gives false positives in lockdep), we're giving sysfs inodes their - * own class for i_mutex. - */ -static struct lock_class_key sysfs_inode_imutex_key; - static int sysfs_count_nlink(struct sysfs_dirent *sd) { struct sysfs_dirent *child; @@ -201,38 +213,55 @@ static int sysfs_count_nlink(struct sysfs_dirent *sd) return nr + 2; } +static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode) +{ + struct sysfs_inode_attrs *iattrs = sd->s_iattr; + + inode->i_mode = sd->s_mode; + if (iattrs) { + /* sysfs_dirent has non-default attributes + * get them from persistent copy in sysfs_dirent + */ + set_inode_attr(inode, &iattrs->ia_iattr); + security_inode_notifysecctx(inode, + iattrs->ia_secdata, + iattrs->ia_secdata_len); + } + + if (sysfs_type(sd) == SYSFS_DIR) + inode->i_nlink = sysfs_count_nlink(sd); +} + +int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) +{ + struct sysfs_dirent *sd = dentry->d_fsdata; + struct inode *inode = dentry->d_inode; + + mutex_lock(&sysfs_mutex); + sysfs_refresh_inode(sd, inode); + mutex_unlock(&sysfs_mutex); + + generic_fillattr(inode, stat); + return 0; +} + static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) { struct bin_attribute *bin_attr; - struct sysfs_inode_attrs *iattrs; inode->i_private = sysfs_get(sd); inode->i_mapping->a_ops = &sysfs_aops; inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; inode->i_op = &sysfs_inode_operations; - inode->i_ino = sd->s_ino; - lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key); - iattrs = sd->s_iattr; - if (iattrs) { - /* sysfs_dirent has non-default attributes - * get them for the new inode from persistent copy - * in sysfs_dirent - */ - set_inode_attr(inode, &iattrs->ia_iattr); - if (iattrs->ia_secdata) - security_inode_notifysecctx(inode, - iattrs->ia_secdata, - iattrs->ia_secdata_len); - } else - set_default_inode_attr(inode, sd->s_mode); + set_default_inode_attr(inode, sd->s_mode); + sysfs_refresh_inode(sd, inode); /* initialize inode according to type */ switch (sysfs_type(sd)) { case SYSFS_DIR: inode->i_op = &sysfs_dir_inode_operations; inode->i_fop = &sysfs_dir_operations; - inode->i_nlink = sysfs_count_nlink(sd); break; case SYSFS_KOBJ_ATTR: inode->i_size = PAGE_SIZE; @@ -315,3 +344,14 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) else return -ENOENT; } + +int sysfs_permission(struct inode *inode, int mask) +{ + struct sysfs_dirent *sd = inode->i_private; + + mutex_lock(&sysfs_mutex); + sysfs_refresh_inode(sd, inode); + mutex_unlock(&sysfs_mutex); + + return generic_permission(inode, mask, NULL); +} diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index c5081ad77026e95689e58fda616dc0784b958044..c5eff49fa41beb9676992504d7ae37d46f0c16f4 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -210,10 +210,13 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *co } const struct inode_operations sysfs_symlink_inode_operations = { - .setxattr = sysfs_setxattr, - .readlink = generic_readlink, - .follow_link = sysfs_follow_link, - .put_link = sysfs_put_link, + .setxattr = sysfs_setxattr, + .readlink = generic_readlink, + .follow_link = sysfs_follow_link, + .put_link = sysfs_put_link, + .setattr = sysfs_setattr, + .getattr = sysfs_getattr, + .permission = sysfs_permission, }; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index af4c4e7482ac80cd41d9072fcf1a9150a626694c..ca52e7b9d8f86029085cd85c6ea1a9db12cc2838 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -89,9 +89,7 @@ static inline unsigned int sysfs_type(struct sysfs_dirent *sd) */ struct sysfs_addrm_cxt { struct sysfs_dirent *parent_sd; - struct inode *parent_inode; struct sysfs_dirent *removed; - int cnt; }; /* @@ -105,7 +103,6 @@ extern struct kmem_cache *sysfs_dir_cachep; * dir.c */ extern struct mutex sysfs_mutex; -extern struct mutex sysfs_rename_mutex; extern spinlock_t sysfs_assoc_lock; extern const struct file_operations sysfs_dir_operations; @@ -133,6 +130,9 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name, struct sysfs_dirent **p_sd); void sysfs_remove_subdir(struct sysfs_dirent *sd); +int sysfs_rename(struct sysfs_dirent *sd, + struct sysfs_dirent *new_parent_sd, const char *new_name); + static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd) { if (sd) { @@ -155,7 +155,10 @@ static inline void __sysfs_put(struct sysfs_dirent *sd) */ struct inode *sysfs_get_inode(struct sysfs_dirent *sd); void sysfs_delete_inode(struct inode *inode); +int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); +int sysfs_permission(struct inode *inode, int mask); int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); +int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index dbc093afd946c98fee961b68a0131054edbf5014..8a771c59ac3eab2e460f5d6f337155215ee014a2 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -2014,7 +2014,7 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr, inum = key_inum_flash(c, &dent->key); fscki1 = read_add_inode(c, priv, inum); if (IS_ERR(fscki1)) { - err = PTR_ERR(fscki); + err = PTR_ERR(fscki1); ubifs_err("error %d while processing entry node and " "trying to find parent inode node %lu", err, (unsigned long)inum); diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 1009adc8d602f264787af5b12d3642b6303df2c8..39849f887e724602fa54d1feedf0d63090fe3d6e 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -1389,7 +1389,6 @@ static ssize_t ubifs_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { int err; - ssize_t ret; struct inode *inode = iocb->ki_filp->f_mapping->host; struct ubifs_info *c = inode->i_sb->s_fs_info; @@ -1397,17 +1396,7 @@ static ssize_t ubifs_aio_write(struct kiocb *iocb, const struct iovec *iov, if (err) return err; - ret = generic_file_aio_write(iocb, iov, nr_segs, pos); - if (ret < 0) - return ret; - - if (ret > 0 && (IS_SYNC(inode) || iocb->ki_filp->f_flags & O_SYNC)) { - err = ubifs_sync_wbufs_by_inode(c, inode); - if (err) - return err; - } - - return ret; + return generic_file_aio_write(iocb, iov, nr_segs, pos); } static int ubifs_set_page_dirty(struct page *page) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 333e181ee9877ed4b992967b268ea193cf9ee894..943ad5624530bfc65d8d47f9d1b5c9721939d454 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1842,22 +1842,32 @@ const struct super_operations ubifs_super_operations = { * @name: UBI volume name * @mode: UBI volume open mode * - * There are several ways to specify UBI volumes when mounting UBIFS: - * o ubiX_Y - UBI device number X, volume Y; - * o ubiY - UBI device number 0, volume Y; + * The primary method of mounting UBIFS is by specifying the UBI volume + * character device node path. However, UBIFS may also be mounted withoug any + * character device node using one of the following methods: + * + * o ubiX_Y - mount UBI device number X, volume Y; + * o ubiY - mount UBI device number 0, volume Y; * o ubiX:NAME - mount UBI device X, volume with name NAME; * o ubi:NAME - mount UBI device 0, volume with name NAME. * * Alternative '!' separator may be used instead of ':' (because some shells * like busybox may interpret ':' as an NFS host name separator). This function - * returns ubi volume object in case of success and a negative error code in - * case of failure. + * returns UBI volume description object in case of success and a negative + * error code in case of failure. */ static struct ubi_volume_desc *open_ubi(const char *name, int mode) { + struct ubi_volume_desc *ubi; int dev, vol; char *endptr; + /* First, try to open using the device node path method */ + ubi = ubi_open_volume_path(name, mode); + if (!IS_ERR(ubi)) + return ubi; + + /* Try the "nodev" method */ if (name[0] != 'u' || name[1] != 'b' || name[2] != 'i') return ERR_PTR(-EINVAL); diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index 1e068535b58bfc78b0970dc3ccb34e03cc7c1ecb..82372e332f08521010183f0ce6c2a674f7912b7f 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c @@ -440,7 +440,7 @@ static void udf_table_free_blocks(struct super_block *sb, (bloc->logicalBlockNum + count) > partmap->s_partition_len) { udf_debug("%d < %d || %d + %d > %d\n", - bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count, + bloc->logicalBlockNum, 0, bloc->logicalBlockNum, count, partmap->s_partition_len); goto error_return; } diff --git a/fs/udf/file.c b/fs/udf/file.c index b80cbd78833cf7aa99430016b84f29b038d5e098..f311d509b6a3541f5f93f81e785dd820b82f7daf 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -196,6 +196,7 @@ static int udf_release_file(struct inode *inode, struct file *filp) mutex_lock(&inode->i_mutex); lock_kernel(); udf_discard_prealloc(inode); + udf_truncate_tail_extent(inode); unlock_kernel(); mutex_unlock(&inode->i_mutex); } diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 6d24c2c63f9353c7baf7e9c7158360c1ef40a9f4..f90231eb29165785d14369191a00fc458dafbc9c 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -97,15 +97,17 @@ no_delete: */ void udf_clear_inode(struct inode *inode) { - struct udf_inode_info *iinfo; - if (!(inode->i_sb->s_flags & MS_RDONLY)) { - lock_kernel(); - udf_truncate_tail_extent(inode); - unlock_kernel(); - write_inode_now(inode, 0); - invalidate_inode_buffers(inode); + struct udf_inode_info *iinfo = UDF_I(inode); + + if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && + inode->i_size != iinfo->i_lenExtents) { + printk(KERN_WARNING "UDF-fs (%s): Inode %lu (mode %o) has " + "inode size %llu different from extent lenght %llu. " + "Filesystem need not be standards compliant.\n", + inode->i_sb->s_id, inode->i_ino, inode->i_mode, + (unsigned long long)inode->i_size, + (unsigned long long)iinfo->i_lenExtents); } - iinfo = UDF_I(inode); kfree(iinfo->i_ext.i_data); iinfo->i_ext.i_data = NULL; } @@ -198,7 +200,6 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, int newblock; struct buffer_head *dbh = NULL; struct kernel_lb_addr eloc; - uint32_t elen; uint8_t alloctype; struct extent_position epos; @@ -273,12 +274,11 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, eloc.logicalBlockNum = *block; eloc.partitionReferenceNum = iinfo->i_location.partitionReferenceNum; - elen = inode->i_sb->s_blocksize; - iinfo->i_lenExtents = elen; + iinfo->i_lenExtents = inode->i_size; epos.bh = NULL; epos.block = iinfo->i_location; epos.offset = udf_file_entry_alloc_offset(inode); - udf_add_aext(inode, &epos, &eloc, elen, 0); + udf_add_aext(inode, &epos, &eloc, inode->i_size, 0); /* UniqueID stuff */ brelse(epos.bh); diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 21dad8c608f955bfac8933e7fea665f0e67a8491..cd2115060fdcc728aeefc7a21e80f6fc6af9c28c 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -408,15 +408,6 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, } add: - /* Is there any extent whose size we need to round up? */ - if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && elen) { - elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1); - if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - epos.offset -= sizeof(struct short_ad); - else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - epos.offset -= sizeof(struct long_ad); - udf_write_aext(dir, &epos, &eloc, elen, 1); - } f_pos += nfidlen; if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB && @@ -439,6 +430,7 @@ add: udf_current_aext(dir, &epos, &eloc, &elen, 1); } + /* Entry fits into current block? */ if (sb->s_blocksize - fibh->eoffset >= nfidlen) { fibh->soffset = fibh->eoffset; fibh->eoffset += nfidlen; @@ -462,6 +454,16 @@ add: (fibh->sbh->b_data + fibh->soffset); } } else { + /* Round up last extent in the file */ + elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1); + if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) + epos.offset -= sizeof(struct short_ad); + else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) + epos.offset -= sizeof(struct long_ad); + udf_write_aext(dir, &epos, &eloc, elen, 1); + dinfo->i_lenExtents = (dinfo->i_lenExtents + sb->s_blocksize + - 1) & ~(sb->s_blocksize - 1); + fibh->soffset = fibh->eoffset - sb->s_blocksize; fibh->eoffset += nfidlen - sb->s_blocksize; if (fibh->sbh != fibh->ebh) { @@ -508,6 +510,20 @@ add: dir->i_size += nfidlen; if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) dinfo->i_lenAlloc += nfidlen; + else { + /* Find the last extent and truncate it to proper size */ + while (udf_next_aext(dir, &epos, &eloc, &elen, 1) == + (EXT_RECORDED_ALLOCATED >> 30)) + ; + elen -= dinfo->i_lenExtents - dir->i_size; + if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) + epos.offset -= sizeof(struct short_ad); + else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) + epos.offset -= sizeof(struct long_ad); + udf_write_aext(dir, &epos, &eloc, elen, 1); + dinfo->i_lenExtents = dir->i_size; + } + mark_inode_dirty(dir); goto out_ok; } else { @@ -922,7 +938,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, block = udf_get_pblock(inode->i_sb, block, iinfo->i_location.partitionReferenceNum, 0); - epos.bh = udf_tread(inode->i_sb, block); + epos.bh = udf_tgetblk(inode->i_sb, block); lock_buffer(epos.bh); memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize); set_buffer_uptodate(epos.bh); @@ -999,6 +1015,8 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, inode->i_size = elen; if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) iinfo->i_lenAlloc = inode->i_size; + else + udf_truncate_tail_extent(inode); mark_inode_dirty(inode); fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); diff --git a/fs/udf/super.c b/fs/udf/super.c index 9d1b8c2e6c45bcc3d5428ef2095f718b970a139f..1e4543cbcd276decb1b43942e999b9f2f851b145 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1078,21 +1078,39 @@ static int udf_fill_partdesc_info(struct super_block *sb, return 0; } -static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) +static void udf_find_vat_block(struct super_block *sb, int p_index, + int type1_index, sector_t start_block) { struct udf_sb_info *sbi = UDF_SB(sb); struct udf_part_map *map = &sbi->s_partmaps[p_index]; + sector_t vat_block; struct kernel_lb_addr ino; + + /* + * VAT file entry is in the last recorded block. Some broken disks have + * it a few blocks before so try a bit harder... + */ + ino.partitionReferenceNum = type1_index; + for (vat_block = start_block; + vat_block >= map->s_partition_root && + vat_block >= start_block - 3 && + !sbi->s_vat_inode; vat_block--) { + ino.logicalBlockNum = vat_block - map->s_partition_root; + sbi->s_vat_inode = udf_iget(sb, &ino); + } +} + +static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) +{ + struct udf_sb_info *sbi = UDF_SB(sb); + struct udf_part_map *map = &sbi->s_partmaps[p_index]; struct buffer_head *bh = NULL; struct udf_inode_info *vati; uint32_t pos; struct virtualAllocationTable20 *vat20; sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; - /* VAT file entry is in the last recorded block */ - ino.partitionReferenceNum = type1_index; - ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root; - sbi->s_vat_inode = udf_iget(sb, &ino); + udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block); if (!sbi->s_vat_inode && sbi->s_last_block != blocks - 1) { printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the" @@ -1100,9 +1118,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) "block of the device (%lu).\n", (unsigned long)sbi->s_last_block, (unsigned long)blocks - 1); - ino.partitionReferenceNum = type1_index; - ino.logicalBlockNum = blocks - 1 - map->s_partition_root; - sbi->s_vat_inode = udf_iget(sb, &ino); + udf_find_vat_block(sb, p_index, type1_index, blocks - 1); } if (!sbi->s_vat_inode) return 1; diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 70f989895d15bfe4ab9d9df2241196eed764d54a..87813e405cef811ddc303608b51ea94d869e84d7 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -235,71 +235,36 @@ xfs_setfilesize( } /* - * Buffered IO write completion for delayed allocate extents. + * IO write completion. */ STATIC void -xfs_end_bio_delalloc( - struct work_struct *work) -{ - xfs_ioend_t *ioend = - container_of(work, xfs_ioend_t, io_work); - - xfs_setfilesize(ioend); - xfs_destroy_ioend(ioend); -} - -/* - * Buffered IO write completion for regular, written extents. - */ -STATIC void -xfs_end_bio_written( - struct work_struct *work) -{ - xfs_ioend_t *ioend = - container_of(work, xfs_ioend_t, io_work); - - xfs_setfilesize(ioend); - xfs_destroy_ioend(ioend); -} - -/* - * IO write completion for unwritten extents. - * - * Issue transactions to convert a buffer range from unwritten - * to written extents. - */ -STATIC void -xfs_end_bio_unwritten( +xfs_end_io( struct work_struct *work) { xfs_ioend_t *ioend = container_of(work, xfs_ioend_t, io_work); struct xfs_inode *ip = XFS_I(ioend->io_inode); - xfs_off_t offset = ioend->io_offset; - size_t size = ioend->io_size; - - if (likely(!ioend->io_error)) { - if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { - int error; - error = xfs_iomap_write_unwritten(ip, offset, size); - if (error) - ioend->io_error = error; - } - xfs_setfilesize(ioend); - } - xfs_destroy_ioend(ioend); -} -/* - * IO read completion for regular, written extents. - */ -STATIC void -xfs_end_bio_read( - struct work_struct *work) -{ - xfs_ioend_t *ioend = - container_of(work, xfs_ioend_t, io_work); + /* + * For unwritten extents we need to issue transactions to convert a + * range to normal written extens after the data I/O has finished. + */ + if (ioend->io_type == IOMAP_UNWRITTEN && + likely(!ioend->io_error && !XFS_FORCED_SHUTDOWN(ip->i_mount))) { + int error; + + error = xfs_iomap_write_unwritten(ip, ioend->io_offset, + ioend->io_size); + if (error) + ioend->io_error = error; + } + /* + * We might have to update the on-disk file size after extending + * writes. + */ + if (ioend->io_type != IOMAP_READ) + xfs_setfilesize(ioend); xfs_destroy_ioend(ioend); } @@ -314,10 +279,10 @@ xfs_finish_ioend( int wait) { if (atomic_dec_and_test(&ioend->io_remaining)) { - struct workqueue_struct *wq = xfsdatad_workqueue; - if (ioend->io_work.func == xfs_end_bio_unwritten) - wq = xfsconvertd_workqueue; + struct workqueue_struct *wq; + wq = (ioend->io_type == IOMAP_UNWRITTEN) ? + xfsconvertd_workqueue : xfsdatad_workqueue; queue_work(wq, &ioend->io_work); if (wait) flush_workqueue(wq); @@ -355,15 +320,7 @@ xfs_alloc_ioend( ioend->io_offset = 0; ioend->io_size = 0; - if (type == IOMAP_UNWRITTEN) - INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten); - else if (type == IOMAP_DELAY) - INIT_WORK(&ioend->io_work, xfs_end_bio_delalloc); - else if (type == IOMAP_READ) - INIT_WORK(&ioend->io_work, xfs_end_bio_read); - else - INIT_WORK(&ioend->io_work, xfs_end_bio_written); - + INIT_WORK(&ioend->io_work, xfs_end_io); return ioend; } @@ -380,7 +337,7 @@ xfs_map_blocks( return -xfs_iomap(XFS_I(inode), offset, count, flags, mapp, &nmaps); } -STATIC_INLINE int +STATIC int xfs_iomap_valid( xfs_iomap_t *iomapp, loff_t offset) @@ -412,8 +369,9 @@ xfs_end_bio( STATIC void xfs_submit_ioend_bio( - xfs_ioend_t *ioend, - struct bio *bio) + struct writeback_control *wbc, + xfs_ioend_t *ioend, + struct bio *bio) { atomic_inc(&ioend->io_remaining); bio->bi_private = ioend; @@ -426,7 +384,8 @@ xfs_submit_ioend_bio( if (xfs_ioend_new_eof(ioend)) xfs_mark_inode_dirty_sync(XFS_I(ioend->io_inode)); - submit_bio(WRITE, bio); + submit_bio(wbc->sync_mode == WB_SYNC_ALL ? + WRITE_SYNC_PLUG : WRITE, bio); ASSERT(!bio_flagged(bio, BIO_EOPNOTSUPP)); bio_put(bio); } @@ -505,6 +464,7 @@ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh) */ STATIC void xfs_submit_ioend( + struct writeback_control *wbc, xfs_ioend_t *ioend) { xfs_ioend_t *head = ioend; @@ -533,19 +493,19 @@ xfs_submit_ioend( retry: bio = xfs_alloc_ioend_bio(bh); } else if (bh->b_blocknr != lastblock + 1) { - xfs_submit_ioend_bio(ioend, bio); + xfs_submit_ioend_bio(wbc, ioend, bio); goto retry; } if (bio_add_buffer(bio, bh) != bh->b_size) { - xfs_submit_ioend_bio(ioend, bio); + xfs_submit_ioend_bio(wbc, ioend, bio); goto retry; } lastblock = bh->b_blocknr; } if (bio) - xfs_submit_ioend_bio(ioend, bio); + xfs_submit_ioend_bio(wbc, ioend, bio); xfs_finish_ioend(ioend, 0); } while ((ioend = next) != NULL); } @@ -1191,7 +1151,7 @@ xfs_page_state_convert( } if (iohead) - xfs_submit_ioend(iohead); + xfs_submit_ioend(wbc, iohead); return page_dirty; @@ -1528,7 +1488,7 @@ xfs_end_io_direct( * didn't map an unwritten extent so switch it's completion * handler. */ - INIT_WORK(&ioend->io_work, xfs_end_bio_written); + ioend->io_type = IOMAP_NEW; xfs_finish_ioend(ioend, 0); } diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 965df1227d644df44b4d2b79810f1ab42747f957..4ddc973aea7ab0a99e67e97a0fadb97b3567f31f 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -149,7 +149,7 @@ page_region_mask( return mask; } -STATIC_INLINE void +STATIC void set_page_region( struct page *page, size_t offset, @@ -161,7 +161,7 @@ set_page_region( SetPageUptodate(page); } -STATIC_INLINE int +STATIC int test_page_region( struct page *page, size_t offset, @@ -582,7 +582,7 @@ found: * although backing storage may not be. */ xfs_buf_t * -xfs_buf_get_flags( +xfs_buf_get( xfs_buftarg_t *target,/* target for buffer */ xfs_off_t ioff, /* starting offset of range */ size_t isize, /* length of range */ @@ -661,7 +661,7 @@ _xfs_buf_read( } xfs_buf_t * -xfs_buf_read_flags( +xfs_buf_read( xfs_buftarg_t *target, xfs_off_t ioff, size_t isize, @@ -671,7 +671,7 @@ xfs_buf_read_flags( flags |= XBF_READ; - bp = xfs_buf_get_flags(target, ioff, isize, flags); + bp = xfs_buf_get(target, ioff, isize, flags); if (bp) { if (!XFS_BUF_ISDONE(bp)) { XB_TRACE(bp, "read", (unsigned long)flags); @@ -718,7 +718,7 @@ xfs_buf_readahead( return; flags |= (XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD); - xfs_buf_read_flags(target, ioff, isize, flags); + xfs_buf_read(target, ioff, isize, flags); } xfs_buf_t * @@ -1113,7 +1113,7 @@ xfs_bdwrite( xfs_buf_delwri_queue(bp, 1); } -STATIC_INLINE void +STATIC void _xfs_buf_ioend( xfs_buf_t *bp, int schedule) diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index 9b4d666ad31f953c640ad4dfdec70a9052a76adc..5f07dd91c5fad311f1fb2bba0c9df8cfed91ec19 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h @@ -186,15 +186,10 @@ extern xfs_buf_t *_xfs_buf_find(xfs_buftarg_t *, xfs_off_t, size_t, #define xfs_incore(buftarg,blkno,len,lockit) \ _xfs_buf_find(buftarg, blkno ,len, lockit, NULL) -extern xfs_buf_t *xfs_buf_get_flags(xfs_buftarg_t *, xfs_off_t, size_t, +extern xfs_buf_t *xfs_buf_get(xfs_buftarg_t *, xfs_off_t, size_t, xfs_buf_flags_t); -#define xfs_buf_get(target, blkno, len, flags) \ - xfs_buf_get_flags((target), (blkno), (len), XBF_LOCK | XBF_MAPPED) - -extern xfs_buf_t *xfs_buf_read_flags(xfs_buftarg_t *, xfs_off_t, size_t, +extern xfs_buf_t *xfs_buf_read(xfs_buftarg_t *, xfs_off_t, size_t, xfs_buf_flags_t); -#define xfs_buf_read(target, blkno, len, flags) \ - xfs_buf_read_flags((target), (blkno), (len), XBF_LOCK | XBF_MAPPED) extern xfs_buf_t *xfs_buf_get_empty(size_t, xfs_buftarg_t *); extern xfs_buf_t *xfs_buf_get_noaddr(size_t, xfs_buftarg_t *); diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index eff61e2732af27c8aad199ebab5c66d83c5b904f..e4caeb28ce2edab5b77f7149adc288b0f51d23b6 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -52,7 +52,7 @@ xfs_file_aio_read( loff_t pos) { struct file *file = iocb->ki_filp; - int ioflags = IO_ISAIO; + int ioflags = 0; BUG_ON(iocb->ki_pos != pos); if (unlikely(file->f_flags & O_DIRECT)) @@ -71,7 +71,7 @@ xfs_file_aio_write( loff_t pos) { struct file *file = iocb->ki_filp; - int ioflags = IO_ISAIO; + int ioflags = 0; BUG_ON(iocb->ki_pos != pos); if (unlikely(file->f_flags & O_DIRECT)) diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index cd42ef78f6b54e705ad604e3ccfc4eb1a3df3743..1f3b4b8f7dd45195b71e41f6ea4df2a6a0b110c9 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -573,8 +573,8 @@ xfs_vn_fallocate( bf.l_len = len; xfs_ilock(ip, XFS_IOLOCK_EXCL); - error = xfs_change_file_space(ip, XFS_IOC_RESVSP, &bf, - 0, XFS_ATTR_NOLOCK); + error = -xfs_change_file_space(ip, XFS_IOC_RESVSP, &bf, + 0, XFS_ATTR_NOLOCK); if (!error && !(mode & FALLOC_FL_KEEP_SIZE) && offset + len > i_size_read(inode)) new_size = offset + len; @@ -585,7 +585,7 @@ xfs_vn_fallocate( iattr.ia_valid = ATTR_SIZE; iattr.ia_size = new_size; - error = xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK); + error = -xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK); } xfs_iunlock(ip, XFS_IOLOCK_EXCL); diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 072050f8d34634d59e4d200dfe14218bcf0e75ad..1bf47f219c971c9da83b6a8208531d47d2f58921 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -255,8 +255,6 @@ xfs_read( iocb->ki_pos = *offset; ret = generic_file_aio_read(iocb, iovp, segs, *offset); - if (ret == -EIOCBQUEUED && !(ioflags & IO_ISAIO)) - ret = wait_on_sync_kiocb(iocb); if (ret > 0) XFS_STATS_ADD(xs_read_bytes, ret); @@ -774,9 +772,6 @@ write_retry: current->backing_dev_info = NULL; - if (ret == -EIOCBQUEUED && !(ioflags & IO_ISAIO)) - ret = wait_on_sync_kiocb(iocb); - isize = i_size_read(inode); if (unlikely(ret < 0 && ret != -EFAULT && *offset > isize)) *offset = isize; @@ -811,7 +806,7 @@ write_retry: XFS_STATS_ADD(xs_write_bytes, ret); /* Handle various SYNC-type writes */ - if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { + if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) { loff_t end = pos + ret - 1; int error2; diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 18a4b8e11df2d4241bcfafd59297c30e961241ad..1bfb0e98019319a84b10e9f148b73874ae979b0c 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -930,13 +930,39 @@ xfs_fs_alloc_inode( */ STATIC void xfs_fs_destroy_inode( - struct inode *inode) + struct inode *inode) { - xfs_inode_t *ip = XFS_I(inode); + struct xfs_inode *ip = XFS_I(inode); + + xfs_itrace_entry(ip); XFS_STATS_INC(vn_reclaim); - if (xfs_reclaim(ip)) - panic("%s: cannot reclaim 0x%p\n", __func__, inode); + + /* bad inode, get out here ASAP */ + if (is_bad_inode(inode)) + goto out_reclaim; + + xfs_ioend_wait(ip); + + ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); + + /* + * We should never get here with one of the reclaim flags already set. + */ + ASSERT_ALWAYS(!xfs_iflags_test(ip, XFS_IRECLAIMABLE)); + ASSERT_ALWAYS(!xfs_iflags_test(ip, XFS_IRECLAIM)); + + /* + * If we have nothing to flush with this inode then complete the + * teardown now, otherwise delay the flush operation. + */ + if (!xfs_inode_clean(ip)) { + xfs_inode_set_reclaim_tag(ip); + return; + } + +out_reclaim: + xfs_ireclaim(ip); } /* @@ -973,7 +999,6 @@ xfs_fs_inode_init_once( mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER, "xfsino", ip->i_ino); - mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); } /* @@ -1075,6 +1100,20 @@ xfs_fs_clear_inode( XFS_STATS_INC(vn_remove); XFS_STATS_DEC(vn_active); + /* + * The iolock is used by the file system to coordinate reads, + * writes, and block truncates. Up to this point the lock + * protected concurrent accesses by users of the inode. But + * from here forward we're doing some final processing of the + * inode because we're done with it, and although we reuse the + * iolock for protection it is really a distinct lock class + * (in the lockdep sense) from before. To keep lockdep happy + * (and basically indicate what we are doing), we explicitly + * re-init the iolock here. + */ + ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock)); + mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); + xfs_inactive(ip); } @@ -1092,8 +1131,6 @@ xfs_fs_put_super( struct super_block *sb) { struct xfs_mount *mp = XFS_M(sb); - struct xfs_inode *rip = mp->m_rootip; - int unmount_event_flags = 0; xfs_syncd_stop(mp); @@ -1109,20 +1146,7 @@ xfs_fs_put_super( xfs_sync_attr(mp, 0); } -#ifdef HAVE_DMAPI - if (mp->m_flags & XFS_MOUNT_DMAPI) { - unmount_event_flags = - (mp->m_dmevmask & (1 << DM_EVENT_UNMOUNT)) ? - 0 : DM_FLAGS_UNWANTED; - /* - * Ignore error from dmapi here, first unmount is not allowed - * to fail anyway, and second we wouldn't want to fail a - * unmount because of dmapi. - */ - XFS_SEND_PREUNMOUNT(mp, rip, DM_RIGHT_NULL, rip, DM_RIGHT_NULL, - NULL, NULL, 0, 0, unmount_event_flags); - } -#endif + XFS_SEND_PREUNMOUNT(mp); /* * Blow away any referenced inode in the filestreams cache. @@ -1133,10 +1157,7 @@ xfs_fs_put_super( XFS_bflush(mp->m_ddev_targp); - if (mp->m_flags & XFS_MOUNT_DMAPI) { - XFS_SEND_UNMOUNT(mp, rip, DM_RIGHT_NULL, 0, 0, - unmount_event_flags); - } + XFS_SEND_UNMOUNT(mp); xfs_unmountfs(mp); xfs_freesb(mp); diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index 961df0a22c7837e9a969a8ab73331c594d5a6116..d895a3a960f5116f64d5931d03d18944ada862dd 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c @@ -663,10 +663,9 @@ xfs_syncd_stop( kthread_stop(mp->m_sync_task); } -int +STATIC int xfs_reclaim_inode( xfs_inode_t *ip, - int locked, int sync_mode) { xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino); @@ -682,10 +681,6 @@ xfs_reclaim_inode( !__xfs_iflags_test(ip, XFS_IRECLAIMABLE)) { spin_unlock(&ip->i_flags_lock); write_unlock(&pag->pag_ici_lock); - if (locked) { - xfs_ifunlock(ip); - xfs_iunlock(ip, XFS_ILOCK_EXCL); - } return -EAGAIN; } __xfs_iflags_set(ip, XFS_IRECLAIM); @@ -704,10 +699,8 @@ xfs_reclaim_inode( * We get the flush lock regardless, though, just to make sure * we don't free it while it is being flushed. */ - if (!locked) { - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_iflock(ip); - } + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_iflock(ip); /* * In the case of a forced shutdown we rely on xfs_iflush() to @@ -778,7 +771,7 @@ xfs_reclaim_inode_now( } read_unlock(&pag->pag_ici_lock); - return xfs_reclaim_inode(ip, 0, flags); + return xfs_reclaim_inode(ip, flags); } int diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h index 27920eb7a820cbe77b2e7799bf441a5da8dd0930..a500b4d91835b39c587ef414a948c8ce96d6d562 100644 --- a/fs/xfs/linux-2.6/xfs_sync.h +++ b/fs/xfs/linux-2.6/xfs_sync.h @@ -44,7 +44,6 @@ void xfs_quiesce_attr(struct xfs_mount *mp); void xfs_flush_inodes(struct xfs_inode *ip); -int xfs_reclaim_inode(struct xfs_inode *ip, int locked, int sync_mode); int xfs_reclaim_inodes(struct xfs_mount *mp, int mode); void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index ad7fbead4c97664331fb406d8d2f5a29640b9208..00cabf5354d265aa4cc73e442844454f96fd9739 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -36,7 +36,6 @@ struct attrlist_cursor_kern; /* * Flags for read/write calls - same values as IRIX */ -#define IO_ISAIO 0x00001 /* don't wait for completion */ #define IO_ISDIRECT 0x00004 /* bypass page cache */ #define IO_INVIS 0x00020 /* don't update inode timestamps */ diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h index 6f4fd37c67af41e684d8371353bb2915a6f62294..d2d20462fd4fd823b850f61918e3e2e28fd53655 100644 --- a/fs/xfs/support/debug.h +++ b/fs/xfs/support/debug.h @@ -41,10 +41,6 @@ extern void assfail(char *expr, char *f, int l); # define STATIC static noinline #endif -#ifndef STATIC_INLINE -# define STATIC_INLINE static inline -#endif - #else /* DEBUG */ #define ASSERT(expr) \ @@ -54,19 +50,5 @@ extern void assfail(char *expr, char *f, int l); # define STATIC noinline #endif -/* - * We stop inlining of inline functions in debug mode. - * Unfortunately, this means static inline in header files - * get multiple definitions, so they need to remain static. - * This then gives tonnes of warnings about unused but defined - * functions, so we need to add the unused attribute to prevent - * these spurious warnings. - */ -#ifndef STATIC_INLINE -# define STATIC_INLINE static __attribute__ ((unused)) noinline -#endif - #endif /* DEBUG */ - - #endif /* __XFS_SUPPORT_DEBUG_H__ */ diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 4ece1906bd41c0d801f8b66a41efb48bd3bcad6d..8fe6f6b78a4a3709815e44d9584b6315ba07b9df 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -123,9 +123,13 @@ xfs_inode_hasattr( * Overall external interface routines. *========================================================================*/ -int -xfs_attr_fetch(xfs_inode_t *ip, struct xfs_name *name, - char *value, int *valuelenp, int flags) +STATIC int +xfs_attr_get_int( + struct xfs_inode *ip, + struct xfs_name *name, + char *value, + int *valuelenp, + int flags) { xfs_da_args_t args; int error; @@ -188,7 +192,7 @@ xfs_attr_get( return error; xfs_ilock(ip, XFS_ILOCK_SHARED); - error = xfs_attr_fetch(ip, &xname, value, valuelenp, flags); + error = xfs_attr_get_int(ip, &xname, value, valuelenp, flags); xfs_iunlock(ip, XFS_ILOCK_SHARED); return(error); } @@ -2143,8 +2147,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock), blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount); - bp = xfs_buf_get_flags(mp->m_ddev_targp, dblkno, blkcnt, - XFS_BUF_LOCK | XBF_DONT_BLOCK); + bp = xfs_buf_get(mp->m_ddev_targp, dblkno, blkcnt, + XFS_BUF_LOCK | XBF_DONT_BLOCK); ASSERT(bp); ASSERT(!XFS_BUF_GETERROR(bp)); diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h index fb3b2a68b9b9d4fc6fc86956cf07c5c62611190b..12f0be3a73d42d5c60f1ba3b3beda8f2078d85c1 100644 --- a/fs/xfs/xfs_attr.h +++ b/fs/xfs/xfs_attr.h @@ -131,7 +131,6 @@ typedef struct xfs_attr_list_context { */ int xfs_attr_calc_size(struct xfs_inode *, int, int, int *); int xfs_attr_inactive(struct xfs_inode *dp); -int xfs_attr_fetch(struct xfs_inode *, struct xfs_name *, char *, int *, int); int xfs_attr_rmtval_get(struct xfs_da_args *args); int xfs_attr_list_int(struct xfs_attr_list_context *); diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index afdc8911637d20c3f7f01ff4eb50ca832e27ab28..0b687351293febc2aecfc2282d84adb17ed2bde8 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -98,7 +98,7 @@ STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index); * If namespace bits don't match return 0. * If all match then return 1. */ -STATIC_INLINE int +STATIC int xfs_attr_namesp_match(int arg_flags, int ondisk_flags) { return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags); diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index eb7b702d0690f673e3b86d178379b8eeb511bb67..6f5ccede63f9868e7d359251f457c4f155f74407 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c @@ -98,8 +98,7 @@ xfs_bmdr_to_bmbt( * This code must be in sync with the routines xfs_bmbt_get_startoff, * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state. */ - -STATIC_INLINE void +STATIC void __xfs_bmbt_get_all( __uint64_t l0, __uint64_t l1, diff --git a/fs/xfs/xfs_filestream.h b/fs/xfs/xfs_filestream.h index f655f7dc334c18b673d81880fa6dd8fec28f1817..4aba67c5f64f733f896872520aa71484ed2823e5 100644 --- a/fs/xfs/xfs_filestream.h +++ b/fs/xfs/xfs_filestream.h @@ -79,7 +79,7 @@ extern ktrace_t *xfs_filestreams_trace_buf; * the cache that reference per-ag array elements that have since been * reallocated. */ -STATIC_INLINE int +static inline int xfs_filestream_peek_ag( xfs_mount_t *mp, xfs_agnumber_t agno) @@ -87,7 +87,7 @@ xfs_filestream_peek_ag( return atomic_read(&mp->m_perag[agno].pagf_fstrms); } -STATIC_INLINE int +static inline int xfs_filestream_get_ag( xfs_mount_t *mp, xfs_agnumber_t agno) @@ -95,7 +95,7 @@ xfs_filestream_get_ag( return atomic_inc_return(&mp->m_perag[agno].pagf_fstrms); } -STATIC_INLINE int +static inline int xfs_filestream_put_ag( xfs_mount_t *mp, xfs_agnumber_t agno) @@ -122,7 +122,7 @@ int xfs_filestream_new_ag(struct xfs_bmalloca *ap, xfs_agnumber_t *agp); /* filestreams for the inode? */ -STATIC_INLINE int +static inline int xfs_inode_is_filestream( struct xfs_inode *ip) { diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 2d0b3e1da9e69094f798967e3ff432d679249f00..36079aa91344bc7e338ddb83c4f4d292d3f85c0a 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -201,8 +201,8 @@ xfs_growfs_data_private( * AG freelist header block */ bp = xfs_buf_get(mp->m_ddev_targp, - XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), - XFS_FSS_TO_BB(mp, 1), 0); + XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), + XFS_FSS_TO_BB(mp, 1), XBF_LOCK | XBF_MAPPED); agf = XFS_BUF_TO_AGF(bp); memset(agf, 0, mp->m_sb.sb_sectsize); agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC); @@ -233,8 +233,8 @@ xfs_growfs_data_private( * AG inode header block */ bp = xfs_buf_get(mp->m_ddev_targp, - XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), - XFS_FSS_TO_BB(mp, 1), 0); + XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), + XFS_FSS_TO_BB(mp, 1), XBF_LOCK | XBF_MAPPED); agi = XFS_BUF_TO_AGI(bp); memset(agi, 0, mp->m_sb.sb_sectsize); agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC); @@ -257,8 +257,9 @@ xfs_growfs_data_private( * BNO btree root block */ bp = xfs_buf_get(mp->m_ddev_targp, - XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)), - BTOBB(mp->m_sb.sb_blocksize), 0); + XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)), + BTOBB(mp->m_sb.sb_blocksize), + XBF_LOCK | XBF_MAPPED); block = XFS_BUF_TO_BLOCK(bp); memset(block, 0, mp->m_sb.sb_blocksize); block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC); @@ -278,8 +279,9 @@ xfs_growfs_data_private( * CNT btree root block */ bp = xfs_buf_get(mp->m_ddev_targp, - XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)), - BTOBB(mp->m_sb.sb_blocksize), 0); + XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)), + BTOBB(mp->m_sb.sb_blocksize), + XBF_LOCK | XBF_MAPPED); block = XFS_BUF_TO_BLOCK(bp); memset(block, 0, mp->m_sb.sb_blocksize); block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC); @@ -300,8 +302,9 @@ xfs_growfs_data_private( * INO btree root block */ bp = xfs_buf_get(mp->m_ddev_targp, - XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)), - BTOBB(mp->m_sb.sb_blocksize), 0); + XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)), + BTOBB(mp->m_sb.sb_blocksize), + XBF_LOCK | XBF_MAPPED); block = XFS_BUF_TO_BLOCK(bp); memset(block, 0, mp->m_sb.sb_blocksize); block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC); @@ -611,7 +614,7 @@ xfs_fs_log_dummy( xfs_inode_t *ip; int error; - tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1); + tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1, KM_SLEEP); error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0); if (error) { xfs_trans_cancel(tp, 0); diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 0785797db82886eea0833f3fc3561204e4e50c4e..cb907ba69c4c1806f27121c7904b8040928c0f8f 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -425,7 +425,7 @@ xfs_ialloc_ag_alloc( return 0; } -STATIC_INLINE xfs_agnumber_t +STATIC xfs_agnumber_t xfs_ialloc_next_ag( xfs_mount_t *mp) { diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 80e526489be5d7ee3dc415ec592fe2807a879a01..073bb4a26b194a8e1508c9b50f4363b444e84b54 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -73,6 +73,9 @@ xfs_inode_alloc( ASSERT(atomic_read(&ip->i_pincount) == 0); ASSERT(!spin_is_locked(&ip->i_flags_lock)); ASSERT(completion_done(&ip->i_flush)); + ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock)); + + mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); /* initialise the xfs inode */ ip->i_ino = ino; @@ -290,7 +293,7 @@ xfs_iget_cache_miss( struct xfs_inode **ipp, xfs_daddr_t bno, int flags, - int lock_flags) __releases(pag->pag_ici_lock) + int lock_flags) { struct xfs_inode *ip; int error; diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 67ae5555a30a6e8be0bd415b1596bea17854add5..7294abce6ef2f4d7d7e7ecae29dd377b14a4a2b3 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -860,8 +860,15 @@ xfs_iomap_write_unwritten( * set up a transaction to convert the range of extents * from unwritten to real. Do allocations in a loop until * we have covered the range passed in. + * + * Note that we open code the transaction allocation here + * to pass KM_NOFS--we can't risk to recursing back into + * the filesystem here as we might be asked to write out + * the same inode that we complete here and might deadlock + * on the iolock. */ - tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); + xfs_wait_for_freeze(mp, SB_FREEZE_TRANS); + tp = _xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE, KM_NOFS); tp->t_flags |= XFS_TRANS_RESERVE; error = xfs_trans_reserve(tp, resblks, XFS_WRITE_LOG_RES(mp), 0, diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index fb17f8226b0955eddc3ee3130708750f72fa3f29..1ec98ed914d4c951461dcff2ff4ae1a23fa2d55c 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -2206,6 +2206,7 @@ xlog_recover_do_buffer_trans( xfs_daddr_t blkno; int len; ushort flags; + uint buf_flags; buf_f = (xfs_buf_log_format_t *)item->ri_buf[0].i_addr; @@ -2246,12 +2247,11 @@ xlog_recover_do_buffer_trans( } mp = log->l_mp; - if (flags & XFS_BLI_INODE_BUF) { - bp = xfs_buf_read_flags(mp->m_ddev_targp, blkno, len, - XFS_BUF_LOCK); - } else { - bp = xfs_buf_read(mp->m_ddev_targp, blkno, len, 0); - } + buf_flags = XFS_BUF_LOCK; + if (!(flags & XFS_BLI_INODE_BUF)) + buf_flags |= XFS_BUF_MAPPED; + + bp = xfs_buf_read(mp->m_ddev_targp, blkno, len, buf_flags); if (XFS_BUF_ISERROR(bp)) { xfs_ioerror_alert("xlog_recover_do..(read#1)", log->l_mp, bp, blkno); @@ -2350,8 +2350,8 @@ xlog_recover_do_inode_trans( goto error; } - bp = xfs_buf_read_flags(mp->m_ddev_targp, in_f->ilf_blkno, - in_f->ilf_len, XFS_BUF_LOCK); + bp = xfs_buf_read(mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len, + XFS_BUF_LOCK); if (XFS_BUF_ISERROR(bp)) { xfs_ioerror_alert("xlog_recover_do..(read#2)", mp, bp, in_f->ilf_blkno); @@ -3517,7 +3517,7 @@ xlog_do_recovery_pass( { xlog_rec_header_t *rhead; xfs_daddr_t blk_no; - xfs_caddr_t bufaddr, offset; + xfs_caddr_t offset; xfs_buf_t *hbp, *dbp; int error = 0, h_size; int bblks, split_bblks; @@ -3610,7 +3610,7 @@ xlog_do_recovery_pass( /* * Check for header wrapping around physical end-of-log */ - offset = NULL; + offset = XFS_BUF_PTR(hbp); split_hblks = 0; wrapped_hblks = 0; if (blk_no + hblks <= log->l_logBBsize) { @@ -3646,9 +3646,8 @@ xlog_do_recovery_pass( * - order is important. */ wrapped_hblks = hblks - split_hblks; - bufaddr = XFS_BUF_PTR(hbp); error = XFS_BUF_SET_PTR(hbp, - bufaddr + BBTOB(split_hblks), + offset + BBTOB(split_hblks), BBTOB(hblks - split_hblks)); if (error) goto bread_err2; @@ -3658,14 +3657,10 @@ xlog_do_recovery_pass( if (error) goto bread_err2; - error = XFS_BUF_SET_PTR(hbp, bufaddr, + error = XFS_BUF_SET_PTR(hbp, offset, BBTOB(hblks)); if (error) goto bread_err2; - - if (!offset) - offset = xlog_align(log, 0, - wrapped_hblks, hbp); } rhead = (xlog_rec_header_t *)offset; error = xlog_valid_rec_header(log, rhead, @@ -3685,7 +3680,7 @@ xlog_do_recovery_pass( } else { /* This log record is split across the * physical end of log */ - offset = NULL; + offset = XFS_BUF_PTR(dbp); split_bblks = 0; if (blk_no != log->l_logBBsize) { /* some data is before the physical @@ -3714,9 +3709,8 @@ xlog_do_recovery_pass( * _first_, then the log start (LR header end) * - order is important. */ - bufaddr = XFS_BUF_PTR(dbp); error = XFS_BUF_SET_PTR(dbp, - bufaddr + BBTOB(split_bblks), + offset + BBTOB(split_bblks), BBTOB(bblks - split_bblks)); if (error) goto bread_err2; @@ -3727,13 +3721,9 @@ xlog_do_recovery_pass( if (error) goto bread_err2; - error = XFS_BUF_SET_PTR(dbp, bufaddr, h_size); + error = XFS_BUF_SET_PTR(dbp, offset, h_size); if (error) goto bread_err2; - - if (!offset) - offset = xlog_align(log, wrapped_hblks, - bblks - split_bblks, dbp); } xlog_unpack_data(rhead, offset, log); if ((error = xlog_recover_process_data(log, rhash, diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 8b6c9e807efb7b8a47bf493563bd5d8dadde3f4f..bfffd6334abbfae37d804174241bc1a1c17760d3 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -583,8 +583,8 @@ xfs_readsb(xfs_mount_t *mp, int flags) sector_size = xfs_getsize_buftarg(mp->m_ddev_targp); extra_flags = XFS_BUF_LOCK | XFS_BUF_MANAGE | XFS_BUF_MAPPED; - bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR, - BTOBB(sector_size), extra_flags); + bp = xfs_buf_read(mp->m_ddev_targp, XFS_SB_DADDR, BTOBB(sector_size), + extra_flags); if (!bp || XFS_BUF_ISERROR(bp)) { xfs_fs_mount_cmn_err(flags, "SB read failed"); error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM; @@ -624,8 +624,8 @@ xfs_readsb(xfs_mount_t *mp, int flags) XFS_BUF_UNMANAGE(bp); xfs_buf_relse(bp); sector_size = mp->m_sb.sb_sectsize; - bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR, - BTOBB(sector_size), extra_flags); + bp = xfs_buf_read(mp->m_ddev_targp, XFS_SB_DADDR, + BTOBB(sector_size), extra_flags); if (!bp || XFS_BUF_ISERROR(bp)) { xfs_fs_mount_cmn_err(flags, "SB re-read failed"); error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM; @@ -1471,7 +1471,7 @@ xfs_log_sbcount( if (!xfs_sb_version_haslazysbcount(&mp->m_sb)) return 0; - tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT); + tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT, KM_SLEEP); error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, XFS_DEFAULT_LOG_COUNT); if (error) { @@ -2123,7 +2123,7 @@ xfs_icsb_destroy_counters( mutex_destroy(&mp->m_icsb_mutex); } -STATIC_INLINE void +STATIC void xfs_icsb_lock_cntr( xfs_icsb_cnts_t *icsbp) { @@ -2132,7 +2132,7 @@ xfs_icsb_lock_cntr( } } -STATIC_INLINE void +STATIC void xfs_icsb_unlock_cntr( xfs_icsb_cnts_t *icsbp) { @@ -2140,7 +2140,7 @@ xfs_icsb_unlock_cntr( } -STATIC_INLINE void +STATIC void xfs_icsb_lock_all_counters( xfs_mount_t *mp) { @@ -2153,7 +2153,7 @@ xfs_icsb_lock_all_counters( } } -STATIC_INLINE void +STATIC void xfs_icsb_unlock_all_counters( xfs_mount_t *mp) { @@ -2389,12 +2389,12 @@ xfs_icsb_modify_counters( { xfs_icsb_cnts_t *icsbp; long long lcounter; /* long counter for 64 bit fields */ - int cpu, ret = 0; + int ret = 0; might_sleep(); again: - cpu = get_cpu(); - icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu); + preempt_disable(); + icsbp = this_cpu_ptr(mp->m_sb_cnts); /* * if the counter is disabled, go to slow path @@ -2438,11 +2438,11 @@ again: break; } xfs_icsb_unlock_cntr(icsbp); - put_cpu(); + preempt_enable(); return 0; slow_path: - put_cpu(); + preempt_enable(); /* * serialise with a mutex so we don't burn lots of cpu on @@ -2490,7 +2490,7 @@ slow_path: balance_counter: xfs_icsb_unlock_cntr(icsbp); - put_cpu(); + preempt_enable(); /* * We may have multiple threads here if multiple per-cpu diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index a6c023bc0fb27191d895578fe910e052840a804a..1df7e4502967a2623a9e5fa79f9f1556ae55e136 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -93,6 +93,9 @@ typedef struct xfs_dmops { xfs_send_unmount_t xfs_send_unmount; } xfs_dmops_t; +#define XFS_DMAPI_UNMOUNT_FLAGS(mp) \ + (((mp)->m_dmevmask & (1 << DM_EVENT_UNMOUNT)) ? 0 : DM_FLAGS_UNWANTED) + #define XFS_SEND_DATA(mp, ev,ip,off,len,fl,lock) \ (*(mp)->m_dm_ops->xfs_send_data)(ev,ip,off,len,fl,lock) #define XFS_SEND_MMAP(mp, vma,fl) \ @@ -101,12 +104,24 @@ typedef struct xfs_dmops { (*(mp)->m_dm_ops->xfs_send_destroy)(ip,right) #define XFS_SEND_NAMESP(mp, ev,b1,r1,b2,r2,n1,n2,mode,rval,fl) \ (*(mp)->m_dm_ops->xfs_send_namesp)(ev,NULL,b1,r1,b2,r2,n1,n2,mode,rval,fl) -#define XFS_SEND_PREUNMOUNT(mp,b1,r1,b2,r2,n1,n2,mode,rval,fl) \ - (*(mp)->m_dm_ops->xfs_send_namesp)(DM_EVENT_PREUNMOUNT,mp,b1,r1,b2,r2,n1,n2,mode,rval,fl) #define XFS_SEND_MOUNT(mp,right,path,name) \ (*(mp)->m_dm_ops->xfs_send_mount)(mp,right,path,name) -#define XFS_SEND_UNMOUNT(mp, ip,right,mode,rval,fl) \ - (*(mp)->m_dm_ops->xfs_send_unmount)(mp,ip,right,mode,rval,fl) +#define XFS_SEND_PREUNMOUNT(mp) \ +do { \ + if (mp->m_flags & XFS_MOUNT_DMAPI) { \ + (*(mp)->m_dm_ops->xfs_send_namesp)(DM_EVENT_PREUNMOUNT, mp, \ + (mp)->m_rootip, DM_RIGHT_NULL, \ + (mp)->m_rootip, DM_RIGHT_NULL, \ + NULL, NULL, 0, 0, XFS_DMAPI_UNMOUNT_FLAGS(mp)); \ + } \ +} while (0) +#define XFS_SEND_UNMOUNT(mp) \ +do { \ + if (mp->m_flags & XFS_MOUNT_DMAPI) { \ + (*(mp)->m_dm_ops->xfs_send_unmount)(mp, (mp)->m_rootip, \ + DM_RIGHT_NULL, 0, 0, XFS_DMAPI_UNMOUNT_FLAGS(mp)); \ + } \ +} while (0) #ifdef HAVE_PERCPU_SB @@ -387,13 +402,13 @@ xfs_put_perag(struct xfs_mount *mp, xfs_perag_t *pag) * Per-cpu superblock locking functions */ #ifdef HAVE_PERCPU_SB -STATIC_INLINE void +static inline void xfs_icsb_lock(xfs_mount_t *mp) { mutex_lock(&mp->m_icsb_mutex); } -STATIC_INLINE void +static inline void xfs_icsb_unlock(xfs_mount_t *mp) { mutex_unlock(&mp->m_icsb_mutex); diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index 3f816ad7ff19e7f0a93458333ac7b98d3842d3ec..4c199d18f8505a774da899dcbb097599ec0e08f7 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c @@ -277,10 +277,10 @@ xfs_read_buf( xfs_buf_t *bp; int error; - if (flags) - bp = xfs_buf_read_flags(target, blkno, len, flags); - else - bp = xfs_buf_read(target, blkno, len, flags); + if (!flags) + flags = XBF_LOCK | XBF_MAPPED; + + bp = xfs_buf_read(target, blkno, len, flags); if (!bp) return XFS_ERROR(EIO); error = XFS_BUF_GETERROR(bp); @@ -336,3 +336,25 @@ xfs_bwrite( } return (error); } + +/* + * helper function to extract extent size hint from inode + */ +xfs_extlen_t +xfs_get_extsz_hint( + struct xfs_inode *ip) +{ + xfs_extlen_t extsz; + + if (unlikely(XFS_IS_REALTIME_INODE(ip))) { + extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) + ? ip->i_d.di_extsize + : ip->i_mount->m_sb.sb_rextsize; + ASSERT(extsz); + } else { + extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) + ? ip->i_d.di_extsize : 0; + } + + return extsz; +} diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h index f5e4874c37d8ecfa55a77a1a1eeca31c7a6d27df..571f2174435c5c04ad843d3860cd9558236e7046 100644 --- a/fs/xfs/xfs_rw.h +++ b/fs/xfs/xfs_rw.h @@ -36,34 +36,6 @@ xfs_fsb_to_db(struct xfs_inode *ip, xfs_fsblock_t fsb) XFS_FSB_TO_DADDR((ip)->i_mount, (fsb))); } -/* - * Flags for xfs_free_eofblocks - */ -#define XFS_FREE_EOF_LOCK (1<<0) -#define XFS_FREE_EOF_NOLOCK (1<<1) - - -/* - * helper function to extract extent size hint from inode - */ -STATIC_INLINE xfs_extlen_t -xfs_get_extsz_hint( - xfs_inode_t *ip) -{ - xfs_extlen_t extsz; - - if (unlikely(XFS_IS_REALTIME_INODE(ip))) { - extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) - ? ip->i_d.di_extsize - : ip->i_mount->m_sb.sb_rextsize; - ASSERT(extsz); - } else { - extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) - ? ip->i_d.di_extsize : 0; - } - return extsz; -} - /* * Prototypes for functions in xfs_rw.c. */ @@ -76,5 +48,6 @@ extern int xfs_read_buf(struct xfs_mount *mp, xfs_buftarg_t *btp, struct xfs_buf **bpp); extern void xfs_ioerror_alert(char *func, struct xfs_mount *mp, xfs_buf_t *bp, xfs_daddr_t blkno); +extern xfs_extlen_t xfs_get_extsz_hint(struct xfs_inode *ip); #endif /* __XFS_RW_H__ */ diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 66b849358e62d16e9a01fc307bc5a03dc1605ffb..237badcbac3bcbbc9fbbba8ecea9229cdac80f08 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -236,19 +236,20 @@ xfs_trans_alloc( uint type) { xfs_wait_for_freeze(mp, SB_FREEZE_TRANS); - return _xfs_trans_alloc(mp, type); + return _xfs_trans_alloc(mp, type, KM_SLEEP); } xfs_trans_t * _xfs_trans_alloc( xfs_mount_t *mp, - uint type) + uint type, + uint memflags) { xfs_trans_t *tp; atomic_inc(&mp->m_active_trans); - tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP); + tp = kmem_zone_zalloc(xfs_trans_zone, memflags); tp->t_magic = XFS_TRANS_MAGIC; tp->t_type = type; tp->t_mountp = mp; diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index ed47fc77759c7cce24f98f283a717fae33fa9eea..a0574f593f5272764adf820c12ad724c9d90011e 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -924,7 +924,7 @@ typedef struct xfs_trans { * XFS transaction mechanism exported interfaces. */ xfs_trans_t *xfs_trans_alloc(struct xfs_mount *, uint); -xfs_trans_t *_xfs_trans_alloc(struct xfs_mount *, uint); +xfs_trans_t *_xfs_trans_alloc(struct xfs_mount *, uint, uint); xfs_trans_t *xfs_trans_dup(xfs_trans_t *); int xfs_trans_reserve(xfs_trans_t *, uint, uint, uint, uint, uint); diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 218829e6a152dce6698dbb8a9a8466fda694d92d..03a1f701fea8aaaae39cc36df9306750d262988c 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -79,11 +79,8 @@ xfs_trans_get_buf(xfs_trans_t *tp, /* * Default to a normal get_buf() call if the tp is NULL. */ - if (tp == NULL) { - bp = xfs_buf_get_flags(target_dev, blkno, len, - flags | BUF_BUSY); - return(bp); - } + if (tp == NULL) + return xfs_buf_get(target_dev, blkno, len, flags | BUF_BUSY); /* * If we find the buffer in the cache with this transaction @@ -129,7 +126,7 @@ xfs_trans_get_buf(xfs_trans_t *tp, * easily deadlock with our current transaction as well as cause * us to run out of stack space. */ - bp = xfs_buf_get_flags(target_dev, blkno, len, flags | BUF_BUSY); + bp = xfs_buf_get(target_dev, blkno, len, flags | BUF_BUSY); if (bp == NULL) { return NULL; } @@ -302,7 +299,7 @@ xfs_trans_read_buf( * Default to a normal get_buf() call if the tp is NULL. */ if (tp == NULL) { - bp = xfs_buf_read_flags(target, blkno, len, flags | BUF_BUSY); + bp = xfs_buf_read(target, blkno, len, flags | BUF_BUSY); if (!bp) return (flags & XFS_BUF_TRYLOCK) ? EAGAIN : XFS_ERROR(ENOMEM); @@ -398,7 +395,7 @@ xfs_trans_read_buf( * easily deadlock with our current transaction as well as cause * us to run out of stack space. */ - bp = xfs_buf_read_flags(target, blkno, len, flags | BUF_BUSY); + bp = xfs_buf_read(target, blkno, len, flags | BUF_BUSY); if (bp == NULL) { *bpp = NULL; return 0; diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index b572f7e840e0b82a372225581d87c85c104dfec6..578f3f59b789e7783c1c33343e0b8579eab46048 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -538,9 +538,8 @@ xfs_readlink_bmap( d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock); byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); - bp = xfs_buf_read_flags(mp->m_ddev_targp, d, BTOBB(byte_cnt), - XBF_LOCK | XBF_MAPPED | - XBF_DONT_BLOCK); + bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), + XBF_LOCK | XBF_MAPPED | XBF_DONT_BLOCK); error = XFS_BUF_GETERROR(bp); if (error) { xfs_ioerror_alert("xfs_readlink", @@ -708,6 +707,11 @@ xfs_fsync( return error; } +/* + * Flags for xfs_free_eofblocks + */ +#define XFS_FREE_EOF_TRYLOCK (1<<0) + /* * This is called by xfs_inactive to free any blocks beyond eof * when the link count isn't zero and by xfs_dm_punch_hole() when @@ -726,7 +730,6 @@ xfs_free_eofblocks( xfs_filblks_t map_len; int nimaps; xfs_bmbt_irec_t imap; - int use_iolock = (flags & XFS_FREE_EOF_LOCK); /* * Figure out if there are any blocks beyond the end @@ -768,14 +771,19 @@ xfs_free_eofblocks( * cache and we can't * do that within a transaction. */ - if (use_iolock) + if (flags & XFS_FREE_EOF_TRYLOCK) { + if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) { + xfs_trans_cancel(tp, 0); + return 0; + } + } else { xfs_ilock(ip, XFS_IOLOCK_EXCL); + } error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, ip->i_size); if (error) { xfs_trans_cancel(tp, 0); - if (use_iolock) - xfs_iunlock(ip, XFS_IOLOCK_EXCL); + xfs_iunlock(ip, XFS_IOLOCK_EXCL); return error; } @@ -812,8 +820,7 @@ xfs_free_eofblocks( error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); } - xfs_iunlock(ip, (use_iolock ? (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL) - : XFS_ILOCK_EXCL)); + xfs_iunlock(ip, XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL); } return error; } @@ -1113,7 +1120,17 @@ xfs_release( (ip->i_df.if_flags & XFS_IFEXTENTS)) && (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) { - error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK); + + /* + * If we can't get the iolock just skip truncating + * the blocks past EOF because we could deadlock + * with the mmap_sem otherwise. We'll get another + * chance to drop them once the last reference to + * the inode is dropped, so we'll never leak blocks + * permanently. + */ + error = xfs_free_eofblocks(mp, ip, + XFS_FREE_EOF_TRYLOCK); if (error) return error; } @@ -1184,7 +1201,7 @@ xfs_inactive( (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || (ip->i_delayed_blks != 0)))) { - error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK); + error = xfs_free_eofblocks(mp, ip, 0); if (error) return VN_INACTIVE_CACHE; } @@ -2456,46 +2473,6 @@ xfs_set_dmattrs( return error; } -int -xfs_reclaim( - xfs_inode_t *ip) -{ - - xfs_itrace_entry(ip); - - ASSERT(!VN_MAPPED(VFS_I(ip))); - - /* bad inode, get out here ASAP */ - if (is_bad_inode(VFS_I(ip))) { - xfs_ireclaim(ip); - return 0; - } - - xfs_ioend_wait(ip); - - ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); - - /* - * If we have nothing to flush with this inode then complete the - * teardown now, otherwise break the link between the xfs inode and the - * linux inode and clean up the xfs inode later. This avoids flushing - * the inode to disk during the delete operation itself. - * - * When breaking the link, we need to set the XFS_IRECLAIMABLE flag - * first to ensure that xfs_iunpin() will never see an xfs inode - * that has a linux inode being reclaimed. Synchronisation is provided - * by the i_flags_lock. - */ - if (!ip->i_update_core && (ip->i_itemp == NULL)) { - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_iflock(ip); - xfs_iflags_set(ip, XFS_IRECLAIMABLE); - return xfs_reclaim_inode(ip, 1, XFS_IFLUSH_DELWRI_ELSE_SYNC); - } - xfs_inode_set_reclaim_tag(ip); - return 0; -} - /* * xfs_alloc_file_space() * This routine allocates disk space for the given file. diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h index a9e102de71a19c35d1bac05181b910d496e180fa..167a467403a59f0c4327bb0a23cbb369e0e9d7af 100644 --- a/fs/xfs/xfs_vnodeops.h +++ b/fs/xfs/xfs_vnodeops.h @@ -38,7 +38,6 @@ int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name, const char *target_path, mode_t mode, struct xfs_inode **ipp, cred_t *credp); int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state); -int xfs_reclaim(struct xfs_inode *ip); int xfs_change_file_space(struct xfs_inode *ip, int cmd, xfs_flock64_t *bf, xfs_off_t offset, int attr_flags); int xfs_rename(struct xfs_inode *src_dp, struct xfs_name *src_name, diff --git a/include/acpi/acpi_hest.h b/include/acpi/acpi_hest.h new file mode 100644 index 0000000000000000000000000000000000000000..63194d03cb2db1a1f9eb19795a203496a72b51c3 --- /dev/null +++ b/include/acpi/acpi_hest.h @@ -0,0 +1,12 @@ +#ifndef __ACPI_HEST_H +#define __ACPI_HEST_H + +#include + +#ifdef CONFIG_ACPI +extern int acpi_hest_firmware_first_pci(struct pci_dev *pci); +#else +static inline int acpi_hest_firmware_first_pci(struct pci_dev *pci) { return 0; } +#endif + +#endif diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 740ac3ad8fd06fc61b8e2dacc10054ec27469439..8b668ead6d6e84a55f7cd9c743524cbeace28e1a 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -295,6 +295,7 @@ static inline void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx void acpi_processor_ppc_init(void); void acpi_processor_ppc_exit(void); int acpi_processor_ppc_has_changed(struct acpi_processor *pr); +extern int acpi_processor_get_bios_limit(int cpu, unsigned int *limit); #else static inline void acpi_processor_ppc_init(void) { @@ -316,6 +317,11 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) } return 0; } +static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) +{ + return -ENODEV; +} + #endif /* CONFIG_CPU_FREQ */ /* in processor_throttling.c */ diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h index 495dc8af4044fa1cb15898dc5c1450f8ecfb19a8..681ddf3e844c1fde1c1db04dbfe1629daaaf9108 100644 --- a/include/asm-generic/fcntl.h +++ b/include/asm-generic/fcntl.h @@ -3,8 +3,6 @@ #include -/* open/fcntl - O_SYNC is only implemented on blocks devices and on files - located on an ext2 file system */ #define O_ACCMODE 00000003 #define O_RDONLY 00000000 #define O_WRONLY 00000001 @@ -27,8 +25,8 @@ #ifndef O_NONBLOCK #define O_NONBLOCK 00004000 #endif -#ifndef O_SYNC -#define O_SYNC 00010000 +#ifndef O_DSYNC +#define O_DSYNC 00010000 /* used to be O_SYNC, see below */ #endif #ifndef FASYNC #define FASYNC 00020000 /* fcntl, for BSD compatibility */ @@ -51,6 +49,25 @@ #ifndef O_CLOEXEC #define O_CLOEXEC 02000000 /* set close_on_exec */ #endif + +/* + * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using + * the O_SYNC flag. We continue to use the existing numerical value + * for O_DSYNC semantics now, but using the correct symbolic name for it. + * This new value is used to request true Posix O_SYNC semantics. It is + * defined in this strange way to make sure applications compiled against + * new headers get at least O_DSYNC semantics on older kernels. + * + * This has the nice side-effect that we can simply test for O_DSYNC + * wherever we do not care if O_DSYNC or O_SYNC is used. + * + * Note: __O_SYNC must never be used directly. + */ +#ifndef O_SYNC +#define __O_SYNC 04000000 +#define O_SYNC (__O_SYNC|O_DSYNC) +#endif + #ifndef O_NDELAY #define O_NDELAY O_NONBLOCK #endif diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 66d6106a2067fefc1f4154e500d93ea889f94cd6..204bed37e82d3b090ca20f2030fbf9d3870a5446 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -28,6 +28,7 @@ static inline int gpio_is_valid(int number) return ((unsigned)number) < ARCH_NR_GPIOS; } +struct device; struct seq_file; struct module; @@ -181,6 +182,8 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value) #ifndef CONFIG_GPIO_SYSFS +struct device; + /* sysfs support is only available with gpiolib, where it's optional */ static inline int gpio_export(unsigned gpio, bool direction_may_change) diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h index 90079c373f1c462d2957b98b64f5f15b8ea7ac19..8087b90d4673d52cdd2f2d8ccf888009b7d0e115 100644 --- a/include/asm-generic/percpu.h +++ b/include/asm-generic/percpu.h @@ -56,6 +56,9 @@ extern unsigned long __per_cpu_offset[NR_CPUS]; #define __raw_get_cpu_var(var) \ (*SHIFT_PERCPU_PTR(&per_cpu_var(var), __my_cpu_offset)) +#define this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, my_cpu_offset) +#define __this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, __my_cpu_offset) + #ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA extern void setup_per_cpu_areas(void); @@ -66,6 +69,8 @@ extern void setup_per_cpu_areas(void); #define per_cpu(var, cpu) (*((void)(cpu), &per_cpu_var(var))) #define __get_cpu_var(var) per_cpu_var(var) #define __raw_get_cpu_var(var) per_cpu_var(var) +#define this_cpu_ptr(ptr) per_cpu_ptr(ptr, 0) +#define __this_cpu_ptr(ptr) this_cpu_ptr(ptr) #endif /* SMP */ diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h index 7c38c147e5e64069bfad5ff6532a06e4e2d18830..6a0b30f78a6255fa2d2134287586dc05d2be35a2 100644 --- a/include/asm-generic/unistd.h +++ b/include/asm-generic/unistd.h @@ -622,9 +622,13 @@ __SYSCALL(__NR_move_pages, sys_move_pages) __SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo) #define __NR_perf_event_open 241 __SYSCALL(__NR_perf_event_open, sys_perf_event_open) +#define __NR_accept4 242 +__SYSCALL(__NR_accept4, sys_accept4) +#define __NR_recvmmsg 243 +__SYSCALL(__NR_recvmmsg, sys_recvmmsg) #undef __NR_syscalls -#define __NR_syscalls 242 +#define __NR_syscalls 244 /* * All syscalls below here should go away really, @@ -802,7 +806,7 @@ __SYSCALL(__NR_fork, sys_ni_syscall) #define __NR_statfs __NR3264_statfs #define __NR_fstatfs __NR3264_fstatfs #define __NR_truncate __NR3264_truncate -#define __NR_ftruncate __NR3264_truncate +#define __NR_ftruncate __NR3264_ftruncate #define __NR_lseek __NR3264_lseek #define __NR_sendfile __NR3264_sendfile #define __NR_newfstatat __NR3264_fstatat @@ -818,7 +822,7 @@ __SYSCALL(__NR_fork, sys_ni_syscall) #define __NR_statfs64 __NR3264_statfs #define __NR_fstatfs64 __NR3264_fstatfs #define __NR_truncate64 __NR3264_truncate -#define __NR_ftruncate64 __NR3264_truncate +#define __NR_ftruncate64 __NR3264_ftruncate #define __NR_llseek __NR3264_lseek #define __NR_sendfile64 __NR3264_sendfile #define __NR_fstatat64 __NR3264_fstatat diff --git a/include/drm/Kbuild b/include/drm/Kbuild index b940fdfa3b25284fb0a244b18781709cda90789b..cfa6af43c9ea49b0d9e00768f1b0a2027b9dd699 100644 --- a/include/drm/Kbuild +++ b/include/drm/Kbuild @@ -8,3 +8,4 @@ unifdef-y += radeon_drm.h unifdef-y += sis_drm.h unifdef-y += savage_drm.h unifdef-y += via_drm.h +unifdef-y += nouveau_drm.h diff --git a/include/drm/drm.h b/include/drm/drm.h index 7cb50bdde46d5f8cdf0d348f21e62da16b926ad3..e3f46e0cb7dc305f8ab0b9ea7af3f96deb3bba0d 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h @@ -36,17 +36,27 @@ #ifndef _DRM_H_ #define _DRM_H_ +#if defined(__linux__) + #include -#include /* For _IO* macros */ -#define DRM_IOCTL_NR(n) _IOC_NR(n) -#define DRM_IOC_VOID _IOC_NONE -#define DRM_IOC_READ _IOC_READ -#define DRM_IOC_WRITE _IOC_WRITE -#define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE -#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) +#include +typedef unsigned int drm_handle_t; -#define DRM_MAJOR 226 -#define DRM_MAX_MINOR 15 +#else /* One of the BSDs */ + +#include +#include +typedef int8_t __s8; +typedef uint8_t __u8; +typedef int16_t __s16; +typedef uint16_t __u16; +typedef int32_t __s32; +typedef uint32_t __u32; +typedef int64_t __s64; +typedef uint64_t __u64; +typedef unsigned long drm_handle_t; + +#endif #define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */ #define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */ @@ -59,7 +69,6 @@ #define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT) #define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT)) -typedef unsigned int drm_handle_t; typedef unsigned int drm_context_t; typedef unsigned int drm_drawable_t; typedef unsigned int drm_magic_t; @@ -454,6 +463,7 @@ struct drm_irq_busid { enum drm_vblank_seq_type { _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + _DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */ _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ @@ -461,8 +471,8 @@ enum drm_vblank_seq_type { }; #define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) -#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \ - _DRM_VBLANK_NEXTONMISS) +#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_EVENT | _DRM_VBLANK_SIGNAL | \ + _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS) struct drm_wait_vblank_request { enum drm_vblank_seq_type type; @@ -686,6 +696,8 @@ struct drm_gem_open { #define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd) #define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd) #define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int) +#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip) +#define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd) /** * Device specific ioctls should only be in their respective headers @@ -698,6 +710,35 @@ struct drm_gem_open { #define DRM_COMMAND_BASE 0x40 #define DRM_COMMAND_END 0xA0 +/** + * Header for events written back to userspace on the drm fd. The + * type defines the type of event, the length specifies the total + * length of the event (including the header), and user_data is + * typically a 64 bit value passed with the ioctl that triggered the + * event. A read on the drm fd will always only return complete + * events, that is, if for example the read buffer is 100 bytes, and + * there are two 64 byte events pending, only one will be returned. + * + * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and + * up are chipset specific. + */ +struct drm_event { + __u32 type; + __u32 length; +}; + +#define DRM_EVENT_VBLANK 0x01 +#define DRM_EVENT_FLIP_COMPLETE 0x02 + +struct drm_event_vblank { + struct drm_event base; + __u64 user_data; + __u32 tv_sec; + __u32 tv_usec; + __u32 sequence; + __u32 reserved; +}; + /* typedef area */ #ifndef __KERNEL__ typedef struct drm_clip_rect drm_clip_rect_t; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index c8e64bbadbcf3c99ccc4eba20a3e13610779a9a9..19ef8ebdc6621c24346b5354764a7d9ba98848f8 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -245,16 +245,6 @@ extern void drm_ut_debug_printk(unsigned int request_level, #endif -#define DRM_PROC_LIMIT (PAGE_SIZE-80) - -#define DRM_PROC_PRINT(fmt, arg...) \ - len += sprintf(&buf[len], fmt , ##arg); \ - if (len > DRM_PROC_LIMIT) { *eof = 1; return len - offset; } - -#define DRM_PROC_PRINT_RET(ret, fmt, arg...) \ - len += sprintf(&buf[len], fmt , ##arg); \ - if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; } - /*@}*/ /***********************************************************************/ @@ -265,19 +255,8 @@ extern void drm_ut_debug_printk(unsigned int request_level, #define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1)) #define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x)) -#define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist) #define DRM_IF_VERSION(maj, min) (maj << 16 | min) -/** - * Get the private SAREA mapping. - * - * \param _dev DRM device. - * \param _ctx context number. - * \param _map output mapping. - */ -#define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do { \ - (_map) = (_dev)->context_sareas[_ctx]; \ -} while(0) /** * Test that the hardware lock is held by the caller, returning otherwise. @@ -296,18 +275,6 @@ do { \ } \ } while (0) -/** - * Copy and IOCTL return string to user space - */ -#define DRM_COPY( name, value ) \ - len = strlen( value ); \ - if ( len > name##_len ) len = name##_len; \ - name##_len = strlen( value ); \ - if ( len && name ) { \ - if ( copy_to_user( name, value, len ) ) \ - return -EFAULT; \ - } - /** * Ioctl function type. * @@ -322,6 +289,9 @@ typedef int drm_ioctl_t(struct drm_device *dev, void *data, typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, unsigned long arg); +#define DRM_IOCTL_NR(n) _IOC_NR(n) +#define DRM_MAJOR 226 + #define DRM_AUTH 0x1 #define DRM_MASTER 0x2 #define DRM_ROOT_ONLY 0x4 @@ -426,6 +396,14 @@ struct drm_buf_entry { struct drm_freelist freelist; }; +/* Event queued up for userspace to read */ +struct drm_pending_event { + struct drm_event *event; + struct list_head link; + struct drm_file *file_priv; + void (*destroy)(struct drm_pending_event *event); +}; + /** File private data */ struct drm_file { int authenticated; @@ -449,6 +427,10 @@ struct drm_file { struct drm_master *master; /* master this node is currently associated with N.B. not always minor->master */ struct list_head fbs; + + wait_queue_head_t event_wait; + struct list_head event_list; + int event_space; }; /** Wait queue */ @@ -795,6 +777,15 @@ struct drm_driver { /* Master routines */ int (*master_create)(struct drm_device *dev, struct drm_master *master); void (*master_destroy)(struct drm_device *dev, struct drm_master *master); + /** + * master_set is called whenever the minor master is set. + * master_drop is called whenever the minor master is dropped. + */ + + int (*master_set)(struct drm_device *dev, struct drm_file *file_priv, + bool from_open); + void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv, + bool from_release); int (*proc_init)(struct drm_minor *minor); void (*proc_cleanup)(struct drm_minor *minor); @@ -900,6 +891,12 @@ struct drm_minor { struct drm_mode_group mode_group; }; +struct drm_pending_vblank_event { + struct drm_pending_event base; + int pipe; + struct drm_event_vblank event; +}; + /** * DRM device structure. This structure represent a complete card that * may contain multiple heads. @@ -999,6 +996,12 @@ struct drm_device { u32 max_vblank_count; /**< size of vblank counter register */ + /** + * List of events + */ + struct list_head vblank_event_list; + spinlock_t event_lock; + /*@} */ cycles_t ctx_start; cycles_t lck_start; @@ -1135,6 +1138,8 @@ extern int drm_lastclose(struct drm_device *dev); extern int drm_open(struct inode *inode, struct file *filp); extern int drm_stub_open(struct inode *inode, struct file *filp); extern int drm_fasync(int fd, struct file *filp, int on); +extern ssize_t drm_read(struct file *filp, char __user *buffer, + size_t count, loff_t *offset); extern int drm_release(struct inode *inode, struct file *filp); /* Mapping support (drm_vm.h) */ @@ -1295,6 +1300,7 @@ extern u32 drm_vblank_count(struct drm_device *dev, int crtc); extern void drm_handle_vblank(struct drm_device *dev, int crtc); extern int drm_vblank_get(struct drm_device *dev, int crtc); extern void drm_vblank_put(struct drm_device *dev, int crtc); +extern void drm_vblank_off(struct drm_device *dev, int crtc); extern void drm_vblank_cleanup(struct drm_device *dev); /* Modesetting support */ extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc); @@ -1519,14 +1525,27 @@ static __inline__ void drm_core_dropmap(struct drm_local_map *map) static __inline__ void *drm_calloc_large(size_t nmemb, size_t size) { + if (size != 0 && nmemb > ULONG_MAX / size) + return NULL; + if (size * nmemb <= PAGE_SIZE) return kcalloc(nmemb, size, GFP_KERNEL); + return __vmalloc(size * nmemb, + GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL); +} + +/* Modeled after cairo's malloc_ab, it's like calloc but without the zeroing. */ +static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size) +{ if (size != 0 && nmemb > ULONG_MAX / size) return NULL; + if (size * nmemb <= PAGE_SIZE) + return kmalloc(nmemb * size, GFP_KERNEL); + return __vmalloc(size * nmemb, - GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL); + GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL); } static __inline void drm_free_large(void *ptr) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index b69347b8904ff29f465a5d2adb29b1385b939e02..fdf43abc36dbe7ae36d0e690ab6e99b8a417f1d7 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -123,7 +123,7 @@ struct drm_display_mode { int type; /* Proposed mode values */ - int clock; + int clock; /* in kHz */ int hdisplay; int hsync_start; int hsync_end; @@ -164,8 +164,8 @@ struct drm_display_mode { int *private; int private_flags; - int vrefresh; - float hsync; + int vrefresh; /* in Hz */ + int hsync; /* in kHz */ }; enum drm_connector_status { @@ -242,6 +242,21 @@ struct drm_framebuffer_funcs { int (*create_handle)(struct drm_framebuffer *fb, struct drm_file *file_priv, unsigned int *handle); + /** + * Optinal callback for the dirty fb ioctl. + * + * Userspace can notify the driver via this callback + * that a area of the framebuffer has changed and should + * be flushed to the display hardware. + * + * See documentation in drm_mode.h for the struct + * drm_mode_fb_dirty_cmd for more information as all + * the semantics and arguments have a one to one mapping + * on this function. + */ + int (*dirty)(struct drm_framebuffer *framebuffer, unsigned flags, + unsigned color, struct drm_clip_rect *clips, + unsigned num_clips); }; struct drm_framebuffer { @@ -256,7 +271,7 @@ struct drm_framebuffer { unsigned int depth; int bits_per_pixel; int flags; - void *fbdev; + struct fb_info *fbdev; u32 pseudo_palette[17]; struct list_head filp_head; /* if you are using the helper */ @@ -290,6 +305,7 @@ struct drm_property { struct drm_crtc; struct drm_connector; struct drm_encoder; +struct drm_pending_vblank_event; /** * drm_crtc_funcs - control CRTCs for a given device @@ -333,6 +349,19 @@ struct drm_crtc_funcs { void (*destroy)(struct drm_crtc *crtc); int (*set_config)(struct drm_mode_set *set); + + /* + * Flip to the given framebuffer. This implements the page + * flip ioctl descibed in drm_mode.h, specifically, the + * implementation must return immediately and block all + * rendering to the current fb until the flip has completed. + * If userspace set the event flag in the ioctl, the event + * argument will point to an event to send back when the flip + * completes, otherwise it will be NULL. + */ + int (*page_flip)(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event); }; /** @@ -596,6 +625,7 @@ struct drm_mode_config { /* Optional properties */ struct drm_property *scaling_mode_property; struct drm_property *dithering_mode_property; + struct drm_property *dirty_info_property; }; #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) @@ -667,6 +697,7 @@ extern void drm_mode_validate_size(struct drm_device *dev, extern void drm_mode_prune_invalid(struct drm_device *dev, struct list_head *mode_list, bool verbose); extern void drm_mode_sort(struct list_head *mode_list); +extern int drm_mode_hsync(struct drm_display_mode *mode); extern int drm_mode_vrefresh(struct drm_display_mode *mode); extern void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags); @@ -703,6 +734,7 @@ extern int drm_mode_create_tv_properties(struct drm_device *dev, int num_formats char *formats[]); extern int drm_mode_create_scaling_mode_property(struct drm_device *dev); extern int drm_mode_create_dithering_property(struct drm_device *dev); +extern int drm_mode_create_dirty_info_property(struct drm_device *dev); extern char *drm_get_encoder_name(struct drm_encoder *encoder); extern int drm_mode_connector_attach_encoder(struct drm_connector *connector, @@ -711,7 +743,8 @@ extern void drm_mode_connector_detach_encoder(struct drm_connector *connector, struct drm_encoder *encoder); extern bool drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, int gamma_size); -extern void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type); +extern struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, + uint32_t id, uint32_t type); /* IOCTLs */ extern int drm_mode_getresources(struct drm_device *dev, void *data, struct drm_file *file_priv); @@ -730,6 +763,8 @@ extern int drm_mode_rmfb(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mode_getfb(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int drm_mode_dirtyfb_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); extern int drm_mode_addmode_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mode_rmmode_ioctl(struct drm_device *dev, @@ -756,6 +791,8 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev, extern int drm_mode_gamma_set_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern bool drm_detect_hdmi_monitor(struct edid *edid); +extern int drm_mode_page_flip_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, bool reduced, bool interlaced, bool margins); diff --git a/drivers/gpu/drm/i915/intel_dp.h b/include/drm/drm_dp_helper.h similarity index 70% rename from drivers/gpu/drm/i915/intel_dp.h rename to include/drm/drm_dp_helper.h index 2b38054d3b6d453ce1095ee6a6a8562198beeffa..a49e791db0b0308f284a17408a7051559102ca1d 100644 --- a/drivers/gpu/drm/i915/intel_dp.h +++ b/include/drm/drm_dp_helper.h @@ -20,8 +20,8 @@ * OF THIS SOFTWARE. */ -#ifndef _INTEL_DP_H_ -#define _INTEL_DP_H_ +#ifndef _DRM_DP_HELPER_H_ +#define _DRM_DP_HELPER_H_ /* From the VESA DisplayPort spec */ @@ -43,16 +43,41 @@ #define AUX_I2C_REPLY_MASK (0x3 << 6) /* AUX CH addresses */ -#define DP_LINK_BW_SET 0x100 +/* DPCD */ +#define DP_DPCD_REV 0x000 + +#define DP_MAX_LINK_RATE 0x001 + +#define DP_MAX_LANE_COUNT 0x002 +# define DP_MAX_LANE_COUNT_MASK 0x1f +# define DP_ENHANCED_FRAME_CAP (1 << 7) + +#define DP_MAX_DOWNSPREAD 0x003 +# define DP_NO_AUX_HANDSHAKE_LINK_TRAINING (1 << 6) + +#define DP_NORP 0x004 + +#define DP_DOWNSTREAMPORT_PRESENT 0x005 +# define DP_DWN_STRM_PORT_PRESENT (1 << 0) +# define DP_DWN_STRM_PORT_TYPE_MASK 0x06 +/* 00b = DisplayPort */ +/* 01b = Analog */ +/* 10b = TMDS or HDMI */ +/* 11b = Other */ +# define DP_FORMAT_CONVERSION (1 << 3) + +#define DP_MAIN_LINK_CHANNEL_CODING 0x006 + +/* link configuration */ +#define DP_LINK_BW_SET 0x100 # define DP_LINK_BW_1_62 0x06 # define DP_LINK_BW_2_7 0x0a -#define DP_LANE_COUNT_SET 0x101 +#define DP_LANE_COUNT_SET 0x101 # define DP_LANE_COUNT_MASK 0x0f # define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7) -#define DP_TRAINING_PATTERN_SET 0x102 - +#define DP_TRAINING_PATTERN_SET 0x102 # define DP_TRAINING_PATTERN_DISABLE 0 # define DP_TRAINING_PATTERN_1 1 # define DP_TRAINING_PATTERN_2 2 @@ -102,11 +127,14 @@ #define DP_LANE0_1_STATUS 0x202 #define DP_LANE2_3_STATUS 0x203 - # define DP_LANE_CR_DONE (1 << 0) # define DP_LANE_CHANNEL_EQ_DONE (1 << 1) # define DP_LANE_SYMBOL_LOCKED (1 << 2) +#define DP_CHANNEL_EQ_BITS (DP_LANE_CR_DONE | \ + DP_LANE_CHANNEL_EQ_DONE | \ + DP_LANE_SYMBOL_LOCKED) + #define DP_LANE_ALIGN_STATUS_UPDATED 0x204 #define DP_INTERLANE_ALIGN_DONE (1 << 0) @@ -120,25 +148,33 @@ #define DP_ADJUST_REQUEST_LANE0_1 0x206 #define DP_ADJUST_REQUEST_LANE2_3 0x207 - -#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03 -#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0 -#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c -#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2 -#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30 -#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4 -#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0 -#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6 +# define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03 +# define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0 +# define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c +# define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2 +# define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30 +# define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4 +# define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0 +# define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6 + +#define DP_SET_POWER 0x600 +# define DP_SET_POWER_D0 0x1 +# define DP_SET_POWER_D3 0x2 + +#define MODE_I2C_START 1 +#define MODE_I2C_WRITE 2 +#define MODE_I2C_READ 4 +#define MODE_I2C_STOP 8 struct i2c_algo_dp_aux_data { bool running; u16 address; int (*aux_ch) (struct i2c_adapter *adapter, - uint8_t *send, int send_bytes, - uint8_t *recv, int recv_bytes); + int mode, uint8_t write_byte, + uint8_t *read_byte); }; int i2c_dp_aux_add_bus(struct i2c_adapter *adapter); -#endif /* _INTEL_DP_H_ */ +#endif /* _DRM_DP_HELPER_H_ */ diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 7d6c9a2dfcbbb8608e400e310640511031c27f76..d33c3e038606c1354d671d90a9d3d776d4e225a7 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -106,6 +106,10 @@ struct detailed_data_color_point { u8 wpindex2[3]; } __attribute__((packed)); +struct cvt_timing { + u8 code[3]; +} __attribute__((packed)); + struct detailed_non_pixel { u8 pad1; u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name @@ -117,9 +121,13 @@ struct detailed_non_pixel { struct detailed_data_monitor_range range; struct detailed_data_wpindex color; struct std_timing timings[5]; + struct cvt_timing cvt[4]; } data; } __attribute__((packed)); +#define EDID_DETAIL_EST_TIMINGS 0xf7 +#define EDID_DETAIL_CVT_3BYTE 0xf8 +#define EDID_DETAIL_COLOR_MGMT_DATA 0xf9 #define EDID_DETAIL_STD_MODES 0xfa #define EDID_DETAIL_MONITOR_CPDATA 0xfb #define EDID_DETAIL_MONITOR_NAME 0xfc diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 62329f9a42cbbc953866e899599fe15e42d099ff..4c10be39a43bd94d7568fbb41bf3cc8d15fac95f 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -66,6 +66,13 @@ extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, unsigned long size, unsigned alignment, int atomic); +extern struct drm_mm_node *drm_mm_get_block_range_generic( + struct drm_mm_node *node, + unsigned long size, + unsigned alignment, + unsigned long start, + unsigned long end, + int atomic); static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent, unsigned long size, unsigned alignment) @@ -78,11 +85,38 @@ static inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *pa { return drm_mm_get_block_generic(parent, size, alignment, 1); } +static inline struct drm_mm_node *drm_mm_get_block_range( + struct drm_mm_node *parent, + unsigned long size, + unsigned alignment, + unsigned long start, + unsigned long end) +{ + return drm_mm_get_block_range_generic(parent, size, alignment, + start, end, 0); +} +static inline struct drm_mm_node *drm_mm_get_block_atomic_range( + struct drm_mm_node *parent, + unsigned long size, + unsigned alignment, + unsigned long start, + unsigned long end) +{ + return drm_mm_get_block_range_generic(parent, size, alignment, + start, end, 1); +} extern void drm_mm_put_block(struct drm_mm_node *cur); extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, unsigned long size, unsigned alignment, int best_match); +extern struct drm_mm_node *drm_mm_search_free_in_range( + const struct drm_mm *mm, + unsigned long size, + unsigned alignment, + unsigned long start, + unsigned long end, + int best_match); extern int drm_mm_init(struct drm_mm *mm, unsigned long start, unsigned long size); extern void drm_mm_takedown(struct drm_mm *mm); @@ -99,6 +133,7 @@ static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block) return block->mm; } +extern void drm_mm_debug_table(struct drm_mm *mm, const char *prefix); #ifdef CONFIG_DEBUG_FS int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm); #endif diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index 1f908416aedbd29a4d436573ebf6d3c6ea511aba..43009bc2e7574ff4dda9f451f25e47abb10d0c06 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -27,9 +27,6 @@ #ifndef _DRM_MODE_H #define _DRM_MODE_H -#include -#include - #define DRM_DISPLAY_INFO_LEN 32 #define DRM_CONNECTOR_NAME_LEN 32 #define DRM_DISPLAY_MODE_LEN 32 @@ -78,6 +75,11 @@ #define DRM_MODE_DITHERING_OFF 0 #define DRM_MODE_DITHERING_ON 1 +/* Dirty info options */ +#define DRM_MODE_DIRTY_OFF 0 +#define DRM_MODE_DIRTY_ON 1 +#define DRM_MODE_DIRTY_ANNOTATE 2 + struct drm_mode_modeinfo { __u32 clock; __u16 hdisplay, hsync_start, hsync_end, htotal, hskew; @@ -225,6 +227,45 @@ struct drm_mode_fb_cmd { __u32 handle; }; +#define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01 +#define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02 +#define DRM_MODE_FB_DIRTY_FLAGS 0x03 + +/* + * Mark a region of a framebuffer as dirty. + * + * Some hardware does not automatically update display contents + * as a hardware or software draw to a framebuffer. This ioctl + * allows userspace to tell the kernel and the hardware what + * regions of the framebuffer have changed. + * + * The kernel or hardware is free to update more then just the + * region specified by the clip rects. The kernel or hardware + * may also delay and/or coalesce several calls to dirty into a + * single update. + * + * Userspace may annotate the updates, the annotates are a + * promise made by the caller that the change is either a copy + * of pixels or a fill of a single color in the region specified. + * + * If the DRM_MODE_FB_DIRTY_ANNOTATE_COPY flag is given then + * the number of updated regions are half of num_clips given, + * where the clip rects are paired in src and dst. The width and + * height of each one of the pairs must match. + * + * If the DRM_MODE_FB_DIRTY_ANNOTATE_FILL flag is given the caller + * promises that the region specified of the clip rects is filled + * completely with a single color as given in the color argument. + */ + +struct drm_mode_fb_dirty_cmd { + __u32 fb_id; + __u32 flags; + __u32 color; + __u32 num_clips; + __u64 clips_ptr; +}; + struct drm_mode_mode_cmd { __u32 connector_id; struct drm_mode_modeinfo mode; @@ -268,4 +309,37 @@ struct drm_mode_crtc_lut { __u64 blue; }; +#define DRM_MODE_PAGE_FLIP_EVENT 0x01 +#define DRM_MODE_PAGE_FLIP_FLAGS DRM_MODE_PAGE_FLIP_EVENT + +/* + * Request a page flip on the specified crtc. + * + * This ioctl will ask KMS to schedule a page flip for the specified + * crtc. Once any pending rendering targeting the specified fb (as of + * ioctl time) has completed, the crtc will be reprogrammed to display + * that fb after the next vertical refresh. The ioctl returns + * immediately, but subsequent rendering to the current fb will block + * in the execbuffer ioctl until the page flip happens. If a page + * flip is already pending as the ioctl is called, EBUSY will be + * returned. + * + * The ioctl supports one flag, DRM_MODE_PAGE_FLIP_EVENT, which will + * request that drm sends back a vblank event (see drm.h: struct + * drm_event_vblank) when the page flip is done. The user_data field + * passed in with this ioctl will be returned as the user_data field + * in the vblank event struct. + * + * The reserved field must be zero until we figure out something + * clever to use it for. + */ + +struct drm_mode_crtc_page_flip { + __u32 crtc_id; + __u32 fb_id; + __u32 flags; + __u32 reserved; + __u64 user_data; +}; + #endif diff --git a/include/drm/drm_os_linux.h b/include/drm/drm_os_linux.h index 26641e95e0a4be8cb0ce273c88eb65196bfe02af..393369147a2dd7812ea5555f30ac8a4390ed1442 100644 --- a/include/drm/drm_os_linux.h +++ b/include/drm/drm_os_linux.h @@ -123,5 +123,5 @@ do { \ remove_wait_queue(&(queue), &entry); \ } while (0) -#define DRM_WAKEUP( queue ) wake_up_interruptible( queue ) +#define DRM_WAKEUP( queue ) wake_up( queue ) #define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue ) diff --git a/include/drm/i2c/ch7006.h b/include/drm/i2c/ch7006.h new file mode 100644 index 0000000000000000000000000000000000000000..8390b437a1f8e2178ac6f71bf9377f9194ea7bd7 --- /dev/null +++ b/include/drm/i2c/ch7006.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +#ifndef __DRM_I2C_CH7006_H__ +#define __DRM_I2C_CH7006_H__ + +/** + * struct ch7006_encoder_params + * + * Describes how the ch7006 is wired up with the GPU. It should be + * used as the @params parameter of its @set_config method. + * + * See "http://www.chrontel.com/pdf/7006.pdf" for their precise + * meaning. + */ +struct ch7006_encoder_params { + enum { + CH7006_FORMAT_RGB16 = 0, + CH7006_FORMAT_YCrCb24m16, + CH7006_FORMAT_RGB24m16, + CH7006_FORMAT_RGB15, + CH7006_FORMAT_RGB24m12C, + CH7006_FORMAT_RGB24m12I, + CH7006_FORMAT_RGB24m8, + CH7006_FORMAT_RGB16m8, + CH7006_FORMAT_RGB15m8, + CH7006_FORMAT_YCrCb24m8, + } input_format; + + enum { + CH7006_CLOCK_SLAVE = 0, + CH7006_CLOCK_MASTER, + } clock_mode; + + enum { + CH7006_CLOCK_EDGE_NEG = 0, + CH7006_CLOCK_EDGE_POS, + } clock_edge; + + int xcm, pcm; + + enum { + CH7006_SYNC_SLAVE = 0, + CH7006_SYNC_MASTER, + } sync_direction; + + enum { + CH7006_SYNC_SEPARATED = 0, + CH7006_SYNC_EMBEDDED, + } sync_encoding; + + enum { + CH7006_POUT_1_8V = 0, + CH7006_POUT_3_3V, + } pout_level; + + enum { + CH7006_ACTIVE_HSYNC = 0, + CH7006_ACTIVE_DSTART, + } active_detect; +}; + +#endif diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index 7e0cb1da92e68be66b9f8c0839a42ea0e6a95e99..ec3f5e80a5df7f6e0148adf67001108864c788ce 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -27,11 +27,11 @@ #ifndef _I915_DRM_H_ #define _I915_DRM_H_ +#include "drm.h" + /* Please note that modifications to all structs defined here are * subject to backwards-compatibility constraints. */ -#include -#include "drm.h" /* Each region is a minimum of 16k, and there are at most 255 of them. */ @@ -186,6 +186,8 @@ typedef struct _drm_i915_sarea { #define DRM_I915_GEM_MMAP_GTT 0x24 #define DRM_I915_GET_PIPE_FROM_CRTC_ID 0x25 #define DRM_I915_GEM_MADVISE 0x26 +#define DRM_I915_OVERLAY_PUT_IMAGE 0x27 +#define DRM_I915_OVERLAY_ATTRS 0x28 #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) @@ -221,8 +223,10 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling) #define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling) #define DRM_IOCTL_I915_GEM_GET_APERTURE DRM_IOR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture) -#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_intel_get_pipe_from_crtc_id) +#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_i915_get_pipe_from_crtc_id) #define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise) +#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_IOCTL_I915_OVERLAY_ATTRS, struct drm_intel_overlay_put_image) +#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -266,6 +270,8 @@ typedef struct drm_i915_irq_wait { #define I915_PARAM_CHIPSET_ID 4 #define I915_PARAM_HAS_GEM 5 #define I915_PARAM_NUM_FENCES_AVAIL 6 +#define I915_PARAM_HAS_OVERLAY 7 +#define I915_PARAM_HAS_PAGEFLIPPING 8 typedef struct drm_i915_getparam { int param; @@ -686,4 +692,70 @@ struct drm_i915_gem_madvise { __u32 retained; }; +/* flags */ +#define I915_OVERLAY_TYPE_MASK 0xff +#define I915_OVERLAY_YUV_PLANAR 0x01 +#define I915_OVERLAY_YUV_PACKED 0x02 +#define I915_OVERLAY_RGB 0x03 + +#define I915_OVERLAY_DEPTH_MASK 0xff00 +#define I915_OVERLAY_RGB24 0x1000 +#define I915_OVERLAY_RGB16 0x2000 +#define I915_OVERLAY_RGB15 0x3000 +#define I915_OVERLAY_YUV422 0x0100 +#define I915_OVERLAY_YUV411 0x0200 +#define I915_OVERLAY_YUV420 0x0300 +#define I915_OVERLAY_YUV410 0x0400 + +#define I915_OVERLAY_SWAP_MASK 0xff0000 +#define I915_OVERLAY_NO_SWAP 0x000000 +#define I915_OVERLAY_UV_SWAP 0x010000 +#define I915_OVERLAY_Y_SWAP 0x020000 +#define I915_OVERLAY_Y_AND_UV_SWAP 0x030000 + +#define I915_OVERLAY_FLAGS_MASK 0xff000000 +#define I915_OVERLAY_ENABLE 0x01000000 + +struct drm_intel_overlay_put_image { + /* various flags and src format description */ + __u32 flags; + /* source picture description */ + __u32 bo_handle; + /* stride values and offsets are in bytes, buffer relative */ + __u16 stride_Y; /* stride for packed formats */ + __u16 stride_UV; + __u32 offset_Y; /* offset for packet formats */ + __u32 offset_U; + __u32 offset_V; + /* in pixels */ + __u16 src_width; + __u16 src_height; + /* to compensate the scaling factors for partially covered surfaces */ + __u16 src_scan_width; + __u16 src_scan_height; + /* output crtc description */ + __u32 crtc_id; + __u16 dst_x; + __u16 dst_y; + __u16 dst_width; + __u16 dst_height; +}; + +/* flags */ +#define I915_OVERLAY_UPDATE_ATTRS (1<<0) +#define I915_OVERLAY_UPDATE_GAMMA (1<<1) +struct drm_intel_overlay_attrs { + __u32 flags; + __u32 color_key; + __s32 brightness; + __u32 contrast; + __u32 saturation; + __u32 gamma0; + __u32 gamma1; + __u32 gamma2; + __u32 gamma3; + __u32 gamma4; + __u32 gamma5; +}; + #endif /* _I915_DRM_H_ */ diff --git a/include/drm/mga_drm.h b/include/drm/mga_drm.h index 325fd6fb4a421e9ef9f8f347af493831fd52595a..3ffbc4798afacaec3f521eac11b607269cfd7c20 100644 --- a/include/drm/mga_drm.h +++ b/include/drm/mga_drm.h @@ -35,7 +35,7 @@ #ifndef __MGA_DRM_H__ #define __MGA_DRM_H__ -#include +#include "drm.h" /* WARNING: If you change any of these defines, make sure to change the * defines in the Xserver file (mga_sarea.h) diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h new file mode 100644 index 0000000000000000000000000000000000000000..1e67c441ea823d619a38d8c2437f6ecb6a138250 --- /dev/null +++ b/include/drm/nouveau_drm.h @@ -0,0 +1,220 @@ +/* + * Copyright 2005 Stephane Marchesin. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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. + */ + +#ifndef __NOUVEAU_DRM_H__ +#define __NOUVEAU_DRM_H__ + +#define NOUVEAU_DRM_HEADER_PATCHLEVEL 15 + +struct drm_nouveau_channel_alloc { + uint32_t fb_ctxdma_handle; + uint32_t tt_ctxdma_handle; + + int channel; + + /* Notifier memory */ + uint32_t notifier_handle; + + /* DRM-enforced subchannel assignments */ + struct { + uint32_t handle; + uint32_t grclass; + } subchan[8]; + uint32_t nr_subchan; +}; + +struct drm_nouveau_channel_free { + int channel; +}; + +struct drm_nouveau_grobj_alloc { + int channel; + uint32_t handle; + int class; +}; + +struct drm_nouveau_notifierobj_alloc { + uint32_t channel; + uint32_t handle; + uint32_t size; + uint32_t offset; +}; + +struct drm_nouveau_gpuobj_free { + int channel; + uint32_t handle; +}; + +/* FIXME : maybe unify {GET,SET}PARAMs */ +#define NOUVEAU_GETPARAM_PCI_VENDOR 3 +#define NOUVEAU_GETPARAM_PCI_DEVICE 4 +#define NOUVEAU_GETPARAM_BUS_TYPE 5 +#define NOUVEAU_GETPARAM_FB_PHYSICAL 6 +#define NOUVEAU_GETPARAM_AGP_PHYSICAL 7 +#define NOUVEAU_GETPARAM_FB_SIZE 8 +#define NOUVEAU_GETPARAM_AGP_SIZE 9 +#define NOUVEAU_GETPARAM_PCI_PHYSICAL 10 +#define NOUVEAU_GETPARAM_CHIPSET_ID 11 +#define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 +struct drm_nouveau_getparam { + uint64_t param; + uint64_t value; +}; + +struct drm_nouveau_setparam { + uint64_t param; + uint64_t value; +}; + +#define NOUVEAU_GEM_DOMAIN_CPU (1 << 0) +#define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) +#define NOUVEAU_GEM_DOMAIN_GART (1 << 2) +#define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3) + +struct drm_nouveau_gem_info { + uint32_t handle; + uint32_t domain; + uint64_t size; + uint64_t offset; + uint64_t map_handle; + uint32_t tile_mode; + uint32_t tile_flags; +}; + +struct drm_nouveau_gem_new { + struct drm_nouveau_gem_info info; + uint32_t channel_hint; + uint32_t align; +}; + +struct drm_nouveau_gem_pushbuf_bo { + uint64_t user_priv; + uint32_t handle; + uint32_t read_domains; + uint32_t write_domains; + uint32_t valid_domains; + uint32_t presumed_ok; + uint32_t presumed_domain; + uint64_t presumed_offset; +}; + +#define NOUVEAU_GEM_RELOC_LOW (1 << 0) +#define NOUVEAU_GEM_RELOC_HIGH (1 << 1) +#define NOUVEAU_GEM_RELOC_OR (1 << 2) +struct drm_nouveau_gem_pushbuf_reloc { + uint32_t bo_index; + uint32_t reloc_index; + uint32_t flags; + uint32_t data; + uint32_t vor; + uint32_t tor; +}; + +#define NOUVEAU_GEM_MAX_BUFFERS 1024 +#define NOUVEAU_GEM_MAX_RELOCS 1024 + +struct drm_nouveau_gem_pushbuf { + uint32_t channel; + uint32_t nr_dwords; + uint32_t nr_buffers; + uint32_t nr_relocs; + uint64_t dwords; + uint64_t buffers; + uint64_t relocs; +}; + +struct drm_nouveau_gem_pushbuf_call { + uint32_t channel; + uint32_t handle; + uint32_t offset; + uint32_t nr_buffers; + uint32_t nr_relocs; + uint32_t nr_dwords; + uint64_t buffers; + uint64_t relocs; + uint32_t suffix0; + uint32_t suffix1; + /* below only accessed for CALL2 */ + uint64_t vram_available; + uint64_t gart_available; +}; + +struct drm_nouveau_gem_pin { + uint32_t handle; + uint32_t domain; + uint64_t offset; +}; + +struct drm_nouveau_gem_unpin { + uint32_t handle; +}; + +#define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001 +#define NOUVEAU_GEM_CPU_PREP_NOBLOCK 0x00000002 +#define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004 +struct drm_nouveau_gem_cpu_prep { + uint32_t handle; + uint32_t flags; +}; + +struct drm_nouveau_gem_cpu_fini { + uint32_t handle; +}; + +struct drm_nouveau_gem_tile { + uint32_t handle; + uint32_t offset; + uint32_t size; + uint32_t tile_mode; + uint32_t tile_flags; +}; + +enum nouveau_bus_type { + NV_AGP = 0, + NV_PCI = 1, + NV_PCIE = 2, +}; + +struct drm_nouveau_sarea { +}; + +#define DRM_NOUVEAU_CARD_INIT 0x00 +#define DRM_NOUVEAU_GETPARAM 0x01 +#define DRM_NOUVEAU_SETPARAM 0x02 +#define DRM_NOUVEAU_CHANNEL_ALLOC 0x03 +#define DRM_NOUVEAU_CHANNEL_FREE 0x04 +#define DRM_NOUVEAU_GROBJ_ALLOC 0x05 +#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x06 +#define DRM_NOUVEAU_GPUOBJ_FREE 0x07 +#define DRM_NOUVEAU_GEM_NEW 0x40 +#define DRM_NOUVEAU_GEM_PUSHBUF 0x41 +#define DRM_NOUVEAU_GEM_PUSHBUF_CALL 0x42 +#define DRM_NOUVEAU_GEM_PIN 0x43 /* !KMS only */ +#define DRM_NOUVEAU_GEM_UNPIN 0x44 /* !KMS only */ +#define DRM_NOUVEAU_GEM_CPU_PREP 0x45 +#define DRM_NOUVEAU_GEM_CPU_FINI 0x46 +#define DRM_NOUVEAU_GEM_INFO 0x47 +#define DRM_NOUVEAU_GEM_PUSHBUF_CALL2 0x48 + +#endif /* __NOUVEAU_DRM_H__ */ diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 3b9932ab1756235fd8479dc99c44e29f33abeac4..39537f3cf98ae89fca7b1d4e6fca5b18668735d5 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -33,7 +33,7 @@ #ifndef __RADEON_DRM_H__ #define __RADEON_DRM_H__ -#include +#include "drm.h" /* WARNING: If you change any of these defines, make sure to change the * defines in the X server file (radeon_sarea.h) diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 491146170522dde71b31c9644c0f782929ac657a..81eb9f45883c4b2111b549f600fd720f6e5a0511 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -44,6 +44,29 @@ struct ttm_bo_device; struct drm_mm_node; + +/** + * struct ttm_placement + * + * @fpfn: first valid page frame number to put the object + * @lpfn: last valid page frame number to put the object + * @num_placement: number of prefered placements + * @placement: prefered placements + * @num_busy_placement: number of prefered placements when need to evict buffer + * @busy_placement: prefered placements when need to evict buffer + * + * Structure indicating the placement you request for an object. + */ +struct ttm_placement { + unsigned fpfn; + unsigned lpfn; + unsigned num_placement; + const uint32_t *placement; + unsigned num_busy_placement; + const uint32_t *busy_placement; +}; + + /** * struct ttm_mem_reg * @@ -109,10 +132,6 @@ struct ttm_tt; * the object is destroyed. * @event_queue: Queue for processes waiting on buffer object status change. * @lock: spinlock protecting mostly synchronization members. - * @proposed_placement: Proposed placement for the buffer. Changed only by the - * creator prior to validation as opposed to bo->mem.proposed_flags which is - * changed by the implementation prior to a buffer move if it wants to outsmart - * the buffer creator / user. This latter happens, for example, at eviction. * @mem: structure describing current placement. * @persistant_swap_storage: Usually the swap storage is deleted for buffers * pinned in physical memory. If this behaviour is not desired, this member @@ -177,7 +196,6 @@ struct ttm_buffer_object { * Members protected by the bo::reserved lock. */ - uint32_t proposed_placement; struct ttm_mem_reg mem; struct file *persistant_swap_storage; struct ttm_tt *ttm; @@ -285,29 +303,30 @@ ttm_bo_reference(struct ttm_buffer_object *bo) * Note: It might be necessary to block validations before the * wait by reserving the buffer. * Returns -EBUSY if no_wait is true and the buffer is busy. - * Returns -ERESTART if interrupted by a signal. + * Returns -ERESTARTSYS if interrupted by a signal. */ extern int ttm_bo_wait(struct ttm_buffer_object *bo, bool lazy, bool interruptible, bool no_wait); /** - * ttm_buffer_object_validate + * ttm_bo_validate * * @bo: The buffer object. - * @proposed_placement: Proposed_placement for the buffer object. + * @placement: Proposed placement for the buffer object. * @interruptible: Sleep interruptible if sleeping. * @no_wait: Return immediately if the buffer is busy. * * Changes placement and caching policy of the buffer object - * according to bo::proposed_flags. + * according proposed placement. * Returns - * -EINVAL on invalid proposed_flags. + * -EINVAL on invalid proposed placement. * -ENOMEM on out-of-memory condition. * -EBUSY if no_wait is true and buffer busy. - * -ERESTART if interrupted by a signal. + * -ERESTARTSYS if interrupted by a signal. */ -extern int ttm_buffer_object_validate(struct ttm_buffer_object *bo, - uint32_t proposed_placement, - bool interruptible, bool no_wait); +extern int ttm_bo_validate(struct ttm_buffer_object *bo, + struct ttm_placement *placement, + bool interruptible, bool no_wait); + /** * ttm_bo_unref * @@ -328,7 +347,7 @@ extern void ttm_bo_unref(struct ttm_buffer_object **bo); * waiting for buffer idle. This lock is recursive. * Returns * -EBUSY if the buffer is busy and no_wait is true. - * -ERESTART if interrupted by a signal. + * -ERESTARTSYS if interrupted by a signal. */ extern int @@ -343,7 +362,7 @@ ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait); extern void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo); /** - * ttm_buffer_object_init + * ttm_bo_init * * @bdev: Pointer to a ttm_bo_device struct. * @bo: Pointer to a ttm_buffer_object to be initialized. @@ -371,20 +390,20 @@ extern void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo); * Returns * -ENOMEM: Out of memory. * -EINVAL: Invalid placement flags. - * -ERESTART: Interrupted by signal while sleeping waiting for resources. + * -ERESTARTSYS: Interrupted by signal while sleeping waiting for resources. */ -extern int ttm_buffer_object_init(struct ttm_bo_device *bdev, - struct ttm_buffer_object *bo, - unsigned long size, - enum ttm_bo_type type, - uint32_t flags, - uint32_t page_alignment, - unsigned long buffer_start, - bool interrubtible, - struct file *persistant_swap_storage, - size_t acc_size, - void (*destroy) (struct ttm_buffer_object *)); +extern int ttm_bo_init(struct ttm_bo_device *bdev, + struct ttm_buffer_object *bo, + unsigned long size, + enum ttm_bo_type type, + struct ttm_placement *placement, + uint32_t page_alignment, + unsigned long buffer_start, + bool interrubtible, + struct file *persistant_swap_storage, + size_t acc_size, + void (*destroy) (struct ttm_buffer_object *)); /** * ttm_bo_synccpu_object_init * @@ -405,47 +424,43 @@ extern int ttm_buffer_object_init(struct ttm_bo_device *bdev, * GEM user interface. * @p_bo: On successful completion *p_bo points to the created object. * - * This function allocates a ttm_buffer_object, and then calls - * ttm_buffer_object_init on that object. - * The destroy function is set to kfree(). + * This function allocates a ttm_buffer_object, and then calls ttm_bo_init + * on that object. The destroy function is set to kfree(). * Returns * -ENOMEM: Out of memory. * -EINVAL: Invalid placement flags. - * -ERESTART: Interrupted by signal while waiting for resources. + * -ERESTARTSYS: Interrupted by signal while waiting for resources. */ -extern int ttm_buffer_object_create(struct ttm_bo_device *bdev, - unsigned long size, - enum ttm_bo_type type, - uint32_t flags, - uint32_t page_alignment, - unsigned long buffer_start, - bool interruptible, - struct file *persistant_swap_storage, - struct ttm_buffer_object **p_bo); +extern int ttm_bo_create(struct ttm_bo_device *bdev, + unsigned long size, + enum ttm_bo_type type, + struct ttm_placement *placement, + uint32_t page_alignment, + unsigned long buffer_start, + bool interruptible, + struct file *persistant_swap_storage, + struct ttm_buffer_object **p_bo); /** * ttm_bo_check_placement * - * @bo: the buffer object. - * @set_flags: placement flags to set. - * @clr_flags: placement flags to clear. + * @bo: the buffer object. + * @placement: placements * * Performs minimal validity checking on an intended change of * placement flags. * Returns * -EINVAL: Intended change is invalid or not allowed. */ - extern int ttm_bo_check_placement(struct ttm_buffer_object *bo, - uint32_t set_flags, uint32_t clr_flags); + struct ttm_placement *placement); /** * ttm_bo_init_mm * * @bdev: Pointer to a ttm_bo_device struct. * @mem_type: The memory type. - * @p_offset: offset for managed area in pages. * @p_size: size managed area in pages. * * Initialize a manager for a given memory type. @@ -458,7 +473,7 @@ extern int ttm_bo_check_placement(struct ttm_buffer_object *bo, */ extern int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, - unsigned long p_offset, unsigned long p_size); + unsigned long p_size); /** * ttm_bo_clean_mm * @@ -503,7 +518,7 @@ extern int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type); * * Returns: * -EINVAL: Invalid or uninitialized memory type. - * -ERESTART: The call was interrupted by a signal while waiting to + * -ERESTARTSYS: The call was interrupted by a signal while waiting to * evict a buffer. */ @@ -606,7 +621,7 @@ extern int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma, * be called from the fops::read and fops::write method. * Returns: * See man (2) write, man(2) read. In particular, - * the function may return -EINTR if + * the function may return -ERESTARTSYS if * interrupted by a signal. */ diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index e8cd6d20aed287acfc4c39e33b4882a9d468a089..ff7664e0c3cdbe78a856ff1b6448baf98eaf77a2 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -242,12 +242,6 @@ struct ttm_mem_type_manager { /** * struct ttm_bo_driver * - * @mem_type_prio: Priority array of memory types to place a buffer object in - * if it fits without evicting buffers from any of these memory types. - * @mem_busy_prio: Priority array of memory types to place a buffer object in - * if it needs to evict buffers to make room. - * @num_mem_type_prio: Number of elements in the @mem_type_prio array. - * @num_mem_busy_prio: Number of elements in the @num_mem_busy_prio array. * @create_ttm_backend_entry: Callback to create a struct ttm_backend. * @invalidate_caches: Callback to invalidate read caches when a buffer object * has been evicted. @@ -265,11 +259,6 @@ struct ttm_mem_type_manager { */ struct ttm_bo_driver { - const uint32_t *mem_type_prio; - const uint32_t *mem_busy_prio; - uint32_t num_mem_type_prio; - uint32_t num_mem_busy_prio; - /** * struct ttm_bo_driver member create_ttm_backend_entry * @@ -306,7 +295,8 @@ struct ttm_bo_driver { * finished, they'll end up in bo->mem.flags */ - uint32_t(*evict_flags) (struct ttm_buffer_object *bo); + void(*evict_flags) (struct ttm_buffer_object *bo, + struct ttm_placement *placement); /** * struct ttm_bo_driver member move: * @@ -544,6 +534,15 @@ extern int ttm_tt_set_user(struct ttm_tt *ttm, */ extern int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem); +/** + * ttm_tt_populate: + * + * @ttm: The struct ttm_tt to contain the backing pages. + * + * Add backing pages to all of @ttm + */ +extern int ttm_tt_populate(struct ttm_tt *ttm); + /** * ttm_ttm_destroy: * @@ -639,12 +638,12 @@ extern bool ttm_mem_reg_is_pci(struct ttm_bo_device *bdev, * -EBUSY: No space available (only if no_wait == 1). * -ENOMEM: Could not allocate memory for the buffer object, either due to * fragmentation or concurrent allocators. - * -ERESTART: An interruptible sleep was interrupted by a signal. + * -ERESTARTSYS: An interruptible sleep was interrupted by a signal. */ extern int ttm_bo_mem_space(struct ttm_buffer_object *bo, - uint32_t proposed_placement, - struct ttm_mem_reg *mem, - bool interruptible, bool no_wait); + struct ttm_placement *placement, + struct ttm_mem_reg *mem, + bool interruptible, bool no_wait); /** * ttm_bo_wait_for_cpu * @@ -654,7 +653,7 @@ extern int ttm_bo_mem_space(struct ttm_buffer_object *bo, * Wait until a buffer object is no longer sync'ed for CPU access. * Returns: * -EBUSY: Buffer object was sync'ed for CPU access. (only if no_wait == 1). - * -ERESTART: An interruptible sleep was interrupted by a signal. + * -ERESTARTSYS: An interruptible sleep was interrupted by a signal. */ extern int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait); @@ -758,7 +757,7 @@ extern void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo); * -EAGAIN: The reservation may cause a deadlock. * Release all buffer reservations, wait for @bo to become unreserved and * try again. (only if use_sequence == 1). - * -ERESTART: A wait for the buffer to become unreserved was interrupted by + * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by * a signal. Release all buffer reservations and return to user-space. */ extern int ttm_bo_reserve(struct ttm_buffer_object *bo, @@ -799,7 +798,7 @@ extern int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo, * * Returns: * -EBUSY: If no_wait == 1 and the buffer is already reserved. - * -ERESTART: If interruptible == 1 and the process received a signal + * -ERESTARTSYS: If interruptible == 1 and the process received a signal * while sleeping. */ extern int ttm_bo_block_reservation(struct ttm_buffer_object *bo, diff --git a/include/drm/ttm/ttm_execbuf_util.h b/include/drm/ttm/ttm_execbuf_util.h new file mode 100644 index 0000000000000000000000000000000000000000..cd2c475da9eae790734d01eef7eff8c7f991263f --- /dev/null +++ b/include/drm/ttm/ttm_execbuf_util.h @@ -0,0 +1,107 @@ +/************************************************************************** + * + * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ +/* + * Authors: Thomas Hellstrom + */ + +#ifndef _TTM_EXECBUF_UTIL_H_ +#define _TTM_EXECBUF_UTIL_H_ + +#include "ttm/ttm_bo_api.h" +#include + +/** + * struct ttm_validate_buffer + * + * @head: list head for thread-private list. + * @bo: refcounted buffer object pointer. + * @new_sync_obj_arg: New sync_obj_arg for @bo, to be used once + * adding a new sync object. + * @reservied: Indicates whether @bo has been reserved for validation. + */ + +struct ttm_validate_buffer { + struct list_head head; + struct ttm_buffer_object *bo; + void *new_sync_obj_arg; + bool reserved; +}; + +/** + * function ttm_eu_backoff_reservation + * + * @list: thread private list of ttm_validate_buffer structs. + * + * Undoes all buffer validation reservations for bos pointed to by + * the list entries. + */ + +extern void ttm_eu_backoff_reservation(struct list_head *list); + +/** + * function ttm_eu_reserve_buffers + * + * @list: thread private list of ttm_validate_buffer structs. + * @val_seq: A unique sequence number. + * + * Tries to reserve bos pointed to by the list entries for validation. + * If the function returns 0, all buffers are marked as "unfenced", + * taken off the lru lists and are not synced for write CPU usage. + * + * If the function detects a deadlock due to multiple threads trying to + * reserve the same buffers in reverse order, all threads except one will + * back off and retry. This function may sleep while waiting for + * CPU write reservations to be cleared, and for other threads to + * unreserve their buffers. + * + * This function may return -ERESTART or -EAGAIN if the calling process + * receives a signal while waiting. In that case, no buffers on the list + * will be reserved upon return. + * + * Buffers reserved by this function should be unreserved by + * a call to either ttm_eu_backoff_reservation() or + * ttm_eu_fence_buffer_objects() when command submission is complete or + * has failed. + */ + +extern int ttm_eu_reserve_buffers(struct list_head *list, uint32_t val_seq); + +/** + * function ttm_eu_fence_buffer_objects. + * + * @list: thread private list of ttm_validate_buffer structs. + * @sync_obj: The new sync object for the buffers. + * + * This function should be called when command submission is complete, and + * it will add a new sync object to bos pointed to by entries on @list. + * It also unreserves all buffers, putting them on lru lists. + * + */ + +extern void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj); + +#endif diff --git a/include/drm/ttm/ttm_lock.h b/include/drm/ttm/ttm_lock.h new file mode 100644 index 0000000000000000000000000000000000000000..81ba0b0b891a9ad298354ec87856707c0f61cb79 --- /dev/null +++ b/include/drm/ttm/ttm_lock.h @@ -0,0 +1,247 @@ +/************************************************************************** + * + * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ +/* + * Authors: Thomas Hellstrom + */ + +/** @file ttm_lock.h + * This file implements a simple replacement for the buffer manager use + * of the DRM heavyweight hardware lock. + * The lock is a read-write lock. Taking it in read mode and write mode + * is relatively fast, and intended for in-kernel use only. + * + * The vt mode is used only when there is a need to block all + * user-space processes from validating buffers. + * It's allowed to leave kernel space with the vt lock held. + * If a user-space process dies while having the vt-lock, + * it will be released during the file descriptor release. The vt lock + * excludes write lock and read lock. + * + * The suspend mode is used to lock out all TTM users when preparing for + * and executing suspend operations. + * + */ + +#ifndef _TTM_LOCK_H_ +#define _TTM_LOCK_H_ + +#include "ttm/ttm_object.h" +#include +#include + +/** + * struct ttm_lock + * + * @base: ttm base object used solely to release the lock if the client + * holding the lock dies. + * @queue: Queue for processes waiting for lock change-of-status. + * @lock: Spinlock protecting some lock members. + * @rw: Read-write lock counter. Protected by @lock. + * @flags: Lock state. Protected by @lock. + * @kill_takers: Boolean whether to kill takers of the lock. + * @signal: Signal to send when kill_takers is true. + */ + +struct ttm_lock { + struct ttm_base_object base; + wait_queue_head_t queue; + spinlock_t lock; + int32_t rw; + uint32_t flags; + bool kill_takers; + int signal; + struct ttm_object_file *vt_holder; +}; + + +/** + * ttm_lock_init + * + * @lock: Pointer to a struct ttm_lock + * Initializes the lock. + */ +extern void ttm_lock_init(struct ttm_lock *lock); + +/** + * ttm_read_unlock + * + * @lock: Pointer to a struct ttm_lock + * + * Releases a read lock. + */ +extern void ttm_read_unlock(struct ttm_lock *lock); + +/** + * ttm_read_lock + * + * @lock: Pointer to a struct ttm_lock + * @interruptible: Interruptible sleeping while waiting for a lock. + * + * Takes the lock in read mode. + * Returns: + * -ERESTARTSYS If interrupted by a signal and interruptible is true. + */ +extern int ttm_read_lock(struct ttm_lock *lock, bool interruptible); + +/** + * ttm_read_trylock + * + * @lock: Pointer to a struct ttm_lock + * @interruptible: Interruptible sleeping while waiting for a lock. + * + * Tries to take the lock in read mode. If the lock is already held + * in write mode, the function will return -EBUSY. If the lock is held + * in vt or suspend mode, the function will sleep until these modes + * are unlocked. + * + * Returns: + * -EBUSY The lock was already held in write mode. + * -ERESTARTSYS If interrupted by a signal and interruptible is true. + */ +extern int ttm_read_trylock(struct ttm_lock *lock, bool interruptible); + +/** + * ttm_write_unlock + * + * @lock: Pointer to a struct ttm_lock + * + * Releases a write lock. + */ +extern void ttm_write_unlock(struct ttm_lock *lock); + +/** + * ttm_write_lock + * + * @lock: Pointer to a struct ttm_lock + * @interruptible: Interruptible sleeping while waiting for a lock. + * + * Takes the lock in write mode. + * Returns: + * -ERESTARTSYS If interrupted by a signal and interruptible is true. + */ +extern int ttm_write_lock(struct ttm_lock *lock, bool interruptible); + +/** + * ttm_lock_downgrade + * + * @lock: Pointer to a struct ttm_lock + * + * Downgrades a write lock to a read lock. + */ +extern void ttm_lock_downgrade(struct ttm_lock *lock); + +/** + * ttm_suspend_lock + * + * @lock: Pointer to a struct ttm_lock + * + * Takes the lock in suspend mode. Excludes read and write mode. + */ +extern void ttm_suspend_lock(struct ttm_lock *lock); + +/** + * ttm_suspend_unlock + * + * @lock: Pointer to a struct ttm_lock + * + * Releases a suspend lock + */ +extern void ttm_suspend_unlock(struct ttm_lock *lock); + +/** + * ttm_vt_lock + * + * @lock: Pointer to a struct ttm_lock + * @interruptible: Interruptible sleeping while waiting for a lock. + * @tfile: Pointer to a struct ttm_object_file to register the lock with. + * + * Takes the lock in vt mode. + * Returns: + * -ERESTARTSYS If interrupted by a signal and interruptible is true. + * -ENOMEM: Out of memory when locking. + */ +extern int ttm_vt_lock(struct ttm_lock *lock, bool interruptible, + struct ttm_object_file *tfile); + +/** + * ttm_vt_unlock + * + * @lock: Pointer to a struct ttm_lock + * + * Releases a vt lock. + * Returns: + * -EINVAL If the lock was not held. + */ +extern int ttm_vt_unlock(struct ttm_lock *lock); + +/** + * ttm_write_unlock + * + * @lock: Pointer to a struct ttm_lock + * + * Releases a write lock. + */ +extern void ttm_write_unlock(struct ttm_lock *lock); + +/** + * ttm_write_lock + * + * @lock: Pointer to a struct ttm_lock + * @interruptible: Interruptible sleeping while waiting for a lock. + * + * Takes the lock in write mode. + * Returns: + * -ERESTARTSYS If interrupted by a signal and interruptible is true. + */ +extern int ttm_write_lock(struct ttm_lock *lock, bool interruptible); + +/** + * ttm_lock_set_kill + * + * @lock: Pointer to a struct ttm_lock + * @val: Boolean whether to kill processes taking the lock. + * @signal: Signal to send to the process taking the lock. + * + * The kill-when-taking-lock functionality is used to kill processes that keep + * on using the TTM functionality when its resources has been taken down, for + * example when the X server exits. A typical sequence would look like this: + * - X server takes lock in write mode. + * - ttm_lock_set_kill() is called with @val set to true. + * - As part of X server exit, TTM resources are taken down. + * - X server releases the lock on file release. + * - Another dri client wants to render, takes the lock and is killed. + * + */ +static inline void ttm_lock_set_kill(struct ttm_lock *lock, bool val, + int signal) +{ + lock->kill_takers = val; + if (val) + lock->signal = signal; +} + +#endif diff --git a/include/drm/ttm/ttm_memory.h b/include/drm/ttm/ttm_memory.h index 6983a7cf4da4a70f69f121a3345bc50da2bcb572..b199170b3c2ca92fd8a56e9a58bf1056401aa720 100644 --- a/include/drm/ttm/ttm_memory.h +++ b/include/drm/ttm/ttm_memory.h @@ -33,6 +33,7 @@ #include #include #include +#include /** * struct ttm_mem_shrink - callback to shrink TTM memory usage. diff --git a/include/drm/ttm/ttm_object.h b/include/drm/ttm/ttm_object.h new file mode 100644 index 0000000000000000000000000000000000000000..703ca4db0a297615f84064ee736ddd191b5f3b83 --- /dev/null +++ b/include/drm/ttm/ttm_object.h @@ -0,0 +1,267 @@ +/************************************************************************** + * + * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ +/* + * Authors: Thomas Hellstrom + */ +/** @file ttm_object.h + * + * Base- and reference object implementation for the various + * ttm objects. Implements reference counting, minimal security checks + * and release on file close. + */ + +#ifndef _TTM_OBJECT_H_ +#define _TTM_OBJECT_H_ + +#include +#include "drm_hashtab.h" +#include +#include + +/** + * enum ttm_ref_type + * + * Describes what type of reference a ref object holds. + * + * TTM_REF_USAGE is a simple refcount on a base object. + * + * TTM_REF_SYNCCPU_READ is a SYNCCPU_READ reference on a + * buffer object. + * + * TTM_REF_SYNCCPU_WRITE is a SYNCCPU_WRITE reference on a + * buffer object. + * + */ + +enum ttm_ref_type { + TTM_REF_USAGE, + TTM_REF_SYNCCPU_READ, + TTM_REF_SYNCCPU_WRITE, + TTM_REF_NUM +}; + +/** + * enum ttm_object_type + * + * One entry per ttm object type. + * Device-specific types should use the + * ttm_driver_typex types. + */ + +enum ttm_object_type { + ttm_fence_type, + ttm_buffer_type, + ttm_lock_type, + ttm_driver_type0 = 256, + ttm_driver_type1 +}; + +struct ttm_object_file; +struct ttm_object_device; + +/** + * struct ttm_base_object + * + * @hash: hash entry for the per-device object hash. + * @type: derived type this object is base class for. + * @shareable: Other ttm_object_files can access this object. + * + * @tfile: Pointer to ttm_object_file of the creator. + * NULL if the object was not created by a user request. + * (kernel object). + * + * @refcount: Number of references to this object, not + * including the hash entry. A reference to a base object can + * only be held by a ref object. + * + * @refcount_release: A function to be called when there are + * no more references to this object. This function should + * destroy the object (or make sure destruction eventually happens), + * and when it is called, the object has + * already been taken out of the per-device hash. The parameter + * "base" should be set to NULL by the function. + * + * @ref_obj_release: A function to be called when a reference object + * with another ttm_ref_type than TTM_REF_USAGE is deleted. + * this function may, for example, release a lock held by a user-space + * process. + * + * This struct is intended to be used as a base struct for objects that + * are visible to user-space. It provides a global name, race-safe + * access and refcounting, minimal access contol and hooks for unref actions. + */ + +struct ttm_base_object { + struct drm_hash_item hash; + enum ttm_object_type object_type; + bool shareable; + struct ttm_object_file *tfile; + struct kref refcount; + void (*refcount_release) (struct ttm_base_object **base); + void (*ref_obj_release) (struct ttm_base_object *base, + enum ttm_ref_type ref_type); +}; + +/** + * ttm_base_object_init + * + * @tfile: Pointer to a struct ttm_object_file. + * @base: The struct ttm_base_object to initialize. + * @shareable: This object is shareable with other applcations. + * (different @tfile pointers.) + * @type: The object type. + * @refcount_release: See the struct ttm_base_object description. + * @ref_obj_release: See the struct ttm_base_object description. + * + * Initializes a struct ttm_base_object. + */ + +extern int ttm_base_object_init(struct ttm_object_file *tfile, + struct ttm_base_object *base, + bool shareable, + enum ttm_object_type type, + void (*refcount_release) (struct ttm_base_object + **), + void (*ref_obj_release) (struct ttm_base_object + *, + enum ttm_ref_type + ref_type)); + +/** + * ttm_base_object_lookup + * + * @tfile: Pointer to a struct ttm_object_file. + * @key: Hash key + * + * Looks up a struct ttm_base_object with the key @key. + * Also verifies that the object is visible to the application, by + * comparing the @tfile argument and checking the object shareable flag. + */ + +extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file + *tfile, uint32_t key); + +/** + * ttm_base_object_unref + * + * @p_base: Pointer to a pointer referncing a struct ttm_base_object. + * + * Decrements the base object refcount and clears the pointer pointed to by + * p_base. + */ + +extern void ttm_base_object_unref(struct ttm_base_object **p_base); + +/** + * ttm_ref_object_add. + * + * @tfile: A struct ttm_object_file representing the application owning the + * ref_object. + * @base: The base object to reference. + * @ref_type: The type of reference. + * @existed: Upon completion, indicates that an identical reference object + * already existed, and the refcount was upped on that object instead. + * + * Adding a ref object to a base object is basically like referencing the + * base object, but a user-space application holds the reference. When the + * file corresponding to @tfile is closed, all its reference objects are + * deleted. A reference object can have different types depending on what + * it's intended for. It can be refcounting to prevent object destruction, + * When user-space takes a lock, it can add a ref object to that lock to + * make sure the lock is released if the application dies. A ref object + * will hold a single reference on a base object. + */ +extern int ttm_ref_object_add(struct ttm_object_file *tfile, + struct ttm_base_object *base, + enum ttm_ref_type ref_type, bool *existed); +/** + * ttm_ref_object_base_unref + * + * @key: Key representing the base object. + * @ref_type: Ref type of the ref object to be dereferenced. + * + * Unreference a ref object with type @ref_type + * on the base object identified by @key. If there are no duplicate + * references, the ref object will be destroyed and the base object + * will be unreferenced. + */ +extern int ttm_ref_object_base_unref(struct ttm_object_file *tfile, + unsigned long key, + enum ttm_ref_type ref_type); + +/** + * ttm_object_file_init - initialize a struct ttm_object file + * + * @tdev: A struct ttm_object device this file is initialized on. + * @hash_order: Order of the hash table used to hold the reference objects. + * + * This is typically called by the file_ops::open function. + */ + +extern struct ttm_object_file *ttm_object_file_init(struct ttm_object_device + *tdev, + unsigned int hash_order); + +/** + * ttm_object_file_release - release data held by a ttm_object_file + * + * @p_tfile: Pointer to pointer to the ttm_object_file object to release. + * *p_tfile will be set to NULL by this function. + * + * Releases all data associated by a ttm_object_file. + * Typically called from file_ops::release. The caller must + * ensure that there are no concurrent users of tfile. + */ + +extern void ttm_object_file_release(struct ttm_object_file **p_tfile); + +/** + * ttm_object device init - initialize a struct ttm_object_device + * + * @hash_order: Order of hash table used to hash the base objects. + * + * This function is typically called on device initialization to prepare + * data structures needed for ttm base and ref objects. + */ + +extern struct ttm_object_device *ttm_object_device_init + (struct ttm_mem_global *mem_glob, unsigned int hash_order); + +/** + * ttm_object_device_release - release data held by a ttm_object_device + * + * @p_tdev: Pointer to pointer to the ttm_object_device object to release. + * *p_tdev will be set to NULL by this function. + * + * Releases all data associated by a ttm_object_device. + * Typically called from driver::unload before the destruction of the + * device private data structure. + */ + +extern void ttm_object_device_release(struct ttm_object_device **p_tdev); + +#endif diff --git a/include/drm/via_drm.h b/include/drm/via_drm.h index 170786e5c2ff2ee5c6cb2a2e4c385b7a9963e84f..fd11a5bd892d6459fb9a96866d2c8fe15fd9884f 100644 --- a/include/drm/via_drm.h +++ b/include/drm/via_drm.h @@ -24,7 +24,7 @@ #ifndef _VIA_DRM_H_ #define _VIA_DRM_H_ -#include +#include "drm.h" /* WARNING: These defines must be the same as what the Xserver uses. * if you change them, you must change the defines in the Xserver. diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 5a5385749e1636a5c327c1c728243eadad25e0af..f72914db2a115f0fb7ad2b074300272f699c696b 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -214,7 +214,6 @@ unifdef-y += futex.h unifdef-y += fs.h unifdef-y += gameport.h unifdef-y += generic_serial.h -unifdef-y += hayesesp.h unifdef-y += hdlcdrv.h unifdef-y += hdlc.h unifdef-y += hdreg.h diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 47536197ffddde1a8c28ef942ceefa78c20719e4..e287863ac053d9788756ac79c9271ba562d455b1 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -43,6 +43,8 @@ extern int sched_create_sysfs_power_savings_entries(struct sysdev_class *cls); #ifdef CONFIG_HOTPLUG_CPU extern void unregister_cpu(struct cpu *cpu); +extern ssize_t arch_cpu_probe(const char *, size_t); +extern ssize_t arch_cpu_release(const char *, size_t); #endif struct notifier_block; @@ -115,6 +117,19 @@ extern void put_online_cpus(void); #define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb) int cpu_down(unsigned int cpu); +#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE +extern void cpu_hotplug_driver_lock(void); +extern void cpu_hotplug_driver_unlock(void); +#else +static inline void cpu_hotplug_driver_lock(void) +{ +} + +static inline void cpu_hotplug_driver_unlock(void) +{ +} +#endif + #else /* CONFIG_HOTPLUG_CPU */ #define get_online_cpus() do { } while (0) diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 79a2340d83cda45c88138841fe4b2a8a3892bcad..4de02b10007ff4258ce6be681687d263239e1c12 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -232,6 +232,7 @@ struct cpufreq_driver { /* optional */ unsigned int (*getavg) (struct cpufreq_policy *policy, unsigned int cpu); + int (*bios_limit) (int cpu, unsigned int *limit); int (*exit) (struct cpufreq_policy *policy); int (*suspend) (struct cpufreq_policy *policy, pm_message_t pmsg); diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 789cf5f920ce80e697ca05a9a7fde743cdde9e1a..d77b54733c5b63980c51fe354ee91de1a41ce81a 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -84,6 +84,7 @@ extern const struct cpumask *const cpu_active_mask; #define num_online_cpus() cpumask_weight(cpu_online_mask) #define num_possible_cpus() cpumask_weight(cpu_possible_mask) #define num_present_cpus() cpumask_weight(cpu_present_mask) +#define num_active_cpus() cpumask_weight(cpu_active_mask) #define cpu_online(cpu) cpumask_test_cpu((cpu), cpu_online_mask) #define cpu_possible(cpu) cpumask_test_cpu((cpu), cpu_possible_mask) #define cpu_present(cpu) cpumask_test_cpu((cpu), cpu_present_mask) @@ -92,6 +93,7 @@ extern const struct cpumask *const cpu_active_mask; #define num_online_cpus() 1 #define num_possible_cpus() 1 #define num_present_cpus() 1 +#define num_active_cpus() 1 #define cpu_online(cpu) ((cpu) == 0) #define cpu_possible(cpu) ((cpu) == 0) #define cpu_present(cpu) ((cpu) == 0) diff --git a/include/linux/device.h b/include/linux/device.h index 2ea3e49218129a6a4a4f314858ba0e0cbaa49691..2a73d9bcbc9c9f02fee174ef4d7cd3419e00c930 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -558,7 +558,7 @@ extern void wait_for_device_probe(void); #ifdef CONFIG_DEVTMPFS extern int devtmpfs_create_node(struct device *dev); extern int devtmpfs_delete_node(struct device *dev); -extern int devtmpfs_mount(const char *mountpoint); +extern int devtmpfs_mount(const char *mntdir); #else static inline int devtmpfs_create_node(struct device *dev) { return 0; } static inline int devtmpfs_delete_node(struct device *dev) { return 0; } diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h index 121720d74e15babe70c9dab51eb4394cb0ca53b2..2dfa7076e8b601f5197420c6bdbab1780ca77d7f 100644 --- a/include/linux/ext2_fs.h +++ b/include/linux/ext2_fs.h @@ -565,14 +565,14 @@ struct ext2_dir_entry_2 { * other bits are reserved for now. */ enum { - EXT2_FT_UNKNOWN, - EXT2_FT_REG_FILE, - EXT2_FT_DIR, - EXT2_FT_CHRDEV, - EXT2_FT_BLKDEV, - EXT2_FT_FIFO, - EXT2_FT_SOCK, - EXT2_FT_SYMLINK, + EXT2_FT_UNKNOWN = 0, + EXT2_FT_REG_FILE = 1, + EXT2_FT_DIR = 2, + EXT2_FT_CHRDEV = 3, + EXT2_FT_BLKDEV = 4, + EXT2_FT_FIFO = 5, + EXT2_FT_SOCK = 6, + EXT2_FT_SYMLINK = 7, EXT2_FT_MAX }; diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index 7499b36677985240f73743c9993c0ceadd16bc5b..6b049030fbe6f3ff063dfe7882712760af13b761 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h @@ -918,6 +918,8 @@ extern void ext3_abort (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); extern void ext3_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); +extern void ext3_msg(struct super_block *, const char *, const char *, ...) + __attribute__ ((format (printf, 3, 4))); extern void ext3_update_dynamic_rev (struct super_block *sb); #define ext3_std_error(sb, errno) \ diff --git a/include/linux/fb.h b/include/linux/fb.h index de9c722e7b90e0827bb39a9ce3c26eb641914599..369767bd873efe5bafedb6b5936982952848a914 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -763,6 +763,7 @@ struct fb_tile_ops { * takes over; acceleration engine should be in a quiescent state */ /* hints */ +#define FBINFO_VIRTFB 0x0004 /* FB is System RAM, not device. */ #define FBINFO_PARTIAL_PAN_OK 0x0040 /* otw use pan only for double-buffering */ #define FBINFO_READS_FAST 0x0080 /* soft-copy faster than rendering */ diff --git a/include/linux/firmware.h b/include/linux/firmware.h index d31544628436cb717b88079f7f99bf6e9b775b68..043811f0d277d163d68c263fe0db9dba1423a11c 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -4,6 +4,7 @@ #include #include #include +#include #define FW_ACTION_NOHOTPLUG 0 #define FW_ACTION_HOTPLUG 1 @@ -38,7 +39,7 @@ int request_firmware(const struct firmware **fw, const char *name, struct device *device); int request_firmware_nowait( struct module *module, int uevent, - const char *name, struct device *device, void *context, + const char *name, struct device *device, gfp_t gfp, void *context, void (*cont)(const struct firmware *fw, void *context)); void release_firmware(const struct firmware *fw); @@ -51,7 +52,7 @@ static inline int request_firmware(const struct firmware **fw, } static inline int request_firmware_nowait( struct module *module, int uevent, - const char *name, struct device *device, void *context, + const char *name, struct device *device, gfp_t gfp, void *context, void (*cont)(const struct firmware *fw, void *context)) { return -EINVAL; diff --git a/include/linux/fs.h b/include/linux/fs.h index 891f7d642e5c6789cb05853137a8caa58a21c2c6..a057f48eb156ca2fb015ddedabd3dbb1da473f1b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2091,8 +2091,6 @@ extern int filemap_fdatawait_range(struct address_space *, loff_t lstart, extern int filemap_write_and_wait(struct address_space *mapping); extern int filemap_write_and_wait_range(struct address_space *mapping, loff_t lstart, loff_t lend); -extern int wait_on_page_writeback_range(struct address_space *mapping, - pgoff_t start, pgoff_t end); extern int __filemap_fdatawrite_range(struct address_space *mapping, loff_t start, loff_t end, int sync_mode); extern int filemap_fdatawrite_range(struct address_space *mapping, diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index 43fc95d822d5e51f2ddd21321a2791c96613abf4..28e33fea510736f179ccfdb985e0d630b0aae616 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -74,7 +74,12 @@ struct spi_device; struct fsl_spi_platform_data { u32 initial_spmode; /* initial SPMODE value */ s16 bus_num; - bool qe_mode; + unsigned int flags; +#define SPI_QE_CPU_MODE (1 << 0) /* QE CPU ("PIO") mode */ +#define SPI_CPM_MODE (1 << 1) /* CPM/QE ("DMA") mode */ +#define SPI_CPM1 (1 << 2) /* SPI unit is in CPM1 block */ +#define SPI_CPM2 (1 << 3) /* SPI unit is in CPM2 block */ +#define SPI_QE (1 << 4) /* SPI unit is in QE block */ /* board specific information */ u16 max_chipselect; void (*cs_control)(struct spi_device *spi, bool on); @@ -90,6 +95,10 @@ struct mpc8xx_pcmcia_ops { * lead to a deep sleep (i.e. power removed from the core, * instead of just the clock). */ +#if defined(CONFIG_PPC_83xx) && defined(CONFIG_SUSPEND) int fsl_deep_sleep(void); +#else +static inline int fsl_deep_sleep(void) { return 0; } +#endif #endif /* _FSL_DEVICE_H_ */ diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index 47bbdf9c38d0428328e48d9c772cdc3086375e5c..38f8d6553831a6a9ee2839ac56071b795700d917 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h @@ -57,6 +57,7 @@ struct trace_iterator { /* The below is zeroed out in pipe_read */ struct trace_seq seq; struct trace_entry *ent; + int leftover; int cpu; u64 ts; diff --git a/include/linux/gigaset_dev.h b/include/linux/gigaset_dev.h index 5dc4a316ca370510bf5e661b0f2eff9ed4d8f107..258ba82937e7937b47f745a067b90fa46f3721a4 100644 --- a/include/linux/gigaset_dev.h +++ b/include/linux/gigaset_dev.h @@ -16,15 +16,23 @@ #include +/* The magic IOCTL value for this interface. */ #define GIGASET_IOCTL 0x47 -#define GIGVER_DRIVER 0 -#define GIGVER_COMPAT 1 -#define GIGVER_FWBASE 2 +/* enable/disable device control via character device (lock out ISDN subsys) */ +#define GIGASET_REDIR _IOWR(GIGASET_IOCTL, 0, int) -#define GIGASET_REDIR _IOWR (GIGASET_IOCTL, 0, int) -#define GIGASET_CONFIG _IOWR (GIGASET_IOCTL, 1, int) -#define GIGASET_BRKCHARS _IOW (GIGASET_IOCTL, 2, unsigned char[6]) //FIXME [6] okay? -#define GIGASET_VERSION _IOWR (GIGASET_IOCTL, 3, unsigned[4]) +/* enable adapter configuration mode (M10x only) */ +#define GIGASET_CONFIG _IOWR(GIGASET_IOCTL, 1, int) + +/* set break characters (M105 only) */ +#define GIGASET_BRKCHARS _IOW(GIGASET_IOCTL, 2, unsigned char[6]) + +/* get version information selected by arg[0] */ +#define GIGASET_VERSION _IOWR(GIGASET_IOCTL, 3, unsigned[4]) +/* values for GIGASET_VERSION arg[0] */ +#define GIGVER_DRIVER 0 /* get driver version */ +#define GIGVER_COMPAT 1 /* get interface compatibility version */ +#define GIGVER_FWBASE 2 /* get base station firmware version */ #endif diff --git a/include/linux/hayesesp.h b/include/linux/hayesesp.h deleted file mode 100644 index 92b08cfe4a752b9ebb73e5973de3f9afba271a6b..0000000000000000000000000000000000000000 --- a/include/linux/hayesesp.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef HAYESESP_H -#define HAYESESP_H - -struct hayes_esp_config { - short flow_on; - short flow_off; - short rx_trigger; - short tx_trigger; - short pio_threshold; - unsigned char rx_timeout; - char dma_channel; -}; - -#ifdef __KERNEL__ - -#define ESP_DMA_CHANNEL 0 -#define ESP_RX_TRIGGER 768 -#define ESP_TX_TRIGGER 768 -#define ESP_FLOW_OFF 1016 -#define ESP_FLOW_ON 944 -#define ESP_RX_TMOUT 128 -#define ESP_PIO_THRESHOLD 32 - -#define ESP_IN_MAJOR 57 /* major dev # for dial in */ -#define ESP_OUT_MAJOR 58 /* major dev # for dial out */ -#define ESPC_SCALE 3 -#define UART_ESI_BASE 0x00 -#define UART_ESI_SID 0x01 -#define UART_ESI_RX 0x02 -#define UART_ESI_TX 0x02 -#define UART_ESI_CMD1 0x04 -#define UART_ESI_CMD2 0x05 -#define UART_ESI_STAT1 0x04 -#define UART_ESI_STAT2 0x05 -#define UART_ESI_RWS 0x07 - -#define UART_IER_DMA_TMOUT 0x80 -#define UART_IER_DMA_TC 0x08 - -#define ESI_SET_IRQ 0x04 -#define ESI_SET_DMA_TMOUT 0x05 -#define ESI_SET_SRV_MASK 0x06 -#define ESI_SET_ERR_MASK 0x07 -#define ESI_SET_FLOW_CNTL 0x08 -#define ESI_SET_FLOW_CHARS 0x09 -#define ESI_SET_FLOW_LVL 0x0a -#define ESI_SET_TRIGGER 0x0b -#define ESI_SET_RX_TIMEOUT 0x0c -#define ESI_SET_FLOW_TMOUT 0x0d -#define ESI_WRITE_UART 0x0e -#define ESI_READ_UART 0x0f -#define ESI_SET_MODE 0x10 -#define ESI_GET_ERR_STAT 0x12 -#define ESI_GET_UART_STAT 0x13 -#define ESI_GET_RX_AVAIL 0x14 -#define ESI_GET_TX_AVAIL 0x15 -#define ESI_START_DMA_RX 0x16 -#define ESI_START_DMA_TX 0x17 -#define ESI_ISSUE_BREAK 0x1a -#define ESI_FLUSH_RX 0x1b -#define ESI_FLUSH_TX 0x1c -#define ESI_SET_BAUD 0x1d -#define ESI_SET_ENH_IRQ 0x1f -#define ESI_SET_REINTR 0x20 -#define ESI_SET_PRESCALAR 0x23 -#define ESI_NO_COMMAND 0xff - -#define ESP_STAT_RX_TIMEOUT 0x01 -#define ESP_STAT_DMA_RX 0x02 -#define ESP_STAT_DMA_TX 0x04 -#define ESP_STAT_NEVER_DMA 0x08 -#define ESP_STAT_USE_PIO 0x10 - -#define ESP_MAGIC 0x53ee -#define ESP_XMIT_SIZE 4096 - -struct esp_struct { - int magic; - struct tty_port port; - spinlock_t lock; - int io_port; - int irq; - int read_status_mask; - int ignore_status_mask; - int timeout; - int stat_flags; - int custom_divisor; - int close_delay; - unsigned short closing_wait; - unsigned short closing_wait2; - int IER; /* Interrupt Enable Register */ - int MCR; /* Modem control register */ - unsigned long last_active; - int line; - unsigned char *xmit_buf; - int xmit_head; - int xmit_tail; - int xmit_cnt; - wait_queue_head_t break_wait; - struct async_icount icount; /* kernel counters for the 4 input interrupts */ - struct hayes_esp_config config; /* port configuration */ - struct esp_struct *next_port; /* For the linked list */ -}; - -struct esp_pio_buffer { - unsigned char data[1024]; - struct esp_pio_buffer *next; -}; - -#endif /* __KERNEL__ */ - - -#endif /* ESP_H */ - diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 9bace4b9f4fe954717b0bf45c840c3fd794734f8..af634e95871deb2dca0b4ef2d2d5a116bc83b0c2 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -162,10 +162,11 @@ struct hrtimer_clock_base { * @expires_next: absolute time of the next event which was scheduled * via clock_set_next_event() * @hres_active: State of high resolution mode - * @check_clocks: Indictator, when set evaluate time source and clock - * event devices whether high resolution mode can be - * activated. - * @nr_events: Total number of timer interrupt events + * @hang_detected: The last hrtimer interrupt detected a hang + * @nr_events: Total number of hrtimer interrupt events + * @nr_retries: Total number of hrtimer interrupt retries + * @nr_hangs: Total number of hrtimer interrupt hangs + * @max_hang_time: Maximum time spent in hrtimer_interrupt */ struct hrtimer_cpu_base { spinlock_t lock; @@ -173,7 +174,11 @@ struct hrtimer_cpu_base { #ifdef CONFIG_HIGH_RES_TIMERS ktime_t expires_next; int hres_active; + int hang_detected; unsigned long nr_events; + unsigned long nr_retries; + unsigned long nr_hangs; + ktime_t max_hang_time; #endif }; @@ -435,47 +440,4 @@ extern u64 ktime_divns(const ktime_t kt, s64 div); /* Show pending timers: */ extern void sysrq_timer_list_show(void); -/* - * Timer-statistics info: - */ -#ifdef CONFIG_TIMER_STATS - -extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf, - void *timerf, char *comm, - unsigned int timer_flag); - -static inline void timer_stats_account_hrtimer(struct hrtimer *timer) -{ - if (likely(!timer_stats_active)) - return; - timer_stats_update_stats(timer, timer->start_pid, timer->start_site, - timer->function, timer->start_comm, 0); -} - -extern void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer, - void *addr); - -static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) -{ - __timer_stats_hrtimer_set_start_info(timer, __builtin_return_address(0)); -} - -static inline void timer_stats_hrtimer_clear_start_info(struct hrtimer *timer) -{ - timer->start_site = NULL; -} -#else -static inline void timer_stats_account_hrtimer(struct hrtimer *timer) -{ -} - -static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) -{ -} - -static inline void timer_stats_hrtimer_clear_start_info(struct hrtimer *timer) -{ -} -#endif - #endif diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h index a03daed08c59e44d8294525df8fda859eeab417e..41235c93e4e95400bf0db52bf2f7b84399d22a39 100644 --- a/include/linux/hw_breakpoint.h +++ b/include/linux/hw_breakpoint.h @@ -20,19 +20,18 @@ enum { #ifdef CONFIG_HAVE_HW_BREAKPOINT -/* As it's for in-kernel or ptrace use, we want it to be pinned */ -#define DEFINE_BREAKPOINT_ATTR(name) \ -struct perf_event_attr name = { \ - .type = PERF_TYPE_BREAKPOINT, \ - .size = sizeof(name), \ - .pinned = 1, \ -}; - static inline void hw_breakpoint_init(struct perf_event_attr *attr) { + memset(attr, 0, sizeof(*attr)); + attr->type = PERF_TYPE_BREAKPOINT; attr->size = sizeof(*attr); + /* + * As it's for in-kernel or ptrace use, we want it to be pinned + * and to call its callback every hits. + */ attr->pinned = 1; + attr->sample_period = 1; } static inline unsigned long hw_breakpoint_addr(struct perf_event *bp) @@ -52,27 +51,24 @@ static inline int hw_breakpoint_len(struct perf_event *bp) extern struct perf_event * register_user_hw_breakpoint(struct perf_event_attr *attr, - perf_callback_t triggered, + perf_overflow_handler_t triggered, struct task_struct *tsk); /* FIXME: only change from the attr, and don't unregister */ -extern struct perf_event * -modify_user_hw_breakpoint(struct perf_event *bp, - struct perf_event_attr *attr, - perf_callback_t triggered, - struct task_struct *tsk); +extern int +modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr); /* * Kernel breakpoints are not associated with any particular thread. */ extern struct perf_event * register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, - perf_callback_t triggered, + perf_overflow_handler_t triggered, int cpu); extern struct perf_event ** register_wide_hw_breakpoint(struct perf_event_attr *attr, - perf_callback_t triggered); + perf_overflow_handler_t triggered); extern int register_perf_hw_breakpoint(struct perf_event *bp); extern int __register_perf_hw_breakpoint(struct perf_event *bp); @@ -93,20 +89,18 @@ static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp) static inline struct perf_event * register_user_hw_breakpoint(struct perf_event_attr *attr, - perf_callback_t triggered, + perf_overflow_handler_t triggered, struct task_struct *tsk) { return NULL; } -static inline struct perf_event * +static inline int modify_user_hw_breakpoint(struct perf_event *bp, - struct perf_event_attr *attr, - perf_callback_t triggered, - struct task_struct *tsk) { return NULL; } + struct perf_event_attr *attr) { return -ENOSYS; } static inline struct perf_event * register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, - perf_callback_t triggered, + perf_overflow_handler_t triggered, int cpu) { return NULL; } static inline struct perf_event ** register_wide_hw_breakpoint(struct perf_event_attr *attr, - perf_callback_t triggered) { return NULL; } + perf_overflow_handler_t triggered) { return NULL; } static inline int register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; } static inline int diff --git a/include/linux/i2c/tps65010.h b/include/linux/i2c/tps65010.h index 918c5354d9b8967825c12882852803b0e6470785..08aa92278d71cdd6b388c24d8fdb083c719e291b 100644 --- a/include/linux/i2c/tps65010.h +++ b/include/linux/i2c/tps65010.h @@ -72,6 +72,21 @@ #define TPS_VDCDC1 0x0c # define TPS_ENABLE_LP (1 << 3) #define TPS_VDCDC2 0x0d +# define TPS_LP_COREOFF (1 << 7) +# define TPS_VCORE_1_8V (7<<4) +# define TPS_VCORE_1_5V (6 << 4) +# define TPS_VCORE_1_4V (5 << 4) +# define TPS_VCORE_1_3V (4 << 4) +# define TPS_VCORE_1_2V (3 << 4) +# define TPS_VCORE_1_1V (2 << 4) +# define TPS_VCORE_1_0V (1 << 4) +# define TPS_VCORE_0_85V (0 << 4) +# define TPS_VCORE_LP_1_2V (3 << 2) +# define TPS_VCORE_LP_1_1V (2 << 2) +# define TPS_VCORE_LP_1_0V (1 << 2) +# define TPS_VCORE_LP_0_85V (0 << 2) +# define TPS_VIB (1 << 1) +# define TPS_VCORE_DISCH (1 << 0) #define TPS_VREGS1 0x0e # define TPS_LDO2_ENABLE (1 << 7) # define TPS_LDO2_OFF (1 << 6) @@ -152,6 +167,10 @@ extern int tps65010_config_vregs1(unsigned value); */ extern int tps65013_set_low_pwr(unsigned mode); +/* tps65010_set_vdcdc2 + * value to be written to VDCDC2 + */ +extern int tps65010_config_vdcdc2(unsigned value); struct i2c_client; diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl.h similarity index 71% rename from include/linux/i2c/twl4030.h rename to include/linux/i2c/twl.h index 5306a759cbdede6e70245440a5140f2df7821e03..bf1c5be1f5b66879e238ff6605c17b4787f13ffc 100644 --- a/include/linux/i2c/twl4030.h +++ b/include/linux/i2c/twl.h @@ -22,8 +22,8 @@ * */ -#ifndef __TWL4030_H_ -#define __TWL4030_H_ +#ifndef __TWL_H_ +#define __TWL_H_ #include #include @@ -61,28 +61,112 @@ #define TWL4030_MODULE_PWMA 0x0E #define TWL4030_MODULE_PWMB 0x0F +#define TWL5031_MODULE_ACCESSORY 0x10 +#define TWL5031_MODULE_INTERRUPTS 0x11 + /* Slave 3 (i2c address 0x4b) */ -#define TWL4030_MODULE_BACKUP 0x10 -#define TWL4030_MODULE_INT 0x11 -#define TWL4030_MODULE_PM_MASTER 0x12 -#define TWL4030_MODULE_PM_RECEIVER 0x13 -#define TWL4030_MODULE_RTC 0x14 -#define TWL4030_MODULE_SECURED_REG 0x15 +#define TWL4030_MODULE_BACKUP 0x12 +#define TWL4030_MODULE_INT 0x13 +#define TWL4030_MODULE_PM_MASTER 0x14 +#define TWL4030_MODULE_PM_RECEIVER 0x15 +#define TWL4030_MODULE_RTC 0x16 +#define TWL4030_MODULE_SECURED_REG 0x17 + +#define TWL_MODULE_USB TWL4030_MODULE_USB +#define TWL_MODULE_AUDIO_VOICE TWL4030_MODULE_AUDIO_VOICE +#define TWL_MODULE_PIH TWL4030_MODULE_PIH +#define TWL_MODULE_MADC TWL4030_MODULE_MADC +#define TWL_MODULE_MAIN_CHARGE TWL4030_MODULE_MAIN_CHARGE +#define TWL_MODULE_PM_MASTER TWL4030_MODULE_PM_MASTER +#define TWL_MODULE_PM_RECEIVER TWL4030_MODULE_PM_RECEIVER +#define TWL_MODULE_RTC TWL4030_MODULE_RTC + +#define GPIO_INTR_OFFSET 0 +#define KEYPAD_INTR_OFFSET 1 +#define BCI_INTR_OFFSET 2 +#define MADC_INTR_OFFSET 3 +#define USB_INTR_OFFSET 4 +#define BCI_PRES_INTR_OFFSET 9 +#define USB_PRES_INTR_OFFSET 10 +#define RTC_INTR_OFFSET 11 + +/* + * Offset from TWL6030_IRQ_BASE / pdata->irq_base + */ +#define PWR_INTR_OFFSET 0 +#define HOTDIE_INTR_OFFSET 12 +#define SMPSLDO_INTR_OFFSET 13 +#define BATDETECT_INTR_OFFSET 14 +#define SIMDETECT_INTR_OFFSET 15 +#define MMCDETECT_INTR_OFFSET 16 +#define GASGAUGE_INTR_OFFSET 17 +#define USBOTG_INTR_OFFSET 4 +#define CHARGER_INTR_OFFSET 2 +#define RSV_INTR_OFFSET 0 + +/* INT register offsets */ +#define REG_INT_STS_A 0x00 +#define REG_INT_STS_B 0x01 +#define REG_INT_STS_C 0x02 + +#define REG_INT_MSK_LINE_A 0x03 +#define REG_INT_MSK_LINE_B 0x04 +#define REG_INT_MSK_LINE_C 0x05 + +#define REG_INT_MSK_STS_A 0x06 +#define REG_INT_MSK_STS_B 0x07 +#define REG_INT_MSK_STS_C 0x08 + +/* MASK INT REG GROUP A */ +#define TWL6030_PWR_INT_MASK 0x07 +#define TWL6030_RTC_INT_MASK 0x18 +#define TWL6030_HOTDIE_INT_MASK 0x20 +#define TWL6030_SMPSLDOA_INT_MASK 0xC0 + +/* MASK INT REG GROUP B */ +#define TWL6030_SMPSLDOB_INT_MASK 0x01 +#define TWL6030_BATDETECT_INT_MASK 0x02 +#define TWL6030_SIMDETECT_INT_MASK 0x04 +#define TWL6030_MMCDETECT_INT_MASK 0x08 +#define TWL6030_GPADC_INT_MASK 0x60 +#define TWL6030_GASGAUGE_INT_MASK 0x80 + +/* MASK INT REG GROUP C */ +#define TWL6030_USBOTG_INT_MASK 0x0F +#define TWL6030_CHARGER_CTRL_INT_MASK 0x10 +#define TWL6030_CHARGER_FAULT_INT_MASK 0x60 + + +#define TWL4030_CLASS_ID 0x4030 +#define TWL6030_CLASS_ID 0x6030 +unsigned int twl_rev(void); +#define GET_TWL_REV (twl_rev()) +#define TWL_CLASS_IS(class, id) \ +static inline int twl_class_is_ ##class(void) \ +{ \ + return ((id) == (GET_TWL_REV)) ? 1 : 0; \ +} + +TWL_CLASS_IS(4030, TWL4030_CLASS_ID) +TWL_CLASS_IS(6030, TWL6030_CLASS_ID) /* * Read and write single 8-bit registers */ -int twl4030_i2c_write_u8(u8 mod_no, u8 val, u8 reg); -int twl4030_i2c_read_u8(u8 mod_no, u8 *val, u8 reg); +int twl_i2c_write_u8(u8 mod_no, u8 val, u8 reg); +int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg); /* * Read and write several 8-bit registers at once. * - * IMPORTANT: For twl4030_i2c_write(), allocate num_bytes + 1 + * IMPORTANT: For twl_i2c_write(), allocate num_bytes + 1 * for the value, and populate your data starting at offset 1. */ -int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); -int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); +int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); +int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); + +int twl6030_interrupt_unmask(u8 bit_mask, u8 offset); +int twl6030_interrupt_mask(u8 bit_mask, u8 offset); /*----------------------------------------------------------------------*/ @@ -221,6 +305,38 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); /*----------------------------------------------------------------------*/ +/* + * Accessory Interrupts + */ +#define TWL5031_ACIIMR_LSB 0x05 +#define TWL5031_ACIIMR_MSB 0x06 +#define TWL5031_ACIIDR_LSB 0x07 +#define TWL5031_ACIIDR_MSB 0x08 +#define TWL5031_ACCISR1 0x0F +#define TWL5031_ACCIMR1 0x10 +#define TWL5031_ACCISR2 0x11 +#define TWL5031_ACCIMR2 0x12 +#define TWL5031_ACCSIR 0x13 +#define TWL5031_ACCEDR1 0x14 +#define TWL5031_ACCSIHCTRL 0x15 + +/*----------------------------------------------------------------------*/ + +/* + * Battery Charger Controller + */ + +#define TWL5031_INTERRUPTS_BCIISR1 0x0 +#define TWL5031_INTERRUPTS_BCIIMR1 0x1 +#define TWL5031_INTERRUPTS_BCIISR2 0x2 +#define TWL5031_INTERRUPTS_BCIIMR2 0x3 +#define TWL5031_INTERRUPTS_BCISIR 0x4 +#define TWL5031_INTERRUPTS_BCIEDR1 0x5 +#define TWL5031_INTERRUPTS_BCIEDR2 0x6 +#define TWL5031_INTERRUPTS_BCISIHCTRL 0x7 + +/*----------------------------------------------------------------------*/ + /* Power bus message definitions */ /* The TWL4030/5030 splits its power-management resources (the various @@ -250,6 +366,7 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); #define RES_TYPE_ALL 0x7 +/* Resource states */ #define RES_STATE_WRST 0xF #define RES_STATE_ACTIVE 0xE #define RES_STATE_SLEEP 0x8 @@ -310,8 +427,18 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); #define MSG_SINGULAR(devgrp, id, state) \ ((devgrp) << 13 | 0 << 12 | (id) << 4 | (state)) +#define MSG_BROADCAST_ALL(devgrp, state) \ + ((devgrp) << 5 | (state)) + +#define MSG_BROADCAST_REF MSG_BROADCAST_ALL +#define MSG_BROADCAST_PROV MSG_BROADCAST_ALL +#define MSG_BROADCAST__CLK_RST MSG_BROADCAST_ALL /*----------------------------------------------------------------------*/ +struct twl4030_clock_init_data { + bool ck32k_lowpwr_enable; +}; + struct twl4030_bci_platform_data { int *battery_tmp_tbl; unsigned int tblsize; @@ -391,12 +518,15 @@ struct twl4030_resconfig { u8 devgroup; /* Processor group that Power resource belongs to */ u8 type; /* Power resource addressed, 6 / broadcast message */ u8 type2; /* Power resource addressed, 3 / broadcast message */ + u8 remap_off; /* off state remapping */ + u8 remap_sleep; /* sleep state remapping */ }; struct twl4030_power_data { struct twl4030_script **scripts; unsigned num; struct twl4030_resconfig *resource_config; +#define TWL4030_RESCONFIG_UNDEF ((u8)-1) }; extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts); @@ -421,6 +551,7 @@ struct twl4030_codec_data { struct twl4030_platform_data { unsigned irq_base, irq_end; + struct twl4030_clock_init_data *clock; struct twl4030_bci_platform_data *bci; struct twl4030_gpio_platform_data *gpio; struct twl4030_madc_platform_data *madc; @@ -429,19 +560,31 @@ struct twl4030_platform_data { struct twl4030_power_data *power; struct twl4030_codec_data *codec; - /* LDO regulators */ + /* Common LDO regulators for TWL4030/TWL6030 */ struct regulator_init_data *vdac; + struct regulator_init_data *vaux1; + struct regulator_init_data *vaux2; + struct regulator_init_data *vaux3; + /* TWL4030 LDO regulators */ struct regulator_init_data *vpll1; struct regulator_init_data *vpll2; struct regulator_init_data *vmmc1; struct regulator_init_data *vmmc2; struct regulator_init_data *vsim; - struct regulator_init_data *vaux1; - struct regulator_init_data *vaux2; - struct regulator_init_data *vaux3; struct regulator_init_data *vaux4; - - /* REVISIT more to come ... _nothing_ should be hard-wired */ + struct regulator_init_data *vio; + struct regulator_init_data *vdd1; + struct regulator_init_data *vdd2; + struct regulator_init_data *vintana1; + struct regulator_init_data *vintana2; + struct regulator_init_data *vintdig; + /* TWL6030 LDO regulators */ + struct regulator_init_data *vmmc; + struct regulator_init_data *vpp; + struct regulator_init_data *vusim; + struct regulator_init_data *vana; + struct regulator_init_data *vcxio; + struct regulator_init_data *vusb; }; /*----------------------------------------------------------------------*/ @@ -473,6 +616,7 @@ int twl4030_sih_setup(int module); * VIO is generally fixed. */ +/* TWL4030 SMPS/LDO's */ /* EXTERNAL dc-to-dc buck converters */ #define TWL4030_REG_VDD1 0 #define TWL4030_REG_VDD2 1 @@ -499,4 +643,31 @@ int twl4030_sih_setup(int module); #define TWL4030_REG_VUSB1V8 18 #define TWL4030_REG_VUSB3V1 19 +/* TWL6030 SMPS/LDO's */ +/* EXTERNAL dc-to-dc buck convertor contollable via SR */ +#define TWL6030_REG_VDD1 30 +#define TWL6030_REG_VDD2 31 +#define TWL6030_REG_VDD3 32 + +/* Non SR compliant dc-to-dc buck convertors */ +#define TWL6030_REG_VMEM 33 +#define TWL6030_REG_V2V1 34 +#define TWL6030_REG_V1V29 35 +#define TWL6030_REG_V1V8 36 + +/* EXTERNAL LDOs */ +#define TWL6030_REG_VAUX1_6030 37 +#define TWL6030_REG_VAUX2_6030 38 +#define TWL6030_REG_VAUX3_6030 39 +#define TWL6030_REG_VMMC 40 +#define TWL6030_REG_VPP 41 +#define TWL6030_REG_VUSIM 42 +#define TWL6030_REG_VANA 43 +#define TWL6030_REG_VCXIO 44 +#define TWL6030_REG_VDAC 45 +#define TWL6030_REG_VUSB 46 + +/* INTERNAL LDOs */ +#define TWL6030_REG_VRTC 47 + #endif /* End of __TWL4030_H */ diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index 005e1525ab867d19be402a948ddc6efcbe2fd4c8..299b4121f91486b90780601f2e6bc389674131e8 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -137,8 +137,6 @@ extern struct ctl_table ether_table[]; extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); #define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" -#define MAC_BUF_SIZE 18 -#define DECLARE_MAC_BUF(var) char var[MAC_BUF_SIZE] #endif diff --git a/include/linux/isicom.h b/include/linux/isicom.h index bbd42197298f14b95f78ffcc24d6d2db508de56f..b92e0565063939ede488f0764011614999e0c148 100644 --- a/include/linux/isicom.h +++ b/include/linux/isicom.h @@ -67,6 +67,7 @@ #define FIRMWARE_LOADED 0x0001 #define BOARD_ACTIVE 0x0002 +#define BOARD_INIT 0x0004 /* isi_port status bitmap */ diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 2d241da07236fd10b8e3ad5b8e8df415a95bb9ef..a24de0b1858e9ad6080a353c4594cb5c3804703d 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -496,6 +496,7 @@ struct kvm_ioeventfd { #define KVM_CAP_VCPU_EVENTS 41 #endif #define KVM_CAP_S390_PSW 42 +#define KVM_CAP_PPC_SEGSTATE 43 #ifdef KVM_CAP_IRQ_ROUTING diff --git a/include/linux/mfd/88pm8607.h b/include/linux/mfd/88pm8607.h new file mode 100644 index 0000000000000000000000000000000000000000..f41b428d2cec5afcedbdfaee8a9eeb17edf95dd6 --- /dev/null +++ b/include/linux/mfd/88pm8607.h @@ -0,0 +1,217 @@ +/* + * Marvell 88PM8607 Interface + * + * Copyright (C) 2009 Marvell International Ltd. + * Haojian Zhuang + * + * 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. + */ + +#ifndef __LINUX_MFD_88PM8607_H +#define __LINUX_MFD_88PM8607_H + +enum { + PM8607_ID_BUCK1 = 0, + PM8607_ID_BUCK2, + PM8607_ID_BUCK3, + + PM8607_ID_LDO1, + PM8607_ID_LDO2, + PM8607_ID_LDO3, + PM8607_ID_LDO4, + PM8607_ID_LDO5, + PM8607_ID_LDO6, + PM8607_ID_LDO7, + PM8607_ID_LDO8, + PM8607_ID_LDO9, + PM8607_ID_LDO10, + PM8607_ID_LDO12, + PM8607_ID_LDO14, + + PM8607_ID_RG_MAX, +}; + +#define CHIP_ID (0x40) +#define CHIP_ID_MASK (0xF8) + +/* Interrupt Registers */ +#define PM8607_STATUS_1 (0x01) +#define PM8607_STATUS_2 (0x02) +#define PM8607_INT_STATUS1 (0x03) +#define PM8607_INT_STATUS2 (0x04) +#define PM8607_INT_STATUS3 (0x05) +#define PM8607_INT_MASK_1 (0x06) +#define PM8607_INT_MASK_2 (0x07) +#define PM8607_INT_MASK_3 (0x08) + +/* Regulator Control Registers */ +#define PM8607_LDO1 (0x10) +#define PM8607_LDO2 (0x11) +#define PM8607_LDO3 (0x12) +#define PM8607_LDO4 (0x13) +#define PM8607_LDO5 (0x14) +#define PM8607_LDO6 (0x15) +#define PM8607_LDO7 (0x16) +#define PM8607_LDO8 (0x17) +#define PM8607_LDO9 (0x18) +#define PM8607_LDO10 (0x19) +#define PM8607_LDO12 (0x1A) +#define PM8607_LDO14 (0x1B) +#define PM8607_SLEEP_MODE1 (0x1C) +#define PM8607_SLEEP_MODE2 (0x1D) +#define PM8607_SLEEP_MODE3 (0x1E) +#define PM8607_SLEEP_MODE4 (0x1F) +#define PM8607_GO (0x20) +#define PM8607_SLEEP_BUCK1 (0x21) +#define PM8607_SLEEP_BUCK2 (0x22) +#define PM8607_SLEEP_BUCK3 (0x23) +#define PM8607_BUCK1 (0x24) +#define PM8607_BUCK2 (0x25) +#define PM8607_BUCK3 (0x26) +#define PM8607_BUCK_CONTROLS (0x27) +#define PM8607_SUPPLIES_EN11 (0x2B) +#define PM8607_SUPPLIES_EN12 (0x2C) +#define PM8607_GROUP1 (0x2D) +#define PM8607_GROUP2 (0x2E) +#define PM8607_GROUP3 (0x2F) +#define PM8607_GROUP4 (0x30) +#define PM8607_GROUP5 (0x31) +#define PM8607_GROUP6 (0x32) +#define PM8607_SUPPLIES_EN21 (0x33) +#define PM8607_SUPPLIES_EN22 (0x34) + +/* RTC Control Registers */ +#define PM8607_RTC1 (0xA0) +#define PM8607_RTC_COUNTER1 (0xA1) +#define PM8607_RTC_COUNTER2 (0xA2) +#define PM8607_RTC_COUNTER3 (0xA3) +#define PM8607_RTC_COUNTER4 (0xA4) +#define PM8607_RTC_EXPIRE1 (0xA5) +#define PM8607_RTC_EXPIRE2 (0xA6) +#define PM8607_RTC_EXPIRE3 (0xA7) +#define PM8607_RTC_EXPIRE4 (0xA8) +#define PM8607_RTC_TRIM1 (0xA9) +#define PM8607_RTC_TRIM2 (0xAA) +#define PM8607_RTC_TRIM3 (0xAB) +#define PM8607_RTC_TRIM4 (0xAC) +#define PM8607_RTC_MISC1 (0xAD) +#define PM8607_RTC_MISC2 (0xAE) +#define PM8607_RTC_MISC3 (0xAF) + +/* Misc Registers */ +#define PM8607_CHIP_ID (0x00) +#define PM8607_LDO1 (0x10) +#define PM8607_DVC3 (0x26) +#define PM8607_MISC1 (0x40) + +/* bit definitions for PM8607 events */ +#define PM8607_EVENT_ONKEY (1 << 0) +#define PM8607_EVENT_EXTON (1 << 1) +#define PM8607_EVENT_CHG (1 << 2) +#define PM8607_EVENT_BAT (1 << 3) +#define PM8607_EVENT_RTC (1 << 4) +#define PM8607_EVENT_CC (1 << 5) +#define PM8607_EVENT_VBAT (1 << 8) +#define PM8607_EVENT_VCHG (1 << 9) +#define PM8607_EVENT_VSYS (1 << 10) +#define PM8607_EVENT_TINT (1 << 11) +#define PM8607_EVENT_GPADC0 (1 << 12) +#define PM8607_EVENT_GPADC1 (1 << 13) +#define PM8607_EVENT_GPADC2 (1 << 14) +#define PM8607_EVENT_GPADC3 (1 << 15) +#define PM8607_EVENT_AUDIO_SHORT (1 << 16) +#define PM8607_EVENT_PEN (1 << 17) +#define PM8607_EVENT_HEADSET (1 << 18) +#define PM8607_EVENT_HOOK (1 << 19) +#define PM8607_EVENT_MICIN (1 << 20) +#define PM8607_EVENT_CHG_TIMEOUT (1 << 21) +#define PM8607_EVENT_CHG_DONE (1 << 22) +#define PM8607_EVENT_CHG_FAULT (1 << 23) + +/* bit definitions of Status Query Interface */ +#define PM8607_STATUS_CC (1 << 3) +#define PM8607_STATUS_PEN (1 << 4) +#define PM8607_STATUS_HEADSET (1 << 5) +#define PM8607_STATUS_HOOK (1 << 6) +#define PM8607_STATUS_MICIN (1 << 7) +#define PM8607_STATUS_ONKEY (1 << 8) +#define PM8607_STATUS_EXTON (1 << 9) +#define PM8607_STATUS_CHG (1 << 10) +#define PM8607_STATUS_BAT (1 << 11) +#define PM8607_STATUS_VBUS (1 << 12) +#define PM8607_STATUS_OV (1 << 13) + +/* bit definitions of BUCK3 */ +#define PM8607_BUCK3_DOUBLE (1 << 6) + +/* bit definitions of Misc1 */ +#define PM8607_MISC1_PI2C (1 << 0) + +/* Interrupt Number in 88PM8607 */ +enum { + PM8607_IRQ_ONKEY = 0, + PM8607_IRQ_EXTON, + PM8607_IRQ_CHG, + PM8607_IRQ_BAT, + PM8607_IRQ_RTC, + PM8607_IRQ_VBAT = 8, + PM8607_IRQ_VCHG, + PM8607_IRQ_VSYS, + PM8607_IRQ_TINT, + PM8607_IRQ_GPADC0, + PM8607_IRQ_GPADC1, + PM8607_IRQ_GPADC2, + PM8607_IRQ_GPADC3, + PM8607_IRQ_AUDIO_SHORT = 16, + PM8607_IRQ_PEN, + PM8607_IRQ_HEADSET, + PM8607_IRQ_HOOK, + PM8607_IRQ_MICIN, + PM8607_IRQ_CHG_FAIL, + PM8607_IRQ_CHG_DONE, + PM8607_IRQ_CHG_FAULT, +}; + +enum { + PM8607_CHIP_A0 = 0x40, + PM8607_CHIP_A1 = 0x41, + PM8607_CHIP_B0 = 0x48, +}; + + +struct pm8607_chip { + struct device *dev; + struct mutex io_lock; + struct i2c_client *client; + + int (*read)(struct pm8607_chip *chip, int reg, int bytes, void *dest); + int (*write)(struct pm8607_chip *chip, int reg, int bytes, void *src); + + int buck3_double; /* DVC ramp slope double */ + unsigned char chip_id; + +}; + +#define PM8607_MAX_REGULATOR 15 /* 3 Bucks, 12 LDOs */ + +enum { + GI2C_PORT = 0, + PI2C_PORT, +}; + +struct pm8607_platform_data { + int i2c_port; /* Controlled by GI2C or PI2C */ + struct regulator_init_data *regulator[PM8607_MAX_REGULATOR]; +}; + +extern int pm8607_reg_read(struct pm8607_chip *, int); +extern int pm8607_reg_write(struct pm8607_chip *, int, unsigned char); +extern int pm8607_bulk_read(struct pm8607_chip *, int, int, + unsigned char *); +extern int pm8607_bulk_write(struct pm8607_chip *, int, int, + unsigned char *); +extern int pm8607_set_bits(struct pm8607_chip *, int, unsigned char, + unsigned char); +#endif /* __LINUX_MFD_88PM8607_H */ diff --git a/include/linux/mfd/ab4500.h b/include/linux/mfd/ab4500.h new file mode 100644 index 0000000000000000000000000000000000000000..a42a7033ae539d5362b87c2c904da3cedc7b4d72 --- /dev/null +++ b/include/linux/mfd/ab4500.h @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2009 ST-Ericsson + * + * Author: Srinidhi KASAGAR + * + * 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. + * + * AB4500 device core funtions, for client access + */ +#ifndef MFD_AB4500_H +#define MFD_AB4500_H + +#include + +/* + * AB4500 bank addresses + */ +#define AB4500_SYS_CTRL1_BLOCK 0x1 +#define AB4500_SYS_CTRL2_BLOCK 0x2 +#define AB4500_REGU_CTRL1 0x3 +#define AB4500_REGU_CTRL2 0x4 +#define AB4500_USB 0x5 +#define AB4500_TVOUT 0x6 +#define AB4500_DBI 0x7 +#define AB4500_ECI_AV_ACC 0x8 +#define AB4500_RESERVED 0x9 +#define AB4500_GPADC 0xA +#define AB4500_CHARGER 0xB +#define AB4500_GAS_GAUGE 0xC +#define AB4500_AUDIO 0xD +#define AB4500_INTERRUPT 0xE +#define AB4500_RTC 0xF +#define AB4500_MISC 0x10 +#define AB4500_DEBUG 0x12 +#define AB4500_PROD_TEST 0x13 +#define AB4500_OTP_EMUL 0x15 + +/* + * System control 1 register offsets. + * Bank = 0x01 + */ +#define AB4500_TURNON_STAT_REG 0x0100 +#define AB4500_RESET_STAT_REG 0x0101 +#define AB4500_PONKEY1_PRESS_STAT_REG 0x0102 + +#define AB4500_FSM_STAT1_REG 0x0140 +#define AB4500_FSM_STAT2_REG 0x0141 +#define AB4500_SYSCLK_REQ_STAT_REG 0x0142 +#define AB4500_USB_STAT1_REG 0x0143 +#define AB4500_USB_STAT2_REG 0x0144 +#define AB4500_STATUS_SPARE1_REG 0x0145 +#define AB4500_STATUS_SPARE2_REG 0x0146 + +#define AB4500_CTRL1_REG 0x0180 +#define AB4500_CTRL2_REG 0x0181 + +/* + * System control 2 register offsets. + * bank = 0x02 + */ +#define AB4500_CTRL3_REG 0x0200 +#define AB4500_MAIN_WDOG_CTRL_REG 0x0201 +#define AB4500_MAIN_WDOG_TIMER_REG 0x0202 +#define AB4500_LOW_BAT_REG 0x0203 +#define AB4500_BATT_OK_REG 0x0204 +#define AB4500_SYSCLK_TIMER_REG 0x0205 +#define AB4500_SMPSCLK_CTRL_REG 0x0206 +#define AB4500_SMPSCLK_SEL1_REG 0x0207 +#define AB4500_SMPSCLK_SEL2_REG 0x0208 +#define AB4500_SMPSCLK_SEL3_REG 0x0209 +#define AB4500_SYSULPCLK_CONF_REG 0x020A +#define AB4500_SYSULPCLK_CTRL1_REG 0x020B +#define AB4500_SYSCLK_CTRL_REG 0x020C +#define AB4500_SYSCLK_REQ1_VALID_REG 0x020D +#define AB4500_SYSCLK_REQ_VALID_REG 0x020E +#define AB4500_SYSCTRL_SPARE_REG 0x020F +#define AB4500_PAD_CONF_REG 0x0210 + +/* + * Regu control1 register offsets + * Bank = 0x03 + */ +#define AB4500_REGU_SERIAL_CTRL1_REG 0x0300 +#define AB4500_REGU_SERIAL_CTRL2_REG 0x0301 +#define AB4500_REGU_SERIAL_CTRL3_REG 0x0302 +#define AB4500_REGU_REQ_CTRL1_REG 0x0303 +#define AB4500_REGU_REQ_CTRL2_REG 0x0304 +#define AB4500_REGU_REQ_CTRL3_REG 0x0305 +#define AB4500_REGU_REQ_CTRL4_REG 0x0306 +#define AB4500_REGU_MISC1_REG 0x0380 +#define AB4500_REGU_OTGSUPPLY_CTRL_REG 0x0381 +#define AB4500_REGU_VUSB_CTRL_REG 0x0382 +#define AB4500_REGU_VAUDIO_SUPPLY_REG 0x0383 +#define AB4500_REGU_CTRL1_SPARE_REG 0x0384 + +/* + * Regu control2 Vmod register offsets + */ +#define AB4500_REGU_VMOD_REGU_REG 0x0440 +#define AB4500_REGU_VMOD_SEL1_REG 0x0441 +#define AB4500_REGU_VMOD_SEL2_REG 0x0442 +#define AB4500_REGU_CTRL_DISCH_REG 0x0443 +#define AB4500_REGU_CTRL_DISCH2_REG 0x0444 + +/* + * USB/ULPI register offsets + * Bank : 0x5 + */ +#define AB4500_USB_LINE_STAT_REG 0x0580 +#define AB4500_USB_LINE_CTRL1_REG 0x0581 +#define AB4500_USB_LINE_CTRL2_REG 0x0582 +#define AB4500_USB_LINE_CTRL3_REG 0x0583 +#define AB4500_USB_LINE_CTRL4_REG 0x0584 +#define AB4500_USB_LINE_CTRL5_REG 0x0585 +#define AB4500_USB_OTG_CTRL_REG 0x0587 +#define AB4500_USB_OTG_STAT_REG 0x0588 +#define AB4500_USB_OTG_STAT_REG 0x0588 +#define AB4500_USB_CTRL_SPARE_REG 0x0589 +#define AB4500_USB_PHY_CTRL_REG 0x058A + +/* + * TVOUT / CTRL register offsets + * Bank : 0x06 + */ +#define AB4500_TVOUT_CTRL_REG 0x0680 + +/* + * DBI register offsets + * Bank : 0x07 + */ +#define AB4500_DBI_REG1_REG 0x0700 +#define AB4500_DBI_REG2_REG 0x0701 + +/* + * ECI regsiter offsets + * Bank : 0x08 + */ +#define AB4500_ECI_CTRL_REG 0x0800 +#define AB4500_ECI_HOOKLEVEL_REG 0x0801 +#define AB4500_ECI_DATAOUT_REG 0x0802 +#define AB4500_ECI_DATAIN_REG 0x0803 + +/* + * AV Connector register offsets + * Bank : 0x08 + */ +#define AB4500_AV_CONN_REG 0x0840 + +/* + * Accessory detection register offsets + * Bank : 0x08 + */ +#define AB4500_ACC_DET_DB1_REG 0x0880 +#define AB4500_ACC_DET_DB2_REG 0x0881 + +/* + * GPADC register offsets + * Bank : 0x0A + */ +#define AB4500_GPADC_CTRL1_REG 0x0A00 +#define AB4500_GPADC_CTRL2_REG 0x0A01 +#define AB4500_GPADC_CTRL3_REG 0x0A02 +#define AB4500_GPADC_AUTO_TIMER_REG 0x0A03 +#define AB4500_GPADC_STAT_REG 0x0A04 +#define AB4500_GPADC_MANDATAL_REG 0x0A05 +#define AB4500_GPADC_MANDATAH_REG 0x0A06 +#define AB4500_GPADC_AUTODATAL_REG 0x0A07 +#define AB4500_GPADC_AUTODATAH_REG 0x0A08 +#define AB4500_GPADC_MUX_CTRL_REG 0x0A09 + +/* + * Charger / status register offfsets + * Bank : 0x0B + */ +#define AB4500_CH_STATUS1_REG 0x0B00 +#define AB4500_CH_STATUS2_REG 0x0B01 +#define AB4500_CH_USBCH_STAT1_REG 0x0B02 +#define AB4500_CH_USBCH_STAT2_REG 0x0B03 +#define AB4500_CH_FSM_STAT_REG 0x0B04 +#define AB4500_CH_STAT_REG 0x0B05 + +/* + * Charger / control register offfsets + * Bank : 0x0B + */ +#define AB4500_CH_VOLT_LVL_REG 0x0B40 + +/* + * Charger / main control register offfsets + * Bank : 0x0B + */ +#define AB4500_MCH_CTRL1 0x0B80 +#define AB4500_MCH_CTRL2 0x0B81 +#define AB4500_MCH_IPT_CURLVL_REG 0x0B82 +#define AB4500_CH_WD_REG 0x0B83 + +/* + * Charger / USB control register offsets + * Bank : 0x0B + */ +#define AB4500_USBCH_CTRL1_REG 0x0BC0 +#define AB4500_USBCH_CTRL2_REG 0x0BC1 +#define AB4500_USBCH_IPT_CRNTLVL_REG 0x0BC2 + +/* + * RTC bank register offsets + * Bank : 0xF + */ +#define AB4500_RTC_SOFF_STAT_REG 0x0F00 +#define AB4500_RTC_CC_CONF_REG 0x0F01 +#define AB4500_RTC_READ_REQ_REG 0x0F02 +#define AB4500_RTC_WATCH_TSECMID_REG 0x0F03 +#define AB4500_RTC_WATCH_TSECHI_REG 0x0F04 +#define AB4500_RTC_WATCH_TMIN_LOW_REG 0x0F05 +#define AB4500_RTC_WATCH_TMIN_MID_REG 0x0F06 +#define AB4500_RTC_WATCH_TMIN_HI_REG 0x0F07 +#define AB4500_RTC_ALRM_MIN_LOW_REG 0x0F08 +#define AB4500_RTC_ALRM_MIN_MID_REG 0x0F09 +#define AB4500_RTC_ALRM_MIN_HI_REG 0x0F0A +#define AB4500_RTC_STAT_REG 0x0F0B +#define AB4500_RTC_BKUP_CHG_REG 0x0F0C +#define AB4500_RTC_FORCE_BKUP_REG 0x0F0D +#define AB4500_RTC_CALIB_REG 0x0F0E +#define AB4500_RTC_SWITCH_STAT_REG 0x0F0F + +/* + * PWM Out generators + * Bank: 0x10 + */ +#define AB4500_PWM_OUT_CTRL1_REG 0x1060 +#define AB4500_PWM_OUT_CTRL2_REG 0x1061 +#define AB4500_PWM_OUT_CTRL3_REG 0x1062 +#define AB4500_PWM_OUT_CTRL4_REG 0x1063 +#define AB4500_PWM_OUT_CTRL5_REG 0x1064 +#define AB4500_PWM_OUT_CTRL6_REG 0x1065 +#define AB4500_PWM_OUT_CTRL7_REG 0x1066 + +#define AB4500_I2C_PAD_CTRL_REG 0x1067 +#define AB4500_REV_REG 0x1080 + +/** + * struct ab4500 + * @spi: spi device structure + * @tx_buf: transmit buffer + * @rx_buf: receive buffer + * @lock: sync primitive + */ +struct ab4500 { + struct spi_device *spi; + unsigned long tx_buf[4]; + unsigned long rx_buf[4]; + struct mutex lock; +}; + +int ab4500_write(struct ab4500 *ab4500, unsigned char block, + unsigned long addr, unsigned char data); +int ab4500_read(struct ab4500 *ab4500, unsigned char block, + unsigned long addr); + +#endif /* MFD_AB4500_H */ diff --git a/include/linux/mfd/adp5520.h b/include/linux/mfd/adp5520.h new file mode 100644 index 0000000000000000000000000000000000000000..ac37558a4673367d52407148c58a04b15e1b6ca1 --- /dev/null +++ b/include/linux/mfd/adp5520.h @@ -0,0 +1,299 @@ +/* + * Definitions and platform data for Analog Devices + * ADP5520/ADP5501 MFD PMICs (Backlight, LED, GPIO and Keys) + * + * Copyright 2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + + +#ifndef __LINUX_MFD_ADP5520_H +#define __LINUX_MFD_ADP5520_H + +#define ID_ADP5520 5520 +#define ID_ADP5501 5501 + +/* + * ADP5520/ADP5501 Register Map + */ + +#define ADP5520_MODE_STATUS 0x00 +#define ADP5520_INTERRUPT_ENABLE 0x01 +#define ADP5520_BL_CONTROL 0x02 +#define ADP5520_BL_TIME 0x03 +#define ADP5520_BL_FADE 0x04 +#define ADP5520_DAYLIGHT_MAX 0x05 +#define ADP5520_DAYLIGHT_DIM 0x06 +#define ADP5520_OFFICE_MAX 0x07 +#define ADP5520_OFFICE_DIM 0x08 +#define ADP5520_DARK_MAX 0x09 +#define ADP5520_DARK_DIM 0x0A +#define ADP5520_BL_VALUE 0x0B +#define ADP5520_ALS_CMPR_CFG 0x0C +#define ADP5520_L2_TRIP 0x0D +#define ADP5520_L2_HYS 0x0E +#define ADP5520_L3_TRIP 0x0F +#define ADP5520_L3_HYS 0x10 +#define ADP5520_LED_CONTROL 0x11 +#define ADP5520_LED_TIME 0x12 +#define ADP5520_LED_FADE 0x13 +#define ADP5520_LED1_CURRENT 0x14 +#define ADP5520_LED2_CURRENT 0x15 +#define ADP5520_LED3_CURRENT 0x16 + +/* + * ADP5520 Register Map + */ + +#define ADP5520_GPIO_CFG_1 0x17 +#define ADP5520_GPIO_CFG_2 0x18 +#define ADP5520_GPIO_IN 0x19 +#define ADP5520_GPIO_OUT 0x1A +#define ADP5520_GPIO_INT_EN 0x1B +#define ADP5520_GPIO_INT_STAT 0x1C +#define ADP5520_GPIO_INT_LVL 0x1D +#define ADP5520_GPIO_DEBOUNCE 0x1E +#define ADP5520_GPIO_PULLUP 0x1F +#define ADP5520_KP_INT_STAT_1 0x20 +#define ADP5520_KP_INT_STAT_2 0x21 +#define ADP5520_KR_INT_STAT_1 0x22 +#define ADP5520_KR_INT_STAT_2 0x23 +#define ADP5520_KEY_STAT_1 0x24 +#define ADP5520_KEY_STAT_2 0x25 + +/* + * MODE_STATUS bits + */ + +#define ADP5520_nSTNBY (1 << 7) +#define ADP5520_BL_EN (1 << 6) +#define ADP5520_DIM_EN (1 << 5) +#define ADP5520_OVP_INT (1 << 4) +#define ADP5520_CMPR_INT (1 << 3) +#define ADP5520_GPI_INT (1 << 2) +#define ADP5520_KR_INT (1 << 1) +#define ADP5520_KP_INT (1 << 0) + +/* + * INTERRUPT_ENABLE bits + */ + +#define ADP5520_AUTO_LD_EN (1 << 4) +#define ADP5520_CMPR_IEN (1 << 3) +#define ADP5520_OVP_IEN (1 << 2) +#define ADP5520_KR_IEN (1 << 1) +#define ADP5520_KP_IEN (1 << 0) + +/* + * BL_CONTROL bits + */ + +#define ADP5520_BL_LVL ((x) << 5) +#define ADP5520_BL_LAW ((x) << 4) +#define ADP5520_BL_AUTO_ADJ (1 << 3) +#define ADP5520_OVP_EN (1 << 2) +#define ADP5520_FOVR (1 << 1) +#define ADP5520_KP_BL_EN (1 << 0) + +/* + * ALS_CMPR_CFG bits + */ + +#define ADP5520_L3_OUT (1 << 3) +#define ADP5520_L2_OUT (1 << 2) +#define ADP5520_L3_EN (1 << 1) + +#define ADP5020_MAX_BRIGHTNESS 0x7F + +#define FADE_VAL(in, out) ((0xF & (in)) | ((0xF & (out)) << 4)) +#define BL_CTRL_VAL(law, auto) (((1 & (auto)) << 3) | ((0x3 & (law)) << 4)) +#define ALS_CMPR_CFG_VAL(filt, l3_en) (((0x7 & filt) << 5) | l3_en) + +/* + * LEDs subdevice bits and masks + */ + +#define ADP5520_01_MAXLEDS 3 + +#define ADP5520_FLAG_LED_MASK 0x3 +#define ADP5520_FLAG_OFFT_SHIFT 8 +#define ADP5520_FLAG_OFFT_MASK 0x3 + +#define ADP5520_R3_MODE (1 << 5) +#define ADP5520_C3_MODE (1 << 4) +#define ADP5520_LED_LAW (1 << 3) +#define ADP5520_LED3_EN (1 << 2) +#define ADP5520_LED2_EN (1 << 1) +#define ADP5520_LED1_EN (1 << 0) + +/* + * GPIO subdevice bits and masks + */ + +#define ADP5520_MAXGPIOS 8 + +#define ADP5520_GPIO_C3 (1 << 7) /* LED2 or GPIO7 aka C3 */ +#define ADP5520_GPIO_C2 (1 << 6) +#define ADP5520_GPIO_C1 (1 << 5) +#define ADP5520_GPIO_C0 (1 << 4) +#define ADP5520_GPIO_R3 (1 << 3) /* LED3 or GPIO3 aka R3 */ +#define ADP5520_GPIO_R2 (1 << 2) +#define ADP5520_GPIO_R1 (1 << 1) +#define ADP5520_GPIO_R0 (1 << 0) + +struct adp5520_gpio_platform_data { + unsigned gpio_start; + u8 gpio_en_mask; + u8 gpio_pullup_mask; +}; + +/* + * Keypad subdevice bits and masks + */ + +#define ADP5520_MAXKEYS 16 + +#define ADP5520_COL_C3 (1 << 7) /* LED2 or GPIO7 aka C3 */ +#define ADP5520_COL_C2 (1 << 6) +#define ADP5520_COL_C1 (1 << 5) +#define ADP5520_COL_C0 (1 << 4) +#define ADP5520_ROW_R3 (1 << 3) /* LED3 or GPIO3 aka R3 */ +#define ADP5520_ROW_R2 (1 << 2) +#define ADP5520_ROW_R1 (1 << 1) +#define ADP5520_ROW_R0 (1 << 0) + +#define ADP5520_KEY(row, col) (col + row * 4) +#define ADP5520_KEYMAPSIZE ADP5520_MAXKEYS + +struct adp5520_keys_platform_data { + int rows_en_mask; /* Number of rows */ + int cols_en_mask; /* Number of columns */ + const unsigned short *keymap; /* Pointer to keymap */ + unsigned short keymapsize; /* Keymap size */ + unsigned repeat:1; /* Enable key repeat */ +}; + + +/* + * LEDs subdevice platform data + */ + +#define FLAG_ID_ADP5520_LED1_ADP5501_LED0 1 /* ADP5520 PIN ILED */ +#define FLAG_ID_ADP5520_LED2_ADP5501_LED1 2 /* ADP5520 PIN C3 */ +#define FLAG_ID_ADP5520_LED3_ADP5501_LED2 3 /* ADP5520 PIN R3 */ + +#define ADP5520_LED_DIS_BLINK (0 << ADP5520_FLAG_OFFT_SHIFT) +#define ADP5520_LED_OFFT_600ms (1 << ADP5520_FLAG_OFFT_SHIFT) +#define ADP5520_LED_OFFT_800ms (2 << ADP5520_FLAG_OFFT_SHIFT) +#define ADP5520_LED_OFFT_1200ms (3 << ADP5520_FLAG_OFFT_SHIFT) + +#define ADP5520_LED_ONT_200ms 0 +#define ADP5520_LED_ONT_600ms 1 +#define ADP5520_LED_ONT_800ms 2 +#define ADP5520_LED_ONT_1200ms 3 + +struct adp5520_leds_platform_data { + int num_leds; + struct led_info *leds; + u8 fade_in; /* Backlight Fade-In Timer */ + u8 fade_out; /* Backlight Fade-Out Timer */ + u8 led_on_time; +}; + +/* + * Backlight subdevice platform data + */ + +#define ADP5520_FADE_T_DIS 0 /* Fade Timer Disabled */ +#define ADP5520_FADE_T_300ms 1 /* 0.3 Sec */ +#define ADP5520_FADE_T_600ms 2 +#define ADP5520_FADE_T_900ms 3 +#define ADP5520_FADE_T_1200ms 4 +#define ADP5520_FADE_T_1500ms 5 +#define ADP5520_FADE_T_1800ms 6 +#define ADP5520_FADE_T_2100ms 7 +#define ADP5520_FADE_T_2400ms 8 +#define ADP5520_FADE_T_2700ms 9 +#define ADP5520_FADE_T_3000ms 10 +#define ADP5520_FADE_T_3500ms 11 +#define ADP5520_FADE_T_4000ms 12 +#define ADP5520_FADE_T_4500ms 13 +#define ADP5520_FADE_T_5000ms 14 +#define ADP5520_FADE_T_5500ms 15 /* 5.5 Sec */ + +#define ADP5520_BL_LAW_LINEAR 0 +#define ADP5520_BL_LAW_SQUARE 1 +#define ADP5520_BL_LAW_CUBIC1 2 +#define ADP5520_BL_LAW_CUBIC2 3 + +#define ADP5520_BL_AMBL_FILT_80ms 0 /* Light sensor filter time */ +#define ADP5520_BL_AMBL_FILT_160ms 1 +#define ADP5520_BL_AMBL_FILT_320ms 2 +#define ADP5520_BL_AMBL_FILT_640ms 3 +#define ADP5520_BL_AMBL_FILT_1280ms 4 +#define ADP5520_BL_AMBL_FILT_2560ms 5 +#define ADP5520_BL_AMBL_FILT_5120ms 6 +#define ADP5520_BL_AMBL_FILT_10240ms 7 /* 10.24 sec */ + + /* + * Blacklight current 0..30mA + */ +#define ADP5520_BL_CUR_mA(I) ((I * 127) / 30) + + /* + * L2 comparator current 0..1000uA + */ +#define ADP5520_L2_COMP_CURR_uA(I) ((I * 255) / 1000) + + /* + * L3 comparator current 0..127uA + */ +#define ADP5520_L3_COMP_CURR_uA(I) ((I * 255) / 127) + +struct adp5520_backlight_platform_data { + u8 fade_in; /* Backlight Fade-In Timer */ + u8 fade_out; /* Backlight Fade-Out Timer */ + u8 fade_led_law; /* fade-on/fade-off transfer characteristic */ + + u8 en_ambl_sens; /* 1 = enable ambient light sensor */ + u8 abml_filt; /* Light sensor filter time */ + u8 l1_daylight_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l1_daylight_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l2_office_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l2_office_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l3_dark_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l3_dark_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l2_trip; /* use L2_COMP_CURR_uA(I) 0 <= I <= 1000 uA */ + u8 l2_hyst; /* use L2_COMP_CURR_uA(I) 0 <= I <= 1000 uA */ + u8 l3_trip; /* use L3_COMP_CURR_uA(I) 0 <= I <= 127 uA */ + u8 l3_hyst; /* use L3_COMP_CURR_uA(I) 0 <= I <= 127 uA */ +}; + +/* + * MFD chip platform data + */ + +struct adp5520_platform_data { + struct adp5520_keys_platform_data *keys; + struct adp5520_gpio_platform_data *gpio; + struct adp5520_leds_platform_data *leds; + struct adp5520_backlight_platform_data *backlight; +}; + +/* + * MFD chip functions + */ + +extern int adp5520_read(struct device *dev, int reg, uint8_t *val); +extern int adp5520_write(struct device *dev, int reg, u8 val); +extern int adp5520_clr_bits(struct device *dev, int reg, uint8_t bit_mask); +extern int adp5520_set_bits(struct device *dev, int reg, uint8_t bit_mask); + +extern int adp5520_register_notifier(struct device *dev, + struct notifier_block *nb, unsigned int events); + +extern int adp5520_unregister_notifier(struct device *dev, + struct notifier_block *nb, unsigned int events); + +#endif /* __LINUX_MFD_ADP5520_H */ diff --git a/include/linux/mfd/ezx-pcap.h b/include/linux/mfd/ezx-pcap.h index 3402042ddc31856e6ca4a7e05991c868ddf2633c..40c372165f3edc0413a709c57c4e728bd0198ca5 100644 --- a/include/linux/mfd/ezx-pcap.h +++ b/include/linux/mfd/ezx-pcap.h @@ -231,9 +231,6 @@ void pcap_set_ts_bits(struct pcap_chip *, u32); #define PCAP_LED_4MA 1 #define PCAP_LED_5MA 2 #define PCAP_LED_9MA 3 -#define PCAP_LED_GPIO_VAL_MASK 0x00ffffff -#define PCAP_LED_GPIO_EN 0x01000000 -#define PCAP_LED_GPIO_INVERT 0x02000000 #define PCAP_LED_T_MASK 0xf #define PCAP_LED_C_MASK 0x3 #define PCAP_BL_MASK 0x1f diff --git a/include/linux/mfd/mc13783-private.h b/include/linux/mfd/mc13783-private.h index 47e698cb0f16264572c07a611de386686214555e..95cf9360553fb3d1a836e1ccabdcefb245c04b4a 100644 --- a/include/linux/mfd/mc13783-private.h +++ b/include/linux/mfd/mc13783-private.h @@ -24,52 +24,23 @@ #include #include -#include #include - -struct mc13783_irq { - void (*handler)(int, void *); - void *data; -}; - -#define MC13783_NUM_IRQ 2 -#define MC13783_IRQ_TS 0 -#define MC13783_IRQ_REGULATOR 1 - -#define MC13783_ADC_MODE_TS 1 -#define MC13783_ADC_MODE_SINGLE_CHAN 2 -#define MC13783_ADC_MODE_MULT_CHAN 3 +#include struct mc13783 { - int revision; - struct device *dev; - struct spi_device *spi_device; - - int (*read_dev)(void *data, char reg, int count, u32 *dst); - int (*write_dev)(void *data, char reg, int count, const u32 *src); - - struct mutex io_lock; - void *io_data; + struct spi_device *spidev; + struct mutex lock; int irq; - unsigned int flags; + int flags; - struct mc13783_irq irq_handler[MC13783_NUM_IRQ]; - struct work_struct work; - struct completion adc_done; - unsigned int ts_active; - struct mutex adc_conv_lock; + irq_handler_t irqhandler[MC13783_NUM_IRQ]; + void *irqdata[MC13783_NUM_IRQ]; + /* XXX these should go as platformdata to the regulator subdevice */ struct mc13783_regulator_init_data *regulators; int num_regulators; }; -int mc13783_reg_read(struct mc13783 *, int reg_num, u32 *); -int mc13783_reg_write(struct mc13783 *, int, u32); -int mc13783_set_bits(struct mc13783 *, int, u32, u32); -int mc13783_free_irq(struct mc13783 *mc13783, int irq); -int mc13783_register_irq(struct mc13783 *mc13783, int irq, - void (*handler) (int, void *), void *data); - #define MC13783_REG_INTERRUPT_STATUS_0 0 #define MC13783_REG_INTERRUPT_MASK_0 1 #define MC13783_REG_INTERRUPT_SENSE_0 2 @@ -136,55 +107,6 @@ int mc13783_register_irq(struct mc13783 *mc13783, int irq, #define MC13783_REG_TEST_3 63 #define MC13783_REG_NB 64 - -/* - * Interrupt Status - */ -#define MC13783_INT_STAT_ADCDONEI (1 << 0) -#define MC13783_INT_STAT_ADCBISDONEI (1 << 1) -#define MC13783_INT_STAT_TSI (1 << 2) -#define MC13783_INT_STAT_WHIGHI (1 << 3) -#define MC13783_INT_STAT_WLOWI (1 << 4) -#define MC13783_INT_STAT_CHGDETI (1 << 6) -#define MC13783_INT_STAT_CHGOVI (1 << 7) -#define MC13783_INT_STAT_CHGREVI (1 << 8) -#define MC13783_INT_STAT_CHGSHORTI (1 << 9) -#define MC13783_INT_STAT_CCCVI (1 << 10) -#define MC13783_INT_STAT_CHGCURRI (1 << 11) -#define MC13783_INT_STAT_BPONI (1 << 12) -#define MC13783_INT_STAT_LOBATLI (1 << 13) -#define MC13783_INT_STAT_LOBATHI (1 << 14) -#define MC13783_INT_STAT_UDPI (1 << 15) -#define MC13783_INT_STAT_USBI (1 << 16) -#define MC13783_INT_STAT_IDI (1 << 19) -#define MC13783_INT_STAT_Unused (1 << 20) -#define MC13783_INT_STAT_SE1I (1 << 21) -#define MC13783_INT_STAT_CKDETI (1 << 22) -#define MC13783_INT_STAT_UDMI (1 << 23) - -/* - * Interrupt Mask - */ -#define MC13783_INT_MASK_ADCDONEM (1 << 0) -#define MC13783_INT_MASK_ADCBISDONEM (1 << 1) -#define MC13783_INT_MASK_TSM (1 << 2) -#define MC13783_INT_MASK_WHIGHM (1 << 3) -#define MC13783_INT_MASK_WLOWM (1 << 4) -#define MC13783_INT_MASK_CHGDETM (1 << 6) -#define MC13783_INT_MASK_CHGOVM (1 << 7) -#define MC13783_INT_MASK_CHGREVM (1 << 8) -#define MC13783_INT_MASK_CHGSHORTM (1 << 9) -#define MC13783_INT_MASK_CCCVM (1 << 10) -#define MC13783_INT_MASK_CHGCURRM (1 << 11) -#define MC13783_INT_MASK_BPONM (1 << 12) -#define MC13783_INT_MASK_LOBATLM (1 << 13) -#define MC13783_INT_MASK_LOBATHM (1 << 14) -#define MC13783_INT_MASK_UDPM (1 << 15) -#define MC13783_INT_MASK_USBM (1 << 16) -#define MC13783_INT_MASK_IDM (1 << 19) -#define MC13783_INT_MASK_SE1M (1 << 21) -#define MC13783_INT_MASK_CKDETM (1 << 22) - /* * Reg Regulator Mode 0 */ @@ -284,113 +206,15 @@ int mc13783_register_irq(struct mc13783 *mc13783, int irq, #define MC13783_SWCTRL_SW3_STBY (1 << 21) #define MC13783_SWCTRL_SW3_MODE (1 << 22) -/* - * ADC/Touch - */ -#define MC13783_ADC0_LICELLCON (1 << 0) -#define MC13783_ADC0_CHRGICON (1 << 1) -#define MC13783_ADC0_BATICON (1 << 2) -#define MC13783_ADC0_RTHEN (1 << 3) -#define MC13783_ADC0_DTHEN (1 << 4) -#define MC13783_ADC0_UIDEN (1 << 5) -#define MC13783_ADC0_ADOUTEN (1 << 6) -#define MC13783_ADC0_ADOUTPER (1 << 7) -#define MC13783_ADC0_ADREFEN (1 << 10) -#define MC13783_ADC0_ADREFMODE (1 << 11) -#define MC13783_ADC0_TSMOD0 (1 << 12) -#define MC13783_ADC0_TSMOD1 (1 << 13) -#define MC13783_ADC0_TSMOD2 (1 << 14) -#define MC13783_ADC0_CHRGRAWDIV (1 << 15) -#define MC13783_ADC0_ADINC1 (1 << 16) -#define MC13783_ADC0_ADINC2 (1 << 17) -#define MC13783_ADC0_WCOMP (1 << 18) -#define MC13783_ADC0_ADCBIS0 (1 << 23) - -#define MC13783_ADC1_ADEN (1 << 0) -#define MC13783_ADC1_RAND (1 << 1) -#define MC13783_ADC1_ADSEL (1 << 3) -#define MC13783_ADC1_TRIGMASK (1 << 4) -#define MC13783_ADC1_ADA10 (1 << 5) -#define MC13783_ADC1_ADA11 (1 << 6) -#define MC13783_ADC1_ADA12 (1 << 7) -#define MC13783_ADC1_ADA20 (1 << 8) -#define MC13783_ADC1_ADA21 (1 << 9) -#define MC13783_ADC1_ADA22 (1 << 10) -#define MC13783_ADC1_ATO0 (1 << 11) -#define MC13783_ADC1_ATO1 (1 << 12) -#define MC13783_ADC1_ATO2 (1 << 13) -#define MC13783_ADC1_ATO3 (1 << 14) -#define MC13783_ADC1_ATO4 (1 << 15) -#define MC13783_ADC1_ATO5 (1 << 16) -#define MC13783_ADC1_ATO6 (1 << 17) -#define MC13783_ADC1_ATO7 (1 << 18) -#define MC13783_ADC1_ATOX (1 << 19) -#define MC13783_ADC1_ASC (1 << 20) -#define MC13783_ADC1_ADTRIGIGN (1 << 21) -#define MC13783_ADC1_ADONESHOT (1 << 22) -#define MC13783_ADC1_ADCBIS1 (1 << 23) - -#define MC13783_ADC1_CHAN0_SHIFT 5 -#define MC13783_ADC1_CHAN1_SHIFT 8 - -#define MC13783_ADC2_ADD10 (1 << 2) -#define MC13783_ADC2_ADD11 (1 << 3) -#define MC13783_ADC2_ADD12 (1 << 4) -#define MC13783_ADC2_ADD13 (1 << 5) -#define MC13783_ADC2_ADD14 (1 << 6) -#define MC13783_ADC2_ADD15 (1 << 7) -#define MC13783_ADC2_ADD16 (1 << 8) -#define MC13783_ADC2_ADD17 (1 << 9) -#define MC13783_ADC2_ADD18 (1 << 10) -#define MC13783_ADC2_ADD19 (1 << 11) -#define MC13783_ADC2_ADD20 (1 << 14) -#define MC13783_ADC2_ADD21 (1 << 15) -#define MC13783_ADC2_ADD22 (1 << 16) -#define MC13783_ADC2_ADD23 (1 << 17) -#define MC13783_ADC2_ADD24 (1 << 18) -#define MC13783_ADC2_ADD25 (1 << 19) -#define MC13783_ADC2_ADD26 (1 << 20) -#define MC13783_ADC2_ADD27 (1 << 21) -#define MC13783_ADC2_ADD28 (1 << 22) -#define MC13783_ADC2_ADD29 (1 << 23) +static inline int mc13783_set_bits(struct mc13783 *mc13783, unsigned int offset, + u32 mask, u32 val) +{ + int ret; + mc13783_lock(mc13783); + ret = mc13783_reg_rmw(mc13783, offset, mask, val); + mc13783_unlock(mc13783); -#define MC13783_ADC3_WHIGH0 (1 << 0) -#define MC13783_ADC3_WHIGH1 (1 << 1) -#define MC13783_ADC3_WHIGH2 (1 << 2) -#define MC13783_ADC3_WHIGH3 (1 << 3) -#define MC13783_ADC3_WHIGH4 (1 << 4) -#define MC13783_ADC3_WHIGH5 (1 << 5) -#define MC13783_ADC3_ICID0 (1 << 6) -#define MC13783_ADC3_ICID1 (1 << 7) -#define MC13783_ADC3_ICID2 (1 << 8) -#define MC13783_ADC3_WLOW0 (1 << 9) -#define MC13783_ADC3_WLOW1 (1 << 10) -#define MC13783_ADC3_WLOW2 (1 << 11) -#define MC13783_ADC3_WLOW3 (1 << 12) -#define MC13783_ADC3_WLOW4 (1 << 13) -#define MC13783_ADC3_WLOW5 (1 << 14) -#define MC13783_ADC3_ADCBIS2 (1 << 23) - -#define MC13783_ADC4_ADDBIS10 (1 << 2) -#define MC13783_ADC4_ADDBIS11 (1 << 3) -#define MC13783_ADC4_ADDBIS12 (1 << 4) -#define MC13783_ADC4_ADDBIS13 (1 << 5) -#define MC13783_ADC4_ADDBIS14 (1 << 6) -#define MC13783_ADC4_ADDBIS15 (1 << 7) -#define MC13783_ADC4_ADDBIS16 (1 << 8) -#define MC13783_ADC4_ADDBIS17 (1 << 9) -#define MC13783_ADC4_ADDBIS18 (1 << 10) -#define MC13783_ADC4_ADDBIS19 (1 << 11) -#define MC13783_ADC4_ADDBIS20 (1 << 14) -#define MC13783_ADC4_ADDBIS21 (1 << 15) -#define MC13783_ADC4_ADDBIS22 (1 << 16) -#define MC13783_ADC4_ADDBIS23 (1 << 17) -#define MC13783_ADC4_ADDBIS24 (1 << 18) -#define MC13783_ADC4_ADDBIS25 (1 << 19) -#define MC13783_ADC4_ADDBIS26 (1 << 20) -#define MC13783_ADC4_ADDBIS27 (1 << 21) -#define MC13783_ADC4_ADDBIS28 (1 << 22) -#define MC13783_ADC4_ADDBIS29 (1 << 23) + return ret; +} #endif /* __LINUX_MFD_MC13783_PRIV_H */ - diff --git a/include/linux/mfd/mc13783.h b/include/linux/mfd/mc13783.h index b3a2a7243573e2d5438688881b08c36497ca795f..35680409b8cfd3674c0a319e252fbb204ca5e1c9 100644 --- a/include/linux/mfd/mc13783.h +++ b/include/linux/mfd/mc13783.h @@ -1,28 +1,50 @@ /* - * Copyright 2009 Pengutronix, Sascha Hauer + * Copyright 2009 Pengutronix + * Uwe Kleine-Koenig * - * Initial development of this code was funded by - * Phytec Messtechnik GmbH, http://www.phytec.de - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You 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 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. */ +#ifndef __LINUX_MFD_MC13783_H +#define __LINUX_MFD_MC13783_H -#ifndef __INCLUDE_LINUX_MFD_MC13783_H -#define __INCLUDE_LINUX_MFD_MC13783_H +#include struct mc13783; + +void mc13783_lock(struct mc13783 *mc13783); +void mc13783_unlock(struct mc13783 *mc13783); + +int mc13783_reg_read(struct mc13783 *mc13783, unsigned int offset, u32 *val); +int mc13783_reg_write(struct mc13783 *mc13783, unsigned int offset, u32 val); +int mc13783_reg_rmw(struct mc13783 *mc13783, unsigned int offset, + u32 mask, u32 val); + +int mc13783_irq_request(struct mc13783 *mc13783, int irq, + irq_handler_t handler, const char *name, void *dev); +int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq, + irq_handler_t handler, const char *name, void *dev); +int mc13783_irq_free(struct mc13783 *mc13783, int irq, void *dev); +int mc13783_ackirq(struct mc13783 *mc13783, int irq); + +int mc13783_mask(struct mc13783 *mc13783, int irq); +int mc13783_unmask(struct mc13783 *mc13783, int irq); + +#define MC13783_ADC0 43 +#define MC13783_ADC0_ADREFEN (1 << 10) +#define MC13783_ADC0_ADREFMODE (1 << 11) +#define MC13783_ADC0_TSMOD0 (1 << 12) +#define MC13783_ADC0_TSMOD1 (1 << 13) +#define MC13783_ADC0_TSMOD2 (1 << 14) +#define MC13783_ADC0_ADINC1 (1 << 16) +#define MC13783_ADC0_ADINC2 (1 << 17) + +#define MC13783_ADC0_TSMOD_MASK (MC13783_ADC0_TSMOD0 | \ + MC13783_ADC0_TSMOD1 | \ + MC13783_ADC0_TSMOD2) + +/* to be cleaned up */ struct regulator_init_data; struct mc13783_regulator_init_data { @@ -30,23 +52,30 @@ struct mc13783_regulator_init_data { struct regulator_init_data *init_data; }; -struct mc13783_platform_data { - struct mc13783_regulator_init_data *regulators; +struct mc13783_regulator_platform_data { int num_regulators; - unsigned int flags; + struct mc13783_regulator_init_data *regulators; }; -/* mc13783_platform_data flags */ +struct mc13783_platform_data { + int num_regulators; + struct mc13783_regulator_init_data *regulators; + #define MC13783_USE_TOUCHSCREEN (1 << 0) #define MC13783_USE_CODEC (1 << 1) #define MC13783_USE_ADC (1 << 2) #define MC13783_USE_RTC (1 << 3) #define MC13783_USE_REGULATOR (1 << 4) + unsigned int flags; +}; + +#define MC13783_ADC_MODE_TS 1 +#define MC13783_ADC_MODE_SINGLE_CHAN 2 +#define MC13783_ADC_MODE_MULT_CHAN 3 int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, unsigned int channel, unsigned int *sample); -void mc13783_adc_set_ts_status(struct mc13783 *mc13783, unsigned int status); #define MC13783_SW_SW1A 0 #define MC13783_SW_SW1B 1 @@ -80,5 +109,46 @@ void mc13783_adc_set_ts_status(struct mc13783 *mc13783, unsigned int status); #define MC13783_REGU_V3 29 #define MC13783_REGU_V4 30 -#endif /* __INCLUDE_LINUX_MFD_MC13783_H */ +#define MC13783_IRQ_ADCDONE 0 +#define MC13783_IRQ_ADCBISDONE 1 +#define MC13783_IRQ_TS 2 +#define MC13783_IRQ_WHIGH 3 +#define MC13783_IRQ_WLOW 4 +#define MC13783_IRQ_CHGDET 6 +#define MC13783_IRQ_CHGOV 7 +#define MC13783_IRQ_CHGREV 8 +#define MC13783_IRQ_CHGSHORT 9 +#define MC13783_IRQ_CCCV 10 +#define MC13783_IRQ_CHGCURR 11 +#define MC13783_IRQ_BPON 12 +#define MC13783_IRQ_LOBATL 13 +#define MC13783_IRQ_LOBATH 14 +#define MC13783_IRQ_UDP 15 +#define MC13783_IRQ_USB 16 +#define MC13783_IRQ_ID 19 +#define MC13783_IRQ_SE1 21 +#define MC13783_IRQ_CKDET 22 +#define MC13783_IRQ_UDM 23 +#define MC13783_IRQ_1HZ 24 +#define MC13783_IRQ_TODA 25 +#define MC13783_IRQ_ONOFD1 27 +#define MC13783_IRQ_ONOFD2 28 +#define MC13783_IRQ_ONOFD3 29 +#define MC13783_IRQ_SYSRST 30 +#define MC13783_IRQ_RTCRST 31 +#define MC13783_IRQ_PC 32 +#define MC13783_IRQ_WARM 33 +#define MC13783_IRQ_MEMHLD 34 +#define MC13783_IRQ_PWRRDY 35 +#define MC13783_IRQ_THWARNL 36 +#define MC13783_IRQ_THWARNH 37 +#define MC13783_IRQ_CLK 38 +#define MC13783_IRQ_SEMAF 39 +#define MC13783_IRQ_MC2B 41 +#define MC13783_IRQ_HSDET 42 +#define MC13783_IRQ_HSL 43 +#define MC13783_IRQ_ALSPTH 44 +#define MC13783_IRQ_AHSSHORT 45 +#define MC13783_NUM_IRQ 46 +#endif /* __LINUX_MFD_MC13783_H */ diff --git a/include/linux/mfd/pcf50633/core.h b/include/linux/mfd/pcf50633/core.h index 9aba7b779fbc35ee13896e8643f97a976ee49758..d9034cc87f187b764979ecad8d27cd9ef77514b5 100644 --- a/include/linux/mfd/pcf50633/core.h +++ b/include/linux/mfd/pcf50633/core.h @@ -40,10 +40,6 @@ struct pcf50633_platform_data { u8 resumers[5]; }; -struct pcf50633_subdev_pdata { - struct pcf50633 *pcf; -}; - struct pcf50633_irq { void (*handler) (int, void *); void *data; @@ -217,5 +213,9 @@ enum pcf50633_reg_int5 { #define PCF50633_REG_LEDCTL 0x2a #define PCF50633_REG_LEDDIM 0x2b -#endif +static inline struct pcf50633 *dev_to_pcf50633(struct device *dev) +{ + return dev_get_drvdata(dev); +} +#endif diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h index 91eb493bf14cffc5a8095c729c9c274afb9fea3c..5184b79c700bdc0c7df7ba5016df71e7d2d85665 100644 --- a/include/linux/mfd/wm831x/core.h +++ b/include/linux/mfd/wm831x/core.h @@ -16,7 +16,6 @@ #define __MFD_WM831X_CORE_H__ #include -#include /* * Register values. @@ -117,6 +116,7 @@ #define WM831X_DC3_SLEEP_CONTROL 0x4063 #define WM831X_DC4_CONTROL 0x4064 #define WM831X_DC4_SLEEP_CONTROL 0x4065 +#define WM832X_DC4_SLEEP_CONTROL 0x4067 #define WM831X_EPE1_CONTROL 0x4066 #define WM831X_EPE2_CONTROL 0x4067 #define WM831X_LDO1_CONTROL 0x4068 @@ -235,6 +235,8 @@ struct regulator_dev; +#define WM831X_NUM_IRQ_REGS 5 + struct wm831x { struct mutex io_lock; @@ -248,10 +250,11 @@ struct wm831x { int irq; /* Our chip IRQ */ struct mutex irq_lock; - struct workqueue_struct *irq_wq; - struct work_struct irq_work; unsigned int irq_base; - int irq_masks[5]; + int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */ + int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */ + + int num_gpio; struct mutex auxadc_lock; @@ -278,12 +281,30 @@ int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg, int wm831x_irq_init(struct wm831x *wm831x, int irq); void wm831x_irq_exit(struct wm831x *wm831x); -int __must_check wm831x_request_irq(struct wm831x *wm831x, - unsigned int irq, irq_handler_t handler, - unsigned long flags, const char *name, - void *dev); -void wm831x_free_irq(struct wm831x *wm831x, unsigned int, void *); -void wm831x_disable_irq(struct wm831x *wm831x, int irq); -void wm831x_enable_irq(struct wm831x *wm831x, int irq); +static inline int __must_check wm831x_request_irq(struct wm831x *wm831x, + unsigned int irq, + irq_handler_t handler, + unsigned long flags, + const char *name, + void *dev) +{ + return request_threaded_irq(irq, NULL, handler, flags, name, dev); +} + +static inline void wm831x_free_irq(struct wm831x *wm831x, + unsigned int irq, void *dev) +{ + free_irq(irq, dev); +} + +static inline void wm831x_disable_irq(struct wm831x *wm831x, int irq) +{ + disable_irq(irq); +} + +static inline void wm831x_enable_irq(struct wm831x *wm831x, int irq) +{ + enable_irq(irq); +} #endif diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h index 90d820260aad579638fdfacd6d7e04a2ac12c907..415c228743d562f3e93bc2c67a49b8dfbbe58a5b 100644 --- a/include/linux/mfd/wm831x/pdata.h +++ b/include/linux/mfd/wm831x/pdata.h @@ -91,6 +91,7 @@ struct wm831x_pdata { /** Called after subdevices are set up */ int (*post_init)(struct wm831x *wm831x); + int irq_base; int gpio_base; struct wm831x_backlight_pdata *backlight; struct wm831x_backup_pdata *backup; diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h index 1d595de6a055d80962226f2b04ebe5ac8c18ceee..43868899bf4915a56779089651c9532ac1ecf2ec 100644 --- a/include/linux/mfd/wm8350/core.h +++ b/include/linux/mfd/wm8350/core.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include @@ -601,7 +601,7 @@ extern const u16 wm8352_mode3_defaults[]; struct wm8350; struct wm8350_irq { - void (*handler) (struct wm8350 *, int, void *); + irq_handler_t handler; void *data; }; @@ -646,10 +646,12 @@ struct wm8350 { * @init: Function called during driver initialisation. Should be * used by the platform to configure GPIO functions and similar. * @irq_high: Set if WM8350 IRQ is active high. + * @irq_base: Base IRQ for genirq (not currently used). */ struct wm8350_platform_data { int (*init)(struct wm8350 *wm8350); int irq_high; + int irq_base; }; @@ -676,11 +678,13 @@ int wm8350_block_write(struct wm8350 *wm8350, int reg, int size, u16 *src); * WM8350 internal interrupts */ int wm8350_register_irq(struct wm8350 *wm8350, int irq, - void (*handler) (struct wm8350 *, int, void *), - void *data); + irq_handler_t handler, unsigned long flags, + const char *name, void *data); int wm8350_free_irq(struct wm8350 *wm8350, int irq); int wm8350_mask_irq(struct wm8350 *wm8350, int irq); int wm8350_unmask_irq(struct wm8350 *wm8350, int irq); - +int wm8350_irq_init(struct wm8350 *wm8350, int irq, + struct wm8350_platform_data *pdata); +int wm8350_irq_exit(struct wm8350 *wm8350); #endif diff --git a/include/linux/mfd/wm8350/gpio.h b/include/linux/mfd/wm8350/gpio.h index ed91e8f5d298fb8ea393927be7f621e746cf83f6..71af3d6ebe9d1ba1957285d8332a364f4237c724 100644 --- a/include/linux/mfd/wm8350/gpio.h +++ b/include/linux/mfd/wm8350/gpio.h @@ -172,6 +172,24 @@ #define WM8350_GPIO_DEBOUNCE_OFF 0 #define WM8350_GPIO_DEBOUNCE_ON 1 +/* + * R30 (0x1E) - GPIO Interrupt Status + */ +#define WM8350_GP12_EINT 0x1000 +#define WM8350_GP11_EINT 0x0800 +#define WM8350_GP10_EINT 0x0400 +#define WM8350_GP9_EINT 0x0200 +#define WM8350_GP8_EINT 0x0100 +#define WM8350_GP7_EINT 0x0080 +#define WM8350_GP6_EINT 0x0040 +#define WM8350_GP5_EINT 0x0020 +#define WM8350_GP4_EINT 0x0010 +#define WM8350_GP3_EINT 0x0008 +#define WM8350_GP2_EINT 0x0004 +#define WM8350_GP1_EINT 0x0002 +#define WM8350_GP0_EINT 0x0001 + + /* * R128 (0x80) - GPIO Debounce */ diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h index 6913b71d9ab2b1654d6332fc56af8485154943ec..b31bd9e9bca3a062c391b17354dc1b828f0ea555 100644 --- a/include/linux/mtd/ubi.h +++ b/include/linux/mtd/ubi.h @@ -174,6 +174,8 @@ void ubi_get_volume_info(struct ubi_volume_desc *desc, struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode); struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name, int mode); +struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode); + int ubi_register_volume_notifier(struct notifier_block *nb, int ignore_existing); int ubi_unregister_volume_notifier(struct notifier_block *nb); diff --git a/include/linux/namei.h b/include/linux/namei.h index ec0f607b364a492237fed9dddc3c2401a340ef5d..028946750289eaa9c7764c6d5cf77ee903c8da22 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -76,7 +76,6 @@ extern struct file *nameidata_to_filp(struct nameidata *nd, int flags); extern void release_open_intent(struct nameidata *); extern struct dentry *lookup_one_len(const char *, struct dentry *, int); -extern struct dentry *lookup_one_noperm(const char *, struct dentry *); extern int follow_down(struct path *); extern int follow_up(struct path *); diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index c4c060208109b35ca6ebde436c0d6302ba93cd6a..9b8299af3741be370af6a3443dc5b73d3ba05b11 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h @@ -128,6 +128,8 @@ #define SEQ4_STATUS_RECALLABLE_STATE_REVOKED 0x00000040 #define SEQ4_STATUS_LEASE_MOVED 0x00000080 #define SEQ4_STATUS_RESTART_RECLAIM_NEEDED 0x00000100 +#define SEQ4_STATUS_CB_PATH_DOWN_SESSION 0x00000200 +#define SEQ4_STATUS_BACKCHANNEL_FAULT 0x00000400 #define NFS4_MAX_UINT64 (~(u64)0) @@ -528,6 +530,7 @@ enum { NFSPROC4_CLNT_DESTROY_SESSION, NFSPROC4_CLNT_SEQUENCE, NFSPROC4_CLNT_GET_LEASE_TIME, + NFSPROC4_CLNT_RECLAIM_COMPLETE, }; /* nfs41 types */ diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 320569eabe3bcc88dea530ac8634d59223a80409..34fc6be5bfcfd95d03534b59687564fe82071042 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -209,6 +209,7 @@ struct nfs4_session { unsigned long session_state; u32 hash_alg; u32 ssv_len; + struct completion complete; /* The fore and back channel */ struct nfs4_channel_attrs fc_attrs; diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 62f63fb0c4c8d6cd54c8c798e5d7239408d45d34..51071b335751daa2723a849a23f0595748a7878e 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -170,8 +170,9 @@ struct nfs4_sequence_args { struct nfs4_sequence_res { struct nfs4_session *sr_session; u8 sr_slotid; /* slot used to send request */ - unsigned long sr_renewal_time; int sr_status; /* sequence operation status */ + unsigned long sr_renewal_time; + u32 sr_status_flags; }; struct nfs4_get_lease_time_args { @@ -938,6 +939,16 @@ struct nfs41_create_session_args { struct nfs41_create_session_res { struct nfs_client *client; }; + +struct nfs41_reclaim_complete_args { + /* In the future extend to include curr_fh for use with migration */ + unsigned char one_fs:1; + struct nfs4_sequence_args seq_args; +}; + +struct nfs41_reclaim_complete_res { + struct nfs4_sequence_res seq_res; +}; #endif /* CONFIG_NFS_V4_1 */ struct nfs_page; diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index ce520402e840e7b46760b9655133da1cbc4f0700..3fe02cf8b65a3097785fd1543097b9cdadf3116e 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h @@ -151,6 +151,8 @@ struct nilfs_super_root { #define NILFS_MOUNT_BARRIER 0x1000 /* Use block barriers */ #define NILFS_MOUNT_STRICT_ORDER 0x2000 /* Apply strict in-order semantics also for data */ +#define NILFS_MOUNT_NORECOVERY 0x4000 /* Disable write access during + mount-time recovery */ /** @@ -402,6 +404,28 @@ struct nilfs_segment_summary { #define NILFS_SS_SYNDT 0x0008 /* includes data only updates */ #define NILFS_SS_GC 0x0010 /* segment written for cleaner operation */ +/** + * struct nilfs_btree_node - B-tree node + * @bn_flags: flags + * @bn_level: level + * @bn_nchildren: number of children + * @bn_pad: padding + */ +struct nilfs_btree_node { + __u8 bn_flags; + __u8 bn_level; + __le16 bn_nchildren; + __le32 bn_pad; +}; + +/* flags */ +#define NILFS_BTREE_NODE_ROOT 0x01 + +/* level */ +#define NILFS_BTREE_LEVEL_DATA 0 +#define NILFS_BTREE_LEVEL_NODE_MIN (NILFS_BTREE_LEVEL_DATA + 1) +#define NILFS_BTREE_LEVEL_MAX 14 + /** * struct nilfs_palloc_group_desc - block group descriptor * @pg_nfrees: number of free entries in block group diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h new file mode 100644 index 0000000000000000000000000000000000000000..f46c40ac6d45a6007e573ee6f30e2c99ee098b06 --- /dev/null +++ b/include/linux/omapfb.h @@ -0,0 +1,251 @@ +/* + * File: include/linux/omapfb.h + * + * Framebuffer driver for TI OMAP boards + * + * Copyright (C) 2004 Nokia Corporation + * Author: Imre Deak + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 __LINUX_OMAPFB_H__ +#define __LINUX_OMAPFB_H__ + +#include +#include +#include + +/* IOCTL commands. */ + +#define OMAP_IOW(num, dtype) _IOW('O', num, dtype) +#define OMAP_IOR(num, dtype) _IOR('O', num, dtype) +#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype) +#define OMAP_IO(num) _IO('O', num) + +#define OMAPFB_MIRROR OMAP_IOW(31, int) +#define OMAPFB_SYNC_GFX OMAP_IO(37) +#define OMAPFB_VSYNC OMAP_IO(38) +#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int) +#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps) +#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int) +#define OMAPFB_LCD_TEST OMAP_IOW(45, int) +#define OMAPFB_CTRL_TEST OMAP_IOW(46, int) +#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old) +#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key) +#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key) +#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info) +#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info) +#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window) +#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info) +#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info) +#define OMAPFB_WAITFORVSYNC OMAP_IO(57) +#define OMAPFB_MEMORY_READ OMAP_IOR(58, struct omapfb_memory_read) +#define OMAPFB_GET_OVERLAY_COLORMODE OMAP_IOR(59, struct omapfb_ovl_colormode) +#define OMAPFB_WAITFORGO OMAP_IO(60) +#define OMAPFB_GET_VRAM_INFO OMAP_IOR(61, struct omapfb_vram_info) +#define OMAPFB_SET_TEARSYNC OMAP_IOW(62, struct omapfb_tearsync_info) + +#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff +#define OMAPFB_CAPS_LCDC_MASK 0x00fff000 +#define OMAPFB_CAPS_PANEL_MASK 0xff000000 + +#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000 +#define OMAPFB_CAPS_TEARSYNC 0x00002000 +#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000 +#define OMAPFB_CAPS_PLANE_SCALE 0x00008000 +#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000 +#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000 +#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000 +#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000 +#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000 + +/* Values from DSP must map to lower 16-bits */ +#define OMAPFB_FORMAT_MASK 0x00ff +#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100 +#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200 +#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400 +#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800 +#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000 + +#define OMAPFB_MEMTYPE_SDRAM 0 +#define OMAPFB_MEMTYPE_SRAM 1 +#define OMAPFB_MEMTYPE_MAX 1 + +enum omapfb_color_format { + OMAPFB_COLOR_RGB565 = 0, + OMAPFB_COLOR_YUV422, + OMAPFB_COLOR_YUV420, + OMAPFB_COLOR_CLUT_8BPP, + OMAPFB_COLOR_CLUT_4BPP, + OMAPFB_COLOR_CLUT_2BPP, + OMAPFB_COLOR_CLUT_1BPP, + OMAPFB_COLOR_RGB444, + OMAPFB_COLOR_YUY422, + + OMAPFB_COLOR_ARGB16, + OMAPFB_COLOR_RGB24U, /* RGB24, 32-bit container */ + OMAPFB_COLOR_RGB24P, /* RGB24, 24-bit container */ + OMAPFB_COLOR_ARGB32, + OMAPFB_COLOR_RGBA32, + OMAPFB_COLOR_RGBX32, +}; + +struct omapfb_update_window { + __u32 x, y; + __u32 width, height; + __u32 format; + __u32 out_x, out_y; + __u32 out_width, out_height; + __u32 reserved[8]; +}; + +struct omapfb_update_window_old { + __u32 x, y; + __u32 width, height; + __u32 format; +}; + +enum omapfb_plane { + OMAPFB_PLANE_GFX = 0, + OMAPFB_PLANE_VID1, + OMAPFB_PLANE_VID2, +}; + +enum omapfb_channel_out { + OMAPFB_CHANNEL_OUT_LCD = 0, + OMAPFB_CHANNEL_OUT_DIGIT, +}; + +struct omapfb_plane_info { + __u32 pos_x; + __u32 pos_y; + __u8 enabled; + __u8 channel_out; + __u8 mirror; + __u8 reserved1; + __u32 out_width; + __u32 out_height; + __u32 reserved2[12]; +}; + +struct omapfb_mem_info { + __u32 size; + __u8 type; + __u8 reserved[3]; +}; + +struct omapfb_caps { + __u32 ctrl; + __u32 plane_color; + __u32 wnd_color; +}; + +enum omapfb_color_key_type { + OMAPFB_COLOR_KEY_DISABLED = 0, + OMAPFB_COLOR_KEY_GFX_DST, + OMAPFB_COLOR_KEY_VID_SRC, +}; + +struct omapfb_color_key { + __u8 channel_out; + __u32 background; + __u32 trans_key; + __u8 key_type; +}; + +enum omapfb_update_mode { + OMAPFB_UPDATE_DISABLED = 0, + OMAPFB_AUTO_UPDATE, + OMAPFB_MANUAL_UPDATE +}; + +struct omapfb_memory_read { + __u16 x; + __u16 y; + __u16 w; + __u16 h; + size_t buffer_size; + void __user *buffer; +}; + +struct omapfb_ovl_colormode { + __u8 overlay_idx; + __u8 mode_idx; + __u32 bits_per_pixel; + __u32 nonstd; + struct fb_bitfield red; + struct fb_bitfield green; + struct fb_bitfield blue; + struct fb_bitfield transp; +}; + +struct omapfb_vram_info { + __u32 total; + __u32 free; + __u32 largest_free_block; + __u32 reserved[5]; +}; + +struct omapfb_tearsync_info { + __u8 enabled; + __u8 reserved1[3]; + __u16 line; + __u16 reserved2; +}; + +#ifdef __KERNEL__ + +#include + +#ifdef CONFIG_ARCH_OMAP1 +#define OMAPFB_PLANE_NUM 1 +#else +#define OMAPFB_PLANE_NUM 3 +#endif + +struct omapfb_mem_region { + u32 paddr; + void __iomem *vaddr; + unsigned long size; + u8 type; /* OMAPFB_PLANE_MEM_* */ + enum omapfb_color_format format;/* OMAPFB_COLOR_* */ + unsigned format_used:1; /* Must be set when format is set. + * Needed b/c of the badly chosen 0 + * base for OMAPFB_COLOR_* values + */ + unsigned alloc:1; /* allocated by the driver */ + unsigned map:1; /* kernel mapped by the driver */ +}; + +struct omapfb_mem_desc { + int region_cnt; + struct omapfb_mem_region region[OMAPFB_PLANE_NUM]; +}; + +struct omapfb_platform_data { + struct omap_lcd_config lcd; + struct omapfb_mem_desc mem_desc; + void *ctrl_platform_data; +}; + +/* in arch/arm/plat-omap/fb.c */ +extern void omapfb_set_platform_data(struct omapfb_platform_data *data); +extern void omapfb_set_ctrl_platform_data(void *pdata); +extern void omapfb_reserve_sdram(void); + +#endif + +#endif /* __OMAPFB_H */ diff --git a/include/linux/pci.h b/include/linux/pci.h index f5c7cd343e56ae85dafe8a660a280054a53bd433..bf1e6708084909b786f19a6fdb095b1573b53df4 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -218,6 +218,7 @@ struct pci_dev { unsigned int class; /* 3 bytes: (base,sub,prog-if) */ u8 revision; /* PCI revision, low byte of class word */ u8 hdr_type; /* PCI header type (`multi' flag masked out) */ + u8 pcie_cap; /* PCI-E capability offset */ u8 pcie_type; /* PCI-E device/port type */ u8 rom_base_reg; /* which config register controls the ROM */ u8 pin; /* which interrupt pin this device uses */ @@ -280,6 +281,7 @@ struct pci_dev { unsigned int is_virtfn:1; unsigned int reset_fn:1; unsigned int is_hotplug_bridge:1; + unsigned int aer_firmware_first:1; pci_dev_flags_t dev_flags; atomic_t enable_cnt; /* pci_enable_device has been called */ @@ -635,7 +637,13 @@ struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from); struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn); -struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn); +struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus, + unsigned int devfn); +static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus, + unsigned int devfn) +{ + return pci_get_domain_bus_and_slot(0, bus, devfn); +} struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from); int pci_dev_present(const struct pci_device_id *ids); @@ -701,6 +709,7 @@ void pci_disable_device(struct pci_dev *dev); void pci_set_master(struct pci_dev *dev); void pci_clear_master(struct pci_dev *dev); int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state); +int pci_set_cacheline_size(struct pci_dev *dev); #define HAVE_PCI_SET_MWI int __must_check pci_set_mwi(struct pci_dev *dev); int pci_try_set_mwi(struct pci_dev *dev); @@ -1246,6 +1255,8 @@ extern int pci_pci_problems; extern unsigned long pci_cardbus_io_size; extern unsigned long pci_cardbus_mem_size; +extern u8 __devinitdata pci_dfl_cache_line_size; +extern u8 pci_cache_line_size; extern unsigned long pci_hotplug_io_size; extern unsigned long pci_hotplug_mem_size; @@ -1290,5 +1301,34 @@ extern void pci_hp_create_module_link(struct pci_slot *pci_slot); extern void pci_hp_remove_module_link(struct pci_slot *pci_slot); #endif +/** + * pci_pcie_cap - get the saved PCIe capability offset + * @dev: PCI device + * + * PCIe capability offset is calculated at PCI device initialization + * time and saved in the data structure. This function returns saved + * PCIe capability offset. Using this instead of pci_find_capability() + * reduces unnecessary search in the PCI configuration space. If you + * need to calculate PCIe capability offset from raw device for some + * reasons, please use pci_find_capability() instead. + */ +static inline int pci_pcie_cap(struct pci_dev *dev) +{ + return dev->pcie_cap; +} + +/** + * pci_is_pcie - check if the PCI device is PCI Express capable + * @dev: PCI device + * + * Retrun true if the PCI device is PCI Express capable, false otherwise. + */ +static inline bool pci_is_pcie(struct pci_dev *dev) +{ + return !!pci_pcie_cap(dev); +} + +void pci_request_acs(void); + #endif /* __KERNEL__ */ #endif /* LINUX_PCI_H */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index eae1f864c9340147cb86de9a420fcfa69e52a1bd..cca8a044e2b6b34d12fa8d215341e37dc8bfaa2e 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2295,6 +2295,20 @@ #define PCI_DEVICE_ID_MPC8536 0x0051 #define PCI_DEVICE_ID_P2020E 0x0070 #define PCI_DEVICE_ID_P2020 0x0071 +#define PCI_DEVICE_ID_P2010E 0x0078 +#define PCI_DEVICE_ID_P2010 0x0079 +#define PCI_DEVICE_ID_P1020E 0x0100 +#define PCI_DEVICE_ID_P1020 0x0101 +#define PCI_DEVICE_ID_P1011E 0x0108 +#define PCI_DEVICE_ID_P1011 0x0109 +#define PCI_DEVICE_ID_P1022E 0x0110 +#define PCI_DEVICE_ID_P1022 0x0111 +#define PCI_DEVICE_ID_P1013E 0x0118 +#define PCI_DEVICE_ID_P1013 0x0119 +#define PCI_DEVICE_ID_P4080E 0x0400 +#define PCI_DEVICE_ID_P4080 0x0401 +#define PCI_DEVICE_ID_P4040E 0x0408 +#define PCI_DEVICE_ID_P4040 0x0409 #define PCI_DEVICE_ID_MPC8641 0x7010 #define PCI_DEVICE_ID_MPC8641D 0x7011 #define PCI_DEVICE_ID_MPC8610 0x7018 diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index dd0bed4f1cf00ffd00f5b2eace8103a25d606432..9f2ad0aa3c3961ae1ba55c981b815815e6cd35b7 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h @@ -365,6 +365,11 @@ #define PCI_X_STATUS_266MHZ 0x40000000 /* 266 MHz capable */ #define PCI_X_STATUS_533MHZ 0x80000000 /* 533 MHz capable */ +/* PCI Bridge Subsystem ID registers */ + +#define PCI_SSVID_VENDOR_ID 4 /* PCI-Bridge subsystem vendor id register */ +#define PCI_SSVID_DEVICE_ID 6 /* PCI-Bridge subsystem device id register */ + /* PCI Express capability registers */ #define PCI_EXP_FLAGS 2 /* Capabilities register */ @@ -502,6 +507,7 @@ #define PCI_EXT_CAP_ID_VC 2 #define PCI_EXT_CAP_ID_DSN 3 #define PCI_EXT_CAP_ID_PWR 4 +#define PCI_EXT_CAP_ID_ACS 13 #define PCI_EXT_CAP_ID_ARI 14 #define PCI_EXT_CAP_ID_ATS 15 #define PCI_EXT_CAP_ID_SRIOV 16 @@ -662,4 +668,16 @@ #define PCI_SRIOV_VFM_MO 0x2 /* Active.MigrateOut */ #define PCI_SRIOV_VFM_AV 0x3 /* Active.Available */ +/* Access Control Service */ +#define PCI_ACS_CAP 0x04 /* ACS Capability Register */ +#define PCI_ACS_SV 0x01 /* Source Validation */ +#define PCI_ACS_TB 0x02 /* Translation Blocking */ +#define PCI_ACS_RR 0x04 /* P2P Request Redirect */ +#define PCI_ACS_CR 0x08 /* P2P Completion Redirect */ +#define PCI_ACS_UF 0x10 /* Upstream Forwarding */ +#define PCI_ACS_EC 0x20 /* P2P Egress Control */ +#define PCI_ACS_DT 0x40 /* Direct Translated P2P */ +#define PCI_ACS_CTRL 0x06 /* ACS Control Register */ +#define PCI_ACS_EGRESS_CTL_V 0x08 /* ACS Egress Control Vector */ + #endif /* LINUX_PCI_REGS_H */ diff --git a/include/linux/pcieport_if.h b/include/linux/pcieport_if.h index b4c79545330be8b5ef8e061161b8a2d61ce868b2..6775532b92a9a04befeff78664023b1181cd2132 100644 --- a/include/linux/pcieport_if.h +++ b/include/linux/pcieport_if.h @@ -10,10 +10,7 @@ #define _PCIEPORT_IF_H_ /* Port Type */ -#define PCIE_RC_PORT 4 /* Root port of RC */ -#define PCIE_SW_UPSTREAM_PORT 5 /* Upstream port of Switch */ -#define PCIE_SW_DOWNSTREAM_PORT 6 /* Downstream port of Switch */ -#define PCIE_ANY_PORT 7 +#define PCIE_ANY_PORT (~0) /* Service Type */ #define PCIE_PORT_SERVICE_PME_SHIFT 0 /* Power Management Event */ @@ -25,17 +22,6 @@ #define PCIE_PORT_SERVICE_VC_SHIFT 3 /* Virtual Channel */ #define PCIE_PORT_SERVICE_VC (1 << PCIE_PORT_SERVICE_VC_SHIFT) -/* Root/Upstream/Downstream Port's Interrupt Mode */ -#define PCIE_PORT_NO_IRQ (-1) -#define PCIE_PORT_INTx_MODE 0 -#define PCIE_PORT_MSI_MODE 1 -#define PCIE_PORT_MSIX_MODE 2 - -struct pcie_port_data { - int port_type; /* Type of the port */ - int port_irq_mode; /* [0:INTx | 1:MSI | 2:MSI-X] */ -}; - struct pcie_device { int irq; /* Service IRQ/MSI/MSI-X Vector */ struct pci_dev *port; /* Root/Upstream/Downstream Port */ diff --git a/include/linux/percpu-defs.h b/include/linux/percpu-defs.h index 9bd03193ecd48c5e2c1283309a2c8ac2914cab37..5a5d6ce4bd55a156c979c89072b0c830c93fc5d2 100644 --- a/include/linux/percpu-defs.h +++ b/include/linux/percpu-defs.h @@ -60,6 +60,7 @@ #define DEFINE_PER_CPU_SECTION(type, name, sec) \ __PCPU_DUMMY_ATTRS char __pcpu_scope_##name; \ + extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ __PCPU_ATTRS(sec) PER_CPU_DEF_ATTRIBUTES __weak \ __typeof__(type) per_cpu__##name diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 878836ca999c0f3e2b65836cbe8bd7816d44ffaa..cf5efbcf716c8cecf74d4d315e2619f6fdcfa1f4 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h @@ -34,8 +34,6 @@ #ifdef CONFIG_SMP -#ifndef CONFIG_HAVE_LEGACY_PER_CPU_AREA - /* minimum unit size, also is the maximum supported allocation size */ #define PCPU_MIN_UNIT_SIZE PFN_ALIGN(64 << 10) @@ -130,30 +128,9 @@ extern int __init pcpu_page_first_chunk(size_t reserved_size, #define per_cpu_ptr(ptr, cpu) SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu))) extern void *__alloc_reserved_percpu(size_t size, size_t align); - -#else /* CONFIG_HAVE_LEGACY_PER_CPU_AREA */ - -struct percpu_data { - void *ptrs[1]; -}; - -/* pointer disguising messes up the kmemleak objects tracking */ -#ifndef CONFIG_DEBUG_KMEMLEAK -#define __percpu_disguise(pdata) (struct percpu_data *)~(unsigned long)(pdata) -#else -#define __percpu_disguise(pdata) (struct percpu_data *)(pdata) -#endif - -#define per_cpu_ptr(ptr, cpu) \ -({ \ - struct percpu_data *__p = __percpu_disguise(ptr); \ - (__typeof__(ptr))__p->ptrs[(cpu)]; \ -}) - -#endif /* CONFIG_HAVE_LEGACY_PER_CPU_AREA */ - extern void *__alloc_percpu(size_t size, size_t align); extern void free_percpu(void *__pdata); +extern phys_addr_t per_cpu_ptr_to_phys(void *addr); #ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA extern void __init setup_per_cpu_areas(void); @@ -179,6 +156,11 @@ static inline void free_percpu(void *p) kfree(p); } +static inline phys_addr_t per_cpu_ptr_to_phys(void *addr) +{ + return __pa(addr); +} + static inline void __init setup_per_cpu_areas(void) { } static inline void *pcpu_lpage_remapped(void *kaddr) @@ -188,8 +170,8 @@ static inline void *pcpu_lpage_remapped(void *kaddr) #endif /* CONFIG_SMP */ -#define alloc_percpu(type) (type *)__alloc_percpu(sizeof(type), \ - __alignof__(type)) +#define alloc_percpu(type) \ + (typeof(type) *)__alloc_percpu(sizeof(type), __alignof__(type)) /* * Optional methods for optimized non-lvalue per-cpu variable access. @@ -243,4 +225,404 @@ do { \ # define percpu_xor(var, val) __percpu_generic_to_op(var, (val), ^=) #endif +/* + * Branching function to split up a function into a set of functions that + * are called for different scalar sizes of the objects handled. + */ + +extern void __bad_size_call_parameter(void); + +#define __pcpu_size_call_return(stem, variable) \ +({ typeof(variable) pscr_ret__; \ + switch(sizeof(variable)) { \ + case 1: pscr_ret__ = stem##1(variable);break; \ + case 2: pscr_ret__ = stem##2(variable);break; \ + case 4: pscr_ret__ = stem##4(variable);break; \ + case 8: pscr_ret__ = stem##8(variable);break; \ + default: \ + __bad_size_call_parameter();break; \ + } \ + pscr_ret__; \ +}) + +#define __pcpu_size_call(stem, variable, ...) \ +do { \ + switch(sizeof(variable)) { \ + case 1: stem##1(variable, __VA_ARGS__);break; \ + case 2: stem##2(variable, __VA_ARGS__);break; \ + case 4: stem##4(variable, __VA_ARGS__);break; \ + case 8: stem##8(variable, __VA_ARGS__);break; \ + default: \ + __bad_size_call_parameter();break; \ + } \ +} while (0) + +/* + * Optimized manipulation for memory allocated through the per cpu + * allocator or for addresses of per cpu variables (can be determined + * using per_cpu_var(xx). + * + * These operation guarantee exclusivity of access for other operations + * on the *same* processor. The assumption is that per cpu data is only + * accessed by a single processor instance (the current one). + * + * The first group is used for accesses that must be done in a + * preemption safe way since we know that the context is not preempt + * safe. Interrupts may occur. If the interrupt modifies the variable + * too then RMW actions will not be reliable. + * + * The arch code can provide optimized functions in two ways: + * + * 1. Override the function completely. F.e. define this_cpu_add(). + * The arch must then ensure that the various scalar format passed + * are handled correctly. + * + * 2. Provide functions for certain scalar sizes. F.e. provide + * this_cpu_add_2() to provide per cpu atomic operations for 2 byte + * sized RMW actions. If arch code does not provide operations for + * a scalar size then the fallback in the generic code will be + * used. + */ + +#define _this_cpu_generic_read(pcp) \ +({ typeof(pcp) ret__; \ + preempt_disable(); \ + ret__ = *this_cpu_ptr(&(pcp)); \ + preempt_enable(); \ + ret__; \ +}) + +#ifndef this_cpu_read +# ifndef this_cpu_read_1 +# define this_cpu_read_1(pcp) _this_cpu_generic_read(pcp) +# endif +# ifndef this_cpu_read_2 +# define this_cpu_read_2(pcp) _this_cpu_generic_read(pcp) +# endif +# ifndef this_cpu_read_4 +# define this_cpu_read_4(pcp) _this_cpu_generic_read(pcp) +# endif +# ifndef this_cpu_read_8 +# define this_cpu_read_8(pcp) _this_cpu_generic_read(pcp) +# endif +# define this_cpu_read(pcp) __pcpu_size_call_return(this_cpu_read_, (pcp)) +#endif + +#define _this_cpu_generic_to_op(pcp, val, op) \ +do { \ + preempt_disable(); \ + *__this_cpu_ptr(&pcp) op val; \ + preempt_enable(); \ +} while (0) + +#ifndef this_cpu_write +# ifndef this_cpu_write_1 +# define this_cpu_write_1(pcp, val) _this_cpu_generic_to_op((pcp), (val), =) +# endif +# ifndef this_cpu_write_2 +# define this_cpu_write_2(pcp, val) _this_cpu_generic_to_op((pcp), (val), =) +# endif +# ifndef this_cpu_write_4 +# define this_cpu_write_4(pcp, val) _this_cpu_generic_to_op((pcp), (val), =) +# endif +# ifndef this_cpu_write_8 +# define this_cpu_write_8(pcp, val) _this_cpu_generic_to_op((pcp), (val), =) +# endif +# define this_cpu_write(pcp, val) __pcpu_size_call(this_cpu_write_, (pcp), (val)) +#endif + +#ifndef this_cpu_add +# ifndef this_cpu_add_1 +# define this_cpu_add_1(pcp, val) _this_cpu_generic_to_op((pcp), (val), +=) +# endif +# ifndef this_cpu_add_2 +# define this_cpu_add_2(pcp, val) _this_cpu_generic_to_op((pcp), (val), +=) +# endif +# ifndef this_cpu_add_4 +# define this_cpu_add_4(pcp, val) _this_cpu_generic_to_op((pcp), (val), +=) +# endif +# ifndef this_cpu_add_8 +# define this_cpu_add_8(pcp, val) _this_cpu_generic_to_op((pcp), (val), +=) +# endif +# define this_cpu_add(pcp, val) __pcpu_size_call(this_cpu_add_, (pcp), (val)) +#endif + +#ifndef this_cpu_sub +# define this_cpu_sub(pcp, val) this_cpu_add((pcp), -(val)) +#endif + +#ifndef this_cpu_inc +# define this_cpu_inc(pcp) this_cpu_add((pcp), 1) +#endif + +#ifndef this_cpu_dec +# define this_cpu_dec(pcp) this_cpu_sub((pcp), 1) +#endif + +#ifndef this_cpu_and +# ifndef this_cpu_and_1 +# define this_cpu_and_1(pcp, val) _this_cpu_generic_to_op((pcp), (val), &=) +# endif +# ifndef this_cpu_and_2 +# define this_cpu_and_2(pcp, val) _this_cpu_generic_to_op((pcp), (val), &=) +# endif +# ifndef this_cpu_and_4 +# define this_cpu_and_4(pcp, val) _this_cpu_generic_to_op((pcp), (val), &=) +# endif +# ifndef this_cpu_and_8 +# define this_cpu_and_8(pcp, val) _this_cpu_generic_to_op((pcp), (val), &=) +# endif +# define this_cpu_and(pcp, val) __pcpu_size_call(this_cpu_and_, (pcp), (val)) +#endif + +#ifndef this_cpu_or +# ifndef this_cpu_or_1 +# define this_cpu_or_1(pcp, val) _this_cpu_generic_to_op((pcp), (val), |=) +# endif +# ifndef this_cpu_or_2 +# define this_cpu_or_2(pcp, val) _this_cpu_generic_to_op((pcp), (val), |=) +# endif +# ifndef this_cpu_or_4 +# define this_cpu_or_4(pcp, val) _this_cpu_generic_to_op((pcp), (val), |=) +# endif +# ifndef this_cpu_or_8 +# define this_cpu_or_8(pcp, val) _this_cpu_generic_to_op((pcp), (val), |=) +# endif +# define this_cpu_or(pcp, val) __pcpu_size_call(this_cpu_or_, (pcp), (val)) +#endif + +#ifndef this_cpu_xor +# ifndef this_cpu_xor_1 +# define this_cpu_xor_1(pcp, val) _this_cpu_generic_to_op((pcp), (val), ^=) +# endif +# ifndef this_cpu_xor_2 +# define this_cpu_xor_2(pcp, val) _this_cpu_generic_to_op((pcp), (val), ^=) +# endif +# ifndef this_cpu_xor_4 +# define this_cpu_xor_4(pcp, val) _this_cpu_generic_to_op((pcp), (val), ^=) +# endif +# ifndef this_cpu_xor_8 +# define this_cpu_xor_8(pcp, val) _this_cpu_generic_to_op((pcp), (val), ^=) +# endif +# define this_cpu_xor(pcp, val) __pcpu_size_call(this_cpu_or_, (pcp), (val)) +#endif + +/* + * Generic percpu operations that do not require preemption handling. + * Either we do not care about races or the caller has the + * responsibility of handling preemptions issues. Arch code can still + * override these instructions since the arch per cpu code may be more + * efficient and may actually get race freeness for free (that is the + * case for x86 for example). + * + * If there is no other protection through preempt disable and/or + * disabling interupts then one of these RMW operations can show unexpected + * behavior because the execution thread was rescheduled on another processor + * or an interrupt occurred and the same percpu variable was modified from + * the interrupt context. + */ +#ifndef __this_cpu_read +# ifndef __this_cpu_read_1 +# define __this_cpu_read_1(pcp) (*__this_cpu_ptr(&(pcp))) +# endif +# ifndef __this_cpu_read_2 +# define __this_cpu_read_2(pcp) (*__this_cpu_ptr(&(pcp))) +# endif +# ifndef __this_cpu_read_4 +# define __this_cpu_read_4(pcp) (*__this_cpu_ptr(&(pcp))) +# endif +# ifndef __this_cpu_read_8 +# define __this_cpu_read_8(pcp) (*__this_cpu_ptr(&(pcp))) +# endif +# define __this_cpu_read(pcp) __pcpu_size_call_return(__this_cpu_read_, (pcp)) +#endif + +#define __this_cpu_generic_to_op(pcp, val, op) \ +do { \ + *__this_cpu_ptr(&(pcp)) op val; \ +} while (0) + +#ifndef __this_cpu_write +# ifndef __this_cpu_write_1 +# define __this_cpu_write_1(pcp, val) __this_cpu_generic_to_op((pcp), (val), =) +# endif +# ifndef __this_cpu_write_2 +# define __this_cpu_write_2(pcp, val) __this_cpu_generic_to_op((pcp), (val), =) +# endif +# ifndef __this_cpu_write_4 +# define __this_cpu_write_4(pcp, val) __this_cpu_generic_to_op((pcp), (val), =) +# endif +# ifndef __this_cpu_write_8 +# define __this_cpu_write_8(pcp, val) __this_cpu_generic_to_op((pcp), (val), =) +# endif +# define __this_cpu_write(pcp, val) __pcpu_size_call(__this_cpu_write_, (pcp), (val)) +#endif + +#ifndef __this_cpu_add +# ifndef __this_cpu_add_1 +# define __this_cpu_add_1(pcp, val) __this_cpu_generic_to_op((pcp), (val), +=) +# endif +# ifndef __this_cpu_add_2 +# define __this_cpu_add_2(pcp, val) __this_cpu_generic_to_op((pcp), (val), +=) +# endif +# ifndef __this_cpu_add_4 +# define __this_cpu_add_4(pcp, val) __this_cpu_generic_to_op((pcp), (val), +=) +# endif +# ifndef __this_cpu_add_8 +# define __this_cpu_add_8(pcp, val) __this_cpu_generic_to_op((pcp), (val), +=) +# endif +# define __this_cpu_add(pcp, val) __pcpu_size_call(__this_cpu_add_, (pcp), (val)) +#endif + +#ifndef __this_cpu_sub +# define __this_cpu_sub(pcp, val) __this_cpu_add((pcp), -(val)) +#endif + +#ifndef __this_cpu_inc +# define __this_cpu_inc(pcp) __this_cpu_add((pcp), 1) +#endif + +#ifndef __this_cpu_dec +# define __this_cpu_dec(pcp) __this_cpu_sub((pcp), 1) +#endif + +#ifndef __this_cpu_and +# ifndef __this_cpu_and_1 +# define __this_cpu_and_1(pcp, val) __this_cpu_generic_to_op((pcp), (val), &=) +# endif +# ifndef __this_cpu_and_2 +# define __this_cpu_and_2(pcp, val) __this_cpu_generic_to_op((pcp), (val), &=) +# endif +# ifndef __this_cpu_and_4 +# define __this_cpu_and_4(pcp, val) __this_cpu_generic_to_op((pcp), (val), &=) +# endif +# ifndef __this_cpu_and_8 +# define __this_cpu_and_8(pcp, val) __this_cpu_generic_to_op((pcp), (val), &=) +# endif +# define __this_cpu_and(pcp, val) __pcpu_size_call(__this_cpu_and_, (pcp), (val)) +#endif + +#ifndef __this_cpu_or +# ifndef __this_cpu_or_1 +# define __this_cpu_or_1(pcp, val) __this_cpu_generic_to_op((pcp), (val), |=) +# endif +# ifndef __this_cpu_or_2 +# define __this_cpu_or_2(pcp, val) __this_cpu_generic_to_op((pcp), (val), |=) +# endif +# ifndef __this_cpu_or_4 +# define __this_cpu_or_4(pcp, val) __this_cpu_generic_to_op((pcp), (val), |=) +# endif +# ifndef __this_cpu_or_8 +# define __this_cpu_or_8(pcp, val) __this_cpu_generic_to_op((pcp), (val), |=) +# endif +# define __this_cpu_or(pcp, val) __pcpu_size_call(__this_cpu_or_, (pcp), (val)) +#endif + +#ifndef __this_cpu_xor +# ifndef __this_cpu_xor_1 +# define __this_cpu_xor_1(pcp, val) __this_cpu_generic_to_op((pcp), (val), ^=) +# endif +# ifndef __this_cpu_xor_2 +# define __this_cpu_xor_2(pcp, val) __this_cpu_generic_to_op((pcp), (val), ^=) +# endif +# ifndef __this_cpu_xor_4 +# define __this_cpu_xor_4(pcp, val) __this_cpu_generic_to_op((pcp), (val), ^=) +# endif +# ifndef __this_cpu_xor_8 +# define __this_cpu_xor_8(pcp, val) __this_cpu_generic_to_op((pcp), (val), ^=) +# endif +# define __this_cpu_xor(pcp, val) __pcpu_size_call(__this_cpu_xor_, (pcp), (val)) +#endif + +/* + * IRQ safe versions of the per cpu RMW operations. Note that these operations + * are *not* safe against modification of the same variable from another + * processors (which one gets when using regular atomic operations) + . They are guaranteed to be atomic vs. local interrupts and + * preemption only. + */ +#define irqsafe_cpu_generic_to_op(pcp, val, op) \ +do { \ + unsigned long flags; \ + local_irq_save(flags); \ + *__this_cpu_ptr(&(pcp)) op val; \ + local_irq_restore(flags); \ +} while (0) + +#ifndef irqsafe_cpu_add +# ifndef irqsafe_cpu_add_1 +# define irqsafe_cpu_add_1(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), +=) +# endif +# ifndef irqsafe_cpu_add_2 +# define irqsafe_cpu_add_2(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), +=) +# endif +# ifndef irqsafe_cpu_add_4 +# define irqsafe_cpu_add_4(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), +=) +# endif +# ifndef irqsafe_cpu_add_8 +# define irqsafe_cpu_add_8(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), +=) +# endif +# define irqsafe_cpu_add(pcp, val) __pcpu_size_call(irqsafe_cpu_add_, (pcp), (val)) +#endif + +#ifndef irqsafe_cpu_sub +# define irqsafe_cpu_sub(pcp, val) irqsafe_cpu_add((pcp), -(val)) +#endif + +#ifndef irqsafe_cpu_inc +# define irqsafe_cpu_inc(pcp) irqsafe_cpu_add((pcp), 1) +#endif + +#ifndef irqsafe_cpu_dec +# define irqsafe_cpu_dec(pcp) irqsafe_cpu_sub((pcp), 1) +#endif + +#ifndef irqsafe_cpu_and +# ifndef irqsafe_cpu_and_1 +# define irqsafe_cpu_and_1(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), &=) +# endif +# ifndef irqsafe_cpu_and_2 +# define irqsafe_cpu_and_2(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), &=) +# endif +# ifndef irqsafe_cpu_and_4 +# define irqsafe_cpu_and_4(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), &=) +# endif +# ifndef irqsafe_cpu_and_8 +# define irqsafe_cpu_and_8(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), &=) +# endif +# define irqsafe_cpu_and(pcp, val) __pcpu_size_call(irqsafe_cpu_and_, (val)) +#endif + +#ifndef irqsafe_cpu_or +# ifndef irqsafe_cpu_or_1 +# define irqsafe_cpu_or_1(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), |=) +# endif +# ifndef irqsafe_cpu_or_2 +# define irqsafe_cpu_or_2(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), |=) +# endif +# ifndef irqsafe_cpu_or_4 +# define irqsafe_cpu_or_4(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), |=) +# endif +# ifndef irqsafe_cpu_or_8 +# define irqsafe_cpu_or_8(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), |=) +# endif +# define irqsafe_cpu_or(pcp, val) __pcpu_size_call(irqsafe_cpu_or_, (val)) +#endif + +#ifndef irqsafe_cpu_xor +# ifndef irqsafe_cpu_xor_1 +# define irqsafe_cpu_xor_1(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), ^=) +# endif +# ifndef irqsafe_cpu_xor_2 +# define irqsafe_cpu_xor_2(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), ^=) +# endif +# ifndef irqsafe_cpu_xor_4 +# define irqsafe_cpu_xor_4(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), ^=) +# endif +# ifndef irqsafe_cpu_xor_8 +# define irqsafe_cpu_xor_8(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), ^=) +# endif +# define irqsafe_cpu_xor(pcp, val) __pcpu_size_call(irqsafe_cpu_xor_, (val)) +#endif + #endif /* __LINUX_PERCPU_H */ diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 43adbd7f0010c21719f75dc05dfbf5d61465abf7..64a53f74c9a91d140331863bbc4a1e0423fbb7ee 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -18,10 +18,6 @@ #include #include -#ifdef CONFIG_HAVE_HW_BREAKPOINT -#include -#endif - /* * User-space ABI bits: */ @@ -215,12 +211,12 @@ struct perf_event_attr { __u32 wakeup_watermark; /* bytes before wakeup */ }; - union { - struct { /* Hardware breakpoint info */ - __u64 bp_addr; - __u32 bp_type; - __u32 bp_len; - }; + struct { /* Hardware breakpoint info */ + __u64 bp_addr; + __u32 bp_type; + __u32 bp_len; + __u64 __bp_reserved_1; + __u64 __bp_reserved_2; }; __u32 __reserved_2; @@ -451,6 +447,10 @@ enum perf_callchain_context { # include #endif +#ifdef CONFIG_HAVE_HW_BREAKPOINT +#include +#endif + #include #include #include @@ -565,10 +565,12 @@ struct perf_pending_entry { void (*func)(struct perf_pending_entry *); }; -typedef void (*perf_callback_t)(struct perf_event *, void *); - struct perf_sample_data; +typedef void (*perf_overflow_handler_t)(struct perf_event *, int, + struct perf_sample_data *, + struct pt_regs *regs); + /** * struct perf_event - performance event kernel representation: */ @@ -660,18 +662,12 @@ struct perf_event { struct pid_namespace *ns; u64 id; - void (*overflow_handler)(struct perf_event *event, - int nmi, struct perf_sample_data *data, - struct pt_regs *regs); + perf_overflow_handler_t overflow_handler; #ifdef CONFIG_EVENT_PROFILE struct event_filter *filter; #endif - perf_callback_t callback; - - perf_callback_t event_callback; - #endif /* CONFIG_PERF_EVENTS */ }; @@ -781,7 +777,7 @@ extern struct perf_event * perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, pid_t pid, - perf_callback_t callback); + perf_overflow_handler_t callback); extern u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running); @@ -876,6 +872,8 @@ extern void perf_output_copy(struct perf_output_handle *handle, const void *buf, unsigned int len); extern int perf_swevent_get_recursion_context(void); extern void perf_swevent_put_recursion_context(int rctx); +extern void perf_event_enable(struct perf_event *event); +extern void perf_event_disable(struct perf_event *event); #else static inline void perf_event_task_sched_in(struct task_struct *task, int cpu) { } @@ -906,7 +904,8 @@ static inline void perf_event_fork(struct task_struct *tsk) { } static inline void perf_event_init(void) { } static inline int perf_swevent_get_recursion_context(void) { return -1; } static inline void perf_swevent_put_recursion_context(int rctx) { } - +static inline void perf_event_enable(struct perf_event *event) { } +static inline void perf_event_disable(struct perf_event *event) { } #endif #define perf_output_put(handle, x) \ diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 3c6675c2444bf030ee9036ce3cc4911463a1c90b..71ff887ca44ee6eccfc83416554b556f61a6231c 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -83,6 +83,8 @@ struct early_platform_driver { struct platform_driver *pdrv; struct list_head list; int requested_id; + char *buffer; + int bufsize; }; #define EARLY_PLATFORM_ID_UNSET -2 @@ -102,21 +104,29 @@ extern int early_platform_driver_probe(char *class_str, int nr_probe, int user_only); extern void early_platform_cleanup(void); +#define early_platform_init(class_string, platdrv) \ + early_platform_init_buffer(class_string, platdrv, NULL, 0) #ifndef MODULE -#define early_platform_init(class_string, platform_driver) \ +#define early_platform_init_buffer(class_string, platdrv, buf, bufsiz) \ static __initdata struct early_platform_driver early_driver = { \ .class_str = class_string, \ - .pdrv = platform_driver, \ + .buffer = buf, \ + .bufsize = bufsiz, \ + .pdrv = platdrv, \ .requested_id = EARLY_PLATFORM_ID_UNSET, \ }; \ -static int __init early_platform_driver_setup_func(char *buf) \ +static int __init early_platform_driver_setup_func(char *buffer) \ { \ - return early_platform_driver_register(&early_driver, buf); \ + return early_platform_driver_register(&early_driver, buffer); \ } \ early_param(class_string, early_platform_driver_setup_func) #else /* MODULE */ -#define early_platform_init(class_string, platform_driver) +#define early_platform_init_buffer(class_string, platdrv, buf, bufsiz) \ +static inline char *early_platform_driver_setup_func(void) \ +{ \ + return bufsiz ? buf : NULL; \ +} #endif /* MODULE */ #endif /* _PLATFORM_DEVICE_H_ */ diff --git a/include/linux/quota.h b/include/linux/quota.h index ce9a9b2e5cd44fffbc9afcd8f4f90b692343a88c..e70e62194243f1a255b83cf930e9d69b9bc6f1fc 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -73,6 +73,8 @@ /* Quota format type IDs */ #define QFMT_VFS_OLD 1 #define QFMT_VFS_V0 2 +#define QFMT_OCFS2 3 +#define QFMT_VFS_V1 4 /* Size of block in which space limits are passed through the quota * interface */ @@ -334,7 +336,7 @@ struct quotactl_ops { struct quota_format_type { int qf_fmt_id; /* Quota format id */ - struct quota_format_ops *qf_ops; /* Operations of format */ + const struct quota_format_ops *qf_ops; /* Operations of format */ struct module *qf_owner; /* Module implementing quota format */ struct quota_format_type *qf_next; }; @@ -394,7 +396,7 @@ struct quota_info { struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */ struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */ struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ - struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ + const struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ }; int register_quota_format(struct quota_format_type *fmt); diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h index d92480f8285c76bec5b67fb5950fdc12f2d06c3c..1cbbd2c11aa921e59d52deaa65b5dc3853e72c17 100644 --- a/include/linux/raid/pq.h +++ b/include/linux/raid/pq.h @@ -78,6 +78,25 @@ struct raid6_calls { /* Selected algorithm */ extern struct raid6_calls raid6_call; +/* Various routine sets */ +extern const struct raid6_calls raid6_intx1; +extern const struct raid6_calls raid6_intx2; +extern const struct raid6_calls raid6_intx4; +extern const struct raid6_calls raid6_intx8; +extern const struct raid6_calls raid6_intx16; +extern const struct raid6_calls raid6_intx32; +extern const struct raid6_calls raid6_mmxx1; +extern const struct raid6_calls raid6_mmxx2; +extern const struct raid6_calls raid6_sse1x1; +extern const struct raid6_calls raid6_sse1x2; +extern const struct raid6_calls raid6_sse2x1; +extern const struct raid6_calls raid6_sse2x2; +extern const struct raid6_calls raid6_sse2x4; +extern const struct raid6_calls raid6_altivec1; +extern const struct raid6_calls raid6_altivec2; +extern const struct raid6_calls raid6_altivec4; +extern const struct raid6_calls raid6_altivec8; + /* Algorithm list */ extern const struct raid6_calls * const raid6_algos[]; int raid6_select_algo(void); diff --git a/include/linux/sched.h b/include/linux/sched.h index 89115ec7d43f2bfe0bcd5c581052615e733fc029..294eb2f8014411540d7be6cf233cd78b1391d5ef 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1102,7 +1102,7 @@ struct sched_class { void (*set_curr_task) (struct rq *rq); void (*task_tick) (struct rq *rq, struct task_struct *p, int queued); - void (*task_new) (struct rq *rq, struct task_struct *p); + void (*task_fork) (struct task_struct *p); void (*switched_from) (struct rq *this_rq, struct task_struct *task, int running); @@ -1111,7 +1111,8 @@ struct sched_class { void (*prio_changed) (struct rq *this_rq, struct task_struct *task, int oldprio, int running); - unsigned int (*get_rr_interval) (struct task_struct *task); + unsigned int (*get_rr_interval) (struct rq *rq, + struct task_struct *task); #ifdef CONFIG_FAIR_GROUP_SCHED void (*moved_group) (struct task_struct *p); @@ -1151,8 +1152,6 @@ struct sched_entity { u64 start_runtime; u64 avg_wakeup; - u64 avg_running; - #ifdef CONFIG_SCHEDSTATS u64 wait_start; u64 wait_max; @@ -1175,7 +1174,6 @@ struct sched_entity { u64 nr_failed_migrations_running; u64 nr_failed_migrations_hot; u64 nr_forced_migrations; - u64 nr_forced2_migrations; u64 nr_wakeups; u64 nr_wakeups_sync; @@ -1840,7 +1838,8 @@ static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask) extern int sched_clock_stable; #endif -extern unsigned long long sched_clock(void); +/* ftrace calls sched_clock() directly */ +extern unsigned long long notrace sched_clock(void); extern void sched_clock_init(void); extern u64 sched_clock_cpu(int cpu); @@ -1903,14 +1902,22 @@ extern unsigned int sysctl_sched_wakeup_granularity; extern unsigned int sysctl_sched_shares_ratelimit; extern unsigned int sysctl_sched_shares_thresh; extern unsigned int sysctl_sched_child_runs_first; + +enum sched_tunable_scaling { + SCHED_TUNABLESCALING_NONE, + SCHED_TUNABLESCALING_LOG, + SCHED_TUNABLESCALING_LINEAR, + SCHED_TUNABLESCALING_END, +}; +extern enum sched_tunable_scaling sysctl_sched_tunable_scaling; + #ifdef CONFIG_SCHED_DEBUG -extern unsigned int sysctl_sched_features; extern unsigned int sysctl_sched_migration_cost; extern unsigned int sysctl_sched_nr_migrate; extern unsigned int sysctl_sched_time_avg; extern unsigned int sysctl_timer_migration; -int sched_nr_latency_handler(struct ctl_table *table, int write, +int sched_proc_update_handler(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos); #endif diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index 850d057500dece3f52497b2bed3aab51dd677852..ca6b2b31799197463220b53179b4a1cd41ead85e 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -110,7 +110,7 @@ extern struct cache_sizes malloc_sizes[]; void *kmem_cache_alloc(struct kmem_cache *, gfp_t); void *__kmalloc(size_t size, gfp_t flags); -#ifdef CONFIG_KMEMTRACE +#ifdef CONFIG_TRACING extern void *kmem_cache_alloc_notrace(struct kmem_cache *cachep, gfp_t flags); extern size_t slab_buffer_size(struct kmem_cache *cachep); #else @@ -166,7 +166,7 @@ found: extern void *__kmalloc_node(size_t size, gfp_t flags, int node); extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node); -#ifdef CONFIG_KMEMTRACE +#ifdef CONFIG_TRACING extern void *kmem_cache_alloc_node_notrace(struct kmem_cache *cachep, gfp_t flags, int nodeid); diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index 5ad70a60fd7473ee7f9a46a8355e847363b6c596..1e14beb23f9ba757c8db47e049261bbec0c9c6f3 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -217,7 +217,7 @@ static __always_inline struct kmem_cache *kmalloc_slab(size_t size) void *kmem_cache_alloc(struct kmem_cache *, gfp_t); void *__kmalloc(size_t size, gfp_t flags); -#ifdef CONFIG_KMEMTRACE +#ifdef CONFIG_TRACING extern void *kmem_cache_alloc_notrace(struct kmem_cache *s, gfp_t gfpflags); #else static __always_inline void * @@ -266,7 +266,7 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags) void *__kmalloc_node(size_t size, gfp_t flags, int node); void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node); -#ifdef CONFIG_KMEMTRACE +#ifdef CONFIG_TRACING extern void *kmem_cache_alloc_node_notrace(struct kmem_cache *s, gfp_t gfpflags, int node); diff --git a/include/linux/spi/sh_msiof.h b/include/linux/spi/sh_msiof.h new file mode 100644 index 0000000000000000000000000000000000000000..2e8db3d2d2e5ef7aedbd834534cd7fe6625d9c34 --- /dev/null +++ b/include/linux/spi/sh_msiof.h @@ -0,0 +1,10 @@ +#ifndef __SPI_SH_MSIOF_H__ +#define __SPI_SH_MSIOF_H__ + +struct sh_msiof_spi_info { + int tx_fifo_override; + int rx_fifo_override; + u16 num_chipselect; +}; + +#endif /* __SPI_SH_MSIOF_H__ */ diff --git a/include/linux/spi/xilinx_spi.h b/include/linux/spi/xilinx_spi.h new file mode 100644 index 0000000000000000000000000000000000000000..6f17278810b05f29544b2c2f21ed081b776b577f --- /dev/null +++ b/include/linux/spi/xilinx_spi.h @@ -0,0 +1,20 @@ +#ifndef __LINUX_SPI_XILINX_SPI_H +#define __LINUX_SPI_XILINX_SPI_H + +/** + * struct xspi_platform_data - Platform data of the Xilinx SPI driver + * @num_chipselect: Number of chip select by the IP. + * @little_endian: If registers should be accessed little endian or not. + * @bits_per_word: Number of bits per word. + * @devices: Devices to add when the driver is probed. + * @num_devices: Number of devices in the devices array. + */ +struct xspi_platform_data { + u16 num_chipselect; + bool little_endian; + u8 bits_per_word; + struct spi_board_info *devices; + u8 num_devices; +}; + +#endif /* __LINUX_SPI_XILINX_SPI_H */ diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 401097781fc0601e5b7359ea15ec76ad2a3f5f03..1906782ec86bc6b668998e17bc3a68d6c244a334 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h @@ -130,12 +130,14 @@ struct rpc_task_setup { #define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */ #define RPC_TASK_KILLED 0x0100 /* task was killed */ #define RPC_TASK_SOFT 0x0200 /* Use soft timeouts */ +#define RPC_TASK_SOFTCONN 0x0400 /* Fail if can't connect */ #define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC) #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) #define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS) #define RPC_ASSASSINATED(t) ((t)->tk_flags & RPC_TASK_KILLED) #define RPC_IS_SOFT(t) ((t)->tk_flags & RPC_TASK_SOFT) +#define RPC_IS_SOFTCONN(t) ((t)->tk_flags & RPC_TASK_SOFTCONN) #define RPC_TASK_RUNNING 0 #define RPC_TASK_QUEUED 1 diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index bc70c5810fec9b430bce77d84885b36194d5a897..939a61507ac5a64d73743784138e26d343ed05ed 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -834,4 +834,8 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[]); asmlinkage long sys_perf_event_open( struct perf_event_attr __user *attr_uptr, pid_t pid, int cpu, int group_fd, unsigned long flags); + +asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff); #endif diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h index 09077f6ed12850cd43a44e26926a3f7b13fcacc7..5cf397ceb726fee2c48da416f8ade27c1ae6a7f5 100644 --- a/include/linux/trace_seq.h +++ b/include/linux/trace_seq.h @@ -14,6 +14,7 @@ struct trace_seq { unsigned char buffer[PAGE_SIZE]; unsigned int len; unsigned int readpos; + int full; }; static inline void @@ -21,6 +22,7 @@ trace_seq_init(struct trace_seq *s) { s->len = 0; s->readpos = 0; + s->full = 0; } /* @@ -33,7 +35,7 @@ extern int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) __attribute__ ((format (printf, 2, 0))); extern int trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary); -extern void trace_print_seq(struct seq_file *m, struct trace_seq *s); +extern int trace_print_seq(struct seq_file *m, struct trace_seq *s); extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt); extern int trace_seq_puts(struct trace_seq *s, const char *str); @@ -55,8 +57,9 @@ trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) return 0; } -static inline void trace_print_seq(struct seq_file *m, struct trace_seq *s) +static inline int trace_print_seq(struct seq_file *m, struct trace_seq *s) { + return 0; } static inline ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt) diff --git a/include/linux/tty.h b/include/linux/tty.h index f0f43d08d8b8765911d51f681034841a73b1c239..405a9035fe40601114e02d77a98aa0090bcd8646 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -190,9 +190,17 @@ struct tty_port_operations { /* Control the DTR line */ void (*dtr_rts)(struct tty_port *port, int raise); /* Called when the last close completes or a hangup finishes - IFF the port was initialized. Do not use to free resources */ + IFF the port was initialized. Do not use to free resources. Called + under the port mutex to serialize against activate/shutdowns */ void (*shutdown)(struct tty_port *port); void (*drop)(struct tty_port *port); + /* Called under the port mutex from tty_port_open, serialized using + the port mutex */ + /* FIXME: long term getting the tty argument *out* of this would be + good for consoles */ + int (*activate)(struct tty_port *port, struct tty_struct *tty); + /* Called on the final put of a port */ + void (*destruct)(struct tty_port *port); }; struct tty_port { @@ -206,12 +214,14 @@ struct tty_port { wait_queue_head_t delta_msr_wait; /* Modem status change */ unsigned long flags; /* TTY flags ASY_*/ struct mutex mutex; /* Locking */ + struct mutex buf_mutex; /* Buffer alloc lock */ unsigned char *xmit_buf; /* Optional buffer */ unsigned int close_delay; /* Close port delay */ unsigned int closing_wait; /* Delay for output */ int drain_delay; /* Set to zero if no pure time based drain is needed else set to size of fifo */ + struct kref kref; /* Ref counter */ }; /* @@ -439,7 +449,7 @@ extern void initialize_tty_struct(struct tty_struct *tty, struct tty_driver *driver, int idx); extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, int first_ok); -extern void tty_release_dev(struct file *filp); +extern int tty_release(struct inode *inode, struct file *filp); extern int tty_init_termios(struct tty_struct *tty); extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty); @@ -454,6 +464,15 @@ extern int tty_write_lock(struct tty_struct *tty, int ndelay); extern void tty_port_init(struct tty_port *port); extern int tty_port_alloc_xmit_buf(struct tty_port *port); extern void tty_port_free_xmit_buf(struct tty_port *port); +extern void tty_port_put(struct tty_port *port); + +extern inline struct tty_port *tty_port_get(struct tty_port *port) +{ + if (port) + kref_get(&port->kref); + return port; +} + extern struct tty_struct *tty_port_tty_get(struct tty_port *port); extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty); extern int tty_port_carrier_raised(struct tty_port *port); @@ -467,6 +486,8 @@ extern int tty_port_close_start(struct tty_port *port, extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty); extern void tty_port_close(struct tty_port *port, struct tty_struct *tty, struct file *filp); +extern int tty_port_open(struct tty_port *port, + struct tty_struct *tty, struct file *filp); extern inline int tty_port_users(struct tty_port *port) { return port->count + port->blocked_open; diff --git a/include/linux/usb.h b/include/linux/usb.h index a34fa89f1474891f51f727f8aa927ca999c9f168..e101a2d04d7588843083bfd466831e4fb807347e 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -331,6 +331,7 @@ struct usb_bus { u8 otg_port; /* 0, or number of OTG/HNP port */ unsigned is_b_host:1; /* true during some HNP roleswitches */ unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */ + unsigned sg_tablesize; /* 0 or largest number of sg list entries */ int devnum_next; /* Next open device number in * round-robin allocation */ @@ -428,11 +429,9 @@ struct usb_tt; * @last_busy: time of last use * @autosuspend_delay: in jiffies * @connect_time: time device was first connected - * @auto_pm: autosuspend/resume in progress * @do_remote_wakeup: remote wakeup should be enabled * @reset_resume: needs reset instead of resume * @autosuspend_disabled: autosuspend disabled by the user - * @autoresume_disabled: autoresume disabled by the user * @skip_sys_resume: skip the next system resume * @wusb_dev: if this is a Wireless USB device, link to the WUSB * specific data for the device. @@ -513,11 +512,9 @@ struct usb_device { int autosuspend_delay; unsigned long connect_time; - unsigned auto_pm:1; unsigned do_remote_wakeup:1; unsigned reset_resume:1; unsigned autosuspend_disabled:1; - unsigned autoresume_disabled:1; unsigned skip_sys_resume:1; #endif struct wusb_dev *wusb_dev; @@ -543,22 +540,20 @@ extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id); /* USB autosuspend and autoresume */ #ifdef CONFIG_USB_SUSPEND -extern int usb_autopm_set_interface(struct usb_interface *intf); extern int usb_autopm_get_interface(struct usb_interface *intf); extern void usb_autopm_put_interface(struct usb_interface *intf); extern int usb_autopm_get_interface_async(struct usb_interface *intf); extern void usb_autopm_put_interface_async(struct usb_interface *intf); -static inline void usb_autopm_enable(struct usb_interface *intf) +static inline void usb_autopm_get_interface_no_resume( + struct usb_interface *intf) { - atomic_set(&intf->pm_usage_cnt, 0); - usb_autopm_set_interface(intf); + atomic_inc(&intf->pm_usage_cnt); } - -static inline void usb_autopm_disable(struct usb_interface *intf) +static inline void usb_autopm_put_interface_no_suspend( + struct usb_interface *intf) { - atomic_set(&intf->pm_usage_cnt, 1); - usb_autopm_set_interface(intf); + atomic_dec(&intf->pm_usage_cnt); } static inline void usb_mark_last_busy(struct usb_device *udev) @@ -568,12 +563,8 @@ static inline void usb_mark_last_busy(struct usb_device *udev) #else -static inline int usb_autopm_set_interface(struct usb_interface *intf) -{ return 0; } - static inline int usb_autopm_get_interface(struct usb_interface *intf) { return 0; } - static inline int usb_autopm_get_interface_async(struct usb_interface *intf) { return 0; } @@ -581,9 +572,11 @@ static inline void usb_autopm_put_interface(struct usb_interface *intf) { } static inline void usb_autopm_put_interface_async(struct usb_interface *intf) { } -static inline void usb_autopm_enable(struct usb_interface *intf) +static inline void usb_autopm_get_interface_no_resume( + struct usb_interface *intf) { } -static inline void usb_autopm_disable(struct usb_interface *intf) +static inline void usb_autopm_put_interface_no_suspend( + struct usb_interface *intf) { } static inline void usb_mark_last_busy(struct usb_device *udev) { } @@ -626,6 +619,10 @@ extern struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev, unsigned ifnum); extern struct usb_host_interface *usb_altnum_to_altsetting( const struct usb_interface *intf, unsigned int altnum); +extern struct usb_host_interface *usb_find_alt_setting( + struct usb_host_config *config, + unsigned int iface_num, + unsigned int alt_num); /** diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 4f6bb3d2160e9f8d84516aae44363a662418431a..738ea1a691cb8a5dab64d631792871273fd45053 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -127,6 +127,7 @@ struct usb_function { /* private: */ /* internals */ struct list_head list; + DECLARE_BITMAP(endpoints, 32); }; int usb_add_function(struct usb_configuration *, struct usb_function *); diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 2443c0e7a80cd5e25ca77d217a0f5abbd2c1151e..52bb917641f050700d7c2ef06f8a28dd367f1631 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -33,6 +33,23 @@ enum usb_otg_state { OTG_STATE_A_VBUS_ERR, }; +#define USB_OTG_PULLUP_ID (1 << 0) +#define USB_OTG_PULLDOWN_DP (1 << 1) +#define USB_OTG_PULLDOWN_DM (1 << 2) +#define USB_OTG_EXT_VBUS_INDICATOR (1 << 3) +#define USB_OTG_DRV_VBUS (1 << 4) +#define USB_OTG_DRV_VBUS_EXT (1 << 5) + +struct otg_transceiver; + +/* for transceivers connected thru an ULPI interface, the user must + * provide access ops + */ +struct otg_io_access_ops { + int (*read)(struct otg_transceiver *otg, u32 reg); + int (*write)(struct otg_transceiver *otg, u32 val, u32 reg); +}; + /* * the otg driver needs to interact with both device side and host side * usb controllers. it decides which controller is active at a given @@ -42,6 +59,7 @@ enum usb_otg_state { struct otg_transceiver { struct device *dev; const char *label; + unsigned int flags; u8 default_a; enum usb_otg_state state; @@ -49,10 +67,17 @@ struct otg_transceiver { struct usb_bus *host; struct usb_gadget *gadget; + struct otg_io_access_ops *io_ops; + void __iomem *io_priv; + /* to pass extra port status to the root hub */ u16 port_status; u16 port_change; + /* initialize/shutdown the OTG controller */ + int (*init)(struct otg_transceiver *otg); + void (*shutdown)(struct otg_transceiver *otg); + /* bind/unbind the host controller */ int (*set_host)(struct otg_transceiver *otg, struct usb_bus *host); @@ -65,6 +90,10 @@ struct otg_transceiver { int (*set_power)(struct otg_transceiver *otg, unsigned mA); + /* effective for A-peripheral, ignored for B devices */ + int (*set_vbus)(struct otg_transceiver *otg, + bool enabled); + /* for non-OTG B devices: set transceiver into suspend mode */ int (*set_suspend)(struct otg_transceiver *otg, int suspend); @@ -85,6 +114,38 @@ extern int otg_set_transceiver(struct otg_transceiver *); extern void usb_nop_xceiv_register(void); extern void usb_nop_xceiv_unregister(void); +/* helpers for direct access thru low-level io interface */ +static inline int otg_io_read(struct otg_transceiver *otg, u32 reg) +{ + if (otg->io_ops && otg->io_ops->read) + return otg->io_ops->read(otg, reg); + + return -EINVAL; +} + +static inline int otg_io_write(struct otg_transceiver *otg, u32 reg, u32 val) +{ + if (otg->io_ops && otg->io_ops->write) + return otg->io_ops->write(otg, reg, val); + + return -EINVAL; +} + +static inline int +otg_init(struct otg_transceiver *otg) +{ + if (otg->init) + return otg->init(otg); + + return 0; +} + +static inline void +otg_shutdown(struct otg_transceiver *otg) +{ + if (otg->shutdown) + otg->shutdown(otg); +} /* for usb host and peripheral controller drivers */ extern struct otg_transceiver *otg_get_transceiver(void); @@ -97,6 +158,12 @@ otg_start_hnp(struct otg_transceiver *otg) return otg->start_hnp(otg); } +/* Context: can sleep */ +static inline int +otg_set_vbus(struct otg_transceiver *otg, bool enabled) +{ + return otg->set_vbus(otg, enabled); +} /* for HCDs */ static inline int @@ -105,7 +172,6 @@ otg_set_host(struct otg_transceiver *otg, struct usb_bus *host) return otg->set_host(otg, host); } - /* for usb peripheral controller drivers */ /* Context: can sleep */ diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index ce911ebf91e82c54c65cc2f46d428ed4c1bcab6a..acf6e457c04b17c695b701febae74415812c5671 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -39,8 +39,6 @@ enum port_dev_state { * @serial: pointer back to the struct usb_serial owner of this port. * @port: pointer to the corresponding tty_port for this port. * @lock: spinlock to grab when updating portions of this structure. - * @mutex: mutex used to synchronize serial_open() and serial_close() - * access for this port. * @number: the number of the port (the minor number). * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. @@ -77,7 +75,6 @@ struct usb_serial_port { struct usb_serial *serial; struct tty_port port; spinlock_t lock; - struct mutex mutex; unsigned char number; unsigned char *interrupt_in_buffer; diff --git a/include/linux/usb/ulpi.h b/include/linux/usb/ulpi.h new file mode 100644 index 0000000000000000000000000000000000000000..20675c6ebc4d1f4b9bcee4245ee7fd0976526d11 --- /dev/null +++ b/include/linux/usb/ulpi.h @@ -0,0 +1,7 @@ +#ifndef __LINUX_USB_ULPI_H +#define __LINUX_USB_ULPI_H + +struct otg_transceiver *otg_ulpi_create(struct otg_io_access_ops *ops, + unsigned int flags); + +#endif /* __LINUX_USB_ULPI_H */ diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index 3d15fb9bc116fbba8f03612b9af2fae6b34ba8bf..a4b947e470a59b9a191e55edab3a0fdd24a2a469 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -56,7 +56,9 @@ US_FLAG(SANE_SENSE, 0x00008000) \ /* Sane Sense (> 18 bytes) */ \ US_FLAG(CAPACITY_OK, 0x00010000) \ - /* READ CAPACITY response is correct */ + /* READ CAPACITY response is correct */ \ + US_FLAG(BAD_SENSE, 0x00020000) \ + /* Bad Sense (never more than 18 bytes) */ #define US_FLAG(name, value) US_FL_##name = value , enum { US_DO_ALL_FLAGS }; diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h index b2a7d8ba6ee3d6c7ee7435bd43eedd6640243a26..15591d2ea4004a86599e940ec4583bb12a1be341 100644 --- a/include/linux/usbdevice_fs.h +++ b/include/linux/usbdevice_fs.h @@ -128,6 +128,29 @@ struct usbdevfs_hub_portinfo { #ifdef __KERNEL__ #ifdef CONFIG_COMPAT #include + +struct usbdevfs_ctrltransfer32 { + u8 bRequestType; + u8 bRequest; + u16 wValue; + u16 wIndex; + u16 wLength; + u32 timeout; /* in milliseconds */ + compat_caddr_t data; +}; + +struct usbdevfs_bulktransfer32 { + compat_uint_t ep; + compat_uint_t len; + compat_uint_t timeout; /* in milliseconds */ + compat_caddr_t data; +}; + +struct usbdevfs_disconnectsignal32 { + compat_int_t signr; + compat_caddr_t context; +}; + struct usbdevfs_urb32 { unsigned char type; unsigned char endpoint; @@ -153,7 +176,9 @@ struct usbdevfs_ioctl32 { #endif /* __KERNEL__ */ #define USBDEVFS_CONTROL _IOWR('U', 0, struct usbdevfs_ctrltransfer) +#define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32) #define USBDEVFS_BULK _IOWR('U', 2, struct usbdevfs_bulktransfer) +#define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32) #define USBDEVFS_RESETEP _IOR('U', 3, unsigned int) #define USBDEVFS_SETINTERFACE _IOR('U', 4, struct usbdevfs_setinterface) #define USBDEVFS_SETCONFIGURATION _IOR('U', 5, unsigned int) @@ -166,6 +191,7 @@ struct usbdevfs_ioctl32 { #define USBDEVFS_REAPURBNDELAY _IOW('U', 13, void *) #define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, __u32) #define USBDEVFS_DISCSIGNAL _IOR('U', 14, struct usbdevfs_disconnectsignal) +#define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32) #define USBDEVFS_CLAIMINTERFACE _IOR('U', 15, unsigned int) #define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int) #define USBDEVFS_CONNECTINFO _IOW('U', 17, struct usbdevfs_connectinfo) diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h index 2d0f222388a8e9f2dfb3f8bec716eff2999d78f2..d85889710f9b6a4fbf5040fd941c1cfca7847428 100644 --- a/include/linux/vmstat.h +++ b/include/linux/vmstat.h @@ -76,24 +76,22 @@ DECLARE_PER_CPU(struct vm_event_state, vm_event_states); static inline void __count_vm_event(enum vm_event_item item) { - __get_cpu_var(vm_event_states).event[item]++; + __this_cpu_inc(per_cpu_var(vm_event_states).event[item]); } static inline void count_vm_event(enum vm_event_item item) { - get_cpu_var(vm_event_states).event[item]++; - put_cpu(); + this_cpu_inc(per_cpu_var(vm_event_states).event[item]); } static inline void __count_vm_events(enum vm_event_item item, long delta) { - __get_cpu_var(vm_event_states).event[item] += delta; + __this_cpu_add(per_cpu_var(vm_event_states).event[item], delta); } static inline void count_vm_events(enum vm_event_item item, long delta) { - get_cpu_var(vm_event_states).event[item] += delta; - put_cpu(); + this_cpu_add(per_cpu_var(vm_event_states).event[item], delta); } extern void all_vm_events(unsigned long *); diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index cf24c20de9e48e43a4712722196aad8555207d8c..9466e860d8c2a6dd816da1f7363117ebd56291f5 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -25,6 +25,7 @@ typedef void (*work_func_t)(struct work_struct *work); struct work_struct { atomic_long_t data; #define WORK_STRUCT_PENDING 0 /* T if work item pending execution */ +#define WORK_STRUCT_STATIC 1 /* static initializer (debugobjects) */ #define WORK_STRUCT_FLAG_MASK (3UL) #define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK) struct list_head entry; @@ -35,6 +36,7 @@ struct work_struct { }; #define WORK_DATA_INIT() ATOMIC_LONG_INIT(0) +#define WORK_DATA_STATIC_INIT() ATOMIC_LONG_INIT(2) struct delayed_work { struct work_struct work; @@ -63,7 +65,7 @@ struct execute_work { #endif #define __WORK_INITIALIZER(n, f) { \ - .data = WORK_DATA_INIT(), \ + .data = WORK_DATA_STATIC_INIT(), \ .entry = { &(n).entry, &(n).entry }, \ .func = (f), \ __WORK_INIT_LOCKDEP_MAP(#n, &(n)) \ @@ -91,6 +93,14 @@ struct execute_work { #define PREPARE_DELAYED_WORK(_work, _func) \ PREPARE_WORK(&(_work)->work, (_func)) +#ifdef CONFIG_DEBUG_OBJECTS_WORK +extern void __init_work(struct work_struct *work, int onstack); +extern void destroy_work_on_stack(struct work_struct *work); +#else +static inline void __init_work(struct work_struct *work, int onstack) { } +static inline void destroy_work_on_stack(struct work_struct *work) { } +#endif + /* * initialize all of a work item in one go * @@ -99,24 +109,36 @@ struct execute_work { * to generate better code. */ #ifdef CONFIG_LOCKDEP -#define INIT_WORK(_work, _func) \ +#define __INIT_WORK(_work, _func, _onstack) \ do { \ static struct lock_class_key __key; \ \ + __init_work((_work), _onstack); \ (_work)->data = (atomic_long_t) WORK_DATA_INIT(); \ lockdep_init_map(&(_work)->lockdep_map, #_work, &__key, 0);\ INIT_LIST_HEAD(&(_work)->entry); \ PREPARE_WORK((_work), (_func)); \ } while (0) #else -#define INIT_WORK(_work, _func) \ +#define __INIT_WORK(_work, _func, _onstack) \ do { \ + __init_work((_work), _onstack); \ (_work)->data = (atomic_long_t) WORK_DATA_INIT(); \ INIT_LIST_HEAD(&(_work)->entry); \ PREPARE_WORK((_work), (_func)); \ } while (0) #endif +#define INIT_WORK(_work, _func) \ + do { \ + __INIT_WORK((_work), (_func), 0); \ + } while (0) + +#define INIT_WORK_ON_STACK(_work, _func) \ + do { \ + __INIT_WORK((_work), (_func), 1); \ + } while (0) + #define INIT_DELAYED_WORK(_work, _func) \ do { \ INIT_WORK(&(_work)->work, (_func)); \ @@ -125,22 +147,16 @@ struct execute_work { #define INIT_DELAYED_WORK_ON_STACK(_work, _func) \ do { \ - INIT_WORK(&(_work)->work, (_func)); \ + INIT_WORK_ON_STACK(&(_work)->work, (_func)); \ init_timer_on_stack(&(_work)->timer); \ } while (0) -#define INIT_DELAYED_WORK_DEFERRABLE(_work, _func) \ +#define INIT_DELAYED_WORK_DEFERRABLE(_work, _func) \ do { \ INIT_WORK(&(_work)->work, (_func)); \ init_timer_deferrable(&(_work)->timer); \ } while (0) -#define INIT_DELAYED_WORK_ON_STACK(_work, _func) \ - do { \ - INIT_WORK(&(_work)->work, (_func)); \ - init_timer_on_stack(&(_work)->timer); \ - } while (0) - /** * work_pending - Find out whether a work item is currently pending * @work: The work item in question diff --git a/include/net/compat.h b/include/net/compat.h index 3c7d4e38fa1d3011d620e6cc1528e8ff39562ac8..28d5428ec6a21dbe8aef4663f4777d771cff1078 100644 --- a/include/net/compat.h +++ b/include/net/compat.h @@ -46,7 +46,7 @@ extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsi extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned); extern asmlinkage long compat_sys_recvmmsg(int, struct compat_mmsghdr __user *, unsigned, unsigned, - struct timespec __user *); + struct compat_timespec __user *); extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *); extern int put_cmsg_compat(struct msghdr*, int, int, int, void *); diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index 92838d3a1ab7e936e4e70eca0423a0cb07f76715..e46674d5daea2c8f08c708c19e1211ef3b71d0b2 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -53,7 +53,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk) return inet6_ehashfn(net, laddr, lport, faddr, fport); } -extern void __inet6_hash(struct sock *sk); +extern int __inet6_hash(struct sock *sk, struct inet_timewait_sock *twp); /* * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 41cbddd25b7058235d58a4e1f35b9e376f111e7f..74358d1b3f439ba6f995ceb0c928730f8c180252 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -251,7 +251,7 @@ extern void inet_put_port(struct sock *sk); void inet_hashinfo_init(struct inet_hashinfo *h); -extern void __inet_hash_nolisten(struct sock *sk); +extern int __inet_hash_nolisten(struct sock *sk, struct inet_timewait_sock *tw); extern void inet_hash(struct sock *sk); extern void inet_unhash(struct sock *sk); @@ -391,10 +391,12 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo, } extern int __inet_hash_connect(struct inet_timewait_death_row *death_row, - struct sock *sk, u32 port_offset, + struct sock *sk, + u32 port_offset, int (*check_established)(struct inet_timewait_death_row *, struct sock *, __u16, struct inet_timewait_sock **), - void (*hash)(struct sock *sk)); + int (*hash)(struct sock *sk, struct inet_timewait_sock *twp)); + extern int inet_hash_connect(struct inet_timewait_death_row *death_row, struct sock *sk); #endif /* _INET_HASHTABLES_H */ diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index b801ade2295ef8af242b97a07393b63c35ab8195..79f67eae8a7e212f30e5b89e09ede8b4d21a245b 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h @@ -201,6 +201,9 @@ extern void inet_twsk_put(struct inet_timewait_sock *tw); extern int inet_twsk_unhash(struct inet_timewait_sock *tw); +extern int inet_twsk_bind_unhash(struct inet_timewait_sock *tw, + struct inet_hashinfo *hashinfo); + extern struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int state); diff --git a/include/net/neighbour.h b/include/net/neighbour.h index 0302f31a2fb7e53956f089efac74848fbd15466d..b0173202cad96f3a8aa55df85d16b2d11a62b608 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -88,12 +88,7 @@ struct neigh_statistics { unsigned long unres_discards; /* number of unresolved drops */ }; -#define NEIGH_CACHE_STAT_INC(tbl, field) \ - do { \ - preempt_disable(); \ - (per_cpu_ptr((tbl)->stats, smp_processor_id())->field)++; \ - preempt_enable(); \ - } while (0) +#define NEIGH_CACHE_STAT_INC(tbl, field) this_cpu_inc((tbl)->stats->field) struct neighbour { struct neighbour *next; diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 5cf7270e3ffc3e94c6d80bd79168056e9c1e539f..a0904adfb8f7aba343152a5af47aa7e818c3b39d 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -293,11 +293,11 @@ extern unsigned int nf_conntrack_htable_size; extern unsigned int nf_conntrack_max; #define NF_CT_STAT_INC(net, count) \ - (per_cpu_ptr((net)->ct.stat, raw_smp_processor_id())->count++) + __this_cpu_inc((net)->ct.stat->count) #define NF_CT_STAT_INC_ATOMIC(net, count) \ do { \ local_bh_disable(); \ - per_cpu_ptr((net)->ct.stat, raw_smp_processor_id())->count++; \ + __this_cpu_inc((net)->ct.stat->count); \ local_bh_enable(); \ } while (0) diff --git a/include/net/snmp.h b/include/net/snmp.h index 8c842e06bec86ad77cbe2f612d1a29d09bb3b421..f0d756f2ac99773f573613d145752b2984dddd13 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h @@ -136,45 +136,31 @@ struct linux_xfrm_mib { #define SNMP_STAT_BHPTR(name) (name[0]) #define SNMP_STAT_USRPTR(name) (name[1]) -#define SNMP_INC_STATS_BH(mib, field) \ - (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field]++) -#define SNMP_INC_STATS_USER(mib, field) \ - do { \ - per_cpu_ptr(mib[1], get_cpu())->mibs[field]++; \ - put_cpu(); \ - } while (0) -#define SNMP_INC_STATS(mib, field) \ - do { \ - per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]++; \ - put_cpu(); \ - } while (0) -#define SNMP_DEC_STATS(mib, field) \ - do { \ - per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]--; \ - put_cpu(); \ - } while (0) -#define SNMP_ADD_STATS(mib, field, addend) \ - do { \ - per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field] += addend; \ - put_cpu(); \ - } while (0) -#define SNMP_ADD_STATS_BH(mib, field, addend) \ - (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend) -#define SNMP_ADD_STATS_USER(mib, field, addend) \ - do { \ - per_cpu_ptr(mib[1], get_cpu())->mibs[field] += addend; \ - put_cpu(); \ - } while (0) +#define SNMP_INC_STATS_BH(mib, field) \ + __this_cpu_inc(mib[0]->mibs[field]) +#define SNMP_INC_STATS_USER(mib, field) \ + this_cpu_inc(mib[1]->mibs[field]) +#define SNMP_INC_STATS(mib, field) \ + this_cpu_inc(mib[!in_softirq()]->mibs[field]) +#define SNMP_DEC_STATS(mib, field) \ + this_cpu_dec(mib[!in_softirq()]->mibs[field]) +#define SNMP_ADD_STATS_BH(mib, field, addend) \ + __this_cpu_add(mib[0]->mibs[field], addend) +#define SNMP_ADD_STATS_USER(mib, field, addend) \ + this_cpu_add(mib[1]->mibs[field], addend) #define SNMP_UPD_PO_STATS(mib, basefield, addend) \ do { \ - __typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], get_cpu());\ + __typeof__(mib[0]) ptr; \ + preempt_disable(); \ + ptr = this_cpu_ptr((mib)[!in_softirq()]); \ ptr->mibs[basefield##PKTS]++; \ ptr->mibs[basefield##OCTETS] += addend;\ - put_cpu(); \ + preempt_enable(); \ } while (0) #define SNMP_UPD_PO_STATS_BH(mib, basefield, addend) \ do { \ - __typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id());\ + __typeof__(mib[0]) ptr = \ + __this_cpu_ptr((mib)[!in_softirq()]); \ ptr->mibs[basefield##PKTS]++; \ ptr->mibs[basefield##OCTETS] += addend;\ } while (0) diff --git a/include/net/tcp.h b/include/net/tcp.h index 5740b85bc5a0978349eb042caf17ec6255c98158..1b6f7d348ceed85dac011ccfc8bc7f0a1dfee1cb 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1261,29 +1261,6 @@ static inline struct sk_buff *tcp_write_queue_prev(struct sock *sk, struct sk_bu #define tcp_for_write_queue_from_safe(skb, tmp, sk) \ skb_queue_walk_from_safe(&(sk)->sk_write_queue, skb, tmp) -/* This function calculates a "timeout" which is equivalent to the timeout of a - * TCP connection after "boundary" unsuccessful, exponentially backed-off - * retransmissions with an initial RTO of TCP_RTO_MIN. - */ -static inline bool retransmits_timed_out(const struct sock *sk, - unsigned int boundary) -{ - unsigned int timeout, linear_backoff_thresh; - - if (!inet_csk(sk)->icsk_retransmits) - return false; - - linear_backoff_thresh = ilog2(TCP_RTO_MAX/TCP_RTO_MIN); - - if (boundary <= linear_backoff_thresh) - timeout = ((2 << boundary) - 1) * TCP_RTO_MIN; - else - timeout = ((2 << linear_backoff_thresh) - 1) * TCP_RTO_MIN + - (boundary - linear_backoff_thresh) * TCP_RTO_MAX; - - return (tcp_time_stamp - tcp_sk(sk)->retrans_stamp) >= timeout; -} - static inline struct sk_buff *tcp_send_head(struct sock *sk) { return sk->sk_send_head; diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index afc2bfb9e917bcb63ebda29847b00e848111d8be..75fa3530345ba362f7460d18e7749ed08f3654c1 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -126,8 +126,8 @@ typedef struct irq_req_t { #define IRQ_TYPE_TIME 0x01 #define IRQ_TYPE_DYNAMIC_SHARING 0x02 #define IRQ_FORCED_PULSE 0x04 -#define IRQ_FIRST_SHARED 0x08 -//#define IRQ_HANDLE_PRESENT 0x10 +#define IRQ_FIRST_SHARED 0x08 /* unused */ +#define IRQ_HANDLE_PRESENT 0x10 /* unused */ #define IRQ_PULSE_ALLOCATED 0x100 /* Bits in IRQInfo1 field */ diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index d403c12f797820928bb040ff166e9469c532ba81..ee148573c11435750dc26e12d135b03a584d3e08 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -82,7 +82,7 @@ struct pcmcia_device { /* the hardware "function" device; certain subdevices can * share one hardware "function" device. */ u8 func; - struct config_t* function_config; + struct config_t *function_config; struct list_head socket_device_list; @@ -121,14 +121,14 @@ struct pcmcia_device { u16 manf_id; u16 card_id; - char * prod_id[4]; + char *prod_id[4]; u64 dma_mask; struct device dev; #ifdef CONFIG_PCMCIA_IOCTL /* device driver wanted by cardmgr */ - struct pcmcia_driver * cardmgr; + struct pcmcia_driver *cardmgr; #endif /* data private to drivers */ diff --git a/include/pcmcia/mem_op.h b/include/pcmcia/mem_op.h index 8d19b9401a5bba76d7f7614728e6d7496c78c998..0fa06e5d5376463c8d8f8f33e990daf9801b3a72 100644 --- a/include/pcmcia/mem_op.h +++ b/include/pcmcia/mem_op.h @@ -15,8 +15,8 @@ #ifndef _LINUX_MEM_OP_H #define _LINUX_MEM_OP_H +#include #include -#include /* If UNSAFE_MEMCPY is defined, we use the (optimized) system routines diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index 7c23be706f128bbc02365e868687aa3dbcc73047..cbfba885eb85b8376dcc60bb0fb4608944b35015 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -154,7 +154,7 @@ struct pcmcia_socket { struct list_head socket_list; struct completion socket_released; - /* deprecated */ + /* deprecated */ unsigned int sock; /* socket number */ @@ -164,7 +164,7 @@ struct pcmcia_socket { u_int map_size; u_int io_offset; u_int pci_irq; - struct pci_dev * cb_dev; + struct pci_dev *cb_dev; /* socket setup is done so resources should be able to be allocated. @@ -179,9 +179,9 @@ struct pcmcia_socket { u8 reserved:5; /* socket operations */ - struct pccard_operations * ops; - struct pccard_resource_ops * resource_ops; - void * resource_data; + struct pccard_operations *ops; + struct pccard_resource_ops *resource_ops; + void *resource_data; /* Zoom video behaviour is so chip specific its not worth adding this to _ops */ @@ -245,7 +245,7 @@ struct pcmcia_socket { /* cardbus (32-bit) */ #ifdef CONFIG_CARDBUS - struct resource * cb_cis_res; + struct resource *cb_cis_res; void __iomem *cb_cis_virt; #endif /* CONFIG_CARDBUS */ diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h index 318f76535bd44c888d2a1045f0f4a520d3c5799a..d0b6cd3afb2fb443d5bd4220f94b5bb698131ea9 100644 --- a/include/trace/events/ext4.h +++ b/include/trace/events/ext4.h @@ -38,7 +38,7 @@ TRACE_EVENT(ext4_free_inode, __entry->blocks = inode->i_blocks; ), - TP_printk("dev %s ino %lu mode %d uid %u gid %u blocks %llu", + TP_printk("dev %s ino %lu mode 0%o uid %u gid %u blocks %llu", jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino, __entry->mode, __entry->uid, __entry->gid, (unsigned long long) __entry->blocks) @@ -61,7 +61,7 @@ TRACE_EVENT(ext4_request_inode, __entry->mode = mode; ), - TP_printk("dev %s dir %lu mode %d", + TP_printk("dev %s dir %lu mode 0%o", jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->dir, __entry->mode) ); @@ -85,7 +85,7 @@ TRACE_EVENT(ext4_allocate_inode, __entry->mode = mode; ), - TP_printk("dev %s ino %lu dir %lu mode %d", + TP_printk("dev %s ino %lu dir %lu mode 0%o", jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino, (unsigned long) __entry->dir, __entry->mode) ); @@ -305,7 +305,6 @@ TRACE_EVENT(ext4_da_writepages_result, __field( int, ret ) __field( int, pages_written ) __field( long, pages_skipped ) - __field( char, encountered_congestion ) __field( char, more_io ) __field( char, no_nrwrite_index_update ) __field( pgoff_t, writeback_index ) @@ -317,17 +316,16 @@ TRACE_EVENT(ext4_da_writepages_result, __entry->ret = ret; __entry->pages_written = pages_written; __entry->pages_skipped = wbc->pages_skipped; - __entry->encountered_congestion = wbc->encountered_congestion; __entry->more_io = wbc->more_io; __entry->no_nrwrite_index_update = wbc->no_nrwrite_index_update; __entry->writeback_index = inode->i_mapping->writeback_index; ), - TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld congestion %d more_io %d no_nrwrite_index_update %d writeback_index %lu", + TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld more_io %d no_nrwrite_index_update %d writeback_index %lu", jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino, __entry->ret, __entry->pages_written, __entry->pages_skipped, - __entry->encountered_congestion, __entry->more_io, + __entry->more_io, __entry->no_nrwrite_index_update, (unsigned long) __entry->writeback_index) ); @@ -591,30 +589,32 @@ TRACE_EVENT(ext4_allocate_blocks, TRACE_EVENT(ext4_free_blocks, TP_PROTO(struct inode *inode, __u64 block, unsigned long count, - int metadata), + int flags), - TP_ARGS(inode, block, count, metadata), + TP_ARGS(inode, block, count, flags), TP_STRUCT__entry( __field( dev_t, dev ) __field( ino_t, ino ) + __field( umode_t, mode ) __field( __u64, block ) __field( unsigned long, count ) - __field( int, metadata ) - + __field( int, flags ) ), TP_fast_assign( __entry->dev = inode->i_sb->s_dev; __entry->ino = inode->i_ino; + __entry->mode = inode->i_mode; __entry->block = block; __entry->count = count; - __entry->metadata = metadata; + __entry->flags = flags; ), - TP_printk("dev %s ino %lu block %llu count %lu metadata %d", + TP_printk("dev %s ino %lu mode 0%o block %llu count %lu flags %d", jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino, - __entry->block, __entry->count, __entry->metadata) + __entry->mode, __entry->block, __entry->count, + __entry->flags) ); TRACE_EVENT(ext4_sync_file, @@ -848,6 +848,32 @@ TRACE_EVENT(ext4_mballoc_free, __entry->result_len, __entry->result_logical) ); +TRACE_EVENT(ext4_forget, + TP_PROTO(struct inode *inode, int is_metadata, __u64 block), + + TP_ARGS(inode, is_metadata, block), + + TP_STRUCT__entry( + __field( dev_t, dev ) + __field( ino_t, ino ) + __field( umode_t, mode ) + __field( int, is_metadata ) + __field( __u64, block ) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->mode = inode->i_mode; + __entry->is_metadata = is_metadata; + __entry->block = block; + ), + + TP_printk("dev %s ino %lu mode 0%o is_metadata %d block %llu", + jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino, + __entry->mode, __entry->is_metadata, __entry->block) +); + #endif /* _TRACE_EXT4_H */ /* This part must be outside protection */ diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h index e5ce87a0498da94355af6e0cfdda0bb88e843cec..9496b965d62ad9dd39929ccc7e471c7fcf2d374a 100644 --- a/include/trace/events/timer.h +++ b/include/trace/events/timer.h @@ -301,8 +301,8 @@ TRACE_EVENT(itimer_state, __entry->interval_usec = value->it_interval.tv_usec; ), - TP_printk("which=%d expires=%lu it_value=%lu.%lu it_interval=%lu.%lu", - __entry->which, __entry->expires, + TP_printk("which=%d expires=%llu it_value=%ld.%ld it_interval=%ld.%ld", + __entry->which, (unsigned long long)__entry->expires, __entry->value_sec, __entry->value_usec, __entry->interval_sec, __entry->interval_usec) ); @@ -331,8 +331,8 @@ TRACE_EVENT(itimer_expire, __entry->pid = pid_nr(pid); ), - TP_printk("which=%d pid=%d now=%lu", __entry->which, - (int) __entry->pid, __entry->now) + TP_printk("which=%d pid=%d now=%llu", __entry->which, + (int) __entry->pid, (unsigned long long)__entry->now) ); #endif /* _TRACE_TIMER_H */ diff --git a/include/xen/xen.h b/include/xen/xen.h new file mode 100644 index 0000000000000000000000000000000000000000..a16402418d314710cf8281a28b5023cc06be94a1 --- /dev/null +++ b/include/xen/xen.h @@ -0,0 +1,32 @@ +#ifndef _XEN_XEN_H +#define _XEN_XEN_H + +enum xen_domain_type { + XEN_NATIVE, /* running on bare hardware */ + XEN_PV_DOMAIN, /* running in a PV domain */ + XEN_HVM_DOMAIN, /* running in a Xen hvm domain */ +}; + +#ifdef CONFIG_XEN +extern enum xen_domain_type xen_domain_type; +#else +#define xen_domain_type XEN_NATIVE +#endif + +#define xen_domain() (xen_domain_type != XEN_NATIVE) +#define xen_pv_domain() (xen_domain() && \ + xen_domain_type == XEN_PV_DOMAIN) +#define xen_hvm_domain() (xen_domain() && \ + xen_domain_type == XEN_HVM_DOMAIN) + +#ifdef CONFIG_XEN_DOM0 +#include +#include + +#define xen_initial_domain() (xen_pv_domain() && \ + xen_start_info->flags & SIF_INITDOMAIN) +#else /* !CONFIG_XEN_DOM0 */ +#define xen_initial_domain() (0) +#endif /* CONFIG_XEN_DOM0 */ + +#endif /* _XEN_XEN_H */ diff --git a/ipc/shm.c b/ipc/shm.c index 464694e0aa4a19c74b973a2a69f0d88049b9c512..11bec626c228c98d5f3e0512f9c6f0dd40f424dc 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -290,28 +290,28 @@ static unsigned long shm_get_unmapped_area(struct file *file, unsigned long flags) { struct shm_file_data *sfd = shm_file_data(file); - return get_unmapped_area(sfd->file, addr, len, pgoff, flags); -} - -int is_file_shm_hugepages(struct file *file) -{ - int ret = 0; - - if (file->f_op == &shm_file_operations) { - struct shm_file_data *sfd; - sfd = shm_file_data(file); - ret = is_file_hugepages(sfd->file); - } - return ret; + return sfd->file->f_op->get_unmapped_area(sfd->file, addr, len, + pgoff, flags); } static const struct file_operations shm_file_operations = { .mmap = shm_mmap, .fsync = shm_fsync, .release = shm_release, +}; + +static const struct file_operations shm_file_operations_huge = { + .mmap = shm_mmap, + .fsync = shm_fsync, + .release = shm_release, .get_unmapped_area = shm_get_unmapped_area, }; +int is_file_shm_hugepages(struct file *file) +{ + return file->f_op == &shm_file_operations_huge; +} + static const struct vm_operations_struct shm_vm_ops = { .open = shm_open, /* callback for a new vm-area open */ .close = shm_close, /* callback for when the vm-area is released */ @@ -889,7 +889,10 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) if (!sfd) goto out_put_dentry; - file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations); + file = alloc_file(path.mnt, path.dentry, f_mode, + is_file_hugepages(shp->shm_file) ? + &shm_file_operations_huge : + &shm_file_operations); if (!file) goto out_free; ima_counts_get(file); diff --git a/kernel/cpu.c b/kernel/cpu.c index 7c4e2713df0a9b12eb31c47b176134516968f6a2..291ac586f37ff93e047391be46b3db90d5f80445 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -212,6 +212,8 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls); if (err == NOTIFY_BAD) { + set_cpu_active(cpu, true); + nr_calls--; __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod, hcpu, nr_calls, NULL); @@ -223,11 +225,11 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) /* Ensure that we are not runnable on dying cpu */ cpumask_copy(old_allowed, ¤t->cpus_allowed); - set_cpus_allowed_ptr(current, - cpumask_of(cpumask_any_but(cpu_online_mask, cpu))); + set_cpus_allowed_ptr(current, cpu_active_mask); err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); if (err) { + set_cpu_active(cpu, true); /* CPU didn't die: tell everyone. Can't complain. */ if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod, hcpu) == NOTIFY_BAD) @@ -292,9 +294,6 @@ int __ref cpu_down(unsigned int cpu) err = _cpu_down(cpu, 0); - if (cpu_online(cpu)) - set_cpu_active(cpu, true); - out: cpu_maps_update_done(); stop_machine_destroy(); @@ -387,6 +386,15 @@ int disable_nonboot_cpus(void) * with the userspace trying to use the CPU hotplug at the same time */ cpumask_clear(frozen_cpus); + + for_each_online_cpu(cpu) { + if (cpu == first_cpu) + continue; + set_cpu_active(cpu, false); + } + + synchronize_sched(); + printk("Disabling non-boot CPUs ...\n"); for_each_online_cpu(cpu) { if (cpu == first_cpu) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 3cf2183b472def78cd42b40d1986977dc8a287be..ba401fab459f94a42010f6175b2b69c490920645 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -737,7 +737,7 @@ static void do_rebuild_sched_domains(struct work_struct *unused) { } -static int generate_sched_domains(struct cpumask **domains, +static int generate_sched_domains(cpumask_var_t **domains, struct sched_domain_attr **attributes) { *domains = NULL; @@ -872,7 +872,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, if (retval < 0) return retval; - if (!cpumask_subset(trialcs->cpus_allowed, cpu_online_mask)) + if (!cpumask_subset(trialcs->cpus_allowed, cpu_active_mask)) return -EINVAL; } retval = validate_change(cs, trialcs); @@ -2010,7 +2010,7 @@ static void scan_for_empty_cpusets(struct cpuset *root) } /* Continue past cpusets with all cpus, mems online */ - if (cpumask_subset(cp->cpus_allowed, cpu_online_mask) && + if (cpumask_subset(cp->cpus_allowed, cpu_active_mask) && nodes_subset(cp->mems_allowed, node_states[N_HIGH_MEMORY])) continue; @@ -2019,7 +2019,7 @@ static void scan_for_empty_cpusets(struct cpuset *root) /* Remove offline cpus and mems from this cpuset. */ mutex_lock(&callback_mutex); cpumask_and(cp->cpus_allowed, cp->cpus_allowed, - cpu_online_mask); + cpu_active_mask); nodes_and(cp->mems_allowed, cp->mems_allowed, node_states[N_HIGH_MEMORY]); mutex_unlock(&callback_mutex); @@ -2057,8 +2057,10 @@ static int cpuset_track_online_cpus(struct notifier_block *unused_nb, switch (phase) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: - case CPU_DEAD: - case CPU_DEAD_FROZEN: + case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: + case CPU_DOWN_FAILED: + case CPU_DOWN_FAILED_FROZEN: break; default: @@ -2067,7 +2069,7 @@ static int cpuset_track_online_cpus(struct notifier_block *unused_nb, cgroup_lock(); mutex_lock(&callback_mutex); - cpumask_copy(top_cpuset.cpus_allowed, cpu_online_mask); + cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask); mutex_unlock(&callback_mutex); scan_for_empty_cpusets(&top_cpuset); ndoms = generate_sched_domains(&doms, &attr); @@ -2114,7 +2116,7 @@ static int cpuset_track_online_nodes(struct notifier_block *self, void __init cpuset_init_smp(void) { - cpumask_copy(top_cpuset.cpus_allowed, cpu_online_mask); + cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask); top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; hotcpu_notifier(cpuset_track_online_cpus, 0); diff --git a/kernel/exit.c b/kernel/exit.c index 1143012951e98433c9bed5011d6f87ebe32d9bbd..6f50ef55a6f39221cd66aff3c44c476cd5a2cf3b 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -971,7 +971,7 @@ NORET_TYPE void do_exit(long code) exit_thread(); cgroup_exit(tsk, 1); - if (group_dead && tsk->signal->leader) + if (group_dead) disassociate_ctty(1); module_put(task_thread_info(tsk)->exec_domain->module); diff --git a/kernel/futex.c b/kernel/futex.c index fb65e822fc41ae698c282aeadc6933b411aa8a78..d73ef1f3e55db35748c444701ff856219612b93b 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -304,8 +304,14 @@ void put_futex_key(int fshared, union futex_key *key) */ static int fault_in_user_writeable(u32 __user *uaddr) { - int ret = get_user_pages(current, current->mm, (unsigned long)uaddr, - 1, 1, 0, NULL, NULL); + struct mm_struct *mm = current->mm; + int ret; + + down_read(&mm->mmap_sem); + ret = get_user_pages(current, mm, (unsigned long)uaddr, + 1, 1, 0, NULL, NULL); + up_read(&mm->mmap_sem); + return ret < 0 ? ret : 0; } diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index ede52770812389282650012fc4cc0a763a435e13..d2f9239dc6ba51f7d2652f948b46fb01153f8aa6 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -557,7 +557,7 @@ hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal) static int hrtimer_reprogram(struct hrtimer *timer, struct hrtimer_clock_base *base) { - ktime_t *expires_next = &__get_cpu_var(hrtimer_bases).expires_next; + struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); ktime_t expires = ktime_sub(hrtimer_get_expires(timer), base->offset); int res; @@ -582,7 +582,16 @@ static int hrtimer_reprogram(struct hrtimer *timer, if (expires.tv64 < 0) return -ETIME; - if (expires.tv64 >= expires_next->tv64) + if (expires.tv64 >= cpu_base->expires_next.tv64) + return 0; + + /* + * If a hang was detected in the last timer interrupt then we + * do not schedule a timer which is earlier than the expiry + * which we enforced in the hang detection. We want the system + * to make progress. + */ + if (cpu_base->hang_detected) return 0; /* @@ -590,7 +599,7 @@ static int hrtimer_reprogram(struct hrtimer *timer, */ res = tick_program_event(expires, 0); if (!IS_ERR_VALUE(res)) - *expires_next = expires; + cpu_base->expires_next = expires; return res; } @@ -747,17 +756,33 @@ static inline void hrtimer_init_timer_hres(struct hrtimer *timer) { } #endif /* CONFIG_HIGH_RES_TIMERS */ -#ifdef CONFIG_TIMER_STATS -void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer, void *addr) +static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) { +#ifdef CONFIG_TIMER_STATS if (timer->start_site) return; - - timer->start_site = addr; + timer->start_site = __builtin_return_address(0); memcpy(timer->start_comm, current->comm, TASK_COMM_LEN); timer->start_pid = current->pid; +#endif } + +static inline void timer_stats_hrtimer_clear_start_info(struct hrtimer *timer) +{ +#ifdef CONFIG_TIMER_STATS + timer->start_site = NULL; +#endif +} + +static inline void timer_stats_account_hrtimer(struct hrtimer *timer) +{ +#ifdef CONFIG_TIMER_STATS + if (likely(!timer_stats_active)) + return; + timer_stats_update_stats(timer, timer->start_pid, timer->start_site, + timer->function, timer->start_comm, 0); #endif +} /* * Counterpart to lock_hrtimer_base above: @@ -1217,30 +1242,6 @@ static void __run_hrtimer(struct hrtimer *timer, ktime_t *now) #ifdef CONFIG_HIGH_RES_TIMERS -static int force_clock_reprogram; - -/* - * After 5 iteration's attempts, we consider that hrtimer_interrupt() - * is hanging, which could happen with something that slows the interrupt - * such as the tracing. Then we force the clock reprogramming for each future - * hrtimer interrupts to avoid infinite loops and use the min_delta_ns - * threshold that we will overwrite. - * The next tick event will be scheduled to 3 times we currently spend on - * hrtimer_interrupt(). This gives a good compromise, the cpus will spend - * 1/4 of their time to process the hrtimer interrupts. This is enough to - * let it running without serious starvation. - */ - -static inline void -hrtimer_interrupt_hanging(struct clock_event_device *dev, - ktime_t try_time) -{ - force_clock_reprogram = 1; - dev->min_delta_ns = (unsigned long)try_time.tv64 * 3; - printk(KERN_WARNING "hrtimer: interrupt too slow, " - "forcing clock min delta to %llu ns\n", - (unsigned long long) dev->min_delta_ns); -} /* * High resolution timer interrupt * Called with interrupts disabled @@ -1249,21 +1250,15 @@ void hrtimer_interrupt(struct clock_event_device *dev) { struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); struct hrtimer_clock_base *base; - ktime_t expires_next, now; - int nr_retries = 0; - int i; + ktime_t expires_next, now, entry_time, delta; + int i, retries = 0; BUG_ON(!cpu_base->hres_active); cpu_base->nr_events++; dev->next_event.tv64 = KTIME_MAX; - retry: - /* 5 retries is enough to notice a hang */ - if (!(++nr_retries % 5)) - hrtimer_interrupt_hanging(dev, ktime_sub(ktime_get(), now)); - - now = ktime_get(); - + entry_time = now = ktime_get(); +retry: expires_next.tv64 = KTIME_MAX; spin_lock(&cpu_base->lock); @@ -1325,10 +1320,48 @@ void hrtimer_interrupt(struct clock_event_device *dev) spin_unlock(&cpu_base->lock); /* Reprogramming necessary ? */ - if (expires_next.tv64 != KTIME_MAX) { - if (tick_program_event(expires_next, force_clock_reprogram)) - goto retry; + if (expires_next.tv64 == KTIME_MAX || + !tick_program_event(expires_next, 0)) { + cpu_base->hang_detected = 0; + return; } + + /* + * The next timer was already expired due to: + * - tracing + * - long lasting callbacks + * - being scheduled away when running in a VM + * + * We need to prevent that we loop forever in the hrtimer + * interrupt routine. We give it 3 attempts to avoid + * overreacting on some spurious event. + */ + now = ktime_get(); + cpu_base->nr_retries++; + if (++retries < 3) + goto retry; + /* + * Give the system a chance to do something else than looping + * here. We stored the entry time, so we know exactly how long + * we spent here. We schedule the next event this amount of + * time away. + */ + cpu_base->nr_hangs++; + cpu_base->hang_detected = 1; + delta = ktime_sub(now, entry_time); + if (delta.tv64 > cpu_base->max_hang_time.tv64) + cpu_base->max_hang_time = delta; + /* + * Limit it to a sensible value as we enforce a longer + * delay. Give the CPU at least 100ms to catch up. + */ + if (delta.tv64 > 100 * NSEC_PER_MSEC) + expires_next = ktime_add_ns(now, 100 * NSEC_PER_MSEC); + else + expires_next = ktime_add(now, delta); + tick_program_event(expires_next, 1); + printk_once(KERN_WARNING "hrtimer: interrupt took %llu ns\n", + ktime_to_ns(delta)); } /* diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c index cf5ee1628411cb58ee249e8ccec84e3c08c53516..366eedf949c0a47380af9050463dae76431aa063 100644 --- a/kernel/hw_breakpoint.c +++ b/kernel/hw_breakpoint.c @@ -52,7 +52,7 @@ static DEFINE_PER_CPU(unsigned int, nr_cpu_bp_pinned); /* Number of pinned task breakpoints in a cpu */ -static DEFINE_PER_CPU(unsigned int, task_bp_pinned[HBP_NUM]); +static DEFINE_PER_CPU(unsigned int, nr_task_bp_pinned[HBP_NUM]); /* Number of non-pinned cpu/task breakpoints in a cpu */ static DEFINE_PER_CPU(unsigned int, nr_bp_flexible); @@ -73,7 +73,7 @@ static DEFINE_MUTEX(nr_bp_mutex); static unsigned int max_task_bp_pinned(int cpu) { int i; - unsigned int *tsk_pinned = per_cpu(task_bp_pinned, cpu); + unsigned int *tsk_pinned = per_cpu(nr_task_bp_pinned, cpu); for (i = HBP_NUM -1; i >= 0; i--) { if (tsk_pinned[i] > 0) @@ -83,15 +83,51 @@ static unsigned int max_task_bp_pinned(int cpu) return 0; } +static int task_bp_pinned(struct task_struct *tsk) +{ + struct perf_event_context *ctx = tsk->perf_event_ctxp; + struct list_head *list; + struct perf_event *bp; + unsigned long flags; + int count = 0; + + if (WARN_ONCE(!ctx, "No perf context for this task")) + return 0; + + list = &ctx->event_list; + + spin_lock_irqsave(&ctx->lock, flags); + + /* + * The current breakpoint counter is not included in the list + * at the open() callback time + */ + list_for_each_entry(bp, list, event_entry) { + if (bp->attr.type == PERF_TYPE_BREAKPOINT) + count++; + } + + spin_unlock_irqrestore(&ctx->lock, flags); + + return count; +} + /* * Report the number of pinned/un-pinned breakpoints we have in * a given cpu (cpu > -1) or in all of them (cpu = -1). */ -static void fetch_bp_busy_slots(struct bp_busy_slots *slots, int cpu) +static void +fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp) { + int cpu = bp->cpu; + struct task_struct *tsk = bp->ctx->task; + if (cpu >= 0) { slots->pinned = per_cpu(nr_cpu_bp_pinned, cpu); - slots->pinned += max_task_bp_pinned(cpu); + if (!tsk) + slots->pinned += max_task_bp_pinned(cpu); + else + slots->pinned += task_bp_pinned(tsk); slots->flexible = per_cpu(nr_bp_flexible, cpu); return; @@ -101,7 +137,10 @@ static void fetch_bp_busy_slots(struct bp_busy_slots *slots, int cpu) unsigned int nr; nr = per_cpu(nr_cpu_bp_pinned, cpu); - nr += max_task_bp_pinned(cpu); + if (!tsk) + nr += max_task_bp_pinned(cpu); + else + nr += task_bp_pinned(tsk); if (nr > slots->pinned) slots->pinned = nr; @@ -118,35 +157,12 @@ static void fetch_bp_busy_slots(struct bp_busy_slots *slots, int cpu) */ static void toggle_bp_task_slot(struct task_struct *tsk, int cpu, bool enable) { - int count = 0; - struct perf_event *bp; - struct perf_event_context *ctx = tsk->perf_event_ctxp; unsigned int *tsk_pinned; - struct list_head *list; - unsigned long flags; - - if (WARN_ONCE(!ctx, "No perf context for this task")) - return; - - list = &ctx->event_list; - - spin_lock_irqsave(&ctx->lock, flags); - - /* - * The current breakpoint counter is not included in the list - * at the open() callback time - */ - list_for_each_entry(bp, list, event_entry) { - if (bp->attr.type == PERF_TYPE_BREAKPOINT) - count++; - } + int count = 0; - spin_unlock_irqrestore(&ctx->lock, flags); + count = task_bp_pinned(tsk); - if (WARN_ONCE(count < 0, "No breakpoint counter found in the counter list")) - return; - - tsk_pinned = per_cpu(task_bp_pinned, cpu); + tsk_pinned = per_cpu(nr_task_bp_pinned, cpu); if (enable) { tsk_pinned[count]++; if (count > 0) @@ -193,7 +209,7 @@ static void toggle_bp_slot(struct perf_event *bp, bool enable) * - If attached to a single cpu, check: * * (per_cpu(nr_bp_flexible, cpu) || (per_cpu(nr_cpu_bp_pinned, cpu) - * + max(per_cpu(task_bp_pinned, cpu)))) < HBP_NUM + * + max(per_cpu(nr_task_bp_pinned, cpu)))) < HBP_NUM * * -> If there are already non-pinned counters in this cpu, it means * there is already a free slot for them. @@ -204,7 +220,7 @@ static void toggle_bp_slot(struct perf_event *bp, bool enable) * - If attached to every cpus, check: * * (per_cpu(nr_bp_flexible, *) || (max(per_cpu(nr_cpu_bp_pinned, *)) - * + max(per_cpu(task_bp_pinned, *)))) < HBP_NUM + * + max(per_cpu(nr_task_bp_pinned, *)))) < HBP_NUM * * -> This is roughly the same, except we check the number of per cpu * bp for every cpu and we keep the max one. Same for the per tasks @@ -216,7 +232,7 @@ static void toggle_bp_slot(struct perf_event *bp, bool enable) * - If attached to a single cpu, check: * * ((per_cpu(nr_bp_flexible, cpu) > 1) + per_cpu(nr_cpu_bp_pinned, cpu) - * + max(per_cpu(task_bp_pinned, cpu))) < HBP_NUM + * + max(per_cpu(nr_task_bp_pinned, cpu))) < HBP_NUM * * -> Same checks as before. But now the nr_bp_flexible, if any, must keep * one register at least (or they will never be fed). @@ -224,7 +240,7 @@ static void toggle_bp_slot(struct perf_event *bp, bool enable) * - If attached to every cpus, check: * * ((per_cpu(nr_bp_flexible, *) > 1) + max(per_cpu(nr_cpu_bp_pinned, *)) - * + max(per_cpu(task_bp_pinned, *))) < HBP_NUM + * + max(per_cpu(nr_task_bp_pinned, *))) < HBP_NUM */ int reserve_bp_slot(struct perf_event *bp) { @@ -233,7 +249,7 @@ int reserve_bp_slot(struct perf_event *bp) mutex_lock(&nr_bp_mutex); - fetch_bp_busy_slots(&slots, bp->cpu); + fetch_bp_busy_slots(&slots, bp); /* Flexible counters need to keep at least one slot */ if (slots.pinned + (!!slots.flexible) == HBP_NUM) { @@ -259,7 +275,7 @@ void release_bp_slot(struct perf_event *bp) } -int __register_perf_hw_breakpoint(struct perf_event *bp) +int register_perf_hw_breakpoint(struct perf_event *bp) { int ret; @@ -276,19 +292,12 @@ int __register_perf_hw_breakpoint(struct perf_event *bp) * This is a quick hack that will be removed soon, once we remove * the tmp breakpoints from ptrace */ - if (!bp->attr.disabled || bp->callback == perf_bp_event) + if (!bp->attr.disabled || !bp->overflow_handler) ret = arch_validate_hwbkpt_settings(bp, bp->ctx->task); return ret; } -int register_perf_hw_breakpoint(struct perf_event *bp) -{ - bp->callback = perf_bp_event; - - return __register_perf_hw_breakpoint(bp); -} - /** * register_user_hw_breakpoint - register a hardware breakpoint for user space * @attr: breakpoint attributes @@ -297,7 +306,7 @@ int register_perf_hw_breakpoint(struct perf_event *bp) */ struct perf_event * register_user_hw_breakpoint(struct perf_event_attr *attr, - perf_callback_t triggered, + perf_overflow_handler_t triggered, struct task_struct *tsk) { return perf_event_create_kernel_counter(attr, -1, tsk->pid, triggered); @@ -311,19 +320,40 @@ EXPORT_SYMBOL_GPL(register_user_hw_breakpoint); * @triggered: callback to trigger when we hit the breakpoint * @tsk: pointer to 'task_struct' of the process to which the address belongs */ -struct perf_event * -modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr, - perf_callback_t triggered, - struct task_struct *tsk) +int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr) { - /* - * FIXME: do it without unregistering - * - We don't want to lose our slot - * - If the new bp is incorrect, don't lose the older one - */ - unregister_hw_breakpoint(bp); + u64 old_addr = bp->attr.bp_addr; + int old_type = bp->attr.bp_type; + int old_len = bp->attr.bp_len; + int err = 0; - return perf_event_create_kernel_counter(attr, -1, tsk->pid, triggered); + perf_event_disable(bp); + + bp->attr.bp_addr = attr->bp_addr; + bp->attr.bp_type = attr->bp_type; + bp->attr.bp_len = attr->bp_len; + + if (attr->disabled) + goto end; + + err = arch_validate_hwbkpt_settings(bp, bp->ctx->task); + if (!err) + perf_event_enable(bp); + + if (err) { + bp->attr.bp_addr = old_addr; + bp->attr.bp_type = old_type; + bp->attr.bp_len = old_len; + if (!bp->attr.disabled) + perf_event_enable(bp); + + return err; + } + +end: + bp->attr.disabled = attr->disabled; + + return 0; } EXPORT_SYMBOL_GPL(modify_user_hw_breakpoint); @@ -348,7 +378,7 @@ EXPORT_SYMBOL_GPL(unregister_hw_breakpoint); */ struct perf_event ** register_wide_hw_breakpoint(struct perf_event_attr *attr, - perf_callback_t triggered) + perf_overflow_handler_t triggered) { struct perf_event **cpu_events, **pevent, *bp; long err; diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 7d70146340224b501c2c77dec5fdc0a40bb1820a..2eb517e2351462bd263d8976cf3d2108ecfeebc2 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c @@ -129,6 +129,7 @@ struct task_struct *kgdb_usethread; struct task_struct *kgdb_contthread; int kgdb_single_step; +pid_t kgdb_sstep_pid; /* Our I/O buffers. */ static char remcom_in_buffer[BUFMAX]; @@ -541,12 +542,17 @@ static struct task_struct *getthread(struct pt_regs *regs, int tid) */ if (tid == 0 || tid == -1) tid = -atomic_read(&kgdb_active) - 2; - if (tid < 0) { + if (tid < -1 && tid > -NR_CPUS - 2) { if (kgdb_info[-tid - 2].task) return kgdb_info[-tid - 2].task; else return idle_task(-tid - 2); } + if (tid <= 0) { + printk(KERN_ERR "KGDB: Internal thread select error\n"); + dump_stack(); + return NULL; + } /* * find_task_by_pid_ns() does not take the tasklist lock anymore @@ -619,7 +625,8 @@ static void kgdb_flush_swbreak_addr(unsigned long addr) static int kgdb_activate_sw_breakpoints(void) { unsigned long addr; - int error = 0; + int error; + int ret = 0; int i; for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { @@ -629,13 +636,16 @@ static int kgdb_activate_sw_breakpoints(void) addr = kgdb_break[i].bpt_addr; error = kgdb_arch_set_breakpoint(addr, kgdb_break[i].saved_instr); - if (error) - return error; + if (error) { + ret = error; + printk(KERN_INFO "KGDB: BP install failed: %lx", addr); + continue; + } kgdb_flush_swbreak_addr(addr); kgdb_break[i].state = BP_ACTIVE; } - return 0; + return ret; } static int kgdb_set_sw_break(unsigned long addr) @@ -682,7 +692,8 @@ static int kgdb_set_sw_break(unsigned long addr) static int kgdb_deactivate_sw_breakpoints(void) { unsigned long addr; - int error = 0; + int error; + int ret = 0; int i; for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { @@ -691,13 +702,15 @@ static int kgdb_deactivate_sw_breakpoints(void) addr = kgdb_break[i].bpt_addr; error = kgdb_arch_remove_breakpoint(addr, kgdb_break[i].saved_instr); - if (error) - return error; + if (error) { + printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr); + ret = error; + } kgdb_flush_swbreak_addr(addr); kgdb_break[i].state = BP_SET; } - return 0; + return ret; } static int kgdb_remove_sw_break(unsigned long addr) @@ -1204,8 +1217,10 @@ static int gdb_cmd_exception_pass(struct kgdb_state *ks) return 1; } else { - error_packet(remcom_out_buffer, -EINVAL); - return 0; + kgdb_msg_write("KGDB only knows signal 9 (pass)" + " and 15 (pass and disconnect)\n" + "Executing a continue without signal passing\n", 0); + remcom_in_buffer[0] = 'c'; } /* Indicate fall through */ @@ -1395,6 +1410,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) struct kgdb_state kgdb_var; struct kgdb_state *ks = &kgdb_var; unsigned long flags; + int sstep_tries = 100; int error = 0; int i, cpu; @@ -1425,13 +1441,14 @@ acquirelock: cpu_relax(); /* - * Do not start the debugger connection on this CPU if the last - * instance of the exception handler wanted to come into the - * debugger on a different CPU via a single step + * For single stepping, try to only enter on the processor + * that was single stepping. To gaurd against a deadlock, the + * kernel will only try for the value of sstep_tries before + * giving up and continuing on. */ if (atomic_read(&kgdb_cpu_doing_single_step) != -1 && - atomic_read(&kgdb_cpu_doing_single_step) != cpu) { - + (kgdb_info[cpu].task && + kgdb_info[cpu].task->pid != kgdb_sstep_pid) && --sstep_tries) { atomic_set(&kgdb_active, -1); touch_softlockup_watchdog(); clocksource_touch_watchdog(); @@ -1524,6 +1541,13 @@ acquirelock: } kgdb_restore: + if (atomic_read(&kgdb_cpu_doing_single_step) != -1) { + int sstep_cpu = atomic_read(&kgdb_cpu_doing_single_step); + if (kgdb_info[sstep_cpu].task) + kgdb_sstep_pid = kgdb_info[sstep_cpu].task->pid; + else + kgdb_sstep_pid = 0; + } /* Free kgdb_active */ atomic_set(&kgdb_active, -1); touch_softlockup_watchdog(); diff --git a/kernel/lockdep.c b/kernel/lockdep.c index f5dcd36d3151a0e3563f786f050795d605d25f99..429540c70d3f497ae7fc58998b0f248817a2cbf9 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -140,7 +140,8 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock) } #ifdef CONFIG_LOCK_STAT -static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], lock_stats); +static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], + cpu_lock_stats); static inline u64 lockstat_clock(void) { @@ -168,7 +169,7 @@ static void lock_time_inc(struct lock_time *lt, u64 time) if (time > lt->max) lt->max = time; - if (time < lt->min || !lt->min) + if (time < lt->min || !lt->nr) lt->min = time; lt->total += time; @@ -177,8 +178,15 @@ static void lock_time_inc(struct lock_time *lt, u64 time) static inline void lock_time_add(struct lock_time *src, struct lock_time *dst) { - dst->min += src->min; - dst->max += src->max; + if (!src->nr) + return; + + if (src->max > dst->max) + dst->max = src->max; + + if (src->min < dst->min || !dst->nr) + dst->min = src->min; + dst->total += src->total; dst->nr += src->nr; } @@ -191,7 +199,7 @@ struct lock_class_stats lock_stats(struct lock_class *class) memset(&stats, 0, sizeof(struct lock_class_stats)); for_each_possible_cpu(cpu) { struct lock_class_stats *pcs = - &per_cpu(lock_stats, cpu)[class - lock_classes]; + &per_cpu(cpu_lock_stats, cpu)[class - lock_classes]; for (i = 0; i < ARRAY_SIZE(stats.contention_point); i++) stats.contention_point[i] += pcs->contention_point[i]; @@ -218,7 +226,7 @@ void clear_lock_stats(struct lock_class *class) for_each_possible_cpu(cpu) { struct lock_class_stats *cpu_stats = - &per_cpu(lock_stats, cpu)[class - lock_classes]; + &per_cpu(cpu_lock_stats, cpu)[class - lock_classes]; memset(cpu_stats, 0, sizeof(struct lock_class_stats)); } @@ -228,12 +236,12 @@ void clear_lock_stats(struct lock_class *class) static struct lock_class_stats *get_lock_stats(struct lock_class *class) { - return &get_cpu_var(lock_stats)[class - lock_classes]; + return &get_cpu_var(cpu_lock_stats)[class - lock_classes]; } static void put_lock_stats(struct lock_class_stats *stats) { - put_cpu_var(lock_stats); + put_cpu_var(cpu_lock_stats); } static void lock_release_holdtime(struct held_lock *hlock) @@ -379,7 +387,8 @@ static int save_trace(struct stack_trace *trace) * complete trace that maxes out the entries provided will be reported * as incomplete, friggin useless */ - if (trace->entries[trace->nr_entries-1] == ULONG_MAX) + if (trace->nr_entries != 0 && + trace->entries[trace->nr_entries-1] == ULONG_MAX) trace->nr_entries--; trace->max_entries = trace->nr_entries; diff --git a/kernel/module.c b/kernel/module.c index 5842a71cf0527163c960cc8c41d549a5033e3443..12afc5a3ddd3a73972604050695ff4ab4ef708f6 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -370,8 +370,6 @@ EXPORT_SYMBOL_GPL(find_module); #ifdef CONFIG_SMP -#ifndef CONFIG_HAVE_LEGACY_PER_CPU_AREA - static void *percpu_modalloc(unsigned long size, unsigned long align, const char *name) { @@ -395,154 +393,6 @@ static void percpu_modfree(void *freeme) free_percpu(freeme); } -#else /* ... CONFIG_HAVE_LEGACY_PER_CPU_AREA */ - -/* Number of blocks used and allocated. */ -static unsigned int pcpu_num_used, pcpu_num_allocated; -/* Size of each block. -ve means used. */ -static int *pcpu_size; - -static int split_block(unsigned int i, unsigned short size) -{ - /* Reallocation required? */ - if (pcpu_num_used + 1 > pcpu_num_allocated) { - int *new; - - new = krealloc(pcpu_size, sizeof(new[0])*pcpu_num_allocated*2, - GFP_KERNEL); - if (!new) - return 0; - - pcpu_num_allocated *= 2; - pcpu_size = new; - } - - /* Insert a new subblock */ - memmove(&pcpu_size[i+1], &pcpu_size[i], - sizeof(pcpu_size[0]) * (pcpu_num_used - i)); - pcpu_num_used++; - - pcpu_size[i+1] -= size; - pcpu_size[i] = size; - return 1; -} - -static inline unsigned int block_size(int val) -{ - if (val < 0) - return -val; - return val; -} - -static void *percpu_modalloc(unsigned long size, unsigned long align, - const char *name) -{ - unsigned long extra; - unsigned int i; - void *ptr; - int cpu; - - if (align > PAGE_SIZE) { - printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n", - name, align, PAGE_SIZE); - align = PAGE_SIZE; - } - - ptr = __per_cpu_start; - for (i = 0; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) { - /* Extra for alignment requirement. */ - extra = ALIGN((unsigned long)ptr, align) - (unsigned long)ptr; - BUG_ON(i == 0 && extra != 0); - - if (pcpu_size[i] < 0 || pcpu_size[i] < extra + size) - continue; - - /* Transfer extra to previous block. */ - if (pcpu_size[i-1] < 0) - pcpu_size[i-1] -= extra; - else - pcpu_size[i-1] += extra; - pcpu_size[i] -= extra; - ptr += extra; - - /* Split block if warranted */ - if (pcpu_size[i] - size > sizeof(unsigned long)) - if (!split_block(i, size)) - return NULL; - - /* add the per-cpu scanning areas */ - for_each_possible_cpu(cpu) - kmemleak_alloc(ptr + per_cpu_offset(cpu), size, 0, - GFP_KERNEL); - - /* Mark allocated */ - pcpu_size[i] = -pcpu_size[i]; - return ptr; - } - - printk(KERN_WARNING "Could not allocate %lu bytes percpu data\n", - size); - return NULL; -} - -static void percpu_modfree(void *freeme) -{ - unsigned int i; - void *ptr = __per_cpu_start + block_size(pcpu_size[0]); - int cpu; - - /* First entry is core kernel percpu data. */ - for (i = 1; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) { - if (ptr == freeme) { - pcpu_size[i] = -pcpu_size[i]; - goto free; - } - } - BUG(); - - free: - /* remove the per-cpu scanning areas */ - for_each_possible_cpu(cpu) - kmemleak_free(freeme + per_cpu_offset(cpu)); - - /* Merge with previous? */ - if (pcpu_size[i-1] >= 0) { - pcpu_size[i-1] += pcpu_size[i]; - pcpu_num_used--; - memmove(&pcpu_size[i], &pcpu_size[i+1], - (pcpu_num_used - i) * sizeof(pcpu_size[0])); - i--; - } - /* Merge with next? */ - if (i+1 < pcpu_num_used && pcpu_size[i+1] >= 0) { - pcpu_size[i] += pcpu_size[i+1]; - pcpu_num_used--; - memmove(&pcpu_size[i+1], &pcpu_size[i+2], - (pcpu_num_used - (i+1)) * sizeof(pcpu_size[0])); - } -} - -static int percpu_modinit(void) -{ - pcpu_num_used = 2; - pcpu_num_allocated = 2; - pcpu_size = kmalloc(sizeof(pcpu_size[0]) * pcpu_num_allocated, - GFP_KERNEL); - /* Static in-kernel percpu data (used). */ - pcpu_size[0] = -(__per_cpu_end-__per_cpu_start); - /* Free room. */ - pcpu_size[1] = PERCPU_ENOUGH_ROOM + pcpu_size[0]; - if (pcpu_size[1] < 0) { - printk(KERN_ERR "No per-cpu room for modules.\n"); - pcpu_num_used = 1; - } - - return 0; -} -__initcall(percpu_modinit); - -#endif /* CONFIG_HAVE_LEGACY_PER_CPU_AREA */ - static unsigned int find_pcpusec(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, const char *secstrings) diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 40a996ec39faed91dea95a28661a98e7ed86878b..e73e53c7582f9a3d872622b277187e31de3db206 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -36,7 +36,7 @@ /* * Each CPU has a list of per CPU events: */ -DEFINE_PER_CPU(struct perf_cpu_context, perf_cpu_context); +static DEFINE_PER_CPU(struct perf_cpu_context, perf_cpu_context); int perf_max_events __read_mostly = 1; static int perf_reserved_percpu __read_mostly; @@ -567,7 +567,7 @@ static void __perf_event_disable(void *info) * is the current context on this CPU and preemption is disabled, * hence we can't get into perf_event_task_sched_out for this context. */ -static void perf_event_disable(struct perf_event *event) +void perf_event_disable(struct perf_event *event) { struct perf_event_context *ctx = event->ctx; struct task_struct *task = ctx->task; @@ -971,7 +971,7 @@ static void __perf_event_enable(void *info) * perf_event_for_each_child or perf_event_for_each as described * for perf_event_disable. */ -static void perf_event_enable(struct perf_event *event) +void perf_event_enable(struct perf_event *event) { struct perf_event_context *ctx = event->ctx; struct task_struct *task = ctx->task; @@ -1579,7 +1579,6 @@ static void __perf_event_init_context(struct perf_event_context *ctx, struct task_struct *task) { - memset(ctx, 0, sizeof(*ctx)); spin_lock_init(&ctx->lock); mutex_init(&ctx->mutex); INIT_LIST_HEAD(&ctx->group_list); @@ -1654,7 +1653,7 @@ static struct perf_event_context *find_get_context(pid_t pid, int cpu) } if (!ctx) { - ctx = kmalloc(sizeof(struct perf_event_context), GFP_KERNEL); + ctx = kzalloc(sizeof(struct perf_event_context), GFP_KERNEL); err = -ENOMEM; if (!ctx) goto errout; @@ -4011,6 +4010,7 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer) event->pmu->read(event); data.addr = 0; + data.raw = NULL; data.period = event->hw.last_period; regs = get_irq_regs(); /* @@ -4080,8 +4080,7 @@ static void cpu_clock_perf_event_update(struct perf_event *event) u64 now; now = cpu_clock(cpu); - prev = atomic64_read(&event->hw.prev_count); - atomic64_set(&event->hw.prev_count, now); + prev = atomic64_xchg(&event->hw.prev_count, now); atomic64_add(now - prev, &event->count); } @@ -4286,15 +4285,8 @@ static void bp_perf_event_destroy(struct perf_event *event) static const struct pmu *bp_perf_event_init(struct perf_event *bp) { int err; - /* - * The breakpoint is already filled if we haven't created the counter - * through perf syscall - * FIXME: manage to get trigerred to NULL if it comes from syscalls - */ - if (!bp->callback) - err = register_perf_hw_breakpoint(bp); - else - err = __register_perf_hw_breakpoint(bp); + + err = register_perf_hw_breakpoint(bp); if (err) return ERR_PTR(err); @@ -4308,6 +4300,7 @@ void perf_bp_event(struct perf_event *bp, void *data) struct perf_sample_data sample; struct pt_regs *regs = data; + sample.raw = NULL; sample.addr = bp->attr.bp_addr; if (!perf_exclude_event(bp, regs)) @@ -4390,7 +4383,7 @@ perf_event_alloc(struct perf_event_attr *attr, struct perf_event_context *ctx, struct perf_event *group_leader, struct perf_event *parent_event, - perf_callback_t callback, + perf_overflow_handler_t overflow_handler, gfp_t gfpflags) { const struct pmu *pmu; @@ -4433,10 +4426,10 @@ perf_event_alloc(struct perf_event_attr *attr, event->state = PERF_EVENT_STATE_INACTIVE; - if (!callback && parent_event) - callback = parent_event->callback; + if (!overflow_handler && parent_event) + overflow_handler = parent_event->overflow_handler; - event->callback = callback; + event->overflow_handler = overflow_handler; if (attr->disabled) event->state = PERF_EVENT_STATE_OFF; @@ -4776,7 +4769,8 @@ err_put_context: */ struct perf_event * perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, - pid_t pid, perf_callback_t callback) + pid_t pid, + perf_overflow_handler_t overflow_handler) { struct perf_event *event; struct perf_event_context *ctx; @@ -4793,7 +4787,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, } event = perf_event_alloc(attr, cpu, ctx, NULL, - NULL, callback, GFP_KERNEL); + NULL, overflow_handler, GFP_KERNEL); if (IS_ERR(event)) { err = PTR_ERR(event); goto err_put_context; @@ -5090,7 +5084,7 @@ again: */ int perf_event_init_task(struct task_struct *child) { - struct perf_event_context *child_ctx, *parent_ctx; + struct perf_event_context *child_ctx = NULL, *parent_ctx; struct perf_event_context *cloned_ctx; struct perf_event *event; struct task_struct *parent = current; @@ -5105,20 +5099,6 @@ int perf_event_init_task(struct task_struct *child) if (likely(!parent->perf_event_ctxp)) return 0; - /* - * This is executed from the parent task context, so inherit - * events that have been marked for cloning. - * First allocate and initialize a context for the child. - */ - - child_ctx = kmalloc(sizeof(struct perf_event_context), GFP_KERNEL); - if (!child_ctx) - return -ENOMEM; - - __perf_event_init_context(child_ctx, child); - child->perf_event_ctxp = child_ctx; - get_task_struct(child); - /* * If the parent's context is a clone, pin it so it won't get * swapped under us. @@ -5149,6 +5129,26 @@ int perf_event_init_task(struct task_struct *child) continue; } + if (!child->perf_event_ctxp) { + /* + * This is executed from the parent task context, so + * inherit events that have been marked for cloning. + * First allocate and initialize a context for the + * child. + */ + + child_ctx = kzalloc(sizeof(struct perf_event_context), + GFP_KERNEL); + if (!child_ctx) { + ret = -ENOMEM; + goto exit; + } + + __perf_event_init_context(child_ctx, child); + child->perf_event_ctxp = child_ctx; + get_task_struct(child); + } + ret = inherit_group(event, parent, parent_ctx, child, child_ctx); if (ret) { @@ -5177,6 +5177,7 @@ int perf_event_init_task(struct task_struct *child) get_ctx(child_ctx->parent_ctx); } +exit: mutex_unlock(&parent_ctx->mutex); perf_unpin_context(parent_ctx); diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index a621a67ef4e3bd5e4aa97522cdff8b443db15e32..9bb52177af02a3e20aa347e3b65c0a236caa1922 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c @@ -763,13 +763,13 @@ static void rcu_torture_timer(unsigned long unused) /* Should not happen, but... */ pipe_count = RCU_TORTURE_PIPE_LEN; } - ++__get_cpu_var(rcu_torture_count)[pipe_count]; + __this_cpu_inc(per_cpu_var(rcu_torture_count)[pipe_count]); completed = cur_ops->completed() - completed; if (completed > RCU_TORTURE_PIPE_LEN) { /* Should not happen, but... */ completed = RCU_TORTURE_PIPE_LEN; } - ++__get_cpu_var(rcu_torture_batch)[completed]; + __this_cpu_inc(per_cpu_var(rcu_torture_batch)[completed]); preempt_enable(); cur_ops->readunlock(idx); } @@ -818,13 +818,13 @@ rcu_torture_reader(void *arg) /* Should not happen, but... */ pipe_count = RCU_TORTURE_PIPE_LEN; } - ++__get_cpu_var(rcu_torture_count)[pipe_count]; + __this_cpu_inc(per_cpu_var(rcu_torture_count)[pipe_count]); completed = cur_ops->completed() - completed; if (completed > RCU_TORTURE_PIPE_LEN) { /* Should not happen, but... */ completed = RCU_TORTURE_PIPE_LEN; } - ++__get_cpu_var(rcu_torture_batch)[completed]; + __this_cpu_inc(per_cpu_var(rcu_torture_batch)[completed]); preempt_enable(); cur_ops->readunlock(idx); schedule(); diff --git a/kernel/resource.c b/kernel/resource.c index fb11a58b95948a08c57ec46033f538d974a480dd..dc15686b7a7783927e28f5866064bdaba10d39e6 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -308,35 +308,37 @@ static int find_resource(struct resource *root, struct resource *new, void *alignf_data) { struct resource *this = root->child; + resource_size_t start, end; - new->start = root->start; + start = root->start; /* * Skip past an allocated resource that starts at 0, since the assignment * of this->start - 1 to new->end below would cause an underflow. */ if (this && this->start == 0) { - new->start = this->end + 1; + start = this->end + 1; this = this->sibling; } for(;;) { if (this) - new->end = this->start - 1; + end = this->start - 1; else - new->end = root->end; - if (new->start < min) - new->start = min; - if (new->end > max) - new->end = max; - new->start = ALIGN(new->start, align); + end = root->end; + if (start < min) + start = min; + if (end > max) + end = max; + start = ALIGN(start, align); if (alignf) alignf(alignf_data, new, size, align); - if (new->start < new->end && new->end - new->start >= size - 1) { - new->end = new->start + size - 1; + if (start < end && end - start >= size - 1) { + new->start = start; + new->end = start + size - 1; return 0; } if (!this) break; - new->start = this->end + 1; + start = this->end + 1; this = this->sibling; } return -EBUSY; diff --git a/kernel/sched.c b/kernel/sched.c index e7f2cfa6a2571afe6338368367a3aa269043daf1..fd05861b2111005a5a88b386d7d77ee036f5e160 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -298,7 +298,7 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(struct cfs_rq, init_tg_cfs_rq); #ifdef CONFIG_RT_GROUP_SCHED static DEFINE_PER_CPU(struct sched_rt_entity, init_sched_rt_entity); -static DEFINE_PER_CPU_SHARED_ALIGNED(struct rt_rq, init_rt_rq); +static DEFINE_PER_CPU_SHARED_ALIGNED(struct rt_rq, init_rt_rq_var); #endif /* CONFIG_RT_GROUP_SCHED */ #else /* !CONFIG_USER_SCHED */ #define root_task_group init_task_group @@ -814,6 +814,7 @@ const_debug unsigned int sysctl_sched_nr_migrate = 32; * default: 0.25ms */ unsigned int sysctl_sched_shares_ratelimit = 250000; +unsigned int normalized_sysctl_sched_shares_ratelimit = 250000; /* * Inject some fuzzyness into changing the per-cpu group shares @@ -1614,7 +1615,7 @@ static void update_group_shares_cpu(struct task_group *tg, int cpu, */ static int tg_shares_up(struct task_group *tg, void *data) { - unsigned long weight, rq_weight = 0, shares = 0; + unsigned long weight, rq_weight = 0, sum_weight = 0, shares = 0; unsigned long *usd_rq_weight; struct sched_domain *sd = data; unsigned long flags; @@ -1630,6 +1631,7 @@ static int tg_shares_up(struct task_group *tg, void *data) weight = tg->cfs_rq[i]->load.weight; usd_rq_weight[i] = weight; + rq_weight += weight; /* * If there are currently no tasks on the cpu pretend there * is one of average load so that when a new task gets to @@ -1638,10 +1640,13 @@ static int tg_shares_up(struct task_group *tg, void *data) if (!weight) weight = NICE_0_LOAD; - rq_weight += weight; + sum_weight += weight; shares += tg->cfs_rq[i]->shares; } + if (!rq_weight) + rq_weight = sum_weight; + if ((!shares && rq_weight) || shares > tg->shares) shares = tg->shares; @@ -1810,6 +1815,22 @@ static void cfs_rq_set_shares(struct cfs_rq *cfs_rq, unsigned long shares) #endif static void calc_load_account_active(struct rq *this_rq); +static void update_sysctl(void); +static int get_update_sysctl_factor(void); + +static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu) +{ + set_task_rq(p, cpu); +#ifdef CONFIG_SMP + /* + * After ->cpu is set up to a new value, task_rq_lock(p, ...) can be + * successfuly executed on another CPU. We must ensure that updates of + * per-task data have been completed by this moment. + */ + smp_wmb(); + task_thread_info(p)->cpu = cpu; +#endif +} #include "sched_stats.h" #include "sched_idletask.c" @@ -1967,20 +1988,6 @@ inline int task_curr(const struct task_struct *p) return cpu_curr(task_cpu(p)) == p; } -static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu) -{ - set_task_rq(p, cpu); -#ifdef CONFIG_SMP - /* - * After ->cpu is set up to a new value, task_rq_lock(p, ...) can be - * successfuly executed on another CPU. We must ensure that updates of - * per-task data have been completed by this moment. - */ - smp_wmb(); - task_thread_info(p)->cpu = cpu; -#endif -} - static inline void check_class_changed(struct rq *rq, struct task_struct *p, const struct sched_class *prev_class, int oldprio, int running) @@ -2060,29 +2067,13 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd) void set_task_cpu(struct task_struct *p, unsigned int new_cpu) { int old_cpu = task_cpu(p); - struct rq *old_rq = cpu_rq(old_cpu), *new_rq = cpu_rq(new_cpu); struct cfs_rq *old_cfsrq = task_cfs_rq(p), *new_cfsrq = cpu_cfs_rq(old_cfsrq, new_cpu); - u64 clock_offset; - - clock_offset = old_rq->clock - new_rq->clock; trace_sched_migrate_task(p, new_cpu); -#ifdef CONFIG_SCHEDSTATS - if (p->se.wait_start) - p->se.wait_start -= clock_offset; - if (p->se.sleep_start) - p->se.sleep_start -= clock_offset; - if (p->se.block_start) - p->se.block_start -= clock_offset; -#endif if (old_cpu != new_cpu) { p->se.nr_migrations++; -#ifdef CONFIG_SCHEDSTATS - if (task_hot(p, old_rq->clock, NULL)) - schedstat_inc(p, se.nr_forced2_migrations); -#endif perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS, 1, 1, NULL, 0); } @@ -2323,6 +2314,14 @@ void task_oncpu_function_call(struct task_struct *p, preempt_enable(); } +#ifdef CONFIG_SMP +static inline +int select_task_rq(struct task_struct *p, int sd_flags, int wake_flags) +{ + return p->sched_class->select_task_rq(p, sd_flags, wake_flags); +} +#endif + /*** * try_to_wake_up - wake up a thread * @p: the to-be-woken-up thread @@ -2374,17 +2373,14 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, if (task_contributes_to_load(p)) rq->nr_uninterruptible--; p->state = TASK_WAKING; - task_rq_unlock(rq, &flags); + __task_rq_unlock(rq); - cpu = p->sched_class->select_task_rq(p, SD_BALANCE_WAKE, wake_flags); - if (cpu != orig_cpu) { - local_irq_save(flags); - rq = cpu_rq(cpu); - update_rq_clock(rq); + cpu = select_task_rq(p, SD_BALANCE_WAKE, wake_flags); + if (cpu != orig_cpu) set_task_cpu(p, cpu); - local_irq_restore(flags); - } - rq = task_rq_lock(p, &flags); + + rq = __task_rq_lock(p); + update_rq_clock(rq); WARN_ON(p->state != TASK_WAKING); cpu = task_cpu(p); @@ -2499,7 +2495,6 @@ static void __sched_fork(struct task_struct *p) p->se.avg_overlap = 0; p->se.start_runtime = 0; p->se.avg_wakeup = sysctl_sched_wakeup_granularity; - p->se.avg_running = 0; #ifdef CONFIG_SCHEDSTATS p->se.wait_start = 0; @@ -2521,7 +2516,6 @@ static void __sched_fork(struct task_struct *p) p->se.nr_failed_migrations_running = 0; p->se.nr_failed_migrations_hot = 0; p->se.nr_forced_migrations = 0; - p->se.nr_forced2_migrations = 0; p->se.nr_wakeups = 0; p->se.nr_wakeups_sync = 0; @@ -2558,7 +2552,6 @@ static void __sched_fork(struct task_struct *p) void sched_fork(struct task_struct *p, int clone_flags) { int cpu = get_cpu(); - unsigned long flags; __sched_fork(p); @@ -2592,13 +2585,13 @@ void sched_fork(struct task_struct *p, int clone_flags) if (!rt_prio(p->prio)) p->sched_class = &fair_sched_class; + if (p->sched_class->task_fork) + p->sched_class->task_fork(p); + #ifdef CONFIG_SMP - cpu = p->sched_class->select_task_rq(p, SD_BALANCE_FORK, 0); + cpu = select_task_rq(p, SD_BALANCE_FORK, 0); #endif - local_irq_save(flags); - update_rq_clock(cpu_rq(cpu)); set_task_cpu(p, cpu); - local_irq_restore(flags); #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) if (likely(sched_info_on())) @@ -2631,17 +2624,7 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags) rq = task_rq_lock(p, &flags); BUG_ON(p->state != TASK_RUNNING); update_rq_clock(rq); - - if (!p->sched_class->task_new || !current->se.on_rq) { - activate_task(rq, p, 0); - } else { - /* - * Let the scheduling class do new task startup - * management (if any): - */ - p->sched_class->task_new(rq, p); - inc_nr_running(rq); - } + activate_task(rq, p, 0); trace_sched_wakeup_new(rq, p, 1); check_preempt_curr(rq, p, WF_FORK); #ifdef CONFIG_SMP @@ -3156,7 +3139,7 @@ out: void sched_exec(void) { int new_cpu, this_cpu = get_cpu(); - new_cpu = current->sched_class->select_task_rq(current, SD_BALANCE_EXEC, 0); + new_cpu = select_task_rq(current, SD_BALANCE_EXEC, 0); put_cpu(); if (new_cpu != this_cpu) sched_migrate_task(current, new_cpu); @@ -3172,10 +3155,6 @@ static void pull_task(struct rq *src_rq, struct task_struct *p, deactivate_task(src_rq, p, 0); set_task_cpu(p, this_cpu); activate_task(this_rq, p, 0); - /* - * Note that idle threads have a prio of MAX_PRIO, for this test - * to be always true for them. - */ check_preempt_curr(this_rq, p, 0); } @@ -4134,7 +4113,7 @@ static int load_balance(int this_cpu, struct rq *this_rq, unsigned long flags; struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask); - cpumask_copy(cpus, cpu_online_mask); + cpumask_copy(cpus, cpu_active_mask); /* * When power savings policy is enabled for the parent domain, idle @@ -4297,7 +4276,7 @@ load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd) int all_pinned = 0; struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask); - cpumask_copy(cpus, cpu_online_mask); + cpumask_copy(cpus, cpu_active_mask); /* * When power savings policy is enabled for the parent domain, idle @@ -4694,7 +4673,7 @@ int select_nohz_load_balancer(int stop_tick) cpumask_set_cpu(cpu, nohz.cpu_mask); /* time for ilb owner also to sleep */ - if (cpumask_weight(nohz.cpu_mask) == num_online_cpus()) { + if (cpumask_weight(nohz.cpu_mask) == num_active_cpus()) { if (atomic_read(&nohz.load_balancer) == cpu) atomic_set(&nohz.load_balancer, -1); return 0; @@ -5396,13 +5375,14 @@ static inline void schedule_debug(struct task_struct *prev) #endif } -static void put_prev_task(struct rq *rq, struct task_struct *p) +static void put_prev_task(struct rq *rq, struct task_struct *prev) { - u64 runtime = p->se.sum_exec_runtime - p->se.prev_sum_exec_runtime; + if (prev->state == TASK_RUNNING) { + u64 runtime = prev->se.sum_exec_runtime; - update_avg(&p->se.avg_running, runtime); + runtime -= prev->se.prev_sum_exec_runtime; + runtime = min_t(u64, runtime, 2*sysctl_sched_migration_cost); - if (p->state == TASK_RUNNING) { /* * In order to avoid avg_overlap growing stale when we are * indeed overlapping and hence not getting put to sleep, grow @@ -5412,12 +5392,9 @@ static void put_prev_task(struct rq *rq, struct task_struct *p) * correlates to the amount of cache footprint a task can * build up. */ - runtime = min_t(u64, runtime, 2*sysctl_sched_migration_cost); - update_avg(&p->se.avg_overlap, runtime); - } else { - update_avg(&p->se.avg_running, 0); + update_avg(&prev->se.avg_overlap, runtime); } - p->sched_class->put_prev_task(rq, p); + prev->sched_class->put_prev_task(rq, prev); } /* @@ -6631,6 +6608,8 @@ SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len, long sched_getaffinity(pid_t pid, struct cpumask *mask) { struct task_struct *p; + unsigned long flags; + struct rq *rq; int retval; get_online_cpus(); @@ -6645,7 +6624,9 @@ long sched_getaffinity(pid_t pid, struct cpumask *mask) if (retval) goto out_unlock; + rq = task_rq_lock(p, &flags); cpumask_and(mask, &p->cpus_allowed, cpu_online_mask); + task_rq_unlock(rq, &flags); out_unlock: read_unlock(&tasklist_lock); @@ -6883,6 +6864,8 @@ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, { struct task_struct *p; unsigned int time_slice; + unsigned long flags; + struct rq *rq; int retval; struct timespec t; @@ -6899,7 +6882,9 @@ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, if (retval) goto out_unlock; - time_slice = p->sched_class->get_rr_interval(p); + rq = task_rq_lock(p, &flags); + time_slice = p->sched_class->get_rr_interval(rq, p); + task_rq_unlock(rq, &flags); read_unlock(&tasklist_lock); jiffies_to_timespec(time_slice, &t); @@ -7000,7 +6985,6 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu) __sched_fork(idle); idle->se.exec_start = sched_clock(); - idle->prio = idle->normal_prio = MAX_PRIO; cpumask_copy(&idle->cpus_allowed, cpumask_of(cpu)); __set_task_cpu(idle, cpu); @@ -7041,22 +7025,43 @@ cpumask_var_t nohz_cpu_mask; * * This idea comes from the SD scheduler of Con Kolivas: */ -static inline void sched_init_granularity(void) +static int get_update_sysctl_factor(void) { - unsigned int factor = 1 + ilog2(num_online_cpus()); - const unsigned long limit = 200000000; + unsigned int cpus = min_t(int, num_online_cpus(), 8); + unsigned int factor; + + switch (sysctl_sched_tunable_scaling) { + case SCHED_TUNABLESCALING_NONE: + factor = 1; + break; + case SCHED_TUNABLESCALING_LINEAR: + factor = cpus; + break; + case SCHED_TUNABLESCALING_LOG: + default: + factor = 1 + ilog2(cpus); + break; + } - sysctl_sched_min_granularity *= factor; - if (sysctl_sched_min_granularity > limit) - sysctl_sched_min_granularity = limit; + return factor; +} - sysctl_sched_latency *= factor; - if (sysctl_sched_latency > limit) - sysctl_sched_latency = limit; +static void update_sysctl(void) +{ + unsigned int factor = get_update_sysctl_factor(); - sysctl_sched_wakeup_granularity *= factor; +#define SET_SYSCTL(name) \ + (sysctl_##name = (factor) * normalized_sysctl_##name) + SET_SYSCTL(sched_min_granularity); + SET_SYSCTL(sched_latency); + SET_SYSCTL(sched_wakeup_granularity); + SET_SYSCTL(sched_shares_ratelimit); +#undef SET_SYSCTL +} - sysctl_sched_shares_ratelimit *= factor; +static inline void sched_init_granularity(void) +{ + update_sysctl(); } #ifdef CONFIG_SMP @@ -7093,7 +7098,7 @@ int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask) int ret = 0; rq = task_rq_lock(p, &flags); - if (!cpumask_intersects(new_mask, cpu_online_mask)) { + if (!cpumask_intersects(new_mask, cpu_active_mask)) { ret = -EINVAL; goto out; } @@ -7115,7 +7120,7 @@ int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask) if (cpumask_test_cpu(task_cpu(p), new_mask)) goto out; - if (migrate_task(p, cpumask_any_and(cpu_online_mask, new_mask), &req)) { + if (migrate_task(p, cpumask_any_and(cpu_active_mask, new_mask), &req)) { /* Need help from migration thread: drop lock and wait. */ struct task_struct *mt = rq->migration_thread; @@ -7269,19 +7274,19 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p) again: /* Look for allowed, online CPU in same node. */ - for_each_cpu_and(dest_cpu, nodemask, cpu_online_mask) + for_each_cpu_and(dest_cpu, nodemask, cpu_active_mask) if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed)) goto move; /* Any allowed, online CPU? */ - dest_cpu = cpumask_any_and(&p->cpus_allowed, cpu_online_mask); + dest_cpu = cpumask_any_and(&p->cpus_allowed, cpu_active_mask); if (dest_cpu < nr_cpu_ids) goto move; /* No more Mr. Nice Guy. */ if (dest_cpu >= nr_cpu_ids) { cpuset_cpus_allowed_locked(p, &p->cpus_allowed); - dest_cpu = cpumask_any_and(cpu_online_mask, &p->cpus_allowed); + dest_cpu = cpumask_any_and(cpu_active_mask, &p->cpus_allowed); /* * Don't tell them about moving exiting tasks or @@ -7310,7 +7315,7 @@ move: */ static void migrate_nr_uninterruptible(struct rq *rq_src) { - struct rq *rq_dest = cpu_rq(cpumask_any(cpu_online_mask)); + struct rq *rq_dest = cpu_rq(cpumask_any(cpu_active_mask)); unsigned long flags; local_irq_save(flags); @@ -7563,7 +7568,7 @@ static ctl_table *sd_alloc_ctl_cpu_table(int cpu) static struct ctl_table_header *sd_sysctl_header; static void register_sched_domain_sysctl(void) { - int i, cpu_num = num_online_cpus(); + int i, cpu_num = num_possible_cpus(); struct ctl_table *entry = sd_alloc_ctl_entry(cpu_num + 1); char buf[32]; @@ -7573,7 +7578,7 @@ static void register_sched_domain_sysctl(void) if (entry == NULL) return; - for_each_online_cpu(i) { + for_each_possible_cpu(i) { snprintf(buf, 32, "cpu%d", i); entry->procname = kstrdup(buf, GFP_KERNEL); entry->mode = 0555; @@ -7703,7 +7708,6 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) spin_lock_irq(&rq->lock); update_rq_clock(rq); deactivate_task(rq, rq->idle, 0); - rq->idle->static_prio = MAX_PRIO; __setscheduler(rq, rq->idle, SCHED_NORMAL, 0); rq->idle->sched_class = &idle_sched_class; migrate_dead_tasks(cpu); @@ -8282,14 +8286,14 @@ enum s_alloc { */ #ifdef CONFIG_SCHED_SMT static DEFINE_PER_CPU(struct static_sched_domain, cpu_domains); -static DEFINE_PER_CPU(struct static_sched_group, sched_group_cpus); +static DEFINE_PER_CPU(struct static_sched_group, sched_groups); static int cpu_to_cpu_group(int cpu, const struct cpumask *cpu_map, struct sched_group **sg, struct cpumask *unused) { if (sg) - *sg = &per_cpu(sched_group_cpus, cpu).sg; + *sg = &per_cpu(sched_groups, cpu).sg; return cpu; } #endif /* CONFIG_SCHED_SMT */ @@ -9099,7 +9103,7 @@ match1: if (doms_new == NULL) { ndoms_cur = 0; doms_new = &fallback_doms; - cpumask_andnot(doms_new[0], cpu_online_mask, cpu_isolated_map); + cpumask_andnot(doms_new[0], cpu_active_mask, cpu_isolated_map); WARN_ON_ONCE(dattr_new); } @@ -9230,8 +9234,10 @@ static int update_sched_domains(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: - case CPU_DEAD: - case CPU_DEAD_FROZEN: + case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: + case CPU_DOWN_FAILED: + case CPU_DOWN_FAILED_FROZEN: partition_sched_domains(1, NULL, NULL); return NOTIFY_OK; @@ -9278,7 +9284,7 @@ void __init sched_init_smp(void) #endif get_online_cpus(); mutex_lock(&sched_domains_mutex); - arch_init_sched_domains(cpu_online_mask); + arch_init_sched_domains(cpu_active_mask); cpumask_andnot(non_isolated_cpus, cpu_possible_mask, cpu_isolated_map); if (cpumask_empty(non_isolated_cpus)) cpumask_set_cpu(smp_processor_id(), non_isolated_cpus); @@ -9577,7 +9583,7 @@ void __init sched_init(void) #elif defined CONFIG_USER_SCHED init_tg_rt_entry(&root_task_group, &rq->rt, NULL, i, 0, NULL); init_tg_rt_entry(&init_task_group, - &per_cpu(init_rt_rq, i), + &per_cpu(init_rt_rq_var, i), &per_cpu(init_sched_rt_entity, i), i, 1, root_task_group.rt_se[i]); #endif @@ -9842,13 +9848,15 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent) se = kzalloc_node(sizeof(struct sched_entity), GFP_KERNEL, cpu_to_node(i)); if (!se) - goto err; + goto err_free_rq; init_tg_cfs_entry(tg, cfs_rq, se, i, 0, parent->se[i]); } return 1; + err_free_rq: + kfree(cfs_rq); err: return 0; } @@ -9930,13 +9938,15 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent) rt_se = kzalloc_node(sizeof(struct sched_rt_entity), GFP_KERNEL, cpu_to_node(i)); if (!rt_se) - goto err; + goto err_free_rq; init_tg_rt_entry(tg, rt_rq, rt_se, i, 0, parent->rt_se[i]); } return 1; + err_free_rq: + kfree(rt_rq); err: return 0; } diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index 6988cf08f705d3bbd7b8cd16a43fe70cd32b795e..5ae24fc65d75c7f9435040b90851c6cdcdd4a579 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -309,6 +309,12 @@ static void print_cpu(struct seq_file *m, int cpu) print_rq(m, rq, cpu); } +static const char *sched_tunable_scaling_names[] = { + "none", + "logaritmic", + "linear" +}; + static int sched_debug_show(struct seq_file *m, void *v) { u64 now = ktime_to_ns(ktime_get()); @@ -334,6 +340,10 @@ static int sched_debug_show(struct seq_file *m, void *v) #undef PN #undef P + SEQ_printf(m, " .%-40s: %d (%s)\n", "sysctl_sched_tunable_scaling", + sysctl_sched_tunable_scaling, + sched_tunable_scaling_names[sysctl_sched_tunable_scaling]); + for_each_online_cpu(cpu) print_cpu(m, cpu); @@ -399,7 +409,6 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) PN(se.sum_exec_runtime); PN(se.avg_overlap); PN(se.avg_wakeup); - PN(se.avg_running); nr_switches = p->nvcsw + p->nivcsw; @@ -423,7 +432,6 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) P(se.nr_failed_migrations_running); P(se.nr_failed_migrations_hot); P(se.nr_forced_migrations); - P(se.nr_forced2_migrations); P(se.nr_wakeups); P(se.nr_wakeups_sync); P(se.nr_wakeups_migrate); @@ -499,7 +507,6 @@ void proc_sched_set_task(struct task_struct *p) p->se.nr_failed_migrations_running = 0; p->se.nr_failed_migrations_hot = 0; p->se.nr_forced_migrations = 0; - p->se.nr_forced2_migrations = 0; p->se.nr_wakeups = 0; p->se.nr_wakeups_sync = 0; p->se.nr_wakeups_migrate = 0; diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index f61837ad336dbefd151be1e5e2acecca0a0b0070..804a411838f12e68690ff9db41796aa4f2a3eefe 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -21,6 +21,7 @@ */ #include +#include /* * Targeted preemption latency for CPU-bound tasks: @@ -35,12 +36,26 @@ * run vmstat and monitor the context-switches (cs) field) */ unsigned int sysctl_sched_latency = 5000000ULL; +unsigned int normalized_sysctl_sched_latency = 5000000ULL; + +/* + * The initial- and re-scaling of tunables is configurable + * (default SCHED_TUNABLESCALING_LOG = *(1+ilog(ncpus)) + * + * Options are: + * SCHED_TUNABLESCALING_NONE - unscaled, always *1 + * SCHED_TUNABLESCALING_LOG - scaled logarithmical, *1+ilog(ncpus) + * SCHED_TUNABLESCALING_LINEAR - scaled linear, *ncpus + */ +enum sched_tunable_scaling sysctl_sched_tunable_scaling + = SCHED_TUNABLESCALING_LOG; /* * Minimal preemption granularity for CPU-bound tasks: * (default: 1 msec * (1 + ilog(ncpus)), units: nanoseconds) */ unsigned int sysctl_sched_min_granularity = 1000000ULL; +unsigned int normalized_sysctl_sched_min_granularity = 1000000ULL; /* * is kept at sysctl_sched_latency / sysctl_sched_min_granularity @@ -70,6 +85,7 @@ unsigned int __read_mostly sysctl_sched_compat_yield; * have immediate wakeup/sleep latencies. */ unsigned int sysctl_sched_wakeup_granularity = 1000000UL; +unsigned int normalized_sysctl_sched_wakeup_granularity = 1000000UL; const_debug unsigned int sysctl_sched_migration_cost = 500000UL; @@ -383,11 +399,12 @@ static struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq) */ #ifdef CONFIG_SCHED_DEBUG -int sched_nr_latency_handler(struct ctl_table *table, int write, +int sched_proc_update_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); + int factor = get_update_sysctl_factor(); if (ret || !write) return ret; @@ -395,6 +412,14 @@ int sched_nr_latency_handler(struct ctl_table *table, int write, sched_nr_latency = DIV_ROUND_UP(sysctl_sched_latency, sysctl_sched_min_granularity); +#define WRT_SYSCTL(name) \ + (normalized_sysctl_##name = sysctl_##name / (factor)) + WRT_SYSCTL(sched_min_granularity); + WRT_SYSCTL(sched_latency); + WRT_SYSCTL(sched_wakeup_granularity); + WRT_SYSCTL(sched_shares_ratelimit); +#undef WRT_SYSCTL + return 0; } #endif @@ -1403,7 +1428,6 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag new_cpu = prev_cpu; } - rcu_read_lock(); for_each_domain(cpu, tmp) { /* * If power savings logic is enabled for a domain, see if we @@ -1484,10 +1508,8 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag update_shares(tmp); } - if (affine_sd && wake_affine(affine_sd, p, sync)) { - new_cpu = cpu; - goto out; - } + if (affine_sd && wake_affine(affine_sd, p, sync)) + return cpu; while (sd) { int load_idx = sd->forkexec_idx; @@ -1528,8 +1550,6 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag /* while loop will break here if sd == NULL */ } -out: - rcu_read_unlock(); return new_cpu; } #endif /* CONFIG_SMP */ @@ -1651,12 +1671,8 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_ int sync = wake_flags & WF_SYNC; int scale = cfs_rq->nr_running >= sched_nr_latency; - update_curr(cfs_rq); - - if (unlikely(rt_prio(p->prio))) { - resched_task(curr); - return; - } + if (unlikely(rt_prio(p->prio))) + goto preempt; if (unlikely(p->sched_class != &fair_sched_class)) return; @@ -1682,50 +1698,44 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_ return; /* Idle tasks are by definition preempted by everybody. */ - if (unlikely(curr->policy == SCHED_IDLE)) { - resched_task(curr); - return; - } + if (unlikely(curr->policy == SCHED_IDLE)) + goto preempt; - if ((sched_feat(WAKEUP_SYNC) && sync) || - (sched_feat(WAKEUP_OVERLAP) && - (se->avg_overlap < sysctl_sched_migration_cost && - pse->avg_overlap < sysctl_sched_migration_cost))) { - resched_task(curr); - return; - } + if (sched_feat(WAKEUP_SYNC) && sync) + goto preempt; - if (sched_feat(WAKEUP_RUNNING)) { - if (pse->avg_running < se->avg_running) { - set_next_buddy(pse); - resched_task(curr); - return; - } - } + if (sched_feat(WAKEUP_OVERLAP) && + se->avg_overlap < sysctl_sched_migration_cost && + pse->avg_overlap < sysctl_sched_migration_cost) + goto preempt; if (!sched_feat(WAKEUP_PREEMPT)) return; + update_curr(cfs_rq); find_matching_se(&se, &pse); - BUG_ON(!pse); + if (wakeup_preempt_entity(se, pse) == 1) + goto preempt; - if (wakeup_preempt_entity(se, pse) == 1) { - resched_task(curr); - /* - * Only set the backward buddy when the current task is still - * on the rq. This can happen when a wakeup gets interleaved - * with schedule on the ->pre_schedule() or idle_balance() - * point, either of which can * drop the rq lock. - * - * Also, during early boot the idle thread is in the fair class, - * for obvious reasons its a bad idea to schedule back to it. - */ - if (unlikely(!se->on_rq || curr == rq->idle)) - return; - if (sched_feat(LAST_BUDDY) && scale && entity_is_task(se)) - set_last_buddy(se); - } + return; + +preempt: + resched_task(curr); + /* + * Only set the backward buddy when the current task is still + * on the rq. This can happen when a wakeup gets interleaved + * with schedule on the ->pre_schedule() or idle_balance() + * point, either of which can * drop the rq lock. + * + * Also, during early boot the idle thread is in the fair class, + * for obvious reasons its a bad idea to schedule back to it. + */ + if (unlikely(!se->on_rq || curr == rq->idle)) + return; + + if (sched_feat(LAST_BUDDY) && scale && entity_is_task(se)) + set_last_buddy(se); } static struct task_struct *pick_next_task_fair(struct rq *rq) @@ -1905,6 +1915,17 @@ move_one_task_fair(struct rq *this_rq, int this_cpu, struct rq *busiest, return 0; } + +static void rq_online_fair(struct rq *rq) +{ + update_sysctl(); +} + +static void rq_offline_fair(struct rq *rq) +{ + update_sysctl(); +} + #endif /* CONFIG_SMP */ /* @@ -1922,28 +1943,30 @@ static void task_tick_fair(struct rq *rq, struct task_struct *curr, int queued) } /* - * Share the fairness runtime between parent and child, thus the - * total amount of pressure for CPU stays equal - new tasks - * get a chance to run but frequent forkers are not allowed to - * monopolize the CPU. Note: the parent runqueue is locked, - * the child is not running yet. + * called on fork with the child task as argument from the parent's context + * - child not yet on the tasklist + * - preemption disabled */ -static void task_new_fair(struct rq *rq, struct task_struct *p) +static void task_fork_fair(struct task_struct *p) { - struct cfs_rq *cfs_rq = task_cfs_rq(p); + struct cfs_rq *cfs_rq = task_cfs_rq(current); struct sched_entity *se = &p->se, *curr = cfs_rq->curr; int this_cpu = smp_processor_id(); + struct rq *rq = this_rq(); + unsigned long flags; + + spin_lock_irqsave(&rq->lock, flags); - sched_info_queued(p); + if (unlikely(task_cpu(p) != this_cpu)) + __set_task_cpu(p, this_cpu); update_curr(cfs_rq); + if (curr) se->vruntime = curr->vruntime; place_entity(cfs_rq, se, 1); - /* 'curr' will be NULL if the child belongs to a different group */ - if (sysctl_sched_child_runs_first && this_cpu == task_cpu(p) && - curr && entity_before(curr, se)) { + if (sysctl_sched_child_runs_first && curr && entity_before(curr, se)) { /* * Upon rescheduling, sched_class::put_prev_task() will place * 'current' within the tree based on its new key value. @@ -1952,7 +1975,7 @@ static void task_new_fair(struct rq *rq, struct task_struct *p) resched_task(rq->curr); } - enqueue_task_fair(rq, p, 0); + spin_unlock_irqrestore(&rq->lock, flags); } /* @@ -2014,21 +2037,17 @@ static void moved_group_fair(struct task_struct *p) } #endif -unsigned int get_rr_interval_fair(struct task_struct *task) +unsigned int get_rr_interval_fair(struct rq *rq, struct task_struct *task) { struct sched_entity *se = &task->se; - unsigned long flags; - struct rq *rq; unsigned int rr_interval = 0; /* * Time slice is 0 for SCHED_OTHER tasks that are on an otherwise * idle runqueue: */ - rq = task_rq_lock(task, &flags); if (rq->cfs.load.weight) rr_interval = NS_TO_JIFFIES(sched_slice(&rq->cfs, se)); - task_rq_unlock(rq, &flags); return rr_interval; } @@ -2052,11 +2071,13 @@ static const struct sched_class fair_sched_class = { .load_balance = load_balance_fair, .move_one_task = move_one_task_fair, + .rq_online = rq_online_fair, + .rq_offline = rq_offline_fair, #endif .set_curr_task = set_curr_task_fair, .task_tick = task_tick_fair, - .task_new = task_new_fair, + .task_fork = task_fork_fair, .prio_changed = prio_changed_fair, .switched_to = switched_to_fair, diff --git a/kernel/sched_features.h b/kernel/sched_features.h index 0d94083582c71c84c48cdbec175191bc39ee43a6..d5059fd761d9bf49aca78e830a4fe9330bd464c9 100644 --- a/kernel/sched_features.h +++ b/kernel/sched_features.h @@ -53,11 +53,6 @@ SCHED_FEAT(WAKEUP_SYNC, 0) */ SCHED_FEAT(WAKEUP_OVERLAP, 0) -/* - * Wakeup preemption towards tasks that run short - */ -SCHED_FEAT(WAKEUP_RUNNING, 0) - /* * Use the SYNC wakeup hint, pipes and the likes use this to indicate * the remote end is likely to consume the data we just wrote, and diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c index b133a28fcde32cbf20421f077686c14319871f74..33d5384a73a86b09a0493600ce4e4b06cf1b9ac5 100644 --- a/kernel/sched_idletask.c +++ b/kernel/sched_idletask.c @@ -97,7 +97,7 @@ static void prio_changed_idle(struct rq *rq, struct task_struct *p, check_preempt_curr(rq, p, 0); } -unsigned int get_rr_interval_idle(struct task_struct *task) +unsigned int get_rr_interval_idle(struct rq *rq, struct task_struct *task) { return 0; } diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 5c5fef3784152396980cd81e5c6c9ebe87c0d93c..aecbd9c6b20c47e081fcffd5c93f396a38ffd04d 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -1721,7 +1721,7 @@ static void set_curr_task_rt(struct rq *rq) dequeue_pushable_task(rq, p); } -unsigned int get_rr_interval_rt(struct task_struct *task) +unsigned int get_rr_interval_rt(struct rq *rq, struct task_struct *task) { /* * Time slice is 0 for SCHED_FIFO tasks diff --git a/kernel/softirq.c b/kernel/softirq.c index 21939d9e830e22b040f15e5562c97b0a8b8a9e47..a09502e2ef758721917ab537e345da0036197628 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -697,7 +697,7 @@ void __init softirq_init(void) open_softirq(HI_SOFTIRQ, tasklet_hi_action); } -static int ksoftirqd(void * __bind_cpu) +static int run_ksoftirqd(void * __bind_cpu) { set_current_state(TASK_INTERRUPTIBLE); @@ -810,7 +810,7 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_UP_PREPARE: case CPU_UP_PREPARE_FROZEN: - p = kthread_create(ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu); + p = kthread_create(run_ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu); if (IS_ERR(p)) { printk("ksoftirqd for %i failed\n", hotcpu); return NOTIFY_BAD; diff --git a/kernel/softlockup.c b/kernel/softlockup.c index 81324d12eb35a5db7fae8a0ae3d18c76ca38ce67..d22579087e27a5bdb04e3962b117432c29497b33 100644 --- a/kernel/softlockup.c +++ b/kernel/softlockup.c @@ -22,9 +22,9 @@ static DEFINE_SPINLOCK(print_lock); -static DEFINE_PER_CPU(unsigned long, touch_timestamp); -static DEFINE_PER_CPU(unsigned long, print_timestamp); -static DEFINE_PER_CPU(struct task_struct *, watchdog_task); +static DEFINE_PER_CPU(unsigned long, softlockup_touch_ts); /* touch timestamp */ +static DEFINE_PER_CPU(unsigned long, softlockup_print_ts); /* print timestamp */ +static DEFINE_PER_CPU(struct task_struct *, softlockup_watchdog); static int __read_mostly did_panic; int __read_mostly softlockup_thresh = 60; @@ -70,12 +70,12 @@ static void __touch_softlockup_watchdog(void) { int this_cpu = raw_smp_processor_id(); - __raw_get_cpu_var(touch_timestamp) = get_timestamp(this_cpu); + __raw_get_cpu_var(softlockup_touch_ts) = get_timestamp(this_cpu); } void touch_softlockup_watchdog(void) { - __raw_get_cpu_var(touch_timestamp) = 0; + __raw_get_cpu_var(softlockup_touch_ts) = 0; } EXPORT_SYMBOL(touch_softlockup_watchdog); @@ -85,7 +85,7 @@ void touch_all_softlockup_watchdogs(void) /* Cause each CPU to re-update its timestamp rather than complain */ for_each_online_cpu(cpu) - per_cpu(touch_timestamp, cpu) = 0; + per_cpu(softlockup_touch_ts, cpu) = 0; } EXPORT_SYMBOL(touch_all_softlockup_watchdogs); @@ -104,28 +104,28 @@ int proc_dosoftlockup_thresh(struct ctl_table *table, int write, void softlockup_tick(void) { int this_cpu = smp_processor_id(); - unsigned long touch_timestamp = per_cpu(touch_timestamp, this_cpu); - unsigned long print_timestamp; + unsigned long touch_ts = per_cpu(softlockup_touch_ts, this_cpu); + unsigned long print_ts; struct pt_regs *regs = get_irq_regs(); unsigned long now; /* Is detection switched off? */ - if (!per_cpu(watchdog_task, this_cpu) || softlockup_thresh <= 0) { + if (!per_cpu(softlockup_watchdog, this_cpu) || softlockup_thresh <= 0) { /* Be sure we don't false trigger if switched back on */ - if (touch_timestamp) - per_cpu(touch_timestamp, this_cpu) = 0; + if (touch_ts) + per_cpu(softlockup_touch_ts, this_cpu) = 0; return; } - if (touch_timestamp == 0) { + if (touch_ts == 0) { __touch_softlockup_watchdog(); return; } - print_timestamp = per_cpu(print_timestamp, this_cpu); + print_ts = per_cpu(softlockup_print_ts, this_cpu); /* report at most once a second */ - if (print_timestamp == touch_timestamp || did_panic) + if (print_ts == touch_ts || did_panic) return; /* do not print during early bootup: */ @@ -140,18 +140,18 @@ void softlockup_tick(void) * Wake up the high-prio watchdog task twice per * threshold timespan. */ - if (now > touch_timestamp + softlockup_thresh/2) - wake_up_process(per_cpu(watchdog_task, this_cpu)); + if (now > touch_ts + softlockup_thresh/2) + wake_up_process(per_cpu(softlockup_watchdog, this_cpu)); /* Warn about unreasonable delays: */ - if (now <= (touch_timestamp + softlockup_thresh)) + if (now <= (touch_ts + softlockup_thresh)) return; - per_cpu(print_timestamp, this_cpu) = touch_timestamp; + per_cpu(softlockup_print_ts, this_cpu) = touch_ts; spin_lock(&print_lock); printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %lus! [%s:%d]\n", - this_cpu, now - touch_timestamp, + this_cpu, now - touch_ts, current->comm, task_pid_nr(current)); print_modules(); print_irqtrace_events(current); @@ -209,32 +209,32 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) switch (action) { case CPU_UP_PREPARE: case CPU_UP_PREPARE_FROZEN: - BUG_ON(per_cpu(watchdog_task, hotcpu)); + BUG_ON(per_cpu(softlockup_watchdog, hotcpu)); p = kthread_create(watchdog, hcpu, "watchdog/%d", hotcpu); if (IS_ERR(p)) { printk(KERN_ERR "watchdog for %i failed\n", hotcpu); return NOTIFY_BAD; } - per_cpu(touch_timestamp, hotcpu) = 0; - per_cpu(watchdog_task, hotcpu) = p; + per_cpu(softlockup_touch_ts, hotcpu) = 0; + per_cpu(softlockup_watchdog, hotcpu) = p; kthread_bind(p, hotcpu); break; case CPU_ONLINE: case CPU_ONLINE_FROZEN: - wake_up_process(per_cpu(watchdog_task, hotcpu)); + wake_up_process(per_cpu(softlockup_watchdog, hotcpu)); break; #ifdef CONFIG_HOTPLUG_CPU case CPU_UP_CANCELED: case CPU_UP_CANCELED_FROZEN: - if (!per_cpu(watchdog_task, hotcpu)) + if (!per_cpu(softlockup_watchdog, hotcpu)) break; /* Unbind so it can run. Fall thru. */ - kthread_bind(per_cpu(watchdog_task, hotcpu), + kthread_bind(per_cpu(softlockup_watchdog, hotcpu), cpumask_any(cpu_online_mask)); case CPU_DEAD: case CPU_DEAD_FROZEN: - p = per_cpu(watchdog_task, hotcpu); - per_cpu(watchdog_task, hotcpu) = NULL; + p = per_cpu(softlockup_watchdog, hotcpu); + per_cpu(softlockup_watchdog, hotcpu) = NULL; kthread_stop(p); break; #endif /* CONFIG_HOTPLUG_CPU */ diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 9327a26765c57da2ec22d8c5b7be03b21dbb4f62..554ac4894f0f893a6f1e26a06e3076510f6dffe9 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -244,6 +244,10 @@ static int min_sched_granularity_ns = 100000; /* 100 usecs */ static int max_sched_granularity_ns = NSEC_PER_SEC; /* 1 second */ static int min_wakeup_granularity_ns; /* 0 usecs */ static int max_wakeup_granularity_ns = NSEC_PER_SEC; /* 1 second */ +static int min_sched_tunable_scaling = SCHED_TUNABLESCALING_NONE; +static int max_sched_tunable_scaling = SCHED_TUNABLESCALING_END-1; +static int min_sched_shares_ratelimit = 100000; /* 100 usec */ +static int max_sched_shares_ratelimit = NSEC_PER_SEC; /* 1 second */ #endif static struct ctl_table kern_table[] = { @@ -260,7 +264,7 @@ static struct ctl_table kern_table[] = { .data = &sysctl_sched_min_granularity, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = sched_nr_latency_handler, + .proc_handler = sched_proc_update_handler, .extra1 = &min_sched_granularity_ns, .extra2 = &max_sched_granularity_ns, }, @@ -269,7 +273,7 @@ static struct ctl_table kern_table[] = { .data = &sysctl_sched_latency, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = sched_nr_latency_handler, + .proc_handler = sched_proc_update_handler, .extra1 = &min_sched_granularity_ns, .extra2 = &max_sched_granularity_ns, }, @@ -278,7 +282,7 @@ static struct ctl_table kern_table[] = { .data = &sysctl_sched_wakeup_granularity, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = proc_dointvec_minmax, + .proc_handler = sched_proc_update_handler, .extra1 = &min_wakeup_granularity_ns, .extra2 = &max_wakeup_granularity_ns, }, @@ -287,7 +291,18 @@ static struct ctl_table kern_table[] = { .data = &sysctl_sched_shares_ratelimit, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = sched_proc_update_handler, + .extra1 = &min_sched_shares_ratelimit, + .extra2 = &max_sched_shares_ratelimit, + }, + { + .procname = "sched_tunable_scaling", + .data = &sysctl_sched_tunable_scaling, + .maxlen = sizeof(enum sched_tunable_scaling), + .mode = 0644, + .proc_handler = sched_proc_update_handler, + .extra1 = &min_sched_tunable_scaling, + .extra2 = &max_sched_tunable_scaling, }, { .procname = "sched_shares_thresh", @@ -297,13 +312,6 @@ static struct ctl_table kern_table[] = { .proc_handler = proc_dointvec_minmax, .extra1 = &zero, }, - { - .procname = "sched_features", - .data = &sysctl_sched_features, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, { .procname = "sched_migration_cost", .data = &sysctl_sched_migration_cost, diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index 665c76edbf1788e277390411810b09901264d416..9d80db4747d4d6371dc023cde7f5cbc73e20d4fa 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c @@ -150,6 +150,9 @@ static void print_cpu(struct seq_file *m, int cpu, u64 now) P_ns(expires_next); P(hres_active); P(nr_events); + P(nr_retries); + P(nr_hangs); + P_ns(max_hang_time); #endif #undef P #undef P_ns @@ -254,7 +257,7 @@ static int timer_list_show(struct seq_file *m, void *v) u64 now = ktime_to_ns(ktime_get()); int cpu; - SEQ_printf(m, "Timer List Version: v0.4\n"); + SEQ_printf(m, "Timer List Version: v0.5\n"); SEQ_printf(m, "HRTIMER_MAX_CLOCK_BASES: %d\n", HRTIMER_MAX_CLOCK_BASES); SEQ_printf(m, "now at %Ld nsecs\n", (unsigned long long)now); diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c index ee5681f8d7ecd2f1429d5455ea2839f12921b42f..63b117e9eba13fb430372601bdc36ff7d3ef42a2 100644 --- a/kernel/time/timer_stats.c +++ b/kernel/time/timer_stats.c @@ -86,7 +86,7 @@ static DEFINE_SPINLOCK(table_lock); /* * Per-CPU lookup locks for fast hash lookup: */ -static DEFINE_PER_CPU(spinlock_t, lookup_lock); +static DEFINE_PER_CPU(spinlock_t, tstats_lookup_lock); /* * Mutex to serialize state changes with show-stats activities: @@ -245,7 +245,7 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf, if (likely(!timer_stats_active)) return; - lock = &per_cpu(lookup_lock, raw_smp_processor_id()); + lock = &per_cpu(tstats_lookup_lock, raw_smp_processor_id()); input.timer = timer; input.start_func = startf; @@ -348,9 +348,10 @@ static void sync_access(void) int cpu; for_each_online_cpu(cpu) { - spin_lock_irqsave(&per_cpu(lookup_lock, cpu), flags); + spinlock_t *lock = &per_cpu(tstats_lookup_lock, cpu); + spin_lock_irqsave(lock, flags); /* nothing */ - spin_unlock_irqrestore(&per_cpu(lookup_lock, cpu), flags); + spin_unlock_irqrestore(lock, flags); } } @@ -408,7 +409,7 @@ void __init init_timer_stats(void) int cpu; for_each_possible_cpu(cpu) - spin_lock_init(&per_cpu(lookup_lock, cpu)); + spin_lock_init(&per_cpu(tstats_lookup_lock, cpu)); } static int __init init_tstats_procfs(void) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 874f2893cff0e1d65d97b99217feb30f9900b4f2..c82dfd92fdfd8d663b6146ea6a584d42ea715508 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -86,17 +86,17 @@ static int dummy_set_flag(u32 old_flags, u32 bit, int set) */ static int tracing_disabled = 1; -DEFINE_PER_CPU(local_t, ftrace_cpu_disabled); +DEFINE_PER_CPU(int, ftrace_cpu_disabled); static inline void ftrace_disable_cpu(void) { preempt_disable(); - local_inc(&__get_cpu_var(ftrace_cpu_disabled)); + __this_cpu_inc(per_cpu_var(ftrace_cpu_disabled)); } static inline void ftrace_enable_cpu(void) { - local_dec(&__get_cpu_var(ftrace_cpu_disabled)); + __this_cpu_dec(per_cpu_var(ftrace_cpu_disabled)); preempt_enable(); } @@ -203,7 +203,7 @@ cycle_t ftrace_now(int cpu) */ static struct trace_array max_tr; -static DEFINE_PER_CPU(struct trace_array_cpu, max_data); +static DEFINE_PER_CPU(struct trace_array_cpu, max_tr_data); /* tracer_enabled is used to toggle activation of a tracer */ static int tracer_enabled = 1; @@ -1085,7 +1085,7 @@ trace_function(struct trace_array *tr, struct ftrace_entry *entry; /* If we are reading the ring buffer, don't trace */ - if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled)))) + if (unlikely(__this_cpu_read(per_cpu_var(ftrace_cpu_disabled)))) return; event = trace_buffer_lock_reserve(buffer, TRACE_FN, sizeof(*entry), @@ -1361,11 +1361,7 @@ int trace_array_vprintk(struct trace_array *tr, pause_graph_tracing(); raw_local_irq_save(irq_flags); __raw_spin_lock(&trace_buf_lock); - if (args == NULL) { - strncpy(trace_buf, fmt, TRACE_BUF_SIZE); - len = strlen(trace_buf); - } else - len = vsnprintf(trace_buf, TRACE_BUF_SIZE, fmt, args); + len = vsnprintf(trace_buf, TRACE_BUF_SIZE, fmt, args); size = sizeof(*entry) + len + 1; buffer = tr->buffer; @@ -1516,6 +1512,8 @@ static void *s_next(struct seq_file *m, void *v, loff_t *pos) int i = (int)*pos; void *ent; + WARN_ON_ONCE(iter->leftover); + (*pos)++; /* can't go backwards */ @@ -1614,8 +1612,16 @@ static void *s_start(struct seq_file *m, loff_t *pos) ; } else { - l = *pos - 1; - p = s_next(m, p, &l); + /* + * If we overflowed the seq_file before, then we want + * to just reuse the trace_seq buffer again. + */ + if (iter->leftover) + p = iter; + else { + l = *pos - 1; + p = s_next(m, p, &l); + } } trace_event_read_lock(); @@ -1923,6 +1929,7 @@ static enum print_line_t print_trace_line(struct trace_iterator *iter) static int s_show(struct seq_file *m, void *v) { struct trace_iterator *iter = v; + int ret; if (iter->ent == NULL) { if (iter->tr) { @@ -1942,9 +1949,27 @@ static int s_show(struct seq_file *m, void *v) if (!(trace_flags & TRACE_ITER_VERBOSE)) print_func_help_header(m); } + } else if (iter->leftover) { + /* + * If we filled the seq_file buffer earlier, we + * want to just show it now. + */ + ret = trace_print_seq(m, &iter->seq); + + /* ret should this time be zero, but you never know */ + iter->leftover = ret; + } else { print_trace_line(iter); - trace_print_seq(m, &iter->seq); + ret = trace_print_seq(m, &iter->seq); + /* + * If we overflow the seq_file buffer, then it will + * ask us for this data again at start up. + * Use that instead. + * ret is 0 if seq_file write succeeded. + * -1 otherwise. + */ + iter->leftover = ret; } return 0; @@ -2898,6 +2923,10 @@ static int tracing_release_pipe(struct inode *inode, struct file *file) else cpumask_clear_cpu(iter->cpu_file, tracing_reader_cpumask); + + if (iter->trace->pipe_close) + iter->trace->pipe_close(iter); + mutex_unlock(&trace_types_lock); free_cpumask_var(iter->started); @@ -3320,6 +3349,16 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, return cnt; } +static int mark_printk(const char *fmt, ...) +{ + int ret; + va_list args; + va_start(args, fmt); + ret = trace_vprintk(0, fmt, args); + va_end(args); + return ret; +} + static ssize_t tracing_mark_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *fpos) @@ -3346,7 +3385,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, } else buf[cnt] = '\0'; - cnt = trace_vprintk(0, buf, NULL); + cnt = mark_printk("%s", buf); kfree(buf); *fpos += cnt; @@ -4415,7 +4454,7 @@ __init static int tracer_alloc_buffers(void) /* Allocate the first page for all buffers */ for_each_tracing_cpu(i) { global_trace.data[i] = &per_cpu(global_trace_cpu, i); - max_tr.data[i] = &per_cpu(max_data, i); + max_tr.data[i] = &per_cpu(max_tr_data, i); } trace_init_cmdlines(); diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 1d7f4830a80d93dd2b3c77a837ad18c5123819fc..a52bed2eedd848ec5e7c249d479baa8d14a98ad6 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -272,6 +272,7 @@ struct tracer_flags { * @pipe_open: called when the trace_pipe file is opened * @wait_pipe: override how the user waits for traces on trace_pipe * @close: called when the trace file is released + * @pipe_close: called when the trace_pipe file is released * @read: override the default read callback on trace_pipe * @splice_read: override the default splice_read callback on trace_pipe * @selftest: selftest to run on boot (see trace_selftest.c) @@ -290,6 +291,7 @@ struct tracer { void (*pipe_open)(struct trace_iterator *iter); void (*wait_pipe)(struct trace_iterator *iter); void (*close)(struct trace_iterator *iter); + void (*pipe_close)(struct trace_iterator *iter); ssize_t (*read)(struct trace_iterator *iter, struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos); @@ -441,7 +443,7 @@ extern int DYN_FTRACE_TEST_NAME(void); extern int ring_buffer_expanded; extern bool tracing_selftest_disabled; -DECLARE_PER_CPU(local_t, ftrace_cpu_disabled); +DECLARE_PER_CPU(int, ftrace_cpu_disabled); #ifdef CONFIG_FTRACE_STARTUP_TEST extern int trace_selftest_startup_function(struct tracer *trace, diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 45e6c01b2e4d96fc3eb9d4ef8b7a96bd7b60e30b..b1342c5d37cfb821cfb96fcfd610cb95cdfb1082 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c @@ -14,9 +14,20 @@ #include "trace.h" #include "trace_output.h" -struct fgraph_data { +struct fgraph_cpu_data { pid_t last_pid; int depth; + int ignore; +}; + +struct fgraph_data { + struct fgraph_cpu_data *cpu_data; + + /* Place to preserve last processed entry. */ + struct ftrace_graph_ent_entry ent; + struct ftrace_graph_ret_entry ret; + int failed; + int cpu; }; #define TRACE_GRAPH_INDENT 2 @@ -176,7 +187,7 @@ static int __trace_graph_entry(struct trace_array *tr, struct ring_buffer *buffer = tr->buffer; struct ftrace_graph_ent_entry *entry; - if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled)))) + if (unlikely(__this_cpu_read(per_cpu_var(ftrace_cpu_disabled)))) return 0; event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_ENT, @@ -240,7 +251,7 @@ static void __trace_graph_return(struct trace_array *tr, struct ring_buffer *buffer = tr->buffer; struct ftrace_graph_ret_entry *entry; - if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled)))) + if (unlikely(__this_cpu_read(per_cpu_var(ftrace_cpu_disabled)))) return; event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_RET, @@ -384,7 +395,7 @@ verif_pid(struct trace_seq *s, pid_t pid, int cpu, struct fgraph_data *data) if (!data) return TRACE_TYPE_HANDLED; - last_pid = &(per_cpu_ptr(data, cpu)->last_pid); + last_pid = &(per_cpu_ptr(data->cpu_data, cpu)->last_pid); if (*last_pid == pid) return TRACE_TYPE_HANDLED; @@ -435,26 +446,49 @@ static struct ftrace_graph_ret_entry * get_return_for_leaf(struct trace_iterator *iter, struct ftrace_graph_ent_entry *curr) { - struct ring_buffer_iter *ring_iter; + struct fgraph_data *data = iter->private; + struct ring_buffer_iter *ring_iter = NULL; struct ring_buffer_event *event; struct ftrace_graph_ret_entry *next; - ring_iter = iter->buffer_iter[iter->cpu]; + /* + * If the previous output failed to write to the seq buffer, + * then we just reuse the data from before. + */ + if (data && data->failed) { + curr = &data->ent; + next = &data->ret; + } else { - /* First peek to compare current entry and the next one */ - if (ring_iter) - event = ring_buffer_iter_peek(ring_iter, NULL); - else { - /* We need to consume the current entry to see the next one */ - ring_buffer_consume(iter->tr->buffer, iter->cpu, NULL); - event = ring_buffer_peek(iter->tr->buffer, iter->cpu, - NULL); - } + ring_iter = iter->buffer_iter[iter->cpu]; + + /* First peek to compare current entry and the next one */ + if (ring_iter) + event = ring_buffer_iter_peek(ring_iter, NULL); + else { + /* + * We need to consume the current entry to see + * the next one. + */ + ring_buffer_consume(iter->tr->buffer, iter->cpu, NULL); + event = ring_buffer_peek(iter->tr->buffer, iter->cpu, + NULL); + } - if (!event) - return NULL; + if (!event) + return NULL; + + next = ring_buffer_event_data(event); - next = ring_buffer_event_data(event); + if (data) { + /* + * Save current and next entries for later reference + * if the output fails. + */ + data->ent = *curr; + data->ret = *next; + } + } if (next->ent.type != TRACE_GRAPH_RET) return NULL; @@ -640,7 +674,7 @@ print_graph_entry_leaf(struct trace_iterator *iter, if (data) { int cpu = iter->cpu; - int *depth = &(per_cpu_ptr(data, cpu)->depth); + int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth); /* * Comments display at + 1 to depth. Since @@ -688,7 +722,7 @@ print_graph_entry_nested(struct trace_iterator *iter, if (data) { int cpu = iter->cpu; - int *depth = &(per_cpu_ptr(data, cpu)->depth); + int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth); *depth = call->depth; } @@ -782,19 +816,34 @@ static enum print_line_t print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s, struct trace_iterator *iter) { - int cpu = iter->cpu; + struct fgraph_data *data = iter->private; struct ftrace_graph_ent *call = &field->graph_ent; struct ftrace_graph_ret_entry *leaf_ret; + static enum print_line_t ret; + int cpu = iter->cpu; if (print_graph_prologue(iter, s, TRACE_GRAPH_ENT, call->func)) return TRACE_TYPE_PARTIAL_LINE; leaf_ret = get_return_for_leaf(iter, field); if (leaf_ret) - return print_graph_entry_leaf(iter, field, leaf_ret, s); + ret = print_graph_entry_leaf(iter, field, leaf_ret, s); else - return print_graph_entry_nested(iter, field, s, cpu); + ret = print_graph_entry_nested(iter, field, s, cpu); + if (data) { + /* + * If we failed to write our output, then we need to make + * note of it. Because we already consumed our entry. + */ + if (s->full) { + data->failed = 1; + data->cpu = cpu; + } else + data->failed = 0; + } + + return ret; } static enum print_line_t @@ -810,7 +859,7 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, if (data) { int cpu = iter->cpu; - int *depth = &(per_cpu_ptr(data, cpu)->depth); + int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth); /* * Comments display at + 1 to depth. This is the @@ -873,7 +922,7 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent, int i; if (data) - depth = per_cpu_ptr(data, iter->cpu)->depth; + depth = per_cpu_ptr(data->cpu_data, iter->cpu)->depth; if (print_graph_prologue(iter, s, 0, 0)) return TRACE_TYPE_PARTIAL_LINE; @@ -941,8 +990,33 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent, enum print_line_t print_graph_function(struct trace_iterator *iter) { + struct ftrace_graph_ent_entry *field; + struct fgraph_data *data = iter->private; struct trace_entry *entry = iter->ent; struct trace_seq *s = &iter->seq; + int cpu = iter->cpu; + int ret; + + if (data && per_cpu_ptr(data->cpu_data, cpu)->ignore) { + per_cpu_ptr(data->cpu_data, cpu)->ignore = 0; + return TRACE_TYPE_HANDLED; + } + + /* + * If the last output failed, there's a possibility we need + * to print out the missing entry which would never go out. + */ + if (data && data->failed) { + field = &data->ent; + iter->cpu = data->cpu; + ret = print_graph_entry(field, s, iter); + if (ret == TRACE_TYPE_HANDLED && iter->cpu != cpu) { + per_cpu_ptr(data->cpu_data, iter->cpu)->ignore = 1; + ret = TRACE_TYPE_NO_CONSUME; + } + iter->cpu = cpu; + return ret; + } switch (entry->type) { case TRACE_GRAPH_ENT: { @@ -952,7 +1026,7 @@ print_graph_function(struct trace_iterator *iter) * sizeof(struct ftrace_graph_ent_entry) is very small, * it can be safely saved at the stack. */ - struct ftrace_graph_ent_entry *field, saved; + struct ftrace_graph_ent_entry saved; trace_assign_type(field, entry); saved = *field; return print_graph_entry(&saved, s, iter); @@ -1030,31 +1104,54 @@ static void print_graph_headers(struct seq_file *s) static void graph_trace_open(struct trace_iterator *iter) { /* pid and depth on the last trace processed */ - struct fgraph_data *data = alloc_percpu(struct fgraph_data); + struct fgraph_data *data; int cpu; + iter->private = NULL; + + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) - pr_warning("function graph tracer: not enough memory\n"); - else - for_each_possible_cpu(cpu) { - pid_t *pid = &(per_cpu_ptr(data, cpu)->last_pid); - int *depth = &(per_cpu_ptr(data, cpu)->depth); - *pid = -1; - *depth = 0; - } + goto out_err; + + data->cpu_data = alloc_percpu(struct fgraph_cpu_data); + if (!data->cpu_data) + goto out_err_free; + + for_each_possible_cpu(cpu) { + pid_t *pid = &(per_cpu_ptr(data->cpu_data, cpu)->last_pid); + int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth); + int *ignore = &(per_cpu_ptr(data->cpu_data, cpu)->ignore); + *pid = -1; + *depth = 0; + *ignore = 0; + } iter->private = data; + + return; + + out_err_free: + kfree(data); + out_err: + pr_warning("function graph tracer: not enough memory\n"); } static void graph_trace_close(struct trace_iterator *iter) { - free_percpu(iter->private); + struct fgraph_data *data = iter->private; + + if (data) { + free_percpu(data->cpu_data); + kfree(data); + } } static struct tracer graph_trace __read_mostly = { .name = "function_graph", .open = graph_trace_open, + .pipe_open = graph_trace_open, .close = graph_trace_close, + .pipe_close = graph_trace_close, .wait_pipe = poll_wait_pipe, .init = graph_trace_init, .reset = graph_trace_reset, diff --git a/kernel/trace/trace_hw_branches.c b/kernel/trace/trace_hw_branches.c index 69543a905cd5f1c92086cb47576a21028db11a37..7b97000745f5cc38601aff4101b58d9d8bb99b6c 100644 --- a/kernel/trace/trace_hw_branches.c +++ b/kernel/trace/trace_hw_branches.c @@ -20,10 +20,10 @@ #define BTS_BUFFER_SIZE (1 << 13) -static DEFINE_PER_CPU(struct bts_tracer *, tracer); -static DEFINE_PER_CPU(unsigned char[BTS_BUFFER_SIZE], buffer); +static DEFINE_PER_CPU(struct bts_tracer *, hwb_tracer); +static DEFINE_PER_CPU(unsigned char[BTS_BUFFER_SIZE], hwb_buffer); -#define this_tracer per_cpu(tracer, smp_processor_id()) +#define this_tracer per_cpu(hwb_tracer, smp_processor_id()) static int trace_hw_branches_enabled __read_mostly; static int trace_hw_branches_suspended __read_mostly; @@ -32,12 +32,13 @@ static struct trace_array *hw_branch_trace __read_mostly; static void bts_trace_init_cpu(int cpu) { - per_cpu(tracer, cpu) = - ds_request_bts_cpu(cpu, per_cpu(buffer, cpu), BTS_BUFFER_SIZE, - NULL, (size_t)-1, BTS_KERNEL); + per_cpu(hwb_tracer, cpu) = + ds_request_bts_cpu(cpu, per_cpu(hwb_buffer, cpu), + BTS_BUFFER_SIZE, NULL, (size_t)-1, + BTS_KERNEL); - if (IS_ERR(per_cpu(tracer, cpu))) - per_cpu(tracer, cpu) = NULL; + if (IS_ERR(per_cpu(hwb_tracer, cpu))) + per_cpu(hwb_tracer, cpu) = NULL; } static int bts_trace_init(struct trace_array *tr) @@ -51,7 +52,7 @@ static int bts_trace_init(struct trace_array *tr) for_each_online_cpu(cpu) { bts_trace_init_cpu(cpu); - if (likely(per_cpu(tracer, cpu))) + if (likely(per_cpu(hwb_tracer, cpu))) trace_hw_branches_enabled = 1; } trace_hw_branches_suspended = 0; @@ -67,9 +68,9 @@ static void bts_trace_reset(struct trace_array *tr) get_online_cpus(); for_each_online_cpu(cpu) { - if (likely(per_cpu(tracer, cpu))) { - ds_release_bts(per_cpu(tracer, cpu)); - per_cpu(tracer, cpu) = NULL; + if (likely(per_cpu(hwb_tracer, cpu))) { + ds_release_bts(per_cpu(hwb_tracer, cpu)); + per_cpu(hwb_tracer, cpu) = NULL; } } trace_hw_branches_enabled = 0; @@ -83,8 +84,8 @@ static void bts_trace_start(struct trace_array *tr) get_online_cpus(); for_each_online_cpu(cpu) - if (likely(per_cpu(tracer, cpu))) - ds_resume_bts(per_cpu(tracer, cpu)); + if (likely(per_cpu(hwb_tracer, cpu))) + ds_resume_bts(per_cpu(hwb_tracer, cpu)); trace_hw_branches_suspended = 0; put_online_cpus(); } @@ -95,8 +96,8 @@ static void bts_trace_stop(struct trace_array *tr) get_online_cpus(); for_each_online_cpu(cpu) - if (likely(per_cpu(tracer, cpu))) - ds_suspend_bts(per_cpu(tracer, cpu)); + if (likely(per_cpu(hwb_tracer, cpu))) + ds_suspend_bts(per_cpu(hwb_tracer, cpu)); trace_hw_branches_suspended = 1; put_online_cpus(); } @@ -114,16 +115,16 @@ static int __cpuinit bts_hotcpu_handler(struct notifier_block *nfb, bts_trace_init_cpu(cpu); if (trace_hw_branches_suspended && - likely(per_cpu(tracer, cpu))) - ds_suspend_bts(per_cpu(tracer, cpu)); + likely(per_cpu(hwb_tracer, cpu))) + ds_suspend_bts(per_cpu(hwb_tracer, cpu)); } break; case CPU_DOWN_PREPARE: /* The notification is sent with interrupts enabled. */ - if (likely(per_cpu(tracer, cpu))) { - ds_release_bts(per_cpu(tracer, cpu)); - per_cpu(tracer, cpu) = NULL; + if (likely(per_cpu(hwb_tracer, cpu))) { + ds_release_bts(per_cpu(hwb_tracer, cpu)); + per_cpu(hwb_tracer, cpu) = NULL; } } @@ -258,8 +259,8 @@ static void trace_bts_prepare(struct trace_iterator *iter) get_online_cpus(); for_each_online_cpu(cpu) - if (likely(per_cpu(tracer, cpu))) - ds_suspend_bts(per_cpu(tracer, cpu)); + if (likely(per_cpu(hwb_tracer, cpu))) + ds_suspend_bts(per_cpu(hwb_tracer, cpu)); /* * We need to collect the trace on the respective cpu since ftrace * implicitly adds the record for the current cpu. @@ -268,8 +269,8 @@ static void trace_bts_prepare(struct trace_iterator *iter) on_each_cpu(trace_bts_cpu, iter->tr, 1); for_each_online_cpu(cpu) - if (likely(per_cpu(tracer, cpu))) - ds_resume_bts(per_cpu(tracer, cpu)); + if (likely(per_cpu(hwb_tracer, cpu))) + ds_resume_bts(per_cpu(hwb_tracer, cpu)); put_online_cpus(); } diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index aff5f80b59b8785cffe69091aa48a225d700add8..b52d397e57ebefbdbc40c84e66460847e8041fd5 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -606,23 +606,22 @@ static int create_trace_probe(int argc, char **argv) */ struct trace_probe *tp; int i, ret = 0; - int is_return = 0; + int is_return = 0, is_delete = 0; char *symbol = NULL, *event = NULL, *arg = NULL, *group = NULL; unsigned long offset = 0; void *addr = NULL; char buf[MAX_EVENT_NAME_LEN]; - if (argc < 2) { - pr_info("Probe point is not specified.\n"); - return -EINVAL; - } - + /* argc must be >= 1 */ if (argv[0][0] == 'p') is_return = 0; else if (argv[0][0] == 'r') is_return = 1; + else if (argv[0][0] == '-') + is_delete = 1; else { - pr_info("Probe definition must be started with 'p' or 'r'.\n"); + pr_info("Probe definition must be started with 'p', 'r' or" + " '-'.\n"); return -EINVAL; } @@ -642,7 +641,29 @@ static int create_trace_probe(int argc, char **argv) return -EINVAL; } } + if (!group) + group = KPROBE_EVENT_SYSTEM; + if (is_delete) { + if (!event) { + pr_info("Delete command needs an event name.\n"); + return -EINVAL; + } + tp = find_probe_event(event, group); + if (!tp) { + pr_info("Event %s/%s doesn't exist.\n", group, event); + return -ENOENT; + } + /* delete an event */ + unregister_trace_probe(tp); + free_trace_probe(tp); + return 0; + } + + if (argc < 2) { + pr_info("Probe point is not specified.\n"); + return -EINVAL; + } if (isdigit(argv[1][0])) { if (is_return) { pr_info("Return probe point must be a symbol.\n"); @@ -671,8 +692,6 @@ static int create_trace_probe(int argc, char **argv) argc -= 2; argv += 2; /* setup a probe */ - if (!group) - group = KPROBE_EVENT_SYSTEM; if (!event) { /* Make a new event name */ if (symbol) @@ -1114,7 +1133,7 @@ static int kprobe_event_define_fields(struct ftrace_event_call *event_call) struct trace_probe *tp = (struct trace_probe *)event_call->data; ret = trace_define_common_fields(event_call); - if (!ret) + if (ret) return ret; DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); @@ -1132,7 +1151,7 @@ static int kretprobe_event_define_fields(struct ftrace_event_call *event_call) struct trace_probe *tp = (struct trace_probe *)event_call->data; ret = trace_define_common_fields(event_call); - if (!ret) + if (ret) return ret; DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0); diff --git a/kernel/trace/trace_ksym.c b/kernel/trace/trace_ksym.c index ddfa0fd43bc0ebab1fa4953918a41323f409e08a..acb87d4a4ac15e8127fc64138918111a1e948936 100644 --- a/kernel/trace/trace_ksym.c +++ b/kernel/trace/trace_ksym.c @@ -79,11 +79,12 @@ void ksym_collect_stats(unsigned long hbp_hit_addr) } #endif /* CONFIG_PROFILE_KSYM_TRACER */ -void ksym_hbp_handler(struct perf_event *hbp, void *data) +void ksym_hbp_handler(struct perf_event *hbp, int nmi, + struct perf_sample_data *data, + struct pt_regs *regs) { struct ring_buffer_event *event; struct ksym_trace_entry *entry; - struct pt_regs *regs = data; struct ring_buffer *buffer; int pc; diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index b6c12c6a1bcde267a7e25d6b1b8df41c559f1500..8e46b3323cdcdd91ad9833aa1eb8d0f1bf82f3af 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c @@ -23,13 +23,21 @@ static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly; static int next_event_type = __TRACE_LAST_TYPE + 1; -void trace_print_seq(struct seq_file *m, struct trace_seq *s) +int trace_print_seq(struct seq_file *m, struct trace_seq *s) { int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len; + int ret; + + ret = seq_write(m, s->buffer, len); - seq_write(m, s->buffer, len); + /* + * Only reset this buffer if we successfully wrote to the + * seq_file buffer. + */ + if (!ret) + trace_seq_init(s); - trace_seq_init(s); + return ret; } enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter) @@ -85,7 +93,7 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...) va_list ap; int ret; - if (!len) + if (s->full || !len) return 0; va_start(ap, fmt); @@ -93,8 +101,10 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...) va_end(ap); /* If we can't write it all, don't bother writing anything */ - if (ret >= len) + if (ret >= len) { + s->full = 1; return 0; + } s->len += ret; @@ -119,14 +129,16 @@ trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) int len = (PAGE_SIZE - 1) - s->len; int ret; - if (!len) + if (s->full || !len) return 0; ret = vsnprintf(s->buffer + s->len, len, fmt, args); /* If we can't write it all, don't bother writing anything */ - if (ret >= len) + if (ret >= len) { + s->full = 1; return 0; + } s->len += ret; @@ -139,14 +151,16 @@ int trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) int len = (PAGE_SIZE - 1) - s->len; int ret; - if (!len) + if (s->full || !len) return 0; ret = bstr_printf(s->buffer + s->len, len, fmt, binary); /* If we can't write it all, don't bother writing anything */ - if (ret >= len) + if (ret >= len) { + s->full = 1; return 0; + } s->len += ret; @@ -167,8 +181,13 @@ int trace_seq_puts(struct trace_seq *s, const char *str) { int len = strlen(str); - if (len > ((PAGE_SIZE - 1) - s->len)) + if (s->full) + return 0; + + if (len > ((PAGE_SIZE - 1) - s->len)) { + s->full = 1; return 0; + } memcpy(s->buffer + s->len, str, len); s->len += len; @@ -178,9 +197,14 @@ int trace_seq_puts(struct trace_seq *s, const char *str) int trace_seq_putc(struct trace_seq *s, unsigned char c) { - if (s->len >= (PAGE_SIZE - 1)) + if (s->full) return 0; + if (s->len >= (PAGE_SIZE - 1)) { + s->full = 1; + return 0; + } + s->buffer[s->len++] = c; return 1; @@ -188,9 +212,14 @@ int trace_seq_putc(struct trace_seq *s, unsigned char c) int trace_seq_putmem(struct trace_seq *s, const void *mem, size_t len) { - if (len > ((PAGE_SIZE - 1) - s->len)) + if (s->full) return 0; + if (len > ((PAGE_SIZE - 1) - s->len)) { + s->full = 1; + return 0; + } + memcpy(s->buffer + s->len, mem, len); s->len += len; @@ -203,6 +232,9 @@ int trace_seq_putmem_hex(struct trace_seq *s, const void *mem, size_t len) const unsigned char *data = mem; int i, j; + if (s->full) + return 0; + #ifdef __BIG_ENDIAN for (i = 0, j = 0; i < len; i++) { #else @@ -220,8 +252,13 @@ void *trace_seq_reserve(struct trace_seq *s, size_t len) { void *ret; - if (len > ((PAGE_SIZE - 1) - s->len)) + if (s->full) + return 0; + + if (len > ((PAGE_SIZE - 1) - s->len)) { + s->full = 1; return NULL; + } ret = s->buffer + s->len; s->len += len; @@ -233,8 +270,14 @@ int trace_seq_path(struct trace_seq *s, struct path *path) { unsigned char *p; - if (s->len >= (PAGE_SIZE - 1)) + if (s->full) + return 0; + + if (s->len >= (PAGE_SIZE - 1)) { + s->full = 1; return 0; + } + p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len); if (!IS_ERR(p)) { p = mangle_path(s->buffer + s->len, p, "\n"); @@ -247,6 +290,7 @@ int trace_seq_path(struct trace_seq *s, struct path *path) return 1; } + s->full = 1; return 0; } @@ -373,6 +417,9 @@ int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm, unsigned long vmstart = 0; int ret = 1; + if (s->full) + return 0; + if (mm) { const struct vm_area_struct *vma; diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 67e526b6ae815bbc846fd0424d43399f9fb5a0ba..dee48658805c4e58d1b4fc5776a165cc18e8c464 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -68,6 +68,116 @@ struct workqueue_struct { #endif }; +#ifdef CONFIG_DEBUG_OBJECTS_WORK + +static struct debug_obj_descr work_debug_descr; + +/* + * fixup_init is called when: + * - an active object is initialized + */ +static int work_fixup_init(void *addr, enum debug_obj_state state) +{ + struct work_struct *work = addr; + + switch (state) { + case ODEBUG_STATE_ACTIVE: + cancel_work_sync(work); + debug_object_init(work, &work_debug_descr); + return 1; + default: + return 0; + } +} + +/* + * fixup_activate is called when: + * - an active object is activated + * - an unknown object is activated (might be a statically initialized object) + */ +static int work_fixup_activate(void *addr, enum debug_obj_state state) +{ + struct work_struct *work = addr; + + switch (state) { + + case ODEBUG_STATE_NOTAVAILABLE: + /* + * This is not really a fixup. The work struct was + * statically initialized. We just make sure that it + * is tracked in the object tracker. + */ + if (test_bit(WORK_STRUCT_STATIC, work_data_bits(work))) { + debug_object_init(work, &work_debug_descr); + debug_object_activate(work, &work_debug_descr); + return 0; + } + WARN_ON_ONCE(1); + return 0; + + case ODEBUG_STATE_ACTIVE: + WARN_ON(1); + + default: + return 0; + } +} + +/* + * fixup_free is called when: + * - an active object is freed + */ +static int work_fixup_free(void *addr, enum debug_obj_state state) +{ + struct work_struct *work = addr; + + switch (state) { + case ODEBUG_STATE_ACTIVE: + cancel_work_sync(work); + debug_object_free(work, &work_debug_descr); + return 1; + default: + return 0; + } +} + +static struct debug_obj_descr work_debug_descr = { + .name = "work_struct", + .fixup_init = work_fixup_init, + .fixup_activate = work_fixup_activate, + .fixup_free = work_fixup_free, +}; + +static inline void debug_work_activate(struct work_struct *work) +{ + debug_object_activate(work, &work_debug_descr); +} + +static inline void debug_work_deactivate(struct work_struct *work) +{ + debug_object_deactivate(work, &work_debug_descr); +} + +void __init_work(struct work_struct *work, int onstack) +{ + if (onstack) + debug_object_init_on_stack(work, &work_debug_descr); + else + debug_object_init(work, &work_debug_descr); +} +EXPORT_SYMBOL_GPL(__init_work); + +void destroy_work_on_stack(struct work_struct *work) +{ + debug_object_free(work, &work_debug_descr); +} +EXPORT_SYMBOL_GPL(destroy_work_on_stack); + +#else +static inline void debug_work_activate(struct work_struct *work) { } +static inline void debug_work_deactivate(struct work_struct *work) { } +#endif + /* Serializes the accesses to the list of workqueues. */ static DEFINE_SPINLOCK(workqueue_lock); static LIST_HEAD(workqueues); @@ -145,6 +255,7 @@ static void __queue_work(struct cpu_workqueue_struct *cwq, { unsigned long flags; + debug_work_activate(work); spin_lock_irqsave(&cwq->lock, flags); insert_work(cwq, work, &cwq->worklist); spin_unlock_irqrestore(&cwq->lock, flags); @@ -280,6 +391,7 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq) struct lockdep_map lockdep_map = work->lockdep_map; #endif trace_workqueue_execution(cwq->thread, work); + debug_work_deactivate(work); cwq->current_work = work; list_del_init(cwq->worklist.next); spin_unlock_irq(&cwq->lock); @@ -350,11 +462,18 @@ static void wq_barrier_func(struct work_struct *work) static void insert_wq_barrier(struct cpu_workqueue_struct *cwq, struct wq_barrier *barr, struct list_head *head) { - INIT_WORK(&barr->work, wq_barrier_func); + /* + * debugobject calls are safe here even with cwq->lock locked + * as we know for sure that this will not trigger any of the + * checks and call back into the fixup functions where we + * might deadlock. + */ + INIT_WORK_ON_STACK(&barr->work, wq_barrier_func); __set_bit(WORK_STRUCT_PENDING, work_data_bits(&barr->work)); init_completion(&barr->done); + debug_work_activate(&barr->work); insert_work(cwq, &barr->work, head); } @@ -372,8 +491,10 @@ static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq) } spin_unlock_irq(&cwq->lock); - if (active) + if (active) { wait_for_completion(&barr.done); + destroy_work_on_stack(&barr.work); + } return active; } @@ -451,6 +572,7 @@ out: return 0; wait_for_completion(&barr.done); + destroy_work_on_stack(&barr.work); return 1; } EXPORT_SYMBOL_GPL(flush_work); @@ -485,6 +607,7 @@ static int try_to_grab_pending(struct work_struct *work) */ smp_rmb(); if (cwq == get_wq_data(work)) { + debug_work_deactivate(work); list_del_init(&work->entry); ret = 1; } @@ -507,8 +630,10 @@ static void wait_on_cpu_work(struct cpu_workqueue_struct *cwq, } spin_unlock_irq(&cwq->lock); - if (unlikely(running)) + if (unlikely(running)) { wait_for_completion(&barr.done); + destroy_work_on_stack(&barr.work); + } } static void wait_on_work(struct work_struct *work) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 96c620a0c59cdf7a052e0737ab759ef21f70b3bc..2f22cf4576dbe719754d329adf18e041c19e2f19 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -298,6 +298,14 @@ config DEBUG_OBJECTS_TIMERS timer routines to track the life time of timer objects and validate the timer operations. +config DEBUG_OBJECTS_WORK + bool "Debug work objects" + depends on DEBUG_OBJECTS + help + If you say Y here, additional code will be inserted into the + work queue routines to track the life time of work objects and + validate the work operations. + config DEBUG_OBJECTS_ENABLE_DEFAULT int "debug_objects bootup default value (0-1)" range 0 1 diff --git a/lib/checksum.c b/lib/checksum.c index b2e2fd4684618341adaff20dea8d04edfd99ec90..097508732f34fdbb9de955509685f43df2feba32 100644 --- a/lib/checksum.c +++ b/lib/checksum.c @@ -37,7 +37,8 @@ #include -static inline unsigned short from32to16(unsigned long x) +#ifndef do_csum +static inline unsigned short from32to16(unsigned int x) { /* add up 16-bit and 16-bit for 16+c bit */ x = (x & 0xffff) + (x >> 16); @@ -49,16 +50,16 @@ static inline unsigned short from32to16(unsigned long x) static unsigned int do_csum(const unsigned char *buff, int len) { int odd, count; - unsigned long result = 0; + unsigned int result = 0; if (len <= 0) goto out; odd = 1 & (unsigned long) buff; if (odd) { #ifdef __LITTLE_ENDIAN - result = *buff; -#else result += (*buff << 8); +#else + result = *buff; #endif len--; buff++; @@ -73,9 +74,9 @@ static unsigned int do_csum(const unsigned char *buff, int len) } count >>= 1; /* nr of 32-bit words.. */ if (count) { - unsigned long carry = 0; + unsigned int carry = 0; do { - unsigned long w = *(unsigned int *) buff; + unsigned int w = *(unsigned int *) buff; count--; buff += 4; result += carry; @@ -102,6 +103,7 @@ static unsigned int do_csum(const unsigned char *buff, int len) out: return result; } +#endif /* * This is a version of ip_compute_csum() optimized for IP headers, diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c index 4ebfa5a164d7d7f2e6089bbe8ca299c432ca9208..5526b46aba9457598bd091f55863da63fce26aa5 100644 --- a/lib/kernel_lock.c +++ b/lib/kernel_lock.c @@ -122,8 +122,10 @@ void __lockfunc _lock_kernel(const char *func, const char *file, int line) trace_lock_kernel(func, file, line); - if (likely(!depth)) + if (likely(!depth)) { + might_sleep(); __lock_kernel(); + } current->lock_depth = depth; } diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 33bed5e67a2110b2201856b8828b457110147728..6438cd5599eefe583451b9b5bd858b9ab5a0ca38 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -595,37 +595,89 @@ static char *symbol_string(char *buf, char *end, void *ptr, } static char *resource_string(char *buf, char *end, struct resource *res, - struct printf_spec spec) + struct printf_spec spec, const char *fmt) { #ifndef IO_RSRC_PRINTK_SIZE -#define IO_RSRC_PRINTK_SIZE 4 +#define IO_RSRC_PRINTK_SIZE 6 #endif #ifndef MEM_RSRC_PRINTK_SIZE -#define MEM_RSRC_PRINTK_SIZE 8 +#define MEM_RSRC_PRINTK_SIZE 10 #endif - struct printf_spec num_spec = { + struct printf_spec hex_spec = { .base = 16, .precision = -1, .flags = SPECIAL | SMALL | ZEROPAD, }; - /* room for the actual numbers, the two "0x", -, [, ] and the final zero */ - char sym[4*sizeof(resource_size_t) + 8]; + struct printf_spec dec_spec = { + .base = 10, + .precision = -1, + .flags = 0, + }; + struct printf_spec str_spec = { + .field_width = -1, + .precision = 10, + .flags = LEFT, + }; + struct printf_spec flag_spec = { + .base = 16, + .precision = -1, + .flags = SPECIAL | SMALL, + }; + + /* 32-bit res (sizeof==4): 10 chars in dec, 10 in hex ("0x" + 8) + * 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */ +#define RSRC_BUF_SIZE ((2 * sizeof(resource_size_t)) + 4) +#define FLAG_BUF_SIZE (2 * sizeof(res->flags)) +#define DECODED_BUF_SIZE sizeof("[mem - 64bit pref disabled]") +#define RAW_BUF_SIZE sizeof("[mem - flags 0x]") + char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE, + 2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)]; + char *p = sym, *pend = sym + sizeof(sym); - int size = -1; + int size = -1, addr = 0; + int decode = (fmt[0] == 'R') ? 1 : 0; - if (res->flags & IORESOURCE_IO) + if (res->flags & IORESOURCE_IO) { size = IO_RSRC_PRINTK_SIZE; - else if (res->flags & IORESOURCE_MEM) + addr = 1; + } else if (res->flags & IORESOURCE_MEM) { size = MEM_RSRC_PRINTK_SIZE; + addr = 1; + } *p++ = '['; - num_spec.field_width = size; - p = number(p, pend, res->start, num_spec); - *p++ = '-'; - p = number(p, pend, res->end, num_spec); + if (res->flags & IORESOURCE_IO) + p = string(p, pend, "io ", str_spec); + else if (res->flags & IORESOURCE_MEM) + p = string(p, pend, "mem ", str_spec); + else if (res->flags & IORESOURCE_IRQ) + p = string(p, pend, "irq ", str_spec); + else if (res->flags & IORESOURCE_DMA) + p = string(p, pend, "dma ", str_spec); + else { + p = string(p, pend, "??? ", str_spec); + decode = 0; + } + hex_spec.field_width = size; + p = number(p, pend, res->start, addr ? hex_spec : dec_spec); + if (res->start != res->end) { + *p++ = '-'; + p = number(p, pend, res->end, addr ? hex_spec : dec_spec); + } + if (decode) { + if (res->flags & IORESOURCE_MEM_64) + p = string(p, pend, " 64bit", str_spec); + if (res->flags & IORESOURCE_PREFETCH) + p = string(p, pend, " pref", str_spec); + if (res->flags & IORESOURCE_DISABLED) + p = string(p, pend, " disabled", str_spec); + } else { + p = string(p, pend, " flags ", str_spec); + p = number(p, pend, res->flags, flag_spec); + } *p++ = ']'; - *p = 0; + *p = '\0'; return string(buf, end, sym, spec); } @@ -801,8 +853,8 @@ static char *ip4_addr_string(char *buf, char *end, const u8 *addr, * - 'f' For simple symbolic function names without offset * - 'S' For symbolic direct pointers with offset * - 's' For symbolic direct pointers without offset - * - 'R' For a struct resource pointer, it prints the range of - * addresses (not the name nor the flags) + * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref] + * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201] * - 'M' For a 6-byte MAC address, it prints the address in the * usual colon-separated hex notation * - 'm' For a 6-byte MAC address, it prints the hex address without colons @@ -833,7 +885,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, case 'S': return symbol_string(buf, end, ptr, spec, *fmt); case 'R': - return resource_string(buf, end, ptr, spec); + case 'r': + return resource_string(buf, end, ptr, spec, fmt); case 'M': /* Colon separated: 00:01:02:03:04:05 */ case 'm': /* Contiguous: 000102030405 */ return mac_address_string(buf, end, ptr, spec, fmt); diff --git a/mm/Makefile b/mm/Makefile index ebf849042ed3d6dd6dc7543d47d35585077b8a1b..82131d0f8d85fbfb007e084e882333771dd47c10 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -34,11 +34,7 @@ obj-$(CONFIG_FAILSLAB) += failslab.o obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o obj-$(CONFIG_FS_XIP) += filemap_xip.o obj-$(CONFIG_MIGRATION) += migrate.o -ifndef CONFIG_HAVE_LEGACY_PER_CPU_AREA obj-$(CONFIG_SMP) += percpu.o -else -obj-$(CONFIG_SMP) += allocpercpu.o -endif obj-$(CONFIG_QUICKLIST) += quicklist.o obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o obj-$(CONFIG_MEMORY_FAILURE) += memory-failure.o diff --git a/mm/allocpercpu.c b/mm/allocpercpu.c deleted file mode 100644 index df34ceae0c678569446930eaf5ceb982a496f8b9..0000000000000000000000000000000000000000 --- a/mm/allocpercpu.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * linux/mm/allocpercpu.c - * - * Separated from slab.c August 11, 2006 Christoph Lameter - */ -#include -#include -#include -#include - -#ifndef cache_line_size -#define cache_line_size() L1_CACHE_BYTES -#endif - -/** - * percpu_depopulate - depopulate per-cpu data for given cpu - * @__pdata: per-cpu data to depopulate - * @cpu: depopulate per-cpu data for this cpu - * - * Depopulating per-cpu data for a cpu going offline would be a typical - * use case. You need to register a cpu hotplug handler for that purpose. - */ -static void percpu_depopulate(void *__pdata, int cpu) -{ - struct percpu_data *pdata = __percpu_disguise(__pdata); - - kfree(pdata->ptrs[cpu]); - pdata->ptrs[cpu] = NULL; -} - -/** - * percpu_depopulate_mask - depopulate per-cpu data for some cpu's - * @__pdata: per-cpu data to depopulate - * @mask: depopulate per-cpu data for cpu's selected through mask bits - */ -static void __percpu_depopulate_mask(void *__pdata, const cpumask_t *mask) -{ - int cpu; - for_each_cpu_mask_nr(cpu, *mask) - percpu_depopulate(__pdata, cpu); -} - -#define percpu_depopulate_mask(__pdata, mask) \ - __percpu_depopulate_mask((__pdata), &(mask)) - -/** - * percpu_populate - populate per-cpu data for given cpu - * @__pdata: per-cpu data to populate further - * @size: size of per-cpu object - * @gfp: may sleep or not etc. - * @cpu: populate per-data for this cpu - * - * Populating per-cpu data for a cpu coming online would be a typical - * use case. You need to register a cpu hotplug handler for that purpose. - * Per-cpu object is populated with zeroed buffer. - */ -static void *percpu_populate(void *__pdata, size_t size, gfp_t gfp, int cpu) -{ - struct percpu_data *pdata = __percpu_disguise(__pdata); - int node = cpu_to_node(cpu); - - /* - * We should make sure each CPU gets private memory. - */ - size = roundup(size, cache_line_size()); - - BUG_ON(pdata->ptrs[cpu]); - if (node_online(node)) - pdata->ptrs[cpu] = kmalloc_node(size, gfp|__GFP_ZERO, node); - else - pdata->ptrs[cpu] = kzalloc(size, gfp); - return pdata->ptrs[cpu]; -} - -/** - * percpu_populate_mask - populate per-cpu data for more cpu's - * @__pdata: per-cpu data to populate further - * @size: size of per-cpu object - * @gfp: may sleep or not etc. - * @mask: populate per-cpu data for cpu's selected through mask bits - * - * Per-cpu objects are populated with zeroed buffers. - */ -static int __percpu_populate_mask(void *__pdata, size_t size, gfp_t gfp, - cpumask_t *mask) -{ - cpumask_t populated; - int cpu; - - cpus_clear(populated); - for_each_cpu_mask_nr(cpu, *mask) - if (unlikely(!percpu_populate(__pdata, size, gfp, cpu))) { - __percpu_depopulate_mask(__pdata, &populated); - return -ENOMEM; - } else - cpu_set(cpu, populated); - return 0; -} - -#define percpu_populate_mask(__pdata, size, gfp, mask) \ - __percpu_populate_mask((__pdata), (size), (gfp), &(mask)) - -/** - * alloc_percpu - initial setup of per-cpu data - * @size: size of per-cpu object - * @align: alignment - * - * Allocate dynamic percpu area. Percpu objects are populated with - * zeroed buffers. - */ -void *__alloc_percpu(size_t size, size_t align) -{ - /* - * We allocate whole cache lines to avoid false sharing - */ - size_t sz = roundup(nr_cpu_ids * sizeof(void *), cache_line_size()); - void *pdata = kzalloc(sz, GFP_KERNEL); - void *__pdata = __percpu_disguise(pdata); - - /* - * Can't easily make larger alignment work with kmalloc. WARN - * on it. Larger alignment should only be used for module - * percpu sections on SMP for which this path isn't used. - */ - WARN_ON_ONCE(align > SMP_CACHE_BYTES); - - if (unlikely(!pdata)) - return NULL; - if (likely(!__percpu_populate_mask(__pdata, size, GFP_KERNEL, - &cpu_possible_map))) - return __pdata; - kfree(pdata); - return NULL; -} -EXPORT_SYMBOL_GPL(__alloc_percpu); - -/** - * free_percpu - final cleanup of per-cpu data - * @__pdata: object to clean up - * - * We simply clean up any per-cpu object left. No need for the client to - * track and specify through a bis mask which per-cpu objects are to free. - */ -void free_percpu(void *__pdata) -{ - if (unlikely(!__pdata)) - return; - __percpu_depopulate_mask(__pdata, cpu_possible_mask); - kfree(__percpu_disguise(__pdata)); -} -EXPORT_SYMBOL_GPL(free_percpu); - -/* - * Generic percpu area setup. - */ -#ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA -unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; - -EXPORT_SYMBOL(__per_cpu_offset); - -void __init setup_per_cpu_areas(void) -{ - unsigned long size, i; - char *ptr; - unsigned long nr_possible_cpus = num_possible_cpus(); - - /* Copy section for each CPU (we discard the original) */ - size = ALIGN(PERCPU_ENOUGH_ROOM, PAGE_SIZE); - ptr = alloc_bootmem_pages(size * nr_possible_cpus); - - for_each_possible_cpu(i) { - __per_cpu_offset[i] = ptr - __per_cpu_start; - memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); - ptr += size; - } -} -#endif /* CONFIG_HAVE_SETUP_PER_CPU_AREA */ diff --git a/mm/filemap.c b/mm/filemap.c index c3d3506ecabaf0a725b32d3b69ad699c5095adfa..8b4d88f9249ee848c82080a0341e80cbd5c92588 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -260,27 +260,27 @@ int filemap_flush(struct address_space *mapping) EXPORT_SYMBOL(filemap_flush); /** - * wait_on_page_writeback_range - wait for writeback to complete - * @mapping: target address_space - * @start: beginning page index - * @end: ending page index + * filemap_fdatawait_range - wait for writeback to complete + * @mapping: address space structure to wait for + * @start_byte: offset in bytes where the range starts + * @end_byte: offset in bytes where the range ends (inclusive) * - * Wait for writeback to complete against pages indexed by start->end - * inclusive + * Walk the list of under-writeback pages of the given address space + * in the given range and wait for all of them. */ -int wait_on_page_writeback_range(struct address_space *mapping, - pgoff_t start, pgoff_t end) +int filemap_fdatawait_range(struct address_space *mapping, loff_t start_byte, + loff_t end_byte) { + pgoff_t index = start_byte >> PAGE_CACHE_SHIFT; + pgoff_t end = end_byte >> PAGE_CACHE_SHIFT; struct pagevec pvec; int nr_pages; int ret = 0; - pgoff_t index; - if (end < start) + if (end_byte < start_byte) return 0; pagevec_init(&pvec, 0); - index = start; while ((index <= end) && (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, PAGECACHE_TAG_WRITEBACK, @@ -310,25 +310,6 @@ int wait_on_page_writeback_range(struct address_space *mapping, return ret; } - -/** - * filemap_fdatawait_range - wait for all under-writeback pages to complete in a given range - * @mapping: address space structure to wait for - * @start: offset in bytes where the range starts - * @end: offset in bytes where the range ends (inclusive) - * - * Walk the list of under-writeback pages of the given address space - * in the given range and wait for all of them. - * - * This is just a simple wrapper so that callers don't have to convert offsets - * to page indexes themselves - */ -int filemap_fdatawait_range(struct address_space *mapping, loff_t start, - loff_t end) -{ - return wait_on_page_writeback_range(mapping, start >> PAGE_CACHE_SHIFT, - end >> PAGE_CACHE_SHIFT); -} EXPORT_SYMBOL(filemap_fdatawait_range); /** @@ -345,8 +326,7 @@ int filemap_fdatawait(struct address_space *mapping) if (i_size == 0) return 0; - return wait_on_page_writeback_range(mapping, 0, - (i_size - 1) >> PAGE_CACHE_SHIFT); + return filemap_fdatawait_range(mapping, 0, i_size - 1); } EXPORT_SYMBOL(filemap_fdatawait); @@ -393,9 +373,8 @@ int filemap_write_and_wait_range(struct address_space *mapping, WB_SYNC_ALL); /* See comment of filemap_write_and_wait() */ if (err != -EIO) { - int err2 = wait_on_page_writeback_range(mapping, - lstart >> PAGE_CACHE_SHIFT, - lend >> PAGE_CACHE_SHIFT); + int err2 = filemap_fdatawait_range(mapping, + lstart, lend); if (!err) err = err2; } diff --git a/mm/migrate.c b/mm/migrate.c index 7dbcb22316d2b2e482de278a8023c6429fe7bfaf..0bc640fd68fa64c38915d40fe20db545c1784799 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1044,7 +1044,7 @@ static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages, int err; for (i = 0; i < nr_pages; i += chunk_nr) { - if (chunk_nr + i > nr_pages) + if (chunk_nr > nr_pages - i) chunk_nr = nr_pages - i; err = copy_from_user(chunk_pages, &pages[i], diff --git a/mm/mmap.c b/mm/mmap.c index 292ddc3cef9cba4bf58053da23bfcae5a2e9de02..ed70a68e882af069988cfcbe5c54a9a0af88d9fa 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -931,13 +931,9 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, if (!(flags & MAP_FIXED)) addr = round_hint_to_min(addr); - error = arch_mmap_check(addr, len, flags); - if (error) - return error; - /* Careful about overflows.. */ len = PAGE_ALIGN(len); - if (!len || len > TASK_SIZE) + if (!len) return -ENOMEM; /* offset overflow? */ @@ -948,24 +944,6 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, if (mm->map_count > sysctl_max_map_count) return -ENOMEM; - if (flags & MAP_HUGETLB) { - struct user_struct *user = NULL; - if (file) - return -EINVAL; - - /* - * VM_NORESERVE is used because the reservations will be - * taken when vm_ops->mmap() is called - * A dummy user value is used because we are not locking - * memory so no accounting is necessary - */ - len = ALIGN(len, huge_page_size(&default_hstate)); - file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE, - &user, HUGETLB_ANONHUGE_INODE); - if (IS_ERR(file)) - return PTR_ERR(file); - } - /* Obtain the address to map to. we verify (or select) it and ensure * that it represents a valid section of the address space. */ @@ -1455,6 +1433,14 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long (*get_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); + unsigned long error = arch_mmap_check(addr, len, flags); + if (error) + return error; + + /* Careful about overflows.. */ + if (len > TASK_SIZE) + return -ENOMEM; + get_area = current->mm->get_unmapped_area; if (file && file->f_op && file->f_op->get_unmapped_area) get_area = file->f_op->get_unmapped_area; @@ -1999,20 +1985,14 @@ unsigned long do_brk(unsigned long addr, unsigned long len) if (!len) return addr; - if ((addr + len) > TASK_SIZE || (addr + len) < addr) - return -EINVAL; - - if (is_hugepage_only_range(mm, addr, len)) - return -EINVAL; - error = security_file_mmap(NULL, 0, 0, 0, addr, 1); if (error) return error; flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; - error = arch_mmap_check(addr, len, flags); - if (error) + error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED); + if (error & ~PAGE_MASK) return error; /* diff --git a/mm/mremap.c b/mm/mremap.c index 97bff2547719e702150e1cdc4d4a3f6b31a23213..845190898d59f206201b4b5d60f1d4534a755913 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -261,6 +261,137 @@ static unsigned long move_vma(struct vm_area_struct *vma, return new_addr; } +static struct vm_area_struct *vma_to_resize(unsigned long addr, + unsigned long old_len, unsigned long new_len, unsigned long *p) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma = find_vma(mm, addr); + + if (!vma || vma->vm_start > addr) + goto Efault; + + if (is_vm_hugetlb_page(vma)) + goto Einval; + + /* We can't remap across vm area boundaries */ + if (old_len > vma->vm_end - addr) + goto Efault; + + if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) { + if (new_len > old_len) + goto Efault; + } + + if (vma->vm_flags & VM_LOCKED) { + unsigned long locked, lock_limit; + locked = mm->locked_vm << PAGE_SHIFT; + lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur; + locked += new_len - old_len; + if (locked > lock_limit && !capable(CAP_IPC_LOCK)) + goto Eagain; + } + + if (!may_expand_vm(mm, (new_len - old_len) >> PAGE_SHIFT)) + goto Enomem; + + if (vma->vm_flags & VM_ACCOUNT) { + unsigned long charged = (new_len - old_len) >> PAGE_SHIFT; + if (security_vm_enough_memory(charged)) + goto Efault; + *p = charged; + } + + return vma; + +Efault: /* very odd choice for most of the cases, but... */ + return ERR_PTR(-EFAULT); +Einval: + return ERR_PTR(-EINVAL); +Enomem: + return ERR_PTR(-ENOMEM); +Eagain: + return ERR_PTR(-EAGAIN); +} + +static unsigned long mremap_to(unsigned long addr, + unsigned long old_len, unsigned long new_addr, + unsigned long new_len) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long ret = -EINVAL; + unsigned long charged = 0; + unsigned long map_flags; + + if (new_addr & ~PAGE_MASK) + goto out; + + if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len) + goto out; + + /* Check if the location we're moving into overlaps the + * old location at all, and fail if it does. + */ + if ((new_addr <= addr) && (new_addr+new_len) > addr) + goto out; + + if ((addr <= new_addr) && (addr+old_len) > new_addr) + goto out; + + ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); + if (ret) + goto out; + + ret = do_munmap(mm, new_addr, new_len); + if (ret) + goto out; + + if (old_len >= new_len) { + ret = do_munmap(mm, addr+new_len, old_len - new_len); + if (ret && old_len != new_len) + goto out; + old_len = new_len; + } + + vma = vma_to_resize(addr, old_len, new_len, &charged); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto out; + } + + map_flags = MAP_FIXED; + if (vma->vm_flags & VM_MAYSHARE) + map_flags |= MAP_SHARED; + + ret = get_unmapped_area(vma->vm_file, new_addr, new_len, vma->vm_pgoff + + ((addr - vma->vm_start) >> PAGE_SHIFT), + map_flags); + if (ret & ~PAGE_MASK) + goto out1; + + ret = move_vma(vma, addr, old_len, new_len, new_addr); + if (!(ret & ~PAGE_MASK)) + goto out; +out1: + vm_unacct_memory(charged); + +out: + return ret; +} + +static int vma_expandable(struct vm_area_struct *vma, unsigned long delta) +{ + unsigned long end = vma->vm_end + delta; + if (end < vma->vm_end) /* overflow */ + return 0; + if (vma->vm_next && vma->vm_next->vm_start < end) /* intersection */ + return 0; + if (get_unmapped_area(NULL, vma->vm_start, end - vma->vm_start, + 0, MAP_FIXED) & ~PAGE_MASK) + return 0; + return 1; +} + /* * Expand (or shrink) an existing mapping, potentially moving it at the * same time (controlled by the MREMAP_MAYMOVE flag and available VM space) @@ -294,32 +425,10 @@ unsigned long do_mremap(unsigned long addr, if (!new_len) goto out; - /* new_addr is only valid if MREMAP_FIXED is specified */ if (flags & MREMAP_FIXED) { - if (new_addr & ~PAGE_MASK) - goto out; - if (!(flags & MREMAP_MAYMOVE)) - goto out; - - if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len) - goto out; - - /* Check if the location we're moving into overlaps the - * old location at all, and fail if it does. - */ - if ((new_addr <= addr) && (new_addr+new_len) > addr) - goto out; - - if ((addr <= new_addr) && (addr+old_len) > new_addr) - goto out; - - ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); - if (ret) - goto out; - - ret = do_munmap(mm, new_addr, new_len); - if (ret) - goto out; + if (flags & MREMAP_MAYMOVE) + ret = mremap_to(addr, old_len, new_addr, new_len); + goto out; } /* @@ -332,60 +441,23 @@ unsigned long do_mremap(unsigned long addr, if (ret && old_len != new_len) goto out; ret = addr; - if (!(flags & MREMAP_FIXED) || (new_addr == addr)) - goto out; - old_len = new_len; + goto out; } /* - * Ok, we need to grow.. or relocate. + * Ok, we need to grow.. */ - ret = -EFAULT; - vma = find_vma(mm, addr); - if (!vma || vma->vm_start > addr) - goto out; - if (is_vm_hugetlb_page(vma)) { - ret = -EINVAL; - goto out; - } - /* We can't remap across vm area boundaries */ - if (old_len > vma->vm_end - addr) - goto out; - if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) { - if (new_len > old_len) - goto out; - } - if (vma->vm_flags & VM_LOCKED) { - unsigned long locked, lock_limit; - locked = mm->locked_vm << PAGE_SHIFT; - lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur; - locked += new_len - old_len; - ret = -EAGAIN; - if (locked > lock_limit && !capable(CAP_IPC_LOCK)) - goto out; - } - if (!may_expand_vm(mm, (new_len - old_len) >> PAGE_SHIFT)) { - ret = -ENOMEM; + vma = vma_to_resize(addr, old_len, new_len, &charged); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); goto out; } - if (vma->vm_flags & VM_ACCOUNT) { - charged = (new_len - old_len) >> PAGE_SHIFT; - if (security_vm_enough_memory(charged)) - goto out_nc; - } - /* old_len exactly to the end of the area.. - * And we're not relocating the area. */ - if (old_len == vma->vm_end - addr && - !((flags & MREMAP_FIXED) && (addr != new_addr)) && - (old_len != new_len || !(flags & MREMAP_MAYMOVE))) { - unsigned long max_addr = TASK_SIZE; - if (vma->vm_next) - max_addr = vma->vm_next->vm_start; + if (old_len == vma->vm_end - addr) { /* can we just expand the current mapping? */ - if (max_addr - addr >= new_len) { + if (vma_expandable(vma, new_len - old_len)) { int pages = (new_len - old_len) >> PAGE_SHIFT; vma_adjust(vma, vma->vm_start, @@ -409,28 +481,27 @@ unsigned long do_mremap(unsigned long addr, */ ret = -ENOMEM; if (flags & MREMAP_MAYMOVE) { - if (!(flags & MREMAP_FIXED)) { - unsigned long map_flags = 0; - if (vma->vm_flags & VM_MAYSHARE) - map_flags |= MAP_SHARED; - - new_addr = get_unmapped_area(vma->vm_file, 0, new_len, - vma->vm_pgoff, map_flags); - if (new_addr & ~PAGE_MASK) { - ret = new_addr; - goto out; - } - - ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); - if (ret) - goto out; + unsigned long map_flags = 0; + if (vma->vm_flags & VM_MAYSHARE) + map_flags |= MAP_SHARED; + + new_addr = get_unmapped_area(vma->vm_file, 0, new_len, + vma->vm_pgoff + + ((addr - vma->vm_start) >> PAGE_SHIFT), + map_flags); + if (new_addr & ~PAGE_MASK) { + ret = new_addr; + goto out; } + + ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); + if (ret) + goto out; ret = move_vma(vma, addr, old_len, new_len, new_addr); } out: if (ret & ~PAGE_MASK) vm_unacct_memory(charged); -out_nc: return ret; } diff --git a/mm/percpu.c b/mm/percpu.c index 5adfc268b408936a3d18ae9014ce70e49590738d..442010cc91c6c82eb8489e64d21500baa52b5911 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -46,8 +46,6 @@ * * To use this allocator, arch code should do the followings. * - * - drop CONFIG_HAVE_LEGACY_PER_CPU_AREA - * * - define __addr_to_pcpu_ptr() and __pcpu_ptr_to_addr() to translate * regular address to percpu pointer and back if they need to be * different from the default @@ -74,6 +72,7 @@ #include #include #include +#include #define PCPU_SLOT_BASE_SHIFT 5 /* 1-31 shares the same slot */ #define PCPU_DFL_MAP_ALLOC 16 /* start a map with 16 ents */ @@ -1302,6 +1301,27 @@ void free_percpu(void *ptr) } EXPORT_SYMBOL_GPL(free_percpu); +/** + * per_cpu_ptr_to_phys - convert translated percpu address to physical address + * @addr: the address to be converted to physical address + * + * Given @addr which is dereferenceable address obtained via one of + * percpu access macros, this function translates it into its physical + * address. The caller is responsible for ensuring @addr stays valid + * until this function finishes. + * + * RETURNS: + * The physical address for @addr. + */ +phys_addr_t per_cpu_ptr_to_phys(void *addr) +{ + if ((unsigned long)addr < VMALLOC_START || + (unsigned long)addr >= VMALLOC_END) + return __pa(addr); + else + return page_to_phys(vmalloc_to_page(addr)); +} + static inline size_t pcpu_calc_fc_sizes(size_t static_size, size_t reserved_size, ssize_t *dyn_sizep) diff --git a/mm/slab.c b/mm/slab.c index 7dfa481c96bade62ae4ba34299dcd4fb8d79cdb3..3f4822938f4605f4e6e1cf55f996f812332cd4a6 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -490,7 +490,7 @@ static void **dbg_userword(struct kmem_cache *cachep, void *objp) #endif -#ifdef CONFIG_KMEMTRACE +#ifdef CONFIG_TRACING size_t slab_buffer_size(struct kmem_cache *cachep) { return cachep->buffer_size; @@ -604,6 +604,26 @@ static struct kmem_cache cache_cache = { #define BAD_ALIEN_MAGIC 0x01020304ul +/* + * chicken and egg problem: delay the per-cpu array allocation + * until the general caches are up. + */ +static enum { + NONE, + PARTIAL_AC, + PARTIAL_L3, + EARLY, + FULL +} g_cpucache_up; + +/* + * used by boot code to determine if it can use slab based allocator + */ +int slab_is_available(void) +{ + return g_cpucache_up >= EARLY; +} + #ifdef CONFIG_LOCKDEP /* @@ -620,40 +640,52 @@ static struct kmem_cache cache_cache = { static struct lock_class_key on_slab_l3_key; static struct lock_class_key on_slab_alc_key; -static inline void init_lock_keys(void) - +static void init_node_lock_keys(int q) { - int q; struct cache_sizes *s = malloc_sizes; - while (s->cs_size != ULONG_MAX) { - for_each_node(q) { - struct array_cache **alc; - int r; - struct kmem_list3 *l3 = s->cs_cachep->nodelists[q]; - if (!l3 || OFF_SLAB(s->cs_cachep)) - continue; - lockdep_set_class(&l3->list_lock, &on_slab_l3_key); - alc = l3->alien; - /* - * FIXME: This check for BAD_ALIEN_MAGIC - * should go away when common slab code is taught to - * work even without alien caches. - * Currently, non NUMA code returns BAD_ALIEN_MAGIC - * for alloc_alien_cache, - */ - if (!alc || (unsigned long)alc == BAD_ALIEN_MAGIC) - continue; - for_each_node(r) { - if (alc[r]) - lockdep_set_class(&alc[r]->lock, - &on_slab_alc_key); - } + if (g_cpucache_up != FULL) + return; + + for (s = malloc_sizes; s->cs_size != ULONG_MAX; s++) { + struct array_cache **alc; + struct kmem_list3 *l3; + int r; + + l3 = s->cs_cachep->nodelists[q]; + if (!l3 || OFF_SLAB(s->cs_cachep)) + return; + lockdep_set_class(&l3->list_lock, &on_slab_l3_key); + alc = l3->alien; + /* + * FIXME: This check for BAD_ALIEN_MAGIC + * should go away when common slab code is taught to + * work even without alien caches. + * Currently, non NUMA code returns BAD_ALIEN_MAGIC + * for alloc_alien_cache, + */ + if (!alc || (unsigned long)alc == BAD_ALIEN_MAGIC) + return; + for_each_node(r) { + if (alc[r]) + lockdep_set_class(&alc[r]->lock, + &on_slab_alc_key); } - s++; } } + +static inline void init_lock_keys(void) +{ + int node; + + for_each_node(node) + init_node_lock_keys(node); +} #else +static void init_node_lock_keys(int q) +{ +} + static inline void init_lock_keys(void) { } @@ -665,27 +697,7 @@ static inline void init_lock_keys(void) static DEFINE_MUTEX(cache_chain_mutex); static struct list_head cache_chain; -/* - * chicken and egg problem: delay the per-cpu array allocation - * until the general caches are up. - */ -static enum { - NONE, - PARTIAL_AC, - PARTIAL_L3, - EARLY, - FULL -} g_cpucache_up; - -/* - * used by boot code to determine if it can use slab based allocator - */ -int slab_is_available(void) -{ - return g_cpucache_up >= EARLY; -} - -static DEFINE_PER_CPU(struct delayed_work, reap_work); +static DEFINE_PER_CPU(struct delayed_work, slab_reap_work); static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep) { @@ -826,7 +838,7 @@ __setup("noaliencache", noaliencache_setup); * objects freed on different nodes from which they were allocated) and the * flushing of remote pcps by calling drain_node_pages. */ -static DEFINE_PER_CPU(unsigned long, reap_node); +static DEFINE_PER_CPU(unsigned long, slab_reap_node); static void init_reap_node(int cpu) { @@ -836,17 +848,17 @@ static void init_reap_node(int cpu) if (node == MAX_NUMNODES) node = first_node(node_online_map); - per_cpu(reap_node, cpu) = node; + per_cpu(slab_reap_node, cpu) = node; } static void next_reap_node(void) { - int node = __get_cpu_var(reap_node); + int node = __get_cpu_var(slab_reap_node); node = next_node(node, node_online_map); if (unlikely(node >= MAX_NUMNODES)) node = first_node(node_online_map); - __get_cpu_var(reap_node) = node; + __get_cpu_var(slab_reap_node) = node; } #else @@ -863,7 +875,7 @@ static void next_reap_node(void) */ static void __cpuinit start_cpu_timer(int cpu) { - struct delayed_work *reap_work = &per_cpu(reap_work, cpu); + struct delayed_work *reap_work = &per_cpu(slab_reap_work, cpu); /* * When this gets called from do_initcalls via cpucache_init(), @@ -1027,7 +1039,7 @@ static void __drain_alien_cache(struct kmem_cache *cachep, */ static void reap_alien(struct kmem_cache *cachep, struct kmem_list3 *l3) { - int node = __get_cpu_var(reap_node); + int node = __get_cpu_var(slab_reap_node); if (l3->alien) { struct array_cache *ac = l3->alien[node]; @@ -1254,6 +1266,8 @@ static int __cpuinit cpuup_prepare(long cpu) kfree(shared); free_alien_cache(alien); } + init_node_lock_keys(node); + return 0; bad: cpuup_canceled(cpu); @@ -1286,9 +1300,9 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb, * anything expensive but will only modify reap_work * and reschedule the timer. */ - cancel_rearming_delayed_work(&per_cpu(reap_work, cpu)); + cancel_rearming_delayed_work(&per_cpu(slab_reap_work, cpu)); /* Now the cache_reaper is guaranteed to be not running. */ - per_cpu(reap_work, cpu).work.func = NULL; + per_cpu(slab_reap_work, cpu).work.func = NULL; break; case CPU_DOWN_FAILED: case CPU_DOWN_FAILED_FROZEN: @@ -3103,13 +3117,19 @@ static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags) } else { STATS_INC_ALLOCMISS(cachep); objp = cache_alloc_refill(cachep, flags); + /* + * the 'ac' may be updated by cache_alloc_refill(), + * and kmemleak_erase() requires its correct value. + */ + ac = cpu_cache_get(cachep); } /* * To avoid a false negative, if an object that is in one of the * per-CPU caches is leaked, we need to make sure kmemleak doesn't * treat the array pointers as a reference to the object. */ - kmemleak_erase(&ac->entry[ac->avail]); + if (objp) + kmemleak_erase(&ac->entry[ac->avail]); return objp; } @@ -3306,7 +3326,7 @@ __cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid, cache_alloc_debugcheck_before(cachep, flags); local_irq_save(save_flags); - if (unlikely(nodeid == -1)) + if (nodeid == -1) nodeid = numa_node_id(); if (unlikely(!cachep->nodelists[nodeid])) { @@ -3558,7 +3578,7 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) } EXPORT_SYMBOL(kmem_cache_alloc); -#ifdef CONFIG_KMEMTRACE +#ifdef CONFIG_TRACING void *kmem_cache_alloc_notrace(struct kmem_cache *cachep, gfp_t flags) { return __cache_alloc(cachep, flags, __builtin_return_address(0)); @@ -3621,7 +3641,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid) } EXPORT_SYMBOL(kmem_cache_alloc_node); -#ifdef CONFIG_KMEMTRACE +#ifdef CONFIG_TRACING void *kmem_cache_alloc_node_notrace(struct kmem_cache *cachep, gfp_t flags, int nodeid) @@ -3649,7 +3669,7 @@ __do_kmalloc_node(size_t size, gfp_t flags, int node, void *caller) return ret; } -#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_KMEMTRACE) +#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_TRACING) void *__kmalloc_node(size_t size, gfp_t flags, int node) { return __do_kmalloc_node(size, flags, node, @@ -3669,7 +3689,7 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node) return __do_kmalloc_node(size, flags, node, NULL); } EXPORT_SYMBOL(__kmalloc_node); -#endif /* CONFIG_DEBUG_SLAB */ +#endif /* CONFIG_DEBUG_SLAB || CONFIG_TRACING */ #endif /* CONFIG_NUMA */ /** @@ -3701,7 +3721,7 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, } -#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_KMEMTRACE) +#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_TRACING) void *__kmalloc(size_t size, gfp_t flags) { return __do_kmalloc(size, flags, __builtin_return_address(0)); diff --git a/mm/slub.c b/mm/slub.c index 4996fc7195528ba931dda8c042da44b2501b083e..8d71aaf888d770b27ba26df5d4d9592832a87b2d 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1735,7 +1735,7 @@ static __always_inline void *slab_alloc(struct kmem_cache *s, } local_irq_restore(flags); - if (unlikely((gfpflags & __GFP_ZERO) && object)) + if (unlikely(gfpflags & __GFP_ZERO) && object) memset(object, 0, objsize); kmemcheck_slab_alloc(s, gfpflags, object, c->objsize); @@ -1754,7 +1754,7 @@ void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags) } EXPORT_SYMBOL(kmem_cache_alloc); -#ifdef CONFIG_KMEMTRACE +#ifdef CONFIG_TRACING void *kmem_cache_alloc_notrace(struct kmem_cache *s, gfp_t gfpflags) { return slab_alloc(s, gfpflags, -1, _RET_IP_); @@ -1775,7 +1775,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node) EXPORT_SYMBOL(kmem_cache_alloc_node); #endif -#ifdef CONFIG_KMEMTRACE +#ifdef CONFIG_TRACING void *kmem_cache_alloc_node_notrace(struct kmem_cache *s, gfp_t gfpflags, int node) @@ -4371,12 +4371,28 @@ static int show_stat(struct kmem_cache *s, char *buf, enum stat_item si) return len + sprintf(buf + len, "\n"); } +static void clear_stat(struct kmem_cache *s, enum stat_item si) +{ + int cpu; + + for_each_online_cpu(cpu) + get_cpu_slab(s, cpu)->stat[si] = 0; +} + #define STAT_ATTR(si, text) \ static ssize_t text##_show(struct kmem_cache *s, char *buf) \ { \ return show_stat(s, buf, si); \ } \ -SLAB_ATTR_RO(text); \ +static ssize_t text##_store(struct kmem_cache *s, \ + const char *buf, size_t length) \ +{ \ + if (buf[0] != '0') \ + return -EINVAL; \ + clear_stat(s, si); \ + return length; \ +} \ +SLAB_ATTR(text); \ STAT_ATTR(ALLOC_FASTPATH, alloc_fastpath); STAT_ATTR(ALLOC_SLOWPATH, alloc_slowpath); diff --git a/mm/util.c b/mm/util.c index 7c35ad95f92756d1473bbc2ae658f5bb27de2ca9..b377ce43080312411a8910ea21a5f2867a7c7007 100644 --- a/mm/util.c +++ b/mm/util.c @@ -4,6 +4,10 @@ #include #include #include +#include +#include +#include +#include #include #define CREATE_TRACE_POINTS @@ -268,6 +272,46 @@ int __attribute__((weak)) get_user_pages_fast(unsigned long start, } EXPORT_SYMBOL_GPL(get_user_pages_fast); +SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, + unsigned long, prot, unsigned long, flags, + unsigned long, fd, unsigned long, pgoff) +{ + struct file * file = NULL; + unsigned long retval = -EBADF; + + if (!(flags & MAP_ANONYMOUS)) { + if (unlikely(flags & MAP_HUGETLB)) + return -EINVAL; + file = fget(fd); + if (!file) + goto out; + } else if (flags & MAP_HUGETLB) { + struct user_struct *user = NULL; + /* + * VM_NORESERVE is used because the reservations will be + * taken when vm_ops->mmap() is called + * A dummy user value is used because we are not locking + * memory so no accounting is necessary + */ + len = ALIGN(len, huge_page_size(&default_hstate)); + file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE, + &user, HUGETLB_ANONHUGE_INODE); + if (IS_ERR(file)) + return PTR_ERR(file); + } + + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + + down_write(¤t->mm->mmap_sem); + retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + up_write(¤t->mm->mmap_sem); + + if (file) + fput(file); +out: + return retval; +} + /* Tracepoints definitions. */ EXPORT_TRACEPOINT_SYMBOL(kmalloc); EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc); diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 0f551a4a44cddc7a042d47bbcd85c7126569ee69..9b08d790df6fe441a2b8c2002ed9f0e1a4677641 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -761,7 +761,7 @@ static struct vmap_block *new_vmap_block(gfp_t gfp_mask) spin_lock(&vbq->lock); list_add(&vb->free_list, &vbq->free); spin_unlock(&vbq->lock); - put_cpu_var(vmap_cpu_blocks); + put_cpu_var(vmap_block_queue); return vb; } @@ -826,7 +826,7 @@ again: } spin_unlock(&vb->lock); } - put_cpu_var(vmap_cpu_blocks); + put_cpu_var(vmap_block_queue); rcu_read_unlock(); if (!addr) { diff --git a/mm/vmstat.c b/mm/vmstat.c index c81321f9feec1cb28eee1b7e07237017336b89d0..dad2327e45804e16a8ff07564a80eb0cac79f482 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -883,11 +883,10 @@ static void vmstat_update(struct work_struct *w) static void __cpuinit start_cpu_timer(int cpu) { - struct delayed_work *vmstat_work = &per_cpu(vmstat_work, cpu); + struct delayed_work *work = &per_cpu(vmstat_work, cpu); - INIT_DELAYED_WORK_DEFERRABLE(vmstat_work, vmstat_update); - schedule_delayed_work_on(cpu, vmstat_work, - __round_jiffies_relative(HZ, cpu)); + INIT_DELAYED_WORK_DEFERRABLE(work, vmstat_update); + schedule_delayed_work_on(cpu, work, __round_jiffies_relative(HZ, cpu)); } /* diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 26a646d4eb32dc3df591bc404420587e9ab0f32a..c9230c398697a75986b71b28263261e37fed2cee 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -554,6 +554,12 @@ static const struct net_device_ops br2684_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; +static const struct net_device_ops br2684_netdev_ops_routed = { + .ndo_start_xmit = br2684_start_xmit, + .ndo_set_mac_address = br2684_mac_addr, + .ndo_change_mtu = eth_change_mtu +}; + static void br2684_setup(struct net_device *netdev) { struct br2684_dev *brdev = BRPRIV(netdev); @@ -569,11 +575,10 @@ static void br2684_setup(struct net_device *netdev) static void br2684_setup_routed(struct net_device *netdev) { struct br2684_dev *brdev = BRPRIV(netdev); - brdev->net_dev = netdev; + brdev->net_dev = netdev; netdev->hard_header_len = 0; - - netdev->netdev_ops = &br2684_netdev_ops; + netdev->netdev_ops = &br2684_netdev_ops_routed; netdev->addr_len = 0; netdev->mtu = 1500; netdev->type = ARPHRD_PPP; diff --git a/net/atm/lec.c b/net/atm/lec.c index b2d644560323c945da9019cdba493212d9dd20e9..42749b7b917cc7d97e3f97bd147e398543b4c3b7 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -62,7 +62,6 @@ static int lec_open(struct net_device *dev); static netdev_tx_t lec_start_xmit(struct sk_buff *skb, struct net_device *dev); static int lec_close(struct net_device *dev); -static void lec_init(struct net_device *dev); static struct lec_arp_table *lec_arp_find(struct lec_priv *priv, const unsigned char *mac_addr); static int lec_arp_remove(struct lec_priv *priv, @@ -670,13 +669,6 @@ static const struct net_device_ops lec_netdev_ops = { .ndo_set_multicast_list = lec_set_multicast_list, }; - -static void lec_init(struct net_device *dev) -{ - dev->netdev_ops = &lec_netdev_ops; - printk("%s: Initialized!\n", dev->name); -} - static const unsigned char lec_ctrl_magic[] = { 0xff, 0x00, @@ -893,6 +885,7 @@ static int lecd_attach(struct atm_vcc *vcc, int arg) dev_lec[i] = alloc_etherdev(size); if (!dev_lec[i]) return -ENOMEM; + dev_lec[i]->netdev_ops = &lec_netdev_ops; snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i); if (register_netdev(dev_lec[i])) { free_netdev(dev_lec[i]); @@ -901,7 +894,6 @@ static int lecd_attach(struct atm_vcc *vcc, int arg) priv = netdev_priv(dev_lec[i]); priv->is_trdev = is_trdev; - lec_init(dev_lec[i]); } else { priv = netdev_priv(dev_lec[i]); if (priv->lecd) diff --git a/net/compat.c b/net/compat.c index e1a56ade803b09b48e047e24192a3649ed0348d5..a1fb1b079a82b00bd269fa208984de34010bf7f4 100644 --- a/net/compat.c +++ b/net/compat.c @@ -754,26 +754,21 @@ asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, size_t len, asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, unsigned vlen, unsigned int flags, - struct timespec __user *timeout) + struct compat_timespec __user *timeout) { int datagrams; struct timespec ktspec; - struct compat_timespec __user *utspec; if (timeout == NULL) return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT, NULL); - utspec = (struct compat_timespec __user *)timeout; - if (get_user(ktspec.tv_sec, &utspec->tv_sec) || - get_user(ktspec.tv_nsec, &utspec->tv_nsec)) + if (get_compat_timespec(&ktspec, timeout)) return -EFAULT; datagrams = __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT, &ktspec); - if (datagrams > 0 && - (put_user(ktspec.tv_sec, &utspec->tv_sec) || - put_user(ktspec.tv_nsec, &utspec->tv_nsec))) + if (datagrams > 0 && put_compat_timespec(&ktspec, timeout)) datagrams = -EFAULT; return datagrams; diff --git a/net/core/dev.c b/net/core/dev.c index c36a17aafcf3167e8c1f4ed4307f5e4386b7c854..6fe7d739e59bdf1fc4ebe10f427b7c3d0d8308ec 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4771,21 +4771,23 @@ static void net_set_todo(struct net_device *dev) static void rollback_registered_many(struct list_head *head) { - struct net_device *dev; + struct net_device *dev, *tmp; BUG_ON(dev_boot_phase); ASSERT_RTNL(); - list_for_each_entry(dev, head, unreg_list) { + list_for_each_entry_safe(dev, tmp, head, unreg_list) { /* Some devices call without registering - * for initialization unwind. + * for initialization unwind. Remove those + * devices and proceed with the remaining. */ if (dev->reg_state == NETREG_UNINITIALIZED) { pr_debug("unregister_netdevice: device %s/%p never " "was registered\n", dev->name, dev); WARN_ON(1); - return; + list_del(&dev->unreg_list); + continue; } BUG_ON(dev->reg_state != NETREG_REGISTERED); diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index efbcfdc12796b89e4d593b296bc1255f54cd9ee0..dad7bc4878e0eb08631e821f94e89a6066b372cc 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -408,7 +408,7 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb, dccp_sync_mss(newsk, dst_mtu(dst)); - __inet_hash_nolisten(newsk); + __inet_hash_nolisten(newsk, NULL); __inet_inherit_port(sk, newsk); return newsk; diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 6574215a1f5190fa584baedd26be974af45475ae..baf05cf43c2879068f86f63abeedfcffb2d30218 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -46,7 +46,7 @@ static void dccp_v6_hash(struct sock *sk) return; } local_bh_disable(); - __inet6_hash(sk); + __inet6_hash(sk, NULL); local_bh_enable(); } } @@ -644,7 +644,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6; newinet->inet_rcv_saddr = LOOPBACK4_IPV6; - __inet6_hash(newsk); + __inet6_hash(newsk, NULL); __inet_inherit_port(sk, newsk); return newsk; diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 21e5e32d8c600c192f53d8acec5f7bfeea5cfed5..2b79377b468dd0b06d69b0c6b5842f52ba52db07 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -351,12 +351,13 @@ static inline u32 inet_sk_port_offset(const struct sock *sk) inet->inet_dport); } -void __inet_hash_nolisten(struct sock *sk) +int __inet_hash_nolisten(struct sock *sk, struct inet_timewait_sock *tw) { struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; struct hlist_nulls_head *list; spinlock_t *lock; struct inet_ehash_bucket *head; + int twrefcnt = 0; WARN_ON(!sk_unhashed(sk)); @@ -367,8 +368,13 @@ void __inet_hash_nolisten(struct sock *sk) spin_lock(lock); __sk_nulls_add_node_rcu(sk, list); + if (tw) { + WARN_ON(sk->sk_hash != tw->tw_hash); + twrefcnt = inet_twsk_unhash(tw); + } spin_unlock(lock); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); + return twrefcnt; } EXPORT_SYMBOL_GPL(__inet_hash_nolisten); @@ -378,7 +384,7 @@ static void __inet_hash(struct sock *sk) struct inet_listen_hashbucket *ilb; if (sk->sk_state != TCP_LISTEN) { - __inet_hash_nolisten(sk); + __inet_hash_nolisten(sk, NULL); return; } @@ -427,7 +433,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, struct sock *sk, u32 port_offset, int (*check_established)(struct inet_timewait_death_row *, struct sock *, __u16, struct inet_timewait_sock **), - void (*hash)(struct sock *sk)) + int (*hash)(struct sock *sk, struct inet_timewait_sock *twp)) { struct inet_hashinfo *hinfo = death_row->hashinfo; const unsigned short snum = inet_sk(sk)->inet_num; @@ -435,6 +441,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, struct inet_bind_bucket *tb; int ret; struct net *net = sock_net(sk); + int twrefcnt = 1; if (!snum) { int i, remaining, low, high, port; @@ -493,13 +500,18 @@ ok: inet_bind_hash(sk, tb, port); if (sk_unhashed(sk)) { inet_sk(sk)->inet_sport = htons(port); - hash(sk); + twrefcnt += hash(sk, tw); } + if (tw) + twrefcnt += inet_twsk_bind_unhash(tw, hinfo); spin_unlock(&head->lock); if (tw) { inet_twsk_deschedule(tw, death_row); - inet_twsk_put(tw); + while (twrefcnt) { + twrefcnt--; + inet_twsk_put(tw); + } } ret = 0; @@ -510,7 +522,7 @@ ok: tb = inet_csk(sk)->icsk_bind_hash; spin_lock_bh(&head->lock); if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) { - hash(sk); + hash(sk, NULL); spin_unlock_bh(&head->lock); return 0; } else { diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index 0fdf45e4c90c8c8475cfd28feb9830d65ebfc204..cc94cc2d8b2d8825d909266b501afb1c6ea03cab 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -15,9 +15,13 @@ #include -/* - * unhash a timewait socket from established hash - * lock must be hold by caller +/** + * inet_twsk_unhash - unhash a timewait socket from established hash + * @tw: timewait socket + * + * unhash a timewait socket from established hash, if hashed. + * ehash lock must be held by caller. + * Returns 1 if caller should call inet_twsk_put() after lock release. */ int inet_twsk_unhash(struct inet_timewait_sock *tw) { @@ -26,6 +30,37 @@ int inet_twsk_unhash(struct inet_timewait_sock *tw) hlist_nulls_del_rcu(&tw->tw_node); sk_nulls_node_init(&tw->tw_node); + /* + * We cannot call inet_twsk_put() ourself under lock, + * caller must call it for us. + */ + return 1; +} + +/** + * inet_twsk_bind_unhash - unhash a timewait socket from bind hash + * @tw: timewait socket + * @hashinfo: hashinfo pointer + * + * unhash a timewait socket from bind hash, if hashed. + * bind hash lock must be held by caller. + * Returns 1 if caller should call inet_twsk_put() after lock release. + */ +int inet_twsk_bind_unhash(struct inet_timewait_sock *tw, + struct inet_hashinfo *hashinfo) +{ + struct inet_bind_bucket *tb = tw->tw_tb; + + if (!tb) + return 0; + + __hlist_del(&tw->tw_bind_node); + tw->tw_tb = NULL; + inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb); + /* + * We cannot call inet_twsk_put() ourself under lock, + * caller must call it for us. + */ return 1; } @@ -34,7 +69,6 @@ static void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashinfo) { struct inet_bind_hashbucket *bhead; - struct inet_bind_bucket *tb; int refcnt; /* Unlink from established hashes. */ spinlock_t *lock = inet_ehash_lockp(hashinfo, tw->tw_hash); @@ -46,15 +80,11 @@ static void __inet_twsk_kill(struct inet_timewait_sock *tw, /* Disassociate with bind bucket. */ bhead = &hashinfo->bhash[inet_bhashfn(twsk_net(tw), tw->tw_num, hashinfo->bhash_size)]; + spin_lock(&bhead->lock); - tb = tw->tw_tb; - if (tb) { - __hlist_del(&tw->tw_bind_node); - tw->tw_tb = NULL; - inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb); - refcnt++; - } + refcnt += inet_twsk_bind_unhash(tw, hashinfo); spin_unlock(&bhead->lock); + #ifdef SOCK_REFCNT_DEBUG if (atomic_read(&tw->tw_refcnt) != 1) { printk(KERN_DEBUG "%s timewait_sock %p refcnt=%d\n", @@ -126,7 +156,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk, /* * Notes : - * - We initially set tw_refcnt to 0 in inet_twsk_alloc() + * - We initially set tw_refcnt to 0 in inet_twsk_alloc() * - We add one reference for the bhash link * - We add one reference for the ehash link * - We want this refcnt update done before allowing other @@ -136,7 +166,6 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk, spin_unlock(lock); } - EXPORT_SYMBOL_GPL(__inet_twsk_hashdance); struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int state) @@ -177,7 +206,6 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat return tw; } - EXPORT_SYMBOL_GPL(inet_twsk_alloc); /* Returns non-zero if quota exceeded. */ @@ -256,7 +284,6 @@ void inet_twdr_hangman(unsigned long data) out: spin_unlock(&twdr->death_lock); } - EXPORT_SYMBOL_GPL(inet_twdr_hangman); void inet_twdr_twkill_work(struct work_struct *work) @@ -287,7 +314,6 @@ void inet_twdr_twkill_work(struct work_struct *work) spin_unlock_bh(&twdr->death_lock); } } - EXPORT_SYMBOL_GPL(inet_twdr_twkill_work); /* These are always called from BH context. See callers in @@ -307,7 +333,6 @@ void inet_twsk_deschedule(struct inet_timewait_sock *tw, spin_unlock(&twdr->death_lock); __inet_twsk_kill(tw, twdr->hashinfo); } - EXPORT_SYMBOL(inet_twsk_deschedule); void inet_twsk_schedule(struct inet_timewait_sock *tw, @@ -388,7 +413,6 @@ void inet_twsk_schedule(struct inet_timewait_sock *tw, mod_timer(&twdr->tw_timer, jiffies + twdr->period); spin_unlock(&twdr->death_lock); } - EXPORT_SYMBOL_GPL(inet_twsk_schedule); void inet_twdr_twcal_tick(unsigned long data) @@ -449,7 +473,6 @@ out: #endif spin_unlock(&twdr->death_lock); } - EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick); void inet_twsk_purge(struct inet_hashinfo *hashinfo, diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index c8666b70cde0cf4c4109a8459a96ace8692419e3..b0a26bb25e2e3b341b2aad2e5f911fd99f6833fe 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2540,11 +2540,6 @@ static int do_tcp_getsockopt(struct sock *sk, int level, ctd.tcpct_cookie_desired = cvp->cookie_desired; ctd.tcpct_s_data_desired = cvp->s_data_desired; - /* Cookie(s) saved, return as nonce */ - if (sizeof(ctd.tcpct_value) < cvp->cookie_pair_size) { - /* impossible? */ - return -EINVAL; - } memcpy(&ctd.tcpct_value[0], &cvp->cookie_pair[0], cvp->cookie_pair_size); ctd.tcpct_used = cvp->cookie_pair_size; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 57ae96a042206274a467e6f8ac5fb5d4899b06bd..12cab7d74dba2a5ecacf226256da5e7fa60910a2 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2717,6 +2717,35 @@ static void tcp_try_undo_dsack(struct sock *sk) } } +/* We can clear retrans_stamp when there are no retransmissions in the + * window. It would seem that it is trivially available for us in + * tp->retrans_out, however, that kind of assumptions doesn't consider + * what will happen if errors occur when sending retransmission for the + * second time. ...It could the that such segment has only + * TCPCB_EVER_RETRANS set at the present time. It seems that checking + * the head skb is enough except for some reneging corner cases that + * are not worth the effort. + * + * Main reason for all this complexity is the fact that connection dying + * time now depends on the validity of the retrans_stamp, in particular, + * that successive retransmissions of a segment must not advance + * retrans_stamp under any conditions. + */ +static int tcp_any_retrans_done(struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct sk_buff *skb; + + if (tp->retrans_out) + return 1; + + skb = tcp_write_queue_head(sk); + if (unlikely(skb && TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS)) + return 1; + + return 0; +} + /* Undo during fast recovery after partial ACK. */ static int tcp_try_undo_partial(struct sock *sk, int acked) @@ -2729,7 +2758,7 @@ static int tcp_try_undo_partial(struct sock *sk, int acked) /* Plain luck! Hole if filled with delayed * packet, rather than with a retransmit. */ - if (tp->retrans_out == 0) + if (!tcp_any_retrans_done(sk)) tp->retrans_stamp = 0; tcp_update_reordering(sk, tcp_fackets_out(tp) + acked, 1); @@ -2788,7 +2817,7 @@ static void tcp_try_keep_open(struct sock *sk) struct tcp_sock *tp = tcp_sk(sk); int state = TCP_CA_Open; - if (tcp_left_out(tp) || tp->retrans_out || tp->undo_marker) + if (tcp_left_out(tp) || tcp_any_retrans_done(sk) || tp->undo_marker) state = TCP_CA_Disorder; if (inet_csk(sk)->icsk_ca_state != state) { @@ -2803,7 +2832,7 @@ static void tcp_try_to_open(struct sock *sk, int flag) tcp_verify_left_out(tp); - if (!tp->frto_counter && tp->retrans_out == 0) + if (!tp->frto_counter && !tcp_any_retrans_done(sk)) tp->retrans_stamp = 0; if (flag & FLAG_ECE) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 29002ab26e0d3debe3b3945a770756a25c0c7e2b..15e96030ce47d16fdd1095807d7b8283a02d1215 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1464,7 +1464,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, } #endif - __inet_hash_nolisten(newsk); + __inet_hash_nolisten(newsk, NULL); __inet_inherit_port(sk, newsk); return newsk; diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 8353a538cd4c76f7ac7a4d95b6c9e505cc0a68da..8816a20c25970ad4fe9ae172a4890af74ee928ce 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -132,6 +132,35 @@ static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk) } } +/* This function calculates a "timeout" which is equivalent to the timeout of a + * TCP connection after "boundary" unsucessful, exponentially backed-off + * retransmissions with an initial RTO of TCP_RTO_MIN. + */ +static bool retransmits_timed_out(struct sock *sk, + unsigned int boundary) +{ + unsigned int timeout, linear_backoff_thresh; + unsigned int start_ts; + + if (!inet_csk(sk)->icsk_retransmits) + return false; + + if (unlikely(!tcp_sk(sk)->retrans_stamp)) + start_ts = TCP_SKB_CB(tcp_write_queue_head(sk))->when; + else + start_ts = tcp_sk(sk)->retrans_stamp; + + linear_backoff_thresh = ilog2(TCP_RTO_MAX/TCP_RTO_MIN); + + if (boundary <= linear_backoff_thresh) + timeout = ((2 << boundary) - 1) * TCP_RTO_MIN; + else + timeout = ((2 << linear_backoff_thresh) - 1) * TCP_RTO_MIN + + (boundary - linear_backoff_thresh) * TCP_RTO_MAX; + + return (tcp_time_stamp - start_ts) >= timeout; +} + /* A write timeout has occurred. Process the after effects. */ static int tcp_write_timeout(struct sock *sk) { diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index c813e294ec0c94d2aac13149f528683a85987d91..633a6c266136ec0a34602fb64bc5b9f68d8658a5 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -22,9 +22,10 @@ #include #include -void __inet6_hash(struct sock *sk) +int __inet6_hash(struct sock *sk, struct inet_timewait_sock *tw) { struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; + int twrefcnt = 0; WARN_ON(!sk_unhashed(sk)); @@ -45,10 +46,15 @@ void __inet6_hash(struct sock *sk) lock = inet_ehash_lockp(hashinfo, hash); spin_lock(lock); __sk_nulls_add_node_rcu(sk, list); + if (tw) { + WARN_ON(sk->sk_hash != tw->tw_hash); + twrefcnt = inet_twsk_unhash(tw); + } spin_unlock(lock); } sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); + return twrefcnt; } EXPORT_SYMBOL(__inet6_hash); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index aadd7cef73b39f8b608c1dca279ec0522b864f60..ee9cf62458d4bb1f97c5f04f1639badb9ceda262 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -96,7 +96,7 @@ static void tcp_v6_hash(struct sock *sk) return; } local_bh_disable(); - __inet6_hash(sk); + __inet6_hash(sk, NULL); local_bh_enable(); } } @@ -1496,7 +1496,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, } #endif - __inet6_hash(newsk); + __inet6_hash(newsk, NULL); __inet_inherit_port(sk, newsk); return newsk; diff --git a/net/key/af_key.c b/net/key/af_key.c index 84209fbbeb1756317e05dbf4ba03cdab6379e2a6..76fa6fef64739c3fb881dafc92947a5e5c1c054c 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1193,6 +1193,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, x->aalg->alg_key_len = key->sadb_key_bits; memcpy(x->aalg->alg_key, key+1, keysize); } + x->aalg->alg_trunc_len = a->uinfo.auth.icv_truncbits; x->props.aalgo = sa->sadb_sa_auth; /* x->algo.flags = sa->sadb_sa_flags; */ } diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 93ee1fd5c08dd6674152072e9045c48cb0863663..6dc3579c0ac5444a0d8811504aefd6c620c9d1f1 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -354,7 +354,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sinfo->rx_packets = sta->rx_packets; sinfo->tx_packets = sta->tx_packets; - if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { + if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || + (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { sinfo->filled |= STATION_INFO_SIGNAL; sinfo->signal = (s8)sta->last_signal; } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 419f186cfcf08fa7268b34389b3761c24632753f..91dc8636d64481bfefe15c063428f0df018b83a1 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -746,6 +746,7 @@ struct ieee80211_local { unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ bool pspolling; + bool scan_ps_enabled; /* * PS can only be enabled when we have exactly one managed * interface (and monitors) in PS, this then points there. diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index c0fe46493f71cbcd70552baef75d34c85225de28..6a43314295988c76067017be5d19de785e404d54 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -427,7 +427,7 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, char *addr5, char *addr6) { int aelen = 0; - memset(meshhdr, 0, sizeof(meshhdr)); + memset(meshhdr, 0, sizeof(*meshhdr)); meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); sdata->u.mesh.mesh_seqnum++; diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 31e102541869080729120683f69eef29d381f59e..85562c59d7d68bd656fdd1ca00f6129b8adefe8c 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -188,8 +188,9 @@ struct mesh_rmc { */ #define MESH_PREQ_MIN_INT 10 #define MESH_DIAM_TRAVERSAL_TIME 50 -/* Paths will be refreshed if they are closer than PATH_REFRESH_TIME to their - * expiration +/* A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds before + * timing out. This way it will remain ACTIVE and no data frames will be + * unnecesarily held in the pending queue. */ #define MESH_PATH_REFRESH_TIME 1000 #define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME) diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 833b2f3670c59ff83c7d3517630706217472f4ee..d28acb6b1f8151e2a822ec5fc697231b5d76e698 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -937,7 +937,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, if (mpath->flags & MESH_PATH_ACTIVE) { if (time_after(jiffies, - mpath->exp_time + + mpath->exp_time - msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && !memcmp(sdata->dev->dev_addr, hdr->addr4, ETH_ALEN) && !(mpath->flags & MESH_PATH_RESOLVING) && diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 6dc7b5ad9a4125dd94ed496b63dfcb1d719e19c6..d8d50fb5e823e395b5d160a6cf560f1678574847 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1083,8 +1083,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_set_wmm_default(sdata); - ieee80211_recalc_idle(local); - /* channel(_type) changes are handled by ieee80211_hw_config */ local->oper_channel_type = NL80211_CHAN_NO_HT; @@ -1370,6 +1368,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, if (!wk) { ieee80211_set_disassoc(sdata, true); + ieee80211_recalc_idle(sdata->local); } else { list_del(&wk->list); kfree(wk); @@ -1403,6 +1402,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, sdata->dev->name, mgmt->sa, reason_code); ieee80211_set_disassoc(sdata, false); + ieee80211_recalc_idle(sdata->local); return RX_MGMT_CFG80211_DISASSOC; } @@ -2117,6 +2117,7 @@ static void ieee80211_sta_work(struct work_struct *work) " after %dms, disconnecting.\n", bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); ieee80211_set_disassoc(sdata, true); + ieee80211_recalc_idle(local); mutex_unlock(&ifmgd->mtx); /* * must be outside lock due to cfg80211, @@ -2560,6 +2561,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, IEEE80211_STYPE_DEAUTH, req->reason_code, cookie); + ieee80211_recalc_idle(sdata->local); + return 0; } @@ -2592,5 +2595,8 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, IEEE80211_STYPE_DISASSOC, req->reason_code, cookie); + + ieee80211_recalc_idle(sdata->local); + return 0; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f237df408378c514e567676eb2272f659f8b3067..9f2807aeaf52d6a7c3ed00134051bf050c2ec5fe 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1712,7 +1712,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) mpp_path_add(proxied_addr, mpp_addr, sdata); } else { spin_lock_bh(&mppath->state_lock); - mppath->exp_time = jiffies; if (compare_ether_addr(mppath->mpp, mpp_addr) != 0) memcpy(mppath->mpp, mpp_addr, ETH_ALEN); spin_unlock_bh(&mppath->state_lock); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 4cf387c944bfa6a2c51a633fe90f08411a8239df..f1a4c7160300a93e8aad02b45a00f3657577574e 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -227,7 +227,8 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) static void ieee80211_scan_ps_enable(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; - bool ps = false; + + local->scan_ps_enabled = false; /* FIXME: what to do when local->pspolling is true? */ @@ -235,12 +236,13 @@ static void ieee80211_scan_ps_enable(struct ieee80211_sub_if_data *sdata) cancel_work_sync(&local->dynamic_ps_enable_work); if (local->hw.conf.flags & IEEE80211_CONF_PS) { - ps = true; + local->scan_ps_enabled = true; local->hw.conf.flags &= ~IEEE80211_CONF_PS; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); } - if (!ps || !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) + if (!(local->scan_ps_enabled) || + !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) /* * If power save was enabled, no need to send a nullfunc * frame because AP knows that we are sleeping. But if the @@ -261,7 +263,7 @@ static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata) if (!local->ps_sdata) ieee80211_send_nullfunc(local, sdata, 0); - else { + else if (local->scan_ps_enabled) { /* * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware * will send a nullfunc frame with the powersave bit set @@ -277,6 +279,16 @@ static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata) */ local->hw.conf.flags |= IEEE80211_CONF_PS; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } else if (local->hw.conf.dynamic_ps_timeout > 0) { + /* + * If IEEE80211_CONF_PS was not set and the dynamic_ps_timer + * had been running before leaving the operating channel, + * restart the timer now and send a nullfunc frame to inform + * the AP that we are awake. + */ + ieee80211_send_nullfunc(local, sdata, 0); + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); } } diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d09f78bb24427cac947d92a7a31e247d27a18996..78a6e924c7e13d11ae31b2acb42e4a2c2c1671af 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -579,7 +579,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, if (elen > left) break; - if (calc_crc && id < 64 && (filter & BIT(id))) + if (calc_crc && id < 64 && (filter & (1ULL << id))) crc = crc32_be(crc, pos - 2, elen + 2); switch (id) { diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 448e5a0fcc2e6b75604426761b5e478486522e6b..c218e07e5cafe80bb65ef86dfec1b27a9cdfb986 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -579,6 +579,8 @@ static ssize_t rfkill_name_show(struct device *dev, static const char *rfkill_get_type_str(enum rfkill_type type) { + BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_FM + 1); + switch (type) { case RFKILL_TYPE_WLAN: return "wlan"; @@ -597,8 +599,6 @@ static const char *rfkill_get_type_str(enum rfkill_type type) default: BUG(); } - - BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_FM + 1); } static ssize_t rfkill_type_show(struct device *dev, diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c index c7450c8f0a7c040ac756bfd28220152e9d3713b8..6dcdd2517819ea2a170038e1d21b35a193606c68 100644 --- a/net/sunrpc/addr.c +++ b/net/sunrpc/addr.c @@ -55,16 +55,8 @@ static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap, /* * RFC 4291, Section 2.2.1 - * - * To keep the result as short as possible, especially - * since we don't shorthand, we don't want leading zeros - * in each halfword, so avoid %pI6. */ - return snprintf(buf, buflen, "%x:%x:%x:%x:%x:%x:%x:%x", - ntohs(addr->s6_addr16[0]), ntohs(addr->s6_addr16[1]), - ntohs(addr->s6_addr16[2]), ntohs(addr->s6_addr16[3]), - ntohs(addr->s6_addr16[4]), ntohs(addr->s6_addr16[5]), - ntohs(addr->s6_addr16[6]), ntohs(addr->s6_addr16[7])); + return snprintf(buf, buflen, "%pI6c", addr); } static size_t rpc_ntop6(const struct sockaddr *sap, diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 7535a7bed2fa89b35910112b9f62e84915cb1513..f394fc190a496f81125a467ec4723862da12c5f2 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c @@ -123,16 +123,19 @@ rpcauth_unhash_cred_locked(struct rpc_cred *cred) clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags); } -static void +static int rpcauth_unhash_cred(struct rpc_cred *cred) { spinlock_t *cache_lock; + int ret; cache_lock = &cred->cr_auth->au_credcache->lock; spin_lock(cache_lock); - if (atomic_read(&cred->cr_count) == 0) + ret = atomic_read(&cred->cr_count) == 0; + if (ret) rpcauth_unhash_cred_locked(cred); spin_unlock(cache_lock); + return ret; } /* @@ -446,31 +449,35 @@ void put_rpccred(struct rpc_cred *cred) { /* Fast path for unhashed credentials */ - if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) - goto need_lock; - - if (!atomic_dec_and_test(&cred->cr_count)) + if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) == 0) { + if (atomic_dec_and_test(&cred->cr_count)) + cred->cr_ops->crdestroy(cred); return; - goto out_destroy; -need_lock: + } + if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock)) return; if (!list_empty(&cred->cr_lru)) { number_cred_unused--; list_del_init(&cred->cr_lru); } - if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) - rpcauth_unhash_cred(cred); if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) { - cred->cr_expire = jiffies; - list_add_tail(&cred->cr_lru, &cred_unused); - number_cred_unused++; - spin_unlock(&rpc_credcache_lock); - return; + if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0) { + cred->cr_expire = jiffies; + list_add_tail(&cred->cr_lru, &cred_unused); + number_cred_unused++; + goto out_nodestroy; + } + if (!rpcauth_unhash_cred(cred)) { + /* We were hashed and someone looked us up... */ + goto out_nodestroy; + } } spin_unlock(&rpc_credcache_lock); -out_destroy: cred->cr_ops->crdestroy(cred); + return; +out_nodestroy: + spin_unlock(&rpc_credcache_lock); } EXPORT_SYMBOL_GPL(put_rpccred); diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index fc6a43ccd95091154cb7aeff1aa457102efe5e93..3c3c50f38a1c4a773113db4f5388b27bc85453f8 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -304,7 +304,7 @@ __gss_find_upcall(struct rpc_inode *rpci, uid_t uid) * to that upcall instead of adding the new upcall. */ static inline struct gss_upcall_msg * -gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg) +gss_add_msg(struct gss_upcall_msg *gss_msg) { struct rpc_inode *rpci = gss_msg->inode; struct inode *inode = &rpci->vfs_inode; @@ -445,7 +445,7 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr gss_new = gss_alloc_msg(gss_auth, uid, clnt, gss_cred->gc_machine_cred); if (IS_ERR(gss_new)) return gss_new; - gss_msg = gss_add_msg(gss_auth, gss_new); + gss_msg = gss_add_msg(gss_new); if (gss_msg == gss_new) { struct inode *inode = &gss_new->inode->vfs_inode; int res = rpc_queue_upcall(inode, &gss_new->msg); @@ -485,7 +485,7 @@ gss_refresh_upcall(struct rpc_task *task) dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid, cred->cr_uid); gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred); - if (IS_ERR(gss_msg) == -EAGAIN) { + if (PTR_ERR(gss_msg) == -EAGAIN) { /* XXX: warning on the first, under the assumption we * shouldn't normally hit this case on a refresh. */ warn_gssd(); diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 38829e20500bf787aa59189501aaf7ce323a113c..154034b675bd90de493d1438ff46a2b230178742 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -79,7 +79,7 @@ static void call_connect_status(struct rpc_task *task); static __be32 *rpc_encode_header(struct rpc_task *task); static __be32 *rpc_verify_header(struct rpc_task *task); -static int rpc_ping(struct rpc_clnt *clnt, int flags); +static int rpc_ping(struct rpc_clnt *clnt); static void rpc_register_client(struct rpc_clnt *clnt) { @@ -340,7 +340,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) return clnt; if (!(args->flags & RPC_CLNT_CREATE_NOPING)) { - int err = rpc_ping(clnt, RPC_TASK_SOFT); + int err = rpc_ping(clnt); if (err != 0) { rpc_shutdown_client(clnt); return ERR_PTR(err); @@ -528,7 +528,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, clnt->cl_prog = program->number; clnt->cl_vers = version->number; clnt->cl_stats = program->stats; - err = rpc_ping(clnt, RPC_TASK_SOFT); + err = rpc_ping(clnt); if (err != 0) { rpc_shutdown_client(clnt); clnt = ERR_PTR(err); @@ -1060,7 +1060,7 @@ call_bind_status(struct rpc_task *task) goto retry_timeout; case -EPFNOSUPPORT: /* server doesn't support any rpcbind version we know of */ - dprintk("RPC: %5u remote rpcbind service unavailable\n", + dprintk("RPC: %5u unrecognized remote rpcbind service\n", task->tk_pid); break; case -EPROTONOSUPPORT: @@ -1069,6 +1069,21 @@ call_bind_status(struct rpc_task *task) task->tk_status = 0; task->tk_action = call_bind; return; + case -ECONNREFUSED: /* connection problems */ + case -ECONNRESET: + case -ENOTCONN: + case -EHOSTDOWN: + case -EHOSTUNREACH: + case -ENETUNREACH: + case -EPIPE: + dprintk("RPC: %5u remote rpcbind unreachable: %d\n", + task->tk_pid, task->tk_status); + if (!RPC_IS_SOFTCONN(task)) { + rpc_delay(task, 5*HZ); + goto retry_timeout; + } + status = task->tk_status; + break; default: dprintk("RPC: %5u unrecognized rpcbind error (%d)\n", task->tk_pid, -task->tk_status); @@ -1180,11 +1195,25 @@ static void call_transmit_status(struct rpc_task *task) { task->tk_action = call_status; + + /* + * Common case: success. Force the compiler to put this + * test first. + */ + if (task->tk_status == 0) { + xprt_end_transmit(task); + rpc_task_force_reencode(task); + return; + } + switch (task->tk_status) { case -EAGAIN: break; default: + dprint_status(task); xprt_end_transmit(task); + rpc_task_force_reencode(task); + break; /* * Special cases: if we've been waiting on the * socket's write_space() callback, or if the @@ -1192,11 +1221,16 @@ call_transmit_status(struct rpc_task *task) * then hold onto the transport lock. */ case -ECONNREFUSED: - case -ECONNRESET: - case -ENOTCONN: case -EHOSTDOWN: case -EHOSTUNREACH: case -ENETUNREACH: + if (RPC_IS_SOFTCONN(task)) { + xprt_end_transmit(task); + rpc_exit(task, task->tk_status); + break; + } + case -ECONNRESET: + case -ENOTCONN: case -EPIPE: rpc_task_force_reencode(task); } @@ -1346,6 +1380,10 @@ call_timeout(struct rpc_task *task) dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid); task->tk_timeouts++; + if (RPC_IS_SOFTCONN(task)) { + rpc_exit(task, -ETIMEDOUT); + return; + } if (RPC_IS_SOFT(task)) { if (clnt->cl_chatty) printk(KERN_NOTICE "%s: server %s not responding, timed out\n", @@ -1675,14 +1713,14 @@ static struct rpc_procinfo rpcproc_null = { .p_decode = rpcproc_decode_null, }; -static int rpc_ping(struct rpc_clnt *clnt, int flags) +static int rpc_ping(struct rpc_clnt *clnt) { struct rpc_message msg = { .rpc_proc = &rpcproc_null, }; int err; msg.rpc_cred = authnull_ops.lookup_cred(NULL, NULL, 0); - err = rpc_call_sync(clnt, &msg, flags); + err = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN); put_rpccred(msg.rpc_cred); return err; } diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 830faf4d9997c971bb717ee0a2210efb2f22bc63..3e3772d8eb921ce00af629ad11627ad3677ea613 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -110,6 +111,9 @@ static void rpcb_getport_done(struct rpc_task *, void *); static void rpcb_map_release(void *data); static struct rpc_program rpcb_program; +static struct rpc_clnt * rpcb_local_clnt; +static struct rpc_clnt * rpcb_local_clnt4; + struct rpcbind_args { struct rpc_xprt * r_xprt; @@ -163,21 +167,60 @@ static const struct sockaddr_in rpcb_inaddr_loopback = { .sin_port = htons(RPCBIND_PORT), }; -static struct rpc_clnt *rpcb_create_local(struct sockaddr *addr, - size_t addrlen, u32 version) +static DEFINE_MUTEX(rpcb_create_local_mutex); + +/* + * Returns zero on success, otherwise a negative errno value + * is returned. + */ +static int rpcb_create_local(void) { struct rpc_create_args args = { - .protocol = XPRT_TRANSPORT_UDP, - .address = addr, - .addrsize = addrlen, + .protocol = XPRT_TRANSPORT_TCP, + .address = (struct sockaddr *)&rpcb_inaddr_loopback, + .addrsize = sizeof(rpcb_inaddr_loopback), .servername = "localhost", .program = &rpcb_program, - .version = version, + .version = RPCBVERS_2, .authflavor = RPC_AUTH_UNIX, .flags = RPC_CLNT_CREATE_NOPING, }; + struct rpc_clnt *clnt, *clnt4; + int result = 0; + + if (rpcb_local_clnt) + return result; + + mutex_lock(&rpcb_create_local_mutex); + if (rpcb_local_clnt) + goto out; + + clnt = rpc_create(&args); + if (IS_ERR(clnt)) { + dprintk("RPC: failed to create local rpcbind " + "client (errno %ld).\n", PTR_ERR(clnt)); + result = -PTR_ERR(clnt); + goto out; + } - return rpc_create(&args); + /* + * This results in an RPC ping. On systems running portmapper, + * the v4 ping will fail. Proceed anyway, but disallow rpcb + * v4 upcalls. + */ + clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4); + if (IS_ERR(clnt4)) { + dprintk("RPC: failed to create local rpcbind v4 " + "cleint (errno %ld).\n", PTR_ERR(clnt4)); + clnt4 = NULL; + } + + rpcb_local_clnt = clnt; + rpcb_local_clnt4 = clnt4; + +out: + mutex_unlock(&rpcb_create_local_mutex); + return result; } static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, @@ -209,22 +252,13 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, return rpc_create(&args); } -static int rpcb_register_call(const u32 version, struct rpc_message *msg) +static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg) { - struct sockaddr *addr = (struct sockaddr *)&rpcb_inaddr_loopback; - size_t addrlen = sizeof(rpcb_inaddr_loopback); - struct rpc_clnt *rpcb_clnt; int result, error = 0; msg->rpc_resp = &result; - rpcb_clnt = rpcb_create_local(addr, addrlen, version); - if (!IS_ERR(rpcb_clnt)) { - error = rpc_call_sync(rpcb_clnt, msg, 0); - rpc_shutdown_client(rpcb_clnt); - } else - error = PTR_ERR(rpcb_clnt); - + error = rpc_call_sync(clnt, msg, RPC_TASK_SOFTCONN); if (error < 0) { dprintk("RPC: failed to contact local rpcbind " "server (errno %d).\n", -error); @@ -279,6 +313,11 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) struct rpc_message msg = { .rpc_argp = &map, }; + int error; + + error = rpcb_create_local(); + if (error) + return error; dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " "rpcbind\n", (port ? "" : "un"), @@ -288,7 +327,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) if (port) msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; - return rpcb_register_call(RPCBVERS_2, &msg); + return rpcb_register_call(rpcb_local_clnt, &msg); } /* @@ -313,7 +352,7 @@ static int rpcb_register_inet4(const struct sockaddr *sap, if (port) msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; - result = rpcb_register_call(RPCBVERS_4, msg); + result = rpcb_register_call(rpcb_local_clnt4, msg); kfree(map->r_addr); return result; } @@ -340,7 +379,7 @@ static int rpcb_register_inet6(const struct sockaddr *sap, if (port) msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; - result = rpcb_register_call(RPCBVERS_4, msg); + result = rpcb_register_call(rpcb_local_clnt4, msg); kfree(map->r_addr); return result; } @@ -356,7 +395,7 @@ static int rpcb_unregister_all_protofamilies(struct rpc_message *msg) map->r_addr = ""; msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; - return rpcb_register_call(RPCBVERS_4, msg); + return rpcb_register_call(rpcb_local_clnt4, msg); } /** @@ -414,6 +453,13 @@ int rpcb_v4_register(const u32 program, const u32 version, struct rpc_message msg = { .rpc_argp = &map, }; + int error; + + error = rpcb_create_local(); + if (error) + return error; + if (rpcb_local_clnt4 == NULL) + return -EPROTONOSUPPORT; if (address == NULL) return rpcb_unregister_all_protofamilies(&msg); @@ -491,7 +537,7 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi .rpc_message = &msg, .callback_ops = &rpcb_getport_ops, .callback_data = map, - .flags = RPC_TASK_ASYNC, + .flags = RPC_TASK_ASYNC | RPC_TASK_SOFTCONN, }; return rpc_run_task(&task_setup_data); @@ -1027,3 +1073,15 @@ static struct rpc_program rpcb_program = { .version = rpcb_version, .stats = &rpcb_stats, }; + +/** + * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister + * + */ +void cleanup_rpcb_clnt(void) +{ + if (rpcb_local_clnt4) + rpc_shutdown_client(rpcb_local_clnt4); + if (rpcb_local_clnt) + rpc_shutdown_client(rpcb_local_clnt); +} diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 8cce92189019c7e8d73cc874820a88187067de22..f438347d817b2bb5889ea6d364db5abeceb819e9 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c @@ -24,6 +24,8 @@ extern struct cache_detail ip_map_cache, unix_gid_cache; +extern void cleanup_rpcb_clnt(void); + static int __init init_sunrpc(void) { @@ -53,6 +55,7 @@ out: static void __exit cleanup_sunrpc(void) { + cleanup_rpcb_clnt(); rpcauth_remove_module(); cleanup_socket_xprt(); svc_cleanup_xprt_sock(); diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index fd46d42afa89ed89e6fe2813822f7570e6683160..469de292c23c34b8ba9a0f9ea24e07d4b77d5e09 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -700,6 +700,10 @@ void xprt_connect(struct rpc_task *task) } if (!xprt_lock_write(xprt, task)) return; + + if (test_and_clear_bit(XPRT_CLOSE_WAIT, &xprt->state)) + xprt->ops->close(xprt); + if (xprt_connected(xprt)) xprt_release_write(xprt, task); else { diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 04732d09013eaa745c1e557d7d0a53f02699e21c..3d739e5d15d8b65a77be7fcb80a9ed012ba7c0d3 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -2019,7 +2019,7 @@ static void xs_connect(struct rpc_task *task) if (xprt_test_and_set_connecting(xprt)) return; - if (transport->sock != NULL) { + if (transport->sock != NULL && !RPC_IS_SOFTCONN(task)) { dprintk("RPC: xs_connect delayed xprt %p for %lu " "seconds\n", xprt, xprt->reestablish_timeout / HZ); diff --git a/net/wireless/reg.c b/net/wireless/reg.c index c01470e7de15a627c3baf0094dfdd5220c56684a..baa898add28760d8c13642c47cdb1f1c4a49c0c5 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -141,62 +141,35 @@ static const struct ieee80211_regdomain us_regdom = { .reg_rules = { /* IEEE 802.11b/g, channels 1..11 */ REG_RULE(2412-10, 2462+10, 40, 6, 27, 0), - /* IEEE 802.11a, channel 36 */ - REG_RULE(5180-10, 5180+10, 40, 6, 23, 0), - /* IEEE 802.11a, channel 40 */ - REG_RULE(5200-10, 5200+10, 40, 6, 23, 0), - /* IEEE 802.11a, channel 44 */ - REG_RULE(5220-10, 5220+10, 40, 6, 23, 0), + /* IEEE 802.11a, channel 36..48 */ + REG_RULE(5180-10, 5240+10, 40, 6, 17, 0), /* IEEE 802.11a, channels 48..64 */ - REG_RULE(5240-10, 5320+10, 40, 6, 23, 0), + REG_RULE(5260-10, 5320+10, 40, 6, 20, NL80211_RRF_DFS), + /* IEEE 802.11a, channels 100..124 */ + REG_RULE(5500-10, 5590+10, 40, 6, 20, NL80211_RRF_DFS), + /* IEEE 802.11a, channels 132..144 */ + REG_RULE(5660-10, 5700+10, 40, 6, 20, NL80211_RRF_DFS), /* IEEE 802.11a, channels 149..165, outdoor */ REG_RULE(5745-10, 5825+10, 40, 6, 30, 0), } }; static const struct ieee80211_regdomain jp_regdom = { - .n_reg_rules = 3, + .n_reg_rules = 6, .alpha2 = "JP", .reg_rules = { - /* IEEE 802.11b/g, channels 1..14 */ - REG_RULE(2412-10, 2484+10, 40, 6, 20, 0), - /* IEEE 802.11a, channels 34..48 */ - REG_RULE(5170-10, 5240+10, 40, 6, 20, - NL80211_RRF_PASSIVE_SCAN), + /* IEEE 802.11b/g, channels 1..11 */ + REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), + /* IEEE 802.11b/g, channels 12..13 */ + REG_RULE(2467-10, 2472+10, 20, 6, 20, 0), + /* IEEE 802.11b/g, channel 14 */ + REG_RULE(2484-10, 2484+10, 20, 6, 20, NL80211_RRF_NO_OFDM), + /* IEEE 802.11a, channels 36..48 */ + REG_RULE(5180-10, 5240+10, 40, 6, 20, 0), /* IEEE 802.11a, channels 52..64 */ - REG_RULE(5260-10, 5320+10, 40, 6, 20, - NL80211_RRF_NO_IBSS | - NL80211_RRF_DFS), - } -}; - -static const struct ieee80211_regdomain eu_regdom = { - .n_reg_rules = 6, - /* - * This alpha2 is bogus, we leave it here just for stupid - * backward compatibility - */ - .alpha2 = "EU", - .reg_rules = { - /* IEEE 802.11b/g, channels 1..13 */ - REG_RULE(2412-10, 2472+10, 40, 6, 20, 0), - /* IEEE 802.11a, channel 36 */ - REG_RULE(5180-10, 5180+10, 40, 6, 23, - NL80211_RRF_PASSIVE_SCAN), - /* IEEE 802.11a, channel 40 */ - REG_RULE(5200-10, 5200+10, 40, 6, 23, - NL80211_RRF_PASSIVE_SCAN), - /* IEEE 802.11a, channel 44 */ - REG_RULE(5220-10, 5220+10, 40, 6, 23, - NL80211_RRF_PASSIVE_SCAN), - /* IEEE 802.11a, channels 48..64 */ - REG_RULE(5240-10, 5320+10, 40, 6, 20, - NL80211_RRF_NO_IBSS | - NL80211_RRF_DFS), - /* IEEE 802.11a, channels 100..140 */ - REG_RULE(5500-10, 5700+10, 40, 6, 30, - NL80211_RRF_NO_IBSS | - NL80211_RRF_DFS), + REG_RULE(5260-10, 5320+10, 40, 6, 20, NL80211_RRF_DFS), + /* IEEE 802.11a, channels 100..144 */ + REG_RULE(5500-10, 5700+10, 40, 6, 23, NL80211_RRF_DFS), } }; @@ -206,15 +179,17 @@ static const struct ieee80211_regdomain *static_regdom(char *alpha2) return &us_regdom; if (alpha2[0] == 'J' && alpha2[1] == 'P') return &jp_regdom; + /* Use world roaming rules for "EU", since it was a pseudo + domain anyway... */ if (alpha2[0] == 'E' && alpha2[1] == 'U') - return &eu_regdom; - /* Default, as per the old rules */ - return &us_regdom; + return &world_regdom; + /* Default, world roaming rules */ + return &world_regdom; } static bool is_old_static_regdom(const struct ieee80211_regdomain *rd) { - if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom) + if (rd == &us_regdom || rd == &jp_regdom || rd == &world_regdom) return true; return false; } diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 584eb4826e02540973297e975e214bd4553bcd9f..54face3d4424c973ab6b297ea9582daba6c0beab 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -479,6 +479,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, } err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); } + wdev->wext.connect.privacy = false; /* * Applications using wireless extensions expect to be * able to delete keys that don't exist, so allow that. diff --git a/samples/hw_breakpoint/data_breakpoint.c b/samples/hw_breakpoint/data_breakpoint.c index 29525500df00e51c5630e7da0e79a8db2b8c99f0..c69cbe9b2426a287bf754a82344957f9a2ead426 100644 --- a/samples/hw_breakpoint/data_breakpoint.c +++ b/samples/hw_breakpoint/data_breakpoint.c @@ -41,7 +41,9 @@ module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO); MODULE_PARM_DESC(ksym, "Kernel symbol to monitor; this module will report any" " write operations on the kernel symbol"); -static void sample_hbp_handler(struct perf_event *temp, void *data) +static void sample_hbp_handler(struct perf_event *bp, int nmi, + struct perf_sample_data *data, + struct pt_regs *regs) { printk(KERN_INFO "%s value is changed\n", ksym_name); dump_stack(); @@ -51,8 +53,9 @@ static void sample_hbp_handler(struct perf_event *temp, void *data) static int __init hw_break_module_init(void) { int ret; - DEFINE_BREAKPOINT_ATTR(attr); + struct perf_event_attr attr; + hw_breakpoint_init(&attr); attr.bp_addr = kallsyms_lookup_name(ksym_name); attr.bp_len = HW_BREAKPOINT_LEN_4; attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R; diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 62a9025cdcc78c0640c2457f4735e0d782f815c6..6f426afbc52230cf01613c420994443e7bdf08af 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -104,7 +104,7 @@ static void device_id_check(const char *modname, const char *device_id, static void do_usb_entry(struct usb_device_id *id, unsigned int bcdDevice_initial, int bcdDevice_initial_digits, unsigned char range_lo, unsigned char range_hi, - struct module *mod) + unsigned char max, struct module *mod) { char alias[500]; strcpy(alias, "usb:"); @@ -118,9 +118,22 @@ static void do_usb_entry(struct usb_device_id *id, sprintf(alias + strlen(alias), "%0*X", bcdDevice_initial_digits, bcdDevice_initial); if (range_lo == range_hi) - sprintf(alias + strlen(alias), "%u", range_lo); - else if (range_lo > 0 || range_hi < 9) - sprintf(alias + strlen(alias), "[%u-%u]", range_lo, range_hi); + sprintf(alias + strlen(alias), "%X", range_lo); + else if (range_lo > 0 || range_hi < max) { + if (range_lo > 0x9 || range_hi < 0xA) + sprintf(alias + strlen(alias), + "[%X-%X]", + range_lo, + range_hi); + else { + sprintf(alias + strlen(alias), + range_lo < 0x9 ? "[%X-9" : "[%X", + range_lo); + sprintf(alias + strlen(alias), + range_hi > 0xA ? "a-%X]" : "%X]", + range_lo); + } + } if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1)) strcat(alias, "*"); @@ -147,10 +160,49 @@ static void do_usb_entry(struct usb_device_id *id, "MODULE_ALIAS(\"%s\");\n", alias); } +/* Handles increment/decrement of BCD formatted integers */ +/* Returns the previous value, so it works like i++ or i-- */ +static unsigned int incbcd(unsigned int *bcd, + int inc, + unsigned char max, + size_t chars) +{ + unsigned int init = *bcd, i, j; + unsigned long long c, dec = 0; + + /* If bcd is not in BCD format, just increment */ + if (max > 0x9) { + *bcd += inc; + return init; + } + + /* Convert BCD to Decimal */ + for (i=0 ; i < chars ; i++) { + c = (*bcd >> (i << 2)) & 0xf; + c = c > 9 ? 9 : c; /* force to bcd just in case */ + for (j=0 ; j < i ; j++) + c = c * 10; + dec += c; + } + + /* Do our increment/decrement */ + dec += inc; + *bcd = 0; + + /* Convert back to BCD */ + for (i=0 ; i < chars ; i++) { + for (c=1,j=0 ; j < i ; j++) + c = c * 10; + c = (dec / c) % 10; + *bcd += c << (i << 2); + } + return init; +} + static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) { unsigned int devlo, devhi; - unsigned char chi, clo; + unsigned char chi, clo, max; int ndigits; id->match_flags = TO_NATIVE(id->match_flags); @@ -162,6 +214,17 @@ static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ? TO_NATIVE(id->bcdDevice_hi) : ~0x0U; + /* Figure out if this entry is in bcd or hex format */ + max = 0x9; /* Default to decimal format */ + for (ndigits = 0 ; ndigits < sizeof(id->bcdDevice_lo) * 2 ; ndigits++) { + clo = (devlo >> (ndigits << 2)) & 0xf; + chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf; + if (clo > max || chi > max) { + max = 0xf; + break; + } + } + /* * Some modules (visor) have empty slots as placeholder for * run-time specification that results in catch-all alias @@ -173,21 +236,27 @@ static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) { clo = devlo & 0xf; chi = devhi & 0xf; - if (chi > 9) /* it's bcd not hex */ - chi = 9; + if (chi > max) /* If we are in bcd mode, truncate if necessary */ + chi = max; devlo >>= 4; devhi >>= 4; if (devlo == devhi || !ndigits) { - do_usb_entry(id, devlo, ndigits, clo, chi, mod); + do_usb_entry(id, devlo, ndigits, clo, chi, max, mod); break; } - if (clo > 0) - do_usb_entry(id, devlo++, ndigits, clo, 9, mod); - - if (chi < 9) - do_usb_entry(id, devhi--, ndigits, 0, chi, mod); + if (clo > 0x0) + do_usb_entry(id, + incbcd(&devlo, 1, max, + sizeof(id->bcdDevice_lo) * 2), + ndigits, clo, max, max, mod); + + if (chi < max) + do_usb_entry(id, + incbcd(&devhi, -1, max, + sizeof(id->bcdDevice_lo) * 2), + ndigits, 0x0, chi, max, mod); } } diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl index f0d14452632b554fa3d85681d075a729b54ebb2f..9cf0a6fad6ba8bc03a11dca5e658fde8ed8f6af4 100755 --- a/scripts/recordmcount.pl +++ b/scripts/recordmcount.pl @@ -295,6 +295,9 @@ if ($arch eq "x86_64") { $ld .= " -m elf64_sparc"; $cc .= " -m64"; $objcopy .= " -O elf64-sparc"; +} elsif ($arch eq "microblaze") { + # Microblaze calls '_mcount' instead of plain 'mcount'. + $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$"; } else { die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD"; } diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index 34c7d48f5061b9fd2025a23e78ac63c4bcd3fd55..7f4d744ae40ae7ce8102e1c6439fc306a5abb174 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c @@ -37,14 +37,22 @@ static unsigned int resolution; struct snd_hrtimer { struct snd_timer *timer; struct hrtimer hrt; + atomic_t running; }; static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt) { struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt); struct snd_timer *t = stime->timer; + + if (!atomic_read(&stime->running)) + return HRTIMER_NORESTART; + hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution)); snd_timer_interrupt(stime->timer, t->sticks); + + if (!atomic_read(&stime->running)) + return HRTIMER_NORESTART; return HRTIMER_RESTART; } @@ -58,6 +66,7 @@ static int snd_hrtimer_open(struct snd_timer *t) hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); stime->timer = t; stime->hrt.function = snd_hrtimer_callback; + atomic_set(&stime->running, 0); t->private_data = stime; return 0; } @@ -78,16 +87,18 @@ static int snd_hrtimer_start(struct snd_timer *t) { struct snd_hrtimer *stime = t->private_data; + atomic_set(&stime->running, 0); + hrtimer_cancel(&stime->hrt); hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution), HRTIMER_MODE_REL); + atomic_set(&stime->running, 1); return 0; } static int snd_hrtimer_stop(struct snd_timer *t) { struct snd_hrtimer *stime = t->private_data; - - hrtimer_cancel(&stime->hrt); + atomic_set(&stime->running, 0); return 0; } diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 2f766123b158114448added4ad9b552fb333e3ee..0f5a194695d90c892b3585031176249de5e4b62b 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -1257,7 +1257,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, break; count -= count1; } - if (file->f_flags & O_SYNC) { + if (file->f_flags & O_DSYNC) { spin_lock_irq(&runtime->lock); while (runtime->avail != runtime->buffer_size) { wait_queue_t wait; diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 106be6e471f7c051c98872dbe4bc8d92ac0de059..c8a8da0d403616f48a3c39d0dc50dcffce8f1e91 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -548,10 +548,13 @@ __skip_mpu: static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id) { - struct snd_wss *codec = dev_id; - struct snd_opti9xx *chip = codec->card->private_data; + struct snd_opti9xx *chip = dev_id; + struct snd_wss *codec = chip->codec; unsigned char status; + if (!codec) + return IRQ_HANDLED; + status = snd_opti9xx_read(chip, OPTi9XX_MC_REG(11)); if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream) snd_pcm_period_elapsed(codec->playback_substream); @@ -691,10 +694,9 @@ static void snd_card_opti9xx_free(struct snd_card *card) if (chip) { #ifdef OPTi93X - struct snd_wss *codec = chip->codec; - if (codec && codec->irq > 0) { - disable_irq(codec->irq); - free_irq(codec->irq, codec); + if (chip->irq > 0) { + disable_irq(chip->irq); + free_irq(chip->irq, chip); } release_and_free_resource(chip->res_mc_indir); #endif @@ -759,9 +761,9 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) #endif #ifdef OPTi93X error = request_irq(irq, snd_opti93x_interrupt, - IRQF_DISABLED, DEV_NAME" - WSS", codec); + IRQF_DISABLED, DEV_NAME" - WSS", chip); if (error < 0) { - snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq); + snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq); return error; } #endif diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 2d627613aea356eb5526f22ed273524c47716afb..1d541b7f5547cde1e3871d45e44e7cae4931a435 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -255,9 +255,13 @@ enum { * in HD-audio specification */ #define AC_PINCAP_HDMI (1<<7) /* HDMI pin */ +#define AC_PINCAP_DP (1<<24) /* DisplayPort pin, can + * coexist with AC_PINCAP_HDMI + */ #define AC_PINCAP_VREF (0x37<<8) #define AC_PINCAP_VREF_SHIFT 8 #define AC_PINCAP_EAPD (1<<16) /* EAPD capable */ +#define AC_PINCAP_HBR (1<<27) /* High Bit Rate */ /* Vref status (used in pin cap) */ #define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */ #define AC_PINCAP_VREF_50 (1<<1) /* 50% */ @@ -635,6 +639,7 @@ struct hda_bus { unsigned int rirb_error:1; /* error in codec communication */ unsigned int response_reset:1; /* controller was reset */ unsigned int in_reset:1; /* during reset operation */ + unsigned int power_keep_link_on:1; /* don't power off HDA link */ }; /* diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index efcc4f7c57f20f7a85f159588b83daa784451a08..e54420e691ae7c9e41da79f26ee277b2f0786357 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2082,7 +2082,8 @@ static void azx_power_notify(struct hda_bus *bus) } if (power_on) azx_init_chip(chip); - else if (chip->running && power_save_controller) + else if (chip->running && power_save_controller && + !bus->power_keep_link_on) azx_stop_chip(chip); } #endif /* CONFIG_SND_HDA_POWER_SAVE */ diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 09476fc1ab64980c78ca170ca00fa7cbb3bb6ab2..c9afc04adac8d126c302b7c11bcdc183b355766a 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -240,9 +240,14 @@ static void print_pin_caps(struct snd_info_buffer *buffer, /* Realtek uses this bit as a different meaning */ if ((codec->vendor_id >> 16) == 0x10ec) snd_iprintf(buffer, " R/L"); - else + else { + if (caps & AC_PINCAP_HBR) + snd_iprintf(buffer, " HBR"); snd_iprintf(buffer, " HDMI"); + } } + if (caps & AC_PINCAP_DP) + snd_iprintf(buffer, " DP"); if (caps & AC_PINCAP_TRIG_REQ) snd_iprintf(buffer, " Trigger"); if (caps & AC_PINCAP_IMP_SENSE) diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c index 928df59be5d8737e27f78a2e9c56f4afa3cde1b6..918f40378d5232e929b3034ac208164d338c3557 100644 --- a/sound/pci/hda/patch_intelhdmi.c +++ b/sound/pci/hda/patch_intelhdmi.c @@ -145,6 +145,42 @@ struct cea_channel_speaker_allocation { int spk_mask; }; +/* + * ALSA sequence is: + * + * surround40 surround41 surround50 surround51 surround71 + * ch0 front left = = = = + * ch1 front right = = = = + * ch2 rear left = = = = + * ch3 rear right = = = = + * ch4 LFE center center center + * ch5 LFE LFE + * ch6 side left + * ch7 side right + * + * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} + */ +static int hdmi_channel_mapping[0x32][8] = { + /* stereo */ + [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* 2.1 */ + [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* Dolby Surround */ + [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* surround40 */ + [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, + /* 4ch */ + [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, + /* surround41 */ + [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, + /* surround50 */ + [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, + /* surround51 */ + [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, + /* 7.1 */ + [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, +}; + /* * This is an ordered list! * @@ -152,32 +188,36 @@ struct cea_channel_speaker_allocation { * hdmi_setup_channel_allocation(). */ static struct cea_channel_speaker_allocation channel_allocations[] = { -/* channel: 8 7 6 5 4 3 2 1 */ +/* channel: 7 6 5 4 3 2 1 0 */ { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, /* 2.1 */ { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, /* Dolby Surround */ { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, + /* surround40 */ +{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, + /* surround41 */ +{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, + /* surround50 */ +{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, + /* surround51 */ +{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, + /* 6.1 */ +{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, + /* surround71 */ +{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, + { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, -{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, - /* 5.1 */ -{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, - /* 6.1 */ -{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, - /* 7.1 */ -{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, @@ -210,7 +250,6 @@ static struct cea_channel_speaker_allocation channel_allocations[] = { { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, }; - /* * HDA/HDMI auto parsing */ @@ -344,7 +383,7 @@ static int intel_hdmi_parse_codec(struct hda_codec *codec) break; case AC_WID_PIN: caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); - if (!(caps & AC_PINCAP_HDMI)) + if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) continue; if (intel_hdmi_add_pin(codec, nid) < 0) return -EINVAL; @@ -352,6 +391,17 @@ static int intel_hdmi_parse_codec(struct hda_codec *codec) } } + /* + * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event + * can be lost and presence sense verb will become inaccurate if the + * HDA link is powered off at hot plug or hw initialization time. + */ +#ifdef CONFIG_SND_HDA_POWER_SAVE + if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & + AC_PWRST_EPSS)) + codec->bus->power_keep_link_on = 1; +#endif + return 0; } @@ -436,14 +486,15 @@ static void hdmi_set_channel_count(struct hda_codec *codec, AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); } -static void hdmi_debug_channel_mapping(struct hda_codec *codec, hda_nid_t nid) +static void hdmi_debug_channel_mapping(struct hda_codec *codec, + hda_nid_t pin_nid) { #ifdef CONFIG_SND_DEBUG_VERBOSE int i; int slot; for (i = 0; i < 8; i++) { - slot = snd_hda_codec_read(codec, nid, 0, + slot = snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_CHAN_SLOT, i); printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", slot >> 4, slot & 0xf); @@ -619,25 +670,32 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, return ai->CA; } -static void hdmi_setup_channel_mapping(struct hda_codec *codec, hda_nid_t nid, +static void hdmi_setup_channel_mapping(struct hda_codec *codec, + hda_nid_t pin_nid, struct hdmi_audio_infoframe *ai) { int i; + int ca = ai->CA; + int err; - if (!ai->CA) - return; - - /* - * TODO: adjust channel mapping if necessary - * ALSA sequence is front/surr/clfe/side? - */ + if (hdmi_channel_mapping[ca][1] == 0) { + for (i = 0; i < channel_allocations[ca].channels; i++) + hdmi_channel_mapping[ca][i] = i | (i << 4); + for (; i < 8; i++) + hdmi_channel_mapping[ca][i] = 0xf | (i << 4); + } - for (i = 0; i < 8; i++) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_HDMI_CHAN_SLOT, - (i << 4) | i); + for (i = 0; i < 8; i++) { + err = snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_HDMI_CHAN_SLOT, + hdmi_channel_mapping[ca][i]); + if (err) { + snd_printdd(KERN_INFO "HDMI: channel mapping failed\n"); + break; + } + } - hdmi_debug_channel_mapping(codec, nid); + hdmi_debug_channel_mapping(codec, pin_nid); } static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, @@ -676,7 +734,6 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, }; hdmi_setup_channel_allocation(codec, nid, &ai); - hdmi_setup_channel_mapping(codec, nid, &ai); for (i = 0; i < spec->num_pins; i++) { if (spec->pin_cvt[i] != nid) @@ -686,6 +743,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, pin_nid = spec->pin[i]; if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { + hdmi_setup_channel_mapping(codec, pin_nid, &ai); hdmi_stop_infoframe_trans(codec, pin_nid); hdmi_fill_audio_infoframe(codec, pin_nid, &ai); hdmi_start_infoframe_trans(codec, pin_nid); diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 6b0bc040c3b134c02ee38b64974de4b53c36b6f4..3d59f83258489d4d89d7bb2399e78430afaff2d8 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -209,6 +209,7 @@ struct sigmatel_spec { unsigned int gpio_data; unsigned int gpio_mute; unsigned int gpio_led; + unsigned int gpio_led_polarity; /* stream */ unsigned int stream_delay; @@ -1538,6 +1539,13 @@ static unsigned int alienware_m17x_pin_configs[13] = { 0x904601b0, }; +static unsigned int intel_dg45id_pin_configs[14] = { + 0x02214230, 0x02A19240, 0x01013214, 0x01014210, + 0x01A19250, 0x01011212, 0x01016211, 0x40f000f0, + 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x014510A0, + 0x074510B0, 0x40f000f0 +}; + static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs, [STAC_DELL_M6_AMIC] = dell_m6_pin_configs, @@ -1545,6 +1553,7 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { [STAC_DELL_M6_BOTH] = dell_m6_pin_configs, [STAC_DELL_EQ] = dell_m6_pin_configs, [STAC_ALIENWARE_M17X] = alienware_m17x_pin_configs, + [STAC_92HD73XX_INTEL] = intel_dg45id_pin_configs, }; static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { @@ -4724,13 +4733,61 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) } } -static int hp_bseries_system(u32 subsystem_id) +/* + * This method searches for the mute LED GPIO configuration + * provided as OEM string in SMBIOS. The format of that string + * is HP_Mute_LED_P_G or HP_Mute_LED_P + * where P can be 0 or 1 and defines mute LED GPIO control state (low/high) + * that corresponds to the NOT muted state of the master volume + * and G is the index of the GPIO to use as the mute LED control (0..9) + * If _G portion is missing it is assigned based on the codec ID + * + * So, HP B-series like systems may have HP_Mute_LED_0 (current models) + * or HP_Mute_LED_0_3 (future models) OEM SMBIOS strings + */ +static int find_mute_led_gpio(struct hda_codec *codec) +{ + struct sigmatel_spec *spec = codec->spec; + const struct dmi_device *dev = NULL; + + if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { + while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, + NULL, dev))) { + if (sscanf(dev->name, "HP_Mute_LED_%d_%d", + &spec->gpio_led_polarity, + &spec->gpio_led) == 2) { + spec->gpio_led = 1 << spec->gpio_led; + return 1; + } + if (sscanf(dev->name, "HP_Mute_LED_%d", + &spec->gpio_led_polarity) == 1) { + switch (codec->vendor_id) { + case 0x111d7608: + /* GPIO 0 */ + spec->gpio_led = 0x01; + return 1; + case 0x111d7600: + case 0x111d7601: + case 0x111d7602: + case 0x111d7603: + /* GPIO 3 */ + spec->gpio_led = 0x08; + return 1; + } + } + } + } + return 0; +} + +static int hp_blike_system(u32 subsystem_id) { switch (subsystem_id) { - case 0x103c307e: - case 0x103c307f: - case 0x103c3080: - case 0x103c3081: + case 0x103c1520: + case 0x103c1521: + case 0x103c1523: + case 0x103c1524: + case 0x103c1525: case 0x103c1722: case 0x103c1723: case 0x103c1724: @@ -4739,6 +4796,14 @@ static int hp_bseries_system(u32 subsystem_id) case 0x103c1727: case 0x103c1728: case 0x103c1729: + case 0x103c172a: + case 0x103c172b: + case 0x103c307e: + case 0x103c307f: + case 0x103c3080: + case 0x103c3081: + case 0x103c7007: + case 0x103c7008: return 1; } return 0; @@ -4833,7 +4898,7 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, else spec->gpio_data |= spec->gpio_led; /* white */ - if (hp_bseries_system(codec->subsystem_id)) { + if (!spec->gpio_led_polarity) { /* LED state is inverted on these systems */ spec->gpio_data ^= spec->gpio_led; } @@ -5526,7 +5591,7 @@ again: break; } - if (hp_bseries_system(codec->subsystem_id)) { + if (hp_blike_system(codec->subsystem_id)) { pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f); if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT || get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER || @@ -5544,26 +5609,10 @@ again: } } - if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { - const struct dmi_device *dev = NULL; - while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, - NULL, dev))) { - if (strcmp(dev->name, "HP_Mute_LED_1")) { - switch (codec->vendor_id) { - case 0x111d7608: - spec->gpio_led = 0x01; - break; - case 0x111d7600: - case 0x111d7601: - case 0x111d7602: - case 0x111d7603: - spec->gpio_led = 0x08; - break; - } - break; - } - } - } + if (find_mute_led_gpio(codec)) + snd_printd("mute LED gpio %d polarity %d\n", + spec->gpio_led, + spec->gpio_led_polarity); #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 7717e01fc07127f51e99c3a669a18be75ab6a0eb..edaa729126bb731b0f86a55a7277f258f2774f4c 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -143,7 +143,8 @@ static int snd_pdacf_probe(struct pcmcia_device *link) link->io.NumPorts1 = 16; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_FORCED_PULSE; - // link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + /* FIXME: This driver should be updated to allow for dynamic IRQ sharing */ + /* link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_FORCED_PULSE; */ link->irq.Handler = pdacf_interrupt; link->conf.Attributes = CONF_ENABLE_IRQ; diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 5f1681f6ca766531d07270e82c1f81494f0d86a4..2a27f7b56726ab951219fd36289d595ba92fdad7 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -175,7 +175,7 @@ static int twl4030_write(struct snd_soc_codec *codec, { twl4030_write_reg_cache(codec, reg, value); if (likely(reg < TWL4030_REG_SW_SHADOW)) - return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, + return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); else return 0; @@ -261,7 +261,7 @@ static void twl4030_power_up(struct snd_soc_codec *codec) do { /* this takes a little while, so don't slam i2c */ udelay(2000); - twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, + twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, TWL4030_REG_ANAMICL); } while ((i++ < 100) && ((byte & TWL4030_CNCL_OFFSET_START) == @@ -542,7 +542,7 @@ static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \ break; \ case SND_SOC_DAPM_POST_PMD: \ reg_val = twl4030_read_reg_cache(w->codec, reg); \ - twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \ + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \ reg_val & (~mask), \ reg); \ break; \ @@ -679,7 +679,7 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / twl4030->sysclk) + 1); /* Bypass the reg_cache to mute the headset */ - twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, hs_gain & (~0x0f), TWL4030_REG_HS_GAIN_SET); diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index f82125d9e85a750e0aefd4d9d3ed7db9f7e30ecb..ebbf11b653a4f3042708ae966c952e6ca46545da 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -1340,9 +1340,10 @@ static int wm8350_resume(struct platform_device *pdev) return 0; } -static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) +static irqreturn_t wm8350_hp_jack_handler(int irq, void *data) { struct wm8350_data *priv = data; + struct wm8350 *wm8350 = priv->codec.control_data; u16 reg; int report; int mask; @@ -1365,7 +1366,7 @@ static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) if (!jack->jack) { dev_warn(wm8350->dev, "Jack interrupt called with no jack\n"); - return; + return IRQ_NONE; } /* Debounce */ @@ -1378,6 +1379,8 @@ static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) report = 0; snd_soc_jack_report(jack->jack, report, jack->report); + + return IRQ_HANDLED; } /** @@ -1421,9 +1424,7 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena); /* Sync status */ - wm8350_hp_jack_handler(wm8350, irq, priv); - - wm8350_unmask_irq(wm8350, irq); + wm8350_hp_jack_handler(irq, priv); return 0; } @@ -1482,12 +1483,16 @@ static int wm8350_probe(struct platform_device *pdev) wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, WM8350_OUT2_VU | WM8350_OUT2R_MUTE); - wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); - wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); + /* Make sure jack detect is disabled to start off with */ + wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, + WM8350_JDL_ENA | WM8350_JDR_ENA); + wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, - wm8350_hp_jack_handler, priv); + wm8350_hp_jack_handler, 0, "Left jack detect", + priv); wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, - wm8350_hp_jack_handler, priv); + wm8350_hp_jack_handler, 0, "Right jack detect", + priv); ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { @@ -1516,8 +1521,6 @@ static int wm8350_remove(struct platform_device *pdev) WM8350_JDL_ENA | WM8350_JDR_ENA); wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); - wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); - wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index d49458a29bb71f415dc0c53201841a41bcbc726b..3db8a6c523f466e0bf491a82a99853bbd2be784a 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile @@ -23,9 +23,9 @@ obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o -obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o -obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o -obj-$(CONFIG_MACH_OMAP3517EVM) += snd-soc-am3517evm.o +obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o +obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o +obj-$(CONFIG_SND_OMAP_SOC_OMAP3517EVM) += snd-soc-am3517evm.o obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt index 44b0ce35c28a4b0c37095c3392d9326f08354ea3..eac4d852e7cdc8074d2c885c27744a99c147d9ec 100644 --- a/tools/perf/Documentation/perf-kmem.txt +++ b/tools/perf/Documentation/perf-kmem.txt @@ -8,16 +8,16 @@ perf-kmem - Tool to trace/measure kernel memory(slab) properties SYNOPSIS -------- [verse] -'perf kmem' {record} [] +'perf kmem' {record|stat} [] DESCRIPTION ----------- -There's two variants of perf kmem: +There are two variants of perf kmem: 'perf kmem record ' to record the kmem events of an arbitrary workload. - 'perf kmem' to report kernel memory statistics. + 'perf kmem stat' to report kernel memory statistics. OPTIONS ------- @@ -25,8 +25,11 @@ OPTIONS --input=:: Select the input file (default: perf.data) ---stat=:: - Select per callsite or per allocation statistics +--caller:: + Show per-callsite statistics + +--alloc:: + Show per-allocation statistics -s :: --sort=:: diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 9270594e6dfd6d0d8a16549ae80bc8082719ed47..8fa6bf99fcb570c334424627df4021671e2e1d97 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt @@ -8,10 +8,13 @@ perf-probe - Define new dynamic tracepoints SYNOPSIS -------- [verse] -'perf probe' [options] --add 'PROBE' [--add 'PROBE' ...] +'perf probe' [options] --add='PROBE' [...] or -'perf probe' [options] 'PROBE' ['PROBE' ...] - +'perf probe' [options] PROBE +or +'perf probe' [options] --del='[GROUP:]EVENT' [...] +or +'perf probe' --list DESCRIPTION ----------- @@ -31,8 +34,16 @@ OPTIONS Be more verbose (show parsed arguments, etc). -a:: ---add:: - Define a probe point (see PROBE SYNTAX for detail) +--add=:: + Define a probe event (see PROBE SYNTAX for detail). + +-d:: +--del=:: + Delete a probe event. + +-l:: +--list:: + List up current probe events. PROBE SYNTAX ------------ diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 23ec66098bdc45c6c81ca9559fd16dc46f3b5ffb..406999668cab5b4538317898cd5ebf1c21718109 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -237,8 +237,8 @@ lib = lib export prefix bindir sharedir sysconfdir -CC = gcc -AR = ar +CC = $(CROSS_COMPILE)gcc +AR = $(CROSS_COMPILE)ar RM = rm -f TAR = tar FIND = find @@ -356,7 +356,9 @@ LIB_H += util/parse-options.h LIB_H += util/parse-events.h LIB_H += util/quote.h LIB_H += util/util.h +LIB_H += util/header.h LIB_H += util/help.h +LIB_H += util/session.h LIB_H += util/strbuf.h LIB_H += util/string.h LIB_H += util/strlist.h @@ -405,6 +407,7 @@ LIB_OBJS += util/callchain.o LIB_OBJS += util/values.o LIB_OBJS += util/debug.o LIB_OBJS += util/map.o +LIB_OBJS += util/session.o LIB_OBJS += util/thread.o LIB_OBJS += util/trace-event-parse.o LIB_OBJS += util/trace-event-read.o @@ -492,8 +495,10 @@ else LIB_OBJS += util/probe-finder.o endif +ifndef NO_LIBPERL PERL_EMBED_LDOPTS = `perl -MExtUtils::Embed -e ldopts 2>/dev/null` PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` +endif ifneq ($(shell sh -c "(echo '\#include '; echo '\#include '; echo 'int main(void) { perl_alloc(); return 0; }') | $(CC) -x c - $(PERL_EMBED_CCOPTS) -o /dev/null $(PERL_EMBED_LDOPTS) > /dev/null 2>&1 && echo y"), y) BASIC_CFLAGS += -DNO_LIBPERL diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c index 605a2a959aa839e11e846e88fe47f91bb22d01e0..81cee78181fa28fd2f382144c061e409c439fb3f 100644 --- a/tools/perf/bench/sched-messaging.c +++ b/tools/perf/bench/sched-messaging.c @@ -1,6 +1,6 @@ /* * - * builtin-bench-messaging.c + * sched-messaging.c * * messaging: Benchmark for scheduler and IPC mechanisms * @@ -320,10 +320,12 @@ int bench_sched_messaging(int argc, const char **argv, num_groups, num_groups * 2 * num_fds, thread_mode ? "threads" : "processes"); printf(" %14s: %lu.%03lu [sec]\n", "Total time", - diff.tv_sec, diff.tv_usec/1000); + diff.tv_sec, + (unsigned long) (diff.tv_usec/1000)); break; case BENCH_FORMAT_SIMPLE: - printf("%lu.%03lu\n", diff.tv_sec, diff.tv_usec/1000); + printf("%lu.%03lu\n", diff.tv_sec, + (unsigned long) (diff.tv_usec/1000)); break; default: /* reaching here is something disaster */ diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c index 238185f97977f1d86270cd1ce50d8ab2d9b046ac..4f77c7c27640791e357a130d71639d688c892641 100644 --- a/tools/perf/bench/sched-pipe.c +++ b/tools/perf/bench/sched-pipe.c @@ -1,6 +1,6 @@ /* * - * builtin-bench-pipe.c + * sched-pipe.c * * pipe: Benchmark for pipe() * @@ -87,7 +87,8 @@ int bench_sched_pipe(int argc, const char **argv, if (pid) { retpid = waitpid(pid, &wait_stat, 0); assert((retpid == pid) && WIFEXITED(wait_stat)); - return 0; + } else { + exit(0); } switch (bench_format) { @@ -99,7 +100,8 @@ int bench_sched_pipe(int argc, const char **argv, result_usec += diff.tv_usec; printf(" %14s: %lu.%03lu [sec]\n\n", "Total time", - diff.tv_sec, diff.tv_usec/1000); + diff.tv_sec, + (unsigned long) (diff.tv_usec/1000)); printf(" %14lf usecs/op\n", (double)result_usec / (double)loops); @@ -110,7 +112,8 @@ int bench_sched_pipe(int argc, const char **argv, case BENCH_FORMAT_SIMPLE: printf("%lu.%03lu\n", - diff.tv_sec, diff.tv_usec / 1000); + diff.tv_sec, + (unsigned long) (diff.tv_usec / 1000)); break; default: diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 0bf2e8f9af5776538237fa7e842c33e070b4dbe0..21a78d30d53dcf584a27ede521b34ddeb53118a3 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -25,6 +25,7 @@ #include "util/thread.h" #include "util/sort.h" #include "util/hist.h" +#include "util/session.h" #include "util/data_map.h" static char const *input_name = "perf.data"; @@ -462,21 +463,23 @@ static struct perf_file_handler file_handler = { static int __cmd_annotate(void) { - struct perf_header *header; + struct perf_session *session = perf_session__new(input_name, O_RDONLY, force); struct thread *idle; int ret; + if (session == NULL) + return -ENOMEM; + idle = register_idle_thread(); register_perf_file_handler(&file_handler); - ret = mmap_dispatch_perf_file(&header, input_name, 0, 0, - &event__cwdlen, &event__cwd); + ret = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd); if (ret) - return ret; + goto out_delete; if (dump_trace) { event__print_totals(); - return 0; + goto out_delete; } if (verbose > 3) @@ -489,6 +492,8 @@ static int __cmd_annotate(void) output__resort(event__total[0]); find_annotations(); +out_delete: + perf_session__delete(session); return ret; } diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c index e043eb83092aa3576a89016f70e8698e36c97e49..46996774e55967dc1351f9bf731ebc2f0c36cc59 100644 --- a/tools/perf/builtin-bench.c +++ b/tools/perf/builtin-bench.c @@ -31,6 +31,9 @@ struct bench_suite { const char *summary; int (*fn)(int, const char **, const char *); }; + \ +/* sentinel: easy for help */ +#define suite_all { "all", "test all suite (pseudo suite)", NULL } static struct bench_suite sched_suites[] = { { "messaging", @@ -39,6 +42,7 @@ static struct bench_suite sched_suites[] = { { "pipe", "Flood of communication over pipe() between two processes", bench_sched_pipe }, + suite_all, { NULL, NULL, NULL } @@ -48,6 +52,7 @@ static struct bench_suite mem_suites[] = { { "memcpy", "Simple memory copy in various ways", bench_mem_memcpy }, + suite_all, { NULL, NULL, NULL } @@ -66,6 +71,9 @@ static struct bench_subsys subsystems[] = { { "mem", "memory access performance", mem_suites }, + { "all", /* sentinel: easy for help */ + "test all subsystem (pseudo subsystem)", + NULL }, { NULL, NULL, NULL } @@ -75,11 +83,11 @@ static void dump_suites(int subsys_index) { int i; - printf("List of available suites for %s...\n\n", + printf("# List of available suites for %s...\n\n", subsystems[subsys_index].name); for (i = 0; subsystems[subsys_index].suites[i].name; i++) - printf("\t%s: %s\n", + printf("%14s: %s\n", subsystems[subsys_index].suites[i].name, subsystems[subsys_index].suites[i].summary); @@ -110,10 +118,10 @@ static void print_usage(void) printf("\t%s\n", bench_usage[i]); printf("\n"); - printf("List of available subsystems...\n\n"); + printf("# List of available subsystems...\n\n"); for (i = 0; subsystems[i].name; i++) - printf("\t%s: %s\n", + printf("%14s: %s\n", subsystems[i].name, subsystems[i].summary); printf("\n"); } @@ -131,6 +139,37 @@ static int bench_str2int(char *str) return BENCH_FORMAT_UNKNOWN; } +static void all_suite(struct bench_subsys *subsys) /* FROM HERE */ +{ + int i; + const char *argv[2]; + struct bench_suite *suites = subsys->suites; + + argv[1] = NULL; + /* + * TODO: + * preparing preset parameters for + * embedded, ordinary PC, HPC, etc... + * will be helpful + */ + for (i = 0; suites[i].fn; i++) { + printf("# Running %s/%s benchmark...\n", + subsys->name, + suites[i].name); + + argv[1] = suites[i].name; + suites[i].fn(1, argv, NULL); + printf("\n"); + } +} + +static void all_subsystem(void) +{ + int i; + for (i = 0; subsystems[i].suites; i++) + all_suite(&subsystems[i]); +} + int cmd_bench(int argc, const char **argv, const char *prefix __used) { int i, j, status = 0; @@ -155,6 +194,11 @@ int cmd_bench(int argc, const char **argv, const char *prefix __used) goto end; } + if (!strcmp(argv[0], "all")) { + all_subsystem(); + goto end; + } + for (i = 0; subsystems[i].name; i++) { if (strcmp(subsystems[i].name, argv[0])) continue; @@ -165,6 +209,11 @@ int cmd_bench(int argc, const char **argv, const char *prefix __used) goto end; } + if (!strcmp(argv[1], "all")) { + all_suite(&subsystems[i]); + goto end; + } + for (j = 0; subsystems[i].suites[j].name; j++) { if (strcmp(subsystems[i].suites[j].name, argv[1])) continue; diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index 7dee9d19ab7a8036494373fb71e2258f6c225fa1..bfd16a1594e4abbcca6d0970eb6bc14571c75c6b 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c @@ -11,15 +11,15 @@ #include "util/cache.h" #include "util/data_map.h" #include "util/debug.h" -#include "util/header.h" #include "util/parse-options.h" +#include "util/session.h" #include "util/symbol.h" static char const *input_name = "perf.data"; static int force; static const char *const buildid_list_usage[] = { - "perf report []", + "perf buildid-list []", NULL }; @@ -55,56 +55,17 @@ static int perf_file_section__process_buildids(struct perf_file_section *self, static int __cmd_buildid_list(void) { int err = -1; - struct perf_header *header; - struct perf_file_header f_header; - struct stat input_stat; - int input = open(input_name, O_RDONLY); + struct perf_session *session = perf_session__new(input_name, O_RDONLY, force); - if (input < 0) { - pr_err("failed to open file: %s", input_name); - if (!strcmp(input_name, "perf.data")) - pr_err(" (try 'perf record' first)"); - pr_err("\n"); - goto out; - } - - err = fstat(input, &input_stat); - if (err < 0) { - perror("failed to stat file"); - goto out_close; - } - - if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { - pr_err("file %s not owned by current user or root\n", - input_name); - goto out_close; - } - - if (!input_stat.st_size) { - pr_info("zero-sized file, nothing to do!\n"); - goto out_close; - } - - err = -1; - header = perf_header__new(); - if (header == NULL) - goto out_close; - - if (perf_file_header__read(&f_header, header, input) < 0) { - pr_warning("incompatible file format"); - goto out_close; - } + if (session == NULL) + return -1; - err = perf_header__process_sections(header, input, + err = perf_header__process_sections(&session->header, session->fd, perf_file_section__process_buildids); + if (err >= 0) + dsos__fprintf_buildid(stdout); - if (err < 0) - goto out_close; - - dsos__fprintf_buildid(stdout); -out_close: - close(input); -out: + perf_session__delete(session); return err; } diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 047fef74bd5276425360dd5e2c3d22cf9d27984a..2071d248591334f8acfe97802ab12e33b3bbbe30 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -6,6 +6,7 @@ #include "util/symbol.h" #include "util/thread.h" #include "util/header.h" +#include "util/session.h" #include "util/parse-options.h" #include "util/trace-event.h" @@ -20,7 +21,6 @@ typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); static char const *input_name = "perf.data"; -static struct perf_header *header; static u64 sample_type; static int alloc_flag; @@ -57,11 +57,6 @@ static struct rb_root root_caller_sorted; static unsigned long total_requested, total_allocated; static unsigned long nr_allocs, nr_cross_allocs; -struct raw_event_sample { - u32 size; - char data[0]; -}; - #define PATH_SYS_NODE "/sys/devices/system/node" static void init_cpunode_map(void) @@ -201,7 +196,7 @@ static void insert_caller_stat(unsigned long call_site, } } -static void process_alloc_event(struct raw_event_sample *raw, +static void process_alloc_event(void *data, struct event *event, int cpu, u64 timestamp __used, @@ -214,10 +209,10 @@ static void process_alloc_event(struct raw_event_sample *raw, int bytes_alloc; int node1, node2; - ptr = raw_field_value(event, "ptr", raw->data); - call_site = raw_field_value(event, "call_site", raw->data); - bytes_req = raw_field_value(event, "bytes_req", raw->data); - bytes_alloc = raw_field_value(event, "bytes_alloc", raw->data); + ptr = raw_field_value(event, "ptr", data); + call_site = raw_field_value(event, "call_site", data); + bytes_req = raw_field_value(event, "bytes_req", data); + bytes_alloc = raw_field_value(event, "bytes_alloc", data); insert_alloc_stat(call_site, ptr, bytes_req, bytes_alloc, cpu); insert_caller_stat(call_site, bytes_req, bytes_alloc); @@ -227,7 +222,7 @@ static void process_alloc_event(struct raw_event_sample *raw, if (node) { node1 = cpunode_map[cpu]; - node2 = raw_field_value(event, "node", raw->data); + node2 = raw_field_value(event, "node", data); if (node1 != node2) nr_cross_allocs++; } @@ -262,7 +257,7 @@ static struct alloc_stat *search_alloc_stat(unsigned long ptr, return NULL; } -static void process_free_event(struct raw_event_sample *raw, +static void process_free_event(void *data, struct event *event, int cpu, u64 timestamp __used, @@ -271,7 +266,7 @@ static void process_free_event(struct raw_event_sample *raw, unsigned long ptr; struct alloc_stat *s_alloc, *s_caller; - ptr = raw_field_value(event, "ptr", raw->data); + ptr = raw_field_value(event, "ptr", data); s_alloc = search_alloc_stat(ptr, 0, &root_alloc_stat, ptr_cmp); if (!s_alloc) @@ -289,66 +284,53 @@ static void process_free_event(struct raw_event_sample *raw, } static void -process_raw_event(event_t *raw_event __used, void *more_data, +process_raw_event(event_t *raw_event __used, void *data, int cpu, u64 timestamp, struct thread *thread) { - struct raw_event_sample *raw = more_data; struct event *event; int type; - type = trace_parse_common_type(raw->data); + type = trace_parse_common_type(data); event = trace_find_event(type); if (!strcmp(event->name, "kmalloc") || !strcmp(event->name, "kmem_cache_alloc")) { - process_alloc_event(raw, event, cpu, timestamp, thread, 0); + process_alloc_event(data, event, cpu, timestamp, thread, 0); return; } if (!strcmp(event->name, "kmalloc_node") || !strcmp(event->name, "kmem_cache_alloc_node")) { - process_alloc_event(raw, event, cpu, timestamp, thread, 1); + process_alloc_event(data, event, cpu, timestamp, thread, 1); return; } if (!strcmp(event->name, "kfree") || !strcmp(event->name, "kmem_cache_free")) { - process_free_event(raw, event, cpu, timestamp, thread); + process_free_event(data, event, cpu, timestamp, thread); return; } } static int process_sample_event(event_t *event) { - u64 ip = event->ip.ip; - u64 timestamp = -1; - u32 cpu = -1; - u64 period = 1; - void *more_data = event->ip.__more_data; - struct thread *thread = threads__findnew(event->ip.pid); - - if (sample_type & PERF_SAMPLE_TIME) { - timestamp = *(u64 *)more_data; - more_data += sizeof(u64); - } + struct sample_data data; + struct thread *thread; - if (sample_type & PERF_SAMPLE_CPU) { - cpu = *(u32 *)more_data; - more_data += sizeof(u32); - more_data += sizeof(u32); /* reserved */ - } + memset(&data, 0, sizeof(data)); + data.time = -1; + data.cpu = -1; + data.period = 1; - if (sample_type & PERF_SAMPLE_PERIOD) { - period = *(u64 *)more_data; - more_data += sizeof(u64); - } + event__parse_sample(event, sample_type, &data); dump_printf("(IP, %d): %d/%d: %p period: %Ld\n", event->header.misc, - event->ip.pid, event->ip.tid, - (void *)(long)ip, - (long long)period); + data.pid, data.tid, + (void *)(long)data.ip, + (long long)data.period); + thread = threads__findnew(event->ip.pid); if (thread == NULL) { pr_debug("problem processing %d event, skipping it.\n", event->header.type); @@ -357,7 +339,8 @@ static int process_sample_event(event_t *event) dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); - process_raw_event(event, more_data, cpu, timestamp, thread); + process_raw_event(event, data.raw_data, data.cpu, + data.time, thread); return 0; } @@ -384,11 +367,18 @@ static struct perf_file_handler file_handler = { static int read_events(void) { + int err; + struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0); + + if (session == NULL) + return -ENOMEM; + register_idle_thread(); register_perf_file_handler(&file_handler); - return mmap_dispatch_perf_file(&header, input_name, 0, 0, - &event__cwdlen, &event__cwd); + err = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd); + perf_session__delete(session); + return err; } static double fragmentation(unsigned long n_req, unsigned long n_alloc) @@ -420,7 +410,7 @@ static void __print_result(struct rb_root *root, int n_lines, int is_caller) if (is_caller) { addr = data->call_site; if (!raw_ip) - sym = thread__find_function(kthread, addr, NULL); + sym = map_groups__find_function(kmaps, addr, NULL); } else addr = data->ptr; @@ -543,7 +533,7 @@ static int __cmd_kmem(void) } static const char * const kmem_usage[] = { - "perf kmem [] {record}", + "perf kmem [] {record|stat}", NULL }; @@ -703,18 +693,17 @@ static int parse_sort_opt(const struct option *opt __used, return 0; } -static int parse_stat_opt(const struct option *opt __used, - const char *arg, int unset __used) +static int parse_caller_opt(const struct option *opt __used, + const char *arg __used, int unset __used) { - if (!arg) - return -1; + caller_flag = (alloc_flag + 1); + return 0; +} - if (strcmp(arg, "alloc") == 0) - alloc_flag = (caller_flag + 1); - else if (strcmp(arg, "caller") == 0) - caller_flag = (alloc_flag + 1); - else - return -1; +static int parse_alloc_opt(const struct option *opt __used, + const char *arg __used, int unset __used) +{ + alloc_flag = (caller_flag + 1); return 0; } @@ -739,14 +728,17 @@ static int parse_line_opt(const struct option *opt __used, static const struct option kmem_options[] = { OPT_STRING('i', "input", &input_name, "file", "input file name"), - OPT_CALLBACK(0, "stat", NULL, "|", - "stat selector, Pass 'alloc' or 'caller'.", - parse_stat_opt), + OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL, + "show per-callsite statistics", + parse_caller_opt), + OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL, + "show per-allocation statistics", + parse_alloc_opt), OPT_CALLBACK('s', "sort", NULL, "key[,key2...]", "sort by keys: ptr, call_site, bytes, hit, pingpong, frag", parse_sort_opt), OPT_CALLBACK('l', "line", NULL, "num", - "show n lins", + "show n lines", parse_line_opt), OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"), OPT_END() @@ -790,18 +782,22 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __used) argc = parse_options(argc, argv, kmem_options, kmem_usage, 0); - if (argc && !strncmp(argv[0], "rec", 3)) - return __cmd_record(argc, argv); - else if (argc) + if (!argc) usage_with_options(kmem_usage, kmem_options); - if (list_empty(&caller_sort)) - setup_sorting(&caller_sort, default_sort_order); - if (list_empty(&alloc_sort)) - setup_sorting(&alloc_sort, default_sort_order); + if (!strncmp(argv[0], "rec", 3)) { + return __cmd_record(argc, argv); + } else if (!strcmp(argv[0], "stat")) { + setup_cpunode_map(); - setup_cpunode_map(); + if (list_empty(&caller_sort)) + setup_sorting(&caller_sort, default_sort_order); + if (list_empty(&alloc_sort)) + setup_sorting(&alloc_sort, default_sort_order); - return __cmd_kmem(); + return __cmd_kmem(); + } + + return 0; } diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index a58e11b7ea8000de71659a93f093d5d2dcddcb73..5a47c1e11f77738b6f770f8e3b67f7a085a0362a 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -35,6 +35,7 @@ #include "perf.h" #include "builtin.h" #include "util/util.h" +#include "util/strlist.h" #include "util/event.h" #include "util/debug.h" #include "util/parse-options.h" @@ -43,11 +44,12 @@ #include "util/probe-event.h" /* Default vmlinux search paths */ -#define NR_SEARCH_PATH 3 +#define NR_SEARCH_PATH 4 const char *default_search_path[NR_SEARCH_PATH] = { "/lib/modules/%s/build/vmlinux", /* Custom build kernel */ "/usr/lib/debug/lib/modules/%s/vmlinux", /* Red Hat debuginfo */ "/boot/vmlinux-debug-%s", /* Ubuntu */ +"./vmlinux", /* CWD */ }; #define MAX_PATH_LEN 256 @@ -60,6 +62,7 @@ static struct { int need_dwarf; int nr_probe; struct probe_point probes[MAX_PROBES]; + struct strlist *dellist; } session; static bool listing; @@ -79,6 +82,25 @@ static void parse_probe_event(const char *str) pr_debug("%d arguments\n", pp->nr_args); } +static void parse_probe_event_argv(int argc, const char **argv) +{ + int i, len; + char *buf; + + /* Bind up rest arguments */ + len = 0; + for (i = 0; i < argc; i++) + len += strlen(argv[i]) + 1; + buf = zalloc(len + 1); + if (!buf) + die("Failed to allocate memory for binding arguments."); + len = 0; + for (i = 0; i < argc; i++) + len += sprintf(&buf[len], "%s ", argv[i]); + parse_probe_event(buf); + free(buf); +} + static int opt_add_probe_event(const struct option *opt __used, const char *str, int unset __used) { @@ -87,6 +109,17 @@ static int opt_add_probe_event(const struct option *opt __used, return 0; } +static int opt_del_probe_event(const struct option *opt __used, + const char *str, int unset __used) +{ + if (str) { + if (!session.dellist) + session.dellist = strlist__new(true, NULL); + strlist__add(session.dellist, str); + } + return 0; +} + #ifndef NO_LIBDWARF static int open_default_vmlinux(void) { @@ -121,6 +154,7 @@ static int open_default_vmlinux(void) static const char * const probe_usage[] = { "perf probe [] 'PROBEDEF' ['PROBEDEF' ...]", "perf probe [] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", + "perf probe [] --del '[GROUP:]EVENT' ...", "perf probe --list", NULL }; @@ -132,7 +166,9 @@ static const struct option options[] = { OPT_STRING('k', "vmlinux", &session.vmlinux, "file", "vmlinux/module pathname"), #endif - OPT_BOOLEAN('l', "list", &listing, "list up current probes"), + OPT_BOOLEAN('l', "list", &listing, "list up current probe events"), + OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", + opt_del_probe_event), OPT_CALLBACK('a', "add", NULL, #ifdef NO_LIBDWARF "FUNC[+OFFS|%return] [ARG ...]", @@ -160,7 +196,7 @@ static const struct option options[] = { int cmd_probe(int argc, const char **argv, const char *prefix __used) { - int i, j, ret; + int i, ret; #ifndef NO_LIBDWARF int fd; #endif @@ -168,40 +204,52 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) argc = parse_options(argc, argv, options, probe_usage, PARSE_OPT_STOP_AT_NON_OPTION); - for (i = 0; i < argc; i++) - parse_probe_event(argv[i]); + if (argc > 0) + parse_probe_event_argv(argc, argv); - if ((session.nr_probe == 0 && !listing) || - (session.nr_probe != 0 && listing)) + if ((session.nr_probe == 0 && !session.dellist && !listing)) usage_with_options(probe_usage, options); if (listing) { + if (session.nr_probe != 0 || session.dellist) { + pr_warning(" Error: Don't use --list with" + " --add/--del.\n"); + usage_with_options(probe_usage, options); + } show_perf_probe_events(); return 0; } + if (session.dellist) { + del_trace_kprobe_events(session.dellist); + strlist__delete(session.dellist); + if (session.nr_probe == 0) + return 0; + } + if (session.need_dwarf) #ifdef NO_LIBDWARF die("Debuginfo-analysis is not supported"); #else /* !NO_LIBDWARF */ pr_debug("Some probes require debuginfo.\n"); - if (session.vmlinux) + if (session.vmlinux) { + pr_debug("Try to open %s.", session.vmlinux); fd = open(session.vmlinux, O_RDONLY); - else + } else fd = open_default_vmlinux(); if (fd < 0) { if (session.need_dwarf) - die("Could not open vmlinux/module file."); + die("Could not open debuginfo file."); - pr_warning("Could not open vmlinux/module file." - " Try to use symbols.\n"); + pr_debug("Could not open vmlinux/module file." + " Try to use symbols.\n"); goto end_dwarf; } /* Searching probe points */ - for (j = 0; j < session.nr_probe; j++) { - pp = &session.probes[j]; + for (i = 0; i < session.nr_probe; i++) { + pp = &session.probes[i]; if (pp->found) continue; @@ -223,8 +271,8 @@ end_dwarf: #endif /* !NO_LIBDWARF */ /* Synthesize probes without dwarf */ - for (j = 0; j < session.nr_probe; j++) { - pp = &session.probes[j]; + for (i = 0; i < session.nr_probe; i++) { + pp = &session.probes[i]; if (pp->found) /* This probe is already found. */ continue; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 0e519c667e3ac47f8fe9576575f62dc7b1991d83..4decbd14eaed080ac046b8a10c793b721280c1df 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -17,6 +17,7 @@ #include "util/header.h" #include "util/event.h" #include "util/debug.h" +#include "util/session.h" #include "util/symbol.h" #include @@ -62,7 +63,7 @@ static int nr_cpu = 0; static int file_new = 1; -struct perf_header *header = NULL; +static struct perf_session *session; struct mmap_data { int counter; @@ -216,12 +217,12 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n { struct perf_header_attr *h_attr; - if (nr < header->attrs) { - h_attr = header->attr[nr]; + if (nr < session->header.attrs) { + h_attr = session->header.attr[nr]; } else { h_attr = perf_header_attr__new(a); if (h_attr != NULL) - if (perf_header__add_attr(header, h_attr) < 0) { + if (perf_header__add_attr(&session->header, h_attr) < 0) { perf_header_attr__delete(h_attr); h_attr = NULL; } @@ -395,9 +396,9 @@ static void open_counters(int cpu, pid_t pid) static void atexit_header(void) { - header->data_size += bytes_written; + session->header.data_size += bytes_written; - perf_header__write(header, output, true); + perf_header__write(&session->header, output, true); } static int __cmd_record(int argc, const char **argv) @@ -440,24 +441,24 @@ static int __cmd_record(int argc, const char **argv) exit(-1); } - header = perf_header__new(); - if (header == NULL) { + session = perf_session__new(output_name, O_WRONLY, force); + if (session == NULL) { pr_err("Not enough memory for reading perf file header\n"); return -1; } if (!file_new) { - err = perf_header__read(header, output); + err = perf_header__read(&session->header, output); if (err < 0) return err; } if (raw_samples) { - perf_header__set_feat(header, HEADER_TRACE_INFO); + perf_header__set_feat(&session->header, HEADER_TRACE_INFO); } else { for (i = 0; i < nr_counters; i++) { if (attrs[i].sample_type & PERF_SAMPLE_RAW) { - perf_header__set_feat(header, HEADER_TRACE_INFO); + perf_header__set_feat(&session->header, HEADER_TRACE_INFO); break; } } @@ -481,7 +482,7 @@ static int __cmd_record(int argc, const char **argv) } if (file_new) { - err = perf_header__write(header, output, false); + err = perf_header__write(&session->header, output, false); if (err < 0) return err; } diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 383c4ab4f9af06e6cfaa0e6f6e358aa63e1d1d68..e2ec49a9b731eab6bb2de7419680107433b7b697 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -22,6 +22,7 @@ #include "perf.h" #include "util/debug.h" #include "util/header.h" +#include "util/session.h" #include "util/parse-options.h" #include "util/parse-events.h" @@ -52,7 +53,7 @@ static int exclude_other = 1; static char callchain_default_opt[] = "fractal,0.5"; -static struct perf_header *header; +static struct perf_session *session; static u64 sample_type; @@ -605,44 +606,41 @@ static int validate_chain(struct ip_callchain *chain, event_t *event) static int process_sample_event(event_t *event) { - u64 ip = event->ip.ip; - u64 period = 1; - void *more_data = event->ip.__more_data; - struct ip_callchain *chain = NULL; + struct sample_data data; int cpumode; struct addr_location al; - struct thread *thread = threads__findnew(event->ip.pid); + struct thread *thread; - if (sample_type & PERF_SAMPLE_PERIOD) { - period = *(u64 *)more_data; - more_data += sizeof(u64); - } + memset(&data, 0, sizeof(data)); + data.period = 1; + + event__parse_sample(event, sample_type, &data); dump_printf("(IP, %d): %d/%d: %p period: %Ld\n", event->header.misc, - event->ip.pid, event->ip.tid, - (void *)(long)ip, - (long long)period); + data.pid, data.tid, + (void *)(long)data.ip, + (long long)data.period); if (sample_type & PERF_SAMPLE_CALLCHAIN) { unsigned int i; - chain = (void *)more_data; + dump_printf("... chain: nr:%Lu\n", data.callchain->nr); - dump_printf("... chain: nr:%Lu\n", chain->nr); - - if (validate_chain(chain, event) < 0) { + if (validate_chain(data.callchain, event) < 0) { pr_debug("call-chain problem with event, " "skipping it.\n"); return 0; } if (dump_trace) { - for (i = 0; i < chain->nr; i++) - dump_printf("..... %2d: %016Lx\n", i, chain->ips[i]); + for (i = 0; i < data.callchain->nr; i++) + dump_printf("..... %2d: %016Lx\n", + i, data.callchain->ips[i]); } } + thread = threads__findnew(data.pid); if (thread == NULL) { pr_debug("problem processing %d event, skipping it.\n", event->header.type); @@ -657,7 +655,7 @@ static int process_sample_event(event_t *event) cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; thread__find_addr_location(thread, cpumode, - MAP__FUNCTION, ip, &al, NULL); + MAP__FUNCTION, data.ip, &al, NULL); /* * We have to do this here as we may have a dso with no symbol hit that * has a name longer than the ones with symbols sampled. @@ -675,12 +673,12 @@ static int process_sample_event(event_t *event) if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name)) return 0; - if (hist_entry__add(&al, chain, period)) { + if (hist_entry__add(&al, data.callchain, data.period)) { pr_debug("problem incrementing symbol count, skipping event\n"); return -1; } - event__stats.total += period; + event__stats.total += data.period; return 0; } @@ -704,7 +702,7 @@ static int process_read_event(event_t *event) { struct perf_event_attr *attr; - attr = perf_header__find_attr(event->read.id, header); + attr = perf_header__find_attr(event->read.id, &session->header); if (show_threads) { const char *name = attr ? __event_name(attr->type, attr->config) @@ -769,6 +767,10 @@ static int __cmd_report(void) struct thread *idle; int ret; + session = perf_session__new(input_name, O_RDONLY, force); + if (session == NULL) + return -ENOMEM; + idle = register_idle_thread(); thread__comm_adjust(idle); @@ -777,14 +779,14 @@ static int __cmd_report(void) register_perf_file_handler(&file_handler); - ret = mmap_dispatch_perf_file(&header, input_name, force, - full_paths, &event__cwdlen, &event__cwd); + ret = perf_session__process_events(session, full_paths, + &event__cwdlen, &event__cwd); if (ret) - return ret; + goto out_delete; if (dump_trace) { event__print_totals(); - return 0; + goto out_delete; } if (verbose > 3) @@ -799,7 +801,8 @@ static int __cmd_report(void) if (show_threads) perf_read_values_destroy(&show_threads_values); - +out_delete: + perf_session__delete(session); return ret; } diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 26b782f26ee1a97c35f8ce8445b07aa470a35806..65021fe1361e0ae712614fcf0d966d89fcb8789e 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -6,6 +6,7 @@ #include "util/symbol.h" #include "util/thread.h" #include "util/header.h" +#include "util/session.h" #include "util/parse-options.h" #include "util/trace-event.h" @@ -13,7 +14,6 @@ #include "util/debug.h" #include "util/data_map.h" -#include #include #include @@ -22,7 +22,6 @@ static char const *input_name = "perf.data"; -static struct perf_header *header; static u64 sample_type; static char default_sort_order[] = "avg, max, switch, runtime"; @@ -141,6 +140,7 @@ struct work_atoms { struct thread *thread; struct rb_node node; u64 max_lat; + u64 max_lat_at; u64 total_lat; u64 nb_atoms; u64 total_runtime; @@ -414,34 +414,33 @@ static u64 get_cpu_usage_nsec_parent(void) return sum; } -static u64 get_cpu_usage_nsec_self(void) +static int self_open_counters(void) { - char filename [] = "/proc/1234567890/sched"; - unsigned long msecs, nsecs; - char *line = NULL; - u64 total = 0; - size_t len = 0; - ssize_t chars; - FILE *file; - int ret; + struct perf_event_attr attr; + int fd; - sprintf(filename, "/proc/%d/sched", getpid()); - file = fopen(filename, "r"); - BUG_ON(!file); + memset(&attr, 0, sizeof(attr)); - while ((chars = getline(&line, &len, file)) != -1) { - ret = sscanf(line, "se.sum_exec_runtime : %ld.%06ld\n", - &msecs, &nsecs); - if (ret == 2) { - total = msecs*1e6 + nsecs; - break; - } - } - if (line) - free(line); - fclose(file); + attr.type = PERF_TYPE_SOFTWARE; + attr.config = PERF_COUNT_SW_TASK_CLOCK; + + fd = sys_perf_event_open(&attr, 0, -1, -1, 0); - return total; + if (fd < 0) + die("Error: sys_perf_event_open() syscall returned" + "with %d (%s)\n", fd, strerror(errno)); + return fd; +} + +static u64 get_cpu_usage_nsec_self(int fd) +{ + u64 runtime; + int ret; + + ret = read(fd, &runtime, sizeof(runtime)); + BUG_ON(ret != sizeof(runtime)); + + return runtime; } static void *thread_func(void *ctx) @@ -450,9 +449,11 @@ static void *thread_func(void *ctx) u64 cpu_usage_0, cpu_usage_1; unsigned long i, ret; char comm2[22]; + int fd; sprintf(comm2, ":%s", this_task->comm); prctl(PR_SET_NAME, comm2); + fd = self_open_counters(); again: ret = sem_post(&this_task->ready_for_work); @@ -462,16 +463,15 @@ again: ret = pthread_mutex_unlock(&start_work_mutex); BUG_ON(ret); - cpu_usage_0 = get_cpu_usage_nsec_self(); + cpu_usage_0 = get_cpu_usage_nsec_self(fd); for (i = 0; i < this_task->nr_events; i++) { this_task->curr_event = i; process_sched_event(this_task, this_task->atoms[i]); } - cpu_usage_1 = get_cpu_usage_nsec_self(); + cpu_usage_1 = get_cpu_usage_nsec_self(fd); this_task->cpu_usage = cpu_usage_1 - cpu_usage_0; - ret = sem_post(&this_task->work_done_sem); BUG_ON(ret); @@ -628,11 +628,6 @@ static void test_calibrations(void) printf("the sleep test took %Ld nsecs\n", T1-T0); } -struct raw_event_sample { - u32 size; - char data[0]; -}; - #define FILL_FIELD(ptr, field, event, data) \ ptr.field = (typeof(ptr.field)) raw_field_value(event, #field, data) @@ -1019,8 +1014,10 @@ add_sched_in_event(struct work_atoms *atoms, u64 timestamp) delta = atom->sched_in_time - atom->wake_up_time; atoms->total_lat += delta; - if (delta > atoms->max_lat) + if (delta > atoms->max_lat) { atoms->max_lat = delta; + atoms->max_lat_at = timestamp; + } atoms->nb_atoms++; } @@ -1216,10 +1213,11 @@ static void output_lat_thread(struct work_atoms *work_list) avg = work_list->total_lat / work_list->nb_atoms; - printf("|%11.3f ms |%9llu | avg:%9.3f ms | max:%9.3f ms |\n", + printf("|%11.3f ms |%9llu | avg:%9.3f ms | max:%9.3f ms | max at: %9.6f s\n", (double)work_list->total_runtime / 1e6, work_list->nb_atoms, (double)avg / 1e6, - (double)work_list->max_lat / 1e6); + (double)work_list->max_lat / 1e6, + (double)work_list->max_lat_at / 1e9); } static int pid_cmp(struct work_atoms *l, struct work_atoms *r) @@ -1356,7 +1354,7 @@ static void sort_lat(void) static struct trace_sched_handler *trace_handler; static void -process_sched_wakeup_event(struct raw_event_sample *raw, +process_sched_wakeup_event(void *data, struct event *event, int cpu __used, u64 timestamp __used, @@ -1364,13 +1362,13 @@ process_sched_wakeup_event(struct raw_event_sample *raw, { struct trace_wakeup_event wakeup_event; - FILL_COMMON_FIELDS(wakeup_event, event, raw->data); + FILL_COMMON_FIELDS(wakeup_event, event, data); - FILL_ARRAY(wakeup_event, comm, event, raw->data); - FILL_FIELD(wakeup_event, pid, event, raw->data); - FILL_FIELD(wakeup_event, prio, event, raw->data); - FILL_FIELD(wakeup_event, success, event, raw->data); - FILL_FIELD(wakeup_event, cpu, event, raw->data); + FILL_ARRAY(wakeup_event, comm, event, data); + FILL_FIELD(wakeup_event, pid, event, data); + FILL_FIELD(wakeup_event, prio, event, data); + FILL_FIELD(wakeup_event, success, event, data); + FILL_FIELD(wakeup_event, cpu, event, data); if (trace_handler->wakeup_event) trace_handler->wakeup_event(&wakeup_event, event, cpu, timestamp, thread); @@ -1469,7 +1467,7 @@ map_switch_event(struct trace_switch_event *switch_event, static void -process_sched_switch_event(struct raw_event_sample *raw, +process_sched_switch_event(void *data, struct event *event, int this_cpu, u64 timestamp __used, @@ -1477,15 +1475,15 @@ process_sched_switch_event(struct raw_event_sample *raw, { struct trace_switch_event switch_event; - FILL_COMMON_FIELDS(switch_event, event, raw->data); + FILL_COMMON_FIELDS(switch_event, event, data); - FILL_ARRAY(switch_event, prev_comm, event, raw->data); - FILL_FIELD(switch_event, prev_pid, event, raw->data); - FILL_FIELD(switch_event, prev_prio, event, raw->data); - FILL_FIELD(switch_event, prev_state, event, raw->data); - FILL_ARRAY(switch_event, next_comm, event, raw->data); - FILL_FIELD(switch_event, next_pid, event, raw->data); - FILL_FIELD(switch_event, next_prio, event, raw->data); + FILL_ARRAY(switch_event, prev_comm, event, data); + FILL_FIELD(switch_event, prev_pid, event, data); + FILL_FIELD(switch_event, prev_prio, event, data); + FILL_FIELD(switch_event, prev_state, event, data); + FILL_ARRAY(switch_event, next_comm, event, data); + FILL_FIELD(switch_event, next_pid, event, data); + FILL_FIELD(switch_event, next_prio, event, data); if (curr_pid[this_cpu] != (u32)-1) { /* @@ -1502,7 +1500,7 @@ process_sched_switch_event(struct raw_event_sample *raw, } static void -process_sched_runtime_event(struct raw_event_sample *raw, +process_sched_runtime_event(void *data, struct event *event, int cpu __used, u64 timestamp __used, @@ -1510,17 +1508,17 @@ process_sched_runtime_event(struct raw_event_sample *raw, { struct trace_runtime_event runtime_event; - FILL_ARRAY(runtime_event, comm, event, raw->data); - FILL_FIELD(runtime_event, pid, event, raw->data); - FILL_FIELD(runtime_event, runtime, event, raw->data); - FILL_FIELD(runtime_event, vruntime, event, raw->data); + FILL_ARRAY(runtime_event, comm, event, data); + FILL_FIELD(runtime_event, pid, event, data); + FILL_FIELD(runtime_event, runtime, event, data); + FILL_FIELD(runtime_event, vruntime, event, data); if (trace_handler->runtime_event) trace_handler->runtime_event(&runtime_event, event, cpu, timestamp, thread); } static void -process_sched_fork_event(struct raw_event_sample *raw, +process_sched_fork_event(void *data, struct event *event, int cpu __used, u64 timestamp __used, @@ -1528,12 +1526,12 @@ process_sched_fork_event(struct raw_event_sample *raw, { struct trace_fork_event fork_event; - FILL_COMMON_FIELDS(fork_event, event, raw->data); + FILL_COMMON_FIELDS(fork_event, event, data); - FILL_ARRAY(fork_event, parent_comm, event, raw->data); - FILL_FIELD(fork_event, parent_pid, event, raw->data); - FILL_ARRAY(fork_event, child_comm, event, raw->data); - FILL_FIELD(fork_event, child_pid, event, raw->data); + FILL_ARRAY(fork_event, parent_comm, event, data); + FILL_FIELD(fork_event, parent_pid, event, data); + FILL_ARRAY(fork_event, child_comm, event, data); + FILL_FIELD(fork_event, child_pid, event, data); if (trace_handler->fork_event) trace_handler->fork_event(&fork_event, event, cpu, timestamp, thread); @@ -1550,7 +1548,7 @@ process_sched_exit_event(struct event *event, } static void -process_sched_migrate_task_event(struct raw_event_sample *raw, +process_sched_migrate_task_event(void *data, struct event *event, int cpu __used, u64 timestamp __used, @@ -1558,80 +1556,66 @@ process_sched_migrate_task_event(struct raw_event_sample *raw, { struct trace_migrate_task_event migrate_task_event; - FILL_COMMON_FIELDS(migrate_task_event, event, raw->data); + FILL_COMMON_FIELDS(migrate_task_event, event, data); - FILL_ARRAY(migrate_task_event, comm, event, raw->data); - FILL_FIELD(migrate_task_event, pid, event, raw->data); - FILL_FIELD(migrate_task_event, prio, event, raw->data); - FILL_FIELD(migrate_task_event, cpu, event, raw->data); + FILL_ARRAY(migrate_task_event, comm, event, data); + FILL_FIELD(migrate_task_event, pid, event, data); + FILL_FIELD(migrate_task_event, prio, event, data); + FILL_FIELD(migrate_task_event, cpu, event, data); if (trace_handler->migrate_task_event) trace_handler->migrate_task_event(&migrate_task_event, event, cpu, timestamp, thread); } static void -process_raw_event(event_t *raw_event __used, void *more_data, +process_raw_event(event_t *raw_event __used, void *data, int cpu, u64 timestamp, struct thread *thread) { - struct raw_event_sample *raw = more_data; struct event *event; int type; - type = trace_parse_common_type(raw->data); + + type = trace_parse_common_type(data); event = trace_find_event(type); if (!strcmp(event->name, "sched_switch")) - process_sched_switch_event(raw, event, cpu, timestamp, thread); + process_sched_switch_event(data, event, cpu, timestamp, thread); if (!strcmp(event->name, "sched_stat_runtime")) - process_sched_runtime_event(raw, event, cpu, timestamp, thread); + process_sched_runtime_event(data, event, cpu, timestamp, thread); if (!strcmp(event->name, "sched_wakeup")) - process_sched_wakeup_event(raw, event, cpu, timestamp, thread); + process_sched_wakeup_event(data, event, cpu, timestamp, thread); if (!strcmp(event->name, "sched_wakeup_new")) - process_sched_wakeup_event(raw, event, cpu, timestamp, thread); + process_sched_wakeup_event(data, event, cpu, timestamp, thread); if (!strcmp(event->name, "sched_process_fork")) - process_sched_fork_event(raw, event, cpu, timestamp, thread); + process_sched_fork_event(data, event, cpu, timestamp, thread); if (!strcmp(event->name, "sched_process_exit")) process_sched_exit_event(event, cpu, timestamp, thread); if (!strcmp(event->name, "sched_migrate_task")) - process_sched_migrate_task_event(raw, event, cpu, timestamp, thread); + process_sched_migrate_task_event(data, event, cpu, timestamp, thread); } static int process_sample_event(event_t *event) { + struct sample_data data; struct thread *thread; - u64 ip = event->ip.ip; - u64 timestamp = -1; - u32 cpu = -1; - u64 period = 1; - void *more_data = event->ip.__more_data; if (!(sample_type & PERF_SAMPLE_RAW)) return 0; - thread = threads__findnew(event->ip.pid); + memset(&data, 0, sizeof(data)); + data.time = -1; + data.cpu = -1; + data.period = -1; - if (sample_type & PERF_SAMPLE_TIME) { - timestamp = *(u64 *)more_data; - more_data += sizeof(u64); - } - - if (sample_type & PERF_SAMPLE_CPU) { - cpu = *(u32 *)more_data; - more_data += sizeof(u32); - more_data += sizeof(u32); /* reserved */ - } - - if (sample_type & PERF_SAMPLE_PERIOD) { - period = *(u64 *)more_data; - more_data += sizeof(u64); - } + event__parse_sample(event, sample_type, &data); dump_printf("(IP, %d): %d/%d: %p period: %Ld\n", event->header.misc, - event->ip.pid, event->ip.tid, - (void *)(long)ip, - (long long)period); + data.pid, data.tid, + (void *)(long)data.ip, + (long long)data.period); + thread = threads__findnew(data.pid); if (thread == NULL) { pr_debug("problem processing %d event, skipping it.\n", event->header.type); @@ -1640,10 +1624,10 @@ static int process_sample_event(event_t *event) dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); - if (profile_cpu != -1 && profile_cpu != (int) cpu) + if (profile_cpu != -1 && profile_cpu != (int)data.cpu) return 0; - process_raw_event(event, more_data, cpu, timestamp, thread); + process_raw_event(event, data.raw_data, data.cpu, data.time, thread); return 0; } @@ -1679,11 +1663,18 @@ static struct perf_file_handler file_handler = { static int read_events(void) { + int err; + struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0); + + if (session == NULL) + return -ENOMEM; + register_idle_thread(); register_perf_file_handler(&file_handler); - return mmap_dispatch_perf_file(&header, input_name, 0, 0, - &event__cwdlen, &event__cwd); + err = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd); + perf_session__delete(session); + return err; } static void print_bad_events(void) @@ -1724,9 +1715,9 @@ static void __cmd_lat(void) read_events(); sort_lat(); - printf("\n -----------------------------------------------------------------------------------------\n"); - printf(" Task | Runtime ms | Switches | Average delay ms | Maximum delay ms |\n"); - printf(" -----------------------------------------------------------------------------------------\n"); + printf("\n ---------------------------------------------------------------------------------------------------------------\n"); + printf(" Task | Runtime ms | Switches | Average delay ms | Maximum delay ms | Maximum delay at |\n"); + printf(" ---------------------------------------------------------------------------------------------------------------\n"); next = rb_first(&sorted_atom_root); @@ -1902,13 +1893,18 @@ static int __cmd_record(int argc, const char **argv) int cmd_sched(int argc, const char **argv, const char *prefix __used) { - symbol__init(0); - argc = parse_options(argc, argv, sched_options, sched_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (!argc) usage_with_options(sched_usage, sched_options); + /* + * Aliased to 'perf trace' for now: + */ + if (!strcmp(argv[0], "trace")) + return cmd_trace(argc, argv, prefix); + + symbol__init(0); if (!strncmp(argv[0], "rec", 3)) { return __cmd_record(argc, argv); } else if (!strncmp(argv[0], "lat", 3)) { @@ -1932,11 +1928,6 @@ int cmd_sched(int argc, const char **argv, const char *prefix __used) usage_with_options(replay_usage, replay_options); } __cmd_replay(); - } else if (!strcmp(argv[0], "trace")) { - /* - * Aliased to 'perf trace' for now: - */ - return cmd_trace(argc, argv, prefix); } else { usage_with_options(sched_usage, sched_options); } diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index cb58b6605fcc875fec3d0122e8607b17a408db3c..759dd2b35fdbce539944627043b0922b7b711982 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -302,12 +302,11 @@ process_exit_event(event_t *event) } struct trace_entry { - u32 size; unsigned short type; unsigned char flags; unsigned char preempt_count; int pid; - int tgid; + int lock_depth; }; struct power_entry { @@ -484,43 +483,22 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te) static int process_sample_event(event_t *event) { - int cursor = 0; - u64 addr = 0; - u64 stamp = 0; - u32 cpu = 0; - u32 pid = 0; + struct sample_data data; struct trace_entry *te; - if (sample_type & PERF_SAMPLE_IP) - cursor++; + memset(&data, 0, sizeof(data)); - if (sample_type & PERF_SAMPLE_TID) { - pid = event->sample.array[cursor]>>32; - cursor++; - } - if (sample_type & PERF_SAMPLE_TIME) { - stamp = event->sample.array[cursor++]; - - if (!first_time || first_time > stamp) - first_time = stamp; - if (last_time < stamp) - last_time = stamp; + event__parse_sample(event, sample_type, &data); + if (sample_type & PERF_SAMPLE_TIME) { + if (!first_time || first_time > data.time) + first_time = data.time; + if (last_time < data.time) + last_time = data.time; } - if (sample_type & PERF_SAMPLE_ADDR) - addr = event->sample.array[cursor++]; - if (sample_type & PERF_SAMPLE_ID) - cursor++; - if (sample_type & PERF_SAMPLE_STREAM_ID) - cursor++; - if (sample_type & PERF_SAMPLE_CPU) - cpu = event->sample.array[cursor++] & 0xFFFFFFFF; - if (sample_type & PERF_SAMPLE_PERIOD) - cursor++; - te = (void *)&event->sample.array[cursor]; - - if (sample_type & PERF_SAMPLE_RAW && te->size > 0) { + te = (void *)data.raw_data; + if (sample_type & PERF_SAMPLE_RAW && data.raw_size > 0) { char *event_str; struct power_entry *pe; @@ -532,19 +510,19 @@ process_sample_event(event_t *event) return 0; if (strcmp(event_str, "power:power_start") == 0) - c_state_start(cpu, stamp, pe->value); + c_state_start(data.cpu, data.time, pe->value); if (strcmp(event_str, "power:power_end") == 0) - c_state_end(cpu, stamp); + c_state_end(data.cpu, data.time); if (strcmp(event_str, "power:power_frequency") == 0) - p_state_change(cpu, stamp, pe->value); + p_state_change(data.cpu, data.time, pe->value); if (strcmp(event_str, "sched:sched_wakeup") == 0) - sched_wakeup(cpu, stamp, pid, te); + sched_wakeup(data.cpu, data.time, data.pid, te); if (strcmp(event_str, "sched:sched_switch") == 0) - sched_switch(cpu, stamp, te); + sched_switch(data.cpu, data.time, te); } return 0; } @@ -1081,15 +1059,17 @@ static struct perf_file_handler file_handler = { static int __cmd_timechart(void) { - struct perf_header *header; + struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0); int ret; + if (session == NULL) + return -ENOMEM; + register_perf_file_handler(&file_handler); - ret = mmap_dispatch_perf_file(&header, input_name, 0, 0, - &event__cwdlen, &event__cwd); + ret = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd); if (ret) - return EXIT_FAILURE; + goto out_delete; process_samples(); @@ -1101,8 +1081,9 @@ static int __cmd_timechart(void) pr_info("Written %2.1f seconds of trace to %s.\n", (last_time - first_time) / 1000000000.0, output_name); - - return EXIT_SUCCESS; +out_delete: + perf_session__delete(session); + return ret; } static const char * const timechart_usage[] = { diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index abb914aa7be62e13c18fa6f7eea3c268d295c65d..0756664666f1021289ac3f610bc06ab685ecac12 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -7,6 +7,7 @@ #include "util/header.h" #include "util/exec_cmd.h" #include "util/trace-event.h" +#include "util/session.h" static char const *script_name; static char const *generate_script_lang; @@ -61,63 +62,45 @@ static int cleanup_scripting(void) static char const *input_name = "perf.data"; -static struct perf_header *header; +static struct perf_session *session; static u64 sample_type; static int process_sample_event(event_t *event) { - u64 ip = event->ip.ip; - u64 timestamp = -1; - u32 cpu = -1; - u64 period = 1; - void *more_data = event->ip.__more_data; - struct thread *thread = threads__findnew(event->ip.pid); - - if (sample_type & PERF_SAMPLE_TIME) { - timestamp = *(u64 *)more_data; - more_data += sizeof(u64); - } + struct sample_data data; + struct thread *thread; - if (sample_type & PERF_SAMPLE_CPU) { - cpu = *(u32 *)more_data; - more_data += sizeof(u32); - more_data += sizeof(u32); /* reserved */ - } + memset(&data, 0, sizeof(data)); + data.time = -1; + data.cpu = -1; + data.period = 1; - if (sample_type & PERF_SAMPLE_PERIOD) { - period = *(u64 *)more_data; - more_data += sizeof(u64); - } + event__parse_sample(event, sample_type, &data); dump_printf("(IP, %d): %d/%d: %p period: %Ld\n", event->header.misc, - event->ip.pid, event->ip.tid, - (void *)(long)ip, - (long long)period); + data.pid, data.tid, + (void *)(long)data.ip, + (long long)data.period); + thread = threads__findnew(event->ip.pid); if (thread == NULL) { pr_debug("problem processing %d event, skipping it.\n", event->header.type); return -1; } - dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); - if (sample_type & PERF_SAMPLE_RAW) { - struct { - u32 size; - char data[0]; - } *raw = more_data; - /* * FIXME: better resolve from pid from the struct trace_entry * field, although it should be the same than this perf * event pid */ - scripting_ops->process_event(cpu, raw->data, raw->size, - timestamp, thread->comm); + scripting_ops->process_event(data.cpu, data.raw_data, + data.raw_size, + data.time, thread->comm); } - event__stats.total += period; + event__stats.total += data.period; return 0; } @@ -144,11 +127,18 @@ static struct perf_file_handler file_handler = { static int __cmd_trace(void) { + int err; + + session = perf_session__new(input_name, O_RDONLY, 0); + if (session == NULL) + return -ENOMEM; + register_idle_thread(); register_perf_file_handler(&file_handler); - return mmap_dispatch_perf_file(&header, input_name, - 0, 0, &event__cwdlen, &event__cwd); + err = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd); + perf_session__delete(session); + return err; } struct script_spec { @@ -366,11 +356,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) return -1; } - header = perf_header__new(); - if (header == NULL) - return -1; - - perf_header__read(header, input); + perf_header__read(&session->header, input); err = scripting_ops->generate_script("perf-trace"); goto out; } diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 454d5d55f32d9cb30d8206c6f03bfe1e0b5f61fb..75f941bfba9eb897b0bdd3075a450425536ac74c 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -59,6 +59,18 @@ #define cpu_relax() asm volatile ("hint @pause" ::: "memory") #endif +#ifdef __arm__ +#include "../../arch/arm/include/asm/unistd.h" +/* + * Use the __kuser_memory_barrier helper in the CPU helper page. See + * arch/arm/kernel/entry-armv.S in the kernel source for details. + */ +#define rmb() asm volatile("mov r0, #0xffff0fff; mov lr, pc;" \ + "sub pc, r0, #95" ::: "r0", "lr", "cc", \ + "memory") +#define cpu_relax() asm volatile("":::"memory") +#endif + #include #include #include diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c index ca0bedf637c243135d40ffafc41562aa3a047c7d..6d46dda53a29db2fe73c8ddeb22ffd8f0648b034 100644 --- a/tools/perf/util/data_map.c +++ b/tools/perf/util/data_map.c @@ -100,11 +100,11 @@ process_event(event_t *event, unsigned long offset, unsigned long head) } } -int perf_header__read_build_ids(int input, off_t offset, off_t size) +int perf_header__read_build_ids(int input, u64 offset, u64 size) { struct build_id_event bev; char filename[PATH_MAX]; - off_t limit = offset + size; + u64 limit = offset + size; int err = -1; while (offset < limit) { @@ -129,23 +129,16 @@ out: return err; } -int mmap_dispatch_perf_file(struct perf_header **pheader, - const char *input_name, - int force, - int full_paths, - int *cwdlen, - char **cwd) +int perf_session__process_events(struct perf_session *self, + int full_paths, int *cwdlen, char **cwd) { int err; - struct perf_header *header; unsigned long head, shift; unsigned long offset = 0; - struct stat input_stat; size_t page_size; u64 sample_type; event_t *event; uint32_t size; - int input; char *buf; if (curr_handler == NULL) { @@ -155,56 +148,19 @@ int mmap_dispatch_perf_file(struct perf_header **pheader, page_size = getpagesize(); - input = open(input_name, O_RDONLY); - if (input < 0) { - pr_err("Failed to open file: %s", input_name); - if (!strcmp(input_name, "perf.data")) - pr_err(" (try 'perf record' first)"); - pr_err("\n"); - return -errno; - } - - if (fstat(input, &input_stat) < 0) { - pr_err("failed to stat file"); - err = -errno; - goto out_close; - } - - err = -EACCES; - if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { - pr_err("file: %s not owned by current user or root\n", - input_name); - goto out_close; - } - - if (input_stat.st_size == 0) { - pr_info("zero-sized file, nothing to do!\n"); - goto done; - } - - err = -ENOMEM; - header = perf_header__new(); - if (header == NULL) - goto out_close; - - err = perf_header__read(header, input); - if (err < 0) - goto out_delete; - *pheader = header; - head = header->data_offset; - - sample_type = perf_header__sample_type(header); + head = self->header.data_offset; + sample_type = perf_header__sample_type(&self->header); err = -EINVAL; if (curr_handler->sample_type_check && curr_handler->sample_type_check(sample_type) < 0) - goto out_delete; + goto out_err; if (!full_paths) { if (getcwd(__cwd, sizeof(__cwd)) == NULL) { pr_err("failed to get the current directory\n"); err = -errno; - goto out_delete; + goto out_err; } *cwd = __cwd; *cwdlen = strlen(*cwd); @@ -219,11 +175,11 @@ int mmap_dispatch_perf_file(struct perf_header **pheader, remap: buf = mmap(NULL, page_size * mmap_window, PROT_READ, - MAP_SHARED, input, offset); + MAP_SHARED, self->fd, offset); if (buf == MAP_FAILED) { pr_err("failed to mmap file\n"); err = -errno; - goto out_delete; + goto out_err; } more: @@ -273,19 +229,14 @@ more: head += size; - if (offset + head >= header->data_offset + header->data_size) + if (offset + head >= self->header.data_offset + self->header.data_size) goto done; - if (offset + head < (unsigned long)input_stat.st_size) + if (offset + head < self->size) goto more; done: err = 0; -out_close: - close(input); - +out_err: return err; -out_delete: - perf_header__delete(header); - goto out_close; } diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h index 3180ff7e3633b4dff29d167c3d2a7e23367d23fb..98c5b823388cd3efe8c84582433230ce273b73c5 100644 --- a/tools/perf/util/data_map.h +++ b/tools/perf/util/data_map.h @@ -3,6 +3,7 @@ #include "event.h" #include "header.h" +#include "session.h" typedef int (*event_type_handler_t)(event_t *); @@ -21,12 +22,8 @@ struct perf_file_handler { }; void register_perf_file_handler(struct perf_file_handler *handler); -int mmap_dispatch_perf_file(struct perf_header **pheader, - const char *input_name, - int force, - int full_paths, - int *cwdlen, - char **cwd); -int perf_header__read_build_ids(int input, off_t offset, off_t file_size); +int perf_session__process_events(struct perf_session *self, + int full_paths, int *cwdlen, char **cwd); +int perf_header__read_build_ids(int input, u64 offset, u64 file_size); #endif diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 414b89d1bde9ec8637ea0390bb29f20f1dd84ec3..ba0de90cd3d4ea6163f699233845fea5fb2b6976 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -254,13 +254,14 @@ void thread__find_addr_location(struct thread *self, u8 cpumode, struct addr_location *al, symbol_filter_t filter) { - struct thread *thread = al->thread = self; + struct map_groups *mg = &self->mg; + al->thread = self; al->addr = addr; if (cpumode & PERF_RECORD_MISC_KERNEL) { al->level = 'k'; - thread = kthread; + mg = kmaps; } else if (cpumode & PERF_RECORD_MISC_USER) al->level = '.'; else { @@ -270,7 +271,7 @@ void thread__find_addr_location(struct thread *self, u8 cpumode, return; } try_again: - al->map = thread__find_map(thread, type, al->addr); + al->map = map_groups__find(mg, type, al->addr); if (al->map == NULL) { /* * If this is outside of all known maps, and is a negative @@ -281,8 +282,8 @@ try_again: * "[vdso]" dso, but for now lets use the old trick of looking * in the whole kernel symbol list. */ - if ((long long)al->addr < 0 && thread != kthread) { - thread = kthread; + if ((long long)al->addr < 0 && mg != kmaps) { + mg = kmaps; goto try_again; } al->sym = NULL; @@ -310,3 +311,70 @@ int event__preprocess_sample(const event_t *self, struct addr_location *al, al->level == 'H' ? "[hypervisor]" : ""); return 0; } + +int event__parse_sample(event_t *event, u64 type, struct sample_data *data) +{ + u64 *array = event->sample.array; + + if (type & PERF_SAMPLE_IP) { + data->ip = event->ip.ip; + array++; + } + + if (type & PERF_SAMPLE_TID) { + u32 *p = (u32 *)array; + data->pid = p[0]; + data->tid = p[1]; + array++; + } + + if (type & PERF_SAMPLE_TIME) { + data->time = *array; + array++; + } + + if (type & PERF_SAMPLE_ADDR) { + data->addr = *array; + array++; + } + + if (type & PERF_SAMPLE_ID) { + data->id = *array; + array++; + } + + if (type & PERF_SAMPLE_STREAM_ID) { + data->stream_id = *array; + array++; + } + + if (type & PERF_SAMPLE_CPU) { + u32 *p = (u32 *)array; + data->cpu = *p; + array++; + } + + if (type & PERF_SAMPLE_PERIOD) { + data->period = *array; + array++; + } + + if (type & PERF_SAMPLE_READ) { + pr_debug("PERF_SAMPLE_READ is unsuported for now\n"); + return -1; + } + + if (type & PERF_SAMPLE_CALLCHAIN) { + data->callchain = (struct ip_callchain *)array; + array += 1 + data->callchain->nr; + } + + if (type & PERF_SAMPLE_RAW) { + u32 *p = (u32 *)array; + data->raw_size = *p; + p++; + data->raw_data = p; + } + + return 0; +} diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index a4cc8105cf675f42285896e674dd81193da7582b..51a96c2effdea662c4a77e5b5a2ed3cde1e61b64 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -56,11 +56,25 @@ struct read_event { u64 id; }; -struct sample_event{ +struct sample_event { struct perf_event_header header; u64 array[]; }; +struct sample_data { + u64 ip; + u32 pid, tid; + u64 time; + u64 addr; + u64 id; + u64 stream_id; + u32 cpu; + u64 period; + struct ip_callchain *callchain; + u32 raw_size; + void *raw_data; +}; + #define BUILD_ID_SIZE 20 struct build_id_event { @@ -89,10 +103,11 @@ void event__print_totals(void); enum map_type { MAP__FUNCTION = 0, - - MAP__NR_TYPES, + MAP__VARIABLE, }; +#define MAP__NR_TYPES (MAP__VARIABLE + 1) + struct map { union { struct rb_node rb_node; @@ -136,6 +151,8 @@ int map__overlap(struct map *l, struct map *r); size_t map__fprintf(struct map *self, FILE *fp); struct symbol *map__find_symbol(struct map *self, u64 addr, symbol_filter_t filter); +struct symbol *map__find_symbol_by_name(struct map *self, const char *name, + symbol_filter_t filter); void map__fixup_start(struct map *self); void map__fixup_end(struct map *self); @@ -155,5 +172,6 @@ int event__process_task(event_t *self); struct addr_location; int event__preprocess_sample(const event_t *self, struct addr_location *al, symbol_filter_t filter); +int event__parse_sample(event_t *event, u64 type, struct sample_data *data); #endif /* __PERF_RECORD_H */ diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 4805e6dfd23c8a77f2ea7a7bf56bc15c8e5a4544..f2e8d87151116c94a78868ba580e56be24382264 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -58,35 +58,19 @@ int perf_header_attr__add_id(struct perf_header_attr *self, u64 id) return 0; } -/* - * Create new perf.data header: - */ -struct perf_header *perf_header__new(void) +int perf_header__init(struct perf_header *self) { - struct perf_header *self = zalloc(sizeof(*self)); - - if (self != NULL) { - self->size = 1; - self->attr = malloc(sizeof(void *)); - - if (self->attr == NULL) { - free(self); - self = NULL; - } - } - - return self; + self->size = 1; + self->attr = malloc(sizeof(void *)); + return self->attr == NULL ? -ENOMEM : 0; } -void perf_header__delete(struct perf_header *self) +void perf_header__exit(struct perf_header *self) { int i; - for (i = 0; i < self->attrs; ++i) - perf_header_attr__delete(self->attr[i]); - + perf_header_attr__delete(self->attr[i]); free(self->attr); - free(self); } int perf_header__add_attr(struct perf_header *self, @@ -187,7 +171,9 @@ static int do_write(int fd, const void *buf, size_t size) static int __dsos__write_buildid_table(struct list_head *head, int fd) { +#define NAME_ALIGN 64 struct dso *pos; + static const char zero_buf[NAME_ALIGN]; list_for_each_entry(pos, head, node) { int err; @@ -197,14 +183,17 @@ static int __dsos__write_buildid_table(struct list_head *head, int fd) if (!pos->has_build_id) continue; len = pos->long_name_len + 1; - len = ALIGN(len, 64); + len = ALIGN(len, NAME_ALIGN); memset(&b, 0, sizeof(b)); memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); b.header.size = sizeof(b) + len; err = do_write(fd, &b, sizeof(b)); if (err < 0) return err; - err = do_write(fd, pos->long_name, len); + err = do_write(fd, pos->long_name, pos->long_name_len + 1); + if (err < 0) + return err; + err = do_write(fd, zero_buf, len - pos->long_name_len - 1); if (err < 0) return err; } diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index d1dbe2b79c42bfcbf9a3e90e965076b6a5afc075..d118d05d3abe772f1feeb0fb1d425d75de687df0 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -55,8 +55,8 @@ struct perf_header { DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); }; -struct perf_header *perf_header__new(void); -void perf_header__delete(struct perf_header *self); +int perf_header__init(struct perf_header *self); +void perf_header__exit(struct perf_header *self); int perf_header__read(struct perf_header *self, int fd); int perf_header__write(struct perf_header *self, int fd, bool at_exit); diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 69f94fe9db20a059e4e00f687bd109a543c7d0e0..76bdca640a9b5fcde2f7206f39940dc23e4750e8 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -104,43 +104,64 @@ void map__fixup_end(struct map *self) #define DSO__DELETED "(deleted)" -struct symbol *map__find_symbol(struct map *self, u64 addr, - symbol_filter_t filter) +static int map__load(struct map *self, symbol_filter_t filter) { - if (!dso__loaded(self->dso, self->type)) { - int nr = dso__load(self->dso, self, filter); - - if (nr < 0) { - if (self->dso->has_build_id) { - char sbuild_id[BUILD_ID_SIZE * 2 + 1]; - - build_id__sprintf(self->dso->build_id, - sizeof(self->dso->build_id), - sbuild_id); - pr_warning("%s with build id %s not found", - self->dso->long_name, sbuild_id); - } else - pr_warning("Failed to open %s", - self->dso->long_name); - pr_warning(", continuing without symbols\n"); - return NULL; - } else if (nr == 0) { - const char *name = self->dso->long_name; - const size_t len = strlen(name); - const size_t real_len = len - sizeof(DSO__DELETED); - - if (len > sizeof(DSO__DELETED) && - strcmp(name + real_len + 1, DSO__DELETED) == 0) { - pr_warning("%.*s was updated, restart the long running apps that use it!\n", - (int)real_len, name); - } else { - pr_warning("no symbols found in %s, maybe install a debug package?\n", name); - } - return NULL; + const char *name = self->dso->long_name; + int nr = dso__load(self->dso, self, filter); + + if (nr < 0) { + if (self->dso->has_build_id) { + char sbuild_id[BUILD_ID_SIZE * 2 + 1]; + + build_id__sprintf(self->dso->build_id, + sizeof(self->dso->build_id), + sbuild_id); + pr_warning("%s with build id %s not found", + name, sbuild_id); + } else + pr_warning("Failed to open %s", name); + + pr_warning(", continuing without symbols\n"); + return -1; + } else if (nr == 0) { + const size_t len = strlen(name); + const size_t real_len = len - sizeof(DSO__DELETED); + + if (len > sizeof(DSO__DELETED) && + strcmp(name + real_len + 1, DSO__DELETED) == 0) { + pr_warning("%.*s was updated, restart the long " + "running apps that use it!\n", + (int)real_len, name); + } else { + pr_warning("no symbols found in %s, maybe install " + "a debug package?\n", name); } + + return -1; } - return self->dso->find_symbol(self->dso, self->type, addr); + return 0; +} + +struct symbol *map__find_symbol(struct map *self, u64 addr, + symbol_filter_t filter) +{ + if (!dso__loaded(self->dso, self->type) && map__load(self, filter) < 0) + return NULL; + + return dso__find_symbol(self->dso, self->type, addr); +} + +struct symbol *map__find_symbol_by_name(struct map *self, const char *name, + symbol_filter_t filter) +{ + if (!dso__loaded(self->dso, self->type) && map__load(self, filter) < 0) + return NULL; + + if (!dso__sorted_by_name(self->dso, self->type)) + dso__sort_by_name(self->dso, self->type); + + return dso__find_symbol_by_name(self->dso, self->type, name); } struct map *map__clone(struct map *self) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 9e5dbd66d34d7aa95aad038d2168eaed5ef920b3..e5bc0fb016b2c130b873ba5808f4ed3d33896400 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -197,7 +197,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) if (id == config) { closedir(evt_dir); closedir(sys_dir); - path = zalloc(sizeof(path)); + path = zalloc(sizeof(*path)); path->system = malloc(MAX_EVENT_LENGTH); if (!path->system) { free(path); @@ -467,7 +467,6 @@ parse_subsystem_tracepoint_event(char *sys_name, char *flags) while ((evt_ent = readdir(evt_dir))) { char event_opt[MAX_EVOPT_LEN + 1]; int len; - unsigned int rem = MAX_EVOPT_LEN; if (!strcmp(evt_ent->d_name, ".") || !strcmp(evt_ent->d_name, "..") @@ -475,20 +474,12 @@ parse_subsystem_tracepoint_event(char *sys_name, char *flags) || !strcmp(evt_ent->d_name, "filter")) continue; - len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name, - evt_ent->d_name); + len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s%s%s", sys_name, + evt_ent->d_name, flags ? ":" : "", + flags ?: ""); if (len < 0) return EVT_FAILED; - rem -= len; - if (flags) { - if (rem < strlen(flags) + 1) - return EVT_FAILED; - - strcat(event_opt, ":"); - strcat(event_opt, flags); - } - if (parse_events(NULL, event_opt, 0)) return EVT_FAILED; } diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 6d8af48c925eb6b0f9f094164e89bb000963afe1..efebd5b476b320685178947332a48214d76529b5 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -430,6 +430,9 @@ int usage_with_options_internal(const char * const *usagestr, pos = fprintf(stderr, " "); if (opts->short_name) pos += fprintf(stderr, "-%c", opts->short_name); + else + pos += fprintf(stderr, " "); + if (opts->long_name && opts->short_name) pos += fprintf(stderr, ", "); if (opts->long_name) diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index cd7fbda5e2a57460a32ef56a673ddb3729d59b43..d14a4585bcafb53fd8a9f664ff50e32e8ca9f95b 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -47,6 +47,9 @@ #define semantic_error(msg ...) die("Semantic error :" msg) /* If there is no space to write, returns -E2BIG. */ +static int e_snprintf(char *str, size_t size, const char *format, ...) + __attribute__((format(printf, 3, 4))); + static int e_snprintf(char *str, size_t size, const char *format, ...) { int ret; @@ -258,7 +261,7 @@ int synthesize_perf_probe_event(struct probe_point *pp) ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->function, offs, pp->retprobe ? "%return" : "", line); else - ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->file, line); + ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", pp->file, line); if (ret <= 0) goto error; len = ret; @@ -373,14 +376,32 @@ static void clear_probe_point(struct probe_point *pp) free(pp->args); for (i = 0; i < pp->found; i++) free(pp->probes[i]); - memset(pp, 0, sizeof(pp)); + memset(pp, 0, sizeof(*pp)); +} + +/* Show an event */ +static void show_perf_probe_event(const char *group, const char *event, + const char *place, struct probe_point *pp) +{ + int i; + char buf[128]; + + e_snprintf(buf, 128, "%s:%s", group, event); + printf(" %-40s (on %s", buf, place); + + if (pp->nr_args > 0) { + printf(" with"); + for (i = 0; i < pp->nr_args; i++) + printf(" %s", pp->args[i]); + } + printf(")\n"); } /* List up current perf-probe events */ void show_perf_probe_events(void) { unsigned int i; - int fd; + int fd, nr; char *group, *event; struct probe_point pp; struct strlist *rawlist; @@ -393,8 +414,13 @@ void show_perf_probe_events(void) for (i = 0; i < strlist__nr_entries(rawlist); i++) { ent = strlist__entry(rawlist, i); parse_trace_kprobe_event(ent->s, &group, &event, &pp); + /* Synthesize only event probe point */ + nr = pp.nr_args; + pp.nr_args = 0; synthesize_perf_probe_event(&pp); - printf("[%s:%s]\t%s\n", group, event, pp.probes[0]); + pp.nr_args = nr; + /* Show an event */ + show_perf_probe_event(group, event, pp.probes[0], &pp); free(group); free(event); clear_probe_point(&pp); @@ -404,21 +430,28 @@ void show_perf_probe_events(void) } /* Get current perf-probe event names */ -static struct strlist *get_perf_event_names(int fd) +static struct strlist *get_perf_event_names(int fd, bool include_group) { unsigned int i; char *group, *event; + char buf[128]; struct strlist *sl, *rawlist; struct str_node *ent; rawlist = get_trace_kprobe_event_rawlist(fd); - sl = strlist__new(false, NULL); + sl = strlist__new(true, NULL); for (i = 0; i < strlist__nr_entries(rawlist); i++) { ent = strlist__entry(rawlist, i); parse_trace_kprobe_event(ent->s, &group, &event, NULL); - strlist__add(sl, event); + if (include_group) { + if (e_snprintf(buf, 128, "%s:%s", group, event) < 0) + die("Failed to copy group:event name."); + strlist__add(sl, buf); + } else + strlist__add(sl, event); free(group); + free(event); } strlist__delete(rawlist); @@ -426,24 +459,30 @@ static struct strlist *get_perf_event_names(int fd) return sl; } -static int write_trace_kprobe_event(int fd, const char *buf) +static void write_trace_kprobe_event(int fd, const char *buf) { int ret; + pr_debug("Writing event: %s\n", buf); ret = write(fd, buf, strlen(buf)); if (ret <= 0) - die("Failed to create event."); - else - printf("Added new event: %s\n", buf); - - return ret; + die("Failed to write event: %s", strerror(errno)); } static void get_new_event_name(char *buf, size_t len, const char *base, struct strlist *namelist) { int i, ret; - for (i = 0; i < MAX_EVENT_INDEX; i++) { + + /* Try no suffix */ + ret = e_snprintf(buf, len, "%s", base); + if (ret < 0) + die("snprintf() failed: %s", strerror(-ret)); + if (!strlist__has_entry(namelist, buf)) + return; + + /* Try to add suffix */ + for (i = 1; i < MAX_EVENT_INDEX; i++) { ret = e_snprintf(buf, len, "%s_%d", base, i); if (ret < 0) die("snprintf() failed: %s", strerror(-ret)); @@ -464,7 +503,7 @@ void add_trace_kprobe_events(struct probe_point *probes, int nr_probes) fd = open_kprobe_events(O_RDWR, O_APPEND); /* Get current event names */ - namelist = get_perf_event_names(fd); + namelist = get_perf_event_names(fd, false); for (j = 0; j < nr_probes; j++) { pp = probes + j; @@ -476,9 +515,73 @@ void add_trace_kprobe_events(struct probe_point *probes, int nr_probes) PERFPROBE_GROUP, event, pp->probes[i]); write_trace_kprobe_event(fd, buf); + printf("Added new event:\n"); + /* Get the first parameter (probe-point) */ + sscanf(pp->probes[i], "%s", buf); + show_perf_probe_event(PERFPROBE_GROUP, event, + buf, pp); /* Add added event name to namelist */ strlist__add(namelist, event); } } + /* Show how to use the event. */ + printf("\nYou can now use it on all perf tools, such as:\n\n"); + printf("\tperf record -e %s:%s -a sleep 1\n\n", PERFPROBE_GROUP, event); + + strlist__delete(namelist); + close(fd); +} + +static void del_trace_kprobe_event(int fd, const char *group, + const char *event, struct strlist *namelist) +{ + char buf[128]; + + if (e_snprintf(buf, 128, "%s:%s", group, event) < 0) + die("Failed to copy event."); + if (!strlist__has_entry(namelist, buf)) { + pr_warning("Warning: event \"%s\" is not found.\n", buf); + return; + } + /* Convert from perf-probe event to trace-kprobe event */ + if (e_snprintf(buf, 128, "-:%s/%s", group, event) < 0) + die("Failed to copy event."); + + write_trace_kprobe_event(fd, buf); + printf("Remove event: %s:%s\n", group, event); +} + +void del_trace_kprobe_events(struct strlist *dellist) +{ + int fd; + unsigned int i; + const char *group, *event; + char *p, *str; + struct str_node *ent; + struct strlist *namelist; + + fd = open_kprobe_events(O_RDWR, O_APPEND); + /* Get current event names */ + namelist = get_perf_event_names(fd, true); + + for (i = 0; i < strlist__nr_entries(dellist); i++) { + ent = strlist__entry(dellist, i); + str = strdup(ent->s); + if (!str) + die("Failed to copy event."); + p = strchr(str, ':'); + if (p) { + group = str; + *p = '\0'; + event = p + 1; + } else { + group = PERFPROBE_GROUP; + event = str; + } + del_trace_kprobe_event(fd, group, event, namelist); + free(str); + } + strlist__delete(namelist); close(fd); } + diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 0c6fe56fe38a01bfe64ca7f2458cd5d1981b261d..f752159124aef11a6a092e7afe497c5c2b6400af 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -10,6 +10,7 @@ extern void parse_trace_kprobe_event(const char *str, char **group, char **event, struct probe_point *pp); extern int synthesize_trace_kprobe_event(struct probe_point *pp); extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes); +extern void del_trace_kprobe_events(struct strlist *dellist); extern void show_perf_probe_events(void); /* Maximum index number of event-name postfix */ diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 293cdfc1b8ca303ae6594e0450f2750af1245928..4585f1d867927db60d5ec9ad5abc1744ef871175 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -106,7 +106,7 @@ static int strtailcmp(const char *s1, const char *s2) { int i1 = strlen(s1); int i2 = strlen(s2); - while (--i1 > 0 && --i2 > 0) { + while (--i1 >= 0 && --i2 >= 0) { if (s1[i1] != s2[i2]) return s1[i1] - s2[i2]; } diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c new file mode 100644 index 0000000000000000000000000000000000000000..707ce1cb1621b3710ac26c16876479bbb086edab --- /dev/null +++ b/tools/perf/util/session.c @@ -0,0 +1,80 @@ +#include + +#include +#include + +#include "session.h" +#include "util.h" + +static int perf_session__open(struct perf_session *self, bool force) +{ + struct stat input_stat; + + self->fd = open(self->filename, O_RDONLY); + if (self->fd < 0) { + pr_err("failed to open file: %s", self->filename); + if (!strcmp(self->filename, "perf.data")) + pr_err(" (try 'perf record' first)"); + pr_err("\n"); + return -errno; + } + + if (fstat(self->fd, &input_stat) < 0) + goto out_close; + + if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { + pr_err("file %s not owned by current user or root\n", + self->filename); + goto out_close; + } + + if (!input_stat.st_size) { + pr_info("zero-sized file (%s), nothing to do!\n", + self->filename); + goto out_close; + } + + if (perf_header__read(&self->header, self->fd) < 0) { + pr_err("incompatible file format"); + goto out_close; + } + + self->size = input_stat.st_size; + return 0; + +out_close: + close(self->fd); + self->fd = -1; + return -1; +} + +struct perf_session *perf_session__new(const char *filename, int mode, bool force) +{ + size_t len = strlen(filename) + 1; + struct perf_session *self = zalloc(sizeof(*self) + len); + + if (self == NULL) + goto out; + + if (perf_header__init(&self->header) < 0) + goto out_delete; + + memcpy(self->filename, filename, len); + + if (mode == O_RDONLY && perf_session__open(self, force) < 0) { + perf_session__delete(self); + self = NULL; + } +out: + return self; +out_delete: + free(self); + return NULL; +} + +void perf_session__delete(struct perf_session *self) +{ + perf_header__exit(&self->header); + close(self->fd); + free(self); +} diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h new file mode 100644 index 0000000000000000000000000000000000000000..f3699c8c8ed4da77e3e1a87a058dcd20049eebe2 --- /dev/null +++ b/tools/perf/util/session.h @@ -0,0 +1,16 @@ +#ifndef __PERF_SESSION_H +#define __PERF_SESSION_H + +#include "header.h" + +struct perf_session { + struct perf_header header; + unsigned long size; + int fd; + char filename[0]; +}; + +struct perf_session *perf_session__new(const char *filename, int mode, bool force); +void perf_session__delete(struct perf_session *self); + +#endif /* __PERF_SESSION_H */ diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index fffcb937cdcb207f470f1bf335f1e316e283bc12..d3d9fed74f1dbcb56fc1ba66aa5cbc09e53e426c 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -29,11 +29,9 @@ enum dso_origin { }; static void dsos__add(struct list_head *head, struct dso *dso); -static struct map *thread__find_map_by_name(struct thread *self, char *name); static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); -struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); static int dso__load_kernel_sym(struct dso *self, struct map *map, - struct thread *thread, symbol_filter_t filter); + struct map_groups *mg, symbol_filter_t filter); unsigned int symbol__priv_size; static int vmlinux_path__nr_entries; static char **vmlinux_path; @@ -43,19 +41,41 @@ static struct symbol_conf symbol_conf__defaults = { .try_vmlinux_path = true, }; -static struct thread kthread_mem; -struct thread *kthread = &kthread_mem; +static struct map_groups kmaps_mem; +struct map_groups *kmaps = &kmaps_mem; bool dso__loaded(const struct dso *self, enum map_type type) { return self->loaded & (1 << type); } +bool dso__sorted_by_name(const struct dso *self, enum map_type type) +{ + return self->sorted_by_name & (1 << type); +} + static void dso__set_loaded(struct dso *self, enum map_type type) { self->loaded |= (1 << type); } +static void dso__set_sorted_by_name(struct dso *self, enum map_type type) +{ + self->sorted_by_name |= (1 << type); +} + +static bool symbol_type__is_a(char symbol_type, enum map_type map_type) +{ + switch (map_type) { + case MAP__FUNCTION: + return symbol_type == 'T' || symbol_type == 'W'; + case MAP__VARIABLE: + return symbol_type == 'D' || symbol_type == 'd'; + default: + return false; + } +} + static void symbols__fixup_end(struct rb_root *self) { struct rb_node *nd, *prevnd = rb_first(self); @@ -79,7 +99,7 @@ static void symbols__fixup_end(struct rb_root *self) curr->end = roundup(curr->start, 4096); } -static void __thread__fixup_maps_end(struct thread *self, enum map_type type) +static void __map_groups__fixup_end(struct map_groups *self, enum map_type type) { struct map *prev, *curr; struct rb_node *nd, *prevnd = rb_first(&self->maps[type]); @@ -102,11 +122,11 @@ static void __thread__fixup_maps_end(struct thread *self, enum map_type type) curr->end = ~0UL; } -static void thread__fixup_maps_end(struct thread *self) +static void map_groups__fixup_end(struct map_groups *self) { int i; for (i = 0; i < MAP__NR_TYPES; ++i) - __thread__fixup_maps_end(self, i); + __map_groups__fixup_end(self, i); } static struct symbol *symbol__new(u64 start, u64 len, const char *name) @@ -164,11 +184,11 @@ struct dso *dso__new(const char *name) dso__set_long_name(self, self->name); self->short_name = self->name; for (i = 0; i < MAP__NR_TYPES; ++i) - self->symbols[i] = RB_ROOT; - self->find_symbol = dso__find_symbol; + self->symbols[i] = self->symbol_names[i] = RB_ROOT; self->slen_calculated = 0; self->origin = DSO__ORIG_NOT_FOUND; self->loaded = 0; + self->sorted_by_name = 0; self->has_build_id = 0; } @@ -246,11 +266,85 @@ static struct symbol *symbols__find(struct rb_root *self, u64 ip) return NULL; } -struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr) +struct symbol_name_rb_node { + struct rb_node rb_node; + struct symbol sym; +}; + +static void symbols__insert_by_name(struct rb_root *self, struct symbol *sym) +{ + struct rb_node **p = &self->rb_node; + struct rb_node *parent = NULL; + struct symbol_name_rb_node *symn = ((void *)sym) - sizeof(*parent), *s; + + while (*p != NULL) { + parent = *p; + s = rb_entry(parent, struct symbol_name_rb_node, rb_node); + if (strcmp(sym->name, s->sym.name) < 0) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + rb_link_node(&symn->rb_node, parent, p); + rb_insert_color(&symn->rb_node, self); +} + +static void symbols__sort_by_name(struct rb_root *self, struct rb_root *source) +{ + struct rb_node *nd; + + for (nd = rb_first(source); nd; nd = rb_next(nd)) { + struct symbol *pos = rb_entry(nd, struct symbol, rb_node); + symbols__insert_by_name(self, pos); + } +} + +static struct symbol *symbols__find_by_name(struct rb_root *self, const char *name) +{ + struct rb_node *n; + + if (self == NULL) + return NULL; + + n = self->rb_node; + + while (n) { + struct symbol_name_rb_node *s; + int cmp; + + s = rb_entry(n, struct symbol_name_rb_node, rb_node); + cmp = strcmp(name, s->sym.name); + + if (cmp < 0) + n = n->rb_left; + else if (cmp > 0) + n = n->rb_right; + else + return &s->sym; + } + + return NULL; +} + +struct symbol *dso__find_symbol(struct dso *self, + enum map_type type, u64 addr) { return symbols__find(&self->symbols[type], addr); } +struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, + const char *name) +{ + return symbols__find_by_name(&self->symbol_names[type], name); +} + +void dso__sort_by_name(struct dso *self, enum map_type type) +{ + dso__set_sorted_by_name(self, type); + return symbols__sort_by_name(&self->symbol_names[type], + &self->symbols[type]); +} + int build_id__sprintf(u8 *self, int len, char *bf) { char *bid = bf; @@ -327,10 +421,7 @@ static int dso__load_all_kallsyms(struct dso *self, struct map *map) continue; symbol_type = toupper(line[len]); - /* - * We're interested only in code ('T'ext) - */ - if (symbol_type != 'T' && symbol_type != 'W') + if (!symbol_type__is_a(symbol_type, map->type)) continue; symbol_name = line + len + 2; @@ -364,8 +455,8 @@ out_failure: * kernel range is broken in several maps, named [kernel].N, as we don't have * the original ELF section names vmlinux have. */ -static int dso__split_kallsyms(struct dso *self, struct map *map, struct thread *thread, - symbol_filter_t filter) +static int dso__split_kallsyms(struct dso *self, struct map *map, + struct map_groups *mg, symbol_filter_t filter) { struct map *curr_map = map; struct symbol *pos; @@ -382,13 +473,13 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, struct thread module = strchr(pos->name, '\t'); if (module) { - if (!thread->use_modules) + if (!mg->use_modules) goto discard_symbol; *module++ = '\0'; if (strcmp(self->name, module)) { - curr_map = thread__find_map_by_name(thread, module); + curr_map = map_groups__find_by_name(mg, map->type, module); if (curr_map == NULL) { pr_debug("/proc/{kallsyms,modules} " "inconsistency!\n"); @@ -419,7 +510,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, struct thread } curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; - __thread__insert_map(thread, curr_map); + map_groups__insert(mg, curr_map); ++kernel_range; } @@ -440,7 +531,7 @@ discard_symbol: rb_erase(&pos->rb_node, root); static int dso__load_kallsyms(struct dso *self, struct map *map, - struct thread *thread, symbol_filter_t filter) + struct map_groups *mg, symbol_filter_t filter) { if (dso__load_all_kallsyms(self, map) < 0) return -1; @@ -448,13 +539,13 @@ static int dso__load_kallsyms(struct dso *self, struct map *map, symbols__fixup_end(&self->symbols[map->type]); self->origin = DSO__ORIG_KERNEL; - return dso__split_kallsyms(self, map, thread, filter); + return dso__split_kallsyms(self, map, mg, filter); } size_t kernel_maps__fprintf(FILE *fp) { size_t printed = fprintf(fp, "Kernel maps:\n"); - printed += thread__fprintf_maps(kthread, fp); + printed += map_groups__fprintf_maps(kmaps, fp); return printed + fprintf(fp, "END kernel maps\n"); } @@ -544,6 +635,13 @@ static inline int elf_sym__is_function(const GElf_Sym *sym) sym->st_shndx != SHN_UNDEF; } +static inline bool elf_sym__is_object(const GElf_Sym *sym) +{ + return elf_sym__type(sym) == STT_OBJECT && + sym->st_name != 0 && + sym->st_shndx != SHN_UNDEF; +} + static inline int elf_sym__is_label(const GElf_Sym *sym) { return elf_sym__type(sym) == STT_NOTYPE && @@ -564,6 +662,12 @@ static inline int elf_sec__is_text(const GElf_Shdr *shdr, return strstr(elf_sec__name(shdr, secstrs), "text") != NULL; } +static inline bool elf_sec__is_data(const GElf_Shdr *shdr, + const Elf_Data *secstrs) +{ + return strstr(elf_sec__name(shdr, secstrs), "data") != NULL; +} + static inline const char *elf_sym__name(const GElf_Sym *sym, const Elf_Data *symstrs) { @@ -744,8 +848,32 @@ out: return 0; } +static bool elf_sym__is_a(GElf_Sym *self, enum map_type type) +{ + switch (type) { + case MAP__FUNCTION: + return elf_sym__is_function(self); + case MAP__VARIABLE: + return elf_sym__is_object(self); + default: + return false; + } +} + +static bool elf_sec__is_a(GElf_Shdr *self, Elf_Data *secstrs, enum map_type type) +{ + switch (type) { + case MAP__FUNCTION: + return elf_sec__is_text(self, secstrs); + case MAP__VARIABLE: + return elf_sec__is_data(self, secstrs); + default: + return false; + } +} + static int dso__load_sym(struct dso *self, struct map *map, - struct thread *thread, const char *name, int fd, + struct map_groups *mg, const char *name, int fd, symbol_filter_t filter, int kernel, int kmodule) { struct map *curr_map = map; @@ -818,7 +946,7 @@ static int dso__load_sym(struct dso *self, struct map *map, int is_label = elf_sym__is_label(&sym); const char *section_name; - if (!is_label && !elf_sym__is_function(&sym)) + if (!is_label && !elf_sym__is_a(&sym, map->type)) continue; sec = elf_getscn(elf, sym.st_shndx); @@ -827,7 +955,7 @@ static int dso__load_sym(struct dso *self, struct map *map, gelf_getshdr(sec, &shdr); - if (is_label && !elf_sec__is_text(&shdr, secstrs)) + if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type)) continue; elf_name = elf_sym__name(&sym, symstrs); @@ -849,7 +977,7 @@ static int dso__load_sym(struct dso *self, struct map *map, snprintf(dso_name, sizeof(dso_name), "%s%s", self->short_name, section_name); - curr_map = thread__find_map_by_name(thread, dso_name); + curr_map = map_groups__find_by_name(mg, map->type, dso_name); if (curr_map == NULL) { u64 start = sym.st_value; @@ -868,7 +996,7 @@ static int dso__load_sym(struct dso *self, struct map *map, curr_map->map_ip = identity__map_ip; curr_map->unmap_ip = identity__map_ip; curr_dso->origin = DSO__ORIG_KERNEL; - __thread__insert_map(kthread, curr_map); + map_groups__insert(kmaps, curr_map); dsos__add(&dsos__kernel, curr_dso); } else curr_dso = curr_map->dso; @@ -938,8 +1066,9 @@ static bool __dsos__read_build_ids(struct list_head *head) bool dsos__read_build_ids(void) { - return __dsos__read_build_ids(&dsos__kernel) || - __dsos__read_build_ids(&dsos__user); + bool kbuildids = __dsos__read_build_ids(&dsos__kernel), + ubuildids = __dsos__read_build_ids(&dsos__user); + return kbuildids || ubuildids; } /* @@ -1093,7 +1222,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) dso__set_loaded(self, map->type); if (self->kernel) - return dso__load_kernel_sym(self, map, kthread, filter); + return dso__load_kernel_sym(self, map, kmaps, filter); name = malloc(size); if (!name) @@ -1179,11 +1308,12 @@ out: return ret; } -static struct map *thread__find_map_by_name(struct thread *self, char *name) +struct map *map_groups__find_by_name(struct map_groups *self, + enum map_type type, const char *name) { struct rb_node *nd; - for (nd = rb_first(&self->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { + for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) { struct map *map = rb_entry(nd, struct map, rb_node); if (map->dso && strcmp(map->dso->name, name) == 0) @@ -1227,7 +1357,7 @@ static int dsos__set_modules_path_dir(char *dirname) (int)(dot - dent->d_name), dent->d_name); strxfrchar(dso_name, '-', '_'); - map = thread__find_map_by_name(kthread, dso_name); + map = map_groups__find_by_name(kmaps, MAP__FUNCTION, dso_name); if (map == NULL) continue; @@ -1280,7 +1410,7 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) return self; } -static int thread__create_module_maps(struct thread *self) +static int map_groups__create_module_maps(struct map_groups *self) { char *line = NULL; size_t n; @@ -1337,7 +1467,7 @@ static int thread__create_module_maps(struct thread *self) dso->has_build_id = true; dso->origin = DSO__ORIG_KMODULE; - __thread__insert_map(self, map); + map_groups__insert(self, map); dsos__add(&dsos__kernel, dso); } @@ -1352,7 +1482,8 @@ out_failure: return -1; } -static int dso__load_vmlinux(struct dso *self, struct map *map, struct thread *thread, +static int dso__load_vmlinux(struct dso *self, struct map *map, + struct map_groups *mg, const char *vmlinux, symbol_filter_t filter) { int err = -1, fd; @@ -1386,14 +1517,14 @@ static int dso__load_vmlinux(struct dso *self, struct map *map, struct thread *t return -1; dso__set_loaded(self, map->type); - err = dso__load_sym(self, map, thread, self->long_name, fd, filter, 1, 0); + err = dso__load_sym(self, map, mg, self->long_name, fd, filter, 1, 0); close(fd); return err; } static int dso__load_kernel_sym(struct dso *self, struct map *map, - struct thread *thread, symbol_filter_t filter) + struct map_groups *mg, symbol_filter_t filter) { int err; bool is_kallsyms; @@ -1403,7 +1534,7 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, pr_debug("Looking at the vmlinux_path (%d entries long)\n", vmlinux_path__nr_entries); for (i = 0; i < vmlinux_path__nr_entries; ++i) { - err = dso__load_vmlinux(self, map, thread, + err = dso__load_vmlinux(self, map, mg, vmlinux_path[i], filter); if (err > 0) { pr_debug("Using %s for symbols\n", @@ -1419,12 +1550,12 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, if (is_kallsyms) goto do_kallsyms; - err = dso__load_vmlinux(self, map, thread, self->long_name, filter); + err = dso__load_vmlinux(self, map, mg, self->long_name, filter); if (err <= 0) { pr_info("The file %s cannot be used, " "trying to use /proc/kallsyms...", self->long_name); do_kallsyms: - err = dso__load_kallsyms(self, map, thread, filter); + err = dso__load_kallsyms(self, map, mg, filter); if (err > 0 && !is_kallsyms) dso__set_long_name(self, strdup("[kernel.kallsyms]")); } @@ -1507,42 +1638,59 @@ size_t dsos__fprintf_buildid(FILE *fp) __dsos__fprintf_buildid(&dsos__user, fp)); } -static int thread__create_kernel_map(struct thread *self, const char *vmlinux) +static struct dso *dsos__create_kernel( const char *vmlinux) { - struct map *kmap; struct dso *kernel = dso__new(vmlinux ?: "[kernel.kallsyms]"); if (kernel == NULL) - return -1; - - kmap = map__new2(0, kernel, MAP__FUNCTION); - if (kmap == NULL) - goto out_delete_kernel_dso; + return NULL; - kmap->map_ip = kmap->unmap_ip = identity__map_ip; kernel->short_name = "[kernel]"; kernel->kernel = 1; vdso = dso__new("[vdso]"); if (vdso == NULL) - goto out_delete_kernel_map; + goto out_delete_kernel_dso; dso__set_loaded(vdso, MAP__FUNCTION); if (sysfs__read_build_id("/sys/kernel/notes", kernel->build_id, sizeof(kernel->build_id)) == 0) kernel->has_build_id = true; - __thread__insert_map(self, kmap); dsos__add(&dsos__kernel, kernel); dsos__add(&dsos__user, vdso); - return 0; + return kernel; -out_delete_kernel_map: - map__delete(kmap); out_delete_kernel_dso: dso__delete(kernel); - return -1; + return NULL; +} + +static int map_groups__create_kernel_maps(struct map_groups *self, const char *vmlinux) +{ + struct map *functions, *variables; + struct dso *kernel = dsos__create_kernel(vmlinux); + + if (kernel == NULL) + return -1; + + functions = map__new2(0, kernel, MAP__FUNCTION); + if (functions == NULL) + return -1; + + variables = map__new2(0, kernel, MAP__VARIABLE); + if (variables == NULL) { + map__delete(functions); + return -1; + } + + functions->map_ip = functions->unmap_ip = + variables->map_ip = variables->unmap_ip = identity__map_ip; + map_groups__insert(self, functions); + map_groups__insert(self, variables); + + return 0; } static void vmlinux_path__exit(void) @@ -1606,23 +1754,26 @@ int symbol__init(struct symbol_conf *conf) elf_version(EV_CURRENT); symbol__priv_size = pconf->priv_size; - thread__init(kthread, 0); + if (pconf->sort_by_name) + symbol__priv_size += (sizeof(struct symbol_name_rb_node) - + sizeof(struct symbol)); + map_groups__init(kmaps); if (pconf->try_vmlinux_path && vmlinux_path__init() < 0) return -1; - if (thread__create_kernel_map(kthread, pconf->vmlinux_name) < 0) { + if (map_groups__create_kernel_maps(kmaps, pconf->vmlinux_name) < 0) { vmlinux_path__exit(); return -1; } - kthread->use_modules = pconf->use_modules; - if (pconf->use_modules && thread__create_module_maps(kthread) < 0) + kmaps->use_modules = pconf->use_modules; + if (pconf->use_modules && map_groups__create_module_maps(kmaps) < 0) pr_debug("Failed to load list of modules in use, " "continuing...\n"); /* * Now that we have all the maps created, just set the ->end of them: */ - thread__fixup_maps_end(kthread); + map_groups__fixup_end(kmaps); return 0; } diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 17003efa0b39ab072f6656109cddd434fe248d9a..cf99f88adf39c52d2010e8b6e0c580307dbc69fa 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -52,7 +52,8 @@ struct symbol { struct symbol_conf { unsigned short priv_size; bool try_vmlinux_path, - use_modules; + use_modules, + sort_by_name; const char *vmlinux_name; }; @@ -74,13 +75,13 @@ struct addr_location { struct dso { struct list_head node; struct rb_root symbols[MAP__NR_TYPES]; - struct symbol *(*find_symbol)(struct dso *self, - enum map_type type, u64 addr); + struct rb_root symbol_names[MAP__NR_TYPES]; u8 adjust_symbols:1; u8 slen_calculated:1; u8 has_build_id:1; u8 kernel:1; unsigned char origin; + u8 sorted_by_name; u8 loaded; u8 build_id[BUILD_ID_SIZE]; u16 long_name_len; @@ -93,6 +94,9 @@ struct dso *dso__new(const char *name); void dso__delete(struct dso *self); bool dso__loaded(const struct dso *self, enum map_type type); +bool dso__sorted_by_name(const struct dso *self, enum map_type type); + +void dso__sort_by_name(struct dso *self, enum map_type type); struct dso *dsos__findnew(const char *name); int dso__load(struct dso *self, struct map *map, symbol_filter_t filter); @@ -103,6 +107,9 @@ size_t dso__fprintf_buildid(struct dso *self, FILE *fp); size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp); char dso__symtab_origin(const struct dso *self); void dso__set_build_id(struct dso *self, void *build_id); +struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); +struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, + const char *name); int filename__read_build_id(const char *filename, void *bf, size_t size); int sysfs__read_build_id(const char *filename, void *bf, size_t size); @@ -113,8 +120,8 @@ size_t kernel_maps__fprintf(FILE *fp); int symbol__init(struct symbol_conf *conf); -struct thread; -struct thread *kthread; +struct map_groups; +struct map_groups *kmaps; extern struct list_head dsos__user, dsos__kernel; extern struct dso *vdso; #endif /* __PERF_SYMBOL */ diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 603f5610861b841cc1a526dc1f1566a0c943d56f..b68a00ea41210cbb69a80d41794700d0bfaccb97 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -9,11 +9,9 @@ static struct rb_root threads; static struct thread *last_match; -void thread__init(struct thread *self, pid_t pid) +void map_groups__init(struct map_groups *self) { int i; - self->pid = pid; - self->comm = NULL; for (i = 0; i < MAP__NR_TYPES; ++i) { self->maps[i] = RB_ROOT; INIT_LIST_HEAD(&self->removed_maps[i]); @@ -25,7 +23,8 @@ static struct thread *thread__new(pid_t pid) struct thread *self = zalloc(sizeof(*self)); if (self != NULL) { - thread__init(self, pid); + map_groups__init(&self->mg); + self->pid = pid; self->comm = malloc(32); if (self->comm) snprintf(self->comm, 32, ":%d", self->pid); @@ -55,10 +54,11 @@ int thread__comm_len(struct thread *self) static const char *map_type__name[MAP__NR_TYPES] = { [MAP__FUNCTION] = "Functions", + [MAP__VARIABLE] = "Variables", }; -static size_t __thread__fprintf_maps(struct thread *self, - enum map_type type, FILE *fp) +static size_t __map_groups__fprintf_maps(struct map_groups *self, + enum map_type type, FILE *fp) { size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); struct rb_node *nd; @@ -76,16 +76,16 @@ static size_t __thread__fprintf_maps(struct thread *self, return printed; } -size_t thread__fprintf_maps(struct thread *self, FILE *fp) +size_t map_groups__fprintf_maps(struct map_groups *self, FILE *fp) { size_t printed = 0, i; for (i = 0; i < MAP__NR_TYPES; ++i) - printed += __thread__fprintf_maps(self, i, fp); + printed += __map_groups__fprintf_maps(self, i, fp); return printed; } -static size_t __thread__fprintf_removed_maps(struct thread *self, - enum map_type type, FILE *fp) +static size_t __map_groups__fprintf_removed_maps(struct map_groups *self, + enum map_type type, FILE *fp) { struct map *pos; size_t printed = 0; @@ -101,20 +101,25 @@ static size_t __thread__fprintf_removed_maps(struct thread *self, return printed; } -static size_t thread__fprintf_removed_maps(struct thread *self, FILE *fp) +static size_t map_groups__fprintf_removed_maps(struct map_groups *self, FILE *fp) { size_t printed = 0, i; for (i = 0; i < MAP__NR_TYPES; ++i) - printed += __thread__fprintf_removed_maps(self, i, fp); + printed += __map_groups__fprintf_removed_maps(self, i, fp); return printed; } -static size_t thread__fprintf(struct thread *self, FILE *fp) +static size_t map_groups__fprintf(struct map_groups *self, FILE *fp) { - size_t printed = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); - printed += thread__fprintf_removed_maps(self, fp); + size_t printed = map_groups__fprintf_maps(self, fp); printed += fprintf(fp, "Removed maps:\n"); - return printed + thread__fprintf_removed_maps(self, fp); + return printed + map_groups__fprintf_removed_maps(self, fp); +} + +static size_t thread__fprintf(struct thread *self, FILE *fp) +{ + return fprintf(fp, "Thread %d %s\n", self->pid, self->comm) + + map_groups__fprintf(&self->mg, fp); } struct thread *threads__findnew(pid_t pid) @@ -168,7 +173,8 @@ struct thread *register_idle_thread(void) return thread; } -static void thread__remove_overlappings(struct thread *self, struct map *map) +static void map_groups__remove_overlappings(struct map_groups *self, + struct map *map) { struct rb_root *root = &self->maps[map->type]; struct rb_node *next = rb_first(root); @@ -238,12 +244,15 @@ struct map *maps__find(struct rb_root *maps, u64 ip) void thread__insert_map(struct thread *self, struct map *map) { - thread__remove_overlappings(self, map); - maps__insert(&self->maps[map->type], map); + map_groups__remove_overlappings(&self->mg, map); + map_groups__insert(&self->mg, map); } -static int thread__clone_maps(struct thread *self, struct thread *parent, - enum map_type type) +/* + * XXX This should not really _copy_ te maps, but refcount them. + */ +static int map_groups__clone(struct map_groups *self, + struct map_groups *parent, enum map_type type) { struct rb_node *nd; for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) { @@ -251,7 +260,7 @@ static int thread__clone_maps(struct thread *self, struct thread *parent, struct map *new = map__clone(map); if (new == NULL) return -ENOMEM; - thread__insert_map(self, new); + map_groups__insert(self, new); } return 0; } @@ -267,7 +276,7 @@ int thread__fork(struct thread *self, struct thread *parent) return -ENOMEM; for (i = 0; i < MAP__NR_TYPES; ++i) - if (thread__clone_maps(self, parent, i) < 0) + if (map_groups__clone(&self->mg, &parent->mg, i) < 0) return -ENOMEM; return 0; } @@ -286,11 +295,11 @@ size_t threads__fprintf(FILE *fp) return ret; } -struct symbol *thread__find_symbol(struct thread *self, - enum map_type type, u64 addr, - symbol_filter_t filter) +struct symbol *map_groups__find_symbol(struct map_groups *self, + enum map_type type, u64 addr, + symbol_filter_t filter) { - struct map *map = thread__find_map(self, type, addr); + struct map *map = map_groups__find(self, type, addr); if (map != NULL) return map__find_symbol(map, map->map_ip(map, addr), filter); diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 686d6e914d9e3711bfb1ea8e53e6b275715f2837..1751802a09ba41aef3fb1e985d94110aff516a12 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -5,52 +5,66 @@ #include #include "symbol.h" -struct thread { - struct rb_node rb_node; +struct map_groups { struct rb_root maps[MAP__NR_TYPES]; struct list_head removed_maps[MAP__NR_TYPES]; - pid_t pid; bool use_modules; +}; + +struct thread { + struct rb_node rb_node; + struct map_groups mg; + pid_t pid; char shortname[3]; char *comm; int comm_len; }; -void thread__init(struct thread *self, pid_t pid); +void map_groups__init(struct map_groups *self); int thread__set_comm(struct thread *self, const char *comm); int thread__comm_len(struct thread *self); struct thread *threads__findnew(pid_t pid); struct thread *register_idle_thread(void); void thread__insert_map(struct thread *self, struct map *map); int thread__fork(struct thread *self, struct thread *parent); -size_t thread__fprintf_maps(struct thread *self, FILE *fp); +size_t map_groups__fprintf_maps(struct map_groups *self, FILE *fp); size_t threads__fprintf(FILE *fp); void maps__insert(struct rb_root *maps, struct map *map); struct map *maps__find(struct rb_root *maps, u64 addr); -static inline struct map *thread__find_map(struct thread *self, +static inline void map_groups__insert(struct map_groups *self, struct map *map) +{ + maps__insert(&self->maps[map->type], map); +} + +static inline struct map *map_groups__find(struct map_groups *self, enum map_type type, u64 addr) { - return self ? maps__find(&self->maps[type], addr) : NULL; + return maps__find(&self->maps[type], addr); } -static inline void __thread__insert_map(struct thread *self, struct map *map) +static inline struct map *thread__find_map(struct thread *self, + enum map_type type, u64 addr) { - maps__insert(&self->maps[map->type], map); + return self ? map_groups__find(&self->mg, type, addr) : NULL; } void thread__find_addr_location(struct thread *self, u8 cpumode, enum map_type type, u64 addr, struct addr_location *al, symbol_filter_t filter); -struct symbol *thread__find_symbol(struct thread *self, - enum map_type type, u64 addr, - symbol_filter_t filter); +struct symbol *map_groups__find_symbol(struct map_groups *self, + enum map_type type, u64 addr, + symbol_filter_t filter); static inline struct symbol * -thread__find_function(struct thread *self, u64 addr, symbol_filter_t filter) +map_groups__find_function(struct map_groups *self, u64 addr, + symbol_filter_t filter) { - return thread__find_symbol(self, MAP__FUNCTION, addr, filter); + return map_groups__find_symbol(self, MAP__FUNCTION, addr, filter); } + +struct map *map_groups__find_by_name(struct map_groups *self, + enum map_type type, const char *name); #endif /* __PERF_THREAD_H */ diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 0302405aa2ca7b0f6e7b77cde32c4b49462ff8c9..c5c32be040bfe85767a155bb951db828aff4e49a 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -177,7 +177,7 @@ void parse_proc_kallsyms(char *file, unsigned int size __unused) func_count++; } - func_list = malloc_or_die(sizeof(*func_list) * func_count + 1); + func_list = malloc_or_die(sizeof(*func_list) * (func_count + 1)); i = 0; while (list) { @@ -1477,7 +1477,7 @@ process_fields(struct event *event, struct print_flag_sym **list, char **tok) goto out_free; field = malloc_or_die(sizeof(*field)); - memset(field, 0, sizeof(field)); + memset(field, 0, sizeof(*field)); value = arg_eval(arg); field->value = strdup(value); diff --git a/tools/perf/util/trace-event-perl.c b/tools/perf/util/trace-event-perl.c index 51e833fd58c39a1c863d65ad799839aa3ce3cd31..a5ffe60db5d6e55f227ab171c3729c82d7eef78b 100644 --- a/tools/perf/util/trace-event-perl.c +++ b/tools/perf/util/trace-event-perl.c @@ -32,9 +32,6 @@ void xs_init(pTHX); -void boot_Perf__Trace__Context(pTHX_ CV *cv); -void boot_DynaLoader(pTHX_ CV *cv); - void xs_init(pTHX) { const char *file = __FILE__; @@ -573,26 +570,72 @@ struct scripting_ops perl_scripting_ops = { .generate_script = perl_generate_script, }; -#ifdef NO_LIBPERL -void setup_perl_scripting(void) +static void print_unsupported_msg(void) { fprintf(stderr, "Perl scripting not supported." - " Install libperl and rebuild perf to enable it. e.g. " - "apt-get install libperl-dev (ubuntu), yum install " - "perl-ExtUtils-Embed (Fedora), etc.\n"); + " Install libperl and rebuild perf to enable it.\n" + "For example:\n # apt-get install libperl-dev (ubuntu)" + "\n # yum install perl-ExtUtils-Embed (Fedora)" + "\n etc.\n"); } -#else -void setup_perl_scripting(void) + +static int perl_start_script_unsupported(const char *script __unused) +{ + print_unsupported_msg(); + + return -1; +} + +static int perl_stop_script_unsupported(void) +{ + return 0; +} + +static void perl_process_event_unsupported(int cpu __unused, + void *data __unused, + int size __unused, + unsigned long long nsecs __unused, + char *comm __unused) +{ +} + +static int perl_generate_script_unsupported(const char *outfile __unused) +{ + print_unsupported_msg(); + + return -1; +} + +struct scripting_ops perl_scripting_unsupported_ops = { + .name = "Perl", + .start_script = perl_start_script_unsupported, + .stop_script = perl_stop_script_unsupported, + .process_event = perl_process_event_unsupported, + .generate_script = perl_generate_script_unsupported, +}; + +static void register_perl_scripting(struct scripting_ops *scripting_ops) { int err; - err = script_spec_register("Perl", &perl_scripting_ops); + err = script_spec_register("Perl", scripting_ops); if (err) die("error registering Perl script extension"); - err = script_spec_register("pl", &perl_scripting_ops); + err = script_spec_register("pl", scripting_ops); if (err) die("error registering pl script extension"); scripting_context = malloc(sizeof(struct scripting_context)); } + +#ifdef NO_LIBPERL +void setup_perl_scripting(void) +{ + register_perl_scripting(&perl_scripting_unsupported_ops); +} +#else +void setup_perl_scripting(void) +{ + register_perl_scripting(&perl_scripting_ops); +} #endif diff --git a/tools/perf/util/trace-event-perl.h b/tools/perf/util/trace-event-perl.h index 8fe0d866fe1afec78cbdb5d1b569e111559fe35b..e88fb26137bbbc125531845d364210e7e91df1dc 100644 --- a/tools/perf/util/trace-event-perl.h +++ b/tools/perf/util/trace-event-perl.h @@ -34,9 +34,13 @@ typedef int INTERP; #define dXSUB_SYS #define pTHX_ static inline void newXS(const char *a, void *b, const char *c) {} +static void boot_Perf__Trace__Context(pTHX_ CV *cv) {} +static void boot_DynaLoader(pTHX_ CV *cv) {} #else #include #include +void boot_Perf__Trace__Context(pTHX_ CV *cv); +void boot_DynaLoader(pTHX_ CV *cv); typedef PerlInterpreter * INTERP; #endif diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index 342dfdd43f875117a0306cb7cd4bb5f7618f82db..1744422cafcb43cf7872b2d7daf67c4409f56e3c 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -145,8 +145,9 @@ static void read_proc_kallsyms(void) if (!size) return; - buf = malloc_or_die(size); + buf = malloc_or_die(size + 1); read_or_die(buf, size); + buf[size] = '\0'; parse_proc_kallsyms(buf, size); diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index f92ba138007ace7a7669492d9852055322e69b64..e1f2bf8d7b1e06903ea499df764a2c0dbe1a66e1 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -49,6 +49,7 @@ #include #include #include +#include #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET #include "coalesced_mmio.h" @@ -1071,8 +1072,8 @@ void mark_page_dirty(struct kvm *kvm, gfn_t gfn) unsigned long rel_gfn = gfn - memslot->base_gfn; /* avoid RMW */ - if (!test_bit(rel_gfn, memslot->dirty_bitmap)) - set_bit(rel_gfn, memslot->dirty_bitmap); + if (!generic_test_le_bit(rel_gfn, memslot->dirty_bitmap)) + generic___set_le_bit(rel_gfn, memslot->dirty_bitmap); } }